Merge branches '3m', 'egalax', 'logitech', 'magicmouse', 'ntrig' and 'roccat' into for-linus
diff --git a/CREDITS b/CREDITS
index 72b4878..41d8e63 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3554,12 +3554,12 @@
 D: portions of the Linux Security Module (LSM) framework and security modules
 
 N: Petr Vandrovec
-E: vandrove@vc.cvut.cz
+E: petr@vandrovec.name
 D: Small contributions to ncpfs
 D: Matrox framebuffer driver
-S: Chudenicka 8
-S: 10200 Prague 10, Hostivar
-S: Czech Republic
+S: 21513 Conradia Ct
+S: Cupertino, CA 95014
+S: USA
 
 N: Thibaut Varene
 E: T-Bone@parisc-linux.org
diff --git a/Documentation/ABI/testing/sysfs-ata b/Documentation/ABI/testing/sysfs-ata
new file mode 100644
index 0000000..0a93215
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-ata
@@ -0,0 +1,99 @@
+What:		/sys/class/ata_...
+Date:		August 2008
+Contact:	Gwendal Grignou<gwendal@google.com>
+Description:
+
+Provide a place in sysfs for storing the ATA topology of the system.  This allows
+retrieving various information about ATA objects.
+
+Files under /sys/class/ata_port
+-------------------------------
+
+	For each port, a directory ataX is created where X is the ata_port_id of
+	the port. The device parent is the ata host device.
+
+idle_irq (read)
+
+	Number of IRQ received by the port while idle [some ata HBA only].
+
+nr_pmp_links (read)
+
+	If a SATA Port Multiplier (PM) is connected, number of link behind it.
+
+Files under /sys/class/ata_link
+-------------------------------
+
+	Behind each port, there is a ata_link. If there is a SATA PM in the
+	topology, 15 ata_link objects are created.
+
+	If a link is behind a port, the directory name is linkX, where X is
+	ata_port_id of the port.
+	If a link is behind a PM, its name is linkX.Y where X is ata_port_id
+	of the parent port and Y the PM port.
+
+hw_sata_spd_limit
+
+	Maximum speed supported by the connected SATA device.
+
+sata_spd_limit
+
+	Maximum speed imposed by libata.
+
+sata_spd
+
+	Current speed of the link [1.5, 3Gps,...].
+
+Files under /sys/class/ata_device
+---------------------------------
+
+	Behind each link, up to two ata device are created.
+	The name of the directory is devX[.Y].Z where:
+	- X is ata_port_id of the port where the device is connected,
+	- Y the port of the PM if any, and
+	- Z the device id: for PATA, there is usually 2 devices [0,1],
+	only 1 for SATA.
+
+class
+	Device class. Can be "ata" for disk, "atapi" for packet device,
+	"pmp" for PM, or "none" if no device was found behind the link.
+
+dma_mode
+
+	Transfer modes supported by the device when in DMA mode.
+	Mostly used by PATA device.
+
+pio_mode
+
+	Transfer modes supported by the device when in PIO mode.
+	Mostly used by PATA device.
+
+xfer_mode
+
+	Current transfer mode.
+
+id
+
+	Cached result of IDENTIFY command, as described in ATA8 7.16 and 7.17.
+	Only valid if the device is not a PM.
+
+gscr
+
+	Cached result of the dump of PM GSCR register.
+	Valid registers are:
+	0: 	SATA_PMP_GSCR_PROD_ID,
+	1: 	SATA_PMP_GSCR_REV,
+	2: 	SATA_PMP_GSCR_PORT_INFO,
+	32:	SATA_PMP_GSCR_ERROR,
+	33:	SATA_PMP_GSCR_ERROR_EN,
+	64:	SATA_PMP_GSCR_FEAT,
+	96:	SATA_PMP_GSCR_FEAT_EN,
+	130:	SATA_PMP_GSCR_SII_GPIO
+	Only valid if the device is a PM.
+
+spdn_cnt
+
+	Number of time libata decided to lower the speed of link due to errors.
+
+ering
+
+	Formatted output of the error ring of the device.
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 6123c52..7628cd1 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -77,3 +77,91 @@
 		devices this attribute is set to "enabled" by bus type code or
 		device drivers and in that cases it should be safe to leave the
 		default value.
+
+What:		/sys/devices/.../power/wakeup_count
+Date:		September 2010
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+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.
+
+What:		/sys/devices/.../power/wakeup_active_count
+Date:		September 2010
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/devices/.../wakeup_active_count attribute contains the
+		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.
+
+What:		/sys/devices/.../power/wakeup_hit_count
+Date:		September 2010
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/devices/.../wakeup_hit_count attribute contains the
+		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.
+
+What:		/sys/devices/.../power/wakeup_active
+Date:		September 2010
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/devices/.../wakeup_active attribute contains either 1,
+		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.
+
+What:		/sys/devices/.../power/wakeup_total_time_ms
+Date:		September 2010
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/devices/.../wakeup_total_time_ms attribute contains
+		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.
+
+What:		/sys/devices/.../power/wakeup_max_time_ms
+Date:		September 2010
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/devices/.../wakeup_max_time_ms attribute contains
+		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.
+
+What:		/sys/devices/.../power/wakeup_last_time_ms
+Date:		September 2010
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/devices/.../wakeup_last_time_ms attribute contains
+		the value of the monotonic clock corresponding to the time of
+		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.
+
+What:		/sys/devices/.../power/autosuspend_delay_ms
+Date:		September 2010
+Contact:	Alan Stern <stern@rowland.harvard.edu>
+Description:
+		The /sys/devices/.../power/autosuspend_delay_ms attribute
+		contains the autosuspend delay value (in milliseconds).  Some
+		drivers do not want their device to suspend as soon as it
+		becomes idle at run time; they want the device to remain
+		inactive for a certain minimum period of time first.  That
+		period is called the autosuspend delay.  Negative values will
+		prevent the device from being suspended at run time (similar
+		to writing "on" to the power/control attribute).  Values >=
+		1000 will cause the autosuspend timer expiration to be rounded
+		up to the nearest second.
+
+		Not all drivers support this attribute.  If it isn't supported,
+		attempts to read or write it will yield I/O errors.
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
new file mode 100644
index 0000000..ad1125b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
@@ -0,0 +1,98 @@
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_cpi
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	It is possible to switch the cpi setting of the mouse with the
+		press of a button.
+		When read, this file returns the raw number of the actual cpi
+		setting reported by the mouse. This number has to be further
+		processed to receive the real dpi value.
+
+		VALUE DPI
+		1     400
+		2     800
+		4     1600
+
+		This file is readonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_profile
+Date:		August 2010
+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.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/firmware_version
+Date:		August 2010
+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 138 means 1.38
+		This file is readonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile_settings
+Date:		August 2010
+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 13 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.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]_settings
+Date:		August 2010
+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 13 bytes in size.
+		This file is readonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile_buttons
+Date:		August 2010
+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 19 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.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]_buttons
+Date:		August 2010
+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 19 bytes in size.
+		This file is readonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/startup_profile
+Date:		August 2010
+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 profile
+                that's active when the mouse is powered on.
+		This file is readonly.
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/settings
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns the settings stored in the mouse.
+		The size of the data is 3 bytes and holds information on the
+		startup_profile.
+		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.
diff --git a/Documentation/ABI/testing/sysfs-module b/Documentation/ABI/testing/sysfs-module
new file mode 100644
index 0000000..cfcec3b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-module
@@ -0,0 +1,12 @@
+What:		/sys/module/pch_phub/drivers/.../pch_mac
+Date:		August 2010
+KernelVersion:	2.6.35
+Contact:	masa-korg@dsn.okisemi.com
+Description:	Write/read GbE MAC address.
+
+What:		/sys/module/pch_phub/drivers/.../pch_firmware
+Date:		August 2010
+KernelVersion:	2.6.35
+Contact:	masa-korg@dsn.okisemi.com
+Description:	Write/read Option ROM data.
+
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index 2875f1f..194ca44 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -99,9 +99,38 @@
 
 		dmesg -s 1000000 | grep 'hash matches'
 
+		If you do not get any matches (or they appear to be false
+		positives), it is possible that the last PM event point
+		referred to a device created by a loadable kernel module.  In
+		this case cat /sys/power/pm_trace_dev_match (see below) after
+		your system is started up and the kernel modules are loaded.
+
 		CAUTION: Using it will cause your machine's real-time (CMOS)
 		clock to be set to a random invalid time after a resume.
 
+What;		/sys/power/pm_trace_dev_match
+Date:		October 2010
+Contact:	James Hogan <james@albanarts.com>
+Description:
+		The /sys/power/pm_trace_dev_match file contains the name of the
+		device associated with the last PM event point saved in the RTC
+		across reboots when pm_trace has been used.  More precisely it
+		contains the list of current devices (including those
+		registered by loadable kernel modules since boot) which match
+		the device hash in the RTC at boot, with a newline after each
+		one.
+
+		The advantage of this file over the hash matches printed to the
+		kernel log (see /sys/power/pm_trace), is that it includes
+		devices created after boot by loadable kernel modules.
+
+		Due to the small hash size necessary to fit in the RTC, it is
+		possible that more than one device matches the hash, in which
+		case further investigation is required to determine which
+		device is causing the problem.  Note that genuine RTC clock
+		values (such as when pm_trace has not been used), can still
+		match a device and output it's name here.
+
 What:		/sys/power/pm_async
 Date:		January 2009
 Contact:	Rafael J. Wysocki <rjw@sisk.pl>
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
new file mode 100644
index 0000000..19a1210
--- /dev/null
+++ b/Documentation/DocBook/80211.tmpl
@@ -0,0 +1,495 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE set PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+<set>
+  <setinfo>
+    <title>The 802.11 subsystems &ndash; for kernel developers</title>
+    <subtitle>
+      Explaining wireless 802.11 networking in the Linux kernel
+    </subtitle>
+
+    <copyright>
+      <year>2007-2009</year>
+      <holder>Johannes Berg</holder>
+    </copyright>
+
+    <authorgroup>
+      <author>
+        <firstname>Johannes</firstname>
+        <surname>Berg</surname>
+        <affiliation>
+          <address><email>johannes@sipsolutions.net</email></address>
+        </affiliation>
+      </author>
+    </authorgroup>
+
+    <legalnotice>
+      <para>
+        This documentation is free software; you can redistribute
+        it and/or modify it under the terms of the GNU General Public
+        License version 2 as published by the Free Software Foundation.
+      </para>
+      <para>
+        This documentation is distributed in the hope that it will be
+        useful, but WITHOUT ANY WARRANTY; without even the implied
+        warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+        See the GNU General Public License for more details.
+      </para>
+      <para>
+        You should have received a copy of the GNU General Public
+        License along with this documentation; if not, write to the Free
+        Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+        MA 02111-1307 USA
+      </para>
+      <para>
+        For more details see the file COPYING in the source
+        distribution of Linux.
+      </para>
+    </legalnotice>
+
+    <abstract>
+      <para>
+        These books attempt to give a description of the
+        various subsystems that play a role in 802.11 wireless
+        networking in Linux. Since these books are for kernel
+        developers they attempts to document the structures
+        and functions used in the kernel as well as giving a
+        higher-level overview.
+      </para>
+      <para>
+	The reader is expected to be familiar with the 802.11
+	standard as published by the IEEE in 802.11-2007 (or
+	possibly later versions). References to this standard
+	will be given as "802.11-2007 8.1.5".
+      </para>
+    </abstract>
+  </setinfo>
+  <book id="cfg80211-developers-guide">
+    <bookinfo>
+      <title>The cfg80211 subsystem</title>
+
+      <abstract>
+!Pinclude/net/cfg80211.h Introduction
+      </abstract>
+    </bookinfo>
+      <chapter>
+      <title>Device registration</title>
+!Pinclude/net/cfg80211.h Device registration
+!Finclude/net/cfg80211.h ieee80211_band
+!Finclude/net/cfg80211.h ieee80211_channel_flags
+!Finclude/net/cfg80211.h ieee80211_channel
+!Finclude/net/cfg80211.h ieee80211_rate_flags
+!Finclude/net/cfg80211.h ieee80211_rate
+!Finclude/net/cfg80211.h ieee80211_sta_ht_cap
+!Finclude/net/cfg80211.h ieee80211_supported_band
+!Finclude/net/cfg80211.h cfg80211_signal_type
+!Finclude/net/cfg80211.h wiphy_params_flags
+!Finclude/net/cfg80211.h wiphy_flags
+!Finclude/net/cfg80211.h wiphy
+!Finclude/net/cfg80211.h wireless_dev
+!Finclude/net/cfg80211.h wiphy_new
+!Finclude/net/cfg80211.h wiphy_register
+!Finclude/net/cfg80211.h wiphy_unregister
+!Finclude/net/cfg80211.h wiphy_free
+
+!Finclude/net/cfg80211.h wiphy_name
+!Finclude/net/cfg80211.h wiphy_dev
+!Finclude/net/cfg80211.h wiphy_priv
+!Finclude/net/cfg80211.h priv_to_wiphy
+!Finclude/net/cfg80211.h set_wiphy_dev
+!Finclude/net/cfg80211.h wdev_priv
+      </chapter>
+      <chapter>
+      <title>Actions and configuration</title>
+!Pinclude/net/cfg80211.h Actions and configuration
+!Finclude/net/cfg80211.h cfg80211_ops
+!Finclude/net/cfg80211.h vif_params
+!Finclude/net/cfg80211.h key_params
+!Finclude/net/cfg80211.h survey_info_flags
+!Finclude/net/cfg80211.h survey_info
+!Finclude/net/cfg80211.h beacon_parameters
+!Finclude/net/cfg80211.h plink_actions
+!Finclude/net/cfg80211.h station_parameters
+!Finclude/net/cfg80211.h station_info_flags
+!Finclude/net/cfg80211.h rate_info_flags
+!Finclude/net/cfg80211.h rate_info
+!Finclude/net/cfg80211.h station_info
+!Finclude/net/cfg80211.h monitor_flags
+!Finclude/net/cfg80211.h mpath_info_flags
+!Finclude/net/cfg80211.h mpath_info
+!Finclude/net/cfg80211.h bss_parameters
+!Finclude/net/cfg80211.h ieee80211_txq_params
+!Finclude/net/cfg80211.h cfg80211_crypto_settings
+!Finclude/net/cfg80211.h cfg80211_auth_request
+!Finclude/net/cfg80211.h cfg80211_assoc_request
+!Finclude/net/cfg80211.h cfg80211_deauth_request
+!Finclude/net/cfg80211.h cfg80211_disassoc_request
+!Finclude/net/cfg80211.h cfg80211_ibss_params
+!Finclude/net/cfg80211.h cfg80211_connect_params
+!Finclude/net/cfg80211.h cfg80211_pmksa
+!Finclude/net/cfg80211.h cfg80211_send_rx_auth
+!Finclude/net/cfg80211.h cfg80211_send_auth_timeout
+!Finclude/net/cfg80211.h __cfg80211_auth_canceled
+!Finclude/net/cfg80211.h cfg80211_send_rx_assoc
+!Finclude/net/cfg80211.h cfg80211_send_assoc_timeout
+!Finclude/net/cfg80211.h cfg80211_send_deauth
+!Finclude/net/cfg80211.h __cfg80211_send_deauth
+!Finclude/net/cfg80211.h cfg80211_send_disassoc
+!Finclude/net/cfg80211.h __cfg80211_send_disassoc
+!Finclude/net/cfg80211.h cfg80211_ibss_joined
+!Finclude/net/cfg80211.h cfg80211_connect_result
+!Finclude/net/cfg80211.h cfg80211_roamed
+!Finclude/net/cfg80211.h cfg80211_disconnected
+!Finclude/net/cfg80211.h cfg80211_ready_on_channel
+!Finclude/net/cfg80211.h cfg80211_remain_on_channel_expired
+!Finclude/net/cfg80211.h cfg80211_new_sta
+!Finclude/net/cfg80211.h cfg80211_rx_mgmt
+!Finclude/net/cfg80211.h cfg80211_mgmt_tx_status
+!Finclude/net/cfg80211.h cfg80211_cqm_rssi_notify
+!Finclude/net/cfg80211.h cfg80211_michael_mic_failure
+      </chapter>
+      <chapter>
+      <title>Scanning and BSS list handling</title>
+!Pinclude/net/cfg80211.h Scanning and BSS list handling
+!Finclude/net/cfg80211.h cfg80211_ssid
+!Finclude/net/cfg80211.h cfg80211_scan_request
+!Finclude/net/cfg80211.h cfg80211_scan_done
+!Finclude/net/cfg80211.h cfg80211_bss
+!Finclude/net/cfg80211.h cfg80211_inform_bss_frame
+!Finclude/net/cfg80211.h cfg80211_inform_bss
+!Finclude/net/cfg80211.h cfg80211_unlink_bss
+!Finclude/net/cfg80211.h cfg80211_find_ie
+!Finclude/net/cfg80211.h ieee80211_bss_get_ie
+      </chapter>
+      <chapter>
+      <title>Utility functions</title>
+!Pinclude/net/cfg80211.h Utility functions
+!Finclude/net/cfg80211.h ieee80211_channel_to_frequency
+!Finclude/net/cfg80211.h ieee80211_frequency_to_channel
+!Finclude/net/cfg80211.h ieee80211_get_channel
+!Finclude/net/cfg80211.h ieee80211_get_response_rate
+!Finclude/net/cfg80211.h ieee80211_hdrlen
+!Finclude/net/cfg80211.h ieee80211_get_hdrlen_from_skb
+!Finclude/net/cfg80211.h ieee80211_radiotap_iterator
+      </chapter>
+      <chapter>
+      <title>Data path helpers</title>
+!Pinclude/net/cfg80211.h Data path helpers
+!Finclude/net/cfg80211.h ieee80211_data_to_8023
+!Finclude/net/cfg80211.h ieee80211_data_from_8023
+!Finclude/net/cfg80211.h ieee80211_amsdu_to_8023s
+!Finclude/net/cfg80211.h cfg80211_classify8021d
+      </chapter>
+      <chapter>
+      <title>Regulatory enforcement infrastructure</title>
+!Pinclude/net/cfg80211.h Regulatory enforcement infrastructure
+!Finclude/net/cfg80211.h regulatory_hint
+!Finclude/net/cfg80211.h wiphy_apply_custom_regulatory
+!Finclude/net/cfg80211.h freq_reg_info
+      </chapter>
+      <chapter>
+      <title>RFkill integration</title>
+!Pinclude/net/cfg80211.h RFkill integration
+!Finclude/net/cfg80211.h wiphy_rfkill_set_hw_state
+!Finclude/net/cfg80211.h wiphy_rfkill_start_polling
+!Finclude/net/cfg80211.h wiphy_rfkill_stop_polling
+      </chapter>
+      <chapter>
+      <title>Test mode</title>
+!Pinclude/net/cfg80211.h Test mode
+!Finclude/net/cfg80211.h cfg80211_testmode_alloc_reply_skb
+!Finclude/net/cfg80211.h cfg80211_testmode_reply
+!Finclude/net/cfg80211.h cfg80211_testmode_alloc_event_skb
+!Finclude/net/cfg80211.h cfg80211_testmode_event
+      </chapter>
+  </book>
+  <book id="mac80211-developers-guide">
+    <bookinfo>
+      <title>The mac80211 subsystem</title>
+      <abstract>
+!Pinclude/net/mac80211.h Introduction
+!Pinclude/net/mac80211.h Warning
+      </abstract>
+    </bookinfo>
+
+    <toc></toc>
+
+  <!--
+  Generally, this document shall be ordered by increasing complexity.
+  It is important to note that readers should be able to read only
+  the first few sections to get a working driver and only advanced
+  usage should require reading the full document.
+  -->
+
+    <part>
+      <title>The basic mac80211 driver interface</title>
+      <partintro>
+        <para>
+          You should read and understand the information contained
+          within this part of the book while implementing a driver.
+          In some chapters, advanced usage is noted, that may be
+          skipped at first.
+        </para>
+        <para>
+          This part of the book only covers station and monitor mode
+          functionality, additional information required to implement
+          the other modes is covered in the second part of the book.
+        </para>
+      </partintro>
+
+      <chapter id="basics">
+        <title>Basic hardware handling</title>
+        <para>TBD</para>
+        <para>
+          This chapter shall contain information on getting a hw
+          struct allocated and registered with mac80211.
+        </para>
+        <para>
+          Since it is required to allocate rates/modes before registering
+          a hw struct, this chapter shall also contain information on setting
+          up the rate/mode structs.
+        </para>
+        <para>
+          Additionally, some discussion about the callbacks and
+          the general programming model should be in here, including
+          the definition of ieee80211_ops which will be referred to
+          a lot.
+        </para>
+        <para>
+          Finally, a discussion of hardware capabilities should be done
+          with references to other parts of the book.
+        </para>
+  <!-- intentionally multiple !F lines to get proper order -->
+!Finclude/net/mac80211.h ieee80211_hw
+!Finclude/net/mac80211.h ieee80211_hw_flags
+!Finclude/net/mac80211.h SET_IEEE80211_DEV
+!Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR
+!Finclude/net/mac80211.h ieee80211_ops
+!Finclude/net/mac80211.h ieee80211_alloc_hw
+!Finclude/net/mac80211.h ieee80211_register_hw
+!Finclude/net/mac80211.h ieee80211_get_tx_led_name
+!Finclude/net/mac80211.h ieee80211_get_rx_led_name
+!Finclude/net/mac80211.h ieee80211_get_assoc_led_name
+!Finclude/net/mac80211.h ieee80211_get_radio_led_name
+!Finclude/net/mac80211.h ieee80211_unregister_hw
+!Finclude/net/mac80211.h ieee80211_free_hw
+      </chapter>
+
+      <chapter id="phy-handling">
+        <title>PHY configuration</title>
+        <para>TBD</para>
+        <para>
+          This chapter should describe PHY handling including
+          start/stop callbacks and the various structures used.
+        </para>
+!Finclude/net/mac80211.h ieee80211_conf
+!Finclude/net/mac80211.h ieee80211_conf_flags
+      </chapter>
+
+      <chapter id="iface-handling">
+        <title>Virtual interfaces</title>
+        <para>TBD</para>
+        <para>
+          This chapter should describe virtual interface basics
+          that are relevant to the driver (VLANs, MGMT etc are not.)
+          It should explain the use of the add_iface/remove_iface
+          callbacks as well as the interface configuration callbacks.
+        </para>
+        <para>Things related to AP mode should be discussed there.</para>
+        <para>
+          Things related to supporting multiple interfaces should be
+          in the appropriate chapter, a BIG FAT note should be here about
+          this though and the recommendation to allow only a single
+          interface in STA mode at first!
+        </para>
+!Finclude/net/mac80211.h ieee80211_vif
+      </chapter>
+
+      <chapter id="rx-tx">
+        <title>Receive and transmit processing</title>
+        <sect1>
+          <title>what should be here</title>
+          <para>TBD</para>
+          <para>
+            This should describe the receive and transmit
+            paths in mac80211/the drivers as well as
+            transmit status handling.
+          </para>
+        </sect1>
+        <sect1>
+          <title>Frame format</title>
+!Pinclude/net/mac80211.h Frame format
+        </sect1>
+        <sect1>
+          <title>Packet alignment</title>
+!Pnet/mac80211/rx.c Packet alignment
+        </sect1>
+        <sect1>
+          <title>Calling into mac80211 from interrupts</title>
+!Pinclude/net/mac80211.h Calling mac80211 from interrupts
+        </sect1>
+        <sect1>
+          <title>functions/definitions</title>
+!Finclude/net/mac80211.h ieee80211_rx_status
+!Finclude/net/mac80211.h mac80211_rx_flags
+!Finclude/net/mac80211.h ieee80211_tx_info
+!Finclude/net/mac80211.h ieee80211_rx
+!Finclude/net/mac80211.h ieee80211_rx_irqsafe
+!Finclude/net/mac80211.h ieee80211_tx_status
+!Finclude/net/mac80211.h ieee80211_tx_status_irqsafe
+!Finclude/net/mac80211.h ieee80211_rts_get
+!Finclude/net/mac80211.h ieee80211_rts_duration
+!Finclude/net/mac80211.h ieee80211_ctstoself_get
+!Finclude/net/mac80211.h ieee80211_ctstoself_duration
+!Finclude/net/mac80211.h ieee80211_generic_frame_duration
+!Finclude/net/mac80211.h ieee80211_wake_queue
+!Finclude/net/mac80211.h ieee80211_stop_queue
+!Finclude/net/mac80211.h ieee80211_wake_queues
+!Finclude/net/mac80211.h ieee80211_stop_queues
+        </sect1>
+      </chapter>
+
+      <chapter id="filters">
+        <title>Frame filtering</title>
+!Pinclude/net/mac80211.h Frame filtering
+!Finclude/net/mac80211.h ieee80211_filter_flags
+      </chapter>
+    </part>
+
+    <part id="advanced">
+      <title>Advanced driver interface</title>
+      <partintro>
+        <para>
+         Information contained within this part of the book is
+         of interest only for advanced interaction of mac80211
+         with drivers to exploit more hardware capabilities and
+         improve performance.
+        </para>
+      </partintro>
+
+      <chapter id="hardware-crypto-offload">
+        <title>Hardware crypto acceleration</title>
+!Pinclude/net/mac80211.h Hardware crypto acceleration
+  <!-- intentionally multiple !F lines to get proper order -->
+!Finclude/net/mac80211.h set_key_cmd
+!Finclude/net/mac80211.h ieee80211_key_conf
+!Finclude/net/mac80211.h ieee80211_key_flags
+      </chapter>
+
+      <chapter id="powersave">
+        <title>Powersave support</title>
+!Pinclude/net/mac80211.h Powersave support
+      </chapter>
+
+      <chapter id="beacon-filter">
+        <title>Beacon filter support</title>
+!Pinclude/net/mac80211.h Beacon filter support
+!Finclude/net/mac80211.h ieee80211_beacon_loss
+      </chapter>
+
+      <chapter id="qos">
+        <title>Multiple queues and QoS support</title>
+        <para>TBD</para>
+!Finclude/net/mac80211.h ieee80211_tx_queue_params
+      </chapter>
+
+      <chapter id="AP">
+        <title>Access point mode support</title>
+        <para>TBD</para>
+        <para>Some parts of the if_conf should be discussed here instead</para>
+        <para>
+          Insert notes about VLAN interfaces with hw crypto here or
+          in the hw crypto chapter.
+        </para>
+!Finclude/net/mac80211.h ieee80211_get_buffered_bc
+!Finclude/net/mac80211.h ieee80211_beacon_get
+      </chapter>
+
+      <chapter id="multi-iface">
+        <title>Supporting multiple virtual interfaces</title>
+        <para>TBD</para>
+        <para>
+          Note: WDS with identical MAC address should almost always be OK
+        </para>
+        <para>
+          Insert notes about having multiple virtual interfaces with
+          different MAC addresses here, note which configurations are
+          supported by mac80211, add notes about supporting hw crypto
+          with it.
+        </para>
+      </chapter>
+
+      <chapter id="hardware-scan-offload">
+        <title>Hardware scan offload</title>
+        <para>TBD</para>
+!Finclude/net/mac80211.h ieee80211_scan_completed
+      </chapter>
+    </part>
+
+    <part id="rate-control">
+      <title>Rate control interface</title>
+      <partintro>
+        <para>TBD</para>
+        <para>
+         This part of the book describes the rate control algorithm
+         interface and how it relates to mac80211 and drivers.
+        </para>
+      </partintro>
+      <chapter id="dummy">
+        <title>dummy chapter</title>
+        <para>TBD</para>
+      </chapter>
+    </part>
+
+    <part id="internal">
+      <title>Internals</title>
+      <partintro>
+        <para>TBD</para>
+        <para>
+         This part of the book describes mac80211 internals.
+        </para>
+      </partintro>
+
+      <chapter id="key-handling">
+        <title>Key handling</title>
+        <sect1>
+          <title>Key handling basics</title>
+!Pnet/mac80211/key.c Key handling basics
+        </sect1>
+        <sect1>
+          <title>MORE TBD</title>
+          <para>TBD</para>
+        </sect1>
+      </chapter>
+
+      <chapter id="rx-processing">
+        <title>Receive processing</title>
+        <para>TBD</para>
+      </chapter>
+
+      <chapter id="tx-processing">
+        <title>Transmit processing</title>
+        <para>TBD</para>
+      </chapter>
+
+      <chapter id="sta-info">
+        <title>Station info handling</title>
+        <sect1>
+          <title>Programming information</title>
+!Fnet/mac80211/sta_info.h sta_info
+!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags
+        </sect1>
+        <sect1>
+          <title>STA information lifetime rules</title>
+!Pnet/mac80211/sta_info.c STA information lifetime rules
+        </sect1>
+      </chapter>
+
+      <chapter id="synchronisation">
+        <title>Synchronisation</title>
+        <para>TBD</para>
+        <para>Locking, lots of RCU</para>
+      </chapter>
+    </part>
+  </book>
+</set>
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 34929f2..8b6e00a 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -12,7 +12,7 @@
 	    kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
 	    gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
 	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
-	    mac80211.xml debugobjects.xml sh.xml regulator.xml \
+	    80211.xml debugobjects.xml sh.xml regulator.xml \
 	    alsa-driver-api.xml writing-an-alsa-driver.xml \
 	    tracepoint.xml media.xml drm.xml
 
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 910c923..2861055 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -136,6 +136,7 @@
 #ifdef CONFIG_COMPAT
 		.compat_ioctl = i915_compat_ioctl,
 #endif
+		.llseek = noop_llseek,
 		},
 	.pci_driver = {
 		.name = DRIVER_NAME,
diff --git a/Documentation/DocBook/genericirq.tmpl b/Documentation/DocBook/genericirq.tmpl
index 1448b33..fb10fd0 100644
--- a/Documentation/DocBook/genericirq.tmpl
+++ b/Documentation/DocBook/genericirq.tmpl
@@ -28,7 +28,7 @@
   </authorgroup>
 
   <copyright>
-   <year>2005-2006</year>
+   <year>2005-2010</year>
    <holder>Thomas Gleixner</holder>
   </copyright>
   <copyright>
@@ -100,6 +100,10 @@
 	  <listitem><para>Edge type</para></listitem>
 	  <listitem><para>Simple type</para></listitem>
 	</itemizedlist>
+	During the implementation we identified another type:
+	<itemizedlist>
+	  <listitem><para>Fast EOI type</para></listitem>
+	</itemizedlist>
 	In the SMP world of the __do_IRQ() super-handler another type
 	was identified:
 	<itemizedlist>
@@ -153,6 +157,7 @@
 	is still available. This leads to a kind of duality for the time
 	being. Over time the new model should be used in more and more
 	architectures, as it enables smaller and cleaner IRQ subsystems.
+	It's deprecated for three years now and about to be removed.
 	</para>
   </chapter>
   <chapter id="bugs">
@@ -217,6 +222,7 @@
 	  <itemizedlist>
 	  <listitem><para>handle_level_irq</para></listitem>
 	  <listitem><para>handle_edge_irq</para></listitem>
+	  <listitem><para>handle_fasteoi_irq</para></listitem>
 	  <listitem><para>handle_simple_irq</para></listitem>
 	  <listitem><para>handle_percpu_irq</para></listitem>
 	  </itemizedlist>
@@ -233,33 +239,33 @@
 		are used by the default flow implementations.
 		The following helper functions are implemented (simplified excerpt):
 		<programlisting>
-default_enable(irq)
+default_enable(struct irq_data *data)
 {
-	desc->chip->unmask(irq);
+	desc->chip->irq_unmask(data);
 }
 
-default_disable(irq)
+default_disable(struct irq_data *data)
 {
-	if (!delay_disable(irq))
-		desc->chip->mask(irq);
+	if (!delay_disable(data))
+		desc->chip->irq_mask(data);
 }
 
-default_ack(irq)
+default_ack(struct irq_data *data)
 {
-	chip->ack(irq);
+	chip->irq_ack(data);
 }
 
-default_mask_ack(irq)
+default_mask_ack(struct irq_data *data)
 {
-	if (chip->mask_ack) {
-		chip->mask_ack(irq);
+	if (chip->irq_mask_ack) {
+		chip->irq_mask_ack(data);
 	} else {
-		chip->mask(irq);
-		chip->ack(irq);
+		chip->irq_mask(data);
+		chip->irq_ack(data);
 	}
 }
 
-noop(irq)
+noop(struct irq_data *data))
 {
 }
 
@@ -278,12 +284,27 @@
 		<para>
 		The following control flow is implemented (simplified excerpt):
 		<programlisting>
-desc->chip->start();
+desc->chip->irq_mask();
 handle_IRQ_event(desc->action);
-desc->chip->end();
+desc->chip->irq_unmask();
 		</programlisting>
 		</para>
-   	    </sect3>
+	    </sect3>
+	    <sect3 id="Default_FASTEOI_IRQ_flow_handler">
+		<title>Default Fast EOI IRQ flow handler</title>
+		<para>
+		handle_fasteoi_irq provides a generic implementation
+		for interrupts, which only need an EOI at the end of
+		the handler
+		</para>
+		<para>
+		The following control flow is implemented (simplified excerpt):
+		<programlisting>
+handle_IRQ_event(desc->action);
+desc->chip->irq_eoi();
+		</programlisting>
+		</para>
+	    </sect3>
 	    <sect3 id="Default_Edge_IRQ_flow_handler">
 	 	<title>Default Edge IRQ flow handler</title>
 		<para>
@@ -294,20 +315,19 @@
 		The following control flow is implemented (simplified excerpt):
 		<programlisting>
 if (desc->status &amp; running) {
-	desc->chip->hold();
+	desc->chip->irq_mask();
 	desc->status |= pending | masked;
 	return;
 }
-desc->chip->start();
+desc->chip->irq_ack();
 desc->status |= running;
 do {
 	if (desc->status &amp; masked)
-		desc->chip->enable();
+		desc->chip->irq_unmask();
 	desc->status &amp;= ~pending;
 	handle_IRQ_event(desc->action);
 } while (status &amp; pending);
 desc->status &amp;= ~running;
-desc->chip->end();
 		</programlisting>
 		</para>
    	    </sect3>
@@ -342,9 +362,9 @@
 		<para>
 		The following control flow is implemented (simplified excerpt):
 		<programlisting>
-desc->chip->start();
 handle_IRQ_event(desc->action);
-desc->chip->end();
+if (desc->chip->irq_eoi)
+        desc->chip->irq_eoi();
 		</programlisting>
 		</para>
    	    </sect3>
@@ -375,8 +395,7 @@
 	mechanism. (It's necessary to enable CONFIG_HARDIRQS_SW_RESEND when
 	you want to use the delayed interrupt disable feature and your
 	hardware is not capable of retriggering	an interrupt.)
-	The delayed interrupt disable can be runtime enabled, per interrupt,
-	by setting the IRQ_DELAYED_DISABLE flag in the irq_desc status field.
+	The delayed interrupt disable is not configurable.
 	</para>
 	</sect2>
     </sect1>
@@ -387,13 +406,13 @@
 	contains all the direct chip relevant functions, which
 	can be utilized by the irq flow implementations.
 	  <itemizedlist>
-	  <listitem><para>ack()</para></listitem>
-	  <listitem><para>mask_ack() - Optional, recommended for performance</para></listitem>
-	  <listitem><para>mask()</para></listitem>
-	  <listitem><para>unmask()</para></listitem>
-	  <listitem><para>retrigger() - Optional</para></listitem>
-	  <listitem><para>set_type() - Optional</para></listitem>
-	  <listitem><para>set_wake() - Optional</para></listitem>
+	  <listitem><para>irq_ack()</para></listitem>
+	  <listitem><para>irq_mask_ack() - Optional, recommended for performance</para></listitem>
+	  <listitem><para>irq_mask()</para></listitem>
+	  <listitem><para>irq_unmask()</para></listitem>
+	  <listitem><para>irq_retrigger() - Optional</para></listitem>
+	  <listitem><para>irq_set_type() - Optional</para></listitem>
+	  <listitem><para>irq_set_wake() - Optional</para></listitem>
 	  </itemizedlist>
 	These primitives are strictly intended to mean what they say: ack means
 	ACK, masking means masking of an IRQ line, etc. It is up to the flow
@@ -458,6 +477,7 @@
      <para>
      This chapter contains the autogenerated documentation of the internal functions.
      </para>
+!Ikernel/irq/irqdesc.c
 !Ikernel/irq/handle.c
 !Ikernel/irq/chip.c
   </chapter>
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 6899f47..6b4e07f 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -257,7 +257,8 @@
 !Iblock/blk-sysfs.c
 !Eblock/blk-settings.c
 !Eblock/blk-exec.c
-!Eblock/blk-barrier.c
+!Eblock/blk-flush.c
+!Eblock/blk-lib.c
 !Eblock/blk-tag.c
 !Iblock/blk-tag.c
 !Eblock/blk-integrity.c
diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl
index a0d479d..f66f4df 100644
--- a/Documentation/DocBook/kernel-locking.tmpl
+++ b/Documentation/DocBook/kernel-locking.tmpl
@@ -1645,7 +1645,9 @@
       all the readers who were traversing the list when we deleted the
       element are finished.  We use <function>call_rcu()</function> to
       register a callback which will actually destroy the object once
-      the readers are finished.
+      all pre-existing readers are finished.  Alternatively,
+      <function>synchronize_rcu()</function> may be used to block until
+      all pre-existing are finished.
     </para>
     <para>
       But how does Read Copy Update know when the readers are
@@ -1714,7 +1716,7 @@
 -        object_put(obj);
 +        list_del_rcu(&amp;obj-&gt;list);
          cache_num--;
-+        call_rcu(&amp;obj-&gt;rcu, cache_delete_rcu, obj);
++        call_rcu(&amp;obj-&gt;rcu, cache_delete_rcu);
  }
 
  /* Must be holding cache_lock */
@@ -1725,14 +1727,6 @@
          if (++cache_num > MAX_CACHE_SIZE) {
                  struct object *i, *outcast = NULL;
                  list_for_each_entry(i, &amp;cache, list) {
-@@ -85,6 +94,7 @@
-         obj-&gt;popularity = 0;
-         atomic_set(&amp;obj-&gt;refcnt, 1); /* The cache holds a reference */
-         spin_lock_init(&amp;obj-&gt;lock);
-+        INIT_RCU_HEAD(&amp;obj-&gt;rcu);
-
-         spin_lock_irqsave(&amp;cache_lock, flags);
-         __cache_add(obj);
 @@ -104,12 +114,11 @@
  struct object *cache_find(int id)
  {
diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl
deleted file mode 100644
index affb15a..0000000
--- a/Documentation/DocBook/mac80211.tmpl
+++ /dev/null
@@ -1,337 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="mac80211-developers-guide">
-  <bookinfo>
-    <title>The mac80211 subsystem for kernel developers</title>
-
-    <authorgroup>
-      <author>
-        <firstname>Johannes</firstname>
-        <surname>Berg</surname>
-        <affiliation>
-          <address><email>johannes@sipsolutions.net</email></address>
-        </affiliation>
-      </author>
-    </authorgroup>
-
-    <copyright>
-      <year>2007-2009</year>
-      <holder>Johannes Berg</holder>
-    </copyright>
-
-    <legalnotice>
-      <para>
-        This documentation is free software; you can redistribute
-        it and/or modify it under the terms of the GNU General Public
-        License version 2 as published by the Free Software Foundation.
-      </para>
-
-      <para>
-        This documentation is distributed in the hope that it will be
-        useful, but WITHOUT ANY WARRANTY; without even the implied
-        warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-        See the GNU General Public License for more details.
-      </para>
-
-      <para>
-        You should have received a copy of the GNU General Public
-        License along with this documentation; if not, write to the Free
-        Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-        MA 02111-1307 USA
-      </para>
-
-      <para>
-        For more details see the file COPYING in the source
-        distribution of Linux.
-      </para>
-    </legalnotice>
-
-    <abstract>
-!Pinclude/net/mac80211.h Introduction
-!Pinclude/net/mac80211.h Warning
-    </abstract>
-  </bookinfo>
-
-  <toc></toc>
-
-<!--
-Generally, this document shall be ordered by increasing complexity.
-It is important to note that readers should be able to read only
-the first few sections to get a working driver and only advanced
-usage should require reading the full document.
--->
-
-  <part>
-    <title>The basic mac80211 driver interface</title>
-    <partintro>
-      <para>
-        You should read and understand the information contained
-        within this part of the book while implementing a driver.
-        In some chapters, advanced usage is noted, that may be
-        skipped at first.
-      </para>
-      <para>
-        This part of the book only covers station and monitor mode
-        functionality, additional information required to implement
-        the other modes is covered in the second part of the book.
-      </para>
-    </partintro>
-
-    <chapter id="basics">
-      <title>Basic hardware handling</title>
-      <para>TBD</para>
-      <para>
-        This chapter shall contain information on getting a hw
-        struct allocated and registered with mac80211.
-      </para>
-      <para>
-        Since it is required to allocate rates/modes before registering
-        a hw struct, this chapter shall also contain information on setting
-        up the rate/mode structs.
-      </para>
-      <para>
-        Additionally, some discussion about the callbacks and
-        the general programming model should be in here, including
-        the definition of ieee80211_ops which will be referred to
-        a lot.
-      </para>
-      <para>
-        Finally, a discussion of hardware capabilities should be done
-        with references to other parts of the book.
-      </para>
-<!-- intentionally multiple !F lines to get proper order -->
-!Finclude/net/mac80211.h ieee80211_hw
-!Finclude/net/mac80211.h ieee80211_hw_flags
-!Finclude/net/mac80211.h SET_IEEE80211_DEV
-!Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR
-!Finclude/net/mac80211.h ieee80211_ops
-!Finclude/net/mac80211.h ieee80211_alloc_hw
-!Finclude/net/mac80211.h ieee80211_register_hw
-!Finclude/net/mac80211.h ieee80211_get_tx_led_name
-!Finclude/net/mac80211.h ieee80211_get_rx_led_name
-!Finclude/net/mac80211.h ieee80211_get_assoc_led_name
-!Finclude/net/mac80211.h ieee80211_get_radio_led_name
-!Finclude/net/mac80211.h ieee80211_unregister_hw
-!Finclude/net/mac80211.h ieee80211_free_hw
-    </chapter>
-
-    <chapter id="phy-handling">
-      <title>PHY configuration</title>
-      <para>TBD</para>
-      <para>
-        This chapter should describe PHY handling including
-        start/stop callbacks and the various structures used.
-      </para>
-!Finclude/net/mac80211.h ieee80211_conf
-!Finclude/net/mac80211.h ieee80211_conf_flags
-    </chapter>
-
-    <chapter id="iface-handling">
-      <title>Virtual interfaces</title>
-      <para>TBD</para>
-      <para>
-        This chapter should describe virtual interface basics
-        that are relevant to the driver (VLANs, MGMT etc are not.)
-        It should explain the use of the add_iface/remove_iface
-        callbacks as well as the interface configuration callbacks.
-      </para>
-      <para>Things related to AP mode should be discussed there.</para>
-      <para>
-        Things related to supporting multiple interfaces should be
-        in the appropriate chapter, a BIG FAT note should be here about
-        this though and the recommendation to allow only a single
-        interface in STA mode at first!
-      </para>
-!Finclude/net/mac80211.h ieee80211_vif
-    </chapter>
-
-    <chapter id="rx-tx">
-      <title>Receive and transmit processing</title>
-      <sect1>
-        <title>what should be here</title>
-        <para>TBD</para>
-        <para>
-          This should describe the receive and transmit
-          paths in mac80211/the drivers as well as
-          transmit status handling.
-        </para>
-      </sect1>
-      <sect1>
-        <title>Frame format</title>
-!Pinclude/net/mac80211.h Frame format
-      </sect1>
-      <sect1>
-        <title>Packet alignment</title>
-!Pnet/mac80211/rx.c Packet alignment
-      </sect1>
-      <sect1>
-        <title>Calling into mac80211 from interrupts</title>
-!Pinclude/net/mac80211.h Calling mac80211 from interrupts
-      </sect1>
-      <sect1>
-        <title>functions/definitions</title>
-!Finclude/net/mac80211.h ieee80211_rx_status
-!Finclude/net/mac80211.h mac80211_rx_flags
-!Finclude/net/mac80211.h ieee80211_tx_info
-!Finclude/net/mac80211.h ieee80211_rx
-!Finclude/net/mac80211.h ieee80211_rx_irqsafe
-!Finclude/net/mac80211.h ieee80211_tx_status
-!Finclude/net/mac80211.h ieee80211_tx_status_irqsafe
-!Finclude/net/mac80211.h ieee80211_rts_get
-!Finclude/net/mac80211.h ieee80211_rts_duration
-!Finclude/net/mac80211.h ieee80211_ctstoself_get
-!Finclude/net/mac80211.h ieee80211_ctstoself_duration
-!Finclude/net/mac80211.h ieee80211_generic_frame_duration
-!Finclude/net/mac80211.h ieee80211_wake_queue
-!Finclude/net/mac80211.h ieee80211_stop_queue
-!Finclude/net/mac80211.h ieee80211_wake_queues
-!Finclude/net/mac80211.h ieee80211_stop_queues
-      </sect1>
-    </chapter>
-
-    <chapter id="filters">
-      <title>Frame filtering</title>
-!Pinclude/net/mac80211.h Frame filtering
-!Finclude/net/mac80211.h ieee80211_filter_flags
-    </chapter>
-  </part>
-
-  <part id="advanced">
-    <title>Advanced driver interface</title>
-    <partintro>
-      <para>
-       Information contained within this part of the book is
-       of interest only for advanced interaction of mac80211
-       with drivers to exploit more hardware capabilities and
-       improve performance.
-      </para>
-    </partintro>
-
-    <chapter id="hardware-crypto-offload">
-      <title>Hardware crypto acceleration</title>
-!Pinclude/net/mac80211.h Hardware crypto acceleration
-<!-- intentionally multiple !F lines to get proper order -->
-!Finclude/net/mac80211.h set_key_cmd
-!Finclude/net/mac80211.h ieee80211_key_conf
-!Finclude/net/mac80211.h ieee80211_key_alg
-!Finclude/net/mac80211.h ieee80211_key_flags
-    </chapter>
-
-    <chapter id="powersave">
-      <title>Powersave support</title>
-!Pinclude/net/mac80211.h Powersave support
-    </chapter>
-
-    <chapter id="beacon-filter">
-      <title>Beacon filter support</title>
-!Pinclude/net/mac80211.h Beacon filter support
-!Finclude/net/mac80211.h ieee80211_beacon_loss
-    </chapter>
-
-    <chapter id="qos">
-      <title>Multiple queues and QoS support</title>
-      <para>TBD</para>
-!Finclude/net/mac80211.h ieee80211_tx_queue_params
-    </chapter>
-
-    <chapter id="AP">
-      <title>Access point mode support</title>
-      <para>TBD</para>
-      <para>Some parts of the if_conf should be discussed here instead</para>
-      <para>
-        Insert notes about VLAN interfaces with hw crypto here or
-        in the hw crypto chapter.
-      </para>
-!Finclude/net/mac80211.h ieee80211_get_buffered_bc
-!Finclude/net/mac80211.h ieee80211_beacon_get
-    </chapter>
-
-    <chapter id="multi-iface">
-      <title>Supporting multiple virtual interfaces</title>
-      <para>TBD</para>
-      <para>
-        Note: WDS with identical MAC address should almost always be OK
-      </para>
-      <para>
-        Insert notes about having multiple virtual interfaces with
-        different MAC addresses here, note which configurations are
-        supported by mac80211, add notes about supporting hw crypto
-        with it.
-      </para>
-    </chapter>
-
-    <chapter id="hardware-scan-offload">
-      <title>Hardware scan offload</title>
-      <para>TBD</para>
-!Finclude/net/mac80211.h ieee80211_scan_completed
-    </chapter>
-  </part>
-
-  <part id="rate-control">
-    <title>Rate control interface</title>
-    <partintro>
-      <para>TBD</para>
-      <para>
-       This part of the book describes the rate control algorithm
-       interface and how it relates to mac80211 and drivers.
-      </para>
-    </partintro>
-    <chapter id="dummy">
-      <title>dummy chapter</title>
-      <para>TBD</para>
-    </chapter>
-  </part>
-
-  <part id="internal">
-    <title>Internals</title>
-    <partintro>
-      <para>TBD</para>
-      <para>
-       This part of the book describes mac80211 internals.
-      </para>
-    </partintro>
-
-    <chapter id="key-handling">
-      <title>Key handling</title>
-      <sect1>
-        <title>Key handling basics</title>
-!Pnet/mac80211/key.c Key handling basics
-      </sect1>
-      <sect1>
-        <title>MORE TBD</title>
-        <para>TBD</para>
-      </sect1>
-    </chapter>
-
-    <chapter id="rx-processing">
-      <title>Receive processing</title>
-      <para>TBD</para>
-    </chapter>
-
-    <chapter id="tx-processing">
-      <title>Transmit processing</title>
-      <para>TBD</para>
-    </chapter>
-
-    <chapter id="sta-info">
-      <title>Station info handling</title>
-      <sect1>
-        <title>Programming information</title>
-!Fnet/mac80211/sta_info.h sta_info
-!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags
-      </sect1>
-      <sect1>
-        <title>STA information lifetime rules</title>
-!Pnet/mac80211/sta_info.c STA information lifetime rules
-      </sect1>
-    </chapter>
-
-    <chapter id="synchronisation">
-      <title>Synchronisation</title>
-      <para>TBD</para>
-      <para>Locking, lots of RCU</para>
-    </chapter>
-  </part>
-</book>
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index 790d1a8..0c134f8 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -218,13 +218,22 @@
 	include:
 
 	a.	Keeping a count of the number of data-structure elements
-		used by the RCU-protected data structure, including those
-		waiting for a grace period to elapse.  Enforce a limit
-		on this number, stalling updates as needed to allow
-		previously deferred frees to complete.
+		used by the RCU-protected data structure, including
+		those waiting for a grace period to elapse.  Enforce a
+		limit on this number, stalling updates as needed to allow
+		previously deferred frees to complete.	Alternatively,
+		limit only the number awaiting deferred free rather than
+		the total number of elements.
 
-		Alternatively, limit only the number awaiting deferred
-		free rather than the total number of elements.
+		One way to stall the updates is to acquire the update-side
+		mutex.	(Don't try this with a spinlock -- other CPUs
+		spinning on the lock could prevent the grace period
+		from ever ending.)  Another way to stall the updates
+		is for the updates to use a wrapper function around
+		the memory allocator, so that this wrapper function
+		simulates OOM when there is too much memory awaiting an
+		RCU grace period.  There are of course many other
+		variations on this theme.
 
 	b.	Limiting update rate.  For example, if updates occur only
 		once per hour, then no explicit rate limiting is required,
@@ -365,3 +374,26 @@
 	and the compiler to freely reorder code into and out of RCU
 	read-side critical sections.  It is the responsibility of the
 	RCU update-side primitives to deal with this.
+
+17.	Use CONFIG_PROVE_RCU, CONFIG_DEBUG_OBJECTS_RCU_HEAD, and
+	the __rcu sparse checks to validate your RCU code.  These
+	can help find problems as follows:
+
+	CONFIG_PROVE_RCU: check that accesses to RCU-protected data
+		structures are carried out under the proper RCU
+		read-side critical section, while holding the right
+		combination of locks, or whatever other conditions
+		are appropriate.
+
+	CONFIG_DEBUG_OBJECTS_RCU_HEAD: check that you don't pass the
+		same object to call_rcu() (or friends) before an RCU
+		grace period has elapsed since the last time that you
+		passed that same object to call_rcu() (or friends).
+
+	__rcu sparse checks: tag the pointer to the RCU-protected data
+		structure with __rcu, and sparse will warn you if you
+		access that pointer without the services of one of the
+		variants of rcu_dereference().
+
+	These debugging aids can help you find problems that are
+	otherwise extremely difficult to spot.
diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt
index 44c6dcc9..862c08e 100644
--- a/Documentation/RCU/stallwarn.txt
+++ b/Documentation/RCU/stallwarn.txt
@@ -80,6 +80,24 @@
 o	For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the kernel
 	without invoking schedule().
 
+o	A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might
+	happen to preempt a low-priority task in the middle of an RCU
+	read-side critical section.   This is especially damaging if
+	that low-priority task is not permitted to run on any other CPU,
+	in which case the next RCU grace period can never complete, which
+	will eventually cause the system to run out of memory and hang.
+	While the system is in the process of running itself out of
+	memory, you might see stall-warning messages.
+
+o	A CPU-bound real-time task in a CONFIG_PREEMPT_RT kernel that
+	is running at a higher priority than the RCU softirq threads.
+	This will prevent RCU callbacks from ever being invoked,
+	and in a CONFIG_TREE_PREEMPT_RCU kernel will further prevent
+	RCU grace periods from ever completing.  Either way, the
+	system will eventually run out of memory and hang.  In the
+	CONFIG_TREE_PREEMPT_RCU case, you might see stall-warning
+	messages.
+
 o	A bug in the RCU implementation.
 
 o	A hardware failure.  This is quite unlikely, but has occurred
diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt
index efd8cc9..a851118 100644
--- a/Documentation/RCU/trace.txt
+++ b/Documentation/RCU/trace.txt
@@ -125,6 +125,17 @@
 	of RCU callbacks is ready to invoke, then the remainder will
 	be deferred.
 
+o	"ci" is the number of RCU callbacks that have been invoked for
+	this CPU.  Note that ci+ql is the number of callbacks that have
+	been registered in absence of CPU-hotplug activity.
+
+o	"co" is the number of RCU callbacks that have been orphaned due to
+	this CPU going offline.
+
+o	"ca" is the number of RCU callbacks that have been adopted due to
+	other CPUs going offline.  Note that ci+co-ca+ql is the number of
+	RCU callbacks registered on this CPU.
+
 There is also an rcu/rcudata.csv file with the same information in
 comma-separated-variable spreadsheet format.
 
@@ -180,7 +191,7 @@
 
 o	"jfq" is the number of jiffies remaining for this grace period
 	before force_quiescent_state() is invoked to help push things
-	along.  Note that CPUs in dyntick-idle mode thoughout the grace
+	along.  Note that CPUs in dyntick-idle mode throughout the grace
 	period will not report on their own, but rather must be check by
 	some other CPU via force_quiescent_state().
 
diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
index 7f5fc3b..ecf7d04 100644
--- a/Documentation/arm/00-INDEX
+++ b/Documentation/arm/00-INDEX
@@ -6,6 +6,8 @@
 	- ARM Interrupt subsystem documentation
 IXP2000
 	- Release Notes for Linux on Intel's IXP2000 Network Processor
+msm
+	- MSM specific documentation
 Netwinder
 	- Netwinder specific documentation
 Porting
diff --git a/Documentation/arm/msm/gpiomux.txt b/Documentation/arm/msm/gpiomux.txt
new file mode 100644
index 0000000..67a8162
--- /dev/null
+++ b/Documentation/arm/msm/gpiomux.txt
@@ -0,0 +1,176 @@
+This document provides an overview of the msm_gpiomux interface, which
+is used to provide gpio pin multiplexing and configuration on mach-msm
+targets.
+
+History
+=======
+
+The first-generation API for gpio configuration & multiplexing on msm
+is the function gpio_tlmm_config().  This function has a few notable
+shortcomings, which led to its deprecation and replacement by gpiomux:
+
+The 'disable' parameter:  Setting the second parameter to
+gpio_tlmm_config to GPIO_CFG_DISABLE tells the peripheral
+processor in charge of the subsystem to perform a look-up into a
+low-power table and apply the low-power/sleep setting for the pin.
+As the msm family evolved this became problematic. Not all pins
+have sleep settings, not all peripheral processors will accept requests
+to apply said sleep settings, and not all msm targets have their gpio
+subsystems managed by a peripheral processor. In order to get consistent
+behavior on all targets, drivers are forced to ignore this parameter,
+rendering it useless.
+
+The 'direction' flag: for all mux-settings other than raw-gpio (0),
+the output-enable bit of a gpio is hard-wired to a known
+input (usually VDD or ground).  For those settings, the direction flag
+is meaningless at best, and deceptive at worst.  In addition, using the
+direction flag to change output-enable (OE) directly can cause trouble in
+gpiolib, which has no visibility into gpio direction changes made
+in this way.  Direction control in gpio mode should be made through gpiolib.
+
+Key Features of gpiomux
+=======================
+
+- A consistent interface across all generations of msm.  Drivers can expect
+the same results on every target.
+- gpiomux plays nicely with gpiolib.  Functions that should belong to gpiolib
+are left to gpiolib and not duplicated here.  gpiomux is written with the
+intent that gpio_chips will call gpiomux reference-counting methods
+from their request() and free() hooks, providing full integration.
+- Tabular configuration.  Instead of having to call gpio_tlmm_config
+hundreds of times, gpio configuration is placed in a single table.
+- Per-gpio sleep.  Each gpio is individually reference counted, allowing only
+those lines which are in use to be put in high-power states.
+- 0 means 'do nothing': all flags are designed so that the default memset-zero
+equates to a sensible default of 'no configuration', preventing users
+from having to provide hundreds of 'no-op' configs for unused or
+unwanted lines.
+
+Usage
+=====
+
+To use gpiomux, provide configuration information for relevant gpio lines
+in the msm_gpiomux_configs table.  Since a 0 equates to "unconfigured",
+only those lines to be managed by gpiomux need to be specified.  Here
+is a completely fictional example:
+
+struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
+	[12] = {
+		.active = GPIOMUX_VALID | GPIOMUX_DRV_8MA | GPIOMUX_FUNC_1,
+		.suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
+	},
+	[34] = {
+		.suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
+	},
+};
+
+To indicate that a gpio is in use, call msm_gpiomux_get() to increase
+its reference count.  To decrease the reference count, call msm_gpiomux_put().
+
+The effect of this configuration is as follows:
+
+When the system boots, gpios 12 and 34 will be initialized with their
+'suspended' configurations.  All other gpios, which were left unconfigured,
+will not be touched.
+
+When msm_gpiomux_get() is called on gpio 12 to raise its reference count
+above 0, its active configuration will be applied.  Since no other gpio
+line has a valid active configuration, msm_gpiomux_get() will have no
+effect on any other line.
+
+When msm_gpiomux_put() is called on gpio 12 or 34 to drop their reference
+count to 0, their suspended configurations will be applied.
+Since no other gpio line has a valid suspended configuration, no other
+gpio line will be effected by msm_gpiomux_put().  Since gpio 34 has no valid
+active configuration, this is effectively a no-op for gpio 34 as well,
+with one small caveat, see the section "About Output-Enable Settings".
+
+All of the GPIOMUX_VALID flags may seem like unnecessary overhead, but
+they address some important issues.  As unused entries (all those
+except 12 and 34) are zero-filled, gpiomux needs a way to distinguish
+the used fields from the unused.  In addition, the all-zero pattern
+is a valid configuration!  Therefore, gpiomux defines an additional bit
+which is used to indicate when a field is used.  This has the pleasant
+side-effect of allowing calls to msm_gpiomux_write to use '0' to indicate
+that a value should not be changed:
+
+  msm_gpiomux_write(0, GPIOMUX_VALID, 0);
+
+replaces the active configuration of gpio 0 with an all-zero configuration,
+but leaves the suspended configuration as it was.
+
+Static Configurations
+=====================
+
+To install a static configuration, which is applied at boot and does
+not change after that, install a configuration with a suspended component
+but no active component, as in the previous example:
+
+	[34] = {
+		.suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
+	},
+
+The suspended setting is applied during boot, and the lack of any valid
+active setting prevents any other setting from being applied at runtime.
+If other subsystems attempting to access the line is a concern, one could
+*really* anchor the configuration down by calling msm_gpiomux_get on the
+line at initialization to move the line into active mode.  With the line
+held, it will never be re-suspended, and with no valid active configuration,
+no new configurations will be applied.
+
+But then, if having other subsystems grabbing for the line is truly a concern,
+it should be reserved with gpio_request instead, which carries an implicit
+msm_gpiomux_get.
+
+gpiomux and gpiolib
+===================
+
+It is expected that msm gpio_chips will call msm_gpiomux_get() and
+msm_gpiomux_put() from their request and free hooks, like this fictional
+example:
+
+static int request(struct gpio_chip *chip, unsigned offset)
+{
+        return msm_gpiomux_get(chip->base + offset);
+}
+
+static void free(struct gpio_chip *chip, unsigned offset)
+{
+        msm_gpiomux_put(chip->base + offset);
+}
+
+	...somewhere in a gpio_chip declaration...
+	.request = request,
+	.free    = free,
+
+This provides important functionality:
+- It guarantees that a gpio line will have its 'active' config applied
+  when the line is requested, and will not be suspended while the line
+  remains requested; and
+- It guarantees that gpio-direction settings from gpiolib behave sensibly.
+  See "About Output-Enable Settings."
+
+This mechanism allows for "auto-request" of gpiomux lines via gpiolib
+when it is suitable.  Drivers wishing more exact control are, of course,
+free to also use msm_gpiomux_set and msm_gpiomux_get.
+
+About Output-Enable Settings
+============================
+
+Some msm targets do not have the ability to query the current gpio
+configuration setting.  This means that changes made to the output-enable
+(OE) bit by gpiolib cannot be consistently detected and preserved by gpiomux.
+Therefore, when gpiomux applies a configuration setting, any direction
+settings which may have been applied by gpiolib are lost and the default
+input settings are re-applied.
+
+For this reason, drivers should not assume that gpio direction settings
+continue to hold if they free and then re-request a gpio.  This seems like
+common sense - after all, anybody could have obtained the line in the
+meantime - but it needs saying.
+
+This also means that calls to msm_gpiomux_write will reset the OE bit,
+which means that if the gpio line is held by a client of gpiolib and
+msm_gpiomux_write is called, the direction setting has been lost and
+gpiolib's internal state has been broken.
+Release gpio lines before reconfiguring them.
diff --git a/Documentation/block/00-INDEX b/Documentation/block/00-INDEX
index a406286f..d111e3b 100644
--- a/Documentation/block/00-INDEX
+++ b/Documentation/block/00-INDEX
@@ -1,7 +1,5 @@
 00-INDEX
 	- This file
-barrier.txt
-	- I/O Barriers
 biodoc.txt
 	- Notes on the Generic Block Layer Rewrite in Linux 2.5
 capability.txt
@@ -16,3 +14,5 @@
 	- Block layer statistics in /sys/block/<dev>/stat
 switching-sched.txt
 	- Switching I/O schedulers at runtime
+writeback_cache_control.txt
+	- Control of volatile write back caches
diff --git a/Documentation/block/barrier.txt b/Documentation/block/barrier.txt
deleted file mode 100644
index 2c2f24f6..0000000
--- a/Documentation/block/barrier.txt
+++ /dev/null
@@ -1,261 +0,0 @@
-I/O Barriers
-============
-Tejun Heo <htejun@gmail.com>, July 22 2005
-
-I/O barrier requests are used to guarantee ordering around the barrier
-requests.  Unless you're crazy enough to use disk drives for
-implementing synchronization constructs (wow, sounds interesting...),
-the ordering is meaningful only for write requests for things like
-journal checkpoints.  All requests queued before a barrier request
-must be finished (made it to the physical medium) before the barrier
-request is started, and all requests queued after the barrier request
-must be started only after the barrier request is finished (again,
-made it to the physical medium).
-
-In other words, I/O barrier requests have the following two properties.
-
-1. Request ordering
-
-Requests cannot pass the barrier request.  Preceding requests are
-processed before the barrier and following requests after.
-
-Depending on what features a drive supports, this can be done in one
-of the following three ways.
-
-i. For devices which have queue depth greater than 1 (TCQ devices) and
-support ordered tags, block layer can just issue the barrier as an
-ordered request and the lower level driver, controller and drive
-itself are responsible for making sure that the ordering constraint is
-met.  Most modern SCSI controllers/drives should support this.
-
-NOTE: SCSI ordered tag isn't currently used due to limitation in the
-      SCSI midlayer, see the following random notes section.
-
-ii. For devices which have queue depth greater than 1 but don't
-support ordered tags, block layer ensures that the requests preceding
-a barrier request finishes before issuing the barrier request.  Also,
-it defers requests following the barrier until the barrier request is
-finished.  Older SCSI controllers/drives and SATA drives fall in this
-category.
-
-iii. Devices which have queue depth of 1.  This is a degenerate case
-of ii.  Just keeping issue order suffices.  Ancient SCSI
-controllers/drives and IDE drives are in this category.
-
-2. Forced flushing to physical medium
-
-Again, if you're not gonna do synchronization with disk drives (dang,
-it sounds even more appealing now!), the reason you use I/O barriers
-is mainly to protect filesystem integrity when power failure or some
-other events abruptly stop the drive from operating and possibly make
-the drive lose data in its cache.  So, I/O barriers need to guarantee
-that requests actually get written to non-volatile medium in order.
-
-There are four cases,
-
-i. No write-back cache.  Keeping requests ordered is enough.
-
-ii. Write-back cache but no flush operation.  There's no way to
-guarantee physical-medium commit order.  This kind of devices can't to
-I/O barriers.
-
-iii. Write-back cache and flush operation but no FUA (forced unit
-access).  We need two cache flushes - before and after the barrier
-request.
-
-iv. Write-back cache, flush operation and FUA.  We still need one
-flush to make sure requests preceding a barrier are written to medium,
-but post-barrier flush can be avoided by using FUA write on the
-barrier itself.
-
-
-How to support barrier requests in drivers
-------------------------------------------
-
-All barrier handling is done inside block layer proper.  All low level
-drivers have to are implementing its prepare_flush_fn and using one
-the following two functions to indicate what barrier type it supports
-and how to prepare flush requests.  Note that the term 'ordered' is
-used to indicate the whole sequence of performing barrier requests
-including draining and flushing.
-
-typedef void (prepare_flush_fn)(struct request_queue *q, struct request *rq);
-
-int blk_queue_ordered(struct request_queue *q, unsigned ordered,
-		      prepare_flush_fn *prepare_flush_fn);
-
-@q			: the queue in question
-@ordered		: the ordered mode the driver/device supports
-@prepare_flush_fn	: this function should prepare @rq such that it
-			  flushes cache to physical medium when executed
-
-For example, SCSI disk driver's prepare_flush_fn looks like the
-following.
-
-static void sd_prepare_flush(struct request_queue *q, struct request *rq)
-{
-	memset(rq->cmd, 0, sizeof(rq->cmd));
-	rq->cmd_type = REQ_TYPE_BLOCK_PC;
-	rq->timeout = SD_TIMEOUT;
-	rq->cmd[0] = SYNCHRONIZE_CACHE;
-	rq->cmd_len = 10;
-}
-
-The following seven ordered modes are supported.  The following table
-shows which mode should be used depending on what features a
-device/driver supports.  In the leftmost column of table,
-QUEUE_ORDERED_ prefix is omitted from the mode names to save space.
-
-The table is followed by description of each mode.  Note that in the
-descriptions of QUEUE_ORDERED_DRAIN*, '=>' is used whereas '->' is
-used for QUEUE_ORDERED_TAG* descriptions.  '=>' indicates that the
-preceding step must be complete before proceeding to the next step.
-'->' indicates that the next step can start as soon as the previous
-step is issued.
-
-	    write-back cache	ordered tag	flush		FUA
------------------------------------------------------------------------
-NONE		yes/no		N/A		no		N/A
-DRAIN		no		no		N/A		N/A
-DRAIN_FLUSH	yes		no		yes		no
-DRAIN_FUA	yes		no		yes		yes
-TAG		no		yes		N/A		N/A
-TAG_FLUSH	yes		yes		yes		no
-TAG_FUA		yes		yes		yes		yes
-
-
-QUEUE_ORDERED_NONE
-	I/O barriers are not needed and/or supported.
-
-	Sequence: N/A
-
-QUEUE_ORDERED_DRAIN
-	Requests are ordered by draining the request queue and cache
-	flushing isn't needed.
-
-	Sequence: drain => barrier
-
-QUEUE_ORDERED_DRAIN_FLUSH
-	Requests are ordered by draining the request queue and both
-	pre-barrier and post-barrier cache flushings are needed.
-
-	Sequence: drain => preflush => barrier => postflush
-
-QUEUE_ORDERED_DRAIN_FUA
-	Requests are ordered by draining the request queue and
-	pre-barrier cache flushing is needed.  By using FUA on barrier
-	request, post-barrier flushing can be skipped.
-
-	Sequence: drain => preflush => barrier
-
-QUEUE_ORDERED_TAG
-	Requests are ordered by ordered tag and cache flushing isn't
-	needed.
-
-	Sequence: barrier
-
-QUEUE_ORDERED_TAG_FLUSH
-	Requests are ordered by ordered tag and both pre-barrier and
-	post-barrier cache flushings are needed.
-
-	Sequence: preflush -> barrier -> postflush
-
-QUEUE_ORDERED_TAG_FUA
-	Requests are ordered by ordered tag and pre-barrier cache
-	flushing is needed.  By using FUA on barrier request,
-	post-barrier flushing can be skipped.
-
-	Sequence: preflush -> barrier
-
-
-Random notes/caveats
---------------------
-
-* SCSI layer currently can't use TAG ordering even if the drive,
-controller and driver support it.  The problem is that SCSI midlayer
-request dispatch function is not atomic.  It releases queue lock and
-switch to SCSI host lock during issue and it's possible and likely to
-happen in time that requests change their relative positions.  Once
-this problem is solved, TAG ordering can be enabled.
-
-* Currently, no matter which ordered mode is used, there can be only
-one barrier request in progress.  All I/O barriers are held off by
-block layer until the previous I/O barrier is complete.  This doesn't
-make any difference for DRAIN ordered devices, but, for TAG ordered
-devices with very high command latency, passing multiple I/O barriers
-to low level *might* be helpful if they are very frequent.  Well, this
-certainly is a non-issue.  I'm writing this just to make clear that no
-two I/O barrier is ever passed to low-level driver.
-
-* Completion order.  Requests in ordered sequence are issued in order
-but not required to finish in order.  Barrier implementation can
-handle out-of-order completion of ordered sequence.  IOW, the requests
-MUST be processed in order but the hardware/software completion paths
-are allowed to reorder completion notifications - eg. current SCSI
-midlayer doesn't preserve completion order during error handling.
-
-* Requeueing order.  Low-level drivers are free to requeue any request
-after they removed it from the request queue with
-blkdev_dequeue_request().  As barrier sequence should be kept in order
-when requeued, generic elevator code takes care of putting requests in
-order around barrier.  See blk_ordered_req_seq() and
-ELEVATOR_INSERT_REQUEUE handling in __elv_add_request() for details.
-
-Note that block drivers must not requeue preceding requests while
-completing latter requests in an ordered sequence.  Currently, no
-error checking is done against this.
-
-* Error handling.  Currently, block layer will report error to upper
-layer if any of requests in an ordered sequence fails.  Unfortunately,
-this doesn't seem to be enough.  Look at the following request flow.
-QUEUE_ORDERED_TAG_FLUSH is in use.
-
- [0] [1] [2] [3] [pre] [barrier] [post] < [4] [5] [6] ... >
-					  still in elevator
-
-Let's say request [2], [3] are write requests to update file system
-metadata (journal or whatever) and [barrier] is used to mark that
-those updates are valid.  Consider the following sequence.
-
- i.	Requests [0] ~ [post] leaves the request queue and enters
-	low-level driver.
- ii.	After a while, unfortunately, something goes wrong and the
-	drive fails [2].  Note that any of [0], [1] and [3] could have
-	completed by this time, but [pre] couldn't have been finished
-	as the drive must process it in order and it failed before
-	processing that command.
- iii.	Error handling kicks in and determines that the error is
-	unrecoverable and fails [2], and resumes operation.
- iv.	[pre] [barrier] [post] gets processed.
- v.	*BOOM* power fails
-
-The problem here is that the barrier request is *supposed* to indicate
-that filesystem update requests [2] and [3] made it safely to the
-physical medium and, if the machine crashes after the barrier is
-written, filesystem recovery code can depend on that.  Sadly, that
-isn't true in this case anymore.  IOW, the success of a I/O barrier
-should also be dependent on success of some of the preceding requests,
-where only upper layer (filesystem) knows what 'some' is.
-
-This can be solved by implementing a way to tell the block layer which
-requests affect the success of the following barrier request and
-making lower lever drivers to resume operation on error only after
-block layer tells it to do so.
-
-As the probability of this happening is very low and the drive should
-be faulty, implementing the fix is probably an overkill.  But, still,
-it's there.
-
-* In previous drafts of barrier implementation, there was fallback
-mechanism such that, if FUA or ordered TAG fails, less fancy ordered
-mode can be selected and the failed barrier request is retried
-automatically.  The rationale for this feature was that as FUA is
-pretty new in ATA world and ordered tag was never used widely, there
-could be devices which report to support those features but choke when
-actually given such requests.
-
- This was removed for two reasons 1. it's an overkill 2. it's
-impossible to implement properly when TAG ordering is used as low
-level drivers resume after an error automatically.  If it's ever
-needed adding it back and modifying low level drivers accordingly
-shouldn't be difficult.
diff --git a/Documentation/block/writeback_cache_control.txt b/Documentation/block/writeback_cache_control.txt
new file mode 100644
index 0000000..83407d3
--- /dev/null
+++ b/Documentation/block/writeback_cache_control.txt
@@ -0,0 +1,86 @@
+
+Explicit volatile write back cache control
+=====================================
+
+Introduction
+------------
+
+Many storage devices, especially in the consumer market, come with volatile
+write back caches.  That means the devices signal I/O completion to the
+operating system before data actually has hit the non-volatile storage.  This
+behavior obviously speeds up various workloads, but it means the operating
+system needs to force data out to the non-volatile storage when it performs
+a data integrity operation like fsync, sync or an unmount.
+
+The Linux block layer provides two simple mechanisms that let filesystems
+control the caching behavior of the storage device.  These mechanisms are
+a forced cache flush, and the Force Unit Access (FUA) flag for requests.
+
+
+Explicit cache flushes
+----------------------
+
+The REQ_FLUSH flag can be OR ed into the r/w flags of a bio submitted from
+the filesystem and will make sure the volatile cache of the storage device
+has been flushed before the actual I/O operation is started.  This explicitly
+guarantees that previously completed write requests are on non-volatile
+storage before the flagged bio starts. In addition the REQ_FLUSH flag can be
+set on an otherwise empty bio structure, which causes only an explicit cache
+flush without any dependent I/O.  It is recommend to use
+the blkdev_issue_flush() helper for a pure cache flush.
+
+
+Forced Unit Access
+-----------------
+
+The REQ_FUA flag can be OR ed into the r/w flags of a bio submitted from the
+filesystem and will make sure that I/O completion for this request is only
+signaled after the data has been committed to non-volatile storage.
+
+
+Implementation details for filesystems
+--------------------------------------
+
+Filesystems can simply set the REQ_FLUSH and REQ_FUA bits and do not have to
+worry if the underlying devices need any explicit cache flushing and how
+the Forced Unit Access is implemented.  The REQ_FLUSH and REQ_FUA flags
+may both be set on a single bio.
+
+
+Implementation details for make_request_fn based block drivers
+--------------------------------------------------------------
+
+These drivers will always see the REQ_FLUSH and REQ_FUA bits as they sit
+directly below the submit_bio interface.  For remapping drivers the REQ_FUA
+bits need to be propagated to underlying devices, and a global flush needs
+to be implemented for bios with the REQ_FLUSH bit set.  For real device
+drivers that do not have a volatile cache the REQ_FLUSH and REQ_FUA bits
+on non-empty bios can simply be ignored, and REQ_FLUSH requests without
+data can be completed successfully without doing any work.  Drivers for
+devices with volatile caches need to implement the support for these
+flags themselves without any help from the block layer.
+
+
+Implementation details for request_fn based block drivers
+--------------------------------------------------------------
+
+For devices that do not support volatile write caches there is no driver
+support required, the block layer completes empty REQ_FLUSH requests before
+entering the driver and strips off the REQ_FLUSH and REQ_FUA bits from
+requests that have a payload.  For devices with volatile write caches the
+driver needs to tell the block layer that it supports flushing caches by
+doing:
+
+	blk_queue_flush(sdkp->disk->queue, REQ_FLUSH);
+
+and handle empty REQ_FLUSH requests in its prep_fn/request_fn.  Note that
+REQ_FLUSH requests with a payload are automatically turned into a sequence
+of an empty REQ_FLUSH request followed by the actual write by the block
+layer.  For devices that also support the FUA bit the block layer needs
+to be told to pass through the REQ_FUA bit using:
+
+	blk_queue_flush(sdkp->disk->queue, REQ_FLUSH | REQ_FUA);
+
+and the driver must handle write requests that have the REQ_FUA bit set
+in prep_fn/request_fn.  If the FUA bit is not natively supported the block
+layer turns it into an empty REQ_FLUSH request after the actual write.
diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt
index 6919d62..d6da611 100644
--- a/Documentation/cgroups/blkio-controller.txt
+++ b/Documentation/cgroups/blkio-controller.txt
@@ -8,12 +8,17 @@
 Plan is to use the same cgroup based management interface for blkio controller
 and based on user options switch IO policies in the background.
 
-In the first phase, this patchset implements proportional weight time based
-division of disk policy. It is implemented in CFQ. Hence this policy takes
-effect only on leaf nodes when CFQ is being used.
+Currently two IO control policies are implemented. First one is proportional
+weight time based division of disk policy. It is implemented in CFQ. Hence
+this policy takes effect only on leaf nodes when CFQ is being used. The second
+one is throttling policy which can be used to specify upper IO rate limits
+on devices. This policy is implemented in generic block layer and can be
+used on leaf nodes as well as higher level logical devices like device mapper.
 
 HOWTO
 =====
+Proportional Weight division of bandwidth
+-----------------------------------------
 You can do a very simple testing of running two dd threads in two different
 cgroups. Here is what you can do.
 
@@ -55,6 +60,35 @@
   group dispatched to the disk. We provide fairness in terms of disk time, so
   ideally io.disk_time of cgroups should be in proportion to the weight.
 
+Throttling/Upper Limit policy
+-----------------------------
+- Enable Block IO controller
+	CONFIG_BLK_CGROUP=y
+
+- Enable throttling in block layer
+	CONFIG_BLK_DEV_THROTTLING=y
+
+- Mount blkio controller
+        mount -t cgroup -o blkio none /cgroup/blkio
+
+- Specify a bandwidth rate on particular device for root group. The format
+  for policy is "<major>:<minor>  <byes_per_second>".
+
+        echo "8:16  1048576" > /cgroup/blkio/blkio.read_bps_device
+
+  Above will put a limit of 1MB/second on reads happening for root group
+  on device having major/minor number 8:16.
+
+- Run dd to read a file and see if rate is throttled to 1MB/s or not.
+
+		# dd if=/mnt/common/zerofile of=/dev/null bs=4K count=1024
+		# iflag=direct
+        1024+0 records in
+        1024+0 records out
+        4194304 bytes (4.2 MB) copied, 4.0001 s, 1.0 MB/s
+
+ Limits for writes can be put using blkio.write_bps_device file.
+
 Various user visible config options
 ===================================
 CONFIG_BLK_CGROUP
@@ -68,8 +102,13 @@
 	- Enables group scheduling in CFQ. Currently only 1 level of group
 	  creation is allowed.
 
+CONFIG_BLK_DEV_THROTTLING
+	- Enable block device throttling support in block layer.
+
 Details of cgroup files
 =======================
+Proportional weight policy files
+--------------------------------
 - blkio.weight
 	- Specifies per cgroup weight. This is default weight of the group
 	  on all the devices until and unless overridden by per device rule.
@@ -210,6 +249,67 @@
 	  and minor number of the device and third field specifies the number
 	  of times a group was dequeued from a particular device.
 
+Throttling/Upper limit policy files
+-----------------------------------
+- blkio.throttle.read_bps_device
+	- Specifies upper limit on READ rate from the device. IO rate is
+	  specified in bytes per second. Rules are per deivce. Following is
+	  the format.
+
+  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.read_bps_device
+
+- blkio.throttle.write_bps_device
+	- Specifies upper limit on WRITE rate to the device. IO rate is
+	  specified in bytes per second. Rules are per deivce. Following is
+	  the format.
+
+  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.write_bps_device
+
+- blkio.throttle.read_iops_device
+	- Specifies upper limit on READ rate from the device. IO rate is
+	  specified in IO per second. Rules are per deivce. Following is
+	  the format.
+
+  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.read_iops_device
+
+- blkio.throttle.write_iops_device
+	- Specifies upper limit on WRITE rate to the device. IO rate is
+	  specified in io per second. Rules are per deivce. Following is
+	  the format.
+
+  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.write_iops_device
+
+Note: If both BW and IOPS rules are specified for a device, then IO is
+      subjectd to both the constraints.
+
+- blkio.throttle.io_serviced
+	- Number of IOs (bio) completed to/from the disk by the group (as
+	  seen by throttling policy). These are further divided by the type
+	  of operation - read or write, sync or async. First two fields specify
+	  the major and minor number of the device, third field specifies the
+	  operation type and the fourth field specifies the number of IOs.
+
+	  blkio.io_serviced does accounting as seen by CFQ and counts are in
+	  number of requests (struct request). On the other hand,
+	  blkio.throttle.io_serviced counts number of IO in terms of number
+	  of bios as seen by throttling policy.  These bios can later be
+	  merged by elevator and total number of requests completed can be
+	  lesser.
+
+- blkio.throttle.io_service_bytes
+	- Number of bytes transferred to/from the disk by the group. These
+	  are further divided by the type of operation - read or write, sync
+	  or async. First two fields specify the major and minor number of the
+	  device, third field specifies the operation type and the fourth field
+	  specifies the number of bytes.
+
+	  These numbers should roughly be same as blkio.io_service_bytes as
+	  updated by CFQ. The difference between two is that
+	  blkio.io_service_bytes will not be updated if CFQ is not operating
+	  on request queue.
+
+Common files among various policies
+-----------------------------------
 - blkio.reset_stats
 	- Writing an int to this file will result in resetting all the stats
 	  for that cgroup.
diff --git a/Documentation/cputopology.txt b/Documentation/cputopology.txt
index f1c5c4b..902d315 100644
--- a/Documentation/cputopology.txt
+++ b/Documentation/cputopology.txt
@@ -14,25 +14,39 @@
 	identifier (rather than the kernel's).  The actual value is
 	architecture and platform dependent.
 
-3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
+3) /sys/devices/system/cpu/cpuX/topology/book_id:
+
+	the book ID of cpuX. Typically it is the hardware platform's
+	identifier (rather than the kernel's).	The actual value is
+	architecture and platform dependent.
+
+4) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
 
 	internel kernel map of cpuX's hardware threads within the same
 	core as cpuX
 
-4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
+5) /sys/devices/system/cpu/cpuX/topology/core_siblings:
 
 	internal kernel map of cpuX's hardware threads within the same
 	physical_package_id.
 
+6) /sys/devices/system/cpu/cpuX/topology/book_siblings:
+
+	internal kernel map of cpuX's hardware threads within the same
+	book_id.
+
 To implement it in an architecture-neutral way, a new source file,
-drivers/base/topology.c, is to export the 4 attributes.
+drivers/base/topology.c, is to export the 4 or 6 attributes. The two book
+related sysfs files will only be created if CONFIG_SCHED_BOOK is selected.
 
 For an architecture to support this feature, it must define some of
 these macros in include/asm-XXX/topology.h:
 #define topology_physical_package_id(cpu)
 #define topology_core_id(cpu)
+#define topology_book_id(cpu)
 #define topology_thread_cpumask(cpu)
 #define topology_core_cpumask(cpu)
+#define topology_book_cpumask(cpu)
 
 The type of **_id is int.
 The type of siblings is (const) struct cpumask *.
@@ -45,6 +59,9 @@
 3) thread_siblings: just the given CPU
 4) core_siblings: just the given CPU
 
+For architectures that don't support books (CONFIG_SCHED_BOOK) there are no
+default definitions for topology_book_id() and topology_book_cpumask().
+
 Additionally, CPU topology information is provided under
 /sys/devices/system/cpu and includes these files.  The internal
 source for the output is in brackets ("[]").
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index d0d1df6..c58abf1 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -239,6 +239,7 @@
 		  0 = /dev/tty		Current TTY device
 		  1 = /dev/console	System console
 		  2 = /dev/ptmx		PTY master multiplex
+		  3 = /dev/ttyprintk	User messages via printk TTY device
 		 64 = /dev/cua0		Callout device for ttyS0
 		    ...
 		255 = /dev/cua191	Callout device for ttyS191
@@ -2553,7 +2554,10 @@
 		175 = /dev/usb/legousbtower15	16th USB Legotower device
 		176 = /dev/usb/usbtmc1	First USB TMC device
 		   ...
-		192 = /dev/usb/usbtmc16	16th USB TMC device
+		191 = /dev/usb/usbtmc16	16th USB TMC device
+		192 = /dev/usb/yurex1	First USB Yurex device
+		   ...
+		209 = /dev/usb/yurex16	16th USB Yurex device
 		240 = /dev/usb/dabusb0	First daubusb device
 		    ...
 		243 = /dev/usb/dabusb3	Fourth dabusb device
diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt
index 674c566..58ea64a9 100644
--- a/Documentation/dynamic-debug-howto.txt
+++ b/Documentation/dynamic-debug-howto.txt
@@ -24,7 +24,7 @@
    read to display the complete list of known debug statements, to help guide you
 
 Controlling dynamic debug Behaviour
-===============================
+===================================
 
 The behaviour of pr_debug()/dev_debug()s are controlled via writing to a
 control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs
@@ -212,6 +212,26 @@
 Note also that there is no convenient syntax to remove all
 the flags at once, you need to use "-psc".
 
+
+Debug messages during boot process
+==================================
+
+To be able to activate debug messages during the boot process,
+even before userspace and debugfs exists, use the boot parameter:
+ddebug_query="QUERY"
+
+QUERY follows the syntax described above, but must not exceed 1023
+characters. The enablement of debug messages is done as an arch_initcall.
+Thus you can enable debug messages in all code processed after this
+arch_initcall via this boot parameter.
+On an x86 system for example ACPI enablement is a subsys_initcall and
+ddebug_query="file ec.c +p"
+will show early Embedded Controller transactions during ACPI setup if
+your machine (typically a laptop) has an Embedded Controller.
+PCI (or other devices) initialization also is a hot candidate for using
+this boot parameter for debugging purposes.
+
+
 Examples
 ========
 
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 842aa9d..9961f15 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -386,34 +386,6 @@
 
 ----------------------------
 
-What:	Support for VMware's guest paravirtuliazation technique [VMI] will be
-	dropped.
-When:	2.6.37 or earlier.
-Why:	With the recent innovations in CPU hardware acceleration technologies
-	from Intel and AMD, VMware ran a few experiments to compare these
-	techniques to guest paravirtualization technique on VMware's platform.
-	These hardware assisted virtualization techniques have outperformed the
-	performance benefits provided by VMI in most of the workloads. VMware
-	expects that these hardware features will be ubiquitous in a couple of
-	years, as a result, VMware has started a phased retirement of this
-	feature from the hypervisor. We will be removing this feature from the
-	Kernel too. Right now we are targeting 2.6.37 but can retire earlier if
-	technical reasons (read opportunity to remove major chunk of pvops)
-	arise.
-
-	Please note that VMI has always been an optimization and non-VMI kernels
-	still work fine on VMware's platform.
-	Latest versions of VMware's product which support VMI are,
-	Workstation 7.0 and VSphere 4.0 on ESX side, future maintainence
-	releases for these products will continue supporting VMI.
-
-	For more details about VMI retirement take a look at this,
-	http://blogs.vmware.com/guestosguide/2009/09/vmi-retirement.html
-
-Who:	Alok N Kataria <akataria@vmware.com>
-
-----------------------------
-
 What:	Support for lcd_switch and display_get in asus-laptop driver
 When:	March 2010
 Why:	These two features use non-standard interfaces. There are the
@@ -564,3 +536,12 @@
 
 ----------------------------
 
+What:	iwlwifi disable_hw_scan module parameters
+When:	2.6.40
+Why:	Hareware scan is the prefer method for iwlwifi devices for
+	scanning operation. Remove software scan support for all the
+	iwlwifi devices.
+
+Who:	Wey-Yi Guy <wey-yi.w.guy@intel.com>
+
+----------------------------
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt
index 1f7ae14..5393e66 100644
--- a/Documentation/filesystems/ocfs2.txt
+++ b/Documentation/filesystems/ocfs2.txt
@@ -87,3 +87,10 @@
 			reservations - users should rarely need to change this
 			value. If allocation reservations are turned off, this
 			option will have no effect.
+coherency=full  (*)	Disallow concurrent O_DIRECT writes, cluster inode
+			lock will be taken to force other nodes drop cache,
+			therefore full cluster coherency is guaranteed even
+			for O_DIRECT writes.
+coherency=buffered	Allow concurrent O_DIRECT writes without EX lock among
+			nodes, which gains high performance at risk of getting
+			stale data on other nodes.
diff --git a/Documentation/input/ntrig.txt b/Documentation/input/ntrig.txt
new file mode 100644
index 0000000..be1fd98
--- /dev/null
+++ b/Documentation/input/ntrig.txt
@@ -0,0 +1,126 @@
+N-Trig touchscreen Driver
+-------------------------
+	Copyright (c) 2008-2010 Rafi Rubin <rafi@seas.upenn.edu>
+	Copyright (c) 2009-2010 Stephane Chatty
+
+This driver provides support for N-Trig pen and multi-touch sensors.  Single
+and multi-touch events are translated to the appropriate protocols for
+the hid and input systems.  Pen events are sufficiently hid compliant and
+are left to the hid core.  The driver also provides additional filtering
+and utility functions accessible with sysfs and module parameters.
+
+This driver has been reported to work properly with multiple N-Trig devices
+attached.
+
+
+Parameters
+----------
+
+Note: values set at load time are global and will apply to all applicable
+devices.  Adjusting parameters with sysfs will override the load time values,
+but only for that one device.
+
+The following parameters are used to configure filters to reduce noise:
+
+activate_slack		number of fingers to ignore before processing events
+
+activation_height	size threshold to activate immediately
+activation_width
+
+min_height		size threshold bellow which fingers are ignored
+min_width		both to decide activation and during activity
+
+deactivate_slack	the number of "no contact" frames to ignore before
+			propagating the end of activity events
+
+When the last finger is removed from the device, it sends a number of empty
+frames.  By holding off on deactivation for a few frames we can tolerate false
+erroneous disconnects, where the sensor may mistakenly not detect a finger that
+is still present.  Thus deactivate_slack addresses problems where a users might
+see breaks in lines during drawing, or drop an object during a long drag.
+
+
+Additional sysfs items
+----------------------
+
+These nodes just provide easy access to the ranges reported by the device.
+sensor_logical_height	the range for positions reported during activity
+sensor_logical_width
+
+sensor_physical_height	internal ranges not used for normal events but
+sensor_physical_width	useful for tuning
+
+All N-Trig devices with product id of 1 report events in the ranges of
+X: 0-9600
+Y: 0-7200
+However not all of these devices have the same physical dimensions.  Most
+seem to be 12" sensors (Dell Latitude XT and XT2 and the HP TX2), and
+at least one model (Dell Studio 17) has a 17" sensor.  The ratio of physical
+to logical sizes is used to adjust the size based filter parameters.
+
+
+Filtering
+---------
+
+With the release of the early multi-touch firmwares it became increasingly
+obvious that these sensors were prone to erroneous events.  Users reported
+seeing both inappropriately dropped contact and ghosts, contacts reported
+where no finger was actually touching the screen.
+
+Deactivation slack helps prevent dropped contact for single touch use, but does
+not address the problem of dropping one of more contacts while other contacts
+are still active.  Drops in the multi-touch context require additional
+processing and should be handled in tandem with tacking.
+
+As observed ghost contacts are similar to actual use of the sensor, but they
+seem to have different profiles.  Ghost activity typically shows up as small
+short lived touches.  As such, I assume that the longer the continuous stream
+of events the more likely those events are from a real contact, and that the
+larger the size of each contact the more likely it is real.  Balancing the
+goals of preventing ghosts and accepting real events quickly (to minimize
+user observable latency), the filter accumulates confidence for incoming
+events until it hits thresholds and begins propagating.  In the interest in
+minimizing stored state as well as the cost of operations to make a decision,
+I've kept that decision simple.
+
+Time is measured in terms of the number of fingers reported, not frames since
+the probability of multiple simultaneous ghosts is expected to drop off
+dramatically with increasing numbers.  Rather than accumulate weight as a
+function of size, I just use it as a binary threshold.  A sufficiently large
+contact immediately overrides the waiting period and leads to activation.
+
+Setting the activation size thresholds to large values will result in deciding
+primarily on activation slack.  If you see longer lived ghosts, turning up the
+activation slack while reducing the size thresholds may suffice to eliminate
+the ghosts while keeping the screen quite responsive to firm taps.
+
+Contacts continue to be filtered with min_height and min_width even after
+the initial activation filter is satisfied.  The intent is to provide
+a mechanism for filtering out ghosts in the form of an extra finger while
+you actually are using the screen.  In practice this sort of ghost has
+been far less problematic or relatively rare and I've left the defaults
+set to 0 for both parameters, effectively turning off that filter.
+
+I don't know what the optimal values are for these filters.  If the defaults
+don't work for you, please play with the parameters.  If you do find other
+values more comfortable, I would appreciate feedback.
+
+The calibration of these devices does drift over time.  If ghosts or contact
+dropping worsen and interfere with the normal usage of your device, try
+recalibrating it.
+
+
+Calibration
+-----------
+
+The N-Trig windows tools provide calibration and testing routines.  Also an
+unofficial unsupported set of user space tools including a calibrator is
+available at:
+http://code.launchpad.net/~rafi-seas/+junk/ntrig_calib
+
+
+Tracking
+--------
+
+As of yet, all tested N-Trig firmwares do not track fingers.  When multiple
+contacts are active they seem to be sorted primarily by Y position.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 8dd7248..4cd8b86 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -43,10 +43,11 @@
 	AVR32	AVR32 architecture is enabled.
 	AX25	Appropriate AX.25 support is enabled.
 	BLACKFIN Blackfin architecture is enabled.
-	DRM	Direct Rendering Management support is enabled.
 	EDD	BIOS Enhanced Disk Drive Services (EDD) is enabled
 	EFI	EFI Partitioning (GPT) is enabled
 	EIDE	EIDE/ATAPI support is enabled.
+	DRM	Direct Rendering Management support is enabled.
+	DYNAMIC_DEBUG Build in debug messages and enable them at runtime
 	FB	The frame buffer device is enabled.
 	GCOV	GCOV profiling is enabled.
 	HW	Appropriate hardware is enabled.
@@ -455,7 +456,7 @@
 			[ARM] imx_timer1,OSTS,netx_timer,mpu_timer2,
 				pxa_timer,timer3,32k_counter,timer0_1
 			[AVR32] avr32
-			[X86-32] pit,hpet,tsc,vmi-timer;
+			[X86-32] pit,hpet,tsc;
 				scx200_hrt on Geode; cyclone on IBM x440
 			[MIPS] MIPS
 			[PARISC] cr16
@@ -570,6 +571,10 @@
 			Format: <port#>,<type>
 			See also Documentation/input/joystick-parport.txt
 
+	ddebug_query=   [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot
+			time. See Documentation/dynamic-debug-howto.txt for
+			details.
+
 	debug		[KNL] Enable kernel debugging (events log level).
 
 	debug_locks_verbose=
@@ -2153,6 +2158,11 @@
 			Reserves a hole at the top of the kernel virtual
 			address space.
 
+	reservelow=	[X86]
+			Format: nn[K]
+			Set the amount of memory to reserve for BIOS at
+			the bottom of the address space.
+
 	reset_devices	[KNL] Force drivers to reset the underlying device
 			during initialization.
 
@@ -2165,6 +2175,11 @@
 			in <PAGE_SIZE> units (needed only for swap files).
 			See  Documentation/power/swsusp-and-swap-files.txt
 
+	hibernate=	[HIBERNATION]
+		noresume	Don't check if there's a hibernation image
+				present during boot.
+		nocompress	Don't compress/decompress hibernation images.
+
 	retain_initrd	[RAM] Keep initrd memory after extraction
 
 	rhash_entries=	[KNL,NET]
@@ -2360,6 +2375,15 @@
 
 	switches=	[HW,M68k]
 
+	sysfs.deprecated=0|1 [KNL]
+			Enable/disable old style sysfs layout for old udev
+			on older distributions. When this option is enabled
+			very new udev will not work anymore. When this option
+			is disabled (or CONFIG_SYSFS_DEPRECATED not compiled)
+			in older udev will not work anymore.
+			Default depends on CONFIG_SYSFS_DEPRECATED_V2 set in
+			the kernel configuration.
+
 	sysrq_always_enabled
 			[KNL]
 			Ignore sysrq setting - this boot parameter will
@@ -2435,6 +2459,10 @@
 			disables clocksource verification at runtime.
 			Used to enable high-resolution timer mode on older
 			hardware, and in virtualized environment.
+			[x86] noirqtime: Do not use TSC to do irq accounting.
+			Used to run time disable IRQ_TIME_ACCOUNTING on any
+			platforms where RDTSC is slow and this accounting
+			can add overhead.
 
 	turbografx.map[2|3]=	[HW,JOY]
 			TurboGraFX parallel port interface
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt
index 1762b81..741fe66 100644
--- a/Documentation/kprobes.txt
+++ b/Documentation/kprobes.txt
@@ -542,9 +542,11 @@
 registration and unregistration.
 
 Probe handlers are run with preemption disabled.  Depending on the
-architecture, handlers may also run with interrupts disabled.  In any
-case, your handler should not yield the CPU (e.g., by attempting to
-acquire a semaphore).
+architecture and optimization state, handlers may also run with
+interrupts disabled (e.g., kretprobe handlers and optimized kprobe
+handlers run without interrupt disabled on x86/x86-64).  In any case,
+your handler should not yield the CPU (e.g., by attempting to acquire
+a semaphore).
 
 Since a return probe is implemented by replacing the return
 address with the trampoline's address, stack backtraces and calls
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index 8a6a8c6..dc73bc54 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -1640,15 +1640,6 @@
 	off = out->sector * 512;
 
 	/*
-	 * The block device implements "barriers", where the Guest indicates
-	 * that it wants all previous writes to occur before this write.  We
-	 * don't have a way of asking our kernel to do a barrier, so we just
-	 * synchronize all the data in the file.  Pretty poor, no?
-	 */
-	if (out->type & VIRTIO_BLK_T_BARRIER)
-		fdatasync(vblk->fd);
-
-	/*
 	 * In general the virtio block driver is allowed to try SCSI commands.
 	 * It'd be nice if we supported eject, for example, but we don't.
 	 */
@@ -1680,6 +1671,13 @@
 			/* Die, bad Guest, die. */
 			errx(1, "Write past end %llu+%u", off, ret);
 		}
+
+		wlen = sizeof(*in);
+		*in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
+	} else if (out->type & VIRTIO_BLK_T_FLUSH) {
+		/* Flush */
+		ret = fdatasync(vblk->fd);
+		verbose("FLUSH fdatasync: %i\n", ret);
 		wlen = sizeof(*in);
 		*in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
 	} else {
@@ -1703,15 +1701,6 @@
 		}
 	}
 
-	/*
-	 * OK, so we noted that it was pretty poor to use an fdatasync as a
-	 * barrier.  But Christoph Hellwig points out that we need a sync
-	 * *afterwards* as well: "Barriers specify no reordering to the front
-	 * or the back."  And Jens Axboe confirmed it, so here we are:
-	 */
-	if (out->type & VIRTIO_BLK_T_BARRIER)
-		fdatasync(vblk->fd);
-
 	/* Finished that request. */
 	add_used(vq, head, wlen);
 }
@@ -1736,8 +1725,8 @@
 	vblk->fd = open_or_die(filename, O_RDWR|O_LARGEFILE);
 	vblk->len = lseek64(vblk->fd, 0, SEEK_END);
 
-	/* We support barriers. */
-	add_feature(dev, VIRTIO_BLK_F_BARRIER);
+	/* We support FLUSH. */
+	add_feature(dev, VIRTIO_BLK_F_FLUSH);
 
 	/* Tell Guest how many sectors this device has. */
 	conf.capacity = cpu_to_le64(vblk->len / 512);
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index d2b62b7..5dc6387 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -765,6 +765,14 @@
 	does not exist, and the layer2 policy is the only policy.  The
 	layer2+3 value was added for bonding version 3.2.2.
 
+resend_igmp
+
+	Specifies the number of IGMP membership reports to be issued after
+	a failover event. One membership report is issued immediately after
+	the failover, subsequent packets are sent in each 200ms interval.
+
+	The valid range is 0 - 255; the default value is 1. This option
+	was added for bonding version 3.7.0.
 
 3. Configuring Bonding Devices
 ==============================
diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt
index cd79735..5b04b67 100644
--- a/Documentation/networking/can.txt
+++ b/Documentation/networking/can.txt
@@ -22,6 +22,7 @@
       4.1.2 RAW socket option CAN_RAW_ERR_FILTER
       4.1.3 RAW socket option CAN_RAW_LOOPBACK
       4.1.4 RAW socket option CAN_RAW_RECV_OWN_MSGS
+      4.1.5 RAW socket returned message flags
     4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
     4.3 connected transport protocols (SOCK_SEQPACKET)
     4.4 unconnected transport protocols (SOCK_DGRAM)
@@ -471,6 +472,17 @@
     setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
                &recv_own_msgs, sizeof(recv_own_msgs));
 
+  4.1.5 RAW socket returned message flags
+
+  When using recvmsg() call, the msg->msg_flags may contain following flags:
+
+    MSG_DONTROUTE: set when the received frame was created on the local host.
+
+    MSG_CONFIRM: set when the frame was sent via the socket it is received on.
+      This flag can be interpreted as a 'transmission confirmation' when the
+      CAN driver supports the echo of frames on driver level, see 3.2 and 6.2.
+      In order to receive such messages, CAN_RAW_RECV_OWN_MSGS must be set.
+
   4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
   4.3 connected transport protocols (SOCK_SEQPACKET)
   4.4 unconnected transport protocols (SOCK_DGRAM)
diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt
index a62fdf7..271d524 100644
--- a/Documentation/networking/dccp.txt
+++ b/Documentation/networking/dccp.txt
@@ -1,18 +1,20 @@
 DCCP protocol
-============
+=============
 
 
 Contents
 ========
-
 - Introduction
 - Missing features
 - Socket options
+- Sysctl variables
+- IOCTLs
+- Other tunables
 - Notes
 
+
 Introduction
 ============
-
 Datagram Congestion Control Protocol (DCCP) is an unreliable, connection
 oriented protocol designed to solve issues present in UDP and TCP, particularly
 for real-time and multimedia (streaming) traffic.
@@ -29,9 +31,9 @@
 DCCP is a Proposed Standard (RFC 2026), and the homepage for DCCP as a protocol
 is at http://www.ietf.org/html.charters/dccp-charter.html
 
+
 Missing features
 ================
-
 The Linux DCCP implementation does not currently support all the features that are
 specified in RFCs 4340...42.
 
@@ -45,7 +47,6 @@
 
 Socket options
 ==============
-
 DCCP_SOCKOPT_SERVICE sets the service. The specification mandates use of
 service codes (RFC 4340, sec. 8.1.2); if this socket option is not set,
 the socket will fall back to 0 (which means that no meaningful service code
@@ -112,6 +113,7 @@
 On unidirectional connections it is useful to close the unused half-connection
 via shutdown (SHUT_WR or SHUT_RD): this will reduce per-packet processing costs.
 
+
 Sysctl variables
 ================
 Several DCCP default parameters can be managed by the following sysctls
@@ -155,15 +157,30 @@
 	sequence-invalid packets on the same socket (RFC 4340, 7.5.4). The unit
 	of this parameter is milliseconds; a value of 0 disables rate-limiting.
 
+
 IOCTLS
 ======
 FIONREAD
 	Works as in udp(7): returns in the `int' argument pointer the size of
 	the next pending datagram in bytes, or 0 when no datagram is pending.
 
+
+Other tunables
+==============
+Per-route rto_min support
+	CCID-2 supports the RTAX_RTO_MIN per-route setting for the minimum value
+	of the RTO timer. This setting can be modified via the 'rto_min' option
+	of iproute2; for example:
+		> ip route change 10.0.0.0/24   rto_min 250j dev wlan0
+		> ip route add    10.0.0.254/32 rto_min 800j dev wlan0
+		> ip route show dev wlan0
+	CCID-3 also supports the rto_min setting: it is used to define the lower
+	bound for the expiry of the nofeedback timer. This can be useful on LANs
+	with very low RTTs (e.g., loopback, Gbit ethernet).
+
+
 Notes
 =====
-
 DCCP does not travel through NAT successfully at present on many boxes. This is
 because the checksum covers the pseudo-header as per TCP and UDP. Linux NAT
 support for DCCP has been added.
diff --git a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt
index 2df7186..d9271e7 100644
--- a/Documentation/networking/e1000.txt
+++ b/Documentation/networking/e1000.txt
@@ -1,82 +1,35 @@
 Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters
 ===============================================================
 
-September 26, 2006
-
+Intel Gigabit Linux driver.
+Copyright(c) 1999 - 2010 Intel Corporation.
 
 Contents
 ========
 
-- In This Release
 - Identifying Your Adapter
-- Building and Installation
 - Command Line Parameters
 - Speed and Duplex Configuration
 - Additional Configurations
-- Known Issues
 - Support
 
-
-In This Release
-===============
-
-This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family
-of Adapters.  This driver includes support for Itanium(R)2-based systems.
-
-For questions related to hardware requirements, refer to the documentation
-supplied with your Intel PRO/1000 adapter. All hardware requirements listed
-apply to use with Linux.
-
-The following features are now available in supported kernels:
- - Native VLANs
- - Channel Bonding (teaming)
- - SNMP
-
-Channel Bonding documentation can be found in the Linux kernel source:
-/Documentation/networking/bonding.txt
-
-The driver information previously displayed in the /proc filesystem is not
-supported in this release.  Alternatively, you can use ethtool (version 1.6
-or later), lspci, and ifconfig to obtain the same information.
-
-Instructions on updating ethtool can be found in the section "Additional
-Configurations" later in this document.
-
-NOTE: The Intel(R) 82562v 10/100 Network Connection only provides 10/100
-support.
-
-
 Identifying Your Adapter
 ========================
 
 For more information on how to identify your adapter, go to the Adapter &
 Driver ID Guide at:
 
-    http://support.intel.com/support/network/adapter/pro100/21397.htm
+    http://support.intel.com/support/go/network/adapter/idguide.htm
 
 For the latest Intel network drivers for Linux, refer to the following
 website.  In the search field, enter your adapter name or type, or use the
 networking link on the left to search for your adapter:
 
-    http://downloadfinder.intel.com/scripts-df/support_intel.asp
-
+    http://support.intel.com/support/go/network/adapter/home.htm
 
 Command Line Parameters
 =======================
 
-If the driver is built as a module, the  following optional parameters
-are used by entering them on the command line with the modprobe command
-using this syntax:
-
-     modprobe e1000 [<option>=<VAL1>,<VAL2>,...]
-
-For example, with two PRO/1000 PCI adapters, entering:
-
-     modprobe e1000 TxDescriptors=80,128
-
-loads the e1000 driver with 80 TX descriptors for the first adapter and
-128 TX descriptors for the second adapter.
-
 The default value for each parameter is generally the recommended setting,
 unless otherwise noted.
 
@@ -89,10 +42,6 @@
         parameters, see the application note at:
         http://www.intel.com/design/network/applnots/ap450.htm
 
-        A descriptor describes a data buffer and attributes related to
-        the data buffer.  This information is accessed by the hardware.
-
-
 AutoNeg
 -------
 (Supported only on adapters with copper connections)
@@ -106,7 +55,6 @@
 NOTE:  Refer to the Speed and Duplex section of this readme for more
        information on the AutoNeg parameter.
 
-
 Duplex
 ------
 (Supported only on adapters with copper connections)
@@ -119,7 +67,6 @@
 link partner is forced (either full or half), Duplex defaults to half-
 duplex.
 
-
 FlowControl
 -----------
 Valid Range:   0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx)
@@ -128,16 +75,16 @@
 This parameter controls the automatic generation(Tx) and response(Rx)
 to Ethernet PAUSE frames.
 
-
 InterruptThrottleRate
 ---------------------
 (not supported on Intel(R) 82542, 82543 or 82544-based adapters)
-Valid Range:   0,1,3,100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
+Valid Range:   0,1,3,4,100-100000 (0=off, 1=dynamic, 3=dynamic conservative,
+                                   4=simplified balancing)
 Default Value: 3
 
 The driver can limit the amount of interrupts per second that the adapter
-will generate for incoming packets. It does this by writing a value to the 
-adapter that is based on the maximum amount of interrupts that the adapter 
+will generate for incoming packets. It does this by writing a value to the
+adapter that is based on the maximum amount of interrupts that the adapter
 will generate per second.
 
 Setting InterruptThrottleRate to a value greater or equal to 100
@@ -146,37 +93,43 @@
 load on the system and can lower CPU utilization under heavy load,
 but will increase latency as packets are not processed as quickly.
 
-The default behaviour of the driver previously assumed a static 
-InterruptThrottleRate value of 8000, providing a good fallback value for 
-all traffic types,but lacking in small packet performance and latency. 
-The hardware can handle many more small packets per second however, and 
+The default behaviour of the driver previously assumed a static
+InterruptThrottleRate value of 8000, providing a good fallback value for
+all traffic types,but lacking in small packet performance and latency.
+The hardware can handle many more small packets per second however, and
 for this reason an adaptive interrupt moderation algorithm was implemented.
 
 Since 7.3.x, the driver has two adaptive modes (setting 1 or 3) in which
-it dynamically adjusts the InterruptThrottleRate value based on the traffic 
+it dynamically adjusts the InterruptThrottleRate value based on the traffic
 that it receives. After determining the type of incoming traffic in the last
-timeframe, it will adjust the InterruptThrottleRate to an appropriate value 
+timeframe, it will adjust the InterruptThrottleRate to an appropriate value
 for that traffic.
 
 The algorithm classifies the incoming traffic every interval into
-classes.  Once the class is determined, the InterruptThrottleRate value is 
-adjusted to suit that traffic type the best. There are three classes defined: 
+classes.  Once the class is determined, the InterruptThrottleRate value is
+adjusted to suit that traffic type the best. There are three classes defined:
 "Bulk traffic", for large amounts of packets of normal size; "Low latency",
 for small amounts of traffic and/or a significant percentage of small
-packets; and "Lowest latency", for almost completely small packets or 
+packets; and "Lowest latency", for almost completely small packets or
 minimal traffic.
 
-In dynamic conservative mode, the InterruptThrottleRate value is set to 4000 
-for traffic that falls in class "Bulk traffic". If traffic falls in the "Low 
-latency" or "Lowest latency" class, the InterruptThrottleRate is increased 
+In dynamic conservative mode, the InterruptThrottleRate value is set to 4000
+for traffic that falls in class "Bulk traffic". If traffic falls in the "Low
+latency" or "Lowest latency" class, the InterruptThrottleRate is increased
 stepwise to 20000. This default mode is suitable for most applications.
 
 For situations where low latency is vital such as cluster or
 grid computing, the algorithm can reduce latency even more when
 InterruptThrottleRate is set to mode 1. In this mode, which operates
-the same as mode 3, the InterruptThrottleRate will be increased stepwise to 
+the same as mode 3, the InterruptThrottleRate will be increased stepwise to
 70000 for traffic in class "Lowest latency".
 
+In simplified mode the interrupt rate is based on the ratio of Tx and
+Rx traffic.  If the bytes per second rate is approximately equal, the
+interrupt rate will drop as low as 2000 interrupts per second.  If the
+traffic is mostly transmit or mostly receive, the interrupt rate could
+be as high as 8000.
+
 Setting InterruptThrottleRate to 0 turns off any interrupt moderation
 and may improve small packet latency, but is generally not suitable
 for bulk throughput traffic.
@@ -212,8 +165,6 @@
        be platform-specific.  If CPU utilization is not a concern, use
        RX_POLLING (NAPI) and default driver settings.
 
-
-
 RxDescriptors
 -------------
 Valid Range:   80-256 for 82542 and 82543-based adapters
@@ -225,15 +176,14 @@
 incoming packets, at the expense of increased system memory utilization.
 
 Each descriptor is 16 bytes.  A receive buffer is also allocated for each
-descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending 
+descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending
 on the MTU setting. The maximum MTU size is 16110.
 
-NOTE:  MTU designates the frame size.  It only needs to be set for Jumbo 
-       Frames.  Depending on the available system resources, the request 
-       for a higher number of receive descriptors may be denied.  In this 
+NOTE:  MTU designates the frame size.  It only needs to be set for Jumbo
+       Frames.  Depending on the available system resources, the request
+       for a higher number of receive descriptors may be denied.  In this
        case, use a lower number.
 
-
 RxIntDelay
 ----------
 Valid Range:   0-65535 (0=off)
@@ -254,7 +204,6 @@
           restoring the network connection.  To eliminate the potential
           for the hang ensure that RxIntDelay is set to 0.
 
-
 RxAbsIntDelay
 -------------
 (This parameter is supported only on 82540, 82545 and later adapters.)
@@ -268,7 +217,6 @@
 along with RxIntDelay, may improve traffic throughput in specific network
 conditions.
 
-
 Speed
 -----
 (This parameter is supported only on adapters with copper connections.)
@@ -280,7 +228,6 @@
 partner is set to auto-negotiate, the board will auto-detect the correct
 speed.  Duplex should also be set when Speed is set to either 10 or 100.
 
-
 TxDescriptors
 -------------
 Valid Range:   80-256 for 82542 and 82543-based adapters
@@ -295,6 +242,36 @@
        higher number of transmit descriptors may be denied.  In this case,
        use a lower number.
 
+TxDescriptorStep
+----------------
+Valid Range:    1 (use every Tx Descriptor)
+		4 (use every 4th Tx Descriptor)
+
+Default Value:  1 (use every Tx Descriptor)
+
+On certain non-Intel architectures, it has been observed that intense TX
+traffic bursts of short packets may result in an improper descriptor
+writeback. If this occurs, the driver will report a "TX Timeout" and reset
+the adapter, after which the transmit flow will restart, though data may
+have stalled for as much as 10 seconds before it resumes.
+
+The improper writeback does not occur on the first descriptor in a system
+memory cache-line, which is typically 32 bytes, or 4 descriptors long.
+
+Setting TxDescriptorStep to a value of 4 will ensure that all TX descriptors
+are aligned to the start of a system memory cache line, and so this problem
+will not occur.
+
+NOTES: Setting TxDescriptorStep to 4 effectively reduces the number of
+       TxDescriptors available for transmits to 1/4 of the normal allocation.
+       This has a possible negative performance impact, which may be
+       compensated for by allocating more descriptors using the TxDescriptors
+       module parameter.
+
+       There are other conditions which may result in "TX Timeout", which will
+       not be resolved by the use of the TxDescriptorStep parameter. As the
+       issue addressed by this parameter has never been observed on Intel
+       Architecture platforms, it should not be used on Intel platforms.
 
 TxIntDelay
 ----------
@@ -307,7 +284,6 @@
 system is reporting dropped transmits, this value may be set too high
 causing the driver to run out of available transmit descriptors.
 
-
 TxAbsIntDelay
 -------------
 (This parameter is supported only on 82540, 82545 and later adapters.)
@@ -330,6 +306,35 @@
 A value of '1' indicates that the driver should enable IP checksum
 offload for received packets (both UDP and TCP) to the adapter hardware.
 
+Copybreak
+---------
+Valid Range:   0-xxxxxxx (0=off)
+Default Value: 256
+Usage: insmod e1000.ko copybreak=128
+
+Driver copies all packets below or equaling this size to a fresh Rx
+buffer before handing it up the stack.
+
+This parameter is different than other parameters, in that it is a
+single (not 1,1,1 etc.) parameter applied to all driver instances and
+it is also available during runtime at
+/sys/module/e1000/parameters/copybreak
+
+SmartPowerDownEnable
+--------------------
+Valid Range: 0-1
+Default Value:  0 (disabled)
+
+Allows PHY to turn off in lower power states. The user can turn off
+this parameter in supported chipsets.
+
+KumeranLockLoss
+---------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+This workaround skips resetting the PHY at shutdown for the initial
+silicon releases of ICH8 systems.
 
 Speed and Duplex Configuration
 ==============================
@@ -385,40 +390,9 @@
 parameter should not be used.  Instead, use the Speed and Duplex parameters
 previously mentioned to force the adapter to the same speed and duplex.
 
-
 Additional Configurations
 =========================
 
-  Configuring the Driver on Different Distributions
-  -------------------------------------------------
-  Configuring a network driver to load properly when the system is started
-  is distribution dependent.  Typically, the configuration process involves
-  adding an alias line to /etc/modules.conf or /etc/modprobe.conf as well
-  as editing other system startup scripts and/or configuration files.  Many
-  popular Linux distributions ship with tools to make these changes for you.
-  To learn the proper way to configure a network device for your system,
-  refer to your distribution documentation.  If during this process you are
-  asked for the driver or module name, the name for the Linux Base Driver
-  for the Intel(R) PRO/1000 Family of Adapters is e1000.
-
-  As an example, if you install the e1000 driver for two PRO/1000 adapters
-  (eth0 and eth1) and set the speed and duplex to 10full and 100half, add
-  the following to modules.conf or or modprobe.conf:
-
-       alias eth0 e1000
-       alias eth1 e1000
-       options e1000 Speed=10,100 Duplex=2,1
-
-  Viewing Link Messages
-  ---------------------
-  Link messages will not be displayed to the console if the distribution is
-  restricting system messages.  In order to see network driver link messages
-  on your console, set dmesg to eight by entering the following:
-
-       dmesg -n 8
-
-  NOTE: This setting is not saved across reboots.
-
   Jumbo Frames
   ------------
   Jumbo Frames support is enabled by changing the MTU to a value larger than
@@ -437,9 +411,11 @@
    setting in a different location.
 
   Notes:
-
-  - To enable Jumbo Frames, increase the MTU size on the interface beyond
-    1500.
+  Degradation in throughput performance may be observed in some Jumbo frames
+  environments. If this is observed, increasing the application's socket buffer
+  size and/or increasing the /proc/sys/net/ipv4/tcp_*mem entry values may help.
+  See the specific application manual and /usr/src/linux*/Documentation/
+  networking/ip-sysctl.txt for more details.
 
   - The maximum MTU setting for Jumbo Frames is 16110.  This value coincides
     with the maximum Jumbo Frames size of 16128.
@@ -447,40 +423,11 @@
   - Using Jumbo Frames at 10 or 100 Mbps may result in poor performance or
     loss of link.
 
-  - Some Intel gigabit adapters that support Jumbo Frames have a frame size
-    limit of 9238 bytes, with a corresponding MTU size limit of 9216 bytes.
-    The adapters with this limitation are based on the Intel(R) 82571EB,
-    82572EI, 82573L and 80003ES2LAN controller.  These correspond to the
-    following product names:
-     Intel(R) PRO/1000 PT Server Adapter
-     Intel(R) PRO/1000 PT Desktop Adapter
-     Intel(R) PRO/1000 PT Network Connection
-     Intel(R) PRO/1000 PT Dual Port Server Adapter
-     Intel(R) PRO/1000 PT Dual Port Network Connection
-     Intel(R) PRO/1000 PF Server Adapter
-     Intel(R) PRO/1000 PF Network Connection
-     Intel(R) PRO/1000 PF Dual Port Server Adapter
-     Intel(R) PRO/1000 PB Server Connection
-     Intel(R) PRO/1000 PL Network Connection
-     Intel(R) PRO/1000 EB Network Connection with I/O Acceleration
-     Intel(R) PRO/1000 EB Backplane Connection with I/O Acceleration
-     Intel(R) PRO/1000 PT Quad Port Server Adapter
-
   - Adapters based on the Intel(R) 82542 and 82573V/E controller do not
     support Jumbo Frames. These correspond to the following product names:
      Intel(R) PRO/1000 Gigabit Server Adapter
      Intel(R) PRO/1000 PM Network Connection
 
-  - The following adapters do not support Jumbo Frames:
-     Intel(R) 82562V 10/100 Network Connection
-     Intel(R) 82566DM Gigabit Network Connection
-     Intel(R) 82566DC Gigabit Network Connection
-     Intel(R) 82566MM Gigabit Network Connection
-     Intel(R) 82566MC Gigabit Network Connection
-     Intel(R) 82562GT 10/100 Network Connection
-     Intel(R) 82562G 10/100 Network Connection
-
-
   Ethtool
   -------
   The driver utilizes the ethtool interface for driver configuration and
@@ -490,142 +437,14 @@
   The latest release of ethtool can be found from
   http://sourceforge.net/projects/gkernel.
 
-  NOTE: Ethtool 1.6 only supports a limited set of ethtool options.  Support
-  for a more complete ethtool feature set can be enabled by upgrading
-  ethtool to ethtool-1.8.1.
-
   Enabling Wake on LAN* (WoL)
   ---------------------------
-  WoL is configured through the Ethtool* utility.  Ethtool is included with
-  all versions of Red Hat after Red Hat 7.2.  For other Linux distributions,
-  download and install Ethtool from the following website:
-  http://sourceforge.net/projects/gkernel.
-
-  For instructions on enabling WoL with Ethtool, refer to the website listed
-  above.
+  WoL is configured through the Ethtool* utility.
 
   WoL will be enabled on the system during the next shut down or reboot.
   For this driver version, in order to enable WoL, the e1000 driver must be
   loaded when shutting down or rebooting the system.
 
-  Wake On LAN is only supported on port A for the following devices:
-  Intel(R) PRO/1000 PT Dual Port Network Connection
-  Intel(R) PRO/1000 PT Dual Port Server Connection
-  Intel(R) PRO/1000 PT Dual Port Server Adapter
-  Intel(R) PRO/1000 PF Dual Port Server Adapter
-  Intel(R) PRO/1000 PT Quad Port Server Adapter
-
-  NAPI
-  ----
-  NAPI (Rx polling mode) is enabled in the e1000 driver.
-
-  See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
-
-
-Known Issues
-============
-
-Dropped Receive Packets on Half-duplex 10/100 Networks
-------------------------------------------------------
-If you have an Intel PCI Express adapter running at 10mbps or 100mbps, half-
-duplex, you may observe occasional dropped receive packets.  There are no
-workarounds for this problem in this network configuration.  The network must
-be updated to operate in full-duplex, and/or 1000mbps only.
-
-Jumbo Frames System Requirement
--------------------------------
-Memory allocation failures have been observed on Linux systems with 64 MB
-of RAM or less that are running Jumbo Frames.  If you are using Jumbo
-Frames, your system may require more than the advertised minimum
-requirement of 64 MB of system memory.
-
-Performance Degradation with Jumbo Frames
------------------------------------------
-Degradation in throughput performance may be observed in some Jumbo frames
-environments.  If this is observed, increasing the application's socket
-buffer size and/or increasing the /proc/sys/net/ipv4/tcp_*mem entry values
-may help.  See the specific application manual and
-/usr/src/linux*/Documentation/
-networking/ip-sysctl.txt for more details.
-
-Jumbo Frames on Foundry BigIron 8000 switch
--------------------------------------------
-There is a known issue using Jumbo frames when connected to a Foundry
-BigIron 8000 switch.  This is a 3rd party limitation.  If you experience
-loss of packets, lower the MTU size.
-
-Allocating Rx Buffers when Using Jumbo Frames 
----------------------------------------------
-Allocating Rx buffers when using Jumbo Frames on 2.6.x kernels may fail if 
-the available memory is heavily fragmented. This issue may be seen with PCI-X 
-adapters or with packet split disabled. This can be reduced or eliminated 
-by changing the amount of available memory for receive buffer allocation, by
-increasing /proc/sys/vm/min_free_kbytes. 
-
-Multiple Interfaces on Same Ethernet Broadcast Network
-------------------------------------------------------
-Due to the default ARP behavior on Linux, it is not possible to have
-one system on two IP networks in the same Ethernet broadcast domain
-(non-partitioned switch) behave as expected.  All Ethernet interfaces
-will respond to IP traffic for any IP address assigned to the system.
-This results in unbalanced receive traffic.
-
-If you have multiple interfaces in a server, either turn on ARP
-filtering by entering:
-
-    echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
-(this only works if your kernel's version is higher than 2.4.5),
-
-NOTE: This setting is not saved across reboots.  The configuration
-change can be made permanent by adding the line:
-    net.ipv4.conf.all.arp_filter = 1
-to the file /etc/sysctl.conf
-
-      or,
-
-install the interfaces in separate broadcast domains (either in
-different switches or in a switch partitioned to VLANs).
-
-82541/82547 can't link or are slow to link with some link partners
------------------------------------------------------------------
-There is a known compatibility issue with 82541/82547 and some
-low-end switches where the link will not be established, or will
-be slow to establish.  In particular, these switches are known to
-be incompatible with 82541/82547:
-
-    Planex FXG-08TE
-    I-O Data ETG-SH8
-
-To workaround this issue, the driver can be compiled with an override
-of the PHY's master/slave setting.  Forcing master or forcing slave
-mode will improve time-to-link.
-
-    # make CFLAGS_EXTRA=-DE1000_MASTER_SLAVE=<n>
-
-Where <n> is:
-
-    0 = Hardware default
-    1 = Master mode
-    2 = Slave mode
-    3 = Auto master/slave
-
-Disable rx flow control with ethtool
-------------------------------------
-In order to disable receive flow control using ethtool, you must turn
-off auto-negotiation on the same command line.
-
-For example:
-
-   ethtool -A eth? autoneg off rx off
-
-Unplugging network cable while ethtool -p is running
-----------------------------------------------------
-In kernel versions 2.5.50 and later (including 2.6 kernel), unplugging
-the network cable while ethtool -p is running will cause the system to
-become unresponsive to keyboard commands, except for control-alt-delete.
-Restarting the system appears to be the only remedy.
-
-
 Support
 =======
 
diff --git a/Documentation/networking/e1000e.txt b/Documentation/networking/e1000e.txt
new file mode 100644
index 0000000..6aa048ba
--- /dev/null
+++ b/Documentation/networking/e1000e.txt
@@ -0,0 +1,302 @@
+Linux* Driver for Intel(R) Network Connection
+===============================================================
+
+Intel Gigabit Linux driver.
+Copyright(c) 1999 - 2010 Intel Corporation.
+
+Contents
+========
+
+- Identifying Your Adapter
+- Command Line Parameters
+- Additional Configurations
+- Support
+
+Identifying Your Adapter
+========================
+
+The e1000e driver supports all PCI Express Intel(R) Gigabit Network
+Connections, except those that are 82575, 82576 and 82580-based*.
+
+* NOTE: The Intel(R) PRO/1000 P Dual Port Server Adapter is supported by
+  the e1000 driver, not the e1000e driver due to the 82546 part being used
+  behind a PCI Express bridge.
+
+For more information on how to identify your adapter, go to the Adapter &
+Driver ID Guide at:
+
+    http://support.intel.com/support/go/network/adapter/idguide.htm
+
+For the latest Intel network drivers for Linux, refer to the following
+website.  In the search field, enter your adapter name or type, or use the
+networking link on the left to search for your adapter:
+
+    http://support.intel.com/support/go/network/adapter/home.htm
+
+Command Line Parameters
+=======================
+
+The default value for each parameter is generally the recommended setting,
+unless otherwise noted.
+
+NOTES:  For more information about the InterruptThrottleRate,
+        RxIntDelay, TxIntDelay, RxAbsIntDelay, and TxAbsIntDelay
+        parameters, see the application note at:
+        http://www.intel.com/design/network/applnots/ap450.htm
+
+InterruptThrottleRate
+---------------------
+Valid Range:   0,1,3,4,100-100000 (0=off, 1=dynamic, 3=dynamic conservative,
+                                   4=simplified balancing)
+Default Value: 3
+
+The driver can limit the amount of interrupts per second that the adapter
+will generate for incoming packets. It does this by writing a value to the
+adapter that is based on the maximum amount of interrupts that the adapter
+will generate per second.
+
+Setting InterruptThrottleRate to a value greater or equal to 100
+will program the adapter to send out a maximum of that many interrupts
+per second, even if more packets have come in. This reduces interrupt
+load on the system and can lower CPU utilization under heavy load,
+but will increase latency as packets are not processed as quickly.
+
+The driver has two adaptive modes (setting 1 or 3) in which
+it dynamically adjusts the InterruptThrottleRate value based on the traffic
+that it receives. After determining the type of incoming traffic in the last
+timeframe, it will adjust the InterruptThrottleRate to an appropriate value
+for that traffic.
+
+The algorithm classifies the incoming traffic every interval into
+classes.  Once the class is determined, the InterruptThrottleRate value is
+adjusted to suit that traffic type the best. There are three classes defined:
+"Bulk traffic", for large amounts of packets of normal size; "Low latency",
+for small amounts of traffic and/or a significant percentage of small
+packets; and "Lowest latency", for almost completely small packets or
+minimal traffic.
+
+In dynamic conservative mode, the InterruptThrottleRate value is set to 4000
+for traffic that falls in class "Bulk traffic". If traffic falls in the "Low
+latency" or "Lowest latency" class, the InterruptThrottleRate is increased
+stepwise to 20000. This default mode is suitable for most applications.
+
+For situations where low latency is vital such as cluster or
+grid computing, the algorithm can reduce latency even more when
+InterruptThrottleRate is set to mode 1. In this mode, which operates
+the same as mode 3, the InterruptThrottleRate will be increased stepwise to
+70000 for traffic in class "Lowest latency".
+
+In simplified mode the interrupt rate is based on the ratio of Tx and
+Rx traffic.  If the bytes per second rate is approximately equal the
+interrupt rate will drop as low as 2000 interrupts per second.  If the
+traffic is mostly transmit or mostly receive, the interrupt rate could
+be as high as 8000.
+
+Setting InterruptThrottleRate to 0 turns off any interrupt moderation
+and may improve small packet latency, but is generally not suitable
+for bulk throughput traffic.
+
+NOTE:  InterruptThrottleRate takes precedence over the TxAbsIntDelay and
+       RxAbsIntDelay parameters.  In other words, minimizing the receive
+       and/or transmit absolute delays does not force the controller to
+       generate more interrupts than what the Interrupt Throttle Rate
+       allows.
+
+NOTE:  When e1000e is loaded with default settings and multiple adapters
+       are in use simultaneously, the CPU utilization may increase non-
+       linearly.  In order to limit the CPU utilization without impacting
+       the overall throughput, we recommend that you load the driver as
+       follows:
+
+           modprobe e1000e InterruptThrottleRate=3000,3000,3000
+
+       This sets the InterruptThrottleRate to 3000 interrupts/sec for
+       the first, second, and third instances of the driver.  The range
+       of 2000 to 3000 interrupts per second works on a majority of
+       systems and is a good starting point, but the optimal value will
+       be platform-specific.  If CPU utilization is not a concern, use
+       RX_POLLING (NAPI) and default driver settings.
+
+RxIntDelay
+----------
+Valid Range:   0-65535 (0=off)
+Default Value: 0
+
+This value delays the generation of receive interrupts in units of 1.024
+microseconds.  Receive interrupt reduction can improve CPU efficiency if
+properly tuned for specific network traffic.  Increasing this value adds
+extra latency to frame reception and can end up decreasing the throughput
+of TCP traffic.  If the system is reporting dropped receives, this value
+may be set too high, causing the driver to run out of available receive
+descriptors.
+
+CAUTION:  When setting RxIntDelay to a value other than 0, adapters may
+          hang (stop transmitting) under certain network conditions.  If
+          this occurs a NETDEV WATCHDOG message is logged in the system
+          event log.  In addition, the controller is automatically reset,
+          restoring the network connection.  To eliminate the potential
+          for the hang ensure that RxIntDelay is set to 0.
+
+RxAbsIntDelay
+-------------
+Valid Range:   0-65535 (0=off)
+Default Value: 8
+
+This value, in units of 1.024 microseconds, limits the delay in which a
+receive interrupt is generated.  Useful only if RxIntDelay is non-zero,
+this value ensures that an interrupt is generated after the initial
+packet is received within the set amount of time.  Proper tuning,
+along with RxIntDelay, may improve traffic throughput in specific network
+conditions.
+
+TxIntDelay
+----------
+Valid Range:   0-65535 (0=off)
+Default Value: 8
+
+This value delays the generation of transmit interrupts in units of
+1.024 microseconds.  Transmit interrupt reduction can improve CPU
+efficiency if properly tuned for specific network traffic.  If the
+system is reporting dropped transmits, this value may be set too high
+causing the driver to run out of available transmit descriptors.
+
+TxAbsIntDelay
+-------------
+Valid Range:   0-65535 (0=off)
+Default Value: 32
+
+This value, in units of 1.024 microseconds, limits the delay in which a
+transmit interrupt is generated.  Useful only if TxIntDelay is non-zero,
+this value ensures that an interrupt is generated after the initial
+packet is sent on the wire within the set amount of time.  Proper tuning,
+along with TxIntDelay, may improve traffic throughput in specific
+network conditions.
+
+Copybreak
+---------
+Valid Range:   0-xxxxxxx (0=off)
+Default Value: 256
+
+Driver copies all packets below or equaling this size to a fresh Rx
+buffer before handing it up the stack.
+
+This parameter is different than other parameters, in that it is a
+single (not 1,1,1 etc.) parameter applied to all driver instances and
+it is also available during runtime at
+/sys/module/e1000e/parameters/copybreak
+
+SmartPowerDownEnable
+--------------------
+Valid Range: 0-1
+Default Value:  0 (disabled)
+
+Allows PHY to turn off in lower power states. The user can set this parameter
+in supported chipsets.
+
+KumeranLockLoss
+---------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+This workaround skips resetting the PHY at shutdown for the initial
+silicon releases of ICH8 systems.
+
+IntMode
+-------
+Valid Range: 0-2 (0=legacy, 1=MSI, 2=MSI-X)
+Default Value: 2
+
+Allows changing the interrupt mode at module load time, without requiring a
+recompile. If the driver load fails to enable a specific interrupt mode, the
+driver will try other interrupt modes, from least to most compatible.  The
+interrupt order is MSI-X, MSI, Legacy.  If specifying MSI (IntMode=1)
+interrupts, only MSI and Legacy will be attempted.
+
+CrcStripping
+------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+Strip the CRC from received packets before sending up the network stack.  If
+you have a machine with a BMC enabled but cannot receive IPMI traffic after
+loading or enabling the driver, try disabling this feature.
+
+WriteProtectNVM
+---------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+Set the hardware to ignore all write/erase cycles to the GbE region in the
+ICHx NVM (non-volatile memory).  This feature can be disabled by the
+WriteProtectNVM module parameter (enabled by default) only after a hardware
+reset, but the machine must be power cycled before trying to enable writes.
+
+Note: the kernel boot option iomem=relaxed may need to be set if the kernel
+config option CONFIG_STRICT_DEVMEM=y, if the root user wants to write the
+NVM from user space via ethtool.
+
+Additional Configurations
+=========================
+
+  Jumbo Frames
+  ------------
+  Jumbo Frames support is enabled by changing the MTU to a value larger than
+  the default of 1500.  Use the ifconfig command to increase the MTU size.
+  For example:
+
+       ifconfig eth<x> mtu 9000 up
+
+  This setting is not saved across reboots.
+
+  Notes:
+
+  - The maximum MTU setting for Jumbo Frames is 9216.  This value coincides
+    with the maximum Jumbo Frames size of 9234 bytes.
+
+  - Using Jumbo Frames at 10 or 100 Mbps is not supported and may result in
+    poor performance or loss of link.
+
+  - Some adapters limit Jumbo Frames sized packets to a maximum of
+    4096 bytes and some adapters do not support Jumbo Frames.
+
+
+  Ethtool
+  -------
+  The driver utilizes the ethtool interface for driver configuration and
+  diagnostics, as well as displaying statistical information.  We
+  strongly recommend downloading the latest version of Ethtool at:
+
+  http://sourceforge.net/projects/gkernel.
+
+  Speed and Duplex
+  ----------------
+  Speed and Duplex are configured through the Ethtool* utility. For
+  instructions,  refer to the Ethtool man page.
+
+  Enabling Wake on LAN* (WoL)
+  ---------------------------
+  WoL is configured through the Ethtool* utility. For instructions on
+  enabling WoL with Ethtool, refer to the Ethtool man page.
+
+  WoL will be enabled on the system during the next shut down or reboot.
+  For this driver version, in order to enable WoL, the e1000e driver must be
+  loaded when shutting down or rebooting the system.
+
+  In most cases Wake On LAN is only supported on port A for multiple port
+  adapters. To verify if a port supports Wake on LAN run ethtool eth<X>.
+
+
+Support
+=======
+
+For general information, go to the Intel support website at:
+
+    www.intel.com/support/
+
+or the Intel Wired Networking project hosted by Sourceforge at:
+
+    http://sourceforge.net/projects/e1000
+
+If an issue is identified with the released source code on the supported
+kernel with a supported adapter, email the specific information related
+to the issue to e1000-devel@lists.sf.net
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index f350c69..c7165f4 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1014,6 +1014,12 @@
 accept_ra - BOOLEAN
 	Accept Router Advertisements; autoconfigure using them.
 
+	Possible values are:
+		0 Do not accept Router Advertisements.
+		1 Accept Router Advertisements if forwarding is disabled.
+		2 Overrule forwarding behaviour. Accept Router Advertisements
+		  even if forwarding is enabled.
+
 	Functional default: enabled if local forwarding is disabled.
 			    disabled if local forwarding is enabled.
 
@@ -1075,7 +1081,12 @@
 	Note: It is recommended to have the same setting on all
 	interfaces; mixed router/host scenarios are rather uncommon.
 
-	FALSE:
+	Possible values are:
+		0 Forwarding disabled
+		1 Forwarding enabled
+		2 Forwarding enabled (Hybrid Mode)
+
+	FALSE (0):
 
 	By default, Host behaviour is assumed.  This means:
 
@@ -1085,18 +1096,24 @@
 	   Advertisements (and do autoconfiguration).
 	4. If accept_redirects is TRUE (default), accept Redirects.
 
-	TRUE:
+	TRUE (1):
 
 	If local forwarding is enabled, Router behaviour is assumed.
 	This means exactly the reverse from the above:
 
 	1. IsRouter flag is set in Neighbour Advertisements.
 	2. Router Solicitations are not sent.
-	3. Router Advertisements are ignored.
+	3. Router Advertisements are ignored unless accept_ra is 2.
 	4. Redirects are ignored.
 
-	Default: FALSE if global forwarding is disabled (default),
-		 otherwise TRUE.
+	TRUE (2):
+
+	Hybrid mode. Same behaviour as TRUE, except for:
+
+	2. Router Solicitations are being sent when necessary.
+
+	Default: 0 (disabled) if global forwarding is disabled (default),
+		 otherwise 1 (enabled).
 
 hop_limit - INTEGER
 	Default Hop Limit to set.
diff --git a/Documentation/networking/ixgbevf.txt b/Documentation/networking/ixgbevf.txt
old mode 100755
new mode 100644
index 19015de..21dd5d1
--- a/Documentation/networking/ixgbevf.txt
+++ b/Documentation/networking/ixgbevf.txt
@@ -1,19 +1,16 @@
 Linux* Base Driver for Intel(R) Network Connection
 ==================================================
 
-November 24, 2009
+Intel Gigabit Linux driver.
+Copyright(c) 1999 - 2010 Intel Corporation.
 
 Contents
 ========
 
-- In This Release
 - Identifying Your Adapter
 - Known Issues/Troubleshooting
 - Support
 
-In This Release
-===============
-
 This file describes the ixgbevf Linux* Base Driver for Intel Network
 Connection.
 
@@ -33,7 +30,7 @@
 For more information on how to identify your adapter, go to the Adapter &
 Driver ID Guide at:
 
-    http://support.intel.com/support/network/sb/CS-008441.htm
+    http://support.intel.com/support/go/network/adapter/idguide.htm
 
 Known Issues/Troubleshooting
 ============================
@@ -57,34 +54,3 @@
 If an issue is identified with the released source code on the supported
 kernel with a supported adapter, email the specific information related
 to the issue to e1000-devel@lists.sf.net
-
-License
-=======
-
-Intel 10 Gigabit Linux driver.
-Copyright(c) 1999 - 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.
-
-The full GNU General Public License is included in this distribution in
-the file called "COPYING".
-
-Trademarks
-==========
-
-Intel, Itanium, and Pentium are trademarks or registered trademarks of
-Intel Corporation or its subsidiaries in the United States and other
-countries.
-
-* Other names and brands may be claimed as the property of others.
diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt
index 6e8ce09..24ad2ad 100644
--- a/Documentation/networking/phonet.txt
+++ b/Documentation/networking/phonet.txt
@@ -112,6 +112,22 @@
 not seem useful with Phonet usages (could be added easily).
 
 
+Resource subscription
+---------------------
+
+A Phonet datagram socket can be subscribed to any number of 8-bits
+Phonet resources, as follow:
+
+  uint32_t res = 0xXX;
+  ioctl(fd, SIOCPNADDRESOURCE, &res);
+
+Subscription is similarly cancelled using the SIOCPNDELRESOURCE I/O
+control request, or when the socket is closed.
+
+Note that no more than one socket can be subcribed to any given
+resource at a time. If not, ioctl() will return EBUSY.
+
+
 Phonet Pipe protocol
 --------------------
 
@@ -166,6 +182,46 @@
     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
+
+
 Authors
 -------
 
diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt
index e8c8f4f..98097d8 100644
--- a/Documentation/networking/timestamping.txt
+++ b/Documentation/networking/timestamping.txt
@@ -172,15 +172,19 @@
 };
 
 Time stamps for outgoing packets are to be generated as follows:
-- In hard_start_xmit(), check if skb_tx(skb)->hardware is set no-zero.
-  If yes, then the driver is expected to do hardware time stamping.
+- In hard_start_xmit(), check if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
+  is set no-zero. If yes, then the driver is expected to do hardware time
+  stamping.
 - If this is possible for the skb and requested, then declare
-  that the driver is doing the time stamping by setting the field
-  skb_tx(skb)->in_progress non-zero. You might want to keep a pointer
-  to the associated skb for the next step and not free the skb. A driver
-  not supporting hardware time stamping doesn't do that. A driver must
-  never touch sk_buff::tstamp! It is used to store software generated
-  time stamps by the network subsystem.
+  that the driver is doing the time stamping by setting the flag
+  SKBTX_IN_PROGRESS in skb_shinfo(skb)->tx_flags , e.g. with
+
+      skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+  You might want to keep a pointer to the associated skb for the next step
+  and not free the skb. A driver not supporting hardware time stamping doesn't
+  do that. A driver must never touch sk_buff::tstamp! It is used to store
+  software generated time stamps by the network subsystem.
 - As soon as the driver has sent the packet and/or obtained a
   hardware time stamp for it, it passes the time stamp back by
   calling skb_hwtstamp_tx() with the original skb, the raw
@@ -191,6 +195,6 @@
   this would occur at a later time in the processing pipeline than other
   software time stamping and therefore could lead to unexpected deltas
   between time stamps.
-- If the driver did not call set skb_tx(skb)->in_progress, then
+- If the driver did not set the SKBTX_IN_PROGRESS flag (see above), then
   dev_hard_start_xmit() checks whether software time stamping
   is wanted as fallback and potentially generates the time stamp.
diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 26c0f9c..dd04361 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,4 +1,29 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
+* pcmcia_loop_config() and autoconfiguration (as of 2.6.36)
+   If struct pcmcia_device *p_dev->config_flags is set accordingly,
+   pcmcia_loop_config() now sets up certain configuration values
+   automatically, though the driver may still override the settings
+   in the callback function. The following autoconfiguration options
+   are provided at the moment:
+	CONF_AUTO_CHECK_VCC : check for matching Vcc
+	CONF_AUTO_SET_VPP   : set Vpp
+	CONF_AUTO_AUDIO     : auto-enable audio line, if required
+	CONF_AUTO_SET_IO    : set ioport resources (->resource[0,1])
+	CONF_AUTO_SET_IOMEM : set first iomem resource (->resource[2])
+
+* pcmcia_request_configuration -> pcmcia_enable_device (as of 2.6.36)
+   pcmcia_request_configuration() got renamed to pcmcia_enable_device(),
+   as it mirrors pcmcia_disable_device(). Configuration settings are now
+   stored in struct pcmcia_device, e.g. in the fields config_flags,
+   config_index, config_base, vpp.
+
+* pcmcia_request_window changes (as of 2.6.36)
+   Instead of win_req_t, drivers are now requested to fill out
+   struct pcmcia_device *p_dev->resource[2,3,4,5] for up to four ioport
+   ranges. After a call to pcmcia_request_window(), the regions found there
+   are reserved and may be used immediately -- until pcmcia_release_window()
+   is called.
+
 * pcmcia_request_io changes (as of 2.6.36)
    Instead of io_req_t, drivers are now requested to fill out
    struct pcmcia_device *p_dev->resource[0,1] for up to two ioport
diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX
index fb742c2..45e9d4a 100644
--- a/Documentation/power/00-INDEX
+++ b/Documentation/power/00-INDEX
@@ -14,6 +14,8 @@
 	- Power management user interface in /sys/power
 notifiers.txt
 	- Registering suspend notifiers in device drivers
+opp.txt
+	- Operating Performance Point library
 pci.txt
 	- How the PCI Subsystem Does Power Management
 pm_qos_interface.txt
diff --git a/Documentation/power/interface.txt b/Documentation/power/interface.txt
index e67211f..c537834 100644
--- a/Documentation/power/interface.txt
+++ b/Documentation/power/interface.txt
@@ -57,7 +57,7 @@
 suspend image will be as small as possible.
 
 Reading from this file will display the current image size limit, which
-is set to 500 MB by default.
+is set to 2/5 of available RAM by default.
 
 /sys/power/pm_trace controls the code which saves the last PM event point in
 the RTC across reboots, so that you can debug a machine that just hangs
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
new file mode 100644
index 0000000..44d87ad
--- /dev/null
+++ b/Documentation/power/opp.txt
@@ -0,0 +1,375 @@
+*=============*
+* OPP Library *
+*=============*
+
+(C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated
+
+Contents
+--------
+1. Introduction
+2. Initial OPP List Registration
+3. OPP Search Functions
+4. OPP Availability Control Functions
+5. OPP Data Retrieval Functions
+6. Cpufreq Table Generation
+7. Data Structures
+
+1. Introduction
+===============
+Complex SoCs of today consists of a multiple sub-modules working in conjunction.
+In an operational system executing varied use cases, not all modules in the SoC
+need to function at their highest performing frequency all the time. To
+facilitate this, sub-modules in a SoC are grouped into domains, allowing some
+domains to run at lower voltage and frequency while other domains are loaded
+more. The set of discrete tuples consisting of frequency and voltage pairs that
+the device will support per domain are called Operating Performance Points or
+OPPs.
+
+OPP library provides a set of helper functions to organize and query the OPP
+information. The library is located in drivers/base/power/opp.c and the header
+is located in include/linux/opp.h. OPP library can be enabled by enabling
+CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on
+CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to
+optionally boot at a certain OPP without needing cpufreq.
+
+Typical usage of the OPP library is as follows:
+(users)		-> registers a set of default OPPs		-> (library)
+SoC framework	-> modifies on required cases certain OPPs	-> OPP layer
+		-> queries to search/retrieve information	->
+
+OPP layer expects each domain to be represented by a unique device pointer. SoC
+framework registers a set of initial OPPs per device with the OPP layer. This
+list is expected to be an optimally small number typically around 5 per device.
+This initial list contains a set of OPPs that the framework expects to be safely
+enabled by default in the system.
+
+Note on OPP Availability:
+------------------------
+As the system proceeds to operate, SoC framework may choose to make certain
+OPPs available or not available on each device based on various external
+factors. Example usage: Thermal management or other exceptional situations where
+SoC framework might choose to disable a higher frequency OPP to safely continue
+operations until that OPP could be re-enabled if possible.
+
+OPP library facilitates this concept in it's implementation. The following
+operational functions operate only on available opps:
+opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count
+and opp_init_cpufreq_table
+
+opp_find_freq_exact is meant to be used to find the opp pointer which can then
+be used for opp_enable/disable functions to make an opp available as required.
+
+WARNING: Users of OPP library should refresh their availability count using
+get_opp_count if opp_enable/disable functions are invoked for a device, the
+exact mechanism to trigger these or the notification mechanism to other
+dependent subsystems such as cpufreq are left to the discretion of the SoC
+specific framework which uses the OPP library. Similar care needs to be taken
+care to refresh the cpufreq table in cases of these operations.
+
+WARNING on OPP List locking mechanism:
+-------------------------------------------------
+OPP library uses RCU for exclusivity. RCU allows the query functions to operate
+in multiple contexts and this synchronization mechanism is optimal for a read
+intensive operations on data structure as the OPP library caters to.
+
+To ensure that the data retrieved are sane, the users such as SoC framework
+should ensure that the section of code operating on OPP queries are locked
+using RCU read locks. The opp_find_freq_{exact,ceil,floor},
+opp_get_{voltage, freq, opp_count} fall into this category.
+
+opp_{add,enable,disable} are updaters which use mutex and implement it's own
+RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses
+mutex to implment RCU updater strategy. These functions should *NOT* be called
+under RCU locks and other contexts that prevent blocking functions in RCU or
+mutex operations from working.
+
+2. Initial OPP List Registration
+================================
+The SoC implementation calls opp_add function iteratively to add OPPs per
+device. It is expected that the SoC framework will register the OPP entries
+optimally- typical numbers range to be less than 5. The list generated by
+registering the OPPs is maintained by OPP library throughout the device
+operation. The SoC framework can subsequently control the availability of the
+OPPs dynamically using the opp_enable / disable functions.
+
+opp_add - Add a new OPP for a specific domain represented by the device pointer.
+	The OPP is defined using the frequency and voltage. Once added, the OPP
+	is assumed to be available and control of it's availability can be done
+	with the opp_enable/disable functions. OPP library internally stores
+	and manages this information in the opp struct. This function may be
+	used by SoC framework to define a optimal list as per the demands of
+	SoC usage environment.
+
+	WARNING: Do not use this function in interrupt context.
+
+	Example:
+	 soc_pm_init()
+	 {
+		/* Do things */
+		r = opp_add(mpu_dev, 1000000, 900000);
+		if (!r) {
+			pr_err("%s: unable to register mpu opp(%d)\n", r);
+			goto no_cpufreq;
+		}
+		/* Do cpufreq things */
+	 no_cpufreq:
+		/* Do remaining things */
+	 }
+
+3. OPP Search Functions
+=======================
+High level framework such as cpufreq operates on frequencies. To map the
+frequency back to the corresponding OPP, OPP library provides handy functions
+to search the OPP list that OPP library internally manages. These search
+functions return the matching pointer representing the opp if a match is
+found, else returns error. These errors are expected to be handled by standard
+error checks such as IS_ERR() and appropriate actions taken by the caller.
+
+opp_find_freq_exact - Search for an OPP based on an *exact* frequency and
+	availability. This function is especially useful to enable an OPP which
+	is not available by default.
+	Example: In a case when SoC framework detects a situation where a
+	higher frequency could be made available, it can use this function to
+	find the OPP prior to call the opp_enable to actually make it available.
+	 rcu_read_lock();
+	 opp = opp_find_freq_exact(dev, 1000000000, false);
+	 rcu_read_unlock();
+	 /* dont operate on the pointer.. just do a sanity check.. */
+	 if (IS_ERR(opp)) {
+		pr_err("frequency not disabled!\n");
+		/* trigger appropriate actions.. */
+	 } else {
+		opp_enable(dev,1000000000);
+	 }
+
+	NOTE: This is the only search function that operates on OPPs which are
+	not available.
+
+opp_find_freq_floor - Search for an available OPP which is *at most* the
+	provided frequency. This function is useful while searching for a lesser
+	match OR operating on OPP information in the order of decreasing
+	frequency.
+	Example: To find the highest opp for a device:
+	 freq = ULONG_MAX;
+	 rcu_read_lock();
+	 opp_find_freq_floor(dev, &freq);
+	 rcu_read_unlock();
+
+opp_find_freq_ceil - Search for an available OPP which is *at least* the
+	provided frequency. This function is useful while searching for a
+	higher match OR operating on OPP information in the order of increasing
+	frequency.
+	Example 1: To find the lowest opp for a device:
+	 freq = 0;
+	 rcu_read_lock();
+	 opp_find_freq_ceil(dev, &freq);
+	 rcu_read_unlock();
+	Example 2: A simplified implementation of a SoC cpufreq_driver->target:
+	 soc_cpufreq_target(..)
+	 {
+		/* Do stuff like policy checks etc. */
+		/* Find the best frequency match for the req */
+		rcu_read_lock();
+		opp = opp_find_freq_ceil(dev, &freq);
+		rcu_read_unlock();
+		if (!IS_ERR(opp))
+			soc_switch_to_freq_voltage(freq);
+		else
+			/* do something when we cant satisfy the req */
+		/* do other stuff */
+	 }
+
+4. OPP Availability Control Functions
+=====================================
+A default OPP list registered with the OPP library may not cater to all possible
+situation. The OPP library provides a set of functions to modify the
+availability of a OPP within the OPP list. This allows SoC frameworks to have
+fine grained dynamic control of which sets of OPPs are operationally available.
+These functions are intended to *temporarily* remove an OPP in conditions such
+as thermal considerations (e.g. don't use OPPx until the temperature drops).
+
+WARNING: Do not use these functions in interrupt context.
+
+opp_enable - Make a OPP available for operation.
+	Example: Lets say that 1GHz OPP is to be made available only if the
+	SoC temperature is lower than a certain threshold. The SoC framework
+	implementation might choose to do something as follows:
+	 if (cur_temp < temp_low_thresh) {
+		/* Enable 1GHz if it was disabled */
+		rcu_read_lock();
+		opp = opp_find_freq_exact(dev, 1000000000, false);
+		rcu_read_unlock();
+		/* just error check */
+		if (!IS_ERR(opp))
+			ret = opp_enable(dev, 1000000000);
+		else
+			goto try_something_else;
+	 }
+
+opp_disable - Make an OPP to be not available for operation
+	Example: Lets say that 1GHz OPP is to be disabled if the temperature
+	exceeds a threshold value. The SoC framework implementation might
+	choose to do something as follows:
+	 if (cur_temp > temp_high_thresh) {
+		/* Disable 1GHz if it was enabled */
+		rcu_read_lock();
+		opp = opp_find_freq_exact(dev, 1000000000, true);
+		rcu_read_unlock();
+		/* just error check */
+		if (!IS_ERR(opp))
+			ret = opp_disable(dev, 1000000000);
+		else
+			goto try_something_else;
+	 }
+
+5. OPP Data Retrieval Functions
+===============================
+Since OPP library abstracts away the OPP information, a set of functions to pull
+information from the OPP structure is necessary. Once an OPP pointer is
+retrieved using the search functions, the following functions can be used by SoC
+framework to retrieve the information represented inside the OPP layer.
+
+opp_get_voltage - Retrieve the voltage represented by the opp pointer.
+	Example: At a cpufreq transition to a different frequency, SoC
+	framework requires to set the voltage represented by the OPP using
+	the regulator framework to the Power Management chip providing the
+	voltage.
+	 soc_switch_to_freq_voltage(freq)
+	 {
+		/* do things */
+		rcu_read_lock();
+		opp = opp_find_freq_ceil(dev, &freq);
+		v = opp_get_voltage(opp);
+		rcu_read_unlock();
+		if (v)
+			regulator_set_voltage(.., v);
+		/* do other things */
+	 }
+
+opp_get_freq - Retrieve the freq represented by the opp pointer.
+	Example: Lets say the SoC framework uses a couple of helper functions
+	we could pass opp pointers instead of doing additional parameters to
+	handle quiet a bit of data parameters.
+	 soc_cpufreq_target(..)
+	 {
+		/* do things.. */
+		 max_freq = ULONG_MAX;
+		 rcu_read_lock();
+		 max_opp = opp_find_freq_floor(dev,&max_freq);
+		 requested_opp = opp_find_freq_ceil(dev,&freq);
+		 if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
+			r = soc_test_validity(max_opp, requested_opp);
+		 rcu_read_unlock();
+		/* do other things */
+	 }
+	 soc_test_validity(..)
+	 {
+		 if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp))
+			 return -EINVAL;
+		 if(opp_get_freq(max_opp) < opp_get_freq(requested_opp))
+			 return -EINVAL;
+		/* do things.. */
+	 }
+
+opp_get_opp_count - Retrieve the number of available opps for a device
+	Example: Lets say a co-processor in the SoC needs to know the available
+	frequencies in a table, the main processor can notify as following:
+	 soc_notify_coproc_available_frequencies()
+	 {
+		/* Do things */
+		rcu_read_lock();
+		num_available = opp_get_opp_count(dev);
+		speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL);
+		/* populate the table in increasing order */
+		freq = 0;
+		while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) {
+			speeds[i] = freq;
+			freq++;
+			i++;
+		}
+		rcu_read_unlock();
+
+		soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available);
+		/* Do other things */
+	 }
+
+6. Cpufreq Table Generation
+===========================
+opp_init_cpufreq_table - cpufreq framework typically is initialized with
+	cpufreq_frequency_table_cpuinfo which is provided with the list of
+	frequencies that are available for operation. This function provides
+	a ready to use conversion routine to translate the OPP layer's internal
+	information about the available frequencies into a format readily
+	providable to cpufreq.
+
+	WARNING: Do not use this function in interrupt context.
+
+	Example:
+	 soc_pm_init()
+	 {
+		/* Do things */
+		r = opp_init_cpufreq_table(dev, &freq_table);
+		if (!r)
+			cpufreq_frequency_table_cpuinfo(policy, freq_table);
+		/* Do other things */
+	 }
+
+	NOTE: This function is available only if CONFIG_CPU_FREQ is enabled in
+	addition to CONFIG_PM as power management feature is required to
+	dynamically scale voltage and frequency in a system.
+
+7. Data Structures
+==================
+Typically an SoC contains multiple voltage domains which are variable. Each
+domain is represented by a device pointer. The relationship to OPP can be
+represented as follows:
+SoC
+ |- device 1
+ |	|- opp 1 (availability, freq, voltage)
+ |	|- opp 2 ..
+ ...	...
+ |	`- opp n ..
+ |- device 2
+ ...
+ `- device m
+
+OPP library maintains a internal list that the SoC framework populates and
+accessed by various functions as described above. However, the structures
+representing the actual OPPs and domains are internal to the OPP library itself
+to allow for suitable abstraction reusable across systems.
+
+struct opp - The internal data structure of OPP library which is used to
+	represent an OPP. In addition to the freq, voltage, availability
+	information, it also contains internal book keeping information required
+	for the OPP library to operate on.  Pointer to this structure is
+	provided back to the users such as SoC framework to be used as a
+	identifier for OPP in the interactions with OPP layer.
+
+	WARNING: The struct opp pointer should not be parsed or modified by the
+	users. The defaults of for an instance is populated by opp_add, but the
+	availability of the OPP can be modified by opp_enable/disable functions.
+
+struct device - This is used to identify a domain to the OPP layer. The
+	nature of the device and it's implementation is left to the user of
+	OPP library such as the SoC framework.
+
+Overall, in a simplistic view, the data structure operations is represented as
+following:
+
+Initialization / modification:
+            +-----+        /- opp_enable
+opp_add --> | opp | <-------
+  |         +-----+        \- opp_disable
+  \-------> domain_info(device)
+
+Search functions:
+             /-- opp_find_freq_ceil  ---\   +-----+
+domain_info<---- opp_find_freq_exact -----> | opp |
+             \-- opp_find_freq_floor ---/   +-----+
+
+Retrieval functions:
++-----+     /- opp_get_voltage
+| opp | <---
++-----+     \- opp_get_freq
+
+domain_info <- opp_get_opp_count
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index 55b859b..489e9ba 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -1,6 +1,7 @@
 Run-time Power Management Framework for I/O Devices
 
 (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+(C) 2010 Alan Stern <stern@rowland.harvard.edu>
 
 1. Introduction
 
@@ -157,7 +158,8 @@
     to execute it, the other callbacks will not be executed for the same device.
 
   * A request to execute ->runtime_resume() will cancel any pending or
-    scheduled requests to execute the other callbacks for the same device.
+    scheduled requests to execute the other callbacks for the same device,
+    except for scheduled autosuspends.
 
 3. Run-time PM Device Fields
 
@@ -165,7 +167,7 @@
 defined in include/linux/pm.h:
 
   struct timer_list suspend_timer;
-    - timer used for scheduling (delayed) suspend request
+    - timer used for scheduling (delayed) suspend and autosuspend requests
 
   unsigned long timer_expires;
     - timer expiration time, in jiffies (if this is different from zero, the
@@ -230,6 +232,28 @@
       interface; it may only be modified with the help of the pm_runtime_allow()
       and pm_runtime_forbid() helper functions
 
+  unsigned int no_callbacks;
+    - indicates that the device does not use the run-time PM callbacks (see
+      Section 8); it may be modified only by the pm_runtime_no_callbacks()
+      helper function
+
+  unsigned int use_autosuspend;
+    - indicates that the device's driver supports delayed autosuspend (see
+      Section 9); it may be modified only by the
+      pm_runtime{_dont}_use_autosuspend() helper functions
+
+  unsigned int timer_autosuspends;
+    - indicates that the PM core should attempt to carry out an autosuspend
+      when the timer expires rather than a normal suspend
+
+  int autosuspend_delay;
+    - the delay time (in milliseconds) to be used for autosuspend
+
+  unsigned long last_busy;
+    - the time (in jiffies) when the pm_runtime_mark_last_busy() helper
+      function was last called for this device; used in calculating inactivity
+      periods for autosuspend
+
 All of the above fields are members of the 'power' member of 'struct device'.
 
 4. Run-time PM Device Helper Functions
@@ -255,6 +279,12 @@
       error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt
       to suspend the device again in future
 
+  int pm_runtime_autosuspend(struct device *dev);
+    - same as pm_runtime_suspend() except that the autosuspend delay is taken
+      into account; if pm_runtime_autosuspend_expiration() says the delay has
+      not yet expired then an autosuspend is scheduled for the appropriate time
+      and 0 is returned
+
   int pm_runtime_resume(struct device *dev);
     - execute the subsystem-level resume callback for the device; returns 0 on
       success, 1 if the device's run-time PM status was already 'active' or
@@ -267,6 +297,11 @@
       device (the request is represented by a work item in pm_wq); returns 0 on
       success or error code if the request has not been queued up
 
+  int pm_request_autosuspend(struct device *dev);
+    - schedule the execution of the subsystem-level suspend callback for the
+      device when the autosuspend delay has expired; if the delay has already
+      expired then the work item is queued up immediately
+
   int pm_schedule_suspend(struct device *dev, unsigned int delay);
     - schedule the execution of the subsystem-level suspend callback for the
       device in future, where 'delay' is the time to wait before queuing up a
@@ -298,12 +333,20 @@
     - decrement the device's usage counter
 
   int pm_runtime_put(struct device *dev);
-    - decrement the device's usage counter, run pm_request_idle(dev) and return
-      its result
+    - decrement the device's usage counter; if the result is 0 then run
+      pm_request_idle(dev) and return its result
+
+  int pm_runtime_put_autosuspend(struct device *dev);
+    - decrement the device's usage counter; if the result is 0 then run
+      pm_request_autosuspend(dev) and return its result
 
   int pm_runtime_put_sync(struct device *dev);
-    - decrement the device's usage counter, run pm_runtime_idle(dev) and return
-      its result
+    - decrement the device's usage counter; if the result is 0 then run
+      pm_runtime_idle(dev) and return its result
+
+  int pm_runtime_put_sync_autosuspend(struct device *dev);
+    - decrement the device's usage counter; if the result is 0 then run
+      pm_runtime_autosuspend(dev) and return its result
 
   void pm_runtime_enable(struct device *dev);
     - enable the run-time PM helper functions to run the device bus type's
@@ -349,19 +392,51 @@
       counter (used by the /sys/devices/.../power/control interface to
       effectively prevent the device from being power managed at run time)
 
+  void pm_runtime_no_callbacks(struct device *dev);
+    - set the power.no_callbacks flag for the device and remove the run-time
+      PM attributes from /sys/devices/.../power (or prevent them from being
+      added when the device is registered)
+
+  void pm_runtime_mark_last_busy(struct device *dev);
+    - set the power.last_busy field to the current time
+
+  void pm_runtime_use_autosuspend(struct device *dev);
+    - set the power.use_autosuspend flag, enabling autosuspend delays
+
+  void pm_runtime_dont_use_autosuspend(struct device *dev);
+    - clear the power.use_autosuspend flag, disabling autosuspend delays
+
+  void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
+    - set the power.autosuspend_delay value to 'delay' (expressed in
+      milliseconds); if 'delay' is negative then run-time suspends are
+      prevented
+
+  unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
+    - calculate the time when the current autosuspend delay period will expire,
+      based on power.last_busy and power.autosuspend_delay; if the delay time
+      is 1000 ms or larger then the expiration time is rounded up to the
+      nearest second; returns 0 if the delay period has already expired or
+      power.use_autosuspend isn't set, otherwise returns the expiration time
+      in jiffies
+
 It is safe to execute the following helper functions from interrupt context:
 
 pm_request_idle()
+pm_request_autosuspend()
 pm_schedule_suspend()
 pm_request_resume()
 pm_runtime_get_noresume()
 pm_runtime_get()
 pm_runtime_put_noidle()
 pm_runtime_put()
+pm_runtime_put_autosuspend()
+pm_runtime_enable()
 pm_suspend_ignore_children()
 pm_runtime_set_active()
 pm_runtime_set_suspended()
-pm_runtime_enable()
+pm_runtime_suspended()
+pm_runtime_mark_last_busy()
+pm_runtime_autosuspend_expiration()
 
 5. Run-time PM Initialization, Device Probing and Removal
 
@@ -524,3 +599,141 @@
 restore, and run-time resume, can achieve this with the help of the
 UNIVERSAL_DEV_PM_OPS macro defined in include/linux/pm.h (possibly setting its
 last argument to NULL).
+
+8. "No-Callback" Devices
+
+Some "devices" are only logical sub-devices of their parent and cannot be
+power-managed on their own.  (The prototype example is a USB interface.  Entire
+USB devices can go into low-power mode or send wake-up requests, but neither is
+possible for individual interfaces.)  The drivers for these devices have no
+need of run-time PM callbacks; if the callbacks did exist, ->runtime_suspend()
+and ->runtime_resume() would always return 0 without doing anything else and
+->runtime_idle() would always call pm_runtime_suspend().
+
+Subsystems can tell the PM core about these devices by calling
+pm_runtime_no_callbacks().  This should be done after the device structure is
+initialized and before it is registered (although after device registration is
+also okay).  The routine will set the device's power.no_callbacks flag and
+prevent the non-debugging run-time PM sysfs attributes from being created.
+
+When power.no_callbacks is set, the PM core will not invoke the
+->runtime_idle(), ->runtime_suspend(), or ->runtime_resume() callbacks.
+Instead it will assume that suspends and resumes always succeed and that idle
+devices should be suspended.
+
+As a consequence, the PM core will never directly inform the device's subsystem
+or driver about run-time power changes.  Instead, the driver for the device's
+parent must take responsibility for telling the device's driver when the
+parent's power state changes.
+
+9. Autosuspend, or automatically-delayed suspends
+
+Changing a device's power state isn't free; it requires both time and energy.
+A device should be put in a low-power state only when there's some reason to
+think it will remain in that state for a substantial time.  A common heuristic
+says that a device which hasn't been used for a while is liable to remain
+unused; following this advice, drivers should not allow devices to be suspended
+at run-time until they have been inactive for some minimum period.  Even when
+the heuristic ends up being non-optimal, it will still prevent devices from
+"bouncing" too rapidly between low-power and full-power states.
+
+The term "autosuspend" is an historical remnant.  It doesn't mean that the
+device is automatically suspended (the subsystem or driver still has to call
+the appropriate PM routines); rather it means that run-time suspends will
+automatically be delayed until the desired period of inactivity has elapsed.
+
+Inactivity is determined based on the power.last_busy field.  Drivers should
+call pm_runtime_mark_last_busy() to update this field after carrying out I/O,
+typically just before calling pm_runtime_put_autosuspend().  The desired length
+of the inactivity period is a matter of policy.  Subsystems can set this length
+initially by calling pm_runtime_set_autosuspend_delay(), but after device
+registration the length should be controlled by user space, using the
+/sys/devices/.../power/autosuspend_delay_ms attribute.
+
+In order to use autosuspend, subsystems or drivers must call
+pm_runtime_use_autosuspend() (preferably before registering the device), and
+thereafter they should use the various *_autosuspend() helper functions instead
+of the non-autosuspend counterparts:
+
+	Instead of: pm_runtime_suspend    use: pm_runtime_autosuspend;
+	Instead of: pm_schedule_suspend   use: pm_request_autosuspend;
+	Instead of: pm_runtime_put        use: pm_runtime_put_autosuspend;
+	Instead of: pm_runtime_put_sync   use: pm_runtime_put_sync_autosuspend.
+
+Drivers may also continue to use the non-autosuspend helper functions; they
+will behave normally, not taking the autosuspend delay into account.
+Similarly, if the power.use_autosuspend field isn't set then the autosuspend
+helper functions will behave just like the non-autosuspend counterparts.
+
+The implementation is well suited for asynchronous use in interrupt contexts.
+However such use inevitably involves races, because the PM core can't
+synchronize ->runtime_suspend() callbacks with the arrival of I/O requests.
+This synchronization must be handled by the driver, using its private lock.
+Here is a schematic pseudo-code example:
+
+	foo_read_or_write(struct foo_priv *foo, void *data)
+	{
+		lock(&foo->private_lock);
+		add_request_to_io_queue(foo, data);
+		if (foo->num_pending_requests++ == 0)
+			pm_runtime_get(&foo->dev);
+		if (!foo->is_suspended)
+			foo_process_next_request(foo);
+		unlock(&foo->private_lock);
+	}
+
+	foo_io_completion(struct foo_priv *foo, void *req)
+	{
+		lock(&foo->private_lock);
+		if (--foo->num_pending_requests == 0) {
+			pm_runtime_mark_last_busy(&foo->dev);
+			pm_runtime_put_autosuspend(&foo->dev);
+		} else {
+			foo_process_next_request(foo);
+		}
+		unlock(&foo->private_lock);
+		/* Send req result back to the user ... */
+	}
+
+	int foo_runtime_suspend(struct device *dev)
+	{
+		struct foo_priv foo = container_of(dev, ...);
+		int ret = 0;
+
+		lock(&foo->private_lock);
+		if (foo->num_pending_requests > 0) {
+			ret = -EBUSY;
+		} else {
+			/* ... suspend the device ... */
+			foo->is_suspended = 1;
+		}
+		unlock(&foo->private_lock);
+		return ret;
+	}
+
+	int foo_runtime_resume(struct device *dev)
+	{
+		struct foo_priv foo = container_of(dev, ...);
+
+		lock(&foo->private_lock);
+		/* ... resume the device ... */
+		foo->is_suspended = 0;
+		pm_runtime_mark_last_busy(&foo->dev);
+		if (foo->num_pending_requests > 0)
+			foo_process_requests(foo);
+		unlock(&foo->private_lock);
+		return 0;
+	}
+
+The important point is that after foo_io_completion() asks for an autosuspend,
+the foo_runtime_suspend() callback may race with foo_read_or_write().
+Therefore foo_runtime_suspend() has to check whether there are any pending I/O
+requests (while holding the private lock) before allowing the suspend to
+proceed.
+
+In addition, the power.autosuspend_delay field can be changed by user space at
+any time.  If a driver cares about this, it can call
+pm_runtime_autosuspend_expiration() from within the ->runtime_suspend()
+callback while holding its private lock.  If the function returns a nonzero
+value then the delay has not yet expired and the callback should return
+-EAGAIN.
diff --git a/Documentation/power/s2ram.txt b/Documentation/power/s2ram.txt
index 514b94f..1bdfa04 100644
--- a/Documentation/power/s2ram.txt
+++ b/Documentation/power/s2ram.txt
@@ -49,6 +49,13 @@
    device (lspci and /sys/devices/pci* is your friend), and see if you can
    fix it, disable it, or trace into its resume function.
 
+   If no device matches the hash (or any matches appear to be false positives),
+   the culprit may be a device from a loadable kernel module that is not loaded
+   until after the hash is checked. You can check the hash against the current
+   devices again after more modules are loaded using sysfs:
+
+	cat /sys/power/pm_trace_dev_match
+
 For example, the above happens to be the VGA device on my EVO, which I
 used to run with "radeonfb" (it's an ATI Radeon mobility). It turns out
 that "radeonfb" simply cannot resume that device - it tries to set the
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 9d60ab7..ea71889 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -66,7 +66,8 @@
 powerdowns.  You must explicitly specify the swap partition to resume from with
 ``resume='' kernel option. If signature is found it loads and restores saved
 state. If the option ``noresume'' is specified as a boot parameter, it skips
-the resuming.
+the resuming.  If the option ``hibernate=nocompress'' is specified as a boot
+parameter, it saves hibernation image without compression.
 
 In the meantime while the system is suspended you should not add/remove any
 of the hardware, write to the filesystems, etc.
diff --git a/Documentation/powerpc/dts-bindings/fsl/spi.txt b/Documentation/powerpc/dts-bindings/fsl/spi.txt
index 80510c0..777abd7 100644
--- a/Documentation/powerpc/dts-bindings/fsl/spi.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/spi.txt
@@ -1,7 +1,9 @@
 * SPI (Serial Peripheral Interface)
 
 Required properties:
-- cell-index : SPI controller index.
+- cell-index : QE SPI subblock index.
+		0: QE subblock SPI1
+		1: QE subblock SPI2
 - compatible : should be "fsl,spi".
 - mode : the SPI operation mode, it can be "cpu" or "cpu-qe".
 - reg : Offset and length of the register set for the device
@@ -29,3 +31,23 @@
 		gpios = <&gpio 18 1	// device reg=<0>
 			 &gpio 19 1>;	// device reg=<1>
 	};
+
+
+* eSPI (Enhanced Serial Peripheral Interface)
+
+Required properties:
+- compatible : should be "fsl,mpc8536-espi".
+- reg : Offset and length of the register set for the device.
+- interrupts : should contain eSPI interrupt, the device has one interrupt.
+- fsl,espi-num-chipselects : the number of the chipselect signals.
+
+Example:
+	spi@110000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mpc8536-espi";
+		reg = <0x110000 0x1000>;
+		interrupts = <53 0x2>;
+		interrupt-parent = <&mpic>;
+		fsl,espi-num-chipselects = <4>;
+	};
diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentation/powerpc/dts-bindings/fsl/usb.txt
index b001524..bd5723f 100644
--- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
@@ -8,6 +8,7 @@
 Required properties :
  - compatible : Should be "fsl-usb2-mph" for multi port host USB
    controllers, or "fsl-usb2-dr" for dual role USB controllers
+   or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121
  - phy_type : For multi port host USB controllers, should be one of
    "ulpi", or "serial". For dual role USB controllers, should be
    one of "ulpi", "utmi", "utmi_wide", or "serial".
@@ -33,6 +34,12 @@
  - interrupt-parent : the phandle for the interrupt controller that
    services interrupts for this device.
 
+Optional properties :
+ - fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the
+   port power polarity of internal PHY signal DRVVBUS is inverted.
+ - fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates
+   the PWR_FAULT signal polarity is inverted.
+
 Example multi port host USB controller device node :
 	usb@22000 {
 		compatible = "fsl-usb2-mph";
@@ -57,3 +64,18 @@
 		dr_mode = "otg";
 		phy = "ulpi";
 	};
+
+Example dual role USB controller device node for MPC5121ADS:
+
+	usb@4000 {
+		compatible = "fsl,mpc5121-usb2-dr";
+		reg = <0x4000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-parent = < &ipic >;
+		interrupts = <44 0x8>;
+		dr_mode = "otg";
+		phy_type = "utmi_wide";
+		fsl,invert-drvvbus;
+		fsl,invert-pwr-fault;
+	};
diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt
index 4075260..691ca29 100644
--- a/Documentation/scsi/st.txt
+++ b/Documentation/scsi/st.txt
@@ -2,7 +2,7 @@
 The driver is currently maintained by Kai Mäkisara (email
 Kai.Makisara@kolumbus.fi)
 
-Last modified: Sun Feb 24 21:59:07 2008 by kai.makisara
+Last modified: Sun Aug 29 18:25:47 2010 by kai.makisara
 
 
 BASICS
@@ -85,6 +85,17 @@
 optionally written. In both cases end of data is signified by
 returning zero bytes for two consecutive reads.
 
+Writing filemarks without the immediate bit set in the SCSI command block acts
+as a synchronization point, i.e., all remaining data form the drive buffers is
+written to tape before the command returns. This makes sure that write errors
+are caught at that point, but this takes time. In some applications, several
+consecutive files must be written fast. The MTWEOFI operation can be used to
+write the filemarks without flushing the drive buffer. Writing filemark at
+close() is always flushing the drive buffers. However, if the previous
+operation is MTWEOFI, close() does not write a filemark. This can be used if
+the program wants to close/open the tape device between files and wants to
+skip waiting.
+
 If rewind, offline, bsf, or seek is done and previous tape operation was
 write, a filemark is written before moving tape.
 
@@ -301,6 +312,8 @@
 MTFSS   Space forward over count setmarks.
 MTBSS   Space backward over count setmarks.
 MTWEOF  Write count filemarks.
+MTWEOFI	Write count filemarks with immediate bit set (i.e., does not
+	wait until data is on tape)
 MTWSM   Write count setmarks.
 MTREW   Rewind tape.
 MTOFFL  Set device off line (often rewind plus eject).
diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt
index fafcd47..afe596d 100644
--- a/Documentation/usb/proc_usb_info.txt
+++ b/Documentation/usb/proc_usb_info.txt
@@ -1,12 +1,17 @@
 /proc/bus/usb filesystem output
 ===============================
-(version 2003.05.30)
+(version 2010.09.13)
 
 
 The usbfs filesystem for USB devices is traditionally mounted at
 /proc/bus/usb.  It provides the /proc/bus/usb/devices file, as well as
 the /proc/bus/usb/BBB/DDD files.
 
+In many modern systems the usbfs filsystem isn't used at all.  Instead
+USB device nodes are created under /dev/usb/ or someplace similar.  The
+"devices" file is available in debugfs, typically as
+/sys/kernel/debug/usb/devices.
+
 
 **NOTE**: If /proc/bus/usb appears empty, and a host controller
 	  driver has been linked, then you need to mount the
@@ -106,8 +111,8 @@
 
 Topology info:
 
-T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
-|   |      |      |       |       |      |        |       |__MaxChildren
+T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd
+|   |      |      |       |       |      |        |        |__MaxChildren
 |   |      |      |       |       |      |        |__Device Speed in Mbps
 |   |      |      |       |       |      |__DeviceNumber
 |   |      |      |       |       |__Count of devices at this level
@@ -120,8 +125,13 @@
     Speed may be:
     	1.5	Mbit/s for low speed USB
 	12	Mbit/s for full speed USB
-	480	Mbit/s for high speed USB (added for USB 2.0)
+	480	Mbit/s for high speed USB (added for USB 2.0);
+		  also used for Wireless USB, which has no fixed speed
+	5000	Mbit/s for SuperSpeed USB (added for USB 3.0)
 
+    For reasons lost in the mists of time, the Port number is always
+    too low by 1.  For example, a device plugged into port 4 will
+    show up with "Port=03".
 
 Bandwidth info:
 B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
@@ -291,7 +301,7 @@
 an external hub connected to the root hub, and a mouse and
 a serial converter connected to the external hub.
 
-T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
+T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
 B:  Alloc= 28/900 us ( 3%), #Int=  2, #Iso=  0
 D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0000 ProdID=0000 Rev= 0.00
@@ -301,21 +311,21 @@
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
 E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
 
-T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
+T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 4
 D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0451 ProdID=1446 Rev= 1.00
 C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
 E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=255ms
 
-T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5  MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=04b4 ProdID=0001 Rev= 0.00
 C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
 E:  Ad=81(I) Atr=03(Int.) MxPS=   3 Ivl= 10ms
 
-T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12   MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0565 ProdID=0001 Rev= 1.08
 S:  Manufacturer=Peracom Networks, Inc.
@@ -330,12 +340,12 @@
 Selecting only the "T:" and "I:" lines from this (for example, by using
 "procusb ti"), we have:
 
-T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
-T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
+T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
+T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 4
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
-T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5  MxCh= 0
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
-T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12   MxCh= 0
 I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
 
 
diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c
index ccd951f..cc96ee2 100644
--- a/Documentation/vm/page-types.c
+++ b/Documentation/vm/page-types.c
@@ -478,7 +478,7 @@
 	}
 
 	if (opt_unpoison && !hwpoison_forget_fd) {
-		sprintf(buf, "%s/renew-pfn", hwpoison_debug_fs);
+		sprintf(buf, "%s/unpoison-pfn", hwpoison_debug_fs);
 		hwpoison_forget_fd = checked_open(buf, O_WRONLY);
 	}
 }
diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt
index e4498a2..996a27d 100644
--- a/Documentation/workqueue.txt
+++ b/Documentation/workqueue.txt
@@ -196,11 +196,11 @@
 	suspend operations.  Work items on the wq are drained and no
 	new work item starts execution until thawed.
 
-  WQ_RESCUER
+  WQ_MEM_RECLAIM
 
 	All wq which might be used in the memory reclaim paths _MUST_
-	have this flag set.  This reserves one worker exclusively for
-	the execution of this wq under memory pressure.
+	have this flag set.  The wq is guaranteed to have at least one
+	execution context regardless of memory pressure.
 
   WQ_HIGHPRI
 
@@ -356,11 +356,11 @@
 
 6. Guidelines
 
-* Do not forget to use WQ_RESCUER if a wq may process work items which
-  are used during memory reclaim.  Each wq with WQ_RESCUER set has one
-  rescuer thread reserved for it.  If there is dependency among
-  multiple work items used during memory reclaim, they should be
-  queued to separate wq each with WQ_RESCUER.
+* Do not forget to use WQ_MEM_RECLAIM if a wq may process work items
+  which are used during memory reclaim.  Each wq with WQ_MEM_RECLAIM
+  set has an execution context reserved for it.  If there is
+  dependency among multiple work items used during memory reclaim,
+  they should be queued to separate wq each with WQ_MEM_RECLAIM.
 
 * Unless strict ordering is required, there is no need to use ST wq.
 
@@ -368,12 +368,13 @@
   recommended.  In most use cases, concurrency level usually stays
   well under the default limit.
 
-* A wq serves as a domain for forward progress guarantee (WQ_RESCUER),
-  flush and work item attributes.  Work items which are not involved
-  in memory reclaim and don't need to be flushed as a part of a group
-  of work items, and don't require any special attribute, can use one
-  of the system wq.  There is no difference in execution
-  characteristics between using a dedicated wq and a system wq.
+* A wq serves as a domain for forward progress guarantee
+  (WQ_MEM_RECLAIM, flush and work item attributes.  Work items which
+  are not involved in memory reclaim and don't need to be flushed as a
+  part of a group of work items, and don't require any special
+  attribute, can use one of the system wq.  There is no difference in
+  execution characteristics between using a dedicated wq and a system
+  wq.
 
 * Unless work items are expected to consume a huge amount of CPU
   cycles, using a bound wq is usually beneficial due to the increased
diff --git a/Documentation/x86/x86_64/kernel-stacks b/Documentation/x86/x86_64/kernel-stacks
index 5ad65d5..a01eec5 100644
--- a/Documentation/x86/x86_64/kernel-stacks
+++ b/Documentation/x86/x86_64/kernel-stacks
@@ -18,9 +18,9 @@
   Used for external hardware interrupts.  If this is the first external
   hardware interrupt (i.e. not a nested hardware interrupt) then the
   kernel switches from the current task to the interrupt stack.  Like
-  the split thread and interrupt stacks on i386 (with CONFIG_4KSTACKS),
-  this gives more room for kernel interrupt processing without having
-  to increase the size of every per thread stack.
+  the split thread and interrupt stacks on i386, this gives more room
+  for kernel interrupt processing without having to increase the size
+  of every per thread stack.
 
   The interrupt stack is also used when processing a softirq.
 
diff --git a/Kbuild b/Kbuild
index e3737ad..431f7ca 100644
--- a/Kbuild
+++ b/Kbuild
@@ -53,6 +53,7 @@
 # Default sed regexp - multiline due to syntax constraints
 define sed-y
 	"/^->/{s:->#\(.*\):/* \1 */:; \
+	s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 (\2) /* \3 */:; \
 	s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
 	s:->::; p;}"
 endef
diff --git a/MAINTAINERS b/MAINTAINERS
index df34283..494e1a0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -157,9 +157,11 @@
 F:	drivers/net/r8169.c
 
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
+M:	Greg Kroah-Hartman <gregkh@suse.de>
 L:	linux-serial@vger.kernel.org
 W:	http://serial.sourceforge.net
-S:	Orphan
+S:	Maintained
+T:	quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 F:	drivers/serial/8250*
 F:	include/linux/serial_8250.h
 
@@ -962,6 +964,23 @@
 S:	Maintained
 F:	arch/arm/mach-s3c6410/
 
+ARM/S5P ARM ARCHITECTURES
+M:	Kukjin Kim <kgene.kim@samsung.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:	linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+S:	Maintained
+F:	arch/arm/mach-s5p*/
+
+ARM/SAMSUNG S5P SERIES FIMC SUPPORT
+M:	Kyungmin Park <kyungmin.park@samsung.com>
+M:	Sylwester Nawrocki <s.nawrocki@samsung.com>
+L:	linux-arm-kernel@lists.infradead.org
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	arch/arm/plat-s5p/dev-fimc*
+F:	arch/arm/plat-samsung/include/plat/*fimc*
+F:	drivers/media/video/s5p-fimc/
+
 ARM/SHMOBILE ARM ARCHITECTURE
 M:	Paul Mundt <lethal@linux-sh.org>
 M:	Magnus Damm <magnus.damm@gmail.com>
@@ -973,11 +992,23 @@
 F:	arch/arm/mach-shmobile/
 F:	drivers/sh/
 
+ARM/TELECHIPS ARM ARCHITECTURE
+M:	"Hans J. Koch" <hjk@linutronix.de>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	arch/arm/plat-tcc/
+F:	arch/arm/mach-tcc8k/
+
 ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
 M:	Lennert Buytenhek <kernel@wantstofly.org>
 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>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+
 ARM/THECUS N2100 MACHINE SUPPORT
 M:	Lennert Buytenhek <kernel@wantstofly.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1120,6 +1151,13 @@
 S:	Maintained
 F:	drivers/net/wireless/ath/ar9170/
 
+CARL9170 LINUX COMMUNITY WIRELESS DRIVER
+M:	Christian Lamparter <chunkeey@googlemail.com>
+L:	linux-wireless@vger.kernel.org
+W:	http://wireless.kernel.org/en/users/Drivers/carl9170
+S:	Maintained
+F:	drivers/net/wireless/ath/carl9170/
+
 ATK0110 HWMON DRIVER
 M:	Luca Tettamanti <kronos.it@gmail.com>
 L:	lm-sensors@lm-sensors.org
@@ -1344,16 +1382,19 @@
 
 BLUETOOTH DRIVERS
 M:	Marcel Holtmann <marcel@holtmann.org>
+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
 S:	Maintained
 F:	drivers/bluetooth/
 
 BLUETOOTH SUBSYSTEM
 M:	Marcel Holtmann <marcel@holtmann.org>
+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/holtmann/bluetooth-2.6.git
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git
 S:	Maintained
 F:	net/bluetooth/
 F:	include/net/bluetooth/
@@ -1398,6 +1439,13 @@
 S:	Supported
 F:	drivers/scsi/bfa/
 
+BROCADE BNA 10 GIGABIT ETHERNET DRIVER
+M:	Rasesh Mody <rmody@brocade.com>
+M:	Debashis Dutt <ddutt@brocade.com>
+L:	netdev@vger.kernel.org
+S:	Supported
+F:	drivers/net/bna/
+
 BSG (block layer generic sg v4 driver)
 M:	FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
 L:	linux-scsi@vger.kernel.org
@@ -1510,6 +1558,8 @@
 S:	Supported
 F:	Documentation/filesystems/ceph.txt
 F:	fs/ceph
+F:	net/ceph
+F:	include/linux/ceph
 
 CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
 M:	David Vrabel <david.vrabel@csr.com>
@@ -1553,9 +1603,9 @@
 F:	scripts/checkpatch.pl
 
 CISCO VIC ETHERNET NIC DRIVER
-M:	Scott Feldman <scofeldm@cisco.com>
 M:	Vasanthy Kolluri <vkolluri@cisco.com>
 M:	Roopa Prabhu <roprabhu@cisco.com>
+M:	David Wang <dwang2@cisco.com>
 S:	Supported
 F:	drivers/net/enic/
 
@@ -2033,14 +2083,16 @@
 F:	lib/lru_cache.c
 F:	Documentation/blockdev/drbd/
 
-DRIVER CORE, KOBJECTS, AND SYSFS
+DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
 M:	Greg Kroah-Hartman <gregkh@suse.de>
 T:	quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 S:	Supported
 F:	Documentation/kobject.txt
 F:	drivers/base/
 F:	fs/sysfs/
+F:	fs/debugfs/
 F:	include/linux/kobj*
+F:	include/linux/debugfs.h
 F:	lib/kobj*
 
 DRM DRIVERS
@@ -2528,7 +2580,7 @@
 F:	drivers/scsi/gdt*
 
 GENERIC GPIO I2C DRIVER
-M:	Haavard Skinnemoen <hskinnemoen@atmel.com>
+M:	Haavard Skinnemoen <hskinnemoen@gmail.com>
 S:	Supported
 F:	drivers/i2c/busses/i2c-gpio.c
 F:	include/linux/i2c-gpio.h
@@ -2668,6 +2720,8 @@
 L:	lm-sensors@lm-sensors.org
 W:	http://www.lm-sensors.org/
 T:	quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
+T:	quilt kernel.org/pub/linux/kernel/people/groeck/linux-staging/
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
 S:	Maintained
 F:	Documentation/hwmon/
 F:	drivers/hwmon/
@@ -2885,6 +2939,12 @@
 S:	Supported
 F:	drivers/scsi/ipr.*
 
+IBM Power Virtual Ethernet Device Driver
+M:	Santiago Leon <santil@linux.vnet.ibm.com>
+L:	netdev@vger.kernel.org
+S:	Supported
+F:	drivers/net/ibmveth.*
+
 IBM ServeRAID RAID DRIVER
 P:	Jack Hammer
 M:	Dave Jeffery <ipslinux@adaptec.com>
@@ -3054,16 +3114,27 @@
 S:	Maintained
 F:	drivers/net/ixp2000/
 
-INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe)
+INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf)
 M:	Jeff Kirsher <jeffrey.t.kirsher@intel.com>
 M:	Jesse Brandeburg <jesse.brandeburg@intel.com>
 M:	Bruce Allan <bruce.w.allan@intel.com>
-M:	Alex Duyck <alexander.h.duyck@intel.com>
+M:	Carolyn Wyborny <carolyn.wyborny@intel.com>
+M:	Don Skidmore <donald.c.skidmore@intel.com>
+M:	Greg Rose <gregory.v.rose@intel.com>
 M:	PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
+M:	Alex Duyck <alexander.h.duyck@intel.com>
 M:	John Ronciak <john.ronciak@intel.com>
 L:	e1000-devel@lists.sourceforge.net
 W:	http://e1000.sourceforge.net/
 S:	Supported
+F:	Documentation/networking/e100.txt
+F:	Documentation/networking/e1000.txt
+F:	Documentation/networking/e1000e.txt
+F:	Documentation/networking/igb.txt
+F:	Documentation/networking/igbvf.txt
+F:	Documentation/networking/ixgb.txt
+F:	Documentation/networking/ixgbe.txt
+F:	Documentation/networking/ixgbevf.txt
 F:	drivers/net/e100.c
 F:	drivers/net/e1000/
 F:	drivers/net/e1000e/
@@ -3071,6 +3142,7 @@
 F:	drivers/net/igbvf/
 F:	drivers/net/ixgb/
 F:	drivers/net/ixgbe/
+F:	drivers/net/ixgbevf/
 
 INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
 L:	linux-wireless@vger.kernel.org
@@ -3131,7 +3203,7 @@
 
 IOC3 SERIAL DRIVER
 M:	Pat Gefre <pfg@sgi.com>
-L:	linux-mips@linux-mips.org
+L:	linux-serial@vger.kernel.org
 S:	Maintained
 F:	drivers/serial/ioc3_serial.c
 
@@ -3208,6 +3280,12 @@
 F:	include/net/irda/
 F:	net/irda/
 
+IRQ SUBSYSTEM
+M:	Thomas Gleixner <tglx@linutronix.de>
+S:	Maintained
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git irq/core
+F:	kernel/irq/
+
 ISAPNP
 M:	Jaroslav Kysela <perex@perex.cz>
 S:	Maintained
@@ -3300,6 +3378,12 @@
 F:	include/linux/ext*jbd*.h
 F:	include/linux/jbd*.h
 
+JSM Neo PCI based serial card
+M:	Breno Leitao <leitao@linux.vnet.ibm.com>
+L:	linux-serial@vger.kernel.org
+S:	Maintained
+F:	drivers/serial/jsm/
+
 K8TEMP HARDWARE MONITORING DRIVER
 M:	Rudolf Marek <r.marek@assembler.cz>
 L:	lm-sensors@lm-sensors.org
@@ -3779,9 +3863,8 @@
 S:	Supported
 
 MATROX FRAMEBUFFER DRIVER
-M:	Petr Vandrovec <vandrove@vc.cvut.cz>
 L:	linux-fbdev@vger.kernel.org
-S:	Maintained
+S:	Orphan
 F:	drivers/video/matrox/matroxfb_*
 F:	include/linux/matroxfb.h
 
@@ -3923,8 +4006,10 @@
 F:	drivers/mfd/
 
 MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
-S:	Orphan
+M:	Chris Ball <cjb@laptop.org>
 L:	linux-mmc@vger.kernel.org
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
+S:	Maintained
 F:	drivers/mmc/
 F:	include/linux/mmc/
 
@@ -3966,8 +4051,8 @@
 F:	drivers/net/natsemi.c
 
 NCP FILESYSTEM
-M:	Petr Vandrovec <vandrove@vc.cvut.cz>
-S:	Maintained
+M:	Petr Vandrovec <petr@vandrovec.name>
+S:	Odd Fixes
 F:	fs/ncpfs/
 
 NCR DUAL 700 SCSI DRIVER (MICROCHANNEL)
@@ -4330,13 +4415,12 @@
 F:	fs/ocfs2/
 
 ORINOCO DRIVER
-M:	Pavel Roskin <proski@gnu.org>
-M:	David Gibson <hermes@gibson.dropbear.id.au>
 L:	linux-wireless@vger.kernel.org
 L:	orinoco-users@lists.sourceforge.net
 L:	orinoco-devel@lists.sourceforge.net
+W:	http://linuxwireless.org/en/users/Drivers/orinoco
 W:	http://www.nongnu.org/orinoco/
-S:	Maintained
+S:	Orphan
 F:	drivers/net/wireless/orinoco/
 
 OSD LIBRARY and FILESYSTEM
@@ -4524,6 +4608,14 @@
 S:	Maintained
 F:	include/linux/personality.h
 
+PHONET PROTOCOL
+M:	Remi Denis-Courmont <remi.denis-courmont@nokia.com>
+S:	Supported
+F:	Documentation/networking/phonet.txt
+F:	include/linux/phonet.h
+F:	include/net/phonet/
+F:	net/phonet/
+
 PHRAM MTD DRIVER
 M:	Joern Engel <joern@lazybastard.org>
 L:	linux-mtd@lists.infradead.org
@@ -4773,6 +4865,15 @@
 F:	include/linux/qnx4_fs.h
 F:	include/linux/qnxtypes.h
 
+RADOS BLOCK DEVICE (RBD)
+F:	include/linux/qnxtypes.h
+M:	Yehuda Sadeh <yehuda@hq.newdream.net>
+M:	Sage Weil <sage@newdream.net>
+M:	ceph-devel@vger.kernel.org
+S:	Supported
+F:	drivers/block/rbd.c
+F:	drivers/block/rbd_types.h
+
 RADEON FRAMEBUFFER DISPLAY DRIVER
 M:	Benjamin Herrenschmidt <benh@kernel.crashing.org>
 L:	linux-fbdev@vger.kernel.org
@@ -4998,6 +5099,12 @@
 F:	drivers/media/video/*7146*
 F:	include/media/*7146*
 
+SAMSUNG AUDIO (ASoC) DRIVERS
+M:	Jassi Brar <jassi.brar@samsung.com>
+L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
+S:	Supported
+F:	sound/soc/s3c24xx
+
 TLG2300 VIDEO4LINUX-2 DRIVER
 M:	Huang Shijie <shijie8@gmail.com>
 M:	Kang Yong <kangyong@telegent.com>
@@ -5095,8 +5202,10 @@
 F:	drivers/mmc/host/sdricoh_cs.c
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
-S:	Orphan
+M:	Chris Ball <cjb@laptop.org>
 L:	linux-mmc@vger.kernel.org
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git
+S:	Maintained
 F:	drivers/mmc/host/sdhci.*
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
@@ -5894,6 +6003,14 @@
 F:	Documentation/usb/acm.txt
 F:	drivers/usb/class/cdc-acm.*
 
+USB ATTACHED SCSI
+M:	Matthew Wilcox <willy@linux.intel.com>
+M:	Sarah Sharp <sarah.a.sharp@linux.intel.com>
+L:	linux-usb@vger.kernel.org
+L:	linux-scsi@vger.kernel.org
+S:	Supported
+F:	drivers/usb/storage/uas.c
+
 USB BLOCK DRIVER (UB ub)
 M:	Pete Zaitcev <zaitcev@redhat.com>
 L:	linux-usb@vger.kernel.org
@@ -6402,21 +6519,21 @@
 F:	drivers/input/misc/wistron_btns.c
 
 WL1251 WIRELESS DRIVER
-M:	Kalle Valo <kalle.valo@iki.fi>
+M:	Kalle Valo <kvalo@adurom.com>
 L:	linux-wireless@vger.kernel.org
 W:	http://wireless.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
 S:	Maintained
-F:	drivers/net/wireless/wl12xx/*
-X:	drivers/net/wireless/wl12xx/wl1271*
+F:	drivers/net/wireless/wl1251/*
 
 WL1271 WIRELESS DRIVER
 M:	Luciano Coelho <luciano.coelho@nokia.com>
 L:	linux-wireless@vger.kernel.org
 W:	http://wireless.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
 S:	Maintained
 F:	drivers/net/wireless/wl12xx/wl1271*
+F:	include/linux/wl12xx.h
 
 WL3501 WIRELESS PCMCIA CARD DRIVER
 M:	Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
@@ -6438,8 +6555,10 @@
 WOLFSON MICROELECTRONICS DRIVERS
 M:	Mark Brown <broonie@opensource.wolfsonmicro.com>
 M:	Ian Lartey <ian@opensource.wolfsonmicro.com>
+M:	Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+T:	git git://opensource.wolfsonmicro.com/linux-2.6-asoc
 T:	git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
-W:	http://opensource.wolfsonmicro.com/node/8
+W:	http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices
 S:	Supported
 F:	Documentation/hwmon/wm83??
 F:	drivers/leds/leds-wm83*.c
@@ -6561,6 +6680,20 @@
 S:	Maintained
 F:	drivers/serial/zs.*
 
+GRE DEMULTIPLEXER DRIVER
+M:	Dmitry Kozlov <xeb@mail.ru>
+L:	netdev@vger.kernel.org
+S:	Maintained
+F:	net/ipv4/gre.c
+F:	include/net/gre.h
+
+PPTP DRIVER
+M:	Dmitry Kozlov <xeb@mail.ru>
+L:	netdev@vger.kernel.org
+S:	Maintained
+F:	drivers/net/pptp.c
+W:	http://sourceforge.net/projects/accel-pptp
+
 THE REST
 M:	Linus Torvalds <torvalds@linux-foundation.org>
 L:	linux-kernel@vger.kernel.org
diff --git a/Makefile b/Makefile
index 3133a57..3e43805 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 36
-EXTRAVERSION = -rc5
-NAME = Sheep on Meth
+EXTRAVERSION =
+NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -554,8 +554,15 @@
 ifdef CONFIG_FRAME_POINTER
 KBUILD_CFLAGS	+= -fno-omit-frame-pointer -fno-optimize-sibling-calls
 else
+# Some targets (ARM with Thumb2, for example), can't be built with frame
+# pointers.  For those, we don't have FUNCTION_TRACER automatically
+# select FRAME_POINTER.  However, FUNCTION_TRACER adds -pg, and this is
+# incompatible with -fomit-frame-pointer with current GCC, so we don't use
+# -fomit-frame-pointer with FUNCTION_TRACER.
+ifndef CONFIG_FUNCTION_TRACER
 KBUILD_CFLAGS	+= -fomit-frame-pointer
 endif
+endif
 
 ifdef CONFIG_DEBUG_INFO
 KBUILD_CFLAGS	+= -g
@@ -568,6 +575,12 @@
 
 ifdef CONFIG_FUNCTION_TRACER
 KBUILD_CFLAGS	+= -pg
+ifdef CONFIG_DYNAMIC_FTRACE
+	ifdef CONFIG_HAVE_C_RECORDMCOUNT
+		BUILD_C_RECORDMCOUNT := y
+		export BUILD_C_RECORDMCOUNT
+	endif
+endif
 endif
 
 # We trigger additional mismatches with less inlining
@@ -591,6 +604,11 @@
 # conserve stack if available
 KBUILD_CFLAGS   += $(call cc-option,-fconserve-stack)
 
+# check for 'asm goto'
+ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
+	KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
+endif
+
 # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
 # But warn user when we do so
 warn-assign = \
diff --git a/arch/Kconfig b/arch/Kconfig
index fe48fc7..53d7f61 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -158,4 +158,7 @@
 	  subsystem.  Also has support for calculating CPU cycle events
 	  to determine how many clock cycles in a given period.
 
+config HAVE_ARCH_JUMP_LABEL
+	bool
+
 source "kernel/gcov/Kconfig"
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index b9647bb..d04ccd7 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -9,6 +9,7 @@
 	select HAVE_IDE
 	select HAVE_OPROFILE
 	select HAVE_SYSCALL_WRAPPERS
+	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select HAVE_DMA_ATTRS
 	help
diff --git a/arch/alpha/include/asm/irqflags.h b/arch/alpha/include/asm/irqflags.h
new file mode 100644
index 0000000..299bbc7
--- /dev/null
+++ b/arch/alpha/include/asm/irqflags.h
@@ -0,0 +1,67 @@
+#ifndef __ALPHA_IRQFLAGS_H
+#define __ALPHA_IRQFLAGS_H
+
+#include <asm/system.h>
+
+#define IPL_MIN		0
+#define IPL_SW0		1
+#define IPL_SW1		2
+#define IPL_DEV0	3
+#define IPL_DEV1	4
+#define IPL_TIMER	5
+#define IPL_PERF	6
+#define IPL_POWERFAIL	6
+#define IPL_MCHECK	7
+#define IPL_MAX		7
+
+#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
+#undef IPL_MIN
+#define IPL_MIN		__min_ipl
+extern int __min_ipl;
+#endif
+
+#define getipl()		(rdps() & 7)
+#define setipl(ipl)		((void) swpipl(ipl))
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	return rdps();
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	setipl(IPL_MAX);
+	barrier();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags = swpipl(IPL_MAX);
+	barrier();
+	return flags;
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	barrier();
+	setipl(IPL_MIN);
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	barrier();
+	setipl(flags);
+	barrier();
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return flags == IPL_MAX;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(getipl());
+}
+
+#endif /* __ALPHA_IRQFLAGS_H */
diff --git a/arch/alpha/include/asm/perf_event.h b/arch/alpha/include/asm/perf_event.h
index 4157cd3..fe792ca 100644
--- a/arch/alpha/include/asm/perf_event.h
+++ b/arch/alpha/include/asm/perf_event.h
@@ -1,11 +1,6 @@
 #ifndef __ASM_ALPHA_PERF_EVENT_H
 #define __ASM_ALPHA_PERF_EVENT_H
 
-/* Alpha only supports software events through this interface. */
-extern void set_perf_event_pending(void);
-
-#define PERF_EVENT_INDEX_OFFSET 0
-
 #ifdef CONFIG_PERF_EVENTS
 extern void init_hw_perf_events(void);
 #else
diff --git a/arch/alpha/include/asm/system.h b/arch/alpha/include/asm/system.h
index 5aa40cc..9f78e69 100644
--- a/arch/alpha/include/asm/system.h
+++ b/arch/alpha/include/asm/system.h
@@ -259,34 +259,6 @@
 __CALL_PAL_W1(wrusp, unsigned long);
 __CALL_PAL_W1(wrvptptr, unsigned long);
 
-#define IPL_MIN		0
-#define IPL_SW0		1
-#define IPL_SW1		2
-#define IPL_DEV0	3
-#define IPL_DEV1	4
-#define IPL_TIMER	5
-#define IPL_PERF	6
-#define IPL_POWERFAIL	6
-#define IPL_MCHECK	7
-#define IPL_MAX		7
-
-#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
-#undef IPL_MIN
-#define IPL_MIN		__min_ipl
-extern int __min_ipl;
-#endif
-
-#define getipl()		(rdps() & 7)
-#define setipl(ipl)		((void) swpipl(ipl))
-
-#define local_irq_disable()			do { setipl(IPL_MAX); barrier(); } while(0)
-#define local_irq_enable()			do { barrier(); setipl(IPL_MIN); } while(0)
-#define local_save_flags(flags)	((flags) = rdps())
-#define local_irq_save(flags)	do { (flags) = swpipl(IPL_MAX); barrier(); } while(0)
-#define local_irq_restore(flags)	do { barrier(); setipl(flags); barrier(); } while(0)
-
-#define irqs_disabled()	(getipl() == IPL_MAX)
-
 /*
  * TB routines..
  */
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index ab1ee0a..6d159ce 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -73,8 +73,6 @@
 	ldq	$20, HAE_REG($19);	\
 	stq	$21, HAE_CACHE($19);	\
 	stq	$21, 0($20);		\
-	ldq	$0, 0($sp);		\
-	ldq	$1, 8($sp);		\
 99:;					\
 	ldq	$19, 72($sp);		\
 	ldq	$20, 80($sp);		\
@@ -316,7 +314,7 @@
 	cmovne	$26, 0, $19		/* $19 = 0 => non-restartable */
 	ldq	$0, SP_OFF($sp)
 	and	$0, 8, $0
-	beq	$0, restore_all
+	beq	$0, ret_to_kernel
 ret_to_user:
 	/* Make sure need_resched and sigpending don't change between
 		sampling and the rti.  */
@@ -329,6 +327,11 @@
 	RESTORE_ALL
 	call_pal PAL_rti
 
+ret_to_kernel:
+	lda	$16, 7
+	call_pal PAL_swpipl
+	br restore_all
+
 	.align 3
 $syscall_error:
 	/*
@@ -657,7 +660,7 @@
 	/* We don't actually care for a3 success widgetry in the kernel.
 	   Not for positive errno values.  */
 	stq	$0, 0($sp)		/* $0 */
-	br	restore_all
+	br	ret_to_kernel
 .end kernel_thread
 
 /*
@@ -912,15 +915,6 @@
 .end sys_execve
 
 	.align	4
-	.globl	osf_sigprocmask
-	.ent	osf_sigprocmask
-osf_sigprocmask:
-	.prologue 0
-	mov	$sp, $18
-	jmp	$31, sys_osf_sigprocmask
-.end osf_sigprocmask
-
-	.align	4
 	.globl	alpha_ni_syscall
 	.ent	alpha_ni_syscall
 alpha_ni_syscall:
diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
index 85d8e4f..1cc4968 100644
--- a/arch/alpha/kernel/perf_event.c
+++ b/arch/alpha/kernel/perf_event.c
@@ -307,7 +307,7 @@
 			     new_raw_count) != prev_raw_count)
 		goto again;
 
-	delta = (new_raw_count  - (prev_raw_count & alpha_pmu->pmc_count_mask[idx])) + ovf;
+	delta = (new_raw_count - (prev_raw_count & alpha_pmu->pmc_count_mask[idx])) + ovf;
 
 	/* It is possible on very rare occasions that the PMC has overflowed
 	 * but the interrupt is yet to come.  Detect and fix this situation.
@@ -402,14 +402,13 @@
 		struct hw_perf_event *hwc = &pe->hw;
 		int idx = hwc->idx;
 
-		if (cpuc->current_idx[j] != PMC_NO_INDEX) {
-			cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
-			continue;
+		if (cpuc->current_idx[j] == PMC_NO_INDEX) {
+			alpha_perf_event_set_period(pe, hwc, idx);
+			cpuc->current_idx[j] = idx;
 		}
 
-		alpha_perf_event_set_period(pe, hwc, idx);
-		cpuc->current_idx[j] = idx;
-		cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
+		if (!(hwc->state & PERF_HES_STOPPED))
+			cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
 	}
 	cpuc->config = cpuc->event[0]->hw.config_base;
 }
@@ -420,12 +419,13 @@
  *  - this function is called from outside this module via the pmu struct
  *    returned from perf event initialisation.
  */
-static int alpha_pmu_enable(struct perf_event *event)
+static int alpha_pmu_add(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct hw_perf_event *hwc = &event->hw;
 	int n0;
 	int ret;
-	unsigned long flags;
+	unsigned long irq_flags;
 
 	/*
 	 * The Sparc code has the IRQ disable first followed by the perf
@@ -435,8 +435,8 @@
 	 * nevertheless we disable the PMCs first to enable a potential
 	 * final PMI to occur before we disable interrupts.
 	 */
-	perf_disable();
-	local_irq_save(flags);
+	perf_pmu_disable(event->pmu);
+	local_irq_save(irq_flags);
 
 	/* Default to error to be returned */
 	ret = -EAGAIN;
@@ -455,8 +455,12 @@
 		}
 	}
 
-	local_irq_restore(flags);
-	perf_enable();
+	hwc->state = PERF_HES_UPTODATE;
+	if (!(flags & PERF_EF_START))
+		hwc->state |= PERF_HES_STOPPED;
+
+	local_irq_restore(irq_flags);
+	perf_pmu_enable(event->pmu);
 
 	return ret;
 }
@@ -467,15 +471,15 @@
  *  - this function is called from outside this module via the pmu struct
  *    returned from perf event initialisation.
  */
-static void alpha_pmu_disable(struct perf_event *event)
+static void alpha_pmu_del(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
-	unsigned long flags;
+	unsigned long irq_flags;
 	int j;
 
-	perf_disable();
-	local_irq_save(flags);
+	perf_pmu_disable(event->pmu);
+	local_irq_save(irq_flags);
 
 	for (j = 0; j < cpuc->n_events; j++) {
 		if (event == cpuc->event[j]) {
@@ -501,8 +505,8 @@
 		}
 	}
 
-	local_irq_restore(flags);
-	perf_enable();
+	local_irq_restore(irq_flags);
+	perf_pmu_enable(event->pmu);
 }
 
 
@@ -514,13 +518,44 @@
 }
 
 
-static void alpha_pmu_unthrottle(struct perf_event *event)
+static void alpha_pmu_stop(struct perf_event *event, int flags)
 {
 	struct hw_perf_event *hwc = &event->hw;
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
+	if (!(hwc->state & PERF_HES_STOPPED)) {
+		cpuc->idx_mask &= ~(1UL<<hwc->idx);
+		hwc->state |= PERF_HES_STOPPED;
+	}
+
+	if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+		alpha_perf_event_update(event, hwc, hwc->idx, 0);
+		hwc->state |= PERF_HES_UPTODATE;
+	}
+
+	if (cpuc->enabled)
+		wrperfmon(PERFMON_CMD_DISABLE, (1UL<<hwc->idx));
+}
+
+
+static void alpha_pmu_start(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+	if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
+		return;
+
+	if (flags & PERF_EF_RELOAD) {
+		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+		alpha_perf_event_set_period(event, hwc, hwc->idx);
+	}
+
+	hwc->state = 0;
+
 	cpuc->idx_mask |= 1UL<<hwc->idx;
-	wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx));
+	if (cpuc->enabled)
+		wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx));
 }
 
 
@@ -642,39 +677,36 @@
 	return 0;
 }
 
-static const struct pmu pmu = {
-	.enable		= alpha_pmu_enable,
-	.disable	= alpha_pmu_disable,
-	.read		= alpha_pmu_read,
-	.unthrottle	= alpha_pmu_unthrottle,
-};
-
-
 /*
  * Main entry point to initialise a HW performance event.
  */
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int alpha_pmu_event_init(struct perf_event *event)
 {
 	int err;
 
+	switch (event->attr.type) {
+	case PERF_TYPE_RAW:
+	case PERF_TYPE_HARDWARE:
+	case PERF_TYPE_HW_CACHE:
+		break;
+
+	default:
+		return -ENOENT;
+	}
+
 	if (!alpha_pmu)
-		return ERR_PTR(-ENODEV);
+		return -ENODEV;
 
 	/* Do the real initialisation work. */
 	err = __hw_perf_event_init(event);
 
-	if (err)
-		return ERR_PTR(err);
-
-	return &pmu;
+	return err;
 }
 
-
-
 /*
  * Main entry point - enable HW performance counters.
  */
-void hw_perf_enable(void)
+static void alpha_pmu_enable(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -700,7 +732,7 @@
  * Main entry point - disable HW performance counters.
  */
 
-void hw_perf_disable(void)
+static void alpha_pmu_disable(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -713,6 +745,17 @@
 	wrperfmon(PERFMON_CMD_DISABLE, cpuc->idx_mask);
 }
 
+static struct pmu pmu = {
+	.pmu_enable	= alpha_pmu_enable,
+	.pmu_disable	= alpha_pmu_disable,
+	.event_init	= alpha_pmu_event_init,
+	.add		= alpha_pmu_add,
+	.del		= alpha_pmu_del,
+	.start		= alpha_pmu_start,
+	.stop		= alpha_pmu_stop,
+	.read		= alpha_pmu_read,
+};
+
 
 /*
  * Main entry point - don't know when this is called but it
@@ -766,7 +809,7 @@
 	wrperfmon(PERFMON_CMD_DISABLE, cpuc->idx_mask);
 
 	/* la_ptr is the counter that overflowed. */
-	if (unlikely(la_ptr >= perf_max_events)) {
+	if (unlikely(la_ptr >= alpha_pmu->num_pmcs)) {
 		/* This should never occur! */
 		irq_err_count++;
 		pr_warning("PMI: silly index %ld\n", la_ptr);
@@ -807,7 +850,7 @@
 			/* Interrupts coming too quickly; "throttle" the
 			 * counter, i.e., disable it for a little while.
 			 */
-			cpuc->idx_mask &= ~(1UL<<idx);
+			alpha_pmu_stop(event, 0);
 		}
 	}
 	wrperfmon(PERFMON_CMD_ENABLE, cpuc->idx_mask);
@@ -837,6 +880,7 @@
 
 	/* And set up PMU specification */
 	alpha_pmu = &ev67_pmu;
-	perf_max_events = alpha_pmu->num_pmcs;
+
+	perf_pmu_register(&pmu);
 }
 
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 842dba3..3ec3506 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -356,7 +356,7 @@
 	dest[27] = pt->r27;
 	dest[28] = pt->r28;
 	dest[29] = pt->gp;
-	dest[30] = rdusp();
+	dest[30] = ti == current_thread_info() ? rdusp() : ti->pcb.usp;
 	dest[31] = pt->pc;
 
 	/* Once upon a time this was the PS value.  Which is stupid
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 0f6b51a..6f7feb5 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -41,46 +41,20 @@
 /*
  * The OSF/1 sigprocmask calling sequence is different from the
  * C sigprocmask() sequence..
- *
- * how:
- * 1 - SIG_BLOCK
- * 2 - SIG_UNBLOCK
- * 3 - SIG_SETMASK
- *
- * We change the range to -1 .. 1 in order to let gcc easily
- * use the conditional move instructions.
- *
- * Note that we don't need to acquire the kernel lock for SMP
- * operation, as all of this is local to this thread.
  */
-SYSCALL_DEFINE3(osf_sigprocmask, int, how, unsigned long, newmask,
-		struct pt_regs *, regs)
+SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask)
 {
-	unsigned long oldmask = -EINVAL;
+	sigset_t oldmask;
+	sigset_t mask;
+	unsigned long res;
 
-	if ((unsigned long)how-1 <= 2) {
-		long sign = how-2;		/* -1 .. 1 */
-		unsigned long block, unblock;
-
-		newmask &= _BLOCKABLE;
-		spin_lock_irq(&current->sighand->siglock);
-		oldmask = current->blocked.sig[0];
-
-		unblock = oldmask & ~newmask;
-		block = oldmask | newmask;
-		if (!sign)
-			block = unblock;
-		if (sign <= 0)
-			newmask = block;
-		if (_NSIG_WORDS > 1 && sign > 0)
-			sigemptyset(&current->blocked);
-		current->blocked.sig[0] = newmask;
-		recalc_sigpending();
-		spin_unlock_irq(&current->sighand->siglock);
-
-		regs->r0 = 0;		/* special no error return */
+	siginitset(&mask, newmask & _BLOCKABLE);
+	res = sigprocmask(how, &mask, &oldmask);
+	if (!res) {
+		force_successful_syscall_return();
+		res = oldmask.sig[0];
 	}
-	return oldmask;
+	return res;
 }
 
 SYSCALL_DEFINE3(osf_sigaction, int, sig,
@@ -94,9 +68,9 @@
 		old_sigset_t mask;
 		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_flags, &act->sa_flags))
+		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+		    __get_user(mask, &act->sa_mask))
 			return -EFAULT;
-		__get_user(mask, &act->sa_mask);
 		siginitset(&new_ka.sa.sa_mask, mask);
 		new_ka.ka_restorer = NULL;
 	}
@@ -106,9 +80,9 @@
 	if (!ret && oact) {
 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
+		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
 			return -EFAULT;
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
 	}
 
 	return ret;
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index ce594ef..a6a1de9 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -58,7 +58,7 @@
 	.quad sys_open				/* 45 */
 	.quad alpha_ni_syscall
 	.quad sys_getxgid
-	.quad osf_sigprocmask
+	.quad sys_osf_sigprocmask
 	.quad alpha_ni_syscall
 	.quad alpha_ni_syscall			/* 50 */
 	.quad sys_acct
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 396af17..0f1d849 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -41,7 +41,7 @@
 #include <linux/init.h>
 #include <linux/bcd.h>
 #include <linux/profile.h>
-#include <linux/perf_event.h>
+#include <linux/irq_work.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -83,25 +83,25 @@
 
 unsigned long est_cycle_freq;
 
-#ifdef CONFIG_PERF_EVENTS
+#ifdef CONFIG_IRQ_WORK
 
-DEFINE_PER_CPU(u8, perf_event_pending);
+DEFINE_PER_CPU(u8, irq_work_pending);
 
-#define set_perf_event_pending_flag()  __get_cpu_var(perf_event_pending) = 1
-#define test_perf_event_pending()      __get_cpu_var(perf_event_pending)
-#define clear_perf_event_pending()     __get_cpu_var(perf_event_pending) = 0
+#define set_irq_work_pending_flag()  __get_cpu_var(irq_work_pending) = 1
+#define test_irq_work_pending()      __get_cpu_var(irq_work_pending)
+#define clear_irq_work_pending()     __get_cpu_var(irq_work_pending) = 0
 
-void set_perf_event_pending(void)
+void set_irq_work_pending(void)
 {
-	set_perf_event_pending_flag();
+	set_irq_work_pending_flag();
 }
 
-#else  /* CONFIG_PERF_EVENTS */
+#else  /* CONFIG_IRQ_WORK */
 
-#define test_perf_event_pending()      0
-#define clear_perf_event_pending()
+#define test_irq_work_pending()      0
+#define clear_irq_work_pending()
 
-#endif /* CONFIG_PERF_EVENTS */
+#endif /* CONFIG_IRQ_WORK */
 
 
 static inline __u32 rpcc(void)
@@ -191,9 +191,9 @@
 
 	write_sequnlock(&xtime_lock);
 
-	if (test_perf_event_pending()) {
-		clear_perf_event_pending();
-		perf_event_do_pending();
+	if (test_irq_work_pending()) {
+		clear_irq_work_pending();
+		irq_work_run();
 	}
 
 #ifndef CONFIG_SMP
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 553b7cf..3849887 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -19,13 +19,17 @@
 	select HAVE_KPROBES if (!XIP_KERNEL)
 	select HAVE_KRETPROBES if (HAVE_KPROBES)
 	select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
+	select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
+	select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_LZO
 	select HAVE_KERNEL_LZMA
+	select HAVE_IRQ_WORK
 	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))
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
@@ -145,6 +149,9 @@
 	  and that the relevant menu configurations are displayed for
 	  it.
 
+config ARCH_HAS_CPU_IDLE_WAIT
+       def_bool y
+
 config GENERIC_HWEIGHT
 	bool
 	default y
@@ -271,7 +278,6 @@
 	bool "Atmel AT91"
 	select ARCH_REQUIRE_GPIOLIB
 	select HAVE_CLK
-	select ARCH_USES_GETTIMEOFFSET
 	help
 	  This enables support for systems based on the Atmel AT91RM9200,
 	  AT91SAM9 and AT91CAP9 processors.
@@ -511,6 +517,7 @@
 	select GENERIC_CLOCKEVENTS
 	select TICK_ONESHOT
 	select PLAT_PXA
+	select SPARSE_IRQ
 	help
 	  Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
 
@@ -588,6 +595,7 @@
 	select GENERIC_CLOCKEVENTS
 	select TICK_ONESHOT
 	select PLAT_PXA
+	select SPARSE_IRQ
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
@@ -679,8 +687,8 @@
 	help
 	  Samsung S3C64XX series based systems
 
-config ARCH_S5P6440
-	bool "Samsung S5P6440"
+config ARCH_S5P64X0
+	bool "Samsung S5P6440 S5P6450"
 	select CPU_V6
 	select GENERIC_GPIO
 	select HAVE_CLK
@@ -689,7 +697,8 @@
 	select HAVE_S3C2410_I2C
 	select HAVE_S3C_RTC
 	help
-	  Samsung S5P6440 CPU based systems
+	  Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440,
+	  SMDK6450.
 
 config ARCH_S5P6442
 	bool "Samsung S5P6442"
@@ -748,6 +757,15 @@
 	  Support for the StrongARM based Digital DNARD machine, also known
 	  as "Shark" (<http://www.shark-linux.de/shark.html>).
 
+config ARCH_TCC_926
+	bool "Telechips TCC ARM926-based systems"
+	select CPU_ARM926T
+	select HAVE_CLK
+	select COMMON_CLKDEV
+	select GENERIC_CLOCKEVENTS
+	help
+	  Support for Telechips TCC ARM926-based systems.
+
 config ARCH_LH7A40X
 	bool "Sharp LH7A40X"
 	select CPU_ARM922T
@@ -916,6 +934,8 @@
 
 source "arch/arm/plat-spear/Kconfig"
 
+source "arch/arm/plat-tcc/Kconfig"
+
 if ARCH_S3C2410
 source "arch/arm/mach-s3c2400/Kconfig"
 source "arch/arm/mach-s3c2410/Kconfig"
@@ -929,7 +949,7 @@
 source "arch/arm/mach-s3c64xx/Kconfig"
 endif
 
-source "arch/arm/mach-s5p6440/Kconfig"
+source "arch/arm/mach-s5p64x0/Kconfig"
 
 source "arch/arm/mach-s5p6442/Kconfig"
 
@@ -1003,7 +1023,7 @@
 
 config ARM_ERRATA_411920
 	bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
-	depends on CPU_V6 && !SMP
+	depends on CPU_V6
 	help
 	  Invalidation of the Instruction Cache operation can
 	  fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
@@ -1051,6 +1071,32 @@
 	  ACTLR register. Note that setting specific bits in the ACTLR register
 	  may not be available in non-secure mode.
 
+config ARM_ERRATA_742230
+	bool "ARM errata: DMB operation may be faulty"
+	depends on CPU_V7 && SMP
+	help
+	  This option enables the workaround for the 742230 Cortex-A9
+	  (r1p0..r2p2) erratum. Under rare circumstances, a DMB instruction
+	  between two write operations may not ensure the correct visibility
+	  ordering of the two writes. This workaround sets a specific bit in
+	  the diagnostic register of the Cortex-A9 which causes the DMB
+	  instruction to behave as a DSB, ensuring the correct behaviour of
+	  the two writes.
+
+config ARM_ERRATA_742231
+	bool "ARM errata: Incorrect hazard handling in the SCU may lead to data corruption"
+	depends on CPU_V7 && SMP
+	help
+	  This option enables the workaround for the 742231 Cortex-A9
+	  (r2p0..r2p2) erratum. Under certain conditions, specific to the
+	  Cortex-A9 MPCore micro-architecture, two CPUs working in SMP mode,
+	  accessing some data located in the same cache line, may get corrupted
+	  data due to bad handling of the address hazard when the line gets
+	  replaced from one of the CPUs at the same time as another CPU is
+	  accessing it. This workaround sets specific bits in the diagnostic
+	  register of the Cortex-A9 which reduces the linefill issuing
+	  capabilities of the processor.
+
 config PL310_ERRATA_588369
 	bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
 	depends on CACHE_L2X0 && ARCH_OMAP4
@@ -1076,6 +1122,20 @@
 	  invalidated are not, resulting in an incoherency in the system page
 	  tables. The workaround changes the TLB flushing routines to invalidate
 	  entries regardless of the ASID.
+
+config ARM_ERRATA_743622
+	bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption"
+	depends on CPU_V7
+	help
+	  This option enables the workaround for the 743622 Cortex-A9
+	  (r2p0..r2p2) erratum. Under very rare conditions, a faulty
+	  optimisation in the Cortex-A9 Store Buffer may lead to data
+	  corruption. This workaround sets a specific bit in the diagnostic
+	  register of the Cortex-A9 which disables the Store Buffer
+	  optimisation, preventing the defect from occurring. This has no
+	  visible impact on the overall performance or power consumption of the
+	  processor.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1142,13 +1202,13 @@
 
 config SMP
 	bool "Symmetric Multi-Processing (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\
-		 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
-		 ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+	depends on EXPERIMENTAL
 	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
 	select USE_GENERIC_SMP_HELPERS
-	select HAVE_ARM_SCU if ARCH_REALVIEW || ARCH_OMAP4 || ARCH_S5PV310 ||\
-		 ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
+	select HAVE_ARM_SCU
 	help
 	  This enables support for systems with more than one CPU. If you have
 	  a system with only one CPU, like most personal computers, say N. If
@@ -1166,6 +1226,19 @@
 
 	  If you don't know what to do here, say N.
 
+config SMP_ON_UP
+	bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	depends on SMP && !XIP && !THUMB2_KERNEL
+	default y
+	help
+	  SMP kernels contain instructions which fail on non-SMP processors.
+	  Enabling this option allows the kernel to modify itself to make
+	  these instructions safe.  Disabling it allows about 1K of space
+	  savings.
+
+	  If you don't know what to do here, say Y.
+
 config HAVE_ARM_SCU
 	bool
 	depends on SMP
@@ -1216,12 +1289,9 @@
 
 config LOCAL_TIMERS
 	bool "Use local timer interrupts"
-	depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
-		REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
-		ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+	depends on SMP
 	default y
-	select HAVE_ARM_TWD if ARCH_REALVIEW || ARCH_OMAP4 || ARCH_S5PV310 || \
-		ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS
+	select HAVE_ARM_TWD
 	help
 	  Enable support for local timers on SMP platforms, rather then the
 	  legacy IPI broadcast method.  Local timers allows the system
@@ -1232,7 +1302,7 @@
 
 config HZ
 	int
-	default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || \
+	default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P64X0 || \
 		ARCH_S5P6442 || ARCH_S5PV210 || ARCH_S5PV310
 	default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
 	default AT91_TIMER_HZ if ARCH_AT91
@@ -1438,6 +1508,20 @@
 	  However, if the CPU data cache is using a write-allocate mode,
 	  this option is unlikely to provide any performance gain.
 
+config SECCOMP
+	bool
+	prompt "Enable seccomp to safely compute untrusted bytecode"
+	---help---
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
 config CC_STACKPROTECTOR
 	bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
 	help
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 91344af..2fd0b99 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -2,6 +2,20 @@
 
 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.
+
 # RMK wants arm kernels compiled with frame pointers or stack unwinding.
 # If you know what you are doing and are willing to live without stack
 # traces, you can get a slightly smaller kernel by setting this option to
@@ -27,6 +41,11 @@
 	  the performance is not affected. Currently, this feature
 	  only works with EABI compilers. If unsure say Y.
 
+config OLD_MCOUNT
+	bool
+	depends on FUNCTION_TRACER && FRAME_POINTER
+	default y
+
 config DEBUG_USER
 	bool "Verbose user fault messages"
 	help
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 59c1ce8..b87aed0 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -173,7 +173,7 @@
 machine-$(CONFIG_ARCH_S3C2410)		:= s3c2410 s3c2400 s3c2412 s3c2416 s3c2440 s3c2443
 machine-$(CONFIG_ARCH_S3C24A0)		:= s3c24a0
 machine-$(CONFIG_ARCH_S3C64XX)		:= s3c64xx
-machine-$(CONFIG_ARCH_S5P6440)		:= s5p6440
+machine-$(CONFIG_ARCH_S5P64X0)		:= s5p64x0
 machine-$(CONFIG_ARCH_S5P6442)		:= s5p6442
 machine-$(CONFIG_ARCH_S5PC100)		:= s5pc100
 machine-$(CONFIG_ARCH_S5PV210)		:= s5pv210
@@ -183,6 +183,7 @@
 machine-$(CONFIG_ARCH_SHMOBILE) 	:= shmobile
 machine-$(CONFIG_ARCH_STMP378X)		:= stmp378x
 machine-$(CONFIG_ARCH_STMP37XX)		:= stmp37xx
+machine-$(CONFIG_ARCH_TCC8K)		:= tcc8k
 machine-$(CONFIG_ARCH_TEGRA)		:= tegra
 machine-$(CONFIG_ARCH_U300)		:= u300
 machine-$(CONFIG_ARCH_U8500)		:= ux500
@@ -202,6 +203,7 @@
 plat-$(CONFIG_ARCH_OMAP)	:= omap
 plat-$(CONFIG_ARCH_S3C64XX)	:= samsung
 plat-$(CONFIG_ARCH_STMP3XXX)	:= stmp3xxx
+plat-$(CONFIG_ARCH_TCC_926)	:= tcc
 plat-$(CONFIG_PLAT_IOP)		:= iop
 plat-$(CONFIG_PLAT_NOMADIK)	:= nomadik
 plat-$(CONFIG_PLAT_ORION)	:= orion
@@ -245,13 +247,14 @@
 FASTFPE_OBJ	:=$(FASTFPE)/
 endif
 
-# If we have a machine-specific directory, then include it in the build.
-core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
-core-y				+= $(machdirs) $(platdirs)
 core-$(CONFIG_FPE_NWFPE)	+= arch/arm/nwfpe/
 core-$(CONFIG_FPE_FASTFPE)	+= $(FASTFPE_OBJ)
 core-$(CONFIG_VFP)		+= arch/arm/vfp/
 
+# If we have a machine-specific directory, then include it in the build.
+core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
+core-y				+= $(machdirs) $(platdirs)
+
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
 
 libs-y				:= arch/arm/lib/ $(libs-y)
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index b23f6bc..65a7c1c 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -116,5 +116,5 @@
 $(obj)/font.c: $(FONTC)
 	$(call cmd,shipped)
 
-$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
+$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG)
 	@sed "$(SEDFLAGS)" < $< > $@
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 7dfa9a8..ada6359 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -67,25 +67,11 @@
 
 /*
  * Routines to acknowledge, disable and enable interrupts
- *
- * Linux assumes that when we're done with an interrupt we need to
- * unmask it, in the same way we need to unmask an interrupt when
- * we first enable it.
- *
- * The GIC has a separate notion of "end of interrupt" to re-enable
- * an interrupt after handling, in order to support hardware
- * prioritisation.
- *
- * We can make the GIC behave in the way that Linux expects by making
- * our "acknowledge" routine disable the interrupt, then mark it as
- * complete.
  */
 static void gic_ack_irq(unsigned int irq)
 {
-	u32 mask = 1 << (irq % 32);
 
 	spin_lock(&irq_controller_lock);
-	writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
 	writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI);
 	spin_unlock(&irq_controller_lock);
 }
diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c
index 5ebbab6..8f0f86d 100644
--- a/arch/arm/common/pl330.c
+++ b/arch/arm/common/pl330.c
@@ -146,8 +146,7 @@
 #define DESIGNER	0x41
 #define REVISION	0x0
 #define INTEG_CFG	0x0
-#define PERIPH_ID_VAL	((PART << 0) | (DESIGNER << 12) \
-			  | (REVISION << 20) | (INTEG_CFG << 24))
+#define PERIPH_ID_VAL	((PART << 0) | (DESIGNER << 12))
 
 #define PCELL_ID_VAL	0xb105f00d
 
@@ -1859,10 +1858,10 @@
 	regs = pi->base;
 
 	/* Check if we can handle this DMAC */
-	if (get_id(pi, PERIPH_ID) != PERIPH_ID_VAL
+	if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL
 	   || get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
 		dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
-			readl(regs + PERIPH_ID), readl(regs + PCELL_ID));
+			get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID));
 		return -EINVAL;
 	}
 
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 517d50d..c0258a8 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -678,7 +678,7 @@
  *	%-EBUSY		physical address already marked in-use.
  *	%0		successful.
  */
-static int
+static int __devinit
 __sa1111_probe(struct device *me, struct resource *mem, int irq)
 {
 	struct sa1111 *sachip;
diff --git a/arch/arm/configs/at91sam9g20ek_defconfig b/arch/arm/configs/at91sam9g20ek_defconfig
index f1bac70..9e90e6d 100644
--- a/arch/arm/configs/at91sam9g20ek_defconfig
+++ b/arch/arm/configs/at91sam9g20ek_defconfig
@@ -13,6 +13,7 @@
 CONFIG_ARCH_AT91=y
 CONFIG_ARCH_AT91SAM9G20=y
 CONFIG_MACH_AT91SAM9G20EK=y
+CONFIG_MACH_AT91SAM9G20EK_2MMC=y
 CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_AEABI=y
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index ccc9c99..2f70428 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -15,6 +15,7 @@
 CONFIG_MACH_SHEEVAPLUG=y
 CONFIG_MACH_ESATA_SHEEVAPLUG=y
 CONFIG_MACH_GURUPLUG=y
+CONFIG_MACH_DOCKSTAR=y
 CONFIG_MACH_TS219=y
 CONFIG_MACH_TS41X=y
 CONFIG_MACH_OPENRD_BASE=y
diff --git a/arch/arm/configs/mx27_defconfig b/arch/arm/configs/mx27_defconfig
index b2038b0..813cfb3 100644
--- a/arch/arm/configs/mx27_defconfig
+++ b/arch/arm/configs/mx27_defconfig
@@ -21,8 +21,14 @@
 CONFIG_MACH_MX27=y
 CONFIG_MACH_MX27ADS=y
 CONFIG_MACH_PCM038=y
+CONFIG_MACH_CPUIMX27=y
+CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
+CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
 CONFIG_MACH_MX27_3DS=y
+CONFIG_MACH_IMX27_VISSTRIM_M10=y
 CONFIG_MACH_IMX27LITE=y
+CONFIG_MACH_PCA100=y
+CONFIG_MACH_MXT_TD60=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
 CONFIG_NO_HZ=y
@@ -76,7 +82,9 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
 # CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=m
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
@@ -85,19 +93,20 @@
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_IMX=y
 CONFIG_SPI=y
-CONFIG_SPI_BITBANG=y
+CONFIG_SPI_IMX=y
 CONFIG_W1=y
 CONFIG_W1_MASTER_MXC=y
 CONFIG_W1_SLAVE_THERM=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FB_IMX=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FONTS=y
 CONFIG_FONT_8x8=y
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=m
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_ULPI=y
 CONFIG_MMC=y
 CONFIG_MMC_MXC=y
 CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/mx31pdk_defconfig b/arch/arm/configs/mx31pdk_defconfig
deleted file mode 100644
index 2d29329..0000000
--- a/arch/arm/configs/mx31pdk_defconfig
+++ /dev/null
@@ -1,44 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_COMPAT_BRK is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_MXC=y
-# CONFIG_MACH_MX31ADS is not set
-CONFIG_MACH_MX31_3DS=y
-CONFIG_AEABI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_LRO is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-# CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/mx3_defconfig b/arch/arm/configs/mx3_defconfig
index 161f907..f0c339f 100644
--- a/arch/arm/configs/mx3_defconfig
+++ b/arch/arm/configs/mx3_defconfig
@@ -24,6 +24,7 @@
 CONFIG_MACH_ARMADILLO5X0=y
 CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_KZM_ARM11_01=y
+CONFIG_MACH_EUKREA_CPUIMX35=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
 CONFIG_NO_HZ=y
@@ -108,7 +109,6 @@
 CONFIG_MMC_MXC=y
 CONFIG_DMADEVICES=y
 # CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_UBIFS_FS=y
diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx51_defconfig
index a665ecb..163cfee 100644
--- a/arch/arm/configs/mx51_defconfig
+++ b/arch/arm/configs/mx51_defconfig
@@ -15,6 +15,8 @@
 CONFIG_ARCH_MXC=y
 CONFIG_ARCH_MX5=y
 CONFIG_MACH_MX51_BABBAGE=y
+CONFIG_MACH_MX51_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX51=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT_VOLUNTARY=y
@@ -69,7 +71,6 @@
 CONFIG_NATIONAL_PHY=y
 CONFIG_STE10XP=y
 CONFIG_LSI_ET1011C_PHY=y
-CONFIG_FIXED_PHY=y
 CONFIG_MDIO_BITBANG=y
 CONFIG_MDIO_GPIO=y
 CONFIG_NET_ETHERNET=y
@@ -100,7 +101,6 @@
 CONFIG_I2C_ALGOPCA=m
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID_SUPPORT is not set
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
@@ -117,13 +117,11 @@
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
-CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
-CONFIG_INOTIFY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
@@ -136,6 +134,7 @@
 CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
 CONFIG_CONFIGFS_FS=m
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -151,7 +150,6 @@
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -159,7 +157,6 @@
 # CONFIG_ARM_UNWIND is not set
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
-CONFIG_KEYS=y
 CONFIG_SECURITYFS=y
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_LZO=y
diff --git a/arch/arm/configs/realview-smp_defconfig b/arch/arm/configs/realview-smp_defconfig
index 9312ef9..5ca7a61 100644
--- a/arch/arm/configs/realview-smp_defconfig
+++ b/arch/arm/configs/realview-smp_defconfig
@@ -39,6 +39,7 @@
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_ARM_INTEGRATOR=y
+CONFIG_ARM_CHARLCD=y
 CONFIG_NETDEVICES=y
 CONFIG_SMSC_PHY=y
 CONFIG_NET_ETHERNET=y
@@ -52,10 +53,13 @@
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_VERSATILE=y
+CONFIG_SPI=y
+CONFIG_GPIOLIB=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FB_ARMCLCD=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
@@ -70,7 +74,13 @@
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
-CONFIG_INOTIFY=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_PL031=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_CRAMFS=y
@@ -80,6 +90,7 @@
 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_RCU_CPU_STALL_DETECTOR is not set
diff --git a/arch/arm/configs/realview_defconfig b/arch/arm/configs/realview_defconfig
index fb75192..fcaa603 100644
--- a/arch/arm/configs/realview_defconfig
+++ b/arch/arm/configs/realview_defconfig
@@ -38,6 +38,7 @@
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_ARM_INTEGRATOR=y
+CONFIG_ARM_CHARLCD=y
 CONFIG_NETDEVICES=y
 CONFIG_SMSC_PHY=y
 CONFIG_NET_ETHERNET=y
@@ -51,10 +52,13 @@
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_VERSATILE=y
+CONFIG_SPI=y
+CONFIG_GPIOLIB=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FB_ARMCLCD=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
@@ -69,7 +73,13 @@
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
-CONFIG_INOTIFY=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_PL031=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_CRAMFS=y
@@ -79,6 +89,7 @@
 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_RCU_CPU_STALL_DETECTOR is not set
diff --git a/arch/arm/configs/s5p6440_defconfig b/arch/arm/configs/s5p6440_defconfig
deleted file mode 100644
index 0b0266c..0000000
--- a/arch/arm/configs/s5p6440_defconfig
+++ /dev/null
@@ -1,65 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSFS_DEPRECATED_V2=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_S5P6440=y
-CONFIG_S3C_BOOT_ERROR_RESET=y
-CONFIG_S3C_LOWLEVEL_UART_PORT=1
-CONFIG_MACH_SMDK6440=y
-CONFIG_CPU_32v6K=y
-CONFIG_AEABI=y
-CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
-CONFIG_FPE_NWFPE=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_NR_UARTS=3
-CONFIG_SERIAL_SAMSUNG=y
-CONFIG_SERIAL_SAMSUNG_CONSOLE=y
-CONFIG_HW_RANDOM=y
-# CONFIG_HWMON is not set
-CONFIG_DISPLAY_SUPPORT=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_INOTIFY=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_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=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_DEBUG_S3C_UART=1
-CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/s5p64x0_defconfig b/arch/arm/configs/s5p64x0_defconfig
new file mode 100644
index 0000000..2993ecd
--- /dev/null
+++ b/arch/arm/configs/s5p64x0_defconfig
@@ -0,0 +1,66 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSFS_DEPRECATED_V2=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_S5P64X0=y
+CONFIG_S3C_BOOT_ERROR_RESET=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_MACH_SMDK6440=y
+CONFIG_MACH_SMDK6450=y
+CONFIG_CPU_32v6K=y
+CONFIG_AEABI=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
+CONFIG_FPE_NWFPE=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_MISC_DEVICES is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_NR_UARTS=3
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+# CONFIG_HWMON is not set
+CONFIG_DISPLAY_SUPPORT=y
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_INOTIFY=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_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=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_DEBUG_S3C_UART=1
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/u300_defconfig b/arch/arm/configs/u300_defconfig
index 46e5e07..c1c252c 100644
--- a/arch/arm/configs/u300_defconfig
+++ b/arch/arm/configs/u300_defconfig
@@ -28,26 +28,9 @@
 CONFIG_FPE_NWFPE=y
 CONFIG_PM=y
 # CONFIG_SUSPEND is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD 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_NAND=y
-CONFIG_MTD_NAND_ECC_SMC=y
+# CONFIG_MISC_DEVICES is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
@@ -58,7 +41,6 @@
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
-CONFIG_POWER_SUPPLY=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_REGULATOR=y
@@ -66,24 +48,10 @@
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-# CONFIG_SND_SUPPORT_OLD_API is not set
-# CONFIG_SND_VERBOSE_PROCFS is not set
-# CONFIG_SND_DRIVERS is not set
-# CONFIG_SND_ARM is not set
-# CONFIG_SND_SPI is not set
-CONFIG_SND_SOC=y
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
-CONFIG_MMC_DEBUG=y
 CONFIG_MMC_ARMMMCI=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_BACKLIGHT=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_HCTOSYS is not set
 CONFIG_RTC_DRV_COH901331=y
@@ -93,12 +61,11 @@
 CONFIG_FUSE_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 6e8f05c..062b58c 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -154,16 +154,39 @@
 	.long	9999b,9001f;			\
 	.popsection
 
+#ifdef CONFIG_SMP
+#define ALT_SMP(instr...)					\
+9998:	instr
+#define ALT_UP(instr...)					\
+	.pushsection ".alt.smp.init", "a"			;\
+	.long	9998b						;\
+	instr							;\
+	.popsection
+#define ALT_UP_B(label)					\
+	.equ	up_b_offset, label - 9998b			;\
+	.pushsection ".alt.smp.init", "a"			;\
+	.long	9998b						;\
+	b	. + up_b_offset					;\
+	.popsection
+#else
+#define ALT_SMP(instr...)
+#define ALT_UP(instr...) instr
+#define ALT_UP_B(label) b label
+#endif
+
 /*
  * SMP data memory barrier
  */
 	.macro	smp_dmb
 #ifdef CONFIG_SMP
 #if __LINUX_ARM_ARCH__ >= 7
-	dmb
+	ALT_SMP(dmb)
 #elif __LINUX_ARM_ARCH__ == 6
-	mcr	p15, 0, r0, c7, c10, 5	@ dmb
+	ALT_SMP(mcr	p15, 0, r0, c7, c10, 5)	@ dmb
+#else
+#error Incompatible SMP platform
 #endif
+	ALT_UP(nop)
 #endif
 	.endm
 
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 4656a24..3acd8fa 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -137,10 +137,10 @@
 #endif
 
 /*
- * This flag is used to indicate that the page pointed to by a pte
- * is dirty and requires cleaning before returning it to the user.
+ * 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_dirty PG_arch_1
+#define PG_dcache_clean PG_arch_1
 
 /*
  *	MM Cache Management
@@ -156,6 +156,12 @@
  *	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.
@@ -206,6 +212,7 @@
  */
 
 struct cpu_cache_fns {
+	void (*flush_icache_all)(void);
 	void (*flush_kern_all)(void);
 	void (*flush_user_all)(void);
 	void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
@@ -227,6 +234,7 @@
 
 extern struct cpu_cache_fns cpu_cache;
 
+#define __cpuc_flush_icache_all		cpu_cache.flush_icache_all
 #define __cpuc_flush_kern_all		cpu_cache.flush_kern_all
 #define __cpuc_flush_user_all		cpu_cache.flush_user_all
 #define __cpuc_flush_user_range		cpu_cache.flush_user_range
@@ -246,6 +254,7 @@
 
 #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)
@@ -253,6 +262,7 @@
 #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);
 extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
@@ -291,6 +301,37 @@
 /*
  * Convert calls to our calling convention.
  */
+
+/* Invalidate I-cache */
+#define __flush_icache_all_generic()					\
+	asm("mcr	p15, 0, %0, c7, c5, 0"				\
+	    : : "r" (0));
+
+/* Invalidate I-cache inner shareable */
+#define __flush_icache_all_v7_smp()					\
+	asm("mcr	p15, 0, %0, c7, c1, 0"				\
+	    : : "r" (0));
+
+/*
+ * 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)) ||		\
+	defined(CONFIG_SMP_ON_UP)
+#define __flush_icache_preferred	__cpuc_flush_icache_all
+#elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
+#define __flush_icache_preferred	__flush_icache_all_v7_smp
+#elif __LINUX_ARM_ARCH__ == 6 && defined(CONFIG_ARM_ERRATA_411920)
+#define __flush_icache_preferred	__cpuc_flush_icache_all
+#else
+#define __flush_icache_preferred	__flush_icache_all_generic
+#endif
+
+static inline void __flush_icache_all(void)
+{
+	__flush_icache_preferred();
+}
+
 #define flush_cache_all()		__cpuc_flush_kern_all()
 
 static inline void vivt_flush_cache_mm(struct mm_struct *mm)
@@ -366,21 +407,6 @@
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 extern void flush_dcache_page(struct page *);
 
-static inline void __flush_icache_all(void)
-{
-#ifdef CONFIG_ARM_ERRATA_411920
-	extern void v6_icache_inval_all(void);
-	v6_icache_inval_all();
-#elif defined(CONFIG_SMP) && __LINUX_ARM_ARCH__ >= 7
-	asm("mcr	p15, 0, %0, c7, c1, 0	@ invalidate I-cache inner shareable\n"
-	    :
-	    : "r" (0));
-#else
-	asm("mcr	p15, 0, %0, c7, c5, 0	@ invalidate I-cache\n"
-	    :
-	    : "r" (0));
-#endif
-}
 static inline void flush_kernel_vmap_range(void *addr, int size)
 {
 	if ((cache_is_vivt() || cache_is_vipt_aliasing()))
@@ -405,9 +431,6 @@
 #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
 static inline void flush_kernel_dcache_page(struct page *page)
 {
-	/* highmem pages are always flushed upon kunmap already */
-	if ((cache_is_vivt() || cache_is_vipt_aliasing()) && !PageHighMem(page))
-		__cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
 }
 
 #define flush_dcache_mmap_lock(mapping) \
diff --git a/arch/arm/include/asm/cachetype.h b/arch/arm/include/asm/cachetype.h
index d3a4c2c..c023db0 100644
--- a/arch/arm/include/asm/cachetype.h
+++ b/arch/arm/include/asm/cachetype.h
@@ -6,6 +6,7 @@
 #define CACHEID_VIPT_ALIASING		(1 << 2)
 #define CACHEID_VIPT			(CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
 #define CACHEID_ASID_TAGGED		(1 << 3)
+#define CACHEID_VIPT_I_ALIASING		(1 << 4)
 
 extern unsigned int cacheid;
 
@@ -14,15 +15,18 @@
 #define cache_is_vipt_nonaliasing()	cacheid_is(CACHEID_VIPT_NONALIASING)
 #define cache_is_vipt_aliasing()	cacheid_is(CACHEID_VIPT_ALIASING)
 #define icache_is_vivt_asid_tagged()	cacheid_is(CACHEID_ASID_TAGGED)
+#define icache_is_vipt_aliasing()	cacheid_is(CACHEID_VIPT_I_ALIASING)
 
 /*
  * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
  * Mask out support which will never be present on newer CPUs.
  * - v6+ is never VIVT
- * - v7+ VIPT never aliases
+ * - v7+ VIPT never aliases on D-side
  */
 #if __LINUX_ARM_ARCH__ >= 7
-#define __CACHEID_ARCH_MIN	(CACHEID_VIPT_NONALIASING | CACHEID_ASID_TAGGED)
+#define __CACHEID_ARCH_MIN	(CACHEID_VIPT_NONALIASING |\
+				 CACHEID_ASID_TAGGED |\
+				 CACHEID_VIPT_I_ALIASING)
 #elif __LINUX_ARM_ARCH__ >= 6
 #define	__CACHEID_ARCH_MIN	(~CACHEID_VIVT)
 #else
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index 5747a8b..8bb66bc 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -127,4 +127,8 @@
 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/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index 103f7ee..f89515a 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -2,12 +2,30 @@
 #define _ASM_ARM_FTRACE
 
 #ifdef CONFIG_FUNCTION_TRACER
-#define MCOUNT_ADDR		((long)(mcount))
+#define MCOUNT_ADDR		((unsigned long)(__gnu_mcount_nc))
 #define MCOUNT_INSN_SIZE	4 /* sizeof mcount call */
 
 #ifndef __ASSEMBLY__
 extern void mcount(void);
 extern void __gnu_mcount_nc(void);
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+struct dyn_arch_ftrace {
+#ifdef CONFIG_OLD_MCOUNT
+	bool	old_mcount;
+#endif
+};
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/* With Thumb-2, the recorded addresses have the lsb set */
+	return addr & ~1;
+}
+
+extern void ftrace_caller_old(void);
+extern void ftrace_call_old(void);
+#endif
+
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 212e478..7ecd793 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -21,18 +21,6 @@
 #define TRACER_RUNNING		BIT(TRACER_RUNNING_BIT)
 #define TRACER_CYCLE_ACC	BIT(TRACER_CYCLE_ACC_BIT)
 
-struct tracectx {
-	unsigned int	etb_bufsz;
-	void __iomem	*etb_regs;
-	void __iomem	*etm_regs;
-	unsigned long	flags;
-	int		ncmppairs;
-	int		etm_portsz;
-	struct device	*dev;
-	struct clk	*emu_clk;
-	struct mutex	mutex;
-};
-
 #define TRACER_TIMEOUT 10000
 
 #define etm_writel(t, v, x) \
@@ -112,10 +100,10 @@
 
 /* ETM status register, "ETM Architecture", 3.3.2 */
 #define ETMR_STATUS		(0x10)
-#define ETMST_OVERFLOW		(1 << 0)
-#define ETMST_PROGBIT		(1 << 1)
-#define ETMST_STARTSTOP		(1 << 2)
-#define ETMST_TRIGGER		(1 << 3)
+#define ETMST_OVERFLOW		BIT(0)
+#define ETMST_PROGBIT		BIT(1)
+#define ETMST_STARTSTOP		BIT(2)
+#define ETMST_TRIGGER		BIT(3)
 
 #define etm_progbit(t)		(etm_readl((t), ETMR_STATUS) & ETMST_PROGBIT)
 #define etm_started(t)		(etm_readl((t), ETMR_STATUS) & ETMST_STARTSTOP)
@@ -123,7 +111,7 @@
 
 #define ETMR_TRACEENCTRL2	0x1c
 #define ETMR_TRACEENCTRL	0x24
-#define ETMTE_INCLEXCL		(1 << 24)
+#define ETMTE_INCLEXCL		BIT(24)
 #define ETMR_TRACEENEVT		0x20
 #define ETMCTRL_OPTS		(ETMCTRL_DO_CPRT | \
 				ETMCTRL_DATA_DO_ADDR | \
@@ -146,12 +134,12 @@
 #define ETBR_CTRL		0x20
 #define ETBR_FORMATTERCTRL	0x304
 #define ETBFF_ENFTC		1
-#define ETBFF_ENFCONT		(1 << 1)
-#define ETBFF_FONFLIN		(1 << 4)
-#define ETBFF_MANUAL_FLUSH	(1 << 6)
-#define ETBFF_TRIGIN		(1 << 8)
-#define ETBFF_TRIGEVT		(1 << 9)
-#define ETBFF_TRIGFL		(1 << 10)
+#define ETBFF_ENFCONT		BIT(1)
+#define ETBFF_FONFLIN		BIT(4)
+#define ETBFF_MANUAL_FLUSH	BIT(6)
+#define ETBFF_TRIGIN		BIT(8)
+#define ETBFF_TRIGEVT		BIT(9)
+#define ETBFF_TRIGFL		BIT(10)
 
 #define etb_writel(t, v, x) \
 	(__raw_writel((v), (t)->etb_regs + (x)))
diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h
new file mode 100644
index 0000000..4d8ae9d
--- /dev/null
+++ b/arch/arm/include/asm/hw_breakpoint.h
@@ -0,0 +1,133 @@
+#ifndef _ARM_HW_BREAKPOINT_H
+#define _ARM_HW_BREAKPOINT_H
+
+#ifdef __KERNEL__
+
+struct task_struct;
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+
+struct arch_hw_breakpoint_ctrl {
+		u32 __reserved	: 9,
+		mismatch	: 1,
+				: 9,
+		len		: 8,
+		type		: 2,
+		privilege	: 2,
+		enabled		: 1;
+};
+
+struct arch_hw_breakpoint {
+	u32	address;
+	u32	trigger;
+	struct perf_event *suspended_wp;
+	struct arch_hw_breakpoint_ctrl ctrl;
+};
+
+static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
+{
+	return (ctrl.mismatch << 22) | (ctrl.len << 5) | (ctrl.type << 3) |
+		(ctrl.privilege << 1) | ctrl.enabled;
+}
+
+static inline void decode_ctrl_reg(u32 reg,
+				   struct arch_hw_breakpoint_ctrl *ctrl)
+{
+	ctrl->enabled	= reg & 0x1;
+	reg >>= 1;
+	ctrl->privilege	= reg & 0x3;
+	reg >>= 2;
+	ctrl->type	= reg & 0x3;
+	reg >>= 2;
+	ctrl->len	= reg & 0xff;
+	reg >>= 17;
+	ctrl->mismatch	= reg & 0x1;
+}
+
+/* Debug architecture numbers. */
+#define ARM_DEBUG_ARCH_RESERVED	0	/* In case of ptrace ABI updates. */
+#define ARM_DEBUG_ARCH_V6	1
+#define ARM_DEBUG_ARCH_V6_1	2
+#define ARM_DEBUG_ARCH_V7_ECP14	3
+#define ARM_DEBUG_ARCH_V7_MM	4
+
+/* Breakpoint */
+#define ARM_BREAKPOINT_EXECUTE	0
+
+/* Watchpoints */
+#define ARM_BREAKPOINT_LOAD	1
+#define ARM_BREAKPOINT_STORE	2
+
+/* Privilege Levels */
+#define ARM_BREAKPOINT_PRIV	1
+#define ARM_BREAKPOINT_USER	2
+
+/* Lengths */
+#define ARM_BREAKPOINT_LEN_1	0x1
+#define ARM_BREAKPOINT_LEN_2	0x3
+#define ARM_BREAKPOINT_LEN_4	0xf
+#define ARM_BREAKPOINT_LEN_8	0xff
+
+/* Limits */
+#define ARM_MAX_BRP		16
+#define ARM_MAX_WRP		16
+#define ARM_MAX_HBP_SLOTS	(ARM_MAX_BRP + ARM_MAX_WRP)
+
+/* DSCR method of entry bits. */
+#define ARM_DSCR_MOE(x)			((x >> 2) & 0xf)
+#define ARM_ENTRY_BREAKPOINT		0x1
+#define ARM_ENTRY_ASYNC_WATCHPOINT	0x2
+#define ARM_ENTRY_SYNC_WATCHPOINT	0xa
+
+/* DSCR monitor/halting bits. */
+#define ARM_DSCR_HDBGEN		(1 << 14)
+#define ARM_DSCR_MDBGEN		(1 << 15)
+
+/* opcode2 numbers for the co-processor instructions. */
+#define ARM_OP2_BVR		4
+#define ARM_OP2_BCR		5
+#define ARM_OP2_WVR		6
+#define ARM_OP2_WCR		7
+
+/* Base register numbers for the debug registers. */
+#define ARM_BASE_BVR		64
+#define ARM_BASE_BCR		80
+#define ARM_BASE_WVR		96
+#define ARM_BASE_WCR		112
+
+/* Accessor macros for the debug registers. */
+#define ARM_DBG_READ(M, OP2, VAL) do {\
+	asm volatile("mrc p14, 0, %0, c0," #M ", " #OP2 : "=r" (VAL));\
+} while (0)
+
+#define ARM_DBG_WRITE(M, OP2, VAL) do {\
+	asm volatile("mcr p14, 0, %0, c0," #M ", " #OP2 : : "r" (VAL));\
+} while (0)
+
+struct notifier_block;
+struct perf_event;
+struct pmu;
+
+extern struct pmu perf_ops_bp;
+extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
+				  int *gen_len, int *gen_type);
+extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
+extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
+extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+					   unsigned long val, void *data);
+
+extern u8 arch_get_debug_arch(void);
+extern u8 arch_get_max_wp_len(void);
+extern void clear_ptrace_hw_breakpoint(struct task_struct *tsk);
+
+int arch_install_hw_breakpoint(struct perf_event *bp);
+void arch_uninstall_hw_breakpoint(struct perf_event *bp);
+void hw_breakpoint_pmu_read(struct perf_event *bp);
+int hw_breakpoint_slots(int type);
+
+#else
+static inline void clear_ptrace_hw_breakpoint(struct task_struct *tsk) {}
+
+#endif	/* CONFIG_HAVE_HW_BREAKPOINT */
+#endif	/* __KERNEL__ */
+#endif	/* _ARM_HW_BREAKPOINT_H */
diff --git a/arch/arm/include/asm/hw_irq.h b/arch/arm/include/asm/hw_irq.h
index 90831f6..5586b7c 100644
--- a/arch/arm/include/asm/hw_irq.h
+++ b/arch/arm/include/asm/hw_irq.h
@@ -24,4 +24,6 @@
 #define IRQF_PROBE	(1 << 1)
 #define IRQF_NOAUTOEN	(1 << 2)
 
+#define ARCH_IRQ_INIT_FLAGS	(IRQ_NOREQUEST | IRQ_NOPROBE)
+
 #endif
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 1261b1f9..815efa2 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -294,6 +294,7 @@
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
 extern int valid_phys_addr_range(unsigned long addr, size_t size);
 extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+extern int devmem_is_allowed(unsigned long pfn);
 #endif
 
 /*
diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h
index 0b30894..9c96298 100644
--- a/arch/arm/include/asm/ioctls.h
+++ b/arch/arm/include/asm/ioctls.h
@@ -1,89 +1,8 @@
 #ifndef __ASM_ARM_IOCTLS_H
 #define __ASM_ARM_IOCTLS_H
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define TIOCGRS485      0x542E
-#define TIOCSRS485      0x542F
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define FIOQSIZE	0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT	0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif
diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h
index 6d09974..1e6cca5 100644
--- a/arch/arm/include/asm/irqflags.h
+++ b/arch/arm/include/asm/irqflags.h
@@ -10,66 +10,85 @@
  */
 #if __LINUX_ARM_ARCH__ >= 6
 
-#define raw_local_irq_save(x)					\
-	({							\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ local_irq_save\n"	\
-	"cpsid	i"						\
-	: "=r" (x) : : "memory", "cc");				\
-	})
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
 
-#define raw_local_irq_enable()  __asm__("cpsie i	@ __sti" : : : "memory", "cc")
-#define raw_local_irq_disable() __asm__("cpsid i	@ __cli" : : : "memory", "cc")
+	asm volatile(
+		"	mrs	%0, cpsr	@ arch_local_irq_save\n"
+		"	cpsid	i"
+		: "=r" (flags) : : "memory", "cc");
+	return flags;
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	asm volatile(
+		"	cpsie i			@ arch_local_irq_enable"
+		:
+		:
+		: "memory", "cc");
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	asm volatile(
+		"	cpsid i			@ arch_local_irq_disable"
+		:
+		:
+		: "memory", "cc");
+}
+
 #define local_fiq_enable()  __asm__("cpsie f	@ __stf" : : : "memory", "cc")
 #define local_fiq_disable() __asm__("cpsid f	@ __clf" : : : "memory", "cc")
-
 #else
 
 /*
  * Save the current interrupt enable state & disable IRQs
  */
-#define raw_local_irq_save(x)					\
-	({							\
-		unsigned long temp;				\
-		(void) (&temp == &x);				\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ local_irq_save\n"	\
-"	orr	%1, %0, #128\n"					\
-"	msr	cpsr_c, %1"					\
-	: "=r" (x), "=r" (temp)					\
-	:							\
-	: "memory", "cc");					\
-	})
-	
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags, temp;
+
+	asm volatile(
+		"	mrs	%0, cpsr	@ arch_local_irq_save\n"
+		"	orr	%1, %0, #128\n"
+		"	msr	cpsr_c, %1"
+		: "=r" (flags), "=r" (temp)
+		:
+		: "memory", "cc");
+	return flags;
+}
+
 /*
  * Enable IRQs
  */
-#define raw_local_irq_enable()					\
-	({							\
-		unsigned long temp;				\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ local_irq_enable\n"	\
-"	bic	%0, %0, #128\n"					\
-"	msr	cpsr_c, %0"					\
-	: "=r" (temp)						\
-	:							\
-	: "memory", "cc");					\
-	})
+static inline void arch_local_irq_enable(void)
+{
+	unsigned long temp;
+	asm volatile(
+		"	mrs	%0, cpsr	@ arch_local_irq_enable\n"
+		"	bic	%0, %0, #128\n"
+		"	msr	cpsr_c, %0"
+		: "=r" (temp)
+		:
+		: "memory", "cc");
+}
 
 /*
  * Disable IRQs
  */
-#define raw_local_irq_disable()					\
-	({							\
-		unsigned long temp;				\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ local_irq_disable\n"	\
-"	orr	%0, %0, #128\n"					\
-"	msr	cpsr_c, %0"					\
-	: "=r" (temp)						\
-	:							\
-	: "memory", "cc");					\
-	})
+static inline void arch_local_irq_disable(void)
+{
+	unsigned long temp;
+	asm volatile(
+		"	mrs	%0, cpsr	@ arch_local_irq_disable\n"
+		"	orr	%0, %0, #128\n"
+		"	msr	cpsr_c, %0"
+		: "=r" (temp)
+		:
+		: "memory", "cc");
+}
 
 /*
  * Enable FIQs
@@ -106,27 +125,31 @@
 /*
  * Save the current interrupt enable state.
  */
-#define raw_local_save_flags(x)					\
-	({							\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ local_save_flags"	\
-	: "=r" (x) : : "memory", "cc");				\
-	})
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile(
+		"	mrs	%0, cpsr	@ local_save_flags"
+		: "=r" (flags) : : "memory", "cc");
+	return flags;
+}
 
 /*
  * restore saved IRQ & FIQ state
  */
-#define raw_local_irq_restore(x)				\
-	__asm__ __volatile__(					\
-	"msr	cpsr_c, %0		@ local_irq_restore\n"	\
-	:							\
-	: "r" (x)						\
-	: "memory", "cc")
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile(
+		"	msr	cpsr_c, %0	@ local_irq_restore"
+		:
+		: "r" (flags)
+		: "memory", "cc");
+}
 
-#define raw_irqs_disabled_flags(flags)	\
-({					\
-	(int)((flags) & PSR_I_BIT);	\
-})
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+	return flags & PSR_I_BIT;
+}
 
 #endif
 #endif
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 8a0dd18..d97a964 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -16,18 +16,15 @@
 
 struct machine_desc {
 	/*
-	 * Note! The first four elements are used
+	 * Note! The first two elements are used
 	 * by assembler code in head.S, head-common.S
 	 */
 	unsigned int		nr;		/* architecture number	*/
-	unsigned int		nr_irqs;	/* number of IRQs */
-	unsigned int		phys_io;	/* start of physical io	*/
-	unsigned int		io_pg_offst;	/* byte offset for io 
-						 * page tabe entry	*/
-
 	const char		*name;		/* architecture name	*/
 	unsigned long		boot_params;	/* tagged list		*/
 
+	unsigned int		nr_irqs;	/* number of IRQs */
+
 	unsigned int		video_start;	/* start of video RAM	*/
 	unsigned int		video_end;	/* end of video RAM	*/
 
diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h
index a0b3cac..71605d9 100644
--- a/arch/arm/include/asm/mmu_context.h
+++ b/arch/arm/include/asm/mmu_context.h
@@ -18,7 +18,6 @@
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
 #include <asm/proc-fns.h>
-#include <asm-generic/mm_hooks.h>
 
 void __check_kvm_seq(struct mm_struct *mm);
 
@@ -134,4 +133,32 @@
 #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/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index e4dfa69..cbb0bc2 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -7,20 +7,27 @@
 
 struct unwind_table;
 
-struct mod_arch_specific
-{
 #ifdef CONFIG_ARM_UNWIND
-	Elf_Shdr *unw_sec_init;
-	Elf_Shdr *unw_sec_devinit;
-	Elf_Shdr *unw_sec_core;
-	Elf_Shdr *sec_init_text;
-	Elf_Shdr *sec_devinit_text;
-	Elf_Shdr *sec_core_text;
-	struct unwind_table *unwind_init;
-	struct unwind_table *unwind_devinit;
-	struct unwind_table *unwind_core;
-#endif
+struct arm_unwind_mapping {
+	Elf_Shdr *unw_sec;
+	Elf_Shdr *sec_text;
+	struct unwind_table *unwind;
 };
+enum {
+	ARM_SEC_INIT,
+	ARM_SEC_DEVINIT,
+	ARM_SEC_CORE,
+	ARM_SEC_EXIT,
+	ARM_SEC_DEVEXIT,
+	ARM_SEC_MAX,
+};
+struct mod_arch_specific {
+	struct arm_unwind_mapping map[ARM_SEC_MAX];
+};
+#else
+struct mod_arch_specific {
+};
+#endif
 
 /*
  * Include the ARM architecture version.
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index b5799a3..c4aa4e8 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -12,18 +12,6 @@
 #ifndef __ARM_PERF_EVENT_H__
 #define __ARM_PERF_EVENT_H__
 
-/*
- * NOP: on *most* (read: all supported) ARM platforms, the performance
- * counter interrupts are regular interrupts and not an NMI. This
- * means that when we receive the interrupt we can call
- * perf_event_do_pending() that handles all of the work with
- * interrupts disabled.
- */
-static inline void
-set_perf_event_pending(void)
-{
-}
-
 /* ARM performance counters start from 1 (in the cp15 accesses) so use the
  * same indexes here for consistency. */
 #define PERF_EVENT_INDEX_OFFSET 1
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index ab68cf1..a9672e8 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -278,9 +278,24 @@
 
 #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
 
-#define set_pte_at(mm,addr,ptep,pteval) do { \
-	set_pte_ext(ptep, pteval, (addr) >= TASK_SIZE ? 0 : PTE_EXT_NG); \
- } while (0)
+#if __LINUX_ARM_ARCH__ < 6
+static inline void __sync_icache_dcache(pte_t pteval)
+{
+}
+#else
+extern void __sync_icache_dcache(pte_t pteval);
+#endif
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep, pte_t pteval)
+{
+	if (addr >= TASK_SIZE)
+		set_pte_ext(ptep, pteval, 0);
+	else {
+		__sync_icache_dcache(pteval);
+		set_pte_ext(ptep, pteval, PTE_EXT_NG);
+	}
+}
 
 /*
  * The following only work if pte_present() is true.
@@ -290,8 +305,13 @@
 #define pte_write(pte)		(pte_val(pte) & L_PTE_WRITE)
 #define pte_dirty(pte)		(pte_val(pte) & L_PTE_DIRTY)
 #define pte_young(pte)		(pte_val(pte) & L_PTE_YOUNG)
+#define pte_exec(pte)		(pte_val(pte) & L_PTE_EXEC)
 #define pte_special(pte)	(0)
 
+#define pte_present_user(pte) \
+	((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \
+	 (L_PTE_PRESENT | L_PTE_USER))
+
 #define PTE_BIT_FUNC(fn,op) \
 static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
 
@@ -317,6 +337,10 @@
 #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
 #define pgprot_dmacoherent(prot) \
 	__pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE)
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+				     unsigned long size, pgprot_t vma_prot);
 #else
 #define pgprot_dmacoherent(prot) \
 	__pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_UNCACHED)
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 7bed3da..67357ba 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -19,6 +19,7 @@
 
 #ifdef __KERNEL__
 
+#include <asm/hw_breakpoint.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
 
@@ -41,6 +42,9 @@
 struct debug_info {
 	int			nsaved;
 	struct debug_entry	bp[2];
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+	struct perf_event	*hbp[ARM_MAX_HBP_SLOTS];
+#endif
 };
 
 struct thread_struct {
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 7ce15eb..783d50f 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -29,6 +29,8 @@
 #define PTRACE_SETCRUNCHREGS	26
 #define PTRACE_GETVFPREGS	27
 #define PTRACE_SETVFPREGS	28
+#define PTRACE_GETHBPREGS	29
+#define PTRACE_SETHBPREGS	30
 
 /*
  * PSR bits
diff --git a/arch/arm/include/asm/seccomp.h b/arch/arm/include/asm/seccomp.h
new file mode 100644
index 0000000..52b156b
--- /dev/null
+++ b/arch/arm/include/asm/seccomp.h
@@ -0,0 +1,11 @@
+#ifndef _ASM_ARM_SECCOMP_H
+#define _ASM_ARM_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#endif /* _ASM_ARM_SECCOMP_H */
diff --git a/arch/arm/include/asm/smp_mpidr.h b/arch/arm/include/asm/smp_mpidr.h
new file mode 100644
index 0000000..6a9307d
--- /dev/null
+++ b/arch/arm/include/asm/smp_mpidr.h
@@ -0,0 +1,17 @@
+#ifndef ASMARM_SMP_MIDR_H
+#define ASMARM_SMP_MIDR_H
+
+#define hard_smp_processor_id()						\
+	({								\
+		unsigned int cpunum;					\
+		__asm__("\n"						\
+			"1:	mrc p15, 0, %0, c0, c0, 5\n"		\
+			"	.pushsection \".alt.smp.init\", \"a\"\n"\
+			"	.long	1b\n"				\
+			"	mov	%0, #0\n"			\
+			"	.popsection"				\
+			: "=r" (cpunum));				\
+		cpunum &= 0x0F;						\
+	})
+
+#endif
diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h
index e621530..f24c1b9 100644
--- a/arch/arm/include/asm/smp_plat.h
+++ b/arch/arm/include/asm/smp_plat.h
@@ -7,15 +7,40 @@
 
 #include <asm/cputype.h>
 
+/*
+ * Return true if we are running on a SMP platform
+ */
+static inline bool is_smp(void)
+{
+#ifndef CONFIG_SMP
+	return false;
+#elif defined(CONFIG_SMP_ON_UP)
+	extern unsigned int smp_on_up;
+	return !!smp_on_up;
+#else
+	return true;
+#endif
+}
+
 /* all SMP configurations have the extended CPUID registers */
 static inline int tlb_ops_need_broadcast(void)
 {
+	if (!is_smp())
+		return 0;
+
 	return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
 }
 
+#if !defined(CONFIG_SMP) || __LINUX_ARM_ARCH__ >= 7
+#define cache_ops_need_broadcast()	0
+#else
 static inline int cache_ops_need_broadcast(void)
 {
+	if (!is_smp())
+		return 0;
+
 	return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1;
 }
+#endif
 
 #endif
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 8ba1ccf..1120f18 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -85,6 +85,10 @@
 				       struct pt_regs *),
 		     int sig, int code, const char *name);
 
+void hook_ifault_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))))
 
@@ -325,6 +329,8 @@
 extern void disable_hlt(void);
 extern void enable_hlt(void);
 
+void cpu_idle_wait(void);
+
 #include <asm-generic/cmpxchg-local.h>
 
 #if __LINUX_ARM_ARCH__ < 6
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 763e29f..7b5cc8d 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -144,6 +144,7 @@
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_FREEZE		19
 #define TIF_RESTORE_SIGMASK	20
+#define TIF_SECCOMP		21
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
@@ -153,6 +154,7 @@
 #define _TIF_USING_IWMMXT	(1 << TIF_USING_IWMMXT)
 #define _TIF_FREEZE		(1 << TIF_FREEZE)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+#define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 
 /*
  * Change these and you break ASM code in entry-common.S
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index 33b546a..ce7378ea 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -70,6 +70,10 @@
 #undef _TLB
 #undef MULTI_TLB
 
+#ifdef CONFIG_SMP_ON_UP
+#define MULTI_TLB 1
+#endif
+
 #define v3_tlb_flags	(TLB_V3_FULL | TLB_V3_PAGE)
 
 #ifdef CONFIG_CPU_TLB_V3
@@ -185,17 +189,23 @@
 # define v6wbi_always_flags	(-1UL)
 #endif
 
-#ifdef CONFIG_SMP
-#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
+#define v7wbi_tlb_flags_smp	(TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
 			 TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
-#else
-#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
+#define v7wbi_tlb_flags_up	(TLB_WB | TLB_DCLEAN | TLB_BTB | \
 			 TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID)
-#endif
 
 #ifdef CONFIG_CPU_TLB_V7
-# define v7wbi_possible_flags	v7wbi_tlb_flags
-# define v7wbi_always_flags	v7wbi_tlb_flags
+
+# ifdef CONFIG_SMP_ON_UP
+#  define v7wbi_possible_flags	(v7wbi_tlb_flags_smp | v7wbi_tlb_flags_up)
+#  define v7wbi_always_flags	(v7wbi_tlb_flags_smp & v7wbi_tlb_flags_up)
+# elif defined(CONFIG_SMP)
+#  define v7wbi_possible_flags	v7wbi_tlb_flags_smp
+#  define v7wbi_always_flags	v7wbi_tlb_flags_smp
+# else
+#  define v7wbi_possible_flags	v7wbi_tlb_flags_up
+#  define v7wbi_always_flags	v7wbi_tlb_flags_up
+# endif
 # ifdef _TLB
 #  define MULTI_TLB 1
 # else
@@ -560,12 +570,20 @@
 #endif
 
 /*
- * if PG_dcache_dirty is set for the page, we need to ensure that any
+ * 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.
+ * back to the page. On ARMv6 and later, the cache coherency is handled via
+ * the set_pte_at() function.
  */
+#if __LINUX_ARM_ARCH__ < 6
 extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
 	pte_t *ptep);
+#else
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+				    unsigned long addr, pte_t *ptep)
+{
+}
+#endif
 
 #endif
 
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 980b78e..5b9b268 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -42,6 +42,7 @@
 obj-$(CONFIG_ARM_UNWIND)	+= unwind.o
 obj-$(CONFIG_HAVE_TCM)		+= tcm.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
+obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= hw_breakpoint.o
 
 obj-$(CONFIG_CRUNCH)		+= crunch.o crunch-bits.o
 AFLAGS_crunch-bits.o		:= -Wa,-mcpu=ep9312
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 8214bfe..e5e1e53 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -165,6 +165,8 @@
 #endif
 
 #ifdef CONFIG_FUNCTION_TRACER
+#ifdef CONFIG_OLD_MCOUNT
 EXPORT_SYMBOL(mcount);
+#endif
 EXPORT_SYMBOL(__gnu_mcount_nc);
 #endif
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 85f2a01..82da661 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -102,8 +102,6 @@
   DEFINE(SIZEOF_MACHINE_DESC,	sizeof(struct machine_desc));
   DEFINE(MACHINFO_TYPE,		offsetof(struct machine_desc, nr));
   DEFINE(MACHINFO_NAME,		offsetof(struct machine_desc, name));
-  DEFINE(MACHINFO_PHYSIO,	offsetof(struct machine_desc, phys_io));
-  DEFINE(MACHINFO_PGOFFIO,	offsetof(struct machine_desc, io_pg_offst));
   BLANK();
   DEFINE(PROC_INFO_SZ,		sizeof(struct proc_info_list));
   DEFINE(PROCINFO_INITFUNC,	offsetof(struct proc_info_list, __cpu_flush));
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index a38b487..a0f0752 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -22,11 +22,11 @@
 #if defined(CONFIG_DEBUG_ICEDCC)
 		@@ debug using ARM EmbeddedICE DCC channel
 
-#if defined(CONFIG_CPU_V6)
-
-		.macro	addruart, rx, tmp
+		.macro	addruart, rp, rv
 		.endm
 
+#if defined(CONFIG_CPU_V6)
+
 		.macro	senduart, rd, rx
 		mcr	p14, 0, \rd, c0, c5, 0
 		.endm
@@ -51,9 +51,6 @@
 
 #elif defined(CONFIG_CPU_V7)
 
-		.macro	addruart, rx, tmp
-		.endm
-
 		.macro	senduart, rd, rx
 		mcr	p14, 0, \rd, c0, c5, 0
 		.endm
@@ -71,9 +68,6 @@
 
 #elif defined(CONFIG_CPU_XSCALE)
 
-		.macro	addruart, rx, tmp
-		.endm
-
 		.macro	senduart, rd, rx
 		mcr	p14, 0, \rd, c8, c0, 0
 		.endm
@@ -98,9 +92,6 @@
 
 #else
 
-		.macro	addruart, rx, tmp
-		.endm
-
 		.macro	senduart, rd, rx
 		mcr	p14, 0, \rd, c1, c0, 0
 		.endm
@@ -130,6 +121,22 @@
 #include <mach/debug-macro.S>
 #endif	/* CONFIG_DEBUG_ICEDCC */
 
+#ifdef CONFIG_MMU
+		.macro	addruart_current, rx, tmp1, tmp2
+		addruart	\tmp1, \tmp2
+		mrc		p15, 0, \rx, c1, c0
+		tst		\rx, #1
+		moveq		\rx, \tmp1
+		movne		\rx, \tmp2
+		.endm
+
+#else /* !CONFIG_MMU */
+		.macro	addruart_current, rx, tmp1, tmp2
+		addruart	\rx, \tmp1
+		.endm
+
+#endif /* CONFIG_MMU */
+
 /*
  * Useful debugging routines
  */
@@ -164,7 +171,7 @@
 		.ltorg
 
 ENTRY(printascii)
-		addruart r3, r1
+		addruart_current r3, r1, r2
 		b	2f
 1:		waituart r2, r3
 		senduart r1, r3
@@ -180,7 +187,7 @@
 ENDPROC(printascii)
 
 ENTRY(printch)
-		addruart r3, r1
+		addruart_current r3, r1, r2
 		mov	r1, r0
 		mov	r0, #0
 		b	1b
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index bb8e93a..c09e357 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -46,7 +46,8 @@
 	 * this macro assumes that irqstat (r6) and base (r5) are
 	 * preserved from get_irqnr_and_base above
 	 */
-	test_for_ipi r0, r6, r5, lr
+	ALT_SMP(test_for_ipi r0, r6, r5, lr)
+	ALT_UP_B(9997f)
 	movne	r0, sp
 	adrne	lr, BSYM(1b)
 	bne	do_IPI
@@ -57,6 +58,7 @@
 	adrne	lr, BSYM(1b)
 	bne	do_local_timer
 #endif
+9997:
 #endif
 
 	.endm
@@ -965,11 +967,8 @@
 	beq	1b
 	rsbs	r0, r3, #0
 	/* beware -- each __kuser slot must be 8 instructions max */
-#ifdef CONFIG_SMP
-	b	__kuser_memory_barrier
-#else
-	usr_ret	lr
-#endif
+	ALT_SMP(b	__kuser_memory_barrier)
+	ALT_UP(usr_ret	lr)
 
 #endif
 
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 1b560825..8bfa987 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -48,6 +48,8 @@
 	beq	no_work_pending
 	mov	r0, sp				@ 'regs'
 	mov	r2, why				@ 'syscall'
+	tst	r1, #_TIF_SIGPENDING		@ delivering a signal?
+	movne	why, #0				@ prevent further restarts
 	bl	do_notify_resume
 	b	ret_slow_syscall		@ Check work again
 
@@ -127,30 +129,58 @@
  * clobber the ip register.  This is OK because the ARM calling convention
  * allows it to be clobbered in subroutines and doesn't use it to hold
  * parameters.)
+ *
+ * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0"
+ * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see
+ * arch/arm/kernel/ftrace.c).
  */
+
+#ifndef CONFIG_OLD_MCOUNT
+#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
+#error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0.
+#endif
+#endif
+
 #ifdef CONFIG_DYNAMIC_FTRACE
-ENTRY(mcount)
+ENTRY(__gnu_mcount_nc)
+	mov	ip, lr
+	ldmia	sp!, {lr}
+	mov	pc, ip
+ENDPROC(__gnu_mcount_nc)
+
+ENTRY(ftrace_caller)
 	stmdb	sp!, {r0-r3, lr}
 	mov	r0, lr
 	sub	r0, r0, #MCOUNT_INSN_SIZE
+	ldr	r1, [sp, #20]
 
-	.globl mcount_call
-mcount_call:
+	.global	ftrace_call
+ftrace_call:
 	bl	ftrace_stub
-	ldr	lr, [fp, #-4]			@ restore lr
-	ldmia	sp!, {r0-r3, pc}
+	ldmia	sp!, {r0-r3, ip, lr}
+	mov	pc, ip
+ENDPROC(ftrace_caller)
 
-ENTRY(ftrace_caller)
+#ifdef CONFIG_OLD_MCOUNT
+ENTRY(mcount)
+	stmdb	sp!, {lr}
+	ldr	lr, [fp, #-4]
+	ldmia	sp!, {pc}
+ENDPROC(mcount)
+
+ENTRY(ftrace_caller_old)
 	stmdb	sp!, {r0-r3, lr}
 	ldr	r1, [fp, #-4]
 	mov	r0, lr
 	sub	r0, r0, #MCOUNT_INSN_SIZE
 
-	.globl ftrace_call
-ftrace_call:
+	.globl ftrace_call_old
+ftrace_call_old:
 	bl	ftrace_stub
 	ldr	lr, [fp, #-4]			@ restore lr
 	ldmia	sp!, {r0-r3, pc}
+ENDPROC(ftrace_caller_old)
+#endif
 
 #else
 
@@ -158,7 +188,7 @@
 	stmdb	sp!, {r0-r3, lr}
 	ldr	r0, =ftrace_trace_function
 	ldr	r2, [r0]
-	adr	r0, ftrace_stub
+	adr	r0, .Lftrace_stub
 	cmp	r0, r2
 	bne	gnu_trace
 	ldmia	sp!, {r0-r3, ip, lr}
@@ -168,11 +198,19 @@
 	ldr	r1, [sp, #20]			@ lr of instrumented routine
 	mov	r0, lr
 	sub	r0, r0, #MCOUNT_INSN_SIZE
-	mov	lr, pc
+	adr	lr, BSYM(1f)
 	mov	pc, r2
+1:
 	ldmia	sp!, {r0-r3, ip, lr}
 	mov	pc, ip
+ENDPROC(__gnu_mcount_nc)
 
+#ifdef CONFIG_OLD_MCOUNT
+/*
+ * This is under an ifdef in order to force link-time errors for people trying
+ * to build with !FRAME_POINTER with a GCC which doesn't use the new-style
+ * mcount.
+ */
 ENTRY(mcount)
 	stmdb	sp!, {r0-r3, lr}
 	ldr	r0, =ftrace_trace_function
@@ -191,12 +229,15 @@
 	mov	pc, r2
 	ldr	lr, [fp, #-4]			@ restore lr
 	ldmia	sp!, {r0-r3, pc}
+ENDPROC(mcount)
+#endif
 
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
-	.globl ftrace_stub
-ftrace_stub:
+ENTRY(ftrace_stub)
+.Lftrace_stub:
 	mov	pc, lr
+ENDPROC(ftrace_stub)
 
 #endif /* CONFIG_FUNCTION_TRACER */
 
@@ -293,7 +334,6 @@
 
 	get_thread_info tsk
 	adr	tbl, sys_call_table		@ load syscall table pointer
-	ldr	ip, [tsk, #TI_FLAGS]		@ check for syscall tracing
 
 #if defined(CONFIG_OABI_COMPAT)
 	/*
@@ -310,8 +350,20 @@
 	eor	scno, scno, #__NR_SYSCALL_BASE	@ check OS number
 #endif
 
+	ldr	r10, [tsk, #TI_FLAGS]		@ check for syscall tracing
 	stmdb	sp!, {r4, r5}			@ push fifth and sixth args
-	tst	ip, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
+
+#ifdef CONFIG_SECCOMP
+	tst	r10, #_TIF_SECCOMP
+	beq	1f
+	mov	r0, scno
+	bl	__secure_computing	
+	add	r0, sp, #S_R0 + S_OFF		@ pointer to regs
+	ldmia	r0, {r0 - r3}			@ have to reload r0 - r3
+1:
+#endif
+
+	tst	r10, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
 	bne	__sys_trace
 
 	cmp	scno, #NR_syscalls		@ check upper syscall limit
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 33c7077..11db628 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -30,6 +30,21 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alexander Shishkin");
 
+/*
+ * ETM tracer state
+ */
+struct tracectx {
+	unsigned int	etb_bufsz;
+	void __iomem	*etb_regs;
+	void __iomem	*etm_regs;
+	unsigned long	flags;
+	int		ncmppairs;
+	int		etm_portsz;
+	struct device	*dev;
+	struct clk	*emu_clk;
+	struct mutex	mutex;
+};
+
 static struct tracectx tracer;
 
 static inline bool trace_isrunning(struct tracectx *t)
@@ -314,6 +329,7 @@
 	.read = etb_read,
 	.open = etb_open,
 	.release = etb_release,
+	.llseek = no_llseek,
 };
 
 static struct miscdevice etb_miscdev = {
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c
index 0298286..971ac8c 100644
--- a/arch/arm/kernel/ftrace.c
+++ b/arch/arm/kernel/ftrace.c
@@ -2,102 +2,194 @@
  * Dynamic function tracing support.
  *
  * Copyright (C) 2008 Abhishek Sagar <sagar.abhishek@gmail.com>
+ * Copyright (C) 2010 Rabin Vincent <rabin@rab.in>
  *
  * For licencing details, see COPYING.
  *
  * Defines low-level handling of mcount calls when the kernel
  * is compiled with the -pg flag. When using dynamic ftrace, the
- * mcount call-sites get patched lazily with NOP till they are
- * enabled. All code mutation routines here take effect atomically.
+ * mcount call-sites get patched with NOP till they are enabled.
+ * All code mutation routines here are called under stop_machine().
  */
 
 #include <linux/ftrace.h>
+#include <linux/uaccess.h>
 
 #include <asm/cacheflush.h>
 #include <asm/ftrace.h>
 
-#define PC_OFFSET      8
-#define BL_OPCODE      0xeb000000
-#define BL_OFFSET_MASK 0x00ffffff
+#ifdef CONFIG_THUMB2_KERNEL
+#define	NOP		0xeb04f85d	/* pop.w {lr} */
+#else
+#define	NOP		0xe8bd4000	/* pop {lr} */
+#endif
 
-static unsigned long bl_insn;
-static const unsigned long NOP = 0xe1a00000; /* mov r0, r0 */
+#ifdef CONFIG_OLD_MCOUNT
+#define OLD_MCOUNT_ADDR	((unsigned long) mcount)
+#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)
 
-unsigned char *ftrace_nop_replace(void)
+#define	OLD_NOP		0xe1a00000	/* mov r0, r0 */
+
+static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
 {
-	return (char *)&NOP;
+	return rec->arch.old_mcount ? OLD_NOP : NOP;
 }
 
+static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
+{
+	if (!rec->arch.old_mcount)
+		return addr;
+
+	if (addr == MCOUNT_ADDR)
+		addr = OLD_MCOUNT_ADDR;
+	else if (addr == FTRACE_ADDR)
+		addr = OLD_FTRACE_ADDR;
+
+	return addr;
+}
+#else
+static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
+{
+	return NOP;
+}
+
+static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
+{
+	return addr;
+}
+#endif
+
 /* construct a branch (BL) instruction to addr */
-unsigned char *ftrace_call_replace(unsigned long pc, unsigned long addr)
+#ifdef CONFIG_THUMB2_KERNEL
+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
+{
+	unsigned long s, j1, j2, i1, i2, imm10, imm11;
+	unsigned long first, second;
+	long offset;
+
+	offset = (long)addr - (long)(pc + 4);
+	if (offset < -16777216 || offset > 16777214) {
+		WARN_ON_ONCE(1);
+		return 0;
+	}
+
+	s	= (offset >> 24) & 0x1;
+	i1	= (offset >> 23) & 0x1;
+	i2	= (offset >> 22) & 0x1;
+	imm10	= (offset >> 12) & 0x3ff;
+	imm11	= (offset >>  1) & 0x7ff;
+
+	j1 = (!i1) ^ s;
+	j2 = (!i2) ^ s;
+
+	first = 0xf000 | (s << 10) | imm10;
+	second = 0xd000 | (j1 << 13) | (j2 << 11) | imm11;
+
+	return (second << 16) | first;
+}
+#else
+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
 {
 	long offset;
 
-	offset = (long)addr - (long)(pc + PC_OFFSET);
+	offset = (long)addr - (long)(pc + 8);
 	if (unlikely(offset < -33554432 || offset > 33554428)) {
 		/* Can't generate branches that far (from ARM ARM). Ftrace
 		 * doesn't generate branches outside of kernel text.
 		 */
 		WARN_ON_ONCE(1);
-		return NULL;
+		return 0;
 	}
-	offset = (offset >> 2) & BL_OFFSET_MASK;
-	bl_insn = BL_OPCODE | offset;
-	return (unsigned char *)&bl_insn;
+
+	offset = (offset >> 2) & 0x00ffffff;
+
+	return 0xeb000000 | offset;
 }
+#endif
 
-int ftrace_modify_code(unsigned long pc, unsigned char *old_code,
-		       unsigned char *new_code)
+static int ftrace_modify_code(unsigned long pc, unsigned long old,
+			      unsigned long new)
 {
-	unsigned long err = 0, replaced = 0, old, new;
+	unsigned long replaced;
 
-	old = *(unsigned long *)old_code;
-	new = *(unsigned long *)new_code;
+	if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
+		return -EFAULT;
 
-	__asm__ __volatile__ (
-		"1:  ldr    %1, [%2]  \n"
-		"    cmp    %1, %4    \n"
-		"2:  streq  %3, [%2]  \n"
-		"    cmpne  %1, %3    \n"
-		"    movne  %0, #2    \n"
-		"3:\n"
+	if (replaced != old)
+		return -EINVAL;
 
-		".pushsection .fixup, \"ax\"\n"
-		"4:  mov  %0, #1  \n"
-		"    b    3b      \n"
-		".popsection\n"
+	if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
+		return -EPERM;
 
-		".pushsection __ex_table, \"a\"\n"
-		"    .long 1b, 4b \n"
-		"    .long 2b, 4b \n"
-		".popsection\n"
+	flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
 
-		: "=r"(err), "=r"(replaced)
-		: "r"(pc), "r"(new), "r"(old), "0"(err), "1"(replaced)
-		: "memory");
-
-	if (!err && (replaced == old))
-		flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
-
-	return err;
+	return 0;
 }
 
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
-	int ret;
 	unsigned long pc, old;
-	unsigned char *new;
+	unsigned long new;
+	int ret;
 
 	pc = (unsigned long)&ftrace_call;
 	memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE);
 	new = ftrace_call_replace(pc, (unsigned long)func);
-	ret = ftrace_modify_code(pc, (unsigned char *)&old, new);
+
+	ret = ftrace_modify_code(pc, old, new);
+
+#ifdef CONFIG_OLD_MCOUNT
+	if (!ret) {
+		pc = (unsigned long)&ftrace_call_old;
+		memcpy(&old, &ftrace_call_old, MCOUNT_INSN_SIZE);
+		new = ftrace_call_replace(pc, (unsigned long)func);
+
+		ret = ftrace_modify_code(pc, old, new);
+	}
+#endif
+
 	return ret;
 }
 
-/* run from ftrace_init with irqs disabled */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long new, old;
+	unsigned long ip = rec->ip;
+
+	old = ftrace_nop_replace(rec);
+	new = ftrace_call_replace(ip, adjust_address(rec, addr));
+
+	return ftrace_modify_code(rec->ip, old, new);
+}
+
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long ip = rec->ip;
+	unsigned long old;
+	unsigned long new;
+	int ret;
+
+	old = ftrace_call_replace(ip, adjust_address(rec, addr));
+	new = ftrace_nop_replace(rec);
+	ret = ftrace_modify_code(ip, old, new);
+
+#ifdef CONFIG_OLD_MCOUNT
+	if (ret == -EINVAL && addr == MCOUNT_ADDR) {
+		rec->arch.old_mcount = true;
+
+		old = ftrace_call_replace(ip, adjust_address(rec, addr));
+		new = ftrace_nop_replace(rec);
+		ret = ftrace_modify_code(ip, old, new);
+	}
+#endif
+
+	return ret;
+}
+
 int __init ftrace_dyn_arch_init(void *data)
 {
-	ftrace_mcount_set(data);
+	*(unsigned long *)data = 0;
+
 	return 0;
 }
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index b9505aa..bbecaac 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -15,55 +15,6 @@
 #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
 #define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)
 
-	.align	2
-	.type	__switch_data, %object
-__switch_data:
-	.long	__mmap_switched
-	.long	__data_loc			@ r4
-	.long	_data				@ r5
-	.long	__bss_start			@ r6
-	.long	_end				@ r7
-	.long	processor_id			@ r4
-	.long	__machine_arch_type		@ r5
-	.long	__atags_pointer			@ r6
-	.long	cr_alignment			@ r7
-	.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#15 control register
- *  r1  = machine ID
- *  r2  = atags pointer
- *  r9  = processor ID
- */
-__mmap_switched:
-	adr	r3, __switch_data + 4
-
-	ldmia	r3!, {r4, r5, r6, r7}
-	cmp	r4, r5				@ Copy data segment if needed
-1:	cmpne	r5, r6
-	ldrne	fp, [r4], #4
-	strne	fp, [r5], #4
-	bne	1b
-
-	mov	fp, #0				@ Clear BSS (and zero fp)
-1:	cmp	r6, r7
-	strcc	fp, [r6],#4
-	bcc	1b
-
- ARM(	ldmia	r3, {r4, r5, r6, r7, sp})
- THUMB(	ldmia	r3, {r4, r5, r6, r7}	)
- THUMB(	ldr	sp, [r3, #16]		)
-	str	r9, [r4]			@ Save processor ID
-	str	r1, [r5]			@ Save machine type
-	str	r2, [r6]			@ Save atags pointer
-	bic	r4, r0, #CR_A			@ Clear 'A' bit
-	stmia	r7, {r0, r4}			@ Save control register values
-	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
@@ -73,21 +24,7 @@
  * 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
-	bl	printascii
-	mov	r0, r9
-	bl	printhex8
-	adr	r0, str_p2
-	bl	printascii
-	b	__error
-str_p1:	.asciz	"\nError: unrecognized/unsupported processor variant (0x"
-str_p2:	.asciz	").\n"
-	.align
-#endif
-ENDPROC(__error_p)
-
+	__HEAD
 __error_a:
 #ifdef CONFIG_DEBUG_LL
 	mov	r4, r1				@ preserve machine ID
@@ -97,7 +34,7 @@
 	bl	printhex8
 	adr	r0, str_a2
 	bl	printascii
-	adr	r3, 4f
+	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
@@ -125,78 +62,6 @@
 	.align
 #endif
 
-__error:
-#ifdef CONFIG_ARCH_RPC
-/*
- * Turn the screen red on a error - RiscPC only.
- */
-	mov	r0, #0x02000000
-	mov	r3, #0x11
-	orr	r3, r3, r3, lsl #8
-	orr	r3, r3, r3, lsl #16
-	str	r3, [r0], #4
-	str	r3, [r0], #4
-	str	r3, [r0], #4
-	str	r3, [r0], #4
-#endif
-1:	mov	r0, r0
-	b	1b
-ENDPROC(__error)
-
-
-/*
- * Read processor ID register (CP#15, CR0), and look up in the linker-built
- * supported processor list.  Note that we can't use the absolute addresses
- * for the __proc_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.
- *
- *	r9 = cpuid
- * Returns:
- *	r3, r4, r6 corrupted
- *	r5 = proc_info pointer in physical address space
- *	r9 = cpuid (preserved)
- */
-__lookup_processor_type:
-	adr	r3, 3f
-	ldmia	r3, {r5 - r7}
-	add	r3, r3, #8
-	sub	r3, r3, r7			@ get offset between virt&phys
-	add	r5, r5, r3			@ convert virt addresses to
-	add	r6, r6, r3			@ physical address space
-1:	ldmia	r5, {r3, r4}			@ value, mask
-	and	r4, r4, r9			@ mask wanted bits
-	teq	r3, r4
-	beq	2f
-	add	r5, r5, #PROC_INFO_SZ		@ sizeof(proc_info_list)
-	cmp	r5, r6
-	blo	1b
-	mov	r5, #0				@ unknown processor
-2:	mov	pc, lr
-ENDPROC(__lookup_processor_type)
-
-/*
- * This provides a C-API version of the above function.
- */
-ENTRY(lookup_processor_type)
-	stmfd	sp!, {r4 - r7, r9, lr}
-	mov	r9, r0
-	bl	__lookup_processor_type
-	mov	r0, r5
-	ldmfd	sp!, {r4 - r7, r9, pc}
-ENDPROC(lookup_processor_type)
-
-/*
- * Look in <asm/procinfo.h> and arch/arm/kernel/arch.[ch] for
- * more information about the __proc_info and __arch_info structures.
- */
-	.align	2
-3:	.long	__proc_info_begin
-	.long	__proc_info_end
-4:	.long	.
-	.long	__arch_info_begin
-	.long	__arch_info_end
-
 /*
  * Lookup machine architecture in the linker-build list of architectures.
  * Note that we can't use the absolute addresses for the __arch_info
@@ -209,7 +74,7 @@
  *  r5 = mach_info pointer in physical address space
  */
 __lookup_machine_type:
-	adr	r3, 4b
+	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
@@ -225,15 +90,16 @@
 ENDPROC(__lookup_machine_type)
 
 /*
- * This provides a C-API version of the above function.
+ * Look in arch/arm/kernel/arch.[ch] for information about the
+ * __arch_info structures.
  */
-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)
+	.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
@@ -265,3 +131,150 @@
 1:	mov	r2, #0
 	mov	pc, lr
 ENDPROC(__vet_atags)
+
+/*
+ * 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#15 control register
+ *  r1  = machine ID
+ *  r2  = atags pointer
+ *  r9  = processor ID
+ */
+	__INIT
+__mmap_switched:
+	adr	r3, __mmap_switched_data
+
+	ldmia	r3!, {r4, r5, r6, r7}
+	cmp	r4, r5				@ Copy data segment if needed
+1:	cmpne	r5, r6
+	ldrne	fp, [r4], #4
+	strne	fp, [r5], #4
+	bne	1b
+
+	mov	fp, #0				@ Clear BSS (and zero fp)
+1:	cmp	r6, r7
+	strcc	fp, [r6],#4
+	bcc	1b
+
+ ARM(	ldmia	r3, {r4, r5, r6, r7, sp})
+ THUMB(	ldmia	r3, {r4, r5, r6, r7}	)
+ THUMB(	ldr	sp, [r3, #16]		)
+	str	r9, [r4]			@ Save processor ID
+	str	r1, [r5]			@ Save machine type
+	str	r2, [r6]			@ Save atags pointer
+	bic	r4, r0, #CR_A			@ Clear 'A' bit
+	stmia	r7, {r0, r4}			@ Save control register values
+	b	start_kernel
+ENDPROC(__mmap_switched)
+
+	.align	2
+	.type	__mmap_switched_data, %object
+__mmap_switched_data:
+	.long	__data_loc			@ r4
+	.long	_sdata				@ r5
+	.long	__bss_start			@ r6
+	.long	_end				@ r7
+	.long	processor_id			@ r4
+	.long	__machine_arch_type		@ r5
+	.long	__atags_pointer			@ r6
+	.long	cr_alignment			@ r7
+	.long	init_thread_union + THREAD_START_SP @ sp
+	.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)
+	stmfd	sp!, {r4 - r6, r9, lr}
+	mov	r9, r0
+	bl	__lookup_processor_type
+	mov	r0, r5
+	ldmfd	sp!, {r4 - r6, r9, pc}
+ENDPROC(lookup_processor_type)
+
+/*
+ * Read processor ID register (CP#15, CR0), and look up in the linker-built
+ * supported processor list.  Note that we can't use the absolute addresses
+ * for the __proc_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.
+ *
+ *	r9 = cpuid
+ * Returns:
+ *	r3, r4, r6 corrupted
+ *	r5 = proc_info pointer in physical address space
+ *	r9 = cpuid (preserved)
+ */
+	__CPUINIT
+__lookup_processor_type:
+	adr	r3, __lookup_processor_type_data
+	ldmia	r3, {r4 - 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:	ldmia	r5, {r3, r4}			@ value, mask
+	and	r4, r4, r9			@ mask wanted bits
+	teq	r3, r4
+	beq	2f
+	add	r5, r5, #PROC_INFO_SZ		@ sizeof(proc_info_list)
+	cmp	r5, r6
+	blo	1b
+	mov	r5, #0				@ unknown processor
+2:	mov	pc, lr
+ENDPROC(__lookup_processor_type)
+
+/*
+ * Look in <asm/procinfo.h> for information about the __proc_info structure.
+ */
+	.align	2
+	.type	__lookup_processor_type_data, %object
+__lookup_processor_type_data:
+	.long	.
+	.long	__proc_info_begin
+	.long	__proc_info_end
+	.size	__lookup_processor_type_data, . - __lookup_processor_type_data
+
+__error_p:
+#ifdef CONFIG_DEBUG_LL
+	adr	r0, str_p1
+	bl	printascii
+	mov	r0, r9
+	bl	printhex8
+	adr	r0, str_p2
+	bl	printascii
+	b	__error
+str_p1:	.asciz	"\nError: unrecognized/unsupported processor variant (0x"
+str_p2:	.asciz	").\n"
+	.align
+#endif
+ENDPROC(__error_p)
+
+__error:
+#ifdef CONFIG_ARCH_RPC
+/*
+ * Turn the screen red on a error - RiscPC only.
+ */
+	mov	r0, #0x02000000
+	mov	r3, #0x11
+	orr	r3, r3, r3, lsl #8
+	orr	r3, r3, r3, lsl #16
+	str	r3, [r0], #4
+	str	r3, [r0], #4
+	str	r3, [r0], #4
+	str	r3, [r0], #4
+#endif
+1:	mov	r0, r0
+	b	1b
+ENDPROC(__error)
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 573b803..814ce1a 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -48,8 +48,6 @@
 	movs	r8, r5				@ invalid machine (r5=0)?
 	beq	__error_a			@ yes, error 'a'
 
-	ldr	r13, __switch_data		@ address to jump to after
-						@ the initialization is done
 	adr	lr, BSYM(__after_proc_init)	@ return (PIC) address
  ARM(	add	pc, r10, #PROCINFO_INITFUNC	)
  THUMB(	add	r12, r10, #PROCINFO_INITFUNC	)
@@ -87,8 +85,7 @@
 	mcr	p15, 0, r0, c1, c0, 0		@ write control reg
 #endif /* CONFIG_CPU_CP15 */
 
-	mov	r3, r13
-	mov	pc, r3				@ clear the BSS and jump
+	b	__mmap_switched			@ clear the BSS and jump
 						@ to start_kernel
 ENDPROC(__after_proc_init)
 	.ltorg
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index eb62bf9..dd6b369 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -22,6 +22,10 @@
 #include <asm/thread_info.h>
 #include <asm/system.h>
 
+#ifdef CONFIG_DEBUG_LL
+#include <mach/debug-macro.S>
+#endif
+
 #if (PHYS_OFFSET & 0x001fffff)
 #error "PHYS_OFFSET must be at an even 2MiB boundary!"
 #endif
@@ -86,6 +90,9 @@
 	movs	r8, r5				@ invalid machine (r5=0)?
 	beq	__error_a			@ yes, error 'a'
 	bl	__vet_atags
+#ifdef CONFIG_SMP_ON_UP
+	bl	__fixup_smp
+#endif
 	bl	__create_page_tables
 
 	/*
@@ -95,113 +102,15 @@
 	 * above.  On return, the CPU will be ready for the MMU to be
 	 * turned on, and r0 will hold the CPU control register value.
 	 */
-	ldr	r13, __switch_data		@ address to jump to after
+	ldr	r13, =__mmap_switched		@ address to jump to after
 						@ mmu has been enabled
-	adr	lr, BSYM(__enable_mmu)		@ return (PIC) address
+	adr	lr, BSYM(1f)			@ return (PIC) address
  ARM(	add	pc, r10, #PROCINFO_INITFUNC	)
  THUMB(	add	r12, r10, #PROCINFO_INITFUNC	)
  THUMB(	mov	pc, r12				)
+1:	b	__enable_mmu
 ENDPROC(stext)
-
-#if defined(CONFIG_SMP)
-ENTRY(secondary_startup)
-	/*
-	 * Common entry point for secondary CPUs.
-	 *
-	 * Ensure that we're in SVC mode, and IRQs are disabled.  Lookup
-	 * the processor type - there is no need to check the machine type
-	 * as it has already been validated by the primary processor.
-	 */
-	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
-	mrc	p15, 0, r9, c0, c0		@ get processor id
-	bl	__lookup_processor_type
-	movs	r10, r5				@ invalid processor?
-	moveq	r0, #'p'			@ yes, error 'p'
-	beq	__error
-
-	/*
-	 * Use the page tables supplied from  __cpu_up.
-	 */
-	adr	r4, __secondary_data
-	ldmia	r4, {r5, r7, r12}		@ address to jump to after
-	sub	r4, r4, r5			@ mmu has been enabled
-	ldr	r4, [r7, r4]			@ get secondary_data.pgdir
-	adr	lr, BSYM(__enable_mmu)		@ return address
-	mov	r13, r12			@ __secondary_switched address
- ARM(	add	pc, r10, #PROCINFO_INITFUNC	) @ initialise processor
-						  @ (return control reg)
- THUMB(	add	r12, r10, #PROCINFO_INITFUNC	)
- THUMB(	mov	pc, r12				)
-ENDPROC(secondary_startup)
-
-	/*
-	 * r6  = &secondary_data
-	 */
-ENTRY(__secondary_switched)
-	ldr	sp, [r7, #4]			@ get secondary_data.stack
-	mov	fp, #0
-	b	secondary_start_kernel
-ENDPROC(__secondary_switched)
-
-	.type	__secondary_data, %object
-__secondary_data:
-	.long	.
-	.long	secondary_data
-	.long	__secondary_switched
-#endif /* defined(CONFIG_SMP) */
-
-
-
-/*
- * Setup common bits before finally enabling the MMU.  Essentially
- * this is just loading the page table pointer and domain access
- * registers.
- */
-__enable_mmu:
-#ifdef CONFIG_ALIGNMENT_TRAP
-	orr	r0, r0, #CR_A
-#else
-	bic	r0, r0, #CR_A
-#endif
-#ifdef CONFIG_CPU_DCACHE_DISABLE
-	bic	r0, r0, #CR_C
-#endif
-#ifdef CONFIG_CPU_BPREDICT_DISABLE
-	bic	r0, r0, #CR_Z
-#endif
-#ifdef CONFIG_CPU_ICACHE_DISABLE
-	bic	r0, r0, #CR_I
-#endif
-	mov	r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
-		      domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
-		      domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
-		      domain_val(DOMAIN_IO, DOMAIN_CLIENT))
-	mcr	p15, 0, r5, c3, c0, 0		@ load domain access register
-	mcr	p15, 0, r4, c2, c0, 0		@ load page table pointer
-	b	__turn_mmu_on
-ENDPROC(__enable_mmu)
-
-/*
- * Enable the MMU.  This completely changes the structure of the visible
- * memory space.  You will not be able to trace execution through this.
- * If you have an enquiry about this, *please* check the linux-arm-kernel
- * mailing list archives BEFORE sending another post to the list.
- *
- *  r0  = cp#15 control register
- *  r13 = *virtual* address to jump to upon completion
- *
- * other registers depend on the function called upon completion
- */
-	.align	5
-__turn_mmu_on:
-	mov	r0, r0
-	mcr	p15, 0, r0, c1, c0, 0		@ write control reg
-	mrc	p15, 0, r3, c0, c0, 0		@ read id reg
-	mov	r3, r3
-	mov	r3, r13
-	mov	pc, r3
-ENDPROC(__turn_mmu_on)
-
+	.ltorg
 
 /*
  * Setup the initial page tables.  We only setup the barest
@@ -213,7 +122,7 @@
  * r10 = procinfo
  *
  * Returns:
- *  r0, r3, r6, r7 corrupted
+ *  r0, r3, r5-r7 corrupted
  *  r4 = physical page table address
  */
 __create_page_tables:
@@ -235,20 +144,30 @@
 	ldr	r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
 
 	/*
-	 * Create identity mapping for first MB 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.
+	 * Create identity mapping to cater for __enable_mmu.
+	 * This identity mapping will be removed by paging_init().
 	 */
-	mov	r6, pc
-	mov	r6, r6, lsr #20			@ start of kernel section
-	orr	r3, r7, r6, lsl #20		@ flags + kernel base
-	str	r3, [r4, r6, lsl #2]		@ identity mapping
+	adr	r0, __enable_mmu_loc
+	ldmia	r0, {r3, r5, r6}
+	sub	r0, r0, r3			@ virt->phys offset
+	add	r5, r5, r0			@ phys __enable_mmu
+	add	r6, r6, r0			@ phys __enable_mmu_end
+	mov	r5, r5, lsr #20
+	mov	r6, r6, lsr #20
+
+1:	orr	r3, r7, r5, lsl #20		@ flags + kernel base
+	str	r3, [r4, r5, lsl #2]		@ identity mapping
+	teq	r5, r6
+	addne	r5, r5, #1			@ next section
+	bne	1b
 
 	/*
 	 * Now setup the pagetables for our kernel direct
 	 * mapped region.
 	 */
+	mov	r3, pc
+	mov	r3, r3, lsr #20
+	orr	r3, r7, r3, lsl #20
 	add	r0, r4,  #(KERNEL_START & 0xff000000) >> 18
 	str	r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
 	ldr	r6, =(KERNEL_END - 1)
@@ -289,24 +208,35 @@
 	str	r6, [r0]
 
 #ifdef CONFIG_DEBUG_LL
-	ldr	r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
+#ifndef CONFIG_DEBUG_ICEDCC
 	/*
 	 * Map in IO space for serial debugging.
 	 * This allows debug messages to be output
 	 * via a serial console before paging_init.
 	 */
-	ldr	r3, [r8, #MACHINFO_PGOFFIO]
+	addruart r7, r3
+
+	mov	r3, r3, lsr #20
+	mov	r3, r3, lsl #2
+
 	add	r0, r4, r3
 	rsb	r3, r3, #0x4000			@ PTRS_PER_PGD*sizeof(long)
 	cmp	r3, #0x0800			@ limit to 512MB
 	movhi	r3, #0x0800
 	add	r6, r0, r3
-	ldr	r3, [r8, #MACHINFO_PHYSIO]
-	orr	r3, r3, r7
+	mov	r3, r7, lsr #20
+	ldr	r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
+	orr	r3, r7, r3, lsl #20
 1:	str	r3, [r0], #4
 	add	r3, r3, #1 << 20
 	teq	r0, r6
 	bne	1b
+
+#else /* CONFIG_DEBUG_ICEDCC */
+	/* we don't need any serial debugging mappings for ICEDCC */
+	ldr	r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
+#endif /* !CONFIG_DEBUG_ICEDCC */
+
 #if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
 	/*
 	 * If we're using the NetWinder or CATS, we also need to map
@@ -332,5 +262,168 @@
 	mov	pc, lr
 ENDPROC(__create_page_tables)
 	.ltorg
+__enable_mmu_loc:
+	.long	.
+	.long	__enable_mmu
+	.long	__enable_mmu_end
+
+#if defined(CONFIG_SMP)
+	__CPUINIT
+ENTRY(secondary_startup)
+	/*
+	 * Common entry point for secondary CPUs.
+	 *
+	 * Ensure that we're in SVC mode, and IRQs are disabled.  Lookup
+	 * the processor type - there is no need to check the machine type
+	 * as it has already been validated by the primary processor.
+	 */
+	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
+	mrc	p15, 0, r9, c0, c0		@ get processor id
+	bl	__lookup_processor_type
+	movs	r10, r5				@ invalid processor?
+	moveq	r0, #'p'			@ yes, error 'p'
+	beq	__error_p
+
+	/*
+	 * Use the page tables supplied from  __cpu_up.
+	 */
+	adr	r4, __secondary_data
+	ldmia	r4, {r5, r7, r12}		@ address to jump to after
+	sub	r4, r4, r5			@ mmu has been enabled
+	ldr	r4, [r7, r4]			@ get secondary_data.pgdir
+	adr	lr, BSYM(__enable_mmu)		@ return address
+	mov	r13, r12			@ __secondary_switched address
+ ARM(	add	pc, r10, #PROCINFO_INITFUNC	) @ initialise processor
+						  @ (return control reg)
+ THUMB(	add	r12, r10, #PROCINFO_INITFUNC	)
+ THUMB(	mov	pc, r12				)
+ENDPROC(secondary_startup)
+
+	/*
+	 * r6  = &secondary_data
+	 */
+ENTRY(__secondary_switched)
+	ldr	sp, [r7, #4]			@ get secondary_data.stack
+	mov	fp, #0
+	b	secondary_start_kernel
+ENDPROC(__secondary_switched)
+
+	.type	__secondary_data, %object
+__secondary_data:
+	.long	.
+	.long	secondary_data
+	.long	__secondary_switched
+#endif /* defined(CONFIG_SMP) */
+
+
+
+/*
+ * Setup common bits before finally enabling the MMU.  Essentially
+ * this is just loading the page table pointer and domain access
+ * registers.
+ *
+ *  r0  = cp#15 control register
+ *  r1  = machine ID
+ *  r2  = atags pointer
+ *  r4  = page table pointer
+ *  r9  = processor ID
+ *  r13 = *virtual* address to jump to upon completion
+ */
+__enable_mmu:
+#ifdef CONFIG_ALIGNMENT_TRAP
+	orr	r0, r0, #CR_A
+#else
+	bic	r0, r0, #CR_A
+#endif
+#ifdef CONFIG_CPU_DCACHE_DISABLE
+	bic	r0, r0, #CR_C
+#endif
+#ifdef CONFIG_CPU_BPREDICT_DISABLE
+	bic	r0, r0, #CR_Z
+#endif
+#ifdef CONFIG_CPU_ICACHE_DISABLE
+	bic	r0, r0, #CR_I
+#endif
+	mov	r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
+		      domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
+		      domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
+		      domain_val(DOMAIN_IO, DOMAIN_CLIENT))
+	mcr	p15, 0, r5, c3, c0, 0		@ load domain access register
+	mcr	p15, 0, r4, c2, c0, 0		@ load page table pointer
+	b	__turn_mmu_on
+ENDPROC(__enable_mmu)
+
+/*
+ * Enable the MMU.  This completely changes the structure of the visible
+ * memory space.  You will not be able to trace execution through this.
+ * If you have an enquiry about this, *please* check the linux-arm-kernel
+ * mailing list archives BEFORE sending another post to the list.
+ *
+ *  r0  = cp#15 control register
+ *  r1  = machine ID
+ *  r2  = atags pointer
+ *  r9  = processor ID
+ *  r13 = *virtual* address to jump to upon completion
+ *
+ * other registers depend on the function called upon completion
+ */
+	.align	5
+__turn_mmu_on:
+	mov	r0, r0
+	mcr	p15, 0, r0, c1, c0, 0		@ write control reg
+	mrc	p15, 0, r3, c0, c0, 0		@ read id reg
+	mov	r3, r3
+	mov	r3, r13
+	mov	pc, r3
+__enable_mmu_end:
+ENDPROC(__turn_mmu_on)
+
+
+#ifdef CONFIG_SMP_ON_UP
+__fixup_smp:
+	mov	r7, #0x00070000
+	orr	r6, r7, #0xff000000	@ mask 0xff070000
+	orr	r7, r7, #0x41000000	@ val 0x41070000
+	and	r0, r9, r6
+	teq	r0, r7			@ ARM CPU and ARMv6/v7?
+	bne	__fixup_smp_on_up	@ no, assume UP
+
+	orr	r6, r6, #0x0000ff00
+	orr	r6, r6, #0x000000f0	@ mask 0xff07fff0
+	orr	r7, r7, #0x0000b000
+	orr	r7, r7, #0x00000020	@ val 0x4107b020
+	and	r0, r9, r6
+	teq	r0, r7			@ ARM 11MPCore?
+	moveq	pc, lr			@ yes, assume SMP
+
+	mrc	p15, 0, r0, c0, c0, 5	@ read MPIDR
+	tst	r0, #1 << 31
+	movne	pc, lr			@ bit 31 => SMP
+
+__fixup_smp_on_up:
+	adr	r0, 1f
+	ldmia	r0, {r3, r6, r7}
+	sub	r3, r0, r3
+	add	r6, r6, r3
+	add	r7, r7, r3
+2:	cmp	r6, r7
+	ldmia	r6!, {r0, r4}
+	strlo	r4, [r0, r3]
+	blo	2b
+	mov	pc, lr
+ENDPROC(__fixup_smp)
+
+1:	.word	.
+	.word	__smpalt_begin
+	.word	__smpalt_end
+
+	.pushsection .data
+	.globl	smp_on_up
+smp_on_up:
+	ALT_SMP(.long	1)
+	ALT_UP(.long	0)
+	.popsection
+
+#endif
 
 #include "head-common.S"
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
new file mode 100644
index 0000000..54593b0
--- /dev/null
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -0,0 +1,849 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2009, 2010 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+/*
+ * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
+ * using the CPU's debug registers.
+ */
+#define pr_fmt(fmt) "hw-breakpoint: " fmt
+
+#include <linux/errno.h>
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
+#include <asm/current.h>
+#include <asm/hw_breakpoint.h>
+#include <asm/kdebug.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+
+/* Breakpoint currently in use for each BRP. */
+static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]);
+
+/* Watchpoint currently in use for each WRP. */
+static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]);
+
+/* Number of BRP/WRP registers on this CPU. */
+static int core_num_brps;
+static int core_num_wrps;
+
+/* Debug architecture version. */
+static u8 debug_arch;
+
+/* Maximum supported watchpoint length. */
+static u8 max_watchpoint_len;
+
+/* Determine number of BRP registers available. */
+static int get_num_brps(void)
+{
+	u32 didr;
+	ARM_DBG_READ(c0, 0, didr);
+	return ((didr >> 24) & 0xf) + 1;
+}
+
+/* Determine number of WRP registers available. */
+static int get_num_wrps(void)
+{
+	/*
+	 * FIXME: When a watchpoint fires, the only way to work out which
+	 * watchpoint it was is by disassembling the faulting instruction
+	 * and working out the address of the memory access.
+	 *
+	 * Furthermore, we can only do this if the watchpoint was precise
+	 * since imprecise watchpoints prevent us from calculating register
+	 * based addresses.
+	 *
+	 * For the time being, we only report 1 watchpoint register so we
+	 * always know which watchpoint fired. In the future we can either
+	 * add a disassembler and address generation emulator, or we can
+	 * insert a check to see if the DFAR is set on watchpoint exception
+	 * entry [the ARM ARM states that the DFAR is UNKNOWN, but
+	 * experience shows that it is set on some implementations].
+	 */
+
+#if 0
+	u32 didr, wrps;
+	ARM_DBG_READ(c0, 0, didr);
+	return ((didr >> 28) & 0xf) + 1;
+#endif
+
+	return 1;
+}
+
+int hw_breakpoint_slots(int type)
+{
+	/*
+	 * We can be called early, so don't rely on
+	 * our static variables being initialised.
+	 */
+	switch (type) {
+	case TYPE_INST:
+		return get_num_brps();
+	case TYPE_DATA:
+		return get_num_wrps();
+	default:
+		pr_warning("unknown slot type: %d\n", type);
+		return 0;
+	}
+}
+
+/* Determine debug architecture. */
+static u8 get_debug_arch(void)
+{
+	u32 didr;
+
+	/* Do we implement the extended CPUID interface? */
+	if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
+		pr_warning("CPUID feature registers not supported. "
+				"Assuming v6 debug is present.\n");
+		return ARM_DEBUG_ARCH_V6;
+	}
+
+	ARM_DBG_READ(c0, 0, didr);
+	return (didr >> 16) & 0xf;
+}
+
+/* Does this core support mismatch breakpoints? */
+static int core_has_mismatch_bps(void)
+{
+	return debug_arch >= ARM_DEBUG_ARCH_V7_ECP14 && core_num_brps > 1;
+}
+
+u8 arch_get_debug_arch(void)
+{
+	return debug_arch;
+}
+
+#define READ_WB_REG_CASE(OP2, M, VAL)		\
+	case ((OP2 << 4) + M):			\
+		ARM_DBG_READ(c ## M, OP2, VAL); \
+		break
+
+#define WRITE_WB_REG_CASE(OP2, M, VAL)		\
+	case ((OP2 << 4) + M):			\
+		ARM_DBG_WRITE(c ## M, OP2, VAL);\
+		break
+
+#define GEN_READ_WB_REG_CASES(OP2, VAL)		\
+	READ_WB_REG_CASE(OP2, 0, VAL);		\
+	READ_WB_REG_CASE(OP2, 1, VAL);		\
+	READ_WB_REG_CASE(OP2, 2, VAL);		\
+	READ_WB_REG_CASE(OP2, 3, VAL);		\
+	READ_WB_REG_CASE(OP2, 4, VAL);		\
+	READ_WB_REG_CASE(OP2, 5, VAL);		\
+	READ_WB_REG_CASE(OP2, 6, VAL);		\
+	READ_WB_REG_CASE(OP2, 7, VAL);		\
+	READ_WB_REG_CASE(OP2, 8, VAL);		\
+	READ_WB_REG_CASE(OP2, 9, VAL);		\
+	READ_WB_REG_CASE(OP2, 10, VAL);		\
+	READ_WB_REG_CASE(OP2, 11, VAL);		\
+	READ_WB_REG_CASE(OP2, 12, VAL);		\
+	READ_WB_REG_CASE(OP2, 13, VAL);		\
+	READ_WB_REG_CASE(OP2, 14, VAL);		\
+	READ_WB_REG_CASE(OP2, 15, VAL)
+
+#define GEN_WRITE_WB_REG_CASES(OP2, VAL)	\
+	WRITE_WB_REG_CASE(OP2, 0, VAL);		\
+	WRITE_WB_REG_CASE(OP2, 1, VAL);		\
+	WRITE_WB_REG_CASE(OP2, 2, VAL);		\
+	WRITE_WB_REG_CASE(OP2, 3, VAL);		\
+	WRITE_WB_REG_CASE(OP2, 4, VAL);		\
+	WRITE_WB_REG_CASE(OP2, 5, VAL);		\
+	WRITE_WB_REG_CASE(OP2, 6, VAL);		\
+	WRITE_WB_REG_CASE(OP2, 7, VAL);		\
+	WRITE_WB_REG_CASE(OP2, 8, VAL);		\
+	WRITE_WB_REG_CASE(OP2, 9, VAL);		\
+	WRITE_WB_REG_CASE(OP2, 10, VAL);	\
+	WRITE_WB_REG_CASE(OP2, 11, VAL);	\
+	WRITE_WB_REG_CASE(OP2, 12, VAL);	\
+	WRITE_WB_REG_CASE(OP2, 13, VAL);	\
+	WRITE_WB_REG_CASE(OP2, 14, VAL);	\
+	WRITE_WB_REG_CASE(OP2, 15, VAL)
+
+static u32 read_wb_reg(int n)
+{
+	u32 val = 0;
+
+	switch (n) {
+	GEN_READ_WB_REG_CASES(ARM_OP2_BVR, val);
+	GEN_READ_WB_REG_CASES(ARM_OP2_BCR, val);
+	GEN_READ_WB_REG_CASES(ARM_OP2_WVR, val);
+	GEN_READ_WB_REG_CASES(ARM_OP2_WCR, val);
+	default:
+		pr_warning("attempt to read from unknown breakpoint "
+				"register %d\n", n);
+	}
+
+	return val;
+}
+
+static void write_wb_reg(int n, u32 val)
+{
+	switch (n) {
+	GEN_WRITE_WB_REG_CASES(ARM_OP2_BVR, val);
+	GEN_WRITE_WB_REG_CASES(ARM_OP2_BCR, val);
+	GEN_WRITE_WB_REG_CASES(ARM_OP2_WVR, val);
+	GEN_WRITE_WB_REG_CASES(ARM_OP2_WCR, val);
+	default:
+		pr_warning("attempt to write to unknown breakpoint "
+				"register %d\n", n);
+	}
+	isb();
+}
+
+/*
+ * In order to access the breakpoint/watchpoint control registers,
+ * we must be running in debug monitor mode. Unfortunately, we can
+ * be put into halting debug mode at any time by an external debugger
+ * but there is nothing we can do to prevent that.
+ */
+static int enable_monitor_mode(void)
+{
+	u32 dscr;
+	int ret = 0;
+
+	ARM_DBG_READ(c1, 0, dscr);
+
+	/* Ensure that halting mode is disabled. */
+	if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, "halting debug mode enabled."
+				"Unable to access hardware resources.")) {
+		ret = -EPERM;
+		goto out;
+	}
+
+	/* Write to the corresponding DSCR. */
+	switch (debug_arch) {
+	case ARM_DEBUG_ARCH_V6:
+	case ARM_DEBUG_ARCH_V6_1:
+		ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
+		break;
+	case ARM_DEBUG_ARCH_V7_ECP14:
+		ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN));
+		break;
+	default:
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* Check that the write made it through. */
+	ARM_DBG_READ(c1, 0, dscr);
+	if (WARN_ONCE(!(dscr & ARM_DSCR_MDBGEN),
+				"failed to enable monitor mode.")) {
+		ret = -EPERM;
+	}
+
+out:
+	return ret;
+}
+
+/*
+ * Check if 8-bit byte-address select is available.
+ * This clobbers WRP 0.
+ */
+static u8 get_max_wp_len(void)
+{
+	u32 ctrl_reg;
+	struct arch_hw_breakpoint_ctrl ctrl;
+	u8 size = 4;
+
+	if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14)
+		goto out;
+
+	if (enable_monitor_mode())
+		goto out;
+
+	memset(&ctrl, 0, sizeof(ctrl));
+	ctrl.len = ARM_BREAKPOINT_LEN_8;
+	ctrl_reg = encode_ctrl_reg(ctrl);
+
+	write_wb_reg(ARM_BASE_WVR, 0);
+	write_wb_reg(ARM_BASE_WCR, ctrl_reg);
+	if ((read_wb_reg(ARM_BASE_WCR) & ctrl_reg) == ctrl_reg)
+		size = 8;
+
+out:
+	return size;
+}
+
+u8 arch_get_max_wp_len(void)
+{
+	return max_watchpoint_len;
+}
+
+/*
+ * Handler for reactivating a suspended watchpoint when the single
+ * step `mismatch' breakpoint is triggered.
+ */
+static void wp_single_step_handler(struct perf_event *bp, int unused,
+				   struct perf_sample_data *data,
+				   struct pt_regs *regs)
+{
+	perf_event_enable(counter_arch_bp(bp)->suspended_wp);
+	unregister_hw_breakpoint(bp);
+}
+
+static int bp_is_single_step(struct perf_event *bp)
+{
+	return bp->overflow_handler == wp_single_step_handler;
+}
+
+/*
+ * Install a perf counter breakpoint.
+ */
+int arch_install_hw_breakpoint(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+	struct perf_event **slot, **slots;
+	int i, max_slots, ctrl_base, val_base, ret = 0;
+
+	/* Ensure that we are in monitor mode and halting mode is disabled. */
+	ret = enable_monitor_mode();
+	if (ret)
+		goto out;
+
+	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
+		/* Breakpoint */
+		ctrl_base = ARM_BASE_BCR;
+		val_base = ARM_BASE_BVR;
+		slots = __get_cpu_var(bp_on_reg);
+		max_slots = core_num_brps - 1;
+
+		if (bp_is_single_step(bp)) {
+			info->ctrl.mismatch = 1;
+			i = max_slots;
+			slots[i] = bp;
+			goto setup;
+		}
+	} else {
+		/* Watchpoint */
+		ctrl_base = ARM_BASE_WCR;
+		val_base = ARM_BASE_WVR;
+		slots = __get_cpu_var(wp_on_reg);
+		max_slots = core_num_wrps;
+	}
+
+	for (i = 0; i < max_slots; ++i) {
+		slot = &slots[i];
+
+		if (!*slot) {
+			*slot = bp;
+			break;
+		}
+	}
+
+	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+setup:
+	/* Setup the address register. */
+	write_wb_reg(val_base + i, info->address);
+
+	/* Setup the control register. */
+	write_wb_reg(ctrl_base + i, encode_ctrl_reg(info->ctrl) | 0x1);
+
+out:
+	return ret;
+}
+
+void arch_uninstall_hw_breakpoint(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+	struct perf_event **slot, **slots;
+	int i, max_slots, base;
+
+	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
+		/* Breakpoint */
+		base = ARM_BASE_BCR;
+		slots = __get_cpu_var(bp_on_reg);
+		max_slots = core_num_brps - 1;
+
+		if (bp_is_single_step(bp)) {
+			i = max_slots;
+			slots[i] = NULL;
+			goto reset;
+		}
+	} else {
+		/* Watchpoint */
+		base = ARM_BASE_WCR;
+		slots = __get_cpu_var(wp_on_reg);
+		max_slots = core_num_wrps;
+	}
+
+	/* Remove the breakpoint. */
+	for (i = 0; i < max_slots; ++i) {
+		slot = &slots[i];
+
+		if (*slot == bp) {
+			*slot = NULL;
+			break;
+		}
+	}
+
+	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
+		return;
+
+reset:
+	/* Reset the control register. */
+	write_wb_reg(base + i, 0);
+}
+
+static int get_hbp_len(u8 hbp_len)
+{
+	unsigned int len_in_bytes = 0;
+
+	switch (hbp_len) {
+	case ARM_BREAKPOINT_LEN_1:
+		len_in_bytes = 1;
+		break;
+	case ARM_BREAKPOINT_LEN_2:
+		len_in_bytes = 2;
+		break;
+	case ARM_BREAKPOINT_LEN_4:
+		len_in_bytes = 4;
+		break;
+	case ARM_BREAKPOINT_LEN_8:
+		len_in_bytes = 8;
+		break;
+	}
+
+	return len_in_bytes;
+}
+
+/*
+ * Check whether bp virtual address is in kernel space.
+ */
+int arch_check_bp_in_kernelspace(struct perf_event *bp)
+{
+	unsigned int len;
+	unsigned long va;
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+	va = info->address;
+	len = get_hbp_len(info->ctrl.len);
+
+	return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
+}
+
+/*
+ * Extract generic type and length encodings from an arch_hw_breakpoint_ctrl.
+ * Hopefully this will disappear when ptrace can bypass the conversion
+ * to generic breakpoint descriptions.
+ */
+int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
+			   int *gen_len, int *gen_type)
+{
+	/* Type */
+	switch (ctrl.type) {
+	case ARM_BREAKPOINT_EXECUTE:
+		*gen_type = HW_BREAKPOINT_X;
+		break;
+	case ARM_BREAKPOINT_LOAD:
+		*gen_type = HW_BREAKPOINT_R;
+		break;
+	case ARM_BREAKPOINT_STORE:
+		*gen_type = HW_BREAKPOINT_W;
+		break;
+	case ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE:
+		*gen_type = HW_BREAKPOINT_RW;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Len */
+	switch (ctrl.len) {
+	case ARM_BREAKPOINT_LEN_1:
+		*gen_len = HW_BREAKPOINT_LEN_1;
+		break;
+	case ARM_BREAKPOINT_LEN_2:
+		*gen_len = HW_BREAKPOINT_LEN_2;
+		break;
+	case ARM_BREAKPOINT_LEN_4:
+		*gen_len = HW_BREAKPOINT_LEN_4;
+		break;
+	case ARM_BREAKPOINT_LEN_8:
+		*gen_len = HW_BREAKPOINT_LEN_8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Construct an arch_hw_breakpoint from a perf_event.
+ */
+static int arch_build_bp_info(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+	/* Type */
+	switch (bp->attr.bp_type) {
+	case HW_BREAKPOINT_X:
+		info->ctrl.type = ARM_BREAKPOINT_EXECUTE;
+		break;
+	case HW_BREAKPOINT_R:
+		info->ctrl.type = ARM_BREAKPOINT_LOAD;
+		break;
+	case HW_BREAKPOINT_W:
+		info->ctrl.type = ARM_BREAKPOINT_STORE;
+		break;
+	case HW_BREAKPOINT_RW:
+		info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Len */
+	switch (bp->attr.bp_len) {
+	case HW_BREAKPOINT_LEN_1:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_1;
+		break;
+	case HW_BREAKPOINT_LEN_2:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_2;
+		break;
+	case HW_BREAKPOINT_LEN_4:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_4;
+		break;
+	case HW_BREAKPOINT_LEN_8:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_8;
+		if ((info->ctrl.type != ARM_BREAKPOINT_EXECUTE)
+			&& max_watchpoint_len >= 8)
+			break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Address */
+	info->address = bp->attr.bp_addr;
+
+	/* Privilege */
+	info->ctrl.privilege = ARM_BREAKPOINT_USER;
+	if (arch_check_bp_in_kernelspace(bp) && !bp_is_single_step(bp))
+		info->ctrl.privilege |= ARM_BREAKPOINT_PRIV;
+
+	/* Enabled? */
+	info->ctrl.enabled = !bp->attr.disabled;
+
+	/* Mismatch */
+	info->ctrl.mismatch = 0;
+
+	return 0;
+}
+
+/*
+ * Validate the arch-specific HW Breakpoint register settings.
+ */
+int arch_validate_hwbkpt_settings(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+	int ret = 0;
+	u32 bytelen, max_len, offset, alignment_mask = 0x3;
+
+	/* Build the arch_hw_breakpoint. */
+	ret = arch_build_bp_info(bp);
+	if (ret)
+		goto out;
+
+	/* Check address alignment. */
+	if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
+		alignment_mask = 0x7;
+	if (info->address & alignment_mask) {
+		/*
+		 * Try to fix the alignment. This may result in a length
+		 * that is too large, so we must check for that.
+		 */
+		bytelen = get_hbp_len(info->ctrl.len);
+		max_len = info->ctrl.type == ARM_BREAKPOINT_EXECUTE ? 4 :
+				max_watchpoint_len;
+
+		if (max_len >= 8)
+			offset = info->address & 0x7;
+		else
+			offset = info->address & 0x3;
+
+		if (bytelen > (1 << ((max_len - (offset + 1)) >> 1))) {
+			ret = -EFBIG;
+			goto out;
+		}
+
+		info->ctrl.len <<= offset;
+		info->address &= ~offset;
+
+		pr_debug("breakpoint alignment fixup: length = 0x%x, "
+			"address = 0x%x\n", info->ctrl.len, info->address);
+	}
+
+	/*
+	 * Currently we rely on an overflow handler to take
+	 * care of single-stepping the breakpoint when it fires.
+	 * In the case of userspace breakpoints on a core with V7 debug,
+	 * we can use the mismatch feature as a poor-man's hardware single-step.
+	 */
+	if (WARN_ONCE(!bp->overflow_handler &&
+		(arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_bps()),
+			"overflow handler required but none found")) {
+		ret = -EINVAL;
+		goto out;
+	}
+out:
+	return ret;
+}
+
+static void update_mismatch_flag(int idx, int flag)
+{
+	struct perf_event *bp = __get_cpu_var(bp_on_reg[idx]);
+	struct arch_hw_breakpoint *info;
+
+	if (bp == NULL)
+		return;
+
+	info = counter_arch_bp(bp);
+
+	/* Update the mismatch field to enter/exit `single-step' mode */
+	if (!bp->overflow_handler && info->ctrl.mismatch != flag) {
+		info->ctrl.mismatch = flag;
+		write_wb_reg(ARM_BASE_BCR + idx, encode_ctrl_reg(info->ctrl) | 0x1);
+	}
+}
+
+static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
+{
+	int i;
+	struct perf_event *bp, **slots = __get_cpu_var(wp_on_reg);
+	struct arch_hw_breakpoint *info;
+	struct perf_event_attr attr;
+
+	/* Without a disassembler, we can only handle 1 watchpoint. */
+	BUG_ON(core_num_wrps > 1);
+
+	hw_breakpoint_init(&attr);
+	attr.bp_addr	= regs->ARM_pc & ~0x3;
+	attr.bp_len	= HW_BREAKPOINT_LEN_4;
+	attr.bp_type	= HW_BREAKPOINT_X;
+
+	for (i = 0; i < core_num_wrps; ++i) {
+		rcu_read_lock();
+
+		if (slots[i] == NULL) {
+			rcu_read_unlock();
+			continue;
+		}
+
+		/*
+		 * The DFAR is an unknown value. Since we only allow a
+		 * single watchpoint, we can set the trigger to the lowest
+		 * possible faulting address.
+		 */
+		info = counter_arch_bp(slots[i]);
+		info->trigger = slots[i]->attr.bp_addr;
+		pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
+		perf_bp_event(slots[i], regs);
+
+		/*
+		 * If no overflow handler is present, insert a temporary
+		 * mismatch breakpoint so we can single-step over the
+		 * watchpoint trigger.
+		 */
+		if (!slots[i]->overflow_handler) {
+			bp = register_user_hw_breakpoint(&attr,
+							 wp_single_step_handler,
+							 current);
+			counter_arch_bp(bp)->suspended_wp = slots[i];
+			perf_event_disable(slots[i]);
+		}
+
+		rcu_read_unlock();
+	}
+}
+
+static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
+{
+	int i;
+	int mismatch;
+	u32 ctrl_reg, val, addr;
+	struct perf_event *bp, **slots = __get_cpu_var(bp_on_reg);
+	struct arch_hw_breakpoint *info;
+	struct arch_hw_breakpoint_ctrl ctrl;
+
+	/* The exception entry code places the amended lr in the PC. */
+	addr = regs->ARM_pc;
+
+	for (i = 0; i < core_num_brps; ++i) {
+		rcu_read_lock();
+
+		bp = slots[i];
+
+		if (bp == NULL) {
+			rcu_read_unlock();
+			continue;
+		}
+
+		mismatch = 0;
+
+		/* Check if the breakpoint value matches. */
+		val = read_wb_reg(ARM_BASE_BVR + i);
+		if (val != (addr & ~0x3))
+			goto unlock;
+
+		/* Possible match, check the byte address select to confirm. */
+		ctrl_reg = read_wb_reg(ARM_BASE_BCR + i);
+		decode_ctrl_reg(ctrl_reg, &ctrl);
+		if ((1 << (addr & 0x3)) & ctrl.len) {
+			mismatch = 1;
+			info = counter_arch_bp(bp);
+			info->trigger = addr;
+		}
+
+unlock:
+		if ((mismatch && !info->ctrl.mismatch) || bp_is_single_step(bp)) {
+			pr_debug("breakpoint fired: address = 0x%x\n", addr);
+			perf_bp_event(bp, regs);
+		}
+
+		update_mismatch_flag(i, mismatch);
+		rcu_read_unlock();
+	}
+}
+
+/*
+ * Called from either the Data Abort Handler [watchpoint] or the
+ * Prefetch Abort Handler [breakpoint].
+ */
+static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
+				 struct pt_regs *regs)
+{
+	int ret = 1; /* Unhandled fault. */
+	u32 dscr;
+
+	/* We only handle watchpoints and hardware breakpoints. */
+	ARM_DBG_READ(c1, 0, dscr);
+
+	/* Perform perf callbacks. */
+	switch (ARM_DSCR_MOE(dscr)) {
+	case ARM_ENTRY_BREAKPOINT:
+		breakpoint_handler(addr, regs);
+		break;
+	case ARM_ENTRY_ASYNC_WATCHPOINT:
+		WARN_ON("Asynchronous watchpoint exception taken. "
+			"Debugging results may be unreliable");
+	case ARM_ENTRY_SYNC_WATCHPOINT:
+		watchpoint_handler(addr, regs);
+		break;
+	default:
+		goto out;
+	}
+
+	ret = 0;
+out:
+	return ret;
+}
+
+/*
+ * One-time initialisation.
+ */
+static void __init reset_ctrl_regs(void *unused)
+{
+	int i;
+
+	if (enable_monitor_mode())
+		return;
+
+	for (i = 0; i < core_num_brps; ++i) {
+		write_wb_reg(ARM_BASE_BCR + i, 0UL);
+		write_wb_reg(ARM_BASE_BVR + i, 0UL);
+	}
+
+	for (i = 0; i < core_num_wrps; ++i) {
+		write_wb_reg(ARM_BASE_WCR + i, 0UL);
+		write_wb_reg(ARM_BASE_WVR + i, 0UL);
+	}
+}
+
+static int __init arch_hw_breakpoint_init(void)
+{
+	int ret = 0;
+	u32 dscr;
+
+	debug_arch = get_debug_arch();
+
+	if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) {
+		pr_info("debug architecture 0x%x unsupported.\n", debug_arch);
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* Determine how many BRPs/WRPs are available. */
+	core_num_brps = get_num_brps();
+	core_num_wrps = get_num_wrps();
+
+	pr_info("found %d breakpoint and %d watchpoint registers.\n",
+			core_num_brps, core_num_wrps);
+
+	if (core_has_mismatch_bps())
+		pr_info("1 breakpoint reserved for watchpoint single-step.\n");
+
+	ARM_DBG_READ(c1, 0, dscr);
+	if (dscr & ARM_DSCR_HDBGEN) {
+		pr_warning("halting debug mode enabled. Assuming maximum "
+				"watchpoint size of 4 bytes.");
+	} else {
+		/* Work out the maximum supported watchpoint length. */
+		max_watchpoint_len = get_max_wp_len();
+		pr_info("maximum watchpoint size is %u bytes.\n",
+				max_watchpoint_len);
+
+		/*
+		 * Reset the breakpoint resources. We assume that a halting
+		 * debugger will leave the world in a nice state for us.
+		 */
+		smp_call_function(reset_ctrl_regs, NULL, 1);
+		reset_ctrl_regs(NULL);
+	}
+
+	/* Register debug fault handler. */
+	hook_fault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
+			"watchpoint debug exception");
+	hook_ifault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
+			"breakpoint debug exception");
+
+out:
+	return ret;
+}
+arch_initcall(arch_hw_breakpoint_init);
+
+void hw_breakpoint_pmu_read(struct perf_event *bp)
+{
+}
+
+/*
+ * Dummy function to register with die_notifier.
+ */
+int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+					unsigned long val, void *data)
+{
+	return NOTIFY_DONE;
+}
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index c0d5c3b..36ad3be 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -154,14 +154,6 @@
 
 void __init init_IRQ(void)
 {
-	struct irq_desc *desc;
-	int irq;
-
-	for (irq = 0; irq < nr_irqs; irq++) {
-		desc = irq_to_desc_alloc_node(irq, 0);
-		desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
-	}
-
 	init_arch_irq();
 }
 
@@ -169,7 +161,7 @@
 int __init arch_probe_nr_irqs(void)
 {
 	nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS;
-	return 0;
+	return nr_irqs;
 }
 #endif
 
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
index 8bccbfa..2c1f005 100644
--- a/arch/arm/kernel/kprobes-decode.c
+++ b/arch/arm/kernel/kprobes-decode.c
@@ -1162,11 +1162,12 @@
 {
 	/*
 	 * MSR   : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
-	 * Undef : cccc 0011 0x00 xxxx xxxx xxxx xxxx xxxx
+	 * Undef : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx
 	 * ALU op with S bit and Rd == 15 :
 	 *	   cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
 	 */
-	if ((insn & 0x0f900000) == 0x03200000 ||	/* MSR & Undef */
+	if ((insn & 0x0fb00000) == 0x03200000 ||	/* MSR */
+	    (insn & 0x0ff00000) == 0x03400000 ||	/* Undef */
 	    (insn & 0x0e10f000) == 0x0210f000)		/* ALU s-bit, R15  */
 		return INSN_REJECTED;
 
@@ -1177,7 +1178,7 @@
 	 * *S (bit 20) updates condition codes
 	 * ADC/SBC/RSC reads the C flag
 	 */
-	insn &= 0xfff00fff;	/* Rn = r0, Rd = r0 */
+	insn &= 0xffff0fff;	/* Rd = r0 */
 	asi->insn[0] = insn;
 	asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
 			emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 6b46058..d9bd786 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -69,20 +69,31 @@
 {
 #ifdef CONFIG_ARM_UNWIND
 	Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+	struct arm_unwind_mapping *maps = mod->arch.map;
 
 	for (s = sechdrs; s < sechdrs_end; s++) {
-		if (strcmp(".ARM.exidx.init.text", secstrings + s->sh_name) == 0)
-			mod->arch.unw_sec_init = s;
-		else if (strcmp(".ARM.exidx.devinit.text", secstrings + s->sh_name) == 0)
-			mod->arch.unw_sec_devinit = s;
-		else if (strcmp(".ARM.exidx", secstrings + s->sh_name) == 0)
-			mod->arch.unw_sec_core = s;
-		else if (strcmp(".init.text", secstrings + s->sh_name) == 0)
-			mod->arch.sec_init_text = s;
-		else if (strcmp(".devinit.text", secstrings + s->sh_name) == 0)
-			mod->arch.sec_devinit_text = s;
-		else if (strcmp(".text", secstrings + s->sh_name) == 0)
-			mod->arch.sec_core_text = s;
+		char const *secname = secstrings + s->sh_name;
+
+		if (strcmp(".ARM.exidx.init.text", secname) == 0)
+			maps[ARM_SEC_INIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
+			maps[ARM_SEC_DEVINIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx", secname) == 0)
+			maps[ARM_SEC_CORE].unw_sec = s;
+		else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
+			maps[ARM_SEC_EXIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
+			maps[ARM_SEC_DEVEXIT].unw_sec = s;
+		else if (strcmp(".init.text", secname) == 0)
+			maps[ARM_SEC_INIT].sec_text = s;
+		else if (strcmp(".devinit.text", secname) == 0)
+			maps[ARM_SEC_DEVINIT].sec_text = s;
+		else if (strcmp(".text", secname) == 0)
+			maps[ARM_SEC_CORE].sec_text = s;
+		else if (strcmp(".exit.text", secname) == 0)
+			maps[ARM_SEC_EXIT].sec_text = s;
+		else if (strcmp(".devexit.text", secname) == 0)
+			maps[ARM_SEC_DEVEXIT].sec_text = s;
 	}
 #endif
 	return 0;
@@ -292,31 +303,22 @@
 #ifdef CONFIG_ARM_UNWIND
 static void register_unwind_tables(struct module *mod)
 {
-	if (mod->arch.unw_sec_init && mod->arch.sec_init_text)
-		mod->arch.unwind_init =
-			unwind_table_add(mod->arch.unw_sec_init->sh_addr,
-					 mod->arch.unw_sec_init->sh_size,
-					 mod->arch.sec_init_text->sh_addr,
-					 mod->arch.sec_init_text->sh_size);
-	if (mod->arch.unw_sec_devinit && mod->arch.sec_devinit_text)
-		mod->arch.unwind_devinit =
-			unwind_table_add(mod->arch.unw_sec_devinit->sh_addr,
-					 mod->arch.unw_sec_devinit->sh_size,
-					 mod->arch.sec_devinit_text->sh_addr,
-					 mod->arch.sec_devinit_text->sh_size);
-	if (mod->arch.unw_sec_core && mod->arch.sec_core_text)
-		mod->arch.unwind_core =
-			unwind_table_add(mod->arch.unw_sec_core->sh_addr,
-					 mod->arch.unw_sec_core->sh_size,
-					 mod->arch.sec_core_text->sh_addr,
-					 mod->arch.sec_core_text->sh_size);
+	int i;
+	for (i = 0; i < ARM_SEC_MAX; ++i) {
+		struct arm_unwind_mapping *map = &mod->arch.map[i];
+		if (map->unw_sec && map->sec_text)
+			map->unwind = unwind_table_add(map->unw_sec->sh_addr,
+						       map->unw_sec->sh_size,
+						       map->sec_text->sh_addr,
+						       map->sec_text->sh_size);
+	}
 }
 
 static void unregister_unwind_tables(struct module *mod)
 {
-	unwind_table_del(mod->arch.unwind_init);
-	unwind_table_del(mod->arch.unwind_devinit);
-	unwind_table_del(mod->arch.unwind_core);
+	int i = ARM_SEC_MAX;
+	while (--i >= 0)
+		unwind_table_del(mod->arch.map[i].unwind);
 }
 #else
 static inline void register_unwind_tables(struct module *mod) { }
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index ecbb028..49643b1 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -123,6 +123,12 @@
 }
 EXPORT_SYMBOL_GPL(armpmu_get_max_events);
 
+int perf_num_counters(void)
+{
+	return armpmu_get_max_events();
+}
+EXPORT_SYMBOL_GPL(perf_num_counters);
+
 #define HW_OP_UNSUPPORTED		0xFFFF
 
 #define C(_x) \
@@ -221,27 +227,6 @@
 }
 
 static void
-armpmu_disable(struct perf_event *event)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	struct hw_perf_event *hwc = &event->hw;
-	int idx = hwc->idx;
-
-	WARN_ON(idx < 0);
-
-	clear_bit(idx, cpuc->active_mask);
-	armpmu->disable(hwc, idx);
-
-	barrier();
-
-	armpmu_event_update(event, hwc, idx);
-	cpuc->events[idx] = NULL;
-	clear_bit(idx, cpuc->used_mask);
-
-	perf_event_update_userpage(event);
-}
-
-static void
 armpmu_read(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
@@ -254,13 +239,44 @@
 }
 
 static void
-armpmu_unthrottle(struct perf_event *event)
+armpmu_stop(struct perf_event *event, int flags)
 {
 	struct hw_perf_event *hwc = &event->hw;
 
+	if (!armpmu)
+		return;
+
+	/*
+	 * ARM pmu always has to update the counter, so ignore
+	 * PERF_EF_UPDATE, see comments in armpmu_start().
+	 */
+	if (!(hwc->state & PERF_HES_STOPPED)) {
+		armpmu->disable(hwc, hwc->idx);
+		barrier(); /* why? */
+		armpmu_event_update(event, hwc, hwc->idx);
+		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+	}
+}
+
+static void
+armpmu_start(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (!armpmu)
+		return;
+
+	/*
+	 * ARM pmu always has to reprogram the period, so ignore
+	 * PERF_EF_RELOAD, see the comment below.
+	 */
+	if (flags & PERF_EF_RELOAD)
+		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+
+	hwc->state = 0;
 	/*
 	 * Set the period again. Some counters can't be stopped, so when we
-	 * were throttled we simply disabled the IRQ source and the counter
+	 * were stopped we simply disabled the IRQ source and the counter
 	 * may have been left counting. If we don't do this step then we may
 	 * get an interrupt too soon or *way* too late if the overflow has
 	 * happened since disabling.
@@ -269,14 +285,33 @@
 	armpmu->enable(hwc, hwc->idx);
 }
 
+static void
+armpmu_del(struct perf_event *event, int flags)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct hw_perf_event *hwc = &event->hw;
+	int idx = hwc->idx;
+
+	WARN_ON(idx < 0);
+
+	clear_bit(idx, cpuc->active_mask);
+	armpmu_stop(event, PERF_EF_UPDATE);
+	cpuc->events[idx] = NULL;
+	clear_bit(idx, cpuc->used_mask);
+
+	perf_event_update_userpage(event);
+}
+
 static int
-armpmu_enable(struct perf_event *event)
+armpmu_add(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
 	int idx;
 	int err = 0;
 
+	perf_pmu_disable(event->pmu);
+
 	/* If we don't have a space for the counter then finish early. */
 	idx = armpmu->get_event_idx(cpuc, hwc);
 	if (idx < 0) {
@@ -293,25 +328,19 @@
 	cpuc->events[idx] = event;
 	set_bit(idx, cpuc->active_mask);
 
-	/* Set the period for the event. */
-	armpmu_event_set_period(event, hwc, idx);
-
-	/* Enable the event. */
-	armpmu->enable(hwc, idx);
+	hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+	if (flags & PERF_EF_START)
+		armpmu_start(event, PERF_EF_RELOAD);
 
 	/* Propagate our changes to the userspace mapping. */
 	perf_event_update_userpage(event);
 
 out:
+	perf_pmu_enable(event->pmu);
 	return err;
 }
 
-static struct pmu pmu = {
-	.enable	    = armpmu_enable,
-	.disable    = armpmu_disable,
-	.unthrottle = armpmu_unthrottle,
-	.read	    = armpmu_read,
-};
+static struct pmu pmu;
 
 static int
 validate_event(struct cpu_hw_events *cpuc,
@@ -491,20 +520,29 @@
 	return err;
 }
 
-const struct pmu *
-hw_perf_event_init(struct perf_event *event)
+static int armpmu_event_init(struct perf_event *event)
 {
 	int err = 0;
 
+	switch (event->attr.type) {
+	case PERF_TYPE_RAW:
+	case PERF_TYPE_HARDWARE:
+	case PERF_TYPE_HW_CACHE:
+		break;
+
+	default:
+		return -ENOENT;
+	}
+
 	if (!armpmu)
-		return ERR_PTR(-ENODEV);
+		return -ENODEV;
 
 	event->destroy = hw_perf_event_destroy;
 
 	if (!atomic_inc_not_zero(&active_events)) {
-		if (atomic_read(&active_events) > perf_max_events) {
+		if (atomic_read(&active_events) > armpmu->num_events) {
 			atomic_dec(&active_events);
-			return ERR_PTR(-ENOSPC);
+			return -ENOSPC;
 		}
 
 		mutex_lock(&pmu_reserve_mutex);
@@ -518,17 +556,16 @@
 	}
 
 	if (err)
-		return ERR_PTR(err);
+		return err;
 
 	err = __hw_perf_event_init(event);
 	if (err)
 		hw_perf_event_destroy(event);
 
-	return err ? ERR_PTR(err) : &pmu;
+	return err;
 }
 
-void
-hw_perf_enable(void)
+static void armpmu_enable(struct pmu *pmu)
 {
 	/* Enable all of the perf events on hardware. */
 	int idx;
@@ -549,13 +586,23 @@
 	armpmu->start();
 }
 
-void
-hw_perf_disable(void)
+static void armpmu_disable(struct pmu *pmu)
 {
 	if (armpmu)
 		armpmu->stop();
 }
 
+static struct pmu pmu = {
+	.pmu_enable	= armpmu_enable,
+	.pmu_disable	= armpmu_disable,
+	.event_init	= armpmu_event_init,
+	.add		= armpmu_add,
+	.del		= armpmu_del,
+	.start		= armpmu_start,
+	.stop		= armpmu_stop,
+	.read		= armpmu_read,
+};
+
 /*
  * ARMv6 Performance counter handling code.
  *
@@ -1045,7 +1092,7 @@
 	 * platforms that can have the PMU interrupts raised as an NMI, this
 	 * will not work.
 	 */
-	perf_event_do_pending();
+	irq_work_run();
 
 	return IRQ_HANDLED;
 }
@@ -2021,7 +2068,7 @@
 	 * platforms that can have the PMU interrupts raised as an NMI, this
 	 * will not work.
 	 */
-	perf_event_do_pending();
+	irq_work_run();
 
 	return IRQ_HANDLED;
 }
@@ -2389,7 +2436,7 @@
 			armpmu->disable(hwc, idx);
 	}
 
-	perf_event_do_pending();
+	irq_work_run();
 
 	/*
 	 * Re-enable the PMU.
@@ -2716,7 +2763,7 @@
 			armpmu->disable(hwc, idx);
 	}
 
-	perf_event_do_pending();
+	irq_work_run();
 
 	/*
 	 * Re-enable the PMU.
@@ -2933,14 +2980,12 @@
 			armpmu = &armv6pmu;
 			memcpy(armpmu_perf_cache_map, armv6_perf_cache_map,
 					sizeof(armv6_perf_cache_map));
-			perf_max_events	= armv6pmu.num_events;
 			break;
 		case 0xB020:	/* ARM11mpcore */
 			armpmu = &armv6mpcore_pmu;
 			memcpy(armpmu_perf_cache_map,
 			       armv6mpcore_perf_cache_map,
 			       sizeof(armv6mpcore_perf_cache_map));
-			perf_max_events = armv6mpcore_pmu.num_events;
 			break;
 		case 0xC080:	/* Cortex-A8 */
 			armv7pmu.id = ARM_PERF_PMU_ID_CA8;
@@ -2952,7 +2997,6 @@
 			/* Reset PMNC and read the nb of CNTx counters
 			    supported */
 			armv7pmu.num_events = armv7_reset_read_pmnc();
-			perf_max_events = armv7pmu.num_events;
 			break;
 		case 0xC090:	/* Cortex-A9 */
 			armv7pmu.id = ARM_PERF_PMU_ID_CA9;
@@ -2964,7 +3008,6 @@
 			/* Reset PMNC and read the nb of CNTx counters
 			    supported */
 			armv7pmu.num_events = armv7_reset_read_pmnc();
-			perf_max_events = armv7pmu.num_events;
 			break;
 		}
 	/* Intel CPUs [xscale]. */
@@ -2975,13 +3018,11 @@
 			armpmu = &xscale1pmu;
 			memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
 					sizeof(xscale_perf_cache_map));
-			perf_max_events	= xscale1pmu.num_events;
 			break;
 		case 2:
 			armpmu = &xscale2pmu;
 			memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
 					sizeof(xscale_perf_cache_map));
-			perf_max_events	= xscale2pmu.num_events;
 			break;
 		}
 	}
@@ -2991,9 +3032,10 @@
 				arm_pmu_names[armpmu->id], armpmu->num_events);
 	} else {
 		pr_info("no hardware support available\n");
-		perf_max_events = -1;
 	}
 
+	perf_pmu_register(&pmu);
+
 	return 0;
 }
 arch_initcall(init_hw_perf_events);
@@ -3001,13 +3043,6 @@
 /*
  * Callchain handling code.
  */
-static inline void
-callchain_store(struct perf_callchain_entry *entry,
-		u64 ip)
-{
-	if (entry->nr < PERF_MAX_STACK_DEPTH)
-		entry->ip[entry->nr++] = ip;
-}
 
 /*
  * The registers we're interested in are at the end of the variable
@@ -3039,7 +3074,7 @@
 	if (__copy_from_user_inatomic(&buftail, tail, sizeof(buftail)))
 		return NULL;
 
-	callchain_store(entry, buftail.lr);
+	perf_callchain_store(entry, buftail.lr);
 
 	/*
 	 * Frame pointers should strictly progress back up the stack
@@ -3051,16 +3086,11 @@
 	return buftail.fp - 1;
 }
 
-static void
-perf_callchain_user(struct pt_regs *regs,
-		    struct perf_callchain_entry *entry)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
 	struct frame_tail *tail;
 
-	callchain_store(entry, PERF_CONTEXT_USER);
-
-	if (!user_mode(regs))
-		regs = task_pt_regs(current);
 
 	tail = (struct frame_tail *)regs->ARM_fp - 1;
 
@@ -3078,56 +3108,18 @@
 		void *data)
 {
 	struct perf_callchain_entry *entry = data;
-	callchain_store(entry, fr->pc);
+	perf_callchain_store(entry, fr->pc);
 	return 0;
 }
 
-static void
-perf_callchain_kernel(struct pt_regs *regs,
-		      struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
 	struct stackframe fr;
 
-	callchain_store(entry, PERF_CONTEXT_KERNEL);
 	fr.fp = regs->ARM_fp;
 	fr.sp = regs->ARM_sp;
 	fr.lr = regs->ARM_lr;
 	fr.pc = regs->ARM_pc;
 	walk_stackframe(&fr, callchain_trace, entry);
 }
-
-static void
-perf_do_callchain(struct pt_regs *regs,
-		  struct perf_callchain_entry *entry)
-{
-	int is_user;
-
-	if (!regs)
-		return;
-
-	is_user = user_mode(regs);
-
-	if (!current || !current->pid)
-		return;
-
-	if (is_user && current->state != TASK_RUNNING)
-		return;
-
-	if (!is_user)
-		perf_callchain_kernel(regs, entry);
-
-	if (current->mm)
-		perf_callchain_user(regs, entry);
-}
-
-static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry);
-
-struct perf_callchain_entry *
-perf_callchain(struct pt_regs *regs)
-{
-	struct perf_callchain_entry *entry = &__get_cpu_var(pmc_irq_entry);
-
-	entry->nr = 0;
-	perf_do_callchain(regs, entry);
-	return entry;
-}
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 401e38b..e76fcaa 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -29,6 +29,7 @@
 #include <linux/utsname.h>
 #include <linux/uaccess.h>
 #include <linux/random.h>
+#include <linux/hw_breakpoint.h>
 
 #include <asm/cacheflush.h>
 #include <asm/leds.h>
@@ -135,6 +136,25 @@
 void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart;
 EXPORT_SYMBOL_GPL(arm_pm_restart);
 
+static void do_nothing(void *unused)
+{
+}
+
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+ * pm_idle and update to new pm_idle value. Required while changing pm_idle
+ * handler on SMP systems.
+ *
+ * Caller must have changed pm_idle to the new value before the call. Old
+ * pm_idle value will not be used by any CPU after the return of this function.
+ */
+void cpu_idle_wait(void)
+{
+	smp_mb();
+	/* kick all the CPUs so that they exit out of pm_idle */
+	smp_call_function(do_nothing, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(cpu_idle_wait);
 
 /*
  * This is our default idle handler.  We need to disable
@@ -317,6 +337,8 @@
 	struct thread_info *thread = current_thread_info();
 	struct task_struct *tsk = current;
 
+	flush_ptrace_hw_breakpoint(tsk);
+
 	memset(thread->used_cp, 0, sizeof(thread->used_cp));
 	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
 	memset(&thread->fpstate, 0, sizeof(union fp_state));
@@ -345,6 +367,8 @@
 	thread->cpu_context.sp = (unsigned long)childregs;
 	thread->cpu_context.pc = (unsigned long)ret_from_fork;
 
+	clear_ptrace_hw_breakpoint(p);
+
 	if (clone_flags & CLONE_SETTLS)
 		thread->tp_value = regs->ARM_r3;
 
@@ -458,3 +482,24 @@
 	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/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index f99d489..e0cb637 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -19,6 +19,8 @@
 #include <linux/init.h>
 #include <linux/signal.h>
 #include <linux/uaccess.h>
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -847,6 +849,232 @@
 }
 #endif
 
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+/*
+ * Convert a virtual register number into an index for a thread_info
+ * breakpoint array. Breakpoints are identified using positive numbers
+ * whilst watchpoints are negative. The registers are laid out as pairs
+ * of (address, control), each pair mapping to a unique hw_breakpoint struct.
+ * Register 0 is reserved for describing resource information.
+ */
+static int ptrace_hbp_num_to_idx(long num)
+{
+	if (num < 0)
+		num = (ARM_MAX_BRP << 1) - num;
+	return (num - 1) >> 1;
+}
+
+/*
+ * Returns the virtual register number for the address of the
+ * breakpoint at index idx.
+ */
+static long ptrace_hbp_idx_to_num(int idx)
+{
+	long mid = ARM_MAX_BRP << 1;
+	long num = (idx << 1) + 1;
+	return num > mid ? mid - num : num;
+}
+
+/*
+ * Handle hitting a HW-breakpoint.
+ */
+static void ptrace_hbptriggered(struct perf_event *bp, int unused,
+				     struct perf_sample_data *data,
+				     struct pt_regs *regs)
+{
+	struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
+	long num;
+	int i;
+	siginfo_t info;
+
+	for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i)
+		if (current->thread.debug.hbp[i] == bp)
+			break;
+
+	num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i);
+
+	info.si_signo	= SIGTRAP;
+	info.si_errno	= (int)num;
+	info.si_code	= TRAP_HWBKPT;
+	info.si_addr	= (void __user *)(bkpt->trigger);
+
+	force_sig_info(SIGTRAP, &info, current);
+}
+
+/*
+ * Set ptrace breakpoint pointers to zero for this task.
+ * This is required in order to prevent child processes from unregistering
+ * breakpoints held by their parent.
+ */
+void clear_ptrace_hw_breakpoint(struct task_struct *tsk)
+{
+	memset(tsk->thread.debug.hbp, 0, sizeof(tsk->thread.debug.hbp));
+}
+
+/*
+ * Unregister breakpoints from this task and reset the pointers in
+ * the thread_struct.
+ */
+void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
+{
+	int i;
+	struct thread_struct *t = &tsk->thread;
+
+	for (i = 0; i < ARM_MAX_HBP_SLOTS; i++) {
+		if (t->debug.hbp[i]) {
+			unregister_hw_breakpoint(t->debug.hbp[i]);
+			t->debug.hbp[i] = NULL;
+		}
+	}
+}
+
+static u32 ptrace_get_hbp_resource_info(void)
+{
+	u8 num_brps, num_wrps, debug_arch, wp_len;
+	u32 reg = 0;
+
+	num_brps	= hw_breakpoint_slots(TYPE_INST);
+	num_wrps	= hw_breakpoint_slots(TYPE_DATA);
+	debug_arch	= arch_get_debug_arch();
+	wp_len		= arch_get_max_wp_len();
+
+	reg		|= debug_arch;
+	reg		<<= 8;
+	reg		|= wp_len;
+	reg		<<= 8;
+	reg		|= num_wrps;
+	reg		<<= 8;
+	reg		|= num_brps;
+
+	return reg;
+}
+
+static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
+{
+	struct perf_event_attr attr;
+
+	ptrace_breakpoint_init(&attr);
+
+	/* Initialise fields to sane defaults. */
+	attr.bp_addr	= 0;
+	attr.bp_len	= HW_BREAKPOINT_LEN_4;
+	attr.bp_type	= type;
+	attr.disabled	= 1;
+
+	return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, tsk);
+}
+
+static int ptrace_gethbpregs(struct task_struct *tsk, long num,
+			     unsigned long  __user *data)
+{
+	u32 reg;
+	int idx, ret = 0;
+	struct perf_event *bp;
+	struct arch_hw_breakpoint_ctrl arch_ctrl;
+
+	if (num == 0) {
+		reg = ptrace_get_hbp_resource_info();
+	} else {
+		idx = ptrace_hbp_num_to_idx(num);
+		if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		bp = tsk->thread.debug.hbp[idx];
+		if (!bp) {
+			reg = 0;
+			goto put;
+		}
+
+		arch_ctrl = counter_arch_bp(bp)->ctrl;
+
+		/*
+		 * Fix up the len because we may have adjusted it
+		 * to compensate for an unaligned address.
+		 */
+		while (!(arch_ctrl.len & 0x1))
+			arch_ctrl.len >>= 1;
+
+		if (idx & 0x1)
+			reg = encode_ctrl_reg(arch_ctrl);
+		else
+			reg = bp->attr.bp_addr;
+	}
+
+put:
+	if (put_user(reg, data))
+		ret = -EFAULT;
+
+out:
+	return ret;
+}
+
+static int ptrace_sethbpregs(struct task_struct *tsk, long num,
+			     unsigned long __user *data)
+{
+	int idx, gen_len, gen_type, implied_type, ret = 0;
+	u32 user_val;
+	struct perf_event *bp;
+	struct arch_hw_breakpoint_ctrl ctrl;
+	struct perf_event_attr attr;
+
+	if (num == 0)
+		goto out;
+	else if (num < 0)
+		implied_type = HW_BREAKPOINT_RW;
+	else
+		implied_type = HW_BREAKPOINT_X;
+
+	idx = ptrace_hbp_num_to_idx(num);
+	if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (get_user(user_val, data)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	bp = tsk->thread.debug.hbp[idx];
+	if (!bp) {
+		bp = ptrace_hbp_create(tsk, implied_type);
+		if (IS_ERR(bp)) {
+			ret = PTR_ERR(bp);
+			goto out;
+		}
+		tsk->thread.debug.hbp[idx] = bp;
+	}
+
+	attr = bp->attr;
+
+	if (num & 0x1) {
+		/* Address */
+		attr.bp_addr	= user_val;
+	} else {
+		/* Control */
+		decode_ctrl_reg(user_val, &ctrl);
+		ret = arch_bp_generic_fields(ctrl, &gen_len, &gen_type);
+		if (ret)
+			goto out;
+
+		if ((gen_type & implied_type) != gen_type) {
+				ret = -EINVAL;
+				goto out;
+		}
+
+		attr.bp_len	= gen_len;
+		attr.bp_type	= gen_type;
+		attr.disabled	= !ctrl.enabled;
+	}
+
+	ret = modify_user_hw_breakpoint(bp, &attr);
+out:
+	return ret;
+}
+#endif
+
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
 	int ret;
@@ -916,6 +1144,17 @@
 			break;
 #endif
 
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+		case PTRACE_GETHBPREGS:
+			ret = ptrace_gethbpregs(child, addr,
+						(unsigned long __user *)data);
+			break;
+		case PTRACE_SETHBPREGS:
+			ret = ptrace_sethbpregs(child, addr,
+						(unsigned long __user *)data);
+			break;
+#endif
+
 		default:
 			ret = ptrace_request(child, request, addr, data);
 			break;
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index d5231ae..336f14e 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -36,6 +36,7 @@
 #include <asm/procinfo.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
+#include <asm/smp_plat.h>
 #include <asm/mach-types.h>
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
@@ -238,6 +239,35 @@
 	return cpu_arch;
 }
 
+static int cpu_has_aliasing_icache(unsigned int arch)
+{
+	int aliasing_icache;
+	unsigned int id_reg, num_sets, line_size;
+
+	/* arch specifies the register format */
+	switch (arch) {
+	case CPU_ARCH_ARMv7:
+		asm("mcr	p15, 2, %0, c0, c0, 0 @ set CSSELR"
+		    : /* No output operands */
+		    : "r" (1));
+		isb();
+		asm("mrc	p15, 1, %0, c0, c0, 0 @ read CCSIDR"
+		    : "=r" (id_reg));
+		line_size = 4 << ((id_reg & 0x7) + 2);
+		num_sets = ((id_reg >> 13) & 0x7fff) + 1;
+		aliasing_icache = (line_size * num_sets) > PAGE_SIZE;
+		break;
+	case CPU_ARCH_ARMv6:
+		aliasing_icache = read_cpuid_cachetype() & (1 << 11);
+		break;
+	default:
+		/* I-cache aliases will be handled by D-cache aliasing code */
+		aliasing_icache = 0;
+	}
+
+	return aliasing_icache;
+}
+
 static void __init cacheid_init(void)
 {
 	unsigned int cachetype = read_cpuid_cachetype();
@@ -249,10 +279,15 @@
 			cacheid = CACHEID_VIPT_NONALIASING;
 			if ((cachetype & (3 << 14)) == 1 << 14)
 				cacheid |= CACHEID_ASID_TAGGED;
-		} else if (cachetype & (1 << 23))
+			else if (cpu_has_aliasing_icache(CPU_ARCH_ARMv7))
+				cacheid |= CACHEID_VIPT_I_ALIASING;
+		} else if (cachetype & (1 << 23)) {
 			cacheid = CACHEID_VIPT_ALIASING;
-		else
+		} else {
 			cacheid = CACHEID_VIPT_NONALIASING;
+			if (cpu_has_aliasing_icache(CPU_ARCH_ARMv6))
+				cacheid |= CACHEID_VIPT_I_ALIASING;
+		}
 	} else {
 		cacheid = CACHEID_VIVT;
 	}
@@ -263,7 +298,7 @@
 		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
 		cache_is_vivt() ? "VIVT" :
 		icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
-		cache_is_vipt_aliasing() ? "VIPT aliasing" :
+		icache_is_vipt_aliasing() ? "VIPT aliasing" :
 		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
 }
 
@@ -490,7 +525,7 @@
 
 	kernel_code.start   = virt_to_phys(_text);
 	kernel_code.end     = virt_to_phys(_etext - 1);
-	kernel_data.start   = virt_to_phys(_data);
+	kernel_data.start   = virt_to_phys(_sdata);
 	kernel_data.end     = virt_to_phys(_end - 1);
 
 	for (i = 0; i < mi->nr_banks; i++) {
@@ -825,7 +860,8 @@
 	request_standard_resources(&meminfo, mdesc);
 
 #ifdef CONFIG_SMP
-	smp_init_cpus();
+	if (is_smp())
+		smp_init_cpus();
 #endif
 	reserve_crashkernel();
 
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 40dc74f..8c19595 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -33,6 +33,7 @@
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
+#include <asm/sections.h>
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
 #include <asm/localtimer.h>
@@ -67,12 +68,47 @@
 	IPI_CPU_STOP,
 };
 
+static inline void identity_mapping_add(pgd_t *pgd, unsigned long start,
+	unsigned long end)
+{
+	unsigned long addr, prot;
+	pmd_t *pmd;
+
+	prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
+	if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
+		prot |= PMD_BIT4;
+
+	for (addr = start & PGDIR_MASK; addr < end;) {
+		pmd = pmd_offset(pgd + pgd_index(addr), addr);
+		pmd[0] = __pmd(addr | prot);
+		addr += SECTION_SIZE;
+		pmd[1] = __pmd(addr | prot);
+		addr += SECTION_SIZE;
+		flush_pmd_entry(pmd);
+		outer_clean_range(__pa(pmd), __pa(pmd + 1));
+	}
+}
+
+static inline void identity_mapping_del(pgd_t *pgd, unsigned long start,
+	unsigned long end)
+{
+	unsigned long addr;
+	pmd_t *pmd;
+
+	for (addr = start & PGDIR_MASK; addr < end; addr += PGDIR_SIZE) {
+		pmd = pmd_offset(pgd + pgd_index(addr), addr);
+		pmd[0] = __pmd(0);
+		pmd[1] = __pmd(0);
+		clean_pmd_entry(pmd);
+		outer_clean_range(__pa(pmd), __pa(pmd + 1));
+	}
+}
+
 int __cpuinit __cpu_up(unsigned int cpu)
 {
 	struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
 	struct task_struct *idle = ci->idle;
 	pgd_t *pgd;
-	pmd_t *pmd;
 	int ret;
 
 	/*
@@ -101,11 +137,16 @@
 	 * a 1:1 mapping for the physical address of the kernel.
 	 */
 	pgd = pgd_alloc(&init_mm);
-	pmd = pmd_offset(pgd + pgd_index(PHYS_OFFSET), PHYS_OFFSET);
-	*pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
-		     PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
-	flush_pmd_entry(pmd);
-	outer_clean_range(__pa(pmd), __pa(pmd + 1));
+	if (!pgd)
+		return -ENOMEM;
+
+	if (PHYS_OFFSET != PAGE_OFFSET) {
+#ifndef CONFIG_HOTPLUG_CPU
+		identity_mapping_add(pgd, __pa(__init_begin), __pa(__init_end));
+#endif
+		identity_mapping_add(pgd, __pa(_stext), __pa(_etext));
+		identity_mapping_add(pgd, __pa(_sdata), __pa(_edata));
+	}
 
 	/*
 	 * We need to tell the secondary core where to find
@@ -143,8 +184,14 @@
 	secondary_data.stack = NULL;
 	secondary_data.pgdir = 0;
 
-	*pmd = __pmd(0);
-	clean_pmd_entry(pmd);
+	if (PHYS_OFFSET != PAGE_OFFSET) {
+#ifndef CONFIG_HOTPLUG_CPU
+		identity_mapping_del(pgd, __pa(__init_begin), __pa(__init_end));
+#endif
+		identity_mapping_del(pgd, __pa(_stext), __pa(_etext));
+		identity_mapping_del(pgd, __pa(_sdata), __pa(_edata));
+	}
+
 	pgd_free(&init_mm, pgd);
 
 	if (ret) {
@@ -567,7 +614,8 @@
 {
 	cpumask_t mask = cpu_online_map;
 	cpu_clear(smp_processor_id(), mask);
-	send_ipi_message(&mask, IPI_CPU_STOP);
+	if (!cpus_empty(mask))
+		send_ipi_message(&mask, IPI_CPU_STOP);
 }
 
 /*
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index dd81a91..2a16176 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -146,6 +146,8 @@
 			    addr < table->end_addr) {
 				idx = search_index(addr, table->start,
 						   table->stop - 1);
+				/* Move-to-front to exploit common traces */
+				list_move(&table->list, &unwind_tables);
 				break;
 			}
 		}
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index b16c079..1953e3d 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -8,6 +8,19 @@
 #include <asm/memory.h>
 #include <asm/page.h>
 	
+#define PROC_INFO							\
+	VMLINUX_SYMBOL(__proc_info_begin) = .;				\
+	*(.proc.info.init)						\
+	VMLINUX_SYMBOL(__proc_info_end) = .;
+
+#ifdef CONFIG_HOTPLUG_CPU
+#define ARM_CPU_DISCARD(x)
+#define ARM_CPU_KEEP(x)		x
+#else
+#define ARM_CPU_DISCARD(x)	x
+#define ARM_CPU_KEEP(x)
+#endif
+
 OUTPUT_ARCH(arm)
 ENTRY(stext)
 
@@ -31,15 +44,18 @@
 			HEAD_TEXT
 			INIT_TEXT
 		_einittext = .;
-		__proc_info_begin = .;
-			*(.proc.info.init)
-		__proc_info_end = .;
+		ARM_CPU_DISCARD(PROC_INFO)
 		__arch_info_begin = .;
 			*(.arch.info.init)
 		__arch_info_end = .;
 		__tagtable_begin = .;
 			*(.taglist.init)
 		__tagtable_end = .;
+#ifdef CONFIG_SMP_ON_UP
+		__smpalt_begin = .;
+			*(.alt.smp.init)
+		__smpalt_end = .;
+#endif
 
 		INIT_SETUP(16)
 
@@ -68,10 +84,8 @@
 	/DISCARD/ : {
 		*(.ARM.exidx.exit.text)
 		*(.ARM.extab.exit.text)
-#ifndef CONFIG_HOTPLUG_CPU
-		*(.ARM.exidx.cpuexit.text)
-		*(.ARM.extab.cpuexit.text)
-#endif
+		ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
+		ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
 #ifndef CONFIG_HOTPLUG
 		*(.ARM.exidx.devexit.text)
 		*(.ARM.extab.devexit.text)
@@ -100,12 +114,11 @@
 			*(.glue_7)
 			*(.glue_7t)
 		*(.got)			/* Global offset table		*/
+			ARM_CPU_KEEP(PROC_INFO)
 	}
 
 	RO_DATA(PAGE_SIZE)
 
-	_etext = .;			/* End of text and rodata section */
-
 #ifdef CONFIG_ARM_UNWIND
 	/*
 	 * Stack unwinding tables
@@ -123,6 +136,8 @@
 	}
 #endif
 
+	_etext = .;			/* End of text and rodata section */
+
 #ifdef CONFIG_XIP_KERNEL
 	__data_loc = ALIGN(4);		/* location in binary */
 	. = PAGE_OFFSET + TEXT_OFFSET;
@@ -237,6 +252,12 @@
 
 	/* Default discards */
 	DISCARDS
+
+#ifndef CONFIG_SMP_ON_UP
+	/DISCARD/ : {
+		*(.alt.smp.init)
+	}
+#endif
 }
 
 /*
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
index 81a3ecc..0eb3e3e 100644
--- a/arch/arm/mach-aaec2000/aaed2000.c
+++ b/arch/arm/mach-aaec2000/aaed2000.c
@@ -95,8 +95,6 @@
 
 MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
 	/* Maintainer: Nicolas Bellido Y Ortega */
-	.phys_io	= PIO_BASE,
-	.io_pg_offst	= ((VIO_BASE) >> 18) & 0xfffc,
 	.map_io		= aaed2000_map_io,
 	.init_irq	= aaed2000_init_irq,
 	.timer		= &aaec2000_timer,
diff --git a/arch/arm/mach-aaec2000/include/mach/debug-macro.S b/arch/arm/mach-aaec2000/include/mach/debug-macro.S
index a9cac36..bc7ad55 100644
--- a/arch/arm/mach-aaec2000/include/mach/debug-macro.S
+++ b/arch/arm/mach-aaec2000/include/mach/debug-macro.S
@@ -10,12 +10,10 @@
  */
 
 #include "hardware.h"
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x80000000		@ physical
-		movne	\rx, #io_p2v(0x80000000)	@ virtual
-		orr	\rx, \rx, #0x00000800
+		.macro	addruart, rp, rv
+		mov	\rp, 0x00000800
+		orr	\rv, \rp, #io_p2v(0x80000000)	@ virtual
+		orr	\rp, \rp, #0x80000000		@ physical
 		.endm
 
 		.macro	senduart,rd,rx
diff --git a/arch/arm/mach-aaec2000/include/mach/vmalloc.h b/arch/arm/mach-aaec2000/include/mach/vmalloc.h
index 551f68f..cff4e0a 100644
--- a/arch/arm/mach-aaec2000/include/mach/vmalloc.h
+++ b/arch/arm/mach-aaec2000/include/mach/vmalloc.h
@@ -11,6 +11,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-#define VMALLOC_END		(PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END		0xd0000000
 
 #endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 939bccd..851e813 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -33,6 +33,7 @@
 	select HAVE_AT91_USART3
 	select HAVE_AT91_USART4
 	select HAVE_AT91_USART5
+	select HAVE_NET_MACB
 
 config ARCH_AT91SAM9261
 	bool "AT91SAM9261"
@@ -51,6 +52,7 @@
 	select CPU_ARM926T
 	select GENERIC_CLOCKEVENTS
 	select HAVE_FB_ATMEL
+	select HAVE_NET_MACB
 
 config ARCH_AT91SAM9RL
 	bool "AT91SAM9RL"
@@ -66,6 +68,7 @@
 	select HAVE_AT91_USART3
 	select HAVE_AT91_USART4
 	select HAVE_AT91_USART5
+	select HAVE_NET_MACB
 
 config ARCH_AT91SAM9G45
 	bool "AT91SAM9G45"
@@ -73,6 +76,7 @@
 	select GENERIC_CLOCKEVENTS
 	select HAVE_AT91_USART3
 	select HAVE_FB_ATMEL
+	select HAVE_NET_MACB
 
 config ARCH_AT91CAP9
 	bool "AT91CAP9"
@@ -248,6 +252,12 @@
 	  Select this if you are using a Eukrea Electromatique's
 	  CPU9260 Board <http://www.eukrea.com/>
 
+config MACH_FLEXIBITY
+	bool "Flexibity Connect board"
+	help
+	  Select this if you are using Flexibity Connect board
+	  <http://www.flexibity.com>
+
 endif
 
 # ----------------------------------------------------------
@@ -338,6 +348,7 @@
 	  that embeds only one SD/MMC slot.
 
 config MACH_AT91SAM9G20EK_2MMC
+	depends on MACH_AT91SAM9G20EK
 	bool "Atmel AT91SAM9G20-EK Evaluation Kit with 2 SD/MMC Slots"
 	select HAVE_NAND_ATMEL_BUSWIDTH_16
 	help
@@ -383,8 +394,8 @@
 
 comment "AT91SAM9G45 Board Type"
 
-config MACH_AT91SAM9G45EKES
-	bool "Atmel AT91SAM9G45-EKES Evaluation Kit"
+config MACH_AT91SAM9M10G45EK
+	bool "Atmel AT91SAM9M10G45-EK Evaluation Kits"
 	select HAVE_NAND_ATMEL_BUSWIDTH_16
 	help
 	  Select this if you are using Atmel's AT91SAM9G45-EKES Evaluation Kit.
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index ca2ac00..412b3a4 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -46,6 +46,7 @@
 obj-$(CONFIG_MACH_QIL_A9260)	+= board-qil-a9260.o
 obj-$(CONFIG_MACH_AFEB9260)	+= board-afeb-9260v1.o
 obj-$(CONFIG_MACH_CPU9260)	+= board-cpu9krea.o
+obj-$(CONFIG_MACH_FLEXIBITY)	+= board-flexibity.o
 
 # AT91SAM9261 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
@@ -61,7 +62,6 @@
 
 # AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
-obj-$(CONFIG_MACH_AT91SAM9G20EK_2MMC) += board-sam9g20ek-2slot-mmc.o
 obj-$(CONFIG_MACH_CPU9G20)	+= board-cpu9krea.o
 obj-$(CONFIG_MACH_STAMP9G20)	+= board-stamp9g20.o
 obj-$(CONFIG_MACH_PORTUXG20)	+= board-stamp9g20.o
@@ -70,7 +70,7 @@
 obj-$(CONFIG_MACH_SNAPPER_9260)	+= board-snapper9260.o
 
 # AT91SAM9G45 board-specific support
-obj-$(CONFIG_MACH_AT91SAM9G45EKES) += board-sam9m10g45ek.o
+obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
 
 # AT91CAP9 board-specific support
 obj-$(CONFIG_MACH_AT91CAP9ADK)	+= board-cap9adk.o
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 5e71ccd..1276bab 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -426,7 +426,7 @@
 	.sda_is_open_drain	= 1,
 	.scl_pin		= AT91_PIN_PA21,
 	.scl_is_open_drain	= 1,
-	.udelay			= 2,		/* ~100 kHz */
+	.udelay			= 5,		/* ~100 kHz */
 };
 
 static struct platform_device at91sam9g45_twi0_device = {
@@ -440,7 +440,7 @@
 	.sda_is_open_drain	= 1,
 	.scl_pin		= AT91_PIN_PB11,
 	.scl_is_open_drain	= 1,
-	.udelay			= 2,		/* ~100 kHz */
+	.udelay			= 5,		/* ~100 kHz */
 };
 
 static struct platform_device at91sam9g45_twi1_device = {
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
index 9b27d16..46bdc82 100644
--- a/arch/arm/mach-at91/board-1arm.c
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -92,8 +92,6 @@
 
 MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= onearm_map_io,
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index 50667be..cba7f77 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -218,8 +218,6 @@
 
 MACHINE_START(AFEB9260, "Custom afeb9260 board")
 	/* Maintainer: Sergey Lapin <slapin@ossfans.org> */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= afeb9260_map_io,
diff --git a/arch/arm/mach-at91/board-at572d940hf_ek.c b/arch/arm/mach-at91/board-at572d940hf_ek.c
index 5daff27..3929f1c 100644
--- a/arch/arm/mach-at91/board-at572d940hf_ek.c
+++ b/arch/arm/mach-at91/board-at572d940hf_ek.c
@@ -216,7 +216,7 @@
 /*	.rdy_pin	= AT91_PIN_PC16, */
 	.enable_pin	= AT91_PIN_PA15,
 	.partition_info	= nand_partitions,
-#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
 	.bus_width_16	= 1,
 #else
 	.bus_width_16	= 0,
@@ -318,8 +318,6 @@
 
 MACHINE_START(AT572D940HFEB, "Atmel AT91D940HF-EB")
 	/* Maintainer: Atmel <costa.antonior@gmail.com> */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= eb_map_io,
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index 44eb9f7..b54e3e6 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -198,8 +198,6 @@
 
 MACHINE_START(CAM60, "KwikByte CAM60")
 	/* Maintainer: KwikByte */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= cam60_map_io,
diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c
index d694087..e727444 100644
--- a/arch/arm/mach-at91/board-cap9adk.c
+++ b/arch/arm/mach-at91/board-cap9adk.c
@@ -399,8 +399,6 @@
 
 MACHINE_START(AT91CAP9ADK, "Atmel AT91CAP9A-DK")
 	/* Maintainer: Stelian Pop <stelian.pop@leadtechdesign.com> */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= cap9adk_map_io,
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index db1f954..2e74a19 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -162,8 +162,6 @@
 
 MACHINE_START(CARMEVA, "Carmeva")
 	/* Maintainer: Conitec Datasystems */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= carmeva_map_io,
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index 4bc2e9f..3838594 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -375,8 +375,6 @@
 MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
 #endif
 	/* Maintainer: Eric Benard - EUKREA Electromatique */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= cpu9krea_map_io,
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
index a28d996..2f4dd8c 100644
--- a/arch/arm/mach-at91/board-cpuat91.c
+++ b/arch/arm/mach-at91/board-cpuat91.c
@@ -175,8 +175,6 @@
 
 MACHINE_START(CPUAT91, "Eukrea")
 	/* Maintainer: Eric Benard - EUKREA Electromatique */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= cpuat91_map_io,
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index fea2529..464839d 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -257,8 +257,6 @@
 
 MACHINE_START(CSB337, "Cogent CSB337")
 	/* Maintainer: Bill Gatliff */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= csb337_map_io,
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index cfa3f04..431688c 100644
--- a/arch/arm/mach-at91/board-csb637.c
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -138,8 +138,6 @@
 
 MACHINE_START(CSB637, "Cogent CSB637")
 	/* Maintainer: Bill Gatliff */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= csb637_map_io,
diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c
index 0fd0f5b..e14f0e1 100644
--- a/arch/arm/mach-at91/board-dk.c
+++ b/arch/arm/mach-at91/board-dk.c
@@ -225,8 +225,6 @@
 
 MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
 	/* Maintainer: SAN People/Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= dk_map_io,
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index 52865676..6cf6566 100644
--- a/arch/arm/mach-at91/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -120,8 +120,6 @@
 }
 
 MACHINE_START(ATEB9200, "Embest ATEB9200")
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= eb9200_map_io,
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
index 1d69908..7b58c94 100644
--- a/arch/arm/mach-at91/board-ecbat91.c
+++ b/arch/arm/mach-at91/board-ecbat91.c
@@ -168,8 +168,6 @@
 
 MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
 	/* Maintainer: emQbit.com */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= ecb_at91map_io,
diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
index 295a966..a158a0c 100644
--- a/arch/arm/mach-at91/board-eco920.c
+++ b/arch/arm/mach-at91/board-eco920.c
@@ -148,8 +148,6 @@
 
 MACHINE_START(ECO920, "eco920")
 	/* Maintainer: Sascha Hauer */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= eco920_map_io,
diff --git a/arch/arm/mach-at91/board-ek.c b/arch/arm/mach-at91/board-ek.c
index 4cdfaac..56e92c4 100644
--- a/arch/arm/mach-at91/board-ek.c
+++ b/arch/arm/mach-at91/board-ek.c
@@ -191,8 +191,6 @@
 
 MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
 	/* Maintainer: SAN People/Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= ek_map_io,
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
new file mode 100644
index 0000000..c8a62dc
--- /dev/null
+++ b/arch/arm/mach-at91/board-flexibity.c
@@ -0,0 +1,162 @@
+/*
+ * linux/arch/arm/mach-at91/board-flexibity.c
+ *
+ *  Copyright (C) 2010 Flexibity
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2006 Atmel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+
+#include "generic.h"
+
+static void __init flexibity_map_io(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91sam9260_initialize(18432000);
+
+	/* DBGU on ttyS0. (Rx & Tx only) */
+	at91_register_uart(0, 0, 0);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+}
+
+static void __init flexibity_init_irq(void)
+{
+	at91sam9260_init_interrupts(NULL);
+}
+
+/* USB Host port */
+static struct at91_usbh_data __initdata flexibity_usbh_data = {
+	.ports		= 2,
+};
+
+/* USB Device port */
+static struct at91_udc_data __initdata flexibity_udc_data = {
+	.vbus_pin	= AT91_PIN_PC5,
+	.pullup_pin	= 0,		/* pull-up driven by UDC */
+};
+
+/* SPI devices */
+static struct spi_board_info flexibity_spi_devices[] = {
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 1,
+		.max_speed_hz	= 15 * 1000 * 1000,
+		.bus_num	= 0,
+	},
+};
+
+/* MCI (SD/MMC) */
+static struct at91_mmc_data __initdata flexibity_mmc_data = {
+	.slot_b		= 0,
+	.wire4		= 1,
+	.det_pin	= AT91_PIN_PC9,
+	.wp_pin		= AT91_PIN_PC4,
+};
+
+/* LEDs */
+static struct gpio_led flexibity_leds[] = {
+	{
+		.name			= "usb1:green",
+		.gpio			= AT91_PIN_PA12,
+		.active_low		= 1,
+		.default_trigger	= "default-on",
+	},
+	{
+		.name			= "usb1:red",
+		.gpio			= AT91_PIN_PA13,
+		.active_low		= 1,
+		.default_trigger	= "default-on",
+	},
+	{
+		.name			= "usb2:green",
+		.gpio			= AT91_PIN_PB26,
+		.active_low		= 1,
+		.default_trigger	= "default-on",
+	},
+	{
+		.name			= "usb2:red",
+		.gpio			= AT91_PIN_PB27,
+		.active_low		= 1,
+		.default_trigger	= "default-on",
+	},
+	{
+		.name			= "usb3:green",
+		.gpio			= AT91_PIN_PC8,
+		.active_low		= 1,
+		.default_trigger	= "default-on",
+	},
+	{
+		.name			= "usb3:red",
+		.gpio			= AT91_PIN_PC6,
+		.active_low		= 1,
+		.default_trigger	= "default-on",
+	},
+	{
+		.name			= "usb4:green",
+		.gpio			= AT91_PIN_PB4,
+		.active_low		= 1,
+		.default_trigger	= "default-on",
+	},
+	{
+		.name			= "usb4:red",
+		.gpio			= AT91_PIN_PB5,
+		.active_low		= 1,
+		.default_trigger	= "default-on",
+	}
+};
+
+static void __init flexibity_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* USB Host */
+	at91_add_device_usbh(&flexibity_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&flexibity_udc_data);
+	/* SPI */
+	at91_add_device_spi(flexibity_spi_devices,
+		ARRAY_SIZE(flexibity_spi_devices));
+	/* MMC */
+	at91_add_device_mmc(0, &flexibity_mmc_data);
+	/* LEDs */
+	at91_gpio_leds(flexibity_leds, ARRAY_SIZE(flexibity_leds));
+}
+
+MACHINE_START(FLEXIBITY, "Flexibity Connect")
+	/* Maintainer: Maxim Osipov */
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91sam926x_timer,
+	.map_io		= flexibity_map_io,
+	.init_irq	= flexibity_init_irq,
+	.init_machine	= flexibity_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index a87956c..c0ce79d 100644
--- a/arch/arm/mach-at91/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -99,8 +99,6 @@
 
 MACHINE_START(KAFA, "Sperry-Sun KAFA")
 	/* Maintainer: Sergei Sharonov */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= kafa_map_io,
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index fe9b991..a13d206 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -136,8 +136,6 @@
 
 MACHINE_START(KB9200, "KB920x")
 	/* Maintainer: KwikByte, Inc. */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= kb9202_map_io,
diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
index 7c1e382..fe5f1d4 100644
--- a/arch/arm/mach-at91/board-neocore926.c
+++ b/arch/arm/mach-at91/board-neocore926.c
@@ -387,8 +387,6 @@
 
 MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
 	/* Maintainer: ADENEO */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= neocore926_map_io,
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
index 859727e..9d833bbc 100644
--- a/arch/arm/mach-at91/board-picotux200.c
+++ b/arch/arm/mach-at91/board-picotux200.c
@@ -156,8 +156,6 @@
 
 MACHINE_START(PICOTUX2XX, "picotux 200")
 	/* Maintainer: Kleinhenz Elektronik GmbH */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= picotux200_map_io,
diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
index 664938e..69d15a8 100644
--- a/arch/arm/mach-at91/board-qil-a9260.c
+++ b/arch/arm/mach-at91/board-qil-a9260.c
@@ -268,8 +268,6 @@
 
 MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
 	/* Maintainer: calao-systems */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index b483469..25a26be 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -212,8 +212,6 @@
 
 MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
 	/* Maintainer: Olimex */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index ba9d501..de1816e 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -356,8 +356,6 @@
 
 MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
 	/* Maintainer: Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 65eb094..14acc90 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -623,8 +623,6 @@
 MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
 #endif
 	/* Maintainer: Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 2d867fb..bfe490d 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -454,8 +454,6 @@
 
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
 	/* Maintainer: Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c b/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c
deleted file mode 100644
index c49f5c0..0000000
--- a/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2008 Atmel
- *  Copyright (C) 2009 Rob Emanuele
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/at73c213.h>
-#include <linux/clk.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/board.h>
-#include <mach/gpio.h>
-#include <mach/at91sam9_smc.h>
-
-#include "sam9_smc.h"
-#include "generic.h"
-
-
-static void __init ek_map_io(void)
-{
-	/* Initialize processor: 18.432 MHz crystal */
-	at91sam9260_initialize(18432000);
-
-	/* DGBU on ttyS0. (Rx & Tx only) */
-	at91_register_uart(0, 0, 0);
-
-	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-			   | ATMEL_UART_RI);
-
-	/* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-	at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
-	/* set serial console to ttyS0 (ie, DBGU) */
-	at91_set_serial_console(0);
-}
-
-static void __init ek_init_irq(void)
-{
-	at91sam9260_init_interrupts(NULL);
-}
-
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-	.ports		= 2,
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-	.vbus_pin	= AT91_PIN_PC5,
-	.pullup_pin	= 0,		/* pull-up driven by UDC */
-};
-
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91))
-	{	/* DataFlash chip */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 1,
-		.max_speed_hz	= 15 * 1000 * 1000,
-		.bus_num	= 0,
-	},
-#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
-	{	/* DataFlash card */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 0,
-		.max_speed_hz	= 15 * 1000 * 1000,
-		.bus_num	= 0,
-	},
-#endif
-#endif
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct at91_eth_data __initdata ek_macb_data = {
-	.phy_irq_pin	= AT91_PIN_PB0,
-	.is_rmii	= 1,
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-	{
-		.name   = "Bootstrap",
-		.offset = 0,
-		.size   = 4 * SZ_1M,
-	},
-	{
-		.name	= "Partition 1",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 60 * SZ_1M,
-	},
-	{
-		.name	= "Partition 2",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= MTDPART_SIZ_FULL,
-	},
-};
-
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
-/* det_pin is not connected */
-static struct atmel_nand_data __initdata ek_nand_data = {
-	.ale		= 21,
-	.cle		= 22,
-	.rdy_pin	= AT91_PIN_PC13,
-	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
-#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
-	.bus_width_16	= 1,
-#else
-	.bus_width_16	= 0,
-#endif
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-	.ncs_read_setup		= 0,
-	.nrd_setup		= 2,
-	.ncs_write_setup	= 0,
-	.nwe_setup		= 2,
-
-	.ncs_read_pulse		= 4,
-	.nrd_pulse		= 4,
-	.ncs_write_pulse	= 4,
-	.nwe_pulse		= 4,
-
-	.read_cycle		= 7,
-	.write_cycle		= 7,
-
-	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
-	.tdf_cycles		= 3,
-};
-
-static void __init ek_add_device_nand(void)
-{
-	/* setup bus-width (8 or 16) */
-	if (ek_nand_data.bus_width_16)
-		ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
-	else
-		ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
-
-	/* configure chip-select 3 (NAND) */
-	sam9_smc_configure(3, &ek_nand_smc_config);
-
-	at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- * MCI (SD/MMC)
- * wp_pin is not connected
- */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static struct mci_platform_data __initdata ek_mmc_data = {
-	.slot[0] = {
-		.bus_width	= 4,
-		.detect_pin	= AT91_PIN_PC2,
-		.wp_pin		= -ENODEV,
-	},
-	.slot[1] = {
-		.bus_width	= 4,
-		.detect_pin	= AT91_PIN_PC9,
-		.wp_pin		= -ENODEV,
-	},
-
-};
-#else
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.slot_b		= 1,	/* Only one slot so use slot B */
-	.wire4		= 1,
-	.det_pin	= AT91_PIN_PC9,
-};
-#endif
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-	{	/* "bottom" led, green, userled1 to be defined */
-		.name			= "ds5",
-		.gpio			= AT91_PIN_PB8,
-		.active_low		= 1,
-		.default_trigger	= "none",
-	},
-	{	/* "power" led, yellow */
-		.name			= "ds1",
-		.gpio			= AT91_PIN_PB9,
-		.default_trigger	= "heartbeat",
-	}
-};
-
-#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
-static struct regulator_consumer_supply ek_audio_consumer_supplies[] = {
-	REGULATOR_SUPPLY("AVDD", "0-001b"),
-	REGULATOR_SUPPLY("HPVDD", "0-001b"),
-	REGULATOR_SUPPLY("DBVDD", "0-001b"),
-	REGULATOR_SUPPLY("DCVDD", "0-001b"),
-};
-
-static struct regulator_init_data ek_avdd_reg_init_data = {
-	.constraints	= {
-		.name	= "3V3",
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-	},
-	.consumer_supplies = ek_audio_consumer_supplies,
-	.num_consumer_supplies = ARRAY_SIZE(ek_audio_consumer_supplies),
-};
-
-static struct fixed_voltage_config ek_vdd_pdata = {
-	.supply_name	= "board-3V3",
-	.microvolts	= 3300000,
-	.gpio		= -EINVAL,
-	.enabled_at_boot = 0,
-	.init_data	= &ek_avdd_reg_init_data,
-};
-static struct platform_device ek_voltage_regulator = {
-	.name		= "reg-fixed-voltage",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &ek_vdd_pdata,
-	},
-};
-static void __init ek_add_regulators(void)
-{
-	platform_device_register(&ek_voltage_regulator);
-}
-#else
-static void __init ek_add_regulators(void) {}
-#endif
-
-static struct i2c_board_info __initdata ek_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("24c512", 0x50),
-	},
-};
-
-
-static void __init ek_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&ek_udc_data);
-	/* SPI */
-	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-	/* NAND */
-	ek_add_device_nand();
-	/* Ethernet */
-	at91_add_device_eth(&ek_macb_data);
-	/* Regulators */
-	ek_add_regulators();
-	/* MMC */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-	at91_add_device_mci(0, &ek_mmc_data);
-#else
-	at91_add_device_mmc(0, &ek_mmc_data);
-#endif
-	/* I2C */
-	at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
-	/* LEDs */
-	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-	/* PCK0 provides MCLK to the WM8731 */
-	at91_set_B_periph(AT91_PIN_PC1, 0);
-	/* SSC (for WM8731) */
-	at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
-}
-
-MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
-	/* Maintainer: Rob Emanuele */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
-	.boot_params	= AT91_SDRAM_BASE + 0x100,
-	.timer		= &at91sam926x_timer,
-	.map_io		= ek_map_io,
-	.init_irq	= ek_init_irq,
-	.init_machine	= ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 6ea9808..ca8198b 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -47,6 +47,18 @@
 #include "sam9_smc.h"
 #include "generic.h"
 
+/*
+ * board revision encoding
+ * bit 0:
+ * 	0 => 1 sd/mmc slot
+ * 	1 => 2 sd/mmc slots connectors (board from revision C)
+ */
+#define HAVE_2MMC	(1 << 0)
+static int inline ek_have_2mmc(void)
+{
+	return machine_is_at91sam9g20ek_2mmc() || (system_rev & HAVE_2MMC);
+}
+
 
 static void __init ek_map_io(void)
 {
@@ -94,7 +106,7 @@
  * SPI devices.
  */
 static struct spi_board_info ek_spi_devices[] = {
-#if !defined(CONFIG_MMC_AT91)
+#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91))
 	{	/* DataFlash chip */
 		.modalias	= "mtd_dataflash",
 		.chip_select	= 1,
@@ -121,6 +133,13 @@
 	.is_rmii	= 1,
 };
 
+static void __init ek_add_device_macb(void)
+{
+	if (ek_have_2mmc())
+		ek_macb_data.phy_irq_pin = AT91_PIN_PB0;
+
+	at91_add_device_eth(&ek_macb_data);
+}
 
 /*
  * NAND flash
@@ -198,13 +217,36 @@
 
 /*
  * MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
+ * wp_pin and vcc_pin are not connected
  */
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.slot_b		= 1,
-	.wire4		= 1,
-};
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+static struct mci_platform_data __initdata ek_mmc_data = {
+	.slot[1] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PC9,
+	},
 
+};
+#else
+static struct at91_mmc_data __initdata ek_mmc_data = {
+	.slot_b		= 1,	/* Only one slot so use slot B */
+	.wire4		= 1,
+	.det_pin	= AT91_PIN_PC9,
+};
+#endif
+
+static void __init ek_add_device_mmc(void)
+{
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+	if (ek_have_2mmc()) {
+		ek_mmc_data.slot[0].bus_width = 4;
+		ek_mmc_data.slot[0].detect_pin = AT91_PIN_PC2;
+	}
+	at91_add_device_mci(0, &ek_mmc_data);
+#else
+	at91_add_device_mmc(0, &ek_mmc_data);
+#endif
+}
 
 /*
  * LEDs
@@ -223,6 +265,15 @@
 	}
 };
 
+static void __init ek_add_device_gpio_leds(void)
+{
+	if (ek_have_2mmc()) {
+		ek_leds[0].gpio = AT91_PIN_PB8;
+		ek_leds[1].gpio = AT91_PIN_PB9;
+	}
+
+	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+}
 
 /*
  * GPIO Buttons
@@ -336,15 +387,15 @@
 	/* NAND */
 	ek_add_device_nand();
 	/* Ethernet */
-	at91_add_device_eth(&ek_macb_data);
+	ek_add_device_macb();
 	/* Regulators */
 	ek_add_regulators();
 	/* MMC */
-	at91_add_device_mmc(0, &ek_mmc_data);
+	ek_add_device_mmc();
 	/* I2C */
 	at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
 	/* LEDs */
-	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+	ek_add_device_gpio_leds();
 	/* Push Buttons */
 	ek_add_device_buttons();
 	/* PCK0 provides MCLK to the WM8731 */
@@ -355,8 +406,15 @@
 
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
 	/* Maintainer: Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91sam926x_timer,
+	.map_io		= ek_map_io,
+	.init_irq	= ek_init_irq,
+	.init_machine	= ek_board_init,
+MACHINE_END
+
+MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
+	/* Maintainer: Atmel */
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index ee80059..7913984 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -135,7 +135,7 @@
 	.rdy_pin	= AT91_PIN_PC8,
 	.enable_pin	= AT91_PIN_PC14,
 	.partition_info	= nand_partitions,
-#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
 	.bus_width_16	= 1,
 #else
 	.bus_width_16	= 0,
@@ -399,10 +399,8 @@
 	at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
 }
 
-MACHINE_START(AT91SAM9G45EKES, "Atmel AT91SAM9G45-EKES")
+MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
 	/* Maintainer: Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 7ac20f3..3bf3408 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -329,8 +329,6 @@
 
 MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
 	/* Maintainer: Atmel */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= ek_map_io,
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 2c08ae4..0a99b3c 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -177,8 +177,6 @@
 }
 
 MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= snapper9260_map_io,
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index 8795827..5206eef 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -294,8 +294,6 @@
 
 MACHINE_START(PORTUXG20, "taskit PortuxG20")
 	/* Maintainer: taskit GmbH */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= portuxg20_map_io,
@@ -305,8 +303,6 @@
 
 MACHINE_START(STAMP9G20, "taskit Stamp9G20")
 	/* Maintainer: taskit GmbH */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= stamp9g20_map_io,
diff --git a/arch/arm/mach-at91/board-usb-a9260.c b/arch/arm/mach-at91/board-usb-a9260.c
index 905d6ef..07784ba 100644
--- a/arch/arm/mach-at91/board-usb-a9260.c
+++ b/arch/arm/mach-at91/board-usb-a9260.c
@@ -228,8 +228,6 @@
 
 MACHINE_START(USB_A9260, "CALAO USB_A9260")
 	/* Maintainer: calao-systems */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= ek_map_io,
diff --git a/arch/arm/mach-at91/board-usb-a9263.c b/arch/arm/mach-at91/board-usb-a9263.c
index b6a3480..b6145089 100644
--- a/arch/arm/mach-at91/board-usb-a9263.c
+++ b/arch/arm/mach-at91/board-usb-a9263.c
@@ -244,8 +244,6 @@
 
 MACHINE_START(USB_A9263, "CALAO USB_A9263")
 	/* Maintainer: calao-systems */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91sam926x_timer,
 	.map_io		= ek_map_io,
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index e22bf05..89df00a 100644
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -594,8 +594,6 @@
 
 MACHINE_START(YL9200, "uCdragon YL-9200")
 	/* Maintainer: S.Birtles */
-	.phys_io	= AT91_BASE_SYS,
-	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
 	.boot_params	= AT91_SDRAM_BASE + 0x100,
 	.timer		= &at91rm9200_timer,
 	.map_io		= yl9200_map_io,
diff --git a/arch/arm/mach-at91/include/mach/at91x40.h b/arch/arm/mach-at91/include/mach/at91x40.h
index d34cdb8..063ac44 100644
--- a/arch/arm/mach-at91/include/mach/at91x40.h
+++ b/arch/arm/mach-at91/include/mach/at91x40.h
@@ -52,4 +52,10 @@
 #define AT91_DBGU_CIDR	(AT91_SF + 0)	/* CIDR in PS segment */
 #define AT91_DBGU_EXID	(AT91_SF + 4)	/* EXID in PS segment */
 
+/*
+ * Support defines for the simple Power Controller module.
+ */
+#define	AT91_PS_CR	(AT91_PS + 0)	/* PS Control register */
+#define	AT91_PS_CR_CPU	(1 << 0)	/* CPU clock disable bit */
+
 #endif /* AT91X40_H */
diff --git a/arch/arm/mach-at91/include/mach/debug-macro.S b/arch/arm/mach-at91/include/mach/debug-macro.S
index 9e750a1..0f959fa 100644
--- a/arch/arm/mach-at91/include/mach/debug-macro.S
+++ b/arch/arm/mach-at91/include/mach/debug-macro.S
@@ -14,11 +14,9 @@
 #include <mach/hardware.h>
 #include <mach/at91_dbgu.h>
 
-	.macro	addruart, rx, tmp
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1						@ MMU enabled?
-	ldreq	\rx, =(AT91_BASE_SYS + AT91_DBGU)		@ System peripherals (phys address)
-	ldrne	\rx, =(AT91_VA_BASE_SYS	+ AT91_DBGU)		@ System peripherals (virt address)
+	.macro	addruart, rp, rv
+	ldr	\rp, =(AT91_BASE_SYS + AT91_DBGU)		@ System peripherals (phys address)
+	ldr	\rv, =(AT91_VA_BASE_SYS	+ AT91_DBGU)		@ System peripherals (virt address)
 	.endm
 
 	.macro	senduart,rd,rx
diff --git a/arch/arm/mach-at91/include/mach/system.h b/arch/arm/mach-at91/include/mach/system.h
index c80e090..36af14b 100644
--- a/arch/arm/mach-at91/include/mach/system.h
+++ b/arch/arm/mach-at91/include/mach/system.h
@@ -28,17 +28,20 @@
 
 static inline void arch_idle(void)
 {
-#ifndef CONFIG_DEBUG_KERNEL
 	/*
 	 * Disable the processor clock.  The processor will be automatically
 	 * re-enabled by an interrupt or by a reset.
 	 */
-	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK);
+#ifdef AT91_PS
+	at91_sys_write(AT91_PS_CR, AT91_PS_CR_CPU);
 #else
+	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK);
+#endif
+#ifndef CONFIG_CPU_ARM920T
 	/*
 	 * Set the processor (CP15) into 'Wait for Interrupt' mode.
-	 * Unlike disabling the processor clock via the PMC (above)
-	 *  this allows the processor to be woken via JTAG.
+	 * Post-RM9200 processors need this in conjunction with the above
+	 * to save power when idle.
 	 */
 	cpu_do_idle();
 #endif
diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c
index 2f13919..73eb066 100644
--- a/arch/arm/mach-bcmring/arch.c
+++ b/arch/arm/mach-bcmring/arch.c
@@ -167,8 +167,6 @@
 
 MACHINE_START(BCMRING, "BCMRING")
 	/* Maintainer: Broadcom Corporation */
-	.phys_io = MM_IO_START,
-	.io_pg_offst = (MM_IO_BASE >> 18) & 0xfffc,
 	.fixup = bcmring_fixup,
 	.map_io = bcmring_map_io,
 	.init_irq = bcmring_init_irq,
diff --git a/arch/arm/mach-bcmring/dma.c b/arch/arm/mach-bcmring/dma.c
index 29c0a91..77eb35c 100644
--- a/arch/arm/mach-bcmring/dma.c
+++ b/arch/arm/mach-bcmring/dma.c
@@ -691,7 +691,7 @@
 
 	memset(&gDMA, 0, sizeof(gDMA));
 
-	init_MUTEX_LOCKED(&gDMA.lock);
+	sema_init(&gDMA.lock, 0);
 	init_waitqueue_head(&gDMA.freeChannelQ);
 
 	/* Initialize the Hardware */
@@ -1574,7 +1574,7 @@
 {
 	memset(memMap, 0, sizeof(*memMap));
 
-	init_MUTEX(&memMap->lock);
+	sema_init(&memMap->lock, 1);
 
 	return 0;
 }
diff --git a/arch/arm/mach-bcmring/include/mach/vmalloc.h b/arch/arm/mach-bcmring/include/mach/vmalloc.h
index 35e2ead..3db3a09 100644
--- a/arch/arm/mach-bcmring/include/mach/vmalloc.h
+++ b/arch/arm/mach-bcmring/include/mach/vmalloc.h
@@ -22,4 +22,4 @@
  * 0xe0000000 to 0xefffffff. This gives us 256 MB of vm space and handles
  * larger physical memory designs better.
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x30000000)
+#define VMALLOC_END       0xf0000000
diff --git a/arch/arm/mach-bcmring/irq.c b/arch/arm/mach-bcmring/irq.c
index dc1c493..e315263 100644
--- a/arch/arm/mach-bcmring/irq.c
+++ b/arch/arm/mach-bcmring/irq.c
@@ -67,21 +67,21 @@
 }
 
 static struct irq_chip bcmring_irq0_chip = {
-	.typename = "ARM-INTC0",
+	.name = "ARM-INTC0",
 	.ack = bcmring_mask_irq0,
 	.mask = bcmring_mask_irq0,	/* mask a specific interrupt, blocking its delivery. */
 	.unmask = bcmring_unmask_irq0,	/* unmaks an interrupt */
 };
 
 static struct irq_chip bcmring_irq1_chip = {
-	.typename = "ARM-INTC1",
+	.name = "ARM-INTC1",
 	.ack = bcmring_mask_irq1,
 	.mask = bcmring_mask_irq1,
 	.unmask = bcmring_unmask_irq1,
 };
 
 static struct irq_chip bcmring_irq2_chip = {
-	.typename = "ARM-SINTC",
+	.name = "ARM-SINTC",
 	.ack = bcmring_mask_irq2,
 	.mask = bcmring_mask_irq2,
 	.unmask = bcmring_unmask_irq2,
diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
index 5f18ecc..4a74b2c9 100644
--- a/arch/arm/mach-clps711x/autcpu12.c
+++ b/arch/arm/mach-clps711x/autcpu12.c
@@ -64,8 +64,6 @@
 
 MACHINE_START(AUTCPU12, "autronix autcpu12")
 	/* Maintainer: Thomas Gleixner */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xff000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0020000,
 	.map_io		= autcpu12_map_io,
 	.init_irq	= clps711x_init_irq,
diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c
index 71a80b5..5a1689d 100644
--- a/arch/arm/mach-clps711x/cdb89712.c
+++ b/arch/arm/mach-clps711x/cdb89712.c
@@ -55,8 +55,6 @@
 
 MACHINE_START(CDB89712, "Cirrus-CDB89712")
 	/* Maintainer: Ray Lehtiniemi */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xff000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= cdb89712_map_io,
 	.init_irq	= clps711x_init_irq,
diff --git a/arch/arm/mach-clps711x/ceiva.c b/arch/arm/mach-clps711x/ceiva.c
index 8ada201..16481cf 100644
--- a/arch/arm/mach-clps711x/ceiva.c
+++ b/arch/arm/mach-clps711x/ceiva.c
@@ -56,8 +56,6 @@
 
 MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame")
 	/* Maintainer: Rob Scott */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xff000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= ceiva_map_io,
 	.init_irq	= clps711x_init_irq,
diff --git a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c
index 3c3bf45..67b5abb4 100644
--- a/arch/arm/mach-clps711x/clep7312.c
+++ b/arch/arm/mach-clps711x/clep7312.c
@@ -37,8 +37,6 @@
 
 MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
 	/* Maintainer: Nobody */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xff000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.fixup		= fixup_clep7312,
 	.map_io		= clps711x_map_io,
diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c
index 4a7a232..98ca5b2 100644
--- a/arch/arm/mach-clps711x/edb7211-arch.c
+++ b/arch/arm/mach-clps711x/edb7211-arch.c
@@ -57,8 +57,6 @@
 
 MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
 	/* Maintainer: Jon McClintock */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xff000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0020100,	/* 0xc0000000 - 0xc001ffff can be video RAM */
 	.fixup		= fixup_edb7211,
 	.map_io		= edb7211_map_io,
diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c
index a696099..b1cb479 100644
--- a/arch/arm/mach-clps711x/fortunet.c
+++ b/arch/arm/mach-clps711x/fortunet.c
@@ -75,8 +75,6 @@
 
 MACHINE_START(FORTUNET, "ARM-FortuNet")
 	/* Maintainer: FortuNet Inc. */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf0000000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000000,
 	.fixup		= fortunet_fixup,
 	.map_io		= clps711x_map_io,
diff --git a/arch/arm/mach-clps711x/include/mach/debug-macro.S b/arch/arm/mach-clps711x/include/mach/debug-macro.S
index 072cc6b..507c687 100644
--- a/arch/arm/mach-clps711x/include/mach/debug-macro.S
+++ b/arch/arm/mach-clps711x/include/mach/debug-macro.S
@@ -14,16 +14,14 @@
 #include <mach/hardware.h>
 #include <asm/hardware/clps7111.h>
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #CLPS7111_PHYS_BASE
-		movne	\rx, #CLPS7111_VIRT_BASE
+		.macro	addruart, rp, rv
 #ifndef CONFIG_DEBUG_CLPS711X_UART2
-		add	\rx, \rx, #0x0000	@ UART1
+		mov	\rp, #0x0000	@ UART1
 #else
-		add	\rx, \rx, #0x1000	@ UART2
+		mov	\rp, #0x1000	@ UART2
 #endif
+		orr	\rv, \rp, #CLPS7111_VIRT_BASE
+		orr	\rp, \rp, #CLPS7111_PHYS_BASE
 		.endm
 
 		.macro	senduart,rd,rx
diff --git a/arch/arm/mach-clps711x/include/mach/vmalloc.h b/arch/arm/mach-clps711x/include/mach/vmalloc.h
index ea6cc7b..30b3a287 100644
--- a/arch/arm/mach-clps711x/include/mach/vmalloc.h
+++ b/arch/arm/mach-clps711x/include/mach/vmalloc.h
@@ -17,4 +17,4 @@
  * 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       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c
index 0d94a30..cefbce0 100644
--- a/arch/arm/mach-clps711x/p720t.c
+++ b/arch/arm/mach-clps711x/p720t.c
@@ -89,8 +89,6 @@
 
 MACHINE_START(P720T, "ARM-Prospector720T")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xff000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.fixup		= fixup_p720t,
 	.map_io		= p720t_map_io,
diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
index 9df8391..90fe9ab 100644
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
@@ -142,8 +142,6 @@
 }
 
 MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board")
-	.phys_io	= CNS3XXX_UART0_BASE,
-	.io_pg_offst	= (CNS3XXX_UART0_BASE_VIRT >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= cns3420_map_io,
 	.init_irq	= cns3xxx_init_irq,
diff --git a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
index d16ce7e..56d8286 100644
--- a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
+++ b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
@@ -10,12 +10,10 @@
  * published by the Free Software Foundation.
  */
 
-		.macro	addruart,rx
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx,      #0x10000000
-		movne	\rx,      #0xf0000000	@ virtual base
-		orr	\rx, \rx, #0x00009000
+		.macro	addruart,rp,rv
+		mov	\rp, #0x00009000
+		orr	\rv, \rp, #0xf0000000	@ virtual base
+		orr	\rp, \rp, #0x10000000
 		.endm
 
 #include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index c3994f3..7f3cdbf 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -597,8 +597,6 @@
 }
 
 MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137 EVM")
-	.phys_io	= IO_PHYS,
-	.io_pg_offst	= (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
 	.boot_params	= (DA8XX_DDR_BASE + 0x100),
 	.map_io		= da830_evm_map_io,
 	.init_irq	= cp_intc_init,
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index fdc2cc5..b26f5cb 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -817,8 +817,6 @@
 }
 
 MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138 EVM")
-	.phys_io	= IO_PHYS,
-	.io_pg_offst	= (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
 	.boot_params	= (DA8XX_DDR_BASE + 0x100),
 	.map_io		= da850_evm_map_io,
 	.init_irq	= cp_intc_init,
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index a319101..6e7cad13 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -351,8 +351,6 @@
 }
 
 MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
-	.phys_io      = IO_PHYS,
-	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
 	.boot_params  = (0x80000100),
 	.map_io	      = dm355_evm_map_io,
 	.init_irq     = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index f1d8132..543f991 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -270,8 +270,6 @@
 }
 
 MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
-	.phys_io      = IO_PHYS,
-	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
 	.boot_params  = (0x80000100),
 	.map_io	      = dm355_leopard_map_io,
 	.init_irq     = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 84acef1..944a0cb 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -613,8 +613,6 @@
 }
 
 MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
-	.phys_io	= IO_PHYS,
-	.io_pg_offst	= (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
 	.boot_params	= (0x80000100),
 	.map_io		= dm365_evm_map_io,
 	.init_irq	= davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 34c8b41..d59fba1 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -706,8 +706,6 @@
 
 MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
 	/* Maintainer: MontaVista Software <source@mvista.com> */
-	.phys_io      = IO_PHYS,
-	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
 	.boot_params  = (DAVINCI_DDR_BASE + 0x100),
 	.map_io	      = davinci_evm_map_io,
 	.init_irq     = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 4502f34..6890488 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -786,8 +786,6 @@
 }
 
 MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
-	.phys_io      = IO_PHYS,
-	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
 	.boot_params  = (0x80000100),
 	.map_io       = davinci_map_io,
 	.init_irq     = davinci_irq_init,
@@ -796,8 +794,6 @@
 MACHINE_END
 
 MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
-	.phys_io      = IO_PHYS,
-	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
 	.boot_params  = (0x80000100),
 	.map_io       = davinci_map_io,
 	.init_irq     = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 4c30e92..a4def88 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -275,8 +275,6 @@
 
 MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
 	/* Maintainer: Neuros Technologies <neuros@groups.google.com> */
-	.phys_io	= IO_PHYS,
-	.io_pg_offst	= (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
 	.boot_params	= (DAVINCI_DDR_BASE + 0x100),
 	.map_io		 = davinci_ntosd2_map_io,
 	.init_irq	= davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 23e664a..9bdf8aa 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -154,8 +154,6 @@
 
 MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
 	/* Maintainer: Hugo Villeneuve hugo.villeneuve@lyrtech.com */
-	.phys_io      = IO_PHYS,
-	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
 	.boot_params  = (DAVINCI_DDR_BASE + 0x100),
 	.map_io	      = davinci_sffsdr_map_io,
 	.init_irq     = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
index fe2a9d9..b4de35b 100644
--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -164,8 +164,6 @@
 #endif
 
 MACHINE_START(TNETV107X, "TNETV107X EVM")
-	.phys_io	= TNETV107X_IO_BASE,
-	.io_pg_offst	= (TNETV107X_IO_VIRT >> 18) & 0xfffc,
 	.boot_params	= (TNETV107X_DDR_BASE + 0x100),
 	.map_io		= tnetv107x_init,
 	.init_irq	= cp_intc_init,
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index 3d996b6..9be261b 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -769,8 +769,7 @@
 		.virtual	= SRAM_VIRT,
 		.pfn		= __phys_to_pfn(0x00010000),
 		.length		= SZ_32K,
-		/* MT_MEMORY_NONCACHED requires supersection alignment */
-		.type		= MT_DEVICE,
+		.type		= MT_MEMORY_NONCACHED,
 	},
 };
 
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 6b6f4c6..7781e35 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -969,8 +969,7 @@
 		.virtual	= SRAM_VIRT,
 		.pfn		= __phys_to_pfn(0x00010000),
 		.length		= SZ_32K,
-		/* MT_MEMORY_NONCACHED requires supersection alignment */
-		.type		= MT_DEVICE,
+		.type		= MT_MEMORY_NONCACHED,
 	},
 };
 
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 40fec31..5e5b0a7 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -653,8 +653,7 @@
 		.virtual	= SRAM_VIRT,
 		.pfn		= __phys_to_pfn(0x00008000),
 		.length		= SZ_16K,
-		/* MT_MEMORY_NONCACHED requires supersection alignment */
-		.type		= MT_DEVICE,
+		.type		= MT_MEMORY_NONCACHED,
 	},
 };
 
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index e4a3df1..26e8a9c 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -737,8 +737,7 @@
 		.virtual	= SRAM_VIRT,
 		.pfn		= __phys_to_pfn(0x00010000),
 		.length		= SZ_32K,
-		/* MT_MEMORY_NONCACHED requires supersection alignment */
-		.type		= MT_DEVICE,
+		.type		= MT_MEMORY_NONCACHED,
 	},
 };
 
diff --git a/arch/arm/mach-davinci/include/mach/debug-macro.S b/arch/arm/mach-davinci/include/mach/debug-macro.S
index f761dfd..9f1befc 100644
--- a/arch/arm/mach-davinci/include/mach/debug-macro.S
+++ b/arch/arm/mach-davinci/include/mach/debug-macro.S
@@ -29,35 +29,39 @@
 davinci_uart_virt:	.word	0
 		.popsection
 
-		.macro addruart, rx, tmp
+		.macro addruart, rp, rv
 
 		/* Use davinci_uart_phys/virt if already configured */
-10:		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		ldreq	\rx, =__virt_to_phys(davinci_uart_phys)
-		ldrne	\rx, =davinci_uart_virt
-		ldr	\rx, [\rx]
-		cmp	\rx, #0			@ is port configured?
+10:		mrc	p15, 0, \rp, c1, c0
+		tst	\rp, #1			@ MMU enabled?
+		ldreq	\rp, =__virt_to_phys(davinci_uart_phys)
+		ldrne	\rp, =davinci_uart_phys
+		add	\rv, \rp, #4		@ davinci_uart_virt
+		ldr	\rp, [\rp, #0]
+		ldr	\rv, [\rv, #0]
+		cmp	\rp, #0			@ is port configured?
+		cmpne	\rv, #0
 		bne	99f			@ already configured
 
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
+		/* Check the debug UART address set in uncompress.h */
+		mrc	p15, 0, \rp, c1, c0
+		tst	\rp, #1			@ MMU enabled?
 
 		/* Copy uart phys address from decompressor uart info */
-		ldreq	\tmp, =__virt_to_phys(davinci_uart_phys)
-		ldrne	\tmp, =davinci_uart_phys
-		ldreq	\rx, =DAVINCI_UART_INFO
-		ldrne	\rx, =__phys_to_virt(DAVINCI_UART_INFO)
-		ldr	\rx, [\rx, #0]
-		str	\rx, [\tmp]
+		ldreq	\rv, =__virt_to_phys(davinci_uart_phys)
+		ldrne	\rv, =davinci_uart_phys
+		ldreq	\rp, =DAVINCI_UART_INFO
+		ldrne	\rp, =__phys_to_virt(DAVINCI_UART_INFO)
+		ldr	\rp, [\rp, #0]
+		str	\rp, [\rv]
 
 		/* Copy uart virt address from decompressor uart info */
-		ldreq	\tmp, =__virt_to_phys(davinci_uart_virt)
-		ldrne	\tmp, =davinci_uart_virt
-		ldreq	\rx, =DAVINCI_UART_INFO
-		ldrne	\rx, =__phys_to_virt(DAVINCI_UART_INFO)
-		ldr	\rx, [\rx, #4]
-		str	\rx, [\tmp]
+		ldreq	\rv, =__virt_to_phys(davinci_uart_virt)
+		ldrne	\rv, =davinci_uart_virt
+		ldreq	\rp, =DAVINCI_UART_INFO
+		ldrne	\rp, =__phys_to_virt(DAVINCI_UART_INFO)
+		ldr	\rp, [\rp, #4]
+		str	\rp, [\rv]
 
 		b	10b
 99:
diff --git a/arch/arm/mach-dove/dove-db-setup.c b/arch/arm/mach-dove/dove-db-setup.c
index bef7046..95925aa 100644
--- a/arch/arm/mach-dove/dove-db-setup.c
+++ b/arch/arm/mach-dove/dove-db-setup.c
@@ -94,8 +94,6 @@
 }
 
 MACHINE_START(DOVE_DB, "Marvell DB-MV88AP510-BP Development Board")
-	.phys_io	= DOVE_SB_REGS_PHYS_BASE,
-	.io_pg_offst	= ((DOVE_SB_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= dove_db_init,
 	.map_io		= dove_map_io,
diff --git a/arch/arm/mach-dove/include/mach/debug-macro.S b/arch/arm/mach-dove/include/mach/debug-macro.S
index 1521d13..da8bf2b 100644
--- a/arch/arm/mach-dove/include/mach/debug-macro.S
+++ b/arch/arm/mach-dove/include/mach/debug-macro.S
@@ -8,12 +8,11 @@
 
 #include <mach/bridge-regs.h>
 
-	.macro	addruart, rx, tmp
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1					@ MMU enabled?
-	ldreq	\rx, =DOVE_SB_REGS_PHYS_BASE
-	ldrne	\rx, =DOVE_SB_REGS_VIRT_BASE
-	orr	\rx, \rx, #0x00012000
+	.macro	addruart, rp, rv
+	ldr	\rp, =DOVE_SB_REGS_PHYS_BASE
+	ldr	\rv, =DOVE_SB_REGS_VIRT_BASE
+	orr	\rp, \rp, #0x00012000
+	orr	\rv, \rv, #0x00012000
 	.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-dove/include/mach/io.h b/arch/arm/mach-dove/include/mach/io.h
index 3b3e472..eb4936f 100644
--- a/arch/arm/mach-dove/include/mach/io.h
+++ b/arch/arm/mach-dove/include/mach/io.h
@@ -13,8 +13,8 @@
 
 #define IO_SPACE_LIMIT		0xffffffff
 
-#define __io(a)  ((void __iomem *)(((a) - DOVE_PCIE0_IO_PHYS_BASE) +\
-				   DOVE_PCIE0_IO_VIRT_BASE))
-#define __mem_pci(a)		(a)
+#define __io(a)  	((void __iomem *)(((a) - DOVE_PCIE0_IO_BUS_BASE) + \
+						 DOVE_PCIE0_IO_VIRT_BASE))
+#define __mem_pci(a)	(a)
 
 #endif
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index c7bc7fb..5df4099 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -280,8 +280,6 @@
 
 MACHINE_START(EBSA110, "EBSA110")
 	/* Maintainer: Russell King */
-	.phys_io	= 0xe0000000,
-	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000400,
 	.reserve_lp0	= 1,
 	.reserve_lp2	= 1,
diff --git a/arch/arm/mach-ebsa110/include/mach/debug-macro.S b/arch/arm/mach-ebsa110/include/mach/debug-macro.S
index ebbd89f..7ef5690 100644
--- a/arch/arm/mach-ebsa110/include/mach/debug-macro.S
+++ b/arch/arm/mach-ebsa110/include/mach/debug-macro.S
@@ -11,9 +11,10 @@
  *
 **/
 
-		.macro	addruart, rx, tmp
-		mov	\rx, #0xf0000000
-		orr	\rx, \rx, #0x00000be0
+		.macro	addruart, rp, rv
+		mov	\rp, #0xf0000000
+		orr	\rp, \rp, #0x00000be0
+		mov	\rp, \rv
 		.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-ebsa110/include/mach/vmalloc.h b/arch/arm/mach-ebsa110/include/mach/vmalloc.h
index 9b44c19..60bde56 100644
--- a/arch/arm/mach-ebsa110/include/mach/vmalloc.h
+++ b/arch/arm/mach-ebsa110/include/mach/vmalloc.h
@@ -7,4 +7,4 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x1f000000)
+#define VMALLOC_END       0xdf000000
diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c
index f744f67..61b98ce 100644
--- a/arch/arm/mach-ep93xx/adssphere.c
+++ b/arch/arm/mach-ep93xx/adssphere.c
@@ -33,8 +33,6 @@
 
 MACHINE_START(ADSSPHERE, "ADS Sphere board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/dma-m2p.c b/arch/arm/mach-ep93xx/dma-m2p.c
index 8904ca4..a696d35 100644
--- a/arch/arm/mach-ep93xx/dma-m2p.c
+++ b/arch/arm/mach-ep93xx/dma-m2p.c
@@ -276,7 +276,7 @@
 	v &= ~(M2P_CONTROL_STALL_IRQ_EN | M2P_CONTROL_NFB_IRQ_EN);
 	m2p_set_control(ch, v);
 
-	while (m2p_channel_state(ch) == STATE_ON)
+	while (m2p_channel_state(ch) >= STATE_ON)
 		cpu_relax();
 
 	m2p_set_control(ch, 0x0);
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index c2ce903..4b04316 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -124,8 +124,6 @@
 #ifdef CONFIG_MACH_EDB9301
 MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
 	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
@@ -137,8 +135,6 @@
 #ifdef CONFIG_MACH_EDB9302
 MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
 	/* Maintainer: George Kashperko <george@chas.com.ua> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
@@ -150,8 +146,6 @@
 #ifdef CONFIG_MACH_EDB9302A
 MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
@@ -163,8 +157,6 @@
 #ifdef CONFIG_MACH_EDB9307
 MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
 	/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
@@ -176,8 +168,6 @@
 #ifdef CONFIG_MACH_EDB9307A
 MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
 	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
@@ -189,8 +179,6 @@
 #ifdef CONFIG_MACH_EDB9312
 MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
 	/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
@@ -202,8 +190,6 @@
 #ifdef CONFIG_MACH_EDB9315
 MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
@@ -215,8 +201,6 @@
 #ifdef CONFIG_MACH_EDB9315A
 MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c
index d97168c..9bd3152 100644
--- a/arch/arm/mach-ep93xx/gesbc9312.c
+++ b/arch/arm/mach-ep93xx/gesbc9312.c
@@ -33,8 +33,6 @@
 
 MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/include/mach/debug-macro.S b/arch/arm/mach-ep93xx/include/mach/debug-macro.S
index 5cd2244..b25bc907 100644
--- a/arch/arm/mach-ep93xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ep93xx/include/mach/debug-macro.S
@@ -11,12 +11,11 @@
  */
 #include <mach/ep93xx-regs.h>
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1				@ MMU enabled?
-		ldreq	\rx, =EP93XX_APB_PHYS_BASE	@ Physical base
-		ldrne	\rx, =EP93XX_APB_VIRT_BASE	@ virtual base
-		orr	\rx, \rx, #0x000c0000
+		.macro	addruart, rp, rv
+		ldr	\rp, =EP93XX_APB_PHYS_BASE	@ Physical base
+		ldr	\rv, =EP93XX_APB_VIRT_BASE	@ virtual base
+		orr	\rp, \rp, #0x000c0000
+		orr	\rv, \rv, #0x000c0000
 		.endm
 
 #include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c
index 2ba7763..7adea62 100644
--- a/arch/arm/mach-ep93xx/micro9.c
+++ b/arch/arm/mach-ep93xx/micro9.c
@@ -77,8 +77,6 @@
 #ifdef CONFIG_MACH_MICRO9H
 MACHINE_START(MICRO9, "Contec Micro9-High")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
@@ -90,8 +88,6 @@
 #ifdef CONFIG_MACH_MICRO9M
 MACHINE_START(MICRO9M, "Contec Micro9-Mid")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
@@ -103,8 +99,6 @@
 #ifdef CONFIG_MACH_MICRO9L
 MACHINE_START(MICRO9L, "Contec Micro9-Lite")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
@@ -116,8 +110,6 @@
 #ifdef CONFIG_MACH_MICRO9S
 MACHINE_START(MICRO9S, "Contec Micro9-Slim")
 	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c
index 5dded58..f22ce8d 100644
--- a/arch/arm/mach-ep93xx/simone.c
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -65,8 +65,6 @@
 
 MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
 /* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
index a12c893..ac601fe 100644
--- a/arch/arm/mach-ep93xx/snappercl15.c
+++ b/arch/arm/mach-ep93xx/snappercl15.c
@@ -163,8 +163,6 @@
 
 MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
 	/* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 93aeab8..c2d2cf4 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -257,8 +257,6 @@
 
 MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
 	.map_io		= ts72xx_map_io,
 	.init_irq	= ep93xx_init_irq,
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index 1b996b2..5b1a8db 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -86,8 +86,6 @@
 
 MACHINE_START(CATS, "Chalice-CATS")
 	/* Maintainer: Philip Blundell */
-	.phys_io	= DC21285_ARMCSR_BASE,
-	.io_pg_offst	= ((0xfe000000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.soft_reboot	= 1,
 	.fixup		= fixup_cats,
diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c
index 30040fd..2ef69ff 100644
--- a/arch/arm/mach-footbridge/ebsa285.c
+++ b/arch/arm/mach-footbridge/ebsa285.c
@@ -15,8 +15,6 @@
 
 MACHINE_START(EBSA285, "EBSA285")
 	/* Maintainer: Russell King */
-	.phys_io	= DC21285_ARMCSR_BASE,
-	.io_pg_offst	= ((0xfe000000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.video_start	= 0x000a0000,
 	.video_end	= 0x000bffff,
diff --git a/arch/arm/mach-footbridge/include/mach/debug-macro.S b/arch/arm/mach-footbridge/include/mach/debug-macro.S
index 60dda13..3c9e0c4 100644
--- a/arch/arm/mach-footbridge/include/mach/debug-macro.S
+++ b/arch/arm/mach-footbridge/include/mach/debug-macro.S
@@ -15,12 +15,10 @@
 
 #ifndef CONFIG_DEBUG_DC21285_PORT
 	/* For NetWinder debugging */
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x7c000000	@ physical
-		movne	\rx, #0xff000000	@ virtual
-		orr	\rx, \rx, #0x000003f8
+		.macro	addruart, rp, rv
+		mov	\rp, #0x000003f8
+		orr	\rv, \rp, #0x7c000000	@ physical
+		orr	\rp, \rp, #0xff000000	@ virtual
 		.endm
 
 #define UART_SHIFT	0
@@ -32,14 +30,14 @@
 		.equ	dc21285_high, ARMCSR_BASE & 0xff000000
 		.equ	dc21285_low,  ARMCSR_BASE & 0x00ffffff
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x42000000
-		movne	\rx, #dc21285_high
+		.macro	addruart, rp, rv
 		.if	dc21285_low
-		orrne	\rx, \rx, #dc21285_low
+		mov	\rp, #dc21285_low
+		.else
+		mov	\rp, #0
 		.endif
+		orr	\rv, \rp, #0x42000000
+		orr	\rp, \rp, #dc21285_high
 		.endm
 
 		.macro	senduart,rd,rx
diff --git a/arch/arm/mach-footbridge/include/mach/vmalloc.h b/arch/arm/mach-footbridge/include/mach/vmalloc.h
index d0958d8..0ffbb7c 100644
--- a/arch/arm/mach-footbridge/include/mach/vmalloc.h
+++ b/arch/arm/mach-footbridge/include/mach/vmalloc.h
@@ -7,4 +7,4 @@
  */
 
 
-#define VMALLOC_END       (PAGE_OFFSET + 0x30000000)
+#define VMALLOC_END       0xf0000000
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index ac7ffa6..06e514f 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -648,8 +648,6 @@
 
 MACHINE_START(NETWINDER, "Rebel-NetWinder")
 	/* Maintainer: Russell King/Rebel.com */
-	.phys_io	= DC21285_ARMCSR_BASE,
-	.io_pg_offst	= ((0xfe000000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.video_start	= 0x000a0000,
 	.video_end	= 0x000bffff,
diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c
index e2c9f06..3285e91 100644
--- a/arch/arm/mach-footbridge/personal.c
+++ b/arch/arm/mach-footbridge/personal.c
@@ -15,8 +15,6 @@
 
 MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
 	/* Maintainer: Jamey Hicks / George France */
-	.phys_io	= DC21285_ARMCSR_BASE,
-	.io_pg_offst	= ((0xfe000000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= footbridge_map_io,
 	.init_irq	= footbridge_init_irq,
diff --git a/arch/arm/mach-gemini/board-nas4220b.c b/arch/arm/mach-gemini/board-nas4220b.c
index 01f1d6d..2ba096d 100644
--- a/arch/arm/mach-gemini/board-nas4220b.c
+++ b/arch/arm/mach-gemini/board-nas4220b.c
@@ -101,8 +101,6 @@
 }
 
 MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
-	.phys_io	= 0x7fffc000,
-	.io_pg_offst	= ((0xffffc000) >> 18) & 0xfffc,
 	.boot_params	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c
index e0de968..a9a0d8b 100644
--- a/arch/arm/mach-gemini/board-rut1xx.c
+++ b/arch/arm/mach-gemini/board-rut1xx.c
@@ -85,8 +85,6 @@
 }
 
 MACHINE_START(RUT100, "Teltonika RUT100")
-	.phys_io	= 0x7fffc000,
-	.io_pg_offst	= ((0xffffc000) >> 18) & 0xfffc,
 	.boot_params	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
diff --git a/arch/arm/mach-gemini/board-wbd111.c b/arch/arm/mach-gemini/board-wbd111.c
index 36538c1..8b88d50 100644
--- a/arch/arm/mach-gemini/board-wbd111.c
+++ b/arch/arm/mach-gemini/board-wbd111.c
@@ -133,8 +133,6 @@
 }
 
 MACHINE_START(WBD111, "Wiliboard WBD-111")
-	.phys_io	= 0x7fffc000,
-	.io_pg_offst	= ((0xffffc000) >> 18) & 0xfffc,
 	.boot_params	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
diff --git a/arch/arm/mach-gemini/board-wbd222.c b/arch/arm/mach-gemini/board-wbd222.c
index ece8b4c..1eebcec 100644
--- a/arch/arm/mach-gemini/board-wbd222.c
+++ b/arch/arm/mach-gemini/board-wbd222.c
@@ -133,8 +133,6 @@
 }
 
 MACHINE_START(WBD222, "Wiliboard WBD-222")
-	.phys_io	= 0x7fffc000,
-	.io_pg_offst	= ((0xffffc000) >> 18) & 0xfffc,
 	.boot_params	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
diff --git a/arch/arm/mach-gemini/include/mach/debug-macro.S b/arch/arm/mach-gemini/include/mach/debug-macro.S
index ad47704..f40e006 100644
--- a/arch/arm/mach-gemini/include/mach/debug-macro.S
+++ b/arch/arm/mach-gemini/include/mach/debug-macro.S
@@ -11,11 +11,9 @@
  */
 #include <mach/hardware.h>
 
-	.macro	addruart, rx, tmp
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1					@ MMU enabled?
-	ldreq	\rx, =GEMINI_UART_BASE			@ physical
-	ldrne	\rx, =IO_ADDRESS(GEMINI_UART_BASE)	@ virtual
+	.macro	addruart, rp, rv
+	ldr	\rp, =GEMINI_UART_BASE			@ physical
+	ldr	\rv, =IO_ADDRESS(GEMINI_UART_BASE)	@ virtual
 	.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c
index 78be457..79f0b89 100644
--- a/arch/arm/mach-h720x/h7201-eval.c
+++ b/arch/arm/mach-h720x/h7201-eval.c
@@ -30,8 +30,6 @@
 
 MACHINE_START(H7201, "Hynix GMS30C7201")
 	/* Maintainer: Robert Schwebel, Pengutronix */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf0000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0001000,
 	.map_io		= h720x_map_io,
 	.init_irq	= h720x_init_irq,
diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
index 8c0ba99..cc28b1e 100644
--- a/arch/arm/mach-h720x/h7202-eval.c
+++ b/arch/arm/mach-h720x/h7202-eval.c
@@ -72,8 +72,6 @@
 
 MACHINE_START(H7202, "Hynix HMS30C7202")
 	/* Maintainer: Robert Schwebel, Pengutronix */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf0000000) >> 18) & 0xfffc,
 	.boot_params	= 0x40000100,
 	.map_io		= h720x_map_io,
 	.init_irq	= h7202_init_irq,
diff --git a/arch/arm/mach-h720x/include/mach/debug-macro.S b/arch/arm/mach-h720x/include/mach/debug-macro.S
index 27cafd1..c2093e8 100644
--- a/arch/arm/mach-h720x/include/mach/debug-macro.S
+++ b/arch/arm/mach-h720x/include/mach/debug-macro.S
@@ -16,12 +16,10 @@
 		.equ    io_virt, IO_VIRT
 		.equ    io_phys, IO_PHYS
 
-		.macro  addruart, rx, tmp
-		mrc     p15, 0, \rx, c1, c0
-		tst     \rx, #1  	       @ MMU enabled?
-		moveq   \rx, #io_phys	       @ physical base address
-		movne   \rx, #io_virt	       @ virtual address
-		add     \rx, \rx, #0x00020000   @ UART1
+		.macro  addruart, rp, rv
+		mov     \rp, #0x00020000	@ UART1
+		add     \rv, \rp, #io_virt	@ virtual address
+		add     \rp, \rp, #io_phys	@ physical base address
 		.endm
 
 		.macro  senduart,rd,rx
diff --git a/arch/arm/mach-h720x/include/mach/vmalloc.h b/arch/arm/mach-h720x/include/mach/vmalloc.h
index ff1460d..a45915b 100644
--- a/arch/arm/mach-h720x/include/mach/vmalloc.h
+++ b/arch/arm/mach-h720x/include/mach/vmalloc.h
@@ -5,6 +5,6 @@
 #ifndef __ARCH_ARM_VMALLOC_H
 #define __ARCH_ARM_VMALLOC_H
 
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
 
 #endif
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index c5c0369..197f9e2 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -122,6 +122,7 @@
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_NAND
+	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for Eukrea CPUIMX27 platform. This includes
 	  specific configurations for the module and its peripherals.
@@ -146,8 +147,8 @@
 	default MACH_EUKREA_MBIMX27_BASEBOARD
 
 config MACH_EUKREA_MBIMX27_BASEBOARD
-	prompt "Eukrea MBIMX27 development board"
-	bool
+	bool "Eukrea MBIMX27 development board"
+	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
@@ -163,6 +164,15 @@
 	  Include support for MX27PDK platform. This includes specific
 	  configurations for the board and its peripherals.
 
+config MACH_IMX27_VISSTRIM_M10
+	bool "Vista Silicon i.MX27 Visstrim_m10"
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
+	help
+	  Include support for Visstrim_m10 platform and its different variants.
+	  This includes specific configurations for the board and its
+	  peripherals.
+
 config MACH_IMX27LITE
 	bool "LogicPD MX27 LITEKIT platform"
 	select IMX_HAVE_PLATFORM_IMX_UART
@@ -173,6 +183,7 @@
 config MACH_PCA100
 	bool "Phytec phyCARD-s (pca100)"
 	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SPI_IMX
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 46a9fdf..5582692 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -27,6 +27,7 @@
 obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o
 obj-$(CONFIG_MACH_MX27_3DS) += mach-mx27_3ds.o
 obj-$(CONFIG_MACH_IMX27LITE) += mach-imx27lite.o
+obj-$(CONFIG_MACH_IMX27_VISSTRIM_M10) += mach-imx27_visstrim_m10.o
 obj-$(CONFIG_MACH_CPUIMX27) += mach-cpuimx27.o
 obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o
 obj-$(CONFIG_MACH_PCA100) += mach-pca100.o
diff --git a/arch/arm/mach-imx/clock-imx1.c b/arch/arm/mach-imx/clock-imx1.c
index c05096c..daca30b 100644
--- a/arch/arm/mach-imx/clock-imx1.c
+++ b/arch/arm/mach-imx/clock-imx1.c
@@ -592,7 +592,7 @@
 	_REGISTER_CLOCK("imx-uart.1", NULL, uart_clk)
 	_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
-	_REGISTER_CLOCK("spi_imx.0", NULL, spi_clk)
+	_REGISTER_CLOCK("imx1-cspi.0", 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-imx21.c b/arch/arm/mach-imx/clock-imx21.c
index bb419ef..cf15ea5 100644
--- a/arch/arm/mach-imx/clock-imx21.c
+++ b/arch/arm/mach-imx/clock-imx21.c
@@ -1172,9 +1172,9 @@
 	_REGISTER_CLOCK(NULL, "pwm", pwm_clk[0])
 	_REGISTER_CLOCK(NULL, "sdhc1", sdhc_clk[0])
 	_REGISTER_CLOCK(NULL, "sdhc2", sdhc_clk[1])
-	_REGISTER_CLOCK(NULL, "cspi1", cspi_clk[0])
-	_REGISTER_CLOCK(NULL, "cspi2", cspi_clk[1])
-	_REGISTER_CLOCK(NULL, "cspi3", cspi_clk[2])
+	_REGISTER_CLOCK("imx21-cspi.0", NULL, cspi_clk[0])
+	_REGISTER_CLOCK("imx21-cspi.1", NULL, cspi_clk[1])
+	_REGISTER_CLOCK("imx21-cspi.2", NULL, cspi_clk[2])
 	_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk[0])
 	_REGISTER_CLOCK(NULL, "csi", csi_clk[0])
 	_REGISTER_CLOCK("imx21-hcd.0", NULL, usb_clk[0])
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index 5a1aa15..98a25ba 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -594,27 +594,27 @@
 DEFINE_CLOCK(uart1_clk1,   0, PCCR1, 31, NULL, NULL, &ipg_clk);
 
 /* Clocks we cannot directly gate, but drivers need their rates */
-DEFINE_CLOCK(cspi1_clk,    0, 0,      0, NULL, &cspi1_clk1, &per2_clk);
-DEFINE_CLOCK(cspi2_clk,    1, 0,      0, NULL, &cspi2_clk1, &per2_clk);
-DEFINE_CLOCK(cspi3_clk,    2, 0,      0, NULL, &cspi13_clk1, &per2_clk);
-DEFINE_CLOCK(sdhc1_clk,    0, 0,      0, NULL, &sdhc1_clk1, &per2_clk);
-DEFINE_CLOCK(sdhc2_clk,    1, 0,      0, NULL, &sdhc2_clk1, &per2_clk);
-DEFINE_CLOCK(sdhc3_clk,    2, 0,      0, NULL, &sdhc3_clk1, &per2_clk);
-DEFINE_CLOCK(pwm_clk,      0, 0,      0, NULL, &pwm_clk1, &per1_clk);
-DEFINE_CLOCK(gpt1_clk,     0, 0,      0, NULL, &gpt1_clk1, &per1_clk);
-DEFINE_CLOCK(gpt2_clk,     1, 0,      0, NULL, &gpt2_clk1, &per1_clk);
-DEFINE_CLOCK(gpt3_clk,     2, 0,      0, NULL, &gpt3_clk1, &per1_clk);
-DEFINE_CLOCK(gpt4_clk,     3, 0,      0, NULL, &gpt4_clk1, &per1_clk);
-DEFINE_CLOCK(gpt5_clk,     4, 0,      0, NULL, &gpt5_clk1, &per1_clk);
-DEFINE_CLOCK(gpt6_clk,     5, 0,      0, NULL, &gpt6_clk1, &per1_clk);
-DEFINE_CLOCK(uart1_clk,    0, 0,      0, NULL, &uart1_clk1, &per1_clk);
-DEFINE_CLOCK(uart2_clk,    1, 0,      0, NULL, &uart2_clk1, &per1_clk);
-DEFINE_CLOCK(uart3_clk,    2, 0,      0, NULL, &uart3_clk1, &per1_clk);
-DEFINE_CLOCK(uart4_clk,    3, 0,      0, NULL, &uart4_clk1, &per1_clk);
-DEFINE_CLOCK(uart5_clk,    4, 0,      0, NULL, &uart5_clk1, &per1_clk);
-DEFINE_CLOCK(uart6_clk,    5, 0,      0, NULL, &uart6_clk1, &per1_clk);
-DEFINE_CLOCK1(lcdc_clk,    0, 0,      0, parent, &lcdc_clk1, &per3_clk);
-DEFINE_CLOCK1(csi_clk,     0, 0,      0, parent, &csi_clk1, &per4_clk);
+DEFINE_CLOCK(cspi1_clk,    0, NULL,   0, NULL, &cspi1_clk1, &per2_clk);
+DEFINE_CLOCK(cspi2_clk,    1, NULL,   0, NULL, &cspi2_clk1, &per2_clk);
+DEFINE_CLOCK(cspi3_clk,    2, NULL,   0, NULL, &cspi13_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc1_clk,    0, NULL,   0, NULL, &sdhc1_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc2_clk,    1, NULL,   0, NULL, &sdhc2_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc3_clk,    2, NULL,   0, NULL, &sdhc3_clk1, &per2_clk);
+DEFINE_CLOCK(pwm_clk,      0, NULL,   0, NULL, &pwm_clk1, &per1_clk);
+DEFINE_CLOCK(gpt1_clk,     0, NULL,   0, NULL, &gpt1_clk1, &per1_clk);
+DEFINE_CLOCK(gpt2_clk,     1, NULL,   0, NULL, &gpt2_clk1, &per1_clk);
+DEFINE_CLOCK(gpt3_clk,     2, NULL,   0, NULL, &gpt3_clk1, &per1_clk);
+DEFINE_CLOCK(gpt4_clk,     3, NULL,   0, NULL, &gpt4_clk1, &per1_clk);
+DEFINE_CLOCK(gpt5_clk,     4, NULL,   0, NULL, &gpt5_clk1, &per1_clk);
+DEFINE_CLOCK(gpt6_clk,     5, NULL,   0, NULL, &gpt6_clk1, &per1_clk);
+DEFINE_CLOCK(uart1_clk,    0, NULL,   0, NULL, &uart1_clk1, &per1_clk);
+DEFINE_CLOCK(uart2_clk,    1, NULL,   0, NULL, &uart2_clk1, &per1_clk);
+DEFINE_CLOCK(uart3_clk,    2, NULL,   0, NULL, &uart3_clk1, &per1_clk);
+DEFINE_CLOCK(uart4_clk,    3, NULL,   0, NULL, &uart4_clk1, &per1_clk);
+DEFINE_CLOCK(uart5_clk,    4, NULL,   0, NULL, &uart5_clk1, &per1_clk);
+DEFINE_CLOCK(uart6_clk,    5, NULL,   0, NULL, &uart6_clk1, &per1_clk);
+DEFINE_CLOCK1(lcdc_clk,    0, NULL,   0, parent, &lcdc_clk1, &per3_clk);
+DEFINE_CLOCK1(csi_clk,     0, NULL,   0, parent, &csi_clk1, &per4_clk);
 
 #define _REGISTER_CLOCK(d, n, c) \
 	{ \
@@ -640,9 +640,9 @@
 	_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
 	_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
 	_REGISTER_CLOCK("mxc-mmc.2", NULL, sdhc3_clk)
-	_REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
-	_REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
-	_REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
+	_REGISTER_CLOCK("imx27-cspi.0", NULL, cspi1_clk)
+	_REGISTER_CLOCK("imx27-cspi.1", NULL, cspi2_clk)
+	_REGISTER_CLOCK("imx27-cspi.2", NULL, cspi3_clk)
 	_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
 	_REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk)
diff --git a/arch/arm/mach-imx/devices-imx1.h b/arch/arm/mach-imx/devices-imx1.h
index a8d94f0..8197948 100644
--- a/arch/arm/mach-imx/devices-imx1.h
+++ b/arch/arm/mach-imx/devices-imx1.h
@@ -9,10 +9,12 @@
 #include <mach/mx1.h>
 #include <mach/devices-common.h>
 
-#define imx1_add_i2c_imx(pdata)		\
-	imx_add_imx_i2c(0, MX1_I2C_BASE_ADDR, SZ_4K, MX1_INT_I2C, 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)
 
-#define imx1_add_imx_uart0(pdata)	\
-	imx_add_imx_uart_3irq(0, MX1_UART1_BASE_ADDR, 0xd0, MX1_INT_UART1RX, MX1_INT_UART1TX, MX1_INT_UART1RTS, pdata)
-#define imx1_add_imx_uart1(pdata)	\
-	imx_add_imx_uart_3irq(0, MX1_UART2_BASE_ADDR, 0xd0, MX1_INT_UART2RX, MX1_INT_UART2TX, MX1_INT_UART2RTS, pdata)
+extern const struct imx_imx_uart_3irq_data imx1_imx_uart_data[] __initconst;
+#define imx1_add_imx_uart(id, pdata)	\
+	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)
diff --git a/arch/arm/mach-imx/devices-imx21.h b/arch/arm/mach-imx/devices-imx21.h
index 42788e9..d189039 100644
--- a/arch/arm/mach-imx/devices-imx21.h
+++ b/arch/arm/mach-imx/devices-imx21.h
@@ -9,22 +9,28 @@
 #include <mach/mx21.h>
 #include <mach/devices-common.h>
 
-#define imx21_add_i2c_imx(pdata)	\
-	imx_add_imx_i2c(0, MX2x_I2C_BASE_ADDR, SZ_4K, MX2x_INT_I2C, pdata)
+extern const struct imx_imx_i2c_data imx21_imx_i2c_data __initconst;
+#define imx21_add_imx_i2c(pdata)	\
+	imx_add_imx_i2c(&imx21_imx_i2c_data, pdata)
 
-#define imx21_add_imx_uart0(pdata)	\
-	imx_add_imx_uart_1irq(0, MX21_UART1_BASE_ADDR, SZ_4K, MX21_INT_UART1, pdata)
-#define imx21_add_imx_uart1(pdata)	\
-	imx_add_imx_uart_1irq(1, MX21_UART2_BASE_ADDR, SZ_4K, MX21_INT_UART2, pdata)
-#define imx21_add_imx_uart2(pdata)	\
-	imx_add_imx_uart_1irq(2, MX21_UART3_BASE_ADDR, SZ_4K, MX21_INT_UART3, pdata)
-#define imx21_add_imx_uart3(pdata)	\
-	imx_add_imx_uart_1irq(3, MX21_UART4_BASE_ADDR, SZ_4K, MX21_INT_UART4, pdata)
+extern const struct imx_imx_ssi_data imx21_imx_ssi_data[] __initconst;
+#define imx21_add_imx_ssi(id, pdata)	\
+	imx_add_imx_ssi(&imx21_imx_ssi_data[id], pdata)
 
+extern const struct imx_imx_uart_1irq_data imx21_imx_uart_data[] __initconst;
+#define imx21_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx21_imx_uart_data[id], pdata)
+#define imx21_add_imx_uart0(pdata)	imx21_add_imx_uart(0, pdata)
+#define imx21_add_imx_uart1(pdata)	imx21_add_imx_uart(1, pdata)
+#define imx21_add_imx_uart2(pdata)	imx21_add_imx_uart(2, pdata)
+#define imx21_add_imx_uart3(pdata)	imx21_add_imx_uart(3, pdata)
+
+extern const struct imx_mxc_nand_data imx21_mxc_nand_data __initconst;
 #define imx21_add_mxc_nand(pdata)	\
-	imx_add_mxc_nand_v1(MX21_NFC_BASE_ADDR, MX21_INT_NANDFC, pdata)
+	imx_add_mxc_nand(&imx21_mxc_nand_data, pdata)
 
-#define imx21_add_spi_imx0(pdata)	\
-	imx_add_spi_imx(0, MX21_CSPI1_BASE_ADDR, SZ_4K, MX21_INT_CSPI1, pdata)
-#define imx21_add_spi_imx1(pdata)	\
-	imx_add_spi_imx(1, MX21_CSPI2_BASE_ADDR, SZ_4K, MX21_INT_CSPI2, pdata)
+extern const struct imx_spi_imx_data imx21_cspi_data[] __initconst;
+#define imx21_add_cspi(id, pdata)	\
+	imx_add_spi_imx(&imx21_cspi_data[id], pdata)
+#define imx21_add_spi_imx0(pdata)	imx21_add_cspi(0, pdata)
+#define imx21_add_spi_imx1(pdata)	imx21_add_cspi(1, pdata)
diff --git a/arch/arm/mach-imx/devices-imx27.h b/arch/arm/mach-imx/devices-imx27.h
index 65e7bb7..7011690 100644
--- a/arch/arm/mach-imx/devices-imx27.h
+++ b/arch/arm/mach-imx/devices-imx27.h
@@ -9,30 +9,35 @@
 #include <mach/mx27.h>
 #include <mach/devices-common.h>
 
-#define imx27_add_i2c_imx0(pdata)	\
-	imx_add_imx_i2c(0, MX27_I2C1_BASE_ADDR, SZ_4K, MX27_INT_I2C1, pdata)
-#define imx27_add_i2c_imx1(pdata)	\
-	imx_add_imx_i2c(1, MX27_I2C2_BASE_ADDR, SZ_4K, MX27_INT_I2C2, pdata)
+extern const struct imx_fec_data imx27_fec_data __initconst;
+#define imx27_add_fec(pdata)	\
+	imx_add_fec(&imx27_fec_data, pdata)
 
-#define imx27_add_imx_uart0(pdata)	\
-	imx_add_imx_uart_1irq(0, MX27_UART1_BASE_ADDR, SZ_4K, MX27_INT_UART1, pdata)
-#define imx27_add_imx_uart1(pdata)	\
-	imx_add_imx_uart_1irq(1, MX27_UART2_BASE_ADDR, SZ_4K, MX27_INT_UART2, pdata)
-#define imx27_add_imx_uart2(pdata)	\
-	imx_add_imx_uart_1irq(2, MX27_UART3_BASE_ADDR, SZ_4K, MX27_INT_UART3, pdata)
-#define imx27_add_imx_uart3(pdata)	\
-	imx_add_imx_uart_1irq(3, MX27_UART4_BASE_ADDR, SZ_4K, MX27_INT_UART4, pdata)
-#define imx27_add_imx_uart4(pdata)	\
-	imx_add_imx_uart_1irq(4, MX27_UART5_BASE_ADDR, SZ_4K, MX27_INT_UART5, pdata)
-#define imx27_add_imx_uart5(pdata)	\
-	imx_add_imx_uart_1irq(5, MX27_UART6_BASE_ADDR, SZ_4K, MX27_INT_UART6, pdata)
+extern const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst;
+#define imx27_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx27_imx_i2c_data[id], pdata)
 
+extern const struct imx_imx_ssi_data imx27_imx_ssi_data[] __initconst;
+#define imx27_add_imx_ssi(id, pdata)    \
+	imx_add_imx_ssi(&imx27_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx27_imx_uart_data[] __initconst;
+#define imx27_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx27_imx_uart_data[id], pdata)
+#define imx27_add_imx_uart0(pdata)	imx27_add_imx_uart(0, pdata)
+#define imx27_add_imx_uart1(pdata)	imx27_add_imx_uart(1, pdata)
+#define imx27_add_imx_uart2(pdata)	imx27_add_imx_uart(2, pdata)
+#define imx27_add_imx_uart3(pdata)	imx27_add_imx_uart(3, pdata)
+#define imx27_add_imx_uart4(pdata)	imx27_add_imx_uart(4, pdata)
+#define imx27_add_imx_uart5(pdata)	imx27_add_imx_uart(5, pdata)
+
+extern const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst;
 #define imx27_add_mxc_nand(pdata)	\
-	imx_add_mxc_nand_v1(MX27_NFC_BASE_ADDR, MX27_INT_NANDFC, pdata)
+	imx_add_mxc_nand(&imx27_mxc_nand_data, pdata)
 
-#define imx27_add_spi_imx0(pdata)	\
-	imx_add_spi_imx(0, MX27_CSPI1_BASE_ADDR, SZ_4K, MX27_INT_CSPI1, pdata)
-#define imx27_add_spi_imx1(pdata)	\
-	imx_add_spi_imx(1, MX27_CSPI2_BASE_ADDR, SZ_4K, MX27_INT_CSPI2, pdata)
-#define imx27_add_spi_imx2(pdata)	\
-	imx_add_spi_imx(2, MX27_CSPI3_BASE_ADDR, SZ_4K, MX27_INT_CSPI3, pdata)
+extern const struct imx_spi_imx_data imx27_cspi_data[] __initconst;
+#define imx27_add_cspi(id, pdata)	\
+	imx_add_spi_imx(&imx27_cspi_data[id], pdata)
+#define imx27_add_spi_imx0(pdata)	imx27_add_cspi(0, pdata)
+#define imx27_add_spi_imx1(pdata)	imx27_add_cspi(1, pdata)
+#define imx27_add_spi_imx2(pdata)	imx27_add_cspi(2, pdata)
diff --git a/arch/arm/mach-imx/devices.c b/arch/arm/mach-imx/devices.c
index 9c271a7..fba5047 100644
--- a/arch/arm/mach-imx/devices.c
+++ b/arch/arm/mach-imx/devices.c
@@ -314,27 +314,6 @@
 	},
 };
 
-#ifdef CONFIG_MACH_MX27
-static struct resource mxc_fec_resources[] = {
-	{
-		.start = MX27_FEC_BASE_ADDR,
-		.end = MX27_FEC_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX27_INT_FEC,
-		.end = MX27_INT_FEC,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_fec_device = {
-	.name = "fec",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_fec_resources),
-	.resource = mxc_fec_resources,
-};
-#endif
-
 static struct resource mxc_pwm_resources[] = {
 	{
 		.start = MX2x_PWM_BASE_ADDR,
@@ -480,41 +459,6 @@
 };
 #endif
 
-#define DEFINE_IMX_SSI_DMARES(_name, ssin, suffix)			\
-	{								\
-		.name = _name,						\
-		.start = MX2x_DMA_REQ_SSI ## ssin ## _ ## suffix,	\
-		.end = MX2x_DMA_REQ_SSI ## ssin ## _ ## suffix,		\
-		.flags = IORESOURCE_DMA,				\
-	}
-
-#define DEFINE_IMX_SSI_DEVICE(n, ssin, baseaddr, irq)			\
-	static struct resource imx_ssi_resources ## n[] = {		\
-		{							\
-			.start = MX2x_SSI ## ssin ## _BASE_ADDR,	\
-			.end = MX2x_SSI ## ssin ## _BASE_ADDR + 0x6f,	\
-			.flags = IORESOURCE_MEM,			\
-		}, {							\
-			.start = MX2x_INT_SSI1,				\
-			.end = MX2x_INT_SSI1,				\
-			.flags = IORESOURCE_IRQ,			\
-		},							\
-		DEFINE_IMX_SSI_DMARES("tx0", ssin, TX0),		\
-		DEFINE_IMX_SSI_DMARES("rx0", ssin, RX0),		\
-		DEFINE_IMX_SSI_DMARES("tx1", ssin, TX1),		\
-		DEFINE_IMX_SSI_DMARES("rx1", ssin, RX1),		\
-	};								\
-									\
-	struct platform_device imx_ssi_device ## n = {			\
-		.name = "imx-ssi",					\
-		.id = n,						\
-		.num_resources = ARRAY_SIZE(imx_ssi_resources ## n),	\
-		.resource = imx_ssi_resources ## n,			\
-	}
-
-DEFINE_IMX_SSI_DEVICE(0, 1, MX2x_SSI1_BASE_ADDR, MX2x_INT_SSI1);
-DEFINE_IMX_SSI_DEVICE(1, 2, MX2x_SSI1_BASE_ADDR, MX2x_INT_SSI1);
-
 /* GPIO port description */
 #define DEFINE_MXC_GPIO_PORT_IRQ(SOC, n, _irq)				\
 	{								\
diff --git a/arch/arm/mach-imx/devices.h b/arch/arm/mach-imx/devices.h
index efd4527..807f02a 100644
--- a/arch/arm/mach-imx/devices.h
+++ b/arch/arm/mach-imx/devices.h
@@ -16,7 +16,6 @@
 extern struct platform_device mxc_wdt;
 extern struct platform_device mxc_w1_master_device;
 extern struct platform_device mxc_fb_device;
-extern struct platform_device mxc_fec_device;
 extern struct platform_device mxc_pwm_device;
 extern struct platform_device mxc_sdhc_device0;
 extern struct platform_device mxc_sdhc_device1;
@@ -26,7 +25,5 @@
 extern struct platform_device mxc_usbh1;
 extern struct platform_device mxc_usbh2;
 extern struct platform_device mx21_usbhc_device;
-extern struct platform_device imx_ssi_device0;
-extern struct platform_device imx_ssi_device1;
 extern struct platform_device imx_kpp_device;
 #endif
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index 4edc5f4..026263c 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -36,13 +36,12 @@
 #include <mach/hardware.h>
 #include <mach/mmc.h>
 #include <mach/spi.h>
-#include <mach/ssi.h>
 #include <mach/audmux.h>
 
 #include "devices-imx27.h"
 #include "devices.h"
 
-static int eukrea_mbimx27_pins[] = {
+static const int eukrea_mbimx27_pins[] __initconst = {
 	/* UART2 */
 	PE3_PF_UART2_CTS,
 	PE4_PF_UART2_RTS,
@@ -311,7 +310,8 @@
 	.dat3_card_detect = 1,
 };
 
-struct imx_ssi_platform_data eukrea_mbimx27_ssi_pdata = {
+static const
+struct imx_ssi_platform_data eukrea_mbimx27_ssi_pdata __initconst = {
 	.flags = IMX_SSI_DMA | IMX_SSI_USE_I2S_SLAVE,
 };
 
@@ -357,7 +357,7 @@
 	i2c_register_board_info(0, eukrea_mbimx27_i2c_devices,
 				ARRAY_SIZE(eukrea_mbimx27_i2c_devices));
 
-	mxc_register_device(&imx_ssi_device0, &eukrea_mbimx27_ssi_pdata);
+	imx27_add_imx_ssi(0, &eukrea_mbimx27_ssi_pdata);
 
 #if defined(CONFIG_TOUCHSCREEN_ADS7846) \
 	|| defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index 339150a..745ee60 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -46,7 +46,7 @@
 #include "devices-imx27.h"
 #include "devices.h"
 
-static int eukrea_cpuimx27_pins[] = {
+static const int eukrea_cpuimx27_pins[] __initconst = {
 	/* UART1 */
 	PE12_PF_UART1_TXD,
 	PE13_PF_UART1_RXD,
@@ -157,7 +157,6 @@
 
 static struct platform_device *platform_devices[] __initdata = {
 	&eukrea_cpuimx27_nor_mtd_device,
-	&mxc_fec_device,
 	&mxc_wdt,
 	&mxc_w1_master_device,
 };
@@ -259,8 +258,9 @@
 	i2c_register_board_info(0, eukrea_cpuimx27_i2c_devices,
 				ARRAY_SIZE(eukrea_cpuimx27_i2c_devices));
 
-	imx27_add_i2c_imx1(&cpuimx27_i2c1_data);
+	imx27_add_imx_i2c(0, &cpuimx27_i2c1_data);
 
+	imx27_add_fec(NULL);
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
 #if defined(CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2)
@@ -307,8 +307,6 @@
 };
 
 MACHINE_START(CPUIMX27, "EUKREA CPUIMX27")
-	.phys_io        = MX27_AIPI_BASE_ADDR,
-	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX27_PHYS_OFFSET + 0x100,
 	.map_io         = mx27_map_io,
 	.init_irq       = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
new file mode 100644
index 0000000..59716fa
--- /dev/null
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -0,0 +1,261 @@
+/*
+ * mach-imx27_visstrim_m10.c
+ *
+ * Copyright 2010  Javier Martin <javier.martin@vista-silicon.com>
+ *
+ * Based on mach-pcm038.c, mach-pca100.c, mach-mx27ads.c 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mmc.h>
+#include <mach/iomux.h>
+#include <mach/mxc_ehci.h>
+
+#include "devices-imx27.h"
+#include "devices.h"
+
+#define OTG_PHY_CS_GPIO (GPIO_PORTF + 17)
+#define SDHC1_IRQ IRQ_GPIOB(25)
+
+static const int visstrim_m10_pins[] __initconst = {
+	/* UART1 (console) */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* 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,
+	/* SDHC1 */
+	PE18_PF_SD1_D0,
+	PE19_PF_SD1_D1,
+	PE20_PF_SD1_D2,
+	PE21_PF_SD1_D3,
+	PE22_PF_SD1_CMD,
+	PE23_PF_SD1_CLK,
+	/* Both I2Cs */
+	PD17_PF_I2C_DATA,
+	PD18_PF_I2C_CLK,
+	PC5_PF_I2C2_SDA,
+	PC6_PF_I2C2_SCL,
+	/* USB OTG */
+	OTG_PHY_CS_GPIO | GPIO_GPIO | GPIO_OUT,
+	PC9_PF_USBOTG_DATA0,
+	PC11_PF_USBOTG_DATA1,
+	PC10_PF_USBOTG_DATA2,
+	PC13_PF_USBOTG_DATA3,
+	PC12_PF_USBOTG_DATA4,
+	PC7_PF_USBOTG_DATA5,
+	PC8_PF_USBOTG_DATA6,
+	PE25_PF_USBOTG_DATA7,
+	PE24_PF_USBOTG_CLK,
+	PE2_PF_USBOTG_DIR,
+	PE0_PF_USBOTG_NXT,
+	PE1_PF_USBOTG_STP,
+	PB23_PF_USB_PWR,
+	PB24_PF_USB_OC,
+};
+
+/* GPIOs used as events for applications */
+static struct gpio_keys_button visstrim_gpio_keys[] = {
+	{
+		.type	= EV_KEY,
+		.code	= KEY_RESTART,
+		.gpio	= (GPIO_PORTC + 15),
+		.desc	= "Default config",
+		.active_low = 0,
+		.wakeup = 1,
+	},
+	{
+		.type	= EV_KEY,
+		.code	= KEY_RECORD,
+		.gpio	= (GPIO_PORTF + 14),
+		.desc	= "Record",
+		.active_low = 0,
+		.wakeup = 1,
+	},
+	{
+		.type   = EV_KEY,
+		.code   = KEY_STOP,
+		.gpio   = (GPIO_PORTF + 13),
+		.desc   = "Stop",
+		.active_low = 0,
+		.wakeup = 1,
+	}
+};
+
+static struct gpio_keys_platform_data visstrim_gpio_keys_platform_data = {
+	.buttons	= visstrim_gpio_keys,
+	.nbuttons	= ARRAY_SIZE(visstrim_gpio_keys),
+};
+
+static struct platform_device visstrim_gpio_keys_device = {
+	.name	= "gpio-keys",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &visstrim_gpio_keys_platform_data,
+	},
+};
+
+/* Visstrim_SM10 has a microSD slot connected to sdhc1 */
+static int visstrim_m10_sdhc1_init(struct device *dev,
+		irq_handler_t detect_irq, void *data)
+{
+	int ret;
+
+	ret = request_irq(SDHC1_IRQ, detect_irq, IRQF_TRIGGER_FALLING,
+				"mmc-detect", data);
+	return ret;
+}
+
+static void visstrim_m10_sdhc1_exit(struct device *dev, void *data)
+{
+	free_irq(SDHC1_IRQ, data);
+}
+
+static struct imxmmc_platform_data visstrim_m10_sdhc_pdata = {
+	.init = visstrim_m10_sdhc1_init,
+	.exit = visstrim_m10_sdhc1_exit,
+};
+
+/* Visstrim_SM10 NOR flash */
+static struct physmap_flash_data visstrim_m10_flash_data = {
+	.width = 2,
+};
+
+static struct resource visstrim_m10_flash_resource = {
+	.start = 0xc0000000,
+	.end = 0xc0000000 + SZ_64M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device visstrim_m10_nor_mtd_device = {
+	.name = "physmap-flash",
+	.id = 0,
+	.dev = {
+		.platform_data = &visstrim_m10_flash_data,
+	},
+	.num_resources = 1,
+	.resource = &visstrim_m10_flash_resource,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&visstrim_gpio_keys_device,
+	&visstrim_m10_nor_mtd_device,
+};
+
+/* Visstrim_M10 uses UART0 as console */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+/* I2C */
+static const struct imxi2c_platform_data visstrim_m10_i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
+static struct pca953x_platform_data visstrim_m10_pca9555_pdata = {
+	.gpio_base = 240, /* After MX27 internal GPIOs */
+	.invert = 0,
+};
+
+static struct i2c_board_info visstrim_m10_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("pca9555", 0x20),
+		.platform_data = &visstrim_m10_pca9555_pdata,
+	},
+};
+
+/* USB OTG */
+static int otg_phy_init(struct platform_device *pdev)
+{
+	gpio_set_value(OTG_PHY_CS_GPIO, 0);
+	return 0;
+}
+
+static struct mxc_usbh_platform_data visstrim_m10_usbotg_pdata = {
+	.init = otg_phy_init,
+	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
+	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
+};
+
+static void __init visstrim_m10_board_init(void)
+{
+	int ret;
+
+	ret = mxc_gpio_setup_multiple_pins(visstrim_m10_pins,
+			ARRAY_SIZE(visstrim_m10_pins), "VISSTRIM_M10");
+	if (ret)
+		pr_err("Failed to setup pins (%d)\n", ret);
+
+	imx27_add_imx_uart0(&uart_pdata);
+
+	i2c_register_board_info(0, visstrim_m10_i2c_devices,
+				ARRAY_SIZE(visstrim_m10_i2c_devices));
+	imx27_add_imx_i2c(0, &visstrim_m10_i2c_data);
+	imx27_add_imx_i2c(1, &visstrim_m10_i2c_data);
+	mxc_register_device(&mxc_sdhc_device0, &visstrim_m10_sdhc_pdata);
+	mxc_register_device(&mxc_otg_host, &visstrim_m10_usbotg_pdata);
+	imx27_add_fec(NULL);
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init visstrim_m10_timer_init(void)
+{
+	mx27_clocks_init((unsigned long)25000000);
+}
+
+static struct sys_timer visstrim_m10_timer = {
+	.init	= visstrim_m10_timer_init,
+};
+
+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,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c
index 22a2b5d..bbdbc75 100644
--- a/arch/arm/mach-imx/mach-imx27lite.c
+++ b/arch/arm/mach-imx/mach-imx27lite.c
@@ -27,7 +27,7 @@
 #include "devices-imx27.h"
 #include "devices.h"
 
-static unsigned int mx27lite_pins[] = {
+static const int mx27lite_pins[] __initconst = {
 	/* UART1 */
 	PE12_PF_UART1_TXD,
 	PE13_PF_UART1_RXD,
@@ -58,16 +58,12 @@
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static struct platform_device *platform_devices[] __initdata = {
-	&mxc_fec_device,
-};
-
 static void __init mx27lite_init(void)
 {
 	mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),
 		"imx27lite");
 	imx27_add_imx_uart0(&uart_pdata);
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	imx27_add_fec(NULL);
 }
 
 static void __init mx27lite_timer_init(void)
@@ -80,8 +76,6 @@
 };
 
 MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
-	.phys_io        = MX27_AIPI_BASE_ADDR,
-	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX27_PHYS_OFFSET + 0x100,
 	.map_io         = mx27_map_io,
 	.init_irq       = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c
index 77a760c..6187ce9 100644
--- a/arch/arm/mach-imx/mach-mx1ads.c
+++ b/arch/arm/mach-imx/mach-mx1ads.c
@@ -32,7 +32,7 @@
 #include "devices-imx1.h"
 #include "devices.h"
 
-static int mx1ads_pins[] = {
+static const int mx1ads_pins[] __initconst = {
 	/* UART1 */
 	PC9_PF_UART1_CTS,
 	PC10_PF_UART1_RTS,
@@ -131,7 +131,7 @@
 	i2c_register_board_info(0, mx1ads_i2c_devices,
 				ARRAY_SIZE(mx1ads_i2c_devices));
 
-	imx1_add_i2c_imx(&mx1ads_i2c_data);
+	imx1_add_imx_i2c(&mx1ads_i2c_data);
 }
 
 static void __init mx1ads_timer_init(void)
@@ -145,8 +145,6 @@
 
 MACHINE_START(MX1ADS, "Freescale MX1ADS")
 	/* Maintainer: Sascha Hauer, Pengutronix */
-	.phys_io	= MX1_IO_BASE_ADDR,
-	.io_pg_offst	= (MX1_IO_BASE_ADDR_VIRT >> 18) & 0xfffc,
 	.boot_params	= MX1_PHYS_OFFSET + 0x100,
 	.map_io		= mx1_map_io,
 	.init_irq	= mx1_init_irq,
@@ -155,8 +153,6 @@
 MACHINE_END
 
 MACHINE_START(MXLADS, "Freescale MXLADS")
-	.phys_io	= MX1_IO_BASE_ADDR,
-	.io_pg_offst	= (MX1_IO_BASE_ADDR_VIRT >> 18) & 0xfffc,
 	.boot_params	= MX1_PHYS_OFFSET + 0x100,
 	.map_io		= mx1_map_io,
 	.init_irq	= mx1_init_irq,
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index 96d7f81..e1282e9 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -67,7 +67,7 @@
 #define MX21ADS_IO_LED4_ON      0x4000
 #define MX21ADS_IO_LED3_ON      0x8000
 
-static unsigned int mx21ads_pins[] = {
+static const int mx21ads_pins[] __initconst = {
 
 	/* CS8900A */
 	(GPIO_PORTE | GPIO_GPIO | GPIO_IN | 11),
@@ -314,8 +314,6 @@
 
 MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.phys_io        = MX21_AIPI_BASE_ADDR,
-	.io_pg_offst    = ((MX21_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX21_PHYS_OFFSET + 0x100,
 	.map_io         = mx21ads_map_io,
 	.init_irq       = mx21_init_irq,
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index e66ffaa..b8bbd31 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -33,7 +33,7 @@
 #include "devices-imx27.h"
 #include "devices.h"
 
-static unsigned int mx27pdk_pins[] = {
+static const int mx27pdk_pins[] __initconst = {
 	/* UART1 */
 	PE12_PF_UART1_TXD,
 	PE13_PF_UART1_RXD,
@@ -64,10 +64,6 @@
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static struct platform_device *platform_devices[] __initdata = {
-	&mxc_fec_device,
-};
-
 /*
  * Matrix keyboard
  */
@@ -94,7 +90,7 @@
 	mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
 		"mx27pdk");
 	imx27_add_imx_uart0(&uart_pdata);
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	imx27_add_fec(NULL);
 	mxc_register_device(&imx_kpp_device, &mx27_3ds_keymap_data);
 }
 
@@ -109,8 +105,6 @@
 
 MACHINE_START(MX27_3DS, "Freescale MX27PDK")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.phys_io        = MX27_AIPI_BASE_ADDR,
-	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX27_PHYS_OFFSET + 0x100,
 	.map_io         = mx27_map_io,
 	.init_irq       = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index 9c77da9..a1e4bc5 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -66,7 +66,7 @@
 /* to determine the correct external crystal reference */
 #define CKIH_27MHZ_BIT_SET      (1 << 3)
 
-static unsigned int mx27ads_pins[] = {
+static const int mx27ads_pins[] __initconst = {
 	/* UART0 */
 	PE12_PF_UART1_TXD,
 	PE13_PF_UART1_RXD,
@@ -284,7 +284,6 @@
 
 static struct platform_device *platform_devices[] __initdata = {
 	&mx27ads_nor_mtd_device,
-	&mxc_fec_device,
 	&mxc_w1_master_device,
 };
 
@@ -308,11 +307,12 @@
 	/* only the i2c master 1 is used on this CPU card */
 	i2c_register_board_info(1, mx27ads_i2c_devices,
 				ARRAY_SIZE(mx27ads_i2c_devices));
-	imx27_add_i2c_imx1(&mx27ads_i2c1_data);
+	imx27_add_imx_i2c(1, &mx27ads_i2c1_data);
 	mxc_register_device(&mxc_fb_device, &mx27ads_fb_data);
 	mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
 	mxc_register_device(&mxc_sdhc_device1, &sdhc2_pdata);
 
+	imx27_add_fec(NULL);
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 }
 
@@ -347,8 +347,6 @@
 
 MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.phys_io        = MX27_AIPI_BASE_ADDR,
-	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX27_PHYS_OFFSET + 0x100,
 	.map_io         = mx27ads_map_io,
 	.init_irq       = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c
index a3a1e45..38d3a4a 100644
--- a/arch/arm/mach-imx/mach-mxt_td60.c
+++ b/arch/arm/mach-imx/mach-mxt_td60.c
@@ -37,7 +37,7 @@
 #include "devices-imx27.h"
 #include "devices.h"
 
-static unsigned int mxt_td60_pins[] __initdata = {
+static const int mxt_td60_pins[] __initconst = {
 	/* UART0 */
 	PE12_PF_UART1_TXD,
 	PE13_PF_UART1_RXD,
@@ -231,10 +231,6 @@
 	.exit = mxt_td60_sdhc1_exit,
 };
 
-static struct platform_device *platform_devices[] __initdata = {
-	&mxc_fec_device,
-};
-
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
@@ -255,12 +251,11 @@
 	i2c_register_board_info(1, mxt_td60_i2c2_devices,
 				ARRAY_SIZE(mxt_td60_i2c2_devices));
 
-	imx27_add_i2c_imx0(&mxt_td60_i2c0_data);
-	imx27_add_i2c_imx1(&mxt_td60_i2c1_data);
+	imx27_add_imx_i2c(0, &mxt_td60_i2c0_data);
+	imx27_add_imx_i2c(1, &mxt_td60_i2c1_data);
 	mxc_register_device(&mxc_fb_device, &mxt_td60_fb_data);
 	mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
-
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	imx27_add_fec(NULL);
 }
 
 static void __init mxt_td60_timer_init(void)
@@ -274,8 +269,6 @@
 
 MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
 	/* maintainer: Maxtrack Industrial */
-	.phys_io	= MX27_AIPI_BASE_ADDR,
-	.io_pg_offst	= ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params	= MX27_PHYS_OFFSET + 0x100,
 	.map_io		= mx27_map_io,
 	.init_irq	= mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index 23c9e1f..8c720d4 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -38,7 +38,6 @@
 #include <mach/iomux-mx27.h>
 #include <asm/mach/time.h>
 #include <mach/audmux.h>
-#include <mach/ssi.h>
 #include <mach/mxc_nand.h>
 #include <mach/irqs.h>
 #include <mach/mmc.h>
@@ -55,7 +54,7 @@
 #define SPI1_SS1 (GPIO_PORTD + 27)
 #define SD2_CD (GPIO_PORTC + 29)
 
-static int pca100_pins[] = {
+static const int pca100_pins[] __initconst = {
 	/* UART1 */
 	PE12_PF_UART1_TXD,
 	PE13_PF_UART1_RXD,
@@ -174,7 +173,6 @@
 
 static struct platform_device *platform_devices[] __initdata = {
 	&mxc_w1_master_device,
-	&mxc_fec_device,
 	&mxc_wdt,
 };
 
@@ -193,11 +191,9 @@
 		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
 		.platform_data = &board_eeprom,
 	}, {
-		I2C_BOARD_INFO("rtc-pcf8563", 0x51),
-		.type = "pcf8563"
+		I2C_BOARD_INFO("pcf8563", 0x51),
 	}, {
 		I2C_BOARD_INFO("lm75", 0x4a),
-		.type = "lm75"
 	}
 };
 
@@ -252,7 +248,7 @@
 	msleep(2);
 }
 
-static struct imx_ssi_platform_data pca100_ssi_pdata = {
+static const struct imx_ssi_platform_data pca100_ssi_pdata __initconst = {
 	.ac97_reset		= pca100_ac97_cold_reset,
 	.ac97_warm_reset	= pca100_ac97_warm_reset,
 	.flags			= IMX_SSI_USE_AC97,
@@ -389,7 +385,7 @@
 	if (ret)
 		printk(KERN_ERR "pca100: Failed to setup pins (%d)\n", ret);
 
-	mxc_register_device(&imx_ssi_device0, &pca100_ssi_pdata);
+	imx27_add_imx_ssi(0, &pca100_ssi_pdata);
 
 	imx27_add_imx_uart0(&uart_pdata);
 
@@ -401,7 +397,7 @@
 	i2c_register_board_info(1, pca100_i2c_devices,
 				ARRAY_SIZE(pca100_i2c_devices));
 
-	imx27_add_i2c_imx1(&pca100_i2c1_data);
+	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);
@@ -436,6 +432,7 @@
 
 	mxc_register_device(&mxc_fb_device, &pca100_fb_data);
 
+	imx27_add_fec(NULL);
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 }
 
@@ -449,8 +446,6 @@
 };
 
 MACHINE_START(PCA100, "phyCARD-i.MX27")
-	.phys_io        = MX27_AIPI_BASE_ADDR,
-	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX27_PHYS_OFFSET + 0x100,
 	.map_io         = mx27_map_io,
 	.init_irq       = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 9212e8f..49a97ce 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -43,7 +43,7 @@
 #include "devices-imx27.h"
 #include "devices.h"
 
-static int pcm038_pins[] = {
+static const int pcm038_pins[] __initconst = {
 	/* UART1 */
 	PE12_PF_UART1_TXD,
 	PE13_PF_UART1_RXD,
@@ -173,7 +173,6 @@
 static struct platform_device *platform_devices[] __initdata = {
 	&pcm038_nor_mtd_device,
 	&mxc_w1_master_device,
-	&mxc_fec_device,
 	&pcm038_sram_mtd_device,
 	&mxc_wdt,
 };
@@ -257,7 +256,7 @@
 	.consumer_supplies = cam_consumers,
 };
 
-struct mc13783_regulator_init_data pcm038_regulators[] = {
+static struct mc13783_regulator_init_data pcm038_regulators[] = {
 	{
 		.id = MC13783_REGU_VCAM,
 		.init_data = &cam_data,
@@ -309,7 +308,7 @@
 	i2c_register_board_info(1, pcm038_i2c_devices,
 				ARRAY_SIZE(pcm038_i2c_devices));
 
-	imx27_add_i2c_imx1(&pcm038_i2c1_data);
+	imx27_add_imx_i2c(1, &pcm038_i2c1_data);
 
 	/* PE18 for user-LED D40 */
 	mxc_gpio_mode(GPIO_PORTE | 18 | GPIO_GPIO | GPIO_OUT);
@@ -325,6 +324,7 @@
 
 	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 
+	imx27_add_fec(NULL);
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
 #ifdef CONFIG_MACH_PCM970_BASEBOARD
@@ -342,8 +342,6 @@
 };
 
 MACHINE_START(PCM038, "phyCORE-i.MX27")
-	.phys_io        = MX27_AIPI_BASE_ADDR,
-	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX27_PHYS_OFFSET + 0x100,
 	.map_io         = mx27_map_io,
 	.init_irq       = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c
index 88bf0d1..1fbdd3f 100644
--- a/arch/arm/mach-imx/mach-scb9328.c
+++ b/arch/arm/mach-imx/mach-scb9328.c
@@ -95,7 +95,7 @@
 	}
 };
 
-static int mxc_uart1_pins[] = {
+static const int mxc_uart1_pins[] = {
 	PC9_PF_UART1_CTS,
 	PC10_PF_UART1_RTS,
 	PC11_PF_UART1_TXD,
@@ -147,8 +147,6 @@
 
 MACHINE_START(SCB9328, "Synertronixx scb9328")
     /* Sascha Hauer */
-	.phys_io	= 0x00200000,
-	.io_pg_offst	= ((0xe0200000) >> 18) & 0xfffc,
 	.boot_params	= 0x08000100,
 	.map_io		= mx1_map_io,
 	.init_irq	= mx1_init_irq,
diff --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c
index f490a40..9110d9c 100644
--- a/arch/arm/mach-imx/pcm970-baseboard.c
+++ b/arch/arm/mach-imx/pcm970-baseboard.c
@@ -31,7 +31,7 @@
 
 #include "devices.h"
 
-static int pcm970_pins[] = {
+static const int pcm970_pins[] __initconst = {
 	/* SDHC */
 	PB4_PF_SD2_D0,
 	PB5_PF_SD2_D1,
@@ -200,7 +200,7 @@
 	},
 };
 
-struct sja1000_platform_data pcm970_sja1000_platform_data = {
+static struct sja1000_platform_data pcm970_sja1000_platform_data = {
 	.osc_freq	= 16000000,
 	.ocr		= OCR_TX1_PULLDOWN | OCR_TX0_PUSHPULL,
 	.cdr		= CDR_CBP,
diff --git a/arch/arm/mach-integrator/include/mach/debug-macro.S b/arch/arm/mach-integrator/include/mach/debug-macro.S
index 87a6888..a1f598f 100644
--- a/arch/arm/mach-integrator/include/mach/debug-macro.S
+++ b/arch/arm/mach-integrator/include/mach/debug-macro.S
@@ -11,12 +11,10 @@
  *
 */
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x16000000	@ physical base address
-		movne	\rx, #0xf0000000	@ virtual base
-		addne	\rx, \rx, #0x16000000 >> 4
+		.macro	addruart, rp, rv
+		mov	\rp, #0x16000000	@ physical base address
+		mov	\rv, #0xf0000000	@ virtual base
+		add	\rv, \rv, #0x16000000 >> 4
 		.endm
 
 #include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-integrator/include/mach/vmalloc.h b/arch/arm/mach-integrator/include/mach/vmalloc.h
index e87ab0b..e056e7c 100644
--- a/arch/arm/mach-integrator/include/mach/vmalloc.h
+++ b/arch/arm/mach-integrator/include/mach/vmalloc.h
@@ -17,4 +17,4 @@
  * 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       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 6ab5a03..548208f 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -500,8 +500,6 @@
 
 MACHINE_START(INTEGRATOR, "ARM-Integrator")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.phys_io	= 0x16000000,
-	.io_pg_offst	= ((0xf1600000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= ap_map_io,
 	.reserve	= integrator_reserve,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 05db40e..6258c90 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -599,8 +599,6 @@
 
 MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.phys_io	= 0x16000000,
-	.io_pg_offst	= ((0xf1600000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= intcp_map_io,
 	.reserve	= integrator_reserve,
diff --git a/arch/arm/mach-iop13xx/include/mach/debug-macro.S b/arch/arm/mach-iop13xx/include/mach/debug-macro.S
index c9d6ba4..e664466 100644
--- a/arch/arm/mach-iop13xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-iop13xx/include/mach/debug-macro.S
@@ -11,15 +11,13 @@
  * published by the Free Software Foundation.
  */
 
-	.macro	addruart, rx, tmp
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1			@ mmu enabled?
-	moveq	\rx, #0xff000000	@ physical
-	orreq	\rx, \rx, #0x00d80000
-	movne	\rx, #0xfe000000	@ virtual
-	orrne	\rx, \rx, #0x00e80000
-	orr	\rx, \rx, #0x00002300
-	orr	\rx, \rx, #0x00000040
+	.macro	addruart, rp, rv
+	mov	\rp, #0x00002300
+	orr	\rp, \rp, #0x00000040
+	orr	\rv, \rp, #0xfe000000	@ virtual
+	orr	\rv, \rv, #0x00e80000
+	orr	\rp, \rp, #0xff000000	@ physical
+	orr	\rp, \rp, #0x00d80000
 	.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c
index f91f315..9b5a63f 100644
--- a/arch/arm/mach-iop13xx/iq81340mc.c
+++ b/arch/arm/mach-iop13xx/iq81340mc.c
@@ -91,8 +91,6 @@
 
 MACHINE_START(IQ81340MC, "Intel IQ81340MC")
 	/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
-	.phys_io        = IOP13XX_PMMR_PHYS_MEM_BASE,
-	.io_pg_offst    = (IOP13XX_PMMR_VIRT_MEM_BASE >> 18) & 0xfffc,
 	.boot_params    = 0x00000100,
 	.map_io         = iop13xx_map_io,
 	.init_irq       = iop13xx_init_irq,
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c
index ddb7a34..df3492a 100644
--- a/arch/arm/mach-iop13xx/iq81340sc.c
+++ b/arch/arm/mach-iop13xx/iq81340sc.c
@@ -93,8 +93,6 @@
 
 MACHINE_START(IQ81340SC, "Intel IQ81340SC")
 	/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
-	.phys_io	= IOP13XX_PMMR_PHYS_MEM_BASE,
-	.io_pg_offst	= (IOP13XX_PMMR_VIRT_MEM_BASE >> 18) & 0xfffc,
 	.boot_params    = 0x00000100,
 	.map_io         = iop13xx_map_io,
 	.init_irq       = iop13xx_init_irq,
diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c
index f34b0ed..7149fcc 100644
--- a/arch/arm/mach-iop13xx/msi.c
+++ b/arch/arm/mach-iop13xx/msi.c
@@ -164,10 +164,10 @@
 static struct irq_chip iop13xx_msi_chip = {
 	.name = "PCI-MSI",
 	.ack = iop13xx_msi_nop,
-	.enable = unmask_msi_irq,
-	.disable = mask_msi_irq,
-	.mask = mask_msi_irq,
-	.unmask = unmask_msi_irq,
+	.irq_enable = unmask_msi_irq,
+	.irq_disable = mask_msi_irq,
+	.irq_mask = mask_msi_irq,
+	.irq_unmask = unmask_msi_irq,
 };
 
 int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
index 2bef9b6..779f924 100644
--- a/arch/arm/mach-iop32x/em7210.c
+++ b/arch/arm/mach-iop32x/em7210.c
@@ -203,8 +203,6 @@
 }
 
 MACHINE_START(EM7210, "Lanner EM7210")
-	.phys_io	= IQ31244_UART,
-	.io_pg_offst	= ((IQ31244_UART) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= em7210_map_io,
 	.init_irq	= iop32x_init_irq,
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index 10384fc..c6b6f9c 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -207,8 +207,6 @@
 
 MACHINE_START(GLANTANK, "GLAN Tank")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= GLANTANK_UART,
-	.io_pg_offst	= ((GLANTANK_UART) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= glantank_map_io,
 	.init_irq	= iop32x_init_irq,
diff --git a/arch/arm/mach-iop32x/include/mach/debug-macro.S b/arch/arm/mach-iop32x/include/mach/debug-macro.S
index 736afe1..ff9e76c 100644
--- a/arch/arm/mach-iop32x/include/mach/debug-macro.S
+++ b/arch/arm/mach-iop32x/include/mach/debug-macro.S
@@ -11,9 +11,10 @@
  * published by the Free Software Foundation.
  */
 
-		.macro	addruart, rx, tmp
-		mov	\rx, #0xfe000000	@ physical as well as virtual
-		orr	\rx, \rx, #0x00800000	@ location of the UART
+		.macro	addruart, rp, rv
+		mov	\rp, #0xfe000000	@ physical as well as virtual
+		orr	\rp, \rp, #0x00800000	@ location of the UART
+		mov	\rv, \rp
 		.endm
 
 #define UART_SHIFT	0
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index d6ac85f..fde962c 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -313,8 +313,6 @@
 
 MACHINE_START(IQ31244, "Intel IQ31244")
 	/* Maintainer: Intel Corp. */
-	.phys_io	= IQ31244_UART,
-	.io_pg_offst	= ((IQ31244_UART) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= iq31244_map_io,
 	.init_irq	= iop32x_init_irq,
@@ -329,8 +327,6 @@
  */
 MACHINE_START(EP80219, "Intel EP80219")
 	/* Maintainer: Intel Corp. */
-	.phys_io	= IQ31244_UART,
-	.io_pg_offst	= ((IQ31244_UART) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= iq31244_map_io,
 	.init_irq	= iop32x_init_irq,
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index c6a0e4e..3a95950 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -186,8 +186,6 @@
 
 MACHINE_START(IQ80321, "Intel IQ80321")
 	/* Maintainer: Intel Corp. */
-	.phys_io	= IQ80321_UART,
-	.io_pg_offst	= ((IQ80321_UART) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= iq80321_map_io,
 	.init_irq	= iop32x_init_irq,
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index f108a31..626aa37 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -327,8 +327,6 @@
 
 MACHINE_START(N2100, "Thecus N2100")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= N2100_UART,
-	.io_pg_offst	= ((N2100_UART) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= n2100_map_io,
 	.init_irq	= iop32x_init_irq,
diff --git a/arch/arm/mach-iop33x/include/mach/debug-macro.S b/arch/arm/mach-iop33x/include/mach/debug-macro.S
index addb2da..40c500d 100644
--- a/arch/arm/mach-iop33x/include/mach/debug-macro.S
+++ b/arch/arm/mach-iop33x/include/mach/debug-macro.S
@@ -11,13 +11,11 @@
  * published by the Free Software Foundation.
  */
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ mmu enabled?
-		moveq	\rx, #0xff000000	@ physical
-		movne	\rx, #0xfe000000	@ virtual
-		orr	\rx, \rx, #0x00ff0000
-		orr	\rx, \rx, #0x0000f700
+		.macro	addruart, rp, rv
+		mov	\rp, #0x00ff0000
+		orr	\rp, \rp, #0x0000f700
+		orr	\rv, #0xfe000000	@ virtual
+		orr	\rp, #0xff000000	@ physical
 		.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
index c6ff552..c565f8d 100644
--- a/arch/arm/mach-iop33x/iq80331.c
+++ b/arch/arm/mach-iop33x/iq80331.c
@@ -141,8 +141,6 @@
 
 MACHINE_START(IQ80331, "Intel IQ80331")
 	/* Maintainer: Intel Corp. */
-	.phys_io	= 0xfefff000,
-	.io_pg_offst	= ((0xfffff000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= iop3xx_map_io,
 	.init_irq	= iop33x_init_irq,
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
index fbf55140..36a9efb 100644
--- a/arch/arm/mach-iop33x/iq80332.c
+++ b/arch/arm/mach-iop33x/iq80332.c
@@ -141,8 +141,6 @@
 
 MACHINE_START(IQ80332, "Intel IQ80332")
 	/* Maintainer: Intel Corp. */
-	.phys_io	= 0xfefff000,
-	.io_pg_offst	= ((0xfffff000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= iop3xx_map_io,
 	.init_irq	= iop33x_init_irq,
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
index 1a557e0..88663ab 100644
--- a/arch/arm/mach-ixp2000/enp2611.c
+++ b/arch/arm/mach-ixp2000/enp2611.c
@@ -253,8 +253,6 @@
 
 MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= IXP2000_UART_PHYS_BASE,
-	.io_pg_offst	= ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= enp2611_map_io,
 	.init_irq	= ixp2000_init_irq,
diff --git a/arch/arm/mach-ixp2000/include/mach/debug-macro.S b/arch/arm/mach-ixp2000/include/mach/debug-macro.S
index 6a82768..0ef533b 100644
--- a/arch/arm/mach-ixp2000/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp2000/include/mach/debug-macro.S
@@ -11,16 +11,14 @@
  *
 */
 
-		.macro  addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0xc0000000	@ Physical base
-		movne	\rx, #0xfe000000	@ virtual base
-		orrne	\rx, \rx, #0x00f00000
-		orr	\rx, \rx, #0x00030000
+		.macro  addruart, rp, rv
+		mov	\rp, #0x00030000
 #ifdef	__ARMEB__
-		orr	\rx, \rx, #0x00000003
+		orr	\rp, \rp, #0x00000003
 #endif
+		orr	\rv, \rp, #0xfe000000	@ virtual base
+		orr	\rv, \rv, #0x00f00000
+		orr	\rp, \rp, #0xc0000000	@ Physical base
 		.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
index 55e5c69..dfffc1e 100644
--- a/arch/arm/mach-ixp2000/ixdp2400.c
+++ b/arch/arm/mach-ixp2000/ixdp2400.c
@@ -170,8 +170,6 @@
 
 MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP2000_UART_PHYS_BASE,
-	.io_pg_offst	= ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= ixdp2x00_map_io,
 	.init_irq	= ixdp2400_init_irq,
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
index 237b61a..cd4c9bc 100644
--- a/arch/arm/mach-ixp2000/ixdp2800.c
+++ b/arch/arm/mach-ixp2000/ixdp2800.c
@@ -285,8 +285,6 @@
 
 MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP2000_UART_PHYS_BASE,
-	.io_pg_offst	= ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= ixdp2x00_map_io,
 	.init_irq	= ixdp2800_init_irq,
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index 0369ec4..6c121bd 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -416,8 +416,6 @@
 #ifdef CONFIG_ARCH_IXDP2401
 MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP2000_UART_PHYS_BASE,
-	.io_pg_offst	= ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= ixdp2x01_map_io,
 	.init_irq	= ixdp2x01_init_irq,
@@ -429,8 +427,6 @@
 #ifdef CONFIG_ARCH_IXDP2801
 MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP2000_UART_PHYS_BASE,
-	.io_pg_offst	= ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= ixdp2x01_map_io,
 	.init_irq	= ixdp2x01_init_irq,
@@ -444,8 +440,6 @@
  */
 MACHINE_START(IXDP28X5, "Intel IXDP2805/2855 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP2000_UART_PHYS_BASE,
-	.io_pg_offst	= ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= ixdp2x01_map_io,
 	.init_irq	= ixdp2x01_init_irq,
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
index 1c06bfc..e25e5fe 100644
--- a/arch/arm/mach-ixp23xx/espresso.c
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -85,8 +85,6 @@
 
 MACHINE_START(ESPRESSO, "IP Fabrics Double Espresso")
 	/* Maintainer: Lennert Buytenhek */
-	.phys_io	= IXP23XX_PERIPHERAL_PHYS,
-	.io_pg_offst	= ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
 	.map_io		= ixp23xx_map_io,
 	.init_irq	= ixp23xx_init_irq,
 	.timer		= &ixp23xx_timer,
diff --git a/arch/arm/mach-ixp23xx/include/mach/debug-macro.S b/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
index a82e3754..f7c6eef 100644
--- a/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
@@ -12,13 +12,12 @@
  */
 #include <mach/ixp23xx.h>
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1				@ mmu enabled?
-		ldreq	\rx, =IXP23XX_PERIPHERAL_PHYS 	@ physical
-		ldrne	\rx, =IXP23XX_PERIPHERAL_VIRT	@ virtual
+		.macro	addruart, rp, rv
+		ldr	\rp, =IXP23XX_PERIPHERAL_PHYS 	@ physical
+		ldr	\rv, =IXP23XX_PERIPHERAL_VIRT	@ virtual
 #ifdef __ARMEB__
-		orr	\rx, \rx, #0x00000003
+		orr	\rp, \rp, #0x00000003
+		orr	\rv, \rv, #0x00000003
 #endif
 		.endm
 
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
index f1b124a..664e39c 100644
--- a/arch/arm/mach-ixp23xx/ixdp2351.c
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -328,8 +328,6 @@
 
 MACHINE_START(IXDP2351, "Intel IXDP2351 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP23XX_PERIPHERAL_PHYS,
-	.io_pg_offst	= ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
 	.map_io		= ixdp2351_map_io,
 	.init_irq	= ixdp2351_init_irq,
 	.timer		= &ixp23xx_timer,
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c
index 6d38d76..76c61ba 100644
--- a/arch/arm/mach-ixp23xx/roadrunner.c
+++ b/arch/arm/mach-ixp23xx/roadrunner.c
@@ -171,8 +171,6 @@
 
 MACHINE_START(ROADRUNNER, "ADI Engineering RoadRunner Development Platform")
 	/* Maintainer: Deepak Saxena */
-	.phys_io	= IXP23XX_PERIPHERAL_PHYS,
-	.io_pg_offst	= ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
 	.map_io		= ixp23xx_map_io,
 	.init_irq	= ixp23xx_init_irq,
 	.timer		= &ixp23xx_timer,
diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
index d8bc86d..73745ff 100644
--- a/arch/arm/mach-ixp4xx/avila-setup.c
+++ b/arch/arm/mach-ixp4xx/avila-setup.c
@@ -164,8 +164,6 @@
 
 MACHINE_START(AVILA, "Gateworks Avila Network Platform")
 	/* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
@@ -181,8 +179,6 @@
 #ifdef CONFIG_MACH_LOFT
 MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
 	/* Maintainer: Tom Billman <kernel@giantshoulderinc.com> */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 31a47f6..355e3de 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -109,8 +109,6 @@
 #ifdef CONFIG_ARCH_ADI_COYOTE
 MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
@@ -126,8 +124,6 @@
 #ifdef CONFIG_MACH_IXDPG425
 MACHINE_START(IXDPG425, "Intel IXDPG425")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 7c1fa54..d398229 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -279,8 +279,6 @@
 
 MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
 	/* Maintainer: www.nslu2-linux.org */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c
index e7f4bef..727ee39 100644
--- a/arch/arm/mach-ixp4xx/fsg-setup.c
+++ b/arch/arm/mach-ixp4xx/fsg-setup.c
@@ -270,8 +270,6 @@
 
 MACHINE_START(FSG, "Freecom FSG-3")
 	/* Maintainer: www.nslu2-linux.org */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
index 2583b2a..9dc0b4e 100644
--- a/arch/arm/mach-ixp4xx/gateway7001-setup.c
+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c
@@ -96,8 +96,6 @@
 #ifdef CONFIG_MACH_GATEWAY7001
 MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
 	/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c
index 1c28048..d0e4861 100644
--- a/arch/arm/mach-ixp4xx/goramo_mlr.c
+++ b/arch/arm/mach-ixp4xx/goramo_mlr.c
@@ -496,8 +496,6 @@
 
 MACHINE_START(GORAMO_MLR, "MultiLink")
 	/* Maintainer: Krzysztof Halasa */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index c67586b..77abead 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -164,8 +164,6 @@
 
 MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
 	/* Maintainer: George Joseph */
-	.phys_io	= IXP4XX_UART2_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
index 3fc66d6..b974a49 100644
--- a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
@@ -10,16 +10,16 @@
  * published by the Free Software Foundation.
 */
 
-                .macro  addruart, rx, tmp
-                mrc     p15, 0, \rx, c1, c0
-                tst     \rx, #1                 @ MMU enabled?
-                moveq   \rx, #0xc8000000
-                movne   \rx, #0xff000000
-		orrne	\rx, \rx, #0x00b00000
+                .macro  addruart, rp, rv
 #ifdef __ARMEB__
-                add     \rx,\rx,#3              @ Uart regs are at off set of 3 if
-						@ byte writes used - Big Endian.
+                mov     \rp, #3         @ Uart regs are at off set of 3 if
+					@ byte writes used - Big Endian.
+#else
+		mov	\rp, #0
 #endif
+                orr     \rv, \rp, #0xff000000	@ virtual
+		orr	\rv, \rv, #0x00b00000
+                orr     \rp, \rp, #0xc8000000	@ physical
                 .endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index ea9ee4e..1407833 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -257,8 +257,6 @@
 #ifdef CONFIG_ARCH_IXDP425
 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
@@ -270,8 +268,6 @@
 #ifdef CONFIG_MACH_IXDP465
 MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
@@ -283,8 +279,6 @@
 #ifdef CONFIG_ARCH_PRPMC1100
 MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
@@ -296,8 +290,6 @@
 #ifdef CONFIG_MACH_KIXRP435
 MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index e3ee880..f18fee7 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -314,8 +314,6 @@
 
 MACHINE_START(NAS100D, "Iomega NAS 100d")
 	/* Maintainer: www.nslu2-linux.org */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index c14e003..f79b62e 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -300,8 +300,6 @@
 
 MACHINE_START(NSLU2, "Linksys NSLU2")
 	/* Maintainer: www.nslu2-linux.org */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
diff --git a/arch/arm/mach-ixp4xx/vulcan-setup.c b/arch/arm/mach-ixp4xx/vulcan-setup.c
index 465cc5c..4e72cfd 100644
--- a/arch/arm/mach-ixp4xx/vulcan-setup.c
+++ b/arch/arm/mach-ixp4xx/vulcan-setup.c
@@ -236,8 +236,6 @@
 
 MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
 	/* Maintainer: Marc Zyngier <maz@misterjones.org> */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
index 4dd7486..5d148c7 100644
--- a/arch/arm/mach-ixp4xx/wg302v2-setup.c
+++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c
@@ -97,8 +97,6 @@
 #ifdef CONFIG_MACH_WG302V2
 MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
 	/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
-	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
-	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
 	.map_io		= ixp4xx_map_io,
 	.init_irq	= ixp4xx_init_irq,
 	.timer		= &ixp4xx_timer,
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index cc25501..3410633 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -58,6 +58,12 @@
 	  QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS
 	  devices.
 
+config MACH_DOCKSTAR
+	bool "Seagate FreeAgent DockStar"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Seagate FreeAgent DockStar.
+
 config MACH_OPENRD
         bool
 
@@ -100,6 +106,12 @@
 	  Say 'Y' here if you want your kernel to support the
 	  LaCie Network Space Max v2 NAS.
 
+config MACH_D2NET_V2
+	bool "LaCie d2 Network v2 NAS Board"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  LaCie d2 Network v2 NAS.
+
 config MACH_NET2BIG_V2
 	bool "LaCie 2Big Network v2 NAS Board"
 	help
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index 295d7ba..5dcaa81 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -7,14 +7,16 @@
 obj-$(CONFIG_MACH_SHEEVAPLUG)		+= sheevaplug-setup.o
 obj-$(CONFIG_MACH_ESATA_SHEEVAPLUG)	+= sheevaplug-setup.o
 obj-$(CONFIG_MACH_GURUPLUG)		+= guruplug-setup.o
+obj-$(CONFIG_MACH_DOCKSTAR)		+= dockstar-setup.o
 obj-$(CONFIG_MACH_TS219)		+= ts219-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_TS41X)		+= ts41x-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_OPENRD)		+= openrd-setup.o
-obj-$(CONFIG_MACH_NETSPACE_V2)		+= netspace_v2-setup.o
-obj-$(CONFIG_MACH_INETSPACE_V2)		+= netspace_v2-setup.o
-obj-$(CONFIG_MACH_NETSPACE_MAX_V2)	+= netspace_v2-setup.o
-obj-$(CONFIG_MACH_NET2BIG_V2)		+= netxbig_v2-setup.o
-obj-$(CONFIG_MACH_NET5BIG_V2)		+= netxbig_v2-setup.o
+obj-$(CONFIG_MACH_NETSPACE_V2)		+= netspace_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_INETSPACE_V2)		+= netspace_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_NETSPACE_MAX_V2)	+= netspace_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_D2NET_V2)		+= d2net_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_NET2BIG_V2)		+= netxbig_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_NET5BIG_V2)		+= netxbig_v2-setup.o lacie_v2-common.o
 obj-$(CONFIG_MACH_T5325)		+= t5325-setup.o
 
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
diff --git a/arch/arm/mach-kirkwood/d2net_v2-setup.c b/arch/arm/mach-kirkwood/d2net_v2-setup.c
new file mode 100644
index 0000000..4aa86e4
--- /dev/null
+++ b/arch/arm/mach-kirkwood/d2net_v2-setup.c
@@ -0,0 +1,229 @@
+/*
+ * arch/arm/mach-kirkwood/d2net_v2-setup.c
+ *
+ * LaCie d2 Network Space v2 Board Setup
+ *
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <mach/leds-ns2.h>
+#include "common.h"
+#include "mpp.h"
+#include "lacie_v2-common.h"
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+
+static struct mv643xx_eth_platform_data d2net_v2_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
+};
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+
+static struct mv_sata_platform_data d2net_v2_sata_data = {
+	.n_ports	= 2,
+};
+
+/*****************************************************************************
+ * GPIO keys
+ ****************************************************************************/
+
+#define D2NET_V2_GPIO_PUSH_BUTTON          34
+#define D2NET_V2_GPIO_POWER_SWITCH_ON      13
+#define D2NET_V2_GPIO_POWER_SWITCH_OFF     15
+
+#define D2NET_V2_SWITCH_POWER_ON           0x1
+#define D2NET_V2_SWITCH_POWER_OFF          0x2
+
+static struct gpio_keys_button d2net_v2_buttons[] = {
+	[0] = {
+		.type           = EV_SW,
+		.code           = D2NET_V2_SWITCH_POWER_ON,
+		.gpio           = D2NET_V2_GPIO_POWER_SWITCH_ON,
+		.desc           = "Back power switch (on|auto)",
+		.active_low     = 0,
+	},
+	[1] = {
+		.type           = EV_SW,
+		.code           = D2NET_V2_SWITCH_POWER_OFF,
+		.gpio           = D2NET_V2_GPIO_POWER_SWITCH_OFF,
+		.desc           = "Back power switch (auto|off)",
+		.active_low     = 0,
+	},
+	[2] = {
+		.code           = KEY_POWER,
+		.gpio           = D2NET_V2_GPIO_PUSH_BUTTON,
+		.desc           = "Front Push Button",
+		.active_low     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data d2net_v2_button_data = {
+	.buttons	= d2net_v2_buttons,
+	.nbuttons	= ARRAY_SIZE(d2net_v2_buttons),
+};
+
+static struct platform_device d2net_v2_gpio_buttons = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &d2net_v2_button_data,
+	},
+};
+
+/*****************************************************************************
+ * GPIO LEDs
+ ****************************************************************************/
+
+#define D2NET_V2_GPIO_RED_LED		12
+
+static struct gpio_led d2net_v2_gpio_led_pins[] = {
+	{
+		.name	= "d2net_v2:red:fail",
+		.gpio	= D2NET_V2_GPIO_RED_LED,
+	},
+};
+
+static struct gpio_led_platform_data d2net_v2_gpio_leds_data = {
+	.num_leds	= ARRAY_SIZE(d2net_v2_gpio_led_pins),
+	.leds		= d2net_v2_gpio_led_pins,
+};
+
+static struct platform_device d2net_v2_gpio_leds = {
+	.name		= "leds-gpio",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &d2net_v2_gpio_leds_data,
+	},
+};
+
+/*****************************************************************************
+ * Dual-GPIO CPLD LEDs
+ ****************************************************************************/
+
+#define D2NET_V2_GPIO_BLUE_LED_SLOW	29
+#define D2NET_V2_GPIO_BLUE_LED_CMD	30
+
+static struct ns2_led d2net_v2_led_pins[] = {
+	{
+		.name	= "d2net_v2:blue:sata",
+		.cmd	= D2NET_V2_GPIO_BLUE_LED_CMD,
+		.slow	= D2NET_V2_GPIO_BLUE_LED_SLOW,
+	},
+};
+
+static struct ns2_led_platform_data d2net_v2_leds_data = {
+	.num_leds	= ARRAY_SIZE(d2net_v2_led_pins),
+	.leds		= d2net_v2_led_pins,
+};
+
+static struct platform_device d2net_v2_leds = {
+	.name		= "leds-ns2",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &d2net_v2_leds_data,
+	},
+};
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+
+static unsigned int d2net_v2_mpp_config[] __initdata = {
+	MPP0_SPI_SCn,
+	MPP1_SPI_MOSI,
+	MPP2_SPI_SCK,
+	MPP3_SPI_MISO,
+	MPP6_SYSRST_OUTn,
+	MPP7_GPO,		/* Request power-off */
+	MPP8_TW0_SDA,
+	MPP9_TW0_SCK,
+	MPP10_UART0_TXD,
+	MPP11_UART0_RXD,
+	MPP12_GPO,		/* Red led */
+	MPP13_GPIO,		/* Rear power switch (on|auto) */
+	MPP14_GPIO,		/* USB fuse */
+	MPP15_GPIO,		/* Rear power switch (auto|off) */
+	MPP16_GPIO,		/* SATA 0 power */
+	MPP21_SATA0_ACTn,
+	MPP24_GPIO,		/* USB mode select */
+	MPP26_GPIO,		/* USB device vbus */
+	MPP28_GPIO,		/* USB enable host vbus */
+	MPP29_GPIO,		/* Blue led (slow register) */
+	MPP30_GPIO,		/* Blue led (command register) */
+	MPP34_GPIO,		/* Power button (1 = Released, 0 = Pushed) */
+	MPP35_GPIO,		/* Inhibit power-off */
+	0
+};
+
+#define D2NET_V2_GPIO_POWER_OFF		7
+
+static void d2net_v2_power_off(void)
+{
+	gpio_set_value(D2NET_V2_GPIO_POWER_OFF, 1);
+}
+
+static void __init d2net_v2_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_init();
+	kirkwood_mpp_conf(d2net_v2_mpp_config);
+
+	lacie_v2_hdd_power_init(1);
+
+	kirkwood_ehci_init();
+	kirkwood_ge00_init(&d2net_v2_ge00_data);
+	kirkwood_sata_init(&d2net_v2_sata_data);
+	kirkwood_uart0_init();
+	lacie_v2_register_flash();
+	lacie_v2_register_i2c_devices();
+
+	platform_device_register(&d2net_v2_leds);
+	platform_device_register(&d2net_v2_gpio_leds);
+	platform_device_register(&d2net_v2_gpio_buttons);
+
+	if (gpio_request(D2NET_V2_GPIO_POWER_OFF, "power-off") == 0 &&
+	    gpio_direction_output(D2NET_V2_GPIO_POWER_OFF, 0) == 0)
+		pm_power_off = d2net_v2_power_off;
+	else
+		pr_err("d2net_v2: failed to configure power-off GPIO\n");
+}
+
+MACHINE_START(D2NET_V2, "LaCie d2 Network v2")
+	.boot_params	= 0x00000100,
+	.init_machine	= d2net_v2_init,
+	.map_io		= kirkwood_map_io,
+	.init_irq	= kirkwood_init_irq,
+	.timer		= &lacie_v2_timer,
+MACHINE_END
diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
index 16f6691..9ea7118 100644
--- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
+++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
@@ -97,8 +97,6 @@
 
 MACHINE_START(DB88F6281_BP, "Marvell DB-88F6281-BP Development Board")
 	/* Maintainer: Saeed Bishara <saeed@marvell.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= db88f6281_init,
 	.map_io		= kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c
new file mode 100644
index 0000000..433ea36
--- /dev/null
+++ b/arch/arm/mach-kirkwood/dockstar-setup.c
@@ -0,0 +1,110 @@
+/*
+ * arch/arm/mach-kirkwood/dockstar-setup.c
+ *
+ * Seagate FreeAgent DockStar Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition dockstar_nand_parts[] = {
+	{
+		.name = "u-boot",
+		.offset = 0,
+		.size = SZ_1M
+	}, {
+		.name = "uImage",
+		.offset = MTDPART_OFS_NXTBLK,
+		.size = SZ_4M
+	}, {
+		.name = "root",
+		.offset = MTDPART_OFS_NXTBLK,
+		.size = MTDPART_SIZ_FULL
+	},
+};
+
+static struct mv643xx_eth_platform_data dockstar_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct gpio_led dockstar_led_pins[] = {
+	{
+		.name			= "dockstar:green:health",
+		.default_trigger	= "default-on",
+		.gpio			= 46,
+		.active_low		= 1,
+	},
+	{
+		.name			= "dockstar:orange:misc",
+		.default_trigger	= "none",
+		.gpio			= 47,
+		.active_low		= 1,
+	},
+};
+
+static struct gpio_led_platform_data dockstar_led_data = {
+	.leds		= dockstar_led_pins,
+	.num_leds	= ARRAY_SIZE(dockstar_led_pins),
+};
+
+static struct platform_device dockstar_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &dockstar_led_data,
+	}
+};
+
+static unsigned int dockstar_mpp_config[] __initdata = {
+	MPP29_GPIO,	/* USB Power Enable */
+	MPP46_GPIO,	/* LED green */
+	MPP47_GPIO,	/* LED orange */
+	0
+};
+
+static void __init dockstar_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_init();
+
+	/* setup gpio pin select */
+	kirkwood_mpp_conf(dockstar_mpp_config);
+
+	kirkwood_uart0_init();
+	kirkwood_nand_init(ARRAY_AND_SIZE(dockstar_nand_parts), 25);
+
+	if (gpio_request(29, "USB Power Enable") != 0 ||
+	    gpio_direction_output(29, 1) != 0)
+		printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n");
+	kirkwood_ehci_init();
+
+	kirkwood_ge00_init(&dockstar_ge00_data);
+
+	platform_device_register(&dockstar_leds);
+}
+
+MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar")
+	.boot_params	= 0x00000100,
+	.init_machine	= dockstar_init,
+	.map_io		= kirkwood_map_io,
+	.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 54d07c8..8f47dc0 100644
--- a/arch/arm/mach-kirkwood/guruplug-setup.c
+++ b/arch/arm/mach-kirkwood/guruplug-setup.c
@@ -121,8 +121,6 @@
 
 MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board")
 	/* Maintainer: Siddarth Gore <gores@marvell.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= guruplug_init,
 	.map_io		= kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/include/mach/debug-macro.S b/arch/arm/mach-kirkwood/include/mach/debug-macro.S
index d060677..db06ae43 100644
--- a/arch/arm/mach-kirkwood/include/mach/debug-macro.S
+++ b/arch/arm/mach-kirkwood/include/mach/debug-macro.S
@@ -8,12 +8,11 @@
 
 #include <mach/bridge-regs.h>
 
-	.macro	addruart, rx, tmp
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1					@ MMU enabled?
-	ldreq	\rx, =KIRKWOOD_REGS_PHYS_BASE
-	ldrne	\rx, =KIRKWOOD_REGS_VIRT_BASE
-	orr	\rx, \rx, #0x00012000
+	.macro	addruart, rp, rv
+	ldr	\rp, =KIRKWOOD_REGS_PHYS_BASE
+	ldr	\rv, =KIRKWOOD_REGS_VIRT_BASE
+	orr	\rp, \rp, #0x00012000
+	orr	\rv, \rv, #0x00012000
 	.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
index 93fc2ec..6e924b3 100644
--- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h
+++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
@@ -38,7 +38,7 @@
 
 #define KIRKWOOD_PCIE1_IO_PHYS_BASE	0xf3000000
 #define KIRKWOOD_PCIE1_IO_VIRT_BASE	0xfef00000
-#define KIRKWOOD_PCIE1_IO_BUS_BASE	0x00000000
+#define KIRKWOOD_PCIE1_IO_BUS_BASE	0x00100000
 #define KIRKWOOD_PCIE1_IO_SIZE		SZ_1M
 
 #define KIRKWOOD_PCIE_IO_PHYS_BASE	0xf2000000
diff --git a/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h b/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
new file mode 100644
index 0000000..24b536e
--- /dev/null
+++ b/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
@@ -0,0 +1,55 @@
+/*
+ * arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
+ *
+ * Platform data structure for netxbig LED driver
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_LEDS_NETXBIG_H
+#define __MACH_LEDS_NETXBIG_H
+
+struct netxbig_gpio_ext {
+	unsigned	*addr;
+	int		num_addr;
+	unsigned	*data;
+	int		num_data;
+	unsigned	enable;
+};
+
+enum netxbig_led_mode {
+	NETXBIG_LED_OFF,
+	NETXBIG_LED_ON,
+	NETXBIG_LED_SATA,
+	NETXBIG_LED_TIMER1,
+	NETXBIG_LED_TIMER2,
+	NETXBIG_LED_MODE_NUM,
+};
+
+#define NETXBIG_LED_INVALID_MODE NETXBIG_LED_MODE_NUM
+
+struct netxbig_led_timer {
+	unsigned long		delay_on;
+	unsigned long		delay_off;
+	enum netxbig_led_mode	mode;
+};
+
+struct netxbig_led {
+	const char	*name;
+	const char	*default_trigger;
+	int		mode_addr;
+	int		*mode_val;
+	int		bright_addr;
+};
+
+struct netxbig_led_platform_data {
+	struct netxbig_gpio_ext	*gpio_ext;
+	struct netxbig_led_timer *timer;
+	int			num_timer;
+	struct netxbig_led	*leds;
+	int			num_leds;
+};
+
+#endif /* __MACH_LEDS_NETXBIG_H */
diff --git a/arch/arm/mach-kirkwood/lacie_v2-common.c b/arch/arm/mach-kirkwood/lacie_v2-common.c
new file mode 100644
index 0000000..d3ea1b6
--- /dev/null
+++ b/arch/arm/mach-kirkwood/lacie_v2-common.c
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/mach-kirkwood/lacie_v2-common.c
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/gpio.h>
+#include <asm/mach/time.h>
+#include <mach/kirkwood.h>
+#include <mach/irqs.h>
+#include <plat/time.h>
+#include "common.h"
+
+/*****************************************************************************
+ * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
+ ****************************************************************************/
+
+static struct mtd_partition lacie_v2_flash_parts[] = {
+	{
+		.name = "u-boot",
+		.size = MTDPART_SIZ_FULL,
+		.offset = 0,
+		.mask_flags = MTD_WRITEABLE, /* force read-only */
+	},
+};
+
+static const struct flash_platform_data lacie_v2_flash = {
+	.type		= "mx25l4005a",
+	.name		= "spi_flash",
+	.parts		= lacie_v2_flash_parts,
+	.nr_parts	= ARRAY_SIZE(lacie_v2_flash_parts),
+};
+
+static struct spi_board_info __initdata lacie_v2_spi_slave_info[] = {
+	{
+		.modalias	= "m25p80",
+		.platform_data	= &lacie_v2_flash,
+		.irq		= -1,
+		.max_speed_hz	= 20000000,
+		.bus_num	= 0,
+		.chip_select	= 0,
+	},
+};
+
+void __init lacie_v2_register_flash(void)
+{
+	spi_register_board_info(lacie_v2_spi_slave_info,
+				ARRAY_SIZE(lacie_v2_spi_slave_info));
+	kirkwood_spi_init();
+}
+
+/*****************************************************************************
+ * I2C devices
+ ****************************************************************************/
+
+static struct at24_platform_data at24c04 = {
+	.byte_len	= SZ_4K / 8,
+	.page_size	= 16,
+};
+
+/*
+ * i2c addr | chip         | description
+ * 0x50     | HT24LC04     | eeprom (512B)
+ */
+
+static struct i2c_board_info __initdata lacie_v2_i2c_info[] = {
+	{
+		I2C_BOARD_INFO("24c04", 0x50),
+		.platform_data  = &at24c04,
+	}
+};
+
+void __init lacie_v2_register_i2c_devices(void)
+{
+	kirkwood_i2c_init();
+	i2c_register_board_info(0, lacie_v2_i2c_info,
+				ARRAY_SIZE(lacie_v2_i2c_info));
+}
+
+/*****************************************************************************
+ * Hard Disk power
+ ****************************************************************************/
+
+static int __initdata lacie_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 };
+
+void __init lacie_v2_hdd_power_init(int hdd_num)
+{
+	int i;
+	int err;
+
+	/* Power up all hard disks. */
+	for (i = 0; i < hdd_num; i++) {
+		err = gpio_request(lacie_v2_gpio_hdd_power[i], NULL);
+		if (err == 0) {
+			err = gpio_direction_output(
+					lacie_v2_gpio_hdd_power[i], 1);
+			/* Free the HDD power GPIOs. This allow user-space to
+			 * configure them via the gpiolib sysfs interface. */
+			gpio_free(lacie_v2_gpio_hdd_power[i]);
+		}
+		if (err)
+			pr_err("Failed to power up HDD%d\n", i + 1);
+	}
+}
+
+/*****************************************************************************
+ * Timer
+ ****************************************************************************/
+
+static void lacie_v2_timer_init(void)
+{
+	kirkwood_tclk = 166666667;
+	orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
+}
+
+struct sys_timer lacie_v2_timer = {
+	.init = lacie_v2_timer_init,
+};
diff --git a/arch/arm/mach-kirkwood/lacie_v2-common.h b/arch/arm/mach-kirkwood/lacie_v2-common.h
new file mode 100644
index 0000000..af52131
--- /dev/null
+++ b/arch/arm/mach-kirkwood/lacie_v2-common.h
@@ -0,0 +1,18 @@
+/*
+ * arch/arm/mach-kirkwood/lacie_v2-common.h
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ARCH_KIRKWOOD_LACIE_V2_COMMON_H
+#define __ARCH_KIRKWOOD_LACIE_V2_COMMON_H
+
+void lacie_v2_register_flash(void);
+void lacie_v2_register_i2c_devices(void);
+void lacie_v2_hdd_power_init(int hdd_num);
+
+extern struct sys_timer lacie_v2_timer;
+
+#endif
diff --git a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
index c6b92b4..1e5266f 100644
--- a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
+++ b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
@@ -163,8 +163,6 @@
 
 MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= mv88f6281gtw_ge_init,
 	.map_io		= kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
index d26bf32..5e28644 100644
--- a/arch/arm/mach-kirkwood/netspace_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -24,56 +24,19 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/i2c.h>
-#include <linux/i2c/at24.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/time.h>
 #include <mach/kirkwood.h>
 #include <mach/leds-ns2.h>
-#include <plat/time.h>
 #include "common.h"
 #include "mpp.h"
-
-/*****************************************************************************
- * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
- ****************************************************************************/
-
-static struct mtd_partition netspace_v2_flash_parts[] = {
-	{
-		.name = "u-boot",
-		.size = MTDPART_SIZ_FULL,
-		.offset = 0,
-		.mask_flags = MTD_WRITEABLE, /* force read-only */
-	},
-};
-
-static const struct flash_platform_data netspace_v2_flash = {
-	.type		= "mx25l4005a",
-	.name		= "spi_flash",
-	.parts		= netspace_v2_flash_parts,
-	.nr_parts	= ARRAY_SIZE(netspace_v2_flash_parts),
-};
-
-static struct spi_board_info __initdata netspace_v2_spi_slave_info[] = {
-	{
-		.modalias	= "m25p80",
-		.platform_data	= &netspace_v2_flash,
-		.irq		= -1,
-		.max_speed_hz	= 20000000,
-		.bus_num	= 0,
-		.chip_select	= 0,
-	},
-};
+#include "lacie_v2-common.h"
 
 /*****************************************************************************
  * Ethernet
@@ -84,27 +47,6 @@
 };
 
 /*****************************************************************************
- * I2C devices
- ****************************************************************************/
-
-static struct at24_platform_data at24c04 = {
-	.byte_len	= SZ_4K / 8,
-	.page_size	= 16,
-};
-
-/*
- * i2c addr | chip         | description
- * 0x50     | HT24LC04     | eeprom (512B)
- */
-
-static struct i2c_board_info __initdata netspace_v2_i2c_info[] = {
-	{
-		I2C_BOARD_INFO("24c04", 0x50),
-		.platform_data  = &at24c04,
-	}
-};
-
-/*****************************************************************************
  * SATA
  ****************************************************************************/
 
@@ -112,35 +54,6 @@
 	.n_ports	= 2,
 };
 
-#define NETSPACE_V2_GPIO_SATA0_POWER	16
-#define NETSPACE_V2_GPIO_SATA1_POWER	17
-
-static void __init netspace_v2_sata_power_init(void)
-{
-	int err;
-
-	err = gpio_request(NETSPACE_V2_GPIO_SATA0_POWER, "SATA0 power");
-	if (err == 0) {
-		err = gpio_direction_output(NETSPACE_V2_GPIO_SATA0_POWER, 1);
-		if (err)
-			gpio_free(NETSPACE_V2_GPIO_SATA0_POWER);
-	}
-	if (err)
-		pr_err("netspace_v2: failed to setup SATA0 power\n");
-
-	if (machine_is_netspace_max_v2()) {
-		err = gpio_request(NETSPACE_V2_GPIO_SATA1_POWER, "SATA1 power");
-		if (err == 0) {
-			err = gpio_direction_output(
-					NETSPACE_V2_GPIO_SATA1_POWER, 1);
-			if (err)
-				gpio_free(NETSPACE_V2_GPIO_SATA1_POWER);
-		}
-		if (err)
-			pr_err("netspace_v2: failed to setup SATA1 power\n");
-	}
-}
-
 /*****************************************************************************
  * GPIO keys
  ****************************************************************************/
@@ -224,20 +137,6 @@
 };
 
 /*****************************************************************************
- * Timer
- ****************************************************************************/
-
-static void netspace_v2_timer_init(void)
-{
-	kirkwood_tclk = 166666667;
-	orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
-}
-
-struct sys_timer netspace_v2_timer = {
-	.init = netspace_v2_timer_init,
-};
-
-/*****************************************************************************
  * General Setup
  ****************************************************************************/
 
@@ -291,18 +190,17 @@
 	kirkwood_init();
 	kirkwood_mpp_conf(netspace_v2_mpp_config);
 
-	netspace_v2_sata_power_init();
+	if (machine_is_netspace_max_v2())
+		lacie_v2_hdd_power_init(2);
+	else
+		lacie_v2_hdd_power_init(1);
 
 	kirkwood_ehci_init();
 	kirkwood_ge00_init(&netspace_v2_ge00_data);
 	kirkwood_sata_init(&netspace_v2_sata_data);
 	kirkwood_uart0_init();
-	spi_register_board_info(netspace_v2_spi_slave_info,
-				ARRAY_SIZE(netspace_v2_spi_slave_info));
-	kirkwood_spi_init();
-	kirkwood_i2c_init();
-	i2c_register_board_info(0, netspace_v2_i2c_info,
-				ARRAY_SIZE(netspace_v2_i2c_info));
+	lacie_v2_register_flash();
+	lacie_v2_register_i2c_devices();
 
 	platform_device_register(&netspace_v2_leds);
 	platform_device_register(&netspace_v2_gpio_leds);
@@ -317,36 +215,30 @@
 
 #ifdef CONFIG_MACH_NETSPACE_V2
 MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &netspace_v2_timer,
+	.timer		= &lacie_v2_timer,
 MACHINE_END
 #endif
 
 #ifdef CONFIG_MACH_INETSPACE_V2
 MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2")
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &netspace_v2_timer,
+	.timer		= &lacie_v2_timer,
 MACHINE_END
 #endif
 
 #ifdef CONFIG_MACH_NETSPACE_MAX_V2
 MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2")
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &netspace_v2_timer,
+	.timer		= &lacie_v2_timer,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-kirkwood/netxbig_v2-setup.c b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
index 2bd14c5..a1b45d5 100644
--- a/arch/arm/mach-kirkwood/netxbig_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
@@ -23,55 +23,19 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/i2c.h>
-#include <linux/i2c/at24.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/time.h>
 #include <mach/kirkwood.h>
-#include <plat/time.h>
+#include <mach/leds-netxbig.h>
 #include "common.h"
 #include "mpp.h"
-
-/*****************************************************************************
- * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
- ****************************************************************************/
-
-static struct mtd_partition netxbig_v2_flash_parts[] = {
-	{
-		.name = "u-boot",
-		.size = MTDPART_SIZ_FULL,
-		.offset = 0,
-		.mask_flags = MTD_WRITEABLE, /* force read-only */
-	},
-};
-
-static const struct flash_platform_data netxbig_v2_flash = {
-	.type		= "mx25l4005a",
-	.name		= "spi_flash",
-	.parts		= netxbig_v2_flash_parts,
-	.nr_parts	= ARRAY_SIZE(netxbig_v2_flash_parts),
-};
-
-static struct spi_board_info __initdata netxbig_v2_spi_slave_info[] = {
-	{
-		.modalias	= "m25p80",
-		.platform_data	= &netxbig_v2_flash,
-		.irq		= -1,
-		.max_speed_hz	= 20000000,
-		.bus_num	= 0,
-		.chip_select	= 0,
-	},
-};
+#include "lacie_v2-common.h"
 
 /*****************************************************************************
  * Ethernet
@@ -86,27 +50,6 @@
 };
 
 /*****************************************************************************
- * I2C devices
- ****************************************************************************/
-
-static struct at24_platform_data at24c04 = {
-	.byte_len	= SZ_4K / 8,
-	.page_size	= 16,
-};
-
-/*
- * i2c addr | chip         | description
- * 0x50     | HT24LC04     | eeprom (512B)
- */
-
-static struct i2c_board_info __initdata netxbig_v2_i2c_info[] = {
-	{
-		I2C_BOARD_INFO("24c04", 0x50),
-		.platform_data  = &at24c04,
-	}
-};
-
-/*****************************************************************************
  * SATA
  ****************************************************************************/
 
@@ -114,34 +57,6 @@
 	.n_ports	= 2,
 };
 
-static int __initdata netxbig_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 };
-
-static void __init netxbig_v2_sata_power_init(void)
-{
-	int i;
-	int err;
-	int hdd_nb;
-
-	if (machine_is_net2big_v2())
-		hdd_nb = 2;
-	else
-		hdd_nb = 5;
-
-	/* Power up all hard disks. */
-	for (i = 0; i < hdd_nb; i++) {
-		err = gpio_request(netxbig_v2_gpio_hdd_power[i], NULL);
-		if (err == 0) {
-			err = gpio_direction_output(
-					netxbig_v2_gpio_hdd_power[i], 1);
-			/* Free the HDD power GPIOs. This allow user-space to
-			 * configure them via the gpiolib sysfs interface. */
-			gpio_free(netxbig_v2_gpio_hdd_power[i]);
-		}
-		if (err)
-			pr_err("netxbig_v2: failed to power up HDD%d\n", i + 1);
-	}
-}
-
 /*****************************************************************************
  * GPIO keys
  ****************************************************************************/
@@ -190,7 +105,7 @@
 };
 
 /*****************************************************************************
- * GPIO LEDs
+ * GPIO extension LEDs
  ****************************************************************************/
 
 /*
@@ -200,19 +115,32 @@
  * - address register : bit [0-2] -> GPIO [47-49]
  * - data register    : bit [0-2] -> GPIO [44-46]
  * - enable register  : GPIO 29
- *
+ */
+
+static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 };
+static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 };
+
+static struct netxbig_gpio_ext netxbig_v2_gpio_ext = {
+	.addr		= netxbig_v2_gpio_ext_addr,
+	.num_addr	= ARRAY_SIZE(netxbig_v2_gpio_ext_addr),
+	.data		= netxbig_v2_gpio_ext_data,
+	.num_data	= ARRAY_SIZE(netxbig_v2_gpio_ext_data),
+	.enable		= 29,
+};
+
+/*
  * Address register selection:
  *
  * addr | register
  * ----------------------------
  *   0  | front LED
  *   1  | front LED brightness
- *   2  | HDD LED brightness
- *   3  | HDD1 LED
- *   4  | HDD2 LED
- *   5  | HDD3 LED
- *   6  | HDD4 LED
- *   7  | HDD5 LED
+ *   2  | SATA LED brightness
+ *   3  | SATA0 LED
+ *   4  | SATA1 LED
+ *   5  | SATA2 LED
+ *   6  | SATA3 LED
+ *   7  | SATA4 LED
  *
  * Data register configuration:
  *
@@ -233,30 +161,107 @@
  *   6  | blink blue on=1 sec and red on=1 sec
  *   7  | blink blue on=0.5 sec and blue off=2.5 sec
  *
- * data | HDD LED mode
+ * data | SATA LED mode
  * -------------------------------------------------
- *   0  | fix blue on
+ *   0  | fix off
  *   1  | SATA activity blink
  *   2  | fix red on
  *   3  | blink blue on=1 sec and blue off=1 sec
  *   4  | blink red on=1 sec and red off=1 sec
  *   5  | blink blue on=2.5 sec and red on=0.5 sec
  *   6  | blink blue on=1 sec and red on=1 sec
- *   7  | blink blue on=0.5 sec and blue off=2.5 sec
+ *   7  | fix blue on
  */
 
-/*****************************************************************************
- * Timer
- ****************************************************************************/
+static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = {
+	[NETXBIG_LED_OFF]	= 0,
+	[NETXBIG_LED_ON]	= 2,
+	[NETXBIG_LED_SATA]	= NETXBIG_LED_INVALID_MODE,
+	[NETXBIG_LED_TIMER1]	= 4,
+	[NETXBIG_LED_TIMER2]	= NETXBIG_LED_INVALID_MODE,
+};
 
-static void netxbig_v2_timer_init(void)
-{
-	kirkwood_tclk = 166666667;
-	orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
-}
+static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = {
+	[NETXBIG_LED_OFF]	= 0,
+	[NETXBIG_LED_ON]	= 1,
+	[NETXBIG_LED_SATA]	= NETXBIG_LED_INVALID_MODE,
+	[NETXBIG_LED_TIMER1]	= 3,
+	[NETXBIG_LED_TIMER2]	= 7,
+};
 
-struct sys_timer netxbig_v2_timer = {
-	.init = netxbig_v2_timer_init,
+static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = {
+	[NETXBIG_LED_OFF]	= 0,
+	[NETXBIG_LED_ON]	= 7,
+	[NETXBIG_LED_SATA]	= 1,
+	[NETXBIG_LED_TIMER1]	= 3,
+	[NETXBIG_LED_TIMER2]	= NETXBIG_LED_INVALID_MODE,
+};
+
+static struct netxbig_led_timer netxbig_v2_led_timer[] = {
+	[0] = {
+		.delay_on	= 500,
+		.delay_off	= 500,
+		.mode		= NETXBIG_LED_TIMER1,
+	},
+	[1] = {
+		.delay_on	= 500,
+		.delay_off	= 1000,
+		.mode		= NETXBIG_LED_TIMER2,
+	},
+};
+
+#define NETXBIG_LED(_name, maddr, mval, baddr)			\
+	{ .name		= _name,				\
+	  .mode_addr	= maddr,				\
+	  .mode_val	= mval,					\
+	  .bright_addr	= baddr }
+
+static struct netxbig_led net2big_v2_leds_ctrl[] = {
+	NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled,  1),
+	NETXBIG_LED("net2big-v2:red:power",  0, netxbig_v2_red_mled,       1),
+	NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net2big-v2:red:sata0",  3, netxbig_v2_red_mled,       2),
+	NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net2big-v2:red:sata1",  4, netxbig_v2_red_mled,       2),
+};
+
+static struct netxbig_led_platform_data net2big_v2_leds_data = {
+	.gpio_ext	= &netxbig_v2_gpio_ext,
+	.timer		= netxbig_v2_led_timer,
+	.num_timer	= ARRAY_SIZE(netxbig_v2_led_timer),
+	.leds		= net2big_v2_leds_ctrl,
+	.num_leds	= ARRAY_SIZE(net2big_v2_leds_ctrl),
+};
+
+static struct netxbig_led net5big_v2_leds_ctrl[] = {
+	NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled,  1),
+	NETXBIG_LED("net5big-v2:red:power",  0, netxbig_v2_red_mled,       1),
+	NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net5big-v2:red:sata0",  3, netxbig_v2_red_mled,       2),
+	NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net5big-v2:red:sata1",  4, netxbig_v2_red_mled,       2),
+	NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net5big-v2:red:sata2",  5, netxbig_v2_red_mled,       2),
+	NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net5big-v2:red:sata3",  6, netxbig_v2_red_mled,       2),
+	NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2),
+	NETXBIG_LED("net5big-v2:red:sata5",  7, netxbig_v2_red_mled,       2),
+};
+
+static struct netxbig_led_platform_data net5big_v2_leds_data = {
+	.gpio_ext	= &netxbig_v2_gpio_ext,
+	.timer		= netxbig_v2_led_timer,
+	.num_timer	= ARRAY_SIZE(netxbig_v2_led_timer),
+	.leds		= net5big_v2_leds_ctrl,
+	.num_leds	= ARRAY_SIZE(net5big_v2_leds_ctrl),
+};
+
+static struct platform_device netxbig_v2_leds = {
+	.name		= "leds-netxbig",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &net2big_v2_leds_data,
+	},
 };
 
 /*****************************************************************************
@@ -284,18 +289,18 @@
 	MPP24_GPIO,		/* USB mode select */
 	MPP26_GPIO,		/* USB device vbus */
 	MPP28_GPIO,		/* USB enable host vbus */
-	MPP29_GPIO,		/* CPLD extension ALE */
+	MPP29_GPIO,		/* GPIO extension ALE */
 	MPP34_GPIO,		/* Rear Push button */
 	MPP35_GPIO,		/* Inhibit switch power-off */
 	MPP36_GPIO,		/* SATA HDD1 presence */
 	MPP37_GPIO,		/* SATA HDD2 presence */
 	MPP40_GPIO,		/* eSATA presence */
-	MPP44_GPIO,		/* CPLD extension (data 0) */
-	MPP45_GPIO,		/* CPLD extension (data 1) */
-	MPP46_GPIO,		/* CPLD extension (data 2) */
-	MPP47_GPIO,		/* CPLD extension (addr 0) */
-	MPP48_GPIO,		/* CPLD extension (addr 1) */
-	MPP49_GPIO,		/* CPLD extension (addr 2) */
+	MPP44_GPIO,		/* GPIO extension (data 0) */
+	MPP45_GPIO,		/* GPIO extension (data 1) */
+	MPP46_GPIO,		/* GPIO extension (data 2) */
+	MPP47_GPIO,		/* GPIO extension (addr 0) */
+	MPP48_GPIO,		/* GPIO extension (addr 1) */
+	MPP49_GPIO,		/* GPIO extension (addr 2) */
 	0
 };
 
@@ -324,7 +329,7 @@
 	MPP26_GE1_RXD2,
 	MPP27_GE1_RXD3,
 	MPP28_GPIO,		/* USB enable host vbus */
-	MPP29_GPIO,		/* CPLD extension ALE */
+	MPP29_GPIO,		/* GPIO extension ALE */
 	MPP30_GE1_RXCTL,
 	MPP31_GE1_RXCLK,
 	MPP32_GE1_TCLKOUT,
@@ -339,12 +344,12 @@
 	MPP41_GPIO,		/* SATA HDD3 power */
 	MPP42_GPIO,		/* SATA HDD4 power */
 	MPP43_GPIO,		/* SATA HDD5 power */
-	MPP44_GPIO,		/* CPLD extension (data 0) */
-	MPP45_GPIO,		/* CPLD extension (data 1) */
-	MPP46_GPIO,		/* CPLD extension (data 2) */
-	MPP47_GPIO,		/* CPLD extension (addr 0) */
-	MPP48_GPIO,		/* CPLD extension (addr 1) */
-	MPP49_GPIO,		/* CPLD extension (addr 2) */
+	MPP44_GPIO,		/* GPIO extension (data 0) */
+	MPP45_GPIO,		/* GPIO extension (data 1) */
+	MPP46_GPIO,		/* GPIO extension (data 2) */
+	MPP47_GPIO,		/* GPIO extension (addr 0) */
+	MPP48_GPIO,		/* GPIO extension (addr 1) */
+	MPP49_GPIO,		/* GPIO extension (addr 2) */
 	0
 };
 
@@ -366,7 +371,10 @@
 	else
 		kirkwood_mpp_conf(net5big_v2_mpp_config);
 
-	netxbig_v2_sata_power_init();
+	if (machine_is_net2big_v2())
+		lacie_v2_hdd_power_init(2);
+	else
+		lacie_v2_hdd_power_init(5);
 
 	kirkwood_ehci_init();
 	kirkwood_ge00_init(&netxbig_v2_ge00_data);
@@ -374,13 +382,12 @@
 		kirkwood_ge01_init(&netxbig_v2_ge01_data);
 	kirkwood_sata_init(&netxbig_v2_sata_data);
 	kirkwood_uart0_init();
-	spi_register_board_info(netxbig_v2_spi_slave_info,
-				ARRAY_SIZE(netxbig_v2_spi_slave_info));
-	kirkwood_spi_init();
-	kirkwood_i2c_init();
-	i2c_register_board_info(0, netxbig_v2_i2c_info,
-				ARRAY_SIZE(netxbig_v2_i2c_info));
+	lacie_v2_register_flash();
+	lacie_v2_register_i2c_devices();
 
+	if (machine_is_net5big_v2())
+		netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data;
+	platform_device_register(&netxbig_v2_leds);
 	platform_device_register(&netxbig_v2_gpio_buttons);
 
 	if (gpio_request(NETXBIG_V2_GPIO_POWER_OFF, "power-off") == 0 &&
@@ -392,24 +399,20 @@
 
 #ifdef CONFIG_MACH_NET2BIG_V2
 MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2")
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= netxbig_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &netxbig_v2_timer,
+	.timer		= &lacie_v2_timer,
 MACHINE_END
 #endif
 
 #ifdef CONFIG_MACH_NET5BIG_V2
 MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2")
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= netxbig_v2_init,
 	.map_io		= kirkwood_map_io,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &netxbig_v2_timer,
+	.timer		= &lacie_v2_timer,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index fd06be6..c9d77fa 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -16,6 +16,7 @@
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/i2c.h>
+#include <linux/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
@@ -57,7 +58,22 @@
 };
 
 static unsigned int openrd_mpp_config[] __initdata = {
+	MPP12_SD_CLK,
+	MPP13_SD_CMD,
+	MPP14_SD_D0,
+	MPP15_SD_D1,
+	MPP16_SD_D2,
+	MPP17_SD_D3,
+	MPP28_GPIO,
 	MPP29_GPIO,
+	MPP34_GPIO,
+	0
+};
+
+/* Configure MPP for UART1 */
+static unsigned int openrd_uart1_mpp_config[] __initdata = {
+	MPP13_UART1_TXD,
+	MPP14_UART1_RXD,
 	0
 };
 
@@ -67,6 +83,68 @@
 	},
 };
 
+static int __initdata uart1;
+
+static int __init sd_uart_selection(char *str)
+{
+	uart1 = -EINVAL;
+
+	/* Default is SD. Change if required, for UART */
+	if (!str)
+		return 0;
+
+	if (!strncmp(str, "232", 3)) {
+		uart1 = 232;
+	} else if (!strncmp(str, "485", 3)) {
+		/* OpenRD-Base doesn't have RS485. Treat is as an
+		 * unknown argument & just have default setting -
+		 * which is SD */
+		if (machine_is_openrd_base()) {
+			uart1 = -ENODEV;
+			return 1;
+		}
+
+		uart1 = 485;
+	}
+	return 1;
+}
+/* Parse boot_command_line string kw_openrd_init_uart1=232/485 */
+__setup("kw_openrd_init_uart1=", sd_uart_selection);
+
+static int __init uart1_mpp_config(void)
+{
+	kirkwood_mpp_conf(openrd_uart1_mpp_config);
+
+	if (gpio_request(34, "SD_UART1_SEL")) {
+		printk(KERN_ERR "GPIO request failed for SD/UART1 selection"
+				", gpio: 34\n");
+		return -EIO;
+	}
+
+	if (gpio_request(28, "RS232_RS485_SEL")) {
+		printk(KERN_ERR "GPIO request failed for RS232/RS485 selection"
+				", gpio# 28\n");
+		gpio_free(34);
+		return -EIO;
+	}
+
+	/* Select UART1
+	 * Pin # 34: 0 => UART1, 1 => SD */
+	gpio_direction_output(34, 0);
+
+	/* Select RS232 OR RS485
+	 * Pin # 28: 0 => RS232, 1 => RS485 */
+	if (uart1 == 232)
+		gpio_direction_output(28, 0);
+	else
+		gpio_direction_output(28, 1);
+
+	gpio_free(34);
+	gpio_free(28);
+
+	return 0;
+}
+
 static void __init openrd_init(void)
 {
 	/*
@@ -90,7 +168,6 @@
 		kirkwood_ge01_init(&openrd_ge01_data);
 
 	kirkwood_sata_init(&openrd_sata_data);
-	kirkwood_sdio_init(&openrd_mvsdio_data);
 
 	kirkwood_i2c_init();
 
@@ -99,6 +176,28 @@
 			ARRAY_SIZE(i2c_board_info));
 		kirkwood_audio_init();
 	}
+
+	if (uart1 <= 0) {
+		if (uart1 < 0)
+			printk(KERN_ERR "Invalid kernel parameter to select "
+				"UART1. Defaulting to SD. ERROR CODE: %d\n",
+				uart1);
+
+		/* Select SD
+		 * Pin # 34: 0 => UART1, 1 => SD */
+		if (gpio_request(34, "SD_UART1_SEL")) {
+			printk(KERN_ERR "GPIO request failed for SD/UART1 "
+					"selection, gpio: 34\n");
+		} else {
+
+			gpio_direction_output(34, 1);
+			gpio_free(34);
+			kirkwood_sdio_init(&openrd_mvsdio_data);
+		}
+	} else {
+		if (!uart1_mpp_config())
+			kirkwood_uart1_init();
+	}
 }
 
 static int __init openrd_pci_init(void)
@@ -115,8 +214,6 @@
 #ifdef CONFIG_MACH_OPENRD_BASE
 MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
 	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
@@ -128,8 +225,6 @@
 #ifdef CONFIG_MACH_OPENRD_CLIENT
 MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
 	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
@@ -141,8 +236,6 @@
 #ifdef CONFIG_MACH_OPENRD_ULTIMATE
 MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board")
 	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index 55e7f00..513ad31 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -117,7 +117,7 @@
 	 * IORESOURCE_IO
 	 */
 	pp->res[0].name = "PCIe 0 I/O Space";
-	pp->res[0].start = KIRKWOOD_PCIE_IO_PHYS_BASE;
+	pp->res[0].start = KIRKWOOD_PCIE_IO_BUS_BASE;
 	pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE_IO_SIZE - 1;
 	pp->res[0].flags = IORESOURCE_IO;
 
@@ -139,7 +139,7 @@
 	 * IORESOURCE_IO
 	 */
 	pp->res[0].name = "PCIe 1 I/O Space";
-	pp->res[0].start = KIRKWOOD_PCIE1_IO_PHYS_BASE;
+	pp->res[0].start = KIRKWOOD_PCIE1_IO_BUS_BASE;
 	pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE1_IO_SIZE - 1;
 	pp->res[0].flags = IORESOURCE_IO;
 
diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
index c34718c..0049614 100644
--- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
@@ -79,8 +79,6 @@
 
 MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board")
 	/* Maintainer: Saeed Bishara <saeed@marvell.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f6192_init,
 	.map_io		= kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c
index 3d147713..0998a08 100644
--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c
@@ -115,8 +115,6 @@
 
 MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board")
 	/* Maintainer: Saeed Bishara <saeed@marvell.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f6281_init,
 	.map_io		= kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
index a00879d..d2eec35 100644
--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c
+++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
@@ -131,8 +131,6 @@
 #ifdef CONFIG_MACH_SHEEVAPLUG
 MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
 	/* Maintainer: shadi Ammouri <shadi@marvell.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= sheevaplug_init,
 	.map_io		= kirkwood_map_io,
@@ -143,8 +141,6 @@
 
 #ifdef CONFIG_MACH_ESATA_SHEEVAPLUG
 MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board")
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= sheevaplug_init,
 	.map_io		= kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/t5325-setup.c b/arch/arm/mach-kirkwood/t5325-setup.c
index d01bf89..ce50e61a 100644
--- a/arch/arm/mach-kirkwood/t5325-setup.c
+++ b/arch/arm/mach-kirkwood/t5325-setup.c
@@ -184,8 +184,6 @@
 
 MACHINE_START(T5325, "HP t5325 Thin Client")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= hp_t5325_init,
 	.map_io		= kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c
index a5bd7fd..6710bd7 100644
--- a/arch/arm/mach-kirkwood/ts219-setup.c
+++ b/arch/arm/mach-kirkwood/ts219-setup.c
@@ -120,8 +120,6 @@
 
 MACHINE_START(TS219, "QNAP TS-119/TS-219")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts219_init,
 	.map_io		= kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/ts41x-setup.c b/arch/arm/mach-kirkwood/ts41x-setup.c
index 2e14afe..8be09a0 100644
--- a/arch/arm/mach-kirkwood/ts41x-setup.c
+++ b/arch/arm/mach-kirkwood/ts41x-setup.c
@@ -149,8 +149,6 @@
 
 MACHINE_START(TS41X, "QNAP TS-41x")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts41x_init,
 	.map_io		= kirkwood_map_io,
diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c
index 9e3e5a6..3ca4f8e 100644
--- a/arch/arm/mach-ks8695/board-acs5k.c
+++ b/arch/arm/mach-ks8695/board-acs5k.c
@@ -223,8 +223,6 @@
 
 MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board")
 	/* Maintainer: Simtec Electronics. */
-	.phys_io	= KS8695_IO_PA,
-	.io_pg_offst	= (KS8695_IO_VA >> 18) & 0xfffc,
 	.boot_params	= KS8695_SDRAM_PA + 0x100,
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
diff --git a/arch/arm/mach-ks8695/board-dsm320.c b/arch/arm/mach-ks8695/board-dsm320.c
index 521ff07..ada92b6 100644
--- a/arch/arm/mach-ks8695/board-dsm320.c
+++ b/arch/arm/mach-ks8695/board-dsm320.c
@@ -121,8 +121,6 @@
 
 MACHINE_START(DSM320, "D-Link DSM-320 Wireless Media Player")
 	/* Maintainer: Simtec Electronics. */
-	.phys_io	= KS8695_IO_PA,
-	.io_pg_offst	= (KS8695_IO_VA >> 18) & 0xfffc,
 	.boot_params	= KS8695_SDRAM_PA + 0x100,
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
diff --git a/arch/arm/mach-ks8695/board-micrel.c b/arch/arm/mach-ks8695/board-micrel.c
index 8ceaf5a..c7ad09b 100644
--- a/arch/arm/mach-ks8695/board-micrel.c
+++ b/arch/arm/mach-ks8695/board-micrel.c
@@ -53,8 +53,6 @@
 
 MACHINE_START(KS8695, "KS8695 Centaur Development Board")
 	/* Maintainer: Micrel Semiconductor Inc. */
-	.phys_io	= KS8695_IO_PA,
-	.io_pg_offst	= (KS8695_IO_VA >> 18) & 0xfffc,
 	.boot_params	= KS8695_SDRAM_PA + 0x100,
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
diff --git a/arch/arm/mach-ks8695/include/mach/debug-macro.S b/arch/arm/mach-ks8695/include/mach/debug-macro.S
index cf2095d..bf516ad 100644
--- a/arch/arm/mach-ks8695/include/mach/debug-macro.S
+++ b/arch/arm/mach-ks8695/include/mach/debug-macro.S
@@ -14,11 +14,9 @@
 #include <mach/hardware.h>
 #include <mach/regs-uart.h>
 
-	.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1				@ MMU enabled?
-		ldreq	\rx, =KS8695_UART_PA		@ physical base address
-		ldrne	\rx, =KS8695_UART_VA		@ virtual base address
+	.macro	addruart, rp, rv
+		ldr	\rp, =KS8695_UART_PA		@ physical base address
+		ldr	\rv, =KS8695_UART_VA		@ virtual base address
 	.endm
 
 	.macro	senduart, rd, rx
diff --git a/arch/arm/mach-l7200/include/mach/debug-macro.S b/arch/arm/mach-l7200/include/mach/debug-macro.S
new file mode 100644
index 0000000..b0a2db7
--- /dev/null
+++ b/arch/arm/mach-l7200/include/mach/debug-macro.S
@@ -0,0 +1,38 @@
+/* arch/arm/mach-l7200/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+		.equ	io_virt, IO_BASE
+		.equ	io_phys, IO_START
+
+		.macro	addruart, rp, rv
+		mov	\rp, #0x00044000	@ UART1
+@		mov	\rp, #0x00045000	@ UART2
+		add	\rv, \rp, #io_virt	@ virtual address
+		add	\rp, \rp, #io_phys	@ physical base address
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0x0]	@ UARTDR
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldr	\rd, [\rx, #0x18]	@ UARTFLG
+		tst	\rd, #1 << 5		@ UARTFLGUTXFF - 1 when full
+		bne	1001b
+		.endm
+
+		.macro	busyuart,rd,rx
+1001:		ldr	\rd, [\rx, #0x18]	@ UARTFLG
+		tst	\rd, #1 << 3		@ UARTFLGUBUSY - 1 when busy
+		bne	1001b
+		.endm
diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
index 3d7bd50..9088c166 100644
--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c
+++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c
@@ -111,8 +111,6 @@
 
 MACHINE_START (KEV7A400, "Sharp KEV7a400")
 	/* Maintainer: Marc Singer */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((io_p2v (0x80000000))>>18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= kev7a400_map_io,
 	.init_irq	= lh7a400_init_irq,
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index cb15e5d..7315a56 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -398,8 +398,6 @@
 
 MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
 	/* Maintainer: Marc Singer */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((io_p2v (0x80000000))>>18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= lpd7a40x_map_io,
 	.init_irq	= lh7a400_init_irq,
@@ -413,8 +411,6 @@
 
 MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
 	/* Maintainer: Marc Singer */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((io_p2v (0x80000000))>>18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= lpd7a40x_map_io,
 	.init_irq	= lh7a404_init_irq,
diff --git a/arch/arm/mach-lh7a40x/include/mach/debug-macro.S b/arch/arm/mach-lh7a40x/include/mach/debug-macro.S
index c0dcbbb..cff3362 100644
--- a/arch/arm/mach-lh7a40x/include/mach/debug-macro.S
+++ b/arch/arm/mach-lh7a40x/include/mach/debug-macro.S
@@ -14,12 +14,10 @@
 	@ It is not known if this will be appropriate for every 40x
 	@ board.
 
-		.macro  addruart, rx, tmp
-		mrc     p15, 0, \rx, c1, c0
-		tst     \rx, #1                 @ MMU enabled?
-		mov     \rx, #0x00000700        @ offset from base
-		orreq   \rx, \rx, #0x80000000   @ physical base
-		orrne   \rx, \rx, #0xf8000000   @ virtual base
+		.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
diff --git a/arch/arm/mach-loki/include/mach/debug-macro.S b/arch/arm/mach-loki/include/mach/debug-macro.S
index 3136c91..cc90d99 100644
--- a/arch/arm/mach-loki/include/mach/debug-macro.S
+++ b/arch/arm/mach-loki/include/mach/debug-macro.S
@@ -8,12 +8,11 @@
 
 #include <mach/loki.h>
 
-	.macro	addruart, rx, tmp
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1					@ MMU enabled?
-	ldreq	\rx, =LOKI_REGS_PHYS_BASE
-	ldrne	\rx, =LOKI_REGS_VIRT_BASE
-	orr	\rx, \rx, #0x00012000
+	.macro	addruart, rp, rv
+	ldr	\rp, =LOKI_REGS_PHYS_BASE
+	ldr	\rv, =LOKI_REGS_VIRT_BASE
+	orr	\rp, \rp, #0x00012000
+	orr	\rv, \rv, #0x00012000
 	.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-loki/lb88rc8480-setup.c b/arch/arm/mach-loki/lb88rc8480-setup.c
index 85f9c12..a1e75e7 100644
--- a/arch/arm/mach-loki/lb88rc8480-setup.c
+++ b/arch/arm/mach-loki/lb88rc8480-setup.c
@@ -90,8 +90,6 @@
 
 MACHINE_START(LB88RC8480, "Marvell LB88RC8480 Development Board")
 	/* Maintainer: Ke Wei <kewei@marvell.com> */
-	.phys_io	= LOKI_REGS_PHYS_BASE,
-	.io_pg_offst	= ((LOKI_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= lb88rc8480_init,
 	.map_io		= loki_map_io,
diff --git a/arch/arm/mach-lpc32xx/include/mach/debug-macro.S b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
index 621744d..629e744 100644
--- a/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
@@ -20,11 +20,9 @@
  * Debug output is hardcoded to standard UART 5
 */
 
-	.macro	addruart,rx, tmp
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1				@ MMU enabled?
-	ldreq	\rx, =0x40090000
-	ldrne	\rx, =0xF4090000
+	.macro	addruart, rp, rv
+	ldreq	\rp, =0x40090000
+	ldrne	\rv, =0xF4090000
 	.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
index bc9a42d..7993b09 100644
--- a/arch/arm/mach-lpc32xx/phy3250.c
+++ b/arch/arm/mach-lpc32xx/phy3250.c
@@ -172,18 +172,12 @@
 }
 
 static struct pl022_config_chip spi0_chip_info = {
-	.lbm			= LOOPBACK_DISABLED,
 	.com_mode		= INTERRUPT_TRANSFER,
 	.iface			= SSP_INTERFACE_MOTOROLA_SPI,
 	.hierarchy		= SSP_MASTER,
 	.slave_tx_disable	= 0,
-	.endian_tx		= SSP_TX_LSB,
-	.endian_rx		= SSP_RX_LSB,
-	.data_size		= SSP_DATA_BITS_8,
 	.rx_lev_trig		= SSP_RX_4_OR_MORE_ELEM,
 	.tx_lev_trig		= SSP_TX_4_OR_MORE_EMPTY_LOC,
-	.clk_phase		= SSP_CLK_FIRST_EDGE,
-	.clk_pol		= SSP_CLK_POL_IDLE_LOW,
 	.ctrl_len		= SSP_BITS_8,
 	.wait_state		= SSP_MWIRE_WAIT_ZERO,
 	.duplex			= SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
@@ -239,6 +233,7 @@
 			.max_speed_hz = 5000000,
 			.bus_num = 0,
 			.chip_select = 0,
+			.mode = SPI_MODE_0,
 			.platform_data = &eeprom,
 			.controller_data = &spi0_chip_info,
 		},
@@ -387,8 +382,6 @@
 
 MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
 	/* Maintainer: Kevin Wells, NXP Semiconductors */
-	.phys_io	= LPC32XX_UART5_BASE,
-	.io_pg_offst	= ((IO_ADDRESS(LPC32XX_UART5_BASE))>>18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= lpc32xx_map_io,
 	.init_irq	= lpc32xx_init_irq,
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 6ab843e..0711d3b 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -57,6 +57,13 @@
 	  PXA910-based development board. Since MMP2 is compatible to
 	  ARMv6 architecture.
 
+config MACH_TETON_BGA
+	bool "Marvell's PXA168 Teton BGA Development Board"
+	select CPU_PXA168
+	help
+	  Say 'Y' here if you want to support the Marvell PXA168-based
+	  Teton BGA Development Board.
+
 endmenu
 
 config CPU_PXA168
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 8b66d06..751cdbf 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -17,3 +17,4 @@
 obj-$(CONFIG_MACH_TTC_DKB)	+= ttc_dkb.o
 obj-$(CONFIG_MACH_FLINT)	+= flint.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
+obj-$(CONFIG_MACH_TETON_BGA)	+= teton_bga.o
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 0629394..06b5fa8 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -16,6 +16,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -23,6 +24,9 @@
 #include <mach/mfp-pxa168.h>
 #include <mach/pxa168.h>
 #include <mach/gpio.h>
+#include <video/pxa168fb.h>
+#include <linux/input.h>
+#include <plat/pxa27x_keypad.h>
 
 #include "common.h"
 
@@ -66,6 +70,43 @@
 	GPIO115_I2S_BCLK,
 	GPIO116_I2S_RXD,
 	GPIO117_I2S_TXD,
+
+	/* LCD */
+	GPIO56_LCD_FCLK_RD,
+	GPIO57_LCD_LCLK_A0,
+	GPIO58_LCD_PCLK_WR,
+	GPIO59_LCD_DENA_BIAS,
+	GPIO60_LCD_DD0,
+	GPIO61_LCD_DD1,
+	GPIO62_LCD_DD2,
+	GPIO63_LCD_DD3,
+	GPIO64_LCD_DD4,
+	GPIO65_LCD_DD5,
+	GPIO66_LCD_DD6,
+	GPIO67_LCD_DD7,
+	GPIO68_LCD_DD8,
+	GPIO69_LCD_DD9,
+	GPIO70_LCD_DD10,
+	GPIO71_LCD_DD11,
+	GPIO72_LCD_DD12,
+	GPIO73_LCD_DD13,
+	GPIO74_LCD_DD14,
+	GPIO75_LCD_DD15,
+	GPIO76_LCD_DD16,
+	GPIO77_LCD_DD17,
+	GPIO78_LCD_DD18,
+	GPIO79_LCD_DD19,
+	GPIO80_LCD_DD20,
+	GPIO81_LCD_DD21,
+	GPIO82_LCD_DD22,
+	GPIO83_LCD_DD23,
+
+	/* Keypad */
+	GPIO109_KP_MKIN1,
+	GPIO110_KP_MKIN0,
+	GPIO111_KP_MKOUT7,
+	GPIO112_KP_MKOUT6,
+	GPIO121_KP_MKIN4,
 };
 
 static struct smc91x_platdata smc91x_info = {
@@ -134,6 +175,51 @@
 	{ I2C_BOARD_INFO("wm8753", 0x1b), },
 };
 
+static struct fb_videomode video_modes[] = {
+	[0] = {
+		.pixclock	= 30120,
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 480,
+		.hsync_len	= 1,
+		.left_margin	= 215,
+		.right_margin	= 40,
+		.vsync_len	= 1,
+		.upper_margin	= 34,
+		.lower_margin	= 10,
+		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
+	},
+};
+
+struct pxa168fb_mach_info aspenite_lcd_info = {
+	.id			= "Graphic Frame",
+	.modes			= video_modes,
+	.num_modes		= ARRAY_SIZE(video_modes),
+	.pix_fmt		= PIX_FMT_RGB565,
+	.io_pin_allocation_mode = PIN_MODE_DUMB_24,
+	.dumb_mode		= DUMB_MODE_RGB888,
+	.active			= 1,
+	.panel_rbswap		= 0,
+	.invert_pixclock	= 0,
+};
+
+static unsigned int aspenite_matrix_key_map[] = {
+	KEY(0, 6, KEY_UP),	/* SW 4 */
+	KEY(0, 7, KEY_DOWN),	/* SW 5 */
+	KEY(1, 6, KEY_LEFT),	/* SW 6 */
+	KEY(1, 7, KEY_RIGHT),	/* SW 7 */
+	KEY(4, 6, KEY_ENTER),	/* SW 8 */
+	KEY(4, 7, KEY_ESC),	/* SW 9 */
+};
+
+static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = {
+	.matrix_key_rows	= 5,
+	.matrix_key_cols	= 8,
+	.matrix_key_map		= aspenite_matrix_key_map,
+	.matrix_key_map_size	= ARRAY_SIZE(aspenite_matrix_key_map),
+	.debounce_interval	= 30,
+};
+
 static void __init common_init(void)
 {
 	mfp_config(ARRAY_AND_SIZE(common_pin_config));
@@ -143,24 +229,24 @@
 	pxa168_add_twsi(1, NULL, ARRAY_AND_SIZE(aspenite_i2c_info));
 	pxa168_add_ssp(1);
 	pxa168_add_nand(&aspenite_nand_info);
+	pxa168_add_fb(&aspenite_lcd_info);
+	pxa168_add_keypad(&aspenite_keypad_info);
 
 	/* off-chip devices */
 	platform_device_register(&smc91x_device);
 }
 
 MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform")
-	.phys_io        = APB_PHYS_BASE,
-	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
 	.map_io		= mmp_map_io,
+	.nr_irqs	= IRQ_BOARD_START,
 	.init_irq       = pxa168_init_irq,
 	.timer          = &pxa168_timer,
 	.init_machine   = common_init,
 MACHINE_END
 
 MACHINE_START(ZYLONITE2, "PXA168-based Zylonite2 Development Platform")
-	.phys_io        = APB_PHYS_BASE,
-	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
 	.map_io		= mmp_map_io,
+	.nr_irqs	= IRQ_BOARD_START,
 	.init_irq       = pxa168_init_irq,
 	.timer          = &pxa168_timer,
 	.init_machine   = common_init,
diff --git a/arch/arm/mach-mmp/avengers_lite.c b/arch/arm/mach-mmp/avengers_lite.c
index 69bcba1..39f0878 100644
--- a/arch/arm/mach-mmp/avengers_lite.c
+++ b/arch/arm/mach-mmp/avengers_lite.c
@@ -41,8 +41,6 @@
 }
 
 MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform")
-	.phys_io        = APB_PHYS_BASE,
-	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
 	.map_io		= mmp_map_io,
 	.init_irq       = pxa168_init_irq,
 	.timer          = &pxa168_timer,
diff --git a/arch/arm/mach-mmp/common.c b/arch/arm/mach-mmp/common.c
index 3b29fa7..0ec0ca8 100644
--- a/arch/arm/mach-mmp/common.c
+++ b/arch/arm/mach-mmp/common.c
@@ -10,13 +10,20 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 
 #include <asm/page.h>
 #include <asm/mach/map.h>
 #include <mach/addr-map.h>
+#include <mach/cputype.h>
 
 #include "common.h"
 
+#define MMP_CHIPID	(AXI_VIRT_BASE + 0x82c00)
+
+unsigned int mmp_chip_id;
+EXPORT_SYMBOL(mmp_chip_id);
+
 static struct map_desc standard_io_desc[] __initdata = {
 	{
 		.pfn		= __phys_to_pfn(APB_PHYS_BASE),
@@ -34,4 +41,7 @@
 void __init mmp_map_io(void)
 {
 	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+
+	/* this is early, initialize mmp_chip_id here */
+	mmp_chip_id = __raw_readl(MMP_CHIPID);
 }
diff --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c
index e4312d2..bdeb6db 100644
--- a/arch/arm/mach-mmp/flint.c
+++ b/arch/arm/mach-mmp/flint.c
@@ -16,6 +16,7 @@
 #include <linux/smc91x.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -25,6 +26,8 @@
 
 #include "common.h"
 
+#define FLINT_NR_IRQS	(IRQ_BOARD_START + 48)
+
 static unsigned long flint_pin_config[] __initdata = {
 	/* UART1 */
 	GPIO45_UART1_RXD,
@@ -113,9 +116,8 @@
 }
 
 MACHINE_START(FLINT, "Flint Development Platform")
-	.phys_io        = APB_PHYS_BASE,
-	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
 	.map_io		= mmp_map_io,
+	.nr_irqs	= FLINT_NR_IRQS,
 	.init_irq       = mmp2_init_irq,
 	.timer          = &mmp2_timer,
 	.init_machine   = flint_init,
diff --git a/arch/arm/mach-mmp/include/mach/cputype.h b/arch/arm/mach-mmp/include/mach/cputype.h
index 83b1872..f43a68b 100644
--- a/arch/arm/mach-mmp/include/mach/cputype.h
+++ b/arch/arm/mach-mmp/include/mach/cputype.h
@@ -4,36 +4,51 @@
 #include <asm/cputype.h>
 
 /*
- *  CPU   Stepping   OLD_ID       CPU_ID      CHIP_ID
+ *  CPU   Stepping   CPU_ID      CHIP_ID
  *
- * PXA168    A0    0x41159263   0x56158400   0x00A0A333
- * PXA910    Y0    0x41159262   0x56158000   0x00F0C910
- * MMP2	     Z0			0x560f5811
+ * PXA168    S0    0x56158400   0x0000C910
+ * PXA168    A0    0x56158400   0x00A0A168
+ * PXA910    Y1    0x56158400   0x00F2C920
+ * PXA910    A0    0x56158400   0x00F2C910
+ * PXA910    A1    0x56158400   0x00A0C910
+ * PXA920    Y0    0x56158400   0x00F2C920
+ * PXA920    A0    0x56158400   0x00A0C920
+ * PXA920    A1    0x56158400   0x00A1C920
+ * MMP2	     Z0	   0x560f5811   0x00F00410
+ * MMP2      Z1    0x560f5811   0x00E00410
+ * MMP2      A0    0x560f5811   0x00A0A610
  */
 
+extern unsigned int mmp_chip_id;
+
 #ifdef CONFIG_CPU_PXA168
-#  define __cpu_is_pxa168(id)	\
-	({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x84; })
+static inline int cpu_is_pxa168(void)
+{
+	return (((read_cpuid_id() >> 8) & 0xff) == 0x84) &&
+		((mmp_chip_id & 0xfff) == 0x168);
+}
 #else
-#  define __cpu_is_pxa168(id)	(0)
+#define cpu_is_pxa168()	(0)
 #endif
 
+/* cpu_is_pxa910() is shared on both pxa910 and pxa920 */
 #ifdef CONFIG_CPU_PXA910
-#  define __cpu_is_pxa910(id)	\
-	({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x80; })
+static inline int cpu_is_pxa910(void)
+{
+	return (((read_cpuid_id() >> 8) & 0xff) == 0x84) &&
+		(((mmp_chip_id & 0xfff) == 0x910) ||
+		 ((mmp_chip_id & 0xfff) == 0x920));
+}
 #else
-#  define __cpu_is_pxa910(id)	(0)
+#define cpu_is_pxa910()	(0)
 #endif
 
 #ifdef CONFIG_CPU_MMP2
-#  define __cpu_is_mmp2(id)	\
-	({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x58; })
+static inline int cpu_is_mmp2(void)
+{
+	return (((cpu_readid_id() >> 8) & 0xff) == 0x58);
 #else
-#  define __cpu_is_mmp2(id)	(0)
+#define cpu_is_mmp2()	(0)
 #endif
 
-#define cpu_is_pxa168()		({ __cpu_is_pxa168(read_cpuid_id()); })
-#define cpu_is_pxa910()		({ __cpu_is_pxa910(read_cpuid_id()); })
-#define cpu_is_mmp2()		({ __cpu_is_mmp2(read_cpuid_id()); })
-
 #endif /* __ASM_MACH_CPUTYPE_H */
diff --git a/arch/arm/mach-mmp/include/mach/debug-macro.S b/arch/arm/mach-mmp/include/mach/debug-macro.S
index 76deff2..7e2ebd3 100644
--- a/arch/arm/mach-mmp/include/mach/debug-macro.S
+++ b/arch/arm/mach-mmp/include/mach/debug-macro.S
@@ -11,12 +11,11 @@
 
 #include <mach/addr-map.h>
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1				@ MMU enabled?
-		ldreq	\rx, =APB_PHYS_BASE		@ physical
-		ldrne	\rx, =APB_VIRT_BASE		@ virtual
-		orr	\rx, \rx, #0x00017000
+		.macro	addruart, rp, rv
+		ldr	\rp, =APB_PHYS_BASE		@ physical
+		ldr	\rv, =APB_VIRT_BASE		@ virtual
+		orr	\rp, \rp, #0x00017000
+		orr	\rv, \rv, #0x00017000
 		.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h
index b379cde..a09d328 100644
--- a/arch/arm/mach-mmp/include/mach/irqs.h
+++ b/arch/arm/mach-mmp/include/mach/irqs.h
@@ -222,10 +222,8 @@
 #define IRQ_GPIO_NUM			192
 #define IRQ_GPIO(x)			(IRQ_GPIO_START + (x))
 
-/* Board IRQ - 64 by default, increase if not enough */
 #define IRQ_BOARD_START			(IRQ_GPIO_START + IRQ_GPIO_NUM)
-#define IRQ_BOARD_END			(IRQ_BOARD_START + 64)
 
-#define NR_IRQS				(IRQ_BOARD_END)
+#define NR_IRQS				(IRQ_BOARD_START)
 
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
index ded43c4..4621067 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
@@ -289,4 +289,11 @@
 #define GPIO86_PWM1_OUT		MFP_CFG(GPIO86, AF2)
 #define GPIO86_PWM2_OUT		MFP_CFG(GPIO86, AF3)
 
+/* Keypad */
+#define GPIO109_KP_MKIN1        MFP_CFG(GPIO109, AF7)
+#define GPIO110_KP_MKIN0        MFP_CFG(GPIO110, AF7)
+#define GPIO111_KP_MKOUT7       MFP_CFG(GPIO111, AF7)
+#define GPIO112_KP_MKOUT6       MFP_CFG(GPIO112, AF7)
+#define GPIO121_KP_MKIN4        MFP_CFG(GPIO121, AF7)
+
 #endif /* __ASM_MACH_MFP_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
index 27e1bc7..1801e42 100644
--- a/arch/arm/mach-mmp/include/mach/pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -5,11 +5,15 @@
 
 extern struct sys_timer pxa168_timer;
 extern void __init pxa168_init_irq(void);
+extern void pxa168_clear_keypad_wakeup(void);
 
 #include <linux/i2c.h>
 #include <mach/devices.h>
 #include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
+#include <video/pxa168fb.h>
+#include <plat/pxa27x_keypad.h>
+#include <mach/cputype.h>
 
 extern struct pxa_device_desc pxa168_device_uart1;
 extern struct pxa_device_desc pxa168_device_uart2;
@@ -25,6 +29,8 @@
 extern struct pxa_device_desc pxa168_device_ssp4;
 extern struct pxa_device_desc pxa168_device_ssp5;
 extern struct pxa_device_desc pxa168_device_nand;
+extern struct pxa_device_desc pxa168_device_fb;
+extern struct pxa_device_desc pxa168_device_keypad;
 
 static inline int pxa168_add_uart(int id)
 {
@@ -97,4 +103,18 @@
 {
 	return pxa_register_device(&pxa168_device_nand, info, sizeof(*info));
 }
+
+static inline int pxa168_add_fb(struct pxa168fb_mach_info *mi)
+{
+	return pxa_register_device(&pxa168_device_fb, mi, sizeof(*mi));
+}
+
+static inline int pxa168_add_keypad(struct pxa27x_keypad_platform_data *data)
+{
+	if (cpu_is_pxa168())
+		data->clear_wakeup_event = pxa168_clear_keypad_wakeup;
+
+	return pxa_register_device(&pxa168_device_keypad, data, sizeof(*data));
+}
+
 #endif /* __ASM_MACH_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h
index 9190305..ac47023 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apmu.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h
@@ -33,4 +33,16 @@
 #define APMU_FNRST_DIS	(1 << 1)
 #define APMU_AXIRST_DIS	(1 << 0)
 
+/* Wake Clear Register */
+#define APMU_WAKE_CLR	APMU_REG(0x07c)
+
+#define APMU_PXA168_KP_WAKE_CLR		(1 << 7)
+#define APMU_PXA168_CFI_WAKE_CLR	(1 << 6)
+#define APMU_PXA168_XD_WAKE_CLR		(1 << 5)
+#define APMU_PXA168_MSP_WAKE_CLR	(1 << 4)
+#define APMU_PXA168_SD4_WAKE_CLR	(1 << 3)
+#define APMU_PXA168_SD3_WAKE_CLR	(1 << 2)
+#define APMU_PXA168_SD2_WAKE_CLR	(1 << 1)
+#define APMU_PXA168_SD1_WAKE_CLR	(1 << 0)
+
 #endif /* __ASM_MACH_REGS_APMU_H */
diff --git a/arch/arm/mach-mmp/include/mach/system.h b/arch/arm/mach-mmp/include/mach/system.h
index 4f5b0e0..1a8a25e 100644
--- a/arch/arm/mach-mmp/include/mach/system.h
+++ b/arch/arm/mach-mmp/include/mach/system.h
@@ -9,6 +9,8 @@
 #ifndef __ASM_MACH_SYSTEM_H
 #define __ASM_MACH_SYSTEM_H
 
+#include <mach/cputype.h>
+
 static inline void arch_idle(void)
 {
 	cpu_do_idle();
@@ -16,6 +18,9 @@
 
 static inline void arch_reset(char mode, const char *cmd)
 {
-	cpu_reset(0);
+	if (cpu_is_pxa168())
+		cpu_reset(0xffff0000);
+	else
+		cpu_reset(0);
 }
 #endif /* __ASM_MACH_SYSTEM_H */
diff --git a/arch/arm/mach-mmp/include/mach/teton_bga.h b/arch/arm/mach-mmp/include/mach/teton_bga.h
new file mode 100644
index 0000000..61a539b
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/teton_bga.h
@@ -0,0 +1,27 @@
+/*
+ *  linux/arch/arm/mach-mmp/include/mach/teton_bga.h
+ *
+ *  Support for the Marvell PXA168 Teton BGA Development Platform.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+#ifndef __ASM_MACH_TETON_BGA_H
+#define __ASM_MACH_TETON_BGA_H
+
+/* GPIOs */
+#define MMC_PWENA_GPIO		27
+#define USBHPENB_GPIO		55
+#define RTC_INT_GPIO		78
+#define LCD_VBLK_EN_GPIO	79
+#define LCD_DVDD_EN_GPIO	80
+#define RST_WIFI_GPIO		81
+#define CF_PWEN_GPIO		82
+#define USB_OC_GPIO		83
+#define PWM_GPIO		84
+#define USBHPENA_GPIO		85
+#define TS_INT_GPIO		86
+#define CIR_GPIO		108
+
+#endif /* __ASM_MACH_TETON_BGA_H */
diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c
index 80c3e7a..2a684fa 100644
--- a/arch/arm/mach-mmp/jasper.c
+++ b/arch/arm/mach-mmp/jasper.c
@@ -18,16 +18,18 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/max8649.h>
 #include <linux/mfd/max8925.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/addr-map.h>
 #include <mach/mfp-mmp2.h>
 #include <mach/mmp2.h>
-#include <mach/irqs.h>
 
 #include "common.h"
 
+#define JASPER_NR_IRQS		(IRQ_BOARD_START + 48)
+
 static unsigned long jasper_pin_config[] __initdata = {
 	/* UART1 */
 	GPIO29_UART1_RXD,
@@ -134,9 +136,8 @@
 }
 
 MACHINE_START(MARVELL_JASPER, "Jasper Development Platform")
-	.phys_io        = APB_PHYS_BASE,
-	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
 	.map_io		= mmp_map_io,
+	.nr_irqs	= JASPER_NR_IRQS,
 	.init_irq       = mmp2_init_irq,
 	.timer          = &mmp2_timer,
 	.init_machine   = jasper_init,
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index 652ae66..72b4e76 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -77,8 +77,10 @@
 static APBC_CLK(ssp3, PXA168_SSP3, 4, 0);
 static APBC_CLK(ssp4, PXA168_SSP4, 4, 0);
 static APBC_CLK(ssp5, PXA168_SSP5, 4, 0);
+static APBC_CLK(keypad, PXA168_KPC, 0, 32000);
 
 static APMU_CLK(nand, NAND, 0x01db, 208000000);
+static APMU_CLK(lcd, LCD, 0x7f, 312000000);
 
 /* device and clock bindings */
 static struct clk_lookup pxa168_clkregs[] = {
@@ -96,6 +98,8 @@
 	INIT_CLKREG(&clk_ssp4, "pxa168-ssp.3", NULL),
 	INIT_CLKREG(&clk_ssp5, "pxa168-ssp.4", NULL),
 	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
+	INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
+	INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
 };
 
 static int __init pxa168_init(void)
@@ -132,6 +136,16 @@
 	.init	= pxa168_timer_init,
 };
 
+void pxa168_clear_keypad_wakeup(void)
+{
+	uint32_t val;
+	uint32_t mask = APMU_PXA168_KP_WAKE_CLR;
+
+	/* wake event clear is needed in order to clear keypad interrupt */
+	val = __raw_readl(APMU_WAKE_CLR);
+	__raw_writel(val |  mask, APMU_WAKE_CLR);
+}
+
 /* on-chip devices */
 PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22);
 PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24);
@@ -147,3 +161,5 @@
 PXA168_DEVICE(ssp3, "pxa168-ssp", 2, SSP3, 0xd401f000, 0x40, 56, 57);
 PXA168_DEVICE(ssp4, "pxa168-ssp", 3, SSP4, 0xd4020000, 0x40, 58, 59);
 PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61);
+PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8);
+PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c);
diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c
index e81db74..c296b75 100644
--- a/arch/arm/mach-mmp/tavorevb.c
+++ b/arch/arm/mach-mmp/tavorevb.c
@@ -99,8 +99,6 @@
 }
 
 MACHINE_START(TAVOREVB, "PXA910 Evaluation Board (aka TavorEVB)")
-	.phys_io        = APB_PHYS_BASE,
-	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
 	.map_io		= mmp_map_io,
 	.init_irq       = pxa910_init_irq,
 	.timer          = &pxa910_timer,
diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c
new file mode 100644
index 0000000..bbe4727
--- /dev/null
+++ b/arch/arm/mach-mmp/teton_bga.c
@@ -0,0 +1,89 @@
+/*
+ *  linux/arch/arm/mach-mmp/teton_bga.c
+ *
+ *  Support for the Marvell PXA168 Teton BGA Development Platform.
+ *
+ *  Author: Mark F. Brown <mark.brown314@gmail.com>
+ *
+ *  This code is based on aspenite.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <plat/pxa27x_keypad.h>
+#include <linux/i2c.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/addr-map.h>
+#include <mach/mfp-pxa168.h>
+#include <mach/pxa168.h>
+#include <mach/teton_bga.h>
+
+#include "common.h"
+
+static unsigned long teton_bga_pin_config[] __initdata = {
+	/* UART1 */
+	GPIO107_UART1_TXD,
+	GPIO108_UART1_RXD,
+
+	/* Keypad */
+	GPIO109_KP_MKIN1,
+	GPIO110_KP_MKIN0,
+	GPIO111_KP_MKOUT7,
+	GPIO112_KP_MKOUT6,
+
+	/* I2C Bus */
+	GPIO105_CI2C_SDA,
+	GPIO106_CI2C_SCL,
+
+	/* RTC */
+	GPIO78_GPIO,
+};
+
+static unsigned int teton_bga_matrix_key_map[] = {
+	KEY(0, 6, KEY_ESC),
+	KEY(0, 7, KEY_ENTER),
+	KEY(1, 6, KEY_LEFT),
+	KEY(1, 7, KEY_RIGHT),
+};
+
+static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = {
+	.matrix_key_rows        = 2,
+	.matrix_key_cols        = 8,
+	.matrix_key_map         = teton_bga_matrix_key_map,
+	.matrix_key_map_size    = ARRAY_SIZE(teton_bga_matrix_key_map),
+	.debounce_interval      = 30,
+};
+
+static struct i2c_board_info teton_bga_i2c_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("ds1337", 0x68),
+		.irq = gpio_to_irq(RTC_INT_GPIO)
+	},
+};
+
+static void __init teton_bga_init(void)
+{
+	mfp_config(ARRAY_AND_SIZE(teton_bga_pin_config));
+
+	/* on-chip devices */
+	pxa168_add_uart(1);
+	pxa168_add_keypad(&teton_bga_keypad_info);
+	pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(teton_bga_i2c_info));
+}
+
+MACHINE_START(TETON_BGA, "PXA168-based Teton BGA Development Platform")
+	.map_io		= mmp_map_io,
+	.nr_irqs	= IRQ_BOARD_START,
+	.init_irq       = pxa168_init_irq,
+	.timer          = &pxa168_timer,
+	.init_machine   = teton_bga_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index ee65e05..e411039 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -14,6 +14,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/onenand.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -24,6 +25,8 @@
 
 #include "common.h"
 
+#define TTCDKB_NR_IRQS		(IRQ_BOARD_START + 24)
+
 static unsigned long ttc_dkb_pin_config[] __initdata = {
 	/* UART2 */
 	GPIO47_UART2_RXD,
@@ -122,9 +125,8 @@
 }
 
 MACHINE_START(TTC_DKB, "PXA910-based TTC_DKB Development Platform")
-	.phys_io        = APB_PHYS_BASE,
-	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
 	.map_io		= mmp_map_io,
+	.nr_irqs	= TTCDKB_NR_IRQS,
 	.init_irq       = pxa910_init_irq,
 	.timer          = &pxa910_timer,
 	.init_machine   = ttc_dkb_init,
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 47264a7..3115a29 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -10,6 +10,8 @@
 	select MSM_SMD
 	select MSM_SMD_PKG3
 	select CPU_V6
+	select MSM_PROC_COMM
+	select HAS_MSM_DEBUG_UART_PHYS
 
 config ARCH_MSM7X30
 	bool "MSM7x30"
@@ -18,6 +20,9 @@
 	select MSM_VIC
 	select CPU_V7
 	select MSM_REMOTE_SPINLOCK_DEKKERS
+	select MSM_GPIOMUX
+	select MSM_PROC_COMM
+	select HAS_MSM_DEBUG_UART_PHYS
 
 config ARCH_QSD8X50
 	bool "QSD8X50"
@@ -26,6 +31,19 @@
 	select MSM_VIC
 	select CPU_V7
 	select MSM_REMOTE_SPINLOCK_LDREX
+	select MSM_GPIOMUX
+	select MSM_PROC_COMM
+	select HAS_MSM_DEBUG_UART_PHYS
+
+config ARCH_MSM8X60
+	bool "MSM8X60"
+	select ARM_GIC
+	select CPU_V7
+	select MSM_V2_TLMM
+	select MSM_GPIOMUX
+	select MACH_MSM8X60_SURF if (!MACH_MSM8X60_RUMI3 && !MACH_MSM8X60_SIM \
+				  && !MACH_MSM8X60_FFA)
+
 endchoice
 
 config MSM_SOC_REV_A
@@ -36,6 +54,9 @@
 config  ARCH_MSM_SCORPION
 	bool
 
+config HAS_MSM_DEBUG_UART_PHYS
+	bool
+
 config  MSM_VIC
 	bool
 
@@ -74,6 +95,30 @@
 	help
 	  Support for the Qualcomm ST1.5.
 
+config MACH_MSM8X60_RUMI3
+	depends on ARCH_MSM8X60
+	bool "MSM8x60 RUMI3"
+	help
+	  Support for the Qualcomm MSM8x60 RUMI3 emulator.
+
+config MACH_MSM8X60_SURF
+	depends on ARCH_MSM8X60
+	bool "MSM8x60 SURF"
+	help
+	  Support for the Qualcomm MSM8x60 SURF eval board.
+
+config MACH_MSM8X60_SIM
+	depends on ARCH_MSM8X60
+	bool "MSM8x60 Simulator"
+	help
+	  Support for the Qualcomm MSM8x60 simulator.
+
+config MACH_MSM8X60_FFA
+	depends on ARCH_MSM8X60
+	bool "MSM8x60 FFA"
+	help
+	  Support for the Qualcomm MSM8x60 FFA eval board.
+
 endmenu
 
 config MSM_DEBUG_UART
@@ -82,6 +127,7 @@
 	default 2 if MSM_DEBUG_UART2
 	default 3 if MSM_DEBUG_UART3
 
+if HAS_MSM_DEBUG_UART_PHYS
 choice
 	prompt "Debug UART"
 
@@ -99,11 +145,20 @@
 	config MSM_DEBUG_UART3
 		bool "UART3"
 endchoice
+endif
 
 config MSM_SMD_PKG3
 	bool
 
+config MSM_PROC_COMM
+	bool
+
 config MSM_SMD
 	bool
 
+config MSM_GPIOMUX
+	bool
+
+config MSM_V2_TLMM
+	bool
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 7046106..b5a7b07 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,16 +1,20 @@
-obj-y += proc_comm.o
-obj-y += io.o idle.o timer.o dma.o
-obj-y += vreg.o
+obj-y += io.o idle.o timer.o
+ifndef CONFIG_ARCH_MSM8X60
 obj-y += acpuclock-arm11.o
-obj-y += clock.o clock-pcom.o
-obj-y += gpio.o
+obj-y += dma.o
+endif
 
 ifdef CONFIG_MSM_VIC
 obj-y += irq-vic.o
 else
+ifndef CONFIG_ARCH_MSM8X60
 obj-y += irq.o
 endif
+endif
 
+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
@@ -19,4 +23,11 @@
 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_MSM7X30) += gpiomux-7x30.o 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
+ifndef CONFIG_MSM_V2_TLMM
+obj-y	+= gpio.o
+endif
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index 7bd72e8..59edecb 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -95,8 +95,6 @@
 
 MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io        = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params	= 0x10000100,
 	.fixup		= halibut_fixup,
diff --git a/arch/arm/mach-msm/board-mahimahi.c b/arch/arm/mach-msm/board-mahimahi.c
index bcbefdf..ef3ebf2 100644
--- a/arch/arm/mach-msm/board-mahimahi.c
+++ b/arch/arm/mach-msm/board-mahimahi.c
@@ -75,8 +75,6 @@
 
 MACHINE_START(MAHIMAHI, "mahimahi")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io        = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params	= 0x20000100,
 	.fixup		= mahimahi_fixup,
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index db9381b..e7a76ef 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -131,8 +131,6 @@
 
 MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io        = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
@@ -143,8 +141,6 @@
 
 MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io        = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
@@ -155,8 +151,6 @@
 
 MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io        = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
@@ -167,8 +161,6 @@
 
 MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io        = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index e329819..05241df 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -39,27 +39,11 @@
 
 extern struct sys_timer msm_timer;
 
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
-static struct msm_gpio uart2_config_data[] = {
-	{ GPIO_CFG(49, 2, GPIO_OUTPUT,  GPIO_PULL_DOWN, GPIO_2MA), "UART2_RFR"},
-	{ GPIO_CFG(50, 2, GPIO_INPUT,   GPIO_PULL_DOWN, GPIO_2MA), "UART2_CTS"},
-	{ GPIO_CFG(51, 2, GPIO_INPUT,   GPIO_PULL_DOWN, GPIO_2MA), "UART2_Rx"},
-	{ GPIO_CFG(52, 2, GPIO_OUTPUT,  GPIO_PULL_DOWN, GPIO_2MA), "UART2_Tx"},
-};
-
-static void msm7x30_init_uart2(void)
-{
-	msm_gpios_request_enable(uart2_config_data,
-			ARRAY_SIZE(uart2_config_data));
-
-}
-#endif
-
 static struct platform_device *devices[] __initdata = {
 #if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER)
         &msm_device_uart2,
 #endif
-
+	&msm_device_smd,
 };
 
 static void __init msm7x30_init_irq(void)
@@ -70,10 +54,6 @@
 static void __init msm7x30_init(void)
 {
 	platform_add_devices(devices, ARRAY_SIZE(devices));
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
-	msm7x30_init_uart2();
-#endif
-
 }
 
 static void __init msm7x30_map_io(void)
@@ -84,8 +64,6 @@
 
 MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io  = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params = PHYS_OFFSET + 0x100,
 	.map_io = msm7x30_map_io,
@@ -96,8 +74,6 @@
 
 MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io  = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params = PHYS_OFFSET + 0x100,
 	.map_io = msm7x30_map_io,
@@ -108,8 +84,6 @@
 
 MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io  = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params = PHYS_OFFSET + 0x100,
 	.map_io = msm7x30_map_io,
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
new file mode 100644
index 0000000..7486a68
--- /dev/null
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -0,0 +1,100 @@
+/* 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/io.h>
+#include <linux/irq.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>
+
+void __iomem *gic_cpu_base_addr;
+
+unsigned long clk_get_max_axi_khz(void)
+{
+	return 0;
+}
+
+static void __init msm8x60_map_io(void)
+{
+	msm_map_msm8x60_io();
+}
+
+static void __init msm8x60_init_irq(void)
+{
+	unsigned int i;
+
+	gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START);
+	gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE;
+	gic_cpu_init(0, MSM_QGIC_CPU_BASE);
+
+	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
+	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
+
+	/* RUMI does not adhere to GIC spec by enabling STIs by default.
+	 * Enable/clear is supposed to be RO for STIs, but is RW on RUMI.
+	 */
+	if (!machine_is_msm8x60_sim())
+		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 void __init msm8x60_init(void)
+{
+}
+
+MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
+	.map_io = msm8x60_map_io,
+	.init_irq = msm8x60_init_irq,
+	.init_machine = msm8x60_init,
+	.timer = &msm_timer,
+MACHINE_END
+
+MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF")
+	.map_io = msm8x60_map_io,
+	.init_irq = msm8x60_init_irq,
+	.init_machine = msm8x60_init,
+	.timer = &msm_timer,
+MACHINE_END
+
+MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR")
+	.map_io = msm8x60_map_io,
+	.init_irq = msm8x60_init_irq,
+	.init_machine = msm8x60_init,
+	.timer = &msm_timer,
+MACHINE_END
+
+MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA")
+	.map_io = msm8x60_map_io,
+	.init_irq = msm8x60_init_irq,
+	.init_machine = msm8x60_init,
+	.timer = &msm_timer,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index e3cc807..ed2af4a 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -35,21 +35,50 @@
 
 extern struct sys_timer msm_timer;
 
-static struct msm_gpio uart3_config_data[] = {
-	{ GPIO_CFG(86, 1, GPIO_INPUT,   GPIO_PULL_DOWN, GPIO_2MA), "UART2_Rx"},
-	{ GPIO_CFG(87, 1, GPIO_OUTPUT,  GPIO_PULL_DOWN, GPIO_2MA), "UART2_Tx"},
+static const resource_size_t qsd8x50_surf_smc91x_base __initdata = 0x70000300;
+static const unsigned        qsd8x50_surf_smc91x_gpio __initdata = 156;
+
+/* Leave smc91x resources empty here, as we'll fill them in
+ * at run-time: they vary from board to board, and the true
+ * configuration won't be known until boot.
+ */
+static struct resource smc91x_resources[] __initdata = {
+	[0] = {
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags = IORESOURCE_IRQ,
+	},
 };
 
+static struct platform_device smc91x_device __initdata = {
+	.name           = "smc91x",
+	.id             = 0,
+	.num_resources  = ARRAY_SIZE(smc91x_resources),
+	.resource       = smc91x_resources,
+};
+
+static int __init msm_init_smc91x(void)
+{
+	if (machine_is_qsd8x50_surf()) {
+		smc91x_resources[0].start = qsd8x50_surf_smc91x_base;
+		smc91x_resources[0].end   = qsd8x50_surf_smc91x_base + 0xff;
+		smc91x_resources[1].start =
+			gpio_to_irq(qsd8x50_surf_smc91x_gpio);
+		smc91x_resources[1].end   =
+			gpio_to_irq(qsd8x50_surf_smc91x_gpio);
+		platform_device_register(&smc91x_device);
+	}
+
+	return 0;
+}
+module_init(msm_init_smc91x);
+
 static struct platform_device *devices[] __initdata = {
 	&msm_device_uart3,
+	&msm_device_smd,
 };
 
-static void msm8x50_init_uart3(void)
-{
-	msm_gpios_request_enable(uart3_config_data,
-				ARRAY_SIZE(uart3_config_data));
-}
-
 static void __init qsd8x50_map_io(void)
 {
 	msm_map_qsd8x50_io();
@@ -64,14 +93,11 @@
 
 static void __init qsd8x50_init(void)
 {
-	msm8x50_init_uart3();
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
 MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io  = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params = PHYS_OFFSET + 0x100,
 	.map_io = qsd8x50_map_io,
@@ -82,8 +108,6 @@
 
 MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io  = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params = PHYS_OFFSET + 0x100,
 	.map_io = qsd8x50_map_io,
diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c
index 2bc1b9d..8919ffb1 100644
--- a/arch/arm/mach-msm/board-sapphire.c
+++ b/arch/arm/mach-msm/board-sapphire.c
@@ -106,8 +106,6 @@
 MACHINE_START(SAPPHIRE, "sapphire")
 /* Maintainer: Brian Swetland <swetland@google.com> */
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io        = MSM_DEBUG_UART_PHYS,
-	.io_pg_offst    = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params    = PHYS_OFFSET + 0x100,
 	.fixup          = sapphire_fixup,
diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c
index 469e0be..73f1460 100644
--- a/arch/arm/mach-msm/board-trout.c
+++ b/arch/arm/mach-msm/board-trout.c
@@ -93,8 +93,6 @@
 
 MACHINE_START(TROUT, "HTC Dream")
 #ifdef CONFIG_MSM_DEBUG_UART
-	.phys_io	= MSM_DEBUG_UART_PHYS,
-	.io_pg_offst	= ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
 #endif
 	.boot_params	= 0x10000100,
 	.fixup		= trout_fixup,
diff --git a/arch/arm/mach-msm/clock-dummy.c b/arch/arm/mach-msm/clock-dummy.c
new file mode 100644
index 0000000..1250d22
--- /dev/null
+++ b/arch/arm/mach-msm/clock-dummy.c
@@ -0,0 +1,54 @@
+/* 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/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index b449e8a..7fcf2e3 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -51,6 +51,11 @@
 	.resource	= resources_uart2,
 };
 
+struct platform_device msm_device_smd = {
+	.name   = "msm_smd",
+	.id     = -1,
+};
+
 struct clk msm_clocks_7x30[] = {
 	CLK_PCOM("adm_clk",	ADM_CLK,	NULL, 0),
 	CLK_PCOM("adsp_clk",	ADSP_CLK,	NULL, 0),
diff --git a/arch/arm/mach-msm/devices-msm8x60-iommu.c b/arch/arm/mach-msm/devices-msm8x60-iommu.c
new file mode 100644
index 0000000..89b9d44
--- /dev/null
+++ b/arch/arm/mach-msm/devices-msm8x60-iommu.c
@@ -0,0 +1,883 @@
+/* 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 platform_device msm_root_iommu_dev = {
+	.name = "msm_iommu",
+	.id = -1,
+};
+
+static struct msm_iommu_dev jpegd_smmu = {
+	.name = "jpegd",
+	.clk_rate = -1
+};
+
+static struct msm_iommu_dev vpe_smmu = {
+	.name = "vpe"
+};
+
+static struct msm_iommu_dev mdp0_smmu = {
+	.name = "mdp0"
+};
+
+static struct msm_iommu_dev mdp1_smmu = {
+	.name = "mdp1"
+};
+
+static struct msm_iommu_dev rot_smmu = {
+	.name = "rot"
+};
+
+static struct msm_iommu_dev ijpeg_smmu = {
+	.name = "ijpeg"
+};
+
+static struct msm_iommu_dev vfe_smmu = {
+	.name = "vfe",
+	.clk_rate = -1
+};
+
+static struct msm_iommu_dev vcodec_a_smmu = {
+	.name = "vcodec_a"
+};
+
+static struct msm_iommu_dev vcodec_b_smmu = {
+	.name = "vcodec_b"
+};
+
+static struct msm_iommu_dev gfx3d_smmu = {
+	.name = "gfx3d",
+	.clk_rate = 27000000
+};
+
+static struct msm_iommu_dev gfx2d0_smmu = {
+	.name = "gfx2d0",
+	.clk_rate = 27000000
+};
+
+static struct platform_device msm_device_smmu_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_smmu_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_smmu_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_smmu_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_smmu_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_smmu_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_smmu_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_smmu_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_smmu_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_smmu_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_smmu_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,
+};
+
+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_rbpa_ctx = {
+	.name = "gfx3d_rbpa",
+	.num = 0,
+	.mids = {-1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_cpvgttc_ctx = {
+	.name = "gfx3d_cpvgttc",
+	.num = 1,
+	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_smmu_ctx = {
+	.name = "gfx3d_smmu",
+	.num = 2,
+	.mids = {8, 9, 10, 11, 12, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx2d0_pixv1_ctx = {
+	.name = "gfx2d0_pixv1_smmu",
+	.num = 0,
+	.mids = {0, 3, 4, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx2d0_texv3_ctx = {
+	.name = "gfx2d0_texv3_smmu",
+	.num = 1,
+	.mids = {1, 6, 7, -1}
+};
+
+static struct platform_device msm_device_jpegd_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 0,
+	.dev = {
+		.parent = &msm_device_smmu_jpegd.dev,
+	},
+};
+
+static struct platform_device msm_device_jpegd_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 1,
+	.dev = {
+		.parent = &msm_device_smmu_jpegd.dev,
+	},
+};
+
+static struct platform_device msm_device_vpe_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 2,
+	.dev = {
+		.parent = &msm_device_smmu_vpe.dev,
+	},
+};
+
+static struct platform_device msm_device_vpe_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 3,
+	.dev = {
+		.parent = &msm_device_smmu_vpe.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_vg1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 4,
+	.dev = {
+		.parent = &msm_device_smmu_mdp0.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_rgb1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 5,
+	.dev = {
+		.parent = &msm_device_smmu_mdp0.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_vg2_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 6,
+	.dev = {
+		.parent = &msm_device_smmu_mdp1.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_rgb2_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 7,
+	.dev = {
+		.parent = &msm_device_smmu_mdp1.dev,
+	},
+};
+
+static struct platform_device msm_device_rot_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 8,
+	.dev = {
+		.parent = &msm_device_smmu_rot.dev,
+	},
+};
+
+static struct platform_device msm_device_rot_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 9,
+	.dev = {
+		.parent = &msm_device_smmu_rot.dev,
+	},
+};
+
+static struct platform_device msm_device_ijpeg_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 10,
+	.dev = {
+		.parent = &msm_device_smmu_ijpeg.dev,
+	},
+};
+
+static struct platform_device msm_device_ijpeg_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 11,
+	.dev = {
+		.parent = &msm_device_smmu_ijpeg.dev,
+	},
+};
+
+static struct platform_device msm_device_vfe_imgwr_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 12,
+	.dev = {
+		.parent = &msm_device_smmu_vfe.dev,
+	},
+};
+
+static struct platform_device msm_device_vfe_misc_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 13,
+	.dev = {
+		.parent = &msm_device_smmu_vfe.dev,
+	},
+};
+
+static struct platform_device msm_device_vcodec_a_stream_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 14,
+	.dev = {
+		.parent = &msm_device_smmu_vcodec_a.dev,
+	},
+};
+
+static struct platform_device msm_device_vcodec_a_mm1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 15,
+	.dev = {
+		.parent = &msm_device_smmu_vcodec_a.dev,
+	},
+};
+
+static struct platform_device msm_device_vcodec_b_mm2_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 16,
+	.dev = {
+		.parent = &msm_device_smmu_vcodec_b.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx3d_rbpa_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 17,
+	.dev = {
+		.parent = &msm_device_smmu_gfx3d.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx3d_cpvgttc_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 18,
+	.dev = {
+		.parent = &msm_device_smmu_gfx3d.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx3d_smmu_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 19,
+	.dev = {
+		.parent = &msm_device_smmu_gfx3d.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx2d0_pixv1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 20,
+	.dev = {
+		.parent = &msm_device_smmu_gfx2d0.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx2d0_texv3_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 21,
+	.dev = {
+		.parent = &msm_device_smmu_gfx2d0.dev,
+	},
+};
+
+static struct platform_device *msm_iommu_devs[] = {
+	&msm_device_smmu_jpegd,
+	&msm_device_smmu_vpe,
+	&msm_device_smmu_mdp0,
+	&msm_device_smmu_mdp1,
+	&msm_device_smmu_rot,
+	&msm_device_smmu_ijpeg,
+	&msm_device_smmu_vfe,
+	&msm_device_smmu_vcodec_a,
+	&msm_device_smmu_vcodec_b,
+	&msm_device_smmu_gfx3d,
+	&msm_device_smmu_gfx2d0,
+};
+
+static struct msm_iommu_dev *msm_iommu_data[] = {
+	&jpegd_smmu,
+	&vpe_smmu,
+	&mdp0_smmu,
+	&mdp1_smmu,
+	&rot_smmu,
+	&ijpeg_smmu,
+	&vfe_smmu,
+	&vcodec_a_smmu,
+	&vcodec_b_smmu,
+	&gfx3d_smmu,
+	&gfx2d0_smmu,
+};
+
+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_rbpa_ctx,
+	&msm_device_gfx3d_cpvgttc_ctx,
+	&msm_device_gfx3d_smmu_ctx,
+	&msm_device_gfx2d0_pixv1_ctx,
+	&msm_device_gfx2d0_texv3_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_rbpa_ctx,
+	&gfx3d_cpvgttc_ctx,
+	&gfx3d_smmu_ctx,
+	&gfx2d0_pixv1_ctx,
+	&gfx2d0_texv3_ctx,
+};
+
+static int 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 smmu 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 smmu 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 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 4d4a507..6fe67c5 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -48,6 +48,11 @@
 	.resource	= resources_uart3,
 };
 
+struct platform_device msm_device_smd = {
+	.name   = "msm_smd",
+	.id     = -1,
+};
+
 struct clk msm_clocks_8x50[] = {
 	CLK_PCOM("adm_clk",	ADM_CLK,	NULL, 0),
 	CLK_PCOM("ebi1_clk",	EBI1_CLK,	NULL, CLK_MIN),
diff --git a/arch/arm/mach-msm/gpio.c b/arch/arm/mach-msm/gpio.c
index bc32c84..33051b5 100644
--- a/arch/arm/mach-msm/gpio.c
+++ b/arch/arm/mach-msm/gpio.c
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-msm/gpio.c
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -14,72 +14,363 @@
  *
  */
 
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/module.h>
-#include <mach/gpio.h>
-#include "proc_comm.h"
+#include "gpio_hw.h"
+#include "gpiomux.h"
 
-int gpio_tlmm_config(unsigned config, unsigned disable)
-{
-	return msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, &disable);
-}
-EXPORT_SYMBOL(gpio_tlmm_config);
+#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
 
-int msm_gpios_enable(const struct msm_gpio *table, int size)
-{
-	int rc;
-	int i;
-	const struct msm_gpio *g;
-	for (i = 0; i < size; i++) {
-		g = table + i;
-		rc = gpio_tlmm_config(g->gpio_cfg, GPIO_ENABLE);
-		if (rc) {
-			pr_err("gpio_tlmm_config(0x%08x, GPIO_ENABLE)"
-			       " <%s> failed: %d\n",
-			       g->gpio_cfg, g->label ?: "?", rc);
-			pr_err("pin %d func %d dir %d pull %d drvstr %d\n",
-			       GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
-			       GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
-			       GPIO_DRVSTR(g->gpio_cfg));
-			goto err;
-		}
+#define MSM_GPIO_BANK(bank, first, last)				\
+	{								\
+		.regs = {						\
+			.out =         MSM_GPIO_OUT_##bank,		\
+			.in =          MSM_GPIO_IN_##bank,		\
+			.int_status =  MSM_GPIO_INT_STATUS_##bank,	\
+			.int_clear =   MSM_GPIO_INT_CLEAR_##bank,	\
+			.int_en =      MSM_GPIO_INT_EN_##bank,		\
+			.int_edge =    MSM_GPIO_INT_EDGE_##bank,	\
+			.int_pos =     MSM_GPIO_INT_POS_##bank,		\
+			.oe =          MSM_GPIO_OE_##bank,		\
+		},							\
+		.chip = {						\
+			.base = (first),				\
+			.ngpio = (last) - (first) + 1,			\
+			.get = msm_gpio_get,				\
+			.set = msm_gpio_set,				\
+			.direction_input = msm_gpio_direction_input,	\
+			.direction_output = msm_gpio_direction_output,	\
+			.to_irq = msm_gpio_to_irq,			\
+			.request = msm_gpio_request,			\
+			.free = msm_gpio_free,				\
+		}							\
 	}
+
+#define MSM_GPIO_BROKEN_INT_CLEAR 1
+
+struct msm_gpio_regs {
+	void __iomem *out;
+	void __iomem *in;
+	void __iomem *int_status;
+	void __iomem *int_clear;
+	void __iomem *int_en;
+	void __iomem *int_edge;
+	void __iomem *int_pos;
+	void __iomem *oe;
+};
+
+struct msm_gpio_chip {
+	spinlock_t		lock;
+	struct gpio_chip	chip;
+	struct msm_gpio_regs	regs;
+#if MSM_GPIO_BROKEN_INT_CLEAR
+	unsigned                int_status_copy;
+#endif
+	unsigned int            both_edge_detect;
+	unsigned int            int_enable[2]; /* 0: awake, 1: sleep */
+};
+
+static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
+			  unsigned offset, unsigned on)
+{
+	unsigned mask = BIT(offset);
+	unsigned val;
+
+	val = readl(msm_chip->regs.out);
+	if (on)
+		writel(val | mask, msm_chip->regs.out);
+	else
+		writel(val & ~mask, msm_chip->regs.out);
 	return 0;
-err:
-	msm_gpios_disable(table, i);
-	return rc;
 }
-EXPORT_SYMBOL(msm_gpios_enable);
 
-void msm_gpios_disable(const struct msm_gpio *table, int size)
+static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
 {
-	int rc;
-	int i;
-	const struct msm_gpio *g;
-	for (i = size-1; i >= 0; i--) {
-		g = table + i;
-		rc = gpio_tlmm_config(g->gpio_cfg, GPIO_DISABLE);
-		if (rc) {
-			pr_err("gpio_tlmm_config(0x%08x, GPIO_DISABLE)"
-			       " <%s> failed: %d\n",
-			       g->gpio_cfg, g->label ?: "?", rc);
-			pr_err("pin %d func %d dir %d pull %d drvstr %d\n",
-			       GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
-			       GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
-			       GPIO_DRVSTR(g->gpio_cfg));
+	int loop_limit = 100;
+	unsigned pol, val, val2, intstat;
+	do {
+		val = readl(msm_chip->regs.in);
+		pol = readl(msm_chip->regs.int_pos);
+		pol = (pol & ~msm_chip->both_edge_detect) |
+		      (~val & msm_chip->both_edge_detect);
+		writel(pol, msm_chip->regs.int_pos);
+		intstat = readl(msm_chip->regs.int_status);
+		val2 = readl(msm_chip->regs.in);
+		if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
+			return;
+	} while (loop_limit-- > 0);
+	printk(KERN_ERR "msm_gpio_update_both_edge_detect, "
+	       "failed to reach stable state %x != %x\n", val, val2);
+}
+
+static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
+					unsigned offset)
+{
+	unsigned bit = BIT(offset);
+
+#if MSM_GPIO_BROKEN_INT_CLEAR
+	/* Save interrupts that already triggered before we loose them. */
+	/* Any interrupt that triggers between the read of int_status */
+	/* and the write to int_clear will still be lost though. */
+	msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
+	msm_chip->int_status_copy &= ~bit;
+#endif
+	writel(bit, msm_chip->regs.int_clear);
+	msm_gpio_update_both_edge_detect(msm_chip);
+	return 0;
+}
+
+static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct msm_gpio_chip *msm_chip;
+	unsigned long irq_flags;
+
+	msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+	writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe);
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+	return 0;
+}
+
+static int
+msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct msm_gpio_chip *msm_chip;
+	unsigned long irq_flags;
+
+	msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+	msm_gpio_write(msm_chip, offset, value);
+	writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe);
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+	return 0;
+}
+
+static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct msm_gpio_chip *msm_chip;
+
+	msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+	return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
+}
+
+static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct msm_gpio_chip *msm_chip;
+	unsigned long irq_flags;
+
+	msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+	msm_gpio_write(msm_chip, offset, value);
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return MSM_GPIO_TO_INT(chip->base + offset);
+}
+
+#ifdef CONFIG_MSM_GPIOMUX
+static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	return msm_gpiomux_get(chip->base + offset);
+}
+
+static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	msm_gpiomux_put(chip->base + offset);
+}
+#else
+#define msm_gpio_request NULL
+#define msm_gpio_free NULL
+#endif
+
+struct msm_gpio_chip msm_gpio_chips[] = {
+#if defined(CONFIG_ARCH_MSM7X00A)
+	MSM_GPIO_BANK(0,   0,  15),
+	MSM_GPIO_BANK(1,  16,  42),
+	MSM_GPIO_BANK(2,  43,  67),
+	MSM_GPIO_BANK(3,  68,  94),
+	MSM_GPIO_BANK(4,  95, 106),
+	MSM_GPIO_BANK(5, 107, 121),
+#elif defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X27)
+	MSM_GPIO_BANK(0,   0,  15),
+	MSM_GPIO_BANK(1,  16,  42),
+	MSM_GPIO_BANK(2,  43,  67),
+	MSM_GPIO_BANK(3,  68,  94),
+	MSM_GPIO_BANK(4,  95, 106),
+	MSM_GPIO_BANK(5, 107, 132),
+#elif defined(CONFIG_ARCH_MSM7X30)
+	MSM_GPIO_BANK(0,   0,  15),
+	MSM_GPIO_BANK(1,  16,  43),
+	MSM_GPIO_BANK(2,  44,  67),
+	MSM_GPIO_BANK(3,  68,  94),
+	MSM_GPIO_BANK(4,  95, 106),
+	MSM_GPIO_BANK(5, 107, 133),
+	MSM_GPIO_BANK(6, 134, 150),
+	MSM_GPIO_BANK(7, 151, 181),
+#elif defined(CONFIG_ARCH_QSD8X50)
+	MSM_GPIO_BANK(0,   0,  15),
+	MSM_GPIO_BANK(1,  16,  42),
+	MSM_GPIO_BANK(2,  43,  67),
+	MSM_GPIO_BANK(3,  68,  94),
+	MSM_GPIO_BANK(4,  95, 103),
+	MSM_GPIO_BANK(5, 104, 121),
+	MSM_GPIO_BANK(6, 122, 152),
+	MSM_GPIO_BANK(7, 153, 164),
+#endif
+};
+
+static void msm_gpio_irq_ack(unsigned int irq)
+{
+	unsigned long irq_flags;
+	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+	msm_gpio_clear_detect_status(msm_chip,
+				     irq - gpio_to_irq(msm_chip->chip.base));
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_mask(unsigned int irq)
+{
+	unsigned long irq_flags;
+	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+	unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+	/* level triggered interrupts are also latched */
+	if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+		msm_gpio_clear_detect_status(msm_chip, offset);
+	msm_chip->int_enable[0] &= ~BIT(offset);
+	writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_unmask(unsigned int irq)
+{
+	unsigned long irq_flags;
+	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+	unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+	/* level triggered interrupts are also latched */
+	if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+		msm_gpio_clear_detect_status(msm_chip, offset);
+	msm_chip->int_enable[0] |= BIT(offset);
+	writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+{
+	unsigned long irq_flags;
+	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+	unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+
+	if (on)
+		msm_chip->int_enable[1] |= BIT(offset);
+	else
+		msm_chip->int_enable[1] &= ~BIT(offset);
+
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+	return 0;
+}
+
+static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
+{
+	unsigned long irq_flags;
+	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+	unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+	unsigned val, mask = BIT(offset);
+
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+	val = readl(msm_chip->regs.int_edge);
+	if (flow_type & IRQ_TYPE_EDGE_BOTH) {
+		writel(val | mask, msm_chip->regs.int_edge);
+		irq_desc[irq].handle_irq = handle_edge_irq;
+	} else {
+		writel(val & ~mask, msm_chip->regs.int_edge);
+		irq_desc[irq].handle_irq = handle_level_irq;
+	}
+	if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+		msm_chip->both_edge_detect |= mask;
+		msm_gpio_update_both_edge_detect(msm_chip);
+	} else {
+		msm_chip->both_edge_detect &= ~mask;
+		val = readl(msm_chip->regs.int_pos);
+		if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
+			writel(val | mask, msm_chip->regs.int_pos);
+		else
+			writel(val & ~mask, msm_chip->regs.int_pos);
+	}
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+	return 0;
+}
+
+static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int i, j, mask;
+	unsigned val;
+
+	for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
+		struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
+		val = readl(msm_chip->regs.int_status);
+		val &= msm_chip->int_enable[0];
+		while (val) {
+			mask = val & -val;
+			j = fls(mask) - 1;
+			/* printk("%s %08x %08x bit %d gpio %d irq %d\n",
+				__func__, v, m, j, msm_chip->chip.start + j,
+				FIRST_GPIO_IRQ + msm_chip->chip.start + j); */
+			val &= ~mask;
+			generic_handle_irq(FIRST_GPIO_IRQ +
+					   msm_chip->chip.base + j);
 		}
 	}
+	desc->chip->ack(irq);
 }
-EXPORT_SYMBOL(msm_gpios_disable);
 
-int msm_gpios_request_enable(const struct msm_gpio *table, int size)
-{
-	int rc = msm_gpios_enable(table, size);
-	return rc;
-}
-EXPORT_SYMBOL(msm_gpios_request_enable);
+static struct irq_chip msm_gpio_irq_chip = {
+	.name      = "msmgpio",
+	.ack       = msm_gpio_irq_ack,
+	.mask      = msm_gpio_irq_mask,
+	.unmask    = msm_gpio_irq_unmask,
+	.set_wake  = msm_gpio_irq_set_wake,
+	.set_type  = msm_gpio_irq_set_type,
+};
 
-void msm_gpios_disable_free(const struct msm_gpio *table, int size)
+static int __init msm_init_gpio(void)
 {
-	msm_gpios_disable(table, size);
+	int i, j = 0;
+
+	for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
+		if (i - FIRST_GPIO_IRQ >=
+			msm_gpio_chips[j].chip.base +
+			msm_gpio_chips[j].chip.ngpio)
+			j++;
+		set_irq_chip_data(i, &msm_gpio_chips[j]);
+		set_irq_chip(i, &msm_gpio_irq_chip);
+		set_irq_handler(i, handle_edge_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
+		spin_lock_init(&msm_gpio_chips[i].lock);
+		writel(0, msm_gpio_chips[i].regs.int_en);
+		gpiochip_add(&msm_gpio_chips[i].chip);
+	}
+
+	set_irq_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
+	set_irq_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
+	set_irq_wake(INT_GPIO_GROUP1, 1);
+	set_irq_wake(INT_GPIO_GROUP2, 2);
+	return 0;
 }
-EXPORT_SYMBOL(msm_gpios_disable_free);
+
+postcore_initcall(msm_init_gpio);
diff --git a/arch/arm/mach-msm/gpio_hw.h b/arch/arm/mach-msm/gpio_hw.h
new file mode 100644
index 0000000..6b50660
--- /dev/null
+++ b/arch/arm/mach-msm/gpio_hw.h
@@ -0,0 +1,278 @@
+/* arch/arm/mach-msm/gpio_hw.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Brian Swetland <swetland@google.com>
+ * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_GPIO_HW_H
+#define __ARCH_ARM_MACH_MSM_GPIO_HW_H
+
+#include <mach/msm_iomap.h>
+
+/* see 80-VA736-2 Rev C pp 695-751
+**
+** These are actually the *shadow* gpio registers, since the
+** real ones (which allow full access) are only available to the
+** ARM9 side of the world.
+**
+** Since the _BASE need to be page-aligned when we're mapping them
+** to virtual addresses, adjust for the additional offset in these
+** macros.
+*/
+
+#if defined(CONFIG_ARCH_MSM7X30)
+#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off))
+#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off))
+#else
+#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
+#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
+#endif
+
+#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X25) ||\
+    defined(CONFIG_ARCH_MSM7X27)
+
+/* output value */
+#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)  /* gpio  15-0  */
+#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)  /* gpio  42-16 */
+#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)  /* gpio  67-43 */
+#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)  /* gpio  94-68 */
+#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)  /* gpio 106-95 */
+#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x50)  /* gpio 107-121 */
+
+/* same pin map as above, output enable */
+#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x10)
+#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
+#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x14)
+#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x18)
+#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x1C)
+#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x54)
+
+/* same pin map as above, input read */
+#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x34)
+#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
+#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x38)
+#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x3C)
+#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x40)
+#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x44)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x60)
+#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
+#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x64)
+#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x68)
+#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x6C)
+#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0xC0)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x70)
+#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
+#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x74)
+#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x78)
+#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x7C)
+#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xBC)
+
+/* same pin map as above, interrupt enable */
+#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0x80)
+#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
+#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0x84)
+#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0x88)
+#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0x8C)
+#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xB8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0x90)
+#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
+#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0x94)
+#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0x98)
+#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0x9C)
+#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xB4)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xA0)
+#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
+#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xA4)
+#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xA8)
+#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xAC)
+#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0xB0)
+
+#endif
+
+#if defined(CONFIG_ARCH_QSD8X50)
+/* output value */
+#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)  /* gpio  15-0   */
+#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)  /* gpio  42-16  */
+#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)  /* gpio  67-43  */
+#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)  /* gpio  94-68  */
+#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)  /* gpio 103-95  */
+#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x10)  /* gpio 121-104 */
+#define MSM_GPIO_OUT_6         MSM_GPIO1_REG(0x14)  /* gpio 152-122 */
+#define MSM_GPIO_OUT_7         MSM_GPIO1_REG(0x18)  /* gpio 164-153 */
+
+/* same pin map as above, output enable */
+#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x20)
+#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
+#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x24)
+#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x28)
+#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x2C)
+#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x30)
+#define MSM_GPIO_OE_6          MSM_GPIO1_REG(0x34)
+#define MSM_GPIO_OE_7          MSM_GPIO1_REG(0x38)
+
+/* same pin map as above, input read */
+#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x50)
+#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
+#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x54)
+#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x58)
+#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x5C)
+#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x60)
+#define MSM_GPIO_IN_6          MSM_GPIO1_REG(0x64)
+#define MSM_GPIO_IN_7          MSM_GPIO1_REG(0x68)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x70)
+#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
+#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x74)
+#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x78)
+#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x7C)
+#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0x80)
+#define MSM_GPIO_INT_EDGE_6    MSM_GPIO1_REG(0x84)
+#define MSM_GPIO_INT_EDGE_7    MSM_GPIO1_REG(0x88)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x90)
+#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
+#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x94)
+#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x98)
+#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x9C)
+#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xA0)
+#define MSM_GPIO_INT_POS_6     MSM_GPIO1_REG(0xA4)
+#define MSM_GPIO_INT_POS_7     MSM_GPIO1_REG(0xA8)
+
+/* same pin map as above, interrupt enable */
+#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0xB0)
+#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
+#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0xB4)
+#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0xB8)
+#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0xBC)
+#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xC0)
+#define MSM_GPIO_INT_EN_6      MSM_GPIO1_REG(0xC4)
+#define MSM_GPIO_INT_EN_7      MSM_GPIO1_REG(0xC8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0xD0)
+#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
+#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0xD4)
+#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0xD8)
+#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0xDC)
+#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xE0)
+#define MSM_GPIO_INT_CLEAR_6   MSM_GPIO1_REG(0xE4)
+#define MSM_GPIO_INT_CLEAR_7   MSM_GPIO1_REG(0xE8)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xF0)
+#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
+#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xF4)
+#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xF8)
+#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xFC)
+#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0x100)
+#define MSM_GPIO_INT_STATUS_6  MSM_GPIO1_REG(0x104)
+#define MSM_GPIO_INT_STATUS_7  MSM_GPIO1_REG(0x108)
+
+#endif
+
+#if defined(CONFIG_ARCH_MSM7X30)
+
+/* output value */
+#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)   /* gpio  15-0   */
+#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)   /* gpio  43-16  */
+#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)   /* gpio  67-44  */
+#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)   /* gpio  94-68  */
+#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)   /* gpio 106-95  */
+#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x50)   /* gpio 133-107 */
+#define MSM_GPIO_OUT_6         MSM_GPIO1_REG(0xC4)   /* gpio 150-134 */
+#define MSM_GPIO_OUT_7         MSM_GPIO1_REG(0x214)  /* gpio 181-151 */
+
+/* same pin map as above, output enable */
+#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x10)
+#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
+#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x14)
+#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x18)
+#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x1C)
+#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x54)
+#define MSM_GPIO_OE_6          MSM_GPIO1_REG(0xC8)
+#define MSM_GPIO_OE_7          MSM_GPIO1_REG(0x218)
+
+/* same pin map as above, input read */
+#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x34)
+#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
+#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x38)
+#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x3C)
+#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x40)
+#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x44)
+#define MSM_GPIO_IN_6          MSM_GPIO1_REG(0xCC)
+#define MSM_GPIO_IN_7          MSM_GPIO1_REG(0x21C)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x60)
+#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
+#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x64)
+#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x68)
+#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x6C)
+#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0xC0)
+#define MSM_GPIO_INT_EDGE_6    MSM_GPIO1_REG(0xD0)
+#define MSM_GPIO_INT_EDGE_7    MSM_GPIO1_REG(0x240)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x70)
+#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
+#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x74)
+#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x78)
+#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x7C)
+#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xBC)
+#define MSM_GPIO_INT_POS_6     MSM_GPIO1_REG(0xD4)
+#define MSM_GPIO_INT_POS_7     MSM_GPIO1_REG(0x228)
+
+/* same pin map as above, interrupt enable */
+#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0x80)
+#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
+#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0x84)
+#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0x88)
+#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0x8C)
+#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xB8)
+#define MSM_GPIO_INT_EN_6      MSM_GPIO1_REG(0xD8)
+#define MSM_GPIO_INT_EN_7      MSM_GPIO1_REG(0x22C)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0x90)
+#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
+#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0x94)
+#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0x98)
+#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0x9C)
+#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xB4)
+#define MSM_GPIO_INT_CLEAR_6   MSM_GPIO1_REG(0xDC)
+#define MSM_GPIO_INT_CLEAR_7   MSM_GPIO1_REG(0x230)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xA0)
+#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
+#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xA4)
+#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xA8)
+#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xAC)
+#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0xB0)
+#define MSM_GPIO_INT_STATUS_6  MSM_GPIO1_REG(0xE0)
+#define MSM_GPIO_INT_STATUS_7  MSM_GPIO1_REG(0x234)
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/gpiomux-7x30.c b/arch/arm/mach-msm/gpiomux-7x30.c
new file mode 100644
index 0000000..6ce41c5
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-7x30.c
@@ -0,0 +1,38 @@
+/* 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
new file mode 100644
index 0000000..4406e0f
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-8x50.c
@@ -0,0 +1,28 @@
+/* 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] = {
+	[86] = { /* UART3 RX */
+		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+			     GPIOMUX_FUNC_1 | GPIOMUX_VALID,
+	},
+	[87] = { /* UART3 TX */
+		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+			     GPIOMUX_FUNC_1 | GPIOMUX_VALID,
+	},
+};
diff --git a/arch/arm/mach-msm/gpiomux-8x60.c b/arch/arm/mach-msm/gpiomux-8x60.c
new file mode 100644
index 0000000..7b380b3
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-8x60.c
@@ -0,0 +1,19 @@
+/* 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] = {};
diff --git a/arch/arm/mach-msm/gpiomux-v1.c b/arch/arm/mach-msm/gpiomux-v1.c
new file mode 100644
index 0000000..27de2ab
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-v1.c
@@ -0,0 +1,33 @@
+/* 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 "gpiomux.h"
+#include "proc_comm.h"
+
+void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
+{
+	unsigned tlmm_config  = (val & ~GPIOMUX_CTL_MASK) |
+				((gpio & 0x3ff) << 4);
+	unsigned tlmm_disable = 0;
+	int rc;
+
+	rc = msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX,
+			   &tlmm_config, &tlmm_disable);
+	if (rc)
+		pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n",
+		       __func__, rc, tlmm_config, tlmm_disable);
+}
diff --git a/arch/arm/mach-msm/gpiomux-v1.h b/arch/arm/mach-msm/gpiomux-v1.h
new file mode 100644
index 0000000..71d86fe
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-v1.h
@@ -0,0 +1,67 @@
+/* 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.
+ */
+#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
+#define __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
+
+#if defined(CONFIG_ARCH_MSM7X30)
+#define GPIOMUX_NGPIOS 182
+#elif defined(CONFIG_ARCH_QSD8X50)
+#define GPIOMUX_NGPIOS 165
+#else
+#define GPIOMUX_NGPIOS 133
+#endif
+
+typedef u32 gpiomux_config_t;
+
+enum {
+	GPIOMUX_DRV_2MA  = 0UL << 17,
+	GPIOMUX_DRV_4MA  = 1UL << 17,
+	GPIOMUX_DRV_6MA  = 2UL << 17,
+	GPIOMUX_DRV_8MA  = 3UL << 17,
+	GPIOMUX_DRV_10MA = 4UL << 17,
+	GPIOMUX_DRV_12MA = 5UL << 17,
+	GPIOMUX_DRV_14MA = 6UL << 17,
+	GPIOMUX_DRV_16MA = 7UL << 17,
+};
+
+enum {
+	GPIOMUX_FUNC_GPIO = 0UL,
+	GPIOMUX_FUNC_1    = 1UL,
+	GPIOMUX_FUNC_2    = 2UL,
+	GPIOMUX_FUNC_3    = 3UL,
+	GPIOMUX_FUNC_4    = 4UL,
+	GPIOMUX_FUNC_5    = 5UL,
+	GPIOMUX_FUNC_6    = 6UL,
+	GPIOMUX_FUNC_7    = 7UL,
+	GPIOMUX_FUNC_8    = 8UL,
+	GPIOMUX_FUNC_9    = 9UL,
+	GPIOMUX_FUNC_A    = 10UL,
+	GPIOMUX_FUNC_B    = 11UL,
+	GPIOMUX_FUNC_C    = 12UL,
+	GPIOMUX_FUNC_D    = 13UL,
+	GPIOMUX_FUNC_E    = 14UL,
+	GPIOMUX_FUNC_F    = 15UL,
+};
+
+enum {
+	GPIOMUX_PULL_NONE   = 0UL << 15,
+	GPIOMUX_PULL_DOWN   = 1UL << 15,
+	GPIOMUX_PULL_KEEPER = 2UL << 15,
+	GPIOMUX_PULL_UP     = 3UL << 15,
+};
+
+#endif
diff --git a/arch/arm/mach-msm/gpiomux-v2.c b/arch/arm/mach-msm/gpiomux-v2.c
new file mode 100644
index 0000000..273396d
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-v2.c
@@ -0,0 +1,25 @@
+/* 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/io.h>
+#include <mach/msm_iomap.h>
+#include "gpiomux.h"
+
+void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
+{
+	writel(val & ~GPIOMUX_CTL_MASK,
+	       MSM_TLMM_BASE + 0x1000 + (0x10 * gpio));
+}
diff --git a/arch/arm/mach-msm/gpiomux-v2.h b/arch/arm/mach-msm/gpiomux-v2.h
new file mode 100644
index 0000000..3bf10e7
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-v2.h
@@ -0,0 +1,61 @@
+/* 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.
+ */
+#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
+#define __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
+
+#define GPIOMUX_NGPIOS 173
+
+typedef u16 gpiomux_config_t;
+
+enum {
+	GPIOMUX_DRV_2MA  = 0UL << 6,
+	GPIOMUX_DRV_4MA  = 1UL << 6,
+	GPIOMUX_DRV_6MA  = 2UL << 6,
+	GPIOMUX_DRV_8MA  = 3UL << 6,
+	GPIOMUX_DRV_10MA = 4UL << 6,
+	GPIOMUX_DRV_12MA = 5UL << 6,
+	GPIOMUX_DRV_14MA = 6UL << 6,
+	GPIOMUX_DRV_16MA = 7UL << 6,
+};
+
+enum {
+	GPIOMUX_FUNC_GPIO = 0UL  << 2,
+	GPIOMUX_FUNC_1    = 1UL  << 2,
+	GPIOMUX_FUNC_2    = 2UL  << 2,
+	GPIOMUX_FUNC_3    = 3UL  << 2,
+	GPIOMUX_FUNC_4    = 4UL  << 2,
+	GPIOMUX_FUNC_5    = 5UL  << 2,
+	GPIOMUX_FUNC_6    = 6UL  << 2,
+	GPIOMUX_FUNC_7    = 7UL  << 2,
+	GPIOMUX_FUNC_8    = 8UL  << 2,
+	GPIOMUX_FUNC_9    = 9UL  << 2,
+	GPIOMUX_FUNC_A    = 10UL << 2,
+	GPIOMUX_FUNC_B    = 11UL << 2,
+	GPIOMUX_FUNC_C    = 12UL << 2,
+	GPIOMUX_FUNC_D    = 13UL << 2,
+	GPIOMUX_FUNC_E    = 14UL << 2,
+	GPIOMUX_FUNC_F    = 15UL << 2,
+};
+
+enum {
+	GPIOMUX_PULL_NONE   = 0UL,
+	GPIOMUX_PULL_DOWN   = 1UL,
+	GPIOMUX_PULL_KEEPER = 2UL,
+	GPIOMUX_PULL_UP     = 3UL,
+};
+
+#endif
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
new file mode 100644
index 0000000..53af21a
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux.c
@@ -0,0 +1,96 @@
+/* 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/module.h>
+#include <linux/spinlock.h>
+#include "gpiomux.h"
+
+static DEFINE_SPINLOCK(gpiomux_lock);
+
+int msm_gpiomux_write(unsigned gpio,
+		      gpiomux_config_t active,
+		      gpiomux_config_t suspended)
+{
+	struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+	unsigned long irq_flags;
+	gpiomux_config_t setting;
+
+	if (gpio >= GPIOMUX_NGPIOS)
+		return -EINVAL;
+
+	spin_lock_irqsave(&gpiomux_lock, irq_flags);
+
+	if (active & GPIOMUX_VALID)
+		cfg->active = active;
+
+	if (suspended & GPIOMUX_VALID)
+		cfg->suspended = suspended;
+
+	setting = cfg->ref ? active : suspended;
+	if (setting & GPIOMUX_VALID)
+		__msm_gpiomux_write(gpio, setting);
+
+	spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
+	return 0;
+}
+EXPORT_SYMBOL(msm_gpiomux_write);
+
+int msm_gpiomux_get(unsigned gpio)
+{
+	struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+	unsigned long irq_flags;
+
+	if (gpio >= GPIOMUX_NGPIOS)
+		return -EINVAL;
+
+	spin_lock_irqsave(&gpiomux_lock, irq_flags);
+	if (cfg->ref++ == 0 && cfg->active & GPIOMUX_VALID)
+		__msm_gpiomux_write(gpio, cfg->active);
+	spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
+	return 0;
+}
+EXPORT_SYMBOL(msm_gpiomux_get);
+
+int msm_gpiomux_put(unsigned gpio)
+{
+	struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+	unsigned long irq_flags;
+
+	if (gpio >= GPIOMUX_NGPIOS)
+		return -EINVAL;
+
+	spin_lock_irqsave(&gpiomux_lock, irq_flags);
+	BUG_ON(cfg->ref == 0);
+	if (--cfg->ref == 0 && cfg->suspended & GPIOMUX_VALID)
+		__msm_gpiomux_write(gpio, cfg->suspended);
+	spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
+	return 0;
+}
+EXPORT_SYMBOL(msm_gpiomux_put);
+
+static int __init gpiomux_init(void)
+{
+	unsigned n;
+
+	for (n = 0; n < GPIOMUX_NGPIOS; ++n) {
+		msm_gpiomux_configs[n].ref = 0;
+		if (!(msm_gpiomux_configs[n].suspended & GPIOMUX_VALID))
+			continue;
+		__msm_gpiomux_write(n, msm_gpiomux_configs[n].suspended);
+	}
+	return 0;
+}
+postcore_initcall(gpiomux_init);
diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h
new file mode 100644
index 0000000..b178d9c
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux.h
@@ -0,0 +1,114 @@
+/* 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.
+ */
+#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_H
+#define __ARCH_ARM_MACH_MSM_GPIOMUX_H
+
+#include <linux/bitops.h>
+#include <linux/errno.h>
+
+#if defined(CONFIG_MSM_V2_TLMM)
+#include "gpiomux-v2.h"
+#else
+#include "gpiomux-v1.h"
+#endif
+
+/**
+ * struct msm_gpiomux_config: gpiomux settings for one gpio line.
+ *
+ * A complete gpiomux config is the bitwise-or of a drive-strength,
+ * function, and pull.  For functions other than GPIO, the OE
+ * is hard-wired according to the function.  For GPIO mode,
+ * OE is controlled by gpiolib.
+ *
+ * Available settings differ by target; see the gpiomux header
+ * specific to your target arch for available configurations.
+ *
+ * @active: The configuration to be installed when the line is
+ * active, or its reference count is > 0.
+ * @suspended: The configuration to be installed when the line
+ * is suspended, or its reference count is 0.
+ * @ref: The reference count of the line.  For internal use of
+ * the gpiomux framework only.
+ */
+struct msm_gpiomux_config {
+	gpiomux_config_t active;
+	gpiomux_config_t suspended;
+	unsigned         ref;
+};
+
+/**
+ * @GPIOMUX_VALID:	If set, the config field contains 'good data'.
+ *                      The absence of this bit will prevent the gpiomux
+ *			system from applying the configuration under all
+ *			circumstances.
+ */
+enum {
+	GPIOMUX_VALID	 = BIT(sizeof(gpiomux_config_t) * BITS_PER_BYTE - 1),
+	GPIOMUX_CTL_MASK = GPIOMUX_VALID,
+};
+
+#ifdef CONFIG_MSM_GPIOMUX
+
+/* Each architecture must provide its own instance of this table.
+ * To avoid having gpiomux manage any given gpio, one or both of
+ * the entries can avoid setting GPIOMUX_VALID - the absence
+ * of that flag will prevent the configuration from being applied
+ * during state transitions.
+ */
+extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS];
+
+/* Increment a gpio's reference count, possibly activating the line. */
+int __must_check msm_gpiomux_get(unsigned gpio);
+
+/* Decrement a gpio's reference count, possibly suspending the line. */
+int msm_gpiomux_put(unsigned gpio);
+
+/* Install a new configuration to the gpio line.  To avoid overwriting
+ * a configuration, leave the VALID bit out.
+ */
+int msm_gpiomux_write(unsigned gpio,
+		      gpiomux_config_t active,
+		      gpiomux_config_t suspended);
+
+/* Architecture-internal function for use by the framework only.
+ * This function can assume the following:
+ * - the gpio value has passed a bounds-check
+ * - the gpiomux spinlock has been obtained
+ *
+ * This function is not for public consumption.  External users
+ * should use msm_gpiomux_write.
+ */
+void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val);
+#else
+static inline int __must_check msm_gpiomux_get(unsigned gpio)
+{
+	return -ENOSYS;
+}
+
+static inline int msm_gpiomux_put(unsigned gpio)
+{
+	return -ENOSYS;
+}
+
+static inline int msm_gpiomux_write(unsigned gpio,
+				    gpiomux_config_t active,
+				    gpiomux_config_t suspended)
+{
+	return -ENOSYS;
+}
+#endif
+#endif
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 5a79bcf..6abf4a6 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -33,6 +33,8 @@
 
 struct clk;
 
+extern struct sys_timer msm_timer;
+
 /* common init routines for use by arch/arm/mach-msm/board-*.c */
 
 void __init msm_add_devices(void);
diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S
index 528750f..fbd5d90 100644
--- a/arch/arm/mach-msm/include/mach/debug-macro.S
+++ b/arch/arm/mach-msm/include/mach/debug-macro.S
@@ -19,13 +19,10 @@
 #include <mach/hardware.h>
 #include <mach/msm_iomap.h>
 
-#ifdef CONFIG_MSM_DEBUG_UART
-	.macro	addruart, rx, tmp
-	@ see if the MMU is enabled and select appropriate base address
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1
-	ldreq	\rx, =MSM_DEBUG_UART_PHYS
-	ldrne	\rx, =MSM_DEBUG_UART_BASE
+#ifdef CONFIG_HAS_MSM_DEBUG_UART_PHYS
+	.macro	addruart, rp, rv
+	ldr	\rp, =MSM_DEBUG_UART_PHYS
+	ldr	\rv, =MSM_DEBUG_UART_BASE
 	.endm
 
 	.macro	senduart,rd,rx
@@ -39,16 +36,7 @@
 	tst	\rd, #0x04
 	beq	1001b
 	.endm
-#else
-	.macro	addruart, rx, tmp
-	.endm
-
-	.macro	senduart,rd,rx
-	.endm
-
-	.macro	waituart,rd,rx
-	.endm
-#endif
 
 	.macro	busyuart,rd,rx
 	.endm
+#endif
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index 00f9bbf..05583f5 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -32,10 +32,18 @@
 	void *data;
 };
 
+#ifndef CONFIG_ARCH_MSM8X60
 void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);
 void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful);
 int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr);
-
+#else
+static inline
+void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) { }
+static inline
+void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful) { }
+static inline
+int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) { return -EIO; }
+#endif
 
 
 #define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2))
diff --git a/arch/arm/mach-msm/include/mach/entry-macro-qgic.S b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
new file mode 100644
index 0000000..4dc99aa
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
@@ -0,0 +1,88 @@
+/*
+ * Low-level IRQ helper macros
+ *
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * 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:
+	 *
+	 * Migrated the code from ARM MP port to be more consistant
+	 * with interrupt processing , the following still holds true
+	 * however, all interrupts are treated the same regardless of
+	 * if they are local IPI or PPI
+	 *
+	 * Interrupts 0-15 are IPI
+	 * 16-31 are PPI
+	 *   (16-18 are the timers)
+	 * 32-1020 are global
+	 * 1021-1022 are reserved
+	 * 1023 is "spurious" (no interrupt)
+	 *
+	 * 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 (0-1020 inclusive).
+	 *
+	 * Base ARM code assumes that the local (private) peripheral interrupts
+	 * are not valid, we treat them differently, in that the privates are
+	 * handled like normal shared interrupts with the exception that only
+	 * one processor can register the interrupt and the handler must be
+	 * the same for all processors.
+	 */
+
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+	ldr  \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 =srcCPU,
+						   9-0 =int # */
+
+	bic     \irqnr, \irqstat, #0x1c00	@mask src
+	cmp     \irqnr, #15
+	ldr		\tmp, =1021
+	cmpcc	\irqnr, \irqnr
+	cmpne	\irqnr, \tmp
+	cmpcs	\irqnr, \irqnr
+
+	.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, #16
+    moveq   \tmp, #1
+    streq   \irqstat, [\base, #GIC_CPU_EOI]
+    cmp \tmp, #0
+	.endm
diff --git a/arch/arm/mach-msm/include/mach/entry-macro-vic.S b/arch/arm/mach-msm/include/mach/entry-macro-vic.S
new file mode 100644
index 0000000..70563ed
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/entry-macro-vic.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * 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 <mach/msm_iomap.h>
+
+	.macro	disable_fiq
+	.endm
+
+	.macro	get_irqnr_preamble, base, tmp
+	@ enable imprecise aborts
+	cpsie	a
+	mov	\base, #MSM_VIC_BASE
+	.endm
+
+	.macro	arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	@ 0xD0 has irq# or old irq# if the irq has been handled
+	@ 0xD4 has irq# or -1 if none pending *but* if you just
+	@ read 0xD4 you never get the first irq for some reason
+	ldr	\irqnr, [\base, #0xD0]
+	ldr	\irqnr, [\base, #0xD4]
+	cmp	\irqnr, #0xffffffff
+	.endm
diff --git a/arch/arm/mach-msm/include/mach/entry-macro.S b/arch/arm/mach-msm/include/mach/entry-macro.S
index d225948..b16f082 100644
--- a/arch/arm/mach-msm/include/mach/entry-macro.S
+++ b/arch/arm/mach-msm/include/mach/entry-macro.S
@@ -1,38 +1,23 @@
-/* arch/arm/mach-msm7200/include/mach/entry-macro.S
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  *
- * Copyright (C) 2007 Google, Inc.
- * 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 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 <mach/msm_iomap.h>
-
- 	.macro	disable_fiq
-	.endm
-
-	.macro	get_irqnr_preamble, base, tmp
-	@ enable imprecise aborts
-	cpsie	a
-	mov	\base, #MSM_VIC_BASE
-	.endm
-
-	.macro	arch_ret_to_user, tmp1, tmp2
-	.endm
-
-	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-	@ 0xD0 has irq# or old irq# if the irq has been handled
-	@ 0xD4 has irq# or -1 if none pending *but* if you just
-	@ read 0xD4 you never get the first irq for some reason
-	ldr	\irqnr, [\base, #0xD0]
-	ldr	\irqnr, [\base, #0xD4]
-	cmp	\irqnr, #0xffffffff
-	.endm
+#if defined(CONFIG_ARM_GIC)
+#include <mach/entry-macro-qgic.S>
+#else
+#include <mach/entry-macro-vic.S>
+#endif
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
index 83e47c0..36ad50d 100644
--- a/arch/arm/mach-msm/include/mach/gpio.h
+++ b/arch/arm/mach-msm/include/mach/gpio.h
@@ -23,127 +23,4 @@
 #define gpio_cansleep   __gpio_cansleep
 #define gpio_to_irq     __gpio_to_irq
 
-/**
- * struct msm_gpio - GPIO pin description
- * @gpio_cfg - configuration bitmap, as per gpio_tlmm_config()
- * @label - textual label
- *
- * Usually, GPIO's are operated by sets.
- * This struct accumulate all GPIO information in single source
- * and facilitete group operations provided by msm_gpios_xxx()
- */
-struct msm_gpio {
-	u32 gpio_cfg;
-	const char *label;
-};
-
-/**
- * msm_gpios_request_enable() - request and enable set of GPIOs
- *
- * Request and configure set of GPIO's
- * In case of error, all operations rolled back.
- * Return error code.
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-int msm_gpios_request_enable(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_disable_free() - disable and free set of GPIOs
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-void msm_gpios_disable_free(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_request() - request set of GPIOs
- * In case of error, all operations rolled back.
- * Return error code.
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-int msm_gpios_request(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_free() - free set of GPIOs
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-void msm_gpios_free(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_enable() - enable set of GPIOs
- * In case of error, all operations rolled back.
- * Return error code.
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-int msm_gpios_enable(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_disable() - disable set of GPIOs
- *
- * @table: GPIO table
- * @size:  number of entries in @table
- */
-void msm_gpios_disable(const struct msm_gpio *table, int size);
-
-/* GPIO TLMM (Top Level Multiplexing) Definitions */
-
-/* GPIO TLMM: Function -- GPIO specific */
-
-/* GPIO TLMM: Direction */
-enum {
-	GPIO_INPUT,
-	GPIO_OUTPUT,
-};
-
-/* GPIO TLMM: Pullup/Pulldown */
-enum {
-	GPIO_NO_PULL,
-	GPIO_PULL_DOWN,
-	GPIO_KEEPER,
-	GPIO_PULL_UP,
-};
-
-/* GPIO TLMM: Drive Strength */
-enum {
-	GPIO_2MA,
-	GPIO_4MA,
-	GPIO_6MA,
-	GPIO_8MA,
-	GPIO_10MA,
-	GPIO_12MA,
-	GPIO_14MA,
-	GPIO_16MA,
-};
-
-enum {
-	GPIO_ENABLE,
-	GPIO_DISABLE,
-};
-
-#define GPIO_CFG(gpio, func, dir, pull, drvstr) \
-	((((gpio) & 0x3FF) << 4)        |	  \
-	 ((func) & 0xf)                  |	  \
-	 (((dir) & 0x1) << 14)           |	  \
-	 (((pull) & 0x3) << 15)          |	  \
-	 (((drvstr) & 0xF) << 17))
-
-/**
- * extract GPIO pin from bit-field used for gpio_tlmm_config
- */
-#define GPIO_PIN(gpio_cfg)    (((gpio_cfg) >>  4) & 0x3ff)
-#define GPIO_FUNC(gpio_cfg)   (((gpio_cfg) >>  0) & 0xf)
-#define GPIO_DIR(gpio_cfg)    (((gpio_cfg) >> 14) & 0x1)
-#define GPIO_PULL(gpio_cfg)   (((gpio_cfg) >> 15) & 0x3)
-#define GPIO_DRVSTR(gpio_cfg) (((gpio_cfg) >> 17) & 0xf)
-
-int gpio_tlmm_config(unsigned config, unsigned disable);
-
 #endif /* __ASM_ARCH_MSM_GPIO_H */
diff --git a/arch/arm/mach-msm/include/mach/io.h b/arch/arm/mach-msm/include/mach/io.h
index c35b29f..7386e73 100644
--- a/arch/arm/mach-msm/include/mach/io.h
+++ b/arch/arm/mach-msm/include/mach/io.h
@@ -28,6 +28,7 @@
 
 void msm_map_qsd8x50_io(void);
 void msm_map_msm7x30_io(void);
+void msm_map_msm8x60_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
new file mode 100644
index 0000000..218ef57
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -0,0 +1,103 @@
+/* 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.
+ */
+
+#ifndef MSM_IOMMU_H
+#define MSM_IOMMU_H
+
+#include <linux/interrupt.h>
+
+/* Maximum number of Machine IDs that we are allowing to be mapped to the same
+ * context bank. The number of MIDs mapped to the same CB does not affect
+ * performance, but there is a practical limit on how many distinct MIDs may
+ * be present. These mappings are typically determined at design time and are
+ * not expected to change at run time.
+ */
+#define MAX_NUM_MIDS	16
+
+/**
+ * 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
+ *
+ */
+struct msm_iommu_dev {
+	const char *name;
+	int clk_rate;
+};
+
+/**
+ * struct msm_iommu_ctx_dev - an IOMMU context bank instance
+ * name		Human-readable name given to this context bank
+ * num		Index of this context bank within the hardware
+ * mids		List of Machine IDs that are to be mapped into this context
+ *		bank, terminated by -1. The MID is a set of signals on the
+ *		AXI bus that identifies the function associated with a specific
+ *		memory request. (See ARM spec).
+ */
+struct msm_iommu_ctx_dev {
+	const char *name;
+	int num;
+	int mids[MAX_NUM_MIDS];
+};
+
+
+/**
+ * struct msm_iommu_drvdata - A single IOMMU hardware instance
+ * @base:	IOMMU config port base address (VA)
+ * @irq:	Interrupt number
+  *
+ * 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;
+};
+
+/**
+ * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
+ * @num:		Hardware context number of this context
+ * @pdev:		Platform device associated wit this HW instance
+ * @attached_elm:	List element for domains to track which devices are
+ *			attached to them
+ *
+ * A msm_iommu_ctx_drvdata holds the driver data for a single context bank
+ * within each IOMMU hardware instance
+ */
+struct msm_iommu_ctx_drvdata {
+	int num;
+	struct platform_device *pdev;
+	struct list_head attached_elm;
+};
+
+/*
+ * Look up an IOMMU context device by its context name. NULL if none found.
+ * Useful for testing and drivers that do not yet fully have IOMMU stuff in
+ * their platform devices.
+ */
+struct device *msm_iommu_get_ctx(const char *ctx_name);
+
+/*
+ * Interrupt handler for the IOMMU context fault interrupt. Hooking the
+ * interrupt is not supported in the API yet, but this will print an error
+ * message and dump useful IOMMU registers.
+ */
+irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id);
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
new file mode 100644
index 0000000..f9386d3
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
@@ -0,0 +1,1871 @@
+/* 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H
+#define __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H
+
+#define CTX_SHIFT 12
+
+#define GET_GLOBAL_REG(reg, base) (readl((base) + (reg)))
+#define GET_CTX_REG(reg, base, ctx) \
+				(readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
+
+#define SET_GLOBAL_REG(reg, base, val)	writel((val), ((base) + (reg)))
+
+#define SET_CTX_REG(reg, base, ctx, val) \
+			writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
+
+/* Wrappers for numbered registers */
+#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v))
+#define GET_GLOBAL_REG_N(b, n, r)    GET_GLOBAL_REG(b, ((r) + (n << 2)))
+
+/* Field wrappers */
+#define GET_GLOBAL_FIELD(b, r, F)    GET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT)
+#define GET_CONTEXT_FIELD(b, c, r, F)	\
+	GET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT)
+
+#define SET_GLOBAL_FIELD(b, r, F, v) \
+	SET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT, (v))
+#define SET_CONTEXT_FIELD(b, c, r, F, v)	\
+	SET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT, (v))
+
+#define GET_FIELD(addr, mask, shift)  ((readl(addr) >> (shift)) & (mask))
+
+#define SET_FIELD(addr, mask, shift, v) \
+do { \
+	int t = readl(addr); \
+	writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\
+} while (0)
+
+
+#define NUM_FL_PTE	4096
+#define NUM_SL_PTE	256
+
+/* First-level page table bits */
+#define FL_BASE_MASK		0xFFFFFC00
+#define FL_TYPE_TABLE		(1 << 0)
+#define FL_TYPE_SECT		(2 << 0)
+#define FL_SUPERSECTION		(1 << 18)
+#define FL_AP_WRITE		(1 << 10)
+#define FL_AP_READ		(1 << 11)
+#define FL_SHARED		(1 << 16)
+#define FL_OFFSET(va)		(((va) & 0xFFF00000) >> 20)
+
+/* Second-level page table bits */
+#define SL_BASE_MASK_LARGE	0xFFFF0000
+#define SL_BASE_MASK_SMALL	0xFFFFF000
+#define SL_TYPE_LARGE		(1 << 0)
+#define SL_TYPE_SMALL		(2 << 0)
+#define SL_AP0			(1 << 4)
+#define SL_AP1			(2 << 4)
+#define SL_SHARED		(1 << 10)
+#define SL_OFFSET(va)		(((va) & 0xFF000) >> 12)
+
+/* Global register setters / getters */
+#define SET_M2VCBR_N(b, N, v)	 SET_GLOBAL_REG_N(M2VCBR_N, N, (b), (v))
+#define SET_CBACR_N(b, N, v)	 SET_GLOBAL_REG_N(CBACR_N, N, (b), (v))
+#define SET_TLBRSW(b, v)	 SET_GLOBAL_REG(TLBRSW, (b), (v))
+#define SET_TLBTR0(b, v)	 SET_GLOBAL_REG(TLBTR0, (b), (v))
+#define SET_TLBTR1(b, v)	 SET_GLOBAL_REG(TLBTR1, (b), (v))
+#define SET_TLBTR2(b, v)	 SET_GLOBAL_REG(TLBTR2, (b), (v))
+#define SET_TESTBUSCR(b, v)	 SET_GLOBAL_REG(TESTBUSCR, (b), (v))
+#define SET_GLOBAL_TLBIALL(b, v) SET_GLOBAL_REG(GLOBAL_TLBIALL, (b), (v))
+#define SET_TLBIVMID(b, v)	 SET_GLOBAL_REG(TLBIVMID, (b), (v))
+#define SET_CR(b, v)		 SET_GLOBAL_REG(CR, (b), (v))
+#define SET_EAR(b, v)		 SET_GLOBAL_REG(EAR, (b), (v))
+#define SET_ESR(b, v)		 SET_GLOBAL_REG(ESR, (b), (v))
+#define SET_ESRRESTORE(b, v)	 SET_GLOBAL_REG(ESRRESTORE, (b), (v))
+#define SET_ESYNR0(b, v)	 SET_GLOBAL_REG(ESYNR0, (b), (v))
+#define SET_ESYNR1(b, v)	 SET_GLOBAL_REG(ESYNR1, (b), (v))
+#define SET_RPU_ACR(b, v)	 SET_GLOBAL_REG(RPU_ACR, (b), (v))
+
+#define GET_M2VCBR_N(b, N)	 GET_GLOBAL_REG_N(M2VCBR_N, N, (b))
+#define GET_CBACR_N(b, N)	 GET_GLOBAL_REG_N(CBACR_N, N, (b))
+#define GET_TLBTR0(b)		 GET_GLOBAL_REG(TLBTR0, (b))
+#define GET_TLBTR1(b)		 GET_GLOBAL_REG(TLBTR1, (b))
+#define GET_TLBTR2(b)		 GET_GLOBAL_REG(TLBTR2, (b))
+#define GET_TESTBUSCR(b)	 GET_GLOBAL_REG(TESTBUSCR, (b))
+#define GET_GLOBAL_TLBIALL(b)	 GET_GLOBAL_REG(GLOBAL_TLBIALL, (b))
+#define GET_TLBIVMID(b)		 GET_GLOBAL_REG(TLBIVMID, (b))
+#define GET_CR(b)		 GET_GLOBAL_REG(CR, (b))
+#define GET_EAR(b)		 GET_GLOBAL_REG(EAR, (b))
+#define GET_ESR(b)		 GET_GLOBAL_REG(ESR, (b))
+#define GET_ESRRESTORE(b)	 GET_GLOBAL_REG(ESRRESTORE, (b))
+#define GET_ESYNR0(b)		 GET_GLOBAL_REG(ESYNR0, (b))
+#define GET_ESYNR1(b)		 GET_GLOBAL_REG(ESYNR1, (b))
+#define GET_REV(b)		 GET_GLOBAL_REG(REV, (b))
+#define GET_IDR(b)		 GET_GLOBAL_REG(IDR, (b))
+#define GET_RPU_ACR(b)		 GET_GLOBAL_REG(RPU_ACR, (b))
+
+
+/* Context register setters/getters */
+#define SET_SCTLR(b, c, v)	 SET_CTX_REG(SCTLR, (b), (c), (v))
+#define SET_ACTLR(b, c, v)	 SET_CTX_REG(ACTLR, (b), (c), (v))
+#define SET_CONTEXTIDR(b, c, v)	 SET_CTX_REG(CONTEXTIDR, (b), (c), (v))
+#define SET_TTBR0(b, c, v)	 SET_CTX_REG(TTBR0, (b), (c), (v))
+#define SET_TTBR1(b, c, v)	 SET_CTX_REG(TTBR1, (b), (c), (v))
+#define SET_TTBCR(b, c, v)	 SET_CTX_REG(TTBCR, (b), (c), (v))
+#define SET_PAR(b, c, v)	 SET_CTX_REG(PAR, (b), (c), (v))
+#define SET_FSR(b, c, v)	 SET_CTX_REG(FSR, (b), (c), (v))
+#define SET_FSRRESTORE(b, c, v)	 SET_CTX_REG(FSRRESTORE, (b), (c), (v))
+#define SET_FAR(b, c, v)	 SET_CTX_REG(FAR, (b), (c), (v))
+#define SET_FSYNR0(b, c, v)	 SET_CTX_REG(FSYNR0, (b), (c), (v))
+#define SET_FSYNR1(b, c, v)	 SET_CTX_REG(FSYNR1, (b), (c), (v))
+#define SET_PRRR(b, c, v)	 SET_CTX_REG(PRRR, (b), (c), (v))
+#define SET_NMRR(b, c, v)	 SET_CTX_REG(NMRR, (b), (c), (v))
+#define SET_TLBLKCR(b, c, v)	 SET_CTX_REG(TLBLCKR, (b), (c), (v))
+#define SET_V2PSR(b, c, v)	 SET_CTX_REG(V2PSR, (b), (c), (v))
+#define SET_TLBFLPTER(b, c, v)	 SET_CTX_REG(TLBFLPTER, (b), (c), (v))
+#define SET_TLBSLPTER(b, c, v)	 SET_CTX_REG(TLBSLPTER, (b), (c), (v))
+#define SET_BFBCR(b, c, v)	 SET_CTX_REG(BFBCR, (b), (c), (v))
+#define SET_CTX_TLBIALL(b, c, v) SET_CTX_REG(CTX_TLBIALL, (b), (c), (v))
+#define SET_TLBIASID(b, c, v)	 SET_CTX_REG(TLBIASID, (b), (c), (v))
+#define SET_TLBIVA(b, c, v)	 SET_CTX_REG(TLBIVA, (b), (c), (v))
+#define SET_TLBIVAA(b, c, v)	 SET_CTX_REG(TLBIVAA, (b), (c), (v))
+#define SET_V2PPR(b, c, v)	 SET_CTX_REG(V2PPR, (b), (c), (v))
+#define SET_V2PPW(b, c, v)	 SET_CTX_REG(V2PPW, (b), (c), (v))
+#define SET_V2PUR(b, c, v)	 SET_CTX_REG(V2PUR, (b), (c), (v))
+#define SET_V2PUW(b, c, v)	 SET_CTX_REG(V2PUW, (b), (c), (v))
+#define SET_RESUME(b, c, v)	 SET_CTX_REG(RESUME, (b), (c), (v))
+
+#define GET_SCTLR(b, c)		 GET_CTX_REG(SCTLR, (b), (c))
+#define GET_ACTLR(b, c)		 GET_CTX_REG(ACTLR, (b), (c))
+#define GET_CONTEXTIDR(b, c)	 GET_CTX_REG(CONTEXTIDR, (b), (c))
+#define GET_TTBR0(b, c)		 GET_CTX_REG(TTBR0, (b), (c))
+#define GET_TTBR1(b, c)		 GET_CTX_REG(TTBR1, (b), (c))
+#define GET_TTBCR(b, c)		 GET_CTX_REG(TTBCR, (b), (c))
+#define GET_PAR(b, c)		 GET_CTX_REG(PAR, (b), (c))
+#define GET_FSR(b, c)		 GET_CTX_REG(FSR, (b), (c))
+#define GET_FSRRESTORE(b, c)	 GET_CTX_REG(FSRRESTORE, (b), (c))
+#define GET_FAR(b, c)		 GET_CTX_REG(FAR, (b), (c))
+#define GET_FSYNR0(b, c)	 GET_CTX_REG(FSYNR0, (b), (c))
+#define GET_FSYNR1(b, c)	 GET_CTX_REG(FSYNR1, (b), (c))
+#define GET_PRRR(b, c)		 GET_CTX_REG(PRRR, (b), (c))
+#define GET_NMRR(b, c)		 GET_CTX_REG(NMRR, (b), (c))
+#define GET_TLBLCKR(b, c)	 GET_CTX_REG(TLBLCKR, (b), (c))
+#define GET_V2PSR(b, c)		 GET_CTX_REG(V2PSR, (b), (c))
+#define GET_TLBFLPTER(b, c)	 GET_CTX_REG(TLBFLPTER, (b), (c))
+#define GET_TLBSLPTER(b, c)	 GET_CTX_REG(TLBSLPTER, (b), (c))
+#define GET_BFBCR(b, c)		 GET_CTX_REG(BFBCR, (b), (c))
+#define GET_CTX_TLBIALL(b, c)	 GET_CTX_REG(CTX_TLBIALL, (b), (c))
+#define GET_TLBIASID(b, c)	 GET_CTX_REG(TLBIASID, (b), (c))
+#define GET_TLBIVA(b, c)	 GET_CTX_REG(TLBIVA, (b), (c))
+#define GET_TLBIVAA(b, c)	 GET_CTX_REG(TLBIVAA, (b), (c))
+#define GET_V2PPR(b, c)		 GET_CTX_REG(V2PPR, (b), (c))
+#define GET_V2PPW(b, c)		 GET_CTX_REG(V2PPW, (b), (c))
+#define GET_V2PUR(b, c)		 GET_CTX_REG(V2PUR, (b), (c))
+#define GET_V2PUW(b, c)		 GET_CTX_REG(V2PUW, (b), (c))
+#define GET_RESUME(b, c)	 GET_CTX_REG(RESUME, (b), (c))
+
+
+/* Global field setters / getters */
+/* Global Field Setters: */
+/* CBACR_N */
+#define SET_RWVMID(b, n, v)   SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID, v)
+#define SET_RWE(b, n, v)      SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE, v)
+#define SET_RWGE(b, n, v)     SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE, v)
+#define SET_CBVMID(b, n, v)   SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID, v)
+#define SET_IRPTNDX(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX, v)
+
+
+/* M2VCBR_N */
+#define SET_VMID(b, n, v)     SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID, v)
+#define SET_CBNDX(b, n, v)    SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX, v)
+#define SET_BYPASSD(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD, v)
+#define SET_BPRCOSH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH, v)
+#define SET_BPRCISH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH, v)
+#define SET_BPRCNSH(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH, v)
+#define SET_BPSHCFG(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG, v)
+#define SET_NSCFG(b, n, v)    SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG, v)
+#define SET_BPMTCFG(b, n, v)  SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG, v)
+#define SET_BPMEMTYPE(b, n, v) \
+	SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE, v)
+
+
+/* CR */
+#define SET_RPUE(b, v)		 SET_GLOBAL_FIELD(b, CR, RPUE, v)
+#define SET_RPUERE(b, v)	 SET_GLOBAL_FIELD(b, CR, RPUERE, v)
+#define SET_RPUEIE(b, v)	 SET_GLOBAL_FIELD(b, CR, RPUEIE, v)
+#define SET_DCDEE(b, v)		 SET_GLOBAL_FIELD(b, CR, DCDEE, v)
+#define SET_CLIENTPD(b, v)       SET_GLOBAL_FIELD(b, CR, CLIENTPD, v)
+#define SET_STALLD(b, v)	 SET_GLOBAL_FIELD(b, CR, STALLD, v)
+#define SET_TLBLKCRWE(b, v)      SET_GLOBAL_FIELD(b, CR, TLBLKCRWE, v)
+#define SET_CR_TLBIALLCFG(b, v)  SET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG, v)
+#define SET_TLBIVMIDCFG(b, v)    SET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG, v)
+#define SET_CR_HUME(b, v)        SET_GLOBAL_FIELD(b, CR, CR_HUME, v)
+
+
+/* ESR */
+#define SET_CFG(b, v)		 SET_GLOBAL_FIELD(b, ESR, CFG, v)
+#define SET_BYPASS(b, v)	 SET_GLOBAL_FIELD(b, ESR, BYPASS, v)
+#define SET_ESR_MULTI(b, v)      SET_GLOBAL_FIELD(b, ESR, ESR_MULTI, v)
+
+
+/* ESYNR0 */
+#define SET_ESYNR0_AMID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID, v)
+#define SET_ESYNR0_APID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID, v)
+#define SET_ESYNR0_ABID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID, v)
+#define SET_ESYNR0_AVMID(b, v)   SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID, v)
+#define SET_ESYNR0_ATID(b, v)    SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID, v)
+
+
+/* ESYNR1 */
+#define SET_ESYNR1_AMEMTYPE(b, v) \
+			SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE, v)
+#define SET_ESYNR1_ASHARED(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED, v)
+#define SET_ESYNR1_AINNERSHARED(b, v) \
+			SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED, v)
+#define SET_ESYNR1_APRIV(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV, v)
+#define SET_ESYNR1_APROTNS(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS, v)
+#define SET_ESYNR1_AINST(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST, v)
+#define SET_ESYNR1_AWRITE(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE, v)
+#define SET_ESYNR1_ABURST(b, v)  SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST, v)
+#define SET_ESYNR1_ALEN(b, v)    SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN, v)
+#define SET_ESYNR1_ASIZE(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE, v)
+#define SET_ESYNR1_ALOCK(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK, v)
+#define SET_ESYNR1_AOOO(b, v)    SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO, v)
+#define SET_ESYNR1_AFULL(b, v)   SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL, v)
+#define SET_ESYNR1_AC(b, v)      SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC, v)
+#define SET_ESYNR1_DCD(b, v)     SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD, v)
+
+
+/* TESTBUSCR */
+#define SET_TBE(b, v)		 SET_GLOBAL_FIELD(b, TESTBUSCR, TBE, v)
+#define SET_SPDMBE(b, v)	 SET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE, v)
+#define SET_WGSEL(b, v)		 SET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL, v)
+#define SET_TBLSEL(b, v)	 SET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL, v)
+#define SET_TBHSEL(b, v)	 SET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL, v)
+#define SET_SPDM0SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL, v)
+#define SET_SPDM1SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL, v)
+#define SET_SPDM2SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL, v)
+#define SET_SPDM3SEL(b, v)       SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL, v)
+
+
+/* TLBIVMID */
+#define SET_TLBIVMID_VMID(b, v)  SET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID, v)
+
+
+/* TLBRSW */
+#define SET_TLBRSW_INDEX(b, v)   SET_GLOBAL_FIELD(b, TLBRSW, TLBRSW_INDEX, v)
+#define SET_TLBBFBS(b, v)	 SET_GLOBAL_FIELD(b, TLBRSW, TLBBFBS, v)
+
+
+/* TLBTR0 */
+#define SET_PR(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, PR, v)
+#define SET_PW(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, PW, v)
+#define SET_UR(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, UR, v)
+#define SET_UW(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, UW, v)
+#define SET_XN(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, XN, v)
+#define SET_NSDESC(b, v)	 SET_GLOBAL_FIELD(b, TLBTR0, NSDESC, v)
+#define SET_ISH(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, ISH, v)
+#define SET_SH(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, SH, v)
+#define SET_MT(b, v)		 SET_GLOBAL_FIELD(b, TLBTR0, MT, v)
+#define SET_DPSIZR(b, v)	 SET_GLOBAL_FIELD(b, TLBTR0, DPSIZR, v)
+#define SET_DPSIZC(b, v)	 SET_GLOBAL_FIELD(b, TLBTR0, DPSIZC, v)
+
+
+/* TLBTR1 */
+#define SET_TLBTR1_VMID(b, v)    SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID, v)
+#define SET_TLBTR1_PA(b, v)      SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA, v)
+
+
+/* TLBTR2 */
+#define SET_TLBTR2_ASID(b, v)    SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID, v)
+#define SET_TLBTR2_V(b, v)       SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V, v)
+#define SET_TLBTR2_NSTID(b, v)   SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID, v)
+#define SET_TLBTR2_NV(b, v)      SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV, v)
+#define SET_TLBTR2_VA(b, v)      SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA, v)
+
+
+/* Global Field Getters */
+/* CBACR_N */
+#define GET_RWVMID(b, n)	 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID)
+#define GET_RWE(b, n)		 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE)
+#define GET_RWGE(b, n)		 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE)
+#define GET_CBVMID(b, n)	 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID)
+#define GET_IRPTNDX(b, n)	 GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX)
+
+
+/* M2VCBR_N */
+#define GET_VMID(b, n)       GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID)
+#define GET_CBNDX(b, n)      GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX)
+#define GET_BYPASSD(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD)
+#define GET_BPRCOSH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH)
+#define GET_BPRCISH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH)
+#define GET_BPRCNSH(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH)
+#define GET_BPSHCFG(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG)
+#define GET_NSCFG(b, n)      GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG)
+#define GET_BPMTCFG(b, n)    GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG)
+#define GET_BPMEMTYPE(b, n)  GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE)
+
+
+/* CR */
+#define GET_RPUE(b)		 GET_GLOBAL_FIELD(b, CR, RPUE)
+#define GET_RPUERE(b)		 GET_GLOBAL_FIELD(b, CR, RPUERE)
+#define GET_RPUEIE(b)		 GET_GLOBAL_FIELD(b, CR, RPUEIE)
+#define GET_DCDEE(b)		 GET_GLOBAL_FIELD(b, CR, DCDEE)
+#define GET_CLIENTPD(b)		 GET_GLOBAL_FIELD(b, CR, CLIENTPD)
+#define GET_STALLD(b)		 GET_GLOBAL_FIELD(b, CR, STALLD)
+#define GET_TLBLKCRWE(b)	 GET_GLOBAL_FIELD(b, CR, TLBLKCRWE)
+#define GET_CR_TLBIALLCFG(b)	 GET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG)
+#define GET_TLBIVMIDCFG(b)	 GET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG)
+#define GET_CR_HUME(b)		 GET_GLOBAL_FIELD(b, CR, CR_HUME)
+
+
+/* ESR */
+#define GET_CFG(b)		 GET_GLOBAL_FIELD(b, ESR, CFG)
+#define GET_BYPASS(b)		 GET_GLOBAL_FIELD(b, ESR, BYPASS)
+#define GET_ESR_MULTI(b)	 GET_GLOBAL_FIELD(b, ESR, ESR_MULTI)
+
+
+/* ESYNR0 */
+#define GET_ESYNR0_AMID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID)
+#define GET_ESYNR0_APID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID)
+#define GET_ESYNR0_ABID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID)
+#define GET_ESYNR0_AVMID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID)
+#define GET_ESYNR0_ATID(b)	 GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID)
+
+
+/* ESYNR1 */
+#define GET_ESYNR1_AMEMTYPE(b)   GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE)
+#define GET_ESYNR1_ASHARED(b)    GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED)
+#define GET_ESYNR1_AINNERSHARED(b) \
+			GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED)
+#define GET_ESYNR1_APRIV(b)      GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV)
+#define GET_ESYNR1_APROTNS(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS)
+#define GET_ESYNR1_AINST(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST)
+#define GET_ESYNR1_AWRITE(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE)
+#define GET_ESYNR1_ABURST(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST)
+#define GET_ESYNR1_ALEN(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN)
+#define GET_ESYNR1_ASIZE(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE)
+#define GET_ESYNR1_ALOCK(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK)
+#define GET_ESYNR1_AOOO(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO)
+#define GET_ESYNR1_AFULL(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL)
+#define GET_ESYNR1_AC(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC)
+#define GET_ESYNR1_DCD(b)	 GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD)
+
+
+/* IDR */
+#define GET_NM2VCBMT(b)		 GET_GLOBAL_FIELD(b, IDR, NM2VCBMT)
+#define GET_HTW(b)		 GET_GLOBAL_FIELD(b, IDR, HTW)
+#define GET_HUM(b)		 GET_GLOBAL_FIELD(b, IDR, HUM)
+#define GET_TLBSIZE(b)		 GET_GLOBAL_FIELD(b, IDR, TLBSIZE)
+#define GET_NCB(b)		 GET_GLOBAL_FIELD(b, IDR, NCB)
+#define GET_NIRPT(b)		 GET_GLOBAL_FIELD(b, IDR, NIRPT)
+
+
+/* REV */
+#define GET_MAJOR(b)		 GET_GLOBAL_FIELD(b, REV, MAJOR)
+#define GET_MINOR(b)		 GET_GLOBAL_FIELD(b, REV, MINOR)
+
+
+/* TESTBUSCR */
+#define GET_TBE(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, TBE)
+#define GET_SPDMBE(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE)
+#define GET_WGSEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL)
+#define GET_TBLSEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL)
+#define GET_TBHSEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL)
+#define GET_SPDM0SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL)
+#define GET_SPDM1SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL)
+#define GET_SPDM2SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL)
+#define GET_SPDM3SEL(b)		 GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL)
+
+
+/* TLBIVMID */
+#define GET_TLBIVMID_VMID(b)	 GET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID)
+
+
+/* TLBTR0 */
+#define GET_PR(b)		 GET_GLOBAL_FIELD(b, TLBTR0, PR)
+#define GET_PW(b)		 GET_GLOBAL_FIELD(b, TLBTR0, PW)
+#define GET_UR(b)		 GET_GLOBAL_FIELD(b, TLBTR0, UR)
+#define GET_UW(b)		 GET_GLOBAL_FIELD(b, TLBTR0, UW)
+#define GET_XN(b)		 GET_GLOBAL_FIELD(b, TLBTR0, XN)
+#define GET_NSDESC(b)		 GET_GLOBAL_FIELD(b, TLBTR0, NSDESC)
+#define GET_ISH(b)		 GET_GLOBAL_FIELD(b, TLBTR0, ISH)
+#define GET_SH(b)		 GET_GLOBAL_FIELD(b, TLBTR0, SH)
+#define GET_MT(b)		 GET_GLOBAL_FIELD(b, TLBTR0, MT)
+#define GET_DPSIZR(b)		 GET_GLOBAL_FIELD(b, TLBTR0, DPSIZR)
+#define GET_DPSIZC(b)		 GET_GLOBAL_FIELD(b, TLBTR0, DPSIZC)
+
+
+/* TLBTR1 */
+#define GET_TLBTR1_VMID(b)	 GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID)
+#define GET_TLBTR1_PA(b)	 GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA)
+
+
+/* TLBTR2 */
+#define GET_TLBTR2_ASID(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID)
+#define GET_TLBTR2_V(b)		 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V)
+#define GET_TLBTR2_NSTID(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID)
+#define GET_TLBTR2_NV(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV)
+#define GET_TLBTR2_VA(b)	 GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA)
+
+
+/* Context Register setters / getters */
+/* Context Register setters */
+/* ACTLR */
+#define SET_CFERE(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, CFERE, v)
+#define SET_CFEIE(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, CFEIE, v)
+#define SET_PTSHCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG, v)
+#define SET_RCOSH(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, RCOSH, v)
+#define SET_RCISH(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, RCISH, v)
+#define SET_RCNSH(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, RCNSH, v)
+#define SET_PRIVCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG, v)
+#define SET_DNA(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, DNA, v)
+#define SET_DNLV2PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA, v)
+#define SET_TLBMCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG, v)
+#define SET_CFCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, CFCFG, v)
+#define SET_TIPCF(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, TIPCF, v)
+#define SET_V2PCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG, v)
+#define SET_HUME(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, HUME, v)
+#define SET_PTMTCFG(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG, v)
+#define SET_PTMEMTYPE(b, c, v)	 SET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE, v)
+
+
+/* BFBCR */
+#define SET_BFBDFE(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE, v)
+#define SET_BFBSFE(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE, v)
+#define SET_SFVS(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, SFVS, v)
+#define SET_FLVIC(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, FLVIC, v)
+#define SET_SLVIC(b, c, v)	 SET_CONTEXT_FIELD(b, c, BFBCR, SLVIC, v)
+
+
+/* CONTEXTIDR */
+#define SET_CONTEXTIDR_ASID(b, c, v)   \
+		SET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID, v)
+#define SET_CONTEXTIDR_PROCID(b, c, v) \
+		SET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID, v)
+
+
+/* FSR */
+#define SET_TF(b, c, v)		 SET_CONTEXT_FIELD(b, c, FSR, TF, v)
+#define SET_AFF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, AFF, v)
+#define SET_APF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, APF, v)
+#define SET_TLBMF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, TLBMF, v)
+#define SET_HTWDEEF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, HTWDEEF, v)
+#define SET_HTWSEEF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, HTWSEEF, v)
+#define SET_MHF(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, MHF, v)
+#define SET_SL(b, c, v)		 SET_CONTEXT_FIELD(b, c, FSR, SL, v)
+#define SET_SS(b, c, v)		 SET_CONTEXT_FIELD(b, c, FSR, SS, v)
+#define SET_MULTI(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSR, MULTI, v)
+
+
+/* FSYNR0 */
+#define SET_AMID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, AMID, v)
+#define SET_APID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, APID, v)
+#define SET_ABID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, ABID, v)
+#define SET_ATID(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR0, ATID, v)
+
+
+/* FSYNR1 */
+#define SET_AMEMTYPE(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE, v)
+#define SET_ASHARED(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED, v)
+#define SET_AINNERSHARED(b, c, v)  \
+				SET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED, v)
+#define SET_APRIV(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, APRIV, v)
+#define SET_APROTNS(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS, v)
+#define SET_AINST(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AINST, v)
+#define SET_AWRITE(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE, v)
+#define SET_ABURST(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ABURST, v)
+#define SET_ALEN(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ALEN, v)
+#define SET_FSYNR1_ASIZE(b, c, v) \
+				SET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE, v)
+#define SET_ALOCK(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK, v)
+#define SET_AFULL(b, c, v)	 SET_CONTEXT_FIELD(b, c, FSYNR1, AFULL, v)
+
+
+/* NMRR */
+#define SET_ICPC0(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC0, v)
+#define SET_ICPC1(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC1, v)
+#define SET_ICPC2(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC2, v)
+#define SET_ICPC3(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC3, v)
+#define SET_ICPC4(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC4, v)
+#define SET_ICPC5(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC5, v)
+#define SET_ICPC6(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC6, v)
+#define SET_ICPC7(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, ICPC7, v)
+#define SET_OCPC0(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC0, v)
+#define SET_OCPC1(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC1, v)
+#define SET_OCPC2(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC2, v)
+#define SET_OCPC3(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC3, v)
+#define SET_OCPC4(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC4, v)
+#define SET_OCPC5(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC5, v)
+#define SET_OCPC6(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC6, v)
+#define SET_OCPC7(b, c, v)	 SET_CONTEXT_FIELD(b, c, NMRR, OCPC7, v)
+
+
+/* PAR */
+#define SET_FAULT(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT, v)
+
+#define SET_FAULT_TF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_TF, v)
+#define SET_FAULT_AFF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF, v)
+#define SET_FAULT_APF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_APF, v)
+#define SET_FAULT_TLBMF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF, v)
+#define SET_FAULT_HTWDEEF(b, c, v) \
+				SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF, v)
+#define SET_FAULT_HTWSEEF(b, c, v) \
+				SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF, v)
+#define SET_FAULT_MHF(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF, v)
+#define SET_FAULT_SL(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_SL, v)
+#define SET_FAULT_SS(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, FAULT_SS, v)
+
+#define SET_NOFAULT_SS(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SS, v)
+#define SET_NOFAULT_MT(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_MT, v)
+#define SET_NOFAULT_SH(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SH, v)
+#define SET_NOFAULT_NS(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NS, v)
+#define SET_NOFAULT_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NOS, v)
+#define SET_NPFAULT_PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, PAR, NPFAULT_PA, v)
+
+
+/* PRRR */
+#define SET_MTC0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC0, v)
+#define SET_MTC1(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC1, v)
+#define SET_MTC2(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC2, v)
+#define SET_MTC3(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC3, v)
+#define SET_MTC4(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC4, v)
+#define SET_MTC5(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC5, v)
+#define SET_MTC6(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC6, v)
+#define SET_MTC7(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, MTC7, v)
+#define SET_SHDSH0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, SHDSH0, v)
+#define SET_SHDSH1(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, SHDSH1, v)
+#define SET_SHNMSH0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0, v)
+#define SET_SHNMSH1(b, c, v)     SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1, v)
+#define SET_NOS0(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS0, v)
+#define SET_NOS1(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS1, v)
+#define SET_NOS2(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS2, v)
+#define SET_NOS3(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS3, v)
+#define SET_NOS4(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS4, v)
+#define SET_NOS5(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS5, v)
+#define SET_NOS6(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS6, v)
+#define SET_NOS7(b, c, v)	 SET_CONTEXT_FIELD(b, c, PRRR, NOS7, v)
+
+
+/* RESUME */
+#define SET_TNR(b, c, v)	 SET_CONTEXT_FIELD(b, c, RESUME, TNR, v)
+
+
+/* SCTLR */
+#define SET_M(b, c, v)		 SET_CONTEXT_FIELD(b, c, SCTLR, M, v)
+#define SET_TRE(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, TRE, v)
+#define SET_AFE(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, AFE, v)
+#define SET_HAF(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, HAF, v)
+#define SET_BE(b, c, v)		 SET_CONTEXT_FIELD(b, c, SCTLR, BE, v)
+#define SET_AFFD(b, c, v)	 SET_CONTEXT_FIELD(b, c, SCTLR, AFFD, v)
+
+
+/* TLBLKCR */
+#define SET_LKE(b, c, v)	   SET_CONTEXT_FIELD(b, c, TLBLKCR, LKE, v)
+#define SET_TLBLKCR_TLBIALLCFG(b, c, v) \
+			SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG, v)
+#define SET_TLBIASIDCFG(b, c, v) \
+			SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG, v)
+#define SET_TLBIVAACFG(b, c, v)	SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG, v)
+#define SET_FLOOR(b, c, v)	SET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR, v)
+#define SET_VICTIM(b, c, v)	SET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM, v)
+
+
+/* TTBCR */
+#define SET_N(b, c, v)	         SET_CONTEXT_FIELD(b, c, TTBCR, N, v)
+#define SET_PD0(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBCR, PD0, v)
+#define SET_PD1(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBCR, PD1, v)
+
+
+/* TTBR0 */
+#define SET_TTBR0_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH, v)
+#define SET_TTBR0_SH(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH, v)
+#define SET_TTBR0_ORGN(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN, v)
+#define SET_TTBR0_NOS(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS, v)
+#define SET_TTBR0_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL, v)
+#define SET_TTBR0_PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA, v)
+
+
+/* TTBR1 */
+#define SET_TTBR1_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH, v)
+#define SET_TTBR1_SH(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH, v)
+#define SET_TTBR1_ORGN(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN, v)
+#define SET_TTBR1_NOS(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS, v)
+#define SET_TTBR1_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL, v)
+#define SET_TTBR1_PA(b, c, v)	 SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA, v)
+
+
+/* V2PSR */
+#define SET_HIT(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PSR, HIT, v)
+#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)
+#define GET_CFEIE(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, CFEIE)
+#define GET_PTSHCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG)
+#define GET_RCOSH(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, RCOSH)
+#define GET_RCISH(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, RCISH)
+#define GET_RCNSH(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, RCNSH)
+#define GET_PRIVCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG)
+#define GET_DNA(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, DNA)
+#define GET_DNLV2PA(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA)
+#define GET_TLBMCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG)
+#define GET_CFCFG(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, CFCFG)
+#define GET_TIPCF(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, TIPCF)
+#define GET_V2PCFG(b, c)        GET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG)
+#define GET_HUME(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, HUME)
+#define GET_PTMTCFG(b, c)       GET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG)
+#define GET_PTMEMTYPE(b, c)     GET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE)
+
+/* BFBCR */
+#define GET_BFBDFE(b, c)	GET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE)
+#define GET_BFBSFE(b, c)	GET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE)
+#define GET_SFVS(b, c)		GET_CONTEXT_FIELD(b, c, BFBCR, SFVS)
+#define GET_FLVIC(b, c)		GET_CONTEXT_FIELD(b, c, BFBCR, FLVIC)
+#define GET_SLVIC(b, c)		GET_CONTEXT_FIELD(b, c, BFBCR, SLVIC)
+
+
+/* CONTEXTIDR */
+#define GET_CONTEXTIDR_ASID(b, c) \
+			GET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID)
+#define GET_CONTEXTIDR_PROCID(b, c) GET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID)
+
+
+/* FSR */
+#define GET_TF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, TF)
+#define GET_AFF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, AFF)
+#define GET_APF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, APF)
+#define GET_TLBMF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, TLBMF)
+#define GET_HTWDEEF(b, c)	GET_CONTEXT_FIELD(b, c, FSR, HTWDEEF)
+#define GET_HTWSEEF(b, c)	GET_CONTEXT_FIELD(b, c, FSR, HTWSEEF)
+#define GET_MHF(b, c)		GET_CONTEXT_FIELD(b, c, FSR, MHF)
+#define GET_SL(b, c)		GET_CONTEXT_FIELD(b, c, FSR, SL)
+#define GET_SS(b, c)		GET_CONTEXT_FIELD(b, c, FSR, SS)
+#define GET_MULTI(b, c)		GET_CONTEXT_FIELD(b, c, FSR, MULTI)
+
+
+/* FSYNR0 */
+#define GET_AMID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, AMID)
+#define GET_APID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, APID)
+#define GET_ABID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, ABID)
+#define GET_ATID(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR0, ATID)
+
+
+/* FSYNR1 */
+#define GET_AMEMTYPE(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE)
+#define GET_ASHARED(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED)
+#define GET_AINNERSHARED(b, c)  GET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED)
+#define GET_APRIV(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, APRIV)
+#define GET_APROTNS(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS)
+#define GET_AINST(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, AINST)
+#define GET_AWRITE(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE)
+#define GET_ABURST(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, ABURST)
+#define GET_ALEN(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, ALEN)
+#define GET_FSYNR1_ASIZE(b, c)	GET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE)
+#define GET_ALOCK(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK)
+#define GET_AFULL(b, c)		GET_CONTEXT_FIELD(b, c, FSYNR1, AFULL)
+
+
+/* NMRR */
+#define GET_ICPC0(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC0)
+#define GET_ICPC1(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC1)
+#define GET_ICPC2(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC2)
+#define GET_ICPC3(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC3)
+#define GET_ICPC4(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC4)
+#define GET_ICPC5(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC5)
+#define GET_ICPC6(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC6)
+#define GET_ICPC7(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, ICPC7)
+#define GET_OCPC0(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC0)
+#define GET_OCPC1(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC1)
+#define GET_OCPC2(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC2)
+#define GET_OCPC3(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC3)
+#define GET_OCPC4(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC4)
+#define GET_OCPC5(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC5)
+#define GET_OCPC6(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC6)
+#define GET_OCPC7(b, c)		GET_CONTEXT_FIELD(b, c, NMRR, OCPC7)
+
+
+/* PAR */
+#define GET_FAULT(b, c)		GET_CONTEXT_FIELD(b, c, PAR, FAULT)
+
+#define GET_FAULT_TF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_TF)
+#define GET_FAULT_AFF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF)
+#define GET_FAULT_APF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_APF)
+#define GET_FAULT_TLBMF(b, c)   GET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF)
+#define GET_FAULT_HTWDEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF)
+#define GET_FAULT_HTWSEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF)
+#define GET_FAULT_MHF(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF)
+#define GET_FAULT_SL(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_SL)
+#define GET_FAULT_SS(b, c)	GET_CONTEXT_FIELD(b, c, PAR, FAULT_SS)
+
+#define GET_NOFAULT_SS(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SS)
+#define GET_NOFAULT_MT(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_MT)
+#define GET_NOFAULT_SH(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SH)
+#define GET_NOFAULT_NS(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NS)
+#define GET_NOFAULT_NOS(b, c)   GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NOS)
+#define GET_NPFAULT_PA(b, c)	GET_CONTEXT_FIELD(b, c, PAR, PAR_NPFAULT_PA)
+
+
+/* PRRR */
+#define GET_MTC0(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC0)
+#define GET_MTC1(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC1)
+#define GET_MTC2(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC2)
+#define GET_MTC3(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC3)
+#define GET_MTC4(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC4)
+#define GET_MTC5(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC5)
+#define GET_MTC6(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC6)
+#define GET_MTC7(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, MTC7)
+#define GET_SHDSH0(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHDSH0)
+#define GET_SHDSH1(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHDSH1)
+#define GET_SHNMSH0(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0)
+#define GET_SHNMSH1(b, c)	GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1)
+#define GET_NOS0(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS0)
+#define GET_NOS1(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS1)
+#define GET_NOS2(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS2)
+#define GET_NOS3(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS3)
+#define GET_NOS4(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS4)
+#define GET_NOS5(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS5)
+#define GET_NOS6(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS6)
+#define GET_NOS7(b, c)		GET_CONTEXT_FIELD(b, c, PRRR, NOS7)
+
+
+/* RESUME */
+#define GET_TNR(b, c)		GET_CONTEXT_FIELD(b, c, RESUME, TNR)
+
+
+/* SCTLR */
+#define GET_M(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, M)
+#define GET_TRE(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, TRE)
+#define GET_AFE(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, AFE)
+#define GET_HAF(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, HAF)
+#define GET_BE(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, BE)
+#define GET_AFFD(b, c)		GET_CONTEXT_FIELD(b, c, SCTLR, AFFD)
+
+
+/* TLBLKCR */
+#define GET_LKE(b, c)		GET_CONTEXT_FIELD(b, c, TLBLKCR, LKE)
+#define GET_TLBLCKR_TLBIALLCFG(b, c) \
+			GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG)
+#define GET_TLBIASIDCFG(b, c)   GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG)
+#define GET_TLBIVAACFG(b, c)	GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG)
+#define GET_FLOOR(b, c)		GET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR)
+#define GET_VICTIM(b, c)	GET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM)
+
+
+/* TTBCR */
+#define GET_N(b, c)		GET_CONTEXT_FIELD(b, c, TTBCR, N)
+#define GET_PD0(b, c)		GET_CONTEXT_FIELD(b, c, TTBCR, PD0)
+#define GET_PD1(b, c)		GET_CONTEXT_FIELD(b, c, TTBCR, PD1)
+
+
+/* TTBR0 */
+#define GET_TTBR0_IRGNH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH)
+#define GET_TTBR0_SH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH)
+#define GET_TTBR0_ORGN(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN)
+#define GET_TTBR0_NOS(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS)
+#define GET_TTBR0_IRGNL(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL)
+#define GET_TTBR0_PA(b, c)	GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA)
+
+
+/* TTBR1 */
+#define GET_TTBR1_IRGNH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH)
+#define GET_TTBR1_SH(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH)
+#define GET_TTBR1_ORGN(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN)
+#define GET_TTBR1_NOS(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS)
+#define GET_TTBR1_IRGNL(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL)
+#define GET_TTBR1_PA(b, c)	GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA)
+
+
+/* V2PSR */
+#define GET_HIT(b, c)		GET_CONTEXT_FIELD(b, c, V2PSR, HIT)
+#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)
+#define TLBRSW		(0xFFE00)
+#define TLBTR0		(0xFFE80)
+#define TLBTR1		(0xFFE84)
+#define TLBTR2		(0xFFE88)
+#define TESTBUSCR	(0xFFE8C)
+#define GLOBAL_TLBIALL	(0xFFF00)
+#define TLBIVMID	(0xFFF04)
+#define CR		(0xFFF80)
+#define EAR		(0xFFF84)
+#define ESR		(0xFFF88)
+#define ESRRESTORE	(0xFFF8C)
+#define ESYNR0		(0xFFF90)
+#define ESYNR1		(0xFFF94)
+#define REV		(0xFFFF4)
+#define IDR		(0xFFFF8)
+#define RPU_ACR		(0xFFFFC)
+
+
+/* Context Bank Registers */
+#define SCTLR		(0x000)
+#define ACTLR		(0x004)
+#define CONTEXTIDR	(0x008)
+#define TTBR0		(0x010)
+#define TTBR1		(0x014)
+#define TTBCR		(0x018)
+#define PAR		(0x01C)
+#define FSR		(0x020)
+#define FSRRESTORE	(0x024)
+#define FAR		(0x028)
+#define FSYNR0		(0x02C)
+#define FSYNR1		(0x030)
+#define PRRR		(0x034)
+#define NMRR		(0x038)
+#define TLBLCKR		(0x03C)
+#define V2PSR		(0x040)
+#define TLBFLPTER	(0x044)
+#define TLBSLPTER	(0x048)
+#define BFBCR		(0x04C)
+#define CTX_TLBIALL	(0x800)
+#define TLBIASID	(0x804)
+#define TLBIVA		(0x808)
+#define TLBIVAA		(0x80C)
+#define V2PPR		(0x810)
+#define V2PPW		(0x814)
+#define V2PUR		(0x818)
+#define V2PUW		(0x81C)
+#define RESUME		(0x820)
+
+
+/* Global Register Fields */
+/* CBACRn */
+#define RWVMID        (RWVMID_MASK       << RWVMID_SHIFT)
+#define RWE           (RWE_MASK          << RWE_SHIFT)
+#define RWGE          (RWGE_MASK         << RWGE_SHIFT)
+#define CBVMID        (CBVMID_MASK       << CBVMID_SHIFT)
+#define IRPTNDX       (IRPTNDX_MASK      << IRPTNDX_SHIFT)
+
+
+/* CR */
+#define RPUE          (RPUE_MASK          << RPUE_SHIFT)
+#define RPUERE        (RPUERE_MASK        << RPUERE_SHIFT)
+#define RPUEIE        (RPUEIE_MASK        << RPUEIE_SHIFT)
+#define DCDEE         (DCDEE_MASK         << DCDEE_SHIFT)
+#define CLIENTPD      (CLIENTPD_MASK      << CLIENTPD_SHIFT)
+#define STALLD        (STALLD_MASK        << STALLD_SHIFT)
+#define TLBLKCRWE     (TLBLKCRWE_MASK     << TLBLKCRWE_SHIFT)
+#define CR_TLBIALLCFG (CR_TLBIALLCFG_MASK << CR_TLBIALLCFG_SHIFT)
+#define TLBIVMIDCFG   (TLBIVMIDCFG_MASK   << TLBIVMIDCFG_SHIFT)
+#define CR_HUME       (CR_HUME_MASK       << CR_HUME_SHIFT)
+
+
+/* ESR */
+#define CFG           (CFG_MASK          << CFG_SHIFT)
+#define BYPASS        (BYPASS_MASK       << BYPASS_SHIFT)
+#define ESR_MULTI     (ESR_MULTI_MASK    << ESR_MULTI_SHIFT)
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID   (ESYNR0_AMID_MASK  << ESYNR0_AMID_SHIFT)
+#define ESYNR0_APID   (ESYNR0_APID_MASK  << ESYNR0_APID_SHIFT)
+#define ESYNR0_ABID   (ESYNR0_ABID_MASK  << ESYNR0_ABID_SHIFT)
+#define ESYNR0_AVMID  (ESYNR0_AVMID_MASK << ESYNR0_AVMID_SHIFT)
+#define ESYNR0_ATID   (ESYNR0_ATID_MASK  << ESYNR0_ATID_SHIFT)
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE      (ESYNR1_AMEMTYPE_MASK    << ESYNR1_AMEMTYPE_SHIFT)
+#define ESYNR1_ASHARED       (ESYNR1_ASHARED_MASK     << ESYNR1_ASHARED_SHIFT)
+#define ESYNR1_AINNERSHARED  (ESYNR1_AINNERSHARED_MASK<< \
+						ESYNR1_AINNERSHARED_SHIFT)
+#define ESYNR1_APRIV         (ESYNR1_APRIV_MASK       << ESYNR1_APRIV_SHIFT)
+#define ESYNR1_APROTNS       (ESYNR1_APROTNS_MASK     << ESYNR1_APROTNS_SHIFT)
+#define ESYNR1_AINST         (ESYNR1_AINST_MASK       << ESYNR1_AINST_SHIFT)
+#define ESYNR1_AWRITE        (ESYNR1_AWRITE_MASK      << ESYNR1_AWRITE_SHIFT)
+#define ESYNR1_ABURST        (ESYNR1_ABURST_MASK      << ESYNR1_ABURST_SHIFT)
+#define ESYNR1_ALEN          (ESYNR1_ALEN_MASK        << ESYNR1_ALEN_SHIFT)
+#define ESYNR1_ASIZE         (ESYNR1_ASIZE_MASK       << ESYNR1_ASIZE_SHIFT)
+#define ESYNR1_ALOCK         (ESYNR1_ALOCK_MASK       << ESYNR1_ALOCK_SHIFT)
+#define ESYNR1_AOOO          (ESYNR1_AOOO_MASK        << ESYNR1_AOOO_SHIFT)
+#define ESYNR1_AFULL         (ESYNR1_AFULL_MASK       << ESYNR1_AFULL_SHIFT)
+#define ESYNR1_AC            (ESYNR1_AC_MASK          << ESYNR1_AC_SHIFT)
+#define ESYNR1_DCD           (ESYNR1_DCD_MASK         << ESYNR1_DCD_SHIFT)
+
+
+/* IDR */
+#define NM2VCBMT      (NM2VCBMT_MASK     << NM2VCBMT_SHIFT)
+#define HTW           (HTW_MASK          << HTW_SHIFT)
+#define HUM           (HUM_MASK          << HUM_SHIFT)
+#define TLBSIZE       (TLBSIZE_MASK      << TLBSIZE_SHIFT)
+#define NCB           (NCB_MASK          << NCB_SHIFT)
+#define NIRPT         (NIRPT_MASK        << NIRPT_SHIFT)
+
+
+/* M2VCBRn */
+#define VMID          (VMID_MASK         << VMID_SHIFT)
+#define CBNDX         (CBNDX_MASK        << CBNDX_SHIFT)
+#define BYPASSD       (BYPASSD_MASK      << BYPASSD_SHIFT)
+#define BPRCOSH       (BPRCOSH_MASK      << BPRCOSH_SHIFT)
+#define BPRCISH       (BPRCISH_MASK      << BPRCISH_SHIFT)
+#define BPRCNSH       (BPRCNSH_MASK      << BPRCNSH_SHIFT)
+#define BPSHCFG       (BPSHCFG_MASK      << BPSHCFG_SHIFT)
+#define NSCFG         (NSCFG_MASK        << NSCFG_SHIFT)
+#define BPMTCFG       (BPMTCFG_MASK      << BPMTCFG_SHIFT)
+#define BPMEMTYPE     (BPMEMTYPE_MASK    << BPMEMTYPE_SHIFT)
+
+
+/* REV */
+#define IDR_MINOR     (MINOR_MASK        << MINOR_SHIFT)
+#define IDR_MAJOR     (MAJOR_MASK        << MAJOR_SHIFT)
+
+
+/* TESTBUSCR */
+#define TBE           (TBE_MASK          << TBE_SHIFT)
+#define SPDMBE        (SPDMBE_MASK       << SPDMBE_SHIFT)
+#define WGSEL         (WGSEL_MASK        << WGSEL_SHIFT)
+#define TBLSEL        (TBLSEL_MASK       << TBLSEL_SHIFT)
+#define TBHSEL        (TBHSEL_MASK       << TBHSEL_SHIFT)
+#define SPDM0SEL      (SPDM0SEL_MASK     << SPDM0SEL_SHIFT)
+#define SPDM1SEL      (SPDM1SEL_MASK     << SPDM1SEL_SHIFT)
+#define SPDM2SEL      (SPDM2SEL_MASK     << SPDM2SEL_SHIFT)
+#define SPDM3SEL      (SPDM3SEL_MASK     << SPDM3SEL_SHIFT)
+
+
+/* TLBIVMID */
+#define TLBIVMID_VMID (TLBIVMID_VMID_MASK << TLBIVMID_VMID_SHIFT)
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX  (TLBRSW_INDEX_MASK << TLBRSW_INDEX_SHIFT)
+#define TLBBFBS       (TLBBFBS_MASK      << TLBBFBS_SHIFT)
+
+
+/* TLBTR0 */
+#define PR            (PR_MASK           << PR_SHIFT)
+#define PW            (PW_MASK           << PW_SHIFT)
+#define UR            (UR_MASK           << UR_SHIFT)
+#define UW            (UW_MASK           << UW_SHIFT)
+#define XN            (XN_MASK           << XN_SHIFT)
+#define NSDESC        (NSDESC_MASK       << NSDESC_SHIFT)
+#define ISH           (ISH_MASK          << ISH_SHIFT)
+#define SH            (SH_MASK           << SH_SHIFT)
+#define MT            (MT_MASK           << MT_SHIFT)
+#define DPSIZR        (DPSIZR_MASK       << DPSIZR_SHIFT)
+#define DPSIZC        (DPSIZC_MASK       << DPSIZC_SHIFT)
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID   (TLBTR1_VMID_MASK  << TLBTR1_VMID_SHIFT)
+#define TLBTR1_PA     (TLBTR1_PA_MASK    << TLBTR1_PA_SHIFT)
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID   (TLBTR2_ASID_MASK  << TLBTR2_ASID_SHIFT)
+#define TLBTR2_V      (TLBTR2_V_MASK     << TLBTR2_V_SHIFT)
+#define TLBTR2_NSTID  (TLBTR2_NSTID_MASK << TLBTR2_NSTID_SHIFT)
+#define TLBTR2_NV     (TLBTR2_NV_MASK    << TLBTR2_NV_SHIFT)
+#define TLBTR2_VA     (TLBTR2_VA_MASK    << TLBTR2_VA_SHIFT)
+
+
+/* Context Register Fields */
+/* ACTLR */
+#define CFERE              (CFERE_MASK              << CFERE_SHIFT)
+#define CFEIE              (CFEIE_MASK              << CFEIE_SHIFT)
+#define PTSHCFG            (PTSHCFG_MASK            << PTSHCFG_SHIFT)
+#define RCOSH              (RCOSH_MASK              << RCOSH_SHIFT)
+#define RCISH              (RCISH_MASK              << RCISH_SHIFT)
+#define RCNSH              (RCNSH_MASK              << RCNSH_SHIFT)
+#define PRIVCFG            (PRIVCFG_MASK            << PRIVCFG_SHIFT)
+#define DNA                (DNA_MASK                << DNA_SHIFT)
+#define DNLV2PA            (DNLV2PA_MASK            << DNLV2PA_SHIFT)
+#define TLBMCFG            (TLBMCFG_MASK            << TLBMCFG_SHIFT)
+#define CFCFG              (CFCFG_MASK              << CFCFG_SHIFT)
+#define TIPCF              (TIPCF_MASK              << TIPCF_SHIFT)
+#define V2PCFG             (V2PCFG_MASK             << V2PCFG_SHIFT)
+#define HUME               (HUME_MASK               << HUME_SHIFT)
+#define PTMTCFG            (PTMTCFG_MASK            << PTMTCFG_SHIFT)
+#define PTMEMTYPE          (PTMEMTYPE_MASK          << PTMEMTYPE_SHIFT)
+
+
+/* BFBCR */
+#define BFBDFE             (BFBDFE_MASK             << BFBDFE_SHIFT)
+#define BFBSFE             (BFBSFE_MASK             << BFBSFE_SHIFT)
+#define SFVS               (SFVS_MASK               << SFVS_SHIFT)
+#define FLVIC              (FLVIC_MASK              << FLVIC_SHIFT)
+#define SLVIC              (SLVIC_MASK              << SLVIC_SHIFT)
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID    (CONTEXTIDR_ASID_MASK    << CONTEXTIDR_ASID_SHIFT)
+#define PROCID             (PROCID_MASK             << PROCID_SHIFT)
+
+
+/* FSR */
+#define TF                 (TF_MASK                 << TF_SHIFT)
+#define AFF                (AFF_MASK                << AFF_SHIFT)
+#define APF                (APF_MASK                << APF_SHIFT)
+#define TLBMF              (TLBMF_MASK              << TLBMF_SHIFT)
+#define HTWDEEF            (HTWDEEF_MASK            << HTWDEEF_SHIFT)
+#define HTWSEEF            (HTWSEEF_MASK            << HTWSEEF_SHIFT)
+#define MHF                (MHF_MASK                << MHF_SHIFT)
+#define SL                 (SL_MASK                 << SL_SHIFT)
+#define SS                 (SS_MASK                 << SS_SHIFT)
+#define MULTI              (MULTI_MASK              << MULTI_SHIFT)
+
+
+/* FSYNR0 */
+#define AMID               (AMID_MASK               << AMID_SHIFT)
+#define APID               (APID_MASK               << APID_SHIFT)
+#define ABID               (ABID_MASK               << ABID_SHIFT)
+#define ATID               (ATID_MASK               << ATID_SHIFT)
+
+
+/* FSYNR1 */
+#define AMEMTYPE           (AMEMTYPE_MASK           << AMEMTYPE_SHIFT)
+#define ASHARED            (ASHARED_MASK            << ASHARED_SHIFT)
+#define AINNERSHARED       (AINNERSHARED_MASK       << AINNERSHARED_SHIFT)
+#define APRIV              (APRIV_MASK              << APRIV_SHIFT)
+#define APROTNS            (APROTNS_MASK            << APROTNS_SHIFT)
+#define AINST              (AINST_MASK              << AINST_SHIFT)
+#define AWRITE             (AWRITE_MASK             << AWRITE_SHIFT)
+#define ABURST             (ABURST_MASK             << ABURST_SHIFT)
+#define ALEN               (ALEN_MASK               << ALEN_SHIFT)
+#define FSYNR1_ASIZE       (FSYNR1_ASIZE_MASK       << FSYNR1_ASIZE_SHIFT)
+#define ALOCK              (ALOCK_MASK              << ALOCK_SHIFT)
+#define AFULL              (AFULL_MASK              << AFULL_SHIFT)
+
+
+/* NMRR */
+#define ICPC0              (ICPC0_MASK              << ICPC0_SHIFT)
+#define ICPC1              (ICPC1_MASK              << ICPC1_SHIFT)
+#define ICPC2              (ICPC2_MASK              << ICPC2_SHIFT)
+#define ICPC3              (ICPC3_MASK              << ICPC3_SHIFT)
+#define ICPC4              (ICPC4_MASK              << ICPC4_SHIFT)
+#define ICPC5              (ICPC5_MASK              << ICPC5_SHIFT)
+#define ICPC6              (ICPC6_MASK              << ICPC6_SHIFT)
+#define ICPC7              (ICPC7_MASK              << ICPC7_SHIFT)
+#define OCPC0              (OCPC0_MASK              << OCPC0_SHIFT)
+#define OCPC1              (OCPC1_MASK              << OCPC1_SHIFT)
+#define OCPC2              (OCPC2_MASK              << OCPC2_SHIFT)
+#define OCPC3              (OCPC3_MASK              << OCPC3_SHIFT)
+#define OCPC4              (OCPC4_MASK              << OCPC4_SHIFT)
+#define OCPC5              (OCPC5_MASK              << OCPC5_SHIFT)
+#define OCPC6              (OCPC6_MASK              << OCPC6_SHIFT)
+#define OCPC7              (OCPC7_MASK              << OCPC7_SHIFT)
+
+
+/* PAR */
+#define FAULT              (FAULT_MASK              << FAULT_SHIFT)
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF           (FAULT_TF_MASK           << FAULT_TF_SHIFT)
+#define FAULT_AFF          (FAULT_AFF_MASK          << FAULT_AFF_SHIFT)
+#define FAULT_APF          (FAULT_APF_MASK          << FAULT_APF_SHIFT)
+#define FAULT_TLBMF        (FAULT_TLBMF_MASK        << FAULT_TLBMF_SHIFT)
+#define FAULT_HTWDEEF      (FAULT_HTWDEEF_MASK      << FAULT_HTWDEEF_SHIFT)
+#define FAULT_HTWSEEF      (FAULT_HTWSEEF_MASK      << FAULT_HTWSEEF_SHIFT)
+#define FAULT_MHF          (FAULT_MHF_MASK          << FAULT_MHF_SHIFT)
+#define FAULT_SL           (FAULT_SL_MASK           << FAULT_SL_SHIFT)
+#define FAULT_SS           (FAULT_SS_MASK           << FAULT_SS_SHIFT)
+
+/* If NO fault is present, the following fields are in effect */
+/* (FAULT remains as before) */
+#define PAR_NOFAULT_SS     (PAR_NOFAULT_SS_MASK     << PAR_NOFAULT_SS_SHIFT)
+#define PAR_NOFAULT_MT     (PAR_NOFAULT_MT_MASK     << PAR_NOFAULT_MT_SHIFT)
+#define PAR_NOFAULT_SH     (PAR_NOFAULT_SH_MASK     << PAR_NOFAULT_SH_SHIFT)
+#define PAR_NOFAULT_NS     (PAR_NOFAULT_NS_MASK     << PAR_NOFAULT_NS_SHIFT)
+#define PAR_NOFAULT_NOS    (PAR_NOFAULT_NOS_MASK    << PAR_NOFAULT_NOS_SHIFT)
+#define PAR_NPFAULT_PA     (PAR_NPFAULT_PA_MASK     << PAR_NPFAULT_PA_SHIFT)
+
+
+/* PRRR */
+#define MTC0               (MTC0_MASK               << MTC0_SHIFT)
+#define MTC1               (MTC1_MASK               << MTC1_SHIFT)
+#define MTC2               (MTC2_MASK               << MTC2_SHIFT)
+#define MTC3               (MTC3_MASK               << MTC3_SHIFT)
+#define MTC4               (MTC4_MASK               << MTC4_SHIFT)
+#define MTC5               (MTC5_MASK               << MTC5_SHIFT)
+#define MTC6               (MTC6_MASK               << MTC6_SHIFT)
+#define MTC7               (MTC7_MASK               << MTC7_SHIFT)
+#define SHDSH0             (SHDSH0_MASK             << SHDSH0_SHIFT)
+#define SHDSH1             (SHDSH1_MASK             << SHDSH1_SHIFT)
+#define SHNMSH0            (SHNMSH0_MASK            << SHNMSH0_SHIFT)
+#define SHNMSH1            (SHNMSH1_MASK            << SHNMSH1_SHIFT)
+#define NOS0               (NOS0_MASK               << NOS0_SHIFT)
+#define NOS1               (NOS1_MASK               << NOS1_SHIFT)
+#define NOS2               (NOS2_MASK               << NOS2_SHIFT)
+#define NOS3               (NOS3_MASK               << NOS3_SHIFT)
+#define NOS4               (NOS4_MASK               << NOS4_SHIFT)
+#define NOS5               (NOS5_MASK               << NOS5_SHIFT)
+#define NOS6               (NOS6_MASK               << NOS6_SHIFT)
+#define NOS7               (NOS7_MASK               << NOS7_SHIFT)
+
+
+/* RESUME */
+#define TNR                (TNR_MASK                << TNR_SHIFT)
+
+
+/* SCTLR */
+#define M                  (M_MASK                  << M_SHIFT)
+#define TRE                (TRE_MASK                << TRE_SHIFT)
+#define AFE                (AFE_MASK                << AFE_SHIFT)
+#define HAF                (HAF_MASK                << HAF_SHIFT)
+#define BE                 (BE_MASK                 << BE_SHIFT)
+#define AFFD               (AFFD_MASK               << AFFD_SHIFT)
+
+
+/* TLBIASID */
+#define TLBIASID_ASID      (TLBIASID_ASID_MASK      << TLBIASID_ASID_SHIFT)
+
+
+/* TLBIVA */
+#define TLBIVA_ASID        (TLBIVA_ASID_MASK        << TLBIVA_ASID_SHIFT)
+#define TLBIVA_VA          (TLBIVA_VA_MASK          << TLBIVA_VA_SHIFT)
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA         (TLBIVAA_VA_MASK         << TLBIVAA_VA_SHIFT)
+
+
+/* TLBLCKR */
+#define LKE                (LKE_MASK                << LKE_SHIFT)
+#define TLBLCKR_TLBIALLCFG (TLBLCKR_TLBIALLCFG_MASK<<TLBLCKR_TLBIALLCFG_SHIFT)
+#define TLBIASIDCFG        (TLBIASIDCFG_MASK        << TLBIASIDCFG_SHIFT)
+#define TLBIVAACFG         (TLBIVAACFG_MASK         << TLBIVAACFG_SHIFT)
+#define FLOOR              (FLOOR_MASK              << FLOOR_SHIFT)
+#define VICTIM             (VICTIM_MASK             << VICTIM_SHIFT)
+
+
+/* TTBCR */
+#define N                  (N_MASK                  << N_SHIFT)
+#define PD0                (PD0_MASK                << PD0_SHIFT)
+#define PD1                (PD1_MASK                << PD1_SHIFT)
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH        (TTBR0_IRGNH_MASK        << TTBR0_IRGNH_SHIFT)
+#define TTBR0_SH           (TTBR0_SH_MASK           << TTBR0_SH_SHIFT)
+#define TTBR0_ORGN         (TTBR0_ORGN_MASK         << TTBR0_ORGN_SHIFT)
+#define TTBR0_NOS          (TTBR0_NOS_MASK          << TTBR0_NOS_SHIFT)
+#define TTBR0_IRGNL        (TTBR0_IRGNL_MASK        << TTBR0_IRGNL_SHIFT)
+#define TTBR0_PA           (TTBR0_PA_MASK           << TTBR0_PA_SHIFT)
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH        (TTBR1_IRGNH_MASK        << TTBR1_IRGNH_SHIFT)
+#define TTBR1_SH           (TTBR1_SH_MASK           << TTBR1_SH_SHIFT)
+#define TTBR1_ORGN         (TTBR1_ORGN_MASK         << TTBR1_ORGN_SHIFT)
+#define TTBR1_NOS          (TTBR1_NOS_MASK          << TTBR1_NOS_SHIFT)
+#define TTBR1_IRGNL        (TTBR1_IRGNL_MASK        << TTBR1_IRGNL_SHIFT)
+#define TTBR1_PA           (TTBR1_PA_MASK           << TTBR1_PA_SHIFT)
+
+
+/* V2PSR */
+#define HIT                (HIT_MASK                << HIT_SHIFT)
+#define INDEX              (INDEX_MASK              << INDEX_SHIFT)
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX        (V2Pxx_INDEX_MASK        << V2Pxx_INDEX_SHIFT)
+#define V2Pxx_VA           (V2Pxx_VA_MASK           << V2Pxx_VA_SHIFT)
+
+
+/* Global Register Masks */
+/* CBACRn */
+#define RWVMID_MASK               0x1F
+#define RWE_MASK                  0x01
+#define RWGE_MASK                 0x01
+#define CBVMID_MASK               0x1F
+#define IRPTNDX_MASK              0xFF
+
+
+/* CR */
+#define RPUE_MASK                 0x01
+#define RPUERE_MASK               0x01
+#define RPUEIE_MASK               0x01
+#define DCDEE_MASK                0x01
+#define CLIENTPD_MASK             0x01
+#define STALLD_MASK               0x01
+#define TLBLKCRWE_MASK            0x01
+#define CR_TLBIALLCFG_MASK        0x01
+#define TLBIVMIDCFG_MASK          0x01
+#define CR_HUME_MASK              0x01
+
+
+/* ESR */
+#define CFG_MASK                  0x01
+#define BYPASS_MASK               0x01
+#define ESR_MULTI_MASK            0x01
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID_MASK          0xFF
+#define ESYNR0_APID_MASK          0x1F
+#define ESYNR0_ABID_MASK          0x07
+#define ESYNR0_AVMID_MASK         0x1F
+#define ESYNR0_ATID_MASK          0xFF
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE_MASK             0x07
+#define ESYNR1_ASHARED_MASK              0x01
+#define ESYNR1_AINNERSHARED_MASK         0x01
+#define ESYNR1_APRIV_MASK                0x01
+#define ESYNR1_APROTNS_MASK              0x01
+#define ESYNR1_AINST_MASK                0x01
+#define ESYNR1_AWRITE_MASK               0x01
+#define ESYNR1_ABURST_MASK               0x01
+#define ESYNR1_ALEN_MASK                 0x0F
+#define ESYNR1_ASIZE_MASK                0x01
+#define ESYNR1_ALOCK_MASK                0x03
+#define ESYNR1_AOOO_MASK                 0x01
+#define ESYNR1_AFULL_MASK                0x01
+#define ESYNR1_AC_MASK                   0x01
+#define ESYNR1_DCD_MASK                  0x01
+
+
+/* IDR */
+#define NM2VCBMT_MASK             0x1FF
+#define HTW_MASK                  0x01
+#define HUM_MASK                  0x01
+#define TLBSIZE_MASK              0x0F
+#define NCB_MASK                  0xFF
+#define NIRPT_MASK                0xFF
+
+
+/* M2VCBRn */
+#define VMID_MASK                 0x1F
+#define CBNDX_MASK                0xFF
+#define BYPASSD_MASK              0x01
+#define BPRCOSH_MASK              0x01
+#define BPRCISH_MASK              0x01
+#define BPRCNSH_MASK              0x01
+#define BPSHCFG_MASK              0x03
+#define NSCFG_MASK                0x03
+#define BPMTCFG_MASK              0x01
+#define BPMEMTYPE_MASK            0x07
+
+
+/* REV */
+#define MINOR_MASK                0x0F
+#define MAJOR_MASK                0x0F
+
+
+/* TESTBUSCR */
+#define TBE_MASK                  0x01
+#define SPDMBE_MASK               0x01
+#define WGSEL_MASK                0x03
+#define TBLSEL_MASK               0x03
+#define TBHSEL_MASK               0x03
+#define SPDM0SEL_MASK             0x0F
+#define SPDM1SEL_MASK             0x0F
+#define SPDM2SEL_MASK             0x0F
+#define SPDM3SEL_MASK             0x0F
+
+
+/* TLBIMID */
+#define TLBIVMID_VMID_MASK        0x1F
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX_MASK         0xFF
+#define TLBBFBS_MASK              0x03
+
+
+/* TLBTR0 */
+#define PR_MASK                   0x01
+#define PW_MASK                   0x01
+#define UR_MASK                   0x01
+#define UW_MASK                   0x01
+#define XN_MASK                   0x01
+#define NSDESC_MASK               0x01
+#define ISH_MASK                  0x01
+#define SH_MASK                   0x01
+#define MT_MASK                   0x07
+#define DPSIZR_MASK               0x07
+#define DPSIZC_MASK               0x07
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID_MASK          0x1F
+#define TLBTR1_PA_MASK            0x000FFFFF
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID_MASK          0xFF
+#define TLBTR2_V_MASK             0x01
+#define TLBTR2_NSTID_MASK         0x01
+#define TLBTR2_NV_MASK            0x01
+#define TLBTR2_VA_MASK            0x000FFFFF
+
+
+/* Global Register Shifts */
+/* CBACRn */
+#define RWVMID_SHIFT             0
+#define RWE_SHIFT                8
+#define RWGE_SHIFT               9
+#define CBVMID_SHIFT             16
+#define IRPTNDX_SHIFT            24
+
+
+/* CR */
+#define RPUE_SHIFT               0
+#define RPUERE_SHIFT             1
+#define RPUEIE_SHIFT             2
+#define DCDEE_SHIFT              3
+#define CLIENTPD_SHIFT           4
+#define STALLD_SHIFT             5
+#define TLBLKCRWE_SHIFT          6
+#define CR_TLBIALLCFG_SHIFT      7
+#define TLBIVMIDCFG_SHIFT        8
+#define CR_HUME_SHIFT            9
+
+
+/* ESR */
+#define CFG_SHIFT                0
+#define BYPASS_SHIFT             1
+#define ESR_MULTI_SHIFT          31
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID_SHIFT        0
+#define ESYNR0_APID_SHIFT        8
+#define ESYNR0_ABID_SHIFT        13
+#define ESYNR0_AVMID_SHIFT       16
+#define ESYNR0_ATID_SHIFT        24
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE_SHIFT           0
+#define ESYNR1_ASHARED_SHIFT            3
+#define ESYNR1_AINNERSHARED_SHIFT       4
+#define ESYNR1_APRIV_SHIFT              5
+#define ESYNR1_APROTNS_SHIFT            6
+#define ESYNR1_AINST_SHIFT              7
+#define ESYNR1_AWRITE_SHIFT             8
+#define ESYNR1_ABURST_SHIFT             10
+#define ESYNR1_ALEN_SHIFT               12
+#define ESYNR1_ASIZE_SHIFT              16
+#define ESYNR1_ALOCK_SHIFT              20
+#define ESYNR1_AOOO_SHIFT               22
+#define ESYNR1_AFULL_SHIFT              24
+#define ESYNR1_AC_SHIFT                 30
+#define ESYNR1_DCD_SHIFT                31
+
+
+/* IDR */
+#define NM2VCBMT_SHIFT           0
+#define HTW_SHIFT                9
+#define HUM_SHIFT                10
+#define TLBSIZE_SHIFT            12
+#define NCB_SHIFT                16
+#define NIRPT_SHIFT              24
+
+
+/* M2VCBRn */
+#define VMID_SHIFT               0
+#define CBNDX_SHIFT              8
+#define BYPASSD_SHIFT            16
+#define BPRCOSH_SHIFT            17
+#define BPRCISH_SHIFT            18
+#define BPRCNSH_SHIFT            19
+#define BPSHCFG_SHIFT            20
+#define NSCFG_SHIFT              22
+#define BPMTCFG_SHIFT            24
+#define BPMEMTYPE_SHIFT          25
+
+
+/* REV */
+#define MINOR_SHIFT              0
+#define MAJOR_SHIFT              4
+
+
+/* TESTBUSCR */
+#define TBE_SHIFT                0
+#define SPDMBE_SHIFT             1
+#define WGSEL_SHIFT              8
+#define TBLSEL_SHIFT             12
+#define TBHSEL_SHIFT             14
+#define SPDM0SEL_SHIFT           16
+#define SPDM1SEL_SHIFT           20
+#define SPDM2SEL_SHIFT           24
+#define SPDM3SEL_SHIFT           28
+
+
+/* TLBIMID */
+#define TLBIVMID_VMID_SHIFT      0
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX_SHIFT       0
+#define TLBBFBS_SHIFT            8
+
+
+/* TLBTR0 */
+#define PR_SHIFT                 0
+#define PW_SHIFT                 1
+#define UR_SHIFT                 2
+#define UW_SHIFT                 3
+#define XN_SHIFT                 4
+#define NSDESC_SHIFT             6
+#define ISH_SHIFT                7
+#define SH_SHIFT                 8
+#define MT_SHIFT                 9
+#define DPSIZR_SHIFT             16
+#define DPSIZC_SHIFT             20
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID_SHIFT        0
+#define TLBTR1_PA_SHIFT          12
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID_SHIFT        0
+#define TLBTR2_V_SHIFT           8
+#define TLBTR2_NSTID_SHIFT       9
+#define TLBTR2_NV_SHIFT          10
+#define TLBTR2_VA_SHIFT          12
+
+
+/* Context Register Masks */
+/* ACTLR */
+#define CFERE_MASK                       0x01
+#define CFEIE_MASK                       0x01
+#define PTSHCFG_MASK                     0x03
+#define RCOSH_MASK                       0x01
+#define RCISH_MASK                       0x01
+#define RCNSH_MASK                       0x01
+#define PRIVCFG_MASK                     0x03
+#define DNA_MASK                         0x01
+#define DNLV2PA_MASK                     0x01
+#define TLBMCFG_MASK                     0x03
+#define CFCFG_MASK                       0x01
+#define TIPCF_MASK                       0x01
+#define V2PCFG_MASK                      0x03
+#define HUME_MASK                        0x01
+#define PTMTCFG_MASK                     0x01
+#define PTMEMTYPE_MASK                   0x07
+
+
+/* BFBCR */
+#define BFBDFE_MASK                      0x01
+#define BFBSFE_MASK                      0x01
+#define SFVS_MASK                        0x01
+#define FLVIC_MASK                       0x0F
+#define SLVIC_MASK                       0x0F
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID_MASK             0xFF
+#define PROCID_MASK                      0x00FFFFFF
+
+
+/* FSR */
+#define TF_MASK                          0x01
+#define AFF_MASK                         0x01
+#define APF_MASK                         0x01
+#define TLBMF_MASK                       0x01
+#define HTWDEEF_MASK                     0x01
+#define HTWSEEF_MASK                     0x01
+#define MHF_MASK                         0x01
+#define SL_MASK                          0x01
+#define SS_MASK                          0x01
+#define MULTI_MASK                       0x01
+
+
+/* FSYNR0 */
+#define AMID_MASK                        0xFF
+#define APID_MASK                        0x1F
+#define ABID_MASK                        0x07
+#define ATID_MASK                        0xFF
+
+
+/* FSYNR1 */
+#define AMEMTYPE_MASK                    0x07
+#define ASHARED_MASK                     0x01
+#define AINNERSHARED_MASK                0x01
+#define APRIV_MASK                       0x01
+#define APROTNS_MASK                     0x01
+#define AINST_MASK                       0x01
+#define AWRITE_MASK                      0x01
+#define ABURST_MASK                      0x01
+#define ALEN_MASK                        0x0F
+#define FSYNR1_ASIZE_MASK                0x07
+#define ALOCK_MASK                       0x03
+#define AFULL_MASK                       0x01
+
+
+/* NMRR */
+#define ICPC0_MASK                       0x03
+#define ICPC1_MASK                       0x03
+#define ICPC2_MASK                       0x03
+#define ICPC3_MASK                       0x03
+#define ICPC4_MASK                       0x03
+#define ICPC5_MASK                       0x03
+#define ICPC6_MASK                       0x03
+#define ICPC7_MASK                       0x03
+#define OCPC0_MASK                       0x03
+#define OCPC1_MASK                       0x03
+#define OCPC2_MASK                       0x03
+#define OCPC3_MASK                       0x03
+#define OCPC4_MASK                       0x03
+#define OCPC5_MASK                       0x03
+#define OCPC6_MASK                       0x03
+#define OCPC7_MASK                       0x03
+
+
+/* PAR */
+#define FAULT_MASK                       0x01
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF_MASK                    0x01
+#define FAULT_AFF_MASK                   0x01
+#define FAULT_APF_MASK                   0x01
+#define FAULT_TLBMF_MASK                 0x01
+#define FAULT_HTWDEEF_MASK               0x01
+#define FAULT_HTWSEEF_MASK               0x01
+#define FAULT_MHF_MASK                   0x01
+#define FAULT_SL_MASK                    0x01
+#define FAULT_SS_MASK                    0x01
+
+/* If NO fault is present, the following
+ * fields are in effect
+ * (FAULT remains as before) */
+#define PAR_NOFAULT_SS_MASK              0x01
+#define PAR_NOFAULT_MT_MASK              0x07
+#define PAR_NOFAULT_SH_MASK              0x01
+#define PAR_NOFAULT_NS_MASK              0x01
+#define PAR_NOFAULT_NOS_MASK             0x01
+#define PAR_NPFAULT_PA_MASK              0x000FFFFF
+
+
+/* PRRR */
+#define MTC0_MASK                        0x03
+#define MTC1_MASK                        0x03
+#define MTC2_MASK                        0x03
+#define MTC3_MASK                        0x03
+#define MTC4_MASK                        0x03
+#define MTC5_MASK                        0x03
+#define MTC6_MASK                        0x03
+#define MTC7_MASK                        0x03
+#define SHDSH0_MASK                      0x01
+#define SHDSH1_MASK                      0x01
+#define SHNMSH0_MASK                     0x01
+#define SHNMSH1_MASK                     0x01
+#define NOS0_MASK                        0x01
+#define NOS1_MASK                        0x01
+#define NOS2_MASK                        0x01
+#define NOS3_MASK                        0x01
+#define NOS4_MASK                        0x01
+#define NOS5_MASK                        0x01
+#define NOS6_MASK                        0x01
+#define NOS7_MASK                        0x01
+
+
+/* RESUME */
+#define TNR_MASK                         0x01
+
+
+/* SCTLR */
+#define M_MASK                           0x01
+#define TRE_MASK                         0x01
+#define AFE_MASK                         0x01
+#define HAF_MASK                         0x01
+#define BE_MASK                          0x01
+#define AFFD_MASK                        0x01
+
+
+/* TLBIASID */
+#define TLBIASID_ASID_MASK               0xFF
+
+
+/* TLBIVA */
+#define TLBIVA_ASID_MASK                 0xFF
+#define TLBIVA_VA_MASK                   0x000FFFFF
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA_MASK                  0x000FFFFF
+
+
+/* TLBLCKR */
+#define LKE_MASK                         0x01
+#define TLBLCKR_TLBIALLCFG_MASK          0x01
+#define TLBIASIDCFG_MASK                 0x01
+#define TLBIVAACFG_MASK                  0x01
+#define FLOOR_MASK                       0xFF
+#define VICTIM_MASK                      0xFF
+
+
+/* TTBCR */
+#define N_MASK                           0x07
+#define PD0_MASK                         0x01
+#define PD1_MASK                         0x01
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH_MASK                 0x01
+#define TTBR0_SH_MASK                    0x01
+#define TTBR0_ORGN_MASK                  0x03
+#define TTBR0_NOS_MASK                   0x01
+#define TTBR0_IRGNL_MASK                 0x01
+#define TTBR0_PA_MASK                    0x0003FFFF
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH_MASK                 0x01
+#define TTBR1_SH_MASK                    0x01
+#define TTBR1_ORGN_MASK                  0x03
+#define TTBR1_NOS_MASK                   0x01
+#define TTBR1_IRGNL_MASK                 0x01
+#define TTBR1_PA_MASK                    0x0003FFFF
+
+
+/* V2PSR */
+#define HIT_MASK                         0x01
+#define INDEX_MASK                       0xFF
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX_MASK                 0xFF
+#define V2Pxx_VA_MASK                    0x000FFFFF
+
+
+/* Context Register Shifts */
+/* ACTLR */
+#define CFERE_SHIFT                    0
+#define CFEIE_SHIFT                    1
+#define PTSHCFG_SHIFT                  2
+#define RCOSH_SHIFT                    4
+#define RCISH_SHIFT                    5
+#define RCNSH_SHIFT                    6
+#define PRIVCFG_SHIFT                  8
+#define DNA_SHIFT                      10
+#define DNLV2PA_SHIFT                  11
+#define TLBMCFG_SHIFT                  12
+#define CFCFG_SHIFT                    14
+#define TIPCF_SHIFT                    15
+#define V2PCFG_SHIFT                   16
+#define HUME_SHIFT                     18
+#define PTMTCFG_SHIFT                  20
+#define PTMEMTYPE_SHIFT                21
+
+
+/* BFBCR */
+#define BFBDFE_SHIFT                   0
+#define BFBSFE_SHIFT                   1
+#define SFVS_SHIFT                     2
+#define FLVIC_SHIFT                    4
+#define SLVIC_SHIFT                    8
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID_SHIFT          0
+#define PROCID_SHIFT                   8
+
+
+/* FSR */
+#define TF_SHIFT                       1
+#define AFF_SHIFT                      2
+#define APF_SHIFT                      3
+#define TLBMF_SHIFT                    4
+#define HTWDEEF_SHIFT                  5
+#define HTWSEEF_SHIFT                  6
+#define MHF_SHIFT                      7
+#define SL_SHIFT                       16
+#define SS_SHIFT                       30
+#define MULTI_SHIFT                    31
+
+
+/* FSYNR0 */
+#define AMID_SHIFT                     0
+#define APID_SHIFT                     8
+#define ABID_SHIFT                     13
+#define ATID_SHIFT                     24
+
+
+/* FSYNR1 */
+#define AMEMTYPE_SHIFT                 0
+#define ASHARED_SHIFT                  3
+#define AINNERSHARED_SHIFT             4
+#define APRIV_SHIFT                    5
+#define APROTNS_SHIFT                  6
+#define AINST_SHIFT                    7
+#define AWRITE_SHIFT                   8
+#define ABURST_SHIFT                   10
+#define ALEN_SHIFT                     12
+#define FSYNR1_ASIZE_SHIFT             16
+#define ALOCK_SHIFT                    20
+#define AFULL_SHIFT                    24
+
+
+/* NMRR */
+#define ICPC0_SHIFT                    0
+#define ICPC1_SHIFT                    2
+#define ICPC2_SHIFT                    4
+#define ICPC3_SHIFT                    6
+#define ICPC4_SHIFT                    8
+#define ICPC5_SHIFT                    10
+#define ICPC6_SHIFT                    12
+#define ICPC7_SHIFT                    14
+#define OCPC0_SHIFT                    16
+#define OCPC1_SHIFT                    18
+#define OCPC2_SHIFT                    20
+#define OCPC3_SHIFT                    22
+#define OCPC4_SHIFT                    24
+#define OCPC5_SHIFT                    26
+#define OCPC6_SHIFT                    28
+#define OCPC7_SHIFT                    30
+
+
+/* PAR */
+#define FAULT_SHIFT                    0
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF_SHIFT                 1
+#define FAULT_AFF_SHIFT                2
+#define FAULT_APF_SHIFT                3
+#define FAULT_TLBMF_SHIFT              4
+#define FAULT_HTWDEEF_SHIFT            5
+#define FAULT_HTWSEEF_SHIFT            6
+#define FAULT_MHF_SHIFT                7
+#define FAULT_SL_SHIFT                 16
+#define FAULT_SS_SHIFT                 30
+
+/* If NO fault is present, the following
+ * fields are in effect
+ * (FAULT remains as before) */
+#define PAR_NOFAULT_SS_SHIFT           1
+#define PAR_NOFAULT_MT_SHIFT           4
+#define PAR_NOFAULT_SH_SHIFT           7
+#define PAR_NOFAULT_NS_SHIFT           9
+#define PAR_NOFAULT_NOS_SHIFT          10
+#define PAR_NPFAULT_PA_SHIFT           12
+
+
+/* PRRR */
+#define MTC0_SHIFT                     0
+#define MTC1_SHIFT                     2
+#define MTC2_SHIFT                     4
+#define MTC3_SHIFT                     6
+#define MTC4_SHIFT                     8
+#define MTC5_SHIFT                     10
+#define MTC6_SHIFT                     12
+#define MTC7_SHIFT                     14
+#define SHDSH0_SHIFT                   16
+#define SHDSH1_SHIFT                   17
+#define SHNMSH0_SHIFT                  18
+#define SHNMSH1_SHIFT                  19
+#define NOS0_SHIFT                     24
+#define NOS1_SHIFT                     25
+#define NOS2_SHIFT                     26
+#define NOS3_SHIFT                     27
+#define NOS4_SHIFT                     28
+#define NOS5_SHIFT                     29
+#define NOS6_SHIFT                     30
+#define NOS7_SHIFT                     31
+
+
+/* RESUME */
+#define TNR_SHIFT                      0
+
+
+/* SCTLR */
+#define M_SHIFT                        0
+#define TRE_SHIFT                      1
+#define AFE_SHIFT                      2
+#define HAF_SHIFT                      3
+#define BE_SHIFT                       4
+#define AFFD_SHIFT                     5
+
+
+/* TLBIASID */
+#define TLBIASID_ASID_SHIFT            0
+
+
+/* TLBIVA */
+#define TLBIVA_ASID_SHIFT              0
+#define TLBIVA_VA_SHIFT                12
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA_SHIFT               12
+
+
+/* TLBLCKR */
+#define LKE_SHIFT                      0
+#define TLBLCKR_TLBIALLCFG_SHIFT       1
+#define TLBIASIDCFG_SHIFT              2
+#define TLBIVAACFG_SHIFT               3
+#define FLOOR_SHIFT                    8
+#define VICTIM_SHIFT                   8
+
+
+/* TTBCR */
+#define N_SHIFT                        3
+#define PD0_SHIFT                      4
+#define PD1_SHIFT                      5
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH_SHIFT              0
+#define TTBR0_SH_SHIFT                 1
+#define TTBR0_ORGN_SHIFT               3
+#define TTBR0_NOS_SHIFT                5
+#define TTBR0_IRGNL_SHIFT              6
+#define TTBR0_PA_SHIFT                 14
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH_SHIFT              0
+#define TTBR1_SH_SHIFT                 1
+#define TTBR1_ORGN_SHIFT               3
+#define TTBR1_NOS_SHIFT                5
+#define TTBR1_IRGNL_SHIFT              6
+#define TTBR1_PA_SHIFT                 14
+
+
+/* V2PSR */
+#define HIT_SHIFT                      0
+#define INDEX_SHIFT                    8
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX_SHIFT              0
+#define V2Pxx_VA_SHIFT                 12
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs-8x60.h b/arch/arm/mach-msm/include/mach/irqs-8x60.h
new file mode 100644
index 0000000..36074cf
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/irqs-8x60.h
@@ -0,0 +1,253 @@
+/* Copyright (c) 2010 Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_IRQS_8X60_H
+#define __ASM_ARCH_MSM_IRQS_8X60_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_DEBUG_TIMER_EXP			(GIC_PPI_START + 0)
+#define INT_GP_TIMER_EXP			(GIC_PPI_START + 1)
+#define INT_GP_TIMER2_EXP			(GIC_PPI_START + 2)
+#define WDT0_ACCSCSSNBARK_INT			(GIC_PPI_START + 3)
+#define WDT1_ACCSCSSNBARK_INT			(GIC_PPI_START + 4)
+#define AVS_SVICINT				(GIC_PPI_START + 5)
+#define AVS_SVICINTSWDONE			(GIC_PPI_START + 6)
+#define CPU_DBGCPUXCOMMRXFULL			(GIC_PPI_START + 7)
+#define CPU_DBGCPUXCOMMTXEMPTY			(GIC_PPI_START + 8)
+#define CPU_SICCPUXPERFMONIRPTREQ		(GIC_PPI_START + 9)
+#define SC_AVSCPUXDOWN				(GIC_PPI_START + 10)
+#define SC_AVSCPUXUP				(GIC_PPI_START + 11)
+#define SC_SICCPUXACGIRPTREQ			(GIC_PPI_START + 12)
+/* PPI 13 to 15 are unused */
+
+
+#define SC_SICMPUIRPTREQ			(GIC_SPI_START + 0)
+#define SC_SICL2IRPTREQ				(GIC_SPI_START + 1)
+#define SC_SICL2ACGIRPTREQ			(GIC_SPI_START + 2)
+#define NC					(GIC_SPI_START + 3)
+#define TLMM_SCSS_DIR_CONN_IRQ_0		(GIC_SPI_START + 4)
+#define TLMM_SCSS_DIR_CONN_IRQ_1		(GIC_SPI_START + 5)
+#define TLMM_SCSS_DIR_CONN_IRQ_2		(GIC_SPI_START + 6)
+#define TLMM_SCSS_DIR_CONN_IRQ_3		(GIC_SPI_START + 7)
+#define TLMM_SCSS_DIR_CONN_IRQ_4		(GIC_SPI_START + 8)
+#define TLMM_SCSS_DIR_CONN_IRQ_5		(GIC_SPI_START + 9)
+#define TLMM_SCSS_DIR_CONN_IRQ_6		(GIC_SPI_START + 10)
+#define TLMM_SCSS_DIR_CONN_IRQ_7		(GIC_SPI_START + 11)
+#define TLMM_SCSS_DIR_CONN_IRQ_8		(GIC_SPI_START + 12)
+#define TLMM_SCSS_DIR_CONN_IRQ_9		(GIC_SPI_START + 13)
+#define PM8058_SEC_IRQ_N			(GIC_SPI_START + 14)
+#define PM8901_SEC_IRQ_N			(GIC_SPI_START + 15)
+#define TLMM_SCSS_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_SCSS_CPU0_GP_HIGH_IRQ		(GIC_SPI_START + 19)
+#define RPM_SCSS_CPU0_GP_MEDIUM_IRQ		(GIC_SPI_START + 20)
+#define RPM_SCSS_CPU0_GP_LOW_IRQ		(GIC_SPI_START + 21)
+#define RPM_SCSS_CPU0_WAKE_UP_IRQ		(GIC_SPI_START + 22)
+#define RPM_SCSS_CPU1_GP_HIGH_IRQ		(GIC_SPI_START + 23)
+#define RPM_SCSS_CPU1_GP_MEDIUM_IRQ		(GIC_SPI_START + 24)
+#define RPM_SCSS_CPU1_GP_LOW_IRQ		(GIC_SPI_START + 25)
+#define RPM_SCSS_CPU1_WAKE_UP_IRQ		(GIC_SPI_START + 26)
+#define SSBI2_2_SC_CPU0_SECURE_INT		(GIC_SPI_START + 27)
+#define SSBI2_2_SC_CPU0_NON_SECURE_INT		(GIC_SPI_START + 28)
+#define SSBI2_1_SC_CPU0_SECURE_INT		(GIC_SPI_START + 29)
+#define SSBI2_1_SC_CPU0_NON_SECURE_INT		(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 MARM_FIQ				(GIC_SPI_START + 33)
+#define MARM_IRQ				(GIC_SPI_START + 34)
+#define MARM_L2CC_IRQ				(GIC_SPI_START + 35)
+#define MARM_WDOG_EXPIRED			(GIC_SPI_START + 36)
+#define MARM_SCSS_GP_IRQ_0			(GIC_SPI_START + 37)
+#define MARM_SCSS_GP_IRQ_1			(GIC_SPI_START + 38)
+#define MARM_SCSS_GP_IRQ_2			(GIC_SPI_START + 39)
+#define MARM_SCSS_GP_IRQ_3			(GIC_SPI_START + 40)
+#define MARM_SCSS_GP_IRQ_4			(GIC_SPI_START + 41)
+#define MARM_SCSS_GP_IRQ_5			(GIC_SPI_START + 42)
+#define MARM_SCSS_GP_IRQ_6			(GIC_SPI_START + 43)
+#define MARM_SCSS_GP_IRQ_7			(GIC_SPI_START + 44)
+#define MARM_SCSS_GP_IRQ_8			(GIC_SPI_START + 45)
+#define MARM_SCSS_GP_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 DSI_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 UXMC_EBI2_WR_ER_DONE_IRQ		(GIC_SPI_START + 139)
+#define UXMC_EBI2_OP_DONE_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 INT_UART1DM_IRQ				(GIC_SPI_START + 146)
+#define GSBI1_QUP_IRQ				(GIC_SPI_START + 147)
+#define INT_UART2DM_IRQ				(GIC_SPI_START + 148)
+#define GSBI2_QUP_IRQ				(GIC_SPI_START + 149)
+#define INT_UART3DM_IRQ				(GIC_SPI_START + 150)
+#define GSBI3_QUP_IRQ				(GIC_SPI_START + 151)
+#define INT_UART4DM_IRQ				(GIC_SPI_START + 152)
+#define GSBI4_QUP_IRQ				(GIC_SPI_START + 153)
+#define INT_UART5DM_IRQ				(GIC_SPI_START + 154)
+#define GSBI5_QUP_IRQ				(GIC_SPI_START + 155)
+#define INT_UART6DM_IRQ				(GIC_SPI_START + 156)
+#define GSBI6_QUP_IRQ				(GIC_SPI_START + 157)
+#define INT_UART7DM_IRQ				(GIC_SPI_START + 158)
+#define GSBI7_QUP_IRQ				(GIC_SPI_START + 159)
+#define INT_UART8DM_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 INT_ADM1_MASTER				(GIC_SPI_START + 166)
+#define INT_ADM1_AARM				(GIC_SPI_START + 167)
+#define INT_ADM1_SD2				(GIC_SPI_START + 168)
+#define INT_ADM1_SD3				(GIC_SPI_START + 169)
+#define INT_ADM0_MASTER				(GIC_SPI_START + 170)
+#define INT_ADM0_AARM				(GIC_SPI_START + 171)
+#define INT_ADM0_SD2				(GIC_SPI_START + 172)
+#define INT_ADM0_SD3				(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_SMICH0_IRQ			(GIC_SPI_START + 185)
+#define HSDDRX_EBI1_IRQ				(GIC_SPI_START + 186)
+#define SDC5_BAM_IRQ				(GIC_SPI_START + 187)
+#define SDC5_IRQ_0				(GIC_SPI_START + 188)
+#define INT_UART9DM_IRQ				(GIC_SPI_START + 189)
+#define GSBI9_QUP_IRQ				(GIC_SPI_START + 190)
+#define INT_UART10DM_IRQ			(GIC_SPI_START + 191)
+#define GSBI10_QUP_IRQ				(GIC_SPI_START + 192)
+#define INT_UART11DM_IRQ			(GIC_SPI_START + 193)
+#define GSBI11_QUP_IRQ				(GIC_SPI_START + 194)
+#define INT_UART12DM_IRQ			(GIC_SPI_START + 195)
+#define GSBI12_QUP_IRQ				(GIC_SPI_START + 196)
+/*SPI 197 to 216 arent used in 8x60*/
+#define SMPSS_SPARE_1				(GIC_SPI_START + 217)
+#define SMPSS_SPARE_2				(GIC_SPI_START + 218)
+#define SMPSS_SPARE_3				(GIC_SPI_START + 219)
+#define SMPSS_SPARE_4				(GIC_SPI_START + 220)
+#define SMPSS_SPARE_5				(GIC_SPI_START + 221)
+#define SMPSS_SPARE_6				(GIC_SPI_START + 222)
+#define SMPSS_SPARE_7				(GIC_SPI_START + 223)
+
+#define NR_GPIO_IRQS 173
+#define NR_MSM_IRQS 256
+#define NR_BOARD_IRQS 0
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index 164d355..8679a45 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -24,6 +24,8 @@
 #elif defined(CONFIG_ARCH_QSD8X50)
 #include "irqs-8x50.h"
 #include "sirc.h"
+#elif defined(CONFIG_ARCH_MSM8X60)
+#include "irqs-8x60.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 50c7847..070e17d 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -23,6 +23,8 @@
 #define PHYS_OFFSET		UL(0x20000000)
 #elif defined(CONFIG_ARCH_MSM7X30)
 #define PHYS_OFFSET		UL(0x00200000)
+#elif defined(CONFIG_ARCH_MSM8X60)
+#define PHYS_OFFSET		UL(0x40200000)
 #else
 #define PHYS_OFFSET		UL(0x10000000)
 #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
new file mode 100644
index 0000000..45bab50
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2008-2010, 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_8X60_H
+#define __ASM_ARCH_MSM_IOMAP_8X60_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * MSM_VIC_BASE must be an value that can be loaded via a "mov"
+ * instruction, otherwise entry-macro.S will not compile.
+ *
+ * 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 MSM_QGIC_DIST_BASE	IOMEM(0xF0000000)
+#define MSM_QGIC_DIST_PHYS	0x02080000
+#define MSM_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 MSM_ACC_BASE		IOMEM(0xF0002000)
+#define MSM_ACC_PHYS		0x02001000
+#define MSM_ACC_SIZE		SZ_4K
+
+#define MSM_GCC_BASE		IOMEM(0xF0003000)
+#define MSM_GCC_PHYS		0x02082000
+#define MSM_GCC_SIZE		SZ_4K
+
+#define MSM_TLMM_BASE		IOMEM(0xF0004000)
+#define MSM_TLMM_PHYS		0x00800000
+#define MSM_TLMM_SIZE		SZ_16K
+
+#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_1M)
+
+#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
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index e6b1821..8e24dd8 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -47,8 +47,12 @@
 #include "msm_iomap-7x30.h"
 #elif defined(CONFIG_ARCH_QSD8X50)
 #include "msm_iomap-8x50.h"
+#elif defined(CONFIG_ARCH_MSM8X60)
+#include "msm_iomap-8x60.h"
 #else
 #include "msm_iomap-7x00.h"
 #endif
 
+
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/smp.h b/arch/arm/mach-msm/include/mach/smp.h
new file mode 100644
index 0000000..3ff7bf5
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/smp.h
@@ -0,0 +1,39 @@
+/* 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.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_SMP_H
+#define __ASM_ARCH_MSM_SMP_H
+
+#include <asm/hardware/gic.h>
+
+static inline void smp_cross_call(const struct cpumask *mask)
+{
+	gic_raise_softirq(mask, 1);
+}
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/vmalloc.h b/arch/arm/mach-msm/include/mach/vmalloc.h
index 05f81fd..31a32ad 100644
--- a/arch/arm/mach-msm/include/mach/vmalloc.h
+++ b/arch/arm/mach-msm/include/mach/vmalloc.h
@@ -16,7 +16,7 @@
 #ifndef __ASM_ARCH_MSM_VMALLOC_H
 #define __ASM_ARCH_MSM_VMALLOC_H
 
-#define VMALLOC_END	  (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END	  0xd0000000
 
 #endif
 
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 1c05060..d36b610 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -100,6 +100,21 @@
 }
 #endif /* CONFIG_ARCH_QSD8X50 */
 
+#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(ACC),
+	MSM_DEVICE(GCC),
+};
+
+void __init msm_map_msm8x60_io(void)
+{
+	iotable_init(msm8x60_io_desc, ARRAY_SIZE(msm8x60_io_desc));
+}
+#endif /* CONFIG_ARCH_MSM8X60 */
+
 #ifdef CONFIG_ARCH_MSM7X30
 static struct map_desc msm7x30_io_desc[] __initdata = {
 	MSM_DEVICE(VIC),
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
new file mode 100644
index 0000000..f71747d
--- /dev/null
+++ b/arch/arm/mach-msm/iommu.c
@@ -0,0 +1,597 @@
+/* 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.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/iommu.h>
+
+#include <asm/cacheflush.h>
+#include <asm/sizes.h>
+
+#include <mach/iommu_hw-8xxx.h>
+#include <mach/iommu.h>
+
+DEFINE_SPINLOCK(msm_iommu_lock);
+
+struct msm_priv {
+	unsigned long *pgtable;
+	struct list_head list_attached;
+};
+
+static void __flush_iotlb(struct iommu_domain *domain)
+{
+	struct msm_priv *priv = domain->priv;
+	struct msm_iommu_drvdata *iommu_drvdata;
+	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+
+#ifndef CONFIG_IOMMU_PGTABLES_L2
+	unsigned long *fl_table = priv->pgtable;
+	int i;
+
+	dmac_flush_range(fl_table, fl_table + SZ_16K);
+
+	for (i = 0; i < NUM_FL_PTE; i++)
+		if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
+			void *sl_table = __va(fl_table[i] & FL_BASE_MASK);
+			dmac_flush_range(sl_table, sl_table + SZ_4K);
+		}
+#endif
+
+	list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
+		if (!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent)
+			BUG();
+
+		iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+		SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
+	}
+}
+
+static void __reset_context(void __iomem *base, int ctx)
+{
+	SET_BPRCOSH(base, ctx, 0);
+	SET_BPRCISH(base, ctx, 0);
+	SET_BPRCNSH(base, ctx, 0);
+	SET_BPSHCFG(base, ctx, 0);
+	SET_BPMTCFG(base, ctx, 0);
+	SET_ACTLR(base, ctx, 0);
+	SET_SCTLR(base, ctx, 0);
+	SET_FSRRESTORE(base, ctx, 0);
+	SET_TTBR0(base, ctx, 0);
+	SET_TTBR1(base, ctx, 0);
+	SET_TTBCR(base, ctx, 0);
+	SET_BFBCR(base, ctx, 0);
+	SET_PAR(base, ctx, 0);
+	SET_FAR(base, ctx, 0);
+	SET_CTX_TLBIALL(base, ctx, 0);
+	SET_TLBFLPTER(base, ctx, 0);
+	SET_TLBSLPTER(base, ctx, 0);
+	SET_TLBLKCR(base, ctx, 0);
+	SET_PRRR(base, ctx, 0);
+	SET_NMRR(base, ctx, 0);
+	SET_CONTEXTIDR(base, ctx, 0);
+}
+
+static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
+{
+	__reset_context(base, ctx);
+
+	/* Set up HTW mode */
+	/* TLB miss configuration: perform HTW on miss */
+	SET_TLBMCFG(base, ctx, 0x3);
+
+	/* V2P configuration: HTW for access */
+	SET_V2PCFG(base, ctx, 0x3);
+
+	SET_TTBCR(base, ctx, 0);
+	SET_TTBR0_PA(base, ctx, (pgtable >> 14));
+
+	/* Invalidate the TLB for this context */
+	SET_CTX_TLBIALL(base, ctx, 0);
+
+	/* Set interrupt number to "secure" interrupt */
+	SET_IRPTNDX(base, ctx, 0);
+
+	/* Enable context fault interrupt */
+	SET_CFEIE(base, ctx, 1);
+
+	/* Stall access on a context fault and let the handler deal with it */
+	SET_CFCFG(base, ctx, 1);
+
+	/* Redirect all cacheable requests to L2 slave port. */
+	SET_RCISH(base, ctx, 1);
+	SET_RCOSH(base, ctx, 1);
+	SET_RCNSH(base, ctx, 1);
+
+	/* Turn on TEX Remap */
+	SET_TRE(base, ctx, 1);
+
+	/* Do not configure PRRR / NMRR on the IOMMU for now. We will assume
+	 * TEX class 0 for everything until attributes are properly worked out
+	 */
+	SET_PRRR(base, ctx, 0);
+	SET_NMRR(base, ctx, 0);
+
+	/* Turn on BFB prefetch */
+	SET_BFBDFE(base, ctx, 1);
+
+#ifdef CONFIG_IOMMU_PGTABLES_L2
+	/* Configure page tables as inner-cacheable and shareable to reduce
+	 * the TLB miss penalty.
+	 */
+	SET_TTBR0_SH(base, ctx, 1);
+	SET_TTBR1_SH(base, ctx, 1);
+
+	SET_TTBR0_NOS(base, ctx, 1);
+	SET_TTBR1_NOS(base, ctx, 1);
+
+	SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */
+	SET_TTBR0_IRGNL(base, ctx, 1);
+
+	SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */
+	SET_TTBR1_IRGNL(base, ctx, 1);
+
+	SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */
+	SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */
+#endif
+
+	/* Enable the MMU */
+	SET_M(base, ctx, 1);
+}
+
+static int msm_iommu_domain_init(struct iommu_domain *domain)
+{
+	struct msm_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+
+	if (!priv)
+		goto fail_nomem;
+
+	INIT_LIST_HEAD(&priv->list_attached);
+	priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
+							  get_order(SZ_16K));
+
+	if (!priv->pgtable)
+		goto fail_nomem;
+
+	memset(priv->pgtable, 0, SZ_16K);
+	domain->priv = priv;
+	return 0;
+
+fail_nomem:
+	kfree(priv);
+	return -ENOMEM;
+}
+
+static void msm_iommu_domain_destroy(struct iommu_domain *domain)
+{
+	struct msm_priv *priv;
+	unsigned long flags;
+	unsigned long *fl_table;
+	int i;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+	priv = domain->priv;
+	domain->priv = NULL;
+
+	if (priv) {
+		fl_table = priv->pgtable;
+
+		for (i = 0; i < NUM_FL_PTE; i++)
+			if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
+				free_page((unsigned long) __va(((fl_table[i]) &
+								FL_BASE_MASK)));
+
+		free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
+		priv->pgtable = NULL;
+	}
+
+	kfree(priv);
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
+
+static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
+{
+	struct msm_priv *priv;
+	struct msm_iommu_ctx_dev *ctx_dev;
+	struct msm_iommu_drvdata *iommu_drvdata;
+	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	struct msm_iommu_ctx_drvdata *tmp_drvdata;
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+
+	priv = domain->priv;
+
+	if (!priv || !dev) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	iommu_drvdata = dev_get_drvdata(dev->parent);
+	ctx_drvdata = dev_get_drvdata(dev);
+	ctx_dev = dev->platform_data;
+
+	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
+		if (tmp_drvdata == ctx_drvdata) {
+			ret = -EBUSY;
+			goto fail;
+		}
+
+	__program_context(iommu_drvdata->base, ctx_dev->num,
+			  __pa(priv->pgtable));
+
+	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
+	__flush_iotlb(domain);
+
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	return ret;
+}
+
+static void msm_iommu_detach_dev(struct iommu_domain *domain,
+				 struct device *dev)
+{
+	struct msm_priv *priv;
+	struct msm_iommu_ctx_dev *ctx_dev;
+	struct msm_iommu_drvdata *iommu_drvdata;
+	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	unsigned long flags;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+	priv = domain->priv;
+
+	if (!priv || !dev)
+		goto fail;
+
+	iommu_drvdata = dev_get_drvdata(dev->parent);
+	ctx_drvdata = dev_get_drvdata(dev);
+	ctx_dev = dev->platform_data;
+
+	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
+		goto fail;
+
+	__flush_iotlb(domain);
+	__reset_context(iommu_drvdata->base, ctx_dev->num);
+	list_del_init(&ctx_drvdata->attached_elm);
+
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
+
+static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
+			 phys_addr_t pa, int order, int prot)
+{
+	struct msm_priv *priv;
+	unsigned long flags;
+	unsigned long *fl_table;
+	unsigned long *fl_pte;
+	unsigned long fl_offset;
+	unsigned long *sl_table;
+	unsigned long *sl_pte;
+	unsigned long sl_offset;
+	size_t len = 0x1000UL << order;
+	int ret = 0;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+	priv = domain->priv;
+
+	if (!priv) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	fl_table = priv->pgtable;
+
+	if (len != SZ_16M && len != SZ_1M &&
+	    len != SZ_64K && len != SZ_4K) {
+		pr_debug("Bad size: %d\n", len);
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (!fl_table) {
+		pr_debug("Null page table\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
+	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
+
+	if (len == SZ_16M) {
+		int i = 0;
+		for (i = 0; i < 16; i++)
+			*(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
+				  FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
+				  FL_SHARED;
+	}
+
+	if (len == SZ_1M)
+		*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE |
+						FL_TYPE_SECT | FL_SHARED;
+
+	/* Need a 2nd level table */
+	if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
+		unsigned long *sl;
+		sl = (unsigned long *) __get_free_pages(GFP_KERNEL,
+							get_order(SZ_4K));
+
+		if (!sl) {
+			pr_debug("Could not allocate second level table\n");
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		memset(sl, 0, SZ_4K);
+		*fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE);
+	}
+
+	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
+	sl_offset = SL_OFFSET(va);
+	sl_pte = sl_table + sl_offset;
+
+
+	if (len == SZ_4K)
+		*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 |
+					  SL_SHARED | SL_TYPE_SMALL;
+
+	if (len == SZ_64K) {
+		int i;
+
+		for (i = 0; i < 16; i++)
+			*(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
+					    SL_AP1 | SL_SHARED | SL_TYPE_LARGE;
+	}
+
+	__flush_iotlb(domain);
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	return ret;
+}
+
+static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
+			    int order)
+{
+	struct msm_priv *priv;
+	unsigned long flags;
+	unsigned long *fl_table;
+	unsigned long *fl_pte;
+	unsigned long fl_offset;
+	unsigned long *sl_table;
+	unsigned long *sl_pte;
+	unsigned long sl_offset;
+	size_t len = 0x1000UL << order;
+	int i, ret = 0;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+
+	priv = domain->priv;
+
+	if (!priv) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	fl_table = priv->pgtable;
+
+	if (len != SZ_16M && len != SZ_1M &&
+	    len != SZ_64K && len != SZ_4K) {
+		pr_debug("Bad length: %d\n", len);
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (!fl_table) {
+		pr_debug("Null page table\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
+	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
+
+	if (*fl_pte == 0) {
+		pr_debug("First level PTE is 0\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	/* Unmap supersection */
+	if (len == SZ_16M)
+		for (i = 0; i < 16; i++)
+			*(fl_pte+i) = 0;
+
+	if (len == SZ_1M)
+		*fl_pte = 0;
+
+	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
+	sl_offset = SL_OFFSET(va);
+	sl_pte = sl_table + sl_offset;
+
+	if (len == SZ_64K) {
+		for (i = 0; i < 16; i++)
+			*(sl_pte+i) = 0;
+	}
+
+	if (len == SZ_4K)
+		*sl_pte = 0;
+
+	if (len == SZ_4K || len == SZ_64K) {
+		int used = 0;
+
+		for (i = 0; i < NUM_SL_PTE; i++)
+			if (sl_table[i])
+				used = 1;
+		if (!used) {
+			free_page((unsigned long)sl_table);
+			*fl_pte = 0;
+		}
+	}
+
+	__flush_iotlb(domain);
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	return ret;
+}
+
+static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
+					  unsigned long va)
+{
+	struct msm_priv *priv;
+	struct msm_iommu_drvdata *iommu_drvdata;
+	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	unsigned int par;
+	unsigned long flags;
+	void __iomem *base;
+	phys_addr_t ret = 0;
+	int ctx;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+
+	priv = domain->priv;
+	if (list_empty(&priv->list_attached))
+		goto fail;
+
+	ctx_drvdata = list_entry(priv->list_attached.next,
+				 struct msm_iommu_ctx_drvdata, attached_elm);
+	iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+
+	base = iommu_drvdata->base;
+	ctx = ctx_drvdata->num;
+
+	/* Invalidate context TLB */
+	SET_CTX_TLBIALL(base, ctx, 0);
+	SET_V2PPR_VA(base, ctx, va >> V2Pxx_VA_SHIFT);
+
+	if (GET_FAULT(base, ctx))
+		goto fail;
+
+	par = GET_PAR(base, ctx);
+
+	/* We are dealing with a supersection */
+	if (GET_NOFAULT_SS(base, ctx))
+		ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
+	else	/* Upper 20 bits from PAR, lower 12 from VA */
+		ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
+
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	return ret;
+}
+
+static int msm_iommu_domain_has_cap(struct iommu_domain *domain,
+				    unsigned long cap)
+{
+	return 0;
+}
+
+static void print_ctx_regs(void __iomem *base, int ctx)
+{
+	unsigned int fsr = GET_FSR(base, ctx);
+	pr_err("FAR    = %08x    PAR    = %08x\n",
+	       GET_FAR(base, ctx), GET_PAR(base, ctx));
+	pr_err("FSR    = %08x [%s%s%s%s%s%s%s%s%s%s]\n", fsr,
+			(fsr & 0x02) ? "TF " : "",
+			(fsr & 0x04) ? "AFF " : "",
+			(fsr & 0x08) ? "APF " : "",
+			(fsr & 0x10) ? "TLBMF " : "",
+			(fsr & 0x20) ? "HTWDEEF " : "",
+			(fsr & 0x40) ? "HTWSEEF " : "",
+			(fsr & 0x80) ? "MHF " : "",
+			(fsr & 0x10000) ? "SL " : "",
+			(fsr & 0x40000000) ? "SS " : "",
+			(fsr & 0x80000000) ? "MULTI " : "");
+
+	pr_err("FSYNR0 = %08x    FSYNR1 = %08x\n",
+	       GET_FSYNR0(base, ctx), GET_FSYNR1(base, ctx));
+	pr_err("TTBR0  = %08x    TTBR1  = %08x\n",
+	       GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
+	pr_err("SCTLR  = %08x    ACTLR  = %08x\n",
+	       GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
+	pr_err("PRRR   = %08x    NMRR   = %08x\n",
+	       GET_PRRR(base, ctx), GET_NMRR(base, ctx));
+}
+
+irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
+{
+	struct msm_iommu_drvdata *drvdata = dev_id;
+	void __iomem *base;
+	unsigned int fsr = 0;
+	int ncb = 0, i = 0;
+
+	spin_lock(&msm_iommu_lock);
+
+	if (!drvdata) {
+		pr_err("Invalid device ID in context interrupt handler\n");
+		goto fail;
+	}
+
+	base = drvdata->base;
+
+	pr_err("===== WOAH! =====\n");
+	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++) {
+		fsr = GET_FSR(base, i);
+		if (fsr) {
+			pr_err("Fault occurred in context %d.\n", i);
+			pr_err("Interesting registers:\n");
+			print_ctx_regs(base, i);
+			SET_FSR(base, i, 0x4000000F);
+		}
+	}
+fail:
+	spin_unlock(&msm_iommu_lock);
+	return 0;
+}
+
+static struct iommu_ops msm_iommu_ops = {
+	.domain_init = msm_iommu_domain_init,
+	.domain_destroy = msm_iommu_domain_destroy,
+	.attach_dev = msm_iommu_attach_dev,
+	.detach_dev = msm_iommu_detach_dev,
+	.map = msm_iommu_map,
+	.unmap = msm_iommu_unmap,
+	.iova_to_phys = msm_iommu_iova_to_phys,
+	.domain_has_cap = msm_iommu_domain_has_cap
+};
+
+static int msm_iommu_init(void)
+{
+	register_iommu(&msm_iommu_ops);
+	return 0;
+}
+
+subsys_initcall(msm_iommu_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
new file mode 100644
index 0000000..c33ae78
--- /dev/null
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -0,0 +1,374 @@
+/* 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.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/iommu.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <mach/iommu_hw-8xxx.h>
+#include <mach/iommu.h>
+
+struct iommu_ctx_iter_data {
+	/* input */
+	const char *name;
+
+	/* output */
+	struct device *dev;
+};
+
+static struct platform_device *msm_iommu_root_dev;
+
+static int each_iommu_ctx(struct device *dev, void *data)
+{
+	struct iommu_ctx_iter_data *res = data;
+	struct msm_iommu_ctx_dev *c = dev->platform_data;
+
+	if (!res || !c || !c->name || !res->name)
+		return -EINVAL;
+
+	if (!strcmp(res->name, c->name)) {
+		res->dev = dev;
+		return 1;
+	}
+	return 0;
+}
+
+static int each_iommu(struct device *dev, void *data)
+{
+	return device_for_each_child(dev, data, each_iommu_ctx);
+}
+
+struct device *msm_iommu_get_ctx(const char *ctx_name)
+{
+	struct iommu_ctx_iter_data r;
+	int found;
+
+	if (!msm_iommu_root_dev) {
+		pr_err("No root IOMMU device.\n");
+		goto fail;
+	}
+
+	r.name = ctx_name;
+	found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
+
+	if (!found) {
+		pr_err("Could not find context <%s>\n", ctx_name);
+		goto fail;
+	}
+
+	return r.dev;
+fail:
+	return NULL;
+}
+EXPORT_SYMBOL(msm_iommu_get_ctx);
+
+static void msm_iommu_reset(void __iomem *base)
+{
+	int ctx, ncb;
+
+	SET_RPUE(base, 0);
+	SET_RPUEIE(base, 0);
+	SET_ESRRESTORE(base, 0);
+	SET_TBE(base, 0);
+	SET_CR(base, 0);
+	SET_SPDMBE(base, 0);
+	SET_TESTBUSCR(base, 0);
+	SET_TLBRSW(base, 0);
+	SET_GLOBAL_TLBIALL(base, 0);
+	SET_RPU_ACR(base, 0);
+	SET_TLBLKCRWE(base, 1);
+	ncb = GET_NCB(base)+1;
+
+	for (ctx = 0; ctx < ncb; ctx++) {
+		SET_BPRCOSH(base, ctx, 0);
+		SET_BPRCISH(base, ctx, 0);
+		SET_BPRCNSH(base, ctx, 0);
+		SET_BPSHCFG(base, ctx, 0);
+		SET_BPMTCFG(base, ctx, 0);
+		SET_ACTLR(base, ctx, 0);
+		SET_SCTLR(base, ctx, 0);
+		SET_FSRRESTORE(base, ctx, 0);
+		SET_TTBR0(base, ctx, 0);
+		SET_TTBR1(base, ctx, 0);
+		SET_TTBCR(base, ctx, 0);
+		SET_BFBCR(base, ctx, 0);
+		SET_PAR(base, ctx, 0);
+		SET_FAR(base, ctx, 0);
+		SET_CTX_TLBIALL(base, ctx, 0);
+		SET_TLBFLPTER(base, ctx, 0);
+		SET_TLBSLPTER(base, ctx, 0);
+		SET_TLBLKCR(base, ctx, 0);
+		SET_PRRR(base, ctx, 0);
+		SET_NMRR(base, ctx, 0);
+		SET_CONTEXTIDR(base, ctx, 0);
+	}
+}
+
+static int msm_iommu_probe(struct platform_device *pdev)
+{
+	struct resource *r;
+	struct clk *iommu_clk;
+	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;
+
+	if (pdev->id != -1) {
+		drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+
+		if (!drvdata) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		if (!iommu_dev) {
+			ret = -ENODEV;
+			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;
+			}
+			clk_put(iommu_clk);
+		}
+
+		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						 "physbase");
+		if (!r) {
+			ret = -ENODEV;
+			goto fail;
+		}
+
+		len = r->end - r->start + 1;
+
+		r = request_mem_region(r->start, len, r->name);
+		if (!r) {
+			pr_err("Could not request memory region: "
+			"start=%p, len=%d\n", (void *) r->start, len);
+			ret = -EBUSY;
+			goto fail;
+		}
+
+		regs_base = ioremap(r->start, len);
+
+		if (!regs_base) {
+			pr_err("Could not ioremap: start=%p, len=%d\n",
+				 (void *) r->start, len);
+			ret = -EBUSY;
+			goto fail;
+		}
+
+		irq = platform_get_irq_byname(pdev, "secure_irq");
+		if (irq < 0) {
+			ret = -ENODEV;
+			goto fail;
+		}
+
+		mb();
+
+		if (GET_IDR(regs_base) == 0) {
+			pr_err("Invalid IDR value detected\n");
+			ret = -ENODEV;
+			goto fail;
+		}
+
+		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;
+		}
+
+		msm_iommu_reset(regs_base);
+		drvdata->base = regs_base;
+		drvdata->irq = irq;
+
+		nm2v = GET_NM2VCBMT((unsigned long) regs_base);
+		ncb = GET_NCB((unsigned long) regs_base);
+
+		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;
+
+	return 0;
+
+fail:
+	kfree(drvdata);
+	return ret;
+}
+
+static int msm_iommu_remove(struct platform_device *pdev)
+{
+	struct msm_iommu_drvdata *drv = NULL;
+
+	drv = platform_get_drvdata(pdev);
+	if (drv) {
+		memset(drv, 0, sizeof(struct msm_iommu_drvdata));
+		kfree(drv);
+		platform_set_drvdata(pdev, NULL);
+	}
+	return 0;
+}
+
+static int msm_iommu_ctx_probe(struct platform_device *pdev)
+{
+	struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
+	struct msm_iommu_drvdata *drvdata;
+	struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
+	int i, ret = 0;
+	if (!c || !pdev->dev.parent) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	drvdata = dev_get_drvdata(pdev->dev.parent);
+
+	if (!drvdata) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
+	if (!ctx_drvdata) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+	ctx_drvdata->num = c->num;
+	ctx_drvdata->pdev = pdev;
+
+	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
+	platform_set_drvdata(pdev, ctx_drvdata);
+
+	/* Program the M2V tables for this context */
+	for (i = 0; i < MAX_NUM_MIDS; i++) {
+		int mid = c->mids[i];
+		if (mid == -1)
+			break;
+
+		SET_M2VCBR_N(drvdata->base, mid, 0);
+		SET_CBACR_N(drvdata->base, c->num, 0);
+
+		/* Set VMID = MID */
+		SET_VMID(drvdata->base, mid, mid);
+
+		/* 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 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);
+
+	return 0;
+fail:
+	kfree(ctx_drvdata);
+	return ret;
+}
+
+static int msm_iommu_ctx_remove(struct platform_device *pdev)
+{
+	struct msm_iommu_ctx_drvdata *drv = NULL;
+	drv = platform_get_drvdata(pdev);
+	if (drv) {
+		memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
+		kfree(drv);
+		platform_set_drvdata(pdev, NULL);
+	}
+	return 0;
+}
+
+static struct platform_driver msm_iommu_driver = {
+	.driver = {
+		.name	= "msm_iommu",
+	},
+	.probe		= msm_iommu_probe,
+	.remove		= msm_iommu_remove,
+};
+
+static struct platform_driver msm_iommu_ctx_driver = {
+	.driver = {
+		.name	= "msm_iommu_ctx",
+	},
+	.probe		= msm_iommu_ctx_probe,
+	.remove		= msm_iommu_ctx_remove,
+};
+
+static int msm_iommu_driver_init(void)
+{
+	int ret;
+	ret = platform_driver_register(&msm_iommu_driver);
+	if (ret != 0) {
+		pr_err("Failed to register IOMMU driver\n");
+		goto error;
+	}
+
+	ret = platform_driver_register(&msm_iommu_ctx_driver);
+	if (ret != 0) {
+		pr_err("Failed to register IOMMU context driver\n");
+		goto error;
+	}
+
+error:
+	return ret;
+}
+
+static void msm_iommu_driver_exit(void)
+{
+	platform_driver_unregister(&msm_iommu_ctx_driver);
+	platform_driver_unregister(&msm_iommu_driver);
+}
+
+subsys_initcall(msm_iommu_driver_init);
+module_exit(msm_iommu_driver_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/last_radio_log.c b/arch/arm/mach-msm/last_radio_log.c
index b64ba5a..1e243f4 100644
--- a/arch/arm/mach-msm/last_radio_log.c
+++ b/arch/arm/mach-msm/last_radio_log.c
@@ -48,7 +48,8 @@
 }
 
 static struct file_operations last_radio_log_fops = {
-	.read = last_radio_log_read
+	.read = last_radio_log_read,
+	.llseek = default_llseek,
 };
 
 void msm_init_last_radio_log(struct module *owner)
diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
index 3b2dd71..f91c3b7 100644
--- a/arch/arm/mach-msm/smd_debug.c
+++ b/arch/arm/mach-msm/smd_debug.c
@@ -212,6 +212,7 @@
 static const struct file_operations debug_ops = {
 	.read = debug_read,
 	.open = debug_open,
+	.llseek = default_llseek,
 };
 
 static void debug_create(const char *name, mode_t mode,
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index dec5ca6..7689848 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -28,7 +28,6 @@
 #ifndef MSM_DGT_BASE
 #define MSM_DGT_BASE (MSM_GPT_BASE + 0x10)
 #endif
-#define MSM_DGT_SHIFT (5)
 
 #define TIMER_MATCH_VAL         0x0000
 #define TIMER_COUNT_VAL         0x0004
@@ -36,12 +35,28 @@
 #define TIMER_ENABLE_CLR_ON_MATCH_EN    2
 #define TIMER_ENABLE_EN                 1
 #define TIMER_CLEAR             0x000C
-
+#define DGT_CLK_CTL             0x0034
+enum {
+	DGT_CLK_CTL_DIV_1 = 0,
+	DGT_CLK_CTL_DIV_2 = 1,
+	DGT_CLK_CTL_DIV_3 = 2,
+	DGT_CLK_CTL_DIV_4 = 3,
+};
 #define CSR_PROTECTION          0x0020
 #define CSR_PROTECTION_EN               1
 
 #define GPT_HZ 32768
+
+#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)
+#define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */
+#define MSM_DGT_SHIFT (0)
+#else
 #define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */
+#define MSM_DGT_SHIFT (5)
+#endif
 
 struct msm_clock {
 	struct clock_event_device   clockevent;
@@ -170,6 +185,10 @@
 	int i;
 	int res;
 
+#ifdef CONFIG_ARCH_MSM8X60
+	writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
+#endif
+
 	for (i = 0; i < ARRAY_SIZE(msm_clocks); i++) {
 		struct msm_clock *clock = &msm_clocks[i];
 		struct clock_event_device *ce = &clock->clockevent;
diff --git a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
index 61e5e58..29e390e 100644
--- a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
+++ b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
@@ -145,8 +145,6 @@
 
 MACHINE_START(TERASTATION_WXL, "Buffalo Nas WXL")
 	/* Maintainer: Sebastien Requiem <sebastien@requiem.fr> */
-	.phys_io	= MV78XX0_REGS_PHYS_BASE,
-	.io_pg_offst	= ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= wxl_init,
 	.map_io		= mv78xx0_map_io,
diff --git a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
index efdabe0..207c95e 100644
--- a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
+++ b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
@@ -93,8 +93,6 @@
 
 MACHINE_START(DB78X00_BP, "Marvell DB-78x00-BP Development Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.phys_io	= MV78XX0_REGS_PHYS_BASE,
-	.io_pg_offst	= ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= db78x00_init,
 	.map_io		= mv78xx0_map_io,
diff --git a/arch/arm/mach-mv78xx0/include/mach/debug-macro.S b/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
index cd81689..0489142 100644
--- a/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
+++ b/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
@@ -8,12 +8,11 @@
 
 #include <mach/mv78xx0.h>
 
-	.macro	addruart, rx, tmp
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1					@ MMU enabled?
-	ldreq	\rx, =MV78XX0_REGS_PHYS_BASE
-	ldrne	\rx, =MV78XX0_REGS_VIRT_BASE
-	orr	\rx, \rx, #0x00012000
+	.macro	addruart, rp, rv
+	ldr	\rp, =MV78XX0_REGS_PHYS_BASE
+	ldr	\rv, =MV78XX0_REGS_VIRT_BASE
+	orr	\rp, \rp, #0x00012000
+	orr	\rv, \rv, #0x00012000
 	.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
index e136b7a..3511ad4 100644
--- a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
+++ b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
@@ -78,8 +78,6 @@
 
 MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.phys_io	= MV78XX0_REGS_PHYS_BASE,
-	.io_pg_offst	= ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= rd78x00_masa_init,
 	.map_io		= mv78xx0_map_io,
diff --git a/arch/arm/mach-mx25/Kconfig b/arch/arm/mach-mx25/Kconfig
index c71a7bc..aa57e35 100644
--- a/arch/arm/mach-mx25/Kconfig
+++ b/arch/arm/mach-mx25/Kconfig
@@ -12,6 +12,8 @@
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_FLEXCAN
+	select IMX_HAVE_PLATFORM_ESDHC
 	select MXC_ULPI if USB_ULPI
 
 choice
@@ -20,8 +22,8 @@
 	default MACH_EUKREA_MBIMXSD25_BASEBOARD
 
 config MACH_EUKREA_MBIMXSD25_BASEBOARD
-	prompt "Eukrea MBIMXSD development board"
-	bool
+	bool "Eukrea MBIMXSD development board"
+	select IMX_HAVE_PLATFORM_IMX_SSI
 	help
 	  This adds board specific devices that can be found on Eukrea's
 	  MBIMXSD evaluation board.
diff --git a/arch/arm/mach-mx25/clock.c b/arch/arm/mach-mx25/clock.c
index 40c7cc4..9e4a557 100644
--- a/arch/arm/mach-mx25/clock.c
+++ b/arch/arm/mach-mx25/clock.c
@@ -72,7 +72,7 @@
 	unsigned long rate = get_rate_mpll();
 
 	if (cctl & (1 << 14))
-		rate = (rate * 3) >> 1;
+		rate = (rate * 3) >> 2;
 
 	return rate / ((cctl >> 30) + 1);
 }
@@ -99,7 +99,7 @@
 	if (readl(CRM_BASE + 0x64) & (1 << per))
 		fref = get_rate_upll();
 	else
-		fref = get_rate_ipg(NULL);
+		fref = get_rate_ahb(NULL);
 
 	return fref / (val + 1);
 }
@@ -139,6 +139,16 @@
 	return get_rate_per(7);
 }
 
+static unsigned long get_rate_esdhc1(struct clk *clk)
+{
+	return get_rate_per(3);
+}
+
+static unsigned long get_rate_esdhc2(struct clk *clk)
+{
+	return get_rate_per(4);
+}
+
 static unsigned long get_rate_csi(struct clk *clk)
 {
 	return get_rate_per(0);
@@ -213,6 +223,12 @@
 DEFINE_CLOCK(cspi1_clk,  0, CCM_CGCR1,  5, get_rate_ipg, NULL, NULL);
 DEFINE_CLOCK(cspi2_clk,  0, CCM_CGCR1,  6, get_rate_ipg, NULL, NULL);
 DEFINE_CLOCK(cspi3_clk,  0, CCM_CGCR1,  7, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(esdhc1_ahb_clk, 0, CCM_CGCR0, 21, get_rate_esdhc1,	 NULL, NULL);
+DEFINE_CLOCK(esdhc1_per_clk, 0, CCM_CGCR0,  3, get_rate_esdhc1,	 NULL,
+		&esdhc1_ahb_clk);
+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(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);
@@ -238,10 +254,14 @@
 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(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,
+		&esdhc2_per_clk);
 DEFINE_CLOCK(audmux_clk, 0, CCM_CGCR1, 0, NULL, NULL, NULL);
 DEFINE_CLOCK(csi_clk,    0, CCM_CGCR1,  4, get_rate_csi, NULL,  &csi_per_clk);
 DEFINE_CLOCK(can1_clk,	 0, CCM_CGCR1,  2, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(can2_clk,	 0, CCM_CGCR1,  3, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(can2_clk,	 1, CCM_CGCR1,  3, get_rate_ipg, NULL, NULL);
 
 #define _REGISTER_CLOCK(d, n, c)	\
 	{				\
@@ -261,9 +281,9 @@
 	_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
 	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
-	_REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
-	_REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
-	_REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
+	_REGISTER_CLOCK("imx25-cspi.0", NULL, cspi1_clk)
+	_REGISTER_CLOCK("imx25-cspi.1", NULL, cspi2_clk)
+	_REGISTER_CLOCK("imx25-cspi.2", NULL, cspi3_clk)
 	_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk)
 	_REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk)
 	_REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk)
@@ -279,6 +299,8 @@
 	_REGISTER_CLOCK("imx-wdt.0", NULL, wdt_clk)
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
 	_REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
 	_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
 	_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
diff --git a/arch/arm/mach-mx25/devices-imx25.h b/arch/arm/mach-mx25/devices-imx25.h
index d86a7c3..93afa10 100644
--- a/arch/arm/mach-mx25/devices-imx25.h
+++ b/arch/arm/mach-mx25/devices-imx25.h
@@ -9,35 +9,46 @@
 #include <mach/mx25.h>
 #include <mach/devices-common.h>
 
+extern const struct imx_fec_data imx25_fec_data __initconst;
+#define imx25_add_fec(pdata)	\
+	imx_add_fec(&imx25_fec_data, pdata)
+
 #define imx25_add_flexcan0(pdata)	\
 	imx_add_flexcan(0, MX25_CAN1_BASE_ADDR, SZ_16K, MX25_INT_CAN1, pdata)
 #define imx25_add_flexcan1(pdata)	\
 	imx_add_flexcan(1, MX25_CAN2_BASE_ADDR, SZ_16K, MX25_INT_CAN2, pdata)
 
-#define imx25_add_imx_i2c0(pdata)	\
-	imx_add_imx_i2c(0, MX25_I2C1_BASE_ADDR, SZ_16K, MX25_INT_I2C1, pdata)
-#define imx25_add_imx_i2c1(pdata)	\
-	imx_add_imx_i2c(1, MX25_I2C2_BASE_ADDR, SZ_16K, MX25_INT_I2C2, pdata)
-#define imx25_add_imx_i2c2(pdata)	\
-	imx_add_imx_i2c(2, MX25_I2C3_BASE_ADDR, SZ_16K, MX25_INT_I2C3, pdata)
+extern const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst;
+#define imx25_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx25_imx_i2c_data[id], pdata)
+#define imx25_add_imx_i2c0(pdata)	imx25_add_imx_i2c(0, pdata)
+#define imx25_add_imx_i2c1(pdata)	imx25_add_imx_i2c(1, pdata)
+#define imx25_add_imx_i2c2(pdata)	imx25_add_imx_i2c(2, pdata)
 
-#define imx25_add_imx_uart0(pdata)	\
-	imx_add_imx_uart_1irq(0, MX25_UART1_BASE_ADDR, SZ_16K, MX25_INT_UART1, pdata)
-#define imx25_add_imx_uart1(pdata)	\
-	imx_add_imx_uart_1irq(1, MX25_UART2_BASE_ADDR, SZ_16K, MX25_INT_UART2, pdata)
-#define imx25_add_imx_uart2(pdata)	\
-	imx_add_imx_uart_1irq(2, MX25_UART3_BASE_ADDR, SZ_16K, MX25_INT_UART3, pdata)
-#define imx25_add_imx_uart3(pdata)	\
-	imx_add_imx_uart_1irq(3, MX25_UART4_BASE_ADDR, SZ_16K, MX25_INT_UART4, pdata)
-#define imx25_add_imx_uart4(pdata)	\
-	imx_add_imx_uart_1irq(4, MX25_UART5_BASE_ADDR, SZ_16K, MX25_INT_UART5, pdata)
+extern const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst;
+#define imx25_add_imx_ssi(id, pdata)	\
+	imx_add_imx_ssi(&imx25_imx_ssi_data[id], pdata)
 
+extern const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst;
+#define imx25_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx25_imx_uart_data[id], pdata)
+#define imx25_add_imx_uart0(pdata)	imx25_add_imx_uart(0, pdata)
+#define imx25_add_imx_uart1(pdata)	imx25_add_imx_uart(1, pdata)
+#define imx25_add_imx_uart2(pdata)	imx25_add_imx_uart(2, pdata)
+#define imx25_add_imx_uart3(pdata)	imx25_add_imx_uart(3, pdata)
+#define imx25_add_imx_uart4(pdata)	imx25_add_imx_uart(4, pdata)
+
+extern const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst;
 #define imx25_add_mxc_nand(pdata)	\
-	imx_add_mxc_nand_v21(MX25_NFC_BASE_ADDR, MX25_INT_NANDFC, pdata)
+	imx_add_mxc_nand(&imx25_mxc_nand_data, pdata)
 
-#define imx25_add_spi_imx0(pdata)	\
-	imx_add_spi_imx(0, MX25_CSPI1_BASE_ADDR, SZ_16K, MX25_INT_CSPI1, pdata)
-#define imx25_add_spi_imx1(pdata)	\
-	imx_add_spi_imx(1, MX25_CSPI2_BASE_ADDR, SZ_16K, MX25_INT_CSPI2, pdata)
-#define imx25_add_spi_imx2(pdata)	\
-	imx_add_spi_imx(2, MX25_CSPI3_BASE_ADDR, SZ_16K, MX25_INT_CSPI3, pdata)
+extern const struct imx_spi_imx_data imx25_spi_imx_data[] __initconst;
+#define imx25_add_spi_imx(id, pdata)	\
+	imx_add_spi_imx(&imx25_spi_imx_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 const struct imx_esdhc_imx_data imx25_esdhc_data[] __initconst;
+#define imx25_add_esdhc(id, pdata)	\
+	imx_add_esdhc(&imx25_esdhc_data[id], pdata)
diff --git a/arch/arm/mach-mx25/devices.c b/arch/arm/mach-mx25/devices.c
index 3468eb1..1d0eb3e 100644
--- a/arch/arm/mach-mx25/devices.c
+++ b/arch/arm/mach-mx25/devices.c
@@ -208,26 +208,6 @@
 	return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
 }
 
-static struct resource mx25_fec_resources[] = {
-	{
-		.start	= MX25_FEC_BASE_ADDR,
-		.end	= MX25_FEC_BASE_ADDR + 0xfff,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= MX25_INT_FEC,
-		.end	= MX25_INT_FEC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mx25_fec_device = {
-	.name	= "fec",
-	.id	= 0,
-	.num_resources	= ARRAY_SIZE(mx25_fec_resources),
-	.resource	= mx25_fec_resources,
-};
-
 static struct resource mx25_rtc_resources[] = {
 	{
 		.start	= MX25_DRYICE_BASE_ADDR,
@@ -305,44 +285,6 @@
 	.resource	= mx25_kpp_resources,
 };
 
-static struct resource imx_ssi_resources0[] = {
-	{
-		.start	= MX25_SSI1_BASE_ADDR,
-		.end	= MX25_SSI1_BASE_ADDR + 0x3fff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= MX25_INT_SSI1,
-		.end	= MX25_INT_SSI1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource imx_ssi_resources1[] = {
-	{
-		.start	= MX25_SSI2_BASE_ADDR,
-		.end	= MX25_SSI2_BASE_ADDR + 0x3fff,
-		.flags	= IORESOURCE_MEM
-	}, {
-		.start	= MX25_INT_SSI2,
-		.end	= MX25_INT_SSI2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device imx_ssi_device0 = {
-	.name = "imx-ssi",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(imx_ssi_resources0),
-	.resource = imx_ssi_resources0,
-};
-
-struct platform_device imx_ssi_device1 = {
-	.name = "imx-ssi",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(imx_ssi_resources1),
-	.resource = imx_ssi_resources1,
-};
-
 static struct resource mx25_csi_resources[] = {
 	{
 		.start	= MX25_CSI_BASE_ADDR,
diff --git a/arch/arm/mach-mx25/devices.h b/arch/arm/mach-mx25/devices.h
index 4aceb68..7b70a43 100644
--- a/arch/arm/mach-mx25/devices.h
+++ b/arch/arm/mach-mx25/devices.h
@@ -6,11 +6,8 @@
 extern struct platform_device mxc_pwm_device2;
 extern struct platform_device mxc_pwm_device3;
 extern struct platform_device mxc_keypad_device;
-extern struct platform_device mx25_fec_device;
 extern struct platform_device mx25_rtc_device;
 extern struct platform_device mx25_fb_device;
 extern struct platform_device mxc_wdt;
 extern struct platform_device mx25_kpp_device;
-extern struct platform_device imx_ssi_device0;
-extern struct platform_device imx_ssi_device1;
 extern struct platform_device mx25_csi_device;
diff --git a/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c
index 4aaadc7..e765ac5 100644
--- a/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c
@@ -34,7 +34,6 @@
 #include <mach/mx25.h>
 #include <mach/imx-uart.h>
 #include <mach/imxfb.h>
-#include <mach/ssi.h>
 #include <mach/audmux.h>
 
 #include "devices-imx25.h"
@@ -90,6 +89,9 @@
 	MX25_PAD_KPP_COL2__AUD5_TXC,
 	MX25_PAD_KPP_COL1__AUD5_RXD,
 	MX25_PAD_KPP_COL0__AUD5_TXD,
+	/* CAN */
+	MX25_PAD_GPIO_D__CAN2_RX,
+	MX25_PAD_GPIO_C__CAN2_TX,
 };
 
 #define GPIO_LED1	83
@@ -114,6 +116,38 @@
 		},
 		.bpp	= 16,
 		.pcr	= 0xCAD08B80,
+	}, {
+		.mode = {
+			.name		= "DVI-VGA",
+			.refresh	= 60,
+			.xres		= 640,
+			.yres		= 480,
+			.pixclock	= 32000,
+			.hsync_len	= 7,
+			.left_margin	= 100,
+			.right_margin	= 100,
+			.vsync_len	= 7,
+			.upper_margin	= 7,
+			.lower_margin	= 100,
+		},
+		.pcr		= 0xFA208B80,
+		.bpp		= 16,
+	}, {
+		.mode = {
+			.name		= "DVI-SVGA",
+			.refresh	= 60,
+			.xres		= 800,
+			.yres		= 600,
+			.pixclock	= 25000,
+			.hsync_len	= 7,
+			.left_margin	= 75,
+			.right_margin	= 75,
+			.vsync_len	= 7,
+			.upper_margin	= 7,
+			.lower_margin	= 75,
+		},
+		.pcr		= 0xFA208B80,
+		.bpp		= 16,
 	},
 };
 
@@ -205,7 +239,8 @@
 	},
 };
 
-struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata = {
+static const
+struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
 	.flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
 };
 
@@ -239,7 +274,10 @@
 
 	imx25_add_imx_uart1(&uart_pdata);
 	mxc_register_device(&mx25_fb_device, &eukrea_mximxsd_fb_pdata);
-	mxc_register_device(&imx_ssi_device0, &eukrea_mbimxsd_ssi_pdata);
+	imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
+
+	imx25_add_flexcan1(NULL);
+	imx25_add_esdhc(0, NULL);
 
 	gpio_request(GPIO_LED1, "LED1");
 	gpio_direction_output(GPIO_LED1, 1);
diff --git a/arch/arm/mach-mx25/mach-cpuimx25.c b/arch/arm/mach-mx25/mach-cpuimx25.c
index e064bb3..f6f9ad6 100644
--- a/arch/arm/mach-mx25/mach-cpuimx25.c
+++ b/arch/arm/mach-mx25/mach-cpuimx25.c
@@ -23,7 +23,6 @@
 #include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
-#include <linux/fec.h>
 #include <linux/platform_device.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
@@ -41,7 +40,6 @@
 #include <mach/mxc_nand.h>
 #include <mach/imxfb.h>
 #include <mach/mxc_ehci.h>
-#include <mach/ulpi.h>
 #include <mach/iomux-mx25.h>
 
 #include "devices-imx25.h"
@@ -67,7 +65,7 @@
 	MX25_PAD_I2C1_DAT__I2C1_DAT,
 };
 
-static struct fec_platform_data mx25_fec_pdata = {
+static const struct fec_platform_data mx25_fec_pdata __initconst = {
 	.phy	= PHY_INTERFACE_MODE_RMII,
 };
 
@@ -129,24 +127,19 @@
 	imx25_add_imx_uart0(&uart_pdata);
 	imx25_add_mxc_nand(&eukrea_cpuimx25_nand_board_info);
 	mxc_register_device(&mx25_rtc_device, NULL);
-	mxc_register_device(&mx25_fec_device, &mx25_fec_pdata);
+	imx25_add_fec(&mx25_fec_pdata);
 
 	i2c_register_board_info(0, eukrea_cpuimx25_i2c_devices,
 				ARRAY_SIZE(eukrea_cpuimx25_i2c_devices));
 	imx25_add_imx_i2c0(&eukrea_cpuimx25_i2c0_data);
 
-#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);
-
+	if (otg_mode_host)
 		mxc_register_device(&mxc_otg, &otg_pdata);
-	}
-	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
-#endif
-	if (!otg_mode_host)
+	else
 		mxc_register_device(&otg_udc_device, &otg_device_pdata);
 
+	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+
 #ifdef CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD
 	eukrea_mbimxsd25_baseboard_init();
 #endif
@@ -163,8 +156,6 @@
 
 MACHINE_START(EUKREA_CPUIMX25, "Eukrea CPUIMX25")
 	/* Maintainer: Eukrea Electromatique */
-	.phys_io	= MX25_AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((MX25_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX25_PHYS_OFFSET + 0x100,
 	.map_io         = mx25_map_io,
 	.init_irq       = mx25_init_irq,
diff --git a/arch/arm/mach-mx25/mach-mx25_3ds.c b/arch/arm/mach-mx25/mach-mx25_3ds.c
index 62bc21f..8080510 100644
--- a/arch/arm/mach-mx25/mach-mx25_3ds.c
+++ b/arch/arm/mach-mx25/mach-mx25_3ds.c
@@ -28,7 +28,6 @@
 #include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
-#include <linux/fec.h>
 #include <linux/platform_device.h>
 #include <linux/input/matrix_keypad.h>
 
@@ -99,7 +98,7 @@
 	MX25_PAD_KPP_COL3__KPP_COL3,
 };
 
-static struct fec_platform_data mx25_fec_pdata = {
+static const struct fec_platform_data mx25_fec_pdata __initconst = {
         .phy    = PHY_INTERFACE_MODE_RMII,
 };
 
@@ -192,7 +191,7 @@
 	mxc_register_device(&mxc_wdt, NULL);
 
 	mx25pdk_fec_reset();
-	mxc_register_device(&mx25_fec_device, &mx25_fec_pdata);
+	imx25_add_fec(&mx25_fec_pdata);
 	mxc_register_device(&mx25_kpp_device, &mx25pdk_keymap_data);
 }
 
@@ -207,8 +206,6 @@
 
 MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.phys_io	= MX25_AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((MX25_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX25_PHYS_OFFSET + 0x100,
 	.map_io         = mx25_map_io,
 	.init_irq       = mx25_init_irq,
diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index 85beece..096fd33 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -9,6 +9,7 @@
 	bool
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
+	select HAVE_EPIT
 
 comment "MX3 platforms:"
 
@@ -16,6 +17,7 @@
 	bool "Support MX31ADS platforms"
 	select ARCH_MX31
 	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IMX_UART
 	default y
 	help
@@ -117,9 +119,11 @@
 	bool "Support Phytec pcm043 (i.MX35) platforms"
 	select ARCH_MX35
 	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_FLEXCAN
+	select IMX_HAVE_PLATFORM_ESDHC
 	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for Phytec pcm043 platform. This includes
@@ -140,6 +144,7 @@
 	bool "Support MX35PDK platform"
 	select ARCH_MX35
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_NAND
 	default n
 	help
 	  Include support for MX35PDK platform. This includes specific
@@ -159,6 +164,8 @@
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_FLEXCAN
+	select IMX_HAVE_PLATFORM_ESDHC
 	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for Eukrea CPUIMX35 platform. This includes
@@ -170,8 +177,8 @@
 	default MACH_EUKREA_MBIMXSD35_BASEBOARD
 
 config MACH_EUKREA_MBIMXSD35_BASEBOARD
-	prompt "Eukrea MBIMXSD development board"
-	bool
+	bool "Eukrea MBIMXSD development board"
+	select IMX_HAVE_PLATFORM_IMX_SSI
 	help
 	  This adds board specific devices that can be found on Eukrea's
 	  MBIMXSD evaluation board.
diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile
index 2bd7bec..8a182d0a 100644
--- a/arch/arm/mach-mx3/Makefile
+++ b/arch/arm/mach-mx3/Makefile
@@ -7,7 +7,6 @@
 obj-y				:= mm.o devices.o cpu.o
 CFLAGS_mm.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
 CFLAGS_devices.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
-CFLAGS_cpu.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
 obj-$(CONFIG_ARCH_MX31)		+= clock-imx31.o iomux-imx31.o
 obj-$(CONFIG_ARCH_MX35)		+= clock-imx35.o
 obj-$(CONFIG_MACH_MX31ADS)	+= mach-mx31ads.o
diff --git a/arch/arm/mach-mx3/clock-imx31.c b/arch/arm/mach-mx3/clock-imx31.c
index 9a9eb6d..109e98f 100644
--- a/arch/arm/mach-mx3/clock-imx31.c
+++ b/arch/arm/mach-mx3/clock-imx31.c
@@ -477,7 +477,7 @@
 DEFINE_CLOCK(epit2_clk,   1, MXC_CCM_CGR0,  8, NULL, NULL, &perclk_clk);
 DEFINE_CLOCK(iim_clk,     0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(ata_clk,     0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, &sdma_clk1, &ahb_clk);
+DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(cspi3_clk,   2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(rng_clk,     0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(uart1_clk,   0, MXC_CCM_CGR0, 20, NULL, NULL, &perclk_clk);
@@ -525,9 +525,9 @@
 
 static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "emi", emi_clk)
-	_REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
-	_REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
-	_REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
+	_REGISTER_CLOCK("imx31-cspi.0", NULL, cspi1_clk)
+	_REGISTER_CLOCK("imx31-cspi.1", NULL, cspi2_clk)
+	_REGISTER_CLOCK("imx31-cspi.2", NULL, cspi3_clk)
 	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
 	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
 	_REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
@@ -564,7 +564,7 @@
 	_REGISTER_CLOCK(NULL, "ata", ata_clk)
 	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
 	_REGISTER_CLOCK(NULL, "rng", rng_clk)
-	_REGISTER_CLOCK(NULL, "sdma_ahb", sdma_clk1)
+	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk1)
 	_REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
 	_REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
 	_REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c
index 7a62e74..61e4a31 100644
--- a/arch/arm/mach-mx3/clock-imx35.c
+++ b/arch/arm/mach-mx3/clock-imx35.c
@@ -364,8 +364,8 @@
 DEFINE_CLOCK(ect_clk,    0, CCM_CGR0, 14, get_rate_ipg, NULL);
 DEFINE_CLOCK(edio_clk,   0, CCM_CGR0, 16, NULL, NULL);
 DEFINE_CLOCK(emi_clk,    0, CCM_CGR0, 18, get_rate_ipg, NULL);
-DEFINE_CLOCK(epit1_clk,  0, CCM_CGR0, 20, get_rate_ipg_per, NULL);
-DEFINE_CLOCK(epit2_clk,  1, CCM_CGR0, 22, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(epit1_clk,  0, CCM_CGR0, 20, get_rate_ipg, NULL);
+DEFINE_CLOCK(epit2_clk,  1, CCM_CGR0, 22, get_rate_ipg, NULL);
 DEFINE_CLOCK(esai_clk,   0, CCM_CGR0, 24, NULL, NULL);
 DEFINE_CLOCK(esdhc1_clk, 0, CCM_CGR0, 26, get_rate_sdhc, NULL);
 DEFINE_CLOCK(esdhc2_clk, 1, CCM_CGR0, 28, get_rate_sdhc, NULL);
@@ -451,17 +451,17 @@
 	_REGISTER_CLOCK(NULL, "ata", ata_clk)
 	_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
 	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
-	_REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
-	_REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
+	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
+	_REGISTER_CLOCK("imx35-cspi.1", NULL, cspi2_clk)
 	_REGISTER_CLOCK(NULL, "ect", ect_clk)
 	_REGISTER_CLOCK(NULL, "edio", edio_clk)
 	_REGISTER_CLOCK(NULL, "emi", emi_clk)
-	_REGISTER_CLOCK(NULL, "epit", epit1_clk)
-	_REGISTER_CLOCK(NULL, "epit", epit2_clk)
+	_REGISTER_CLOCK("imx-epit.0", NULL, epit1_clk)
+	_REGISTER_CLOCK("imx-epit.1", NULL, epit2_clk)
 	_REGISTER_CLOCK(NULL, "esai", esai_clk)
-	_REGISTER_CLOCK(NULL, "sdhc", esdhc1_clk)
-	_REGISTER_CLOCK(NULL, "sdhc", esdhc2_clk)
-	_REGISTER_CLOCK(NULL, "sdhc", esdhc3_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("fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK(NULL, "gpio", gpio1_clk)
 	_REGISTER_CLOCK(NULL, "gpio", gpio2_clk)
@@ -482,7 +482,7 @@
 	_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
 	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
 	_REGISTER_CLOCK(NULL, "scc", scc_clk)
-	_REGISTER_CLOCK(NULL, "sdma", sdma_clk)
+	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
 	_REGISTER_CLOCK(NULL, "spba", spba_clk)
 	_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
@@ -535,8 +535,16 @@
 	__raw_writel(cgr2, CCM_BASE + CCM_CGR2);
 	__raw_writel(cgr3, CCM_BASE + CCM_CGR3);
 
+	clk_enable(&iim_clk);
+	mx35_read_cpu_rev();
+
+#ifdef CONFIG_MXC_USE_EPIT
+	epit_timer_init(&epit1_clk,
+			MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1);
+#else
 	mxc_timer_init(&gpt_clk,
 			MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT);
+#endif
 
 	return 0;
 }
diff --git a/arch/arm/mach-mx3/cpu.c b/arch/arm/mach-mx3/cpu.c
index 861afe0..d00a754 100644
--- a/arch/arm/mach-mx3/cpu.c
+++ b/arch/arm/mach-mx3/cpu.c
@@ -25,15 +25,15 @@
 };
 
 static struct mx3_cpu_type mx31_cpu_type[] __initdata = {
-	{ .srev = 0x00, .name = "i.MX31(L)", .v = "1.0",  .rev = CHIP_REV_1_0	},
-	{ .srev = 0x10, .name = "i.MX31",    .v = "1.1",  .rev = CHIP_REV_1_1	},
-	{ .srev = 0x11, .name = "i.MX31L",   .v = "1.1",  .rev = CHIP_REV_1_1	},
-	{ .srev = 0x12, .name = "i.MX31",    .v = "1.15", .rev = CHIP_REV_1_1	},
-	{ .srev = 0x13, .name = "i.MX31L",   .v = "1.15", .rev = CHIP_REV_1_1	},
-	{ .srev = 0x14, .name = "i.MX31",    .v = "1.2",  .rev = CHIP_REV_1_2	},
-	{ .srev = 0x15, .name = "i.MX31L",   .v = "1.2",  .rev = CHIP_REV_1_2	},
-	{ .srev = 0x28, .name = "i.MX31",    .v = "2.0",  .rev = CHIP_REV_2_0	},
-	{ .srev = 0x29, .name = "i.MX31L",   .v = "2.0",  .rev = CHIP_REV_2_0	},
+	{ .srev = 0x00, .name = "i.MX31(L)", .v = "1.0",  .rev = MX3x_CHIP_REV_1_0 },
+	{ .srev = 0x10, .name = "i.MX31",    .v = "1.1",  .rev = MX3x_CHIP_REV_1_1 },
+	{ .srev = 0x11, .name = "i.MX31L",   .v = "1.1",  .rev = MX3x_CHIP_REV_1_1 },
+	{ .srev = 0x12, .name = "i.MX31",    .v = "1.15", .rev = MX3x_CHIP_REV_1_1 },
+	{ .srev = 0x13, .name = "i.MX31L",   .v = "1.15", .rev = MX3x_CHIP_REV_1_1 },
+	{ .srev = 0x14, .name = "i.MX31",    .v = "1.2",  .rev = MX3x_CHIP_REV_1_2 },
+	{ .srev = 0x15, .name = "i.MX31L",   .v = "1.2",  .rev = MX3x_CHIP_REV_1_2 },
+	{ .srev = 0x28, .name = "i.MX31",    .v = "2.0",  .rev = MX3x_CHIP_REV_2_0 },
+	{ .srev = 0x29, .name = "i.MX31L",   .v = "2.0",  .rev = MX3x_CHIP_REV_2_0 },
 };
 
 void __init mx31_read_cpu_rev(void)
@@ -41,7 +41,7 @@
 	u32 i, srev;
 
 	/* read SREV register from IIM module */
-	srev = __raw_readl(IO_ADDRESS(IIM_BASE_ADDR + MXC_IIMSREV));
+	srev = __raw_readl(MX31_IO_ADDRESS(MX31_IIM_BASE_ADDR + MXC_IIMSREV));
 
 	for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
 		if (srev == mx31_cpu_type[i].srev) {
@@ -55,3 +55,30 @@
 
 	printk(KERN_WARNING "Unknown CPU identifier. srev = %02x\n", srev);
 }
+
+unsigned int mx35_cpu_rev;
+EXPORT_SYMBOL(mx35_cpu_rev);
+
+void __init mx35_read_cpu_rev(void)
+{
+	u32 rev;
+	char *srev = "unknown";
+
+	rev = __raw_readl(MX35_IO_ADDRESS(MX35_IIM_BASE_ADDR + MXC_IIMSREV));
+	switch (rev) {
+	case 0x00:
+		mx35_cpu_rev = MX3x_CHIP_REV_1_0;
+		srev = "1.0";
+		break;
+	case 0x10:
+		mx35_cpu_rev = MX3x_CHIP_REV_2_0;
+		srev = "2.0";
+		break;
+	case 0x11:
+		mx35_cpu_rev = MX3x_CHIP_REV_2_1;
+		srev = "2.1";
+		break;
+	}
+
+	printk(KERN_INFO "CPU identified as i.MX35, silicon rev %s\n", srev);
+}
diff --git a/arch/arm/mach-mx3/devices-imx31.h b/arch/arm/mach-mx3/devices-imx31.h
index 3b1a44a..de95985 100644
--- a/arch/arm/mach-mx3/devices-imx31.h
+++ b/arch/arm/mach-mx3/devices-imx31.h
@@ -9,30 +9,33 @@
 #include <mach/mx31.h>
 #include <mach/devices-common.h>
 
-#define imx31_add_imx_i2c0(pdata)	\
-	imx_add_imx_i2c(0, MX31_I2C1_BASE_ADDR, SZ_4K, MX31_INT_I2C1, pdata)
-#define imx31_add_imx_i2c1(pdata)	\
-	imx_add_imx_i2c(1, MX31_I2C2_BASE_ADDR, SZ_4K, MX31_INT_I2C2, pdata)
-#define imx31_add_imx_i2c2(pdata)	\
-	imx_add_imx_i2c(2, MX31_I2C3_BASE_ADDR, SZ_4K, MX31_INT_I2C3, pdata)
+extern const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst;
+#define imx31_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx31_imx_i2c_data[id], pdata)
+#define imx31_add_imx_i2c0(pdata)	imx31_add_imx_i2c(0, pdata)
+#define imx31_add_imx_i2c1(pdata)	imx31_add_imx_i2c(1, pdata)
+#define imx31_add_imx_i2c2(pdata)	imx31_add_imx_i2c(2, pdata)
 
-#define imx31_add_imx_uart0(pdata)	\
-	imx_add_imx_uart_1irq(0, MX31_UART1_BASE_ADDR, SZ_16K, MX31_INT_UART1, pdata)
-#define imx31_add_imx_uart1(pdata)	\
-	imx_add_imx_uart_1irq(1, MX31_UART2_BASE_ADDR, SZ_16K, MX31_INT_UART2, pdata)
-#define imx31_add_imx_uart2(pdata)	\
-	imx_add_imx_uart_1irq(2, MX31_UART3_BASE_ADDR, SZ_16K, MX31_INT_UART3, pdata)
-#define imx31_add_imx_uart3(pdata)	\
-	imx_add_imx_uart_1irq(3, MX31_UART4_BASE_ADDR, SZ_16K, MX31_INT_UART4, pdata)
-#define imx31_add_imx_uart4(pdata)	\
-	imx_add_imx_uart_1irq(4, MX31_UART5_BASE_ADDR, SZ_16K, MX31_INT_UART5, pdata)
+extern const struct imx_imx_ssi_data imx31_imx_ssi_data[] __initconst;
+#define imx31_add_imx_ssi(id, pdata)    \
+	imx_add_imx_ssi(&imx31_imx_ssi_data[id], pdata)
 
+extern const struct imx_imx_uart_1irq_data imx31_imx_uart_data[] __initconst;
+#define imx31_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx31_imx_uart_data[id], pdata)
+#define imx31_add_imx_uart0(pdata)	imx31_add_imx_uart(0, pdata)
+#define imx31_add_imx_uart1(pdata)	imx31_add_imx_uart(1, pdata)
+#define imx31_add_imx_uart2(pdata)	imx31_add_imx_uart(2, pdata)
+#define imx31_add_imx_uart3(pdata)	imx31_add_imx_uart(3, pdata)
+#define imx31_add_imx_uart4(pdata)	imx31_add_imx_uart(4, pdata)
+
+extern const struct imx_mxc_nand_data imx31_mxc_nand_data __initconst;
 #define imx31_add_mxc_nand(pdata)	\
-	imx_add_mxc_nand_v1(MX31_NFC_BASE_ADDR, MX31_INT_NANDFC, pdata)
+	imx_add_mxc_nand(&imx31_mxc_nand_data, pdata)
 
-#define imx31_add_spi_imx0(pdata)	\
-	imx_add_spi_imx(0, MX31_CSPI1_BASE_ADDR, SZ_4K, MX31_INT_CSPI1, pdata)
-#define imx31_add_spi_imx1(pdata)	\
-	imx_add_spi_imx(1, MX31_CSPI2_BASE_ADDR, SZ_4K, MX31_INT_CSPI2, pdata)
-#define imx31_add_spi_imx2(pdata)	\
-	imx_add_spi_imx(2, MX31_CSPI3_BASE_ADDR, SZ_4K, MX31_INT_CSPI3, pdata)
+extern const struct imx_spi_imx_data imx31_cspi_data[] __initconst;
+#define imx31_add_cspi(id, pdata)	\
+	imx_add_spi_imx(&imx31_cspi_data[id], pdata)
+#define imx31_add_spi_imx0(pdata)	imx31_add_cspi(0, pdata)
+#define imx31_add_spi_imx1(pdata)	imx31_add_cspi(1, pdata)
+#define imx31_add_spi_imx2(pdata)	imx31_add_cspi(2, pdata)
diff --git a/arch/arm/mach-mx3/devices-imx35.h b/arch/arm/mach-mx3/devices-imx35.h
index f6a431a..5eb917b 100644
--- a/arch/arm/mach-mx3/devices-imx35.h
+++ b/arch/arm/mach-mx3/devices-imx35.h
@@ -9,29 +9,43 @@
 #include <mach/mx35.h>
 #include <mach/devices-common.h>
 
+extern const struct imx_fec_data imx35_fec_data __initconst;
+#define imx35_add_fec(pdata)	\
+	imx_add_fec(&imx35_fec_data, pdata)
+
 #define imx35_add_flexcan0(pdata)	\
 	imx_add_flexcan(0, MX35_CAN1_BASE_ADDR, SZ_16K, MX35_INT_CAN1, pdata)
 #define imx35_add_flexcan1(pdata)	\
 	imx_add_flexcan(1, MX35_CAN2_BASE_ADDR, SZ_16K, MX35_INT_CAN2, pdata)
 
-#define imx35_add_imx_i2c0(pdata)	\
-	imx_add_imx_i2c(0, MX35_I2C1_BASE_ADDR, SZ_4K, MX35_INT_I2C1, pdata)
-#define imx35_add_imx_i2c1(pdata)	\
-	imx_add_imx_i2c(1, MX35_I2C2_BASE_ADDR, SZ_4K, MX35_INT_I2C2, pdata)
-#define imx35_add_imx_i2c2(pdata)	\
-	imx_add_imx_i2c(2, MX35_I2C3_BASE_ADDR, SZ_4K, MX35_INT_I2C3, pdata)
+extern const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst;
+#define imx35_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx35_imx_i2c_data[id], pdata)
+#define imx35_add_imx_i2c0(pdata)	imx35_add_imx_i2c(0, pdata)
+#define imx35_add_imx_i2c1(pdata)	imx35_add_imx_i2c(1, pdata)
+#define imx35_add_imx_i2c2(pdata)	imx35_add_imx_i2c(2, pdata)
 
-#define imx35_add_imx_uart0(pdata)	\
-	imx_add_imx_uart_1irq(0, MX35_UART1_BASE_ADDR, SZ_16K, MX35_INT_UART1, pdata)
-#define imx35_add_imx_uart1(pdata)	\
-	imx_add_imx_uart_1irq(1, MX35_UART2_BASE_ADDR, SZ_16K, MX35_INT_UART2, pdata)
-#define imx35_add_imx_uart2(pdata)	\
-	imx_add_imx_uart_1irq(2, MX35_UART3_BASE_ADDR, SZ_16K, MX35_INT_UART3, pdata)
+extern const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst;
+#define imx35_add_imx_ssi(id, pdata)    \
+	imx_add_imx_ssi(&imx35_imx_ssi_data[id], pdata)
 
+extern const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst;
+#define imx35_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx35_imx_uart_data[id], pdata)
+#define imx35_add_imx_uart0(pdata)	imx35_add_imx_uart(0, pdata)
+#define imx35_add_imx_uart1(pdata)	imx35_add_imx_uart(1, pdata)
+#define imx35_add_imx_uart2(pdata)	imx35_add_imx_uart(2, pdata)
+
+extern const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst;
 #define imx35_add_mxc_nand(pdata)	\
-	imx_add_mxc_nand_v21(MX35_NFC_BASE_ADDR, MX35_INT_NANDFC, pdata)
+	imx_add_mxc_nand(&imx35_mxc_nand_data, pdata)
 
-#define imx35_add_spi_imx0(pdata)	\
-	imx_add_spi_imx(0, MX35_CSPI1_BASE_ADDR, SZ_4K, MX35_INT_CSPI1, pdata)
-#define imx35_add_spi_imx1(pdata)	\
-	imx_add_spi_imx(1, MX35_CSPI2_BASE_ADDR, SZ_4K, MX35_INT_CSPI2, pdata)
+extern const struct imx_spi_imx_data imx35_cspi_data[] __initconst;
+#define imx35_add_cspi(id, pdata)	\
+	imx_add_spi_imx(&imx35_cspi_data[id], pdata)
+#define imx35_add_spi_imx0(pdata)	imx35_add_cspi(0, pdata)
+#define imx35_add_spi_imx1(pdata)	imx35_add_cspi(1, pdata)
+
+extern const struct imx_esdhc_imx_data imx35_esdhc_data[] __initconst;
+#define imx35_add_esdhc(id, pdata)	\
+	imx_add_esdhc(&imx35_esdhc_data[id], pdata)
diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c
index a4fd1a2..f4dff11 100644
--- a/arch/arm/mach-mx3/devices.c
+++ b/arch/arm/mach-mx3/devices.c
@@ -281,65 +281,6 @@
 	.num_resources = ARRAY_SIZE(mxc_usbh2_resources),
 };
 
-#if defined(CONFIG_ARCH_MX35)
-static struct resource mxc_fec_resources[] = {
-	{
-		.start	= MXC_FEC_BASE_ADDR,
-		.end	= MXC_FEC_BASE_ADDR + 0xfff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= MXC_INT_FEC,
-		.end	= MXC_INT_FEC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_fec_device = {
-	.name = "fec",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_fec_resources),
-	.resource = mxc_fec_resources,
-};
-#endif
-
-static struct resource imx_ssi_resources0[] = {
-	{
-		.start	= SSI1_BASE_ADDR,
-		.end	= SSI1_BASE_ADDR + 0xfff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= MX31_INT_SSI1,
-		.end	= MX31_INT_SSI1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource imx_ssi_resources1[] = {
-	{
-		.start	= SSI2_BASE_ADDR,
-		.end	= SSI2_BASE_ADDR + 0xfff,
-		.flags	= IORESOURCE_MEM
-	}, {
-		.start	= MX31_INT_SSI2,
-		.end	= MX31_INT_SSI2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device imx_ssi_device0 = {
-	.name = "imx-ssi",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(imx_ssi_resources0),
-	.resource = imx_ssi_resources0,
-};
-
-struct platform_device imx_ssi_device1 = {
-	.name = "imx-ssi",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(imx_ssi_resources1),
-	.resource = imx_ssi_resources1,
-};
-
 static struct resource imx_wdt_resources[] = {
 	{
 		.flags = IORESOURCE_MEM,
@@ -410,10 +351,6 @@
 		mxc_usbh1_resources[0].end = MX35_OTG_BASE_ADDR + 0x5ff;
 		mxc_usbh1_resources[1].start = MXC_INT_USBHS;
 		mxc_usbh1_resources[1].end = MXC_INT_USBHS;
-		imx_ssi_resources0[1].start = MX35_INT_SSI1;
-		imx_ssi_resources0[1].end = MX35_INT_SSI1;
-		imx_ssi_resources1[1].start = MX35_INT_SSI2;
-		imx_ssi_resources1[1].end = MX35_INT_SSI2;
 		imx_wdt_resources[0].start = MX35_WDOG_BASE_ADDR;
 		imx_wdt_resources[0].end = MX35_WDOG_BASE_ADDR + 0x3fff;
 	}
diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h
index e553523..585f814 100644
--- a/arch/arm/mach-mx3/devices.h
+++ b/arch/arm/mach-mx3/devices.h
@@ -2,7 +2,6 @@
 extern struct platform_device mx3_ipu;
 extern struct platform_device mx3_fb;
 extern struct platform_device mx3_camera;
-extern struct platform_device mxc_fec_device;
 extern struct platform_device mxcsdhc_device0;
 extern struct platform_device mxcsdhc_device1;
 extern struct platform_device mxc_otg_udc_device;
@@ -10,9 +9,6 @@
 extern struct platform_device mxc_usbh1;
 extern struct platform_device mxc_usbh2;
 extern struct platform_device mxc_rnga_device;
-extern struct platform_device imx_ssi_device0;
-extern struct platform_device imx_ssi_device1;
-extern struct platform_device imx_ssi_device1;
 extern struct platform_device imx_wdt_device0;
 extern struct platform_device imx_rtc_device0;
 extern struct platform_device imx_kpp_device;
diff --git a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
index f8f15e3..1abc10d 100644
--- a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
@@ -43,14 +43,13 @@
 #include <mach/ipu.h>
 #include <mach/mx3fb.h>
 #include <mach/audmux.h>
-#include <mach/ssi.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
 
 static const struct fb_videomode fb_modedb[] = {
 	{
-		.name		= "CMO_QVGA",
+		.name		= "CMO-QVGA",
 		.refresh	= 60,
 		.xres		= 320,
 		.yres		= 240,
@@ -65,6 +64,40 @@
 		.vmode		= FB_VMODE_NONINTERLACED,
 		.flag		= 0,
 	},
+	{
+		.name		= "DVI-VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 32000,
+		.left_margin	= 100,
+		.right_margin	= 100,
+		.upper_margin	= 7,
+		.lower_margin	= 100,
+		.hsync_len	= 7,
+		.vsync_len	= 7,
+		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT |
+				  FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	},
+	{
+		.name		= "DVI-SVGA",
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 600,
+		.pixclock	= 25000,
+		.left_margin	= 75,
+		.right_margin	= 75,
+		.upper_margin	= 7,
+		.lower_margin	= 75,
+		.hsync_len	= 7,
+		.vsync_len	= 7,
+		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT |
+				  FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	},
 };
 
 static struct ipu_platform_data mx3_ipu_data = {
@@ -73,7 +106,7 @@
 
 static struct mx3fb_platform_data mx3fb_pdata = {
 	.dma_dev	= &mx3_ipu.dev,
-	.name		= "CMO_QVGA",
+	.name		= "CMO-QVGA",
 	.mode		= fb_modedb,
 	.num_modes	= ARRAY_SIZE(fb_modedb),
 };
@@ -120,6 +153,16 @@
 	MX35_PAD_STXD4__AUDMUX_AUD4_TXD,
 	MX35_PAD_SRXD4__AUDMUX_AUD4_RXD,
 	MX35_PAD_SCK4__AUDMUX_AUD4_TXC,
+	/* CAN2 */
+	MX35_PAD_TX5_RX0__CAN2_TXCAN,
+	MX35_PAD_TX4_RX1__CAN2_RXCAN,
+	/* 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,
 };
 
 #define GPIO_LED1	(2 * 32 + 29)
@@ -206,7 +249,8 @@
 	},
 };
 
-struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata = {
+static const
+struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
 	.flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
 };
 
@@ -242,7 +286,10 @@
 	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
 	mxc_register_device(&mx3_fb, &mx3fb_pdata);
 
-	mxc_register_device(&imx_ssi_device0, &eukrea_mbimxsd_ssi_pdata);
+	imx35_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
+
+	imx35_add_flexcan1(NULL);
+	imx35_add_esdhc(0, NULL);
 
 	gpio_request(GPIO_LED1, "LED1");
 	gpio_direction_output(GPIO_LED1, 1);
@@ -254,7 +301,7 @@
 
 	gpio_request(GPIO_LCDPWR, "LCDPWR");
 	gpio_direction_output(GPIO_LCDPWR, 1);
-	gpio_free(GPIO_SWITCH1);
+	gpio_free(GPIO_LCDPWR);
 
 	i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
 				ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
diff --git a/arch/arm/mach-mx3/mach-armadillo5x0.c b/arch/arm/mach-mx3/mach-armadillo5x0.c
index 68879c9..aaa30fe 100644
--- a/arch/arm/mach-mx3/mach-armadillo5x0.c
+++ b/arch/arm/mach-mx3/mach-armadillo5x0.c
@@ -571,8 +571,6 @@
 
 MACHINE_START(ARMADILLO5X0, "Armadillo-500")
 	/* Maintainer: Alberto Panizzo  */
-	.phys_io	= MX31_AIPS1_BASE_ADDR,
-	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
 	.boot_params	= MX3x_PHYS_OFFSET + 0x100,
 	.map_io		= mx31_map_io,
 	.init_irq	= mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-cpuimx35.c b/arch/arm/mach-mx3/mach-cpuimx35.c
index 2a4f8b7..9fde873 100644
--- a/arch/arm/mach-mx3/mach-cpuimx35.c
+++ b/arch/arm/mach-mx3/mach-cpuimx35.c
@@ -31,6 +31,7 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/fsl_devices.h>
+#include <linux/i2c-gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -43,7 +44,6 @@
 #include <mach/iomux-mx35.h>
 #include <mach/mxc_nand.h>
 #include <mach/mxc_ehci.h>
-#include <mach/ulpi.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
@@ -53,39 +53,16 @@
 };
 
 static const struct imxi2c_platform_data
-eukrea_cpuimx35_i2c0_data __initconst = {
-	.bitrate = 50000,
+		eukrea_cpuimx35_i2c0_data __initconst = {
+	.bitrate =		100000,
 };
 
-#define TSC2007_IRQGPIO		(2 * 32 + 2)
-static int ts_get_pendown_state(void)
-{
-	int val = 0;
-	gpio_free(TSC2007_IRQGPIO);
-	gpio_request(TSC2007_IRQGPIO, NULL);
-	gpio_direction_input(TSC2007_IRQGPIO);
-
-	val = gpio_get_value(TSC2007_IRQGPIO);
-
-	gpio_free(TSC2007_IRQGPIO);
-	gpio_request(TSC2007_IRQGPIO, NULL);
-
-	return val ? 0 : 1;
-}
-
-static int ts_init(void)
-{
-	gpio_request(TSC2007_IRQGPIO, NULL);
-	return 0;
-}
-
 static struct tsc2007_platform_data tsc2007_info = {
 	.model			= 2007,
 	.x_plate_ohms		= 180,
-	.get_pendown_state	= ts_get_pendown_state,
-	.init_platform_hw	= ts_init,
 };
 
+#define TSC2007_IRQGPIO		(2 * 32 + 2)
 static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("pcf8563", 0x51),
@@ -98,7 +75,6 @@
 };
 
 static struct platform_device *devices[] __initdata = {
-	&mxc_fec_device,
 	&imx_wdt_device0,
 };
 
@@ -135,18 +111,18 @@
 };
 
 static const struct mxc_nand_platform_data
-eukrea_cpuimx35_nand_board_info __initconst = {
+		eukrea_cpuimx35_nand_board_info __initconst = {
 	.width		= 1,
 	.hw_ecc		= 1,
 	.flash_bbt	= 1,
 };
 
-static struct mxc_usbh_platform_data otg_pdata = {
+static struct mxc_usbh_platform_data __maybe_unused otg_pdata = {
 	.portsc	= MXC_EHCI_MODE_UTMI,
 	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
-static struct mxc_usbh_platform_data usbh1_pdata = {
+static struct mxc_usbh_platform_data __maybe_unused usbh1_pdata = {
 	.portsc	= MXC_EHCI_MODE_SERIAL,
 	.flags	= MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
 		  MXC_EHCI_IPPUE_DOWN,
@@ -155,6 +131,7 @@
 static struct fsl_usb2_platform_data otg_device_pdata = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI,
+	.workaround	= FLS_USB2_WORKAROUND_ENGCM09152,
 };
 
 static int otg_mode_host;
@@ -180,6 +157,7 @@
 	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx35_pads,
 			ARRAY_SIZE(eukrea_cpuimx35_pads));
 
+	imx35_add_fec(NULL);
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
 	imx35_add_imx_uart0(&uart_pdata);
@@ -189,18 +167,13 @@
 			ARRAY_SIZE(eukrea_cpuimx35_i2c_devices));
 	imx35_add_imx_i2c0(&eukrea_cpuimx35_i2c0_data);
 
-#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);
-
+	if (otg_mode_host)
 		mxc_register_device(&mxc_otg_host, &otg_pdata);
-	}
-	mxc_register_device(&mxc_usbh1, &usbh1_pdata);
-#endif
-	if (!otg_mode_host)
+	else
 		mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
 
+	mxc_register_device(&mxc_usbh1, &usbh1_pdata);
+
 #ifdef CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD
 	eukrea_mbimxsd35_baseboard_init();
 #endif
@@ -217,8 +190,6 @@
 
 MACHINE_START(EUKREA_CPUIMX35, "Eukrea CPUIMX35")
 	/* Maintainer: Eukrea Electromatique */
-	.phys_io	= MX35_AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((MX35_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
 	.map_io         = mx35_map_io,
 	.init_irq       = mx35_init_irq,
diff --git a/arch/arm/mach-mx3/mach-kzm_arm11_01.c b/arch/arm/mach-mx3/mach-kzm_arm11_01.c
index 5b23e41..042cd56 100644
--- a/arch/arm/mach-mx3/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-mx3/mach-kzm_arm11_01.c
@@ -274,8 +274,6 @@
  * initialize __mach_desc_KZM_ARM11_01 data structure.
  */
 MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
-	.phys_io        = MX31_AIPS1_BASE_ADDR,
-	.io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
 	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
 	.map_io         = kzm_map_io,
 	.init_irq       = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c
index 6fe69e1..5c1d0e8 100644
--- a/arch/arm/mach-mx3/mach-mx31_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx31_3ds.c
@@ -301,8 +301,6 @@
  */
 MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.phys_io	= MX31_AIPS1_BASE_ADDR,
-	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
 	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
 	.map_io         = mx31_3ds_map_io,
 	.init_irq       = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx31ads.c b/arch/arm/mach-mx3/mach-mx31ads.c
index 94b3e7c..b993b9b 100644
--- a/arch/arm/mach-mx3/mach-mx31ads.c
+++ b/arch/arm/mach-mx3/mach-mx31ads.c
@@ -22,13 +22,13 @@
 #include <linux/i2c.h>
 #include <linux/irq.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
 #include <mach/common.h>
+#include <mach/board-mx31ads.h>
 #include <mach/iomux-mx3.h>
 
 #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
@@ -40,10 +40,6 @@
 #include "devices-imx31.h"
 #include "devices.h"
 
-/* Base address of PBC controller */
-#define PBC_BASE_ADDRESS        MX31_CS4_BASE_ADDR_VIRT
-/* Offsets for the PBC Controller register */
-
 /* PBC Board interrupt status register */
 #define PBC_INTSTATUS           0x000016
 
@@ -67,7 +63,6 @@
 #define PBC_INTMASK_CLEAR_REG	(PBC_INTMASK_CLEAR + PBC_BASE_ADDRESS)
 #define EXPIO_PARENT_INT	IOMUX_TO_IRQ(MX31_PIN_GPIO1_4)
 
-#define MXC_EXP_IO_BASE		(MXC_BOARD_IRQ_START)
 #define MXC_IRQ_TO_EXPIO(irq)	((irq) - MXC_EXP_IO_BASE)
 
 #define EXPIO_INT_XUART_INTA	(MXC_EXP_IO_BASE + 10)
@@ -517,7 +512,7 @@
 
 static void mxc_init_audio(void)
 {
-	mxc_register_device(&imx_ssi_device0, NULL);
+	imx31_add_imx_ssi(0, NULL);
 	mxc_iomux_setup_multiple_pins(ssi_pins, ARRAY_SIZE(ssi_pins), "ssi");
 }
 
@@ -574,8 +569,6 @@
  */
 MACHINE_START(MX31ADS, "Freescale MX31ADS")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.phys_io	= MX31_AIPS1_BASE_ADDR,
-	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
 	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
 	.map_io         = mx31ads_map_io,
 	.init_irq       = mx31ads_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx31lilly.c b/arch/arm/mach-mx3/mach-mx31lilly.c
index 7c37daa..42f47fa 100644
--- a/arch/arm/mach-mx3/mach-mx31lilly.c
+++ b/arch/arm/mach-mx3/mach-mx31lilly.c
@@ -348,8 +348,6 @@
 };
 
 MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
-	.phys_io	= MX31_AIPS1_BASE_ADDR,
-	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
 	.boot_params	= MX3x_PHYS_OFFSET + 0x100,
 	.map_io		= mx31_map_io,
 	.init_irq	= mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx31lite.c b/arch/arm/mach-mx3/mach-mx31lite.c
index f66a957..b938958 100644
--- a/arch/arm/mach-mx3/mach-mx31lite.c
+++ b/arch/arm/mach-mx3/mach-mx31lite.c
@@ -282,8 +282,6 @@
 
 MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.phys_io        = MX31_AIPS1_BASE_ADDR,
-	.io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
 	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
 	.map_io         = mx31lite_map_io,
 	.init_irq       = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx31moboard.c b/arch/arm/mach-mx3/mach-mx31moboard.c
index 7a075e8..eb5f426 100644
--- a/arch/arm/mach-mx3/mach-mx31moboard.c
+++ b/arch/arm/mach-mx3/mach-mx31moboard.c
@@ -560,8 +560,6 @@
 
 MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
 	/* Maintainer: Valentin Longchamp, EPFL Mobots group */
-	.phys_io	= MX31_AIPS1_BASE_ADDR,
-	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
 	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
 	.map_io         = mx31_map_io,
 	.init_irq       = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx35_3ds.c b/arch/arm/mach-mx3/mach-mx35_3ds.c
index 1c30d72..05f628d 100644
--- a/arch/arm/mach-mx3/mach-mx35_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx35_3ds.c
@@ -1,5 +1,6 @@
 /*
  * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Marc Kleine-Budde, Pengutronix
  *
  * Author: Fabio Estevam <fabio.estevam@freescale.com>
  *
@@ -27,6 +28,8 @@
 #include <linux/gpio.h>
 #include <linux/fsl_devices.h>
 
+#include <linux/mtd/physmap.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
@@ -35,6 +38,7 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx35.h>
+#include <mach/mxc_ehci.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
@@ -43,8 +47,34 @@
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
+static struct physmap_flash_data mx35pdk_flash_data = {
+	.width  = 2,
+};
+
+static struct resource mx35pdk_flash_resource = {
+	.start	= MX35_CS0_BASE_ADDR,
+	.end	= MX35_CS0_BASE_ADDR + SZ_64M - 1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device mx35pdk_flash = {
+	.name	= "physmap-flash",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &mx35pdk_flash_data,
+	},
+	.resource = &mx35pdk_flash_resource,
+	.num_resources = 1,
+};
+
+static const struct mxc_nand_platform_data mx35pdk_nand_board_info __initconst = {
+	.width = 1,
+	.hw_ecc = 1,
+	.flash_bbt = 1,
+};
+
 static struct platform_device *devices[] __initdata = {
-	&mxc_fec_device,
+	&mx35pdk_flash,
 };
 
 static struct pad_desc mx35pdk_pads[] = {
@@ -75,14 +105,24 @@
 	/* USBOTG */
 	MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR,
 	MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC,
+	/* USBH1 */
+	MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR,
+	MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC,
 };
 
 /* OTG config */
-static struct fsl_usb2_platform_data usb_pdata = {
+static struct fsl_usb2_platform_data usb_otg_pdata = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
 };
 
+/* USB HOST config */
+static struct mxc_usbh_platform_data usb_host_pdata = {
+	.portsc		= MXC_EHCI_MODE_SERIAL,
+	.flags		= MXC_EHCI_INTERFACE_SINGLE_UNI |
+			  MXC_EHCI_INTERNAL_PHY,
+};
+
 /*
  * Board specific initialization.
  */
@@ -90,11 +130,16 @@
 {
 	mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
 
+	imx35_add_fec(NULL);
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
 	imx35_add_imx_uart0(&uart_pdata);
 
-	mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
+	mxc_register_device(&mxc_otg_udc_device, &usb_otg_pdata);
+
+	mxc_register_device(&mxc_usbh1, &usb_host_pdata);
+
+	imx35_add_mxc_nand(&mx35pdk_nand_board_info);
 }
 
 static void __init mx35pdk_timer_init(void)
@@ -108,8 +153,6 @@
 
 MACHINE_START(MX35_3DS, "Freescale MX35PDK")
 	/* Maintainer: Freescale Semiconductor, Inc */
-	.phys_io	= MX35_AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((MX35_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
 	.map_io         = mx35_map_io,
 	.init_irq       = mx35_init_irq,
diff --git a/arch/arm/mach-mx3/mach-pcm037.c b/arch/arm/mach-mx3/mach-pcm037.c
index 214de11..86e86c1 100644
--- a/arch/arm/mach-mx3/mach-pcm037.c
+++ b/arch/arm/mach-mx3/mach-pcm037.c
@@ -680,8 +680,6 @@
 
 MACHINE_START(PCM037, "Phytec Phycore pcm037")
 	/* Maintainer: Pengutronix */
-	.phys_io	= MX31_AIPS1_BASE_ADDR,
-	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
 	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
 	.map_io         = mx31_map_io,
 	.init_irq       = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-pcm037_eet.c b/arch/arm/mach-mx3/mach-pcm037_eet.c
index c8b9821..99e0894 100644
--- a/arch/arm/mach-mx3/mach-pcm037_eet.c
+++ b/arch/arm/mach-mx3/mach-pcm037_eet.c
@@ -19,6 +19,7 @@
 
 #include "pcm037.h"
 #include "devices.h"
+#include "devices-imx31.h"
 
 static unsigned int pcm037_eet_pins[] = {
 	/* Reserve and hardwire GPIO 57 high - S6E63D6 chipselect */
@@ -181,7 +182,7 @@
 	/* SPI */
 	spi_register_board_info(pcm037_spi_dev, ARRAY_SIZE(pcm037_spi_dev));
 #if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
-	imx35_add_spi_imx0(&pcm037_spi1_pdata);
+	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 28886f0..4e1de87 100644
--- a/arch/arm/mach-mx3/mach-pcm043.c
+++ b/arch/arm/mach-mx3/mach-pcm043.c
@@ -42,7 +42,6 @@
 #include <mach/mxc_ehci.h>
 #include <mach/ulpi.h>
 #include <mach/audmux.h>
-#include <mach/ssi.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
@@ -141,7 +140,6 @@
 
 static struct platform_device *devices[] __initdata = {
 	&pcm043_flash,
-	&mxc_fec_device,
 	&imx_wdt_device0,
 };
 
@@ -217,6 +215,13 @@
 	/* CAN2 */
 	MX35_PAD_TX5_RX0__CAN2_TXCAN,
 	MX35_PAD_TX4_RX1__CAN2_RXCAN,
+	/* esdhc */
+	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,
 };
 
 #define AC97_GPIO_TXFS	(1 * 32 + 31)
@@ -293,7 +298,7 @@
 	mdelay(1);
 }
 
-static struct imx_ssi_platform_data pcm043_ssi_pdata = {
+static const struct imx_ssi_platform_data pcm043_ssi_pdata __initconst = {
 	.ac97_reset = pcm043_ac97_cold_reset,
 	.ac97_warm_reset = pcm043_ac97_warm_reset,
 	.flags = IMX_SSI_USE_AC97,
@@ -357,11 +362,12 @@
 			MXC_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */
 			MXC_AUDMUX_V2_PDCR_RXDSEL(3));
 
+	imx35_add_fec(NULL);
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
 	imx35_add_imx_uart0(&uart_pdata);
 	imx35_add_mxc_nand(&pcm037_nand_board_info);
-	mxc_register_device(&imx_ssi_device0, &pcm043_ssi_pdata);
+	imx35_add_imx_ssi(0, &pcm043_ssi_pdata);
 
 	imx35_add_imx_uart1(&uart_pdata);
 
@@ -389,6 +395,7 @@
 		mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
 
 	imx35_add_flexcan1(NULL);
+	imx35_add_esdhc(0, NULL);
 }
 
 static void __init pcm043_timer_init(void)
@@ -402,8 +409,6 @@
 
 MACHINE_START(PCM043, "Phytec Phycore pcm043")
 	/* Maintainer: Pengutronix */
-	.phys_io	= MX35_AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((MX35_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
 	.map_io         = mx35_map_io,
 	.init_irq       = mx35_init_irq,
diff --git a/arch/arm/mach-mx3/mach-qong.c b/arch/arm/mach-mx3/mach-qong.c
index c8c380e..fd1050c 100644
--- a/arch/arm/mach-mx3/mach-qong.c
+++ b/arch/arm/mach-mx3/mach-qong.c
@@ -270,8 +270,6 @@
 
 MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
 	/* Maintainer: DENX Software Engineering GmbH */
-	.phys_io        = MX31_AIPS1_BASE_ADDR,
-	.io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
 	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
 	.map_io         = mx31_map_io,
 	.init_irq       = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mm.c b/arch/arm/mach-mx3/mm.c
index 20e48c0..b4ffc53 100644
--- a/arch/arm/mach-mx3/mm.c
+++ b/arch/arm/mach-mx3/mm.c
@@ -110,6 +110,24 @@
 static int mxc_init_l2x0(void)
 {
 	void __iomem *l2x0_base;
+	void __iomem *clkctl_base;
+/*
+ * First of all, we must repair broken chip settings. There are some
+ * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
+ * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
+ * Workaraound is to setup the correct register setting prior enabling the
+ * L2 cache. This should not hurt already working CPUs, as they are using the
+ * same value
+ */
+#define L2_MEM_VAL 0x10
+
+	clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
+	if (clkctl_base != NULL) {
+		writel(0x00000515, clkctl_base + L2_MEM_VAL);
+		iounmap(clkctl_base);
+	} else {
+		pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
+	}
 
 	l2x0_base = ioremap(L2CC_BASE_ADDR, 4096);
 	if (IS_ERR(l2x0_base)) {
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 0848db5..a2df9ac 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -5,11 +5,14 @@
 	default y
 	select MXC_TZIC
 	select ARCH_MXC_IOMUX_V3
+	select ARCH_MXC_AUDMUX_V2
 
 comment "MX5 platforms:"
 
 config MACH_MX51_BABBAGE
 	bool "Support MX51 BABBAGE platforms"
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
 	help
 	  Include support for MX51 Babbage platform, also known as MX51EVK in
 	  u-boot. This includes specific configurations for the board and its
@@ -17,6 +20,8 @@
 
 config MACH_MX51_3DS
 	bool "Support MX51PDK (3DS)"
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_DEBUG_BOARD
 	help
 	  Include support for MX51PDK (3DS) platform. This includes specific
@@ -24,6 +29,10 @@
 
 config MACH_EUKREA_CPUIMX51
 	bool "Support Eukrea CPUIMX51 module"
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
 	  Include support for Eukrea CPUIMX51 platform. This includes
 	  specific configurations for the module and its peripherals.
@@ -36,10 +45,43 @@
 config MACH_EUKREA_MBIMX51_BASEBOARD
 	prompt "Eukrea MBIMX51 development board"
 	bool
+	select IMX_HAVE_PLATFORM_ESDHC
 	help
 	  This adds board specific devices that can be found on Eukrea's
 	  MBIMX51 evaluation board.
 
 endchoice
 
+config MACH_EUKREA_CPUIMX51SD
+	bool "Support Eukrea CPUIMX51SD module"
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_SPI_IMX
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_NAND
+	help
+	  Include support for Eukrea CPUIMX51SD platform. This includes
+	  specific configurations for the module and its peripherals.
+
+choice
+	prompt "Baseboard"
+	depends on MACH_EUKREA_CPUIMX51SD
+	default MACH_EUKREA_MBIMXSD51_BASEBOARD
+
+config MACH_EUKREA_MBIMXSD51_BASEBOARD
+	prompt "Eukrea MBIMXSD development board"
+	bool
+	select IMX_HAVE_PLATFORM_ESDHC
+	help
+	  This adds board specific devices that can be found on Eukrea's
+	  MBIMXSD evaluation board.
+
+endchoice
+
+config MACH_MX51_EFIKAMX
+	bool "Support MX51 Genesi Efika MX nettop"
+	select IMX_HAVE_PLATFORM_IMX_UART
+	help
+	  Include support for Genesi Efika MX nettop. This includes specific
+	  configurations for the board and its peripherals.
+
 endif
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 86c66e7..1769c16 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -9,3 +9,6 @@
 obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
 obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
+obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
+obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c
index 623607a..6a9792f 100644
--- a/arch/arm/mach-mx5/board-cpuimx51.c
+++ b/arch/arm/mach-mx5/board-cpuimx51.c
@@ -28,9 +28,7 @@
 #include <mach/eukrea-baseboards.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/imx-uart.h>
 #include <mach/iomux-mx51.h>
-#include <mach/i2c.h>
 #include <mach/mxc_ehci.h>
 
 #include <asm/irq.h>
@@ -39,6 +37,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "devices-imx51.h"
 #include "devices.h"
 
 #define CPUIMX51_USBH1_STP	(0*32 + 27)
@@ -109,7 +108,6 @@
 #endif
 
 static struct platform_device *devices[] __initdata = {
-	&mxc_fec_device,
 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
 	&serial_device,
 #endif
@@ -148,11 +146,19 @@
 	MX51_PAD_USBH1_STP__USBH1_STP,
 };
 
-static struct imxuart_platform_data uart_pdata = {
+static const struct mxc_nand_platform_data
+		eukrea_cpuimx51_nand_board_info __initconst = {
+	.width		= 1,
+	.hw_ecc		= 1,
+	.flash_bbt	= 1,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static struct imxi2c_platform_data eukrea_cpuimx51_i2c_data = {
+static const
+struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = {
 	.bitrate = 100000,
 };
 
@@ -239,7 +245,9 @@
 	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
 					ARRAY_SIZE(eukrea_cpuimx51_pads));
 
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	imx51_add_imx_uart(0, &uart_pdata);
+	imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info);
+
 	gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq");
 	gpio_direction_input(CPUIMX51_QUARTA_GPIO);
 	gpio_free(CPUIMX51_QUARTA_GPIO);
@@ -253,9 +261,10 @@
 	gpio_direction_input(CPUIMX51_QUARTD_GPIO);
 	gpio_free(CPUIMX51_QUARTD_GPIO);
 
+	imx51_add_fec(NULL);
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
-	mxc_register_device(&mxc_i2c_device1, &eukrea_cpuimx51_i2c_data);
+	imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data);
 	i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices,
 				ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
 
@@ -283,8 +292,6 @@
 
 MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
 	/* Maintainer: Eric Bénard <eric@eukrea.com> */
-	.phys_io = MX51_AIPS1_BASE_ADDR,
-	.io_pg_offst = ((MX51_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params = PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
 	.init_irq = mx51_init_irq,
diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c
new file mode 100644
index 0000000..4b3a611
--- /dev/null
+++ b/arch/arm/mach-mx5/board-cpuimx51sd.c
@@ -0,0 +1,331 @@
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * based on board-mx51_babbage.c which is
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c/tsc2007.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/fsl_devices.h>
+#include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/can/platform/mcp251x.h>
+
+#include <mach/eukrea-baseboards.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.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"
+
+#define USBH1_RST		(1*32 + 28)
+#define ETH_RST			(1*32 + 31)
+#define TSC2007_IRQGPIO		(2*32 + 12)
+#define CAN_IRQGPIO		(0*32 + 1)
+#define CAN_RST			(3*32 + 15)
+#define CAN_NCS			(3*32 + 24)
+#define CAN_RXOBF		(0*32 + 4)
+#define CAN_RX1BF		(0*32 + 6)
+#define CAN_TXORTS		(0*32 + 7)
+#define CAN_TX1RTS		(0*32 + 8)
+#define CAN_TX2RTS		(0*32 + 9)
+#define I2C_SCL			(3*32 + 16)
+#define I2C_SDA			(3*32 + 17)
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET		0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN	(1 << 25)
+
+#define	MX51_USB_PLLDIV_12_MHZ		0x00
+#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
+#define	MX51_USB_PLL_DIV_24_MHZ		0x02
+
+#define CPUIMX51SD_GPIO_3_12 IOMUX_PAD(0x57C, 0x194, 3, 0x0, 0, \
+				MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
+
+static struct pad_desc eukrea_cpuimx51sd_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,
+
+	/* 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,
+	MX51_PAD_USBH1_STP__USBH1_STP,
+	MX51_PAD_EIM_CS3__GPIO_2_28,		/* PHY nRESET */
+
+	/* FEC */
+	MX51_PAD_EIM_DTACK__GPIO_2_31,		/* PHY nRESET */
+
+	/* HSI2C */
+	MX51_PAD_I2C1_CLK__GPIO_4_16,
+	MX51_PAD_I2C1_DAT__GPIO_4_17,
+
+	/* CAN */
+	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+	MX51_PAD_CSPI1_SS0__GPIO_4_24,		/* nCS */
+	MX51_PAD_CSI2_PIXCLK__GPIO_4_15,	/* nReset */
+	MX51_PAD_GPIO_1_1__GPIO_1_1,		/* IRQ */
+	MX51_PAD_GPIO_1_4__GPIO_1_4,		/* Control signals */
+	MX51_PAD_GPIO_1_6__GPIO_1_6,
+	MX51_PAD_GPIO_1_7__GPIO_1_7,
+	MX51_PAD_GPIO_1_8__GPIO_1_8,
+	MX51_PAD_GPIO_1_9__GPIO_1_9,
+
+	/* Touchscreen */
+	CPUIMX51SD_GPIO_3_12,			/* IRQ */
+};
+
+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[] = {
+	{
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	}, {
+		I2C_BOARD_INFO("tsc2007", 0x49),
+		.type		= "tsc2007",
+		.platform_data	= &tsc2007_info,
+		.irq		= gpio_to_irq(TSC2007_IRQGPIO),
+	},
+};
+
+static const struct mxc_nand_platform_data
+		eukrea_cpuimx51sd_nand_board_info __initconst = {
+	.width		= 1,
+	.hw_ecc		= 1,
+	.flash_bbt	= 1,
+};
+
+/* 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);
+	usbother_base = 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);
+	return 0;
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *usbother_base;
+
+	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+	/* The clock for the USBH1 ULPI port will come from the PHY. */
+	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;
+}
+
+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 = {
+	.operating_mode	= FSL_USB2_DR_DEVICE,
+	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
+};
+
+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;
+
+static int __init eukrea_cpuimx51sd_otg_mode(char *options)
+{
+	if (!strcmp(options, "host"))
+		otg_mode_host = 1;
+	else if (!strcmp(options, "device"))
+		otg_mode_host = 0;
+	else
+		pr_info("otg_mode neither \"host\" nor \"device\". "
+			"Defaulting to device\n");
+	return 0;
+}
+__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);
+
+static struct i2c_gpio_platform_data pdata = {
+	.sda_pin		= I2C_SDA,
+	.sda_is_open_drain	= 0,
+	.scl_pin		= I2C_SCL,
+	.scl_is_open_drain	= 0,
+	.udelay			= 2,
+};
+
+static struct platform_device hsi2c_gpio_device = {
+	.name			= "i2c-gpio",
+	.id			= 0,
+	.dev.platform_data	= &pdata,
+};
+
+static struct mcp251x_platform_data mcp251x_info = {
+	.oscillator_frequency = 24E6,
+};
+
+static struct spi_board_info cpuimx51sd_spi_device[] = {
+	{
+		.modalias        = "mcp2515",
+		.max_speed_hz    = 6500000,
+		.bus_num         = 0,
+		.mode		= SPI_MODE_0,
+		.chip_select     = 0,
+		.platform_data   = &mcp251x_info,
+		.irq             = gpio_to_irq(0 * 32 + 1)
+	},
+};
+
+static int cpuimx51sd_spi1_cs[] = {
+	CAN_NCS,
+};
+
+static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = {
+	.chipselect	= cpuimx51sd_spi1_cs,
+	.num_chipselect	= ARRAY_SIZE(cpuimx51sd_spi1_cs),
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&hsi2c_gpio_device,
+};
+
+static void __init eukrea_cpuimx51sd_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
+					ARRAY_SIZE(eukrea_cpuimx51sd_pads));
+
+	imx51_add_imx_uart(0, &uart_pdata);
+	imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
+
+	gpio_request(ETH_RST, "eth_rst");
+	gpio_set_value(ETH_RST, 1);
+	imx51_add_fec(NULL);
+
+	gpio_request(CAN_IRQGPIO, "can_irq");
+	gpio_direction_input(CAN_IRQGPIO);
+	gpio_free(CAN_IRQGPIO);
+	gpio_request(CAN_NCS, "can_ncs");
+	gpio_direction_output(CAN_NCS, 1);
+	gpio_free(CAN_NCS);
+	gpio_request(CAN_RST, "can_rst");
+	gpio_direction_output(CAN_RST, 0);
+	msleep(20);
+	gpio_set_value(CAN_RST, 1);
+	imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
+	spi_register_board_info(cpuimx51sd_spi_device,
+				ARRAY_SIZE(cpuimx51sd_spi_device));
+
+	gpio_request(TSC2007_IRQGPIO, "tsc2007_irq");
+	gpio_direction_input(TSC2007_IRQGPIO);
+	gpio_free(TSC2007_IRQGPIO);
+
+	i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices,
+			ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices));
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+	if (otg_mode_host)
+		mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+	else {
+		initialize_otg_port(NULL);
+		mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+	}
+
+	gpio_request(USBH1_RST, "usb_rst");
+	gpio_direction_output(USBH1_RST, 0);
+	msleep(20);
+	gpio_set_value(USBH1_RST, 1);
+	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
+	eukrea_mbimxsd51_baseboard_init();
+#endif
+}
+
+static void __init eukrea_cpuimx51sd_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mxc_timer = {
+	.init	= eukrea_cpuimx51sd_timer_init,
+};
+
+MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
+	/* Maintainer: Eric Bénard <eric@eukrea.com> */
+	.boot_params = PHYS_OFFSET + 0x100,
+	.map_io = mx51_map_io,
+	.init_irq = mx51_init_irq,
+	.init_machine = eukrea_cpuimx51sd_init,
+	.timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c
index f95c2fd..79ce8dc 100644
--- a/arch/arm/mach-mx5/board-mx51_3ds.c
+++ b/arch/arm/mach-mx5/board-mx51_3ds.c
@@ -13,6 +13,7 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/spi/spi.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -21,12 +22,13 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx51.h>
-#include <mach/imx-uart.h>
 #include <mach/3ds_debugboard.h>
 
+#include "devices-imx51.h"
 #include "devices.h"
 
 #define EXPIO_PARENT_INT	(MXC_INTERNAL_IRQS + GPIO_PORTA + 6)
+#define MX51_3DS_ECSPI2_CS	(GPIO_PORTC + 28)
 
 static struct pad_desc mx51_3ds_pads[] = {
 	/* UART1 */
@@ -61,19 +63,25 @@
 	MX51_PAD_KEY_COL3__KEY_COL3,
 	MX51_PAD_KEY_COL4__KEY_COL4,
 	MX51_PAD_KEY_COL5__KEY_COL5,
+
+	/* eCSPI2 */
+	MX51_PAD_NANDF_RB2__ECSPI2_SCLK,
+	MX51_PAD_NANDF_RB3__ECSPI2_MISO,
+	MX51_PAD_NANDF_D15__ECSPI2_MOSI,
+	MX51_PAD_NANDF_D12__GPIO_3_28,
 };
 
 /* Serial ports */
 #if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
-static struct imxuart_platform_data uart_pdata = {
+static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
 static inline void mxc_init_imx_uart(void)
 {
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-	mxc_register_device(&mxc_uart_device1, &uart_pdata);
-	mxc_register_device(&mxc_uart_device2, &uart_pdata);
+	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)
@@ -127,6 +135,26 @@
 }
 #endif
 
+static int mx51_3ds_spi2_cs[] = {
+	MXC_SPI_CS(0),
+	MX51_3DS_ECSPI2_CS,
+};
+
+static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = {
+	.chipselect	= mx51_3ds_spi2_cs,
+	.num_chipselect	= ARRAY_SIZE(mx51_3ds_spi2_cs),
+};
+
+static struct spi_board_info mx51_3ds_spi_nor_device[] = {
+	{
+	 .modalias = "m25p80",
+	 .max_speed_hz = 25000000,	/* max spi clock (SCK) speed in HZ */
+	 .bus_num = 1,
+	 .chip_select = 1,
+	 .mode = SPI_MODE_0,
+	 .platform_data = NULL,},
+};
+
 /*
  * Board specific initialization.
  */
@@ -136,6 +164,10 @@
 					ARRAY_SIZE(mx51_3ds_pads));
 	mxc_init_imx_uart();
 
+	imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
+	spi_register_board_info(mx51_3ds_spi_nor_device,
+				ARRAY_SIZE(mx51_3ds_spi_nor_device));
+
 	if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT))
 		printk(KERN_WARNING "Init of the debugboard failed, all "
 				    "devices on the board are unusable.\n");
@@ -154,8 +186,6 @@
 
 MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.phys_io = MX51_AIPS1_BASE_ADDR,
-	.io_pg_offst = ((MX51_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params = PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
 	.init_irq = mx51_init_irq,
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 6e384d9..0821fe9 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -17,12 +17,11 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
+#include <linux/fec.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/imx-uart.h>
 #include <mach/iomux-mx51.h>
-#include <mach/i2c.h>
 #include <mach/mxc_ehci.h>
 
 #include <asm/irq.h>
@@ -31,11 +30,13 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "devices-imx51.h"
 #include "devices.h"
 
 #define BABBAGE_USB_HUB_RESET	(0*32 + 7)	/* GPIO_1_7 */
 #define BABBAGE_USBH1_STP	(0*32 + 27)	/* GPIO_1_27 */
-#define BABBAGE_PHY_RESET (1*32 +5)	/* GPIO_2_5 */
+#define BABBAGE_PHY_RESET	(1*32 + 5)	/* GPIO_2_5 */
+#define BABBAGE_FEC_PHY_RESET	(1*32 + 14)	/* GPIO_2_14 */
 
 /* USB_CTRL_1 */
 #define MX51_USB_CTRL_1_OFFSET			0x10
@@ -45,10 +46,6 @@
 #define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
 #define	MX51_USB_PLL_DIV_24_MHZ	0x02
 
-static struct platform_device *devices[] __initdata = {
-	&mxc_fec_device,
-};
-
 static struct pad_desc mx51babbage_pads[] = {
 	/* UART1 */
 	MX51_PAD_UART1_RXD__UART1_RXD,
@@ -93,19 +90,41 @@
 
 	/* USB HUB reset line*/
 	MX51_PAD_GPIO_1_7__GPIO_1_7,
+
+	/* FEC */
+	MX51_PAD_EIM_EB2__FEC_MDIO,
+	MX51_PAD_EIM_EB3__FEC_RDAT1,
+	MX51_PAD_EIM_CS2__FEC_RDAT2,
+	MX51_PAD_EIM_CS3__FEC_RDAT3,
+	MX51_PAD_EIM_CS4__FEC_RX_ER,
+	MX51_PAD_EIM_CS5__FEC_CRS,
+	MX51_PAD_NANDF_RB2__FEC_COL,
+	MX51_PAD_NANDF_RB3__FEC_RXCLK,
+	MX51_PAD_NANDF_RB6__FEC_RDAT0,
+	MX51_PAD_NANDF_RB7__FEC_TDAT0,
+	MX51_PAD_NANDF_CS2__FEC_TX_ER,
+	MX51_PAD_NANDF_CS3__FEC_MDC,
+	MX51_PAD_NANDF_CS4__FEC_TDAT1,
+	MX51_PAD_NANDF_CS5__FEC_TDAT2,
+	MX51_PAD_NANDF_CS6__FEC_TDAT3,
+	MX51_PAD_NANDF_CS7__FEC_TX_EN,
+	MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
+
+	/* FEC PHY reset line */
+	MX51_PAD_EIM_A20__GPIO_2_14,
 };
 
 /* Serial ports */
 #if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
-static struct imxuart_platform_data uart_pdata = {
+static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
 static inline void mxc_init_imx_uart(void)
 {
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-	mxc_register_device(&mxc_uart_device1, &uart_pdata);
-	mxc_register_device(&mxc_uart_device2, &uart_pdata);
+	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)
@@ -113,7 +132,7 @@
 }
 #endif /* SERIAL_IMX */
 
-static struct imxi2c_platform_data babbage_i2c_data = {
+static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
 	.bitrate = 100000,
 };
 
@@ -171,6 +190,22 @@
 	gpio_set_value(BABBAGE_USB_HUB_RESET, 1);
 }
 
+static inline void babbage_fec_reset(void)
+{
+	int ret;
+
+	/* reset FEC PHY */
+	ret = gpio_request(BABBAGE_FEC_PHY_RESET, "fec-phy-reset");
+	if (ret) {
+		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+		return;
+	}
+	gpio_direction_output(BABBAGE_FEC_PHY_RESET, 0);
+	gpio_set_value(BABBAGE_FEC_PHY_RESET, 0);
+	msleep(1);
+	gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
+}
+
 /* 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.*/
@@ -178,7 +213,7 @@
 {
 	u32 v;
 	void __iomem *usb_base;
-	u32 usbother_base;
+	void __iomem *usbother_base;
 
 	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -196,7 +231,7 @@
 {
 	u32 v;
 	void __iomem *usb_base;
-	u32 usbother_base;
+	void __iomem *usbother_base;
 
 	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -250,10 +285,11 @@
 	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
 					ARRAY_SIZE(mx51babbage_pads));
 	mxc_init_imx_uart();
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	babbage_fec_reset();
+	imx51_add_fec(NULL);
 
-	mxc_register_device(&mxc_i2c_device0, &babbage_i2c_data);
-	mxc_register_device(&mxc_i2c_device1, &babbage_i2c_data);
+	imx51_add_imx_i2c(0, &babbage_i2c_data);
+	imx51_add_imx_i2c(1, &babbage_i2c_data);
 	mxc_register_device(&mxc_hsi2c_device, &babbage_hsi2c_data);
 
 	if (otg_mode_host)
@@ -281,9 +317,7 @@
 
 MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
 	/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
-	.phys_io = MX51_AIPS1_BASE_ADDR,
-	.io_pg_offst = ((MX51_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
 	.init_irq = mx51_init_irq,
 	.init_machine = mxc_board_init,
diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c
new file mode 100644
index 0000000..6e623bd
--- /dev/null
+++ b/arch/arm/mach-mx5/board-mx51_efikamx.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2010 Linaro Limited
+ *
+ * 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/delay.h>
+#include <linux/io.h>
+#include <linux/fsl_devices.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"
+
+#define	MX51_USB_PLL_DIV_24_MHZ	0x01
+
+static struct pad_desc 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,
+};
+
+/* 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);
+	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,
+};
+
+static void __init mxc_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
+					ARRAY_SIZE(mx51efikamx_pads));
+	mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+	mxc_init_imx_uart();
+}
+
+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,
+};
+
+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_irq = mx51_init_irq,
+	.init_machine =  mxc_board_init,
+	.timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
index 57c10a9..f2aae92 100644
--- a/arch/arm/mach-mx5/clock-mx51.c
+++ b/arch/arm/mach-mx5/clock-mx51.c
@@ -41,34 +41,66 @@
 
 #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
 
+/* calculate best pre and post dividers to get the required divider */
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
+	u32 max_pre, u32 max_post)
+{
+	if (div >= max_pre * max_post) {
+		*pre = max_pre;
+		*post = max_post;
+	} else if (div >= max_pre) {
+		u32 min_pre, temp_pre, old_err, err;
+		min_pre = DIV_ROUND_UP(div, max_post);
+		old_err = max_pre;
+		for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
+			err = div % temp_pre;
+			if (err == 0) {
+				*pre = temp_pre;
+				break;
+			}
+			err = temp_pre - err;
+			if (err < old_err) {
+				old_err = err;
+				*pre = temp_pre;
+			}
+		}
+		*post = DIV_ROUND_UP(div, *pre);
+	} else {
+		*pre = div;
+		*post = 1;
+	}
+}
+
+static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
+{
+	u32 reg = __raw_readl(clk->enable_reg);
+
+	reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+	reg |= mode << clk->enable_shift;
+
+	__raw_writel(reg, clk->enable_reg);
+}
+
 static int _clk_ccgr_enable(struct clk *clk)
 {
-	u32 reg;
-
-	reg = __raw_readl(clk->enable_reg);
-	reg |= MXC_CCM_CCGRx_MOD_ON << clk->enable_shift;
-	__raw_writel(reg, clk->enable_reg);
-
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
 	return 0;
 }
 
 static void _clk_ccgr_disable(struct clk *clk)
 {
-	u32 reg;
-	reg = __raw_readl(clk->enable_reg);
-	reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
-	__raw_writel(reg, clk->enable_reg);
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
+}
 
+static int _clk_ccgr_enable_inrun(struct clk *clk)
+{
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
+	return 0;
 }
 
 static void _clk_ccgr_disable_inwait(struct clk *clk)
 {
-	u32 reg;
-
-	reg = __raw_readl(clk->enable_reg);
-	reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
-	reg |= MXC_CCM_CCGRx_MOD_IDLE << clk->enable_shift;
-	__raw_writel(reg, clk->enable_reg);
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
 }
 
 /*
@@ -542,60 +574,60 @@
 	return 0;
 }
 
-static unsigned long clk_uart_get_rate(struct clk *clk)
+#define clk_nfc_set_parent	NULL
+
+static unsigned long clk_nfc_get_rate(struct clk *clk)
 {
-	u32 reg, prediv, podf;
-	unsigned long parent_rate;
+	unsigned long rate;
+	u32 reg, div;
 
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CSCDR1);
-	prediv = ((reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
-		  MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) + 1;
-	podf = ((reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
-		MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
-
-	return parent_rate / (prediv * podf);
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
+	       MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
+	rate = clk_get_rate(clk->parent) / div;
+	WARN_ON(rate == 0);
+	return rate;
 }
 
-static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
+static unsigned long clk_nfc_round_rate(struct clk *clk,
+						unsigned long rate)
 {
-	u32 reg, mux;
+	u32 div;
+	unsigned long parent_rate = clk_get_rate(clk->parent);
 
-	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
-		       &lp_apm_clk);
-	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_UART_CLK_SEL_MASK;
-	reg |= mux << MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
+	if (!rate)
+		return -EINVAL;
 
-	return 0;
+	div = parent_rate / rate;
+
+	if (parent_rate % rate)
+		div++;
+
+	if (div > 8)
+		return -EINVAL;
+
+	return parent_rate / div;
+
 }
 
-static unsigned long clk_usboh3_get_rate(struct clk *clk)
+static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
 {
-	u32 reg, prediv, podf;
-	unsigned long parent_rate;
+	u32 reg, div;
 
-	parent_rate = clk_get_rate(clk->parent);
+	div = clk_get_rate(clk->parent) / rate;
+	if (div == 0)
+		div++;
+	if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
+		return -EINVAL;
 
-	reg = __raw_readl(MXC_CCM_CSCDR1);
-	prediv = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK) >>
-		  MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET) + 1;
-	podf = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK) >>
-		MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET) + 1;
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
+	reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
+	__raw_writel(reg, MXC_CCM_CBCDR);
 
-	return parent_rate / (prediv * podf);
-}
-
-static int _clk_usboh3_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg, mux;
-
-	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
-		       &lp_apm_clk);
-	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK;
-	reg |= mux << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
+	while (__raw_readl(MXC_CCM_CDHIPR) &
+			MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
+	}
 
 	return 0;
 }
@@ -620,6 +652,17 @@
 	return ckih2_reference;
 }
 
+static unsigned long clk_emi_slow_get_rate(struct clk *clk)
+{
+	u32 reg, div;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
+	       MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
+
+	return clk_get_rate(clk->parent) / div;
+}
+
 /* External high frequency clock */
 static struct clk ckih_clk = {
 	.get_rate = get_high_reference_clock_rate,
@@ -715,18 +758,6 @@
 	.set_parent = _clk_ipg_per_set_parent,
 };
 
-static struct clk uart_root_clk = {
-	.parent = &pll2_sw_clk,
-	.get_rate = clk_uart_get_rate,
-	.set_parent = _clk_uart_set_parent,
-};
-
-static struct clk usboh3_clk = {
-	.parent = &pll2_sw_clk,
-	.get_rate = clk_usboh3_get_rate,
-	.set_parent = _clk_usboh3_set_parent,
-};
-
 static struct clk ahb_max_clk = {
 	.parent = &ahb_clk,
 	.enable_reg = MXC_CCM_CCGR0,
@@ -762,45 +793,183 @@
 	.id = 0,
 };
 
-#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)	\
+static struct clk emi_slow_clk = {
+	.parent = &pll2_sw_clk,
+	.enable_reg = MXC_CCM_CCGR5,
+	.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable_inwait,
+	.get_rate = clk_emi_slow_get_rate,
+};
+
+#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)	\
 	static struct clk name = {			\
 		.id		= i,			\
 		.enable_reg	= er,			\
 		.enable_shift	= es,			\
-		.get_rate	= gr,			\
-		.set_rate	= sr,			\
+		.get_rate	= pfx##_get_rate,	\
+		.set_rate	= pfx##_set_rate,	\
+		.round_rate	= pfx##_round_rate,	\
+		.set_parent	= pfx##_set_parent,	\
 		.enable		= _clk_ccgr_enable,	\
 		.disable	= _clk_ccgr_disable,	\
 		.parent		= p,			\
 		.secondary	= s,			\
 	}
 
-/* DEFINE_CLOCK(name, id, enable_reg, enable_shift,
-   get_rate, set_rate, parent, secondary); */
+#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s)	\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.get_rate	= pfx##_get_rate,	\
+		.set_rate	= pfx##_set_rate,	\
+		.set_parent	= pfx##_set_parent,	\
+		.enable		= _clk_max_enable,	\
+		.disable	= _clk_max_disable,	\
+		.parent		= p,			\
+		.secondary	= s,			\
+	}
+
+#define CLK_GET_RATE(name, nr, bitsname)				\
+static unsigned long clk_##name##_get_rate(struct clk *clk)		\
+{									\
+	u32 reg, pred, podf;						\
+									\
+	reg = __raw_readl(MXC_CCM_CSCDR##nr);				\
+	pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK)	\
+		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
+	podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK)	\
+		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
+									\
+	return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),		\
+			(pred + 1) * (podf + 1));			\
+}
+
+#define CLK_SET_PARENT(name, nr, bitsname)				\
+static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
+{									\
+	u32 reg, mux;							\
+									\
+	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,		\
+			&pll3_sw_clk, &lp_apm_clk);			\
+	reg = __raw_readl(MXC_CCM_CSCMR##nr) &				\
+		~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;		\
+	reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;	\
+	__raw_writel(reg, MXC_CCM_CSCMR##nr);				\
+									\
+	return 0;							\
+}
+
+#define CLK_SET_RATE(name, nr, bitsname)				\
+static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)	\
+{									\
+	u32 reg, div, parent_rate;					\
+	u32 pre = 0, post = 0;						\
+									\
+	parent_rate = clk_get_rate(clk->parent);			\
+	div = parent_rate / rate;					\
+									\
+	if ((parent_rate / div) != rate)				\
+		return -EINVAL;						\
+									\
+	__calc_pre_post_dividers(div, &pre, &post,			\
+		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >>	\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1,	\
+		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >>	\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
+									\
+	/* Set sdhc1 clock divider */					\
+	reg = __raw_readl(MXC_CCM_CSCDR##nr) &				\
+		~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK	\
+		| MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK);	\
+	reg |= (post - 1) <<						\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
+	reg |= (pre - 1) <<						\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
+	__raw_writel(reg, MXC_CCM_CSCDR##nr);				\
+									\
+	return 0;							\
+}
+
+/* UART */
+CLK_GET_RATE(uart, 1, UART)
+CLK_SET_PARENT(uart, 1, UART)
+
+static struct clk uart_root_clk = {
+	.parent = &pll2_sw_clk,
+	.get_rate = clk_uart_get_rate,
+	.set_parent = clk_uart_set_parent,
+};
+
+/* USBOH3 */
+CLK_GET_RATE(usboh3, 1, USBOH3)
+CLK_SET_PARENT(usboh3, 1, USBOH3)
+
+static struct clk usboh3_clk = {
+	.parent = &pll2_sw_clk,
+	.get_rate = clk_usboh3_get_rate,
+	.set_parent = clk_usboh3_set_parent,
+};
+
+/* eCSPI */
+CLK_GET_RATE(ecspi, 2, CSPI)
+CLK_SET_PARENT(ecspi, 1, CSPI)
+
+static struct clk ecspi_main_clk = {
+	.parent = &pll3_sw_clk,
+	.get_rate = clk_ecspi_get_rate,
+	.set_parent = clk_ecspi_set_parent,
+};
+
+/* eSDHC */
+CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+
+CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+
+#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)		\
+	static struct clk name = {					\
+		.id		= i,					\
+		.enable_reg	= er,					\
+		.enable_shift	= es,					\
+		.get_rate	= gr,					\
+		.set_rate	= sr,					\
+		.enable		= e,					\
+		.disable	= d,					\
+		.parent		= p,					\
+		.secondary	= s,					\
+	}
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)			\
+	DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
 
 /* Shared peripheral bus arbiter */
 DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
 	NULL,  NULL, &ipg_clk, NULL);
 
 /* UART */
-DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
-	NULL,  NULL, &uart_root_clk, NULL);
-DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
-	NULL,  NULL, &uart_root_clk, NULL);
-DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
-	NULL,  NULL, &uart_root_clk, NULL);
 DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
 	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
 DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
 	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
 DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
 	NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart1_ipg_clk);
+DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart2_ipg_clk);
+DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart3_ipg_clk);
 
 /* GPT */
-DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
-	NULL,  NULL, &ipg_clk, NULL);
 DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
 	NULL,  NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
+	NULL,  NULL, &ipg_clk, &gpt_ipg_clk);
 
 /* I2C */
 DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
@@ -814,6 +983,52 @@
 DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
 	NULL,  NULL, &ipg_clk, NULL);
 
+/* NFC */
+DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
+	clk_nfc, &emi_slow_clk, NULL);
+
+/* SSI */
+DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
+	NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
+DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
+	NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
+
+/* eCSPI */
+DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+		&ipg_clk, &spba_clk);
+DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
+		NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
+DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
+		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+		&ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
+		NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
+
+/* CSPI */
+DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+		NULL, NULL, &ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
+		NULL, NULL, &ipg_clk, &cspi_ipg_clk);
+
+/* SDMA */
+DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
+		NULL, NULL, &ahb_clk, NULL);
+
+/* eSDHC */
+DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+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_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
+	clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
+
 #define _REGISTER_CLOCK(d, n, c) \
        { \
 		.dev_id = d, \
@@ -837,6 +1052,18 @@
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
 	_REGISTER_CLOCK("imx-keypad.0", NULL, kpp_clk)
+	_REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
+	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+	_REGISTER_CLOCK(NULL, "ckih", ckih_clk)
+	_REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
+	_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
+	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+	_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
 };
 
 static void clk_tree_init(void)
@@ -880,6 +1107,14 @@
 	/* set the usboh3_clk parent to pll2_sw_clk */
 	clk_set_parent(&usboh3_clk, &pll2_sw_clk);
 
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+	clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
+
+	/* set SDHC root clock as 166.25MHZ*/
+	clk_set_rate(&esdhc1_clk, 166250000);
+	clk_set_rate(&esdhc2_clk, 166250000);
+
 	/* System timer */
 	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
 		MX51_MXC_INT_GPT);
diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c
index 2d37785..eaacb6e 100644
--- a/arch/arm/mach-mx5/cpu.c
+++ b/arch/arm/mach-mx5/cpu.c
@@ -70,6 +70,25 @@
 }
 EXPORT_SYMBOL(mx51_revision);
 
+#ifdef CONFIG_NEON
+
+/*
+ * All versions of the silicon before Rev. 3 have broken NEON implementations.
+ * Dependent on link order - so the assumption is that vfp_init is called
+ * before us.
+ */
+static int __init mx51_neon_fixup(void)
+{
+	if (mx51_revision() < MX51_CHIP_REV_3_0 && (elf_hwcap & HWCAP_NEON)) {
+		elf_hwcap &= ~HWCAP_NEON;
+		pr_info("Turning off NEON support, detected broken NEON implementation\n");
+	}
+	return 0;
+}
+
+late_initcall(mx51_neon_fixup);
+#endif
+
 static int __init post_cpu_init(void)
 {
 	unsigned int reg;
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
new file mode 100644
index 0000000..5cc910e
--- /dev/null
+++ b/arch/arm/mach-mx5/devices-imx51.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+#include <mach/mx51.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_fec_data imx51_fec_data __initconst;
+#define imx51_add_fec(pdata)	\
+	imx_add_fec(&imx51_fec_data, pdata)
+
+extern const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst;
+#define imx51_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
+
+extern const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst;
+#define imx51_add_imx_ssi(id, pdata)	\
+	imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst;
+#define imx51_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
+
+extern const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst;
+#define imx51_add_mxc_nand(pdata)	\
+	imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
+
+extern const struct imx_spi_imx_data imx51_cspi_data __initconst;
+#define imx51_add_cspi(pdata)	\
+	imx_add_spi_imx(&imx51_cspi_data, pdata)
+
+extern const struct imx_spi_imx_data imx51_ecspi_data[] __initconst;
+#define imx51_add_ecspi(id, pdata)	\
+	imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
+
+extern const struct imx_esdhc_imx_data imx51_esdhc_data[] __initconst;
+#define imx51_add_esdhc(id, pdata)	\
+	imx_add_esdhc(&imx51_esdhc_data[id], pdata)
diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
index 1920ff4..4c7be87 100644
--- a/arch/arm/mach-mx5/devices.c
+++ b/arch/arm/mach-mx5/devices.c
@@ -17,120 +17,6 @@
 #include <mach/imx-uart.h>
 #include <mach/irqs.h>
 
-static struct resource uart0[] = {
-	{
-		.start = MX51_UART1_BASE_ADDR,
-		.end = MX51_UART1_BASE_ADDR + 0xfff,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX51_MXC_INT_UART1,
-		.end = MX51_MXC_INT_UART1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_uart_device0 = {
-	.name = "imx-uart",
-	.id = 0,
-	.resource = uart0,
-	.num_resources = ARRAY_SIZE(uart0),
-};
-
-static struct resource uart1[] = {
-	{
-		.start = MX51_UART2_BASE_ADDR,
-		.end = MX51_UART2_BASE_ADDR + 0xfff,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX51_MXC_INT_UART2,
-		.end = MX51_MXC_INT_UART2,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_uart_device1 = {
-	.name = "imx-uart",
-	.id = 1,
-	.resource = uart1,
-	.num_resources = ARRAY_SIZE(uart1),
-};
-
-static struct resource uart2[] = {
-	{
-		.start = MX51_UART3_BASE_ADDR,
-		.end = MX51_UART3_BASE_ADDR + 0xfff,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX51_MXC_INT_UART3,
-		.end = MX51_MXC_INT_UART3,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_uart_device2 = {
-	.name = "imx-uart",
-	.id = 2,
-	.resource = uart2,
-	.num_resources = ARRAY_SIZE(uart2),
-};
-
-static struct resource mxc_fec_resources[] = {
-	{
-		.start	= MX51_MXC_FEC_BASE_ADDR,
-		.end	= MX51_MXC_FEC_BASE_ADDR + 0xfff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= MX51_MXC_INT_FEC,
-		.end	= MX51_MXC_INT_FEC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_fec_device = {
-	.name = "fec",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_fec_resources),
-	.resource = mxc_fec_resources,
-};
-
-static struct resource mxc_i2c0_resources[] = {
-	{
-		.start = MX51_I2C1_BASE_ADDR,
-		.end = MX51_I2C1_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX51_MXC_INT_I2C1,
-		.end = MX51_MXC_INT_I2C1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_i2c_device0 = {
-	.name = "imx-i2c",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_i2c0_resources),
-	.resource = mxc_i2c0_resources,
-};
-
-static struct resource mxc_i2c1_resources[] = {
-	{
-		.start = MX51_I2C2_BASE_ADDR,
-		.end = MX51_I2C2_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MX51_MXC_INT_I2C2,
-		.end = MX51_MXC_INT_I2C2,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_i2c_device1 = {
-	.name = "imx-i2c",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(mxc_i2c1_resources),
-	.resource = mxc_i2c1_resources,
-};
-
 static struct resource mxc_hsi2c_resources[] = {
 	{
 		.start = MX51_HSI2C_DMA_BASE_ADDR,
diff --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h
index e509cfa..af1d07c 100644
--- a/arch/arm/mach-mx5/devices.h
+++ b/arch/arm/mach-mx5/devices.h
@@ -1,12 +1,6 @@
-extern struct platform_device mxc_uart_device0;
-extern struct platform_device mxc_uart_device1;
-extern struct platform_device mxc_uart_device2;
-extern struct platform_device mxc_fec_device;
 extern struct platform_device mxc_usbdr_host_device;
 extern struct platform_device mxc_usbh1_device;
 extern struct platform_device mxc_usbdr_udc_device;
 extern struct platform_device mxc_wdt;
-extern struct platform_device mxc_i2c_device0;
-extern struct platform_device mxc_i2c_device1;
 extern struct platform_device mxc_hsi2c_device;
 extern struct platform_device mxc_keypad_device;
diff --git a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
index ffa93d1..a2e6e8c 100644
--- a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
@@ -30,6 +30,7 @@
 
 #include <asm/mach/arch.h>
 
+#include "devices-imx51.h"
 #include "devices.h"
 
 #define MBIMX51_TSC2007_GPIO	(2*32 + 30)
@@ -112,9 +113,25 @@
 	MX51_PAD_KEY_COL1__KEY_COL1,
 	MX51_PAD_KEY_COL2__KEY_COL2,
 	MX51_PAD_KEY_COL3__KEY_COL3,
+
+	/* 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,
 };
 
-static struct imxuart_platform_data uart_pdata = {
+static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
@@ -158,9 +175,11 @@
 
 static struct i2c_board_info mbimx51_i2c_devices[] = {
 	{
-		I2C_BOARD_INFO("tsc2007", 0x48),
+		I2C_BOARD_INFO("tsc2007", 0x49),
 		.irq  = MBIMX51_TSC2007_IRQ,
 		.platform_data = &tsc2007_data,
+	}, {
+		I2C_BOARD_INFO("tlv320aic23", 0x1a),
 	},
 };
 
@@ -172,8 +191,8 @@
 	mxc_iomux_v3_setup_multiple_pads(mbimx51_pads,
 					ARRAY_SIZE(mbimx51_pads));
 
-	mxc_register_device(&mxc_uart_device1, NULL);
-	mxc_register_device(&mxc_uart_device2, &uart_pdata);
+	imx51_add_imx_uart(1, NULL);
+	imx51_add_imx_uart(2, &uart_pdata);
 
 	gpio_request(MBIMX51_LED0, "LED0");
 	gpio_direction_output(MBIMX51_LED0, 1);
@@ -197,4 +216,7 @@
 	set_irq_type(MBIMX51_TSC2007_IRQ, IRQF_TRIGGER_FALLING);
 	i2c_register_board_info(1, mbimx51_i2c_devices,
 				ARRAY_SIZE(mbimx51_i2c_devices));
+
+	imx51_add_esdhc(0, NULL);
+	imx51_add_esdhc(1, NULL);
 }
diff --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
new file mode 100644
index 0000000..2b48f51
--- /dev/null
+++ b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2010 Eric Benard - eric@eukrea.com
+ *
+ * Based on pcm970-baseboard.c which is :
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx51.h>
+#include <mach/audmux.h>
+
+#include "devices-imx51.h"
+#include "devices.h"
+
+#define MBIMXSD_GPIO_3_31 IOMUX_PAD(0x554, 0x16C, 3, 0x0, 0, \
+				MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
+
+static struct pad_desc eukrea_mbimxsd_pads[] = {
+	/* LED */
+	MX51_PAD_NANDF_D10__GPIO_3_30,
+	/* SWITCH */
+	MBIMXSD_GPIO_3_31,
+	/* UART2 */
+	MX51_PAD_UART2_RXD__UART2_RXD,
+	MX51_PAD_UART2_TXD__UART2_TXD,
+	/* UART 3 */
+	MX51_PAD_UART3_RXD__UART3_RXD,
+	MX51_PAD_UART3_TXD__UART3_TXD,
+	MX51_PAD_KEY_COL4__UART3_RTS,
+	MX51_PAD_KEY_COL5__UART3_CTS,
+	/* SD */
+	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,
+};
+
+#define GPIO_LED1	(2 * 32 + 30)
+#define GPIO_SWITCH1	(2 * 32 + 31)
+
+static struct gpio_led eukrea_mbimxsd_leds[] = {
+	{
+		.name			= "led1",
+		.default_trigger	= "heartbeat",
+		.active_low		= 1,
+		.gpio			= GPIO_LED1,
+	},
+};
+
+static struct gpio_led_platform_data eukrea_mbimxsd_led_info = {
+	.leds		= eukrea_mbimxsd_leds,
+	.num_leds	= ARRAY_SIZE(eukrea_mbimxsd_leds),
+};
+
+static struct platform_device eukrea_mbimxsd_leds_gpio = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &eukrea_mbimxsd_led_info,
+	},
+};
+
+static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
+	{
+		.gpio		= GPIO_SWITCH1,
+		.code		= BTN_0,
+		.desc		= "BP1",
+		.active_low	= 1,
+		.wakeup		= 1,
+	},
+};
+
+static struct gpio_keys_platform_data eukrea_mbimxsd_button_data = {
+	.buttons	= eukrea_mbimxsd_gpio_buttons,
+	.nbuttons	= ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
+};
+
+static struct platform_device eukrea_mbimxsd_button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &eukrea_mbimxsd_button_data,
+	}
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&eukrea_mbimxsd_leds_gpio,
+	&eukrea_mbimxsd_button_device,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("tlv320aic23", 0x1a),
+	},
+};
+
+/*
+ * system init for baseboard usage. Will be called by cpuimx51sd init.
+ *
+ * Add platform devices present on this baseboard and init
+ * them from CPU side as far as required to use them later on
+ */
+void __init eukrea_mbimxsd51_baseboard_init(void)
+{
+	if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
+			ARRAY_SIZE(eukrea_mbimxsd_pads)))
+		printk(KERN_ERR "error setting mbimxsd pads !\n");
+
+	imx51_add_imx_uart(1, NULL);
+	imx51_add_imx_uart(2, &uart_pdata);
+
+	imx51_add_esdhc(0, NULL);
+
+	gpio_request(GPIO_LED1, "LED1");
+	gpio_direction_output(GPIO_LED1, 1);
+	gpio_free(GPIO_LED1);
+
+	gpio_request(GPIO_SWITCH1, "SWITCH1");
+	gpio_direction_input(GPIO_SWITCH1);
+	gpio_free(GPIO_SWITCH1);
+
+	i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
+				ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
+
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
diff --git a/arch/arm/mach-mxc91231/magx-zn5.c b/arch/arm/mach-mxc91231/magx-zn5.c
index 69816ba..395d83b 100644
--- a/arch/arm/mach-mxc91231/magx-zn5.c
+++ b/arch/arm/mach-mxc91231/magx-zn5.c
@@ -53,8 +53,6 @@
 };
 
 MACHINE_START(MAGX_ZN5, "Motorola Zn5")
-	.phys_io	= MXC91231_AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((MXC91231_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params	= MXC91231_PHYS_OFFSET + 0x100,
 	.map_io		= mxc91231_map_io,
 	.init_irq	= mxc91231_init_irq,
diff --git a/arch/arm/mach-netx/include/mach/debug-macro.S b/arch/arm/mach-netx/include/mach/debug-macro.S
index e96339e..56a9152 100644
--- a/arch/arm/mach-netx/include/mach/debug-macro.S
+++ b/arch/arm/mach-netx/include/mach/debug-macro.S
@@ -13,12 +13,10 @@
 
 #include "hardware.h"
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x00100000		@ physical
-		movne	\rx, #io_p2v(0x00100000)	@ virtual
-		orr	\rx, \rx, #0x00000a00
+		.macro	addruart, rp, rv
+		mov	\rp, #0x00000a00
+		orr	\rv, \rp, #io_p2v(0x00100000)	@ virtual
+		orr	\rp, \rp, #0x00100000		@ physical
 		.endm
 
 		.macro	senduart,rd,rx
diff --git a/arch/arm/mach-netx/include/mach/vmalloc.h b/arch/arm/mach-netx/include/mach/vmalloc.h
index 25d5cc6..7cca357 100644
--- a/arch/arm/mach-netx/include/mach/vmalloc.h
+++ b/arch/arm/mach-netx/include/mach/vmalloc.h
@@ -16,4 +16,4 @@
  * 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       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c
index c9b174b..ca8b203 100644
--- a/arch/arm/mach-netx/nxdb500.c
+++ b/arch/arm/mach-netx/nxdb500.c
@@ -200,8 +200,6 @@
 }
 
 MACHINE_START(NXDB500, "Hilscher nxdb500")
-	.phys_io	= 0x00100000,
-	.io_pg_offst	= (io_p2v(0x00100000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c
index 15b54c6..d775cbe 100644
--- a/arch/arm/mach-netx/nxdkn.c
+++ b/arch/arm/mach-netx/nxdkn.c
@@ -93,8 +93,6 @@
 }
 
 MACHINE_START(NXDKN, "Hilscher nxdkn")
-	.phys_io	= 0x00100000,
-	.io_pg_offst	= (io_p2v(0x00100000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c
index 1061c01..de369cd 100644
--- a/arch/arm/mach-netx/nxeb500hmi.c
+++ b/arch/arm/mach-netx/nxeb500hmi.c
@@ -177,8 +177,6 @@
 }
 
 MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
-	.phys_io	= 0x00100000,
-	.io_pg_offst	= (io_p2v(0x00100000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index 841d459..1399303 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -276,8 +276,6 @@
 
 MACHINE_START(NOMADIK, "NHK8815")
 	/* Maintainer: ST MicroElectronics */
-	.phys_io	= NOMADIK_UART0_BASE,
-	.io_pg_offst	= (IO_ADDRESS(NOMADIK_UART0_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x100,
 	.map_io		= cpu8815_map_io,
 	.init_irq	= cpu8815_init_irq,
diff --git a/arch/arm/mach-nomadik/include/mach/debug-macro.S b/arch/arm/mach-nomadik/include/mach/debug-macro.S
index 4f92acf..e7151b4 100644
--- a/arch/arm/mach-nomadik/include/mach/debug-macro.S
+++ b/arch/arm/mach-nomadik/include/mach/debug-macro.S
@@ -10,13 +10,11 @@
  *
 */
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x10000000	@ physical base address
-		movne	\rx, #0xf0000000	@ virtual base
-		add	\rx, \rx, #0x00100000
-		add	\rx, \rx, #0x000fb000
+		.macro	addruart, rp, rv
+		mov	\rp, #0x00100000
+		add	\rp, \rp, #0x000fb000
+		add	\rv, \rp, #0xf0000000	@ virtual base
+		add	\rp, \rp, #0x10000000	@ physical base address
 		.endm
 
 #include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-ns9xxx/include/mach/debug-macro.S b/arch/arm/mach-ns9xxx/include/mach/debug-macro.S
index 5c934bd..5a2acbd 100644
--- a/arch/arm/mach-ns9xxx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ns9xxx/include/mach/debug-macro.S
@@ -12,11 +12,9 @@
 
 #include <mach/regs-board-a9m9750dev.h>
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1
-		ldreq	\rx, =NS9XXX_CSxSTAT_PHYS(0)
-		ldrne	\rx, =io_p2v(NS9XXX_CSxSTAT_PHYS(0))
+		.macro	addruart, rp, rv
+		ldr	\rp, =NS9XXX_CSxSTAT_PHYS(0)
+		ldr	\rv, =io_p2v(NS9XXX_CSxSTAT_PHYS(0))
 		.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-nuc93x/mach-nuc932evb.c b/arch/arm/mach-nuc93x/mach-nuc932evb.c
index 9f79266..d702570 100644
--- a/arch/arm/mach-nuc93x/mach-nuc932evb.c
+++ b/arch/arm/mach-nuc93x/mach-nuc932evb.c
@@ -35,8 +35,6 @@
 
 MACHINE_START(NUC932EVB, "NUC932EVB")
 	/* Maintainer: Wan ZongShun */
-	.phys_io	= NUC93X_PA_UART,
-	.io_pg_offst	= (((u32)NUC93X_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= 0,
 	.map_io		= nuc932evb_map_io,
 	.init_irq	= nuc93x_init_irq,
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 41992ab..73c8639 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -297,8 +297,6 @@
 
 MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
 	/* Maintainer: Jonathan McDowell <noodles@earth.li> */
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= ams_delta_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 180ce79..149fdd3 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -386,8 +386,6 @@
 
 MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
 /* Maintainer: Brian Swetland <swetland@google.com> */
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= omap_fsample_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 93b9ab8..23f4ab9 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -94,8 +94,6 @@
 
 MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
 	/* Maintainer: Tony Lindgren <tony@atomide.com> */
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= omap_generic_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index d2cda58..197adb4 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -458,8 +458,6 @@
 
 MACHINE_START(OMAP_H2, "TI-H2")
 	/* Maintainer: Imre Deak <imre.deak@nokia.com> */
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= h2_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index c2ef4ff..9126e3e 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -446,8 +446,6 @@
 
 MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
 	/* Maintainer: Texas Instruments, Inc. */
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= h3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index 311899f..86afb29 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -300,8 +300,6 @@
 MACHINE_START(HERALD, "HTC Herald")
 	/* Maintainer: Cory Maccarrone <darkstar6262@gmail.com> */
 	/* Maintainer: wing-linux.sourceforge.net */
-	.phys_io        = 0xfff00000,
-	.io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params    = 0x10000100,
 	.map_io         = htcherald_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 3daf87a..dc2b86f 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -459,8 +459,6 @@
 
 MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
 	/* Maintainer: MontaVista Software, Inc. */
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= innovator_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 51a4539..aa8375b 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -262,8 +262,6 @@
 }
 
 MACHINE_START(NOKIA770, "Nokia 770")
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= omap_nokia770_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 679740c..e9dd791 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -580,8 +580,6 @@
 
 MACHINE_START(OMAP_OSK, "TI-OSK")
 	/* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= osk_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 782bb25..f32738b 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -285,8 +285,6 @@
 }
 
 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= omap_palmte_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index 0b35ef5..ed1400a 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -317,8 +317,6 @@
 }
 
 MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= omap_palmtt_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index 6636290..d7a245c 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -338,8 +338,6 @@
 }
 
 MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= omap_palmz71_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 34ab354..a8d16a2 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -347,8 +347,6 @@
 
 MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
 	/* Maintainer: Kevin Hilman <kjh@hilman.org> */
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= omap_perseus2_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 2eb148b..d25f59e 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -419,8 +419,6 @@
 }
 
 MACHINE_START(SX1, "OMAP310 based Siemens SX1")
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= omap_sx1_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 6b3cf14..f5992c2 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -283,8 +283,6 @@
 
 MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
 	/* Maintainer: Ladislav Michl <michl@2n.cz> */
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.map_io		= voiceblue_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap1/include/mach/debug-macro.S b/arch/arm/mach-omap1/include/mach/debug-macro.S
index 671408e..6a0fa04 100644
--- a/arch/arm/mach-omap1/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap1/include/mach/debug-macro.S
@@ -28,56 +28,58 @@
 		 * the desired UART phys and virt addresses temporarily into
 		 * the omap_uart_phys and omap_uart_virt above.
 		 */
-		.macro	addruart, rx, tmp
+		.macro	addruart, rp, rv
 
 		/* Use omap_uart_phys/virt if already configured */
-9:		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		ldreq	\rx, =__virt_to_phys(omap_uart_phys)	@ physical base address
-		ldrne	\rx, =omap_uart_virt	@ virtual base
-		ldr	\rx, [\rx, #0]
-		cmp	\rx, #0			@ is port configured?
+9:		mrc	p15, 0, \rp, c1, c0
+		tst	\rp, #1			@ MMU enabled?
+		ldreq	\rp, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldrne	\rp, =omap_uart_phys	@ MMU enabled
+		add	\rv, \rp, #4		@ omap_uart_virt
+		ldr	\rp, [\rp, #0]
+		ldr	\rv, [\rv, #0]
+		cmp	\rp, #0			@ is port configured?
+		cmpne	\rv, #0
 		bne	99f			@ already configured
 
 		/* Check the debug UART configuration set in uncompress.h */
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		ldreq	\rx, =OMAP_UART_INFO
-		ldrne	\rx, =__phys_to_virt(OMAP_UART_INFO)
-		ldr	\rx, [\rx, #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
+		ldr	\rp, [\rp, #0]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
-10:		cmp	\rx, #0			@ no port configured?
+10:		cmp	\rp, #0			@ no port configured?
 		beq	11f			@ if none, try to use UART1
-		cmp	\rx, #OMAP1UART1
+		cmp	\rp, #OMAP1UART1
 		beq	11f			@ configure OMAP1UART1
-		cmp	\rx, #OMAP1UART2
+		cmp	\rp, #OMAP1UART2
 		beq	12f			@ configure OMAP1UART2
-		cmp	\rx, #OMAP1UART3
+		cmp	\rp, #OMAP1UART3
 		beq	13f			@ configure OMAP2UART3
 
 		/* Configure the UART offset from the phys/virt base */
-11:		mov	\rx, #0x00fb0000	@ OMAP1UART1
+11:		mov	\rp, #0x00fb0000	@ OMAP1UART1
 		b	98f
-12:		mov	\rx, #0x00fb0000	@ OMAP1UART1
-		orr	\rx, \rx, #0x00000800	@ OMAP1UART2
+12:		mov	\rp, #0x00fb0000	@ OMAP1UART1
+		orr	\rp, \rp, #0x00000800	@ OMAP1UART2
 		b	98f
-13:		mov	\rx, #0x00fb0000	@ OMAP1UART1
-		orr	\rx, \rx, #0x00000800	@ OMAP1UART2
-		orr	\rx, \rx, #0x00009000	@ OMAP1UART3
+13:		mov	\rp, #0x00fb0000	@ OMAP1UART1
+		orr	\rp, \rp, #0x00000800	@ OMAP1UART2
+		orr	\rp, \rp, #0x00009000	@ OMAP1UART3
 
 		/* Store both phys and virt address for the uart */
-98:		add	\rx, \rx, #0xff000000	@ phys base
-		mrc	p15, 0, \tmp, c1, c0
-		tst	\tmp, #1		@ MMU enabled?
-		ldreq	\tmp, =__virt_to_phys(omap_uart_phys)
-		ldrne	\tmp, =omap_uart_phys
-		str	\rx, [\tmp, #0]
-		sub	\rx, \rx, #0xff000000	@ phys base
-		add	\rx, \rx, #0xfe000000	@ virt base
-		ldreq	\tmp, =__virt_to_phys(omap_uart_virt)
-		ldrne	\tmp, =omap_uart_virt
-		str	\rx, [\tmp, #0]
+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
+		ldrne	\rv, =omap_uart_phys	@ MMU enabled
+		str	\rp, [\rv, #0]
+		sub	\rp, \rp, #0xff000000	@ phys base
+		add	\rp, \rp, #0xfe000000	@ virt base
+		add	\rv, \rv, #4		@ omap_uart_lsr
+		str	\rp, [\rv, #0]
 		b	9b
 99:
 		.endm
diff --git a/arch/arm/mach-omap1/include/mach/vmalloc.h b/arch/arm/mach-omap1/include/mach/vmalloc.h
index 1b2af14..b001f67 100644
--- a/arch/arm/mach-omap1/include/mach/vmalloc.h
+++ b/arch/arm/mach-omap1/include/mach/vmalloc.h
@@ -17,4 +17,4 @@
  * 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	(PAGE_OFFSET + 0x18000000)
+#define VMALLOC_END	0xd8000000
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 8538e41..b857ce4 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -253,8 +253,6 @@
 
 MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
 	/* Maintainer: Syed Khasim - Texas Instruments Inc */
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap_2430sdp_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 67b95b5f..a5b095c 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -817,8 +817,6 @@
 
 MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
 	/* Maintainer: Syed Khasim - Texas Instruments Inc */
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index b359c3f..fd27ac0 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -217,8 +217,6 @@
 }
 
 MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 9447644..0b6a65f 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -458,8 +458,6 @@
 
 MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
 	/* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap_4430sdp_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 4d0f585..d547036 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -375,6 +375,31 @@
 	omap_gpio_init();
 }
 
+static struct omap_musb_board_data musb_board_data = {
+	.interface_type         = MUSB_INTERFACE_ULPI,
+	.mode                   = MUSB_OTG,
+	.power                  = 500,
+};
+
+static __init void am3517_evm_musb_init(void)
+{
+	u32 devconf2;
+
+	/*
+	 * Set up USB clock/mode in the DEVCONF2 register.
+	 */
+	devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+	/* USB2.0 PHY reference clock is 13 MHz */
+	devconf2 &= ~(CONF2_REFFREQ | CONF2_OTGMODE | CONF2_PHY_GPIOMODE);
+	devconf2 |=  CONF2_REFFREQ_13MHZ | CONF2_SESENDEN | CONF2_VBDTCTEN
+			| CONF2_DATPOL;
+
+	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+
+	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,
 #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
@@ -393,6 +418,8 @@
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
+	/* USB OTG DRVVBUS offset = 0x212 */
+	OMAP3_MUX(SAD2D_MCAD23, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
 #else
@@ -459,11 +486,12 @@
 				ARRAY_SIZE(am3517evm_i2c1_boardinfo));
 	/*Ethernet*/
 	am3517_evm_ethernet_init(&am3517_evm_emac_pdata);
+
+	/* MUSB */
+	am3517_evm_musb_init();
 }
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xd8000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index c6421a7..68f07f5 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -356,8 +356,6 @@
 
 MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
 	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap_apollon_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index e10bc10..934d938 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -809,8 +809,6 @@
 }
 
 MACHINE_START(CM_T35, "Compulab CM-T35")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xd8000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index a07086d..2205c20 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -800,8 +800,6 @@
 }
 
 MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xd8000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 3482b99..69064b1 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -54,8 +54,6 @@
 
 MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
 	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap_generic_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index e09bd68..cc39fc8 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -376,8 +376,6 @@
 
 MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
 	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap_h4_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 175f043..b62a68b 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -533,8 +533,6 @@
 }
 
 MACHINE_START(IGEP0020, "IGEP v2 board")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 00d9b13..f28fd77 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -442,8 +442,6 @@
 }
 
 MACHINE_START(OMAP_LDP, "OMAP LDP board")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index a3e2b49..3f79668 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -674,8 +674,6 @@
 }
 
 MACHINE_START(NOKIA_N800, "Nokia N800")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= n8x0_map_io,
 	.reserve	= omap_reserve,
@@ -685,8 +683,6 @@
 MACHINE_END
 
 MACHINE_START(NOKIA_N810, "Nokia N810")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= n8x0_map_io,
 	.reserve	= omap_reserve,
@@ -696,8 +692,6 @@
 MACHINE_END
 
 MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= n8x0_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 87969c7..9d9f5b8 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -487,8 +487,6 @@
 
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
 	/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index f76d9c0..8936e4f 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -714,8 +714,6 @@
 
 MACHINE_START(OMAP3EVM, "OMAP3 EVM")
 	/* Maintainer: Syed Mohammed Khasim - Texas Instruments */
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index dd3af2b..41d6f54 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -25,7 +25,7 @@
 #include <linux/spi/ads7846.h>
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
-#include <linux/spi/wl12xx.h>
+#include <linux/wl12xx.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
 #include <linux/leds.h>
@@ -717,8 +717,6 @@
 }
 
 MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index bcd01d2..bc5ac83 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -654,8 +654,6 @@
 
 MACHINE_START(SBC3530, "OMAP3 STALKER")
 	/* Maintainer: Jason Lam -lzg@ema-tech.com */
-	.phys_io		= 0x48000000,
-	.io_pg_offst		= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params		= 0x80000100,
 	.map_io			= omap3_map_io,
 	.init_irq		= omap3_stalker_init_irq,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 663c62d..0e99ce5 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -538,8 +538,6 @@
 
 MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
 	/* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xd8000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index c03d1d5..db69bca 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -294,8 +294,6 @@
 
 MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
 	/* Maintainer: David Anders - Texas Instruments Inc */
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap4_panda_map_io,
 	.init_irq	= omap4_panda_init_irq,
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 4c48436..5e528ca 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -501,8 +501,6 @@
 }
 
 MACHINE_START(OVERO, "Gumstix Overo")
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 9a5eb87..ce28a85 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -14,7 +14,7 @@
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/wl12xx.h>
+#include <linux/wl12xx.h>
 #include <linux/i2c.h>
 #include <linux/i2c/twl.h>
 #include <linux/clk.h>
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index a58e8cb..36f2cf4 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -150,8 +150,6 @@
 
 MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
 	/* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
-	.phys_io	= 0x48000000,
-	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= rx51_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 6b39849..189a6d1 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -16,6 +16,8 @@
 #include <linux/gpio.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/wl12xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -27,6 +29,9 @@
 #include "mux.h"
 #include "hsmmc.h"
 
+#define OMAP_ZOOM_WLAN_PMENA_GPIO	(101)
+#define OMAP_ZOOM_WLAN_IRQ_GPIO		(162)
+
 /* Zoom2 has Qwerty keyboard*/
 static int board_keymap[] = {
 	KEY(0, 0, KEY_E),
@@ -106,6 +111,11 @@
 	.supply		= "vmmc",
 };
 
+static struct regulator_consumer_supply zoom_vmmc3_supply = {
+	.supply		= "vmmc",
+	.dev_name	= "mmci-omap-hs.2",
+};
+
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data zoom_vmmc1 = {
 	.constraints = {
@@ -151,6 +161,38 @@
 	.consumer_supplies      = &zoom_vsim_supply,
 };
 
+static struct regulator_init_data zoom_vmmc3 = {
+	.constraints = {
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies = &zoom_vmmc3_supply,
+};
+
+static struct fixed_voltage_config zoom_vwlan = {
+	.supply_name		= "vwl1271",
+	.microvolts		= 1800000, /* 1.8V */
+	.gpio			= OMAP_ZOOM_WLAN_PMENA_GPIO,
+	.startup_delay		= 70000, /* 70msec */
+	.enable_high		= 1,
+	.enabled_at_boot	= 0,
+	.init_data		= &zoom_vmmc3,
+};
+
+static struct platform_device omap_vwlan_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &zoom_vwlan,
+	},
+};
+
+struct wl12xx_platform_data omap_zoom_wlan_data __initdata = {
+	.irq = OMAP_GPIO_IRQ(OMAP_ZOOM_WLAN_IRQ_GPIO),
+	/* ZOOM ref clock is 26 MHz */
+	.board_ref_clock = 1,
+};
+
 static struct omap2_hsmmc_info mmc[] __initdata = {
 	{
 		.name		= "external",
@@ -168,6 +210,14 @@
 		.nonremovable	= true,
 		.power_saving	= true,
 	},
+	{
+		.name		= "wl1271",
+		.mmc		= 3,
+		.caps		= MMC_CAP_4_BIT_DATA,
+		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
+		.nonremovable	= true,
+	},
 	{}      /* Terminator */
 };
 
@@ -279,7 +329,11 @@
 
 void __init zoom_peripherals_init(void)
 {
+	if (wl12xx_set_platform_data(&omap_zoom_wlan_data))
+		pr_err("error setting wl12xx data\n");
+
 	omap_i2c_init();
+	platform_device_register(&omap_vwlan_device);
 	usb_musb_init(&musb_board_data);
 	enable_board_wakeup_source();
 }
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
index 3ad9ecf..24bbd0d 100644
--- a/arch/arm/mach-omap2/board-zoom2.c
+++ b/arch/arm/mach-omap2/board-zoom2.c
@@ -141,8 +141,6 @@
 }
 
 MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
-	.phys_io	= ZOOM_UART_BASE,
-	.io_pg_offst	= (ZOOM_UART_VIRT >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/board-zoom3.c b/arch/arm/mach-omap2/board-zoom3.c
index 6ca0b83..b2bb3ff 100644
--- a/arch/arm/mach-omap2/board-zoom3.c
+++ b/arch/arm/mach-omap2/board-zoom3.c
@@ -123,8 +123,6 @@
 }
 
 MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
-	.phys_io	= ZOOM_UART_BASE,
-	.io_pg_offst	= (ZOOM_UART_VIRT >> 18) & 0xfffc,
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
diff --git a/arch/arm/mach-omap2/include/mach/debug-macro.S b/arch/arm/mach-omap2/include/mach/debug-macro.S
index 09331bb..6a4d413 100644
--- a/arch/arm/mach-omap2/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap2/include/mach/debug-macro.S
@@ -31,95 +31,94 @@
 		 * the desired UART phys and virt addresses temporarily into
 		 * the omap_uart_phys and omap_uart_virt above.
 		 */
-		.macro	addruart, rx, tmp
+		.macro	addruart, rp, rv
 
 		/* Use omap_uart_phys/virt if already configured */
-10:		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		ldreq	\rx, =__virt_to_phys(omap_uart_phys)	@ physical base address
-		ldrne	\rx, =omap_uart_virt	@ virtual base address
-		ldr	\rx, [\rx, #0]
-		cmp	\rx, #0			@ is port configured?
+10:		mrc	p15, 0, \rp, c1, c0
+		tst	\rp, #1			@ MMU enabled?
+		ldreq	\rp, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldrne	\rp, =omap_uart_phys	@ MMU enabled
+		add	\rv, \rp, #4		@ omap_uart_virt
+		ldr	\rp, [\rp, #0]
+		ldr	\rv, [\rv, #0]
+		cmp	\rp, #0			@ is port configured?
+		cmpne	\rv, #0
 		bne	99f			@ already configured
 
 		/* Check the debug UART configuration set in uncompress.h */
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		ldreq	\rx, =OMAP_UART_INFO
-		ldrne	\rx, =__phys_to_virt(OMAP_UART_INFO)
-		ldr	\rx, [\rx, #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
+		ldr	\rp, [\rp, #0]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
-		cmp	\rx, #0			@ no port configured?
+		cmp	\rp, #0			@ no port configured?
 		beq	21f			@ if none, try to use UART1
-		cmp	\rx, #OMAP2UART1	@ OMAP2/3/4UART1
+		cmp	\rp, #OMAP2UART1	@ OMAP2/3/4UART1
 		beq	21f			@ configure OMAP2/3/4UART1
-		cmp	\rx, #OMAP2UART2	@ OMAP2/3/4UART2
+		cmp	\rp, #OMAP2UART2	@ OMAP2/3/4UART2
 		beq	22f			@ configure OMAP2/3/4UART2
-		cmp	\rx, #OMAP2UART3	@ only on 24xx
+		cmp	\rp, #OMAP2UART3	@ only on 24xx
 		beq	23f			@ configure OMAP2UART3
-		cmp	\rx, #OMAP3UART3	@ only on 34xx
+		cmp	\rp, #OMAP3UART3	@ only on 34xx
 		beq	33f			@ configure OMAP3UART3
-		cmp	\rx, #OMAP4UART3	@ only on 44xx
+		cmp	\rp, #OMAP4UART3	@ only on 44xx
 		beq	43f			@ configure OMAP4UART3
-		cmp	\rx, #OMAP3UART4	@ only on 36xx
+		cmp	\rp, #OMAP3UART4	@ only on 36xx
 		beq	34f			@ configure OMAP3UART4
-		cmp	\rx, #OMAP4UART4	@ only on 44xx
+		cmp	\rp, #OMAP4UART4	@ only on 44xx
 		beq	44f			@ configure OMAP4UART4
-		cmp	\rx, #ZOOM_UART		@ only on zoom2/3
+		cmp	\rp, #ZOOM_UART		@ only on zoom2/3
 		beq	95f			@ configure ZOOM_UART
 
 		/* Configure the UART offset from the phys/virt base */
-21:		mov	\rx, #UART_OFFSET(OMAP2_UART1_BASE)	@ omap2/3/4
+21:		mov	\rp, #UART_OFFSET(OMAP2_UART1_BASE)	@ omap2/3/4
 		b	98f
-22:		mov	\rx, #UART_OFFSET(OMAP2_UART2_BASE)	@ omap2/3/4
+22:		mov	\rp, #UART_OFFSET(OMAP2_UART2_BASE)	@ omap2/3/4
 		b	98f
-23:		mov	\rx, #UART_OFFSET(OMAP2_UART3_BASE)
+23:		mov	\rp, #UART_OFFSET(OMAP2_UART3_BASE)
 		b	98f
-33:		mov	\rx, #UART_OFFSET(OMAP3_UART1_BASE)
-		add	\rx, \rx, #0x00fb0000
-		add	\rx, \rx, #0x00006000		@ OMAP3_UART3_BASE
+33:		mov	\rp, #UART_OFFSET(OMAP3_UART1_BASE)
+		add	\rp, \rp, #0x00fb0000
+		add	\rp, \rp, #0x00006000		@ OMAP3_UART3_BASE
 		b	98f
-34:		mov	\rx, #UART_OFFSET(OMAP3_UART1_BASE)
-		add	\rx, \rx, #0x00fb0000
-		add	\rx, \rx, #0x00028000		@ OMAP3_UART4_BASE
+34:		mov	\rp, #UART_OFFSET(OMAP3_UART1_BASE)
+		add	\rp, \rp, #0x00fb0000
+		add	\rp, \rp, #0x00028000		@ OMAP3_UART4_BASE
 		b	98f
-43:		mov	\rx, #UART_OFFSET(OMAP4_UART3_BASE)
+43:		mov	\rp, #UART_OFFSET(OMAP4_UART3_BASE)
 		b	98f
-44:		mov	\rx, #UART_OFFSET(OMAP4_UART4_BASE)
+44:		mov	\rp, #UART_OFFSET(OMAP4_UART4_BASE)
 		b	98f
-95:		ldr	\rx, =ZOOM_UART_BASE
-		mrc	p15, 0, \tmp, c1, c0
-		tst	\tmp, #1		@ MMU enabled?
-		ldreq	\tmp, =__virt_to_phys(omap_uart_phys)
-		ldrne	\tmp, =omap_uart_phys
-		str	\rx, [\tmp, #0]
-		ldr	\rx, =ZOOM_UART_VIRT
-		ldreq	\tmp, =__virt_to_phys(omap_uart_virt)
-		ldrne	\tmp, =omap_uart_virt
-		str	\rx, [\tmp, #0]
-		mov	\rx, #(UART_LSR << ZOOM_PORT_SHIFT)
-		ldreq	\tmp, =__virt_to_phys(omap_uart_lsr)
-		ldrne	\tmp, =omap_uart_lsr
-		str	\rx, [\tmp, #0]
+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
+		ldrne	\rv, =omap_uart_phys	@ MMU enabled
+		str	\rp, [\rv, #0]
+		ldr	\rp, =ZOOM_UART_VIRT
+		add	\rv, \rv, #4		@ omap_uart_virt
+		str	\rp, [\rv, #0]
+		mov	\rp, #(UART_LSR << ZOOM_PORT_SHIFT)
+		add	\rv, \rv, #4		@ omap_uart_lsr
+		str	\rp, [\rv, #0]
 		b	10b
 
 		/* Store both phys and virt address for the uart */
-98:		add	\rx, \rx, #0x48000000	@ phys base
-		mrc	p15, 0, \tmp, c1, c0
-		tst	\tmp, #1		@ MMU enabled?
-		ldreq	\tmp, =__virt_to_phys(omap_uart_phys)
-		ldrne	\tmp, =omap_uart_phys
-		str	\rx, [\tmp, #0]
-		sub	\rx, \rx, #0x48000000	@ phys base
-		add	\rx, \rx, #0xfa000000	@ virt base
-		ldreq	\tmp, =__virt_to_phys(omap_uart_virt)
-		ldrne	\tmp, =omap_uart_virt
-		str	\rx, [\tmp, #0]
-		mov	\rx, #(UART_LSR << OMAP_PORT_SHIFT)
-		ldreq	\tmp, =__virt_to_phys(omap_uart_lsr)
-		ldrne	\tmp, =omap_uart_lsr
-		str	\rx, [\tmp, #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
+		ldrne	\rv, =omap_uart_phys	@ MMU enabled
+		str	\rp, [\rv, #0]
+		sub	\rp, \rp, #0x48000000	@ phys base
+		add	\rp, \rp, #0xfa000000	@ virt base
+		add	\rv, \rv, #4		@ omap_uart_virt
+		str	\rp, [\rv, #0]
+		mov	\rp, #(UART_LSR << OMAP_PORT_SHIFT)
+		add	\rv, \rv, #4		@ omap_uart_lsr
+		str	\rp, [\rv, #0]
 
 		b	10b
 99:
@@ -131,9 +130,9 @@
 
 		.macro	busyuart,rd,rx
 1001:		mrc	p15, 0, \rd, c1, c0
-		tst	\rd, #1		@ MMU enabled?
-		ldreq	\rd, =__virt_to_phys(omap_uart_lsr)
-		ldrne	\rd, =omap_uart_lsr
+		tst	\rd, #1			@ MMU enabled?
+		ldreq	\rd, =__virt_to_phys(omap_uart_lsr)	@ MMU not enabled
+		ldrne	\rd, =omap_uart_lsr	@ MMU enabled
 		ldr	\rd, [\rd, #0]
 		ldrb	\rd, [\rx, \rd]
 		and	\rd, \rd, #(UART_LSR_TEMT | UART_LSR_THRE)
diff --git a/arch/arm/mach-omap2/include/mach/vmalloc.h b/arch/arm/mach-omap2/include/mach/vmalloc.h
index 9ce9b6e..4da31e9 100644
--- a/arch/arm/mach-omap2/include/mach/vmalloc.h
+++ b/arch/arm/mach-omap2/include/mach/vmalloc.h
@@ -17,4 +17,4 @@
  * 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	  (PAGE_OFFSET + 0x38000000)
+#define VMALLOC_END	  0xf8000000
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 33a5cde..7260558 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -28,6 +28,7 @@
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
+#include <mach/am35xx.h>
 #include <plat/usb.h>
 
 #ifdef CONFIG_USB_MUSB_SOC
@@ -89,6 +90,9 @@
 {
 	if (cpu_is_omap243x()) {
 		musb_resources[0].start = OMAP243X_HS_BASE;
+	} else if (cpu_is_omap3517() || cpu_is_omap3505()) {
+		musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
+		musb_resources[1].start = INT_35XX_USBOTG_IRQ;
 	} else if (cpu_is_omap34xx()) {
 		musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
 	} else if (cpu_is_omap44xx()) {
diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c
index 7130904..b1c451f 100644
--- a/arch/arm/mach-orion5x/d2net-setup.c
+++ b/arch/arm/mach-orion5x/d2net-setup.c
@@ -336,8 +336,6 @@
 
 #ifdef CONFIG_MACH_D2NET
 MACHINE_START(D2NET, "LaCie d2 Network")
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= d2net_init,
 	.map_io		= orion5x_map_io,
@@ -349,8 +347,6 @@
 
 #ifdef CONFIG_MACH_BIGDISK
 MACHINE_START(BIGDISK, "LaCie Big Disk Network")
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= d2net_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
index d318bea..df1083f 100644
--- a/arch/arm/mach-orion5x/db88f5281-setup.c
+++ b/arch/arm/mach-orion5x/db88f5281-setup.c
@@ -358,8 +358,6 @@
 
 MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
 	/* Maintainer: Tzachi Perelstein <tzachi@marvell.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.init_machine	= db88f5281_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index a47100d..3a7bc0e 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -730,8 +730,6 @@
 /* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
 MACHINE_START(DNS323, "D-Link DNS-323")
 	/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= dns323_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/edmini_v2-setup.c b/arch/arm/mach-orion5x/edmini_v2-setup.c
index b24ee0c..ba98459 100644
--- a/arch/arm/mach-orion5x/edmini_v2-setup.c
+++ b/arch/arm/mach-orion5x/edmini_v2-setup.c
@@ -251,8 +251,6 @@
 /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
 MACHINE_START(EDMINI_V2, "LaCie Ethernet Disk mini V2")
 	/* Maintainer: Christopher Moore <moore@free.fr> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= edmini_v2_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/include/mach/debug-macro.S b/arch/arm/mach-orion5x/include/mach/debug-macro.S
index 91e0e39..5e3bf5b 100644
--- a/arch/arm/mach-orion5x/include/mach/debug-macro.S
+++ b/arch/arm/mach-orion5x/include/mach/debug-macro.S
@@ -10,12 +10,11 @@
 
 #include <mach/orion5x.h>
 
-	.macro  addruart, rx, tmp
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1					@ MMU enabled?
-	ldreq	\rx, =ORION5X_REGS_PHYS_BASE
-	ldrne	\rx, =ORION5X_REGS_VIRT_BASE
-	orr	\rx, \rx, #0x00012000
+	.macro  addruart, rp, rv
+	ldr	\rp, =ORION5X_REGS_PHYS_BASE
+	ldr	\rv, =ORION5X_REGS_VIRT_BASE
+	orr	\rp, \rp, #0x00012000
+	orr	\rv, \rv, #0x00012000
 	.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
index dfbb68d..4be9aa0 100644
--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
@@ -379,8 +379,6 @@
 #ifdef CONFIG_MACH_KUROBOX_PRO
 MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
 	/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= kurobox_pro_init,
 	.map_io		= orion5x_map_io,
@@ -393,8 +391,6 @@
 #ifdef CONFIG_MACH_LINKSTATION_PRO
 MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
 	/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= kurobox_pro_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c
index 8e569be..437364b 100644
--- a/arch/arm/mach-orion5x/ls_hgl-setup.c
+++ b/arch/arm/mach-orion5x/ls_hgl-setup.c
@@ -265,8 +265,6 @@
 
 MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL")
 	/* Maintainer: Zhu Qingsen <zhuqs@cn.fujistu.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= ls_hgl_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c
index c704f05..ab9b0cf 100644
--- a/arch/arm/mach-orion5x/lsmini-setup.c
+++ b/arch/arm/mach-orion5x/lsmini-setup.c
@@ -267,8 +267,6 @@
 #ifdef CONFIG_MACH_LINKSTATION_MINI
 MACHINE_START(LINKSTATION_MINI, "Buffalo Linkstation Mini")
 	/* Maintainer: Alexey Kopytko <alexey@kopytko.ru> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= lsmini_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c
index 61c086b..2f0e16c 100644
--- a/arch/arm/mach-orion5x/mss2-setup.c
+++ b/arch/arm/mach-orion5x/mss2-setup.c
@@ -261,8 +261,6 @@
 
 MACHINE_START(MSS2, "Maxtor Shared Storage II")
 	/* Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= mss2_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c
index 97c9ccb..b3d90f2 100644
--- a/arch/arm/mach-orion5x/mv2120-setup.c
+++ b/arch/arm/mach-orion5x/mv2120-setup.c
@@ -229,8 +229,6 @@
 /* Warning: HP uses a wrong mach-type (=526) in their bootloader */
 MACHINE_START(MV2120, "HP Media Vault mv2120")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= mv2120_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c
index 7bd6283..d6665b3 100644
--- a/arch/arm/mach-orion5x/net2big-setup.c
+++ b/arch/arm/mach-orion5x/net2big-setup.c
@@ -419,8 +419,6 @@
 
 /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
 MACHINE_START(NET2BIG, "LaCie 2Big Network")
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= net2big_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
index 9c1ca41..f4c26fd 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
@@ -169,8 +169,6 @@
 
 MACHINE_START(RD88F5181L_FXO, "Marvell Orion-VoIP FXO Reference Design")
 	/* Maintainer: Nicolas Pitre <nico@marvell.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f5181l_fxo_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
index ee1399f..b594290 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
@@ -181,8 +181,6 @@
 
 MACHINE_START(RD88F5181L_GE, "Marvell Orion-VoIP GE Reference Design")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f5181l_ge_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
index a04f9e4..165ed870 100644
--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
@@ -305,8 +305,6 @@
 
 MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
 	/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f5182_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
index 7737cf9..02ff45f 100644
--- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
@@ -123,8 +123,6 @@
 
 MACHINE_START(RD88F6183AP_GE, "Marvell Orion-1-90 AP GE Reference Design")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f6183ap_ge_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c
index 0b101d7d..4403fae 100644
--- a/arch/arm/mach-orion5x/terastation_pro2-setup.c
+++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c
@@ -358,8 +358,6 @@
 
 MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
 	/* Maintainer:  Sylver Bruneau <sylver.bruneau@googlemail.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= tsp2_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
index 9d68905..1e19612 100644
--- a/arch/arm/mach-orion5x/ts209-setup.c
+++ b/arch/arm/mach-orion5x/ts209-setup.c
@@ -322,8 +322,6 @@
 
 MACHINE_START(TS209, "QNAP TS-109/TS-209")
 	/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts209_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c
index d85588a..428af20 100644
--- a/arch/arm/mach-orion5x/ts409-setup.c
+++ b/arch/arm/mach-orion5x/ts409-setup.c
@@ -311,8 +311,6 @@
 
 MACHINE_START(TS409, "QNAP TS-409")
 	/* Maintainer:  Sylver Bruneau <sylver.bruneau@gmail.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts409_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index 696b1a9..16f1bd5 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -550,8 +550,6 @@
 
 MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
 	/* Maintainer: Alexander Clouter <alex@digriz.org.uk> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= ts78xx_init,
 	.map_io		= ts78xx_map_io,
diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c
index 6920821..7994d6e 100644
--- a/arch/arm/mach-orion5x/wnr854t-setup.c
+++ b/arch/arm/mach-orion5x/wnr854t-setup.c
@@ -172,8 +172,6 @@
 
 MACHINE_START(WNR854T, "Netgear WNR854T")
 	/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= wnr854t_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
index f9f222e..a5989b7 100644
--- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c
+++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
@@ -260,8 +260,6 @@
 
 MACHINE_START(WRT350N_V2, "Linksys WRT350N v2")
 	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
-	.phys_io	= ORION5X_REGS_PHYS_BASE,
-	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
 	.boot_params	= 0x00000100,
 	.init_machine	= wrt350n_v2_init,
 	.map_io		= orion5x_map_io,
diff --git a/arch/arm/mach-pnx4008/core.c b/arch/arm/mach-pnx4008/core.c
index 45734bb..63399755 100644
--- a/arch/arm/mach-pnx4008/core.c
+++ b/arch/arm/mach-pnx4008/core.c
@@ -264,8 +264,6 @@
 
 MACHINE_START(PNX4008, "Philips PNX4008")
 	/* Maintainer: MontaVista Software Inc. */
-	.phys_io 		= 0x40090000,
-	.io_pg_offst 		= (0xf4090000 >> 18) & 0xfffc,
 	.boot_params		= 0x80000100,
 	.map_io 		= pnx4008_map_io,
 	.init_irq 		= pnx4008_init_irq,
diff --git a/arch/arm/mach-pnx4008/include/mach/debug-macro.S b/arch/arm/mach-pnx4008/include/mach/debug-macro.S
index 6ca8bd3..931afeb 100644
--- a/arch/arm/mach-pnx4008/include/mach/debug-macro.S
+++ b/arch/arm/mach-pnx4008/include/mach/debug-macro.S
@@ -11,12 +11,10 @@
  *
 */
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		mov	\rx, #0x00090000
-		addeq	\rx, \rx, #0x40000000
-		addne	\rx, \rx, #0xf4000000
+		.macro	addruart, rp, rv
+		mov	\rp, #0x00090000
+		add	\rv, \rp, #0xf4000000	@ virtual
+		add	\rp, \rp, #0x40000000	@ physical
 		.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-pnx4008/include/mach/vmalloc.h b/arch/arm/mach-pnx4008/include/mach/vmalloc.h
index 2ad3983..31b65ee 100644
--- a/arch/arm/mach-pnx4008/include/mach/vmalloc.h
+++ b/arch/arm/mach-pnx4008/include/mach/vmalloc.h
@@ -17,4 +17,4 @@
  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
  * area for the same reason. ;)
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 7aefb90..dd235ec 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -8,19 +8,16 @@
 	bool "Intel DBPXA250 Development Platform (aka Lubbock)"
 	select PXA25x
 	select SA1111
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_MAINSTONE
 	bool "Intel HCDDBBVA0 Development Platform (aka Mainstone)"
 	select PXA27x
 	select HAVE_PWM
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_ZYLONITE
 	bool
 	select PXA3xx
 	select HAVE_PWM
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_ZYLONITE300
 	bool "PXA3xx Development Platform (aka Zylonite) PXA300/310"
@@ -44,6 +41,10 @@
 	select PXA3xx
 	select CPU_PXA930
 
+config MACH_TAVOREVB3
+	bool "PXA95x Development Platform (aka TavorEVB III)"
+	select CPU_PXA950
+
 config MACH_SAAR
 	bool "PXA930 Handheld Platform (aka SAAR)"
 	select PXA3xx
@@ -61,7 +62,6 @@
 	select ISA
 	select I2C_GPIO
 	select HAVE_PWM
-	select PXA_HAVE_BOARD_IRQS
 	select PXA_HAVE_ISA_IRQS
 	select ARCOM_PCMCIA
 
@@ -69,7 +69,6 @@
 	bool "Arcom/Eurotech ZEUS SBC"
 	select PXA27x
 	select ISA
-	select PXA_HAVE_BOARD_IRQS
 	select PXA_HAVE_ISA_IRQS
 	select ARCOM_PCMCIA
 
@@ -77,7 +76,6 @@
 	bool "Balloon 3 board"
 	select PXA27x
 	select IWMMXT
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_CSB726
 	bool "Enable Cogent CSB726 System On a Module"
@@ -140,13 +138,11 @@
 	bool "Intel Mote 2 Platform"
 	select PXA27x
 	select IWMMXT
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_STARGATE2
 	bool "Intel Stargate 2 Platform"
 	select PXA27x
 	select IWMMXT
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_XCEP
 	bool "Iskratel Electronics XCEP"
@@ -206,13 +202,11 @@
 	bool "LogicPD PXA270 Card Engine Development Platform"
 	select PXA27x
 	select HAVE_PWM
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_PCM027
 	bool "Phytec phyCORE-PXA270 CPU module (PCM-027)"
 	select PXA27x
 	select IWMMXT
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_PCM990_BASEBOARD
 	bool "PHYTEC PCM-990 development board"
@@ -247,7 +241,6 @@
 	depends on MACH_COLIBRI
 	select PXA27x
 	select HAVE_PWM
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_COLIBRI300
 	bool "Toradex Colibri PXA300/310"
@@ -274,7 +267,6 @@
 	select PXA27x
 	select IWMMXT
 	select HAVE_PWM
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_H5000
 	bool "HP iPAQ h5000"
@@ -289,7 +281,6 @@
 	select PXA27x
 	select IWMMXT
 	select HAVE_PWM
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_MIOA701
 	bool "Mitac Mio A701 Support"
@@ -307,7 +298,6 @@
 	select PXA27x
 	select IWMMXT
 	select HAVE_PWM
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_EZX_A780
 	bool "Motorola EZX A780"
@@ -478,7 +468,6 @@
 	depends on PXA_SHARPSL
 	select PXA25x
 	select SHARP_LOCOMO
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_CORGI
 	bool "Enable Sharp SL-C700 (Corgi) Support"
@@ -523,7 +512,6 @@
 	bool "Enable Sharp SL-6000x (Tosa) Support"
 	depends on PXA_SHARPSL
 	select PXA25x
-	select PXA_HAVE_BOARD_IRQS
 
 config TOSA_BT
 	tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
@@ -552,7 +540,6 @@
 config ARCH_PXA_ESERIES
 	bool "PXA based Toshiba e-series PDAs"
 	select PXA25x
-	select PXA_HAVE_BOARD_IRQS
 
 config MACH_E330
 	bool "Toshiba e330"
@@ -606,7 +593,6 @@
 	bool "Zipit Z2 Handheld"
 	select PXA27x
 	select HAVE_PWM
-	select PXA_HAVE_BOARD_IRQS
 
 endmenu
 
@@ -643,6 +629,7 @@
 config CPU_PXA310
 	bool
 	select CPU_PXA300
+	select PXA310_ULPI if USB_ULPI
 	help
 	  PXA310 (codename Monahans-LV)
 
@@ -692,10 +679,10 @@
 	select HWMON
 	select SENSORS_MAX1111
 
-config PXA_HAVE_BOARD_IRQS
+config PXA_HAVE_ISA_IRQS
 	bool
 
-config PXA_HAVE_ISA_IRQS
+config PXA310_ULPI
 	bool
 
 endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 85c7fb3..e2f89c2 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -18,7 +18,7 @@
 # SoC-specific code
 obj-$(CONFIG_PXA25x)		+= mfp-pxa2xx.o pxa2xx.o pxa25x.o
 obj-$(CONFIG_PXA27x)		+= mfp-pxa2xx.o pxa2xx.o pxa27x.o
-obj-$(CONFIG_PXA3xx)		+= mfp-pxa3xx.o pxa3xx.o smemc.o
+obj-$(CONFIG_PXA3xx)		+= mfp-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
 obj-$(CONFIG_CPU_PXA300)	+= pxa300.o
 obj-$(CONFIG_CPU_PXA320)	+= pxa320.o
 obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
@@ -32,6 +32,7 @@
 obj-$(CONFIG_MACH_ZYLONITE320)	+= zylonite.o zylonite_pxa320.o
 obj-$(CONFIG_MACH_LITTLETON)	+= littleton.o
 obj-$(CONFIG_MACH_TAVOREVB)	+= tavorevb.o
+obj-$(CONFIG_MACH_TAVOREVB3)	+= tavorevb3.o
 obj-$(CONFIG_MACH_SAAR)		+= saar.o
 
 # 3rd Party Dev Platforms
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index 9041340..21e18890 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -68,42 +68,6 @@
 
 	/* Reset, configured as GPIO wakeup source */
 	GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
-
-	/* LEDs */
-	GPIO9_GPIO,	/* NAND activity LED */
-	GPIO10_GPIO,	/* Heartbeat LED */
-
-	/* AC97 */
-	GPIO28_AC97_BITCLK,
-	GPIO29_AC97_SDATA_IN_0,
-	GPIO30_AC97_SDATA_OUT,
-	GPIO31_AC97_SYNC,
-	GPIO113_AC97_nRESET,
-	GPIO95_GPIO,
-
-	/* MMC */
-	GPIO32_MMC_CLK,
-	GPIO92_MMC_DAT_0,
-	GPIO109_MMC_DAT_1,
-	GPIO110_MMC_DAT_2,
-	GPIO111_MMC_DAT_3,
-	GPIO112_MMC_CMD,
-
-	/* USB Host */
-	GPIO88_USBH1_PWR,
-	GPIO89_USBH1_PEN,
-
-	/* PC Card */
-	GPIO48_nPOE,
-	GPIO49_nPWE,
-	GPIO50_nPIOR,
-	GPIO51_nPIOW,
-	GPIO85_nPCE_1,
-	GPIO54_nPCE_2,
-	GPIO79_PSKTSEL,
-	GPIO55_nPREG,
-	GPIO56_nPWAIT,
-	GPIO57_nIOIS16,
 };
 
 /******************************************************************************
@@ -132,6 +96,34 @@
 early_param("balloon3_features", parse_balloon3_features);
 
 /******************************************************************************
+ * Compact Flash slot
+ ******************************************************************************/
+#if	defined(CONFIG_PCMCIA_PXA2XX) || defined(CONFIG_PCMCIA_PXA2XX_MODULE)
+static unsigned long balloon3_cf_pin_config[] __initdata = {
+	GPIO48_nPOE,
+	GPIO49_nPWE,
+	GPIO50_nPIOR,
+	GPIO51_nPIOW,
+	GPIO85_nPCE_1,
+	GPIO54_nPCE_2,
+	GPIO79_PSKTSEL,
+	GPIO55_nPREG,
+	GPIO56_nPWAIT,
+	GPIO57_nIOIS16,
+};
+
+static void __init balloon3_cf_init(void)
+{
+	if (!balloon3_has(BALLOON3_FEATURE_CF))
+		return;
+
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_cf_pin_config));
+}
+#else
+static inline void balloon3_cf_init(void) {}
+#endif
+
+/******************************************************************************
  * NOR Flash
  ******************************************************************************/
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
@@ -179,6 +171,15 @@
  ******************************************************************************/
 #if	defined(CONFIG_TOUCHSCREEN_UCB1400) || \
 	defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
+static unsigned long balloon3_ac97_pin_config[] __initdata = {
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+	GPIO113_AC97_nRESET,
+	GPIO95_GPIO,
+};
+
 static struct ucb1400_pdata vpac270_ucb1400_pdata = {
 	.irq		= IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ),
 };
@@ -197,6 +198,7 @@
 	if (!balloon3_has(BALLOON3_FEATURE_AUDIO))
 		return;
 
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_ac97_pin_config));
 	pxa_set_ac97_info(NULL);
 	platform_device_register(&balloon3_ucb1400_device);
 }
@@ -208,6 +210,11 @@
  * Framebuffer
  ******************************************************************************/
 #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
+static unsigned long balloon3_lcd_pin_config[] __initdata = {
+	GPIOxx_LCD_TFT_16BPP,
+	GPIO99_GPIO,
+};
+
 static struct pxafb_mode_info balloon3_lcd_modes[] = {
 	{
 		.pixclock		= 38000,
@@ -242,6 +249,8 @@
 	if (!balloon3_has(BALLOON3_FEATURE_TOPPOLY))
 		return;
 
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_lcd_pin_config));
+
 	ret = gpio_request(BALLOON3_GPIO_RUN_BACKLIGHT, "BKL-ON");
 	if (ret) {
 		pr_err("Requesting BKL-ON GPIO failed!\n");
@@ -271,6 +280,15 @@
  * SD/MMC card controller
  ******************************************************************************/
 #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
+static unsigned long balloon3_mmc_pin_config[] __initdata = {
+	GPIO32_MMC_CLK,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+	GPIO112_MMC_CMD,
+};
+
 static struct pxamci_platform_data balloon3_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
 	.gpio_card_detect	= -1,
@@ -281,6 +299,7 @@
 
 static void __init balloon3_mmc_init(void)
 {
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_mmc_pin_config));
 	pxa_set_mci_info(&balloon3_mci_platform_data);
 }
 #else
@@ -339,6 +358,11 @@
  * USB Host
  ******************************************************************************/
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static unsigned long balloon3_uhc_pin_config[] __initdata = {
+	GPIO88_USBH1_PWR,
+	GPIO89_USBH1_PEN,
+};
+
 static struct pxaohci_platform_data balloon3_ohci_info = {
 	.port_mode	= PMM_PERPORT_MODE,
 	.flags		= ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
@@ -348,6 +372,7 @@
 {
 	if (!balloon3_has(BALLOON3_FEATURE_OHCI))
 		return;
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_uhc_pin_config));
 	pxa_set_ohci_info(&balloon3_ohci_info);
 }
 #else
@@ -358,6 +383,11 @@
  * LEDs
  ******************************************************************************/
 #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static unsigned long balloon3_led_pin_config[] __initdata = {
+	GPIO9_GPIO,	/* NAND activity LED */
+	GPIO10_GPIO,	/* Heartbeat LED */
+};
+
 struct gpio_led balloon3_gpio_leds[] = {
 	{
 		.name			= "balloon3:green:idle",
@@ -436,6 +466,7 @@
 
 static void __init balloon3_leds_init(void)
 {
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_led_pin_config));
 	platform_device_register(&balloon3_leds);
 	platform_device_register(&balloon3_pcf_leds);
 }
@@ -757,6 +788,7 @@
 	balloon3_ts_init();
 	balloon3_udc_init();
 	balloon3_uhc_init();
+	balloon3_cf_init();
 }
 
 static struct map_desc balloon3_io_desc[] __initdata = {
@@ -776,9 +808,8 @@
 
 MACHINE_START(BALLOON3, "Balloon3")
 	/* Maintainer: Nick Bane. */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= balloon3_map_io,
+	.nr_irqs	= BALLOON3_NR_IRQS,
 	.init_irq	= balloon3_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= balloon3_init,
diff --git a/arch/arm/mach-pxa/capc7117.c b/arch/arm/mach-pxa/capc7117.c
index aae5446..4bd7a3c 100644
--- a/arch/arm/mach-pxa/capc7117.c
+++ b/arch/arm/mach-pxa/capc7117.c
@@ -148,9 +148,7 @@
 
 MACHINE_START(CAPC7117,
 	      "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
-	.phys_io = 0x40000000,
 	.boot_params = 0xa0000100,
-	.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io = pxa_map_io,
 	.init_irq = pxa3xx_init_irq,
 	.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index bff6e78..ac5598c 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -33,6 +33,9 @@
 extern void cmx255_init(void);
 extern void cmx270_init(void);
 
+/* reserve IRQs for IT8152 */
+#define CMX2XX_NR_IRQS		(IRQ_BOARD_START + 40)
+
 /* virtual addresses for statically mapped regions */
 #define CMX2XX_VIRT_BASE	(0xe8000000)
 #define CMX2XX_IT8152_VIRT	(CMX2XX_VIRT_BASE)
@@ -511,9 +514,8 @@
 
 MACHINE_START(ARMCORE, "Compulab CM-X2XX")
 	.boot_params	= 0xa0000100,
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= cmx2xx_map_io,
+	.nr_irqs	= CMX2XX_NR_IRQS,
 	.init_irq	= cmx2xx_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= cmx2xx_init,
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index c70e6c2..922b107 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 
 #include <linux/gpio.h>
 #include <linux/dm9000.h>
@@ -50,6 +51,7 @@
 #include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 #include <mach/audio.h>
+#include <mach/pxa3xx-u2d.h>
 
 #include <asm/mach/map.h>
 
@@ -68,6 +70,8 @@
 #define GPIO97_RTC_RD		(97)
 #define GPIO98_RTC_IO		(98)
 
+#define GPIO_ULPI_PHY_RST	(127)
+
 static mfp_cfg_t cm_x3xx_mfp_cfg[] __initdata = {
 	/* LCD */
 	GPIO54_LCD_LDD_0,
@@ -472,6 +476,78 @@
 static inline void cm_x300_init_mmc(void) {}
 #endif
 
+#if defined(CONFIG_PXA310_ULPI)
+static struct clk *pout_clk;
+
+static int cm_x300_ulpi_phy_reset(void)
+{
+	int err;
+
+	/* reset the PHY */
+	err = gpio_request(GPIO_ULPI_PHY_RST, "ulpi reset");
+	if (err) {
+		pr_err("%s: failed to request ULPI reset GPIO: %d\n",
+		       __func__, err);
+		return err;
+	}
+
+	gpio_direction_output(GPIO_ULPI_PHY_RST, 0);
+	msleep(10);
+	gpio_set_value(GPIO_ULPI_PHY_RST, 1);
+	msleep(10);
+
+	gpio_free(GPIO_ULPI_PHY_RST);
+
+	return 0;
+}
+
+static inline int cm_x300_u2d_init(struct device *dev)
+{
+	int err = 0;
+
+	if (cpu_is_pxa310()) {
+		/* CLK_POUT is connected to the ULPI PHY */
+		pout_clk = clk_get(NULL, "CLK_POUT");
+		if (IS_ERR(pout_clk)) {
+			err = PTR_ERR(pout_clk);
+			pr_err("%s: failed to get CLK_POUT: %d\n",
+			       __func__, err);
+			return err;
+		}
+		clk_enable(pout_clk);
+
+		err = cm_x300_ulpi_phy_reset();
+		if (err) {
+			clk_disable(pout_clk);
+			clk_put(pout_clk);
+		}
+	}
+
+	return err;
+}
+
+static void cm_x300_u2d_exit(struct device *dev)
+{
+	if (cpu_is_pxa310()) {
+		clk_disable(pout_clk);
+		clk_put(pout_clk);
+	}
+}
+
+static struct pxa3xx_u2d_platform_data cm_x300_u2d_platform_data = {
+	.ulpi_mode	= ULPI_SER_6PIN,
+	.init		= cm_x300_u2d_init,
+	.exit		= cm_x300_u2d_exit,
+};
+
+static void cm_x300_init_u2d(void)
+{
+	pxa3xx_set_u2d_info(&cm_x300_u2d_platform_data);
+}
+#else
+static inline void cm_x300_init_u2d(void) {}
+#endif
+
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 static int cm_x300_ohci_init(struct device *dev)
 {
@@ -754,6 +830,7 @@
 	cm_x300_init_da9030();
 	cm_x300_init_dm9000();
 	cm_x300_init_lcd();
+	cm_x300_init_u2d();
 	cm_x300_init_ohci();
 	cm_x300_init_mmc();
 	cm_x300_init_nand();
@@ -779,9 +856,7 @@
 }
 
 MACHINE_START(CM_X300, "CM-X300 module")
-	.phys_io	= 0x40000000,
 	.boot_params	= 0xa0000100,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
diff --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c
index 98673ac..bc04510 100644
--- a/arch/arm/mach-pxa/colibri-pxa270.c
+++ b/arch/arm/mach-pxa/colibri-pxa270.c
@@ -207,8 +207,6 @@
 }
 
 MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
 	.init_machine	= colibri_pxa270_init,
 	.map_io		= pxa_map_io,
@@ -217,8 +215,6 @@
 MACHINE_END
 
 MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.init_machine	= colibri_pxa270_income_init,
 	.map_io		= pxa_map_io,
diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c
index 40b6ac2..a70b256 100644
--- a/arch/arm/mach-pxa/colibri-pxa300.c
+++ b/arch/arm/mach-pxa/colibri-pxa300.c
@@ -186,8 +186,6 @@
 }
 
 MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
 	.init_machine	= colibri_pxa300_init,
 	.map_io		= pxa_map_io,
diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c
index 99e850d..ca5f29e 100644
--- a/arch/arm/mach-pxa/colibri-pxa320.c
+++ b/arch/arm/mach-pxa/colibri-pxa320.c
@@ -255,8 +255,6 @@
 }
 
 MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
 	.init_machine	= colibri_pxa320_init,
 	.map_io		= pxa_map_io,
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 3fb0fc0..821229ac 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -720,8 +720,6 @@
 
 #ifdef CONFIG_MACH_CORGI
 MACHINE_START(CORGI, "SHARP Corgi")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa25x_init_irq,
@@ -732,8 +730,6 @@
 
 #ifdef CONFIG_MACH_SHEPHERD
 MACHINE_START(SHEPHERD, "SHARP Shepherd")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa25x_init_irq,
@@ -744,8 +740,6 @@
 
 #ifdef CONFIG_MACH_HUSKY
 MACHINE_START(HUSKY, "SHARP Husky")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
index 50d5939..58093d9 100644
--- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c
+++ b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
@@ -312,8 +312,7 @@
 	freqs.cpu = policy->cpu;
 
 	if (freq_debug)
-		pr_debug(KERN_INFO "Changing CPU frequency to %d Mhz, "
-			 "(SDRAM %d Mhz)\n",
+		pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n",
 			 freqs.new / 1000, (pxa_freq_settings[idx].div2) ?
 			 (new_freq_mem / 2000) : (new_freq_mem / 1000));
 
diff --git a/arch/arm/mach-pxa/cpufreq-pxa3xx.c b/arch/arm/mach-pxa/cpufreq-pxa3xx.c
index 0a0d0fe..88fbec0 100644
--- a/arch/arm/mach-pxa/cpufreq-pxa3xx.c
+++ b/arch/arm/mach-pxa/cpufreq-pxa3xx.c
@@ -159,7 +159,7 @@
 
 static unsigned int pxa3xx_cpufreq_get(unsigned int cpu)
 {
-	return get_clk_frequency_khz(0);
+	return pxa3xx_get_clk_frequency_khz(0);
 }
 
 static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy,
@@ -212,7 +212,8 @@
 	policy->cpuinfo.min_freq = 104000;
 	policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000;
 	policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
-	policy->cur = policy->min = policy->max = get_clk_frequency_khz(0);
+	policy->max = pxa3xx_get_clk_frequency_khz(0);
+	policy->cur = policy->min = policy->max;
 
 	if (cpu_is_pxa300() || cpu_is_pxa310())
 		ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa300_freqs));
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index 91fd4fe..57cacaf 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -272,9 +272,7 @@
 }
 
 MACHINE_START(CSB726, "Cogent CSB726")
-	.phys_io	= 0x40000000,
 	.boot_params	= 0xa0000100,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io         = pxa_map_io,
 	.init_irq       = pxa27x_init_irq,
 	.init_machine   = csb726_init,
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 65447dc..08b4103 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -6,11 +6,12 @@
 
 #include <asm/pmu.h>
 #include <mach/udc.h>
+#include <mach/pxa3xx-u2d.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/pxa2xx_spi.h>
 #include <mach/camera.h>
 #include <mach/audio.h>
@@ -134,6 +135,33 @@
 	}
 };
 
+#ifdef CONFIG_PXA3xx
+static struct resource pxa3xx_u2d_resources[] = {
+	[0] = {
+		.start	= 0x54100000,
+		.end	= 0x54100fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_USB2,
+		.end	= IRQ_USB2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device pxa3xx_device_u2d = {
+	.name		= "pxa3xx-u2d",
+	.id		= -1,
+	.resource	= pxa3xx_u2d_resources,
+	.num_resources	= ARRAY_SIZE(pxa3xx_u2d_resources),
+};
+
+void __init pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info)
+{
+	pxa_register_device(&pxa3xx_device_u2d, info);
+}
+#endif /* CONFIG_PXA3xx */
+
 static struct resource pxafb_resources[] = {
 	[0] = {
 		.start	= 0x44000000,
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index 50353ea..715e8bd 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -4,6 +4,7 @@
 extern struct platform_device pxa3xx_device_mci3;
 extern struct platform_device pxa25x_device_udc;
 extern struct platform_device pxa27x_device_udc;
+extern struct platform_device pxa3xx_device_u2d;
 extern struct platform_device pxa_device_fb;
 extern struct platform_device pxa_device_ffuart;
 extern struct platform_device pxa_device_btuart;
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 0517c17..ab48bb8 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -43,7 +43,7 @@
 #include <mach/pxafb.h>
 #include <mach/ohci.h>
 #include <mach/mmc.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <plat/i2c.h>
 #include <mach/camera.h>
 #include <mach/pxa2xx_spi.h>
@@ -1301,8 +1301,6 @@
 
 MACHINE_START(EM_X270, "Compulab EM-X270")
 	.boot_params	= 0xa0000100,
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
@@ -1311,8 +1309,6 @@
 
 MACHINE_START(EXEDA, "Compulab eXeda")
 	.boot_params	= 0xa0000100,
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index 349212a..b25690c 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -29,6 +29,7 @@
 
 #include <mach/pxa25x.h>
 #include <mach/eseries-gpio.h>
+#include <mach/eseries-irq.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
 #include <mach/udc.h>
@@ -179,10 +180,9 @@
 
 MACHINE_START(E330, "Toshiba e330")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa_map_io,
+	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e330_init,
@@ -229,10 +229,9 @@
 
 MACHINE_START(E350, "Toshiba e350")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa_map_io,
+	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e350_init,
@@ -352,10 +351,9 @@
 
 MACHINE_START(E400, "Toshiba e400")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa_map_io,
+	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e400_init,
@@ -541,10 +539,9 @@
 
 MACHINE_START(E740, "Toshiba e740")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa_map_io,
+	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e740_init,
@@ -733,10 +730,9 @@
 
 MACHINE_START(E750, "Toshiba e750")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa_map_io,
+	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e750_init,
@@ -929,10 +925,9 @@
 
 MACHINE_START(E800, "Toshiba e800")
 	/* Maintainer: Ian Molton (spyro@f2s.com) */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa_map_io,
+	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e800_init,
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index 626c82b..80a9352 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -32,12 +32,14 @@
 #include <mach/ohci.h>
 #include <plat/i2c.h>
 #include <mach/hardware.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/camera.h>
 
 #include "devices.h"
 #include "generic.h"
 
+#define EZX_NR_IRQS			(IRQ_BOARD_START + 24)
+
 #define GPIO12_A780_FLIP_LID 		12
 #define GPIO15_A1200_FLIP_LID 		15
 #define GPIO15_A910_FLIP_LID 		15
@@ -796,10 +798,9 @@
 }
 
 MACHINE_START(EZX_A780, "Motorola EZX A780")
-	.phys_io        = 0x40000000,
-	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params    = 0xa0000100,
 	.map_io         = pxa_map_io,
+	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = a780_init,
@@ -862,10 +863,9 @@
 }
 
 MACHINE_START(EZX_E680, "Motorola EZX E680")
-	.phys_io        = 0x40000000,
-	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params    = 0xa0000100,
 	.map_io         = pxa_map_io,
+	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = e680_init,
@@ -928,10 +928,9 @@
 }
 
 MACHINE_START(EZX_A1200, "Motorola EZX A1200")
-	.phys_io        = 0x40000000,
-	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params    = 0xa0000100,
 	.map_io         = pxa_map_io,
+	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = a1200_init,
@@ -1120,10 +1119,9 @@
 }
 
 MACHINE_START(EZX_A910, "Motorola EZX A910")
-	.phys_io        = 0x40000000,
-	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params    = 0xa0000100,
 	.map_io         = pxa_map_io,
+	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = a910_init,
@@ -1186,10 +1184,9 @@
 }
 
 MACHINE_START(EZX_E6, "Motorola EZX E6")
-	.phys_io        = 0x40000000,
-	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params    = 0xa0000100,
 	.map_io         = pxa_map_io,
+	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = e6_init,
@@ -1226,10 +1223,9 @@
 }
 
 MACHINE_START(EZX_E2, "Motorola EZX E2")
-	.phys_io        = 0x40000000,
-	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params    = 0xa0000100,
 	.map_io         = pxa_map_io,
+	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = e2_init,
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index baabb3c..6451e9c 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -66,8 +66,7 @@
 		return pxa25x_get_clk_frequency_khz(info);
 	else if (cpu_is_pxa27x())
 		return pxa27x_get_clk_frequency_khz(info);
-	else
-		return pxa3xx_get_clk_frequency_khz(info);
+	return 0;
 }
 EXPORT_SYMBOL(get_clk_frequency_khz);
 
@@ -80,8 +79,7 @@
 		return pxa25x_get_memclk_frequency_10khz();
 	else if (cpu_is_pxa27x())
 		return pxa27x_get_memclk_frequency_10khz();
-	else
-		return pxa3xx_get_memclk_frequency_10khz();
+	return 0;
 }
 EXPORT_SYMBOL(get_memclk_frequency_10khz);
 
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index c6305c5..4b1ad27 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -54,11 +54,9 @@
 
 #ifdef CONFIG_PXA3xx
 extern unsigned pxa3xx_get_clk_frequency_khz(int);
-extern unsigned pxa3xx_get_memclk_frequency_10khz(void);
 extern void pxa3xx_clear_reset_status(unsigned int);
 #else
 #define pxa3xx_get_clk_frequency_khz(x)		(0)
-#define pxa3xx_get_memclk_frequency_10khz()	(0)
 static inline void pxa3xx_clear_reset_status(unsigned int mask) {}
 #endif
 
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index 96c3451..1e2a9a1 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -224,9 +224,7 @@
 }
 
 MACHINE_START(GUMSTIX, "Gumstix")
-	.phys_io	= 0x40000000,
 	.boot_params	= 0xa0000100, /* match u-boot bi_boot_params */
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.timer		= &pxa_timer,
diff --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c
index c1cab08..7057a1f 100644
--- a/arch/arm/mach-pxa/h5000.c
+++ b/arch/arm/mach-pxa/h5000.c
@@ -201,8 +201,6 @@
 }
 
 MACHINE_START(H5400, "HP iPAQ H5000")
-	.phys_io = 0x40000000,
-	.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params = 0xa0000100,
 	.map_io = pxa_map_io,
 	.init_irq = pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/himalaya.c b/arch/arm/mach-pxa/himalaya.c
index f9a2e4b..01b7f07 100644
--- a/arch/arm/mach-pxa/himalaya.c
+++ b/arch/arm/mach-pxa/himalaya.c
@@ -159,8 +159,6 @@
 
 
 MACHINE_START(HIMALAYA, "HTC Himalaya")
-	.phys_io = 0x40000000,
-	.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params = 0xa0000100,
 	.map_io = pxa_map_io,
 	.init_irq = pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index 848c861..76d93a2 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -870,10 +870,9 @@
 }
 
 MACHINE_START(H4700, "HP iPAQ HX4700")
-	.phys_io      = 0x40000000,
-	.io_pg_offst  = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params  = 0xa0000100,
 	.map_io       = pxa_map_io,
+	.nr_irqs      = HX4700_NR_IRQS,
 	.init_irq     = pxa27x_init_irq,
 	.init_machine = hx4700_init,
 	.timer        = &pxa_timer,
diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c
index 5ccb0ce..d51ee3d 100644
--- a/arch/arm/mach-pxa/icontrol.c
+++ b/arch/arm/mach-pxa/icontrol.c
@@ -191,9 +191,7 @@
 }
 
 MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
-	.phys_io	= 0x40000000,
 	.boot_params	= 0xa0000100,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index bc78c4d..e773dce 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -194,8 +194,6 @@
 
 MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
 	/* Maintainer: Vibren Technologies */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= idp_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.timer		= &pxa_timer,
diff --git a/arch/arm/mach-pxa/include/mach/balloon3.h b/arch/arm/mach-pxa/include/mach/balloon3.h
index eec92e6..561562b 100644
--- a/arch/arm/mach-pxa/include/mach/balloon3.h
+++ b/arch/arm/mach-pxa/include/mach/balloon3.h
@@ -174,6 +174,8 @@
 #define BALLOON3_CODEC_IRQ	IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ)
 #define BALLOON3_S0_CD_IRQ	IRQ_GPIO(BALLOON3_GPIO_S0_CD)
 
+#define BALLOON3_NR_IRQS	(IRQ_BOARD_START + 4)
+
 extern int balloon3_has(enum balloon3_features feature);
 
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/debug-macro.S b/arch/arm/mach-pxa/include/mach/debug-macro.S
index 01cf813..7d5c751 100644
--- a/arch/arm/mach-pxa/include/mach/debug-macro.S
+++ b/arch/arm/mach-pxa/include/mach/debug-macro.S
@@ -13,12 +13,10 @@
 
 #include "hardware.h"
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x40000000		@ physical
-		movne	\rx, #io_p2v(0x40000000)	@ virtual
-		orr	\rx, \rx, #0x00100000
+		.macro	addruart, rp, rv
+		mov	\rp, #0x00100000
+		orr	\rv, \rp, #io_p2v(0x40000000)	@ virtual
+		orr	\rp, \rp, #0x40000000		@ physical
 		.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-pxa/include/mach/eseries-irq.h b/arch/arm/mach-pxa/include/mach/eseries-irq.h
index f2a93d5..de292b2 100644
--- a/arch/arm/mach-pxa/include/mach/eseries-irq.h
+++ b/arch/arm/mach-pxa/include/mach/eseries-irq.h
@@ -25,3 +25,4 @@
 #define TMIO_SD_IRQ     IRQ_TMIO(1)
 #define TMIO_USB_IRQ    IRQ_TMIO(2)
 
+#define ESERIES_NR_IRQS	(IRQ_BOARD_START + 16)
diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h
index 428cc7b..814f145 100644
--- a/arch/arm/mach-pxa/include/mach/hardware.h
+++ b/arch/arm/mach-pxa/include/mach/hardware.h
@@ -264,23 +264,35 @@
  * <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x
  * == 0x3 for pxa300/pxa310/pxa320
  */
+#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
 #define __cpu_is_pxa2xx(id)				\
 	({						\
 		unsigned int _id = (id) >> 13 & 0x7;	\
 		_id <= 0x2;				\
 	 })
+#else
+#define __cpu_is_pxa2xx(id)	(0)
+#endif
 
+#ifdef CONFIG_PXA3xx
 #define __cpu_is_pxa3xx(id)				\
 	({						\
 		unsigned int _id = (id) >> 13 & 0x7;	\
 		_id == 0x3;				\
 	 })
+#else
+#define __cpu_is_pxa3xx(id)	(0)
+#endif
 
+#if defined(CONFIG_CPU_PXA930) || defined(CONFIG_CPU_PXA935)
 #define __cpu_is_pxa93x(id)				\
 	({						\
 		unsigned int _id = (id) >> 4 & 0xfff;	\
 		_id == 0x683 || _id == 0x693;		\
 	 })
+#else
+#define __cpu_is_pxa93x(id)	(0)
+#endif
 
 #define cpu_is_pxa2xx()					\
 	({						\
diff --git a/arch/arm/mach-pxa/include/mach/hx4700.h b/arch/arm/mach-pxa/include/mach/hx4700.h
index 9eaeed1..3740844 100644
--- a/arch/arm/mach-pxa/include/mach/hx4700.h
+++ b/arch/arm/mach-pxa/include/mach/hx4700.h
@@ -17,6 +17,7 @@
 
 #define HX4700_ASIC3_GPIO_BASE	NR_BUILTIN_GPIO
 #define HX4700_EGPIO_BASE	(HX4700_ASIC3_GPIO_BASE + ASIC3_NUM_GPIOS)
+#define HX4700_NR_IRQS		(IRQ_BOARD_START + 70)
 
 /*
  * PXA GPIOs
diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index ffc8314..d372caa 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -117,48 +117,12 @@
 /*
  * The following interrupts are for board specific purposes. Since
  * the kernel can only run on one machine at a time, we can re-use
- * these.  There will be 16 IRQs by default.  If it is not enough,
- * IRQ_BOARD_END is allowed be customized for each board, but keep
- * the numbers within sensible limits and in descending order, so
- * when multiple config options are selected, the maximum will be
- * used.
+ * these.
+ * By default, no board IRQ is reserved. It should be finished in
+ * custom board since sparse IRQ is already enabled.
  */
 #define IRQ_BOARD_START		(PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
 
-#if defined(CONFIG_MACH_H4700)
-#define IRQ_BOARD_END		(IRQ_BOARD_START + 70)
-#elif defined(CONFIG_MACH_ZYLONITE)
-#define IRQ_BOARD_END		(IRQ_BOARD_START + 32)
-#elif defined(CONFIG_PXA_EZX)
-#define IRQ_BOARD_END		(IRQ_BOARD_START + 23)
-#else
-#define IRQ_BOARD_END		(IRQ_BOARD_START + 16)
-#endif
-
-/*
- * Figure out the MAX IRQ number.
- *
- * If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1.
- * If we have an LoCoMo, the max IRQ is IRQ_LOCOMO_SPI_TEND+1
- * Otherwise, we have the standard IRQs only.
- */
-#ifdef CONFIG_SA1111
-#define NR_IRQS			(IRQ_BOARD_END + 55)
-#elif defined(CONFIG_PXA_HAVE_BOARD_IRQS)
-#define NR_IRQS			(IRQ_BOARD_END)
-#else
 #define NR_IRQS			(IRQ_BOARD_START)
-#endif
-
-/* add IT8152 IRQs beyond BOARD_END */
-#ifdef CONFIG_PCI_HOST_ITE8152
-#define IT8152_LAST_IRQ         (IRQ_BOARD_END + 40)
-
-#if NR_IRQS < (IT8152_LAST_IRQ+1)
-#undef NR_IRQS
-#define NR_IRQS (IT8152_LAST_IRQ+1)
-#endif
-
-#endif /* CONFIG_PCI_HOST_ITE8152 */
 
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/include/mach/littleton.h b/arch/arm/mach-pxa/include/mach/littleton.h
index 6c9b21c..2a5726c 100644
--- a/arch/arm/mach-pxa/include/mach/littleton.h
+++ b/arch/arm/mach-pxa/include/mach/littleton.h
@@ -10,4 +10,6 @@
 #define EXT0_GPIO_BASE	(NR_BUILTIN_GPIO)
 #define EXT0_GPIO(x)	(EXT0_GPIO_BASE + (x))
 
+#define LITTLETON_NR_IRQS	(IRQ_BOARD_START + 8)
+
 #endif /* __ASM_ARCH_LITTLETON_H */
diff --git a/arch/arm/mach-pxa/include/mach/lpd270.h b/arch/arm/mach-pxa/include/mach/lpd270.h
index 0e6440c..cd07009 100644
--- a/arch/arm/mach-pxa/include/mach/lpd270.h
+++ b/arch/arm/mach-pxa/include/mach/lpd270.h
@@ -38,5 +38,6 @@
 #define LPD270_USBC_IRQ		LPD270_IRQ(2)
 #define LPD270_ETHERNET_IRQ	LPD270_IRQ(3)
 #define LPD270_AC97_IRQ		LPD270_IRQ(4)
+#define LPD270_NR_IRQS		(IRQ_BOARD_START + 5)
 
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/lubbock.h b/arch/arm/mach-pxa/include/mach/lubbock.h
index a0d4247..2a086e8 100644
--- a/arch/arm/mach-pxa/include/mach/lubbock.h
+++ b/arch/arm/mach-pxa/include/mach/lubbock.h
@@ -45,6 +45,9 @@
 #define LUBBOCK_USB_DISC_IRQ	LUBBOCK_IRQ(6)  /* usb disconnect */
 #define LUBBOCK_LAST_IRQ	LUBBOCK_IRQ(6)
 
+#define LUBBOCK_SA1111_IRQ_BASE	(IRQ_BOARD_START + 16)
+#define LUBBOCK_NR_IRQS		(IRQ_BOARD_START + 16 + 55)
+
 #ifndef __ASSEMBLY__
 extern void lubbock_set_misc_wr(unsigned int mask, unsigned int set);
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/magician.h b/arch/arm/mach-pxa/include/mach/magician.h
index 20ef37d..0a2efcf 100644
--- a/arch/arm/mach-pxa/include/mach/magician.h
+++ b/arch/arm/mach-pxa/include/mach/magician.h
@@ -71,6 +71,8 @@
 #define IRQ_MAGICIAN_BT		(IRQ_BOARD_START + 2)
 #define IRQ_MAGICIAN_VBUS	(IRQ_BOARD_START + 3)
 
+#define MAGICIAN_NR_IRQS	(IRQ_BOARD_START + 8)
+
 /*
  * CPLD EGPIOs
  */
diff --git a/arch/arm/mach-pxa/include/mach/mainstone.h b/arch/arm/mach-pxa/include/mach/mainstone.h
index 86e623a..4c2d11c 100644
--- a/arch/arm/mach-pxa/include/mach/mainstone.h
+++ b/arch/arm/mach-pxa/include/mach/mainstone.h
@@ -134,4 +134,6 @@
 #define MAINSTONE_S1_STSCHG_IRQ	MAINSTONE_IRQ(14)
 #define MAINSTONE_S1_IRQ	MAINSTONE_IRQ(15)
 
+#define MAINSTONE_NR_IRQS	(IRQ_BOARD_START + 16)
+
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h
index 0d119d3..04f7c97 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h
@@ -69,6 +69,7 @@
 #define nBE0_GPIO_60		MFP_CFG(nBE0, AF0)
 #define nBE1_GPIO_61		MFP_CFG(nBE1, AF0)
 #define RDY_GPIO_62		MFP_CFG(RDY, AF0)
+#define PMIC_INT_GPIO83		MFP_CFG_LPM(PMIC_INT, AF0, PULL_HIGH)
 
 /* Chip Select */
 #define DF_nCS0_nCS2		MFP_CFG_LPM(DF_nCS0, AF3, PULL_HIGH)
@@ -92,6 +93,9 @@
 #define GPIO63_CI2C_SCL		MFP_CFG_LPM(GPIO63, AF4, PULL_HIGH)
 #define GPIO64_CI2C_SDA		MFP_CFG_LPM(GPIO64, AF4, PULL_HIGH)
 
+#define GPIO73_CI2C_SCL		MFP_CFG_LPM(GPIO73, AF1, PULL_HIGH)
+#define GPIO74_CI2C_SDA		MFP_CFG_LPM(GPIO74, AF1, PULL_HIGH)
+
 #define GPIO77_CI2C_SCL		MFP_CFG_LPM(GPIO77, AF2, PULL_HIGH)
 #define GPIO78_CI2C_SDA		MFP_CFG_LPM(GPIO78, AF2, PULL_HIGH)
 
@@ -345,6 +349,9 @@
 #define GPIO69_UART1_CTS	MFP_CFG(GPIO69, AF2)
 #define GPIO70_UART1_RTS	MFP_CFG(GPIO70, AF2)
 
+#define GPIO53_UART1_TXD	MFP_CFG(GPIO53, AF2)
+#define GPIO54_UART1_RXD	MFP_CFG(GPIO54, AF2)
+
 /* UART2 - BTUART */
 #define GPIO91_UART2_RXD	MFP_CFG(GPIO91, AF1)
 #define GPIO92_UART2_TXD	MFP_CFG(GPIO92, AF1)
diff --git a/arch/arm/mach-pxa/include/mach/pcm027.h b/arch/arm/mach-pxa/include/mach/pcm027.h
index 0408326..4bac588 100644
--- a/arch/arm/mach-pxa/include/mach/pcm027.h
+++ b/arch/arm/mach-pxa/include/mach/pcm027.h
@@ -30,6 +30,8 @@
 #define PCM027_MMCDET_IRQ      PCM027_IRQ(2)
 #define PCM027_PM_5V_IRQ       PCM027_IRQ(3)
 
+#define PCM027_NR_IRQS		(IRQ_BOARD_START + 32)
+
 /* I2C RTC */
 #define PCM027_RTC_IRQ_GPIO	0
 #define PCM027_RTC_IRQ		IRQ_GPIO(PCM027_RTC_IRQ_GPIO)
diff --git a/arch/arm/mach-pxa/include/mach/poodle.h b/arch/arm/mach-pxa/include/mach/poodle.h
index 0b3e6d0..83d1cfd 100644
--- a/arch/arm/mach-pxa/include/mach/poodle.h
+++ b/arch/arm/mach-pxa/include/mach/poodle.h
@@ -85,6 +85,8 @@
 #define POODLE_LOCOMO_GPIO_232VCC_ON   LOCOMO_GPIO(12)
 #define POODLE_LOCOMO_GPIO_JK_B        LOCOMO_GPIO(13)
 
+#define POODLE_NR_IRQS		(IRQ_BOARD_START + 4)	/* 4 for LoCoMo */
+
 extern struct platform_device poodle_locomo_device;
 
 #endif /* __ASM_ARCH_POODLE_H  */
diff --git a/arch/arm/mach-pxa/include/mach/pxa27x_keypad.h b/arch/arm/mach-pxa/include/mach/pxa27x_keypad.h
deleted file mode 100644
index 7b4eadc..0000000
--- a/arch/arm/mach-pxa/include/mach/pxa27x_keypad.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef __ASM_ARCH_PXA27x_KEYPAD_H
-#define __ASM_ARCH_PXA27x_KEYPAD_H
-
-#include <linux/input.h>
-#include <linux/input/matrix_keypad.h>
-
-#define MAX_MATRIX_KEY_ROWS	(8)
-#define MAX_MATRIX_KEY_COLS	(8)
-#define MATRIX_ROW_SHIFT	(3)
-#define MAX_DIRECT_KEY_NUM	(8)
-
-/* pxa3xx keypad platform specific parameters
- *
- * NOTE:
- * 1. direct_key_num indicates the number of keys in the direct keypad
- *    _plus_ the number of rotary-encoder sensor inputs,  this can be
- *    left as 0 if only rotary encoders are enabled,  the driver will
- *    automatically calculate this
- *
- * 2. direct_key_map is the key code map for the direct keys, if rotary
- *    encoder(s) are enabled, direct key 0/1(2/3) will be ignored
- *
- * 3. rotary can be either interpreted as a relative input event (e.g.
- *    REL_WHEEL/REL_HWHEEL) or specific keys (e.g. UP/DOWN/LEFT/RIGHT)
- *
- * 4. matrix key and direct key will use the same debounce_interval by
- *    default, which should be sufficient in most cases
- */
-struct pxa27x_keypad_platform_data {
-
-	/* code map for the matrix keys */
-	unsigned int	matrix_key_rows;
-	unsigned int	matrix_key_cols;
-	unsigned int	*matrix_key_map;
-	int		matrix_key_map_size;
-
-	/* direct keys */
-	int		direct_key_num;
-	unsigned int	direct_key_map[MAX_DIRECT_KEY_NUM];
-
-	/* rotary encoders 0 */
-	int		enable_rotary0;
-	int		rotary0_rel_code;
-	int		rotary0_up_key;
-	int		rotary0_down_key;
-
-	/* rotary encoders 1 */
-	int		enable_rotary1;
-	int		rotary1_rel_code;
-	int		rotary1_up_key;
-	int		rotary1_down_key;
-
-	/* key debounce interval */
-	unsigned int	debounce_interval;
-};
-
-extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info);
-
-#endif /* __ASM_ARCH_PXA27x_KEYPAD_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
new file mode 100644
index 0000000..9d82cb6
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
@@ -0,0 +1,35 @@
+/*
+ * PXA3xx U2D header
+ *
+ * Copyright (C) 2010 CompuLab Ltd.
+ *
+ * Igor Grinberg <grinberg@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __PXA310_U2D__
+#define __PXA310_U2D__
+
+#include <linux/usb/ulpi.h>
+
+struct pxa3xx_u2d_platform_data {
+
+#define ULPI_SER_6PIN	(1 << 0)
+#define ULPI_SER_3PIN	(1 << 1)
+	unsigned int ulpi_mode;
+
+	int (*init)(struct device *);
+	void (*exit)(struct device *);
+};
+
+
+/* Start PXA3xx U2D host */
+int pxa3xx_u2d_start_hc(struct usb_bus *host);
+/* Stop PXA3xx U2D host */
+void pxa3xx_u2d_stop_hc(struct usb_bus *host);
+
+extern void pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info);
+
+#endif /* __PXA310_U2D__ */
diff --git a/arch/arm/mach-pxa/include/mach/tosa.h b/arch/arm/mach-pxa/include/mach/tosa.h
index 1bbd1f2..1272c4b 100644
--- a/arch/arm/mach-pxa/include/mach/tosa.h
+++ b/arch/arm/mach-pxa/include/mach/tosa.h
@@ -20,6 +20,7 @@
 /* Jacket Scoop */
 #define TOSA_SCOOP_PHYS  	(PXA_CS5_PHYS + 0x00800000)
 
+#define TOSA_NR_IRQS		(IRQ_BOARD_START + TC6393XB_NR_IRQS)
 /*
  * SCOOP2 internal GPIOs
  */
diff --git a/arch/arm/mach-pxa/include/mach/zeus.h b/arch/arm/mach-pxa/include/mach/zeus.h
index 6e11997..faa408a 100644
--- a/arch/arm/mach-pxa/include/mach/zeus.h
+++ b/arch/arm/mach-pxa/include/mach/zeus.h
@@ -15,6 +15,8 @@
 #ifndef _MACH_ZEUS_H
 #define _MACH_ZEUS_H
 
+#define ZEUS_NR_IRQS		(IRQ_BOARD_START + 48)
+
 /* Physical addresses */
 #define ZEUS_FLASH_PHYS		PXA_CS0_PHYS
 #define ZEUS_ETH0_PHYS		PXA_CS1_PHYS
diff --git a/arch/arm/mach-pxa/include/mach/zylonite.h b/arch/arm/mach-pxa/include/mach/zylonite.h
index 9edf645..ea24998 100644
--- a/arch/arm/mach-pxa/include/mach/zylonite.h
+++ b/arch/arm/mach-pxa/include/mach/zylonite.h
@@ -5,6 +5,8 @@
 
 #define EXT_GPIO(x)		(128 + (x))
 
+#define ZYLONITE_NR_IRQS	(IRQ_BOARD_START + 32)
+
 /* the following variables are processor specific and initialized
  * by the corresponding zylonite_pxa3xx_init()
  */
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 9b90461..41aa89e 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -43,7 +43,7 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/pxa2xx_spi.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/littleton.h>
 #include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
@@ -437,10 +437,9 @@
 }
 
 MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
-	.phys_io	= 0x40000000,
 	.boot_params	= 0xa0000100,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= pxa_map_io,
+	.nr_irqs	= LITTLETON_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= littleton_init,
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index d279507..623af02 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -505,10 +505,9 @@
 
 MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
 	/* Maintainer: Peter Barada */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= lpd270_map_io,
+	.nr_irqs	= LPD270_NR_IRQS,
 	.init_irq	= lpd270_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= lpd270_init,
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 330c328..1499493 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -229,7 +229,7 @@
 };
 
 static struct sa1111_platform_data sa1111_info = {
-	.irq_base	= IRQ_BOARD_END,
+	.irq_base	= LUBBOCK_SA1111_IRQ_BASE,
 };
 
 static struct platform_device sa1111_device = {
@@ -557,9 +557,8 @@
 
 MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")
 	/* Maintainer: MontaVista Software Inc. */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= lubbock_map_io,
+	.nr_irqs	= LUBBOCK_NR_IRQS,
 	.init_irq	= lubbock_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= lubbock_init,
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index e81dd0c..9066376 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -764,10 +764,9 @@
 
 
 MACHINE_START(MAGICIAN, "HTC Magician")
-	.phys_io = 0x40000000,
-	.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params = 0xa0000100,
 	.map_io = pxa_map_io,
+	.nr_irqs = MAGICIAN_NR_IRQS,
 	.init_irq = pxa27x_init_irq,
 	.init_machine = magician_init,
 	.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 5543c64..a980a5c 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -50,7 +50,7 @@
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -624,10 +624,9 @@
 
 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
 	/* Maintainer: MontaVista Software Inc. */
-	.phys_io	= 0x40000000,
 	.boot_params	= 0xa0000100,	/* BLOB boot parameter setting */
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= mainstone_map_io,
+	.nr_irqs	= MAINSTONE_NR_IRQS,
 	.init_irq	= mainstone_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= mainstone_init,
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index dc66942..0c31fab 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -45,7 +45,7 @@
 
 #include <mach/pxa27x.h>
 #include <mach/regs-rtc.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
@@ -819,8 +819,6 @@
 }
 
 MACHINE_START(MIOA701, "MIO A701")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= &pxa_map_io,
 	.init_irq	= &pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/mp900.c b/arch/arm/mach-pxa/mp900.c
index 6d45039..116167aa 100644
--- a/arch/arm/mach-pxa/mp900.c
+++ b/arch/arm/mach-pxa/mp900.c
@@ -92,9 +92,7 @@
 
 /* Maintainer - Michael Petchkovsky <mkpetch@internode.on.net> */
 MACHINE_START(NEC_MP900, "MobilePro900/C")
-	.phys_io	= 0x40000000,
 	.boot_params	= 0xa0220100,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.timer		= &pxa_timer,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c
index 77ad6d3..405b92a 100644
--- a/arch/arm/mach-pxa/palm27x.c
+++ b/arch/arm/mach-pxa/palm27x.c
@@ -469,9 +469,13 @@
 	},
 };
 
+static struct i2c_pxa_platform_data palm27x_i2c_power_info = {
+	.use_pio	= 1,
+};
+
 void __init palm27x_pmic_init(void)
 {
 	i2c_register_board_info(1, ARRAY_AND_SIZE(palm27x_pi2c_board_info));
-	pxa27x_set_i2c_power_info(NULL);
+	pxa27x_set_i2c_power_info(&palm27x_i2c_power_info);
 }
 #endif
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index 91038ee..ce092c5 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -39,7 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
 #include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/palmasoc.h>
 #include <mach/palm27x.h>
 
@@ -343,8 +343,6 @@
 }
 
 MACHINE_START(PALMLD, "Palm LifeDrive")
-	.phys_io	= PALMLD_PHYS_IO_START,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= palmld_map_io,
 	.init_irq	= pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index 1c28199..862da81 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -39,7 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
 #include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/udc.h>
 #include <mach/palmasoc.h>
 #include <mach/palm27x.h>
@@ -202,8 +202,6 @@
 }
 
 MACHINE_START(PALMT5, "Palm Tungsten|T5")
-	.phys_io	= PALMT5_PHYS_IO_START,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa_map_io,
 	.reserve	= palmt5_reserve,
diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index ce1104d..2131d58 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -412,9 +412,7 @@
 };
 
 MACHINE_START(PALMTC, "Palm Tungsten|C")
-	.phys_io	= 0x40000000,
 	.boot_params 	= 0xa0000100,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa25x_init_irq,
 	.timer		= &pxa_timer,
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index 93c11a0..a9dae7b 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -373,8 +373,6 @@
 }
 
 MACHINE_START(PALMTE2, "Palm Tungsten|E2")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index 52defd5..00e2d7b 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -39,7 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
 #include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/udc.h>
 #include <mach/ohci.h>
 #include <mach/pxa2xx-regs.h>
@@ -441,8 +441,6 @@
 }
 
 MACHINE_START(TREO680, "Palm Treo 680")
-	.phys_io        = TREO_PHYS_IO_START,
-	.io_pg_offst    = io_p2v(0x40000000),
 	.boot_params    = 0xa0000100,
 	.map_io         = pxa_map_io,
 	.reserve	= treo_reserve,
@@ -452,8 +450,6 @@
 MACHINE_END
 
 MACHINE_START(CENTRO, "Palm Centro 685")
-	.phys_io        = TREO_PHYS_IO_START,
-	.io_pg_offst    = io_p2v(0x40000000),
 	.boot_params    = 0xa0000100,
 	.map_io         = pxa_map_io,
 	.reserve	= treo_reserve,
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 144dc2b..d2060a1 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -43,7 +43,7 @@
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
 #include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/udc.h>
 #include <mach/palmasoc.h>
 #include <mach/palm27x.h>
@@ -363,8 +363,6 @@
 }
 
 MACHINE_START(PALMTX, "Palm T|X")
-	.phys_io	= PALMTX_PHYS_IO_START,
-	.io_pg_offst	= io_p2v(0x40000000),
 	.boot_params	= 0xa0000100,
 	.map_io		= palmtx_map_io,
 	.init_irq	= pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 87e4b10..af6203f 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -41,7 +41,7 @@
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
 #include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/udc.h>
 #include <mach/palmasoc.h>
 #include <mach/palm27x.h>
@@ -279,8 +279,6 @@
 }
 
 MACHINE_START(PALMZ72, "Palm Zire72")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= io_p2v(0x40000000),
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index 2190af0..c77e8f3 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -259,9 +259,8 @@
 MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270")
 	/* Maintainer: Pengutronix */
 	.boot_params	= 0xa0000100,
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= pcm027_map_io,
+	.nr_irqs	= PCM027_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= pcm027_init,
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 55e8fcd..93a191c 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -465,10 +465,9 @@
 }
 
 MACHINE_START(POODLE, "SHARP Poodle")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_poodle,
 	.map_io		= pxa_map_io,
+	.nr_irqs	= POODLE_NR_IRQS,	/* 4 for LoCoMo */
 	.init_irq	= pxa25x_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= poodle_init,
diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c
new file mode 100644
index 0000000..ce7168b
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c
@@ -0,0 +1,400 @@
+/*
+ * linux/arch/arm/mach-pxa/pxa3xx-ulpi.c
+ *
+ * code specific to pxa3xx aka Monahans
+ *
+ * Copyright (C) 2010 CompuLab Ltd.
+ *
+ * 2010-13-07: Igor Grinberg <grinberg@compulab.co.il>
+ *             initial version: pxa310 USB Host mode 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/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-u2d.h>
+#include <mach/pxa3xx-u2d.h>
+
+struct pxa3xx_u2d_ulpi {
+	struct clk		*clk;
+	void __iomem		*mmio_base;
+
+	struct otg_transceiver	*otg;
+	unsigned int		ulpi_mode;
+};
+
+static struct pxa3xx_u2d_ulpi *u2d;
+
+static inline u32 u2d_readl(u32 reg)
+{
+	return __raw_readl(u2d->mmio_base + reg);
+}
+
+static inline void u2d_writel(u32 reg, u32 val)
+{
+	__raw_writel(val, u2d->mmio_base + reg);
+}
+
+#if defined(CONFIG_PXA310_ULPI)
+enum u2d_ulpi_phy_mode {
+	SYNCH		= 0,
+	CARKIT		= (1 << 0),
+	SER_3PIN	= (1 << 1),
+	SER_6PIN	= (1 << 2),
+	LOWPOWER	= (1 << 3),
+};
+
+static inline enum u2d_ulpi_phy_mode pxa310_ulpi_get_phymode(void)
+{
+	return (u2d_readl(U2DOTGUSR) >> 28) & 0xF;
+}
+
+static int pxa310_ulpi_poll(void)
+{
+	int timeout = 50000;
+
+	while (timeout--) {
+		if (!(u2d_readl(U2DOTGUCR) & U2DOTGUCR_RUN))
+			return 0;
+
+		cpu_relax();
+	}
+
+	pr_warning("%s: ULPI access timed out!\n", __func__);
+
+	return -ETIMEDOUT;
+}
+
+static int pxa310_ulpi_read(struct otg_transceiver *otg, u32 reg)
+{
+	int err;
+
+	if (pxa310_ulpi_get_phymode() != SYNCH) {
+		pr_warning("%s: PHY is not in SYNCH mode!\n", __func__);
+		return -EBUSY;
+	}
+
+	u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | U2DOTGUCR_RNW | (reg << 16));
+	msleep(5);
+
+	err = pxa310_ulpi_poll();
+	if (err)
+		return err;
+
+	return u2d_readl(U2DOTGUCR) & U2DOTGUCR_RDATA;
+}
+
+static int pxa310_ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
+{
+	if (pxa310_ulpi_get_phymode() != SYNCH) {
+		pr_warning("%s: PHY is not in SYNCH mode!\n", __func__);
+		return -EBUSY;
+	}
+
+	u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | (reg << 16) | (val << 8));
+	msleep(5);
+
+	return pxa310_ulpi_poll();
+}
+
+struct otg_io_access_ops pxa310_ulpi_access_ops = {
+	.read	= pxa310_ulpi_read,
+	.write	= pxa310_ulpi_write,
+};
+
+static void pxa310_otg_transceiver_rtsm(void)
+{
+	u32 u2dotgcr;
+
+	/* put PHY to sync mode */
+	u2dotgcr = u2d_readl(U2DOTGCR);
+	u2dotgcr |=  U2DOTGCR_RTSM | U2DOTGCR_UTMID;
+	u2d_writel(U2DOTGCR, u2dotgcr);
+	msleep(10);
+
+	/* setup OTG sync mode */
+	u2dotgcr = u2d_readl(U2DOTGCR);
+	u2dotgcr |= U2DOTGCR_ULAF;
+	u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF);
+	u2d_writel(U2DOTGCR, u2dotgcr);
+}
+
+static int pxa310_start_otg_host_transcvr(struct usb_bus *host)
+{
+	int err;
+
+	pxa310_otg_transceiver_rtsm();
+
+	err = otg_init(u2d->otg);
+	if (err) {
+		pr_err("OTG transceiver init failed");
+		return err;
+	}
+
+	err = otg_set_vbus(u2d->otg, 1);
+	if (err) {
+		pr_err("OTG transceiver VBUS set failed");
+		return err;
+	}
+
+	err = otg_set_host(u2d->otg, host);
+	if (err)
+		pr_err("OTG transceiver Host mode set failed");
+
+	return err;
+}
+
+static int pxa310_start_otg_hc(struct usb_bus *host)
+{
+	u32 u2dotgcr;
+	int err;
+
+	/* disable USB device controller */
+	u2d_writel(U2DCR, u2d_readl(U2DCR) & ~U2DCR_UDE);
+	u2d_writel(U2DOTGCR, u2d_readl(U2DOTGCR) | U2DOTGCR_UTMID);
+	u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F);
+
+	err = pxa310_start_otg_host_transcvr(host);
+	if (err)
+		return err;
+
+	/* set xceiver mode */
+	if (u2d->ulpi_mode & ULPI_IC_6PIN_SERIAL)
+		u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) & ~U2DP3CR_P2SS);
+	else if (u2d->ulpi_mode & ULPI_IC_3PIN_SERIAL)
+		u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) | U2DP3CR_P2SS);
+
+	/* start OTG host controller */
+	u2dotgcr = u2d_readl(U2DOTGCR) | U2DOTGCR_SMAF;
+	u2d_writel(U2DOTGCR, u2dotgcr & ~(U2DOTGCR_ULAF | U2DOTGCR_CKAF));
+
+	return 0;
+}
+
+static void pxa310_stop_otg_hc(void)
+{
+	pxa310_otg_transceiver_rtsm();
+
+	otg_set_host(u2d->otg, NULL);
+	otg_set_vbus(u2d->otg, 0);
+	otg_shutdown(u2d->otg);
+}
+
+static void pxa310_u2d_setup_otg_hc(void)
+{
+	u32 u2dotgcr;
+
+	u2dotgcr = u2d_readl(U2DOTGCR);
+	u2dotgcr |= U2DOTGCR_ULAF | U2DOTGCR_UTMID;
+	u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF);
+	u2d_writel(U2DOTGCR, u2dotgcr);
+	msleep(5);
+	u2d_writel(U2DOTGCR, u2dotgcr | U2DOTGCR_ULE);
+	msleep(5);
+	u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F);
+}
+
+static int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
+{
+	unsigned int ulpi_mode = ULPI_OTG_DRVVBUS;
+
+	if (pdata) {
+		if (pdata->ulpi_mode & ULPI_SER_6PIN)
+			ulpi_mode |= ULPI_IC_6PIN_SERIAL;
+		else if (pdata->ulpi_mode & ULPI_SER_3PIN)
+			ulpi_mode |= ULPI_IC_3PIN_SERIAL;
+	}
+
+	u2d->ulpi_mode = ulpi_mode;
+
+	u2d->otg = otg_ulpi_create(&pxa310_ulpi_access_ops, ulpi_mode);
+	if (!u2d->otg)
+		return -ENOMEM;
+
+	u2d->otg->io_priv = u2d->mmio_base;
+
+	return 0;
+}
+
+static void pxa310_otg_exit(void)
+{
+	kfree(u2d->otg);
+}
+#else
+static inline void pxa310_u2d_setup_otg_hc(void) {}
+static inline int pxa310_start_otg_hc(struct usb_bus *host)
+{
+	return 0;
+}
+static inline void pxa310_stop_otg_hc(void) {}
+static inline int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
+{
+	return 0;
+}
+static inline void pxa310_otg_exit(void) {}
+#endif /* CONFIG_PXA310_ULPI */
+
+int pxa3xx_u2d_start_hc(struct usb_bus *host)
+{
+	int err = 0;
+
+	/* In case the PXA3xx ULPI isn't used, do nothing. */
+	if (!u2d)
+		return 0;
+
+	clk_enable(u2d->clk);
+
+	if (cpu_is_pxa310()) {
+		pxa310_u2d_setup_otg_hc();
+		err = pxa310_start_otg_hc(host);
+	}
+
+	return err;
+}
+
+void pxa3xx_u2d_stop_hc(struct usb_bus *host)
+{
+	/* In case the PXA3xx ULPI isn't used, do nothing. */
+	if (!u2d)
+		return;
+
+	if (cpu_is_pxa310())
+		pxa310_stop_otg_hc();
+
+	clk_disable(u2d->clk);
+}
+
+static int pxa3xx_u2d_probe(struct platform_device *pdev)
+{
+	struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data;
+	struct resource *r;
+	int err;
+
+	u2d = kzalloc(sizeof(struct pxa3xx_u2d_ulpi), GFP_KERNEL);
+	if (!u2d) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	u2d->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(u2d->clk)) {
+		dev_err(&pdev->dev, "failed to get u2d clock\n");
+		err = PTR_ERR(u2d->clk);
+		goto err_free_mem;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no IO memory resource defined\n");
+		err = -ENODEV;
+		goto err_put_clk;
+	}
+
+        r = request_mem_region(r->start, resource_size(r), pdev->name);
+        if (!r) {
+                dev_err(&pdev->dev, "failed to request memory resource\n");
+                err = -EBUSY;
+                goto err_put_clk;
+        }
+
+	u2d->mmio_base = ioremap(r->start, resource_size(r));
+	if (!u2d->mmio_base) {
+		dev_err(&pdev->dev, "ioremap() failed\n");
+		err = -ENODEV;
+		goto err_free_res;
+	}
+
+	if (pdata->init) {
+		err = pdata->init(&pdev->dev);
+		if (err)
+			goto err_free_io;
+	}
+
+	/* Only PXA310 U2D has OTG functionality */
+	if (cpu_is_pxa310()) {
+		err = pxa310_otg_init(pdata);
+		if (err)
+			goto err_free_plat;
+	}
+
+	platform_set_drvdata(pdev, &u2d);
+
+	return 0;
+
+err_free_plat:
+	if (pdata->exit)
+		pdata->exit(&pdev->dev);
+err_free_io:
+	iounmap(u2d->mmio_base);
+err_free_res:
+	release_mem_region(r->start, resource_size(r));
+err_put_clk:
+	clk_put(u2d->clk);
+err_free_mem:
+	kfree(u2d);
+	return err;
+}
+
+static int pxa3xx_u2d_remove(struct platform_device *pdev)
+{
+	struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data;
+	struct resource *r;
+
+	if (cpu_is_pxa310()) {
+		pxa310_stop_otg_hc();
+		pxa310_otg_exit();
+	}
+
+	if (pdata->exit)
+		pdata->exit(&pdev->dev);
+
+	platform_set_drvdata(pdev, NULL);
+	iounmap(u2d->mmio_base);
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, resource_size(r));
+
+	clk_put(u2d->clk);
+
+	kfree(u2d);
+
+	return 0;
+}
+
+static struct platform_driver pxa3xx_u2d_ulpi_driver = {
+        .driver		= {
+                .name   = "pxa3xx-u2d",
+		.owner	= THIS_MODULE,
+        },
+        .probe          = pxa3xx_u2d_probe,
+        .remove         = pxa3xx_u2d_remove,
+};
+
+static int pxa3xx_u2d_ulpi_init(void)
+{
+	return platform_driver_register(&pxa3xx_u2d_ulpi_driver);
+}
+module_init(pxa3xx_u2d_ulpi_init);
+
+static void __exit pxa3xx_u2d_ulpi_exit(void)
+{
+	platform_driver_unregister(&pxa3xx_u2d_ulpi_driver);
+}
+module_exit(pxa3xx_u2d_ulpi_exit);
+
+MODULE_DESCRIPTION("PXA3xx U2D ULPI driver");
+MODULE_AUTHOR("Igor Grinberg");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index fa00148..c85c3a7 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -98,23 +98,6 @@
 	return CLK / 1000;
 }
 
-/*
- * Return the current static memory controller clock frequency
- * in units of 10kHz
- */
-unsigned int pxa3xx_get_memclk_frequency_10khz(void)
-{
-	unsigned long acsr;
-	unsigned int smcfs, clk = 0;
-
-	acsr = ACSR;
-
-	smcfs = (acsr >> 23) & 0x7;
-	clk = (acsr & ACCR_D0CS) ? RO_CLK : smcfs_mult[smcfs] * BASE_CLK;
-
-	return (clk / 10000);
-}
-
 void pxa3xx_clear_reset_status(unsigned int mask)
 {
 	/* RESET_STATUS_* has a 1:1 mapping with ARSR */
@@ -265,7 +248,7 @@
 	INIT_CLKREG(&clk_pxa3xx_i2c, "pxa2xx-i2c.0", NULL),
 	INIT_CLKREG(&clk_pxa3xx_udc, "pxa27x-udc", NULL),
 	INIT_CLKREG(&clk_pxa3xx_usbh, "pxa27x-ohci", NULL),
-	INIT_CLKREG(&clk_pxa3xx_u2d, NULL, "U2DCLK"),
+	INIT_CLKREG(&clk_pxa3xx_u2d, "pxa3xx-u2d", NULL),
 	INIT_CLKREG(&clk_pxa3xx_keypad, "pxa27x-keypad", NULL),
 	INIT_CLKREG(&clk_pxa3xx_ssp1, "pxa27x-ssp.0", NULL),
 	INIT_CLKREG(&clk_pxa3xx_ssp2, "pxa27x-ssp.1", NULL),
diff --git a/arch/arm/mach-pxa/pxa930.c b/arch/arm/mach-pxa/pxa930.c
index 0642920..7d29dd3 100644
--- a/arch/arm/mach-pxa/pxa930.c
+++ b/arch/arm/mach-pxa/pxa930.c
@@ -192,7 +192,7 @@
 
 static int __init pxa930_init(void)
 {
-	if (cpu_is_pxa930() || cpu_is_pxa935()) {
+	if (cpu_is_pxa930() || cpu_is_pxa935() || cpu_is_pxa950()) {
 		mfp_init_base(io_p2v(MFPR_BASE));
 		mfp_init_addr(pxa930_mfp_addr_map);
 	}
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index 67e04f4..4121d03 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -1083,8 +1083,6 @@
 
 #ifdef CONFIG_MACH_RAUMFELD_RC
 MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
 	.init_machine	= raumfeld_controller_init,
 	.map_io		= pxa_map_io,
@@ -1095,8 +1093,6 @@
 
 #ifdef CONFIG_MACH_RAUMFELD_CONNECTOR
 MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
 	.init_machine	= raumfeld_connector_init,
 	.map_io		= pxa_map_io,
@@ -1107,8 +1103,6 @@
 
 #ifdef CONFIG_MACH_RAUMFELD_SPEAKER
 MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
 	.init_machine	= raumfeld_speaker_init,
 	.map_io		= pxa_map_io,
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index 115b6f2..4b521e0 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -596,9 +596,7 @@
 
 MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
 	/* Maintainer: Eric Miao <eric.miao@marvell.com> */
-	.phys_io        = 0x40000000,
 	.boot_params    = 0xa0000100,
-	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io         = pxa_map_io,
 	.init_irq       = pxa3xx_init_irq,
 	.timer          = &pxa_timer,
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 1cd99cb..f736119 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -979,8 +979,6 @@
 
 #ifdef CONFIG_MACH_SPITZ
 MACHINE_START(SPITZ, "SHARP Spitz")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= spitz_fixup,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa27x_init_irq,
@@ -991,8 +989,6 @@
 
 #ifdef CONFIG_MACH_BORZOI
 MACHINE_START(BORZOI, "SHARP Borzoi")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= spitz_fixup,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa27x_init_irq,
@@ -1003,8 +999,6 @@
 
 #ifdef CONFIG_MACH_AKITA
 MACHINE_START(AKITA, "SHARP Akita")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= spitz_fixup,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index a654d1e..738adc1 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -56,6 +56,8 @@
 #include "devices.h"
 #include "generic.h"
 
+#define STARGATE_NR_IRQS	(IRQ_BOARD_START + 8)
+
 /* Bluetooth */
 #define SG2_BT_RESET		81
 
@@ -996,8 +998,6 @@
 
 #ifdef CONFIG_MACH_INTELMOTE2
 MACHINE_START(INTELMOTE2, "IMOTE 2")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
@@ -1008,9 +1008,8 @@
 
 #ifdef CONFIG_MACH_STARGATE2
 MACHINE_START(STARGATE2, "Stargate 2")
-	.phys_io = 0x40000000,
-	.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io = pxa_map_io,
+	.nr_irqs = STARGATE_NR_IRQS,
 	.init_irq = pxa27x_init_irq,
 	.timer = &pxa_timer,
 	.init_machine = stargate2_init,
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
index f02dcb5..2ea7545 100644
--- a/arch/arm/mach-pxa/tavorevb.c
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -25,7 +25,7 @@
 
 #include <mach/pxa930.h>
 #include <mach/pxafb.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 
 #include "devices.h"
 #include "generic.h"
@@ -489,9 +489,7 @@
 
 MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
 	/* Maintainer: Eric Miao <eric.miao@marvell.com> */
-	.phys_io        = 0x40000000,
 	.boot_params    = 0xa0000100,
-	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io         = pxa_map_io,
 	.init_irq       = pxa3xx_init_irq,
 	.timer          = &pxa_timer,
diff --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c
new file mode 100644
index 0000000..dc30116
--- /dev/null
+++ b/arch/arm/mach-pxa/tavorevb3.c
@@ -0,0 +1,135 @@
+/*
+ *  linux/arch/arm/mach-pxa/tavorevb3.c
+ *
+ *  Support for the Marvell EVB3 Development Platform.
+ *
+ *  Copyright:  (C) Copyright 2008-2010 Marvell International Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/mfd/88pm860x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pxa930.h>
+
+#include <plat/i2c.h>
+
+#include "devices.h"
+#include "generic.h"
+
+#define TAVOREVB3_NR_IRQS	(IRQ_BOARD_START + 24)
+
+static mfp_cfg_t evb3_mfp_cfg[] __initdata = {
+	/* UART */
+	GPIO53_UART1_TXD,
+	GPIO54_UART1_RXD,
+
+	/* PMIC */
+	PMIC_INT_GPIO83,
+};
+
+#if defined(CONFIG_I2C_PXA) || defined(CONFIG_I2C_PXA_MODULE)
+static struct pm860x_touch_pdata evb3_touch = {
+	.gpadc_prebias	= 1,
+	.slot_cycle	= 1,
+	.tsi_prebias	= 6,
+	.pen_prebias	= 16,
+	.pen_prechg	= 2,
+	.res_x		= 300,
+};
+
+static struct pm860x_backlight_pdata evb3_backlight[] = {
+	{
+		.id	= PM8606_ID_BACKLIGHT,
+		.iset	= PM8606_WLED_CURRENT(24),
+		.flags	= PM8606_BACKLIGHT1,
+	},
+	{},
+};
+
+static struct pm860x_led_pdata evb3_led[] = {
+	{
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED1_RED,
+	}, {
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED1_GREEN,
+	}, {
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED1_BLUE,
+	}, {
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED2_RED,
+	}, {
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED2_GREEN,
+	}, {
+		.id	= PM8606_ID_LED,
+		.iset	= PM8606_LED_CURRENT(12),
+		.flags	= PM8606_LED2_BLUE,
+	},
+};
+
+static struct pm860x_platform_data evb3_pm8607_info = {
+	.touch				= &evb3_touch,
+	.backlight			= &evb3_backlight[0],
+	.led				= &evb3_led[0],
+	.companion_addr			= 0x10,
+	.irq_mode			= 0,
+	.irq_base			= IRQ_BOARD_START,
+
+	.i2c_port			= GI2C_PORT,
+};
+
+static struct i2c_board_info evb3_i2c_info[] = {
+	{
+		.type		= "88PM860x",
+		.addr		= 0x34,
+		.platform_data	= &evb3_pm8607_info,
+		.irq		= gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)),
+	},
+};
+
+static void __init evb3_init_i2c(void)
+{
+	pxa_set_i2c_info(NULL);
+	i2c_register_board_info(0, ARRAY_AND_SIZE(evb3_i2c_info));
+}
+#else
+static inline void evb3_init_i2c(void) {}
+#endif
+
+static void __init evb3_init(void)
+{
+	/* initialize MFP configurations */
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(evb3_mfp_cfg));
+
+	pxa_set_ffuart_info(NULL);
+
+	evb3_init_i2c();
+}
+
+MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
+	.boot_params	= 0xa0000100,
+	.map_io         = pxa_map_io,
+	.nr_irqs	= TAVOREVB3_NR_IRQS,
+	.init_irq       = pxa3xx_init_irq,
+	.timer          = &pxa_timer,
+	.init_machine   = evb3_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 83cc3a1..0ee1df4 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -952,10 +952,9 @@
 }
 
 MACHINE_START(TOSA, "SHARP Tosa")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup          = fixup_tosa,
 	.map_io         = pxa_map_io,
+	.nr_irqs	= TOSA_NR_IRQS,
 	.init_irq       = pxa25x_init_irq,
 	.init_machine   = tosa_init,
 	.timer          = &pxa_timer,
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 0acff17..565d062 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -555,8 +555,6 @@
 
 MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
 	/* MAINTAINER("Jürgen Schindele") */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= TRIZEPS4_SDRAM_BASE + 0x100,
 	.init_machine	= trizeps4_init,
 	.map_io		= trizeps4_map_io,
@@ -566,8 +564,6 @@
 
 MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
 	/* MAINTAINER("Jürgen Schindele") */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= TRIZEPS4_SDRAM_BASE + 0x100,
 	.init_machine	= trizeps4_init,
 	.map_io		= trizeps4_map_io,
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index e90114a..438fc9a 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -992,8 +992,6 @@
 
 MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
 	/* Maintainer: Marc Zyngier <maz@misterjones.org> */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= viper_map_io,
 	.init_irq	= viper_init_irq,
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index c9b747c..f45ac09 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -240,6 +240,7 @@
 #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
 static struct pxamci_platform_data vpac270_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.gpio_power		= -1,
 	.gpio_card_detect	= GPIO53_VPAC270_SD_DETECT_N,
 	.gpio_card_ro		= GPIO52_VPAC270_SD_READONLY,
 	.detect_delay_ms	= 200,
@@ -717,8 +718,6 @@
 }
 
 MACHINE_START(VPAC270, "Voipac PXA270")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/xcep.c b/arch/arm/mach-pxa/xcep.c
index d3b4e3f..3260ce7 100644
--- a/arch/arm/mach-pxa/xcep.c
+++ b/arch/arm/mach-pxa/xcep.c
@@ -181,8 +181,6 @@
 }
 
 MACHINE_START(XCEP, "Iskratel XCEP")
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= 0xa0000100,
 	.init_machine	= xcep_init,
 	.map_io		= pxa_map_io,
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index f0d0228..fefde98 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -37,7 +37,7 @@
 #include <mach/z2.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <mach/pxa2xx_spi.h>
 
 #include <plat/i2c.h>
@@ -703,9 +703,7 @@
 }
 
 MACHINE_START(ZIPIT2, "Zipit Z2")
-	.phys_io	= 0x40000000,
 	.boot_params	= 0xa0000100,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index 03b9cb9..dea46a2 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -900,10 +900,9 @@
 
 MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
 	/* Maintainer: Marc Zyngier <maz@misterjones.org> */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= ((io_p2v(0x40000000) >> 18) & 0xfffc),
 	.boot_params	= 0xa0000100,
 	.map_io		= zeus_map_io,
+	.nr_irqs	= ZEUS_NR_IRQS,
 	.init_irq	= zeus_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= zeus_init,
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index c479cbe..f25fb62 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -30,7 +30,7 @@
 #include <mach/zylonite.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 #include <plat/pxa3xx_nand.h>
 
 #include "devices.h"
@@ -411,10 +411,9 @@
 }
 
 MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
-	.phys_io	= 0x40000000,
 	.boot_params	= 0xa0000100,
-	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.map_io		= pxa_map_io,
+	.nr_irqs	= ZYLONITE_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= zylonite_init,
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 2fa38df..07c0815 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -259,6 +259,7 @@
 	.status		= realview_mmc_status,
 	.gpio_wp	= 17,
 	.gpio_cd	= 16,
+	.cd_invert	= true,
 };
 
 struct mmci_platform_data realview_mmc1_plat_data = {
@@ -266,6 +267,7 @@
 	.status		= realview_mmc_status,
 	.gpio_wp	= 19,
 	.gpio_cd	= 18,
+	.cd_invert	= true,
 };
 
 /*
diff --git a/arch/arm/mach-realview/include/mach/debug-macro.S b/arch/arm/mach-realview/include/mach/debug-macro.S
index 8662228..90b687c 100644
--- a/arch/arm/mach-realview/include/mach/debug-macro.S
+++ b/arch/arm/mach-realview/include/mach/debug-macro.S
@@ -33,12 +33,10 @@
 #error "Unknown RealView platform"
 #endif
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx,      #0x10000000
-		movne	\rx,      #0xfb000000	@ virtual base
-		orr	\rx, \rx, #DEBUG_LL_UART_OFFSET
+		.macro	addruart, rp, rv
+		mov	\rp, #DEBUG_LL_UART_OFFSET
+		orr	\rv, \rp, #0xfb000000	@ virtual base
+		orr	\rp, \rp, #0x10000000	@ physical base
 		.endm
 
 #include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-realview/include/mach/smp.h b/arch/arm/mach-realview/include/mach/smp.h
index dd53892..d3cd265 100644
--- a/arch/arm/mach-realview/include/mach/smp.h
+++ b/arch/arm/mach-realview/include/mach/smp.h
@@ -1,16 +1,8 @@
 #ifndef ASMARM_ARCH_SMP_H
 #define ASMARM_ARCH_SMP_H
 
-
 #include <asm/hardware/gic.h>
-
-#define hard_smp_processor_id()			\
-	({						\
-		unsigned int cpunum;			\
-		__asm__("mrc p15, 0, %0, c0, c0, 5"	\
-			: "=r" (cpunum));		\
-		cpunum &= 0x0F;				\
-	})
+#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 991c1f8..f269710 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -486,8 +486,6 @@
 
 MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.phys_io	= REALVIEW_EB_UART0_BASE & SECTION_MASK,
-	.io_pg_offst	= (IO_ADDRESS(REALVIEW_EB_UART0_BASE) >> 18) & 0xfffc,
 	.boot_params	= PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_eb_map_io,
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index d2be12e..a412561 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -378,8 +378,6 @@
 
 MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.phys_io	= REALVIEW_PB1176_UART0_BASE & SECTION_MASK,
-	.io_pg_offst	= (IO_ADDRESS(REALVIEW_PB1176_UART0_BASE) >> 18) & 0xfffc,
 	.boot_params	= PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_pb1176_fixup,
 	.map_io		= realview_pb1176_map_io,
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index d591bc0..117b95b 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -381,8 +381,6 @@
 
 MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.phys_io	= REALVIEW_PB11MP_UART0_BASE & SECTION_MASK,
-	.io_pg_offst	= (IO_ADDRESS(REALVIEW_PB11MP_UART0_BASE) >> 18) & 0xfffc,
 	.boot_params	= PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_pb11mp_map_io,
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 6c37621..929b8dc 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -331,8 +331,6 @@
 
 MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.phys_io	= REALVIEW_PBA8_UART0_BASE & SECTION_MASK,
-	.io_pg_offst	= (IO_ADDRESS(REALVIEW_PBA8_UART0_BASE) >> 18) & 0xfffc,
 	.boot_params	= PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_pba8_map_io,
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 9428eff..b9f9e20 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -417,8 +417,6 @@
 
 MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.phys_io	= REALVIEW_PBX_UART0_BASE & SECTION_MASK,
-	.io_pg_offst	= (IO_ADDRESS(REALVIEW_PBX_UART0_BASE) >> 18) & 0xfffc,
 	.boot_params	= PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_pbx_fixup,
 	.map_io		= realview_pbx_map_io,
diff --git a/arch/arm/mach-rpc/include/mach/debug-macro.S b/arch/arm/mach-rpc/include/mach/debug-macro.S
index 6fc8d66..85effff 100644
--- a/arch/arm/mach-rpc/include/mach/debug-macro.S
+++ b/arch/arm/mach-rpc/include/mach/debug-macro.S
@@ -11,13 +11,11 @@
  *
 */
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x03000000
-		movne	\rx, #0xe0000000
-		orr	\rx, \rx, #0x00010000
-		orr	\rx, \rx, #0x00000fe0
+		.macro	addruart, rp, rv
+		mov	\rp, #0x00010000
+		orr	\rp, \rp, #0x00000fe0
+		orr	\rv, \rp, #0xe0000000	@ virtual
+		orr	\rp, \rp, #0x03000000	@ physical
 		.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-rpc/include/mach/vmalloc.h b/arch/arm/mach-rpc/include/mach/vmalloc.h
index 9a96fd6..3bcd86f 100644
--- a/arch/arm/mach-rpc/include/mach/vmalloc.h
+++ b/arch/arm/mach-rpc/include/mach/vmalloc.h
@@ -7,4 +7,4 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x1c000000)
+#define VMALLOC_END       0xdc000000
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index c7fc01e..580b3c7 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -218,8 +218,6 @@
 
 MACHINE_START(RISCPC, "Acorn-RiscPC")
 	/* Maintainer: Russell King */
-	.phys_io	= 0x03000000,
-	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
 	.boot_params	= 0x10000100,
 	.reserve_lp0	= 1,
 	.reserve_lp1	= 1,
diff --git a/arch/arm/mach-s3c2410/include/mach/debug-macro.S b/arch/arm/mach-s3c2410/include/mach/debug-macro.S
index 0eef78b..5882dea 100644
--- a/arch/arm/mach-s3c2410/include/mach/debug-macro.S
+++ b/arch/arm/mach-s3c2410/include/mach/debug-macro.S
@@ -19,13 +19,12 @@
 #define S3C2410_UART1_OFF (0x4000)
 #define SHIFT_2440TXF (14-9)
 
-	.macro addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1
-		ldreq	\rx, = S3C24XX_PA_UART
-		ldrne	\rx, = S3C24XX_VA_UART
+	.macro addruart, rp, rv
+		ldr	\rp, = S3C24XX_PA_UART
+		ldr	\rv, = S3C24XX_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-		add	\rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+		add	\rp, \rp, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
 #endif
 	.endm
 
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index 34fc05a..44440cb 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -241,8 +241,6 @@
 }
 
 MACHINE_START(AML_M5900, "AML_M5900")
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= amlm5900_map_io,
 	.init_irq	= s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index c1f90f6..2970ea9 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -664,8 +664,6 @@
 
 MACHINE_START(BAST, "Simtec-BAST")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= bast_map_io,
 	.init_irq	= s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 3ba3bab..98c5c9e 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -350,8 +350,6 @@
 
 MACHINE_START(H1940, "IPAQ-H1940")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= h1940_map_io,
 	.reserve	= h1940_reserve,
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 41f299d..271b9aa 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -605,8 +605,6 @@
 	/* Maintainer: Christer Weinigel <christer@weinigel.se>,
 				Ben Dooks <ben-linux@fluff.org>
 	*/
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.timer		= &s3c24xx_timer,
 	.init_machine	= n30_init,
@@ -617,8 +615,6 @@
 MACHINE_START(N35, "Acer-N35")
 	/* Maintainer: Christer Weinigel <christer@weinigel.se>
 	*/
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.timer		= &s3c24xx_timer,
 	.init_machine	= n30_init,
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index d8c7f2e..0aa16cd 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -116,8 +116,6 @@
 
 MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
 	/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= otom11_map_io,
 	.init_machine	= otom11_init,
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
index d0e87b6..e8f49fe 100644
--- a/arch/arm/mach-s3c2410/mach-qt2410.c
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -362,8 +362,6 @@
 }
 
 MACHINE_START(QT2410, "QT2410")
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= qt2410_map_io,
 	.init_irq	= s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 4522230..e17f033 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -111,8 +111,6 @@
 MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
 				    * to SMDK2410 */
 	/* Maintainer: Jonas Dietsche */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= smdk2410_map_io,
 	.init_irq	= s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-tct_hammer.c b/arch/arm/mach-s3c2410/mach-tct_hammer.c
index 929164a..a15d062 100644
--- a/arch/arm/mach-s3c2410/mach-tct_hammer.c
+++ b/arch/arm/mach-s3c2410/mach-tct_hammer.c
@@ -152,8 +152,6 @@
 }
 
 MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= tct_hammer_map_io,
 	.init_irq	= s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index d540d79..6ccce5a 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -400,8 +400,6 @@
 
 MACHINE_START(VR1000, "Thorcom-VR1000")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= vr1000_map_io,
 	.init_machine	= vr1000_init,
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index 478f4b4..923e01b 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -675,8 +675,6 @@
 
 MACHINE_START(JIVE, "JIVE")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2412/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c
index 054c9f9..8e5758b 100644
--- a/arch/arm/mach-s3c2412/mach-smdk2413.c
+++ b/arch/arm/mach-s3c2412/mach-smdk2413.c
@@ -150,8 +150,6 @@
 
 MACHINE_START(S3C2413, "S3C2413")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 
 	.fixup		= smdk2413_fixup,
@@ -163,8 +161,6 @@
 
 MACHINE_START(SMDK2412, "SMDK2412")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 
 	.fixup		= smdk2413_fixup,
@@ -176,8 +172,6 @@
 
 MACHINE_START(SMDK2413, "SMDK2413")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 
 	.fixup		= smdk2413_fixup,
diff --git a/arch/arm/mach-s3c2412/mach-vstms.c b/arch/arm/mach-s3c2412/mach-vstms.c
index f291ac2..83544eb 100644
--- a/arch/arm/mach-s3c2412/mach-vstms.c
+++ b/arch/arm/mach-s3c2412/mach-vstms.c
@@ -156,8 +156,6 @@
 }
 
 MACHINE_START(VSTMS, "VSTMS")
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 
 	.fixup		= vstms_fixup,
diff --git a/arch/arm/mach-s3c2416/mach-smdk2416.c b/arch/arm/mach-s3c2416/mach-smdk2416.c
index 5fc3f67..7fc3664 100644
--- a/arch/arm/mach-s3c2416/mach-smdk2416.c
+++ b/arch/arm/mach-s3c2416/mach-smdk2416.c
@@ -195,8 +195,6 @@
 
 MACHINE_START(SMDK2416, "SMDK2416")
 	/* Maintainer: Yauhen Kharuzhy <jekhor@gmail.com> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index b73f78a..d708678 100644
--- a/arch/arm/mach-s3c2440/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -498,8 +498,6 @@
 
 MACHINE_START(ANUBIS, "Simtec-Anubis")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= anubis_map_io,
 	.init_machine	= anubis_init,
diff --git a/arch/arm/mach-s3c2440/mach-at2440evb.c b/arch/arm/mach-s3c2440/mach-at2440evb.c
index 8472579..e3810c8 100644
--- a/arch/arm/mach-s3c2440/mach-at2440evb.c
+++ b/arch/arm/mach-s3c2440/mach-at2440evb.c
@@ -233,8 +233,6 @@
 
 
 MACHINE_START(AT2440EVB, "AT2440EVB")
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= at2440evb_map_io,
 	.init_machine	= at2440evb_init,
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index deaabe8..9f2c14e 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -572,8 +572,6 @@
 
 MACHINE_START(NEO1973_GTA02, "GTA02")
 	/* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= gta02_map_io,
 	.init_irq	= s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c
index a76bcda..f62bb4c 100644
--- a/arch/arm/mach-s3c2440/mach-mini2440.c
+++ b/arch/arm/mach-s3c2440/mach-mini2440.c
@@ -691,8 +691,6 @@
 
 MACHINE_START(MINI2440, "MINI2440")
 	/* Maintainer: Michel Pollet <buserror@gmail.com> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= mini2440_map_io,
 	.init_machine	= mini2440_init,
diff --git a/arch/arm/mach-s3c2440/mach-nexcoder.c b/arch/arm/mach-s3c2440/mach-nexcoder.c
index 3ff62de..37dd306 100644
--- a/arch/arm/mach-s3c2440/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2440/mach-nexcoder.c
@@ -151,8 +151,6 @@
 
 MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
 	/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= nexcoder_map_io,
 	.init_machine	= nexcoder_init,
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index 319458d..14dc678 100644
--- a/arch/arm/mach-s3c2440/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -455,8 +455,6 @@
 
 MACHINE_START(OSIRIS, "Simtec-OSIRIS")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= osiris_map_io,
 	.init_irq	= s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-rx1950.c b/arch/arm/mach-s3c2440/mach-rx1950.c
index 142d1f9..32019bd 100644
--- a/arch/arm/mach-s3c2440/mach-rx1950.c
+++ b/arch/arm/mach-s3c2440/mach-rx1950.c
@@ -580,8 +580,6 @@
 
 MACHINE_START(RX1950, "HP iPAQ RX1950")
     /* Maintainers: Vasily Khoruzhick */
-    .phys_io = S3C2410_PA_UART,
-	.io_pg_offst = (((u32) S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params = S3C2410_SDRAM_PA + 0x100,
 	.map_io = rx1950_map_io,
 	.reserve	= rx1950_reserve,
diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index 6bb44f7..1472b1a 100644
--- a/arch/arm/mach-s3c2440/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -218,8 +218,6 @@
 
 MACHINE_START(RX3715, "IPAQ-RX3715")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= rx3715_map_io,
 	.reserve	= rx3715_reserve,
diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c
index df83276..eedfe0f 100644
--- a/arch/arm/mach-s3c2440/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2440/mach-smdk2440.c
@@ -175,8 +175,6 @@
 
 MACHINE_START(S3C2440, "SMDK2440")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c
index 4c863d3..4337f0a 100644
--- a/arch/arm/mach-s3c2443/mach-smdk2443.c
+++ b/arch/arm/mach-s3c2443/mach-smdk2443.c
@@ -132,8 +132,6 @@
 
 MACHINE_START(SMDK2443, "SMDK2443")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 
 	.init_irq	= s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S
index 239476b..0c5a738 100644
--- a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S
+++ b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S
@@ -10,13 +10,12 @@
 #include <mach/map.h>
 #include <plat/regs-serial.h>
 
-	.macro addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1
-		ldreq	\rx, = S3C24XX_PA_UART
-		ldrne	\rx, = S3C24XX_VA_UART
+	.macro addruart, rp, rv
+		ldr	\rp, = S3C24XX_PA_UART
+		ldr	\rv, = S3C24XX_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-		add	\rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+		add	\rp, \rp, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
 #endif
 	.endm
 
diff --git a/arch/arm/mach-s3c64xx/include/mach/debug-macro.S b/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
index f9ab5d2..a29e705 100644
--- a/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
@@ -21,13 +21,12 @@
 	 * aligned and add in the offset when we load the value here.
 	 */
 
-	.macro addruart, rx, rtmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1
-		ldreq	\rx, = S3C_PA_UART
-		ldrne	\rx, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
+	.macro addruart, rp, rv
+		ldr	\rp, = S3C_PA_UART
+		ldr	\rv, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
 #if CONFIG_DEBUG_S3C_UART != 0
-		add	\rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+		add	\rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
 #endif
 	.endm
 
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index 742dc87..a53cf14 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -233,8 +233,6 @@
 
 MACHINE_START(ANW6410, "A&W6410")
 	/* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
 
 	.init_irq	= s3c6410_init_irq,
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index fba9022..b263958 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -265,8 +265,6 @@
 
 MACHINE_START(HMT, "Airgoo-HMT")
 	/* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= hmt_map_io,
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index bf65747..c498649 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -97,8 +97,6 @@
 
 MACHINE_START(NCP, "NCP")
 	/* Maintainer: Samsung Electronics */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= ncp_map_io,
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index e130379..4b4475d 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -141,8 +141,6 @@
 
 MACHINE_START(REAL6410, "REAL6410")
 	/* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
 
 	.init_irq	= s3c6410_init_irq,
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index 3a9639b..cb1ebeb 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -136,7 +136,7 @@
 	.dev.platform_data	= &smartq_usb_otg_vbus_pdata,
 };
 
-static int __init smartq_bl_init(struct device *dev)
+static int smartq_bl_init(struct device *dev)
 {
     s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2));
 
diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c
index a4d59b0..3a3e5ac 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq5.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq5.c
@@ -32,7 +32,7 @@
 
 #include "mach-smartq.h"
 
-static struct gpio_led smartq5_leds[] __initdata = {
+static struct gpio_led smartq5_leds[] = {
 	{
 		.name			= "smartq5:green",
 		.active_low		= 1,
@@ -146,8 +146,6 @@
 
 MACHINE_START(SMARTQ5, "SmartQ 5")
 	/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= smartq_map_io,
diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c
index e50a7d7..e653758 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq7.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq7.c
@@ -32,7 +32,7 @@
 
 #include "mach-smartq.h"
 
-static struct gpio_led smartq7_leds[] __initdata = {
+static struct gpio_led smartq7_leds[] = {
 	{
 		.name			= "smartq7:red",
 		.active_low		= 1,
@@ -162,8 +162,6 @@
 
 MACHINE_START(SMARTQ7, "SmartQ 7")
 	/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
 	.init_irq	= s3c6410_init_irq,
 	.map_io		= smartq_map_io,
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
index 5991667..3cca642 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6400.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -85,8 +85,6 @@
 
 MACHINE_START(SMDK6400, "SMDK6400")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
 
 	.init_irq	= s3c6400_init_irq,
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index d498219..ec8865c 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -704,8 +704,6 @@
 
 MACHINE_START(SMDK6410, "SMDK6410")
 	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
 
 	.init_irq	= s3c6410_init_irq,
diff --git a/arch/arm/mach-s5p6440/Kconfig b/arch/arm/mach-s5p6440/Kconfig
deleted file mode 100644
index 6a4af7f..0000000
--- a/arch/arm/mach-s5p6440/Kconfig
+++ /dev/null
@@ -1,33 +0,0 @@
-# arch/arm/mach-s5p6440/Kconfig
-#
-# Copyright (c) 2009 Samsung Electronics Co., Ltd.
-#		http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-if ARCH_S5P6440
-
-config CPU_S5P6440
-	bool
-	select S3C_PL330_DMA
-	help
-	  Enable S5P6440 CPU support
-
-config S5P6440_SETUP_I2C1
-	bool
-	help
-	  Common setup code for i2c bus 1.
-
-config MACH_SMDK6440
-	bool "SMDK6440"
-	select CPU_S5P6440
-	select S3C_DEV_I2C1
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select SAMSUNG_DEV_ADC
-	select SAMSUNG_DEV_TS
-	select S5P6440_SETUP_I2C1
-	help
-	  Machine support for the Samsung SMDK6440
-
-endif
diff --git a/arch/arm/mach-s5p6440/Makefile b/arch/arm/mach-s5p6440/Makefile
deleted file mode 100644
index c3fe4d3..0000000
--- a/arch/arm/mach-s5p6440/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-# arch/arm/mach-s5p6440/Makefile
-#
-# Copyright (c) 2009 Samsung Electronics Co., Ltd.
-# 		http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-# Core support for S5P6440 system
-
-obj-$(CONFIG_CPU_S5P6440)	+= cpu.o init.o clock.o gpio.o dma.o
-obj-$(CONFIG_CPU_S5P6440)	+= setup-i2c0.o
-
-# machine support
-
-obj-$(CONFIG_MACH_SMDK6440)	+= mach-smdk6440.o
-
-# device support
-obj-y				+= dev-audio.o
-obj-$(CONFIG_S3C64XX_DEV_SPI)	+= dev-spi.o
-obj-$(CONFIG_S5P6440_SETUP_I2C1)	+= setup-i2c1.o
diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c
deleted file mode 100644
index ca6e48d..0000000
--- a/arch/arm/mach-s5p6440/clock.c
+++ /dev/null
@@ -1,846 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/clock.c
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - 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/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/sysdev.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <plat/cpu-freq.h>
-#include <mach/regs-clock.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/clock-clksrc.h>
-#include <plat/s5p-clock.h>
-#include <plat/pll.h>
-#include <plat/s5p6440.h>
-
-/* APLL Mux output clock */
-static struct clksrc_clk clk_mout_apll = {
-	.clk    = {
-		.name           = "mout_apll",
-		.id             = -1,
-	},
-	.sources        = &clk_src_apll,
-	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
-};
-
-static int s5p6440_epll_enable(struct clk *clk, int enable)
-{
-	unsigned int ctrlbit = clk->ctrlbit;
-	unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
-
-	if (enable)
-		__raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
-	else
-		__raw_writel(epll_con, S5P_EPLL_CON);
-
-	return 0;
-}
-
-static unsigned long s5p6440_epll_get_rate(struct clk *clk)
-{
-	return clk->rate;
-}
-
-static u32 epll_div[][5] = {
-	{ 36000000,	0,	48, 1, 4 },
-	{ 48000000,	0,	32, 1, 3 },
-	{ 60000000,	0,	40, 1, 3 },
-	{ 72000000,	0,	48, 1, 3 },
-	{ 84000000,	0,	28, 1, 2 },
-	{ 96000000,	0,	32, 1, 2 },
-	{ 32768000,	45264,	43, 1, 4 },
-	{ 45158000,	6903,	30, 1, 3 },
-	{ 49152000,	50332,	32, 1, 3 },
-	{ 67738000,	10398,	45, 1, 3 },
-	{ 73728000,	9961,	49, 1, 3 }
-};
-
-static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned int epll_con, epll_con_k;
-	unsigned int i;
-
-	if (clk->rate == rate)	/* Return if nothing changed */
-		return 0;
-
-	epll_con = __raw_readl(S5P_EPLL_CON);
-	epll_con_k = __raw_readl(S5P_EPLL_CON_K);
-
-	epll_con_k &= ~(PLL90XX_KDIV_MASK);
-	epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
-
-	for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
-		 if (epll_div[i][0] == rate) {
-			epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
-			epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
-				    (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
-				    (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(epll_div)) {
-		printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
-		return -EINVAL;
-	}
-
-	__raw_writel(epll_con, S5P_EPLL_CON);
-	__raw_writel(epll_con_k, S5P_EPLL_CON_K);
-
-	clk->rate = rate;
-
-	return 0;
-}
-
-static struct clk_ops s5p6440_epll_ops = {
-	.get_rate = s5p6440_epll_get_rate,
-	.set_rate = s5p6440_epll_set_rate,
-};
-
-static struct clksrc_clk clk_mout_epll = {
-	.clk    = {
-		.name           = "mout_epll",
-		.id             = -1,
-	},
-	.sources        = &clk_src_epll,
-	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 2, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_mpll = {
-	.clk = {
-		.name           = "mout_mpll",
-		.id             = -1,
-	},
-	.sources        = &clk_src_mpll,
-	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 1, .size = 1 },
-};
-
-enum perf_level {
-	L0 = 532*1000,
-	L1 = 266*1000,
-	L2 = 133*1000,
-};
-
-static const u32 clock_table[][3] = {
-	/*{ARM_CLK, DIVarm, DIVhclk}*/
-	{L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P_CLKDIV0_HCLK_SHIFT)},
-	{L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P_CLKDIV0_HCLK_SHIFT)},
-	{L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P_CLKDIV0_HCLK_SHIFT)},
-};
-
-static unsigned long s5p6440_armclk_get_rate(struct clk *clk)
-{
-	unsigned long rate = clk_get_rate(clk->parent);
-	u32 clkdiv;
-
-	/* divisor mask starts at bit0, so no need to shift */
-	clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK;
-
-	return rate / (clkdiv + 1);
-}
-
-static unsigned long s5p6440_armclk_round_rate(struct clk *clk,
-						unsigned long rate)
-{
-	u32 iter;
-
-	for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
-		if (rate > clock_table[iter][0])
-			return clock_table[iter-1][0];
-	}
-
-	return clock_table[ARRAY_SIZE(clock_table) - 1][0];
-}
-
-static int s5p6440_armclk_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 round_tmp;
-	u32 iter;
-	u32 clk_div0_tmp;
-	u32 cur_rate = clk->ops->get_rate(clk);
-	unsigned long flags;
-
-	round_tmp = clk->ops->round_rate(clk, rate);
-	if (round_tmp == cur_rate)
-		return 0;
-
-
-	for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
-		if (round_tmp == clock_table[iter][0])
-			break;
-	}
-
-	if (iter >= ARRAY_SIZE(clock_table))
-		iter = ARRAY_SIZE(clock_table) - 1;
-
-	local_irq_save(flags);
-	if (cur_rate > round_tmp) {
-		/* Frequency Down */
-		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
-		clk_div0_tmp |= clock_table[iter][1];
-		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
-		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
-				~(S5P_CLKDIV0_HCLK_MASK);
-		clk_div0_tmp |= clock_table[iter][2];
-		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
-
-	} else {
-		/* Frequency Up */
-		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
-				~(S5P_CLKDIV0_HCLK_MASK);
-		clk_div0_tmp |= clock_table[iter][2];
-		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
-		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
-		clk_div0_tmp |= clock_table[iter][1];
-		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-		}
-	local_irq_restore(flags);
-
-	clk->rate = clock_table[iter][0];
-
-	return 0;
-}
-
-static struct clk_ops s5p6440_clkarm_ops = {
-	.get_rate	= s5p6440_armclk_get_rate,
-	.set_rate	= s5p6440_armclk_set_rate,
-	.round_rate	= s5p6440_armclk_round_rate,
-};
-
-static struct clksrc_clk clk_armclk = {
-	.clk	= {
-		.name	= "armclk",
-		.id	= 1,
-		.parent	= &clk_mout_apll.clk,
-		.ops	= &s5p6440_clkarm_ops,
-	},
-	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mpll = {
-	.clk	= {
-		.name	= "dout_mpll",
-		.id	= -1,
-		.parent	= &clk_mout_mpll.clk,
-	},
-	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk clk_hclk = {
-	.clk	= {
-		.name	= "clk_hclk",
-		.id	= -1,
-		.parent	= &clk_armclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk = {
-	.clk	= {
-		.name	= "clk_pclk",
-		.id	= -1,
-		.parent	= &clk_hclk.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 4 },
-};
-
-static struct clk *clkset_hclklow_list[] = {
-	&clk_mout_apll.clk,
-	&clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_hclklow = {
-	.sources	= clkset_hclklow_list,
-	.nr_sources	= ARRAY_SIZE(clkset_hclklow_list),
-};
-
-static struct clksrc_clk clk_hclk_low = {
-	.clk = {
-		.name	= "hclk_low",
-		.id	= -1,
-	},
-	.sources	= &clkset_hclklow,
-	.reg_src	= { .reg = S5P_SYS_OTHERS, .shift = 6, .size = 1 },
-	.reg_div	= { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_low = {
-	.clk	= {
-		.name	= "pclk_low",
-		.id	= -1,
-		.parent	= &clk_hclk_low.clk,
-	},
-	.reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
-};
-
-int s5p6440_clk48m_ctrl(struct clk *clk, int enable)
-{
-	unsigned long flags;
-	u32 val;
-
-	/* can't rely on clock lock, this register has other usages */
-	local_irq_save(flags);
-
-	val = __raw_readl(S5P_OTHERS);
-	if (enable)
-		val |= S5P_OTHERS_USB_SIG_MASK;
-	else
-		val &= ~S5P_OTHERS_USB_SIG_MASK;
-
-	__raw_writel(val, S5P_OTHERS);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-static int s5p6440_pclk_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLK_GATE_PCLK, clk, enable);
-}
-
-static int s5p6440_hclk0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLK_GATE_HCLK0, clk, enable);
-}
-
-static int s5p6440_hclk1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLK_GATE_HCLK1, clk, enable);
-}
-
-static int s5p6440_sclk_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLK_GATE_SCLK0, clk, enable);
-}
-
-static int s5p6440_sclk1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLK_GATE_SCLK1, clk, enable);
-}
-
-static int s5p6440_mem_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLK_GATE_MEM0, clk, enable);
-}
-
-/*
- * The following clocks will be disabled during clock initialization. It is
- * recommended to keep the following clocks disabled until the driver requests
- * for enabling the clock.
- */
-static struct clk init_clocks_disable[] = {
-	{
-		.name		= "nand",
-		.id		= -1,
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p6440_mem_ctrl,
-		.ctrlbit	= S5P_CLKCON_MEM0_HCLK_NFCON,
-	}, {
-		.name		= "adc",
-		.id		= -1,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_TSADC,
-	}, {
-		.name		= "i2c",
-		.id		= -1,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_IIC0,
-	}, {
-		.name		= "i2s_v40",
-		.id		= 0,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_IIS2,
-	}, {
-		.name		= "spi",
-		.id		= 0,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_SPI0,
-	}, {
-		.name		= "spi",
-		.id		= 1,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_SPI1,
-	}, {
-		.name		= "sclk_spi_48",
-		.id		= 0,
-		.parent		= &clk_48m,
-		.enable		= s5p6440_sclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_SCLK0_SPI0_48,
-	}, {
-		.name		= "sclk_spi_48",
-		.id		= 1,
-		.parent		= &clk_48m,
-		.enable		= s5p6440_sclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_SCLK0_SPI1_48,
-	}, {
-		.name		= "mmc_48m",
-		.id		= 0,
-		.parent		= &clk_48m,
-		.enable		= s5p6440_sclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_SCLK0_MMC0_48,
-	}, {
-		.name		= "mmc_48m",
-		.id		= 1,
-		.parent		= &clk_48m,
-		.enable		= s5p6440_sclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_SCLK0_MMC1_48,
-	}, {
-		.name		= "mmc_48m",
-		.id		= 2,
-		.parent		= &clk_48m,
-		.enable		= s5p6440_sclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_SCLK0_MMC2_48,
-	}, {
-		.name    	= "otg",
-		.id	   	= -1,
-		.parent		= &clk_hclk_low.clk,
-		.enable  	= s5p6440_hclk0_ctrl,
-		.ctrlbit 	= S5P_CLKCON_HCLK0_USB
-	}, {
-		.name    	= "post",
-		.id	   	= -1,
-		.parent		= &clk_hclk_low.clk,
-		.enable  	= s5p6440_hclk0_ctrl,
-		.ctrlbit 	= S5P_CLKCON_HCLK0_POST0
-	}, {
-		.name		= "lcd",
-		.id		= -1,
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p6440_hclk1_ctrl,
-		.ctrlbit	= S5P_CLKCON_HCLK1_DISPCON,
-	}, {
-		.name		= "hsmmc",
-		.id		= 0,
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p6440_hclk0_ctrl,
-		.ctrlbit	= S5P_CLKCON_HCLK0_HSMMC0,
-	}, {
-		.name		= "hsmmc",
-		.id		= 1,
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p6440_hclk0_ctrl,
-		.ctrlbit	= S5P_CLKCON_HCLK0_HSMMC1,
-	}, {
-		.name		= "hsmmc",
-		.id		= 2,
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p6440_hclk0_ctrl,
-		.ctrlbit	= S5P_CLKCON_HCLK0_HSMMC2,
-	}, {
-		.name		= "rtc",
-		.id		= -1,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_RTC,
-	}, {
-		.name		= "watchdog",
-		.id		= -1,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_WDT,
-	}, {
-		.name		= "timers",
-		.id		= -1,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_PWM,
-	}, {
-		.name		= "hclk_fimgvg",
-		.id		= -1,
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p6440_hclk1_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "tsi",
-		.id		= -1,
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p6440_hclk1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "pclk_fimgvg",
-		.id		= -1,
-		.parent		= &clk_pclk.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= (1 << 31),
-	}, {
-		.name		= "dmc0",
-		.id		= -1,
-		.parent		= &clk_pclk.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= (1 << 30),
-	}, {
-		.name		= "etm",
-		.id		= -1,
-		.parent		= &clk_pclk.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= (1 << 29),
-	}, {
-		.name		= "dsim",
-		.id		= -1,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= (1 << 28),
-	}, {
-		.name		= "gps",
-		.id		= -1,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= (1 << 25),
-	}, {
-		.name		= "pcm",
-		.id		= -1,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "irom",
-		.id		= -1,
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p6440_hclk0_ctrl,
-		.ctrlbit	= (1 << 25),
-	}, {
-		.name		= "dma",
-		.id		= -1,
-		.parent		= &clk_hclk_low.clk,
-		.enable		= s5p6440_hclk0_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "2d",
-		.id		= -1,
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p6440_hclk0_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-};
-
-/*
- * The following clocks will be enabled during clock initialization.
- */
-static struct clk init_clocks[] = {
-	{
-		.name		= "gpio",
-		.id		= -1,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_GPIO,
-	}, {
-		.name		= "uart",
-		.id		= 0,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_UART0,
-	}, {
-		.name		= "uart",
-		.id		= 1,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_UART1,
-	}, {
-		.name		= "uart",
-		.id		= 2,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_UART2,
-	}, {
-		.name		= "uart",
-		.id		= 3,
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p6440_pclk_ctrl,
-		.ctrlbit	= S5P_CLKCON_PCLK_UART3,
-	}, {
-		.name		= "mem",
-		.id		= -1,
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p6440_hclk0_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "intc",
-		.id		= -1,
-		.parent		= &clk_hclk.clk,
-		.enable		= s5p6440_hclk0_ctrl,
-		.ctrlbit	= (1 << 1),
-	},
-};
-
-static struct clk clk_iis_cd_v40 = {
-	.name		= "iis_cdclk_v40",
-	.id		= -1,
-};
-
-static struct clk clk_pcm_cd = {
-	.name		= "pcm_cdclk",
-	.id		= -1,
-};
-
-static struct clk *clkset_group1_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll.clk,
-	&clk_fin_epll,
-};
-
-static struct clksrc_sources clkset_group1 = {
-	.sources	= clkset_group1_list,
-	.nr_sources	= ARRAY_SIZE(clkset_group1_list),
-};
-
-static struct clk *clkset_uart_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_uart = {
-	.sources	= clkset_uart_list,
-	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_audio_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll.clk,
-	&clk_fin_epll,
-	&clk_iis_cd_v40,
-	&clk_pcm_cd,
-};
-
-static struct clksrc_sources clkset_audio = {
-	.sources	= clkset_audio_list,
-	.nr_sources	= ARRAY_SIZE(clkset_audio_list),
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "mmc_bus",
-			.id		= 0,
-			.ctrlbit        = S5P_CLKCON_SCLK0_MMC0,
-			.enable		= s5p6440_sclk_ctrl,
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 18, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "mmc_bus",
-			.id		= 1,
-			.ctrlbit        = S5P_CLKCON_SCLK0_MMC1,
-			.enable		= s5p6440_sclk_ctrl,
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "mmc_bus",
-			.id		= 2,
-			.ctrlbit        = S5P_CLKCON_SCLK0_MMC2,
-			.enable		= s5p6440_sclk_ctrl,
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 22, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "uclk1",
-			.id		= -1,
-			.ctrlbit        = S5P_CLKCON_SCLK0_UART,
-			.enable		= s5p6440_sclk_ctrl,
-		},
-		.sources = &clkset_uart,
-		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 13, .size = 1 },
-		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "spi_epll",
-			.id		= 0,
-			.ctrlbit        = S5P_CLKCON_SCLK0_SPI0,
-			.enable		= s5p6440_sclk_ctrl,
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 14, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "spi_epll",
-			.id		= 1,
-			.ctrlbit        = S5P_CLKCON_SCLK0_SPI1,
-			.enable		= s5p6440_sclk_ctrl,
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_post",
-			.id		= -1,
-			.ctrlbit	= (1 << 10),
-			.enable		= s5p6440_sclk_ctrl,
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 26, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_dispcon",
-			.id		= -1,
-			.ctrlbit	= (1 << 1),
-			.enable		= s5p6440_sclk1_ctrl,
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimgvg",
-			.id		= -1,
-			.ctrlbit	= (1 << 2),
-			.enable		= s5p6440_sclk1_ctrl,
-		},
-		.sources = &clkset_group1,
-		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
-		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_audio2",
-			.id		= -1,
-			.ctrlbit	= (1 << 11),
-			.enable		= s5p6440_sclk_ctrl,
-		},
-		.sources = &clkset_audio,
-		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 3 },
-		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 24, .size = 4 },
-	},
-};
-
-/* Clock initialisation code */
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_apll,
-	&clk_mout_epll,
-	&clk_mout_mpll,
-	&clk_dout_mpll,
-	&clk_armclk,
-	&clk_hclk,
-	&clk_pclk,
-	&clk_hclk_low,
-	&clk_pclk_low,
-};
-
-void __init_or_cpufreq s5p6440_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long xtal;
-	unsigned long fclk;
-	unsigned long hclk;
-	unsigned long hclk_low;
-	unsigned long pclk;
-	unsigned long pclk_low;
-	unsigned long epll;
-	unsigned long apll;
-	unsigned long mpll;
-	unsigned int ptr;
-
-	/* Set S5P6440 functions for clk_fout_epll */
-	clk_fout_epll.enable = s5p6440_epll_enable;
-	clk_fout_epll.ops = &s5p6440_epll_ops;
-
-	clk_48m.enable = s5p6440_clk48m_ctrl;
-
-	xtal_clk = clk_get(NULL, "ext_xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-	clk_put(xtal_clk);
-
-	epll = s5p_get_pll90xx(xtal, __raw_readl(S5P_EPLL_CON),
-				__raw_readl(S5P_EPLL_CON_K));
-	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
-	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4502);
-
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_apll.rate = apll;
-
-	printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
-			" E=%ld.%ldMHz\n",
-			print_mhz(apll), print_mhz(mpll), print_mhz(epll));
-
-	fclk = clk_get_rate(&clk_armclk.clk);
-	hclk = clk_get_rate(&clk_hclk.clk);
-	pclk = clk_get_rate(&clk_pclk.clk);
-	hclk_low = clk_get_rate(&clk_hclk_low.clk);
-	pclk_low = clk_get_rate(&clk_pclk_low.clk);
-
-	printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
-			" PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
-			print_mhz(hclk), print_mhz(hclk_low),
-			print_mhz(pclk), print_mhz(pclk_low));
-
-	clk_f.rate = fclk;
-	clk_h.rate = hclk;
-	clk_p.rate = pclk;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-		s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks[] __initdata = {
-	&clk_ext,
-	&clk_iis_cd_v40,
-	&clk_pcm_cd,
-};
-
-void __init s5p6440_register_clocks(void)
-{
-	struct clk *clkp;
-	int ret;
-	int ptr;
-
-	ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-	if (ret > 0)
-		printk(KERN_ERR "Failed to register %u clocks\n", ret);
-
-	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));
-
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-		(clkp->enable)(clkp, 0);
-	}
-
-	s3c_pwmclk_init();
-}
diff --git a/arch/arm/mach-s5p6440/cpu.c b/arch/arm/mach-s5p6440/cpu.c
deleted file mode 100644
index 526f33a..0000000
--- a/arch/arm/mach-s5p6440/cpu.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/cpu.c
- *
- * Copyright (c) 2009 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/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/sysdev.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/proc-fns.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <asm/irq.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/clock.h>
-#include <plat/s5p6440.h>
-#include <plat/adc-core.h>
-
-static void s5p6440_idle(void)
-{
-	unsigned long val;
-
-	if (!need_resched()) {
-		val = __raw_readl(S5P_PWR_CFG);
-		val &= ~(0x3<<5);
-		val |= (0x1<<5);
-		__raw_writel(val, S5P_PWR_CFG);
-
-		cpu_do_idle();
-	}
-	local_irq_enable();
-}
-
-/* s5p6440_map_io
- *
- * register the standard cpu IO areas
-*/
-
-void __init s5p6440_map_io(void)
-{
-	/* initialize any device information early */
-	s3c_adc_setname("s3c64xx-adc");
-}
-
-void __init s5p6440_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-	s5p6440_register_clocks();
-	s5p6440_setup_clocks();
-}
-
-void __init s5p6440_init_irq(void)
-{
-	/* S5P6440 supports only 2 VIC */
-	u32 vic[2];
-
-	/*
-	 * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)]
-	 * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22]
-	 */
-	vic[0] = 0xff800ae7;
-	vic[1] = 0xffbf23e5;
-
-	s5p_init_irq(vic, ARRAY_SIZE(vic));
-}
-
-struct sysdev_class s5p6440_sysclass = {
-	.name	= "s5p6440-core",
-};
-
-static struct sys_device s5p6440_sysdev = {
-	.cls	= &s5p6440_sysclass,
-};
-
-static int __init s5p6440_core_init(void)
-{
-	return sysdev_class_register(&s5p6440_sysclass);
-}
-
-core_initcall(s5p6440_core_init);
-
-int __init s5p6440_init(void)
-{
-	printk(KERN_INFO "S5P6440: Initializing architecture\n");
-
-	/* set idle function */
-	pm_idle = s5p6440_idle;
-
-	return sysdev_register(&s5p6440_sysdev);
-}
diff --git a/arch/arm/mach-s5p6440/dev-audio.c b/arch/arm/mach-s5p6440/dev-audio.c
deleted file mode 100644
index 3ca0d2b..0000000
--- a/arch/arm/mach-s5p6440/dev-audio.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/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 int s5p6440_cfg_i2s(struct platform_device *pdev)
-{
-	/* configure GPIO for i2s port */
-	switch (pdev->id) {
-	case -1:
-		s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5));
-		s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5));
-		s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5));
-		s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5));
-		s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5));
-		s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5));
-		s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5));
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata s3c_i2s_pdata = {
-	.cfg_gpio = s5p6440_cfg_i2s,
-};
-
-static struct resource s5p6440_iis0_resource[] = {
-	[0] = {
-		.start = S5P6440_PA_I2S,
-		.end   = S5P6440_PA_I2S + 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,
-	},
-};
-
-struct platform_device s5p6440_device_iis = {
-	.name		  = "s3c64xx-iis-v4",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s5p6440_iis0_resource),
-	.resource	  = s5p6440_iis0_resource,
-	.dev = {
-		.platform_data = &s3c_i2s_pdata,
-	},
-};
-
-/* PCM Controller platform_devices */
-
-static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev)
-{
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2));
-		s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2));
-		s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2));
-		s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2));
-		s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2));
-		break;
-
-	default:
-		printk(KERN_DEBUG "Invalid PCM Controller number!");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata s3c_pcm_pdata = {
-	.cfg_gpio = s5p6440_pcm_cfg_gpio,
-};
-
-static struct resource s5p6440_pcm0_resource[] = {
-	[0] = {
-		.start = S5P6440_PA_PCM,
-		.end   = S5P6440_PA_PCM + 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 s5p6440_device_pcm = {
-	.name		  = "samsung-pcm",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s5p6440_pcm0_resource),
-	.resource	  = s5p6440_pcm0_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
diff --git a/arch/arm/mach-s5p6440/dev-spi.c b/arch/arm/mach-s5p6440/dev-spi.c
deleted file mode 100644
index 510af44..0000000
--- a/arch/arm/mach-s5p6440/dev-spi.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/dev-spi.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 <mach/dma.h>
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/spi-clocks.h>
-
-#include <plat/s3c64xx-spi.h>
-#include <plat/gpio-cfg.h>
-
-static char *spi_src_clks[] = {
-	[S5P6440_SPI_SRCCLK_PCLK] = "pclk",
-	[S5P6440_SPI_SRCCLK_SCLK] = "spi_epll",
-};
-
-/* SPI Controller platform_devices */
-
-/* Since we emulate multi-cs capability, we do not touch the CS.
- * The emulated CS is toggled by board specific mechanism, as it can
- * be either some immediate GPIO or some signal out of some other
- * chip in between ... or some yet another way.
- * We simply do not assume anything about CS.
- */
-static int s5p6440_spi_cfg_gpio(struct platform_device *pdev)
-{
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin(S5P6440_GPC(0), S3C_GPIO_SFN(2));
-		s3c_gpio_cfgpin(S5P6440_GPC(1), S3C_GPIO_SFN(2));
-		s3c_gpio_cfgpin(S5P6440_GPC(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(S5P6440_GPC(0), S3C_GPIO_PULL_UP);
-		s3c_gpio_setpull(S5P6440_GPC(1), S3C_GPIO_PULL_UP);
-		s3c_gpio_setpull(S5P6440_GPC(2), S3C_GPIO_PULL_UP);
-		break;
-
-	case 1:
-		s3c_gpio_cfgpin(S5P6440_GPC(4), S3C_GPIO_SFN(2));
-		s3c_gpio_cfgpin(S5P6440_GPC(5), S3C_GPIO_SFN(2));
-		s3c_gpio_cfgpin(S5P6440_GPC(6), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(S5P6440_GPC(4), S3C_GPIO_PULL_UP);
-		s3c_gpio_setpull(S5P6440_GPC(5), S3C_GPIO_PULL_UP);
-		s3c_gpio_setpull(S5P6440_GPC(6), S3C_GPIO_PULL_UP);
-		break;
-
-	default:
-		dev_err(&pdev->dev, "Invalid SPI Controller number!");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct resource s5p6440_spi0_resource[] = {
-	[0] = {
-		.start = S5P6440_PA_SPI0,
-		.end   = S5P6440_PA_SPI0 + 0x100 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = DMACH_SPI0_TX,
-		.end   = DMACH_SPI0_TX,
-		.flags = IORESOURCE_DMA,
-	},
-	[2] = {
-		.start = DMACH_SPI0_RX,
-		.end   = DMACH_SPI0_RX,
-		.flags = IORESOURCE_DMA,
-	},
-	[3] = {
-		.start = IRQ_SPI0,
-		.end   = IRQ_SPI0,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c64xx_spi_info s5p6440_spi0_pdata = {
-	.cfg_gpio = s5p6440_spi_cfg_gpio,
-	.fifo_lvl_mask = 0x1ff,
-	.rx_lvl_offset = 15,
-};
-
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5p6440_device_spi0 = {
-	.name		  = "s3c64xx-spi",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s5p6440_spi0_resource),
-	.resource	  = s5p6440_spi0_resource,
-	.dev = {
-		.dma_mask		= &spi_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data = &s5p6440_spi0_pdata,
-	},
-};
-
-static struct resource s5p6440_spi1_resource[] = {
-	[0] = {
-		.start = S5P6440_PA_SPI1,
-		.end   = S5P6440_PA_SPI1 + 0x100 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = DMACH_SPI1_TX,
-		.end   = DMACH_SPI1_TX,
-		.flags = IORESOURCE_DMA,
-	},
-	[2] = {
-		.start = DMACH_SPI1_RX,
-		.end   = DMACH_SPI1_RX,
-		.flags = IORESOURCE_DMA,
-	},
-	[3] = {
-		.start = IRQ_SPI1,
-		.end   = IRQ_SPI1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c64xx_spi_info s5p6440_spi1_pdata = {
-	.cfg_gpio = s5p6440_spi_cfg_gpio,
-	.fifo_lvl_mask = 0x7f,
-	.rx_lvl_offset = 15,
-};
-
-struct platform_device s5p6440_device_spi1 = {
-	.name		  = "s3c64xx-spi",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s5p6440_spi1_resource),
-	.resource	  = s5p6440_spi1_resource,
-	.dev = {
-		.dma_mask		= &spi_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data = &s5p6440_spi1_pdata,
-	},
-};
-
-void __init s5p6440_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
-{
-	struct s3c64xx_spi_info *pd;
-
-	/* Reject invalid configuration */
-	if (!num_cs || src_clk_nr < 0
-			|| src_clk_nr > S5P6440_SPI_SRCCLK_SCLK) {
-		printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
-		return;
-	}
-
-	switch (cntrlr) {
-	case 0:
-		pd = &s5p6440_spi0_pdata;
-		break;
-	case 1:
-		pd = &s5p6440_spi1_pdata;
-		break;
-	default:
-		printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
-							__func__, cntrlr);
-		return;
-	}
-
-	pd->num_cs = num_cs;
-	pd->src_clk_nr = src_clk_nr;
-	pd->src_clk_name = spi_src_clks[src_clk_nr];
-}
diff --git a/arch/arm/mach-s5p6440/dma.c b/arch/arm/mach-s5p6440/dma.c
deleted file mode 100644
index 07606ad..0000000
--- a/arch/arm/mach-s5p6440/dma.c
+++ /dev/null
@@ -1,105 +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 s5p6440_pdma_resource[] = {
-	[0] = {
-		.start  = S5P6440_PA_PDMA,
-		.end    = S5P6440_PA_PDMA + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_DMA0,
-		.end	= IRQ_DMA0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_MAX,
-		[10] = DMACH_PCM0_TX,
-		[11] = DMACH_PCM0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S0_RX,
-		[14] = DMACH_SPI0_TX,
-		[15] = DMACH_SPI0_RX,
-		[16] = DMACH_MAX,
-		[17] = DMACH_MAX,
-		[18] = DMACH_MAX,
-		[19] = DMACH_MAX,
-		[20] = DMACH_SPI1_TX,
-		[21] = DMACH_SPI1_RX,
-		[22] = DMACH_MAX,
-		[23] = DMACH_MAX,
-		[24] = DMACH_MAX,
-		[25] = DMACH_MAX,
-		[26] = DMACH_MAX,
-		[27] = DMACH_MAX,
-		[28] = DMACH_MAX,
-		[29] = DMACH_PWM,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
-};
-
-static struct platform_device s5p6440_device_pdma = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5p6440_pdma_resource),
-	.resource	= s5p6440_pdma_resource,
-	.dev		= {
-		.dma_mask = &dma_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.platform_data = &s5p6440_pdma_pdata,
-	},
-};
-
-static struct platform_device *s5p6440_dmacs[] __initdata = {
-	&s5p6440_device_pdma,
-};
-
-static int __init s5p6440_dma_init(void)
-{
-	platform_add_devices(s5p6440_dmacs, ARRAY_SIZE(s5p6440_dmacs));
-
-	return 0;
-}
-arch_initcall(s5p6440_dma_init);
diff --git a/arch/arm/mach-s5p6440/gpio.c b/arch/arm/mach-s5p6440/gpio.c
deleted file mode 100644
index 8bf6e0c..0000000
--- a/arch/arm/mach-s5p6440/gpio.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/* arch/arm/mach-s5p6440/gpio.c
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * 		http://www.samsung.com/
- *
- * S5P6440 - 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 <mach/regs-gpio.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-/* GPIO bank summary:
-*
-* Bank	GPIOs	Style	SlpCon	ExtInt Group
-* A	6	4Bit	Yes	1
-* B	7	4Bit	Yes	1
-* C	8	4Bit	Yes	2
-* F	2	2Bit	Yes	4 [1]
-* G	7	4Bit	Yes	5
-* H	10	4Bit[2]	Yes	6
-* I	16	2Bit	Yes	None
-* J	12	2Bit	Yes	None
-* N	16	2Bit	No	IRQ_EINT
-* P	8	2Bit	Yes	8
-* R	15	4Bit[2]	Yes	8
-*
-* [1] BANKF pins 14,15 do not form part of the external interrupt sources
-* [2] BANK has two control registers, GPxCON0 and GPxCON1
-*/
-
-static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
-					     unsigned int offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	void __iomem *regcon = base;
-	unsigned long con;
-	unsigned long flags;
-
-	switch (offset) {
-	case 6:
-		offset += 1;
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-		regcon -= 4;
-		break;
-	default:
-		offset -= 7;
-		break;
-	}
-
-	s3c_gpio_lock(ourchip, flags);
-
-	con = __raw_readl(regcon);
-	con &= ~(0xf << con_4bit_shift(offset));
-	__raw_writel(con, regcon);
-
-	s3c_gpio_unlock(ourchip, flags);
-
-	return 0;
-}
-
-static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
-					      unsigned int offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	void __iomem *regcon = base;
-	unsigned long con;
-	unsigned long dat;
-	unsigned long flags;
-	unsigned con_offset  = offset;
-
-	switch (con_offset) {
-	case 6:
-		con_offset += 1;
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-		regcon -= 4;
-		break;
-	default:
-		con_offset -= 7;
-		break;
-	}
-
-	s3c_gpio_lock(ourchip, flags);
-
-	con = __raw_readl(regcon);
-	con &= ~(0xf << con_4bit_shift(con_offset));
-	con |= 0x1 << con_4bit_shift(con_offset);
-
-	dat = __raw_readl(base + GPIODAT_OFF);
-	if (value)
-		dat |= 1 << offset;
-	else
-		dat &= ~(1 << offset);
-
-	__raw_writel(con, regcon);
-	__raw_writel(dat, base + GPIODAT_OFF);
-
-	s3c_gpio_unlock(ourchip, flags);
-
-	return 0;
-}
-
-int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
-				   unsigned int off, unsigned int cfg)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift;
-	unsigned long flags;
-	u32 con;
-
-	switch (off) {
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-		shift = (off & 7) * 4;
-		reg -= 4;
-		break;
-	case 6:
-		shift = ((off + 1) & 7) * 4;
-		reg -= 4;
-	default:
-		shift = ((off + 1) & 7) * 4;
-		break;
-	}
-
-	if (s3c_gpio_is_cfg_special(cfg)) {
-		cfg &= 0xf;
-		cfg <<= shift;
-	}
-
-	s3c_gpio_lock(chip, flags);
-
-	con = __raw_readl(reg);
-	con &= ~(0xf << shift);
-	con |= cfg;
-	__raw_writel(con, reg);
-
-	s3c_gpio_unlock(chip, flags);
-
-	return 0;
-}
-
-static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = {
-	{
-		.cfg_eint	= 0,
-	}, {
-		.cfg_eint	= 7,
-	}, {
-		.cfg_eint	= 3,
-		.set_config	= s5p6440_gpio_setcfg_4bit_rbank,
-	}, {
-		.cfg_eint	= 0,
-		.set_config	= s3c_gpio_setcfg_s3c24xx,
-		.get_config	= s3c_gpio_getcfg_s3c24xx,
-	}, {
-		.cfg_eint	= 2,
-		.set_config	= s3c_gpio_setcfg_s3c24xx,
-		.get_config	= s3c_gpio_getcfg_s3c24xx,
-	}, {
-		.cfg_eint	= 3,
-		.set_config	= s3c_gpio_setcfg_s3c24xx,
-		.get_config	= s3c_gpio_getcfg_s3c24xx,
-	},
-};
-
-static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
-	{
-		.base	= S5P6440_GPA_BASE,
-		.config	= &s5p6440_gpio_cfgs[1],
-		.chip	= {
-			.base	= S5P6440_GPA(0),
-			.ngpio	= S5P6440_GPIO_A_NR,
-			.label	= "GPA",
-		},
-	}, {
-		.base	= S5P6440_GPB_BASE,
-		.config	= &s5p6440_gpio_cfgs[1],
-		.chip	= {
-			.base	= S5P6440_GPB(0),
-			.ngpio	= S5P6440_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.base	= S5P6440_GPC_BASE,
-		.config	= &s5p6440_gpio_cfgs[1],
-		.chip	= {
-			.base	= S5P6440_GPC(0),
-			.ngpio	= S5P6440_GPIO_C_NR,
-			.label	= "GPC",
-		},
-	}, {
-		.base	= S5P6440_GPG_BASE,
-		.config	= &s5p6440_gpio_cfgs[1],
-		.chip	= {
-			.base	= S5P6440_GPG(0),
-			.ngpio	= S5P6440_GPIO_G_NR,
-			.label	= "GPG",
-		},
-	},
-};
-
-static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
-	{
-		.base	= S5P6440_GPH_BASE + 0x4,
-		.config	= &s5p6440_gpio_cfgs[1],
-		.chip	= {
-			.base	= S5P6440_GPH(0),
-			.ngpio	= S5P6440_GPIO_H_NR,
-			.label	= "GPH",
-		},
-	},
-};
-
-static struct s3c_gpio_chip gpio_rbank_4bit2[] = {
-	{
-		.base	= S5P6440_GPR_BASE + 0x4,
-		.config	= &s5p6440_gpio_cfgs[2],
-		.chip	= {
-			.base	= S5P6440_GPR(0),
-			.ngpio	= S5P6440_GPIO_R_NR,
-			.label	= "GPR",
-		},
-	},
-};
-
-static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
-	{
-		.base	= S5P6440_GPF_BASE,
-		.config	= &s5p6440_gpio_cfgs[5],
-		.chip	= {
-			.base	= S5P6440_GPF(0),
-			.ngpio	= S5P6440_GPIO_F_NR,
-			.label	= "GPF",
-		},
-	}, {
-		.base	= S5P6440_GPI_BASE,
-		.config	= &s5p6440_gpio_cfgs[3],
-		.chip	= {
-			.base	= S5P6440_GPI(0),
-			.ngpio	= S5P6440_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.base	= S5P6440_GPJ_BASE,
-		.config	= &s5p6440_gpio_cfgs[3],
-		.chip	= {
-			.base	= S5P6440_GPJ(0),
-			.ngpio	= S5P6440_GPIO_J_NR,
-			.label	= "GPJ",
-		},
-	}, {
-		.base	= S5P6440_GPN_BASE,
-		.config	= &s5p6440_gpio_cfgs[4],
-		.chip	= {
-			.base	= S5P6440_GPN(0),
-			.ngpio	= S5P6440_GPIO_N_NR,
-			.label	= "GPN",
-		},
-	}, {
-		.base	= S5P6440_GPP_BASE,
-		.config	= &s5p6440_gpio_cfgs[5],
-		.chip	= {
-			.base	= S5P6440_GPP(0),
-			.ngpio	= S5P6440_GPIO_P_NR,
-			.label	= "GPP",
-		},
-	},
-};
-
-void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
-{
-	for (; nr_chips > 0; nr_chips--, chipcfg++) {
-		if (!chipcfg->set_config)
-			chipcfg->set_config	= s3c_gpio_setcfg_s3c64xx_4bit;
-		if (!chipcfg->get_config)
-			chipcfg->get_config	= s3c_gpio_getcfg_s3c64xx_4bit;
-		if (!chipcfg->set_pull)
-			chipcfg->set_pull	= s3c_gpio_setpull_updown;
-		if (!chipcfg->get_pull)
-			chipcfg->get_pull	= s3c_gpio_getpull_updown;
-	}
-}
-
-static void __init s5p6440_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
-						int nr_chips)
-{
-	for (; nr_chips > 0; nr_chips--, chip++) {
-		chip->chip.direction_input = s5p6440_gpiolib_rbank_4bit2_input;
-		chip->chip.direction_output =
-					s5p6440_gpiolib_rbank_4bit2_output;
-		s3c_gpiolib_add(chip);
-	}
-}
-
-static int __init s5p6440_gpiolib_init(void)
-{
-	struct s3c_gpio_chip *chips = s5p6440_gpio_2bit;
-	int nr_chips = ARRAY_SIZE(s5p6440_gpio_2bit);
-
-	s5p6440_gpiolib_set_cfg(s5p6440_gpio_cfgs,
-				ARRAY_SIZE(s5p6440_gpio_cfgs));
-
-	for (; nr_chips > 0; nr_chips--, chips++)
-		s3c_gpiolib_add(chips);
-
-	samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit,
-				ARRAY_SIZE(s5p6440_gpio_4bit));
-
-	samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
-				ARRAY_SIZE(s5p6440_gpio_4bit2));
-
-	s5p6440_gpio_add_rbank_4bit2(gpio_rbank_4bit2,
-				ARRAY_SIZE(gpio_rbank_4bit2));
-
-	return 0;
-}
-arch_initcall(s5p6440_gpiolib_init);
diff --git a/arch/arm/mach-s5p6440/include/mach/debug-macro.S b/arch/arm/mach-s5p6440/include/mach/debug-macro.S
deleted file mode 100644
index 1347d7f..0000000
--- a/arch/arm/mach-s5p6440/include/mach/debug-macro.S
+++ /dev/null
@@ -1,37 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/debug-macro.S
- *
- * Copyright (c) 2009 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.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <mach/map.h>
-#include <plat/regs-serial.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, rx, rtmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1
-		ldreq	\rx, = S3C_PA_UART
-		ldrne	\rx, = S3C_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
-		add	\rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
-#endif
-	.endm
-
-/* include the reset of the code which will do the work, we're only
- * compiling for a single cpu processor type so the default of s3c2440
- * will be fine with us.
- */
-
-#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s5p6440/include/mach/entry-macro.S b/arch/arm/mach-s5p6440/include/mach/entry-macro.S
deleted file mode 100644
index e65f1b9..0000000
--- a/arch/arm/mach-s5p6440/include/mach/entry-macro.S
+++ /dev/null
@@ -1,16 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/entry-macro.S
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Low-level IRQ helper macros for the Samsung S5P6440
- *
- * This program is free software; you can redistribute 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/map.h>
-#include <plat/irqs.h>
-
-#include <asm/entry-macro-vic2.S>
diff --git a/arch/arm/mach-s5p6440/include/mach/gpio.h b/arch/arm/mach-s5p6440/include/mach/gpio.h
deleted file mode 100644
index 2178383..0000000
--- a/arch/arm/mach-s5p6440/include/mach/gpio.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/gpio.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - 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
-
-/* GPIO bank sizes */
-#define S5P6440_GPIO_A_NR	(6)
-#define S5P6440_GPIO_B_NR	(7)
-#define S5P6440_GPIO_C_NR	(8)
-#define S5P6440_GPIO_F_NR	(2)
-#define S5P6440_GPIO_G_NR	(7)
-#define S5P6440_GPIO_H_NR	(10)
-#define S5P6440_GPIO_I_NR	(16)
-#define S5P6440_GPIO_J_NR	(12)
-#define S5P6440_GPIO_N_NR	(16)
-#define S5P6440_GPIO_P_NR	(8)
-#define S5P6440_GPIO_R_NR	(15)
-
-/* GPIO bank numbers */
-
-/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
- * space for debugging purposes so that any accidental
- * change from one gpio bank to another can be caught.
-*/
-#define S5P6440_GPIO_NEXT(__gpio) \
-	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p_gpio_number {
-	S5P6440_GPIO_A_START = 0,
-	S5P6440_GPIO_B_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_A),
-	S5P6440_GPIO_C_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_B),
-	S5P6440_GPIO_F_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_C),
-	S5P6440_GPIO_G_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_F),
-	S5P6440_GPIO_H_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_G),
-	S5P6440_GPIO_I_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_H),
-	S5P6440_GPIO_J_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_I),
-	S5P6440_GPIO_N_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_J),
-	S5P6440_GPIO_P_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_N),
-	S5P6440_GPIO_R_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_P),
-};
-
-/* S5P6440 GPIO number definitions. */
-#define S5P6440_GPA(_nr)	(S5P6440_GPIO_A_START + (_nr))
-#define S5P6440_GPB(_nr)	(S5P6440_GPIO_B_START + (_nr))
-#define S5P6440_GPC(_nr)	(S5P6440_GPIO_C_START + (_nr))
-#define S5P6440_GPF(_nr)	(S5P6440_GPIO_F_START + (_nr))
-#define S5P6440_GPG(_nr)	(S5P6440_GPIO_G_START + (_nr))
-#define S5P6440_GPH(_nr)	(S5P6440_GPIO_H_START + (_nr))
-#define S5P6440_GPI(_nr)	(S5P6440_GPIO_I_START + (_nr))
-#define S5P6440_GPJ(_nr)	(S5P6440_GPIO_J_START + (_nr))
-#define S5P6440_GPN(_nr)	(S5P6440_GPIO_N_START + (_nr))
-#define S5P6440_GPP(_nr)	(S5P6440_GPIO_P_START + (_nr))
-#define S5P6440_GPR(_nr)	(S5P6440_GPIO_R_START + (_nr))
-
-/* the end of the S5P6440 specific gpios */
-#define S5P6440_GPIO_END	(S5P6440_GPR(S5P6440_GPIO_R_NR) + 1)
-#define S3C_GPIO_END		S5P6440_GPIO_END
-
-/* define the number of gpios we need to the one after the GPR() range */
-#define ARCH_NR_GPIOS		(S5P6440_GPR(S5P6440_GPIO_R_NR) +	\
-				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
-
-#include <asm-generic/gpio.h>
-
-#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/hardware.h b/arch/arm/mach-s5p6440/include/mach/hardware.h
deleted file mode 100644
index be8b26e..0000000
--- a/arch/arm/mach-s5p6440/include/mach/hardware.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/hardware.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - 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-s5p6440/include/mach/io.h b/arch/arm/mach-s5p6440/include/mach/io.h
deleted file mode 100644
index fa2d69c..0000000
--- a/arch/arm/mach-s5p6440/include/mach/io.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-s5p6440/include/mach/io.h
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben-linux@fluff.org>
- *
- * Default IO routines for S3C64XX based
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/* No current ISA/PCI bus support. */
-#define __io(a)		__typesafe_io(a)
-#define __mem_pci(a)	(a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif
diff --git a/arch/arm/mach-s5p6440/include/mach/irqs.h b/arch/arm/mach-s5p6440/include/mach/irqs.h
deleted file mode 100644
index 16a7612..0000000
--- a/arch/arm/mach-s5p6440/include/mach/irqs.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/irqs.h
- *
- * Copyright 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - 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_S5P_IRQS_H
-#define __ASM_ARCH_S5P_IRQS_H __FILE__
-
-#include <plat/irqs.h>
-
-/* VIC0 */
-
-#define IRQ_EINT0_3		S5P_IRQ_VIC0(0)
-#define IRQ_EINT4_11		S5P_IRQ_VIC0(1)
-#define IRQ_RTC_TIC		S5P_IRQ_VIC0(2)
-#define IRQ_IIC1		S5P_IRQ_VIC0(5)
-#define IRQ_I2SV40		S5P_IRQ_VIC0(6)
-#define IRQ_GPS			S5P_IRQ_VIC0(7)
-#define IRQ_POST0		S5P_IRQ_VIC0(9)
-#define IRQ_2D			S5P_IRQ_VIC0(11)
-#define IRQ_TIMER0_VIC		S5P_IRQ_VIC0(23)
-#define IRQ_TIMER1_VIC		S5P_IRQ_VIC0(24)
-#define IRQ_TIMER2_VIC		S5P_IRQ_VIC0(25)
-#define IRQ_WDT			S5P_IRQ_VIC0(26)
-#define IRQ_TIMER3_VIC		S5P_IRQ_VIC0(27)
-#define IRQ_TIMER4_VIC		S5P_IRQ_VIC0(28)
-#define IRQ_DISPCON0		S5P_IRQ_VIC0(29)
-#define IRQ_DISPCON1		S5P_IRQ_VIC0(30)
-#define IRQ_DISPCON2		S5P_IRQ_VIC0(31)
-
-/* VIC1 */
-
-#define IRQ_EINT12_15		S5P_IRQ_VIC1(0)
-#define IRQ_PCM0		S5P_IRQ_VIC1(2)
-#define IRQ_UART0		S5P_IRQ_VIC1(5)
-#define IRQ_UART1		S5P_IRQ_VIC1(6)
-#define IRQ_UART2		S5P_IRQ_VIC1(7)
-#define IRQ_UART3		S5P_IRQ_VIC1(8)
-#define IRQ_DMA0		S5P_IRQ_VIC1(9)
-#define IRQ_NFC			S5P_IRQ_VIC1(13)
-#define IRQ_SPI0		S5P_IRQ_VIC1(16)
-#define IRQ_SPI1		S5P_IRQ_VIC1(17)
-#define IRQ_IIC			S5P_IRQ_VIC1(18)
-#define IRQ_DISPCON3		S5P_IRQ_VIC1(19)
-#define IRQ_FIMGVG		S5P_IRQ_VIC1(20)
-#define IRQ_EINT_GROUPS		S5P_IRQ_VIC1(21)
-#define IRQ_PMU			S5P_IRQ_VIC1(23)
-#define IRQ_HSMMC0		S5P_IRQ_VIC1(24)
-#define IRQ_HSMMC1		S5P_IRQ_VIC1(25)
-#define IRQ_HSMMC2		IRQ_SPI1	/* shared with SPI1 */
-#define IRQ_OTG			S5P_IRQ_VIC1(26)
-#define IRQ_DSI			S5P_IRQ_VIC1(27)
-#define IRQ_RTC_ALARM		S5P_IRQ_VIC1(28)
-#define IRQ_TSI			S5P_IRQ_VIC1(29)
-#define IRQ_PENDN		S5P_IRQ_VIC1(30)
-#define IRQ_TC			IRQ_PENDN
-#define IRQ_ADC			S5P_IRQ_VIC1(31)
-
-/*
- * Since the IRQ_EINT(x) are a linear mapping on s5p6440 we just defined
- * them as an IRQ_EINT(x) macro from S5P_IRQ_EINT_BASE which we place
- * after the pair of VICs.
- */
-
-#define S5P_IRQ_EINT_BASE	(S5P_IRQ_VIC1(31) + 6)
-
-#define S5P_EINT(x)		((x) + S5P_IRQ_EINT_BASE)
-
-#define S5P_EINT_BASE1		(S5P_IRQ_EINT_BASE)
-/*
- * S5P6440 has 0-15 external interrupts in group 0. Only these can be used
- * to wake up from sleep. If request is beyond this range, by mistake, a large
- * return value for an irq number should be indication of something amiss.
- */
-#define S5P_EINT_BASE2		(0xf0000000)
-
-/*
- * Next the external interrupt groups. These are similar to the IRQ_EINT(x)
- * that they are sourced from the GPIO pins but with a different scheme for
- * priority and source indication.
- *
- * The IRQ_EINT(x) can be thought of as 'group 0' of the available GPIO
- * interrupts, but for historical reasons they are kept apart from these
- * next interrupts.
- *
- * Use IRQ_EINT_GROUP(group, offset) to get the number for use in the
- * machine specific support files.
- */
-
-/* Actually, #6 and #7 are missing in the EINT_GROUP1 */
-#define IRQ_EINT_GROUP1_NR	(15)
-#define IRQ_EINT_GROUP2_NR	(8)
-#define IRQ_EINT_GROUP5_NR	(7)
-#define IRQ_EINT_GROUP6_NR	(10)
-/* Actually, #0, #1 and #2 are missing in the EINT_GROUP8 */
-#define IRQ_EINT_GROUP8_NR	(11)
-
-#define IRQ_EINT_GROUP_BASE	S5P_EINT(16)
-#define IRQ_EINT_GROUP1_BASE	(IRQ_EINT_GROUP_BASE + 0)
-#define IRQ_EINT_GROUP2_BASE	(IRQ_EINT_GROUP1_BASE + IRQ_EINT_GROUP1_NR)
-#define IRQ_EINT_GROUP5_BASE	(IRQ_EINT_GROUP2_BASE + IRQ_EINT_GROUP2_NR)
-#define IRQ_EINT_GROUP6_BASE	(IRQ_EINT_GROUP5_BASE + IRQ_EINT_GROUP5_NR)
-#define IRQ_EINT_GROUP8_BASE	(IRQ_EINT_GROUP6_BASE + IRQ_EINT_GROUP6_NR)
-
-#define IRQ_EINT_GROUP(grp, x)	(IRQ_EINT_GROUP##grp##_BASE + (x))
-
-/* Set the default NR_IRQS */
-
-#define NR_IRQS			(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
-
-#endif /* __ASM_ARCH_S5P_IRQS_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/map.h b/arch/arm/mach-s5p6440/include/mach/map.h
deleted file mode 100644
index 6cc5cbc..0000000
--- a/arch/arm/mach-s5p6440/include/mach/map.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/map.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - 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>
-#include <plat/map-s5p.h>
-
-#define S5P6440_PA_CHIPID	(0xE0000000)
-#define S5P_PA_CHIPID		S5P6440_PA_CHIPID
-
-#define S5P6440_PA_SYSCON	(0xE0100000)
-#define S5P6440_PA_CLK		(S5P6440_PA_SYSCON + 0x0)
-#define S5P_PA_SYSCON		S5P6440_PA_SYSCON
-
-#define S5P6440_PA_GPIO		(0xE0308000)
-#define S5P_PA_GPIO		S5P6440_PA_GPIO
-
-#define S5P6440_PA_VIC0		(0xE4000000)
-#define S5P_PA_VIC0		S5P6440_PA_VIC0
-
-#define S5P6440_PA_PDMA		0xE9000000
-
-#define S5P6440_PA_VIC1		(0xE4100000)
-#define S5P_PA_VIC1		S5P6440_PA_VIC1
-
-#define S5P6440_PA_TIMER	(0xEA000000)
-#define S5P_PA_TIMER		S5P6440_PA_TIMER
-
-#define S5P6440_PA_RTC		(0xEA100000)
-
-#define S5P6440_PA_WDT		(0xEA200000)
-#define S5P_PA_WDT		S5P6440_PA_WDT
-
-#define S5P6440_PA_UART		(0xEC000000)
-
-#define S5P_PA_UART0		(S5P6440_PA_UART + 0x0)
-#define S5P_PA_UART1		(S5P6440_PA_UART + 0x400)
-#define S5P_PA_UART2		(S5P6440_PA_UART + 0x800)
-#define S5P_PA_UART3		(S5P6440_PA_UART + 0xC00)
-
-#define S5P_SZ_UART		SZ_256
-
-#define S5P6440_PA_IIC0		(0xEC104000)
-#define S5P6440_PA_IIC1		(0xEC20F000)
-
-#define S5P6440_PA_SPI0		0xEC400000
-#define S5P6440_PA_SPI1		0xEC500000
-
-#define S5P6440_PA_HSOTG	(0xED100000)
-
-#define S5P6440_PA_HSMMC0	(0xED800000)
-#define S5P6440_PA_HSMMC1	(0xED900000)
-#define S5P6440_PA_HSMMC2	(0xEDA00000)
-
-#define S5P6440_PA_SDRAM	(0x20000000)
-#define S5P_PA_SDRAM		S5P6440_PA_SDRAM
-
-/* I2S */
-#define S5P6440_PA_I2S		0xF2000000
-
-/* PCM */
-#define S5P6440_PA_PCM		0xF2100000
-
-#define S5P6440_PA_ADC		(0xF3000000)
-
-/* compatibiltiy defines. */
-#define S3C_PA_UART		S5P6440_PA_UART
-#define S3C_PA_IIC		S5P6440_PA_IIC0
-#define S3C_PA_RTC		S5P6440_PA_RTC
-#define S3C_PA_IIC1		S5P6440_PA_IIC1
-#define S3C_PA_WDT		S5P6440_PA_WDT
-
-#define SAMSUNG_PA_ADC		S5P6440_PA_ADC
-
-#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/memory.h b/arch/arm/mach-s5p6440/include/mach/memory.h
deleted file mode 100644
index d62910c..0000000
--- a/arch/arm/mach-s5p6440/include/mach/memory.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/memory.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - 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
-
-#define PHYS_OFFSET     	UL(0x20000000)
-#define CONSISTENT_DMA_SIZE	SZ_8M
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h b/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
deleted file mode 100644
index 6a2a02f..0000000
--- a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
- *
- * Copyright (c) 2009 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
- *
- * S5P6440 - 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 0;
-}
-
-/**
- * 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 0
-
-#endif /* __ASM_ARCH_PWMCLK_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/regs-clock.h b/arch/arm/mach-s5p6440/include/mach/regs-clock.h
deleted file mode 100644
index c783ecc..0000000
--- a/arch/arm/mach-s5p6440/include/mach/regs-clock.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/regs-clock.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - 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)		(S3C_VA_SYS + (x))
-
-#define S5P_APLL_LOCK		S5P_CLKREG(0x00)
-#define S5P_MPLL_LOCK		S5P_CLKREG(0x04)
-#define S5P_EPLL_LOCK		S5P_CLKREG(0x08)
-#define S5P_APLL_CON		S5P_CLKREG(0x0C)
-#define S5P_MPLL_CON		S5P_CLKREG(0x10)
-#define S5P_EPLL_CON		S5P_CLKREG(0x14)
-#define S5P_EPLL_CON_K		S5P_CLKREG(0x18)
-#define S5P_CLK_SRC0		S5P_CLKREG(0x1C)
-#define S5P_CLK_DIV0		S5P_CLKREG(0x20)
-#define S5P_CLK_DIV1		S5P_CLKREG(0x24)
-#define S5P_CLK_DIV2		S5P_CLKREG(0x28)
-#define S5P_CLK_OUT		S5P_CLKREG(0x2C)
-#define S5P_CLK_GATE_HCLK0	S5P_CLKREG(0x30)
-#define S5P_CLK_GATE_PCLK	S5P_CLKREG(0x34)
-#define S5P_CLK_GATE_SCLK0	S5P_CLKREG(0x38)
-#define S5P_CLK_GATE_MEM0	S5P_CLKREG(0x3C)
-#define S5P_CLK_DIV3		S5P_CLKREG(0x40)
-#define S5P_CLK_GATE_HCLK1	S5P_CLKREG(0x44)
-#define S5P_CLK_GATE_SCLK1	S5P_CLKREG(0x48)
-#define S5P_AHB_CON0           	S5P_CLKREG(0x100)
-#define S5P_CLK_SRC1           	S5P_CLKREG(0x10C)
-#define S5P_SWRESET		S5P_CLKREG(0x114)
-#define S5P_SYS_ID		S5P_CLKREG(0x118)
-#define S5P_SYS_OTHERS		S5P_CLKREG(0x11C)
-#define S5P_MEM_CFG_STAT	S5P_CLKREG(0x12C)
-#define S5P_PWR_CFG		S5P_CLKREG(0x804)
-#define S5P_EINT_WAKEUP_MASK	S5P_CLKREG(0x808)
-#define S5P_NORMAL_CFG		S5P_CLKREG(0x810)
-#define S5P_STOP_CFG		S5P_CLKREG(0x814)
-#define S5P_SLEEP_CFG		S5P_CLKREG(0x818)
-#define S5P_OSC_FREQ		S5P_CLKREG(0x820)
-#define S5P_OSC_STABLE		S5P_CLKREG(0x824)
-#define S5P_PWR_STABLE		S5P_CLKREG(0x828)
-#define S5P_MTC_STABLE		S5P_CLKREG(0x830)
-#define S5P_OTHERS		S5P_CLKREG(0x900)
-#define S5P_RST_STAT		S5P_CLKREG(0x904)
-#define S5P_WAKEUP_STAT		S5P_CLKREG(0x908)
-#define S5P_SLPEN		S5P_CLKREG(0x930)
-#define S5P_INFORM0		S5P_CLKREG(0xA00)
-#define S5P_INFORM1		S5P_CLKREG(0xA04)
-#define S5P_INFORM2		S5P_CLKREG(0xA08)
-#define S5P_INFORM3		S5P_CLKREG(0xA0C)
-
-/* CLKDIV0 */
-#define S5P_CLKDIV0_PCLK_MASK		(0xf << 12)
-#define S5P_CLKDIV0_PCLK_SHIFT		(12)
-#define S5P_CLKDIV0_HCLK_MASK		(0xf << 8)
-#define S5P_CLKDIV0_HCLK_SHIFT		(8)
-#define S5P_CLKDIV0_MPLL_MASK		(0x1 << 4)
-#define S5P_CLKDIV0_ARM_MASK		(0xf << 0)
-#define S5P_CLKDIV0_ARM_SHIFT		(0)
-
-/* CLKDIV3 */
-#define S5P_CLKDIV3_PCLK_LOW_MASK	(0xf << 12)
-#define S5P_CLKDIV3_PCLK_LOW_SHIFT	(12)
-#define S5P_CLKDIV3_HCLK_LOW_MASK	(0xf << 8)
-#define S5P_CLKDIV3_HCLK_LOW_SHIFT	(8)
-
-/* HCLK0 GATE Registers */
-#define S5P_CLKCON_HCLK0_USB		(1<<20)
-#define S5P_CLKCON_HCLK0_HSMMC2		(1<<19)
-#define S5P_CLKCON_HCLK0_HSMMC1		(1<<18)
-#define S5P_CLKCON_HCLK0_HSMMC0		(1<<17)
-#define S5P_CLKCON_HCLK0_POST0		(1<<5)
-
-/* HCLK1 GATE Registers */
-#define S5P_CLKCON_HCLK1_DISPCON	(1<<1)
-
-/* PCLK GATE Registers */
-#define S5P_CLKCON_PCLK_IIS2		(1<<26)
-#define S5P_CLKCON_PCLK_SPI1		(1<<22)
-#define S5P_CLKCON_PCLK_SPI0		(1<<21)
-#define S5P_CLKCON_PCLK_GPIO		(1<<18)
-#define S5P_CLKCON_PCLK_IIC0		(1<<17)
-#define S5P_CLKCON_PCLK_TSADC		(1<<12)
-#define S5P_CLKCON_PCLK_PWM		(1<<7)
-#define S5P_CLKCON_PCLK_RTC		(1<<6)
-#define S5P_CLKCON_PCLK_WDT		(1<<5)
-#define S5P_CLKCON_PCLK_UART3		(1<<4)
-#define S5P_CLKCON_PCLK_UART2		(1<<3)
-#define S5P_CLKCON_PCLK_UART1		(1<<2)
-#define S5P_CLKCON_PCLK_UART0		(1<<1)
-
-/* SCLK0 GATE Registers */
-#define S5P_CLKCON_SCLK0_MMC2_48	(1<<29)
-#define S5P_CLKCON_SCLK0_MMC1_48	(1<<28)
-#define S5P_CLKCON_SCLK0_MMC0_48	(1<<27)
-#define S5P_CLKCON_SCLK0_MMC2		(1<<26)
-#define S5P_CLKCON_SCLK0_MMC1		(1<<25)
-#define S5P_CLKCON_SCLK0_MMC0		(1<<24)
-#define S5P_CLKCON_SCLK0_SPI1_48 	(1<<23)
-#define S5P_CLKCON_SCLK0_SPI0_48 	(1<<22)
-#define S5P_CLKCON_SCLK0_SPI1		(1<<21)
-#define S5P_CLKCON_SCLK0_SPI0		(1<<20)
-#define S5P_CLKCON_SCLK0_UART		(1<<5)
-
-/* SCLK1 GATE Registers */
-
-/* MEM0 GATE Registers */
-#define S5P_CLKCON_MEM0_HCLK_NFCON	(1<<2)
-
-/*OTHERS Resgister */
-#define S5P_OTHERS_USB_SIG_MASK		(1<<16)
-#define S5P_OTHERS_HCLK_LOW_SEL_MPLL	(1<<6)
-
-/* Compatibility defines */
-#define ARM_CLK_DIV			S5P_CLK_DIV0
-#define ARM_DIV_RATIO_SHIFT		0
-#define ARM_DIV_MASK			(0xf << ARM_DIV_RATIO_SHIFT)
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/regs-gpio.h b/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
deleted file mode 100644
index 82ff753..0000000
--- a/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - GPIO 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>
-
-/* Base addresses for each of the banks */
-#define S5P6440_GPA_BASE		(S5P_VA_GPIO + 0x0000)
-#define S5P6440_GPB_BASE		(S5P_VA_GPIO + 0x0020)
-#define S5P6440_GPC_BASE		(S5P_VA_GPIO + 0x0040)
-#define S5P6440_GPF_BASE		(S5P_VA_GPIO + 0x00A0)
-#define S5P6440_GPG_BASE		(S5P_VA_GPIO + 0x00C0)
-#define S5P6440_GPH_BASE		(S5P_VA_GPIO + 0x00E0)
-#define S5P6440_GPI_BASE		(S5P_VA_GPIO + 0x0100)
-#define S5P6440_GPJ_BASE		(S5P_VA_GPIO + 0x0120)
-#define S5P6440_GPN_BASE		(S5P_VA_GPIO + 0x0830)
-#define S5P6440_GPP_BASE		(S5P_VA_GPIO + 0x0160)
-#define S5P6440_GPR_BASE		(S5P_VA_GPIO + 0x0290)
-#define S5P6440_EINT0CON0		(S5P_VA_GPIO + 0x900)
-#define S5P6440_EINT0FLTCON0		(S5P_VA_GPIO + 0x910)
-#define S5P6440_EINT0FLTCON1		(S5P_VA_GPIO + 0x914)
-#define S5P6440_EINT0MASK		(S5P_VA_GPIO + 0x920)
-#define S5P6440_EINT0PEND		(S5P_VA_GPIO + 0x924)
-
-/* for LCD */
-#define S5P6440_SPCON_LCD_SEL_RGB	(1 << 0)
-#define S5P6440_SPCON_LCD_SEL_MASK	(3 << 0)
-
-/* These set of macros are not really useful for the
- * GPF/GPI/GPJ/GPN/GPP,
- * useful for others set of GPIO's (4 bit)
- */
-#define S5P6440_GPIO_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
-#define S5P6440_GPIO_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
-#define S5P6440_GPIO_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
-
-/* Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit)
- * */
-#define S5P6440_GPIO2_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
-#define S5P6440_GPIO2_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
-#define S5P6440_GPIO2_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
-
-#endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/regs-irq.h b/arch/arm/mach-s5p6440/include/mach/regs-irq.h
deleted file mode 100644
index a961f4b..0000000
--- a/arch/arm/mach-s5p6440/include/mach/regs-irq.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/regs-irq.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - 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/vic.h>
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/spi-clocks.h b/arch/arm/mach-s5p6440/include/mach/spi-clocks.h
deleted file mode 100644
index 5fbca50..0000000
--- a/arch/arm/mach-s5p6440/include/mach/spi-clocks.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/spi-clocks.h
- *
- * 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.
- */
-
-#ifndef __S5P6440_PLAT_SPI_CLKS_H
-#define __S5P6440_PLAT_SPI_CLKS_H __FILE__
-
-#define S5P6440_SPI_SRCCLK_PCLK		0
-#define S5P6440_SPI_SRCCLK_SCLK		1
-
-#endif /* __S5P6440_PLAT_SPI_CLKS_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/system.h b/arch/arm/mach-s5p6440/include/mach/system.h
deleted file mode 100644
index a359ee3..0000000
--- a/arch/arm/mach-s5p6440/include/mach/system.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/system.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - 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-s5p6440/include/mach/tick.h b/arch/arm/mach-s5p6440/include/mach/tick.h
deleted file mode 100644
index 2f25c7f..0000000
--- a/arch/arm/mach-s5p6440/include/mach/tick.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/tick.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - Timer tick support 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_TICK_H
-#define __ASM_ARCH_TICK_H __FILE__
-
-static inline u32 s3c24xx_ostimer_pending(void)
-{
-	u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);
-	return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0)));
-}
-
-#define TICK_MAX	(0xffffffff)
-
-#endif /* __ASM_ARCH_TICK_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/timex.h b/arch/arm/mach-s5p6440/include/mach/timex.h
deleted file mode 100644
index fb2e8cd..0000000
--- a/arch/arm/mach-s5p6440/include/mach/timex.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* arch/arm/mach-s3c64xx/include/mach/timex.h
- *
- * Copyright (c) 2003-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C6400 - 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
-
-/* 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-s5p6440/include/mach/uncompress.h b/arch/arm/mach-s5p6440/include/mach/uncompress.h
deleted file mode 100644
index 7c1f600d..0000000
--- a/arch/arm/mach-s5p6440/include/mach/uncompress.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/uncompress.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - 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
-
-#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. */
-}
-
-#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/vmalloc.h b/arch/arm/mach-s5p6440/include/mach/vmalloc.h
deleted file mode 100644
index e3f0eeb..0000000
--- a/arch/arm/mach-s5p6440/include/mach/vmalloc.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* arch/arm/mach-s5p6440/include/mach/vmalloc.h
- *
- * Copyright 2010 Ben Dooks <ben-linux@fluff.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.
- *
- * S3C6400 vmalloc definition
-*/
-
-#ifndef __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H
-
-#define VMALLOC_END	0xE0000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5p6440/init.c b/arch/arm/mach-s5p6440/init.c
deleted file mode 100644
index a1f3727..0000000
--- a/arch/arm/mach-s5p6440/init.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/init.c
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P6440 - Init support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/s5p6440.h>
-#include <plat/regs-serial.h>
-
-static struct s3c24xx_uart_clksrc s5p6440_serial_clocks[] = {
-	[0] = {
-		.name		= "pclk_low",
-		.divisor	= 1,
-		.min_baud	= 0,
-		.max_baud	= 0,
-	},
-	[1] = {
-		.name		= "uclk1",
-		.divisor	= 1,
-		.min_baud	= 0,
-		.max_baud	= 0,
-	},
-};
-
-/* uart registration process */
-void __init s5p6440_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->clocks = s5p6440_serial_clocks;
-			tcfg->clocks_size = ARRAY_SIZE(s5p6440_serial_clocks);
-		}
-	}
-
-	s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
-}
diff --git a/arch/arm/mach-s5p6440/mach-smdk6440.c b/arch/arm/mach-s5p6440/mach-smdk6440.c
deleted file mode 100644
index 9202aaa..0000000
--- a/arch/arm/mach-s5p6440/mach-smdk6440.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/mach-smdk6440.c
- *
- * Copyright (c) 2009 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/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-
-#include <plat/s5p6440.h>
-#include <plat/clock.h>
-#include <mach/regs-clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/iic.h>
-#include <plat/pll.h>
-#include <plat/adc.h>
-#include <plat/ts.h>
-
-#define SMDK6440_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				S3C2410_UCON_RXILEVEL |		\
-				S3C2410_UCON_TXIRQMODE |	\
-				S3C2410_UCON_RXIRQMODE |	\
-				S3C2410_UCON_RXFIFO_TOI |	\
-				S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDK6440_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDK6440_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				S3C2440_UFCON_TXTRIG16 |	\
-				S3C2410_UFCON_RXTRIG8)
-
-static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = SMDK6440_UCON_DEFAULT,
-		.ulcon	     = SMDK6440_ULCON_DEFAULT,
-		.ufcon	     = SMDK6440_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = SMDK6440_UCON_DEFAULT,
-		.ulcon	     = SMDK6440_ULCON_DEFAULT,
-		.ufcon	     = SMDK6440_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport	     = 2,
-		.flags	     = 0,
-		.ucon	     = SMDK6440_UCON_DEFAULT,
-		.ulcon	     = SMDK6440_ULCON_DEFAULT,
-		.ufcon	     = SMDK6440_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport	     = 3,
-		.flags	     = 0,
-		.ucon	     = SMDK6440_UCON_DEFAULT,
-		.ulcon	     = SMDK6440_ULCON_DEFAULT,
-		.ufcon	     = SMDK6440_UFCON_DEFAULT,
-	},
-};
-
-static struct platform_device *smdk6440_devices[] __initdata = {
-	&s5p6440_device_iis,
-	&s3c_device_adc,
-	&s3c_device_rtc,
-	&s3c_device_i2c0,
-	&s3c_device_i2c1,
-	&s3c_device_ts,
-	&s3c_device_wdt,
-};
-
-static struct i2c_board_info smdk6440_i2c_devs0[] __initdata = {
-	{ I2C_BOARD_INFO("24c08", 0x50), },
-};
-
-static struct i2c_board_info smdk6440_i2c_devs1[] __initdata = {
-	/* To be populated */
-};
-
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
-static void __init smdk6440_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_SYS_ID);
-	s3c24xx_init_clocks(12000000);
-	s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs));
-}
-
-static void __init smdk6440_machine_init(void)
-{
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
-
-	/* I2C */
-	s3c_i2c0_set_platdata(NULL);
-	s3c_i2c1_set_platdata(NULL);
-	i2c_register_board_info(0, smdk6440_i2c_devs0,
-			ARRAY_SIZE(smdk6440_i2c_devs0));
-	i2c_register_board_info(1, smdk6440_i2c_devs1,
-			ARRAY_SIZE(smdk6440_i2c_devs1));
-
-	platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
-}
-
-MACHINE_START(SMDK6440, "SMDK6440")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-
-	.init_irq	= s5p6440_init_irq,
-	.map_io		= smdk6440_map_io,
-	.init_machine	= smdk6440_machine_init,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s5p6440/setup-i2c0.c b/arch/arm/mach-s5p6440/setup-i2c0.c
deleted file mode 100644
index 2c99d14..0000000
--- a/arch/arm/mach-s5p6440/setup-i2c0.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/setup-i2c0.c
- *
- * Copyright (c) 2009 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.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/gpio-cfg.h>
-#include <plat/iic.h>
-
-void s3c_i2c0_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgpin(S5P6440_GPB(5), S3C_GPIO_SFN(2));
-	s3c_gpio_setpull(S5P6440_GPB(5), S3C_GPIO_PULL_UP);
-	s3c_gpio_cfgpin(S5P6440_GPB(6), S3C_GPIO_SFN(2));
-	s3c_gpio_setpull(S5P6440_GPB(6), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5p6440/setup-i2c1.c b/arch/arm/mach-s5p6440/setup-i2c1.c
deleted file mode 100644
index 9a1537f..0000000
--- a/arch/arm/mach-s5p6440/setup-i2c1.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/setup-i2c1.c
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * I2C1 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.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <plat/gpio-cfg.h>
-#include <plat/iic.h>
-
-void s3c_i2c1_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgpin(S5P6440_GPR(9), S3C_GPIO_SFN(6));
-	s3c_gpio_setpull(S5P6440_GPR(9), S3C_GPIO_PULL_UP);
-	s3c_gpio_cfgpin(S5P6440_GPR(10), S3C_GPIO_SFN(6));
-	s3c_gpio_setpull(S5P6440_GPR(10), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5p6442/cpu.c b/arch/arm/mach-s5p6442/cpu.c
index a48fb55..842af86 100644
--- a/arch/arm/mach-s5p6442/cpu.c
+++ b/arch/arm/mach-s5p6442/cpu.c
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-s5p6442/cpu.c
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
+ *		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
@@ -19,6 +19,7 @@
 #include <linux/sysdev.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -47,10 +48,30 @@
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
 	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO,
+		.pfn		= __phys_to_pfn(S5P6442_PA_GPIO),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC0,
+		.pfn		= __phys_to_pfn(S5P6442_PA_VIC0),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC1,
+		.pfn		= __phys_to_pfn(S5P6442_PA_VIC1),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
 		.virtual	= (unsigned long)VA_VIC2,
 		.pfn		= __phys_to_pfn(S5P6442_PA_VIC2),
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_UART,
+		.pfn		= __phys_to_pfn(S3C_PA_UART),
+		.length		= SZ_512K,
+		.type		= MT_DEVICE,
 	}
 };
 
@@ -62,10 +83,11 @@
 	local_irq_enable();
 }
 
-/* s5p6442_map_io
+/*
+ * s5p6442_map_io
  *
  * register the standard cpu IO areas
-*/
+ */
 
 void __init s5p6442_map_io(void)
 {
diff --git a/arch/arm/mach-s5p6442/include/mach/debug-macro.S b/arch/arm/mach-s5p6442/include/mach/debug-macro.S
index bb65361..e2213205 100644
--- a/arch/arm/mach-s5p6442/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5p6442/include/mach/debug-macro.S
@@ -15,13 +15,12 @@
 #include <mach/map.h>
 #include <plat/regs-serial.h>
 
-	.macro addruart, rx, rtmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1
-		ldreq	\rx, = S3C_PA_UART
-		ldrne	\rx, = S3C_VA_UART
+	.macro addruart, rp, rv
+		ldr	\rp, = S3C_PA_UART
+		ldr	\rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-		add	\rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+		add	\rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
 #endif
 	.endm
 
diff --git a/arch/arm/mach-s5p6442/include/mach/map.h b/arch/arm/mach-s5p6442/include/mach/map.h
index 281d256..31fb2e68 100644
--- a/arch/arm/mach-s5p6442/include/mach/map.h
+++ b/arch/arm/mach-s5p6442/include/mach/map.h
@@ -23,16 +23,10 @@
 #define S5P_PA_SYSCON		S5P6442_PA_SYSCON
 
 #define S5P6442_PA_GPIO		(0xE0200000)
-#define S5P_PA_GPIO		S5P6442_PA_GPIO
 
 #define S5P6442_PA_VIC0		(0xE4000000)
-#define S5P_PA_VIC0		S5P6442_PA_VIC0
-
 #define S5P6442_PA_VIC1		(0xE4100000)
-#define S5P_PA_VIC1		S5P6442_PA_VIC1
-
 #define S5P6442_PA_VIC2		(0xE4200000)
-#define S5P_PA_VIC2		S5P6442_PA_VIC2
 
 #define S5P6442_PA_MDMA		0xE8000000
 #define S5P6442_PA_PDMA		0xE9000000
diff --git a/arch/arm/mach-s5p6442/mach-smdk6442.c b/arch/arm/mach-s5p6442/mach-smdk6442.c
index 8d8d042..819fd80 100644
--- a/arch/arm/mach-s5p6442/mach-smdk6442.c
+++ b/arch/arm/mach-s5p6442/mach-smdk6442.c
@@ -83,8 +83,6 @@
 
 MACHINE_START(SMDK6442, "SMDK6442")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S5P_PA_SDRAM + 0x100,
 	.init_irq	= s5p6442_init_irq,
 	.map_io		= smdk6442_map_io,
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
new file mode 100644
index 0000000..fbcae93
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/Kconfig
@@ -0,0 +1,57 @@
+# arch/arm/mach-s5p64x0/Kconfig
+#
+# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+if ARCH_S5P64X0
+
+config CPU_S5P6440
+	bool
+	select PLAT_S5P
+	select S3C_PL330_DMA
+	help
+	  Enable S5P6440 CPU support
+
+config CPU_S5P6450
+	bool
+	select PLAT_S5P
+	select S3C_PL330_DMA
+	help
+	  Enable S5P6450 CPU support
+
+config S5P64X0_SETUP_I2C1
+	bool
+	help
+	  Common setup code for i2c bus 1.
+
+# machine support
+
+config MACH_SMDK6440
+	bool "SMDK6440"
+	select CPU_S5P6440
+	select S3C_DEV_I2C1
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C64XX_DEV_SPI
+	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_TS
+	select S5P64X0_SETUP_I2C1
+	help
+	  Machine support for the Samsung SMDK6440
+
+config MACH_SMDK6450
+	bool "SMDK6450"
+	select CPU_S5P6450
+	select S3C_DEV_I2C1
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C64XX_DEV_SPI
+	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_TS
+	select S5P64X0_SETUP_I2C1
+	help
+	  Machine support for the Samsung SMDK6450
+
+endif
diff --git a/arch/arm/mach-s5p64x0/Makefile b/arch/arm/mach-s5p64x0/Makefile
new file mode 100644
index 0000000..2655829
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/Makefile
@@ -0,0 +1,30 @@
+# arch/arm/mach-s5p64x0/Makefile
+#
+# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+# 		http://www.samsung.com
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+# Core support for S5P64X0 system
+
+obj-$(CONFIG_ARCH_S5P64X0)	+= cpu.o init.o clock.o dma.o
+obj-$(CONFIG_ARCH_S5P64X0)	+= setup-i2c0.o
+obj-$(CONFIG_CPU_S5P6440)	+= clock-s5p6440.o gpio.o
+obj-$(CONFIG_CPU_S5P6450)	+= clock-s5p6450.o
+
+# machine support
+
+obj-$(CONFIG_MACH_SMDK6440)	+= mach-smdk6440.o
+obj-$(CONFIG_MACH_SMDK6450)	+= mach-smdk6450.o
+
+# device support
+
+obj-y				+= dev-audio.o
+obj-$(CONFIG_S3C64XX_DEV_SPI)	+= dev-spi.o
+
+obj-$(CONFIG_S5P64X0_SETUP_I2C1)	+= setup-i2c1.o
diff --git a/arch/arm/mach-s5p6440/Makefile.boot b/arch/arm/mach-s5p64x0/Makefile.boot
similarity index 100%
rename from arch/arm/mach-s5p6440/Makefile.boot
rename to arch/arm/mach-s5p64x0/Makefile.boot
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
new file mode 100644
index 0000000..f93dcd8
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c
@@ -0,0 +1,626 @@
+/* linux/arch/arm/mach-s5p64x0/clock-s5p6440.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P6440 - 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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/s5p64x0-clock.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p6440.h>
+
+static u32 epll_div[][5] = {
+	{ 36000000,	0,	48, 1, 4 },
+	{ 48000000,	0,	32, 1, 3 },
+	{ 60000000,	0,	40, 1, 3 },
+	{ 72000000,	0,	48, 1, 3 },
+	{ 84000000,	0,	28, 1, 2 },
+	{ 96000000,	0,	32, 1, 2 },
+	{ 32768000,	45264,	43, 1, 4 },
+	{ 45158000,	6903,	30, 1, 3 },
+	{ 49152000,	50332,	32, 1, 3 },
+	{ 67738000,	10398,	45, 1, 3 },
+	{ 73728000,	9961,	49, 1, 3 }
+};
+
+static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned int epll_con, epll_con_k;
+	unsigned int i;
+
+	if (clk->rate == rate)	/* Return if nothing changed */
+		return 0;
+
+	epll_con = __raw_readl(S5P64X0_EPLL_CON);
+	epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K);
+
+	epll_con_k &= ~(PLL90XX_KDIV_MASK);
+	epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
+
+	for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
+		 if (epll_div[i][0] == rate) {
+			epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
+			epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
+				    (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
+				    (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(epll_div)) {
+		printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
+		return -EINVAL;
+	}
+
+	__raw_writel(epll_con, S5P64X0_EPLL_CON);
+	__raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+static struct clk_ops s5p6440_epll_ops = {
+	.get_rate = s5p64x0_epll_get_rate,
+	.set_rate = s5p6440_epll_set_rate,
+};
+
+static struct clksrc_clk clk_hclk = {
+	.clk	= {
+		.name		= "clk_hclk",
+		.id		= -1,
+		.parent		= &clk_armclk.clk,
+	},
+	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk = {
+	.clk	= {
+		.name		= "clk_pclk",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+	},
+	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
+};
+static struct clksrc_clk clk_hclk_low = {
+	.clk	= {
+		.name		= "clk_hclk_low",
+		.id		= -1,
+	},
+	.sources	= &clkset_hclk_low,
+	.reg_src	= { .reg = S5P64X0_SYS_OTHERS, .shift = 6, .size = 1 },
+	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_low = {
+	.clk	= {
+		.name		= "clk_pclk_low",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+	},
+	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
+};
+
+/*
+ * The following clocks will be disabled during clock initialization. It is
+ * recommended to keep the following clocks disabled until the driver requests
+ * for enabling the clock.
+ */
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p64x0_mem_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "post",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 5)
+	}, {
+		.name		= "2d",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "hsmmc",
+		.id		= 0,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 17),
+	}, {
+		.name		= "hsmmc",
+		.id		= 1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 18),
+	}, {
+		.name		= "hsmmc",
+		.id		= 2,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 19),
+	}, {
+		.name		= "otg",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 20)
+	}, {
+		.name		= "irom",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 25),
+	}, {
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk1_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "hclk_fimgvg",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p64x0_hclk1_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "tsi",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk1_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 6),
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "pcm",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 17),
+	}, {
+		.name		= "spi",
+		.id		= 0,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 21),
+	}, {
+		.name		= "spi",
+		.id		= 1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 22),
+	}, {
+		.name		= "gps",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 25),
+	}, {
+		.name		= "i2s_v40",
+		.id		= 0,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 26),
+	}, {
+		.name		= "dsim",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 28),
+	}, {
+		.name		= "etm",
+		.id		= -1,
+		.parent		= &clk_pclk.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 29),
+	}, {
+		.name		= "dmc0",
+		.id		= -1,
+		.parent		= &clk_pclk.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 30),
+	}, {
+		.name		= "pclk_fimgvg",
+		.id		= -1,
+		.parent		= &clk_pclk.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 31),
+	}, {
+		.name		= "sclk_spi_48",
+		.id		= 0,
+		.parent		= &clk_48m,
+		.enable		= s5p64x0_sclk_ctrl,
+		.ctrlbit	= (1 << 22),
+	}, {
+		.name		= "sclk_spi_48",
+		.id		= 1,
+		.parent		= &clk_48m,
+		.enable		= s5p64x0_sclk_ctrl,
+		.ctrlbit	= (1 << 23),
+	}, {
+		.name		= "mmc_48m",
+		.id		= 0,
+		.parent		= &clk_48m,
+		.enable		= s5p64x0_sclk_ctrl,
+		.ctrlbit	= (1 << 27),
+	}, {
+		.name		= "mmc_48m",
+		.id		= 1,
+		.parent		= &clk_48m,
+		.enable		= s5p64x0_sclk_ctrl,
+		.ctrlbit	= (1 << 28),
+	}, {
+		.name		= "mmc_48m",
+		.id		= 2,
+		.parent		= &clk_48m,
+		.enable		= s5p64x0_sclk_ctrl,
+		.ctrlbit	= (1 << 29),
+	},
+};
+
+/*
+ * The following clocks will be enabled during clock initialization.
+ */
+static struct clk init_clocks[] = {
+	{
+		.name		= "intc",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "mem",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 21),
+	}, {
+		.name		= "dma",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "uart",
+		.id		= 3,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 18),
+	},
+};
+
+static struct clk clk_iis_cd_v40 = {
+	.name		= "iis_cdclk_v40",
+	.id		= -1,
+};
+
+static struct clk clk_pcm_cd = {
+	.name		= "pcm_cdclk",
+	.id		= -1,
+};
+
+static struct clk *clkset_group1_list[] = {
+	&clk_mout_epll.clk,
+	&clk_dout_mpll.clk,
+	&clk_fin_epll,
+};
+
+static struct clksrc_sources clkset_group1 = {
+	.sources	= clkset_group1_list,
+	.nr_sources	= ARRAY_SIZE(clkset_group1_list),
+};
+
+static struct clk *clkset_uart_list[] = {
+	&clk_mout_epll.clk,
+	&clk_dout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_uart = {
+	.sources	= clkset_uart_list,
+	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
+};
+
+static struct clk *clkset_audio_list[] = {
+	&clk_mout_epll.clk,
+	&clk_dout_mpll.clk,
+	&clk_fin_epll,
+	&clk_iis_cd_v40,
+	&clk_pcm_cd,
+};
+
+static struct clksrc_sources clkset_audio = {
+	.sources	= clkset_audio_list,
+	.nr_sources	= ARRAY_SIZE(clkset_audio_list),
+};
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 0,
+			.ctrlbit	= (1 << 24),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 1,
+			.ctrlbit	= (1 << 25),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 2,
+			.ctrlbit	= (1 << 26),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "uclk1",
+			.id		= -1,
+			.ctrlbit	= (1 << 5),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_uart,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_spi",
+			.id		= 0,
+			.ctrlbit	= (1 << 20),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_spi",
+			.id		= 1,
+			.ctrlbit	= (1 << 21),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_post",
+			.id		= -1,
+			.ctrlbit	= (1 << 10),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_dispcon",
+			.id		= -1,
+			.ctrlbit	= (1 << 1),
+			.enable		= s5p64x0_sclk1_ctrl,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_fimgvg",
+			.id		= -1,
+			.ctrlbit	= (1 << 2),
+			.enable		= s5p64x0_sclk1_ctrl,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_audio2",
+			.id		= -1,
+			.ctrlbit	= (1 << 11),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_audio,
+		.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 0, .size = 3 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 24, .size = 4 },
+	},
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *sysclks[] = {
+	&clk_mout_apll,
+	&clk_mout_epll,
+	&clk_mout_mpll,
+	&clk_dout_mpll,
+	&clk_armclk,
+	&clk_hclk,
+	&clk_pclk,
+	&clk_hclk_low,
+	&clk_pclk_low,
+};
+
+void __init_or_cpufreq s5p6440_setup_clocks(void)
+{
+	struct clk *xtal_clk;
+
+	unsigned long xtal;
+	unsigned long fclk;
+	unsigned long hclk;
+	unsigned long hclk_low;
+	unsigned long pclk;
+	unsigned long pclk_low;
+
+	unsigned long apll;
+	unsigned long mpll;
+	unsigned long epll;
+	unsigned int ptr;
+
+	/* Set S5P6440 functions for clk_fout_epll */
+
+	clk_fout_epll.enable = s5p64x0_epll_enable;
+	clk_fout_epll.ops = &s5p6440_epll_ops;
+
+	clk_48m.enable = s5p64x0_clk48m_ctrl;
+
+	xtal_clk = clk_get(NULL, "ext_xtal");
+	BUG_ON(IS_ERR(xtal_clk));
+
+	xtal = clk_get_rate(xtal_clk);
+	clk_put(xtal_clk);
+
+	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502);
+	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502);
+	epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON),
+				__raw_readl(S5P64X0_EPLL_CON_K));
+
+	clk_fout_apll.rate = apll;
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+
+	printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
+			" E=%ld.%ldMHz\n",
+			print_mhz(apll), print_mhz(mpll), print_mhz(epll));
+
+	fclk = clk_get_rate(&clk_armclk.clk);
+	hclk = clk_get_rate(&clk_hclk.clk);
+	pclk = clk_get_rate(&clk_pclk.clk);
+	hclk_low = clk_get_rate(&clk_hclk_low.clk);
+	pclk_low = clk_get_rate(&clk_pclk_low.clk);
+
+	printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
+			" PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
+			print_mhz(hclk), print_mhz(hclk_low),
+			print_mhz(pclk), print_mhz(pclk_low));
+
+	clk_f.rate = fclk;
+	clk_h.rate = hclk;
+	clk_p.rate = pclk;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+		s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks[] __initdata = {
+	&clk_ext,
+	&clk_iis_cd_v40,
+	&clk_pcm_cd,
+};
+
+void __init s5p6440_register_clocks(void)
+{
+	struct clk *clkp;
+	int ret;
+	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));
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+		(clkp->enable)(clkp, 0);
+	}
+
+	s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
new file mode 100644
index 0000000..f9afb05
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c
@@ -0,0 +1,655 @@
+/* linux/arch/arm/mach-s5p64x0/clock-s5p6450.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P6450 - 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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/s5p64x0-clock.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p6450.h>
+
+static struct clksrc_clk clk_mout_dpll = {
+	.clk	= {
+		.name		= "mout_dpll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_dpll,
+	.reg_src	= { .reg = S5P64X0_CLK_SRC0, .shift = 5, .size = 1 },
+};
+
+static u32 epll_div[][5] = {
+	{ 133000000,	27307,	55, 2, 2 },
+	{ 100000000,	43691,	41, 2, 2 },
+	{ 480000000,	0,	80, 2, 0 },
+};
+
+static int s5p6450_epll_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned int epll_con, epll_con_k;
+	unsigned int i;
+
+	if (clk->rate == rate)	/* Return if nothing changed */
+		return 0;
+
+	epll_con = __raw_readl(S5P64X0_EPLL_CON);
+	epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K);
+
+	epll_con_k &= ~(PLL90XX_KDIV_MASK);
+	epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
+
+	for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
+		 if (epll_div[i][0] == rate) {
+			epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
+			epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
+				    (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
+				    (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(epll_div)) {
+		printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
+		return -EINVAL;
+	}
+
+	__raw_writel(epll_con, S5P64X0_EPLL_CON);
+	__raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+static struct clk_ops s5p6450_epll_ops = {
+	.get_rate = s5p64x0_epll_get_rate,
+	.set_rate = s5p6450_epll_set_rate,
+};
+
+static struct clksrc_clk clk_dout_epll = {
+	.clk	= {
+		.name		= "dout_epll",
+		.id		= -1,
+		.parent		= &clk_mout_epll.clk,
+	},
+	.reg_div	= { .reg = S5P64X0_CLK_DIV1, .shift = 24, .size = 4 },
+};
+
+static struct clksrc_clk clk_mout_hclk_sel = {
+	.clk	= {
+		.name		= "mout_hclk_sel",
+		.id		= -1,
+	},
+	.sources	= &clkset_hclk_low,
+	.reg_src	= { .reg = S5P64X0_OTHERS, .shift = 15, .size = 1 },
+};
+
+static struct clk *clkset_hclk_list[] = {
+	&clk_mout_hclk_sel.clk,
+	&clk_armclk.clk,
+};
+
+static struct clksrc_sources clkset_hclk = {
+	.sources	= clkset_hclk_list,
+	.nr_sources	= ARRAY_SIZE(clkset_hclk_list),
+};
+
+static struct clksrc_clk clk_hclk = {
+	.clk	= {
+		.name		= "clk_hclk",
+		.id		= -1,
+	},
+	.sources	= &clkset_hclk,
+	.reg_src	= { .reg = S5P64X0_OTHERS, .shift = 14, .size = 1 },
+	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk = {
+	.clk	= {
+		.name		= "clk_pclk",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+	},
+	.reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
+};
+static struct clksrc_clk clk_dout_pwm_ratio0 = {
+	.clk	= {
+		.name		= "clk_dout_pwm_ratio0",
+		.id		= -1,
+		.parent		= &clk_mout_hclk_sel.clk,
+	},
+	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_to_wdt_pwm = {
+	.clk	= {
+		.name		= "clk_pclk_to_wdt_pwm",
+		.id		= -1,
+		.parent		= &clk_dout_pwm_ratio0.clk,
+	},
+	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 20, .size = 4 },
+};
+
+static struct clksrc_clk clk_hclk_low = {
+	.clk	= {
+		.name		= "clk_hclk_low",
+		.id		= -1,
+	},
+	.sources	= &clkset_hclk_low,
+	.reg_src	= { .reg = S5P64X0_OTHERS, .shift = 6, .size = 1 },
+	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_low = {
+	.clk	= {
+		.name		= "clk_pclk_low",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+	},
+	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
+};
+
+/*
+ * The following clocks will be disabled during clock initialization. It is
+ * recommended to keep the following clocks disabled until the driver requests
+ * for enabling the clock.
+ */
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "usbhost",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "hsmmc",
+		.id		= 0,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 17),
+	}, {
+		.name		= "hsmmc",
+		.id		= 1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 18),
+	}, {
+		.name		= "hsmmc",
+		.id		= 2,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 19),
+	}, {
+		.name		= "usbotg",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 20),
+	}, {
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s5p64x0_hclk1_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "i2c",
+		.id		= 0,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 17),
+	}, {
+		.name		= "spi",
+		.id		= 0,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 21),
+	}, {
+		.name		= "spi",
+		.id		= 1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 22),
+	}, {
+		.name		= "iis",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 26),
+	}, {
+		.name		= "i2c",
+		.id		= 1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 27),
+	}, {
+		.name		= "dmc0",
+		.id		= -1,
+		.parent		= &clk_pclk.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 30),
+	}
+};
+
+/*
+ * The following clocks will be enabled during clock initialization.
+ */
+static struct clk init_clocks[] = {
+	{
+		.name		= "intc",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "mem",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 21),
+	}, {
+		.name		= "dma",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p64x0_hclk0_ctrl,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "uart",
+		.id		= 3,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_pclk_to_wdt_pwm.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p64x0_pclk_ctrl,
+		.ctrlbit	= (1 << 18),
+	},
+};
+
+static struct clk *clkset_uart_list[] = {
+	&clk_dout_epll.clk,
+	&clk_dout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_uart = {
+	.sources	= clkset_uart_list,
+	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
+};
+
+static struct clk *clkset_mali_list[] = {
+	&clk_mout_epll.clk,
+	&clk_mout_apll.clk,
+	&clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_mali = {
+	.sources	= clkset_mali_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mali_list),
+};
+
+static struct clk *clkset_group2_list[] = {
+	&clk_dout_epll.clk,
+	&clk_dout_mpll.clk,
+	&clk_ext_xtal_mux,
+};
+
+static struct clksrc_sources clkset_group2 = {
+	.sources	= clkset_group2_list,
+	.nr_sources	= ARRAY_SIZE(clkset_group2_list),
+};
+
+static struct clk *clkset_dispcon_list[] = {
+	&clk_dout_epll.clk,
+	&clk_dout_mpll.clk,
+	&clk_ext_xtal_mux,
+	&clk_mout_dpll.clk,
+};
+
+static struct clksrc_sources clkset_dispcon = {
+	.sources	= clkset_dispcon_list,
+	.nr_sources	= ARRAY_SIZE(clkset_dispcon_list),
+};
+
+static struct clk *clkset_hsmmc44_list[] = {
+	&clk_dout_epll.clk,
+	&clk_dout_mpll.clk,
+	&clk_ext_xtal_mux,
+	&s5p_clk_27m,
+	&clk_48m,
+};
+
+static struct clksrc_sources clkset_hsmmc44 = {
+	.sources	= clkset_hsmmc44_list,
+	.nr_sources	= ARRAY_SIZE(clkset_hsmmc44_list),
+};
+
+static struct clk *clkset_sclk_audio0_list[] = {
+	[0] = &clk_dout_epll.clk,
+	[1] = &clk_dout_mpll.clk,
+	[2] = &clk_ext_xtal_mux,
+	[3] = NULL,
+	[4] = NULL,
+};
+
+static struct clksrc_sources clkset_sclk_audio0 = {
+	.sources	= clkset_sclk_audio0_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio0_list),
+};
+
+static struct clksrc_clk clk_sclk_audio0 = {
+	.clk		= {
+		.name		= "audio-bus",
+		.id		= -1,
+		.enable		= s5p64x0_sclk_ctrl,
+		.ctrlbit	= (1 << 8),
+		.parent		= &clk_dout_epll.clk,
+	},
+	.sources	= &clkset_sclk_audio0,
+	.reg_src	= { .reg = S5P64X0_CLK_SRC1, .shift = 10, .size = 3 },
+	.reg_div	= { .reg = S5P64X0_CLK_DIV2, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk	= {
+			.name		= "sclk_mmc",
+			.id		= 0,
+			.ctrlbit	= (1 << 24),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_mmc",
+			.id		= 1,
+			.ctrlbit	= (1 << 25),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_mmc",
+			.id		= 2,
+			.ctrlbit	= (1 << 26),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "uclk1",
+			.id		= -1,
+			.ctrlbit	= (1 << 5),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_uart,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_spi",
+			.id		= 0,
+			.ctrlbit	= (1 << 20),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_spi",
+			.id		= 1,
+			.ctrlbit	= (1 << 21),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_fimc",
+			.id		= -1,
+			.ctrlbit	= (1 << 10),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "aclk_mali",
+			.id		= -1,
+			.ctrlbit	= (1 << 2),
+			.enable		= s5p64x0_sclk1_ctrl,
+		},
+		.sources = &clkset_mali,
+		.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_2d",
+			.id		= -1,
+			.ctrlbit	= (1 << 12),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_mali,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 30, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 20, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_usi",
+			.id		= -1,
+			.ctrlbit	= (1 << 7),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 10, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 16, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_camif",
+			.id		= -1,
+			.ctrlbit	= (1 << 6),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 28, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 20, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_dispcon",
+			.id		= -1,
+			.ctrlbit	= (1 << 1),
+			.enable		= s5p64x0_sclk1_ctrl,
+		},
+		.sources = &clkset_dispcon,
+		.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_hsmmc44",
+			.id		= -1,
+			.ctrlbit	= (1 << 30),
+			.enable		= s5p64x0_sclk_ctrl,
+		},
+		.sources = &clkset_hsmmc44,
+		.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 6, .size = 3 },
+		.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 28, .size = 4 },
+	},
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *sysclks[] = {
+	&clk_mout_apll,
+	&clk_mout_epll,
+	&clk_dout_epll,
+	&clk_mout_mpll,
+	&clk_dout_mpll,
+	&clk_armclk,
+	&clk_mout_hclk_sel,
+	&clk_dout_pwm_ratio0,
+	&clk_pclk_to_wdt_pwm,
+	&clk_hclk,
+	&clk_pclk,
+	&clk_hclk_low,
+	&clk_pclk_low,
+	&clk_sclk_audio0,
+};
+
+void __init_or_cpufreq s5p6450_setup_clocks(void)
+{
+	struct clk *xtal_clk;
+
+	unsigned long xtal;
+	unsigned long fclk;
+	unsigned long hclk;
+	unsigned long hclk_low;
+	unsigned long pclk;
+	unsigned long pclk_low;
+
+	unsigned long apll;
+	unsigned long mpll;
+	unsigned long epll;
+	unsigned long dpll;
+	unsigned int ptr;
+
+	/* Set S5P6450 functions for clk_fout_epll */
+
+	clk_fout_epll.enable = s5p64x0_epll_enable;
+	clk_fout_epll.ops = &s5p6450_epll_ops;
+
+	clk_48m.enable = s5p64x0_clk48m_ctrl;
+
+	xtal_clk = clk_get(NULL, "ext_xtal");
+	BUG_ON(IS_ERR(xtal_clk));
+
+	xtal = clk_get_rate(xtal_clk);
+	clk_put(xtal_clk);
+
+	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502);
+	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502);
+	epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON),
+				__raw_readl(S5P64X0_EPLL_CON_K));
+	dpll = s5p_get_pll46xx(xtal, __raw_readl(S5P6450_DPLL_CON),
+				__raw_readl(S5P6450_DPLL_CON_K), pll_4650c);
+
+	clk_fout_apll.rate = apll;
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+	clk_fout_dpll.rate = dpll;
+
+	printk(KERN_INFO "S5P6450: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
+			" E=%ld.%ldMHz, D=%ld.%ldMHz\n",
+			print_mhz(apll), print_mhz(mpll), print_mhz(epll),
+			print_mhz(dpll));
+
+	fclk = clk_get_rate(&clk_armclk.clk);
+	hclk = clk_get_rate(&clk_hclk.clk);
+	pclk = clk_get_rate(&clk_pclk.clk);
+	hclk_low = clk_get_rate(&clk_hclk_low.clk);
+	pclk_low = clk_get_rate(&clk_pclk_low.clk);
+
+	printk(KERN_INFO "S5P6450: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
+			" PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
+			print_mhz(hclk), print_mhz(hclk_low),
+			print_mhz(pclk), print_mhz(pclk_low));
+
+	clk_f.rate = fclk;
+	clk_h.rate = hclk;
+	clk_p.rate = pclk;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+		s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+void __init s5p6450_register_clocks(void)
+{
+	struct clk *clkp;
+	int ret;
+	int ptr;
+
+	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));
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+		(clkp->enable)(clkp, 0);
+	}
+
+	s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-s5p64x0/clock.c b/arch/arm/mach-s5p64x0/clock.c
new file mode 100644
index 0000000..523ba80
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/clock.c
@@ -0,0 +1,253 @@
+/* linux/arch/arm/mach-s5p64x0/clock.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p6440.h>
+#include <plat/s5p6450.h>
+
+struct clksrc_clk clk_mout_apll = {
+	.clk	= {
+		.name		= "mout_apll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_apll,
+	.reg_src	= { .reg = S5P64X0_CLK_SRC0, .shift = 0, .size = 1 },
+};
+
+struct clksrc_clk clk_mout_mpll = {
+	.clk	= {
+		.name		= "mout_mpll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_mpll,
+	.reg_src	= { .reg = S5P64X0_CLK_SRC0, .shift = 1, .size = 1 },
+};
+
+struct clksrc_clk clk_mout_epll = {
+	.clk	= {
+		.name		= "mout_epll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_epll,
+	.reg_src	= { .reg = S5P64X0_CLK_SRC0, .shift = 2, .size = 1 },
+};
+
+enum perf_level {
+	L0 = 532*1000,
+	L1 = 266*1000,
+	L2 = 133*1000,
+};
+
+static const u32 clock_table[][3] = {
+	/*{ARM_CLK, DIVarm, DIVhclk}*/
+	{L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
+	{L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
+	{L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
+};
+
+int s5p64x0_epll_enable(struct clk *clk, int enable)
+{
+	unsigned int ctrlbit = clk->ctrlbit;
+	unsigned int epll_con = __raw_readl(S5P64X0_EPLL_CON) & ~ctrlbit;
+
+	if (enable)
+		__raw_writel(epll_con | ctrlbit, S5P64X0_EPLL_CON);
+	else
+		__raw_writel(epll_con, S5P64X0_EPLL_CON);
+
+	return 0;
+}
+
+unsigned long s5p64x0_epll_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+unsigned long s5p64x0_armclk_get_rate(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk->parent);
+	u32 clkdiv;
+
+	/* divisor mask starts at bit0, so no need to shift */
+	clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK;
+
+	return rate / (clkdiv + 1);
+}
+
+unsigned long s5p64x0_armclk_round_rate(struct clk *clk, unsigned long rate)
+{
+	u32 iter;
+
+	for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
+		if (rate > clock_table[iter][0])
+			return clock_table[iter-1][0];
+	}
+
+	return clock_table[ARRAY_SIZE(clock_table) - 1][0];
+}
+
+int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 round_tmp;
+	u32 iter;
+	u32 clk_div0_tmp;
+	u32 cur_rate = clk->ops->get_rate(clk);
+	unsigned long flags;
+
+	round_tmp = clk->ops->round_rate(clk, rate);
+	if (round_tmp == cur_rate)
+		return 0;
+
+
+	for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
+		if (round_tmp == clock_table[iter][0])
+			break;
+	}
+
+	if (iter >= ARRAY_SIZE(clock_table))
+		iter = ARRAY_SIZE(clock_table) - 1;
+
+	local_irq_save(flags);
+	if (cur_rate > round_tmp) {
+		/* Frequency Down */
+		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
+		clk_div0_tmp |= clock_table[iter][1];
+		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
+				~(S5P64X0_CLKDIV0_HCLK_MASK);
+		clk_div0_tmp |= clock_table[iter][2];
+		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+
+	} else {
+		/* Frequency Up */
+		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
+				~(S5P64X0_CLKDIV0_HCLK_MASK);
+		clk_div0_tmp |= clock_table[iter][2];
+		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
+		clk_div0_tmp |= clock_table[iter][1];
+		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+	}
+	local_irq_restore(flags);
+
+	clk->rate = clock_table[iter][0];
+
+	return 0;
+}
+
+struct clk_ops s5p64x0_clkarm_ops = {
+	.get_rate	= s5p64x0_armclk_get_rate,
+	.set_rate	= s5p64x0_armclk_set_rate,
+	.round_rate	= s5p64x0_armclk_round_rate,
+};
+
+struct clksrc_clk clk_armclk = {
+	.clk	= {
+		.name		= "armclk",
+		.id		= 1,
+		.parent		= &clk_mout_apll.clk,
+		.ops		= &s5p64x0_clkarm_ops,
+	},
+	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 0, .size = 4 },
+};
+
+struct clksrc_clk clk_dout_mpll = {
+	.clk	= {
+		.name		= "dout_mpll",
+		.id		= -1,
+		.parent		= &clk_mout_mpll.clk,
+	},
+	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 4, .size = 1 },
+};
+
+struct clk *clkset_hclk_low_list[] = {
+	&clk_mout_apll.clk,
+	&clk_mout_mpll.clk,
+};
+
+struct clksrc_sources clkset_hclk_low = {
+	.sources	= clkset_hclk_low_list,
+	.nr_sources	= ARRAY_SIZE(clkset_hclk_low_list),
+};
+
+int s5p64x0_pclk_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P64X0_CLK_GATE_PCLK, clk, enable);
+}
+
+int s5p64x0_hclk0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK0, clk, enable);
+}
+
+int s5p64x0_hclk1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK1, clk, enable);
+}
+
+int s5p64x0_sclk_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK0, clk, enable);
+}
+
+int s5p64x0_sclk1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK1, clk, enable);
+}
+
+int s5p64x0_mem_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P64X0_CLK_GATE_MEM0, clk, enable);
+}
+
+int s5p64x0_clk48m_ctrl(struct clk *clk, int enable)
+{
+	unsigned long flags;
+	u32 val;
+
+	/* can't rely on clock lock, this register has other usages */
+	local_irq_save(flags);
+
+	val = __raw_readl(S5P64X0_OTHERS);
+	if (enable)
+		val |= S5P64X0_OTHERS_USB_SIG_MASK;
+	else
+		val &= ~S5P64X0_OTHERS_USB_SIG_MASK;
+
+	__raw_writel(val, S5P64X0_OTHERS);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
diff --git a/arch/arm/mach-s5p64x0/cpu.c b/arch/arm/mach-s5p64x0/cpu.c
new file mode 100644
index 0000000..b8d02eb
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/cpu.c
@@ -0,0 +1,209 @@
+/* linux/arch/arm/mach-s5p64x0/cpu.c
+ *
+ * Copyright (c) 2009-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/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/proc-fns.h>
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include <plat/regs-serial.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/s5p6440.h>
+#include <plat/s5p6450.h>
+#include <plat/adc-core.h>
+
+/* Initial IO mappings */
+
+static struct map_desc s5p64x0_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_GPIO,
+		.pfn		= __phys_to_pfn(S5P64X0_PA_GPIO),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC0,
+		.pfn		= __phys_to_pfn(S5P64X0_PA_VIC0),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC1,
+		.pfn		= __phys_to_pfn(S5P64X0_PA_VIC1),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc s5p6440_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S3C_VA_UART,
+		.pfn		= __phys_to_pfn(S5P6440_PA_UART(0)),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc s5p6450_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S3C_VA_UART,
+		.pfn		= __phys_to_pfn(S5P6450_PA_UART(0)),
+		.length		= SZ_512K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_UART + SZ_512K,
+		.pfn		= __phys_to_pfn(S5P6450_PA_UART(5)),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void s5p64x0_idle(void)
+{
+	unsigned long val;
+
+	if (!need_resched()) {
+		val = __raw_readl(S5P64X0_PWR_CFG);
+		val &= ~(0x3 << 5);
+		val |= (0x1 << 5);
+		__raw_writel(val, S5P64X0_PWR_CFG);
+
+		cpu_do_idle();
+	}
+	local_irq_enable();
+}
+
+/*
+ * s5p64x0_map_io
+ *
+ * register the standard CPU IO areas
+ */
+
+void __init s5p6440_map_io(void)
+{
+	/* initialize any device information early */
+	s3c_adc_setname("s3c64xx-adc");
+
+	iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
+	iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+}
+
+void __init s5p6450_map_io(void)
+{
+	/* initialize any device information early */
+	s3c_adc_setname("s3c64xx-adc");
+
+	iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
+	iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+}
+
+/*
+ * s5p64x0_init_clocks
+ *
+ * register and setup the CPU clocks
+ */
+
+void __init s5p6440_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+	s3c24xx_register_baseclocks(xtal);
+	s5p_register_clocks(xtal);
+	s5p6440_register_clocks();
+	s5p6440_setup_clocks();
+}
+
+void __init s5p6450_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+	s3c24xx_register_baseclocks(xtal);
+	s5p_register_clocks(xtal);
+	s5p6450_register_clocks();
+	s5p6450_setup_clocks();
+}
+
+/*
+ * s5p64x0_init_irq
+ *
+ * register the CPU interrupts
+ */
+
+void __init s5p6440_init_irq(void)
+{
+	/* S5P6440 supports 2 VIC */
+	u32 vic[2];
+
+	/*
+	 * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)]
+	 * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22]
+	 */
+	vic[0] = 0xff800ae7;
+	vic[1] = 0xffbf23e5;
+
+	s5p_init_irq(vic, ARRAY_SIZE(vic));
+}
+
+void __init s5p6450_init_irq(void)
+{
+	/* S5P6450 supports only 2 VIC */
+	u32 vic[2];
+
+	/*
+	 * VIC0 is missing IRQ_VIC0[(13-15), (21-22)]
+	 * VIC1 is missing IRQ VIC1[12, 14, 23]
+	 */
+	vic[0] = 0xff9f1fff;
+	vic[1] = 0xff7fafff;
+
+	s5p_init_irq(vic, ARRAY_SIZE(vic));
+}
+
+struct sysdev_class s5p64x0_sysclass = {
+	.name	= "s5p64x0-core",
+};
+
+static struct sys_device s5p64x0_sysdev = {
+	.cls	= &s5p64x0_sysclass,
+};
+
+static int __init s5p64x0_core_init(void)
+{
+	return sysdev_class_register(&s5p64x0_sysclass);
+}
+core_initcall(s5p64x0_core_init);
+
+int __init s5p64x0_init(void)
+{
+	printk(KERN_INFO "S5P64X0(S5P6440/S5P6450): Initializing architecture\n");
+
+	/* set idle function */
+	pm_idle = s5p64x0_idle;
+
+	return sysdev_register(&s5p64x0_sysdev);
+}
diff --git a/arch/arm/mach-s5p64x0/dev-audio.c b/arch/arm/mach-s5p64x0/dev-audio.c
new file mode 100644
index 0000000..fa097bd
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/dev-audio.c
@@ -0,0 +1,164 @@
+/* linux/arch/arm/mach-s5p64x0/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 int s5p6440_cfg_i2s(struct platform_device *pdev)
+{
+	/* configure GPIO for i2s port */
+	switch (pdev->id) {
+	case -1:
+		s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5));
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int s5p6450_cfg_i2s(struct platform_device *pdev)
+{
+	/* configure GPIO for i2s port */
+	switch (pdev->id) {
+	case -1:
+		s3c_gpio_cfgpin(S5P6450_GPB(4), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6450_GPR(4), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6450_GPR(5), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6450_GPR(6), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6450_GPR(7), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6450_GPR(8), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6450_GPR(13), S3C_GPIO_SFN(5));
+		s3c_gpio_cfgpin(S5P6450_GPR(14), S3C_GPIO_SFN(5));
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct s3c_audio_pdata s5p6440_i2s_pdata = {
+	.cfg_gpio = s5p6440_cfg_i2s,
+};
+
+static struct s3c_audio_pdata s5p6450_i2s_pdata = {
+	.cfg_gpio = s5p6450_cfg_i2s,
+};
+
+static struct resource s5p64x0_iis0_resource[] = {
+	[0] = {
+		.start	= S5P64X0_PA_I2S,
+		.end	= S5P64X0_PA_I2S + 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,
+	},
+};
+
+struct platform_device s5p6440_device_iis = {
+	.name		= "s3c64xx-iis-v4",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p64x0_iis0_resource),
+	.resource	= s5p64x0_iis0_resource,
+	.dev = {
+		.platform_data = &s5p6440_i2s_pdata,
+	},
+};
+
+struct platform_device s5p6450_device_iis0 = {
+	.name		= "s3c64xx-iis-v4",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p64x0_iis0_resource),
+	.resource	= s5p64x0_iis0_resource,
+	.dev = {
+		.platform_data = &s5p6450_i2s_pdata,
+	},
+};
+
+/* PCM Controller platform_devices */
+
+static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev)
+{
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2));
+		break;
+
+	default:
+		printk(KERN_DEBUG "Invalid PCM Controller number!");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct s3c_audio_pdata s5p6440_pcm_pdata = {
+	.cfg_gpio = s5p6440_pcm_cfg_gpio,
+};
+
+static struct resource s5p6440_pcm0_resource[] = {
+	[0] = {
+		.start	= S5P64X0_PA_PCM,
+		.end	= S5P64X0_PA_PCM + 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 s5p6440_device_pcm = {
+	.name		= "samsung-pcm",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p6440_pcm0_resource),
+	.resource	= s5p6440_pcm0_resource,
+	.dev = {
+		.platform_data = &s5p6440_pcm_pdata,
+	},
+};
diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c
new file mode 100644
index 0000000..5b69ec4
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/dev-spi.c
@@ -0,0 +1,232 @@
+/* linux/arch/arm/mach-s5p64x0/dev-spi.c
+ *
+ * Copyright (c) 2010 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 <mach/dma.h>
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/regs-clock.h>
+#include <mach/spi-clocks.h>
+
+#include <plat/s3c64xx-spi.h>
+#include <plat/gpio-cfg.h>
+
+static char *s5p64x0_spi_src_clks[] = {
+	[S5P64X0_SPI_SRCCLK_PCLK] = "pclk",
+	[S5P64X0_SPI_SRCCLK_SCLK] = "sclk_spi",
+};
+
+/* SPI Controller platform_devices */
+
+/* Since we emulate multi-cs capability, we do not touch the CS.
+ * The emulated CS is toggled by board specific mechanism, as it can
+ * be either some immediate GPIO or some signal out of some other
+ * chip in between ... or some yet another way.
+ * We simply do not assume anything about CS.
+ */
+static int s5p6440_spi_cfg_gpio(struct platform_device *pdev)
+{
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin(S5P6440_GPC(0), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6440_GPC(1), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6440_GPC(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(S5P6440_GPC(0), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S5P6440_GPC(1), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S5P6440_GPC(2), S3C_GPIO_PULL_UP);
+		break;
+
+	case 1:
+		s3c_gpio_cfgpin(S5P6440_GPC(4), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6440_GPC(5), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6440_GPC(6), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(S5P6440_GPC(4), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S5P6440_GPC(5), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S5P6440_GPC(6), S3C_GPIO_PULL_UP);
+		break;
+
+	default:
+		dev_err(&pdev->dev, "Invalid SPI Controller number!");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int s5p6450_spi_cfg_gpio(struct platform_device *pdev)
+{
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin(S5P6450_GPC(0), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6450_GPC(1), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6450_GPC(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(S5P6450_GPC(0), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S5P6450_GPC(1), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S5P6450_GPC(2), S3C_GPIO_PULL_UP);
+		break;
+
+	case 1:
+		s3c_gpio_cfgpin(S5P6450_GPC(4), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6450_GPC(5), S3C_GPIO_SFN(2));
+		s3c_gpio_cfgpin(S5P6450_GPC(6), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(S5P6450_GPC(4), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S5P6450_GPC(5), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S5P6450_GPC(6), S3C_GPIO_PULL_UP);
+		break;
+
+	default:
+		dev_err(&pdev->dev, "Invalid SPI Controller number!");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct resource s5p64x0_spi0_resource[] = {
+	[0] = {
+		.start	= S5P64X0_PA_SPI0,
+		.end	= S5P64X0_PA_SPI0 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_SPI0_TX,
+		.end	= DMACH_SPI0_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_SPI0_RX,
+		.end	= DMACH_SPI0_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= IRQ_SPI0,
+		.end	= IRQ_SPI0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c64xx_spi_info s5p6440_spi0_pdata = {
+	.cfg_gpio	= s5p6440_spi_cfg_gpio,
+	.fifo_lvl_mask	= 0x1ff,
+	.rx_lvl_offset	= 15,
+};
+
+static struct s3c64xx_spi_info s5p6450_spi0_pdata = {
+	.cfg_gpio	= s5p6450_spi_cfg_gpio,
+	.fifo_lvl_mask	= 0x1ff,
+	.rx_lvl_offset	= 15,
+};
+
+static u64 spi_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5p64x0_device_spi0 = {
+	.name		= "s3c64xx-spi",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p64x0_spi0_resource),
+	.resource	= s5p64x0_spi0_resource,
+	.dev = {
+		.dma_mask		= &spi_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+static struct resource s5p64x0_spi1_resource[] = {
+	[0] = {
+		.start	= S5P64X0_PA_SPI1,
+		.end	= S5P64X0_PA_SPI1 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_SPI1_TX,
+		.end	= DMACH_SPI1_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_SPI1_RX,
+		.end	= DMACH_SPI1_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= IRQ_SPI1,
+		.end	= IRQ_SPI1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c64xx_spi_info s5p6440_spi1_pdata = {
+	.cfg_gpio	= s5p6440_spi_cfg_gpio,
+	.fifo_lvl_mask	= 0x7f,
+	.rx_lvl_offset	= 15,
+};
+
+static struct s3c64xx_spi_info s5p6450_spi1_pdata = {
+	.cfg_gpio	= s5p6450_spi_cfg_gpio,
+	.fifo_lvl_mask	= 0x7f,
+	.rx_lvl_offset	= 15,
+};
+
+struct platform_device s5p64x0_device_spi1 = {
+	.name		= "s3c64xx-spi",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(s5p64x0_spi1_resource),
+	.resource	= s5p64x0_spi1_resource,
+	.dev = {
+		.dma_mask		= &spi_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
+{
+	unsigned int id;
+	struct s3c64xx_spi_info *pd;
+
+	id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
+
+	/* Reject invalid configuration */
+	if (!num_cs || src_clk_nr < 0
+			|| src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) {
+		printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
+		return;
+	}
+
+	switch (cntrlr) {
+	case 0:
+		if (id == 0x50000)
+			pd = &s5p6450_spi0_pdata;
+		else
+			pd = &s5p6440_spi0_pdata;
+
+		s5p64x0_device_spi0.dev.platform_data = pd;
+		break;
+	case 1:
+		if (id == 0x50000)
+			pd = &s5p6450_spi1_pdata;
+		else
+			pd = &s5p6440_spi1_pdata;
+
+		s5p64x0_device_spi1.dev.platform_data = pd;
+		break;
+	default:
+		printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
+							__func__, cntrlr);
+		return;
+	}
+
+	pd->num_cs = num_cs;
+	pd->src_clk_nr = src_clk_nr;
+	pd->src_clk_name = s5p64x0_spi_src_clks[src_clk_nr];
+}
diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c
new file mode 100644
index 0000000..29a8c24
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/dma.c
@@ -0,0 +1,149 @@
+/* linux/arch/arm/mach-s5p64x0/dma.c
+ *
+ * Copyright (c) 2010 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 <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/regs-clock.h>
+
+#include <plat/devs.h>
+#include <plat/s3c-pl330-pdata.h>
+
+static u64 dma_dmamask = DMA_BIT_MASK(32);
+
+static struct resource s5p64x0_pdma_resource[] = {
+	[0] = {
+		.start	= S5P64X0_PA_PDMA,
+		.end	= S5P64X0_PA_PDMA + SZ_4K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_DMA0,
+		.end	= IRQ_DMA0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
+	.peri = {
+		[0] = DMACH_UART0_RX,
+		[1] = DMACH_UART0_TX,
+		[2] = DMACH_UART1_RX,
+		[3] = DMACH_UART1_TX,
+		[4] = DMACH_UART2_RX,
+		[5] = DMACH_UART2_TX,
+		[6] = DMACH_UART3_RX,
+		[7] = DMACH_UART3_TX,
+		[8] = DMACH_MAX,
+		[9] = DMACH_MAX,
+		[10] = DMACH_PCM0_TX,
+		[11] = DMACH_PCM0_RX,
+		[12] = DMACH_I2S0_TX,
+		[13] = DMACH_I2S0_RX,
+		[14] = DMACH_SPI0_TX,
+		[15] = DMACH_SPI0_RX,
+		[16] = DMACH_MAX,
+		[17] = DMACH_MAX,
+		[18] = DMACH_MAX,
+		[19] = DMACH_MAX,
+		[20] = DMACH_SPI1_TX,
+		[21] = DMACH_SPI1_RX,
+		[22] = DMACH_MAX,
+		[23] = DMACH_MAX,
+		[24] = DMACH_MAX,
+		[25] = DMACH_MAX,
+		[26] = DMACH_MAX,
+		[27] = DMACH_MAX,
+		[28] = DMACH_MAX,
+		[29] = DMACH_PWM,
+		[30] = DMACH_MAX,
+		[31] = DMACH_MAX,
+	},
+};
+
+static struct s3c_pl330_platdata s5p6450_pdma_pdata = {
+	.peri = {
+		[0] = DMACH_UART0_RX,
+		[1] = DMACH_UART0_TX,
+		[2] = DMACH_UART1_RX,
+		[3] = DMACH_UART1_TX,
+		[4] = DMACH_UART2_RX,
+		[5] = DMACH_UART2_TX,
+		[6] = DMACH_UART3_RX,
+		[7] = DMACH_UART3_TX,
+		[8] = DMACH_UART4_RX,
+		[9] = DMACH_UART4_TX,
+		[10] = DMACH_PCM0_TX,
+		[11] = DMACH_PCM0_RX,
+		[12] = DMACH_I2S0_TX,
+		[13] = DMACH_I2S0_RX,
+		[14] = DMACH_SPI0_TX,
+		[15] = DMACH_SPI0_RX,
+		[16] = DMACH_PCM1_TX,
+		[17] = DMACH_PCM1_RX,
+		[18] = DMACH_PCM2_TX,
+		[19] = DMACH_PCM2_RX,
+		[20] = DMACH_SPI1_TX,
+		[21] = DMACH_SPI1_RX,
+		[22] = DMACH_USI_TX,
+		[23] = DMACH_USI_RX,
+		[24] = DMACH_MAX,
+		[25] = DMACH_I2S1_TX,
+		[26] = DMACH_I2S1_RX,
+		[27] = DMACH_I2S2_TX,
+		[28] = DMACH_I2S2_RX,
+		[29] = DMACH_PWM,
+		[30] = DMACH_UART5_RX,
+		[31] = DMACH_UART5_TX,
+	},
+};
+
+static struct platform_device s5p64x0_device_pdma = {
+	.name		= "s3c-pl330",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p64x0_pdma_resource),
+	.resource	= s5p64x0_pdma_resource,
+	.dev		= {
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+static int __init s5p64x0_dma_init(void)
+{
+	unsigned int id;
+
+	id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
+
+	if (id == 0x50000)
+		s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata;
+	else
+		s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
+
+	platform_device_register(&s5p64x0_device_pdma);
+
+	return 0;
+}
+arch_initcall(s5p64x0_dma_init);
diff --git a/arch/arm/mach-s5p64x0/gpio.c b/arch/arm/mach-s5p64x0/gpio.c
new file mode 100644
index 0000000..39159dd
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/gpio.c
@@ -0,0 +1,342 @@
+/* linux/arch/arm/mach-s5p64x0/gpio.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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 <mach/regs-gpio.h>
+
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
+/* To be implemented S5P6450 GPIO */
+
+/*
+ * S5P6440 GPIO bank summary:
+ *
+ * Bank	GPIOs	Style	SlpCon	ExtInt Group
+ * A	6	4Bit	Yes	1
+ * B	7	4Bit	Yes	1
+ * C	8	4Bit	Yes	2
+ * F	2	2Bit	Yes	4 [1]
+ * G	7	4Bit	Yes	5
+ * H	10	4Bit[2]	Yes	6
+ * I	16	2Bit	Yes	None
+ * J	12	2Bit	Yes	None
+ * N	16	2Bit	No	IRQ_EINT
+ * P	8	2Bit	Yes	8
+ * R	15	4Bit[2]	Yes	8
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
+
+static int s5p64x0_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
+					     unsigned int offset)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+	unsigned long flags;
+
+	switch (offset) {
+	case 6:
+		offset += 1;
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		regcon -= 4;
+		break;
+	default:
+		offset -= 7;
+		break;
+	}
+
+	s3c_gpio_lock(ourchip, flags);
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(offset));
+	__raw_writel(con, regcon);
+
+	s3c_gpio_unlock(ourchip, flags);
+
+	return 0;
+}
+
+static int s5p64x0_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
+					      unsigned int offset, int value)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+	unsigned long dat;
+	unsigned long flags;
+	unsigned con_offset  = offset;
+
+	switch (con_offset) {
+	case 6:
+		con_offset += 1;
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		regcon -= 4;
+		break;
+	default:
+		con_offset -= 7;
+		break;
+	}
+
+	s3c_gpio_lock(ourchip, flags);
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(con_offset));
+	con |= 0x1 << con_4bit_shift(con_offset);
+
+	dat = __raw_readl(base + GPIODAT_OFF);
+	if (value)
+		dat |= 1 << offset;
+	else
+		dat &= ~(1 << offset);
+
+	__raw_writel(con, regcon);
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	s3c_gpio_unlock(ourchip, flags);
+
+	return 0;
+}
+
+int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
+				   unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift;
+	u32 con;
+
+	switch (off) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		shift = (off & 7) * 4;
+		reg -= 4;
+		break;
+	case 6:
+		shift = ((off + 1) & 7) * 4;
+		reg -= 4;
+	default:
+		shift = ((off + 1) & 7) * 4;
+		break;
+	}
+
+	if (s3c_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0xf << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+
+static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = {
+	{
+		.cfg_eint	= 0,
+	}, {
+		.cfg_eint	= 7,
+	}, {
+		.cfg_eint	= 3,
+		.set_config	= s5p64x0_gpio_setcfg_4bit_rbank,
+	}, {
+		.cfg_eint	= 0,
+		.set_config	= s3c_gpio_setcfg_s3c24xx,
+		.get_config	= s3c_gpio_getcfg_s3c24xx,
+	}, {
+		.cfg_eint	= 2,
+		.set_config	= s3c_gpio_setcfg_s3c24xx,
+		.get_config	= s3c_gpio_getcfg_s3c24xx,
+	}, {
+		.cfg_eint	= 3,
+		.set_config	= s3c_gpio_setcfg_s3c24xx,
+		.get_config	= s3c_gpio_getcfg_s3c24xx,
+	},
+};
+
+static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
+	{
+		.base	= S5P6440_GPA_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPA(0),
+			.ngpio	= S5P6440_GPIO_A_NR,
+			.label	= "GPA",
+		},
+	}, {
+		.base	= S5P6440_GPB_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPB(0),
+			.ngpio	= S5P6440_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.base	= S5P6440_GPC_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPC(0),
+			.ngpio	= S5P6440_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.base	= S5P6440_GPG_BASE,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPG(0),
+			.ngpio	= S5P6440_GPIO_G_NR,
+			.label	= "GPG",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
+	{
+		.base	= S5P6440_GPH_BASE + 0x4,
+		.config	= &s5p64x0_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPH(0),
+			.ngpio	= S5P6440_GPIO_H_NR,
+			.label	= "GPH",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = {
+	{
+		.base	= S5P6440_GPR_BASE + 0x4,
+		.config	= &s5p64x0_gpio_cfgs[2],
+		.chip	= {
+			.base	= S5P6440_GPR(0),
+			.ngpio	= S5P6440_GPIO_R_NR,
+			.label	= "GPR",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
+	{
+		.base	= S5P6440_GPF_BASE,
+		.config	= &s5p64x0_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6440_GPF(0),
+			.ngpio	= S5P6440_GPIO_F_NR,
+			.label	= "GPF",
+		},
+	}, {
+		.base	= S5P6440_GPI_BASE,
+		.config	= &s5p64x0_gpio_cfgs[3],
+		.chip	= {
+			.base	= S5P6440_GPI(0),
+			.ngpio	= S5P6440_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.base	= S5P6440_GPJ_BASE,
+		.config	= &s5p64x0_gpio_cfgs[3],
+		.chip	= {
+			.base	= S5P6440_GPJ(0),
+			.ngpio	= S5P6440_GPIO_J_NR,
+			.label	= "GPJ",
+		},
+	}, {
+		.base	= S5P6440_GPN_BASE,
+		.config	= &s5p64x0_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6440_GPN(0),
+			.ngpio	= S5P6440_GPIO_N_NR,
+			.label	= "GPN",
+		},
+	}, {
+		.base	= S5P6440_GPP_BASE,
+		.config	= &s5p64x0_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6440_GPP(0),
+			.ngpio	= S5P6440_GPIO_P_NR,
+			.label	= "GPP",
+		},
+	},
+};
+
+void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chipcfg++) {
+		if (!chipcfg->set_config)
+			chipcfg->set_config	= s3c_gpio_setcfg_s3c64xx_4bit;
+		if (!chipcfg->get_config)
+			chipcfg->get_config	= s3c_gpio_getcfg_s3c64xx_4bit;
+		if (!chipcfg->set_pull)
+			chipcfg->set_pull	= s3c_gpio_setpull_updown;
+		if (!chipcfg->get_pull)
+			chipcfg->get_pull	= s3c_gpio_getpull_updown;
+	}
+}
+
+static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
+						int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chip++) {
+		chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input;
+		chip->chip.direction_output =
+					s5p64x0_gpiolib_rbank_4bit2_output;
+		s3c_gpiolib_add(chip);
+	}
+}
+
+static int __init s5p6440_gpiolib_init(void)
+{
+	struct s3c_gpio_chip *chips = s5p6440_gpio_2bit;
+	int nr_chips = ARRAY_SIZE(s5p6440_gpio_2bit);
+
+	s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
+				ARRAY_SIZE(s5p64x0_gpio_cfgs));
+
+	for (; nr_chips > 0; nr_chips--, chips++)
+		s3c_gpiolib_add(chips);
+
+	samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit,
+				ARRAY_SIZE(s5p6440_gpio_4bit));
+
+	samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
+				ARRAY_SIZE(s5p6440_gpio_4bit2));
+
+	s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2,
+				ARRAY_SIZE(s5p6440_gpio_rbank_4bit2));
+
+	return 0;
+}
+arch_initcall(s5p6440_gpiolib_init);
diff --git a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
new file mode 100644
index 0000000..79b04e6
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
@@ -0,0 +1,33 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2009-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.
+*/
+
+/* pull in the relevant register and map files. */
+
+#include <plat/map-base.h>
+#include <plat/map-s5p.h>
+
+#include <plat/regs-serial.h>
+
+	.macro addruart, rp, rv
+		mov	\rp, #0xE0000000
+		orr	\rp, \rp, #0x00100000
+		ldr	\rp, [\rp, #0x118 ]
+		and	\rp, \rp, #0xff000
+		teq	\rp, #0x50000		@@ S5P6450
+		ldreq	\rp, =0xEC800000
+		movne	\rp, #0xEC000000	@@ S5P6440
+		ldrne	\rv, = S3C_VA_UART
+#if CONFIG_DEBUG_S3C_UART != 0
+		add	\rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
+#endif
+	.endm
+
+#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s5p6440/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h
similarity index 100%
rename from arch/arm/mach-s5p6440/include/mach/dma.h
rename to arch/arm/mach-s5p64x0/include/mach/dma.h
diff --git a/arch/arm/mach-s5p64x0/include/mach/entry-macro.S b/arch/arm/mach-s5p64x0/include/mach/entry-macro.S
new file mode 100644
index 0000000..10b62b4
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/entry-macro.S
@@ -0,0 +1,16 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/entry-macro.S
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Low-level IRQ helper macros for the Samsung S5P64X0
+ *
+ * This program is free software; you can redistribute 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/map.h>
+#include <plat/irqs.h>
+
+#include <asm/entry-macro-vic2.S>
diff --git a/arch/arm/mach-s5p64x0/include/mach/gpio.h b/arch/arm/mach-s5p64x0/include/mach/gpio.h
new file mode 100644
index 0000000..5486c8f
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/gpio.h
@@ -0,0 +1,139 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/gpio.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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
+
+/* GPIO bank sizes */
+
+#define S5P6440_GPIO_A_NR	(6)
+#define S5P6440_GPIO_B_NR	(7)
+#define S5P6440_GPIO_C_NR	(8)
+#define S5P6440_GPIO_F_NR	(2)
+#define S5P6440_GPIO_G_NR	(7)
+#define S5P6440_GPIO_H_NR	(10)
+#define S5P6440_GPIO_I_NR	(16)
+#define S5P6440_GPIO_J_NR	(12)
+#define S5P6440_GPIO_N_NR	(16)
+#define S5P6440_GPIO_P_NR	(8)
+#define S5P6440_GPIO_R_NR	(15)
+
+#define S5P6450_GPIO_A_NR	(6)
+#define S5P6450_GPIO_B_NR	(7)
+#define S5P6450_GPIO_C_NR	(8)
+#define S5P6450_GPIO_D_NR	(8)
+#define S5P6450_GPIO_F_NR	(2)
+#define S5P6450_GPIO_G_NR	(14)
+#define S5P6450_GPIO_H_NR	(10)
+#define S5P6450_GPIO_I_NR	(16)
+#define S5P6450_GPIO_J_NR	(12)
+#define S5P6450_GPIO_K_NR	(5)
+#define S5P6450_GPIO_N_NR	(16)
+#define S5P6450_GPIO_P_NR	(11)
+#define S5P6450_GPIO_Q_NR	(14)
+#define S5P6450_GPIO_R_NR	(15)
+#define S5P6450_GPIO_S_NR	(8)
+
+/* GPIO bank numbers */
+
+/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
+ * space for debugging purposes so that any accidental
+ * change from one gpio bank to another can be caught.
+*/
+
+#define S5P64X0_GPIO_NEXT(__gpio) \
+	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+enum s5p6440_gpio_number {
+	S5P6440_GPIO_A_START	= 0,
+	S5P6440_GPIO_B_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_A),
+	S5P6440_GPIO_C_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_B),
+	S5P6440_GPIO_F_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_C),
+	S5P6440_GPIO_G_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_F),
+	S5P6440_GPIO_H_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_G),
+	S5P6440_GPIO_I_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_H),
+	S5P6440_GPIO_J_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_I),
+	S5P6440_GPIO_N_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_J),
+	S5P6440_GPIO_P_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_N),
+	S5P6440_GPIO_R_START	= S5P64X0_GPIO_NEXT(S5P6440_GPIO_P),
+};
+
+enum s5p6450_gpio_number {
+	S5P6450_GPIO_A_START	= 0,
+	S5P6450_GPIO_B_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_A),
+	S5P6450_GPIO_C_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_B),
+	S5P6450_GPIO_D_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_C),
+	S5P6450_GPIO_F_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_D),
+	S5P6450_GPIO_G_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_F),
+	S5P6450_GPIO_H_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_G),
+	S5P6450_GPIO_I_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_H),
+	S5P6450_GPIO_J_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_I),
+	S5P6450_GPIO_K_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_J),
+	S5P6450_GPIO_N_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_K),
+	S5P6450_GPIO_P_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_N),
+	S5P6450_GPIO_Q_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_P),
+	S5P6450_GPIO_R_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_Q),
+	S5P6450_GPIO_S_START	= S5P64X0_GPIO_NEXT(S5P6450_GPIO_R),
+};
+
+/* GPIO number definitions */
+
+#define S5P6440_GPA(_nr)	(S5P6440_GPIO_A_START + (_nr))
+#define S5P6440_GPB(_nr)	(S5P6440_GPIO_B_START + (_nr))
+#define S5P6440_GPC(_nr)	(S5P6440_GPIO_C_START + (_nr))
+#define S5P6440_GPF(_nr)	(S5P6440_GPIO_F_START + (_nr))
+#define S5P6440_GPG(_nr)	(S5P6440_GPIO_G_START + (_nr))
+#define S5P6440_GPH(_nr)	(S5P6440_GPIO_H_START + (_nr))
+#define S5P6440_GPI(_nr)	(S5P6440_GPIO_I_START + (_nr))
+#define S5P6440_GPJ(_nr)	(S5P6440_GPIO_J_START + (_nr))
+#define S5P6440_GPN(_nr)	(S5P6440_GPIO_N_START + (_nr))
+#define S5P6440_GPP(_nr)	(S5P6440_GPIO_P_START + (_nr))
+#define S5P6440_GPR(_nr)	(S5P6440_GPIO_R_START + (_nr))
+
+#define S5P6450_GPA(_nr)	(S5P6450_GPIO_A_START + (_nr))
+#define S5P6450_GPB(_nr)	(S5P6450_GPIO_B_START + (_nr))
+#define S5P6450_GPC(_nr)	(S5P6450_GPIO_C_START + (_nr))
+#define S5P6450_GPD(_nr)	(S5P6450_GPIO_D_START + (_nr))
+#define S5P6450_GPF(_nr)	(S5P6450_GPIO_F_START + (_nr))
+#define S5P6450_GPG(_nr)	(S5P6450_GPIO_G_START + (_nr))
+#define S5P6450_GPH(_nr)	(S5P6450_GPIO_H_START + (_nr))
+#define S5P6450_GPI(_nr)	(S5P6450_GPIO_I_START + (_nr))
+#define S5P6450_GPJ(_nr)	(S5P6450_GPIO_J_START + (_nr))
+#define S5P6450_GPK(_nr)	(S5P6450_GPIO_K_START + (_nr))
+#define S5P6450_GPN(_nr)	(S5P6450_GPIO_N_START + (_nr))
+#define S5P6450_GPP(_nr)	(S5P6450_GPIO_P_START + (_nr))
+#define S5P6450_GPQ(_nr)	(S5P6450_GPIO_Q_START + (_nr))
+#define S5P6450_GPR(_nr)	(S5P6450_GPIO_R_START + (_nr))
+#define S5P6450_GPS(_nr)	(S5P6450_GPIO_S_START + (_nr))
+
+/* the end of the S5P64X0 specific gpios */
+
+#define S5P6440_GPIO_END	(S5P6440_GPR(S5P6440_GPIO_R_NR) + 1)
+#define S5P6450_GPIO_END	(S5P6450_GPS(S5P6450_GPIO_S_NR) + 1)
+
+#define S5P64X0_GPIO_END	(S5P6440_GPIO_END > S5P6450_GPIO_END ?	\
+				 S5P6440_GPIO_END : S5P6450_GPIO_END)
+
+#define S3C_GPIO_END		S5P64X0_GPIO_END
+
+/* define the number of gpios we need to the one after the last GPIO range */
+
+#define ARCH_NR_GPIOS		(S5P64X0_GPIO_END + CONFIG_SAMSUNG_GPIO_EXTRA)
+
+#include <asm-generic/gpio.h>
+
+#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/hardware.h b/arch/arm/mach-s5p64x0/include/mach/hardware.h
new file mode 100644
index 0000000..d3e8799
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/hardware.h
@@ -0,0 +1,18 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/hardware.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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-s5p64x0/include/mach/i2c.h b/arch/arm/mach-s5p64x0/include/mach/i2c.h
new file mode 100644
index 0000000..887d252
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/i2c.h
@@ -0,0 +1,17 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/i2c.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 I2C 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.
+*/
+
+extern void s5p6440_i2c0_cfg_gpio(struct platform_device *dev);
+extern void s5p6440_i2c1_cfg_gpio(struct platform_device *dev);
+
+extern void s5p6450_i2c0_cfg_gpio(struct platform_device *dev);
+extern void s5p6450_i2c1_cfg_gpio(struct platform_device *dev);
diff --git a/arch/arm/mach-s5p64x0/include/mach/io.h b/arch/arm/mach-s5p64x0/include/mach/io.h
new file mode 100644
index 0000000..a3e095c
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/io.h
@@ -0,0 +1,25 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/io.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben-linux@fluff.org>
+ *
+ * Default IO routines for S5P64X0 based
+ *
+ * This program is free software; you can 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
+
+/* No current ISA/PCI bus support. */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif
diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
new file mode 100644
index 0000000..513abff
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
@@ -0,0 +1,142 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/irqs.h
+ *
+ * Copyright 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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>
+
+/* VIC0 */
+
+#define IRQ_EINT0_3		S5P_IRQ_VIC0(0)
+#define IRQ_EINT4_11		S5P_IRQ_VIC0(1)
+#define IRQ_RTC_TIC		S5P_IRQ_VIC0(2)
+#define IRQ_IIS1		S5P_IRQ_VIC0(3)	/* for only S5P6450 */
+#define IRQ_IIS2		S5P_IRQ_VIC0(4)	/* for only S5P6450 */
+#define IRQ_IIC1		S5P_IRQ_VIC0(5)
+#define IRQ_I2SV40		S5P_IRQ_VIC0(6)
+#define IRQ_GPS			S5P_IRQ_VIC0(7)	/* for only S5P6450 */
+
+#define IRQ_2D			S5P_IRQ_VIC0(11)
+#define IRQ_TIMER0_VIC		S5P_IRQ_VIC0(23)
+#define IRQ_TIMER1_VIC		S5P_IRQ_VIC0(24)
+#define IRQ_TIMER2_VIC		S5P_IRQ_VIC0(25)
+#define IRQ_WDT			S5P_IRQ_VIC0(26)
+#define IRQ_TIMER3_VIC		S5P_IRQ_VIC0(27)
+#define IRQ_TIMER4_VIC		S5P_IRQ_VIC0(28)
+#define IRQ_DISPCON0		S5P_IRQ_VIC0(29)
+#define IRQ_DISPCON1		S5P_IRQ_VIC0(30)
+#define IRQ_DISPCON2		S5P_IRQ_VIC0(31)
+
+/* VIC1 */
+
+#define IRQ_EINT12_15		S5P_IRQ_VIC1(0)
+#define IRQ_PCM0		S5P_IRQ_VIC1(2)
+#define IRQ_PCM1		S5P_IRQ_VIC1(3)	/* for only S5P6450 */
+#define IRQ_PCM2		S5P_IRQ_VIC1(4)	/* for only S5P6450 */
+#define IRQ_UART0		S5P_IRQ_VIC1(5)
+#define IRQ_UART1		S5P_IRQ_VIC1(6)
+#define IRQ_UART2		S5P_IRQ_VIC1(7)
+#define IRQ_UART3		S5P_IRQ_VIC1(8)
+#define IRQ_DMA0		S5P_IRQ_VIC1(9)
+#define IRQ_UART4		S5P_IRQ_VIC1(10)	/* S5P6450 */
+#define IRQ_UART5		S5P_IRQ_VIC1(11)	/* S5P6450 */
+#define IRQ_NFC			S5P_IRQ_VIC1(13)
+#define IRQ_USI			S5P_IRQ_VIC1(15)	/* S5P6450 */
+#define IRQ_SPI0		S5P_IRQ_VIC1(16)
+#define IRQ_SPI1		S5P_IRQ_VIC1(17)
+#define IRQ_HSMMC2		S5P_IRQ_VIC1(17)	/* Shared */
+#define IRQ_IIC			S5P_IRQ_VIC1(18)
+#define IRQ_DISPCON3		S5P_IRQ_VIC1(19)
+#define IRQ_EINT_GROUPS		S5P_IRQ_VIC1(21)
+#define IRQ_PMU			S5P_IRQ_VIC1(23)	/* S5P6440 */
+#define IRQ_HSMMC0		S5P_IRQ_VIC1(24)
+#define IRQ_HSMMC1		S5P_IRQ_VIC1(25)
+#define IRQ_OTG			S5P_IRQ_VIC1(26)
+#define IRQ_DSI			S5P_IRQ_VIC1(27)
+#define IRQ_RTC_ALARM		S5P_IRQ_VIC1(28)
+#define IRQ_TSI			S5P_IRQ_VIC1(29)
+#define IRQ_PENDN		S5P_IRQ_VIC1(30)
+#define IRQ_TC			IRQ_PENDN
+#define IRQ_ADC			S5P_IRQ_VIC1(31)
+
+/* UART interrupts, S5P6450 has 5 UARTs */
+#define IRQ_S5P_UART_BASE4	(96)
+#define IRQ_S5P_UART_BASE5	(100)
+
+#define IRQ_S5P_UART_RX4	(IRQ_S5P_UART_BASE4 + UART_IRQ_RXD)
+#define IRQ_S5P_UART_TX4	(IRQ_S5P_UART_BASE4 + UART_IRQ_TXD)
+#define IRQ_S5P_UART_ERR4	(IRQ_S5P_UART_BASE4 + UART_IRQ_ERR)
+
+#define IRQ_S5P_UART_RX5	(IRQ_S5P_UART_BASE5 + UART_IRQ_RXD)
+#define IRQ_S5P_UART_TX5	(IRQ_S5P_UART_BASE5 + UART_IRQ_TXD)
+#define IRQ_S5P_UART_ERR5	(IRQ_S5P_UART_BASE5 + UART_IRQ_ERR)
+
+/* S3C compatibilty defines */
+#define IRQ_S3CUART_RX4		IRQ_S5P_UART_RX4
+#define IRQ_S3CUART_RX5		IRQ_S5P_UART_RX5
+
+/* S5P6450 EINT feature will be added */
+
+/*
+ * Since the IRQ_EINT(x) are a linear mapping on s5p6440 we just defined
+ * them as an IRQ_EINT(x) macro from S5P_IRQ_EINT_BASE which we place
+ * after the pair of VICs.
+ */
+
+#define S5P_IRQ_EINT_BASE	(S5P_IRQ_VIC1(31) + 6)
+
+#define S5P_EINT(x)		((x) + S5P_IRQ_EINT_BASE)
+
+#define S5P_EINT_BASE1		(S5P_IRQ_EINT_BASE)
+/*
+ * S5P6440 has 0-15 external interrupts in group 0. Only these can be used
+ * to wake up from sleep. If request is beyond this range, by mistake, a large
+ * return value for an irq number should be indication of something amiss.
+ */
+#define S5P_EINT_BASE2		(0xf0000000)
+
+/*
+ * Next the external interrupt groups. These are similar to the IRQ_EINT(x)
+ * that they are sourced from the GPIO pins but with a different scheme for
+ * priority and source indication.
+ *
+ * The IRQ_EINT(x) can be thought of as 'group 0' of the available GPIO
+ * interrupts, but for historical reasons they are kept apart from these
+ * next interrupts.
+ *
+ * Use IRQ_EINT_GROUP(group, offset) to get the number for use in the
+ * machine specific support files.
+ */
+
+/* Actually, #6 and #7 are missing in the EINT_GROUP1 */
+#define IRQ_EINT_GROUP1_NR	(15)
+#define IRQ_EINT_GROUP2_NR	(8)
+#define IRQ_EINT_GROUP5_NR	(7)
+#define IRQ_EINT_GROUP6_NR	(10)
+/* Actually, #0, #1 and #2 are missing in the EINT_GROUP8 */
+#define IRQ_EINT_GROUP8_NR	(11)
+
+#define IRQ_EINT_GROUP_BASE	S5P_EINT(16)
+#define IRQ_EINT_GROUP1_BASE	(IRQ_EINT_GROUP_BASE + 0)
+#define IRQ_EINT_GROUP2_BASE	(IRQ_EINT_GROUP1_BASE + IRQ_EINT_GROUP1_NR)
+#define IRQ_EINT_GROUP5_BASE	(IRQ_EINT_GROUP2_BASE + IRQ_EINT_GROUP2_NR)
+#define IRQ_EINT_GROUP6_BASE	(IRQ_EINT_GROUP5_BASE + IRQ_EINT_GROUP5_NR)
+#define IRQ_EINT_GROUP8_BASE	(IRQ_EINT_GROUP6_BASE + IRQ_EINT_GROUP6_NR)
+
+#define IRQ_EINT_GROUP(grp, x)	(IRQ_EINT_GROUP##grp##_BASE + (x))
+
+/* Set the default NR_IRQS */
+
+#define NR_IRQS			(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
+
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h
new file mode 100644
index 0000000..31e5341
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/map.h
@@ -0,0 +1,83 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/map.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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>
+#include <plat/map-s5p.h>
+
+#define S5P64X0_PA_SDRAM	(0x20000000)
+
+#define S5P64X0_PA_CHIPID	(0xE0000000)
+#define S5P_PA_CHIPID		S5P64X0_PA_CHIPID
+
+#define S5P64X0_PA_SYSCON	(0xE0100000)
+#define S5P_PA_SYSCON		S5P64X0_PA_SYSCON
+
+#define S5P64X0_PA_GPIO		(0xE0308000)
+
+#define S5P64X0_PA_VIC0		(0xE4000000)
+#define S5P64X0_PA_VIC1		(0xE4100000)
+
+#define S5P64X0_PA_PDMA		(0xE9000000)
+
+#define S5P64X0_PA_TIMER	(0xEA000000)
+#define S5P_PA_TIMER		S5P64X0_PA_TIMER
+
+#define S5P64X0_PA_RTC		(0xEA100000)
+
+#define S5P64X0_PA_WDT		(0xEA200000)
+
+#define S5P6440_PA_UART(x)	(0xEC000000 + ((x) * S3C_UART_OFFSET))
+#define S5P6450_PA_UART(x)	((x < 5) ? (0xEC800000 + ((x) * S3C_UART_OFFSET)) : (0xEC000000))
+
+#define S5P_PA_UART0		S5P6450_PA_UART(0)
+#define S5P_PA_UART1		S5P6450_PA_UART(1)
+#define S5P_PA_UART2		S5P6450_PA_UART(2)
+#define S5P_PA_UART3		S5P6450_PA_UART(3)
+#define S5P_PA_UART4		S5P6450_PA_UART(4)
+#define S5P_PA_UART5		S5P6450_PA_UART(5)
+
+#define S5P_SZ_UART		SZ_256
+
+#define S5P6440_PA_IIC0		(0xEC104000)
+#define S5P6440_PA_IIC1		(0xEC20F000)
+#define S5P6450_PA_IIC0		(0xEC100000)
+#define S5P6450_PA_IIC1		(0xEC200000)
+
+#define S5P64X0_PA_SPI0		(0xEC400000)
+#define S5P64X0_PA_SPI1		(0xEC500000)
+
+#define S5P64X0_PA_HSOTG	(0xED100000)
+
+#define S5P64X0_PA_HSMMC(x)	(0xED800000 + ((x) * 0x100000))
+
+#define S5P64X0_PA_I2S		(0xF2000000)
+
+#define S5P64X0_PA_PCM		(0xF2100000)
+
+#define S5P64X0_PA_ADC		(0xF3000000)
+
+/* compatibiltiy defines. */
+
+#define S3C_PA_HSMMC0		S5P64X0_PA_HSMMC(0)
+#define S3C_PA_HSMMC1		S5P64X0_PA_HSMMC(1)
+#define S3C_PA_HSMMC2		S5P64X0_PA_HSMMC(2)
+#define S3C_PA_IIC		S5P6440_PA_IIC0
+#define S3C_PA_IIC1		S5P6440_PA_IIC1
+#define S3C_PA_RTC		S5P64X0_PA_RTC
+#define S3C_PA_WDT		S5P64X0_PA_WDT
+
+#define SAMSUNG_PA_ADC		S5P64X0_PA_ADC
+
+#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/memory.h b/arch/arm/mach-s5p64x0/include/mach/memory.h
new file mode 100644
index 0000000..1b036b0
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/memory.h
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/memory.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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(0x20000000)
+#define CONSISTENT_DMA_SIZE	SZ_8M
+
+#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h b/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
new file mode 100644
index 0000000..19fff8b7
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
@@ -0,0 +1,68 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
+ *
+ * Copyright (c) 2009-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/
+ *
+ * S5P64X0 - 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 0;
+}
+
+/**
+ * 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 0
+
+#endif /* __ASM_ARCH_PWMCLK_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
new file mode 100644
index 0000000..58e1bc8
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
@@ -0,0 +1,63 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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)			(S3C_VA_SYS + (x))
+
+#define S5P64X0_APLL_CON		S5P_CLKREG(0x0C)
+#define S5P64X0_MPLL_CON		S5P_CLKREG(0x10)
+#define S5P64X0_EPLL_CON		S5P_CLKREG(0x14)
+#define S5P64X0_EPLL_CON_K		S5P_CLKREG(0x18)
+
+#define S5P64X0_CLK_SRC0		S5P_CLKREG(0x1C)
+
+#define S5P64X0_CLK_DIV0		S5P_CLKREG(0x20)
+#define S5P64X0_CLK_DIV1		S5P_CLKREG(0x24)
+#define S5P64X0_CLK_DIV2		S5P_CLKREG(0x28)
+
+#define S5P64X0_CLK_GATE_HCLK0		S5P_CLKREG(0x30)
+#define S5P64X0_CLK_GATE_PCLK		S5P_CLKREG(0x34)
+#define S5P64X0_CLK_GATE_SCLK0		S5P_CLKREG(0x38)
+#define S5P64X0_CLK_GATE_MEM0		S5P_CLKREG(0x3C)
+
+#define S5P64X0_CLK_DIV3		S5P_CLKREG(0x40)
+
+#define S5P64X0_CLK_GATE_HCLK1		S5P_CLKREG(0x44)
+#define S5P64X0_CLK_GATE_SCLK1		S5P_CLKREG(0x48)
+
+#define S5P6450_DPLL_CON		S5P_CLKREG(0x50)
+#define S5P6450_DPLL_CON_K		S5P_CLKREG(0x54)
+
+#define S5P64X0_CLK_SRC1		S5P_CLKREG(0x10C)
+
+#define S5P64X0_SYS_ID			S5P_CLKREG(0x118)
+#define S5P64X0_SYS_OTHERS		S5P_CLKREG(0x11C)
+
+#define S5P64X0_PWR_CFG			S5P_CLKREG(0x804)
+#define S5P64X0_OTHERS			S5P_CLKREG(0x900)
+
+#define S5P64X0_CLKDIV0_HCLK_SHIFT	(8)
+#define S5P64X0_CLKDIV0_HCLK_MASK	(0xF << S5P64X0_CLKDIV0_HCLK_SHIFT)
+
+#define S5P64X0_OTHERS_USB_SIG_MASK	(1 << 16)
+
+/* Compatibility defines */
+
+#define ARM_CLK_DIV			S5P64X0_CLK_DIV0
+#define ARM_DIV_RATIO_SHIFT		0
+#define ARM_DIV_MASK			(0xF << ARM_DIV_RATIO_SHIFT)
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
new file mode 100644
index 0000000..85f448e
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
@@ -0,0 +1,62 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - GPIO 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>
+
+/* Will be implemented S5P6442 GPIOlib */
+
+/* Base addresses for each of the banks */
+
+#define S5P6440_GPA_BASE		(S5P_VA_GPIO + 0x0000)
+#define S5P6440_GPB_BASE		(S5P_VA_GPIO + 0x0020)
+#define S5P6440_GPC_BASE		(S5P_VA_GPIO + 0x0040)
+#define S5P6440_GPF_BASE		(S5P_VA_GPIO + 0x00A0)
+#define S5P6440_GPG_BASE		(S5P_VA_GPIO + 0x00C0)
+#define S5P6440_GPH_BASE		(S5P_VA_GPIO + 0x00E0)
+#define S5P6440_GPI_BASE		(S5P_VA_GPIO + 0x0100)
+#define S5P6440_GPJ_BASE		(S5P_VA_GPIO + 0x0120)
+#define S5P6440_GPN_BASE		(S5P_VA_GPIO + 0x0830)
+#define S5P6440_GPP_BASE		(S5P_VA_GPIO + 0x0160)
+#define S5P6440_GPR_BASE		(S5P_VA_GPIO + 0x0290)
+
+#define S5P6440_EINT0CON0		(S5P_VA_GPIO + 0x900)
+#define S5P6440_EINT0FLTCON0		(S5P_VA_GPIO + 0x910)
+#define S5P6440_EINT0FLTCON1		(S5P_VA_GPIO + 0x914)
+#define S5P6440_EINT0MASK		(S5P_VA_GPIO + 0x920)
+#define S5P6440_EINT0PEND		(S5P_VA_GPIO + 0x924)
+
+/* for LCD */
+
+#define S5P6440_SPCON_LCD_SEL_RGB	(1 << 0)
+#define S5P6440_SPCON_LCD_SEL_MASK	(3 << 0)
+
+/*
+ * These set of macros are not really useful for the
+ * GPF/GPI/GPJ/GPN/GPP, useful for others set of GPIO's (4 bit)
+ */
+
+#define S5P6440_GPIO_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
+#define S5P6440_GPIO_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
+#define S5P6440_GPIO_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
+
+/*
+ * Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit)
+ */
+
+#define S5P6440_GPIO2_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
+#define S5P6440_GPIO2_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
+#define S5P6440_GPIO2_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
+
+#endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-irq.h b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
new file mode 100644
index 0000000..4aaebda
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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/vic.h>
+#include <mach/map.h>
+
+#endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h b/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h
new file mode 100644
index 0000000..ff85b4b
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h
@@ -0,0 +1,46 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for s5p64x0 clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+extern struct clksrc_clk clk_mout_apll;
+extern struct clksrc_clk clk_mout_mpll;
+extern struct clksrc_clk clk_mout_epll;
+
+extern int s5p64x0_epll_enable(struct clk *clk, int enable);
+extern unsigned long s5p64x0_epll_get_rate(struct clk *clk);
+
+extern unsigned long s5p64x0_armclk_get_rate(struct clk *clk);
+extern unsigned long s5p64x0_armclk_round_rate(struct clk *clk, unsigned long rate);
+extern int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate);
+
+extern struct clk_ops s5p64x0_clkarm_ops;
+
+extern struct clksrc_clk clk_armclk;
+extern struct clksrc_clk clk_dout_mpll;
+
+extern struct clk *clkset_hclk_low_list[];
+extern struct clksrc_sources clkset_hclk_low;
+
+extern int s5p64x0_pclk_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_hclk0_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_hclk1_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_sclk_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_sclk1_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_mem_ctrl(struct clk *clk, int enable);
+
+extern int s5p64x0_clk48m_ctrl(struct clk *clk, int enable);
+
+#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
new file mode 100644
index 0000000..170a20a
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
@@ -0,0 +1,20 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
+ *
+ * Copyright (c) 2010 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.
+*/
+
+#ifndef __ASM_ARCH_SPI_CLKS_H
+#define __ASM_ARCH_SPI_CLKS_H __FILE__
+
+#define S5P64X0_SPI_SRCCLK_PCLK		0
+#define S5P64X0_SPI_SRCCLK_SCLK		1
+
+#endif /* __ASM_ARCH_SPI_CLKS_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/system.h b/arch/arm/mach-s5p64x0/include/mach/system.h
new file mode 100644
index 0000000..60f5753
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/system.h
@@ -0,0 +1,23 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/system.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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-s5p64x0/include/mach/tick.h b/arch/arm/mach-s5p64x0/include/mach/tick.h
new file mode 100644
index 0000000..00aa7f1
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/tick.h
@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/tick.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S5P64X0 - Timer tick support 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_TICK_H
+#define __ASM_ARCH_TICK_H __FILE__
+
+static inline u32 s3c24xx_ostimer_pending(void)
+{
+	u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);
+	return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0)));
+}
+
+#define TICK_MAX	(0xffffffff)
+
+#endif /* __ASM_ARCH_TICK_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/timex.h b/arch/arm/mach-s5p64x0/include/mach/timex.h
new file mode 100644
index 0000000..4b91faa
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/timex.h
@@ -0,0 +1,27 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/timex.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (c) 2003-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S5P64X0 - 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
+
+/* 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-s5p64x0/include/mach/uncompress.h b/arch/arm/mach-s5p64x0/include/mach/uncompress.h
new file mode 100644
index 0000000..c65b229
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/uncompress.h
@@ -0,0 +1,212 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/uncompress.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - 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
+
+#include <mach/map.h>
+
+/*
+ * cannot use commonly <plat/uncompress.h>
+ * because uart base of S5P6440 and S5P6450 is different
+ */
+
+typedef unsigned int upf_t;	/* cannot include linux/serial_core.h */
+
+/* uart setup */
+
+static unsigned int fifo_mask;
+static unsigned int fifo_max;
+
+/* forward declerations */
+
+static void arch_detect_cpu(void);
+
+/* defines for UART registers */
+
+#include <plat/regs-serial.h>
+#include <plat/regs-watchdog.h>
+
+/* working in physical space... */
+#undef S3C2410_WDOGREG
+#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x)))
+
+/* how many bytes we allow into the FIFO at a time in FIFO mode */
+#define FIFO_MAX	 (14)
+
+static unsigned long uart_base;
+
+static __inline__ void get_uart_base(void)
+{
+	unsigned int chipid;
+
+	chipid = *(const volatile unsigned int __force *) 0xE0100118;
+
+	uart_base = S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT;
+
+	if ((chipid & 0xff000) == 0x50000)
+		uart_base += 0xEC800000;
+	else
+		uart_base += 0xEC000000;
+}
+
+static __inline__ void uart_wr(unsigned int reg, unsigned int val)
+{
+	volatile unsigned int *ptr;
+
+	get_uart_base();
+	ptr = (volatile unsigned int *)(reg + uart_base);
+	*ptr = val;
+}
+
+static __inline__ unsigned int uart_rd(unsigned int reg)
+{
+	volatile unsigned int *ptr;
+
+	get_uart_base();
+	ptr = (volatile unsigned int *)(reg + uart_base);
+	return *ptr;
+}
+
+/*
+ * we can deal with the case the UARTs are being run
+ * in FIFO mode, so that we don't hold up our execution
+ * waiting for tx to happen...
+ */
+
+static void putc(int ch)
+{
+	if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
+		int level;
+
+		while (1) {
+			level = uart_rd(S3C2410_UFSTAT);
+			level &= fifo_mask;
+
+			if (level < fifo_max)
+				break;
+		}
+
+	} else {
+		/* not using fifos */
+
+		while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
+			barrier();
+	}
+
+	/* write byte to transmission register */
+	uart_wr(S3C2410_UTXH, ch);
+}
+
+static inline void flush(void)
+{
+}
+
+#define __raw_writel(d, ad)			\
+	do {							\
+		*((volatile unsigned int __force *)(ad)) = (d); \
+	} while (0)
+
+/*
+ * CONFIG_S3C_BOOT_WATCHDOG
+ *
+ * Simple boot-time watchdog setup, to reboot the system if there is
+ * any problem with the boot process
+ */
+
+#ifdef CONFIG_S3C_BOOT_WATCHDOG
+
+#define WDOG_COUNT (0xff00)
+
+static inline void arch_decomp_wdog(void)
+{
+	__raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+}
+
+static void arch_decomp_wdog_start(void)
+{
+	__raw_writel(WDOG_COUNT, S3C2410_WTDAT);
+	__raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+	__raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON);
+}
+
+#else
+#define arch_decomp_wdog_start()
+#define arch_decomp_wdog()
+#endif
+
+#ifdef CONFIG_S3C_BOOT_ERROR_RESET
+
+static void arch_decomp_error(const char *x)
+{
+	putstr("\n\n");
+	putstr(x);
+	putstr("\n\n -- System resetting\n");
+
+	__raw_writel(0x4000, S3C2410_WTDAT);
+	__raw_writel(0x4000, S3C2410_WTCNT);
+	__raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
+
+	while(1);
+}
+
+#define arch_error arch_decomp_error
+#endif
+
+#ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO
+static inline void arch_enable_uart_fifo(void)
+{
+	u32 fifocon = uart_rd(S3C2410_UFCON);
+
+	if (!(fifocon & S3C2410_UFCON_FIFOMODE)) {
+		fifocon |= S3C2410_UFCON_RESETBOTH;
+		uart_wr(S3C2410_UFCON, fifocon);
+
+		/* wait for fifo reset to complete */
+		while (1) {
+			fifocon = uart_rd(S3C2410_UFCON);
+			if (!(fifocon & S3C2410_UFCON_RESETBOTH))
+				break;
+		}
+	}
+}
+#else
+#define arch_enable_uart_fifo() do { } while(0)
+#endif
+
+static void arch_decomp_setup(void)
+{
+	/*
+	 * we may need to setup the uart(s) here if we are not running
+	 * on an BAST... the BAST will have left the uarts configured
+	 * after calling linux.
+	 */
+
+	arch_detect_cpu();
+	arch_decomp_wdog_start();
+
+	/*
+	 * Enable the UART FIFOs if they where not enabled and our
+	 * configuration says we should turn them on.
+	 */
+
+	arch_enable_uart_fifo();
+}
+
+
+
+static void arch_detect_cpu(void)
+{
+	/* we do not need to do any cpu detection here at the moment. */
+}
+
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/vmalloc.h b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h
new file mode 100644
index 0000000..97a9df3
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2010 Ben Dooks <ben-linux@fluff.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.
+ *
+ * S3C6400 vmalloc definition
+*/
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END	0xE0000000UL
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5p64x0/init.c b/arch/arm/mach-s5p64x0/init.c
new file mode 100644
index 0000000..79833ca
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/init.c
@@ -0,0 +1,73 @@
+/* linux/arch/arm/mach-s5p64x0/init.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5P64X0 - Init support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+
+#include <mach/map.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/s5p6440.h>
+#include <plat/s5p6450.h>
+#include <plat/regs-serial.h>
+
+static struct s3c24xx_uart_clksrc s5p64x0_serial_clocks[] = {
+	[0] = {
+		.name		= "pclk_low",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+	[1] = {
+		.name		= "uclk1",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+};
+
+/* uart registration process */
+
+void __init s5p64x0_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->clocks = s5p64x0_serial_clocks;
+			tcfg->clocks_size = ARRAY_SIZE(s5p64x0_serial_clocks);
+		}
+	}
+}
+
+void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	int uart;
+
+	for (uart = 0; uart < no; uart++) {
+		s5p_uart_resources[uart].resources->start = S5P6440_PA_UART(uart);
+		s5p_uart_resources[uart].resources->end = S5P6440_PA_UART(uart) + S5P_SZ_UART;
+	}
+
+	s5p64x0_common_init_uarts(cfg, no);
+	s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
+}
+
+void __init s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s5p64x0_common_init_uarts(cfg, no);
+	s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
+}
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
new file mode 100644
index 0000000..87c3f03
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -0,0 +1,161 @@
+/* linux/arch/arm/mach-s5p64x0/mach-smdk6440.c
+ *
+ * Copyright (c) 2009-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/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/i2c.h>
+
+#include <plat/regs-serial.h>
+#include <plat/gpio-cfg.h>
+#include <plat/s5p6440.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/iic.h>
+#include <plat/pll.h>
+#include <plat/adc.h>
+#include <plat/ts.h>
+
+#define SMDK6440_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				S3C2410_UCON_RXILEVEL |		\
+				S3C2410_UCON_TXIRQMODE |	\
+				S3C2410_UCON_RXIRQMODE |	\
+				S3C2410_UCON_RXFIFO_TOI |	\
+				S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDK6440_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define SMDK6440_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				S3C2440_UFCON_TXTRIG16 |	\
+				S3C2410_UFCON_RXTRIG8)
+
+static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= SMDK6440_UCON_DEFAULT,
+		.ulcon		= SMDK6440_ULCON_DEFAULT,
+		.ufcon		= SMDK6440_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= SMDK6440_UCON_DEFAULT,
+		.ulcon		= SMDK6440_ULCON_DEFAULT,
+		.ufcon		= SMDK6440_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= SMDK6440_UCON_DEFAULT,
+		.ulcon		= SMDK6440_ULCON_DEFAULT,
+		.ufcon		= SMDK6440_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= SMDK6440_UCON_DEFAULT,
+		.ulcon		= SMDK6440_ULCON_DEFAULT,
+		.ufcon		= SMDK6440_UFCON_DEFAULT,
+	},
+};
+
+static struct platform_device *smdk6440_devices[] __initdata = {
+	&s3c_device_adc,
+	&s3c_device_rtc,
+	&s3c_device_i2c0,
+	&s3c_device_i2c1,
+	&s3c_device_ts,
+	&s3c_device_wdt,
+	&s5p6440_device_iis,
+};
+
+static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
+	.flags		= 0,
+	.slave_addr	= 0x10,
+	.frequency	= 100*1000,
+	.sda_delay	= 100,
+	.cfg_gpio	= s5p6440_i2c0_cfg_gpio,
+};
+
+static struct s3c2410_platform_i2c s5p6440_i2c1_data __initdata = {
+	.flags		= 0,
+	.bus_num	= 1,
+	.slave_addr	= 0x10,
+	.frequency	= 100*1000,
+	.sda_delay	= 100,
+	.cfg_gpio	= s5p6440_i2c1_cfg_gpio,
+};
+
+static struct i2c_board_info smdk6440_i2c_devs0[] __initdata = {
+	{ I2C_BOARD_INFO("24c08", 0x50), },
+};
+
+static struct i2c_board_info smdk6440_i2c_devs1[] __initdata = {
+	/* To be populated */
+};
+
+static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
+	.delay			= 10000,
+	.presc			= 49,
+	.oversampling_shift	= 2,
+};
+
+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));
+}
+
+static void __init smdk6440_machine_init(void)
+{
+	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+
+	s3c_i2c0_set_platdata(&s5p6440_i2c0_data);
+	s3c_i2c1_set_platdata(&s5p6440_i2c1_data);
+	i2c_register_board_info(0, smdk6440_i2c_devs0,
+			ARRAY_SIZE(smdk6440_i2c_devs0));
+	i2c_register_board_info(1, smdk6440_i2c_devs1,
+			ARRAY_SIZE(smdk6440_i2c_devs1));
+
+	platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
+}
+
+MACHINE_START(SMDK6440, "SMDK6440")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.boot_params	= S5P64X0_PA_SDRAM + 0x100,
+
+	.init_irq	= s5p6440_init_irq,
+	.map_io		= smdk6440_map_io,
+	.init_machine	= smdk6440_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
new file mode 100644
index 0000000..d609f5a
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -0,0 +1,180 @@
+/* linux/arch/arm/mach-s5p64x0/mach-smdk6450.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/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/i2c.h>
+
+#include <plat/regs-serial.h>
+#include <plat/gpio-cfg.h>
+#include <plat/s5p6450.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/iic.h>
+#include <plat/pll.h>
+#include <plat/adc.h>
+#include <plat/ts.h>
+
+#define SMDK6450_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				S3C2410_UCON_RXILEVEL |		\
+				S3C2410_UCON_TXIRQMODE |	\
+				S3C2410_UCON_RXIRQMODE |	\
+				S3C2410_UCON_RXFIFO_TOI |	\
+				S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDK6450_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define SMDK6450_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				S3C2440_UFCON_TXTRIG16 |	\
+				S3C2410_UFCON_RXTRIG8)
+
+static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= SMDK6450_UCON_DEFAULT,
+		.ulcon		= SMDK6450_ULCON_DEFAULT,
+		.ufcon		= SMDK6450_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= SMDK6450_UCON_DEFAULT,
+		.ulcon		= SMDK6450_ULCON_DEFAULT,
+		.ufcon		= SMDK6450_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= SMDK6450_UCON_DEFAULT,
+		.ulcon		= SMDK6450_ULCON_DEFAULT,
+		.ufcon		= SMDK6450_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= SMDK6450_UCON_DEFAULT,
+		.ulcon		= SMDK6450_ULCON_DEFAULT,
+		.ufcon		= SMDK6450_UFCON_DEFAULT,
+	},
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 4
+	[4] = {
+		.hwport		= 4,
+		.flags		= 0,
+		.ucon		= SMDK6450_UCON_DEFAULT,
+		.ulcon		= SMDK6450_ULCON_DEFAULT,
+		.ufcon		= SMDK6450_UFCON_DEFAULT,
+	},
+#endif
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 5
+	[5] = {
+		.hwport		= 5,
+		.flags		= 0,
+		.ucon		= SMDK6450_UCON_DEFAULT,
+		.ulcon		= SMDK6450_ULCON_DEFAULT,
+		.ufcon		= SMDK6450_UFCON_DEFAULT,
+	},
+#endif
+};
+
+static struct platform_device *smdk6450_devices[] __initdata = {
+	&s3c_device_adc,
+	&s3c_device_rtc,
+	&s3c_device_i2c0,
+	&s3c_device_i2c1,
+	&s3c_device_ts,
+	&s3c_device_wdt,
+	&s5p6450_device_iis0,
+	/* s5p6450_device_spi0 will be added */
+};
+
+static struct s3c2410_platform_i2c s5p6450_i2c0_data __initdata = {
+	.flags		= 0,
+	.slave_addr	= 0x10,
+	.frequency	= 100*1000,
+	.sda_delay	= 100,
+	.cfg_gpio	= s5p6450_i2c0_cfg_gpio,
+};
+
+static struct s3c2410_platform_i2c s5p6450_i2c1_data __initdata = {
+	.flags		= 0,
+	.bus_num	= 1,
+	.slave_addr	= 0x10,
+	.frequency	= 100*1000,
+	.sda_delay	= 100,
+	.cfg_gpio	= s5p6450_i2c1_cfg_gpio,
+};
+
+static struct i2c_board_info smdk6450_i2c_devs0[] __initdata = {
+	{ I2C_BOARD_INFO("24c08", 0x50), },	/* Samsung KS24C080C EEPROM */
+};
+
+static struct i2c_board_info smdk6450_i2c_devs1[] __initdata = {
+	{ I2C_BOARD_INFO("24c128", 0x57), },/* Samsung S524AD0XD1 EEPROM */
+};
+
+static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
+	.delay			= 10000,
+	.presc			= 49,
+	.oversampling_shift	= 2,
+};
+
+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));
+}
+
+static void __init smdk6450_machine_init(void)
+{
+	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+
+	s3c_i2c0_set_platdata(&s5p6450_i2c0_data);
+	s3c_i2c1_set_platdata(&s5p6450_i2c1_data);
+	i2c_register_board_info(0, smdk6450_i2c_devs0,
+			ARRAY_SIZE(smdk6450_i2c_devs0));
+	i2c_register_board_info(1, smdk6450_i2c_devs1,
+			ARRAY_SIZE(smdk6450_i2c_devs1));
+
+	platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
+}
+
+MACHINE_START(SMDK6450, "SMDK6450")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.boot_params	= S5P64X0_PA_SDRAM + 0x100,
+
+	.init_irq	= s5p6450_init_irq,
+	.map_io		= smdk6450_map_io,
+	.init_machine	= smdk6450_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s5p64x0/setup-i2c0.c b/arch/arm/mach-s5p64x0/setup-i2c0.c
new file mode 100644
index 0000000..dc4cc65
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/setup-i2c0.c
@@ -0,0 +1,42 @@
+/* linux/arch/arm/mach-s5p64x0/setup-i2c0.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * I2C0 GPIO configuration.
+ *
+ * Based on plat-s3c64x0/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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+
+struct platform_device; /* don't need the contents */
+
+#include <plat/gpio-cfg.h>
+#include <plat/iic.h>
+
+#include <mach/i2c.h>
+
+void s5p6440_i2c0_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgpin(S5P6440_GPB(5), S3C_GPIO_SFN(2));
+	s3c_gpio_setpull(S5P6440_GPB(5), S3C_GPIO_PULL_UP);
+	s3c_gpio_cfgpin(S5P6440_GPB(6), S3C_GPIO_SFN(2));
+	s3c_gpio_setpull(S5P6440_GPB(6), S3C_GPIO_PULL_UP);
+}
+
+void s5p6450_i2c0_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgpin(S5P6450_GPB(5), S3C_GPIO_SFN(2));
+	s3c_gpio_setpull(S5P6450_GPB(5), S3C_GPIO_PULL_UP);
+	s3c_gpio_cfgpin(S5P6450_GPB(6), S3C_GPIO_SFN(2));
+	s3c_gpio_setpull(S5P6450_GPB(6), S3C_GPIO_PULL_UP);
+}
+
+void s3c_i2c0_cfg_gpio(struct platform_device *dev) { }
diff --git a/arch/arm/mach-s5p64x0/setup-i2c1.c b/arch/arm/mach-s5p64x0/setup-i2c1.c
new file mode 100644
index 0000000..2edd791
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/setup-i2c1.c
@@ -0,0 +1,42 @@
+/* linux/arch/arm/mach-s5p64xx/setup-i2c1.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * I2C1 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+
+struct platform_device; /* don't need the contents */
+
+#include <plat/gpio-cfg.h>
+#include <plat/iic.h>
+
+#include <mach/i2c.h>
+
+void s5p6440_i2c1_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgpin(S5P6440_GPR(9), S3C_GPIO_SFN(6));
+	s3c_gpio_setpull(S5P6440_GPR(9), S3C_GPIO_PULL_UP);
+	s3c_gpio_cfgpin(S5P6440_GPR(10), S3C_GPIO_SFN(6));
+	s3c_gpio_setpull(S5P6440_GPR(10), S3C_GPIO_PULL_UP);
+}
+
+void s5p6450_i2c1_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgpin(S5P6450_GPR(9), S3C_GPIO_SFN(6));
+	s3c_gpio_setpull(S5P6450_GPR(9), S3C_GPIO_PULL_UP);
+	s3c_gpio_cfgpin(S5P6450_GPR(10), S3C_GPIO_SFN(6));
+	s3c_gpio_setpull(S5P6450_GPR(10), S3C_GPIO_PULL_UP);
+}
+
+void s3c_i2c1_cfg_gpio(struct platform_device *dev) { }
diff --git a/arch/arm/mach-s5pc100/cpu.c b/arch/arm/mach-s5pc100/cpu.c
index 251c92a..fd2708e 100644
--- a/arch/arm/mach-s5pc100/cpu.c
+++ b/arch/arm/mach-s5pc100/cpu.c
@@ -1,5 +1,8 @@
 /* linux/arch/arm/mach-s5pc100/cpu.c
  *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
  * Copyright 2009 Samsung Electronics Co.
  *	Byungho Min <bhmin@samsung.com>
  *
@@ -21,6 +24,7 @@
 #include <linux/sysdev.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -56,11 +60,31 @@
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= (unsigned long)VA_VIC2,
-		.pfn		= __phys_to_pfn(S5P_PA_VIC2),
+		.virtual	= (unsigned long)S5P_VA_GPIO,
+		.pfn		= __phys_to_pfn(S5PC100_PA_GPIO),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC0,
+		.pfn		= __phys_to_pfn(S5PC100_PA_VIC0),
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
 	}, {
+		.virtual	= (unsigned long)VA_VIC1,
+		.pfn		= __phys_to_pfn(S5PC100_PA_VIC1),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC2,
+		.pfn		= __phys_to_pfn(S5PC100_PA_VIC2),
+		.length		= SZ_16K,
+		.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)S5PC100_VA_OTHERS,
 		.pfn		= __phys_to_pfn(S5PC100_PA_OTHERS),
 		.length		= SZ_4K,
diff --git a/arch/arm/mach-s5pc100/include/mach/debug-macro.S b/arch/arm/mach-s5pc100/include/mach/debug-macro.S
index 70e02e9..b2ba95d 100644
--- a/arch/arm/mach-s5pc100/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5pc100/include/mach/debug-macro.S
@@ -22,13 +22,12 @@
 	 * aligned and add in the offset when we load the value here.
 	 */
 
-	.macro addruart, rx, rtmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1
-		ldreq	\rx, = S3C_PA_UART
-		ldrne	\rx, = S3C_VA_UART
+	.macro addruart, rp, rv
+		ldr	\rp, = S3C_PA_UART
+		ldr	\rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-		add	\rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+		add	\rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
 #endif
 	.endm
 
diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h
index 01b9134..8751ef4 100644
--- a/arch/arm/mach-s5pc100/include/mach/map.h
+++ b/arch/arm/mach-s5pc100/include/mach/map.h
@@ -44,19 +44,16 @@
 #define S5PC100_PA_OTHERS	(0xE0200000)
 #define S5PC100_VA_OTHERS	(S3C_VA_SYS + 0x10000)
 
-#define S5P_PA_GPIO		(0xE0300000)
+#define S5PC100_PA_GPIO		(0xE0300000)
 #define S5PC1XX_VA_GPIO		S3C_ADDR(0x00500000)
 
 /* Interrupt */
-#define S5PC100_PA_VIC		(0xE4000000)
+#define S5PC100_PA_VIC0		(0xE4000000)
+#define S5PC100_PA_VIC1		(0xE4100000)
+#define S5PC100_PA_VIC2		(0xE4200000)
 #define S5PC100_VA_VIC		S3C_VA_IRQ
-#define S5PC100_PA_VIC_OFFSET	0x100000
 #define S5PC100_VA_VIC_OFFSET	0x10000
-#define S5PC1XX_PA_VIC(x)	(S5PC100_PA_VIC + ((x) * S5PC100_PA_VIC_OFFSET))
 #define S5PC1XX_VA_VIC(x)	(S5PC100_VA_VIC + ((x) * S5PC100_VA_VIC_OFFSET))
-#define S5P_PA_VIC0		S5PC1XX_PA_VIC(0)
-#define S5P_PA_VIC1		S5PC1XX_PA_VIC(1)
-#define S5P_PA_VIC2		S5PC1XX_PA_VIC(2)
 
 
 #define S5PC100_PA_ONENAND	(0xE7100000)
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 020c3f9..880fb07 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -235,8 +235,6 @@
 
 MACHINE_START(SMDKC100, "SMDKC100")
 	/* Maintainer: Byungho Min <bhmin@samsung.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S5P_PA_SDRAM + 0x100,
 	.init_irq	= s5pc100_init_irq,
 	.map_io		= smdkc100_map_io,
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index d3a3895..5315fec 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -53,11 +53,6 @@
 	help
 	  Common setup code for SDHCI gpio.
 
-config S5PC110_DEV_ONENAND
-	bool
-	help
-	  Compile in platform device definition for OneNAND1 controller
-
 menu "S5PC110 Machines"
 
 config MACH_AQUILA
@@ -71,7 +66,7 @@
 	select S3C_DEV_HSMMC
 	select S3C_DEV_HSMMC1
 	select S3C_DEV_HSMMC2
-	select S5PC110_DEV_ONENAND
+	select S5P_DEV_ONENAND
 	select S5PV210_SETUP_FB_24BPP
 	select S5PV210_SETUP_SDHCI
 	help
@@ -88,7 +83,7 @@
 	select S3C_DEV_HSMMC
 	select S3C_DEV_HSMMC1
 	select S3C_DEV_HSMMC2
-	select S5PC110_DEV_ONENAND
+	select S5P_DEV_ONENAND
 	select S5PV210_SETUP_FB_24BPP
 	select S5PV210_SETUP_SDHCI
 	help
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 05048c5..7045489 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -26,7 +26,6 @@
 
 obj-y				+= dev-audio.o
 obj-$(CONFIG_S3C64XX_DEV_SPI)	+= dev-spi.o
-obj-$(CONFIG_S5PC110_DEV_ONENAND) += dev-onenand.o
 
 obj-$(CONFIG_S5PV210_SETUP_FB_24BPP)	+= setup-fb-24bpp.o
 obj-$(CONFIG_S5PV210_SETUP_I2C1) 	+= setup-i2c1.o
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index cfecd70..d562670 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -173,11 +173,6 @@
 	return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
 }
 
-static int s5pv210_clk_ip4_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP4, clk, enable);
-}
-
 static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable);
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 77f456c..2f16bfc 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-s5pv210/cpu.c
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
+ *		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
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 #include <linux/sysdev.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -50,6 +51,21 @@
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
 	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO,
+		.pfn		= __phys_to_pfn(S5PV210_PA_GPIO),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC0,
+		.pfn		= __phys_to_pfn(S5PV210_PA_VIC0),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC1,
+		.pfn		= __phys_to_pfn(S5PV210_PA_VIC1),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
 		.virtual	= (unsigned long)VA_VIC2,
 		.pfn		= __phys_to_pfn(S5PV210_PA_VIC2),
 		.length		= SZ_16K,
@@ -60,6 +76,11 @@
 		.length		= SZ_16K,
 		.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(S5PV210_PA_SROMC),
 		.length		= SZ_4K,
diff --git a/arch/arm/mach-s5pv210/dev-onenand.c b/arch/arm/mach-s5pv210/dev-onenand.c
deleted file mode 100644
index f8ede33..0000000
--- a/arch/arm/mach-s5pv210/dev-onenand.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv210/dev-onenand.c
- *
- *  Copyright (c) 2008-2010 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * S5PC110 series device definition for OneNAND devices
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/onenand.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-static struct resource s5pc110_onenand_resources[] = {
-	[0] = {
-		.start	= S5PC110_PA_ONENAND,
-		.end	= S5PC110_PA_ONENAND + SZ_128K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= S5PC110_PA_ONENAND_DMA,
-		.end	= S5PC110_PA_ONENAND_DMA + SZ_8K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= IRQ_ONENAND_AUDI,
-		.end	= IRQ_ONENAND_AUDI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s5pc110_device_onenand = {
-	.name		= "s5pc110-onenand",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5pc110_onenand_resources),
-	.resource	= s5pc110_onenand_resources,
-};
-
-void s5pc110_onenand_set_platdata(struct onenand_platform_data *pdata)
-{
-	struct onenand_platform_data *pd;
-
-	pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL);
-	if (!pd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-	s5pc110_device_onenand.dev.platform_data = pd;
-}
diff --git a/arch/arm/mach-s5pv210/include/mach/debug-macro.S b/arch/arm/mach-s5pv210/include/mach/debug-macro.S
index 7872f5c..169fe65 100644
--- a/arch/arm/mach-s5pv210/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5pv210/include/mach/debug-macro.S
@@ -21,13 +21,12 @@
 	 * aligned and add in the offset when we load the value here.
 	 */
 
-	.macro addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1
-		ldreq	\rx, = S3C_PA_UART
-		ldrne	\rx, = S3C_VA_UART
+	.macro addruart, rp, rv
+		ldr	\rp, = S3C_PA_UART
+		ldr	\rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-		add	\rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+		add	\rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
 #endif
 	.endm
 
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index dd4fb6b..bd9afd5 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -17,7 +17,10 @@
 #include <plat/map-s5p.h>
 
 #define S5PC110_PA_ONENAND	(0xB0000000)
+#define S5P_PA_ONENAND		S5PC110_PA_ONENAND
+
 #define S5PC110_PA_ONENAND_DMA	(0xB0600000)
+#define S5P_PA_ONENAND_DMA	S5PC110_PA_ONENAND_DMA
 
 #define S5PV210_PA_CHIPID	(0xE0000000)
 #define S5P_PA_CHIPID		S5PV210_PA_CHIPID
@@ -26,7 +29,6 @@
 #define S5P_PA_SYSCON		S5PV210_PA_SYSCON
 
 #define S5PV210_PA_GPIO		(0xE0200000)
-#define S5P_PA_GPIO		S5PV210_PA_GPIO
 
 /* SPI */
 #define S5PV210_PA_SPI0		0xE1300000
@@ -72,16 +74,9 @@
 #define S5PV210_PA_HSMMC(x)	(0xEB000000 + ((x) * 0x100000))
 
 #define S5PV210_PA_VIC0		(0xF2000000)
-#define S5P_PA_VIC0		S5PV210_PA_VIC0
-
 #define S5PV210_PA_VIC1		(0xF2100000)
-#define S5P_PA_VIC1		S5PV210_PA_VIC1
-
 #define S5PV210_PA_VIC2		(0xF2200000)
-#define S5P_PA_VIC2		S5PV210_PA_VIC2
-
 #define S5PV210_PA_VIC3		(0xF2300000)
-#define S5P_PA_VIC3		S5PV210_PA_VIC3
 
 #define S5PV210_PA_SDRAM	(0x20000000)
 #define S5P_PA_SDRAM		S5PV210_PA_SDRAM
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 0dda801..0088308 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -477,7 +477,7 @@
 	&aquila_i2c_gpio_pmic,
 	&aquila_device_gpiokeys,
 	&s3c_device_fb,
-	&s5pc110_device_onenand,
+	&s5p_device_onenand,
 	&s3c_device_hsmmc0,
 	&s3c_device_hsmmc1,
 	&s3c_device_hsmmc2,
@@ -516,8 +516,6 @@
 	/* Maintainers:
 	   Marek Szyprowski <m.szyprowski@samsung.com>
 	   Kyungmin Park <kyungmin.park@samsung.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S5P_PA_SDRAM + 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= aquila_map_io,
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 53754d7..d9ecf57 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -456,7 +456,7 @@
 
 static struct platform_device *goni_devices[] __initdata = {
 	&s3c_device_fb,
-	&s5pc110_device_onenand,
+	&s5p_device_onenand,
 	&goni_i2c_gpio_pmic,
 	&goni_device_gpiokeys,
 	&s5p_device_fimc0,
@@ -491,8 +491,6 @@
 
 MACHINE_START(GONI, "GONI")
 	/* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S5P_PA_SDRAM + 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= goni_map_io,
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index 8211bb8..cea9bca 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -127,8 +127,6 @@
 
 MACHINE_START(SMDKC110, "SMDKC110")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S5P_PA_SDRAM + 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkc110_map_io,
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index fbbc0a3..83189ae 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -165,8 +165,6 @@
 
 MACHINE_START(SMDKV210, "SMDKV210")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S5P_PA_SDRAM + 0x100,
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkv210_map_io,
diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
index e5b261a..4add398 100644
--- a/arch/arm/mach-s5pv310/cpu.c
+++ b/arch/arm/mach-s5pv310/cpu.c
@@ -31,21 +31,6 @@
 /* Initial IO mappings */
 static struct map_desc s5pv310_iodesc[] __initdata = {
 	{
-		.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_COMBINER_BASE,
-		.pfn		= __phys_to_pfn(S5PV310_PA_COMBINER),
-		.length		= SZ_4K,
-		.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_SYSRAM,
 		.pfn		= __phys_to_pfn(S5PV310_PA_SYSRAM),
 		.length		= SZ_4K,
@@ -55,6 +40,31 @@
 		.pfn		= __phys_to_pfn(S5PV310_PA_CMU),
 		.length		= SZ_128K,
 		.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_GPIO,
+		.pfn		= __phys_to_pfn(S5PV310_PA_GPIO1),
+		.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,
 	},
 };
 
diff --git a/arch/arm/mach-s5pv310/include/mach/debug-macro.S b/arch/arm/mach-s5pv310/include/mach/debug-macro.S
index 6fb3893..b0d920c 100644
--- a/arch/arm/mach-s5pv310/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5pv310/include/mach/debug-macro.S
@@ -20,13 +20,12 @@
 	 * aligned and add in the offset when we load the value here.
 	 */
 
-	.macro addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1
-		ldreq	\rx, = S3C_PA_UART
-		ldrne	\rx, = S3C_VA_UART
+	.macro addruart, rp, rv
+		ldreq	\rp, = S3C_PA_UART
+		ldrne	\rv, = S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
-		add	\rx, \rx, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+		add	\rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
 #endif
 	.endm
 
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
index 4cdedda..471fc3b 100644
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -68,6 +68,8 @@
 
 #define IRQ_IIC			COMBINER_IRQ(27, 0)
 
+#define IRQ_ONENAND_AUDI	COMBINER_IRQ(34, 0)
+
 /* Set the default NR_IRQS */
 
 #define NR_IRQS			COMBINER_IRQ(MAX_COMBINER_NR, 0)
diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h
index 213e110..aff6d23 100644
--- a/arch/arm/mach-s5pv310/include/mach/map.h
+++ b/arch/arm/mach-s5pv310/include/mach/map.h
@@ -25,6 +25,12 @@
 
 #define S5PV310_PA_SYSRAM		(0x02025000)
 
+#define S5PC210_PA_ONENAND		(0x0C000000)
+#define S5P_PA_ONENAND			S5PC210_PA_ONENAND
+
+#define S5PC210_PA_ONENAND_DMA		(0x0C600000)
+#define S5P_PA_ONENAND_DMA		S5PC210_PA_ONENAND_DMA
+
 #define S5PV310_PA_CHIPID		(0x10000000)
 #define S5P_PA_CHIPID			S5PV310_PA_CHIPID
 
@@ -46,7 +52,6 @@
 #define S5PV310_PA_GPIO1		(0x11400000)
 #define S5PV310_PA_GPIO2		(0x11000000)
 #define S5PV310_PA_GPIO3		(0x03860000)
-#define S5P_PA_GPIO			S5PV310_PA_GPIO1
 
 #define S5PV310_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
 
diff --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h
index 990f3ba..b7ec252 100644
--- a/arch/arm/mach-s5pv310/include/mach/smp.h
+++ b/arch/arm/mach-s5pv310/include/mach/smp.h
@@ -7,17 +7,10 @@
 #define ASM_ARCH_SMP_H __FILE__
 
 #include <asm/hardware/gic.h>
+#include <asm/smp_mpidr.h>
 
 extern void __iomem *gic_cpu_base_addr;
 
-#define hard_smp_processor_id()			\
-	({						\
-		unsigned int cpunum;			\
-		__asm__("mrc p15, 0, %0, c0, c0, 5"	\
-			: "=r" (cpunum));		\
-		cpunum &= 0x03;				\
-	})
-
 /*
  * We use IRQ1 as the IPI
  */
diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-s5pv310/mach-smdkv310.c
index 0d6ab77..46215a1 100644
--- a/arch/arm/mach-s5pv310/mach-smdkv310.c
+++ b/arch/arm/mach-s5pv310/mach-smdkv310.c
@@ -82,8 +82,6 @@
 MACHINE_START(SMDKV310, "SMDKV310")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
 	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S5P_PA_SDRAM + 0x100,
 	.init_irq	= s5pv310_init_irq,
 	.map_io		= smdkv310_map_io,
diff --git a/arch/arm/mach-s5pv310/mach-universal_c210.c b/arch/arm/mach-s5pv310/mach-universal_c210.c
index 2388cb9..d7c2ec7 100644
--- a/arch/arm/mach-s5pv310/mach-universal_c210.c
+++ b/arch/arm/mach-s5pv310/mach-universal_c210.c
@@ -76,8 +76,6 @@
 
 MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
 	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S5P_PA_SDRAM + 0x100,
 	.init_irq	= s5pv310_init_irq,
 	.map_io		= universal_map_io,
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 169e5b8..5778274 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -447,8 +447,6 @@
 
 
 MACHINE_START(ASSABET, "Intel-Assabet")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.fixup		= fixup_assabet,
 	.map_io		= assabet_map_io,
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index 259cb2c..4f19ff8 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -302,8 +302,6 @@
 }
 
 MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= badge4_map_io,
 	.init_irq	= sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index bc950ef..98d7806 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -135,8 +135,6 @@
 
 MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
 	/* Maintainer: support@intrinsyc.com */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.map_io		= cerf_map_io,
 	.init_irq	= cerf_init_irq,
 	.timer		= &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 16e682d..d43c5ef 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -379,8 +379,6 @@
 }
 
 MACHINE_START(COLLIE, "Sharp-Collie")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.map_io		= collie_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c
index 0c7cea0..03d7376 100644
--- a/arch/arm/mach-sa1100/h3100.c
+++ b/arch/arm/mach-sa1100/h3100.c
@@ -84,8 +84,6 @@
 }
 
 MACHINE_START(H3100, "Compaq iPAQ H3100")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= h3100_map_io,
 	.init_irq	= sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index af3b714..965f64a 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -125,8 +125,6 @@
 }
 
 MACHINE_START(H3600, "Compaq iPAQ H3600")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= h3600_map_io,
 	.init_irq	= sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c
index 51568df..db5e434 100644
--- a/arch/arm/mach-sa1100/hackkit.c
+++ b/arch/arm/mach-sa1100/hackkit.c
@@ -195,8 +195,6 @@
  */
 
 MACHINE_START(HACKKIT, "HackKit Cpu Board")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= hackkit_map_io,
 	.init_irq	= sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/include/mach/debug-macro.S b/arch/arm/mach-sa1100/include/mach/debug-macro.S
index 336adcc..0cd0fc9 100644
--- a/arch/arm/mach-sa1100/include/mach/debug-macro.S
+++ b/arch/arm/mach-sa1100/include/mach/debug-macro.S
@@ -12,33 +12,37 @@
 */
 #include <mach/hardware.h>
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x80000000	@ physical base address
-		movne	\rx, #0xf8000000	@ virtual address
+		.macro	addruart, rp, rv
+		mrc	p15, 0, \rp, c1, c0
+		tst	\rp, #1			@ MMU enabled?
+		moveq	\rp, #0x80000000	@ physical base address
+		movne	\rp, #0xf8000000	@ virtual address
 
 		@ We probe for the active serial port here, coherently with
 		@ the comment in arch/arm/mach-sa1100/include/mach/uncompress.h.
 		@ We assume r1 can be clobbered.
 
 		@ see if Ser3 is active
-		add	\rx, \rx, #0x00050000
-		ldr	r1, [\rx, #UTCR3]
-		tst	r1, #UTCR3_TXE
+		add	\rp, \rp, #0x00050000
+		ldr	\rv, [\rp, #UTCR3]
+		tst	\rv, #UTCR3_TXE
 
 		@ if Ser3 is inactive, then try Ser1
-		addeq	\rx, \rx, #(0x00010000 - 0x00050000)
-		ldreq	r1, [\rx, #UTCR3]
-		tsteq	r1, #UTCR3_TXE
+		addeq	\rp, \rp, #(0x00010000 - 0x00050000)
+		ldreq	\rv, [\rp, #UTCR3]
+		tsteq	\rv, #UTCR3_TXE
 
 		@ if Ser1 is inactive, then try Ser2
-		addeq	\rx, \rx, #(0x00030000 - 0x00010000)
-		ldreq	r1, [\rx, #UTCR3]
-		tsteq	r1, #UTCR3_TXE
+		addeq	\rp, \rp, #(0x00030000 - 0x00010000)
+		ldreq	\rv, [\rp, #UTCR3]
+		tsteq	\rv, #UTCR3_TXE
 
-		@ if all ports are inactive, then there is nothing we can do
-		moveq	pc, lr
+		@ clear top bits, and generate both phys and virt addresses
+		lsl	\rp, \rp, #8
+		lsr	\rp, \rp, #8
+		orr	\rv, \rp, #0xf8000000	@ virtual
+		orr	\rp, \rp, #0x80000000	@ physical
+
 		.endm
 
 		.macro	senduart,rd,rx
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index d3ec620..491ac9f 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -364,8 +364,6 @@
 
 MACHINE_START(JORNADA720, "HP Jornada 720")
 	/* Maintainer: Kristoffer Ericson <Kristoffer.Ericson@gmail.com> */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= jornada720_map_io,
 	.init_irq	= sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index 68069d6..7b9556b 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -61,8 +61,6 @@
 }
 
 MACHINE_START(LART, "LART")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= lart_map_io,
 	.init_irq	= sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
index 1ccd601..42b8040 100644
--- a/arch/arm/mach-sa1100/pleb.c
+++ b/arch/arm/mach-sa1100/pleb.c
@@ -146,8 +146,6 @@
 }
 
 MACHINE_START(PLEB, "PLEB")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.map_io		= pleb_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index 85e82bb..7917b24 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -82,8 +82,6 @@
 }
 
 MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= shannon_map_io,
 	.init_irq	= sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 49cfd64..27692d0 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -228,8 +228,6 @@
 
 MACHINE_START(SIMPAD, "Simpad")
 	/* Maintainer: Holger Freyther */
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
 	.boot_params	= 0xc0000100,
 	.map_io		= simpad_map_io,
 	.init_irq	= sa1100_init_irq,
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index 358d875..5cf7f94 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -152,8 +152,6 @@
 
 MACHINE_START(SHARK, "Shark")
 	/* Maintainer: Alexander Schulz */
-	.phys_io	= 0x40000000,
-	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
 	.boot_params	= 0x08003000,
 	.map_io		= shark_map_io,
 	.init_irq	= shark_init_irq,
diff --git a/arch/arm/mach-shark/include/mach/debug-macro.S b/arch/arm/mach-shark/include/mach/debug-macro.S
index 5ea24d4..a473f55 100644
--- a/arch/arm/mach-shark/include/mach/debug-macro.S
+++ b/arch/arm/mach-shark/include/mach/debug-macro.S
@@ -11,9 +11,10 @@
  *
 */
 
-		.macro	addruart, rx, tmp
-		mov	\rx, #0xe0000000
-		orr	\rx, \rx, #0x000003f8
+		.macro	addruart, rp, rv
+		mov	\rp, #0xe0000000
+		orr	\rp, \rp, #0x000003f8
+		mov	\rv, \rp
 		.endm
 
 		.macro	senduart,rd,rx
diff --git a/arch/arm/mach-shark/include/mach/vmalloc.h b/arch/arm/mach-shark/include/mach/vmalloc.h
index f6c6837..8e845b6 100644
--- a/arch/arm/mach-shark/include/mach/vmalloc.h
+++ b/arch/arm/mach-shark/include/mach/vmalloc.h
@@ -1,4 +1,4 @@
 /*
  * arch/arm/mach-shark/include/mach/vmalloc.h
  */
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       0xd0000000
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 95935c8..1492398 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -1105,8 +1105,6 @@
 };
 
 MACHINE_START(AP4EVB, "ap4evb")
-	.phys_io	= 0xe6000000,
-	.io_pg_offst	= ((0xe6000000) >> 18) & 0xfffc,
 	.map_io		= ap4evb_map_io,
 	.init_irq	= sh7372_init_irq,
 	.init_machine	= ap4evb_init,
diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c
index a552590..3b83d63 100644
--- a/arch/arm/mach-shmobile/board-g3evm.c
+++ b/arch/arm/mach-shmobile/board-g3evm.c
@@ -365,8 +365,6 @@
 };
 
 MACHINE_START(G3EVM, "g3evm")
-	.phys_io	= 0xe6000000,
-	.io_pg_offst	= ((0xe6000000) >> 18) & 0xfffc,
 	.map_io		= g3evm_map_io,
 	.init_irq	= sh7367_init_irq,
 	.init_machine	= g3evm_init,
diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c
index 2c3ff6f..5b3b582 100644
--- a/arch/arm/mach-shmobile/board-g4evm.c
+++ b/arch/arm/mach-shmobile/board-g4evm.c
@@ -392,8 +392,6 @@
 };
 
 MACHINE_START(G4EVM, "g4evm")
-	.phys_io	= 0xe6000000,
-	.io_pg_offst	= ((0xe6000000) >> 18) & 0xfffc,
 	.map_io		= g4evm_map_io,
 	.init_irq	= sh7377_init_irq,
 	.init_machine	= g4evm_init,
diff --git a/arch/arm/mach-stmp378x/stmp378x_devb.c b/arch/arm/mach-stmp378x/stmp378x_devb.c
index 90d8fe6..0615884 100644
--- a/arch/arm/mach-stmp378x/stmp378x_devb.c
+++ b/arch/arm/mach-stmp378x/stmp378x_devb.c
@@ -324,8 +324,6 @@
 }
 
 MACHINE_START(STMP378X, "STMP378X")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf0000000) >> 18) & 0xfffc,
 	.boot_params	= 0x40000100,
 	.map_io		= stmp378x_map_io,
 	.init_irq	= stmp378x_init_irq,
diff --git a/arch/arm/mach-stmp37xx/stmp37xx_devb.c b/arch/arm/mach-stmp37xx/stmp37xx_devb.c
index 394f21a..311d855 100644
--- a/arch/arm/mach-stmp37xx/stmp37xx_devb.c
+++ b/arch/arm/mach-stmp37xx/stmp37xx_devb.c
@@ -91,8 +91,6 @@
 }
 
 MACHINE_START(STMP37XX, "STMP37XX")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf0000000) >> 18) & 0xfffc,
 	.boot_params	= 0x40000100,
 	.map_io		= stmp37xx_map_io,
 	.init_irq	= stmp37xx_init_irq,
diff --git a/arch/arm/mach-tcc8k/Kconfig b/arch/arm/mach-tcc8k/Kconfig
new file mode 100644
index 0000000..ad86415
--- /dev/null
+++ b/arch/arm/mach-tcc8k/Kconfig
@@ -0,0 +1,11 @@
+if ARCH_TCC8K
+
+comment "TCC8000 systems:"
+
+config MACH_TCC8000_SDK
+	bool "Telechips TCC8000-SDK development kit"
+	default y
+	help
+	  Support for the Telechips TCC8000-SDK board.
+
+endif
diff --git a/arch/arm/mach-tcc8k/Makefile b/arch/arm/mach-tcc8k/Makefile
new file mode 100644
index 0000000..9bacf31
--- /dev/null
+++ b/arch/arm/mach-tcc8k/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for TCC8K boards and common files.
+#
+
+# Common support
+obj-y += clock.o irq.o time.o io.o devices.o
+
+# Board specific support
+obj-$(CONFIG_MACH_TCC8000_SDK) += board-tcc8000-sdk.o
diff --git a/arch/arm/mach-tcc8k/Makefile.boot b/arch/arm/mach-tcc8k/Makefile.boot
new file mode 100644
index 0000000..f135c9d
--- /dev/null
+++ b/arch/arm/mach-tcc8k/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y		:= 0x20008000
+params_phys-y		:= 0x20000100
+initrd_phys-y		:= 0x20800000
diff --git a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
new file mode 100644
index 0000000..7991415
--- /dev/null
+++ b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.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/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <mach/clock.h>
+
+#include "common.h"
+
+#define XI_FREQUENCY	12000000
+#define XTI_FREQUENCY	32768
+
+#ifdef CONFIG_MTD_NAND_TCC
+/* NAND */
+static struct tcc_nand_platform_data tcc8k_sdk_nand_data = {
+	.width = 1,
+	.hw_ecc = 0,
+};
+#endif
+
+static void __init tcc8k_init(void)
+{
+#ifdef CONFIG_MTD_NAND_TCC
+	tcc_nand_device.dev.platform_data = &tcc8k_sdk_nand_data;
+	platform_device_register(&tcc_nand_device);
+#endif
+}
+
+static void __init tcc8k_init_timer(void)
+{
+	tcc_clocks_init(XI_FREQUENCY, XTI_FREQUENCY);
+}
+
+static struct sys_timer tcc8k_timer = {
+	.init	= tcc8k_init_timer,
+};
+
+static void __init tcc8k_map_io(void)
+{
+	tcc8k_map_common_io();
+}
+
+MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board")
+	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.map_io		= tcc8k_map_io,
+	.init_irq	= tcc8k_init_irq,
+	.init_machine	= tcc8k_init,
+	.timer		= &tcc8k_timer,
+MACHINE_END
diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c
new file mode 100644
index 0000000..ba32a15
--- /dev/null
+++ b/arch/arm/mach-tcc8k/clock.c
@@ -0,0 +1,567 @@
+/*
+ * Lowlevel clock handling for Telechips TCC8xxx SoCs
+ *
+ * Copyright (C) 2010 by Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+#include <asm/clkdev.h>
+
+#include <mach/clock.h>
+#include <mach/irqs.h>
+#include <mach/tcc8k-regs.h>
+
+#include "common.h"
+
+#define BCLKCTR0	(CKC_BASE + BCLKCTR0_OFFS)
+#define BCLKCTR1	(CKC_BASE + BCLKCTR1_OFFS)
+
+#define ACLKREF		(CKC_BASE + ACLKREF_OFFS)
+#define ACLKUART0	(CKC_BASE + ACLKUART0_OFFS)
+#define ACLKUART1	(CKC_BASE + ACLKUART1_OFFS)
+#define ACLKUART2	(CKC_BASE + ACLKUART2_OFFS)
+#define ACLKUART3	(CKC_BASE + ACLKUART3_OFFS)
+#define ACLKUART4	(CKC_BASE + ACLKUART4_OFFS)
+#define ACLKI2C		(CKC_BASE + ACLKI2C_OFFS)
+#define ACLKADC		(CKC_BASE + ACLKADC_OFFS)
+#define ACLKUSBH	(CKC_BASE + ACLKUSBH_OFFS)
+#define ACLKLCD		(CKC_BASE + ACLKLCD_OFFS)
+#define ACLKSDH0	(CKC_BASE + ACLKSDH0_OFFS)
+#define ACLKSDH1	(CKC_BASE + ACLKSDH1_OFFS)
+#define ACLKSPI0	(CKC_BASE + ACLKSPI0_OFFS)
+#define ACLKSPI1	(CKC_BASE + ACLKSPI1_OFFS)
+#define ACLKSPDIF	(CKC_BASE + ACLKSPDIF_OFFS)
+#define ACLKC3DEC	(CKC_BASE + ACLKC3DEC_OFFS)
+#define ACLKCAN0	(CKC_BASE + ACLKCAN0_OFFS)
+#define ACLKCAN1	(CKC_BASE + ACLKCAN1_OFFS)
+#define ACLKGSB0	(CKC_BASE + ACLKGSB0_OFFS)
+#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)
+
+/* Crystal frequencies */
+static unsigned long xi_rate, xti_rate;
+
+static void __iomem *pll_cfg_addr(int pll)
+{
+	switch (pll) {
+	case 0: return (CKC_BASE + PLL0CFG_OFFS);
+	case 1: return (CKC_BASE + PLL1CFG_OFFS);
+	case 2: return (CKC_BASE + PLL2CFG_OFFS);
+	default:
+		BUG();
+	}
+}
+
+static int pll_enable(int pll, int enable)
+{
+	u32 reg;
+	void __iomem *addr = pll_cfg_addr(pll);
+
+	reg = __raw_readl(addr);
+	if (enable)
+		reg &= ~PLLxCFG_PD;
+	else
+		reg |= PLLxCFG_PD;
+
+	__raw_writel(reg, addr);
+	return 0;
+}
+
+static int xi_enable(int enable)
+{
+	u32 reg;
+
+	reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS);
+	if (enable)
+		reg |= CLKCTRL_XE;
+	else
+		reg &= ~CLKCTRL_XE;
+
+	__raw_writel(reg, CKC_BASE + CLKCTRL_OFFS);
+	return 0;
+}
+
+static int root_clk_enable(enum root_clks src)
+{
+	switch (src) {
+	case CLK_SRC_PLL0: return pll_enable(0, 1);
+	case CLK_SRC_PLL1: return pll_enable(1, 1);
+	case CLK_SRC_PLL2: return pll_enable(2, 1);
+	case CLK_SRC_XI: return xi_enable(1);
+	default:
+		BUG();
+	}
+	return 0;
+}
+
+static int root_clk_disable(enum root_clks root_src)
+{
+	switch (root_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);
+	case CLK_SRC_XI: return xi_enable(0);
+	default:
+		BUG();
+	}
+	return 0;
+}
+
+static int enable_clk(struct clk *clk)
+{
+	u32 reg;
+
+	if (clk->root_id != CLK_SRC_NOROOT)
+		return root_clk_enable(clk->root_id);
+
+	if (clk->aclkreg) {
+		reg = __raw_readl(clk->aclkreg);
+		reg |= ACLK_EN;
+		__raw_writel(reg, clk->aclkreg);
+	}
+	if (clk->bclkctr) {
+		reg = __raw_readl(clk->bclkctr);
+		reg |= 1 << clk->bclk_shift;
+		__raw_writel(reg, clk->bclkctr);
+	}
+	return 0;
+}
+
+static void disable_clk(struct clk *clk)
+{
+	u32 reg;
+
+	if (clk->root_id != CLK_SRC_NOROOT) {
+		root_clk_disable(clk->root_id);
+		return;
+	}
+
+	if (clk->bclkctr) {
+		reg = __raw_readl(clk->bclkctr);
+		reg &= ~(1 << clk->bclk_shift);
+		__raw_writel(reg, clk->bclkctr);
+	}
+	if (clk->aclkreg) {
+		reg = __raw_readl(clk->aclkreg);
+		reg &= ~ACLK_EN;
+		__raw_writel(reg, clk->aclkreg);
+	}
+}
+
+static unsigned long get_rate_pll(int pll)
+{
+	u32 reg;
+	unsigned long s, m, p;
+	void __iomem *addr = pll_cfg_addr(pll);
+
+	reg = __raw_readl(addr);
+	s = (reg >> 16) & 0x07;
+	m = (reg >> 8) & 0xff;
+	p = reg & 0x3f;
+
+	return (m * xi_rate) / (p * (1 << s));
+}
+
+static unsigned long get_rate_pll_div(int pll)
+{
+	u32 reg;
+	unsigned long div = 0;
+	void __iomem *addr;
+
+	switch (pll) {
+	case 0:
+		addr = CKC_BASE + CLKDIVC0_OFFS;
+		reg = __raw_readl(addr);
+		if (reg & CLKDIVC0_P0E)
+			div = (reg >> 24) & 0x3f;
+		break;
+	case 1:
+		addr = CKC_BASE + CLKDIVC0_OFFS;
+		reg = __raw_readl(addr);
+		if (reg & CLKDIVC0_P1E)
+			div = (reg >> 16) & 0x3f;
+		break;
+	case 2:
+		addr = CKC_BASE + CLKDIVC1_OFFS;
+		reg = __raw_readl(addr);
+		if (reg & CLKDIVC1_P2E)
+			div = __raw_readl(addr) & 0x3f;
+		break;
+	}
+	return get_rate_pll(pll) / (div + 1);
+}
+
+static unsigned long get_rate_xi_div(void)
+{
+	unsigned long div = 0;
+	u32 reg = __raw_readl(CKC_BASE + CLKDIVC0_OFFS);
+
+	if (reg & CLKDIVC0_XE)
+		div = (reg >> 8) & 0x3f;
+
+	return xi_rate / (div + 1);
+}
+
+static unsigned long get_rate_xti_div(void)
+{
+	unsigned long div = 0;
+	u32 reg = __raw_readl(CKC_BASE + CLKDIVC0_OFFS);
+
+	if (reg & CLKDIVC0_XTE)
+		div = reg & 0x3f;
+
+	return xti_rate / (div + 1);
+}
+
+static unsigned long root_clk_get_rate(enum root_clks src)
+{
+	switch (src) {
+	case CLK_SRC_PLL0: return get_rate_pll(0);
+	case CLK_SRC_PLL1: return get_rate_pll(1);
+	case CLK_SRC_PLL2: return get_rate_pll(2);
+	case CLK_SRC_PLL0DIV: return get_rate_pll_div(0);
+	case CLK_SRC_PLL1DIV: return get_rate_pll_div(1);
+	case CLK_SRC_PLL2DIV: return get_rate_pll_div(2);
+	case CLK_SRC_XI: return xi_rate;
+	case CLK_SRC_XTI: return xti_rate;
+	case CLK_SRC_XIDIV: return get_rate_xi_div();
+	case CLK_SRC_XTIDIV: return get_rate_xti_div();
+	default: return 0;
+	}
+}
+
+static unsigned long aclk_get_rate(struct clk *clk)
+{
+	u32 reg;
+	unsigned long div;
+	unsigned int src;
+
+	reg = __raw_readl(clk->aclkreg);
+	div = reg & 0x0fff;
+	src = (reg >> ACLK_SEL_SHIFT) & CLK_SRC_MASK;
+	return root_clk_get_rate(src) / (div + 1);
+}
+
+static unsigned long aclk_best_div(struct clk *clk, unsigned long rate)
+{
+	unsigned long div, src, freq, r1, r2;
+
+	src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
+	src &= CLK_SRC_MASK;
+	freq = root_clk_get_rate(src);
+	div = freq / rate + 1;
+	r1 = freq / div;
+	r2 = freq / (div + 1);
+	if (r2 >= rate)
+		return div + 1;
+	if ((rate - r2) < (r1 - rate))
+		return div + 1;
+
+	return div;
+}
+
+static unsigned long aclk_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned int src;
+
+	src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
+	src &= CLK_SRC_MASK;
+
+	return root_clk_get_rate(src) / aclk_best_div(clk, rate);
+}
+
+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);
+	return 0;
+}
+
+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);
+}
+
+static unsigned long get_rate_bus(struct clk *clk)
+{
+	unsigned int div;
+
+	div = (__raw_readl(CKC_BASE + CLKCTRL_OFFS) >> 4) & 0xff;
+	return get_rate_sys(clk) / (div + 1);
+}
+
+static unsigned long get_rate_cpu(struct clk *clk)
+{
+	unsigned int reg, div, fsys, fbus;
+
+	fbus = get_rate_bus(clk);
+	reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS);
+	if (reg & (1 << 29))
+		return fbus;
+	fsys = get_rate_sys(clk);
+	div = (reg >> 16) & 0x0f;
+	return fbus + ((fsys - fbus) * (div + 1)) / 16;
+}
+
+static unsigned long get_rate_root(struct clk *clk)
+{
+	return root_clk_get_rate(clk->root_id);
+}
+
+static int aclk_set_parent(struct clk *clock, struct clk *parent)
+{
+	u32 reg;
+
+	if (clock->parent == parent)
+		return 0;
+
+	clock->parent = parent;
+
+	if (!parent)
+		return 0;
+
+	if (parent->root_id == CLK_SRC_NOROOT)
+		return 0;
+	reg = __raw_readl(clock->aclkreg);
+	reg &= ~ACLK_SEL_MASK;
+	reg |= (parent->root_id << ACLK_SEL_SHIFT) & ACLK_SEL_MASK;
+	__raw_writel(reg, clock->aclkreg);
+
+	return 0;
+}
+
+#define DEFINE_ROOT_CLOCK(name, ri, p)	\
+	static struct clk name = {		\
+		.root_id = ri,			\
+		.get_rate = get_rate_root,			\
+		.enable = enable_clk,		\
+		.disable = disable_clk,		\
+		.parent = p,			\
+	};
+
+#define DEFINE_SPECIAL_CLOCK(name, gr, p)	\
+	static struct clk name = {		\
+		.root_id = CLK_SRC_NOROOT,	\
+		.get_rate = gr,			\
+		.parent = p,			\
+	};
+
+#define DEFINE_ACLOCK(name, bc, bs, ar)		\
+	static struct clk name = {		\
+		.root_id = CLK_SRC_NOROOT,	\
+		.bclkctr = bc,			\
+		.bclk_shift = bs,		\
+		.aclkreg = ar,			\
+		.get_rate = aclk_get_rate,	\
+		.set_rate = aclk_set_rate,	\
+		.round_rate = aclk_round_rate,	\
+		.enable = enable_clk,		\
+		.disable = disable_clk,		\
+		.set_parent = aclk_set_parent,	\
+	};
+
+#define DEFINE_BCLOCK(name, bc, bs, gr, p)	\
+	static struct clk name = {		\
+		.root_id = CLK_SRC_NOROOT,	\
+		.bclkctr = bc,			\
+		.bclk_shift = bs,		\
+		.get_rate = gr,			\
+		.enable = enable_clk,		\
+		.disable = disable_clk,		\
+		.parent = p,			\
+	};
+
+DEFINE_ROOT_CLOCK(xi, CLK_SRC_XI, NULL)
+DEFINE_ROOT_CLOCK(xti, CLK_SRC_XTI, NULL)
+DEFINE_ROOT_CLOCK(xidiv, CLK_SRC_XIDIV, &xi)
+DEFINE_ROOT_CLOCK(xtidiv, CLK_SRC_XTIDIV, &xti)
+DEFINE_ROOT_CLOCK(pll0, CLK_SRC_PLL0, &xi)
+DEFINE_ROOT_CLOCK(pll1, CLK_SRC_PLL1, &xi)
+DEFINE_ROOT_CLOCK(pll2, CLK_SRC_PLL2, &xi)
+DEFINE_ROOT_CLOCK(pll0div, CLK_SRC_PLL0DIV, &pll0)
+DEFINE_ROOT_CLOCK(pll1div, CLK_SRC_PLL1DIV, &pll1)
+DEFINE_ROOT_CLOCK(pll2div, CLK_SRC_PLL2DIV, &pll2)
+
+/* The following 3 clocks are special and are initialized explicitly later */
+DEFINE_SPECIAL_CLOCK(sys, get_rate_sys, NULL)
+DEFINE_SPECIAL_CLOCK(bus, get_rate_bus, &sys)
+DEFINE_SPECIAL_CLOCK(cpu, get_rate_cpu, &sys)
+
+DEFINE_ACLOCK(tct, NULL, 0, ACLKTCT)
+DEFINE_ACLOCK(tcx, NULL, 0, ACLKTCX)
+DEFINE_ACLOCK(tcz, NULL, 0, ACLKTCZ)
+DEFINE_ACLOCK(ref, NULL, 0, ACLKREF)
+DEFINE_ACLOCK(uart0, BCLKCTR0, 5, ACLKUART0)
+DEFINE_ACLOCK(uart1, BCLKCTR0, 23, ACLKUART1)
+DEFINE_ACLOCK(uart2, BCLKCTR0, 6, ACLKUART2)
+DEFINE_ACLOCK(uart3, BCLKCTR0, 8, ACLKUART3)
+DEFINE_ACLOCK(uart4, BCLKCTR1, 6, ACLKUART4)
+DEFINE_ACLOCK(i2c, BCLKCTR0, 7, ACLKI2C)
+DEFINE_ACLOCK(adc, BCLKCTR0, 10, ACLKADC)
+DEFINE_ACLOCK(usbh0, BCLKCTR0, 11, ACLKUSBH)
+DEFINE_ACLOCK(lcd, BCLKCTR0, 13, ACLKLCD)
+DEFINE_ACLOCK(sd0, BCLKCTR0, 17, ACLKSDH0)
+DEFINE_ACLOCK(sd1, BCLKCTR1, 5, ACLKSDH1)
+DEFINE_ACLOCK(spi0, BCLKCTR0, 24, ACLKSPI0)
+DEFINE_ACLOCK(spi1, BCLKCTR0, 30, ACLKSPI1)
+DEFINE_ACLOCK(spdif, BCLKCTR1, 2, ACLKSPDIF)
+DEFINE_ACLOCK(c3dec, BCLKCTR1, 9, ACLKC3DEC)
+DEFINE_ACLOCK(can0, BCLKCTR1, 10, ACLKCAN0)
+DEFINE_ACLOCK(can1, BCLKCTR1, 11, ACLKCAN1)
+DEFINE_ACLOCK(gsb0, BCLKCTR1, 13, ACLKGSB0)
+DEFINE_ACLOCK(gsb1, BCLKCTR1, 14, ACLKGSB1)
+DEFINE_ACLOCK(gsb2, BCLKCTR1, 15, ACLKGSB2)
+DEFINE_ACLOCK(gsb3, BCLKCTR1, 16, ACLKGSB3)
+DEFINE_ACLOCK(usbh1, BCLKCTR1, 20, ACLKUSBH)
+
+DEFINE_BCLOCK(dai0, BCLKCTR0, 0, NULL, NULL)
+DEFINE_BCLOCK(pic, BCLKCTR0, 1, NULL, NULL)
+DEFINE_BCLOCK(tc, BCLKCTR0, 2, NULL, NULL)
+DEFINE_BCLOCK(gpio, BCLKCTR0, 3, NULL, NULL)
+DEFINE_BCLOCK(usbd, BCLKCTR0, 4, NULL, NULL)
+DEFINE_BCLOCK(ecc, BCLKCTR0, 9, NULL, NULL)
+DEFINE_BCLOCK(gdma0, BCLKCTR0, 12, NULL, NULL)
+DEFINE_BCLOCK(rtc, BCLKCTR0, 15, NULL, NULL)
+DEFINE_BCLOCK(nfc, BCLKCTR0, 16, NULL, NULL)
+DEFINE_BCLOCK(g2d, BCLKCTR0, 18, NULL, NULL)
+DEFINE_BCLOCK(gdma1, BCLKCTR0, 22, NULL, NULL)
+DEFINE_BCLOCK(mscl, BCLKCTR0, 25, NULL, NULL)
+DEFINE_BCLOCK(bdma, BCLKCTR1, 0, NULL, NULL)
+DEFINE_BCLOCK(adma0, BCLKCTR1, 1, NULL, NULL)
+DEFINE_BCLOCK(scfg, BCLKCTR1, 3, NULL, NULL)
+DEFINE_BCLOCK(cid, BCLKCTR1, 4, NULL, NULL)
+DEFINE_BCLOCK(dai1, BCLKCTR1, 7, NULL, NULL)
+DEFINE_BCLOCK(adma1, BCLKCTR1, 8, NULL, NULL)
+DEFINE_BCLOCK(gps, BCLKCTR1, 12, NULL, NULL)
+DEFINE_BCLOCK(gdma2, BCLKCTR1, 17, NULL, NULL)
+DEFINE_BCLOCK(gdma3, BCLKCTR1, 18, NULL, NULL)
+DEFINE_BCLOCK(ddrc, BCLKCTR1, 19, NULL, NULL)
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c, \
+	},
+
+static struct clk_lookup lookups[] = {
+	_REGISTER_CLOCK(NULL, "bus", bus)
+	_REGISTER_CLOCK(NULL, "cpu", cpu)
+	_REGISTER_CLOCK(NULL, "tct", tct)
+	_REGISTER_CLOCK(NULL, "tcx", tcx)
+	_REGISTER_CLOCK(NULL, "tcz", tcz)
+	_REGISTER_CLOCK(NULL, "ref", ref)
+	_REGISTER_CLOCK(NULL, "dai0", dai0)
+	_REGISTER_CLOCK(NULL, "pic", pic)
+	_REGISTER_CLOCK(NULL, "tc", tc)
+	_REGISTER_CLOCK(NULL, "gpio", gpio)
+	_REGISTER_CLOCK(NULL, "usbd", usbd)
+	_REGISTER_CLOCK("tcc-uart.0", NULL, uart0)
+	_REGISTER_CLOCK("tcc-uart.2", NULL, uart2)
+	_REGISTER_CLOCK("tcc-i2c", NULL, i2c)
+	_REGISTER_CLOCK("tcc-uart.3", NULL, uart3)
+	_REGISTER_CLOCK(NULL, "ecc", ecc)
+	_REGISTER_CLOCK(NULL, "adc", adc)
+	_REGISTER_CLOCK("tcc-usbh.0", "usb", usbh0)
+	_REGISTER_CLOCK(NULL, "gdma0", gdma0)
+	_REGISTER_CLOCK(NULL, "lcd", lcd)
+	_REGISTER_CLOCK(NULL, "rtc", rtc)
+	_REGISTER_CLOCK(NULL, "nfc", nfc)
+	_REGISTER_CLOCK("tcc-mmc.0", NULL, sd0)
+	_REGISTER_CLOCK(NULL, "g2d", g2d)
+	_REGISTER_CLOCK(NULL, "gdma1", gdma1)
+	_REGISTER_CLOCK("tcc-uart.1", NULL, uart1)
+	_REGISTER_CLOCK("tcc-spi.0", NULL, spi0)
+	_REGISTER_CLOCK(NULL, "mscl", mscl)
+	_REGISTER_CLOCK("tcc-spi.1", NULL, spi1)
+	_REGISTER_CLOCK(NULL, "bdma", bdma)
+	_REGISTER_CLOCK(NULL, "adma0", adma0)
+	_REGISTER_CLOCK(NULL, "spdif", spdif)
+	_REGISTER_CLOCK(NULL, "scfg", scfg)
+	_REGISTER_CLOCK(NULL, "cid", cid)
+	_REGISTER_CLOCK("tcc-mmc.1", NULL, sd1)
+	_REGISTER_CLOCK("tcc-uart.4", NULL, uart4)
+	_REGISTER_CLOCK(NULL, "dai1", dai1)
+	_REGISTER_CLOCK(NULL, "adma1", adma1)
+	_REGISTER_CLOCK(NULL, "c3dec", c3dec)
+	_REGISTER_CLOCK("tcc-can.0", NULL, can0)
+	_REGISTER_CLOCK("tcc-can.1", NULL, can1)
+	_REGISTER_CLOCK(NULL, "gps", gps)
+	_REGISTER_CLOCK("tcc-gsb.0", NULL, gsb0)
+	_REGISTER_CLOCK("tcc-gsb.1", NULL, gsb1)
+	_REGISTER_CLOCK("tcc-gsb.2", NULL, gsb2)
+	_REGISTER_CLOCK("tcc-gsb.3", NULL, gsb3)
+	_REGISTER_CLOCK(NULL, "gdma2", gdma2)
+	_REGISTER_CLOCK(NULL, "gdma3", gdma3)
+	_REGISTER_CLOCK(NULL, "ddrc", ddrc)
+	_REGISTER_CLOCK("tcc-usbh.1", "usb", usbh1)
+};
+
+static struct clk *root_clk_by_index(enum root_clks src)
+{
+	switch (src) {
+	case CLK_SRC_PLL0: return &pll0;
+	case CLK_SRC_PLL1: return &pll1;
+	case CLK_SRC_PLL2: return &pll2;
+	case CLK_SRC_PLL0DIV: return &pll0div;
+	case CLK_SRC_PLL1DIV: return &pll1div;
+	case CLK_SRC_PLL2DIV: return &pll2div;
+	case CLK_SRC_XI: return &xi;
+	case CLK_SRC_XTI: return &xti;
+	case CLK_SRC_XIDIV: return &xidiv;
+	case CLK_SRC_XTIDIV: return &xtidiv;
+	default: return NULL;
+	}
+}
+
+static void find_aclk_parent(struct clk *clk)
+{
+	unsigned int src;
+	struct clk *clock;
+
+	if (!clk->aclkreg)
+		return;
+
+	src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
+	src &= CLK_SRC_MASK;
+
+	clock = root_clk_by_index(src);
+	if (!clock)
+		return;
+
+	clk->parent = clock;
+	clk->set_parent = aclk_set_parent;
+}
+
+void __init tcc_clocks_init(unsigned long xi_freq, unsigned long xti_freq)
+{
+	int i;
+
+	xi_rate = xi_freq;
+	xti_rate = xti_freq;
+
+	/* fixup parents and add the clock */
+	for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+		find_aclk_parent(lookups[i].clk);
+		clkdev_add(&lookups[i]);
+	}
+	tcc8k_timer_init(&tcz, (void __iomem *)TIMER_BASE, INT_TC32);
+}
diff --git a/arch/arm/mach-tcc8k/common.h b/arch/arm/mach-tcc8k/common.h
new file mode 100644
index 0000000..705690a
--- /dev/null
+++ b/arch/arm/mach-tcc8k/common.h
@@ -0,0 +1,15 @@
+#ifndef MACH_TCC8K_COMMON_H
+#define MACH_TCC8K_COMMON_H
+
+#include <linux/platform_device.h>
+
+extern struct platform_device tcc_nand_device;
+
+struct clk;
+
+extern void tcc_clocks_init(unsigned long xi_freq, unsigned long xti_freq);
+extern void tcc8k_timer_init(struct clk *clock, void __iomem *base, int irq);
+extern void tcc8k_init_irq(void);
+extern void tcc8k_map_common_io(void);
+
+#endif
diff --git a/arch/arm/mach-tcc8k/devices.c b/arch/arm/mach-tcc8k/devices.c
new file mode 100644
index 0000000..6722ad7
--- /dev/null
+++ b/arch/arm/mach-tcc8k/devices.c
@@ -0,0 +1,239 @@
+/*
+ * linux/arch/arm/mach-tcc8k/devices.c
+ *
+ * Copyright (C) Telechips, Inc.
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of GPL v2.
+ *
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/tcc8k-regs.h>
+#include <mach/irqs.h>
+
+#include "common.h"
+
+static u64 tcc8k_dmamask = DMA_BIT_MASK(32);
+
+#ifdef CONFIG_MTD_NAND_TCC
+/* NAND controller */
+static struct resource tcc_nand_resources[] = {
+	{
+		.start	= (resource_size_t)NFC_BASE,
+		.end	= (resource_size_t)NFC_BASE + 0x7f,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= INT_NFC,
+		.end	= INT_NFC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device tcc_nand_device = {
+	.name = "tcc_nand",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(tcc_nand_resources),
+	.resource = tcc_nand_resources,
+};
+#endif
+
+#ifdef CONFIG_MMC_TCC8K
+/* MMC controller */
+static struct resource tcc8k_mmc0_resource[] = {
+	{
+		.start = INT_SD0,
+		.end   = INT_SD0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tcc8k_mmc1_resource[] = {
+	{
+		.start = INT_SD1,
+		.end   = INT_SD1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device tcc8k_mmc0_device = {
+	.name		= "tcc-mmc",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(tcc8k_mmc0_resource),
+	.resource	= tcc8k_mmc0_resource,
+	.dev		= {
+		.dma_mask		= &tcc8k_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+struct platform_device tcc8k_mmc1_device = {
+	.name		= "tcc-mmc",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(tcc8k_mmc1_resource),
+	.resource	= tcc8k_mmc1_resource,
+	.dev		= {
+		.dma_mask		= &tcc8k_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+
+static inline void tcc8k_init_mmc(void)
+{
+	u32 reg = __raw_readl(GPIOPS_BASE + GPIOPS_FS1_OFFS);
+
+	reg |= GPIOPS_FS1_SDH0_BITS | GPIOPS_FS1_SDH1_BITS;
+	__raw_writel(reg, GPIOPS_BASE + GPIOPS_FS1_OFFS);
+
+	platform_device_register(&tcc8k_mmc0_device);
+	platform_device_register(&tcc8k_mmc1_device);
+}
+#else
+static inline void tcc8k_init_mmc(void) { }
+#endif
+
+#ifdef CONFIG_USB_OHCI_HCD
+static int tcc8k_ohci_init(struct device *dev)
+{
+	u32 reg;
+
+	/* Use GPIO PK19 as VBUS control output */
+	reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS0_OFFS);
+	reg &= ~(1 << 19);
+	__raw_writel(reg, GPIOPK_BASE + GPIOPK_FS0_OFFS);
+	reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS1_OFFS);
+	reg &= ~(1 << 19);
+	__raw_writel(reg, GPIOPK_BASE + GPIOPK_FS1_OFFS);
+
+	reg = __raw_readl(GPIOPK_BASE + GPIOPK_DOE_OFFS);
+	reg |= (1 << 19);
+	__raw_writel(reg, GPIOPK_BASE + GPIOPK_DOE_OFFS);
+	/* Turn on VBUS */
+	reg = __raw_readl(GPIOPK_BASE + GPIOPK_DAT_OFFS);
+	reg |= (1 << 19);
+	__raw_writel(reg, GPIOPK_BASE + GPIOPK_DAT_OFFS);
+
+	return 0;
+}
+
+static struct resource tcc8k_ohci0_resources[] = {
+	[0] = {
+		.start = (resource_size_t)USBH0_BASE,
+		.end   = (resource_size_t)USBH0_BASE + 0x5c,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = INT_USBH0,
+		.end   = INT_USBH0,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource tcc8k_ohci1_resources[] = {
+	[0] = {
+		.start = (resource_size_t)USBH1_BASE,
+		.end   = (resource_size_t)USBH1_BASE + 0x5c,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = INT_USBH1,
+		.end   = INT_USBH1,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct tccohci_platform_data tcc8k_ohci0_platform_data = {
+	.controller	= 0,
+	.port_mode	= PMM_PERPORT_MODE,
+	.init		= tcc8k_ohci_init,
+};
+
+static struct tccohci_platform_data tcc8k_ohci1_platform_data = {
+	.controller	= 1,
+	.port_mode	= PMM_PERPORT_MODE,
+	.init		= tcc8k_ohci_init,
+};
+
+static struct platform_device ohci0_device = {
+	.name = "tcc-ohci",
+	.id = 0,
+	.dev = {
+		.dma_mask = &tcc8k_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &tcc8k_ohci0_platform_data,
+	},
+	.num_resources  = ARRAY_SIZE(tcc8k_ohci0_resources),
+	.resource       = tcc8k_ohci0_resources,
+};
+
+static struct platform_device ohci1_device = {
+	.name = "tcc-ohci",
+	.id = 1,
+	.dev = {
+		.dma_mask = &tcc8k_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &tcc8k_ohci1_platform_data,
+	},
+	.num_resources  = ARRAY_SIZE(tcc8k_ohci1_resources),
+	.resource       = tcc8k_ohci1_resources,
+};
+
+static void __init tcc8k_init_usbhost(void)
+{
+	platform_device_register(&ohci0_device);
+	platform_device_register(&ohci1_device);
+}
+#else
+static void __init tcc8k_init_usbhost(void) { }
+#endif
+
+/* USB device controller*/
+#ifdef CONFIG_USB_GADGET_TCC8K
+static struct resource udc_resources[] = {
+	[0] = {
+		.start = INT_USBD,
+		.end   = INT_USBD,
+		.flags = IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start = INT_UDMA,
+		.end   = INT_UDMA,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tcc8k_udc_device = {
+	.name = "tcc-udc",
+	.id = 0,
+	.resource = udc_resources,
+	.num_resources = ARRAY_SIZE(udc_resources),
+	.dev = {
+		 .dma_mask = &tcc8k_dmamask,
+		 .coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+static void __init tcc8k_init_usb_gadget(void)
+{
+	platform_device_register(&tcc8k_udc_device);
+}
+#else
+static void __init tcc8k_init_usb_gadget(void) { }
+#endif	/* CONFIG_USB_GADGET_TCC83X */
+
+static int __init tcc8k_init_devices(void)
+{
+	tcc8k_init_mmc();
+	tcc8k_init_usbhost();
+	tcc8k_init_usb_gadget();
+	return 0;
+}
+
+arch_initcall(tcc8k_init_devices);
diff --git a/arch/arm/mach-tcc8k/io.c b/arch/arm/mach-tcc8k/io.c
new file mode 100644
index 0000000..9b39d7f
--- /dev/null
+++ b/arch/arm/mach-tcc8k/io.c
@@ -0,0 +1,62 @@
+/*
+ * linux/arch/arm/mach-tcc8k/io.c
+ *
+ * (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * derived from TCC83xx io.c
+ * Copyright (C) Telechips, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/tcc8k-regs.h>
+
+/*
+ * The machine specific code may provide the extra mapping besides the
+ * default mapping provided here.
+ */
+static struct map_desc tcc8k_io_desc[] __initdata = {
+	{
+		.virtual	= (unsigned long)CS1_BASE_VIRT,
+		.pfn		= __phys_to_pfn(CS1_BASE),
+		.length		= CS1_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)AHB_PERI_BASE_VIRT,
+		.pfn		= __phys_to_pfn(AHB_PERI_BASE),
+		.length		= AHB_PERI_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)APB0_PERI_BASE_VIRT,
+		.pfn		= __phys_to_pfn(APB0_PERI_BASE),
+		.length		= APB0_PERI_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)APB1_PERI_BASE_VIRT,
+		.pfn		= __phys_to_pfn(APB1_PERI_BASE),
+		.length		= APB1_PERI_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)EXT_MEM_CTRL_BASE_VIRT,
+		.pfn		= __phys_to_pfn(EXT_MEM_CTRL_BASE),
+		.length		= EXT_MEM_CTRL_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+
+/*
+ * Maps common IO regions for tcc8k.
+ *
+ */
+void __init tcc8k_map_common_io(void)
+{
+	iotable_init(tcc8k_io_desc, ARRAY_SIZE(tcc8k_io_desc));
+}
diff --git a/arch/arm/mach-tcc8k/irq.c b/arch/arm/mach-tcc8k/irq.c
new file mode 100644
index 0000000..34575c4
--- /dev/null
+++ b/arch/arm/mach-tcc8k/irq.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) Telechips, Inc.
+ * Copyright (C) 2009-2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GNU GPL version 2.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+#include <mach/tcc8k-regs.h>
+#include <mach/irqs.h>
+
+#include "common.h"
+
+/* Disable IRQ */
+static void tcc8000_mask_ack_irq0(unsigned int irq)
+{
+	PIC0_IEN &= ~(1 << irq);
+	PIC0_CREQ |=  (1 << irq);
+}
+
+static void tcc8000_mask_ack_irq1(unsigned int irq)
+{
+	PIC1_IEN &= ~(1 << (irq - 32));
+	PIC1_CREQ |= (1 << (irq - 32));
+}
+
+static void tcc8000_mask_irq0(unsigned int irq)
+{
+	PIC0_IEN &= ~(1 << irq);
+}
+
+static void tcc8000_mask_irq1(unsigned int irq)
+{
+	PIC1_IEN &= ~(1 << (irq - 32));
+}
+
+static void tcc8000_ack_irq0(unsigned int irq)
+{
+	PIC0_CREQ |=  (1 << irq);
+}
+
+static void tcc8000_ack_irq1(unsigned int irq)
+{
+	PIC1_CREQ |= (1 << (irq - 32));
+}
+
+/* Enable IRQ */
+static void tcc8000_unmask_irq0(unsigned int irq)
+{
+	PIC0_IEN |= (1 << irq);
+	PIC0_INTOEN |= (1 << irq);
+}
+
+static void tcc8000_unmask_irq1(unsigned int irq)
+{
+	PIC1_IEN |= (1 << (irq - 32));
+	PIC1_INTOEN |= (1 << (irq - 32));
+}
+
+static struct irq_chip tcc8000_irq_chip0 = {
+	.name		= "tcc_irq0",
+	.mask		= tcc8000_mask_irq0,
+	.ack		= tcc8000_ack_irq0,
+	.mask_ack	= tcc8000_mask_ack_irq0,
+	.unmask		= tcc8000_unmask_irq0,
+};
+
+static struct irq_chip tcc8000_irq_chip1 = {
+	.name		= "tcc_irq1",
+	.mask		= tcc8000_mask_irq1,
+	.ack		= tcc8000_ack_irq1,
+	.mask_ack	= tcc8000_mask_ack_irq1,
+	.unmask		= tcc8000_unmask_irq1,
+};
+
+void __init tcc8k_init_irq(void)
+{
+	int irqno;
+
+	/* Mask and clear all interrupts */
+	PIC0_IEN = 0x00000000;
+	PIC0_CREQ = 0xffffffff;
+	PIC1_IEN = 0x00000000;
+	PIC1_CREQ = 0xffffffff;
+
+	PIC0_MEN0 = 0x00000003;
+	PIC1_MEN1 = 0x00000003;
+	PIC1_MEN = 0x00000003;
+
+	/* let all IRQs be level triggered */
+	PIC0_TMODE = 0xffffffff;
+	PIC1_TMODE = 0xffffffff;
+	/* all IRQs are IRQs (not FIQs) */
+	PIC0_IRQSEL = 0xffffffff;
+	PIC1_IRQSEL = 0xffffffff;
+
+	for (irqno = 0; irqno < NR_IRQS; irqno++) {
+		if (irqno < 32)
+			set_irq_chip(irqno, &tcc8000_irq_chip0);
+		else
+			set_irq_chip(irqno, &tcc8000_irq_chip1);
+		set_irq_handler(irqno, handle_level_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+}
diff --git a/arch/arm/mach-tcc8k/time.c b/arch/arm/mach-tcc8k/time.c
new file mode 100644
index 0000000..78d0600
--- /dev/null
+++ b/arch/arm/mach-tcc8k/time.c
@@ -0,0 +1,149 @@
+/*
+ * TCC8000 system timer setup
+ *
+ * (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL version 2.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach/time.h>
+
+#include <mach/tcc8k-regs.h>
+#include <mach/irqs.h>
+
+#include "common.h"
+
+static void __iomem *timer_base;
+
+static cycle_t tcc_get_cycles(struct clocksource *cs)
+{
+	return __raw_readl(timer_base + TC32MCNT_OFFS);
+}
+
+static struct clocksource clocksource_tcc = {
+	.name		= "tcc_tc32",
+	.rating		= 200,
+	.read		= tcc_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.shift		= 28,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int tcc_set_next_event(unsigned long evt,
+			      struct clock_event_device *unused)
+{
+	unsigned long reg = __raw_readl(timer_base + TC32MCNT_OFFS);
+
+	__raw_writel(reg + evt, timer_base + TC32CMP0_OFFS);
+	return 0;
+}
+
+static void tcc_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	unsigned long tc32irq;
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_ONESHOT:
+		tc32irq = __raw_readl(timer_base + TC32IRQ_OFFS);
+		tc32irq |= TC32IRQ_IRQEN0;
+		__raw_writel(tc32irq, timer_base + TC32IRQ_OFFS);
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+		tc32irq = __raw_readl(timer_base + TC32IRQ_OFFS);
+		tc32irq &= ~TC32IRQ_IRQEN0;
+		__raw_writel(tc32irq, timer_base + TC32IRQ_OFFS);
+		break;
+	case CLOCK_EVT_MODE_PERIODIC:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static irqreturn_t tcc8k_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	/* Acknowledge TC32 interrupt by reading TC32IRQ */
+	__raw_readl(timer_base + TC32IRQ_OFFS);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct clock_event_device clockevent_tcc = {
+	.name		= "tcc_timer1",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.set_mode	= tcc_set_mode,
+	.set_next_event	= tcc_set_next_event,
+	.rating		= 200,
+};
+
+static struct irqaction tcc8k_timer_irq = {
+	.name		= "TC32_timer",
+	.flags		= IRQF_DISABLED | IRQF_TIMER,
+	.handler	= tcc8k_timer_interrupt,
+	.dev_id		= &clockevent_tcc,
+};
+
+static int __init tcc_clockevent_init(struct clk *clock)
+{
+	unsigned int c = clk_get_rate(clock);
+
+	clocksource_tcc.mult = clocksource_hz2mult(c,
+					clocksource_tcc.shift);
+	clocksource_register(&clocksource_tcc);
+
+	clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC,
+					clockevent_tcc.shift);
+	clockevent_tcc.max_delta_ns =
+			clockevent_delta2ns(0xfffffffe, &clockevent_tcc);
+	clockevent_tcc.min_delta_ns =
+			clockevent_delta2ns(0xff, &clockevent_tcc);
+
+	clockevent_tcc.cpumask = cpumask_of(0);
+
+	clockevents_register_device(&clockevent_tcc);
+
+	return 0;
+}
+
+void __init tcc8k_timer_init(struct clk *clock, void __iomem *base, int irq)
+{
+	u32 reg;
+
+	timer_base = base;
+	tcc8k_timer_irq.irq = irq;
+
+	/* Enable clocks */
+	clk_enable(clock);
+
+	/* Initialize 32-bit timer */
+	reg = __raw_readl(timer_base + TC32EN_OFFS);
+	reg &= ~TC32EN_ENABLE; /* Disable timer */
+	__raw_writel(reg, timer_base + TC32EN_OFFS);
+	/* Free running timer, counting from 0 to 0xffffffff */
+	__raw_writel(0, timer_base + TC32EN_OFFS);
+	__raw_writel(0, timer_base + TC32LDV_OFFS);
+	reg = __raw_readl(timer_base + TC32IRQ_OFFS);
+	reg |= TC32IRQ_IRQEN0; /* irq at match with CMP0 */
+	__raw_writel(reg, timer_base + TC32IRQ_OFFS);
+
+	__raw_writel(TC32EN_ENABLE, timer_base + TC32EN_OFFS);
+
+	tcc_clockevent_init(clock);
+	setup_irq(irq, &tcc8k_timer_irq);
+}
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index 9e305de..b9dbdb1 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -115,8 +115,6 @@
 
 MACHINE_START(HARMONY, "harmony")
 	.boot_params  = 0x00000100,
-	.phys_io        = IO_APB_PHYS,
-	.io_pg_offst    = ((IO_APB_VIRT) >> 18) & 0xfffc,
 	.fixup		= tegra_harmony_fixup,
 	.init_irq       = tegra_init_irq,
 	.init_machine   = tegra_harmony_init,
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S
index 55a3956..8ea3bff 100644
--- a/arch/arm/mach-tegra/include/mach/debug-macro.S
+++ b/arch/arm/mach-tegra/include/mach/debug-macro.S
@@ -20,24 +20,28 @@
 
 #include <mach/io.h>
 
-	.macro  addruart,rx, tmp
-        mrc     p15, 0, \rx, c1, c0
-        tst     \rx, #1                 @ MMU enabled?
-        ldreq   \rx, =IO_APB_PHYS       @ physical
-        ldrne   \rx, =IO_APB_VIRT        @ virtual
+	.macro  addruart, rp, rv
+        ldreq   \rp, =IO_APB_PHYS       @ physical
+        ldrne   \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     \rx, \rx, #0x6000
+        orr     \rp, \rp, #0x6000
+        orr     \rv, \rv, #0x6000
 #elif defined(CONFIG_TEGRA_DEBUG_UARTB)
-	ldr	\tmp, =0x6040
-        orr     \rx, \rx, \tmp
+        orr     \rp, \rp, #0x6000
+	orr	\rp, \rp, #0x40
+        orr     \rv, \rv, #0x6000
+	orr	\rv, \rv, #0x40
 #elif defined(CONFIG_TEGRA_DEBUG_UARTC)
-        orr     \rx, \rx, #0x6200
+        orr     \rp, \rp, #0x6200
+        orr     \rv, \rv, #0x6200
 #elif defined(CONFIG_TEGRA_DEBUG_UARTD)
-        orr     \rx, \rx, #0x6300
+        orr     \rp, \rp, #0x6300
+        orr     \rv, \rv, #0x6300
 #elif defined(CONFIG_TEGRA_DEBUG_UARTE)
-        orr     \rx, \rx, #0x6400
+        orr     \rp, \rp, #0x6400
+        orr     \rv, \rv, #0x6400
 #endif
 	.endm
 
diff --git a/arch/arm/mach-tegra/include/mach/smp.h b/arch/arm/mach-tegra/include/mach/smp.h
index 8b42dab..e4a34a3 100644
--- a/arch/arm/mach-tegra/include/mach/smp.h
+++ b/arch/arm/mach-tegra/include/mach/smp.h
@@ -1,16 +1,8 @@
 #ifndef ASMARM_ARCH_SMP_H
 #define ASMARM_ARCH_SMP_H
 
-
 #include <asm/hardware/gic.h>
-
-#define hard_smp_processor_id()			\
-	({						\
-		unsigned int cpunum;			\
-		__asm__("mrc p15, 0, %0, c0, c0, 5"	\
-			: "=r" (cpunum));		\
-		cpunum &= 0x0F;				\
-	})
+#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
diff --git a/arch/arm/mach-u300/dummyspichip.c b/arch/arm/mach-u300/dummyspichip.c
index 5f55012..03f7936 100644
--- a/arch/arm/mach-u300/dummyspichip.c
+++ b/arch/arm/mach-u300/dummyspichip.c
@@ -46,7 +46,6 @@
 	 * struct, this is just used here to alter the behaviour of the chip
 	 * in order to perform tests.
 	 */
-	struct pl022_config_chip *chip_info = spi->controller_data;
 	int status;
 	u8 txbuf[14] = {0xDE, 0xAD, 0xBE, 0xEF, 0x2B, 0xAD,
 			0xCA, 0xFE, 0xBA, 0xBE, 0xB1, 0x05,
@@ -72,7 +71,7 @@
 	 * Force chip to 8 bit mode
 	 * WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC!
 	 */
-	chip_info->data_size = SSP_DATA_BITS_8;
+	spi->bits_per_word = 8;
 	/* You should NOT DO THIS EITHER */
 	spi->master->setup(spi);
 
@@ -159,7 +158,7 @@
 	 * Force chip to 16 bit mode
 	 * WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC!
 	 */
-	chip_info->data_size = SSP_DATA_BITS_16;
+	spi->bits_per_word = 16;
 	/* You should NOT DO THIS EITHER */
 	spi->master->setup(spi);
 
diff --git a/arch/arm/mach-u300/include/mach/debug-macro.S b/arch/arm/mach-u300/include/mach/debug-macro.S
index 92c1242..df71570 100644
--- a/arch/arm/mach-u300/include/mach/debug-macro.S
+++ b/arch/arm/mach-u300/include/mach/debug-macro.S
@@ -10,13 +10,12 @@
  */
 #include <mach/hardware.h>
 
-	.macro	addruart, rx, tmp
+	.macro	addruart, rp, rv
 	/* If we move the address using MMU, use this. */
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1			@ MMU enabled?
-	ldreq	\rx,	  = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
-	ldrne	\rx,	  = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
-	orr	\rx, \rx, #0x00003000
+	ldr	\rp,	  = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
+	ldr	\rv,	  = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
+	orr	\rp, \rp, #0x00003000
+	orr	\rv, \rv, #0x00003000
 	.endm
 
 #include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-u300/include/mach/gpio.h b/arch/arm/mach-u300/include/mach/gpio.h
index 7b1fc98..d5a71ab 100644
--- a/arch/arm/mach-u300/include/mach/gpio.h
+++ b/arch/arm/mach-u300/include/mach/gpio.h
@@ -273,6 +273,9 @@
 extern int gpio_get_value(unsigned gpio);
 extern void gpio_set_value(unsigned gpio, int value);
 
+#define gpio_get_value_cansleep gpio_get_value
+#define gpio_set_value_cansleep gpio_set_value
+
 /* wrappers to sleep-enable the previous two functions */
 static inline unsigned gpio_to_irq(unsigned gpio)
 {
diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c
index f0e887b..edb2c0d 100644
--- a/arch/arm/mach-u300/spi.c
+++ b/arch/arm/mach-u300/spi.c
@@ -30,8 +30,6 @@
 }
 
 struct pl022_config_chip dummy_chip_info = {
-	/* Nominally this is LOOPBACK_DISABLED, but this is our dummy chip! */
-	.lbm = LOOPBACK_ENABLED,
 	/*
 	 * available POLLING_TRANSFER and INTERRUPT_TRANSFER,
 	 * DMA_TRANSFER does not work
@@ -42,14 +40,8 @@
 	.hierarchy = SSP_MASTER,
 	/* 0 = drive TX even as slave, 1 = do not drive TX as slave */
 	.slave_tx_disable = 0,
-	/* LSB first */
-	.endian_tx = SSP_TX_LSB,
-	.endian_rx = SSP_RX_LSB,
-	.data_size = SSP_DATA_BITS_8, /* used to be 12 in some default */
 	.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
 	.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
-	.clk_phase = SSP_CLK_SECOND_EDGE,
-	.clk_pol = SSP_CLK_POL_IDLE_LOW,
 	.ctrl_len = SSP_BITS_12,
 	.wait_state = SSP_MWIRE_WAIT_ZERO,
 	.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
@@ -75,7 +67,7 @@
 		.bus_num        = 0, /* Only one bus on this chip */
 		.chip_select    = 0,
 		/* Means SPI_CS_HIGH, change if e.g low CS */
-		.mode           = 0,
+		.mode           = SPI_MODE_1 | SPI_LSB_FIRST | SPI_LOOP,
 	},
 #endif
 };
diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c
index bfcda98..07c35a8 100644
--- a/arch/arm/mach-u300/u300.c
+++ b/arch/arm/mach-u300/u300.c
@@ -61,8 +61,6 @@
 
 MACHINE_START(U300, MACH_U300_STRING)
 	/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
-	.phys_io	= U300_AHB_PER_PHYS_BASE,
-	.io_pg_offst	= ((U300_AHB_PER_VIRT_BASE) >> 18) & 0xfffc,
 	.boot_params	= BOOT_PARAMS_OFFSET,
 	.map_io		= u300_map_io,
 	.reserve	= u300_reserve,
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 6625e5b..2dd44a0 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -21,9 +21,7 @@
 	bool "U8500 Development platform"
 	select UX500_SOC_DB8500
 	help
-	  Include support for mop500 development platform
-	  based on U8500 architecture. The platform is based
-	  on early drop silicon version of 8500.
+	  Include support for the mop500 development platform.
 
 config MACH_U5500
 	bool "U5500 Development platform"
@@ -39,4 +37,18 @@
 	  Choose the UART on which kernel low-level debug messages should be
 	  output.
 
+config U5500_MODEM_IRQ
+	bool "Modem IRQ support"
+	depends on MACH_U5500
+	default y
+	help
+	  Add support for handling IRQ:s from modem side
+
+config U5500_MBOX
+	bool "Mailbox support"
+	depends on MACH_U5500 && U5500_MODEM_IRQ
+	default y
+	help
+	  Add support for U5500 mailbox communication with modem side
+
 endif
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 4556aea..9e27a84 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -4,8 +4,12 @@
 
 obj-y				:= clock.o cpu.o devices.o
 obj-$(CONFIG_UX500_SOC_DB5500)	+= cpu-db5500.o devices-db5500.o
-obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o devices-db8500.o
-obj-$(CONFIG_MACH_U8500_MOP)	+= board-mop500.o
+obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o devices-db8500.o prcmu.o
+obj-$(CONFIG_MACH_U8500_MOP)	+= board-mop500.o board-mop500-sdi.o
 obj-$(CONFIG_MACH_U5500)	+= board-u5500.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.o
+obj-$(CONFIG_U5500_MBOX)	+= mbox.o
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
new file mode 100644
index 0000000..1187f1f
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ * MOP500 board specific initialization for regulators
+ */
+#include <linux/kernel.h>
+#include <linux/regulator/machine.h>
+
+/* supplies to the display/camera */
+static struct regulator_init_data ab8500_vaux1_regulator = {
+	.constraints = {
+		.name = "V-DISPLAY",
+		.min_uV = 2500000,
+		.max_uV = 2900000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
+					REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* supplies to the on-board eMMC */
+static struct regulator_init_data ab8500_vaux2_regulator = {
+	.constraints = {
+		.name = "V-eMMC1",
+		.min_uV = 1100000,
+		.max_uV = 3300000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
+					REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* supply for VAUX3, supplies to SDcard slots */
+static struct regulator_init_data ab8500_vaux3_regulator = {
+	.constraints = {
+		.name = "V-MMC-SD",
+		.min_uV = 1100000,
+		.max_uV = 3300000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
+					REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* supply for tvout, gpadc, TVOUT LDO */
+static struct regulator_init_data ab8500_vtvout_init = {
+	.constraints = {
+		.name = "V-TVOUT",
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* supply for ab8500-vaudio, VAUDIO LDO */
+static struct regulator_init_data ab8500_vaudio_init = {
+	.constraints = {
+		.name = "V-AUD",
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* supply for v-anamic1 VAMic1-LDO */
+static struct regulator_init_data ab8500_vamic1_init = {
+	.constraints = {
+		.name = "V-AMIC1",
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
+static struct regulator_init_data ab8500_vamic2_init = {
+	.constraints = {
+		.name = "V-AMIC2",
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* supply for v-dmic, VDMIC LDO */
+static struct regulator_init_data ab8500_vdmic_init = {
+	.constraints = {
+		.name = "V-DMIC",
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* supply for v-intcore12, VINTCORE12 LDO */
+static struct regulator_init_data ab8500_vintcore_init = {
+	.constraints = {
+		.name = "V-INTCORE",
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* supply for U8500 CSI/DSI, VANA LDO */
+static struct regulator_init_data ab8500_vana_init = {
+	.constraints = {
+		.name = "V-CSI/DSI",
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+};
+
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
new file mode 100644
index 0000000..bac9956
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Hanumath Prasad <hanumath.prasad@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/mmci.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+
+#include <plat/pincfg.h>
+#include <mach/devices.h>
+#include <mach/hardware.h>
+
+#include "pins-db8500.h"
+#include "board-mop500.h"
+
+static pin_cfg_t mop500_sdi_pins[] = {
+	/* 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,
+};
+
+/*
+ * SDI 2 (POP eMMC, not on DB8500ed)
+ */
+
+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,
+};
+
+/*
+ * SDI 4 (on-board eMMC)
+ */
+
+static struct mmci_platform_data mop500_sdi4_data = {
+	.ocr_mask	= MMC_VDD_29_30,
+	.f_max		= 100000000,
+	.capabilities	= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
+			  MMC_CAP_MMC_HIGHSPEED,
+	.gpio_cd	= -1,
+	.gpio_wp	= -1,
+};
+
+void mop500_sdi_init(void)
+{
+	nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins));
+
+	u8500_sdi2_device.dev.platform_data = &mop500_sdi2_data;
+	u8500_sdi4_device.dev.platform_data = &mop500_sdi4_data;
+
+	if (!cpu_is_u8500ed()) {
+		nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins));
+		amba_device_register(&u8500_sdi2_device, &iomem_resource);
+	}
+
+	/* On-board eMMC */
+	amba_device_register(&u8500_sdi4_device, &iomem_resource);
+}
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 0e8fd13..fcb587f 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -28,8 +28,10 @@
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
+#include <mach/irqs.h>
 
 #include "pins-db8500.h"
+#include "board-mop500.h"
 
 static pin_cfg_t mop500_pins[] = {
 	/* SSP0 */
@@ -55,19 +57,13 @@
 }
 
 struct pl022_config_chip ab4500_chip_info = {
-	.lbm = LOOPBACK_DISABLED,
 	.com_mode = INTERRUPT_TRANSFER,
 	.iface = SSP_INTERFACE_MOTOROLA_SPI,
 	/* we can act as master only */
 	.hierarchy = SSP_MASTER,
 	.slave_tx_disable = 0,
-	.endian_rx = SSP_RX_MSB,
-	.endian_tx = SSP_TX_MSB,
-	.data_size = SSP_DATA_BITS_24,
 	.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
 	.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
-	.clk_phase = SSP_CLK_SECOND_EDGE,
-	.clk_pol = SSP_CLK_POL_IDLE_HIGH,
 	.cs_control = ab4500_spi_cs_control,
 };
 
@@ -75,15 +71,33 @@
 	.irq_base	= MOP500_AB8500_IRQ_BASE,
 };
 
-static struct spi_board_info u8500_spi_devices[] = {
+static struct resource ab8500_resources[] = {
+	[0] = {
+		.start = IRQ_AB8500,
+		.end = IRQ_AB8500,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+struct platform_device ab8500_device = {
+	.name = "ab8500-i2c",
+	.id = 0,
+	.dev = {
+		.platform_data = &ab8500_platdata,
+	},
+	.num_resources = 1,
+	.resource = ab8500_resources,
+};
+
+static struct spi_board_info ab8500_spi_devices[] = {
 	{
-		.modalias = "ab8500",
+		.modalias = "ab8500-spi",
 		.controller_data = &ab4500_chip_info,
 		.platform_data = &ab8500_platdata,
 		.max_speed_hz = 12000000,
 		.bus_num = 0,
 		.chip_select = 0,
-		.mode = SPI_MODE_0,
+		.mode = SPI_MODE_3,
 		.irq = IRQ_DB8500_AB8500,
 	},
 };
@@ -163,14 +177,18 @@
 
 	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
-	spi_register_board_info(u8500_spi_devices,
-			ARRAY_SIZE(u8500_spi_devices));
+	mop500_sdi_init();
+
+	/* If HW is early drop (ED) or V1.0 then use SPI to access AB8500 */
+	if (cpu_is_u8500ed() || cpu_is_u8500v10())
+		spi_register_board_info(ab8500_spi_devices,
+			ARRAY_SIZE(ab8500_spi_devices));
+	else /* If HW is v.1.1 or later use I2C to access AB8500 */
+		platform_device_register(&ab8500_device);
 }
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
 	/* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
-	.phys_io	= U8500_UART2_BASE,
-	.io_pg_offst	= (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x100,
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
new file mode 100644
index 0000000..2d24032
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __BOARD_MOP500_H
+#define __BOARD_MOP500_H
+
+extern void mop500_sdi_init(void);
+
+#endif
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c
index 4430e69..1ca094a 100644
--- a/arch/arm/mach-ux500/board-u5500.c
+++ b/arch/arm/mach-ux500/board-u5500.c
@@ -31,8 +31,6 @@
 }
 
 MACHINE_START(U8500, "ST-Ericsson U5500 Platform")
-	.phys_io	= UX500_UART0_BASE,
-	.io_pg_offst	= (IO_ADDRESS(UX500_UART0_BASE) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= u5500_map_io,
 	.init_irq	= ux500_init_irq,
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index e9278f6..2f87075 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -14,6 +14,7 @@
 #include <mach/hardware.h>
 #include <mach/devices.h>
 #include <mach/setup.h>
+#include <mach/irqs.h>
 
 static struct map_desc u5500_io_desc[] __initdata = {
 	__IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K),
@@ -24,6 +25,90 @@
 	__IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K),
 };
 
+static struct resource mbox0_resources[] = {
+	{
+		.name = "mbox_peer",
+		.start = U5500_MBOX0_PEER_START,
+		.end = U5500_MBOX0_PEER_END,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "mbox_local",
+		.start = U5500_MBOX0_LOCAL_START,
+		.end = U5500_MBOX0_LOCAL_END,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "mbox_irq",
+		.start = MBOX_PAIR0_VIRT_IRQ,
+		.end = MBOX_PAIR0_VIRT_IRQ,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource mbox1_resources[] = {
+	{
+		.name = "mbox_peer",
+		.start = U5500_MBOX1_PEER_START,
+		.end = U5500_MBOX1_PEER_END,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "mbox_local",
+		.start = U5500_MBOX1_LOCAL_START,
+		.end = U5500_MBOX1_LOCAL_END,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "mbox_irq",
+		.start = MBOX_PAIR1_VIRT_IRQ,
+		.end = MBOX_PAIR1_VIRT_IRQ,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource mbox2_resources[] = {
+	{
+		.name = "mbox_peer",
+		.start = U5500_MBOX2_PEER_START,
+		.end = U5500_MBOX2_PEER_END,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "mbox_local",
+		.start = U5500_MBOX2_LOCAL_START,
+		.end = U5500_MBOX2_LOCAL_END,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "mbox_irq",
+		.start = MBOX_PAIR2_VIRT_IRQ,
+		.end = MBOX_PAIR2_VIRT_IRQ,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device mbox0_device = {
+	.id = 0,
+	.name = "mbox",
+	.resource = mbox0_resources,
+	.num_resources = ARRAY_SIZE(mbox0_resources),
+};
+
+static struct platform_device mbox1_device = {
+	.id = 1,
+	.name = "mbox",
+	.resource = mbox1_resources,
+	.num_resources = ARRAY_SIZE(mbox1_resources),
+};
+
+static struct platform_device mbox2_device = {
+	.id = 2,
+	.name = "mbox",
+	.resource = mbox2_resources,
+	.num_resources = ARRAY_SIZE(mbox2_resources),
+};
+
 static struct platform_device *u5500_platform_devs[] __initdata = {
 	&u5500_gpio_devs[0],
 	&u5500_gpio_devs[1],
@@ -33,6 +118,9 @@
 	&u5500_gpio_devs[5],
 	&u5500_gpio_devs[6],
 	&u5500_gpio_devs[7],
+	&mbox0_device,
+	&mbox1_device,
+	&mbox2_device,
 };
 
 void __init u5500_map_io(void)
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index f21c444..4acab75 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -38,10 +38,12 @@
 /* minimum static i/o mapping required to boot U8500 platforms */
 static struct map_desc u8500_io_desc[] __initdata = {
 	__IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
+	__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
 	__IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K),
 	__IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
 	__IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
 	__IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K),
+	__MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M),
 };
 
 static struct map_desc u8500ed_io_desc[] __initdata = {
@@ -53,6 +55,69 @@
 	__IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
 };
 
+/*
+ * Functions to differentiate between later ASICs
+ * We look into the end of the ROM to locate the hardcoded ASIC ID.
+ * This is only needed to differentiate between minor revisions and
+ * process variants of an ASIC, the major revisions are encoded in
+ * the cpuid.
+ */
+#define U8500_ASIC_ID_LOC_ED_V1	(U8500_BOOT_ROM_BASE + 0x1FFF4)
+#define U8500_ASIC_ID_LOC_V2	(U8500_BOOT_ROM_BASE + 0x1DBF4)
+#define U8500_ASIC_REV_ED	0x01
+#define U8500_ASIC_REV_V10	0xA0
+#define U8500_ASIC_REV_V11	0xA1
+#define U8500_ASIC_REV_V20	0xB0
+
+/**
+ * struct db8500_asic_id - fields of the ASIC ID
+ * @process: the manufacturing process, 0x40 is 40 nm
+ *  0x00 is "standard"
+ * @partnumber: hithereto 0x8500 for DB8500
+ * @revision: version code in the series
+ * This field definion is not formally defined but makes
+ * sense.
+ */
+struct db8500_asic_id {
+	u8 process;
+	u16 partnumber;
+	u8 revision;
+};
+
+/* This isn't going to change at runtime */
+static struct db8500_asic_id db8500_id;
+
+static void __init get_db8500_asic_id(void)
+{
+	u32 asicid;
+
+	if (cpu_is_u8500v1() || cpu_is_u8500ed())
+		asicid = readl(__io_address(U8500_ASIC_ID_LOC_ED_V1));
+	else if (cpu_is_u8500v2())
+		asicid = readl(__io_address(U8500_ASIC_ID_LOC_V2));
+	else
+		BUG();
+
+	db8500_id.process = (asicid >> 24);
+	db8500_id.partnumber = (asicid >> 16) & 0xFFFFU;
+	db8500_id.revision = asicid & 0xFFU;
+}
+
+bool cpu_is_u8500v10(void)
+{
+	return (db8500_id.revision == U8500_ASIC_REV_V10);
+}
+
+bool cpu_is_u8500v11(void)
+{
+	return (db8500_id.revision == U8500_ASIC_REV_V11);
+}
+
+bool cpu_is_u8500v20(void)
+{
+	return (db8500_id.revision == U8500_ASIC_REV_V20);
+}
+
 void __init u8500_map_io(void)
 {
 	ux500_map_io();
@@ -63,6 +128,9 @@
 		iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc));
 	else
 		iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc));
+
+	/* Read out the ASIC ID as early as we can */
+	get_db8500_asic_id();
 }
 
 /*
@@ -70,6 +138,20 @@
  */
 void __init u8500_init_devices(void)
 {
+	/* Display some ASIC boilerplate */
+	pr_info("DB8500: process: %02x, revision ID: 0x%02x\n",
+		db8500_id.process, db8500_id.revision);
+	if (cpu_is_u8500ed())
+		pr_info("DB8500: Early Drop (ED)\n");
+	else if (cpu_is_u8500v10())
+		pr_info("DB8500: version 1.0\n");
+	else if (cpu_is_u8500v11())
+		pr_info("DB8500: version 1.1\n");
+	else if (cpu_is_u8500v20())
+		pr_info("DB8500: version 2.0\n");
+	else
+		pr_warning("ASIC: UNKNOWN SILICON VERSION!\n");
+
 	ux500_init_devices();
 
 	if (cpu_is_u8500ed())
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index 9280d25..40032fe 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -110,6 +110,82 @@
 	.num_resources	= ARRAY_SIZE(u8500_i2c4_resources),
 };
 
+/*
+ * SD/MMC
+ */
+
+struct amba_device u8500_sdi0_device = {
+	.dev		= {
+		.init_name = "sdi0",
+	},
+	.res		= {
+		.start	= U8500_SDI0_BASE,
+		.end	= U8500_SDI0_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	.irq		= {IRQ_DB8500_SDMMC0, NO_IRQ},
+};
+
+struct amba_device u8500_sdi1_device = {
+	.dev		= {
+		.init_name = "sdi1",
+	},
+	.res		= {
+		.start	= U8500_SDI1_BASE,
+		.end	= U8500_SDI1_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	.irq		= {IRQ_DB8500_SDMMC1, NO_IRQ},
+};
+
+struct amba_device u8500_sdi2_device = {
+	.dev		= {
+		.init_name = "sdi2",
+	},
+	.res		= {
+		.start	= U8500_SDI2_BASE,
+		.end	= U8500_SDI2_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	.irq		= {IRQ_DB8500_SDMMC2, NO_IRQ},
+};
+
+struct amba_device u8500_sdi3_device = {
+	.dev		= {
+		.init_name = "sdi3",
+	},
+	.res		= {
+		.start	= U8500_SDI3_BASE,
+		.end	= U8500_SDI3_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	.irq		= {IRQ_DB8500_SDMMC3, NO_IRQ},
+};
+
+struct amba_device u8500_sdi4_device = {
+	.dev		= {
+		.init_name = "sdi4",
+	},
+	.res		= {
+		.start	= U8500_SDI4_BASE,
+		.end	= U8500_SDI4_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	.irq		= {IRQ_DB8500_SDMMC4, NO_IRQ},
+};
+
+struct amba_device u8500_sdi5_device = {
+	.dev		= {
+		.init_name = "sdi5",
+	},
+	.res		= {
+		.start	= U8500_SDI5_BASE,
+		.end	= U8500_SDI5_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	.irq		= {IRQ_DB8500_SDMMC5, NO_IRQ},
+};
+
 static struct resource dma40_resources[] = {
 	[0] = {
 		.start = U8500_DMA_BASE,
@@ -170,23 +246,23 @@
  * Mapping between destination event lines and physical device address.
  * The event line is tied to a device and therefor the address is constant.
  */
-static const dma_addr_t dma40_tx_map[STEDMA40_NR_DEV];
+static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV];
 
 /* Mapping between source event lines and physical device address */
-static const dma_addr_t dma40_rx_map[STEDMA40_NR_DEV];
+static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV];
 
 /* Reserved event lines for memcpy only */
 static int dma40_memcpy_event[] = {
-	STEDMA40_MEMCPY_TX_0,
-	STEDMA40_MEMCPY_TX_1,
-	STEDMA40_MEMCPY_TX_2,
-	STEDMA40_MEMCPY_TX_3,
-	STEDMA40_MEMCPY_TX_4,
-	STEDMA40_MEMCPY_TX_5,
+	DB8500_DMA_MEMCPY_TX_0,
+	DB8500_DMA_MEMCPY_TX_1,
+	DB8500_DMA_MEMCPY_TX_2,
+	DB8500_DMA_MEMCPY_TX_3,
+	DB8500_DMA_MEMCPY_TX_4,
+	DB8500_DMA_MEMCPY_TX_5,
 };
 
 static struct stedma40_platform_data dma40_plat_data = {
-	.dev_len = STEDMA40_NR_DEV,
+	.dev_len = DB8500_DMA_NR_DEV,
 	.dev_rx = dma40_rx_map,
 	.dev_tx = dma40_tx_map,
 	.memcpy = dma40_memcpy_event,
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c
new file mode 100644
index 0000000..b782a03
--- /dev/null
+++ b/arch/arm/mach-ux500/hotplug.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *	Based on ARM realview platform
+ *
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/completion.h>
+
+#include <asm/cacheflush.h>
+
+extern volatile int pen_release;
+
+static DECLARE_COMPLETION(cpu_killed);
+
+static inline void platform_do_lowpower(unsigned int cpu)
+{
+	flush_cache_all();
+
+	/* we put the platform to just WFI */
+	for (;;) {
+		__asm__ __volatile__("dsb\n\t" "wfi\n\t"
+				: : : "memory");
+		if (pen_release == cpu) {
+			/*
+			 * OK, proper wakeup, we're done
+			 */
+			break;
+		}
+	}
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return wait_for_completion_timeout(&cpu_killed, 5000);
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+#ifdef DEBUG
+	unsigned int this_cpu = hard_smp_processor_id();
+
+	if (cpu != this_cpu) {
+		printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
+			   this_cpu, cpu);
+		BUG();
+	}
+#endif
+
+	printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
+	complete(&cpu_killed);
+
+	/* directly enter low power state, skipping secure registers */
+	platform_do_lowpower(cpu);
+}
+
+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-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h
index 545c80f..3eafc0e 100644
--- a/arch/arm/mach-ux500/include/mach/db5500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h
@@ -100,4 +100,18 @@
 #define U5500_GPIOBANK6_BASE	(U5500_GPIO4_BASE + 0x80)
 #define U5500_GPIOBANK7_BASE	(U5500_GPIO4_BASE + 0x100)
 
+#define U5500_MBOX_BASE		(U5500_MODEM_BASE + 0xFFD1000)
+#define U5500_MBOX0_PEER_START	(U5500_MBOX_BASE + 0x40)
+#define U5500_MBOX0_PEER_END	(U5500_MBOX_BASE + 0x5F)
+#define U5500_MBOX0_LOCAL_START	(U5500_MBOX_BASE + 0x60)
+#define U5500_MBOX0_LOCAL_END	(U5500_MBOX_BASE + 0x7F)
+#define U5500_MBOX1_PEER_START	(U5500_MBOX_BASE + 0x80)
+#define U5500_MBOX1_PEER_END	(U5500_MBOX_BASE + 0x9F)
+#define U5500_MBOX1_LOCAL_START	(U5500_MBOX_BASE + 0xA0)
+#define U5500_MBOX1_LOCAL_END	(U5500_MBOX_BASE + 0xBF)
+#define U5500_MBOX2_PEER_START	(U5500_MBOX_BASE + 0x00)
+#define U5500_MBOX2_PEER_END	(U5500_MBOX_BASE + 0x1F)
+#define U5500_MBOX2_LOCAL_START	(U5500_MBOX_BASE + 0x20)
+#define U5500_MBOX2_LOCAL_END	(U5500_MBOX_BASE + 0x3F)
+
 #endif
diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h
index f000218..f07d098 100644
--- a/arch/arm/mach-ux500/include/mach/db8500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h
@@ -30,8 +30,6 @@
 #define U8500_ICN_BASE		0x81000000
 
 #define U8500_BOOT_ROM_BASE	0x90000000
-/* ASIC ID is at 0xff4 offset within this region */
-#define U8500_ASIC_ID_BASE	0x9001F000
 
 #define U8500_PER6_BASE		0xa03c0000
 #define U8500_PER5_BASE		0xa03e0000
diff --git a/arch/arm/mach-ux500/include/mach/debug-macro.S b/arch/arm/mach-ux500/include/mach/debug-macro.S
index c5203b7..be7c0f1 100644
--- a/arch/arm/mach-ux500/include/mach/debug-macro.S
+++ b/arch/arm/mach-ux500/include/mach/debug-macro.S
@@ -18,11 +18,9 @@
 #define UX500_UART(n)	__UX500_UART(n)
 #define UART_BASE	UX500_UART(CONFIG_UX500_DEBUG_UART)
 
-	.macro	addruart, rx, tmp
-	mrc	p15, 0, \rx, c1, c0
-	tst	\rx, #1					@ MMU enabled?
-	ldreq	\rx, =UART_BASE				@ no, physical address
-	ldrne	\rx, =IO_ADDRESS(UART_BASE)		@ yes, virtual address
+	.macro	addruart, rp, rv
+	ldr	\rp, =UART_BASE				@ no, physical address
+	ldr	\rv, =IO_ADDRESS(UART_BASE)		@ yes, virtual address
 	.endm
 
 #include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h
index c2b2f25..33a120c 100644
--- a/arch/arm/mach-ux500/include/mach/devices.h
+++ b/arch/arm/mach-ux500/include/mach/devices.h
@@ -27,6 +27,13 @@
 extern struct platform_device u8500_i2c4_device;
 extern struct platform_device u8500_dma40_device;
 
+extern struct amba_device u8500_sdi0_device;
+extern struct amba_device u8500_sdi1_device;
+extern struct amba_device u8500_sdi2_device;
+extern struct amba_device u8500_sdi3_device;
+extern struct amba_device u8500_sdi4_device;
+extern struct amba_device u8500_sdi5_device;
+
 void dma40_u8500ed_fixup(void);
 
 #endif
diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h
index 8656379..32e883a 100644
--- a/arch/arm/mach-ux500/include/mach/hardware.h
+++ b/arch/arm/mach-ux500/include/mach/hardware.h
@@ -104,16 +104,35 @@
 #endif
 }
 
+#define CPUID_DB8500ED	0x410fc090
+#define CPUID_DB8500V1	0x411fc091
+#define CPUID_DB8500V2	0x412fc091
+
 static inline bool cpu_is_u8500ed(void)
 {
-	return cpu_is_u8500() && (read_cpuid_id() & 15) == 0;
+	return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500ED);
 }
 
 static inline bool cpu_is_u8500v1(void)
 {
-	return cpu_is_u8500() && (read_cpuid_id() & 15) == 1;
+	return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V1);
 }
 
+static inline bool cpu_is_u8500v2(void)
+{
+	return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V2);
+}
+
+#ifdef CONFIG_UX500_SOC_DB8500
+bool cpu_is_u8500v10(void);
+bool cpu_is_u8500v11(void);
+bool cpu_is_u8500v20(void);
+#else
+static inline bool cpu_is_u8500v10(void) { return false; }
+static inline bool cpu_is_u8500v11(void) { return false; }
+static inline bool cpu_is_u8500v20(void) { return false; }
+#endif
+
 static inline bool cpu_is_u5500(void)
 {
 #ifdef CONFIG_UX500_SOC_DB5500
diff --git a/arch/arm/mach-ux500/include/mach/irqs-db5500.h b/arch/arm/mach-ux500/include/mach/irqs-db5500.h
index 6fbfe5e..bfa123d 100644
--- a/arch/arm/mach-ux500/include/mach/irqs-db5500.h
+++ b/arch/arm/mach-ux500/include/mach/irqs-db5500.h
@@ -61,6 +61,7 @@
 #define IRQ_DB5500_SDMMC0		(IRQ_SHPI_START + 60)
 #define IRQ_DB5500_HSEM			(IRQ_SHPI_START + 61)
 #define IRQ_DB5500_SBAG			(IRQ_SHPI_START + 63)
+#define IRQ_DB5500_MODEM		(IRQ_SHPI_START + 65)
 #define IRQ_DB5500_SPI1			(IRQ_SHPI_START + 96)
 #define IRQ_DB5500_MSP2			(IRQ_SHPI_START + 98)
 #define IRQ_DB5500_SRPTIMER		(IRQ_SHPI_START + 101)
diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h
index 10385bd..693aa57 100644
--- a/arch/arm/mach-ux500/include/mach/irqs.h
+++ b/arch/arm/mach-ux500/include/mach/irqs.h
@@ -40,7 +40,8 @@
 #define IRQ_HSIR_CH1_OVRRUN	(IRQ_SHPI_START + 33)
 #define IRQ_HSIR_CH2_OVRRUN	(IRQ_SHPI_START + 34)
 #define IRQ_HSIR_CH3_OVRRUN	(IRQ_SHPI_START + 35)
-#define IRQ_AB4500		(IRQ_SHPI_START + 40)
+#define IRQ_AB8500		(IRQ_SHPI_START + 40)
+#define IRQ_PRCMU               (IRQ_SHPI_START + 47)
 #define IRQ_DISP		(IRQ_SHPI_START + 48)
 #define IRQ_SiPI3		(IRQ_SHPI_START + 49)
 #define IRQ_I2C4		(IRQ_SHPI_START + 51)
@@ -83,6 +84,19 @@
 #include <mach/irqs-board-mop500.h>
 #endif
 
-#define NR_IRQS				IRQ_BOARD_END
+/*
+ * After the board specific IRQ:s we reserve a range of IRQ:s in which virtual
+ * IRQ:s representing modem IRQ:s can be allocated
+ */
+#define IRQ_MODEM_EVENTS_BASE (IRQ_BOARD_END + 1)
+#define IRQ_MODEM_EVENTS_NBR 72
+#define IRQ_MODEM_EVENTS_END (IRQ_MODEM_EVENTS_BASE + IRQ_MODEM_EVENTS_NBR)
+
+/* List of virtual IRQ:s that are allocated from the range above */
+#define MBOX_PAIR0_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 43)
+#define MBOX_PAIR1_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 45)
+#define MBOX_PAIR2_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 41)
+
+#define NR_IRQS				IRQ_MODEM_EVENTS_END
 
 #endif /* ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-ux500/include/mach/mbox.h b/arch/arm/mach-ux500/include/mach/mbox.h
new file mode 100644
index 0000000..7f9da4d
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/mbox.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __INC_STE_MBOX_H
+#define __INC_STE_MBOX_H
+
+#define MBOX_BUF_SIZE 16
+#define MBOX_NAME_SIZE 8
+
+/**
+  * mbox_recv_cb_t - Definition of the mailbox callback.
+  * @mbox_msg:	The mailbox message.
+  * @priv:	The clients private data as specified in the call to mbox_setup.
+  *
+  * This function will be called upon reception of new mailbox messages.
+  */
+typedef void mbox_recv_cb_t (u32 mbox_msg, void *priv);
+
+/**
+  * struct mbox - Mailbox instance struct
+  * @list:		Linked list head.
+  * @pdev:		Pointer to device struct.
+  * @cb:		Callback function. Will be called
+  *			when new data is received.
+  * @client_data:	Clients private data. Will be sent back
+  *			in the callback function.
+  * @virtbase_peer:	Virtual address for outgoing mailbox.
+  * @virtbase_local:	Virtual address for incoming mailbox.
+  * @buffer:		Then internal queue for outgoing messages.
+  * @name:		Name of this mailbox.
+  * @buffer_available:	Completion variable to achieve "blocking send".
+  *			This variable will be signaled when there is
+  *			internal buffer space available.
+  * @client_blocked:	To keep track if any client is currently
+  *			blocked.
+  * @lock:		Spinlock to protect this mailbox instance.
+  * @write_index:	Index in internal buffer to write to.
+  * @read_index:	Index in internal buffer to read from.
+  * @allocated:		Indicates whether this particular mailbox
+  *			id has been allocated by someone.
+  */
+struct mbox {
+	struct list_head list;
+	struct platform_device *pdev;
+	mbox_recv_cb_t *cb;
+	void *client_data;
+	void __iomem *virtbase_peer;
+	void __iomem *virtbase_local;
+	u32 buffer[MBOX_BUF_SIZE];
+	char name[MBOX_NAME_SIZE];
+	struct completion buffer_available;
+	u8 client_blocked;
+	spinlock_t lock;
+	u8 write_index;
+	u8 read_index;
+	bool allocated;
+};
+
+/**
+  * mbox_setup - Set up a mailbox and return its instance.
+  * @mbox_id:	The ID number of the mailbox. 0 or 1 for modem CPU,
+  *		2 for modem DSP.
+  * @mbox_cb:	Pointer to the callback function to be called when a new message
+  *		is received.
+  * @priv:	Client user data which will be returned in the callback.
+  *
+  * Returns a mailbox instance to be specified in subsequent calls to mbox_send.
+  */
+struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv);
+
+/**
+  * mbox_send - Send a mailbox message.
+  * @mbox:	Mailbox instance (returned by mbox_setup)
+  * @mbox_msg:	The mailbox message to send.
+  * @block:	Specifies whether this call will block until send is possible,
+  *		or return an error if the mailbox buffer is full.
+  *
+  * Returns 0 on success or a negative error code on error. -ENOMEM indicates
+  * that the internal buffer is full and you have to try again later (or
+  * specify "block" in order to block until send is possible).
+  */
+int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block);
+
+#endif /*INC_STE_MBOX_H*/
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
new file mode 100644
index 0000000..8885f39
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2009 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 published by the Free Software Foundation.
+ */
+#ifndef __MACH_PRCMU_REGS_H
+#define __MACH_PRCMU_REGS_H
+
+#include <mach/hardware.h>
+
+#define _PRCMU_BASE		IO_ADDRESS(U8500_PRCMU_BASE)
+
+#define PRCM_ARM_PLLDIVPS	(_PRCMU_BASE + 0x118)
+#define PRCM_ARM_CHGCLKREQ	(_PRCMU_BASE + 0x114)
+#define PRCM_PLLARM_ENABLE	(_PRCMU_BASE + 0x98)
+#define PRCM_ARMCLKFIX_MGT	(_PRCMU_BASE + 0x0)
+#define PRCM_A9_RESETN_CLR	(_PRCMU_BASE + 0x1f4)
+#define PRCM_A9_RESETN_SET	(_PRCMU_BASE + 0x1f0)
+#define PRCM_ARM_LS_CLAMP	(_PRCMU_BASE + 0x30c)
+#define PRCM_SRAM_A9		(_PRCMU_BASE + 0x308)
+
+/* ARM WFI Standby signal register */
+#define PRCM_ARM_WFI_STANDBY    (_PRCMU_BASE + 0x130)
+#define PRCMU_IOCR              (_PRCMU_BASE + 0x310)
+
+/* CPU mailbox registers */
+#define PRCM_MBOX_CPU_VAL	(_PRCMU_BASE + 0x0fc)
+#define PRCM_MBOX_CPU_SET	(_PRCMU_BASE + 0x100)
+#define PRCM_MBOX_CPU_CLR	(_PRCMU_BASE + 0x104)
+
+/* Dual A9 core interrupt management unit registers */
+#define PRCM_A9_MASK_REQ	(_PRCMU_BASE + 0x328)
+#define PRCM_A9_MASK_ACK	(_PRCMU_BASE + 0x32c)
+#define PRCM_ARMITMSK31TO0	(_PRCMU_BASE + 0x11c)
+#define PRCM_ARMITMSK63TO32	(_PRCMU_BASE + 0x120)
+#define PRCM_ARMITMSK95TO64	(_PRCMU_BASE + 0x124)
+#define PRCM_ARMITMSK127TO96	(_PRCMU_BASE + 0x128)
+#define PRCM_POWER_STATE_VAL	(_PRCMU_BASE + 0x25C)
+#define PRCM_ARMITVAL31TO0	(_PRCMU_BASE + 0x260)
+#define PRCM_ARMITVAL63TO32	(_PRCMU_BASE + 0x264)
+#define PRCM_ARMITVAL95TO64	(_PRCMU_BASE + 0x268)
+#define PRCM_ARMITVAL127TO96	(_PRCMU_BASE + 0x26C)
+
+#define PRCM_HOSTACCESS_REQ	(_PRCMU_BASE + 0x334)
+#define ARM_WAKEUP_MODEM	0x1
+
+#define PRCM_ARM_IT1_CLEAR	(_PRCMU_BASE + 0x48C)
+#define PRCM_ARM_IT1_VAL	(_PRCMU_BASE + 0x494)
+#define PRCM_HOLD_EVT		(_PRCMU_BASE + 0x174)
+
+#define PRCM_ITSTATUS0		(_PRCMU_BASE + 0x148)
+#define PRCM_ITSTATUS1		(_PRCMU_BASE + 0x150)
+#define PRCM_ITSTATUS2		(_PRCMU_BASE + 0x158)
+#define PRCM_ITSTATUS3		(_PRCMU_BASE + 0x160)
+#define PRCM_ITSTATUS4		(_PRCMU_BASE + 0x168)
+#define PRCM_ITSTATUS5		(_PRCMU_BASE + 0x484)
+#define PRCM_ITCLEAR5		(_PRCMU_BASE + 0x488)
+#define PRCM_ARMIT_MASKXP70_IT	(_PRCMU_BASE + 0x1018)
+
+/* System reset register */
+#define PRCM_APE_SOFTRST	(_PRCMU_BASE + 0x228)
+
+/* Level shifter and clamp control registers */
+#define PRCM_MMIP_LS_CLAMP_SET     (_PRCMU_BASE + 0x420)
+#define PRCM_MMIP_LS_CLAMP_CLR     (_PRCMU_BASE + 0x424)
+
+/* PRCMU clock/PLL/reset registers */
+#define PRCM_PLLDSI_FREQ           (_PRCMU_BASE + 0x500)
+#define PRCM_PLLDSI_ENABLE         (_PRCMU_BASE + 0x504)
+#define PRCM_LCDCLK_MGT            (_PRCMU_BASE + 0x044)
+#define PRCM_MCDECLK_MGT           (_PRCMU_BASE + 0x064)
+#define PRCM_HDMICLK_MGT           (_PRCMU_BASE + 0x058)
+#define PRCM_TVCLK_MGT             (_PRCMU_BASE + 0x07c)
+#define PRCM_DSI_PLLOUT_SEL        (_PRCMU_BASE + 0x530)
+#define PRCM_DSITVCLK_DIV          (_PRCMU_BASE + 0x52C)
+#define PRCM_APE_RESETN_SET        (_PRCMU_BASE + 0x1E4)
+#define PRCM_APE_RESETN_CLR        (_PRCMU_BASE + 0x1E8)
+
+/* ePOD and memory power signal control registers */
+#define PRCM_EPOD_C_SET            (_PRCMU_BASE + 0x410)
+#define PRCM_SRAM_LS_SLEEP         (_PRCMU_BASE + 0x304)
+
+/* Debug power control unit registers */
+#define PRCM_POWER_STATE_SET       (_PRCMU_BASE + 0x254)
+
+/* Miscellaneous unit registers */
+#define PRCM_DSI_SW_RESET          (_PRCMU_BASE + 0x324)
+
+#endif /* __MACH_PRCMU__REGS_H */
diff --git a/arch/arm/mach-ux500/include/mach/prcmu.h b/arch/arm/mach-ux500/include/mach/prcmu.h
new file mode 100644
index 0000000..549843f
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/prcmu.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * PRCMU f/w APIs
+ */
+#ifndef __MACH_PRCMU_H
+#define __MACH_PRCMU_H
+
+int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
+int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+
+#endif /* __MACH_PRCMU_H */
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h
index e978dbd..54bbe64 100644
--- a/arch/arm/mach-ux500/include/mach/setup.h
+++ b/arch/arm/mach-ux500/include/mach/setup.h
@@ -38,4 +38,11 @@
 	.type		= MT_DEVICE,		\
 }
 
+#define __MEM_DEV_DESC(x, sz)	{		\
+	.virtual	= IO_ADDRESS(x),	\
+	.pfn		= __phys_to_pfn(x),	\
+	.length		= sz,			\
+	.type		= MT_MEMORY,		\
+}
+
 #endif /*  __ASM_ARCH_SETUP_H */
diff --git a/arch/arm/mach-ux500/include/mach/smp.h b/arch/arm/mach-ux500/include/mach/smp.h
index b59f7bc..197e841 100644
--- a/arch/arm/mach-ux500/include/mach/smp.h
+++ b/arch/arm/mach-ux500/include/mach/smp.h
@@ -10,18 +10,11 @@
 #define ASMARM_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
+#include <asm/smp_mpidr.h>
 
 /* This is required to wakeup the secondary core */
 extern void u8500_secondary_startup(void);
 
-#define hard_smp_processor_id()				\
-	({						\
-		unsigned int cpunum;			\
-		__asm__("mrc p15, 0, %0, c0, c0, 5"	\
-			: "=r" (cpunum));		\
-		cpunum &= 0x0F;				\
-	})
-
 /*
  * We use IRQ1 as the IPI
  */
diff --git a/arch/arm/mach-ux500/mbox.c b/arch/arm/mach-ux500/mbox.c
new file mode 100644
index 0000000..6343538
--- /dev/null
+++ b/arch/arm/mach-ux500/mbox.c
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+/*
+ * Mailbox nomenclature:
+ *
+ *       APE           MODEM
+ *           mbox pairX
+ *   ..........................
+ *   .                       .
+ *   .           peer        .
+ *   .     send  ----        .
+ *   .      -->  |  |        .
+ *   .           |  |        .
+ *   .           ----        .
+ *   .                       .
+ *   .           local       .
+ *   .     rec   ----        .
+ *   .           |  | <--    .
+ *   .           |  |        .
+ *   .           ----        .
+ *   .........................
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/completion.h>
+#include <mach/mbox.h>
+
+#define MBOX_NAME "mbox"
+
+#define MBOX_FIFO_DATA        0x000
+#define MBOX_FIFO_ADD         0x004
+#define MBOX_FIFO_REMOVE      0x008
+#define MBOX_FIFO_THRES_FREE  0x00C
+#define MBOX_FIFO_THRES_OCCUP 0x010
+#define MBOX_FIFO_STATUS      0x014
+
+#define MBOX_DISABLE_IRQ 0x4
+#define MBOX_ENABLE_IRQ  0x0
+#define MBOX_LATCH 1
+
+/* Global list of all mailboxes */
+static struct list_head mboxs = LIST_HEAD_INIT(mboxs);
+
+static struct mbox *get_mbox_with_id(u8 id)
+{
+	u8 i;
+	struct list_head *pos = &mboxs;
+	for (i = 0; i <= id; i++)
+		pos = pos->next;
+
+	return (struct mbox *) list_entry(pos, struct mbox, list);
+}
+
+int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block)
+{
+	int res = 0;
+
+	spin_lock(&mbox->lock);
+
+	dev_dbg(&(mbox->pdev->dev),
+		"About to buffer 0x%X to mailbox 0x%X."
+		" ri = %d, wi = %d\n",
+		mbox_msg, (u32)mbox, mbox->read_index,
+		mbox->write_index);
+
+	/* Check if write buffer is full */
+	while (((mbox->write_index + 1) % MBOX_BUF_SIZE) == mbox->read_index) {
+		if (!block) {
+			dev_dbg(&(mbox->pdev->dev),
+			"Buffer full in non-blocking call! "
+			"Returning -ENOMEM!\n");
+			res = -ENOMEM;
+			goto exit;
+		}
+		spin_unlock(&mbox->lock);
+		dev_dbg(&(mbox->pdev->dev),
+			"Buffer full in blocking call! Sleeping...\n");
+		mbox->client_blocked = 1;
+		wait_for_completion(&mbox->buffer_available);
+		dev_dbg(&(mbox->pdev->dev),
+			"Blocking send was woken up! Trying again...\n");
+		spin_lock(&mbox->lock);
+	}
+
+	mbox->buffer[mbox->write_index] = mbox_msg;
+	mbox->write_index = (mbox->write_index + 1) % MBOX_BUF_SIZE;
+
+	/*
+	 * Indicate that we want an IRQ as soon as there is a slot
+	 * in the FIFO
+	 */
+	writel(MBOX_ENABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+
+exit:
+	spin_unlock(&mbox->lock);
+	return res;
+}
+EXPORT_SYMBOL(mbox_send);
+
+#if defined(CONFIG_DEBUG_FS)
+/*
+ * Expected input: <value> <nbr sends>
+ * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times
+ */
+static ssize_t mbox_write_fifo(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf,
+			       size_t count)
+{
+	unsigned long mbox_mess;
+	unsigned long nbr_sends;
+	unsigned long i;
+	char int_buf[16];
+	char *token;
+	char *val;
+
+	struct mbox *mbox = (struct mbox *) dev->platform_data;
+
+	strncpy((char *) &int_buf, buf, sizeof(int_buf));
+	token = (char *) &int_buf;
+
+	/* Parse message */
+	val = strsep(&token, " ");
+	if ((val == NULL) || (strict_strtoul(val, 16, &mbox_mess) != 0))
+		mbox_mess = 0xDEADBEEF;
+
+	val = strsep(&token, " ");
+	if ((val == NULL) || (strict_strtoul(val, 10, &nbr_sends) != 0))
+		nbr_sends = 1;
+
+	dev_dbg(dev, "Will write 0x%lX %ld times using data struct at 0x%X\n",
+		mbox_mess, nbr_sends, (u32) mbox);
+
+	for (i = 0; i < nbr_sends; i++)
+		mbox_send(mbox, mbox_mess, true);
+
+	return count;
+}
+
+static ssize_t mbox_read_fifo(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	int mbox_value;
+	struct mbox *mbox = (struct mbox *) dev->platform_data;
+
+	if ((readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7) <= 0)
+		return sprintf(buf, "Mailbox is empty\n");
+
+	mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
+	writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
+
+	return sprintf(buf, "0x%X\n", mbox_value);
+}
+
+static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
+
+static int mbox_show(struct seq_file *s, void *data)
+{
+	struct list_head *pos;
+	u8 mbox_index = 0;
+
+	list_for_each(pos, &mboxs) {
+		struct mbox *m =
+			(struct mbox *) list_entry(pos, struct mbox, list);
+		if (m == NULL) {
+			seq_printf(s,
+				   "Unable to retrieve mailbox %d\n",
+				   mbox_index);
+			continue;
+		}
+
+		spin_lock(&m->lock);
+		if ((m->virtbase_peer == NULL) || (m->virtbase_local == NULL)) {
+			seq_printf(s, "MAILBOX %d not setup or corrupt\n",
+				   mbox_index);
+			spin_unlock(&m->lock);
+			continue;
+		}
+
+		seq_printf(s,
+		"===========================\n"
+		" MAILBOX %d\n"
+		" PEER MAILBOX DUMP\n"
+		"---------------------------\n"
+		"FIFO:                 0x%X (%d)\n"
+		"Free     Threshold:   0x%.2X (%d)\n"
+		"Occupied Threshold:   0x%.2X (%d)\n"
+		"Status:               0x%.2X (%d)\n"
+		"   Free spaces  (ot):    %d (%d)\n"
+		"   Occup spaces (ot):    %d (%d)\n"
+		"===========================\n"
+		" LOCAL MAILBOX DUMP\n"
+		"---------------------------\n"
+		"FIFO:                 0x%.X (%d)\n"
+		"Free     Threshold:   0x%.2X (%d)\n"
+		"Occupied Threshold:   0x%.2X (%d)\n"
+		"Status:               0x%.2X (%d)\n"
+		"   Free spaces  (ot):    %d (%d)\n"
+		"   Occup spaces (ot):    %d (%d)\n"
+		"===========================\n"
+		"write_index: %d\n"
+		"read_index : %d\n"
+		"===========================\n"
+		"\n",
+		mbox_index,
+		readl(m->virtbase_peer + MBOX_FIFO_DATA),
+		readl(m->virtbase_peer + MBOX_FIFO_DATA),
+		readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
+		readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
+		readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
+		readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
+		readl(m->virtbase_peer + MBOX_FIFO_STATUS),
+		readl(m->virtbase_peer + MBOX_FIFO_STATUS),
+		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 4) & 0x7,
+		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 7) & 0x1,
+		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 0) & 0x7,
+		(readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 3) & 0x1,
+		readl(m->virtbase_local + MBOX_FIFO_DATA),
+		readl(m->virtbase_local + MBOX_FIFO_DATA),
+		readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
+		readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
+		readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
+		readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
+		readl(m->virtbase_local + MBOX_FIFO_STATUS),
+		readl(m->virtbase_local + MBOX_FIFO_STATUS),
+		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 4) & 0x7,
+		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 7) & 0x1,
+		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 0) & 0x7,
+		(readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 3) & 0x1,
+		m->write_index, m->read_index);
+		mbox_index++;
+		spin_unlock(&m->lock);
+	}
+
+	return 0;
+}
+
+static int mbox_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mbox_show, NULL);
+}
+
+static const struct file_operations mbox_operations = {
+	.owner = THIS_MODULE,
+	.open = mbox_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+#endif
+
+static irqreturn_t mbox_irq(int irq, void *arg)
+{
+	u32 mbox_value;
+	int nbr_occup;
+	int nbr_free;
+	struct mbox *mbox = (struct mbox *) arg;
+
+	spin_lock(&mbox->lock);
+
+	dev_dbg(&(mbox->pdev->dev),
+		"mbox IRQ [%d] received. ri = %d, wi = %d\n",
+		irq, mbox->read_index, mbox->write_index);
+
+	/*
+	 * Check if we have any outgoing messages, and if there is space for
+	 * them in the FIFO.
+	 */
+	if (mbox->read_index != mbox->write_index) {
+		/*
+		 * Check by reading FREE for LOCAL since that indicates
+		 * OCCUP for PEER
+		 */
+		nbr_free = (readl(mbox->virtbase_local + MBOX_FIFO_STATUS)
+			    >> 4) & 0x7;
+		dev_dbg(&(mbox->pdev->dev),
+			"Status indicates %d empty spaces in the FIFO!\n",
+			nbr_free);
+
+		while ((nbr_free > 0) &&
+		       (mbox->read_index != mbox->write_index)) {
+			/* Write the message and latch it into the FIFO */
+			writel(mbox->buffer[mbox->read_index],
+			       (mbox->virtbase_peer + MBOX_FIFO_DATA));
+			writel(MBOX_LATCH,
+			       (mbox->virtbase_peer + MBOX_FIFO_ADD));
+			dev_dbg(&(mbox->pdev->dev),
+				"Wrote message 0x%X to addr 0x%X\n",
+				mbox->buffer[mbox->read_index],
+				(u32) (mbox->virtbase_peer + MBOX_FIFO_DATA));
+
+			nbr_free--;
+			mbox->read_index =
+				(mbox->read_index + 1) % MBOX_BUF_SIZE;
+		}
+
+		/*
+		 * Check if we still want IRQ:s when there is free
+		 * space to send
+		 */
+		if (mbox->read_index != mbox->write_index) {
+			dev_dbg(&(mbox->pdev->dev),
+				"Still have messages to send, but FIFO full. "
+				"Request IRQ again!\n");
+			writel(MBOX_ENABLE_IRQ,
+			       mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+		} else {
+			dev_dbg(&(mbox->pdev->dev),
+				"No more messages to send. "
+				"Do not request IRQ again!\n");
+			writel(MBOX_DISABLE_IRQ,
+			       mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+		}
+
+		/*
+		 * Check if we can signal any blocked clients that it is OK to
+		 * start buffering again
+		 */
+		if (mbox->client_blocked &&
+		    (((mbox->write_index + 1) % MBOX_BUF_SIZE)
+		     != mbox->read_index)) {
+			dev_dbg(&(mbox->pdev->dev),
+				"Waking up blocked client\n");
+			complete(&mbox->buffer_available);
+			mbox->client_blocked = 0;
+		}
+	}
+
+	/* Check if we have any incoming messages */
+	nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7;
+	if (nbr_occup == 0)
+		goto exit;
+
+	if (mbox->cb == NULL) {
+		dev_dbg(&(mbox->pdev->dev), "No receive callback registered, "
+			"leaving %d incoming messages in fifo!\n", nbr_occup);
+		goto exit;
+	}
+
+	/* Read and acknowledge the message */
+	mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
+	writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
+
+	/* Notify consumer of new mailbox message */
+	dev_dbg(&(mbox->pdev->dev), "Calling callback for message 0x%X!\n",
+		mbox_value);
+	mbox->cb(mbox_value, mbox->client_data);
+
+exit:
+	dev_dbg(&(mbox->pdev->dev), "Exit mbox IRQ. ri = %d, wi = %d\n",
+		mbox->read_index, mbox->write_index);
+	spin_unlock(&mbox->lock);
+
+	return IRQ_HANDLED;
+}
+
+/* Setup is executed once for each mbox pair */
+struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv)
+{
+	struct resource *resource;
+	int irq;
+	int res;
+	struct mbox *mbox;
+
+	mbox = get_mbox_with_id(mbox_id);
+	if (mbox == NULL) {
+		dev_err(&(mbox->pdev->dev), "Incorrect mailbox id: %d!\n",
+			mbox_id);
+		goto exit;
+	}
+
+	/*
+	 * Check if mailbox has been allocated to someone else,
+	 * otherwise allocate it
+	 */
+	if (mbox->allocated) {
+		dev_err(&(mbox->pdev->dev), "Mailbox number %d is busy!\n",
+			mbox_id);
+		mbox = NULL;
+		goto exit;
+	}
+	mbox->allocated = true;
+
+	dev_dbg(&(mbox->pdev->dev), "Initiating mailbox number %d: 0x%X...\n",
+		mbox_id, (u32)mbox);
+
+	mbox->client_data = priv;
+	mbox->cb = mbox_cb;
+
+	/* Get addr for peer mailbox and ioremap it */
+	resource = platform_get_resource_byname(mbox->pdev,
+						IORESOURCE_MEM,
+						"mbox_peer");
+	if (resource == NULL) {
+		dev_err(&(mbox->pdev->dev),
+			"Unable to retrieve mbox peer resource\n");
+		mbox = NULL;
+		goto exit;
+	}
+	dev_dbg(&(mbox->pdev->dev),
+		"Resource name: %s start: 0x%X, end: 0x%X\n",
+		resource->name, resource->start, resource->end);
+	mbox->virtbase_peer =
+		ioremap(resource->start, resource->end - resource->start);
+	if (!mbox->virtbase_peer) {
+		dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n");
+		mbox = NULL;
+		goto exit;
+	}
+	dev_dbg(&(mbox->pdev->dev),
+		"ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n",
+		resource->start, resource->end, (u32) mbox->virtbase_peer);
+
+	/* Get addr for local mailbox and ioremap it */
+	resource = platform_get_resource_byname(mbox->pdev,
+						IORESOURCE_MEM,
+						"mbox_local");
+	if (resource == NULL) {
+		dev_err(&(mbox->pdev->dev),
+			"Unable to retrieve mbox local resource\n");
+		mbox = NULL;
+		goto exit;
+	}
+	dev_dbg(&(mbox->pdev->dev),
+		"Resource name: %s start: 0x%X, end: 0x%X\n",
+		resource->name, resource->start, resource->end);
+	mbox->virtbase_local =
+		ioremap(resource->start, resource->end - resource->start);
+	if (!mbox->virtbase_local) {
+		dev_err(&(mbox->pdev->dev), "Unable to ioremap local mbox\n");
+		mbox = NULL;
+		goto exit;
+	}
+	dev_dbg(&(mbox->pdev->dev),
+		"ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n",
+		resource->start, resource->end, (u32) mbox->virtbase_peer);
+
+	init_completion(&mbox->buffer_available);
+	mbox->client_blocked = 0;
+
+	/* Get IRQ for mailbox and allocate it */
+	irq = platform_get_irq_byname(mbox->pdev, "mbox_irq");
+	if (irq < 0) {
+		dev_err(&(mbox->pdev->dev),
+			"Unable to retrieve mbox irq resource\n");
+		mbox = NULL;
+		goto exit;
+	}
+
+	dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq);
+	res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox);
+	if (res < 0) {
+		dev_err(&(mbox->pdev->dev),
+			"Unable to allocate mbox irq %d\n", irq);
+		mbox = NULL;
+		goto exit;
+	}
+
+	/* Set up mailbox to not launch IRQ on free space in mailbox */
+	writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+
+	/*
+	 * Set up mailbox to launch IRQ on new message if we have
+	 * a callback set. If not, do not raise IRQ, but keep message
+	 * in FIFO for manual retrieval
+	 */
+	if (mbox_cb != NULL)
+		writel(MBOX_ENABLE_IRQ,
+		       mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
+	else
+		writel(MBOX_DISABLE_IRQ,
+		       mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
+
+#if defined(CONFIG_DEBUG_FS)
+	res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo);
+	if (res != 0)
+		dev_warn(&(mbox->pdev->dev),
+			 "Unable to create mbox sysfs entry");
+
+	(void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL,
+				   NULL, &mbox_operations);
+#endif
+
+	dev_info(&(mbox->pdev->dev),
+		 "Mailbox driver with index %d initated!\n", mbox_id);
+
+exit:
+	return mbox;
+}
+EXPORT_SYMBOL(mbox_setup);
+
+
+int __init mbox_probe(struct platform_device *pdev)
+{
+	struct mbox local_mbox;
+	struct mbox *mbox;
+	int res = 0;
+	dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev);
+
+	memset(&local_mbox, 0x0, sizeof(struct mbox));
+
+	/* Associate our mbox data with the platform device */
+	res = platform_device_add_data(pdev,
+				       (void *) &local_mbox,
+				       sizeof(struct mbox));
+	if (res != 0) {
+		dev_err(&(pdev->dev),
+			"Unable to allocate driver platform data!\n");
+		goto exit;
+	}
+
+	mbox = (struct mbox *) pdev->dev.platform_data;
+	mbox->pdev = pdev;
+	mbox->write_index = 0;
+	mbox->read_index = 0;
+
+	INIT_LIST_HEAD(&(mbox->list));
+	list_add_tail(&(mbox->list), &mboxs);
+
+	sprintf(mbox->name, "%s", MBOX_NAME);
+	spin_lock_init(&mbox->lock);
+
+	dev_info(&(pdev->dev), "Mailbox driver loaded\n");
+
+exit:
+	return res;
+}
+
+static struct platform_driver mbox_driver = {
+	.driver = {
+		.name = MBOX_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init mbox_init(void)
+{
+	return platform_driver_probe(&mbox_driver, mbox_probe);
+}
+
+module_init(mbox_init);
+
+void __exit mbox_exit(void)
+{
+	platform_driver_unregister(&mbox_driver);
+}
+
+module_exit(mbox_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MBOX driver");
diff --git a/arch/arm/mach-ux500/modem_irq.c b/arch/arm/mach-ux500/modem_irq.c
new file mode 100644
index 0000000..3187f88
--- /dev/null
+++ b/arch/arm/mach-ux500/modem_irq.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#define MODEM_INTCON_BASE_ADDR 0xBFFD3000
+#define MODEM_INTCON_SIZE 0xFFF
+
+#define DEST_IRQ41_OFFSET 0x2A4
+#define DEST_IRQ43_OFFSET 0x2AC
+#define DEST_IRQ45_OFFSET 0x2B4
+
+#define PRIO_IRQ41_OFFSET 0x6A4
+#define PRIO_IRQ43_OFFSET 0x6AC
+#define PRIO_IRQ45_OFFSET 0x6B4
+
+#define ALLOW_IRQ_OFFSET 0x104
+
+#define MODEM_INTCON_CPU_NBR 0x1
+#define MODEM_INTCON_PRIO_HIGH 0x0
+
+#define MODEM_INTCON_ALLOW_IRQ41 0x0200
+#define MODEM_INTCON_ALLOW_IRQ43 0x0800
+#define MODEM_INTCON_ALLOW_IRQ45 0x2000
+
+#define MODEM_IRQ_REG_OFFSET 0x4
+
+struct modem_irq {
+	void __iomem *modem_intcon_base;
+};
+
+
+static void setup_modem_intcon(void __iomem *modem_intcon_base)
+{
+	/* IC_DESTINATION_BASE_ARRAY - Which CPU to receive the IRQ */
+	writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ41_OFFSET);
+	writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ43_OFFSET);
+	writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ45_OFFSET);
+
+	/* IC_PRIORITY_BASE_ARRAY - IRQ priority in modem IRQ controller */
+	writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ41_OFFSET);
+	writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ43_OFFSET);
+	writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ45_OFFSET);
+
+	/* IC_ALLOW_ARRAY - IRQ enable */
+	writel(MODEM_INTCON_ALLOW_IRQ41 |
+		   MODEM_INTCON_ALLOW_IRQ43 |
+		   MODEM_INTCON_ALLOW_IRQ45,
+		   modem_intcon_base + ALLOW_IRQ_OFFSET);
+}
+
+static irqreturn_t modem_cpu_irq_handler(int irq, void *data)
+{
+	int real_irq;
+	int virt_irq;
+	struct modem_irq *mi = (struct modem_irq *)data;
+
+	/* Read modem side IRQ number from modem IRQ controller */
+	real_irq = readl(mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET) & 0xFF;
+	virt_irq = IRQ_MODEM_EVENTS_BASE + real_irq;
+
+	pr_debug("modem_irq: Worker read addr 0x%X and got value 0x%X "
+		 "which will be 0x%X (%d) which translates to "
+		 "virtual IRQ 0x%X (%d)!\n",
+		   (u32)mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET,
+		   real_irq,
+		   real_irq & 0xFF,
+		   real_irq & 0xFF,
+		   virt_irq,
+		   virt_irq);
+
+	if (virt_irq != 0)
+		generic_handle_irq(virt_irq);
+
+	pr_debug("modem_irq: Done handling virtual IRQ %d!\n", virt_irq);
+
+	return IRQ_HANDLED;
+}
+
+static void create_virtual_irq(int irq, struct irq_chip *modem_irq_chip)
+{
+	set_irq_chip(irq, modem_irq_chip);
+	set_irq_handler(irq, handle_simple_irq);
+	set_irq_flags(irq, IRQF_VALID);
+
+	pr_debug("modem_irq: Created virtual IRQ %d\n", irq);
+}
+
+static int modem_irq_init(void)
+{
+	int err;
+	static struct irq_chip  modem_irq_chip;
+	struct modem_irq *mi;
+
+	pr_info("modem_irq: Set up IRQ handler for incoming modem IRQ %d\n",
+		   IRQ_DB5500_MODEM);
+
+	mi = kmalloc(sizeof(struct modem_irq), GFP_KERNEL);
+	if (!mi) {
+		pr_err("modem_irq: Could not allocate device\n");
+		return -ENOMEM;
+	}
+
+	mi->modem_intcon_base =
+		ioremap(MODEM_INTCON_BASE_ADDR, MODEM_INTCON_SIZE);
+	pr_debug("modem_irq: ioremapped modem_intcon_base from "
+		 "phy 0x%x to virt 0x%x\n", MODEM_INTCON_BASE_ADDR,
+		 (u32)mi->modem_intcon_base);
+
+	setup_modem_intcon(mi->modem_intcon_base);
+
+	modem_irq_chip = dummy_irq_chip;
+	modem_irq_chip.name = "modem_irq";
+
+	/* Create the virtual IRQ:s needed */
+	create_virtual_irq(MBOX_PAIR0_VIRT_IRQ, &modem_irq_chip);
+	create_virtual_irq(MBOX_PAIR1_VIRT_IRQ, &modem_irq_chip);
+	create_virtual_irq(MBOX_PAIR2_VIRT_IRQ, &modem_irq_chip);
+
+	err = request_threaded_irq(IRQ_DB5500_MODEM, NULL,
+				   modem_cpu_irq_handler, IRQF_ONESHOT,
+				   "modem_irq", mi);
+	if (err)
+		pr_err("modem_irq: Could not register IRQ %d\n",
+		       IRQ_DB5500_MODEM);
+
+	return 0;
+}
+
+arch_initcall(modem_irq_init);
diff --git a/arch/arm/mach-ux500/pins-db5500.h b/arch/arm/mach-ux500/pins-db5500.h
new file mode 100644
index 0000000..bf50c21
--- /dev/null
+++ b/arch/arm/mach-ux500/pins-db5500.h
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License, version 2
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com>
+ */
+
+#ifndef __MACH_DB5500_PINS_H
+#define __MACH_DB5500_PINS_H
+
+#define GPIO0_GPIO		PIN_CFG(0, GPIO)
+#define GPIO0_SM_CS3n		PIN_CFG(0, ALT_A)
+
+#define GPIO1_GPIO		PIN_CFG(1, GPIO)
+#define GPIO1_SM_A3		PIN_CFG(1, ALT_A)
+
+#define GPIO2_GPIO		PIN_CFG(2, GPIO)
+#define GPIO2_SM_A4		PIN_CFG(2, ALT_A)
+#define GPIO2_SM_AVD		PIN_CFG(2, ALT_B)
+
+#define GPIO3_GPIO		PIN_CFG(3, GPIO)
+#define GPIO3_I2C1_SCL		PIN_CFG(3, ALT_A)
+
+#define GPIO4_GPIO		PIN_CFG(4, GPIO)
+#define GPIO4_I2C1_SDA		PIN_CFG(4, ALT_A)
+
+#define GPIO5_GPIO		PIN_CFG(5, GPIO)
+#define GPIO5_MC0_DAT0		PIN_CFG(5, ALT_A)
+#define GPIO5_SM_ADQ8		PIN_CFG(5, ALT_B)
+
+#define GPIO6_GPIO		PIN_CFG(6, GPIO)
+#define GPIO6_MC0_DAT1		PIN_CFG(6, ALT_A)
+#define GPIO6_SM_ADQ0		PIN_CFG(6, ALT_B)
+
+#define GPIO7_GPIO		PIN_CFG(7, GPIO)
+#define GPIO7_MC0_DAT2		PIN_CFG(7, ALT_A)
+#define GPIO7_SM_ADQ9		PIN_CFG(7, ALT_B)
+
+#define GPIO8_GPIO		PIN_CFG(8, GPIO)
+#define GPIO8_MC0_DAT3		PIN_CFG(8, ALT_A)
+#define GPIO8_SM_ADQ1		PIN_CFG(8, ALT_B)
+
+#define GPIO9_GPIO		PIN_CFG(9, GPIO)
+#define GPIO9_MC0_DAT4		PIN_CFG(9, ALT_A)
+#define GPIO9_SM_ADQ10		PIN_CFG(9, ALT_B)
+
+#define GPIO10_GPIO		PIN_CFG(10, GPIO)
+#define GPIO10_MC0_DAT5		PIN_CFG(10, ALT_A)
+#define GPIO10_SM_ADQ2		PIN_CFG(10, ALT_B)
+
+#define GPIO11_GPIO		PIN_CFG(11, GPIO)
+#define GPIO11_MC0_DAT6		PIN_CFG(11, ALT_A)
+#define GPIO11_SM_ADQ11		PIN_CFG(11, ALT_B)
+
+#define GPIO12_GPIO		PIN_CFG(12, GPIO)
+#define GPIO12_MC0_DAT7		PIN_CFG(12, ALT_A)
+#define GPIO12_SM_ADQ3		PIN_CFG(12, ALT_B)
+
+#define GPIO13_GPIO		PIN_CFG(13, GPIO)
+#define GPIO13_MC0_CMD		PIN_CFG(13, ALT_A)
+#define GPIO13_SM_BUSY0n	PIN_CFG(13, ALT_B)
+#define GPIO13_SM_WAIT0n	PIN_CFG(13, ALT_C)
+
+#define GPIO14_GPIO		PIN_CFG(14, GPIO)
+#define GPIO14_MC0_CLK		PIN_CFG(14, ALT_A)
+#define GPIO14_SM_CS1n		PIN_CFG(14, ALT_B)
+#define GPIO14_SM_CKO		PIN_CFG(14, ALT_C)
+
+#define GPIO15_GPIO		PIN_CFG(15, GPIO)
+#define GPIO15_SM_A5		PIN_CFG(15, ALT_A)
+#define GPIO15_SM_CLE		PIN_CFG(15, ALT_B)
+
+#define GPIO16_GPIO		PIN_CFG(16, GPIO)
+#define GPIO16_MC2_CMD		PIN_CFG(16, ALT_A)
+#define GPIO16_SM_OEn		PIN_CFG(16, ALT_B)
+
+#define GPIO17_GPIO		PIN_CFG(17, GPIO)
+#define GPIO17_MC2_CLK		PIN_CFG(17, ALT_A)
+#define GPIO17_SM_WEn		PIN_CFG(17, ALT_B)
+
+#define GPIO18_GPIO		PIN_CFG(18, GPIO)
+#define GPIO18_SM_A6		PIN_CFG(18, ALT_A)
+#define GPIO18_SM_ALE		PIN_CFG(18, ALT_B)
+#define GPIO18_SM_AVDn		PIN_CFG(18, ALT_C)
+
+#define GPIO19_GPIO		PIN_CFG(19, GPIO)
+#define GPIO19_MC2_DAT1		PIN_CFG(19, ALT_A)
+#define GPIO19_SM_ADQ4		PIN_CFG(19, ALT_B)
+
+#define GPIO20_GPIO		PIN_CFG(20, GPIO)
+#define GPIO20_MC2_DAT3		PIN_CFG(20, ALT_A)
+#define GPIO20_SM_ADQ5		PIN_CFG(20, ALT_B)
+
+#define GPIO21_GPIO		PIN_CFG(21, GPIO)
+#define GPIO21_MC2_DAT5		PIN_CFG(21, ALT_A)
+#define GPIO21_SM_ADQ6		PIN_CFG(21, ALT_B)
+
+#define GPIO22_GPIO		PIN_CFG(22, GPIO)
+#define GPIO22_MC2_DAT7		PIN_CFG(22, ALT_A)
+#define GPIO22_SM_ADQ7		PIN_CFG(22, ALT_B)
+
+#define GPIO23_GPIO		PIN_CFG(23, GPIO)
+#define GPIO23_MC2_DAT0		PIN_CFG(23, ALT_A)
+#define GPIO23_SM_ADQ12		PIN_CFG(23, ALT_B)
+#define GPIO23_MC0_DAT1		PIN_CFG(23, ALT_C)
+
+#define GPIO24_GPIO		PIN_CFG(24, GPIO)
+#define GPIO24_MC2_DAT2		PIN_CFG(24, ALT_A)
+#define GPIO24_SM_ADQ13		PIN_CFG(24, ALT_B)
+#define GPIO24_MC0_DAT3		PIN_CFG(24, ALT_C)
+
+#define GPIO25_GPIO		PIN_CFG(25, GPIO)
+#define GPIO25_MC2_DAT4		PIN_CFG(25, ALT_A)
+#define GPIO25_SM_ADQ14		PIN_CFG(25, ALT_B)
+#define GPIO25_MC0_CMD		PIN_CFG(25, ALT_C)
+
+#define GPIO26_GPIO		PIN_CFG(26, GPIO)
+#define GPIO26_MC2_DAT6		PIN_CFG(26, ALT_A)
+#define GPIO26_SM_ADQ15		PIN_CFG(26, ALT_B)
+
+#define GPIO27_GPIO		PIN_CFG(27, GPIO)
+#define GPIO27_SM_CS0n		PIN_CFG(27, ALT_A)
+#define GPIO27_SM_PS0n		PIN_CFG(27, ALT_B)
+
+#define GPIO28_GPIO		PIN_CFG(28, GPIO)
+#define GPIO28_U0_TXD		PIN_CFG(28, ALT_A)
+#define GPIO28_SM_A0		PIN_CFG(28, ALT_B)
+
+#define GPIO29_GPIO		PIN_CFG(29, GPIO)
+#define GPIO29_U0_RXD		PIN_CFG(29, ALT_A)
+#define GPIO29_SM_A1		PIN_CFG(29, ALT_B)
+#define GPIO29_PWM_0		PIN_CFG(29, ALT_C)
+
+#define GPIO30_GPIO		PIN_CFG(30, GPIO)
+#define GPIO30_MC0_DAT5		PIN_CFG(30, ALT_A)
+#define GPIO30_SM_A2		PIN_CFG(30, ALT_B)
+#define GPIO30_PWM_1		PIN_CFG(30, ALT_C)
+
+#define GPIO31_GPIO		PIN_CFG(31, GPIO)
+#define GPIO31_MC0_DAT7		PIN_CFG(31, ALT_A)
+#define GPIO31_SM_CS2n		PIN_CFG(31, ALT_B)
+#define GPIO31_PWM_2		PIN_CFG(31, ALT_C)
+
+#define GPIO32_GPIO		PIN_CFG(32, GPIO)
+#define GPIO32_MSP0_TCK		PIN_CFG(32, ALT_A)
+#define GPIO32_ACCI2S0_SCK	PIN_CFG(32, ALT_B)
+
+#define GPIO33_GPIO		PIN_CFG(33, GPIO)
+#define GPIO33_MSP0_TFS		PIN_CFG(33, ALT_A)
+#define GPIO33_ACCI2S0_WS	PIN_CFG(33, ALT_B)
+
+#define GPIO34_GPIO		PIN_CFG(34, GPIO)
+#define GPIO34_MSP0_TXD		PIN_CFG(34, ALT_A)
+#define GPIO34_ACCI2S0_DLD	PIN_CFG(34, ALT_B)
+
+#define GPIO35_GPIO		PIN_CFG(35, GPIO)
+#define GPIO35_MSP0_RXD		PIN_CFG(35, ALT_A)
+#define GPIO35_ACCI2S0_ULD	PIN_CFG(35, ALT_B)
+
+#define GPIO64_GPIO		PIN_CFG(64, GPIO)
+#define GPIO64_USB_DAT0		PIN_CFG(64, ALT_A)
+#define GPIO64_U0_TXD		PIN_CFG(64, ALT_B)
+
+#define GPIO65_GPIO		PIN_CFG(65, GPIO)
+#define GPIO65_USB_DAT1		PIN_CFG(65, ALT_A)
+#define GPIO65_U0_RXD		PIN_CFG(65, ALT_B)
+
+#define GPIO66_GPIO		PIN_CFG(66, GPIO)
+#define GPIO66_USB_DAT2		PIN_CFG(66, ALT_A)
+
+#define GPIO67_GPIO		PIN_CFG(67, GPIO)
+#define GPIO67_USB_DAT3		PIN_CFG(67, ALT_A)
+
+#define GPIO68_GPIO		PIN_CFG(68, GPIO)
+#define GPIO68_USB_DAT4		PIN_CFG(68, ALT_A)
+
+#define GPIO69_GPIO		PIN_CFG(69, GPIO)
+#define GPIO69_USB_DAT5		PIN_CFG(69, ALT_A)
+
+#define GPIO70_GPIO		PIN_CFG(70, GPIO)
+#define GPIO70_USB_DAT6		PIN_CFG(70, ALT_A)
+
+#define GPIO71_GPIO		PIN_CFG(71, GPIO)
+#define GPIO71_USB_DAT7		PIN_CFG(71, ALT_A)
+
+#define GPIO72_GPIO		PIN_CFG(72, GPIO)
+#define GPIO72_USB_STP		PIN_CFG(72, ALT_A)
+
+#define GPIO73_GPIO		PIN_CFG(73, GPIO)
+#define GPIO73_USB_DIR		PIN_CFG(73, ALT_A)
+
+#define GPIO74_GPIO		PIN_CFG(74, GPIO)
+#define GPIO74_USB_NXT		PIN_CFG(74, ALT_A)
+
+#define GPIO75_GPIO		PIN_CFG(75, GPIO)
+#define GPIO75_USB_XCLK		PIN_CFG(75, ALT_A)
+
+#define GPIO76_GPIO		PIN_CFG(76, GPIO)
+
+#define GPIO77_GPIO		PIN_CFG(77, GPIO)
+#define GPIO77_ACCTX_ON		PIN_CFG(77, ALT_A)
+
+#define GPIO78_GPIO		PIN_CFG(78, GPIO)
+#define GPIO78_IRQn		PIN_CFG(78, ALT_A)
+
+#define GPIO79_GPIO		PIN_CFG(79, GPIO)
+#define GPIO79_ACCSIM_Clk	PIN_CFG(79, ALT_A)
+
+#define GPIO80_GPIO		PIN_CFG(80, GPIO)
+#define GPIO80_ACCSIM_Da	PIN_CFG(80, ALT_A)
+
+#define GPIO81_GPIO		PIN_CFG(81, GPIO)
+#define GPIO81_ACCSIM_Reset	PIN_CFG(81, ALT_A)
+
+#define GPIO82_GPIO		PIN_CFG(82, GPIO)
+#define GPIO82_ACCSIM_DDir	PIN_CFG(82, ALT_A)
+
+#define GPIO96_GPIO		PIN_CFG(96, GPIO)
+#define GPIO96_MSP1_TCK		PIN_CFG(96, ALT_A)
+#define GPIO96_PRCMU_DEBUG3	PIN_CFG(96, ALT_B)
+#define GPIO96_PRCMU_DEBUG7	PIN_CFG(96, ALT_C)
+
+#define GPIO97_GPIO		PIN_CFG(97, GPIO)
+#define GPIO97_MSP1_TFS		PIN_CFG(97, ALT_A)
+#define GPIO97_PRCMU_DEBUG2	PIN_CFG(97, ALT_B)
+#define GPIO97_PRCMU_DEBUG6	PIN_CFG(97, ALT_C)
+
+#define GPIO98_GPIO		PIN_CFG(98, GPIO)
+#define GPIO98_MSP1_TXD		PIN_CFG(98, ALT_A)
+#define GPIO98_PRCMU_DEBUG1	PIN_CFG(98, ALT_B)
+#define GPIO98_PRCMU_DEBUG5	PIN_CFG(98, ALT_C)
+
+#define GPIO99_GPIO		PIN_CFG(99, GPIO)
+#define GPIO99_MSP1_RXD		PIN_CFG(99, ALT_A)
+#define GPIO99_PRCMU_DEBUG0	PIN_CFG(99, ALT_B)
+#define GPIO99_PRCMU_DEBUG4	PIN_CFG(99, ALT_C)
+
+#define GPIO100_GPIO		PIN_CFG(100, GPIO)
+#define GPIO100_I2C0_SCL	PIN_CFG(100, ALT_A)
+
+#define GPIO101_GPIO		PIN_CFG(101, GPIO)
+#define GPIO101_I2C0_SDA	PIN_CFG(101, ALT_A)
+
+#define GPIO128_GPIO		PIN_CFG(128, GPIO)
+#define GPIO128_KP_I0		PIN_CFG(128, ALT_A)
+#define GPIO128_BUSMON_D0	PIN_CFG(128, ALT_B)
+
+#define GPIO129_GPIO		PIN_CFG(129, GPIO)
+#define GPIO129_KP_O0		PIN_CFG(129, ALT_A)
+#define GPIO129_BUSMON_D1	PIN_CFG(129, ALT_B)
+
+#define GPIO130_GPIO		PIN_CFG(130, GPIO)
+#define GPIO130_KP_I1		PIN_CFG(130, ALT_A)
+#define GPIO130_BUSMON_D2	PIN_CFG(130, ALT_B)
+
+#define GPIO131_GPIO		PIN_CFG(131, GPIO)
+#define GPIO131_KP_O1		PIN_CFG(131, ALT_A)
+#define GPIO131_BUSMON_D3	PIN_CFG(131, ALT_B)
+
+#define GPIO132_GPIO		PIN_CFG(132, GPIO)
+#define GPIO132_KP_I2		PIN_CFG(132, ALT_A)
+#define GPIO132_ETM_D15		PIN_CFG(132, ALT_B)
+#define GPIO132_STMAPE_CLK	PIN_CFG(132, ALT_C)
+
+#define GPIO133_GPIO		PIN_CFG(133, GPIO)
+#define GPIO133_KP_O2		PIN_CFG(133, ALT_A)
+#define GPIO133_ETM_D14		PIN_CFG(133, ALT_B)
+#define GPIO133_U0_RXD		PIN_CFG(133, ALT_C)
+
+#define GPIO134_GPIO		PIN_CFG(134, GPIO)
+#define GPIO134_KP_I3		PIN_CFG(134, ALT_A)
+#define GPIO134_ETM_D13		PIN_CFG(134, ALT_B)
+#define GPIO134_STMAPE_DAT0	PIN_CFG(134, ALT_C)
+
+#define GPIO135_GPIO		PIN_CFG(135, GPIO)
+#define GPIO135_KP_O3		PIN_CFG(135, ALT_A)
+#define GPIO135_ETM_D12		PIN_CFG(135, ALT_B)
+#define GPIO135_STMAPE_DAT1	PIN_CFG(135, ALT_C)
+
+#define GPIO136_GPIO		PIN_CFG(136, GPIO)
+#define GPIO136_KP_I4		PIN_CFG(136, ALT_A)
+#define GPIO136_ETM_D11		PIN_CFG(136, ALT_B)
+#define GPIO136_STMAPE_DAT2	PIN_CFG(136, ALT_C)
+
+#define GPIO137_GPIO		PIN_CFG(137, GPIO)
+#define GPIO137_KP_O4		PIN_CFG(137, ALT_A)
+#define GPIO137_ETM_D10		PIN_CFG(137, ALT_B)
+#define GPIO137_STMAPE_DAT3	PIN_CFG(137, ALT_C)
+
+#define GPIO138_GPIO		PIN_CFG(138, GPIO)
+#define GPIO138_KP_I5		PIN_CFG(138, ALT_A)
+#define GPIO138_ETM_D9		PIN_CFG(138, ALT_B)
+#define GPIO138_U0_TXD		PIN_CFG(138, ALT_C)
+
+#define GPIO139_GPIO		PIN_CFG(139, GPIO)
+#define GPIO139_KP_O5		PIN_CFG(139, ALT_A)
+#define GPIO139_ETM_D8		PIN_CFG(139, ALT_B)
+#define GPIO139_BUSMON_D11	PIN_CFG(139, ALT_C)
+
+#define GPIO140_GPIO		PIN_CFG(140, GPIO)
+#define GPIO140_KP_I6		PIN_CFG(140, ALT_A)
+#define GPIO140_ETM_D7		PIN_CFG(140, ALT_B)
+#define GPIO140_STMAPE_CLK	PIN_CFG(140, ALT_C)
+
+#define GPIO141_GPIO		PIN_CFG(141, GPIO)
+#define GPIO141_KP_O6		PIN_CFG(141, ALT_A)
+#define GPIO141_ETM_D6		PIN_CFG(141, ALT_B)
+#define GPIO141_U0_RXD		PIN_CFG(141, ALT_C)
+
+#define GPIO142_GPIO		PIN_CFG(142, GPIO)
+#define GPIO142_KP_I7		PIN_CFG(142, ALT_A)
+#define GPIO142_ETM_D5		PIN_CFG(142, ALT_B)
+#define GPIO142_STMAPE_DAT0	PIN_CFG(142, ALT_C)
+
+#define GPIO143_GPIO		PIN_CFG(143, GPIO)
+#define GPIO143_KP_O7		PIN_CFG(143, ALT_A)
+#define GPIO143_ETM_D4		PIN_CFG(143, ALT_B)
+#define GPIO143_STMAPE_DAT1	PIN_CFG(143, ALT_C)
+
+#define GPIO144_GPIO		PIN_CFG(144, GPIO)
+#define GPIO144_I2C3_SCL	PIN_CFG(144, ALT_A)
+#define GPIO144_ETM_D3		PIN_CFG(144, ALT_B)
+#define GPIO144_STMAPE_DAT2	PIN_CFG(144, ALT_C)
+
+#define GPIO145_GPIO		PIN_CFG(145, GPIO)
+#define GPIO145_I2C3_SDA	PIN_CFG(145, ALT_A)
+#define GPIO145_ETM_D2		PIN_CFG(145, ALT_B)
+#define GPIO145_STMAPE_DAT3	PIN_CFG(145, ALT_C)
+
+#define GPIO146_GPIO		PIN_CFG(146, GPIO)
+#define GPIO146_PWM_0		PIN_CFG(146, ALT_A)
+#define GPIO146_ETM_D1		PIN_CFG(146, ALT_B)
+
+#define GPIO147_GPIO		PIN_CFG(147, GPIO)
+#define GPIO147_PWM_1		PIN_CFG(147, ALT_A)
+#define GPIO147_ETM_D0		PIN_CFG(147, ALT_B)
+
+#define GPIO148_GPIO		PIN_CFG(148, GPIO)
+#define GPIO148_PWM_2		PIN_CFG(148, ALT_A)
+#define GPIO148_ETM_CLK		PIN_CFG(148, ALT_B)
+
+#define GPIO160_GPIO		PIN_CFG(160, GPIO)
+#define GPIO160_CLKOUT_REQn	PIN_CFG(160, ALT_A)
+
+#define GPIO161_GPIO		PIN_CFG(161, GPIO)
+#define GPIO161_CLKOUT_0	PIN_CFG(161, ALT_A)
+
+#define GPIO162_GPIO		PIN_CFG(162, GPIO)
+#define GPIO162_CLKOUT_1	PIN_CFG(162, ALT_A)
+
+#define GPIO163_GPIO		PIN_CFG(163, GPIO)
+
+#define GPIO164_GPIO		PIN_CFG(164, GPIO)
+#define GPIO164_GPS_START	PIN_CFG(164, ALT_A)
+
+#define GPIO165_GPIO		PIN_CFG(165, GPIO)
+#define GPIO165_SPI1_CS2n	PIN_CFG(165, ALT_A)
+#define GPIO165_U3_RXD		PIN_CFG(165, ALT_B)
+#define GPIO165_BUSMON_D20	PIN_CFG(165, ALT_C)
+
+#define GPIO166_GPIO		PIN_CFG(166, GPIO)
+#define GPIO166_SPI1_CS1n	PIN_CFG(166, ALT_A)
+#define GPIO166_U3_TXD		PIN_CFG(166, ALT_B)
+#define GPIO166_BUSMON_D21	PIN_CFG(166, ALT_C)
+
+#define GPIO167_GPIO		PIN_CFG(167, GPIO)
+#define GPIO167_SPI1_CS0n	PIN_CFG(167, ALT_A)
+#define GPIO167_U3_RTSn		PIN_CFG(167, ALT_B)
+#define GPIO167_BUSMON_D22	PIN_CFG(167, ALT_C)
+
+#define GPIO168_GPIO		PIN_CFG(168, GPIO)
+#define GPIO168_SPI1_RXD	PIN_CFG(168, ALT_A)
+#define GPIO168_U3_CTSn		PIN_CFG(168, ALT_B)
+#define GPIO168_BUSMON_D23	PIN_CFG(168, ALT_C)
+
+#define GPIO169_GPIO		PIN_CFG(169, GPIO)
+#define GPIO169_SPI1_TXD	PIN_CFG(169, ALT_A)
+#define GPIO169_DDR_RC		PIN_CFG(169, ALT_B)
+#define GPIO169_BUSMON_D24	PIN_CFG(169, ALT_C)
+
+#define GPIO170_GPIO		PIN_CFG(170, GPIO)
+#define GPIO170_SPI1_CLK	PIN_CFG(170, ALT_A)
+
+#define GPIO171_GPIO		PIN_CFG(171, GPIO)
+#define GPIO171_MC3_DAT0	PIN_CFG(171, ALT_A)
+#define GPIO171_SPI3_RXD	PIN_CFG(171, ALT_B)
+#define GPIO171_BUSMON_D25	PIN_CFG(171, ALT_C)
+
+#define GPIO172_GPIO		PIN_CFG(172, GPIO)
+#define GPIO172_MC3_DAT1	PIN_CFG(172, ALT_A)
+#define GPIO172_SPI3_CS1n	PIN_CFG(172, ALT_B)
+#define GPIO172_BUSMON_D26	PIN_CFG(172, ALT_C)
+
+#define GPIO173_GPIO		PIN_CFG(173, GPIO)
+#define GPIO173_MC3_DAT2	PIN_CFG(173, ALT_A)
+#define GPIO173_SPI3_CS2n	PIN_CFG(173, ALT_B)
+#define GPIO173_BUSMON_D27	PIN_CFG(173, ALT_C)
+
+#define GPIO174_GPIO		PIN_CFG(174, GPIO)
+#define GPIO174_MC3_DAT3	PIN_CFG(174, ALT_A)
+#define GPIO174_SPI3_CS0n	PIN_CFG(174, ALT_B)
+#define GPIO174_BUSMON_D28	PIN_CFG(174, ALT_C)
+
+#define GPIO175_GPIO		PIN_CFG(175, GPIO)
+#define GPIO175_MC3_CMD		PIN_CFG(175, ALT_A)
+#define GPIO175_SPI3_TXD	PIN_CFG(175, ALT_B)
+#define GPIO175_BUSMON_D29	PIN_CFG(175, ALT_C)
+
+#define GPIO176_GPIO		PIN_CFG(176, GPIO)
+#define GPIO176_MC3_CLK		PIN_CFG(176, ALT_A)
+#define GPIO176_SPI3_CLK	PIN_CFG(176, ALT_B)
+
+#define GPIO177_GPIO		PIN_CFG(177, GPIO)
+#define GPIO177_U2_RXD		PIN_CFG(177, ALT_A)
+#define GPIO177_I2C3_SCL	PIN_CFG(177, ALT_B)
+#define GPIO177_BUSMON_D30	PIN_CFG(177, ALT_C)
+
+#define GPIO178_GPIO		PIN_CFG(178, GPIO)
+#define GPIO178_U2_TXD		PIN_CFG(178, ALT_A)
+#define GPIO178_I2C3_SDA	PIN_CFG(178, ALT_B)
+#define GPIO178_BUSMON_D31	PIN_CFG(178, ALT_C)
+
+#define GPIO179_GPIO		PIN_CFG(179, GPIO)
+#define GPIO179_U2_CTSn		PIN_CFG(179, ALT_A)
+#define GPIO179_U3_RXD		PIN_CFG(179, ALT_B)
+#define GPIO179_BUSMON_D32	PIN_CFG(179, ALT_C)
+
+#define GPIO180_GPIO		PIN_CFG(180, GPIO)
+#define GPIO180_U2_RTSn		PIN_CFG(180, ALT_A)
+#define GPIO180_U3_TXD		PIN_CFG(180, ALT_B)
+#define GPIO180_BUSMON_D33	PIN_CFG(180, ALT_C)
+
+#define GPIO185_GPIO		PIN_CFG(185, GPIO)
+#define GPIO185_SPI3_CS2n	PIN_CFG(185, ALT_A)
+#define GPIO185_MC4_DAT0	PIN_CFG(185, ALT_B)
+
+#define GPIO186_GPIO		PIN_CFG(186, GPIO)
+#define GPIO186_SPI3_CS1n	PIN_CFG(186, ALT_A)
+#define GPIO186_MC4_DAT1	PIN_CFG(186, ALT_B)
+
+#define GPIO187_GPIO		PIN_CFG(187, GPIO)
+#define GPIO187_SPI3_CS0n	PIN_CFG(187, ALT_A)
+#define GPIO187_MC4_DAT2	PIN_CFG(187, ALT_B)
+
+#define GPIO188_GPIO		PIN_CFG(188, GPIO)
+#define GPIO188_SPI3_RXD	PIN_CFG(188, ALT_A)
+#define GPIO188_MC4_DAT3	PIN_CFG(188, ALT_B)
+
+#define GPIO189_GPIO		PIN_CFG(189, GPIO)
+#define GPIO189_SPI3_TXD	PIN_CFG(189, ALT_A)
+#define GPIO189_MC4_CMD		PIN_CFG(189, ALT_B)
+
+#define GPIO190_GPIO		PIN_CFG(190, GPIO)
+#define GPIO190_SPI3_CLK	PIN_CFG(190, ALT_A)
+#define GPIO190_MC4_CLK		PIN_CFG(190, ALT_B)
+
+#define GPIO191_GPIO		PIN_CFG(191, GPIO)
+#define GPIO191_MC1_DAT0	PIN_CFG(191, ALT_A)
+#define GPIO191_MC4_DAT4	PIN_CFG(191, ALT_B)
+#define GPIO191_STMAPE_DAT0	PIN_CFG(191, ALT_C)
+
+#define GPIO192_GPIO		PIN_CFG(192, GPIO)
+#define GPIO192_MC1_DAT1	PIN_CFG(192, ALT_A)
+#define GPIO192_MC4_DAT5	PIN_CFG(192, ALT_B)
+#define GPIO192_STMAPE_DAT1	PIN_CFG(192, ALT_C)
+
+#define GPIO193_GPIO		PIN_CFG(193, GPIO)
+#define GPIO193_MC1_DAT2	PIN_CFG(193, ALT_A)
+#define GPIO193_MC4_DAT6	PIN_CFG(193, ALT_B)
+#define GPIO193_STMAPE_DAT2	PIN_CFG(193, ALT_C)
+
+#define GPIO194_GPIO		PIN_CFG(194, GPIO)
+#define GPIO194_MC1_DAT3	PIN_CFG(194, ALT_A)
+#define GPIO194_MC4_DAT7	PIN_CFG(194, ALT_B)
+#define GPIO194_STMAPE_DAT3	PIN_CFG(194, ALT_C)
+
+#define GPIO195_GPIO		PIN_CFG(195, GPIO)
+#define GPIO195_MC1_CLK		PIN_CFG(195, ALT_A)
+#define GPIO195_STMAPE_CLK	PIN_CFG(195, ALT_B)
+#define GPIO195_BUSMON_CLK	PIN_CFG(195, ALT_C)
+
+#define GPIO196_GPIO		PIN_CFG(196, GPIO)
+#define GPIO196_MC1_CMD		PIN_CFG(196, ALT_A)
+#define GPIO196_U0_RXD		PIN_CFG(196, ALT_B)
+#define GPIO196_BUSMON_D38	PIN_CFG(196, ALT_C)
+
+#define GPIO197_GPIO		PIN_CFG(197, GPIO)
+#define GPIO197_MC1_CMDDIR	PIN_CFG(197, ALT_A)
+#define GPIO197_BUSMON_D39	PIN_CFG(197, ALT_B)
+
+#define GPIO198_GPIO		PIN_CFG(198, GPIO)
+#define GPIO198_MC1_FBCLK	PIN_CFG(198, ALT_A)
+
+#define GPIO199_GPIO		PIN_CFG(199, GPIO)
+#define GPIO199_MC1_DAT0DIR	PIN_CFG(199, ALT_A)
+#define GPIO199_BUSMON_D40	PIN_CFG(199, ALT_B)
+
+#define GPIO200_GPIO		PIN_CFG(200, GPIO)
+#define GPIO200_U1_TXD		PIN_CFG(200, ALT_A)
+#define GPIO200_ACCU0_RTSn	PIN_CFG(200, ALT_B)
+
+#define GPIO201_GPIO		PIN_CFG(201, GPIO)
+#define GPIO201_U1_RXD		PIN_CFG(201, ALT_A)
+#define GPIO201_ACCU0_CTSn	PIN_CFG(201, ALT_B)
+
+#define GPIO202_GPIO		PIN_CFG(202, GPIO)
+#define GPIO202_U1_CTSn		PIN_CFG(202, ALT_A)
+#define GPIO202_ACCU0_RXD	PIN_CFG(202, ALT_B)
+
+#define GPIO203_GPIO		PIN_CFG(203, GPIO)
+#define GPIO203_U1_RTSn		PIN_CFG(203, ALT_A)
+#define GPIO203_ACCU0_TXD	PIN_CFG(203, ALT_B)
+
+#define GPIO204_GPIO		PIN_CFG(204, GPIO)
+#define GPIO204_SPI0_CS2n	PIN_CFG(204, ALT_A)
+#define GPIO204_ACCGPIO_000	PIN_CFG(204, ALT_B)
+#define GPIO204_LCD_VSI1	PIN_CFG(204, ALT_C)
+
+#define GPIO205_GPIO		PIN_CFG(205, GPIO)
+#define GPIO205_SPI0_CS1n	PIN_CFG(205, ALT_A)
+#define GPIO205_ACCGPIO_001	PIN_CFG(205, ALT_B)
+#define GPIO205_LCD_D3		PIN_CFG(205, ALT_C)
+
+#define GPIO206_GPIO		PIN_CFG(206, GPIO)
+#define GPIO206_SPI0_CS0n	PIN_CFG(206, ALT_A)
+#define GPIO206_ACCGPIO_002	PIN_CFG(206, ALT_B)
+#define GPIO206_LCD_D2		PIN_CFG(206, ALT_C)
+
+#define GPIO207_GPIO		PIN_CFG(207, GPIO)
+#define GPIO207_SPI0_RXD	PIN_CFG(207, ALT_A)
+#define GPIO207_ACCGPIO_003	PIN_CFG(207, ALT_B)
+#define GPIO207_LCD_D1		PIN_CFG(207, ALT_C)
+
+#define GPIO208_GPIO		PIN_CFG(208, GPIO)
+#define GPIO208_SPI0_TXD	PIN_CFG(208, ALT_A)
+#define GPIO208_ACCGPIO_004	PIN_CFG(208, ALT_B)
+#define GPIO208_LCD_D0		PIN_CFG(208, ALT_C)
+
+#define GPIO209_GPIO		PIN_CFG(209, GPIO)
+#define GPIO209_SPI0_CLK	PIN_CFG(209, ALT_A)
+#define GPIO209_ACCGPIO_005	PIN_CFG(209, ALT_B)
+#define GPIO209_LCD_CLK		PIN_CFG(209, ALT_C)
+
+#define GPIO210_GPIO		PIN_CFG(210, GPIO)
+#define GPIO210_LCD_VSO		PIN_CFG(210, ALT_A)
+#define GPIO210_PRCMU_PWRCTRL1	PIN_CFG(210, ALT_B)
+
+#define GPIO211_GPIO		PIN_CFG(211, GPIO)
+#define GPIO211_LCD_VSI0	PIN_CFG(211, ALT_A)
+#define GPIO211_PRCMU_PWRCTRL2	PIN_CFG(211, ALT_B)
+
+#define GPIO212_GPIO		PIN_CFG(212, GPIO)
+#define GPIO212_SPI2_CS2n	PIN_CFG(212, ALT_A)
+#define GPIO212_LCD_HSO		PIN_CFG(212, ALT_B)
+
+#define GPIO213_GPIO		PIN_CFG(213, GPIO)
+#define GPIO213_SPI2_CS1n	PIN_CFG(213, ALT_A)
+#define GPIO213_LCD_DE		PIN_CFG(213, ALT_B)
+#define GPIO213_BUSMON_D16	PIN_CFG(213, ALT_C)
+
+#define GPIO214_GPIO		PIN_CFG(214, GPIO)
+#define GPIO214_SPI2_CS0n	PIN_CFG(214, ALT_A)
+#define GPIO214_LCD_D7		PIN_CFG(214, ALT_B)
+#define GPIO214_BUSMON_D17	PIN_CFG(214, ALT_C)
+
+#define GPIO215_GPIO		PIN_CFG(215, GPIO)
+#define GPIO215_SPI2_RXD	PIN_CFG(215, ALT_A)
+#define GPIO215_LCD_D6		PIN_CFG(215, ALT_B)
+#define GPIO215_BUSMON_D18	PIN_CFG(215, ALT_C)
+
+#define GPIO216_GPIO		PIN_CFG(216, GPIO)
+#define GPIO216_SPI2_CLK	PIN_CFG(216, ALT_A)
+#define GPIO216_LCD_D5		PIN_CFG(216, ALT_B)
+
+#define GPIO217_GPIO		PIN_CFG(217, GPIO)
+#define GPIO217_SPI2_TXD	PIN_CFG(217, ALT_A)
+#define GPIO217_LCD_D4		PIN_CFG(217, ALT_B)
+#define GPIO217_BUSMON_D19	PIN_CFG(217, ALT_C)
+
+#define GPIO218_GPIO		PIN_CFG(218, GPIO)
+#define GPIO218_I2C2_SCL	PIN_CFG(218, ALT_A)
+#define GPIO218_LCD_VSO		PIN_CFG(218, ALT_B)
+
+#define GPIO219_GPIO		PIN_CFG(219, GPIO)
+#define GPIO219_I2C2_SDA	PIN_CFG(219, ALT_A)
+#define GPIO219_LCD_D3		PIN_CFG(219, ALT_B)
+
+#define GPIO220_GPIO		PIN_CFG(220, GPIO)
+#define GPIO220_MSP2_TCK	PIN_CFG(220, ALT_A)
+#define GPIO220_LCD_D2		PIN_CFG(220, ALT_B)
+
+#define GPIO221_GPIO		PIN_CFG(221, GPIO)
+#define GPIO221_MSP2_TFS	PIN_CFG(221, ALT_A)
+#define GPIO221_LCD_D1		PIN_CFG(221, ALT_B)
+
+#define GPIO222_GPIO		PIN_CFG(222, GPIO)
+#define GPIO222_MSP2_TXD	PIN_CFG(222, ALT_A)
+#define GPIO222_LCD_D0		PIN_CFG(222, ALT_B)
+
+#define GPIO223_GPIO		PIN_CFG(223, GPIO)
+#define GPIO223_MSP2_RXD	PIN_CFG(223, ALT_A)
+#define GPIO223_LCD_CLK		PIN_CFG(223, ALT_B)
+
+#define GPIO224_GPIO		PIN_CFG(224, GPIO)
+#define GPIO224_PRCMU_PWRCTRL0	PIN_CFG(224, ALT_A)
+#define GPIO224_LCD_VSI1	PIN_CFG(224, ALT_B)
+
+#define GPIO225_GPIO		PIN_CFG(225, GPIO)
+#define GPIO225_PRCMU_PWRCTRL1	PIN_CFG(225, ALT_A)
+#define GPIO225_IRDA_RXD	PIN_CFG(225, ALT_B)
+
+#define GPIO226_GPIO		PIN_CFG(226, GPIO)
+#define GPIO226_PRCMU_PWRCTRL2	PIN_CFG(226, ALT_A)
+#define GPIO226_IRRC_DAT	PIN_CFG(226, ALT_B)
+
+#define GPIO227_GPIO		PIN_CFG(227, GPIO)
+#define GPIO227_IRRC_DAT	PIN_CFG(227, ALT_A)
+#define GPIO227_IRDA_TXD	PIN_CFG(227, ALT_B)
+
+#endif
diff --git a/arch/arm/mach-ux500/pins-db8500.h b/arch/arm/mach-ux500/pins-db8500.h
index 9055d5d..66f8761 100644
--- a/arch/arm/mach-ux500/pins-db8500.h
+++ b/arch/arm/mach-ux500/pins-db8500.h
@@ -96,57 +96,57 @@
 #define GPIO17_SLIM0_CLK	PIN_CFG(17, ALT_C)
 
 #define GPIO18_GPIO		PIN_CFG(18, GPIO)
-#define GPIO18_MC0_CMDDIR	PIN_CFG(18, ALT_A)
+#define GPIO18_MC0_CMDDIR	PIN_CFG_PULL(18, ALT_A, UP)
 #define GPIO18_U2_RXD		PIN_CFG(18, ALT_B)
 #define GPIO18_MS_IEP		PIN_CFG(18, ALT_C)
 
 #define GPIO19_GPIO		PIN_CFG(19, GPIO)
-#define GPIO19_MC0_DAT0DIR	PIN_CFG(19, ALT_A)
+#define GPIO19_MC0_DAT0DIR	PIN_CFG_PULL(19, ALT_A, UP)
 #define GPIO19_U2_TXD		PIN_CFG(19, ALT_B)
 #define GPIO19_MS_DAT0DIR	PIN_CFG(19, ALT_C)
 
 #define GPIO20_GPIO		PIN_CFG(20, GPIO)
-#define GPIO20_MC0_DAT2DIR	PIN_CFG(20, ALT_A)
+#define GPIO20_MC0_DAT2DIR	PIN_CFG_PULL(20, ALT_A, UP)
 #define GPIO20_UARTMOD_TXD	PIN_CFG(20, ALT_B)
 #define GPIO20_IP_TRIGOUT	PIN_CFG(20, ALT_C)
 
 #define GPIO21_GPIO		PIN_CFG(21, GPIO)
-#define GPIO21_MC0_DAT31DIR	PIN_CFG(21, ALT_A)
+#define GPIO21_MC0_DAT31DIR	PIN_CFG_PULL(21, ALT_A, UP)
 #define GPIO21_MSP0_SCK		PIN_CFG(21, ALT_B)
 #define GPIO21_MS_DAT31DIR	PIN_CFG(21, ALT_C)
 
 #define GPIO22_GPIO		PIN_CFG(22, GPIO)
-#define GPIO22_MC0_FBCLK	PIN_CFG(22, ALT_A)
+#define GPIO22_MC0_FBCLK	PIN_CFG_PULL(22, ALT_A, UP)
 #define GPIO22_UARTMOD_RXD	PIN_CFG(22, ALT_B)
 #define GPIO22_MS_FBCLK		PIN_CFG(22, ALT_C)
 
 #define GPIO23_GPIO		PIN_CFG(23, GPIO)
-#define GPIO23_MC0_CLK		PIN_CFG(23, ALT_A)
+#define GPIO23_MC0_CLK		PIN_CFG_PULL(23, ALT_A, UP)
 #define GPIO23_STMMOD_CLK	PIN_CFG(23, ALT_B)
 #define GPIO23_MS_CLK		PIN_CFG(23, ALT_C)
 
 #define GPIO24_GPIO		PIN_CFG(24, GPIO)
-#define GPIO24_MC0_CMD		PIN_CFG(24, ALT_A)
+#define GPIO24_MC0_CMD		PIN_CFG_PULL(24, ALT_A, UP)
 #define GPIO24_UARTMOD_RXD	PIN_CFG(24, ALT_B)
 #define GPIO24_MS_BS		PIN_CFG(24, ALT_C)
 
 #define GPIO25_GPIO		PIN_CFG(25, GPIO)
-#define GPIO25_MC0_DAT0		PIN_CFG(25, ALT_A)
+#define GPIO25_MC0_DAT0		PIN_CFG_PULL(25, ALT_A, UP)
 #define GPIO25_STMMOD_DAT0	PIN_CFG(25, ALT_B)
 #define GPIO25_MS_DAT0		PIN_CFG(25, ALT_C)
 
 #define GPIO26_GPIO		PIN_CFG(26, GPIO)
-#define GPIO26_MC0_DAT1		PIN_CFG(26, ALT_A)
+#define GPIO26_MC0_DAT1		PIN_CFG_PULL(26, ALT_A, UP)
 #define GPIO26_STMMOD_DAT1	PIN_CFG(26, ALT_B)
 #define GPIO26_MS_DAT1		PIN_CFG(26, ALT_C)
 
 #define GPIO27_GPIO		PIN_CFG(27, GPIO)
-#define GPIO27_MC0_DAT2		PIN_CFG(27, ALT_A)
+#define GPIO27_MC0_DAT2		PIN_CFG_PULL(27, ALT_A, UP)
 #define GPIO27_STMMOD_DAT2	PIN_CFG(27, ALT_B)
 #define GPIO27_MS_DAT2		PIN_CFG(27, ALT_C)
 
 #define GPIO28_GPIO		PIN_CFG(28, GPIO)
-#define GPIO28_MC0_DAT3		PIN_CFG(28, ALT_A)
+#define GPIO28_MC0_DAT3		PIN_CFG_PULL(28, ALT_A, UP)
 #define GPIO28_STMMOD_DAT3	PIN_CFG(28, ALT_B)
 #define GPIO28_MS_DAT3		PIN_CFG(28, ALT_C)
 
@@ -357,48 +357,48 @@
 #define GPIO97_MC5_DAT7		PIN_CFG(97, ALT_C)
 
 #define GPIO128_GPIO		PIN_CFG(128, GPIO)
-#define GPIO128_MC2_CLK		PIN_CFG(128, ALT_A)
+#define GPIO128_MC2_CLK		PIN_CFG_PULL(128, ALT_A, UP)
 #define GPIO128_SM_CKO		PIN_CFG(128, ALT_B)
 
 #define GPIO129_GPIO		PIN_CFG(129, GPIO)
-#define GPIO129_MC2_CMD		PIN_CFG(129, ALT_A)
+#define GPIO129_MC2_CMD		PIN_CFG_PULL(129, ALT_A, UP)
 #define GPIO129_SM_WAIT0n	PIN_CFG(129, ALT_B)
 
 #define GPIO130_GPIO		PIN_CFG(130, GPIO)
-#define GPIO130_MC2_FBCLK	PIN_CFG(130, ALT_A)
+#define GPIO130_MC2_FBCLK	PIN_CFG_PULL(130, ALT_A, UP)
 #define GPIO130_SM_FBCLK	PIN_CFG(130, ALT_B)
 #define GPIO130_MC2_RSTN	PIN_CFG(130, ALT_C)
 
 #define GPIO131_GPIO		PIN_CFG(131, GPIO)
-#define GPIO131_MC2_DAT0	PIN_CFG(131, ALT_A)
+#define GPIO131_MC2_DAT0	PIN_CFG_PULL(131, ALT_A, UP)
 #define GPIO131_SM_ADQ8		PIN_CFG(131, ALT_B)
 
 #define GPIO132_GPIO		PIN_CFG(132, GPIO)
-#define GPIO132_MC2_DAT1	PIN_CFG(132, ALT_A)
+#define GPIO132_MC2_DAT1	PIN_CFG_PULL(132, ALT_A, UP)
 #define GPIO132_SM_ADQ9		PIN_CFG(132, ALT_B)
 
 #define GPIO133_GPIO		PIN_CFG(133, GPIO)
-#define GPIO133_MC2_DAT2	PIN_CFG(133, ALT_A)
+#define GPIO133_MC2_DAT2	PIN_CFG_PULL(133, ALT_A, UP)
 #define GPIO133_SM_ADQ10	PIN_CFG(133, ALT_B)
 
 #define GPIO134_GPIO		PIN_CFG(134, GPIO)
-#define GPIO134_MC2_DAT3	PIN_CFG(134, ALT_A)
+#define GPIO134_MC2_DAT3	PIN_CFG_PULL(134, ALT_A, UP)
 #define GPIO134_SM_ADQ11	PIN_CFG(134, ALT_B)
 
 #define GPIO135_GPIO		PIN_CFG(135, GPIO)
-#define GPIO135_MC2_DAT4	PIN_CFG(135, ALT_A)
+#define GPIO135_MC2_DAT4	PIN_CFG_PULL(135, ALT_A, UP)
 #define GPIO135_SM_ADQ12	PIN_CFG(135, ALT_B)
 
 #define GPIO136_GPIO		PIN_CFG(136, GPIO)
-#define GPIO136_MC2_DAT5	PIN_CFG(136, ALT_A)
+#define GPIO136_MC2_DAT5	PIN_CFG_PULL(136, ALT_A, UP)
 #define GPIO136_SM_ADQ13	PIN_CFG(136, ALT_B)
 
 #define GPIO137_GPIO		PIN_CFG(137, GPIO)
-#define GPIO137_MC2_DAT6	PIN_CFG(137, ALT_A)
+#define GPIO137_MC2_DAT6	PIN_CFG_PULL(137, ALT_A, UP)
 #define GPIO137_SM_ADQ14	PIN_CFG(137, ALT_B)
 
 #define GPIO138_GPIO		PIN_CFG(138, GPIO)
-#define GPIO138_MC2_DAT7	PIN_CFG(138, ALT_A)
+#define GPIO138_MC2_DAT7	PIN_CFG_PULL(138, ALT_A, UP)
 #define GPIO138_SM_ADQ15	PIN_CFG(138, ALT_B)
 
 #define GPIO139_GPIO		PIN_CFG(139, GPIO)
@@ -569,39 +569,39 @@
 #define GPIO196_MSP2_RXD	PIN_CFG(196, ALT_A)
 
 #define GPIO197_GPIO		PIN_CFG(197, GPIO)
-#define GPIO197_MC4_DAT3	PIN_CFG(197, ALT_A)
+#define GPIO197_MC4_DAT3	PIN_CFG_PULL(197, ALT_A, UP)
 
 #define GPIO198_GPIO		PIN_CFG(198, GPIO)
-#define GPIO198_MC4_DAT2	PIN_CFG(198, ALT_A)
+#define GPIO198_MC4_DAT2	PIN_CFG_PULL(198, ALT_A, UP)
 
 #define GPIO199_GPIO		PIN_CFG(199, GPIO)
-#define GPIO199_MC4_DAT1	PIN_CFG(199, ALT_A)
+#define GPIO199_MC4_DAT1	PIN_CFG_PULL(199, ALT_A, UP)
 
 #define GPIO200_GPIO		PIN_CFG(200, GPIO)
-#define GPIO200_MC4_DAT0	PIN_CFG(200, ALT_A)
+#define GPIO200_MC4_DAT0	PIN_CFG_PULL(200, ALT_A, UP)
 
 #define GPIO201_GPIO		PIN_CFG(201, GPIO)
-#define GPIO201_MC4_CMD		PIN_CFG(201, ALT_A)
+#define GPIO201_MC4_CMD		PIN_CFG_PULL(201, ALT_A, UP)
 
 #define GPIO202_GPIO		PIN_CFG(202, GPIO)
-#define GPIO202_MC4_FBCLK	PIN_CFG(202, ALT_A)
+#define GPIO202_MC4_FBCLK	PIN_CFG_PULL(202, ALT_A, UP)
 #define GPIO202_PWL		PIN_CFG(202, ALT_B)
 #define GPIO202_MC4_RSTN	PIN_CFG(202, ALT_C)
 
 #define GPIO203_GPIO		PIN_CFG(203, GPIO)
-#define GPIO203_MC4_CLK		PIN_CFG(203, ALT_A)
+#define GPIO203_MC4_CLK		PIN_CFG_PULL(203, ALT_A, UP)
 
 #define GPIO204_GPIO		PIN_CFG(204, GPIO)
-#define GPIO204_MC4_DAT7	PIN_CFG(204, ALT_A)
+#define GPIO204_MC4_DAT7	PIN_CFG_PULL(204, ALT_A, UP)
 
 #define GPIO205_GPIO		PIN_CFG(205, GPIO)
-#define GPIO205_MC4_DAT6	PIN_CFG(205, ALT_A)
+#define GPIO205_MC4_DAT6	PIN_CFG_PULL(205, ALT_A, UP)
 
 #define GPIO206_GPIO		PIN_CFG(206, GPIO)
-#define GPIO206_MC4_DAT5	PIN_CFG(206, ALT_A)
+#define GPIO206_MC4_DAT5	PIN_CFG_PULL(206, ALT_A, UP)
 
 #define GPIO207_GPIO		PIN_CFG(207, GPIO)
-#define GPIO207_MC4_DAT4	PIN_CFG(207, ALT_A)
+#define GPIO207_MC4_DAT4	PIN_CFG_PULL(207, ALT_A, UP)
 
 #define GPIO208_GPIO		PIN_CFG(208, GPIO)
 #define GPIO208_MC1_CLK		PIN_CFG(208, ALT_A)
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index 438ef16..9e4c678 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -78,6 +78,8 @@
 	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
 	outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1);
 
+	smp_cross_call(cpumask_of(cpu));
+
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
 		if (pen_release == -1)
diff --git a/arch/arm/mach-ux500/prcmu.c b/arch/arm/mach-ux500/prcmu.c
new file mode 100644
index 0000000..293274d
--- /dev/null
+++ b/arch/arm/mach-ux500/prcmu.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) ST Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
+ *
+ * U8500 PRCMU driver.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/jiffies.h>
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+
+#include <mach/hardware.h>
+#include <mach/prcmu-regs.h>
+
+#define PRCMU_TCDM_BASE __io_address(U8500_PRCMU_TCDM_BASE)
+
+#define REQ_MB5 (PRCMU_TCDM_BASE + 0xE44)
+#define ACK_MB5 (PRCMU_TCDM_BASE + 0xDF4)
+
+#define REQ_MB5_I2C_SLAVE_OP (REQ_MB5)
+#define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1)
+#define REQ_MB5_I2C_REG (REQ_MB5 + 2)
+#define REQ_MB5_I2C_VAL (REQ_MB5 + 3)
+
+#define ACK_MB5_I2C_STATUS (ACK_MB5 + 1)
+#define ACK_MB5_I2C_VAL (ACK_MB5 + 3)
+
+#define I2C_WRITE(slave) ((slave) << 1)
+#define I2C_READ(slave) (((slave) << 1) | BIT(0))
+#define I2C_STOP_EN BIT(3)
+
+enum ack_mb5_status {
+	I2C_WR_OK = 0x01,
+	I2C_RD_OK = 0x02,
+};
+
+#define MBOX_BIT BIT
+#define NUM_MBOX 8
+
+static struct {
+	struct mutex lock;
+	struct completion work;
+	bool failed;
+	struct {
+		u8 status;
+		u8 value;
+	} ack;
+} mb5_transfer;
+
+/**
+ * prcmu_abb_read() - Read register value(s) from the ABB.
+ * @slave:	The I2C slave address.
+ * @reg:	The (start) register address.
+ * @value:	The read out value(s).
+ * @size:	The number of registers to read.
+ *
+ * Reads register value(s) from the ABB.
+ * @size has to be 1 for the current firmware version.
+ */
+int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+{
+	int r;
+
+	if (size != 1)
+		return -EINVAL;
+
+	r = mutex_lock_interruptible(&mb5_transfer.lock);
+	if (r)
+		return r;
+
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+		cpu_relax();
+
+	writeb(I2C_READ(slave), REQ_MB5_I2C_SLAVE_OP);
+	writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
+	writeb(reg, REQ_MB5_I2C_REG);
+
+	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
+	if (!wait_for_completion_timeout(&mb5_transfer.work,
+			msecs_to_jiffies(500))) {
+		pr_err("prcmu: prcmu_abb_read timed out.\n");
+		r = -EIO;
+		goto unlock_and_return;
+	}
+	r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO);
+	if (!r)
+		*value = mb5_transfer.ack.value;
+
+unlock_and_return:
+	mutex_unlock(&mb5_transfer.lock);
+	return r;
+}
+EXPORT_SYMBOL(prcmu_abb_read);
+
+/**
+ * prcmu_abb_write() - Write register value(s) to the ABB.
+ * @slave:	The I2C slave address.
+ * @reg:	The (start) register address.
+ * @value:	The value(s) to write.
+ * @size:	The number of registers to write.
+ *
+ * Reads register value(s) from the ABB.
+ * @size has to be 1 for the current firmware version.
+ */
+int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+	int r;
+
+	if (size != 1)
+		return -EINVAL;
+
+	r = mutex_lock_interruptible(&mb5_transfer.lock);
+	if (r)
+		return r;
+
+
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+		cpu_relax();
+
+	writeb(I2C_WRITE(slave), REQ_MB5_I2C_SLAVE_OP);
+	writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
+	writeb(reg, REQ_MB5_I2C_REG);
+	writeb(*value, REQ_MB5_I2C_VAL);
+
+	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
+	if (!wait_for_completion_timeout(&mb5_transfer.work,
+			msecs_to_jiffies(500))) {
+		pr_err("prcmu: prcmu_abb_write timed out.\n");
+		r = -EIO;
+		goto unlock_and_return;
+	}
+	r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO);
+
+unlock_and_return:
+	mutex_unlock(&mb5_transfer.lock);
+	return r;
+}
+EXPORT_SYMBOL(prcmu_abb_write);
+
+static void read_mailbox_0(void)
+{
+	writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_1(void)
+{
+	writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_2(void)
+{
+	writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_3(void)
+{
+	writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_4(void)
+{
+	writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_5(void)
+{
+	mb5_transfer.ack.status = readb(ACK_MB5_I2C_STATUS);
+	mb5_transfer.ack.value = readb(ACK_MB5_I2C_VAL);
+	complete(&mb5_transfer.work);
+	writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_6(void)
+{
+	writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_7(void)
+{
+	writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR);
+}
+
+static void (* const read_mailbox[NUM_MBOX])(void) = {
+	read_mailbox_0,
+	read_mailbox_1,
+	read_mailbox_2,
+	read_mailbox_3,
+	read_mailbox_4,
+	read_mailbox_5,
+	read_mailbox_6,
+	read_mailbox_7
+};
+
+static irqreturn_t prcmu_irq_handler(int irq, void *data)
+{
+	u32 bits;
+	u8 n;
+
+	bits = (readl(PRCM_ARM_IT1_VAL) & (MBOX_BIT(NUM_MBOX) - 1));
+	if (unlikely(!bits))
+		return IRQ_NONE;
+
+	for (n = 0; bits; n++) {
+		if (bits & MBOX_BIT(n)) {
+			bits -= MBOX_BIT(n);
+			read_mailbox[n]();
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int __init prcmu_init(void)
+{
+	mutex_init(&mb5_transfer.lock);
+	init_completion(&mb5_transfer.work);
+
+	/* Clean up the mailbox interrupts after pre-kernel code. */
+	writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR);
+
+	return request_irq(IRQ_PRCMU, prcmu_irq_handler, 0, "prcmu", NULL);
+}
+
+arch_initcall(prcmu_init);
diff --git a/arch/arm/mach-ux500/ste-dma40-db5500.h b/arch/arm/mach-ux500/ste-dma40-db5500.h
new file mode 100644
index 0000000..cb2110c
--- /dev/null
+++ b/arch/arm/mach-ux500/ste-dma40-db5500.h
@@ -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
+ *
+ * DB5500-SoC-specific configuration for DMA40
+ */
+
+#ifndef STE_DMA40_DB5500_H
+#define STE_DMA40_DB5500_H
+
+#define DB5500_DMA_NR_DEV 64
+
+enum dma_src_dev_type {
+	DB5500_DMA_DEV0_SPI0_RX = 0,
+	DB5500_DMA_DEV1_SPI1_RX = 1,
+	DB5500_DMA_DEV2_SPI2_RX = 2,
+	DB5500_DMA_DEV3_SPI3_RX = 3,
+	DB5500_DMA_DEV4_USB_OTG_IEP_1_9 = 4,
+	DB5500_DMA_DEV5_USB_OTG_IEP_2_10 = 5,
+	DB5500_DMA_DEV6_USB_OTG_IEP_3_11 = 6,
+	DB5500_DMA_DEV7_IRDA_RFS = 7,
+	DB5500_DMA_DEV8_IRDA_FIFO_RX = 8,
+	DB5500_DMA_DEV9_MSP0_RX = 9,
+	DB5500_DMA_DEV10_MSP1_RX = 10,
+	DB5500_DMA_DEV11_MSP2_RX = 11,
+	DB5500_DMA_DEV12_UART0_RX = 12,
+	DB5500_DMA_DEV13_UART1_RX = 13,
+	DB5500_DMA_DEV14_UART2_RX = 14,
+	DB5500_DMA_DEV15_UART3_RX = 15,
+	DB5500_DMA_DEV16_USB_OTG_IEP_8 = 16,
+	DB5500_DMA_DEV17_USB_OTG_IEP_1_9 = 17,
+	DB5500_DMA_DEV18_USB_OTG_IEP_2_10 = 18,
+	DB5500_DMA_DEV19_USB_OTG_IEP_3_11 = 19,
+	DB5500_DMA_DEV20_USB_OTG_IEP_4_12 = 20,
+	DB5500_DMA_DEV21_USB_OTG_IEP_5_13 = 21,
+	DB5500_DMA_DEV22_USB_OTG_IEP_6_14 = 22,
+	DB5500_DMA_DEV23_USB_OTG_IEP_7_15 = 23,
+	DB5500_DMA_DEV24_SDMMC0_RX = 24,
+	DB5500_DMA_DEV25_SDMMC1_RX = 25,
+	DB5500_DMA_DEV26_SDMMC2_RX = 26,
+	DB5500_DMA_DEV27_SDMMC3_RX = 27,
+	DB5500_DMA_DEV28_SDMMC4_RX = 28,
+	/* 29 - 32 not used */
+	DB5500_DMA_DEV33_SDMMC0_RX = 33,
+	DB5500_DMA_DEV34_SDMMC1_RX = 34,
+	DB5500_DMA_DEV35_SDMMC2_RX = 35,
+	DB5500_DMA_DEV36_SDMMC3_RX = 36,
+	DB5500_DMA_DEV37_SDMMC4_RX = 37,
+	DB5500_DMA_DEV38_USB_OTG_IEP_8 = 38,
+	DB5500_DMA_DEV39_USB_OTG_IEP_1_9 = 39,
+	DB5500_DMA_DEV40_USB_OTG_IEP_2_10 = 40,
+	DB5500_DMA_DEV41_USB_OTG_IEP_3_11 = 41,
+	DB5500_DMA_DEV42_USB_OTG_IEP_4_12 = 42,
+	DB5500_DMA_DEV43_USB_OTG_IEP_5_13 = 43,
+	DB5500_DMA_DEV44_USB_OTG_IEP_6_14 = 44,
+	DB5500_DMA_DEV45_USB_OTG_IEP_7_15 = 45,
+	/* 46 not used */
+	DB5500_DMA_DEV47_MCDE_RX = 47,
+	DB5500_DMA_DEV48_CRYPTO1_RX = 48,
+	/* 49, 50 not used */
+	DB5500_DMA_DEV49_I2C1_RX = 51,
+	DB5500_DMA_DEV50_I2C3_RX = 52,
+	DB5500_DMA_DEV51_I2C2_RX = 53,
+	/* 54 - 60 not used */
+	DB5500_DMA_DEV61_CRYPTO0_RX = 61,
+	/* 62, 63 not used */
+};
+
+enum dma_dest_dev_type {
+	DB5500_DMA_DEV0_SPI0_TX = 0,
+	DB5500_DMA_DEV1_SPI1_TX = 1,
+	DB5500_DMA_DEV2_SPI2_TX = 2,
+	DB5500_DMA_DEV3_SPI3_TX = 3,
+	DB5500_DMA_DEV4_USB_OTG_OEP_1_9 = 4,
+	DB5500_DMA_DEV5_USB_OTG_OEP_2_10 = 5,
+	DB5500_DMA_DEV6_USB_OTG_OEP_3_11 = 6,
+	DB5500_DMA_DEV7_IRRC_TX = 7,
+	DB5500_DMA_DEV8_IRDA_FIFO_TX = 8,
+	DB5500_DMA_DEV9_MSP0_TX = 9,
+	DB5500_DMA_DEV10_MSP1_TX = 10,
+	DB5500_DMA_DEV11_MSP2_TX = 11,
+	DB5500_DMA_DEV12_UART0_TX = 12,
+	DB5500_DMA_DEV13_UART1_TX = 13,
+	DB5500_DMA_DEV14_UART2_TX = 14,
+	DB5500_DMA_DEV15_UART3_TX = 15,
+	DB5500_DMA_DEV16_USB_OTG_OEP_8 = 16,
+	DB5500_DMA_DEV17_USB_OTG_OEP_1_9 = 17,
+	DB5500_DMA_DEV18_USB_OTG_OEP_2_10 = 18,
+	DB5500_DMA_DEV19_USB_OTG_OEP_3_11 = 19,
+	DB5500_DMA_DEV20_USB_OTG_OEP_4_12 = 20,
+	DB5500_DMA_DEV21_USB_OTG_OEP_5_13 = 21,
+	DB5500_DMA_DEV22_USB_OTG_OEP_6_14 = 22,
+	DB5500_DMA_DEV23_USB_OTG_OEP_7_15 = 23,
+	DB5500_DMA_DEV24_SDMMC0_TX = 24,
+	DB5500_DMA_DEV25_SDMMC1_TX = 25,
+	DB5500_DMA_DEV26_SDMMC2_TX = 26,
+	DB5500_DMA_DEV27_SDMMC3_TX = 27,
+	DB5500_DMA_DEV28_SDMMC4_TX = 28,
+	/* 29 - 31 not used */
+	DB5500_DMA_DEV32_FSMC_TX = 32,
+	DB5500_DMA_DEV33_SDMMC0_TX = 33,
+	DB5500_DMA_DEV34_SDMMC1_TX = 34,
+	DB5500_DMA_DEV35_SDMMC2_TX = 35,
+	DB5500_DMA_DEV36_SDMMC3_TX = 36,
+	DB5500_DMA_DEV37_SDMMC4_TX = 37,
+	DB5500_DMA_DEV38_USB_OTG_OEP_8 = 38,
+	DB5500_DMA_DEV39_USB_OTG_OEP_1_9 = 39,
+	DB5500_DMA_DEV40_USB_OTG_OEP_2_10 = 40,
+	DB5500_DMA_DEV41_USB_OTG_OEP_3_11 = 41,
+	DB5500_DMA_DEV42_USB_OTG_OEP_4_12 = 42,
+	DB5500_DMA_DEV43_USB_OTG_OEP_5_13 = 43,
+	DB5500_DMA_DEV44_USB_OTG_OEP_6_14 = 44,
+	DB5500_DMA_DEV45_USB_OTG_OEP_7_15 = 45,
+	/* 46 not used */
+	DB5500_DMA_DEV47_STM_TX = 47,
+	DB5500_DMA_DEV48_CRYPTO1_TX = 48,
+	DB5500_DMA_DEV49_CRYPTO1_TX_HASH1_TX = 49,
+	DB5500_DMA_DEV50_HASH1_TX = 50,
+	DB5500_DMA_DEV51_I2C1_TX = 51,
+	DB5500_DMA_DEV52_I2C3_TX = 52,
+	DB5500_DMA_DEV53_I2C2_TX = 53,
+	/* 54, 55 not used */
+	DB5500_DMA_MEMCPY_TX_1 = 56,
+	DB5500_DMA_MEMCPY_TX_2 = 57,
+	DB5500_DMA_MEMCPY_TX_3 = 58,
+	DB5500_DMA_MEMCPY_TX_4 = 59,
+	DB5500_DMA_MEMCPY_TX_5 = 60,
+	DB5500_DMA_DEV61_CRYPTO0_TX = 61,
+	DB5500_DMA_DEV62_CRYPTO0_TX_HASH0_TX = 62,
+	DB5500_DMA_DEV63_HASH0_TX = 63,
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/ste-dma40-db8500.h b/arch/arm/mach-ux500/ste-dma40-db8500.h
index 9d9d379..a616419 100644
--- a/arch/arm/mach-ux500/ste-dma40-db8500.h
+++ b/arch/arm/mach-ux500/ste-dma40-db8500.h
@@ -10,145 +10,135 @@
 #ifndef STE_DMA40_DB8500_H
 #define STE_DMA40_DB8500_H
 
-#define STEDMA40_NR_DEV 64
+#define DB8500_DMA_NR_DEV 64
 
 enum dma_src_dev_type {
-	STEDMA40_DEV_SPI0_RX = 0,
-	STEDMA40_DEV_SD_MMC0_RX = 1,
-	STEDMA40_DEV_SD_MMC1_RX = 2,
-	STEDMA40_DEV_SD_MMC2_RX = 3,
-	STEDMA40_DEV_I2C1_RX = 4,
-	STEDMA40_DEV_I2C3_RX = 5,
-	STEDMA40_DEV_I2C2_RX = 6,
-	STEDMA40_DEV_I2C4_RX = 7, /* Only on V1 */
-	STEDMA40_DEV_SSP0_RX = 8,
-	STEDMA40_DEV_SSP1_RX = 9,
-	STEDMA40_DEV_MCDE_RX = 10,
-	STEDMA40_DEV_UART2_RX = 11,
-	STEDMA40_DEV_UART1_RX = 12,
-	STEDMA40_DEV_UART0_RX = 13,
-	STEDMA40_DEV_MSP2_RX = 14,
-	STEDMA40_DEV_I2C0_RX = 15,
-	STEDMA40_DEV_USB_OTG_IEP_8 = 16,
-	STEDMA40_DEV_USB_OTG_IEP_1_9 = 17,
-	STEDMA40_DEV_USB_OTG_IEP_2_10 = 18,
-	STEDMA40_DEV_USB_OTG_IEP_3_11 = 19,
-	STEDMA40_DEV_SLIM0_CH0_RX_HSI_RX_CH0 = 20,
-	STEDMA40_DEV_SLIM0_CH1_RX_HSI_RX_CH1 = 21,
-	STEDMA40_DEV_SLIM0_CH2_RX_HSI_RX_CH2 = 22,
-	STEDMA40_DEV_SLIM0_CH3_RX_HSI_RX_CH3 = 23,
-	STEDMA40_DEV_SRC_SXA0_RX_TX = 24,
-	STEDMA40_DEV_SRC_SXA1_RX_TX = 25,
-	STEDMA40_DEV_SRC_SXA2_RX_TX = 26,
-	STEDMA40_DEV_SRC_SXA3_RX_TX = 27,
-	STEDMA40_DEV_SD_MM2_RX = 28,
-	STEDMA40_DEV_SD_MM0_RX = 29,
-	STEDMA40_DEV_MSP1_RX = 30,
-	/*
-	 * This channel is either SlimBus or MSP,
-	 * never both at the same time.
-	 */
-	STEDMA40_SLIM0_CH0_RX = 31,
-	STEDMA40_DEV_MSP0_RX = 31,
-	STEDMA40_DEV_SD_MM1_RX = 32,
-	STEDMA40_DEV_SPI2_RX = 33,
-	STEDMA40_DEV_I2C3_RX2 = 34,
-	STEDMA40_DEV_SPI1_RX = 35,
-	STEDMA40_DEV_USB_OTG_IEP_4_12 = 36,
-	STEDMA40_DEV_USB_OTG_IEP_5_13 = 37,
-	STEDMA40_DEV_USB_OTG_IEP_6_14 = 38,
-	STEDMA40_DEV_USB_OTG_IEP_7_15 = 39,
-	STEDMA40_DEV_SPI3_RX = 40,
-	STEDMA40_DEV_SD_MM3_RX = 41,
-	STEDMA40_DEV_SD_MM4_RX = 42,
-	STEDMA40_DEV_SD_MM5_RX = 43,
-	STEDMA40_DEV_SRC_SXA4_RX_TX = 44,
-	STEDMA40_DEV_SRC_SXA5_RX_TX = 45,
-	STEDMA40_DEV_SRC_SXA6_RX_TX = 46,
-	STEDMA40_DEV_SRC_SXA7_RX_TX = 47,
-	STEDMA40_DEV_CAC1_RX = 48,
-	/* RX channels 49 and 50 are unused */
-	STEDMA40_DEV_MSHC_RX = 51,
-	STEDMA40_DEV_SLIM1_CH0_RX_HSI_RX_CH4 = 52,
-	STEDMA40_DEV_SLIM1_CH1_RX_HSI_RX_CH5 = 53,
-	STEDMA40_DEV_SLIM1_CH2_RX_HSI_RX_CH6 = 54,
-	STEDMA40_DEV_SLIM1_CH3_RX_HSI_RX_CH7 = 55,
-	/* RX channels 56 thru 60 are unused */
-	STEDMA40_DEV_CAC0_RX = 61,
-	/* RX channels 62 and 63 are unused */
+	DB8500_DMA_DEV0_SPI0_RX = 0,
+	DB8500_DMA_DEV1_SD_MMC0_RX = 1,
+	DB8500_DMA_DEV2_SD_MMC1_RX = 2,
+	DB8500_DMA_DEV3_SD_MMC2_RX = 3,
+	DB8500_DMA_DEV4_I2C1_RX = 4,
+	DB8500_DMA_DEV5_I2C3_RX = 5,
+	DB8500_DMA_DEV6_I2C2_RX = 6,
+	DB8500_DMA_DEV7_I2C4_RX = 7, /* Only on V1 and later */
+	DB8500_DMA_DEV8_SSP0_RX = 8,
+	DB8500_DMA_DEV9_SSP1_RX = 9,
+	DB8500_DMA_DEV10_MCDE_RX = 10,
+	DB8500_DMA_DEV11_UART2_RX = 11,
+	DB8500_DMA_DEV12_UART1_RX = 12,
+	DB8500_DMA_DEV13_UART0_RX = 13,
+	DB8500_DMA_DEV14_MSP2_RX = 14,
+	DB8500_DMA_DEV15_I2C0_RX = 15,
+	DB8500_DMA_DEV16_USB_OTG_IEP_7_15 = 16,
+	DB8500_DMA_DEV17_USB_OTG_IEP_6_14 = 17,
+	DB8500_DMA_DEV18_USB_OTG_IEP_5_13 = 18,
+	DB8500_DMA_DEV19_USB_OTG_IEP_4_12 = 19,
+	DB8500_DMA_DEV20_SLIM0_CH0_RX_HSI_RX_CH0 = 20,
+	DB8500_DMA_DEV21_SLIM0_CH1_RX_HSI_RX_CH1 = 21,
+	DB8500_DMA_DEV22_SLIM0_CH2_RX_HSI_RX_CH2 = 22,
+	DB8500_DMA_DEV23_SLIM0_CH3_RX_HSI_RX_CH3 = 23,
+	DB8500_DMA_DEV24_SRC_SXA0_RX_TX = 24,
+	DB8500_DMA_DEV25_SRC_SXA1_RX_TX = 25,
+	DB8500_DMA_DEV26_SRC_SXA2_RX_TX = 26,
+	DB8500_DMA_DEV27_SRC_SXA3_RX_TX = 27,
+	DB8500_DMA_DEV28_SD_MM2_RX = 28,
+	DB8500_DMA_DEV29_SD_MM0_RX = 29,
+	DB8500_DMA_DEV30_MSP1_RX = 30,
+	/* On DB8500v2, MSP3 RX replaces MSP1 RX */
+	DB8500_DMA_DEV30_MSP3_RX = 30,
+	DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX = 31,
+	DB8500_DMA_DEV32_SD_MM1_RX = 32,
+	DB8500_DMA_DEV33_SPI2_RX = 33,
+	DB8500_DMA_DEV34_I2C3_RX2 = 34,
+	DB8500_DMA_DEV35_SPI1_RX = 35,
+	DB8500_DMA_DEV36_USB_OTG_IEP_3_11 = 36,
+	DB8500_DMA_DEV37_USB_OTG_IEP_2_10 = 37,
+	DB8500_DMA_DEV38_USB_OTG_IEP_1_9 = 38,
+	DB8500_DMA_DEV39_USB_OTG_IEP_8 = 39,
+	DB8500_DMA_DEV40_SPI3_RX = 40,
+	DB8500_DMA_DEV41_SD_MM3_RX = 41,
+	DB8500_DMA_DEV42_SD_MM4_RX = 42,
+	DB8500_DMA_DEV43_SD_MM5_RX = 43,
+	DB8500_DMA_DEV44_SRC_SXA4_RX_TX = 44,
+	DB8500_DMA_DEV45_SRC_SXA5_RX_TX = 45,
+	DB8500_DMA_DEV46_SLIM0_CH8_RX_SRC_SXA6_RX_TX = 46,
+	DB8500_DMA_DEV47_SLIM0_CH9_RX_SRC_SXA7_RX_TX = 47,
+	DB8500_DMA_DEV48_CAC1_RX = 48,
+	/* 49, 50 and 51 are not used */
+	DB8500_DMA_DEV52_SLIM0_CH4_RX_HSI_RX_CH4 = 52,
+	DB8500_DMA_DEV53_SLIM0_CH5_RX_HSI_RX_CH5 = 53,
+	DB8500_DMA_DEV54_SLIM0_CH6_RX_HSI_RX_CH6 = 54,
+	DB8500_DMA_DEV55_SLIM0_CH7_RX_HSI_RX_CH7 = 55,
+	/* 56, 57, 58, 59 and 60 are not used */
+	DB8500_DMA_DEV61_CAC0_RX = 61,
+	/* 62 and 63 are not used */
 };
 
 enum dma_dest_dev_type {
-	STEDMA40_DEV_SPI0_TX = 0,
-	STEDMA40_DEV_SD_MMC0_TX = 1,
-	STEDMA40_DEV_SD_MMC1_TX = 2,
-	STEDMA40_DEV_SD_MMC2_TX = 3,
-	STEDMA40_DEV_I2C1_TX = 4,
-	STEDMA40_DEV_I2C3_TX = 5,
-	STEDMA40_DEV_I2C2_TX = 6,
-	STEDMA50_DEV_I2C4_TX = 7, /* Only on V1 */
-	STEDMA40_DEV_SSP0_TX = 8,
-	STEDMA40_DEV_SSP1_TX = 9,
-	/* TX channel 10 is unused */
-	STEDMA40_DEV_UART2_TX = 11,
-	STEDMA40_DEV_UART1_TX = 12,
-	STEDMA40_DEV_UART0_TX= 13,
-	STEDMA40_DEV_MSP2_TX = 14,
-	STEDMA40_DEV_I2C0_TX = 15,
-	STEDMA40_DEV_USB_OTG_OEP_8 = 16,
-	STEDMA40_DEV_USB_OTG_OEP_1_9 = 17,
-	STEDMA40_DEV_USB_OTG_OEP_2_10= 18,
-	STEDMA40_DEV_USB_OTG_OEP_3_11 = 19,
-	STEDMA40_DEV_SLIM0_CH0_TX_HSI_TX_CH0 = 20,
-	STEDMA40_DEV_SLIM0_CH1_TX_HSI_TX_CH1 = 21,
-	STEDMA40_DEV_SLIM0_CH2_TX_HSI_TX_CH2 = 22,
-	STEDMA40_DEV_SLIM0_CH3_TX_HSI_TX_CH3 = 23,
-	STEDMA40_DEV_DST_SXA0_RX_TX = 24,
-	STEDMA40_DEV_DST_SXA1_RX_TX = 25,
-	STEDMA40_DEV_DST_SXA2_RX_TX = 26,
-	STEDMA40_DEV_DST_SXA3_RX_TX = 27,
-	STEDMA40_DEV_SD_MM2_TX = 28,
-	STEDMA40_DEV_SD_MM0_TX = 29,
-	STEDMA40_DEV_MSP1_TX = 30,
-	/*
-	 * This channel is either SlimBus or MSP,
-	 * never both at the same time.
-	 */
-	STEDMA40_SLIM0_CH0_TX = 31,
-	STEDMA40_DEV_MSP0_TX = 31,
-	STEDMA40_DEV_SD_MM1_TX = 32,
-	STEDMA40_DEV_SPI2_TX = 33,
-	/* Secondary I2C3 channel */
-	STEDMA40_DEV_I2C3_TX2 = 34,
-	STEDMA40_DEV_SPI1_TX = 35,
-	STEDMA40_DEV_USB_OTG_OEP_4_12 = 36,
-	STEDMA40_DEV_USB_OTG_OEP_5_13 = 37,
-	STEDMA40_DEV_USB_OTG_OEP_6_14 = 38,
-	STEDMA40_DEV_USB_OTG_OEP_7_15 = 39,
-	STEDMA40_DEV_SPI3_TX = 40,
-	STEDMA40_DEV_SD_MM3_TX = 41,
-	STEDMA40_DEV_SD_MM4_TX = 42,
-	STEDMA40_DEV_SD_MM5_TX = 43,
-	STEDMA40_DEV_DST_SXA4_RX_TX = 44,
-	STEDMA40_DEV_DST_SXA5_RX_TX = 45,
-	STEDMA40_DEV_DST_SXA6_RX_TX = 46,
-	STEDMA40_DEV_DST_SXA7_RX_TX = 47,
-	STEDMA40_DEV_CAC1_TX = 48,
-	STEDMA40_DEV_CAC1_TX_HAC1_TX = 49,
-	STEDMA40_DEV_HAC1_TX = 50,
-	STEDMA40_MEMCPY_TX_0 = 51,
-	STEDMA40_DEV_SLIM1_CH0_TX_HSI_TX_CH4 = 52,
-	STEDMA40_DEV_SLIM1_CH1_TX_HSI_TX_CH5 = 53,
-	STEDMA40_DEV_SLIM1_CH2_TX_HSI_TX_CH6 = 54,
-	STEDMA40_DEV_SLIM1_CH3_TX_HSI_TX_CH7 = 55,
-	STEDMA40_MEMCPY_TX_1 = 56,
-	STEDMA40_MEMCPY_TX_2 = 57,
-	STEDMA40_MEMCPY_TX_3 = 58,
-	STEDMA40_MEMCPY_TX_4 = 59,
-	STEDMA40_MEMCPY_TX_5 = 60,
-	STEDMA40_DEV_CAC0_TX = 61,
-	STEDMA40_DEV_CAC0_TX_HAC0_TX = 62,
-	STEDMA40_DEV_HAC0_TX = 63,
+	DB8500_DMA_DEV0_SPI0_TX = 0,
+	DB8500_DMA_DEV1_SD_MMC0_TX = 1,
+	DB8500_DMA_DEV2_SD_MMC1_TX = 2,
+	DB8500_DMA_DEV3_SD_MMC2_TX = 3,
+	DB8500_DMA_DEV4_I2C1_TX = 4,
+	DB8500_DMA_DEV5_I2C3_TX = 5,
+	DB8500_DMA_DEV6_I2C2_TX = 6,
+	DB8500_DMA_DEV7_I2C4_TX = 7, /* Only on V1 and later */
+	DB8500_DMA_DEV8_SSP0_TX = 8,
+	DB8500_DMA_DEV9_SSP1_TX = 9,
+	/* 10 is not used*/
+	DB8500_DMA_DEV11_UART2_TX = 11,
+	DB8500_DMA_DEV12_UART1_TX = 12,
+	DB8500_DMA_DEV13_UART0_TX = 13,
+	DB8500_DMA_DEV14_MSP2_TX = 14,
+	DB8500_DMA_DEV15_I2C0_TX = 15,
+	DB8500_DMA_DEV16_USB_OTG_OEP_7_15 = 16,
+	DB8500_DMA_DEV17_USB_OTG_OEP_6_14 = 17,
+	DB8500_DMA_DEV18_USB_OTG_OEP_5_13 = 18,
+	DB8500_DMA_DEV19_USB_OTG_OEP_4_12 = 19,
+	DB8500_DMA_DEV20_SLIM0_CH0_TX_HSI_TX_CH0 = 20,
+	DB8500_DMA_DEV21_SLIM0_CH1_TX_HSI_TX_CH1 = 21,
+	DB8500_DMA_DEV22_SLIM0_CH2_TX_HSI_TX_CH2 = 22,
+	DB8500_DMA_DEV23_SLIM0_CH3_TX_HSI_TX_CH3 = 23,
+	DB8500_DMA_DEV24_DST_SXA0_RX_TX = 24,
+	DB8500_DMA_DEV25_DST_SXA1_RX_TX = 25,
+	DB8500_DMA_DEV26_DST_SXA2_RX_TX = 26,
+	DB8500_DMA_DEV27_DST_SXA3_RX_TX = 27,
+	DB8500_DMA_DEV28_SD_MM2_TX = 28,
+	DB8500_DMA_DEV29_SD_MM0_TX = 29,
+	DB8500_DMA_DEV30_MSP1_TX = 30,
+	DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX = 31,
+	DB8500_DMA_DEV32_SD_MM1_TX = 32,
+	DB8500_DMA_DEV33_SPI2_TX = 33,
+	DB8500_DMA_DEV34_I2C3_TX2 = 34,
+	DB8500_DMA_DEV35_SPI1_TX = 35,
+	DB8500_DMA_DEV36_USB_OTG_OEP_3_11 = 36,
+	DB8500_DMA_DEV37_USB_OTG_OEP_2_10 = 37,
+	DB8500_DMA_DEV38_USB_OTG_OEP_1_9 = 38,
+	DB8500_DMA_DEV39_USB_OTG_OEP_8 = 39,
+	DB8500_DMA_DEV40_SPI3_TX = 40,
+	DB8500_DMA_DEV41_SD_MM3_TX = 41,
+	DB8500_DMA_DEV42_SD_MM4_TX = 42,
+	DB8500_DMA_DEV43_SD_MM5_TX = 43,
+	DB8500_DMA_DEV44_DST_SXA4_RX_TX = 44,
+	DB8500_DMA_DEV45_DST_SXA5_RX_TX = 45,
+	DB8500_DMA_DEV46_SLIM0_CH8_TX_DST_SXA6_RX_TX = 46,
+	DB8500_DMA_DEV47_SLIM0_CH9_TX_DST_SXA7_RX_TX = 47,
+	DB8500_DMA_DEV48_CAC1_TX  = 48,
+	DB8500_DMA_DEV49_CAC1_TX_HAC1_TX = 49,
+	DB8500_DMA_DEV50_HAC1_TX = 50,
+	DB8500_DMA_MEMCPY_TX_0 = 51,
+	DB8500_DMA_DEV52_SLIM1_CH4_TX_HSI_TX_CH4 = 52,
+	DB8500_DMA_DEV53_SLIM1_CH5_TX_HSI_TX_CH5 = 53,
+	DB8500_DMA_DEV54_SLIM1_CH6_TX_HSI_TX_CH6 = 54,
+	DB8500_DMA_DEV55_SLIM1_CH7_TX_HSI_TX_CH7 = 55,
+	DB8500_DMA_MEMCPY_TX_1 = 56,
+	DB8500_DMA_MEMCPY_TX_2 = 57,
+	DB8500_DMA_MEMCPY_TX_3 = 58,
+	DB8500_DMA_MEMCPY_TX_4 = 59,
+	DB8500_DMA_MEMCPY_TX_5 = 60,
+	DB8500_DMA_DEV61_CAC0_TX = 61,
+	DB8500_DMA_DEV62_CAC0_TX_HAC0_TX = 62,
+	DB8500_DMA_DEV63_HAC0_TX = 63,
 };
 
 #endif
diff --git a/arch/arm/mach-versatile/include/mach/debug-macro.S b/arch/arm/mach-versatile/include/mach/debug-macro.S
index 6fea719..eb2cf7d 100644
--- a/arch/arm/mach-versatile/include/mach/debug-macro.S
+++ b/arch/arm/mach-versatile/include/mach/debug-macro.S
@@ -11,13 +11,11 @@
  *
 */
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx,      #0x10000000
-		movne	\rx,      #0xf1000000	@ virtual base
-		orr	\rx, \rx, #0x001F0000
-		orr	\rx, \rx, #0x00001000
+		.macro	addruart, rp, rv
+		mov	\rp,      #0x001F0000
+		orr	\rp, \rp, #0x00001000
+		orr	\rv, \rp, #0xf1000000	@ virtual base
+		orr	\rp, \rp,  #0x10000000	@ physical base
 		.endm
 
 #include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-versatile/include/mach/vmalloc.h b/arch/arm/mach-versatile/include/mach/vmalloc.h
index 427e361..ebd8a25 100644
--- a/arch/arm/mach-versatile/include/mach/vmalloc.h
+++ b/arch/arm/mach-versatile/include/mach/vmalloc.h
@@ -18,4 +18,4 @@
  * 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		(PAGE_OFFSET + 0x18000000)
+#define VMALLOC_END		0xd8000000
diff --git a/arch/arm/mach-versatile/versatile_ab.c b/arch/arm/mach-versatile/versatile_ab.c
index bb8ec77..aa9730f 100644
--- a/arch/arm/mach-versatile/versatile_ab.c
+++ b/arch/arm/mach-versatile/versatile_ab.c
@@ -35,8 +35,6 @@
 
 MACHINE_START(VERSATILE_AB, "ARM-Versatile AB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.phys_io	= 0x101f1000,
-	.io_pg_offst	= ((0xf11f1000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= versatile_map_io,
 	.init_irq	= versatile_init_irq,
diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c
index 239cd30..bf46964 100644
--- a/arch/arm/mach-versatile/versatile_pb.c
+++ b/arch/arm/mach-versatile/versatile_pb.c
@@ -108,8 +108,6 @@
 
 MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.phys_io	= 0x101f1000,
-	.io_pg_offst	= ((0xf11f1000) >> 18) & 0xfffc,
 	.boot_params	= 0x00000100,
 	.map_io		= versatile_map_io,
 	.init_irq	= versatile_init_irq,
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 577df6c..c2e405a 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -68,7 +68,7 @@
 }
 
 #if 0
-static void ct_ca9x4_timer_init(void)
+static void __init ct_ca9x4_timer_init(void)
 {
 	writel(0, MMIO_P2V(CT_CA9X4_TIMER0) + TIMER_CTRL);
 	writel(0, MMIO_P2V(CT_CA9X4_TIMER1) + TIMER_CTRL);
@@ -222,12 +222,18 @@
 	.resource	= pmu_resources,
 };
 
-static void ct_ca9x4_init(void)
+static void __init ct_ca9x4_init(void)
 {
 	int i;
 
 #ifdef CONFIG_CACHE_L2X0
-	l2x0_init(MMIO_P2V(CT_CA9X4_L2CC), 0x00000000, 0xfe0fffff);
+	void __iomem *l2x0_base = MMIO_P2V(CT_CA9X4_L2CC);
+
+	/* set RAM latencies to 1 cycle for this core tile. */
+	writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL);
+	writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL);
+
+	l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
 #endif
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
@@ -239,8 +245,6 @@
 }
 
 MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4")
-	.phys_io	= V2M_UART0 & SECTION_MASK,
-	.io_pg_offst	= (__MMIO_P2V(V2M_UART0) >> 18) & 0xfffc,
 	.boot_params	= PHYS_OFFSET + 0x00000100,
 	.map_io		= ct_ca9x4_map_io,
 	.init_irq	= ct_ca9x4_init_irq,
diff --git a/arch/arm/mach-vexpress/include/mach/debug-macro.S b/arch/arm/mach-vexpress/include/mach/debug-macro.S
index 5167e2a..050d65e 100644
--- a/arch/arm/mach-vexpress/include/mach/debug-macro.S
+++ b/arch/arm/mach-vexpress/include/mach/debug-macro.S
@@ -12,12 +12,10 @@
 
 #define DEBUG_LL_UART_OFFSET	0x00009000
 
-		.macro	addruart,rx,tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx,      #0x10000000
-		movne	\rx,      #0xf8000000	@ virtual base
-		orr	\rx, \rx, #DEBUG_LL_UART_OFFSET
+		.macro	addruart,rp,rv
+		mov	\rp, #DEBUG_LL_UART_OFFSET
+		orr	\rv, \rp, #0xf8000000	@ virtual base
+		orr	\rp, \rp, #0x10000000	@ physical base
 		.endm
 
 #include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-vexpress/include/mach/smp.h b/arch/arm/mach-vexpress/include/mach/smp.h
index 72a9621..5a6da4f 100644
--- a/arch/arm/mach-vexpress/include/mach/smp.h
+++ b/arch/arm/mach-vexpress/include/mach/smp.h
@@ -2,14 +2,7 @@
 #define __MACH_SMP_H
 
 #include <asm/hardware/gic.h>
-
-#define hard_smp_processor_id()				\
-	({						\
-		unsigned int cpunum;			\
-		__asm__("mrc p15, 0, %0, c0, c0, 5"	\
-			: "=r" (cpunum));		\
-		cpunum &= 0x0F;				\
-	})
+#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 817f0ad..7eaa232 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -48,7 +48,7 @@
 }
 
 
-static void v2m_timer_init(void)
+static void __init v2m_timer_init(void)
 {
 	writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL);
 	writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL);
diff --git a/arch/arm/mach-w90x900/mach-nuc910evb.c b/arch/arm/mach-w90x900/mach-nuc910evb.c
index ec05bda..30fccde 100644
--- a/arch/arm/mach-w90x900/mach-nuc910evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc910evb.c
@@ -34,8 +34,6 @@
 
 MACHINE_START(W90P910EVB, "W90P910EVB")
 	/* Maintainer: Wan ZongShun */
-	.phys_io	= W90X900_PA_UART,
-	.io_pg_offst	= (((u32)W90X900_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= 0,
 	.map_io		= nuc910evb_map_io,
 	.init_irq	= nuc900_init_irq,
diff --git a/arch/arm/mach-w90x900/mach-nuc950evb.c b/arch/arm/mach-w90x900/mach-nuc950evb.c
index 04d295f..590c99b 100644
--- a/arch/arm/mach-w90x900/mach-nuc950evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc950evb.c
@@ -37,8 +37,6 @@
 
 MACHINE_START(W90P950EVB, "W90P950EVB")
 	/* Maintainer: Wan ZongShun */
-	.phys_io	= W90X900_PA_UART,
-	.io_pg_offst	= (((u32)W90X900_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= 0,
 	.map_io		= nuc950evb_map_io,
 	.init_irq	= nuc900_init_irq,
diff --git a/arch/arm/mach-w90x900/mach-nuc960evb.c b/arch/arm/mach-w90x900/mach-nuc960evb.c
index e3a46f1..e09c645 100644
--- a/arch/arm/mach-w90x900/mach-nuc960evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc960evb.c
@@ -34,8 +34,6 @@
 
 MACHINE_START(W90N960EVB, "W90N960EVB")
 	/* Maintainer: Wan ZongShun */
-	.phys_io	= W90X900_PA_UART,
-	.io_pg_offst	= (((u32)W90X900_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= 0,
 	.map_io		= nuc960evb_map_io,
 	.init_irq	= nuc900_init_irq,
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index d073b64..724ba3b 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -885,8 +885,23 @@
 
 	if (ai_usermode & UM_SIGNAL)
 		force_sig(SIGBUS, current);
-	else
-		set_cr(cr_no_alignment);
+	else {
+		/*
+		 * We're about to disable the alignment trap and return to
+		 * user space.  But if an interrupt occurs before actually
+		 * reaching user space, then the IRQ vector entry code will
+		 * notice that we were still in kernel space and therefore
+		 * the alignment trap won't be re-enabled in that case as it
+		 * is presumed to be always on from kernel space.
+		 * Let's prevent that race by disabling interrupts here (they
+		 * are disabled on the way back to user space anyway in
+		 * entry-common.S) and disable the alignment trap only if
+		 * there is no work pending for this thread.
+		 */
+		raw_local_irq_disable();
+		if (!(current_thread_info()->flags & _TIF_WORK_MASK))
+			set_cr(cr_no_alignment);
+	}
 
 	return 0;
 }
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 86aa689..99fa688 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -21,18 +21,22 @@
 #define D_CACHE_LINE_SIZE	32
 #define BTB_FLUSH_SIZE		8
 
-#ifdef CONFIG_ARM_ERRATA_411920
 /*
- * Invalidate the entire I cache (this code is a workaround for the ARM1136
- * erratum 411920 - Invalidate Instruction Cache operation can fail. This
- * erratum is present in 1136, 1156 and 1176. It does not affect the MPCore.
+ *	v6_flush_icache_all()
  *
- * Registers:
- *   r0 - set to 0
- *   r1 - corrupted
+ *	Flush the whole I-cache.
+ *
+ *	ARM1136 erratum 411920 - Invalidate Instruction Cache operation can fail.
+ *	This erratum is present in 1136, 1156 and 1176. It does not affect the
+ *	MPCore.
+ *
+ *	Registers:
+ *	r0 - set to 0
+ *	r1 - corrupted
  */
-ENTRY(v6_icache_inval_all)
+ENTRY(v6_flush_icache_all)
 	mov	r0, #0
+#ifdef CONFIG_ARM_ERRATA_411920
 	mrs	r1, cpsr
 	cpsid	ifa				@ disable interrupts
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate entire I-cache
@@ -43,8 +47,11 @@
 	.rept	11				@ ARM Ltd recommends at least
 	nop					@ 11 NOPs
 	.endr
-	mov	pc, lr
+#else
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I-cache
 #endif
+	mov	pc, lr
+ENDPROC(v6_flush_icache_all)
 
 /*
  *	v6_flush_cache_all()
@@ -60,7 +67,7 @@
 #ifndef CONFIG_ARM_ERRATA_411920
 	mcr	p15, 0, r0, c7, c5, 0		@ I+BTB cache invalidate
 #else
-	b	v6_icache_inval_all
+	b	v6_flush_icache_all
 #endif
 #else
 	mcr	p15, 0, r0, c7, c15, 0		@ Cache clean+invalidate
@@ -138,7 +145,7 @@
 #ifndef CONFIG_ARM_ERRATA_411920
 	mcr	p15, 0, r0, c7, c5, 0		@ I+BTB cache invalidate
 #else
-	b	v6_icache_inval_all
+	b	v6_flush_icache_all
 #endif
 #else
 	mcr	p15, 0, r0, c7, c5, 6		@ invalidate BTB
@@ -312,6 +319,7 @@
 
 	.type	v6_cache_fns, #object
 ENTRY(v6_cache_fns)
+	.long	v6_flush_icache_all
 	.long	v6_flush_kern_cache_all
 	.long	v6_flush_user_cache_all
 	.long	v6_flush_user_cache_range
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 37c8157..a3ebf7a 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -18,6 +18,21 @@
 #include "proc-macros.S"
 
 /*
+ *	v7_flush_icache_all()
+ *
+ *	Flush the whole I-cache.
+ *
+ *	Registers:
+ *	r0 - set to 0
+ */
+ENTRY(v7_flush_icache_all)
+	mov	r0, #0
+	ALT_SMP(mcr	p15, 0, r0, c7, c1, 0)		@ invalidate I-cache inner shareable
+	ALT_UP(mcr	p15, 0, r0, c7, c5, 0)		@ I+BTB cache invalidate
+	mov	pc, lr
+ENDPROC(v7_flush_icache_all)
+
+/*
  *	v7_flush_dcache_all()
  *
  *	Flush the whole D-cache.
@@ -91,11 +106,8 @@
  THUMB(	stmfd	sp!, {r4-r7, r9-r11, lr}	)
 	bl	v7_flush_dcache_all
 	mov	r0, #0
-#ifdef CONFIG_SMP
-	mcr	p15, 0, r0, c7, c1, 0		@ invalidate I-cache inner shareable
-#else
-	mcr	p15, 0, r0, c7, c5, 0		@ I+BTB cache invalidate
-#endif
+	ALT_SMP(mcr	p15, 0, r0, c7, c1, 0)	@ invalidate I-cache inner shareable
+	ALT_UP(mcr	p15, 0, r0, c7, c5, 0)	@ I+BTB cache invalidate
  ARM(	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
  THUMB(	ldmfd	sp!, {r4-r7, r9-r11, lr}	)
 	mov	pc, lr
@@ -171,11 +183,8 @@
 	cmp	r0, r1
 	blo	1b
 	mov	r0, #0
-#ifdef CONFIG_SMP
-	mcr	p15, 0, r0, c7, c1, 6		@ invalidate BTB Inner Shareable
-#else
-	mcr	p15, 0, r0, c7, c5, 6		@ invalidate BTB
-#endif
+	ALT_SMP(mcr	p15, 0, r0, c7, c1, 6)	@ invalidate BTB Inner Shareable
+	ALT_UP(mcr	p15, 0, r0, c7, c5, 6)	@ invalidate BTB
 	dsb
 	isb
 	mov	pc, lr
@@ -309,6 +318,7 @@
 
 	.type	v7_cache_fns, #object
 ENTRY(v7_cache_fns)
+	.long	v7_flush_icache_all
 	.long	v7_flush_kern_cache_all
 	.long	v7_flush_user_cache_all
 	.long	v7_flush_user_cache_range
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
index 598c51a..b806151 100644
--- a/arch/arm/mm/copypage-v4mc.c
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -73,7 +73,7 @@
 {
 	void *kto = kmap_atomic(to, KM_USER1);
 
-	if (test_and_clear_bit(PG_dcache_dirty, &from->flags))
+	if (!test_and_set_bit(PG_dcache_clean, &from->flags))
 		__flush_dcache_page(page_mapping(from), from);
 
 	spin_lock(&minicache_lock);
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index f55fa10..bdba6c6 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -79,7 +79,7 @@
 	unsigned int offset = CACHE_COLOUR(vaddr);
 	unsigned long kfrom, kto;
 
-	if (test_and_clear_bit(PG_dcache_dirty, &from->flags))
+	if (!test_and_set_bit(PG_dcache_clean, &from->flags))
 		__flush_dcache_page(page_mapping(from), from);
 
 	/* FIXME: not highmem safe */
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
index 9920c0a..649bbcd 100644
--- a/arch/arm/mm/copypage-xscale.c
+++ b/arch/arm/mm/copypage-xscale.c
@@ -95,7 +95,7 @@
 {
 	void *kto = kmap_atomic(to, KM_USER1);
 
-	if (test_and_clear_bit(PG_dcache_dirty, &from->flags))
+	if (!test_and_set_bit(PG_dcache_clean, &from->flags))
 		__flush_dcache_page(page_mapping(from), from);
 
 	spin_lock(&minicache_lock);
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 4bc43e5..e4dd064 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -523,6 +523,12 @@
 		outer_inv_range(paddr, paddr + size);
 
 	dma_cache_maint_page(page, off, size, dir, dmac_unmap_area);
+
+	/*
+	 * Mark the D-cache clean for this page to avoid extra flushing.
+	 */
+	if (dir != DMA_TO_DEVICE && off == 0 && size >= PAGE_SIZE)
+		set_bit(PG_dcache_clean, &page->flags);
 }
 EXPORT_SYMBOL(___dma_page_dev_to_cpu);
 
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 9b906de..8440d95 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -28,6 +28,7 @@
 
 static unsigned long shared_pte_mask = L_PTE_MT_BUFFERABLE;
 
+#if __LINUX_ARM_ARCH__ < 6
 /*
  * We take the easy way out of this problem - we make the
  * PTE uncacheable.  However, we leave the write buffer on.
@@ -141,7 +142,7 @@
  * a page table, or changing an existing PTE.  Basically, there are two
  * things that we need to take care of:
  *
- *  1. If PG_dcache_dirty is set for the page, we need to ensure
+ *  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
@@ -168,10 +169,8 @@
 		return;
 
 	mapping = page_mapping(page);
-#ifndef CONFIG_SMP
-	if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
+	if (!test_and_set_bit(PG_dcache_clean, &page->flags))
 		__flush_dcache_page(mapping, page);
-#endif
 	if (mapping) {
 		if (cache_is_vivt())
 			make_coherent(mapping, vma, addr, ptep, pfn);
@@ -179,6 +178,7 @@
 			__flush_icache_all();
 	}
 }
+#endif	/* __LINUX_ARM_ARCH__ < 6 */
 
 /*
  * Check whether the write buffer has physical address aliasing
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 23b0b03..1e21e12 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -581,6 +581,19 @@
 	{ do_bad,		SIGBUS,  0,		"unknown 31"			   },
 };
 
+void __init
+hook_ifault_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(ifsr_info))
+		BUG();
+
+	ifsr_info[nr].fn   = fn;
+	ifsr_info[nr].sig  = sig;
+	ifsr_info[nr].code = code;
+	ifsr_info[nr].name = name;
+}
+
 asmlinkage void __exception
 do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
 {
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index c6844cb..391ffae 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -17,6 +17,7 @@
 #include <asm/smp_plat.h>
 #include <asm/system.h>
 #include <asm/tlbflush.h>
+#include <asm/smp_plat.h>
 
 #include "mm.h"
 
@@ -39,6 +40,18 @@
 	    : "cc");
 }
 
+static void flush_icache_alias(unsigned long pfn, unsigned long vaddr, unsigned long len)
+{
+	unsigned long colour = CACHE_COLOUR(vaddr);
+	unsigned long offset = vaddr & (PAGE_SIZE - 1);
+	unsigned long to;
+
+	set_pte_ext(TOP_PTE(ALIAS_FLUSH_START) + colour, pfn_pte(pfn, PAGE_KERNEL), 0);
+	to = ALIAS_FLUSH_START + (colour << PAGE_SHIFT) + offset;
+	flush_tlb_kernel_page(to);
+	flush_icache_range(to, to + len);
+}
+
 void flush_cache_mm(struct mm_struct *mm)
 {
 	if (cache_is_vivt()) {
@@ -89,16 +102,16 @@
 	if (vma->vm_flags & VM_EXEC && icache_is_vivt_asid_tagged())
 		__flush_icache_all();
 }
+
 #else
-#define flush_pfn_alias(pfn,vaddr)	do { } while (0)
+#define flush_pfn_alias(pfn,vaddr)		do { } while (0)
+#define flush_icache_alias(pfn,vaddr,len)	do { } while (0)
 #endif
 
-#ifdef CONFIG_SMP
 static void flush_ptrace_access_other(void *args)
 {
 	__flush_icache_all();
 }
-#endif
 
 static
 void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
@@ -118,15 +131,16 @@
 		return;
 	}
 
-	/* VIPT non-aliasing cache */
+	/* VIPT non-aliasing D-cache */
 	if (vma->vm_flags & VM_EXEC) {
 		unsigned long addr = (unsigned long)kaddr;
-		__cpuc_coherent_kern_range(addr, addr + len);
-#ifdef CONFIG_SMP
+		if (icache_is_vipt_aliasing())
+			flush_icache_alias(page_to_pfn(page), uaddr, len);
+		else
+			__cpuc_coherent_kern_range(addr, addr + len);
 		if (cache_ops_need_broadcast())
 			smp_call_function(flush_ptrace_access_other,
 					  NULL, 1);
-#endif
 	}
 }
 
@@ -215,6 +229,36 @@
 	flush_dcache_mmap_unlock(mapping);
 }
 
+#if __LINUX_ARM_ARCH__ >= 6
+void __sync_icache_dcache(pte_t pteval)
+{
+	unsigned long pfn;
+	struct page *page;
+	struct address_space *mapping;
+
+	if (!pte_present_user(pteval))
+		return;
+	if (cache_is_vipt_nonaliasing() && !pte_exec(pteval))
+		/* only flush non-aliasing VIPT caches for exec mappings */
+		return;
+	pfn = pte_pfn(pteval);
+	if (!pfn_valid(pfn))
+		return;
+
+	page = pfn_to_page(pfn);
+	if (cache_is_vipt_aliasing())
+		mapping = page_mapping(page);
+	else
+		mapping = NULL;
+
+	if (!test_and_set_bit(PG_dcache_clean, &page->flags))
+		__flush_dcache_page(mapping, page);
+	/* pte_exec() already checked above for non-aliasing VIPT cache */
+	if (cache_is_vipt_nonaliasing() || pte_exec(pteval))
+		__flush_icache_all();
+}
+#endif
+
 /*
  * Ensure cache coherency between kernel mapping and userspace mapping
  * of this page.
@@ -246,17 +290,16 @@
 
 	mapping = page_mapping(page);
 
-#ifndef CONFIG_SMP
-	if (!PageHighMem(page) && mapping && !mapping_mapped(mapping))
-		set_bit(PG_dcache_dirty, &page->flags);
-	else
-#endif
-	{
+	if (!cache_ops_need_broadcast() &&
+	    mapping && !mapping_mapped(mapping))
+		clear_bit(PG_dcache_clean, &page->flags);
+	else {
 		__flush_dcache_page(mapping, page);
 		if (mapping && cache_is_vivt())
 			__flush_dcache_aliases(mapping, page);
 		else if (mapping)
 			__flush_icache_all();
+		set_bit(PG_dcache_clean, &page->flags);
 	}
 }
 EXPORT_SYMBOL(flush_dcache_page);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 7185b00..7fd9b5e 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -150,6 +150,7 @@
 static void __init arm_bootmem_init(struct meminfo *mi,
 	unsigned long start_pfn, unsigned long end_pfn)
 {
+	struct memblock_region *reg;
 	unsigned int boot_pages;
 	phys_addr_t bitmap;
 	pg_data_t *pgdat;
@@ -180,13 +181,13 @@
 	/*
 	 * Reserve the memblock reserved regions in bootmem.
 	 */
-	for (i = 0; i < memblock.reserved.cnt; i++) {
-		phys_addr_t start = memblock_start_pfn(&memblock.reserved, i);
-		if (start >= start_pfn &&
-		    memblock_end_pfn(&memblock.reserved, i) <= end_pfn)
+	for_each_memblock(reserved, reg) {
+		phys_addr_t start = memblock_region_reserved_base_pfn(reg);
+		phys_addr_t end = memblock_region_reserved_end_pfn(reg);
+		if (start >= start_pfn && end <= end_pfn)
 			reserve_bootmem_node(pgdat, __pfn_to_phys(start),
-				memblock_size_bytes(&memblock.reserved, i),
-				BOOTMEM_DEFAULT);
+					     (end - start) << PAGE_SHIFT,
+					     BOOTMEM_DEFAULT);
 	}
 }
 
@@ -237,20 +238,7 @@
 #ifndef CONFIG_SPARSEMEM
 int pfn_valid(unsigned long pfn)
 {
-	struct memblock_region *mem = &memblock.memory;
-	unsigned int left = 0, right = mem->cnt;
-
-	do {
-		unsigned int mid = (right + left) / 2;
-
-		if (pfn < memblock_start_pfn(mem, mid))
-			right = mid;
-		else if (pfn >= memblock_end_pfn(mem, mid))
-			left = mid + 1;
-		else
-			return 1;
-	} while (left < right);
-	return 0;
+	return memblock_is_memory(pfn << PAGE_SHIFT);
 }
 EXPORT_SYMBOL(pfn_valid);
 
@@ -260,10 +248,11 @@
 #else
 static void arm_memory_present(void)
 {
-	int i;
-	for (i = 0; i < memblock.memory.cnt; i++)
-		memory_present(0, memblock_start_pfn(&memblock.memory, i),
-				  memblock_end_pfn(&memblock.memory, i));
+	struct memblock_region *reg;
+
+	for_each_memblock(memory, reg)
+		memory_present(0, memblock_region_memory_base_pfn(reg),
+			       memblock_region_memory_end_pfn(reg));
 }
 #endif
 
@@ -277,7 +266,7 @@
 
 	/* Register the kernel text, kernel data and initrd with memblock. */
 #ifdef CONFIG_XIP_KERNEL
-	memblock_reserve(__pa(_data), _end - _data);
+	memblock_reserve(__pa(_sdata), _end - _sdata);
 #else
 	memblock_reserve(__pa(_stext), _end - _stext);
 #endif
@@ -545,7 +534,7 @@
 
 			MLK_ROUNDUP(__init_begin, __init_end),
 			MLK_ROUNDUP(_text, _etext),
-			MLK_ROUNDUP(_data, _edata));
+			MLK_ROUNDUP(_sdata, _edata));
 
 #undef MLK
 #undef MLM
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index ab50627..17e7b0b 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -204,8 +204,12 @@
 	/*
 	 * Don't allow RAM to be mapped - this causes problems with ARMv6+
 	 */
-	if (WARN_ON(pfn_valid(pfn)))
-		return NULL;
+	if (pfn_valid(pfn)) {
+		printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory.  This leads\n"
+		       KERN_WARNING "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n"
+		       KERN_WARNING "will fail in the next kernel release.  Please fix your driver.\n");
+		WARN_ON(1);
+	}
 
 	type = get_mem_type(mtype);
 	if (!type)
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 4f5b396..b0a9830 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -144,3 +144,25 @@
 {
 	return !(pfn + (size >> PAGE_SHIFT) > 0x00100000);
 }
+
+#ifdef CONFIG_STRICT_DEVMEM
+
+#include <linux/ioport.h>
+
+/*
+ * devmem_is_allowed() checks to see if /dev/mem access to a certain
+ * address is valid. The argument is a physical page number.
+ * We mimic x86 here by disallowing access to system RAM as well as
+ * device-exclusive MMIO regions. This effectively disable read()/write()
+ * on /dev/mem.
+ */
+int devmem_is_allowed(unsigned long pfn)
+{
+	if (iomem_is_exclusive(pfn << PAGE_SHIFT))
+		return 0;
+	if (!page_is_ram(pfn))
+		return 1;
+	return 0;
+}
+
+#endif
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 6e1c4f6..c32f731 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -15,6 +15,7 @@
 #include <linux/nodemask.h>
 #include <linux/memblock.h>
 #include <linux/sort.h>
+#include <linux/fs.h>
 
 #include <asm/cputype.h>
 #include <asm/sections.h>
@@ -246,6 +247,9 @@
 		.domain    = DOMAIN_USER,
 	},
 	[MT_MEMORY] = {
+		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+				L_PTE_WRITE | L_PTE_EXEC,
+		.prot_l1   = PMD_TYPE_TABLE,
 		.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
 		.domain    = DOMAIN_KERNEL,
 	},
@@ -254,6 +258,9 @@
 		.domain    = DOMAIN_KERNEL,
 	},
 	[MT_MEMORY_NONCACHED] = {
+		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+				L_PTE_WRITE | L_PTE_EXEC | L_PTE_MT_BUFFERABLE,
+		.prot_l1   = PMD_TYPE_TABLE,
 		.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
 		.domain    = DOMAIN_KERNEL,
 	},
@@ -303,9 +310,8 @@
 			cachepolicy = CPOLICY_WRITEBACK;
 		ecc_mask = 0;
 	}
-#ifdef CONFIG_SMP
-	cachepolicy = CPOLICY_WRITEALLOC;
-#endif
+	if (is_smp())
+		cachepolicy = CPOLICY_WRITEALLOC;
 
 	/*
 	 * Strip out features not present on earlier architectures.
@@ -399,21 +405,22 @@
 	cp = &cache_policies[cachepolicy];
 	vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
 
-#ifndef CONFIG_SMP
 	/*
 	 * Only use write-through for non-SMP systems
 	 */
-	if (cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH)
+	if (!is_smp() && cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH)
 		vecs_pgprot = cache_policies[CPOLICY_WRITETHROUGH].pte;
-#endif
 
 	/*
 	 * Enable CPU-specific coherency if supported.
 	 * (Only available on XSC3 at the moment.)
 	 */
-	if (arch_is_coherent() && cpu_is_xsc3())
+	if (arch_is_coherent() && cpu_is_xsc3()) {
 		mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-
+		mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
+		mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
+		mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
+	}
 	/*
 	 * ARMv6 and above have extended page tables.
 	 */
@@ -426,20 +433,23 @@
 		mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
 		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
 
-#ifdef CONFIG_SMP
-		/*
-		 * Mark memory with the "shared" attribute for SMP systems
-		 */
-		user_pgprot |= L_PTE_SHARED;
-		kern_pgprot |= L_PTE_SHARED;
-		vecs_pgprot |= L_PTE_SHARED;
-		mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
-		mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
-		mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
-		mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
-		mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-		mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
-#endif
+		if (is_smp()) {
+			/*
+			 * Mark memory with the "shared" attribute
+			 * for SMP systems
+			 */
+			user_pgprot |= L_PTE_SHARED;
+			kern_pgprot |= L_PTE_SHARED;
+			vecs_pgprot |= L_PTE_SHARED;
+			mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
+			mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
+			mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
+			mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
+			mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+			mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
+			mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
+			mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
+		}
 	}
 
 	/*
@@ -475,6 +485,8 @@
 	mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
 	mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
 	mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
+	mem_types[MT_MEMORY].prot_pte |= kern_pgprot;
+	mem_types[MT_MEMORY_NONCACHED].prot_sect |= ecc_mask;
 	mem_types[MT_ROM].prot_sect |= cp->pmd;
 
 	switch (cp->pmd) {
@@ -498,6 +510,19 @@
 	}
 }
 
+#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+			      unsigned long size, pgprot_t vma_prot)
+{
+	if (!pfn_valid(pfn))
+		return pgprot_noncached(vma_prot);
+	else if (file->f_flags & O_SYNC)
+		return pgprot_writecombine(vma_prot);
+	return vma_prot;
+}
+EXPORT_SYMBOL(phys_mem_access_prot);
+#endif
+
 #define vectors_base()	(vectors_high() ? 0xffff0000 : 0)
 
 static void __init *early_alloc(unsigned long sz)
@@ -802,8 +827,7 @@
 			 * rather difficult.
 			 */
 			reason = "with VIPT aliasing cache";
-#ifdef CONFIG_SMP
-		} else if (tlb_ops_need_broadcast()) {
+		} 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
@@ -813,7 +837,6 @@
 			 *   (must not be called with irqs off)
 			 */
 			reason = "without hardware TLB ops broadcasting";
-#endif
 		}
 		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 203a4e9..a6f5f84 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -430,7 +430,7 @@
 #endif /* CONFIG_MMU */
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm1020_setup, #function
 __arm1020_setup:
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index 1a511e7..afc06b9 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -412,7 +412,7 @@
 #endif /* CONFIG_MMU */
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm1020e_setup, #function
 __arm1020e_setup:
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 1ffa4eb..8915e0b 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -394,7 +394,7 @@
 #endif /* CONFIG_MMU */
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm1022_setup, #function
 __arm1022_setup:
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 5697c34..ff446c5 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -384,7 +384,7 @@
 	mov	pc, lr
 
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm1026_setup, #function
 __arm1026_setup:
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 64e0b32..6a7be18 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -238,7 +238,7 @@
 		mcr	p15, 0, r1, c1, c0, 0		@ turn off MMU etc
 		mov	pc, r0
 
-		__INIT
+		__CPUINIT
 
 		.type	__arm6_setup, #function
 __arm6_setup:	mov	r0, #0
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index 9d96824..c285395 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -113,7 +113,7 @@
 		mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
 		mov	pc, r0
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm710_setup, #function
 __arm710_setup:
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
index 6c1a9ab..38b27dc 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -55,7 +55,7 @@
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
 	mov	pc, r0
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm740_setup, #function
 __arm740_setup:
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
index 6a850db..0c9786d 100644
--- a/arch/arm/mm/proc-arm7tdmi.S
+++ b/arch/arm/mm/proc-arm7tdmi.S
@@ -46,7 +46,7 @@
 ENTRY(cpu_arm7tdmi_reset)
 		mov	pc, r0
 
-		__INIT
+		__CPUINIT
 
 		.type	__arm7tdmi_setup, #function
 __arm7tdmi_setup:
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 86f80aa..fecf570 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -375,7 +375,7 @@
 #endif
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm920_setup, #function
 __arm920_setup:
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index f76ce9b..e3cbf87 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -379,7 +379,7 @@
 #endif /* CONFIG_MMU */
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm922_setup, #function
 __arm922_setup:
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index 657bd3f..572424c 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -428,7 +428,7 @@
 #endif /* CONFIG_MMU */
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm925_setup, #function
 __arm925_setup:
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 73f1f3c..63d168b 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -389,7 +389,7 @@
 #endif
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm926_setup, #function
 __arm926_setup:
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index fffb061..f6a6282 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -264,7 +264,7 @@
 	.long	arm940_dma_unmap_area
 	.long	arm940_dma_flush_range
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm940_setup, #function
 __arm940_setup:
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 249a605..ea2e7f2 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -317,7 +317,7 @@
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__arm946_setup, #function
 __arm946_setup:
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
index db47566..db67e31 100644
--- a/arch/arm/mm/proc-arm9tdmi.S
+++ b/arch/arm/mm/proc-arm9tdmi.S
@@ -46,7 +46,7 @@
 ENTRY(cpu_arm9tdmi_reset)
 		mov	pc, r0
 
-		__INIT
+		__CPUINIT
 
 		.type	__arm9tdmi_setup, #function
 __arm9tdmi_setup:
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
index 7803fdf..7c9ad62 100644
--- a/arch/arm/mm/proc-fa526.S
+++ b/arch/arm/mm/proc-fa526.S
@@ -134,7 +134,7 @@
 #endif
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__fa526_setup, #function
 __fa526_setup:
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index b304d01..578da69 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -494,7 +494,7 @@
 #endif
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__feroceon_setup, #function
 __feroceon_setup:
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 5f6892f..4458ee6 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -338,7 +338,7 @@
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__mohawk_setup, #function
 __mohawk_setup:
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index a201eb0..5aa8d59 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -156,7 +156,7 @@
 #endif
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__sa110_setup, #function
 __sa110_setup:
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 7ddc480..2ac4e6f 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -169,7 +169,7 @@
 #endif
 	mov	pc, lr
 
-	__INIT
+	__CPUINIT
 
 	.type	__sa1100_setup, #function
 __sa1100_setup:
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 22aac85..59a7e1f 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -30,13 +30,10 @@
 #define TTB_RGN_WT	(2 << 3)
 #define TTB_RGN_WB	(3 << 3)
 
-#ifndef CONFIG_SMP
-#define TTB_FLAGS	TTB_RGN_WBWA
-#define PMD_FLAGS	PMD_SECT_WB
-#else
-#define TTB_FLAGS	TTB_RGN_WBWA|TTB_S
-#define PMD_FLAGS	PMD_SECT_WBWA|PMD_SECT_S
-#endif
+#define TTB_FLAGS_UP	TTB_RGN_WBWA
+#define PMD_FLAGS_UP	PMD_SECT_WB
+#define TTB_FLAGS_SMP	TTB_RGN_WBWA|TTB_S
+#define PMD_FLAGS_SMP	PMD_SECT_WBWA|PMD_SECT_S
 
 ENTRY(cpu_v6_proc_init)
 	mov	pc, lr
@@ -97,7 +94,8 @@
 #ifdef CONFIG_MMU
 	mov	r2, #0
 	ldr	r1, [r1, #MM_CONTEXT_ID]	@ get mm->context.id
-	orr	r0, r0, #TTB_FLAGS
+	ALT_SMP(orr	r0, r0, #TTB_FLAGS_SMP)
+	ALT_UP(orr	r0, r0, #TTB_FLAGS_UP)
 	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
 	mcr	p15, 0, r2, c7, c10, 4		@ drain write buffer
 	mcr	p15, 0, r0, c2, c0, 0		@ set TTB 0
@@ -137,7 +135,7 @@
 
 	.align
 
-	__INIT
+	__CPUINIT
 
 /*
  *	__v6_setup
@@ -156,9 +154,11 @@
  */
 __v6_setup:
 #ifdef CONFIG_SMP
-	mrc	p15, 0, r0, c1, c0, 1		@ Enable SMP/nAMP mode
+	ALT_SMP(mrc	p15, 0, r0, c1, c0, 1)	@ Enable SMP/nAMP mode
+	ALT_UP(nop)
 	orr	r0, r0, #0x20
-	mcr	p15, 0, r0, c1, c0, 1
+	ALT_SMP(mcr	p15, 0, r0, c1, c0, 1)
+	ALT_UP(nop)
 #endif
 
 	mov	r0, #0
@@ -169,7 +169,8 @@
 #ifdef CONFIG_MMU
 	mcr	p15, 0, r0, c8, c7, 0		@ invalidate I + D TLBs
 	mcr	p15, 0, r0, c2, c0, 2		@ TTB control register
-	orr	r4, r4, #TTB_FLAGS
+	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
 #endif /* CONFIG_MMU */
 	adr	r5, v6_crval
@@ -192,6 +193,8 @@
 v6_crval:
 	crval	clear=0x01e0fb7f, mmuset=0x00c0387d, ucset=0x00c0187c
 
+	__INITDATA
+
 	.type	v6_processor_functions, #object
 ENTRY(v6_processor_functions)
 	.word	v6_early_abort
@@ -205,6 +208,8 @@
 	.word	cpu_v6_set_pte_ext
 	.size	v6_processor_functions, . - v6_processor_functions
 
+	.section ".rodata"
+
 	.type	cpu_arch_name, #object
 cpu_arch_name:
 	.asciz	"armv6"
@@ -225,10 +230,16 @@
 __v6_proc_info:
 	.long	0x0007b000
 	.long	0x0007f000
-	.long   PMD_TYPE_SECT | \
+	ALT_SMP(.long \
+		PMD_TYPE_SECT | \
 		PMD_SECT_AP_WRITE | \
 		PMD_SECT_AP_READ | \
-		PMD_FLAGS
+		PMD_FLAGS_SMP)
+	ALT_UP(.long \
+		PMD_TYPE_SECT | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ | \
+		PMD_FLAGS_UP)
 	.long   PMD_TYPE_SECT | \
 		PMD_SECT_XN | \
 		PMD_SECT_AP_WRITE | \
@@ -249,10 +260,16 @@
 __pj4_v6_proc_info:
 	.long	0x560f5810
 	.long	0xff0ffff0
-	.long   PMD_TYPE_SECT | \
+	ALT_SMP(.long \
+		PMD_TYPE_SECT | \
 		PMD_SECT_AP_WRITE | \
 		PMD_SECT_AP_READ | \
-		PMD_FLAGS
+		PMD_FLAGS_SMP)
+	ALT_UP(.long \
+		PMD_TYPE_SECT | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ | \
+		PMD_FLAGS_UP)
 	.long   PMD_TYPE_SECT | \
 		PMD_SECT_XN | \
 		PMD_SECT_AP_WRITE | \
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 6a8506d..53cbe22 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -30,15 +30,13 @@
 #define TTB_IRGN_WT	((1 << 0) | (0 << 6))
 #define TTB_IRGN_WB	((1 << 0) | (1 << 6))
 
-#ifndef CONFIG_SMP
 /* PTWs cacheable, inner WB not shareable, outer WB not shareable */
-#define TTB_FLAGS	TTB_IRGN_WB|TTB_RGN_OC_WB
-#define PMD_FLAGS	PMD_SECT_WB
-#else
+#define TTB_FLAGS_UP	TTB_IRGN_WB|TTB_RGN_OC_WB
+#define PMD_FLAGS_UP	PMD_SECT_WB
+
 /* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
-#define TTB_FLAGS	TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
-#define PMD_FLAGS	PMD_SECT_WBWA|PMD_SECT_S
-#endif
+#define TTB_FLAGS_SMP	TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
+#define PMD_FLAGS_SMP	PMD_SECT_WBWA|PMD_SECT_S
 
 ENTRY(cpu_v7_proc_init)
 	mov	pc, lr
@@ -105,7 +103,8 @@
 #ifdef CONFIG_MMU
 	mov	r2, #0
 	ldr	r1, [r1, #MM_CONTEXT_ID]	@ get mm->context.id
-	orr	r0, r0, #TTB_FLAGS
+	ALT_SMP(orr	r0, r0, #TTB_FLAGS_SMP)
+	ALT_UP(orr	r0, r0, #TTB_FLAGS_UP)
 #ifdef CONFIG_ARM_ERRATA_430973
 	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
 #endif
@@ -169,7 +168,7 @@
 	.ascii	"ARMv7 Processor"
 	.align
 
-	__INIT
+	__CPUINIT
 
 /*
  *	__v7_setup
@@ -186,13 +185,15 @@
  *	It is assumed that:
  *	- cache type register is implemented
  */
-__v7_setup:
+__v7_ca9mp_setup:
 #ifdef CONFIG_SMP
-	mrc	p15, 0, r0, c1, c0, 1
+	ALT_SMP(mrc	p15, 0, r0, c1, c0, 1)
+	ALT_UP(mov	r0, #(1 << 6))		@ fake it for UP
 	tst	r0, #(1 << 6)			@ SMP/nAMP mode enabled?
 	orreq	r0, r0, #(1 << 6) | (1 << 0)	@ Enable SMP/nAMP mode and
 	mcreq	p15, 0, r0, c1, c0, 1		@ TLB ops broadcasting
 #endif
+__v7_setup:
 	adr	r12, __v7_setup_stack		@ the local stack
 	stmia	r12, {r0-r5, r7, r9, r11, lr}
 	bl	v7_flush_dcache_all
@@ -201,11 +202,16 @@
 	mrc	p15, 0, r0, c0, c0, 0		@ read main ID register
 	and	r10, r0, #0xff000000		@ ARM?
 	teq	r10, #0x41000000
-	bne	2f
+	bne	3f
 	and	r5, r0, #0x00f00000		@ variant
 	and	r6, r0, #0x0000000f		@ revision
-	orr	r0, r6, r5, lsr #20-4		@ combine variant and revision
+	orr	r6, r6, r5, lsr #20-4		@ combine variant and revision
+	ubfx	r0, r0, #4, #12			@ primary part number
 
+	/* Cortex-A8 Errata */
+	ldr	r10, =0x00000c08		@ Cortex-A8 primary part number
+	teq	r0, r10
+	bne	2f
 #ifdef CONFIG_ARM_ERRATA_430973
 	teq	r5, #0x00100000			@ only present in r1p*
 	mrceq	p15, 0, r10, c1, c0, 1		@ read aux control register
@@ -213,21 +219,50 @@
 	mcreq	p15, 0, r10, c1, c0, 1		@ write aux control register
 #endif
 #ifdef CONFIG_ARM_ERRATA_458693
-	teq	r0, #0x20			@ only present in r2p0
+	teq	r6, #0x20			@ only present in r2p0
 	mrceq	p15, 0, r10, c1, c0, 1		@ read aux control register
 	orreq	r10, r10, #(1 << 5)		@ set L1NEON to 1
 	orreq	r10, r10, #(1 << 9)		@ set PLDNOP to 1
 	mcreq	p15, 0, r10, c1, c0, 1		@ write aux control register
 #endif
 #ifdef CONFIG_ARM_ERRATA_460075
-	teq	r0, #0x20			@ only present in r2p0
+	teq	r6, #0x20			@ only present in r2p0
 	mrceq	p15, 1, r10, c9, c0, 2		@ read L2 cache aux ctrl register
 	tsteq	r10, #1 << 22
 	orreq	r10, r10, #(1 << 22)		@ set the Write Allocate disable bit
 	mcreq	p15, 1, r10, c9, c0, 2		@ write the L2 cache aux ctrl register
 #endif
+	b	3f
 
-2:	mov	r10, #0
+	/* Cortex-A9 Errata */
+2:	ldr	r10, =0x00000c09		@ Cortex-A9 primary part number
+	teq	r0, r10
+	bne	3f
+#ifdef CONFIG_ARM_ERRATA_742230
+	cmp	r6, #0x22			@ only present up to r2p2
+	mrcle	p15, 0, r10, c15, c0, 1		@ read diagnostic register
+	orrle	r10, r10, #1 << 4		@ set bit #4
+	mcrle	p15, 0, r10, c15, c0, 1		@ write diagnostic register
+#endif
+#ifdef CONFIG_ARM_ERRATA_742231
+	teq	r6, #0x20			@ present in r2p0
+	teqne	r6, #0x21			@ present in r2p1
+	teqne	r6, #0x22			@ present in r2p2
+	mrceq	p15, 0, r10, c15, c0, 1		@ read diagnostic register
+	orreq	r10, r10, #1 << 12		@ set bit #12
+	orreq	r10, r10, #1 << 22		@ set bit #22
+	mcreq	p15, 0, r10, c15, c0, 1		@ write diagnostic register
+#endif
+#ifdef CONFIG_ARM_ERRATA_743622
+	teq	r6, #0x20			@ present in r2p0
+	teqne	r6, #0x21			@ present in r2p1
+	teqne	r6, #0x22			@ present in r2p2
+	mrceq	p15, 0, r10, c15, c0, 1		@ read diagnostic register
+	orreq	r10, r10, #1 << 6		@ set bit #6
+	mcreq	p15, 0, r10, c15, c0, 1		@ write diagnostic register
+#endif
+
+3:	mov	r10, #0
 #ifdef HARVARD_CACHE
 	mcr	p15, 0, r10, c7, c5, 0		@ I+BTB cache invalidate
 #endif
@@ -235,7 +270,8 @@
 #ifdef CONFIG_MMU
 	mcr	p15, 0, r10, c8, c7, 0		@ invalidate I + D TLBs
 	mcr	p15, 0, r10, c2, c0, 2		@ TTB control register
-	orr	r4, r4, #TTB_FLAGS
+	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
 	mov	r10, #0x1f			@ domains 0, 1 = manager
 	mcr	p15, 0, r10, c3, c0, 0		@ load domain access register
@@ -297,6 +333,8 @@
 __v7_setup_stack:
 	.space	4 * 11				@ 11 registers
 
+	__INITDATA
+
 	.type	v7_processor_functions, #object
 ENTRY(v7_processor_functions)
 	.word	v7_early_abort
@@ -310,6 +348,8 @@
 	.word	cpu_v7_set_pte_ext
 	.size	v7_processor_functions, . - v7_processor_functions
 
+	.section ".rodata"
+
 	.type	cpu_arch_name, #object
 cpu_arch_name:
 	.asciz	"armv7"
@@ -323,6 +363,35 @@
 
 	.section ".proc.info.init", #alloc, #execinstr
 
+	.type   __v7_ca9mp_proc_info, #object
+__v7_ca9mp_proc_info:
+	.long	0x410fc090		@ Required ID value
+	.long	0xff0ffff0		@ Mask for ID
+	ALT_SMP(.long \
+		PMD_TYPE_SECT | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ | \
+		PMD_FLAGS_SMP)
+	ALT_UP(.long \
+		PMD_TYPE_SECT | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ | \
+		PMD_FLAGS_UP)
+	.long   PMD_TYPE_SECT | \
+		PMD_SECT_XN | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ
+	b	__v7_ca9mp_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
+	.long	cpu_v7_name
+	.long	v7_processor_functions
+	.long	v7wbi_tlb_fns
+	.long	v6_user_fns
+	.long	v7_cache_fns
+	.size	__v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
+
 	/*
 	 * Match any ARMv7 processor core.
 	 */
@@ -330,10 +399,16 @@
 __v7_proc_info:
 	.long	0x000f0000		@ Required ID value
 	.long	0x000f0000		@ Mask for ID
-	.long   PMD_TYPE_SECT | \
+	ALT_SMP(.long \
+		PMD_TYPE_SECT | \
 		PMD_SECT_AP_WRITE | \
 		PMD_SECT_AP_READ | \
-		PMD_FLAGS
+		PMD_FLAGS_SMP)
+	ALT_UP(.long \
+		PMD_TYPE_SECT | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ | \
+		PMD_FLAGS_UP)
 	.long   PMD_TYPE_SECT | \
 		PMD_SECT_XN | \
 		PMD_SECT_AP_WRITE | \
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index 361a51e..cad07e4 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -404,7 +404,7 @@
 
 	.align
 
-	__INIT
+	__CPUINIT
 
 	.type	__xsc3_setup, #function
 __xsc3_setup:
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 1407597..cb245ed 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -506,7 +506,7 @@
 
 	.align
 
-	__INIT
+	__CPUINIT
 
 	.type	__xscale_setup, #function
 __xscale_setup:
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
index f3f288a..53cd5b4 100644
--- a/arch/arm/mm/tlb-v7.S
+++ b/arch/arm/mm/tlb-v7.S
@@ -13,6 +13,7 @@
  */
 #include <linux/init.h>
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/page.h>
 #include <asm/tlbflush.h>
@@ -41,20 +42,15 @@
 	orr	r0, r3, r0, lsl #PAGE_SHIFT	@ Create initial MVA
 	mov	r1, r1, lsl #PAGE_SHIFT
 1:
-#ifdef CONFIG_SMP
-	mcr	p15, 0, r0, c8, c3, 1		@ TLB invalidate U MVA (shareable) 
-#else
-	mcr	p15, 0, r0, c8, c7, 1		@ TLB invalidate U MVA
-#endif
+	ALT_SMP(mcr	p15, 0, r0, c8, c3, 1)	@ TLB invalidate U MVA (shareable)
+	ALT_UP(mcr	p15, 0, r0, c8, c7, 1)	@ TLB invalidate U MVA
+
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
 	mov	ip, #0
-#ifdef CONFIG_SMP
-	mcr	p15, 0, ip, c7, c1, 6		@ flush BTAC/BTB Inner Shareable
-#else
-	mcr	p15, 0, ip, c7, c5, 6		@ flush BTAC/BTB
-#endif
+	ALT_SMP(mcr	p15, 0, ip, c7, c1, 6)	@ flush BTAC/BTB Inner Shareable
+	ALT_UP(mcr	p15, 0, ip, c7, c5, 6)	@ flush BTAC/BTB
 	dsb
 	mov	pc, lr
 ENDPROC(v7wbi_flush_user_tlb_range)
@@ -74,20 +70,14 @@
 	mov	r0, r0, lsl #PAGE_SHIFT
 	mov	r1, r1, lsl #PAGE_SHIFT
 1:
-#ifdef CONFIG_SMP
-	mcr	p15, 0, r0, c8, c3, 1		@ TLB invalidate U MVA (shareable)
-#else
-	mcr	p15, 0, r0, c8, c7, 1		@ TLB invalidate U MVA
-#endif
+	ALT_SMP(mcr	p15, 0, r0, c8, c3, 1)	@ TLB invalidate U MVA (shareable)
+	ALT_UP(mcr	p15, 0, r0, c8, c7, 1)	@ TLB invalidate U MVA
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
 	mov	r2, #0
-#ifdef CONFIG_SMP
-	mcr	p15, 0, r2, c7, c1, 6		@ flush BTAC/BTB Inner Shareable
-#else
-	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
-#endif
+	ALT_SMP(mcr	p15, 0, r2, c7, c1, 6)	@ flush BTAC/BTB Inner Shareable
+	ALT_UP(mcr	p15, 0, r2, c7, c5, 6)	@ flush BTAC/BTB
 	dsb
 	isb
 	mov	pc, lr
@@ -99,5 +89,6 @@
 ENTRY(v7wbi_tlb_fns)
 	.long	v7wbi_flush_user_tlb_range
 	.long	v7wbi_flush_kern_tlb_range
-	.long	v7wbi_tlb_flags
+	ALT_SMP(.long	v7wbi_tlb_flags_smp)
+	ALT_UP(.long	v7wbi_tlb_flags_up)
 	.size	v7wbi_tlb_fns, . - v7wbi_tlb_fns
diff --git a/arch/arm/oprofile/Makefile b/arch/arm/oprofile/Makefile
index e666eaf..b2215c6 100644
--- a/arch/arm/oprofile/Makefile
+++ b/arch/arm/oprofile/Makefile
@@ -6,4 +6,8 @@
 		oprofilefs.o oprofile_stats.o \
 		timer_int.o )
 
+ifeq ($(CONFIG_HW_PERF_EVENTS),y)
+DRIVER_OBJS += $(addprefix ../../../drivers/oprofile/, oprofile_perf.o)
+endif
+
 oprofile-y				:= $(DRIVER_OBJS) common.o
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
index 0691176..8aa9744 100644
--- a/arch/arm/oprofile/common.c
+++ b/arch/arm/oprofile/common.c
@@ -25,138 +25,10 @@
 #include <asm/ptrace.h>
 
 #ifdef CONFIG_HW_PERF_EVENTS
-/*
- * Per performance monitor configuration as set via oprofilefs.
- */
-struct op_counter_config {
-	unsigned long count;
-	unsigned long enabled;
-	unsigned long event;
-	unsigned long unit_mask;
-	unsigned long kernel;
-	unsigned long user;
-	struct perf_event_attr attr;
-};
-
-static int op_arm_enabled;
-static DEFINE_MUTEX(op_arm_mutex);
-
-static struct op_counter_config *counter_config;
-static struct perf_event **perf_events[nr_cpumask_bits];
-static int perf_num_counters;
-
-/*
- * Overflow callback for oprofile.
- */
-static void op_overflow_handler(struct perf_event *event, int unused,
-			struct perf_sample_data *data, struct pt_regs *regs)
+char *op_name_from_perf_id(void)
 {
-	int id;
-	u32 cpu = smp_processor_id();
+	enum arm_perf_pmu_ids id = armpmu_get_pmu_id();
 
-	for (id = 0; id < perf_num_counters; ++id)
-		if (perf_events[cpu][id] == event)
-			break;
-
-	if (id != perf_num_counters)
-		oprofile_add_sample(regs, id);
-	else
-		pr_warning("oprofile: ignoring spurious overflow "
-				"on cpu %u\n", cpu);
-}
-
-/*
- * Called by op_arm_setup to create perf attributes to mirror the oprofile
- * settings in counter_config. Attributes are created as `pinned' events and
- * so are permanently scheduled on the PMU.
- */
-static void op_perf_setup(void)
-{
-	int i;
-	u32 size = sizeof(struct perf_event_attr);
-	struct perf_event_attr *attr;
-
-	for (i = 0; i < perf_num_counters; ++i) {
-		attr = &counter_config[i].attr;
-		memset(attr, 0, size);
-		attr->type		= PERF_TYPE_RAW;
-		attr->size		= size;
-		attr->config		= counter_config[i].event;
-		attr->sample_period	= counter_config[i].count;
-		attr->pinned		= 1;
-	}
-}
-
-static int op_create_counter(int cpu, int event)
-{
-	int ret = 0;
-	struct perf_event *pevent;
-
-	if (!counter_config[event].enabled || (perf_events[cpu][event] != NULL))
-		return ret;
-
-	pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
-						  cpu, -1,
-						  op_overflow_handler);
-
-	if (IS_ERR(pevent)) {
-		ret = PTR_ERR(pevent);
-	} else if (pevent->state != PERF_EVENT_STATE_ACTIVE) {
-		pr_warning("oprofile: failed to enable event %d "
-				"on CPU %d\n", event, cpu);
-		ret = -EBUSY;
-	} else {
-		perf_events[cpu][event] = pevent;
-	}
-
-	return ret;
-}
-
-static void op_destroy_counter(int cpu, int event)
-{
-	struct perf_event *pevent = perf_events[cpu][event];
-
-	if (pevent) {
-		perf_event_release_kernel(pevent);
-		perf_events[cpu][event] = NULL;
-	}
-}
-
-/*
- * Called by op_arm_start to create active perf events based on the
- * perviously configured attributes.
- */
-static int op_perf_start(void)
-{
-	int cpu, event, ret = 0;
-
-	for_each_online_cpu(cpu) {
-		for (event = 0; event < perf_num_counters; ++event) {
-			ret = op_create_counter(cpu, event);
-			if (ret)
-				goto out;
-		}
-	}
-
-out:
-	return ret;
-}
-
-/*
- * Called by op_arm_stop at the end of a profiling run.
- */
-static void op_perf_stop(void)
-{
-	int cpu, event;
-
-	for_each_online_cpu(cpu)
-		for (event = 0; event < perf_num_counters; ++event)
-			op_destroy_counter(cpu, event);
-}
-
-
-static char *op_name_from_perf_id(enum arm_perf_pmu_ids id)
-{
 	switch (id) {
 	case ARM_PERF_PMU_ID_XSCALE1:
 		return "arm/xscale1";
@@ -175,116 +47,6 @@
 	}
 }
 
-static int op_arm_create_files(struct super_block *sb, struct dentry *root)
-{
-	unsigned int i;
-
-	for (i = 0; i < perf_num_counters; i++) {
-		struct dentry *dir;
-		char buf[4];
-
-		snprintf(buf, sizeof buf, "%d", i);
-		dir = oprofilefs_mkdir(sb, root, buf);
-		oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
-		oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);
-		oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);
-		oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
-		oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
-		oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
-	}
-
-	return 0;
-}
-
-static int op_arm_setup(void)
-{
-	spin_lock(&oprofilefs_lock);
-	op_perf_setup();
-	spin_unlock(&oprofilefs_lock);
-	return 0;
-}
-
-static int op_arm_start(void)
-{
-	int ret = -EBUSY;
-
-	mutex_lock(&op_arm_mutex);
-	if (!op_arm_enabled) {
-		ret = 0;
-		op_perf_start();
-		op_arm_enabled = 1;
-	}
-	mutex_unlock(&op_arm_mutex);
-	return ret;
-}
-
-static void op_arm_stop(void)
-{
-	mutex_lock(&op_arm_mutex);
-	if (op_arm_enabled)
-		op_perf_stop();
-	op_arm_enabled = 0;
-	mutex_unlock(&op_arm_mutex);
-}
-
-#ifdef CONFIG_PM
-static int op_arm_suspend(struct platform_device *dev, pm_message_t state)
-{
-	mutex_lock(&op_arm_mutex);
-	if (op_arm_enabled)
-		op_perf_stop();
-	mutex_unlock(&op_arm_mutex);
-	return 0;
-}
-
-static int op_arm_resume(struct platform_device *dev)
-{
-	mutex_lock(&op_arm_mutex);
-	if (op_arm_enabled && op_perf_start())
-		op_arm_enabled = 0;
-	mutex_unlock(&op_arm_mutex);
-	return 0;
-}
-
-static struct platform_driver oprofile_driver = {
-	.driver		= {
-		.name		= "arm-oprofile",
-	},
-	.resume		= op_arm_resume,
-	.suspend	= op_arm_suspend,
-};
-
-static struct platform_device *oprofile_pdev;
-
-static int __init init_driverfs(void)
-{
-	int ret;
-
-	ret = platform_driver_register(&oprofile_driver);
-	if (ret)
-		goto out;
-
-	oprofile_pdev =	platform_device_register_simple(
-				oprofile_driver.driver.name, 0, NULL, 0);
-	if (IS_ERR(oprofile_pdev)) {
-		ret = PTR_ERR(oprofile_pdev);
-		platform_driver_unregister(&oprofile_driver);
-	}
-
-out:
-	return ret;
-}
-
-static void  exit_driverfs(void)
-{
-	platform_device_unregister(oprofile_pdev);
-	platform_driver_unregister(&oprofile_driver);
-}
-#else
-static int __init init_driverfs(void) { return 0; }
-#define exit_driverfs() do { } while (0)
-#endif /* CONFIG_PM */
-
 static int report_trace(struct stackframe *frame, void *d)
 {
 	unsigned int *depth = d;
@@ -349,72 +111,14 @@
 
 int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
-	int cpu, ret = 0;
-
-	perf_num_counters = armpmu_get_max_events();
-
-	counter_config = kcalloc(perf_num_counters,
-			sizeof(struct op_counter_config), GFP_KERNEL);
-
-	if (!counter_config) {
-		pr_info("oprofile: failed to allocate %d "
-				"counters\n", perf_num_counters);
-		return -ENOMEM;
-	}
-
-	ret = init_driverfs();
-	if (ret) {
-		kfree(counter_config);
-		return ret;
-	}
-
-	for_each_possible_cpu(cpu) {
-		perf_events[cpu] = kcalloc(perf_num_counters,
-				sizeof(struct perf_event *), GFP_KERNEL);
-		if (!perf_events[cpu]) {
-			pr_info("oprofile: failed to allocate %d perf events "
-					"for cpu %d\n", perf_num_counters, cpu);
-			while (--cpu >= 0)
-				kfree(perf_events[cpu]);
-			return -ENOMEM;
-		}
-	}
-
 	ops->backtrace		= arm_backtrace;
-	ops->create_files	= op_arm_create_files;
-	ops->setup		= op_arm_setup;
-	ops->start		= op_arm_start;
-	ops->stop		= op_arm_stop;
-	ops->shutdown		= op_arm_stop;
-	ops->cpu_type		= op_name_from_perf_id(armpmu_get_pmu_id());
 
-	if (!ops->cpu_type)
-		ret = -ENODEV;
-	else
-		pr_info("oprofile: using %s\n", ops->cpu_type);
-
-	return ret;
+	return oprofile_perf_init(ops);
 }
 
-void oprofile_arch_exit(void)
+void __exit oprofile_arch_exit(void)
 {
-	int cpu, id;
-	struct perf_event *event;
-
-	if (*perf_events) {
-		exit_driverfs();
-		for_each_possible_cpu(cpu) {
-			for (id = 0; id < perf_num_counters; ++id) {
-				event = perf_events[cpu][id];
-				if (event != NULL)
-					perf_event_release_kernel(event);
-			}
-			kfree(perf_events[cpu]);
-		}
-	}
-
-	if (counter_config)
-		kfree(counter_config);
+	oprofile_perf_exit();
 }
 #else
 int __init oprofile_arch_init(struct oprofile_operations *ops)
@@ -422,5 +126,5 @@
 	pr_info("oprofile: hardware counters not available\n");
 	return -ENODEV;
 }
-void oprofile_arch_exit(void) {}
+void __exit oprofile_arch_exit(void) {}
 #endif /* CONFIG_HW_PERF_EVENTS */
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 6785db4..64e3a64 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -92,6 +92,18 @@
 	  data/address de-multiplexing and decode, signal level shift,
 	  interrupt control and various board functions.
 
+config HAVE_EPIT
+	bool
+
+config MXC_USE_EPIT
+	bool "Use EPIT instead of GPT"
+	depends on HAVE_EPIT
+	help
+	  Use EPIT as the system timer on systems that have it. Normally you
+	  don't have a reason to do so as the EPIT has the same features and
+	  uses the same clocks as the GPT. Anyway, on some systems the GPT
+	  may be in use for other purposes.
+
 config MXC_ULPI
 	bool
 
@@ -110,4 +122,8 @@
 config ARCH_MXC_AUDMUX_V2
 	bool
 
+config IRAM_ALLOC
+	bool
+	select GENERIC_ALLOCATOR
+
 endif
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 78d405e..06875b4 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -10,9 +10,11 @@
 
 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
 obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o
 obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c
index f9e7cdb..0be1ac7 100644
--- a/arch/arm/plat-mxc/audmux-v2.c
+++ b/arch/arm/plat-mxc/audmux-v2.c
@@ -137,6 +137,7 @@
 static const struct file_operations audmux_debugfs_fops = {
 	.open = audmux_open_file,
 	.read = audmux_read_file,
+	.llseek = default_llseek,
 };
 
 static void audmux_debugfs_init(void)
@@ -186,7 +187,13 @@
 static int mxc_audmux_v2_init(void)
 {
 	int ret;
-
+#if defined(CONFIG_ARCH_MX5)
+	if (cpu_is_mx51()) {
+		audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR);
+		ret = 0;
+		return ret;
+	}
+#endif
 #if defined(CONFIG_ARCH_MX3)
 	if (cpu_is_mx31())
 		audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR);
diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig
index 9ab784b..4047994 100644
--- a/arch/arm/plat-mxc/devices/Kconfig
+++ b/arch/arm/plat-mxc/devices/Kconfig
@@ -1,3 +1,10 @@
+config IMX_HAVE_PLATFORM_ESDHC
+	bool
+
+config IMX_HAVE_PLATFORM_FEC
+	bool
+	default y if ARCH_MX25 || SOC_IMX27 || ARCH_MX35 || ARCH_MX51
+
 config IMX_HAVE_PLATFORM_FLEXCAN
 	select HAVE_CAN_FLEXCAN
 	bool
@@ -5,6 +12,9 @@
 config IMX_HAVE_PLATFORM_IMX_I2C
 	bool
 
+config IMX_HAVE_PLATFORM_IMX_SSI
+	bool
+
 config IMX_HAVE_PLATFORM_IMX_UART
 	bool
 
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index 347da51..0a3c1f0 100644
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -1,8 +1,9 @@
-ifdef CONFIG_CAN_FLEXCAN
-# the ifdef can be removed once the flexcan driver has been merged
-obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) +=  platform-flexcan.o
-endif
+obj-$(CONFIG_IMX_HAVE_PLATFORM_ESDHC) += platform-esdhc.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
+obj-y += platform-imx-dma.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_NAND) += platform-mxc_nand.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) +=  platform-spi_imx.o
diff --git a/arch/arm/plat-mxc/devices/platform-esdhc.c b/arch/arm/plat-mxc/devices/platform-esdhc.c
new file mode 100644
index 0000000..2605bfa
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-esdhc.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 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 <mach/hardware.h>
+#include <mach/devices-common.h>
+#include <mach/esdhc.h>
+
+#define imx_esdhc_imx_data_entry_single(soc, _id, hwid) \
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _ESDHC ## hwid ## _BASE_ADDR,	\
+		.irq = soc ## _INT_ESDHC ## hwid,			\
+	}
+
+#define imx_esdhc_imx_data_entry(soc, id, hwid)	\
+	[id] = imx_esdhc_imx_data_entry_single(soc, id, hwid)
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_esdhc_imx_data imx25_esdhc_data[] __initconst = {
+#define imx25_esdhc_data_entry(_id, _hwid)				\
+	imx_esdhc_imx_data_entry(MX25, _id, _hwid)
+	imx25_esdhc_data_entry(0, 1),
+	imx25_esdhc_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_esdhc_imx_data imx35_esdhc_data[] __initconst = {
+#define imx35_esdhc_data_entry(_id, _hwid)                           \
+	imx_esdhc_imx_data_entry(MX35, _id, _hwid)
+	imx35_esdhc_data_entry(0, 1),
+	imx35_esdhc_data_entry(1, 2),
+	imx35_esdhc_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_esdhc_imx_data imx51_esdhc_data[] __initconst = {
+#define imx51_esdhc_data_entry(_id, _hwid)				\
+	imx_esdhc_imx_data_entry(MX51, _id, _hwid)
+	imx51_esdhc_data_entry(0, 1),
+	imx51_esdhc_data_entry(1, 2),
+	imx51_esdhc_data_entry(2, 3),
+	imx51_esdhc_data_entry(3, 4),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_esdhc(
+		const struct imx_esdhc_imx_data *data,
+		const struct esdhc_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
+			ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c
new file mode 100644
index 0000000..11d087f
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-fec.c
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_fec_data_entry_single(soc)					\
+	{								\
+		.iobase = soc ## _FEC_BASE_ADDR,			\
+		.irq = soc ## _INT_FEC,					\
+	}
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_fec_data imx25_fec_data __initconst =
+	imx_fec_data_entry_single(MX25);
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_fec_data imx27_fec_data __initconst =
+	imx_fec_data_entry_single(MX27);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_fec_data imx35_fec_data __initconst =
+	imx_fec_data_entry_single(MX35);
+#endif
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_fec_data imx51_fec_data __initconst =
+	imx_fec_data_entry_single(MX51);
+#endif
+
+struct platform_device *__init imx_add_fec(
+		const struct imx_fec_data *data,
+		const struct fec_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("fec", 0 /* -1? */,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c
new file mode 100644
index 0000000..02d9890
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx-dma.c
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+#ifdef SDMA_IS_MERGED
+#include <mach/sdma.h>
+#else
+struct sdma_platform_data {
+	int sdma_version;
+	char *cpu_name;
+	int to_version;
+};
+#endif
+
+struct imx_imx_sdma_data {
+	resource_size_t iobase;
+	resource_size_t irq;
+	struct sdma_platform_data pdata;
+};
+
+#define imx_imx_sdma_data_entry_single(soc, _sdma_version, _cpu_name, _to_version)\
+	{								\
+		.iobase = soc ## _SDMA ## _BASE_ADDR,			\
+		.irq = soc ## _INT_SDMA,				\
+		.pdata = {						\
+			.sdma_version = _sdma_version,			\
+			.cpu_name = _cpu_name,				\
+			.to_version = _to_version,			\
+		},							\
+	}
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_sdma_data imx25_imx_sdma_data __initconst =
+	imx_imx_sdma_data_entry_single(MX25, 1, "imx25", 0);
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_ARCH_MX31
+struct imx_imx_sdma_data imx31_imx_sdma_data __initdata =
+	imx_imx_sdma_data_entry_single(MX31, 1, "imx31", 0);
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+struct imx_imx_sdma_data imx35_imx_sdma_data __initdata =
+	imx_imx_sdma_data_entry_single(MX35, 2, "imx35", 0);
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_sdma_data imx51_imx_sdma_data __initconst =
+	imx_imx_sdma_data_entry_single(MX51, 2, "imx51", 0);
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+static struct platform_device __init __maybe_unused *imx_add_imx_sdma(
+		const struct imx_imx_sdma_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("imx-sdma", -1,
+			res, ARRAY_SIZE(res),
+			&data->pdata, sizeof(data->pdata));
+}
+
+static struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
+{
+	return imx_add_platform_device("imx-dma", -1, NULL, 0, NULL, 0);
+}
+
+static int __init imxXX_add_imx_dma(void)
+{
+	struct platform_device *ret;
+
+#if defined(CONFIG_SOC_IMX21) || defined(CONFIG_SOC_IMX27)
+	if (cpu_is_mx21() || cpu_is_mx27())
+		ret = imx_add_imx_dma();
+	else
+#endif
+
+#if defined(CONFIG_ARCH_MX25)
+	if (cpu_is_mx25())
+		ret = imx_add_imx_sdma(&imx25_imx_sdma_data);
+	else
+#endif
+
+#if defined(CONFIG_ARCH_MX31)
+	if (cpu_is_mx31()) {
+		imx31_imx_sdma_data.pdata.to_version = mx31_revision() >> 4;
+		ret = imx_add_imx_sdma(&imx31_imx_sdma_data);
+	} else
+#endif
+
+#if defined(CONFIG_ARCH_MX35)
+	if (cpu_is_mx35()) {
+		imx35_imx_sdma_data.pdata.to_version = mx35_revision() >> 4;
+		ret = imx_add_imx_sdma(&imx35_imx_sdma_data);
+	} else
+#endif
+
+#if defined(CONFIG_ARCH_MX51)
+	if (cpu_is_mx51())
+		ret = imx_add_imx_sdma(&imx51_imx_sdma_data);
+	else
+#endif
+		ret = ERR_PTR(-ENODEV);
+
+	if (IS_ERR(ret))
+		return PTR_ERR(ret);
+
+	return 0;
+}
+arch_initcall(imxXX_add_imx_dma);
diff --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
index d0af9f7..6795884 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
@@ -6,24 +6,95 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <mach/hardware.h>
 #include <mach/devices-common.h>
 
-struct platform_device *__init imx_add_imx_i2c(int id,
-		resource_size_t iobase, resource_size_t iosize, int irq,
+#define imx_imx_i2c_data_entry_single(soc, _id, _hwid, _size)		\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _I2C ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_I2C ## _hwid,			\
+	}
+
+#define imx_imx_i2c_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = imx_imx_i2c_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_i2c_data imx1_imx_i2c_data __initconst =
+	imx_imx_i2c_data_entry_single(MX1, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_i2c_data imx21_imx_i2c_data __initconst =
+	imx_imx_i2c_data_entry_single(MX21, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst = {
+#define imx25_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX25, _id, _hwid, SZ_16K)
+	imx25_imx_i2c_data_entry(0, 1),
+	imx25_imx_i2c_data_entry(1, 2),
+	imx25_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst = {
+#define imx27_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX27, _id, _hwid, SZ_4K)
+	imx27_imx_i2c_data_entry(0, 1),
+	imx27_imx_i2c_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst = {
+#define imx31_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX31, _id, _hwid, SZ_4K)
+	imx31_imx_i2c_data_entry(0, 1),
+	imx31_imx_i2c_data_entry(1, 2),
+	imx31_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = {
+#define imx35_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX35, _id, _hwid, SZ_4K)
+	imx35_imx_i2c_data_entry(0, 1),
+	imx35_imx_i2c_data_entry(1, 2),
+	imx35_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
+#define imx51_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX51, _id, _hwid, SZ_4K)
+	imx51_imx_i2c_data_entry(0, 1),
+	imx51_imx_i2c_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_imx_i2c(
+		const struct imx_imx_i2c_data *data,
 		const struct imxi2c_platform_data *pdata)
 {
 	struct resource res[] = {
 		{
-			.start = iobase,
-			.end = iobase + iosize - 1,
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
 			.flags = IORESOURCE_MEM,
 		}, {
-			.start = irq,
-			.end = irq,
+			.start = data->irq,
+			.end = data->irq,
 			.flags = IORESOURCE_IRQ,
 		},
 	};
 
-	return imx_add_platform_device("imx-i2c", id, res, ARRAY_SIZE(res),
+	return imx_add_platform_device("imx-i2c", data->id,
+			res, ARRAY_SIZE(res),
 			pdata, sizeof(*pdata));
 }
diff --git a/arch/arm/plat-mxc/devices/platform-imx-ssi.c b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
new file mode 100644
index 0000000..38a7a0b
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_imx_ssi_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = {							\
+		.id = _id,						\
+		.iobase = soc ## _SSI ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_SSI ## _hwid,			\
+		.dmatx0 = soc ## _DMA_REQ_SSI ## _hwid ## _TX0,		\
+		.dmarx0 = soc ## _DMA_REQ_SSI ## _hwid ## _RX0,		\
+		.dmatx1 = soc ## _DMA_REQ_SSI ## _hwid ## _TX1,		\
+		.dmarx1 = soc ## _DMA_REQ_SSI ## _hwid ## _RX1,		\
+	}
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_ssi_data imx21_imx_ssi_data[] __initconst = {
+#define imx21_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX21, _id, _hwid, SZ_4K)
+	imx21_imx_ssi_data_entry(0, 1),
+	imx21_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst = {
+#define imx25_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX25, _id, _hwid, SZ_4K)
+	imx25_imx_ssi_data_entry(0, 1),
+	imx25_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_ssi_data imx27_imx_ssi_data[] __initconst = {
+#define imx27_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX27, _id, _hwid, SZ_4K)
+	imx27_imx_ssi_data_entry(0, 1),
+	imx27_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_imx_ssi_data imx31_imx_ssi_data[] __initconst = {
+#define imx31_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX31, _id, _hwid, SZ_4K)
+	imx31_imx_ssi_data_entry(0, 1),
+	imx31_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst = {
+#define imx35_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX35, _id, _hwid, SZ_4K)
+	imx35_imx_ssi_data_entry(0, 1),
+	imx35_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst = {
+#define imx51_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_4K)
+	imx51_imx_ssi_data_entry(0, 1),
+	imx51_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_imx_ssi(
+		const struct imx_imx_ssi_data *data,
+		const struct imx_ssi_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,
+		},
+#define DMARES(_name) {							\
+	.name = #_name,							\
+	.start = data->dma ## _name,					\
+	.end = data->dma ## _name,					\
+	.flags = IORESOURCE_DMA,					\
+}
+		DMARES(tx0),
+		DMARES(rx0),
+		DMARES(tx1),
+		DMARES(rx1),
+	};
+
+	return imx_add_platform_device("imx-ssi", data->id,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
index fa3dff1..2039640 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-uart.c
@@ -6,55 +6,148 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <mach/hardware.h>
 #include <mach/devices-common.h>
 
-struct platform_device *__init imx_add_imx_uart_3irq(int id,
-		resource_size_t iobase, resource_size_t iosize,
-		resource_size_t irqrx, resource_size_t irqtx,
-		resource_size_t irqrts,
+#define imx_imx_uart_3irq_data_entry(soc, _id, _hwid, _size)		\
+	[_id] = {							\
+		.id = _id,						\
+		.iobase = soc ## _UART ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irqrx = soc ## _INT_UART ## _hwid ## RX,		\
+		.irqtx = soc ## _INT_UART ## _hwid ## TX,		\
+		.irqrts = soc ## _INT_UART ## _hwid ## RTS,		\
+	}
+
+#define imx_imx_uart_1irq_data_entry(soc, _id, _hwid, _size)		\
+	[_id] = {							\
+		.id = _id,						\
+		.iobase = soc ## _UART ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_UART ## _hwid,			\
+	}
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_uart_3irq_data imx1_imx_uart_data[] __initconst = {
+#define imx1_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_3irq_data_entry(MX1, _id, _hwid, 0xd0)
+	imx1_imx_uart_data_entry(0, 1),
+	imx1_imx_uart_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_uart_1irq_data imx21_imx_uart_data[] __initconst = {
+#define imx21_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX21, _id, _hwid, SZ_4K)
+	imx21_imx_uart_data_entry(0, 1),
+	imx21_imx_uart_data_entry(1, 2),
+	imx21_imx_uart_data_entry(2, 3),
+	imx21_imx_uart_data_entry(3, 4),
+};
+#endif
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst = {
+#define imx25_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX25, _id, _hwid, SZ_16K)
+	imx25_imx_uart_data_entry(0, 1),
+	imx25_imx_uart_data_entry(1, 2),
+	imx25_imx_uart_data_entry(2, 3),
+	imx25_imx_uart_data_entry(3, 4),
+	imx25_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_uart_1irq_data imx27_imx_uart_data[] __initconst = {
+#define imx27_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX27, _id, _hwid, SZ_4K)
+	imx27_imx_uart_data_entry(0, 1),
+	imx27_imx_uart_data_entry(1, 2),
+	imx27_imx_uart_data_entry(2, 3),
+	imx27_imx_uart_data_entry(3, 4),
+	imx27_imx_uart_data_entry(4, 5),
+	imx27_imx_uart_data_entry(5, 6),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_imx_uart_1irq_data imx31_imx_uart_data[] __initconst = {
+#define imx31_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX31, _id, _hwid, SZ_4K)
+	imx31_imx_uart_data_entry(0, 1),
+	imx31_imx_uart_data_entry(1, 2),
+	imx31_imx_uart_data_entry(2, 3),
+	imx31_imx_uart_data_entry(3, 4),
+	imx31_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst = {
+#define imx35_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX31, _id, _hwid, SZ_16K)
+	imx35_imx_uart_data_entry(0, 1),
+	imx35_imx_uart_data_entry(1, 2),
+	imx35_imx_uart_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst = {
+#define imx51_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX51, _id, _hwid, SZ_4K)
+	imx51_imx_uart_data_entry(0, 1),
+	imx51_imx_uart_data_entry(1, 2),
+	imx51_imx_uart_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_imx_uart_3irq(
+		const struct imx_imx_uart_3irq_data *data,
 		const struct imxuart_platform_data *pdata)
 {
 	struct resource res[] = {
 		{
-			.start = iobase,
-			.end = iobase + iosize - 1,
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
 			.flags = IORESOURCE_MEM,
 		}, {
-			.start = irqrx,
-			.end = irqrx,
+			.start = data->irqrx,
+			.end = data->irqrx,
 			.flags = IORESOURCE_IRQ,
 		}, {
-			.start = irqtx,
-			.end = irqtx,
+			.start = data->irqtx,
+			.end = data->irqtx,
 			.flags = IORESOURCE_IRQ,
 		}, {
-			.start = irqrts,
-			.end = irqrx,
+			.start = data->irqrts,
+			.end = data->irqrx,
 			.flags = IORESOURCE_IRQ,
 		},
 	};
 
-	return imx_add_platform_device("imx-uart", id, res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata));
+	return imx_add_platform_device("imx-uart", data->id, res,
+			ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
 
-struct platform_device *__init imx_add_imx_uart_1irq(int id,
-		resource_size_t iobase, resource_size_t iosize,
-		resource_size_t irq,
+struct platform_device *__init imx_add_imx_uart_1irq(
+		const struct imx_imx_uart_1irq_data *data,
 		const struct imxuart_platform_data *pdata)
 {
 	struct resource res[] = {
 		{
-			.start = iobase,
-			.end = iobase + iosize - 1,
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
 			.flags = IORESOURCE_MEM,
 		}, {
-			.start = irq,
-			.end = irq,
+			.start = data->irq,
+			.end = data->irq,
 			.flags = IORESOURCE_IRQ,
 		},
 	};
 
-	return imx_add_platform_device("imx-uart", id, res, ARRAY_SIZE(res),
+	return imx_add_platform_device("imx-uart", data->id, res, ARRAY_SIZE(res),
 			pdata, sizeof(*pdata));
 }
diff --git a/arch/arm/plat-mxc/devices/platform-mxc_nand.c b/arch/arm/plat-mxc/devices/platform-mxc_nand.c
index 1c28641..3fdcc32 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc_nand.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc_nand.c
@@ -7,38 +7,77 @@
  * Free Software Foundation.
  */
 #include <asm/sizes.h>
+#include <mach/hardware.h>
 #include <mach/devices-common.h>
 
-static struct platform_device *__init imx_add_mxc_nand(resource_size_t iobase,
-		int irq, const struct mxc_nand_platform_data *pdata,
-		resource_size_t iosize)
+#define imx_mxc_nand_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _NFC_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_NFC					\
+	}
+
+#define imx_mxc_nandv3_data_entry_single(soc, _size)			\
+	{								\
+		.id = -1,						\
+		.iobase = soc ## _NFC_BASE_ADDR,			\
+		.iosize = _size,					\
+		.axibase = soc ## _NFC_AXI_BASE_ADDR,			\
+		.irq = soc ## _INT_NFC					\
+	}
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_mxc_nand_data imx21_mxc_nand_data __initconst =
+	imx_mxc_nand_data_entry_single(MX21, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst =
+	imx_mxc_nand_data_entry_single(MX25, SZ_8K);
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst =
+	imx_mxc_nand_data_entry_single(MX27, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_mxc_nand_data imx31_mxc_nand_data __initconst =
+	imx_mxc_nand_data_entry_single(MX31, SZ_4K);
+#endif
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst =
+	imx_mxc_nand_data_entry_single(MX35, SZ_8K);
+#endif
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst =
+	imx_mxc_nandv3_data_entry_single(MX51, SZ_16K);
+#endif
+
+struct platform_device *__init imx_add_mxc_nand(
+		const struct imx_mxc_nand_data *data,
+		const struct mxc_nand_platform_data *pdata)
 {
-	static int id = 0;
-	
+	/* AXI has to come first, that's how the mxc_nand driver expect it */
 	struct resource res[] = {
 		{
-			.start = iobase,
-			.end = iobase + iosize - 1,
+			.start = data->axibase,
+			.end = data->axibase + SZ_16K - 1,
 			.flags = IORESOURCE_MEM,
 		}, {
-			.start = irq,
-			.end = irq,
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
 			.flags = IORESOURCE_IRQ,
 		},
 	};
-
-	return imx_add_platform_device("mxc_nand", id++, res, ARRAY_SIZE(res),
+	return imx_add_platform_device("mxc_nand", data->id,
+			res + !data->axibase,
+			ARRAY_SIZE(res) - !data->axibase,
 			pdata, sizeof(*pdata));
 }
-
-struct platform_device *__init imx_add_mxc_nand_v1(resource_size_t iobase,
-		int irq, const struct mxc_nand_platform_data *pdata)
-{
-	return imx_add_mxc_nand(iobase, irq, pdata, SZ_4K);
-}
-
-struct platform_device *__init imx_add_mxc_nand_v21(resource_size_t iobase,
-		int irq, const struct mxc_nand_platform_data *pdata)
-{
-	return imx_add_mxc_nand(iobase, irq, pdata, SZ_8K);
-}
diff --git a/arch/arm/plat-mxc/devices/platform-spi_imx.c b/arch/arm/plat-mxc/devices/platform-spi_imx.c
index 2831a6d..e48340e 100644
--- a/arch/arm/plat-mxc/devices/platform-spi_imx.c
+++ b/arch/arm/plat-mxc/devices/platform-spi_imx.c
@@ -6,25 +6,96 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <asm/sizes.h>
+#include <mach/hardware.h>
 #include <mach/devices-common.h>
 
-struct platform_device *__init imx_add_spi_imx(int id,
-		resource_size_t iobase, resource_size_t iosize, int irq,
+#define imx_spi_imx_data_entry_single(soc, type, _devid, _id, hwid, _size) \
+	{								\
+		.devid = _devid,					\
+		.id = _id,						\
+		.iobase = soc ## _ ## type ## hwid ## _BASE_ADDR,	\
+		.iosize = _size,					\
+		.irq = soc ## _INT_ ## type ## hwid,			\
+	}
+
+#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_IMX21
+const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
+#define imx21_cspi_data_entry(_id, _hwid)                            \
+	imx_spi_imx_data_entry(MX21, CSPI, "imx21-cspi", _id, _hwid, SZ_4K)
+	imx21_cspi_data_entry(0, 1),
+	imx21_cspi_data_entry(1, 2),
+#endif
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_spi_imx_data imx25_cspi_data[] __initconst = {
+#define imx25_cspi_data_entry(_id, _hwid)				\
+	imx_spi_imx_data_entry(MX25, CSPI, "imx25-cspi", _id, _hwid, SZ_16K)
+	imx25_cspi_data_entry(0, 1),
+	imx25_cspi_data_entry(1, 2),
+	imx25_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_spi_imx_data imx27_cspi_data[] __initconst = {
+#define imx27_cspi_data_entry(_id, _hwid)				\
+	imx_spi_imx_data_entry(MX27, CSPI, "imx27-cspi", _id, _hwid, SZ_4K)
+	imx27_cspi_data_entry(0, 1),
+	imx27_cspi_data_entry(1, 2),
+	imx27_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_spi_imx_data imx31_cspi_data[] __initconst = {
+#define imx31_cspi_data_entry(_id, _hwid)				\
+	imx_spi_imx_data_entry(MX31, CSPI, "imx31-cspi", _id, _hwid, SZ_4K)
+	imx31_cspi_data_entry(0, 1),
+	imx31_cspi_data_entry(1, 2),
+	imx31_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_spi_imx_data imx35_cspi_data[] __initconst = {
+#define imx35_cspi_data_entry(_id, _hwid)                           \
+	imx_spi_imx_data_entry(MX35, CSPI, "imx35-cspi", _id, _hwid, SZ_4K)
+	imx35_cspi_data_entry(0, 1),
+	imx35_cspi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_spi_imx_data imx51_cspi_data __initconst =
+	imx_spi_imx_data_entry_single(MX51, CSPI, "imx51-cspi", 0, , SZ_4K);
+
+const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
+#define imx51_ecspi_data_entry(_id, _hwid)				\
+	imx_spi_imx_data_entry(MX51, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
+	imx51_ecspi_data_entry(0, 1),
+	imx51_ecspi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_spi_imx(
+		const struct imx_spi_imx_data *data,
 		const struct spi_imx_master *pdata)
 {
 	struct resource res[] = {
 		{
-			.start = iobase,
-			.end = iobase + iosize - 1,
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
 			.flags = IORESOURCE_MEM,
 		}, {
-			.start = irq,
-			.end = irq,
+			.start = data->irq,
+			.end = data->irq,
 			.flags = IORESOURCE_IRQ,
 		},
 	};
 
-	return imx_add_platform_device("spi_imx", id, res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata));
+	return imx_add_platform_device(data->devid, data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c
index 35a064f..9915607 100644
--- a/arch/arm/plat-mxc/ehci.c
+++ b/arch/arm/plat-mxc/ehci.c
@@ -249,8 +249,8 @@
 #ifdef CONFIG_ARCH_MX51
 	if (cpu_is_mx51()) {
 		void __iomem *usb_base;
-		u32 usbotg_base;
-		u32 usbother_base;
+		void __iomem *usbotg_base;
+		void __iomem *usbother_base;
 		int ret = 0;
 
 		usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
diff --git a/arch/arm/plat-mxc/epit.c b/arch/arm/plat-mxc/epit.c
new file mode 100644
index 0000000..ee9582f
--- /dev/null
+++ b/arch/arm/plat-mxc/epit.c
@@ -0,0 +1,242 @@
+/*
+ *  linux/arch/arm/plat-mxc/epit.c
+ *
+ *  Copyright (C) 2010 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#define EPITCR		0x00
+#define EPITSR		0x04
+#define EPITLR		0x08
+#define EPITCMPR	0x0c
+#define EPITCNR		0x10
+
+#define EPITCR_EN			(1 << 0)
+#define EPITCR_ENMOD			(1 << 1)
+#define EPITCR_OCIEN			(1 << 2)
+#define EPITCR_RLD			(1 << 3)
+#define EPITCR_PRESC(x)			(((x) & 0xfff) << 4)
+#define EPITCR_SWR			(1 << 16)
+#define EPITCR_IOVW			(1 << 17)
+#define EPITCR_DBGEN			(1 << 18)
+#define EPITCR_WAITEN			(1 << 19)
+#define EPITCR_RES			(1 << 20)
+#define EPITCR_STOPEN			(1 << 21)
+#define EPITCR_OM_DISCON		(0 << 22)
+#define EPITCR_OM_TOGGLE		(1 << 22)
+#define EPITCR_OM_CLEAR			(2 << 22)
+#define EPITCR_OM_SET			(3 << 22)
+#define EPITCR_CLKSRC_OFF		(0 << 24)
+#define EPITCR_CLKSRC_PERIPHERAL	(1 << 24)
+#define EPITCR_CLKSRC_REF_HIGH		(1 << 24)
+#define EPITCR_CLKSRC_REF_LOW		(3 << 24)
+
+#define EPITSR_OCIF			(1 << 0)
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+
+static struct clock_event_device clockevent_epit;
+static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
+
+static void __iomem *timer_base;
+
+static inline void epit_irq_disable(void)
+{
+	u32 val;
+
+	val = __raw_readl(timer_base + EPITCR);
+	val &= ~EPITCR_OCIEN;
+	__raw_writel(val, timer_base + EPITCR);
+}
+
+static inline void epit_irq_enable(void)
+{
+	u32 val;
+
+	val = __raw_readl(timer_base + EPITCR);
+	val |= EPITCR_OCIEN;
+	__raw_writel(val, timer_base + EPITCR);
+}
+
+static void epit_irq_acknowledge(void)
+{
+	__raw_writel(EPITSR_OCIF, timer_base + EPITSR);
+}
+
+static cycle_t epit_read(struct clocksource *cs)
+{
+	return 0 - __raw_readl(timer_base + EPITCNR);
+}
+
+static struct clocksource clocksource_epit = {
+	.name		= "epit",
+	.rating		= 200,
+	.read		= epit_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.shift		= 20,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init epit_clocksource_init(struct clk *timer_clk)
+{
+	unsigned int c = clk_get_rate(timer_clk);
+
+	clocksource_epit.mult = clocksource_hz2mult(c,
+					clocksource_epit.shift);
+	clocksource_register(&clocksource_epit);
+
+	return 0;
+}
+
+/* clock event */
+
+static int epit_set_next_event(unsigned long evt,
+			      struct clock_event_device *unused)
+{
+	unsigned long tcmp;
+
+	tcmp = __raw_readl(timer_base + EPITCNR);
+
+	__raw_writel(tcmp - evt, timer_base + EPITCMPR);
+
+	return 0;
+}
+
+static void epit_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	unsigned long flags;
+
+	/*
+	 * The timer interrupt generation is disabled at least
+	 * for enough time to call epit_set_next_event()
+	 */
+	local_irq_save(flags);
+
+	/* Disable interrupt in GPT module */
+	epit_irq_disable();
+
+	if (mode != clockevent_mode) {
+		/* Set event time into far-far future */
+
+		/* Clear pending interrupt */
+		epit_irq_acknowledge();
+	}
+
+	/* Remember timer mode */
+	clockevent_mode = mode;
+	local_irq_restore(flags);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		printk(KERN_ERR "epit_set_mode: Periodic mode is not "
+				"supported for i.MX EPIT\n");
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+	/*
+	 * Do not put overhead of interrupt enable/disable into
+	 * epit_set_next_event(), the core has about 4 minutes
+	 * to call epit_set_next_event() or shutdown clock after
+	 * mode switching
+	 */
+		local_irq_save(flags);
+		epit_irq_enable();
+		local_irq_restore(flags);
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_RESUME:
+		/* Left event sources disabled, no more interrupts appear */
+		break;
+	}
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &clockevent_epit;
+
+	epit_irq_acknowledge();
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction epit_timer_irq = {
+	.name		= "i.MX EPIT Timer Tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= epit_timer_interrupt,
+};
+
+static struct clock_event_device clockevent_epit = {
+	.name		= "epit",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.set_mode	= epit_set_mode,
+	.set_next_event	= epit_set_next_event,
+	.rating		= 200,
+};
+
+static int __init epit_clockevent_init(struct clk *timer_clk)
+{
+	unsigned int c = clk_get_rate(timer_clk);
+
+	clockevent_epit.mult = div_sc(c, NSEC_PER_SEC,
+					clockevent_epit.shift);
+	clockevent_epit.max_delta_ns =
+			clockevent_delta2ns(0xfffffffe, &clockevent_epit);
+	clockevent_epit.min_delta_ns =
+			clockevent_delta2ns(0x800, &clockevent_epit);
+
+	clockevent_epit.cpumask = cpumask_of(0);
+
+	clockevents_register_device(&clockevent_epit);
+
+	return 0;
+}
+
+void __init epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
+{
+	clk_enable(timer_clk);
+
+	timer_base = base;
+
+	/*
+	 * Initialise to a known state (all timers off, and timing reset)
+	 */
+	__raw_writel(0x0, timer_base + EPITCR);
+
+	__raw_writel(0xffffffff, timer_base + EPITLR);
+	__raw_writel(EPITCR_EN | EPITCR_CLKSRC_REF_HIGH | EPITCR_WAITEN,
+			timer_base + EPITCR);
+
+	/* init and register the timer to the framework */
+	epit_clocksource_init(timer_clk);
+	epit_clockevent_init(timer_clk);
+
+	/* Make irqs happen */
+	setup_irq(irq, &epit_timer_irq);
+}
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index 57ec4a8..9d38da0 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -235,7 +235,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&port->lock, flags);
-	l = (__raw_readl(reg) & (~(1 << offset))) | (value << offset);
+	l = (__raw_readl(reg) & (~(1 << offset))) | (!!value << offset);
 	__raw_writel(l, reg);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
diff --git a/arch/arm/plat-mxc/include/mach/board-mx31ads.h b/arch/arm/plat-mxc/include/mach/board-mx31ads.h
new file mode 100644
index 0000000..94b60dd4
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/board-mx31ads.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_MX31ADS_H__
+#define __ASM_ARCH_MXC_BOARD_MX31ADS_H__
+
+#include <mach/hardware.h>
+
+/*
+ * These symbols are used by drivers/net/cs89x0.c.
+ * This is ugly as hell, but we have to provide them until
+ * someone fixed the driver.
+ */
+
+/* Base address of PBC controller */
+#define PBC_BASE_ADDRESS        MX31_CS4_BASE_ADDR_VIRT
+/* Offsets for the PBC Controller register */
+
+/* Ethernet Controller IO base address */
+#define PBC_CS8900A_IOBASE      0x020000
+
+#define MXC_EXP_IO_BASE		(MXC_BOARD_IRQ_START)
+
+#define EXPIO_INT_ENET_INT	(MXC_EXP_IO_BASE + 8)
+
+#endif /* __ASM_ARCH_MXC_BOARD_MX31ADS_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 2941472..7a1e1f8 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -32,6 +32,7 @@
 extern void mx35_init_irq(void);
 extern void mx51_init_irq(void);
 extern void mxc91231_init_irq(void);
+extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq);
 extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);
 extern int mx1_clocks_init(unsigned long fref);
 extern int mx21_clocks_init(unsigned long lref, unsigned long fref);
diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
index 2560640..d56213f 100644
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ b/arch/arm/plat-mxc/include/mach/debug-macro.S
@@ -62,11 +62,9 @@
 #define UART_PADDR	MXC91231_UART2_BASE_ADDR
 #define UART_VADDR	MXC91231_IO_ADDRESS(MXC91231_UART2_BASE_ADDR)
 #endif
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		ldreq	\rx, =UART_PADDR	@ physical
-		ldrne	\rx, =UART_VADDR	@ virtual
+		.macro	addruart, rp, rv
+		ldr	\rp, =UART_PADDR	@ physical
+		ldr	\rv, =UART_VADDR	@ virtual
 		.endm
 
 		.macro	senduart,rd,rx
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index c5f68c5..86d7575 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -14,47 +14,105 @@
 		const struct resource *res, unsigned int num_resources,
 		const void *data, size_t size_data);
 
-#if defined (CONFIG_CAN_FLEXCAN) || defined (CONFIG_CAN_FLEXCAN_MODULE)
+#include <linux/fec.h>
+struct imx_fec_data {
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_fec(
+		const struct imx_fec_data *data,
+		const struct fec_platform_data *pdata);
+
 #include <linux/can/platform/flexcan.h>
 struct platform_device *__init imx_add_flexcan(int id,
 		resource_size_t iobase, resource_size_t iosize,
 		resource_size_t irq,
 		const struct flexcan_platform_data *pdata);
-#else
-/* the ifdef can be removed once the flexcan driver has been merged */
-struct flexcan_platform_data;
-static inline struct platform_device *__init imx_add_flexcan(int id,
-		resource_size_t iobase, resource_size_t iosize,
-		resource_size_t irq,
-		const struct flexcan_platform_data *pdata)
-{
-	return NULL;
-}
-#endif
 
 #include <mach/i2c.h>
-struct platform_device *__init imx_add_imx_i2c(int id,
-		resource_size_t iobase, resource_size_t iosize, int irq,
+struct imx_imx_i2c_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_i2c(
+		const struct imx_imx_i2c_data *data,
 		const struct imxi2c_platform_data *pdata);
 
+#include <mach/ssi.h>
+struct imx_imx_ssi_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+	resource_size_t dmatx0;
+	resource_size_t dmarx0;
+	resource_size_t dmatx1;
+	resource_size_t dmarx1;
+};
+struct platform_device *__init imx_add_imx_ssi(
+		const struct imx_imx_ssi_data *data,
+		const struct imx_ssi_platform_data *pdata);
+
 #include <mach/imx-uart.h>
-struct platform_device *__init imx_add_imx_uart_3irq(int id,
-		resource_size_t iobase, resource_size_t iosize,
-		resource_size_t irqrx, resource_size_t irqtx,
-		resource_size_t irqrts,
+struct imx_imx_uart_3irq_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irqrx;
+	resource_size_t irqtx;
+	resource_size_t irqrts;
+};
+struct platform_device *__init imx_add_imx_uart_3irq(
+		const struct imx_imx_uart_3irq_data *data,
 		const struct imxuart_platform_data *pdata);
-struct platform_device *__init imx_add_imx_uart_1irq(int id,
-		resource_size_t iobase, resource_size_t iosize,
-		resource_size_t irq,
+
+struct imx_imx_uart_1irq_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_uart_1irq(
+		const struct imx_imx_uart_1irq_data *data,
 		const struct imxuart_platform_data *pdata);
 
 #include <mach/mxc_nand.h>
-struct platform_device *__init imx_add_mxc_nand_v1(resource_size_t iobase,
-		int irq, const struct mxc_nand_platform_data *pdata);
-struct platform_device *__init imx_add_mxc_nand_v21(resource_size_t iobase,
-		int irq, const struct mxc_nand_platform_data *pdata);
+struct imx_mxc_nand_data {
+	/*
+	 * id is traditionally 0, but -1 is more appropriate.  We use -1 for new
+	 * machines but don't change existing devices as the nand device usually
+	 * appears in the kernel command line to pass its partitioning.
+	 */
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t axibase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_mxc_nand(
+		const struct imx_mxc_nand_data *data,
+		const struct mxc_nand_platform_data *pdata);
 
 #include <mach/spi.h>
-struct platform_device *__init imx_add_spi_imx(int id,
-		resource_size_t iobase, resource_size_t iosize, int irq,
+struct imx_spi_imx_data {
+	const char *devid;
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	int irq;
+};
+struct platform_device *__init imx_add_spi_imx(
+		const struct imx_spi_imx_data *data,
 		const struct spi_imx_master *pdata);
+
+#include <mach/esdhc.h>
+struct imx_esdhc_imx_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_esdhc(
+		const struct imx_esdhc_imx_data *data,
+		const struct esdhc_platform_data *pdata);
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
new file mode 100644
index 0000000..a48a9aa
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2010 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
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#ifndef __ASM_ARCH_IMX_ESDHC_H
+#define __ASM_ARCH_IMX_ESDHC_H
+
+struct esdhc_platform_data {
+	unsigned int wp_gpio;	/* write protect pin */
+};
+#endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h b/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h
index 656acb4..a21d331 100644
--- a/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h
+++ b/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h
@@ -28,19 +28,22 @@
  * its own devices, it calls baseboard's init function.
  * TODO: Add your own baseboard init function and call it from
  * inside eukrea_cpuimx25_init() eukrea_cpuimx27_init()
- * eukrea_cpuimx35_init() or eukrea_cpuimx51_init().
+ * eukrea_cpuimx35_init() eukrea_cpuimx51_init()
+ * or eukrea_cpuimx51sd_init().
  *
  * This example here is for the development board. Refer
  * mach-mx25/eukrea_mbimxsd-baseboard.c for cpuimx25
  * mach-imx/eukrea_mbimx27-baseboard.c for cpuimx27
  * mach-mx3/eukrea_mbimxsd-baseboard.c for cpuimx35
  * mach-mx5/eukrea_mbimx51-baseboard.c for cpuimx51
+ * mach-mx5/eukrea_mbimxsd-baseboard.c for cpuimx51sd
  */
 
 extern void eukrea_mbimxsd25_baseboard_init(void);
 extern void eukrea_mbimx27_baseboard_init(void);
 extern void eukrea_mbimxsd35_baseboard_init(void);
 extern void eukrea_mbimx51_baseboard_init(void);
+extern void eukrea_mbimxsd51_baseboard_init(void);
 
 #endif
 
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
index 21bfa46..e46b1c2 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -45,6 +45,18 @@
 				PAD_CTL_PKE | PAD_CTL_HYS)
 #define MX51_GPIO_PAD_CTRL		(PAD_CTL_DSE_HIGH | PAD_CTL_PKE | \
 				PAD_CTL_SRE_FAST)
+#define MX51_ECSPI_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
+				PAD_CTL_SRE_FAST)
+#define MX51_SDHCI_PAD_CTRL	(PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \
+				PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_SRE_FAST | \
+				PAD_CTL_DVS)
+
+#define MX51_PAD_CTRL_1	(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \
+					PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_HYS)
+#define MX51_PAD_CTRL_2	(PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX51_PAD_CTRL_3	(PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_CTRL_4	(PAD_CTL_DVS | PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX51_PAD_CTRL_5	(PAD_CTL_DVS | PAD_CTL_DSE_HIGH)
 
 /*
  * The naming convention for the pad modes is MX51_PAD_<padname>__<padmode>
@@ -106,14 +118,20 @@
 #define MX51_PAD_EIM_EB0__EIM_EB0               IOMUX_PAD(0x460, 0x0cc, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_EB1__EIM_EB1               IOMUX_PAD(0x464, 0x0d0, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_EB2__GPIO_2_22             IOMUX_PAD(0x468, 0x0d4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__FEC_MDIO		IOMUX_PAD(0x468, 0x0d4, 3, 0x0,   0, MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
 #define MX51_PAD_EIM_EB3__GPIO_2_23             IOMUX_PAD(0x46c, 0x0d8, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__FEC_RDAT1		IOMUX_PAD(0x46c, 0x0d8, 3, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_EIM_OE__GPIO_2_24              IOMUX_PAD(0x470, 0x0dc, 1, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_CS0__GPIO_2_25             IOMUX_PAD(0x474, 0x0e0, 1, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_CS1__GPIO_2_26             IOMUX_PAD(0x478, 0x0e4, 1, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_CS2__GPIO_2_27             IOMUX_PAD(0x47c, 0x0e8, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__FEC_RDAT2		IOMUX_PAD(0x47c, 0x0e8, 3, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_EIM_CS3__GPIO_2_28             IOMUX_PAD(0x480, 0x0ec, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__FEC_RDAT3		IOMUX_PAD(0x480, 0x0ec, 3, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_EIM_CS4__GPIO_2_29             IOMUX_PAD(0x484, 0x0f0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__FEC_RX_ER		IOMUX_PAD(0x484, 0x0f0, 3, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_EIM_CS5__GPIO_2_30             IOMUX_PAD(0x488, 0x0f4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__FEC_CRS		IOMUX_PAD(0x488, 0x0f4, 3, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_EIM_DTACK__GPIO_2_31           IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_LBA__GPIO_3_1              IOMUX_PAD(0x494, 0x0FC, 1, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_CRE__GPIO_3_2              IOMUX_PAD(0x4A0, 0x100, 1, 0x0,   0, NO_PAD_CTRL)
@@ -126,18 +144,32 @@
 #define MX51_PAD_NANDF_RB0__GPIO_3_8            IOMUX_PAD(0x4F8, 0x11C, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB1__GPIO_3_9            IOMUX_PAD(0x4FC, 0x120, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__GPIO_3_10           IOMUX_PAD(0x500, 0x124, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK         IOMUX_PAD(0x500, 0x124, 2, 0x0,   0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__FEC_COL		IOMUX_PAD(0x500, 0x124, 1, 0x0,   0, MX51_PAD_CTRL_2)
 #define MX51_PAD_NANDF_RB3__GPIO_3_11           IOMUX_PAD(0x504, 0x128, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__ECSPI2_MISO         IOMUX_PAD(0x504, 0x128, 2, 0x0,   0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__FEC_RXCLK		IOMUX_PAD(0x504, 0x128, 1, 0x0,   0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB6__FEC_RDAT0		IOMUX_PAD(0x5DC, 0x134, 1, 0x0,   0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_RB7__FEC_TDAT0		IOMUX_PAD(0x5E0, 0x138, 1, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_GPIO_NAND__GPIO_3_12           IOMUX_PAD(0x514, 0x12C, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_CS0__GPIO_3_16           IOMUX_PAD(0x518, 0x130, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_CS1__GPIO_3_17           IOMUX_PAD(0x51C, 0x134, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_CS2__GPIO_3_18           IOMUX_PAD(0x520, 0x138, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__FEC_TX_ER		IOMUX_PAD(0x520, 0x138, 2, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_CS3__GPIO_3_19           IOMUX_PAD(0x524, 0x13C, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__FEC_MDC		IOMUX_PAD(0x524, 0x13C, 2, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_CS4__GPIO_3_20           IOMUX_PAD(0x528, 0x140, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__FEC_TDAT1		IOMUX_PAD(0x528, 0x140, 2, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_CS5__GPIO_3_21           IOMUX_PAD(0x52C, 0x144, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__FEC_TDAT2		IOMUX_PAD(0x52C, 0x144, 2, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_CS6__GPIO_3_22           IOMUX_PAD(0x530, 0x148, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__FEC_TDAT3		IOMUX_PAD(0x530, 0x148, 2, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_CS7__GPIO_3_23           IOMUX_PAD(0x534, 0x14C, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__FEC_TX_EN		IOMUX_PAD(0x534, 0x14C, 1, 0x0,   0, MX51_PAD_CTRL_5)
 #define MX51_PAD_NANDF_RDY_INT__GPIO_3_24       IOMUX_PAD(0x538, 0x150, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	IOMUX_PAD(0x538, 0x150, 1, 0x0,   0, MX51_PAD_CTRL_4)
 #define MX51_PAD_NANDF_D15__GPIO_3_25           IOMUX_PAD(0x53C, 0x154, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__ECSPI2_MOSI         IOMUX_PAD(0x53C, 0x154, 2, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_NANDF_D14__GPIO_3_26           IOMUX_PAD(0x540, 0x158, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_D13__GPIO_3_27           IOMUX_PAD(0x544, 0x15C, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_D12__GPIO_3_28           IOMUX_PAD(0x548, 0x160, 3, 0x0,   0, NO_PAD_CTRL)
@@ -185,15 +217,25 @@
 #define MX51_PAD_I2C1_CLK__HSI2C_CLK		IOMUX_PAD(0x5E8, 0x1F8, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_I2C1_DAT__GPIO_4_17            IOMUX_PAD(0x5EC, 0x1FC, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_I2C1_DAT__HSI2C_DAT		IOMUX_PAD(0x5EC, 0x1FC, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__AUD3_BB_TXD       IOMUX_PAD(0x5F0, 0x200, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_AUD3_BB_TXD__GPIO_4_18         IOMUX_PAD(0x5F0, 0x200, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__AUD3_BB_RXD       IOMUX_PAD(0x5F4, 0x204, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_AUD3_BB_RXD__GPIO_4_19         IOMUX_PAD(0x5F4, 0x204, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__AUD3_BB_CK         IOMUX_PAD(0x5F8, 0x208, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_AUD3_BB_CK__GPIO_4_20          IOMUX_PAD(0x5F8, 0x208, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__AUD3_BB_FS         IOMUX_PAD(0x5FC, 0x20C, IOMUX_CONFIG_SION, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_AUD3_BB_FS__GPIO_4_21          IOMUX_PAD(0x5FC, 0x20C, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI        IOMUX_PAD(0x600, 0x210, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_MOSI__GPIO_4_22          IOMUX_PAD(0x600, 0x210, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO        IOMUX_PAD(0x604, 0x214, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_MISO__GPIO_4_23          IOMUX_PAD(0x604, 0x214, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0          IOMUX_PAD(0x608, 0x218, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_SS0__GPIO_4_24           IOMUX_PAD(0x608, 0x218, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1          IOMUX_PAD(0x60C, 0x21C, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_SS1__GPIO_4_25           IOMUX_PAD(0x60C, 0x21C, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY          IOMUX_PAD(0x610, 0x220, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_RDY__GPIO_4_26           IOMUX_PAD(0x610, 0x220, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK        IOMUX_PAD(0x614, 0x224, 0, 0x0,   0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_CSPI1_SCLK__GPIO_4_27          IOMUX_PAD(0x614, 0x224, 3, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_UART1_RXD__UART1_RXD           IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART1_PAD_CTRL | PAD_CTL_SRE_FAST)
 #define MX51_PAD_UART1_TXD__UART1_TXD           IOMUX_PAD(0x61C, 0x22C, 0, 0x0,   0, MX51_UART1_PAD_CTRL | PAD_CTL_SRE_FAST)
@@ -236,14 +278,14 @@
 #define MX51_PAD_USBH1_DATA6__USBH1_DATA6       IOMUX_PAD(0x6A0, 0x2A0, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
 #define MX51_PAD_USBH1_DATA7__USBH1_DATA7       IOMUX_PAD(0x6A4, 0x2A4, 0, 0x0,   0, MX51_USBH1_PAD_CTRL)
 #define MX51_PAD_DI1_PIN11__GPIO_3_0            IOMUX_PAD(0x6A8, 0x2A8, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN12__GPIO_3_1            IOMUX_PAD(0x6AC, 0x2AC, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN13__GPIO_3_2            IOMUX_PAD(0x6B0, 0x2B0, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D0_CS__GPIO_3_3            IOMUX_PAD(0x6B4, 0x2B4, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__GPIO_3_4            IOMUX_PAD(0x6B8, 0x2B8, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__GPIO_3_5       IOMUX_PAD(0x6BC, 0x2BC, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__GPIO_3_6       IOMUX_PAD(0x6C0, 0x2C0, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__GPIO_3_7       IOMUX_PAD(0x6C4, 0x2C4, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__GPIO_3_8        IOMUX_PAD(0x6C8, 0x2C8, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__GPIO_3_1            IOMUX_PAD(0x6AC, 0x2AC, 4, 0x978, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__GPIO_3_2            IOMUX_PAD(0x6B0, 0x2B0, 4, 0x97c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__GPIO_3_3            IOMUX_PAD(0x6B4, 0x2B4, 4, 0x980, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__GPIO_3_4            IOMUX_PAD(0x6B8, 0x2B8, 4, 0x984, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__GPIO_3_5       IOMUX_PAD(0x6BC, 0x2BC, 4, 0x988, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__GPIO_3_6       IOMUX_PAD(0x6C0, 0x2C0, 4, 0x98c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__GPIO_3_7       IOMUX_PAD(0x6C4, 0x2C4, 4, 0x990, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__GPIO_3_8        IOMUX_PAD(0x6C8, 0x2C8, 4, 0x994, 1, NO_PAD_CTRL)
 #define MX51_PAD_DISP1_DAT0__DISP1_DAT0         IOMUX_PAD(0x6CC, 0x2CC, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP1_DAT1__DISP1_DAT1         IOMUX_PAD(0x6D0, 0x2D0, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP1_DAT2__DISP1_DAT2         IOMUX_PAD(0x6D4, 0x2D4, 0, 0x0,   0, NO_PAD_CTRL)
@@ -294,32 +336,50 @@
 #define MX51_PAD_DISP2_DAT13__DISP2_DAT13       IOMUX_PAD(0x790, 0x388, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP2_DAT14__DISP2_DAT14       IOMUX_PAD(0x794, 0x38C, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP2_DAT15__DISP2_DAT15       IOMUX_PAD(0x798, 0x390, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__SD1_CMD               IOMUX_PAD(0x79C, 0x394, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__SD1_CLK               IOMUX_PAD(0x7A0, 0x398, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__SD1_DATA0           IOMUX_PAD(0x7A4, 0x39C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__SD1_DATA1           IOMUX_PAD(0x7A8, 0x3A0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__SD1_DATA2           IOMUX_PAD(0x7AC, 0x3A4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__SD1_DATA3           IOMUX_PAD(0x7B0, 0x3A8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_0__GPIO_1_0		IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_1__GPIO_1_1		IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__SD2_CMD               IOMUX_PAD(0x7BC, 0x3B4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__SD2_CLK               IOMUX_PAD(0x7C0, 0x3B8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA0__SD2_DATA0           IOMUX_PAD(0x7C4, 0x3BC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD2_DATA1           IOMUX_PAD(0x7C8, 0x3C0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD2_DATA2           IOMUX_PAD(0x7CC, 0x3C4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD2_DATA3           IOMUX_PAD(0x7D0, 0x3C8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_2__GPIO_1_2		IOMUX_PAD(0x7D4, 0x3CC, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79C, 0x394, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__AUD5_RXFS             IOMUX_PAD(0x79C, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7A0, 0x398, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD1_CLK__AUD5_RXC              IOMUX_PAD(0x7A0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7A4, 0x39C, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__AUD5_TXD            IOMUX_PAD(0x7A4, 0x39C, 1, 0x8d8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7A8, 0x3A0, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__AUD5_RXD            IOMUX_PAD(0x7A8, 0x3A0, 1, 0x8d4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7AC, 0x3A4, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__AUD5_TXC            IOMUX_PAD(0x7AC, 0x3A4, 1, 0x8e4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7B0, 0x3A8, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__AUD5_TXFS           IOMUX_PAD(0x7B0, 0x3A8, 1, 0x8e8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7BC, 0x3B4, IOMUX_CONFIG_SION, 0x0, 1, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7C0, 0x3B8, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7C4, 0x3BC, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7C8, 0x3C0, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7CC, 0x3C4, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7D0, 0x3C8, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO_1_0__GPIO_1_0		IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_1__GPIO_1_1		IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_2__GPIO_1_2		IOMUX_PAD(0x7D4, 0x3CC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_2__I2C2_SCL		IOMUX_PAD(0x7D4, 0x3CC, (2 | IOMUX_CONFIG_SION), \
 							0x9b8,   3, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_GPIO_1_3__GPIO_1_3		IOMUX_PAD(0x7D8, 0x3D0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_3__GPIO_1_3		IOMUX_PAD(0x7D8, 0x3D0, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_3__I2C2_SDA		IOMUX_PAD(0x7D8, 0x3D0, (2 | IOMUX_CONFIG_SION), \
 							0x9bc,   3, MX51_I2C_PAD_CTRL)
 #define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7FC, 0x3D4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_4__GPIO_1_4		IOMUX_PAD(0x804, 0x3D8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_5__GPIO_1_5		IOMUX_PAD(0x808, 0x3DC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_6__GPIO_1_6		IOMUX_PAD(0x80C, 0x3E0, 0, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_7__GPIO_1_7		IOMUX_PAD(0x810, 0x3E4, 0, 0x0,   0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_8__GPIO_1_8		IOMUX_PAD(0x814, 0x3E8, 0, 0x0,   1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_9__GPIO_1_9		IOMUX_PAD(0x818, 0x3EC, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_4__GPIO_1_4		IOMUX_PAD(0x804, 0x3D8, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_5__GPIO_1_5		IOMUX_PAD(0x808, 0x3DC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_6__GPIO_1_6		IOMUX_PAD(0x80C, 0x3E0, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_7__GPIO_1_7		IOMUX_PAD(0x810, 0x3E4, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_8__GPIO_1_8		IOMUX_PAD(0x814, 0x3E8, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_9__GPIO_1_9		IOMUX_PAD(0x818, 0x3EC, 1, 0x0,   0, MX51_GPIO_PAD_CTRL)
 
 #endif /* __MACH_IOMUX_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iram.h b/arch/arm/plat-mxc/include/mach/iram.h
new file mode 100644
index 0000000..022690c
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/iram.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <linux/errno.h>
+
+#ifdef CONFIG_IRAM_ALLOC
+
+int __init iram_init(unsigned long base, unsigned long size);
+void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr);
+void iram_free(unsigned long dma_addr, unsigned int size);
+
+#else
+
+static inline int __init iram_init(unsigned long base, unsigned long size)
+{
+	return -ENOMEM;
+}
+
+static inline void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
+{
+	return NULL;
+}
+
+static inline void iram_free(unsigned long base, unsigned long size) {}
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/mx21.h b/arch/arm/plat-mxc/include/mach/mx21.h
index ed98b9c..8bc5972 100644
--- a/arch/arm/plat-mxc/include/mach/mx21.h
+++ b/arch/arm/plat-mxc/include/mach/mx21.h
@@ -120,7 +120,7 @@
 #define MX21_INT_GPT1		26
 #define MX21_INT_WDOG		27
 #define MX21_INT_PCMCIA		28
-#define MX21_INT_NANDFC		29
+#define MX21_INT_NFC		29
 #define MX21_INT_BMI		30
 #define MX21_INT_CSI		31
 #define MX21_INT_DMACH0		32
diff --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h
index 4a6f800..cf46a45 100644
--- a/arch/arm/plat-mxc/include/mach/mx25.h
+++ b/arch/arm/plat-mxc/include/mach/mx25.h
@@ -50,8 +50,11 @@
 #define MX25_SSI1_BASE_ADDR		0x50034000
 #define MX25_NFC_BASE_ADDR		0xbb000000
 #define MX25_DRYICE_BASE_ADDR		0x53ffc000
+#define MX25_ESDHC1_BASE_ADDR		0x53fb4000
+#define MX25_ESDHC2_BASE_ADDR		0x53fb8000
 #define MX25_LCDC_BASE_ADDR		0x53fbc000
 #define MX25_KPP_BASE_ADDR		0x43fa8000
+#define MX25_SDMA_BASE_ADDR		0x53fd4000
 #define MX25_OTG_BASE_ADDR		0x53ff4000
 #define MX25_CSI_BASE_ADDR		0x53ff8000
 
@@ -59,6 +62,8 @@
 #define MX25_INT_I2C1		3
 #define MX25_INT_I2C2		4
 #define MX25_INT_UART4		5
+#define MX25_INT_ESDHC2		8
+#define MX25_INT_ESDHC1		9
 #define MX25_INT_I2C3		10
 #define MX25_INT_SSI2		11
 #define MX25_INT_SSI1		12
@@ -69,7 +74,8 @@
 #define MX25_INT_KPP		24
 #define MX25_INT_DRYICE		25
 #define MX25_INT_UART2		32
-#define MX25_INT_NANDFC		33
+#define MX25_INT_NFC		33
+#define MX25_INT_SDMA		34
 #define MX25_INT_LCDC		39
 #define MX25_INT_UART5		40
 #define MX25_INT_CAN1		43
@@ -77,4 +83,13 @@
 #define MX25_INT_UART1		45
 #define MX25_INT_FEC		57
 
+#define MX25_DMA_REQ_SSI2_RX1	22
+#define MX25_DMA_REQ_SSI2_TX1	23
+#define MX25_DMA_REQ_SSI2_RX0	24
+#define MX25_DMA_REQ_SSI2_TX0	25
+#define MX25_DMA_REQ_SSI1_RX1	26
+#define MX25_DMA_REQ_SSI1_TX1	27
+#define MX25_DMA_REQ_SSI1_RX0	28
+#define MX25_DMA_REQ_SSI1_TX0	29
+
 #endif /* ifndef __MACH_MX25_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h
index a8ab2e0..2237ba2 100644
--- a/arch/arm/plat-mxc/include/mach/mx27.h
+++ b/arch/arm/plat-mxc/include/mach/mx27.h
@@ -167,7 +167,7 @@
 #define MX27_INT_GPT1		26
 #define MX27_INT_WDOG		27
 #define MX27_INT_PCMCIA		28
-#define MX27_INT_NANDFC		29
+#define MX27_INT_NFC		29
 #define MX27_INT_ATA		30
 #define MX27_INT_CSI		31
 #define MX27_INT_DMACH0		32
diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h
index afee3ab..03e2afa 100644
--- a/arch/arm/plat-mxc/include/mach/mx31.h
+++ b/arch/arm/plat-mxc/include/mach/mx31.h
@@ -168,7 +168,7 @@
 #define MX31_INT_POWER_FAIL	30
 #define MX31_INT_CCM_DVFS	31
 #define MX31_INT_UART2		32
-#define MX31_INT_NANDFC		33
+#define MX31_INT_NFC		33
 #define MX31_INT_SDMA		34
 #define MX31_INT_USB1		35
 #define MX31_INT_USB2		36
@@ -197,6 +197,15 @@
 #define MX31_INT_EXT_WDOG	62
 #define MX31_INT_EXT_TV		63
 
+#define MX31_DMA_REQ_SSI2_RX1	22
+#define MX31_DMA_REQ_SSI2_TX1	23
+#define MX31_DMA_REQ_SSI2_RX0	24
+#define MX31_DMA_REQ_SSI2_TX0	25
+#define MX31_DMA_REQ_SSI1_RX1	26
+#define MX31_DMA_REQ_SSI1_TX1	27
+#define MX31_DMA_REQ_SSI1_RX0	28
+#define MX31_DMA_REQ_SSI1_TX0	29
+
 #define MX31_PROD_SIGNATURE		0x1	/* For MX31 */
 
 /* silicon revisions specific to i.MX31 */
diff --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h
index af3038c..ff905cb 100644
--- a/arch/arm/plat-mxc/include/mach/mx35.h
+++ b/arch/arm/plat-mxc/include/mach/mx35.h
@@ -1,5 +1,6 @@
 #ifndef __MACH_MX35_H__
 #define __MACH_MX35_H__
+
 /*
  * IRAM
  */
@@ -52,6 +53,9 @@
 #define MX35_GPIO3_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xa4000)
 #define MX35_SCC_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xac000)
 #define MX35_RNGA_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xb0000)
+#define MX35_ESDHC1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xb4000)
+#define MX35_ESDHC2_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xb8000)
+#define MX35_ESDHC3_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xbc000)
 #define MX35_IPU_CTRL_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xc0000)
 #define MX35_AUDMUX_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xc4000)
 #define MX35_GPIO1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xcc000)
@@ -63,6 +67,8 @@
 #define MX35_CAN1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xe4000)
 #define MX35_CAN2_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xe8000)
 #define MX35_RTIC_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xec000)
+#define MX35_IIM_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xf0000)
+
 #define MX35_OTG_BASE_ADDR		0x53ff4000
 
 #define MX35_ROMP_BASE_ADDR		0x60000000
@@ -122,9 +128,9 @@
 #define MX35_INT_I2C3		3
 #define MX35_INT_I2C2		4
 #define MX35_INT_RTIC		6
-#define MX35_INT_MMC_SDHC1	7
-#define MX35_INT_MMC_SDHC2	8
-#define MX35_INT_MMC_SDHC3	9
+#define MX35_INT_ESDHC1		7
+#define MX35_INT_ESDHC2		8
+#define MX35_INT_ESDHC3		9
 #define MX35_INT_I2C1		10
 #define MX35_INT_SSI1		11
 #define MX35_INT_SSI2		12
@@ -145,7 +151,7 @@
 #define MX35_INT_GPT		29
 #define MX35_INT_POWER_FAIL	30
 #define MX35_INT_UART2		32
-#define MX35_INT_NANDFC		33
+#define MX35_INT_NFC		33
 #define MX35_INT_SDMA		34
 #define MX35_INT_USBHS		35
 #define MX35_INT_USBOTG		37
@@ -173,22 +179,18 @@
 #define MX35_INT_EXT_WDOG	62
 #define MX35_INT_EXT_TV		63
 
+#define MX35_DMA_REQ_SSI2_RX1   22
+#define MX35_DMA_REQ_SSI2_TX1   23
+#define MX35_DMA_REQ_SSI2_RX0   24
+#define MX35_DMA_REQ_SSI2_TX0   25
+#define MX35_DMA_REQ_SSI1_RX1   26
+#define MX35_DMA_REQ_SSI1_TX1   27
+#define MX35_DMA_REQ_SSI1_RX0   28
+#define MX35_DMA_REQ_SSI1_TX0   29
+
 #define MX35_PROD_SIGNATURE		0x1	/* For MX31 */
 
-/* silicon revisions specific to i.MX31 */
-#define MX35_CHIP_REV_1_0		0x10
-#define MX35_CHIP_REV_1_1		0x11
-#define MX35_CHIP_REV_1_2		0x12
-#define MX35_CHIP_REV_1_3		0x13
-#define MX35_CHIP_REV_2_0		0x20
-#define MX35_CHIP_REV_2_1		0x21
-#define MX35_CHIP_REV_2_2		0x22
-#define MX35_CHIP_REV_2_3		0x23
-#define MX35_CHIP_REV_3_0		0x30
-#define MX35_CHIP_REV_3_1		0x31
-#define MX35_CHIP_REV_3_2		0x32
-
-#define MX35_SYSTEM_REV_MIN		MX35_CHIP_REV_1_0
+#define MX35_SYSTEM_REV_MIN		MX3x_CHIP_REV_1_0
 #define MX35_SYSTEM_REV_NUM		3
 
 #ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
diff --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h
index 7a356de3..d1bd26d 100644
--- a/arch/arm/plat-mxc/include/mach/mx3x.h
+++ b/arch/arm/plat-mxc/include/mach/mx3x.h
@@ -240,7 +240,7 @@
 
 #define MX3x_PROD_SIGNATURE		0x1	/* For MX31 */
 
-/* silicon revisions specific to i.MX31 */
+/* silicon revisions specific to i.MX31 and i.MX35 */
 #define MX3x_CHIP_REV_1_0		0x10
 #define MX3x_CHIP_REV_1_1		0x11
 #define MX3x_CHIP_REV_1_2		0x12
@@ -267,6 +267,14 @@
 {
 	return mx31_cpu_rev;
 }
+
+extern unsigned int mx35_cpu_rev;
+extern void mx35_read_cpu_rev(void);
+
+static inline int mx35_revision(void)
+{
+	return mx35_cpu_rev;
+}
 #endif
 
 #ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
@@ -389,19 +397,6 @@
 #define MXC_INT_EXT_WDOG MX3x_INT_EXT_WDOG
 #define MXC_INT_EXT_TV MX3x_INT_EXT_TV
 #define PROD_SIGNATURE MX3x_PROD_SIGNATURE
-#define CHIP_REV_1_0 MX3x_CHIP_REV_1_0
-#define CHIP_REV_1_1 MX3x_CHIP_REV_1_1
-#define CHIP_REV_1_2 MX3x_CHIP_REV_1_2
-#define CHIP_REV_1_3 MX3x_CHIP_REV_1_3
-#define CHIP_REV_2_0 MX3x_CHIP_REV_2_0
-#define CHIP_REV_2_1 MX3x_CHIP_REV_2_1
-#define CHIP_REV_2_2 MX3x_CHIP_REV_2_2
-#define CHIP_REV_2_3 MX3x_CHIP_REV_2_3
-#define CHIP_REV_3_0 MX3x_CHIP_REV_3_0
-#define CHIP_REV_3_1 MX3x_CHIP_REV_3_1
-#define CHIP_REV_3_2 MX3x_CHIP_REV_3_2
-#define SYSTEM_REV_MIN MX3x_SYSTEM_REV_MIN
-#define SYSTEM_REV_NUM MX3x_SYSTEM_REV_NUM
 #endif
 
 #endif /* ifndef __MACH_MX3x_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx51.h b/arch/arm/plat-mxc/include/mach/mx51.h
index 5aad344..2af7a10 100644
--- a/arch/arm/plat-mxc/include/mach/mx51.h
+++ b/arch/arm/plat-mxc/include/mach/mx51.h
@@ -1,5 +1,5 @@
-#ifndef __ASM_ARCH_MXC_MX51_H__
-#define __ASM_ARCH_MXC_MX51_H__
+#ifndef __MACH_MX51_H__
+#define __MACH_MX51_H__
 
 /*
  * MX51 memory map:
@@ -7,24 +7,23 @@
  *
  * Virt		Phys		Size	What
  * ---------------------------------------------------------------------------
- * FA3E0000	1FFE0000	128K	IRAM (SCCv2 RAM)
+ * fa3e0000	1ffe0000	128K	IRAM (SCCv2 RAM)
  *         	30000000	256M	GPU
  *         	40000000	512M	IPU
- * FA200000	60000000	1M	DEBUG
- * FB100000	70000000	1M	SPBA 0
- * FB000000	73F00000	1M	AIPS 1
- * FB200000	83F00000	1M	AIPS 2
- *		8FFFC000	16K	TZIC (interrupt controller)
+ * fa200000	60000000	1M	DEBUG
+ * fb100000	70000000	1M	SPBA 0
+ * fb000000	73f00000	1M	AIPS 1
+ * fb200000	83f00000	1M	AIPS 2
+ *		8fffc000	16K	TZIC (interrupt controller)
  *         	90000000	256M	CSD0 SDRAM/DDR
- *         	A0000000	256M	CSD1 SDRAM/DDR
- *         	B0000000	128M	CS0 Flash
- *         	B8000000	128M	CS1 Flash
- *         	C0000000	128M	CS2 Flash
- *         	C8000000	64M	CS3 Flash
- *         	CC000000	32M	CS4 SRAM
- *         	CE000000	32M	CS5 SRAM
- *		CFFF0000	64K	NFC (NAND Flash AXI)
- *
+ *         	a0000000	256M	CSD1 SDRAM/DDR
+ *         	b0000000	128M	CS0 Flash
+ *         	b8000000	128M	CS1 Flash
+ *         	c0000000	128M	CS2 Flash
+ *         	c8000000	64M	CS3 Flash
+ *         	cc000000	32M	CS4 SRAM
+ *         	ce000000	32M	CS5 SRAM
+ *		cfff0000	64K	NFC (NAND Flash AXI)
  */
 
 /*
@@ -36,65 +35,151 @@
 /*
  * IRAM
  */
-#define MX51_IRAM_BASE_ADDR		0x1FFE0000	/* internal ram */
-#define MX51_IRAM_BASE_ADDR_VIRT	0xFA3E0000
+#define MX51_IRAM_BASE_ADDR		0x1ffe0000	/* internal ram */
+#define MX51_IRAM_BASE_ADDR_VIRT	0xfa3e0000
 #define MX51_IRAM_PARTITIONS		16
-#define MX51_IRAM_PARTITIONS_TO1	12
 #define MX51_IRAM_SIZE		(MX51_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
 
-/*
- * NFC
- */
-#define MX51_NFC_AXI_BASE_ADDR		0xCFFF0000	/* NAND flash AXI */
-#define MX51_NFC_AXI_SIZE		SZ_64K
-
-/*
- * Graphics Memory of GPU
- */
 #define MX51_GPU_BASE_ADDR		0x20000000
-#define MX51_GPU2D_BASE_ADDR		0xD0000000
-
-#define MX51_TZIC_BASE_ADDR_TO1		0x8FFFC000
-#define MX51_TZIC_BASE_ADDR		0xE0000000
+#define MX51_GPU_CTRL_BASE_ADDR		0x30000000
+#define MX51_IPU_CTRL_BASE_ADDR		0x40000000
 
 #define MX51_DEBUG_BASE_ADDR		0x60000000
-#define MX51_DEBUG_BASE_ADDR_VIRT	0xFA200000
+#define MX51_DEBUG_BASE_ADDR_VIRT	0xfa200000
 #define MX51_DEBUG_SIZE			SZ_1M
-#define MX51_ETB_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00001000)
-#define MX51_ETM_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00002000)
-#define MX51_TPIU_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00003000)
-#define MX51_CTI0_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00004000)
-#define MX51_CTI1_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00005000)
-#define MX51_CTI2_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00006000)
-#define MX51_CTI3_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00007000)
-#define MX51_CORTEX_DBG_BASE_ADDR	(MX51_DEBUG_BASE_ADDR + 0x00008000)
+
+#define MX51_ETB_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x01000)
+#define MX51_ETM_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x02000)
+#define MX51_TPIU_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x03000)
+#define MX51_CTI0_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x04000)
+#define MX51_CTI1_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x05000)
+#define MX51_CTI2_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x06000)
+#define MX51_CTI3_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x07000)
+#define MX51_CORTEX_DBG_BASE_ADDR	(MX51_DEBUG_BASE_ADDR + 0x08000)
 
 /*
  * SPBA global module enabled #0
  */
-#define MX51_SPBA0_BASE_ADDR 		0x70000000
-#define MX51_SPBA0_BASE_ADDR_VIRT	0xFB100000
+#define MX51_SPBA0_BASE_ADDR		0x70000000
+#define MX51_SPBA0_BASE_ADDR_VIRT	0xfb100000
 #define MX51_SPBA0_SIZE			SZ_1M
 
-#define MX51_MMC_SDHC1_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x00004000)
-#define MX51_MMC_SDHC2_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x00008000)
-#define MX51_UART3_BASE_ADDR 		(MX51_SPBA0_BASE_ADDR + 0x0000C000)
-#define MX51_CSPI1_BASE_ADDR 		(MX51_SPBA0_BASE_ADDR + 0x00010000)
-#define MX51_SSI2_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x00014000)
-#define MX51_MMC_SDHC3_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x00020000)
-#define MX51_MMC_SDHC4_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x00024000)
-#define MX51_SPDIF_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x00028000)
-#define MX51_ATA_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x00030000)
-#define MX51_SLIM_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x00034000)
-#define MX51_HSI2C_DMA_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x00038000)
-#define MX51_SPBA_CTRL_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x0003C000)
+#define MX51_ESDHC1_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x04000)
+#define MX51_ESDHC2_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x08000)
+#define MX51_UART3_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x0c000)
+#define MX51_ECSPI1_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x10000)
+#define MX51_SSI2_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x14000)
+#define MX51_ESDHC3_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x20000)
+#define MX51_ESDHC4_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x24000)
+#define MX51_SPDIF_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x28000)
+#define MX51_ATA_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x30000)
+#define MX51_SLIM_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x34000)
+#define MX51_HSI2C_DMA_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x38000)
+#define MX51_SPBA_CTRL_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x3c000)
+
+/*
+ * AIPS 1
+ */
+#define MX51_AIPS1_BASE_ADDR		0x73f00000
+#define MX51_AIPS1_BASE_ADDR_VIRT	0xfb000000
+#define MX51_AIPS1_SIZE			SZ_1M
+
+#define MX51_OTG_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_GPIO1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x84000)
+#define MX51_GPIO2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x88000)
+#define MX51_GPIO3_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x8c000)
+#define MX51_GPIO4_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x90000)
+#define MX51_KPP_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x94000)
+#define MX51_WDOG_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x98000)
+#define MX51_WDOG2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x9c000)
+#define MX51_GPT1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa0000)
+#define MX51_SRTC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa4000)
+#define MX51_IOMUXC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa8000)
+#define MX51_EPIT1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xac000)
+#define MX51_EPIT2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb0000)
+#define MX51_PWM1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb4000)
+#define MX51_PWM2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb8000)
+#define MX51_UART1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xbc000)
+#define MX51_UART2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xc0000)
+#define MX51_SRC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd0000)
+#define MX51_CCM_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd4000)
+#define MX51_GPC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd8000)
+
+/*
+ * AIPS 2
+ */
+#define MX51_AIPS2_BASE_ADDR		0x83f00000
+#define MX51_AIPS2_BASE_ADDR_VIRT	0xfb200000
+#define MX51_AIPS2_SIZE			SZ_1M
+
+#define MX51_PLL1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x80000)
+#define MX51_PLL2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x84000)
+#define MX51_PLL3_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x88000)
+#define MX51_AHBMAX_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x94000)
+#define MX51_IIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x98000)
+#define MX51_CSU_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x9c000)
+#define MX51_ARM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa0000)
+#define MX51_OWIRE_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa4000)
+#define MX51_FIRI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa8000)
+#define MX51_ECSPI2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xac000)
+#define MX51_SDMA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb0000)
+#define MX51_SCC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb4000)
+#define MX51_ROMCP_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb8000)
+#define MX51_RTIC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xbc000)
+#define MX51_CSPI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc0000)
+#define MX51_I2C2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc4000)
+#define MX51_I2C1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc8000)
+#define MX51_SSI1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xcc000)
+#define MX51_AUDMUX_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd0000)
+#define MX51_M4IF_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd8000)
+#define MX51_ESDCTL_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd9000)
+#define MX51_WEIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xda000)
+#define MX51_NFC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdb000)
+#define MX51_EMI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdbf00)
+#define MX51_MIPI_HSC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdc000)
+#define MX51_ATA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe0000)
+#define MX51_SIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe4000)
+#define MX51_SSI3BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe8000)
+#define MX51_FEC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xec000)
+#define MX51_TVE_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf0000)
+#define MX51_VPU_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf4000)
+#define MX51_SAHARA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf8000)
+
+#define MX51_CSD0_BASE_ADDR		0x90000000
+#define MX51_CSD1_BASE_ADDR		0xa0000000
+#define MX51_CS0_BASE_ADDR		0xb0000000
+#define MX51_CS1_BASE_ADDR		0xb8000000
+#define MX51_CS2_BASE_ADDR		0xc0000000
+#define MX51_CS3_BASE_ADDR		0xc8000000
+#define MX51_CS4_BASE_ADDR		0xcc000000
+#define MX51_CS5_BASE_ADDR		0xce000000
+
+/*
+ * NFC
+ */
+#define MX51_NFC_AXI_BASE_ADDR		0xcfff0000	/* NAND flash AXI */
+#define MX51_NFC_AXI_SIZE		SZ_64K
+
+#define MX51_GPU2D_BASE_ADDR		0xd0000000
+#define MX51_TZIC_BASE_ADDR		0xe0000000
+
+#define MX51_IO_ADDRESS(x) (						\
+	IMX_IO_ADDRESS(x, MX51_IRAM) ?:					\
+	IMX_IO_ADDRESS(x, MX51_DEBUG) ?:				\
+	IMX_IO_ADDRESS(x, MX51_SPBA0) ?:				\
+	IMX_IO_ADDRESS(x, MX51_AIPS1) ?:				\
+	IMX_IO_ADDRESS(x, MX51_AIPS2))
+
+/* This is currently used in <mach/debug-macro.S>, but should go away */
+#define MX51_AIPS1_IO_ADDRESS(x)  \
+	(((x) - MX51_AIPS1_BASE_ADDR) + MX51_AIPS1_BASE_ADDR_VIRT)
 
 /*
  * defines for SPBA modules
  */
 #define MX51_SPBA_SDHC1	0x04
 #define MX51_SPBA_SDHC2	0x08
-#define MX51_SPBA_UART3	0x0C
+#define MX51_SPBA_UART3	0x0c
 #define MX51_SPBA_CSPI1	0x10
 #define MX51_SPBA_SSI2	0x14
 #define MX51_SPBA_SDHC3	0x20
@@ -103,35 +188,7 @@
 #define MX51_SPBA_ATA	0x30
 #define MX51_SPBA_SLIM	0x34
 #define MX51_SPBA_HSI2C	0x38
-#define MX51_SPBA_CTRL	0x3C
-
-/*
- * AIPS 1
- */
-#define MX51_AIPS1_BASE_ADDR 	0x73F00000
-#define MX51_AIPS1_BASE_ADDR_VIRT	0xFB000000
-#define MX51_AIPS1_SIZE		SZ_1M
-
-#define MX51_OTG_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x00080000)
-#define MX51_GPIO1_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x00084000)
-#define MX51_GPIO2_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x00088000)
-#define MX51_GPIO3_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x0008C000)
-#define MX51_GPIO4_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x00090000)
-#define MX51_KPP_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x00094000)
-#define MX51_WDOG_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x00098000)
-#define MX51_WDOG2_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x0009C000)
-#define MX51_GPT1_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000A0000)
-#define MX51_SRTC_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000A4000)
-#define MX51_IOMUXC_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000A8000)
-#define MX51_EPIT1_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000AC000)
-#define MX51_EPIT2_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000B0000)
-#define MX51_PWM1_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000B4000)
-#define MX51_PWM2_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000B8000)
-#define MX51_UART1_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000BC000)
-#define MX51_UART2_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000C0000)
-#define MX51_SRC_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000D0000)
-#define MX51_CCM_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000D4000)
-#define MX51_GPC_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000D8000)
+#define MX51_SPBA_CTRL	0x3c
 
 /*
  * Defines for modules using static and dynamic DMA channels
@@ -164,282 +221,186 @@
 #define MX51_MXC_DMA_CHANNEL_ATA_TX	MXC_DMA_DYNAMIC_CHANNEL
 #define MX51_MXC_DMA_CHANNEL_MEMORY	MXC_DMA_DYNAMIC_CHANNEL
 
-/*
- * AIPS 2
- */
-#define MX51_AIPS2_BASE_ADDR		0x83F00000
-#define MX51_AIPS2_BASE_ADDR_VIRT	0xFB200000
-#define MX51_AIPS2_SIZE			SZ_1M
-
-#define MX51_PLL1_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x00080000)
-#define MX51_PLL2_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x00084000)
-#define MX51_PLL3_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x00088000)
-#define MX51_AHBMAX_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x00094000)
-#define MX51_IIM_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x00098000)
-#define MX51_CSU_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x0009C000)
-#define MX51_ARM_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000A0000)
-#define MX51_OWIRE_BASE_ADDR 	(MX51_AIPS2_BASE_ADDR + 0x000A4000)
-#define MX51_FIRI_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000A8000)
-#define MX51_CSPI2_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000AC000)
-#define MX51_SDMA_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000B0000)
-#define MX51_SCC_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000B4000)
-#define MX51_ROMCP_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000B8000)
-#define MX51_RTIC_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000BC000)
-#define MX51_CSPI3_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000C0000)
-#define MX51_I2C2_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000C4000)
-#define MX51_I2C1_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000C8000)
-#define MX51_SSI1_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000CC000)
-#define MX51_AUDMUX_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000D0000)
-#define MX51_M4IF_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000D8000)
-#define MX51_ESDCTL_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000D9000)
-#define MX51_WEIM_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000DA000)
-#define MX51_NFC_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000DB000)
-#define MX51_EMI_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000DBF00)
-#define MX51_MIPI_HSC_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000DC000)
-#define MX51_ATA_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000E0000)
-#define MX51_SIM_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000E4000)
-#define MX51_SSI3BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000E8000)
-#define MX51_MXC_FEC_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000EC000)
-#define MX51_TVE_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000F0000)
-#define MX51_VPU_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000F4000)
-#define MX51_SAHARA_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000F8000)
-
-/*
- * Memory regions and CS
- */
-#define MX51_GPU_CTRL_BASE_ADDR		0x30000000
-#define MX51_IPU_CTRL_BASE_ADDR		0x40000000
-#define MX51_CSD0_BASE_ADDR		0x90000000
-#define MX51_CSD1_BASE_ADDR		0xA0000000
-#define MX51_CS0_BASE_ADDR		0xB0000000
-#define MX51_CS1_BASE_ADDR		0xB8000000
-#define MX51_CS2_BASE_ADDR		0xC0000000
-#define MX51_CS3_BASE_ADDR		0xC8000000
-#define MX51_CS4_BASE_ADDR		0xCC000000
-#define MX51_CS5_BASE_ADDR		0xCE000000
-
-/* Does given address belongs to the specified memory region? */
-#define ADDRESS_IN_REGION(addr, start, size)			\
-	(((addr) >= (start)) && ((addr) < (start)+(size)))
-
-/* Does given address belongs to the specified named `module'? */
-#define MX51_IS_MODULE(addr, module)			       \
-	ADDRESS_IN_REGION(addr, MX51_ ## module ## _BASE_ADDR, \
-				MX51_ ## module ## _SIZE)
-/*
- * This macro defines the physical to virtual address mapping for all the
- * peripheral modules. It is used by passing in the physical address as x
- * and returning the virtual address. If the physical address is not mapped,
- * it returns 0xDEADBEEF
- */
-
-#define MX51_IO_ADDRESS(x)					\
-	(void __iomem *)					\
-	(MX51_IS_MODULE(x, IRAM) ? MX51_IRAM_IO_ADDRESS(x) :	\
-	MX51_IS_MODULE(x, DEBUG) ? MX51_DEBUG_IO_ADDRESS(x) :	\
-	MX51_IS_MODULE(x, SPBA0) ? MX51_SPBA0_IO_ADDRESS(x) :	\
-	MX51_IS_MODULE(x, AIPS1) ? MX51_AIPS1_IO_ADDRESS(x) :	\
-	MX51_IS_MODULE(x, AIPS2) ? MX51_AIPS2_IO_ADDRESS(x) : \
-	0xDEADBEEF)
-
-/*
- * define the address mapping macros: in physical address order
- */
-#define MX51_IRAM_IO_ADDRESS(x)  \
-	(((x) - MX51_IRAM_BASE_ADDR) + MX51_IRAM_BASE_ADDR_VIRT)
-
-#define MX51_DEBUG_IO_ADDRESS(x)  \
-	(((x) - MX51_DEBUG_BASE_ADDR) + MX51_DEBUG_BASE_ADDR_VIRT)
-
-#define MX51_SPBA0_IO_ADDRESS(x)  \
-	(((x) - MX51_SPBA0_BASE_ADDR) + MX51_SPBA0_BASE_ADDR_VIRT)
-
-#define MX51_AIPS1_IO_ADDRESS(x)  \
-	(((x) - MX51_AIPS1_BASE_ADDR) + MX51_AIPS1_BASE_ADDR_VIRT)
-
-#define MX51_AIPS2_IO_ADDRESS(x)  \
-	(((x) - MX51_AIPS2_BASE_ADDR) + MX51_AIPS2_BASE_ADDR_VIRT)
-
 #define MX51_IS_MEM_DEVICE_NONSHARED(x)		0
 
 /*
  * DMA request assignments
  */
-#define MX51_DMA_REQ_SSI3_TX1	47
-#define MX51_DMA_REQ_SSI3_RX1	46
-#define MX51_DMA_REQ_SPDIF	45
-#define MX51_DMA_REQ_UART3_TX	44
-#define MX51_DMA_REQ_UART3_RX	43
-#define MX51_DMA_REQ_SLIM_B_TX	42
-#define MX51_DMA_REQ_SDHC4	41
-#define MX51_DMA_REQ_SDHC3	40
-#define MX51_DMA_REQ_CSPI_TX	39
-#define MX51_DMA_REQ_CSPI_RX	38
-#define MX51_DMA_REQ_SSI3_TX2	37
-#define MX51_DMA_REQ_IPU	36
-#define MX51_DMA_REQ_SSI3_RX2	35
-#define MX51_DMA_REQ_EPIT2	34
-#define MX51_DMA_REQ_CTI2_1	33
-#define MX51_DMA_REQ_EMI_WR	32
-#define MX51_DMA_REQ_CTI2_0	31
-#define MX51_DMA_REQ_EMI_RD	30
-#define MX51_DMA_REQ_SSI1_TX1	29
-#define MX51_DMA_REQ_SSI1_RX1	28
-#define MX51_DMA_REQ_SSI1_TX2	27
-#define MX51_DMA_REQ_SSI1_RX2	26
-#define MX51_DMA_REQ_SSI2_TX1	25
-#define MX51_DMA_REQ_SSI2_RX1	24
-#define MX51_DMA_REQ_SSI2_TX2	23
-#define MX51_DMA_REQ_SSI2_RX2	22
-#define MX51_DMA_REQ_SDHC2	21
-#define MX51_DMA_REQ_SDHC1	20
-#define MX51_DMA_REQ_UART1_TX	19
-#define MX51_DMA_REQ_UART1_RX	18
-#define MX51_DMA_REQ_UART2_TX	17
-#define MX51_DMA_REQ_UART2_RX	16
-#define MX51_DMA_REQ_GPU	15
-#define MX51_DMA_REQ_EXTREQ1	14
-#define MX51_DMA_REQ_FIRI_TX	13
-#define MX51_DMA_REQ_FIRI_RX	12
-#define MX51_DMA_REQ_HS_I2C_RX	11
-#define MX51_DMA_REQ_HS_I2C_TX	10
-#define MX51_DMA_REQ_CSPI2_TX	9
-#define MX51_DMA_REQ_CSPI2_RX	8
-#define MX51_DMA_REQ_CSPI1_TX	7
-#define MX51_DMA_REQ_CSPI1_RX	6
-#define MX51_DMA_REQ_SLIM_B	5
-#define MX51_DMA_REQ_ATA_TX_END	4
-#define MX51_DMA_REQ_ATA_TX	3
-#define MX51_DMA_REQ_ATA_RX	2
-#define MX51_DMA_REQ_GPC	1
-#define MX51_DMA_REQ_VPU	0
+#define MX51_DMA_REQ_VPU		0
+#define MX51_DMA_REQ_GPC		1
+#define MX51_DMA_REQ_ATA_RX		2
+#define MX51_DMA_REQ_ATA_TX		3
+#define MX51_DMA_REQ_ATA_TX_END		4
+#define MX51_DMA_REQ_SLIM_B		5
+#define MX51_DMA_REQ_CSPI1_RX		6
+#define MX51_DMA_REQ_CSPI1_TX		7
+#define MX51_DMA_REQ_CSPI2_RX		8
+#define MX51_DMA_REQ_CSPI2_TX		9
+#define MX51_DMA_REQ_HS_I2C_TX		10
+#define MX51_DMA_REQ_HS_I2C_RX		11
+#define MX51_DMA_REQ_FIRI_RX		12
+#define MX51_DMA_REQ_FIRI_TX		13
+#define MX51_DMA_REQ_EXTREQ1		14
+#define MX51_DMA_REQ_GPU		15
+#define MX51_DMA_REQ_UART2_RX		16
+#define MX51_DMA_REQ_UART2_TX		17
+#define MX51_DMA_REQ_UART1_RX		18
+#define MX51_DMA_REQ_UART1_TX		19
+#define MX51_DMA_REQ_SDHC1		20
+#define MX51_DMA_REQ_SDHC2		21
+#define MX51_DMA_REQ_SSI2_RX1		22
+#define MX51_DMA_REQ_SSI2_TX1		23
+#define MX51_DMA_REQ_SSI2_RX0		24
+#define MX51_DMA_REQ_SSI2_TX0		25
+#define MX51_DMA_REQ_SSI1_RX1		26
+#define MX51_DMA_REQ_SSI1_TX1		27
+#define MX51_DMA_REQ_SSI1_RX0		28
+#define MX51_DMA_REQ_SSI1_TX0		29
+#define MX51_DMA_REQ_EMI_RD		30
+#define MX51_DMA_REQ_CTI2_0		31
+#define MX51_DMA_REQ_EMI_WR		32
+#define MX51_DMA_REQ_CTI2_1		33
+#define MX51_DMA_REQ_EPIT2		34
+#define MX51_DMA_REQ_SSI3_RX2		35
+#define MX51_DMA_REQ_IPU		36
+#define MX51_DMA_REQ_SSI3_TX2		37
+#define MX51_DMA_REQ_CSPI_RX		38
+#define MX51_DMA_REQ_CSPI_TX		39
+#define MX51_DMA_REQ_SDHC3		40
+#define MX51_DMA_REQ_SDHC4		41
+#define MX51_DMA_REQ_SLIM_B_TX		42
+#define MX51_DMA_REQ_UART3_RX		43
+#define MX51_DMA_REQ_UART3_TX		44
+#define MX51_DMA_REQ_SPDIF		45
+#define MX51_DMA_REQ_SSI3_RX1		46
+#define MX51_DMA_REQ_SSI3_TX1		47
 
 /*
  * Interrupt numbers
  */
-#define MX51_MXC_INT_BASE	0
-#define MX51_MXC_INT_RESV0	0
-#define MX51_MXC_INT_MMC_SDHC1	1
-#define MX51_MXC_INT_MMC_SDHC2	2
-#define MX51_MXC_INT_MMC_SDHC3	3
-#define MX51_MXC_INT_MMC_SDHC4	4
-#define MX51_MXC_INT_RESV5	5
-#define MX51_MXC_INT_SDMA	6
-#define MX51_MXC_INT_IOMUX	7
-#define MX51_MXC_INT_NFC	8
-#define MX51_MXC_INT_VPU	9
-#define MX51_MXC_INT_IPU_ERR	10
-#define MX51_MXC_INT_IPU_SYN	11
-#define MX51_MXC_INT_GPU	12
-#define MX51_MXC_INT_RESV13	13
-#define MX51_MXC_INT_USB_H1	14
-#define MX51_MXC_INT_EMI	15
-#define MX51_MXC_INT_USB_H2	16
-#define MX51_MXC_INT_USB_H3	17
-#define MX51_MXC_INT_USB_OTG	18
-#define MX51_MXC_INT_SAHARA_H0	19
-#define MX51_MXC_INT_SAHARA_H1	20
-#define MX51_MXC_INT_SCC_SMN	21
-#define MX51_MXC_INT_SCC_STZ	22
-#define MX51_MXC_INT_SCC_SCM	23
-#define MX51_MXC_INT_SRTC_NTZ	24
-#define MX51_MXC_INT_SRTC_TZ	25
-#define MX51_MXC_INT_RTIC	26
-#define MX51_MXC_INT_CSU	27
-#define MX51_MXC_INT_SLIM_B	28
-#define MX51_MXC_INT_SSI1	29
-#define MX51_MXC_INT_SSI2	30
-#define MX51_MXC_INT_UART1	31
-#define MX51_MXC_INT_UART2	32
-#define MX51_MXC_INT_UART3	33
-#define MX51_MXC_INT_RESV34	34
-#define MX51_MXC_INT_RESV35	35
-#define MX51_MXC_INT_CSPI1	36
-#define MX51_MXC_INT_CSPI2	37
-#define MX51_MXC_INT_CSPI	38
-#define MX51_MXC_INT_GPT	39
-#define MX51_MXC_INT_EPIT1	40
-#define MX51_MXC_INT_EPIT2	41
-#define MX51_MXC_INT_GPIO1_INT7	42
-#define MX51_MXC_INT_GPIO1_INT6	43
-#define MX51_MXC_INT_GPIO1_INT5	44
-#define MX51_MXC_INT_GPIO1_INT4	45
-#define MX51_MXC_INT_GPIO1_INT3	46
-#define MX51_MXC_INT_GPIO1_INT2	47
-#define MX51_MXC_INT_GPIO1_INT1	48
-#define MX51_MXC_INT_GPIO1_INT0	49
-#define MX51_MXC_INT_GPIO1_LOW	50
-#define MX51_MXC_INT_GPIO1_HIGH	51
-#define MX51_MXC_INT_GPIO2_LOW	52
-#define MX51_MXC_INT_GPIO2_HIGH	53
-#define MX51_MXC_INT_GPIO3_LOW	54
-#define MX51_MXC_INT_GPIO3_HIGH	55
-#define MX51_MXC_INT_GPIO4_LOW	56
-#define MX51_MXC_INT_GPIO4_HIGH	57
-#define MX51_MXC_INT_WDOG1	58
-#define MX51_MXC_INT_WDOG2	59
-#define MX51_MXC_INT_KPP	60
-#define MX51_MXC_INT_PWM1	61
-#define MX51_MXC_INT_I2C1	62
-#define MX51_MXC_INT_I2C2	63
-#define MX51_MXC_INT_HS_I2C	64
-#define MX51_MXC_INT_RESV65	65
-#define MX51_MXC_INT_RESV66	66
-#define MX51_MXC_INT_SIM_IPB	67
-#define MX51_MXC_INT_SIM_DAT	68
-#define MX51_MXC_INT_IIM	69
-#define MX51_MXC_INT_ATA	70
-#define MX51_MXC_INT_CCM1	71
-#define MX51_MXC_INT_CCM2	72
-#define MX51_MXC_INT_GPC1	73
-#define MX51_MXC_INT_GPC2	74
-#define MX51_MXC_INT_SRC	75
-#define MX51_MXC_INT_NM		76
-#define MX51_MXC_INT_PMU	77
-#define MX51_MXC_INT_CTI_IRQ	78
-#define MX51_MXC_INT_CTI1_TG0	79
-#define MX51_MXC_INT_CTI1_TG1	80
-#define MX51_MXC_INT_MCG_ERR	81
-#define MX51_MXC_INT_MCG_TMR	82
-#define MX51_MXC_INT_MCG_FUNC	83
-#define MX51_MXC_INT_GPU2_IRQ	84
-#define MX51_MXC_INT_GPU2_BUSY	85
-#define MX51_MXC_INT_RESV86	86
-#define MX51_MXC_INT_FEC	87
-#define MX51_MXC_INT_OWIRE	88
-#define MX51_MXC_INT_CTI1_TG2	89
-#define MX51_MXC_INT_SJC	90
-#define MX51_MXC_INT_SPDIF	91
-#define MX51_MXC_INT_TVE	92
-#define MX51_MXC_INT_FIRI	93
-#define MX51_MXC_INT_PWM2	94
-#define MX51_MXC_INT_SLIM_EXP	95
-#define MX51_MXC_INT_SSI3	96
-#define MX51_MXC_INT_EMI_BOOT	97
-#define MX51_MXC_INT_CTI1_TG3	98
-#define MX51_MXC_INT_SMC_RX	99
-#define MX51_MXC_INT_VPU_IDLE	100
-#define MX51_MXC_INT_EMI_NFC	101
-#define MX51_MXC_INT_GPU_IDLE	102
+#define MX51_MXC_INT_BASE		0
+#define MX51_MXC_INT_RESV0		0
+#define MX51_INT_ESDHC1			1
+#define MX51_INT_ESDHC2			2
+#define MX51_INT_ESDHC3			3
+#define MX51_INT_ESDHC4			4
+#define MX51_MXC_INT_RESV5		5
+#define MX51_INT_SDMA			6
+#define MX51_MXC_INT_IOMUX		7
+#define MX51_INT_NFC			8
+#define MX51_MXC_INT_VPU		9
+#define MX51_MXC_INT_IPU_ERR		10
+#define MX51_MXC_INT_IPU_SYN		11
+#define MX51_MXC_INT_GPU		12
+#define MX51_MXC_INT_RESV13		13
+#define MX51_MXC_INT_USB_H1		14
+#define MX51_MXC_INT_EMI		15
+#define MX51_MXC_INT_USB_H2		16
+#define MX51_MXC_INT_USB_H3		17
+#define MX51_MXC_INT_USB_OTG		18
+#define MX51_MXC_INT_SAHARA_H0		19
+#define MX51_MXC_INT_SAHARA_H1		20
+#define MX51_MXC_INT_SCC_SMN		21
+#define MX51_MXC_INT_SCC_STZ		22
+#define MX51_MXC_INT_SCC_SCM		23
+#define MX51_MXC_INT_SRTC_NTZ		24
+#define MX51_MXC_INT_SRTC_TZ		25
+#define MX51_MXC_INT_RTIC		26
+#define MX51_MXC_INT_CSU		27
+#define MX51_MXC_INT_SLIM_B		28
+#define MX51_INT_SSI1			29
+#define MX51_INT_SSI2			30
+#define MX51_INT_UART1			31
+#define MX51_INT_UART2			32
+#define MX51_INT_UART3			33
+#define MX51_MXC_INT_RESV34		34
+#define MX51_MXC_INT_RESV35		35
+#define MX51_INT_ECSPI1			36
+#define MX51_INT_ECSPI2			37
+#define MX51_INT_CSPI			38
+#define MX51_MXC_INT_GPT		39
+#define MX51_MXC_INT_EPIT1		40
+#define MX51_MXC_INT_EPIT2		41
+#define MX51_MXC_INT_GPIO1_INT7		42
+#define MX51_MXC_INT_GPIO1_INT6		43
+#define MX51_MXC_INT_GPIO1_INT5		44
+#define MX51_MXC_INT_GPIO1_INT4		45
+#define MX51_MXC_INT_GPIO1_INT3		46
+#define MX51_MXC_INT_GPIO1_INT2		47
+#define MX51_MXC_INT_GPIO1_INT1		48
+#define MX51_MXC_INT_GPIO1_INT0		49
+#define MX51_MXC_INT_GPIO1_LOW		50
+#define MX51_MXC_INT_GPIO1_HIGH		51
+#define MX51_MXC_INT_GPIO2_LOW		52
+#define MX51_MXC_INT_GPIO2_HIGH		53
+#define MX51_MXC_INT_GPIO3_LOW		54
+#define MX51_MXC_INT_GPIO3_HIGH		55
+#define MX51_MXC_INT_GPIO4_LOW		56
+#define MX51_MXC_INT_GPIO4_HIGH		57
+#define MX51_MXC_INT_WDOG1		58
+#define MX51_MXC_INT_WDOG2		59
+#define MX51_MXC_INT_KPP		60
+#define MX51_MXC_INT_PWM1		61
+#define MX51_INT_I2C1			62
+#define MX51_INT_I2C2			63
+#define MX51_MXC_INT_HS_I2C		64
+#define MX51_MXC_INT_RESV65		65
+#define MX51_MXC_INT_RESV66		66
+#define MX51_MXC_INT_SIM_IPB		67
+#define MX51_MXC_INT_SIM_DAT		68
+#define MX51_MXC_INT_IIM		69
+#define MX51_MXC_INT_ATA		70
+#define MX51_MXC_INT_CCM1		71
+#define MX51_MXC_INT_CCM2		72
+#define MX51_MXC_INT_GPC1		73
+#define MX51_MXC_INT_GPC2		74
+#define MX51_MXC_INT_SRC		75
+#define MX51_MXC_INT_NM			76
+#define MX51_MXC_INT_PMU		77
+#define MX51_MXC_INT_CTI_IRQ		78
+#define MX51_MXC_INT_CTI1_TG0		79
+#define MX51_MXC_INT_CTI1_TG1		80
+#define MX51_MXC_INT_MCG_ERR		81
+#define MX51_MXC_INT_MCG_TMR		82
+#define MX51_MXC_INT_MCG_FUNC		83
+#define MX51_MXC_INT_GPU2_IRQ		84
+#define MX51_MXC_INT_GPU2_BUSY		85
+#define MX51_MXC_INT_RESV86		86
+#define MX51_INT_FEC			87
+#define MX51_MXC_INT_OWIRE		88
+#define MX51_MXC_INT_CTI1_TG2		89
+#define MX51_MXC_INT_SJC		90
+#define MX51_MXC_INT_SPDIF		91
+#define MX51_MXC_INT_TVE		92
+#define MX51_MXC_INT_FIRI		93
+#define MX51_MXC_INT_PWM2		94
+#define MX51_MXC_INT_SLIM_EXP		95
+#define MX51_MXC_INT_SSI3		96
+#define MX51_MXC_INT_EMI_BOOT		97
+#define MX51_MXC_INT_CTI1_TG3		98
+#define MX51_MXC_INT_SMC_RX		99
+#define MX51_MXC_INT_VPU_IDLE		100
+#define MX51_MXC_INT_EMI_NFC		101
+#define MX51_MXC_INT_GPU_IDLE		102
 
 /* silicon revisions specific to i.MX51 */
-#define MX51_CHIP_REV_1_0	0x10
-#define MX51_CHIP_REV_1_1	0x11
-#define MX51_CHIP_REV_1_2	0x12
-#define MX51_CHIP_REV_1_3	0x13
-#define MX51_CHIP_REV_2_0	0x20
-#define MX51_CHIP_REV_2_1	0x21
-#define MX51_CHIP_REV_2_2	0x22
-#define MX51_CHIP_REV_2_3	0x23
-#define MX51_CHIP_REV_3_0	0x30
-#define MX51_CHIP_REV_3_1	0x31
-#define MX51_CHIP_REV_3_2	0x32
-
-/* Mandatory defines used globally */
+#define MX51_CHIP_REV_1_0		0x10
+#define MX51_CHIP_REV_1_1		0x11
+#define MX51_CHIP_REV_1_2		0x12
+#define MX51_CHIP_REV_1_3		0x13
+#define MX51_CHIP_REV_2_0		0x20
+#define MX51_CHIP_REV_2_1		0x21
+#define MX51_CHIP_REV_2_2		0x22
+#define MX51_CHIP_REV_2_3		0x23
+#define MX51_CHIP_REV_3_0		0x30
+#define MX51_CHIP_REV_3_1		0x31
+#define MX51_CHIP_REV_3_2		0x32
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-
 extern int mx51_revision(void);
 #endif
 
-#endif	/*  __ASM_ARCH_MXC_MX51_H__ */
+/* tape-out 1 defines */
+#define MX51_TZIC_BASE_ADDR_TO1		0x8fffc000
+
+#endif	/* ifndef __MACH_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h
index 4acd114..95be51b 100644
--- a/arch/arm/plat-mxc/include/mach/system.h
+++ b/arch/arm/plat-mxc/include/mach/system.h
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999 ARM Limited
  *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *  Copyright 2004-2008 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
@@ -28,8 +28,34 @@
 		mxc91231_prepare_idle();
 	}
 #endif
-
-	cpu_do_idle();
+	/* fix i.MX31 errata TLSbo65953 and i.MX35 errata ENGcm09472 */
+	if (cpu_is_mx31() || cpu_is_mx35()) {
+		unsigned long reg = 0;
+		__asm__ __volatile__(
+			/* disable I and D cache */
+			"mrc p15, 0, %0, c1, c0, 0\n"
+			"bic %0, %0, #0x00001000\n"
+			"bic %0, %0, #0x00000004\n"
+			"mcr p15, 0, %0, c1, c0, 0\n"
+			/* invalidate I cache */
+			"mov %0, #0\n"
+			"mcr p15, 0, %0, c7, c5, 0\n"
+			/* clear and invalidate D cache */
+			"mov %0, #0\n"
+			"mcr p15, 0, %0, c7, c14, 0\n"
+			/* WFI */
+			"mov %0, #0\n"
+			"mcr p15, 0, %0, c7, c0, 4\n"
+			"nop\n" "nop\n" "nop\n" "nop\n"
+			"nop\n" "nop\n" "nop\n"
+			/* enable I and D cache */
+			"mrc p15, 0, %0, c1, c0, 0\n"
+			"orr %0, %0, #0x00001000\n"
+			"orr %0, %0, #0x00000004\n"
+			"mcr p15, 0, %0, c1, c0, 0\n"
+			: "=r" (reg));
+	} else
+		cpu_do_idle();
 }
 
 void arch_reset(char mode, const char *cmd);
diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
index d9bd37e..9dd9c20 100644
--- a/arch/arm/plat-mxc/include/mach/uncompress.h
+++ b/arch/arm/plat-mxc/include/mach/uncompress.h
@@ -99,6 +99,7 @@
 		uart_base = MX3X_UART2_BASE_ADDR;
 		break;
 	case MACH_TYPE_MX51_BABBAGE:
+	case MACH_TYPE_EUKREA_CPUIMX51SD:
 		uart_base = MX51_UART1_BASE_ADDR;
 		break;
 	default:
diff --git a/arch/arm/plat-mxc/iram_alloc.c b/arch/arm/plat-mxc/iram_alloc.c
new file mode 100644
index 0000000..074c386
--- /dev/null
+++ b/arch/arm/plat-mxc/iram_alloc.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/genalloc.h>
+#include <mach/iram.h>
+
+static unsigned long iram_phys_base;
+static void __iomem *iram_virt_base;
+static struct gen_pool *iram_pool;
+
+static inline void __iomem *iram_phys_to_virt(unsigned long p)
+{
+	return iram_virt_base + (p - iram_phys_base);
+}
+
+void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
+{
+	if (!iram_pool)
+		return NULL;
+
+	*dma_addr = gen_pool_alloc(iram_pool, size);
+	pr_debug("iram alloc - %dB@0x%lX\n", size, *dma_addr);
+	if (!*dma_addr)
+		return NULL;
+	return iram_phys_to_virt(*dma_addr);
+}
+EXPORT_SYMBOL(iram_alloc);
+
+void iram_free(unsigned long addr, unsigned int size)
+{
+	if (!iram_pool)
+		return;
+
+	gen_pool_free(iram_pool, addr, size);
+}
+EXPORT_SYMBOL(iram_free);
+
+int __init iram_init(unsigned long base, unsigned long size)
+{
+	iram_phys_base = base;
+
+	iram_pool = gen_pool_create(PAGE_SHIFT, -1);
+	if (!iram_pool)
+		return -ENOMEM;
+
+	gen_pool_add(iram_pool, base, size, -1);
+	iram_virt_base = ioremap(iram_phys_base, size);
+	if (!iram_virt_base)
+		return -EIO;
+
+	pr_debug("i.MX IRAM pool: %ld KB@0x%p\n", size / 1024, iram_virt_base);
+	return 0;
+}
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c
index 977c8f9..85e6fd21 100644
--- a/arch/arm/plat-nomadik/gpio.c
+++ b/arch/arm/plat-nomadik/gpio.c
@@ -102,6 +102,22 @@
 	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
 }
 
+static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip,
+				  unsigned offset, int val)
+{
+	if (val)
+		writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS);
+	else
+		writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC);
+}
+
+static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
+				  unsigned offset, int val)
+{
+	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
+	__nmk_gpio_set_output(nmk_chip, offset, val);
+}
+
 static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
 			     pin_cfg_t cfg)
 {
@@ -118,20 +134,29 @@
 		[3] /* illegal */	= "??"
 	};
 	static const char *slpmnames[] = {
-		[NMK_GPIO_SLPM_INPUT]		= "input",
-		[NMK_GPIO_SLPM_NOCHANGE]	= "no-change",
+		[NMK_GPIO_SLPM_INPUT]		= "input/wakeup",
+		[NMK_GPIO_SLPM_NOCHANGE]	= "no-change/no-wakeup",
 	};
 
 	int pin = PIN_NUM(cfg);
 	int pull = PIN_PULL(cfg);
 	int af = PIN_ALT(cfg);
 	int slpm = PIN_SLPM(cfg);
+	int output = PIN_DIR(cfg);
+	int val = PIN_VAL(cfg);
 
-	dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s\n",
-		pin, afnames[af], pullnames[pull], slpmnames[slpm]);
+	dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n",
+		pin, afnames[af], pullnames[pull], slpmnames[slpm],
+		output ? "output " : "input",
+		output ? (val ? "high" : "low") : "");
 
-	__nmk_gpio_make_input(nmk_chip, offset);
-	__nmk_gpio_set_pull(nmk_chip, offset, pull);
+	if (output)
+		__nmk_gpio_make_output(nmk_chip, offset, val);
+	else {
+		__nmk_gpio_make_input(nmk_chip, 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);
 }
@@ -200,6 +225,10 @@
  * changed to an input (with pullup/down enabled) in sleep and deep sleep.  If
  * @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was
  * configured even when in sleep and deep sleep.
+ *
+ * On DB8500v2 onwards, this setting loses the previous meaning and instead
+ * indicates if wakeup detection is enabled on the pin.  Note that
+ * enable_irq_wake() will automatically enable wakeup detection.
  */
 int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
 {
@@ -367,7 +396,27 @@
 
 static int nmk_gpio_irq_set_wake(unsigned int irq, unsigned int on)
 {
-	return nmk_gpio_irq_modify(irq, WAKE, on);
+	struct nmk_gpio_chip *nmk_chip;
+	unsigned long flags;
+	int gpio;
+
+	gpio = NOMADIK_IRQ_TO_GPIO(irq);
+	nmk_chip = get_irq_chip_data(irq);
+	if (!nmk_chip)
+		return -EINVAL;
+
+	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);
+
+	return 0;
 }
 
 static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type)
@@ -495,12 +544,8 @@
 {
 	struct nmk_gpio_chip *nmk_chip =
 		container_of(chip, struct nmk_gpio_chip, chip);
-	u32 bit = 1 << offset;
 
-	if (val)
-		writel(bit, nmk_chip->addr + NMK_GPIO_DATS);
-	else
-		writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
+	__nmk_gpio_set_output(nmk_chip, offset, val);
 }
 
 static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
@@ -509,8 +554,7 @@
 	struct nmk_gpio_chip *nmk_chip =
 		container_of(chip, struct nmk_gpio_chip, chip);
 
-	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
-	nmk_gpio_set_output(chip, offset, val);
+	__nmk_gpio_make_output(nmk_chip, offset, val);
 
 	return 0;
 }
@@ -534,7 +578,7 @@
 	.can_sleep		= 0,
 };
 
-static int __init nmk_gpio_probe(struct platform_device *dev)
+static int __devinit nmk_gpio_probe(struct platform_device *dev)
 {
 	struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
 	struct nmk_gpio_chip *nmk_chip;
diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h
index aba3551..67b113d 100644
--- a/arch/arm/plat-nomadik/include/plat/gpio.h
+++ b/arch/arm/plat-nomadik/include/plat/gpio.h
@@ -65,7 +65,9 @@
 /* Sleep mode */
 enum nmk_gpio_slpm {
 	NMK_GPIO_SLPM_INPUT,
+	NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
 	NMK_GPIO_SLPM_NOCHANGE,
+	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
 };
 
 extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h
index 7eed11c..8c5ae3f 100644
--- a/arch/arm/plat-nomadik/include/plat/pincfg.h
+++ b/arch/arm/plat-nomadik/include/plat/pincfg.h
@@ -19,12 +19,16 @@
  *	bit  9..10 - Alternate Function Selection
  *	bit 11..12 - Pull up/down state
  *	bit     13 - Sleep mode behaviour
+ *	bit     14 - (sleep mode) Direction
+ *	bit     15 - (sleep mode) Value (if output)
  *
  * to facilitate the definition, the following macros are provided
  *
  * PIN_CFG_DEFAULT - default config (0):
  *		     pull up/down = disabled
- *		     sleep mode = input
+ *		     sleep mode = input/wakeup
+ *		     (sleep mode) direction = input
+ *		     (sleep mode) value = low
  *
  * PIN_CFG	   - default config with alternate function
  * PIN_CFG_PULL	   - default config with alternate function and pull up/down
@@ -53,8 +57,36 @@
 #define PIN_SLPM_SHIFT		13
 #define PIN_SLPM_MASK		(0x1 << PIN_SLPM_SHIFT)
 #define PIN_SLPM(x)		(((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
-#define PIN_SLPM_INPUT		(NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
+#define PIN_SLPM_MAKE_INPUT	(NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
 #define PIN_SLPM_NOCHANGE	(NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
+/* These two replace the above in DB8500v2+ */
+#define PIN_SLPM_WAKEUP_ENABLE	(NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_WAKEUP_DISABLE	(NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
+
+#define PIN_DIR_SHIFT		14
+#define PIN_DIR_MASK		(0x1 << PIN_DIR_SHIFT)
+#define PIN_DIR(x)		(((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
+#define PIN_DIR_INPUT		(0 << PIN_DIR_SHIFT)
+#define PIN_DIR_OUTPUT		(1 << PIN_DIR_SHIFT)
+
+#define PIN_VAL_SHIFT		15
+#define PIN_VAL_MASK		(0x1 << PIN_VAL_SHIFT)
+#define PIN_VAL(x)		(((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
+#define PIN_VAL_LOW		(0 << PIN_VAL_SHIFT)
+#define PIN_VAL_HIGH		(1 << PIN_VAL_SHIFT)
+
+/* Shortcuts.  Use these instead of separate DIR and VAL.  */
+#define PIN_INPUT		PIN_DIR_INPUT
+#define PIN_OUTPUT_LOW		(PIN_DIR_OUTPUT | PIN_VAL_LOW)
+#define PIN_OUTPUT_HIGH		(PIN_DIR_OUTPUT | PIN_VAL_HIGH)
+
+/*
+ * These are the same as the ones above, but should make more sense to the
+ * reader when seen along with a setting a pin to AF mode.
+ */
+#define PIN_SLPM_INPUT		PIN_INPUT
+#define PIN_SLPM_OUTPUT_LOW	PIN_OUTPUT_LOW
+#define PIN_SLPM_OUTPUT_HIGH	PIN_OUTPUT_HIGH
 
 #define PIN_CFG_DEFAULT		(PIN_PULL_NONE | PIN_SLPM_INPUT)
 
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c
index ea3ca86..aedf9c1 100644
--- a/arch/arm/plat-nomadik/timer.c
+++ b/arch/arm/plat-nomadik/timer.c
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/mach-nomadik/timer.c
+ *  linux/arch/arm/plat-nomadik/timer.c
  *
  * Copyright (C) 2008 STMicroelectronics
  * Copyright (C) 2010 Alessandro Rubini
@@ -75,7 +75,7 @@
 		cr = readl(mtu_base + MTU_CR(1));
 		writel(0, mtu_base + MTU_LR(1));
 		writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1));
-		writel(0x2, mtu_base + MTU_IMSC);
+		writel(1 << 1, mtu_base + MTU_IMSC);
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	case CLOCK_EVT_MODE_UNUSED:
@@ -131,25 +131,23 @@
 {
 	unsigned long rate;
 	struct clk *clk0;
-	struct clk *clk1;
-	u32 cr;
+	u32 cr = MTU_CRn_32BITS;
 
 	clk0 = clk_get_sys("mtu0", NULL);
 	BUG_ON(IS_ERR(clk0));
 
-	clk1 = clk_get_sys("mtu1", NULL);
-	BUG_ON(IS_ERR(clk1));
-
 	clk_enable(clk0);
-	clk_enable(clk1);
 
 	/*
-	 * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500:
-	 * use a divide-by-16 counter if it's more than 16MHz
+	 * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz
+	 * for ux500.
+	 * Use a divide-by-16 counter if the tick rate is more than 32MHz.
+	 * At 32 MHz, the timer (with 32 bit counter) can be programmed
+	 * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer
+	 * with 16 gives too low timer resolution.
 	 */
-	cr = MTU_CRn_32BITS;;
 	rate = clk_get_rate(clk0);
-	if (rate > 16 << 20) {
+	if (rate > 32000000) {
 		rate /= 16;
 		cr |= MTU_CRn_PRESCALE_16;
 	} else {
@@ -170,15 +168,8 @@
 		pr_err("timer: failed to initialize clock source %s\n",
 		       nmdk_clksrc.name);
 
-	/* Timer 1 is used for events, fix according to rate */
-	cr = MTU_CRn_32BITS;
-	rate = clk_get_rate(clk1);
-	if (rate > 16 << 20) {
-		rate /= 16;
-		cr |= MTU_CRn_PRESCALE_16;
-	} else {
-		cr |= MTU_CRn_PRESCALE_1;
-	}
+	/* Timer 1 is used for events */
+
 	clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);
 
 	writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index e39a417..a92cb49 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -33,7 +33,7 @@
 config OMAP_DEBUG_LEDS
 	bool
 	depends on OMAP_DEBUG_DEVICES
-	default y if LEDS
+	default y if LEDS_CLASS
 
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index 0054b95..7193481 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -173,11 +173,7 @@
 
 static int valid_sdram(unsigned long addr, unsigned long size)
 {
-	struct memblock_property res;
-
-	res.base = addr;
-	res.size = size;
-	return !memblock_find(&res) && res.base == addr && res.size == size;
+	return memblock_is_region_memory(addr, size);
 }
 
 static int reserve_sdram(unsigned long addr, unsigned long size)
diff --git a/arch/arm/plat-omap/include/plat/smp.h b/arch/arm/plat-omap/include/plat/smp.h
index 5177a9c..ecd6a48 100644
--- a/arch/arm/plat-omap/include/plat/smp.h
+++ b/arch/arm/plat-omap/include/plat/smp.h
@@ -18,6 +18,7 @@
 #define OMAP_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
+#include <asm/smp_mpidr.h>
 
 /* Needed for secondary core boot */
 extern void omap_secondary_startup(void);
@@ -33,15 +34,4 @@
 	gic_raise_softirq(mask, 1);
 }
 
-/*
- * Read MPIDR: Multiprocessor affinity register
- */
-#define hard_smp_processor_id()			\
-	({						\
-		unsigned int cpunum;			\
-		__asm__("mrc p15, 0, %0, c0, c0, 5"	\
-			: "=r" (cpunum));		\
-		cpunum &= 0x0F;				\
-	})
-
 #endif
diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 2a9427c..9feddac 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -218,6 +218,27 @@
 #	define	USBT2TLL5PI		(1 << 17)
 #	define	USB0PUENACTLOI		(1 << 16)
 #	define	USBSTANDBYCTRL		(1 << 15)
+/* AM35x */
+/* USB 2.0 PHY Control */
+#define CONF2_PHY_GPIOMODE	(1 << 23)
+#define CONF2_OTGMODE		(3 << 14)
+#define CONF2_NO_OVERRIDE	(0 << 14)
+#define CONF2_FORCE_HOST	(1 << 14)
+#define CONF2_FORCE_DEVICE	(2 << 14)
+#define CONF2_FORCE_HOST_VBUS_LOW (3 << 14)
+#define CONF2_SESENDEN		(1 << 13)
+#define CONF2_VBDTCTEN		(1 << 12)
+#define CONF2_REFFREQ_24MHZ	(2 << 8)
+#define CONF2_REFFREQ_26MHZ	(7 << 8)
+#define CONF2_REFFREQ_13MHZ	(6 << 8)
+#define CONF2_REFFREQ		(0xf << 8)
+#define CONF2_PHYCLKGD		(1 << 7)
+#define CONF2_VBUSSENSE		(1 << 6)
+#define CONF2_PHY_PLLON		(1 << 5)
+#define CONF2_RESET		(1 << 4)
+#define CONF2_PHYPWRDN		(1 << 3)
+#define CONF2_OTGPWRDN		(1 << 2)
+#define CONF2_DATPOL		(1 << 1)
 
 #if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_USB)
 u32 omap1_usb0_init(unsigned nwires, unsigned is_device);
diff --git a/arch/arm/plat-omap/iommu-debug.c b/arch/arm/plat-omap/iommu-debug.c
index e6c0d53..f07cf2f 100644
--- a/arch/arm/plat-omap/iommu-debug.c
+++ b/arch/arm/plat-omap/iommu-debug.c
@@ -328,12 +328,14 @@
 		.open = debug_open_generic,				\
 		.read = debug_read_##name,				\
 		.write = debug_write_##name,				\
+		.llseek = generic_file_llseek,				\
 	};
 
 #define DEBUG_FOPS_RO(name)						\
 	static const struct file_operations debug_##name##_fops = {	\
 		.open = debug_open_generic,				\
 		.read = debug_read_##name,				\
+		.llseek = generic_file_llseek,				\
 	};
 
 DEBUG_FOPS_RO(ver);
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index a202a2c..6cd151b 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -320,6 +320,7 @@
 		if ((start <= da) && (da < start + bytes)) {
 			dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
 				__func__, start, da, bytes);
+			iotlb_load_cr(obj, &cr);
 			iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
 		}
 	}
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index e31496e..0c8612f 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -156,7 +156,7 @@
 		/* Writing zero to RSYNC_ERR clears the IRQ */
 		MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1));
 	} else {
-		complete(&mcbsp_rx->tx_irq_completion);
+		complete(&mcbsp_rx->rx_irq_completion);
 	}
 
 	return IRQ_HANDLED;
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 226b2e8..10b3b4c 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -220,20 +220,7 @@
 	if (omap_sram_size == 0)
 		return;
 
-	if (cpu_is_omap24xx()) {
-		omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA;
-
-		base = OMAP2_SRAM_PA;
-		base = ROUND_DOWN(base, PAGE_SIZE);
-		omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
-	}
-
 	if (cpu_is_omap34xx()) {
-		omap_sram_io_desc[0].virtual = OMAP3_SRAM_VA;
-		base = OMAP3_SRAM_PA;
-		base = ROUND_DOWN(base, PAGE_SIZE);
-		omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
-
 		/*
 		 * SRAM must be marked as non-cached on OMAP3 since the
 		 * CORE DPLL M2 divider change code (in SRAM) runs with the
@@ -244,13 +231,11 @@
 		omap_sram_io_desc[0].type = MT_MEMORY_NONCACHED;
 	}
 
-	if (cpu_is_omap44xx()) {
-		omap_sram_io_desc[0].virtual = OMAP4_SRAM_VA;
-		base = OMAP4_SRAM_PA;
-		base = ROUND_DOWN(base, PAGE_SIZE);
-		omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
-	}
-	omap_sram_io_desc[0].length = 1024 * 1024;	/* Use section desc */
+	omap_sram_io_desc[0].virtual = omap_sram_base;
+	base = omap_sram_start;
+	base = ROUND_DOWN(base, PAGE_SIZE);
+	omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
+	omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE);
 	iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
 
 	printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n",
diff --git a/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h b/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h
new file mode 100644
index 0000000..abcc36e
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h
@@ -0,0 +1,69 @@
+#ifndef __ASM_ARCH_PXA27x_KEYPAD_H
+#define __ASM_ARCH_PXA27x_KEYPAD_H
+
+#include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
+
+#define MAX_MATRIX_KEY_ROWS	(8)
+#define MAX_MATRIX_KEY_COLS	(8)
+#define MATRIX_ROW_SHIFT	(3)
+#define MAX_DIRECT_KEY_NUM	(8)
+
+/* pxa3xx keypad platform specific parameters
+ *
+ * NOTE:
+ * 1. direct_key_num indicates the number of keys in the direct keypad
+ *    _plus_ the number of rotary-encoder sensor inputs,  this can be
+ *    left as 0 if only rotary encoders are enabled,  the driver will
+ *    automatically calculate this
+ *
+ * 2. direct_key_map is the key code map for the direct keys, if rotary
+ *    encoder(s) are enabled, direct key 0/1(2/3) will be ignored
+ *
+ * 3. rotary can be either interpreted as a relative input event (e.g.
+ *    REL_WHEEL/REL_HWHEEL) or specific keys (e.g. UP/DOWN/LEFT/RIGHT)
+ *
+ * 4. matrix key and direct key will use the same debounce_interval by
+ *    default, which should be sufficient in most cases
+ *
+ * pxa168 keypad platform specific parameter
+ *
+ * NOTE:
+ * clear_wakeup_event callback is a workaround required to clear the
+ * keypad interrupt. The keypad wake must be cleared in addition to
+ * reading the MI/DI bits in the KPC register.
+ */
+struct pxa27x_keypad_platform_data {
+
+	/* code map for the matrix keys */
+	unsigned int	matrix_key_rows;
+	unsigned int	matrix_key_cols;
+	unsigned int	*matrix_key_map;
+	int		matrix_key_map_size;
+
+	/* direct keys */
+	int		direct_key_num;
+	unsigned int	direct_key_map[MAX_DIRECT_KEY_NUM];
+
+	/* rotary encoders 0 */
+	int		enable_rotary0;
+	int		rotary0_rel_code;
+	int		rotary0_up_key;
+	int		rotary0_down_key;
+
+	/* rotary encoders 1 */
+	int		enable_rotary1;
+	int		rotary1_rel_code;
+	int		rotary1_up_key;
+	int		rotary1_down_key;
+
+	/* key debounce interval */
+	unsigned int	debounce_interval;
+
+	/* clear wakeup event requirement for pxa168 */
+	void		(*clear_wakeup_event)(void);
+};
+
+extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info);
+
+#endif /* __ASM_ARCH_PXA27x_KEYPAD_H */
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index c6a855d..2596096 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -7,7 +7,7 @@
 
 config PLAT_S5P
 	bool
-	depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310)
+	depends on (ARCH_S5P64X0 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310)
 	default y
 	select ARM_VIC if !ARCH_S5PV310
 	select ARM_GIC if ARCH_S5PV310
@@ -30,7 +30,7 @@
 	bool
 	help
 	  Use the external interrupts (other than GPIO interrupts.)
-	  Note: Do not choose this for S5P6440.
+	  Note: Do not choose this for S5P6440 and S5P6450.
 
 config S5P_DEV_FIMC0
 	bool
@@ -46,3 +46,8 @@
 	bool
 	help
 	  Compile in platform device definitions for FIMC controller 2
+
+config S5P_DEV_ONENAND
+	bool
+	help
+	  Compile in platform device definition for OneNAND controller
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index b2e0296..f3e917e 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -24,3 +24,4 @@
 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_ONENAND)	+= dev-onenand.o
diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c
index b5e2552..8aaf4e6 100644
--- a/arch/arm/plat-s5p/clock.c
+++ b/arch/arm/plat-s5p/clock.c
@@ -74,6 +74,13 @@
 	.ctrlbit	= (1 << 31),
 };
 
+/* DPLL clock output */
+struct clk clk_fout_dpll = {
+	.name		= "fout_dpll",
+	.id		= -1,
+	.ctrlbit	= (1 << 31),
+};
+
 /* VPLL clock output */
 struct clk clk_fout_vpll = {
 	.name		= "fout_vpll",
@@ -122,6 +129,17 @@
 	.nr_sources	= ARRAY_SIZE(clk_src_epll_list),
 };
 
+/* Possible clock sources for DPLL Mux */
+static struct clk *clk_src_dpll_list[] = {
+	[0] = &clk_fin_dpll,
+	[1] = &clk_fout_dpll,
+};
+
+struct clksrc_sources clk_src_dpll = {
+	.sources	= clk_src_dpll_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_dpll_list),
+};
+
 struct clk clk_vpll = {
 	.name		= "vpll",
 	.id		= -1,
@@ -145,6 +163,7 @@
 	&clk_fout_apll,
 	&clk_fout_mpll,
 	&clk_fout_epll,
+	&clk_fout_dpll,
 	&clk_fout_vpll,
 	&clk_arm,
 	&clk_vpll,
diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
index b07a078..74f7f5a 100644
--- a/arch/arm/plat-s5p/cpu.c
+++ b/arch/arm/plat-s5p/cpu.c
@@ -19,6 +19,7 @@
 #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>
@@ -27,6 +28,7 @@
 
 static const char name_s5p6440[] = "S5P6440";
 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";
@@ -38,7 +40,7 @@
 		.map_io		= s5p6440_map_io,
 		.init_clocks	= s5p6440_init_clocks,
 		.init_uarts	= s5p6440_init_uarts,
-		.init		= s5p6440_init,
+		.init		= s5p64x0_init,
 		.name		= name_s5p6440,
 	}, {
 		.idcode		= 0x36442000,
@@ -49,6 +51,14 @@
 		.init		= s5p6442_init,
 		.name		= name_s5p6442,
 	}, {
+		.idcode		= 0x36450000,
+		.idmask		= 0xffffff00,
+		.map_io		= s5p6450_map_io,
+		.init_clocks	= s5p6450_init_clocks,
+		.init_uarts	= s5p6450_init_uarts,
+		.init		= s5p64x0_init,
+		.name		= name_s5p6450,
+	}, {
 		.idcode		= 0x43100000,
 		.idmask		= 0xfffff000,
 		.map_io		= s5pc100_map_io,
@@ -89,33 +99,11 @@
 		.length		= SZ_64K,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= (unsigned long)S3C_VA_UART,
-		.pfn		= __phys_to_pfn(S3C_PA_UART),
-		.length		= SZ_512K,
-		.type		= MT_DEVICE,
-#ifdef CONFIG_ARM_VIC
-	}, {
-		.virtual	= (unsigned long)VA_VIC0,
-		.pfn		= __phys_to_pfn(S5P_PA_VIC0),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)VA_VIC1,
-		.pfn		= __phys_to_pfn(S5P_PA_VIC1),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-#endif
-	}, {
 		.virtual	= (unsigned long)S3C_VA_TIMER,
 		.pfn		= __phys_to_pfn(S5P_PA_TIMER),
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO,
-		.pfn		= __phys_to_pfn(S5P_PA_GPIO),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
 		.virtual	= (unsigned long)S3C_VA_WATCHDOG,
 		.pfn		= __phys_to_pfn(S3C_PA_WDT),
 		.length		= SZ_4K,
diff --git a/arch/arm/plat-s5p/dev-onenand.c b/arch/arm/plat-s5p/dev-onenand.c
new file mode 100644
index 0000000..6db9262
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-onenand.c
@@ -0,0 +1,57 @@
+/* linux/arch/arm/plat-s5p/dev-onenand.c
+ *
+ * Copyright 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ *  Copyright (c) 2008-2010 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * S5P series device definition for OneNAND devices
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+static struct resource s5p_onenand_resources[] = {
+	[0] = {
+		.start	= S5P_PA_ONENAND,
+		.end	= S5P_PA_ONENAND + SZ_128K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= S5P_PA_ONENAND_DMA,
+		.end	= S5P_PA_ONENAND_DMA + SZ_8K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[2] = {
+		.start	= IRQ_ONENAND_AUDI,
+		.end	= IRQ_ONENAND_AUDI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device s5p_device_onenand = {
+	.name		= "s5pc110-onenand",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_onenand_resources),
+	.resource	= s5p_onenand_resources,
+};
+
+void s5p_onenand_set_platdata(struct onenand_platform_data *pdata)
+{
+	struct onenand_platform_data *pd;
+
+	pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL);
+	if (!pd)
+		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+	s5p_device_onenand.dev.platform_data = pd;
+}
diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c
index a89331e..6a73428 100644
--- a/arch/arm/plat-s5p/dev-uart.c
+++ b/arch/arm/plat-s5p/dev-uart.c
@@ -119,6 +119,56 @@
 #endif
 };
 
+static struct resource s5p_uart4_resource[] = {
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 4
+	[0] = {
+		.start	= S5P_PA_UART4,
+		.end	= S5P_PA_UART4 + S5P_SZ_UART,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_S5P_UART_RX4,
+		.end	= IRQ_S5P_UART_RX4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_S5P_UART_TX4,
+		.end	= IRQ_S5P_UART_TX4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= IRQ_S5P_UART_ERR4,
+		.end	= IRQ_S5P_UART_ERR4,
+		.flags	= IORESOURCE_IRQ,
+	},
+#endif
+};
+
+static struct resource s5p_uart5_resource[] = {
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 5
+	[0] = {
+		.start	= S5P_PA_UART5,
+		.end	= S5P_PA_UART5 + S5P_SZ_UART,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_S5P_UART_RX5,
+		.end	= IRQ_S5P_UART_RX5,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_S5P_UART_TX5,
+		.end	= IRQ_S5P_UART_TX5,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= IRQ_S5P_UART_ERR5,
+		.end	= IRQ_S5P_UART_ERR5,
+		.flags	= IORESOURCE_IRQ,
+	},
+#endif
+};
+
 struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = {
 	[0] = {
 		.resources	= s5p_uart0_resource,
@@ -136,4 +186,12 @@
 		.resources	= s5p_uart3_resource,
 		.nr_resources	= ARRAY_SIZE(s5p_uart3_resource),
 	},
+	[4] = {
+		.resources	= s5p_uart4_resource,
+		.nr_resources	= ARRAY_SIZE(s5p_uart4_resource),
+	},
+	[5] = {
+		.resources	= s5p_uart5_resource,
+		.nr_resources	= ARRAY_SIZE(s5p_uart5_resource),
+	},
 };
diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h
index 4e8fe08..bf28fad 100644
--- a/arch/arm/plat-s5p/include/plat/pll.h
+++ b/arch/arm/plat-s5p/include/plat/pll.h
@@ -47,6 +47,7 @@
 }
 
 #define PLL46XX_KDIV_MASK	(0xFFFF)
+#define PLL4650C_KDIV_MASK	(0xFFF)
 #define PLL46XX_MDIV_MASK	(0x1FF)
 #define PLL46XX_PDIV_MASK	(0x3F)
 #define PLL46XX_SDIV_MASK	(0x7)
@@ -57,6 +58,7 @@
 enum pll46xx_type_t {
 	pll_4600,
 	pll_4650,
+	pll_4650c,
 };
 
 static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
@@ -72,6 +74,11 @@
 	sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
 	kdiv = pll_con1 & PLL46XX_KDIV_MASK;
 
+	if (pll_type == pll_4650c)
+		kdiv = pll_con1 & PLL4650C_KDIV_MASK;
+	else
+		kdiv = pll_con1 & PLL46XX_KDIV_MASK;
+
 	tmp = baseclk;
 
 	if (pll_type == pll_4600) {
diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h
index 09418b1..17036c8 100644
--- a/arch/arm/plat-s5p/include/plat/s5p-clock.h
+++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h
@@ -1,7 +1,7 @@
 /* linux/arch/arm/plat-s5p/include/plat/s5p-clock.h
  *
- * Copyright 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
  *
  * Header file for s5p clock support
  *
@@ -20,6 +20,7 @@
 #define clk_fin_apll clk_ext_xtal_mux
 #define clk_fin_mpll clk_ext_xtal_mux
 #define clk_fin_epll clk_ext_xtal_mux
+#define clk_fin_dpll clk_ext_xtal_mux
 #define clk_fin_vpll clk_ext_xtal_mux
 #define clk_fin_hpll clk_ext_xtal_mux
 
@@ -30,6 +31,7 @@
 extern struct clk clk_fout_apll;
 extern struct clk clk_fout_mpll;
 extern struct clk clk_fout_epll;
+extern struct clk clk_fout_dpll;
 extern struct clk clk_fout_vpll;
 extern struct clk clk_arm;
 extern struct clk clk_vpll;
@@ -37,8 +39,8 @@
 extern struct clksrc_sources clk_src_apll;
 extern struct clksrc_sources clk_src_mpll;
 extern struct clksrc_sources clk_src_epll;
+extern struct clksrc_sources clk_src_dpll;
 
-extern int s5p6440_clk48m_ctrl(struct clk *clk, int enable);
 extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
 
 #endif /* __ASM_PLAT_S5P_CLOCK_H */
diff --git a/arch/arm/plat-s5p/include/plat/s5p6440.h b/arch/arm/plat-s5p/include/plat/s5p6440.h
index a4cd75a..528585d 100644
--- a/arch/arm/plat-s5p/include/plat/s5p6440.h
+++ b/arch/arm/plat-s5p/include/plat/s5p6440.h
@@ -12,24 +12,23 @@
 
  /* Common init code for S5P6440 related SoCs */
 
-extern void s5p6440_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 extern void s5p6440_register_clocks(void);
 extern void s5p6440_setup_clocks(void);
 
 #ifdef CONFIG_CPU_S5P6440
 
-extern  int s5p6440_init(void);
+extern  int s5p64x0_init(void);
 extern void s5p6440_init_irq(void);
 extern void s5p6440_map_io(void);
 extern void s5p6440_init_clocks(int xtal);
 
-#define s5p6440_init_uarts s5p6440_common_init_uarts
+extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 
 #else
 #define s5p6440_init_clocks NULL
 #define s5p6440_init_uarts NULL
 #define s5p6440_map_io NULL
-#define s5p6440_init NULL
+#define s5p64x0_init NULL
 #endif
 
 /* S5P6440 timer */
diff --git a/arch/arm/plat-s5p/include/plat/s5p6450.h b/arch/arm/plat-s5p/include/plat/s5p6450.h
new file mode 100644
index 0000000..640a41c
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/s5p6450.h
@@ -0,0 +1,36 @@
+/* arch/arm/plat-s5p/include/plat/s5p6450.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for s5p6450 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 S5P6450 related SoCs */
+
+extern void s5p6450_register_clocks(void);
+extern void s5p6450_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5P6450
+
+extern  int s5p64x0_init(void);
+extern void s5p6450_init_irq(void);
+extern void s5p6450_map_io(void);
+extern void s5p6450_init_clocks(int xtal);
+
+extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+#else
+#define s5p6450_init_clocks NULL
+#define s5p6450_init_uarts NULL
+#define s5p6450_map_io NULL
+#define s5p64x0_init NULL
+#endif
+
+/* S5P6450 timer */
+
+extern struct sys_timer s5p6450_timer;
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index 04d9521..e8f2be2 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -435,7 +435,6 @@
 static int s3c_adc_resume(struct platform_device *pdev)
 {
 	struct adc_device *adc = platform_get_drvdata(pdev);
-	unsigned long flags;
 
 	clk_enable(adc->clk);
 	enable_irq(adc->irq);
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
index 90a2051..e8d20b0 100644
--- a/arch/arm/plat-samsung/clock.c
+++ b/arch/arm/plat-samsung/clock.c
@@ -48,6 +48,9 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 
+#include <linux/serial_core.h>
+#include <plat/regs-serial.h> /* for s3c24xx_uart_devs */
+
 /* clock information */
 
 static LIST_HEAD(clocks);
@@ -65,6 +68,28 @@
 	return 0;
 }
 
+static int dev_is_s3c_uart(struct device *dev)
+{
+	struct platform_device **pdev = s3c24xx_uart_devs;
+	int i;
+	for (i = 0; i < ARRAY_SIZE(s3c24xx_uart_devs); i++, pdev++)
+		if (*pdev && dev == &(*pdev)->dev)
+			return 1;
+	return 0;
+}
+
+/*
+ * Serial drivers call get_clock() very early, before platform bus
+ * has been set up, this requires a special check to let them get
+ * a proper clock
+ */
+
+static int dev_is_platform_device(struct device *dev)
+{
+	return dev->bus == &platform_bus_type ||
+	       (dev->bus == NULL && dev_is_s3c_uart(dev));
+}
+
 /* Clock API calls */
 
 struct clk *clk_get(struct device *dev, const char *id)
@@ -73,7 +98,7 @@
 	struct clk *clk = ERR_PTR(-ENOENT);
 	int idno;
 
-	if (dev == NULL || dev->bus != &platform_bus_type)
+	if (dev == NULL || !dev_is_platform_device(dev))
 		idno = -1;
 	else
 		idno = to_platform_device(dev)->id;
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 6412933..9addb3d 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -79,7 +79,7 @@
 extern struct sysdev_class s3c2443_sysclass;
 extern struct sysdev_class s3c6410_sysclass;
 extern struct sysdev_class s3c64xx_sysclass;
-extern struct sysdev_class s5p6440_sysclass;
+extern struct sysdev_class s5p64x0_sysclass;
 extern struct sysdev_class s5p6442_sysclass;
 extern struct sysdev_class s5pv210_sysclass;
 
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 85f6f23..7d448e1 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -67,13 +67,15 @@
 extern struct platform_device s5pv210_device_spi1;
 extern struct platform_device s5p6440_device_spi0;
 extern struct platform_device s5p6440_device_spi1;
+extern struct platform_device s5p6450_device_spi0;
+extern struct platform_device s5p6450_device_spi1;
 
 extern struct platform_device s3c_device_hwmon;
 
 extern struct platform_device s3c_device_nand;
 extern struct platform_device s3c_device_onenand;
 extern struct platform_device s3c64xx_device_onenand1;
-extern struct platform_device s5pc110_device_onenand;
+extern struct platform_device s5p_device_onenand;
 
 extern struct platform_device s3c_device_usbgadget;
 extern struct platform_device s3c_device_usb_hsotg;
@@ -95,6 +97,9 @@
 extern struct platform_device s5p6440_device_pcm;
 extern struct platform_device s5p6440_device_iis;
 
+extern struct platform_device s5p6450_device_iis0;
+extern struct platform_device s5p6450_device_pcm0;
+
 extern struct platform_device s5pc100_device_ac97;
 extern struct platform_device s5pc100_device_pcm0;
 extern struct platform_device s5pc100_device_pcm1;
diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
index 5fe6721..8107442 100644
--- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
@@ -32,6 +32,12 @@
 	DMACH_UART2_TX,
 	DMACH_UART3_RX,
 	DMACH_UART3_TX,
+	DMACH_UART4_RX,
+	DMACH_UART4_TX,
+	DMACH_UART5_RX,
+	DMACH_UART5_TX,
+	DMACH_USI_RX,
+	DMACH_USI_TX,
 	DMACH_IRDA,
 	DMACH_I2S0_RX,
 	DMACH_I2S0_TX,
@@ -64,6 +70,20 @@
 	DMACH_MSM_REQ2,
 	DMACH_MSM_REQ1,
 	DMACH_MSM_REQ0,
+	DMACH_SLIMBUS0_RX,
+	DMACH_SLIMBUS0_TX,
+	DMACH_SLIMBUS0AUX_RX,
+	DMACH_SLIMBUS0AUX_TX,
+	DMACH_SLIMBUS1_RX,
+	DMACH_SLIMBUS1_TX,
+	DMACH_SLIMBUS2_RX,
+	DMACH_SLIMBUS2_TX,
+	DMACH_SLIMBUS3_RX,
+	DMACH_SLIMBUS3_TX,
+	DMACH_SLIMBUS4_RX,
+	DMACH_SLIMBUS4_TX,
+	DMACH_SLIMBUS5_RX,
+	DMACH_SLIMBUS5_TX,
 	/* END Marker, also used to denote a reserved channel */
 	DMACH_MAX,
 };
diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
index e5aba8f..ff1a561 100644
--- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
+++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
@@ -32,6 +32,8 @@
  * struct s3c64xx_spi_info - SPI Controller defining structure
  * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
  * @src_clk_name: Platform name of the corresponding clock.
+ * @clk_from_cmu: If the SPI clock/prescalar control block is present
+ *     by the platform's clock-management-unit and not in SPI controller.
  * @num_cs: Number of CS this controller emulates.
  * @cfg_gpio: Configure pins for this SPI controller.
  * @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6
@@ -41,6 +43,7 @@
 struct s3c64xx_spi_info {
 	int src_clk_nr;
 	char *src_clk_name;
+	bool clk_from_cmu;
 
 	int num_cs;
 
@@ -65,7 +68,7 @@
 extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
 extern void s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
 extern void s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
-extern void s5p6440_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
+extern void s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
 extern void s5p6442_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
 
 #endif /* __S3C64XX_PLAT_SPI_H */
diff --git a/arch/arm/plat-spear/include/plat/debug-macro.S b/arch/arm/plat-spear/include/plat/debug-macro.S
index 37fa593..e91270e 100644
--- a/arch/arm/plat-spear/include/plat/debug-macro.S
+++ b/arch/arm/plat-spear/include/plat/debug-macro.S
@@ -14,11 +14,9 @@
 #include <linux/amba/serial.h>
 #include <mach/spear.h>
 
-		.macro	addruart, rx
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1					@ MMU enabled?
-		moveq	\rx, #SPEAR_DBG_UART_BASE		@ Physical base
-		movne	\rx, #VA_SPEAR_DBG_UART_BASE		@ Virtual base
+		.macro	addruart, rp, rv
+		mov	\rp, #SPEAR_DBG_UART_BASE		@ Physical base
+		mov	\rv, #VA_SPEAR_DBG_UART_BASE		@ Virtual base
 		.endm
 
 		.macro	senduart, rd, rx
diff --git a/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S b/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S
index 1b9348b..d3a0985 100644
--- a/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S
+++ b/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S
@@ -16,13 +16,10 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-		.macro	addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x80000000	@ physical base address
-		addeq	\rx, \rx, #0x00070000
-		movne	\rx, #0xf0000000	@ virtual base
-		addne	\rx, \rx, #0x00070000
+		.macro	addruart, rp, rv
+		mov	\rp,      #0x00070000
+		add	\rv, \rp, #0xf0000000	@ virtual base
+		add	\rp, \rp, #0x80000000	@ physical base
 		.endm
 
 		.macro	senduart,rd,rx
diff --git a/arch/arm/plat-tcc/Kconfig b/arch/arm/plat-tcc/Kconfig
new file mode 100644
index 0000000..1bf4995
--- /dev/null
+++ b/arch/arm/plat-tcc/Kconfig
@@ -0,0 +1,20 @@
+if ARCH_TCC_926
+
+menu "Telechips ARM926-based CPUs"
+
+choice
+	prompt "Telechips CPU type:"
+	default ARCH_TCC8K
+
+config ARCH_TCC8K
+	bool TCC8000
+	select USB_ARCH_HAS_OHCI
+	help
+	  Support for Telechips TCC8000 systems
+
+endchoice
+
+source "arch/arm/mach-tcc8k/Kconfig"
+
+endmenu
+endif
diff --git a/arch/arm/plat-tcc/Makefile b/arch/arm/plat-tcc/Makefile
new file mode 100644
index 0000000..eceabc8
--- /dev/null
+++ b/arch/arm/plat-tcc/Makefile
@@ -0,0 +1,3 @@
+# "Telechips Platform Common Modules"
+
+obj-y := clock.o system.o
diff --git a/arch/arm/plat-tcc/clock.c b/arch/arm/plat-tcc/clock.c
new file mode 100644
index 0000000..f3ced10
--- /dev/null
+++ b/arch/arm/plat-tcc/clock.c
@@ -0,0 +1,179 @@
+/*
+ * Clock framework for Telechips SoCs
+ * Based on arch/arm/plat-mxc/clock.c
+ *
+ * Copyright (C) 2004 - 2005 Nokia corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
+ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2010 Hans J. Koch, hjk@linutronix.de
+ *
+ * Licensed under the terms of the GPL v2.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+
+#include <mach/clock.h>
+#include <mach/hardware.h>
+
+static DEFINE_MUTEX(clocks_mutex);
+
+/*-------------------------------------------------------------------------
+ * Standard clock functions defined in include/linux/clk.h
+ *-------------------------------------------------------------------------*/
+
+static void __clk_disable(struct clk *clk)
+{
+	BUG_ON(clk->refcount == 0);
+
+	if (!(--clk->refcount) && clk->disable) {
+		/* Unconditionally disable the clock in hardware */
+		clk->disable(clk);
+		/* recursively disable parents */
+		if (clk->parent)
+			__clk_disable(clk->parent);
+	}
+}
+
+static int __clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (clk->refcount++ == 0 && clk->enable) {
+		if (clk->parent)
+			ret = __clk_enable(clk->parent);
+		if (ret)
+			return ret;
+		else
+			return clk->enable(clk);
+	}
+
+	return 0;
+}
+
+/* This function increments the reference count on the clock and enables the
+ * clock if not already enabled. The parent clock tree is recursively enabled
+ */
+int clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk)
+		return -EINVAL;
+
+	mutex_lock(&clocks_mutex);
+	ret = __clk_enable(clk);
+	mutex_unlock(&clocks_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+/* This function decrements the reference count on the clock and disables
+ * the clock when reference count is 0. The parent clock tree is
+ * recursively disabled
+ */
+void clk_disable(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	mutex_lock(&clocks_mutex);
+	__clk_disable(clk);
+	mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+/* Retrieve the *current* clock rate. If the clock itself
+ * does not provide a special calculation routine, ask
+ * its parent and so on, until one is able to return
+ * a valid clock rate
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (!clk)
+		return 0UL;
+
+	if (clk->get_rate)
+		return clk->get_rate(clk);
+
+	return clk_get_rate(clk->parent);
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+/* Round the requested clock rate to the nearest supported
+ * rate that is less than or equal to the requested rate.
+ * This is dependent on the clock's current parent.
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk)
+		return 0;
+	if (!clk->round_rate)
+		return 0;
+
+	return clk->round_rate(clk, rate);
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+/* Set the clock to the requested clock rate. The rate must
+ * match a supported rate exactly based on what clk_round_rate returns
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret = -EINVAL;
+
+	if (!clk)
+		return ret;
+	if (!clk->set_rate || !rate)
+		return ret;
+
+	mutex_lock(&clocks_mutex);
+	ret = clk->set_rate(clk, rate);
+	mutex_unlock(&clocks_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+/* Set the clock's parent to another clock source */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk *old;
+	int ret = -EINVAL;
+
+	if (!clk)
+		return ret;
+	if (!clk->set_parent || !parent)
+		return ret;
+
+	mutex_lock(&clocks_mutex);
+	old = clk->parent;
+	if (clk->refcount)
+		__clk_enable(parent);
+	ret = clk->set_parent(clk, parent);
+	if (ret)
+		old = parent;
+	if (clk->refcount)
+		__clk_disable(old);
+	mutex_unlock(&clocks_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+/* Retrieve the clock's parent clock source */
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (!clk)
+		return NULL;
+
+	return clk->parent;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
diff --git a/arch/arm/plat-tcc/include/mach/clkdev.h b/arch/arm/plat-tcc/include/mach/clkdev.h
new file mode 100644
index 0000000..04b37a8
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/plat-tcc/include/mach/clock.h b/arch/arm/plat-tcc/include/mach/clock.h
new file mode 100644
index 0000000..a12f58a
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/clock.h
@@ -0,0 +1,48 @@
+/*
+ * Low level clock header file for Telechips TCC architecture
+ * (C) 2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the GPL v2.
+ */
+
+#ifndef __ASM_ARCH_TCC_CLOCK_H__
+#define __ASM_ARCH_TCC_CLOCK_H__
+
+#ifndef __ASSEMBLY__
+
+struct clk {
+	struct clk *parent;
+	/* id number of a root clock, 0 for normal clocks */
+	int root_id;
+	/* Reference count of clock enable/disable */
+	int refcount;
+	/* Address of associated BCLKCTRx register. Must be set. */
+	void __iomem *bclkctr;
+	/* Bit position for BCLKCTRx. Must be set. */
+	int bclk_shift;
+	/* Address of ACLKxxx register, if any. */
+	void __iomem *aclkreg;
+	/* get the current clock rate (always a fresh value) */
+	unsigned long (*get_rate) (struct clk *);
+	/* Function ptr to set the clock to a new rate. The rate must match a
+	   supported rate returned from round_rate. Leave blank if clock is not
+	   programmable */
+	int (*set_rate) (struct clk *, unsigned long);
+	/* Function ptr to round the requested clock rate to the nearest
+	   supported rate that is less than or equal to the requested rate. */
+	unsigned long (*round_rate) (struct clk *, unsigned long);
+	/* Function ptr to enable the clock. Leave blank if clock can not
+	   be gated. */
+	int (*enable) (struct clk *);
+	/* Function ptr to disable the clock. Leave blank if clock can not
+	   be gated. */
+	void (*disable) (struct clk *);
+	/* Function ptr to set the parent clock of the clock. */
+	int (*set_parent) (struct clk *, struct clk *);
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_ARCH_MXC_CLOCK_H__ */
diff --git a/arch/arm/plat-tcc/include/mach/debug-macro.S b/arch/arm/plat-tcc/include/mach/debug-macro.S
new file mode 100644
index 0000000..7662f73
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/debug-macro.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 1994-1999 Russell King
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.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.
+ *
+ */
+
+		.macro	addruart, rp, rv
+		moveq	\rp, #0x90000000	@ physical base address
+		movne	\rv, #0xF1000000	@ virtual base
+		orr	\rp, \rp, #0x00007000	@ UART0
+		orr	\rv, \rv, #0x00007000	@ UART0
+		.endm
+
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx, #0x44]
+		.endm
+
+		.macro	waituart,rd,rx
+		.endm
+
+		.macro	busyuart,rd,rx
+1001:
+		ldr \rd, [\rx, #0x14]
+		tst \rd, #0x20
+
+		beq 1001b
+		.endm
diff --git a/arch/arm/plat-tcc/include/mach/entry-macro.S b/arch/arm/plat-tcc/include/mach/entry-macro.S
new file mode 100644
index 0000000..748f401
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/entry-macro.S
@@ -0,0 +1,68 @@
+/*
+ * include/asm-arm/arch-tcc83x/entry-macro.S
+ *
+ * Author : <linux@telechips.com>
+ * Created: June 10, 2008
+ * Description: Low-level IRQ helper macros for Telechips-based platforms
+ *
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * 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>
+
+	.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
+
+		ldr	\base, =0xF2003000 @ base address of PIC registers
+
+		@@ read MREQ register of PIC0
+
+		mov	\irqnr, #0
+		ldr	\irqstat, [\base, #0x00000014 ]	@ lower 32 interrupts
+		cmp	\irqstat, #0
+		bne	1001f
+
+		@@ read MREQ register of PIC1
+
+		ldr	\irqstat, [\base, #0x00000094]	@ upper 32 interrupts
+		cmp	\irqstat, #0
+		beq	1002f
+		mov	\irqnr, #0x20
+
+1001:
+		movs	\tmp, \irqstat, lsl #16
+		movne	\irqstat, \tmp
+		addeq	\irqnr, \irqnr, #16
+
+		movs	\tmp, \irqstat, lsl #8
+		movne	\irqstat, \tmp
+		addeq	\irqnr, \irqnr, #8
+
+		movs	\tmp, \irqstat, lsl #4
+		movne	\irqstat, \tmp
+		addeq	\irqnr, \irqnr, #4
+
+		movs	\tmp, \irqstat, lsl #2
+		movne	\irqstat, \tmp
+		addeq	\irqnr, \irqnr, #2
+
+		movs	\tmp, \irqstat, lsl #1
+		addeq	\irqnr, \irqnr, #1
+		orrs	\base, \base, #1
+1002:
+		@@ exit here, Z flag unset if IRQ
+
+	.endm
diff --git a/arch/arm/plat-tcc/include/mach/hardware.h b/arch/arm/plat-tcc/include/mach/hardware.h
new file mode 100644
index 0000000..e70d126
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/hardware.h
@@ -0,0 +1,43 @@
+/*
+ * Author: RidgeRun, Inc. Greg Lonnon <glonnon@ridgerun.com>
+ * Reorganized for Linux-2.6 by Tony Lindgren <tony@atomide.com>
+ *                          and Dirk Behme <dirk.behme@de.bosch.com>
+ * Rewritten by:    <linux@telechips.com>
+ * Description: Hardware definitions for TCC8300 processors and boards
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * Modifications for mainline (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GNU Pulic License version 2.
+ */
+
+#ifndef __ASM_ARCH_TCC_HARDWARE_H
+#define __ASM_ARCH_TCC_HARDWARE_H
+
+#include <asm/sizes.h>
+#ifndef __ASSEMBLER__
+#include <asm/types.h>
+#endif
+#include <mach/io.h>
+
+/*
+ * ----------------------------------------------------------------------------
+ * Clocks
+ * ----------------------------------------------------------------------------
+ */
+#define CLKGEN_REG_BASE		0xfffece00
+#define ARM_CKCTL		(CLKGEN_REG_BASE + 0x0)
+#define ARM_IDLECT1		(CLKGEN_REG_BASE + 0x4)
+#define ARM_IDLECT2		(CLKGEN_REG_BASE + 0x8)
+#define ARM_EWUPCT		(CLKGEN_REG_BASE + 0xC)
+#define ARM_RSTCT1		(CLKGEN_REG_BASE + 0x10)
+#define ARM_RSTCT2		(CLKGEN_REG_BASE + 0x14)
+#define ARM_SYSST		(CLKGEN_REG_BASE + 0x18)
+#define ARM_IDLECT3		(CLKGEN_REG_BASE + 0x24)
+
+/* DPLL control registers */
+#define DPLL_CTL		0xfffecf00
+
+#endif	/* __ASM_ARCH_TCC_HARDWARE_H */
diff --git a/arch/arm/plat-tcc/include/mach/io.h b/arch/arm/plat-tcc/include/mach/io.h
new file mode 100644
index 0000000..3e911d3
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/io.h
@@ -0,0 +1,23 @@
+/*
+ * IO definitions for TCC8000 processors and boards
+ *
+ * Copyright (C) 1997-1999 Russell King
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GNU Public License version 2.
+ */
+
+#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/plat-tcc/include/mach/irqs.h b/arch/arm/plat-tcc/include/mach/irqs.h
new file mode 100644
index 0000000..da86389
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/irqs.h
@@ -0,0 +1,83 @@
+/*
+ * IRQ definitions for TCC8xxx
+ *
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2.
+ *
+ */
+
+#ifndef __ASM_ARCH_TCC_IRQS_H
+#define __ASM_ARCH_TCC_IRQS_H
+
+#define NR_IRQS 64
+
+/* PIC0 interrupts */
+#define INT_ADMA1	0
+#define INT_BDMA	1
+#define INT_ADMA0	2
+#define INT_GDMA1	3
+#define INT_I2S0RX	4
+#define INT_I2S0TX	5
+#define INT_TC		6
+#define INT_UART0	7
+#define INT_USBD	8
+#define INT_SPI0TX	9
+#define INT_UDMA	10
+#define INT_LIRQ	11
+#define INT_GDMA2	12
+#define INT_GDMA0	13
+#define INT_TC32	14
+#define INT_LCD		15
+#define INT_ADC		16
+#define INT_I2C		17
+#define INT_RTCP	18
+#define INT_RTCA	19
+#define INT_NFC		20
+#define INT_SD0		21
+#define INT_GSB0	22
+#define INT_PK		23
+#define INT_USBH0	24
+#define INT_USBH1	25
+#define INT_G2D		26
+#define INT_ECC		27
+#define INT_SPI0RX	28
+#define INT_UART1	29
+#define INT_MSCL	30
+#define INT_GSB1	31
+/* PIC1 interrupts */
+#define INT_E0		32
+#define INT_E1		33
+#define INT_E2		34
+#define INT_E3		35
+#define INT_E4		36
+#define INT_E5		37
+#define INT_E6		38
+#define INT_E7		39
+#define INT_UART2	40
+#define INT_UART3	41
+#define INT_SPI1TX	42
+#define INT_SPI1RX	43
+#define INT_GSB2	44
+#define INT_SPDIF	45
+#define INT_CDIF	46
+#define INT_VBON	47
+#define INT_VBOFF	48
+#define INT_SD1		49
+#define INT_UART4	50
+#define INT_GDMA3	51
+#define INT_I2S1RX	52
+#define INT_I2S1TX	53
+#define INT_CAN0	54
+#define INT_CAN1	55
+#define INT_GSB3	56
+#define INT_KRST	57
+#define INT_UNUSED	58
+#define INT_SD0D3	59
+#define INT_SD1D3	60
+#define INT_GPS0	61
+#define INT_GPS1	62
+#define INT_GPS2	63
+
+#endif  /* ASM_ARCH_TCC_IRQS_H */
diff --git a/arch/arm/plat-tcc/include/mach/memory.h b/arch/arm/plat-tcc/include/mach/memory.h
new file mode 100644
index 0000000..cd91ba8
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/memory.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET		UL(0x20000000)
+
+#endif
diff --git a/arch/arm/plat-tcc/include/mach/system.h b/arch/arm/plat-tcc/include/mach/system.h
new file mode 100644
index 0000000..909e603
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/system.h
@@ -0,0 +1,31 @@
+/*
+ * Author: <linux@telechips.com>
+ * Created: June 10, 2008
+ * Description: LINUX SYSTEM FUNCTIONS for TCC83x
+ *
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * Licensed under the terms of the GPL v2.
+ *
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+#include <linux/clk.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+extern void plat_tcc_reboot(void);
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	plat_tcc_reboot();
+}
+
+#endif
diff --git a/arch/arm/plat-tcc/include/mach/tcc8k-regs.h b/arch/arm/plat-tcc/include/mach/tcc8k-regs.h
new file mode 100644
index 0000000..1d94282
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/tcc8k-regs.h
@@ -0,0 +1,807 @@
+/*
+ * Telechips TCC8000 register definitions
+ *
+ * (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPLv2.
+ */
+
+#ifndef TCC8K_REGS_H
+#define TCC8K_REGS_H
+
+#include <linux/types.h>
+
+#define EXT_SDRAM_BASE		0x20000000
+#define INT_SRAM_BASE		0x30000000
+#define INT_SRAM_SIZE		SZ_32K
+#define CS0_BASE		0x40000000
+#define CS1_BASE		0x50000000
+#define CS1_SIZE		SZ_64K
+#define CS2_BASE		0x60000000
+#define CS3_BASE		0x70000000
+#define AHB_PERI_BASE		0x80000000
+#define AHB_PERI_SIZE		SZ_64K
+#define APB0_PERI_BASE		0x90000000
+#define APB0_PERI_SIZE		SZ_128K
+#define APB1_PERI_BASE		0x98000000
+#define APB1_PERI_SIZE		SZ_128K
+#define DATA_TCM_BASE		0xa0000000
+#define DATA_TCM_SIZE		SZ_8K
+#define EXT_MEM_CTRL_BASE	0xf0000000
+#define EXT_MEM_CTRL_SIZE	SZ_4K
+
+#define CS1_BASE_VIRT		(void __iomem *)0xf7000000
+#define AHB_PERI_BASE_VIRT	(void __iomem *)0xf4000000
+#define APB0_PERI_BASE_VIRT	(void __iomem *)0xf1000000
+#define APB1_PERI_BASE_VIRT	(void __iomem *)0xf2000000
+#define EXT_MEM_CTRL_BASE_VIRT	(void __iomem *)0xf3000000
+#define INT_SRAM_BASE_VIRT	(void __iomem *)0xf5000000
+#define DATA_TCM_BASE_VIRT	(void __iomem *)0xf6000000
+
+#define __REG(x)     (*((volatile u32 *)(x)))
+
+/* USB Device Controller Registers */
+#define UDC_BASE	(AHB_PERI_BASE_VIRT + 0x8000)
+#define UDC_BASE_PHYS	(AHB_PERI_BASE + 0x8000)
+
+#define UDC_IR_OFFS		0x00
+#define UDC_EIR_OFFS		0x04
+#define UDC_EIER_OFFS		0x08
+#define UDC_FAR_OFFS		0x0c
+#define UDC_FNR_OFFS		0x10
+#define UDC_EDR_OFFS		0x14
+#define UDC_RT_OFFS		0x18
+#define UDC_SSR_OFFS		0x1c
+#define UDC_SCR_OFFS		0x20
+#define UDC_EP0SR_OFFS		0x24
+#define UDC_EP0CR_OFFS		0x28
+
+#define UDC_ESR_OFFS		0x2c
+#define UDC_ECR_OFFS		0x30
+#define UDC_BRCR_OFFS		0x34
+#define UDC_BWCR_OFFS		0x38
+#define UDC_MPR_OFFS		0x3c
+#define UDC_DCR_OFFS		0x40
+#define UDC_DTCR_OFFS		0x44
+#define UDC_DFCR_OFFS		0x48
+#define UDC_DTTCR1_OFFS		0x4c
+#define UDC_DTTCR2_OFFS		0x50
+#define UDC_ESR2_OFFS		0x54
+
+#define UDC_SCR2_OFFS		0x58
+#define UDC_EP0BUF_OFFS		0x60
+#define UDC_EP1BUF_OFFS		0x64
+#define UDC_EP2BUF_OFFS		0x68
+#define UDC_EP3BUF_OFFS		0x6c
+#define UDC_PLICR_OFFS		0xa0
+#define UDC_PCR_OFFS		0xa4
+
+#define UDC_UPCR0_OFFS		0xc8
+#define UDC_UPCR1_OFFS		0xcc
+#define UDC_UPCR2_OFFS		0xd0
+#define UDC_UPCR3_OFFS		0xd4
+
+/* Bits in UDC_EIR */
+#define UDC_EIR_EP0I		(1 << 0)
+#define UDC_EIR_EP1I		(1 << 1)
+#define UDC_EIR_EP2I		(1 << 2)
+#define UDC_EIR_EP3I		(1 << 3)
+#define UDC_EIR_EPI_MASK	0x0f
+
+/* Bits in UDC_EIER */
+#define UDC_EIER_EP0IE		(1 << 0)
+#define UDC_EIER_EP1IE		(1 << 1)
+#define UDC_EIER_EP2IE		(1 << 2)
+#define UDC_EIER_EP3IE		(1 << 3)
+
+/* Bits in UDC_FNR */
+#define UDC_FNR_FN_MASK		0x7ff
+#define UDC_FNR_SM		(1 << 13)
+#define UDC_FNR_FTL		(1 << 14)
+
+/* Bits in UDC_SSR */
+#define UDC_SSR_HFRES		(1 << 0)
+#define UDC_SSR_HFSUSP		(1 << 1)
+#define UDC_SSR_HFRM		(1 << 2)
+#define UDC_SSR_SDE		(1 << 3)
+#define UDC_SSR_HSP		(1 << 4)
+#define UDC_SSR_DM		(1 << 5)
+#define UDC_SSR_DP		(1 << 6)
+#define UDC_SSR_TBM		(1 << 7)
+#define UDC_SSR_VBON		(1 << 8)
+#define UDC_SSR_VBOFF		(1 << 9)
+#define UDC_SSR_EOERR		(1 << 10)
+#define UDC_SSR_DCERR		(1 << 11)
+#define UDC_SSR_TCERR		(1 << 12)
+#define UDC_SSR_BSERR		(1 << 13)
+#define UDC_SSR_TMERR		(1 << 14)
+#define UDC_SSR_BAERR		(1 << 15)
+
+/* Bits in UDC_SCR */
+#define UDC_SCR_HRESE		(1 << 0)
+#define UDC_SCR_HSSPE		(1 << 1)
+#define UDC_SCR_RRDE		(1 << 5)
+#define UDC_SCR_SPDEN		(1 << 6)
+#define UDC_SCR_DIEN		(1 << 12)
+
+/* Bits in UDC_EP0SR */
+#define UDC_EP0SR_RSR		(1 << 0)
+#define UDC_EP0SR_TST		(1 << 1)
+#define UDC_EP0SR_SHT		(1 << 4)
+#define UDC_EP0SR_LWO		(1 << 6)
+
+/* Bits in UDC_EP0CR */
+#define UDC_EP0CR_ESS		(1 << 1)
+
+/* Bits in UDC_ESR */
+#define UDC_ESR_RPS		(1 << 0)
+#define UDC_ESR_TPS		(1 << 1)
+#define UDC_ESR_LWO		(1 << 4)
+#define UDC_ESR_FFS		(1 << 6)
+
+/* Bits in UDC_ECR */
+#define UDC_ECR_ESS		(1 << 1)
+#define UDC_ECR_CDP		(1 << 2)
+
+#define UDC_ECR_FLUSH		(1 << 6)
+#define UDC_ECR_DUEN		(1 << 7)
+
+/* Bits in UDC_UPCR0 */
+#define UDC_UPCR0_VBD		(1 << 1)
+#define UDC_UPCR0_VBDS		(1 << 6)
+#define UDC_UPCR0_RCD_12	(0x0 << 9)
+#define UDC_UPCR0_RCD_24	(0x1 << 9)
+#define UDC_UPCR0_RCD_48	(0x2 << 9)
+#define UDC_UPCR0_RCS_EXT	(0x1 << 11)
+#define UDC_UPCR0_RCS_XTAL	(0x0 << 11)
+
+/* Bits in UDC_UPCR1 */
+#define UDC_UPCR1_CDT(x)	((x) << 0)
+#define UDC_UPCR1_OTGT(x)	((x) << 3)
+#define UDC_UPCR1_SQRXT(x)	((x) << 8)
+#define UDC_UPCR1_TXFSLST(x)	((x) << 12)
+
+/* Bits in UDC_UPCR2 */
+#define UDC_UPCR2_TP		(1 << 0)
+#define UDC_UPCR2_TXRT(x)	((x) << 2)
+#define UDC_UPCR2_TXVRT(x)	((x) << 5)
+#define UDC_UPCR2_OPMODE(x)	((x) << 9)
+#define UDC_UPCR2_XCVRSEL(x)	((x) << 12)
+#define UDC_UPCR2_TM		(1 << 14)
+
+/* USB Host Controller registers */
+#define USBH0_BASE	(AHB_PERI_BASE_VIRT + 0xb000)
+#define USBH1_BASE	(AHB_PERI_BASE_VIRT + 0xb800)
+
+#define OHCI_INT_ENABLE_OFFS	0x10
+
+#define RH_DESCRIPTOR_A_OFFS	0x48
+#define RH_DESCRIPTOR_B_OFFS	0x4c
+
+#define USBHTCFG0_OFFS		0x100
+#define USBHHCFG0_OFFS		0x104
+#define USBHHCFG1_OFFS		0x104
+
+/* DMA controller registers */
+#define DMAC0_BASE	(AHB_PERI_BASE + 0x4000)
+#define DMAC1_BASE	(AHB_PERI_BASE + 0xa000)
+#define DMAC2_BASE	(AHB_PERI_BASE + 0x4800)
+#define DMAC3_BASE	(AHB_PERI_BASE + 0xa800)
+
+#define DMAC_CH_OFFSET(ch)	(ch * 0x30)
+
+#define ST_SADR_OFFS		0x00
+#define SPARAM_OFFS		0x04
+#define C_SADR_OFFS		0x0c
+#define ST_DADR_OFFS		0x10
+#define DPARAM_OFFS		0x14
+#define C_DADR_OFFS		0x1c
+#define HCOUNT_OFFS		0x20
+#define CHCTRL_OFFS		0x24
+#define RPTCTRL_OFFS		0x28
+#define EXTREQ_A_OFFS		0x2c
+
+/* Bits in CHCTRL register */
+#define CHCTRL_EN		(1 << 0)
+
+#define CHCTRL_IEN		(1 << 2)
+#define CHCTRL_FLAG		(1 << 3)
+#define CHCTRL_WSIZE8		(0 << 4)
+#define CHCTRL_WSIZE16		(1 << 4)
+#define CHCTRL_WSIZE32		(2 << 4)
+
+#define CHCTRL_BSIZE1		(0 << 6)
+#define CHCTRL_BSIZE2		(1 << 6)
+#define CHCTRL_BSIZE4		(2 << 6)
+#define CHCTRL_BSIZE8		(3 << 6)
+
+#define CHCTRL_TYPE_SINGLE_E	(0 << 8)
+#define CHCTRL_TYPE_HW		(1 << 8)
+#define CHCTRL_TYPE_SW		(2 << 8)
+#define CHCTRL_TYPE_SINGLE_L	(3 << 8)
+
+#define CHCTRL_BST		(1 << 10)
+
+/* Use DMA controller 0, channel 2 for USB */
+#define USB_DMA_BASE		(DMAC0_BASE + DMAC_CH_OFFSET(2))
+
+/* NAND flash controller registers */
+#define NFC_BASE	(AHB_PERI_BASE_VIRT + 0xd000)
+#define NFC_BASE_PHYS	(AHB_PERI_BASE + 0xd000)
+
+#define NFC_CMD_OFFS		0x00
+#define NFC_LADDR_OFFS		0x04
+#define NFC_BADDR_OFFS		0x08
+#define NFC_SADDR_OFFS		0x0c
+#define NFC_WDATA_OFFS		0x10
+#define NFC_LDATA_OFFS		0x20
+#define NFC_SDATA_OFFS		0x40
+#define NFC_CTRL_OFFS		0x50
+#define NFC_PSTART_OFFS		0x54
+#define NFC_RSTART_OFFS		0x58
+#define NFC_DSIZE_OFFS		0x5c
+#define NFC_IREQ_OFFS		0x60
+#define NFC_RST_OFFS		0x64
+#define NFC_CTRL1_OFFS		0x68
+#define NFC_MDATA_OFFS		0x70
+
+#define NFC_WDATA_PHYS_ADDR	(NFC_BASE_PHYS + NFC_WDATA_OFFS)
+
+/* Bits in NFC_CTRL */
+#define NFC_CTRL_BHLD_MASK	(0xf << 0)
+#define NFC_CTRL_BPW_MASK	(0xf << 4)
+#define NFC_CTRL_BSTP_MASK	(0xf << 8)
+#define NFC_CTRL_CADDR_MASK	(0x7 << 12)
+#define NFC_CTRL_CADDR_1	(0x0 << 12)
+#define NFC_CTRL_CADDR_2	(0x1 << 12)
+#define NFC_CTRL_CADDR_3	(0x2 << 12)
+#define NFC_CTRL_CADDR_4	(0x3 << 12)
+#define NFC_CTRL_CADDR_5	(0x4 << 12)
+#define NFC_CTRL_MSK		(1 << 15)
+#define NFC_CTRL_PSIZE256	(0 << 16)
+#define NFC_CTRL_PSIZE512	(1 << 16)
+#define NFC_CTRL_PSIZE1024	(2 << 16)
+#define NFC_CTRL_PSIZE2048	(3 << 16)
+#define NFC_CTRL_PSIZE4096	(4 << 16)
+#define NFC_CTRL_PSIZE_MASK	(7 << 16)
+#define NFC_CTRL_BSIZE1		(0 << 19)
+#define NFC_CTRL_BSIZE2		(1 << 19)
+#define NFC_CTRL_BSIZE4		(2 << 19)
+#define NFC_CTRL_BSIZE8		(3 << 19)
+#define NFC_CTRL_BSIZE_MASK	(3 << 19)
+#define NFC_CTRL_RDY		(1 << 21)
+#define NFC_CTRL_CS0SEL		(1 << 22)
+#define NFC_CTRL_CS1SEL		(1 << 23)
+#define NFC_CTRL_CS2SEL		(1 << 24)
+#define NFC_CTRL_CS3SEL		(1 << 25)
+#define NFC_CTRL_CSMASK		(0xf << 22)
+#define NFC_CTRL_BW		(1 << 26)
+#define NFC_CTRL_FS		(1 << 27)
+#define NFC_CTRL_DEN		(1 << 28)
+#define NFC_CTRL_READ_IEN	(1 << 29)
+#define NFC_CTRL_PROG_IEN	(1 << 30)
+#define NFC_CTRL_RDY_IEN	(1 << 31)
+
+/* Bits in NFC_IREQ */
+#define NFC_IREQ_IRQ0		(1 << 0)
+#define NFC_IREQ_IRQ1		(1 << 1)
+#define NFC_IREQ_IRQ2		(1 << 2)
+
+#define NFC_IREQ_FLAG0		(1 << 4)
+#define NFC_IREQ_FLAG1		(1 << 5)
+#define NFC_IREQ_FLAG2		(1 << 6)
+
+/* MMC controller registers */
+#define MMC0_BASE	(AHB_PERI_BASE_VIRT + 0xe000)
+#define MMC1_BASE	(AHB_PERI_BASE_VIRT + 0xe800)
+
+/* UART base addresses */
+
+#define UART0_BASE	(APB0_PERI_BASE_VIRT + 0x07000)
+#define UART0_BASE_PHYS	(APB0_PERI_BASE + 0x07000)
+#define UART1_BASE	(APB0_PERI_BASE_VIRT + 0x08000)
+#define UART1_BASE_PHYS	(APB0_PERI_BASE + 0x08000)
+#define UART2_BASE	(APB0_PERI_BASE_VIRT + 0x09000)
+#define UART2_BASE_PHYS	(APB0_PERI_BASE + 0x09000)
+#define UART3_BASE	(APB0_PERI_BASE_VIRT + 0x0a000)
+#define UART3_BASE_PHYS	(APB0_PERI_BASE + 0x0a000)
+#define UART4_BASE	(APB0_PERI_BASE_VIRT + 0x15000)
+#define UART4_BASE_PHYS	(APB0_PERI_BASE + 0x15000)
+
+#define UART_BASE	UART0_BASE
+#define UART_BASE_PHYS	UART0_BASE_PHYS
+
+/* ECC controller */
+#define ECC_CTR_BASE	(APB0_PERI_BASE_VIRT + 0xd000)
+
+#define ECC_CTRL_OFFS		0x00
+#define ECC_BASE_OFFS		0x04
+#define ECC_MASK_OFFS		0x08
+#define ECC_CLEAR_OFFS		0x0c
+#define ECC4_0_OFFS		0x10
+#define ECC4_1_OFFS		0x14
+
+#define ECC_EADDR0_OFFS		0x50
+
+#define ECC_ERRNUM_OFFS		0x90
+#define ECC_IREQ_OFFS		0x94
+
+/* Bits in ECC_CTRL */
+#define ECC_CTRL_ECC4_DIEN	(1 << 28)
+#define ECC_CTRL_ECC8_DIEN	(1 << 29)
+#define ECC_CTRL_ECC12_DIEN	(1 << 30)
+#define ECC_CTRL_ECC_DISABLE	0x0
+#define ECC_CTRL_ECC_SLC_ENC	0x8
+#define ECC_CTRL_ECC_SLC_DEC	0x9
+#define ECC_CTRL_ECC4_ENC	0xa
+#define ECC_CTRL_ECC4_DEC	0xb
+#define ECC_CTRL_ECC8_ENC	0xc
+#define ECC_CTRL_ECC8_DEC	0xd
+#define ECC_CTRL_ECC12_ENC	0xe
+#define ECC_CTRL_ECC12_DEC	0xf
+
+/* Bits in ECC_IREQ */
+#define ECC_IREQ_E4DI		(1 << 4)
+
+#define ECC_IREQ_E4DF		(1 << 20)
+#define ECC_IREQ_E4EF		(1 << 21)
+
+/* Interrupt controller */
+
+#define PIC0_BASE	(APB1_PERI_BASE_VIRT + 0x3000)
+#define PIC0_BASE_PHYS	(APB1_PERI_BASE + 0x3000)
+
+#define PIC0_IEN_OFFS		0x00
+#define PIC0_CREQ_OFFS		0x04
+#define PIC0_IREQ_OFFS		0x08
+#define PIC0_IRQSEL_OFFS	0x0c
+#define PIC0_SRC_OFFS		0x10
+#define PIC0_MREQ_OFFS		0x14
+#define PIC0_TSTREQ_OFFS	0x18
+#define PIC0_POL_OFFS		0x1c
+#define PIC0_IRQ_OFFS		0x20
+#define PIC0_FIQ_OFFS		0x24
+#define PIC0_MIRQ_OFFS		0x28
+#define PIC0_MFIQ_OFFS		0x2c
+#define PIC0_TMODE_OFFS		0x30
+#define PIC0_SYNC_OFFS		0x34
+#define PIC0_WKUP_OFFS		0x38
+#define PIC0_TMODEA_OFFS	0x3c
+#define PIC0_INTOEN_OFFS	0x40
+#define PIC0_MEN0_OFFS		0x44
+#define PIC0_MEN_OFFS		0x48
+
+#define PIC0_IEN		__REG(PIC0_BASE + PIC0_IEN_OFFS)
+#define PIC0_IEN_PHYS		__REG(PIC0_BASE_PHYS + PIC0_IEN_OFFS)
+#define PIC0_CREQ		__REG(PIC0_BASE + PIC0_CREQ_OFFS)
+#define PIC0_CREQ_PHYS		__REG(PIC0_BASE_PHYS + PIC0_CREQ_OFFS)
+#define PIC0_IREQ		__REG(PIC0_BASE + PIC0_IREQ_OFFS)
+#define PIC0_IRQSEL		__REG(PIC0_BASE + PIC0_IRQSEL_OFFS)
+#define PIC0_IRQSEL_PHYS	__REG(PIC0_BASE_PHYS + PIC0_IRQSEL_OFFS)
+#define PIC0_SRC		__REG(PIC0_BASE + PIC0_SRC_OFFS)
+#define PIC0_MREQ		__REG(PIC0_BASE + PIC0_MREQ_OFFS)
+#define PIC0_TSTREQ		__REG(PIC0_BASE + PIC0_TSTREQ_OFFS)
+#define PIC0_POL		__REG(PIC0_BASE + PIC0_POL_OFFS)
+#define PIC0_IRQ		__REG(PIC0_BASE + PIC0_IRQ_OFFS)
+#define PIC0_FIQ		__REG(PIC0_BASE + PIC0_FIQ_OFFS)
+#define PIC0_MIRQ		__REG(PIC0_BASE + PIC0_MIRQ_OFFS)
+#define PIC0_MFIQ		__REG(PIC0_BASE + PIC0_MFIQ_OFFS)
+#define PIC0_TMODE		__REG(PIC0_BASE + PIC0_TMODE_OFFS)
+#define PIC0_TMODE_PHYS		__REG(PIC0_BASE_PHYS + PIC0_TMODE_OFFS)
+#define PIC0_SYNC		__REG(PIC0_BASE + PIC0_SYNC_OFFS)
+#define PIC0_WKUP		__REG(PIC0_BASE + PIC0_WKUP_OFFS)
+#define PIC0_TMODEA		__REG(PIC0_BASE + PIC0_TMODEA_OFFS)
+#define PIC0_INTOEN		__REG(PIC0_BASE + PIC0_INTOEN_OFFS)
+#define PIC0_MEN0		__REG(PIC0_BASE + PIC0_MEN0_OFFS)
+#define PIC0_MEN		__REG(PIC0_BASE + PIC0_MEN_OFFS)
+
+#define PIC1_BASE	(APB1_PERI_BASE_VIRT + 0x3080)
+
+#define PIC1_IEN_OFFS		0x00
+#define PIC1_CREQ_OFFS		0x04
+#define PIC1_IREQ_OFFS		0x08
+#define PIC1_IRQSEL_OFFS	0x0c
+#define PIC1_SRC_OFFS		0x10
+#define PIC1_MREQ_OFFS		0x14
+#define PIC1_TSTREQ_OFFS	0x18
+#define PIC1_POL_OFFS		0x1c
+#define PIC1_IRQ_OFFS		0x20
+#define PIC1_FIQ_OFFS		0x24
+#define PIC1_MIRQ_OFFS		0x28
+#define PIC1_MFIQ_OFFS		0x2c
+#define PIC1_TMODE_OFFS		0x30
+#define PIC1_SYNC_OFFS		0x34
+#define PIC1_WKUP_OFFS		0x38
+#define PIC1_TMODEA_OFFS	0x3c
+#define PIC1_INTOEN_OFFS	0x40
+#define PIC1_MEN1_OFFS		0x44
+#define PIC1_MEN_OFFS		0x48
+
+#define PIC1_IEN	__REG(PIC1_BASE + PIC1_IEN_OFFS)
+#define PIC1_CREQ	__REG(PIC1_BASE + PIC1_CREQ_OFFS)
+#define PIC1_IREQ	__REG(PIC1_BASE + PIC1_IREQ_OFFS)
+#define PIC1_IRQSEL	__REG(PIC1_BASE + PIC1_IRQSEL_OFFS)
+#define PIC1_SRC	__REG(PIC1_BASE + PIC1_SRC_OFFS)
+#define PIC1_MREQ	__REG(PIC1_BASE + PIC1_MREQ_OFFS)
+#define PIC1_TSTREQ	__REG(PIC1_BASE + PIC1_TSTREQ_OFFS)
+#define PIC1_POL	__REG(PIC1_BASE + PIC1_POL_OFFS)
+#define PIC1_IRQ	__REG(PIC1_BASE + PIC1_IRQ_OFFS)
+#define PIC1_FIQ	__REG(PIC1_BASE + PIC1_FIQ_OFFS)
+#define PIC1_MIRQ	__REG(PIC1_BASE + PIC1_MIRQ_OFFS)
+#define PIC1_MFIQ	__REG(PIC1_BASE + PIC1_MFIQ_OFFS)
+#define PIC1_TMODE	__REG(PIC1_BASE + PIC1_TMODE_OFFS)
+#define PIC1_SYNC	__REG(PIC1_BASE + PIC1_SYNC_OFFS)
+#define PIC1_WKUP	__REG(PIC1_BASE + PIC1_WKUP_OFFS)
+#define PIC1_TMODEA	__REG(PIC1_BASE + PIC1_TMODEA_OFFS)
+#define PIC1_INTOEN	__REG(PIC1_BASE + PIC1_INTOEN_OFFS)
+#define PIC1_MEN1	__REG(PIC1_BASE + PIC1_MEN1_OFFS)
+#define PIC1_MEN	__REG(PIC1_BASE + PIC1_MEN_OFFS)
+
+/* Timer registers */
+#define TIMER_BASE		(APB1_PERI_BASE_VIRT + 0x4000)
+#define TIMER_BASE_PHYS		(APB1_PERI_BASE + 0x4000)
+
+#define TWDCFG_OFFS		0x70
+
+#define TC32EN_OFFS		0x80
+#define TC32LDV_OFFS		0x84
+#define TC32CMP0_OFFS		0x88
+#define TC32CMP1_OFFS		0x8c
+#define TC32PCNT_OFFS		0x90
+#define TC32MCNT_OFFS		0x94
+#define TC32IRQ_OFFS		0x98
+
+/* Bits in TC32EN */
+#define TC32EN_PRESCALE_MASK	0x00ffffff
+#define TC32EN_ENABLE		(1 << 24)
+#define TC32EN_LOADZERO		(1 << 25)
+#define TC32EN_STOPMODE		(1 << 26)
+#define TC32EN_LDM0		(1 << 28)
+#define TC32EN_LDM1		(1 << 29)
+
+/* Bits in TC32IRQ */
+#define TC32IRQ_MSTAT_MASK	0x0000001f
+#define TC32IRQ_RSTAT_MASK	(0x1f << 8)
+#define TC32IRQ_IRQEN0		(1 << 16)
+#define TC32IRQ_IRQEN1		(1 << 17)
+#define TC32IRQ_IRQEN2		(1 << 18)
+#define TC32IRQ_IRQEN3		(1 << 19)
+#define TC32IRQ_IRQEN4		(1 << 20)
+#define TC32IRQ_RSYNC		(1 << 30)
+#define TC32IRQ_IRQCLR		(1 << 31)
+
+/* GPIO registers */
+#define GPIOPD_BASE		(APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOPD_DAT_OFFS		0x00
+#define GPIOPD_DOE_OFFS		0x04
+#define GPIOPD_FS0_OFFS		0x08
+#define GPIOPD_FS1_OFFS		0x0c
+#define GPIOPD_FS2_OFFS		0x10
+#define GPIOPD_RPU_OFFS		0x30
+#define GPIOPD_RPD_OFFS		0x34
+#define GPIOPD_DV0_OFFS		0x38
+#define GPIOPD_DV1_OFFS		0x3c
+
+#define GPIOPS_BASE		(APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOPS_DAT_OFFS		0x40
+#define GPIOPS_DOE_OFFS		0x44
+#define GPIOPS_FS0_OFFS		0x48
+#define GPIOPS_FS1_OFFS		0x4c
+#define GPIOPS_FS2_OFFS		0x50
+#define GPIOPS_FS3_OFFS		0x54
+#define GPIOPS_RPU_OFFS		0x70
+#define GPIOPS_RPD_OFFS		0x74
+#define GPIOPS_DV0_OFFS		0x78
+#define GPIOPS_DV1_OFFS		0x7c
+
+#define GPIOPS_FS1_SDH0_BITS	0x000000ff
+#define GPIOPS_FS1_SDH1_BITS	0x0000ff00
+
+#define GPIOPU_BASE		(APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOPU_DAT_OFFS		0x80
+#define GPIOPU_DOE_OFFS		0x84
+#define GPIOPU_FS0_OFFS		0x88
+#define GPIOPU_FS1_OFFS		0x8c
+#define GPIOPU_FS2_OFFS		0x90
+#define GPIOPU_RPU_OFFS		0xb0
+#define GPIOPU_RPD_OFFS		0xb4
+#define GPIOPU_DV0_OFFS		0xb8
+#define GPIOPU_DV1_OFFS		0xbc
+
+#define GPIOPU_FS0_TXD0		(1 << 0)
+#define GPIOPU_FS0_RXD0		(1 << 1)
+#define GPIOPU_FS0_CTS0		(1 << 2)
+#define GPIOPU_FS0_RTS0		(1 << 3)
+#define GPIOPU_FS0_TXD1		(1 << 4)
+#define GPIOPU_FS0_RXD1		(1 << 5)
+#define GPIOPU_FS0_CTS1		(1 << 6)
+#define GPIOPU_FS0_RTS1		(1 << 7)
+#define GPIOPU_FS0_TXD2		(1 << 8)
+#define GPIOPU_FS0_RXD2		(1 << 9)
+#define GPIOPU_FS0_CTS2		(1 << 10)
+#define GPIOPU_FS0_RTS2		(1 << 11)
+#define GPIOPU_FS0_TXD3		(1 << 12)
+#define GPIOPU_FS0_RXD3		(1 << 13)
+#define GPIOPU_FS0_CTS3		(1 << 14)
+#define GPIOPU_FS0_RTS3		(1 << 15)
+#define GPIOPU_FS0_TXD4		(1 << 16)
+#define GPIOPU_FS0_RXD4		(1 << 17)
+#define GPIOPU_FS0_CTS4		(1 << 18)
+#define GPIOPU_FS0_RTS4		(1 << 19)
+
+#define GPIOFC_BASE		(APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOFC_DAT_OFFS		0xc0
+#define GPIOFC_DOE_OFFS		0xc4
+#define GPIOFC_FS0_OFFS		0xc8
+#define GPIOFC_FS1_OFFS		0xcc
+#define GPIOFC_FS2_OFFS		0xd0
+#define GPIOFC_FS3_OFFS		0xd4
+#define GPIOFC_RPU_OFFS		0xf0
+#define GPIOFC_RPD_OFFS		0xf4
+#define GPIOFC_DV0_OFFS		0xf8
+#define GPIOFC_DV1_OFFS		0xfc
+
+#define GPIOFD_BASE		(APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOFD_DAT_OFFS		0x100
+#define GPIOFD_DOE_OFFS		0x104
+#define GPIOFD_FS0_OFFS		0x108
+#define GPIOFD_FS1_OFFS		0x10c
+#define GPIOFD_FS2_OFFS		0x110
+#define GPIOFD_RPU_OFFS		0x130
+#define GPIOFD_RPD_OFFS		0x134
+#define GPIOFD_DV0_OFFS		0x138
+#define GPIOFD_DV1_OFFS		0x13c
+
+#define GPIOLC_BASE		(APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOLC_DAT_OFFS		0x140
+#define GPIOLC_DOE_OFFS		0x144
+#define GPIOLC_FS0_OFFS		0x148
+#define GPIOLC_FS1_OFFS		0x14c
+#define GPIOLC_RPU_OFFS		0x170
+#define GPIOLC_RPD_OFFS		0x174
+#define GPIOLC_DV0_OFFS		0x178
+#define GPIOLC_DV1_OFFS		0x17c
+
+#define GPIOLD_BASE		(APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOLD_DAT_OFFS		0x180
+#define GPIOLD_DOE_OFFS		0x184
+#define GPIOLD_FS0_OFFS		0x188
+#define GPIOLD_FS1_OFFS		0x18c
+#define GPIOLD_FS2_OFFS		0x190
+#define GPIOLD_RPU_OFFS		0x1b0
+#define GPIOLD_RPD_OFFS		0x1b4
+#define GPIOLD_DV0_OFFS		0x1b8
+#define GPIOLD_DV1_OFFS		0x1bc
+
+#define GPIOAD_BASE		(APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOAD_DAT_OFFS		0x1c0
+#define GPIOAD_DOE_OFFS		0x1c4
+#define GPIOAD_FS0_OFFS		0x1c8
+#define GPIOAD_RPU_OFFS		0x1f0
+#define GPIOAD_RPD_OFFS		0x1f4
+#define GPIOAD_DV0_OFFS		0x1f8
+#define GPIOAD_DV1_OFFS		0x1fc
+
+#define GPIOXC_BASE		(APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOXC_DAT_OFFS		0x200
+#define GPIOXC_DOE_OFFS		0x204
+#define GPIOXC_FS0_OFFS		0x208
+#define GPIOXC_RPU_OFFS		0x230
+#define GPIOXC_RPD_OFFS		0x234
+#define GPIOXC_DV0_OFFS		0x238
+#define GPIOXC_DV1_OFFS		0x23c
+
+#define GPIOXC_FS0		__REG(GPIOXC_BASE + GPIOXC_FS0_OFFS)
+
+#define GPIOXC_FS0_CS0		(1 << 26)
+#define GPIOXC_FS0_CS1		(1 << 27)
+
+#define GPIOXD_BASE		(APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOXD_DAT_OFFS		0x240
+#define GPIOXD_FS0_OFFS		0x248
+#define GPIOXD_RPU_OFFS		0x270
+#define GPIOXD_RPD_OFFS		0x274
+#define GPIOXD_DV0_OFFS		0x278
+#define GPIOXD_DV1_OFFS		0x27c
+
+#define GPIOPK_BASE		(APB1_PERI_BASE_VIRT + 0x1c000)
+
+#define GPIOPK_RST_OFFS		0x008
+#define GPIOPK_DAT_OFFS		0x100
+#define GPIOPK_DOE_OFFS		0x104
+#define GPIOPK_FS0_OFFS		0x108
+#define GPIOPK_FS1_OFFS		0x10c
+#define GPIOPK_FS2_OFFS		0x110
+#define GPIOPK_IRQST_OFFS	0x210
+#define GPIOPK_IRQEN_OFFS	0x214
+#define GPIOPK_IRQPOL_OFFS	0x218
+#define GPIOPK_IRQTM0_OFFS	0x21c
+#define GPIOPK_IRQTM1_OFFS	0x220
+#define GPIOPK_CTL_OFFS		0x22c
+
+#define PMGPIO_BASE		(APB1_PERI_BASE_VIRT + 0x10000)
+#define BACKUP_RAM_BASE		PMGPIO_BASE
+
+#define PMGPIO_DAT_OFFS		0x800
+#define PMGPIO_DOE_OFFS		0x804
+#define PMGPIO_FS0_OFFS		0x808
+#define PMGPIO_RPU_OFFS		0x810
+#define PMGPIO_RPD_OFFS		0x814
+#define PMGPIO_DV0_OFFS		0x818
+#define PMGPIO_DV1_OFFS		0x81c
+#define PMGPIO_EE0_OFFS		0x820
+#define PMGPIO_EE1_OFFS		0x824
+#define PMGPIO_CTL_OFFS		0x828
+#define PMGPIO_DI_OFFS		0x82c
+#define PMGPIO_STR_OFFS		0x830
+#define PMGPIO_STF_OFFS		0x834
+#define PMGPIO_POL_OFFS		0x838
+#define PMGPIO_APB_OFFS		0x800
+
+/* Clock controller registers */
+#define CKC_BASE	((void __iomem *)(APB1_PERI_BASE_VIRT + 0x6000))
+
+#define CLKCTRL_OFFS		0x00
+#define PLL0CFG_OFFS		0x04
+#define PLL1CFG_OFFS		0x08
+#define CLKDIVC0_OFFS		0x0c
+
+#define BCLKCTR0_OFFS		0x14
+#define SWRESET0_OFFS		0x18
+
+#define BCLKCTR1_OFFS		0x60
+#define SWRESET1_OFFS		0x64
+#define PWDCTL_OFFS		0x68
+#define PLL2CFG_OFFS		0x6c
+#define CLKDIVC1_OFFS		0x70
+
+#define ACLKREF_OFFS		0x80
+#define ACLKI2C_OFFS		0x84
+#define ACLKSPI0_OFFS		0x88
+#define ACLKSPI1_OFFS		0x8c
+#define ACLKUART0_OFFS		0x90
+#define ACLKUART1_OFFS		0x94
+#define ACLKUART2_OFFS		0x98
+#define ACLKUART3_OFFS		0x9c
+#define ACLKUART4_OFFS		0xa0
+#define ACLKTCT_OFFS		0xa4
+#define ACLKTCX_OFFS		0xa8
+#define ACLKTCZ_OFFS		0xac
+#define ACLKADC_OFFS		0xb0
+#define ACLKDAI0_OFFS		0xb4
+#define ACLKDAI1_OFFS		0xb8
+#define ACLKLCD_OFFS		0xbc
+#define ACLKSPDIF_OFFS		0xc0
+#define ACLKUSBH_OFFS		0xc4
+#define ACLKSDH0_OFFS		0xc8
+#define ACLKSDH1_OFFS		0xcc
+#define ACLKC3DEC_OFFS		0xd0
+#define ACLKEXT_OFFS		0xd4
+#define ACLKCAN0_OFFS		0xd8
+#define ACLKCAN1_OFFS		0xdc
+#define ACLKGSB0_OFFS		0xe0
+#define ACLKGSB1_OFFS		0xe4
+#define ACLKGSB2_OFFS		0xe8
+#define ACLKGSB3_OFFS		0xec
+
+#define PLLxCFG_PD		(1 << 31)
+
+/* CLKCTRL bits */
+#define CLKCTRL_XE		(1 << 31)
+
+/* CLKDIVCx bits */
+#define CLKDIVC0_XTE		(1 << 7)
+#define CLKDIVC0_XE		(1 << 15)
+#define CLKDIVC0_P1E		(1 << 23)
+#define CLKDIVC0_P0E		(1 << 31)
+
+#define CLKDIVC1_P2E		(1 << 7)
+
+/* BCLKCTR0 clock bits */
+#define BCLKCTR0_USBD		(1 << 4)
+#define BCLKCTR0_ECC		(1 << 9)
+#define BCLKCTR0_USBH0		(1 << 11)
+#define BCLKCTR0_NFC		(1 << 16)
+
+/* BCLKCTR1 clock bits */
+#define BCLKCTR1_USBH1		(1 << 20)
+
+/* SWRESET0 bits */
+#define SWRESET0_USBD		(1 << 4)
+#define SWRESET0_USBH0		(1 << 11)
+
+/* SWRESET1 bits */
+#define SWRESET1_USBH1		(1 << 20)
+
+/* System clock sources.
+ * Note: These are the clock sources that serve as parents for
+ * all other clocks. They have no parents themselves.
+ *
+ * These values are used for struct clk->root_id. All clocks
+ * that are not system clock sources have this value set to
+ * CLK_SRC_NOROOT.
+ * The values for system clocks start with CLK_SRC_PLL0 == 0
+ * because this gives us exactly the values needed for the lower
+ * 4 bits of ACLK_* registers. Therefore, CLK_SRC_NOROOT is
+ * defined as -1 to not disturb the order.
+ */
+enum root_clks {
+	CLK_SRC_NOROOT = -1,
+	CLK_SRC_PLL0 = 0,
+	CLK_SRC_PLL1,
+	CLK_SRC_PLL0DIV,
+	CLK_SRC_PLL1DIV,
+	CLK_SRC_XI,
+	CLK_SRC_XIDIV,
+	CLK_SRC_XTI,
+	CLK_SRC_XTIDIV,
+	CLK_SRC_PLL2,
+	CLK_SRC_PLL2DIV,
+	CLK_SRC_PK0,
+	CLK_SRC_PK1,
+	CLK_SRC_PK2,
+	CLK_SRC_PK3,
+	CLK_SRC_PK4,
+	CLK_SRC_48MHZ
+};
+
+#define CLK_SRC_MASK		0xf
+
+/* Bits in ACLK* registers */
+#define ACLK_EN		(1 << 28)
+#define ACLK_SEL_SHIFT		24
+#define ACLK_SEL_MASK		0x0f000000
+#define ACLK_DIV_MASK		0x00000fff
+
+/* System configuration registers */
+
+#define SCFG_BASE		(APB1_PERI_BASE_VIRT + 0x13000)
+
+#define	BMI_OFFS		0x00
+#define AHBCON0_OFFS		0x04
+#define APBPWE_OFFS		0x08
+#define DTCMWAIT_OFFS		0x0c
+#define ECCSEL_OFFS		0x10
+#define AHBCON1_OFFS		0x14
+#define SDHCFG_OFFS		0x18
+#define REMAP_OFFS		0x20
+#define LCDSIAE_OFFS		0x24
+#define XMCCFG_OFFS		0xe0
+#define IMCCFG_OFFS		0xe4
+
+/* Values for ECCSEL */
+#define ECCSEL_EXTMEM		0x0
+#define ECCSEL_DTCM		0x1
+#define ECCSEL_INT_SRAM		0x2
+#define ECCSEL_AHB		0x3
+
+/* Bits in XMCCFG */
+#define XMCCFG_NFCE		(1 << 1)
+#define XMCCFG_FDXD		(1 << 2)
+
+/* External memory controller registers */
+
+#define EMC_BASE		EXT_MEM_CTRL_BASE
+
+#define SDCFG_OFFS		0x00
+#define SDFSM_OFFS		0x04
+#define MCFG_OFFS		0x08
+
+#define CSCFG0_OFFS		0x10
+#define CSCFG1_OFFS		0x14
+#define CSCFG2_OFFS		0x18
+#define CSCFG3_OFFS		0x1c
+
+#define MCFG_SDEN		(1 << 4)
+
+#endif /* TCC8K_REGS_H */
diff --git a/arch/arm/plat-tcc/include/mach/timex.h b/arch/arm/plat-tcc/include/mach/timex.h
new file mode 100644
index 0000000..057acbe
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/timex.h
@@ -0,0 +1,5 @@
+/*
+ * A definition needed by arch core code.
+ *
+ */
+#define CLOCK_TICK_RATE		(HZ * 100000UL)
diff --git a/arch/arm/plat-tcc/include/mach/uncompress.h b/arch/arm/plat-tcc/include/mach/uncompress.h
new file mode 100644
index 0000000..7a3e33a
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/uncompress.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * This file is licensed under the terms of the GPL version 2.
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/types.h>
+
+#include <mach/tcc8k-regs.h>
+
+unsigned int system_rev;
+
+#define ID_MASK			0x7fff
+
+static void putc(int c)
+{
+	u32 *uart_lsr = (u32 *)(UART_BASE_PHYS + (UART_LSR << 2));
+	u32 *uart_tx = (u32 *)(UART_BASE_PHYS + (UART_TX << 2));
+
+	while (!(*uart_lsr & UART_LSR_THRE))
+		barrier();
+	*uart_tx = c;
+}
+
+static inline void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/plat-tcc/include/mach/vmalloc.h b/arch/arm/plat-tcc/include/mach/vmalloc.h
new file mode 100644
index 0000000..99414d9
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/vmalloc.h
@@ -0,0 +1,10 @@
+/*
+ * Author: <linux@telechips.com>
+ * Created: June 10, 2008
+ *
+ * Copyright (C) 2000 Russell King.
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * Licensed under the terms of the GPL v2.
+ */
+#define VMALLOC_END	0xf0000000UL
diff --git a/arch/arm/plat-tcc/system.c b/arch/arm/plat-tcc/system.c
new file mode 100644
index 0000000..cc208fa
--- /dev/null
+++ b/arch/arm/plat-tcc/system.c
@@ -0,0 +1,25 @@
+/*
+ * System functions for Telechips TCCxxxx SoCs
+ *
+ * Copyright (C) Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2.
+ *
+ */
+
+#include <linux/io.h>
+
+#include <mach/tcc8k-regs.h>
+
+/* System reboot */
+void plat_tcc_reboot(void)
+{
+	/* Make sure clocks are on */
+	__raw_writel(0xffffffff, CKC_BASE + BCLKCTR0_OFFS);
+
+	/* Enable watchdog reset */
+	__raw_writel(0x49, TIMER_BASE + TWDCFG_OFFS);
+	/* Wait for reset */
+	while(1)
+		;
+}
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index f515727..9ac8725 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -90,6 +90,7 @@
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_ALLOCATOR
 	select HAVE_FB_ATMEL
+	select HAVE_NET_MACB
 
 #
 # CPU types
diff --git a/arch/avr32/boards/mimc200/fram.c b/arch/avr32/boards/mimc200/fram.c
index 54fbd95..9764a1a 100644
--- a/arch/avr32/boards/mimc200/fram.c
+++ b/arch/avr32/boards/mimc200/fram.c
@@ -41,6 +41,7 @@
 static const struct file_operations fram_fops = {
 	.owner			= THIS_MODULE,
 	.mmap			= fram_mmap,
+	.llseek			= noop_llseek,
 };
 
 #define FRAM_MINOR	0
diff --git a/arch/avr32/include/asm/ioctls.h b/arch/avr32/include/asm/ioctls.h
index b7dd324..909cf66 100644
--- a/arch/avr32/include/asm/ioctls.h
+++ b/arch/avr32/include/asm/ioctls.h
@@ -1,90 +1,6 @@
 #ifndef __ASM_AVR32_IOCTLS_H
 #define __ASM_AVR32_IOCTLS_H
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define TIOCGRS485      0x542E
-#define TIOCSRS485      0x542F
-
-#define FIONCLEX	0x5450
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-#define FIOQSIZE	0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ASM_AVR32_IOCTLS_H */
diff --git a/arch/avr32/include/asm/irqflags.h b/arch/avr32/include/asm/irqflags.h
index 93570da..006e948 100644
--- a/arch/avr32/include/asm/irqflags.h
+++ b/arch/avr32/include/asm/irqflags.h
@@ -8,16 +8,14 @@
 #ifndef __ASM_AVR32_IRQFLAGS_H
 #define __ASM_AVR32_IRQFLAGS_H
 
+#include <linux/types.h>
 #include <asm/sysreg.h>
 
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
 {
 	return sysreg_read(SR);
 }
 
-#define raw_local_save_flags(x)					\
-	do { (x) = __raw_local_save_flags(); } while (0)
-
 /*
  * This will restore ALL status register flags, not only the interrupt
  * mask flag.
@@ -25,44 +23,39 @@
  * The empty asm statement informs the compiler of this fact while
  * also serving as a barrier.
  */
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
 {
 	sysreg_write(SR, flags);
 	asm volatile("" : : : "memory", "cc");
 }
 
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
 {
 	asm volatile("ssrf %0" : : "n"(SYSREG_GM_OFFSET) : "memory");
 }
 
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
 {
 	asm volatile("csrf %0" : : "n"(SYSREG_GM_OFFSET) : "memory");
 }
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
 {
 	return (flags & SYSREG_BIT(GM)) != 0;
 }
 
-static inline int raw_irqs_disabled(void)
+static inline bool arch_irqs_disabled(void)
 {
-	unsigned long flags = __raw_local_save_flags();
-
-	return raw_irqs_disabled_flags(flags);
+	return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
 {
-	unsigned long flags = __raw_local_save_flags();
+	unsigned long flags = arch_local_save_flags();
 
-	raw_local_irq_disable();
+	arch_local_irq_disable();
 
 	return flags;
 }
 
-#define raw_local_irq_save(flags)				\
-	do { (flags) = __raw_local_irq_save(); } while (0)
-
 #endif /* __ASM_AVR32_IRQFLAGS_H */
diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c
index 98f94d0..a727f54 100644
--- a/arch/avr32/kernel/module.c
+++ b/arch/avr32/kernel/module.c
@@ -314,10 +314,9 @@
 	vfree(module->arch.syminfo);
 	module->arch.syminfo = NULL;
 
-	return module_bug_finalize(hdr, sechdrs, module);
+	return 0;
 }
 
 void module_arch_cleanup(struct module *module)
 {
-	module_bug_cleanup(module);
 }
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index 5a3152b..d9a1cb7 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -300,7 +300,7 @@
 
 config BF_REV_0_2
 	bool "0.2"
-	depends on (BF52x || BF537 || BF536 || BF534 || (BF54x && !BF54xM))
+	depends on (BF51x || BF52x || BF537 || BF536 || BF534 || (BF54x && !BF54xM))
 
 config BF_REV_0_3
 	bool "0.3"
@@ -356,7 +356,7 @@
 
 config MEM_MT48LC32M16A2TG_75
 	bool
-	depends on (BFIN527_EZKIT || BFIN527_EZKIT_V2 || BFIN532_IP0X || BLACKSTAMP)
+	depends on (BFIN527_EZKIT || BFIN527_EZKIT_V2 || BFIN532_IP0X || BLACKSTAMP || BFIN527_AD7160EVAL)
 	default y
 
 config MEM_MT48H32M16LFCJ_75
@@ -426,6 +426,7 @@
 	default "25000000" # most people use this
 	default "27000000" if BFIN533_EZKIT
 	default "30000000" if BFIN561_EZKIT
+	default "24000000" if BFIN527_AD7160EVAL
 	help
 	  The frequency of CLKIN crystal oscillator on the board in Hz.
 	  Warning: This value should match the crystal on the board. Otherwise,
@@ -463,6 +464,7 @@
 	default "20" if (BFIN537_BLUETECHNIX_CM_E || BFIN537_BLUETECHNIX_CM_U || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM)
 	default "20" if BFIN561_EZKIT
 	default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN518F_EZBRD)
+	default "25" if BFIN527_AD7160EVAL
 	help
 	  This controls the frequency of the on-chip PLL. This can be between 1 and 64.
 	  PLL Frequency = (Crystal Frequency) * (this setting)
@@ -926,6 +928,12 @@
 
 endchoice
 
+# Common code uses "ROMKERNEL" or "XIP_KERNEL", so define both
+config XIP_KERNEL
+	bool
+	default y
+	depends on ROMKERNEL
+
 source "mm/Kconfig"
 
 config BFIN_GPTIMERS
diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
index 3e65b0f..46738d4 100644
--- a/arch/blackfin/Makefile
+++ b/arch/blackfin/Makefile
@@ -101,9 +101,8 @@
 KBUILD_AFLAGS += -mcpu=$(cpu-y)-$(rev-y)
 
 # - we utilize the silicon rev from the toolchain, so move it over to the checkflags
-# - the l1_text attribute is Blackfin specific, so fake it out as used to kill warnings
 CHECKFLAGS_SILICON = $(shell echo "" | $(CPP) $(KBUILD_CFLAGS) -dD - 2>/dev/null | awk '$$2 == "__SILICON_REVISION__" { print $$3 }')
-CHECKFLAGS += -D__SILICON_REVISION__=$(CHECKFLAGS_SILICON) -Dl1_text=__used__
+CHECKFLAGS += -D__SILICON_REVISION__=$(CHECKFLAGS_SILICON) -D__bfin__
 
 head-y   := arch/$(ARCH)/kernel/init_task.o
 
diff --git a/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig b/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig
new file mode 100644
index 0000000..08c55f6
--- /dev/null
+++ b/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig
@@ -0,0 +1,105 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_AIO is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_PREEMPT=y
+CONFIG_BF527=y
+CONFIG_BF_REV_0_2=y
+CONFIG_IRQ_TWI=7
+CONFIG_IRQ_PORTH_INTA=7
+CONFIG_IRQ_PORTH_INTB=7
+CONFIG_BFIN527_AD7160EVAL=y
+CONFIG_BF527_SPORT0_PORTF=y
+CONFIG_BF527_UART1_PORTG=y
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="bootargs=root=/dev/mtdblock0 rw clkin_hz=24000000 earlyprintk=serial,uart0,57600 console=tty0 console=ttyBF0,57600"
+CONFIG_CLKIN_HZ=24000000
+CONFIG_HZ_300=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+CONFIG_IP_CHECKSUM_L1=y
+CONFIG_SYSCALL_TAB_L1=y
+CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_BFIN_GPTIMERS=y
+CONFIG_C_CDPRIO=y
+CONFIG_BANK_1=0x5554
+CONFIG_BANK_3=0xFFC0
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+# CONFIG_WIRELESS is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_MISC_DEVICES is not set
+# 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_TOUCHSCREEN_AD7160=y
+CONFIG_TOUCHSCREEN_AD7160_FW=y
+# CONFIG_SERIO is not set
+# CONFIG_BFIN_DMA_INTERFACE is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_BFIN_OTP is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=400
+CONFIG_SPI=y
+CONFIG_SPI_BFIN=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_BLACKFIN_VGA16 is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_G_SERIAL=y
+CONFIG_MMC=y
+CONFIG_MMC_SPI=y
+CONFIG_EXT2_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPLB_INFO=y
+CONFIG_SECURITY=y
+CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/BF527-TLL6527M_defconfig b/arch/blackfin/configs/BF527-TLL6527M_defconfig
new file mode 100644
index 0000000..92ded5e
--- /dev/null
+++ b/arch/blackfin/configs/BF527-TLL6527M_defconfig
@@ -0,0 +1,180 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="DEV_0-1_pre2010"
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_ELF_CORE is not set
+# CONFIG_FUTEX is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+CONFIG_SLAB=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=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_PREEMPT_VOLUNTARY=y
+CONFIG_BF527=y
+CONFIG_BF_REV_0_2=y
+CONFIG_BFIN527_TLL6527M=y
+CONFIG_BF527_UART1_PORTG=y
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
+CONFIG_BOOT_LOAD=0x400000
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_SCHEDULE_L1 is not set
+# CONFIG_MEMSET_L1 is not set
+# CONFIG_MEMCPY_L1 is not set
+# CONFIG_SYS_BFIN_SPINLOCK_L1 is not set
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
+CONFIG_BFIN_GPTIMERS=y
+CONFIG_DMA_UNCACHED_2M=y
+CONFIG_C_CDPRIO=y
+CONFIG_BANK_0=0xFFC2
+CONFIG_BANK_1=0xFFC2
+CONFIG_BANK_2=0xFFC2
+CONFIG_BANK_3=0xFFC2
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_IRDA=m
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+CONFIG_IRTTY_SIR=m
+CONFIG_BFIN_SIR=m
+CONFIG_BFIN_SIR0=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_GPIO_ADDR=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_BFIN_MAC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# 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_TOUCHSCREEN_AD7879=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=y
+CONFIG_INPUT_ADXL34X=y
+# CONFIG_SERIO is not set
+CONFIG_BFIN_PPI=m
+CONFIG_BFIN_SIMPLE_TIMER=m
+CONFIG_BFIN_SPORT=m
+# CONFIG_CONSOLE_TRANSLATIONS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_SMBUS=y
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_BFIN_WDT=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_BLACKFIN_CAM=m
+CONFIG_OV9655=y
+CONFIG_FB=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_6x11=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_BLACKFIN_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SOC=y
+CONFIG_SND_BF5XX_I2S=y
+CONFIG_SND_BF5XX_SOC_SSM2602=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_BFIN=y
+CONFIG_EXT2_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_UTF8=m
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_MMRS=y
+CONFIG_DEBUG_HWERR=y
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPLB_INFO=y
+CONFIG_SECURITY=y
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC7=m
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index d9eb29e..9e7c537 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -1,4 +1,5 @@
 include include/asm-generic/Kbuild.asm
 
 header-y += bfin_sport.h
+header-y += cachectl.h
 header-y += fixed_code.h
diff --git a/arch/blackfin/include/asm/bfin5xx_spi.h b/arch/blackfin/include/asm/bfin5xx_spi.h
index ed4f8c6..0b5136e 100644
--- a/arch/blackfin/include/asm/bfin5xx_spi.h
+++ b/arch/blackfin/include/asm/bfin5xx_spi.h
@@ -11,26 +11,17 @@
 
 #define MIN_SPI_BAUD_VAL	2
 
-#define SPI_READ              0
-#define SPI_WRITE             1
-
-#define SPI_CTRL_OFF            0x0
-#define SPI_FLAG_OFF            0x4
-#define SPI_STAT_OFF            0x8
-#define SPI_TXBUFF_OFF          0xc
-#define SPI_RXBUFF_OFF          0x10
-#define SPI_BAUD_OFF            0x14
-#define SPI_SHAW_OFF            0x18
-
-
 #define BIT_CTL_ENABLE      0x4000
 #define BIT_CTL_OPENDRAIN   0x2000
 #define BIT_CTL_MASTER      0x1000
-#define BIT_CTL_POLAR       0x0800
-#define BIT_CTL_PHASE       0x0400
-#define BIT_CTL_BITORDER    0x0200
+#define BIT_CTL_CPOL        0x0800
+#define BIT_CTL_CPHA        0x0400
+#define BIT_CTL_LSBF        0x0200
 #define BIT_CTL_WORDSIZE    0x0100
-#define BIT_CTL_MISOENABLE  0x0020
+#define BIT_CTL_EMISO       0x0020
+#define BIT_CTL_PSSE        0x0010
+#define BIT_CTL_GM          0x0008
+#define BIT_CTL_SZ          0x0004
 #define BIT_CTL_RXMOD       0x0000
 #define BIT_CTL_TXMOD       0x0001
 #define BIT_CTL_TIMOD_DMA_TX 0x0003
@@ -50,61 +41,26 @@
 #define BIT_STU_SENDOVER    0x0001
 #define BIT_STU_RECVFULL    0x0020
 
-#define CFG_SPI_ENABLE      1
-#define CFG_SPI_DISABLE     0
+/*
+ * All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits.  So use a helper macro to streamline this.
+ */
+#define __BFP(m) u16 m; u16 __pad_##m
 
-#define CFG_SPI_OUTENABLE   1
-#define CFG_SPI_OUTDISABLE  0
+/*
+ * bfin spi registers layout
+ */
+struct bfin_spi_regs {
+	__BFP(ctl);
+	__BFP(flg);
+	__BFP(stat);
+	__BFP(tdbr);
+	__BFP(rdbr);
+	__BFP(baud);
+	__BFP(shadow);
+};
 
-#define CFG_SPI_ACTLOW      1
-#define CFG_SPI_ACTHIGH     0
-
-#define CFG_SPI_PHASESTART  1
-#define CFG_SPI_PHASEMID    0
-
-#define CFG_SPI_MASTER      1
-#define CFG_SPI_SLAVE       0
-
-#define CFG_SPI_SENELAST    0
-#define CFG_SPI_SENDZERO    1
-
-#define CFG_SPI_RCVFLUSH    1
-#define CFG_SPI_RCVDISCARD  0
-
-#define CFG_SPI_LSBFIRST    1
-#define CFG_SPI_MSBFIRST    0
-
-#define CFG_SPI_WORDSIZE16  1
-#define CFG_SPI_WORDSIZE8   0
-
-#define CFG_SPI_MISOENABLE   1
-#define CFG_SPI_MISODISABLE  0
-
-#define CFG_SPI_READ      0x00
-#define CFG_SPI_WRITE     0x01
-#define CFG_SPI_DMAREAD   0x02
-#define CFG_SPI_DMAWRITE  0x03
-
-#define CFG_SPI_CSCLEARALL  0
-#define CFG_SPI_CHIPSEL1    1
-#define CFG_SPI_CHIPSEL2    2
-#define CFG_SPI_CHIPSEL3    3
-#define CFG_SPI_CHIPSEL4    4
-#define CFG_SPI_CHIPSEL5    5
-#define CFG_SPI_CHIPSEL6    6
-#define CFG_SPI_CHIPSEL7    7
-
-#define CFG_SPI_CS1VALUE    1
-#define CFG_SPI_CS2VALUE    2
-#define CFG_SPI_CS3VALUE    3
-#define CFG_SPI_CS4VALUE    4
-#define CFG_SPI_CS5VALUE    5
-#define CFG_SPI_CS6VALUE    6
-#define CFG_SPI_CS7VALUE    7
-
-#define CMD_SPI_SET_BAUDRATE  2
-#define CMD_SPI_GET_SYSTEMCLOCK   25
-#define CMD_SPI_SET_WRITECONTINUOUS     26
+#define MAX_CTRL_CS          8  /* cs in spi controller */
 
 /* device.platform_data for SSP controller devices */
 struct bfin5xx_spi_master {
@@ -120,9 +76,7 @@
 	u16 ctl_reg;
 	u8 enable_dma;
 	u8 bits_per_word;
-	u8 cs_change_per_word;
 	u16 cs_chg_udelay; /* Some devices require 16-bit delays */
-	u32 cs_gpio;
 	/* Value to send if no TX value is supplied, usually 0x0 or 0xFFFF */
 	u16 idle_tx_val;
 	u8 pio_interrupt; /* Enable spi data irq */
diff --git a/arch/blackfin/include/asm/bfin_can.h b/arch/blackfin/include/asm/bfin_can.h
index eec0076..b1492e0 100644
--- a/arch/blackfin/include/asm/bfin_can.h
+++ b/arch/blackfin/include/asm/bfin_can.h
@@ -34,6 +34,7 @@
 };
 
 struct bfin_can_channel_regs {
+	/* data[0,2,4,6] -> data{0,1,2,3} while data[1,3,5,7] is padding */
 	u16 data[8];
 	__BFP(dlc);
 	__BFP(tsv);
@@ -83,16 +84,18 @@
 	__BFP(gif);           /* offset 0x9c */
 	__BFP(control);       /* offset 0xa0 */
 	__BFP(intr);          /* offset 0xa4 */
-	u32 __pad3[1];
+	__BFP(version);       /* offset 0xa8 */
 	__BFP(mbtd);          /* offset 0xac */
 	__BFP(ewr);           /* offset 0xb0 */
 	__BFP(esr);           /* offset 0xb4 */
-	u32 __pad4[2];
+	u32 __pad3[2];
 	__BFP(ucreg);         /* offset 0xc0 */
 	__BFP(uccnt);         /* offset 0xc4 */
 	__BFP(ucrc);          /* offset 0xc8 */
 	__BFP(uccnf);         /* offset 0xcc */
-	u32 __pad5[12];
+	u32 __pad4[1];
+	__BFP(version2);      /* offset 0xd4 */
+	u32 __pad5[10];
 
 	/*
 	 * channel(mailbox) mask and message registers
diff --git a/arch/blackfin/include/asm/bfin_ppi.h b/arch/blackfin/include/asm/bfin_ppi.h
new file mode 100644
index 0000000..0039008
--- /dev/null
+++ b/arch/blackfin/include/asm/bfin_ppi.h
@@ -0,0 +1,51 @@
+/*
+ * bfin_ppi.h - interface to Blackfin PPIs
+ *
+ * Copyright 2005-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ASM_BFIN_PPI_H__
+#define __ASM_BFIN_PPI_H__
+
+#include <linux/types.h>
+
+/*
+ * All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits.  So use a helper macro to streamline this.
+ */
+#define __BFP(m) u16 m; u16 __pad_##m
+
+/*
+ * bfin ppi registers layout
+ */
+struct bfin_ppi_regs {
+	__BFP(control);
+	__BFP(status);
+	__BFP(count);
+	__BFP(delay);
+	__BFP(frame);
+};
+
+/*
+ * bfin eppi registers layout
+ */
+struct bfin_eppi_regs {
+	__BFP(status);
+	__BFP(hcount);
+	__BFP(hdelay);
+	__BFP(vcount);
+	__BFP(vdelay);
+	__BFP(frame);
+	__BFP(line);
+	__BFP(clkdiv);
+	u32 control;
+	u32 fs1w_hbl;
+	u32 fs1p_avpl;
+	u32 fs2w_lvb;
+	u32 fs2p_lavf;
+	u32 clip;
+};
+
+#endif
diff --git a/arch/blackfin/include/asm/cachectl.h b/arch/blackfin/include/asm/cachectl.h
new file mode 100644
index 0000000..03255df
--- /dev/null
+++ b/arch/blackfin/include/asm/cachectl.h
@@ -0,0 +1,20 @@
+/*
+ * based on the mips/cachectl.h
+ *
+ * Copyright 2010 Analog Devices Inc.
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef	_ASM_CACHECTL
+#define	_ASM_CACHECTL
+
+/*
+ * Options for cacheflush system call
+ */
+#define	ICACHE	(1<<0)		/* flush instruction cache        */
+#define	DCACHE	(1<<1)		/* writeback and flush data cache */
+#define	BCACHE	(ICACHE|DCACHE)	/* flush both caches              */
+
+#endif	/* _ASM_CACHECTL */
diff --git a/arch/blackfin/include/asm/cdef_LPBlackfin.h b/arch/blackfin/include/asm/cdef_LPBlackfin.h
index 6c39d94..a1f6817 100644
--- a/arch/blackfin/include/asm/cdef_LPBlackfin.h
+++ b/arch/blackfin/include/asm/cdef_LPBlackfin.h
@@ -172,16 +172,19 @@
 #define bfin_write_ICPLB_DATA14(val)         bfin_write32(ICPLB_DATA14,val)
 #define bfin_read_ICPLB_DATA15()             bfin_read32(ICPLB_DATA15)
 #define bfin_write_ICPLB_DATA15(val)         bfin_write32(ICPLB_DATA15,val)
-#define bfin_read_ITEST_COMMAND()            bfin_read32(ITEST_COMMAND)
 #define bfin_write_ITEST_COMMAND(val)        bfin_write32(ITEST_COMMAND,val)
 #if 0
 #define ITEST_INDEX            0xFFE01304   /* Instruction Test Index Register */
 #endif
-#define bfin_read_ITEST_DATA0()              bfin_read32(ITEST_DATA0)
 #define bfin_write_ITEST_DATA0(val)          bfin_write32(ITEST_DATA0,val)
-#define bfin_read_ITEST_DATA1()              bfin_read32(ITEST_DATA1)
 #define bfin_write_ITEST_DATA1(val)          bfin_write32(ITEST_DATA1,val)
 
+#if ANOMALY_05000481
+#define bfin_read_ITEST_COMMAND()            bfin_read32(ITEST_COMMAND)
+#define bfin_read_ITEST_DATA0()              bfin_read32(ITEST_DATA0)
+#define bfin_read_ITEST_DATA1()              bfin_read32(ITEST_DATA1)
+#endif
+
 /* Event/Interrupt Registers*/
 
 #define bfin_read_EVT0()                     bfin_read32(EVT0)
diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h
index d3b40449..40f94a7 100644
--- a/arch/blackfin/include/asm/ipipe.h
+++ b/arch/blackfin/include/asm/ipipe.h
@@ -49,7 +49,7 @@
 #define prepare_arch_switch(next)		\
 do {						\
 	ipipe_schedule_notify(current, next);	\
-	local_irq_disable_hw();			\
+	hard_local_irq_disable();			\
 } while (0)
 
 #define task_hijacked(p)						\
@@ -57,7 +57,7 @@
 		int __x__ = __ipipe_root_domain_p;			\
 		__clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \
 		if (__x__)						\
-			local_irq_enable_hw();				\
+			hard_local_irq_enable();				\
 		!__x__;							\
 	})
 
@@ -167,7 +167,7 @@
 #define __ipipe_run_isr(ipd, irq)					\
 	do {								\
 		if (!__ipipe_pipeline_head_p(ipd))			\
-			local_irq_enable_hw();				\
+			hard_local_irq_enable();				\
 		if (ipd == ipipe_root_domain) {				\
 			if (unlikely(ipipe_virtual_irq_p(irq))) {	\
 				irq_enter();				\
@@ -183,7 +183,7 @@
 			__ipipe_run_irqtail();				\
 			__set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
 		}							\
-		local_irq_disable_hw();					\
+		hard_local_irq_disable();					\
 	} while (0)
 
 #define __ipipe_syscall_watched_p(p, sc)	\
diff --git a/arch/blackfin/include/asm/irqflags.h b/arch/blackfin/include/asm/irqflags.h
index 813a1af..41c4d70 100644
--- a/arch/blackfin/include/asm/irqflags.h
+++ b/arch/blackfin/include/asm/irqflags.h
@@ -8,6 +8,8 @@
 #ifndef __ASM_BFIN_IRQFLAGS_H__
 #define __ASM_BFIN_IRQFLAGS_H__
 
+#include <mach/blackfin.h>
+
 #ifdef CONFIG_SMP
 # include <asm/pda.h>
 # include <asm/processor.h>
@@ -31,54 +33,108 @@
 	return flags;
 }
 
-#ifdef CONFIG_IPIPE
-
-#include <linux/compiler.h>
-#include <linux/ipipe_base.h>
-#include <linux/ipipe_trace.h>
-
 #ifdef CONFIG_DEBUG_HWERR
 # define bfin_no_irqs 0x3f
 #else
 # define bfin_no_irqs 0x1f
 #endif
 
-#define raw_local_irq_disable()				\
-	do {						\
-		ipipe_check_context(ipipe_root_domain);	\
-		__ipipe_stall_root();			\
-		barrier();				\
-	} while (0)
+/*****************************************************************************/
+/*
+ * Hard, untraced CPU interrupt flag manipulation and access.
+ */
+static inline void __hard_local_irq_disable(void)
+{
+	bfin_cli();
+}
 
-#define raw_local_irq_enable()				\
-	do {						\
-		barrier();				\
-		ipipe_check_context(ipipe_root_domain);	\
-		__ipipe_unstall_root();			\
-	} while (0)
+static inline void __hard_local_irq_enable(void)
+{
+	bfin_sti(bfin_irq_flags);
+}
 
-#define raw_local_save_flags_ptr(x)					\
-	do {								\
-		*(x) = __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags; \
-	} while (0)
+static inline unsigned long hard_local_save_flags(void)
+{
+	return bfin_read_IMASK();
+}
 
-#define raw_local_save_flags(x)		raw_local_save_flags_ptr(&(x))
+static inline unsigned long __hard_local_irq_save(void)
+{
+	unsigned long flags;
+	flags = bfin_cli();
+#ifdef CONFIG_DEBUG_HWERR
+	bfin_sti(0x3f);
+#endif
+	return flags;
+}
 
-#define raw_irqs_disabled_flags(x)	((x) == bfin_no_irqs)
+static inline int hard_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags & ~0x3f) == 0;
+}
 
-#define raw_local_irq_save_ptr(x)					\
-	do {								\
-		*(x) = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags; \
-		barrier();						\
-	} while (0)
+static inline int hard_irqs_disabled(void)
+{
+	unsigned long flags = hard_local_save_flags();
+	return hard_irqs_disabled_flags(flags);
+}
 
-#define raw_local_irq_save(x)				\
-	do {						\
-		ipipe_check_context(ipipe_root_domain);	\
-		raw_local_irq_save_ptr(&(x));		\
-	} while (0)
+static inline void __hard_local_irq_restore(unsigned long flags)
+{
+	if (!hard_irqs_disabled_flags(flags))
+		__hard_local_irq_enable();
+}
 
-static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real)
+/*****************************************************************************/
+/*
+ * Interrupt pipe handling.
+ */
+#ifdef CONFIG_IPIPE
+
+#include <linux/compiler.h>
+#include <linux/ipipe_base.h>
+#include <linux/ipipe_trace.h>
+
+/*
+ * Interrupt pipe interface to linux/irqflags.h.
+ */
+static inline void arch_local_irq_disable(void)
+{
+	ipipe_check_context(ipipe_root_domain);
+	__ipipe_stall_root();
+	barrier();
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	barrier();
+	ipipe_check_context(ipipe_root_domain);
+	__ipipe_unstall_root();
+}
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags;
+}
+
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+	return flags == bfin_no_irqs;
+}
+
+static inline void arch_local_irq_save_ptr(unsigned long *_flags)
+{
+	x = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
+	barrier();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	ipipe_check_context(ipipe_root_domain);
+	return __hard_local_irq_save();
+}
+
+static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
 {
 	/*
 	 * Merge virtual and real interrupt mask bits into a single
@@ -87,130 +143,79 @@
 	return (real & ~(1 << 31)) | ((virt != 0) << 31);
 }
 
-static inline int raw_demangle_irq_bits(unsigned long *x)
+static inline int arch_demangle_irq_bits(unsigned long *x)
 {
 	int virt = (*x & (1 << 31)) != 0;
 	*x &= ~(1L << 31);
 	return virt;
 }
 
-static inline void local_irq_disable_hw_notrace(void)
-{
-	bfin_cli();
-}
-
-static inline void local_irq_enable_hw_notrace(void)
-{
-	bfin_sti(bfin_irq_flags);
-}
-
-#define local_save_flags_hw(flags)			\
-	do {						\
-		(flags) = bfin_read_IMASK();		\
-	} while (0)
-
-#define irqs_disabled_flags_hw(flags) (((flags) & ~0x3f) == 0)
-
-#define irqs_disabled_hw()			\
-	({					\
-	unsigned long flags;			\
-	local_save_flags_hw(flags);		\
-	irqs_disabled_flags_hw(flags);		\
-	})
-
-static inline void local_irq_save_ptr_hw(unsigned long *flags)
-{
-	*flags = bfin_cli();
-#ifdef CONFIG_DEBUG_HWERR
-	bfin_sti(0x3f);
-#endif
-}
-
-#define local_irq_save_hw_notrace(flags)		\
-	do {						\
-		local_irq_save_ptr_hw(&(flags));	\
-	} while (0)
-
-static inline void local_irq_restore_hw_notrace(unsigned long flags)
-{
-	if (!irqs_disabled_flags_hw(flags))
-		local_irq_enable_hw_notrace();
-}
-
+/*
+ * Interface to various arch routines that may be traced.
+ */
 #ifdef CONFIG_IPIPE_TRACE_IRQSOFF
-# define local_irq_disable_hw()				\
-	do {						\
-		if (!irqs_disabled_hw()) {		\
-			local_irq_disable_hw_notrace();	\
-			ipipe_trace_begin(0x80000000);	\
-		}					\
-	} while (0)
-# define local_irq_enable_hw()				\
-	do {						\
-		if (irqs_disabled_hw()) {		\
-			ipipe_trace_end(0x80000000);	\
-			local_irq_enable_hw_notrace();	\
-		}					\
-	} while (0)
-# define local_irq_save_hw(flags)			\
-	do {						\
-		local_save_flags_hw(flags);		\
-		if (!irqs_disabled_flags_hw(flags)) {	\
-			local_irq_disable_hw_notrace();	\
-			ipipe_trace_begin(0x80000001);	\
-		}					\
-	} while (0)
-# define local_irq_restore_hw(flags)			\
-	do {						\
-		if (!irqs_disabled_flags_hw(flags)) {	\
-			ipipe_trace_end(0x80000001);	\
-			local_irq_enable_hw_notrace();	\
-		}					\
-	} while (0)
+static inline void hard_local_irq_disable(void)
+{
+	if (!hard_irqs_disabled()) {
+		__hard_local_irq_disable();
+		ipipe_trace_begin(0x80000000);
+	}
+}
+
+static inline void hard_local_irq_enable(void)
+{
+	if (hard_irqs_disabled()) {
+		ipipe_trace_end(0x80000000);
+		__hard_local_irq_enable();
+	}
+}
+
+static inline unsigned long hard_local_irq_save(void)
+{
+	unsigned long flags = hard_local_save_flags();
+	if (!hard_irqs_disabled_flags(flags)) {
+		__hard_local_irq_disable();
+		ipipe_trace_begin(0x80000001);
+	}
+	return flags;
+}
+
+static inline void hard_local_irq_restore(unsigned long flags)
+{
+	if (!hard_irqs_disabled_flags(flags)) {
+		ipipe_trace_end(0x80000001);
+		__hard_local_irq_enable();
+	}
+}
+
 #else /* !CONFIG_IPIPE_TRACE_IRQSOFF */
-# define local_irq_disable_hw()		local_irq_disable_hw_notrace()
-# define local_irq_enable_hw()		local_irq_enable_hw_notrace()
-# define local_irq_save_hw(flags)	local_irq_save_hw_notrace(flags)
-# define local_irq_restore_hw(flags)	local_irq_restore_hw_notrace(flags)
+# define hard_local_irq_disable()	__hard_local_irq_disable()
+# define hard_local_irq_enable()	__hard_local_irq_enable()
+# define hard_local_irq_save()		__hard_local_irq_save()
+# define hard_local_irq_restore(flags)	__hard_local_irq_restore(flags)
 #endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */
 
 #else /* CONFIG_IPIPE */
 
-static inline void raw_local_irq_disable(void)
-{
-	bfin_cli();
-}
-static inline void raw_local_irq_enable(void)
-{
-	bfin_sti(bfin_irq_flags);
-}
+/*
+ * Direct interface to linux/irqflags.h.
+ */
+#define arch_local_save_flags()		hard_local_save_flags()
+#define arch_local_irq_save(flags)	__hard_local_irq_save()
+#define arch_local_irq_restore(flags)	__hard_local_irq_restore(flags)
+#define arch_local_irq_enable()		__hard_local_irq_enable()
+#define arch_local_irq_disable()	__hard_local_irq_disable()
+#define arch_irqs_disabled_flags(flags)	hard_irqs_disabled_flags(flags)
+#define arch_irqs_disabled()		hard_irqs_disabled()
 
-#define raw_local_save_flags(flags) do { (flags) = bfin_read_IMASK(); } while (0)
+/*
+ * Interface to various arch routines that may be traced.
+ */
+#define hard_local_irq_save()		__hard_local_irq_save()
+#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 raw_irqs_disabled_flags(flags) (((flags) & ~0x3f) == 0)
-
-static inline unsigned long __raw_local_irq_save(void)
-{
-	unsigned long flags = bfin_cli();
-#ifdef CONFIG_DEBUG_HWERR
-	bfin_sti(0x3f);
-#endif
-	return flags;
-}
-#define raw_local_irq_save(flags) do { (flags) = __raw_local_irq_save(); } while (0)
-
-#define local_irq_save_hw(flags)	raw_local_irq_save(flags)
-#define local_irq_restore_hw(flags)	raw_local_irq_restore(flags)
-#define local_irq_enable_hw()		raw_local_irq_enable()
-#define local_irq_disable_hw()		raw_local_irq_disable()
-#define irqs_disabled_hw()		irqs_disabled()
 
 #endif /* !CONFIG_IPIPE */
-
-static inline void raw_local_irq_restore(unsigned long flags)
-{
-	if (!raw_irqs_disabled_flags(flags))
-		raw_local_irq_enable();
-}
-
 #endif
diff --git a/arch/blackfin/include/asm/mmu_context.h b/arch/blackfin/include/asm/mmu_context.h
index e1a9b46..3828c70 100644
--- a/arch/blackfin/include/asm/mmu_context.h
+++ b/arch/blackfin/include/asm/mmu_context.h
@@ -97,8 +97,8 @@
 }
 
 #ifdef CONFIG_IPIPE
-#define lock_mm_switch(flags)	local_irq_save_hw_cond(flags)
-#define unlock_mm_switch(flags)	local_irq_restore_hw_cond(flags)
+#define lock_mm_switch(flags)	flags = hard_local_irq_save_cond()
+#define unlock_mm_switch(flags)	hard_local_irq_restore_cond(flags)
 #else
 #define lock_mm_switch(flags)	do { (void)(flags); } while (0)
 #define unlock_mm_switch(flags)	do { (void)(flags); } while (0)
@@ -205,9 +205,9 @@
 }
 
 #define ipipe_mm_switch_protect(flags)		\
-	local_irq_save_hw_cond(flags)
+	flags = hard_local_irq_save_cond()
 
 #define ipipe_mm_switch_unprotect(flags)	\
-	local_irq_restore_hw_cond(flags)
+	hard_local_irq_restore_cond(flags)
 
 #endif
diff --git a/arch/blackfin/include/asm/ptrace.h b/arch/blackfin/include/asm/ptrace.h
index aaa1c6c..832d7c0 100644
--- a/arch/blackfin/include/asm/ptrace.h
+++ b/arch/blackfin/include/asm/ptrace.h
@@ -113,6 +113,9 @@
 /* common code demands this function */
 #define ptrace_disable(child) user_disable_single_step(child)
 
+extern int is_user_addr_valid(struct task_struct *child,
+			      unsigned long start, unsigned long len);
+
 /*
  * Get the address of the live pt_regs for the specified task.
  * These are saved onto the top kernel stack when the process
diff --git a/arch/blackfin/include/asm/serial.h b/arch/blackfin/include/asm/serial.h
index 94a4a12..a0cb0caf 100644
--- a/arch/blackfin/include/asm/serial.h
+++ b/arch/blackfin/include/asm/serial.h
@@ -1,2 +1 @@
 #include <asm-generic/serial.h>
-#define SERIAL_EXTRA_IRQ_FLAGS IRQF_TRIGGER_HIGH
diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h
index dde19b1..19e2c7c 100644
--- a/arch/blackfin/include/asm/system.h
+++ b/arch/blackfin/include/asm/system.h
@@ -117,7 +117,7 @@
 	unsigned long tmp = 0;
 	unsigned long flags;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	switch (size) {
 	case 1:
@@ -139,7 +139,7 @@
 			 : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
 		break;
 	}
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 	return tmp;
 }
 
diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h
index 14fcd25..928ae97 100644
--- a/arch/blackfin/include/asm/unistd.h
+++ b/arch/blackfin/include/asm/unistd.h
@@ -392,8 +392,9 @@
 #define __NR_fanotify_init	371
 #define __NR_fanotify_mark	372
 #define __NR_prlimit64		373
+#define __NR_cacheflush		374
 
-#define __NR_syscall		374
+#define __NR_syscall		375
 #define NR_syscalls		__NR_syscall
 
 /* Old optional stuff no one actually uses */
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index dc07ed0..170cf90 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -1,7 +1,7 @@
 /*
  * GPIO Abstraction Layer
  *
- * Copyright 2006-2009 Analog Devices Inc.
+ * Copyright 2006-2010 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later
  */
@@ -215,82 +215,91 @@
 }
 
 #ifdef BF537_FAMILY
-static struct {
-	unsigned short res;
-	unsigned short offset;
-} port_mux_lut[] = {
-	{.res = P_PPI0_D13, .offset = 11},
-	{.res = P_PPI0_D14, .offset = 11},
-	{.res = P_PPI0_D15, .offset = 11},
-	{.res = P_SPORT1_TFS, .offset = 11},
-	{.res = P_SPORT1_TSCLK, .offset = 11},
-	{.res = P_SPORT1_DTPRI, .offset = 11},
-	{.res = P_PPI0_D10, .offset = 10},
-	{.res = P_PPI0_D11, .offset = 10},
-	{.res = P_PPI0_D12, .offset = 10},
-	{.res = P_SPORT1_RSCLK, .offset = 10},
-	{.res = P_SPORT1_RFS, .offset = 10},
-	{.res = P_SPORT1_DRPRI, .offset = 10},
-	{.res = P_PPI0_D8, .offset = 9},
-	{.res = P_PPI0_D9, .offset = 9},
-	{.res = P_SPORT1_DRSEC, .offset = 9},
-	{.res = P_SPORT1_DTSEC, .offset = 9},
-	{.res = P_TMR2, .offset = 8},
-	{.res = P_PPI0_FS3, .offset = 8},
-	{.res = P_TMR3, .offset = 7},
-	{.res = P_SPI0_SSEL4, .offset = 7},
-	{.res = P_TMR4, .offset = 6},
-	{.res = P_SPI0_SSEL5, .offset = 6},
-	{.res = P_TMR5, .offset = 5},
-	{.res = P_SPI0_SSEL6, .offset = 5},
-	{.res = P_UART1_RX, .offset = 4},
-	{.res = P_UART1_TX, .offset = 4},
-	{.res = P_TMR6, .offset = 4},
-	{.res = P_TMR7, .offset = 4},
-	{.res = P_UART0_RX, .offset = 3},
-	{.res = P_UART0_TX, .offset = 3},
-	{.res = P_DMAR0, .offset = 3},
-	{.res = P_DMAR1, .offset = 3},
-	{.res = P_SPORT0_DTSEC, .offset = 1},
-	{.res = P_SPORT0_DRSEC, .offset = 1},
-	{.res = P_CAN0_RX, .offset = 1},
-	{.res = P_CAN0_TX, .offset = 1},
-	{.res = P_SPI0_SSEL7, .offset = 1},
-	{.res = P_SPORT0_TFS, .offset = 0},
-	{.res = P_SPORT0_DTPRI, .offset = 0},
-	{.res = P_SPI0_SSEL2, .offset = 0},
-	{.res = P_SPI0_SSEL3, .offset = 0},
+static const s8 port_mux[] = {
+	[GPIO_PF0] = 3,
+	[GPIO_PF1] = 3,
+	[GPIO_PF2] = 4,
+	[GPIO_PF3] = 4,
+	[GPIO_PF4] = 5,
+	[GPIO_PF5] = 6,
+	[GPIO_PF6] = 7,
+	[GPIO_PF7] = 8,
+	[GPIO_PF8 ... GPIO_PF15] = -1,
+	[GPIO_PG0 ... GPIO_PG7] = -1,
+	[GPIO_PG8] = 9,
+	[GPIO_PG9] = 9,
+	[GPIO_PG10] = 10,
+	[GPIO_PG11] = 10,
+	[GPIO_PG12] = 10,
+	[GPIO_PG13] = 11,
+	[GPIO_PG14] = 11,
+	[GPIO_PG15] = 11,
+	[GPIO_PH0 ... GPIO_PH15] = -1,
+	[PORT_PJ0 ... PORT_PJ3] = -1,
+	[PORT_PJ4] = 1,
+	[PORT_PJ5] = 1,
+	[PORT_PJ6 ... PORT_PJ9] = -1,
+	[PORT_PJ10] = 0,
+	[PORT_PJ11] = 0,
 };
 
+static int portmux_group_check(unsigned short per)
+{
+	u16 ident = P_IDENT(per);
+	u16 function = P_FUNCT2MUX(per);
+	s8 offset = port_mux[ident];
+	u16 m, pmux, pfunc;
+
+	if (offset < 0)
+		return 0;
+
+	pmux = bfin_read_PORT_MUX();
+	for (m = 0; m < ARRAY_SIZE(port_mux); ++m) {
+		if (m == ident)
+			continue;
+		if (port_mux[m] != offset)
+			continue;
+		if (!is_reserved(peri, m, 1))
+			continue;
+
+		if (offset == 1)
+			pfunc = (pmux >> offset) & 3;
+		else
+			pfunc = (pmux >> offset) & 1;
+		if (pfunc != function) {
+			pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
+				ident, function, m, pfunc);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 static void portmux_setup(unsigned short per)
 {
-	u16 y, offset, muxreg;
+	u16 ident = P_IDENT(per);
 	u16 function = P_FUNCT2MUX(per);
+	s8 offset = port_mux[ident];
+	u16 pmux;
 
-	for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) {
-		if (port_mux_lut[y].res == per) {
+	if (offset == -1)
+		return;
 
-			/* SET PORTMUX REG */
-
-			offset = port_mux_lut[y].offset;
-			muxreg = bfin_read_PORT_MUX();
-
-			if (offset != 1)
-				muxreg &= ~(1 << offset);
-			else
-				muxreg &= ~(3 << 1);
-
-			muxreg |= (function << offset);
-			bfin_write_PORT_MUX(muxreg);
-		}
-	}
+	pmux = bfin_read_PORT_MUX();
+	if (offset != 1)
+		pmux &= ~(1 << offset);
+	else
+		pmux &= ~(3 << 1);
+	pmux |= (function << offset);
+	bfin_write_PORT_MUX(pmux);
 }
 #elif defined(CONFIG_BF54x)
 inline void portmux_setup(unsigned short per)
 {
-	u32 pmux;
 	u16 ident = P_IDENT(per);
 	u16 function = P_FUNCT2MUX(per);
+	u32 pmux;
 
 	pmux = gpio_array[gpio_bank(ident)]->port_mux;
 
@@ -302,20 +311,54 @@
 
 inline u16 get_portmux(unsigned short per)
 {
-	u32 pmux;
 	u16 ident = P_IDENT(per);
-
-	pmux = gpio_array[gpio_bank(ident)]->port_mux;
-
+	u32 pmux = gpio_array[gpio_bank(ident)]->port_mux;
 	return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
 }
+static int portmux_group_check(unsigned short per)
+{
+	return 0;
+}
 #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
+static int portmux_group_check(unsigned short per)
+{
+	u16 ident = P_IDENT(per);
+	u16 function = P_FUNCT2MUX(per);
+	u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
+	u16 pin, gpiopin, pfunc;
+
+	for (pin = 0; pin < GPIO_BANKSIZE; ++pin) {
+		if (offset != pmux_offset[gpio_bank(ident)][pin])
+			continue;
+
+		gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin;
+		if (gpiopin == ident)
+			continue;
+		if (!is_reserved(peri, gpiopin, 1))
+			continue;
+
+		pfunc = *port_mux[gpio_bank(ident)];
+		pfunc = (pfunc >> offset) & 3;
+		if (pfunc != function) {
+			pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
+				ident, function, gpiopin, pfunc);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 inline void portmux_setup(unsigned short per)
 {
-	u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per);
+	u16 ident = P_IDENT(per);
+	u16 function = P_FUNCT2MUX(per);
 	u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
+	u16 pmux;
 
 	pmux = *port_mux[gpio_bank(ident)];
+	if  (((pmux >> offset) & 3) == function)
+		return;
 	pmux &= ~(3 << offset);
 	pmux |= (function & 3) << offset;
 	*port_mux[gpio_bank(ident)] = pmux;
@@ -323,6 +366,10 @@
 }
 #else
 # define portmux_setup(...)  do { } while (0)
+static int portmux_group_check(unsigned short per)
+{
+	return 0;
+}
 #endif
 
 #ifndef CONFIG_BF54x
@@ -349,13 +396,13 @@
 void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
 { \
 	unsigned long flags; \
-	local_irq_save_hw(flags); \
+	flags = hard_local_irq_save(); \
 	if (arg) \
 		gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
 	else \
 		gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
 	AWA_DUMMY_READ(name); \
-	local_irq_restore_hw(flags); \
+	hard_local_irq_restore(flags); \
 } \
 EXPORT_SYMBOL(set_gpio_ ## name);
 
@@ -371,14 +418,14 @@
 { \
 	unsigned long flags; \
 	if (ANOMALY_05000311 || ANOMALY_05000323) \
-		local_irq_save_hw(flags); \
+		flags = hard_local_irq_save(); \
 	if (arg) \
 		gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
 	else \
 		gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
 	if (ANOMALY_05000311 || ANOMALY_05000323) { \
 		AWA_DUMMY_READ(name); \
-		local_irq_restore_hw(flags); \
+		hard_local_irq_restore(flags); \
 	} \
 } \
 EXPORT_SYMBOL(set_gpio_ ## name);
@@ -391,11 +438,11 @@
 {
 	unsigned long flags;
 	if (ANOMALY_05000311 || ANOMALY_05000323)
-		local_irq_save_hw(flags);
+		flags = hard_local_irq_save();
 	gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
 	if (ANOMALY_05000311 || ANOMALY_05000323) {
 		AWA_DUMMY_READ(toggle);
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 	}
 }
 EXPORT_SYMBOL(set_gpio_toggle);
@@ -408,11 +455,11 @@
 { \
 	unsigned long flags; \
 	if (ANOMALY_05000311 || ANOMALY_05000323) \
-		local_irq_save_hw(flags); \
+		flags = hard_local_irq_save(); \
 	gpio_array[gpio_bank(gpio)]->name = arg; \
 	if (ANOMALY_05000311 || ANOMALY_05000323) { \
 		AWA_DUMMY_READ(name); \
-		local_irq_restore_hw(flags); \
+		hard_local_irq_restore(flags); \
 	} \
 } \
 EXPORT_SYMBOL(set_gpiop_ ## name);
@@ -433,11 +480,11 @@
 	unsigned long flags; \
 	unsigned short ret; \
 	if (ANOMALY_05000311 || ANOMALY_05000323) \
-		local_irq_save_hw(flags); \
+		flags = hard_local_irq_save(); \
 	ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
 	if (ANOMALY_05000311 || ANOMALY_05000323) { \
 		AWA_DUMMY_READ(name); \
-		local_irq_restore_hw(flags); \
+		hard_local_irq_restore(flags); \
 	} \
 	return ret; \
 } \
@@ -460,11 +507,11 @@
 	unsigned long flags; \
 	unsigned short ret; \
 	if (ANOMALY_05000311 || ANOMALY_05000323) \
-		local_irq_save_hw(flags); \
+		flags = hard_local_irq_save(); \
 	ret = (gpio_array[gpio_bank(gpio)]->name); \
 	if (ANOMALY_05000311 || ANOMALY_05000323) { \
 		AWA_DUMMY_READ(name); \
-		local_irq_restore_hw(flags); \
+		hard_local_irq_restore(flags); \
 	} \
 	return ret; \
 } \
@@ -525,14 +572,14 @@
 	if (check_gpio(gpio) < 0)
 		return -EINVAL;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	if (ctrl)
 		reserve(wakeup, gpio);
 	else
 		unreserve(wakeup, gpio);
 
 	set_gpio_maskb(gpio, ctrl);
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 
 	return 0;
 }
@@ -690,7 +737,7 @@
 
 	BUG_ON(ident >= MAX_RESOURCES);
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	/* If a pin can be muxed as either GPIO or peripheral, make
 	 * sure it is not already a GPIO pin when we request it.
@@ -701,7 +748,7 @@
 		printk(KERN_ERR
 		       "%s: Peripheral %d is already reserved as GPIO by %s !\n",
 		       __func__, ident, get_label(ident));
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return -EBUSY;
 	}
 
@@ -730,18 +777,22 @@
 			printk(KERN_ERR
 			       "%s: Peripheral %d function %d is already reserved by %s !\n",
 			       __func__, ident, P_FUNCT2MUX(per), get_label(ident));
-			local_irq_restore_hw(flags);
+			hard_local_irq_restore(flags);
 			return -EBUSY;
 		}
 	}
 
+	if (unlikely(portmux_group_check(per))) {
+		hard_local_irq_restore(flags);
+		return -EBUSY;
+	}
  anyway:
 	reserve(peri, ident);
 
 	portmux_setup(per);
 	port_setup(ident, PERIPHERAL_USAGE);
 
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 	set_label(ident, label);
 
 	return 0;
@@ -780,10 +831,10 @@
 	if (!(per & P_DEFINED))
 		return;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	if (unlikely(!is_reserved(peri, ident, 0))) {
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return;
 	}
 
@@ -794,7 +845,7 @@
 
 	set_label(ident, "free");
 
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(peripheral_free);
 
@@ -828,7 +879,7 @@
 	if (check_gpio(gpio) < 0)
 		return -EINVAL;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	/*
 	 * Allow that the identical GPIO can
@@ -837,7 +888,7 @@
 	 */
 
 	if (cmp_label(gpio, label) == 0) {
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return 0;
 	}
 
@@ -846,7 +897,7 @@
 			dump_stack();
 		printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
 		       gpio, get_label(gpio));
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return -EBUSY;
 	}
 	if (unlikely(is_reserved(peri, gpio, 1))) {
@@ -855,7 +906,7 @@
 		printk(KERN_ERR
 		       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
 		       gpio, get_label(gpio));
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return -EBUSY;
 	}
 	if (unlikely(is_reserved(gpio_irq, gpio, 1))) {
@@ -871,7 +922,7 @@
 	reserve(gpio, gpio);
 	set_label(gpio, label);
 
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 
 	port_setup(gpio, GPIO_USAGE);
 
@@ -888,13 +939,13 @@
 
 	might_sleep();
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	if (unlikely(!is_reserved(gpio, gpio, 0))) {
 		if (system_state == SYSTEM_BOOTING)
 			dump_stack();
 		gpio_error(gpio);
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return;
 	}
 
@@ -902,7 +953,7 @@
 
 	set_label(gpio, "free");
 
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(bfin_gpio_free);
 
@@ -913,7 +964,7 @@
 {
 	unsigned long flags;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	/*
 	 * Allow that the identical GPIO can
@@ -922,19 +973,19 @@
 	 */
 
 	if (cmp_label(gpio, label) == 0) {
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return 0;
 	}
 
 	if (unlikely(is_reserved(special_gpio, gpio, 1))) {
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
 		       gpio, get_label(gpio));
 
 		return -EBUSY;
 	}
 	if (unlikely(is_reserved(peri, gpio, 1))) {
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		printk(KERN_ERR
 		       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
 		       gpio, get_label(gpio));
@@ -946,7 +997,7 @@
 	reserve(peri, gpio);
 
 	set_label(gpio, label);
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 	port_setup(gpio, GPIO_USAGE);
 
 	return 0;
@@ -959,18 +1010,18 @@
 
 	might_sleep();
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
 		gpio_error(gpio);
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return;
 	}
 
 	unreserve(special_gpio, gpio);
 	unreserve(peri, gpio);
 	set_label(gpio, "free");
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(bfin_special_gpio_free);
 #endif
@@ -983,7 +1034,7 @@
 	if (check_gpio(gpio) < 0)
 		return -EINVAL;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	if (unlikely(is_reserved(peri, gpio, 1))) {
 		if (system_state == SYSTEM_BOOTING)
@@ -991,7 +1042,7 @@
 		printk(KERN_ERR
 		       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
 		       gpio, get_label(gpio));
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return -EBUSY;
 	}
 	if (unlikely(is_reserved(gpio, gpio, 1)))
@@ -1002,7 +1053,7 @@
 	reserve(gpio_irq, gpio);
 	set_label(gpio, label);
 
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 
 	port_setup(gpio, GPIO_USAGE);
 
@@ -1016,13 +1067,13 @@
 	if (check_gpio(gpio) < 0)
 		return;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	if (unlikely(!is_reserved(gpio_irq, gpio, 0))) {
 		if (system_state == SYSTEM_BOOTING)
 			dump_stack();
 		gpio_error(gpio);
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return;
 	}
 
@@ -1030,7 +1081,7 @@
 
 	set_label(gpio, "free");
 
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 
 static inline void __bfin_gpio_direction_input(unsigned gpio)
@@ -1052,10 +1103,10 @@
 		return -EINVAL;
 	}
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	__bfin_gpio_direction_input(gpio);
 	AWA_DUMMY_READ(inen);
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 
 	return 0;
 }
@@ -1070,9 +1121,9 @@
 	port_setup(gpio, GPIO_USAGE);
 
 #ifdef CONFIG_BF54x
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	__bfin_gpio_direction_input(gpio);
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 #endif
 }
 
@@ -1094,7 +1145,7 @@
 		return -EINVAL;
 	}
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
 	gpio_set_value(gpio, value);
@@ -1105,7 +1156,7 @@
 #endif
 
 	AWA_DUMMY_READ(dir);
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 
 	return 0;
 }
@@ -1120,11 +1171,11 @@
 
 	if (unlikely(get_gpio_edge(gpio))) {
 		int ret;
-		local_irq_save_hw(flags);
+		flags = hard_local_irq_save();
 		set_gpio_edge(gpio, 0);
 		ret = get_gpio_data(gpio);
 		set_gpio_edge(gpio, 1);
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return ret;
 	} else
 		return get_gpio_data(gpio);
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
index 87b25b1..8de9229 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
@@ -318,7 +318,7 @@
 
 	nr_cplb_flush[cpu]++;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	_disable_icplb();
 	for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
 		icplb_tbl[cpu][i].data = 0;
@@ -332,7 +332,7 @@
 		bfin_write32(DCPLB_DATA0 + i * 4, 0);
 	}
 	_enable_dcplb();
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 
 }
 
@@ -348,7 +348,7 @@
 		return;
 	}
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	current_rwx_mask[cpu] = masks;
 
 	if (L2_LENGTH && addr >= L2_START && addr < L2_START + L2_LENGTH) {
@@ -373,5 +373,5 @@
 		addr += PAGE_SIZE;
 	}
 	_enable_dcplb();
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c
index 1a496cd..3b1da4a 100644
--- a/arch/blackfin/kernel/ipipe.c
+++ b/arch/blackfin/kernel/ipipe.c
@@ -219,10 +219,10 @@
 
 	ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs);
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	if (!__ipipe_root_domain_p) {
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		return 1;
 	}
 
@@ -230,7 +230,7 @@
 	if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0)
 		__ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
 
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 
 	return -ret;
 }
@@ -239,14 +239,14 @@
 {
 	unsigned long flags;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	return flags;
 }
 
 void ipipe_critical_exit(unsigned long flags)
 {
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 
 static void __ipipe_no_irqtail(void)
@@ -279,9 +279,9 @@
 		return -EINVAL;
 #endif
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	__ipipe_handle_irq(irq, NULL);
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 
 	return 1;
 }
@@ -293,7 +293,7 @@
 
 	BUG_ON(irqs_disabled());
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	if (irq_tail_hook)
 		irq_tail_hook();
@@ -303,7 +303,7 @@
 	if (ipipe_root_cpudom_var(irqpend_himask) != 0)
 		__ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
 
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 
 void ___ipipe_sync_pipeline(unsigned long syncmask)
@@ -344,10 +344,10 @@
 {
 	unsigned long *p, flags;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	p = &__ipipe_root_status;
 	__set_bit(IPIPE_STALL_FLAG, p);
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(__ipipe_stall_root);
 
@@ -356,10 +356,10 @@
 	unsigned long *p, flags;
 	int x;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	p = &__ipipe_root_status;
 	x = __test_and_set_bit(IPIPE_STALL_FLAG, p);
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 
 	return x;
 }
@@ -371,10 +371,10 @@
 	unsigned long flags;
 	int x;
 
-	local_irq_save_hw_smp(flags);
+	flags = hard_local_irq_save_smp();
 	p = &__ipipe_root_status;
 	x = test_bit(IPIPE_STALL_FLAG, p);
-	local_irq_restore_hw_smp(flags);
+	hard_local_irq_restore_smp(flags);
 
 	return x;
 }
@@ -384,10 +384,10 @@
 {
 	unsigned long *p, flags;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	p = &__ipipe_root_status;
 	__set_bit(IPIPE_SYNCDEFER_FLAG, p);
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(__ipipe_lock_root);
 
@@ -395,9 +395,9 @@
 {
 	unsigned long *p, flags;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	p = &__ipipe_root_status;
 	__clear_bit(IPIPE_SYNCDEFER_FLAG, p);
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(__ipipe_unlock_root);
diff --git a/arch/blackfin/kernel/kgdb_test.c b/arch/blackfin/kernel/kgdb_test.c
index 9a4b075..08c0236 100644
--- a/arch/blackfin/kernel/kgdb_test.c
+++ b/arch/blackfin/kernel/kgdb_test.c
@@ -88,6 +88,7 @@
 	.owner = THIS_MODULE,
 	.read  = kgdb_test_proc_read,
 	.write = kgdb_test_proc_write,
+	.llseek = noop_llseek,
 };
 
 static int __init kgdbtest_init(void)
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 01f98cb..cd0c090 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -65,11 +65,11 @@
 #ifdef CONFIG_IPIPE
 	ipipe_suspend_domain();
 #endif
-	local_irq_disable_hw();
+	hard_local_irq_disable();
 	if (!need_resched())
 		idle_with_irq_disabled();
 
-	local_irq_enable_hw();
+	hard_local_irq_enable();
 }
 
 /*
@@ -493,6 +493,11 @@
 		return 1;
 #endif
 
+#ifndef CONFIG_EXCEPTION_L1_SCRATCH
+	if (in_mem_const(addr, size, (unsigned long)l1_stack_base, l1_stack_len))
+		return 1;
+#endif
+
 	aret = in_async(addr, size);
 	if (aret < 2)
 		return aret;
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 6ec7768..b358393 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -27,6 +27,7 @@
 #include <asm/fixed_code.h>
 #include <asm/cacheflush.h>
 #include <asm/mem_map.h>
+#include <asm/mmu_context.h>
 
 /*
  * does not yet catch signals sent when the child dies.
@@ -113,8 +114,8 @@
 /*
  * check that an address falls within the bounds of the target process's memory mappings
  */
-static inline int is_user_addr_valid(struct task_struct *child,
-				     unsigned long start, unsigned long len)
+int
+is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len)
 {
 	struct vm_area_struct *vma;
 	struct sram_list_struct *sraml;
@@ -135,6 +136,13 @@
 	if (start >= FIXED_CODE_START && start + len < FIXED_CODE_END)
 		return 0;
 
+#ifdef CONFIG_APP_STACK_L1
+	if (child->mm->context.l1_stack_save)
+		if (start >= (unsigned long)l1_stack_base &&
+			start + len < (unsigned long)l1_stack_base + l1_stack_len)
+			return 0;
+#endif
+
 	return -EIO;
 }
 
diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c
index bdc1e2f..89448ed 100644
--- a/arch/blackfin/kernel/sys_bfin.c
+++ b/arch/blackfin/kernel/sys_bfin.c
@@ -21,6 +21,8 @@
 
 #include <asm/cacheflush.h>
 #include <asm/dma.h>
+#include <asm/cachectl.h>
+#include <asm/ptrace.h>
 
 asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags)
 {
@@ -70,3 +72,16 @@
 
 	return ret;
 }
+
+SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, len, int, op)
+{
+	if (is_user_addr_valid(current, addr, len) != 0)
+		return -EINVAL;
+
+	if (op & DCACHE)
+		blackfin_dcache_flush_range(addr, addr + len);
+	if (op & ICACHE)
+		blackfin_icache_flush_range(addr, addr + len);
+
+	return 0;
+}
diff --git a/arch/blackfin/kernel/trace.c b/arch/blackfin/kernel/trace.c
index 59fcdf6..05b5508 100644
--- a/arch/blackfin/kernel/trace.c
+++ b/arch/blackfin/kernel/trace.c
@@ -15,6 +15,7 @@
 #include <linux/kallsyms.h>
 #include <linux/err.h>
 #include <linux/fs.h>
+#include <linux/irq.h>
 #include <asm/dma.h>
 #include <asm/trace.h>
 #include <asm/fixed_code.h>
diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c
index 44d6d52..f95e609 100644
--- a/arch/blackfin/mach-bf518/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf518/boards/ezbrd.c
@@ -312,7 +312,7 @@
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
 /* SPI (0) */
 static struct bfin5xx_spi_master bfin_spi0_info = {
-	.num_chipselect = 5,
+	.num_chipselect = 6,
 	.enable_dma = 1,  /* master has the ability to do dma transfer */
 	.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
 };
@@ -347,7 +347,7 @@
 
 /* SPI (1) */
 static struct bfin5xx_spi_master bfin_spi1_info = {
-	.num_chipselect = 5,
+	.num_chipselect = 6,
 	.enable_dma = 1,  /* master has the ability to do dma transfer */
 	.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
 };
@@ -525,6 +525,14 @@
 #endif
 #endif
 
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s = {
+	.name = "bfin-i2s",
+	.id = CONFIG_SND_BF5XX_SPORT_NUM,
+	/* TODO: add platform data here */
+};
+#endif
+
 #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
 static struct resource bfin_twi0_resource[] = {
 	[0] = {
@@ -559,6 +567,11 @@
 		.irq = IRQ_PF8,
 	},
 #endif
+#if defined(CONFIG_SND_SOC_SSM2602) || defined(CONFIG_SND_SOC_SSM2602_MODULE)
+	{
+		I2C_BOARD_INFO("ssm2602", 0x1b),
+	},
+#endif
 };
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -736,6 +749,10 @@
 	&i2c_bfin_twi_device,
 #endif
 
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+	&bfin_i2s,
+#endif
+
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
 #ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
 	&bfin_sport0_uart_device,
diff --git a/arch/blackfin/mach-bf518/boards/tcm-bf518.c b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
index 9b72e5c..bead810 100644
--- a/arch/blackfin/mach-bf518/boards/tcm-bf518.c
+++ b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
@@ -291,7 +291,7 @@
 
 /* SPI (1) */
 static struct bfin5xx_spi_master bfin_spi1_info = {
-	.num_chipselect = 5,
+	.num_chipselect = 6,
 	.enable_dma = 1,  /* master has the ability to do dma transfer */
 	.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
 };
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h b/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
index e548e9d..e16969f 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
@@ -262,14 +262,14 @@
 #define bfin_write_SPORT0_TX(val)		bfin_write32(SPORT0_TX, val)
 #define bfin_read_SPORT0_RX()			bfin_read32(SPORT0_RX)
 #define bfin_write_SPORT0_RX(val)		bfin_write32(SPORT0_RX, val)
-#define bfin_read_SPORT0_TX32()			bfin_read32(SPORT0_TX32)
-#define bfin_write_SPORT0_TX32(val)		bfin_write32(SPORT0_TX32, val)
-#define bfin_read_SPORT0_RX32()			bfin_read32(SPORT0_RX32)
-#define bfin_write_SPORT0_RX32(val)		bfin_write32(SPORT0_RX32, val)
-#define bfin_read_SPORT0_TX16()			bfin_read16(SPORT0_TX16)
-#define bfin_write_SPORT0_TX16(val)		bfin_write16(SPORT0_TX16, val)
-#define bfin_read_SPORT0_RX16()			bfin_read16(SPORT0_RX16)
-#define bfin_write_SPORT0_RX16(val)		bfin_write16(SPORT0_RX16, val)
+#define bfin_read_SPORT0_TX32()			bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX32(val)		bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX32()			bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX32(val)		bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_TX16()			bfin_read16(SPORT0_TX)
+#define bfin_write_SPORT0_TX16(val)		bfin_write16(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX16()			bfin_read16(SPORT0_RX)
+#define bfin_write_SPORT0_RX16(val)		bfin_write16(SPORT0_RX, val)
 #define bfin_read_SPORT0_RCR1()			bfin_read16(SPORT0_RCR1)
 #define bfin_write_SPORT0_RCR1(val)		bfin_write16(SPORT0_RCR1, val)
 #define bfin_read_SPORT0_RCR2()			bfin_read16(SPORT0_RCR2)
@@ -317,14 +317,14 @@
 #define bfin_write_SPORT1_TX(val)		bfin_write32(SPORT1_TX, val)
 #define bfin_read_SPORT1_RX()			bfin_read32(SPORT1_RX)
 #define bfin_write_SPORT1_RX(val)		bfin_write32(SPORT1_RX, val)
-#define bfin_read_SPORT1_TX32()			bfin_read32(SPORT1_TX32)
-#define bfin_write_SPORT1_TX32(val)		bfin_write32(SPORT1_TX32, val)
-#define bfin_read_SPORT1_RX32()			bfin_read32(SPORT1_RX32)
-#define bfin_write_SPORT1_RX32(val)		bfin_write32(SPORT1_RX32, val)
-#define bfin_read_SPORT1_TX16()			bfin_read16(SPORT1_TX16)
-#define bfin_write_SPORT1_TX16(val)		bfin_write16(SPORT1_TX16, val)
-#define bfin_read_SPORT1_RX16()			bfin_read16(SPORT1_RX16)
-#define bfin_write_SPORT1_RX16(val)		bfin_write16(SPORT1_RX16, val)
+#define bfin_read_SPORT1_TX32()			bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX32(val)		bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX32()			bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX32(val)		bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_TX16()			bfin_read16(SPORT1_TX)
+#define bfin_write_SPORT1_TX16(val)		bfin_write16(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX16()			bfin_read16(SPORT1_RX)
+#define bfin_write_SPORT1_RX16(val)		bfin_write16(SPORT1_RX, val)
 #define bfin_read_SPORT1_RCR1()			bfin_read16(SPORT1_RCR1)
 #define bfin_write_SPORT1_RCR1(val)		bfin_write16(SPORT1_RCR1, val)
 #define bfin_read_SPORT1_RCR2()			bfin_read16(SPORT1_RCR2)
@@ -1058,54 +1058,4 @@
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore_hw(flags);
-}
-
 #endif /* _CDEF_BF52X_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h b/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
index 037a51f..5f84913 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
@@ -748,51 +748,6 @@
 #define FFE			0x20		/* Force Framing Error On Transmit	*/
 
 
-/* ***********  SERIAL PERIPHERAL INTERFACE (SPI) MASKS  ****************************/
-/* SPI_CTL Masks																	*/
-#define	TIMOD		0x0003		/* Transfer Initiate Mode							*/
-#define RDBR_CORE	0x0000		/* 		RDBR Read Initiates, IRQ When RDBR Full		*/
-#define	TDBR_CORE	0x0001		/* 		TDBR Write Initiates, IRQ When TDBR Empty	*/
-#define RDBR_DMA	0x0002		/* 		DMA Read, DMA Until FIFO Empty				*/
-#define TDBR_DMA	0x0003		/* 		DMA Write, DMA Until FIFO Full				*/
-#define SZ			0x0004		/* Send Zero (When TDBR Empty, Send Zero/Last*)		*/
-#define GM			0x0008		/* Get More (When RDBR Full, Overwrite/Discard*)	*/
-#define PSSE		0x0010		/* Slave-Select Input Enable						*/
-#define EMISO		0x0020		/* Enable MISO As Output							*/
-#define SIZE		0x0100		/* Size of Words (16/8* Bits)						*/
-#define LSBF		0x0200		/* LSB First										*/
-#define CPHA		0x0400		/* Clock Phase										*/
-#define CPOL		0x0800		/* Clock Polarity									*/
-#define MSTR		0x1000		/* Master/Slave*									*/
-#define WOM			0x2000		/* Write Open Drain Master							*/
-#define SPE			0x4000		/* SPI Enable										*/
-
-/* SPI_FLG Masks																	*/
-#define FLS1		0x0002		/* Enables SPI_FLOUT1 as SPI Slave-Select Output	*/
-#define FLS2		0x0004		/* Enables SPI_FLOUT2 as SPI Slave-Select Output	*/
-#define FLS3		0x0008		/* Enables SPI_FLOUT3 as SPI Slave-Select Output	*/
-#define FLS4		0x0010		/* Enables SPI_FLOUT4 as SPI Slave-Select Output	*/
-#define FLS5		0x0020		/* Enables SPI_FLOUT5 as SPI Slave-Select Output	*/
-#define FLS6		0x0040		/* Enables SPI_FLOUT6 as SPI Slave-Select Output	*/
-#define FLS7		0x0080		/* Enables SPI_FLOUT7 as SPI Slave-Select Output	*/
-#define FLG1		0xFDFF		/* Activates SPI_FLOUT1 							*/
-#define FLG2		0xFBFF		/* Activates SPI_FLOUT2								*/
-#define FLG3		0xF7FF		/* Activates SPI_FLOUT3								*/
-#define FLG4		0xEFFF		/* Activates SPI_FLOUT4								*/
-#define FLG5		0xDFFF		/* Activates SPI_FLOUT5								*/
-#define FLG6		0xBFFF		/* Activates SPI_FLOUT6								*/
-#define FLG7		0x7FFF		/* Activates SPI_FLOUT7								*/
-
-/* SPI_STAT Masks																				*/
-#define SPIF		0x0001		/* SPI Finished (Single-Word Transfer Complete)					*/
-#define MODF		0x0002		/* Mode Fault Error (Another Device Tried To Become Master)		*/
-#define TXE			0x0004		/* Transmission Error (Data Sent With No New Data In TDBR)		*/
-#define TXS			0x0008		/* SPI_TDBR Data Buffer Status (Full/Empty*)					*/
-#define RBSY		0x0010		/* Receive Error (Data Received With RDBR Full)					*/
-#define RXS			0x0020		/* SPI_RDBR Data Buffer Status (Full/Empty*)					*/
-#define TXCOL		0x0040		/* Transmit Collision Error (Corrupt Data May Have Been Sent)	*/
-
-
 /*  ****************  GENERAL PURPOSE TIMER MASKS  **********************/
 /* TIMER_ENABLE Masks													*/
 #define TIMEN0			0x0001		/* Enable Timer 0					*/
diff --git a/arch/blackfin/mach-bf518/include/mach/pll.h b/arch/blackfin/mach-bf518/include/mach/pll.h
new file mode 100644
index 0000000..d550298
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/pll.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1;
+
+	if (val == bfin_read_PLL_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SIC_IWR0);
+	iwr1 = bfin_read32(SIC_IWR1);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+	bfin_write32(SIC_IWR1, 0);
+
+	bfin_write16(PLL_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR0, iwr0);
+	bfin_write32(SIC_IWR1, iwr1);
+	hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1;
+
+	if (val == bfin_read_VR_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SIC_IWR0);
+	iwr1 = bfin_read32(SIC_IWR1);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+	bfin_write32(SIC_IWR1, 0);
+
+	bfin_write16(VR_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR0, iwr0);
+	bfin_write32(SIC_IWR1, iwr1);
+	hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf527/boards/Kconfig b/arch/blackfin/mach-bf527/boards/Kconfig
index b14c288..1cc2667 100644
--- a/arch/blackfin/mach-bf527/boards/Kconfig
+++ b/arch/blackfin/mach-bf527/boards/Kconfig
@@ -24,4 +24,14 @@
 	help
 	  BF526-EZBRD/EZKIT Lite board support.
 
+config BFIN527_AD7160EVAL
+	bool "BF527-AD7160-EVAL"
+	help
+	  BF527-AD7160-EVAL board support.
+
+config BFIN527_TLL6527M
+	bool "The Learning Labs TLL6527M"
+	help
+	  TLL6527M V1.0 platform support
+
 endchoice
diff --git a/arch/blackfin/mach-bf527/boards/Makefile b/arch/blackfin/mach-bf527/boards/Makefile
index 51a5817..1d67da9 100644
--- a/arch/blackfin/mach-bf527/boards/Makefile
+++ b/arch/blackfin/mach-bf527/boards/Makefile
@@ -6,3 +6,5 @@
 obj-$(CONFIG_BFIN527_EZKIT_V2)         += ezkit.o
 obj-$(CONFIG_BFIN527_BLUETECHNIX_CM)   += cm_bf527.o
 obj-$(CONFIG_BFIN526_EZBRD)            += ezbrd.o
+obj-$(CONFIG_BFIN527_AD7160EVAL)       += ad7160eval.o
+obj-$(CONFIG_BFIN527_TLL6527M)         += tll6527m.o
diff --git a/arch/blackfin/mach-bf527/boards/ad7160eval.c b/arch/blackfin/mach-bf527/boards/ad7160eval.c
new file mode 100644
index 0000000..fc767ac
--- /dev/null
+++ b/arch/blackfin/mach-bf527/boards/ad7160eval.c
@@ -0,0 +1,870 @@
+/*
+ * Copyright 2004-20010 Analog Devices Inc.
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/usb/musb.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <asm/dma.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/reboot.h>
+#include <asm/nand.h>
+#include <asm/portmux.h>
+#include <asm/dpmc.h>
+
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "ADI BF527-AD7160EVAL";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+static struct resource musb_resources[] = {
+	[0] = {
+		.start	= 0xffc03800,
+		.end	= 0xffc03cff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {	/* general IRQ */
+		.start	= IRQ_USB_INT0,
+		.end	= IRQ_USB_INT0,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+	},
+	[2] = {	/* DMA IRQ */
+		.start	= IRQ_USB_DMA,
+		.end	= IRQ_USB_DMA,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+	},
+};
+
+static struct musb_hdrc_config musb_config = {
+	.multipoint	= 0,
+	.dyn_fifo	= 0,
+	.soft_con	= 1,
+	.dma		= 1,
+	.num_eps	= 8,
+	.dma_channels	= 8,
+	.gpio_vrsel	= GPIO_PG13,
+	/* Some custom boards need to be active low, just set it to "0"
+	 * if it is the case.
+	 */
+	.gpio_vrsel_active	= 1,
+};
+
+static struct musb_hdrc_platform_data musb_plat = {
+#if defined(CONFIG_USB_MUSB_OTG)
+	.mode		= MUSB_OTG,
+#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+	.mode		= MUSB_HOST,
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+	.mode		= MUSB_PERIPHERAL,
+#endif
+	.config		= &musb_config,
+};
+
+static u64 musb_dmamask = ~(u32)0;
+
+static struct platform_device musb_device = {
+	.name		= "musb_hdrc",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &musb_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &musb_plat,
+	},
+	.num_resources	= ARRAY_SIZE(musb_resources),
+	.resource	= musb_resources,
+};
+#endif
+
+#if defined(CONFIG_FB_BFIN_RA158Z) || defined(CONFIG_FB_BFIN_RA158Z_MODULE)
+static struct resource bf52x_ra158z_resources[] = {
+	{
+		.start = IRQ_PPI_ERROR,
+		.end = IRQ_PPI_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bf52x_ra158z_device = {
+	.name		= "bfin-ra158z",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(bf52x_ra158z_resources),
+	.resource	= bf52x_ra158z_resources,
+};
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+static struct mtd_partition ad7160eval_partitions[] = {
+	{
+		.name       = "bootloader(nor)",
+		.size       = 0x40000,
+		.offset     = 0,
+	}, {
+		.name       = "linux kernel(nor)",
+		.size       = 0x1C0000,
+		.offset     = MTDPART_OFS_APPEND,
+	}, {
+		.name       = "file system(nor)",
+		.size       = MTDPART_SIZ_FULL,
+		.offset     = MTDPART_OFS_APPEND,
+	}
+};
+
+static struct physmap_flash_data ad7160eval_flash_data = {
+	.width      = 2,
+	.parts      = ad7160eval_partitions,
+	.nr_parts   = ARRAY_SIZE(ad7160eval_partitions),
+};
+
+static struct resource ad7160eval_flash_resource = {
+	.start = 0x20000000,
+	.end   = 0x203fffff,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ad7160eval_flash_device = {
+	.name          = "physmap-flash",
+	.id            = 0,
+	.dev = {
+		.platform_data = &ad7160eval_flash_data,
+	},
+	.num_resources = 1,
+	.resource      = &ad7160eval_flash_resource,
+};
+#endif
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+static struct mtd_partition partition_info[] = {
+	{
+		.name = "linux kernel(nand)",
+		.offset = 0,
+		.size = 4 * 1024 * 1024,
+	},
+	{
+		.name = "file system(nand)",
+		.offset = MTDPART_OFS_APPEND,
+		.size = MTDPART_SIZ_FULL,
+	},
+};
+
+static struct bf5xx_nand_platform bf5xx_nand_platform = {
+	.data_width = NFC_NWIDTH_8,
+	.partitions = partition_info,
+	.nr_partitions = ARRAY_SIZE(partition_info),
+	.rd_dly = 3,
+	.wr_dly = 3,
+};
+
+static struct resource bf5xx_nand_resources[] = {
+	{
+		.start = NFC_CTL,
+		.end = NFC_DATA_RD + 2,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = CH_NFC,
+		.end = CH_NFC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bf5xx_nand_device = {
+	.name = "bf5xx-nand",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bf5xx_nand_resources),
+	.resource = bf5xx_nand_resources,
+	.dev = {
+		.platform_data = &bf5xx_nand_platform,
+	},
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+	.name = "rtc-bfin",
+	.id   = -1,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_RMII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
+static struct platform_device bfin_mii_bus = {
+	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
+};
+
+static struct platform_device bfin_mac_device = {
+	.name = "bfin_mac",
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
+};
+#endif
+
+
+#if defined(CONFIG_MTD_M25P80) \
+	|| defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+	{
+		.name = "bootloader(spi)",
+		.size = 0x00040000,
+		.offset = 0,
+		.mask_flags = MTD_CAP_ROM
+	}, {
+		.name = "linux kernel(spi)",
+		.size = MTDPART_SIZ_FULL,
+		.offset = MTDPART_OFS_APPEND,
+	}
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+	.name = "m25p80",
+	.parts = bfin_spi_flash_partitions,
+	.nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+	.type = "m25p16",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+	.enable_dma = 0,         /* use dma transfer with this chip*/
+	.bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s = {
+	.name = "bfin-i2s",
+	.id = CONFIG_SND_BF5XX_SPORT_NUM,
+	/* TODO: add platform data here */
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+static struct platform_device bfin_tdm = {
+	.name = "bfin-tdm",
+	.id = CONFIG_SND_BF5XX_SPORT_NUM,
+	/* TODO: add platform data here */
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+	|| defined(CONFIG_MTD_M25P80_MODULE)
+	{
+		/* the modalias must be the same as spi device driver name */
+		.modalias = "m25p80", /* Name of spi_driver for this device */
+		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0, /* Framework bus number */
+		.chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+		.platform_data = &bfin_spi_flash_data,
+		.controller_data = &spi_flash_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
+	{
+		.modalias = "ad183x",
+		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 4,
+		.controller_data = &ad1836_spi_chip_info,
+	},
+#endif
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+	{
+		.modalias = "mmc_spi",
+		.max_speed_hz = 30000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = GPIO_PH3 + MAX_CTRL_CS,
+		.controller_data = &mmc_spi_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+	{
+		.modalias = "spidev",
+		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 1,
+		.controller_data = &spidev_chip_info,
+	},
+#endif
+};
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* SPI controller data */
+static struct bfin5xx_spi_master bfin_spi0_info = {
+	.num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS,
+	.enable_dma = 1,  /* master has the ability to do dma transfer */
+	.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+	[0] = {
+		.start = SPI0_REGBASE,
+		.end   = SPI0_REGBASE + 0xFF,
+		.flags = IORESOURCE_MEM,
+		},
+	[1] = {
+		.start = CH_SPI,
+		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bfin_spi0_device = {
+	.name = "bfin-spi",
+	.id = 0, /* Bus number */
+	.num_resources = ARRAY_SIZE(bfin_spi0_resource),
+	.resource = bfin_spi0_resource,
+	.dev = {
+		.platform_data = &bfin_spi0_info, /* Passed to driver */
+	},
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+static struct resource bfin_uart0_resources[] = {
+	{
+		.start = UART0_THR,
+		.end = UART0_GCTL+2,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_UART0_RX,
+		.end = IRQ_UART0_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_UART0_ERROR,
+		.end = IRQ_UART0_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = CH_UART0_TX,
+		.end = CH_UART0_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	{
+		.start = CH_UART0_RX,
+		.end = CH_UART0_RX,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+unsigned short bfin_uart0_peripherals[] = {
+	P_UART0_TX, P_UART0_RX, 0
+};
+
+static struct platform_device bfin_uart0_device = {
+	.name = "bfin-uart",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_uart0_resources),
+	.resource = bfin_uart0_resources,
+	.dev = {
+		.platform_data = &bfin_uart0_peripherals, /* Passed to driver */
+	},
+};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+static struct resource bfin_uart1_resources[] = {
+	{
+		.start = UART1_THR,
+		.end = UART1_GCTL+2,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_UART1_RX,
+		.end = IRQ_UART1_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_UART1_ERROR,
+		.end = IRQ_UART1_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = CH_UART1_TX,
+		.end = CH_UART1_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	{
+		.start = CH_UART1_RX,
+		.end = CH_UART1_RX,
+		.flags = IORESOURCE_DMA,
+	},
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+	{	/* CTS pin */
+		.start = GPIO_PF9,
+		.end = GPIO_PF9,
+		.flags = IORESOURCE_IO,
+	},
+	{	/* RTS pin */
+		.start = GPIO_PF10,
+		.end = GPIO_PF10,
+		.flags = IORESOURCE_IO,
+	},
+#endif
+};
+
+unsigned short bfin_uart1_peripherals[] = {
+	P_UART1_TX, P_UART1_RX, 0
+};
+
+static struct platform_device bfin_uart1_device = {
+	.name = "bfin-uart",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(bfin_uart1_resources),
+	.resource = bfin_uart1_resources,
+	.dev = {
+		.platform_data = &bfin_uart1_peripherals, /* Passed to driver */
+	},
+};
+#endif
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
+	{
+		.start = 0xFFC00400,
+		.end = 0xFFC004FF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_UART0_RX,
+		.end = IRQ_UART0_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = CH_UART0_RX,
+		.end = CH_UART0_RX+1,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device bfin_sir0_device = {
+	.name = "bfin_sir",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_sir0_resources),
+	.resource = bfin_sir0_resources,
+};
+#endif
+#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
+	{
+		.start = 0xFFC02000,
+		.end = 0xFFC020FF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_UART1_RX,
+		.end = IRQ_UART1_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = CH_UART1_RX,
+		.end = CH_UART1_RX+1,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device bfin_sir1_device = {
+	.name = "bfin_sir",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(bfin_sir1_resources),
+	.resource = bfin_sir1_resources,
+};
+#endif
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7160) || defined(CONFIG_TOUCHSCREEN_AD7160_MODULE)
+#include <linux/input/ad7160.h>
+static const struct ad7160_platform_data bfin_ad7160_ts_info = {
+	.sensor_x_res = 854,
+	.sensor_y_res = 480,
+	.pressure = 100,
+	.filter_coef = 3,
+	.coord_pref = AD7160_ORIG_TOP_LEFT,
+	.first_touch_window = 5,
+	.move_window = 3,
+	.event_cabs = AD7160_EMIT_ABS_MT_TRACKING_ID |
+			AD7160_EMIT_ABS_MT_PRESSURE |
+			AD7160_TRACKING_ID_ASCENDING,
+	.finger_act_ctrl = 0x64,
+	.haptic_effect1_ctrl = AD7160_HAPTIC_SLOT_A(60) |
+				AD7160_HAPTIC_SLOT_A_LVL_HIGH |
+				AD7160_HAPTIC_SLOT_B(60) |
+				AD7160_HAPTIC_SLOT_B_LVL_LOW,
+
+	.haptic_effect2_ctrl = AD7160_HAPTIC_SLOT_A(20) |
+				AD7160_HAPTIC_SLOT_A_LVL_HIGH |
+				AD7160_HAPTIC_SLOT_B(80) |
+				AD7160_HAPTIC_SLOT_B_LVL_LOW |
+				AD7160_HAPTIC_SLOT_C(120) |
+				AD7160_HAPTIC_SLOT_C_LVL_HIGH |
+				AD7160_HAPTIC_SLOT_D(30) |
+				AD7160_HAPTIC_SLOT_D_LVL_LOW,
+};
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+	[0] = {
+		.start = TWI0_REGBASE,
+		.end   = TWI0_REGBASE,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TWI,
+		.end   = IRQ_TWI,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device i2c_bfin_twi_device = {
+	.name = "i2c-bfin-twi",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_twi0_resource),
+	.resource = bfin_twi0_resource,
+};
+#endif
+
+static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_TOUCHSCREEN_AD7160) || defined(CONFIG_TOUCHSCREEN_AD7160_MODULE)
+	{
+		I2C_BOARD_INFO("ad7160", 0x33),
+		.irq = IRQ_PH1,
+		.platform_data = (void *)&bfin_ad7160_ts_info,
+	},
+#endif
+};
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+static struct resource bfin_sport0_uart_resources[] = {
+	{
+		.start = SPORT0_TCR1,
+		.end = SPORT0_MRCS3+4,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_SPORT0_RX,
+		.end = IRQ_SPORT0_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_SPORT0_ERROR,
+		.end = IRQ_SPORT0_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+unsigned short bfin_sport0_peripherals[] = {
+	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+};
+
+static struct platform_device bfin_sport0_uart_device = {
+	.name = "bfin-sport-uart",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_sport0_uart_resources),
+	.resource = bfin_sport0_uart_resources,
+	.dev = {
+		.platform_data = &bfin_sport0_peripherals, /* Passed to driver */
+	},
+};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+static struct resource bfin_sport1_uart_resources[] = {
+	{
+		.start = SPORT1_TCR1,
+		.end = SPORT1_MRCS3+4,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_SPORT1_RX,
+		.end = IRQ_SPORT1_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_SPORT1_ERROR,
+		.end = IRQ_SPORT1_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+unsigned short bfin_sport1_peripherals[] = {
+	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+	.name = "bfin-sport-uart",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(bfin_sport1_uart_resources),
+	.resource = bfin_sport1_uart_resources,
+	.dev = {
+		.platform_data = &bfin_sport1_peripherals, /* Passed to driver */
+	},
+};
+#endif
+#endif
+
+#if defined(CONFIG_INPUT_BFIN_ROTARY) || defined(CONFIG_INPUT_BFIN_ROTARY_MODULE)
+#include <asm/bfin_rotary.h>
+
+static struct bfin_rotary_platform_data bfin_rotary_data = {
+	/*.rotary_up_key     = KEY_UP,*/
+	/*.rotary_down_key   = KEY_DOWN,*/
+	.rotary_rel_code   = REL_WHEEL,
+	.rotary_button_key = KEY_ENTER,
+	.debounce	   = 10,	/* 0..17 */
+	.mode		   = ROT_QUAD_ENC | ROT_DEBE,
+};
+
+static struct resource bfin_rotary_resources[] = {
+	{
+		.start = IRQ_CNT,
+		.end = IRQ_CNT,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bfin_rotary_device = {
+	.name		= "bfin-rotary",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(bfin_rotary_resources),
+	.resource	= bfin_rotary_resources,
+	.dev		= {
+		.platform_data = &bfin_rotary_data,
+	},
+};
+#endif
+
+static const unsigned int cclk_vlev_datasheet[] = {
+	VRPAIR(VLEV_100, 400000000),
+	VRPAIR(VLEV_105, 426000000),
+	VRPAIR(VLEV_110, 500000000),
+	VRPAIR(VLEV_115, 533000000),
+	VRPAIR(VLEV_120, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+	.tuple_tab = cclk_vlev_datasheet,
+	.tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+	.vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+	.name = "bfin dpmc",
+	.dev = {
+		.platform_data = &bfin_dmpc_vreg_data,
+	},
+};
+
+static struct platform_device *stamp_devices[] __initdata = {
+
+	&bfin_dpmc,
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+	&bf5xx_nand_device,
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+	&rtc_device,
+#endif
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+	&musb_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+	&bfin_mii_bus,
+	&bfin_mac_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+	&bfin_spi0_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+	&bfin_uart0_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+	&bfin_uart1_device,
+#endif
+#endif
+
+#if defined(CONFIG_FB_BFIN_RA158Z) || defined(CONFIG_FB_BFIN_RA158Z_MODULE)
+	&bf52x_ra158z_device,
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+	&bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+	&bfin_sir1_device,
+#endif
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+	&i2c_bfin_twi_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+	&bfin_sport0_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+	&bfin_sport1_uart_device,
+#endif
+#endif
+
+#if defined(CONFIG_INPUT_BFIN_ROTARY) || defined(CONFIG_INPUT_BFIN_ROTARY_MODULE)
+	&bfin_rotary_device,
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+	&ad7160eval_flash_device,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+	&bfin_i2s,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+	&bfin_tdm,
+#endif
+};
+
+static int __init ad7160eval_init(void)
+{
+	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+	i2c_register_board_info(0, bfin_i2c_board_info,
+				ARRAY_SIZE(bfin_i2c_board_info));
+	platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+	return 0;
+}
+
+arch_initcall(ad7160eval_init);
+
+static struct platform_device *ad7160eval_early_devices[] __initdata = {
+#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+	&bfin_uart0_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+	&bfin_uart1_device,
+#endif
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT_CONSOLE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+	&bfin_sport0_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+	&bfin_sport1_uart_device,
+#endif
+#endif
+};
+
+void __init native_machine_early_platform_add_devices(void)
+{
+	printk(KERN_INFO "register early platform devices\n");
+	early_platform_add_devices(ad7160eval_early_devices,
+		ARRAY_SIZE(ad7160eval_early_devices));
+}
+
+void native_machine_restart(char *cmd)
+{
+	/* workaround reboot hang when booting from SPI */
+	if ((bfin_read_SYSCR() & 0x7) == 0x3)
+		bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
+}
+
+void bfin_get_ether_addr(char *addr)
+{
+	/* the MAC is stored in OTP memory page 0xDF */
+	u32 ret;
+	u64 otp_mac;
+	u32 (*otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)0xEF00001A;
+
+	ret = otp_read(0xDF, 0x00, &otp_mac);
+	if (!(ret & 0x1)) {
+		char *otp_mac_p = (char *)&otp_mac;
+		for (ret = 0; ret < 6; ++ret)
+			addr[ret] = otp_mac_p[5 - ret];
+	}
+}
+EXPORT_SYMBOL(bfin_get_ether_addr);
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index 645ba5c..38037c7 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -342,8 +342,8 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
-	|| defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -420,13 +420,13 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
-	|| defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
 		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c
index c975fe8..6cc64a1 100644
--- a/arch/blackfin/mach-bf527/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf527/boards/ezbrd.c
@@ -137,8 +137,12 @@
 #if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
 static struct mtd_partition partition_info[] = {
 	{
-		.name = "linux kernel(nand)",
+		.name = "bootloader(nand)",
 		.offset = 0,
+		.size = 0x40000,
+	}, {
+		.name = "linux kernel(nand)",
+		.offset = MTDPART_OFS_APPEND,
 		.size = 4 * 1024 * 1024,
 	},
 	{
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index 87b41e9..07c132d 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -222,8 +222,12 @@
 #if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
 static struct mtd_partition partition_info[] = {
 	{
-		.name = "linux kernel(nand)",
+		.name = "bootloader(nand)",
 		.offset = 0,
+		.size = 0x40000,
+	}, {
+		.name = "linux kernel(nand)",
+		.offset = MTDPART_OFS_APPEND,
 		.size = 4 * 1024 * 1024,
 	},
 	{
@@ -431,8 +435,8 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
-	|| defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -547,13 +551,13 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
-	|| defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
 		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
@@ -929,6 +933,11 @@
 		I2C_BOARD_INFO("ssm2602", 0x1b),
 	},
 #endif
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
+	{
+		I2C_BOARD_INFO("ad5252", 0x2f),
+	},
+#endif
 };
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
diff --git a/arch/blackfin/mach-bf527/boards/tll6527m.c b/arch/blackfin/mach-bf527/boards/tll6527m.c
new file mode 100644
index 0000000..ae4130e
--- /dev/null
+++ b/arch/blackfin/mach-bf527/boards/tll6527m.c
@@ -0,0 +1,986 @@
+/* File:	arch/blackfin/mach-bf527/boards/tll6527m.c
+ * Based on:	arch/blackfin/mach-bf527/boards/ezkit.c
+ * Author:	Ashish Gupta
+ *
+ * Copyright: 2010 - The Learning Labs Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/usb/musb.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <asm/dma.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/reboot.h>
+#include <asm/nand.h>
+#include <asm/portmux.h>
+#include <asm/dpmc.h>
+
+#if defined(CONFIG_TOUCHSCREEN_AD7879) \
+	|| defined(CONFIG_TOUCHSCREEN_AD7879_MODULE)
+#include <linux/spi/ad7879.h>
+#define LCD_BACKLIGHT_GPIO 0x40
+/* TLL6527M uses TLL7UIQ35 / ADI LCD EZ Extender. AD7879 AUX GPIO is used for
+ * LCD Backlight Enable
+ */
+#endif
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "TLL6527M";
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+static struct resource musb_resources[] = {
+	[0] = {
+		.start	= 0xffc03800,
+		.end	= 0xffc03cff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {	/* general IRQ */
+		.start	= IRQ_USB_INT0,
+		.end	= IRQ_USB_INT0,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+	},
+	[2] = {	/* DMA IRQ */
+		.start	= IRQ_USB_DMA,
+		.end	= IRQ_USB_DMA,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+	},
+};
+
+static struct musb_hdrc_config musb_config = {
+	.multipoint	= 0,
+	.dyn_fifo	= 0,
+	.soft_con	= 1,
+	.dma		= 1,
+	.num_eps	= 8,
+	.dma_channels	= 8,
+	/*.gpio_vrsel	= GPIO_PG13,*/
+	/* Some custom boards need to be active low, just set it to "0"
+	 * if it is the case.
+	 */
+	.gpio_vrsel_active	= 1,
+};
+
+static struct musb_hdrc_platform_data musb_plat = {
+#if defined(CONFIG_USB_MUSB_OTG)
+	.mode		= MUSB_OTG,
+#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+	.mode		= MUSB_HOST,
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+	.mode		= MUSB_PERIPHERAL,
+#endif
+	.config		= &musb_config,
+};
+
+static u64 musb_dmamask = ~(u32)0;
+
+static struct platform_device musb_device = {
+	.name		= "musb_hdrc",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &musb_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &musb_plat,
+	},
+	.num_resources	= ARRAY_SIZE(musb_resources),
+	.resource	= musb_resources,
+};
+#endif
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+#include <asm/bfin-lq035q1.h>
+
+static struct bfin_lq035q1fb_disp_info bfin_lq035q1_data = {
+	.mode = LQ035_NORM | LQ035_RGB | LQ035_RL | LQ035_TB,
+	.ppi_mode = USE_RGB565_16_BIT_PPI,
+	.use_bl = 1,
+	.gpio_bl = LCD_BACKLIGHT_GPIO,
+};
+
+static struct resource bfin_lq035q1_resources[] = {
+	{
+		.start = IRQ_PPI_ERROR,
+		.end = IRQ_PPI_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bfin_lq035q1_device = {
+	.name		= "bfin-lq035q1",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(bfin_lq035q1_resources),
+	.resource	= bfin_lq035q1_resources,
+	.dev		= {
+		.platform_data = &bfin_lq035q1_data,
+	},
+};
+#endif
+
+#if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
+static struct mtd_partition tll6527m_partitions[] = {
+	{
+		.name       = "bootloader(nor)",
+		.size       = 0xA0000,
+		.offset     = 0,
+	}, {
+		.name       = "linux kernel(nor)",
+		.size       = 0xD00000,
+		.offset     = MTDPART_OFS_APPEND,
+	}, {
+		.name       = "file system(nor)",
+		.size       = MTDPART_SIZ_FULL,
+		.offset     = MTDPART_OFS_APPEND,
+	}
+};
+
+static struct physmap_flash_data tll6527m_flash_data = {
+	.width      = 2,
+	.parts      = tll6527m_partitions,
+	.nr_parts   = ARRAY_SIZE(tll6527m_partitions),
+};
+
+static unsigned tll6527m_flash_gpios[] = { GPIO_PG11, GPIO_PH11, GPIO_PH12 };
+
+static struct resource tll6527m_flash_resource[] = {
+	{
+		.name  = "cfi_probe",
+		.start = 0x20000000,
+		.end   = 0x201fffff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = (unsigned long)tll6527m_flash_gpios,
+		.end   = ARRAY_SIZE(tll6527m_flash_gpios),
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device tll6527m_flash_device = {
+	.name          = "gpio-addr-flash",
+	.id            = 0,
+	.dev = {
+		.platform_data = &tll6527m_flash_data,
+	},
+	.num_resources = ARRAY_SIZE(tll6527m_flash_resource),
+	.resource      = tll6527m_flash_resource,
+};
+#endif
+
+#if defined(CONFIG_GPIO_DECODER) || defined(CONFIG_GPIO_DECODER_MODULE)
+/* An SN74LVC138A 3:8 decoder chip has been used to generate 7 augmented
+ * outputs used as SPI CS lines for all SPI SLAVE devices on TLL6527v1-0.
+ * EXP_GPIO_SPISEL_BASE is the base number for the expanded outputs being
+ * used as SPI CS lines, this should be > MAX_BLACKFIN_GPIOS
+ */
+#include <linux/gpio-decoder.h>
+#define EXP_GPIO_SPISEL_BASE 0x64
+static unsigned gpio_addr_inputs[] = {
+	GPIO_PG1, GPIO_PH9, GPIO_PH10
+};
+
+static struct gpio_decoder_platfrom_data spi_decoded_cs = {
+	.base		= EXP_GPIO_SPISEL_BASE,
+	.input_addrs	= gpio_addr_inputs,
+	.nr_input_addrs = ARRAY_SIZE(gpio_addr_inputs),
+	.default_output	= 0,
+/*	.default_output = (1 << ARRAY_SIZE(gpio_addr_inputs)) - 1 */
+};
+
+static struct platform_device spi_decoded_gpio = {
+	.name	= "gpio-decoder",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &spi_decoded_cs,
+	},
+};
+
+#else
+#define EXP_GPIO_SPISEL_BASE 0x0
+
+#endif
+
+#if defined(CONFIG_INPUT_ADXL34X) || defined(CONFIG_INPUT_ADXL34X_MODULE)
+#include <linux/input/adxl34x.h>
+static const struct adxl34x_platform_data adxl345_info = {
+	.x_axis_offset = 0,
+	.y_axis_offset = 0,
+	.z_axis_offset = 0,
+	.tap_threshold = 0x31,
+	.tap_duration = 0x10,
+	.tap_latency = 0x60,
+	.tap_window = 0xF0,
+	.tap_axis_control = ADXL_TAP_X_EN | ADXL_TAP_Y_EN | ADXL_TAP_Z_EN,
+	.act_axis_control = 0xFF,
+	.activity_threshold = 5,
+	.inactivity_threshold = 2,
+	.inactivity_time = 2,
+	.free_fall_threshold = 0x7,
+	.free_fall_time = 0x20,
+	.data_rate = 0x8,
+	.data_range = ADXL_FULL_RES,
+
+	.ev_type = EV_ABS,
+	.ev_code_x = ABS_X,		/* EV_REL */
+	.ev_code_y = ABS_Y,		/* EV_REL */
+	.ev_code_z = ABS_Z,		/* EV_REL */
+
+	.ev_code_tap = {BTN_TOUCH, BTN_TOUCH, BTN_TOUCH}, /* EV_KEY x,y,z */
+
+/*	.ev_code_ff = KEY_F,*/		/* EV_KEY */
+	.ev_code_act_inactivity = KEY_A,	/* EV_KEY */
+	.use_int2 = 1,
+	.power_mode = ADXL_AUTO_SLEEP | ADXL_LINK,
+	.fifo_mode = ADXL_FIFO_STREAM,
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+	.name = "rtc-bfin",
+	.id   = -1,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+	.name = "bfin_mii_bus",
+};
+
+static struct platform_device bfin_mac_device = {
+	.name = "bfin_mac",
+	.dev.platform_data = &bfin_mii_bus,
+};
+#endif
+
+#if defined(CONFIG_MTD_M25P80) \
+	|| defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+	{
+		.name = "bootloader(spi)",
+		.size = 0x00040000,
+		.offset = 0,
+		.mask_flags = MTD_CAP_ROM
+	}, {
+		.name = "linux kernel(spi)",
+		.size = MTDPART_SIZ_FULL,
+		.offset = MTDPART_OFS_APPEND,
+	}
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+	.name = "m25p80",
+	.parts = bfin_spi_flash_partitions,
+	.nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+	.type = "m25p16",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+	.enable_dma = 0,         /* use dma transfer with this chip*/
+	.bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+	.enable_dma = 0,         /* use dma transfer with this chip*/
+/*
+ * tll6527m V1.0 does not support native spi slave selects
+ * hence DMA mode will not be useful since the ADC needs
+ * CS to toggle for each sample and cs_change_per_word
+ * seems to be removed from spi_bfin5xx.c
+ */
+	.bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7879) \
+	|| defined(CONFIG_TOUCHSCREEN_AD7879_MODULE)
+static const struct ad7879_platform_data bfin_ad7879_ts_info = {
+	.model			= 7879,	/* Model = AD7879 */
+	.x_plate_ohms		= 620,	/* 620 Ohm from the touch datasheet */
+	.pressure_max		= 10000,
+	.pressure_min		= 0,
+	.first_conversion_delay = 3,
+				/* wait 512us before do a first conversion */
+	.acquisition_time	= 1,	/* 4us acquisition time per sample */
+	.median			= 2,	/* do 8 measurements */
+	.averaging		= 1,
+				/* take the average of 4 middle samples */
+	.pen_down_acc_interval	= 255,	/* 9.4 ms */
+	.gpio_export		= 1,	/* configure AUX as GPIO output*/
+	.gpio_base		= LCD_BACKLIGHT_GPIO,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) \
+	|| defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s = {
+	.name = "bfin-i2s",
+	.id = CONFIG_SND_BF5XX_SPORT_NUM,
+	/* TODO: add platform data here */
+};
+#endif
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
+	.enable_dma	= 0,
+	.bits_per_word	= 8,
+};
+#endif
+
+#if defined(CONFIG_GPIO_MCP23S08) || defined(CONFIG_GPIO_MCP23S08_MODULE)
+static struct bfin5xx_spi_chip spi_mcp23s08_sys_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+
+static struct bfin5xx_spi_chip spi_mcp23s08_usr_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+
+#include <linux/spi/mcp23s08.h>
+static const struct mcp23s08_platform_data bfin_mcp23s08_sys_gpio_info = {
+	.chip[0].is_present = true,
+	.base = 0x30,
+};
+static const struct mcp23s08_platform_data bfin_mcp23s08_usr_gpio_info = {
+	.chip[2].is_present = true,
+	.base = 0x38,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+	|| defined(CONFIG_MTD_M25P80_MODULE)
+	{
+		/* the modalias must be the same as spi device driver name */
+		.modalias = "m25p80", /* Name of spi_driver for this device */
+		.max_speed_hz = 25000000,
+				/* max spi clock (SCK) speed in HZ */
+		.bus_num = 0, /* Framework bus number */
+		.chip_select = EXP_GPIO_SPISEL_BASE + 0x04 + MAX_CTRL_CS,
+		/* Can be connected to TLL6527M GPIO connector */
+		/* Either SPI_ADC or M25P80 FLASH can be installed at a time */
+		.platform_data = &bfin_spi_flash_data,
+		.controller_data = &spi_flash_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
+
+#if defined(CONFIG_BFIN_SPI_ADC)
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
+	{
+		.modalias = "bfin_spi_adc",
+				/* Name of spi_driver for this device */
+		.max_speed_hz = 10000000,
+				/* max spi clock (SCK) speed in HZ */
+		.bus_num = 0, /* Framework bus number */
+		.chip_select = EXP_GPIO_SPISEL_BASE + 0x04 + MAX_CTRL_CS,
+		 /* Framework chip select. */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.controller_data = &spi_adc_chip_info,
+		.mode = SPI_MODE_0,
+	},
+#endif
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+	{
+		.modalias = "mmc_spi",
+/*
+ * TLL6527M V1.0 does not support SD Card at SPI Clock > 10 MHz due to
+ * SPI buffer limitations
+ */
+		.max_speed_hz = 10000000,
+					/* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = EXP_GPIO_SPISEL_BASE + 0x05 + MAX_CTRL_CS,
+		.controller_data = &mmc_spi_chip_info,
+		.mode = SPI_MODE_0,
+	},
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) \
+	|| defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+	{
+		.modalias = "ad7879",
+		.platform_data = &bfin_ad7879_ts_info,
+		.irq = IRQ_PH14,
+		.max_speed_hz = 5000000,
+					/* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = EXP_GPIO_SPISEL_BASE + 0x07 + MAX_CTRL_CS,
+		.controller_data = &spi_ad7879_chip_info,
+		.mode = SPI_CPHA | SPI_CPOL,
+	},
+#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+	{
+		.modalias = "spidev",
+		.max_speed_hz = 10000000,
+		/* TLL6527Mv1-0 supports max spi clock (SCK) speed = 10 MHz */
+		.bus_num = 0,
+		.chip_select = EXP_GPIO_SPISEL_BASE + 0x03 + MAX_CTRL_CS,
+		.mode = SPI_CPHA | SPI_CPOL,
+		.controller_data = &spidev_chip_info,
+	},
+#endif
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+	{
+		.modalias = "bfin-lq035q1-spi",
+		.max_speed_hz = 20000000,
+		.bus_num = 0,
+		.chip_select = EXP_GPIO_SPISEL_BASE + 0x06 + MAX_CTRL_CS,
+		.controller_data = &lq035q1_spi_chip_info,
+		.mode = SPI_CPHA | SPI_CPOL,
+	},
+#endif
+#if defined(CONFIG_GPIO_MCP23S08) || defined(CONFIG_GPIO_MCP23S08_MODULE)
+	{
+		.modalias = "mcp23s08",
+		.platform_data = &bfin_mcp23s08_sys_gpio_info,
+		.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = EXP_GPIO_SPISEL_BASE + 0x01 + MAX_CTRL_CS,
+		.controller_data = &spi_mcp23s08_sys_chip_info,
+		.mode = SPI_CPHA | SPI_CPOL,
+	},
+	{
+		.modalias = "mcp23s08",
+		.platform_data = &bfin_mcp23s08_usr_gpio_info,
+		.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = EXP_GPIO_SPISEL_BASE + 0x02 + MAX_CTRL_CS,
+		.controller_data = &spi_mcp23s08_usr_chip_info,
+		.mode = SPI_CPHA | SPI_CPOL,
+	},
+#endif
+};
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* SPI controller data */
+static struct bfin5xx_spi_master bfin_spi0_info = {
+	.num_chipselect = EXP_GPIO_SPISEL_BASE + 8 + MAX_CTRL_CS,
+	/* EXP_GPIO_SPISEL_BASE will be > MAX_BLACKFIN_GPIOS */
+	.enable_dma = 1,  /* master has the ability to do dma transfer */
+	.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+	[0] = {
+		.start = SPI0_REGBASE,
+		.end   = SPI0_REGBASE + 0xFF,
+		.flags = IORESOURCE_MEM,
+		},
+	[1] = {
+		.start = CH_SPI,
+		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bfin_spi0_device = {
+	.name = "bfin-spi",
+	.id = 0, /* Bus number */
+	.num_resources = ARRAY_SIZE(bfin_spi0_resource),
+	.resource = bfin_spi0_resource,
+	.dev = {
+		.platform_data = &bfin_spi0_info, /* Passed to driver */
+	},
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+static struct resource bfin_uart0_resources[] = {
+	{
+		.start = UART0_THR,
+		.end = UART0_GCTL+2,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_UART0_RX,
+		.end = IRQ_UART0_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_UART0_ERROR,
+		.end = IRQ_UART0_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = CH_UART0_TX,
+		.end = CH_UART0_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	{
+		.start = CH_UART0_RX,
+		.end = CH_UART0_RX,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+unsigned short bfin_uart0_peripherals[] = {
+	P_UART0_TX, P_UART0_RX, 0
+};
+
+static struct platform_device bfin_uart0_device = {
+	.name = "bfin-uart",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_uart0_resources),
+	.resource = bfin_uart0_resources,
+	.dev = {
+		.platform_data = &bfin_uart0_peripherals,
+					/* Passed to driver */
+	},
+};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+static struct resource bfin_uart1_resources[] = {
+	{
+		.start = UART1_THR,
+		.end = UART1_GCTL+2,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_UART1_RX,
+		.end = IRQ_UART1_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_UART1_ERROR,
+		.end = IRQ_UART1_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = CH_UART1_TX,
+		.end = CH_UART1_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	{
+		.start = CH_UART1_RX,
+		.end = CH_UART1_RX,
+		.flags = IORESOURCE_DMA,
+	},
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+	{	/* CTS pin */
+		.start = GPIO_PF9,
+		.end = GPIO_PF9,
+		.flags = IORESOURCE_IO,
+	},
+	{	/* RTS pin */
+		.start = GPIO_PF10,
+		.end = GPIO_PF10,
+		.flags = IORESOURCE_IO,
+	},
+#endif
+};
+
+unsigned short bfin_uart1_peripherals[] = {
+	P_UART1_TX, P_UART1_RX, 0
+};
+
+static struct platform_device bfin_uart1_device = {
+	.name = "bfin-uart",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(bfin_uart1_resources),
+	.resource = bfin_uart1_resources,
+	.dev = {
+		.platform_data = &bfin_uart1_peripherals,
+						/* Passed to driver */
+	},
+};
+#endif
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
+	{
+		.start = 0xFFC00400,
+		.end = 0xFFC004FF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_UART0_RX,
+		.end = IRQ_UART0_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = CH_UART0_RX,
+		.end = CH_UART0_RX+1,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device bfin_sir0_device = {
+	.name = "bfin_sir",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_sir0_resources),
+	.resource = bfin_sir0_resources,
+};
+#endif
+#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
+	{
+		.start = 0xFFC02000,
+		.end = 0xFFC020FF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_UART1_RX,
+		.end = IRQ_UART1_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = CH_UART1_RX,
+		.end = CH_UART1_RX+1,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device bfin_sir1_device = {
+	.name = "bfin_sir",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(bfin_sir1_resources),
+	.resource = bfin_sir1_resources,
+};
+#endif
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+	[0] = {
+		.start = TWI0_REGBASE,
+		.end   = TWI0_REGBASE,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TWI,
+		.end   = IRQ_TWI,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device i2c_bfin_twi_device = {
+	.name = "i2c-bfin-twi",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_twi0_resource),
+	.resource = bfin_twi0_resource,
+};
+#endif
+
+static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
+	{
+		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
+	},
+#endif
+
+#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
+	{
+		I2C_BOARD_INFO("bfin-adv7393", 0x2B),
+	},
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7879_I2C) \
+	|| defined(CONFIG_TOUCHSCREEN_AD7879_I2C_MODULE)
+	{
+		I2C_BOARD_INFO("ad7879", 0x2C),
+		.irq = IRQ_PH14,
+		.platform_data = (void *)&bfin_ad7879_ts_info,
+	},
+#endif
+#if defined(CONFIG_SND_SOC_SSM2602) || defined(CONFIG_SND_SOC_SSM2602_MODULE)
+	{
+		I2C_BOARD_INFO("ssm2602", 0x1b),
+	},
+#endif
+	{
+		I2C_BOARD_INFO("adm1192", 0x2e),
+	},
+
+	{
+		I2C_BOARD_INFO("ltc3576", 0x09),
+	},
+#if defined(CONFIG_INPUT_ADXL34X_I2C) \
+	|| defined(CONFIG_INPUT_ADXL34X_I2C_MODULE)
+	{
+		I2C_BOARD_INFO("adxl34x", 0x53),
+		.irq = IRQ_PH13,
+		.platform_data = (void *)&adxl345_info,
+	},
+#endif
+};
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) \
+	|| defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+static struct resource bfin_sport0_uart_resources[] = {
+	{
+		.start = SPORT0_TCR1,
+		.end = SPORT0_MRCS3+4,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_SPORT0_RX,
+		.end = IRQ_SPORT0_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_SPORT0_ERROR,
+		.end = IRQ_SPORT0_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+unsigned short bfin_sport0_peripherals[] = {
+	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+};
+
+static struct platform_device bfin_sport0_uart_device = {
+	.name = "bfin-sport-uart",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_sport0_uart_resources),
+	.resource = bfin_sport0_uart_resources,
+	.dev = {
+		.platform_data = &bfin_sport0_peripherals,
+		/* Passed to driver */
+	},
+};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+static struct resource bfin_sport1_uart_resources[] = {
+	{
+		.start = SPORT1_TCR1,
+		.end = SPORT1_MRCS3+4,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_SPORT1_RX,
+		.end = IRQ_SPORT1_RX+1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_SPORT1_ERROR,
+		.end = IRQ_SPORT1_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+unsigned short bfin_sport1_peripherals[] = {
+	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+	.name = "bfin-sport-uart",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(bfin_sport1_uart_resources),
+	.resource = bfin_sport1_uart_resources,
+	.dev = {
+		.platform_data = &bfin_sport1_peripherals,
+		/* Passed to driver */
+	},
+};
+#endif
+#endif
+
+static const unsigned int cclk_vlev_datasheet[] = {
+	VRPAIR(VLEV_100, 400000000),
+	VRPAIR(VLEV_105, 426000000),
+	VRPAIR(VLEV_110, 500000000),
+	VRPAIR(VLEV_115, 533000000),
+	VRPAIR(VLEV_120, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+	.tuple_tab = cclk_vlev_datasheet,
+	.tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+	.vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+	.name = "bfin dpmc",
+	.dev = {
+		.platform_data = &bfin_dmpc_vreg_data,
+	},
+};
+
+static struct platform_device *tll6527m_devices[] __initdata = {
+
+	&bfin_dpmc,
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+	&rtc_device,
+#endif
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+	&musb_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+	&bfin_mii_bus,
+	&bfin_mac_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+	&bfin_spi0_device,
+#endif
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+	&bfin_lq035q1_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+	&bfin_uart0_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+	&bfin_uart1_device,
+#endif
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+	&bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+	&bfin_sir1_device,
+#endif
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+	&i2c_bfin_twi_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) \
+	|| defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+	&bfin_sport0_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+	&bfin_sport1_uart_device,
+#endif
+#endif
+
+#if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
+	&tll6527m_flash_device,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+	&bfin_i2s,
+#endif
+
+#if defined(CONFIG_GPIO_DECODER) || defined(CONFIG_GPIO_DECODER_MODULE)
+	&spi_decoded_gpio,
+#endif
+};
+
+static int __init tll6527m_init(void)
+{
+	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+	i2c_register_board_info(0, bfin_i2c_board_info,
+				ARRAY_SIZE(bfin_i2c_board_info));
+	platform_add_devices(tll6527m_devices, ARRAY_SIZE(tll6527m_devices));
+	spi_register_board_info(bfin_spi_board_info,
+				ARRAY_SIZE(bfin_spi_board_info));
+	return 0;
+}
+
+arch_initcall(tll6527m_init);
+
+static struct platform_device *tll6527m_early_devices[] __initdata = {
+#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+	&bfin_uart0_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+	&bfin_uart1_device,
+#endif
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT_CONSOLE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+	&bfin_sport0_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+	&bfin_sport1_uart_device,
+#endif
+#endif
+};
+
+void __init native_machine_early_platform_add_devices(void)
+{
+	printk(KERN_INFO "register early platform devices\n");
+	early_platform_add_devices(tll6527m_early_devices,
+		ARRAY_SIZE(tll6527m_early_devices));
+}
+
+void native_machine_restart(char *cmd)
+{
+	/* workaround reboot hang when booting from SPI */
+	if ((bfin_read_SYSCR() & 0x7) == 0x3)
+		bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
+}
+
+void bfin_get_ether_addr(char *addr)
+{
+	/* the MAC is stored in OTP memory page 0xDF */
+	u32 ret;
+	u64 otp_mac;
+	u32 (*otp_read)(u32 page, u32 flags,
+			u64 *page_content) = (void *)0xEF00001A;
+
+	ret = otp_read(0xDF, 0x00, &otp_mac);
+	if (!(ret & 0x1)) {
+		char *otp_mac_p = (char *)&otp_mac;
+		for (ret = 0; ret < 6; ++ret)
+			addr[ret] = otp_mac_p[5 - ret];
+	}
+}
+EXPORT_SYMBOL(bfin_get_ether_addr);
diff --git a/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h b/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
index 12f2ad4..3048b52b 100644
--- a/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
+++ b/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
@@ -279,14 +279,14 @@
 #define bfin_write_SPORT0_TX(val)		bfin_write32(SPORT0_TX, val)
 #define bfin_read_SPORT0_RX()			bfin_read32(SPORT0_RX)
 #define bfin_write_SPORT0_RX(val)		bfin_write32(SPORT0_RX, val)
-#define bfin_read_SPORT0_TX32()			bfin_read32(SPORT0_TX32)
-#define bfin_write_SPORT0_TX32(val)		bfin_write32(SPORT0_TX32, val)
-#define bfin_read_SPORT0_RX32()			bfin_read32(SPORT0_RX32)
-#define bfin_write_SPORT0_RX32(val)		bfin_write32(SPORT0_RX32, val)
-#define bfin_read_SPORT0_TX16()			bfin_read16(SPORT0_TX16)
-#define bfin_write_SPORT0_TX16(val)		bfin_write16(SPORT0_TX16, val)
-#define bfin_read_SPORT0_RX16()			bfin_read16(SPORT0_RX16)
-#define bfin_write_SPORT0_RX16(val)		bfin_write16(SPORT0_RX16, val)
+#define bfin_read_SPORT0_TX32()			bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX32(val)		bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX32()			bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX32(val)		bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_TX16()			bfin_read16(SPORT0_TX)
+#define bfin_write_SPORT0_TX16(val)		bfin_write16(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX16()			bfin_read16(SPORT0_RX)
+#define bfin_write_SPORT0_RX16(val)		bfin_write16(SPORT0_RX, val)
 #define bfin_read_SPORT0_RCR1()			bfin_read16(SPORT0_RCR1)
 #define bfin_write_SPORT0_RCR1(val)		bfin_write16(SPORT0_RCR1, val)
 #define bfin_read_SPORT0_RCR2()			bfin_read16(SPORT0_RCR2)
@@ -334,14 +334,14 @@
 #define bfin_write_SPORT1_TX(val)		bfin_write32(SPORT1_TX, val)
 #define bfin_read_SPORT1_RX()			bfin_read32(SPORT1_RX)
 #define bfin_write_SPORT1_RX(val)		bfin_write32(SPORT1_RX, val)
-#define bfin_read_SPORT1_TX32()			bfin_read32(SPORT1_TX32)
-#define bfin_write_SPORT1_TX32(val)		bfin_write32(SPORT1_TX32, val)
-#define bfin_read_SPORT1_RX32()			bfin_read32(SPORT1_RX32)
-#define bfin_write_SPORT1_RX32(val)		bfin_write32(SPORT1_RX32, val)
-#define bfin_read_SPORT1_TX16()			bfin_read16(SPORT1_TX16)
-#define bfin_write_SPORT1_TX16(val)		bfin_write16(SPORT1_TX16, val)
-#define bfin_read_SPORT1_RX16()			bfin_read16(SPORT1_RX16)
-#define bfin_write_SPORT1_RX16(val)		bfin_write16(SPORT1_RX16, val)
+#define bfin_read_SPORT1_TX32()			bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX32(val)		bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX32()			bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX32(val)		bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_TX16()			bfin_read16(SPORT1_TX)
+#define bfin_write_SPORT1_TX16(val)		bfin_write16(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX16()			bfin_read16(SPORT1_RX)
+#define bfin_write_SPORT1_RX16(val)		bfin_write16(SPORT1_RX, val)
 #define bfin_read_SPORT1_RCR1()			bfin_read16(SPORT1_RCR1)
 #define bfin_write_SPORT1_RCR1(val)		bfin_write16(SPORT1_RCR1, val)
 #define bfin_read_SPORT1_RCR2()			bfin_read16(SPORT1_RCR2)
@@ -1110,54 +1110,4 @@
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore_hw(flags);
-}
-
 #endif /* _CDEF_BF52X_H */
diff --git a/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h b/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
index 3e00075..0947503 100644
--- a/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
+++ b/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
@@ -749,51 +749,6 @@
 #define FFE			0x20		/* Force Framing Error On Transmit	*/
 
 
-/* ***********  SERIAL PERIPHERAL INTERFACE (SPI) MASKS  ****************************/
-/* SPI_CTL Masks																	*/
-#define	TIMOD		0x0003		/* Transfer Initiate Mode							*/
-#define RDBR_CORE	0x0000		/* 		RDBR Read Initiates, IRQ When RDBR Full		*/
-#define	TDBR_CORE	0x0001		/* 		TDBR Write Initiates, IRQ When TDBR Empty	*/
-#define RDBR_DMA	0x0002		/* 		DMA Read, DMA Until FIFO Empty				*/
-#define TDBR_DMA	0x0003		/* 		DMA Write, DMA Until FIFO Full				*/
-#define SZ			0x0004		/* Send Zero (When TDBR Empty, Send Zero/Last*)		*/
-#define GM			0x0008		/* Get More (When RDBR Full, Overwrite/Discard*)	*/
-#define PSSE		0x0010		/* Slave-Select Input Enable						*/
-#define EMISO		0x0020		/* Enable MISO As Output							*/
-#define SIZE		0x0100		/* Size of Words (16/8* Bits)						*/
-#define LSBF		0x0200		/* LSB First										*/
-#define CPHA		0x0400		/* Clock Phase										*/
-#define CPOL		0x0800		/* Clock Polarity									*/
-#define MSTR		0x1000		/* Master/Slave*									*/
-#define WOM			0x2000		/* Write Open Drain Master							*/
-#define SPE			0x4000		/* SPI Enable										*/
-
-/* SPI_FLG Masks																	*/
-#define FLS1		0x0002		/* Enables SPI_FLOUT1 as SPI Slave-Select Output	*/
-#define FLS2		0x0004		/* Enables SPI_FLOUT2 as SPI Slave-Select Output	*/
-#define FLS3		0x0008		/* Enables SPI_FLOUT3 as SPI Slave-Select Output	*/
-#define FLS4		0x0010		/* Enables SPI_FLOUT4 as SPI Slave-Select Output	*/
-#define FLS5		0x0020		/* Enables SPI_FLOUT5 as SPI Slave-Select Output	*/
-#define FLS6		0x0040		/* Enables SPI_FLOUT6 as SPI Slave-Select Output	*/
-#define FLS7		0x0080		/* Enables SPI_FLOUT7 as SPI Slave-Select Output	*/
-#define FLG1		0xFDFF		/* Activates SPI_FLOUT1 							*/
-#define FLG2		0xFBFF		/* Activates SPI_FLOUT2								*/
-#define FLG3		0xF7FF		/* Activates SPI_FLOUT3								*/
-#define FLG4		0xEFFF		/* Activates SPI_FLOUT4								*/
-#define FLG5		0xDFFF		/* Activates SPI_FLOUT5								*/
-#define FLG6		0xBFFF		/* Activates SPI_FLOUT6								*/
-#define FLG7		0x7FFF		/* Activates SPI_FLOUT7								*/
-
-/* SPI_STAT Masks																				*/
-#define SPIF		0x0001		/* SPI Finished (Single-Word Transfer Complete)					*/
-#define MODF		0x0002		/* Mode Fault Error (Another Device Tried To Become Master)		*/
-#define TXE			0x0004		/* Transmission Error (Data Sent With No New Data In TDBR)		*/
-#define TXS			0x0008		/* SPI_TDBR Data Buffer Status (Full/Empty*)					*/
-#define RBSY		0x0010		/* Receive Error (Data Received With RDBR Full)					*/
-#define RXS			0x0020		/* SPI_RDBR Data Buffer Status (Full/Empty*)					*/
-#define TXCOL		0x0040		/* Transmit Collision Error (Corrupt Data May Have Been Sent)	*/
-
-
 /*  ****************  GENERAL PURPOSE TIMER MASKS  **********************/
 /* TIMER_ENABLE Masks													*/
 #define TIMEN0			0x0001		/* Enable Timer 0					*/
diff --git a/arch/blackfin/mach-bf527/include/mach/pll.h b/arch/blackfin/mach-bf527/include/mach/pll.h
new file mode 100644
index 0000000..24f1d7c
--- /dev/null
+++ b/arch/blackfin/mach-bf527/include/mach/pll.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1;
+
+	if (val == bfin_read_PLL_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SIC_IWR0);
+	iwr1 = bfin_read32(SIC_IWR1);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+	bfin_write32(SIC_IWR1, 0);
+
+	bfin_write16(PLL_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR0, iwr0);
+	bfin_write32(SIC_IWR1, iwr1);
+	hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1;
+
+	if (val == bfin_read_VR_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SIC_IWR0);
+	iwr1 = bfin_read32(SIC_IWR1);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+	bfin_write32(SIC_IWR1, 0);
+
+	bfin_write16(VR_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR0, iwr0);
+	bfin_write32(SIC_IWR1, iwr1);
+	hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
index 175371a..2ce7b16 100644
--- a/arch/blackfin/mach-bf533/boards/H8606.c
+++ b/arch/blackfin/mach-bf533/boards/H8606.c
@@ -171,7 +171,7 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -206,12 +206,12 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 16,
 		.bus_num = 1,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
 		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
@@ -347,6 +347,7 @@
 		.membase = (void *)0x20200000,
 		.mapbase = 0x20200000,
 		.irq = IRQ_PF8,
+		.irqflags = IRQF_TRIGGER_HIGH,
 		.flags = UPF_BOOT_AUTOCONF | UART_CONFIG_TYPE,
 		.iotype = UPIO_MEM,
 		.regshift = 1,
@@ -355,6 +356,7 @@
 		.membase = (void *)0x20200010,
 		.mapbase = 0x20200010,
 		.irq = IRQ_PF8,
+		.irqflags = IRQF_TRIGGER_HIGH,
 		.flags = UPF_BOOT_AUTOCONF | UART_CONFIG_TYPE,
 		.iotype = UPIO_MEM,
 		.regshift = 1,
diff --git a/arch/blackfin/mach-bf533/boards/blackstamp.c b/arch/blackfin/mach-bf533/boards/blackstamp.c
index 842b4fa..20c1022 100644
--- a/arch/blackfin/mach-bf533/boards/blackstamp.c
+++ b/arch/blackfin/mach-bf533/boards/blackstamp.c
@@ -25,6 +25,7 @@
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
 #include <asm/dpmc.h>
+#include <mach/fio_flag.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -367,8 +368,8 @@
 #include <linux/i2c-gpio.h>
 
 static struct i2c_gpio_platform_data i2c_gpio_data = {
-	.sda_pin		= 8,
-	.scl_pin		= 9,
+	.sda_pin		= GPIO_PF8,
+	.scl_pin		= GPIO_PF9,
 	.sda_is_open_drain	= 0,
 	.scl_is_open_drain	= 0,
 	.udelay			= 40,
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index fdcde61..adbe62a 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -71,7 +71,7 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -110,12 +110,12 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
 		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
@@ -400,7 +400,7 @@
 	}, {
 		.start = IRQ_PF4,
 		.end = IRQ_PF4,
-		.flags = IORESOURCE_IRQ,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	},
 };
 
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index 739773c..a1cb8e7 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -222,7 +222,7 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -261,12 +261,12 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
 		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
@@ -422,8 +422,8 @@
 #include <linux/i2c-gpio.h>
 
 static struct i2c_gpio_platform_data i2c_gpio_data = {
-	.sda_pin		= 1,
-	.scl_pin		= 0,
+	.sda_pin		= GPIO_PF1,
+	.scl_pin		= GPIO_PF0,
 	.sda_is_open_drain	= 0,
 	.scl_is_open_drain	= 0,
 	.udelay			= 40,
diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c
index 7349970..5ba4b02 100644
--- a/arch/blackfin/mach-bf533/boards/ip0x.c
+++ b/arch/blackfin/mach-bf533/boards/ip0x.c
@@ -22,6 +22,7 @@
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
+#include <mach/fio_flag.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -231,7 +232,7 @@
 	},{
 		.start = IRQ_PF11,
 		.end   = IRQ_PF11,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	},
 };
 
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index c457eaa..b3b1cde 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -24,6 +24,7 @@
 #include <asm/reboot.h>
 #include <asm/portmux.h>
 #include <asm/dpmc.h>
+#include <mach/fio_flag.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -184,7 +185,7 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -251,13 +252,15 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
+		.platform_data = "ad1836", /* only includes chip name for the moment */
 		.controller_data = &ad1836_spi_chip_info,
+		.mode = SPI_MODE_3,
 	},
 #endif
 
@@ -494,8 +497,8 @@
 #include <linux/i2c-gpio.h>
 
 static struct i2c_gpio_platform_data i2c_gpio_data = {
-	.sda_pin		= 2,
-	.scl_pin		= 3,
+	.sda_pin		= GPIO_PF2,
+	.scl_pin		= GPIO_PF3,
 	.sda_is_open_drain	= 0,
 	.scl_is_open_drain	= 0,
 	.udelay			= 40,
@@ -533,6 +536,11 @@
 		I2C_BOARD_INFO("bfin-adv7393", 0x2B),
 	},
 #endif
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
+	{
+		I2C_BOARD_INFO("ad5252", 0x2f),
+	},
+#endif
 };
 
 static const unsigned int cclk_vlev_datasheet[] =
diff --git a/arch/blackfin/mach-bf533/include/mach/cdefBF532.h b/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
index feb2392..401e524 100644
--- a/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
+++ b/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
@@ -7,11 +7,6 @@
 #ifndef _CDEF_BF532_H
 #define _CDEF_BF532_H
 
-#include <asm/blackfin.h>
-
-/*include all Core registers and bit definitions*/
-#include "defBF532.h"
-
 /*include core specific register pointer definitions*/
 #include <asm/cdef_LPBlackfin.h>
 
@@ -655,90 +650,4 @@
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-#if ANOMALY_05000311
-#define BFIN_WRITE_FIO_FLAG(name) \
-static inline void bfin_write_FIO_FLAG_##name(unsigned short val) \
-{ \
-	unsigned long flags; \
-	local_irq_save_hw(flags); \
-	bfin_write16(FIO_FLAG_##name, val); \
-	bfin_read_CHIPID(); \
-	local_irq_restore_hw(flags); \
-}
-BFIN_WRITE_FIO_FLAG(D)
-BFIN_WRITE_FIO_FLAG(C)
-BFIN_WRITE_FIO_FLAG(S)
-BFIN_WRITE_FIO_FLAG(T)
-
-#define BFIN_READ_FIO_FLAG(name) \
-static inline u16 bfin_read_FIO_FLAG_##name(void) \
-{ \
-	unsigned long flags; \
-	u16 ret; \
-	local_irq_save_hw(flags); \
-	ret = bfin_read16(FIO_FLAG_##name); \
-	bfin_read_CHIPID(); \
-	local_irq_restore_hw(flags); \
-	return ret; \
-}
-BFIN_READ_FIO_FLAG(D)
-BFIN_READ_FIO_FLAG(C)
-BFIN_READ_FIO_FLAG(S)
-BFIN_READ_FIO_FLAG(T)
-
-#else
-#define bfin_write_FIO_FLAG_D(val)           bfin_write16(FIO_FLAG_D, val)
-#define bfin_write_FIO_FLAG_C(val)           bfin_write16(FIO_FLAG_C, val)
-#define bfin_write_FIO_FLAG_S(val)           bfin_write16(FIO_FLAG_S, val)
-#define bfin_write_FIO_FLAG_T(val)           bfin_write16(FIO_FLAG_T, val)
-#define bfin_read_FIO_FLAG_T()               bfin_read16(FIO_FLAG_T)
-#define bfin_read_FIO_FLAG_C()               bfin_read16(FIO_FLAG_C)
-#define bfin_read_FIO_FLAG_S()               bfin_read16(FIO_FLAG_S)
-#define bfin_read_FIO_FLAG_D()               bfin_read16(FIO_FLAG_D)
-#endif
-
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr = bfin_read32(SIC_IWR);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR, iwr);
-	local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr = bfin_read32(SIC_IWR);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR, iwr);
-	local_irq_restore_hw(flags);
-}
-
 #endif				/* _CDEF_BF532_H */
diff --git a/arch/blackfin/mach-bf533/include/mach/defBF532.h b/arch/blackfin/mach-bf533/include/mach/defBF532.h
index 04acf1e..3adb0b4 100644
--- a/arch/blackfin/mach-bf533/include/mach/defBF532.h
+++ b/arch/blackfin/mach-bf533/include/mach/defBF532.h
@@ -681,76 +681,6 @@
 #define PF14_P        14
 #define PF15_P        15
 
-/* ***********  SERIAL PERIPHERAL INTERFACE (SPI) MASKS  **************** */
-
-/* SPI_CTL Masks */
-#define TIMOD                  0x00000003	/* Transfer initiation mode and interrupt generation */
-#define RDBR_CORE	0x0000		/* 		RDBR Read Initiates, IRQ When RDBR Full		*/
-#define	TDBR_CORE	0x0001		/* 		TDBR Write Initiates, IRQ When TDBR Empty	*/
-#define RDBR_DMA	0x0002		/* 		DMA Read, DMA Until FIFO Empty				*/
-#define TDBR_DMA	0x0003		/* 		DMA Write, DMA Until FIFO Full				*/
-#define SZ                     0x00000004	/* Send Zero (=0) or last (=1) word when TDBR empty. */
-#define GM                     0x00000008	/* When RDBR full, get more (=1) data or discard (=0) incoming Data */
-#define PSSE                   0x00000010	/* Enable (=1) Slave-Select input for Master. */
-#define EMISO                  0x00000020	/* Enable (=1) MISO pin as an output. */
-#define SIZE                   0x00000100	/* Word length (0 => 8 bits, 1 => 16 bits) */
-#define LSBF                   0x00000200	/* Data format (0 => MSB sent/received first 1 => LSB sent/received first) */
-#define CPHA                   0x00000400	/* Clock phase (0 => SPICLK starts toggling in middle of xfer, 1 => SPICLK toggles at the beginning of xfer. */
-#define CPOL                   0x00000800	/* Clock polarity (0 => active-high, 1 => active-low) */
-#define MSTR                   0x00001000	/* Configures SPI as master (=1) or slave (=0) */
-#define WOM                    0x00002000	/* Open drain (=1) data output enable (for MOSI and MISO) */
-#define SPE                    0x00004000	/* SPI module enable (=1), disable (=0) */
-
-/* SPI_FLG Masks */
-#define FLS1                   0x00000002	/* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLS2                   0x00000004	/* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLS3                   0x00000008	/* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLS4                   0x00000010	/* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLS5                   0x00000020	/* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLS6                   0x00000040	/* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLS7                   0x00000080	/* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
-#define FLG1                   0x00000200	/* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select  */
-#define FLG2                   0x00000400	/* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLG3                   0x00000800	/* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select  */
-#define FLG4                   0x00001000	/* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select  */
-#define FLG5                   0x00002000	/* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select  */
-#define FLG6                   0x00004000	/* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select  */
-#define FLG7                   0x00008000	/* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
-
-/* SPI_FLG Bit Positions */
-#define FLS1_P                 0x00000001	/* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLS2_P                 0x00000002	/* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLS3_P                 0x00000003	/* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLS4_P                 0x00000004	/* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLS5_P                 0x00000005	/* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLS6_P                 0x00000006	/* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLS7_P                 0x00000007	/* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
-#define FLG1_P                 0x00000009	/* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select  */
-#define FLG2_P                 0x0000000A	/* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLG3_P                 0x0000000B	/* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select  */
-#define FLG4_P                 0x0000000C	/* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select  */
-#define FLG5_P                 0x0000000D	/* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select  */
-#define FLG6_P                 0x0000000E	/* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select  */
-#define FLG7_P                 0x0000000F	/* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
-
-/* SPI_STAT Masks */
-#define SPIF                   0x00000001	/* Set (=1) when SPI single-word transfer complete */
-#define MODF                   0x00000002	/* Set (=1) in a master device when some other device tries to become master */
-#define TXE                    0x00000004	/* Set (=1) when transmission occurs with no new data in SPI_TDBR */
-#define TXS                    0x00000008	/* SPI_TDBR Data Buffer Status (0=Empty, 1=Full) */
-#define RBSY                   0x00000010	/* Set (=1) when data is received with RDBR full */
-#define RXS                    0x00000020	/* SPI_RDBR Data Buffer Status (0=Empty, 1=Full)  */
-#define TXCOL                  0x00000040	/* When set (=1), corrupt data may have been transmitted  */
-
-/* SPIx_FLG Masks																	*/
-#define FLG1E	0xFDFF		/* Activates SPI_FLOUT1 							*/
-#define FLG2E	0xFBFF		/* Activates SPI_FLOUT2								*/
-#define FLG3E	0xF7FF		/* Activates SPI_FLOUT3								*/
-#define FLG4E	0xEFFF		/* Activates SPI_FLOUT4								*/
-#define FLG5E	0xDFFF		/* Activates SPI_FLOUT5								*/
-#define FLG6E	0xBFFF		/* Activates SPI_FLOUT6								*/
-#define FLG7E	0x7FFF		/* Activates SPI_FLOUT7								*/
-
 /* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  ************* */
 
 /* AMGCTL Masks */
diff --git a/arch/blackfin/mach-bf533/include/mach/fio_flag.h b/arch/blackfin/mach-bf533/include/mach/fio_flag.h
new file mode 100644
index 0000000..d0bfba0
--- /dev/null
+++ b/arch/blackfin/mach-bf533/include/mach/fio_flag.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_FIO_FLAG_H
+#define _MACH_FIO_FLAG_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+#if ANOMALY_05000311
+#define BFIN_WRITE_FIO_FLAG(name) \
+static inline void bfin_write_FIO_FLAG_##name(unsigned short val) \
+{ \
+	unsigned long flags; \
+	flags = hard_local_irq_save(); \
+	bfin_write16(FIO_FLAG_##name, val); \
+	bfin_read_CHIPID(); \
+	hard_local_irq_restore(flags); \
+}
+BFIN_WRITE_FIO_FLAG(D)
+BFIN_WRITE_FIO_FLAG(C)
+BFIN_WRITE_FIO_FLAG(S)
+BFIN_WRITE_FIO_FLAG(T)
+
+#define BFIN_READ_FIO_FLAG(name) \
+static inline u16 bfin_read_FIO_FLAG_##name(void) \
+{ \
+	unsigned long flags; \
+	u16 ret; \
+	flags = hard_local_irq_save(); \
+	ret = bfin_read16(FIO_FLAG_##name); \
+	bfin_read_CHIPID(); \
+	hard_local_irq_restore(flags); \
+	return ret; \
+}
+BFIN_READ_FIO_FLAG(D)
+BFIN_READ_FIO_FLAG(C)
+BFIN_READ_FIO_FLAG(S)
+BFIN_READ_FIO_FLAG(T)
+
+#else
+#define bfin_write_FIO_FLAG_D(val)           bfin_write16(FIO_FLAG_D, val)
+#define bfin_write_FIO_FLAG_C(val)           bfin_write16(FIO_FLAG_C, val)
+#define bfin_write_FIO_FLAG_S(val)           bfin_write16(FIO_FLAG_S, val)
+#define bfin_write_FIO_FLAG_T(val)           bfin_write16(FIO_FLAG_T, val)
+#define bfin_read_FIO_FLAG_T()               bfin_read16(FIO_FLAG_T)
+#define bfin_read_FIO_FLAG_C()               bfin_read16(FIO_FLAG_C)
+#define bfin_read_FIO_FLAG_S()               bfin_read16(FIO_FLAG_S)
+#define bfin_read_FIO_FLAG_D()               bfin_read16(FIO_FLAG_D)
+#endif
+
+#endif /* _MACH_FIO_FLAG_H */
diff --git a/arch/blackfin/mach-bf533/include/mach/pll.h b/arch/blackfin/mach-bf533/include/mach/pll.h
new file mode 100644
index 0000000..169c106
--- /dev/null
+++ b/arch/blackfin/mach-bf533/include/mach/pll.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+	unsigned long flags, iwr;
+
+	if (val == bfin_read_PLL_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr = bfin_read32(SIC_IWR);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+	bfin_write16(PLL_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR, iwr);
+	hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+	unsigned long flags, iwr;
+
+	if (val == bfin_read_VR_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr = bfin_read32(SIC_IWR);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+	bfin_write16(VR_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR, iwr);
+	hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf537/Kconfig b/arch/blackfin/mach-bf537/Kconfig
index d81224f..08b2b34 100644
--- a/arch/blackfin/mach-bf537/Kconfig
+++ b/arch/blackfin/mach-bf537/Kconfig
@@ -14,8 +14,8 @@
 	int "IRQ_DMA_ERROR Generic"
 	default 7
 config IRQ_ERROR
-	int "IRQ_ERROR: CAN MAC SPORT0 SPORT1 SPI UART0 UART1"
-	default 7
+	int "IRQ_ERROR: PPI CAN MAC SPORT0 SPORT1 SPI UART0 UART1"
+	default 11
 config IRQ_RTC
 	int "IRQ_RTC"
 	default 8
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537e.c b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
index d35fc5f..e2e7be4 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537e.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
@@ -73,7 +73,7 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -112,12 +112,12 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
 		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
@@ -229,7 +229,7 @@
 	}, {
 		.start = IRQ_PG15,
 		.end = IRQ_PG15,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	},
 };
 
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537u.c b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
index d464ad5..752c833 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537u.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
@@ -74,7 +74,7 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -113,12 +113,12 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
 		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
@@ -230,7 +230,7 @@
 	}, {
 		.start = IRQ_PG15,
 		.end = IRQ_PG15,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	},
 };
 
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
index 812e8f9..6b03808 100644
--- a/arch/blackfin/mach-bf537/boards/pnav10.c
+++ b/arch/blackfin/mach-bf537/boards/pnav10.c
@@ -175,8 +175,8 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
-	|| defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -238,13 +238,13 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
-	|| defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
 		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index 68a27bc..c9e0e85 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -35,12 +35,10 @@
 #include <asm/reboot.h>
 #include <asm/portmux.h>
 #include <asm/dpmc.h>
-#ifdef CONFIG_REGULATOR_ADP_SWITCH
-#include <linux/regulator/adp_switch.h>
+#ifdef CONFIG_REGULATOR_FIXED_VOLTAGE
+#include <linux/regulator/fixed.h>
 #endif
-#ifdef CONFIG_REGULATOR_AD5398
-#include <linux/regulator/ad5398.h>
-#endif
+#include <linux/regulator/machine.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/userspace-consumer.h>
 
@@ -264,7 +262,7 @@
 	}, {
 		.start = IRQ_PF3,
 		.end = IRQ_PF3,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	},
 };
 
@@ -418,7 +416,7 @@
 static struct resource bfin_plat_nand_resources = {
 	.start = 0x20212000,
 	.end   = 0x20212000 + (1 << MAX(BFIN_NAND_PLAT_CLE, BFIN_NAND_PLAT_ALE)),
-	.flags = IORESOURCE_IO,
+	.flags = IORESOURCE_MEM,
 };
 
 static struct platform_device bfin_async_nand_device = {
@@ -545,6 +543,14 @@
 };
 #endif
 
+#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+static struct bfin5xx_spi_chip adav801_spi_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+#endif
+
 #if defined(CONFIG_INPUT_AD714X_SPI) || defined(CONFIG_INPUT_AD714X_SPI_MODULE)
 #include <linux/input/ad714x.h>
 static struct bfin5xx_spi_chip ad7147_spi_chip_info = {
@@ -693,6 +699,65 @@
 };
 #endif
 
+#if defined(CONFIG_AD7314) || defined(CONFIG_AD7314_MODULE)
+static struct bfin5xx_spi_chip ad7314_spi_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_AD7816) || defined(CONFIG_AD7816_MODULE)
+static unsigned short ad7816_platform_data[] = {
+	GPIO_PF4, /* rdwr_pin */
+	GPIO_PF5, /* convert_pin */
+	GPIO_PF7, /* busy_pin */
+	0,
+};
+
+static struct bfin5xx_spi_chip ad7816_spi_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_ADT7310) || defined(CONFIG_ADT7310_MODULE)
+static unsigned long adt7310_platform_data[3] = {
+/* INT bound temperature alarm event. line 1 */
+	IRQ_PG4, IRQF_TRIGGER_LOW,
+/* CT bound temperature alarm event irq_flags. line 0 */
+	IRQF_TRIGGER_LOW,
+};
+
+static struct bfin5xx_spi_chip adt7310_spi_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_AD7298) || defined(CONFIG_AD7298_MODULE)
+static unsigned short ad7298_platform_data[] = {
+	GPIO_PF7, /* busy_pin */
+	0,
+};
+
+static struct bfin5xx_spi_chip ad7298_spi_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_ADT7316_SPI) || defined(CONFIG_ADT7316_SPI_MODULE)
+static unsigned long adt7316_spi_data[2] = {
+	IRQF_TRIGGER_LOW, /* interrupt flags */
+	GPIO_PF7, /* ldac_pin, 0 means DAC/LDAC registers control DAC update */
+};
+
+static struct bfin5xx_spi_chip adt7316_spi_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+#endif
+
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 #define MMC_SPI_CARD_DETECT_INT IRQ_PF5
 
@@ -824,14 +889,12 @@
 static struct bfin5xx_spi_chip enc28j60_spi_chip_info = {
 	.enable_dma	= 1,
 	.bits_per_word	= 8,
-	.cs_gpio = GPIO_PF10,
 };
 #endif
 
 #if defined(CONFIG_ADF702X) || defined(CONFIG_ADF702X_MODULE)
 static struct bfin5xx_spi_chip adf7021_spi_chip_info = {
 	.bits_per_word = 16,
-	.cs_gpio = GPIO_PF10,
 };
 
 #include <linux/spi/adf702x.h>
@@ -938,6 +1001,13 @@
 };
 #endif
 
+#if defined(CONFIG_AD7476) || defined(CONFIG_AD7476_MODULE)
+static struct bfin5xx_spi_chip spi_ad7476_chip_info = {
+	.enable_dma = 0,         /* use dma transfer with this chip*/
+	.bits_per_word = 8,
+};
+#endif
+
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -982,7 +1052,7 @@
 		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = 4,/* CONFIG_SND_BLACKFIN_SPI_PFBIT */
+		.chip_select = 4,
 		.platform_data = "ad1836", /* only includes chip name for the moment */
 		.controller_data = &ad1836_spi_chip_info,
 		.mode = SPI_MODE_3,
@@ -1000,6 +1070,17 @@
 	},
 #endif
 
+#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+	{
+		.modalias = "adav80x",
+		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 1,
+		.controller_data = &adav801_spi_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
+
 #if defined(CONFIG_INPUT_AD714X_SPI) || defined(CONFIG_INPUT_AD714X_SPI_MODULE)
 	{
 		.modalias = "ad714x_captouch",
@@ -1018,6 +1099,7 @@
 		.modalias = "ad2s90",
 		.bus_num = 0,
 		.chip_select = 3,            /* change it for your board */
+		.mode = SPI_MODE_3,
 		.platform_data = NULL,
 		.controller_data = &ad2s90_spi_chip_info,
 	},
@@ -1044,6 +1126,67 @@
 	},
 #endif
 
+#if defined(CONFIG_AD7314) || defined(CONFIG_AD7314_MODULE)
+	{
+		.modalias = "ad7314",
+		.max_speed_hz = 1000000,
+		.bus_num = 0,
+		.chip_select = 4,            /* CS, change it for your board */
+		.controller_data = &ad7314_spi_chip_info,
+		.mode = SPI_MODE_1,
+	},
+#endif
+
+#if defined(CONFIG_AD7816) || defined(CONFIG_AD7816_MODULE)
+	{
+		.modalias = "ad7818",
+		.max_speed_hz = 1000000,
+		.bus_num = 0,
+		.chip_select = 4,            /* CS, change it for your board */
+		.platform_data = ad7816_platform_data,
+		.controller_data = &ad7816_spi_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
+
+#if defined(CONFIG_ADT7310) || defined(CONFIG_ADT7310_MODULE)
+	{
+		.modalias = "adt7310",
+		.max_speed_hz = 1000000,
+		.irq = IRQ_PG5,		/* CT alarm event. Line 0 */
+		.bus_num = 0,
+		.chip_select = 4,	/* CS, change it for your board */
+		.platform_data = adt7310_platform_data,
+		.controller_data = &adt7310_spi_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
+
+#if defined(CONFIG_AD7298) || defined(CONFIG_AD7298_MODULE)
+	{
+		.modalias = "ad7298",
+		.max_speed_hz = 1000000,
+		.bus_num = 0,
+		.chip_select = 4,            /* CS, change it for your board */
+		.platform_data = ad7298_platform_data,
+		.controller_data = &ad7298_spi_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
+
+#if defined(CONFIG_ADT7316_SPI) || defined(CONFIG_ADT7316_SPI_MODULE)
+	{
+		.modalias = "adt7316",
+		.max_speed_hz = 1000000,
+		.irq = IRQ_PG5,		/* interrupt line */
+		.bus_num = 0,
+		.chip_select = 4,	/* CS, change it for your board */
+		.platform_data = adt7316_spi_data,
+		.controller_data = &adt7316_spi_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
+
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
 		.modalias = "mmc_spi",
@@ -1103,7 +1246,7 @@
 		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
 		.irq = IRQ_PF6,
 		.bus_num = 0,
-		.chip_select = 0,	/* GPIO controlled SSEL */
+		.chip_select = GPIO_PF10 + MAX_CTRL_CS,	/* GPIO controlled SSEL */
 		.controller_data = &enc28j60_spi_chip_info,
 		.mode = SPI_MODE_0,
 	},
@@ -1125,7 +1268,7 @@
 		.modalias = "adf702x",
 		.max_speed_hz = 16000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = 0,	/* GPIO controlled SSEL */
+		.chip_select = GPIO_PF10 + MAX_CTRL_CS,	/* GPIO controlled SSEL */
 		.controller_data = &adf7021_spi_chip_info,
 		.platform_data = &adf7021_platform_data,
 		.mode = SPI_MODE_0,
@@ -1143,12 +1286,239 @@
 		.mode = SPI_MODE_0,
 	},
 #endif
+#if defined(CONFIG_AD7476) \
+	|| defined(CONFIG_AD7476_MODULE)
+	{
+		.modalias = "ad7476", /* Name of spi_driver for this device */
+		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0, /* Framework bus number */
+		.chip_select = 1, /* Framework chip select. */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.controller_data = &spi_ad7476_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
+#if defined(CONFIG_ADE7753) \
+	|| defined(CONFIG_ADE7753_MODULE)
+	{
+		.modalias = "ade7753",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 1, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_1,
+	},
+#endif
+#if defined(CONFIG_ADE7754) \
+	|| defined(CONFIG_ADE7754_MODULE)
+	{
+		.modalias = "ade7754",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 1, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_1,
+	},
+#endif
+#if defined(CONFIG_ADE7758) \
+	|| defined(CONFIG_ADE7758_MODULE)
+	{
+		.modalias = "ade7758",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 1, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_1,
+	},
+#endif
+#if defined(CONFIG_ADE7759) \
+	|| defined(CONFIG_ADE7759_MODULE)
+	{
+		.modalias = "ade7759",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 1, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_1,
+	},
+#endif
+#if defined(CONFIG_ADE7854_SPI) \
+	|| defined(CONFIG_ADE7854_SPI_MODULE)
+	{
+		.modalias = "ade7854",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 1, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+	},
+#endif
+#if defined(CONFIG_ADIS16060) \
+	|| defined(CONFIG_ADIS16060_MODULE)
+	{
+		.modalias = "adis16060_r",
+		.max_speed_hz = 2900000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = MAX_CTRL_CS + 1, /* CS for read, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_0,
+	},
+	{
+		.modalias = "adis16060_w",
+		.max_speed_hz = 2900000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 2, /* CS for write, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_1,
+	},
+#endif
+#if defined(CONFIG_ADIS16130) \
+	|| defined(CONFIG_ADIS16130_MODULE)
+	{
+		.modalias = "adis16130",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 1, /* CS for read, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+	},
+#endif
+#if defined(CONFIG_ADIS16201) \
+	|| defined(CONFIG_ADIS16201_MODULE)
+	{
+		.modalias = "adis16201",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 5, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+		.irq = IRQ_PF4,
+	},
+#endif
+#if defined(CONFIG_ADIS16203) \
+	|| defined(CONFIG_ADIS16203_MODULE)
+	{
+		.modalias = "adis16203",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 5, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+		.irq = IRQ_PF4,
+	},
+#endif
+#if defined(CONFIG_ADIS16204) \
+	|| defined(CONFIG_ADIS16204_MODULE)
+	{
+		.modalias = "adis16204",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 5, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+		.irq = IRQ_PF4,
+	},
+#endif
+#if defined(CONFIG_ADIS16209) \
+	|| defined(CONFIG_ADIS16209_MODULE)
+	{
+		.modalias = "adis16209",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 5, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+		.irq = IRQ_PF4,
+	},
+#endif
+#if defined(CONFIG_ADIS16220) \
+	|| defined(CONFIG_ADIS16220_MODULE)
+	{
+		.modalias = "adis16220",
+		.max_speed_hz = 2000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 5, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+		.irq = IRQ_PF4,
+	},
+#endif
+#if defined(CONFIG_ADIS16240) \
+	|| defined(CONFIG_ADIS16240_MODULE)
+	{
+		.modalias = "adis16240",
+		.max_speed_hz = 1500000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 5, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+		.irq = IRQ_PF4,
+	},
+#endif
+#if defined(CONFIG_ADIS16260) \
+	|| defined(CONFIG_ADIS16260_MODULE)
+	{
+		.modalias = "adis16260",
+		.max_speed_hz = 1500000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 5, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+		.irq = IRQ_PF4,
+	},
+#endif
+#if defined(CONFIG_ADIS16261) \
+	|| defined(CONFIG_ADIS16261_MODULE)
+	{
+		.modalias = "adis16261",
+		.max_speed_hz = 2500000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 1, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+	},
+#endif
+#if defined(CONFIG_ADIS16300) \
+	|| defined(CONFIG_ADIS16300_MODULE)
+	{
+		.modalias = "adis16300",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 5, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+		.irq = IRQ_PF4,
+	},
+#endif
+#if defined(CONFIG_ADIS16350) \
+	|| defined(CONFIG_ADIS16350_MODULE)
+	{
+		.modalias = "adis16364",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 5, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+		.irq = IRQ_PF4,
+	},
+#endif
+#if defined(CONFIG_ADIS16400) \
+	|| defined(CONFIG_ADIS16400_MODULE)
+	{
+		.modalias = "adis16400",
+		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 1, /* CS, change it for your board */
+		.platform_data = NULL, /* No spi_driver specific config */
+		.mode = SPI_MODE_3,
+	},
+#endif
 };
 
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
 /* SPI controller data */
 static struct bfin5xx_spi_master bfin_spi0_info = {
-	.num_chipselect = 8,
+	.num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS,
 	.enable_dma = 1,  /* master has the ability to do dma transfer */
 	.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
 };
@@ -1773,12 +2143,6 @@
 	.consumer_supplies     = &ad5398_consumer,
 };
 
-static struct ad5398_platform_data ad5398_i2c_platform_data = {
-	.current_bits = 10,
-	.current_offset = 4,
-	.regulator_data = &ad5398_regulator_data,
-};
-
 #if defined(CONFIG_REGULATOR_VIRTUAL_CONSUMER) || \
 	defined(CONFIG_REGULATOR_VIRTUAL_CONSUMER_MODULE)
 static struct platform_device ad5398_virt_consumer_device = {
@@ -1811,7 +2175,34 @@
 #endif
 #endif
 
+#if defined(CONFIG_ADT7410) || defined(CONFIG_ADT7410_MODULE)
+/* INT bound temperature alarm event. line 1 */
+static unsigned long adt7410_platform_data[2] = {
+	IRQ_PG4, IRQF_TRIGGER_LOW,
+};
+#endif
+
+#if defined(CONFIG_ADT7316_I2C) || defined(CONFIG_ADT7316_I2C_MODULE)
+/* INT bound temperature alarm event. line 1 */
+static unsigned long adt7316_i2c_data[2] = {
+	IRQF_TRIGGER_LOW, /* interrupt flags */
+	GPIO_PF4, /* ldac_pin, 0 means DAC/LDAC registers control DAC update */
+};
+#endif
+
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_SND_BF5XX_SOC_AD193X) || defined(CONFIG_SND_BF5XX_SOC_AD193X_MODULE)
+	{
+		I2C_BOARD_INFO("ad1937", 0x04),
+	},
+#endif
+
+#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+	{
+		I2C_BOARD_INFO("adav803", 0x10),
+	},
+#endif
+
 #if defined(CONFIG_INPUT_AD714X_I2C) || defined(CONFIG_INPUT_AD714X_I2C_MODULE)
 	{
 		I2C_BOARD_INFO("ad7142_captouch", 0x2C),
@@ -1843,12 +2234,7 @@
 	{
 		I2C_BOARD_INFO("ad7414", 0x9),
 		.irq = IRQ_PG5,
-		/*
-		 * platform_data pointer is borrwoed by the driver to
-		 * store custimer defined IRQ ALART level mode.
-		 * only IRQF_TRIGGER_HIGH and IRQF_TRIGGER_LOW are valid.
-		 */
-		.platform_data = (void *)IRQF_TRIGGER_LOW,
+		.irq_flags = IRQF_TRIGGER_LOW,
 	},
 #endif
 
@@ -1856,12 +2242,56 @@
 	{
 		I2C_BOARD_INFO("ad7417", 0xb),
 		.irq = IRQ_PG5,
-		/*
-		 * platform_data pointer is borrwoed by the driver to
-		 * store custimer defined IRQ ALART level mode.
-		 * only IRQF_TRIGGER_HIGH and IRQF_TRIGGER_LOW are valid.
-		 */
-		.platform_data = (void *)IRQF_TRIGGER_LOW,
+		.irq_flags = IRQF_TRIGGER_LOW,
+		.platform_data = (void *)GPIO_PF4,
+	},
+#endif
+
+#if defined(CONFIG_ADE7854_I2C) || defined(CONFIG_ADE7854_I2C_MODULE)
+	{
+		I2C_BOARD_INFO("ade7854", 0x38),
+	},
+#endif
+
+#if defined(CONFIG_ADT75) || defined(CONFIG_ADT75_MODULE)
+	{
+		I2C_BOARD_INFO("adt75", 0x9),
+		.irq = IRQ_PG5,
+		.irq_flags = IRQF_TRIGGER_LOW,
+	},
+#endif
+
+#if defined(CONFIG_ADT7408) || defined(CONFIG_ADT7408_MODULE)
+	{
+		I2C_BOARD_INFO("adt7408", 0x18),
+		.irq = IRQ_PG5,
+		.irq_flags = IRQF_TRIGGER_LOW,
+	},
+#endif
+
+#if defined(CONFIG_ADT7410) || defined(CONFIG_ADT7410_MODULE)
+	{
+		I2C_BOARD_INFO("adt7410", 0x48),
+		/* CT critical temperature event. line 0 */
+		.irq = IRQ_PG5,
+		.irq_flags = IRQF_TRIGGER_LOW,
+		.platform_data = (void *)&adt7410_platform_data,
+	},
+#endif
+
+#if defined(CONFIG_AD7291) || defined(CONFIG_AD7291_MODULE)
+	{
+		I2C_BOARD_INFO("ad7291", 0x20),
+		.irq = IRQ_PG5,
+		.irq_flags = IRQF_TRIGGER_LOW,
+	},
+#endif
+
+#if defined(CONFIG_ADT7316_I2C) || defined(CONFIG_ADT7316_I2C_MODULE)
+	{
+		I2C_BOARD_INFO("adt7316", 0x48),
+		.irq = IRQ_PG6,
+		.platform_data = (void *)&adt7316_i2c_data,
 	},
 #endif
 
@@ -1917,7 +2347,7 @@
 #endif
 #if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
 	{
-		I2C_BOARD_INFO("bf537-lq035-ad5280", 0x2C),
+		I2C_BOARD_INFO("bf537-lq035-ad5280", 0x2F),
 	},
 #endif
 #if defined(CONFIG_BACKLIGHT_ADP8870) || defined(CONFIG_BACKLIGHT_ADP8870_MODULE)
@@ -1954,7 +2384,7 @@
 #if defined(CONFIG_REGULATOR_AD5398) || defined(CONFIG_REGULATOR_AD5398_MODULE)
 	{
 		I2C_BOARD_INFO("ad5398", 0xC),
-		.platform_data = (void *)&ad5398_i2c_platform_data,
+		.platform_data = (void *)&ad5398_regulator_data,
 	},
 #endif
 #if defined(CONFIG_BACKLIGHT_ADP8860) || defined(CONFIG_BACKLIGHT_ADP8860_MODULE)
@@ -1963,6 +2393,16 @@
 		.platform_data = (void *)&adp8860_pdata,
 	},
 #endif
+#if defined(CONFIG_SND_SOC_ADAU1373) || defined(CONFIG_SND_SOC_ADAU1373_MODULE)
+	{
+		I2C_BOARD_INFO("adau1373", 0x1A),
+	},
+#endif
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
+	{
+		I2C_BOARD_INFO("ad5252", 0x2e),
+	},
+#endif
 };
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -2147,50 +2587,38 @@
 };
 #endif
 
-#if defined(CONFIG_REGULATOR_ADP_SWITCH) || defined(CONFIG_REGULATOR_ADP_SWITCH_MODULE)
-#define REGULATOR_ADP122        "adp122"
-#define REGULATOR_ADP150        "adp150"
+#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
+#define REGULATOR_ADP122	"adp122"
+#define REGULATOR_ADP122_UV	2500000
 
 static struct regulator_consumer_supply adp122_consumers = {
 		.supply = REGULATOR_ADP122,
 };
 
-static struct regulator_consumer_supply adp150_consumers = {
-		.supply = REGULATOR_ADP150,
+static struct regulator_init_data adp_switch_regulator_data = {
+	.constraints = {
+		.name = REGULATOR_ADP122,
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.min_uV = REGULATOR_ADP122_UV,
+		.max_uV = REGULATOR_ADP122_UV,
+		.min_uA = 0,
+		.max_uA = 300000,
+	},
+	.num_consumer_supplies = 1,	/* only 1 */
+	.consumer_supplies     = &adp122_consumers,
 };
 
-static struct regulator_init_data adp_switch_regulator_data[] = {
-	{
-		.constraints = {
-			.name = REGULATOR_ADP122,
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-			.min_uA = 0,
-			.max_uA = 300000,
-		},
-		.num_consumer_supplies = 1,	/* only 1 */
-		.consumer_supplies     = &adp122_consumers,
-		.driver_data	       = (void *)GPIO_PF2, /* gpio port only */
-	},
-	{
-		.constraints = {
-			.name = REGULATOR_ADP150,
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-			.min_uA = 0,
-			.max_uA = 150000,
-		},
-		.num_consumer_supplies = 1,	/* only 1 */
-		.consumer_supplies     = &adp150_consumers,
-		.driver_data	       = (void *)GPIO_PF3, /* gpio port only */
-	},
-};
-
-static struct adp_switch_platform_data adp_switch_pdata = {
-	.regulator_num = ARRAY_SIZE(adp_switch_regulator_data),
-	.regulator_data = adp_switch_regulator_data,
+static struct fixed_voltage_config adp_switch_pdata = {
+	.supply_name = REGULATOR_ADP122,
+	.microvolts = REGULATOR_ADP122_UV,
+	.gpio = GPIO_PF2,
+	.enable_high = 1,
+	.enabled_at_boot = 0,
+	.init_data = &adp_switch_regulator_data,
 };
 
 static struct platform_device adp_switch_device = {
-	.name = "adp_switch",
+	.name = "reg-fixed-voltage",
 	.id = 0,
 	.dev = {
 		.platform_data = &adp_switch_pdata,
@@ -2216,27 +2644,26 @@
 		.platform_data = &adp122_userspace_comsumer_data,
 	},
 };
+#endif
+#endif
 
-static struct regulator_bulk_data adp150_bulk_data = {
-	.supply = REGULATOR_ADP150,
-};
+#if defined(CONFIG_IIO_GPIO_TRIGGER) || \
+	defined(CONFIG_IIO_GPIO_TRIGGER_MODULE)
 
-static struct regulator_userspace_consumer_data adp150_userspace_comsumer_data = {
-	.name = REGULATOR_ADP150,
-	.num_supplies = 1,
-	.supplies = &adp150_bulk_data,
-};
-
-static struct platform_device adp150_userspace_consumer_device = {
-	.name = "reg-userspace-consumer",
-	.id = 1,
-	.dev = {
-		.platform_data = &adp150_userspace_comsumer_data,
+static struct resource iio_gpio_trigger_resources[] = {
+	[0] = {
+		.start  = IRQ_PF5,
+		.end    = IRQ_PF5,
+		.flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	},
 };
-#endif
-#endif
 
+static struct platform_device iio_gpio_trigger = {
+	.name = "iio_gpio_trigger",
+	.num_resources = ARRAY_SIZE(iio_gpio_trigger_resources),
+	.resource = iio_gpio_trigger_resources,
+};
+#endif
 
 static struct platform_device *stamp_devices[] __initdata = {
 
@@ -2369,14 +2796,18 @@
 #endif
 #endif
 
-#if defined(CONFIG_REGULATOR_ADP_SWITCH) || defined(CONFIG_REGULATOR_ADP_SWITCH_MODULE)
+#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
 	&adp_switch_device,
 #if defined(CONFIG_REGULATOR_USERSPACE_CONSUMER) || \
 	defined(CONFIG_REGULATOR_USERSPACE_CONSUMER_MODULE)
 	&adp122_userspace_consumer_device,
-	&adp150_userspace_consumer_device,
 #endif
 #endif
+
+#if defined(CONFIG_IIO_GPIO_TRIGGER) || \
+	defined(CONFIG_IIO_GPIO_TRIGGER_MODULE)
+	&iio_gpio_trigger,
+#endif
 };
 
 static int __init stamp_init(void)
diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
index 4f0a2e7..a4d62b5 100644
--- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
@@ -74,7 +74,7 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -113,12 +113,12 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
 		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
@@ -230,7 +230,7 @@
 	}, {
 		.start = IRQ_PG15,
 		.end = IRQ_PG15,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	},
 };
 
diff --git a/arch/blackfin/mach-bf537/include/mach/cdefBF534.h b/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
index 91825c9..fbeb35e 100644
--- a/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
+++ b/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
@@ -1750,48 +1750,4 @@
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr = bfin_read32(SIC_IWR);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR, iwr);
-	local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr = bfin_read32(SIC_IWR);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR, iwr);
-	local_irq_restore_hw(flags);
-}
-
 #endif				/* _CDEF_BF534_H */
diff --git a/arch/blackfin/mach-bf537/include/mach/defBF534.h b/arch/blackfin/mach-bf537/include/mach/defBF534.h
index 6f56907..0323e6b 100644
--- a/arch/blackfin/mach-bf537/include/mach/defBF534.h
+++ b/arch/blackfin/mach-bf537/include/mach/defBF534.h
@@ -1071,50 +1071,6 @@
 #define FPE			0x10	/* Force Parity Error On Transmit       */
 #define FFE			0x20	/* Force Framing Error On Transmit      */
 
-/* ***********  SERIAL PERIPHERAL INTERFACE (SPI) MASKS  ****************************/
-/* SPI_CTL Masks																	*/
-#define	TIMOD		0x0003	/* Transfer Initiate Mode                                                       */
-#define RDBR_CORE	0x0000	/*              RDBR Read Initiates, IRQ When RDBR Full         */
-#define	TDBR_CORE	0x0001	/*              TDBR Write Initiates, IRQ When TDBR Empty       */
-#define RDBR_DMA	0x0002	/*              DMA Read, DMA Until FIFO Empty                          */
-#define TDBR_DMA	0x0003	/*              DMA Write, DMA Until FIFO Full                          */
-#define SZ			0x0004	/* Send Zero (When TDBR Empty, Send Zero/Last*)         */
-#define GM			0x0008	/* Get More (When RDBR Full, Overwrite/Discard*)        */
-#define PSSE		0x0010	/* Slave-Select Input Enable                                            */
-#define EMISO		0x0020	/* Enable MISO As Output                                                        */
-#define SIZE		0x0100	/* Size of Words (16/8* Bits)                                           */
-#define LSBF		0x0200	/* LSB First                                                                            */
-#define CPHA		0x0400	/* Clock Phase                                                                          */
-#define CPOL		0x0800	/* Clock Polarity                                                                       */
-#define MSTR		0x1000	/* Master/Slave*                                                                        */
-#define WOM			0x2000	/* Write Open Drain Master                                                      */
-#define SPE			0x4000	/* SPI Enable                                                                           */
-
-/* SPI_FLG Masks																	*/
-#define FLS1		0x0002	/* Enables SPI_FLOUT1 as SPI Slave-Select Output        */
-#define FLS2		0x0004	/* Enables SPI_FLOUT2 as SPI Slave-Select Output        */
-#define FLS3		0x0008	/* Enables SPI_FLOUT3 as SPI Slave-Select Output        */
-#define FLS4		0x0010	/* Enables SPI_FLOUT4 as SPI Slave-Select Output        */
-#define FLS5		0x0020	/* Enables SPI_FLOUT5 as SPI Slave-Select Output        */
-#define FLS6		0x0040	/* Enables SPI_FLOUT6 as SPI Slave-Select Output        */
-#define FLS7		0x0080	/* Enables SPI_FLOUT7 as SPI Slave-Select Output        */
-#define FLG1		0xFDFF	/* Activates SPI_FLOUT1                                                         */
-#define FLG2		0xFBFF	/* Activates SPI_FLOUT2                                                         */
-#define FLG3		0xF7FF	/* Activates SPI_FLOUT3                                                         */
-#define FLG4		0xEFFF	/* Activates SPI_FLOUT4                                                         */
-#define FLG5		0xDFFF	/* Activates SPI_FLOUT5                                                         */
-#define FLG6		0xBFFF	/* Activates SPI_FLOUT6                                                         */
-#define FLG7		0x7FFF	/* Activates SPI_FLOUT7                                                         */
-
-/* SPI_STAT Masks																				*/
-#define SPIF		0x0001	/* SPI Finished (Single-Word Transfer Complete)                                 */
-#define MODF		0x0002	/* Mode Fault Error (Another Device Tried To Become Master)             */
-#define TXE			0x0004	/* Transmission Error (Data Sent With No New Data In TDBR)              */
-#define TXS			0x0008	/* SPI_TDBR Data Buffer Status (Full/Empty*)                                    */
-#define RBSY		0x0010	/* Receive Error (Data Received With RDBR Full)                                 */
-#define RXS			0x0020	/* SPI_RDBR Data Buffer Status (Full/Empty*)                                    */
-#define TXCOL		0x0040	/* Transmit Collision Error (Corrupt Data May Have Been Sent)   */
-
 /*  ****************  GENERAL PURPOSE TIMER MASKS  **********************/
 /* TIMER_ENABLE Masks													*/
 #define TIMEN0			0x0001	/* Enable Timer 0                                       */
diff --git a/arch/blackfin/mach-bf537/include/mach/pll.h b/arch/blackfin/mach-bf537/include/mach/pll.h
new file mode 100644
index 0000000..169c106
--- /dev/null
+++ b/arch/blackfin/mach-bf537/include/mach/pll.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+	unsigned long flags, iwr;
+
+	if (val == bfin_read_PLL_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr = bfin_read32(SIC_IWR);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+	bfin_write16(PLL_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR, iwr);
+	hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+	unsigned long flags, iwr;
+
+	if (val == bfin_read_VR_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr = bfin_read32(SIC_IWR);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+	bfin_write16(VR_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR, iwr);
+	hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf538/boards/ezkit.c b/arch/blackfin/mach-bf538/boards/ezkit.c
index 1a1f658..c6fb0a5 100644
--- a/arch/blackfin/mach-bf538/boards/ezkit.c
+++ b/arch/blackfin/mach-bf538/boards/ezkit.c
@@ -695,7 +695,7 @@
 };
 
 static struct bfin5xx_spi_master bf538_spi_master_info1 = {
-	.num_chipselect = 8,
+	.num_chipselect = 2,
 	.enable_dma = 1,  /* master has the ability to do dma transfer */
 	.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
 };
@@ -711,7 +711,7 @@
 };
 
 static struct bfin5xx_spi_master bf538_spi_master_info2 = {
-	.num_chipselect = 8,
+	.num_chipselect = 2,
 	.enable_dma = 1,  /* master has the ability to do dma transfer */
 	.pin_req = {P_SPI2_SCK, P_SPI2_MISO, P_SPI2_MOSI, 0},
 };
diff --git a/arch/blackfin/mach-bf538/include/mach/cdefBF538.h b/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
index 66aa722..085b06b 100644
--- a/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
+++ b/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
@@ -2027,54 +2027,4 @@
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	local_irq_restore_hw(flags);
-}
-
 #endif
diff --git a/arch/blackfin/mach-bf538/include/mach/defBF539.h b/arch/blackfin/mach-bf538/include/mach/defBF539.h
index fe43062..7a8ac5f 100644
--- a/arch/blackfin/mach-bf538/include/mach/defBF539.h
+++ b/arch/blackfin/mach-bf538/include/mach/defBF539.h
@@ -32,6 +32,7 @@
 /* System Interrupt Controller (0xFFC00100 - 0xFFC001FF) */
 #define	SWRST			0xFFC00100  /* Software	Reset Register (16-bit) */
 #define	SYSCR			0xFFC00104  /* System Configuration registe */
+#define	SIC_RVECT		0xFFC00108
 #define	SIC_IMASK0		0xFFC0010C  /* Interrupt Mask Register */
 #define	SIC_IAR0		0xFFC00110  /* Interrupt Assignment Register 0 */
 #define	SIC_IAR1		0xFFC00114  /* Interrupt Assignment Register 1 */
@@ -1894,78 +1895,6 @@
 #define	PE14_P	0xE
 #define	PE15_P	0xF
 
-
-/* ***********	SERIAL PERIPHERAL INTERFACE (SPI) MASKS	 **************** */
-/* SPIx_CTL Masks */
-#define	TIMOD		0x0003		/* Transfer Initiate Mode */
-#define	RDBR_CORE	0x0000		/*		RDBR Read Initiates, IRQ When RDBR Full */
-#define	TDBR_CORE	0x0001		/*		TDBR Write Initiates, IRQ When TDBR Empty */
-#define	RDBR_DMA	0x0002		/*		DMA Read, DMA Until FIFO Empty */
-#define	TDBR_DMA	0x0003		/*		DMA Write, DMA Until FIFO Full */
-#define	SZ			0x0004		/* Send	Zero (When TDBR	Empty, Send Zero/Last*) */
-#define	GM			0x0008		/* Get More (When RDBR Full, Overwrite/Discard*) */
-#define	PSSE		0x0010		/* Slave-Select	Input Enable */
-#define	EMISO		0x0020		/* Enable MISO As Output */
-#define	SIZE		0x0100		/* Size	of Words (16/8*	Bits) */
-#define	LSBF		0x0200		/* LSB First			 */
-#define	CPHA		0x0400		/* Clock Phase			 */
-#define	CPOL		0x0800		/* Clock Polarity		 */
-#define	MSTR		0x1000		/* Master/Slave*		 */
-#define	WOM			0x2000		/* Write Open Drain Master */
-#define	SPE			0x4000		/* SPI Enable			 */
-
-/* SPIx_FLG Masks */
-#define	FLS1	0x0002	/* Enables (=1)	SPI_FLOUT1 as flag output for SPI Slave-select */
-#define	FLS2	0x0004	/* Enables (=1)	SPI_FLOUT2 as flag output for SPI Slave-select */
-#define	FLS3	0x0008	/* Enables (=1)	SPI_FLOUT3 as flag output for SPI Slave-select */
-#define	FLS4	0x0010	/* Enables (=1)	SPI_FLOUT4 as flag output for SPI Slave-select */
-#define	FLS5	0x0020	/* Enables (=1)	SPI_FLOUT5 as flag output for SPI Slave-select */
-#define	FLS6	0x0040	/* Enables (=1)	SPI_FLOUT6 as flag output for SPI Slave-select */
-#define	FLS7	0x0080	/* Enables (=1)	SPI_FLOUT7 as flag output for SPI Slave-select */
-
-#define	FLG1	0x0200	/* Activates (=0) SPI_FLOUT1 as	flag output for	SPI Slave-select  */
-#define	FLG2	0x0400	/* Activates (=0) SPI_FLOUT2 as	flag output for	SPI Slave-select */
-#define	FLG3	0x0800	/* Activates (=0) SPI_FLOUT3 as	flag output for	SPI Slave-select  */
-#define	FLG4	0x1000	/* Activates (=0) SPI_FLOUT4 as	flag output for	SPI Slave-select  */
-#define	FLG5	0x2000	/* Activates (=0) SPI_FLOUT5 as	flag output for	SPI Slave-select  */
-#define	FLG6	0x4000	/* Activates (=0) SPI_FLOUT6 as	flag output for	SPI Slave-select  */
-#define	FLG7	0x8000	/* Activates (=0) SPI_FLOUT7 as	flag output for	SPI Slave-select */
-
-/* SPIx_FLG Bit	Positions */
-#define	FLS1_P	0x0001	/* Enables (=1)	SPI_FLOUT1 as flag output for SPI Slave-select */
-#define	FLS2_P	0x0002	/* Enables (=1)	SPI_FLOUT2 as flag output for SPI Slave-select */
-#define	FLS3_P	0x0003	/* Enables (=1)	SPI_FLOUT3 as flag output for SPI Slave-select */
-#define	FLS4_P	0x0004	/* Enables (=1)	SPI_FLOUT4 as flag output for SPI Slave-select */
-#define	FLS5_P	0x0005	/* Enables (=1)	SPI_FLOUT5 as flag output for SPI Slave-select */
-#define	FLS6_P	0x0006	/* Enables (=1)	SPI_FLOUT6 as flag output for SPI Slave-select */
-#define	FLS7_P	0x0007	/* Enables (=1)	SPI_FLOUT7 as flag output for SPI Slave-select */
-#define	FLG1_P	0x0009	/* Activates (=0) SPI_FLOUT1 as	flag output for	SPI Slave-select  */
-#define	FLG2_P	0x000A	/* Activates (=0) SPI_FLOUT2 as	flag output for	SPI Slave-select */
-#define	FLG3_P	0x000B	/* Activates (=0) SPI_FLOUT3 as	flag output for	SPI Slave-select  */
-#define	FLG4_P	0x000C	/* Activates (=0) SPI_FLOUT4 as	flag output for	SPI Slave-select  */
-#define	FLG5_P	0x000D	/* Activates (=0) SPI_FLOUT5 as	flag output for	SPI Slave-select  */
-#define	FLG6_P	0x000E	/* Activates (=0) SPI_FLOUT6 as	flag output for	SPI Slave-select  */
-#define	FLG7_P	0x000F	/* Activates (=0) SPI_FLOUT7 as	flag output for	SPI Slave-select */
-
-/* SPIx_STAT Masks */
-#define	SPIF	0x0001	/* Set (=1) when SPI single-word transfer complete */
-#define	MODF	0x0002	/* Set (=1) in a master	device when some other device tries to become master */
-#define	TXE		0x0004	/* Set (=1) when transmission occurs with no new data in SPI_TDBR */
-#define	TXS		0x0008	/* SPI_TDBR Data Buffer	Status (0=Empty, 1=Full) */
-#define	RBSY	0x0010	/* Set (=1) when data is received with RDBR full */
-#define	RXS		0x0020	/* SPI_RDBR Data Buffer	Status (0=Empty, 1=Full)  */
-#define	TXCOL	0x0040	/* When	set (=1), corrupt data may have	been transmitted  */
-
-/* SPIx_FLG Masks										 */
-#define	FLG1E	0xFDFF		/* Activates SPI_FLOUT1	 */
-#define	FLG2E	0xFBFF		/* Activates SPI_FLOUT2	 */
-#define	FLG3E	0xF7FF		/* Activates SPI_FLOUT3	 */
-#define	FLG4E	0xEFFF		/* Activates SPI_FLOUT4	 */
-#define	FLG5E	0xDFFF		/* Activates SPI_FLOUT5	 */
-#define	FLG6E	0xBFFF		/* Activates SPI_FLOUT6	 */
-#define	FLG7E	0x7FFF		/* Activates SPI_FLOUT7	 */
-
-
 /* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS	************* */
 /* EBIU_AMGCTL Masks */
 #define	AMCKEN		0x0001	/* Enable CLKOUT */
diff --git a/arch/blackfin/mach-bf538/include/mach/pll.h b/arch/blackfin/mach-bf538/include/mach/pll.h
new file mode 100644
index 0000000..b30bbcd
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/pll.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1;
+
+	if (val == bfin_read_PLL_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SIC_IWR0);
+	iwr1 = bfin_read32(SIC_IWR1);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+	bfin_write32(SIC_IWR1, 0);
+
+	bfin_write16(PLL_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR0, iwr0);
+	bfin_write32(SIC_IWR1, iwr1);
+	hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1;
+
+	if (val == bfin_read_VR_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SIC_IWR0);
+	iwr1 = bfin_read32(SIC_IWR1);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+	bfin_write32(SIC_IWR1, 0);
+
+	bfin_write16(VR_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR0, iwr0);
+	bfin_write32(SIC_IWR1, iwr1);
+	hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c
index 0c38eec..f0c0eef 100644
--- a/arch/blackfin/mach-bf548/boards/cm_bf548.c
+++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c
@@ -753,6 +753,44 @@
 };
 #endif
 
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+unsigned short bfin_can_peripherals[] = {
+	P_CAN0_RX, P_CAN0_TX, 0
+};
+
+static struct resource bfin_can_resources[] = {
+	{
+		.start = 0xFFC02A00,
+		.end = 0xFFC02FFF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_CAN0_RX,
+		.end = IRQ_CAN0_RX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN0_TX,
+		.end = IRQ_CAN0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN0_ERROR,
+		.end = IRQ_CAN0_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bfin_can_device = {
+	.name = "bfin_can",
+	.num_resources = ARRAY_SIZE(bfin_can_resources),
+	.resource = bfin_can_resources,
+	.dev = {
+		.platform_data = &bfin_can_peripherals, /* Passed to driver */
+	},
+};
+#endif
+
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
 static struct mtd_partition para_partitions[] = {
 	{
@@ -928,7 +966,7 @@
 
 /* SPI controller data */
 static struct bfin5xx_spi_master bf54x_spi_master_info0 = {
-	.num_chipselect = 3,
+	.num_chipselect = 4,
 	.enable_dma = 1,  /* master has the ability to do dma transfer */
 	.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
 };
@@ -944,7 +982,7 @@
 };
 
 static struct bfin5xx_spi_master bf54x_spi_master_info1 = {
-	.num_chipselect = 3,
+	.num_chipselect = 4,
 	.enable_dma = 1,  /* master has the ability to do dma transfer */
 	.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
 };
@@ -1152,6 +1190,11 @@
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
 	&para_flash_device,
 #endif
+
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+	&bfin_can_device,
+#endif
+
 };
 
 static int __init cm_bf548_init(void)
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 56682a3..216e269 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -837,8 +837,12 @@
 #if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
 static struct mtd_partition partition_info[] = {
 	{
-		.name = "linux kernel(nand)",
+		.name = "bootloader(nand)",
 		.offset = 0,
+		.size = 0x80000,
+	}, {
+		.name = "linux kernel(nand)",
+		.offset = MTDPART_OFS_APPEND,
 		.size = 4 * 1024 * 1024,
 	},
 	{
@@ -901,7 +905,7 @@
 static struct mtd_partition ezkit_partitions[] = {
 	{
 		.name       = "bootloader(nor)",
-		.size       = 0x40000,
+		.size       = 0x80000,
 		.offset     = 0,
 	}, {
 		.name       = "linux kernel(nor)",
@@ -943,7 +947,7 @@
 static struct mtd_partition bfin_spi_flash_partitions[] = {
 	{
 		.name = "bootloader(spi)",
-		.size = 0x00040000,
+		.size = 0x00080000,
 		.offset = 0,
 		.mask_flags = MTD_CAP_ROM
 	}, {
@@ -966,8 +970,8 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
-	|| defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -1023,13 +1027,13 @@
 		.mode = SPI_MODE_3,
 	},
 #endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
-	|| defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 1,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
 		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
@@ -1107,7 +1111,7 @@
 
 /* SPI controller data */
 static struct bfin5xx_spi_master bf54x_spi_master_info0 = {
-	.num_chipselect = 3,
+	.num_chipselect = 4,
 	.enable_dma = 1,  /* master has the ability to do dma transfer */
 	.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
 };
@@ -1123,7 +1127,7 @@
 };
 
 static struct bfin5xx_spi_master bf54x_spi_master_info1 = {
-	.num_chipselect = 3,
+	.num_chipselect = 4,
 	.enable_dma = 1,  /* master has the ability to do dma transfer */
 	.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
 };
@@ -1206,6 +1210,11 @@
 		.platform_data = (void *)&adxl34x_info,
 	},
 #endif
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
+	{
+		I2C_BOARD_INFO("ad5252", 0x2f),
+	},
+#endif
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf548/dma.c b/arch/blackfin/mach-bf548/dma.c
index 039a6d9..888b9cc 100644
--- a/arch/blackfin/mach-bf548/dma.c
+++ b/arch/blackfin/mach-bf548/dma.c
@@ -63,6 +63,7 @@
 		break;
 	case CH_SPORT1_TX:
 		ret_irq = IRQ_SPORT1_TX;
+		break;
 	case CH_SPI0:
 		ret_irq = IRQ_SPI0;
 		break;
diff --git a/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h b/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
index ea3ec4e..deaf5d6 100644
--- a/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
+++ b/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
@@ -40,6 +40,8 @@
 
 /* SIC Registers */
 
+#define bfin_read_SIC_RVECT()		bfin_read32(SIC_RVECT)
+#define bfin_write_SIC_RVECT(val)	bfin_write32(SIC_RVECT, val)
 #define bfin_read_SIC_IMASK0()		bfin_read32(SIC_IMASK0)
 #define bfin_write_SIC_IMASK0(val)	bfin_write32(SIC_IMASK0, val)
 #define bfin_read_SIC_IMASK1()		bfin_read32(SIC_IMASK1)
@@ -2648,61 +2650,5 @@
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1, iwr2;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	iwr2 = bfin_read32(SIC_IWR2);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-	bfin_write32(SIC_IWR2, 0);
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	bfin_write32(SIC_IWR2, iwr2);
-	local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1, iwr2;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SIC_IWR0);
-	iwr1 = bfin_read32(SIC_IWR1);
-	iwr2 = bfin_read32(SIC_IWR2);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
-	bfin_write32(SIC_IWR1, 0);
-	bfin_write32(SIC_IWR2, 0);
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SIC_IWR0, iwr0);
-	bfin_write32(SIC_IWR1, iwr1);
-	bfin_write32(SIC_IWR2, iwr2);
-	local_irq_restore_hw(flags);
-}
-
 #endif /* _CDEF_BF54X_H */
 
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h b/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
index 7866197..78f9110 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
@@ -35,6 +35,7 @@
 
 /* SIC Registers */
 
+#define                        SIC_RVECT  0xffc00108
 #define                       SIC_IMASK0  0xffc0010c   /* System Interrupt Mask Register 0 */
 #define                       SIC_IMASK1  0xffc00110   /* System Interrupt Mask Register 1 */
 #define                       SIC_IMASK2  0xffc00114   /* System Interrupt Mask Register 2 */
@@ -2061,56 +2062,6 @@
 #define                  LOW_EVEN  0xff0000   /* Lower Limit for Even Bytes (Luma) */
 #define                 HIGH_EVEN  0xff000000 /* Upper Limit for Even Bytes (Luma) */
 
-/* Bit masks for SPIx_BAUD */
-
-#define                  SPI_BAUD  0xffff     /* Baud Rate */
-
-/* Bit masks for SPIx_CTL */
-
-#define                       SPE  0x4000     /* SPI Enable */
-#define                       WOM  0x2000     /* Write Open Drain Master */
-#define                      MSTR  0x1000     /* Master Mode */
-#define                      CPOL  0x800      /* Clock Polarity */
-#define                      CPHA  0x400      /* Clock Phase */
-#define                      LSBF  0x200      /* LSB First */
-#define                      SIZE  0x100      /* Size of Words */
-#define                     EMISO  0x20       /* Enable MISO Output */
-#define                      PSSE  0x10       /* Slave-Select Enable */
-#define                        GM  0x8        /* Get More Data */
-#define                        SZ  0x4        /* Send Zero */
-#define                     TIMOD  0x3        /* Transfer Initiation Mode */
-
-/* Bit masks for SPIx_FLG */
-
-#define                      FLS1  0x2        /* Slave Select Enable 1 */
-#define                      FLS2  0x4        /* Slave Select Enable 2 */
-#define                      FLS3  0x8        /* Slave Select Enable 3 */
-#define                      FLG1  0x200      /* Slave Select Value 1 */
-#define                      FLG2  0x400      /* Slave Select Value 2 */
-#define                      FLG3  0x800      /* Slave Select Value 3 */
-
-/* Bit masks for SPIx_STAT */
-
-#define                     TXCOL  0x40       /* Transmit Collision Error */
-#define                       RXS  0x20       /* RDBR Data Buffer Status */
-#define                      RBSY  0x10       /* Receive Error */
-#define                       TXS  0x8        /* TDBR Data Buffer Status */
-#define                       TXE  0x4        /* Transmission Error */
-#define                      MODF  0x2        /* Mode Fault Error */
-#define                      SPIF  0x1        /* SPI Finished */
-
-/* Bit masks for SPIx_TDBR */
-
-#define                      TDBR  0xffff     /* Transmit Data Buffer */
-
-/* Bit masks for SPIx_RDBR */
-
-#define                      RDBR  0xffff     /* Receive Data Buffer */
-
-/* Bit masks for SPIx_SHADOW */
-
-#define                    SHADOW  0xffff     /* RDBR Shadow */
-
 /* ************************************************ */
 /* The TWI bit masks fields are from the ADSP-BF538 */
 /* and they have not been verified as the final     */
diff --git a/arch/blackfin/mach-bf548/include/mach/pll.h b/arch/blackfin/mach-bf548/include/mach/pll.h
new file mode 100644
index 0000000..7865a09
--- /dev/null
+++ b/arch/blackfin/mach-bf548/include/mach/pll.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1, iwr2;
+
+	if (val == bfin_read_PLL_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SIC_IWR0);
+	iwr1 = bfin_read32(SIC_IWR1);
+	iwr2 = bfin_read32(SIC_IWR2);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+	bfin_write32(SIC_IWR1, 0);
+	bfin_write32(SIC_IWR2, 0);
+
+	bfin_write16(PLL_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR0, iwr0);
+	bfin_write32(SIC_IWR1, iwr1);
+	bfin_write32(SIC_IWR2, iwr2);
+	hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1, iwr2;
+
+	if (val == bfin_read_VR_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SIC_IWR0);
+	iwr1 = bfin_read32(SIC_IWR1);
+	iwr2 = bfin_read32(SIC_IWR2);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+	bfin_write32(SIC_IWR1, 0);
+	bfin_write32(SIC_IWR2, 0);
+
+	bfin_write16(VR_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SIC_IWR0, iwr0);
+	bfin_write32(SIC_IWR1, iwr1);
+	bfin_write32(SIC_IWR2, iwr2);
+	hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf561/boards/acvilon.c b/arch/blackfin/mach-bf561/boards/acvilon.c
index 35b6d12..0b1c20f 100644
--- a/arch/blackfin/mach-bf561/boards/acvilon.c
+++ b/arch/blackfin/mach-bf561/boards/acvilon.c
@@ -302,7 +302,7 @@
 static struct resource bfin_plat_nand_resources = {
 	.start = 0x24000000,
 	.end = 0x24000000 + (1 << MAX(BFIN_NAND_PLAT_CLE, BFIN_NAND_PLAT_ALE)),
-	.flags = IORESOURCE_IO,
+	.flags = IORESOURCE_MEM,
 };
 
 static struct platform_device bfin_async_nand_device = {
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index e127aed..087b6b0 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -72,7 +72,7 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -111,12 +111,12 @@
 	},
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
 		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
@@ -278,7 +278,7 @@
 	}, {
 		.start = IRQ_PF47,
 		.end = IRQ_PF47,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	},
 };
 
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 9b93e2f..ab7a487 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -14,6 +14,7 @@
 #include <linux/spi/spi.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
@@ -74,7 +75,7 @@
 	}, {
 		.start = IRQ_PF8,
 		.end = IRQ_PF8,
-		.flags = IORESOURCE_IRQ,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	},
 };
 
@@ -274,8 +275,8 @@
 };
 #endif
 
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
-	|| defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
@@ -328,14 +329,16 @@
 #endif
 
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
-	|| defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
-		.modalias = "ad1836",
+		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
-		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+		.chip_select = 4,
+		.platform_data = "ad1836", /* only includes chip name for the moment */
 		.controller_data = &ad1836_spi_chip_info,
+		.mode = SPI_MODE_3,
 	},
 #endif
 #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
@@ -377,8 +380,8 @@
 #include <linux/i2c-gpio.h>
 
 static struct i2c_gpio_platform_data i2c_gpio_data = {
-	.sda_pin		= 1,
-	.scl_pin		= 0,
+	.sda_pin		= GPIO_PF1,
+	.scl_pin		= GPIO_PF0,
 	.sda_is_open_drain	= 0,
 	.scl_is_open_drain	= 0,
 	.udelay			= 40,
@@ -420,6 +423,30 @@
 	},
 };
 
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s = {
+	.name = "bfin-i2s",
+	.id = CONFIG_SND_BF5XX_SPORT_NUM,
+	/* TODO: add platform data here */
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+static struct platform_device bfin_tdm = {
+	.name = "bfin-tdm",
+	.id = CONFIG_SND_BF5XX_SPORT_NUM,
+	/* TODO: add platform data here */
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+static struct platform_device bfin_ac97 = {
+	.name = "bfin-ac97",
+	.id = CONFIG_SND_BF5XX_SPORT_NUM,
+	/* TODO: add platform data here */
+};
+#endif
+
 static struct platform_device *ezkit_devices[] __initdata = {
 
 	&bfin_dpmc,
@@ -467,6 +494,18 @@
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
 	&ezkit_flash_device,
 #endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+	&bfin_i2s,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+	&bfin_tdm,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+	&bfin_ac97,
+#endif
 };
 
 static int __init ezkit_init(void)
@@ -484,6 +523,17 @@
 	SSYNC();
 #endif
 
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
+	bfin_write_FIO0_DIR(bfin_read_FIO0_DIR() | (1 << 15));
+	bfin_write_FIO0_FLAG_S(1 << 15);
+	SSYNC();
+	/*
+	 * This initialization lasts for approximately 4500 MCLKs.
+	 * MCLK = 12.288MHz
+	 */
+	udelay(400);
+#endif
+
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf561/coreb.c b/arch/blackfin/mach-bf561/coreb.c
index deb2271..78ecb50 100644
--- a/arch/blackfin/mach-bf561/coreb.c
+++ b/arch/blackfin/mach-bf561/coreb.c
@@ -18,9 +18,9 @@
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 
-#define CMD_COREB_START		2
-#define CMD_COREB_STOP		3
-#define CMD_COREB_RESET		4
+#define CMD_COREB_START		_IO('b', 0)
+#define CMD_COREB_STOP		_IO('b', 1)
+#define CMD_COREB_RESET		_IO('b', 2)
 
 static long
 coreb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -29,10 +29,10 @@
 
 	switch (cmd) {
 	case CMD_COREB_START:
-		bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~0x0020);
+		bfin_write_SYSCR(bfin_read_SYSCR() & ~0x0020);
 		break;
 	case CMD_COREB_STOP:
-		bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() | 0x0020);
+		bfin_write_SYSCR(bfin_read_SYSCR() | 0x0020);
 		bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | 0x0080);
 		break;
 	case CMD_COREB_RESET:
@@ -51,6 +51,7 @@
 static const struct file_operations coreb_fops = {
 	.owner          = THIS_MODULE,
 	.unlocked_ioctl = coreb_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice coreb_dev = {
@@ -73,3 +74,4 @@
 
 MODULE_AUTHOR("Bas Vermeulen <bvermeul@blackstar.xs4all.nl>");
 MODULE_DESCRIPTION("BF561 Core B Support");
+MODULE_LICENSE("GPL");
diff --git a/arch/blackfin/mach-bf561/include/mach/blackfin.h b/arch/blackfin/mach-bf561/include/mach/blackfin.h
index 67d6bdc..6c7dc58 100644
--- a/arch/blackfin/mach-bf561/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf561/include/mach/blackfin.h
@@ -24,29 +24,16 @@
 #define bfin_read_FIO_INEN() bfin_read_FIO0_INEN()
 #define bfin_write_FIO_INEN(val) bfin_write_FIO0_INEN(val)
 
-#define SIC_IWR0 SICA_IWR0
-#define SIC_IWR1 SICA_IWR1
-#define SIC_IAR0 SICA_IAR0
-#define bfin_write_SIC_IMASK0 bfin_write_SICA_IMASK0
-#define bfin_write_SIC_IMASK1 bfin_write_SICA_IMASK1
-#define bfin_write_SIC_IWR0   bfin_write_SICA_IWR0
-#define bfin_write_SIC_IWR1   bfin_write_SICA_IWR1
-
-#define bfin_read_SIC_IMASK0 bfin_read_SICA_IMASK0
-#define bfin_read_SIC_IMASK1 bfin_read_SICA_IMASK1
-#define bfin_read_SIC_IWR0   bfin_read_SICA_IWR0
-#define bfin_read_SIC_IWR1   bfin_read_SICA_IWR1
-#define bfin_read_SIC_ISR0   bfin_read_SICA_ISR0
-#define bfin_read_SIC_ISR1   bfin_read_SICA_ISR1
-
-#define bfin_read_SIC_IMASK(x)		bfin_read32(SICA_IMASK0 + (x << 2))
-#define bfin_write_SIC_IMASK(x, val)	bfin_write32((SICA_IMASK0 + (x << 2)), val)
-#define bfin_read_SICB_IMASK(x)		bfin_read32(SICB_IMASK0 + (x << 2))
-#define bfin_write_SICB_IMASK(x, val)	bfin_write32((SICB_IMASK0 + (x << 2)), val)
-#define bfin_read_SIC_ISR(x)		bfin_read32(SICA_ISR0 + (x << 2))
-#define bfin_write_SIC_ISR(x, val)	bfin_write32((SICA_ISR0 + (x << 2)), val)
-#define bfin_read_SICB_ISR(x)		bfin_read32(SICB_ISR0 + (x << 2))
-#define bfin_write_SICB_ISR(x, val)	bfin_write32((SICB_ISR0 + (x << 2)), val)
+/* Weird muxer funcs which pick SIC regs from IMASK base */
+#define __SIC_MUX(base, x)		((base) + ((x) << 2))
+#define bfin_read_SIC_IMASK(x)		bfin_read32(__SIC_MUX(SIC_IMASK0, x))
+#define bfin_write_SIC_IMASK(x, val)	bfin_write32(__SIC_MUX(SIC_IMASK0, x), val)
+#define bfin_read_SICB_IMASK(x)		bfin_read32(__SIC_MUX(SICB_IMASK0, x))
+#define bfin_write_SICB_IMASK(x, val)	bfin_write32(__SIC_MUX(SICB_IMASK0, x), val)
+#define bfin_read_SIC_ISR(x)		bfin_read32(__SIC_MUX(SIC_ISR0, x))
+#define bfin_write_SIC_ISR(x, val)	bfin_write32(__SIC_MUX(SIC_ISR0, x), val)
+#define bfin_read_SICB_ISR(x)		bfin_read32(__SIC_MUX(SICB_ISR0, x))
+#define bfin_write_SICB_ISR(x, val)	bfin_write32(__SIC_MUX(SICB_ISR0, x), val)
 
 #define BFIN_UART_NR_PORTS      1
 
diff --git a/arch/blackfin/mach-bf561/include/mach/cdefBF561.h b/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
index 81ecdb7..2bab991 100644
--- a/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
+++ b/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
@@ -30,49 +30,41 @@
 #define bfin_write_PLL_LOCKCNT(val)          bfin_write16(PLL_LOCKCNT,val)
 #define bfin_read_CHIPID()                   bfin_read32(CHIPID)
 
-/* For MMR's that are reserved on Core B, set up defines to better integrate with other ports */
-#define bfin_read_SWRST()                    bfin_read_SICA_SWRST()
-#define bfin_write_SWRST(val)                bfin_write_SICA_SWRST(val)
-#define bfin_read_SYSCR()                    bfin_read_SICA_SYSCR()
-#define bfin_write_SYSCR(val)                bfin_write_SICA_SYSCR(val)
-
 /* System Reset and Interrupt Controller registers for core A (0xFFC0 0100-0xFFC0 01FF) */
-#define bfin_read_SICA_SWRST()               bfin_read16(SICA_SWRST)
-#define bfin_write_SICA_SWRST(val)           bfin_write16(SICA_SWRST,val)
-#define bfin_read_SICA_SYSCR()               bfin_read16(SICA_SYSCR)
-#define bfin_write_SICA_SYSCR(val)           bfin_write16(SICA_SYSCR,val)
-#define bfin_read_SICA_RVECT()               bfin_read16(SICA_RVECT)
-#define bfin_write_SICA_RVECT(val)           bfin_write16(SICA_RVECT,val)
-#define bfin_read_SICA_IMASK()               bfin_read32(SICA_IMASK)
-#define bfin_write_SICA_IMASK(val)           bfin_write32(SICA_IMASK,val)
-#define bfin_read_SICA_IMASK0()              bfin_read32(SICA_IMASK0)
-#define bfin_write_SICA_IMASK0(val)          bfin_write32(SICA_IMASK0,val)
-#define bfin_read_SICA_IMASK1()              bfin_read32(SICA_IMASK1)
-#define bfin_write_SICA_IMASK1(val)          bfin_write32(SICA_IMASK1,val)
-#define bfin_read_SICA_IAR0()                bfin_read32(SICA_IAR0)
-#define bfin_write_SICA_IAR0(val)            bfin_write32(SICA_IAR0,val)
-#define bfin_read_SICA_IAR1()                bfin_read32(SICA_IAR1)
-#define bfin_write_SICA_IAR1(val)            bfin_write32(SICA_IAR1,val)
-#define bfin_read_SICA_IAR2()                bfin_read32(SICA_IAR2)
-#define bfin_write_SICA_IAR2(val)            bfin_write32(SICA_IAR2,val)
-#define bfin_read_SICA_IAR3()                bfin_read32(SICA_IAR3)
-#define bfin_write_SICA_IAR3(val)            bfin_write32(SICA_IAR3,val)
-#define bfin_read_SICA_IAR4()                bfin_read32(SICA_IAR4)
-#define bfin_write_SICA_IAR4(val)            bfin_write32(SICA_IAR4,val)
-#define bfin_read_SICA_IAR5()                bfin_read32(SICA_IAR5)
-#define bfin_write_SICA_IAR5(val)            bfin_write32(SICA_IAR5,val)
-#define bfin_read_SICA_IAR6()                bfin_read32(SICA_IAR6)
-#define bfin_write_SICA_IAR6(val)            bfin_write32(SICA_IAR6,val)
-#define bfin_read_SICA_IAR7()                bfin_read32(SICA_IAR7)
-#define bfin_write_SICA_IAR7(val)            bfin_write32(SICA_IAR7,val)
-#define bfin_read_SICA_ISR0()                bfin_read32(SICA_ISR0)
-#define bfin_write_SICA_ISR0(val)            bfin_write32(SICA_ISR0,val)
-#define bfin_read_SICA_ISR1()                bfin_read32(SICA_ISR1)
-#define bfin_write_SICA_ISR1(val)            bfin_write32(SICA_ISR1,val)
-#define bfin_read_SICA_IWR0()                bfin_read32(SICA_IWR0)
-#define bfin_write_SICA_IWR0(val)            bfin_write32(SICA_IWR0,val)
-#define bfin_read_SICA_IWR1()                bfin_read32(SICA_IWR1)
-#define bfin_write_SICA_IWR1(val)            bfin_write32(SICA_IWR1,val)
+#define bfin_read_SWRST()                    bfin_read16(SWRST)
+#define bfin_write_SWRST(val)                bfin_write16(SWRST,val)
+#define bfin_read_SYSCR()                    bfin_read16(SYSCR)
+#define bfin_write_SYSCR(val)                bfin_write16(SYSCR,val)
+#define bfin_read_SIC_RVECT()                bfin_read16(SIC_RVECT)
+#define bfin_write_SIC_RVECT(val)            bfin_write16(SIC_RVECT,val)
+#define bfin_read_SIC_IMASK0()               bfin_read32(SIC_IMASK0)
+#define bfin_write_SIC_IMASK0(val)           bfin_write32(SIC_IMASK0,val)
+#define bfin_read_SIC_IMASK1()               bfin_read32(SIC_IMASK1)
+#define bfin_write_SIC_IMASK1(val)           bfin_write32(SIC_IMASK1,val)
+#define bfin_read_SIC_IAR0()                 bfin_read32(SIC_IAR0)
+#define bfin_write_SIC_IAR0(val)             bfin_write32(SIC_IAR0,val)
+#define bfin_read_SIC_IAR1()                 bfin_read32(SIC_IAR1)
+#define bfin_write_SIC_IAR1(val)             bfin_write32(SIC_IAR1,val)
+#define bfin_read_SIC_IAR2()                 bfin_read32(SIC_IAR2)
+#define bfin_write_SIC_IAR2(val)             bfin_write32(SIC_IAR2,val)
+#define bfin_read_SIC_IAR3()                 bfin_read32(SIC_IAR3)
+#define bfin_write_SIC_IAR3(val)             bfin_write32(SIC_IAR3,val)
+#define bfin_read_SIC_IAR4()                 bfin_read32(SIC_IAR4)
+#define bfin_write_SIC_IAR4(val)             bfin_write32(SIC_IAR4,val)
+#define bfin_read_SIC_IAR5()                 bfin_read32(SIC_IAR5)
+#define bfin_write_SIC_IAR5(val)             bfin_write32(SIC_IAR5,val)
+#define bfin_read_SIC_IAR6()                 bfin_read32(SIC_IAR6)
+#define bfin_write_SIC_IAR6(val)             bfin_write32(SIC_IAR6,val)
+#define bfin_read_SIC_IAR7()                 bfin_read32(SIC_IAR7)
+#define bfin_write_SIC_IAR7(val)             bfin_write32(SIC_IAR7,val)
+#define bfin_read_SIC_ISR0()                 bfin_read32(SIC_ISR0)
+#define bfin_write_SIC_ISR0(val)             bfin_write32(SIC_ISR0,val)
+#define bfin_read_SIC_ISR1()                 bfin_read32(SIC_ISR1)
+#define bfin_write_SIC_ISR1(val)             bfin_write32(SIC_ISR1,val)
+#define bfin_read_SIC_IWR0()                 bfin_read32(SIC_IWR0)
+#define bfin_write_SIC_IWR0(val)             bfin_write32(SIC_IWR0,val)
+#define bfin_read_SIC_IWR1()                 bfin_read32(SIC_IWR1)
+#define bfin_write_SIC_IWR1(val)             bfin_write32(SIC_IWR1,val)
 
 /* System Reset and Interrupt Controller registers for Core B (0xFFC0 1100-0xFFC0 11FF) */
 #define bfin_read_SICB_SWRST()               bfin_read16(SICB_SWRST)
@@ -1534,54 +1526,4 @@
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_PLL_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SICA_IWR0);
-	iwr1 = bfin_read32(SICA_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SICA_IWR0, IWR_ENABLE(0));
-	bfin_write32(SICA_IWR1, 0);
-
-	bfin_write16(PLL_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SICA_IWR0, iwr0);
-	bfin_write32(SICA_IWR1, iwr1);
-	local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
-	unsigned long flags, iwr0, iwr1;
-
-	if (val == bfin_read_VR_CTL())
-		return;
-
-	local_irq_save_hw(flags);
-	/* Enable the PLL Wakeup bit in SIC IWR */
-	iwr0 = bfin_read32(SICA_IWR0);
-	iwr1 = bfin_read32(SICA_IWR1);
-	/* Only allow PPL Wakeup) */
-	bfin_write32(SICA_IWR0, IWR_ENABLE(0));
-	bfin_write32(SICA_IWR1, 0);
-
-	bfin_write16(VR_CTL, val);
-	SSYNC();
-	asm("IDLE;");
-
-	bfin_write32(SICA_IWR0, iwr0);
-	bfin_write32(SICA_IWR1, iwr1);
-	local_irq_restore_hw(flags);
-}
-
 #endif				/* _CDEF_BF561_H */
diff --git a/arch/blackfin/mach-bf561/include/mach/defBF561.h b/arch/blackfin/mach-bf561/include/mach/defBF561.h
index 2674f00..79e048d 100644
--- a/arch/blackfin/mach-bf561/include/mach/defBF561.h
+++ b/arch/blackfin/mach-bf561/include/mach/defBF561.h
@@ -28,32 +28,29 @@
 #define CHIPID                 0xFFC00014       /* Chip ID Register */
 
 /* For MMR's that are reserved on Core B, set up defines to better integrate with other ports */
-#define SWRST                   SICA_SWRST
-#define SYSCR                   SICA_SYSCR
 #define DOUBLE_FAULT            (DOUBLE_FAULT_B|DOUBLE_FAULT_A)
 #define RESET_DOUBLE            (SWRST_DBL_FAULT_B|SWRST_DBL_FAULT_A)
 #define RESET_WDOG              (SWRST_WDT_B|SWRST_WDT_A)
 #define RESET_SOFTWARE          (SWRST_OCCURRED)
 
 /* System Reset and Interrupt Controller registers for core A (0xFFC0 0100-0xFFC0 01FF) */
-#define SICA_SWRST              0xFFC00100	/* Software Reset register */
-#define SICA_SYSCR              0xFFC00104	/* System Reset Configuration register */
-#define SICA_RVECT              0xFFC00108	/* SIC Reset Vector Address Register */
-#define SICA_IMASK              0xFFC0010C	/* SIC Interrupt Mask register 0 - hack to fix old tests */
-#define SICA_IMASK0             0xFFC0010C	/* SIC Interrupt Mask register 0 */
-#define SICA_IMASK1             0xFFC00110	/* SIC Interrupt Mask register 1 */
-#define SICA_IAR0               0xFFC00124	/* SIC Interrupt Assignment Register 0 */
-#define SICA_IAR1               0xFFC00128	/* SIC Interrupt Assignment Register 1 */
-#define SICA_IAR2               0xFFC0012C	/* SIC Interrupt Assignment Register 2 */
-#define SICA_IAR3               0xFFC00130	/* SIC Interrupt Assignment Register 3 */
-#define SICA_IAR4               0xFFC00134	/* SIC Interrupt Assignment Register 4 */
-#define SICA_IAR5               0xFFC00138	/* SIC Interrupt Assignment Register 5 */
-#define SICA_IAR6               0xFFC0013C	/* SIC Interrupt Assignment Register 6 */
-#define SICA_IAR7               0xFFC00140	/* SIC Interrupt Assignment Register 7 */
-#define SICA_ISR0               0xFFC00114	/* SIC Interrupt Status register 0 */
-#define SICA_ISR1               0xFFC00118	/* SIC Interrupt Status register 1 */
-#define SICA_IWR0               0xFFC0011C	/* SIC Interrupt Wakeup-Enable register 0 */
-#define SICA_IWR1               0xFFC00120	/* SIC Interrupt Wakeup-Enable register 1 */
+#define SWRST                   0xFFC00100	/* Software Reset register */
+#define SYSCR                   0xFFC00104	/* System Reset Configuration register */
+#define SIC_RVECT               0xFFC00108	/* SIC Reset Vector Address Register */
+#define SIC_IMASK0              0xFFC0010C	/* SIC Interrupt Mask register 0 */
+#define SIC_IMASK1              0xFFC00110	/* SIC Interrupt Mask register 1 */
+#define SIC_IAR0                0xFFC00124	/* SIC Interrupt Assignment Register 0 */
+#define SIC_IAR1                0xFFC00128	/* SIC Interrupt Assignment Register 1 */
+#define SIC_IAR2                0xFFC0012C	/* SIC Interrupt Assignment Register 2 */
+#define SIC_IAR3                0xFFC00130	/* SIC Interrupt Assignment Register 3 */
+#define SIC_IAR4                0xFFC00134	/* SIC Interrupt Assignment Register 4 */
+#define SIC_IAR5                0xFFC00138	/* SIC Interrupt Assignment Register 5 */
+#define SIC_IAR6                0xFFC0013C	/* SIC Interrupt Assignment Register 6 */
+#define SIC_IAR7                0xFFC00140	/* SIC Interrupt Assignment Register 7 */
+#define SIC_ISR0                0xFFC00114	/* SIC Interrupt Status register 0 */
+#define SIC_ISR1                0xFFC00118	/* SIC Interrupt Status register 1 */
+#define SIC_IWR0                0xFFC0011C	/* SIC Interrupt Wakeup-Enable register 0 */
+#define SIC_IWR1                0xFFC00120	/* SIC Interrupt Wakeup-Enable register 1 */
 
 /* System Reset and Interrupt Controller registers for Core B (0xFFC0 1100-0xFFC0 11FF) */
 #define SICB_SWRST              0xFFC01100	/* reserved */
@@ -1271,63 +1268,6 @@
 #define PF14_P        14
 #define PF15_P        15
 
-/* ***********  SERIAL PERIPHERAL INTERFACE (SPI) MASKS  **************** */
-
-/* SPI_CTL Masks */
-#define TIMOD                  0x00000003	/* Transfer initiation mode and interrupt generation */
-#define SZ                     0x00000004	/* Send Zero (=0) or last (=1) word when TDBR empty. */
-#define GM                     0x00000008	/* When RDBR full, get more (=1) data or discard (=0) incoming Data */
-#define PSSE                   0x00000010	/* Enable (=1) Slave-Select input for Master. */
-#define EMISO                  0x00000020	/* Enable (=1) MISO pin as an output. */
-#define SIZE                   0x00000100	/* Word length (0 => 8 bits, 1 => 16 bits) */
-#define LSBF                   0x00000200	/* Data format (0 => MSB sent/received first 1 => LSB sent/received first) */
-#define CPHA                   0x00000400	/* Clock phase (0 => SPICLK starts toggling in middle of xfer, 1 => SPICLK toggles at the beginning of xfer. */
-#define CPOL                   0x00000800	/* Clock polarity (0 => active-high, 1 => active-low) */
-#define MSTR                   0x00001000	/* Configures SPI as master (=1) or slave (=0) */
-#define WOM                    0x00002000	/* Open drain (=1) data output enable (for MOSI and MISO) */
-#define SPE                    0x00004000	/* SPI module enable (=1), disable (=0) */
-
-/* SPI_FLG Masks */
-#define FLS1                   0x00000002	/* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLS2                   0x00000004	/* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLS3                   0x00000008	/* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLS4                   0x00000010	/* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLS5                   0x00000020	/* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLS6                   0x00000040	/* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLS7                   0x00000080	/* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
-#define FLG1                   0x00000200	/* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select  */
-#define FLG2                   0x00000400	/* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLG3                   0x00000800	/* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select  */
-#define FLG4                   0x00001000	/* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select  */
-#define FLG5                   0x00002000	/* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select  */
-#define FLG6                   0x00004000	/* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select  */
-#define FLG7                   0x00008000	/* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
-
-/* SPI_FLG Bit Positions */
-#define FLS1_P                 0x00000001	/* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLS2_P                 0x00000002	/* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLS3_P                 0x00000003	/* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLS4_P                 0x00000004	/* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLS5_P                 0x00000005	/* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLS6_P                 0x00000006	/* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLS7_P                 0x00000007	/* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
-#define FLG1_P                 0x00000009	/* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select  */
-#define FLG2_P                 0x0000000A	/* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLG3_P                 0x0000000B	/* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select  */
-#define FLG4_P                 0x0000000C	/* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select  */
-#define FLG5_P                 0x0000000D	/* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select  */
-#define FLG6_P                 0x0000000E	/* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select  */
-#define FLG7_P                 0x0000000F	/* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
-
-/* SPI_STAT Masks */
-#define SPIF                   0x00000001	/* Set (=1) when SPI single-word transfer complete */
-#define MODF                   0x00000002	/* Set (=1) in a master device when some other device tries to become master */
-#define TXE                    0x00000004	/* Set (=1) when transmission occurs with no new data in SPI_TDBR */
-#define TXS                    0x00000008	/* SPI_TDBR Data Buffer Status (0=Empty, 1=Full) */
-#define RBSY                   0x00000010	/* Set (=1) when data is received with RDBR full */
-#define RXS                    0x00000020	/* SPI_RDBR Data Buffer Status (0=Empty, 1=Full)  */
-#define TXCOL                  0x00000040	/* When set (=1), corrupt data may have been transmitted  */
-
 /* *********************  ASYNCHRONOUS MEMORY CONTROLLER MASKS  ************* */
 
 /* AMGCTL Masks */
diff --git a/arch/blackfin/mach-bf561/include/mach/pll.h b/arch/blackfin/mach-bf561/include/mach/pll.h
new file mode 100644
index 0000000..f2b1fbd
--- /dev/null
+++ b/arch/blackfin/mach-bf561/include/mach/pll.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2005-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1;
+
+	if (val == bfin_read_PLL_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SICA_IWR0);
+	iwr1 = bfin_read32(SICA_IWR1);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+	bfin_write32(SICA_IWR1, 0);
+
+	bfin_write16(PLL_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SICA_IWR0, iwr0);
+	bfin_write32(SICA_IWR1, iwr1);
+	hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+	unsigned long flags, iwr0, iwr1;
+
+	if (val == bfin_read_VR_CTL())
+		return;
+
+	flags = hard_local_irq_save();
+	/* Enable the PLL Wakeup bit in SIC IWR */
+	iwr0 = bfin_read32(SICA_IWR0);
+	iwr1 = bfin_read32(SICA_IWR1);
+	/* Only allow PPL Wakeup) */
+	bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+	bfin_write32(SICA_IWR1, 0);
+
+	bfin_write16(VR_CTL, val);
+	SSYNC();
+	asm("IDLE;");
+
+	bfin_write32(SICA_IWR0, iwr0);
+	bfin_write32(SICA_IWR1, iwr1);
+	hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf561/ints-priority.c b/arch/blackfin/mach-bf561/ints-priority.c
index b442417..7ee9262 100644
--- a/arch/blackfin/mach-bf561/ints-priority.c
+++ b/arch/blackfin/mach-bf561/ints-priority.c
@@ -13,7 +13,7 @@
 void __init program_IAR(void)
 {
 	/* Program the IAR0 Register with the configured priority */
-	bfin_write_SICA_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
+	bfin_write_SIC_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
 			     ((CONFIG_IRQ_DMA1_ERROR - 7) << IRQ_DMA1_ERROR_POS) |
 			     ((CONFIG_IRQ_DMA2_ERROR - 7) << IRQ_DMA2_ERROR_POS) |
 			     ((CONFIG_IRQ_IMDMA_ERROR - 7) << IRQ_IMDMA_ERROR_POS) |
@@ -22,7 +22,7 @@
 			     ((CONFIG_IRQ_SPORT0_ERROR - 7) << IRQ_SPORT0_ERROR_POS) |
 			     ((CONFIG_IRQ_SPORT1_ERROR - 7) << IRQ_SPORT1_ERROR_POS));
 
-	bfin_write_SICA_IAR1(((CONFIG_IRQ_SPI_ERROR - 7) << IRQ_SPI_ERROR_POS) |
+	bfin_write_SIC_IAR1(((CONFIG_IRQ_SPI_ERROR - 7) << IRQ_SPI_ERROR_POS) |
 			     ((CONFIG_IRQ_UART_ERROR - 7) << IRQ_UART_ERROR_POS) |
 			     ((CONFIG_IRQ_RESERVED_ERROR - 7) << IRQ_RESERVED_ERROR_POS) |
 			     ((CONFIG_IRQ_DMA1_0 - 7) << IRQ_DMA1_0_POS) |
@@ -31,7 +31,7 @@
 			     ((CONFIG_IRQ_DMA1_3 - 7) << IRQ_DMA1_3_POS) |
 			     ((CONFIG_IRQ_DMA1_4 - 7) << IRQ_DMA1_4_POS));
 
-	bfin_write_SICA_IAR2(((CONFIG_IRQ_DMA1_5 - 7) << IRQ_DMA1_5_POS) |
+	bfin_write_SIC_IAR2(((CONFIG_IRQ_DMA1_5 - 7) << IRQ_DMA1_5_POS) |
 			     ((CONFIG_IRQ_DMA1_6 - 7) << IRQ_DMA1_6_POS) |
 			     ((CONFIG_IRQ_DMA1_7 - 7) << IRQ_DMA1_7_POS) |
 			     ((CONFIG_IRQ_DMA1_8 - 7) << IRQ_DMA1_8_POS) |
@@ -40,7 +40,7 @@
 			     ((CONFIG_IRQ_DMA1_11 - 7) << IRQ_DMA1_11_POS) |
 			     ((CONFIG_IRQ_DMA2_0 - 7) << IRQ_DMA2_0_POS));
 
-	bfin_write_SICA_IAR3(((CONFIG_IRQ_DMA2_1 - 7) << IRQ_DMA2_1_POS) |
+	bfin_write_SIC_IAR3(((CONFIG_IRQ_DMA2_1 - 7) << IRQ_DMA2_1_POS) |
 			     ((CONFIG_IRQ_DMA2_2 - 7) << IRQ_DMA2_2_POS) |
 			     ((CONFIG_IRQ_DMA2_3 - 7) << IRQ_DMA2_3_POS) |
 			     ((CONFIG_IRQ_DMA2_4 - 7) << IRQ_DMA2_4_POS) |
@@ -49,7 +49,7 @@
 			     ((CONFIG_IRQ_DMA2_7 - 7) << IRQ_DMA2_7_POS) |
 			     ((CONFIG_IRQ_DMA2_8 - 7) << IRQ_DMA2_8_POS));
 
-	bfin_write_SICA_IAR4(((CONFIG_IRQ_DMA2_9 - 7) << IRQ_DMA2_9_POS) |
+	bfin_write_SIC_IAR4(((CONFIG_IRQ_DMA2_9 - 7) << IRQ_DMA2_9_POS) |
 			     ((CONFIG_IRQ_DMA2_10 - 7) << IRQ_DMA2_10_POS) |
 			     ((CONFIG_IRQ_DMA2_11 - 7) << IRQ_DMA2_11_POS) |
 			     ((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
@@ -58,7 +58,7 @@
 			     ((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
 			     ((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS));
 
-	bfin_write_SICA_IAR5(((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+	bfin_write_SIC_IAR5(((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
 			     ((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
 			     ((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS) |
 			     ((CONFIG_IRQ_TIMER8 - 7) << IRQ_TIMER8_POS) |
@@ -67,7 +67,7 @@
 			     ((CONFIG_IRQ_TIMER11 - 7) << IRQ_TIMER11_POS) |
 			     ((CONFIG_IRQ_PROG0_INTA - 7) << IRQ_PROG0_INTA_POS));
 
-	bfin_write_SICA_IAR6(((CONFIG_IRQ_PROG0_INTB - 7) << IRQ_PROG0_INTB_POS) |
+	bfin_write_SIC_IAR6(((CONFIG_IRQ_PROG0_INTB - 7) << IRQ_PROG0_INTB_POS) |
 			     ((CONFIG_IRQ_PROG1_INTA - 7) << IRQ_PROG1_INTA_POS) |
 			     ((CONFIG_IRQ_PROG1_INTB - 7) << IRQ_PROG1_INTB_POS) |
 			     ((CONFIG_IRQ_PROG2_INTA - 7) << IRQ_PROG2_INTA_POS) |
@@ -76,7 +76,7 @@
 			     ((CONFIG_IRQ_DMA1_WRRD1 - 7) << IRQ_DMA1_WRRD1_POS) |
 			     ((CONFIG_IRQ_DMA2_WRRD0 - 7) << IRQ_DMA2_WRRD0_POS));
 
-	bfin_write_SICA_IAR7(((CONFIG_IRQ_DMA2_WRRD1 - 7) << IRQ_DMA2_WRRD1_POS) |
+	bfin_write_SIC_IAR7(((CONFIG_IRQ_DMA2_WRRD1 - 7) << IRQ_DMA2_WRRD1_POS) |
 			     ((CONFIG_IRQ_IMDMA_WRRD0 - 7) << IRQ_IMDMA_WRRD0_POS) |
 			     ((CONFIG_IRQ_IMDMA_WRRD1 - 7) << IRQ_IMDMA_WRRD1_POS) |
 			     ((CONFIG_IRQ_WDTIMER - 7) << IRQ_WDTIMER_POS) |
diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c
index 3b9a4bf..f540ed1 100644
--- a/arch/blackfin/mach-bf561/smp.c
+++ b/arch/blackfin/mach-bf561/smp.c
@@ -52,19 +52,19 @@
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
 	/* Clone setup for peripheral interrupt sources from CoreA. */
-	bfin_write_SICB_IMASK0(bfin_read_SICA_IMASK0());
-	bfin_write_SICB_IMASK1(bfin_read_SICA_IMASK1());
+	bfin_write_SICB_IMASK0(bfin_read_SIC_IMASK0());
+	bfin_write_SICB_IMASK1(bfin_read_SIC_IMASK1());
 	SSYNC();
 
 	/* Clone setup for IARs from CoreA. */
-	bfin_write_SICB_IAR0(bfin_read_SICA_IAR0());
-	bfin_write_SICB_IAR1(bfin_read_SICA_IAR1());
-	bfin_write_SICB_IAR2(bfin_read_SICA_IAR2());
-	bfin_write_SICB_IAR3(bfin_read_SICA_IAR3());
-	bfin_write_SICB_IAR4(bfin_read_SICA_IAR4());
-	bfin_write_SICB_IAR5(bfin_read_SICA_IAR5());
-	bfin_write_SICB_IAR6(bfin_read_SICA_IAR6());
-	bfin_write_SICB_IAR7(bfin_read_SICA_IAR7());
+	bfin_write_SICB_IAR0(bfin_read_SIC_IAR0());
+	bfin_write_SICB_IAR1(bfin_read_SIC_IAR1());
+	bfin_write_SICB_IAR2(bfin_read_SIC_IAR2());
+	bfin_write_SICB_IAR3(bfin_read_SIC_IAR3());
+	bfin_write_SICB_IAR4(bfin_read_SIC_IAR4());
+	bfin_write_SICB_IAR5(bfin_read_SIC_IAR5());
+	bfin_write_SICB_IAR6(bfin_read_SIC_IAR6());
+	bfin_write_SICB_IAR7(bfin_read_SIC_IAR7());
 	bfin_write_SICB_IWR0(IWR_DISABLE_ALL);
 	bfin_write_SICB_IWR1(IWR_DISABLE_ALL);
 	SSYNC();
@@ -86,12 +86,12 @@
 
 	spin_lock(&boot_lock);
 
-	if ((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0) {
+	if ((bfin_read_SIC_SYSCR() & COREB_SRAM_INIT) == 0) {
 		/* CoreB already running, sending ipi to wakeup it */
 		platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
 	} else {
 		/* Kick CoreB, which should start execution from CORE_SRAM_BASE. */
-		bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT);
+		bfin_write_SIC_SYSCR(bfin_read_SIC_SYSCR() & ~COREB_SRAM_INIT);
 		SSYNC();
 	}
 
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
index 4391d03..f4cf11d 100644
--- a/arch/blackfin/mach-common/cpufreq.c
+++ b/arch/blackfin/mach-common/cpufreq.c
@@ -134,7 +134,7 @@
 
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 		if (cpu == CPUFREQ_CPU) {
-			local_irq_save_hw(flags);
+			flags = hard_local_irq_save();
 			plldiv = (bfin_read_PLL_DIV() & SSEL) |
 						dpm_state_table[index].csel;
 			bfin_write_PLL_DIV(plldiv);
@@ -155,7 +155,7 @@
 				loops_per_jiffy = cpufreq_scale(lpj_ref,
 						lpj_ref_freq, freqs.new);
 			}
-			local_irq_restore_hw(flags);
+			hard_local_irq_restore(flags);
 		}
 		/* TODO: just test case for cycles clock source, remove later */
 		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S
index 5969d86..9cfdd49 100644
--- a/arch/blackfin/mach-common/dpmc_modes.S
+++ b/arch/blackfin/mach-common/dpmc_modes.S
@@ -292,13 +292,7 @@
 #ifdef SIC_IMASK
 	PM_SYS_PUSH(SIC_IMASK)
 #endif
-#ifdef SICA_IMASK0
-	PM_SYS_PUSH(SICA_IMASK0)
-#endif
-#ifdef SICA_IMASK1
-	PM_SYS_PUSH(SICA_IMASK1)
-#endif
-#ifdef SIC_IAR2
+#ifdef SIC_IAR0
 	PM_SYS_PUSH(SIC_IAR0)
 	PM_SYS_PUSH(SIC_IAR1)
 	PM_SYS_PUSH(SIC_IAR2)
@@ -321,17 +315,6 @@
 	PM_SYS_PUSH(SIC_IAR11)
 #endif
 
-#ifdef SICA_IAR0
-	PM_SYS_PUSH(SICA_IAR0)
-	PM_SYS_PUSH(SICA_IAR1)
-	PM_SYS_PUSH(SICA_IAR2)
-	PM_SYS_PUSH(SICA_IAR3)
-	PM_SYS_PUSH(SICA_IAR4)
-	PM_SYS_PUSH(SICA_IAR5)
-	PM_SYS_PUSH(SICA_IAR6)
-	PM_SYS_PUSH(SICA_IAR7)
-#endif
-
 #ifdef SIC_IWR
 	PM_SYS_PUSH(SIC_IWR)
 #endif
@@ -344,12 +327,6 @@
 #ifdef SIC_IWR2
 	PM_SYS_PUSH(SIC_IWR2)
 #endif
-#ifdef SICA_IWR0
-	PM_SYS_PUSH(SICA_IWR0)
-#endif
-#ifdef SICA_IWR1
-	PM_SYS_PUSH(SICA_IWR1)
-#endif
 
 #ifdef PINT0_ASSIGN
 	PM_SYS_PUSH(PINT0_MASK_SET)
@@ -750,12 +727,6 @@
 	PM_SYS_POP(PINT0_MASK_SET)
 #endif
 
-#ifdef SICA_IWR1
-	PM_SYS_POP(SICA_IWR1)
-#endif
-#ifdef SICA_IWR0
-	PM_SYS_POP(SICA_IWR0)
-#endif
 #ifdef SIC_IWR2
 	PM_SYS_POP(SIC_IWR2)
 #endif
@@ -769,17 +740,6 @@
 	PM_SYS_POP(SIC_IWR)
 #endif
 
-#ifdef SICA_IAR0
-	PM_SYS_POP(SICA_IAR7)
-	PM_SYS_POP(SICA_IAR6)
-	PM_SYS_POP(SICA_IAR5)
-	PM_SYS_POP(SICA_IAR4)
-	PM_SYS_POP(SICA_IAR3)
-	PM_SYS_POP(SICA_IAR2)
-	PM_SYS_POP(SICA_IAR1)
-	PM_SYS_POP(SICA_IAR0)
-#endif
-
 #ifdef SIC_IAR8
 	PM_SYS_POP(SIC_IAR11)
 	PM_SYS_POP(SIC_IAR10)
@@ -797,17 +757,11 @@
 #ifdef SIC_IAR3
 	PM_SYS_POP(SIC_IAR3)
 #endif
-#ifdef SIC_IAR2
+#ifdef SIC_IAR0
 	PM_SYS_POP(SIC_IAR2)
 	PM_SYS_POP(SIC_IAR1)
 	PM_SYS_POP(SIC_IAR0)
 #endif
-#ifdef SICA_IMASK1
-	PM_SYS_POP(SICA_IMASK1)
-#endif
-#ifdef SICA_IMASK0
-	PM_SYS_POP(SICA_IMASK0)
-#endif
 #ifdef SIC_IMASK
 	PM_SYS_POP(SIC_IMASK)
 #endif
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index af1bffa..2ca915e 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -889,6 +889,66 @@
 	rts;
 ENDPROC(_ret_from_exception)
 
+#if defined(CONFIG_PREEMPT)
+
+ENTRY(_up_to_irq14)
+#if ANOMALY_05000281 || ANOMALY_05000461
+	r0.l = lo(SAFE_USER_INSTRUCTION);
+	r0.h = hi(SAFE_USER_INSTRUCTION);
+	reti = r0;
+#endif
+
+#ifdef CONFIG_DEBUG_HWERR
+	/* enable irq14 & hwerr interrupt, until we transition to _evt_evt14 */
+	r0 = (EVT_IVG14 | EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+#else
+	/* Only enable irq14 interrupt, until we transition to _evt_evt14 */
+	r0 = (EVT_IVG14 | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+#endif
+	sti r0;
+
+	p0.l = lo(EVT14);
+	p0.h = hi(EVT14);
+	p1.l = _evt_up_evt14;
+	p1.h = _evt_up_evt14;
+	[p0] = p1;
+	csync;
+
+	raise 14;
+1:
+	jump 1b;
+ENDPROC(_up_to_irq14)
+
+ENTRY(_evt_up_evt14)
+#ifdef CONFIG_DEBUG_HWERR
+	r0 = (EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+	sti r0;
+#else
+	cli r0;
+#endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+	[--sp] = rets;
+	sp += -12;
+	call _trace_hardirqs_off;
+	sp += 12;
+	rets = [sp++];
+#endif
+	[--sp] = RETI;
+	SP += 4;
+
+	/* restore normal evt14 */
+	p0.l = lo(EVT14);
+	p0.h = hi(EVT14);
+	p1.l = _evt_evt14;
+	p1.h = _evt_evt14;
+	[p0] = p1;
+	csync;
+
+	rts;
+ENDPROC(_evt_up_evt14)
+
+#endif
+
 #ifdef CONFIG_IPIPE
 
 _resume_kernel_from_int:
@@ -902,8 +962,54 @@
 	( r7:4, p5:3 ) = [sp++];
 	rets = [sp++];
 	rts
+#elif defined(CONFIG_PREEMPT)
+
+_resume_kernel_from_int:
+	/* check preempt_count */
+	r7 = sp;
+	r4.l = lo(ALIGN_PAGE_MASK);
+	r4.h = hi(ALIGN_PAGE_MASK);
+	r7 = r7 & r4;
+	p5 = r7;
+	r7 = [p5 + TI_PREEMPT];
+	cc = r7 == 0x0;
+	if !cc jump .Lreturn_to_kernel;
+.Lneed_schedule:
+	r7 = [p5 + TI_FLAGS];
+	r4.l = lo(_TIF_WORK_MASK);
+	r4.h = hi(_TIF_WORK_MASK);
+	r7 =  r7 & r4;
+	cc = BITTST(r7, TIF_NEED_RESCHED);
+	if !cc jump .Lreturn_to_kernel;
+	/*
+	 * let schedule done at level 15, otherwise sheduled process will run
+	 * at high level and block low level interrupt
+	 */
+	r6 = reti;  /* save reti */
+	r5.l = .Lkernel_schedule;
+	r5.h = .Lkernel_schedule;
+	reti = r5;
+	rti;
+.Lkernel_schedule:
+	[--sp] = rets;
+	sp += -12;
+	pseudo_long_call _preempt_schedule_irq, p4;
+	sp += 12;
+	rets = [sp++];
+
+	[--sp] = rets;
+	sp += -12;
+	/* up to irq14 so that reti after restore_all can return to irq15(kernel) */
+	pseudo_long_call _up_to_irq14, p4;
+	sp += 12;
+	rets = [sp++];
+
+	reti = r6; /* restore reti so that origin process can return to interrupted point */
+
+	jump .Lneed_schedule;
 #else
-#define _resume_kernel_from_int	 2f
+
+#define _resume_kernel_from_int	.Lreturn_to_kernel
 #endif
 
 ENTRY(_return_from_int)
@@ -913,7 +1019,7 @@
 	p2.h = hi(ILAT);
 	r0 = [p2];
 	cc = bittst (r0, EVT_IVG15_P);
-	if cc jump 2f;
+	if cc jump .Lreturn_to_kernel;
 
 	/* if not return to user mode, get out */
 	p2.l = lo(IPEND);
@@ -945,7 +1051,7 @@
 	STI r0;
 	raise 15;	/* raise evt15 to do signal or reschedule */
 	rti;
-2:
+.Lreturn_to_kernel:
 	rts;
 ENDPROC(_return_from_int)
 
@@ -1631,6 +1737,7 @@
 	.long _sys_fanotify_init
 	.long _sys_fanotify_mark
 	.long _sys_prlimit64
+	.long _sys_cacheflush
 
 	.rept NR_syscalls-(.-_sys_call_table)/4
 	.long _sys_ni_syscall
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
index cee62cf..2df37db 100644
--- a/arch/blackfin/mach-common/interrupt.S
+++ b/arch/blackfin/mach-common/interrupt.S
@@ -116,7 +116,24 @@
 	cc = r0 == 0;
 	if cc jump .Lcommon_restore_context;
 #else /* CONFIG_IPIPE */
+
+#ifdef CONFIG_PREEMPT
+	r7 = sp;
+	r4.l = lo(ALIGN_PAGE_MASK);
+	r4.h = hi(ALIGN_PAGE_MASK);
+	r7 = r7 & r4;
+	p5 = r7;
+	r7 = [p5 + TI_PREEMPT]; /* get preempt count */
+	r7 += 1;                /* increment it */
+	[p5 + TI_PREEMPT] = r7;
+#endif
 	pseudo_long_call _do_irq, p2;
+
+#ifdef CONFIG_PREEMPT
+	r7 += -1;
+	[p5 + TI_PREEMPT] = r7; /* restore preempt count */
+#endif
+
 	SP += 12;
 #endif /* CONFIG_IPIPE */
 	pseudo_long_call _return_from_int, p2;
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 1c8c4c7..da7e3c6 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -132,8 +132,8 @@
 static void bfin_core_mask_irq(unsigned int irq)
 {
 	bfin_irq_flags &= ~(1 << irq);
-	if (!irqs_disabled_hw())
-		local_irq_enable_hw();
+	if (!hard_irqs_disabled())
+		hard_local_irq_enable();
 }
 
 static void bfin_core_unmask_irq(unsigned int irq)
@@ -148,8 +148,8 @@
 	 * local_irq_enable just does "STI bfin_irq_flags", so it's exactly
 	 * what we need.
 	 */
-	if (!irqs_disabled_hw())
-		local_irq_enable_hw();
+	if (!hard_irqs_disabled())
+		hard_local_irq_enable();
 	return;
 }
 
@@ -158,12 +158,12 @@
 	unsigned long flags;
 
 #ifdef CONFIG_BF53x
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
 			     ~(1 << SIC_SYSIRQ(irq)));
 #else
 	unsigned mask_bank, mask_bit;
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	mask_bank = SIC_SYSIRQ(irq) / 32;
 	mask_bit = SIC_SYSIRQ(irq) % 32;
 	bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
@@ -173,7 +173,7 @@
 			     ~(1 << mask_bit));
 #endif
 #endif
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 
 #ifdef CONFIG_SMP
@@ -186,12 +186,12 @@
 	unsigned long flags;
 
 #ifdef CONFIG_BF53x
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
 			     (1 << SIC_SYSIRQ(irq)));
 #else
 	unsigned mask_bank, mask_bit;
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	mask_bank = SIC_SYSIRQ(irq) / 32;
 	mask_bit = SIC_SYSIRQ(irq) % 32;
 #ifdef CONFIG_SMP
@@ -207,7 +207,7 @@
 			(1 << mask_bit));
 #endif
 #endif
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 
 #ifdef CONFIG_SMP
@@ -264,7 +264,7 @@
 	break;
 	}
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	if (state) {
 		bfin_sic_iwr[bank] |= (1 << bit);
@@ -275,7 +275,7 @@
 		vr_wakeup  &= ~wakeup;
 	}
 
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 
 	return 0;
 }
@@ -511,7 +511,7 @@
 	int i, irq = 0;
 	u32 status = bfin_read_EMAC_SYSTAT();
 
-	for (i = 0; i < (IRQ_MAC_STMDONE - IRQ_MAC_PHYINT); i++)
+	for (i = 0; i <= (IRQ_MAC_STMDONE - IRQ_MAC_PHYINT); i++)
 		if (status & (1L << i)) {
 			irq = IRQ_MAC_PHYINT + i;
 			break;
@@ -529,8 +529,9 @@
 	} else
 		printk(KERN_ERR
 		       "%s : %s : LINE %d :\nIRQ ?: MAC ERROR"
-		       " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
-		       __func__, __FILE__, __LINE__);
+		       " INTERRUPT ASSERTED BUT NO SOURCE FOUND"
+		       "(EMAC_SYSTAT=0x%X)\n",
+		       __func__, __FILE__, __LINE__, status);
 }
 #endif
 
@@ -1298,7 +1299,7 @@
 	} else {
 		struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
 		struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
-#if defined(SIC_ISR0) || defined(SICA_ISR0)
+#if defined(SIC_ISR0)
 		unsigned long sic_status[3];
 
 		if (smp_processor_id()) {
@@ -1378,7 +1379,7 @@
 	if (likely(vec == EVT_IVTMR_P))
 		irq = IRQ_CORETMR;
 	else {
-#if defined(SIC_ISR0) || defined(SICA_ISR0)
+#if defined(SIC_ISR0)
 		unsigned long sic_status[3];
 
 		sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index 09c1fb4..80884b1 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -25,7 +25,7 @@
 {
 	unsigned long flags;
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 	bfin_pm_standby_setup();
 
 #ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
@@ -56,7 +56,7 @@
 	bfin_write_SIC_IWR(IWR_DISABLE_ALL);
 #endif
 
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 }
 
 int bf53x_suspend_l1_mem(unsigned char *memptr)
@@ -149,12 +149,12 @@
 	wakeup |= GPWE;
 #endif
 
-	local_irq_save_hw(flags);
+	flags = hard_local_irq_save();
 
 	ret = blackfin_dma_suspend();
 
 	if (ret) {
-		local_irq_restore_hw(flags);
+		hard_local_irq_restore(flags);
 		kfree(memptr);
 		return ret;
 	}
@@ -178,7 +178,7 @@
 	bfin_gpio_pm_hibernate_restore();
 	blackfin_dma_resume();
 
-	local_irq_restore_hw(flags);
+	hard_local_irq_restore(flags);
 	kfree(memptr);
 
 	return 0;
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c
index bb4e8ff..f8435cd 100644
--- a/arch/blackfin/mm/init.c
+++ b/arch/blackfin/mm/init.c
@@ -158,5 +158,8 @@
 	free_init_pages("unused kernel memory",
 			(unsigned long)(&__init_begin),
 			(unsigned long)(&__init_end));
+
+	if (memory_start == (unsigned long)(&__init_end))
+		memory_start = (unsigned long)(&__init_begin);
 #endif
 }
diff --git a/arch/cris/arch-v10/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c
index 8842756..3d655dc 100644
--- a/arch/cris/arch-v10/drivers/ds1302.c
+++ b/arch/cris/arch-v10/drivers/ds1302.c
@@ -19,7 +19,7 @@
 #include <linux/module.h>
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/bcd.h>
 #include <linux/capability.h>
 
@@ -34,6 +34,7 @@
 
 #define RTC_MAJOR_NR 121 /* local major, change later */
 
+static DEFINE_MUTEX(ds1302_mutex);
 static const char ds1302_name[] = "ds1302";
 
 /* The DS1302 might be connected to different bits on different products. 
@@ -357,9 +358,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ds1302_mutex);
 	ret = rtc_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ds1302_mutex);
 
 	return ret;
 }
@@ -387,6 +388,7 @@
 static const struct file_operations rtc_fops = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl = rtc_unlocked_ioctl,
+	.llseek		= noop_llseek,
 }; 
 
 /* Probe for the chip by writing something to its RAM and try reading it back. */
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index a07b6d2..a276f08 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -745,6 +745,7 @@
 	.write          = gpio_write,
 	.open           = gpio_open,
 	.release        = gpio_release,
+	.llseek		= noop_llseek,
 };
 
 static void ioif_watcher(const unsigned int gpio_in_available,
diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c
index 77a9418..c413539 100644
--- a/arch/cris/arch-v10/drivers/i2c.c
+++ b/arch/cris/arch-v10/drivers/i2c.c
@@ -617,6 +617,7 @@
 	.unlocked_ioctl	= i2c_ioctl,
 	.open		= i2c_open,
 	.release	= i2c_release,
+	.llseek		= noop_llseek,
 };
 
 int __init
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c
index 7dcb1f8..ea69fab 100644
--- a/arch/cris/arch-v10/drivers/pcf8563.c
+++ b/arch/cris/arch-v10/drivers/pcf8563.c
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 #include <linux/bcd.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -49,6 +48,7 @@
 #define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
 #define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
 
+static DEFINE_MUTEX(pcf8563_mutex);
 static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
 
 static const unsigned char days_in_month[] =
@@ -64,6 +64,7 @@
 static const struct file_operations pcf8563_fops = {
 	.owner = THIS_MODULE,
 	.unlocked_ioctl = pcf8563_unlocked_ioctl,
+	.llseek		= noop_llseek,
 };
 
 unsigned char
@@ -343,9 +344,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pcf8563_mutex);
 	return pcf8563_ioctl(filp, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&pcf8563_mutex);
 
 	return ret;
 }
diff --git a/arch/cris/arch-v10/drivers/sync_serial.c b/arch/cris/arch-v10/drivers/sync_serial.c
index ee2dd43..399dc1e 100644
--- a/arch/cris/arch-v10/drivers/sync_serial.c
+++ b/arch/cris/arch-v10/drivers/sync_serial.c
@@ -20,7 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/timer.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
@@ -149,6 +149,7 @@
 };
 
 
+static DEFINE_MUTEX(sync_serial_mutex);
 static int etrax_sync_serial_init(void);
 static void initialize_port(int portnbr);
 static inline int sync_data_avail(struct sync_port *port);
@@ -250,7 +251,8 @@
 	.poll		= sync_serial_poll,
 	.unlocked_ioctl	= sync_serial_ioctl,
 	.open		= sync_serial_open,
-	.release	= sync_serial_release
+	.release	= sync_serial_release,
+	.llseek		= noop_llseek,
 };
 
 static int __init etrax_sync_serial_init(void)
@@ -445,7 +447,7 @@
 	int mode;
 	int err = -EBUSY;
 
-	lock_kernel();
+	mutex_lock(&sync_serial_mutex);
 	DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));
 
 	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) {
@@ -626,7 +628,7 @@
 	ret = 0;
 	
 out:
-	unlock_kernel();
+	mutex_unlock(&sync_serial_mutex);
 	return ret;
 }
 
@@ -961,9 +963,9 @@
 {
 	long ret;
 
-	lock_kernel();
+	mutex_lock(&sync_serial_mutex);
 	ret = sync_serial_ioctl_unlocked(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&sync_serial_mutex);
 
 	return ret;
 }
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index b07646a..c03bc3b 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -281,7 +281,8 @@
 	.owner		= THIS_MODULE,
 	.open		= cryptocop_open,
 	.release	= cryptocop_release,
-	.unlocked_ioctl = cryptocop_ioctl
+	.unlocked_ioctl = cryptocop_ioctl,
+	.llseek		= noop_llseek,
 };
 
 
@@ -3139,9 +3140,9 @@
        struct inode *inode = file->f_path.dentry->d_inode;
        long ret;
 
-       lock_kernel();
+       mutex_lock(&cryptocop_mutex);
        ret = cryptocop_ioctl_unlocked(inode, filp, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&cryptocop_mutex);
 
        return ret;
 }
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index 5a3e900..ddb2399 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -698,6 +698,7 @@
 	.unlocked_ioctl = i2c_ioctl,
 	.open		= i2c_open,
 	.release	= i2c_release,
+	.llseek		= noop_llseek,
 };
 
 static int __init i2c_init(void)
diff --git a/arch/cris/arch-v32/drivers/mach-a3/gpio.c b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
index 2dcd27a..c845831 100644
--- a/arch/cris/arch-v32/drivers/mach-a3/gpio.c
+++ b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
@@ -23,7 +23,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/etraxgpio.h>
 #include <hwregs/reg_map.h>
@@ -66,6 +66,7 @@
 #define DP(x)
 #endif
 
+static DEFINE_MUTEX(gpio_mutex);
 static char gpio_name[] = "etrax gpio";
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
@@ -391,7 +392,7 @@
 	if (!priv)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&gpio_mutex);
 	memset(priv, 0, sizeof(*priv));
 
 	priv->minor = p;
@@ -414,7 +415,7 @@
 		spin_unlock_irq(&gpio_lock);
 	}
 
-	unlock_kernel();
+	mutex_unlock(&gpio_mutex);
 	return 0;
 }
 
@@ -667,9 +668,9 @@
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&gpio_mutex);
        ret = gpio_ioctl_unlocked(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&gpio_mutex);
 
        return ret;
 }
@@ -893,6 +894,7 @@
 	.write		= gpio_write,
 	.open		= gpio_open,
 	.release	= gpio_release,
+	.llseek		= noop_llseek,
 };
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
diff --git a/arch/cris/arch-v32/drivers/mach-fs/gpio.c b/arch/cris/arch-v32/drivers/mach-fs/gpio.c
index 5ec8a7d..ee90d26 100644
--- a/arch/cris/arch-v32/drivers/mach-fs/gpio.c
+++ b/arch/cris/arch-v32/drivers/mach-fs/gpio.c
@@ -22,7 +22,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/etraxgpio.h>
 #include <hwregs/reg_map.h>
@@ -64,6 +64,7 @@
 #define DP(x)
 #endif
 
+static DEFINE_MUTEX(gpio_mutex);
 static char gpio_name[] = "etrax gpio";
 
 #if 0
@@ -429,7 +430,7 @@
 	if (!priv)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&gpio_mutex);
 	memset(priv, 0, sizeof(*priv));
 
 	priv->minor = p;
@@ -450,7 +451,7 @@
 	alarmlist = priv;
 	spin_unlock_irq(&alarm_lock);
 
-	unlock_kernel();
+	mutex_unlock(&gpio_mutex);
 	return 0;
 }
 
@@ -708,9 +709,9 @@
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&gpio_mutex);
        ret = gpio_ioctl_unlocked(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&gpio_mutex);
 
        return ret;
 }
@@ -870,6 +871,7 @@
 	.write		= gpio_write,
 	.open		= gpio_open,
 	.release	= gpio_release,
+	.llseek		= noop_llseek,
 };
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
index bef6eb5..b6e4fc0 100644
--- a/arch/cris/arch-v32/drivers/pcf8563.c
+++ b/arch/cris/arch-v32/drivers/pcf8563.c
@@ -24,7 +24,6 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/bcd.h>
 #include <linux/mutex.h>
@@ -45,6 +44,7 @@
 #define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
 #define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
 
+static DEFINE_MUTEX(pcf8563_mutex);
 static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
 
 static const unsigned char days_in_month[] =
@@ -60,6 +60,7 @@
 static const struct file_operations pcf8563_fops = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl = pcf8563_unlocked_ioctl,
+	.llseek		= noop_llseek,
 };
 
 unsigned char
@@ -339,9 +340,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pcf8563_mutex);
 	return pcf8563_ioctl(filp, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&pcf8563_mutex);
 
 	return ret;
 }
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c
index ca248f3..c8637a9 100644
--- a/arch/cris/arch-v32/drivers/sync_serial.c
+++ b/arch/cris/arch-v32/drivers/sync_serial.c
@@ -13,7 +13,7 @@
 #include <linux/errno.h>
 #include <linux/major.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
 #include <linux/init.h>
@@ -145,6 +145,7 @@
 	spinlock_t lock;
 } sync_port;
 
+static DEFINE_MUTEX(sync_serial_mutex);
 static int etrax_sync_serial_init(void);
 static void initialize_port(int portnbr);
 static inline int sync_data_avail(struct sync_port *port);
@@ -247,7 +248,8 @@
 	.poll		= sync_serial_poll,
 	.unlocked_ioctl	= sync_serial_ioctl,
 	.open		= sync_serial_open,
-	.release	= sync_serial_release
+	.release	= sync_serial_release,
+	.llseek		= noop_llseek,
 };
 
 static int __init etrax_sync_serial_init(void)
@@ -434,7 +436,7 @@
 	reg_dma_rw_cfg cfg = {.en = regk_dma_yes};
 	reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes};
 
-	lock_kernel();
+	mutex_lock(&sync_serial_mutex);
 	DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));
 
 	if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled)
@@ -583,7 +585,7 @@
 	port->busy++;
 	ret = 0;
 out:
-	unlock_kernel();
+	mutex_unlock(&sync_serial_mutex);
 	return ret;
 }
 
@@ -966,9 +968,9 @@
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&sync_serial_mutex);
        ret = sync_serial_ioctl_unlocked(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&sync_serial_mutex);
 
        return ret;
 }
diff --git a/arch/cris/include/arch-v10/arch/irqflags.h b/arch/cris/include/arch-v10/arch/irqflags.h
new file mode 100644
index 0000000..75ef189
--- /dev/null
+++ b/arch/cris/include/arch-v10/arch/irqflags.h
@@ -0,0 +1,45 @@
+#ifndef __ASM_CRIS_ARCH_IRQFLAGS_H
+#define __ASM_CRIS_ARCH_IRQFLAGS_H
+
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile("move $ccr,%0" : "=rm" (flags) : : "memory");
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	asm volatile("di" : : : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	asm volatile("ei" : : : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags = arch_local_save_flags();
+	arch_local_irq_disable();
+	return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile("move %0,$ccr" : : "rm" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return !(flags & (1 << 5));
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __ASM_CRIS_ARCH_IRQFLAGS_H */
diff --git a/arch/cris/include/arch-v10/arch/system.h b/arch/cris/include/arch-v10/arch/system.h
index 4a9cd36..935fde3 100644
--- a/arch/cris/include/arch-v10/arch/system.h
+++ b/arch/cris/include/arch-v10/arch/system.h
@@ -44,20 +44,4 @@
 struct __xchg_dummy { unsigned long a[100]; };
 #define __xg(x) ((struct __xchg_dummy *)(x))
 
-/* interrupt control.. */
-#define local_save_flags(x)	__asm__ __volatile__ ("move $ccr,%0" : "=rm" (x) : : "memory");
-#define local_irq_restore(x) 	__asm__ __volatile__ ("move %0,$ccr" : : "rm" (x) : "memory");
-#define local_irq_disable() 	__asm__ __volatile__ ( "di" : : :"memory");
-#define local_irq_enable()	__asm__ __volatile__ ( "ei" : : :"memory");
-
-#define irqs_disabled()			\
-({					\
-	unsigned long flags;		\
-	local_save_flags(flags);	\
-	!(flags & (1<<5));		\
-})
-
-/* For spinlocks etc */
-#define local_irq_save(x) __asm__ __volatile__ ("move $ccr,%0\n\tdi" : "=rm" (x) : : "memory");
-
 #endif
diff --git a/arch/cris/include/arch-v32/arch/irqflags.h b/arch/cris/include/arch-v32/arch/irqflags.h
new file mode 100644
index 0000000..041851f
--- /dev/null
+++ b/arch/cris/include/arch-v32/arch/irqflags.h
@@ -0,0 +1,46 @@
+#ifndef __ASM_CRIS_ARCH_IRQFLAGS_H
+#define __ASM_CRIS_ARCH_IRQFLAGS_H
+
+#include <linux/types.h>
+#include <arch/ptrace.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile("move $ccs,%0" : "=rm" (flags) : : "memory");
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	asm volatile("di" : : : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	asm volatile("ei" : : : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags = arch_local_save_flags();
+	arch_local_irq_disable();
+	return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile("move %0,$ccs" : : "rm" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return !(flags & (1 << I_CCS_BITNR));
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __ASM_CRIS_ARCH_IRQFLAGS_H */
diff --git a/arch/cris/include/arch-v32/arch/system.h b/arch/cris/include/arch-v32/arch/system.h
index 6ca90f1..76cea99 100644
--- a/arch/cris/include/arch-v32/arch/system.h
+++ b/arch/cris/include/arch-v32/arch/system.h
@@ -44,26 +44,4 @@
 struct __xchg_dummy { unsigned long a[100]; };
 #define __xg(x) ((struct __xchg_dummy *)(x))
 
-/* Used for interrupt control. */
-#define local_save_flags(x) \
-	__asm__ __volatile__ ("move $ccs, %0" : "=rm" (x) : : "memory");
-
-#define local_irq_restore(x) \
-	__asm__ __volatile__ ("move %0, $ccs" : : "rm" (x) : "memory");
-
-#define local_irq_disable()  __asm__ __volatile__ ("di" : : : "memory");
-#define local_irq_enable()   __asm__ __volatile__ ("ei" : : : "memory");
-
-#define irqs_disabled()		\
-({				\
-	unsigned long flags;	\
-				\
-	local_save_flags(flags);\
-	!(flags & (1 << I_CCS_BITNR));	\
-})
-
-/* Used for spinlocks, etc. */
-#define local_irq_save(x) \
-	__asm__ __volatile__ ("move $ccs, %0\n\tdi" : "=rm" (x) : : "memory");
-
 #endif /* _ASM_CRIS_ARCH_SYSTEM_H */
diff --git a/arch/cris/include/asm/ioctls.h b/arch/cris/include/asm/ioctls.h
index c9129ed..488fbb3 100644
--- a/arch/cris/include/asm/ioctls.h
+++ b/arch/cris/include/asm/ioctls.h
@@ -1,93 +1,11 @@
 #ifndef __ARCH_CRIS_IOCTLS_H__
 #define __ARCH_CRIS_IOCTLS_H__
 
-/* verbatim copy of asm-i386/ioctls.h */
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
 #define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-#define FIOQSIZE	0x5460
-
 #define TIOCSERSETRS485	0x5461  /* enable rs-485 (deprecated) */
 #define TIOCSERWRRS485	0x5462  /* write rs-485 */
 #define TIOCSRS485	0x5463  /* enable rs-485 */
-#define TIOCGRS485	0x542E  /* get rs-485 */
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif
diff --git a/arch/cris/include/asm/irqflags.h b/arch/cris/include/asm/irqflags.h
new file mode 100644
index 0000000..943ba5c
--- /dev/null
+++ b/arch/cris/include/asm/irqflags.h
@@ -0,0 +1 @@
+#include <arch/irqflags.h>
diff --git a/arch/cris/include/asm/system.h b/arch/cris/include/asm/system.h
index 8657b08..ea10592 100644
--- a/arch/cris/include/asm/system.h
+++ b/arch/cris/include/asm/system.h
@@ -1,6 +1,7 @@
 #ifndef __ASM_CRIS_SYSTEM_H
 #define __ASM_CRIS_SYSTEM_H
 
+#include <linux/irqflags.h>
 #include <arch/system.h>
 
 /* the switch_to macro calls resume, an asm function in entry.S which does the actual
diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c
index 195ec5f..b82e086 100644
--- a/arch/cris/kernel/profile.c
+++ b/arch/cris/kernel/profile.c
@@ -59,6 +59,7 @@
 static const struct file_operations cris_proc_profile_operations = {
 	.read		= read_cris_profile,
 	.write		= write_cris_profile,
+	.llseek		= default_llseek,
 };
 
 static int __init init_cris_profile(void)
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 16399bd..0f2417d 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -7,6 +7,7 @@
 	default y
 	select HAVE_IDE
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 
 config ZONE_DMA
diff --git a/arch/frv/include/asm/ioctls.h b/arch/frv/include/asm/ioctls.h
index a993e37..2f9fb43 100644
--- a/arch/frv/include/asm/ioctls.h
+++ b/arch/frv/include/asm/ioctls.h
@@ -1,88 +1,10 @@
 #ifndef __ASM_IOCTLS_H__
 #define __ASM_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
 #define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define FIOQSIZE	0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ASM_IOCTLS_H__ */
 
diff --git a/arch/frv/include/asm/irqflags.h b/arch/frv/include/asm/irqflags.h
new file mode 100644
index 0000000..82f0b53
--- /dev/null
+++ b/arch/frv/include/asm/irqflags.h
@@ -0,0 +1,158 @@
+/* FR-V interrupt handling
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+/*
+ * interrupt flag manipulation
+ * - use virtual interrupt management since touching the PSR is slow
+ *   - ICC2.Z: T if interrupts virtually disabled
+ *   - ICC2.C: F if interrupts really disabled
+ * - if Z==1 upon interrupt:
+ *   - C is set to 0
+ *   - interrupts are really disabled
+ *   - entry.S returns immediately
+ * - uses TIHI (TRAP if Z==0 && C==0) #2 to really reenable interrupts
+ *   - if taken, the trap:
+ *     - sets ICC2.C
+ *     - enables interrupts
+ */
+static inline void arch_local_irq_disable(void)
+{
+	/* set Z flag, but don't change the C flag */
+	asm volatile("	andcc	gr0,gr0,gr0,icc2	\n"
+		     :
+		     :
+		     : "memory", "icc2"
+		     );
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	/* clear Z flag and then test the C flag */
+	asm volatile("  oricc	gr0,#1,gr0,icc2		\n"
+		     "	tihi	icc2,gr0,#2		\n"
+		     :
+		     :
+		     : "memory", "icc2"
+		     );
+}
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+
+	asm volatile("movsg ccr,%0"
+		     : "=r"(flags)
+		     :
+		     : "memory");
+
+	/* shift ICC2.Z to bit 0 */
+	flags >>= 26;
+
+	/* make flags 1 if interrupts disabled, 0 otherwise */
+	return flags & 1UL;
+
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags = arch_local_save_flags();
+	arch_local_irq_disable();
+	return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	/* load the Z flag by turning 1 if disabled into 0 if disabled
+	 * and thus setting the Z flag but not the C flag */
+	asm volatile("  xoricc	%0,#1,gr0,icc2		\n"
+		     /* then trap if Z=0 and C=0 */
+		     "	tihi	icc2,gr0,#2		\n"
+		     :
+		     : "r"(flags)
+		     : "memory", "icc2"
+		     );
+
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+/*
+ * real interrupt flag manipulation
+ */
+#define __arch_local_irq_disable()			\
+do {							\
+	unsigned long psr;				\
+	asm volatile("	movsg	psr,%0		\n"	\
+		     "	andi	%0,%2,%0	\n"	\
+		     "	ori	%0,%1,%0	\n"	\
+		     "	movgs	%0,psr		\n"	\
+		     : "=r"(psr)			\
+		     : "i" (PSR_PIL_14), "i" (~PSR_PIL)	\
+		     : "memory");			\
+} while (0)
+
+#define __arch_local_irq_enable()			\
+do {							\
+	unsigned long psr;				\
+	asm volatile("	movsg	psr,%0		\n"	\
+		     "	andi	%0,%1,%0	\n"	\
+		     "	movgs	%0,psr		\n"	\
+		     : "=r"(psr)			\
+		     : "i" (~PSR_PIL)			\
+		     : "memory");			\
+} while (0)
+
+#define __arch_local_save_flags(flags)		\
+do {						\
+	typecheck(unsigned long, flags);	\
+	asm("movsg psr,%0"			\
+	    : "=r"(flags)			\
+	    :					\
+	    : "memory");			\
+} while (0)
+
+#define	__arch_local_irq_save(flags)			\
+do {							\
+	unsigned long npsr;				\
+	typecheck(unsigned long, flags);		\
+	asm volatile("	movsg	psr,%0		\n"	\
+		     "	andi	%0,%3,%1	\n"	\
+		     "	ori	%1,%2,%1	\n"	\
+		     "	movgs	%1,psr		\n"	\
+		     : "=r"(flags), "=r"(npsr)		\
+		     : "i" (PSR_PIL_14), "i" (~PSR_PIL)	\
+		     : "memory");			\
+} while (0)
+
+#define	__arch_local_irq_restore(flags)			\
+do {							\
+	typecheck(unsigned long, flags);		\
+	asm volatile("	movgs	%0,psr		\n"	\
+		     :					\
+		     : "r" (flags)			\
+		     : "memory");			\
+} while (0)
+
+#define __arch_irqs_disabled()			\
+	((__get_PSR() & PSR_PIL) >= PSR_PIL_14)
+
+#endif /* _ASM_IRQFLAGS_H */
diff --git a/arch/frv/include/asm/system.h b/arch/frv/include/asm/system.h
index efd22d9..0a6d8d9 100644
--- a/arch/frv/include/asm/system.h
+++ b/arch/frv/include/asm/system.h
@@ -37,142 +37,6 @@
 } while(0)
 
 /*
- * interrupt flag manipulation
- * - use virtual interrupt management since touching the PSR is slow
- *   - ICC2.Z: T if interrupts virtually disabled
- *   - ICC2.C: F if interrupts really disabled
- * - if Z==1 upon interrupt:
- *   - C is set to 0
- *   - interrupts are really disabled
- *   - entry.S returns immediately
- * - uses TIHI (TRAP if Z==0 && C==0) #2 to really reenable interrupts
- *   - if taken, the trap:
- *     - sets ICC2.C
- *     - enables interrupts
- */
-#define local_irq_disable()					\
-do {								\
-	/* set Z flag, but don't change the C flag */		\
-	asm volatile("	andcc	gr0,gr0,gr0,icc2	\n"	\
-		     :						\
-		     :						\
-		     : "memory", "icc2"				\
-		     );						\
-} while(0)
-
-#define local_irq_enable()					\
-do {								\
-	/* clear Z flag and then test the C flag */		\
-	asm volatile("  oricc	gr0,#1,gr0,icc2		\n"	\
-		     "	tihi	icc2,gr0,#2		\n"	\
-		     :						\
-		     :						\
-		     : "memory", "icc2"				\
-		     );						\
-} while(0)
-
-#define local_save_flags(flags)					\
-do {								\
-	typecheck(unsigned long, flags);			\
-	asm volatile("movsg ccr,%0"				\
-		     : "=r"(flags)				\
-		     :						\
-		     : "memory");				\
-								\
-	/* shift ICC2.Z to bit 0 */				\
-	flags >>= 26;						\
-								\
-	/* make flags 1 if interrupts disabled, 0 otherwise */	\
-	flags &= 1UL;						\
-} while(0)
-
-#define irqs_disabled() \
-	({unsigned long flags; local_save_flags(flags); !!flags; })
-
-#define	local_irq_save(flags)			\
-do {						\
-	typecheck(unsigned long, flags);	\
-	local_save_flags(flags);		\
-	local_irq_disable();			\
-} while(0)
-
-#define	local_irq_restore(flags)					\
-do {									\
-	typecheck(unsigned long, flags);				\
-									\
-	/* load the Z flag by turning 1 if disabled into 0 if disabled	\
-	 * and thus setting the Z flag but not the C flag */		\
-	asm volatile("  xoricc	%0,#1,gr0,icc2		\n"		\
-		     /* then test Z=0 and C=0 */			\
-		     "	tihi	icc2,gr0,#2		\n"		\
-		     :							\
-		     : "r"(flags)					\
-		     : "memory", "icc2"					\
-		     );							\
-									\
-} while(0)
-
-/*
- * real interrupt flag manipulation
- */
-#define __local_irq_disable()				\
-do {							\
-	unsigned long psr;				\
-	asm volatile("	movsg	psr,%0		\n"	\
-		     "	andi	%0,%2,%0	\n"	\
-		     "	ori	%0,%1,%0	\n"	\
-		     "	movgs	%0,psr		\n"	\
-		     : "=r"(psr)			\
-		     : "i" (PSR_PIL_14), "i" (~PSR_PIL)	\
-		     : "memory");			\
-} while(0)
-
-#define __local_irq_enable()				\
-do {							\
-	unsigned long psr;				\
-	asm volatile("	movsg	psr,%0		\n"	\
-		     "	andi	%0,%1,%0	\n"	\
-		     "	movgs	%0,psr		\n"	\
-		     : "=r"(psr)			\
-		     : "i" (~PSR_PIL)			\
-		     : "memory");			\
-} while(0)
-
-#define __local_save_flags(flags)		\
-do {						\
-	typecheck(unsigned long, flags);	\
-	asm("movsg psr,%0"			\
-	    : "=r"(flags)			\
-	    :					\
-	    : "memory");			\
-} while(0)
-
-#define	__local_irq_save(flags)				\
-do {							\
-	unsigned long npsr;				\
-	typecheck(unsigned long, flags);		\
-	asm volatile("	movsg	psr,%0		\n"	\
-		     "	andi	%0,%3,%1	\n"	\
-		     "	ori	%1,%2,%1	\n"	\
-		     "	movgs	%1,psr		\n"	\
-		     : "=r"(flags), "=r"(npsr)		\
-		     : "i" (PSR_PIL_14), "i" (~PSR_PIL)	\
-		     : "memory");			\
-} while(0)
-
-#define	__local_irq_restore(flags)			\
-do {							\
-	typecheck(unsigned long, flags);		\
-	asm volatile("	movgs	%0,psr		\n"	\
-		     :					\
-		     : "r" (flags)			\
-		     : "memory");			\
-} while(0)
-
-#define __irqs_disabled() \
-	((__get_PSR() & PSR_PIL) >= PSR_PIL_14)
-
-/*
  * Force strict CPU ordering.
  */
 #define nop()			asm volatile ("nop"::)
diff --git a/arch/frv/lib/Makefile b/arch/frv/lib/Makefile
index f470975..4ff2fb1 100644
--- a/arch/frv/lib/Makefile
+++ b/arch/frv/lib/Makefile
@@ -5,4 +5,4 @@
 lib-y := \
 	__ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \
 	checksum.o memcpy.o memset.o atomic-ops.o atomic64-ops.o \
-	outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o perf_event.o
+	outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o
diff --git a/arch/frv/lib/perf_event.c b/arch/frv/lib/perf_event.c
deleted file mode 100644
index 9ac5acf..0000000
--- a/arch/frv/lib/perf_event.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Performance event handling
- *
- * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#include <linux/perf_event.h>
-
-/*
- * mark the performance event as pending
- */
-void set_perf_event_pending(void)
-{
-}
diff --git a/arch/h8300/include/asm/ioctls.h b/arch/h8300/include/asm/ioctls.h
index b6b249f..30eaed2 100644
--- a/arch/h8300/include/asm/ioctls.h
+++ b/arch/h8300/include/asm/ioctls.h
@@ -1,87 +1,8 @@
 #ifndef __ARCH_H8300_IOCTLS_H__
 #define __ARCH_H8300_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define FIOQSIZE	0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ARCH_H8300_IOCTLS_H__ */
diff --git a/arch/h8300/include/asm/irqflags.h b/arch/h8300/include/asm/irqflags.h
new file mode 100644
index 0000000..9617cd5
--- /dev/null
+++ b/arch/h8300/include/asm/irqflags.h
@@ -0,0 +1,43 @@
+#ifndef _H8300_IRQFLAGS_H
+#define _H8300_IRQFLAGS_H
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile ("stc ccr,%w0" : "=r" (flags));
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	asm volatile ("orc  #0x80,ccr" : : : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	asm volatile ("andc #0x7f,ccr" : : : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags = arch_local_save_flags();
+	arch_local_irq_disable();
+	return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile ("ldc %w0,ccr" : : "r" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags & 0x80) == 0x80;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _H8300_IRQFLAGS_H */
diff --git a/arch/h8300/include/asm/system.h b/arch/h8300/include/asm/system.h
index 16bf156..2c2382e 100644
--- a/arch/h8300/include/asm/system.h
+++ b/arch/h8300/include/asm/system.h
@@ -2,6 +2,7 @@
 #define _H8300_SYSTEM_H
 
 #include <linux/linkage.h>
+#include <linux/irqflags.h>
 
 struct pt_regs;
 
@@ -51,31 +52,8 @@
   (last) = _last; 					    \
 }
 
-#define __sti() asm volatile ("andc #0x7f,ccr")
-#define __cli() asm volatile ("orc  #0x80,ccr")
-
-#define __save_flags(x) \
-       asm volatile ("stc ccr,%w0":"=r" (x))
-
-#define __restore_flags(x) \
-       asm volatile ("ldc %w0,ccr": :"r" (x))
-
-#define	irqs_disabled()			\
-({					\
-	unsigned char flags;		\
-	__save_flags(flags);	        \
-	((flags & 0x80) == 0x80);	\
-})
-
 #define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
 
-/* For spinlocks etc */
-#define local_irq_disable()	__cli()
-#define local_irq_enable()      __sti()
-#define local_irq_save(x)	({ __save_flags(x); local_irq_disable(); })
-#define local_irq_restore(x)	__restore_flags(x)
-#define local_save_flags(x)     __save_flags(x)
-
 /*
  * Force strict CPU ordering.
  * Not really required on H8...
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c
index 0865e29..db4953d 100644
--- a/arch/h8300/kernel/module.c
+++ b/arch/h8300/kernel/module.c
@@ -112,10 +112,9 @@
 		    const Elf_Shdr *sechdrs,
 		    struct module *me)
 {
-	return module_bug_finalize(hdr, sechdrs, me);
+	return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
-	module_bug_cleanup(mod);
 }
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index ba22849..7c82fa1 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -53,6 +53,9 @@
 	bool
 	default y
 
+config ARCH_DMA_ADDR_T_64BIT
+	def_bool y
+
 config NEED_DMA_MAP_STATE
 	def_bool y
 
@@ -62,6 +65,9 @@
 config SWIOTLB
        bool
 
+config STACKTRACE_SUPPORT
+	def_bool y
+
 config GENERIC_LOCKBREAK
 	def_bool n
 
@@ -683,8 +689,10 @@
 # Use the generic interrupt handling code in kernel/irq/:
 #
 config GENERIC_HARDIRQS
-	bool
-	default y
+	def_bool y
+
+config GENERIC_HARDIRQS_NO__DO_IRQ
+	def_bool y
 
 config GENERIC_IRQ_PROBE
 	bool
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 1e8d71a..13633da 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -395,7 +395,7 @@
 {
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
 	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	    (cmd != TIOCMIWAIT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -433,16 +433,6 @@
 		case TIOCMIWAIT:
 			printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n");
 			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.
-		 */
-		case TIOCGICOUNT:
-			printk(KERN_INFO "rs_ioctl: TIOCGICOUNT called\n");
-			return 0;
-
 		case TIOCSERGWILD:
 		case TIOCSERSWILD:
 			/* "setserial -W" is called in Debian boot */
diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h
deleted file mode 100644
index 9301a28..0000000
--- a/arch/ia64/include/asm/compat.h
+++ /dev/null
@@ -1,208 +0,0 @@
-#ifndef _ASM_IA64_COMPAT_H
-#define _ASM_IA64_COMPAT_H
-/*
- * Architecture specific compatibility types
- */
-#include <linux/types.h>
-
-#define COMPAT_USER_HZ		100
-#define COMPAT_UTS_MACHINE	"i686\0\0\0"
-
-typedef u32		compat_size_t;
-typedef s32		compat_ssize_t;
-typedef s32		compat_time_t;
-typedef s32		compat_clock_t;
-typedef s32		compat_key_t;
-typedef s32		compat_pid_t;
-typedef u16		__compat_uid_t;
-typedef u16		__compat_gid_t;
-typedef u32		__compat_uid32_t;
-typedef u32		__compat_gid32_t;
-typedef u16		compat_mode_t;
-typedef u32		compat_ino_t;
-typedef u16		compat_dev_t;
-typedef s32		compat_off_t;
-typedef s64		compat_loff_t;
-typedef u16		compat_nlink_t;
-typedef u16		compat_ipc_pid_t;
-typedef s32		compat_daddr_t;
-typedef u32		compat_caddr_t;
-typedef __kernel_fsid_t	compat_fsid_t;
-typedef s32		compat_timer_t;
-
-typedef s32		compat_int_t;
-typedef s32		compat_long_t;
-typedef s64 __attribute__((aligned(4))) compat_s64;
-typedef u32		compat_uint_t;
-typedef u32		compat_ulong_t;
-typedef u64 __attribute__((aligned(4))) compat_u64;
-
-struct compat_timespec {
-	compat_time_t	tv_sec;
-	s32		tv_nsec;
-};
-
-struct compat_timeval {
-	compat_time_t	tv_sec;
-	s32		tv_usec;
-};
-
-struct compat_stat {
-	compat_dev_t	st_dev;
-	u16		__pad1;
-	compat_ino_t	st_ino;
-	compat_mode_t	st_mode;
-	compat_nlink_t	st_nlink;
-	__compat_uid_t	st_uid;
-	__compat_gid_t	st_gid;
-	compat_dev_t	st_rdev;
-	u16		__pad2;
-	u32		st_size;
-	u32		st_blksize;
-	u32		st_blocks;
-	u32		st_atime;
-	u32		st_atime_nsec;
-	u32		st_mtime;
-	u32		st_mtime_nsec;
-	u32		st_ctime;
-	u32		st_ctime_nsec;
-	u32		__unused4;
-	u32		__unused5;
-};
-
-struct compat_flock {
-	short		l_type;
-	short		l_whence;
-	compat_off_t	l_start;
-	compat_off_t	l_len;
-	compat_pid_t	l_pid;
-};
-
-#define F_GETLK64	12
-#define F_SETLK64	13
-#define F_SETLKW64	14
-
-/*
- * IA32 uses 4 byte alignment for 64 bit quantities,
- * so we need to pack this structure.
- */
-struct compat_flock64 {
-	short		l_type;
-	short		l_whence;
-	compat_loff_t	l_start;
-	compat_loff_t	l_len;
-	compat_pid_t	l_pid;
-} __attribute__((packed));
-
-struct compat_statfs {
-	int		f_type;
-	int		f_bsize;
-	int		f_blocks;
-	int		f_bfree;
-	int		f_bavail;
-	int		f_files;
-	int		f_ffree;
-	compat_fsid_t	f_fsid;
-	int		f_namelen;	/* SunOS ignores this field. */
-	int		f_frsize;
-	int		f_spare[5];
-};
-
-#define COMPAT_RLIM_OLD_INFINITY       0x7fffffff
-#define COMPAT_RLIM_INFINITY           0xffffffff
-
-typedef u32		compat_old_sigset_t;	/* at least 32 bits */
-
-#define _COMPAT_NSIG		64
-#define _COMPAT_NSIG_BPW	32
-
-typedef u32		compat_sigset_word;
-
-#define COMPAT_OFF_T_MAX	0x7fffffff
-#define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
-
-struct compat_ipc64_perm {
-	compat_key_t key;
-	__compat_uid32_t uid;
-	__compat_gid32_t gid;
-	__compat_uid32_t cuid;
-	__compat_gid32_t cgid;
-	unsigned short mode;
-	unsigned short __pad1;
-	unsigned short seq;
-	unsigned short __pad2;
-	compat_ulong_t unused1;
-	compat_ulong_t unused2;
-};
-
-struct compat_semid64_ds {
-	struct compat_ipc64_perm sem_perm;
-	compat_time_t  sem_otime;
-	compat_ulong_t __unused1;
-	compat_time_t  sem_ctime;
-	compat_ulong_t __unused2;
-	compat_ulong_t sem_nsems;
-	compat_ulong_t __unused3;
-	compat_ulong_t __unused4;
-};
-
-struct compat_msqid64_ds {
-	struct compat_ipc64_perm msg_perm;
-	compat_time_t  msg_stime;
-	compat_ulong_t __unused1;
-	compat_time_t  msg_rtime;
-	compat_ulong_t __unused2;
-	compat_time_t  msg_ctime;
-	compat_ulong_t __unused3;
-	compat_ulong_t msg_cbytes;
-	compat_ulong_t msg_qnum;
-	compat_ulong_t msg_qbytes;
-	compat_pid_t   msg_lspid;
-	compat_pid_t   msg_lrpid;
-	compat_ulong_t __unused4;
-	compat_ulong_t __unused5;
-};
-
-struct compat_shmid64_ds {
-	struct compat_ipc64_perm shm_perm;
-	compat_size_t  shm_segsz;
-	compat_time_t  shm_atime;
-	compat_ulong_t __unused1;
-	compat_time_t  shm_dtime;
-	compat_ulong_t __unused2;
-	compat_time_t  shm_ctime;
-	compat_ulong_t __unused3;
-	compat_pid_t   shm_cpid;
-	compat_pid_t   shm_lpid;
-	compat_ulong_t shm_nattch;
-	compat_ulong_t __unused4;
-	compat_ulong_t __unused5;
-};
-
-/*
- * A pointer passed in from user mode. This should not be used for syscall parameters,
- * just declare them as pointers because the syscall entry code will have appropriately
- * converted them already.
- */
-typedef	u32		compat_uptr_t;
-
-static inline void __user *
-compat_ptr (compat_uptr_t uptr)
-{
-	return (void __user *) (unsigned long) uptr;
-}
-
-static inline compat_uptr_t
-ptr_to_compat(void __user *uptr)
-{
-	return (u32)(unsigned long)uptr;
-}
-
-static __inline__ void __user *
-arch_compat_alloc_user_space (long len)
-{
-	struct pt_regs *regs = task_pt_regs(current);
-	return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
-}
-
-#endif /* _ASM_IA64_COMPAT_H */
diff --git a/arch/ia64/include/asm/hardirq.h b/arch/ia64/include/asm/hardirq.h
index d514cd9..8fb7d33 100644
--- a/arch/ia64/include/asm/hardirq.h
+++ b/arch/ia64/include/asm/hardirq.h
@@ -6,12 +6,6 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-
-#include <linux/threads.h>
-#include <linux/irq.h>
-
-#include <asm/processor.h>
-
 /*
  * No irq_cpustat_t for IA-64.  The data is held in the per-CPU data structure.
  */
@@ -20,6 +14,11 @@
 
 #define local_softirq_pending()		(local_cpu_data->softirq_pending)
 
+#include <linux/threads.h>
+#include <linux/irq.h>
+
+#include <asm/processor.h>
+
 extern void __iomem *ipi_base_addr;
 
 void ack_bad_irq(unsigned int irq);
diff --git a/arch/ia64/include/asm/ioctls.h b/arch/ia64/include/asm/ioctls.h
index b79c385..f3aab551 100644
--- a/arch/ia64/include/asm/ioctls.h
+++ b/arch/ia64/include/asm/ioctls.h
@@ -1,93 +1,6 @@
 #ifndef _ASM_IA64_IOCTLS_H
 #define _ASM_IA64_IOCTLS_H
 
-/*
- * Based on <asm-i386/ioctls.h>
- *
- * Modified 1998, 1999, 2002
- *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402	/* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-#define FIOQSIZE	0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* _ASM_IA64_IOCTLS_H */
diff --git a/arch/ia64/include/asm/iommu_table.h b/arch/ia64/include/asm/iommu_table.h
new file mode 100644
index 0000000..92c8d36
--- /dev/null
+++ b/arch/ia64/include/asm/iommu_table.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_IA64_IOMMU_TABLE_H
+#define _ASM_IA64_IOMMU_TABLE_H
+
+#define IOMMU_INIT_POST(_detect)
+
+#endif /* _ASM_IA64_IOMMU_TABLE_H */
diff --git a/arch/ia64/include/asm/irqflags.h b/arch/ia64/include/asm/irqflags.h
new file mode 100644
index 0000000..f82d6be
--- /dev/null
+++ b/arch/ia64/include/asm/irqflags.h
@@ -0,0 +1,94 @@
+/*
+ * IRQ flags defines.
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+
+#ifndef _ASM_IA64_IRQFLAGS_H
+#define _ASM_IA64_IRQFLAGS_H
+
+#ifdef CONFIG_IA64_DEBUG_IRQ
+extern unsigned long last_cli_ip;
+static inline void arch_maybe_save_ip(unsigned long flags)
+{
+	if (flags & IA64_PSR_I)
+		last_cli_ip = ia64_getreg(_IA64_REG_IP);
+}
+#else
+#define arch_maybe_save_ip(flags) do {} while (0)
+#endif
+
+/*
+ * - clearing psr.i is implicitly serialized (visible by next insn)
+ * - setting psr.i requires data serialization
+ * - we need a stop-bit before reading PSR because we sometimes
+ *   write a floating-point register right before reading the PSR
+ *   and that writes to PSR.mfl
+ */
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	ia64_stop();
+#ifdef CONFIG_PARAVIRT
+	return ia64_get_psr_i();
+#else
+	return ia64_getreg(_IA64_REG_PSR);
+#endif
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags = arch_local_save_flags();
+
+	ia64_stop();
+	ia64_rsm(IA64_PSR_I);
+	arch_maybe_save_ip(flags);
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+#ifdef CONFIG_IA64_DEBUG_IRQ
+	arch_local_irq_save();
+#else
+	ia64_stop();
+	ia64_rsm(IA64_PSR_I);
+#endif
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	ia64_stop();
+	ia64_ssm(IA64_PSR_I);
+	ia64_srlz_d();
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+#ifdef CONFIG_IA64_DEBUG_IRQ
+	unsigned long old_psr = arch_local_save_flags();
+#endif
+	ia64_intrin_local_irq_restore(flags & IA64_PSR_I);
+	arch_maybe_save_ip(old_psr & ~flags);
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags & IA64_PSR_I) == 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+static inline void arch_safe_halt(void)
+{
+	ia64_pal_halt_light();	/* PAL_HALT_LIGHT */
+}
+
+
+#endif /* _ASM_IA64_IRQFLAGS_H */
diff --git a/arch/ia64/include/asm/system.h b/arch/ia64/include/asm/system.h
index 9f342a5..6cca307 100644
--- a/arch/ia64/include/asm/system.h
+++ b/arch/ia64/include/asm/system.h
@@ -107,87 +107,11 @@
  */
 #define set_mb(var, value)	do { (var) = (value); mb(); } while (0)
 
-#define safe_halt()         ia64_pal_halt_light()    /* PAL_HALT_LIGHT */
-
 /*
  * The group barrier in front of the rsm & ssm are necessary to ensure
  * that none of the previous instructions in the same group are
  * affected by the rsm/ssm.
  */
-/* For spinlocks etc */
-
-/*
- * - clearing psr.i is implicitly serialized (visible by next insn)
- * - setting psr.i requires data serialization
- * - we need a stop-bit before reading PSR because we sometimes
- *   write a floating-point register right before reading the PSR
- *   and that writes to PSR.mfl
- */
-#ifdef CONFIG_PARAVIRT
-#define __local_save_flags()	ia64_get_psr_i()
-#else
-#define __local_save_flags()	ia64_getreg(_IA64_REG_PSR)
-#endif
-
-#define __local_irq_save(x)			\
-do {						\
-	ia64_stop();				\
-	(x) = __local_save_flags();		\
-	ia64_stop();				\
-	ia64_rsm(IA64_PSR_I);			\
-} while (0)
-
-#define __local_irq_disable()			\
-do {						\
-	ia64_stop();				\
-	ia64_rsm(IA64_PSR_I);			\
-} while (0)
-
-#define __local_irq_restore(x)	ia64_intrin_local_irq_restore((x) & IA64_PSR_I)
-
-#ifdef CONFIG_IA64_DEBUG_IRQ
-
-  extern unsigned long last_cli_ip;
-
-# define __save_ip()		last_cli_ip = ia64_getreg(_IA64_REG_IP)
-
-# define local_irq_save(x)					\
-do {								\
-	unsigned long __psr;					\
-								\
-	__local_irq_save(__psr);				\
-	if (__psr & IA64_PSR_I)					\
-		__save_ip();					\
-	(x) = __psr;						\
-} while (0)
-
-# define local_irq_disable()	do { unsigned long __x; local_irq_save(__x); } while (0)
-
-# define local_irq_restore(x)					\
-do {								\
-	unsigned long __old_psr, __psr = (x);			\
-								\
-	local_save_flags(__old_psr);				\
-	__local_irq_restore(__psr);				\
-	if ((__old_psr & IA64_PSR_I) && !(__psr & IA64_PSR_I))	\
-		__save_ip();					\
-} while (0)
-
-#else /* !CONFIG_IA64_DEBUG_IRQ */
-# define local_irq_save(x)	__local_irq_save(x)
-# define local_irq_disable()	__local_irq_disable()
-# define local_irq_restore(x)	__local_irq_restore(x)
-#endif /* !CONFIG_IA64_DEBUG_IRQ */
-
-#define local_irq_enable()	({ ia64_stop(); ia64_ssm(IA64_PSR_I); ia64_srlz_d(); })
-#define local_save_flags(flags)	({ ia64_stop(); (flags) = __local_save_flags(); })
-
-#define irqs_disabled()				\
-({						\
-	unsigned long __ia64_id_flags;		\
-	local_save_flags(__ia64_id_flags);	\
-	(__ia64_id_flags & IA64_PSR_I) == 0;	\
-})
 
 #ifdef __KERNEL__
 
@@ -272,10 +196,6 @@
 
 void default_idle(void);
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void account_system_vtime(struct task_struct *);
-#endif
-
 #endif /* __KERNEL__ */
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index db10b1e..395c2f2 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -34,6 +34,7 @@
 obj-$(CONFIG_PCI_MSI)		+= msi_ia64.o
 mca_recovery-y			+= mca_drv.o mca_drv_asm.o
 obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o
+obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 
 obj-$(CONFIG_PARAVIRT)		+= paravirt.o paravirtentry.o \
 				   paravirt_patch.o
diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
index 71e3586..d52f1f7 100644
--- a/arch/ia64/kernel/cyclone.c
+++ b/arch/ia64/kernel/cyclone.c
@@ -59,13 +59,13 @@
 		return -ENODEV;
 	}
 	base = readq(reg);
+	iounmap(reg);
 	if(!base){
 		printk(KERN_ERR "Summit chipset: Could not find valid CBAR"
 				" value.\n");
 		use_cyclone = 0;
 		return -ENODEV;
 	}
-	iounmap(reg);
 
 	/* setup PMCC */
 	offset = (base + CYCLONE_PMCC_OFFSET);
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 7ded766..22c3840 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -108,10 +108,6 @@
 #define DBG(fmt...)
 #endif
 
-#define NR_PREALLOCATE_RTE_ENTRIES \
-	(PAGE_SIZE / sizeof(struct iosapic_rte_info))
-#define RTE_PREALLOCATED	(1)
-
 static DEFINE_SPINLOCK(iosapic_lock);
 
 /*
@@ -136,7 +132,6 @@
 	struct list_head rte_list;	/* RTEs sharing the same vector */
 	char		rte_index;	/* IOSAPIC RTE index */
 	int		refcnt;		/* reference counter */
-	unsigned int	flags;		/* flags */
 	struct iosapic	*iosapic;
 } ____cacheline_aligned;
 
@@ -155,9 +150,6 @@
 
 static unsigned char pcat_compat __devinitdata;	/* 8259 compatibility flag */
 
-static int iosapic_kmalloc_ok;
-static LIST_HEAD(free_rte_list);
-
 static inline void
 iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val)
 {
@@ -394,7 +386,7 @@
 }
 
 static void
-iosapic_end_level_irq (unsigned int irq)
+iosapic_unmask_level_irq (unsigned int irq)
 {
 	ia64_vector vec = irq_to_vector(irq);
 	struct iosapic_rte_info *rte;
@@ -404,7 +396,8 @@
 	if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
 		do_unmask_irq = 1;
 		mask_irq(irq);
-	}
+	} else
+		unmask_irq(irq);
 
 	list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
 		iosapic_eoi(rte->iosapic->addr, vec);
@@ -427,9 +420,8 @@
 	.enable =	iosapic_enable_level_irq,
 	.disable =	iosapic_disable_level_irq,
 	.ack =		iosapic_ack_level_irq,
-	.end =		iosapic_end_level_irq,
 	.mask =		mask_irq,
-	.unmask =	unmask_irq,
+	.unmask =	iosapic_unmask_level_irq,
 	.set_affinity =	iosapic_set_affinity
 };
 
@@ -552,37 +544,6 @@
 	}
 }
 
-static struct iosapic_rte_info * __init_refok iosapic_alloc_rte (void)
-{
-	int i;
-	struct iosapic_rte_info *rte;
-	int preallocated = 0;
-
-	if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) {
-		rte = alloc_bootmem(sizeof(struct iosapic_rte_info) *
-				    NR_PREALLOCATE_RTE_ENTRIES);
-		for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++)
-			list_add(&rte->rte_list, &free_rte_list);
-	}
-
-	if (!list_empty(&free_rte_list)) {
-		rte = list_entry(free_rte_list.next, struct iosapic_rte_info,
-				 rte_list);
-		list_del(&rte->rte_list);
-		preallocated++;
-	} else {
-		rte = kmalloc(sizeof(struct iosapic_rte_info), GFP_ATOMIC);
-		if (!rte)
-			return NULL;
-	}
-
-	memset(rte, 0, sizeof(struct iosapic_rte_info));
-	if (preallocated)
-		rte->flags |= RTE_PREALLOCATED;
-
-	return rte;
-}
-
 static inline int irq_is_shared (int irq)
 {
 	return (iosapic_intr_info[irq].count > 1);
@@ -615,7 +576,7 @@
 
 	rte = find_rte(irq, gsi);
 	if (!rte) {
-		rte = iosapic_alloc_rte();
+		rte = kzalloc(sizeof (*rte), GFP_ATOMIC);
 		if (!rte) {
 			printk(KERN_WARNING "%s: cannot allocate memory\n",
 			       __func__);
@@ -658,6 +619,10 @@
 			       idesc->chip->name, irq_type->name);
 		idesc->chip = irq_type;
 	}
+	if (trigger == IOSAPIC_EDGE)
+		__set_irq_handler_unlocked(irq, handle_edge_irq);
+	else
+		__set_irq_handler_unlocked(irq, handle_level_irq);
 	return 0;
 }
 
@@ -1161,10 +1126,3 @@
 	return;
 }
 #endif
-
-static int __init iosapic_enable_kmalloc (void)
-{
-	iosapic_kmalloc_ok = 1;
-	return 0;
-}
-core_initcall (iosapic_enable_kmalloc);
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index f14c35f..9a26015 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -30,6 +30,7 @@
 #include <linux/bitops.h>
 #include <linux/irq.h>
 #include <linux/ratelimit.h>
+#include <linux/acpi.h>
 
 #include <asm/delay.h>
 #include <asm/intrinsics.h>
@@ -635,6 +636,7 @@
 	desc->chip = &irq_type_ia64_lsapic;
 	if (action)
 		setup_irq(irq, action);
+	set_irq_handler(irq, handle_percpu_irq);
 }
 
 void __init
@@ -650,6 +652,9 @@
 void __init
 init_IRQ (void)
 {
+#ifdef CONFIG_ACPI
+	acpi_boot_init();
+#endif
 	ia64_register_ipi();
 	register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
 #ifdef CONFIG_SMP
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index a0220dc..1753f6a 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -2055,25 +2055,6 @@
 
 	IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __func__);
 
-	/*
-	 *  Configure the CMCI/P vector and handler. Interrupts for CMC are
-	 *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
-	 */
-	register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
-	register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction);
-	ia64_mca_cmc_vector_setup();       /* Setup vector on BSP */
-
-	/* Setup the MCA rendezvous interrupt vector */
-	register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
-
-	/* Setup the MCA wakeup interrupt vector */
-	register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
-
-#ifdef CONFIG_ACPI
-	/* Setup the CPEI/P handler */
-	register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
-#endif
-
 	/* Initialize the areas set aside by the OS to buffer the
 	 * platform/processor error states for MCA/INIT/CMC
 	 * handling.
@@ -2103,6 +2084,25 @@
 	if (!mca_init)
 		return 0;
 
+	/*
+	 *  Configure the CMCI/P vector and handler. Interrupts for CMC are
+	 *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
+	 */
+	register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
+	register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction);
+	ia64_mca_cmc_vector_setup();       /* Setup vector on BSP */
+
+	/* Setup the MCA rendezvous interrupt vector */
+	register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
+
+	/* Setup the MCA wakeup interrupt vector */
+	register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
+
+#ifdef CONFIG_ACPI
+	/* Setup the CPEI/P handler */
+	register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
+#endif
+
 	register_hotcpu_notifier(&mca_cpu_notifier);
 
 	/* Setup the CMCI/P vector and handler */
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index 4a746ea..00b19a4 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -104,8 +104,8 @@
  */
 static struct irq_chip ia64_msi_chip = {
 	.name		= "PCI-MSI",
-	.mask		= mask_msi_irq,
-	.unmask		= unmask_msi_irq,
+	.irq_mask	= mask_msi_irq,
+	.irq_unmask	= unmask_msi_irq,
 	.ack		= ia64_ack_msi_irq,
 #ifdef CONFIG_SMP
 	.set_affinity	= ia64_set_msi_irq_affinity,
@@ -160,8 +160,8 @@
 
 static struct irq_chip dmar_msi_type = {
 	.name = "DMAR_MSI",
-	.unmask = dmar_msi_unmask,
-	.mask = dmar_msi_mask,
+	.irq_unmask = dmar_msi_unmask,
+	.irq_mask = dmar_msi_mask,
 	.ack = ia64_ack_msi_irq,
 #ifdef CONFIG_SMP
 	.set_affinity = dmar_msi_set_affinity,
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index fdf6f9d..77597e5 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -434,7 +434,7 @@
 	unsigned long phys_stacked;
 	pal_hints_u_t hints;
 	unsigned long iregs, dregs;
-	char *info_type[]={
+	static const char * const info_type[] = {
 		"Implemented AR(s)",
 		"AR(s) with read side-effects",
 		"Implemented CR(s)",
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index cce050e..6b1852f 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -1573,7 +1573,7 @@
 		return -EINVAL;
 	}
 
-	ctx = (pfm_context_t *)filp->private_data;
+	ctx = filp->private_data;
 	if (ctx == NULL) {
 		printk(KERN_ERR "perfmon: pfm_read: NULL ctx [%d]\n", task_pid_nr(current));
 		return -EINVAL;
@@ -1673,7 +1673,7 @@
 		return 0;
 	}
 
-	ctx = (pfm_context_t *)filp->private_data;
+	ctx = filp->private_data;
 	if (ctx == NULL) {
 		printk(KERN_ERR "perfmon: pfm_poll: NULL ctx [%d]\n", task_pid_nr(current));
 		return 0;
@@ -1733,7 +1733,7 @@
 		return -EBADF;
 	}
 
-	ctx = (pfm_context_t *)filp->private_data;
+	ctx = filp->private_data;
 	if (ctx == NULL) {
 		printk(KERN_ERR "perfmon: pfm_fasync NULL ctx [%d]\n", task_pid_nr(current));
 		return -EBADF;
@@ -1841,7 +1841,7 @@
 		return -EBADF;
 	}
 
-	ctx = (pfm_context_t *)filp->private_data;
+	ctx = filp->private_data;
 	if (ctx == NULL) {
 		printk(KERN_ERR "perfmon: pfm_flush: NULL ctx [%d]\n", task_pid_nr(current));
 		return -EBADF;
@@ -1984,7 +1984,7 @@
 		return -EBADF;
 	}
 	
-	ctx = (pfm_context_t *)filp->private_data;
+	ctx = filp->private_data;
 	if (ctx == NULL) {
 		printk(KERN_ERR "perfmon: pfm_close: NULL ctx [%d]\n", task_pid_nr(current));
 		return -EBADF;
@@ -4907,7 +4907,7 @@
 		goto error_args;
 	}
 
-	ctx = (pfm_context_t *)file->private_data;
+	ctx = file->private_data;
 	if (unlikely(ctx == NULL)) {
 		DPRINT(("no context for fd %d\n", fd));
 		goto error_args;
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index aa8b5fa..79802e5 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -354,6 +354,7 @@
 static const struct file_operations salinfo_event_fops = {
 	.open  = salinfo_event_open,
 	.read  = salinfo_event_read,
+	.llseek = noop_llseek,
 };
 
 static int
@@ -571,6 +572,7 @@
 	.release = salinfo_log_release,
 	.read    = salinfo_log_read,
 	.write   = salinfo_log_write,
+	.llseek  = default_llseek,
 };
 
 static int __cpuinit
@@ -642,7 +644,7 @@
 	for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
 		data = salinfo_data + i;
 		data->type = i;
-		init_MUTEX(&data->mutex);
+		sema_init(&data->mutex, 1);
 		dir = proc_mkdir(salinfo_log_name[i], salinfo_dir);
 		if (!dir)
 			continue;
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 8fb958a..911cf97 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -594,10 +594,6 @@
 	cpu_init();	/* initialize the bootstrap CPU */
 	mmu_context_init();	/* initialize context_id bitmap */
 
-#ifdef CONFIG_ACPI
-	acpi_boot_init();
-#endif
-
 	paravirt_banner();
 	paravirt_arch_setup_console(cmdline_p);
 
diff --git a/arch/ia64/kernel/stacktrace.c b/arch/ia64/kernel/stacktrace.c
new file mode 100644
index 0000000..5af2783
--- /dev/null
+++ b/arch/ia64/kernel/stacktrace.c
@@ -0,0 +1,39 @@
+/*
+ * arch/ia64/kernel/stacktrace.c
+ *
+ * Stack trace management functions
+ *
+ */
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/module.h>
+
+static void
+ia64_do_save_stack(struct unw_frame_info *info, void *arg)
+{
+	struct stack_trace *trace = arg;
+	unsigned long ip;
+	int skip = trace->skip;
+
+	trace->nr_entries = 0;
+	do {
+		unw_get_ip(info, &ip);
+		if (ip == 0)
+			break;
+		if (skip == 0) {
+			trace->entries[trace->nr_entries++] = ip;
+			if (trace->nr_entries == trace->max_entries)
+				break;
+		} else
+			skip--;
+	} while (unw_unwind(info) >= 0);
+}
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace)
+{
+	unw_init_running(ia64_do_save_stack, trace);
+}
+EXPORT_SYMBOL(save_stack_trace);
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index b6c0e63..fed6afa 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -1204,10 +1204,10 @@
 static inline unw_hash_index_t
 hash (unsigned long ip)
 {
-#	define hashmagic	0x9e3779b97f4a7c16UL	/* based on (sqrt(5)/2-1)*2^64 */
+	/* magic number = ((sqrt(5)-1)/2)*2^64 */
+	static const unsigned long hashmagic = 0x9e3779b97f4a7c16UL;
 
-	return (ip >> 4)*hashmagic >> (64 - UNW_LOG_HASH_SIZE);
-#undef hashmagic
+	return (ip >> 4) * hashmagic >> (64 - UNW_LOG_HASH_SIZE);
 }
 
 static inline long
@@ -1531,7 +1531,7 @@
 	struct unw_labeled_state *ls, *next;
 	unsigned long ip = info->ip;
 	struct unw_state_record sr;
-	struct unw_table *table;
+	struct unw_table *table, *prev;
 	struct unw_reg_info *r;
 	struct unw_insn insn;
 	u8 *dp, *desc_end;
@@ -1560,11 +1560,26 @@
 
 	STAT(parse_start = ia64_get_itc());
 
+	prev = NULL;
 	for (table = unw.tables; table; table = table->next) {
 		if (ip >= table->start && ip < table->end) {
+			/*
+			 * Leave the kernel unwind table at the very front,
+			 * lest moving it breaks some assumption elsewhere.
+			 * Otherwise, move the matching table to the second
+			 * position in the list so that traversals can benefit
+			 * from commonality in backtrace paths.
+			 */
+			if (prev && prev != unw.tables) {
+				/* unw is safe - we're already spinlocked */
+				prev->next = table->next;
+				table->next = unw.tables->next;
+				unw.tables->next = table;
+			}
 			e = lookup(table, ip - table->segment_base);
 			break;
 		}
+		prev = table;
 	}
 	if (!e) {
 		/* no info, return default unwinder (leaf proc, no mem stack, no saved regs)  */
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c
index 0c72dd4..a5e500f 100644
--- a/arch/ia64/sn/kernel/msi_sn.c
+++ b/arch/ia64/sn/kernel/msi_sn.c
@@ -228,8 +228,8 @@
 
 static struct irq_chip sn_msi_chip = {
 	.name		= "PCI-MSI",
-	.mask		= mask_msi_irq,
-	.unmask		= unmask_msi_irq,
+	.irq_mask	= mask_msi_irq,
+	.irq_unmask	= unmask_msi_irq,
 	.ack		= sn_ack_msi_irq,
 #ifdef CONFIG_SMP
 	.set_affinity	= sn_set_msi_irq_affinity,
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index fa1ecee..30862c0 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -860,6 +860,7 @@
 
 static const struct file_operations sn_hwperf_fops = {
 	.unlocked_ioctl = sn_hwperf_ioctl,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice sn_hwperf_dev = {
diff --git a/arch/ia64/xen/xen_pv_ops.c b/arch/ia64/xen/xen_pv_ops.c
index 8adc6a1..3e8d350 100644
--- a/arch/ia64/xen/xen_pv_ops.c
+++ b/arch/ia64/xen/xen_pv_ops.c
@@ -1136,7 +1136,6 @@
 static void __init
 xen_patch_branch(unsigned long tag, unsigned long type)
 {
-	const unsigned long nelem =
-		sizeof(xen_branch_target) / sizeof(xen_branch_target[0]);
-	__paravirt_patch_apply_branch(tag, type, xen_branch_target, nelem);
+	__paravirt_patch_apply_branch(tag, type, xen_branch_target,
+					ARRAY_SIZE(xen_branch_target));
 }
diff --git a/arch/m32r/include/asm/elf.h b/arch/m32r/include/asm/elf.h
index 2f85412..b8da7d0 100644
--- a/arch/m32r/include/asm/elf.h
+++ b/arch/m32r/include/asm/elf.h
@@ -82,9 +82,9 @@
  * These are used to set parameters in the core dumps.
  */
 #define ELF_CLASS	ELFCLASS32
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN__)
 #define ELF_DATA	ELFDATA2LSB
-#elif defined(__BIG_ENDIAN)
+#elif defined(__BIG_ENDIAN__)
 #define ELF_DATA	ELFDATA2MSB
 #else
 #error no endian defined
diff --git a/arch/m32r/include/asm/ioctls.h b/arch/m32r/include/asm/ioctls.h
index 6628806..349bf87 100644
--- a/arch/m32r/include/asm/ioctls.h
+++ b/arch/m32r/include/asm/ioctls.h
@@ -1,87 +1,6 @@
 #ifndef __ARCH_M32R_IOCTLS_H__
 #define __ARCH_M32R_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-#define FIOQSIZE	0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ARCH_M32R_IOCTLS_H__ */
diff --git a/arch/m32r/include/asm/irqflags.h b/arch/m32r/include/asm/irqflags.h
new file mode 100644
index 0000000..1f92d29
--- /dev/null
+++ b/arch/m32r/include/asm/irqflags.h
@@ -0,0 +1,104 @@
+/*
+ * 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  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#ifndef _ASM_M32R_IRQFLAGS_H
+#define _ASM_M32R_IRQFLAGS_H
+
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile("mvfc %0,psw" : "=r"(flags));
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
+	asm volatile (
+		"clrpsw #0x40 -> nop"
+		: : : "memory");
+#else
+	unsigned long tmpreg0, tmpreg1;
+	asm volatile (
+		"ld24	%0, #0	; Use 32-bit insn.			\n\t"
+		"mvfc	%1, psw	; No interrupt can be accepted here.	\n\t"
+		"mvtc	%0, psw						\n\t"
+		"and3	%0, %1, #0xffbf					\n\t"
+		"mvtc	%0, psw						\n\t"
+		: "=&r" (tmpreg0), "=&r" (tmpreg1)
+		:
+		: "cbit", "memory");
+#endif
+}
+
+static inline void arch_local_irq_enable(void)
+{
+#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
+	asm volatile (
+		"setpsw #0x40 -> nop"
+		: : : "memory");
+#else
+	unsigned long tmpreg;
+	asm volatile (
+		"mvfc	%0, psw;		\n\t"
+		"or3	%0, %0, #0x0040;	\n\t"
+		"mvtc	%0, psw;		\n\t"
+		: "=&r" (tmpreg)
+		:
+		: "cbit", "memory");
+#endif
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+
+#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
+	asm volatile (
+		"mvfc	%0, psw;	\n\t"
+		"clrpsw	#0x40 -> nop;	\n\t"
+		: "=r" (flags)
+		:
+		: "memory");
+#else
+	unsigned long tmpreg;
+	asm volatile (
+		"ld24	%1, #0		\n\t"
+		"mvfc	%0, psw		\n\t"
+		"mvtc	%1, psw		\n\t"
+		"and3	%1, %0, #0xffbf	\n\t"
+		"mvtc	%1, psw		\n\t"
+		: "=r" (flags), "=&r" (tmpreg)
+		:
+		: "cbit", "memory");
+#endif
+	return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile("mvtc %0,psw"
+		     :
+		     : "r" (flags)
+		     : "cbit", "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return !(flags & 0x40);
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _ASM_M32R_IRQFLAGS_H */
diff --git a/arch/m32r/include/asm/signal.h b/arch/m32r/include/asm/signal.h
index 9c1acb2..b2eeb0d 100644
--- a/arch/m32r/include/asm/signal.h
+++ b/arch/m32r/include/asm/signal.h
@@ -157,7 +157,6 @@
 #undef __HAVE_ARCH_SIG_BITOPS
 
 struct pt_regs;
-extern int do_signal(struct pt_regs *regs, sigset_t *oldset);
 
 #define ptrace_signal_deliver(regs, cookie)	do { } while (0)
 
diff --git a/arch/m32r/include/asm/system.h b/arch/m32r/include/asm/system.h
index c980f5b..13c4679 100644
--- a/arch/m32r/include/asm/system.h
+++ b/arch/m32r/include/asm/system.h
@@ -11,6 +11,7 @@
  */
 
 #include <linux/compiler.h>
+#include <linux/irqflags.h>
 #include <asm/assembler.h>
 
 #ifdef __KERNEL__
@@ -54,71 +55,6 @@
 	); \
 } while(0)
 
-/* Interrupt Control */
-#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
-#define local_irq_enable() \
-	__asm__ __volatile__ ("setpsw #0x40 -> nop": : :"memory")
-#define local_irq_disable() \
-	__asm__ __volatile__ ("clrpsw #0x40 -> nop": : :"memory")
-#else	/* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-static inline void local_irq_enable(void)
-{
-	unsigned long tmpreg;
-	__asm__ __volatile__(
-		"mvfc	%0, psw;		\n\t"
-		"or3	%0, %0, #0x0040;	\n\t"
-		"mvtc	%0, psw;		\n\t"
-	: "=&r" (tmpreg) : : "cbit", "memory");
-}
-
-static inline void local_irq_disable(void)
-{
-	unsigned long tmpreg0, tmpreg1;
-	__asm__ __volatile__(
-		"ld24	%0, #0	; Use 32-bit insn. \n\t"
-		"mvfc	%1, psw	; No interrupt can be accepted here. \n\t"
-		"mvtc	%0, psw	\n\t"
-		"and3	%0, %1, #0xffbf	\n\t"
-		"mvtc	%0, psw	\n\t"
-	: "=&r" (tmpreg0), "=&r" (tmpreg1) : : "cbit", "memory");
-}
-#endif	/* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-
-#define local_save_flags(x) \
-	__asm__ __volatile__("mvfc %0,psw" : "=r"(x) : /* no input */)
-
-#define local_irq_restore(x) \
-	__asm__ __volatile__("mvtc %0,psw" : /* no outputs */ \
-		: "r" (x) : "cbit", "memory")
-
-#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
-#define local_irq_save(x)				\
-	__asm__ __volatile__(				\
-  		"mvfc	%0, psw;		\n\t"	\
-	  	"clrpsw	#0x40 -> nop;		\n\t"	\
-  		: "=r" (x) : /* no input */ : "memory")
-#else	/* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-#define local_irq_save(x) 				\
-	({						\
-		unsigned long tmpreg;			\
-		__asm__ __volatile__( 			\
-			"ld24	%1, #0 \n\t" 		\
-			"mvfc	%0, psw \n\t"		\
-			"mvtc	%1, psw \n\t"		\
-			"and3	%1, %0, #0xffbf \n\t"	\
-			"mvtc	%1, psw \n\t" 		\
-			: "=r" (x), "=&r" (tmpreg)	\
-			: : "cbit", "memory");		\
-	})
-#endif	/* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-
-#define irqs_disabled()					\
-	({						\
-		unsigned long flags;			\
-		local_save_flags(flags);		\
-		!(flags & 0x40);			\
-	})
-
 #define nop()	__asm__ __volatile__ ("nop" : : )
 
 #define xchg(ptr, x)							\
diff --git a/arch/m32r/include/asm/unistd.h b/arch/m32r/include/asm/unistd.h
index 7612577..c705456 100644
--- a/arch/m32r/include/asm/unistd.h
+++ b/arch/m32r/include/asm/unistd.h
@@ -351,6 +351,7 @@
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
 #define __IGNORE_lchown
 #define __IGNORE_setuid
diff --git a/arch/m32r/kernel/.gitignore b/arch/m32r/kernel/.gitignore
new file mode 100644
index 0000000..c5f676c
--- /dev/null
+++ b/arch/m32r/kernel/.gitignore
@@ -0,0 +1 @@
+vmlinux.lds
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index 4038698..225412b 100644
--- a/arch/m32r/kernel/entry.S
+++ b/arch/m32r/kernel/entry.S
@@ -235,10 +235,9 @@
 work_notifysig:				; deal with pending signals and
 					; notify-resume requests
 	mv	r0, sp			; arg1 : struct pt_regs *regs
-	ldi	r1, #0			; arg2 : sigset_t *oldset
-	mv	r2, r9			; arg3 : __u32 thread_info_flags
+	mv	r1, r9			; arg2 : __u32 thread_info_flags
 	bl	do_notify_resume
-	bra	restore_all
+	bra	resume_userspace
 
 	; perform syscall exit tracing
 	ALIGN
diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c
index 3c71f77..7db26f1 100644
--- a/arch/m32r/kernel/irq.c
+++ b/arch/m32r/kernel/irq.c
@@ -51,7 +51,7 @@
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", irq_desc[i].chip->typename);
+		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
index e555091..0021ade 100644
--- a/arch/m32r/kernel/ptrace.c
+++ b/arch/m32r/kernel/ptrace.c
@@ -592,16 +592,17 @@
 
 	if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
 	    != sizeof(insn))
-		break;
+		return -EIO;
 
 	compute_next_pc(insn, pc, &next_pc, child);
 	if (next_pc & 0x80000000)
-		break;
+		return -EIO;
 
 	if (embed_debug_trap(child, next_pc))
-		break;
+		return -EIO;
 
 	invalidate_cache();
+	return 0;
 }
 
 void user_disable_single_step(struct task_struct *child)
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index 144b0f12..a08697f 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -30,35 +30,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-int do_signal(struct pt_regs *, sigset_t *);
-
-asmlinkage int
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
-		  unsigned long r2, unsigned long r3, unsigned long r4,
-		  unsigned long r5, unsigned long r6, struct pt_regs *regs)
-{
-	sigset_t newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
-		return -EFAULT;
-	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->saved_sigmask = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule();
-	set_thread_flag(TIF_RESTORE_SIGMASK);
-	return -ERESTARTNOHAND;
-}
-
 asmlinkage int
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
 		unsigned long r2, unsigned long r3, unsigned long r4,
@@ -218,7 +189,7 @@
 	return (void __user *)((sp - frame_size) & -8ul);
 }
 
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 			   sigset_t *set, struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
@@ -275,22 +246,34 @@
 		current->comm, current->pid, frame, regs->pc);
 #endif
 
-	return;
+	return 0;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return -EFAULT;
+}
+
+static int prev_insn(struct pt_regs *regs)
+{
+	u16 inst;
+	if (get_user(inst, (u16 __user *)(regs->bpc - 2)))
+		return -EFAULT;
+	if ((inst & 0xfff0) == 0x10f0)	/* trap ? */
+		regs->bpc -= 2;
+	else
+		regs->bpc -= 4;
+	regs->syscall_nr = -1;
+	return 0;
 }
 
 /*
  * OK, we're invoking a handler
  */
 
-static void
+static int
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
 	      sigset_t *oldset, struct pt_regs *regs)
 {
-	unsigned short inst;
-
 	/* Are we from a system call? */
 	if (regs->syscall_nr >= 0) {
 		/* If so, check system call restarting.. */
@@ -308,16 +291,14 @@
 			/* fallthrough */
 			case -ERESTARTNOINTR:
 				regs->r0 = regs->orig_r0;
-				inst = *(unsigned short *)(regs->bpc - 2);
-				if ((inst & 0xfff0) == 0x10f0)	/* trap ? */
-					regs->bpc -= 2;
-				else
-					regs->bpc -= 4;
+				if (prev_insn(regs) < 0)
+					return -EFAULT;
 		}
 	}
 
 	/* Set up the stack frame */
-	setup_rt_frame(sig, ka, info, oldset, regs);
+	if (setup_rt_frame(sig, ka, info, oldset, regs))
+		return -EFAULT;
 
 	spin_lock_irq(&current->sighand->siglock);
 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -325,6 +306,7 @@
 		sigaddset(&current->blocked,sig);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
+	return 0;
 }
 
 /*
@@ -332,12 +314,12 @@
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void do_signal(struct pt_regs *regs)
 {
 	siginfo_t info;
 	int signr;
 	struct k_sigaction ka;
-	unsigned short inst;
+	sigset_t *oldset;
 
 	/*
 	 * We want the common case to go fast, which
@@ -346,12 +328,14 @@
 	 * if so.
 	 */
 	if (!user_mode(regs))
-		return 1;
+		return;
 
 	if (try_to_freeze()) 
 		goto no_signal;
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -363,8 +347,10 @@
 		 */
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &ka, &info, oldset, regs);
-		return 1;
+		if (handle_signal(signr, &ka, &info, oldset, regs) == 0)
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+		return;
 	}
 
  no_signal:
@@ -375,31 +361,24 @@
 		    regs->r0 == -ERESTARTSYS ||
 		    regs->r0 == -ERESTARTNOINTR) {
 			regs->r0 = regs->orig_r0;
-			inst = *(unsigned short *)(regs->bpc - 2);
-			if ((inst & 0xfff0) == 0x10f0)	/* trap ? */
-				regs->bpc -= 2;
-			else
-				regs->bpc -= 4;
-		}
-		if (regs->r0 == -ERESTART_RESTARTBLOCK){
+			prev_insn(regs);
+		} else if (regs->r0 == -ERESTART_RESTARTBLOCK){
 			regs->r0 = regs->orig_r0;
 			regs->r7 = __NR_restart_syscall;
-			inst = *(unsigned short *)(regs->bpc - 2);
-			if ((inst & 0xfff0) == 0x10f0)	/* trap ? */
-				regs->bpc -= 2;
-			else
-				regs->bpc -= 4;
+			prev_insn(regs);
 		}
 	}
-	return 0;
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 }
 
 /*
  * notification of userspace execution resumption
  * - triggered by current->work.notify_resume
  */
-void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
-		      __u32 thread_info_flags)
+void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags)
 {
 	/* Pending single-step? */
 	if (thread_info_flags & _TIF_SINGLESTEP)
@@ -407,7 +386,7 @@
 
 	/* deal with pending signal delivery */
 	if (thread_info_flags & _TIF_SIGPENDING)
-		do_signal(regs,oldset);
+		do_signal(regs);
 
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 		clear_thread_flag(TIF_NOTIFY_RESUME);
diff --git a/arch/m32r/platforms/m32104ut/setup.c b/arch/m32r/platforms/m32104ut/setup.c
index 922fdfd..402a59d 100644
--- a/arch/m32r/platforms/m32104ut/setup.c
+++ b/arch/m32r/platforms/m32104ut/setup.c
@@ -65,7 +65,7 @@
 
 static struct irq_chip m32104ut_irq_type =
 {
-	.typename = "M32104UT-IRQ",
+	.name = "M32104UT-IRQ",
 	.startup = startup_m32104ut_irq,
 	.shutdown = shutdown_m32104ut_irq,
 	.enable = enable_m32104ut_irq,
diff --git a/arch/m32r/platforms/m32700ut/setup.c b/arch/m32r/platforms/m32700ut/setup.c
index 9c1bc74..80b1a02 100644
--- a/arch/m32r/platforms/m32700ut/setup.c
+++ b/arch/m32r/platforms/m32700ut/setup.c
@@ -71,7 +71,7 @@
 
 static struct irq_chip m32700ut_irq_type =
 {
-	.typename = "M32700UT-IRQ",
+	.name = "M32700UT-IRQ",
 	.startup = startup_m32700ut_irq,
 	.shutdown = shutdown_m32700ut_irq,
 	.enable = enable_m32700ut_irq,
@@ -148,7 +148,7 @@
 
 static struct irq_chip m32700ut_pld_irq_type =
 {
-	.typename = "M32700UT-PLD-IRQ",
+	.name = "M32700UT-PLD-IRQ",
 	.startup = startup_m32700ut_pld_irq,
 	.shutdown = shutdown_m32700ut_pld_irq,
 	.enable = enable_m32700ut_pld_irq,
@@ -217,7 +217,7 @@
 
 static struct irq_chip m32700ut_lanpld_irq_type =
 {
-	.typename = "M32700UT-PLD-LAN-IRQ",
+	.name = "M32700UT-PLD-LAN-IRQ",
 	.startup = startup_m32700ut_lanpld_irq,
 	.shutdown = shutdown_m32700ut_lanpld_irq,
 	.enable = enable_m32700ut_lanpld_irq,
@@ -286,7 +286,7 @@
 
 static struct irq_chip m32700ut_lcdpld_irq_type =
 {
-	.typename = "M32700UT-PLD-LCD-IRQ",
+	.name = "M32700UT-PLD-LCD-IRQ",
 	.startup = startup_m32700ut_lcdpld_irq,
 	.shutdown = shutdown_m32700ut_lcdpld_irq,
 	.enable = enable_m32700ut_lcdpld_irq,
diff --git a/arch/m32r/platforms/mappi/setup.c b/arch/m32r/platforms/mappi/setup.c
index fb4b177..ea00c84 100644
--- a/arch/m32r/platforms/mappi/setup.c
+++ b/arch/m32r/platforms/mappi/setup.c
@@ -65,7 +65,7 @@
 
 static struct irq_chip mappi_irq_type =
 {
-	.typename = "MAPPI-IRQ",
+	.name = "MAPPI-IRQ",
 	.startup = startup_mappi_irq,
 	.shutdown = shutdown_mappi_irq,
 	.enable = enable_mappi_irq,
diff --git a/arch/m32r/platforms/mappi2/setup.c b/arch/m32r/platforms/mappi2/setup.c
index 6a65eda..c049376 100644
--- a/arch/m32r/platforms/mappi2/setup.c
+++ b/arch/m32r/platforms/mappi2/setup.c
@@ -72,7 +72,7 @@
 
 static struct irq_chip mappi2_irq_type =
 {
-	.typename = "MAPPI2-IRQ",
+	.name = "MAPPI2-IRQ",
 	.startup = startup_mappi2_irq,
 	.shutdown = shutdown_mappi2_irq,
 	.enable = enable_mappi2_irq,
diff --git a/arch/m32r/platforms/mappi3/setup.c b/arch/m32r/platforms/mappi3/setup.c
index 9c337ae..882de25 100644
--- a/arch/m32r/platforms/mappi3/setup.c
+++ b/arch/m32r/platforms/mappi3/setup.c
@@ -72,7 +72,7 @@
 
 static struct irq_chip mappi3_irq_type =
 {
-	.typename = "MAPPI3-IRQ",
+	.name = "MAPPI3-IRQ",
 	.startup = startup_mappi3_irq,
 	.shutdown = shutdown_mappi3_irq,
 	.enable = enable_mappi3_irq,
diff --git a/arch/m32r/platforms/oaks32r/setup.c b/arch/m32r/platforms/oaks32r/setup.c
index ed86574..d11d93b 100644
--- a/arch/m32r/platforms/oaks32r/setup.c
+++ b/arch/m32r/platforms/oaks32r/setup.c
@@ -63,7 +63,7 @@
 
 static struct irq_chip oaks32r_irq_type =
 {
-	.typename = "OAKS32R-IRQ",
+	.name = "OAKS32R-IRQ",
 	.startup = startup_oaks32r_irq,
 	.shutdown = shutdown_oaks32r_irq,
 	.enable = enable_oaks32r_irq,
diff --git a/arch/m32r/platforms/opsput/setup.c b/arch/m32r/platforms/opsput/setup.c
index 80d6806..5f3402a 100644
--- a/arch/m32r/platforms/opsput/setup.c
+++ b/arch/m32r/platforms/opsput/setup.c
@@ -72,7 +72,7 @@
 
 static struct irq_chip opsput_irq_type =
 {
-	.typename = "OPSPUT-IRQ",
+	.name = "OPSPUT-IRQ",
 	.startup = startup_opsput_irq,
 	.shutdown = shutdown_opsput_irq,
 	.enable = enable_opsput_irq,
@@ -149,7 +149,7 @@
 
 static struct irq_chip opsput_pld_irq_type =
 {
-	.typename = "OPSPUT-PLD-IRQ",
+	.name = "OPSPUT-PLD-IRQ",
 	.startup = startup_opsput_pld_irq,
 	.shutdown = shutdown_opsput_pld_irq,
 	.enable = enable_opsput_pld_irq,
@@ -218,7 +218,7 @@
 
 static struct irq_chip opsput_lanpld_irq_type =
 {
-	.typename = "OPSPUT-PLD-LAN-IRQ",
+	.name = "OPSPUT-PLD-LAN-IRQ",
 	.startup = startup_opsput_lanpld_irq,
 	.shutdown = shutdown_opsput_lanpld_irq,
 	.enable = enable_opsput_lanpld_irq,
diff --git a/arch/m32r/platforms/usrv/setup.c b/arch/m32r/platforms/usrv/setup.c
index 7573026..1beac7a 100644
--- a/arch/m32r/platforms/usrv/setup.c
+++ b/arch/m32r/platforms/usrv/setup.c
@@ -63,7 +63,7 @@
 
 static struct irq_chip mappi_irq_type =
 {
-	.typename = "M32700-IRQ",
+	.name = "M32700-IRQ",
 	.startup = startup_mappi_irq,
 	.shutdown = shutdown_mappi_irq,
 	.enable = enable_mappi_irq,
@@ -136,7 +136,7 @@
 
 static struct irq_chip m32700ut_pld_irq_type =
 {
-	.typename = "USRV-PLD-IRQ",
+	.name = "USRV-PLD-IRQ",
 	.startup = startup_m32700ut_pld_irq,
 	.shutdown = shutdown_m32700ut_pld_irq,
 	.enable = enable_m32700ut_pld_irq,
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 8030e24..77bb0d6 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -434,7 +434,7 @@
 
 config ISA
 	bool
-	depends on Q40 || AMIGA_PCMCIA || GG2
+	depends on Q40 || AMIGA_PCMCIA
 	default y
 	help
 	  Find out whether you have ISA slots on your motherboard.  ISA is the
@@ -445,7 +445,7 @@
 
 config GENERIC_ISA_DMA
 	bool
-	depends on Q40 || AMIGA_PCMCIA || GG2
+	depends on Q40 || AMIGA_PCMCIA
 	default y
 
 config ZONE_DMA
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
index cb8617b..1c4d4c7 100644
--- a/arch/m68k/bvme6000/rtc.c
+++ b/arch/m68k/bvme6000/rtc.c
@@ -155,6 +155,7 @@
 	.unlocked_ioctl	= rtc_ioctl,
 	.open		= rtc_open,
 	.release	= rtc_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice rtc_dev = {
diff --git a/arch/m68k/include/asm/amigahw.h b/arch/m68k/include/asm/amigahw.h
index 5ca5dd9..7a19b56 100644
--- a/arch/m68k/include/asm/amigahw.h
+++ b/arch/m68k/include/asm/amigahw.h
@@ -102,7 +102,6 @@
     AMIGAHW_DECLARE(ALICE_NTSC);	/* NTSC Alice (8374) */
     AMIGAHW_DECLARE(MAGIC_REKICK);	/* A3000 Magic Hard Rekick */
     AMIGAHW_DECLARE(PCMCIA);		/* PCMCIA Slot */
-    AMIGAHW_DECLARE(GG2_ISA);		/* GG2 Zorro2ISA Bridge */
     AMIGAHW_DECLARE(ZORRO);		/* Zorro AutoConfig */
     AMIGAHW_DECLARE(ZORRO3);		/* Zorro III */
 };
diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h
index eab36dc..03ae3d1 100644
--- a/arch/m68k/include/asm/atomic.h
+++ b/arch/m68k/include/asm/atomic.h
@@ -1,7 +1,211 @@
-#ifdef __uClinux__
-#include "atomic_no.h"
+#ifndef __ARCH_M68K_ATOMIC__
+#define __ARCH_M68K_ATOMIC__
+
+#include <linux/types.h>
+#include <asm/system.h>
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+/*
+ * We do not have SMP m68k systems, so we don't have to deal with that.
+ */
+
+#define ATOMIC_INIT(i)	{ (i) }
+
+#define atomic_read(v)		(*(volatile int *)&(v)->counter)
+#define atomic_set(v, i)	(((v)->counter) = i)
+
+/*
+ * The ColdFire parts cannot do some immediate to memory operations,
+ * so for them we do not specify the "i" asm constraint.
+ */
+#ifdef CONFIG_COLDFIRE
+#define	ASM_DI	"d"
 #else
-#include "atomic_mm.h"
+#define	ASM_DI	"di"
 #endif
 
+static inline void atomic_add(int i, atomic_t *v)
+{
+	__asm__ __volatile__("addl %1,%0" : "+m" (*v) : ASM_DI (i));
+}
+
+static inline void atomic_sub(int i, atomic_t *v)
+{
+	__asm__ __volatile__("subl %1,%0" : "+m" (*v) : ASM_DI (i));
+}
+
+static inline void atomic_inc(atomic_t *v)
+{
+	__asm__ __volatile__("addql #1,%0" : "+m" (*v));
+}
+
+static inline void atomic_dec(atomic_t *v)
+{
+	__asm__ __volatile__("subql #1,%0" : "+m" (*v));
+}
+
+static inline int atomic_dec_and_test(atomic_t *v)
+{
+	char c;
+	__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
+	return c != 0;
+}
+
+static inline int atomic_inc_and_test(atomic_t *v)
+{
+	char c;
+	__asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
+	return c != 0;
+}
+
+#ifdef CONFIG_RMW_INSNS
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+	int t, tmp;
+
+	__asm__ __volatile__(
+			"1:	movel %2,%1\n"
+			"	addl %3,%1\n"
+			"	casl %2,%1,%0\n"
+			"	jne 1b"
+			: "+m" (*v), "=&d" (t), "=&d" (tmp)
+			: "g" (i), "2" (atomic_read(v)));
+	return t;
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+	int t, tmp;
+
+	__asm__ __volatile__(
+			"1:	movel %2,%1\n"
+			"	subl %3,%1\n"
+			"	casl %2,%1,%0\n"
+			"	jne 1b"
+			: "+m" (*v), "=&d" (t), "=&d" (tmp)
+			: "g" (i), "2" (atomic_read(v)));
+	return t;
+}
+
+#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+#else /* !CONFIG_RMW_INSNS */
+
+static inline int atomic_add_return(int i, atomic_t * v)
+{
+	unsigned long flags;
+	int t;
+
+	local_irq_save(flags);
+	t = atomic_read(v);
+	t += i;
+	atomic_set(v, t);
+	local_irq_restore(flags);
+
+	return t;
+}
+
+static inline int atomic_sub_return(int i, atomic_t * v)
+{
+	unsigned long flags;
+	int t;
+
+	local_irq_save(flags);
+	t = atomic_read(v);
+	t -= i;
+	atomic_set(v, t);
+	local_irq_restore(flags);
+
+	return t;
+}
+
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+	unsigned long flags;
+	int prev;
+
+	local_irq_save(flags);
+	prev = atomic_read(v);
+	if (prev == old)
+		atomic_set(v, new);
+	local_irq_restore(flags);
+	return prev;
+}
+
+static inline int atomic_xchg(atomic_t *v, int new)
+{
+	unsigned long flags;
+	int prev;
+
+	local_irq_save(flags);
+	prev = atomic_read(v);
+	atomic_set(v, new);
+	local_irq_restore(flags);
+	return prev;
+}
+
+#endif /* !CONFIG_RMW_INSNS */
+
+#define atomic_dec_return(v)	atomic_sub_return(1, (v))
+#define atomic_inc_return(v)	atomic_add_return(1, (v))
+
+static inline int atomic_sub_and_test(int i, atomic_t *v)
+{
+	char c;
+	__asm__ __volatile__("subl %2,%1; seq %0"
+			     : "=d" (c), "+m" (*v)
+			     : ASM_DI (i));
+	return c != 0;
+}
+
+static inline int atomic_add_negative(int i, atomic_t *v)
+{
+	char c;
+	__asm__ __volatile__("addl %2,%1; smi %0"
+			     : "=d" (c), "+m" (*v)
+			     : "id" (i));
+	return c != 0;
+}
+
+static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
+{
+	__asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
+}
+
+static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
+{
+	__asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
+}
+
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+	int c, old;
+	c = atomic_read(v);
+	for (;;) {
+		if (unlikely(c == (u)))
+			break;
+		old = atomic_cmpxchg((v), c, c + (a));
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+	return c != (u);
+}
+
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec()	barrier()
+#define smp_mb__after_atomic_dec()	barrier()
+#define smp_mb__before_atomic_inc()	barrier()
+#define smp_mb__after_atomic_inc()	barrier()
+
+#include <asm-generic/atomic-long.h>
 #include <asm-generic/atomic64.h>
+#endif /* __ARCH_M68K_ATOMIC __ */
diff --git a/arch/m68k/include/asm/atomic_mm.h b/arch/m68k/include/asm/atomic_mm.h
deleted file mode 100644
index 6a223b3..0000000
--- a/arch/m68k/include/asm/atomic_mm.h
+++ /dev/null
@@ -1,200 +0,0 @@
-#ifndef __ARCH_M68K_ATOMIC__
-#define __ARCH_M68K_ATOMIC__
-
-#include <linux/types.h>
-#include <asm/system.h>
-
-/*
- * Atomic operations that C can't guarantee us.  Useful for
- * resource counting etc..
- */
-
-/*
- * We do not have SMP m68k systems, so we don't have to deal with that.
- */
-
-#define ATOMIC_INIT(i)	{ (i) }
-
-#define atomic_read(v)		(*(volatile int *)&(v)->counter)
-#define atomic_set(v, i)	(((v)->counter) = i)
-
-static inline void atomic_add(int i, atomic_t *v)
-{
-	__asm__ __volatile__("addl %1,%0" : "+m" (*v) : "id" (i));
-}
-
-static inline void atomic_sub(int i, atomic_t *v)
-{
-	__asm__ __volatile__("subl %1,%0" : "+m" (*v) : "id" (i));
-}
-
-static inline void atomic_inc(atomic_t *v)
-{
-	__asm__ __volatile__("addql #1,%0" : "+m" (*v));
-}
-
-static inline void atomic_dec(atomic_t *v)
-{
-	__asm__ __volatile__("subql #1,%0" : "+m" (*v));
-}
-
-static inline int atomic_dec_and_test(atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
-	return c != 0;
-}
-
-static inline int atomic_inc_and_test(atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
-	return c != 0;
-}
-
-#ifdef CONFIG_RMW_INSNS
-
-static inline int atomic_add_return(int i, atomic_t *v)
-{
-	int t, tmp;
-
-	__asm__ __volatile__(
-			"1:	movel %2,%1\n"
-			"	addl %3,%1\n"
-			"	casl %2,%1,%0\n"
-			"	jne 1b"
-			: "+m" (*v), "=&d" (t), "=&d" (tmp)
-			: "g" (i), "2" (atomic_read(v)));
-	return t;
-}
-
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
-	int t, tmp;
-
-	__asm__ __volatile__(
-			"1:	movel %2,%1\n"
-			"	subl %3,%1\n"
-			"	casl %2,%1,%0\n"
-			"	jne 1b"
-			: "+m" (*v), "=&d" (t), "=&d" (tmp)
-			: "g" (i), "2" (atomic_read(v)));
-	return t;
-}
-
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-#else /* !CONFIG_RMW_INSNS */
-
-static inline int atomic_add_return(int i, atomic_t * v)
-{
-	unsigned long flags;
-	int t;
-
-	local_irq_save(flags);
-	t = atomic_read(v);
-	t += i;
-	atomic_set(v, t);
-	local_irq_restore(flags);
-
-	return t;
-}
-
-static inline int atomic_sub_return(int i, atomic_t * v)
-{
-	unsigned long flags;
-	int t;
-
-	local_irq_save(flags);
-	t = atomic_read(v);
-	t -= i;
-	atomic_set(v, t);
-	local_irq_restore(flags);
-
-	return t;
-}
-
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
-	unsigned long flags;
-	int prev;
-
-	local_irq_save(flags);
-	prev = atomic_read(v);
-	if (prev == old)
-		atomic_set(v, new);
-	local_irq_restore(flags);
-	return prev;
-}
-
-static inline int atomic_xchg(atomic_t *v, int new)
-{
-	unsigned long flags;
-	int prev;
-
-	local_irq_save(flags);
-	prev = atomic_read(v);
-	atomic_set(v, new);
-	local_irq_restore(flags);
-	return prev;
-}
-
-#endif /* !CONFIG_RMW_INSNS */
-
-#define atomic_dec_return(v)	atomic_sub_return(1, (v))
-#define atomic_inc_return(v)	atomic_add_return(1, (v))
-
-static inline int atomic_sub_and_test(int i, atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("subl %2,%1; seq %0"
-			     : "=d" (c), "+m" (*v)
-			     : "id" (i));
-	return c != 0;
-}
-
-static inline int atomic_add_negative(int i, atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("addl %2,%1; smi %0"
-			     : "=d" (c), "+m" (*v)
-			     : "id" (i));
-	return c != 0;
-}
-
-static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
-{
-	__asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
-}
-
-static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
-{
-	__asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
-}
-
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
-{
-	int c, old;
-	c = atomic_read(v);
-	for (;;) {
-		if (unlikely(c == (u)))
-			break;
-		old = atomic_cmpxchg((v), c, c + (a));
-		if (likely(old == c))
-			break;
-		c = old;
-	}
-	return c != (u);
-}
-
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec()	barrier()
-#define smp_mb__after_atomic_dec()	barrier()
-#define smp_mb__before_atomic_inc()	barrier()
-#define smp_mb__after_atomic_inc()	barrier()
-
-#include <asm-generic/atomic-long.h>
-#endif /* __ARCH_M68K_ATOMIC __ */
diff --git a/arch/m68k/include/asm/atomic_no.h b/arch/m68k/include/asm/atomic_no.h
deleted file mode 100644
index 289310c..0000000
--- a/arch/m68k/include/asm/atomic_no.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#ifndef __ARCH_M68KNOMMU_ATOMIC__
-#define __ARCH_M68KNOMMU_ATOMIC__
-
-#include <linux/types.h>
-#include <asm/system.h>
-
-/*
- * Atomic operations that C can't guarantee us.  Useful for
- * resource counting etc..
- */
-
-/*
- * We do not have SMP m68k systems, so we don't have to deal with that.
- */
-
-#define ATOMIC_INIT(i)	{ (i) }
-
-#define atomic_read(v)		(*(volatile int *)&(v)->counter)
-#define atomic_set(v, i)	(((v)->counter) = i)
-
-static __inline__ void atomic_add(int i, atomic_t *v)
-{
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__("addl %1,%0" : "+m" (*v) : "d" (i));
-#else
-	__asm__ __volatile__("addl %1,%0" : "+m" (*v) : "di" (i));
-#endif
-}
-
-static __inline__ void atomic_sub(int i, atomic_t *v)
-{
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__("subl %1,%0" : "+m" (*v) : "d" (i));
-#else
-	__asm__ __volatile__("subl %1,%0" : "+m" (*v) : "di" (i));
-#endif
-}
-
-static __inline__ int atomic_sub_and_test(int i, atomic_t * v)
-{
-	char c;
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__("subl %2,%1; seq %0"
-			     : "=d" (c), "+m" (*v)
-			     : "d" (i));
-#else
-	__asm__ __volatile__("subl %2,%1; seq %0"
-			     : "=d" (c), "+m" (*v)
-			     : "di" (i));
-#endif
-	return c != 0;
-}
-
-static __inline__ void atomic_inc(volatile atomic_t *v)
-{
-	__asm__ __volatile__("addql #1,%0" : "+m" (*v));
-}
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-
-static __inline__ int atomic_inc_and_test(volatile atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
-	return c != 0;
-}
-
-static __inline__ void atomic_dec(volatile atomic_t *v)
-{
-	__asm__ __volatile__("subql #1,%0" : "+m" (*v));
-}
-
-static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
-	return c != 0;
-}
-
-static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v)
-{
-	__asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
-}
-
-static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v)
-{
-	__asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
-}
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-static inline int atomic_add_return(int i, atomic_t * v)
-{
-	unsigned long temp, flags;
-
-	local_irq_save(flags);
-	temp = *(long *)v;
-	temp += i;
-	*(long *)v = temp;
-	local_irq_restore(flags);
-
-	return temp;
-}
-
-#define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
-
-static inline int atomic_sub_return(int i, atomic_t * v)
-{
-	unsigned long temp, flags;
-
-	local_irq_save(flags);
-	temp = *(long *)v;
-	temp -= i;
-	*(long *)v = temp;
-	local_irq_restore(flags);
-
-	return temp;
-}
-
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
-{
-	int c, old;
-	c = atomic_read(v);
-	for (;;) {
-		if (unlikely(c == (u)))
-			break;
-		old = atomic_cmpxchg((v), c, c + (a));
-		if (likely(old == c))
-			break;
-		c = old;
-	}
-	return c != (u);
-}
-
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-#define atomic_dec_return(v) atomic_sub_return(1,(v))
-#define atomic_inc_return(v) atomic_add_return(1,(v))
-
-#include <asm-generic/atomic-long.h>
-#endif /* __ARCH_M68KNOMMU_ATOMIC __ */
diff --git a/arch/m68k/include/asm/entry_mm.h b/arch/m68k/include/asm/entry_mm.h
index 4741258..e41fea3 100644
--- a/arch/m68k/include/asm/entry_mm.h
+++ b/arch/m68k/include/asm/entry_mm.h
@@ -3,6 +3,9 @@
 
 #include <asm/setup.h>
 #include <asm/page.h>
+#ifdef __ASSEMBLY__
+#include <asm/thread_info.h>
+#endif
 
 /*
  * Stack layout in 'ret_from_exception':
diff --git a/arch/m68k/include/asm/entry_no.h b/arch/m68k/include/asm/entry_no.h
index 907ed03..80e4149 100644
--- a/arch/m68k/include/asm/entry_no.h
+++ b/arch/m68k/include/asm/entry_no.h
@@ -28,7 +28,7 @@
  *			M68K		  COLDFIRE
  */
 
-#define ALLOWINT 0xf8ff
+#define ALLOWINT (~0x700)
 
 #ifdef __ASSEMBLY__
 
diff --git a/arch/m68k/include/asm/io_mm.h b/arch/m68k/include/asm/io_mm.h
index 9e673e3..0fb3468 100644
--- a/arch/m68k/include/asm/io_mm.h
+++ b/arch/m68k/include/asm/io_mm.h
@@ -49,23 +49,6 @@
 #define MULTI_ISA 0
 #endif /* Q40 */
 
-/* GG-II Zorro to ISA bridge */
-#ifdef CONFIG_GG2
-
-extern unsigned long gg2_isa_base;
-#define GG2_ISA_IO_B(ioaddr) (gg2_isa_base+1+((unsigned long)(ioaddr)*4))
-#define GG2_ISA_IO_W(ioaddr) (gg2_isa_base+  ((unsigned long)(ioaddr)*4))
-#define GG2_ISA_MEM_B(madr)  (gg2_isa_base+1+(((unsigned long)(madr)*4) & 0xfffff))
-#define GG2_ISA_MEM_W(madr)  (gg2_isa_base+  (((unsigned long)(madr)*4) & 0xfffff))
-
-#ifndef MULTI_ISA
-#define MULTI_ISA 0
-#else
-#undef MULTI_ISA
-#define MULTI_ISA 1
-#endif
-#endif /* GG2 */
-
 #ifdef CONFIG_AMIGA_PCMCIA
 #include <asm/amigayle.h>
 
@@ -89,8 +72,7 @@
 #endif
 
 #define ISA_TYPE_Q40 (1)
-#define ISA_TYPE_GG2 (2)
-#define ISA_TYPE_AG  (3)
+#define ISA_TYPE_AG  (2)
 
 #if defined(CONFIG_Q40) && !defined(MULTI_ISA)
 #define ISA_TYPE ISA_TYPE_Q40
@@ -100,10 +82,6 @@
 #define ISA_TYPE ISA_TYPE_AG
 #define ISA_SEX  1
 #endif
-#if defined(CONFIG_GG2) && !defined(MULTI_ISA)
-#define ISA_TYPE ISA_TYPE_GG2
-#define ISA_SEX  0
-#endif
 
 #ifdef MULTI_ISA
 extern int isa_type;
@@ -125,9 +103,6 @@
 #ifdef CONFIG_Q40
     case ISA_TYPE_Q40: return (u8 __iomem *)Q40_ISA_IO_B(addr);
 #endif
-#ifdef CONFIG_GG2
-    case ISA_TYPE_GG2: return (u8 __iomem *)GG2_ISA_IO_B(addr);
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
     case ISA_TYPE_AG: return (u8 __iomem *)AG_ISA_IO_B(addr);
 #endif
@@ -141,9 +116,6 @@
 #ifdef CONFIG_Q40
     case ISA_TYPE_Q40: return (u16 __iomem *)Q40_ISA_IO_W(addr);
 #endif
-#ifdef CONFIG_GG2
-    case ISA_TYPE_GG2: return (u16 __iomem *)GG2_ISA_IO_W(addr);
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
     case ISA_TYPE_AG: return (u16 __iomem *)AG_ISA_IO_W(addr);
 #endif
@@ -167,9 +139,6 @@
 #ifdef CONFIG_Q40
     case ISA_TYPE_Q40: return (u8 __iomem *)Q40_ISA_MEM_B(addr);
 #endif
-#ifdef CONFIG_GG2
-    case ISA_TYPE_GG2: return (u8 __iomem *)GG2_ISA_MEM_B(addr);
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
     case ISA_TYPE_AG: return (u8 __iomem *)addr;
 #endif
@@ -183,9 +152,6 @@
 #ifdef CONFIG_Q40
     case ISA_TYPE_Q40: return (u16 __iomem *)Q40_ISA_MEM_W(addr);
 #endif
-#ifdef CONFIG_GG2
-    case ISA_TYPE_GG2: return (u16 __iomem *)GG2_ISA_MEM_W(addr);
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
     case ISA_TYPE_AG: return (u16 __iomem *)addr;
 #endif
@@ -217,9 +183,6 @@
 #ifdef CONFIG_Q40
     case ISA_TYPE_Q40: isa_outb(0,0x80); break;
 #endif
-#ifdef CONFIG_GG2
-    case ISA_TYPE_GG2: break;
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
     case ISA_TYPE_AG: break;
 #endif
@@ -287,9 +250,13 @@
 #define outb(val,port)     ((void)0)
 #define outb_p(val,port)   ((void)0)
 #define inw(port)          0xffff
+#define inw_p(port)        0xffff
 #define outw(val,port)     ((void)0)
+#define outw_p(val,port)   ((void)0)
 #define inl(port)          0xffffffffUL
+#define inl_p(port)        0xffffffffUL
 #define outl(val,port)     ((void)0)
+#define outl_p(val,port)   ((void)0)
 
 #define insb(port,buf,nr)  ((void)0)
 #define outsb(port,buf,nr) ((void)0)
diff --git a/arch/m68k/include/asm/ioctls.h b/arch/m68k/include/asm/ioctls.h
index 91a57d6..1332bb4 100644
--- a/arch/m68k/include/asm/ioctls.h
+++ b/arch/m68k/include/asm/ioctls.h
@@ -1,86 +1,8 @@
 #ifndef __ARCH_M68K_IOCTLS_H__
 #define __ARCH_M68K_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define FIOQSIZE	0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ARCH_M68K_IOCTLS_H__ */
diff --git a/arch/m68k/include/asm/irqflags.h b/arch/m68k/include/asm/irqflags.h
new file mode 100644
index 0000000..4a5b284
--- /dev/null
+++ b/arch/m68k/include/asm/irqflags.h
@@ -0,0 +1,76 @@
+#ifndef _M68K_IRQFLAGS_H
+#define _M68K_IRQFLAGS_H
+
+#include <linux/types.h>
+#include <linux/hardirq.h>
+#include <linux/preempt.h>
+#include <asm/thread_info.h>
+#include <asm/entry.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile ("movew %%sr,%0" : "=d" (flags) : : "memory");
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+#ifdef CONFIG_COLDFIRE
+	asm volatile (
+		"move	%/sr,%%d0	\n\t"
+		"ori.l	#0x0700,%%d0	\n\t"
+		"move	%%d0,%/sr	\n"
+		: /* no outputs */
+		:
+		: "cc", "%d0", "memory");
+#else
+	asm volatile ("oriw  #0x0700,%%sr" : : : "memory");
+#endif
+}
+
+static inline void arch_local_irq_enable(void)
+{
+#if defined(CONFIG_COLDFIRE)
+	asm volatile (
+		"move	%/sr,%%d0	\n\t"
+		"andi.l	#0xf8ff,%%d0	\n\t"
+		"move	%%d0,%/sr	\n"
+		: /* no outputs */
+		:
+		: "cc", "%d0", "memory");
+#else
+# if defined(CONFIG_MMU)
+	if (MACH_IS_Q40 || !hardirq_count())
+# endif
+		asm volatile (
+			"andiw %0,%%sr"
+			:
+			: "i" (ALLOWINT)
+			: "memory");
+#endif
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags = arch_local_save_flags();
+	arch_local_irq_disable();
+	return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile ("movew %0,%%sr" : : "d" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags & ~ALLOWINT) != 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _M68K_IRQFLAGS_H */
diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h
index fc24b6f..789f3b2 100644
--- a/arch/m68k/include/asm/machdep.h
+++ b/arch/m68k/include/asm/machdep.h
@@ -1,5 +1,44 @@
-#ifdef __uClinux__
-#include "machdep_no.h"
-#else
-#include "machdep_mm.h"
-#endif
+#ifndef _M68K_MACHDEP_H
+#define _M68K_MACHDEP_H
+
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+
+struct pt_regs;
+struct mktime;
+struct rtc_time;
+struct rtc_pll_info;
+struct buffer_head;
+
+extern void (*mach_sched_init) (irq_handler_t handler);
+/* machine dependent irq functions */
+extern void (*mach_init_IRQ) (void);
+extern void (*mach_get_model) (char *model);
+extern void (*mach_get_hardware_list) (struct seq_file *m);
+/* machine dependent timer functions */
+extern unsigned long (*mach_gettimeoffset)(void);
+extern int (*mach_hwclk)(int, struct rtc_time*);
+extern unsigned int (*mach_get_ss)(void);
+extern int (*mach_get_rtc_pll)(struct rtc_pll_info *);
+extern int (*mach_set_rtc_pll)(struct rtc_pll_info *);
+extern int (*mach_set_clock_mmss)(unsigned long);
+extern void (*mach_gettod)(int *year, int *mon, int *day, int *hour,
+			    int *min, int *sec);
+extern void (*mach_reset)( void );
+extern void (*mach_halt)( void );
+extern void (*mach_power_off)( void );
+extern unsigned long (*mach_hd_init) (unsigned long, unsigned long);
+extern void (*mach_hd_setup)(char *, int *);
+extern long mach_max_dma_address;
+extern void (*mach_heartbeat) (int);
+extern void (*mach_l2_flush) (int);
+extern void (*mach_beep) (unsigned int, unsigned int);
+
+/* Hardware clock functions */
+extern void hw_timer_init(void);
+extern unsigned long hw_timer_offset(void);
+extern irqreturn_t arch_timer_interrupt(int irq, void *dummy);
+
+extern void config_BSP(char *command, int len);
+
+#endif /* _M68K_MACHDEP_H */
diff --git a/arch/m68k/include/asm/machdep_mm.h b/arch/m68k/include/asm/machdep_mm.h
deleted file mode 100644
index 5637dce..0000000
--- a/arch/m68k/include/asm/machdep_mm.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _M68K_MACHDEP_H
-#define _M68K_MACHDEP_H
-
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-
-struct pt_regs;
-struct mktime;
-struct rtc_time;
-struct rtc_pll_info;
-struct buffer_head;
-
-extern void (*mach_sched_init) (irq_handler_t handler);
-/* machine dependent irq functions */
-extern void (*mach_init_IRQ) (void);
-extern void (*mach_get_model) (char *model);
-extern void (*mach_get_hardware_list) (struct seq_file *m);
-/* machine dependent timer functions */
-extern unsigned long (*mach_gettimeoffset)(void);
-extern int (*mach_hwclk)(int, struct rtc_time*);
-extern unsigned int (*mach_get_ss)(void);
-extern int (*mach_get_rtc_pll)(struct rtc_pll_info *);
-extern int (*mach_set_rtc_pll)(struct rtc_pll_info *);
-extern int (*mach_set_clock_mmss)(unsigned long);
-extern void (*mach_reset)( void );
-extern void (*mach_halt)( void );
-extern void (*mach_power_off)( void );
-extern unsigned long (*mach_hd_init) (unsigned long, unsigned long);
-extern void (*mach_hd_setup)(char *, int *);
-extern long mach_max_dma_address;
-extern void (*mach_heartbeat) (int);
-extern void (*mach_l2_flush) (int);
-extern void (*mach_beep) (unsigned int, unsigned int);
-
-#endif /* _M68K_MACHDEP_H */
diff --git a/arch/m68k/include/asm/machdep_no.h b/arch/m68k/include/asm/machdep_no.h
deleted file mode 100644
index de9f47a..0000000
--- a/arch/m68k/include/asm/machdep_no.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef _M68KNOMMU_MACHDEP_H
-#define _M68KNOMMU_MACHDEP_H
-
-#include <linux/interrupt.h>
-
-/* Hardware clock functions */
-extern void hw_timer_init(void);
-extern unsigned long hw_timer_offset(void);
-
-extern irqreturn_t arch_timer_interrupt(int irq, void *dummy);
-
-/* Machine dependent time handling */
-extern void (*mach_gettod)(int *year, int *mon, int *day, int *hour,
-			   int *min, int *sec);
-extern int (*mach_set_clock_mmss)(unsigned long);
-
-/* machine dependent power off functions */
-extern void (*mach_reset)( void );
-extern void (*mach_halt)( void );
-extern void (*mach_power_off)( void );
-
-extern void config_BSP(char *command, int len);
-
-extern void do_IRQ(int irq, struct pt_regs *fp);
-
-#endif /* _M68KNOMMU_MACHDEP_H */
diff --git a/arch/m68k/include/asm/page.h b/arch/m68k/include/asm/page.h
index f2b4480..dfebb7c 100644
--- a/arch/m68k/include/asm/page.h
+++ b/arch/m68k/include/asm/page.h
@@ -1,5 +1,49 @@
-#ifdef __uClinux__
-#include "page_no.h"
+#ifndef _M68K_PAGE_H
+#define _M68K_PAGE_H
+
+#include <linux/const.h>
+#include <asm/setup.h>
+#include <asm/page_offset.h>
+
+/* PAGE_SHIFT determines the page size */
+#ifndef CONFIG_SUN3
+#define PAGE_SHIFT	(12)
 #else
-#include "page_mm.h"
+#define PAGE_SHIFT	(13)
 #endif
+#define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
+#define PAGE_MASK	(~(PAGE_SIZE-1))
+#define PAGE_OFFSET	(PAGE_OFFSET_RAW)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd[16]; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
+
+#define pte_val(x)	((x).pte)
+#define pmd_val(x)	((&x)->pmd[0])
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x)	((pte_t) { (x) } )
+#define __pmd(x)	((pmd_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+#endif /* !__ASSEMBLY__ */
+
+#ifdef CONFIG_MMU
+#include "page_mm.h"
+#else
+#include "page_no.h"
+#endif
+
+#include <asm-generic/getorder.h>
+
+#endif /* _M68K_PAGE_H */
diff --git a/arch/m68k/include/asm/page_mm.h b/arch/m68k/include/asm/page_mm.h
index d009f3e..31d5570 100644
--- a/arch/m68k/include/asm/page_mm.h
+++ b/arch/m68k/include/asm/page_mm.h
@@ -1,29 +1,9 @@
-#ifndef _M68K_PAGE_H
-#define _M68K_PAGE_H
-
-#include <linux/const.h>
-
-/* PAGE_SHIFT determines the page size */
-#ifndef CONFIG_SUN3
-#define PAGE_SHIFT	(12)
-#else
-#define PAGE_SHIFT	(13)
-#endif
-#define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK	(~(PAGE_SIZE-1))
-
-#include <asm/setup.h>
-
-#if PAGE_SHIFT < 13
-#define THREAD_SIZE (8192)
-#else
-#define THREAD_SIZE PAGE_SIZE
-#endif
+#ifndef _M68K_PAGE_MM_H
+#define _M68K_PAGE_MM_H
 
 #ifndef __ASSEMBLY__
 
 #include <linux/compiler.h>
-
 #include <asm/module.h>
 
 #define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
@@ -84,33 +64,6 @@
 		flush_dcache_page(page);	\
 	} while (0)
 
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd[16]; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-typedef struct page *pgtable_t;
-
-#define pte_val(x)	((x).pte)
-#define pmd_val(x)	((&x)->pmd[0])
-#define pgd_val(x)	((x).pgd)
-#define pgprot_val(x)	((x).pgprot)
-
-#define __pte(x)	((pte_t) { (x) } )
-#define __pmd(x)	((pmd_t) { (x) } )
-#define __pgd(x)	((pgd_t) { (x) } )
-#define __pgprot(x)	((pgprot_t) { (x) } )
-
-#endif /* !__ASSEMBLY__ */
-
-#include <asm/page_offset.h>
-
-#define PAGE_OFFSET		(PAGE_OFFSET_RAW)
-
-#ifndef __ASSEMBLY__
-
 extern unsigned long m68k_memoffset;
 
 #ifndef CONFIG_SUN3
@@ -127,7 +80,7 @@
 		: "0" (vaddr), "i" (m68k_fixup_memoffset));
 	return paddr;
 }
-#define __pa(vaddr)	___pa((void *)(vaddr))
+#define __pa(vaddr)	___pa((void *)(long)(vaddr))
 static inline void *__va(unsigned long paddr)
 {
 	void *vaddr;
@@ -223,6 +176,4 @@
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#include <asm-generic/getorder.h>
-
-#endif /* _M68K_PAGE_H */
+#endif /* _M68K_PAGE_MM_H */
diff --git a/arch/m68k/include/asm/page_no.h b/arch/m68k/include/asm/page_no.h
index 8029a33..9059572 100644
--- a/arch/m68k/include/asm/page_no.h
+++ b/arch/m68k/include/asm/page_no.h
@@ -1,18 +1,11 @@
-#ifndef _M68KNOMMU_PAGE_H
-#define _M68KNOMMU_PAGE_H
-
-#include <linux/const.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))
-
-#include <asm/setup.h>
+#ifndef _M68K_PAGE_NO_H
+#define _M68K_PAGE_NO_H
 
 #ifndef __ASSEMBLY__
  
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+
 #define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
 #define free_user_page(page, addr)	free_page(addr)
 
@@ -26,36 +19,6 @@
 	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd[16]; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-typedef struct page *pgtable_t;
-
-#define pte_val(x)	((x).pte)
-#define pmd_val(x)	((&x)->pmd[0])
-#define pgd_val(x)	((x).pgd)
-#define pgprot_val(x)	((x).pgprot)
-
-#define __pte(x)	((pte_t) { (x) } )
-#define __pmd(x)	((pmd_t) { (x) } )
-#define __pgd(x)	((pgd_t) { (x) } )
-#define __pgprot(x)	((pgprot_t) { (x) } )
-
-extern unsigned long memory_start;
-extern unsigned long memory_end;
-
-#endif /* !__ASSEMBLY__ */
-
-#include <asm/page_offset.h>
-
-#define PAGE_OFFSET		(PAGE_OFFSET_RAW)
-
-#ifndef __ASSEMBLY__
-
 #define __pa(vaddr)		((unsigned long)(vaddr))
 #define __va(paddr)		((void *)(paddr))
 
@@ -74,6 +37,4 @@
 
 #endif /* __ASSEMBLY__ */
 
-#include <asm-generic/getorder.h>
-
-#endif /* _M68KNOMMU_PAGE_H */
+#endif /* _M68K_PAGE_NO_H */
diff --git a/arch/m68k/include/asm/string.h b/arch/m68k/include/asm/string.h
index 2c356f9..2936dda 100644
--- a/arch/m68k/include/asm/string.h
+++ b/arch/m68k/include/asm/string.h
@@ -1,5 +1,133 @@
-#ifdef __uClinux__
-#include "string_no.h"
+#ifndef _M68K_STRING_H_
+#define _M68K_STRING_H_
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+static inline size_t __kernel_strlen(const char *s)
+{
+	const char *sc;
+
+	for (sc = s; *sc++; )
+		;
+	return sc - s - 1;
+}
+
+static inline char *__kernel_strcpy(char *dest, const char *src)
+{
+	char *xdest = dest;
+
+	asm volatile ("\n"
+		"1:	move.b	(%1)+,(%0)+\n"
+		"	jne	1b"
+		: "+a" (dest), "+a" (src)
+		: : "memory");
+	return xdest;
+}
+
+#ifndef __IN_STRING_C
+
+#define __HAVE_ARCH_STRLEN
+#define strlen(s)	(__builtin_constant_p(s) ?	\
+			 __builtin_strlen(s) :		\
+			 __kernel_strlen(s))
+
+#define __HAVE_ARCH_STRNLEN
+static inline size_t strnlen(const char *s, size_t count)
+{
+	const char *sc = s;
+
+	asm volatile ("\n"
+		"1:     subq.l  #1,%1\n"
+		"       jcs     2f\n"
+		"       tst.b   (%0)+\n"
+		"       jne     1b\n"
+		"       subq.l  #1,%0\n"
+		"2:"
+		: "+a" (sc), "+d" (count));
+	return sc - s;
+}
+
+#define __HAVE_ARCH_STRCPY
+#if __GNUC__ >= 4
+#define strcpy(d, s)	(__builtin_constant_p(s) &&	\
+			 __builtin_strlen(s) <= 32 ?	\
+			 __builtin_strcpy(d, s) :	\
+			 __kernel_strcpy(d, s))
 #else
-#include "string_mm.h"
+#define strcpy(d, s)	__kernel_strcpy(d, s)
 #endif
+
+#define __HAVE_ARCH_STRNCPY
+static inline char *strncpy(char *dest, const char *src, size_t n)
+{
+	char *xdest = dest;
+
+	asm volatile ("\n"
+		"	jra	2f\n"
+		"1:	move.b	(%1),(%0)+\n"
+		"	jeq	2f\n"
+		"	addq.l	#1,%1\n"
+		"2:	subq.l	#1,%2\n"
+		"	jcc	1b\n"
+		: "+a" (dest), "+a" (src), "+d" (n)
+		: : "memory");
+	return xdest;
+}
+
+#define __HAVE_ARCH_STRCAT
+#define strcat(d, s)	({			\
+	char *__d = (d);			\
+	strcpy(__d + strlen(__d), (s));		\
+})
+
+#define __HAVE_ARCH_STRCHR
+static inline char *strchr(const char *s, int c)
+{
+	char sc, ch = c;
+
+	for (; (sc = *s++) != ch; ) {
+		if (!sc)
+			return NULL;
+	}
+	return (char *)s - 1;
+}
+
+#ifndef CONFIG_COLDFIRE
+#define __HAVE_ARCH_STRCMP
+static inline int strcmp(const char *cs, const char *ct)
+{
+	char res;
+
+	asm ("\n"
+		"1:	move.b	(%0)+,%2\n"	/* get *cs */
+		"	cmp.b	(%1)+,%2\n"	/* compare a byte */
+		"	jne	2f\n"		/* not equal, break out */
+		"	tst.b	%2\n"		/* at end of cs? */
+		"	jne	1b\n"		/* no, keep going */
+		"	jra	3f\n"		/* strings are equal */
+		"2:	sub.b	-(%1),%2\n"	/* *cs - *ct */
+		"3:"
+		: "+a" (cs), "+a" (ct), "=d" (res));
+	return res;
+}
+
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMCMP
+extern int memcmp(const void *, const void *, __kernel_size_t);
+#define memcmp(d, s, n) __builtin_memcmp(d, s, n)
+#endif /* CONFIG_COLDFIRE */
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *, int, __kernel_size_t);
+#define memset(d, c, n) __builtin_memset(d, c, n)
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *, const void *, __kernel_size_t);
+#define memcpy(d, s, n) __builtin_memcpy(d, s, n)
+
+#endif
+
+#endif /* _M68K_STRING_H_ */
diff --git a/arch/m68k/include/asm/string_mm.h b/arch/m68k/include/asm/string_mm.h
deleted file mode 100644
index 2eb7df1..0000000
--- a/arch/m68k/include/asm/string_mm.h
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifndef _M68K_STRING_H_
-#define _M68K_STRING_H_
-
-#include <linux/types.h>
-#include <linux/compiler.h>
-
-static inline size_t __kernel_strlen(const char *s)
-{
-	const char *sc;
-
-	for (sc = s; *sc++; )
-		;
-	return sc - s - 1;
-}
-
-static inline char *__kernel_strcpy(char *dest, const char *src)
-{
-	char *xdest = dest;
-
-	asm volatile ("\n"
-		"1:	move.b	(%1)+,(%0)+\n"
-		"	jne	1b"
-		: "+a" (dest), "+a" (src)
-		: : "memory");
-	return xdest;
-}
-
-#ifndef __IN_STRING_C
-
-#define __HAVE_ARCH_STRLEN
-#define strlen(s)	(__builtin_constant_p(s) ?	\
-			 __builtin_strlen(s) :		\
-			 __kernel_strlen(s))
-
-#define __HAVE_ARCH_STRNLEN
-static inline size_t strnlen(const char *s, size_t count)
-{
-	const char *sc = s;
-
-	asm volatile ("\n"
-		"1:     subq.l  #1,%1\n"
-		"       jcs     2f\n"
-		"       tst.b   (%0)+\n"
-		"       jne     1b\n"
-		"       subq.l  #1,%0\n"
-		"2:"
-		: "+a" (sc), "+d" (count));
-	return sc - s;
-}
-
-#define __HAVE_ARCH_STRCPY
-#if __GNUC__ >= 4
-#define strcpy(d, s)	(__builtin_constant_p(s) &&	\
-			 __builtin_strlen(s) <= 32 ?	\
-			 __builtin_strcpy(d, s) :	\
-			 __kernel_strcpy(d, s))
-#else
-#define strcpy(d, s)	__kernel_strcpy(d, s)
-#endif
-
-#define __HAVE_ARCH_STRNCPY
-static inline char *strncpy(char *dest, const char *src, size_t n)
-{
-	char *xdest = dest;
-
-	asm volatile ("\n"
-		"	jra	2f\n"
-		"1:	move.b	(%1),(%0)+\n"
-		"	jeq	2f\n"
-		"	addq.l	#1,%1\n"
-		"2:	subq.l	#1,%2\n"
-		"	jcc	1b\n"
-		: "+a" (dest), "+a" (src), "+d" (n)
-		: : "memory");
-	return xdest;
-}
-
-#define __HAVE_ARCH_STRCAT
-#define strcat(d, s)	({			\
-	char *__d = (d);			\
-	strcpy(__d + strlen(__d), (s));		\
-})
-
-#define __HAVE_ARCH_STRCHR
-static inline char *strchr(const char *s, int c)
-{
-	char sc, ch = c;
-
-	for (; (sc = *s++) != ch; ) {
-		if (!sc)
-			return NULL;
-	}
-	return (char *)s - 1;
-}
-
-#define __HAVE_ARCH_STRCMP
-static inline int strcmp(const char *cs, const char *ct)
-{
-	char res;
-
-	asm ("\n"
-		"1:	move.b	(%0)+,%2\n"	/* get *cs */
-		"	cmp.b	(%1)+,%2\n"	/* compare a byte */
-		"	jne	2f\n"		/* not equal, break out */
-		"	tst.b	%2\n"		/* at end of cs? */
-		"	jne	1b\n"		/* no, keep going */
-		"	jra	3f\n"		/* strings are equal */
-		"2:	sub.b	-(%1),%2\n"	/* *cs - *ct */
-		"3:"
-		: "+a" (cs), "+a" (ct), "=d" (res));
-	return res;
-}
-
-#define __HAVE_ARCH_MEMSET
-extern void *memset(void *, int, __kernel_size_t);
-#define memset(d, c, n) __builtin_memset(d, c, n)
-
-#define __HAVE_ARCH_MEMCPY
-extern void *memcpy(void *, const void *, __kernel_size_t);
-#define memcpy(d, s, n) __builtin_memcpy(d, s, n)
-
-#define __HAVE_ARCH_MEMMOVE
-extern void *memmove(void *, const void *, __kernel_size_t);
-
-#define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *, const void *, __kernel_size_t);
-#define memcmp(d, s, n) __builtin_memcmp(d, s, n)
-
-#endif
-
-#endif /* _M68K_STRING_H_ */
diff --git a/arch/m68k/include/asm/string_no.h b/arch/m68k/include/asm/string_no.h
deleted file mode 100644
index af09e17..0000000
--- a/arch/m68k/include/asm/string_no.h
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifndef _M68KNOMMU_STRING_H_
-#define _M68KNOMMU_STRING_H_
-
-#ifdef __KERNEL__ /* only set these up for kernel code */
-
-#include <asm/setup.h>
-#include <asm/page.h>
-
-#define __HAVE_ARCH_STRCPY
-static inline char * strcpy(char * dest,const char *src)
-{
-  char *xdest = dest;
-
-  __asm__ __volatile__
-       ("1:\tmoveb %1@+,%0@+\n\t"
-        "jne 1b"
-	: "=a" (dest), "=a" (src)
-        : "0" (dest), "1" (src) : "memory");
-  return xdest;
-}
-
-#define __HAVE_ARCH_STRNCPY
-static inline char * strncpy(char *dest, const char *src, size_t n)
-{
-  char *xdest = dest;
-
-  if (n == 0)
-    return xdest;
-
-  __asm__ __volatile__
-       ("1:\tmoveb %1@+,%0@+\n\t"
-	"jeq 2f\n\t"
-        "subql #1,%2\n\t"
-        "jne 1b\n\t"
-        "2:"
-        : "=a" (dest), "=a" (src), "=d" (n)
-        : "0" (dest), "1" (src), "2" (n)
-        : "memory");
-  return xdest;
-}
-
-
-#ifndef CONFIG_COLDFIRE
-
-#define __HAVE_ARCH_STRCMP
-static inline int strcmp(const char * cs,const char * ct)
-{
-  char __res;
-
-  __asm__
-       ("1:\tmoveb %0@+,%2\n\t" /* get *cs */
-        "cmpb %1@+,%2\n\t"      /* compare a byte */
-        "jne  2f\n\t"           /* not equal, break out */
-        "tstb %2\n\t"           /* at end of cs? */
-        "jne  1b\n\t"           /* no, keep going */
-        "jra  3f\n\t"		/* strings are equal */
-        "2:\tsubb %1@-,%2\n\t"  /* *cs - *ct */
-        "3:"
-        : "=a" (cs), "=a" (ct), "=d" (__res)
-        : "0" (cs), "1" (ct));
-
-  return __res;
-}
-
-#define __HAVE_ARCH_STRNCMP
-static inline int strncmp(const char * cs,const char * ct,size_t count)
-{
-  char __res;
-
-  if (!count)
-    return 0;
-  __asm__
-       ("1:\tmovb %0@+,%3\n\t"          /* get *cs */
-        "cmpb   %1@+,%3\n\t"            /* compare a byte */
-        "jne    3f\n\t"                 /* not equal, break out */
-        "tstb   %3\n\t"                 /* at end of cs? */
-        "jeq    4f\n\t"                 /* yes, all done */
-        "subql  #1,%2\n\t"              /* no, adjust count */
-        "jne    1b\n\t"                 /* more to do, keep going */
-        "2:\tmoveq #0,%3\n\t"           /* strings are equal */
-        "jra    4f\n\t"
-        "3:\tsubb %1@-,%3\n\t"          /* *cs - *ct */
-        "4:"
-        : "=a" (cs), "=a" (ct), "=d" (count), "=d" (__res)
-        : "0" (cs), "1" (ct), "2" (count));
-  return __res;
-}
-
-#endif /* CONFIG_COLDFIRE */
-
-#define __HAVE_ARCH_MEMSET
-extern void * memset(void * s, int c, size_t count);
-
-#define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *d, const void *s, size_t count);
-
-#else /* KERNEL */
-
-/*
- *	let user libraries deal with these,
- *	IMHO the kernel has no place defining these functions for user apps
- */
-
-#define __HAVE_ARCH_STRCPY 1
-#define __HAVE_ARCH_STRNCPY 1
-#define __HAVE_ARCH_STRCAT 1
-#define __HAVE_ARCH_STRNCAT 1
-#define __HAVE_ARCH_STRCMP 1
-#define __HAVE_ARCH_STRNCMP 1
-#define __HAVE_ARCH_STRNICMP 1
-#define __HAVE_ARCH_STRCHR 1
-#define __HAVE_ARCH_STRRCHR 1
-#define __HAVE_ARCH_STRSTR 1
-#define __HAVE_ARCH_STRLEN 1
-#define __HAVE_ARCH_STRNLEN 1
-#define __HAVE_ARCH_MEMSET 1
-#define __HAVE_ARCH_MEMCPY 1
-#define __HAVE_ARCH_MEMMOVE 1
-#define __HAVE_ARCH_MEMSCAN 1
-#define __HAVE_ARCH_MEMCMP 1
-#define __HAVE_ARCH_MEMCHR 1
-#define __HAVE_ARCH_STRTOK 1
-
-#endif /* KERNEL */
-
-#endif /* _M68K_STRING_H_ */
diff --git a/arch/m68k/include/asm/system_mm.h b/arch/m68k/include/asm/system_mm.h
index dbb6515..47b01f47 100644
--- a/arch/m68k/include/asm/system_mm.h
+++ b/arch/m68k/include/asm/system_mm.h
@@ -3,6 +3,7 @@
 
 #include <linux/linkage.h>
 #include <linux/kernel.h>
+#include <linux/irqflags.h>
 #include <asm/segment.h>
 #include <asm/entry.h>
 
@@ -62,30 +63,6 @@
 #define smp_wmb()	barrier()
 #define smp_read_barrier_depends()	((void)0)
 
-/* interrupt control.. */
-#if 0
-#define local_irq_enable() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory")
-#else
-#include <linux/hardirq.h>
-#define local_irq_enable() ({							\
-	if (MACH_IS_Q40 || !hardirq_count())					\
-		asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory");	\
-})
-#endif
-#define local_irq_disable() asm volatile ("oriw  #0x0700,%%sr": : : "memory")
-#define local_save_flags(x) asm volatile ("movew %%sr,%0":"=d" (x) : : "memory")
-#define local_irq_restore(x) asm volatile ("movew %0,%%sr": :"d" (x) : "memory")
-
-static inline int irqs_disabled(void)
-{
-	unsigned long flags;
-	local_save_flags(flags);
-	return flags & ~ALLOWINT;
-}
-
-/* For spinlocks etc */
-#define local_irq_save(x)	({ local_save_flags(x); local_irq_disable(); })
-
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
 struct __xchg_dummy { unsigned long a[100]; };
@@ -205,9 +182,7 @@
 	((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
 			(unsigned long)(n), sizeof(*(ptr))))
 
-#ifndef CONFIG_SMP
 #include <asm-generic/cmpxchg.h>
-#endif
 
 #endif
 
diff --git a/arch/m68k/include/asm/system_no.h b/arch/m68k/include/asm/system_no.h
index 3c0718d..6fe9f93 100644
--- a/arch/m68k/include/asm/system_no.h
+++ b/arch/m68k/include/asm/system_no.h
@@ -2,6 +2,7 @@
 #define _M68KNOMMU_SYSTEM_H
 
 #include <linux/linkage.h>
+#include <linux/irqflags.h>
 #include <asm/segment.h>
 #include <asm/entry.h>
 
@@ -46,54 +47,6 @@
   (last) = _last;						\
 }
 
-#ifdef CONFIG_COLDFIRE
-#define local_irq_enable() __asm__ __volatile__ (		\
-	"move %/sr,%%d0\n\t"					\
-	"andi.l #0xf8ff,%%d0\n\t"				\
-	"move %%d0,%/sr\n"					\
-	: /* no outputs */					\
-	:							\
-        : "cc", "%d0", "memory")
-#define local_irq_disable() __asm__ __volatile__ (		\
-	"move %/sr,%%d0\n\t"					\
-	"ori.l #0x0700,%%d0\n\t"				\
-	"move %%d0,%/sr\n"					\
-	: /* no outputs */					\
-	:							\
-	: "cc", "%d0", "memory")
-/* For spinlocks etc */
-#define local_irq_save(x) __asm__ __volatile__ (		\
-	"movew %%sr,%0\n\t"					\
-	"movew #0x0700,%%d0\n\t"				\
-	"or.l  %0,%%d0\n\t"					\
-	"movew %%d0,%/sr"					\
-	: "=d" (x)						\
-	:							\
-	: "cc", "%d0", "memory")
-#else
-
-/* portable version */ /* FIXME - see entry.h*/
-#define ALLOWINT 0xf8ff
-
-#define local_irq_enable() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory")
-#define local_irq_disable() asm volatile ("oriw  #0x0700,%%sr": : : "memory")
-#endif
-
-#define local_save_flags(x) asm volatile ("movew %%sr,%0":"=d" (x) : : "memory")
-#define local_irq_restore(x) asm volatile ("movew %0,%%sr": :"d" (x) : "memory")
-
-/* For spinlocks etc */
-#ifndef local_irq_save
-#define local_irq_save(x) do { local_save_flags(x); local_irq_disable(); } while (0)
-#endif
-
-#define	irqs_disabled()			\
-({					\
-	unsigned long flags;		\
-	local_save_flags(flags);	\
-	((flags & 0x0700) == 0x0700);	\
-})
-
 #define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
 
 /*
@@ -106,17 +59,10 @@
 #define wmb()  asm volatile (""   : : :"memory")
 #define set_mb(var, value)	({ (var) = (value); wmb(); })
 
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#define smp_rmb()	rmb()
-#define smp_wmb()	wmb()
-#define smp_read_barrier_depends()	read_barrier_depends()
-#else
 #define smp_mb()	barrier()
 #define smp_rmb()	barrier()
 #define smp_wmb()	barrier()
 #define smp_read_barrier_depends()	do { } while(0)
-#endif
 
 #define read_barrier_depends()  ((void)0)
 
@@ -199,19 +145,9 @@
 			(unsigned long)(n), sizeof(*(ptr))))
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 
-#ifndef CONFIG_SMP
 #include <asm-generic/cmpxchg.h>
-#endif
 
 #define arch_align_stack(x) (x)
 
 
-static inline int irqs_disabled_flags(unsigned long flags)
-{
-	if (flags & 0x0700)
-		return 0;
-	else
-		return 1;
-}
-
 #endif /* _M68KNOMMU_SYSTEM_H */
diff --git a/arch/m68k/include/asm/thread_info.h b/arch/m68k/include/asm/thread_info.h
index f31a3f4..1da5d53 100644
--- a/arch/m68k/include/asm/thread_info.h
+++ b/arch/m68k/include/asm/thread_info.h
@@ -1,5 +1,108 @@
-#ifdef __uClinux__
-#include "thread_info_no.h"
+#ifndef _ASM_M68K_THREAD_INFO_H
+#define _ASM_M68K_THREAD_INFO_H
+
+#include <asm/types.h>
+#include <asm/page.h>
+
+/*
+ * On machines with 4k pages we default to an 8k thread size, though we
+ * allow a 4k with config option. Any other machine page size then
+ * the thread size must match the page size (which is 8k and larger here).
+ */
+#if PAGE_SHIFT < 13
+#ifdef CONFIG_4KSTACKS
+#define THREAD_SIZE	4096
 #else
-#include "thread_info_mm.h"
+#define THREAD_SIZE	8192
 #endif
+#else
+#define THREAD_SIZE	PAGE_SIZE
+#endif
+#define THREAD_SIZE_ORDER	((THREAD_SIZE / PAGE_SIZE) - 1)
+
+#ifndef __ASSEMBLY__
+
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	unsigned long		flags;
+	struct exec_domain	*exec_domain;	/* execution domain */
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	__u32			cpu;		/* should always be 0 on m68k */
+	unsigned long		tp_value;	/* thread pointer */
+	struct restart_block    restart_block;
+};
+#endif /* __ASSEMBLY__ */
+
+#define PREEMPT_ACTIVE		0x4000000
+
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	.task		= &tsk,			\
+	.exec_domain	= &default_exec_domain,	\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
+	.restart_block = {			\
+		.fn = do_no_restart_syscall,	\
+	},					\
+}
+
+#define init_stack		(init_thread_union.stack)
+
+#ifdef CONFIG_MMU
+
+#ifndef __ASSEMBLY__
+#include <asm/current.h>
+#endif
+
+#ifdef ASM_OFFSETS_C
+#define task_thread_info(tsk)	((struct thread_info *) NULL)
+#else
+#include <asm/asm-offsets.h>
+#define task_thread_info(tsk)	((struct thread_info *)((char *)tsk+TASK_TINFO))
+#endif
+
+#define init_thread_info	(init_task.thread.info)
+#define task_stack_page(tsk)	((tsk)->stack)
+#define current_thread_info()	task_thread_info(current)
+
+#define __HAVE_THREAD_FUNCTIONS
+
+#define setup_thread_stack(p, org) ({			\
+	*(struct task_struct **)(p)->stack = (p);	\
+	task_thread_info(p)->task = (p);		\
+})
+
+#define end_of_stack(p)		((unsigned long *)(p)->stack + 1)
+
+#else /* !CONFIG_MMU */
+
+#ifndef __ASSEMBLY__
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+	struct thread_info *ti;
+	__asm__(
+		"move.l %%sp, %0 \n\t"
+		"and.l  %1, %0"
+		: "=&d"(ti)
+		: "di" (~(THREAD_SIZE-1))
+		);
+	return ti;
+}
+#endif
+
+#define init_thread_info	(init_thread_union.thread_info)
+
+#endif /* CONFIG_MMU */
+
+/* entry.S relies on these definitions!
+ * bits 0-7 are tested at every exception exit
+ * bits 8-15 are also tested at syscall exit
+ */
+#define TIF_SIGPENDING		6	/* signal pending */
+#define TIF_NEED_RESCHED	7	/* rescheduling necessary */
+#define TIF_DELAYED_TRACE	14	/* single step a syscall */
+#define TIF_SYSCALL_TRACE	15	/* syscall trace active */
+#define TIF_MEMDIE		16	/* is terminating due to OOM killer */
+#define TIF_FREEZE		17	/* thread is freezing for suspend */
+
+#endif	/* _ASM_M68K_THREAD_INFO_H */
diff --git a/arch/m68k/include/asm/thread_info_mm.h b/arch/m68k/include/asm/thread_info_mm.h
deleted file mode 100644
index 3bf31dc..0000000
--- a/arch/m68k/include/asm/thread_info_mm.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef _ASM_M68K_THREAD_INFO_H
-#define _ASM_M68K_THREAD_INFO_H
-
-#ifndef ASM_OFFSETS_C
-#include <asm/asm-offsets.h>
-#endif
-#include <asm/types.h>
-#include <asm/page.h>
-
-#ifndef __ASSEMBLY__
-#include <asm/current.h>
-
-struct thread_info {
-	struct task_struct	*task;		/* main task structure */
-	unsigned long		flags;
-	struct exec_domain	*exec_domain;	/* execution domain */
-	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
-	__u32 cpu; /* should always be 0 on m68k */
-	unsigned long		tp_value;	/* thread pointer */
-	struct restart_block    restart_block;
-};
-#endif /* __ASSEMBLY__ */
-
-#define PREEMPT_ACTIVE		0x4000000
-
-#define INIT_THREAD_INFO(tsk)			\
-{						\
-	.task		= &tsk,			\
-	.exec_domain	= &default_exec_domain,	\
-	.preempt_count	= INIT_PREEMPT_COUNT,	\
-	.restart_block = {			\
-		.fn = do_no_restart_syscall,	\
-	},					\
-}
-
-/* THREAD_SIZE should be 8k, so handle differently for 4k and 8k machines */
-#define THREAD_SIZE_ORDER (13 - PAGE_SHIFT)
-
-#define init_thread_info	(init_task.thread.info)
-#define init_stack		(init_thread_union.stack)
-
-#ifdef ASM_OFFSETS_C
-#define task_thread_info(tsk)	((struct thread_info *) NULL)
-#else
-#define task_thread_info(tsk)	((struct thread_info *)((char *)tsk+TASK_TINFO))
-#endif
-
-#define task_stack_page(tsk)	((tsk)->stack)
-#define current_thread_info()	task_thread_info(current)
-
-#define __HAVE_THREAD_FUNCTIONS
-
-#define setup_thread_stack(p, org) ({			\
-	*(struct task_struct **)(p)->stack = (p);	\
-	task_thread_info(p)->task = (p);		\
-})
-
-#define end_of_stack(p) ((unsigned long *)(p)->stack + 1)
-
-/* entry.S relies on these definitions!
- * bits 0-7 are tested at every exception exit
- * bits 8-15 are also tested at syscall exit
- */
-#define TIF_SIGPENDING		6	/* signal pending */
-#define TIF_NEED_RESCHED	7	/* rescheduling necessary */
-#define TIF_DELAYED_TRACE	14	/* single step a syscall */
-#define TIF_SYSCALL_TRACE	15	/* syscall trace active */
-#define TIF_MEMDIE		16	/* is terminating due to OOM killer */
-#define TIF_FREEZE		17	/* thread is freezing for suspend */
-
-#endif	/* _ASM_M68K_THREAD_INFO_H */
diff --git a/arch/m68k/include/asm/thread_info_no.h b/arch/m68k/include/asm/thread_info_no.h
deleted file mode 100644
index 51f354b..0000000
--- a/arch/m68k/include/asm/thread_info_no.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* thread_info.h: m68knommu low-level thread information
- * adapted from the i386 and PPC versions by Greg Ungerer (gerg@snapgear.com)
- *
- * Copyright (C) 2002  David Howells (dhowells@redhat.com)
- * - Incorporating suggestions made by Linus Torvalds and Dave Miller
- */
-
-#ifndef _ASM_THREAD_INFO_H
-#define _ASM_THREAD_INFO_H
-
-#include <asm/page.h>
-
-#ifdef __KERNEL__
-
-/*
- * Size of kernel stack for each process. This must be a power of 2...
- */
-#ifdef CONFIG_4KSTACKS
-#define THREAD_SIZE_ORDER (0)
-#else
-#define THREAD_SIZE_ORDER (1)
-#endif
-                                                                                
-/*
- * for asm files, THREAD_SIZE is now generated by asm-offsets.c
- */
-#define THREAD_SIZE (PAGE_SIZE<<THREAD_SIZE_ORDER)
-
-#ifndef __ASSEMBLY__
-
-/*
- * low level task data.
- */
-struct thread_info {
-	struct task_struct *task;		/* main task structure */
-	struct exec_domain *exec_domain;	/* execution domain */
-	unsigned long	   flags;		/* low level flags */
-	int		   cpu;			/* cpu we're on */
-	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
-	unsigned long	   tp_value;		/* thread pointer */
-	struct restart_block restart_block;
-};
-
-/*
- * macros/functions for gaining access to the thread information structure
- */
-#define INIT_THREAD_INFO(tsk)			\
-{						\
-	.task		= &tsk,			\
-	.exec_domain	= &default_exec_domain,	\
-	.flags		= 0,			\
-	.cpu		= 0,			\
-	.preempt_count	= INIT_PREEMPT_COUNT,	\
-	.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)
-{
-	struct thread_info *ti;
-	__asm__(
-		"move.l	%%sp, %0 \n\t"
-		"and.l	%1, %0"
-		: "=&d"(ti)
-		: "di" (~(THREAD_SIZE-1))
-		);
-	return ti;
-}
-
-#endif /* __ASSEMBLY__ */
-
-#define	PREEMPT_ACTIVE	0x4000000
-
-/*
- * thread information flag bit numbers
- */
-#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
-#define TIF_SIGPENDING		1	/* signal pending */
-#define TIF_NEED_RESCHED	2	/* rescheduling necessary */
-#define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
-					   TIF_NEED_RESCHED */
-#define TIF_MEMDIE		4	/* is terminating due to OOM killer */
-#define TIF_FREEZE		16	/* is freezing for suspend */
-
-/* as above, but as bit values */
-#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
-#define _TIF_FREEZE		(1<<TIF_FREEZE)
-
-#define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/m68k/include/asm/traps.h b/arch/m68k/include/asm/traps.h
index 3011ec0..0bffb17 100644
--- a/arch/m68k/include/asm/traps.h
+++ b/arch/m68k/include/asm/traps.h
@@ -1,5 +1,272 @@
-#ifdef __uClinux__
-#include "traps_no.h"
-#else
-#include "traps_mm.h"
+/*
+ *  linux/include/asm/traps.h
+ *
+ *  Copyright (C) 1993        Hamish Macdonald
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _M68K_TRAPS_H
+#define _M68K_TRAPS_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+
+typedef void (*e_vector)(void);
+extern e_vector vectors[];
+
+asmlinkage void auto_inthandler(void);
+asmlinkage void user_inthandler(void);
+asmlinkage void bad_inthandler(void);
+extern void init_vectors(void);
+
 #endif
+
+#define VEC_RESETSP (0)
+#define VEC_RESETPC (1)
+#define VEC_BUSERR  (2)
+#define VEC_ADDRERR (3)
+#define VEC_ILLEGAL (4)
+#define VEC_ZERODIV (5)
+#define VEC_CHK     (6)
+#define VEC_TRAP    (7)
+#define VEC_PRIV    (8)
+#define VEC_TRACE   (9)
+#define VEC_LINE10  (10)
+#define VEC_LINE11  (11)
+#define VEC_RESV12  (12)
+#define VEC_COPROC  (13)
+#define VEC_FORMAT  (14)
+#define VEC_UNINT   (15)
+#define VEC_RESV16  (16)
+#define VEC_RESV17  (17)
+#define VEC_RESV18  (18)
+#define VEC_RESV19  (19)
+#define VEC_RESV20  (20)
+#define VEC_RESV21  (21)
+#define VEC_RESV22  (22)
+#define VEC_RESV23  (23)
+#define VEC_SPUR    (24)
+#define VEC_INT1    (25)
+#define VEC_INT2    (26)
+#define VEC_INT3    (27)
+#define VEC_INT4    (28)
+#define VEC_INT5    (29)
+#define VEC_INT6    (30)
+#define VEC_INT7    (31)
+#define VEC_SYS     (32)
+#define VEC_TRAP1   (33)
+#define VEC_TRAP2   (34)
+#define VEC_TRAP3   (35)
+#define VEC_TRAP4   (36)
+#define VEC_TRAP5   (37)
+#define VEC_TRAP6   (38)
+#define VEC_TRAP7   (39)
+#define VEC_TRAP8   (40)
+#define VEC_TRAP9   (41)
+#define VEC_TRAP10  (42)
+#define VEC_TRAP11  (43)
+#define VEC_TRAP12  (44)
+#define VEC_TRAP13  (45)
+#define VEC_TRAP14  (46)
+#define VEC_TRAP15  (47)
+#define VEC_FPBRUC  (48)
+#define VEC_FPIR    (49)
+#define VEC_FPDIVZ  (50)
+#define VEC_FPUNDER (51)
+#define VEC_FPOE    (52)
+#define VEC_FPOVER  (53)
+#define VEC_FPNAN   (54)
+#define VEC_FPUNSUP (55)
+#define VEC_MMUCFG  (56)
+#define VEC_MMUILL  (57)
+#define VEC_MMUACC  (58)
+#define VEC_RESV59  (59)
+#define	VEC_UNIMPEA (60)
+#define	VEC_UNIMPII (61)
+#define VEC_RESV62  (62)
+#define VEC_RESV63  (63)
+#define VEC_USER    (64)
+
+#define VECOFF(vec) ((vec)<<2)
+
+#ifndef __ASSEMBLY__
+
+/* Status register bits */
+#define PS_T  (0x8000)
+#define PS_S  (0x2000)
+#define PS_M  (0x1000)
+#define PS_C  (0x0001)
+
+/* bits for 68020/68030 special status word */
+
+#define FC    (0x8000)
+#define FB    (0x4000)
+#define RC    (0x2000)
+#define RB    (0x1000)
+#define DF    (0x0100)
+#define RM    (0x0080)
+#define RW    (0x0040)
+#define SZ    (0x0030)
+#define DFC   (0x0007)
+
+/* bits for 68030 MMU status register (mmusr,psr) */
+
+#define MMU_B	     (0x8000)    /* bus error */
+#define MMU_L	     (0x4000)    /* limit violation */
+#define MMU_S	     (0x2000)    /* supervisor violation */
+#define MMU_WP	     (0x0800)    /* write-protected */
+#define MMU_I	     (0x0400)    /* invalid descriptor */
+#define MMU_M	     (0x0200)    /* ATC entry modified */
+#define MMU_T	     (0x0040)    /* transparent translation */
+#define MMU_NUM      (0x0007)    /* number of levels traversed */
+
+
+/* bits for 68040 special status word */
+#define CP_040	(0x8000)
+#define CU_040	(0x4000)
+#define CT_040	(0x2000)
+#define CM_040	(0x1000)
+#define MA_040	(0x0800)
+#define ATC_040 (0x0400)
+#define LK_040	(0x0200)
+#define RW_040	(0x0100)
+#define SIZ_040 (0x0060)
+#define TT_040	(0x0018)
+#define TM_040	(0x0007)
+
+/* bits for 68040 write back status word */
+#define WBV_040   (0x80)
+#define WBSIZ_040 (0x60)
+#define WBBYT_040 (0x20)
+#define WBWRD_040 (0x40)
+#define WBLNG_040 (0x00)
+#define WBTT_040  (0x18)
+#define WBTM_040  (0x07)
+
+/* bus access size codes */
+#define BA_SIZE_BYTE    (0x20)
+#define BA_SIZE_WORD    (0x40)
+#define BA_SIZE_LONG    (0x00)
+#define BA_SIZE_LINE    (0x60)
+
+/* bus access transfer type codes */
+#define BA_TT_MOVE16    (0x08)
+
+/* bits for 68040 MMU status register (mmusr) */
+#define MMU_B_040   (0x0800)
+#define MMU_G_040   (0x0400)
+#define MMU_S_040   (0x0080)
+#define MMU_CM_040  (0x0060)
+#define MMU_M_040   (0x0010)
+#define MMU_WP_040  (0x0004)
+#define MMU_T_040   (0x0002)
+#define MMU_R_040   (0x0001)
+
+/* bits in the 68060 fault status long word (FSLW) */
+#define	MMU060_MA	(0x08000000)	/* misaligned */
+#define	MMU060_LK	(0x02000000)	/* locked transfer */
+#define	MMU060_RW	(0x01800000)	/* read/write */
+# define MMU060_RW_W	(0x00800000)	/* write */
+# define MMU060_RW_R	(0x01000000)	/* read */
+# define MMU060_RW_RMW	(0x01800000)	/* read/modify/write */
+# define MMU060_W	(0x00800000)	/* general write, includes rmw */
+#define	MMU060_SIZ	(0x00600000)	/* transfer size */
+#define	MMU060_TT	(0x00180000)	/* transfer type (TT) bits */
+#define	MMU060_TM	(0x00070000)	/* transfer modifier (TM) bits */
+#define	MMU060_IO	(0x00008000)	/* instruction or operand */
+#define	MMU060_PBE	(0x00004000)	/* push buffer bus error */
+#define	MMU060_SBE	(0x00002000)	/* store buffer bus error */
+#define	MMU060_PTA	(0x00001000)	/* pointer A fault */
+#define	MMU060_PTB	(0x00000800)	/* pointer B fault */
+#define	MMU060_IL	(0x00000400)	/* double indirect descr fault */
+#define	MMU060_PF	(0x00000200)	/* page fault (invalid descr) */
+#define	MMU060_SP	(0x00000100)	/* supervisor protection */
+#define	MMU060_WP	(0x00000080)	/* write protection */
+#define	MMU060_TWE	(0x00000040)	/* bus error on table search */
+#define	MMU060_RE	(0x00000020)	/* bus error on read */
+#define	MMU060_WE	(0x00000010)	/* bus error on write */
+#define	MMU060_TTR	(0x00000008)	/* error caused by TTR translation */
+#define	MMU060_BPE	(0x00000004)	/* branch prediction error */
+#define	MMU060_SEE	(0x00000001)	/* software emulated error */
+
+/* cases of missing or invalid descriptors */
+#define MMU060_DESC_ERR (MMU060_PTA | MMU060_PTB | \
+			 MMU060_IL  | MMU060_PF)
+/* bits that indicate real errors */
+#define MMU060_ERR_BITS (MMU060_PBE | MMU060_SBE | MMU060_DESC_ERR | MMU060_SP | \
+			 MMU060_WP  | MMU060_TWE | MMU060_RE       | MMU060_WE)
+
+/* structure for stack frames */
+
+struct frame {
+    struct pt_regs ptregs;
+    union {
+	    struct {
+		    unsigned long  iaddr;    /* instruction address */
+	    } fmt2;
+	    struct {
+		    unsigned long  effaddr;  /* effective address */
+	    } fmt3;
+	    struct {
+		    unsigned long  effaddr;  /* effective address */
+		    unsigned long  pc;	     /* pc of faulted instr */
+	    } fmt4;
+	    struct {
+		    unsigned long  effaddr;  /* effective address */
+		    unsigned short ssw;      /* special status word */
+		    unsigned short wb3s;     /* write back 3 status */
+		    unsigned short wb2s;     /* write back 2 status */
+		    unsigned short wb1s;     /* write back 1 status */
+		    unsigned long  faddr;    /* fault address */
+		    unsigned long  wb3a;     /* write back 3 address */
+		    unsigned long  wb3d;     /* write back 3 data */
+		    unsigned long  wb2a;     /* write back 2 address */
+		    unsigned long  wb2d;     /* write back 2 data */
+		    unsigned long  wb1a;     /* write back 1 address */
+		    unsigned long  wb1dpd0;  /* write back 1 data/push data 0*/
+		    unsigned long  pd1;      /* push data 1*/
+		    unsigned long  pd2;      /* push data 2*/
+		    unsigned long  pd3;      /* push data 3*/
+	    } fmt7;
+	    struct {
+		    unsigned long  iaddr;    /* instruction address */
+		    unsigned short int1[4];  /* internal registers */
+	    } fmt9;
+	    struct {
+		    unsigned short int1;
+		    unsigned short ssw;      /* special status word */
+		    unsigned short isc;      /* instruction stage c */
+		    unsigned short isb;      /* instruction stage b */
+		    unsigned long  daddr;    /* data cycle fault address */
+		    unsigned short int2[2];
+		    unsigned long  dobuf;    /* data cycle output buffer */
+		    unsigned short int3[2];
+	    } fmta;
+	    struct {
+		    unsigned short int1;
+		    unsigned short ssw;     /* special status word */
+		    unsigned short isc;     /* instruction stage c */
+		    unsigned short isb;     /* instruction stage b */
+		    unsigned long  daddr;   /* data cycle fault address */
+		    unsigned short int2[2];
+		    unsigned long  dobuf;   /* data cycle output buffer */
+		    unsigned short int3[4];
+		    unsigned long  baddr;   /* stage B address */
+		    unsigned short int4[2];
+		    unsigned long  dibuf;   /* data cycle input buffer */
+		    unsigned short int5[3];
+		    unsigned	   ver : 4; /* stack frame version # */
+		    unsigned	   int6:12;
+		    unsigned short int7[18];
+	    } fmtb;
+    } un;
+};
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _M68K_TRAPS_H */
diff --git a/arch/m68k/include/asm/traps_mm.h b/arch/m68k/include/asm/traps_mm.h
deleted file mode 100644
index 8caef25..0000000
--- a/arch/m68k/include/asm/traps_mm.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- *  linux/include/asm/traps.h
- *
- *  Copyright (C) 1993        Hamish Macdonald
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#ifndef _M68K_TRAPS_H
-#define _M68K_TRAPS_H
-
-#ifndef __ASSEMBLY__
-
-#include <linux/linkage.h>
-#include <asm/ptrace.h>
-
-typedef void (*e_vector)(void);
-
-asmlinkage void auto_inthandler(void);
-asmlinkage void user_inthandler(void);
-asmlinkage void bad_inthandler(void);
-
-extern e_vector vectors[];
-
-#endif
-
-#define VEC_RESETSP (0)
-#define VEC_RESETPC (1)
-#define VEC_BUSERR  (2)
-#define VEC_ADDRERR (3)
-#define VEC_ILLEGAL (4)
-#define VEC_ZERODIV (5)
-#define VEC_CHK     (6)
-#define VEC_TRAP    (7)
-#define VEC_PRIV    (8)
-#define VEC_TRACE   (9)
-#define VEC_LINE10  (10)
-#define VEC_LINE11  (11)
-#define VEC_RESV12  (12)
-#define VEC_COPROC  (13)
-#define VEC_FORMAT  (14)
-#define VEC_UNINT   (15)
-#define VEC_RESV16  (16)
-#define VEC_RESV17  (17)
-#define VEC_RESV18  (18)
-#define VEC_RESV19  (19)
-#define VEC_RESV20  (20)
-#define VEC_RESV21  (21)
-#define VEC_RESV22  (22)
-#define VEC_RESV23  (23)
-#define VEC_SPUR    (24)
-#define VEC_INT1    (25)
-#define VEC_INT2    (26)
-#define VEC_INT3    (27)
-#define VEC_INT4    (28)
-#define VEC_INT5    (29)
-#define VEC_INT6    (30)
-#define VEC_INT7    (31)
-#define VEC_SYS     (32)
-#define VEC_TRAP1   (33)
-#define VEC_TRAP2   (34)
-#define VEC_TRAP3   (35)
-#define VEC_TRAP4   (36)
-#define VEC_TRAP5   (37)
-#define VEC_TRAP6   (38)
-#define VEC_TRAP7   (39)
-#define VEC_TRAP8   (40)
-#define VEC_TRAP9   (41)
-#define VEC_TRAP10  (42)
-#define VEC_TRAP11  (43)
-#define VEC_TRAP12  (44)
-#define VEC_TRAP13  (45)
-#define VEC_TRAP14  (46)
-#define VEC_TRAP15  (47)
-#define VEC_FPBRUC  (48)
-#define VEC_FPIR    (49)
-#define VEC_FPDIVZ  (50)
-#define VEC_FPUNDER (51)
-#define VEC_FPOE    (52)
-#define VEC_FPOVER  (53)
-#define VEC_FPNAN   (54)
-#define VEC_FPUNSUP (55)
-#define VEC_MMUCFG  (56)
-#define VEC_MMUILL  (57)
-#define VEC_MMUACC  (58)
-#define VEC_RESV59  (59)
-#define	VEC_UNIMPEA (60)
-#define	VEC_UNIMPII (61)
-#define VEC_RESV62  (62)
-#define VEC_RESV63  (63)
-#define VEC_USER    (64)
-
-#define VECOFF(vec) ((vec)<<2)
-
-#ifndef __ASSEMBLY__
-
-/* Status register bits */
-#define PS_T  (0x8000)
-#define PS_S  (0x2000)
-#define PS_M  (0x1000)
-#define PS_C  (0x0001)
-
-/* bits for 68020/68030 special status word */
-
-#define FC    (0x8000)
-#define FB    (0x4000)
-#define RC    (0x2000)
-#define RB    (0x1000)
-#define DF    (0x0100)
-#define RM    (0x0080)
-#define RW    (0x0040)
-#define SZ    (0x0030)
-#define DFC   (0x0007)
-
-/* bits for 68030 MMU status register (mmusr,psr) */
-
-#define MMU_B	     (0x8000)    /* bus error */
-#define MMU_L	     (0x4000)    /* limit violation */
-#define MMU_S	     (0x2000)    /* supervisor violation */
-#define MMU_WP	     (0x0800)    /* write-protected */
-#define MMU_I	     (0x0400)    /* invalid descriptor */
-#define MMU_M	     (0x0200)    /* ATC entry modified */
-#define MMU_T	     (0x0040)    /* transparent translation */
-#define MMU_NUM      (0x0007)    /* number of levels traversed */
-
-
-/* bits for 68040 special status word */
-#define CP_040	(0x8000)
-#define CU_040	(0x4000)
-#define CT_040	(0x2000)
-#define CM_040	(0x1000)
-#define MA_040	(0x0800)
-#define ATC_040 (0x0400)
-#define LK_040	(0x0200)
-#define RW_040	(0x0100)
-#define SIZ_040 (0x0060)
-#define TT_040	(0x0018)
-#define TM_040	(0x0007)
-
-/* bits for 68040 write back status word */
-#define WBV_040   (0x80)
-#define WBSIZ_040 (0x60)
-#define WBBYT_040 (0x20)
-#define WBWRD_040 (0x40)
-#define WBLNG_040 (0x00)
-#define WBTT_040  (0x18)
-#define WBTM_040  (0x07)
-
-/* bus access size codes */
-#define BA_SIZE_BYTE    (0x20)
-#define BA_SIZE_WORD    (0x40)
-#define BA_SIZE_LONG    (0x00)
-#define BA_SIZE_LINE    (0x60)
-
-/* bus access transfer type codes */
-#define BA_TT_MOVE16    (0x08)
-
-/* bits for 68040 MMU status register (mmusr) */
-#define MMU_B_040   (0x0800)
-#define MMU_G_040   (0x0400)
-#define MMU_S_040   (0x0080)
-#define MMU_CM_040  (0x0060)
-#define MMU_M_040   (0x0010)
-#define MMU_WP_040  (0x0004)
-#define MMU_T_040   (0x0002)
-#define MMU_R_040   (0x0001)
-
-/* bits in the 68060 fault status long word (FSLW) */
-#define	MMU060_MA	(0x08000000)	/* misaligned */
-#define	MMU060_LK	(0x02000000)	/* locked transfer */
-#define	MMU060_RW	(0x01800000)	/* read/write */
-# define MMU060_RW_W	(0x00800000)	/* write */
-# define MMU060_RW_R	(0x01000000)	/* read */
-# define MMU060_RW_RMW	(0x01800000)	/* read/modify/write */
-# define MMU060_W	(0x00800000)	/* general write, includes rmw */
-#define	MMU060_SIZ	(0x00600000)	/* transfer size */
-#define	MMU060_TT	(0x00180000)	/* transfer type (TT) bits */
-#define	MMU060_TM	(0x00070000)	/* transfer modifier (TM) bits */
-#define	MMU060_IO	(0x00008000)	/* instruction or operand */
-#define	MMU060_PBE	(0x00004000)	/* push buffer bus error */
-#define	MMU060_SBE	(0x00002000)	/* store buffer bus error */
-#define	MMU060_PTA	(0x00001000)	/* pointer A fault */
-#define	MMU060_PTB	(0x00000800)	/* pointer B fault */
-#define	MMU060_IL	(0x00000400)	/* double indirect descr fault */
-#define	MMU060_PF	(0x00000200)	/* page fault (invalid descr) */
-#define	MMU060_SP	(0x00000100)	/* supervisor protection */
-#define	MMU060_WP	(0x00000080)	/* write protection */
-#define	MMU060_TWE	(0x00000040)	/* bus error on table search */
-#define	MMU060_RE	(0x00000020)	/* bus error on read */
-#define	MMU060_WE	(0x00000010)	/* bus error on write */
-#define	MMU060_TTR	(0x00000008)	/* error caused by TTR translation */
-#define	MMU060_BPE	(0x00000004)	/* branch prediction error */
-#define	MMU060_SEE	(0x00000001)	/* software emulated error */
-
-/* cases of missing or invalid descriptors */
-#define MMU060_DESC_ERR (MMU060_PTA | MMU060_PTB | \
-			 MMU060_IL  | MMU060_PF)
-/* bits that indicate real errors */
-#define MMU060_ERR_BITS (MMU060_PBE | MMU060_SBE | MMU060_DESC_ERR | MMU060_SP | \
-			 MMU060_WP  | MMU060_TWE | MMU060_RE       | MMU060_WE)
-
-/* structure for stack frames */
-
-struct frame {
-    struct pt_regs ptregs;
-    union {
-	    struct {
-		    unsigned long  iaddr;    /* instruction address */
-	    } fmt2;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-	    } fmt3;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-		    unsigned long  pc;	     /* pc of faulted instr */
-	    } fmt4;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-		    unsigned short ssw;      /* special status word */
-		    unsigned short wb3s;     /* write back 3 status */
-		    unsigned short wb2s;     /* write back 2 status */
-		    unsigned short wb1s;     /* write back 1 status */
-		    unsigned long  faddr;    /* fault address */
-		    unsigned long  wb3a;     /* write back 3 address */
-		    unsigned long  wb3d;     /* write back 3 data */
-		    unsigned long  wb2a;     /* write back 2 address */
-		    unsigned long  wb2d;     /* write back 2 data */
-		    unsigned long  wb1a;     /* write back 1 address */
-		    unsigned long  wb1dpd0;  /* write back 1 data/push data 0*/
-		    unsigned long  pd1;      /* push data 1*/
-		    unsigned long  pd2;      /* push data 2*/
-		    unsigned long  pd3;      /* push data 3*/
-	    } fmt7;
-	    struct {
-		    unsigned long  iaddr;    /* instruction address */
-		    unsigned short int1[4];  /* internal registers */
-	    } fmt9;
-	    struct {
-		    unsigned short int1;
-		    unsigned short ssw;      /* special status word */
-		    unsigned short isc;      /* instruction stage c */
-		    unsigned short isb;      /* instruction stage b */
-		    unsigned long  daddr;    /* data cycle fault address */
-		    unsigned short int2[2];
-		    unsigned long  dobuf;    /* data cycle output buffer */
-		    unsigned short int3[2];
-	    } fmta;
-	    struct {
-		    unsigned short int1;
-		    unsigned short ssw;     /* special status word */
-		    unsigned short isc;     /* instruction stage c */
-		    unsigned short isb;     /* instruction stage b */
-		    unsigned long  daddr;   /* data cycle fault address */
-		    unsigned short int2[2];
-		    unsigned long  dobuf;   /* data cycle output buffer */
-		    unsigned short int3[4];
-		    unsigned long  baddr;   /* stage B address */
-		    unsigned short int4[2];
-		    unsigned long  dibuf;   /* data cycle input buffer */
-		    unsigned short int5[3];
-		    unsigned	   ver : 4; /* stack frame version # */
-		    unsigned	   int6:12;
-		    unsigned short int7[18];
-	    } fmtb;
-    } un;
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _M68K_TRAPS_H */
diff --git a/arch/m68k/include/asm/traps_no.h b/arch/m68k/include/asm/traps_no.h
deleted file mode 100644
index d0671e5..0000000
--- a/arch/m68k/include/asm/traps_no.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- *  linux/include/asm/traps.h
- *
- *  Copyright (C) 1993        Hamish Macdonald
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#ifndef _M68KNOMMU_TRAPS_H
-#define _M68KNOMMU_TRAPS_H
-
-#ifndef __ASSEMBLY__
-
-typedef void (*e_vector)(void);
-
-extern e_vector vectors[];
-extern void init_vectors(void);
-extern void enable_vector(unsigned int irq);
-extern void disable_vector(unsigned int irq);
-extern void ack_vector(unsigned int irq);
-
-#endif
-
-#define VEC_BUSERR  (2)
-#define VEC_ADDRERR (3)
-#define VEC_ILLEGAL (4)
-#define VEC_ZERODIV (5)
-#define VEC_CHK     (6)
-#define VEC_TRAP    (7)
-#define VEC_PRIV    (8)
-#define VEC_TRACE   (9)
-#define VEC_LINE10  (10)
-#define VEC_LINE11  (11)
-#define VEC_RESV1   (12)
-#define VEC_COPROC  (13)
-#define VEC_FORMAT  (14)
-#define VEC_UNINT   (15)
-#define VEC_SPUR    (24)
-#define VEC_INT1    (25)
-#define VEC_INT2    (26)
-#define VEC_INT3    (27)
-#define VEC_INT4    (28)
-#define VEC_INT5    (29)
-#define VEC_INT6    (30)
-#define VEC_INT7    (31)
-#define VEC_SYS     (32)
-#define VEC_TRAP1   (33)
-#define VEC_TRAP2   (34)
-#define VEC_TRAP3   (35)
-#define VEC_TRAP4   (36)
-#define VEC_TRAP5   (37)
-#define VEC_TRAP6   (38)
-#define VEC_TRAP7   (39)
-#define VEC_TRAP8   (40)
-#define VEC_TRAP9   (41)
-#define VEC_TRAP10  (42)
-#define VEC_TRAP11  (43)
-#define VEC_TRAP12  (44)
-#define VEC_TRAP13  (45)
-#define VEC_TRAP14  (46)
-#define VEC_TRAP15  (47)
-#define VEC_FPBRUC  (48)
-#define VEC_FPIR    (49)
-#define VEC_FPDIVZ  (50)
-#define VEC_FPUNDER (51)
-#define VEC_FPOE    (52)
-#define VEC_FPOVER  (53)
-#define VEC_FPNAN   (54)
-#define VEC_FPUNSUP (55)
-#define	VEC_UNIMPEA (60)
-#define	VEC_UNIMPII (61)
-#define VEC_USER    (64)
-
-#define VECOFF(vec) ((vec)<<2)
-
-#ifndef __ASSEMBLY__
-
-/* Status register bits */
-#define PS_T  (0x8000)
-#define PS_S  (0x2000)
-#define PS_M  (0x1000)
-#define PS_C  (0x0001)
-
-/* structure for stack frames */
-
-struct frame {
-    struct pt_regs ptregs;
-    union {
-	    struct {
-		    unsigned long  iaddr;    /* instruction address */
-	    } fmt2;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-	    } fmt3;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-		    unsigned long  pc;	     /* pc of faulted instr */
-	    } fmt4;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-		    unsigned short ssw;      /* special status word */
-		    unsigned short wb3s;     /* write back 3 status */
-		    unsigned short wb2s;     /* write back 2 status */
-		    unsigned short wb1s;     /* write back 1 status */
-		    unsigned long  faddr;    /* fault address */
-		    unsigned long  wb3a;     /* write back 3 address */
-		    unsigned long  wb3d;     /* write back 3 data */
-		    unsigned long  wb2a;     /* write back 2 address */
-		    unsigned long  wb2d;     /* write back 2 data */
-		    unsigned long  wb1a;     /* write back 1 address */
-		    unsigned long  wb1dpd0;  /* write back 1 data/push data 0*/
-		    unsigned long  pd1;      /* push data 1*/
-		    unsigned long  pd2;      /* push data 2*/
-		    unsigned long  pd3;      /* push data 3*/
-	    } fmt7;
-	    struct {
-		    unsigned long  iaddr;    /* instruction address */
-		    unsigned short int1[4];  /* internal registers */
-	    } fmt9;
-	    struct {
-		    unsigned short int1;
-		    unsigned short ssw;      /* special status word */
-		    unsigned short isc;      /* instruction stage c */
-		    unsigned short isb;      /* instruction stage b */
-		    unsigned long  daddr;    /* data cycle fault address */
-		    unsigned short int2[2];
-		    unsigned long  dobuf;    /* data cycle output buffer */
-		    unsigned short int3[2];
-	    } fmta;
-	    struct {
-		    unsigned short int1;
-		    unsigned short ssw;     /* special status word */
-		    unsigned short isc;     /* instruction stage c */
-		    unsigned short isb;     /* instruction stage b */
-		    unsigned long  daddr;   /* data cycle fault address */
-		    unsigned short int2[2];
-		    unsigned long  dobuf;   /* data cycle output buffer */
-		    unsigned short int3[4];
-		    unsigned long  baddr;   /* stage B address */
-		    unsigned short int4[2];
-		    unsigned long  dibuf;   /* data cycle input buffer */
-		    unsigned short int5[3];
-		    unsigned	   ver : 4; /* stack frame version # */
-		    unsigned	   int6:12;
-		    unsigned short int7[18];
-	    } fmtb;
-    } un;
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _M68KNOMMU_TRAPS_H */
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 303730a..b3963ab 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -359,12 +359,6 @@
 		isa_type = ISA_TYPE_Q40;
 		isa_sex = 0;
 	}
-#ifdef CONFIG_GG2
-	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)) {
-		isa_type = ISA_TYPE_GG2;
-		isa_sex = 0;
-	}
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
 	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
 		isa_type = ISA_TYPE_AG;
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 2f431ec..3db2e7f 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -12,7 +12,6 @@
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
@@ -377,7 +376,6 @@
 	struct vm_area_struct *vma;
 	int ret = -EINVAL;
 
-	lock_kernel();
 	if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
 	    cache & ~FLUSH_CACHE_BOTH)
 		goto out;
@@ -446,7 +444,6 @@
 	    }
 	}
 out:
-	unlock_kernel();
 	return ret;
 }
 
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 4926b38..06438da 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -42,9 +42,7 @@
 static irqreturn_t timer_interrupt(int irq, void *dummy)
 {
 	do_timer(1);
-#ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
-#endif
 	profile_tick(CPU_PROFILING);
 
 #ifdef CONFIG_HEARTBEAT
diff --git a/arch/m68k/mac/macboing.c b/arch/m68k/mac/macboing.c
index 8f06408..05285d0 100644
--- a/arch/m68k/mac/macboing.c
+++ b/arch/m68k/mac/macboing.c
@@ -162,7 +162,7 @@
 void mac_mksound( unsigned int freq, unsigned int length )
 {
 	__u32 cfreq = ( freq << 5 ) / 468;
-	__u32 flags;
+	unsigned long flags;
 	int i;
 
 	if ( mac_special_bell == NULL )
@@ -224,7 +224,7 @@
  */
 static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsigned int volume )
 {
-	__u32 flags;
+	unsigned long flags;
 
 	/* if the bell is already ringing, ring longer */
 	if ( mac_bell_duration > 0 )
@@ -271,7 +271,7 @@
 static void mac_quadra_ring_bell( unsigned long ignored )
 {
 	int	i, count = mac_asc_samplespersec / HZ;
-	__u32 flags;
+	unsigned long flags;
 
 	/*
 	 * we neither want a sound buffer overflow nor underflow, so we need to match
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
index 11ac6f6..39c79eb 100644
--- a/arch/m68k/mvme16x/rtc.c
+++ b/arch/m68k/mvme16x/rtc.c
@@ -144,6 +144,7 @@
 	.unlocked_ioctl	= rtc_ioctl,
 	.open		= rtc_open,
 	.release	= rtc_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice rtc_dev=
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index ad90393..2d9e21bd 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -67,9 +67,7 @@
 	intersil_clear();
 #endif
         do_timer(1);
-#ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
-#endif
         if (!(kstat_cpu(0).irqs[irq] % 20))
                 sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
 	return IRQ_HANDLED;
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
index 9a8876f..2433502 100644
--- a/arch/m68knommu/kernel/asm-offsets.c
+++ b/arch/m68knommu/kernel/asm-offsets.c
@@ -74,8 +74,6 @@
 
 	DEFINE(PT_PTRACED, PT_PTRACED);
 
-	DEFINE(THREAD_SIZE, THREAD_SIZE);
-
 	/* Offsets in thread_info structure */
 	DEFINE(TI_TASK, offsetof(struct thread_info, task));
 	DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index a90acf5..7089dd9 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -50,9 +50,8 @@
 
 	write_sequnlock(&xtime_lock);
 
-#ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
-#endif
+
 	return(IRQ_HANDLED);
 }
 #endif
diff --git a/arch/m68knommu/platform/coldfire/entry.S b/arch/m68knommu/platform/coldfire/entry.S
index dd7d591..cd79d7e 100644
--- a/arch/m68knommu/platform/coldfire/entry.S
+++ b/arch/m68knommu/platform/coldfire/entry.S
@@ -112,7 +112,7 @@
 	andl	#-THREAD_SIZE,%d1	/* at base of kernel stack */
 	movel	%d1,%a0
 	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
-	andl	#_TIF_NEED_RESCHED,%d1
+	andl	#(1<<TIF_NEED_RESCHED),%d1
 	jeq	Lkernel_return
 
 	movel	%a0@(TI_PREEMPTCOUNT),%d1
@@ -136,7 +136,7 @@
 	andl	#-THREAD_SIZE,%d1	/* at base of kernel stack */
 	movel	%d1,%a0
 	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
-	andl	#_TIF_WORK_MASK,%d1
+	andl	#0xefff,%d1
 	jne	Lwork_to_do		/* still work to do */
 
 Lreturn:
diff --git a/arch/m68knommu/platform/coldfire/head.S b/arch/m68knommu/platform/coldfire/head.S
index 4b91aa2..0b2d7c7 100644
--- a/arch/m68knommu/platform/coldfire/head.S
+++ b/arch/m68knommu/platform/coldfire/head.S
@@ -15,6 +15,7 @@
 #include <asm/coldfire.h>
 #include <asm/mcfcache.h>
 #include <asm/mcfsim.h>
+#include <asm/thread_info.h>
 
 /*****************************************************************************/
 
diff --git a/arch/microblaze/include/asm/irqflags.h b/arch/microblaze/include/asm/irqflags.h
index 2c38c6d..5fd3190 100644
--- a/arch/microblaze/include/asm/irqflags.h
+++ b/arch/microblaze/include/asm/irqflags.h
@@ -9,103 +9,114 @@
 #ifndef _ASM_MICROBLAZE_IRQFLAGS_H
 #define _ASM_MICROBLAZE_IRQFLAGS_H
 
-#include <linux/irqflags.h>
+#include <linux/types.h>
 #include <asm/registers.h>
 
-# if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+#ifdef CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
 
-# define raw_local_irq_save(flags)			\
-	do {						\
-		asm volatile ("	msrclr %0, %1;		\
-				nop;"			\
-				: "=r"(flags)		\
-				: "i"(MSR_IE)		\
-				: "memory");		\
-	} while (0)
-
-# define raw_local_irq_disable()			\
-	do {						\
-		asm volatile ("	msrclr r0, %0;		\
-				nop;"			\
-				:			\
-				: "i"(MSR_IE)		\
-				: "memory");		\
-	} while (0)
-
-# define raw_local_irq_enable()				\
-	do {						\
-		asm volatile ("	msrset	r0, %0;		\
-				nop;"			\
-				:			\
-				: "i"(MSR_IE)		\
-				: "memory");		\
-	} while (0)
-
-# else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */
-
-# define raw_local_irq_save(flags)				\
-	do {							\
-		register unsigned tmp;				\
-		asm volatile ("	mfs	%0, rmsr;		\
-				nop;				\
-				andi	%1, %0, %2;		\
-				mts	rmsr, %1;		\
-				nop;"				\
-				: "=r"(flags), "=r" (tmp)	\
-				: "i"(~MSR_IE)			\
-				: "memory");			\
-	} while (0)
-
-# define raw_local_irq_disable()				\
-	do {							\
-		register unsigned tmp;				\
-		asm volatile ("	mfs	%0, rmsr;		\
-				nop;				\
-				andi	%0, %0, %1;		\
-				mts	rmsr, %0;		\
-				nop;"			\
-				: "=r"(tmp)			\
-				: "i"(~MSR_IE)			\
-				: "memory");			\
-	} while (0)
-
-# define raw_local_irq_enable()					\
-	do {							\
-		register unsigned tmp;				\
-		asm volatile ("	mfs	%0, rmsr;		\
-				nop;				\
-				ori	%0, %0, %1;		\
-				mts	rmsr, %0;		\
-				nop;"				\
-				: "=r"(tmp)			\
-				: "i"(MSR_IE)			\
-				: "memory");			\
-	} while (0)
-
-# endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
-
-#define raw_local_irq_restore(flags)				\
-	do {							\
-		asm volatile ("	mts	rmsr, %0;		\
-				nop;"				\
-				:				\
-				: "r"(flags)			\
-				: "memory");			\
-	} while (0)
-
-static inline unsigned long get_msr(void)
+static inline unsigned long arch_local_irq_save(void)
 {
 	unsigned long flags;
-	asm volatile ("	mfs	%0, rmsr;	\
-			nop;"			\
-			: "=r"(flags)		\
-			:			\
-			: "memory");		\
+	asm volatile("	msrclr %0, %1	\n"
+		     "	nop		\n"
+		     : "=r"(flags)
+		     : "i"(MSR_IE)
+		     : "memory");
 	return flags;
 }
 
-#define raw_local_save_flags(flags)	((flags) = get_msr())
-#define raw_irqs_disabled()		((get_msr() & MSR_IE) == 0)
-#define raw_irqs_disabled_flags(flags)	((flags & MSR_IE) == 0)
+static inline void arch_local_irq_disable(void)
+{
+	/* this uses r0 without declaring it - is that correct? */
+	asm volatile("	msrclr r0, %0	\n"
+		     "	nop		\n"
+		     :
+		     : "i"(MSR_IE)
+		     : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	/* this uses r0 without declaring it - is that correct? */
+	asm volatile("	msrset	r0, %0	\n"
+		     "	nop		\n"
+		     :
+		     : "i"(MSR_IE)
+		     : "memory");
+}
+
+#else /* !CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags, tmp;
+	asm volatile ("	mfs	%0, rmsr	\n"
+		      "	nop			\n"
+		      "	andi	%1, %0, %2	\n"
+		      "	mts	rmsr, %1	\n"
+		      "	nop			\n"
+		      : "=r"(flags), "=r"(tmp)
+		      : "i"(~MSR_IE)
+		      : "memory");
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	unsigned long tmp;
+	asm volatile("	mfs	%0, rmsr	\n"
+		     "	nop			\n"
+		     "	andi	%0, %0, %1	\n"
+		     "	mts	rmsr, %0	\n"
+		     "	nop			\n"
+		     : "=r"(tmp)
+		     : "i"(~MSR_IE)
+		     : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	unsigned long tmp;
+	asm volatile("	mfs	%0, rmsr	\n"
+		     "	nop			\n"
+		     "	ori	%0, %0, %1	\n"
+		     "	mts	rmsr, %0	\n"
+		     "	nop			\n"
+		     : "=r"(tmp)
+		     : "i"(MSR_IE)
+		     : "memory");
+}
+
+#endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile("	mfs	%0, rmsr	\n"
+		     "	nop			\n"
+		     : "=r"(flags)
+		     :
+		     : "memory");
+	return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile("	mts	rmsr, %0	\n"
+		     "	nop			\n"
+		     :
+		     : "r"(flags)
+		     : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags & MSR_IE) == 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
 
 #endif /* _ASM_MICROBLAZE_IRQFLAGS_H */
diff --git a/arch/microblaze/include/asm/memblock.h b/arch/microblaze/include/asm/memblock.h
index f9c2fa3..20a8e25 100644
--- a/arch/microblaze/include/asm/memblock.h
+++ b/arch/microblaze/include/asm/memblock.h
@@ -9,9 +9,6 @@
 #ifndef _ASM_MICROBLAZE_MEMBLOCK_H
 #define _ASM_MICROBLAZE_MEMBLOCK_H
 
-/* MEMBLOCK limit is OFF */
-#define MEMBLOCK_REAL_LIMIT	0xFFFFFFFF
-
 #endif /* _ASM_MICROBLAZE_MEMBLOCK_H */
 
 
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c
index 65eb004..c843786 100644
--- a/arch/microblaze/mm/init.c
+++ b/arch/microblaze/mm/init.c
@@ -70,16 +70,16 @@
 
 void __init setup_memory(void)
 {
-	int i;
 	unsigned long map_size;
+	struct memblock_region *reg;
+
 #ifndef CONFIG_MMU
 	u32 kernel_align_start, kernel_align_size;
 
 	/* Find main memory where is the kernel */
-	for (i = 0; i < memblock.memory.cnt; i++) {
-		memory_start = (u32) memblock.memory.region[i].base;
-		memory_end = (u32) memblock.memory.region[i].base
-				+ (u32) memblock.memory.region[i].size;
+	for_each_memblock(memory, reg) {
+		memory_start = (u32)reg->base;
+		memory_end = (u32) reg->base + reg->size;
 		if ((memory_start <= (u32)_text) &&
 					((u32)_text <= memory_end)) {
 			memory_size = memory_end - memory_start;
@@ -142,12 +142,10 @@
 	free_bootmem(memory_start, memory_size);
 
 	/* reserve allocate blocks */
-	for (i = 0; i < memblock.reserved.cnt; i++) {
-		pr_debug("reserved %d - 0x%08x-0x%08x\n", i,
-			(u32) memblock.reserved.region[i].base,
-			(u32) memblock_size_bytes(&memblock.reserved, i));
-		reserve_bootmem(memblock.reserved.region[i].base,
-			memblock_size_bytes(&memblock.reserved, i) - 1, BOOTMEM_DEFAULT);
+	for_each_memblock(reserved, reg) {
+		pr_debug("reserved - 0x%08x-0x%08x\n",
+			 (u32) reg->base, (u32) reg->size);
+		reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
 	}
 #ifdef CONFIG_MMU
 	init_bootmem_done = 1;
@@ -230,7 +228,7 @@
 		if (maxmem && memory_size > maxmem) {
 			memory_size = maxmem;
 			memory_end = memory_start + memory_size;
-			memblock.memory.region[0].size = memory_size;
+			memblock.memory.regions[0].size = memory_size;
 		}
 	}
 }
@@ -273,14 +271,14 @@
 		machine_restart(NULL);
 	}
 
-	if ((u32) memblock.memory.region[0].size < 0x1000000) {
+	if ((u32) memblock.memory.regions[0].size < 0x1000000) {
 		printk(KERN_EMERG "Memory must be greater than 16MB\n");
 		machine_restart(NULL);
 	}
 	/* Find main memory where the kernel is */
-	memory_start = (u32) memblock.memory.region[0].base;
-	memory_end = (u32) memblock.memory.region[0].base +
-				(u32) memblock.memory.region[0].size;
+	memory_start = (u32) memblock.memory.regions[0].base;
+	memory_end = (u32) memblock.memory.regions[0].base +
+				(u32) memblock.memory.regions[0].size;
 	memory_size = memory_end - memory_start;
 
 	mm_cmdline_setup(); /* FIXME parse args from command line - not used */
diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild
index e322d65..7dd65cf 100644
--- a/arch/mips/Kbuild
+++ b/arch/mips/Kbuild
@@ -7,6 +7,10 @@
 include arch/mips/Kbuild.platforms
 obj-y := $(platform-y)
 
+# make clean traverses $(obj-) without having included .config, so
+# everything ends up here
+obj- := $(platform-)
+
 # mips object files
 # The object files are linked as core-y files would be linked
 
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 3ad59dd..4c9f402 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -13,6 +13,7 @@
 	select HAVE_KPROBES
 	select HAVE_KRETPROBES
 	select RTC_LIB if !MACH_LOONGSON
+	select GENERIC_ATOMIC64 if !64BIT
 
 mainmenu "Linux/MIPS Kernel Configuration"
 
@@ -880,11 +881,15 @@
 config GENERIC_ISA_DMA
 	bool
 	select ZONE_DMA if GENERIC_ISA_DMA_SUPPORT_BROKEN=n
+	select ISA_DMA_API
 
 config GENERIC_ISA_DMA_SUPPORT_BROKEN
 	bool
 	select GENERIC_ISA_DMA
 
+config ISA_DMA_API
+	bool
+
 config GENERIC_GPIO
 	bool
 
@@ -1646,8 +1651,16 @@
 	select SYS_SUPPORTS_SMP
 	select SMP_UP
 	help
-	  This is a kernel model which is also known a VSMP or lately
-	  has been marketesed into SMVP.
+	  This is a kernel model which is known a VSMP but lately has been
+	  marketesed into SMVP.
+	  Virtual SMP uses the processor's VPEs  to implement virtual
+	  processors. In currently available configuration of the 34K processor
+	  this allows for a dual processor. Both processors will share the same
+	  primary caches; each will obtain the half of the TLB for it's own
+	  exclusive use. For a layman this model can be described as similar to
+	  what Intel calls Hyperthreading.
+
+	  For further information see http://www.linux-mips.org/wiki/34K#VSMP
 
 config MIPS_MT_SMTC
 	bool "SMTC: Use all TCs on all VPEs for SMP"
@@ -1664,6 +1677,14 @@
 	help
 	  This is a kernel model which is known a SMTC or lately has been
 	  marketesed into SMVP.
+	  is presenting the available TC's of the core as processors to Linux.
+	  On currently available 34K processors this means a Linux system will
+	  see up to 5 processors. The implementation of the SMTC kernel differs
+	  significantly from VSMP and cannot efficiently coexist in the same
+	  kernel binary so the choice between VSMP and SMTC is a compile time
+	  decision.
+
+	  For further information see http://www.linux-mips.org/wiki/34K#SMTC
 
 endchoice
 
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c
index 1dc55ee..3691630 100644
--- a/arch/mips/alchemy/common/platform.c
+++ b/arch/mips/alchemy/common/platform.c
@@ -24,6 +24,33 @@
 
 #include <prom.h>
 
+static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
+			    unsigned int old_state)
+{
+	switch (state) {
+	case 0:
+		if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) {
+			/* power-on sequence as suggested in the databooks */
+			__raw_writel(0, port->membase + UART_MOD_CNTRL);
+			wmb();
+			__raw_writel(1, port->membase + UART_MOD_CNTRL);
+			wmb();
+		}
+		__raw_writel(3, port->membase + UART_MOD_CNTRL); /* full on */
+		wmb();
+		serial8250_do_pm(port, state, old_state);
+		break;
+	case 3:		/* power off */
+		serial8250_do_pm(port, state, old_state);
+		__raw_writel(0, port->membase + UART_MOD_CNTRL);
+		wmb();
+		break;
+	default:
+		serial8250_do_pm(port, state, old_state);
+		break;
+	}
+}
+
 #define PORT(_base, _irq)					\
 	{							\
 		.mapbase	= _base,			\
@@ -33,6 +60,7 @@
 		.flags		= UPF_SKIP_TEST | UPF_IOREMAP |	\
 				  UPF_FIXED_TYPE,		\
 		.type		= PORT_16550A,			\
+		.pm		= alchemy_8250_pm,		\
 	}
 
 static struct plat_serial8250_port au1x00_uart_data[] = {
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c
index 5ef06a1..e5916a5 100644
--- a/arch/mips/alchemy/common/power.c
+++ b/arch/mips/alchemy/common/power.c
@@ -49,11 +49,6 @@
  * We only have to save/restore registers that aren't otherwise
  * done as part of a driver pm_* function.
  */
-static unsigned int sleep_uart0_inten;
-static unsigned int sleep_uart0_fifoctl;
-static unsigned int sleep_uart0_linectl;
-static unsigned int sleep_uart0_clkdiv;
-static unsigned int sleep_uart0_enable;
 static unsigned int sleep_usb[2];
 static unsigned int sleep_sys_clocks[5];
 static unsigned int sleep_sys_pinfunc;
@@ -62,22 +57,6 @@
 
 static void save_core_regs(void)
 {
-	extern void save_au1xxx_intctl(void);
-	extern void pm_eth0_shutdown(void);
-
-	/*
-	 * Do the serial ports.....these really should be a pm_*
-	 * registered function by the driver......but of course the
-	 * standard serial driver doesn't understand our Au1xxx
-	 * unique registers.
-	 */
-	sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER);
-	sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR);
-	sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
-	sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
-	sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
-	au_sync();
-
 #ifndef CONFIG_SOC_AU1200
 	/* Shutdown USB host/device. */
 	sleep_usb[0] = au_readl(USB_HOST_CONFIG);
@@ -175,20 +154,6 @@
 	au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
 	au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
 	au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
-
-	/*
-	 * Enable the UART if it was enabled before sleep.
-	 * I guess I should define module control bits........
-	 */
-	if (sleep_uart0_enable & 0x02) {
-		au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync();
-		au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync();
-		au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync();
-		au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync();
-		au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync();
-		au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync();
-		au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync();
-	}
 }
 
 void au_sleep(void)
diff --git a/arch/mips/alchemy/common/prom.c b/arch/mips/alchemy/common/prom.c
index c29511b..5340210 100644
--- a/arch/mips/alchemy/common/prom.c
+++ b/arch/mips/alchemy/common/prom.c
@@ -43,7 +43,7 @@
 char **prom_argv;
 char **prom_envp;
 
-void prom_init_cmdline(void)
+void __init prom_init_cmdline(void)
 {
 	int i;
 
@@ -104,7 +104,7 @@
 	}
 }
 
-int prom_get_ethernet_addr(char *ethernet_addr)
+int __init prom_get_ethernet_addr(char *ethernet_addr)
 {
 	char *ethaddr_str;
 
@@ -123,7 +123,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(prom_get_ethernet_addr);
 
 void __init prom_free_prom_memory(void)
 {
diff --git a/arch/mips/alchemy/devboards/bcsr.c b/arch/mips/alchemy/devboards/bcsr.c
index 3bc4fd2..c52af88 100644
--- a/arch/mips/alchemy/devboards/bcsr.c
+++ b/arch/mips/alchemy/devboards/bcsr.c
@@ -10,6 +10,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/irq.h>
 #include <asm/addrspace.h>
 #include <asm/io.h>
 #include <asm/mach-db1x00/bcsr.h>
diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c
index c781556..4ec2642 100644
--- a/arch/mips/ar7/irq.c
+++ b/arch/mips/ar7/irq.c
@@ -19,6 +19,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c
index a0c5cd1..3be87f2 100644
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <bcm63xx_cpu.h>
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index ed9bb70..5042d51 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -59,7 +59,7 @@
 hostprogs-y := calc_vmlinuz_load_addr
 
 VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \
-		$(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS))
+		$(obj)/vmlinux.bin $(VMLINUX_LOAD_ADDRESS))
 
 vmlinuzobjs-y += $(obj)/piggy.o
 
@@ -105,4 +105,4 @@
 vmlinuz.srec: vmlinuz
 	$(call cmd,objcopy)
 
-clean-files := $(objtree)/vmlinuz.*
+clean-files := $(objtree)/vmlinuz $(objtree)/vmlinuz.{32,ecoff,bin,srec}
diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig
index 094c17e..47323ca 100644
--- a/arch/mips/cavium-octeon/Kconfig
+++ b/arch/mips/cavium-octeon/Kconfig
@@ -83,3 +83,7 @@
 	def_bool y
 	select SPARSEMEM_STATIC
 	depends on CPU_CAVIUM_OCTEON
+
+config CAVIUM_OCTEON_HELPER
+	def_bool y
+	depends on OCTEON_ETHERNET || PCI
diff --git a/arch/mips/cavium-octeon/cpu.c b/arch/mips/cavium-octeon/cpu.c
index c664c8c..a5b4279 100644
--- a/arch/mips/cavium-octeon/cpu.c
+++ b/arch/mips/cavium-octeon/cpu.c
@@ -41,7 +41,7 @@
 	return NOTIFY_OK;		/* Let default notifier send signals */
 }
 
-static int cnmips_cu2_setup(void)
+static int __init cnmips_cu2_setup(void)
 {
 	return cu2_notifier(cnmips_cu2_call, 0);
 }
diff --git a/arch/mips/cavium-octeon/executive/Makefile b/arch/mips/cavium-octeon/executive/Makefile
index 2fd66db..7f41c5b 100644
--- a/arch/mips/cavium-octeon/executive/Makefile
+++ b/arch/mips/cavium-octeon/executive/Makefile
@@ -11,4 +11,4 @@
 
 obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o
 
-obj-$(CONFIG_PCI) += cvmx-helper-errata.o cvmx-helper-jtag.o
+obj-$(CONFIG_CAVIUM_OCTEON_HELPER) += cvmx-helper-errata.o cvmx-helper-jtag.o
diff --git a/arch/mips/cavium-octeon/serial.c b/arch/mips/cavium-octeon/serial.c
index 638adab..12dbf53 100644
--- a/arch/mips/cavium-octeon/serial.c
+++ b/arch/mips/cavium-octeon/serial.c
@@ -13,6 +13,7 @@
 #include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/tty.h>
+#include <linux/irq.h>
 
 #include <asm/time.h>
 
diff --git a/arch/mips/dec/Platform b/arch/mips/dec/Platform
index 3adbcbd..cf55a6f 100644
--- a/arch/mips/dec/Platform
+++ b/arch/mips/dec/Platform
@@ -1,7 +1,7 @@
 #
 # DECstation family
 #
-platform-$(CONFIG_MACH_DECSTATION)	= dec/
+platform-$(CONFIG_MACH_DECSTATION)	+= dec/
 cflags-$(CONFIG_MACH_DECSTATION)	+= \
 			-I$(srctree)/arch/mips/include/asm/mach-dec
 libs-$(CONFIG_MACH_DECSTATION)		+= arch/mips/dec/prom/
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index bd5431e..fa45e92 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/pm.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index c63c56b..47d87da 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -782,6 +782,10 @@
  */
 #define atomic64_add_negative(i, v) (atomic64_add_return(i, (v)) < 0)
 
+#else /* !CONFIG_64BIT */
+
+#include <asm-generic/atomic64.h>
+
 #endif /* CONFIG_64BIT */
 
 /*
diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h
index 2cb2f0c..3532e2c 100644
--- a/arch/mips/include/asm/cop2.h
+++ b/arch/mips/include/asm/cop2.h
@@ -24,7 +24,7 @@
 
 #define cu2_notifier(fn, pri)						\
 ({									\
-	static struct notifier_block fn##_nb __cpuinitdata = {		\
+	static struct notifier_block fn##_nb = {			\
 		.notifier_call = fn,					\
 		.priority = pri						\
 	};								\
diff --git a/arch/mips/include/asm/fcntl.h b/arch/mips/include/asm/fcntl.h
index e482fe9..75edded 100644
--- a/arch/mips/include/asm/fcntl.h
+++ b/arch/mips/include/asm/fcntl.h
@@ -56,6 +56,7 @@
  */
 
 #ifdef CONFIG_32BIT
+#include <linux/types.h>
 
 struct flock {
 	short	l_type;
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index 9b9436a..86548da 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -321,6 +321,7 @@
  */
 struct gic_intr_map {
 	unsigned int cpunum;	/* Directed to this CPU */
+#define GIC_UNUSED		0xdead			/* Dummy data */
 	unsigned int pin;	/* Directed to this Pin */
 	unsigned int polarity;	/* Polarity : +/-	*/
 	unsigned int trigtype;	/* Trigger  : Edge/Levl */
diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h
index 701ec0b..9ef3b0d 100644
--- a/arch/mips/include/asm/irqflags.h
+++ b/arch/mips/include/asm/irqflags.h
@@ -17,7 +17,7 @@
 #include <asm/hazards.h>
 
 __asm__(
-	"	.macro	raw_local_irq_enable				\n"
+	"	.macro	arch_local_irq_enable				\n"
 	"	.set	push						\n"
 	"	.set	reorder						\n"
 	"	.set	noat						\n"
@@ -40,7 +40,7 @@
 
 extern void smtc_ipi_replay(void);
 
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
 	/*
@@ -50,7 +50,7 @@
 	smtc_ipi_replay();
 #endif
 	__asm__ __volatile__(
-		"raw_local_irq_enable"
+		"arch_local_irq_enable"
 		: /* no outputs */
 		: /* no inputs */
 		: "memory");
@@ -76,7 +76,7 @@
  * Workaround: mask EXL bit of the result or place a nop before mfc0.
  */
 __asm__(
-	"	.macro	raw_local_irq_disable\n"
+	"	.macro	arch_local_irq_disable\n"
 	"	.set	push						\n"
 	"	.set	noat						\n"
 #ifdef CONFIG_MIPS_MT_SMTC
@@ -97,17 +97,17 @@
 	"	.set	pop						\n"
 	"	.endm							\n");
 
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
 {
 	__asm__ __volatile__(
-		"raw_local_irq_disable"
+		"arch_local_irq_disable"
 		: /* no outputs */
 		: /* no inputs */
 		: "memory");
 }
 
 __asm__(
-	"	.macro	raw_local_save_flags flags			\n"
+	"	.macro	arch_local_save_flags flags			\n"
 	"	.set	push						\n"
 	"	.set	reorder						\n"
 #ifdef CONFIG_MIPS_MT_SMTC
@@ -118,13 +118,15 @@
 	"	.set	pop						\n"
 	"	.endm							\n");
 
-#define raw_local_save_flags(x)						\
-__asm__ __volatile__(							\
-	"raw_local_save_flags %0"					\
-	: "=r" (x))
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile("arch_local_save_flags %0" : "=r" (flags));
+	return flags;
+}
 
 __asm__(
-	"	.macro	raw_local_irq_save result			\n"
+	"	.macro	arch_local_irq_save result			\n"
 	"	.set	push						\n"
 	"	.set	reorder						\n"
 	"	.set	noat						\n"
@@ -148,15 +150,18 @@
 	"	.set	pop						\n"
 	"	.endm							\n");
 
-#define raw_local_irq_save(x)						\
-__asm__ __volatile__(							\
-	"raw_local_irq_save\t%0"					\
-	: "=r" (x)							\
-	: /* no inputs */						\
-	: "memory")
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+	asm volatile("arch_local_irq_save\t%0"
+		     : "=r" (flags)
+		     : /* no inputs */
+		     : "memory");
+	return flags;
+}
 
 __asm__(
-	"	.macro	raw_local_irq_restore flags			\n"
+	"	.macro	arch_local_irq_restore flags			\n"
 	"	.set	push						\n"
 	"	.set	noreorder					\n"
 	"	.set	noat						\n"
@@ -196,7 +201,7 @@
 	"	.endm							\n");
 
 
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
 {
 	unsigned long __tmp1;
 
@@ -211,24 +216,24 @@
 #endif
 
 	__asm__ __volatile__(
-		"raw_local_irq_restore\t%0"
+		"arch_local_irq_restore\t%0"
 		: "=r" (__tmp1)
 		: "0" (flags)
 		: "memory");
 }
 
-static inline void __raw_local_irq_restore(unsigned long flags)
+static inline void __arch_local_irq_restore(unsigned long flags)
 {
 	unsigned long __tmp1;
 
 	__asm__ __volatile__(
-		"raw_local_irq_restore\t%0"
+		"arch_local_irq_restore\t%0"
 		: "=r" (__tmp1)
 		: "0" (flags)
 		: "memory");
 }
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
 	/*
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index cb6985f..1e29b9d 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -13,6 +13,7 @@
 
 #include <linux/io.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 /* loongson internal northbridge initialization */
 extern void bonito_irq_init(void);
diff --git a/arch/mips/include/asm/mach-tx49xx/kmalloc.h b/arch/mips/include/asm/mach-tx49xx/kmalloc.h
index b74caf6..ff9a8b86 100644
--- a/arch/mips/include/asm/mach-tx49xx/kmalloc.h
+++ b/arch/mips/include/asm/mach-tx49xx/kmalloc.h
@@ -1,6 +1,6 @@
 #ifndef __ASM_MACH_TX49XX_KMALLOC_H
 #define __ASM_MACH_TX49XX_KMALLOC_H
 
-#define ARCH_KMALLOC_MINALIGN	L1_CACHE_BYTES
+#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
 
 #endif /* __ASM_MACH_TX49XX_KMALLOC_H */
diff --git a/arch/mips/include/asm/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h
index cea872f..d11aa02 100644
--- a/arch/mips/include/asm/mips-boards/maltaint.h
+++ b/arch/mips/include/asm/mips-boards/maltaint.h
@@ -88,9 +88,6 @@
 
 #define GIC_EXT_INTR(x)		x
 
-/* Dummy data */
-#define X			0xdead
-
 /* External Interrupts used for IPI */
 #define GIC_IPI_EXT_INTR_RESCHED_VPE0	16
 #define GIC_IPI_EXT_INTR_CALLFNC_VPE0	17
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index a16beaf..e59cd1a 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -150,6 +150,20 @@
     ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
 #endif
 #define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
+
+/*
+ * RELOC_HIDE was originally added by 6007b903dfe5f1d13e0c711ac2894bdd4a61b1ad
+ * (lmo) rsp. 8431fd094d625b94d364fe393076ccef88e6ce18 (kernel.org).  The
+ * discussion can be found in lkml posting
+ * <a2ebde260608230500o3407b108hc03debb9da6e62c@mail.gmail.com> which is
+ * archived at http://lists.linuxcoding.com/kernel/2006-q3/msg17360.html
+ *
+ * It is unclear if the misscompilations mentioned in
+ * http://lkml.org/lkml/2010/8/8/138 also affect MIPS so we keep this one
+ * until GCC 3.x has been retired before we can apply
+ * https://patchwork.linux-mips.org/patch/1541/
+ */
+
 #define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x), 0))
 
 #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
diff --git a/arch/mips/include/asm/siginfo.h b/arch/mips/include/asm/siginfo.h
index 96e28f1..1ca64b4 100644
--- a/arch/mips/include/asm/siginfo.h
+++ b/arch/mips/include/asm/siginfo.h
@@ -88,6 +88,7 @@
 #ifdef __ARCH_SI_TRAPNO
 			int _trapno;	/* TRAP # which caused the signal */
 #endif
+			short _addr_lsb;
 		} _sigfault;
 
 		/* SIGPOLL, SIGXFSZ (To do ...)  */
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 2376f2e..70df9c0 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -146,7 +146,8 @@
 #define _TIF_LOAD_WATCH		(1<<TIF_LOAD_WATCH)
 
 /* work to do on interrupt/exception return */
-#define _TIF_WORK_MASK		(0x0000ffef & ~_TIF_SECCOMP)
+#define _TIF_WORK_MASK		(0x0000ffef &				\
+					~(_TIF_SECCOMP | _TIF_SYSCALL_AUDIT))
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK	(0x8000ffff & ~_TIF_SECCOMP)
 
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h
index baa318a..550725b 100644
--- a/arch/mips/include/asm/unistd.h
+++ b/arch/mips/include/asm/unistd.h
@@ -356,16 +356,19 @@
 #define __NR_perf_event_open		(__NR_Linux + 333)
 #define __NR_accept4			(__NR_Linux + 334)
 #define __NR_recvmmsg			(__NR_Linux + 335)
+#define __NR_fanotify_init		(__NR_Linux + 336)
+#define __NR_fanotify_mark		(__NR_Linux + 337)
+#define __NR_prlimit64			(__NR_Linux + 338)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		335
+#define __NR_Linux_syscalls		338
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		335
+#define __NR_O32_Linux_syscalls		338
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -668,16 +671,19 @@
 #define __NR_perf_event_open		(__NR_Linux + 292)
 #define __NR_accept4			(__NR_Linux + 293)
 #define __NR_recvmmsg			(__NR_Linux + 294)
+#define __NR_fanotify_init		(__NR_Linux + 295)
+#define __NR_fanotify_mark		(__NR_Linux + 296)
+#define __NR_prlimit64			(__NR_Linux + 297)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		294
+#define __NR_Linux_syscalls		297
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		294
+#define __NR_64_Linux_syscalls		297
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -985,16 +991,19 @@
 #define __NR_accept4			(__NR_Linux + 297)
 #define __NR_recvmmsg			(__NR_Linux + 298)
 #define __NR_getdents64			(__NR_Linux + 299)
+#define __NR_fanotify_init		(__NR_Linux + 300)
+#define __NR_fanotify_mark		(__NR_Linux + 301)
+#define __NR_prlimit64			(__NR_Linux + 302)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		299
+#define __NR_Linux_syscalls		302
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		299
+#define __NR_N32_Linux_syscalls		302
 
 #ifdef __KERNEL__
 
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index ee18028..35b3e2f 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/spinlock.h>
+#include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/i8253.h>
diff --git a/arch/mips/jz4740/Platform b/arch/mips/jz4740/Platform
index 6a97230..ba91be9 100644
--- a/arch/mips/jz4740/Platform
+++ b/arch/mips/jz4740/Platform
@@ -1,3 +1,3 @@
-core-$(CONFIG_MACH_JZ4740)	+= arch/mips/jz4740/
+platform-$(CONFIG_MACH_JZ4740)	+= jz4740/
 cflags-$(CONFIG_MACH_JZ4740)	+= -I$(srctree)/arch/mips/include/asm/mach-jz4740
 load-$(CONFIG_MACH_JZ4740)	+= 0xffffffff80010000
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 0176ed0..32103cc 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -40,7 +40,6 @@
 		return -EFAULT;
 	}
 
-	regs->regs[0] = 0;
 	switch (insn.i_format.opcode) {
 	/*
 	 * jr and jalr are in r_format format.
diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c
index bfea327..36c3898 100644
--- a/arch/mips/kernel/cevt-bcm1480.c
+++ b/arch/mips/kernel/cevt-bcm1480.c
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/smp.h>
+#include <linux/irq.h>
 
 #include <asm/addrspace.h>
 #include <asm/io.h>
diff --git a/arch/mips/kernel/cevt-ds1287.c b/arch/mips/kernel/cevt-ds1287.c
index 00a4da2..939157e 100644
--- a/arch/mips/kernel/cevt-ds1287.c
+++ b/arch/mips/kernel/cevt-ds1287.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
+#include <linux/irq.h>
 
 #include <asm/time.h>
 
diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c
index 392ef37..339f363 100644
--- a/arch/mips/kernel/cevt-gt641xx.c
+++ b/arch/mips/kernel/cevt-gt641xx.c
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/irq.h>
 
 #include <asm/gt64120.h>
 #include <asm/time.h>
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 2a4d50f..2f4d7a9 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -10,6 +10,7 @@
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/smp.h>
+#include <linux/irq.h>
 
 #include <asm/smtc_ipi.h>
 #include <asm/time.h>
diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c
index da78eea..590c54f 100644
--- a/arch/mips/kernel/cevt-sb1250.c
+++ b/arch/mips/kernel/cevt-sb1250.c
@@ -17,6 +17,7 @@
  */
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/percpu.h>
 #include <linux/smp.h>
 
diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c
index b102e4f..2e72d30 100644
--- a/arch/mips/kernel/cevt-smtc.c
+++ b/arch/mips/kernel/cevt-smtc.c
@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/smp.h>
+#include <linux/irq.h>
 
 #include <asm/smtc_ipi.h>
 #include <asm/time.h>
diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c
index 218ee6b..0b73773 100644
--- a/arch/mips/kernel/cevt-txx9.c
+++ b/arch/mips/kernel/cevt-txx9.c
@@ -13,6 +13,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/time.h>
 #include <asm/txx9tmr.h>
 
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
index 9479406..2392a7a2 100644
--- a/arch/mips/kernel/i8253.c
+++ b/arch/mips/kernel/i8253.c
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/spinlock.h>
+#include <linux/irq.h>
 
 #include <asm/delay.h>
 #include <asm/i8253.h>
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 2779911..c58176c 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/sysdev.h>
+#include <linux/irq.h>
 
 #include <asm/i8259.h>
 #include <asm/io.h>
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index b181f2f..1774271 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -3,12 +3,11 @@
 #include <linux/bitmap.h>
 #include <linux/init.h>
 #include <linux/smp.h>
+#include <linux/irq.h>
 
 #include <asm/io.h>
 #include <asm/gic.h>
 #include <asm/gcmpregs.h>
-#include <asm/mips-boards/maltaint.h>
-#include <asm/irq.h>
 #include <linux/hardirq.h>
 #include <asm-generic/bitops/find.h>
 
@@ -131,7 +130,7 @@
 	int		i;
 
 	irq -= _irqbase;
-	pr_debug(KERN_DEBUG "%s(%d) called\n", __func__, irq);
+	pr_debug("%s(%d) called\n", __func__, irq);
 	cpumask_and(&tmp, cpumask, cpu_online_mask);
 	if (cpus_empty(tmp))
 		return -1;
@@ -222,7 +221,7 @@
 	/* Setup specifics */
 	for (i = 0; i < mapsize; i++) {
 		cpu = intrmap[i].cpunum;
-		if (cpu == X)
+		if (cpu == GIC_UNUSED)
 			continue;
 		if (cpu == 0 && i != 0 && intrmap[i].flags == 0)
 			continue;
diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c
index fb50cc7..9731e8b4 100644
--- a/arch/mips/kernel/irq-rm7000.c
+++ b/arch/mips/kernel/irq-rm7000.c
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 
 #include <asm/irq_cpu.h>
diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c
index b47e461..b7e4025 100644
--- a/arch/mips/kernel/irq-rm9000.c
+++ b/arch/mips/kernel/irq-rm9000.c
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 55c8a3c..0262abe 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
diff --git a/arch/mips/kernel/irq_txx9.c b/arch/mips/kernel/irq_txx9.c
index 9b78029..95a96f6 100644
--- a/arch/mips/kernel/irq_txx9.c
+++ b/arch/mips/kernel/irq_txx9.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/types.h>
+#include <linux/irq.h>
 #include <asm/txx9irq.h>
 
 struct txx9_irc_reg {
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index 1f4e2fa..f4546e9 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -283,7 +283,7 @@
 	struct pt_regs *regs = args->regs;
 	int trap = (regs->cp0_cause & 0x7c) >> 2;
 
-	/* Userpace events, ignore. */
+	/* Userspace events, ignore. */
 	if (user_mode(regs))
 		return NOTIFY_DONE;
 
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
index 80e2ba6..29811f0 100644
--- a/arch/mips/kernel/kspd.c
+++ b/arch/mips/kernel/kspd.c
@@ -251,7 +251,7 @@
  		memset(&tz, 0, sizeof(tz));
  		if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv,
 					     (int)&tz, 0, 0)) == 0)
-		ret.retval = tv.tv_sec;
+			ret.retval = tv.tv_sec;
 		break;
 
  	case MTSP_SYSCALL_EXIT:
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index c2dab14..6343b4a 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -341,3 +341,10 @@
 {
 	return sys_lookup_dcookie(merge_64(a0, a1), buf, len);
 }
+
+SYSCALL_DEFINE6(32_fanotify_mark, int, fanotify_fd, unsigned int, flags,
+		u64, a3, u64, a4, int, dfd, const char  __user *, pathname)
+{
+	return sys_fanotify_mark(fanotify_fd, flags, merge_64(a3, a4),
+				 dfd, pathname);
+}
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index 2340f11..9a526ba 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -103,7 +103,7 @@
 	if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
 		goto out_unlock;
 
-	retval = security_task_setscheduler(p, 0, NULL);
+	retval = security_task_setscheduler(p)
 	if (retval)
 		goto out_unlock;
 
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index c51b95f..c877733 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -536,7 +536,7 @@
 {
 	/* do the secure computing check first */
 	if (!entryexit)
-		secure_computing(regs->regs[0]);
+		secure_computing(regs->regs[2]);
 
 	if (unlikely(current->audit_context) && entryexit)
 		audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]),
@@ -565,7 +565,7 @@
 
 out:
 	if (unlikely(current->audit_context) && !entryexit)
-		audit_syscall_entry(audit_arch(), regs->regs[0],
+		audit_syscall_entry(audit_arch(), regs->regs[2],
 				    regs->regs[4], regs->regs[5],
 				    regs->regs[6], regs->regs[7]);
 }
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 26f9b9a..557ef72 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -468,7 +468,8 @@
 	.release = file_release,
 	.write =   file_write,
 	.read =    file_read,
-	.poll =    file_poll
+	.poll =    file_poll,
+	.llseek =  noop_llseek,
 };
 
 static struct irqaction rtlx_irq = {
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 17202bb..fbaabad 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -63,9 +63,9 @@
 	sw	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
+	lw	t1, PT_R2(sp)		# syscall number
 	negu	v0			# error
-	sw	v0, PT_R0(sp)		# set flag for syscall
-					# restarting
+	sw	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sw	v0, PT_R2(sp)		# result
 
 o32_syscall_exit:
@@ -104,9 +104,9 @@
 	sw	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
+	lw	t1, PT_R2(sp)		# syscall number
 	negu	v0			# error
-	sw	v0, PT_R0(sp)		# set flag for syscall
-					# restarting
+	sw	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sw	v0, PT_R2(sp)		# result
 
 	j	syscall_exit
@@ -169,8 +169,7 @@
 	 * We probably should handle this case a bit more drastic.
 	 */
 bad_stack:
-	negu	v0				# error
-	sw	v0, PT_R0(sp)
+	li	v0, EFAULT
 	sw	v0, PT_R2(sp)
 	li	t0, 1				# set error flag
 	sw	t0, PT_R7(sp)
@@ -583,7 +582,10 @@
 	sys	sys_rt_tgsigqueueinfo	4
 	sys	sys_perf_event_open	5
 	sys	sys_accept4		4
-	sys     sys_recvmmsg            5
+	sys	sys_recvmmsg		5	/* 4335 */
+	sys	sys_fanotify_init	2
+	sys	sys_fanotify_mark	6
+	sys	sys_prlimit64		4
 	.endm
 
 	/* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index a8a6c59..3f41792 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -66,9 +66,9 @@
 	sd	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
+	ld	t1, PT_R2(sp)		# syscall number
 	dnegu	v0			# error
-	sd	v0, PT_R0(sp)		# set flag for syscall
-					# restarting
+	sd	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sd	v0, PT_R2(sp)		# result
 
 n64_syscall_exit:
@@ -109,8 +109,9 @@
 	sd	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
+	ld	t1, PT_R2(sp)		# syscall number
 	dnegu	v0			# error
-	sd	v0, PT_R0(sp)		# set flag for syscall restarting
+	sd	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sd	v0, PT_R2(sp)		# result
 
 	j	syscall_exit
@@ -416,9 +417,12 @@
 	PTR	sys_pipe2
 	PTR	sys_inotify_init1
 	PTR	sys_preadv
-	PTR	sys_pwritev			/* 5390 */
+	PTR	sys_pwritev			/* 5290 */
 	PTR	sys_rt_tgsigqueueinfo
 	PTR	sys_perf_event_open
 	PTR	sys_accept4
-	PTR     sys_recvmmsg
+	PTR	sys_recvmmsg
+	PTR	sys_fanotify_init		/* 5295 */
+	PTR	sys_fanotify_mark
+	PTR	sys_prlimit64
 	.size	sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index a3d6613..f08ece6 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -65,8 +65,9 @@
 	sd	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
+	ld	t1, PT_R2(sp)		# syscall number
 	dnegu	v0			# error
-	sd	v0, PT_R0(sp)		# set flag for syscall restarting
+	sd	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sd	v0, PT_R2(sp)		# result
 
 	local_irq_disable		# make sure need_resched and
@@ -106,8 +107,9 @@
 	sd	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
+	ld	t1, PT_R2(sp)		# syscall number
 	dnegu	v0			# error
-	sd	v0, PT_R0(sp)		# set flag for syscall restarting
+	sd	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sd	v0, PT_R2(sp)		# result
 
 	j	syscall_exit
@@ -320,10 +322,10 @@
 	PTR	sys_cacheflush
 	PTR	sys_cachectl
 	PTR	sys_sysmips
-	PTR	sys_io_setup			/* 6200 */
+	PTR	compat_sys_io_setup			/* 6200 */
 	PTR	sys_io_destroy
-	PTR	sys_io_getevents
-	PTR	sys_io_submit
+	PTR	compat_sys_io_getevents
+	PTR	compat_sys_io_submit
 	PTR	sys_io_cancel
 	PTR	sys_exit_group			/* 6205 */
 	PTR	sys_lookup_dcookie
@@ -419,5 +421,8 @@
 	PTR	sys_perf_event_open
 	PTR	sys_accept4
 	PTR     compat_sys_recvmmsg
-	PTR     sys_getdents
+	PTR     sys_getdents64
+	PTR	sys_fanotify_init		/* 6300 */
+	PTR	sys_fanotify_mark
+	PTR	sys_prlimit64
 	.size	sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 813689e..78d768a 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -93,8 +93,9 @@
 	sd	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
+	ld	t1, PT_R2(sp)		# syscall number
 	dnegu	v0			# error
-	sd	v0, PT_R0(sp)		# flag for syscall restarting
+	sd	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sd	v0, PT_R2(sp)		# result
 
 o32_syscall_exit:
@@ -142,8 +143,9 @@
 	sd	t0, PT_R7(sp)		# set error flag
 	beqz	t0, 1f
 
+	ld	t1, PT_R2(sp)		# syscall number
 	dnegu	v0			# error
-	sd	v0, PT_R0(sp)		# set flag for syscall restarting
+	sd	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sd	v0, PT_R2(sp)		# result
 
 	j	syscall_exit
@@ -154,8 +156,7 @@
 	 * The stackpointer for a call with more than 4 arguments is bad.
 	 */
 bad_stack:
-	dnegu	v0			# error
-	sd	v0, PT_R0(sp)
+	li	v0, EFAULT
 	sd	v0, PT_R2(sp)
 	li	t0, 1			# set error flag
 	sd	t0, PT_R7(sp)
@@ -444,10 +445,10 @@
 	PTR	compat_sys_futex
 	PTR	compat_sys_sched_setaffinity
 	PTR	compat_sys_sched_getaffinity	/* 4240 */
-	PTR	sys_io_setup
+	PTR	compat_sys_io_setup
 	PTR	sys_io_destroy
-	PTR	sys_io_getevents
-	PTR	sys_io_submit
+	PTR	compat_sys_io_getevents
+	PTR	compat_sys_io_submit
 	PTR	sys_io_cancel			/* 4245 */
 	PTR	sys_exit_group
 	PTR	sys32_lookup_dcookie
@@ -538,5 +539,8 @@
 	PTR	compat_sys_rt_tgsigqueueinfo
 	PTR	sys_perf_event_open
 	PTR	sys_accept4
-	PTR     compat_sys_recvmmsg
+	PTR	compat_sys_recvmmsg		/* 4335 */
+	PTR	sys_fanotify_init
+	PTR	sys_32_fanotify_mark
+	PTR	sys_prlimit64
 	.size	sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 2099d5a..5922342 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -390,7 +390,6 @@
 {
 	struct rt_sigframe __user *frame;
 	sigset_t set;
-	stack_t st;
 	int sig;
 
 	frame = (struct rt_sigframe __user *) regs.regs[29];
@@ -411,11 +410,9 @@
 	else if (sig)
 		force_sig(sig, current);
 
-	if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
-		goto badframe;
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
-	do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
+	do_sigaltstack(&frame->rs_uc.uc_stack, NULL, regs.regs[29]);
 
 	/*
 	 * Don't let your children do this ...
@@ -550,23 +547,26 @@
 	struct mips_abi *abi = current->thread.abi;
 	void *vdso = current->mm->context.vdso;
 
-	switch(regs->regs[0]) {
-	case ERESTART_RESTARTBLOCK:
-	case ERESTARTNOHAND:
-		regs->regs[2] = EINTR;
-		break;
-	case ERESTARTSYS:
-		if (!(ka->sa.sa_flags & SA_RESTART)) {
+	if (regs->regs[0]) {
+		switch(regs->regs[2]) {
+		case ERESTART_RESTARTBLOCK:
+		case ERESTARTNOHAND:
 			regs->regs[2] = EINTR;
 			break;
+		case ERESTARTSYS:
+			if (!(ka->sa.sa_flags & SA_RESTART)) {
+				regs->regs[2] = EINTR;
+				break;
+			}
+		/* fallthrough */
+		case ERESTARTNOINTR:
+			regs->regs[7] = regs->regs[26];
+			regs->regs[2] = regs->regs[0];
+			regs->cp0_epc -= 4;
 		}
-	/* fallthrough */
-	case ERESTARTNOINTR:		/* Userland will reload $v0.  */
-		regs->regs[7] = regs->regs[26];
-		regs->cp0_epc -= 8;
-	}
 
-	regs->regs[0] = 0;		/* Don't deal with this again.  */
+		regs->regs[0] = 0;		/* Don't deal with this again.  */
+	}
 
 	if (sig_uses_siginfo(ka))
 		ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
@@ -575,6 +575,9 @@
 		ret = abi->setup_frame(vdso + abi->signal_return_offset,
 				       ka, regs, sig, oldset);
 
+	if (ret)
+		return ret;
+
 	spin_lock_irq(&current->sighand->siglock);
 	sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
 	if (!(ka->sa.sa_flags & SA_NODEFER))
@@ -622,17 +625,13 @@
 		return;
 	}
 
-	/*
-	 * Who's code doesn't conform to the restartable syscall convention
-	 * dies here!!!  The li instruction, a single machine instruction,
-	 * must directly be followed by the syscall instruction.
-	 */
 	if (regs->regs[0]) {
 		if (regs->regs[2] == ERESTARTNOHAND ||
 		    regs->regs[2] == ERESTARTSYS ||
 		    regs->regs[2] == ERESTARTNOINTR) {
+			regs->regs[2] = regs->regs[0];
 			regs->regs[7] = regs->regs[26];
-			regs->cp0_epc -= 8;
+			regs->cp0_epc -= 4;
 		}
 		if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
 			regs->regs[2] = current->thread.abi->restart;
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 2c5df81..ee24d81 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -109,6 +109,7 @@
 asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
 	struct rt_sigframe_n32 __user *frame;
+	mm_segment_t old_fs;
 	sigset_t set;
 	stack_t st;
 	s32 sp;
@@ -143,7 +144,11 @@
 
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
 	do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
+	set_fs(old_fs);
+
 
 	/*
 	 * Don't let your children do this ...
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index cfeb2c1..39c0825 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1038,7 +1038,7 @@
 		 * but it's more efficient, given that we're already
 		 * running down the IPI queue.
 		 */
-		__raw_local_irq_restore(flags);
+		__arch_local_irq_restore(flags);
 	}
 }
 
@@ -1190,7 +1190,7 @@
 		/*
 		 ** But use a raw restore here to avoid recursion.
 		 */
-		__raw_local_irq_restore(flags);
+		__arch_local_irq_restore(flags);
 
 		if (pipi) {
 			self_ipi(pipi);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 03ec001..d053bf4 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -28,6 +28,7 @@
 #include <linux/kprobes.h>
 #include <linux/notifier.h>
 #include <linux/kdb.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
@@ -51,7 +52,6 @@
 #include <asm/mmu_context.h>
 #include <asm/types.h>
 #include <asm/stacktrace.h>
-#include <asm/irq.h>
 #include <asm/uasm.h>
 
 extern void check_wait(void);
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 69b039c..33d5a5c 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -109,8 +109,6 @@
 	unsigned long value;
 	unsigned int res;
 
-	regs->regs[0] = 0;
-
 	/*
 	 * This load never faults.
 	 */
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 2bd2151..3eb3cde 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1192,7 +1192,8 @@
 	.owner = THIS_MODULE,
 	.open = vpe_open,
 	.release = vpe_release,
-	.write = vpe_write
+	.write = vpe_write,
+	.llseek = noop_llseek,
 };
 
 /* module wrapper entry points */
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 7ba8908..469d401 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -44,27 +44,39 @@
 
 static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
 {
+	gfp_t dma_flag;
+
 	/* ignore region specifiers */
 	gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
 
-#ifdef CONFIG_ZONE_DMA
+#ifdef CONFIG_ISA
 	if (dev == NULL)
-		gfp |= __GFP_DMA;
-	else if (dev->coherent_dma_mask < DMA_BIT_MASK(24))
-		gfp |= __GFP_DMA;
+		dma_flag = __GFP_DMA;
 	else
 #endif
-#ifdef CONFIG_ZONE_DMA32
+#if defined(CONFIG_ZONE_DMA32) && defined(CONFIG_ZONE_DMA)
 	     if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
-		gfp |= __GFP_DMA32;
+			dma_flag = __GFP_DMA;
+	else if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+			dma_flag = __GFP_DMA32;
 	else
 #endif
-		;
+#if defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_ZONE_DMA)
+	     if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+		dma_flag = __GFP_DMA32;
+	else
+#endif
+#if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32)
+	     if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+		dma_flag = __GFP_DMA;
+	else
+#endif
+		dma_flag = 0;
 
 	/* Don't invoke OOM killer */
 	gfp |= __GFP_NORETRY;
 
-	return gfp;
+	return gfp | dma_flag;
 }
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
index 1ef75cd..274af3b 100644
--- a/arch/mips/mm/sc-rm7k.c
+++ b/arch/mips/mm/sc-rm7k.c
@@ -30,7 +30,7 @@
 #define tc_lsize	32
 
 extern unsigned long icache_way_size, dcache_way_size;
-unsigned long tcache_size;
+static unsigned long tcache_size;
 
 #include <asm/r4kcache.h>
 
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index 15949b0..b79b24a 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -385,6 +385,8 @@
  */
 
 #define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
+#define X GIC_UNUSED
+
 static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
 	{ X, X,		   X,		X,		0 },
 	{ X, X,		   X,	 	X,		0 },
@@ -404,6 +406,7 @@
 	{ X, X,		   X,		X,	        0 },
 	/* The remainder of this table is initialised by fill_ipi_map */
 };
+#undef X
 
 /*
  * GCMP needs to be detected before any SMP initialisation
diff --git a/arch/mips/mti-malta/malta-platform.c b/arch/mips/mti-malta/malta-platform.c
index 72e32a7..4c35301 100644
--- a/arch/mips/mti-malta/malta-platform.c
+++ b/arch/mips/mti-malta/malta-platform.c
@@ -25,6 +25,7 @@
 #include <linux/serial_8250.h>
 #include <linux/mc146818rtc.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c
index 31c1501..6a3bdb5 100644
--- a/arch/mips/pci/ops-tx3927.c
+++ b/arch/mips/pci/ops-tx3927.c
@@ -38,6 +38,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <asm/addrspace.h>
 #include <asm/txx9irq.h>
diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c
index 5989e74..a1e7e6d 100644
--- a/arch/mips/pci/ops-tx4927.c
+++ b/arch/mips/pci/ops-tx4927.c
@@ -17,6 +17,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/txx9/pci.h>
 #include <asm/txx9/tx4927pcic.h>
 
diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c
index 71f7d27..f31218e 100644
--- a/arch/mips/pci/pci-rc32434.c
+++ b/arch/mips/pci/pci-rc32434.c
@@ -118,7 +118,7 @@
 	if (!((pcicvalue == PCIM_H_EA) ||
 	      (pcicvalue == PCIM_H_IA_FIX) ||
 	      (pcicvalue == PCIM_H_IA_RR))) {
-		pr_err(KERN_ERR "PCI init error!!!\n");
+		pr_err("PCI init error!!!\n");
 		/* Not in Host Mode, return ERROR */
 		return -1;
 	}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
index 94c9c2c..07e71ff 100644
--- a/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/bitops.h>
+#include <linux/irq.h>
 
 #include <asm/system.h>
 
diff --git a/arch/mips/pnx8550/common/reset.c b/arch/mips/pnx8550/common/reset.c
index fadd8744..e7a12ff 100644
--- a/arch/mips/pnx8550/common/reset.c
+++ b/arch/mips/pnx8550/common/reset.c
@@ -22,29 +22,19 @@
  */
 #include <linux/kernel.h>
 
+#include <asm/processor.h>
 #include <asm/reboot.h>
 #include <glb.h>
 
 void pnx8550_machine_restart(char *command)
 {
-	char head[] = "************* Machine restart *************";
-	char foot[] = "*******************************************";
-
-	printk("\n\n");
-	printk("%s\n", head);
-	if (command != NULL)
-		printk("* %s\n", command);
-	printk("%s\n", foot);
-
 	PNX8550_RST_CTL = PNX8550_RST_DO_SW_RST;
 }
 
 void pnx8550_machine_halt(void)
 {
-	printk("*** Machine halt. (Not implemented) ***\n");
-}
-
-void pnx8550_machine_power_off(void)
-{
-	printk("*** Machine power off.  (Not implemented) ***\n");
+	while (1) {
+		if (cpu_wait)
+			cpu_wait();
+	}
 }
diff --git a/arch/mips/pnx8550/common/setup.c b/arch/mips/pnx8550/common/setup.c
index 64246c9..43cb394 100644
--- a/arch/mips/pnx8550/common/setup.c
+++ b/arch/mips/pnx8550/common/setup.c
@@ -44,7 +44,6 @@
 extern void __init board_setup(void);
 extern void pnx8550_machine_restart(char *);
 extern void pnx8550_machine_halt(void);
-extern void pnx8550_machine_power_off(void);
 extern struct resource ioport_resource;
 extern struct resource iomem_resource;
 extern char *prom_getcmdline(void);
@@ -100,7 +99,7 @@
 
         _machine_restart = pnx8550_machine_restart;
         _machine_halt = pnx8550_machine_halt;
-        pm_power_off = pnx8550_machine_power_off;
+        pm_power_off = pnx8550_machine_halt;
 
 	/* Clear the Global 2 Register, PCI Inta Output Enable Registers
 	   Bit 1:Enable DAC Powerdown
diff --git a/arch/mips/powertv/asic/irq_asic.c b/arch/mips/powertv/asic/irq_asic.c
index b54d244..e553824 100644
--- a/arch/mips/powertv/asic/irq_asic.c
+++ b/arch/mips/powertv/asic/irq_asic.c
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
diff --git a/arch/mips/rb532/serial.c b/arch/mips/rb532/serial.c
index 00ed19f..7048254 100644
--- a/arch/mips/rb532/serial.c
+++ b/arch/mips/rb532/serial.c
@@ -29,6 +29,7 @@
 #include <linux/tty.h>
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
+#include <linux/irq.h>
 
 #include <asm/serial.h>
 #include <asm/mach-rc32434/rb.h>
diff --git a/arch/mips/sibyte/common/sb_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c
index d4ed7a9..ca35b73 100644
--- a/arch/mips/sibyte/common/sb_tbprof.c
+++ b/arch/mips/sibyte/common/sb_tbprof.c
@@ -545,6 +545,7 @@
 	.unlocked_ioctl	= sbprof_tb_ioctl,
 	.compat_ioctl	= sbprof_tb_ioctl,
 	.mmap		= NULL,
+	.llseek		= default_llseek,
 };
 
 static struct class *tb_class;
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index e698089..bbe7187 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -10,6 +10,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 51e62bb..8c92c73 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -11,6 +11,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/pci.h>
 #include <linux/serial_8250.h>
 
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
index f4699d3..dc98745 100644
--- a/arch/mips/sni/pcit.c
+++ b/arch/mips/sni/pcit.c
@@ -10,6 +10,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/pci.h>
 #include <linux/serial_8250.h>
 
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
index 90c558f..0e6f42c 100644
--- a/arch/mips/sni/rm200.c
+++ b/arch/mips/sni/rm200.c
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/io.h>
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index f3b60e6..c76151b 100644
--- a/arch/mips/sni/time.c
+++ b/arch/mips/sni/time.c
@@ -1,5 +1,6 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/smp.h>
 #include <linux/time.h>
 #include <linux/clockchips.h>
diff --git a/arch/mips/txx9/generic/irq_tx4927.c b/arch/mips/txx9/generic/irq_tx4927.c
index ad2870d..e1828e8 100644
--- a/arch/mips/txx9/generic/irq_tx4927.c
+++ b/arch/mips/txx9/generic/irq_tx4927.c
@@ -25,6 +25,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/irq_cpu.h>
 #include <asm/txx9/tx4927.h>
 
diff --git a/arch/mips/txx9/generic/irq_tx4938.c b/arch/mips/txx9/generic/irq_tx4938.c
index 025ae11..a6e6e80 100644
--- a/arch/mips/txx9/generic/irq_tx4938.c
+++ b/arch/mips/txx9/generic/irq_tx4938.c
@@ -13,6 +13,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/irq_cpu.h>
 #include <asm/txx9/tx4938.h>
 
diff --git a/arch/mips/txx9/generic/irq_tx4939.c b/arch/mips/txx9/generic/irq_tx4939.c
index 013213a8..3886ad7 100644
--- a/arch/mips/txx9/generic/irq_tx4939.c
+++ b/arch/mips/txx9/generic/irq_tx4939.c
@@ -19,6 +19,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/types.h>
 #include <asm/irq_cpu.h>
 #include <asm/txx9irq.h>
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index 575d219b..812816c 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -24,6 +24,7 @@
 #include <linux/leds.h>
 #include <linux/sysdev.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 #include <asm/reboot.h>
diff --git a/arch/mips/txx9/jmr3927/irq.c b/arch/mips/txx9/jmr3927/irq.c
index 6ec626c..0a7f8e3 100644
--- a/arch/mips/txx9/jmr3927/irq.c
+++ b/arch/mips/txx9/jmr3927/irq.c
@@ -32,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <asm/io.h>
 #include <asm/mipsregs.h>
diff --git a/arch/mips/txx9/rbtx4927/irq.c b/arch/mips/txx9/rbtx4927/irq.c
index 9c14ebb..c4b54d2 100644
--- a/arch/mips/txx9/rbtx4927/irq.c
+++ b/arch/mips/txx9/rbtx4927/irq.c
@@ -111,6 +111,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/io.h>
 #include <asm/mipsregs.h>
 #include <asm/txx9/generic.h>
diff --git a/arch/mips/txx9/rbtx4938/irq.c b/arch/mips/txx9/rbtx4938/irq.c
index 7d21bef..67a73a8 100644
--- a/arch/mips/txx9/rbtx4938/irq.c
+++ b/arch/mips/txx9/rbtx4938/irq.c
@@ -64,6 +64,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/mipsregs.h>
 #include <asm/txx9/generic.h>
 #include <asm/txx9/rbtx4938.h>
diff --git a/arch/mips/txx9/rbtx4939/irq.c b/arch/mips/txx9/rbtx4939/irq.c
index 500cc0a..57fa740 100644
--- a/arch/mips/txx9/rbtx4939/irq.c
+++ b/arch/mips/txx9/rbtx4939/irq.c
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <asm/mipsregs.h>
 #include <asm/txx9/rbtx4939.h>
 
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index bef0687..0975eb7 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -19,6 +19,7 @@
  */
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/system.h>
diff --git a/arch/mips/vr41xx/common/siu.c b/arch/mips/vr41xx/common/siu.c
index 54eae56..bbd45d2 100644
--- a/arch/mips/vr41xx/common/siu.c
+++ b/arch/mips/vr41xx/common/siu.c
@@ -22,6 +22,7 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
+#include <linux/irq.h>
 
 #include <asm/cpu.h>
 #include <asm/vr41xx/siu.h>
diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug
index ff80e86..ce83c74 100644
--- a/arch/mn10300/Kconfig.debug
+++ b/arch/mn10300/Kconfig.debug
@@ -101,7 +101,7 @@
 
 choice
 	prompt "GDB stub port"
-	default GDBSTUB_TTYSM0
+	default GDBSTUB_ON_TTYSM0
 	depends on GDBSTUB
 	help
 	  Select the serial port used for GDB-stub.
diff --git a/arch/mn10300/include/asm/ioctls.h b/arch/mn10300/include/asm/ioctls.h
index cb8cf19..0212f4b 100644
--- a/arch/mn10300/include/asm/ioctls.h
+++ b/arch/mn10300/include/asm/ioctls.h
@@ -1,88 +1,6 @@
 #ifndef _ASM_IOCTLS_H
 #define _ASM_IOCTLS_H
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T', 0x2A, struct termios2)
-#define TCSETS2		_IOW('T', 0x2B, struct termios2)
-#define TCSETSW2	_IOW('T', 0x2C, struct termios2)
-#define TCSETSF2	_IOW('T', 0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T', 0x30, unsigned int) /* Get Pty Number
-						       * (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T', 0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T', 0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-#define FIOQSIZE	0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* _ASM_IOCTLS_H */
diff --git a/arch/mn10300/include/asm/irqflags.h b/arch/mn10300/include/asm/irqflags.h
new file mode 100644
index 0000000..5e529a1
--- /dev/null
+++ b/arch/mn10300/include/asm/irqflags.h
@@ -0,0 +1,123 @@
+/* MN10300 IRQ flag handling
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#include <asm/cpu-regs.h>
+
+/*
+ * interrupt control
+ * - "disabled": run in IM1/2
+ *   - level 0 - GDB stub
+ *   - level 1 - virtual serial DMA (if present)
+ *   - level 5 - normal interrupt priority
+ *   - level 6 - timer interrupt
+ * - "enabled":  run in IM7
+ */
+#ifdef CONFIG_MN10300_TTYSM
+#define MN10300_CLI_LEVEL	EPSW_IM_2
+#else
+#define MN10300_CLI_LEVEL	EPSW_IM_1
+#endif
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+
+	asm volatile("mov epsw,%0" : "=d"(flags));
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	asm volatile(
+		"	and %0,epsw	\n"
+		"	or %1,epsw	\n"
+		"	nop		\n"
+		"	nop		\n"
+		"	nop		\n"
+		:
+		: "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)
+		: "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+
+	flags = arch_local_save_flags();
+	arch_local_irq_disable();
+	return flags;
+}
+
+/*
+ * we make sure arch_irq_enable() doesn't cause priority inversion
+ */
+extern unsigned long __mn10300_irq_enabled_epsw;
+
+static inline void arch_local_irq_enable(void)
+{
+	unsigned long tmp;
+
+	asm volatile(
+		"	mov	epsw,%0		\n"
+		"	and	%1,%0		\n"
+		"	or	%2,%0		\n"
+		"	mov	%0,epsw		\n"
+		: "=&d"(tmp)
+		: "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw)
+		: "memory");
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile(
+		"	mov %0,epsw	\n"
+		"	nop		\n"
+		"	nop		\n"
+		"	nop		\n"
+		:
+		: "d"(flags)
+		: "memory", "cc");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags & EPSW_IM) <= MN10300_CLI_LEVEL;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+/*
+ * Hook to save power by halting the CPU
+ * - called from the idle loop
+ * - must reenable interrupts (which takes three instruction cycles to complete)
+ */
+static inline void arch_safe_halt(void)
+{
+	asm volatile(
+		"	or	%0,epsw	\n"
+		"	nop		\n"
+		"	nop		\n"
+		"	bset	%2,(%1)	\n"
+		:
+		: "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)
+		: "cc");
+}
+
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_IRQFLAGS_H */
diff --git a/arch/mn10300/include/asm/system.h b/arch/mn10300/include/asm/system.h
index 3636c05..9f7c7e1 100644
--- a/arch/mn10300/include/asm/system.h
+++ b/arch/mn10300/include/asm/system.h
@@ -17,6 +17,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/kernel.h>
+#include <linux/irqflags.h>
 
 struct task_struct;
 struct thread_struct;
@@ -81,114 +82,6 @@
 
 /*****************************************************************************/
 /*
- * interrupt control
- * - "disabled": run in IM1/2
- *   - level 0 - GDB stub
- *   - level 1 - virtual serial DMA (if present)
- *   - level 5 - normal interrupt priority
- *   - level 6 - timer interrupt
- * - "enabled":  run in IM7
- */
-#ifdef CONFIG_MN10300_TTYSM
-#define MN10300_CLI_LEVEL	EPSW_IM_2
-#else
-#define MN10300_CLI_LEVEL	EPSW_IM_1
-#endif
-
-#define local_save_flags(x)			\
-do {						\
-	typecheck(unsigned long, x);		\
-	asm volatile(				\
-		"	mov epsw,%0	\n"	\
-		: "=d"(x)			\
-		);				\
-} while (0)
-
-#define local_irq_disable()						\
-do {									\
-	asm volatile(							\
-		"	and %0,epsw	\n"				\
-		"	or %1,epsw	\n"				\
-		"	nop		\n"				\
-		"	nop		\n"				\
-		"	nop		\n"				\
-		:							\
-		: "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)	\
-		);							\
-} while (0)
-
-#define local_irq_save(x)			\
-do {						\
-	local_save_flags(x);			\
-	local_irq_disable();			\
-} while (0)
-
-/*
- * we make sure local_irq_enable() doesn't cause priority inversion
- */
-#ifndef __ASSEMBLY__
-
-extern unsigned long __mn10300_irq_enabled_epsw;
-
-#endif
-
-#define local_irq_enable()						\
-do {									\
-	unsigned long tmp;						\
-									\
-	asm volatile(							\
-		"	mov	epsw,%0		\n"			\
-		"	and	%1,%0		\n"			\
-		"	or	%2,%0		\n"			\
-		"	mov	%0,epsw		\n"			\
-		: "=&d"(tmp)						\
-		: "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw)	\
-		: "cc"							\
-		);							\
-} while (0)
-
-#define local_irq_restore(x)			\
-do {						\
-	typecheck(unsigned long, x);		\
-	asm volatile(				\
-		"	mov %0,epsw	\n"	\
-		"	nop		\n"	\
-		"	nop		\n"	\
-		"	nop		\n"	\
-		:				\
-		: "d"(x)			\
-		: "memory", "cc"		\
-		);				\
-} while (0)
-
-#define irqs_disabled()				\
-({						\
-	unsigned long flags;			\
-	local_save_flags(flags);		\
-	(flags & EPSW_IM) <= MN10300_CLI_LEVEL;	\
-})
-
-/* hook to save power by halting the CPU
- * - called from the idle loop
- * - must reenable interrupts (which takes three instruction cycles to complete)
- */
-#define safe_halt()							\
-do {									\
-	asm volatile("	or	%0,epsw	\n"				\
-		     "	nop		\n"				\
-		     "	nop		\n"				\
-		     "	bset	%2,(%1)	\n"				\
-		     :							\
-		     : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)\
-		     : "cc"						\
-		     );							\
-} while (0)
-
-#define STI	or EPSW_IE|EPSW_IM,epsw
-#define CLI	and ~EPSW_IM,epsw; or EPSW_IE|MN10300_CLI_LEVEL,epsw; nop; nop; nop
-
-/*****************************************************************************/
-/*
  * MN10300 doesn't actually have an exchange instruction
  */
 #ifndef __ASSEMBLY__
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
index d9ed5a1..3d394b4 100644
--- a/arch/mn10300/kernel/entry.S
+++ b/arch/mn10300/kernel/entry.S
@@ -16,6 +16,7 @@
 #include <linux/linkage.h>
 #include <asm/smp.h>
 #include <asm/system.h>
+#include <asm/irqflags.h>
 #include <asm/thread_info.h>
 #include <asm/intctl-regs.h>
 #include <asm/busctl-regs.h>
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c
index 6aea7fd..196a111 100644
--- a/arch/mn10300/kernel/module.c
+++ b/arch/mn10300/kernel/module.c
@@ -206,7 +206,7 @@
 		    const Elf_Shdr *sechdrs,
 		    struct module *me)
 {
-	return module_bug_finalize(hdr, sechdrs, me);
+	return 0;
 }
 
 /*
@@ -214,5 +214,4 @@
  */
 void module_arch_cleanup(struct module *mod)
 {
-	module_bug_cleanup(mod);
 }
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c
index 717db14..d4de05a 100644
--- a/arch/mn10300/kernel/signal.c
+++ b/arch/mn10300/kernel/signal.c
@@ -65,10 +65,10 @@
 		old_sigset_t mask;
 		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
 		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+		    __get_user(mask, &act->sa_mask))
 			return -EFAULT;
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
 		siginitset(&new_ka.sa.sa_mask, mask);
 	}
 
@@ -77,10 +77,10 @@
 	if (!ret && oact) {
 		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
 		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
 			return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
 	}
 
 	return ret;
@@ -102,6 +102,9 @@
 {
 	unsigned int err = 0;
 
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
 	if (is_using_fpu(current))
 		fpu_kill_state(current);
 
@@ -330,8 +333,6 @@
 	regs->d0 = sig;
 	regs->d1 = (unsigned long) &frame->sc;
 
-	set_fs(USER_DS);
-
 	/* the tracer may want to single-step inside the handler */
 	if (test_thread_flag(TIF_SINGLESTEP))
 		ptrace_notify(SIGTRAP);
@@ -345,7 +346,7 @@
 	return 0;
 
 give_sigsegv:
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	return -EFAULT;
 }
 
@@ -413,8 +414,6 @@
 	regs->d0 = sig;
 	regs->d1 = (long) &frame->info;
 
-	set_fs(USER_DS);
-
 	/* the tracer may want to single-step inside the handler */
 	if (test_thread_flag(TIF_SINGLESTEP))
 		ptrace_notify(SIGTRAP);
@@ -428,10 +427,16 @@
 	return 0;
 
 give_sigsegv:
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	return -EFAULT;
 }
 
+static inline void stepback(struct pt_regs *regs)
+{
+	regs->pc -= 2;
+	regs->orig_d0 = -1;
+}
+
 /*
  * handle the actual delivery of a signal to userspace
  */
@@ -459,7 +464,7 @@
 			/* fallthrough */
 		case -ERESTARTNOINTR:
 			regs->d0 = regs->orig_d0;
-			regs->pc -= 2;
+			stepback(regs);
 		}
 	}
 
@@ -527,12 +532,12 @@
 		case -ERESTARTSYS:
 		case -ERESTARTNOINTR:
 			regs->d0 = regs->orig_d0;
-			regs->pc -= 2;
+			stepback(regs);
 			break;
 
 		case -ERESTART_RESTARTBLOCK:
 			regs->d0 = __NR_restart_syscall;
-			regs->pc -= 2;
+			stepback(regs);
 			break;
 		}
 	}
diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile
index 28b9d98..1557277 100644
--- a/arch/mn10300/mm/Makefile
+++ b/arch/mn10300/mm/Makefile
@@ -2,13 +2,11 @@
 # Makefile for the MN10300-specific memory management code
 #
 
+cacheflush-y	:= cache.o cache-mn10300.o
+cacheflush-$(CONFIG_MN10300_CACHE_WBACK) += cache-flush-mn10300.o
+
+cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o
+
 obj-y := \
 	init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \
-	misalignment.o dma-alloc.o
-
-ifneq ($(CONFIG_MN10300_CACHE_DISABLED),y)
-obj-y	+= cache.o cache-mn10300.o
-ifeq ($(CONFIG_MN10300_CACHE_WBACK),y)
-obj-y	+= cache-flush-mn10300.o
-endif
-endif
+	misalignment.o dma-alloc.o $(cacheflush-y)
diff --git a/arch/mn10300/mm/cache-disabled.c b/arch/mn10300/mm/cache-disabled.c
new file mode 100644
index 0000000..f669ea4
--- /dev/null
+++ b/arch/mn10300/mm/cache-disabled.c
@@ -0,0 +1,21 @@
+/* Handle the cache being disabled
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/mm.h>
+
+/*
+ * allow userspace to flush the instruction cache
+ */
+asmlinkage long sys_cacheflush(unsigned long start, unsigned long end)
+{
+	if (end < start)
+		return -EINVAL;
+	return 0;
+}
diff --git a/arch/mn10300/mm/cache.c b/arch/mn10300/mm/cache.c
index 1b76719..9261217 100644
--- a/arch/mn10300/mm/cache.c
+++ b/arch/mn10300/mm/cache.c
@@ -54,13 +54,30 @@
 void flush_icache_range(unsigned long start, unsigned long end)
 {
 #ifdef CONFIG_MN10300_CACHE_WBACK
-	unsigned long addr, size, off;
+	unsigned long addr, size, base, off;
 	struct page *page;
 	pgd_t *pgd;
 	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *ppte, pte;
 
+	if (end > 0x80000000UL) {
+		/* addresses above 0xa0000000 do not go through the cache */
+		if (end > 0xa0000000UL) {
+			end = 0xa0000000UL;
+			if (start >= end)
+				return;
+		}
+
+		/* kernel addresses between 0x80000000 and 0x9fffffff do not
+		 * require page tables, so we just map such addresses directly */
+		base = (start >= 0x80000000UL) ? start : 0x80000000UL;
+		mn10300_dcache_flush_range(base, end);
+		if (base == start)
+			goto invalidate;
+		end = base;
+	}
+
 	for (; start < end; start += size) {
 		/* work out how much of the page to flush */
 		off = start & (PAGE_SIZE - 1);
@@ -104,6 +121,7 @@
 	}
 #endif
 
+invalidate:
 	mn10300_icache_inv();
 }
 EXPORT_SYMBOL(flush_icache_range);
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 907417d..79a04a9 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -16,6 +16,7 @@
 	select RTC_DRV_GENERIC
 	select INIT_ALL_POSSIBLE
 	select BUG
+	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select GENERIC_ATOMIC64 if !64BIT
 	help
diff --git a/arch/parisc/include/asm/irqflags.h b/arch/parisc/include/asm/irqflags.h
new file mode 100644
index 0000000..34f9cb9
--- /dev/null
+++ b/arch/parisc/include/asm/irqflags.h
@@ -0,0 +1,46 @@
+#ifndef __PARISC_IRQFLAGS_H
+#define __PARISC_IRQFLAGS_H
+
+#include <linux/types.h>
+#include <asm/psw.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile("ssm 0, %0" : "=r" (flags) : : "memory");
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	asm volatile("rsm %0,%%r0\n" : : "i" (PSW_I) : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	asm volatile("ssm %0,%%r0\n" : : "i" (PSW_I) : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+	asm volatile("rsm %1,%0" : "=r" (flags) : "i" (PSW_I) : "memory");
+	return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile("mtsm %0" : : "r" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags & PSW_I) == 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __PARISC_IRQFLAGS_H */
diff --git a/arch/parisc/include/asm/perf_event.h b/arch/parisc/include/asm/perf_event.h
index cc146427..1e0fd8b 100644
--- a/arch/parisc/include/asm/perf_event.h
+++ b/arch/parisc/include/asm/perf_event.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_PARISC_PERF_EVENT_H
 #define __ASM_PARISC_PERF_EVENT_H
 
-/* parisc only supports software events through this interface. */
-static inline void set_perf_event_pending(void) { }
+/* Empty, just to avoid compiling error */
 
 #endif /* __ASM_PARISC_PERF_EVENT_H */
diff --git a/arch/parisc/include/asm/system.h b/arch/parisc/include/asm/system.h
index 2ab4af5..b19e63a 100644
--- a/arch/parisc/include/asm/system.h
+++ b/arch/parisc/include/asm/system.h
@@ -1,7 +1,7 @@
 #ifndef __PARISC_SYSTEM_H
 #define __PARISC_SYSTEM_H
 
-#include <asm/psw.h>
+#include <linux/irqflags.h>
 
 /* The program status word as bitfields.  */
 struct pa_psw {
@@ -48,23 +48,6 @@
 	(last) = _switch_to(prev, next);			\
 } while(0)
 
-/* interrupt control */
-#define local_save_flags(x)	__asm__ __volatile__("ssm 0, %0" : "=r" (x) : : "memory")
-#define local_irq_disable()	__asm__ __volatile__("rsm %0,%%r0\n" : : "i" (PSW_I) : "memory" )
-#define local_irq_enable()	__asm__ __volatile__("ssm %0,%%r0\n" : : "i" (PSW_I) : "memory" )
-
-#define local_irq_save(x) \
-	__asm__ __volatile__("rsm %1,%0" : "=r" (x) :"i" (PSW_I) : "memory" )
-#define local_irq_restore(x) \
-	__asm__ __volatile__("mtsm %0" : : "r" (x) : "memory" )
-
-#define irqs_disabled()			\
-({					\
-	unsigned long flags;		\
-	local_save_flags(flags);	\
-	(flags & PSW_I) == 0;		\
-})
-
 #define mfctl(reg)	({		\
 	unsigned long cr;		\
 	__asm__ __volatile__(		\
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index 159a2b8..6e81bb5 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -941,11 +941,10 @@
 	nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
 	DEBUGP("NEW num_symtab %lu\n", nsyms);
 	symhdr->sh_size = nsyms * sizeof(Elf_Sym);
-	return module_bug_finalize(hdr, sechdrs, me);
+	return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
 	deregister_unwind_table(mod);
-	module_bug_cleanup(mod);
 }
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index f9f6783..ba0c053 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -46,7 +46,6 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 
 #include <asm/uaccess.h>
@@ -261,16 +260,13 @@
  */
 static int perf_open(struct inode *inode, struct file *file)
 {
-	lock_kernel();
 	spin_lock(&perf_lock);
 	if (perf_enabled) {
 		spin_unlock(&perf_lock);
-		unlock_kernel();
 		return -EBUSY;
 	}
 	perf_enabled = 1;
  	spin_unlock(&perf_lock);
-	unlock_kernel();
 
 	return 0;
 }
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 631e5a0..4b1e521 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -138,6 +138,7 @@
 	select HAVE_OPROFILE
 	select HAVE_SYSCALL_WRAPPERS if PPC64
 	select GENERIC_ATOMIC64 if PPC32
+	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select HAVE_REGS_AND_STACK_ACCESS_API
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
diff --git a/arch/powerpc/boot/addnote.c b/arch/powerpc/boot/addnote.c
index b1e5611..349b553 100644
--- a/arch/powerpc/boot/addnote.c
+++ b/arch/powerpc/boot/addnote.c
@@ -20,7 +20,7 @@
 #include <string.h>
 
 /* CHRP note section */
-char arch[] = "PowerPC";
+static const char arch[] = "PowerPC";
 
 #define N_DESCR	6
 unsigned int descr[N_DESCR] = {
@@ -33,7 +33,7 @@
 };
 
 /* RPA note section */
-char rpaname[] = "IBM,RPA-Client-Config";
+static const char rpaname[] = "IBM,RPA-Client-Config";
 
 /*
  * Note: setting ignore_my_client_config *should* mean that OF ignores
diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/bluestone.dts
new file mode 100644
index 0000000..9bb3d72
--- /dev/null
+++ b/arch/powerpc/boot/dts/bluestone.dts
@@ -0,0 +1,254 @@
+/*
+ * Device Tree for Bluestone (APM821xx) board.
+ *
+ * Copyright (c) 2010, Applied Micro Circuits Corporation
+ * Author: Tirumala R Marri <tmarri@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
+ *
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	model = "apm,bluestone";
+	compatible = "apm,bluestone";
+	dcr-parent = <&{/cpus/cpu@0}>;
+
+	aliases {
+		ethernet0 = &EMAC0;
+		serial0 = &UART0;
+		serial1 = &UART1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			model = "PowerPC,apm821xx";
+			reg = <0x00000000>;
+			clock-frequency = <0>; /* Filled in by U-Boot */
+			timebase-frequency = <0>; /* Filled in by U-Boot */
+			i-cache-line-size = <32>;
+			d-cache-line-size = <32>;
+			i-cache-size = <32768>;
+			d-cache-size = <32768>;
+			dcr-controller;
+			dcr-access-method = "native";
+			next-level-cache = <&L2C0>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by U-Boot */
+	};
+
+	UIC0: interrupt-controller0 {
+		compatible = "ibm,uic";
+		interrupt-controller;
+		cell-index = <0>;
+		dcr-reg = <0x0c0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+	};
+
+	UIC1: interrupt-controller1 {
+		compatible = "ibm,uic";
+		interrupt-controller;
+		cell-index = <1>;
+		dcr-reg = <0x0d0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	UIC2: interrupt-controller2 {
+		compatible = "ibm,uic";
+		interrupt-controller;
+		cell-index = <2>;
+		dcr-reg = <0x0e0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0xa 0x4 0xb 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	UIC3: interrupt-controller3 {
+		compatible = "ibm,uic";
+		interrupt-controller;
+		cell-index = <3>;
+		dcr-reg = <0x0f0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0x10 0x4 0x11 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	SDR0: sdr {
+		compatible = "ibm,sdr-apm821xx";
+		dcr-reg = <0x00e 0x002>;
+	};
+
+	CPR0: cpr {
+		compatible = "ibm,cpr-apm821xx";
+		dcr-reg = <0x00c 0x002>;
+	};
+
+	plb {
+		compatible = "ibm,plb4";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges;
+		clock-frequency = <0>; /* Filled in by U-Boot */
+
+		SDRAM0: sdram {
+			compatible = "ibm,sdram-apm821xx";
+			dcr-reg = <0x010 0x002>;
+		};
+
+		MAL0: mcmal {
+			compatible = "ibm,mcmal2";
+			descriptor-memory = "ocm";
+			dcr-reg = <0x180 0x062>;
+			num-tx-chans = <1>;
+			num-rx-chans = <1>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-parent = <&UIC2>;
+			interrupts = <	/*TXEOB*/ 0x6 0x4
+					/*RXEOB*/ 0x7 0x4
+					/*SERR*/  0x3 0x4
+					/*TXDE*/  0x4 0x4
+					/*RXDE*/  0x5 0x4
+		};
+
+		POB0: opb {
+			compatible = "ibm,opb";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xb0000000 0x00000004 0xb0000000 0x50000000>;
+			clock-frequency = <0>; /* Filled in by U-Boot */
+
+			EBC0: ebc {
+				compatible = "ibm,ebc";
+				dcr-reg = <0x012 0x002>;
+				#address-cells = <2>;
+				#size-cells = <1>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				/* ranges property is supplied by U-Boot */
+				ranges = < 0x00000003 0x00000000 0xe0000000 0x8000000>;
+				interrupts = <0x6 0x4>;
+				interrupt-parent = <&UIC1>;
+
+				nor_flash@0,0 {
+					compatible = "amd,s29gl512n", "cfi-flash";
+					bank-width = <2>;
+					reg = <0x00000000 0x00000000 0x00400000>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					partition@0 {
+						label = "kernel";
+						reg = <0x00000000 0x00180000>;
+					};
+					partition@180000 {
+						label = "env";
+						reg = <0x00180000 0x00020000>;
+					};
+					partition@1a0000 {
+						label = "u-boot";
+						reg = <0x001a0000 0x00060000>;
+					};
+				};
+			}
+
+			UART0: serial@ef600300 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <0xef600300 0x00000008>;
+				virtual-reg = <0xef600300>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				current-speed = <0>; /* Filled in by U-Boot */
+				interrupt-parent = <&UIC1>;
+				interrupts = <0x1 0x4>;
+			};
+
+			IIC0: i2c@ef600700 {
+				compatible = "ibm,iic";
+				reg = <0xef600700 0x00000014>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <0x2 0x4>;
+			};
+
+			IIC1: i2c@ef600800 {
+				compatible = "ibm,iic";
+				reg = <0xef600800 0x00000014>;
+				interrupt-parent = <&UIC0>;
+				interrupts = <0x3 0x4>;
+			};
+
+			RGMII0: emac-rgmii@ef601500 {
+				compatible = "ibm,rgmii";
+				reg = <0xef601500 0x00000008>;
+				has-mdio;
+			};
+
+			TAH0: emac-tah@ef601350 {
+				compatible = "ibm,tah";
+				reg = <0xef601350 0x00000030>;
+			};
+
+			EMAC0: ethernet@ef600c00 {
+				device_type = "network";
+				compatible = "ibm,emac4sync";
+				interrupt-parent = <&EMAC0>;
+				interrupts = <0x0 0x1>;
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = </*Status*/ 0x0 &UIC2 0x10 0x4
+						 /*Wake*/   0x1 &UIC2 0x14 0x4>;
+				reg = <0xef600c00 0x000000c4>;
+				local-mac-address = [000000000000]; /* Filled in by U-Boot */
+				mal-device = <&MAL0>;
+				mal-tx-channel = <0>;
+				mal-rx-channel = <0>;
+				cell-index = <0>;
+				max-frame-size = <9000>;
+				rx-fifo-size = <16384>;
+				tx-fifo-size = <2048>;
+				phy-mode = "rgmii";
+				phy-map = <0x00000000>;
+				rgmii-device = <&RGMII0>;
+				rgmii-channel = <0>;
+				tah-device = <&TAH0>;
+				tah-channel = <0>;
+				has-inverted-stacr-oc;
+				has-new-stacr-staopc;
+			};
+		};
+
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8308_p1m.dts b/arch/powerpc/boot/dts/mpc8308_p1m.dts
new file mode 100644
index 0000000..05a76cc
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8308_p1m.dts
@@ -0,0 +1,332 @@
+/*
+ * mpc8308_p1m Device Tree Source
+ *
+ * Copyright 2010 Ilya Yanok, Emcraft Systems, yanok@emcraft.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "denx,mpc8308_p1m";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8308@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			d-cache-line-size = <32>;
+			i-cache-line-size = <32>;
+			d-cache-size = <16384>;
+			i-cache-size = <16384>;
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x08000000>;	// 128MB at 0
+	};
+
+	localbus@e0005000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8315-elbc", "fsl,elbc", "simple-bus";
+		reg = <0xe0005000 0x1000>;
+		interrupts = <77 0x8>;
+		interrupt-parent = <&ipic>;
+
+		ranges = <0x0 0x0 0xfc000000 0x04000000
+		          0x1 0x0 0xfbff0000 0x00008000
+		          0x2 0x0 0xfbff8000 0x00008000>;
+
+		flash@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x4000000>;
+			bank-width = <2>;
+			device-width = <1>;
+
+			u-boot@0 {
+				reg = <0x0 0x60000>;
+				read-only;
+			};
+			env@60000 {
+				reg = <0x60000 0x20000>;
+			};
+			env1@80000 {
+				reg = <0x80000 0x20000>;
+			};
+			kernel@a0000 {
+				reg = <0xa0000 0x200000>;
+			};
+			dtb@2a0000 {
+				reg = <0x2a0000 0x20000>;
+			};
+			ramdisk@2c0000 {
+				reg = <0x2c0000 0x640000>;
+			};
+			user@700000 {
+				reg = <0x700000 0x3900000>;
+			};
+		};
+
+		can@1,0 {
+			compatible = "nxp,sja1000";
+			reg = <0x1 0x0 0x80>;
+			interrupts = <18 0x8>;
+			interrups-parent = <&ipic>;
+		};
+
+		cpld@2,0 {
+			compatible = "denx,mpc8308_p1m-cpld";
+			reg = <0x2 0x0 0x8>;
+			interrupts = <48 0x8>;
+			interrups-parent = <&ipic>;
+		};
+	};
+
+	immr@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "fsl,mpc8308-immr", "simple-bus";
+		ranges = <0 0xe0000000 0x00100000>;
+		reg = <0xe0000000 0x00000200>;
+		bus-frequency = <0>;
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <14 0x8>;
+			interrupt-parent = <&ipic>;
+			dfsrr;
+			fram@50 {
+				compatible = "ramtron,24c64";
+				reg = <0x50>;
+			};
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <15 0x8>;
+			interrupt-parent = <&ipic>;
+			dfsrr;
+			pwm@28 {
+				compatible = "maxim,ds1050";
+				reg = <0x28>;
+			};
+			sensor@48 {
+				compatible = "maxim,max6625";
+				reg = <0x48>;
+			};
+			sensor@49 {
+				compatible = "maxim,max6625";
+				reg = <0x49>;
+			};
+			sensor@4b {
+				compatible = "maxim,max6625";
+				reg = <0x4b>;
+			};
+		};
+
+		usb@23000 {
+			compatible = "fsl-usb2-dr";
+			reg = <0x23000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <&ipic>;
+			interrupts = <38 0x8>;
+			dr_mode = "peripheral";
+			phy_type = "ulpi";
+		};
+
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0x24000 0x1000>;
+
+			cell-index = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <32 0x8 33 0x8 34 0x8>;
+			interrupt-parent = <&ipic>;
+			phy-handle = < &phy1 >;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&ipic>;
+					interrupts = <17 0x8>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&ipic>;
+					interrupts = <19 0x8>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <35 0x8 36 0x8 37 0x8>;
+			interrupt-parent = <&ipic>;
+			phy-handle = < &phy2 >;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <133333333>;
+			interrupts = <9 0x8>;
+			interrupt-parent = <&ipic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <133333333>;
+			interrupts = <10 0x8>;
+			interrupt-parent = <&ipic>;
+		};
+
+		gpio@c00 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8308-gpio", "fsl,mpc8349-gpio";
+			reg = <0xc00 0x18>;
+			interrupts = <74 0x8>;
+			interrupt-parent = <&ipic>;
+			gpio-controller;
+		};
+
+		timer@500 {
+			compatible = "fsl,mpc8308-gtm", "fsl,gtm";
+			reg = <0x500 0x100>;
+			interrupts = <90 8 78 8 84 8 72 8>;
+			interrupt-parent = <&ipic>;
+			clock-frequency = <133333333>;
+		};
+
+		/* IPIC
+		 * interrupts cell = <intr #, sense>
+		 * sense values match linux IORESOURCE_IRQ_* defines:
+		 * sense == 8: Level, low assertion
+		 * sense == 2: Edge, high-to-low change
+		 */
+		ipic: interrupt-controller@700 {
+			compatible = "fsl,ipic";
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x700 0x100>;
+			device_type = "ipic";
+		};
+
+		ipic-msi@7c0 {
+			compatible = "fsl,ipic-msi";
+			reg = <0x7c0 0x40>;
+			msi-available-ranges = <0x0 0x100>;
+			interrupts = < 0x43 0x8
+					0x4  0x8
+					0x51 0x8
+					0x52 0x8
+					0x56 0x8
+					0x57 0x8
+					0x58 0x8
+					0x59 0x8 >;
+			interrupt-parent = < &ipic >;
+		};
+
+	};
+
+	pci0: pcie@e0009000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8308-pcie", "fsl,mpc8314-pcie";
+		reg = <0xe0009000 0x00001000
+			0xb0000000 0x01000000>;
+		ranges = <0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
+		          0x01000000 0 0x00000000 0xb1000000 0 0x00800000>;
+		bus-range = <0 0>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &ipic 1 8>;
+		interrupts = <0x1 0x8>;
+		interrupt-parent = <&ipic>;
+		clock-frequency = <0>;
+
+		pcie@0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			reg = <0 0 0 0 0>;
+			ranges = <0x02000000 0 0xa0000000
+				  0x02000000 0 0xa0000000
+				  0 0x10000000
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00800000>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts b/arch/powerpc/boot/dts/mpc8536ds.dts
index 815cebb..a75c10e 100644
--- a/arch/powerpc/boot/dts/mpc8536ds.dts
+++ b/arch/powerpc/boot/dts/mpc8536ds.dts
@@ -108,6 +108,58 @@
 			};
 		};
 
+		spi@7000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc8536-espi";
+			reg = <0x7000 0x1000>;
+			interrupts = <59 0x2>;
+			interrupt-parent = <&mpic>;
+			fsl,espi-num-chipselects = <4>;
+
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,s25sl12801";
+				reg = <0>;
+				spi-max-frequency = <40000000>;
+				partition@u-boot {
+					label = "u-boot";
+					reg = <0x00000000 0x00100000>;
+					read-only;
+				};
+				partition@kernel {
+					label = "kernel";
+					reg = <0x00100000 0x00500000>;
+					read-only;
+				};
+				partition@dtb {
+					label = "dtb";
+					reg = <0x00600000 0x00100000>;
+					read-only;
+				};
+				partition@fs {
+					label = "file system";
+					reg = <0x00700000 0x00900000>;
+				};
+			};
+			flash@1 {
+				compatible = "spansion,s25sl12801";
+				reg = <1>;
+				spi-max-frequency = <40000000>;
+			};
+			flash@2 {
+				compatible = "spansion,s25sl12801";
+				reg = <2>;
+				spi-max-frequency = <40000000>;
+			};
+			flash@3 {
+				compatible = "spansion,s25sl12801";
+				reg = <3>;
+				spi-max-frequency = <40000000>;
+			};
+		};
+
 		dma@21300 {
 			#address-cells = <1>;
 			#size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/p1022ds.dts b/arch/powerpc/boot/dts/p1022ds.dts
index 8bcb10b..2bbecbb 100644
--- a/arch/powerpc/boot/dts/p1022ds.dts
+++ b/arch/powerpc/boot/dts/p1022ds.dts
@@ -148,6 +148,17 @@
 				label = "reserved-nand";
 			};
 		};
+
+		board-control@3,0 {
+			compatible = "fsl,p1022ds-pixis";
+			reg = <3 0 0x30>;
+			interrupt-parent = <&mpic>;
+			/*
+			 * IRQ8 is generated if the "EVENT" switch is pressed
+			 * and PX_CTL[EVESEL] is set to 00.
+			 */
+			interrupts = <8 8>;
+		};
 	};
 
 	soc@fffe00000 {
diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts
index 2f0de24..5b7fc29 100644
--- a/arch/powerpc/boot/dts/p4080ds.dts
+++ b/arch/powerpc/boot/dts/p4080ds.dts
@@ -236,22 +236,19 @@
 		};
 
 		spi@110000 {
-			cell-index = <0>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			compatible = "fsl,espi";
+			compatible = "fsl,p4080-espi", "fsl,mpc8536-espi";
 			reg = <0x110000 0x1000>;
 			interrupts = <53 0x2>;
 			interrupt-parent = <&mpic>;
-			espi,num-ss-bits = <4>;
-			mode = "cpu";
+			fsl,espi-num-chipselects = <4>;
 
-			fsl_m25p80@0 {
+			flash@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "fsl,espi-flash";
+				compatible = "spansion,s25sl12801";
 				reg = <0>;
-				linux,modalias = "fsl_m25p80";
 				spi-max-frequency = <40000000>; /* input clock */
 				partition@u-boot {
 					label = "u-boot";
diff --git a/arch/powerpc/configs/44x/bluestone_defconfig b/arch/powerpc/configs/44x/bluestone_defconfig
new file mode 100644
index 0000000..ac65b48
--- /dev/null
+++ b/arch/powerpc/configs/44x/bluestone_defconfig
@@ -0,0 +1,68 @@
+CONFIG_44x=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_PCI_QUIRKS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BLUESTONE=y
+# CONFIG_EBONY is not set
+# CONFIG_KVM_GUEST is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+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_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_CONNECTOR=y
+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_AMDSTD=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=35000
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=256
+CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_IBM_IIC=y
+CONFIG_SENSORS_AD7414=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_M41T80=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS=y
diff --git a/arch/powerpc/configs/e55xx_smp_defconfig b/arch/powerpc/configs/e55xx_smp_defconfig
new file mode 100644
index 0000000..94d120e
--- /dev/null
+++ b/arch/powerpc/configs/e55xx_smp_defconfig
@@ -0,0 +1,84 @@
+CONFIG_PPC64=y
+CONFIG_PPC_BOOK3E_64=y
+# CONFIG_VIRT_CPU_ACCOUNTING is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_P5020_DS=y
+# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BINFMT_MISC=m
+CONFIG_SPARSE_IRQ=y
+# CONFIG_PCI is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_EEPROM_LEGACY=y
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_I2C=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_DMADEVICES=y
+CONFIG_FSL_DMA=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_UTF8=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
+CONFIG_LIBCRC32C=m
+CONFIG_FRAME_WARN=1024
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_VIRQ_DEBUG=y
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_TALITOS=y
diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig
index cd446fb..2fa05f7 100644
--- a/arch/powerpc/configs/ppc44x_defconfig
+++ b/arch/powerpc/configs/ppc44x_defconfig
@@ -12,6 +12,7 @@
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_BAMBOO=y
+CONFIG_BLUESTONE=y
 CONFIG_SAM440EP=y
 CONFIG_SEQUOIA=y
 CONFIG_TAISHAN=y
@@ -97,14 +98,17 @@
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=m
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_UBIFS_FS=m
 CONFIG_UBIFS_FS_XATTR=y
+CONFIG_LOGFS=m
 CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
@@ -116,11 +120,8 @@
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=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
 CONFIG_VIRTUALIZATION=y
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig
index 04ae074..7bd1763 100644
--- a/arch/powerpc/configs/ppc64e_defconfig
+++ b/arch/powerpc/configs/ppc64e_defconfig
@@ -18,6 +18,7 @@
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_P5020_DS=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -256,7 +257,6 @@
 CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
 # CONFIG_USB_EHCI_HCD_PPC_OF is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_STORAGE=m
@@ -290,7 +290,6 @@
 CONFIG_JFS_SECURITY=y
 CONFIG_XFS_FS=m
 CONFIG_XFS_POSIX_ACL=y
-CONFIG_INOTIFY=y
 CONFIG_AUTOFS4_FS=m
 CONFIG_ISO9660_FS=y
 CONFIG_UDF_FS=m
@@ -384,7 +383,6 @@
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_KHAZAD=m
diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h
index 7cdf358..ce0c284 100644
--- a/arch/powerpc/include/asm/checksum.h
+++ b/arch/powerpc/include/asm/checksum.h
@@ -52,12 +52,22 @@
 extern __wsum csum_partial_copy_generic(const void *src, void *dst,
 					      int len, __wsum sum,
 					      int *src_err, int *dst_err);
+
+#ifdef __powerpc64__
+#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
+extern __wsum csum_and_copy_from_user(const void __user *src, void *dst,
+				      int len, __wsum sum, int *err_ptr);
+#define HAVE_CSUM_COPY_USER
+extern __wsum csum_and_copy_to_user(const void *src, void __user *dst,
+				    int len, __wsum sum, int *err_ptr);
+#else
 /*
  * the same as csum_partial, but copies from src to dst while it
  * checksums.
  */
 #define csum_partial_copy_from_user(src, dst, len, sum, errp)   \
         csum_partial_copy_generic((__force const void *)(src), (dst), (len), (sum), (errp), NULL)
+#endif
 
 #define csum_partial_copy_nocheck(src, dst, len, sum)   \
         csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index a11d4ea..2296112 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -143,7 +143,7 @@
 	 * We cant access below the stack pointer in the 32bit ABI and
 	 * can access 288 bytes in the 64bit ABI
 	 */
-	if (!(test_thread_flag(TIF_32BIT)))
+	if (!is_32bit_task())
 		usp -= 288;
 
 	return (void __user *) (usp - len);
@@ -213,7 +213,7 @@
 
 static inline int is_compat_task(void)
 {
-	return test_thread_flag(TIF_32BIT);
+	return is_32bit_task();
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 3a40a99..f3a1fdd 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -198,6 +198,7 @@
 #define CPU_FTR_CP_USE_DCBTZ		LONG_ASM_CONST(0x0040000000000000)
 #define CPU_FTR_UNALIGNED_LD_STD	LONG_ASM_CONST(0x0080000000000000)
 #define CPU_FTR_ASYM_SMT		LONG_ASM_CONST(0x0100000000000000)
+#define CPU_FTR_STCX_CHECKS_ADDRESS	LONG_ASM_CONST(0x0200000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -392,28 +393,31 @@
 	    CPU_FTR_MMCRA | CPU_FTR_CTRL)
 #define CPU_FTRS_POWER4	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
-	    CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ)
+	    CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \
+	    CPU_FTR_STCX_CHECKS_ADDRESS)
 #define CPU_FTRS_PPC970	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA | \
-	    CPU_FTR_CP_USE_DCBTZ)
+	    CPU_FTR_CP_USE_DCBTZ | CPU_FTR_STCX_CHECKS_ADDRESS)
 #define CPU_FTRS_POWER5	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
-	    CPU_FTR_PURR)
+	    CPU_FTR_PURR | CPU_FTR_STCX_CHECKS_ADDRESS)
 #define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
-	    CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD)
+	    CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \
+	    CPU_FTR_STCX_CHECKS_ADDRESS)
 #define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
-	    CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT)
+	    CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT | \
+	    CPU_FTR_STCX_CHECKS_ADDRESS)
 #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 8c9c6ad..6d2416a 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -127,19 +127,7 @@
 	return dma_ops->dma_supported(dev, mask);
 }
 
-static inline int dma_set_mask(struct device *dev, u64 dma_mask)
-{
-	struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
-	if (unlikely(dma_ops == NULL))
-		return -EIO;
-	if (dma_ops->set_dma_mask != NULL)
-		return dma_ops->set_dma_mask(dev, dma_mask);
-	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
-		return -EIO;
-	*dev->dma_mask = dma_mask;
-	return 0;
-}
+extern int dma_set_mask(struct device *dev, u64 dma_mask);
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
 				       dma_addr_t *dma_handle, gfp_t flag)
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index c376eda..2b917c6 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -250,7 +250,7 @@
  * the 64bit ABI has never had these issues dont enable the workaround
  * even if we have an executable stack.
  */
-# define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \
+# define elf_read_implies_exec(ex, exec_stk) (is_32bit_task() ? \
 		(exec_stk == EXSTACK_DEFAULT) : 0)
 #else 
 # define SET_PERSONALITY(ex) \
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index 57c4000..7778d6f 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -137,7 +137,8 @@
 	li	r10,0;							   \
 	ld	r11,exception_marker@toc(r2);				   \
 	std	r10,RESULT(r1);		/* clear regs->result		*/ \
-	std	r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame	*/
+	std	r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame	*/ \
+	ACCOUNT_STOLEN_TIME
 
 /*
  * Exception vectors.
diff --git a/arch/powerpc/include/asm/fsl_85xx_cache_sram.h b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h
new file mode 100644
index 0000000..2af2bdc
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * Cache SRAM handling for QorIQ platform
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+
+ * This file is derived from the original work done
+ * by Sylvain Munaut for the Bestcomm SRAM allocator.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__
+#define __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__
+
+#include <asm/rheap.h>
+#include <linux/spinlock.h>
+
+/*
+ * Cache-SRAM
+ */
+
+struct mpc85xx_cache_sram {
+	phys_addr_t base_phys;
+	void *base_virt;
+	unsigned int size;
+	rh_info_t *rh;
+	spinlock_t lock;
+};
+
+extern void mpc85xx_cache_sram_free(void *ptr);
+extern void *mpc85xx_cache_sram_alloc(unsigned int size,
+				  phys_addr_t *phys, unsigned int align);
+
+#endif /* __AMS_POWERPC_FSL_85XX_CACHE_SRAM_H__ */
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index bd100fc..ff08b70 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -16,42 +16,57 @@
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 
-static inline unsigned long local_get_flags(void)
+static inline unsigned long arch_local_save_flags(void)
 {
 	unsigned long flags;
 
-	__asm__ __volatile__("lbz %0,%1(13)"
-	: "=r" (flags)
-	: "i" (offsetof(struct paca_struct, soft_enabled)));
+	asm volatile(
+		"lbz %0,%1(13)"
+		: "=r" (flags)
+		: "i" (offsetof(struct paca_struct, soft_enabled)));
 
 	return flags;
 }
 
-static inline unsigned long raw_local_irq_disable(void)
+static inline unsigned long arch_local_irq_disable(void)
 {
 	unsigned long flags, zero;
 
-	__asm__ __volatile__("li %1,0; lbz %0,%2(13); stb %1,%2(13)"
-	: "=r" (flags), "=&r" (zero)
-	: "i" (offsetof(struct paca_struct, soft_enabled))
-	: "memory");
+	asm volatile(
+		"li %1,0; lbz %0,%2(13); stb %1,%2(13)"
+		: "=r" (flags), "=&r" (zero)
+		: "i" (offsetof(struct paca_struct, soft_enabled))
+		: "memory");
 
 	return flags;
 }
 
-extern void raw_local_irq_restore(unsigned long);
+extern void arch_local_irq_restore(unsigned long);
 extern void iseries_handle_interrupts(void);
 
-#define raw_local_irq_enable()		raw_local_irq_restore(1)
-#define raw_local_save_flags(flags)	((flags) = local_get_flags())
-#define raw_local_irq_save(flags)	((flags) = raw_local_irq_disable())
+static inline void arch_local_irq_enable(void)
+{
+	arch_local_irq_restore(1);
+}
 
-#define raw_irqs_disabled()		(local_get_flags() == 0)
-#define raw_irqs_disabled_flags(flags)	((flags) == 0)
+static inline unsigned long arch_local_irq_save(void)
+{
+	return arch_local_irq_disable();
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return flags == 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
 
 #ifdef CONFIG_PPC_BOOK3E
-#define __hard_irq_enable()	__asm__ __volatile__("wrteei 1": : :"memory");
-#define __hard_irq_disable()	__asm__ __volatile__("wrteei 0": : :"memory");
+#define __hard_irq_enable()	asm volatile("wrteei 1" : : : "memory");
+#define __hard_irq_disable()	asm volatile("wrteei 0" : : : "memory");
 #else
 #define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
 #define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
@@ -64,64 +79,66 @@
 		get_paca()->hard_enabled = 0;	\
 	} while(0)
 
-#else
+#else /* CONFIG_PPC64 */
 
-#if defined(CONFIG_BOOKE)
 #define SET_MSR_EE(x)	mtmsr(x)
-#define raw_local_irq_restore(flags)	__asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
-#else
-#define SET_MSR_EE(x)	mtmsr(x)
-#define raw_local_irq_restore(flags)	mtmsr(flags)
-#endif
 
-static inline void raw_local_irq_disable(void)
+static inline unsigned long arch_local_save_flags(void)
 {
-#ifdef CONFIG_BOOKE
-	__asm__ __volatile__("wrteei 0": : :"memory");
-#else
-	unsigned long msr;
+	return mfmsr();
+}
 
-	msr = mfmsr();
-	SET_MSR_EE(msr & ~MSR_EE);
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+#if defined(CONFIG_BOOKE)
+	asm volatile("wrtee %0" : : "r" (flags) : "memory");
+#else
+	mtmsr(flags);
 #endif
 }
 
-static inline void raw_local_irq_enable(void)
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags = arch_local_save_flags();
+#ifdef CONFIG_BOOKE
+	asm volatile("wrteei 0" : : : "memory");
+#else
+	SET_MSR_EE(flags & ~MSR_EE);
+#endif
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
 {
 #ifdef CONFIG_BOOKE
-	__asm__ __volatile__("wrteei 1": : :"memory");
+	asm volatile("wrteei 0" : : : "memory");
 #else
-	unsigned long msr;
+	arch_local_irq_save();
+#endif
+}
 
-	msr = mfmsr();
+static inline void arch_local_irq_enable(void)
+{
+#ifdef CONFIG_BOOKE
+	asm volatile("wrteei 1" : : : "memory");
+#else
+	unsigned long msr = mfmsr();
 	SET_MSR_EE(msr | MSR_EE);
 #endif
 }
 
-static inline void raw_local_irq_save_ptr(unsigned long *flags)
-{
-	unsigned long msr;
-	msr = mfmsr();
-	*flags = msr;
-#ifdef CONFIG_BOOKE
-	__asm__ __volatile__("wrteei 0": : :"memory");
-#else
-	SET_MSR_EE(msr & ~MSR_EE);
-#endif
-}
-
-#define raw_local_save_flags(flags)	((flags) = mfmsr())
-#define raw_local_irq_save(flags)	raw_local_irq_save_ptr(&flags)
-#define raw_irqs_disabled()		((mfmsr() & MSR_EE) == 0)
-#define raw_irqs_disabled_flags(flags)	(((flags) & MSR_EE) == 0)
-
-#define hard_irq_disable()		raw_local_irq_disable()
-
-static inline int irqs_disabled_flags(unsigned long flags)
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
 {
 	return (flags & MSR_EE) == 0;
 }
 
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#define hard_irq_disable()		arch_local_irq_disable()
+
 #endif /* CONFIG_PPC64 */
 
 /*
diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h
index 5f68ecf..b85d8dd 100644
--- a/arch/powerpc/include/asm/irqflags.h
+++ b/arch/powerpc/include/asm/irqflags.h
@@ -6,7 +6,7 @@
 
 #ifndef __ASSEMBLY__
 /*
- * Get definitions for raw_local_save_flags(x), etc.
+ * Get definitions for arch_local_save_flags(x), etc.
  */
 #include <asm/hw_irq.h>
 
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index 076327f..f54408d 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -91,6 +91,7 @@
 extern void crash_kexec_secondary(struct pt_regs *regs);
 extern int overlaps_crashkernel(unsigned long start, unsigned long size);
 extern void reserve_crashkernel(void);
+extern void machine_kexec_mask_interrupts(void);
 
 #else /* !CONFIG_KEXEC */
 static inline int kexec_sr_activated(int cpu) { return 0; }
diff --git a/arch/powerpc/include/asm/kvm_fpu.h b/arch/powerpc/include/asm/kvm_fpu.h
index c3d4f05..92daae1 100644
--- a/arch/powerpc/include/asm/kvm_fpu.h
+++ b/arch/powerpc/include/asm/kvm_fpu.h
@@ -82,7 +82,7 @@
 FPD_THREE_IN(fnmsub)
 FPD_THREE_IN(fnmadd)
 
-extern void kvm_cvt_fd(u32 *from, u64 *to, u64 *fpscr);
-extern void kvm_cvt_df(u64 *from, u32 *to, u64 *fpscr);
+extern void kvm_cvt_fd(u32 *from, u64 *to);
+extern void kvm_cvt_df(u64 *from, u32 *to);
 
 #endif
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h
index 14b592d..7f5e0fe 100644
--- a/arch/powerpc/include/asm/lppaca.h
+++ b/arch/powerpc/include/asm/lppaca.h
@@ -153,6 +153,8 @@
 
 extern struct lppaca lppaca[];
 
+#define lppaca_of(cpu)	(*paca[cpu].lppaca_ptr)
+
 /*
  * SLB shadow buffer structure as defined in the PAPR.  The save_area
  * contains adjacent ESID and VSID pairs for each shadowed SLB.  The
@@ -170,6 +172,33 @@
 
 extern struct slb_shadow slb_shadow[];
 
+/*
+ * Layout of entries in the hypervisor's dispatch trace log buffer.
+ */
+struct dtl_entry {
+	u8	dispatch_reason;
+	u8	preempt_reason;
+	u16	processor_id;
+	u32	enqueue_to_dispatch_time;
+	u32	ready_to_enqueue_time;
+	u32	waiting_to_ready_time;
+	u64	timebase;
+	u64	fault_addr;
+	u64	srr0;
+	u64	srr1;
+};
+
+#define DISPATCH_LOG_BYTES	4096	/* bytes per cpu */
+#define N_DISPATCH_LOG		(DISPATCH_LOG_BYTES / sizeof(struct dtl_entry))
+
+/*
+ * When CONFIG_VIRT_CPU_ACCOUNTING = y, the cpu accounting code controls
+ * reading from the dispatch trace log.  If other code wants to consume
+ * DTL entries, it can set this pointer to a function that will get
+ * called once for each DTL entry that gets processed.
+ */
+extern void (*dtl_consumer)(struct dtl_entry *entry, u64 index);
+
 #endif /* CONFIG_PPC_BOOK3S */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_LPPACA_H */
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index adc8e6c..d045b01 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -102,6 +102,9 @@
 	void		(*pci_dma_dev_setup)(struct pci_dev *dev);
 	void		(*pci_dma_bus_setup)(struct pci_bus *bus);
 
+	/* Platform set_dma_mask override */
+	int		(*dma_set_mask)(struct device *dev, u64 dma_mask);
+
 	int		(*probe)(void);
 	void		(*setup_arch)(void); /* Optional, may be NULL */
 	void		(*init_early)(void);
diff --git a/arch/powerpc/include/asm/memblock.h b/arch/powerpc/include/asm/memblock.h
index 3c29728..43efc34 100644
--- a/arch/powerpc/include/asm/memblock.h
+++ b/arch/powerpc/include/asm/memblock.h
@@ -5,11 +5,4 @@
 
 #define MEMBLOCK_DBG(fmt...) udbg_printf(fmt)
 
-#ifdef CONFIG_PPC32
-extern phys_addr_t lowmem_end_addr;
-#define MEMBLOCK_REAL_LIMIT	lowmem_end_addr
-#else
-#define MEMBLOCK_REAL_LIMIT	0
-#endif
-
 #endif /* _ASM_POWERPC_MEMBLOCK_H */
diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h
index 87a1d78..8eaed81 100644
--- a/arch/powerpc/include/asm/mmu-book3e.h
+++ b/arch/powerpc/include/asm/mmu-book3e.h
@@ -114,6 +114,17 @@
 
 #define MAS7_RPN		0xFFFFFFFF
 
+/* Bit definitions for MMUCFG */
+#define MMUCFG_MAVN	0x00000003	/* MMU Architecture Version Number */
+#define MMUCFG_MAVN_V1	0x00000000	/* v1.0 */
+#define MMUCFG_MAVN_V2	0x00000001	/* v2.0 */
+#define MMUCFG_NTLBS	0x0000000c	/* Number of TLBs */
+#define MMUCFG_PIDSIZE	0x000007c0	/* PID Reg Size */
+#define MMUCFG_TWC	0x00008000	/* TLB Write Conditional (v2.0) */
+#define MMUCFG_LRAT	0x00010000	/* LRAT Supported (v2.0) */
+#define MMUCFG_RASIZE	0x00fe0000	/* Real Addr Size */
+#define MMUCFG_LPIDSIZE	0x0f000000	/* LPID Reg Size */
+
 /* Bit definitions for MMUCSR0 */
 #define MMUCSR0_TLB1FI	0x00000002	/* TLB1 Flash invalidate */
 #define MMUCSR0_TLB0FI	0x00000004	/* TLB0 Flash invalidate */
@@ -133,6 +144,10 @@
 #define TLBnCFG_GTWE		0x00010000	/* Guest can write */
 #define TLBnCFG_IND		0x00020000	/* IND entries supported */
 #define TLBnCFG_PT		0x00040000	/* Can load from page table */
+#define TLBnCFG_MINSIZE		0x00f00000	/* Minimum Page Size (v1.0) */
+#define TLBnCFG_MINSIZE_SHIFT	20
+#define TLBnCFG_MAXSIZE		0x000f0000	/* Maximum Page Size (v1.0) */
+#define TLBnCFG_MAXSIZE_SHIFT	16
 #define TLBnCFG_ASSOC		0xff000000	/* Associativity */
 
 /* TLBnPS encoding */
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 7ebf42e..bb40a06 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -2,6 +2,8 @@
 #define _ASM_POWERPC_MMU_H_
 #ifdef __KERNEL__
 
+#include <linux/types.h>
+
 #include <asm/asm-compat.h>
 #include <asm/feature-fixups.h>
 
@@ -82,6 +84,16 @@
 extern void early_init_mmu(void);
 extern void early_init_mmu_secondary(void);
 
+extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+				       phys_addr_t first_memblock_size);
+
+#ifdef CONFIG_PPC64
+/* This is our real memory area size on ppc64 server, on embedded, we
+ * make it match the size our of bolted TLB area
+ */
+extern u64 ppc64_rma_size;
+#endif /* CONFIG_PPC64 */
+
 #endif /* !__ASSEMBLY__ */
 
 /* The kernel use the constants below to index in the page sizes array.
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 1ff6662..ec57540 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -85,6 +85,8 @@
 	u8 kexec_state;		/* set when kexec down has irqs off */
 #ifdef CONFIG_PPC_STD_MMU_64
 	struct slb_shadow *slb_shadow_ptr;
+	struct dtl_entry *dispatch_log;
+	struct dtl_entry *dispatch_log_end;
 
 	/*
 	 * Now, starting in cacheline 2, the exception save areas
@@ -129,13 +131,19 @@
 	u8 soft_enabled;		/* irq soft-enable flag */
 	u8 hard_enabled;		/* set if irqs are enabled in MSR */
 	u8 io_sync;			/* writel() needs spin_unlock sync */
-	u8 perf_event_pending;		/* PM interrupt while soft-disabled */
+	u8 irq_work_pending;		/* IRQ_WORK interrupt while soft-disable */
 
 	/* Stuff for accurate time accounting */
 	u64 user_time;			/* accumulated usermode TB ticks */
 	u64 system_time;		/* accumulated system TB ticks */
-	u64 startpurr;			/* PURR/TB value snapshot */
+	u64 user_time_scaled;		/* accumulated usermode SPURR ticks */
+	u64 starttime;			/* TB value snapshot */
+	u64 starttime_user;		/* TB value on exit to usermode */
 	u64 startspurr;			/* SPURR value snapshot */
+	u64 utime_sspurr;		/* ->user_time when ->startspurr set */
+	u64 stolen_time;		/* TB ticks taken by hypervisor */
+	u64 dtl_ridx;			/* read index in dispatch log */
+	struct dtl_entry *dtl_curr;	/* pointer corresponding to dtl_ridx */
 
 #ifdef CONFIG_KVM_BOOK3S_HANDLER
 	/* We use this to store guest state in */
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h
index 358ff14..932f88d 100644
--- a/arch/powerpc/include/asm/page_64.h
+++ b/arch/powerpc/include/asm/page_64.h
@@ -163,7 +163,7 @@
 #endif /* !CONFIG_HUGETLB_PAGE */
 
 #define VM_DATA_DEFAULT_FLAGS \
-	(test_thread_flag(TIF_32BIT) ? \
+	(is_32bit_task() ? \
 	 VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64)
 
 /*
@@ -179,7 +179,7 @@
 					 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #define VM_STACK_DEFAULT_FLAGS \
-	(test_thread_flag(TIF_32BIT) ? \
+	(is_32bit_task() ? \
 	 VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
 
 #include <asm-generic/getorder.h>
diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h
index 42fdff0..43268f1 100644
--- a/arch/powerpc/include/asm/ppc-pci.h
+++ b/arch/powerpc/include/asm/ppc-pci.h
@@ -28,8 +28,8 @@
 extern struct pci_dev *isa_bridge_pcidev;	/* may be NULL if no ISA bus */
 
 /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
-#define BUID_HI(buid) ((buid) >> 32)
-#define BUID_LO(buid) ((buid) & 0xffffffff)
+#define BUID_HI(buid) upper_32_bits(buid)
+#define BUID_LO(buid) lower_32_bits(buid)
 
 /* PCI device_node operations */
 struct device_node;
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 498fe09..9821006 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/asm-compat.h>
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
+#include <asm/firmware.h>
 
 #ifndef __ASSEMBLY__
 #error __FILE__ should only be used in assembler files
@@ -26,17 +27,13 @@
 #ifndef CONFIG_VIRT_CPU_ACCOUNTING
 #define ACCOUNT_CPU_USER_ENTRY(ra, rb)
 #define ACCOUNT_CPU_USER_EXIT(ra, rb)
+#define ACCOUNT_STOLEN_TIME
 #else
 #define ACCOUNT_CPU_USER_ENTRY(ra, rb)					\
 	beq	2f;			/* if from kernel mode */	\
-BEGIN_FTR_SECTION;							\
-	mfspr	ra,SPRN_PURR;		/* get processor util. reg */	\
-END_FTR_SECTION_IFSET(CPU_FTR_PURR);					\
-BEGIN_FTR_SECTION;							\
-	MFTB(ra);			/* or get TB if no PURR */	\
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR);					\
-	ld	rb,PACA_STARTPURR(r13);					\
-	std	ra,PACA_STARTPURR(r13);					\
+	MFTB(ra);			/* get timebase */		\
+	ld	rb,PACA_STARTTIME_USER(r13);				\
+	std	ra,PACA_STARTTIME(r13);					\
 	subf	rb,rb,ra;		/* subtract start value */	\
 	ld	ra,PACA_USER_TIME(r13);					\
 	add	ra,ra,rb;		/* add on to user time */	\
@@ -44,19 +41,34 @@
 2:
 
 #define ACCOUNT_CPU_USER_EXIT(ra, rb)					\
-BEGIN_FTR_SECTION;							\
-	mfspr	ra,SPRN_PURR;		/* get processor util. reg */	\
-END_FTR_SECTION_IFSET(CPU_FTR_PURR);					\
-BEGIN_FTR_SECTION;							\
-	MFTB(ra);			/* or get TB if no PURR */	\
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR);					\
-	ld	rb,PACA_STARTPURR(r13);					\
-	std	ra,PACA_STARTPURR(r13);					\
+	MFTB(ra);			/* get timebase */		\
+	ld	rb,PACA_STARTTIME(r13);					\
+	std	ra,PACA_STARTTIME_USER(r13);				\
 	subf	rb,rb,ra;		/* subtract start value */	\
 	ld	ra,PACA_SYSTEM_TIME(r13);				\
-	add	ra,ra,rb;		/* add on to user time */	\
-	std	ra,PACA_SYSTEM_TIME(r13);
-#endif
+	add	ra,ra,rb;		/* add on to system time */	\
+	std	ra,PACA_SYSTEM_TIME(r13)
+
+#ifdef CONFIG_PPC_SPLPAR
+#define ACCOUNT_STOLEN_TIME						\
+BEGIN_FW_FTR_SECTION;							\
+	beq	33f;							\
+	/* from user - see if there are any DTL entries to process */	\
+	ld	r10,PACALPPACAPTR(r13);	/* get ptr to VPA */		\
+	ld	r11,PACA_DTL_RIDX(r13);	/* get log read index */	\
+	ld	r10,LPPACA_DTLIDX(r10);	/* get log write index */	\
+	cmpd	cr1,r11,r10;						\
+	beq+	cr1,33f;						\
+	bl	.accumulate_stolen_time;				\
+33:									\
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
+
+#else  /* CONFIG_PPC_SPLPAR */
+#define ACCOUNT_STOLEN_TIME
+
+#endif /* CONFIG_PPC_SPLPAR */
+
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
 
 /*
  * Macros for storing registers into and loading registers from
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 19c05b0..4c14187 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -118,7 +118,7 @@
 #define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4))
 #define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_USER64 / 4))
 
-#define TASK_UNMAPPED_BASE ((test_thread_flag(TIF_32BIT)) ? \
+#define TASK_UNMAPPED_BASE ((is_32bit_task()) ? \
 		TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 )
 #endif
 
@@ -128,7 +128,7 @@
 #define STACK_TOP_USER64 TASK_SIZE_USER64
 #define STACK_TOP_USER32 TASK_SIZE_USER32
 
-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
+#define STACK_TOP (is_32bit_task() ? \
 		   STACK_TOP_USER32 : STACK_TOP_USER64)
 
 #define STACK_TOP_MAX STACK_TOP_USER64
diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h
index f2b3701..76bb195 100644
--- a/arch/powerpc/include/asm/pte-common.h
+++ b/arch/powerpc/include/asm/pte-common.h
@@ -171,6 +171,13 @@
 /* Make modules code happy. We don't set RO yet */
 #define PAGE_KERNEL_EXEC	PAGE_KERNEL_X
 
+/*
+ * Don't just check for any non zero bits in __PAGE_USER, since for book3e
+ * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in
+ * _PAGE_USER.  Need to explictly match _PAGE_BAP_UR bit in that case too.
+ */
+#define pte_user(val)		((val & _PAGE_USER) == _PAGE_USER)
+
 /* Advertise special mapping type for AGP */
 #define PAGE_AGP		(PAGE_KERNEL_NC)
 #define HAVE_PAGE_AGP
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index 3d35f8a..9a1193e 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -187,6 +187,7 @@
 extern void rtas_initialize(void);
 extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data);
 extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data);
+extern int rtas_ibm_suspend_me(struct rtas_args *);
 
 struct rtc_time;
 extern unsigned long rtas_get_boot_time(void);
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index 3d21266..aa0f1eb 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -329,3 +329,22 @@
 SYSCALL(fanotify_init)
 COMPAT_SYS(fanotify_mark)
 SYSCALL_SPU(prlimit64)
+SYSCALL_SPU(socket)
+SYSCALL_SPU(bind)
+SYSCALL_SPU(connect)
+SYSCALL_SPU(listen)
+SYSCALL_SPU(accept)
+SYSCALL_SPU(getsockname)
+SYSCALL_SPU(getpeername)
+SYSCALL_SPU(socketpair)
+SYSCALL_SPU(send)
+SYSCALL_SPU(sendto)
+COMPAT_SYS_SPU(recv)
+COMPAT_SYS_SPU(recvfrom)
+SYSCALL_SPU(shutdown)
+COMPAT_SYS_SPU(setsockopt)
+COMPAT_SYS_SPU(getsockopt)
+COMPAT_SYS_SPU(sendmsg)
+COMPAT_SYS_SPU(recvmsg)
+COMPAT_SYS_SPU(recvmmsg)
+SYSCALL_SPU(accept4)
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
index 6c294ac..5e474dd 100644
--- a/arch/powerpc/include/asm/system.h
+++ b/arch/powerpc/include/asm/system.h
@@ -154,8 +154,8 @@
 extern void giveup_spe(struct task_struct *);
 extern void load_up_spe(struct task_struct *);
 extern int fix_alignment(struct pt_regs *);
-extern void cvt_fd(float *from, double *to, struct thread_struct *thread);
-extern void cvt_df(double *from, float *to, struct thread_struct *thread);
+extern void cvt_fd(float *from, double *to);
+extern void cvt_df(double *from, float *to);
 
 #ifndef CONFIG_SMP
 extern void discard_lazy_cpu_state(void);
@@ -542,10 +542,6 @@
 
 #define PTRRELOC(x)	((typeof(x)) add_reloc_offset((unsigned long)(x)))
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void account_system_vtime(struct task_struct *);
-#endif
-
 extern struct dentry *powerpc_debugfs_root;
 
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h
index dc779df..fe6f7c2 100644
--- a/arch/powerpc/include/asm/time.h
+++ b/arch/powerpc/include/asm/time.h
@@ -34,7 +34,6 @@
 extern void GregorianDay(struct rtc_time *tm);
 
 extern void generic_calibrate_decr(void);
-extern void snapshot_timebase(void);
 
 extern void set_dec_cpu6(unsigned int val);
 
@@ -212,12 +211,8 @@
 DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
 
 #if defined(CONFIG_VIRT_CPU_ACCOUNTING)
-extern void calculate_steal_time(void);
-extern void snapshot_timebases(void);
 #define account_process_vtime(tsk)		account_process_tick(tsk, 0)
 #else
-#define calculate_steal_time()			do { } while (0)
-#define snapshot_timebases()			do { } while (0)
 #define account_process_vtime(tsk)		do { } while (0)
 #endif
 
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index 597e6f9..6151937 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -348,10 +348,29 @@
 #define __NR_fanotify_init	323
 #define __NR_fanotify_mark	324
 #define __NR_prlimit64		325
+#define __NR_socket		326
+#define __NR_bind		327
+#define __NR_connect		328
+#define __NR_listen		329
+#define __NR_accept		330
+#define __NR_getsockname	331
+#define __NR_getpeername	332
+#define __NR_socketpair		333
+#define __NR_send		334
+#define __NR_sendto		335
+#define __NR_recv		336
+#define __NR_recvfrom		337
+#define __NR_shutdown		338
+#define __NR_setsockopt		339
+#define __NR_getsockopt		340
+#define __NR_sendmsg		341
+#define __NR_recvmsg		342
+#define __NR_recvmmsg		343
+#define __NR_accept4		344
 
 #ifdef __KERNEL__
 
-#define __NR_syscalls		326
+#define __NR_syscalls		345
 
 #define __NR__exit __NR_exit
 #define NR_syscalls	__NR_syscalls
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 1dda701..4ed076a 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -55,7 +55,9 @@
 obj-$(CONFIG_IBMEBUS)           += ibmebus.o
 obj-$(CONFIG_GENERIC_TBSYNC)	+= smp-tbsync.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
+ifeq ($(CONFIG_PPC32),y)
 obj-$(CONFIG_E500)		+= idle_e500.o
+endif
 obj-$(CONFIG_6xx)		+= idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
 obj-$(CONFIG_TAU)		+= tau_6xx.o
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o suspend.o
@@ -67,7 +69,7 @@
 obj64-$(CONFIG_HIBERNATION)	+= swsusp_asm64.o
 obj-$(CONFIG_MODULES)		+= module.o module_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_44x)		+= cpu_setup_44x.o
-obj-$(CONFIG_FSL_BOOKE)		+= cpu_setup_fsl_booke.o dbell.o
+obj-$(CONFIG_PPC_FSL_BOOK3E)	+= cpu_setup_fsl_booke.o dbell.o
 obj-$(CONFIG_PPC_BOOK3E_64)	+= dbell.o
 
 extra-y				:= head_$(CONFIG_WORD_SIZE).o
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index b876e989..8184ee9 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -889,7 +889,7 @@
 #ifdef CONFIG_PPC_FPU
 			preempt_disable();
 			enable_kernel_fp();
-			cvt_df(&data.dd, (float *)&data.v[4], &current->thread);
+			cvt_df(&data.dd, (float *)&data.v[4]);
 			preempt_enable();
 #else
 			return 0;
@@ -933,7 +933,7 @@
 #ifdef CONFIG_PPC_FPU
 		preempt_disable();
 		enable_kernel_fp();
-		cvt_fd((float *)&data.v[4], &data.dd, &current->thread);
+		cvt_fd((float *)&data.v[4], &data.dd);
 		preempt_enable();
 #else
 		return 0;
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 1c0607d..c3e0194 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -61,7 +61,7 @@
 #endif
 #endif
 
-#if defined(CONFIG_FSL_BOOKE)
+#if defined(CONFIG_PPC_FSL_BOOK3E)
 #include "../mm/mmu_decl.h"
 #endif
 
@@ -181,17 +181,19 @@
 	       offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));
 	DEFINE(SLBSHADOW_STACKESID,
 	       offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid));
+	DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area));
 	DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0));
 	DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1));
 	DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int));
 	DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int));
-	DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area));
+	DEFINE(LPPACA_DTLIDX, offsetof(struct lppaca, dtl_idx));
+	DEFINE(PACA_DTL_RIDX, offsetof(struct paca_struct, dtl_ridx));
 #endif /* CONFIG_PPC_STD_MMU_64 */
 	DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
 	DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
 	DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
-	DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr));
-	DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr));
+	DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime));
+	DEFINE(PACA_STARTTIME_USER, offsetof(struct paca_struct, starttime_user));
 	DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
 	DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
 	DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
@@ -468,7 +470,7 @@
 	DEFINE(PGD_T_LOG2, PGD_T_LOG2);
 	DEFINE(PTE_T_LOG2, PTE_T_LOG2);
 #endif
-#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_PPC_FSL_BOOK3E
 	DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam));
 	DEFINE(TLBCAM_MAS0, offsetof(struct tlbcam, MAS0));
 	DEFINE(TLBCAM_MAS1, offsetof(struct tlbcam, MAS1));
diff --git a/arch/powerpc/kernel/cpu_setup_44x.S b/arch/powerpc/kernel/cpu_setup_44x.S
index 7d606f8..e32b4a9 100644
--- a/arch/powerpc/kernel/cpu_setup_44x.S
+++ b/arch/powerpc/kernel/cpu_setup_44x.S
@@ -35,6 +35,7 @@
 _GLOBAL(__setup_cpu_460ex)
 _GLOBAL(__setup_cpu_460gt)
 _GLOBAL(__setup_cpu_460sx)
+_GLOBAL(__setup_cpu_apm821xx)
 	mflr	r4
 	bl	__init_fpu_44x
 	bl	__fixup_440A_mcheck
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
index 0adb50a..894e64f 100644
--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -51,6 +51,7 @@
 	isync
 	blr
 
+#ifdef CONFIG_PPC32
 _GLOBAL(__setup_cpu_e200)
 	/* enable dedicated debug exception handling resources (Debug APU) */
 	mfspr	r3,SPRN_HID0
@@ -72,3 +73,17 @@
 	bl	__setup_e500mc_ivors
 	mtlr	r4
 	blr
+#endif
+/* Right now, restore and setup are the same thing */
+_GLOBAL(__restore_cpu_e5500)
+_GLOBAL(__setup_cpu_e5500)
+	mflr	r4
+	bl	__e500_icache_setup
+	bl	__e500_dcache_setup
+#ifdef CONFIG_PPC_BOOK3E_64
+	bl	.__setup_base_ivors
+#else
+	bl	__setup_e500mc_ivors
+#endif
+	mtlr	r4
+	blr
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 1f9123f..96a908f 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -48,6 +48,7 @@
 extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_460sx(unsigned long offset, struct cpu_spec *spec);
+extern void __setup_cpu_apm821xx(unsigned long offset, struct cpu_spec *spec);
 extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
@@ -66,6 +67,10 @@
 extern void __setup_cpu_power7(unsigned long offset, struct cpu_spec* spec);
 extern void __restore_cpu_power7(void);
 #endif /* CONFIG_PPC64 */
+#if defined(CONFIG_E500)
+extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
+extern void __restore_cpu_e5500(void);
+#endif /* CONFIG_E500 */
 
 /* This table only contains "desktop" CPUs, it need to be filled with embedded
  * ones as well...
@@ -1805,6 +1810,20 @@
 		.machine_check		= machine_check_440A,
 		.platform		= "ppc440",
 	},
+	{ /* 464 in APM821xx */
+		.pvr_mask		= 0xffffff00,
+		.pvr_value		= 0x12C41C80,
+		.cpu_name		= "APM821XX",
+		.cpu_features		= CPU_FTRS_44X,
+		.cpu_user_features	= COMMON_USER_BOOKE |
+			PPC_FEATURE_HAS_FPU,
+		.mmu_features		= MMU_FTR_TYPE_44x,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 32,
+		.cpu_setup		= __setup_cpu_apm821xx,
+		.machine_check		= machine_check_440A,
+		.platform		= "ppc440",
+	},
 	{ /* 476 core */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x11a50000,
@@ -1891,7 +1910,9 @@
 		.platform		= "ppc5554",
 	}
 #endif /* CONFIG_E200 */
+#endif /* CONFIG_PPC32 */
 #ifdef CONFIG_E500
+#ifdef CONFIG_PPC32
 	{	/* e500 */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x80200000,
@@ -1946,6 +1967,26 @@
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce500mc",
 	},
+#endif /* CONFIG_PPC32 */
+	{	/* e5500 */
+		.pvr_mask		= 0xffff0000,
+		.pvr_value		= 0x80240000,
+		.cpu_name		= "e5500",
+		.cpu_features		= CPU_FTRS_E500MC,
+		.cpu_user_features	= COMMON_USER_BOOKE,
+		.mmu_features		= MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
+			MMU_FTR_USE_TLBILX,
+		.icache_bsize		= 64,
+		.dcache_bsize		= 64,
+		.num_pmcs		= 4,
+		.oprofile_cpu_type	= "ppc/e500mc",
+		.oprofile_type		= PPC_OPROFILE_FSL_EMB,
+		.cpu_setup		= __setup_cpu_e5500,
+		.cpu_restore		= __restore_cpu_e5500,
+		.machine_check		= machine_check_e500mc,
+		.platform		= "ppce5500",
+	},
+#ifdef CONFIG_PPC32
 	{	/* default match */
 		.pvr_mask		= 0x00000000,
 		.pvr_value		= 0x00000000,
@@ -1960,8 +2001,8 @@
 		.machine_check		= machine_check_e500,
 		.platform		= "powerpc",
 	}
-#endif /* CONFIG_E500 */
 #endif /* CONFIG_PPC32 */
+#endif /* CONFIG_E500 */
 
 #ifdef CONFIG_PPC_BOOK3E_64
 	{	/* This is a default entry to get going, to be replaced by
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 4457382..832c8c4 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -414,18 +414,7 @@
 	crash_kexec_wait_realmode(crashing_cpu);
 #endif
 
-	for_each_irq(i) {
-		struct irq_desc *desc = irq_to_desc(i);
-
-		if (!desc || !desc->chip || !desc->chip->eoi)
-			continue;
-
-		if (desc->status & IRQ_INPROGRESS)
-			desc->chip->eoi(i);
-
-		if (!(desc->status & IRQ_DISABLED))
-			desc->chip->shutdown(i);
-	}
+	machine_kexec_mask_interrupts();
 
 	/*
 	 * Call registered shutdown routines savely.  Swap out
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index 37771a5..6e54a0f 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -74,16 +74,17 @@
 {
 	struct iommu_table *tbl = get_iommu_table_base(dev);
 
-	if (!tbl || tbl->it_offset > mask) {
-		printk(KERN_INFO
-		       "Warning: IOMMU offset too big for device mask\n");
-		if (tbl)
-			printk(KERN_INFO
-			       "mask: 0x%08llx, table offset: 0x%08lx\n",
-				mask, tbl->it_offset);
-		else
-			printk(KERN_INFO "mask: 0x%08llx, table unavailable\n",
-				mask);
+	if (!tbl) {
+		dev_info(dev, "Warning: IOMMU dma not supported: mask 0x%08llx"
+			", table unavailable\n", mask);
+		return 0;
+	}
+
+	if ((tbl->it_offset + tbl->it_size) > (mask >> IOMMU_PAGE_SHIFT)) {
+		dev_info(dev, "Warning: IOMMU window too big for device mask\n");
+		dev_info(dev, "mask: 0x%08llx, table end: 0x%08lx\n",
+				mask, (tbl->it_offset + tbl->it_size) <<
+				IOMMU_PAGE_SHIFT);
 		return 0;
 	} else
 		return 1;
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 84d6367..cf02cad 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -12,6 +12,7 @@
 #include <linux/memblock.h>
 #include <asm/bug.h>
 #include <asm/abs_addr.h>
+#include <asm/machdep.h>
 
 /*
  * Generic direct DMA implementation
@@ -89,7 +90,7 @@
 	/* Could be improved so platforms can set the limit in case
 	 * they have limited DMA windows
 	 */
-	return mask >= (memblock_end_of_DRAM() - 1);
+	return mask >= get_dma_offset(dev) + (memblock_end_of_DRAM() - 1);
 #else
 	return 1;
 #endif
@@ -154,6 +155,23 @@
 
 #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
 
+int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	if (ppc_md.dma_set_mask)
+		return ppc_md.dma_set_mask(dev, dma_mask);
+	if (unlikely(dma_ops == NULL))
+		return -EIO;
+	if (dma_ops->set_dma_mask != NULL)
+		return dma_ops->set_dma_mask(dev, dma_mask);
+	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+		return -EIO;
+	*dev->dma_mask = dma_mask;
+	return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
 static int __init dma_init(void)
 {
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 42e9d90..d82878c 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -97,6 +97,24 @@
 	addi	r9,r1,STACK_FRAME_OVERHEAD
 	ld	r11,exception_marker@toc(r2)
 	std	r11,-16(r9)		/* "regshere" marker */
+#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)
+BEGIN_FW_FTR_SECTION
+	beq	33f
+	/* if from user, see if there are any DTL entries to process */
+	ld	r10,PACALPPACAPTR(r13)	/* get ptr to VPA */
+	ld	r11,PACA_DTL_RIDX(r13)	/* get log read index */
+	ld	r10,LPPACA_DTLIDX(r10)	/* get log write index */
+	cmpd	cr1,r11,r10
+	beq+	cr1,33f
+	bl	.accumulate_stolen_time
+	REST_GPR(0,r1)
+	REST_4GPRS(3,r1)
+	REST_2GPRS(7,r1)
+	addi	r9,r1,STACK_FRAME_OVERHEAD
+33:
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING && CONFIG_PPC_SPLPAR */
+
 #ifdef CONFIG_TRACE_IRQFLAGS
 	bl	.trace_hardirqs_on
 	REST_GPR(0,r1)
@@ -202,7 +220,9 @@
 	bge-	syscall_error
 syscall_error_cont:
 	ld	r7,_NIP(r1)
+BEGIN_FTR_SECTION
 	stdcx.	r0,0,r1			/* to clear the reservation */
+END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
 	andi.	r6,r8,MSR_PR
 	ld	r4,_LINK(r1)
 	/*
@@ -419,6 +439,17 @@
 	sync
 #endif /* CONFIG_SMP */
 
+	/*
+	 * If we optimise away the clear of the reservation in system
+	 * calls because we know the CPU tracks the address of the
+	 * reservation, then we need to clear it here to cover the
+	 * case that the kernel context switch path has no larx
+	 * instructions.
+	 */
+BEGIN_FTR_SECTION
+	ldarx	r6,0,r1
+END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS)
+
 	addi	r6,r4,-THREAD	/* Convert THREAD to 'current' */
 	std	r6,PACACURRENT(r13)	/* Set new 'current' */
 
@@ -576,7 +607,16 @@
 	andi.	r0,r3,MSR_RI
 	beq-	unrecov_restore
 
+	/*
+	 * Clear the reservation. If we know the CPU tracks the address of
+	 * the reservation then we can potentially save some cycles and use
+	 * a larx. On POWER6 and POWER7 this is significantly faster.
+	 */
+BEGIN_FTR_SECTION
 	stdcx.	r0,0,r1		/* to clear the reservation */
+FTR_SECTION_ELSE
+	ldarx	r4,0,r1
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
 
 	/*
 	 * Clear RI before restoring r13.  If we are returning to
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index f53029a..39b0c48 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -818,12 +818,12 @@
 
 	/*
 	 * hash_page couldn't handle it, set soft interrupt enable back
-	 * to what it was before the trap.  Note that .raw_local_irq_restore
+	 * to what it was before the trap.  Note that .arch_local_irq_restore
 	 * handles any interrupts pending at this point.
 	 */
 	ld	r3,SOFTE(r1)
 	TRACE_AND_RESTORE_IRQ_PARTIAL(r3, 11f)
-	bl	.raw_local_irq_restore
+	bl	.arch_local_irq_restore
 	b	11f
 
 /* We have a data breakpoint exception - handle it */
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index fc8f5b1..e86c040 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -163,24 +163,14 @@
 /*
  * These are used in the alignment trap handler when emulating
  * single-precision loads and stores.
- * We restore and save the fpscr so the task gets the same result
- * and exceptions as if the cpu had performed the load or store.
  */
 
 _GLOBAL(cvt_fd)
-	lfd	0,THREAD_FPSCR(r5)	/* load up fpscr value */
-	MTFSF_L(0)
 	lfs	0,0(r3)
 	stfd	0,0(r4)
-	mffs	0
-	stfd	0,THREAD_FPSCR(r5)	/* save new fpscr value */
 	blr
 
 _GLOBAL(cvt_df)
-	lfd	0,THREAD_FPSCR(r5)	/* load up fpscr value */
-	MTFSF_L(0)
 	lfd	0,0(r3)
 	stfs	0,0(r4)
-	mffs	0
-	stfd	0,THREAD_FPSCR(r5)	/* save new fpscr value */
 	blr
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S
index a90625f..8278e8b 100644
--- a/arch/powerpc/kernel/head_40x.S
+++ b/arch/powerpc/kernel/head_40x.S
@@ -923,11 +923,7 @@
 	mtspr	SPRN_PID,r0
 	sync
 
-	/* Configure and load two entries into TLB slots 62 and 63.
-	 * In case we are pinning TLBs, these are reserved in by the
-	 * other TLB functions.  If not reserving, then it doesn't
-	 * matter where they are loaded.
-	 */
+	/* Configure and load one entry into TLB slots 63 */
 	clrrwi	r4,r4,10		/* Mask off the real page number */
 	ori	r4,r4,(TLB_WR | TLB_EX)	/* Set the write and execute bits */
 
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 4faeba2..529b817 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -152,8 +152,11 @@
 	/* Check to see if we're the second processor, and jump
 	 * to the secondary_start code if so
 	 */
-	mfspr	r24,SPRN_PIR
-	cmpwi	r24,0
+	lis	r24, boot_cpuid@h
+	ori	r24, r24, boot_cpuid@l
+	lwz	r24, 0(r24)
+	cmpwi	r24, -1
+	mfspr   r24,SPRN_PIR
 	bne	__secondary_start
 #endif
 
@@ -175,6 +178,9 @@
 	li	r0,0
 	stwu	r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
 
+	rlwinm  r22,r1,0,0,31-THREAD_SHIFT      /* current thread_info */
+	stw	r24, TI_CPU(r22)
+
 	bl	early_init
 
 #ifdef CONFIG_RELOCATABLE
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 4a65386..ce557f6 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -116,7 +116,7 @@
 	: : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
 }
 
-notrace void raw_local_irq_restore(unsigned long en)
+notrace void arch_local_irq_restore(unsigned long en)
 {
 	/*
 	 * get_paca()->soft_enabled = en;
@@ -192,7 +192,7 @@
 
 	__hard_irq_enable();
 }
-EXPORT_SYMBOL(raw_local_irq_restore);
+EXPORT_SYMBOL(arch_local_irq_restore);
 #endif /* CONFIG_PPC64 */
 
 static int show_other_interrupts(struct seq_file *p, int prec)
@@ -587,8 +587,10 @@
 			 * this will be fixed once slab is made available early
 			 * instead of the current cruft
 			 */
-			if (mem_init_done)
+			if (mem_init_done) {
+				of_node_put(host->of_node);
 				kfree(host);
+			}
 			return NULL;
 		}
 		irq_map[0].host = host;
@@ -1143,7 +1145,7 @@
 	unsigned long flags;
 	struct irq_desc *desc;
 	const char *p;
-	char none[] = "none";
+	static const char none[] = "none";
 	int i;
 
 	seq_printf(m, "%-5s  %-7s  %-15s  %s\n", "virq", "hwirq",
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 50362b6..1646836 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -56,7 +56,7 @@
 
 	for_each_possible_cpu(cpu) {
 		if (firmware_has_feature(FW_FEATURE_ISERIES))
-			sum_purr += lppaca[cpu].emulated_time_base;
+			sum_purr += lppaca_of(cpu).emulated_time_base;
 		else {
 			struct cpu_usage *cu;
 
@@ -263,7 +263,7 @@
 	           ppp_data.active_system_procs);
 
 	/* pool related entries are apropriate for shared configs */
-	if (lppaca[0].shared_proc) {
+	if (lppaca_of(0).shared_proc) {
 		unsigned long pool_idle_time, pool_procs;
 
 		seq_printf(m, "pool=%d\n", ppp_data.pool_num);
@@ -460,8 +460,8 @@
 		return;
 
 	for_each_possible_cpu(cpu) {
-		cmo_faults += lppaca[cpu].cmo_faults;
-		cmo_fault_time += lppaca[cpu].cmo_fault_time;
+		cmo_faults += lppaca_of(cpu).cmo_faults;
+		cmo_fault_time += lppaca_of(cpu).cmo_fault_time;
 	}
 
 	seq_printf(m, "cmo_faults=%lu\n", cmo_faults);
@@ -479,8 +479,8 @@
 	unsigned long dispatch_dispersions = 0;
 
 	for_each_possible_cpu(cpu) {
-		dispatches += lppaca[cpu].yield_count;
-		dispatch_dispersions += lppaca[cpu].dispersion_count;
+		dispatches += lppaca_of(cpu).yield_count;
+		dispatch_dispersions += lppaca_of(cpu).dispersion_count;
 	}
 
 	seq_printf(m, "dispatches=%lu\n", dispatches);
@@ -545,7 +545,7 @@
 	seq_printf(m, "partition_potential_processors=%d\n",
 		   partition_potential_processors);
 
-	seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc);
+	seq_printf(m, "shared_processor_mode=%d\n", lppaca_of(0).shared_proc);
 
 	seq_printf(m, "slb_size=%d\n", mmu_slb_size);
 
@@ -780,6 +780,7 @@
 	.write		= lparcfg_write,
 	.open		= lparcfg_open,
 	.release	= single_release,
+	.llseek		= seq_lseek,
 };
 
 static int __init lparcfg_init(void)
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index dd6c141..df7e20c 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -14,10 +14,34 @@
 #include <linux/threads.h>
 #include <linux/memblock.h>
 #include <linux/of.h>
+#include <linux/irq.h>
+
 #include <asm/machdep.h>
 #include <asm/prom.h>
 #include <asm/sections.h>
 
+void machine_kexec_mask_interrupts(void) {
+	unsigned int i;
+
+	for_each_irq(i) {
+		struct irq_desc *desc = irq_to_desc(i);
+
+		if (!desc || !desc->chip)
+			continue;
+
+		if (desc->chip->eoi &&
+		    desc->status & IRQ_INPROGRESS)
+			desc->chip->eoi(i);
+
+		if (desc->chip->mask)
+			desc->chip->mask(i);
+
+		if (desc->chip->disable &&
+		    !(desc->status & IRQ_DISABLED))
+			desc->chip->disable(i);
+	}
+}
+
 void machine_crash_shutdown(struct pt_regs *regs)
 {
 	if (ppc_md.machine_crash_shutdown)
diff --git a/arch/powerpc/kernel/machine_kexec_32.c b/arch/powerpc/kernel/machine_kexec_32.c
index ae63a96..e63f2e7 100644
--- a/arch/powerpc/kernel/machine_kexec_32.c
+++ b/arch/powerpc/kernel/machine_kexec_32.c
@@ -39,6 +39,10 @@
 	/* Interrupts aren't acceptable while we reboot */
 	local_irq_disable();
 
+	/* mask each interrupt so we are in a more sane state for the
+	 * kexec kernel */
+	machine_kexec_mask_interrupts();
+
 	page_list = image->head;
 
 	/* we need both effective and real address here */
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
index 477c663..49cee9d 100644
--- a/arch/powerpc/kernel/module.c
+++ b/arch/powerpc/kernel/module.c
@@ -63,11 +63,6 @@
 		const Elf_Shdr *sechdrs, struct module *me)
 {
 	const Elf_Shdr *sect;
-	int err;
-
-	err = module_bug_finalize(hdr, sechdrs, me);
-	if (err)
-		return err;
 
 	/* Apply feature fixups */
 	sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -101,5 +96,4 @@
 
 void module_arch_cleanup(struct module *mod)
 {
-	module_bug_cleanup(mod);
 }
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index d0a26f1..ebf9846 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -27,6 +27,20 @@
 #ifdef CONFIG_PPC_BOOK3S
 
 /*
+ * We only have to have statically allocated lppaca structs on
+ * legacy iSeries, which supports at most 64 cpus.
+ */
+#ifdef CONFIG_PPC_ISERIES
+#if NR_CPUS < 64
+#define NR_LPPACAS	NR_CPUS
+#else
+#define NR_LPPACAS	64
+#endif
+#else /* not iSeries */
+#define NR_LPPACAS	1
+#endif
+
+/*
  * The structure which the hypervisor knows about - this structure
  * should not cross a page boundary.  The vpa_init/register_vpa call
  * is now known to fail if the lppaca structure crosses a page
@@ -36,7 +50,7 @@
  * will suffice to ensure that it doesn't cross a page boundary.
  */
 struct lppaca lppaca[] = {
-	[0 ... (NR_CPUS-1)] = {
+	[0 ... (NR_LPPACAS-1)] = {
 		.desc = 0xd397d781,	/* "LpPa" */
 		.size = sizeof(struct lppaca),
 		.dyn_proc_status = 2,
@@ -49,6 +63,54 @@
 	},
 };
 
+static struct lppaca *extra_lppacas;
+static long __initdata lppaca_size;
+
+static void allocate_lppacas(int nr_cpus, unsigned long limit)
+{
+	if (nr_cpus <= NR_LPPACAS)
+		return;
+
+	lppaca_size = PAGE_ALIGN(sizeof(struct lppaca) *
+				 (nr_cpus - NR_LPPACAS));
+	extra_lppacas = __va(memblock_alloc_base(lppaca_size,
+						 PAGE_SIZE, limit));
+}
+
+static struct lppaca *new_lppaca(int cpu)
+{
+	struct lppaca *lp;
+
+	if (cpu < NR_LPPACAS)
+		return &lppaca[cpu];
+
+	lp = extra_lppacas + (cpu - NR_LPPACAS);
+	*lp = lppaca[0];
+
+	return lp;
+}
+
+static void free_lppacas(void)
+{
+	long new_size = 0, nr;
+
+	if (!lppaca_size)
+		return;
+	nr = num_possible_cpus() - NR_LPPACAS;
+	if (nr > 0)
+		new_size = PAGE_ALIGN(nr * sizeof(struct lppaca));
+	if (new_size >= lppaca_size)
+		return;
+
+	memblock_free(__pa(extra_lppacas) + new_size, lppaca_size - new_size);
+	lppaca_size = new_size;
+}
+
+#else
+
+static inline void allocate_lppacas(int nr_cpus, unsigned long limit) { }
+static inline void free_lppacas(void) { }
+
 #endif /* CONFIG_PPC_BOOK3S */
 
 #ifdef CONFIG_PPC_STD_MMU_64
@@ -88,7 +150,7 @@
 	unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL;
 
 #ifdef CONFIG_PPC_BOOK3S
-	new_paca->lppaca_ptr = &lppaca[cpu];
+	new_paca->lppaca_ptr = new_lppaca(cpu);
 #else
 	new_paca->kernel_pgd = swapper_pg_dir;
 #endif
@@ -127,7 +189,7 @@
 	 * the first segment. On iSeries they must be within the area mapped
 	 * by the HV, which is HvPagesToMap * HVPAGESIZE bytes.
 	 */
-	limit = min(0x10000000ULL, memblock.rmo_size);
+	limit = min(0x10000000ULL, ppc64_rma_size);
 	if (firmware_has_feature(FW_FEATURE_ISERIES))
 		limit = min(limit, HvPagesToMap * HVPAGESIZE);
 
@@ -144,6 +206,8 @@
 	printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p\n",
 		paca_size, nr_cpus, paca);
 
+	allocate_lppacas(nr_cpus, limit);
+
 	/* Can't use for_each_*_cpu, as they aren't functional yet */
 	for (cpu = 0; cpu < nr_cpus; cpu++)
 		initialise_paca(&paca[cpu], cpu);
@@ -164,4 +228,6 @@
 		paca_size - new_size);
 
 	paca_size = new_size;
+
+	free_lppacas();
 }
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 9021c4a..10a44e6 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1090,8 +1090,6 @@
 		 bus->number, bus->self ? pci_name(bus->self) : "PHB");
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
-		struct dev_archdata *sd = &dev->dev.archdata;
-
 		/* Cardbus can call us to add new devices to a bus, so ignore
 		 * those who are already fully discovered
 		 */
@@ -1107,7 +1105,7 @@
 		set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
 
 		/* Hook up default DMA ops */
-		sd->dma_ops = pci_dma_ops;
+		set_dma_ops(&dev->dev, pci_dma_ops);
 		set_dma_offset(&dev->dev, PCI_DRAM_OFFSET);
 
 		/* Additional platform DMA/iommu setup */
diff --git a/arch/powerpc/kernel/perf_callchain.c b/arch/powerpc/kernel/perf_callchain.c
index 95ad9da..d05ae42 100644
--- a/arch/powerpc/kernel/perf_callchain.c
+++ b/arch/powerpc/kernel/perf_callchain.c
@@ -23,18 +23,6 @@
 #include "ppc32.h"
 #endif
 
-/*
- * Store another value in a callchain_entry.
- */
-static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
-	unsigned int nr = entry->nr;
-
-	if (nr < PERF_MAX_STACK_DEPTH) {
-		entry->ip[nr] = ip;
-		entry->nr = nr + 1;
-	}
-}
 
 /*
  * Is sp valid as the address of the next kernel stack frame after prev_sp?
@@ -58,8 +46,8 @@
 	return 0;
 }
 
-static void perf_callchain_kernel(struct pt_regs *regs,
-				  struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
 	unsigned long sp, next_sp;
 	unsigned long next_ip;
@@ -69,8 +57,7 @@
 
 	lr = regs->link;
 	sp = regs->gpr[1];
-	callchain_store(entry, PERF_CONTEXT_KERNEL);
-	callchain_store(entry, regs->nip);
+	perf_callchain_store(entry, regs->nip);
 
 	if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
 		return;
@@ -89,7 +76,7 @@
 			next_ip = regs->nip;
 			lr = regs->link;
 			level = 0;
-			callchain_store(entry, PERF_CONTEXT_KERNEL);
+			perf_callchain_store(entry, PERF_CONTEXT_KERNEL);
 
 		} else {
 			if (level == 0)
@@ -111,7 +98,7 @@
 			++level;
 		}
 
-		callchain_store(entry, next_ip);
+		perf_callchain_store(entry, next_ip);
 		if (!valid_next_sp(next_sp, sp))
 			return;
 		sp = next_sp;
@@ -233,8 +220,8 @@
 		puc == (unsigned long) &sf->uc;
 }
 
-static void perf_callchain_user_64(struct pt_regs *regs,
-				   struct perf_callchain_entry *entry)
+static void perf_callchain_user_64(struct perf_callchain_entry *entry,
+				   struct pt_regs *regs)
 {
 	unsigned long sp, next_sp;
 	unsigned long next_ip;
@@ -246,8 +233,7 @@
 	next_ip = regs->nip;
 	lr = regs->link;
 	sp = regs->gpr[1];
-	callchain_store(entry, PERF_CONTEXT_USER);
-	callchain_store(entry, next_ip);
+	perf_callchain_store(entry, next_ip);
 
 	for (;;) {
 		fp = (unsigned long __user *) sp;
@@ -276,14 +262,14 @@
 			    read_user_stack_64(&uregs[PT_R1], &sp))
 				return;
 			level = 0;
-			callchain_store(entry, PERF_CONTEXT_USER);
-			callchain_store(entry, next_ip);
+			perf_callchain_store(entry, PERF_CONTEXT_USER);
+			perf_callchain_store(entry, next_ip);
 			continue;
 		}
 
 		if (level == 0)
 			next_ip = lr;
-		callchain_store(entry, next_ip);
+		perf_callchain_store(entry, next_ip);
 		++level;
 		sp = next_sp;
 	}
@@ -315,8 +301,8 @@
 	return __get_user_inatomic(*ret, ptr);
 }
 
-static inline void perf_callchain_user_64(struct pt_regs *regs,
-					  struct perf_callchain_entry *entry)
+static inline void perf_callchain_user_64(struct perf_callchain_entry *entry,
+					  struct pt_regs *regs)
 {
 }
 
@@ -435,8 +421,8 @@
 	return mctx->mc_gregs;
 }
 
-static void perf_callchain_user_32(struct pt_regs *regs,
-				   struct perf_callchain_entry *entry)
+static void perf_callchain_user_32(struct perf_callchain_entry *entry,
+				   struct pt_regs *regs)
 {
 	unsigned int sp, next_sp;
 	unsigned int next_ip;
@@ -447,8 +433,7 @@
 	next_ip = regs->nip;
 	lr = regs->link;
 	sp = regs->gpr[1];
-	callchain_store(entry, PERF_CONTEXT_USER);
-	callchain_store(entry, next_ip);
+	perf_callchain_store(entry, next_ip);
 
 	while (entry->nr < PERF_MAX_STACK_DEPTH) {
 		fp = (unsigned int __user *) (unsigned long) sp;
@@ -470,45 +455,24 @@
 			    read_user_stack_32(&uregs[PT_R1], &sp))
 				return;
 			level = 0;
-			callchain_store(entry, PERF_CONTEXT_USER);
-			callchain_store(entry, next_ip);
+			perf_callchain_store(entry, PERF_CONTEXT_USER);
+			perf_callchain_store(entry, next_ip);
 			continue;
 		}
 
 		if (level == 0)
 			next_ip = lr;
-		callchain_store(entry, next_ip);
+		perf_callchain_store(entry, next_ip);
 		++level;
 		sp = next_sp;
 	}
 }
 
-/*
- * Since we can't get PMU interrupts inside a PMU interrupt handler,
- * we don't need separate irq and nmi entries here.
- */
-static DEFINE_PER_CPU(struct perf_callchain_entry, cpu_perf_callchain);
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
-	struct perf_callchain_entry *entry = &__get_cpu_var(cpu_perf_callchain);
-
-	entry->nr = 0;
-
-	if (!user_mode(regs)) {
-		perf_callchain_kernel(regs, entry);
-		if (current->mm)
-			regs = task_pt_regs(current);
-		else
-			regs = NULL;
-	}
-
-	if (regs) {
-		if (current_is_64bit())
-			perf_callchain_user_64(regs, entry);
-		else
-			perf_callchain_user_32(regs, entry);
-	}
-
-	return entry;
+	if (current_is_64bit())
+		perf_callchain_user_64(entry, regs);
+	else
+		perf_callchain_user_32(entry, regs);
 }
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index d301a30..3129c85 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -402,6 +402,9 @@
 {
 	s64 val, delta, prev;
 
+	if (event->hw.state & PERF_HES_STOPPED)
+		return;
+
 	if (!event->hw.idx)
 		return;
 	/*
@@ -517,7 +520,7 @@
  * Disable all events to prevent PMU interrupts and to allow
  * events to be added or removed.
  */
-void hw_perf_disable(void)
+static void power_pmu_disable(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuhw;
 	unsigned long flags;
@@ -565,7 +568,7 @@
  * If we were previously disabled and events were added, then
  * put the new config on the PMU.
  */
-void hw_perf_enable(void)
+static void power_pmu_enable(struct pmu *pmu)
 {
 	struct perf_event *event;
 	struct cpu_hw_events *cpuhw;
@@ -672,6 +675,8 @@
 		}
 		local64_set(&event->hw.prev_count, val);
 		event->hw.idx = idx;
+		if (event->hw.state & PERF_HES_STOPPED)
+			val = 0;
 		write_pmc(idx, val);
 		perf_event_update_userpage(event);
 	}
@@ -727,7 +732,7 @@
  * re-enable the PMU in order to get hw_perf_enable to do the
  * actual work of reconfiguring the PMU.
  */
-static int power_pmu_enable(struct perf_event *event)
+static int power_pmu_add(struct perf_event *event, int ef_flags)
 {
 	struct cpu_hw_events *cpuhw;
 	unsigned long flags;
@@ -735,7 +740,7 @@
 	int ret = -EAGAIN;
 
 	local_irq_save(flags);
-	perf_disable();
+	perf_pmu_disable(event->pmu);
 
 	/*
 	 * Add the event to the list (if there is room)
@@ -749,6 +754,9 @@
 	cpuhw->events[n0] = event->hw.config;
 	cpuhw->flags[n0] = event->hw.event_base;
 
+	if (!(ef_flags & PERF_EF_START))
+		event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+
 	/*
 	 * If group events scheduling transaction was started,
 	 * skip the schedulability test here, it will be peformed
@@ -769,7 +777,7 @@
 
 	ret = 0;
  out:
-	perf_enable();
+	perf_pmu_enable(event->pmu);
 	local_irq_restore(flags);
 	return ret;
 }
@@ -777,14 +785,14 @@
 /*
  * Remove a event from the PMU.
  */
-static void power_pmu_disable(struct perf_event *event)
+static void power_pmu_del(struct perf_event *event, int ef_flags)
 {
 	struct cpu_hw_events *cpuhw;
 	long i;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	perf_disable();
+	perf_pmu_disable(event->pmu);
 
 	power_pmu_read(event);
 
@@ -821,34 +829,60 @@
 		cpuhw->mmcr[0] &= ~(MMCR0_PMXE | MMCR0_FCECE);
 	}
 
-	perf_enable();
+	perf_pmu_enable(event->pmu);
 	local_irq_restore(flags);
 }
 
 /*
- * Re-enable interrupts on a event after they were throttled
- * because they were coming too fast.
+ * POWER-PMU does not support disabling individual counters, hence
+ * program their cycle counter to their max value and ignore the interrupts.
  */
-static void power_pmu_unthrottle(struct perf_event *event)
+
+static void power_pmu_start(struct perf_event *event, int ef_flags)
 {
-	s64 val, left;
+	unsigned long flags;
+	s64 left;
+
+	if (!event->hw.idx || !event->hw.sample_period)
+		return;
+
+	if (!(event->hw.state & PERF_HES_STOPPED))
+		return;
+
+	if (ef_flags & PERF_EF_RELOAD)
+		WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+
+	local_irq_save(flags);
+	perf_pmu_disable(event->pmu);
+
+	event->hw.state = 0;
+	left = local64_read(&event->hw.period_left);
+	write_pmc(event->hw.idx, left);
+
+	perf_event_update_userpage(event);
+	perf_pmu_enable(event->pmu);
+	local_irq_restore(flags);
+}
+
+static void power_pmu_stop(struct perf_event *event, int ef_flags)
+{
 	unsigned long flags;
 
 	if (!event->hw.idx || !event->hw.sample_period)
 		return;
+
+	if (event->hw.state & PERF_HES_STOPPED)
+		return;
+
 	local_irq_save(flags);
-	perf_disable();
+	perf_pmu_disable(event->pmu);
+
 	power_pmu_read(event);
-	left = event->hw.sample_period;
-	event->hw.last_period = left;
-	val = 0;
-	if (left < 0x80000000L)
-		val = 0x80000000L - left;
-	write_pmc(event->hw.idx, val);
-	local64_set(&event->hw.prev_count, val);
-	local64_set(&event->hw.period_left, left);
+	event->hw.state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+	write_pmc(event->hw.idx, 0);
+
 	perf_event_update_userpage(event);
-	perf_enable();
+	perf_pmu_enable(event->pmu);
 	local_irq_restore(flags);
 }
 
@@ -857,10 +891,11 @@
  * Set the flag to make pmu::enable() not perform the
  * schedulability test, it will be performed at commit time
  */
-void power_pmu_start_txn(const struct pmu *pmu)
+void power_pmu_start_txn(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
 
+	perf_pmu_disable(pmu);
 	cpuhw->group_flag |= PERF_EVENT_TXN;
 	cpuhw->n_txn_start = cpuhw->n_events;
 }
@@ -870,11 +905,12 @@
  * Clear the flag and pmu::enable() will perform the
  * schedulability test.
  */
-void power_pmu_cancel_txn(const struct pmu *pmu)
+void power_pmu_cancel_txn(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
 
 	cpuhw->group_flag &= ~PERF_EVENT_TXN;
+	perf_pmu_enable(pmu);
 }
 
 /*
@@ -882,7 +918,7 @@
  * Perform the group schedulability test as a whole
  * Return 0 if success
  */
-int power_pmu_commit_txn(const struct pmu *pmu)
+int power_pmu_commit_txn(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuhw;
 	long i, n;
@@ -901,19 +937,10 @@
 		cpuhw->event[i]->hw.config = cpuhw->events[i];
 
 	cpuhw->group_flag &= ~PERF_EVENT_TXN;
+	perf_pmu_enable(pmu);
 	return 0;
 }
 
-struct pmu power_pmu = {
-	.enable		= power_pmu_enable,
-	.disable	= power_pmu_disable,
-	.read		= power_pmu_read,
-	.unthrottle	= power_pmu_unthrottle,
-	.start_txn	= power_pmu_start_txn,
-	.cancel_txn	= power_pmu_cancel_txn,
-	.commit_txn	= power_pmu_commit_txn,
-};
-
 /*
  * Return 1 if we might be able to put event on a limited PMC,
  * or 0 if not.
@@ -1014,7 +1041,7 @@
 	return 0;
 }
 
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int power_pmu_event_init(struct perf_event *event)
 {
 	u64 ev;
 	unsigned long flags;
@@ -1026,25 +1053,27 @@
 	struct cpu_hw_events *cpuhw;
 
 	if (!ppmu)
-		return ERR_PTR(-ENXIO);
+		return -ENOENT;
+
 	switch (event->attr.type) {
 	case PERF_TYPE_HARDWARE:
 		ev = event->attr.config;
 		if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
-			return ERR_PTR(-EOPNOTSUPP);
+			return -EOPNOTSUPP;
 		ev = ppmu->generic_events[ev];
 		break;
 	case PERF_TYPE_HW_CACHE:
 		err = hw_perf_cache_event(event->attr.config, &ev);
 		if (err)
-			return ERR_PTR(err);
+			return err;
 		break;
 	case PERF_TYPE_RAW:
 		ev = event->attr.config;
 		break;
 	default:
-		return ERR_PTR(-EINVAL);
+		return -ENOENT;
 	}
+
 	event->hw.config_base = ev;
 	event->hw.idx = 0;
 
@@ -1063,7 +1092,7 @@
 	 * XXX we should check if the task is an idle task.
 	 */
 	flags = 0;
-	if (event->ctx->task)
+	if (event->attach_state & PERF_ATTACH_TASK)
 		flags |= PPMU_ONLY_COUNT_RUN;
 
 	/*
@@ -1081,7 +1110,7 @@
 			 */
 			ev = normal_pmc_alternative(ev, flags);
 			if (!ev)
-				return ERR_PTR(-EINVAL);
+				return -EINVAL;
 		}
 	}
 
@@ -1095,19 +1124,19 @@
 		n = collect_events(event->group_leader, ppmu->n_counter - 1,
 				   ctrs, events, cflags);
 		if (n < 0)
-			return ERR_PTR(-EINVAL);
+			return -EINVAL;
 	}
 	events[n] = ev;
 	ctrs[n] = event;
 	cflags[n] = flags;
 	if (check_excludes(ctrs, cflags, n, 1))
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 	cpuhw = &get_cpu_var(cpu_hw_events);
 	err = power_check_constraints(cpuhw, events, cflags, n + 1);
 	put_cpu_var(cpu_hw_events);
 	if (err)
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 	event->hw.config = events[n];
 	event->hw.event_base = cflags[n];
@@ -1132,11 +1161,23 @@
 	}
 	event->destroy = hw_perf_event_destroy;
 
-	if (err)
-		return ERR_PTR(err);
-	return &power_pmu;
+	return err;
 }
 
+struct pmu power_pmu = {
+	.pmu_enable	= power_pmu_enable,
+	.pmu_disable	= power_pmu_disable,
+	.event_init	= power_pmu_event_init,
+	.add		= power_pmu_add,
+	.del		= power_pmu_del,
+	.start		= power_pmu_start,
+	.stop		= power_pmu_stop,
+	.read		= power_pmu_read,
+	.start_txn	= power_pmu_start_txn,
+	.cancel_txn	= power_pmu_cancel_txn,
+	.commit_txn	= power_pmu_commit_txn,
+};
+
 /*
  * A counter has overflowed; update its count and record
  * things if requested.  Note that interrupts are hard-disabled
@@ -1149,6 +1190,11 @@
 	s64 prev, delta, left;
 	int record = 0;
 
+	if (event->hw.state & PERF_HES_STOPPED) {
+		write_pmc(event->hw.idx, 0);
+		return;
+	}
+
 	/* we don't have to worry about interrupts here */
 	prev = local64_read(&event->hw.prev_count);
 	delta = (val - prev) & 0xfffffffful;
@@ -1171,6 +1217,11 @@
 			val = 0x80000000LL - left;
 	}
 
+	write_pmc(event->hw.idx, val);
+	local64_set(&event->hw.prev_count, val);
+	local64_set(&event->hw.period_left, left);
+	perf_event_update_userpage(event);
+
 	/*
 	 * Finally record data if requested.
 	 */
@@ -1183,23 +1234,9 @@
 		if (event->attr.sample_type & PERF_SAMPLE_ADDR)
 			perf_get_data_addr(regs, &data.addr);
 
-		if (perf_event_overflow(event, nmi, &data, regs)) {
-			/*
-			 * Interrupts are coming too fast - throttle them
-			 * by setting the event to 0, so it will be
-			 * at least 2^30 cycles until the next interrupt
-			 * (assuming each event counts at most 2 counts
-			 * per cycle).
-			 */
-			val = 0;
-			left = ~0ULL >> 1;
-		}
+		if (perf_event_overflow(event, nmi, &data, regs))
+			power_pmu_stop(event, 0);
 	}
-
-	write_pmc(event->hw.idx, val);
-	local64_set(&event->hw.prev_count, val);
-	local64_set(&event->hw.period_left, left);
-	perf_event_update_userpage(event);
 }
 
 /*
@@ -1342,6 +1379,7 @@
 		freeze_events_kernel = MMCR0_FCHV;
 #endif /* CONFIG_PPC64 */
 
+	perf_pmu_register(&power_pmu);
 	perf_cpu_notifier(power_pmu_notifier);
 
 	return 0;
diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c
index 1ba4547..7ecca59 100644
--- a/arch/powerpc/kernel/perf_event_fsl_emb.c
+++ b/arch/powerpc/kernel/perf_event_fsl_emb.c
@@ -156,6 +156,9 @@
 {
 	s64 val, delta, prev;
 
+	if (event->hw.state & PERF_HES_STOPPED)
+		return;
+
 	/*
 	 * Performance monitor interrupts come even when interrupts
 	 * are soft-disabled, as long as interrupts are hard-enabled.
@@ -177,7 +180,7 @@
  * Disable all events to prevent PMU interrupts and to allow
  * events to be added or removed.
  */
-void hw_perf_disable(void)
+static void fsl_emb_pmu_disable(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuhw;
 	unsigned long flags;
@@ -216,7 +219,7 @@
  * If we were previously disabled and events were added, then
  * put the new config on the PMU.
  */
-void hw_perf_enable(void)
+static void fsl_emb_pmu_enable(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuhw;
 	unsigned long flags;
@@ -262,8 +265,8 @@
 	return n;
 }
 
-/* perf must be disabled, context locked on entry */
-static int fsl_emb_pmu_enable(struct perf_event *event)
+/* context locked on entry */
+static int fsl_emb_pmu_add(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuhw;
 	int ret = -EAGAIN;
@@ -271,6 +274,7 @@
 	u64 val;
 	int i;
 
+	perf_pmu_disable(event->pmu);
 	cpuhw = &get_cpu_var(cpu_hw_events);
 
 	if (event->hw.config & FSL_EMB_EVENT_RESTRICTED)
@@ -301,6 +305,12 @@
 			val = 0x80000000L - left;
 	}
 	local64_set(&event->hw.prev_count, val);
+
+	if (!(flags & PERF_EF_START)) {
+		event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+		val = 0;
+	}
+
 	write_pmc(i, val);
 	perf_event_update_userpage(event);
 
@@ -310,15 +320,17 @@
 	ret = 0;
  out:
 	put_cpu_var(cpu_hw_events);
+	perf_pmu_enable(event->pmu);
 	return ret;
 }
 
-/* perf must be disabled, context locked on entry */
-static void fsl_emb_pmu_disable(struct perf_event *event)
+/* context locked on entry */
+static void fsl_emb_pmu_del(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuhw;
 	int i = event->hw.idx;
 
+	perf_pmu_disable(event->pmu);
 	if (i < 0)
 		goto out;
 
@@ -346,45 +358,58 @@
 	cpuhw->n_events--;
 
  out:
+	perf_pmu_enable(event->pmu);
 	put_cpu_var(cpu_hw_events);
 }
 
-/*
- * Re-enable interrupts on a event after they were throttled
- * because they were coming too fast.
- *
- * Context is locked on entry, but perf is not disabled.
- */
-static void fsl_emb_pmu_unthrottle(struct perf_event *event)
+static void fsl_emb_pmu_start(struct perf_event *event, int ef_flags)
 {
-	s64 val, left;
+	unsigned long flags;
+	s64 left;
+
+	if (event->hw.idx < 0 || !event->hw.sample_period)
+		return;
+
+	if (!(event->hw.state & PERF_HES_STOPPED))
+		return;
+
+	if (ef_flags & PERF_EF_RELOAD)
+		WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+
+	local_irq_save(flags);
+	perf_pmu_disable(event->pmu);
+
+	event->hw.state = 0;
+	left = local64_read(&event->hw.period_left);
+	write_pmc(event->hw.idx, left);
+
+	perf_event_update_userpage(event);
+	perf_pmu_enable(event->pmu);
+	local_irq_restore(flags);
+}
+
+static void fsl_emb_pmu_stop(struct perf_event *event, int ef_flags)
+{
 	unsigned long flags;
 
 	if (event->hw.idx < 0 || !event->hw.sample_period)
 		return;
+
+	if (event->hw.state & PERF_HES_STOPPED)
+		return;
+
 	local_irq_save(flags);
-	perf_disable();
+	perf_pmu_disable(event->pmu);
+
 	fsl_emb_pmu_read(event);
-	left = event->hw.sample_period;
-	event->hw.last_period = left;
-	val = 0;
-	if (left < 0x80000000L)
-		val = 0x80000000L - left;
-	write_pmc(event->hw.idx, val);
-	local64_set(&event->hw.prev_count, val);
-	local64_set(&event->hw.period_left, left);
+	event->hw.state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+	write_pmc(event->hw.idx, 0);
+
 	perf_event_update_userpage(event);
-	perf_enable();
+	perf_pmu_enable(event->pmu);
 	local_irq_restore(flags);
 }
 
-static struct pmu fsl_emb_pmu = {
-	.enable		= fsl_emb_pmu_enable,
-	.disable	= fsl_emb_pmu_disable,
-	.read		= fsl_emb_pmu_read,
-	.unthrottle	= fsl_emb_pmu_unthrottle,
-};
-
 /*
  * Release the PMU if this is the last perf_event.
  */
@@ -428,7 +453,7 @@
 	return 0;
 }
 
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int fsl_emb_pmu_event_init(struct perf_event *event)
 {
 	u64 ev;
 	struct perf_event *events[MAX_HWEVENTS];
@@ -441,14 +466,14 @@
 	case PERF_TYPE_HARDWARE:
 		ev = event->attr.config;
 		if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
-			return ERR_PTR(-EOPNOTSUPP);
+			return -EOPNOTSUPP;
 		ev = ppmu->generic_events[ev];
 		break;
 
 	case PERF_TYPE_HW_CACHE:
 		err = hw_perf_cache_event(event->attr.config, &ev);
 		if (err)
-			return ERR_PTR(err);
+			return err;
 		break;
 
 	case PERF_TYPE_RAW:
@@ -456,12 +481,12 @@
 		break;
 
 	default:
-		return ERR_PTR(-EINVAL);
+		return -ENOENT;
 	}
 
 	event->hw.config = ppmu->xlate_event(ev);
 	if (!(event->hw.config & FSL_EMB_EVENT_VALID))
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 	/*
 	 * If this is in a group, check if it can go on with all the
@@ -473,7 +498,7 @@
 		n = collect_events(event->group_leader,
 		                   ppmu->n_counter - 1, events);
 		if (n < 0)
-			return ERR_PTR(-EINVAL);
+			return -EINVAL;
 	}
 
 	if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) {
@@ -484,7 +509,7 @@
 		}
 
 		if (num_restricted >= ppmu->n_restricted)
-			return ERR_PTR(-EINVAL);
+			return -EINVAL;
 	}
 
 	event->hw.idx = -1;
@@ -497,7 +522,7 @@
 	if (event->attr.exclude_kernel)
 		event->hw.config_base |= PMLCA_FCS;
 	if (event->attr.exclude_idle)
-		return ERR_PTR(-ENOTSUPP);
+		return -ENOTSUPP;
 
 	event->hw.last_period = event->hw.sample_period;
 	local64_set(&event->hw.period_left, event->hw.last_period);
@@ -523,11 +548,20 @@
 	}
 	event->destroy = hw_perf_event_destroy;
 
-	if (err)
-		return ERR_PTR(err);
-	return &fsl_emb_pmu;
+	return err;
 }
 
+static struct pmu fsl_emb_pmu = {
+	.pmu_enable	= fsl_emb_pmu_enable,
+	.pmu_disable	= fsl_emb_pmu_disable,
+	.event_init	= fsl_emb_pmu_event_init,
+	.add		= fsl_emb_pmu_add,
+	.del		= fsl_emb_pmu_del,
+	.start		= fsl_emb_pmu_start,
+	.stop		= fsl_emb_pmu_stop,
+	.read		= fsl_emb_pmu_read,
+};
+
 /*
  * A counter has overflowed; update its count and record
  * things if requested.  Note that interrupts are hard-disabled
@@ -540,6 +574,11 @@
 	s64 prev, delta, left;
 	int record = 0;
 
+	if (event->hw.state & PERF_HES_STOPPED) {
+		write_pmc(event->hw.idx, 0);
+		return;
+	}
+
 	/* we don't have to worry about interrupts here */
 	prev = local64_read(&event->hw.prev_count);
 	delta = (val - prev) & 0xfffffffful;
@@ -562,6 +601,11 @@
 			val = 0x80000000LL - left;
 	}
 
+	write_pmc(event->hw.idx, val);
+	local64_set(&event->hw.prev_count, val);
+	local64_set(&event->hw.period_left, left);
+	perf_event_update_userpage(event);
+
 	/*
 	 * Finally record data if requested.
 	 */
@@ -571,23 +615,9 @@
 		perf_sample_data_init(&data, 0);
 		data.period = event->hw.last_period;
 
-		if (perf_event_overflow(event, nmi, &data, regs)) {
-			/*
-			 * Interrupts are coming too fast - throttle them
-			 * by setting the event to 0, so it will be
-			 * at least 2^30 cycles until the next interrupt
-			 * (assuming each event counts at most 2 counts
-			 * per cycle).
-			 */
-			val = 0;
-			left = ~0ULL >> 1;
-		}
+		if (perf_event_overflow(event, nmi, &data, regs))
+			fsl_emb_pmu_stop(event, 0);
 	}
-
-	write_pmc(event->hw.idx, val);
-	local64_set(&event->hw.prev_count, val);
-	local64_set(&event->hw.period_left, left);
-	perf_event_update_userpage(event);
 }
 
 static void perf_event_interrupt(struct pt_regs *regs)
@@ -651,5 +681,7 @@
 	pr_info("%s performance monitor hardware support registered\n",
 		pmu->name);
 
+	perf_pmu_register(&fsl_emb_pmu);
+
 	return 0;
 }
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c
index 8eff48e..3fee685 100644
--- a/arch/powerpc/kernel/ppc970-pmu.c
+++ b/arch/powerpc/kernel/ppc970-pmu.c
@@ -169,9 +169,11 @@
 	switch (unit) {
 	case PM_VPU:
 		mask = 0x4c;		/* byte 0 bits 2,3,6 */
+		break;
 	case PM_LSU0:
 		/* byte 2 bits 0,2,3,4,6; all of byte 1 */
 		mask = 0x085dff00;
+		break;
 	case PM_LSU1L:
 		mask = 0x50 << 24;	/* byte 3 bits 4,6 */
 		break;
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index b1c648a..84906d3 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -517,7 +517,6 @@
 
 	account_system_vtime(current);
 	account_process_vtime(current);
-	calculate_steal_time();
 
 	/*
 	 * We can't take a PMU exception inside _switch() since there is a
@@ -1298,14 +1297,3 @@
 
 	return ret;
 }
-
-#ifdef CONFIG_SMP
-int arch_sd_sibling_asym_packing(void)
-{
-	if (cpu_has_feature(CPU_FTR_ASYM_SMT)) {
-		printk_once(KERN_INFO "Enabling Asymmetric SMT scheduling\n");
-		return SD_ASYM_PACKING;
-	}
-	return 0;
-}
-#endif
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index fed9bf6..c3c6a88 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -66,6 +66,7 @@
 int __initdata iommu_is_off;
 int __initdata iommu_force_on;
 unsigned long tce_alloc_start, tce_alloc_end;
+u64 ppc64_rma_size;
 #endif
 
 static int __init early_parse_mem(char *p)
@@ -98,7 +99,7 @@
 
 	if ((memory_limit && (start + size) > memory_limit) ||
 			overlaps_crashkernel(start, size)) {
-		p = __va(memblock_alloc_base(size, PAGE_SIZE, memblock.rmo_size));
+		p = __va(memblock_alloc(size, PAGE_SIZE));
 		memcpy(p, initial_boot_params, size);
 		initial_boot_params = (struct boot_param_header *)p;
 		DBG("Moved device tree to 0x%p\n", p);
@@ -492,7 +493,7 @@
 
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
-#if defined(CONFIG_PPC64)
+#ifdef CONFIG_PPC64
 	if (iommu_is_off) {
 		if (base >= 0x80000000ul)
 			return;
@@ -501,9 +502,13 @@
 	}
 #endif
 
-	memblock_add(base, size);
-
+	/* First MEMBLOCK added, do some special initializations */
+	if (memstart_addr == ~(phys_addr_t)0)
+		setup_initial_memory_limit(base, size);
 	memstart_addr = min((u64)memstart_addr, base);
+
+	/* Add the chunk to the MEMBLOCK list */
+	memblock_add(base, size);
 }
 
 u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
@@ -655,7 +660,6 @@
 static inline void __init phyp_dump_reserve_mem(void) {}
 #endif /* CONFIG_PHYP_DUMP  && CONFIG_PPC_RTAS */
 
-
 void __init early_init_devtree(void *params)
 {
 	phys_addr_t limit;
@@ -683,6 +687,7 @@
 
 	/* Scan memory nodes and rebuild MEMBLOCKs */
 	memblock_init();
+
 	of_scan_flat_dt(early_init_dt_scan_root, NULL);
 	of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
 
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 11f3cd9..286d978 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1681,7 +1681,7 @@
 
 	if (unlikely(current->audit_context)) {
 #ifdef CONFIG_PPC64
-		if (!test_thread_flag(TIF_32BIT))
+		if (!is_32bit_task())
 			audit_syscall_entry(AUDIT_ARCH_PPC64,
 					    regs->gpr[0],
 					    regs->gpr[3], regs->gpr[4],
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 41048de..8fe8bc6 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -805,7 +805,7 @@
 	__rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1);
 }
 
-static int rtas_ibm_suspend_me(struct rtas_args *args)
+int rtas_ibm_suspend_me(struct rtas_args *args)
 {
 	long state;
 	long rc;
@@ -855,7 +855,7 @@
 	return atomic_read(&data.error);
 }
 #else /* CONFIG_PPC_PSERIES */
-static int rtas_ibm_suspend_me(struct rtas_args *args)
+int rtas_ibm_suspend_me(struct rtas_args *args)
 {
 	return -ENOSYS;
 }
@@ -969,7 +969,7 @@
 	 */
 #ifdef CONFIG_PPC64
 	if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) {
-		rtas_region = min(memblock.rmo_size, RTAS_INSTANTIATE_MAX);
+		rtas_region = min(ppc64_rma_size, RTAS_INSTANTIATE_MAX);
 		ibm_suspend_me_token = rtas_token("ibm,suspend-me");
 	}
 #endif
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 67a84d8..2b442e6 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -716,6 +716,7 @@
 	.write		= rtas_flash_write,
 	.open		= rtas_excl_open,
 	.release	= rtas_flash_release,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations manage_flash_operations = {
@@ -724,6 +725,7 @@
 	.write		= manage_flash_write,
 	.open		= rtas_excl_open,
 	.release	= rtas_excl_release,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations validate_flash_operations = {
@@ -732,6 +734,7 @@
 	.write		= validate_flash_write,
 	.open		= rtas_excl_open,
 	.release	= validate_flash_release,
+	.llseek		= default_llseek,
 };
 
 static int __init rtas_flash_init(void)
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index 638883e..0438f81 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -354,6 +354,7 @@
 	.poll =		rtas_log_poll,
 	.open =		rtas_log_open,
 	.release =	rtas_log_release,
+	.llseek =	noop_llseek,
 };
 
 static int enable_surveillance(int timeout)
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 93666f9..1d2fbc9 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -46,7 +46,7 @@
 
 extern void bootx_init(unsigned long r4, unsigned long phys);
 
-int boot_cpuid;
+int boot_cpuid = -1;
 EXPORT_SYMBOL_GPL(boot_cpuid);
 int boot_cpuid_phys;
 
@@ -246,7 +246,7 @@
 	unsigned int i;
 
 	/* interrupt stacks must be in lowmem, we get that for free on ppc32
-	 * as the memblock is limited to lowmem by MEMBLOCK_REAL_LIMIT */
+	 * as the memblock is limited to lowmem by default */
 	for_each_possible_cpu(i) {
 		softirq_ctx[i] = (struct thread_info *)
 			__va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index e72690e..2a178b0 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -486,7 +486,7 @@
 	 * bringup, we need to get at them in real mode. This means they
 	 * must also be within the RMO region.
 	 */
-	limit = min(slb0_limit(), memblock.rmo_size);
+	limit = min(slb0_limit(), ppc64_rma_size);
 
 	for_each_possible_cpu(i) {
 		unsigned long sp;
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 0008bc5..68034bb 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -508,9 +508,6 @@
 	if (smp_ops->take_timebase)
 		smp_ops->take_timebase();
 
-	if (system_state > SYSTEM_BOOTING)
-		snapshot_timebase();
-
 	secondary_cpu_time_init();
 
 	ipi_call_lock();
@@ -575,11 +572,18 @@
 
 	free_cpumask_var(old_mask);
 
-	snapshot_timebases();
-
 	dump_numa_cpu_topology();
 }
 
+int arch_sd_sibling_asym_packing(void)
+{
+	if (cpu_has_feature(CPU_FTR_ASYM_SMT)) {
+		printk_once(KERN_INFO "Enabling Asymmetric SMT scheduling\n");
+		return SD_ASYM_PACKING;
+	}
+	return 0;
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 int __cpu_disable(void)
 {
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 8533b3b..0104069 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -53,7 +53,7 @@
 #include <linux/posix-timers.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
-#include <linux/perf_event.h>
+#include <linux/irq_work.h>
 #include <asm/trace.h>
 
 #include <asm/io.h>
@@ -161,10 +161,9 @@
 static long timezone_offset;
 
 unsigned long ppc_proc_freq;
-EXPORT_SYMBOL(ppc_proc_freq);
+EXPORT_SYMBOL_GPL(ppc_proc_freq);
 unsigned long ppc_tb_freq;
-
-static DEFINE_PER_CPU(u64, last_jiffy);
+EXPORT_SYMBOL_GPL(ppc_tb_freq);
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 /*
@@ -185,6 +184,8 @@
 
 cputime_t cputime_one_jiffy;
 
+void (*dtl_consumer)(struct dtl_entry *, u64);
+
 static void calc_cputime_factors(void)
 {
 	struct div_result res;
@@ -200,62 +201,153 @@
 }
 
 /*
- * Read the PURR on systems that have it, otherwise the timebase.
+ * Read the SPURR on systems that have it, otherwise the PURR,
+ * or if that doesn't exist return the timebase value passed in.
  */
-static u64 read_purr(void)
+static u64 read_spurr(u64 tb)
 {
+	if (cpu_has_feature(CPU_FTR_SPURR))
+		return mfspr(SPRN_SPURR);
 	if (cpu_has_feature(CPU_FTR_PURR))
 		return mfspr(SPRN_PURR);
-	return mftb();
+	return tb;
+}
+
+#ifdef CONFIG_PPC_SPLPAR
+
+/*
+ * Scan the dispatch trace log and count up the stolen time.
+ * Should be called with interrupts disabled.
+ */
+static u64 scan_dispatch_log(u64 stop_tb)
+{
+	u64 i = local_paca->dtl_ridx;
+	struct dtl_entry *dtl = local_paca->dtl_curr;
+	struct dtl_entry *dtl_end = local_paca->dispatch_log_end;
+	struct lppaca *vpa = local_paca->lppaca_ptr;
+	u64 tb_delta;
+	u64 stolen = 0;
+	u64 dtb;
+
+	if (i == vpa->dtl_idx)
+		return 0;
+	while (i < vpa->dtl_idx) {
+		if (dtl_consumer)
+			dtl_consumer(dtl, i);
+		dtb = dtl->timebase;
+		tb_delta = dtl->enqueue_to_dispatch_time +
+			dtl->ready_to_enqueue_time;
+		barrier();
+		if (i + N_DISPATCH_LOG < vpa->dtl_idx) {
+			/* buffer has overflowed */
+			i = vpa->dtl_idx - N_DISPATCH_LOG;
+			dtl = local_paca->dispatch_log + (i % N_DISPATCH_LOG);
+			continue;
+		}
+		if (dtb > stop_tb)
+			break;
+		stolen += tb_delta;
+		++i;
+		++dtl;
+		if (dtl == dtl_end)
+			dtl = local_paca->dispatch_log;
+	}
+	local_paca->dtl_ridx = i;
+	local_paca->dtl_curr = dtl;
+	return stolen;
 }
 
 /*
- * Read the SPURR on systems that have it, otherwise the purr
+ * Accumulate stolen time by scanning the dispatch trace log.
+ * Called on entry from user mode.
  */
-static u64 read_spurr(u64 purr)
+void accumulate_stolen_time(void)
 {
-	/*
-	 * cpus without PURR won't have a SPURR
-	 * We already know the former when we use this, so tell gcc
-	 */
-	if (cpu_has_feature(CPU_FTR_PURR) && cpu_has_feature(CPU_FTR_SPURR))
-		return mfspr(SPRN_SPURR);
-	return purr;
+	u64 sst, ust;
+
+	sst = scan_dispatch_log(get_paca()->starttime_user);
+	ust = scan_dispatch_log(get_paca()->starttime);
+	get_paca()->system_time -= sst;
+	get_paca()->user_time -= ust;
+	get_paca()->stolen_time += ust + sst;
 }
 
+static inline u64 calculate_stolen_time(u64 stop_tb)
+{
+	u64 stolen = 0;
+
+	if (get_paca()->dtl_ridx != get_paca()->lppaca_ptr->dtl_idx) {
+		stolen = scan_dispatch_log(stop_tb);
+		get_paca()->system_time -= stolen;
+	}
+
+	stolen += get_paca()->stolen_time;
+	get_paca()->stolen_time = 0;
+	return stolen;
+}
+
+#else /* CONFIG_PPC_SPLPAR */
+static inline u64 calculate_stolen_time(u64 stop_tb)
+{
+	return 0;
+}
+
+#endif /* CONFIG_PPC_SPLPAR */
+
 /*
  * Account time for a transition between system, hard irq
  * or soft irq state.
  */
 void account_system_vtime(struct task_struct *tsk)
 {
-	u64 now, nowscaled, delta, deltascaled, sys_time;
+	u64 now, nowscaled, delta, deltascaled;
 	unsigned long flags;
+	u64 stolen, udelta, sys_scaled, user_scaled;
 
 	local_irq_save(flags);
-	now = read_purr();
+	now = mftb();
 	nowscaled = read_spurr(now);
-	delta = now - get_paca()->startpurr;
+	get_paca()->system_time += now - get_paca()->starttime;
+	get_paca()->starttime = now;
 	deltascaled = nowscaled - get_paca()->startspurr;
-	get_paca()->startpurr = now;
 	get_paca()->startspurr = nowscaled;
-	if (!in_interrupt()) {
-		/* deltascaled includes both user and system time.
-		 * Hence scale it based on the purr ratio to estimate
-		 * the system time */
-		sys_time = get_paca()->system_time;
-		if (get_paca()->user_time)
-			deltascaled = deltascaled * sys_time /
-			     (sys_time + get_paca()->user_time);
-		delta += sys_time;
-		get_paca()->system_time = 0;
+
+	stolen = calculate_stolen_time(now);
+
+	delta = get_paca()->system_time;
+	get_paca()->system_time = 0;
+	udelta = get_paca()->user_time - get_paca()->utime_sspurr;
+	get_paca()->utime_sspurr = get_paca()->user_time;
+
+	/*
+	 * Because we don't read the SPURR on every kernel entry/exit,
+	 * deltascaled includes both user and system SPURR ticks.
+	 * Apportion these ticks to system SPURR ticks and user
+	 * SPURR ticks in the same ratio as the system time (delta)
+	 * and user time (udelta) values obtained from the timebase
+	 * over the same interval.  The system ticks get accounted here;
+	 * the user ticks get saved up in paca->user_time_scaled to be
+	 * used by account_process_tick.
+	 */
+	sys_scaled = delta;
+	user_scaled = udelta;
+	if (deltascaled != delta + udelta) {
+		if (udelta) {
+			sys_scaled = deltascaled * delta / (delta + udelta);
+			user_scaled = deltascaled - sys_scaled;
+		} else {
+			sys_scaled = deltascaled;
+		}
 	}
-	if (in_irq() || idle_task(smp_processor_id()) != tsk)
-		account_system_time(tsk, 0, delta, deltascaled);
-	else
-		account_idle_time(delta);
-	__get_cpu_var(cputime_last_delta) = delta;
-	__get_cpu_var(cputime_scaled_last_delta) = deltascaled;
+	get_paca()->user_time_scaled += user_scaled;
+
+	if (in_irq() || idle_task(smp_processor_id()) != tsk) {
+		account_system_time(tsk, 0, delta, sys_scaled);
+		if (stolen)
+			account_steal_time(stolen);
+	} else {
+		account_idle_time(delta + stolen);
+	}
 	local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(account_system_vtime);
@@ -265,125 +357,26 @@
  * by the exception entry and exit code to the generic process
  * user and system time records.
  * Must be called with interrupts disabled.
+ * Assumes that account_system_vtime() has been called recently
+ * (i.e. since the last entry from usermode) so that
+ * get_paca()->user_time_scaled is up to date.
  */
 void account_process_tick(struct task_struct *tsk, int user_tick)
 {
 	cputime_t utime, utimescaled;
 
 	utime = get_paca()->user_time;
+	utimescaled = get_paca()->user_time_scaled;
 	get_paca()->user_time = 0;
-	utimescaled = cputime_to_scaled(utime);
+	get_paca()->user_time_scaled = 0;
+	get_paca()->utime_sspurr = 0;
 	account_user_time(tsk, utime, utimescaled);
 }
 
-/*
- * Stuff for accounting stolen time.
- */
-struct cpu_purr_data {
-	int	initialized;			/* thread is running */
-	u64	tb;			/* last TB value read */
-	u64	purr;			/* last PURR value read */
-	u64	spurr;			/* last SPURR value read */
-};
-
-/*
- * Each entry in the cpu_purr_data array is manipulated only by its
- * "owner" cpu -- usually in the timer interrupt but also occasionally
- * in process context for cpu online.  As long as cpus do not touch
- * each others' cpu_purr_data, disabling local interrupts is
- * sufficient to serialize accesses.
- */
-static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data);
-
-static void snapshot_tb_and_purr(void *data)
-{
-	unsigned long flags;
-	struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
-
-	local_irq_save(flags);
-	p->tb = get_tb_or_rtc();
-	p->purr = mfspr(SPRN_PURR);
-	wmb();
-	p->initialized = 1;
-	local_irq_restore(flags);
-}
-
-/*
- * Called during boot when all cpus have come up.
- */
-void snapshot_timebases(void)
-{
-	if (!cpu_has_feature(CPU_FTR_PURR))
-		return;
-	on_each_cpu(snapshot_tb_and_purr, NULL, 1);
-}
-
-/*
- * Must be called with interrupts disabled.
- */
-void calculate_steal_time(void)
-{
-	u64 tb, purr;
-	s64 stolen;
-	struct cpu_purr_data *pme;
-
-	pme = &__get_cpu_var(cpu_purr_data);
-	if (!pme->initialized)
-		return;		/* !CPU_FTR_PURR or early in early boot */
-	tb = mftb();
-	purr = mfspr(SPRN_PURR);
-	stolen = (tb - pme->tb) - (purr - pme->purr);
-	if (stolen > 0) {
-		if (idle_task(smp_processor_id()) != current)
-			account_steal_time(stolen);
-		else
-			account_idle_time(stolen);
-	}
-	pme->tb = tb;
-	pme->purr = purr;
-}
-
-#ifdef CONFIG_PPC_SPLPAR
-/*
- * Must be called before the cpu is added to the online map when
- * a cpu is being brought up at runtime.
- */
-static void snapshot_purr(void)
-{
-	struct cpu_purr_data *pme;
-	unsigned long flags;
-
-	if (!cpu_has_feature(CPU_FTR_PURR))
-		return;
-	local_irq_save(flags);
-	pme = &__get_cpu_var(cpu_purr_data);
-	pme->tb = mftb();
-	pme->purr = mfspr(SPRN_PURR);
-	pme->initialized = 1;
-	local_irq_restore(flags);
-}
-
-#endif /* CONFIG_PPC_SPLPAR */
-
 #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */
 #define calc_cputime_factors()
-#define calculate_steal_time()		do { } while (0)
 #endif
 
-#if !(defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR))
-#define snapshot_purr()			do { } while (0)
-#endif
-
-/*
- * Called when a cpu comes up after the system has finished booting,
- * i.e. as a result of a hotplug cpu action.
- */
-void snapshot_timebase(void)
-{
-	__get_cpu_var(last_jiffy) = get_tb_or_rtc();
-	snapshot_purr();
-}
-
 void __delay(unsigned long loops)
 {
 	unsigned long start;
@@ -493,60 +486,60 @@
 }
 #endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PERF_EVENTS
+#ifdef CONFIG_IRQ_WORK
 
 /*
  * 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable...
  */
 #ifdef CONFIG_PPC64
-static inline unsigned long test_perf_event_pending(void)
+static inline unsigned long test_irq_work_pending(void)
 {
 	unsigned long x;
 
 	asm volatile("lbz %0,%1(13)"
 		: "=r" (x)
-		: "i" (offsetof(struct paca_struct, perf_event_pending)));
+		: "i" (offsetof(struct paca_struct, irq_work_pending)));
 	return x;
 }
 
-static inline void set_perf_event_pending_flag(void)
+static inline void set_irq_work_pending_flag(void)
 {
 	asm volatile("stb %0,%1(13)" : :
 		"r" (1),
-		"i" (offsetof(struct paca_struct, perf_event_pending)));
+		"i" (offsetof(struct paca_struct, irq_work_pending)));
 }
 
-static inline void clear_perf_event_pending(void)
+static inline void clear_irq_work_pending(void)
 {
 	asm volatile("stb %0,%1(13)" : :
 		"r" (0),
-		"i" (offsetof(struct paca_struct, perf_event_pending)));
+		"i" (offsetof(struct paca_struct, irq_work_pending)));
 }
 
 #else /* 32-bit */
 
-DEFINE_PER_CPU(u8, perf_event_pending);
+DEFINE_PER_CPU(u8, irq_work_pending);
 
-#define set_perf_event_pending_flag()	__get_cpu_var(perf_event_pending) = 1
-#define test_perf_event_pending()	__get_cpu_var(perf_event_pending)
-#define clear_perf_event_pending()	__get_cpu_var(perf_event_pending) = 0
+#define set_irq_work_pending_flag()	__get_cpu_var(irq_work_pending) = 1
+#define test_irq_work_pending()		__get_cpu_var(irq_work_pending)
+#define clear_irq_work_pending()	__get_cpu_var(irq_work_pending) = 0
 
 #endif /* 32 vs 64 bit */
 
-void set_perf_event_pending(void)
+void set_irq_work_pending(void)
 {
 	preempt_disable();
-	set_perf_event_pending_flag();
+	set_irq_work_pending_flag();
 	set_dec(1);
 	preempt_enable();
 }
 
-#else  /* CONFIG_PERF_EVENTS */
+#else  /* CONFIG_IRQ_WORK */
 
-#define test_perf_event_pending()	0
-#define clear_perf_event_pending()
+#define test_irq_work_pending()	0
+#define clear_irq_work_pending()
 
-#endif /* CONFIG_PERF_EVENTS */
+#endif /* CONFIG_IRQ_WORK */
 
 /*
  * For iSeries shared processors, we have to let the hypervisor
@@ -585,11 +578,9 @@
 	old_regs = set_irq_regs(regs);
 	irq_enter();
 
-	calculate_steal_time();
-
-	if (test_perf_event_pending()) {
-		clear_perf_event_pending();
-		perf_event_do_pending();
+	if (test_irq_work_pending()) {
+		clear_irq_work_pending();
+		irq_work_run();
 	}
 
 #ifdef CONFIG_PPC_ISERIES
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index a45a63c..1b2cdc8 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -538,6 +538,11 @@
 
 	return 0;
 }
+
+int machine_check_generic(struct pt_regs *regs)
+{
+	return 0;
+}
 #elif defined(CONFIG_E200)
 int machine_check_e200(struct pt_regs *regs)
 {
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 13002fe..fd87287 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -159,7 +159,7 @@
 {
 	int i;
 
-	if (!vma || test_thread_flag(TIF_32BIT)) {
+	if (!vma || is_32bit_task()) {
 		printk("vDSO32 @ %016lx:\n", (unsigned long)vdso32_kbase);
 		for (i=0; i<vdso32_pages; i++) {
 			struct page *pg = virt_to_page(vdso32_kbase +
@@ -170,7 +170,7 @@
 			dump_one_vdso_page(pg, upg);
 		}
 	}
-	if (!vma || !test_thread_flag(TIF_32BIT)) {
+	if (!vma || !is_32bit_task()) {
 		printk("vDSO64 @ %016lx:\n", (unsigned long)vdso64_kbase);
 		for (i=0; i<vdso64_pages; i++) {
 			struct page *pg = virt_to_page(vdso64_kbase +
@@ -200,7 +200,7 @@
 		return 0;
 
 #ifdef CONFIG_PPC64
-	if (test_thread_flag(TIF_32BIT)) {
+	if (is_32bit_task()) {
 		vdso_pagelist = vdso32_pagelist;
 		vdso_pages = vdso32_pages;
 		vdso_base = VDSO32_MBASE;
diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile
index 51ead52..9a7946c 100644
--- a/arch/powerpc/kernel/vdso32/Makefile
+++ b/arch/powerpc/kernel/vdso32/Makefile
@@ -14,10 +14,10 @@
 
 GCOV_PROFILE := n
 
-EXTRA_CFLAGS := -shared -fno-common -fno-builtin
-EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1 \
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso32.so.1 \
 		$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
-EXTRA_AFLAGS := -D__VDSO32__ -s
+asflags-y := -D__VDSO32__ -s
 
 obj-y += vdso32_wrapper.o
 extra-y += vdso32.lds
diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile
index 79da65d..8c500d8 100644
--- a/arch/powerpc/kernel/vdso64/Makefile
+++ b/arch/powerpc/kernel/vdso64/Makefile
@@ -9,10 +9,10 @@
 
 GCOV_PROFILE := n
 
-EXTRA_CFLAGS := -shared -fno-common -fno-builtin
-EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
 		$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
-EXTRA_AFLAGS := -D__VDSO64__ -s
+asflags-y := -D__VDSO64__ -s
 
 obj-y += vdso64_wrapper.o
 extra-y += vdso64.lds
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index fa3469d..d692989 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -1184,7 +1184,12 @@
 /* vio_dev refcount hit 0 */
 static void __devinit vio_dev_release(struct device *dev)
 {
-	/* XXX should free TCE table */
+	struct iommu_table *tbl = get_iommu_table_base(dev);
+
+	/* iSeries uses a common table for all vio devices */
+	if (!firmware_has_feature(FW_FEATURE_ISERIES) && tbl)
+		iommu_free_table(tbl, dev->of_node ?
+			dev->of_node->full_name : dev_name(dev));
 	of_node_put(dev->of_node);
 	kfree(to_vio_dev(dev));
 }
@@ -1254,8 +1259,7 @@
 	if (device_register(&viodev->dev)) {
 		printk(KERN_ERR "%s: failed to register device %s\n",
 				__func__, dev_name(&viodev->dev));
-		/* XXX free TCE table */
-		kfree(viodev);
+		put_device(&viodev->dev);
 		return NULL;
 	}
 
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index d45c818..4d68638 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -4,7 +4,7 @@
 
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm
+ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm
 
 common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
 
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c
index 474f2e2..35a701f 100644
--- a/arch/powerpc/kvm/book3s_paired_singles.c
+++ b/arch/powerpc/kvm/book3s_paired_singles.c
@@ -159,7 +159,7 @@
 
 static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt)
 {
-	kvm_cvt_df(&vcpu->arch.fpr[rt], &vcpu->arch.qpr[rt], &vcpu->arch.fpscr);
+	kvm_cvt_df(&vcpu->arch.fpr[rt], &vcpu->arch.qpr[rt]);
 }
 
 static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
@@ -204,7 +204,7 @@
 	/* put in registers */
 	switch (ls_type) {
 	case FPU_LS_SINGLE:
-		kvm_cvt_fd((u32*)tmp, &vcpu->arch.fpr[rs], &vcpu->arch.fpscr);
+		kvm_cvt_fd((u32*)tmp, &vcpu->arch.fpr[rs]);
 		vcpu->arch.qpr[rs] = *((u32*)tmp);
 		break;
 	case FPU_LS_DOUBLE:
@@ -230,7 +230,7 @@
 
 	switch (ls_type) {
 	case FPU_LS_SINGLE:
-		kvm_cvt_df(&vcpu->arch.fpr[rs], (u32*)tmp, &vcpu->arch.fpscr);
+		kvm_cvt_df(&vcpu->arch.fpr[rs], (u32*)tmp);
 		val = *((u32*)tmp);
 		len = sizeof(u32);
 		break;
@@ -296,7 +296,7 @@
 	emulated = EMULATE_DONE;
 
 	/* put in registers */
-	kvm_cvt_fd(&tmp[0], &vcpu->arch.fpr[rs], &vcpu->arch.fpscr);
+	kvm_cvt_fd(&tmp[0], &vcpu->arch.fpr[rs]);
 	vcpu->arch.qpr[rs] = tmp[1];
 
 	dprintk(KERN_INFO "KVM: PSQ_LD [0x%x, 0x%x] at 0x%lx (%d)\n", tmp[0],
@@ -314,7 +314,7 @@
 	u32 tmp[2];
 	int len = w ? sizeof(u32) : sizeof(u64);
 
-	kvm_cvt_df(&vcpu->arch.fpr[rs], &tmp[0], &vcpu->arch.fpscr);
+	kvm_cvt_df(&vcpu->arch.fpr[rs], &tmp[0]);
 	tmp[1] = vcpu->arch.qpr[rs];
 
 	r = kvmppc_st(vcpu, &addr, len, tmp, true);
@@ -516,9 +516,9 @@
 	WARN_ON(rc);
 
 	/* PS0 */
-	kvm_cvt_df(&fpr[reg_in1], &ps0_in1, &vcpu->arch.fpscr);
-	kvm_cvt_df(&fpr[reg_in2], &ps0_in2, &vcpu->arch.fpscr);
-	kvm_cvt_df(&fpr[reg_in3], &ps0_in3, &vcpu->arch.fpscr);
+	kvm_cvt_df(&fpr[reg_in1], &ps0_in1);
+	kvm_cvt_df(&fpr[reg_in2], &ps0_in2);
+	kvm_cvt_df(&fpr[reg_in3], &ps0_in3);
 
 	if (scalar & SCALAR_LOW)
 		ps0_in2 = qpr[reg_in2];
@@ -529,7 +529,7 @@
 			  ps0_in1, ps0_in2, ps0_in3, ps0_out);
 
 	if (!(scalar & SCALAR_NO_PS0))
-		kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr);
+		kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
 
 	/* PS1 */
 	ps1_in1 = qpr[reg_in1];
@@ -566,12 +566,12 @@
 	WARN_ON(rc);
 
 	/* PS0 */
-	kvm_cvt_df(&fpr[reg_in1], &ps0_in1, &vcpu->arch.fpscr);
+	kvm_cvt_df(&fpr[reg_in1], &ps0_in1);
 
 	if (scalar & SCALAR_LOW)
 		ps0_in2 = qpr[reg_in2];
 	else
-		kvm_cvt_df(&fpr[reg_in2], &ps0_in2, &vcpu->arch.fpscr);
+		kvm_cvt_df(&fpr[reg_in2], &ps0_in2);
 
 	func(&vcpu->arch.fpscr, &ps0_out, &ps0_in1, &ps0_in2);
 
@@ -579,7 +579,7 @@
 		dprintk(KERN_INFO "PS2 ps0 -> f(0x%x, 0x%x) = 0x%x\n",
 				  ps0_in1, ps0_in2, ps0_out);
 
-		kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr);
+		kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
 	}
 
 	/* PS1 */
@@ -615,13 +615,13 @@
 	WARN_ON(rc);
 
 	/* PS0 */
-	kvm_cvt_df(&fpr[reg_in], &ps0_in, &vcpu->arch.fpscr);
+	kvm_cvt_df(&fpr[reg_in], &ps0_in);
 	func(&vcpu->arch.fpscr, &ps0_out, &ps0_in);
 
 	dprintk(KERN_INFO "PS1 ps0 -> f(0x%x) = 0x%x\n",
 			  ps0_in, ps0_out);
 
-	kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr);
+	kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
 
 	/* PS1 */
 	ps1_in = qpr[reg_in];
@@ -671,7 +671,7 @@
 #ifdef DEBUG
 	for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) {
 		u32 f;
-		kvm_cvt_df(&vcpu->arch.fpr[i], &f, &vcpu->arch.fpscr);
+		kvm_cvt_df(&vcpu->arch.fpr[i], &f);
 		dprintk(KERN_INFO "FPR[%d] = 0x%x / 0x%llx    QPR[%d] = 0x%x\n",
 			i, f, vcpu->arch.fpr[i], i, vcpu->arch.qpr[i]);
 	}
@@ -796,8 +796,7 @@
 			vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_ra];
 			/* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */
 			kvm_cvt_df(&vcpu->arch.fpr[ax_rb],
-				   &vcpu->arch.qpr[ax_rd],
-				   &vcpu->arch.fpscr);
+				   &vcpu->arch.qpr[ax_rd]);
 			break;
 		case OP_4X_PS_MERGE01:
 			WARN_ON(rcomp);
@@ -808,19 +807,16 @@
 			WARN_ON(rcomp);
 			/* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */
 			kvm_cvt_fd(&vcpu->arch.qpr[ax_ra],
-				   &vcpu->arch.fpr[ax_rd],
-				   &vcpu->arch.fpscr);
+				   &vcpu->arch.fpr[ax_rd]);
 			/* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */
 			kvm_cvt_df(&vcpu->arch.fpr[ax_rb],
-				   &vcpu->arch.qpr[ax_rd],
-				   &vcpu->arch.fpscr);
+				   &vcpu->arch.qpr[ax_rd]);
 			break;
 		case OP_4X_PS_MERGE11:
 			WARN_ON(rcomp);
 			/* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */
 			kvm_cvt_fd(&vcpu->arch.qpr[ax_ra],
-				   &vcpu->arch.fpr[ax_rd],
-				   &vcpu->arch.fpscr);
+				   &vcpu->arch.fpr[ax_rd]);
 			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 			break;
 		}
@@ -1255,7 +1251,7 @@
 #ifdef DEBUG
 	for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) {
 		u32 f;
-		kvm_cvt_df(&vcpu->arch.fpr[i], &f, &vcpu->arch.fpscr);
+		kvm_cvt_df(&vcpu->arch.fpr[i], &f);
 		dprintk(KERN_INFO "FPR[%d] = 0x%x\n", i, f);
 	}
 #endif
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 4568ec3..b83ba58 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -145,7 +145,7 @@
 	/* this default type might be overwritten by subcategories */
 	kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
 
-	pr_debug(KERN_INFO "Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
+	pr_debug("Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
 
 	switch (get_op(inst)) {
 	case OP_TRAP:
@@ -275,7 +275,7 @@
 			{
 				u64 jd = get_tb() - vcpu->arch.dec_jiffies;
 				kvmppc_set_gpr(vcpu, rt, vcpu->arch.dec - jd);
-				pr_debug(KERN_INFO "mfDEC: %x - %llx = %lx\n",
+				pr_debug("mfDEC: %x - %llx = %lx\n",
 					 vcpu->arch.dec, jd,
 					 kvmppc_get_gpr(vcpu, rt));
 				break;
diff --git a/arch/powerpc/kvm/fpu.S b/arch/powerpc/kvm/fpu.S
index cb34bbe..bf68d59 100644
--- a/arch/powerpc/kvm/fpu.S
+++ b/arch/powerpc/kvm/fpu.S
@@ -273,19 +273,11 @@
 FPD_THREE_IN(fnmadd)
 
 _GLOBAL(kvm_cvt_fd)
-	lfd	0,0(r5)			/* load up fpscr value */
-	MTFSF_L(0)
 	lfs	0,0(r3)
 	stfd	0,0(r4)
-	mffs	0
-	stfd	0,0(r5)			/* save new fpscr value */
 	blr
 
 _GLOBAL(kvm_cvt_df)
-	lfd	0,0(r5)			/* load up fpscr value */
-	MTFSF_L(0)
 	lfd	0,0(r3)
 	stfs	0,0(r4)
-	mffs	0
-	stfd	0,0(r5)			/* save new fpscr value */
 	blr
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 5bb89c82..889f2bc 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -4,9 +4,7 @@
 
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS		+= -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64)	:= -mno-minimal-toc
 
 CFLAGS_REMOVE_code-patching.o = -pg
 CFLAGS_REMOVE_feature-fixups.o = -pg
@@ -17,7 +15,8 @@
 obj-$(CONFIG_HAS_IOMEM)	+= devres.o
 
 obj-$(CONFIG_PPC64)	+= copypage_64.o copyuser_64.o \
-			   memcpy_64.o usercopy_64.o mem_64.o string.o
+			   memcpy_64.o usercopy_64.o mem_64.o string.o \
+			   checksum_wrappers_64.o
 obj-$(CONFIG_XMON)	+= sstep.o ldstfp.o
 obj-$(CONFIG_KPROBES)	+= sstep.o ldstfp.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= sstep.o ldstfp.o
diff --git a/arch/powerpc/lib/checksum_64.S b/arch/powerpc/lib/checksum_64.S
index ef96c6c..18245af 100644
--- a/arch/powerpc/lib/checksum_64.S
+++ b/arch/powerpc/lib/checksum_64.S
@@ -65,165 +65,393 @@
 	srwi	r3,r3,16
 	blr
 
+#define STACKFRAMESIZE 256
+#define STK_REG(i)	(112 + ((i)-14)*8)
+
 /*
  * Computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit).
  *
- * This code assumes at least halfword alignment, though the length
- * can be any number of bytes.  The sum is accumulated in r5.
- *
  * csum_partial(r3=buff, r4=len, r5=sum)
  */
 _GLOBAL(csum_partial)
-        subi	r3,r3,8		/* we'll offset by 8 for the loads */
-        srdi.	r6,r4,3         /* divide by 8 for doubleword count */
-        addic   r5,r5,0         /* clear carry */
-        beq	3f              /* if we're doing < 8 bytes */
-        andi.	r0,r3,2         /* aligned on a word boundary already? */
-        beq+	1f
-        lhz     r6,8(r3)        /* do 2 bytes to get aligned */
-        addi    r3,r3,2
-        subi    r4,r4,2
-        addc    r5,r5,r6
-        srdi.   r6,r4,3         /* recompute number of doublewords */
-        beq     3f              /* any left? */
-1:      mtctr   r6
-2:      ldu     r6,8(r3)        /* main sum loop */
-        adde    r5,r5,r6
-        bdnz    2b
-        andi.	r4,r4,7         /* compute bytes left to sum after doublewords */
-3:	cmpwi	0,r4,4		/* is at least a full word left? */
-	blt	4f
-	lwz	r6,8(r3)	/* sum this word */
+	addic	r0,r5,0			/* clear carry */
+
+	srdi.	r6,r4,3			/* less than 8 bytes? */
+	beq	.Lcsum_tail_word
+
+	/*
+	 * If only halfword aligned, align to a double word. Since odd
+	 * aligned addresses should be rare and they would require more
+	 * work to calculate the correct checksum, we ignore that case
+	 * and take the potential slowdown of unaligned loads.
+	 */
+	rldicl. r6,r3,64-1,64-2		/* r6 = (r3 & 0x3) >> 1 */
+	beq	.Lcsum_aligned
+
+	li	r7,4
+	sub	r6,r7,r6
+	mtctr	r6
+
+1:
+	lhz	r6,0(r3)		/* align to doubleword */
+	subi	r4,r4,2
+	addi	r3,r3,2
+	adde	r0,r0,r6
+	bdnz	1b
+
+.Lcsum_aligned:
+	/*
+	 * We unroll the loop such that each iteration is 64 bytes with an
+	 * entry and exit limb of 64 bytes, meaning a minimum size of
+	 * 128 bytes.
+	 */
+	srdi.	r6,r4,7
+	beq	.Lcsum_tail_doublewords		/* len < 128 */
+
+	srdi	r6,r4,6
+	subi	r6,r6,1
+	mtctr	r6
+
+	stdu	r1,-STACKFRAMESIZE(r1)
+	std	r14,STK_REG(r14)(r1)
+	std	r15,STK_REG(r15)(r1)
+	std	r16,STK_REG(r16)(r1)
+
+	ld	r6,0(r3)
+	ld	r9,8(r3)
+
+	ld	r10,16(r3)
+	ld	r11,24(r3)
+
+	/*
+	 * On POWER6 and POWER7 back to back addes take 2 cycles because of
+	 * the XER dependency. This means the fastest this loop can go is
+	 * 16 cycles per iteration. The scheduling of the loop below has
+	 * been shown to hit this on both POWER6 and POWER7.
+	 */
+	.align 5
+2:
+	adde	r0,r0,r6
+	ld	r12,32(r3)
+	ld	r14,40(r3)
+
+	adde	r0,r0,r9
+	ld	r15,48(r3)
+	ld	r16,56(r3)
+	addi	r3,r3,64
+
+	adde	r0,r0,r10
+
+	adde	r0,r0,r11
+
+	adde	r0,r0,r12
+
+	adde	r0,r0,r14
+
+	adde	r0,r0,r15
+	ld	r6,0(r3)
+	ld	r9,8(r3)
+
+	adde	r0,r0,r16
+	ld	r10,16(r3)
+	ld	r11,24(r3)
+	bdnz	2b
+
+
+	adde	r0,r0,r6
+	ld	r12,32(r3)
+	ld	r14,40(r3)
+
+	adde	r0,r0,r9
+	ld	r15,48(r3)
+	ld	r16,56(r3)
+	addi	r3,r3,64
+
+	adde	r0,r0,r10
+	adde	r0,r0,r11
+	adde	r0,r0,r12
+	adde	r0,r0,r14
+	adde	r0,r0,r15
+	adde	r0,r0,r16
+
+	ld	r14,STK_REG(r14)(r1)
+	ld	r15,STK_REG(r15)(r1)
+	ld	r16,STK_REG(r16)(r1)
+	addi	r1,r1,STACKFRAMESIZE
+
+	andi.	r4,r4,63
+
+.Lcsum_tail_doublewords:		/* Up to 127 bytes to go */
+	srdi.	r6,r4,3
+	beq	.Lcsum_tail_word
+
+	mtctr	r6
+3:
+	ld	r6,0(r3)
+	addi	r3,r3,8
+	adde	r0,r0,r6
+	bdnz	3b
+
+	andi.	r4,r4,7
+
+.Lcsum_tail_word:			/* Up to 7 bytes to go */
+	srdi.	r6,r4,2
+	beq	.Lcsum_tail_halfword
+
+	lwz	r6,0(r3)
 	addi	r3,r3,4
+	adde	r0,r0,r6
 	subi	r4,r4,4
-	adde	r5,r5,r6
-4:	cmpwi	0,r4,2		/* is at least a halfword left? */
-        blt+	5f
-        lhz     r6,8(r3)        /* sum this halfword */
-        addi    r3,r3,2
-        subi    r4,r4,2
-        adde    r5,r5,r6
-5:	cmpwi	0,r4,1		/* is at least a byte left? */
-        bne+    6f
-        lbz     r6,8(r3)        /* sum this byte */
-        slwi    r6,r6,8         /* this byte is assumed to be the upper byte of a halfword */
-        adde    r5,r5,r6
-6:      addze	r5,r5		/* add in final carry */
-	rldicl  r4,r5,32,0      /* fold two 32-bit halves together */
-        add     r3,r4,r5
-        srdi    r3,r3,32
-        blr
+
+.Lcsum_tail_halfword:			/* Up to 3 bytes to go */
+	srdi.	r6,r4,1
+	beq	.Lcsum_tail_byte
+
+	lhz	r6,0(r3)
+	addi	r3,r3,2
+	adde	r0,r0,r6
+	subi	r4,r4,2
+
+.Lcsum_tail_byte:			/* Up to 1 byte to go */
+	andi.	r6,r4,1
+	beq	.Lcsum_finish
+
+	lbz	r6,0(r3)
+	sldi	r9,r6,8			/* Pad the byte out to 16 bits */
+	adde	r0,r0,r9
+
+.Lcsum_finish:
+	addze	r0,r0			/* add in final carry */
+	rldicl	r4,r0,32,0		/* fold two 32 bit halves together */
+	add	r3,r4,r0
+	srdi	r3,r3,32
+	blr
+
+
+	.macro source
+100:
+	.section __ex_table,"a"
+	.align 3
+	.llong 100b,.Lsrc_error
+	.previous
+	.endm
+
+	.macro dest
+200:
+	.section __ex_table,"a"
+	.align 3
+	.llong 200b,.Ldest_error
+	.previous
+	.endm
 
 /*
  * Computes the checksum of a memory block at src, length len,
  * and adds in "sum" (32-bit), while copying the block to dst.
  * If an access exception occurs on src or dst, it stores -EFAULT
- * to *src_err or *dst_err respectively, and (for an error on
- * src) zeroes the rest of dst.
- *
- * This code needs to be reworked to take advantage of 64 bit sum+copy.
- * However, due to tokenring halfword alignment problems this will be very
- * tricky.  For now we'll leave it until we instrument it somehow.
+ * to *src_err or *dst_err respectively. The caller must take any action
+ * required in this case (zeroing memory, recalculating partial checksum etc).
  *
  * csum_partial_copy_generic(r3=src, r4=dst, r5=len, r6=sum, r7=src_err, r8=dst_err)
  */
 _GLOBAL(csum_partial_copy_generic)
-	addic	r0,r6,0
-	subi	r3,r3,4
-	subi	r4,r4,4
-	srwi.	r6,r5,2
-	beq	3f		/* if we're doing < 4 bytes */
-	andi.	r9,r4,2		/* Align dst to longword boundary */
-	beq+	1f
-81:	lhz	r6,4(r3)	/* do 2 bytes to get aligned */
-	addi	r3,r3,2
+	addic	r0,r6,0			/* clear carry */
+
+	srdi.	r6,r5,3			/* less than 8 bytes? */
+	beq	.Lcopy_tail_word
+
+	/*
+	 * If only halfword aligned, align to a double word. Since odd
+	 * aligned addresses should be rare and they would require more
+	 * work to calculate the correct checksum, we ignore that case
+	 * and take the potential slowdown of unaligned loads.
+	 *
+	 * If the source and destination are relatively unaligned we only
+	 * align the source. This keeps things simple.
+	 */
+	rldicl. r6,r3,64-1,64-2		/* r6 = (r3 & 0x3) >> 1 */
+	beq	.Lcopy_aligned
+
+	li	r7,4
+	sub	r6,r7,r6
+	mtctr	r6
+
+1:
+source;	lhz	r6,0(r3)		/* align to doubleword */
 	subi	r5,r5,2
-91:	sth	r6,4(r4)
-	addi	r4,r4,2
-	addc	r0,r0,r6
-	srwi.	r6,r5,2		/* # words to do */
-	beq	3f
-1:	mtctr	r6
-82:	lwzu	r6,4(r3)	/* the bdnz has zero overhead, so it should */
-92:	stwu	r6,4(r4)	/* be unnecessary to unroll this loop */
-	adde	r0,r0,r6
-	bdnz	82b
-	andi.	r5,r5,3
-3:	cmpwi	0,r5,2
-	blt+	4f
-83:	lhz	r6,4(r3)
 	addi	r3,r3,2
-	subi	r5,r5,2
-93:	sth	r6,4(r4)
+	adde	r0,r0,r6
+dest;	sth	r6,0(r4)
 	addi	r4,r4,2
+	bdnz	1b
+
+.Lcopy_aligned:
+	/*
+	 * We unroll the loop such that each iteration is 64 bytes with an
+	 * entry and exit limb of 64 bytes, meaning a minimum size of
+	 * 128 bytes.
+	 */
+	srdi.	r6,r5,7
+	beq	.Lcopy_tail_doublewords		/* len < 128 */
+
+	srdi	r6,r5,6
+	subi	r6,r6,1
+	mtctr	r6
+
+	stdu	r1,-STACKFRAMESIZE(r1)
+	std	r14,STK_REG(r14)(r1)
+	std	r15,STK_REG(r15)(r1)
+	std	r16,STK_REG(r16)(r1)
+
+source;	ld	r6,0(r3)
+source;	ld	r9,8(r3)
+
+source;	ld	r10,16(r3)
+source;	ld	r11,24(r3)
+
+	/*
+	 * On POWER6 and POWER7 back to back addes take 2 cycles because of
+	 * the XER dependency. This means the fastest this loop can go is
+	 * 16 cycles per iteration. The scheduling of the loop below has
+	 * been shown to hit this on both POWER6 and POWER7.
+	 */
+	.align 5
+2:
 	adde	r0,r0,r6
-4:	cmpwi	0,r5,1
-	bne+	5f
-84:	lbz	r6,4(r3)
-94:	stb	r6,4(r4)
-	slwi	r6,r6,8		/* Upper byte of word */
+source;	ld	r12,32(r3)
+source;	ld	r14,40(r3)
+
+	adde	r0,r0,r9
+source;	ld	r15,48(r3)
+source;	ld	r16,56(r3)
+	addi	r3,r3,64
+
+	adde	r0,r0,r10
+dest;	std	r6,0(r4)
+dest;	std	r9,8(r4)
+
+	adde	r0,r0,r11
+dest;	std	r10,16(r4)
+dest;	std	r11,24(r4)
+
+	adde	r0,r0,r12
+dest;	std	r12,32(r4)
+dest;	std	r14,40(r4)
+
+	adde	r0,r0,r14
+dest;	std	r15,48(r4)
+dest;	std	r16,56(r4)
+	addi	r4,r4,64
+
+	adde	r0,r0,r15
+source;	ld	r6,0(r3)
+source;	ld	r9,8(r3)
+
+	adde	r0,r0,r16
+source;	ld	r10,16(r3)
+source;	ld	r11,24(r3)
+	bdnz	2b
+
+
 	adde	r0,r0,r6
-5:	addze	r3,r0		/* add in final carry (unlikely with 64-bit regs) */
-        rldicl  r4,r3,32,0      /* fold 64 bit value */
-        add     r3,r4,r3
-        srdi    r3,r3,32
+source;	ld	r12,32(r3)
+source;	ld	r14,40(r3)
+
+	adde	r0,r0,r9
+source;	ld	r15,48(r3)
+source;	ld	r16,56(r3)
+	addi	r3,r3,64
+
+	adde	r0,r0,r10
+dest;	std	r6,0(r4)
+dest;	std	r9,8(r4)
+
+	adde	r0,r0,r11
+dest;	std	r10,16(r4)
+dest;	std	r11,24(r4)
+
+	adde	r0,r0,r12
+dest;	std	r12,32(r4)
+dest;	std	r14,40(r4)
+
+	adde	r0,r0,r14
+dest;	std	r15,48(r4)
+dest;	std	r16,56(r4)
+	addi	r4,r4,64
+
+	adde	r0,r0,r15
+	adde	r0,r0,r16
+
+	ld	r14,STK_REG(r14)(r1)
+	ld	r15,STK_REG(r15)(r1)
+	ld	r16,STK_REG(r16)(r1)
+	addi	r1,r1,STACKFRAMESIZE
+
+	andi.	r5,r5,63
+
+.Lcopy_tail_doublewords:		/* Up to 127 bytes to go */
+	srdi.	r6,r5,3
+	beq	.Lcopy_tail_word
+
+	mtctr	r6
+3:
+source;	ld	r6,0(r3)
+	addi	r3,r3,8
+	adde	r0,r0,r6
+dest;	std	r6,0(r4)
+	addi	r4,r4,8
+	bdnz	3b
+
+	andi.	r5,r5,7
+
+.Lcopy_tail_word:			/* Up to 7 bytes to go */
+	srdi.	r6,r5,2
+	beq	.Lcopy_tail_halfword
+
+source;	lwz	r6,0(r3)
+	addi	r3,r3,4
+	adde	r0,r0,r6
+dest;	stw	r6,0(r4)
+	addi	r4,r4,4
+	subi	r5,r5,4
+
+.Lcopy_tail_halfword:			/* Up to 3 bytes to go */
+	srdi.	r6,r5,1
+	beq	.Lcopy_tail_byte
+
+source;	lhz	r6,0(r3)
+	addi	r3,r3,2
+	adde	r0,r0,r6
+dest;	sth	r6,0(r4)
+	addi	r4,r4,2
+	subi	r5,r5,2
+
+.Lcopy_tail_byte:			/* Up to 1 byte to go */
+	andi.	r6,r5,1
+	beq	.Lcopy_finish
+
+source;	lbz	r6,0(r3)
+	sldi	r9,r6,8			/* Pad the byte out to 16 bits */
+	adde	r0,r0,r9
+dest;	stb	r6,0(r4)
+
+.Lcopy_finish:
+	addze	r0,r0			/* add in final carry */
+	rldicl	r4,r0,32,0		/* fold two 32 bit halves together */
+	add	r3,r4,r0
+	srdi	r3,r3,32
 	blr
 
-/* These shouldn't go in the fixup section, since that would
-   cause the ex_table addresses to get out of order. */
-
-	.globl src_error_1
-src_error_1:
-	li	r6,0
-	subi	r5,r5,2
-95:	sth	r6,4(r4)
-	addi	r4,r4,2
-	srwi.	r6,r5,2
-	beq	3f
-	mtctr	r6
-	.globl src_error_2
-src_error_2:
-	li	r6,0
-96:	stwu	r6,4(r4)
-	bdnz	96b
-3:	andi.	r5,r5,3
-	beq	src_error
-	.globl src_error_3
-src_error_3:
-	li	r6,0
-	mtctr	r5
-	addi	r4,r4,3
-97:	stbu	r6,1(r4)
-	bdnz	97b
-	.globl src_error
-src_error:
+.Lsrc_error:
 	cmpdi	0,r7,0
-	beq	1f
+	beqlr
 	li	r6,-EFAULT
 	stw	r6,0(r7)
-1:	addze	r3,r0
 	blr
 
-	.globl dst_error
-dst_error:
+.Ldest_error:
 	cmpdi	0,r8,0
-	beq	1f
+	beqlr
 	li	r6,-EFAULT
 	stw	r6,0(r8)
-1:	addze	r3,r0
 	blr
-
-.section __ex_table,"a"
-	.align  3
-	.llong	81b,src_error_1
-	.llong	91b,dst_error
-	.llong	82b,src_error_2
-	.llong	92b,dst_error
-	.llong	83b,src_error_3
-	.llong	93b,dst_error
-	.llong	84b,src_error_3
-	.llong	94b,dst_error
-	.llong	95b,dst_error
-	.llong	96b,dst_error
-	.llong	97b,dst_error
diff --git a/arch/powerpc/lib/checksum_wrappers_64.c b/arch/powerpc/lib/checksum_wrappers_64.c
new file mode 100644
index 0000000..769b817
--- /dev/null
+++ b/arch/powerpc/lib/checksum_wrappers_64.c
@@ -0,0 +1,102 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2010
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#include <linux/module.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <asm/checksum.h>
+#include <asm/uaccess.h>
+
+__wsum csum_and_copy_from_user(const void __user *src, void *dst,
+			       int len, __wsum sum, int *err_ptr)
+{
+	unsigned int csum;
+
+	might_sleep();
+
+	*err_ptr = 0;
+
+	if (!len) {
+		csum = 0;
+		goto out;
+	}
+
+	if (unlikely((len < 0) || !access_ok(VERIFY_READ, src, len))) {
+		*err_ptr = -EFAULT;
+		csum = (__force unsigned int)sum;
+		goto out;
+	}
+
+	csum = csum_partial_copy_generic((void __force *)src, dst,
+					 len, sum, err_ptr, NULL);
+
+	if (unlikely(*err_ptr)) {
+		int missing = __copy_from_user(dst, src, len);
+
+		if (missing) {
+			memset(dst + len - missing, 0, missing);
+			*err_ptr = -EFAULT;
+		} else {
+			*err_ptr = 0;
+		}
+
+		csum = csum_partial(dst, len, sum);
+	}
+
+out:
+	return (__force __wsum)csum;
+}
+EXPORT_SYMBOL(csum_and_copy_from_user);
+
+__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
+			     __wsum sum, int *err_ptr)
+{
+	unsigned int csum;
+
+	might_sleep();
+
+	*err_ptr = 0;
+
+	if (!len) {
+		csum = 0;
+		goto out;
+	}
+
+	if (unlikely((len < 0) || !access_ok(VERIFY_WRITE, dst, len))) {
+		*err_ptr = -EFAULT;
+		csum = -1; /* invalid checksum */
+		goto out;
+	}
+
+	csum = csum_partial_copy_generic(src, (void __force *)dst,
+					 len, sum, NULL, err_ptr);
+
+	if (unlikely(*err_ptr)) {
+		csum = csum_partial(src, len, sum);
+
+		if (copy_to_user(dst, src, len)) {
+			*err_ptr = -EFAULT;
+			csum = -1; /* invalid checksum */
+		}
+	}
+
+out:
+	return (__force __wsum)csum;
+}
+EXPORT_SYMBOL(csum_and_copy_to_user);
diff --git a/arch/powerpc/lib/copy_32.S b/arch/powerpc/lib/copy_32.S
index 74a7f41..55f19f9 100644
--- a/arch/powerpc/lib/copy_32.S
+++ b/arch/powerpc/lib/copy_32.S
@@ -62,7 +62,7 @@
 
 	.text
 	.stabs	"arch/powerpc/lib/",N_SO,0,0,0f
-	.stabs	"copy32.S",N_SO,0,0,0f
+	.stabs	"copy_32.S",N_SO,0,0,0f
 0:
 
 CACHELINE_BYTES = L1_CACHE_BYTES
diff --git a/arch/powerpc/lib/ldstfp.S b/arch/powerpc/lib/ldstfp.S
index f644863..6a85380 100644
--- a/arch/powerpc/lib/ldstfp.S
+++ b/arch/powerpc/lib/ldstfp.S
@@ -17,6 +17,8 @@
 #include <asm/asm-offsets.h>
 #include <linux/errno.h>
 
+#ifdef CONFIG_PPC_FPU
+
 #define STKFRM	(PPC_MIN_STKFRM + 16)
 
 	.macro	extab	instr,handler
@@ -81,7 +83,7 @@
 	mfmsr	r6
 	ori	r7,r6,MSR_FP
 	cmpwi	cr7,r3,0
-	mtmsrd	r7
+	MTMSRD(r7)
 	isync
 	beq	cr7,1f
 	stfd	fr0,STKFRM-16(r1)
@@ -93,7 +95,7 @@
 	lfd	fr0,STKFRM-16(r1)
 4:	PPC_LL	r0,STKFRM+PPC_LR_STKOFF(r1)
 	mtlr	r0
-	mtmsrd	r6
+	MTMSRD(r6)
 	isync
 	mr	r3,r9
 	addi	r1,r1,STKFRM
@@ -108,7 +110,7 @@
 	mfmsr	r6
 	ori	r7,r6,MSR_FP
 	cmpwi	cr7,r3,0
-	mtmsrd	r7
+	MTMSRD(r7)
 	isync
 	beq	cr7,1f
 	stfd	fr0,STKFRM-16(r1)
@@ -120,7 +122,7 @@
 	lfd	fr0,STKFRM-16(r1)
 4:	PPC_LL	r0,STKFRM+PPC_LR_STKOFF(r1)
 	mtlr	r0
-	mtmsrd	r6
+	MTMSRD(r6)
 	isync
 	mr	r3,r9
 	addi	r1,r1,STKFRM
@@ -135,7 +137,7 @@
 	mfmsr	r6
 	ori	r7,r6,MSR_FP
 	cmpwi	cr7,r3,0
-	mtmsrd	r7
+	MTMSRD(r7)
 	isync
 	beq	cr7,1f
 	stfd	fr0,STKFRM-16(r1)
@@ -147,7 +149,7 @@
 	lfd	fr0,STKFRM-16(r1)
 4:	PPC_LL	r0,STKFRM+PPC_LR_STKOFF(r1)
 	mtlr	r0
-	mtmsrd	r6
+	MTMSRD(r6)
 	isync
 	mr	r3,r9
 	addi	r1,r1,STKFRM
@@ -162,7 +164,7 @@
 	mfmsr	r6
 	ori	r7,r6,MSR_FP
 	cmpwi	cr7,r3,0
-	mtmsrd	r7
+	MTMSRD(r7)
 	isync
 	beq	cr7,1f
 	stfd	fr0,STKFRM-16(r1)
@@ -174,7 +176,7 @@
 	lfd	fr0,STKFRM-16(r1)
 4:	PPC_LL	r0,STKFRM+PPC_LR_STKOFF(r1)
 	mtlr	r0
-	mtmsrd	r6
+	MTMSRD(r6)
 	isync
 	mr	r3,r9
 	addi	r1,r1,STKFRM
@@ -229,7 +231,7 @@
 	oris	r7,r6,MSR_VEC@h
 	cmpwi	cr7,r3,0
 	li	r8,STKFRM-16
-	mtmsrd	r7
+	MTMSRD(r7)
 	isync
 	beq	cr7,1f
 	stvx	vr0,r1,r8
@@ -241,7 +243,7 @@
 	lvx	vr0,r1,r8
 4:	PPC_LL	r0,STKFRM+PPC_LR_STKOFF(r1)
 	mtlr	r0
-	mtmsrd	r6
+	MTMSRD(r6)
 	isync
 	mr	r3,r9
 	addi	r1,r1,STKFRM
@@ -257,7 +259,7 @@
 	oris	r7,r6,MSR_VEC@h
 	cmpwi	cr7,r3,0
 	li	r8,STKFRM-16
-	mtmsrd	r7
+	MTMSRD(r7)
 	isync
 	beq	cr7,1f
 	stvx	vr0,r1,r8
@@ -269,7 +271,7 @@
 	lvx	vr0,r1,r8
 4:	PPC_LL	r0,STKFRM+PPC_LR_STKOFF(r1)
 	mtlr	r0
-	mtmsrd	r6
+	MTMSRD(r6)
 	isync
 	mr	r3,r9
 	addi	r1,r1,STKFRM
@@ -325,7 +327,7 @@
 	oris	r7,r6,MSR_VSX@h
 	cmpwi	cr7,r3,0
 	li	r8,STKFRM-16
-	mtmsrd	r7
+	MTMSRD(r7)
 	isync
 	beq	cr7,1f
 	STXVD2X(0,r1,r8)
@@ -337,7 +339,7 @@
 	LXVD2X(0,r1,r8)
 4:	PPC_LL	r0,STKFRM+PPC_LR_STKOFF(r1)
 	mtlr	r0
-	mtmsrd	r6
+	MTMSRD(r6)
 	isync
 	mr	r3,r9
 	addi	r1,r1,STKFRM
@@ -353,7 +355,7 @@
 	oris	r7,r6,MSR_VSX@h
 	cmpwi	cr7,r3,0
 	li	r8,STKFRM-16
-	mtmsrd	r7
+	MTMSRD(r7)
 	isync
 	beq	cr7,1f
 	STXVD2X(0,r1,r8)
@@ -365,7 +367,7 @@
 	LXVD2X(0,r1,r8)
 4:	PPC_LL	r0,STKFRM+PPC_LR_STKOFF(r1)
 	mtlr	r0
-	mtmsrd	r6
+	MTMSRD(r6)
 	isync
 	mr	r3,r9
 	addi	r1,r1,STKFRM
@@ -373,3 +375,5 @@
 	extab	2b,3b
 
 #endif /* CONFIG_VSX */
+
+#endif	/* CONFIG_PPC_FPU */
diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c
index 58e14fb..9b8182e 100644
--- a/arch/powerpc/lib/locks.c
+++ b/arch/powerpc/lib/locks.c
@@ -34,7 +34,7 @@
 		return;
 	holder_cpu = lock_value & 0xffff;
 	BUG_ON(holder_cpu >= NR_CPUS);
-	yield_count = lppaca[holder_cpu].yield_count;
+	yield_count = lppaca_of(holder_cpu).yield_count;
 	if ((yield_count & 1) == 0)
 		return;		/* virtual cpu is currently running */
 	rmb();
@@ -65,7 +65,7 @@
 		return;		/* no write lock at present */
 	holder_cpu = lock_value & 0xffff;
 	BUG_ON(holder_cpu >= NR_CPUS);
-	yield_count = lppaca[holder_cpu].yield_count;
+	yield_count = lppaca_of(holder_cpu).yield_count;
 	if ((yield_count & 1) == 0)
 		return;		/* virtual cpu is currently running */
 	rmb();
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index e0a9858..ae5189a 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -30,6 +30,7 @@
 #define XER_OV		0x40000000U
 #define XER_CA		0x20000000U
 
+#ifdef CONFIG_PPC_FPU
 /*
  * Functions in ldstfp.S
  */
@@ -41,6 +42,7 @@
 extern int do_stvx(int rn, unsigned long ea);
 extern int do_lxvd2x(int rn, unsigned long ea);
 extern int do_stxvd2x(int rn, unsigned long ea);
+#endif
 
 /*
  * Determine whether a conditional branch instruction would branch.
@@ -290,6 +292,7 @@
 	return write_mem_unaligned(val, ea, nb, regs);
 }
 
+#ifdef CONFIG_PPC_FPU
 /*
  * Check the address and alignment, and call func to do the actual
  * load or store.
@@ -351,6 +354,7 @@
 	}
 	return err;
 }
+#endif
 
 #ifdef CONFIG_ALTIVEC
 /* For Altivec/VMX, no need to worry about alignment */
@@ -1393,6 +1397,7 @@
 				regs->gpr[rd] = byterev_4(val);
 			goto ldst_done;
 
+#ifdef CONFIG_PPC_CPU
 		case 535:	/* lfsx */
 		case 567:	/* lfsux */
 			if (!(regs->msr & MSR_FP))
@@ -1424,6 +1429,7 @@
 			ea = xform_ea(instr, regs, u);
 			err = do_fp_store(rd, do_stfd, ea, 8, regs);
 			goto ldst_done;
+#endif
 
 #ifdef __powerpc64__
 		case 660:	/* stdbrx */
@@ -1534,6 +1540,7 @@
 		} while (++rd < 32);
 		goto instr_done;
 
+#ifdef CONFIG_PPC_FPU
 	case 48:	/* lfs */
 	case 49:	/* lfsu */
 		if (!(regs->msr & MSR_FP))
@@ -1565,6 +1572,7 @@
 		ea = dform_ea(instr, regs);
 		err = do_fp_store(rd, do_stfd, ea, 8, regs);
 		goto ldst_done;
+#endif
 
 #ifdef __powerpc64__
 	case 58:	/* ld[u], lwa */
diff --git a/arch/powerpc/math-emu/Makefile b/arch/powerpc/math-emu/Makefile
index 0c16ab9..7d1dba0 100644
--- a/arch/powerpc/math-emu/Makefile
+++ b/arch/powerpc/math-emu/Makefile
@@ -15,4 +15,4 @@
 CFLAGS_fabs.o = -fno-builtin-fabs
 CFLAGS_math.o = -fno-builtin-fabs
 
-EXTRA_CFLAGS = -I. -Iinclude/math-emu -w
+ccflags-y = -I. -Iinclude/math-emu -w
diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c
index 1dc2fa5..5810967 100644
--- a/arch/powerpc/mm/40x_mmu.c
+++ b/arch/powerpc/mm/40x_mmu.c
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/highmem.h>
+#include <linux/memblock.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -47,6 +48,7 @@
 #include <asm/bootx.h>
 #include <asm/machdep.h>
 #include <asm/setup.h>
+
 #include "mmu_decl.h"
 
 extern int __map_without_ltlbs;
@@ -139,8 +141,19 @@
 	 * coverage with normal-sized pages (or other reasons) do not
 	 * attempt to allocate outside the allowed range.
 	 */
-
-	__initial_memory_limit_addr = memstart_addr + mapped;
+	memblock_set_current_limit(mapped);
 
 	return mapped;
 }
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+				phys_addr_t first_memblock_size)
+{
+	/* We don't currently support the first MEMBLOCK not mapping 0
+	 * physical on those processors
+	 */
+	BUG_ON(first_memblock_base != 0);
+
+	/* 40x can only access 16MB at the moment (see head_40x.S) */
+	memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000));
+}
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index d8c6efb..024acab 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -24,6 +24,8 @@
  */
 
 #include <linux/init.h>
+#include <linux/memblock.h>
+
 #include <asm/mmu.h>
 #include <asm/system.h>
 #include <asm/page.h>
@@ -213,6 +215,18 @@
 	return total_lowmem;
 }
 
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+				phys_addr_t first_memblock_size)
+{
+	/* We don't currently support the first MEMBLOCK not mapping 0
+	 * physical on those processors
+	 */
+	BUG_ON(first_memblock_base != 0);
+
+	/* 44x has a 256M TLB entry pinned at boot */
+	memblock_set_current_limit(min_t(u64, first_memblock_size, PPC_PIN_SIZE));
+}
+
 #ifdef CONFIG_SMP
 void __cpuinit mmu_init_secondary(int cpu)
 {
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index ce68708..bdca46e 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -4,9 +4,7 @@
 
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS	+= -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64)	:= -mno-minimal-toc
 
 obj-y				:= fault.o mem.o pgtable.o gup.o \
 				   init_$(CONFIG_WORD_SIZE).o \
@@ -25,7 +23,7 @@
 				   mmu_context_hash$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_40x)		+= 40x_mmu.o
 obj-$(CONFIG_44x)		+= 44x_mmu.o
-obj-$(CONFIG_FSL_BOOKE)		+= fsl_booke_mmu.o
+obj-$(CONFIG_PPC_FSL_BOOK3E)	+= fsl_booke_mmu.o
 obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
 obj-$(CONFIG_PPC_MM_SLICES)	+= slice.o
 ifeq ($(CONFIG_HUGETLB_PAGE),y)
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 1bd712c..54f4fb9 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -30,6 +30,7 @@
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
 #include <linux/perf_event.h>
+#include <linux/magic.h>
 
 #include <asm/firmware.h>
 #include <asm/page.h>
@@ -385,6 +386,7 @@
 void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
 {
 	const struct exception_table_entry *entry;
+	unsigned long *stackend;
 
 	/* Are we prepared to handle this fault?  */
 	if ((entry = search_exception_tables(regs->nip)) != NULL) {
@@ -413,5 +415,9 @@
 	printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n",
 		regs->nip);
 
+	stackend = end_of_stack(current);
+	if (current != &init_task && *stackend != STACK_END_MAGIC)
+		printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
+
 	die("Kernel access of bad area", regs, sig);
 }
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index 4b66a1e..f7802c8 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -40,6 +40,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/highmem.h>
+#include <linux/memblock.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -56,11 +57,6 @@
 
 unsigned int tlbcam_index;
 
-
-#if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS)
-#error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS"
-#endif
-
 #define NUM_TLBCAMS	(64)
 struct tlbcam TLBCAM[NUM_TLBCAMS];
 
@@ -137,7 +133,8 @@
 	if (mmu_has_feature(MMU_FTR_BIG_PHYS))
 		TLBCAM[index].MAS7 = (u64)phys >> 32;
 
-	if (flags & _PAGE_USER) {
+	/* Below is unlikely -- only for large user pages or similar */
+	if (pte_user(flags)) {
 	   TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
 	   TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
 	}
@@ -184,6 +181,12 @@
 	return amount_mapped;
 }
 
+#ifdef CONFIG_PPC32
+
+#if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS)
+#error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS"
+#endif
+
 unsigned long __init mmu_mapin_ram(unsigned long top)
 {
 	return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1;
@@ -213,5 +216,15 @@
 	pr_cont("%lu Mb, residual: %dMb\n", tlbcam_sz(tlbcam_index - 1) >> 20,
 	        (unsigned int)((total_lowmem - __max_low_memory) >> 20));
 
-	__initial_memory_limit_addr = memstart_addr + __max_low_memory;
+	memblock_set_current_limit(memstart_addr + __max_low_memory);
 }
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+				phys_addr_t first_memblock_size)
+{
+	phys_addr_t limit = first_memblock_base + first_memblock_size;
+
+	/* 64M mapped initially according to head_fsl_booke.S */
+	memblock_set_current_limit(min_t(u64, limit, 0x04000000));
+}
+#endif
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 09dffe6..83f534d 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -588,7 +588,7 @@
 	unsigned long pteg_count;
 	unsigned long prot;
 	unsigned long base = 0, size = 0, limit;
-	int i;
+	struct memblock_region *reg;
 
 	DBG(" -> htab_initialize()\n");
 
@@ -625,7 +625,7 @@
 		if (machine_is(cell))
 			limit = 0x80000000;
 		else
-			limit = 0;
+			limit = MEMBLOCK_ALLOC_ANYWHERE;
 
 		table = memblock_alloc_base(htab_size_bytes, htab_size_bytes, limit);
 
@@ -649,7 +649,7 @@
 #ifdef CONFIG_DEBUG_PAGEALLOC
 	linear_map_hash_count = memblock_end_of_DRAM() >> PAGE_SHIFT;
 	linear_map_hash_slots = __va(memblock_alloc_base(linear_map_hash_count,
-						    1, memblock.rmo_size));
+						    1, ppc64_rma_size));
 	memset(linear_map_hash_slots, 0, linear_map_hash_count);
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
@@ -659,9 +659,9 @@
 	 */
 
 	/* create bolted the linear mapping in the hash table */
-	for (i=0; i < memblock.memory.cnt; i++) {
-		base = (unsigned long)__va(memblock.memory.region[i].base);
-		size = memblock.memory.region[i].size;
+	for_each_memblock(memory, reg) {
+		base = (unsigned long)__va(reg->base);
+		size = reg->size;
 
 		DBG("creating mapping for region: %lx..%lx (prot: %lx)\n",
 		    base, size, prot);
@@ -696,7 +696,8 @@
 #endif /* CONFIG_U3_DART */
 		BUG_ON(htab_bolt_mapping(base, base + size, __pa(base),
 				prot, mmu_linear_psize, mmu_kernel_ssize));
-       }
+	}
+	memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
 
 	/*
 	 * If we have a memory_limit and we've allocated TCEs then we need to
@@ -1247,3 +1248,23 @@
 	local_irq_restore(flags);
 }
 #endif /* CONFIG_DEBUG_PAGEALLOC */
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+				phys_addr_t first_memblock_size)
+{
+	/* We don't currently support the first MEMBLOCK not mapping 0
+	 * physical on those processors
+	 */
+	BUG_ON(first_memblock_base != 0);
+
+	/* On LPAR systems, the first entry is our RMA region,
+	 * non-LPAR 64-bit hash MMU systems don't have a limitation
+	 * on real mode access, but using the first entry works well
+	 * enough. We also clamp it to 1G to avoid some funky things
+	 * such as RTAS bugs etc...
+	 */
+	ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+
+	/* Finally limit subsequent allocations */
+	memblock_set_current_limit(ppc64_rma_size);
+}
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 6a6975d..742da43 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -92,12 +92,6 @@
 unsigned long __max_low_memory = MAX_LOW_MEM;
 
 /*
- * address of the limit of what is accessible with initial MMU setup -
- * 256MB usually, but only 16MB on 601.
- */
-phys_addr_t __initial_memory_limit_addr = (phys_addr_t)0x10000000;
-
-/*
  * Check for command-line options that affect what MMU_init will do.
  */
 void MMU_setup(void)
@@ -126,13 +120,6 @@
 	if (ppc_md.progress)
 		ppc_md.progress("MMU:enter", 0x111);
 
-	/* 601 can only access 16MB at the moment */
-	if (PVR_VER(mfspr(SPRN_PVR)) == 1)
-		__initial_memory_limit_addr = 0x01000000;
-	/* 8xx can only access 8MB at the moment */
-	if (PVR_VER(mfspr(SPRN_PVR)) == 0x50)
-		__initial_memory_limit_addr = 0x00800000;
-
 	/* parse args from command line */
 	MMU_setup();
 
@@ -190,20 +177,18 @@
 #ifdef CONFIG_BOOTX_TEXT
 	btext_unmap();
 #endif
+
+	/* Shortly after that, the entire linear mapping will be available */
+	memblock_set_current_limit(lowmem_end_addr);
 }
 
 /* This is only called until mem_init is done. */
 void __init *early_get_page(void)
 {
-	void *p;
-
-	if (init_bootmem_done) {
-		p = alloc_bootmem_pages(PAGE_SIZE);
-	} else {
-		p = __va(memblock_alloc_base(PAGE_SIZE, PAGE_SIZE,
-					__initial_memory_limit_addr));
-	}
-	return p;
+	if (init_bootmem_done)
+		return alloc_bootmem_pages(PAGE_SIZE);
+	else
+		return __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
 }
 
 /* Free up now-unused memory */
@@ -252,3 +237,17 @@
 }
 #endif
 
+
+#ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+				phys_addr_t first_memblock_size)
+{
+	/* We don't currently support the first MEMBLOCK not mapping 0
+	 * physical on those processors
+	 */
+	BUG_ON(first_memblock_base != 0);
+
+	/* 8xx can only access 8MB at the moment */
+	memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000));
+}
+#endif /* CONFIG_8xx */
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index ace85fa..6374b21 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -330,3 +330,4 @@
 	return 0;
 }
 #endif /* CONFIG_SPARSEMEM_VMEMMAP */
+
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 1a84a8d..a664996 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -82,18 +82,11 @@
 	return pfn < max_pfn;
 #else
 	unsigned long paddr = (pfn << PAGE_SHIFT);
-	int i;
-	for (i=0; i < memblock.memory.cnt; i++) {
-		unsigned long base;
+	struct memblock_region *reg;
 
-		base = memblock.memory.region[i].base;
-
-		if ((paddr >= base) &&
-			(paddr < (base + memblock.memory.region[i].size))) {
+	for_each_memblock(memory, reg)
+		if (paddr >= reg->base && paddr < (reg->base + reg->size))
 			return 1;
-		}
-	}
-
 	return 0;
 #endif
 }
@@ -149,23 +142,19 @@
 walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
 		void *arg, int (*func)(unsigned long, unsigned long, void *))
 {
-	struct memblock_property res;
-	unsigned long pfn, len;
-	u64 end;
+	struct memblock_region *reg;
+	unsigned long end_pfn = start_pfn + nr_pages;
+	unsigned long tstart, tend;
 	int ret = -1;
 
-	res.base = (u64) start_pfn << PAGE_SHIFT;
-	res.size = (u64) nr_pages << PAGE_SHIFT;
-
-	end = res.base + res.size - 1;
-	while ((res.base < end) && (memblock_find(&res) >= 0)) {
-		pfn = (unsigned long)(res.base >> PAGE_SHIFT);
-		len = (unsigned long)(res.size >> PAGE_SHIFT);
-		ret = (*func)(pfn, len, arg);
+	for_each_memblock(memory, reg) {
+		tstart = max(start_pfn, memblock_region_memory_base_pfn(reg));
+		tend = min(end_pfn, memblock_region_memory_end_pfn(reg));
+		if (tstart >= tend)
+			continue;
+		ret = (*func)(tstart, tend - tstart, arg);
 		if (ret)
 			break;
-		res.base += (res.size + 1);
-		res.size = (end - res.base + 1);
 	}
 	return ret;
 }
@@ -179,9 +168,9 @@
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 void __init do_init_bootmem(void)
 {
-	unsigned long i;
 	unsigned long start, bootmap_pages;
 	unsigned long total_pages;
+	struct memblock_region *reg;
 	int boot_mapsize;
 
 	max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
@@ -204,10 +193,10 @@
 	boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn);
 
 	/* Add active regions with valid PFNs */
-	for (i = 0; i < memblock.memory.cnt; i++) {
+	for_each_memblock(memory, reg) {
 		unsigned long start_pfn, end_pfn;
-		start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
-		end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+		start_pfn = memblock_region_memory_base_pfn(reg);
+		end_pfn = memblock_region_memory_end_pfn(reg);
 		add_active_range(0, start_pfn, end_pfn);
 	}
 
@@ -218,29 +207,21 @@
 	free_bootmem_with_active_regions(0, lowmem_end_addr >> PAGE_SHIFT);
 
 	/* reserve the sections we're already using */
-	for (i = 0; i < memblock.reserved.cnt; i++) {
-		unsigned long addr = memblock.reserved.region[i].base +
-				     memblock_size_bytes(&memblock.reserved, i) - 1;
-		if (addr < lowmem_end_addr)
-			reserve_bootmem(memblock.reserved.region[i].base,
-					memblock_size_bytes(&memblock.reserved, i),
-					BOOTMEM_DEFAULT);
-		else if (memblock.reserved.region[i].base < lowmem_end_addr) {
-			unsigned long adjusted_size = lowmem_end_addr -
-				      memblock.reserved.region[i].base;
-			reserve_bootmem(memblock.reserved.region[i].base,
-					adjusted_size, BOOTMEM_DEFAULT);
+	for_each_memblock(reserved, reg) {
+		unsigned long top = reg->base + reg->size - 1;
+		if (top < lowmem_end_addr)
+			reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+		else if (reg->base < lowmem_end_addr) {
+			unsigned long trunc_size = lowmem_end_addr - reg->base;
+			reserve_bootmem(reg->base, trunc_size, BOOTMEM_DEFAULT);
 		}
 	}
 #else
 	free_bootmem_with_active_regions(0, max_pfn);
 
 	/* reserve the sections we're already using */
-	for (i = 0; i < memblock.reserved.cnt; i++)
-		reserve_bootmem(memblock.reserved.region[i].base,
-				memblock_size_bytes(&memblock.reserved, i),
-				BOOTMEM_DEFAULT);
-
+	for_each_memblock(reserved, reg)
+		reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
 #endif
 	/* XXX need to clip this if using highmem? */
 	sparse_memory_present_with_active_regions(0);
@@ -251,22 +232,15 @@
 /* mark pages that don't exist as nosave */
 static int __init mark_nonram_nosave(void)
 {
-	unsigned long memblock_next_region_start_pfn,
-		      memblock_region_max_pfn;
-	int i;
+	struct memblock_region *reg, *prev = NULL;
 
-	for (i = 0; i < memblock.memory.cnt - 1; i++) {
-		memblock_region_max_pfn =
-			(memblock.memory.region[i].base >> PAGE_SHIFT) +
-			(memblock.memory.region[i].size >> PAGE_SHIFT);
-		memblock_next_region_start_pfn =
-			memblock.memory.region[i+1].base >> PAGE_SHIFT;
-
-		if (memblock_region_max_pfn < memblock_next_region_start_pfn)
-			register_nosave_region(memblock_region_max_pfn,
-					       memblock_next_region_start_pfn);
+	for_each_memblock(memory, reg) {
+		if (prev &&
+		    memblock_region_memory_end_pfn(prev) < memblock_region_memory_base_pfn(reg))
+			register_nosave_region(memblock_region_memory_end_pfn(prev),
+					       memblock_region_memory_base_pfn(reg));
+		prev = reg;
 	}
-
 	return 0;
 }
 
@@ -327,7 +301,7 @@
 		swiotlb_init(1);
 #endif
 
-	num_physpages = memblock.memory.size >> PAGE_SHIFT;
+	num_physpages = memblock_phys_mem_size() >> PAGE_SHIFT;
 	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
 
 #ifdef CONFIG_NEED_MULTIPLE_NODES
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c
index ddfd7ad..5ce9984 100644
--- a/arch/powerpc/mm/mmu_context_nohash.c
+++ b/arch/powerpc/mm/mmu_context_nohash.c
@@ -334,7 +334,7 @@
 	/* We don't touch CPU 0 map, it's allocated at aboot and kept
 	 * around forever
 	 */
-	if (cpu == 0)
+	if (cpu == boot_cpuid)
 		return NOTIFY_OK;
 
 	switch (action) {
@@ -420,9 +420,11 @@
 	 */
 	context_map = alloc_bootmem(CTX_MAP_SIZE);
 	context_mm = alloc_bootmem(sizeof(void *) * (last_context + 1));
+#ifndef CONFIG_SMP
 	stale_map[0] = alloc_bootmem(CTX_MAP_SIZE);
+#else
+	stale_map[boot_cpuid] = alloc_bootmem(CTX_MAP_SIZE);
 
-#ifdef CONFIG_SMP
 	register_cpu_notifier(&mmu_context_cpu_nb);
 #endif
 
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 63b84a0..dd0a258 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -140,10 +140,13 @@
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(unsigned long top);
 
-#elif defined(CONFIG_FSL_BOOKE)
+#elif defined(CONFIG_PPC_FSL_BOOK3E)
+extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx);
+#ifdef CONFIG_PPC32
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(unsigned long top);
 extern void adjust_total_lowmem(void);
+#endif
 extern void loadcam_entry(unsigned int index);
 
 struct tlbcam {
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 002878c..74505b2 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -802,16 +802,17 @@
 	unsigned long top_of_ram = memblock_end_of_DRAM();
 	unsigned long total_ram = memblock_phys_mem_size();
 	unsigned long start_pfn, end_pfn;
-	unsigned int i, nid = 0;
+	unsigned int nid = 0;
+	struct memblock_region *reg;
 
 	printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
 	       top_of_ram, total_ram);
 	printk(KERN_DEBUG "Memory hole size: %ldMB\n",
 	       (top_of_ram - total_ram) >> 20);
 
-	for (i = 0; i < memblock.memory.cnt; ++i) {
-		start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
-		end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+	for_each_memblock(memory, reg) {
+		start_pfn = memblock_region_memory_base_pfn(reg);
+		end_pfn = memblock_region_memory_end_pfn(reg);
 
 		fake_numa_create_new_node(end_pfn, &nid);
 		add_active_range(nid, start_pfn, end_pfn);
@@ -947,11 +948,11 @@
 static void mark_reserved_regions_for_nid(int nid)
 {
 	struct pglist_data *node = NODE_DATA(nid);
-	int i;
+	struct memblock_region *reg;
 
-	for (i = 0; i < memblock.reserved.cnt; i++) {
-		unsigned long physbase = memblock.reserved.region[i].base;
-		unsigned long size = memblock.reserved.region[i].size;
+	for_each_memblock(reserved, reg) {
+		unsigned long physbase = reg->base;
+		unsigned long size = reg->size;
 		unsigned long start_pfn = physbase >> PAGE_SHIFT;
 		unsigned long end_pfn = PFN_UP(physbase + size);
 		struct node_active_region node_ar;
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index f8a0182..11571e1 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -223,8 +223,7 @@
 	 * Find some memory for the hash table.
 	 */
 	if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
-	Hash = __va(memblock_alloc_base(Hash_size, Hash_size,
-				   __initial_memory_limit_addr));
+	Hash = __va(memblock_alloc(Hash_size, Hash_size));
 	cacheable_memzero(Hash, Hash_size);
 	_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
 
@@ -272,3 +271,18 @@
 
 	if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
 }
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+				phys_addr_t first_memblock_size)
+{
+	/* We don't currently support the first MEMBLOCK not mapping 0
+	 * physical on those processors
+	 */
+	BUG_ON(first_memblock_base != 0);
+
+	/* 601 can only access 16MB at the moment */
+	if (PVR_VER(mfspr(SPRN_PVR)) == 1)
+		memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01000000));
+	else /* Anything else has 256M mapped */
+		memblock_set_current_limit(min_t(u64, first_memblock_size, 0x10000000));
+}
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index fe391e9..36c0c44 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -349,11 +349,47 @@
 
 static void setup_page_sizes(void)
 {
-	unsigned int tlb0cfg = mfspr(SPRN_TLB0CFG);
-	unsigned int tlb0ps = mfspr(SPRN_TLB0PS);
-	unsigned int eptcfg = mfspr(SPRN_EPTCFG);
+	unsigned int tlb0cfg;
+	unsigned int tlb0ps;
+	unsigned int eptcfg;
 	int i, psize;
 
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	unsigned int mmucfg = mfspr(SPRN_MMUCFG);
+
+	if (((mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V1) &&
+		(mmu_has_feature(MMU_FTR_TYPE_FSL_E))) {
+		unsigned int tlb1cfg = mfspr(SPRN_TLB1CFG);
+		unsigned int min_pg, max_pg;
+
+		min_pg = (tlb1cfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
+		max_pg = (tlb1cfg & TLBnCFG_MAXSIZE) >> TLBnCFG_MAXSIZE_SHIFT;
+
+		for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
+			struct mmu_psize_def *def;
+			unsigned int shift;
+
+			def = &mmu_psize_defs[psize];
+			shift = def->shift;
+
+			if (shift == 0)
+				continue;
+
+			/* adjust to be in terms of 4^shift Kb */
+			shift = (shift - 10) >> 1;
+
+			if ((shift >= min_pg) && (shift <= max_pg))
+				def->flags |= MMU_PAGE_SIZE_DIRECT;
+		}
+
+		goto no_indirect;
+	}
+#endif
+
+	tlb0cfg = mfspr(SPRN_TLB0CFG);
+	tlb0ps = mfspr(SPRN_TLB0PS);
+	eptcfg = mfspr(SPRN_EPTCFG);
+
 	/* Look for supported direct sizes */
 	for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
 		struct mmu_psize_def *def = &mmu_psize_defs[psize];
@@ -505,10 +541,26 @@
 	 */
 	linear_map_top = memblock_end_of_DRAM();
 
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
+		unsigned int num_cams;
+
+		/* use a quarter of the TLBCAM for bolted linear map */
+		num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
+		linear_map_top = map_mem_in_cams(linear_map_top, num_cams);
+
+		/* limit memory so we dont have linear faults */
+		memblock_enforce_memory_limit(linear_map_top);
+		memblock_analyze();
+	}
+#endif
+
 	/* A sync won't hurt us after mucking around with
 	 * the MMU configuration
 	 */
 	mb();
+
+	memblock_set_current_limit(linear_map_top);
 }
 
 void __init early_init_mmu(void)
@@ -521,4 +573,18 @@
 	__early_init_mmu(0);
 }
 
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+				phys_addr_t first_memblock_size)
+{
+	/* On Embedded 64-bit, we adjust the RMA size to match
+	 * the bolted TLB entry. We know for now that only 1G
+	 * entries are supported though that may eventually
+	 * change. We crop it to the size of the first MEMBLOCK to
+	 * avoid going over total available memory just in case...
+	 */
+	ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+
+	/* Finally limit subsequent allocations */
+	memblock_set_current_limit(ppc64_memblock_base + ppc64_rma_size);
+}
 #endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/mm/tlb_nohash_low.S b/arch/powerpc/mm/tlb_nohash_low.S
index b9d9fed..af405ee 100644
--- a/arch/powerpc/mm/tlb_nohash_low.S
+++ b/arch/powerpc/mm/tlb_nohash_low.S
@@ -367,7 +367,7 @@
 #error Unsupported processor type !
 #endif
 
-#if defined(CONFIG_FSL_BOOKE)
+#if defined(CONFIG_PPC_FSL_BOOK3E)
 /*
  * extern void loadcam_entry(unsigned int index)
  *
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index e219ca4..73456c4 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -1,8 +1,6 @@
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS	+= -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64)	:= -mno-minimal-toc
 
 obj-$(CONFIG_OPROFILE) += oprofile.o
 
diff --git a/arch/powerpc/oprofile/backtrace.c b/arch/powerpc/oprofile/backtrace.c
index b4278cf..f75301f 100644
--- a/arch/powerpc/oprofile/backtrace.c
+++ b/arch/powerpc/oprofile/backtrace.c
@@ -105,7 +105,7 @@
 		}
 	} else {
 #ifdef CONFIG_PPC64
-		if (!test_thread_flag(TIF_32BIT)) {
+		if (!is_32bit_task()) {
 			while (depth--) {
 				sp = user_getsp64(sp, first_frame);
 				if (!sp)
diff --git a/arch/powerpc/oprofile/op_model_fsl_emb.c b/arch/powerpc/oprofile/op_model_fsl_emb.c
index 62312ab..d4e6507 100644
--- a/arch/powerpc/oprofile/op_model_fsl_emb.c
+++ b/arch/powerpc/oprofile/op_model_fsl_emb.c
@@ -2,7 +2,7 @@
  * Freescale Embedded oprofile support, based on ppc64 oprofile support
  * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
  *
- * Copyright (c) 2004 Freescale Semiconductor, Inc
+ * Copyright (c) 2004, 2010 Freescale Semiconductor, Inc
  *
  * Author: Andy Fleming
  * Maintainer: Kumar Gala <galak@kernel.crashing.org>
@@ -321,9 +321,6 @@
 	int val;
 	int i;
 
-	/* set the PMM bit (see comment below) */
-	mtmsr(mfmsr() | MSR_PMM);
-
 	pc = regs->nip;
 	is_kernel = is_kernel_addr(pc);
 
@@ -340,9 +337,13 @@
 	}
 
 	/* The freeze bit was set by the interrupt. */
-	/* Clear the freeze bit, and reenable the interrupt.
-	 * The counters won't actually start until the rfi clears
-	 * the PMM bit */
+	/* Clear the freeze bit, and reenable the interrupt.  The
+	 * counters won't actually start until the rfi clears the PMM
+	 * bit.  The PMM bit should not be set until after the interrupt
+	 * is cleared to avoid it getting lost in some hypervisor
+	 * environments.
+	 */
+	mtmsr(mfmsr() | MSR_PMM);
 	pmc_start_ctrs(1);
 }
 
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 69d668c..0f979c5 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -17,6 +17,16 @@
 	help
 	  This option enables support for the IBM PPC440EP evaluation board.
 
+config BLUESTONE
+	bool "Bluestone"
+	depends on 44x
+	default n
+	select PPC44x_SIMPLE
+	select APM821xx
+	select IBM_NEW_EMAC_RGMII
+	help
+	  This option enables support for the APM APM821xx Evaluation board.
+
 config EBONY
 	bool "Ebony"
 	depends on 44x
@@ -293,6 +303,12 @@
 	select IBM_NEW_EMAC_ZMII
 	select IBM_NEW_EMAC_TAH
 
+config APM821xx
+	bool
+	select PPC_FPU
+	select IBM_NEW_EMAC_EMAC4
+	select IBM_NEW_EMAC_TAH
+
 # 44x errata/workaround config symbols, selected by the CPU models above
 config IBM440EP_ERR42
 	bool
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c
index 5f7a29d..7ddcba3 100644
--- a/arch/powerpc/platforms/44x/ppc44x_simple.c
+++ b/arch/powerpc/platforms/44x/ppc44x_simple.c
@@ -52,6 +52,7 @@
 static char *board[] __initdata = {
 	"amcc,arches",
 	"amcc,bamboo",
+	"amcc,bluestone",
 	"amcc,canyonlands",
 	"amcc,glacier",
 	"ibm,ebony",
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
index 5b243bd..3dc2a8d 100644
--- a/arch/powerpc/platforms/512x/clock.c
+++ b/arch/powerpc/platforms/512x/clock.c
@@ -57,7 +57,7 @@
 	int id_match = 0;
 
 	if (dev == NULL || id == NULL)
-		return NULL;
+		return clk;
 
 	mutex_lock(&clocks_mutex);
 	list_for_each_entry(p, &clocks, node) {
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index 45c0cb9..18c1048 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -99,7 +99,7 @@
 	if (bus_range == NULL || len < 2 * sizeof(int)) {
 		printk(KERN_WARNING EFIKA_PLATFORM_NAME
 		       ": Can't get bus-range for %s\n", pcictrl->full_name);
-		return;
+		goto out_put;
 	}
 
 	if (bus_range[1] == bus_range[0])
@@ -111,12 +111,12 @@
 	printk(" controlled by %s\n", pcictrl->full_name);
 	printk("\n");
 
-	hose = pcibios_alloc_controller(of_node_get(pcictrl));
+	hose = pcibios_alloc_controller(pcictrl);
 	if (!hose) {
 		printk(KERN_WARNING EFIKA_PLATFORM_NAME
 		       ": Can't allocate PCI controller structure for %s\n",
 		       pcictrl->full_name);
-		return;
+		goto out_put;
 	}
 
 	hose->first_busno = bus_range[0];
@@ -124,6 +124,9 @@
 	hose->ops = &rtas_pci_ops;
 
 	pci_process_bridge_OF_ranges(hose, pcictrl, 0);
+	return;
+out_put:
+	of_node_put(pcictrl);
 }
 
 #else
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 6e90531..41f3a7e 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -325,12 +325,16 @@
 	clrbits32(&simple_gpio->simple_dvo, sync | out);
 	clrbits8(&wkup_gpio->wkup_dvo, reset);
 
-	/* wait at lease 1 us */
-	udelay(2);
+	/* wait for 1 us */
+	udelay(1);
 
 	/* Deassert reset */
 	setbits8(&wkup_gpio->wkup_dvo, reset);
 
+	/* wait at least 200ns */
+	/* 7 ~= (200ns * timebase) / ns2sec */
+	__delay(7);
+
 	/* Restore pin-muxing */
 	out_be32(&simple_gpio->port_config, mux);
 
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 021763a..73f4135f 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -10,12 +10,12 @@
 if PPC_83xx
 
 config MPC830x_RDB
-	bool "Freescale MPC830x RDB"
+	bool "Freescale MPC830x RDB and derivatives"
 	select DEFAULT_UIMAGE
 	select PPC_MPC831x
 	select FSL_GTM
 	help
-	  This option enables support for the MPC8308 RDB board.
+	  This option enables support for the MPC8308 RDB and MPC8308 P1M boards.
 
 config MPC831x_RDB
 	bool "Freescale MPC831x RDB"
diff --git a/arch/powerpc/platforms/83xx/mpc830x_rdb.c b/arch/powerpc/platforms/83xx/mpc830x_rdb.c
index ac102ee..846831d 100644
--- a/arch/powerpc/platforms/83xx/mpc830x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc830x_rdb.c
@@ -65,7 +65,8 @@
 	unsigned long root = of_get_flat_dt_root();
 
 	return of_flat_dt_is_compatible(root, "MPC8308RDB") ||
-	       of_flat_dt_is_compatible(root, "fsl,mpc8308rdb");
+	       of_flat_dt_is_compatible(root, "fsl,mpc8308rdb") ||
+	       of_flat_dt_is_compatible(root, "denx,mpc8308_p1m");
 }
 
 static struct of_device_id __initdata of_bus_ids[] = {
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index bea1f59..b6976e1 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -11,6 +11,8 @@
 
 if FSL_SOC_BOOKE
 
+if PPC32
+
 config MPC8540_ADS
 	bool "Freescale MPC8540 ADS"
 	select DEFAULT_UIMAGE
@@ -153,10 +155,20 @@
 	help
 	  This option enables support for the Wind River SBC8560 board
 
+config P3041_DS
+	bool "Freescale P3041 DS"
+	select DEFAULT_UIMAGE
+	select PPC_E500MC
+	select PHYS_64BIT
+	select SWIOTLB
+	select MPC8xxx_GPIO
+	select HAS_RAPIDIO
+	help
+	  This option enables support for the P3041 DS board
+
 config P4080_DS
 	bool "Freescale P4080 DS"
 	select DEFAULT_UIMAGE
-	select PPC_FSL_BOOK3E
 	select PPC_E500MC
 	select PHYS_64BIT
 	select SWIOTLB
@@ -165,6 +177,20 @@
 	help
 	  This option enables support for the P4080 DS board
 
+endif # PPC32
+
+config P5020_DS
+	bool "Freescale P5020 DS"
+	select DEFAULT_UIMAGE
+	select E500
+	select PPC_E500MC
+	select PHYS_64BIT
+	select SWIOTLB
+	select MPC8xxx_GPIO
+	select HAS_RAPIDIO
+	help
+	  This option enables support for the P5020 DS board
+
 endif # FSL_SOC_BOOKE
 
 config TQM85xx
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index a2ec3f8..dd70db7 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -11,7 +11,9 @@
 obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
 obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
 obj-$(CONFIG_P1022_DS)    += p1022_ds.o
+obj-$(CONFIG_P3041_DS)    += p3041_ds.o corenet_ds.o
 obj-$(CONFIG_P4080_DS)    += p4080_ds.o corenet_ds.o
+obj-$(CONFIG_P5020_DS)    += p5020_ds.o corenet_ds.o
 obj-$(CONFIG_STX_GP3)	  += stx_gp3.o
 obj-$(CONFIG_TQM85xx)	  += tqm85xx.o
 obj-$(CONFIG_SBC8560)     += sbc8560.o
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 34e0090..2b390d1 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -112,6 +112,8 @@
 	{ .compatible = "soc", },
 	{ .compatible = "simple-bus", },
 	{ .compatible = "gianfar", },
+	/* So that the DMA channel nodes can be probed individually: */
+	{ .compatible = "fsl,eloplus-dma", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c
new file mode 100644
index 0000000..0ed52e1
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p3041_ds.c
@@ -0,0 +1,64 @@
+/*
+ * P3041 DS Setup
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2009-2010 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p3041_ds_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	return of_flat_dt_is_compatible(root, "fsl,P3041DS");
+}
+
+define_machine(p3041_ds) {
+	.name			= "P3041 DS",
+	.probe			= p3041_ds_probe,
+	.setup_arch		= corenet_ds_setup_arch,
+	.init_IRQ		= corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_coreint_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
+
+machine_device_initcall(p3041_ds, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p3041_ds, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c
new file mode 100644
index 0000000..7467b71
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p5020_ds.c
@@ -0,0 +1,69 @@
+/*
+ * P5020 DS Setup
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2009-2010 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p5020_ds_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	return of_flat_dt_is_compatible(root, "fsl,P5020DS");
+}
+
+define_machine(p5020_ds) {
+	.name			= "P5020 DS",
+	.probe			= p5020_ds_probe,
+	.setup_arch		= corenet_ds_setup_arch,
+	.init_IRQ		= corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+/* coreint doesn't play nice with lazy EE, use legacy mpic for now */
+#ifdef CONFIG_PPC64
+	.get_irq		= mpic_get_irq,
+#else
+	.get_irq		= mpic_get_coreint_irq,
+#endif
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
+
+machine_device_initcall(p5020_ds, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p5020_ds, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index a6b1065..5c91a99 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/kexec.h>
+#include <linux/highmem.h>
 
 #include <asm/machdep.h>
 #include <asm/pgtable.h>
@@ -79,6 +80,7 @@
 	local_irq_save(flags);
 
 	out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr);
+#ifdef CONFIG_PPC32
 	out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
 
 	if (!ioremappable)
@@ -88,6 +90,12 @@
 	/* Wait a bit for the CPU to ack. */
 	while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
 		mdelay(1);
+#else
+	out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER),
+		__pa((u64)*((unsigned long long *) generic_secondary_smp_init)));
+
+	smp_generic_kick_cpu(nr);
+#endif
 
 	local_irq_restore(flags);
 
@@ -114,19 +122,15 @@
 };
 
 #ifdef CONFIG_KEXEC
-static int kexec_down_cpus = 0;
+atomic_t kexec_down_cpus = ATOMIC_INIT(0);
 
 void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary)
 {
-	mpic_teardown_this_cpu(1);
+	local_irq_disable();
 
-	/* When crashing, this gets called on all CPU's we only
-	 * take down the non-boot cpus */
-	if (smp_processor_id() != boot_cpuid)
-	{
-		local_irq_disable();
-		kexec_down_cpus++;
-
+	if (secondary) {
+		atomic_inc(&kexec_down_cpus);
+		/* loop forever */
 		while (1);
 	}
 }
@@ -137,16 +141,65 @@
 		ppc_md.kexec_cpu_down(0,1);
 }
 
-static void mpc85xx_smp_machine_kexec(struct kimage *image)
+static void map_and_flush(unsigned long paddr)
 {
-	int timeout = 2000;
+	struct page *page = pfn_to_page(paddr >> PAGE_SHIFT);
+	unsigned long kaddr  = (unsigned long)kmap(page);
+
+	flush_dcache_range(kaddr, kaddr + PAGE_SIZE);
+	kunmap(page);
+}
+
+/**
+ * Before we reset the other cores, we need to flush relevant cache
+ * out to memory so we don't get anything corrupted, some of these flushes
+ * are performed out of an overabundance of caution as interrupts are not
+ * disabled yet and we can switch cores
+ */
+static void mpc85xx_smp_flush_dcache_kexec(struct kimage *image)
+{
+	kimage_entry_t *ptr, entry;
+	unsigned long paddr;
 	int i;
 
-	set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid));
+	if (image->type == KEXEC_TYPE_DEFAULT) {
+		/* normal kexec images are stored in temporary pages */
+		for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE);
+		     ptr = (entry & IND_INDIRECTION) ?
+				phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
+			if (!(entry & IND_DESTINATION)) {
+				map_and_flush(entry);
+			}
+		}
+		/* flush out last IND_DONE page */
+		map_and_flush(entry);
+	} else {
+		/* crash type kexec images are copied to the crash region */
+		for (i = 0; i < image->nr_segments; i++) {
+			struct kexec_segment *seg = &image->segment[i];
+			for (paddr = seg->mem; paddr < seg->mem + seg->memsz;
+			     paddr += PAGE_SIZE) {
+				map_and_flush(paddr);
+			}
+		}
+	}
 
-	smp_call_function(mpc85xx_smp_kexec_down, NULL, 0);
+	/* also flush the kimage struct to be passed in as well */
+	flush_dcache_range((unsigned long)image,
+			   (unsigned long)image + sizeof(*image));
+}
 
-	while ( (kexec_down_cpus != (num_online_cpus() - 1)) &&
+static void mpc85xx_smp_machine_kexec(struct kimage *image)
+{
+	int timeout = INT_MAX;
+	int i, num_cpus = num_present_cpus();
+
+	mpc85xx_smp_flush_dcache_kexec(image);
+
+	if (image->type == KEXEC_TYPE_DEFAULT)
+		smp_call_function(mpc85xx_smp_kexec_down, NULL, 0);
+
+	while ( (atomic_read(&kexec_down_cpus) != (num_cpus - 1)) &&
 		( timeout > 0 ) )
 	{
 		timeout--;
@@ -155,7 +208,7 @@
 	if ( !timeout )
 		printk(KERN_ERR "Unable to bring down secondary cpu(s)");
 
-	for (i = 0; i < num_present_cpus(); i++)
+	for (i = 0; i < num_cpus; i++)
 	{
 		if ( i == smp_processor_id() ) continue;
 		mpic_reset_core(i);
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index d361f81..111138c 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -125,6 +125,7 @@
 
 config E500
 	select FSL_EMB_PERFMON
+	select PPC_FSL_BOOK3E
 	bool
 
 config PPC_E500MC
@@ -166,9 +167,14 @@
 
 config FSL_BOOKE
 	bool
-	depends on E200 || E500
+	depends on (E200 || E500) && PPC32
 	default y
 
+# this is for common code between PPC32 & PPC64 FSL BOOKE
+config PPC_FSL_BOOK3E
+	bool
+	select FSL_EMB_PERFMON
+	default y if FSL_BOOKE
 
 config PTE_64BIT
 	bool
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 9708553..e3e379c 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -310,9 +310,9 @@
 }
 
 static struct irq_chip msic_irq_chip = {
-	.mask		= mask_msi_irq,
-	.unmask		= unmask_msi_irq,
-	.shutdown	= unmask_msi_irq,
+	.irq_mask	= mask_msi_irq,
+	.irq_unmask	= unmask_msi_irq,
+	.irq_shutdown	= mask_msi_irq,
 	.name		= "AXON-MSI",
 };
 
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 1d3c4ef..5ec1e47 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -173,8 +173,10 @@
 		return -ENODEV;
 
 	size = of_get_property(np, "ibm,cbe-ptcal-size", NULL);
-	if (!size)
+	if (!size) {
+		of_node_put(np);
 		return -ENODEV;
+	}
 
 	pr_debug("%s: enabling PTCAL, size = 0x%x\n", __func__, *size);
 	order = get_order(*size);
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 5876e88..3f2e557 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -258,8 +258,10 @@
 		return NO_IRQ;
 	imap += intsize + 1;
 	tmp = of_get_property(iic, "#interrupt-cells", NULL);
-	if (tmp == NULL)
+	if (tmp == NULL) {
+		of_node_put(iic);
 		return NO_IRQ;
+	}
 	intsize = *tmp;
 	/* Assume unit is last entry of interrupt specifier */
 	unit = imap[intsize - 1];
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 1a40da9..02f7b11 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -154,6 +154,7 @@
 	.release = spufs_attr_release,					\
 	.read	 = spufs_attr_read,					\
 	.write	 = spufs_attr_write,					\
+	.llseek  = generic_file_llseek,					\
 };
 
 
@@ -521,6 +522,7 @@
 	.release = spufs_cntl_release,
 	.read = simple_attr_read,
 	.write = simple_attr_write,
+	.llseek	= generic_file_llseek,
 	.mmap = spufs_cntl_mmap,
 };
 
@@ -714,6 +716,7 @@
 static const struct file_operations spufs_mbox_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_mbox_read,
+	.llseek	= no_llseek,
 };
 
 static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
@@ -743,6 +746,7 @@
 static const struct file_operations spufs_mbox_stat_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_mbox_stat_read,
+	.llseek = no_llseek,
 };
 
 /* low-level ibox access function */
@@ -863,6 +867,7 @@
 	.read	= spufs_ibox_read,
 	.poll	= spufs_ibox_poll,
 	.fasync	= spufs_ibox_fasync,
+	.llseek = no_llseek,
 };
 
 static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
@@ -890,6 +895,7 @@
 static const struct file_operations spufs_ibox_stat_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_ibox_stat_read,
+	.llseek = no_llseek,
 };
 
 /* low-level mailbox write */
@@ -1011,6 +1017,7 @@
 	.write	= spufs_wbox_write,
 	.poll	= spufs_wbox_poll,
 	.fasync	= spufs_wbox_fasync,
+	.llseek = no_llseek,
 };
 
 static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
@@ -1038,6 +1045,7 @@
 static const struct file_operations spufs_wbox_stat_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_wbox_stat_read,
+	.llseek = no_llseek,
 };
 
 static int spufs_signal1_open(struct inode *inode, struct file *file)
@@ -1166,6 +1174,7 @@
 	.read = spufs_signal1_read,
 	.write = spufs_signal1_write,
 	.mmap = spufs_signal1_mmap,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations spufs_signal1_nosched_fops = {
@@ -1173,6 +1182,7 @@
 	.release = spufs_signal1_release,
 	.write = spufs_signal1_write,
 	.mmap = spufs_signal1_mmap,
+	.llseek = no_llseek,
 };
 
 static int spufs_signal2_open(struct inode *inode, struct file *file)
@@ -1305,6 +1315,7 @@
 	.read = spufs_signal2_read,
 	.write = spufs_signal2_write,
 	.mmap = spufs_signal2_mmap,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations spufs_signal2_nosched_fops = {
@@ -1312,6 +1323,7 @@
 	.release = spufs_signal2_release,
 	.write = spufs_signal2_write,
 	.mmap = spufs_signal2_mmap,
+	.llseek = no_llseek,
 };
 
 /*
@@ -1451,6 +1463,7 @@
 	.open	 = spufs_mss_open,
 	.release = spufs_mss_release,
 	.mmap	 = spufs_mss_mmap,
+	.llseek  = no_llseek,
 };
 
 static int
@@ -1508,6 +1521,7 @@
 	.open	 = spufs_psmap_open,
 	.release = spufs_psmap_release,
 	.mmap	 = spufs_psmap_mmap,
+	.llseek  = no_llseek,
 };
 
 
@@ -1871,6 +1885,7 @@
 	.fsync	 = spufs_mfc_fsync,
 	.fasync	 = spufs_mfc_fasync,
 	.mmap	 = spufs_mfc_mmap,
+	.llseek  = no_llseek,
 };
 
 static int spufs_npc_set(void *data, u64 val)
@@ -2246,6 +2261,7 @@
 static const struct file_operations spufs_dma_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_dma_info_read,
+	.llseek = no_llseek,
 };
 
 static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx,
@@ -2299,6 +2315,7 @@
 static const struct file_operations spufs_proxydma_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_proxydma_info_read,
+	.llseek = no_llseek,
 };
 
 static int spufs_show_tid(struct seq_file *s, void *private)
@@ -2585,6 +2602,7 @@
 	.read		= spufs_switch_log_read,
 	.poll		= spufs_switch_log_poll,
 	.release	= spufs_switch_log_release,
+	.llseek		= no_llseek,
 };
 
 /**
diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c
index ba3588f..d3ceff0 100644
--- a/arch/powerpc/platforms/chrp/nvram.c
+++ b/arch/powerpc/platforms/chrp/nvram.c
@@ -74,8 +74,10 @@
 		return;
 
 	nbytes_p = of_get_property(nvram, "#bytes", &proplen);
-	if (nbytes_p == NULL || proplen != sizeof(unsigned int))
+	if (nbytes_p == NULL || proplen != sizeof(unsigned int)) {
+		of_node_put(nvram);
 		return;
+	}
 
 	nvram_size = *nbytes_p;
 
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
index 5cdcc7c..649473a 100644
--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -65,7 +65,7 @@
 
 void __init wii_memory_fixups(void)
 {
-	struct memblock_property *p = memblock.memory.region;
+	struct memblock_region *p = memblock.memory.regions;
 
 	/*
 	 * This is part of a workaround to allow the use of two
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index ce01492..a7602b1 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS	+= -mno-minimal-toc
+ccflags-y	:= -mno-minimal-toc
 
 obj-y += exception.o
 obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 7f45a51..fdb7384 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -243,7 +243,7 @@
 	pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
 
 	for (i = 0; i < NR_CPUS; i++) {
-		if (lppaca[i].dyn_proc_status >= 2)
+		if (lppaca_of(i).dyn_proc_status >= 2)
 			continue;
 
 		snprintf(p, 32 - (p - buf), "@%d", i);
@@ -251,7 +251,7 @@
 
 		dt_prop_str(dt, "device_type", device_type_cpu);
 
-		index = lppaca[i].dyn_hv_phys_proc_index;
+		index = lppaca_of(i).dyn_hv_phys_proc_index;
 		d = &xIoHriProcessorVpd[index];
 
 		dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index 33e5fc7..42d0a88 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -1249,6 +1249,7 @@
 
 static const struct file_operations proc_vmlinux_operations = {
 	.write		= proc_mf_change_vmlinux,
+	.llseek		= default_llseek,
 };
 
 static int __init mf_proc_init(void)
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c
index 6590850..6c60299 100644
--- a/arch/powerpc/platforms/iseries/smp.c
+++ b/arch/powerpc/platforms/iseries/smp.c
@@ -91,7 +91,7 @@
 	BUG_ON((nr < 0) || (nr >= NR_CPUS));
 
 	/* Verify that our partition has a processor nr */
-	if (lppaca[nr].dyn_proc_status >= 2)
+	if (lppaca_of(nr).dyn_proc_status >= 2)
 		return;
 
 	/* The processor is currently spinning, waiting
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 3fff8d9..fe34c3d 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -358,6 +358,7 @@
 	model = (const unsigned char *)of_get_property(np, "model", NULL);
 	if (!model) {
 		printk(KERN_ERR "%s: Unabel to get model info\n", __func__);
+		of_node_put(np);
 		return -ENODEV;
 	}
 
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index cec6359..b0c3777 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -837,8 +837,10 @@
 		return NULL;
  find_it:
 	dev = pmf_find_device(actor);
-	if (dev == NULL)
-		return NULL;
+	if (dev == NULL) {
+		result = NULL;
+		goto out;
+	}
 
 	list_for_each_entry(func, &dev->functions, link) {
 		if (name && strcmp(name, func->name))
@@ -850,8 +852,9 @@
 		result = func;
 		break;
 	}
-	of_node_put(actor);
 	pmf_put_device(dev);
+out:
+	of_node_put(actor);
 	return result;
 }
 
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 046ace9..59eb8bd 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -1,14 +1,9 @@
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS		+= -mno-minimal-toc
-endif
-
-ifeq ($(CONFIG_PPC_PSERIES_DEBUG),y)
-EXTRA_CFLAGS		+= -DDEBUG
-endif
+ccflags-$(CONFIG_PPC64)			:= -mno-minimal-toc
+ccflags-$(CONFIG_PPC_PSERIES_DEBUG)	+= -DDEBUG
 
 obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
 			   setup.o iommu.o event_sources.o ras.o \
-			   firmware.o power.o dlpar.o
+			   firmware.o power.o dlpar.o mobility.o
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_XICS)	+= xics.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
@@ -23,7 +18,7 @@
 obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
 obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst.o
-obj-$(CONFIG_PHYP_DUMP)	+= phyp_dump.o
+obj-$(CONFIG_PHYP_DUMP)		+= phyp_dump.o
 obj-$(CONFIG_CMM)		+= cmm.o
 obj-$(CONFIG_DTL)		+= dtl.o
 
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 72d8054..b74a923 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -33,7 +33,7 @@
 	u32	prop_offset;
 };
 
-static void dlpar_free_cc_property(struct property *prop)
+void dlpar_free_cc_property(struct property *prop)
 {
 	kfree(prop->name);
 	kfree(prop->value);
@@ -55,13 +55,12 @@
 
 	prop->length = ccwa->prop_length;
 	value = (char *)ccwa + ccwa->prop_offset;
-	prop->value = kzalloc(prop->length, GFP_KERNEL);
+	prop->value = kmemdup(value, prop->length, GFP_KERNEL);
 	if (!prop->value) {
 		dlpar_free_cc_property(prop);
 		return NULL;
 	}
 
-	memcpy(prop->value, value, prop->length);
 	return prop;
 }
 
@@ -102,7 +101,7 @@
 	kfree(dn);
 }
 
-static void dlpar_free_cc_nodes(struct device_node *dn)
+void dlpar_free_cc_nodes(struct device_node *dn)
 {
 	if (dn->child)
 		dlpar_free_cc_nodes(dn->child);
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index a00addb5..c371bc0 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -23,37 +23,22 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
+#include <linux/spinlock.h>
 #include <asm/smp.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/firmware.h>
+#include <asm/lppaca.h>
 
 #include "plpar_wrappers.h"
 
-/*
- * Layout of entries in the hypervisor's DTL buffer. Although we don't
- * actually access the internals of an entry (we only need to know the size),
- * we might as well define it here for reference.
- */
-struct dtl_entry {
-	u8	dispatch_reason;
-	u8	preempt_reason;
-	u16	processor_id;
-	u32	enqueue_to_dispatch_time;
-	u32	ready_to_enqueue_time;
-	u32	waiting_to_ready_time;
-	u64	timebase;
-	u64	fault_addr;
-	u64	srr0;
-	u64	srr1;
-};
-
 struct dtl {
 	struct dtl_entry	*buf;
 	struct dentry		*file;
 	int			cpu;
 	int			buf_entries;
 	u64			last_idx;
+	spinlock_t		lock;
 };
 static DEFINE_PER_CPU(struct dtl, cpu_dtl);
 
@@ -72,26 +57,98 @@
 static int dtl_buf_entries = (16 * 85);
 
 
-static int dtl_enable(struct dtl *dtl)
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+struct dtl_ring {
+	u64	write_index;
+	struct dtl_entry *write_ptr;
+	struct dtl_entry *buf;
+	struct dtl_entry *buf_end;
+	u8	saved_dtl_mask;
+};
+
+static DEFINE_PER_CPU(struct dtl_ring, dtl_rings);
+
+static atomic_t dtl_count;
+
+/*
+ * The cpu accounting code controls the DTL ring buffer, and we get
+ * given entries as they are processed.
+ */
+static void consume_dtle(struct dtl_entry *dtle, u64 index)
+{
+	struct dtl_ring *dtlr = &__get_cpu_var(dtl_rings);
+	struct dtl_entry *wp = dtlr->write_ptr;
+	struct lppaca *vpa = local_paca->lppaca_ptr;
+
+	if (!wp)
+		return;
+
+	*wp = *dtle;
+	barrier();
+
+	/* check for hypervisor ring buffer overflow, ignore this entry if so */
+	if (index + N_DISPATCH_LOG < vpa->dtl_idx)
+		return;
+
+	++wp;
+	if (wp == dtlr->buf_end)
+		wp = dtlr->buf;
+	dtlr->write_ptr = wp;
+
+	/* incrementing write_index makes the new entry visible */
+	smp_wmb();
+	++dtlr->write_index;
+}
+
+static int dtl_start(struct dtl *dtl)
+{
+	struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu);
+
+	dtlr->buf = dtl->buf;
+	dtlr->buf_end = dtl->buf + dtl->buf_entries;
+	dtlr->write_index = 0;
+
+	/* setting write_ptr enables logging into our buffer */
+	smp_wmb();
+	dtlr->write_ptr = dtl->buf;
+
+	/* enable event logging */
+	dtlr->saved_dtl_mask = lppaca_of(dtl->cpu).dtl_enable_mask;
+	lppaca_of(dtl->cpu).dtl_enable_mask |= dtl_event_mask;
+
+	dtl_consumer = consume_dtle;
+	atomic_inc(&dtl_count);
+	return 0;
+}
+
+static void dtl_stop(struct dtl *dtl)
+{
+	struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu);
+
+	dtlr->write_ptr = NULL;
+	smp_wmb();
+
+	dtlr->buf = NULL;
+
+	/* restore dtl_enable_mask */
+	lppaca_of(dtl->cpu).dtl_enable_mask = dtlr->saved_dtl_mask;
+
+	if (atomic_dec_and_test(&dtl_count))
+		dtl_consumer = NULL;
+}
+
+static u64 dtl_current_index(struct dtl *dtl)
+{
+	return per_cpu(dtl_rings, dtl->cpu).write_index;
+}
+
+#else /* CONFIG_VIRT_CPU_ACCOUNTING */
+
+static int dtl_start(struct dtl *dtl)
 {
 	unsigned long addr;
 	int ret, hwcpu;
 
-	/* only allow one reader */
-	if (dtl->buf)
-		return -EBUSY;
-
-	/* we need to store the original allocation size for use during read */
-	dtl->buf_entries = dtl_buf_entries;
-
-	dtl->buf = kmalloc_node(dtl->buf_entries * sizeof(struct dtl_entry),
-			GFP_KERNEL, cpu_to_node(dtl->cpu));
-	if (!dtl->buf) {
-		printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
-				__func__, dtl->cpu);
-		return -ENOMEM;
-	}
-
 	/* Register our dtl buffer with the hypervisor. The HV expects the
 	 * buffer size to be passed in the second word of the buffer */
 	((u32 *)dtl->buf)[1] = dtl->buf_entries * sizeof(struct dtl_entry);
@@ -102,34 +159,82 @@
 	if (ret) {
 		printk(KERN_WARNING "%s: DTL registration for cpu %d (hw %d) "
 		       "failed with %d\n", __func__, dtl->cpu, hwcpu, ret);
-		kfree(dtl->buf);
 		return -EIO;
 	}
 
 	/* set our initial buffer indices */
-	dtl->last_idx = lppaca[dtl->cpu].dtl_idx = 0;
+	lppaca_of(dtl->cpu).dtl_idx = 0;
 
 	/* ensure that our updates to the lppaca fields have occurred before
 	 * we actually enable the logging */
 	smp_wmb();
 
 	/* enable event logging */
-	lppaca[dtl->cpu].dtl_enable_mask = dtl_event_mask;
+	lppaca_of(dtl->cpu).dtl_enable_mask = dtl_event_mask;
 
 	return 0;
 }
 
-static void dtl_disable(struct dtl *dtl)
+static void dtl_stop(struct dtl *dtl)
 {
 	int hwcpu = get_hard_smp_processor_id(dtl->cpu);
 
-	lppaca[dtl->cpu].dtl_enable_mask = 0x0;
+	lppaca_of(dtl->cpu).dtl_enable_mask = 0x0;
 
 	unregister_dtl(hwcpu, __pa(dtl->buf));
+}
 
+static u64 dtl_current_index(struct dtl *dtl)
+{
+	return lppaca_of(dtl->cpu).dtl_idx;
+}
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+
+static int dtl_enable(struct dtl *dtl)
+{
+	long int n_entries;
+	long int rc;
+	struct dtl_entry *buf = NULL;
+
+	/* only allow one reader */
+	if (dtl->buf)
+		return -EBUSY;
+
+	n_entries = dtl_buf_entries;
+	buf = kmalloc_node(n_entries * sizeof(struct dtl_entry),
+			GFP_KERNEL, cpu_to_node(dtl->cpu));
+	if (!buf) {
+		printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
+				__func__, dtl->cpu);
+		return -ENOMEM;
+	}
+
+	spin_lock(&dtl->lock);
+	rc = -EBUSY;
+	if (!dtl->buf) {
+		/* store the original allocation size for use during read */
+		dtl->buf_entries = n_entries;
+		dtl->buf = buf;
+		dtl->last_idx = 0;
+		rc = dtl_start(dtl);
+		if (rc)
+			dtl->buf = NULL;
+	}
+	spin_unlock(&dtl->lock);
+
+	if (rc)
+		kfree(buf);
+	return rc;
+}
+
+static void dtl_disable(struct dtl *dtl)
+{
+	spin_lock(&dtl->lock);
+	dtl_stop(dtl);
 	kfree(dtl->buf);
 	dtl->buf = NULL;
 	dtl->buf_entries = 0;
+	spin_unlock(&dtl->lock);
 }
 
 /* file interface */
@@ -157,8 +262,9 @@
 static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len,
 		loff_t *pos)
 {
-	int rc, cur_idx, last_idx, n_read, n_req, read_size;
+	long int rc, n_read, n_req, read_size;
 	struct dtl *dtl;
+	u64 cur_idx, last_idx, i;
 
 	if ((len % sizeof(struct dtl_entry)) != 0)
 		return -EINVAL;
@@ -171,41 +277,48 @@
 	/* actual number of entries read */
 	n_read = 0;
 
-	cur_idx = lppaca[dtl->cpu].dtl_idx;
+	spin_lock(&dtl->lock);
+
+	cur_idx = dtl_current_index(dtl);
 	last_idx = dtl->last_idx;
 
-	if (cur_idx - last_idx > dtl->buf_entries) {
-		pr_debug("%s: hv buffer overflow for cpu %d, samples lost\n",
-				__func__, dtl->cpu);
-	}
+	if (last_idx + dtl->buf_entries <= cur_idx)
+		last_idx = cur_idx - dtl->buf_entries + 1;
 
-	cur_idx  %= dtl->buf_entries;
-	last_idx %= dtl->buf_entries;
+	if (last_idx + n_req > cur_idx)
+		n_req = cur_idx - last_idx;
+
+	if (n_req > 0)
+		dtl->last_idx = last_idx + n_req;
+
+	spin_unlock(&dtl->lock);
+
+	if (n_req <= 0)
+		return 0;
+
+	i = last_idx % dtl->buf_entries;
 
 	/* read the tail of the buffer if we've wrapped */
-	if (last_idx > cur_idx) {
-		read_size = min(n_req, dtl->buf_entries - last_idx);
+	if (i + n_req > dtl->buf_entries) {
+		read_size = dtl->buf_entries - i;
 
-		rc = copy_to_user(buf, &dtl->buf[last_idx],
+		rc = copy_to_user(buf, &dtl->buf[i],
 				read_size * sizeof(struct dtl_entry));
 		if (rc)
 			return -EFAULT;
 
-		last_idx = 0;
+		i = 0;
 		n_req -= read_size;
 		n_read += read_size;
 		buf += read_size * sizeof(struct dtl_entry);
 	}
 
 	/* .. and now the head */
-	read_size = min(n_req, cur_idx - last_idx);
-	rc = copy_to_user(buf, &dtl->buf[last_idx],
-			read_size * sizeof(struct dtl_entry));
+	rc = copy_to_user(buf, &dtl->buf[i], n_req * sizeof(struct dtl_entry));
 	if (rc)
 		return -EFAULT;
 
-	n_read += read_size;
-	dtl->last_idx += n_read;
+	n_read += n_req;
 
 	return n_read * sizeof(struct dtl_entry);
 }
@@ -263,6 +376,7 @@
 	/* set up the per-cpu log structures */
 	for_each_possible_cpu(i) {
 		struct dtl *dtl = &per_cpu(cpu_dtl, i);
+		spin_lock_init(&dtl->lock);
 		dtl->cpu = i;
 
 		rc = dtl_setup_file(dtl);
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index cf79b46..f129040 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -248,11 +248,13 @@
 	int hwcpu = get_hard_smp_processor_id(cpu);
 	unsigned long addr;
 	long ret;
+	struct paca_struct *pp;
+	struct dtl_entry *dtl;
 
 	if (cpu_has_feature(CPU_FTR_ALTIVEC))
-		lppaca[cpu].vmxregs_in_use = 1;
+		lppaca_of(cpu).vmxregs_in_use = 1;
 
-	addr = __pa(&lppaca[cpu]);
+	addr = __pa(&lppaca_of(cpu));
 	ret = register_vpa(hwcpu, addr);
 
 	if (ret) {
@@ -274,6 +276,25 @@
 			       "registration for cpu %d (hw %d) of area %lx "
 			       "returns %ld\n", cpu, hwcpu, addr, ret);
 	}
+
+	/*
+	 * Register dispatch trace log, if one has been allocated.
+	 */
+	pp = &paca[cpu];
+	dtl = pp->dispatch_log;
+	if (dtl) {
+		pp->dtl_ridx = 0;
+		pp->dtl_curr = dtl;
+		lppaca_of(cpu).dtl_idx = 0;
+
+		/* hypervisor reads buffer length from this field */
+		dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES;
+		ret = register_dtl(hwcpu, __pa(dtl));
+		if (ret)
+			pr_warn("DTL registration failed for cpu %d (%ld)\n",
+				cpu, ret);
+		lppaca_of(cpu).dtl_enable_mask = 2;
+	}
 }
 
 static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
new file mode 100644
index 0000000..3e7f651
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -0,0 +1,362 @@
+/*
+ * Support for Partition Mobility/Migration
+ *
+ * Copyright (C) 2010 Nathan Fontenot
+ * Copyright (C) 2010 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/smp.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include <asm/rtas.h>
+#include "pseries.h"
+
+static struct kobject *mobility_kobj;
+
+struct update_props_workarea {
+	u32 phandle;
+	u32 state;
+	u64 reserved;
+	u32 nprops;
+};
+
+#define NODE_ACTION_MASK	0xff000000
+#define NODE_COUNT_MASK		0x00ffffff
+
+#define DELETE_DT_NODE	0x01000000
+#define UPDATE_DT_NODE	0x02000000
+#define ADD_DT_NODE	0x03000000
+
+static int mobility_rtas_call(int token, char *buf)
+{
+	int rc;
+
+	spin_lock(&rtas_data_buf_lock);
+
+	memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE);
+	rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, 1);
+	memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);
+
+	spin_unlock(&rtas_data_buf_lock);
+	return rc;
+}
+
+static int delete_dt_node(u32 phandle)
+{
+	struct device_node *dn;
+
+	dn = of_find_node_by_phandle(phandle);
+	if (!dn)
+		return -ENOENT;
+
+	dlpar_detach_node(dn);
+	return 0;
+}
+
+static int update_dt_property(struct device_node *dn, struct property **prop,
+			      const char *name, u32 vd, char *value)
+{
+	struct property *new_prop = *prop;
+	struct property *old_prop;
+	int more = 0;
+
+	/* A negative 'vd' value indicates that only part of the new property
+	 * value is contained in the buffer and we need to call
+	 * ibm,update-properties again to get the rest of the value.
+	 *
+	 * A negative value is also the two's compliment of the actual value.
+	 */
+	if (vd & 0x80000000) {
+		vd = ~vd + 1;
+		more = 1;
+	}
+
+	if (new_prop) {
+		/* partial property fixup */
+		char *new_data = kzalloc(new_prop->length + vd, GFP_KERNEL);
+		if (!new_data)
+			return -ENOMEM;
+
+		memcpy(new_data, new_prop->value, new_prop->length);
+		memcpy(new_data + new_prop->length, value, vd);
+
+		kfree(new_prop->value);
+		new_prop->value = new_data;
+		new_prop->length += vd;
+	} else {
+		new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
+		if (!new_prop)
+			return -ENOMEM;
+
+		new_prop->name = kstrdup(name, GFP_KERNEL);
+		if (!new_prop->name) {
+			kfree(new_prop);
+			return -ENOMEM;
+		}
+
+		new_prop->length = vd;
+		new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
+		if (!new_prop->value) {
+			kfree(new_prop->name);
+			kfree(new_prop);
+			return -ENOMEM;
+		}
+
+		memcpy(new_prop->value, value, vd);
+		*prop = new_prop;
+	}
+
+	if (!more) {
+		old_prop = of_find_property(dn, new_prop->name, NULL);
+		if (old_prop)
+			prom_update_property(dn, new_prop, old_prop);
+		else
+			prom_add_property(dn, new_prop);
+
+		new_prop = NULL;
+	}
+
+	return 0;
+}
+
+static int update_dt_node(u32 phandle)
+{
+	struct update_props_workarea *upwa;
+	struct device_node *dn;
+	struct property *prop = NULL;
+	int i, rc;
+	char *prop_data;
+	char *rtas_buf;
+	int update_properties_token;
+
+	update_properties_token = rtas_token("ibm,update-properties");
+	if (update_properties_token == RTAS_UNKNOWN_SERVICE)
+		return -EINVAL;
+
+	rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+	if (!rtas_buf)
+		return -ENOMEM;
+
+	dn = of_find_node_by_phandle(phandle);
+	if (!dn) {
+		kfree(rtas_buf);
+		return -ENOENT;
+	}
+
+	upwa = (struct update_props_workarea *)&rtas_buf[0];
+	upwa->phandle = phandle;
+
+	do {
+		rc = mobility_rtas_call(update_properties_token, rtas_buf);
+		if (rc < 0)
+			break;
+
+		prop_data = rtas_buf + sizeof(*upwa);
+
+		for (i = 0; i < upwa->nprops; i++) {
+			char *prop_name;
+			u32 vd;
+
+			prop_name = prop_data + 1;
+			prop_data += strlen(prop_name) + 1;
+			vd = *prop_data++;
+
+			switch (vd) {
+			case 0x00000000:
+				/* name only property, nothing to do */
+				break;
+
+			case 0x80000000:
+				prop = of_find_property(dn, prop_name, NULL);
+				prom_remove_property(dn, prop);
+				prop = NULL;
+				break;
+
+			default:
+				rc = update_dt_property(dn, &prop, prop_name,
+							vd, prop_data);
+				if (rc) {
+					printk(KERN_ERR "Could not update %s"
+					       " property\n", prop_name);
+				}
+
+				prop_data += vd;
+			}
+		}
+	} while (rc == 1);
+
+	of_node_put(dn);
+	kfree(rtas_buf);
+	return 0;
+}
+
+static int add_dt_node(u32 parent_phandle, u32 drc_index)
+{
+	struct device_node *dn;
+	struct device_node *parent_dn;
+	int rc;
+
+	dn = dlpar_configure_connector(drc_index);
+	if (!dn)
+		return -ENOENT;
+
+	parent_dn = of_find_node_by_phandle(parent_phandle);
+	if (!parent_dn) {
+		dlpar_free_cc_nodes(dn);
+		return -ENOENT;
+	}
+
+	dn->parent = parent_dn;
+	rc = dlpar_attach_node(dn);
+	if (rc)
+		dlpar_free_cc_nodes(dn);
+
+	of_node_put(parent_dn);
+	return rc;
+}
+
+static int pseries_devicetree_update(void)
+{
+	char *rtas_buf;
+	u32 *data;
+	int update_nodes_token;
+	int rc;
+
+	update_nodes_token = rtas_token("ibm,update-nodes");
+	if (update_nodes_token == RTAS_UNKNOWN_SERVICE)
+		return -EINVAL;
+
+	rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+	if (!rtas_buf)
+		return -ENOMEM;
+
+	do {
+		rc = mobility_rtas_call(update_nodes_token, rtas_buf);
+		if (rc && rc != 1)
+			break;
+
+		data = (u32 *)rtas_buf + 4;
+		while (*data & NODE_ACTION_MASK) {
+			int i;
+			u32 action = *data & NODE_ACTION_MASK;
+			int node_count = *data & NODE_COUNT_MASK;
+
+			data++;
+
+			for (i = 0; i < node_count; i++) {
+				u32 phandle = *data++;
+				u32 drc_index;
+
+				switch (action) {
+				case DELETE_DT_NODE:
+					delete_dt_node(phandle);
+					break;
+				case UPDATE_DT_NODE:
+					update_dt_node(phandle);
+					break;
+				case ADD_DT_NODE:
+					drc_index = *data++;
+					add_dt_node(phandle, drc_index);
+					break;
+				}
+			}
+		}
+	} while (rc == 1);
+
+	kfree(rtas_buf);
+	return rc;
+}
+
+void post_mobility_fixup(void)
+{
+	int rc;
+	int activate_fw_token;
+
+	rc = pseries_devicetree_update();
+	if (rc) {
+		printk(KERN_ERR "Initial post-mobility device tree update "
+		       "failed: %d\n", rc);
+		return;
+	}
+
+	activate_fw_token = rtas_token("ibm,activate-firmware");
+	if (activate_fw_token == RTAS_UNKNOWN_SERVICE) {
+		printk(KERN_ERR "Could not make post-mobility "
+		       "activate-fw call.\n");
+		return;
+	}
+
+	rc = rtas_call(activate_fw_token, 0, 1, NULL);
+	if (!rc) {
+		rc = pseries_devicetree_update();
+		if (rc)
+			printk(KERN_ERR "Secondary post-mobility device tree "
+			       "update failed: %d\n", rc);
+	} else {
+		printk(KERN_ERR "Post-mobility activate-fw failed: %d\n", rc);
+		return;
+	}
+
+	return;
+}
+
+static ssize_t migrate_store(struct class *class, struct class_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct rtas_args args;
+	u64 streamid;
+	int rc;
+
+	rc = strict_strtoull(buf, 0, &streamid);
+	if (rc)
+		return rc;
+
+	memset(&args, 0, sizeof(args));
+	args.token = rtas_token("ibm,suspend-me");
+	args.nargs = 2;
+	args.nret = 1;
+
+	args.args[0] = streamid >> 32 ;
+	args.args[1] = streamid & 0xffffffff;
+	args.rets = &args.args[args.nargs];
+
+	do {
+		args.rets[0] = 0;
+		rc = rtas_ibm_suspend_me(&args);
+		if (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE)
+			ssleep(1);
+	} while (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE);
+
+	if (rc)
+		return rc;
+	else if (args.rets[0])
+		return args.rets[0];
+
+	post_mobility_fixup();
+	return count;
+}
+
+static CLASS_ATTR(migration, S_IWUSR, NULL, migrate_store);
+
+static int __init mobility_sysfs_init(void)
+{
+	int rc;
+
+	mobility_kobj = kobject_create_and_add("mobility", kernel_kobj);
+	if (!mobility_kobj)
+		return -ENOMEM;
+
+	rc = sysfs_create_file(mobility_kobj, &class_attr_migration.attr);
+
+	return rc;
+}
+device_initcall(mobility_sysfs_init);
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 40c93ca..e9f6d28 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -17,6 +17,8 @@
 extern void request_event_sources_irqs(struct device_node *np,
 				       irq_handler_t handler, const char *name);
 
+#include <linux/of.h>
+
 extern void __init fw_feature_init(const char *hypertas, unsigned long len);
 
 struct pt_regs;
@@ -47,4 +49,11 @@
 
 extern void find_udbg_vterm(void);
 
+/* Dynamic logical Partitioning/Mobility */
+extern void dlpar_free_cc_nodes(struct device_node *);
+extern void dlpar_free_cc_property(struct property *);
+extern struct device_node *dlpar_configure_connector(u32);
+extern int dlpar_attach_node(struct device_node *);
+extern int dlpar_detach_node(struct device_node *);
+
 #endif /* _PSERIES_PSERIES_H */
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 57ddbb4..1de2cbb 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -539,7 +539,8 @@
 }
 
 static const struct file_operations ofdt_fops = {
-	.write = ofdt_write
+	.write = ofdt_write,
+	.llseek = noop_llseek,
 };
 
 /* create /proc/powerpc/ofdt write-only by root */
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 80e9e76..5544572 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -170,6 +170,7 @@
 	.write		= scanlog_write,
 	.open		= scanlog_open,
 	.release	= scanlog_release,
+	.llseek		= noop_llseek,
 };
 
 static int __init scanlog_init(void)
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index a6d19e3..d345bfd 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -273,6 +273,58 @@
 	.notifier_call = pci_dn_reconfig_notifier,
 };
 
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+/*
+ * Allocate space for the dispatch trace log for all possible cpus
+ * and register the buffers with the hypervisor.  This is used for
+ * computing time stolen by the hypervisor.
+ */
+static int alloc_dispatch_logs(void)
+{
+	int cpu, ret;
+	struct paca_struct *pp;
+	struct dtl_entry *dtl;
+
+	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
+		return 0;
+
+	for_each_possible_cpu(cpu) {
+		pp = &paca[cpu];
+		dtl = kmalloc_node(DISPATCH_LOG_BYTES, GFP_KERNEL,
+				   cpu_to_node(cpu));
+		if (!dtl) {
+			pr_warn("Failed to allocate dispatch trace log for cpu %d\n",
+				cpu);
+			pr_warn("Stolen time statistics will be unreliable\n");
+			break;
+		}
+
+		pp->dtl_ridx = 0;
+		pp->dispatch_log = dtl;
+		pp->dispatch_log_end = dtl + N_DISPATCH_LOG;
+		pp->dtl_curr = dtl;
+	}
+
+	/* Register the DTL for the current (boot) cpu */
+	dtl = get_paca()->dispatch_log;
+	get_paca()->dtl_ridx = 0;
+	get_paca()->dtl_curr = dtl;
+	get_paca()->lppaca_ptr->dtl_idx = 0;
+
+	/* hypervisor reads buffer length from this field */
+	dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES;
+	ret = register_dtl(hard_smp_processor_id(), __pa(dtl));
+	if (ret)
+		pr_warn("DTL registration failed for boot cpu %d (%d)\n",
+			smp_processor_id(), ret);
+	get_paca()->lppaca_ptr->dtl_enable_mask = 2;
+
+	return 0;
+}
+
+early_initcall(alloc_dispatch_logs);
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+
 static void __init pSeries_setup_arch(void)
 {
 	/* Discover PIC type and setup ppc_md accordingly */
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 93834b0..7b96e5a 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -178,7 +178,7 @@
 	if (!distribute_irqs)
 		return default_server;
 
-	if (!cpumask_equal(cpumask, cpu_all_mask)) {
+	if (!cpumask_subset(cpu_possible_mask, cpumask)) {
 		int server = cpumask_first_and(cpu_online_mask, cpumask);
 
 		if (server < nr_cpu_ids)
@@ -243,7 +243,7 @@
 	 * at that level, so we do it here by hand.
 	 */
 	if (irq_to_desc(virq)->msi_desc)
-		unmask_msi_irq(virq);
+		unmask_msi_irq(irq_get_irq_data(virq));
 
 	/* unmask it */
 	xics_unmask_irq(virq);
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 5642924..0bef9da 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -1,8 +1,6 @@
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS			+= -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64)		:= -mno-minimal-toc
 
 mpic-msi-obj-$(CONFIG_PCI_MSI)	+= mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
 obj-$(CONFIG_MPIC)		+= mpic.o $(mpic-msi-obj-y)
@@ -20,6 +18,7 @@
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
 obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o
 obj-$(CONFIG_MPC8xxx_GPIO)	+= mpc8xxx_gpio.o
+obj-$(CONFIG_FSL_85XX_CACHE_SRAM)	+= fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
 obj-$(CONFIG_SIMPLE_GPIO)	+= simple_gpio.o
 obj-$(CONFIG_RAPIDIO)		+= fsl_rio.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 559db2b..17cf15e 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -70,6 +70,8 @@
 static int dart_dirty;
 static int dart_is_u4;
 
+#define DART_U4_BYPASS_BASE	0x8000000000ull
+
 #define DBG(...)
 
 static inline void dart_tlb_invalidate_all(void)
@@ -292,12 +294,20 @@
 	set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map);
 }
 
-static void pci_dma_dev_setup_dart(struct pci_dev *dev)
+static void dma_dev_setup_dart(struct device *dev)
 {
 	/* We only have one iommu table on the mac for now, which makes
 	 * things simple. Setup all PCI devices to point to this table
 	 */
-	set_iommu_table_base(&dev->dev, &iommu_table_dart);
+	if (get_dma_ops(dev) == &dma_direct_ops)
+		set_dma_offset(dev, DART_U4_BYPASS_BASE);
+	else
+		set_iommu_table_base(dev, &iommu_table_dart);
+}
+
+static void pci_dma_dev_setup_dart(struct pci_dev *dev)
+{
+	dma_dev_setup_dart(&dev->dev);
 }
 
 static void pci_dma_bus_setup_dart(struct pci_bus *bus)
@@ -315,6 +325,45 @@
 		PCI_DN(dn)->iommu_table = &iommu_table_dart;
 }
 
+static bool dart_device_on_pcie(struct device *dev)
+{
+	struct device_node *np = of_node_get(dev->of_node);
+
+	while(np) {
+		if (of_device_is_compatible(np, "U4-pcie") ||
+		    of_device_is_compatible(np, "u4-pcie")) {
+			of_node_put(np);
+			return true;
+		}
+		np = of_get_next_parent(np);
+	}
+	return false;
+}
+
+static int dart_dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+		return -EIO;
+
+	/* U4 supports a DART bypass, we use it for 64-bit capable
+	 * devices to improve performances. However, that only works
+	 * for devices connected to U4 own PCIe interface, not bridged
+	 * through hypertransport. We need the device to support at
+	 * least 40 bits of addresses.
+	 */
+	if (dart_device_on_pcie(dev) && dma_mask >= DMA_BIT_MASK(40)) {
+		dev_info(dev, "Using 64-bit DMA iommu bypass\n");
+		set_dma_ops(dev, &dma_direct_ops);
+	} else {
+		dev_info(dev, "Using 32-bit DMA via iommu\n");
+		set_dma_ops(dev, &dma_iommu_ops);
+	}
+	dma_dev_setup_dart(dev);
+
+	*dev->dma_mask = dma_mask;
+	return 0;
+}
+
 void __init iommu_init_early_dart(void)
 {
 	struct device_node *dn;
@@ -328,20 +377,25 @@
 		dart_is_u4 = 1;
 	}
 
+	/* Initialize the DART HW */
+	if (dart_init(dn) != 0)
+		goto bail;
+
 	/* Setup low level TCE operations for the core IOMMU code */
 	ppc_md.tce_build = dart_build;
 	ppc_md.tce_free  = dart_free;
 	ppc_md.tce_flush = dart_flush;
 
-	/* Initialize the DART HW */
-	if (dart_init(dn) == 0) {
-		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart;
-		ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart;
+	/* Setup bypass if supported */
+	if (dart_is_u4)
+		ppc_md.dma_set_mask = dart_dma_set_mask;
 
-		/* Setup pci_dma ops */
-		set_pci_dma_ops(&dma_iommu_ops);
-		return;
-	}
+	ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart;
+	ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart;
+
+	/* Setup pci_dma ops */
+	set_pci_dma_ops(&dma_iommu_ops);
+	return;
 
  bail:
 	/* If init failed, use direct iommu and null setup functions */
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
new file mode 100644
index 0000000..60c9c0b
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc
+ *
+ * QorIQ based Cache Controller Memory Mapped Registers
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __FSL_85XX_CACHE_CTLR_H__
+#define __FSL_85XX_CACHE_CTLR_H__
+
+#define L2CR_L2FI		0x40000000	/* L2 flash invalidate */
+#define L2CR_L2IO		0x00200000	/* L2 instruction only */
+#define L2CR_SRAM_ZERO		0x00000000	/* L2SRAM zero size */
+#define L2CR_SRAM_FULL		0x00010000	/* L2SRAM full size */
+#define L2CR_SRAM_HALF		0x00020000	/* L2SRAM half size */
+#define L2CR_SRAM_TWO_HALFS	0x00030000	/* L2SRAM two half sizes */
+#define L2CR_SRAM_QUART		0x00040000	/* L2SRAM one quarter size */
+#define L2CR_SRAM_TWO_QUARTS	0x00050000	/* L2SRAM two quarter size */
+#define L2CR_SRAM_EIGHTH	0x00060000	/* L2SRAM one eighth size */
+#define L2CR_SRAM_TWO_EIGHTH	0x00070000	/* L2SRAM two eighth size */
+
+#define L2SRAM_OPTIMAL_SZ_SHIFT	0x00000003	/* Optimum size for L2SRAM */
+
+#define L2SRAM_BAR_MSK_LO18	0xFFFFC000	/* Lower 18 bits */
+#define L2SRAM_BARE_MSK_HI4	0x0000000F	/* Upper 4 bits */
+
+enum cache_sram_lock_ways {
+	LOCK_WAYS_ZERO,
+	LOCK_WAYS_EIGHTH,
+	LOCK_WAYS_TWO_EIGHTH,
+	LOCK_WAYS_HALF = 4,
+	LOCK_WAYS_FULL = 8,
+};
+
+struct mpc85xx_l2ctlr {
+	u32	ctl;		/* 0x000 - L2 control */
+	u8	res1[0xC];
+	u32	ewar0;		/* 0x010 - External write address 0 */
+	u32	ewarea0;	/* 0x014 - External write address extended 0 */
+	u32	ewcr0;		/* 0x018 - External write ctrl */
+	u8	res2[4];
+	u32	ewar1;		/* 0x020 - External write address 1 */
+	u32	ewarea1;	/* 0x024 - External write address extended 1 */
+	u32	ewcr1;		/* 0x028 - External write ctrl 1 */
+	u8	res3[4];
+	u32	ewar2;		/* 0x030 - External write address 2 */
+	u32	ewarea2;	/* 0x034 - External write address extended 2 */
+	u32	ewcr2;		/* 0x038 - External write ctrl 2 */
+	u8	res4[4];
+	u32	ewar3;		/* 0x040 - External write address 3 */
+	u32	ewarea3;	/* 0x044 - External write address extended 3 */
+	u32	ewcr3;		/* 0x048 - External write ctrl 3 */
+	u8	res5[0xB4];
+	u32	srbar0;		/* 0x100 - SRAM base address 0 */
+	u32	srbarea0;	/* 0x104 - SRAM base addr reg ext address 0 */
+	u32	srbar1;		/* 0x108 - SRAM base address 1 */
+	u32	srbarea1;	/* 0x10C - SRAM base addr reg ext address 1 */
+	u8	res6[0xCF0];
+	u32	errinjhi;	/* 0xE00 - Error injection mask high */
+	u32	errinjlo;	/* 0xE04 - Error injection mask low */
+	u32	errinjctl;	/* 0xE08 - Error injection tag/ecc control */
+	u8	res7[0x14];
+	u32	captdatahi;	/* 0xE20 - Error data high capture */
+	u32	captdatalo;	/* 0xE24 - Error data low capture */
+	u32	captecc;	/* 0xE28 - Error syndrome */
+	u8	res8[0x14];
+	u32	errdet;		/* 0xE40 - Error detect */
+	u32	errdis;		/* 0xE44 - Error disable */
+	u32	errinten;	/* 0xE48 - Error interrupt enable */
+	u32	errattr;	/* 0xE4c - Error attribute capture */
+	u32	erradrrl;	/* 0xE50 - Error address capture low */
+	u32	erradrrh;	/* 0xE54 - Error address capture high */
+	u32	errctl;		/* 0xE58 - Error control */
+	u8	res9[0x1A4];
+};
+
+struct sram_parameters {
+	unsigned int sram_size;
+	uint64_t sram_offset;
+};
+
+extern int instantiate_cache_sram(struct platform_device *dev,
+		struct sram_parameters sram_params);
+extern void remove_cache_sram(struct platform_device *dev);
+
+#endif /* __FSL_85XX_CACHE_CTLR_H__ */
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
new file mode 100644
index 0000000..54fb192
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * Simple memory allocator abstraction for QorIQ (P1/P2) based Cache-SRAM
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * This file is derived from the original work done
+ * by Sylvain Munaut for the Bestcomm SRAM allocator.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of_platform.h>
+#include <asm/pgtable.h>
+#include <asm/fsl_85xx_cache_sram.h>
+
+#include "fsl_85xx_cache_ctlr.h"
+
+struct mpc85xx_cache_sram *cache_sram;
+
+void *mpc85xx_cache_sram_alloc(unsigned int size,
+				phys_addr_t *phys, unsigned int align)
+{
+	unsigned long offset;
+	unsigned long flags;
+
+	if (unlikely(cache_sram == NULL))
+		return NULL;
+
+	if (!size || (size > cache_sram->size) || (align > cache_sram->size)) {
+		pr_err("%s(): size(=%x) or align(=%x) zero or too big\n",
+			__func__, size, align);
+		return NULL;
+	}
+
+	if ((align & (align - 1)) || align <= 1) {
+		pr_err("%s(): align(=%x) must be power of two and >1\n",
+			__func__, align);
+		return NULL;
+	}
+
+	spin_lock_irqsave(&cache_sram->lock, flags);
+	offset = rh_alloc_align(cache_sram->rh, size, align, NULL);
+	spin_unlock_irqrestore(&cache_sram->lock, flags);
+
+	if (IS_ERR_VALUE(offset))
+		return NULL;
+
+	*phys = cache_sram->base_phys + offset;
+
+	return (unsigned char *)cache_sram->base_virt + offset;
+}
+EXPORT_SYMBOL(mpc85xx_cache_sram_alloc);
+
+void mpc85xx_cache_sram_free(void *ptr)
+{
+	unsigned long flags;
+	BUG_ON(!ptr);
+
+	spin_lock_irqsave(&cache_sram->lock, flags);
+	rh_free(cache_sram->rh, ptr - cache_sram->base_virt);
+	spin_unlock_irqrestore(&cache_sram->lock, flags);
+}
+EXPORT_SYMBOL(mpc85xx_cache_sram_free);
+
+int __init instantiate_cache_sram(struct platform_device *dev,
+		struct sram_parameters sram_params)
+{
+	int ret = 0;
+
+	if (cache_sram) {
+		dev_err(&dev->dev, "Already initialized cache-sram\n");
+		return -EBUSY;
+	}
+
+	cache_sram = kzalloc(sizeof(struct mpc85xx_cache_sram), GFP_KERNEL);
+	if (!cache_sram) {
+		dev_err(&dev->dev, "Out of memory for cache_sram structure\n");
+		return -ENOMEM;
+	}
+
+	cache_sram->base_phys = sram_params.sram_offset;
+	cache_sram->size = sram_params.sram_size;
+
+	if (!request_mem_region(cache_sram->base_phys, cache_sram->size,
+						"fsl_85xx_cache_sram")) {
+		dev_err(&dev->dev, "%s: request memory failed\n",
+				dev->dev.of_node->full_name);
+		ret = -ENXIO;
+		goto out_free;
+	}
+
+	cache_sram->base_virt = ioremap_flags(cache_sram->base_phys,
+				cache_sram->size, _PAGE_COHERENT | PAGE_KERNEL);
+	if (!cache_sram->base_virt) {
+		dev_err(&dev->dev, "%s: ioremap_flags failed\n",
+				dev->dev.of_node->full_name);
+		ret = -ENOMEM;
+		goto out_release;
+	}
+
+	cache_sram->rh = rh_create(sizeof(unsigned int));
+	if (IS_ERR(cache_sram->rh)) {
+		dev_err(&dev->dev, "%s: Unable to create remote heap\n",
+				dev->dev.of_node->full_name);
+		ret = PTR_ERR(cache_sram->rh);
+		goto out_unmap;
+	}
+
+	rh_attach_region(cache_sram->rh, 0, cache_sram->size);
+	spin_lock_init(&cache_sram->lock);
+
+	dev_info(&dev->dev, "[base:0x%llx, size:0x%x] configured and loaded\n",
+		(unsigned long long)cache_sram->base_phys, cache_sram->size);
+
+	return 0;
+
+out_unmap:
+	iounmap(cache_sram->base_virt);
+
+out_release:
+	release_mem_region(cache_sram->base_phys, cache_sram->size);
+
+out_free:
+	kfree(cache_sram);
+	return ret;
+}
+
+void remove_cache_sram(struct platform_device *dev)
+{
+	BUG_ON(!cache_sram);
+
+	rh_detach_region(cache_sram->rh, 0, cache_sram->size);
+	rh_destroy(cache_sram->rh);
+
+	iounmap(cache_sram->base_virt);
+	release_mem_region(cache_sram->base_phys, cache_sram->size);
+
+	kfree(cache_sram);
+	cache_sram = NULL;
+
+	dev_info(&dev->dev, "MPC85xx Cache-SRAM driver unloaded\n");
+}
diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
new file mode 100644
index 0000000..cc8d655
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * QorIQ (P1/P2) L2 controller init for Cache-SRAM instantiation
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+
+#include "fsl_85xx_cache_ctlr.h"
+
+static char *sram_size;
+static char *sram_offset;
+struct mpc85xx_l2ctlr __iomem *l2ctlr;
+
+static long get_cache_sram_size(void)
+{
+	unsigned long val;
+
+	if (!sram_size || (strict_strtoul(sram_size, 0, &val) < 0))
+		return -EINVAL;
+
+	return val;
+}
+
+static long get_cache_sram_offset(void)
+{
+	unsigned long val;
+
+	if (!sram_offset || (strict_strtoul(sram_offset, 0, &val) < 0))
+		return -EINVAL;
+
+	return val;
+}
+
+static int __init get_size_from_cmdline(char *str)
+{
+	if (!str)
+		return 0;
+
+	sram_size = str;
+	return 1;
+}
+
+static int __init get_offset_from_cmdline(char *str)
+{
+	if (!str)
+		return 0;
+
+	sram_offset = str;
+	return 1;
+}
+
+__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)
+{
+	long rval;
+	unsigned int rem;
+	unsigned char ways;
+	const unsigned int *prop;
+	unsigned int l2cache_size;
+	struct sram_parameters sram_params;
+
+	if (!dev->dev.of_node) {
+		dev_err(&dev->dev, "Device's OF-node is NULL\n");
+		return -EINVAL;
+	}
+
+	prop = of_get_property(dev->dev.of_node, "cache-size", NULL);
+	if (!prop) {
+		dev_err(&dev->dev, "Missing L2 cache-size\n");
+		return -EINVAL;
+	}
+	l2cache_size = *prop;
+
+	sram_params.sram_size  = get_cache_sram_size();
+	if (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) {
+		dev_err(&dev->dev,
+			"Entire L2 as cache, provide a valid sram offset\n");
+		return -EINVAL;
+	}
+
+
+	rem = l2cache_size % sram_params.sram_size;
+	ways = LOCK_WAYS_FULL * sram_params.sram_size / l2cache_size;
+	if (rem || (ways & (ways - 1))) {
+		dev_err(&dev->dev, "Illegal cache-sram-size in command line\n");
+		return -EINVAL;
+	}
+
+	l2ctlr = of_iomap(dev->dev.of_node, 0);
+	if (!l2ctlr) {
+		dev_err(&dev->dev, "Can't map L2 controller\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Write bits[0-17] to srbar0
+	 */
+	out_be32(&l2ctlr->srbar0,
+		sram_params.sram_offset & L2SRAM_BAR_MSK_LO18);
+
+	/*
+	 * Write bits[18-21] to srbare0
+	 */
+#ifdef CONFIG_PHYS_64BIT
+	out_be32(&l2ctlr->srbarea0,
+		(sram_params.sram_offset >> 32) & L2SRAM_BARE_MSK_HI4);
+#endif
+
+	clrsetbits_be32(&l2ctlr->ctl, L2CR_L2E, L2CR_L2FI);
+
+	switch (ways) {
+	case LOCK_WAYS_EIGHTH:
+		setbits32(&l2ctlr->ctl,
+			L2CR_L2E | L2CR_L2FI | L2CR_SRAM_EIGHTH);
+		break;
+
+	case LOCK_WAYS_TWO_EIGHTH:
+		setbits32(&l2ctlr->ctl,
+			L2CR_L2E | L2CR_L2FI | L2CR_SRAM_QUART);
+		break;
+
+	case LOCK_WAYS_HALF:
+		setbits32(&l2ctlr->ctl,
+			L2CR_L2E | L2CR_L2FI | L2CR_SRAM_HALF);
+		break;
+
+	case LOCK_WAYS_FULL:
+	default:
+		setbits32(&l2ctlr->ctl,
+			L2CR_L2E | L2CR_L2FI | L2CR_SRAM_FULL);
+		break;
+	}
+	eieio();
+
+	rval = instantiate_cache_sram(dev, sram_params);
+	if (rval < 0) {
+		dev_err(&dev->dev, "Can't instantiate Cache-SRAM\n");
+		iounmap(l2ctlr);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int __devexit mpc85xx_l2ctlr_of_remove(struct platform_device *dev)
+{
+	BUG_ON(!l2ctlr);
+
+	iounmap(l2ctlr);
+	remove_cache_sram(dev);
+	dev_info(&dev->dev, "MPC85xx L2 controller unloaded\n");
+
+	return 0;
+}
+
+static struct of_device_id mpc85xx_l2ctlr_of_match[] = {
+	{
+		.compatible = "fsl,p2020-l2-cache-controller",
+	},
+	{
+		.compatible = "fsl,p2010-l2-cache-controller",
+	},
+	{
+		.compatible = "fsl,p1020-l2-cache-controller",
+	},
+	{
+		.compatible = "fsl,p1011-l2-cache-controller",
+	},
+	{
+		.compatible = "fsl,p1013-l2-cache-controller",
+	},
+	{
+		.compatible = "fsl,p1022-l2-cache-controller",
+	},
+	{},
+};
+
+static struct of_platform_driver mpc85xx_l2ctlr_of_platform_driver = {
+	.driver	= {
+		.name		= "fsl-l2ctlr",
+		.owner		= THIS_MODULE,
+		.of_match_table	= mpc85xx_l2ctlr_of_match,
+	},
+	.probe		= mpc85xx_l2ctlr_of_probe,
+	.remove		= __devexit_p(mpc85xx_l2ctlr_of_remove),
+};
+
+static __init int mpc85xx_l2ctlr_of_init(void)
+{
+	return of_register_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+}
+
+static void __exit mpc85xx_l2ctlr_of_exit(void)
+{
+	of_unregister_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+}
+
+subsys_initcall(mpc85xx_l2ctlr_of_init);
+module_exit(mpc85xx_l2ctlr_of_exit);
+
+MODULE_DESCRIPTION("Freescale MPC85xx L2 controller init");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 87991d3..108d76f 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -24,6 +24,7 @@
 #include <asm/ppc-pci.h>
 #include <asm/mpic.h>
 #include "fsl_msi.h"
+#include "fsl_pci.h"
 
 LIST_HEAD(msi_head);
 
@@ -51,8 +52,8 @@
 }
 
 static struct irq_chip fsl_msi_chip = {
-	.mask		= mask_msi_irq,
-	.unmask		= unmask_msi_irq,
+	.irq_mask	= mask_msi_irq,
+	.irq_unmask	= unmask_msi_irq,
 	.ack		= fsl_msi_end_irq,
 	.name		= "FSL-MSI",
 };
@@ -125,13 +126,11 @@
 {
 	struct fsl_msi *msi_data = fsl_msi_data;
 	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
-	u32 base = 0;
+	u64 base = fsl_pci_immrbar_base(hose);
 
-	pci_bus_read_config_dword(hose->bus,
-		PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base);
+	msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base);
+	msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base);
 
-	msg->address_lo = msi_data->msi_addr_lo + base;
-	msg->address_hi = msi_data->msi_addr_hi;
 	msg->data = hwirq;
 
 	pr_debug("%s: allocated srs: %d, ibs: %d\n",
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 4ae9332..818f7c6 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-2009 Freescale Semiconductor, Inc.
+ * Copyright 2007-2010 Freescale Semiconductor, Inc.
  * Copyright 2008-2009 MontaVista Software, Inc.
  *
  * Initial author: Xianghua Xiao <x.xiao@freescale.com>
@@ -34,7 +34,7 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 
-static int fsl_pcie_bus_fixup;
+static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
 
 static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
 {
@@ -407,10 +407,18 @@
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020, quirk_fsl_pcie_header);
 #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
 
 #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
@@ -430,6 +438,13 @@
 	u32 dev_base;
 };
 
+struct pex_inbound_window {
+	u32 ar;
+	u32 tar;
+	u32 barl;
+	u32 barh;
+};
+
 /*
  * With the convention of u-boot, the PCIE outbound window 0 serves
  * as configuration transactions outbound.
@@ -437,6 +452,8 @@
 #define PEX_OUTWIN0_BAR		0xCA4
 #define PEX_OUTWIN0_TAL		0xCA8
 #define PEX_OUTWIN0_TAH		0xCAC
+#define PEX_RC_INWIN_BASE	0xE60
+#define PEX_RCIWARn_EN		0x1
 
 static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn)
 {
@@ -604,6 +621,8 @@
 	const int *bus_range;
 	int primary;
 
+	is_mpc83xx_pci = 1;
+
 	if (!of_device_is_available(dev)) {
 		pr_warning("%s: disabled by the firmware.\n",
 			   dev->full_name);
@@ -683,3 +702,40 @@
 	return ret;
 }
 #endif /* CONFIG_PPC_83xx */
+
+u64 fsl_pci_immrbar_base(struct pci_controller *hose)
+{
+#ifdef CONFIG_PPC_83xx
+	if (is_mpc83xx_pci) {
+		struct mpc83xx_pcie_priv *pcie = hose->dn->data;
+		struct pex_inbound_window *in;
+		int i;
+
+		/* Walk the Root Complex Inbound windows to match IMMR base */
+		in = pcie->cfg_type0 + PEX_RC_INWIN_BASE;
+		for (i = 0; i < 4; i++) {
+			/* not enabled, skip */
+			if (!in_le32(&in[i].ar) & PEX_RCIWARn_EN)
+				 continue;
+
+			if (get_immrbase() == in_le32(&in[i].tar))
+				return (u64)in_le32(&in[i].barh) << 32 |
+					    in_le32(&in[i].barl);
+		}
+
+		printk(KERN_WARNING "could not find PCI BAR matching IMMR\n");
+	}
+#endif
+
+#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
+	if (!is_mpc83xx_pci) {
+		u32 base;
+
+		pci_bus_read_config_dword(hose->bus,
+			PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base);
+		return base;
+	}
+#endif
+
+	return 0;
+}
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index a9d8bbe..8ad72a1 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -88,6 +88,7 @@
 extern int fsl_add_bridge(struct device_node *dev, int is_primary);
 extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
 extern int mpc83xx_add_bridge(struct device_node *dev);
+u64 fsl_pci_immrbar_base(struct pci_controller *hose);
 
 #endif /* __POWERPC_FSL_PCI_H */
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 3017532..4127636 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -117,44 +117,59 @@
 };
 
 struct rio_msg_regs {
-	u32 omr;
-	u32 osr;
+	u32 omr;	/* 0xD_3000 - Outbound message 0 mode register */
+	u32 osr;	/* 0xD_3004 - Outbound message 0 status register */
 	u32 pad1;
-	u32 odqdpar;
+	u32 odqdpar;	/* 0xD_300C - Outbound message 0 descriptor queue
+			   dequeue pointer address register */
 	u32 pad2;
-	u32 osar;
-	u32 odpr;
-	u32 odatr;
-	u32 odcr;
+	u32 osar;	/* 0xD_3014 - Outbound message 0 source address
+			   register */
+	u32 odpr;	/* 0xD_3018 - Outbound message 0 destination port
+			   register */
+	u32 odatr;	/* 0xD_301C - Outbound message 0 destination attributes
+			   Register*/
+	u32 odcr;	/* 0xD_3020 - Outbound message 0 double-word count
+			   register */
 	u32 pad3;
-	u32 odqepar;
+	u32 odqepar;	/* 0xD_3028 - Outbound message 0 descriptor queue
+			   enqueue pointer address register */
 	u32 pad4[13];
-	u32 imr;
-	u32 isr;
+	u32 imr;	/* 0xD_3060 - Inbound message 0 mode register */
+	u32 isr;	/* 0xD_3064 - Inbound message 0 status register */
 	u32 pad5;
-	u32 ifqdpar;
+	u32 ifqdpar;	/* 0xD_306C - Inbound message 0 frame queue dequeue
+			   pointer address register*/
 	u32 pad6;
-	u32 ifqepar;
+	u32 ifqepar;	/* 0xD_3074 - Inbound message 0 frame queue enqueue
+			   pointer address register */
 	u32 pad7[226];
-	u32 odmr;
-	u32 odsr;
+	u32 odmr;	/* 0xD_3400 - Outbound doorbell mode register */
+	u32 odsr;	/* 0xD_3404 - Outbound doorbell status register */
 	u32 res0[4];
-	u32 oddpr;
-	u32 oddatr;
+	u32 oddpr;	/* 0xD_3418 - Outbound doorbell destination port
+			   register */
+	u32 oddatr;	/* 0xD_341c - Outbound doorbell destination attributes
+			   register */
 	u32 res1[3];
-	u32 odretcr;
+	u32 odretcr;	/* 0xD_342C - Outbound doorbell retry error threshold
+			   configuration register */
 	u32 res2[12];
-	u32 dmr;
-	u32 dsr;
+	u32 dmr;	/* 0xD_3460 - Inbound doorbell mode register */
+	u32 dsr;	/* 0xD_3464 - Inbound doorbell status register */
 	u32 pad8;
-	u32 dqdpar;
+	u32 dqdpar;	/* 0xD_346C - Inbound doorbell queue dequeue Pointer
+			   address register */
 	u32 pad9;
-	u32 dqepar;
+	u32 dqepar;	/* 0xD_3474 - Inbound doorbell Queue enqueue pointer
+			   address register */
 	u32 pad10[26];
-	u32 pwmr;
-	u32 pwsr;
-	u32 epwqbar;
-	u32 pwqbar;
+	u32 pwmr;	/* 0xD_34E0 - Inbound port-write mode register */
+	u32 pwsr;	/* 0xD_34E4 - Inbound port-write status register */
+	u32 epwqbar;	/* 0xD_34E8 - Extended Port-Write Queue Base Address
+			   register */
+	u32 pwqbar;	/* 0xD_34EC - Inbound port-write queue base address
+			   register */
 };
 
 struct rio_tx_desc {
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index b91f7ac..19e5015 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -209,186 +209,29 @@
 arch_initcall(of_add_fixed_phys);
 #endif /* CONFIG_FIXED_PHY */
 
-static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
-{
-	if (!phy_type)
-		return FSL_USB2_PHY_NONE;
-	if (!strcasecmp(phy_type, "ulpi"))
-		return FSL_USB2_PHY_ULPI;
-	if (!strcasecmp(phy_type, "utmi"))
-		return FSL_USB2_PHY_UTMI;
-	if (!strcasecmp(phy_type, "utmi_wide"))
-		return FSL_USB2_PHY_UTMI_WIDE;
-	if (!strcasecmp(phy_type, "serial"))
-		return FSL_USB2_PHY_SERIAL;
-
-	return FSL_USB2_PHY_NONE;
-}
-
-static int __init fsl_usb_of_init(void)
-{
-	struct device_node *np;
-	unsigned int i = 0;
-	struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
-		*usb_dev_dr_client = NULL;
-	int ret;
-
-	for_each_compatible_node(np, NULL, "fsl-usb2-mph") {
-		struct resource r[2];
-		struct fsl_usb2_platform_data usb_data;
-		const unsigned char *prop = NULL;
-
-		memset(&r, 0, sizeof(r));
-		memset(&usb_data, 0, sizeof(usb_data));
-
-		ret = of_address_to_resource(np, 0, &r[0]);
-		if (ret)
-			goto err;
-
-		of_irq_to_resource(np, 0, &r[1]);
-
-		usb_dev_mph =
-		    platform_device_register_simple("fsl-ehci", i, r, 2);
-		if (IS_ERR(usb_dev_mph)) {
-			ret = PTR_ERR(usb_dev_mph);
-			goto err;
-		}
-
-		usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
-		usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
-
-		usb_data.operating_mode = FSL_USB2_MPH_HOST;
-
-		prop = of_get_property(np, "port0", NULL);
-		if (prop)
-			usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
-
-		prop = of_get_property(np, "port1", NULL);
-		if (prop)
-			usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
-
-		prop = of_get_property(np, "phy_type", NULL);
-		usb_data.phy_mode = determine_usb_phy(prop);
-
-		ret =
-		    platform_device_add_data(usb_dev_mph, &usb_data,
-					     sizeof(struct
-						    fsl_usb2_platform_data));
-		if (ret)
-			goto unreg_mph;
-		i++;
-	}
-
-	for_each_compatible_node(np, NULL, "fsl-usb2-dr") {
-		struct resource r[2];
-		struct fsl_usb2_platform_data usb_data;
-		const unsigned char *prop = NULL;
-
-		if (!of_device_is_available(np))
-			continue;
-
-		memset(&r, 0, sizeof(r));
-		memset(&usb_data, 0, sizeof(usb_data));
-
-		ret = of_address_to_resource(np, 0, &r[0]);
-		if (ret)
-			goto unreg_mph;
-
-		of_irq_to_resource(np, 0, &r[1]);
-
-		prop = of_get_property(np, "dr_mode", NULL);
-
-		if (!prop || !strcmp(prop, "host")) {
-			usb_data.operating_mode = FSL_USB2_DR_HOST;
-			usb_dev_dr_host = platform_device_register_simple(
-					"fsl-ehci", i, r, 2);
-			if (IS_ERR(usb_dev_dr_host)) {
-				ret = PTR_ERR(usb_dev_dr_host);
-				goto err;
-			}
-		} else if (prop && !strcmp(prop, "peripheral")) {
-			usb_data.operating_mode = FSL_USB2_DR_DEVICE;
-			usb_dev_dr_client = platform_device_register_simple(
-					"fsl-usb2-udc", i, r, 2);
-			if (IS_ERR(usb_dev_dr_client)) {
-				ret = PTR_ERR(usb_dev_dr_client);
-				goto err;
-			}
-		} else if (prop && !strcmp(prop, "otg")) {
-			usb_data.operating_mode = FSL_USB2_DR_OTG;
-			usb_dev_dr_host = platform_device_register_simple(
-					"fsl-ehci", i, r, 2);
-			if (IS_ERR(usb_dev_dr_host)) {
-				ret = PTR_ERR(usb_dev_dr_host);
-				goto err;
-			}
-			usb_dev_dr_client = platform_device_register_simple(
-					"fsl-usb2-udc", i, r, 2);
-			if (IS_ERR(usb_dev_dr_client)) {
-				ret = PTR_ERR(usb_dev_dr_client);
-				goto err;
-			}
-		} else {
-			ret = -EINVAL;
-			goto err;
-		}
-
-		prop = of_get_property(np, "phy_type", NULL);
-		usb_data.phy_mode = determine_usb_phy(prop);
-
-		if (usb_dev_dr_host) {
-			usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
-			usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
-				dev.coherent_dma_mask;
-			if ((ret = platform_device_add_data(usb_dev_dr_host,
-						&usb_data, sizeof(struct
-						fsl_usb2_platform_data))))
-				goto unreg_dr;
-		}
-		if (usb_dev_dr_client) {
-			usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL;
-			usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client->
-				dev.coherent_dma_mask;
-			if ((ret = platform_device_add_data(usb_dev_dr_client,
-						&usb_data, sizeof(struct
-						fsl_usb2_platform_data))))
-				goto unreg_dr;
-		}
-		i++;
-	}
-	return 0;
-
-unreg_dr:
-	if (usb_dev_dr_host)
-		platform_device_unregister(usb_dev_dr_host);
-	if (usb_dev_dr_client)
-		platform_device_unregister(usb_dev_dr_client);
-unreg_mph:
-	if (usb_dev_mph)
-		platform_device_unregister(usb_dev_mph);
-err:
-	return ret;
-}
-
-arch_initcall(fsl_usb_of_init);
-
 #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
 static __be32 __iomem *rstcr;
 
 static int __init setup_rstcr(void)
 {
 	struct device_node *np;
-	np = of_find_node_by_name(NULL, "global-utilities");
-	if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
-		rstcr = of_iomap(np, 0) + 0xb0;
-		if (!rstcr)
-			printk (KERN_EMERG "Error: reset control register "
-					"not mapped!\n");
-	} else if (ppc_md.restart == fsl_rstcr_restart)
+
+	for_each_node_by_name(np, "global-utilities") {
+		if ((of_get_property(np, "fsl,has-rstcr", NULL))) {
+			rstcr = of_iomap(np, 0) + 0xb0;
+			if (!rstcr)
+				printk (KERN_ERR "Error: reset control "
+						"register not mapped!\n");
+			break;
+		}
+	}
+
+	if (!rstcr && ppc_md.restart == fsl_rstcr_restart)
 		printk(KERN_ERR "No RSTCR register, warm reboot won't work\n");
 
 	if (np)
 		of_node_put(np);
+
 	return 0;
 }
 
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c
index 2b69084..c0ea05e 100644
--- a/arch/powerpc/sysdev/mpc8xxx_gpio.c
+++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c
@@ -330,6 +330,9 @@
 	for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio")
 		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_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
index 3b6a9a4..320ad5a 100644
--- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
+++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
@@ -39,24 +39,24 @@
 static struct mpic *msi_mpic;
 
 
-static void mpic_pasemi_msi_mask_irq(unsigned int irq)
+static void mpic_pasemi_msi_mask_irq(struct irq_data *data)
 {
-	pr_debug("mpic_pasemi_msi_mask_irq %d\n", irq);
-	mask_msi_irq(irq);
-	mpic_mask_irq(irq);
+	pr_debug("mpic_pasemi_msi_mask_irq %d\n", data->irq);
+	mask_msi_irq(data);
+	mpic_mask_irq(data->irq);
 }
 
-static void mpic_pasemi_msi_unmask_irq(unsigned int irq)
+static void mpic_pasemi_msi_unmask_irq(struct irq_data *data)
 {
-	pr_debug("mpic_pasemi_msi_unmask_irq %d\n", irq);
-	mpic_unmask_irq(irq);
-	unmask_msi_irq(irq);
+	pr_debug("mpic_pasemi_msi_unmask_irq %d\n", data->irq);
+	mpic_unmask_irq(data->irq);
+	unmask_msi_irq(data);
 }
 
 static struct irq_chip mpic_pasemi_msi_chip = {
-	.shutdown	= mpic_pasemi_msi_mask_irq,
-	.mask		= mpic_pasemi_msi_mask_irq,
-	.unmask		= mpic_pasemi_msi_unmask_irq,
+	.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,
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c
index bcbfe79..a2b028b 100644
--- a/arch/powerpc/sysdev/mpic_u3msi.c
+++ b/arch/powerpc/sysdev/mpic_u3msi.c
@@ -23,22 +23,22 @@
 /* A bit ugly, can we get this from the pci_dev somehow? */
 static struct mpic *msi_mpic;
 
-static void mpic_u3msi_mask_irq(unsigned int irq)
+static void mpic_u3msi_mask_irq(struct irq_data *data)
 {
-	mask_msi_irq(irq);
-	mpic_mask_irq(irq);
+	mask_msi_irq(data);
+	mpic_mask_irq(data->irq);
 }
 
-static void mpic_u3msi_unmask_irq(unsigned int irq)
+static void mpic_u3msi_unmask_irq(struct irq_data *data)
 {
-	mpic_unmask_irq(irq);
-	unmask_msi_irq(irq);
+	mpic_unmask_irq(data->irq);
+	unmask_msi_irq(data);
 }
 
 static struct irq_chip mpic_u3msi_chip = {
-	.shutdown	= mpic_u3msi_mask_irq,
-	.mask		= mpic_u3msi_mask_irq,
-	.unmask		= mpic_u3msi_unmask_irq,
+	.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,
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
index 24a0bb9..4260f36 100644
--- a/arch/powerpc/sysdev/pmi.c
+++ b/arch/powerpc/sysdev/pmi.c
@@ -114,7 +114,7 @@
 
 	spin_lock(&data->handler_spinlock);
 	list_for_each_entry(handler, &data->handler, node) {
-		pr_debug(KERN_INFO "pmi: notifying handler %p\n", handler);
+		pr_debug("pmi: notifying handler %p\n", handler);
 		if (handler->type == data->msg.type)
 			handler->handle_pmi_message(data->msg);
 	}
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
index faa81b6..c168c54e 100644
--- a/arch/powerpc/xmon/Makefile
+++ b/arch/powerpc/xmon/Makefile
@@ -4,9 +4,7 @@
 
 GCOV_PROFILE := n
 
-ifdef CONFIG_PPC64
-EXTRA_CFLAGS += -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
 
 obj-y			+= xmon.o start.o nonstdio.o
 
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index f0777a4..75976a1 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -95,6 +95,7 @@
 	select HAVE_KVM if 64BIT
 	select HAVE_ARCH_TRACEHOOK
 	select INIT_ALL_POSSIBLE
+	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_BZIP2
@@ -198,6 +199,13 @@
 	  can be controlled through /sys/devices/system/cpu/cpu#.
 	  Say N if you want to disable CPU hotplug.
 
+config SCHED_BOOK
+	bool "Book scheduler support"
+	depends on SMP
+	help
+	  Book scheduler support improves the CPU scheduler's decision making
+	  when dealing with machines that have several books.
+
 config MATHEMU
 	bool "IEEE FPU emulation"
 	depends on MARCH_G5
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c
index aa819da..975e3ab 100644
--- a/arch/s390/crypto/prng.c
+++ b/arch/s390/crypto/prng.c
@@ -152,6 +152,7 @@
 	.open		= &prng_open,
 	.release	= NULL,
 	.read		= &prng_read,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice prng_dev = {
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 1211bb1..020e51c 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -618,6 +618,7 @@
 	.open		= dbfs_d204_open,
 	.read		= dbfs_d204_read,
 	.release	= dbfs_d204_release,
+	.llseek		= no_llseek,
 };
 
 static int hypfs_dbfs_init(void)
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c
index ee5ab1a..26cf177 100644
--- a/arch/s390/hypfs/hypfs_vm.c
+++ b/arch/s390/hypfs/hypfs_vm.c
@@ -275,6 +275,7 @@
 	.open		= dbfs_d2fc_open,
 	.read		= dbfs_d2fc_read,
 	.release	= dbfs_d2fc_release,
+	.llseek		= no_llseek,
 };
 
 int hypfs_vm_init(void)
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 98a4a4c..74d9867 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -449,6 +449,7 @@
 	.write		= do_sync_write,
 	.aio_read	= hypfs_aio_read,
 	.aio_write	= hypfs_aio_write,
+	.llseek		= no_llseek,
 };
 
 static struct file_system_type hypfs_type = {
diff --git a/arch/s390/include/asm/hardirq.h b/arch/s390/include/asm/hardirq.h
index 498bc38..881d945 100644
--- a/arch/s390/include/asm/hardirq.h
+++ b/arch/s390/include/asm/hardirq.h
@@ -12,10 +12,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/threads.h>
-#include <linux/sched.h>
-#include <linux/cache.h>
-#include <linux/interrupt.h>
 #include <asm/lowcore.h>
 
 #define local_softirq_pending() (S390_lowcore.softirq_pending)
diff --git a/arch/s390/include/asm/ioctls.h b/arch/s390/include/asm/ioctls.h
index 2f3d873..960a4c1 100644
--- a/arch/s390/include/asm/ioctls.h
+++ b/arch/s390/include/asm/ioctls.h
@@ -1,94 +1,8 @@
-/*
- *  include/asm-s390/ioctls.h
- *
- *  S390 version
- *
- *  Derived from "include/asm-i386/ioctls.h"
- */
-
 #ifndef __ARCH_S390_IOCTLS_H__
 #define __ARCH_S390_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define FIOQSIZE	0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif
diff --git a/arch/s390/include/asm/irqflags.h b/arch/s390/include/asm/irqflags.h
index 15b3ac2..865d6d8 100644
--- a/arch/s390/include/asm/irqflags.h
+++ b/arch/s390/include/asm/irqflags.h
@@ -8,8 +8,8 @@
 
 #include <linux/types.h>
 
-/* store then or system mask. */
-#define __raw_local_irq_stosm(__or)					\
+/* store then OR system mask. */
+#define __arch_local_irq_stosm(__or)					\
 ({									\
 	unsigned long __mask;						\
 	asm volatile(							\
@@ -18,8 +18,8 @@
 	__mask;								\
 })
 
-/* store then and system mask. */
-#define __raw_local_irq_stnsm(__and)					\
+/* store then AND system mask. */
+#define __arch_local_irq_stnsm(__and)					\
 ({									\
 	unsigned long __mask;						\
 	asm volatile(							\
@@ -29,39 +29,44 @@
 })
 
 /* set system mask. */
-#define __raw_local_irq_ssm(__mask)					\
-({									\
-	asm volatile("ssm   %0" : : "Q" (__mask) : "memory");		\
-})
-
-/* interrupt control.. */
-static inline unsigned long raw_local_irq_enable(void)
+static inline void __arch_local_irq_ssm(unsigned long flags)
 {
-	return __raw_local_irq_stosm(0x03);
+	asm volatile("ssm   %0" : : "Q" (flags) : "memory");
 }
 
-static inline unsigned long raw_local_irq_disable(void)
+static inline unsigned long arch_local_save_flags(void)
 {
-	return __raw_local_irq_stnsm(0xfc);
+	return __arch_local_irq_stosm(0x00);
 }
 
-#define raw_local_save_flags(x)						\
-do {									\
-	typecheck(unsigned long, x);					\
-	(x) = __raw_local_irq_stosm(0x00);				\
-} while (0)
-
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline unsigned long arch_local_irq_save(void)
 {
-	__raw_local_irq_ssm(flags);
+	return __arch_local_irq_stnsm(0xfc);
 }
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline void arch_local_irq_disable(void)
+{
+	arch_local_irq_save();
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	__arch_local_irq_stosm(0x03);
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	__arch_local_irq_ssm(flags);
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
 {
 	return !(flags & (3UL << (BITS_PER_LONG - 8)));
 }
 
-/* For spinlocks etc */
-#define raw_local_irq_save(x)	((x) = raw_local_irq_disable())
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
 
 #endif /* __ASM_IRQFLAGS_H */
diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h
index 3840cbe..a75f168 100644
--- a/arch/s390/include/asm/perf_event.h
+++ b/arch/s390/include/asm/perf_event.h
@@ -4,7 +4,6 @@
  * Copyright 2009 Martin Schwidefsky, IBM Corporation.
  */
 
-static inline void set_perf_event_pending(void) {}
-static inline void clear_perf_event_pending(void) {}
+/* Empty, just to avoid compiling error */
 
 #define PERF_EVENT_INDEX_OFFSET 0
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index 2ba6302..46e96bc 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -360,6 +360,7 @@
 	unsigned int no_output_qs;
 	qdio_handler_t *input_handler;
 	qdio_handler_t *output_handler;
+	void (*queue_start_poll) (struct ccw_device *, int, unsigned long);
 	unsigned long int_parm;
 	void **input_sbal_addr_array;
 	void **output_sbal_addr_array;
@@ -377,11 +378,13 @@
 extern int qdio_allocate(struct qdio_initialize *);
 extern int qdio_establish(struct qdio_initialize *);
 extern int qdio_activate(struct ccw_device *);
-
-extern int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
-		   int q_nr, unsigned int bufnr, unsigned int count);
-extern int qdio_shutdown(struct ccw_device*, int);
+extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int,
+		   unsigned int);
+extern int qdio_start_irq(struct ccw_device *, int);
+extern int qdio_stop_irq(struct ccw_device *, int);
+extern int qdio_get_next_buffers(struct ccw_device *, int, int *, int *);
+extern int qdio_shutdown(struct ccw_device *, int);
 extern int qdio_free(struct ccw_device *);
-extern int qdio_get_ssqd_desc(struct ccw_device *dev, struct qdio_ssqd_desc*);
+extern int qdio_get_ssqd_desc(struct ccw_device *, struct qdio_ssqd_desc *);
 
 #endif /* __QDIO_H__ */
diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h
index cef6621..1f2ebc4 100644
--- a/arch/s390/include/asm/system.h
+++ b/arch/s390/include/asm/system.h
@@ -97,7 +97,6 @@
 
 extern void account_vtime(struct task_struct *, struct task_struct *);
 extern void account_tick_vtime(struct task_struct *);
-extern void account_system_vtime(struct task_struct *);
 
 #ifdef CONFIG_PFAULT
 extern void pfault_irq_init(void);
@@ -399,7 +398,7 @@
 static inline void
 __set_psw_mask(unsigned long mask)
 {
-	__load_psw_mask(mask | (__raw_local_irq_stosm(0x00) & ~(-1UL >> 8)));
+	__load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
 }
 
 #define local_mcck_enable()  __set_psw_mask(psw_kernel_bits)
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h
index 831bd03..051107a 100644
--- a/arch/s390/include/asm/topology.h
+++ b/arch/s390/include/asm/topology.h
@@ -3,15 +3,32 @@
 
 #include <linux/cpumask.h>
 
-#define mc_capable()	(1)
-
-const struct cpumask *cpu_coregroup_mask(unsigned int cpu);
-
 extern unsigned char cpu_core_id[NR_CPUS];
 extern cpumask_t cpu_core_map[NR_CPUS];
 
+static inline const struct cpumask *cpu_coregroup_mask(unsigned int cpu)
+{
+	return &cpu_core_map[cpu];
+}
+
 #define topology_core_id(cpu)		(cpu_core_id[cpu])
 #define topology_core_cpumask(cpu)	(&cpu_core_map[cpu])
+#define mc_capable()			(1)
+
+#ifdef CONFIG_SCHED_BOOK
+
+extern unsigned char cpu_book_id[NR_CPUS];
+extern cpumask_t cpu_book_map[NR_CPUS];
+
+static inline const struct cpumask *cpu_book_mask(unsigned int cpu)
+{
+	return &cpu_book_map[cpu];
+}
+
+#define topology_book_id(cpu)		(cpu_book_id[cpu])
+#define topology_book_cpumask(cpu)	(&cpu_book_map[cpu])
+
+#endif /* CONFIG_SCHED_BOOK */
 
 int topology_set_cpu_management(int fc);
 void topology_schedule_update(void);
@@ -30,6 +47,8 @@
 };
 #endif
 
+#define SD_BOOK_INIT	SD_CPU_INIT
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_S390_TOPOLOGY_H */
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 9819226..5ad6bc0 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -174,6 +174,7 @@
 	.write   = debug_input,
 	.open    = debug_open,
 	.release = debug_close,
+	.llseek  = no_llseek,
 };
 
 static struct dentry *debug_debugfs_root_entry;
diff --git a/arch/s390/kernel/mem_detect.c b/arch/s390/kernel/mem_detect.c
index 559af0d..0fbe4e3 100644
--- a/arch/s390/kernel/mem_detect.c
+++ b/arch/s390/kernel/mem_detect.c
@@ -54,11 +54,11 @@
 	 * right thing and we don't get scheduled away with low address
 	 * protection disabled.
 	 */
-	flags = __raw_local_irq_stnsm(0xf8);
+	flags = __arch_local_irq_stnsm(0xf8);
 	__ctl_store(cr0, 0, 0);
 	__ctl_clear_bit(0, 28);
 	find_memory_chunks(chunk);
 	__ctl_load(cr0, 0, 0);
-	__raw_local_irq_ssm(flags);
+	arch_local_irq_restore(flags);
 }
 EXPORT_SYMBOL(detect_memory_layout);
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index 22cfd63..f7167ee 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -407,10 +407,9 @@
 {
 	vfree(me->arch.syminfo);
 	me->arch.syminfo = NULL;
-	return module_bug_finalize(hdr, sechdrs, me);
+	return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
-	module_bug_cleanup(mod);
 }
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index bcef007..13559c9 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -57,8 +57,8 @@
 	union tl_entry tle[0];
 };
 
-struct core_info {
-	struct core_info *next;
+struct mask_info {
+	struct mask_info *next;
 	unsigned char id;
 	cpumask_t mask;
 };
@@ -66,7 +66,6 @@
 static int topology_enabled;
 static void topology_work_fn(struct work_struct *work);
 static struct tl_info *tl_info;
-static struct core_info core_info;
 static int machine_has_topology;
 static struct timer_list topology_timer;
 static void set_topology_timer(void);
@@ -74,38 +73,37 @@
 /* topology_lock protects the core linked list */
 static DEFINE_SPINLOCK(topology_lock);
 
+static struct mask_info core_info;
 cpumask_t cpu_core_map[NR_CPUS];
 unsigned char cpu_core_id[NR_CPUS];
 
-static cpumask_t cpu_coregroup_map(unsigned int cpu)
+#ifdef CONFIG_SCHED_BOOK
+static struct mask_info book_info;
+cpumask_t cpu_book_map[NR_CPUS];
+unsigned char cpu_book_id[NR_CPUS];
+#endif
+
+static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
 {
-	struct core_info *core = &core_info;
-	unsigned long flags;
 	cpumask_t mask;
 
 	cpus_clear(mask);
 	if (!topology_enabled || !machine_has_topology)
 		return cpu_possible_map;
-	spin_lock_irqsave(&topology_lock, flags);
-	while (core) {
-		if (cpu_isset(cpu, core->mask)) {
-			mask = core->mask;
+	while (info) {
+		if (cpu_isset(cpu, info->mask)) {
+			mask = info->mask;
 			break;
 		}
-		core = core->next;
+		info = info->next;
 	}
-	spin_unlock_irqrestore(&topology_lock, flags);
 	if (cpus_empty(mask))
 		mask = cpumask_of_cpu(cpu);
 	return mask;
 }
 
-const struct cpumask *cpu_coregroup_mask(unsigned int cpu)
-{
-	return &cpu_core_map[cpu];
-}
-
-static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core)
+static void add_cpus_to_mask(struct tl_cpu *tl_cpu, struct mask_info *book,
+			     struct mask_info *core)
 {
 	unsigned int cpu;
 
@@ -117,23 +115,35 @@
 
 		rcpu = CPU_BITS - 1 - cpu + tl_cpu->origin;
 		for_each_present_cpu(lcpu) {
-			if (cpu_logical_map(lcpu) == rcpu) {
-				cpu_set(lcpu, core->mask);
-				cpu_core_id[lcpu] = core->id;
-				smp_cpu_polarization[lcpu] = tl_cpu->pp;
-			}
+			if (cpu_logical_map(lcpu) != rcpu)
+				continue;
+#ifdef CONFIG_SCHED_BOOK
+			cpu_set(lcpu, book->mask);
+			cpu_book_id[lcpu] = book->id;
+#endif
+			cpu_set(lcpu, core->mask);
+			cpu_core_id[lcpu] = core->id;
+			smp_cpu_polarization[lcpu] = tl_cpu->pp;
 		}
 	}
 }
 
-static void clear_cores(void)
+static void clear_masks(void)
 {
-	struct core_info *core = &core_info;
+	struct mask_info *info;
 
-	while (core) {
-		cpus_clear(core->mask);
-		core = core->next;
+	info = &core_info;
+	while (info) {
+		cpus_clear(info->mask);
+		info = info->next;
 	}
+#ifdef CONFIG_SCHED_BOOK
+	info = &book_info;
+	while (info) {
+		cpus_clear(info->mask);
+		info = info->next;
+	}
+#endif
 }
 
 static union tl_entry *next_tle(union tl_entry *tle)
@@ -146,29 +156,36 @@
 
 static void tl_to_cores(struct tl_info *info)
 {
+#ifdef CONFIG_SCHED_BOOK
+	struct mask_info *book = &book_info;
+#else
+	struct mask_info *book = NULL;
+#endif
+	struct mask_info *core = &core_info;
 	union tl_entry *tle, *end;
-	struct core_info *core = &core_info;
+
 
 	spin_lock_irq(&topology_lock);
-	clear_cores();
+	clear_masks();
 	tle = info->tle;
 	end = (union tl_entry *)((unsigned long)info + info->length);
 	while (tle < end) {
 		switch (tle->nl) {
-		case 5:
-		case 4:
-		case 3:
+#ifdef CONFIG_SCHED_BOOK
 		case 2:
+			book = book->next;
+			book->id = tle->container.id;
 			break;
+#endif
 		case 1:
 			core = core->next;
 			core->id = tle->container.id;
 			break;
 		case 0:
-			add_cpus_to_core(&tle->cpu, core);
+			add_cpus_to_mask(&tle->cpu, book, core);
 			break;
 		default:
-			clear_cores();
+			clear_masks();
 			machine_has_topology = 0;
 			goto out;
 		}
@@ -221,10 +238,29 @@
 
 static void update_cpu_core_map(void)
 {
+	unsigned long flags;
 	int cpu;
 
-	for_each_possible_cpu(cpu)
-		cpu_core_map[cpu] = cpu_coregroup_map(cpu);
+	spin_lock_irqsave(&topology_lock, flags);
+	for_each_possible_cpu(cpu) {
+		cpu_core_map[cpu] = cpu_group_map(&core_info, cpu);
+#ifdef CONFIG_SCHED_BOOK
+		cpu_book_map[cpu] = cpu_group_map(&book_info, cpu);
+#endif
+	}
+	spin_unlock_irqrestore(&topology_lock, flags);
+}
+
+static void store_topology(struct tl_info *info)
+{
+#ifdef CONFIG_SCHED_BOOK
+	int rc;
+
+	rc = stsi(info, 15, 1, 3);
+	if (rc != -ENOSYS)
+		return;
+#endif
+	stsi(info, 15, 1, 2);
 }
 
 int arch_update_cpu_topology(void)
@@ -238,7 +274,7 @@
 		topology_update_polarization_simple();
 		return 0;
 	}
-	stsi(info, 15, 1, 2);
+	store_topology(info);
 	tl_to_cores(info);
 	update_cpu_core_map();
 	for_each_online_cpu(cpu) {
@@ -299,12 +335,24 @@
 }
 __initcall(init_topology_update);
 
+static void alloc_masks(struct tl_info *info, struct mask_info *mask, int offset)
+{
+	int i, nr_masks;
+
+	nr_masks = info->mag[NR_MAG - offset];
+	for (i = 0; i < info->mnest - offset; i++)
+		nr_masks *= info->mag[NR_MAG - offset - 1 - i];
+	nr_masks = max(nr_masks, 1);
+	for (i = 0; i < nr_masks; i++) {
+		mask->next = alloc_bootmem(sizeof(struct mask_info));
+		mask = mask->next;
+	}
+}
+
 void __init s390_init_cpu_topology(void)
 {
 	unsigned long long facility_bits;
 	struct tl_info *info;
-	struct core_info *core;
-	int nr_cores;
 	int i;
 
 	if (stfle(&facility_bits, 1) <= 0)
@@ -315,25 +363,13 @@
 
 	tl_info = alloc_bootmem_pages(PAGE_SIZE);
 	info = tl_info;
-	stsi(info, 15, 1, 2);
-
-	nr_cores = info->mag[NR_MAG - 2];
-	for (i = 0; i < info->mnest - 2; i++)
-		nr_cores *= info->mag[NR_MAG - 3 - i];
-
+	store_topology(info);
 	pr_info("The CPU configuration topology of the machine is:");
 	for (i = 0; i < NR_MAG; i++)
 		printk(" %d", info->mag[i]);
 	printk(" / %d\n", info->mnest);
-
-	core = &core_info;
-	for (i = 0; i < nr_cores; i++) {
-		core->next = alloc_bootmem(sizeof(struct core_info));
-		core = core->next;
-		if (!core)
-			goto error;
-	}
-	return;
-error:
-	machine_has_topology = 0;
+	alloc_masks(info, &core_info, 2);
+#ifdef CONFIG_SCHED_BOOK
+	alloc_masks(info, &book_info, 3);
+#endif
 }
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 30eb6d02..94b8ba2 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -50,7 +50,6 @@
  */
 void __init paging_init(void)
 {
-	static const int ssm_mask = 0x04000000L;
 	unsigned long max_zone_pfns[MAX_NR_ZONES];
 	unsigned long pgd_type;
 
@@ -72,7 +71,7 @@
 	__ctl_load(S390_lowcore.kernel_asce, 1, 1);
 	__ctl_load(S390_lowcore.kernel_asce, 7, 7);
 	__ctl_load(S390_lowcore.kernel_asce, 13, 13);
-	__raw_local_irq_ssm(ssm_mask);
+	arch_local_irq_restore(4UL << (BITS_PER_LONG - 8));
 
 	atomic_set(&init_mm.context.attach_count, 1);
 
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index a8c2af8..71a4b0d 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -71,7 +71,7 @@
 
 	if (!count)
 		return 0;
-	flags = __raw_local_irq_stnsm(0xf8UL);
+	flags = __arch_local_irq_stnsm(0xf8UL);
 	asm volatile (
 		"0:	mvcle	%1,%2,0x0\n"
 		"1:	jo	0b\n"
@@ -82,6 +82,6 @@
 		  "+d" (_len2), "=m" (*((long *) dest))
 		: "m" (*((long *) src))
 		: "cc", "memory");
-	__raw_local_irq_ssm(flags);
+	arch_local_irq_restore(flags);
 	return rc;
 }
diff --git a/arch/score/include/asm/irqflags.h b/arch/score/include/asm/irqflags.h
index 690a6ca..5c75638 100644
--- a/arch/score/include/asm/irqflags.h
+++ b/arch/score/include/asm/irqflags.h
@@ -3,107 +3,118 @@
 
 #ifndef __ASSEMBLY__
 
-#define raw_local_irq_save(x)			\
-{						\
-	__asm__ __volatile__(			\
-		"mfcr	r8, cr0;"		\
-		"li	r9, 0xfffffffe;"	\
-		"nop;"				\
-		"mv	%0, r8;"		\
-		"and	r8, r8, r9;"		\
-		"mtcr	r8, cr0;"		\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		: "=r" (x)			\
-		:				\
-		: "r8", "r9"			\
-		);				\
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+
+	asm volatile(
+		"	mfcr	r8, cr0		\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	mv	%0, r8		\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	ldi	r9, 0x1		\n"
+		"	and	%0, %0, r9	\n"
+		: "=r" (flags)
+		:
+		: "r8", "r9");
+	return flags;
 }
 
-#define raw_local_irq_restore(x)		\
-{						\
-	__asm__ __volatile__(			\
-		"mfcr	r8, cr0;"		\
-		"ldi	r9, 0x1;"		\
-		"and	%0, %0, r9;"		\
-		"or	r8, r8, %0;"		\
-		"mtcr	r8, cr0;"		\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		:				\
-		: "r"(x)			\
-		: "r8", "r9"			\
-		);				\
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags
+
+	asm volatile(
+		"	mfcr	r8, cr0		\n"
+		"	li	r9, 0xfffffffe	\n"
+		"	nop			\n"
+		"	mv	%0, r8		\n"
+		"	and	r8, r8, r9	\n"
+		"	mtcr	r8, cr0		\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		: "=r" (flags)
+		:
+		: "r8", "r9", "memory");
+
+	return flags;
 }
 
-#define raw_local_irq_enable(void)		\
-{						\
-	__asm__ __volatile__(			\
-		"mfcr\tr8,cr0;"			\
-		"nop;"				\
-		"nop;"				\
-		"ori\tr8,0x1;"			\
-		"mtcr\tr8,cr0;"			\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		:				\
-		:				\
-		: "r8");			\
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile(
+		"	mfcr	r8, cr0		\n"
+		"	ldi	r9, 0x1		\n"
+		"	and	%0, %0, r9	\n"
+		"	or	r8, r8, %0	\n"
+		"	mtcr	r8, cr0		\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		:
+		: "r"(flags)
+		: "r8", "r9", "memory");
 }
 
-#define raw_local_irq_disable(void)		\
-{						\
-	__asm__ __volatile__(			\
-		"mfcr\tr8,cr0;"			\
-		"nop;"				\
-		"nop;"				\
-		"srli\tr8,r8,1;"		\
-		"slli\tr8,r8,1;"		\
-		"mtcr\tr8,cr0;"			\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		:				\
-		:				\
-		: "r8");			\
+static inline void arch_local_irq_enable(void)
+{
+	asm volatile(
+		"	mfcr	r8,cr0		\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	ori	r8,0x1		\n"
+		"	mtcr	r8,cr0		\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		:
+		:
+		: "r8", "memory");
 }
 
-#define raw_local_save_flags(x)			\
-{						\
-	__asm__ __volatile__(			\
-		"mfcr	r8, cr0;"		\
-		"nop;"				\
-		"nop;"				\
-		"mv	%0, r8;"		\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		"nop;"				\
-		"ldi	r9, 0x1;"		\
-		"and	%0, %0, r9;"		\
-		: "=r" (x)			\
-		:				\
-		: "r8", "r9"			\
-		);				\
+static inline void arch_local_irq_disable(void)
+{
+	asm volatile(
+		"	mfcr	r8,cr0		\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	srli	r8,r8,1		\n"
+		"	slli	r8,r8,1		\n"
+		"	mtcr	r8,cr0		\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		"	nop			\n"
+		:
+		:
+		: "r8", "memory");
 }
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
 {
 	return !(flags & 1);
 }
 
-#endif
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_SCORE_IRQFLAGS_H */
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 33990fa..35b6879 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -16,6 +16,7 @@
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
+	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
 	select HAVE_KERNEL_GZIP
@@ -249,6 +250,11 @@
 	select PM
 	select PM_RUNTIME
 
+config CPU_HAS_PMU
+       depends on CPU_SH4 || CPU_SH4A
+       default y
+       bool
+
 if SUPERH32
 
 choice
@@ -738,6 +744,14 @@
 	  LLSC, this should be more efficient than the other alternative of
 	  disabling interrupts around the atomic sequence.
 
+config HW_PERF_EVENTS
+	bool "Enable hardware performance counter support for perf events"
+	depends on PERF_EVENTS && CPU_HAS_PMU
+	default y
+	help
+	  Enable hardware performance counter support for perf events. If
+	  disabled, perf events will use software events only.
+
 source "drivers/sh/Kconfig"
 
 endmenu
diff --git a/arch/sh/boards/mach-landisk/gio.c b/arch/sh/boards/mach-landisk/gio.c
index 01e6abb..8132dff 100644
--- a/arch/sh/boards/mach-landisk/gio.c
+++ b/arch/sh/boards/mach-landisk/gio.c
@@ -128,6 +128,7 @@
 	.open = gio_open,	/* open */
 	.release = gio_close,	/* release */
 	.unlocked_ioctl = gio_ioctl,
+	.llseek = noop_llseek,
 };
 
 static int __init gio_init(void)
diff --git a/arch/sh/include/asm/irqflags.h b/arch/sh/include/asm/irqflags.h
index a741153..43b7608 100644
--- a/arch/sh/include/asm/irqflags.h
+++ b/arch/sh/include/asm/irqflags.h
@@ -1,8 +1,8 @@
 #ifndef __ASM_SH_IRQFLAGS_H
 #define __ASM_SH_IRQFLAGS_H
 
-#define RAW_IRQ_DISABLED	0xf0
-#define RAW_IRQ_ENABLED		0x00
+#define ARCH_IRQ_DISABLED	0xf0
+#define ARCH_IRQ_ENABLED	0x00
 
 #include <asm-generic/irqflags.h>
 
diff --git a/arch/sh/include/asm/memblock.h b/arch/sh/include/asm/memblock.h
index dfe683b..e87063f 100644
--- a/arch/sh/include/asm/memblock.h
+++ b/arch/sh/include/asm/memblock.h
@@ -1,6 +1,4 @@
 #ifndef __ASM_SH_MEMBLOCK_H
 #define __ASM_SH_MEMBLOCK_H
 
-#define MEMBLOCK_REAL_LIMIT	0
-
 #endif /* __ASM_SH_MEMBLOCK_H */
diff --git a/arch/sh/include/asm/perf_event.h b/arch/sh/include/asm/perf_event.h
index 3d0c9f3..14308be 100644
--- a/arch/sh/include/asm/perf_event.h
+++ b/arch/sh/include/asm/perf_event.h
@@ -26,11 +26,4 @@
 extern int reserve_pmc_hardware(void);
 extern void release_pmc_hardware(void);
 
-static inline void set_perf_event_pending(void)
-{
-	/* Nothing to see here, move along. */
-}
-
-#define PERF_EVENT_INDEX_OFFSET	0
-
 #endif /* __ASM_SH_PERF_EVENT_H */
diff --git a/arch/sh/include/asm/syscalls_32.h b/arch/sh/include/asm/syscalls_32.h
index be201fd..ae717e3 100644
--- a/arch/sh/include/asm/syscalls_32.h
+++ b/arch/sh/include/asm/syscalls_32.h
@@ -19,9 +19,10 @@
 asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
 			 unsigned long r6, unsigned long r7,
 			 struct pt_regs __regs);
-asmlinkage int sys_execve(const char __user *ufilename, char __user * __user *uargv,
-			  char __user * __user *uenvp, unsigned long r7,
-			  struct pt_regs __regs);
+asmlinkage int sys_execve(const char __user *ufilename,
+			  const char __user *const __user *uargv,
+			  const char __user *const __user *uenvp,
+			  unsigned long r7, struct pt_regs __regs);
 asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5,
 			      unsigned long r6, unsigned long r7,
 			      struct pt_regs __regs);
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 257de1f..ae5bac3 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -290,7 +290,7 @@
 int __init arch_probe_nr_irqs(void)
 {
 	nr_irqs = sh_mv.mv_nr_irqs;
-	return 0;
+	return NR_IRQS_LEGACY;
 }
 #endif
 
diff --git a/arch/sh/kernel/irq_32.c b/arch/sh/kernel/irq_32.c
index e33ab15..e5a755b 100644
--- a/arch/sh/kernel/irq_32.c
+++ b/arch/sh/kernel/irq_32.c
@@ -10,11 +10,11 @@
 #include <linux/irqflags.h>
 #include <linux/module.h>
 
-void notrace raw_local_irq_restore(unsigned long flags)
+void notrace arch_local_irq_restore(unsigned long flags)
 {
 	unsigned long __dummy0, __dummy1;
 
-	if (flags == RAW_IRQ_DISABLED) {
+	if (flags == ARCH_IRQ_DISABLED) {
 		__asm__ __volatile__ (
 			"stc	sr, %0\n\t"
 			"or	#0xf0, %0\n\t"
@@ -33,14 +33,14 @@
 #endif
 			"ldc	%0, sr\n\t"
 			: "=&r" (__dummy0), "=r" (__dummy1)
-			: "1" (~RAW_IRQ_DISABLED)
+			: "1" (~ARCH_IRQ_DISABLED)
 			: "memory"
 		);
 	}
 }
-EXPORT_SYMBOL(raw_local_irq_restore);
+EXPORT_SYMBOL(arch_local_irq_restore);
 
-unsigned long notrace __raw_local_save_flags(void)
+unsigned long notrace arch_local_save_flags(void)
 {
 	unsigned long flags;
 
@@ -54,4 +54,4 @@
 
 	return flags;
 }
-EXPORT_SYMBOL(__raw_local_save_flags);
+EXPORT_SYMBOL(arch_local_save_flags);
diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c
index 43adddf..ae0be69 100644
--- a/arch/sh/kernel/module.c
+++ b/arch/sh/kernel/module.c
@@ -149,13 +149,11 @@
 	int ret = 0;
 
 	ret |= module_dwarf_finalize(hdr, sechdrs, me);
-	ret |= module_bug_finalize(hdr, sechdrs, me);
 
 	return ret;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
-	module_bug_cleanup(mod);
 	module_dwarf_cleanup(mod);
 }
diff --git a/arch/sh/kernel/perf_callchain.c b/arch/sh/kernel/perf_callchain.c
index a9dd3ab..d5ca1ef 100644
--- a/arch/sh/kernel/perf_callchain.c
+++ b/arch/sh/kernel/perf_callchain.c
@@ -14,11 +14,6 @@
 #include <asm/unwinder.h>
 #include <asm/ptrace.h>
 
-static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
-	if (entry->nr < PERF_MAX_STACK_DEPTH)
-		entry->ip[entry->nr++] = ip;
-}
 
 static void callchain_warning(void *data, char *msg)
 {
@@ -39,7 +34,7 @@
 	struct perf_callchain_entry *entry = data;
 
 	if (reliable)
-		callchain_store(entry, addr);
+		perf_callchain_store(entry, addr);
 }
 
 static const struct stacktrace_ops callchain_ops = {
@@ -49,47 +44,10 @@
 	.address	= callchain_address,
 };
 
-static void
-perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
-	callchain_store(entry, PERF_CONTEXT_KERNEL);
-	callchain_store(entry, regs->pc);
+	perf_callchain_store(entry, regs->pc);
 
 	unwind_stack(NULL, regs, NULL, &callchain_ops, entry);
 }
-
-static void
-perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry)
-{
-	int is_user;
-
-	if (!regs)
-		return;
-
-	is_user = user_mode(regs);
-
-	if (is_user && current->state != TASK_RUNNING)
-		return;
-
-	/*
-	 * Only the kernel side is implemented for now.
-	 */
-	if (!is_user)
-		perf_callchain_kernel(regs, entry);
-}
-
-/*
- * No need for separate IRQ and NMI entries.
- */
-static DEFINE_PER_CPU(struct perf_callchain_entry, callchain);
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
-{
-	struct perf_callchain_entry *entry = &__get_cpu_var(callchain);
-
-	entry->nr = 0;
-
-	perf_do_callchain(regs, entry);
-
-	return entry;
-}
diff --git a/arch/sh/kernel/perf_event.c b/arch/sh/kernel/perf_event.c
index 7a3dc35..5a4b334 100644
--- a/arch/sh/kernel/perf_event.c
+++ b/arch/sh/kernel/perf_event.c
@@ -59,6 +59,24 @@
 	return !!sh_pmu;
 }
 
+const char *perf_pmu_name(void)
+{
+	if (!sh_pmu)
+		return NULL;
+
+	return sh_pmu->name;
+}
+EXPORT_SYMBOL_GPL(perf_pmu_name);
+
+int perf_num_counters(void)
+{
+	if (!sh_pmu)
+		return 0;
+
+	return sh_pmu->num_events;
+}
+EXPORT_SYMBOL_GPL(perf_num_counters);
+
 /*
  * Release the PMU if this is the last perf_event.
  */
@@ -206,50 +224,80 @@
 	local64_add(delta, &event->count);
 }
 
-static void sh_pmu_disable(struct perf_event *event)
+static void sh_pmu_stop(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
 	int idx = hwc->idx;
 
-	clear_bit(idx, cpuc->active_mask);
-	sh_pmu->disable(hwc, idx);
+	if (!(event->hw.state & PERF_HES_STOPPED)) {
+		sh_pmu->disable(hwc, idx);
+		cpuc->events[idx] = NULL;
+		event->hw.state |= PERF_HES_STOPPED;
+	}
 
-	barrier();
+	if ((flags & PERF_EF_UPDATE) && !(event->hw.state & PERF_HES_UPTODATE)) {
+		sh_perf_event_update(event, &event->hw, idx);
+		event->hw.state |= PERF_HES_UPTODATE;
+	}
+}
 
-	sh_perf_event_update(event, &event->hw, idx);
+static void sh_pmu_start(struct perf_event *event, int flags)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	struct hw_perf_event *hwc = &event->hw;
+	int idx = hwc->idx;
 
-	cpuc->events[idx] = NULL;
-	clear_bit(idx, cpuc->used_mask);
+	if (WARN_ON_ONCE(idx == -1))
+		return;
+
+	if (flags & PERF_EF_RELOAD)
+		WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+
+	cpuc->events[idx] = event;
+	event->hw.state = 0;
+	sh_pmu->enable(hwc, idx);
+}
+
+static void sh_pmu_del(struct perf_event *event, int flags)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+	sh_pmu_stop(event, PERF_EF_UPDATE);
+	__clear_bit(event->hw.idx, cpuc->used_mask);
 
 	perf_event_update_userpage(event);
 }
 
-static int sh_pmu_enable(struct perf_event *event)
+static int sh_pmu_add(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
 	int idx = hwc->idx;
+	int ret = -EAGAIN;
 
-	if (test_and_set_bit(idx, cpuc->used_mask)) {
+	perf_pmu_disable(event->pmu);
+
+	if (__test_and_set_bit(idx, cpuc->used_mask)) {
 		idx = find_first_zero_bit(cpuc->used_mask, sh_pmu->num_events);
 		if (idx == sh_pmu->num_events)
-			return -EAGAIN;
+			goto out;
 
-		set_bit(idx, cpuc->used_mask);
+		__set_bit(idx, cpuc->used_mask);
 		hwc->idx = idx;
 	}
 
 	sh_pmu->disable(hwc, idx);
 
-	cpuc->events[idx] = event;
-	set_bit(idx, cpuc->active_mask);
-
-	sh_pmu->enable(hwc, idx);
+	event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+	if (flags & PERF_EF_START)
+		sh_pmu_start(event, PERF_EF_RELOAD);
 
 	perf_event_update_userpage(event);
-
-	return 0;
+	ret = 0;
+out:
+	perf_pmu_enable(event->pmu);
+	return ret;
 }
 
 static void sh_pmu_read(struct perf_event *event)
@@ -257,24 +305,56 @@
 	sh_perf_event_update(event, &event->hw, event->hw.idx);
 }
 
-static const struct pmu pmu = {
-	.enable		= sh_pmu_enable,
-	.disable	= sh_pmu_disable,
-	.read		= sh_pmu_read,
-};
-
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int sh_pmu_event_init(struct perf_event *event)
 {
-	int err = __hw_perf_event_init(event);
+	int err;
+
+	switch (event->attr.type) {
+	case PERF_TYPE_RAW:
+	case PERF_TYPE_HW_CACHE:
+	case PERF_TYPE_HARDWARE:
+		err = __hw_perf_event_init(event);
+		break;
+
+	default:
+		return -ENOENT;
+	}
+
 	if (unlikely(err)) {
 		if (event->destroy)
 			event->destroy(event);
-		return ERR_PTR(err);
 	}
 
-	return &pmu;
+	return err;
 }
 
+static void sh_pmu_enable(struct pmu *pmu)
+{
+	if (!sh_pmu_initialized())
+		return;
+
+	sh_pmu->enable_all();
+}
+
+static void sh_pmu_disable(struct pmu *pmu)
+{
+	if (!sh_pmu_initialized())
+		return;
+
+	sh_pmu->disable_all();
+}
+
+static struct pmu pmu = {
+	.pmu_enable	= sh_pmu_enable,
+	.pmu_disable	= sh_pmu_disable,
+	.event_init	= sh_pmu_event_init,
+	.add		= sh_pmu_add,
+	.del		= sh_pmu_del,
+	.start		= sh_pmu_start,
+	.stop		= sh_pmu_stop,
+	.read		= sh_pmu_read,
+};
+
 static void sh_pmu_setup(int cpu)
 {
 	struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu);
@@ -299,32 +379,17 @@
 	return NOTIFY_OK;
 }
 
-void hw_perf_enable(void)
-{
-	if (!sh_pmu_initialized())
-		return;
-
-	sh_pmu->enable_all();
-}
-
-void hw_perf_disable(void)
-{
-	if (!sh_pmu_initialized())
-		return;
-
-	sh_pmu->disable_all();
-}
-
-int __cpuinit register_sh_pmu(struct sh_pmu *pmu)
+int __cpuinit register_sh_pmu(struct sh_pmu *_pmu)
 {
 	if (sh_pmu)
 		return -EBUSY;
-	sh_pmu = pmu;
+	sh_pmu = _pmu;
 
-	pr_info("Performance Events: %s support registered\n", pmu->name);
+	pr_info("Performance Events: %s support registered\n", _pmu->name);
 
-	WARN_ON(pmu->num_events > MAX_HWEVENTS);
+	WARN_ON(_pmu->num_events > MAX_HWEVENTS);
 
+	perf_pmu_register(&pmu);
 	perf_cpu_notifier(sh_pmu_notifier);
 	return 0;
 }
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index d0e24910..552bea5 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -200,7 +200,6 @@
 	unsigned long total_pages, paddr;
 	unsigned long end_pfn;
 	struct pglist_data *p;
-	int i;
 
 	p = NODE_DATA(nid);
 
@@ -226,11 +225,12 @@
 	 * reservations in other nodes.
 	 */
 	if (nid == 0) {
+		struct memblock_region *reg;
+
 		/* Reserve the sections we're already using. */
-		for (i = 0; i < memblock.reserved.cnt; i++)
-			reserve_bootmem(memblock.reserved.region[i].base,
-					memblock_size_bytes(&memblock.reserved, i),
-					BOOTMEM_DEFAULT);
+		for_each_memblock(reserved, reg) {
+			reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+		}
 	}
 
 	sparse_memory_present_with_active_regions(nid);
@@ -238,13 +238,14 @@
 
 static void __init do_init_bootmem(void)
 {
+	struct memblock_region *reg;
 	int i;
 
 	/* Add active regions with valid PFNs. */
-	for (i = 0; i < memblock.memory.cnt; i++) {
+	for_each_memblock(memory, reg) {
 		unsigned long start_pfn, end_pfn;
-		start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
-		end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+		start_pfn = memblock_region_memory_base_pfn(reg);
+		end_pfn = memblock_region_memory_end_pfn(reg);
 		__add_active_range(0, start_pfn, end_pfn);
 	}
 
diff --git a/arch/sh/oprofile/Makefile b/arch/sh/oprofile/Makefile
index 4886c5c..e85aae7 100644
--- a/arch/sh/oprofile/Makefile
+++ b/arch/sh/oprofile/Makefile
@@ -6,4 +6,8 @@
 		oprofilefs.o oprofile_stats.o \
 		timer_int.o )
 
+ifeq ($(CONFIG_HW_PERF_EVENTS),y)
+DRIVER_OBJS += $(addprefix ../../../drivers/oprofile/, oprofile_perf.o)
+endif
+
 oprofile-y	:= $(DRIVER_OBJS) common.o backtrace.o
diff --git a/arch/sh/oprofile/common.c b/arch/sh/oprofile/common.c
index ac60493..e10d893 100644
--- a/arch/sh/oprofile/common.c
+++ b/arch/sh/oprofile/common.c
@@ -17,114 +17,45 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
+#include <linux/perf_event.h>
 #include <asm/processor.h>
-#include "op_impl.h"
 
-static struct op_sh_model *model;
-
-static struct op_counter_config ctr[20];
-
+#ifdef CONFIG_HW_PERF_EVENTS
 extern void sh_backtrace(struct pt_regs * const regs, unsigned int depth);
 
-static int op_sh_setup(void)
+char *op_name_from_perf_id(void)
 {
-	/* Pre-compute the values to stuff in the hardware registers.  */
-	model->reg_setup(ctr);
+	const char *pmu;
+	char buf[20];
+	int size;
 
-	/* Configure the registers on all cpus.  */
-	on_each_cpu(model->cpu_setup, NULL, 1);
+	pmu = perf_pmu_name();
+	if (!pmu)
+		return NULL;
 
-        return 0;
-}
+	size = snprintf(buf, sizeof(buf), "sh/%s", pmu);
+	if (size > -1 && size < sizeof(buf))
+		return buf;
 
-static int op_sh_create_files(struct super_block *sb, struct dentry *root)
-{
-	int i, ret = 0;
-
-	for (i = 0; i < model->num_counters; i++) {
-		struct dentry *dir;
-		char buf[4];
-
-		snprintf(buf, sizeof(buf), "%d", i);
-		dir = oprofilefs_mkdir(sb, root, buf);
-
-		ret |= oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
-		ret |= oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
-		ret |= oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
-		ret |= oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
-
-		if (model->create_files)
-			ret |= model->create_files(sb, dir);
-		else
-			ret |= oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
-
-		/* Dummy entries */
-		ret |= oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
-	}
-
-	return ret;
-}
-
-static int op_sh_start(void)
-{
-	/* Enable performance monitoring for all counters.  */
-	on_each_cpu(model->cpu_start, NULL, 1);
-
-	return 0;
-}
-
-static void op_sh_stop(void)
-{
-	/* Disable performance monitoring for all counters.  */
-	on_each_cpu(model->cpu_stop, NULL, 1);
+	return NULL;
 }
 
 int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
-	struct op_sh_model *lmodel = NULL;
-	int ret;
-
-	/*
-	 * Always assign the backtrace op. If the counter initialization
-	 * fails, we fall back to the timer which will still make use of
-	 * this.
-	 */
 	ops->backtrace = sh_backtrace;
 
-	/*
-	 * XXX
-	 *
-	 * All of the SH7750/SH-4A counters have been converted to perf,
-	 * this infrastructure hook is left for other users until they've
-	 * had a chance to convert over, at which point all of this
-	 * will be deleted.
-	 */
-
-	if (!lmodel)
-		return -ENODEV;
-	if (!(current_cpu_data.flags & CPU_HAS_PERF_COUNTER))
-		return -ENODEV;
-
-	ret = lmodel->init();
-	if (unlikely(ret != 0))
-		return ret;
-
-	model = lmodel;
-
-	ops->setup		= op_sh_setup;
-	ops->create_files	= op_sh_create_files;
-	ops->start		= op_sh_start;
-	ops->stop		= op_sh_stop;
-	ops->cpu_type		= lmodel->cpu_type;
-
-	printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
-	       lmodel->cpu_type);
-
-	return 0;
+	return oprofile_perf_init(ops);
 }
 
-void oprofile_arch_exit(void)
+void __exit oprofile_arch_exit(void)
 {
-	if (model && model->exit)
-		model->exit();
+	oprofile_perf_exit();
 }
+#else
+int __init oprofile_arch_init(struct oprofile_operations *ops)
+{
+	pr_info("oprofile: hardware counters not available\n");
+	return -ENODEV;
+}
+void __exit oprofile_arch_exit(void) {}
+#endif /* CONFIG_HW_PERF_EVENTS */
diff --git a/arch/sh/oprofile/op_impl.h b/arch/sh/oprofile/op_impl.h
deleted file mode 100644
index 1244479..0000000
--- a/arch/sh/oprofile/op_impl.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef __OP_IMPL_H
-#define __OP_IMPL_H
-
-/* Per-counter configuration as set via oprofilefs.  */
-struct op_counter_config {
-	unsigned long enabled;
-	unsigned long event;
-
-	unsigned long count;
-
-	/* Dummy values for userspace tool compliance */
-	unsigned long kernel;
-	unsigned long user;
-	unsigned long unit_mask;
-};
-
-/* Per-architecture configury and hooks.  */
-struct op_sh_model {
-	void (*reg_setup)(struct op_counter_config *);
-	int (*create_files)(struct super_block *sb, struct dentry *dir);
-	void (*cpu_setup)(void *dummy);
-	int (*init)(void);
-	void (*exit)(void);
-	void (*cpu_start)(void *args);
-	void (*cpu_stop)(void *args);
-	char *cpu_type;
-	unsigned char num_counters;
-};
-
-/* arch/sh/oprofile/common.c */
-extern void sh_backtrace(struct pt_regs * const regs, unsigned int depth);
-
-#endif /* __OP_IMPL_H */
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 491e9d6..3e9d314 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -26,10 +26,12 @@
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select RTC_CLASS
 	select RTC_DRV_M48T59
+	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_API_DEBUG
+	select HAVE_ARCH_JUMP_LABEL
 
 config SPARC32
 	def_bool !64BIT
@@ -53,6 +55,7 @@
 	select RTC_DRV_BQ4802
 	select RTC_DRV_SUN4V
 	select RTC_DRV_STARFIRE
+	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
 
diff --git a/arch/sparc/include/asm/irqflags_32.h b/arch/sparc/include/asm/irqflags_32.h
index 0fca9d9..d4d0711 100644
--- a/arch/sparc/include/asm/irqflags_32.h
+++ b/arch/sparc/include/asm/irqflags_32.h
@@ -5,33 +5,40 @@
  *
  * This file gets included from lowlevel asm headers too, to provide
  * wrapped versions of the local_irq_*() APIs, based on the
- * raw_local_irq_*() functions from the lowlevel headers.
+ * arch_local_irq_*() functions from the lowlevel headers.
  */
 #ifndef _ASM_IRQFLAGS_H
 #define _ASM_IRQFLAGS_H
 
 #ifndef __ASSEMBLY__
 
-extern void raw_local_irq_restore(unsigned long);
-extern unsigned long __raw_local_irq_save(void);
-extern void raw_local_irq_enable(void);
+#include <linux/types.h>
 
-static inline unsigned long getipl(void)
+extern void arch_local_irq_restore(unsigned long);
+extern unsigned long arch_local_irq_save(void);
+extern void arch_local_irq_enable(void);
+
+static inline unsigned long arch_local_save_flags(void)
 {
-        unsigned long retval;
+	unsigned long flags;
 
-        __asm__ __volatile__("rd        %%psr, %0" : "=r" (retval));
-        return retval;
+	asm volatile("rd        %%psr, %0" : "=r" (flags));
+	return flags;
 }
 
-#define raw_local_save_flags(flags) ((flags) = getipl())
-#define raw_local_irq_save(flags)   ((flags) = __raw_local_irq_save())
-#define raw_local_irq_disable()     ((void) __raw_local_irq_save())
-#define raw_irqs_disabled()         ((getipl() & PSR_PIL) != 0)
-
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline void arch_local_irq_disable(void)
 {
-        return ((flags & PSR_PIL) != 0);
+	arch_local_irq_save();
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags & PSR_PIL) != 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
 #endif /* (__ASSEMBLY__) */
diff --git a/arch/sparc/include/asm/irqflags_64.h b/arch/sparc/include/asm/irqflags_64.h
index bfa1ea4..aab969c 100644
--- a/arch/sparc/include/asm/irqflags_64.h
+++ b/arch/sparc/include/asm/irqflags_64.h
@@ -5,7 +5,7 @@
  *
  * This file gets included from lowlevel asm headers too, to provide
  * wrapped versions of the local_irq_*() APIs, based on the
- * raw_local_irq_*() functions from the lowlevel headers.
+ * arch_local_irq_*() functions from the lowlevel headers.
  */
 #ifndef _ASM_IRQFLAGS_H
 #define _ASM_IRQFLAGS_H
@@ -14,7 +14,7 @@
 
 #ifndef __ASSEMBLY__
 
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
 {
 	unsigned long flags;
 
@@ -26,10 +26,7 @@
 	return flags;
 }
 
-#define raw_local_save_flags(flags) \
-		do { (flags) = __raw_local_save_flags(); } while (0)
-
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
 {
 	__asm__ __volatile__(
 		"wrpr	%0, %%pil"
@@ -39,7 +36,7 @@
 	);
 }
 
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
 {
 	__asm__ __volatile__(
 		"wrpr	%0, %%pil"
@@ -49,7 +46,7 @@
 	);
 }
 
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
 {
 	__asm__ __volatile__(
 		"wrpr	0, %%pil"
@@ -59,22 +56,17 @@
 	);
 }
 
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
 	return (flags > 0);
 }
 
-static inline int raw_irqs_disabled(void)
+static inline int arch_irqs_disabled(void)
 {
-	unsigned long flags = __raw_local_save_flags();
-
-	return raw_irqs_disabled_flags(flags);
+	return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
-/*
- * For spinlocks, etc:
- */
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
 {
 	unsigned long flags, tmp;
 
@@ -100,9 +92,6 @@
 	return flags;
 }
 
-#define raw_local_irq_save(flags) \
-		do { (flags) = __raw_local_irq_save(); } while (0)
-
 #endif /* (__ASSEMBLY__) */
 
 #endif /* !(_ASM_IRQFLAGS_H) */
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
new file mode 100644
index 0000000..62e66d7
--- /dev/null
+++ b/arch/sparc/include/asm/jump_label.h
@@ -0,0 +1,32 @@
+#ifndef _ASM_SPARC_JUMP_LABEL_H
+#define _ASM_SPARC_JUMP_LABEL_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <asm/system.h>
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+#define JUMP_LABEL(key, label)					\
+	do {							\
+		asm goto("1:\n\t"				\
+			 "nop\n\t"				\
+			 "nop\n\t"				\
+			 ".pushsection __jump_table,  \"a\"\n\t"\
+			 ".word 1b, %l[" #label "], %c0\n\t"	\
+			 ".popsection \n\t"			\
+			 : :  "i" (key) :  : label);\
+	} while (0)
+
+#endif /* __KERNEL__ */
+
+typedef u32 jump_label_t;
+
+struct jump_entry {
+	jump_label_t code;
+	jump_label_t target;
+	jump_label_t key;
+};
+
+#endif
diff --git a/arch/sparc/include/asm/memblock.h b/arch/sparc/include/asm/memblock.h
index f12af88..c67b047 100644
--- a/arch/sparc/include/asm/memblock.h
+++ b/arch/sparc/include/asm/memblock.h
@@ -5,6 +5,4 @@
 
 #define MEMBLOCK_DBG(fmt...) prom_printf(fmt)
 
-#define MEMBLOCK_REAL_LIMIT	0
-
 #endif /* !(_SPARC64_MEMBLOCK_H) */
diff --git a/arch/sparc/include/asm/perf_event.h b/arch/sparc/include/asm/perf_event.h
index 727af70..6e8bfa1 100644
--- a/arch/sparc/include/asm/perf_event.h
+++ b/arch/sparc/include/asm/perf_event.h
@@ -1,10 +1,6 @@
 #ifndef __ASM_SPARC_PERF_EVENT_H
 #define __ASM_SPARC_PERF_EVENT_H
 
-extern void set_perf_event_pending(void);
-
-#define	PERF_EVENT_INDEX_OFFSET	0
-
 #ifdef CONFIG_PERF_EVENTS
 #include <asm/ptrace.h>
 
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 0c2dc1f..599398f 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -119,3 +119,5 @@
 
 pc--$(CONFIG_PERF_EVENTS) := perf_event.o
 obj-$(CONFIG_SPARC64)	+= $(pc--y)
+
+obj-$(CONFIG_SPARC64)	+= jump_label.o
diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c
index 2c0046e..52de4a9 100644
--- a/arch/sparc/kernel/apc.c
+++ b/arch/sparc/kernel/apc.c
@@ -132,6 +132,7 @@
 	.unlocked_ioctl =	apc_ioctl,
 	.open =			apc_open,
 	.release =		apc_release,
+	.llseek =		noop_llseek,
 };
 
 static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops };
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index e1af437..0116d8d1 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -57,7 +57,7 @@
 #define SMP_NOP2
 #define SMP_NOP3
 #endif /* SMP */
-unsigned long __raw_local_irq_save(void)
+unsigned long arch_local_irq_save(void)
 {
 	unsigned long retval;
 	unsigned long tmp;
@@ -74,8 +74,9 @@
 
 	return retval;
 }
+EXPORT_SYMBOL(arch_local_irq_save);
 
-void raw_local_irq_enable(void)
+void arch_local_irq_enable(void)
 {
 	unsigned long tmp;
 
@@ -89,8 +90,9 @@
 		: "i" (PSR_PIL)
 		: "memory");
 }
+EXPORT_SYMBOL(arch_local_irq_enable);
 
-void raw_local_irq_restore(unsigned long old_psr)
+void arch_local_irq_restore(unsigned long old_psr)
 {
 	unsigned long tmp;
 
@@ -105,10 +107,7 @@
 		: "i" (PSR_PIL), "r" (old_psr)
 		: "memory");
 }
-
-EXPORT_SYMBOL(__raw_local_irq_save);
-EXPORT_SYMBOL(raw_local_irq_enable);
-EXPORT_SYMBOL(raw_local_irq_restore);
+EXPORT_SYMBOL(arch_local_irq_restore);
 
 /*
  * Dave Redman (djhr@tadpole.co.uk)
diff --git a/arch/sparc/kernel/jump_label.c b/arch/sparc/kernel/jump_label.c
new file mode 100644
index 0000000..ea2dafc
--- /dev/null
+++ b/arch/sparc/kernel/jump_label.c
@@ -0,0 +1,47 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/cpu.h>
+
+#include <linux/jump_label.h>
+#include <linux/memory.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+void arch_jump_label_transform(struct jump_entry *entry,
+			       enum jump_label_type type)
+{
+	u32 val;
+	u32 *insn = (u32 *) (unsigned long) entry->code;
+
+	if (type == JUMP_LABEL_ENABLE) {
+		s32 off = (s32)entry->target - (s32)entry->code;
+
+#ifdef CONFIG_SPARC64
+		/* ba,pt %xcc, . + (off << 2) */
+		val = 0x10680000 | ((u32) off >> 2);
+#else
+		/* ba . + (off << 2) */
+		val = 0x10800000 | ((u32) off >> 2);
+#endif
+	} else {
+		val = 0x01000000;
+	}
+
+	get_online_cpus();
+	mutex_lock(&text_mutex);
+	*insn = val;
+	flushi(insn);
+	mutex_unlock(&text_mutex);
+	put_online_cpus();
+}
+
+void arch_jump_label_text_poke_early(jump_label_t addr)
+{
+	u32 *insn_p = (u32 *) (unsigned long) addr;
+
+	*insn_p = 0x01000000;
+	flushi(insn_p);
+}
+
+#endif
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index 83e85c2..6addb91 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -890,6 +890,7 @@
 static const struct file_operations mdesc_fops = {
 	.read	= mdesc_read,
 	.owner	= THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice mdesc_misc = {
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index f848aad..ee3c7dd 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -18,6 +18,9 @@
 #include <asm/spitfire.h>
 
 #ifdef CONFIG_SPARC64
+
+#include <linux/jump_label.h>
+
 static void *module_map(unsigned long size)
 {
 	struct vm_struct *area;
@@ -227,6 +230,9 @@
 		    const Elf_Shdr *sechdrs,
 		    struct module *me)
 {
+	/* make jump label nops */
+	jump_label_apply_nops(me);
+
 	/* Cheetah's I-cache is fully coherent.  */
 	if (tlb_type == spitfire) {
 		unsigned long va;
diff --git a/arch/sparc/kernel/pci_msi.c b/arch/sparc/kernel/pci_msi.c
index 548b8ca..b210416 100644
--- a/arch/sparc/kernel/pci_msi.c
+++ b/arch/sparc/kernel/pci_msi.c
@@ -114,10 +114,10 @@
 
 static struct irq_chip msi_irq = {
 	.name		= "PCI-MSI",
-	.mask		= mask_msi_irq,
-	.unmask		= unmask_msi_irq,
-	.enable		= unmask_msi_irq,
-	.disable	= mask_msi_irq,
+	.irq_mask	= mask_msi_irq,
+	.irq_unmask	= unmask_msi_irq,
+	.irq_enable	= unmask_msi_irq,
+	.irq_disable	= mask_msi_irq,
 	/* XXX affinity XXX */
 };
 
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c
index c4a6a50..b87873c 100644
--- a/arch/sparc/kernel/pcr.c
+++ b/arch/sparc/kernel/pcr.c
@@ -7,7 +7,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 
-#include <linux/perf_event.h>
+#include <linux/irq_work.h>
 #include <linux/ftrace.h>
 
 #include <asm/pil.h>
@@ -43,14 +43,14 @@
 
 	old_regs = set_irq_regs(regs);
 	irq_enter();
-#ifdef CONFIG_PERF_EVENTS
-	perf_event_do_pending();
+#ifdef CONFIG_IRQ_WORK
+	irq_work_run();
 #endif
 	irq_exit();
 	set_irq_regs(old_regs);
 }
 
-void set_perf_event_pending(void)
+void arch_irq_work_raise(void)
 {
 	set_softint(1 << PIL_DEFERRED_PCR_WORK);
 }
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 6318e62..0d6deb5 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -658,13 +658,16 @@
 
 		enc = perf_event_get_enc(cpuc->events[i]);
 		pcr &= ~mask_for_index(idx);
-		pcr |= event_encoding(enc, idx);
+		if (hwc->state & PERF_HES_STOPPED)
+			pcr |= nop_for_index(idx);
+		else
+			pcr |= event_encoding(enc, idx);
 	}
 out:
 	return pcr;
 }
 
-void hw_perf_enable(void)
+static void sparc_pmu_enable(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	u64 pcr;
@@ -691,7 +694,7 @@
 	pcr_ops->write(cpuc->pcr);
 }
 
-void hw_perf_disable(void)
+static void sparc_pmu_disable(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	u64 val;
@@ -710,48 +713,6 @@
 	pcr_ops->write(cpuc->pcr);
 }
 
-static void sparc_pmu_disable(struct perf_event *event)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	struct hw_perf_event *hwc = &event->hw;
-	unsigned long flags;
-	int i;
-
-	local_irq_save(flags);
-	perf_disable();
-
-	for (i = 0; i < cpuc->n_events; i++) {
-		if (event == cpuc->event[i]) {
-			int idx = cpuc->current_idx[i];
-
-			/* Shift remaining entries down into
-			 * the existing slot.
-			 */
-			while (++i < cpuc->n_events) {
-				cpuc->event[i - 1] = cpuc->event[i];
-				cpuc->events[i - 1] = cpuc->events[i];
-				cpuc->current_idx[i - 1] =
-					cpuc->current_idx[i];
-			}
-
-			/* Absorb the final count and turn off the
-			 * event.
-			 */
-			sparc_pmu_disable_event(cpuc, hwc, idx);
-			barrier();
-			sparc_perf_event_update(event, hwc, idx);
-
-			perf_event_update_userpage(event);
-
-			cpuc->n_events--;
-			break;
-		}
-	}
-
-	perf_enable();
-	local_irq_restore(flags);
-}
-
 static int active_event_index(struct cpu_hw_events *cpuc,
 			      struct perf_event *event)
 {
@@ -765,6 +726,74 @@
 	return cpuc->current_idx[i];
 }
 
+static void sparc_pmu_start(struct perf_event *event, int flags)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	int idx = active_event_index(cpuc, event);
+
+	if (flags & PERF_EF_RELOAD) {
+		WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+		sparc_perf_event_set_period(event, &event->hw, idx);
+	}
+
+	event->hw.state = 0;
+
+	sparc_pmu_enable_event(cpuc, &event->hw, idx);
+}
+
+static void sparc_pmu_stop(struct perf_event *event, int flags)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	int idx = active_event_index(cpuc, event);
+
+	if (!(event->hw.state & PERF_HES_STOPPED)) {
+		sparc_pmu_disable_event(cpuc, &event->hw, idx);
+		event->hw.state |= PERF_HES_STOPPED;
+	}
+
+	if (!(event->hw.state & PERF_HES_UPTODATE) && (flags & PERF_EF_UPDATE)) {
+		sparc_perf_event_update(event, &event->hw, idx);
+		event->hw.state |= PERF_HES_UPTODATE;
+	}
+}
+
+static void sparc_pmu_del(struct perf_event *event, int _flags)
+{
+	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+	perf_pmu_disable(event->pmu);
+
+	for (i = 0; i < cpuc->n_events; i++) {
+		if (event == cpuc->event[i]) {
+			/* Absorb the final count and turn off the
+			 * event.
+			 */
+			sparc_pmu_stop(event, PERF_EF_UPDATE);
+
+			/* Shift remaining entries down into
+			 * the existing slot.
+			 */
+			while (++i < cpuc->n_events) {
+				cpuc->event[i - 1] = cpuc->event[i];
+				cpuc->events[i - 1] = cpuc->events[i];
+				cpuc->current_idx[i - 1] =
+					cpuc->current_idx[i];
+			}
+
+			perf_event_update_userpage(event);
+
+			cpuc->n_events--;
+			break;
+		}
+	}
+
+	perf_pmu_enable(event->pmu);
+	local_irq_restore(flags);
+}
+
 static void sparc_pmu_read(struct perf_event *event)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -774,15 +803,6 @@
 	sparc_perf_event_update(event, hwc, idx);
 }
 
-static void sparc_pmu_unthrottle(struct perf_event *event)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	int idx = active_event_index(cpuc, event);
-	struct hw_perf_event *hwc = &event->hw;
-
-	sparc_pmu_enable_event(cpuc, hwc, idx);
-}
-
 static atomic_t active_events = ATOMIC_INIT(0);
 static DEFINE_MUTEX(pmc_grab_mutex);
 
@@ -877,7 +897,7 @@
 	if (!n_ev)
 		return 0;
 
-	if (n_ev > perf_max_events)
+	if (n_ev > MAX_HWEVENTS)
 		return -1;
 
 	msk0 = perf_event_get_msk(events[0]);
@@ -984,23 +1004,27 @@
 	return n;
 }
 
-static int sparc_pmu_enable(struct perf_event *event)
+static int sparc_pmu_add(struct perf_event *event, int ef_flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	int n0, ret = -EAGAIN;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	perf_disable();
+	perf_pmu_disable(event->pmu);
 
 	n0 = cpuc->n_events;
-	if (n0 >= perf_max_events)
+	if (n0 >= MAX_HWEVENTS)
 		goto out;
 
 	cpuc->event[n0] = event;
 	cpuc->events[n0] = event->hw.event_base;
 	cpuc->current_idx[n0] = PIC_NO_INDEX;
 
+	event->hw.state = PERF_HES_UPTODATE;
+	if (!(ef_flags & PERF_EF_START))
+		event->hw.state |= PERF_HES_STOPPED;
+
 	/*
 	 * If group events scheduling transaction was started,
 	 * skip the schedulability test here, it will be peformed
@@ -1020,12 +1044,12 @@
 
 	ret = 0;
 out:
-	perf_enable();
+	perf_pmu_enable(event->pmu);
 	local_irq_restore(flags);
 	return ret;
 }
 
-static int __hw_perf_event_init(struct perf_event *event)
+static int sparc_pmu_event_init(struct perf_event *event)
 {
 	struct perf_event_attr *attr = &event->attr;
 	struct perf_event *evts[MAX_HWEVENTS];
@@ -1038,22 +1062,33 @@
 	if (atomic_read(&nmi_active) < 0)
 		return -ENODEV;
 
-	pmap = NULL;
-	if (attr->type == PERF_TYPE_HARDWARE) {
+	switch (attr->type) {
+	case PERF_TYPE_HARDWARE:
 		if (attr->config >= sparc_pmu->max_events)
 			return -EINVAL;
 		pmap = sparc_pmu->event_map(attr->config);
-	} else if (attr->type == PERF_TYPE_HW_CACHE) {
+		break;
+
+	case PERF_TYPE_HW_CACHE:
 		pmap = sparc_map_cache_event(attr->config);
 		if (IS_ERR(pmap))
 			return PTR_ERR(pmap);
-	} else if (attr->type != PERF_TYPE_RAW)
-		return -EOPNOTSUPP;
+		break;
+
+	case PERF_TYPE_RAW:
+		pmap = NULL;
+		break;
+
+	default:
+		return -ENOENT;
+
+	}
 
 	if (pmap) {
 		hwc->event_base = perf_event_encode(pmap);
 	} else {
-		/* User gives us "(encoding << 16) | pic_mask" for
+		/*
+		 * User gives us "(encoding << 16) | pic_mask" for
 		 * PERF_TYPE_RAW events.
 		 */
 		hwc->event_base = attr->config;
@@ -1071,7 +1106,7 @@
 	n = 0;
 	if (event->group_leader != event) {
 		n = collect_events(event->group_leader,
-				   perf_max_events - 1,
+				   MAX_HWEVENTS - 1,
 				   evts, events, current_idx_dmy);
 		if (n < 0)
 			return -EINVAL;
@@ -1107,10 +1142,11 @@
  * Set the flag to make pmu::enable() not perform the
  * schedulability test, it will be performed at commit time
  */
-static void sparc_pmu_start_txn(const struct pmu *pmu)
+static void sparc_pmu_start_txn(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
 
+	perf_pmu_disable(pmu);
 	cpuhw->group_flag |= PERF_EVENT_TXN;
 }
 
@@ -1119,11 +1155,12 @@
  * Clear the flag and pmu::enable() will perform the
  * schedulability test.
  */
-static void sparc_pmu_cancel_txn(const struct pmu *pmu)
+static void sparc_pmu_cancel_txn(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
 
 	cpuhw->group_flag &= ~PERF_EVENT_TXN;
+	perf_pmu_enable(pmu);
 }
 
 /*
@@ -1131,7 +1168,7 @@
  * Perform the group schedulability test as a whole
  * Return 0 if success
  */
-static int sparc_pmu_commit_txn(const struct pmu *pmu)
+static int sparc_pmu_commit_txn(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	int n;
@@ -1147,28 +1184,24 @@
 		return -EAGAIN;
 
 	cpuc->group_flag &= ~PERF_EVENT_TXN;
+	perf_pmu_enable(pmu);
 	return 0;
 }
 
-static const struct pmu pmu = {
-	.enable		= sparc_pmu_enable,
-	.disable	= sparc_pmu_disable,
+static struct pmu pmu = {
+	.pmu_enable	= sparc_pmu_enable,
+	.pmu_disable	= sparc_pmu_disable,
+	.event_init	= sparc_pmu_event_init,
+	.add		= sparc_pmu_add,
+	.del		= sparc_pmu_del,
+	.start		= sparc_pmu_start,
+	.stop		= sparc_pmu_stop,
 	.read		= sparc_pmu_read,
-	.unthrottle	= sparc_pmu_unthrottle,
 	.start_txn	= sparc_pmu_start_txn,
 	.cancel_txn	= sparc_pmu_cancel_txn,
 	.commit_txn	= sparc_pmu_commit_txn,
 };
 
-const struct pmu *hw_perf_event_init(struct perf_event *event)
-{
-	int err = __hw_perf_event_init(event);
-
-	if (err)
-		return ERR_PTR(err);
-	return &pmu;
-}
-
 void perf_event_print_debug(void)
 {
 	unsigned long flags;
@@ -1244,7 +1277,7 @@
 			continue;
 
 		if (perf_event_overflow(event, 1, &data, regs))
-			sparc_pmu_disable_event(cpuc, hwc, idx);
+			sparc_pmu_stop(event, 0);
 	}
 
 	return NOTIFY_STOP;
@@ -1285,28 +1318,21 @@
 
 	pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
 
-	/* All sparc64 PMUs currently have 2 events.  */
-	perf_max_events = 2;
-
+	perf_pmu_register(&pmu);
 	register_die_notifier(&perf_event_nmi_notifier);
 }
 
-static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
-	if (entry->nr < PERF_MAX_STACK_DEPTH)
-		entry->ip[entry->nr++] = ip;
-}
-
-static void perf_callchain_kernel(struct pt_regs *regs,
-				  struct perf_callchain_entry *entry)
+void perf_callchain_kernel(struct perf_callchain_entry *entry,
+			   struct pt_regs *regs)
 {
 	unsigned long ksp, fp;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	int graph = 0;
 #endif
 
-	callchain_store(entry, PERF_CONTEXT_KERNEL);
-	callchain_store(entry, regs->tpc);
+	stack_trace_flush();
+
+	perf_callchain_store(entry, regs->tpc);
 
 	ksp = regs->u_regs[UREG_I6];
 	fp = ksp + STACK_BIAS;
@@ -1330,13 +1356,13 @@
 			pc = sf->callers_pc;
 			fp = (unsigned long)sf->fp + STACK_BIAS;
 		}
-		callchain_store(entry, pc);
+		perf_callchain_store(entry, pc);
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 		if ((pc + 8UL) == (unsigned long) &return_to_handler) {
 			int index = current->curr_ret_stack;
 			if (current->ret_stack && index >= graph) {
 				pc = current->ret_stack[index - graph].ret;
-				callchain_store(entry, pc);
+				perf_callchain_store(entry, pc);
 				graph++;
 			}
 		}
@@ -1344,13 +1370,12 @@
 	} while (entry->nr < PERF_MAX_STACK_DEPTH);
 }
 
-static void perf_callchain_user_64(struct pt_regs *regs,
-				   struct perf_callchain_entry *entry)
+static void perf_callchain_user_64(struct perf_callchain_entry *entry,
+				   struct pt_regs *regs)
 {
 	unsigned long ufp;
 
-	callchain_store(entry, PERF_CONTEXT_USER);
-	callchain_store(entry, regs->tpc);
+	perf_callchain_store(entry, regs->tpc);
 
 	ufp = regs->u_regs[UREG_I6] + STACK_BIAS;
 	do {
@@ -1363,17 +1388,16 @@
 
 		pc = sf.callers_pc;
 		ufp = (unsigned long)sf.fp + STACK_BIAS;
-		callchain_store(entry, pc);
+		perf_callchain_store(entry, pc);
 	} while (entry->nr < PERF_MAX_STACK_DEPTH);
 }
 
-static void perf_callchain_user_32(struct pt_regs *regs,
-				   struct perf_callchain_entry *entry)
+static void perf_callchain_user_32(struct perf_callchain_entry *entry,
+				   struct pt_regs *regs)
 {
 	unsigned long ufp;
 
-	callchain_store(entry, PERF_CONTEXT_USER);
-	callchain_store(entry, regs->tpc);
+	perf_callchain_store(entry, regs->tpc);
 
 	ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
 	do {
@@ -1386,34 +1410,16 @@
 
 		pc = sf.callers_pc;
 		ufp = (unsigned long)sf.fp;
-		callchain_store(entry, pc);
+		perf_callchain_store(entry, pc);
 	} while (entry->nr < PERF_MAX_STACK_DEPTH);
 }
 
-/* Like powerpc we can't get PMU interrupts within the PMU handler,
- * so no need for separate NMI and IRQ chains as on x86.
- */
-static DEFINE_PER_CPU(struct perf_callchain_entry, callchain);
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
-	struct perf_callchain_entry *entry = &__get_cpu_var(callchain);
-
-	entry->nr = 0;
-	if (!user_mode(regs)) {
-		stack_trace_flush();
-		perf_callchain_kernel(regs, entry);
-		if (current->mm)
-			regs = task_pt_regs(current);
-		else
-			regs = NULL;
-	}
-	if (regs) {
-		flushw_user();
-		if (test_thread_flag(TIF_32BIT))
-			perf_callchain_user_32(regs, entry);
-		else
-			perf_callchain_user_64(regs, entry);
-	}
-	return entry;
+	flushw_user();
+	if (test_thread_flag(TIF_32BIT))
+		perf_callchain_user_32(entry, regs);
+	else
+		perf_callchain_user_64(entry, regs);
 }
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index f043451..4c25727 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -785,8 +785,7 @@
 	return -1;
 }
 
-static unsigned long long nid_range(unsigned long long start,
-				    unsigned long long end, int *nid)
+u64 memblock_nid_range(u64 start, u64 end, int *nid)
 {
 	*nid = find_node(start);
 	start += PAGE_SIZE;
@@ -804,8 +803,7 @@
 	return start;
 }
 #else
-static unsigned long long nid_range(unsigned long long start,
-				    unsigned long long end, int *nid)
+u64 memblock_nid_range(u64 start, u64 end, int *nid)
 {
 	*nid = 0;
 	return end;
@@ -822,8 +820,7 @@
 	struct pglist_data *p;
 
 #ifdef CONFIG_NEED_MULTIPLE_NODES
-	paddr = memblock_alloc_nid(sizeof(struct pglist_data),
-			      SMP_CACHE_BYTES, nid, nid_range);
+	paddr = memblock_alloc_try_nid(sizeof(struct pglist_data), SMP_CACHE_BYTES, nid);
 	if (!paddr) {
 		prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid);
 		prom_halt();
@@ -843,8 +840,7 @@
 	if (p->node_spanned_pages) {
 		num_pages = bootmem_bootmap_pages(p->node_spanned_pages);
 
-		paddr = memblock_alloc_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid,
-				      nid_range);
+		paddr = memblock_alloc_try_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid);
 		if (!paddr) {
 			prom_printf("Cannot allocate bootmap for nid[%d]\n",
 				  nid);
@@ -972,19 +968,19 @@
 
 static void __init add_node_ranges(void)
 {
-	int i;
+	struct memblock_region *reg;
 
-	for (i = 0; i < memblock.memory.cnt; i++) {
-		unsigned long size = memblock_size_bytes(&memblock.memory, i);
+	for_each_memblock(memory, reg) {
+		unsigned long size = reg->size;
 		unsigned long start, end;
 
-		start = memblock.memory.region[i].base;
+		start = reg->base;
 		end = start + size;
 		while (start < end) {
 			unsigned long this_end;
 			int nid;
 
-			this_end = nid_range(start, end, &nid);
+			this_end = memblock_nid_range(start, end, &nid);
 
 			numadbg("Adding active range nid[%d] "
 				"start[%lx] end[%lx]\n",
@@ -1281,7 +1277,7 @@
 {
 	unsigned long top_of_ram = memblock_end_of_DRAM();
 	unsigned long total_ram = memblock_phys_mem_size();
-	unsigned int i;
+	struct memblock_region *reg;
 
 	numadbg("bootmem_init_nonnuma()\n");
 
@@ -1292,15 +1288,14 @@
 
 	init_node_masks_nonnuma();
 
-	for (i = 0; i < memblock.memory.cnt; i++) {
-		unsigned long size = memblock_size_bytes(&memblock.memory, i);
+	for_each_memblock(memory, reg) {
 		unsigned long start_pfn, end_pfn;
 
-		if (!size)
+		if (!reg->size)
 			continue;
 
-		start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
-		end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+		start_pfn = memblock_region_memory_base_pfn(reg);
+		end_pfn = memblock_region_memory_end_pfn(reg);
 		add_active_range(0, start_pfn, end_pfn);
 	}
 
@@ -1318,7 +1313,7 @@
 		unsigned long this_end;
 		int n;
 
-		this_end = nid_range(start, end, &n);
+		this_end = memblock_nid_range(start, end, &n);
 		if (n == nid) {
 			numadbg("      MATCH reserving range [%lx:%lx]\n",
 				start, this_end);
@@ -1334,17 +1329,12 @@
 
 static void __init trim_reserved_in_node(int nid)
 {
-	int i;
+	struct memblock_region *reg;
 
 	numadbg("  trim_reserved_in_node(%d)\n", nid);
 
-	for (i = 0; i < memblock.reserved.cnt; i++) {
-		unsigned long start = memblock.reserved.region[i].base;
-		unsigned long size = memblock_size_bytes(&memblock.reserved, i);
-		unsigned long end = start + size;
-
-		reserve_range_in_node(nid, start, end);
-	}
+	for_each_memblock(reserved, reg)
+		reserve_range_in_node(nid, reg->base, reg->base + reg->size);
 }
 
 static void __init bootmem_init_one_node(int nid)
diff --git a/arch/sparc/prom/p1275.c b/arch/sparc/prom/p1275.c
index fa6e4e2..d9850c2 100644
--- a/arch/sparc/prom/p1275.c
+++ b/arch/sparc/prom/p1275.c
@@ -39,7 +39,7 @@
 	unsigned long flags;
 
 	raw_local_save_flags(flags);
-	raw_local_irq_restore(PIL_NMI);
+	raw_local_irq_restore((unsigned long)PIL_NMI);
 	raw_spin_lock(&prom_entry_lock);
 
 	prom_world(1);
diff --git a/arch/tile/include/asm/bitops.h b/arch/tile/include/asm/bitops.h
index 6832b4b..6d4f0ff 100644
--- a/arch/tile/include/asm/bitops.h
+++ b/arch/tile/include/asm/bitops.h
@@ -120,6 +120,7 @@
 
 #include <asm-generic/bitops/const_hweight.h>
 #include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/ext2-non-atomic.h>
 #include <asm-generic/bitops/minix.h>
diff --git a/arch/tile/include/asm/irqflags.h b/arch/tile/include/asm/irqflags.h
index 45cf67c..a11d483 100644
--- a/arch/tile/include/asm/irqflags.h
+++ b/arch/tile/include/asm/irqflags.h
@@ -103,55 +103,57 @@
 #define INITIAL_INTERRUPTS_ENABLED INT_MASK(INT_MEM_ERROR)
 
 /* Disable interrupts. */
-#define raw_local_irq_disable() \
+#define arch_local_irq_disable() \
 	interrupt_mask_set_mask(LINUX_MASKABLE_INTERRUPTS)
 
 /* Disable all interrupts, including NMIs. */
-#define raw_local_irq_disable_all() \
+#define arch_local_irq_disable_all() \
 	interrupt_mask_set_mask(-1UL)
 
 /* Re-enable all maskable interrupts. */
-#define raw_local_irq_enable() \
+#define arch_local_irq_enable() \
 	interrupt_mask_reset_mask(__get_cpu_var(interrupts_enabled_mask))
 
 /* Disable or enable interrupts based on flag argument. */
-#define raw_local_irq_restore(disabled) do { \
+#define arch_local_irq_restore(disabled) do { \
 	if (disabled) \
-		raw_local_irq_disable(); \
+		arch_local_irq_disable(); \
 	else \
-		raw_local_irq_enable(); \
+		arch_local_irq_enable(); \
 } while (0)
 
 /* Return true if "flags" argument means interrupts are disabled. */
-#define raw_irqs_disabled_flags(flags) ((flags) != 0)
+#define arch_irqs_disabled_flags(flags) ((flags) != 0)
 
 /* Return true if interrupts are currently disabled. */
-#define raw_irqs_disabled() interrupt_mask_check(INT_MEM_ERROR)
+#define arch_irqs_disabled() interrupt_mask_check(INT_MEM_ERROR)
 
 /* Save whether interrupts are currently disabled. */
-#define raw_local_save_flags(flags) ((flags) = raw_irqs_disabled())
+#define arch_local_save_flags() arch_irqs_disabled()
 
 /* Save whether interrupts are currently disabled, then disable them. */
-#define raw_local_irq_save(flags) \
-	do { raw_local_save_flags(flags); raw_local_irq_disable(); } while (0)
+#define arch_local_irq_save() ({ \
+	unsigned long __flags = arch_local_save_flags(); \
+	arch_local_irq_disable(); \
+	__flags; })
 
 /* Prevent the given interrupt from being enabled next time we enable irqs. */
-#define raw_local_irq_mask(interrupt) \
+#define arch_local_irq_mask(interrupt) \
 	(__get_cpu_var(interrupts_enabled_mask) &= ~INT_MASK(interrupt))
 
 /* Prevent the given interrupt from being enabled immediately. */
-#define raw_local_irq_mask_now(interrupt) do { \
-	raw_local_irq_mask(interrupt); \
+#define arch_local_irq_mask_now(interrupt) do { \
+	arch_local_irq_mask(interrupt); \
 	interrupt_mask_set(interrupt); \
 } while (0)
 
 /* Allow the given interrupt to be enabled next time we enable irqs. */
-#define raw_local_irq_unmask(interrupt) \
+#define arch_local_irq_unmask(interrupt) \
 	(__get_cpu_var(interrupts_enabled_mask) |= INT_MASK(interrupt))
 
 /* Allow the given interrupt to be enabled immediately, if !irqs_disabled. */
-#define raw_local_irq_unmask_now(interrupt) do { \
-	raw_local_irq_unmask(interrupt); \
+#define arch_local_irq_unmask_now(interrupt) do { \
+	arch_local_irq_unmask(interrupt); \
 	if (!irqs_disabled()) \
 		interrupt_mask_reset(interrupt); \
 } while (0)
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c
index 584b965..1e54a78 100644
--- a/arch/tile/kernel/hardwall.c
+++ b/arch/tile/kernel/hardwall.c
@@ -774,6 +774,7 @@
 #endif
 	.flush          = hardwall_flush,
 	.release        = hardwall_release,
+	.llseek		= noop_llseek,
 };
 
 static struct cdev hardwall_dev;
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index 84f296c..8f58bdf 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -1506,13 +1506,6 @@
 	}
 	STD_ENDPROC(handle_ill)
 
-	.pushsection .rodata, "a"
-	.align  8
-bpt_code:
-	bpt
-	ENDPROC(bpt_code)
-	.popsection
-
 /* Various stub interrupt handlers and syscall handlers */
 
 STD_ENTRY_LOCAL(_kernel_double_fault)
diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c
index 596c600..9a27d56 100644
--- a/arch/tile/kernel/irq.c
+++ b/arch/tile/kernel/irq.c
@@ -208,7 +208,7 @@
 }
 
 static struct irq_chip tile_irq_chip = {
-	.typename = "tile_irq_chip",
+	.name = "tile_irq_chip",
 	.ack = tile_irq_chip_ack,
 	.eoi = tile_irq_chip_eoi,
 	.mask = tile_irq_chip_mask,
@@ -288,7 +288,7 @@
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", irq_desc[i].chip->typename);
+		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action = action->next; action; action = action->next)
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index cfcac1f..2d0266d 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -42,7 +42,7 @@
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/reboot.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
@@ -50,6 +50,7 @@
 
 MODULE_LICENSE("GPL");
 
+static DEFINE_MUTEX(harddog_mutex);
 static DEFINE_SPINLOCK(lock);
 static int timer_alive;
 static int harddog_in_fd = -1;
@@ -66,7 +67,7 @@
 	int err = -EBUSY;
 	char *sock = NULL;
 
-	lock_kernel();
+	mutex_lock(&harddog_mutex);
 	spin_lock(&lock);
 	if(timer_alive)
 		goto err;
@@ -83,11 +84,11 @@
 
 	timer_alive = 1;
 	spin_unlock(&lock);
-	unlock_kernel();
+	mutex_unlock(&harddog_mutex);
 	return nonseekable_open(inode, file);
 err:
 	spin_unlock(&lock);
-	unlock_kernel();
+	mutex_unlock(&harddog_mutex);
 	return err;
 }
 
@@ -153,9 +154,9 @@
 {
 	long ret;
 
-	lock_kernel();
+	mutex_lock(&harddog_mutex);
 	ret = harddog_ioctl_unlocked(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&harddog_mutex);
 
 	return ret;
 }
@@ -166,6 +167,7 @@
 	.unlocked_ioctl	= harddog_ioctl,
 	.open		= harddog_open,
 	.release	= harddog_release,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice harddog_miscdev = {
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 0c46e39..f9f6a4e 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -8,7 +8,7 @@
 #include "linux/slab.h"
 #include "linux/sound.h"
 #include "linux/soundcard.h"
-#include "linux/smp_lock.h"
+#include "linux/mutex.h"
 #include "asm/uaccess.h"
 #include "init.h"
 #include "os.h"
@@ -40,6 +40,11 @@
 "    This is used to specify the host mixer device to the hostaudio driver.\n"\
 "    The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
 
+module_param(dsp, charp, 0644);
+MODULE_PARM_DESC(dsp, DSP_HELP);
+module_param(mixer, charp, 0644);
+MODULE_PARM_DESC(mixer, MIXER_HELP);
+
 #ifndef MODULE
 static int set_dsp(char *name, int *add)
 {
@@ -56,17 +61,10 @@
 }
 
 __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
-
-#else /*MODULE*/
-
-module_param(dsp, charp, 0644);
-MODULE_PARM_DESC(dsp, DSP_HELP);
-
-module_param(mixer, charp, 0644);
-MODULE_PARM_DESC(mixer, MIXER_HELP);
-
 #endif
 
+static DEFINE_MUTEX(hostaudio_mutex);
+
 /* /dev/dsp file operations */
 
 static ssize_t hostaudio_read(struct file *file, char __user *buffer,
@@ -202,9 +200,9 @@
 		w = 1;
 
 	kparam_block_sysfs_write(dsp);
-	lock_kernel();
+	mutex_lock(&hostaudio_mutex);
 	ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
-	unlock_kernel();
+	mutex_unlock(&hostaudio_mutex);
 	kparam_unblock_sysfs_write(dsp);
 
 	if (ret < 0) {
@@ -263,9 +261,9 @@
 		w = 1;
 
 	kparam_block_sysfs_write(mixer);
-	lock_kernel();
+	mutex_lock(&hostaudio_mutex);
 	ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
-	unlock_kernel();
+	mutex_unlock(&hostaudio_mutex);
 	kparam_unblock_sysfs_write(mixer);
 
 	if (ret < 0) {
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index ebc6807..975613b 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -843,6 +843,7 @@
 static const struct file_operations mconsole_proc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= mconsole_proc_write,
+	.llseek		= noop_llseek,
 };
 
 static int create_proc_mconsole(void)
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 7158393..8501e7d 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -93,6 +93,7 @@
 	.mmap		= mmapper_mmap,
 	.open		= mmapper_open,
 	.release	= mmapper_release,
+	.llseek		= default_llseek,
 };
 
 /*
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 2ab233b..47d0c37 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -255,18 +255,6 @@
 	netif_wake_queue(dev);
 }
 
-static int uml_net_set_mac(struct net_device *dev, void *addr)
-{
-	struct uml_net_private *lp = netdev_priv(dev);
-	struct sockaddr *hwaddr = addr;
-
-	spin_lock_irq(&lp->lock);
-	eth_mac_addr(dev, hwaddr->sa_data);
-	spin_unlock_irq(&lp->lock);
-
-	return 0;
-}
-
 static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
 {
 	dev->mtu = new_mtu;
@@ -373,7 +361,7 @@
 	.ndo_start_xmit 	= uml_net_start_xmit,
 	.ndo_set_multicast_list = uml_net_set_multicast_list,
 	.ndo_tx_timeout 	= uml_net_tx_timeout,
-	.ndo_set_mac_address	= uml_net_set_mac,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu 	= uml_net_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 };
@@ -472,7 +460,8 @@
 	    ((*transport->user->init)(&lp->user, dev) != 0))
 		goto out_unregister;
 
-	eth_mac_addr(dev, device->mac);
+	/* don't use eth_mac_addr, it will not work here */
+	memcpy(dev->dev_addr, device->mac, ETH_ALEN);
 	dev->mtu = transport->user->mtu;
 	dev->netdev_ops = &uml_netdev_ops;
 	dev->ethtool_ops = &uml_net_ethtool_ops;
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 4949044..981085a 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -100,6 +100,7 @@
 	.owner		= THIS_MODULE,
 	.open		= rng_dev_open,
 	.read		= rng_dev_read,
+	.llseek		= noop_llseek,
 };
 
 /* rng_init shouldn't be called more than once at boot time */
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 1bcd208..ba4a98b 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -33,7 +33,7 @@
 #include "linux/mm.h"
 #include "linux/slab.h"
 #include "linux/vmalloc.h"
-#include "linux/smp_lock.h"
+#include "linux/mutex.h"
 #include "linux/blkpg.h"
 #include "linux/genhd.h"
 #include "linux/spinlock.h"
@@ -100,6 +100,7 @@
 #define DRIVER_NAME "uml-blkdev"
 
 static DEFINE_MUTEX(ubd_lock);
+static DEFINE_MUTEX(ubd_mutex); /* replaces BKL, might not be needed */
 
 static int ubd_open(struct block_device *bdev, fmode_t mode);
 static int ubd_release(struct gendisk *disk, fmode_t mode);
@@ -163,6 +164,7 @@
 	struct scatterlist sg[MAX_SG];
 	struct request *request;
 	int start_sg, end_sg;
+	sector_t rq_pos;
 };
 
 #define DEFAULT_COW { \
@@ -187,6 +189,7 @@
 	.request =		NULL, \
 	.start_sg =		0, \
 	.end_sg =		0, \
+	.rq_pos =		0, \
 }
 
 /* Protected by ubd_lock */
@@ -1099,7 +1102,7 @@
 	struct ubd *ubd_dev = disk->private_data;
 	int err = 0;
 
-	lock_kernel();
+	mutex_lock(&ubd_mutex);
 	if(ubd_dev->count == 0){
 		err = ubd_open_dev(ubd_dev);
 		if(err){
@@ -1118,7 +1121,7 @@
 	        err = -EROFS;
 	}*/
 out:
-	unlock_kernel();
+	mutex_unlock(&ubd_mutex);
 	return err;
 }
 
@@ -1126,10 +1129,10 @@
 {
 	struct ubd *ubd_dev = disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&ubd_mutex);
 	if(--ubd_dev->count == 0)
 		ubd_close_dev(ubd_dev);
-	unlock_kernel();
+	mutex_unlock(&ubd_mutex);
 	return 0;
 }
 
@@ -1228,7 +1231,6 @@
 {
 	struct io_thread_req *io_req;
 	struct request *req;
-	sector_t sector;
 	int n;
 
 	while(1){
@@ -1239,12 +1241,12 @@
 				return;
 
 			dev->request = req;
+			dev->rq_pos = blk_rq_pos(req);
 			dev->start_sg = 0;
 			dev->end_sg = blk_rq_map_sg(q, req, dev->sg);
 		}
 
 		req = dev->request;
-		sector = blk_rq_pos(req);
 		while(dev->start_sg < dev->end_sg){
 			struct scatterlist *sg = &dev->sg[dev->start_sg];
 
@@ -1256,10 +1258,9 @@
 				return;
 			}
 			prepare_request(req, io_req,
-					(unsigned long long)sector << 9,
+					(unsigned long long)dev->rq_pos << 9,
 					sg->offset, sg->length, sg_page(sg));
 
-			sector += sg->length >> 9;
 			n = os_write_file(thread_fd, &io_req,
 					  sizeof(struct io_thread_req *));
 			if(n != sizeof(struct io_thread_req *)){
@@ -1272,6 +1273,7 @@
 				return;
 			}
 
+			dev->rq_pos += sg->length >> 9;
 			dev->start_sg++;
 		}
 		dev->end_sg = 0;
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 49b5e1e..340268b 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -78,13 +78,11 @@
 	long error;
 	char *filename;
 
-	lock_kernel();
 	filename = getname(file);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename)) goto out;
 	error = execve1(filename, argv, env);
 	putname(filename);
  out:
-	unlock_kernel();
 	return error;
 }
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index a3f0b04..a746e30 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -46,7 +46,7 @@
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", irq_desc[i].chip->typename);
+		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -369,7 +369,7 @@
 
 /* This is used for everything else than the timer. */
 static struct irq_chip normal_irq_type = {
-	.typename = "SIGIO",
+	.name = "SIGIO",
 	.release = free_irq_by_irq_and_dev,
 	.disable = dummy,
 	.enable = dummy,
@@ -378,7 +378,7 @@
 };
 
 static struct irq_chip SIGVTALRM_irq_type = {
-	.typename = "SIGVTALRM",
+	.name = "SIGVTALRM",
 	.release = free_irq_by_irq_and_dev,
 	.shutdown = dummy, /* never called */
 	.disable = dummy,
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index cea0cd9..dfabfef 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -25,14 +25,17 @@
 	select HAVE_IDE
 	select HAVE_OPROFILE
 	select HAVE_PERF_EVENTS if (!M386 && !M486)
+	select HAVE_IRQ_WORK
 	select HAVE_IOREMAP_PROT
 	select HAVE_KPROBES
+	select HAVE_MEMBLOCK
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARCH_WANT_FRAME_POINTERS
 	select HAVE_DMA_ATTRS
 	select HAVE_KRETPROBES
 	select HAVE_OPTPROBES
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
@@ -59,6 +62,12 @@
 	select ANON_INODES
 	select HAVE_ARCH_KMEMCHECK
 	select HAVE_USER_RETURN_NOTIFIER
+	select HAVE_ARCH_JUMP_LABEL
+	select HAVE_TEXT_POKE_SMP
+	select HAVE_GENERIC_HARDIRQS
+	select HAVE_SPARSE_IRQ
+	select GENERIC_IRQ_PROBE
+	select GENERIC_PENDING_IRQ if SMP
 
 config INSTRUCTION_DECODER
 	def_bool (KPROBES || PERF_EVENTS)
@@ -193,27 +202,10 @@
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
 	def_bool y
 
-config HAVE_EARLY_RES
-	def_bool y
-
 config HAVE_INTEL_TXT
 	def_bool y
 	depends on EXPERIMENTAL && DMAR && ACPI
 
-# Use the generic interrupt handling code in kernel/irq/:
-config GENERIC_HARDIRQS
-	def_bool y
-
-config GENERIC_HARDIRQS_NO__DO_IRQ
-       def_bool y
-
-config GENERIC_IRQ_PROBE
-	def_bool y
-
-config GENERIC_PENDING_IRQ
-	def_bool y
-	depends on GENERIC_HARDIRQS && SMP
-
 config USE_GENERIC_SMP_HELPERS
 	def_bool y
 	depends on SMP
@@ -296,23 +288,6 @@
 
 	  If you don't know what to do here, say N.
 
-config SPARSE_IRQ
-	bool "Support sparse irq numbering"
-	depends on PCI_MSI || HT_IRQ
-	---help---
-	  This enables support for sparse irqs. This is useful for distro
-	  kernels that want to define a high CONFIG_NR_CPUS value but still
-	  want to have low kernel memory footprint on smaller machines.
-
-	  ( Sparse IRQs can also be beneficial on NUMA boxes, as they spread
-	    out the irq_desc[] array in a more NUMA-friendly way. )
-
-	  If you don't know what to do here, say N.
-
-config NUMA_IRQ_DESC
-	def_bool y
-	depends on SPARSE_IRQ && NUMA
-
 config X86_MPPARSE
 	bool "Enable MPS table" if ACPI
 	default y
@@ -517,25 +492,6 @@
 
 source "arch/x86/xen/Kconfig"
 
-config VMI
-	bool "VMI Guest support (DEPRECATED)"
-	select PARAVIRT
-	depends on X86_32
-	---help---
-	  VMI provides a paravirtualized interface to the VMware ESX server
-	  (it could be used by other hypervisors in theory too, but is not
-	  at the moment), by linking the kernel to a GPL-ed ROM module
-	  provided by the hypervisor.
-
-	  As of September 2009, VMware has started a phased retirement
-	  of this feature from VMware's products. Please see
-	  feature-removal-schedule.txt for details.  If you are
-	  planning to enable this option, please note that you cannot
-	  live migrate a VMI enabled VM to a future VMware product,
-	  which doesn't support VMI. So if you expect your kernel to
-	  seamlessly migrate to newer VMware products, keep this
-	  disabled.
-
 config KVM_CLOCK
 	bool "KVM paravirtualized clock"
 	select PARAVIRT
@@ -590,16 +546,7 @@
 	  a paravirt_op is missing when it is called.
 
 config NO_BOOTMEM
-	default y
-	bool "Disable Bootmem code"
-	---help---
-	  Use early_res directly instead of bootmem before slab is ready.
-		- allocator (buddy) [generic]
-		- early allocator (bootmem) [generic]
-		- very early allocator (reserve_early*()) [x86]
-		- very very early allocator (early brk model) [x86]
-	  So reduce one layer between early allocator to final allocator
-
+	def_bool y
 
 config MEMTEST
 	bool "Memtest"
@@ -670,7 +617,7 @@
 	bool "GART IOMMU support" if EMBEDDED
 	default y
 	select SWIOTLB
-	depends on X86_64 && PCI && K8_NB
+	depends on X86_64 && PCI && AMD_NB
 	---help---
 	  Support for full DMA access of devices with 32bit memory access only
 	  on systems with more than 3GB. This is usually needed for USB,
@@ -795,6 +742,17 @@
 	  making when dealing with multi-core CPU chips at a cost of slightly
 	  increased overhead in some places. If unsure say N here.
 
+config IRQ_TIME_ACCOUNTING
+	bool "Fine granularity task level IRQ time accounting"
+	default n
+	---help---
+	  Select this option to enable fine granularity task irq time
+	  accounting. This is done by reading a timestamp on each
+	  transitions between softirq and hardirq state, so there can be a
+	  small performance impact.
+
+	  If in doubt, say N here.
+
 source "kernel/Kconfig.preempt"
 
 config X86_UP_APIC
@@ -1148,6 +1106,9 @@
 config ARCH_PHYS_ADDR_T_64BIT
 	def_bool X86_64 || X86_PAE
 
+config ARCH_DMA_ADDR_T_64BIT
+	def_bool X86_64 || HIGHMEM64G
+
 config DIRECT_GBPAGES
 	bool "Enable 1GB pages for kernel pagetables" if EMBEDDED
 	default y
@@ -1326,25 +1287,34 @@
 	  Set whether the default state of memory_corruption_check is
 	  on or off.
 
-config X86_RESERVE_LOW_64K
-	bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen"
-	default y
+config X86_RESERVE_LOW
+	int "Amount of low memory, in kilobytes, to reserve for the BIOS"
+	default 64
+	range 4 640
 	---help---
-	  Reserve the first 64K of physical RAM on BIOSes that are known
-	  to potentially corrupt that memory range. A numbers of BIOSes are
-	  known to utilize this area during suspend/resume, so it must not
-	  be used by the kernel.
+	  Specify the amount of low memory to reserve for the BIOS.
 
-	  Set this to N if you are absolutely sure that you trust the BIOS
-	  to get all its memory reservations and usages right.
+	  The first page contains BIOS data structures that the kernel
+	  must not use, so that page must always be reserved.
 
-	  If you have doubts about the BIOS (e.g. suspend/resume does not
-	  work or there's kernel crashes after certain hardware hotplug
-	  events) and it's not AMI or Phoenix, then you might want to enable
-	  X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical
-	  corruption patterns.
+	  By default we reserve the first 64K of physical RAM, as a
+	  number of BIOSes are known to corrupt that memory range
+	  during events such as suspend/resume or monitor cable
+	  insertion, so it must not be used by the kernel.
 
-	  Say Y if unsure.
+	  You can set this to 4 if you are absolutely sure that you
+	  trust the BIOS to get all its memory reservations and usages
+	  right.  If you know your BIOS have problems beyond the
+	  default 64K area, you can set this to 640 to avoid using the
+	  entire low memory range.
+
+	  If you have doubts about the BIOS (e.g. suspend/resume does
+	  not work or there's kernel crashes after certain hardware
+	  hotplug events) then you might want to enable
+	  X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check
+	  typical corruption patterns.
+
+	  Leave this to the default value of 64 if you are unsure.
 
 config MATH_EMULATION
 	bool
@@ -1900,7 +1870,7 @@
 	bool "Direct"
 
 config PCI_GOOLPC
-	bool "OLPC"
+	bool "OLPC XO-1"
 	depends on OLPC
 
 config PCI_GOANY
@@ -2061,14 +2031,21 @@
 config OLPC
 	bool "One Laptop Per Child support"
 	select GPIOLIB
+	select OLPC_OPENFIRMWARE
 	---help---
 	  Add support for detecting the unique features of the OLPC
 	  XO hardware.
 
+config OLPC_XO1
+	tristate "OLPC XO-1 support"
+	depends on OLPC && PCI
+	---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 y if OLPC
+	default n
 	help
 	  This option adds support for the implementation of Open Firmware
 	  that is used on the OLPC XO-1 Children's Machine.
@@ -2076,7 +2053,7 @@
 
 endif # X86_32
 
-config K8_NB
+config AMD_NB
 	def_bool y
 	depends on CPU_SUP_AMD && PCI
 
@@ -2125,6 +2102,10 @@
 	def_bool y
 	depends on X86_32
 
+config HAVE_TEXT_POKE_SMP
+	bool
+	select STOP_MACHINE if SMP
+
 source "net/Kconfig"
 
 source "drivers/Kconfig"
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 7508508..b59ee76 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -43,6 +43,10 @@
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash.
 
+config EARLY_PRINTK_MRST
+	bool "Early printk for MRST platform support"
+	depends on EARLY_PRINTK && X86_MRST
+
 config EARLY_PRINTK_DBGP
 	bool "Early printk via EHCI debug port"
 	depends on EARLY_PRINTK && PCI
@@ -121,16 +125,6 @@
 	  and the software setup of this feature.
 	  If in doubt, say "N"
 
-config 4KSTACKS
-	bool "Use 4Kb for kernel stacks instead of 8Kb"
-	depends on X86_32
-	---help---
-	  If you say Y here the kernel will use a 4Kb stacksize for the
-	  kernel stack attached to each process/thread. This facilitates
-	  running more threads on a system and also reduces the pressure
-	  on the VM subsystem for higher order allocations. This option
-	  will also use IRQ stacks to compensate for the reduced stackspace.
-
 config DOUBLEFAULT
 	default y
 	bool "Enable doublefault exception handler" if EMBEDDED
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index e8c8881..b02e509 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -96,8 +96,12 @@
 # is .cfi_signal_frame supported too?
 cfi-sigframe := $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1)
 cfi-sections := $(call as-instr,.cfi_sections .debug_frame,-DCONFIG_AS_CFI_SECTIONS=1)
-KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections)
-KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections)
+
+# does binutils support specific instructions?
+asinstr := $(call as-instr,fxsaveq (%rax),-DCONFIG_AS_FXSAVEQ=1)
+
+KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr)
+KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr)
 
 LDFLAGS := -m elf_$(UTS_MACHINE)
 
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 8f7bef8..23f315c 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -229,18 +229,35 @@
 		ss[i] = c;
 	return s;
 }
-
+#ifdef CONFIG_X86_32
 void *memcpy(void *dest, const void *src, size_t n)
 {
-	int i;
-	const char *s = src;
-	char *d = dest;
+	int d0, d1, d2;
+	asm volatile(
+		"rep ; movsl\n\t"
+		"movl %4,%%ecx\n\t"
+		"rep ; movsb\n\t"
+		: "=&c" (d0), "=&D" (d1), "=&S" (d2)
+		: "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src)
+		: "memory");
 
-	for (i = 0; i < n; i++)
-		d[i] = s[i];
 	return dest;
 }
+#else
+void *memcpy(void *dest, const void *src, size_t n)
+{
+	long d0, d1, d2;
+	asm volatile(
+		"rep ; movsq\n\t"
+		"movq %4,%%rcx\n\t"
+		"rep ; movsb\n\t"
+		: "=&c" (d0), "=&D" (d1), "=&S" (d2)
+		: "0" (n >> 3), "g" (n & 7), "1" (dest), "2" (src)
+		: "memory");
 
+	return dest;
+}
+#endif
 
 static void error(char *x)
 {
diff --git a/arch/x86/boot/early_serial_console.c b/arch/x86/boot/early_serial_console.c
index 030f4b9..5df2869 100644
--- a/arch/x86/boot/early_serial_console.c
+++ b/arch/x86/boot/early_serial_console.c
@@ -58,7 +58,19 @@
 		if (arg[pos] == ',')
 			pos++;
 
-		if (!strncmp(arg, "ttyS", 4)) {
+		/*
+		 * make sure we have
+		 *	"serial,0x3f8,115200"
+		 *	"serial,ttyS0,115200"
+		 *	"ttyS0,115200"
+		 */
+		if (pos == 7 && !strncmp(arg + pos, "0x", 2)) {
+			port = simple_strtoull(arg + pos, &e, 16);
+			if (port == 0 || arg + pos == e)
+				port = DEFAULT_SERIAL_PORT;
+			else
+				pos = e - arg;
+		} else if (!strncmp(arg + pos, "ttyS", 4)) {
 			static const int bases[] = { 0x3f8, 0x2f8 };
 			int idx = 0;
 
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 0350311..2d93bdb 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -34,7 +34,7 @@
 #include <asm/ia32.h>
 
 #undef WARN_OLD
-#undef CORE_DUMP /* probably broken */
+#undef CORE_DUMP /* definitely broken */
 
 static int load_aout_binary(struct linux_binprm *, struct pt_regs *regs);
 static int load_aout_library(struct file *);
@@ -131,21 +131,15 @@
  * macros to write out all the necessary info.
  */
 
-static int dump_write(struct file *file, const void *addr, int nr)
-{
-	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
+#include <linux/coredump.h>
 
 #define DUMP_WRITE(addr, nr)			     \
 	if (!dump_write(file, (void *)(addr), (nr))) \
 		goto end_coredump;
 
-#define DUMP_SEEK(offset)						\
-	if (file->f_op->llseek) {					\
-		if (file->f_op->llseek(file, (offset), 0) != (offset))	\
-			goto end_coredump;				\
-	} else								\
-		file->f_pos = (offset)
+#define DUMP_SEEK(offset)		\
+	if (!dump_seek(file, offset))	\
+		goto end_coredump;
 
 #define START_DATA()	(u.u_tsize << PAGE_SHIFT)
 #define START_STACK(u)	(u.start_stack)
@@ -217,12 +211,6 @@
 		dump_size = dump.u_ssize << PAGE_SHIFT;
 		DUMP_WRITE(dump_start, dump_size);
 	}
-	/*
-	 * Finally dump the task struct.  Not be used by gdb, but
-	 * could be useful
-	 */
-	set_fs(KERNEL_DS);
-	DUMP_WRITE(current, sizeof(*current));
 end_coredump:
 	set_fs(fs);
 	return has_dumped;
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index bc6abb7..76561d2 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -4,6 +4,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <linux/stringify.h>
+#include <linux/jump_label.h>
 #include <asm/asm.h>
 
 /*
@@ -160,6 +161,8 @@
 #define __parainstructions_end	NULL
 #endif
 
+extern void *text_poke_early(void *addr, const void *opcode, size_t len);
+
 /*
  * Clear and restore the kernel write-protection flag on the local CPU.
  * Allows the kernel to edit read-only pages.
@@ -180,4 +183,12 @@
 extern void *text_poke(void *addr, const void *opcode, size_t len);
 extern void *text_poke_smp(void *addr, const void *opcode, size_t len);
 
+#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
+#define IDEAL_NOP_SIZE_5 5
+extern unsigned char ideal_nop5[IDEAL_NOP_SIZE_5];
+extern void arch_init_ideal_nop5(void);
+#else
+static inline void arch_init_ideal_nop5(void) {}
+#endif
+
 #endif /* _ASM_X86_ALTERNATIVE_H */
diff --git a/arch/x86/include/asm/amd_iommu.h b/arch/x86/include/asm/amd_iommu.h
index 5af2982..a6863a2 100644
--- a/arch/x86/include/asm/amd_iommu.h
+++ b/arch/x86/include/asm/amd_iommu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
@@ -24,11 +24,11 @@
 
 #ifdef CONFIG_AMD_IOMMU
 
-extern void amd_iommu_detect(void);
+extern int amd_iommu_detect(void);
 
 #else
 
-static inline void amd_iommu_detect(void) { }
+static inline int amd_iommu_detect(void) { return -ENODEV; }
 
 #endif
 
diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h
index d2544f1..916bc81 100644
--- a/arch/x86/include/asm/amd_iommu_proto.h
+++ b/arch/x86/include/asm/amd_iommu_proto.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2009-2010 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -38,4 +38,10 @@
 
 #endif /* !CONFIG_AMD_IOMMU_STATS */
 
+static inline bool is_rd890_iommu(struct pci_dev *pdev)
+{
+	return (pdev->vendor == PCI_VENDOR_ID_ATI) &&
+	       (pdev->device == PCI_DEVICE_ID_RD890_IOMMU);
+}
+
 #endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 7014e88..e3509fc 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
@@ -368,6 +368,9 @@
 	/* capabilities of that IOMMU read from ACPI */
 	u32 cap;
 
+	/* flags read from acpi table */
+	u8 acpi_flags;
+
 	/*
 	 * Capability pointer. There could be more than one IOMMU per PCI
 	 * device function if there are more than one AMD IOMMU capability
@@ -411,6 +414,24 @@
 
 	/* default dma_ops domain for that IOMMU */
 	struct dma_ops_domain *default_dom;
+
+	/*
+	 * We can't rely on the BIOS to restore all values on reinit, so we
+	 * need to stash them
+	 */
+
+	/* The iommu BAR */
+	u32 stored_addr_lo;
+	u32 stored_addr_hi;
+
+	/*
+	 * Each iommu has 6 l1s, each of which is documented as having 0x12
+	 * registers
+	 */
+	u32 stored_l1[6][0x12];
+
+	/* The l2 indirect registers */
+	u32 stored_l2[0x83];
 };
 
 /*
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h
new file mode 100644
index 0000000..c8517f8
--- /dev/null
+++ b/arch/x86/include/asm/amd_nb.h
@@ -0,0 +1,39 @@
+#ifndef _ASM_X86_AMD_NB_H
+#define _ASM_X86_AMD_NB_H
+
+#include <linux/pci.h>
+
+extern struct pci_device_id k8_nb_ids[];
+struct bootnode;
+
+extern int early_is_k8_nb(u32 value);
+extern int cache_k8_northbridges(void);
+extern void k8_flush_garts(void);
+extern int k8_get_nodes(struct bootnode *nodes);
+extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn);
+extern int k8_scan_nodes(void);
+
+struct k8_northbridge_info {
+	u16 num;
+	u8 gart_supported;
+	struct pci_dev **nb_misc;
+};
+extern struct k8_northbridge_info k8_northbridges;
+
+#ifdef CONFIG_AMD_NB
+
+static inline struct pci_dev *node_to_k8_nb_misc(int node)
+{
+	return (node < k8_northbridges.num) ? k8_northbridges.nb_misc[node] : NULL;
+}
+
+#else
+
+static inline struct pci_dev *node_to_k8_nb_misc(int node)
+{
+	return NULL;
+}
+#endif
+
+
+#endif /* _ASM_X86_AMD_NB_H */
diff --git a/arch/x86/include/asm/apb_timer.h b/arch/x86/include/asm/apb_timer.h
index a69b1ac..2fefa50 100644
--- a/arch/x86/include/asm/apb_timer.h
+++ b/arch/x86/include/asm/apb_timer.h
@@ -54,7 +54,6 @@
 extern unsigned long apbt_quick_calibrate(void);
 extern int arch_setup_apbt_irqs(int irq, int trigger, int mask, int cpu);
 extern void apbt_setup_secondary_clock(void);
-extern unsigned int boot_cpu_id;
 
 extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint);
 extern void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr);
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 1fa03e0..286de34 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -252,9 +252,7 @@
 }
 #endif
 
-extern u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask);
-extern u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask);
-
+extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask);
 
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 7fe3b30..a859ca4 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -131,6 +131,7 @@
 #define APIC_EILVTn(n)	(0x500 + 0x10 * n)
 #define		APIC_EILVT_NR_AMD_K8	1	/* # of extended interrupts */
 #define		APIC_EILVT_NR_AMD_10H	4
+#define		APIC_EILVT_NR_MAX	APIC_EILVT_NR_AMD_10H
 #define		APIC_EILVT_LVTOFF(x)	(((x) >> 4) & 0xF)
 #define		APIC_EILVT_MSG_FIX	0x0
 #define		APIC_EILVT_MSG_SMI	0x2
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index 545776e..903683b0 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -309,7 +309,7 @@
 static __always_inline int constant_test_bit(unsigned int nr, const volatile unsigned long *addr)
 {
 	return ((1UL << (nr % BITS_PER_LONG)) &
-		(((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
+		(addr[nr / BITS_PER_LONG])) != 0;
 }
 
 static inline int variable_test_bit(int nr, volatile const unsigned long *addr)
@@ -440,6 +440,8 @@
 
 #ifdef __KERNEL__
 
+#include <asm-generic/bitops/find.h>
+
 #include <asm-generic/bitops/sched.h>
 
 #define ARCH_HAS_FAST_MULTIPLIER 1
diff --git a/arch/x86/include/asm/calgary.h b/arch/x86/include/asm/calgary.h
index 0918654..0d467b3 100644
--- a/arch/x86/include/asm/calgary.h
+++ b/arch/x86/include/asm/calgary.h
@@ -62,9 +62,9 @@
 extern int use_calgary;
 
 #ifdef CONFIG_CALGARY_IOMMU
-extern void detect_calgary(void);
+extern int detect_calgary(void);
 #else
-static inline void detect_calgary(void) { return; }
+static inline int detect_calgary(void) { return -ENODEV; }
 #endif
 
 #endif /* _ASM_X86_CALGARY_H */
diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h
index 0e63c9a..30af5a8 100644
--- a/arch/x86/include/asm/calling.h
+++ b/arch/x86/include/asm/calling.h
@@ -48,36 +48,38 @@
 
 
 /*
- * 64-bit system call stack frame layout defines and helpers,
- * for assembly code:
+ * 64-bit system call stack frame layout defines and helpers, for
+ * assembly code (note that the seemingly unnecessary parentheses
+ * are to prevent cpp from inserting spaces in expressions that get
+ * passed to macros):
  */
 
-#define R15		  0
-#define R14		  8
-#define R13		 16
-#define R12		 24
-#define RBP		 32
-#define RBX		 40
+#define R15		  (0)
+#define R14		  (8)
+#define R13		 (16)
+#define R12		 (24)
+#define RBP		 (32)
+#define RBX		 (40)
 
 /* arguments: interrupts/non tracing syscalls only save up to here: */
-#define R11		 48
-#define R10		 56
-#define R9		 64
-#define R8		 72
-#define RAX		 80
-#define RCX		 88
-#define RDX		 96
-#define RSI		104
-#define RDI		112
-#define ORIG_RAX	120       /* + error_code */
+#define R11		 (48)
+#define R10		 (56)
+#define R9		 (64)
+#define R8		 (72)
+#define RAX		 (80)
+#define RCX		 (88)
+#define RDX		 (96)
+#define RSI		(104)
+#define RDI		(112)
+#define ORIG_RAX	(120)       /* + error_code */
 /* end of arguments */
 
 /* cpu exception frame or undefined in case of fast syscall: */
-#define RIP		128
-#define CS		136
-#define EFLAGS		144
-#define RSP		152
-#define SS		160
+#define RIP		(128)
+#define CS		(136)
+#define EFLAGS		(144)
+#define RSP		(152)
+#define SS		(160)
 
 #define ARGOFFSET	R11
 #define SWFRAME		ORIG_RAX
@@ -111,7 +113,7 @@
 	.endif
 	.endm
 
-#define ARG_SKIP	9*8
+#define ARG_SKIP	(9*8)
 
 	.macro RESTORE_ARGS skiprax=0, addskip=0, skiprcx=0, skipr11=0, \
 			    skipr8910=0, skiprdx=0
@@ -169,7 +171,7 @@
 	.endif
 	.endm
 
-#define REST_SKIP	6*8
+#define REST_SKIP	(6*8)
 
 	.macro SAVE_REST
 	subq $REST_SKIP, %rsp
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index b185091..4fab24d 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -32,6 +32,5 @@
 
 DECLARE_PER_CPU(int, cpu_state);
 
-extern unsigned int boot_cpu_id;
 
 #endif /* _ASM_X86_CPU_H */
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index c6fbb7b..220e2ea 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -152,10 +152,14 @@
 #define X86_FEATURE_3DNOWPREFETCH (6*32+ 8) /* 3DNow prefetch instructions */
 #define X86_FEATURE_OSVW	(6*32+ 9) /* OS Visible Workaround */
 #define X86_FEATURE_IBS		(6*32+10) /* Instruction Based Sampling */
-#define X86_FEATURE_SSE5	(6*32+11) /* SSE-5 */
+#define X86_FEATURE_XOP		(6*32+11) /* extended AVX instructions */
 #define X86_FEATURE_SKINIT	(6*32+12) /* SKINIT/STGI instructions */
 #define X86_FEATURE_WDT		(6*32+13) /* Watchdog timer */
+#define X86_FEATURE_LWP		(6*32+15) /* Light Weight Profiling */
+#define X86_FEATURE_FMA4	(6*32+16) /* 4 operands MAC instructions */
 #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 */
 
 /*
  * Auxiliary flags: Linux defined - For features scattered in various
@@ -168,6 +172,7 @@
 #define X86_FEATURE_XSAVEOPT	(7*32+ 4) /* Optimized Xsave */
 #define X86_FEATURE_PLN		(7*32+ 5) /* Intel Power Limit Notification */
 #define X86_FEATURE_PTS		(7*32+ 6) /* Intel Package Thermal Status */
+#define X86_FEATURE_DTS		(7*32+ 7) /* Digital Thermal Sensor */
 
 /* Virtualization flags: Linux defined, word 8 */
 #define X86_FEATURE_TPR_SHADOW  (8*32+ 0) /* Intel TPR Shadow */
@@ -179,6 +184,13 @@
 #define X86_FEATURE_LBRV	(8*32+ 6) /* AMD LBR Virtualization support */
 #define X86_FEATURE_SVML	(8*32+ 7) /* "svm_lock" AMD SVM locking MSR */
 #define X86_FEATURE_NRIPS	(8*32+ 8) /* "nrip_save" AMD SVM next_rip save */
+#define X86_FEATURE_TSCRATEMSR  (8*32+ 9) /* "tsc_scale" AMD TSC scaling support */
+#define X86_FEATURE_VMCBCLEAN   (8*32+10) /* "vmcb_clean" AMD VMCB clean bits support */
+#define X86_FEATURE_FLUSHBYASID (8*32+11) /* AMD flush-by-ASID support */
+#define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */
+#define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */
+#define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */
+
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
 #define X86_FEATURE_FSGSBASE	(9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h
index 733f7e9..3260991 100644
--- a/arch/x86/include/asm/dwarf2.h
+++ b/arch/x86/include/asm/dwarf2.h
@@ -89,6 +89,16 @@
 	CFI_ADJUST_CFA_OFFSET -8
 	.endm
 
+	.macro pushfq_cfi
+	pushfq
+	CFI_ADJUST_CFA_OFFSET 8
+	.endm
+
+	.macro popfq_cfi
+	popfq
+	CFI_ADJUST_CFA_OFFSET -8
+	.endm
+
 	.macro movq_cfi reg offset=0
 	movq %\reg, \offset(%rsp)
 	CFI_REL_OFFSET \reg, \offset
@@ -109,6 +119,16 @@
 	CFI_ADJUST_CFA_OFFSET -4
 	.endm
 
+	.macro pushfl_cfi
+	pushfl
+	CFI_ADJUST_CFA_OFFSET 4
+	.endm
+
+	.macro popfl_cfi
+	popfl
+	CFI_ADJUST_CFA_OFFSET -4
+	.endm
+
 	.macro movl_cfi reg offset=0
 	movl %\reg, \offset(%esp)
 	CFI_REL_OFFSET \reg, \offset
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index ec8a52d..5be1542 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -112,23 +112,13 @@
 }
 #endif
 
-extern unsigned long end_user_pfn;
-
-extern u64 find_e820_area(u64 start, u64 end, u64 size, u64 align);
-extern u64 find_e820_area_size(u64 start, u64 *sizep, u64 align);
-extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
-#include <linux/early_res.h>
-
 extern unsigned long e820_end_of_ram_pfn(void);
 extern unsigned long e820_end_of_low_ram_pfn(void);
-extern int e820_find_active_region(const struct e820entry *ei,
-				  unsigned long start_pfn,
-				  unsigned long last_pfn,
-				  unsigned long *ei_startpfn,
-				  unsigned long *ei_endpfn);
-extern void e820_register_active_regions(int nid, unsigned long start_pfn,
-					 unsigned long end_pfn);
-extern u64 e820_hole_size(u64 start, u64 end);
+extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
+
+void memblock_x86_fill(void);
+void memblock_find_dma_reserve(void);
+
 extern void finish_e820_parsing(void);
 extern void e820_reserve_resources(void);
 extern void e820_reserve_resources_late(void);
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 8406ed7..8e4a165 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -90,7 +90,7 @@
 #endif /* CONFIG_X86_32 */
 
 extern int add_efi_memmap;
-extern void efi_reserve_early(void);
+extern void efi_memblock_x86_reserve_range(void);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
 
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h
index 8e8ec66..57650ab 100644
--- a/arch/x86/include/asm/entry_arch.h
+++ b/arch/x86/include/asm/entry_arch.h
@@ -16,22 +16,11 @@
 BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR)
 BUILD_INTERRUPT(reboot_interrupt,REBOOT_VECTOR)
 
-BUILD_INTERRUPT3(invalidate_interrupt0,INVALIDATE_TLB_VECTOR_START+0,
+.irpc idx, "01234567"
+BUILD_INTERRUPT3(invalidate_interrupt\idx,
+		 (INVALIDATE_TLB_VECTOR_START)+\idx,
 		 smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt1,INVALIDATE_TLB_VECTOR_START+1,
-		 smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt2,INVALIDATE_TLB_VECTOR_START+2,
-		 smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt3,INVALIDATE_TLB_VECTOR_START+3,
-		 smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt4,INVALIDATE_TLB_VECTOR_START+4,
-		 smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt5,INVALIDATE_TLB_VECTOR_START+5,
-		 smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt6,INVALIDATE_TLB_VECTOR_START+6,
-		 smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt7,INVALIDATE_TLB_VECTOR_START+7,
-		 smp_invalidate_interrupt)
+.endr
 #endif
 
 BUILD_INTERRUPT(x86_platform_ipi, X86_PLATFORM_IPI_VECTOR)
@@ -49,8 +38,8 @@
 BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
 BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
 
-#ifdef CONFIG_PERF_EVENTS
-BUILD_INTERRUPT(perf_pending_interrupt, LOCAL_PENDING_VECTOR)
+#ifdef CONFIG_IRQ_WORK
+BUILD_INTERRUPT(irq_work_interrupt, IRQ_WORK_VECTOR)
 #endif
 
 #ifdef CONFIG_X86_THERMAL_VECTOR
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index d07b44f..4d293dc 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -214,5 +214,20 @@
 	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
 	return __virt_to_fix(vaddr);
 }
+
+/* Return an pointer with offset calculated */
+static inline unsigned long __set_fixmap_offset(enum fixed_addresses idx,
+				phys_addr_t phys, pgprot_t flags)
+{
+	__set_fixmap(idx, phys, flags);
+	return fix_to_virt(idx) + (phys & (PAGE_SIZE - 1));
+}
+
+#define set_fixmap_offset(idx, phys)			\
+	__set_fixmap_offset(idx, phys, PAGE_KERNEL)
+
+#define set_fixmap_offset_nocache(idx, phys)			\
+	__set_fixmap_offset(idx, phys, PAGE_KERNEL_NOCACHE)
+
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_X86_FIXMAP_H */
diff --git a/arch/x86/include/asm/gart.h b/arch/x86/include/asm/gart.h
index 4ac5b0f..43085bf 100644
--- a/arch/x86/include/asm/gart.h
+++ b/arch/x86/include/asm/gart.h
@@ -17,6 +17,7 @@
 #define GARTEN		(1<<0)
 #define DISGARTCPU	(1<<4)
 #define DISGARTIO	(1<<5)
+#define DISTLBWALKPRB	(1<<6)
 
 /* GART cache control register bits. */
 #define INVGART		(1<<0)
@@ -27,7 +28,6 @@
 #define AMD64_GARTAPERTUREBASE	0x94
 #define AMD64_GARTTABLEBASE	0x98
 #define AMD64_GARTCACHECTL	0x9c
-#define AMD64_GARTEN		(1<<0)
 
 #ifdef CONFIG_GART_IOMMU
 extern int gart_iommu_aperture;
@@ -37,7 +37,7 @@
 extern void early_gart_iommu_check(void);
 extern int gart_iommu_init(void);
 extern void __init gart_parse_options(char *);
-extern void gart_iommu_hole_init(void);
+extern int gart_iommu_hole_init(void);
 
 #else
 #define gart_iommu_aperture            0
@@ -50,13 +50,27 @@
 static inline void gart_parse_options(char *options)
 {
 }
-static inline void gart_iommu_hole_init(void)
+static inline int gart_iommu_hole_init(void)
 {
+	return -ENODEV;
 }
 #endif
 
 extern int agp_amd64_init(void);
 
+static inline void gart_set_size_and_enable(struct pci_dev *dev, u32 order)
+{
+	u32 ctl;
+
+	/*
+	 * Don't enable translation but enable GART IO and CPU accesses.
+	 * Also, set DISTLBWALKPRB since GART tables memory is UC.
+	 */
+	ctl = DISTLBWALKPRB | order << 1;
+
+	pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
+}
+
 static inline void enable_gart_translation(struct pci_dev *dev, u64 addr)
 {
 	u32 tmp, ctl;
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index aeab29a..55e4de6 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -14,7 +14,7 @@
 #endif
 	unsigned int x86_platform_ipis;	/* arch dependent */
 	unsigned int apic_perf_irqs;
-	unsigned int apic_pending_irqs;
+	unsigned int apic_irq_work_irqs;
 #ifdef CONFIG_SMP
 	unsigned int irq_resched_count;
 	unsigned int irq_call_count;
diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h
index 1d5c08a..2c392d6 100644
--- a/arch/x86/include/asm/hpet.h
+++ b/arch/x86/include/asm/hpet.h
@@ -74,10 +74,12 @@
 extern unsigned int hpet_readl(unsigned int a);
 extern void force_hpet_resume(void);
 
-extern void hpet_msi_unmask(unsigned int irq);
-extern void hpet_msi_mask(unsigned int irq);
-extern void hpet_msi_write(unsigned int irq, struct msi_msg *msg);
-extern void hpet_msi_read(unsigned int irq, struct msi_msg *msg);
+struct irq_data;
+extern void hpet_msi_unmask(struct irq_data *data);
+extern void hpet_msi_mask(struct irq_data *data);
+struct hpet_dev;
+extern void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg);
+extern void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg);
 
 #ifdef CONFIG_PCI_MSI
 extern int arch_setup_hpet_msi(unsigned int irq, unsigned int id);
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index 46c0fe0..0274ec5 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -29,7 +29,7 @@
 extern void apic_timer_interrupt(void);
 extern void x86_platform_ipi(void);
 extern void error_interrupt(void);
-extern void perf_pending_interrupt(void);
+extern void irq_work_interrupt(void);
 
 extern void spurious_interrupt(void);
 extern void thermal_interrupt(void);
@@ -78,6 +78,13 @@
 	irq_attr->polarity	= polarity;
 }
 
+struct irq_2_iommu {
+	struct intel_iommu *iommu;
+	u16 irte_index;
+	u16 sub_handle;
+	u8  irte_mask;
+};
+
 /*
  * This is performance-critical, we want to do it O(1)
  *
@@ -89,15 +96,17 @@
 	cpumask_var_t		old_domain;
 	u8			vector;
 	u8			move_in_progress : 1;
+#ifdef CONFIG_INTR_REMAP
+	struct irq_2_iommu	irq_2_iommu;
+#endif
 };
 
-extern struct irq_cfg *irq_cfg(unsigned int);
 extern int assign_irq_vector(int, struct irq_cfg *, const struct cpumask *);
 extern void send_cleanup_vector(struct irq_cfg *);
 
-struct irq_desc;
-extern unsigned int set_desc_affinity(struct irq_desc *, const struct cpumask *,
-				      unsigned int *dest_id);
+struct irq_data;
+int __ioapic_set_affinity(struct irq_data *, const struct cpumask *,
+			  unsigned int *dest_id);
 extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin, struct io_apic_irq_attr *irq_attr);
 extern void setup_ioapic_dest(void);
 
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index a73a8d5..4aa2bb3 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -55,6 +55,12 @@
 extern int restore_i387_xstate_ia32(void __user *buf);
 #endif
 
+#ifdef CONFIG_MATH_EMULATION
+extern void finit_soft_fpu(struct i387_soft_struct *soft);
+#else
+static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
+#endif
+
 #define X87_FSW_ES (1 << 7)	/* Exception Summary */
 
 static __always_inline __pure bool use_xsaveopt(void)
@@ -67,6 +73,11 @@
 	return static_cpu_has(X86_FEATURE_XSAVE);
 }
 
+static __always_inline __pure bool use_fxsr(void)
+{
+        return static_cpu_has(X86_FEATURE_FXSR);
+}
+
 extern void __sanitize_i387_state(struct task_struct *);
 
 static inline void sanitize_i387_state(struct task_struct *tsk)
@@ -77,19 +88,11 @@
 }
 
 #ifdef CONFIG_X86_64
-
-/* Ignore delayed exceptions from user space */
-static inline void tolerant_fwait(void)
-{
-	asm volatile("1: fwait\n"
-		     "2:\n"
-		     _ASM_EXTABLE(1b, 2b));
-}
-
 static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
 {
 	int err;
 
+	/* See comment in fxsave() below. */
 	asm volatile("1:  rex64/fxrstor (%[fx])\n\t"
 		     "2:\n"
 		     ".section .fixup,\"ax\"\n"
@@ -98,44 +101,10 @@
 		     ".previous\n"
 		     _ASM_EXTABLE(1b, 3b)
 		     : [err] "=r" (err)
-#if 0 /* See comment in fxsave() below. */
-		     : [fx] "r" (fx), "m" (*fx), "0" (0));
-#else
-		     : [fx] "cdaSDb" (fx), "m" (*fx), "0" (0));
-#endif
+		     : [fx] "R" (fx), "m" (*fx), "0" (0));
 	return err;
 }
 
-/* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
-   is pending. Clear the x87 state here by setting it to fixed
-   values. The kernel data segment can be sometimes 0 and sometimes
-   new user value. Both should be ok.
-   Use the PDA as safe address because it should be already in L1. */
-static inline void fpu_clear(struct fpu *fpu)
-{
-	struct xsave_struct *xstate = &fpu->state->xsave;
-	struct i387_fxsave_struct *fx = &fpu->state->fxsave;
-
-	/*
-	 * xsave header may indicate the init state of the FP.
-	 */
-	if (use_xsave() &&
-	    !(xstate->xsave_hdr.xstate_bv & XSTATE_FP))
-		return;
-
-	if (unlikely(fx->swd & X87_FSW_ES))
-		asm volatile("fnclex");
-	alternative_input(ASM_NOP8 ASM_NOP2,
-			  "    emms\n"		/* clear stack tags */
-			  "    fildl %%gs:0",	/* load to clear state */
-			  X86_FEATURE_FXSAVE_LEAK);
-}
-
-static inline void clear_fpu_state(struct task_struct *tsk)
-{
-	fpu_clear(&tsk->thread.fpu);
-}
-
 static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
 {
 	int err;
@@ -149,6 +118,7 @@
 	if (unlikely(err))
 		return -EFAULT;
 
+	/* See comment in fxsave() below. */
 	asm volatile("1:  rex64/fxsave (%[fx])\n\t"
 		     "2:\n"
 		     ".section .fixup,\"ax\"\n"
@@ -157,11 +127,7 @@
 		     ".previous\n"
 		     _ASM_EXTABLE(1b, 3b)
 		     : [err] "=r" (err), "=m" (*fx)
-#if 0 /* See comment in fxsave() below. */
-		     : [fx] "r" (fx), "0" (0));
-#else
-		     : [fx] "cdaSDb" (fx), "0" (0));
-#endif
+		     : [fx] "R" (fx), "0" (0));
 	if (unlikely(err) &&
 	    __clear_user(fx, sizeof(struct i387_fxsave_struct)))
 		err = -EFAULT;
@@ -175,56 +141,29 @@
 	   uses any extended registers for addressing, a second REX prefix
 	   will be generated (to the assembler, rex64 followed by semicolon
 	   is a separate instruction), and hence the 64-bitness is lost. */
-#if 0
+
+#ifdef CONFIG_AS_FXSAVEQ
 	/* Using "fxsaveq %0" would be the ideal choice, but is only supported
 	   starting with gas 2.16. */
 	__asm__ __volatile__("fxsaveq %0"
 			     : "=m" (fpu->state->fxsave));
-#elif 0
+#else
 	/* Using, as a workaround, the properly prefixed form below isn't
 	   accepted by any binutils version so far released, complaining that
 	   the same type of prefix is used twice if an extended register is
-	   needed for addressing (fix submitted to mainline 2005-11-21). */
-	__asm__ __volatile__("rex64/fxsave %0"
-			     : "=m" (fpu->state->fxsave));
-#else
-	/* This, however, we can work around by forcing the compiler to select
+	   needed for addressing (fix submitted to mainline 2005-11-21).
+	asm volatile("rex64/fxsave %0"
+		     : "=m" (fpu->state->fxsave));
+	   This, however, we can work around by forcing the compiler to select
 	   an addressing mode that doesn't require extended registers. */
-	__asm__ __volatile__("rex64/fxsave (%1)"
-			     : "=m" (fpu->state->fxsave)
-			     : "cdaSDb" (&fpu->state->fxsave));
+	asm volatile("rex64/fxsave (%[fx])"
+		     : "=m" (fpu->state->fxsave)
+		     : [fx] "R" (&fpu->state->fxsave));
 #endif
 }
 
-static inline void fpu_save_init(struct fpu *fpu)
-{
-	if (use_xsave())
-		fpu_xsave(fpu);
-	else
-		fpu_fxsave(fpu);
-
-	fpu_clear(fpu);
-}
-
-static inline void __save_init_fpu(struct task_struct *tsk)
-{
-	fpu_save_init(&tsk->thread.fpu);
-	task_thread_info(tsk)->status &= ~TS_USEDFPU;
-}
-
 #else  /* CONFIG_X86_32 */
 
-#ifdef CONFIG_MATH_EMULATION
-extern void finit_soft_fpu(struct i387_soft_struct *soft);
-#else
-static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
-#endif
-
-static inline void tolerant_fwait(void)
-{
-	asm volatile("fnclex ; fwait");
-}
-
 /* perform fxrstor iff the processor has extended states, otherwise frstor */
 static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
 {
@@ -241,6 +180,14 @@
 	return 0;
 }
 
+static inline void fpu_fxsave(struct fpu *fpu)
+{
+	asm volatile("fxsave %[fx]"
+		     : [fx] "=m" (fpu->state->fxsave));
+}
+
+#endif	/* CONFIG_X86_64 */
+
 /* We need a safe address that is cheap to find and that is already
    in L1 during context switch. The best choices are unfortunately
    different for UP and SMP */
@@ -256,47 +203,33 @@
 static inline void fpu_save_init(struct fpu *fpu)
 {
 	if (use_xsave()) {
-		struct xsave_struct *xstate = &fpu->state->xsave;
-		struct i387_fxsave_struct *fx = &fpu->state->fxsave;
-
 		fpu_xsave(fpu);
 
 		/*
 		 * xsave header may indicate the init state of the FP.
 		 */
-		if (!(xstate->xsave_hdr.xstate_bv & XSTATE_FP))
-			goto end;
-
-		if (unlikely(fx->swd & X87_FSW_ES))
-			asm volatile("fnclex");
-
-		/*
-		 * we can do a simple return here or be paranoid :)
-		 */
-		goto clear_state;
+		if (!(fpu->state->xsave.xsave_hdr.xstate_bv & XSTATE_FP))
+			return;
+	} else if (use_fxsr()) {
+		fpu_fxsave(fpu);
+	} else {
+		asm volatile("fsave %[fx]; fwait"
+			     : [fx] "=m" (fpu->state->fsave));
+		return;
 	}
 
-	/* Use more nops than strictly needed in case the compiler
-	   varies code */
-	alternative_input(
-		"fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4,
-		"fxsave %[fx]\n"
-		"bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
-		X86_FEATURE_FXSR,
-		[fx] "m" (fpu->state->fxsave),
-		[fsw] "m" (fpu->state->fxsave.swd) : "memory");
-clear_state:
+	if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES))
+		asm volatile("fnclex");
+
 	/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
 	   is pending.  Clear the x87 state here by setting it to fixed
 	   values. safe_address is a random variable that should be in L1 */
 	alternative_input(
-		GENERIC_NOP8 GENERIC_NOP2,
+		ASM_NOP8 ASM_NOP2,
 		"emms\n\t"	  	/* clear stack tags */
-		"fildl %[addr]", 	/* set F?P to defined value */
+		"fildl %P[addr]",	/* set F?P to defined value */
 		X86_FEATURE_FXSAVE_LEAK,
 		[addr] "m" (safe_address));
-end:
-	;
 }
 
 static inline void __save_init_fpu(struct task_struct *tsk)
@@ -305,9 +238,6 @@
 	task_thread_info(tsk)->status &= ~TS_USEDFPU;
 }
 
-
-#endif	/* CONFIG_X86_64 */
-
 static inline int fpu_fxrstor_checking(struct fpu *fpu)
 {
 	return fxrstor_checking(&fpu->state->fxsave);
@@ -344,7 +274,10 @@
 static inline void __clear_fpu(struct task_struct *tsk)
 {
 	if (task_thread_info(tsk)->status & TS_USEDFPU) {
-		tolerant_fwait();
+		/* Ignore delayed exceptions from user space */
+		asm volatile("1: fwait\n"
+			     "2:\n"
+			     _ASM_EXTABLE(1b, 2b));
 		task_thread_info(tsk)->status &= ~TS_USEDFPU;
 		stts();
 	}
@@ -405,19 +338,6 @@
 		stts();
 }
 
-#ifdef CONFIG_X86_64
-
-static inline void save_init_fpu(struct task_struct *tsk)
-{
-	__save_init_fpu(tsk);
-	stts();
-}
-
-#define unlazy_fpu	__unlazy_fpu
-#define clear_fpu	__clear_fpu
-
-#else  /* CONFIG_X86_32 */
-
 /*
  * These disable preemption on their own and are safe
  */
@@ -443,8 +363,6 @@
 	preempt_enable();
 }
 
-#endif	/* CONFIG_X86_64 */
-
 /*
  * i387 state interaction
  */
@@ -508,7 +426,4 @@
 
 #endif /* __ASSEMBLY__ */
 
-#define PSHUFB_XMM5_XMM0 .byte 0x66, 0x0f, 0x38, 0x00, 0xc5
-#define PSHUFB_XMM5_XMM6 .byte 0x66, 0x0f, 0x38, 0x00, 0xf5
-
 #endif /* _ASM_X86_I387_H */
diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index 1655147..a203659 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -55,6 +55,8 @@
 struct legacy_pic {
 	int nr_legacy_irqs;
 	struct irq_chip *chip;
+	void (*mask)(unsigned int irq);
+	void (*unmask)(unsigned int irq);
 	void (*mask_all)(void);
 	void (*restore_mask)(void);
 	void (*init)(int auto_eoi);
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 30a3e97..f0203f4 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -206,6 +206,7 @@
 
 extern void iounmap(volatile void __iomem *addr);
 
+extern void set_iounmap_nonlazy(void);
 
 #ifdef __KERNEL__
 
@@ -348,6 +349,7 @@
 				    unsigned long size);
 extern void early_iounmap(void __iomem *addr, unsigned long size);
 extern void fixup_early_ioremap(void);
+extern bool is_early_ioremap_ptep(pte_t *ptep);
 
 #define IO_SPACE_LIMIT 0xffff
 
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 9cb2edb..c8be456 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -170,12 +170,6 @@
 
 extern void probe_nr_irqs_gsi(void);
 
-extern int setup_ioapic_entry(int apic, int irq,
-			      struct IO_APIC_route_entry *entry,
-			      unsigned int destination, int trigger,
-			      int polarity, int vector, int pin);
-extern void ioapic_write_entry(int apic, int pin,
-			       struct IO_APIC_route_entry e);
 extern void setup_ioapic_ids_from_mpc(void);
 
 struct mp_ioapic_gsi{
diff --git a/arch/x86/include/asm/iommu_table.h b/arch/x86/include/asm/iommu_table.h
new file mode 100644
index 0000000..f229b13
--- /dev/null
+++ b/arch/x86/include/asm/iommu_table.h
@@ -0,0 +1,100 @@
+#ifndef _ASM_X86_IOMMU_TABLE_H
+#define _ASM_X86_IOMMU_TABLE_H
+
+#include <asm/swiotlb.h>
+
+/*
+ * History lesson:
+ * The execution chain of IOMMUs in 2.6.36 looks as so:
+ *
+ *            [xen-swiotlb]
+ *                 |
+ *         +----[swiotlb *]--+
+ *        /         |         \
+ *       /          |          \
+ *    [GART]     [Calgary]  [Intel VT-d]
+ *     /
+ *    /
+ * [AMD-Vi]
+ *
+ * *: if SWIOTLB detected 'iommu=soft'/'swiotlb=force' it would skip
+ * over the rest of IOMMUs and unconditionally initialize the SWIOTLB.
+ * Also it would surreptitiously initialize set the swiotlb=1 if there were
+ * more than 4GB and if the user did not pass in 'iommu=off'. The swiotlb
+ * flag would be turned off by all IOMMUs except the Calgary one.
+ *
+ * The IOMMU_INIT* macros allow a similar tree (or more complex if desired)
+ * to be built by defining who we depend on.
+ *
+ * And all that needs to be done is to use one of the macros in the IOMMU
+ * and the pci-dma.c will take care of the rest.
+ */
+
+struct iommu_table_entry {
+	initcall_t	detect;
+	initcall_t	depend;
+	void		(*early_init)(void); /* No memory allocate available. */
+	void		(*late_init)(void); /* Yes, can allocate memory. */
+#define IOMMU_FINISH_IF_DETECTED (1<<0)
+#define IOMMU_DETECTED		 (1<<1)
+	int		flags;
+};
+/*
+ * Macro fills out an entry in the .iommu_table that is equivalent
+ * to the fields that 'struct iommu_table_entry' has. The entries
+ * that are put in the .iommu_table section are not put in any order
+ * hence during boot-time we will have to resort them based on
+ * dependency. */
+
+
+#define __IOMMU_INIT(_detect, _depend, _early_init, _late_init, _finish)\
+	static const struct iommu_table_entry const			\
+		__iommu_entry_##_detect __used				\
+	__attribute__ ((unused, __section__(".iommu_table"),		\
+			aligned((sizeof(void *)))))	\
+	= {_detect, _depend, _early_init, _late_init,			\
+	   _finish ? IOMMU_FINISH_IF_DETECTED : 0}
+/*
+ * The simplest IOMMU definition. Provide the detection routine
+ * and it will be run after the SWIOTLB and the other IOMMUs
+ * that utilize this macro. If the IOMMU is detected (ie, the
+ * detect routine returns a positive value), the other IOMMUs
+ * are also checked. You can use IOMMU_INIT_POST_FINISH if you prefer
+ * to stop detecting the other IOMMUs after yours has been detected.
+ */
+#define IOMMU_INIT_POST(_detect)					\
+	__IOMMU_INIT(_detect, pci_swiotlb_detect_4gb,  0, 0, 0)
+
+#define IOMMU_INIT_POST_FINISH(detect)					\
+	__IOMMU_INIT(_detect, pci_swiotlb_detect_4gb,  0, 0, 1)
+
+/*
+ * A more sophisticated version of IOMMU_INIT. This variant requires:
+ *  a). A detection routine function.
+ *  b). The name of the detection routine we depend on to get called
+ *      before us.
+ *  c). The init routine which gets called if the detection routine
+ *      returns a positive value from the pci_iommu_alloc. This means
+ *      no presence of a memory allocator.
+ *  d). Similar to the 'init', except that this gets called from pci_iommu_init
+ *      where we do have a memory allocator.
+ *
+ * The standard vs the _FINISH differs in that the _FINISH variant will
+ * continue detecting other IOMMUs in the call list after the
+ * the detection routine returns a positive number. The _FINISH will
+ * stop the execution chain. Both will still call the 'init' and
+ * 'late_init' functions if they are set.
+ */
+#define IOMMU_INIT_FINISH(_detect, _depend, _init, _late_init)		\
+	__IOMMU_INIT(_detect, _depend, _init, _late_init, 1)
+
+#define IOMMU_INIT(_detect, _depend, _init, _late_init)			\
+	__IOMMU_INIT(_detect, _depend, _init, _late_init, 0)
+
+void sort_iommu_table(struct iommu_table_entry *start,
+		      struct iommu_table_entry *finish);
+
+void check_iommu_entries(struct iommu_table_entry *start,
+			 struct iommu_table_entry *finish);
+
+#endif /* _ASM_X86_IOMMU_TABLE_H */
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 5458380..0bf5b00 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -19,18 +19,16 @@
 # define ARCH_HAS_NMI_WATCHDOG
 #endif
 
-#ifdef CONFIG_4KSTACKS
-  extern void irq_ctx_init(int cpu);
-  extern void irq_ctx_exit(int cpu);
-# define __ARCH_HAS_DO_SOFTIRQ
+#ifdef CONFIG_X86_32
+extern void irq_ctx_init(int cpu);
+extern void irq_ctx_exit(int cpu);
 #else
 # define irq_ctx_init(cpu) do { } while (0)
 # define irq_ctx_exit(cpu) do { } while (0)
-# ifdef CONFIG_X86_64
-#  define __ARCH_HAS_DO_SOFTIRQ
-# endif
 #endif
 
+#define __ARCH_HAS_DO_SOFTIRQ
+
 #ifdef CONFIG_HOTPLUG_CPU
 #include <linux/cpumask.h>
 extern void fixup_irqs(void);
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h
index f275e22..1c23360 100644
--- a/arch/x86/include/asm/irq_remapping.h
+++ b/arch/x86/include/asm/irq_remapping.h
@@ -3,4 +3,39 @@
 
 #define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
 
+#ifdef CONFIG_INTR_REMAP
+static inline void prepare_irte(struct irte *irte, int vector,
+			        unsigned int dest)
+{
+	memset(irte, 0, sizeof(*irte));
+
+	irte->present = 1;
+	irte->dst_mode = apic->irq_dest_mode;
+	/*
+	 * Trigger mode in the IRTE will always be edge, and for IO-APIC, the
+	 * actual level or edge trigger will be setup in the IO-APIC
+	 * RTE. This will help simplify level triggered irq migration.
+	 * For more details, see the comments (in io_apic.c) explainig IO-APIC
+	 * irq migration in the presence of interrupt-remapping.
+	*/
+	irte->trigger_mode = 0;
+	irte->dlvry_mode = apic->irq_delivery_mode;
+	irte->vector = vector;
+	irte->dest_id = IRTE_DEST(dest);
+	irte->redir_hint = 1;
+}
+static inline bool irq_remapped(struct irq_cfg *cfg)
+{
+	return cfg->irq_2_iommu.iommu != NULL;
+}
+#else
+static void prepare_irte(struct irte *irte, int vector, unsigned int dest)
+{
+}
+static inline bool irq_remapped(struct irq_cfg *cfg)
+{
+	return false;
+}
+#endif
+
 #endif	/* _ASM_X86_IRQ_REMAPPING_H */
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index e2ca300..6af0894 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -114,9 +114,9 @@
 #define X86_PLATFORM_IPI_VECTOR		0xed
 
 /*
- * Performance monitoring pending work vector:
+ * IRQ work vector:
  */
-#define LOCAL_PENDING_VECTOR		0xec
+#define IRQ_WORK_VECTOR			0xec
 
 #define UV_BAU_MESSAGE			0xea
 
diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h
index 9e2b952..5745ce8 100644
--- a/arch/x86/include/asm/irqflags.h
+++ b/arch/x86/include/asm/irqflags.h
@@ -61,22 +61,22 @@
 #else
 #ifndef __ASSEMBLY__
 
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
 {
 	return native_save_fl();
 }
 
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
 {
 	native_restore_fl(flags);
 }
 
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
 {
 	native_irq_disable();
 }
 
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
 {
 	native_irq_enable();
 }
@@ -85,7 +85,7 @@
  * Used in the idle loop; sti takes one instruction cycle
  * to complete:
  */
-static inline void raw_safe_halt(void)
+static inline void arch_safe_halt(void)
 {
 	native_safe_halt();
 }
@@ -102,12 +102,10 @@
 /*
  * For spinlocks, etc:
  */
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
 {
-	unsigned long flags = __raw_local_save_flags();
-
-	raw_local_irq_disable();
-
+	unsigned long flags = arch_local_save_flags();
+	arch_local_irq_disable();
 	return flags;
 }
 #else
@@ -153,22 +151,16 @@
 #endif /* CONFIG_PARAVIRT */
 
 #ifndef __ASSEMBLY__
-#define raw_local_save_flags(flags)				\
-	do { (flags) = __raw_local_save_flags(); } while (0)
-
-#define raw_local_irq_save(flags)				\
-	do { (flags) = __raw_local_irq_save(); } while (0)
-
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
 	return !(flags & X86_EFLAGS_IF);
 }
 
-static inline int raw_irqs_disabled(void)
+static inline int arch_irqs_disabled(void)
 {
-	unsigned long flags = __raw_local_save_flags();
+	unsigned long flags = arch_local_save_flags();
 
-	return raw_irqs_disabled_flags(flags);
+	return arch_irqs_disabled_flags(flags);
 }
 
 #else
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
new file mode 100644
index 0000000..f52d42e
--- /dev/null
+++ b/arch/x86/include/asm/jump_label.h
@@ -0,0 +1,37 @@
+#ifndef _ASM_X86_JUMP_LABEL_H
+#define _ASM_X86_JUMP_LABEL_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <asm/nops.h>
+
+#define JUMP_LABEL_NOP_SIZE 5
+
+# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"
+
+# define JUMP_LABEL(key, label)					\
+	do {							\
+		asm goto("1:"					\
+			JUMP_LABEL_INITIAL_NOP			\
+			".pushsection __jump_table,  \"a\" \n\t"\
+			_ASM_PTR "1b, %l[" #label "], %c0 \n\t" \
+			".popsection \n\t"			\
+			: :  "i" (key) :  : label);		\
+	} while (0)
+
+#endif /* __KERNEL__ */
+
+#ifdef CONFIG_X86_64
+typedef u64 jump_label_t;
+#else
+typedef u32 jump_label_t;
+#endif
+
+struct jump_entry {
+	jump_label_t code;
+	jump_label_t target;
+	jump_label_t key;
+};
+
+#endif
diff --git a/arch/x86/include/asm/k8.h b/arch/x86/include/asm/k8.h
deleted file mode 100644
index af00bd1..0000000
--- a/arch/x86/include/asm/k8.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef _ASM_X86_K8_H
-#define _ASM_X86_K8_H
-
-#include <linux/pci.h>
-
-extern struct pci_device_id k8_nb_ids[];
-struct bootnode;
-
-extern int early_is_k8_nb(u32 value);
-extern struct pci_dev **k8_northbridges;
-extern int num_k8_northbridges;
-extern int cache_k8_northbridges(void);
-extern void k8_flush_garts(void);
-extern int k8_get_nodes(struct bootnode *nodes);
-extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn);
-extern int k8_scan_nodes(void);
-
-#ifdef CONFIG_K8_NB
-extern int num_k8_northbridges;
-
-static inline struct pci_dev *node_to_k8_nb_misc(int node)
-{
-	return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL;
-}
-
-#else
-#define num_k8_northbridges 0
-
-static inline struct pci_dev *node_to_k8_nb_misc(int node)
-{
-	return NULL;
-}
-#endif
-
-
-#endif /* _ASM_X86_K8_H */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 502e53f..c52e2eb 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -652,20 +652,6 @@
 	return (struct kvm_mmu_page *)page_private(page);
 }
 
-static inline u16 kvm_read_fs(void)
-{
-	u16 seg;
-	asm("mov %%fs, %0" : "=g"(seg));
-	return seg;
-}
-
-static inline u16 kvm_read_gs(void)
-{
-	u16 seg;
-	asm("mov %%gs, %0" : "=g"(seg));
-	return seg;
-}
-
 static inline u16 kvm_read_ldt(void)
 {
 	u16 ldt;
@@ -673,16 +659,6 @@
 	return ldt;
 }
 
-static inline void kvm_load_fs(u16 sel)
-{
-	asm("mov %0, %%fs" : : "rm"(sel));
-}
-
-static inline void kvm_load_gs(u16 sel)
-{
-	asm("mov %0, %%gs" : : "rm"(sel));
-}
-
 static inline void kvm_load_ldt(u16 sel)
 {
 	asm("lldt %0" : : "rm"(sel));
diff --git a/arch/x86/include/asm/memblock.h b/arch/x86/include/asm/memblock.h
new file mode 100644
index 0000000..19ae14b
--- /dev/null
+++ b/arch/x86/include/asm/memblock.h
@@ -0,0 +1,23 @@
+#ifndef _X86_MEMBLOCK_H
+#define _X86_MEMBLOCK_H
+
+#define ARCH_DISCARD_MEMBLOCK
+
+u64 memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align);
+void memblock_x86_to_bootmem(u64 start, u64 end);
+
+void memblock_x86_reserve_range(u64 start, u64 end, char *name);
+void memblock_x86_free_range(u64 start, u64 end);
+struct range;
+int __get_free_all_memory_range(struct range **range, int nodeid,
+			 unsigned long start_pfn, unsigned long end_pfn);
+int get_free_all_memory_range(struct range **rangep, int nodeid);
+
+void memblock_x86_register_active_regions(int nid, unsigned long start_pfn,
+					 unsigned long last_pfn);
+u64 memblock_x86_hole_size(u64 start, u64 end);
+u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align);
+u64 memblock_x86_free_memory_in_range(u64 addr, u64 limit);
+u64 memblock_x86_memory_in_range(u64 addr, u64 limit);
+
+#endif
diff --git a/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h
index 3e2ce58..67763c5 100644
--- a/arch/x86/include/asm/module.h
+++ b/arch/x86/include/asm/module.h
@@ -60,12 +60,7 @@
 #endif
 
 #ifdef CONFIG_X86_32
-# ifdef CONFIG_4KSTACKS
-#  define MODULE_STACKSIZE "4KSTACKS "
-# else
-#  define MODULE_STACKSIZE ""
-# endif
-# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE
+# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
 #endif
 
 #endif /* _ASM_X86_MODULE_H */
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
index 1635074..4a711a6 100644
--- a/arch/x86/include/asm/mrst.h
+++ b/arch/x86/include/asm/mrst.h
@@ -10,6 +10,9 @@
  */
 #ifndef _ASM_X86_MRST_H
 #define _ASM_X86_MRST_H
+
+#include <linux/sfi.h>
+
 extern int pci_mrst_init(void);
 int __init sfi_parse_mrtc(struct sfi_table_header *table);
 
@@ -26,7 +29,7 @@
 };
 
 extern enum mrst_cpu_type __mrst_cpu_chip;
-static enum mrst_cpu_type mrst_identify_cpu(void)
+static inline enum mrst_cpu_type mrst_identify_cpu(void)
 {
 	return __mrst_cpu_chip;
 }
@@ -42,4 +45,9 @@
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX	8
 
+extern struct console early_mrst_console;
+extern void mrst_early_console_init(void);
+
+extern struct console early_hsu_console;
+extern void hsu_early_console_init(void);
 #endif /* _ASM_X86_MRST_H */
diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h
new file mode 100644
index 0000000..bcdff99
--- /dev/null
+++ b/arch/x86/include/asm/mwait.h
@@ -0,0 +1,15 @@
+#ifndef _ASM_X86_MWAIT_H
+#define _ASM_X86_MWAIT_H
+
+#define MWAIT_SUBSTATE_MASK		0xf
+#define MWAIT_CSTATE_MASK		0xf
+#define MWAIT_SUBSTATE_SIZE		4
+#define MWAIT_MAX_NUM_CSTATES		8
+
+#define CPUID_MWAIT_LEAF		5
+#define CPUID5_ECX_EXTENSIONS_SUPPORTED 0x1
+#define CPUID5_ECX_INTERRUPT_BREAK	0x2
+
+#define MWAIT_ECX_INTERRUPT_BREAK	0x1
+
+#endif /* _ASM_X86_MWAIT_H */
diff --git a/arch/x86/include/asm/olpc_ofw.h b/arch/x86/include/asm/olpc_ofw.h
index 08fde47..2a84781 100644
--- a/arch/x86/include/asm/olpc_ofw.h
+++ b/arch/x86/include/asm/olpc_ofw.h
@@ -21,10 +21,14 @@
 /* install OFW's pde permanently into the kernel's pgtable */
 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 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 */
 
diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h
index 6f1b733..ade619f 100644
--- a/arch/x86/include/asm/page_32_types.h
+++ b/arch/x86/include/asm/page_32_types.h
@@ -15,11 +15,7 @@
  */
 #define __PAGE_OFFSET		_AC(CONFIG_PAGE_OFFSET, UL)
 
-#ifdef CONFIG_4KSTACKS
-#define THREAD_ORDER	0
-#else
 #define THREAD_ORDER	1
-#endif
 #define THREAD_SIZE 	(PAGE_SIZE << THREAD_ORDER)
 
 #define STACKFAULT_STACK 0
diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h
index a667f24..1df6621 100644
--- a/arch/x86/include/asm/page_types.h
+++ b/arch/x86/include/asm/page_types.h
@@ -8,7 +8,7 @@
 #define PAGE_SIZE	(_AC(1,UL) << PAGE_SHIFT)
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
-#define __PHYSICAL_MASK		((phys_addr_t)(1ULL << __PHYSICAL_MASK_SHIFT) - 1)
+#define __PHYSICAL_MASK		((phys_addr_t)((1ULL << __PHYSICAL_MASK_SHIFT) - 1))
 #define __VIRTUAL_MASK		((1UL << __VIRTUAL_MASK_SHIFT) - 1)
 
 /* Cast PAGE_MASK to a signed type so that it is sign-extended if
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 5653f43..18e3b8a 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -105,7 +105,7 @@
 }
 #endif
 
-static inline void raw_safe_halt(void)
+static inline void arch_safe_halt(void)
 {
 	PVOP_VCALL0(pv_irq_ops.safe_halt);
 }
@@ -416,11 +416,6 @@
 	PVOP_VCALL2(pv_mmu_ops.alloc_pmd, mm, pfn);
 }
 
-static inline void paravirt_alloc_pmd_clone(unsigned long pfn, unsigned long clonepfn,
-					    unsigned long start, unsigned long count)
-{
-	PVOP_VCALL4(pv_mmu_ops.alloc_pmd_clone, pfn, clonepfn, start, count);
-}
 static inline void paravirt_release_pmd(unsigned long pfn)
 {
 	PVOP_VCALL1(pv_mmu_ops.release_pmd, pfn);
@@ -829,32 +824,32 @@
 #define __PV_IS_CALLEE_SAVE(func)			\
 	((struct paravirt_callee_save) { func })
 
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
 {
 	return PVOP_CALLEE0(unsigned long, pv_irq_ops.save_fl);
 }
 
-static inline void raw_local_irq_restore(unsigned long f)
+static inline void arch_local_irq_restore(unsigned long f)
 {
 	PVOP_VCALLEE1(pv_irq_ops.restore_fl, f);
 }
 
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
 {
 	PVOP_VCALLEE0(pv_irq_ops.irq_disable);
 }
 
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
 {
 	PVOP_VCALLEE0(pv_irq_ops.irq_enable);
 }
 
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
 {
 	unsigned long f;
 
-	f = __raw_local_save_flags();
-	raw_local_irq_disable();
+	f = arch_local_save_flags();
+	arch_local_irq_disable();
 	return f;
 }
 
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index db9ef55..b82bac9 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -255,7 +255,6 @@
 	 */
 	void (*alloc_pte)(struct mm_struct *mm, unsigned long pfn);
 	void (*alloc_pmd)(struct mm_struct *mm, unsigned long pfn);
-	void (*alloc_pmd_clone)(unsigned long pfn, unsigned long clonepfn, unsigned long start, unsigned long count);
 	void (*alloc_pud)(struct mm_struct *mm, unsigned long pfn);
 	void (*release_pte)(unsigned long pfn);
 	void (*release_pmd)(unsigned long pfn);
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index cd28f9a..f899e01 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -47,6 +47,20 @@
 #ifdef CONFIG_SMP
 #define __percpu_arg(x)		"%%"__stringify(__percpu_seg)":%P" #x
 #define __my_cpu_offset		percpu_read(this_cpu_off)
+
+/*
+ * Compared to the generic __my_cpu_offset version, the following
+ * saves one instruction and avoids clobbering a temp register.
+ */
+#define __this_cpu_ptr(ptr)				\
+({							\
+	unsigned long tcp_ptr__;			\
+	__verify_pcpu_ptr(ptr);				\
+	asm volatile("add " __percpu_arg(1) ", %0"	\
+		     : "=r" (tcp_ptr__)			\
+		     : "m" (this_cpu_off), "0" (ptr));	\
+	(typeof(*(ptr)) __kernel __force *)tcp_ptr__;	\
+})
 #else
 #define __percpu_arg(x)		"%P" #x
 #endif
diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h
index def5007..a70cd21 100644
--- a/arch/x86/include/asm/perf_event_p4.h
+++ b/arch/x86/include/asm/perf_event_p4.h
@@ -36,19 +36,6 @@
 #define P4_ESCR_EMASK(v)	((v) << P4_ESCR_EVENTMASK_SHIFT)
 #define P4_ESCR_TAG(v)		((v) << P4_ESCR_TAG_SHIFT)
 
-/* Non HT mask */
-#define P4_ESCR_MASK			\
-	(P4_ESCR_EVENT_MASK	|	\
-	P4_ESCR_EVENTMASK_MASK	|	\
-	P4_ESCR_TAG_MASK	|	\
-	P4_ESCR_TAG_ENABLE	|	\
-	P4_ESCR_T0_OS		|	\
-	P4_ESCR_T0_USR)
-
-/* HT mask */
-#define P4_ESCR_MASK_HT			\
-	(P4_ESCR_MASK |	P4_ESCR_T1_OS | P4_ESCR_T1_USR)
-
 #define P4_CCCR_OVF			0x80000000U
 #define P4_CCCR_CASCADE			0x40000000U
 #define P4_CCCR_OVF_PMI_T0		0x04000000U
@@ -70,23 +57,6 @@
 #define P4_CCCR_THRESHOLD(v)		((v) << P4_CCCR_THRESHOLD_SHIFT)
 #define P4_CCCR_ESEL(v)			((v) << P4_CCCR_ESCR_SELECT_SHIFT)
 
-/* Non HT mask */
-#define P4_CCCR_MASK				\
-	(P4_CCCR_OVF			|	\
-	P4_CCCR_CASCADE			|	\
-	P4_CCCR_OVF_PMI_T0		|	\
-	P4_CCCR_FORCE_OVF		|	\
-	P4_CCCR_EDGE			|	\
-	P4_CCCR_THRESHOLD_MASK		|	\
-	P4_CCCR_COMPLEMENT		|	\
-	P4_CCCR_COMPARE			|	\
-	P4_CCCR_ESCR_SELECT_MASK	|	\
-	P4_CCCR_ENABLE)
-
-/* HT mask */
-#define P4_CCCR_MASK_HT				\
-	(P4_CCCR_MASK | P4_CCCR_OVF_PMI_T1 | P4_CCCR_THREAD_ANY)
-
 #define P4_GEN_ESCR_EMASK(class, name, bit)	\
 	class##__##name = ((1 << bit) << P4_ESCR_EVENTMASK_SHIFT)
 #define P4_ESCR_EMASK_BIT(class, name)		class##__##name
@@ -127,6 +97,28 @@
 #define P4_CONFIG_HT_SHIFT		63
 #define P4_CONFIG_HT			(1ULL << P4_CONFIG_HT_SHIFT)
 
+/*
+ * The bits we allow to pass for RAW events
+ */
+#define P4_CONFIG_MASK_ESCR		\
+	P4_ESCR_EVENT_MASK	|	\
+	P4_ESCR_EVENTMASK_MASK	|	\
+	P4_ESCR_TAG_MASK	|	\
+	P4_ESCR_TAG_ENABLE
+
+#define P4_CONFIG_MASK_CCCR		\
+	P4_CCCR_EDGE		|	\
+	P4_CCCR_THRESHOLD_MASK	|	\
+	P4_CCCR_COMPLEMENT	|	\
+	P4_CCCR_COMPARE		|	\
+	P4_CCCR_THREAD_ANY	|	\
+	P4_CCCR_RESERVED
+
+/* some dangerous bits are reserved for kernel internals */
+#define P4_CONFIG_MASK				  	  \
+	(p4_config_pack_escr(P4_CONFIG_MASK_ESCR))	| \
+	(p4_config_pack_cccr(P4_CONFIG_MASK_CCCR))
+
 static inline bool p4_is_event_cascaded(u64 config)
 {
 	u32 cccr = p4_config_unpack_cccr(config);
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index a34c785..ada823a 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -28,6 +28,8 @@
 extern spinlock_t pgd_lock;
 extern struct list_head pgd_list;
 
+extern struct mm_struct *pgd_page_get_mm(struct page *page);
+
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else  /* !CONFIG_PARAVIRT */
@@ -603,6 +605,8 @@
 	pte_update(mm, addr, ptep);
 }
 
+#define flush_tlb_fix_spurious_fault(vma, address)
+
 /*
  * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
  *
diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h
index f686f49..8abde9e 100644
--- a/arch/x86/include/asm/pgtable_32.h
+++ b/arch/x86/include/asm/pgtable_32.h
@@ -26,7 +26,7 @@
 struct vm_area_struct;
 
 extern pgd_t swapper_pg_dir[1024];
-extern pgd_t trampoline_pg_dir[1024];
+extern pgd_t initial_page_table[1024];
 
 static inline void pgtable_cache_init(void) { }
 static inline void check_pgt_cache(void) { }
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h
index 076052c..f96ac9b 100644
--- a/arch/x86/include/asm/pgtable_64.h
+++ b/arch/x86/include/asm/pgtable_64.h
@@ -102,6 +102,8 @@
 	native_set_pgd(pgd, native_make_pgd(0));
 }
 
+extern void sync_global_pgds(unsigned long start, unsigned long end);
+
 /*
  * 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/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 325b7bd..cae9c3c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -110,6 +110,8 @@
 	u16			phys_proc_id;
 	/* Core id: */
 	u16			cpu_core_id;
+	/* Compute unit id */
+	u8			compute_unit_id;
 	/* Index into per_cpu list: */
 	u16			cpu_index;
 #endif
@@ -602,7 +604,7 @@
 
 static inline void set_in_cr4(unsigned long mask)
 {
-	unsigned cr4;
+	unsigned long cr4;
 
 	mmu_cr4_features |= mask;
 	cr4 = read_cr4();
@@ -612,7 +614,7 @@
 
 static inline void clear_in_cr4(unsigned long mask)
 {
-	unsigned cr4;
+	unsigned long cr4;
 
 	mmu_cr4_features &= ~mask;
 	cr4 = read_cr4();
@@ -764,29 +766,6 @@
 extern unsigned long		idle_nomwait;
 extern bool			c1e_detected;
 
-/*
- * on systems with caches, caches must be flashed as the absolute
- * last instruction before going into a suspended halt.  Otherwise,
- * dirty data can linger in the cache and become stale on resume,
- * leading to strange errors.
- *
- * perform a variety of operations to guarantee that the compiler
- * will not reorder instructions.  wbinvd itself is serializing
- * so the processor will not reorder.
- *
- * Systems without cache can just go into halt.
- */
-static inline void wbinvd_halt(void)
-{
-	mb();
-	/* check for clflush to determine if wbinvd is legal */
-	if (cpu_has_clflush)
-		asm volatile("cli; wbinvd; 1: hlt; jmp 1b" : : : "memory");
-	else
-		while (1)
-			halt();
-}
-
 extern void enable_sep_cpu(void);
 extern int sysenter_setup(void);
 
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index 14e0ed8..231f1c1 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -73,31 +73,31 @@
 
 #define GDT_ENTRY_DEFAULT_USER_DS	15
 
-#define GDT_ENTRY_KERNEL_BASE	12
+#define GDT_ENTRY_KERNEL_BASE		(12)
 
-#define GDT_ENTRY_KERNEL_CS		(GDT_ENTRY_KERNEL_BASE + 0)
+#define GDT_ENTRY_KERNEL_CS		(GDT_ENTRY_KERNEL_BASE+0)
 
-#define GDT_ENTRY_KERNEL_DS		(GDT_ENTRY_KERNEL_BASE + 1)
+#define GDT_ENTRY_KERNEL_DS		(GDT_ENTRY_KERNEL_BASE+1)
 
-#define GDT_ENTRY_TSS			(GDT_ENTRY_KERNEL_BASE + 4)
-#define GDT_ENTRY_LDT			(GDT_ENTRY_KERNEL_BASE + 5)
+#define GDT_ENTRY_TSS			(GDT_ENTRY_KERNEL_BASE+4)
+#define GDT_ENTRY_LDT			(GDT_ENTRY_KERNEL_BASE+5)
 
-#define GDT_ENTRY_PNPBIOS_BASE		(GDT_ENTRY_KERNEL_BASE + 6)
-#define GDT_ENTRY_APMBIOS_BASE		(GDT_ENTRY_KERNEL_BASE + 11)
+#define GDT_ENTRY_PNPBIOS_BASE		(GDT_ENTRY_KERNEL_BASE+6)
+#define GDT_ENTRY_APMBIOS_BASE		(GDT_ENTRY_KERNEL_BASE+11)
 
-#define GDT_ENTRY_ESPFIX_SS		(GDT_ENTRY_KERNEL_BASE + 14)
-#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
+#define GDT_ENTRY_ESPFIX_SS		(GDT_ENTRY_KERNEL_BASE+14)
+#define __ESPFIX_SS			(GDT_ENTRY_ESPFIX_SS*8)
 
-#define GDT_ENTRY_PERCPU			(GDT_ENTRY_KERNEL_BASE + 15)
+#define GDT_ENTRY_PERCPU		(GDT_ENTRY_KERNEL_BASE+15)
 #ifdef CONFIG_SMP
 #define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8)
 #else
 #define __KERNEL_PERCPU 0
 #endif
 
-#define GDT_ENTRY_STACK_CANARY		(GDT_ENTRY_KERNEL_BASE + 16)
+#define GDT_ENTRY_STACK_CANARY		(GDT_ENTRY_KERNEL_BASE+16)
 #ifdef CONFIG_CC_STACKPROTECTOR
-#define __KERNEL_STACK_CANARY		(GDT_ENTRY_STACK_CANARY * 8)
+#define __KERNEL_STACK_CANARY		(GDT_ENTRY_STACK_CANARY*8)
 #else
 #define __KERNEL_STACK_CANARY		0
 #endif
@@ -182,10 +182,10 @@
 
 #endif
 
-#define __KERNEL_CS	(GDT_ENTRY_KERNEL_CS * 8)
-#define __KERNEL_DS	(GDT_ENTRY_KERNEL_DS * 8)
-#define __USER_DS     (GDT_ENTRY_DEFAULT_USER_DS* 8 + 3)
-#define __USER_CS     (GDT_ENTRY_DEFAULT_USER_CS* 8 + 3)
+#define __KERNEL_CS	(GDT_ENTRY_KERNEL_CS*8)
+#define __KERNEL_DS	(GDT_ENTRY_KERNEL_DS*8)
+#define __USER_DS	(GDT_ENTRY_DEFAULT_USER_DS*8+3)
+#define __USER_CS	(GDT_ENTRY_DEFAULT_USER_CS*8+3)
 #ifndef CONFIG_PARAVIRT
 #define get_kernel_rpl()  0
 #endif
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index ef292c7..d6763b139a 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -93,6 +93,11 @@
 			: : "i" (sz));					\
 	}
 
+/* Helper for reserving space for arrays of things */
+#define RESERVE_BRK_ARRAY(type, name, entries)		\
+	type *name;					\
+	RESERVE_BRK(name, sizeof(type) * entries)
+
 #ifdef __i386__
 
 void __init i386_start_kernel(void);
diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
index 8085277..977f176 100644
--- a/arch/x86/include/asm/swiotlb.h
+++ b/arch/x86/include/asm/swiotlb.h
@@ -5,17 +5,26 @@
 
 #ifdef CONFIG_SWIOTLB
 extern int swiotlb;
-extern int __init pci_swiotlb_detect(void);
+extern int __init pci_swiotlb_detect_override(void);
+extern int __init pci_swiotlb_detect_4gb(void);
 extern void __init pci_swiotlb_init(void);
+extern void __init pci_swiotlb_late_init(void);
 #else
 #define swiotlb 0
-static inline int pci_swiotlb_detect(void)
+static inline int pci_swiotlb_detect_override(void)
+{
+	return 0;
+}
+static inline int pci_swiotlb_detect_4gb(void)
 {
 	return 0;
 }
 static inline void pci_swiotlb_init(void)
 {
 }
+static inline void pci_swiotlb_late_init(void)
+{
+}
 #endif
 
 static inline void dma_mark_clean(void *addr, size_t size) {}
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 7f3eba0..169be89 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -172,6 +172,4 @@
 	flush_tlb_all();
 }
 
-extern void zap_low_mappings(bool early);
-
 #endif /* _ASM_X86_TLBFLUSH_H */
diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h
index 4dde797..f4500fb 100644
--- a/arch/x86/include/asm/trampoline.h
+++ b/arch/x86/include/asm/trampoline.h
@@ -13,16 +13,13 @@
 
 extern unsigned long init_rsp;
 extern unsigned long initial_code;
-extern unsigned long initial_page_table;
 extern unsigned long initial_gs;
 
 #define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE)
 
 extern unsigned long setup_trampoline(void);
-extern void __init setup_trampoline_page_table(void);
 extern void __init reserve_trampoline_memory(void);
 #else
-static inline void setup_trampoline_page_table(void) {}
 static inline void reserve_trampoline_memory(void) {}
 #endif /* CONFIG_X86_TRAMPOLINE */
 
diff --git a/arch/x86/include/asm/vmi.h b/arch/x86/include/asm/vmi.h
deleted file mode 100644
index 61e08c0..0000000
--- a/arch/x86/include/asm/vmi.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * VMI interface definition
- *
- * Copyright (C) 2005, VMware, 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Maintained by: Zachary Amsden zach@vmware.com
- *
- */
-#include <linux/types.h>
-
-/*
- *---------------------------------------------------------------------
- *
- *  VMI Option ROM API
- *
- *---------------------------------------------------------------------
- */
-#define VMI_SIGNATURE 0x696d5663   /* "cVmi" */
-
-#define PCI_VENDOR_ID_VMWARE            0x15AD
-#define PCI_DEVICE_ID_VMWARE_VMI        0x0801
-
-/*
- * We use two version numbers for compatibility, with the major
- * number signifying interface breakages, and the minor number
- * interface extensions.
- */
-#define VMI_API_REV_MAJOR       3
-#define VMI_API_REV_MINOR       0
-
-#define VMI_CALL_CPUID			0
-#define VMI_CALL_WRMSR			1
-#define VMI_CALL_RDMSR			2
-#define VMI_CALL_SetGDT			3
-#define VMI_CALL_SetLDT			4
-#define VMI_CALL_SetIDT			5
-#define VMI_CALL_SetTR			6
-#define VMI_CALL_GetGDT			7
-#define VMI_CALL_GetLDT			8
-#define VMI_CALL_GetIDT			9
-#define VMI_CALL_GetTR			10
-#define VMI_CALL_WriteGDTEntry		11
-#define VMI_CALL_WriteLDTEntry		12
-#define VMI_CALL_WriteIDTEntry		13
-#define VMI_CALL_UpdateKernelStack	14
-#define VMI_CALL_SetCR0			15
-#define VMI_CALL_SetCR2			16
-#define VMI_CALL_SetCR3			17
-#define VMI_CALL_SetCR4			18
-#define VMI_CALL_GetCR0			19
-#define VMI_CALL_GetCR2			20
-#define VMI_CALL_GetCR3			21
-#define VMI_CALL_GetCR4			22
-#define VMI_CALL_WBINVD			23
-#define VMI_CALL_SetDR			24
-#define VMI_CALL_GetDR			25
-#define VMI_CALL_RDPMC			26
-#define VMI_CALL_RDTSC			27
-#define VMI_CALL_CLTS			28
-#define VMI_CALL_EnableInterrupts	29
-#define VMI_CALL_DisableInterrupts	30
-#define VMI_CALL_GetInterruptMask	31
-#define VMI_CALL_SetInterruptMask	32
-#define VMI_CALL_IRET			33
-#define VMI_CALL_SYSEXIT		34
-#define VMI_CALL_Halt			35
-#define VMI_CALL_Reboot			36
-#define VMI_CALL_Shutdown		37
-#define VMI_CALL_SetPxE			38
-#define VMI_CALL_SetPxELong		39
-#define VMI_CALL_UpdatePxE		40
-#define VMI_CALL_UpdatePxELong		41
-#define VMI_CALL_MachineToPhysical	42
-#define VMI_CALL_PhysicalToMachine	43
-#define VMI_CALL_AllocatePage		44
-#define VMI_CALL_ReleasePage		45
-#define VMI_CALL_InvalPage		46
-#define VMI_CALL_FlushTLB		47
-#define VMI_CALL_SetLinearMapping	48
-
-#define VMI_CALL_SetIOPLMask		61
-#define VMI_CALL_SetInitialAPState	62
-#define VMI_CALL_APICWrite		63
-#define VMI_CALL_APICRead		64
-#define VMI_CALL_IODelay		65
-#define VMI_CALL_SetLazyMode		73
-
-/*
- *---------------------------------------------------------------------
- *
- * MMU operation flags
- *
- *---------------------------------------------------------------------
- */
-
-/* Flags used by VMI_{Allocate|Release}Page call */
-#define VMI_PAGE_PAE             0x10  /* Allocate PAE shadow */
-#define VMI_PAGE_CLONE           0x20  /* Clone from another shadow */
-#define VMI_PAGE_ZEROED          0x40  /* Page is pre-zeroed */
-
-
-/* Flags shared by Allocate|Release Page and PTE updates */
-#define VMI_PAGE_PT              0x01
-#define VMI_PAGE_PD              0x02
-#define VMI_PAGE_PDP             0x04
-#define VMI_PAGE_PML4            0x08
-
-#define VMI_PAGE_NORMAL          0x00 /* for debugging */
-
-/* Flags used by PTE updates */
-#define VMI_PAGE_CURRENT_AS      0x10 /* implies VMI_PAGE_VA_MASK is valid */
-#define VMI_PAGE_DEFER           0x20 /* may queue update until TLB inval */
-#define VMI_PAGE_VA_MASK         0xfffff000
-
-#ifdef CONFIG_X86_PAE
-#define VMI_PAGE_L1		(VMI_PAGE_PT | VMI_PAGE_PAE | VMI_PAGE_ZEROED)
-#define VMI_PAGE_L2		(VMI_PAGE_PD | VMI_PAGE_PAE | VMI_PAGE_ZEROED)
-#else
-#define VMI_PAGE_L1		(VMI_PAGE_PT | VMI_PAGE_ZEROED)
-#define VMI_PAGE_L2		(VMI_PAGE_PD | VMI_PAGE_ZEROED)
-#endif
-
-/* Flags used by VMI_FlushTLB call */
-#define VMI_FLUSH_TLB            0x01
-#define VMI_FLUSH_GLOBAL         0x02
-
-/*
- *---------------------------------------------------------------------
- *
- *  VMI relocation definitions for ROM call get_reloc
- *
- *---------------------------------------------------------------------
- */
-
-/* VMI Relocation types */
-#define VMI_RELOCATION_NONE     0
-#define VMI_RELOCATION_CALL_REL 1
-#define VMI_RELOCATION_JUMP_REL 2
-#define VMI_RELOCATION_NOP	3
-
-#ifndef __ASSEMBLY__
-struct vmi_relocation_info {
-	unsigned char           *eip;
-	unsigned char           type;
-	unsigned char           reserved[3];
-};
-#endif
-
-
-/*
- *---------------------------------------------------------------------
- *
- *  Generic ROM structures and definitions
- *
- *---------------------------------------------------------------------
- */
-
-#ifndef __ASSEMBLY__
-
-struct vrom_header {
-	u16     rom_signature;  /* option ROM signature */
-	u8      rom_length;     /* ROM length in 512 byte chunks */
-	u8      rom_entry[4];   /* 16-bit code entry point */
-	u8      rom_pad0;       /* 4-byte align pad */
-	u32     vrom_signature; /* VROM identification signature */
-	u8      api_version_min;/* Minor version of API */
-	u8      api_version_maj;/* Major version of API */
-	u8      jump_slots;     /* Number of jump slots */
-	u8      reserved1;      /* Reserved for expansion */
-	u32     virtual_top;    /* Hypervisor virtual address start */
-	u16     reserved2;      /* Reserved for expansion */
-	u16	license_offs;	/* Offset to License string */
-	u16     pci_header_offs;/* Offset to PCI OPROM header */
-	u16     pnp_header_offs;/* Offset to PnP OPROM header */
-	u32     rom_pad3;       /* PnP reserverd / VMI reserved */
-	u8      reserved[96];   /* Reserved for headers */
-	char    vmi_init[8];    /* VMI_Init jump point */
-	char    get_reloc[8];   /* VMI_GetRelocationInfo jump point */
-} __attribute__((packed));
-
-struct pnp_header {
-	char sig[4];
-	char rev;
-	char size;
-	short next;
-	short res;
-	long devID;
-	unsigned short manufacturer_offset;
-	unsigned short product_offset;
-} __attribute__((packed));
-
-struct pci_header {
-	char sig[4];
-	short vendorID;
-	short deviceID;
-	short vpdData;
-	short size;
-	char rev;
-	char class;
-	char subclass;
-	char interface;
-	short chunks;
-	char rom_version_min;
-	char rom_version_maj;
-	char codetype;
-	char lastRom;
-	short reserved;
-} __attribute__((packed));
-
-/* Function prototypes for bootstrapping */
-#ifdef CONFIG_VMI
-extern void vmi_init(void);
-extern void vmi_activate(void);
-extern void vmi_bringup(void);
-#else
-static inline void vmi_init(void) {}
-static inline void vmi_activate(void) {}
-static inline void vmi_bringup(void) {}
-#endif
-
-/* State needed to start an application processor in an SMP system. */
-struct vmi_ap_state {
-	u32 cr0;
-	u32 cr2;
-	u32 cr3;
-	u32 cr4;
-
-	u64 efer;
-
-	u32 eip;
-	u32 eflags;
-	u32 eax;
-	u32 ebx;
-	u32 ecx;
-	u32 edx;
-	u32 esp;
-	u32 ebp;
-	u32 esi;
-	u32 edi;
-	u16 cs;
-	u16 ss;
-	u16 ds;
-	u16 es;
-	u16 fs;
-	u16 gs;
-	u16 ldtr;
-
-	u16 gdtr_limit;
-	u32 gdtr_base;
-	u32 idtr_base;
-	u16 idtr_limit;
-};
-
-#endif
diff --git a/arch/x86/include/asm/vmi_time.h b/arch/x86/include/asm/vmi_time.h
deleted file mode 100644
index c6e0bee..0000000
--- a/arch/x86/include/asm/vmi_time.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * VMI Time wrappers
- *
- * Copyright (C) 2006, VMware, 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to dhecht@vmware.com
- *
- */
-
-#ifndef _ASM_X86_VMI_TIME_H
-#define _ASM_X86_VMI_TIME_H
-
-/*
- * Raw VMI call indices for timer functions
- */
-#define VMI_CALL_GetCycleFrequency	66
-#define VMI_CALL_GetCycleCounter	67
-#define VMI_CALL_SetAlarm		68
-#define VMI_CALL_CancelAlarm		69
-#define VMI_CALL_GetWallclockTime	70
-#define VMI_CALL_WallclockUpdated	71
-
-/* Cached VMI timer operations */
-extern struct vmi_timer_ops {
-	u64 (*get_cycle_frequency)(void);
-	u64 (*get_cycle_counter)(int);
-	u64 (*get_wallclock)(void);
-	int (*wallclock_updated)(void);
-	void (*set_alarm)(u32 flags, u64 expiry, u64 period);
-	void (*cancel_alarm)(u32 flags);
-} vmi_timer_ops;
-
-/* Prototypes */
-extern void __init vmi_time_init(void);
-extern unsigned long vmi_get_wallclock(void);
-extern int vmi_set_wallclock(unsigned long now);
-extern unsigned long long vmi_sched_clock(void);
-extern unsigned long vmi_tsc_khz(void);
-
-#ifdef CONFIG_X86_LOCAL_APIC
-extern void __devinit vmi_time_bsp_init(void);
-extern void __devinit vmi_time_ap_init(void);
-#endif
-
-/*
- * When run under a hypervisor, a vcpu is always in one of three states:
- * running, halted, or ready.  The vcpu is in the 'running' state if it
- * is executing.  When the vcpu executes the halt interface, the vcpu
- * enters the 'halted' state and remains halted until there is some work
- * pending for the vcpu (e.g. an alarm expires, host I/O completes on
- * behalf of virtual I/O).  At this point, the vcpu enters the 'ready'
- * state (waiting for the hypervisor to reschedule it).  Finally, at any
- * time when the vcpu is not in the 'running' state nor the 'halted'
- * state, it is in the 'ready' state.
- *
- * Real time is advances while the vcpu is 'running', 'ready', or
- * 'halted'.  Stolen time is the time in which the vcpu is in the
- * 'ready' state.  Available time is the remaining time -- the vcpu is
- * either 'running' or 'halted'.
- *
- * All three views of time are accessible through the VMI cycle
- * counters.
- */
-
-/* The cycle counters. */
-#define VMI_CYCLES_REAL         0
-#define VMI_CYCLES_AVAILABLE    1
-#define VMI_CYCLES_STOLEN       2
-
-/* The alarm interface 'flags' bits */
-#define VMI_ALARM_COUNTERS      2
-
-#define VMI_ALARM_COUNTER_MASK  0x000000ff
-
-#define VMI_ALARM_WIRED_IRQ0    0x00000000
-#define VMI_ALARM_WIRED_LVTT    0x00010000
-
-#define VMI_ALARM_IS_ONESHOT    0x00000000
-#define VMI_ALARM_IS_PERIODIC   0x00000100
-
-#define CONFIG_VMI_ALARM_HZ	100
-
-#endif /* _ASM_X86_VMI_TIME_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 0925676..2c833d8 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -11,6 +11,8 @@
 CFLAGS_REMOVE_tsc.o = -pg
 CFLAGS_REMOVE_rtc.o = -pg
 CFLAGS_REMOVE_paravirt-spinlocks.o = -pg
+CFLAGS_REMOVE_pvclock.o = -pg
+CFLAGS_REMOVE_kvmclock.o = -pg
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 endif
@@ -32,7 +34,8 @@
 obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
 obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
 obj-y			+= time.o ioport.o ldt.o dumpstack.o
-obj-y			+= setup.o x86_init.o i8259.o irqinit.o
+obj-y			+= setup.o x86_init.o i8259.o irqinit.o jump_label.o
+obj-$(CONFIG_IRQ_WORK)  += irq_work.o
 obj-$(CONFIG_X86_VISWS)	+= visws_quirks.o
 obj-$(CONFIG_X86_32)	+= probe_roms_32.o
 obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o
@@ -42,6 +45,7 @@
 obj-y			+= pci-dma.o quirks.o i8237.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-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
 obj-y				+= process.o
@@ -83,15 +87,15 @@
 obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_VM86)		+= vm86_32.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+obj-$(CONFIG_EARLY_PRINTK_MRST)	+= early_printk_mrst.o
 
 obj-$(CONFIG_HPET_TIMER) 	+= hpet.o
 obj-$(CONFIG_APB_TIMER)		+= apb_timer.o
 
-obj-$(CONFIG_K8_NB)		+= k8.o
+obj-$(CONFIG_AMD_NB)		+= amd_nb.o
 obj-$(CONFIG_DEBUG_RODATA_TEST)	+= test_rodata.o
 obj-$(CONFIG_DEBUG_NX_TEST)	+= test_nx.o
 
-obj-$(CONFIG_VMI)		+= vmi_32.o vmiclock_32.o
 obj-$(CONFIG_KVM_GUEST)		+= kvm.o
 obj-$(CONFIG_KVM_CLOCK)		+= kvmclock.o
 obj-$(CONFIG_PARAVIRT)		+= paravirt.o paravirt_patch_$(BITS).o
@@ -104,6 +108,7 @@
 scx200-y			+= scx200_32.o
 
 obj-$(CONFIG_OLPC)		+= olpc.o
+obj-$(CONFIG_OLPC_XO1)		+= olpc-xo1.o
 obj-$(CONFIG_OLPC_OPENFIRMWARE)	+= olpc_ofw.o
 obj-$(CONFIG_X86_MRST)		+= mrst.o
 
@@ -120,7 +125,6 @@
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
 	obj-$(CONFIG_X86_UV)		+= tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o
-	obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer_64.o
 	obj-$(CONFIG_AUDIT)		+= audit_64.o
 
 	obj-$(CONFIG_GART_IOMMU)	+= pci-gart_64.o aperture_64.o
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index fb7a5f0..5812404 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -13,6 +13,7 @@
 
 #include <acpi/processor.h>
 #include <asm/acpi.h>
+#include <asm/mwait.h>
 
 /*
  * Initialize bm_flags based on the CPU cache properties
@@ -61,20 +62,10 @@
 		unsigned int ecx;
 	} states[ACPI_PROCESSOR_MAX_POWER];
 };
-static struct cstate_entry *cpu_cstate_entry;	/* per CPU ptr */
+static struct cstate_entry __percpu *cpu_cstate_entry;	/* per CPU ptr */
 
 static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
 
-#define MWAIT_SUBSTATE_MASK	(0xf)
-#define MWAIT_CSTATE_MASK	(0xf)
-#define MWAIT_SUBSTATE_SIZE	(4)
-
-#define CPUID_MWAIT_LEAF (5)
-#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
-#define CPUID5_ECX_INTERRUPT_BREAK	(0x2)
-
-#define MWAIT_ECX_INTERRUPT_BREAK	(0x1)
-
 #define NATIVE_CSTATE_BEYOND_HALT	(2)
 
 static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 33cec15..74a84783 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -7,11 +7,17 @@
 
 #include <linux/acpi.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/dmi.h>
 #include <linux/cpumask.h>
 #include <asm/segment.h>
 #include <asm/desc.h>
 
+#ifdef CONFIG_X86_32
+#include <asm/pgtable.h>
+#include <asm/pgtable_32.h>
+#endif
+
 #include "realmode/wakeup.h"
 #include "sleep.h"
 
@@ -90,7 +96,7 @@
 
 #ifndef CONFIG_64BIT
 	header->pmode_entry = (u32)&wakeup_pmode_return;
-	header->pmode_cr3 = (u32)(swsusp_pg_dir - __PAGE_OFFSET);
+	header->pmode_cr3 = (u32)__pa(&initial_page_table);
 	saved_magic = 0x12345678;
 #else /* CONFIG_64BIT */
 	header->trampoline_segment = setup_trampoline() >> 4;
@@ -125,7 +131,7 @@
  */
 void __init acpi_reserve_wakeup_memory(void)
 {
-	unsigned long mem;
+	phys_addr_t mem;
 
 	if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) {
 		printk(KERN_ERR
@@ -133,15 +139,15 @@
 		return;
 	}
 
-	mem = find_e820_area(0, 1<<20, WAKEUP_SIZE, PAGE_SIZE);
+	mem = memblock_find_in_range(0, 1<<20, WAKEUP_SIZE, PAGE_SIZE);
 
-	if (mem == -1L) {
+	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;
-	reserve_early(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP");
+	memblock_x86_reserve_range(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP");
 }
 
 
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index f65ab8b..a36bb90 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -195,7 +195,7 @@
 
 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
 extern s32 __smp_locks[], __smp_locks_end[];
-static void *text_poke_early(void *addr, const void *opcode, size_t len);
+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
@@ -522,7 +522,7 @@
  * instructions. And on the local CPU you need to be protected again NMI or MCE
  * handlers seeing an inconsistent instruction while you patch.
  */
-static void *__init_or_module text_poke_early(void *addr, const void *opcode,
+void *__init_or_module text_poke_early(void *addr, const void *opcode,
 					      size_t len)
 {
 	unsigned long flags;
@@ -637,7 +637,72 @@
 	tpp.len = len;
 	atomic_set(&stop_machine_first, 1);
 	wrote_text = 0;
-	stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
+	/* Use __stop_machine() because the caller already got online_cpus. */
+	__stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
 	return addr;
 }
 
+#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
+
+unsigned char ideal_nop5[IDEAL_NOP_SIZE_5];
+
+void __init arch_init_ideal_nop5(void)
+{
+	extern const unsigned char ftrace_test_p6nop[];
+	extern const unsigned char ftrace_test_nop5[];
+	extern const unsigned char ftrace_test_jmp[];
+	int faulted = 0;
+
+	/*
+	 * There is no good nop for all x86 archs.
+	 * We will default to using the P6_NOP5, but first we
+	 * will test to make sure that the nop will actually
+	 * work on this CPU. If it faults, we will then
+	 * go to a lesser efficient 5 byte nop. If that fails
+	 * we then just use a jmp as our nop. This isn't the most
+	 * efficient nop, but we can not use a multi part nop
+	 * since we would then risk being preempted in the middle
+	 * of that nop, and if we enabled tracing then, it might
+	 * cause a system crash.
+	 *
+	 * TODO: check the cpuid to determine the best nop.
+	 */
+	asm volatile (
+		"ftrace_test_jmp:"
+		"jmp ftrace_test_p6nop\n"
+		"nop\n"
+		"nop\n"
+		"nop\n"  /* 2 byte jmp + 3 bytes */
+		"ftrace_test_p6nop:"
+		P6_NOP5
+		"jmp 1f\n"
+		"ftrace_test_nop5:"
+		".byte 0x66,0x66,0x66,0x66,0x90\n"
+		"1:"
+		".section .fixup, \"ax\"\n"
+		"2:	movl $1, %0\n"
+		"	jmp ftrace_test_nop5\n"
+		"3:	movl $2, %0\n"
+		"	jmp 1b\n"
+		".previous\n"
+		_ASM_EXTABLE(ftrace_test_p6nop, 2b)
+		_ASM_EXTABLE(ftrace_test_nop5, 3b)
+		: "=r"(faulted) : "0" (faulted));
+
+	switch (faulted) {
+	case 0:
+		pr_info("converting mcount calls to 0f 1f 44 00 00\n");
+		memcpy(ideal_nop5, ftrace_test_p6nop, IDEAL_NOP_SIZE_5);
+		break;
+	case 1:
+		pr_info("converting mcount calls to 66 66 66 66 90\n");
+		memcpy(ideal_nop5, ftrace_test_nop5, IDEAL_NOP_SIZE_5);
+		break;
+	case 2:
+		pr_info("converting mcount calls to jmp . + 5\n");
+		memcpy(ideal_nop5, ftrace_test_jmp, IDEAL_NOP_SIZE_5);
+		break;
+	}
+
+}
+#endif
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index fa044e1..d2fdb08 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
@@ -1953,6 +1953,7 @@
 			   size_t size,
 			   int dir)
 {
+	dma_addr_t flush_addr;
 	dma_addr_t i, start;
 	unsigned int pages;
 
@@ -1960,6 +1961,7 @@
 	    (dma_addr + size > dma_dom->aperture_size))
 		return;
 
+	flush_addr = dma_addr;
 	pages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
 	dma_addr &= PAGE_MASK;
 	start = dma_addr;
@@ -1974,7 +1976,7 @@
 	dma_ops_free_addresses(dma_dom, dma_addr, pages);
 
 	if (amd_iommu_unmap_flush || dma_dom->need_flush) {
-		iommu_flush_pages(&dma_dom->domain, dma_addr, size);
+		iommu_flush_pages(&dma_dom->domain, flush_addr, size);
 		dma_dom->need_flush = false;
 	}
 }
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 3cc63e2..6e11c81 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
@@ -31,7 +31,7 @@
 #include <asm/iommu.h>
 #include <asm/gart.h>
 #include <asm/x86_init.h>
-
+#include <asm/iommu_table.h>
 /*
  * definitions for the ACPI scanning code
  */
@@ -194,6 +194,39 @@
 	return 1UL << shift;
 }
 
+/* Access to l1 and l2 indexed register spaces */
+
+static u32 iommu_read_l1(struct amd_iommu *iommu, u16 l1, u8 address)
+{
+	u32 val;
+
+	pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
+	pci_read_config_dword(iommu->dev, 0xfc, &val);
+	return val;
+}
+
+static void iommu_write_l1(struct amd_iommu *iommu, u16 l1, u8 address, u32 val)
+{
+	pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16 | 1 << 31));
+	pci_write_config_dword(iommu->dev, 0xfc, val);
+	pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
+}
+
+static u32 iommu_read_l2(struct amd_iommu *iommu, u8 address)
+{
+	u32 val;
+
+	pci_write_config_dword(iommu->dev, 0xf0, address);
+	pci_read_config_dword(iommu->dev, 0xf4, &val);
+	return val;
+}
+
+static void iommu_write_l2(struct amd_iommu *iommu, u8 address, u32 val)
+{
+	pci_write_config_dword(iommu->dev, 0xf0, (address | 1 << 8));
+	pci_write_config_dword(iommu->dev, 0xf4, val);
+}
+
 /****************************************************************************
  *
  * AMD IOMMU MMIO register space handling functions
@@ -619,6 +652,7 @@
 {
 	int cap_ptr = iommu->cap_ptr;
 	u32 range, misc;
+	int i, j;
 
 	pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
 			      &iommu->cap);
@@ -632,6 +666,30 @@
 	iommu->last_device = calc_devid(MMIO_GET_BUS(range),
 					MMIO_GET_LD(range));
 	iommu->evt_msi_num = MMIO_MSI_NUM(misc);
+
+	if (!is_rd890_iommu(iommu->dev))
+		return;
+
+	/*
+	 * Some rd890 systems may not be fully reconfigured by the BIOS, so
+	 * it's necessary for us to store this information so it can be
+	 * reprogrammed on resume
+	 */
+
+	pci_read_config_dword(iommu->dev, iommu->cap_ptr + 4,
+			      &iommu->stored_addr_lo);
+	pci_read_config_dword(iommu->dev, iommu->cap_ptr + 8,
+			      &iommu->stored_addr_hi);
+
+	/* Low bit locks writes to configuration space */
+	iommu->stored_addr_lo &= ~1;
+
+	for (i = 0; i < 6; i++)
+		for (j = 0; j < 0x12; j++)
+			iommu->stored_l1[i][j] = iommu_read_l1(iommu, i, j);
+
+	for (i = 0; i < 0x83; i++)
+		iommu->stored_l2[i] = iommu_read_l2(iommu, i);
 }
 
 /*
@@ -649,29 +707,9 @@
 	struct ivhd_entry *e;
 
 	/*
-	 * First set the recommended feature enable bits from ACPI
-	 * into the IOMMU control registers
+	 * First save the recommended feature enable bits from ACPI
 	 */
-	h->flags & IVHD_FLAG_HT_TUN_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
-		iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
-
-	h->flags & IVHD_FLAG_PASSPW_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
-		iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
-
-	h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
-		iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
-
-	h->flags & IVHD_FLAG_ISOC_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
-		iommu_feature_disable(iommu, CONTROL_ISOC_EN);
-
-	/*
-	 * make IOMMU memory accesses cache coherent
-	 */
-	iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
+	iommu->acpi_flags = h->flags;
 
 	/*
 	 * Done. Now parse the device entries
@@ -1116,6 +1154,79 @@
 	}
 }
 
+static void iommu_init_flags(struct amd_iommu *iommu)
+{
+	iommu->acpi_flags & IVHD_FLAG_HT_TUN_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
+		iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
+
+	iommu->acpi_flags & IVHD_FLAG_PASSPW_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
+		iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
+
+	iommu->acpi_flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
+		iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
+
+	iommu->acpi_flags & IVHD_FLAG_ISOC_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
+		iommu_feature_disable(iommu, CONTROL_ISOC_EN);
+
+	/*
+	 * make IOMMU memory accesses cache coherent
+	 */
+	iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
+}
+
+static void iommu_apply_resume_quirks(struct amd_iommu *iommu)
+{
+	int i, j;
+	u32 ioc_feature_control;
+	struct pci_dev *pdev = NULL;
+
+	/* RD890 BIOSes may not have completely reconfigured the iommu */
+	if (!is_rd890_iommu(iommu->dev))
+		return;
+
+	/*
+	 * First, we need to ensure that the iommu is enabled. This is
+	 * controlled by a register in the northbridge
+	 */
+	pdev = pci_get_bus_and_slot(iommu->dev->bus->number, PCI_DEVFN(0, 0));
+
+	if (!pdev)
+		return;
+
+	/* Select Northbridge indirect register 0x75 and enable writing */
+	pci_write_config_dword(pdev, 0x60, 0x75 | (1 << 7));
+	pci_read_config_dword(pdev, 0x64, &ioc_feature_control);
+
+	/* Enable the iommu */
+	if (!(ioc_feature_control & 0x1))
+		pci_write_config_dword(pdev, 0x64, ioc_feature_control | 1);
+
+	pci_dev_put(pdev);
+
+	/* Restore the iommu BAR */
+	pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
+			       iommu->stored_addr_lo);
+	pci_write_config_dword(iommu->dev, iommu->cap_ptr + 8,
+			       iommu->stored_addr_hi);
+
+	/* Restore the l1 indirect regs for each of the 6 l1s */
+	for (i = 0; i < 6; i++)
+		for (j = 0; j < 0x12; j++)
+			iommu_write_l1(iommu, i, j, iommu->stored_l1[i][j]);
+
+	/* Restore the l2 indirect regs */
+	for (i = 0; i < 0x83; i++)
+		iommu_write_l2(iommu, i, iommu->stored_l2[i]);
+
+	/* Lock PCI setup registers */
+	pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
+			       iommu->stored_addr_lo | 1);
+}
+
 /*
  * This function finally enables all IOMMUs found in the system after
  * they have been initialized
@@ -1126,6 +1237,7 @@
 
 	for_each_iommu(iommu) {
 		iommu_disable(iommu);
+		iommu_init_flags(iommu);
 		iommu_set_device_table(iommu);
 		iommu_enable_command_buffer(iommu);
 		iommu_enable_event_buffer(iommu);
@@ -1150,6 +1262,11 @@
 
 static int amd_iommu_resume(struct sys_device *dev)
 {
+	struct amd_iommu *iommu;
+
+	for_each_iommu(iommu)
+		iommu_apply_resume_quirks(iommu);
+
 	/* re-load the hardware */
 	enable_iommus();
 
@@ -1382,13 +1499,13 @@
 	return 0;
 }
 
-void __init amd_iommu_detect(void)
+int __init amd_iommu_detect(void)
 {
 	if (no_iommu || (iommu_detected && !gart_iommu_aperture))
-		return;
+		return -ENODEV;
 
 	if (amd_iommu_disabled)
-		return;
+		return -ENODEV;
 
 	if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {
 		iommu_detected = 1;
@@ -1397,7 +1514,9 @@
 
 		/* Make sure ACS will be enabled */
 		pci_request_acs();
+		return 1;
 	}
+	return -ENODEV;
 }
 
 /****************************************************************************
@@ -1428,3 +1547,8 @@
 
 __setup("amd_iommu_dump", parse_amd_iommu_dump);
 __setup("amd_iommu=", parse_amd_iommu_options);
+
+IOMMU_INIT_FINISH(amd_iommu_detect,
+		  gart_iommu_hole_init,
+		  0,
+		  0);
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
new file mode 100644
index 0000000..8f6463d
--- /dev/null
+++ b/arch/x86/kernel/amd_nb.c
@@ -0,0 +1,147 @@
+/*
+ * Shared support code for AMD K8 northbridges and derivates.
+ * Copyright 2006 Andi Kleen, SUSE Labs. Subject to GPLv2.
+ */
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/amd_nb.h>
+
+static u32 *flush_words;
+
+struct pci_device_id k8_nb_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) },
+	{}
+};
+EXPORT_SYMBOL(k8_nb_ids);
+
+struct k8_northbridge_info k8_northbridges;
+EXPORT_SYMBOL(k8_northbridges);
+
+static struct pci_dev *next_k8_northbridge(struct pci_dev *dev)
+{
+	do {
+		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+		if (!dev)
+			break;
+	} while (!pci_match_id(&k8_nb_ids[0], dev));
+	return dev;
+}
+
+int cache_k8_northbridges(void)
+{
+	int i;
+	struct pci_dev *dev;
+
+	if (k8_northbridges.num)
+		return 0;
+
+	dev = NULL;
+	while ((dev = next_k8_northbridge(dev)) != NULL)
+		k8_northbridges.num++;
+
+	/* some CPU families (e.g. family 0x11) do not support GART */
+	if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 ||
+	    boot_cpu_data.x86 == 0x15)
+		k8_northbridges.gart_supported = 1;
+
+	k8_northbridges.nb_misc = kmalloc((k8_northbridges.num + 1) *
+					  sizeof(void *), GFP_KERNEL);
+	if (!k8_northbridges.nb_misc)
+		return -ENOMEM;
+
+	if (!k8_northbridges.num) {
+		k8_northbridges.nb_misc[0] = NULL;
+		return 0;
+	}
+
+	if (k8_northbridges.gart_supported) {
+		flush_words = kmalloc(k8_northbridges.num * sizeof(u32),
+				      GFP_KERNEL);
+		if (!flush_words) {
+			kfree(k8_northbridges.nb_misc);
+			return -ENOMEM;
+		}
+	}
+
+	dev = NULL;
+	i = 0;
+	while ((dev = next_k8_northbridge(dev)) != NULL) {
+		k8_northbridges.nb_misc[i] = dev;
+		if (k8_northbridges.gart_supported)
+			pci_read_config_dword(dev, 0x9c, &flush_words[i++]);
+	}
+	k8_northbridges.nb_misc[i] = NULL;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cache_k8_northbridges);
+
+/* Ignores subdevice/subvendor but as far as I can figure out
+   they're useless anyways */
+int __init early_is_k8_nb(u32 device)
+{
+	struct pci_device_id *id;
+	u32 vendor = device & 0xffff;
+	device >>= 16;
+	for (id = k8_nb_ids; id->vendor; id++)
+		if (vendor == id->vendor && device == id->device)
+			return 1;
+	return 0;
+}
+
+void k8_flush_garts(void)
+{
+	int flushed, i;
+	unsigned long flags;
+	static DEFINE_SPINLOCK(gart_lock);
+
+	if (!k8_northbridges.gart_supported)
+		return;
+
+	/* Avoid races between AGP and IOMMU. In theory it's not needed
+	   but I'm not sure if the hardware won't lose flush requests
+	   when another is pending. This whole thing is so expensive anyways
+	   that it doesn't matter to serialize more. -AK */
+	spin_lock_irqsave(&gart_lock, flags);
+	flushed = 0;
+	for (i = 0; i < k8_northbridges.num; i++) {
+		pci_write_config_dword(k8_northbridges.nb_misc[i], 0x9c,
+				       flush_words[i]|1);
+		flushed++;
+	}
+	for (i = 0; i < k8_northbridges.num; i++) {
+		u32 w;
+		/* Make sure the hardware actually executed the flush*/
+		for (;;) {
+			pci_read_config_dword(k8_northbridges.nb_misc[i],
+					      0x9c, &w);
+			if (!(w & 1))
+				break;
+			cpu_relax();
+		}
+	}
+	spin_unlock_irqrestore(&gart_lock, flags);
+	if (!flushed)
+		printk("nothing to flush?\n");
+}
+EXPORT_SYMBOL_GPL(k8_flush_garts);
+
+static __init int init_k8_nbs(void)
+{
+	int err = 0;
+
+	err = cache_k8_northbridges();
+
+	if (err < 0)
+		printk(KERN_NOTICE "K8 NB: Cannot enumerate AMD northbridges.\n");
+
+	return err;
+}
+
+/* This has to go after the PCI subsystem */
+fs_initcall(init_k8_nbs);
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index 8dd7780..92543c7 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -231,34 +231,6 @@
 	apbt_start_counter(phy_cs_timer_id);
 }
 
-/* Setup IRQ routing via IOAPIC */
-#ifdef CONFIG_SMP
-static void apbt_setup_irq(struct apbt_dev *adev)
-{
-	struct irq_chip *chip;
-	struct irq_desc *desc;
-
-	/* timer0 irq has been setup early */
-	if (adev->irq == 0)
-		return;
-	desc = irq_to_desc(adev->irq);
-	chip = get_irq_chip(adev->irq);
-	disable_irq(adev->irq);
-	desc->status |= IRQ_MOVE_PCNTXT;
-	irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
-	/* APB timer irqs are set up as mp_irqs, timer is edge triggerred */
-	set_irq_chip_and_handler_name(adev->irq, chip, handle_edge_irq, "edge");
-	enable_irq(adev->irq);
-	if (system_state == SYSTEM_BOOTING)
-		if (request_irq(adev->irq, apbt_interrupt_handler,
-				IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
-				adev->name, adev)) {
-			printk(KERN_ERR "Failed request IRQ for APBT%d\n",
-			       adev->num);
-		}
-}
-#endif
-
 static void apbt_enable_int(int n)
 {
 	unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
@@ -334,6 +306,27 @@
 }
 
 #ifdef CONFIG_SMP
+
+static void apbt_setup_irq(struct apbt_dev *adev)
+{
+	/* timer0 irq has been setup early */
+	if (adev->irq == 0)
+		return;
+
+	if (system_state == SYSTEM_BOOTING) {
+		irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
+		/* APB timer irqs are set up as mp_irqs, timer is edge type */
+		__set_irq_handler(adev->irq, handle_edge_irq, 0, "edge");
+		if (request_irq(adev->irq, apbt_interrupt_handler,
+				IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
+				adev->name, adev)) {
+			printk(KERN_ERR "Failed request IRQ for APBT%d\n",
+			       adev->num);
+		}
+	} else
+		enable_irq(adev->irq);
+}
+
 /* Should be called with per cpu */
 void apbt_setup_secondary_clock(void)
 {
@@ -343,7 +336,7 @@
 
 	/* Don't register boot CPU clockevent */
 	cpu = smp_processor_id();
-	if (cpu == boot_cpu_id)
+	if (!cpu)
 		return;
 	/*
 	 * We need to calculate the scaled math multiplication factor for
@@ -389,16 +382,17 @@
 
 	switch (action & 0xf) {
 	case CPU_DEAD:
+		disable_irq(adev->irq);
 		apbt_disable_int(cpu);
-		if (system_state == SYSTEM_RUNNING)
+		if (system_state == SYSTEM_RUNNING) {
 			pr_debug("skipping APBT CPU %lu offline\n", cpu);
-		else if (adev) {
+		} else if (adev) {
 			pr_debug("APBT clockevent for cpu %lu offline\n", cpu);
 			free_irq(adev->irq, adev);
 		}
 		break;
 	default:
-		pr_debug(KERN_INFO "APBT notified %lu, no action\n", action);
+		pr_debug("APBT notified %lu, no action\n", action);
 	}
 	return NOTIFY_OK;
 }
@@ -552,7 +546,7 @@
 		pr_debug("APB CS going back %lx:%lx:%lx ",
 			 t2, last_read, t2 - last_read);
 bad_count_x3:
-		pr_debug(KERN_INFO "tripple check enforced\n");
+		pr_debug("triple check enforced\n");
 		t0 = apbt_readl(phy_cs_timer_id,
 				APBTMR_N_CURRENT_VALUE);
 		udelay(1);
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index a2e0caf..b3a16e8 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -27,7 +27,7 @@
 #include <asm/gart.h>
 #include <asm/pci-direct.h>
 #include <asm/dma.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 #include <asm/x86_init.h>
 
 int gart_iommu_aperture;
@@ -307,7 +307,7 @@
 				continue;
 
 			ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL);
-			aper_enabled = ctl & AMD64_GARTEN;
+			aper_enabled = ctl & GARTEN;
 			aper_order = (ctl >> 1) & 7;
 			aper_size = (32 * 1024 * 1024) << aper_order;
 			aper_base = read_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE) & 0x7fff;
@@ -362,7 +362,7 @@
 				continue;
 
 			ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL);
-			ctl &= ~AMD64_GARTEN;
+			ctl &= ~GARTEN;
 			write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl);
 		}
 	}
@@ -371,7 +371,7 @@
 
 static int __initdata printed_gart_size_msg;
 
-void __init gart_iommu_hole_init(void)
+int __init gart_iommu_hole_init(void)
 {
 	u32 agp_aper_base = 0, agp_aper_order = 0;
 	u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
@@ -381,7 +381,7 @@
 
 	if (gart_iommu_aperture_disabled || !fix_aperture ||
 	    !early_pci_allowed())
-		return;
+		return -ENODEV;
 
 	printk(KERN_INFO  "Checking aperture...\n");
 
@@ -463,8 +463,9 @@
 			unsigned long n = (32 * 1024 * 1024) << last_aper_order;
 
 			insert_aperture_resource((u32)last_aper_base, n);
+			return 1;
 		}
-		return;
+		return 0;
 	}
 
 	if (!fallback_aper_force) {
@@ -500,13 +501,18 @@
 			panic("Not enough memory for aperture");
 		}
 	} else {
-		return;
+		return 0;
 	}
 
 	/* Fix up the north bridges */
 	for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) {
-		int bus;
-		int dev_base, dev_limit;
+		int bus, dev_base, dev_limit;
+
+		/*
+		 * Don't enable translation yet but enable GART IO and CPU
+		 * accesses and set DISTLBWALKPRB since GART table memory is UC.
+		 */
+		u32 ctl = DISTLBWALKPRB | aper_order << 1;
 
 		bus = bus_dev_ranges[i].bus;
 		dev_base = bus_dev_ranges[i].dev_base;
@@ -515,13 +521,12 @@
 			if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00)))
 				continue;
 
-			/* Don't enable translation yet. That is done later.
-			   Assume this BIOS didn't initialise the GART so
-			   just overwrite all previous bits */
-			write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, aper_order << 1);
+			write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl);
 			write_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE, aper_alloc >> 25);
 		}
 	}
 
 	set_up_gart_resume(aper_order, aper_alloc);
+
+	return 1;
 }
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index e3b534c..850657d 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -52,6 +52,7 @@
 #include <asm/mce.h>
 #include <asm/kvm_para.h>
 #include <asm/tsc.h>
+#include <asm/atomic.h>
 
 unsigned int num_processors;
 
@@ -370,38 +371,87 @@
 }
 
 /*
- * Setup extended LVT, AMD specific (K8, family 10h)
+ * Setup extended LVT, AMD specific
  *
- * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
- * MCE interrupts are supported. Thus MCE offset must be set to 0.
+ * Software should use the LVT offsets the BIOS provides.  The offsets
+ * are determined by the subsystems using it like those for MCE
+ * threshold or IBS.  On K8 only offset 0 (APIC500) and MCE interrupts
+ * are supported. Beginning with family 10h at least 4 offsets are
+ * available.
  *
+ * Since the offsets must be consistent for all cores, we keep track
+ * of the LVT offsets in software and reserve the offset for the same
+ * vector also to be used on other cores. An offset is freed by
+ * setting the entry to APIC_EILVT_MASKED.
+ *
+ * If the BIOS is right, there should be no conflicts. Otherwise a
+ * "[Firmware Bug]: ..." error message is generated. However, if
+ * software does not properly determines the offsets, it is not
+ * necessarily a BIOS bug.
+ */
+
+static atomic_t eilvt_offsets[APIC_EILVT_NR_MAX];
+
+static inline int eilvt_entry_is_changeable(unsigned int old, unsigned int new)
+{
+	return (old & APIC_EILVT_MASKED)
+		|| (new == APIC_EILVT_MASKED)
+		|| ((new & ~APIC_EILVT_MASKED) == old);
+}
+
+static unsigned int reserve_eilvt_offset(int offset, unsigned int new)
+{
+	unsigned int rsvd;			/* 0: uninitialized */
+
+	if (offset >= APIC_EILVT_NR_MAX)
+		return ~0;
+
+	rsvd = atomic_read(&eilvt_offsets[offset]) & ~APIC_EILVT_MASKED;
+	do {
+		if (rsvd &&
+		    !eilvt_entry_is_changeable(rsvd, new))
+			/* may not change if vectors are different */
+			return rsvd;
+		rsvd = atomic_cmpxchg(&eilvt_offsets[offset], rsvd, new);
+	} while (rsvd != new);
+
+	return new;
+}
+
+/*
  * If mask=1, the LVT entry does not generate interrupts while mask=0
  * enables the vector. See also the BKDGs.
  */
 
-#define APIC_EILVT_LVTOFF_MCE 0
-#define APIC_EILVT_LVTOFF_IBS 1
-
-static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
+int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask)
 {
-	unsigned long reg = (lvt_off << 4) + APIC_EILVTn(0);
-	unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
+	unsigned long reg = APIC_EILVTn(offset);
+	unsigned int new, old, reserved;
 
-	apic_write(reg, v);
-}
+	new = (mask << 16) | (msg_type << 8) | vector;
+	old = apic_read(reg);
+	reserved = reserve_eilvt_offset(offset, new);
 
-u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask)
-{
-	setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask);
-	return APIC_EILVT_LVTOFF_MCE;
-}
+	if (reserved != new) {
+		pr_err(FW_BUG "cpu %d, try to setup vector 0x%x, but "
+		       "vector 0x%x was already reserved by another core, "
+		       "APIC%lX=0x%x\n",
+		       smp_processor_id(), new, reserved, reg, old);
+		return -EINVAL;
+	}
 
-u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
-{
-	setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask);
-	return APIC_EILVT_LVTOFF_IBS;
+	if (!eilvt_entry_is_changeable(old, new)) {
+		pr_err(FW_BUG "cpu %d, try to setup vector 0x%x but "
+		       "register already in use, APIC%lX=0x%x\n",
+		       smp_processor_id(), new, reg, old);
+		return -EBUSY;
+	}
+
+	apic_write(reg, new);
+
+	return 0;
 }
-EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs);
+EXPORT_SYMBOL_GPL(setup_APIC_eilvt);
 
 /*
  * Program the next event, relative to now
@@ -1665,10 +1715,7 @@
 	}
 #endif
 
-#ifndef CONFIG_SMP
-	enable_IR_x2apic();
 	default_setup_apic_routing();
-#endif
 
 	verify_local_APIC();
 	connect_bsp_APIC();
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index f1efeba..8ae808d 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -131,13 +131,9 @@
 	struct irq_pin_list *next;
 };
 
-static struct irq_pin_list *get_one_free_irq_2_pin(int node)
+static struct irq_pin_list *alloc_irq_pin_list(int node)
 {
-	struct irq_pin_list *pin;
-
-	pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node);
-
-	return pin;
+	return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
 }
 
 /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
@@ -150,10 +146,7 @@
 int __init arch_early_irq_init(void)
 {
 	struct irq_cfg *cfg;
-	struct irq_desc *desc;
-	int count;
-	int node;
-	int i;
+	int count, node, i;
 
 	if (!legacy_pic->nr_legacy_irqs) {
 		nr_irqs_gsi = 0;
@@ -162,13 +155,15 @@
 
 	cfg = irq_cfgx;
 	count = ARRAY_SIZE(irq_cfgx);
-	node= cpu_to_node(boot_cpu_id);
+	node = cpu_to_node(0);
+
+	/* Make sure the legacy interrupts are marked in the bitmap */
+	irq_reserve_irqs(0, legacy_pic->nr_legacy_irqs);
 
 	for (i = 0; i < count; i++) {
-		desc = irq_to_desc(i);
-		desc->chip_data = &cfg[i];
-		zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
-		zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);
+		set_irq_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);
 		/*
 		 * For legacy IRQ's, start with assigning irq0 to irq15 to
 		 * IRQ0_VECTOR to IRQ15_VECTOR on cpu 0.
@@ -183,165 +178,88 @@
 }
 
 #ifdef CONFIG_SPARSE_IRQ
-struct irq_cfg *irq_cfg(unsigned int irq)
+static struct irq_cfg *irq_cfg(unsigned int irq)
 {
-	struct irq_cfg *cfg = NULL;
-	struct irq_desc *desc;
+	return get_irq_chip_data(irq);
+}
 
-	desc = irq_to_desc(irq);
-	if (desc)
-		cfg = desc->chip_data;
+static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node)
+{
+	struct irq_cfg *cfg;
 
+	cfg = kzalloc_node(sizeof(*cfg), GFP_KERNEL, node);
+	if (!cfg)
+		return NULL;
+	if (!zalloc_cpumask_var_node(&cfg->domain, GFP_KERNEL, node))
+		goto out_cfg;
+	if (!zalloc_cpumask_var_node(&cfg->old_domain, GFP_KERNEL, node))
+		goto out_domain;
 	return cfg;
+out_domain:
+	free_cpumask_var(cfg->domain);
+out_cfg:
+	kfree(cfg);
+	return NULL;
 }
 
-static struct irq_cfg *get_one_free_irq_cfg(int node)
+static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg)
 {
-	struct irq_cfg *cfg;
-
-	cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
-	if (cfg) {
-		if (!zalloc_cpumask_var_node(&cfg->domain, GFP_ATOMIC, node)) {
-			kfree(cfg);
-			cfg = NULL;
-		} else if (!zalloc_cpumask_var_node(&cfg->old_domain,
-							  GFP_ATOMIC, node)) {
-			free_cpumask_var(cfg->domain);
-			kfree(cfg);
-			cfg = NULL;
-		}
-	}
-
-	return cfg;
-}
-
-int arch_init_chip_data(struct irq_desc *desc, int node)
-{
-	struct irq_cfg *cfg;
-
-	cfg = desc->chip_data;
-	if (!cfg) {
-		desc->chip_data = get_one_free_irq_cfg(node);
-		if (!desc->chip_data) {
-			printk(KERN_ERR "can not alloc irq_cfg\n");
-			BUG_ON(1);
-		}
-	}
-
-	return 0;
-}
-
-/* for move_irq_desc */
-static void
-init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int node)
-{
-	struct irq_pin_list *old_entry, *head, *tail, *entry;
-
-	cfg->irq_2_pin = NULL;
-	old_entry = old_cfg->irq_2_pin;
-	if (!old_entry)
-		return;
-
-	entry = get_one_free_irq_2_pin(node);
-	if (!entry)
-		return;
-
-	entry->apic	= old_entry->apic;
-	entry->pin	= old_entry->pin;
-	head		= entry;
-	tail		= entry;
-	old_entry	= old_entry->next;
-	while (old_entry) {
-		entry = get_one_free_irq_2_pin(node);
-		if (!entry) {
-			entry = head;
-			while (entry) {
-				head = entry->next;
-				kfree(entry);
-				entry = head;
-			}
-			/* still use the old one */
-			return;
-		}
-		entry->apic	= old_entry->apic;
-		entry->pin	= old_entry->pin;
-		tail->next	= entry;
-		tail		= entry;
-		old_entry	= old_entry->next;
-	}
-
-	tail->next = NULL;
-	cfg->irq_2_pin = head;
-}
-
-static void free_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg)
-{
-	struct irq_pin_list *entry, *next;
-
-	if (old_cfg->irq_2_pin == cfg->irq_2_pin)
-		return;
-
-	entry = old_cfg->irq_2_pin;
-
-	while (entry) {
-		next = entry->next;
-		kfree(entry);
-		entry = next;
-	}
-	old_cfg->irq_2_pin = NULL;
-}
-
-void arch_init_copy_chip_data(struct irq_desc *old_desc,
-				 struct irq_desc *desc, int node)
-{
-	struct irq_cfg *cfg;
-	struct irq_cfg *old_cfg;
-
-	cfg = get_one_free_irq_cfg(node);
-
 	if (!cfg)
 		return;
-
-	desc->chip_data = cfg;
-
-	old_cfg = old_desc->chip_data;
-
-	memcpy(cfg, old_cfg, sizeof(struct irq_cfg));
-
-	init_copy_irq_2_pin(old_cfg, cfg, node);
+	set_irq_chip_data(at, NULL);
+	free_cpumask_var(cfg->domain);
+	free_cpumask_var(cfg->old_domain);
+	kfree(cfg);
 }
 
-static void free_irq_cfg(struct irq_cfg *old_cfg)
-{
-	kfree(old_cfg);
-}
-
-void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
-{
-	struct irq_cfg *old_cfg, *cfg;
-
-	old_cfg = old_desc->chip_data;
-	cfg = desc->chip_data;
-
-	if (old_cfg == cfg)
-		return;
-
-	if (old_cfg) {
-		free_irq_2_pin(old_cfg, cfg);
-		free_irq_cfg(old_cfg);
-		old_desc->chip_data = NULL;
-	}
-}
-/* end for move_irq_desc */
-
 #else
+
 struct irq_cfg *irq_cfg(unsigned int irq)
 {
 	return irq < nr_irqs ? irq_cfgx + irq : NULL;
 }
 
+static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node)
+{
+	return irq_cfgx + irq;
+}
+
+static inline void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) { }
+
 #endif
 
+static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
+{
+	int res = irq_alloc_desc_at(at, node);
+	struct irq_cfg *cfg;
+
+	if (res < 0) {
+		if (res != -EEXIST)
+			return NULL;
+		cfg = get_irq_chip_data(at);
+		if (cfg)
+			return cfg;
+	}
+
+	cfg = alloc_irq_cfg(at, node);
+	if (cfg)
+		set_irq_chip_data(at, cfg);
+	else
+		irq_free_desc(at);
+	return cfg;
+}
+
+static int alloc_irq_from(unsigned int from, int node)
+{
+	return irq_alloc_desc_from(from, node);
+}
+
+static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
+{
+	free_irq_cfg(at, cfg);
+	irq_free_desc(at);
+}
+
 struct io_apic {
 	unsigned int index;
 	unsigned int unused[3];
@@ -446,7 +364,7 @@
 	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
 }
 
-void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
 {
 	unsigned long flags;
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
@@ -476,7 +394,7 @@
  * fast in the common case, and fast for shared ISA-space IRQs.
  */
 static int
-add_pin_to_irq_node_nopanic(struct irq_cfg *cfg, int node, int apic, int pin)
+__add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
 {
 	struct irq_pin_list **last, *entry;
 
@@ -488,7 +406,7 @@
 		last = &entry->next;
 	}
 
-	entry = get_one_free_irq_2_pin(node);
+	entry = alloc_irq_pin_list(node);
 	if (!entry) {
 		printk(KERN_ERR "can not alloc irq_pin_list (%d,%d,%d)\n",
 				node, apic, pin);
@@ -503,7 +421,7 @@
 
 static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
 {
-	if (add_pin_to_irq_node_nopanic(cfg, node, apic, pin))
+	if (__add_pin_to_irq_node(cfg, node, apic, pin))
 		panic("IO-APIC: failed to add irq-pin. Can not proceed\n");
 }
 
@@ -566,11 +484,6 @@
 			     IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
 }
 
-static void __unmask_IO_APIC_irq(struct irq_cfg *cfg)
-{
-	io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL);
-}
-
 static void io_apic_sync(struct irq_pin_list *entry)
 {
 	/*
@@ -582,44 +495,37 @@
 	readl(&io_apic->data);
 }
 
-static void __mask_IO_APIC_irq(struct irq_cfg *cfg)
+static void mask_ioapic(struct irq_cfg *cfg)
 {
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
-}
-
-static void mask_IO_APIC_irq_desc(struct irq_desc *desc)
-{
-	struct irq_cfg *cfg = desc->chip_data;
-	unsigned long flags;
-
-	BUG_ON(!cfg);
-
-	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	__mask_IO_APIC_irq(cfg);
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
-static void unmask_IO_APIC_irq_desc(struct irq_desc *desc)
+static void mask_ioapic_irq(struct irq_data *data)
 {
-	struct irq_cfg *cfg = desc->chip_data;
+	mask_ioapic(data->chip_data);
+}
+
+static void __unmask_ioapic(struct irq_cfg *cfg)
+{
+	io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL);
+}
+
+static void unmask_ioapic(struct irq_cfg *cfg)
+{
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	__unmask_IO_APIC_irq(cfg);
+	__unmask_ioapic(cfg);
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
-static void mask_IO_APIC_irq(unsigned int irq)
+static void unmask_ioapic_irq(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	mask_IO_APIC_irq_desc(desc);
-}
-static void unmask_IO_APIC_irq(unsigned int irq)
-{
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	unmask_IO_APIC_irq_desc(desc);
+	unmask_ioapic(data->chip_data);
 }
 
 static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
@@ -689,14 +595,14 @@
 	struct IO_APIC_route_entry **ioapic_entries;
 
 	ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
-				GFP_ATOMIC);
+				GFP_KERNEL);
 	if (!ioapic_entries)
 		return 0;
 
 	for (apic = 0; apic < nr_ioapics; apic++) {
 		ioapic_entries[apic] =
 			kzalloc(sizeof(struct IO_APIC_route_entry) *
-				nr_ioapic_registers[apic], GFP_ATOMIC);
+				nr_ioapic_registers[apic], GFP_KERNEL);
 		if (!ioapic_entries[apic])
 			goto nomem;
 	}
@@ -1254,7 +1160,6 @@
 	/* Initialize vector_irq on a new cpu */
 	int irq, vector;
 	struct irq_cfg *cfg;
-	struct irq_desc *desc;
 
 	/*
 	 * vector_lock will make sure that we don't run into irq vector
@@ -1263,9 +1168,10 @@
 	 */
 	raw_spin_lock(&vector_lock);
 	/* Mark the inuse vectors */
-	for_each_irq_desc(irq, desc) {
-		cfg = desc->chip_data;
-
+	for_each_active_irq(irq) {
+		cfg = get_irq_chip_data(irq);
+		if (!cfg)
+			continue;
 		/*
 		 * If it is a legacy IRQ handled by the legacy PIC, this cpu
 		 * will be part of the irq_cfg's domain.
@@ -1322,17 +1228,17 @@
 }
 #endif
 
-static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long trigger)
+static void ioapic_register_intr(unsigned int irq, unsigned long trigger)
 {
 
 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
 	    trigger == IOAPIC_LEVEL)
-		desc->status |= IRQ_LEVEL;
+		irq_set_status_flags(irq, IRQ_LEVEL);
 	else
-		desc->status &= ~IRQ_LEVEL;
+		irq_clear_status_flags(irq, IRQ_LEVEL);
 
-	if (irq_remapped(irq)) {
-		desc->status |= IRQ_MOVE_PCNTXT;
+	if (irq_remapped(get_irq_chip_data(irq))) {
+		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
 		if (trigger)
 			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
 						      handle_fasteoi_irq,
@@ -1353,10 +1259,10 @@
 					      handle_edge_irq, "edge");
 }
 
-int setup_ioapic_entry(int apic_id, int irq,
-		       struct IO_APIC_route_entry *entry,
-		       unsigned int destination, int trigger,
-		       int polarity, int vector, int pin)
+static int setup_ioapic_entry(int apic_id, int irq,
+			      struct IO_APIC_route_entry *entry,
+			      unsigned int destination, int trigger,
+			      int polarity, int vector, int pin)
 {
 	/*
 	 * add it to the IO-APIC irq-routing table:
@@ -1377,21 +1283,7 @@
 		if (index < 0)
 			panic("Failed to allocate IRTE for ioapic %d\n", apic_id);
 
-		memset(&irte, 0, sizeof(irte));
-
-		irte.present = 1;
-		irte.dst_mode = apic->irq_dest_mode;
-		/*
-		 * Trigger mode in the IRTE will always be edge, and the
-		 * actual level or edge trigger will be setup in the IO-APIC
-		 * RTE. This will help simplify level triggered irq migration.
-		 * For more details, see the comments above explainig IO-APIC
-		 * irq migration in the presence of interrupt-remapping.
-		 */
-		irte.trigger_mode = 0;
-		irte.dlvry_mode = apic->irq_delivery_mode;
-		irte.vector = vector;
-		irte.dest_id = IRTE_DEST(destination);
+		prepare_irte(&irte, vector, destination);
 
 		/* Set source-id of interrupt request */
 		set_ioapic_sid(&irte, apic_id);
@@ -1426,18 +1318,14 @@
 	return 0;
 }
 
-static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq_desc *desc,
-			      int trigger, int polarity)
+static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
+			     struct irq_cfg *cfg, int trigger, int polarity)
 {
-	struct irq_cfg *cfg;
 	struct IO_APIC_route_entry entry;
 	unsigned int dest;
 
 	if (!IO_APIC_IRQ(irq))
 		return;
-
-	cfg = desc->chip_data;
-
 	/*
 	 * For legacy irqs, cfg->domain starts with cpu 0 for legacy
 	 * controllers like 8259. Now that IO-APIC can handle this irq, update
@@ -1466,9 +1354,9 @@
 		return;
 	}
 
-	ioapic_register_intr(irq, desc, trigger);
+	ioapic_register_intr(irq, trigger);
 	if (irq < legacy_pic->nr_legacy_irqs)
-		legacy_pic->chip->mask(irq);
+		legacy_pic->mask(irq);
 
 	ioapic_write_entry(apic_id, pin, entry);
 }
@@ -1479,11 +1367,9 @@
 
 static void __init setup_IO_APIC_irqs(void)
 {
-	int apic_id, pin, idx, irq;
-	int notcon = 0;
-	struct irq_desc *desc;
+	int apic_id, pin, idx, irq, notcon = 0;
+	int node = cpu_to_node(0);
 	struct irq_cfg *cfg;
-	int node = cpu_to_node(boot_cpu_id);
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
@@ -1520,19 +1406,17 @@
 				apic->multi_timer_check(apic_id, irq))
 			continue;
 
-		desc = irq_to_desc_alloc_node(irq, node);
-		if (!desc) {
-			printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+		cfg = alloc_irq_and_cfg_at(irq, node);
+		if (!cfg)
 			continue;
-		}
-		cfg = desc->chip_data;
+
 		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_IO_APIC_irq(apic_id, pin, irq, desc,
-				irq_trigger(idx), irq_polarity(idx));
+		setup_ioapic_irq(apic_id, pin, irq, cfg, irq_trigger(idx),
+				  irq_polarity(idx));
 	}
 
 	if (notcon)
@@ -1547,9 +1431,7 @@
  */
 void setup_IO_APIC_irq_extra(u32 gsi)
 {
-	int apic_id = 0, pin, idx, irq;
-	int node = cpu_to_node(boot_cpu_id);
-	struct irq_desc *desc;
+	int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
 	struct irq_cfg *cfg;
 
 	/*
@@ -1565,18 +1447,15 @@
 		return;
 
 	irq = pin_2_irq(idx, apic_id, pin);
-#ifdef CONFIG_SPARSE_IRQ
-	desc = irq_to_desc(irq);
-	if (desc)
-		return;
-#endif
-	desc = irq_to_desc_alloc_node(irq, node);
-	if (!desc) {
-		printk(KERN_INFO "can not get irq_desc for %d\n", irq);
-		return;
-	}
 
-	cfg = desc->chip_data;
+	/* Only handle the non legacy irqs on secondary ioapics */
+	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)) {
@@ -1586,7 +1465,7 @@
 	}
 	set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
 
-	setup_IO_APIC_irq(apic_id, pin, irq, desc,
+	setup_ioapic_irq(apic_id, pin, irq, cfg,
 			irq_trigger(idx), irq_polarity(idx));
 }
 
@@ -1637,7 +1516,6 @@
 	union IO_APIC_reg_03 reg_03;
 	unsigned long flags;
 	struct irq_cfg *cfg;
-	struct irq_desc *desc;
 	unsigned int irq;
 
 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
@@ -1724,10 +1602,10 @@
 	}
 	}
 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
-	for_each_irq_desc(irq, desc) {
+	for_each_active_irq(irq) {
 		struct irq_pin_list *entry;
 
-		cfg = desc->chip_data;
+		cfg = get_irq_chip_data(irq);
 		if (!cfg)
 			continue;
 		entry = cfg->irq_2_pin;
@@ -2234,29 +2112,26 @@
  * an edge even if it isn't on the 8259A...
  */
 
-static unsigned int startup_ioapic_irq(unsigned int irq)
+static unsigned int startup_ioapic_irq(struct irq_data *data)
 {
-	int was_pending = 0;
+	int was_pending = 0, irq = data->irq;
 	unsigned long flags;
-	struct irq_cfg *cfg;
 
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	if (irq < legacy_pic->nr_legacy_irqs) {
-		legacy_pic->chip->mask(irq);
+		legacy_pic->mask(irq);
 		if (legacy_pic->irq_pending(irq))
 			was_pending = 1;
 	}
-	cfg = irq_cfg(irq);
-	__unmask_IO_APIC_irq(cfg);
+	__unmask_ioapic(data->chip_data);
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	return was_pending;
 }
 
-static int ioapic_retrigger_irq(unsigned int irq)
+static int ioapic_retrigger_irq(struct irq_data *data)
 {
-
-	struct irq_cfg *cfg = irq_cfg(irq);
+	struct irq_cfg *cfg = data->chip_data;
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&vector_lock, flags);
@@ -2307,7 +2182,7 @@
 		 * With interrupt-remapping, destination information comes
 		 * from interrupt-remapping table entry.
 		 */
-		if (!irq_remapped(irq))
+		if (!irq_remapped(cfg))
 			io_apic_write(apic, 0x11 + pin*2, dest);
 		reg = io_apic_read(apic, 0x10 + pin*2);
 		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
@@ -2317,65 +2192,46 @@
 }
 
 /*
- * Either sets desc->affinity to a valid value, and returns
+ * Either sets data->affinity to a valid value, and returns
  * ->cpu_mask_to_apicid of that in dest_id, or returns -1 and
- * leaves desc->affinity untouched.
+ * leaves data->affinity untouched.
  */
-unsigned int
-set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask,
-		  unsigned int *dest_id)
+int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+			  unsigned int *dest_id)
 {
-	struct irq_cfg *cfg;
-	unsigned int irq;
+	struct irq_cfg *cfg = data->chip_data;
 
 	if (!cpumask_intersects(mask, cpu_online_mask))
 		return -1;
 
-	irq = desc->irq;
-	cfg = desc->chip_data;
-	if (assign_irq_vector(irq, cfg, mask))
+	if (assign_irq_vector(data->irq, data->chip_data, mask))
 		return -1;
 
-	cpumask_copy(desc->affinity, mask);
+	cpumask_copy(data->affinity, mask);
 
-	*dest_id = apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+	*dest_id = apic->cpu_mask_to_apicid_and(mask, cfg->domain);
 	return 0;
 }
 
 static int
-set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+		    bool force)
 {
-	struct irq_cfg *cfg;
+	unsigned int dest, irq = data->irq;
 	unsigned long flags;
-	unsigned int dest;
-	unsigned int irq;
-	int ret = -1;
-
-	irq = desc->irq;
-	cfg = desc->chip_data;
+	int ret;
 
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	ret = set_desc_affinity(desc, mask, &dest);
+	ret = __ioapic_set_affinity(data, mask, &dest);
 	if (!ret) {
 		/* Only the high 8 bits are valid. */
 		dest = SET_APIC_LOGICAL_ID(dest);
-		__target_IO_APIC_irq(irq, dest, cfg);
+		__target_IO_APIC_irq(irq, dest, data->chip_data);
 	}
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-
 	return ret;
 }
 
-static int
-set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
-{
-	struct irq_desc *desc;
-
-	desc = irq_to_desc(irq);
-
-	return set_ioapic_affinity_irq_desc(desc, mask);
-}
-
 #ifdef CONFIG_INTR_REMAP
 
 /*
@@ -2390,24 +2246,21 @@
  * the interrupt-remapping table entry.
  */
 static int
-migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+		       bool force)
 {
-	struct irq_cfg *cfg;
+	struct irq_cfg *cfg = data->chip_data;
+	unsigned int dest, irq = data->irq;
 	struct irte irte;
-	unsigned int dest;
-	unsigned int irq;
-	int ret = -1;
 
 	if (!cpumask_intersects(mask, cpu_online_mask))
-		return ret;
+		return -EINVAL;
 
-	irq = desc->irq;
 	if (get_irte(irq, &irte))
-		return ret;
+		return -EBUSY;
 
-	cfg = desc->chip_data;
 	if (assign_irq_vector(irq, cfg, mask))
-		return ret;
+		return -EBUSY;
 
 	dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
 
@@ -2422,29 +2275,14 @@
 	if (cfg->move_in_progress)
 		send_cleanup_vector(cfg);
 
-	cpumask_copy(desc->affinity, mask);
-
+	cpumask_copy(data->affinity, mask);
 	return 0;
 }
 
-/*
- * Migrates the IRQ destination in the process context.
- */
-static int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
-					    const struct cpumask *mask)
-{
-	return migrate_ioapic_irq_desc(desc, mask);
-}
-static int set_ir_ioapic_affinity_irq(unsigned int irq,
-				       const struct cpumask *mask)
-{
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	return set_ir_ioapic_affinity_irq_desc(desc, mask);
-}
 #else
-static inline int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
-						   const struct cpumask *mask)
+static inline int
+ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+		       bool force)
 {
 	return 0;
 }
@@ -2506,10 +2344,8 @@
 	irq_exit();
 }
 
-static void __irq_complete_move(struct irq_desc **descp, unsigned vector)
+static void __irq_complete_move(struct irq_cfg *cfg, unsigned vector)
 {
-	struct irq_desc *desc = *descp;
-	struct irq_cfg *cfg = desc->chip_data;
 	unsigned me;
 
 	if (likely(!cfg->move_in_progress))
@@ -2521,31 +2357,28 @@
 		send_cleanup_vector(cfg);
 }
 
-static void irq_complete_move(struct irq_desc **descp)
+static void irq_complete_move(struct irq_cfg *cfg)
 {
-	__irq_complete_move(descp, ~get_irq_regs()->orig_ax);
+	__irq_complete_move(cfg, ~get_irq_regs()->orig_ax);
 }
 
 void irq_force_complete_move(int irq)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	struct irq_cfg *cfg = desc->chip_data;
+	struct irq_cfg *cfg = get_irq_chip_data(irq);
 
 	if (!cfg)
 		return;
 
-	__irq_complete_move(&desc, cfg->vector);
+	__irq_complete_move(cfg, cfg->vector);
 }
 #else
-static inline void irq_complete_move(struct irq_desc **descp) {}
+static inline void irq_complete_move(struct irq_cfg *cfg) { }
 #endif
 
-static void ack_apic_edge(unsigned int irq)
+static void ack_apic_edge(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	irq_complete_move(&desc);
-	move_native_irq(irq);
+	irq_complete_move(data->chip_data);
+	move_native_irq(data->irq);
 	ack_APIC_irq();
 }
 
@@ -2567,10 +2400,12 @@
  * Otherwise, we simulate the EOI message manually by changing the trigger
  * mode to edge and then back to level, with RTE being masked during this.
 */
-static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
 {
 	struct irq_pin_list *entry;
+	unsigned long flags;
 
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	for_each_irq_pin(entry, cfg->irq_2_pin) {
 		if (mp_ioapics[entry->apic].apicver >= 0x20) {
 			/*
@@ -2579,7 +2414,7 @@
 			 * intr-remapping table entry. Hence for the io-apic
 			 * EOI we use the pin number.
 			 */
-			if (irq_remapped(irq))
+			if (irq_remapped(cfg))
 				io_apic_eoi(entry->apic, entry->pin);
 			else
 				io_apic_eoi(entry->apic, cfg->vector);
@@ -2588,36 +2423,22 @@
 			__unmask_and_level_IO_APIC_irq(entry);
 		}
 	}
-}
-
-static void eoi_ioapic_irq(struct irq_desc *desc)
-{
-	struct irq_cfg *cfg;
-	unsigned long flags;
-	unsigned int irq;
-
-	irq = desc->irq;
-	cfg = desc->chip_data;
-
-	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	__eoi_ioapic_irq(irq, cfg);
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
-static void ack_apic_level(unsigned int irq)
+static void ack_apic_level(struct irq_data *data)
 {
+	struct irq_cfg *cfg = data->chip_data;
+	int i, do_unmask_irq = 0, irq = data->irq;
 	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long v;
-	int i;
-	struct irq_cfg *cfg;
-	int do_unmask_irq = 0;
 
-	irq_complete_move(&desc);
+	irq_complete_move(cfg);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 	/* If we are moving the irq we need to mask it */
 	if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
 		do_unmask_irq = 1;
-		mask_IO_APIC_irq_desc(desc);
+		mask_ioapic(cfg);
 	}
 #endif
 
@@ -2653,7 +2474,6 @@
 	 * we use the above logic (mask+edge followed by unmask+level) from
 	 * Manfred Spraul to clear the remote IRR.
 	 */
-	cfg = desc->chip_data;
 	i = cfg->vector;
 	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
 
@@ -2673,7 +2493,7 @@
 	if (!(v & (1 << (i & 0x1f)))) {
 		atomic_inc(&irq_mis_count);
 
-		eoi_ioapic_irq(desc);
+		eoi_ioapic_irq(irq, cfg);
 	}
 
 	/* Now we can move and renable the irq */
@@ -2704,61 +2524,57 @@
 		 * accurate and is causing problems then it is a hardware bug
 		 * and you can go talk to the chipset vendor about it.
 		 */
-		cfg = desc->chip_data;
 		if (!io_apic_level_ack_pending(cfg))
 			move_masked_irq(irq);
-		unmask_IO_APIC_irq_desc(desc);
+		unmask_ioapic(cfg);
 	}
 }
 
 #ifdef CONFIG_INTR_REMAP
-static void ir_ack_apic_edge(unsigned int irq)
+static void ir_ack_apic_edge(struct irq_data *data)
 {
 	ack_APIC_irq();
 }
 
-static void ir_ack_apic_level(unsigned int irq)
+static void ir_ack_apic_level(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-
 	ack_APIC_irq();
-	eoi_ioapic_irq(desc);
+	eoi_ioapic_irq(data->irq, data->chip_data);
 }
 #endif /* CONFIG_INTR_REMAP */
 
 static struct irq_chip ioapic_chip __read_mostly = {
-	.name		= "IO-APIC",
-	.startup	= startup_ioapic_irq,
-	.mask		= mask_IO_APIC_irq,
-	.unmask		= unmask_IO_APIC_irq,
-	.ack		= ack_apic_edge,
-	.eoi		= ack_apic_level,
+	.name			= "IO-APIC",
+	.irq_startup		= startup_ioapic_irq,
+	.irq_mask		= mask_ioapic_irq,
+	.irq_unmask		= unmask_ioapic_irq,
+	.irq_ack		= ack_apic_edge,
+	.irq_eoi		= ack_apic_level,
 #ifdef CONFIG_SMP
-	.set_affinity	= set_ioapic_affinity_irq,
+	.irq_set_affinity	= ioapic_set_affinity,
 #endif
-	.retrigger	= ioapic_retrigger_irq,
+	.irq_retrigger		= ioapic_retrigger_irq,
 };
 
 static struct irq_chip ir_ioapic_chip __read_mostly = {
-	.name		= "IR-IO-APIC",
-	.startup	= startup_ioapic_irq,
-	.mask		= mask_IO_APIC_irq,
-	.unmask		= unmask_IO_APIC_irq,
+	.name			= "IR-IO-APIC",
+	.irq_startup		= startup_ioapic_irq,
+	.irq_mask		= mask_ioapic_irq,
+	.irq_unmask		= unmask_ioapic_irq,
 #ifdef CONFIG_INTR_REMAP
-	.ack		= ir_ack_apic_edge,
-	.eoi		= ir_ack_apic_level,
+	.irq_ack		= ir_ack_apic_edge,
+	.irq_eoi		= ir_ack_apic_level,
 #ifdef CONFIG_SMP
-	.set_affinity	= set_ir_ioapic_affinity_irq,
+	.irq_set_affinity	= ir_ioapic_set_affinity,
 #endif
 #endif
-	.retrigger	= ioapic_retrigger_irq,
+	.irq_retrigger		= ioapic_retrigger_irq,
 };
 
 static inline void init_IO_APIC_traps(void)
 {
-	int irq;
-	struct irq_desc *desc;
 	struct irq_cfg *cfg;
+	unsigned int irq;
 
 	/*
 	 * NOTE! The local APIC isn't very good at handling
@@ -2771,8 +2587,8 @@
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	for_each_irq_desc(irq, desc) {
-		cfg = desc->chip_data;
+	for_each_active_irq(irq) {
+		cfg = get_irq_chip_data(irq);
 		if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
 			/*
 			 * Hmm.. We don't have an entry for this,
@@ -2783,7 +2599,7 @@
 				legacy_pic->make_irq(irq);
 			else
 				/* Strange. Oh, well.. */
-				desc->chip = &no_irq_chip;
+				set_irq_chip(irq, &no_irq_chip);
 		}
 	}
 }
@@ -2792,7 +2608,7 @@
  * The local APIC irq-chip implementation:
  */
 
-static void mask_lapic_irq(unsigned int irq)
+static void mask_lapic_irq(struct irq_data *data)
 {
 	unsigned long v;
 
@@ -2800,7 +2616,7 @@
 	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
 }
 
-static void unmask_lapic_irq(unsigned int irq)
+static void unmask_lapic_irq(struct irq_data *data)
 {
 	unsigned long v;
 
@@ -2808,21 +2624,21 @@
 	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
 }
 
-static void ack_lapic_irq(unsigned int irq)
+static void ack_lapic_irq(struct irq_data *data)
 {
 	ack_APIC_irq();
 }
 
 static struct irq_chip lapic_chip __read_mostly = {
 	.name		= "local-APIC",
-	.mask		= mask_lapic_irq,
-	.unmask		= unmask_lapic_irq,
-	.ack		= ack_lapic_irq,
+	.irq_mask	= mask_lapic_irq,
+	.irq_unmask	= unmask_lapic_irq,
+	.irq_ack	= ack_lapic_irq,
 };
 
-static void lapic_register_intr(int irq, struct irq_desc *desc)
+static void lapic_register_intr(int irq)
 {
-	desc->status &= ~IRQ_LEVEL;
+	irq_clear_status_flags(irq, IRQ_LEVEL);
 	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
 				      "edge");
 }
@@ -2925,9 +2741,8 @@
  */
 static inline void __init check_timer(void)
 {
-	struct irq_desc *desc = irq_to_desc(0);
-	struct irq_cfg *cfg = desc->chip_data;
-	int node = cpu_to_node(boot_cpu_id);
+	struct irq_cfg *cfg = get_irq_chip_data(0);
+	int node = cpu_to_node(0);
 	int apic1, pin1, apic2, pin2;
 	unsigned long flags;
 	int no_pin1 = 0;
@@ -2937,7 +2752,7 @@
 	/*
 	 * get/set the timer IRQ vector:
 	 */
-	legacy_pic->chip->mask(0);
+	legacy_pic->mask(0);
 	assign_irq_vector(0, cfg, apic->target_cpus());
 
 	/*
@@ -2996,7 +2811,7 @@
 			add_pin_to_irq_node(cfg, node, apic1, pin1);
 			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
 		} else {
-			/* for edge trigger, setup_IO_APIC_irq already
+			/* for edge trigger, setup_ioapic_irq already
 			 * leave it unmasked.
 			 * so only need to unmask if it is level-trigger
 			 * do we really have level trigger timer?
@@ -3004,12 +2819,12 @@
 			int idx;
 			idx = find_irq_entry(apic1, pin1, mp_INT);
 			if (idx != -1 && irq_trigger(idx))
-				unmask_IO_APIC_irq_desc(desc);
+				unmask_ioapic(cfg);
 		}
 		if (timer_irq_works()) {
 			if (nmi_watchdog == NMI_IO_APIC) {
 				setup_nmi();
-				legacy_pic->chip->unmask(0);
+				legacy_pic->unmask(0);
 			}
 			if (disable_timer_pin_1 > 0)
 				clear_IO_APIC_pin(0, pin1);
@@ -3032,14 +2847,14 @@
 		 */
 		replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
 		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
-		legacy_pic->chip->unmask(0);
+		legacy_pic->unmask(0);
 		if (timer_irq_works()) {
 			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
 			timer_through_8259 = 1;
 			if (nmi_watchdog == NMI_IO_APIC) {
-				legacy_pic->chip->mask(0);
+				legacy_pic->mask(0);
 				setup_nmi();
-				legacy_pic->chip->unmask(0);
+				legacy_pic->unmask(0);
 			}
 			goto out;
 		}
@@ -3047,7 +2862,7 @@
 		 * Cleanup, just in case ...
 		 */
 		local_irq_disable();
-		legacy_pic->chip->mask(0);
+		legacy_pic->mask(0);
 		clear_IO_APIC_pin(apic2, pin2);
 		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
 	}
@@ -3064,16 +2879,16 @@
 	apic_printk(APIC_QUIET, KERN_INFO
 		    "...trying to set up timer as Virtual Wire IRQ...\n");
 
-	lapic_register_intr(0, desc);
+	lapic_register_intr(0);
 	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
-	legacy_pic->chip->unmask(0);
+	legacy_pic->unmask(0);
 
 	if (timer_irq_works()) {
 		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
 		goto out;
 	}
 	local_irq_disable();
-	legacy_pic->chip->mask(0);
+	legacy_pic->mask(0);
 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
 	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
 
@@ -3239,49 +3054,42 @@
 /*
  * Dynamic irq allocate and deallocation
  */
-unsigned int create_irq_nr(unsigned int irq_want, int node)
+unsigned int create_irq_nr(unsigned int from, int node)
 {
-	/* Allocate an unused irq */
-	unsigned int irq;
-	unsigned int new;
+	struct irq_cfg *cfg;
 	unsigned long flags;
-	struct irq_cfg *cfg_new = NULL;
-	struct irq_desc *desc_new = NULL;
+	unsigned int ret = 0;
+	int irq;
 
-	irq = 0;
-	if (irq_want < nr_irqs_gsi)
-		irq_want = nr_irqs_gsi;
+	if (from < nr_irqs_gsi)
+		from = nr_irqs_gsi;
+
+	irq = alloc_irq_from(from, node);
+	if (irq < 0)
+		return 0;
+	cfg = alloc_irq_cfg(irq, node);
+	if (!cfg) {
+		free_irq_at(irq, NULL);
+		return 0;
+	}
 
 	raw_spin_lock_irqsave(&vector_lock, flags);
-	for (new = irq_want; new < nr_irqs; new++) {
-		desc_new = irq_to_desc_alloc_node(new, node);
-		if (!desc_new) {
-			printk(KERN_INFO "can not get irq_desc for %d\n", new);
-			continue;
-		}
-		cfg_new = desc_new->chip_data;
-
-		if (cfg_new->vector != 0)
-			continue;
-
-		desc_new = move_irq_desc(desc_new, node);
-		cfg_new = desc_new->chip_data;
-
-		if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
-			irq = new;
-		break;
-	}
+	if (!__assign_irq_vector(irq, cfg, apic->target_cpus()))
+		ret = irq;
 	raw_spin_unlock_irqrestore(&vector_lock, flags);
 
-	if (irq > 0)
-		dynamic_irq_init_keep_chip_data(irq);
-
-	return irq;
+	if (ret) {
+		set_irq_chip_data(irq, cfg);
+		irq_clear_status_flags(irq, IRQ_NOREQUEST);
+	} else {
+		free_irq_at(irq, cfg);
+	}
+	return ret;
 }
 
 int create_irq(void)
 {
-	int node = cpu_to_node(boot_cpu_id);
+	int node = cpu_to_node(0);
 	unsigned int irq_want;
 	int irq;
 
@@ -3296,14 +3104,17 @@
 
 void destroy_irq(unsigned int irq)
 {
+	struct irq_cfg *cfg = get_irq_chip_data(irq);
 	unsigned long flags;
 
-	dynamic_irq_cleanup_keep_chip_data(irq);
+	irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
 
-	free_irte(irq);
+	if (intr_remapping_enabled)
+		free_irte(irq);
 	raw_spin_lock_irqsave(&vector_lock, flags);
-	__clear_irq_vector(irq, get_irq_chip_data(irq));
+	__clear_irq_vector(irq, cfg);
 	raw_spin_unlock_irqrestore(&vector_lock, flags);
+	free_irq_at(irq, cfg);
 }
 
 /*
@@ -3327,7 +3138,7 @@
 
 	dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
 
-	if (irq_remapped(irq)) {
+	if (irq_remapped(get_irq_chip_data(irq))) {
 		struct irte irte;
 		int ir_index;
 		u16 sub_handle;
@@ -3335,14 +3146,7 @@
 		ir_index = map_irq_to_irte_handle(irq, &sub_handle);
 		BUG_ON(ir_index == -1);
 
-		memset (&irte, 0, sizeof(irte));
-
-		irte.present = 1;
-		irte.dst_mode = apic->irq_dest_mode;
-		irte.trigger_mode = 0; /* edge */
-		irte.dlvry_mode = apic->irq_delivery_mode;
-		irte.vector = cfg->vector;
-		irte.dest_id = IRTE_DEST(dest);
+		prepare_irte(&irte, cfg->vector, dest);
 
 		/* Set source-id of interrupt request */
 		if (pdev)
@@ -3387,26 +3191,24 @@
 }
 
 #ifdef CONFIG_SMP
-static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	struct irq_cfg *cfg;
+	struct irq_cfg *cfg = data->chip_data;
 	struct msi_msg msg;
 	unsigned int dest;
 
-	if (set_desc_affinity(desc, mask, &dest))
+	if (__ioapic_set_affinity(data, mask, &dest))
 		return -1;
 
-	cfg = desc->chip_data;
-
-	get_cached_msi_msg_desc(desc, &msg);
+	__get_cached_msi_msg(data->msi_desc, &msg);
 
 	msg.data &= ~MSI_DATA_VECTOR_MASK;
 	msg.data |= MSI_DATA_VECTOR(cfg->vector);
 	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
-	write_msi_msg_desc(desc, &msg);
+	__write_msi_msg(data->msi_desc, &msg);
 
 	return 0;
 }
@@ -3416,17 +3218,17 @@
  * done in the process context using interrupt-remapping hardware.
  */
 static int
-ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+ir_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
+		    bool force)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	struct irq_cfg *cfg = desc->chip_data;
-	unsigned int dest;
+	struct irq_cfg *cfg = data->chip_data;
+	unsigned int dest, irq = data->irq;
 	struct irte irte;
 
 	if (get_irte(irq, &irte))
 		return -1;
 
-	if (set_desc_affinity(desc, mask, &dest))
+	if (__ioapic_set_affinity(data, mask, &dest))
 		return -1;
 
 	irte.vector = cfg->vector;
@@ -3456,27 +3258,27 @@
  * which implement the MSI or MSI-X Capability Structure.
  */
 static struct irq_chip msi_chip = {
-	.name		= "PCI-MSI",
-	.unmask		= unmask_msi_irq,
-	.mask		= mask_msi_irq,
-	.ack		= ack_apic_edge,
+	.name			= "PCI-MSI",
+	.irq_unmask		= unmask_msi_irq,
+	.irq_mask		= mask_msi_irq,
+	.irq_ack		= ack_apic_edge,
 #ifdef CONFIG_SMP
-	.set_affinity	= set_msi_irq_affinity,
+	.irq_set_affinity	= msi_set_affinity,
 #endif
-	.retrigger	= ioapic_retrigger_irq,
+	.irq_retrigger		= ioapic_retrigger_irq,
 };
 
 static struct irq_chip msi_ir_chip = {
-	.name		= "IR-PCI-MSI",
-	.unmask		= unmask_msi_irq,
-	.mask		= mask_msi_irq,
+	.name			= "IR-PCI-MSI",
+	.irq_unmask		= unmask_msi_irq,
+	.irq_mask		= mask_msi_irq,
 #ifdef CONFIG_INTR_REMAP
-	.ack		= ir_ack_apic_edge,
+	.irq_ack		= ir_ack_apic_edge,
 #ifdef CONFIG_SMP
-	.set_affinity	= ir_set_msi_irq_affinity,
+	.irq_set_affinity	= ir_msi_set_affinity,
 #endif
 #endif
-	.retrigger	= ioapic_retrigger_irq,
+	.irq_retrigger		= ioapic_retrigger_irq,
 };
 
 /*
@@ -3508,8 +3310,8 @@
 
 static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
 {
-	int ret;
 	struct msi_msg msg;
+	int ret;
 
 	ret = msi_compose_msg(dev, irq, &msg, -1);
 	if (ret < 0)
@@ -3518,12 +3320,8 @@
 	set_irq_msi(irq, msidesc);
 	write_msi_msg(irq, &msg);
 
-	if (irq_remapped(irq)) {
-		struct irq_desc *desc = irq_to_desc(irq);
-		/*
-		 * irq migration in process context
-		 */
-		desc->status |= IRQ_MOVE_PCNTXT;
+	if (irq_remapped(get_irq_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");
@@ -3535,13 +3333,10 @@
 
 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
-	unsigned int irq;
-	int ret, sub_handle;
+	int node, ret, sub_handle, index = 0;
+	unsigned int irq, irq_want;
 	struct msi_desc *msidesc;
-	unsigned int irq_want;
 	struct intel_iommu *iommu = NULL;
-	int index = 0;
-	int node;
 
 	/* x86 doesn't support multiple MSI yet */
 	if (type == PCI_CAP_ID_MSI && nvec > 1)
@@ -3601,18 +3396,17 @@
 
 #if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
 #ifdef CONFIG_SMP
-static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
+		      bool force)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	struct irq_cfg *cfg;
+	struct irq_cfg *cfg = data->chip_data;
+	unsigned int dest, irq = data->irq;
 	struct msi_msg msg;
-	unsigned int dest;
 
-	if (set_desc_affinity(desc, mask, &dest))
+	if (__ioapic_set_affinity(data, mask, &dest))
 		return -1;
 
-	cfg = desc->chip_data;
-
 	dmar_msi_read(irq, &msg);
 
 	msg.data &= ~MSI_DATA_VECTOR_MASK;
@@ -3628,14 +3422,14 @@
 #endif /* CONFIG_SMP */
 
 static struct irq_chip dmar_msi_type = {
-	.name = "DMAR_MSI",
-	.unmask = dmar_msi_unmask,
-	.mask = dmar_msi_mask,
-	.ack = ack_apic_edge,
+	.name			= "DMAR_MSI",
+	.irq_unmask		= dmar_msi_unmask,
+	.irq_mask		= dmar_msi_mask,
+	.irq_ack		= ack_apic_edge,
 #ifdef CONFIG_SMP
-	.set_affinity = dmar_msi_set_affinity,
+	.irq_set_affinity	= dmar_msi_set_affinity,
 #endif
-	.retrigger = ioapic_retrigger_irq,
+	.irq_retrigger		= ioapic_retrigger_irq,
 };
 
 int arch_setup_dmar_msi(unsigned int irq)
@@ -3656,26 +3450,24 @@
 #ifdef CONFIG_HPET_TIMER
 
 #ifdef CONFIG_SMP
-static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int hpet_msi_set_affinity(struct irq_data *data,
+				 const struct cpumask *mask, bool force)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	struct irq_cfg *cfg;
+	struct irq_cfg *cfg = data->chip_data;
 	struct msi_msg msg;
 	unsigned int dest;
 
-	if (set_desc_affinity(desc, mask, &dest))
+	if (__ioapic_set_affinity(data, mask, &dest))
 		return -1;
 
-	cfg = desc->chip_data;
-
-	hpet_msi_read(irq, &msg);
+	hpet_msi_read(data->handler_data, &msg);
 
 	msg.data &= ~MSI_DATA_VECTOR_MASK;
 	msg.data |= MSI_DATA_VECTOR(cfg->vector);
 	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
-	hpet_msi_write(irq, &msg);
+	hpet_msi_write(data->handler_data, &msg);
 
 	return 0;
 }
@@ -3683,34 +3475,33 @@
 #endif /* CONFIG_SMP */
 
 static struct irq_chip ir_hpet_msi_type = {
-	.name = "IR-HPET_MSI",
-	.unmask = hpet_msi_unmask,
-	.mask = hpet_msi_mask,
+	.name			= "IR-HPET_MSI",
+	.irq_unmask		= hpet_msi_unmask,
+	.irq_mask		= hpet_msi_mask,
 #ifdef CONFIG_INTR_REMAP
-	.ack = ir_ack_apic_edge,
+	.irq_ack		= ir_ack_apic_edge,
 #ifdef CONFIG_SMP
-	.set_affinity = ir_set_msi_irq_affinity,
+	.irq_set_affinity	= ir_msi_set_affinity,
 #endif
 #endif
-	.retrigger = ioapic_retrigger_irq,
+	.irq_retrigger		= ioapic_retrigger_irq,
 };
 
 static struct irq_chip hpet_msi_type = {
 	.name = "HPET_MSI",
-	.unmask = hpet_msi_unmask,
-	.mask = hpet_msi_mask,
-	.ack = ack_apic_edge,
+	.irq_unmask = hpet_msi_unmask,
+	.irq_mask = hpet_msi_mask,
+	.irq_ack = ack_apic_edge,
 #ifdef CONFIG_SMP
-	.set_affinity = hpet_msi_set_affinity,
+	.irq_set_affinity = hpet_msi_set_affinity,
 #endif
-	.retrigger = ioapic_retrigger_irq,
+	.irq_retrigger = ioapic_retrigger_irq,
 };
 
 int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
 {
-	int ret;
 	struct msi_msg msg;
-	struct irq_desc *desc = irq_to_desc(irq);
+	int ret;
 
 	if (intr_remapping_enabled) {
 		struct intel_iommu *iommu = map_hpet_to_ir(id);
@@ -3728,9 +3519,9 @@
 	if (ret < 0)
 		return ret;
 
-	hpet_msi_write(irq, &msg);
-	desc->status |= IRQ_MOVE_PCNTXT;
-	if (irq_remapped(irq))
+	hpet_msi_write(get_irq_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
@@ -3763,33 +3554,30 @@
 	write_ht_irq_msg(irq, &msg);
 }
 
-static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	struct irq_cfg *cfg;
+	struct irq_cfg *cfg = data->chip_data;
 	unsigned int dest;
 
-	if (set_desc_affinity(desc, mask, &dest))
+	if (__ioapic_set_affinity(data, mask, &dest))
 		return -1;
 
-	cfg = desc->chip_data;
-
-	target_ht_irq(irq, dest, cfg->vector);
-
+	target_ht_irq(data->irq, dest, cfg->vector);
 	return 0;
 }
 
 #endif
 
 static struct irq_chip ht_irq_chip = {
-	.name		= "PCI-HT",
-	.mask		= mask_ht_irq,
-	.unmask		= unmask_ht_irq,
-	.ack		= ack_apic_edge,
+	.name			= "PCI-HT",
+	.irq_mask		= mask_ht_irq,
+	.irq_unmask		= unmask_ht_irq,
+	.irq_ack		= ack_apic_edge,
 #ifdef CONFIG_SMP
-	.set_affinity	= set_ht_irq_affinity,
+	.irq_set_affinity	= ht_set_affinity,
 #endif
-	.retrigger	= ioapic_retrigger_irq,
+	.irq_retrigger		= ioapic_retrigger_irq,
 };
 
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
@@ -3880,14 +3668,13 @@
 	if (nr < nr_irqs)
 		nr_irqs = nr;
 
-	return 0;
+	return NR_IRQS_LEGACY;
 }
 #endif
 
 static int __io_apic_set_pci_routing(struct device *dev, int irq,
 				struct io_apic_irq_attr *irq_attr)
 {
-	struct irq_desc *desc;
 	struct irq_cfg *cfg;
 	int node;
 	int ioapic, pin;
@@ -3903,13 +3690,11 @@
 	if (dev)
 		node = dev_to_node(dev);
 	else
-		node = cpu_to_node(boot_cpu_id);
+		node = cpu_to_node(0);
 
-	desc = irq_to_desc_alloc_node(irq, node);
-	if (!desc) {
-		printk(KERN_INFO "can not get irq_desc %d\n", irq);
+	cfg = alloc_irq_and_cfg_at(irq, node);
+	if (!cfg)
 		return 0;
-	}
 
 	pin = irq_attr->ioapic_pin;
 	trigger = irq_attr->trigger;
@@ -3919,15 +3704,14 @@
 	 * IRQs < 16 are already in the irq_2_pin[] map
 	 */
 	if (irq >= legacy_pic->nr_legacy_irqs) {
-		cfg = desc->chip_data;
-		if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) {
+		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_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity);
+	setup_ioapic_irq(ioapic, pin, irq, cfg, trigger, polarity);
 
 	return 0;
 }
@@ -4120,14 +3904,14 @@
 		 */
 		if (desc->status &
 		    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
-			mask = desc->affinity;
+			mask = desc->irq_data.affinity;
 		else
 			mask = apic->target_cpus();
 
 		if (intr_remapping_enabled)
-			set_ir_ioapic_affinity_irq_desc(desc, mask);
+			ir_ioapic_set_affinity(&desc->irq_data, mask, false);
 		else
-			set_ioapic_affinity_irq_desc(desc, mask);
+			ioapic_set_affinity(&desc->irq_data, mask, false);
 	}
 
 }
@@ -4311,19 +4095,18 @@
 void __init pre_init_apic_IRQ0(void)
 {
 	struct irq_cfg *cfg;
-	struct irq_desc *desc;
 
 	printk(KERN_INFO "Early APIC setup for system timer0\n");
 #ifndef CONFIG_SMP
 	phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
 #endif
-	desc = irq_to_desc_alloc_node(0, 0);
+	/* Make sure the irq descriptor is set up */
+	cfg = alloc_irq_and_cfg_at(0, 0);
 
 	setup_local_APIC();
 
-	cfg = irq_cfg(0);
 	add_pin_to_irq_node(cfg, 0, 0, 0);
 	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
 
-	setup_IO_APIC_irq(0, 0, 0, desc, 0, 0);
+	setup_ioapic_irq(0, 0, 0, cfg, 0, 0);
 }
diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c
index a43f71c..c90041c 100644
--- a/arch/x86/kernel/apic/nmi.c
+++ b/arch/x86/kernel/apic/nmi.c
@@ -178,7 +178,7 @@
 error:
 	if (nmi_watchdog == NMI_IO_APIC) {
 		if (!timer_through_8259)
-			legacy_pic->chip->mask(0);
+			legacy_pic->mask(0);
 		on_each_cpu(__acpi_nmi_disable, NULL, 1);
 	}
 
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c
index 3e28401..960f26a 100644
--- a/arch/x86/kernel/apic/numaq_32.c
+++ b/arch/x86/kernel/apic/numaq_32.c
@@ -26,6 +26,7 @@
 #include <linux/nodemask.h>
 #include <linux/topology.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/kernel.h>
@@ -88,7 +89,7 @@
 	node_end_pfn[node] =
 		 MB_TO_PAGES(eq->hi_shrd_mem_start + eq->hi_shrd_mem_size);
 
-	e820_register_active_regions(node, node_start_pfn[node],
+	memblock_x86_register_active_regions(node, node_start_pfn[node],
 						node_end_pfn[node]);
 
 	memory_present(node, node_start_pfn[node], node_end_pfn[node]);
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c
index 83e9be4..f9e4e6a 100644
--- a/arch/x86/kernel/apic/probe_64.c
+++ b/arch/x86/kernel/apic/probe_64.c
@@ -54,6 +54,9 @@
  */
 void __init default_setup_apic_routing(void)
 {
+
+	enable_IR_x2apic();
+
 #ifdef CONFIG_X86_X2APIC
 	if (x2apic_mode
 #ifdef CONFIG_X86_UV
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 4c9c67b..fbbc4da 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -1926,6 +1926,7 @@
 	.unlocked_ioctl	= do_ioctl,
 	.open		= do_open,
 	.release	= do_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice apm_device = {
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index dfdbf64..1a4088d 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -99,9 +99,7 @@
 
 	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
 	DEFINE(PAGE_SHIFT_asm, PAGE_SHIFT);
-	DEFINE(PTRS_PER_PTE, PTRS_PER_PTE);
-	DEFINE(PTRS_PER_PMD, PTRS_PER_PMD);
-	DEFINE(PTRS_PER_PGD, PTRS_PER_PGD);
+	DEFINE(THREAD_SIZE_asm, THREAD_SIZE);
 
 	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
 
diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c
index fc999e6..13a3891 100644
--- a/arch/x86/kernel/check.c
+++ b/arch/x86/kernel/check.c
@@ -2,7 +2,8 @@
 #include <linux/sched.h>
 #include <linux/kthread.h>
 #include <linux/workqueue.h>
-#include <asm/e820.h>
+#include <linux/memblock.h>
+
 #include <asm/proto.h>
 
 /*
@@ -18,10 +19,12 @@
 static unsigned __read_mostly corruption_check_size = 64*1024;
 static unsigned __read_mostly corruption_check_period = 60; /* seconds */
 
-static struct e820entry scan_areas[MAX_SCAN_AREAS];
+static struct scan_area {
+	u64 addr;
+	u64 size;
+} scan_areas[MAX_SCAN_AREAS];
 static int num_scan_areas;
 
-
 static __init int set_corruption_check(char *arg)
 {
 	char *end;
@@ -81,9 +84,9 @@
 
 	while (addr < corruption_check_size && num_scan_areas < MAX_SCAN_AREAS) {
 		u64 size;
-		addr = find_e820_area_size(addr, &size, PAGE_SIZE);
+		addr = memblock_x86_find_in_range_size(addr, &size, PAGE_SIZE);
 
-		if (!(addr + 1))
+		if (addr == MEMBLOCK_ERROR)
 			break;
 
 		if (addr >= corruption_check_size)
@@ -92,7 +95,7 @@
 		if ((addr + size) > corruption_check_size)
 			size = corruption_check_size - addr;
 
-		e820_update_range(addr, size, E820_RAM, E820_RESERVED);
+		memblock_x86_reserve_range(addr, addr + size, "SCAN RAM");
 		scan_areas[num_scan_areas].addr = addr;
 		scan_areas[num_scan_areas].size = size;
 		num_scan_areas++;
@@ -105,7 +108,6 @@
 
 	printk(KERN_INFO "Scanning %d areas for low memory corruption\n",
 	       num_scan_areas);
-	update_e820();
 }
 
 
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index ba5f62f..9e093f8 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -148,7 +148,7 @@
 {
 #ifdef CONFIG_SMP
 	/* calling is from identify_secondary_cpu() ? */
-	if (c->cpu_index == boot_cpu_id)
+	if (!c->cpu_index)
 		return;
 
 	/*
@@ -253,37 +253,51 @@
 #endif
 
 /*
- * Fixup core topology information for AMD multi-node processors.
- * Assumption: Number of cores in each internal node is the same.
+ * Fixup core topology information for
+ * (1) AMD multi-node processors
+ *     Assumption: Number of cores in each internal node is the same.
+ * (2) AMD processors supporting compute units
  */
 #ifdef CONFIG_X86_HT
-static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c)
+static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c)
 {
-	unsigned long long value;
-	u32 nodes, cores_per_node;
+	u32 nodes;
+	u8 node_id;
 	int cpu = smp_processor_id();
 
-	if (!cpu_has(c, X86_FEATURE_NODEID_MSR))
+	/* get information required for multi-node processors */
+	if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
+		u32 eax, ebx, ecx, edx;
+
+		cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
+		nodes = ((ecx >> 8) & 7) + 1;
+		node_id = ecx & 7;
+
+		/* get compute unit information */
+		smp_num_siblings = ((ebx >> 8) & 3) + 1;
+		c->compute_unit_id = ebx & 0xff;
+	} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
+		u64 value;
+
+		rdmsrl(MSR_FAM10H_NODE_ID, value);
+		nodes = ((value >> 3) & 7) + 1;
+		node_id = value & 7;
+	} else
 		return;
 
-	/* fixup topology information only once for a core */
-	if (cpu_has(c, X86_FEATURE_AMD_DCM))
-		return;
+	/* fixup multi-node processor information */
+	if (nodes > 1) {
+		u32 cores_per_node;
 
-	rdmsrl(MSR_FAM10H_NODE_ID, value);
+		set_cpu_cap(c, X86_FEATURE_AMD_DCM);
+		cores_per_node = c->x86_max_cores / nodes;
 
-	nodes = ((value >> 3) & 7) + 1;
-	if (nodes == 1)
-		return;
+		/* store NodeID, use llc_shared_map to store sibling info */
+		per_cpu(cpu_llc_id, cpu) = node_id;
 
-	set_cpu_cap(c, X86_FEATURE_AMD_DCM);
-	cores_per_node = c->x86_max_cores / nodes;
-
-	/* store NodeID, use llc_shared_map to store sibling info */
-	per_cpu(cpu_llc_id, cpu) = value & 7;
-
-	/* fixup 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 to be in range from 0 to (cores_per_node - 1) */
+		c->cpu_core_id = c->cpu_core_id % cores_per_node;
+	}
 }
 #endif
 
@@ -304,9 +318,7 @@
 	c->phys_proc_id = c->initial_apicid >> bits;
 	/* use socket ID also for last level cache */
 	per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
-	/* fixup topology information on multi-node processors */
-	if ((c->x86 == 0x10) && (c->x86_model == 9))
-		amd_fixup_dcm(c);
+	amd_get_topology(c);
 #endif
 }
 
@@ -412,6 +424,23 @@
 			set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
 	}
 #endif
+
+	/* We need to do the following only once */
+	if (c != &boot_cpu_data)
+		return;
+
+	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
+
+		if (c->x86 > 0x10 ||
+		    (c->x86 == 0x10 && c->x86_model >= 0x2)) {
+			u64 val;
+
+			rdmsrl(MSR_K7_HWCR, val);
+			if (!(val & BIT(24)))
+				printk(KERN_WARNING FW_BUG "TSC doesn't count "
+					"with P0 frequency!\n");
+		}
+	}
 }
 
 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
@@ -523,7 +552,7 @@
 #endif
 
 	if (c->extended_cpuid_level >= 0x80000006) {
-		if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000))
+		if (cpuid_edx(0x80000006) & 0xf000)
 			num_cache_leaves = 4;
 		else
 			num_cache_leaves = 3;
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 490dac6..4b68bda 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -545,7 +545,7 @@
 	}
 }
 
-static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
+void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
 {
 	u32 tfms, xlvl;
 	u32 ebx;
@@ -665,7 +665,7 @@
 		this_cpu->c_early_init(c);
 
 #ifdef CONFIG_SMP
-	c->cpu_index = boot_cpu_id;
+	c->cpu_index = 0;
 #endif
 	filter_cpuid_features(c, false);
 }
@@ -704,16 +704,21 @@
 }
 
 /*
- * The NOPL instruction is supposed to exist on all CPUs with
- * family >= 6; unfortunately, that's not true in practice because
- * of early VIA chips and (more importantly) broken virtualizers that
- * are not easy to detect.  In the latter case it doesn't even *fail*
- * reliably, so probing for it doesn't even work.  Disable it completely
+ * The NOPL instruction is supposed to exist on all CPUs of family >= 6;
+ * unfortunately, that's not true in practice because of early VIA
+ * chips and (more importantly) broken virtualizers that are not easy
+ * to detect. In the latter case it doesn't even *fail* reliably, so
+ * probing for it doesn't even work. Disable it completely on 32-bit
  * unless we can find a reliable way to detect all the broken cases.
+ * Enable it explicitly on 64-bit for non-constant inputs of cpu_has().
  */
 static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
 {
+#ifdef CONFIG_X86_32
 	clear_cpu_cap(c, X86_FEATURE_NOPL);
+#else
+	set_cpu_cap(c, X86_FEATURE_NOPL);
+#endif
 }
 
 static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
@@ -1264,13 +1269,6 @@
 	clear_all_debug_regs();
 	dbg_restore_debug_regs();
 
-	/*
-	 * Force FPU initialization:
-	 */
-	current_thread_info()->status = 0;
-	clear_used_math();
-	mxcsr_feature_mask_init();
-
 	fpu_init();
 	xsave_init();
 }
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index 3624e8a..e765633 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -32,6 +32,8 @@
 extern const struct cpu_dev *const __x86_cpu_dev_start[],
 			    *const __x86_cpu_dev_end[];
 
+extern void get_cpu_cap(struct cpuinfo_x86 *c);
 extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c);
+extern void get_cpu_cap(struct cpuinfo_x86 *c);
 
 #endif
diff --git a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
index 994230d..4f6f679 100644
--- a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
@@ -368,16 +368,22 @@
 		return -ENODEV;
 
 	out_obj = output.pointer;
-	if (out_obj->type != ACPI_TYPE_BUFFER)
-		return -ENODEV;
+	if (out_obj->type != ACPI_TYPE_BUFFER) {
+		ret = -ENODEV;
+		goto out_free;
+	}
 
 	errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
-	if (errors)
-		return -ENODEV;
+	if (errors) {
+		ret = -ENODEV;
+		goto out_free;
+	}
 
 	supported = *((u32 *)(out_obj->buffer.pointer + 4));
-	if (!(supported & 0x1))
-		return -ENODEV;
+	if (!(supported & 0x1)) {
+		ret = -ENODEV;
+		goto out_free;
+	}
 
 out_free:
 	kfree(output.pointer);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 85f69cd..d16c2c5 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -39,6 +39,7 @@
 			misc_enable &= ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID;
 			wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
 			c->cpuid_level = cpuid_eax(0);
+			get_cpu_cap(c);
 		}
 	}
 
@@ -169,7 +170,7 @@
 {
 #ifdef CONFIG_SMP
 	/* calling is from identify_secondary_cpu() ? */
-	if (c->cpu_index == boot_cpu_id)
+	if (!c->cpu_index)
 		return;
 
 	/*
@@ -283,9 +284,7 @@
 	/* Don't do the funky fallback heuristics the AMD version employs
 	   for now. */
 	node = apicid_to_node[apicid];
-	if (node == NUMA_NO_NODE)
-		node = first_node(node_online_map);
-	else if (!node_online(node)) {
+	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 898c2f4..12cd823 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -17,7 +17,7 @@
 
 #include <asm/processor.h>
 #include <linux/smp.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 #include <asm/smp.h>
 
 #define LVL_1_INST	1
@@ -306,7 +306,7 @@
 	ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
 };
 
-#ifdef CONFIG_CPU_SUP_AMD
+#ifdef CONFIG_AMD_NB
 
 /*
  * L3 cache descriptors
@@ -369,7 +369,7 @@
 			return;
 
 	/* not in virtualized environments */
-	if (num_k8_northbridges == 0)
+	if (k8_northbridges.num == 0)
 		return;
 
 	/*
@@ -377,7 +377,7 @@
 	 * never freed but this is done only on shutdown so it doesn't matter.
 	 */
 	if (!l3_caches) {
-		int size = num_k8_northbridges * sizeof(struct amd_l3_cache *);
+		int size = k8_northbridges.num * sizeof(struct amd_l3_cache *);
 
 		l3_caches = kzalloc(size, GFP_ATOMIC);
 		if (!l3_caches)
@@ -556,12 +556,12 @@
 static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
 		show_cache_disable_1, store_cache_disable_1);
 
-#else	/* CONFIG_CPU_SUP_AMD */
+#else	/* CONFIG_AMD_NB */
 static void __cpuinit
 amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, int index)
 {
 };
-#endif /* CONFIG_CPU_SUP_AMD */
+#endif /* CONFIG_AMD_NB */
 
 static int
 __cpuinit cpuid4_cache_lookup_regs(int index,
@@ -1000,7 +1000,7 @@
 
 static struct attribute *default_l3_attrs[] = {
 	DEFAULT_SYSFS_CACHE_ATTRS,
-#ifdef CONFIG_CPU_SUP_AMD
+#ifdef CONFIG_AMD_NB
 	&cache_disable_0.attr,
 	&cache_disable_1.attr,
 #endif
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 8a85dd1..1e8d66c 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -192,6 +192,7 @@
 	.release	= seq_release,
 	.read		= seq_read,
 	.write		= severities_coverage_write,
+	.llseek		= seq_lseek,
 };
 
 static int __init severities_debugfs_init(void)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index ed41562..7a35b72 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1665,6 +1665,7 @@
 	.read			= mce_read,
 	.poll			= mce_poll,
 	.unlocked_ioctl		= mce_ioctl,
+	.llseek		= no_llseek,
 };
 EXPORT_SYMBOL_GPL(mce_chrdev_ops);
 
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 5e97529..80c4823 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -131,7 +131,8 @@
 	u32 low = 0, high = 0, address = 0;
 	unsigned int bank, block;
 	struct thresh_restart tr;
-	u8 lvt_off;
+	int lvt_off = -1;
+	u8 offset;
 
 	for (bank = 0; bank < NR_BANKS; ++bank) {
 		for (block = 0; block < NR_BLOCKS; ++block) {
@@ -141,6 +142,7 @@
 				address = (low & MASK_BLKPTR_LO) >> 21;
 				if (!address)
 					break;
+
 				address += MCG_XBLK_ADDR;
 			} else
 				++address;
@@ -148,12 +150,8 @@
 			if (rdmsr_safe(address, &low, &high))
 				break;
 
-			if (!(high & MASK_VALID_HI)) {
-				if (block)
-					continue;
-				else
-					break;
-			}
+			if (!(high & MASK_VALID_HI))
+				continue;
 
 			if (!(high & MASK_CNTP_HI)  ||
 			     (high & MASK_LOCKED_HI))
@@ -165,8 +163,28 @@
 			if (shared_bank[bank] && c->cpu_core_id)
 				break;
 #endif
-			lvt_off = setup_APIC_eilvt_mce(THRESHOLD_APIC_VECTOR,
-						       APIC_EILVT_MSG_FIX, 0);
+			offset = (high & MASK_LVTOFF_HI) >> 20;
+			if (lvt_off < 0) {
+				if (setup_APIC_eilvt(offset,
+						     THRESHOLD_APIC_VECTOR,
+						     APIC_EILVT_MSG_FIX, 0)) {
+					pr_err(FW_BUG "cpu %d, failed to "
+					       "setup threshold interrupt "
+					       "for bank %d, block %d "
+					       "(MSR%08X=0x%x%08x)",
+					       smp_processor_id(), bank, block,
+					       address, high, low);
+					continue;
+				}
+				lvt_off = offset;
+			} else if (lvt_off != offset) {
+				pr_err(FW_BUG "cpu %d, invalid threshold "
+				       "interrupt offset %d for bank %d,"
+				       "block %d (MSR%08X=0x%x%08x)",
+				       smp_processor_id(), lvt_off, bank,
+				       block, address, high, low);
+				continue;
+			}
 
 			high &= ~MASK_LVTOFF_HI;
 			high |= lvt_off << 20;
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index d9368ee..4b68326 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -216,7 +216,7 @@
 		err = sysfs_add_file_to_group(&sys_dev->kobj,
 					      &attr_core_power_limit_count.attr,
 					      thermal_attr_group.name);
-	if (cpu_has(c, X86_FEATURE_PTS))
+	if (cpu_has(c, X86_FEATURE_PTS)) {
 		err = sysfs_add_file_to_group(&sys_dev->kobj,
 					      &attr_package_throttle_count.attr,
 					      thermal_attr_group.name);
@@ -224,6 +224,7 @@
 			err = sysfs_add_file_to_group(&sys_dev->kobj,
 					&attr_package_power_limit_count.attr,
 					thermal_attr_group.name);
+	}
 
 	return err;
 }
@@ -349,7 +350,7 @@
 
 static void unexpected_thermal_interrupt(void)
 {
-	printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
+	printk(KERN_ERR "CPU%d: Unexpected LVT thermal interrupt!\n",
 			smp_processor_id());
 	add_taint(TAINT_MACHINE_CHECK);
 }
diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c
index c5f59d0..ac140c7 100644
--- a/arch/x86/kernel/cpu/mtrr/cleanup.c
+++ b/arch/x86/kernel/cpu/mtrr/cleanup.c
@@ -827,7 +827,7 @@
 
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
 		return 0;
-	if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
+	if (boot_cpu_data.x86 < 0xf)
 		return 0;
 	/* In case some hypervisor doesn't pass SYSCFG through: */
 	if (rdmsr_safe(MSR_K8_SYSCFG, &l, &h) < 0)
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 7d28d7d..9f27228 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -64,18 +64,59 @@
 	}
 }
 
+/* Get the size of contiguous MTRR range */
+static u64 get_mtrr_size(u64 mask)
+{
+	u64 size;
+
+	mask >>= PAGE_SHIFT;
+	mask |= size_or_mask;
+	size = -mask;
+	size <<= PAGE_SHIFT;
+	return size;
+}
+
 /*
- * Returns the effective MTRR type for the region
- * Error returns:
- * - 0xFE - when the range is "not entirely covered" by _any_ var range MTRR
- * - 0xFF - when MTRR is not enabled
+ * Check and return the effective type for MTRR-MTRR type overlap.
+ * Returns 1 if the effective type is UNCACHEABLE, else returns 0
  */
-u8 mtrr_type_lookup(u64 start, u64 end)
+static int check_type_overlap(u8 *prev, u8 *curr)
+{
+	if (*prev == MTRR_TYPE_UNCACHABLE || *curr == MTRR_TYPE_UNCACHABLE) {
+		*prev = MTRR_TYPE_UNCACHABLE;
+		*curr = MTRR_TYPE_UNCACHABLE;
+		return 1;
+	}
+
+	if ((*prev == MTRR_TYPE_WRBACK && *curr == MTRR_TYPE_WRTHROUGH) ||
+	    (*prev == MTRR_TYPE_WRTHROUGH && *curr == MTRR_TYPE_WRBACK)) {
+		*prev = MTRR_TYPE_WRTHROUGH;
+		*curr = MTRR_TYPE_WRTHROUGH;
+	}
+
+	if (*prev != *curr) {
+		*prev = MTRR_TYPE_UNCACHABLE;
+		*curr = MTRR_TYPE_UNCACHABLE;
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Error/Semi-error returns:
+ * 0xFF - when MTRR is not enabled
+ * *repeat == 1 implies [start:end] spanned across MTRR range and type returned
+ *		corresponds only to [start:*partial_end].
+ *		Caller has to lookup again for [*partial_end:end].
+ */
+static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 {
 	int i;
 	u64 base, mask;
 	u8 prev_match, curr_match;
 
+	*repeat = 0;
 	if (!mtrr_state_set)
 		return 0xFF;
 
@@ -126,8 +167,34 @@
 
 		start_state = ((start & mask) == (base & mask));
 		end_state = ((end & mask) == (base & mask));
-		if (start_state != end_state)
-			return 0xFE;
+
+		if (start_state != end_state) {
+			/*
+			 * We have start:end spanning across an MTRR.
+			 * We split the region into
+			 * either
+			 * (start:mtrr_end) (mtrr_end:end)
+			 * or
+			 * (start:mtrr_start) (mtrr_start:end)
+			 * depending on kind of overlap.
+			 * Return the type for first region and a pointer to
+			 * the start of second region so that caller will
+			 * lookup again on the second region.
+			 * Note: This way we handle multiple overlaps as well.
+			 */
+			if (start_state)
+				*partial_end = base + get_mtrr_size(mask);
+			else
+				*partial_end = base;
+
+			if (unlikely(*partial_end <= start)) {
+				WARN_ON(1);
+				*partial_end = start + PAGE_SIZE;
+			}
+
+			end = *partial_end - 1; /* end is inclusive */
+			*repeat = 1;
+		}
 
 		if ((start & mask) != (base & mask))
 			continue;
@@ -138,21 +205,8 @@
 			continue;
 		}
 
-		if (prev_match == MTRR_TYPE_UNCACHABLE ||
-		    curr_match == MTRR_TYPE_UNCACHABLE) {
-			return MTRR_TYPE_UNCACHABLE;
-		}
-
-		if ((prev_match == MTRR_TYPE_WRBACK &&
-		     curr_match == MTRR_TYPE_WRTHROUGH) ||
-		    (prev_match == MTRR_TYPE_WRTHROUGH &&
-		     curr_match == MTRR_TYPE_WRBACK)) {
-			prev_match = MTRR_TYPE_WRTHROUGH;
-			curr_match = MTRR_TYPE_WRTHROUGH;
-		}
-
-		if (prev_match != curr_match)
-			return MTRR_TYPE_UNCACHABLE;
+		if (check_type_overlap(&prev_match, &curr_match))
+			return curr_match;
 	}
 
 	if (mtrr_tom2) {
@@ -166,6 +220,36 @@
 	return mtrr_state.def_type;
 }
 
+/*
+ * Returns the effective MTRR type for the region
+ * Error return:
+ * 0xFF - when MTRR is not enabled
+ */
+u8 mtrr_type_lookup(u64 start, u64 end)
+{
+	u8 type, prev_type;
+	int repeat;
+	u64 partial_end;
+
+	type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
+
+	/*
+	 * Common path is with repeat = 0.
+	 * However, we can have cases where [start:end] spans across some
+	 * MTRR range. Do repeated lookups for that case here.
+	 */
+	while (repeat) {
+		prev_type = type;
+		start = partial_end;
+		type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
+
+		if (check_type_overlap(&prev_type, &type))
+			return type;
+	}
+
+	return type;
+}
+
 /* Get the MSR pair relating to a var range */
 static void
 get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 3efdf28..fe73c18 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -102,6 +102,7 @@
 	 */
 	struct perf_event	*events[X86_PMC_IDX_MAX]; /* in counter order */
 	unsigned long		active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+	unsigned long		running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
 	int			enabled;
 
 	int			n_events;
@@ -530,7 +531,7 @@
 /*
  * Setup the hardware configuration for a given attr_type
  */
-static int __hw_perf_event_init(struct perf_event *event)
+static int __x86_pmu_event_init(struct perf_event *event)
 {
 	int err;
 
@@ -583,7 +584,7 @@
 	}
 }
 
-void hw_perf_disable(void)
+static void x86_pmu_disable(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -618,7 +619,7 @@
 	}
 }
 
-static const struct pmu pmu;
+static struct pmu pmu;
 
 static inline int is_x86_event(struct perf_event *event)
 {
@@ -800,10 +801,10 @@
 		hwc->last_tag == cpuc->tags[i];
 }
 
-static int x86_pmu_start(struct perf_event *event);
-static void x86_pmu_stop(struct perf_event *event);
+static void x86_pmu_start(struct perf_event *event, int flags);
+static void x86_pmu_stop(struct perf_event *event, int flags);
 
-void hw_perf_enable(void)
+static void x86_pmu_enable(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct perf_event *event;
@@ -839,7 +840,14 @@
 			    match_prev_assignment(hwc, cpuc, i))
 				continue;
 
-			x86_pmu_stop(event);
+			/*
+			 * Ensure we don't accidentally enable a stopped
+			 * counter simply because we rescheduled.
+			 */
+			if (hwc->state & PERF_HES_STOPPED)
+				hwc->state |= PERF_HES_ARCH;
+
+			x86_pmu_stop(event, PERF_EF_UPDATE);
 		}
 
 		for (i = 0; i < cpuc->n_events; i++) {
@@ -851,7 +859,10 @@
 			else if (i < n_running)
 				continue;
 
-			x86_pmu_start(event);
+			if (hwc->state & PERF_HES_ARCH)
+				continue;
+
+			x86_pmu_start(event, PERF_EF_RELOAD);
 		}
 		cpuc->n_added = 0;
 		perf_events_lapic_init();
@@ -952,15 +963,12 @@
 }
 
 /*
- * activate a single event
+ * Add a single event to the PMU.
  *
  * The event is added to the group of enabled events
  * but only if it can be scehduled with existing events.
- *
- * Called with PMU disabled. If successful and return value 1,
- * then guaranteed to call perf_enable() and hw_perf_enable()
  */
-static int x86_pmu_enable(struct perf_event *event)
+static int x86_pmu_add(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc;
@@ -969,57 +977,67 @@
 
 	hwc = &event->hw;
 
+	perf_pmu_disable(event->pmu);
 	n0 = cpuc->n_events;
-	n = collect_events(cpuc, event, false);
-	if (n < 0)
-		return n;
+	ret = n = collect_events(cpuc, event, false);
+	if (ret < 0)
+		goto out;
+
+	hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+	if (!(flags & PERF_EF_START))
+		hwc->state |= PERF_HES_ARCH;
 
 	/*
 	 * If group events scheduling transaction was started,
 	 * skip the schedulability test here, it will be peformed
-	 * at commit time(->commit_txn) as a whole
+	 * at commit time (->commit_txn) as a whole
 	 */
 	if (cpuc->group_flag & PERF_EVENT_TXN)
-		goto out;
+		goto done_collect;
 
 	ret = x86_pmu.schedule_events(cpuc, n, assign);
 	if (ret)
-		return ret;
+		goto out;
 	/*
 	 * copy new assignment, now we know it is possible
 	 * will be used by hw_perf_enable()
 	 */
 	memcpy(cpuc->assign, assign, n*sizeof(int));
 
-out:
+done_collect:
 	cpuc->n_events = n;
 	cpuc->n_added += n - n0;
 	cpuc->n_txn += n - n0;
 
-	return 0;
+	ret = 0;
+out:
+	perf_pmu_enable(event->pmu);
+	return ret;
 }
 
-static int x86_pmu_start(struct perf_event *event)
+static void x86_pmu_start(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	int idx = event->hw.idx;
 
-	if (idx == -1)
-		return -EAGAIN;
+	if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+		return;
 
-	x86_perf_event_set_period(event);
+	if (WARN_ON_ONCE(idx == -1))
+		return;
+
+	if (flags & PERF_EF_RELOAD) {
+		WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+		x86_perf_event_set_period(event);
+	}
+
+	event->hw.state = 0;
+
 	cpuc->events[idx] = event;
 	__set_bit(idx, cpuc->active_mask);
+	__set_bit(idx, cpuc->running);
 	x86_pmu.enable(event);
 	perf_event_update_userpage(event);
-
-	return 0;
-}
-
-static void x86_pmu_unthrottle(struct perf_event *event)
-{
-	int ret = x86_pmu_start(event);
-	WARN_ON_ONCE(ret);
 }
 
 void perf_event_print_debug(void)
@@ -1076,27 +1094,29 @@
 	local_irq_restore(flags);
 }
 
-static void x86_pmu_stop(struct perf_event *event)
+static void x86_pmu_stop(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
-	int idx = hwc->idx;
 
-	if (!__test_and_clear_bit(idx, cpuc->active_mask))
-		return;
+	if (__test_and_clear_bit(hwc->idx, cpuc->active_mask)) {
+		x86_pmu.disable(event);
+		cpuc->events[hwc->idx] = NULL;
+		WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+		hwc->state |= PERF_HES_STOPPED;
+	}
 
-	x86_pmu.disable(event);
-
-	/*
-	 * Drain the remaining delta count out of a event
-	 * that we are disabling:
-	 */
-	x86_perf_event_update(event);
-
-	cpuc->events[idx] = NULL;
+	if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+		/*
+		 * Drain the remaining delta count out of a event
+		 * that we are disabling:
+		 */
+		x86_perf_event_update(event);
+		hwc->state |= PERF_HES_UPTODATE;
+	}
 }
 
-static void x86_pmu_disable(struct perf_event *event)
+static void x86_pmu_del(struct perf_event *event, int flags)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	int i;
@@ -1109,7 +1129,7 @@
 	if (cpuc->group_flag & PERF_EVENT_TXN)
 		return;
 
-	x86_pmu_stop(event);
+	x86_pmu_stop(event, PERF_EF_UPDATE);
 
 	for (i = 0; i < cpuc->n_events; i++) {
 		if (event == cpuc->event_list[i]) {
@@ -1132,7 +1152,6 @@
 	struct perf_sample_data data;
 	struct cpu_hw_events *cpuc;
 	struct perf_event *event;
-	struct hw_perf_event *hwc;
 	int idx, handled = 0;
 	u64 val;
 
@@ -1141,11 +1160,18 @@
 	cpuc = &__get_cpu_var(cpu_hw_events);
 
 	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-		if (!test_bit(idx, cpuc->active_mask))
+		if (!test_bit(idx, cpuc->active_mask)) {
+			/*
+			 * Though we deactivated the counter some cpus
+			 * might still deliver spurious interrupts still
+			 * in flight. Catch them:
+			 */
+			if (__test_and_clear_bit(idx, cpuc->running))
+				handled++;
 			continue;
+		}
 
 		event = cpuc->events[idx];
-		hwc = &event->hw;
 
 		val = x86_perf_event_update(event);
 		if (val & (1ULL << (x86_pmu.cntval_bits - 1)))
@@ -1161,7 +1187,7 @@
 			continue;
 
 		if (perf_event_overflow(event, 1, &data, regs))
-			x86_pmu_stop(event);
+			x86_pmu_stop(event, 0);
 	}
 
 	if (handled)
@@ -1170,25 +1196,6 @@
 	return handled;
 }
 
-void smp_perf_pending_interrupt(struct pt_regs *regs)
-{
-	irq_enter();
-	ack_APIC_irq();
-	inc_irq_stat(apic_pending_irqs);
-	perf_event_do_pending();
-	irq_exit();
-}
-
-void set_perf_event_pending(void)
-{
-#ifdef CONFIG_X86_LOCAL_APIC
-	if (!x86_pmu.apic || !x86_pmu_initialized())
-		return;
-
-	apic->send_IPI_self(LOCAL_PENDING_VECTOR);
-#endif
-}
-
 void perf_events_lapic_init(void)
 {
 	if (!x86_pmu.apic || !x86_pmu_initialized())
@@ -1378,7 +1385,6 @@
 		x86_pmu.num_counters = X86_PMC_MAX_GENERIC;
 	}
 	x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
-	perf_max_events = x86_pmu.num_counters;
 
 	if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) {
 		WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
@@ -1414,6 +1420,7 @@
 	pr_info("... fixed-purpose events:   %d\n",     x86_pmu.num_counters_fixed);
 	pr_info("... event mask:             %016Lx\n", x86_pmu.intel_ctrl);
 
+	perf_pmu_register(&pmu);
 	perf_cpu_notifier(x86_pmu_notifier);
 }
 
@@ -1427,10 +1434,11 @@
  * Set the flag to make pmu::enable() not perform the
  * schedulability test, it will be performed at commit time
  */
-static void x86_pmu_start_txn(const struct pmu *pmu)
+static void x86_pmu_start_txn(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
+	perf_pmu_disable(pmu);
 	cpuc->group_flag |= PERF_EVENT_TXN;
 	cpuc->n_txn = 0;
 }
@@ -1440,7 +1448,7 @@
  * Clear the flag and pmu::enable() will perform the
  * schedulability test.
  */
-static void x86_pmu_cancel_txn(const struct pmu *pmu)
+static void x86_pmu_cancel_txn(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -1450,6 +1458,7 @@
 	 */
 	cpuc->n_added -= cpuc->n_txn;
 	cpuc->n_events -= cpuc->n_txn;
+	perf_pmu_enable(pmu);
 }
 
 /*
@@ -1457,7 +1466,7 @@
  * Perform the group schedulability test as a whole
  * Return 0 if success
  */
-static int x86_pmu_commit_txn(const struct pmu *pmu)
+static int x86_pmu_commit_txn(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	int assign[X86_PMC_IDX_MAX];
@@ -1479,22 +1488,10 @@
 	memcpy(cpuc->assign, assign, n*sizeof(int));
 
 	cpuc->group_flag &= ~PERF_EVENT_TXN;
-
+	perf_pmu_enable(pmu);
 	return 0;
 }
 
-static const struct pmu pmu = {
-	.enable		= x86_pmu_enable,
-	.disable	= x86_pmu_disable,
-	.start		= x86_pmu_start,
-	.stop		= x86_pmu_stop,
-	.read		= x86_pmu_read,
-	.unthrottle	= x86_pmu_unthrottle,
-	.start_txn	= x86_pmu_start_txn,
-	.cancel_txn	= x86_pmu_cancel_txn,
-	.commit_txn	= x86_pmu_commit_txn,
-};
-
 /*
  * validate that we can schedule this event
  */
@@ -1569,12 +1566,22 @@
 	return ret;
 }
 
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+int x86_pmu_event_init(struct perf_event *event)
 {
-	const struct pmu *tmp;
+	struct pmu *tmp;
 	int err;
 
-	err = __hw_perf_event_init(event);
+	switch (event->attr.type) {
+	case PERF_TYPE_RAW:
+	case PERF_TYPE_HARDWARE:
+	case PERF_TYPE_HW_CACHE:
+		break;
+
+	default:
+		return -ENOENT;
+	}
+
+	err = __x86_pmu_event_init(event);
 	if (!err) {
 		/*
 		 * we temporarily connect event to its pmu
@@ -1594,27 +1601,32 @@
 	if (err) {
 		if (event->destroy)
 			event->destroy(event);
-		return ERR_PTR(err);
 	}
 
-	return &pmu;
+	return err;
 }
 
+static struct pmu pmu = {
+	.pmu_enable	= x86_pmu_enable,
+	.pmu_disable	= x86_pmu_disable,
+
+	.event_init	= x86_pmu_event_init,
+
+	.add		= x86_pmu_add,
+	.del		= x86_pmu_del,
+	.start		= x86_pmu_start,
+	.stop		= x86_pmu_stop,
+	.read		= x86_pmu_read,
+
+	.start_txn	= x86_pmu_start_txn,
+	.cancel_txn	= x86_pmu_cancel_txn,
+	.commit_txn	= x86_pmu_commit_txn,
+};
+
 /*
  * callchain support
  */
 
-static inline
-void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
-	if (entry->nr < PERF_MAX_STACK_DEPTH)
-		entry->ip[entry->nr++] = ip;
-}
-
-static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry);
-static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_nmi_entry);
-
-
 static void
 backtrace_warning_symbol(void *data, char *msg, unsigned long symbol)
 {
@@ -1635,7 +1647,7 @@
 {
 	struct perf_callchain_entry *entry = data;
 
-	callchain_store(entry, addr);
+	perf_callchain_store(entry, addr);
 }
 
 static const struct stacktrace_ops backtrace_ops = {
@@ -1646,11 +1658,15 @@
 	.walk_stack		= print_context_stack_bp,
 };
 
-static void
-perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
-	callchain_store(entry, PERF_CONTEXT_KERNEL);
-	callchain_store(entry, regs->ip);
+	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+		/* TODO: We don't support guest os callchain now */
+		return;
+	}
+
+	perf_callchain_store(entry, regs->ip);
 
 	dump_trace(NULL, regs, NULL, regs->bp, &backtrace_ops, entry);
 }
@@ -1679,7 +1695,7 @@
 		if (fp < compat_ptr(regs->sp))
 			break;
 
-		callchain_store(entry, frame.return_address);
+		perf_callchain_store(entry, frame.return_address);
 		fp = compat_ptr(frame.next_frame);
 	}
 	return 1;
@@ -1692,19 +1708,20 @@
 }
 #endif
 
-static void
-perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
 	struct stack_frame frame;
 	const void __user *fp;
 
-	if (!user_mode(regs))
-		regs = task_pt_regs(current);
+	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+		/* TODO: We don't support guest os callchain now */
+		return;
+	}
 
 	fp = (void __user *)regs->bp;
 
-	callchain_store(entry, PERF_CONTEXT_USER);
-	callchain_store(entry, regs->ip);
+	perf_callchain_store(entry, regs->ip);
 
 	if (perf_callchain_user32(regs, entry))
 		return;
@@ -1721,52 +1738,11 @@
 		if ((unsigned long)fp < regs->sp)
 			break;
 
-		callchain_store(entry, frame.return_address);
+		perf_callchain_store(entry, frame.return_address);
 		fp = frame.next_frame;
 	}
 }
 
-static void
-perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry)
-{
-	int is_user;
-
-	if (!regs)
-		return;
-
-	is_user = user_mode(regs);
-
-	if (is_user && current->state != TASK_RUNNING)
-		return;
-
-	if (!is_user)
-		perf_callchain_kernel(regs, entry);
-
-	if (current->mm)
-		perf_callchain_user(regs, entry);
-}
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
-{
-	struct perf_callchain_entry *entry;
-
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-		/* TODO: We don't support guest os callchain now */
-		return NULL;
-	}
-
-	if (in_nmi())
-		entry = &__get_cpu_var(pmc_nmi_entry);
-	else
-		entry = &__get_cpu_var(pmc_irq_entry);
-
-	entry->nr = 0;
-
-	perf_do_callchain(regs, entry);
-
-	return entry;
-}
-
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
 	unsigned long ip;
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index c2897b7..46d5844 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -52,7 +52,7 @@
  [ C(DTLB) ] = {
 	[ C(OP_READ) ] = {
 		[ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses        */
-		[ C(RESULT_MISS)   ] = 0x0046, /* L1 DTLB and L2 DLTB Miss   */
+		[ C(RESULT_MISS)   ] = 0x0746, /* L1_DTLB_AND_L2_DLTB_MISS.ALL */
 	},
 	[ C(OP_WRITE) ] = {
 		[ C(RESULT_ACCESS) ] = 0,
@@ -66,7 +66,7 @@
  [ C(ITLB) ] = {
 	[ C(OP_READ) ] = {
 		[ C(RESULT_ACCESS) ] = 0x0080, /* Instruction fecthes        */
-		[ C(RESULT_MISS)   ] = 0x0085, /* Instr. fetch ITLB misses   */
+		[ C(RESULT_MISS)   ] = 0x0385, /* L1_ITLB_AND_L2_ITLB_MISS.ALL */
 	},
 	[ C(OP_WRITE) ] = {
 		[ C(RESULT_ACCESS) ] = -1,
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index ee05c90..c8f5c08 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -713,18 +713,18 @@
 	struct cpu_hw_events *cpuc;
 	int bit, loops;
 	u64 status;
-	int handled = 0;
+	int handled;
 
 	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
 
 	intel_pmu_disable_all();
-	intel_pmu_drain_bts_buffer();
+	handled = intel_pmu_drain_bts_buffer();
 	status = intel_pmu_get_status();
 	if (!status) {
 		intel_pmu_enable_all(0);
-		return 0;
+		return handled;
 	}
 
 	loops = 0;
@@ -763,7 +763,7 @@
 		data.period = event->hw.last_period;
 
 		if (perf_event_overflow(event, 1, &data, regs))
-			x86_pmu_stop(event);
+			x86_pmu_stop(event, 0);
 	}
 
 	/*
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 18018d1..4977f9c 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -214,7 +214,7 @@
 	update_debugctlmsr(debugctlmsr);
 }
 
-static void intel_pmu_drain_bts_buffer(void)
+static int intel_pmu_drain_bts_buffer(void)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct debug_store *ds = cpuc->ds;
@@ -231,16 +231,16 @@
 	struct pt_regs regs;
 
 	if (!event)
-		return;
+		return 0;
 
 	if (!ds)
-		return;
+		return 0;
 
 	at  = (struct bts_record *)(unsigned long)ds->bts_buffer_base;
 	top = (struct bts_record *)(unsigned long)ds->bts_index;
 
 	if (top <= at)
-		return;
+		return 0;
 
 	ds->bts_index = ds->bts_buffer_base;
 
@@ -256,7 +256,7 @@
 	perf_prepare_sample(&header, &data, event, &regs);
 
 	if (perf_output_begin(&handle, event, header.size * (top - at), 1, 1))
-		return;
+		return 1;
 
 	for (; at < top; at++) {
 		data.ip		= at->from;
@@ -270,6 +270,7 @@
 	/* There's new data available. */
 	event->hw.interrupts++;
 	event->pending_kill = POLL_IN;
+	return 1;
 }
 
 /*
@@ -491,7 +492,7 @@
 		regs.flags &= ~PERF_EFLAGS_EXACT;
 
 	if (perf_event_overflow(event, 1, &data, &regs))
-		x86_pmu_stop(event);
+		x86_pmu_stop(event, 0);
 }
 
 static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index b560db3..81400b9 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -18,6 +18,8 @@
 struct p4_event_bind {
 	unsigned int opcode;			/* Event code and ESCR selector */
 	unsigned int escr_msr[2];		/* ESCR MSR for this event */
+	unsigned int escr_emask;		/* valid ESCR EventMask bits */
+	unsigned int shared;			/* event is shared across threads */
 	char cntr[2][P4_CNTR_LIMIT];		/* counter index (offset), -1 on abscence */
 };
 
@@ -66,231 +68,435 @@
 	[P4_EVENT_TC_DELIVER_MODE] = {
 		.opcode		= P4_OPCODE(P4_EVENT_TC_DELIVER_MODE),
 		.escr_msr	= { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DD)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DB)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DI)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BD)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BB)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BI)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, ID),
+		.shared		= 1,
 		.cntr		= { {4, 5, -1}, {6, 7, -1} },
 	},
 	[P4_EVENT_BPU_FETCH_REQUEST] = {
 		.opcode		= P4_OPCODE(P4_EVENT_BPU_FETCH_REQUEST),
 		.escr_msr	= { MSR_P4_BPU_ESCR0, MSR_P4_BPU_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_BPU_FETCH_REQUEST, TCMISS),
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_ITLB_REFERENCE] = {
 		.opcode		= P4_OPCODE(P4_EVENT_ITLB_REFERENCE),
 		.escr_msr	= { MSR_P4_ITLB_ESCR0, MSR_P4_ITLB_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, HIT)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, MISS)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, HIT_UK),
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_MEMORY_CANCEL] = {
 		.opcode		= P4_OPCODE(P4_EVENT_MEMORY_CANCEL),
 		.escr_msr	= { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_CANCEL, ST_RB_FULL)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_CANCEL, 64K_CONF),
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_MEMORY_COMPLETE] = {
 		.opcode		= P4_OPCODE(P4_EVENT_MEMORY_COMPLETE),
 		.escr_msr	= { MSR_P4_SAAT_ESCR0 , MSR_P4_SAAT_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_COMPLETE, LSC)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_COMPLETE, SSC),
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_LOAD_PORT_REPLAY] = {
 		.opcode		= P4_OPCODE(P4_EVENT_LOAD_PORT_REPLAY),
 		.escr_msr	= { MSR_P4_SAAT_ESCR0, MSR_P4_SAAT_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_LOAD_PORT_REPLAY, SPLIT_LD),
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_STORE_PORT_REPLAY] = {
 		.opcode		= P4_OPCODE(P4_EVENT_STORE_PORT_REPLAY),
 		.escr_msr	= { MSR_P4_SAAT_ESCR0 ,  MSR_P4_SAAT_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_STORE_PORT_REPLAY, SPLIT_ST),
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_MOB_LOAD_REPLAY] = {
 		.opcode		= P4_OPCODE(P4_EVENT_MOB_LOAD_REPLAY),
 		.escr_msr	= { MSR_P4_MOB_ESCR0, MSR_P4_MOB_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, NO_STA)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, NO_STD)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, PARTIAL_DATA)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, UNALGN_ADDR),
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_PAGE_WALK_TYPE] = {
 		.opcode		= P4_OPCODE(P4_EVENT_PAGE_WALK_TYPE),
 		.escr_msr	= { MSR_P4_PMH_ESCR0, MSR_P4_PMH_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_PAGE_WALK_TYPE, DTMISS)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_PAGE_WALK_TYPE, ITMISS),
+		.shared		= 1,
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_BSQ_CACHE_REFERENCE] = {
 		.opcode		= P4_OPCODE(P4_EVENT_BSQ_CACHE_REFERENCE),
 		.escr_msr	= { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITS)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITM)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITS)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITM)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_MISS)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_MISS)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, WR_2ndL_MISS),
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_IOQ_ALLOCATION] = {
 		.opcode		= P4_OPCODE(P4_EVENT_IOQ_ALLOCATION),
 		.escr_msr	= { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, DEFAULT)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, ALL_READ)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, ALL_WRITE)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_UC)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WC)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WT)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WP)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WB)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, OWN)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, OTHER)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, PREFETCH),
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_IOQ_ACTIVE_ENTRIES] = {	/* shared ESCR */
 		.opcode		= P4_OPCODE(P4_EVENT_IOQ_ACTIVE_ENTRIES),
 		.escr_msr	= { MSR_P4_FSB_ESCR1,  MSR_P4_FSB_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, DEFAULT)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_READ)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_WRITE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_UC)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WC)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WT)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WP)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WB)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, OWN)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, OTHER)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, PREFETCH),
 		.cntr		= { {2, -1, -1}, {3, -1, -1} },
 	},
 	[P4_EVENT_FSB_DATA_ACTIVITY] = {
 		.opcode		= P4_OPCODE(P4_EVENT_FSB_DATA_ACTIVITY),
 		.escr_msr	= { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_DRV)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OWN)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OTHER)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_DRV)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OWN)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OTHER),
+		.shared		= 1,
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_BSQ_ALLOCATION] = {		/* shared ESCR, broken CCCR1 */
 		.opcode		= P4_OPCODE(P4_EVENT_BSQ_ALLOCATION),
 		.escr_msr	= { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR0 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE0)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE1)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LEN0)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LEN1)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_IO_TYPE)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LOCK_TYPE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_CACHE_TYPE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_SPLIT_TYPE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_DEM_TYPE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_ORD_TYPE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE0)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE1)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE2),
 		.cntr		= { {0, -1, -1}, {1, -1, -1} },
 	},
 	[P4_EVENT_BSQ_ACTIVE_ENTRIES] = {	/* shared ESCR */
 		.opcode		= P4_OPCODE(P4_EVENT_BSQ_ACTIVE_ENTRIES),
 		.escr_msr	= { MSR_P4_BSU_ESCR1 , MSR_P4_BSU_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE0)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE1)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN0)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN1)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_IO_TYPE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LOCK_TYPE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_CACHE_TYPE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_SPLIT_TYPE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_DEM_TYPE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_ORD_TYPE)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE0)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE1)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE2),
 		.cntr		= { {2, -1, -1}, {3, -1, -1} },
 	},
 	[P4_EVENT_SSE_INPUT_ASSIST] = {
 		.opcode		= P4_OPCODE(P4_EVENT_SSE_INPUT_ASSIST),
 		.escr_msr	= { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_SSE_INPUT_ASSIST, ALL),
+		.shared		= 1,
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_PACKED_SP_UOP] = {
 		.opcode		= P4_OPCODE(P4_EVENT_PACKED_SP_UOP),
 		.escr_msr	= { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_PACKED_SP_UOP, ALL),
+		.shared		= 1,
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_PACKED_DP_UOP] = {
 		.opcode		= P4_OPCODE(P4_EVENT_PACKED_DP_UOP),
 		.escr_msr	= { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_PACKED_DP_UOP, ALL),
+		.shared		= 1,
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_SCALAR_SP_UOP] = {
 		.opcode		= P4_OPCODE(P4_EVENT_SCALAR_SP_UOP),
 		.escr_msr	= { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_SCALAR_SP_UOP, ALL),
+		.shared		= 1,
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_SCALAR_DP_UOP] = {
 		.opcode		= P4_OPCODE(P4_EVENT_SCALAR_DP_UOP),
 		.escr_msr	= { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_SCALAR_DP_UOP, ALL),
+		.shared		= 1,
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_64BIT_MMX_UOP] = {
 		.opcode		= P4_OPCODE(P4_EVENT_64BIT_MMX_UOP),
 		.escr_msr	= { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_64BIT_MMX_UOP, ALL),
+		.shared		= 1,
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_128BIT_MMX_UOP] = {
 		.opcode		= P4_OPCODE(P4_EVENT_128BIT_MMX_UOP),
 		.escr_msr	= { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_128BIT_MMX_UOP, ALL),
+		.shared		= 1,
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_X87_FP_UOP] = {
 		.opcode		= P4_OPCODE(P4_EVENT_X87_FP_UOP),
 		.escr_msr	= { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_X87_FP_UOP, ALL),
+		.shared		= 1,
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_TC_MISC] = {
 		.opcode		= P4_OPCODE(P4_EVENT_TC_MISC),
 		.escr_msr	= { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_TC_MISC, FLUSH),
 		.cntr		= { {4, 5, -1}, {6, 7, -1} },
 	},
 	[P4_EVENT_GLOBAL_POWER_EVENTS] = {
 		.opcode		= P4_OPCODE(P4_EVENT_GLOBAL_POWER_EVENTS),
 		.escr_msr	= { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING),
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_TC_MS_XFER] = {
 		.opcode		= P4_OPCODE(P4_EVENT_TC_MS_XFER),
 		.escr_msr	= { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_TC_MS_XFER, CISC),
 		.cntr		= { {4, 5, -1}, {6, 7, -1} },
 	},
 	[P4_EVENT_UOP_QUEUE_WRITES] = {
 		.opcode		= P4_OPCODE(P4_EVENT_UOP_QUEUE_WRITES),
 		.escr_msr	= { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_BUILD)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_DELIVER)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_ROM),
 		.cntr		= { {4, 5, -1}, {6, 7, -1} },
 	},
 	[P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE] = {
 		.opcode		= P4_OPCODE(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE),
 		.escr_msr	= { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR0 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CONDITIONAL)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CALL)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, RETURN)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, INDIRECT),
 		.cntr		= { {4, 5, -1}, {6, 7, -1} },
 	},
 	[P4_EVENT_RETIRED_BRANCH_TYPE] = {
 		.opcode		= P4_OPCODE(P4_EVENT_RETIRED_BRANCH_TYPE),
 		.escr_msr	= { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CONDITIONAL)	|
+			P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CALL)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, RETURN)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, INDIRECT),
 		.cntr		= { {4, 5, -1}, {6, 7, -1} },
 	},
 	[P4_EVENT_RESOURCE_STALL] = {
 		.opcode		= P4_OPCODE(P4_EVENT_RESOURCE_STALL),
 		.escr_msr	= { MSR_P4_ALF_ESCR0, MSR_P4_ALF_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_RESOURCE_STALL, SBFULL),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 	[P4_EVENT_WC_BUFFER] = {
 		.opcode		= P4_OPCODE(P4_EVENT_WC_BUFFER),
 		.escr_msr	= { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_WC_BUFFER, WCB_EVICTS)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_WC_BUFFER, WCB_FULL_EVICTS),
+		.shared		= 1,
 		.cntr		= { {8, 9, -1}, {10, 11, -1} },
 	},
 	[P4_EVENT_B2B_CYCLES] = {
 		.opcode		= P4_OPCODE(P4_EVENT_B2B_CYCLES),
 		.escr_msr	= { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+		.escr_emask	= 0,
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_BNR] = {
 		.opcode		= P4_OPCODE(P4_EVENT_BNR),
 		.escr_msr	= { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+		.escr_emask	= 0,
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_SNOOP] = {
 		.opcode		= P4_OPCODE(P4_EVENT_SNOOP),
 		.escr_msr	= { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+		.escr_emask	= 0,
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_RESPONSE] = {
 		.opcode		= P4_OPCODE(P4_EVENT_RESPONSE),
 		.escr_msr	= { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+		.escr_emask	= 0,
 		.cntr		= { {0, -1, -1}, {2, -1, -1} },
 	},
 	[P4_EVENT_FRONT_END_EVENT] = {
 		.opcode		= P4_OPCODE(P4_EVENT_FRONT_END_EVENT),
 		.escr_msr	= { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_FRONT_END_EVENT, NBOGUS)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_FRONT_END_EVENT, BOGUS),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 	[P4_EVENT_EXECUTION_EVENT] = {
 		.opcode		= P4_OPCODE(P4_EVENT_EXECUTION_EVENT),
 		.escr_msr	= { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 	[P4_EVENT_REPLAY_EVENT] = {
 		.opcode		= P4_OPCODE(P4_EVENT_REPLAY_EVENT),
 		.escr_msr	= { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_REPLAY_EVENT, NBOGUS)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_REPLAY_EVENT, BOGUS),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 	[P4_EVENT_INSTR_RETIRED] = {
 		.opcode		= P4_OPCODE(P4_EVENT_INSTR_RETIRED),
 		.escr_msr	= { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSNTAG)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSTAG)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSNTAG)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSTAG),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 	[P4_EVENT_UOPS_RETIRED] = {
 		.opcode		= P4_OPCODE(P4_EVENT_UOPS_RETIRED),
 		.escr_msr	= { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_UOPS_RETIRED, NBOGUS)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_UOPS_RETIRED, BOGUS),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 	[P4_EVENT_UOP_TYPE] = {
 		.opcode		= P4_OPCODE(P4_EVENT_UOP_TYPE),
 		.escr_msr	= { MSR_P4_RAT_ESCR0, MSR_P4_RAT_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_UOP_TYPE, TAGLOADS)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_UOP_TYPE, TAGSTORES),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 	[P4_EVENT_BRANCH_RETIRED] = {
 		.opcode		= P4_OPCODE(P4_EVENT_BRANCH_RETIRED),
 		.escr_msr	= { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMNP)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMNM)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMTP)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMTM),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 	[P4_EVENT_MISPRED_BRANCH_RETIRED] = {
 		.opcode		= P4_OPCODE(P4_EVENT_MISPRED_BRANCH_RETIRED),
 		.escr_msr	= { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+		.escr_emask	=
+		P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 	[P4_EVENT_X87_ASSIST] = {
 		.opcode		= P4_OPCODE(P4_EVENT_X87_ASSIST),
 		.escr_msr	= { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, FPSU)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, FPSO)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, POAO)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, POAU)			|
+			P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, PREA),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 	[P4_EVENT_MACHINE_CLEAR] = {
 		.opcode		= P4_OPCODE(P4_EVENT_MACHINE_CLEAR),
 		.escr_msr	= { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, CLEAR)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, MOCLEAR)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, SMCLEAR),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 	[P4_EVENT_INSTR_COMPLETED] = {
 		.opcode		= P4_OPCODE(P4_EVENT_INSTR_COMPLETED),
 		.escr_msr	= { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+		.escr_emask	=
+			P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_COMPLETED, NBOGUS)		|
+			P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_COMPLETED, BOGUS),
 		.cntr		= { {12, 13, 16}, {14, 15, 17} },
 	},
 };
@@ -428,29 +634,73 @@
 	return config;
 }
 
-static int p4_validate_raw_event(struct perf_event *event)
+/* check cpu model specifics */
+static bool p4_event_match_cpu_model(unsigned int event_idx)
 {
-	unsigned int v;
-
-	/* user data may have out-of-bound event index */
-	v = p4_config_unpack_event(event->attr.config);
-	if (v >= ARRAY_SIZE(p4_event_bind_map)) {
-		pr_warning("P4 PMU: Unknown event code: %d\n", v);
-		return -EINVAL;
+	/* INSTR_COMPLETED event only exist for model 3, 4, 6 (Prescott) */
+	if (event_idx == P4_EVENT_INSTR_COMPLETED) {
+		if (boot_cpu_data.x86_model != 3 &&
+			boot_cpu_data.x86_model != 4 &&
+			boot_cpu_data.x86_model != 6)
+			return false;
 	}
 
 	/*
-	 * it may have some screwed PEBS bits
+	 * For info
+	 * - IQ_ESCR0, IQ_ESCR1 only for models 1 and 2
 	 */
-	if (p4_config_pebs_has(event->attr.config, P4_PEBS_CONFIG_ENABLE)) {
-		pr_warning("P4 PMU: PEBS are not supported yet\n");
+
+	return true;
+}
+
+static int p4_validate_raw_event(struct perf_event *event)
+{
+	unsigned int v, emask;
+
+	/* User data may have out-of-bound event index */
+	v = p4_config_unpack_event(event->attr.config);
+	if (v >= ARRAY_SIZE(p4_event_bind_map))
 		return -EINVAL;
+
+	/* It may be unsupported: */
+	if (!p4_event_match_cpu_model(v))
+		return -EINVAL;
+
+	/*
+	 * NOTE: P4_CCCR_THREAD_ANY has not the same meaning as
+	 * in Architectural Performance Monitoring, it means not
+	 * on _which_ logical cpu to count but rather _when_, ie it
+	 * depends on logical cpu state -- count event if one cpu active,
+	 * none, both or any, so we just allow user to pass any value
+	 * desired.
+	 *
+	 * In turn we always set Tx_OS/Tx_USR bits bound to logical
+	 * cpu without their propagation to another cpu
+	 */
+
+	/*
+	 * if an event is shared accross the logical threads
+	 * the user needs special permissions to be able to use it
+	 */
+	if (p4_event_bind_map[v].shared) {
+		if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
+			return -EACCES;
 	}
+
+	/* ESCR EventMask bits may be invalid */
+	emask = p4_config_unpack_escr(event->attr.config) & P4_ESCR_EVENTMASK_MASK;
+	if (emask & ~p4_event_bind_map[v].escr_emask)
+		return -EINVAL;
+
+	/*
+	 * it may have some invalid PEBS bits
+	 */
+	if (p4_config_pebs_has(event->attr.config, P4_PEBS_CONFIG_ENABLE))
+		return -EINVAL;
+
 	v = p4_config_unpack_metric(event->attr.config);
-	if (v >= ARRAY_SIZE(p4_pebs_bind_map)) {
-		pr_warning("P4 PMU: Unknown metric code: %d\n", v);
+	if (v >= ARRAY_SIZE(p4_pebs_bind_map))
 		return -EINVAL;
-	}
 
 	return 0;
 }
@@ -478,27 +728,21 @@
 
 	if (event->attr.type == PERF_TYPE_RAW) {
 
+		/*
+		 * Clear bits we reserve to be managed by kernel itself
+		 * and never allowed from a user space
+		 */
+		 event->attr.config &= P4_CONFIG_MASK;
+
 		rc = p4_validate_raw_event(event);
 		if (rc)
 			goto out;
 
 		/*
-		 * We don't control raw events so it's up to the caller
-		 * to pass sane values (and we don't count the thread number
-		 * on HT machine but allow HT-compatible specifics to be
-		 * passed on)
-		 *
 		 * Note that for RAW events we allow user to use P4_CCCR_RESERVED
 		 * bits since we keep additional info here (for cache events and etc)
-		 *
-		 * XXX: HT wide things should check perf_paranoid_cpu() &&
-		 *      CAP_SYS_ADMIN
 		 */
-		event->hw.config |= event->attr.config &
-			(p4_config_pack_escr(P4_ESCR_MASK_HT) |
-			 p4_config_pack_cccr(P4_CCCR_MASK_HT | P4_CCCR_RESERVED));
-
-		event->hw.config &= ~P4_CCCR_FORCE_OVF;
+		event->hw.config |= event->attr.config;
 	}
 
 	rc = x86_setup_perfctr(event);
@@ -660,8 +904,12 @@
 	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
 		int overflow;
 
-		if (!test_bit(idx, cpuc->active_mask))
+		if (!test_bit(idx, cpuc->active_mask)) {
+			/* catch in-flight IRQs */
+			if (__test_and_clear_bit(idx, cpuc->running))
+				handled++;
 			continue;
+		}
 
 		event = cpuc->events[idx];
 		hwc = &event->hw;
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
index fb329e9..d9f4ff8 100644
--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -700,11 +700,10 @@
 {
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
-		if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15 &&
-		    boot_cpu_data.x86 != 16 && boot_cpu_data.x86 != 17)
-			return;
-		wd_ops = &k7_wd_ops;
-		break;
+		if (boot_cpu_data.x86 == 6 ||
+		    (boot_cpu_data.x86 >= 0xf && boot_cpu_data.x86 <= 0x15))
+			wd_ops = &k7_wd_ops;
+		return;
 	case X86_VENDOR_INTEL:
 		/* Work around where perfctr1 doesn't have a working enable
 		 * bit as described in the following errata:
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 34b4dad..c7f64e6 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -31,6 +31,7 @@
 	const struct cpuid_bit *cb;
 
 	static const struct cpuid_bit __cpuinitconst cpuid_bits[] = {
+		{ X86_FEATURE_DTS,		CR_EAX, 0, 0x00000006, 0 },
 		{ X86_FEATURE_IDA,		CR_EAX, 1, 0x00000006, 0 },
 		{ X86_FEATURE_ARAT,		CR_EAX, 2, 0x00000006, 0 },
 		{ X86_FEATURE_PLN,		CR_EAX, 4, 0x00000006, 0 },
@@ -43,6 +44,12 @@
 		{ X86_FEATURE_LBRV,		CR_EDX, 1, 0x8000000a, 0 },
 		{ X86_FEATURE_SVML,		CR_EDX, 2, 0x8000000a, 0 },
 		{ X86_FEATURE_NRIPS,		CR_EDX, 3, 0x8000000a, 0 },
+		{ X86_FEATURE_TSCRATEMSR,	CR_EDX, 4, 0x8000000a, 0 },
+		{ X86_FEATURE_VMCBCLEAN,	CR_EDX, 5, 0x8000000a, 0 },
+		{ X86_FEATURE_FLUSHBYASID,	CR_EDX, 6, 0x8000000a, 0 },
+		{ X86_FEATURE_DECODEASSISTS,	CR_EDX, 7, 0x8000000a, 0 },
+		{ X86_FEATURE_PAUSEFILTER,	CR_EDX,10, 0x8000000a, 0 },
+		{ X86_FEATURE_PFTHRESHOLD,	CR_EDX,12, 0x8000000a, 0 },
 		{ 0, 0, 0, 0, 0 }
 	};
 
diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c
index 045b36c..9948288 100644
--- a/arch/x86/kernel/crash_dump_64.c
+++ b/arch/x86/kernel/crash_dump_64.c
@@ -34,7 +34,7 @@
 	if (!csize)
 		return 0;
 
-	vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
+	vaddr = ioremap_cache(pfn << PAGE_SHIFT, PAGE_SIZE);
 	if (!vaddr)
 		return -ENOMEM;
 
@@ -46,6 +46,7 @@
 	} else
 		memcpy(buf, vaddr + offset, csize);
 
+	set_iounmap_nonlazy();
 	iounmap(vaddr);
 	return csize;
 }
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 0d6fc71..0c2b7ef 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -15,6 +15,7 @@
 #include <linux/pfn.h>
 #include <linux/suspend.h>
 #include <linux/firmware-map.h>
+#include <linux/memblock.h>
 
 #include <asm/e820.h>
 #include <asm/proto.h>
@@ -738,73 +739,7 @@
 #endif
 
 /*
- * Find a free area with specified alignment in a specific range.
- */
-u64 __init find_e820_area(u64 start, u64 end, u64 size, u64 align)
-{
-	int i;
-
-	for (i = 0; i < e820.nr_map; i++) {
-		struct e820entry *ei = &e820.map[i];
-		u64 addr;
-		u64 ei_start, ei_last;
-
-		if (ei->type != E820_RAM)
-			continue;
-
-		ei_last = ei->addr + ei->size;
-		ei_start = ei->addr;
-		addr = find_early_area(ei_start, ei_last, start, end,
-					 size, align);
-
-		if (addr != -1ULL)
-			return addr;
-	}
-	return -1ULL;
-}
-
-u64 __init find_fw_memmap_area(u64 start, u64 end, u64 size, u64 align)
-{
-	return find_e820_area(start, end, size, align);
-}
-
-u64 __init get_max_mapped(void)
-{
-	u64 end = max_pfn_mapped;
-
-	end <<= PAGE_SHIFT;
-
-	return end;
-}
-/*
- * Find next free range after *start
- */
-u64 __init find_e820_area_size(u64 start, u64 *sizep, u64 align)
-{
-	int i;
-
-	for (i = 0; i < e820.nr_map; i++) {
-		struct e820entry *ei = &e820.map[i];
-		u64 addr;
-		u64 ei_start, ei_last;
-
-		if (ei->type != E820_RAM)
-			continue;
-
-		ei_last = ei->addr + ei->size;
-		ei_start = ei->addr;
-		addr = find_early_area_size(ei_start, ei_last, start,
-					 sizep, align);
-
-		if (addr != -1ULL)
-			return addr;
-	}
-
-	return -1ULL;
-}
-
-/*
- * pre allocated 4k and reserved it in e820
+ * pre allocated 4k and reserved it in memblock and e820_saved
  */
 u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
 {
@@ -813,8 +748,8 @@
 	u64 start;
 
 	for (start = startt; ; start += size) {
-		start = find_e820_area_size(start, &size, align);
-		if (!(start + 1))
+		start = memblock_x86_find_in_range_size(start, &size, align);
+		if (start == MEMBLOCK_ERROR)
 			return 0;
 		if (size >= sizet)
 			break;
@@ -830,10 +765,9 @@
 	addr = round_down(start + size - sizet, align);
 	if (addr < start)
 		return 0;
-	e820_update_range(addr, sizet, E820_RAM, E820_RESERVED);
+	memblock_x86_reserve_range(addr, addr + sizet, "new next");
 	e820_update_range_saved(addr, sizet, E820_RAM, E820_RESERVED);
-	printk(KERN_INFO "update e820 for early_reserve_e820\n");
-	update_e820();
+	printk(KERN_INFO "update e820_saved for early_reserve_e820\n");
 	update_e820_saved();
 
 	return addr;
@@ -895,74 +829,6 @@
 {
 	return e820_end_pfn(1UL<<(32 - PAGE_SHIFT), E820_RAM);
 }
-/*
- * Finds an active region in the address range from start_pfn to last_pfn and
- * returns its range in ei_startpfn and ei_endpfn for the e820 entry.
- */
-int __init e820_find_active_region(const struct e820entry *ei,
-				  unsigned long start_pfn,
-				  unsigned long last_pfn,
-				  unsigned long *ei_startpfn,
-				  unsigned long *ei_endpfn)
-{
-	u64 align = PAGE_SIZE;
-
-	*ei_startpfn = round_up(ei->addr, align) >> PAGE_SHIFT;
-	*ei_endpfn = round_down(ei->addr + ei->size, align) >> PAGE_SHIFT;
-
-	/* Skip map entries smaller than a page */
-	if (*ei_startpfn >= *ei_endpfn)
-		return 0;
-
-	/* Skip if map is outside the node */
-	if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
-				    *ei_startpfn >= last_pfn)
-		return 0;
-
-	/* Check for overlaps */
-	if (*ei_startpfn < start_pfn)
-		*ei_startpfn = start_pfn;
-	if (*ei_endpfn > last_pfn)
-		*ei_endpfn = last_pfn;
-
-	return 1;
-}
-
-/* Walk the e820 map and register active regions within a node */
-void __init e820_register_active_regions(int nid, unsigned long start_pfn,
-					 unsigned long last_pfn)
-{
-	unsigned long ei_startpfn;
-	unsigned long ei_endpfn;
-	int i;
-
-	for (i = 0; i < e820.nr_map; i++)
-		if (e820_find_active_region(&e820.map[i],
-					    start_pfn, last_pfn,
-					    &ei_startpfn, &ei_endpfn))
-			add_active_range(nid, ei_startpfn, ei_endpfn);
-}
-
-/*
- * Find the hole size (in bytes) in the memory range.
- * @start: starting address of the memory range to scan
- * @end: ending address of the memory range to scan
- */
-u64 __init e820_hole_size(u64 start, u64 end)
-{
-	unsigned long start_pfn = start >> PAGE_SHIFT;
-	unsigned long last_pfn = end >> PAGE_SHIFT;
-	unsigned long ei_startpfn, ei_endpfn, ram = 0;
-	int i;
-
-	for (i = 0; i < e820.nr_map; i++) {
-		if (e820_find_active_region(&e820.map[i],
-					    start_pfn, last_pfn,
-					    &ei_startpfn, &ei_endpfn))
-			ram += ei_endpfn - ei_startpfn;
-	}
-	return end - start - ((u64)ram << PAGE_SHIFT);
-}
 
 static void early_panic(char *msg)
 {
@@ -1210,3 +1076,48 @@
 	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
 	e820_print_map(who);
 }
+
+void __init memblock_x86_fill(void)
+{
+	int i;
+	u64 end;
+
+	/*
+	 * EFI may have more than 128 entries
+	 * We are safe to enable resizing, beause memblock_x86_fill()
+	 * is rather later for x86
+	 */
+	memblock_can_resize = 1;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+
+		end = ei->addr + ei->size;
+		if (end != (resource_size_t)end)
+			continue;
+
+		if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN)
+			continue;
+
+		memblock_add(ei->addr, ei->size);
+	}
+
+	memblock_analyze();
+	memblock_dump_all();
+}
+
+void __init memblock_find_dma_reserve(void)
+{
+#ifdef CONFIG_X86_64
+	u64 free_size_pfn;
+	u64 mem_size_pfn;
+	/*
+	 * need to find out used area below MAX_DMA_PFN
+	 * need to use memblock to get free size in [0, MAX_DMA_PFN]
+	 * at first, and assume boot_mem will not take below MAX_DMA_PFN
+	 */
+	mem_size_pfn = memblock_x86_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT;
+	free_size_pfn = memblock_x86_free_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT;
+	set_dma_reserve(mem_size_pfn - free_size_pfn);
+#endif
+}
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index ebdb85c..76b8cd9 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -97,7 +97,6 @@
 }
 
 #if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC)
-#if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC)
 static u32 __init ati_ixp4x0_rev(int num, int slot, int func)
 {
 	u32 d;
@@ -115,7 +114,6 @@
 	d &= 0xff;
 	return d;
 }
-#endif
 
 static void __init ati_bugs(int num, int slot, int func)
 {
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index fa99bae..4572f25 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -14,6 +14,7 @@
 #include <xen/hvc-console.h>
 #include <asm/pci-direct.h>
 #include <asm/fixmap.h>
+#include <asm/mrst.h>
 #include <asm/pgtable.h>
 #include <linux/usb/ehci_def.h>
 
@@ -239,6 +240,18 @@
 		if (!strncmp(buf, "xen", 3))
 			early_console_register(&xenboot_console, keep);
 #endif
+#ifdef CONFIG_X86_MRST_EARLY_PRINTK
+		if (!strncmp(buf, "mrst", 4)) {
+			mrst_early_console_init();
+			early_console_register(&early_mrst_console, keep);
+		}
+
+		if (!strncmp(buf, "hsu", 3)) {
+			hsu_early_console_init();
+			early_console_register(&early_hsu_console, keep);
+		}
+
+#endif
 		buf++;
 	}
 	return 0;
diff --git a/arch/x86/kernel/early_printk_mrst.c b/arch/x86/kernel/early_printk_mrst.c
new file mode 100644
index 0000000..65df603
--- /dev/null
+++ b/arch/x86/kernel/early_printk_mrst.c
@@ -0,0 +1,319 @@
+/*
+ * early_printk_mrst.c - early consoles for Intel MID platforms
+ *
+ * Copyright (c) 2008-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.
+ */
+
+/*
+ * This file implements two early consoles named mrst and hsu.
+ * mrst is based on Maxim3110 spi-uart device, it exists in both
+ * Moorestown and Medfield platforms, while hsu is based on a High
+ * Speed UART device which only exists in the Medfield platform
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/serial_mfd.h>
+#include <linux/kmsg_dump.h>
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+#include <asm/mrst.h>
+
+#define MRST_SPI_TIMEOUT		0x200000
+#define MRST_REGBASE_SPI0		0xff128000
+#define MRST_REGBASE_SPI1		0xff128400
+#define MRST_CLK_SPI0_REG		0xff11d86c
+
+/* 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_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)
+
+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;
+
+	/* Currently operates as 32 bits, though only the low 16 bits matter */
+	u32	dr;
+} __packed;
+
+#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
+#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
+
+/* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */
+static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0;
+
+static u32 *pclk_spi0;
+/* Always contains an accessable address, start with 0 */
+static struct dw_spi_reg *pspi;
+
+static struct kmsg_dumper dw_dumper;
+static int dumper_registered;
+
+static void dw_kmsg_dump(struct kmsg_dumper *dumper,
+			enum kmsg_dump_reason reason,
+			const char *s1, unsigned long l1,
+			const char *s2, unsigned long l2)
+{
+	int i;
+
+	/* When run to this, we'd better re-init the HW */
+	mrst_early_console_init();
+
+	for (i = 0; i < l1; i++)
+		early_mrst_console.write(&early_mrst_console, s1 + i, 1);
+	for (i = 0; i < l2; i++)
+		early_mrst_console.write(&early_mrst_console, s2 + i, 1);
+}
+
+/* Set the ratio rate to 115200, 8n1, IRQ disabled */
+static void max3110_write_config(void)
+{
+	u16 config;
+
+	config = 0xc001;
+	dw_writel(pspi, dr, config);
+}
+
+/* Translate char to a eligible word and send to max3110 */
+static void max3110_write_data(char c)
+{
+	u16 data;
+
+	data = 0x8000 | c;
+	dw_writel(pspi, dr, data);
+}
+
+void mrst_early_console_init(void)
+{
+	u32 ctrlr0 = 0;
+	u32 spi0_cdiv;
+	u32 freq; /* Freqency info only need be searched once */
+
+	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
+	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+							MRST_CLK_SPI0_REG);
+	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
+	freq = 100000000 / (spi0_cdiv + 1);
+
+	if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL)
+		mrst_spi_paddr = MRST_REGBASE_SPI1;
+
+	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+						mrst_spi_paddr);
+
+	/* Disable SPI controller */
+	dw_writel(pspi, ssienr, 0);
+
+	/* Set control param, 8 bits, transmit only mode */
+	ctrlr0 = dw_readl(pspi, ctrl0);
+
+	ctrlr0 &= 0xfcc0;
+	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
+		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
+	dw_writel(pspi, ctrl0, ctrlr0);
+
+	/*
+	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
+	 * calculate the clk dividor to make the clock a little slower
+	 * than real baud rate.
+	 */
+	dw_writel(pspi, baudr, freq/100000);
+
+	/* Disable all INT for early phase */
+	dw_writel(pspi, imr, 0x0);
+
+	/* Set the cs to spi-uart */
+	dw_writel(pspi, ser, 0x2);
+
+	/* Enable the HW, the last step for HW init */
+	dw_writel(pspi, ssienr, 0x1);
+
+	/* Set the default configuration */
+	max3110_write_config();
+
+	/* Register the kmsg dumper */
+	if (!dumper_registered) {
+		dw_dumper.dump = dw_kmsg_dump;
+		kmsg_dump_register(&dw_dumper);
+		dumper_registered = 1;
+	}
+}
+
+/* Slave select should be called in the read/write function */
+static void early_mrst_spi_putc(char c)
+{
+	unsigned int timeout;
+	u32 sr;
+
+	timeout = MRST_SPI_TIMEOUT;
+	/* Early putc needs to make sure the TX FIFO is not full */
+	while (--timeout) {
+		sr = dw_readl(pspi, sr);
+		if (!(sr & SR_TF_NOT_FULL))
+			cpu_relax();
+		else
+			break;
+	}
+
+	if (!timeout)
+		pr_warning("MRST earlycon: timed out\n");
+	else
+		max3110_write_data(c);
+}
+
+/* Early SPI only uses polling mode */
+static void early_mrst_spi_write(struct console *con, const char *str, unsigned n)
+{
+	int i;
+
+	for (i = 0; i < n && *str; i++) {
+		if (*str == '\n')
+			early_mrst_spi_putc('\r');
+		early_mrst_spi_putc(*str);
+		str++;
+	}
+}
+
+struct console early_mrst_console = {
+	.name =		"earlymrst",
+	.write =	early_mrst_spi_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
+/*
+ * Following is the early console based on Medfield HSU (High
+ * Speed UART) device.
+ */
+#define HSU_PORT2_PADDR		0xffa28180
+
+static void __iomem *phsu;
+
+void hsu_early_console_init(void)
+{
+	u8 lcr;
+
+	phsu = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+							HSU_PORT2_PADDR);
+
+	/* Disable FIFO */
+	writeb(0x0, phsu + UART_FCR);
+
+	/* Set to default 115200 bps, 8n1 */
+	lcr = readb(phsu + UART_LCR);
+	writeb((0x80 | lcr), phsu + UART_LCR);
+	writeb(0x18, phsu + UART_DLL);
+	writeb(lcr,  phsu + UART_LCR);
+	writel(0x3600, phsu + UART_MUL*4);
+
+	writeb(0x8, phsu + UART_MCR);
+	writeb(0x7, phsu + UART_FCR);
+	writeb(0x3, phsu + UART_LCR);
+
+	/* Clear IRQ status */
+	readb(phsu + UART_LSR);
+	readb(phsu + UART_RX);
+	readb(phsu + UART_IIR);
+	readb(phsu + UART_MSR);
+
+	/* Enable FIFO */
+	writeb(0x7, phsu + UART_FCR);
+}
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+static void early_hsu_putc(char ch)
+{
+	unsigned int timeout = 10000; /* 10ms */
+	u8 status;
+
+	while (--timeout) {
+		status = readb(phsu + UART_LSR);
+		if (status & BOTH_EMPTY)
+			break;
+		udelay(1);
+	}
+
+	/* Only write the char when there was no timeout */
+	if (timeout)
+		writeb(ch, phsu + UART_TX);
+}
+
+static void early_hsu_write(struct console *con, const char *str, unsigned n)
+{
+	int i;
+
+	for (i = 0; i < n && *str; i++) {
+		if (*str == '\n')
+			early_hsu_putc('\r');
+		early_hsu_putc(*str);
+		str++;
+	}
+}
+
+struct console early_hsu_console = {
+	.name =		"earlyhsu",
+	.write =	early_hsu_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c
index c2fa9b8..0fe27d7 100644
--- a/arch/x86/kernel/efi.c
+++ b/arch/x86/kernel/efi.c
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/efi.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
 #include <linux/time.h>
@@ -275,7 +276,7 @@
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 }
 
-void __init efi_reserve_early(void)
+void __init efi_memblock_x86_reserve_range(void)
 {
 	unsigned long pmap;
 
@@ -290,7 +291,7 @@
 		boot_params.efi_info.efi_memdesc_size;
 	memmap.desc_version = boot_params.efi_info.efi_memdesc_version;
 	memmap.desc_size = boot_params.efi_info.efi_memdesc_size;
-	reserve_early(pmap, pmap + memmap.nr_map * memmap.desc_size,
+	memblock_x86_reserve_range(pmap, pmap + memmap.nr_map * memmap.desc_size,
 		      "EFI memmap");
 }
 
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 227d009..59e175e 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -115,8 +115,7 @@
 
  /* unfortunately push/pop can't be no-op */
 .macro PUSH_GS
-	pushl $0
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $0
 .endm
 .macro POP_GS pop=0
 	addl $(4 + \pop), %esp
@@ -140,14 +139,12 @@
 #else	/* CONFIG_X86_32_LAZY_GS */
 
 .macro PUSH_GS
-	pushl %gs
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %gs
 	/*CFI_REL_OFFSET gs, 0*/
 .endm
 
 .macro POP_GS pop=0
-98:	popl %gs
-	CFI_ADJUST_CFA_OFFSET -4
+98:	popl_cfi %gs
 	/*CFI_RESTORE gs*/
   .if \pop <> 0
 	add $\pop, %esp
@@ -195,35 +192,25 @@
 .macro SAVE_ALL
 	cld
 	PUSH_GS
-	pushl %fs
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %fs
 	/*CFI_REL_OFFSET fs, 0;*/
-	pushl %es
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %es
 	/*CFI_REL_OFFSET es, 0;*/
-	pushl %ds
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ds
 	/*CFI_REL_OFFSET ds, 0;*/
-	pushl %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %eax
 	CFI_REL_OFFSET eax, 0
-	pushl %ebp
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebp
 	CFI_REL_OFFSET ebp, 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
-	pushl %edx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %edx
 	CFI_REL_OFFSET edx, 0
-	pushl %ecx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ecx
 	CFI_REL_OFFSET ecx, 0
-	pushl %ebx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebx
 	CFI_REL_OFFSET ebx, 0
 	movl $(__USER_DS), %edx
 	movl %edx, %ds
@@ -234,39 +221,29 @@
 .endm
 
 .macro RESTORE_INT_REGS
-	popl %ebx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebx
 	CFI_RESTORE ebx
-	popl %ecx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ecx
 	CFI_RESTORE ecx
-	popl %edx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %edx
 	CFI_RESTORE edx
-	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 %ebp
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebp
 	CFI_RESTORE ebp
-	popl %eax
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %eax
 	CFI_RESTORE eax
 .endm
 
 .macro RESTORE_REGS pop=0
 	RESTORE_INT_REGS
-1:	popl %ds
-	CFI_ADJUST_CFA_OFFSET -4
+1:	popl_cfi %ds
 	/*CFI_RESTORE ds;*/
-2:	popl %es
-	CFI_ADJUST_CFA_OFFSET -4
+2:	popl_cfi %es
 	/*CFI_RESTORE es;*/
-3:	popl %fs
-	CFI_ADJUST_CFA_OFFSET -4
+3:	popl_cfi %fs
 	/*CFI_RESTORE fs;*/
 	POP_GS \pop
 .pushsection .fixup, "ax"
@@ -320,16 +297,12 @@
 
 ENTRY(ret_from_fork)
 	CFI_STARTPROC
-	pushl %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %eax
 	call schedule_tail
 	GET_THREAD_INFO(%ebp)
-	popl %eax
-	CFI_ADJUST_CFA_OFFSET -4
-	pushl $0x0202			# Reset kernel eflags
-	CFI_ADJUST_CFA_OFFSET 4
-	popfl
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %eax
+	pushl_cfi $0x0202		# Reset kernel eflags
+	popfl_cfi
 	jmp syscall_exit
 	CFI_ENDPROC
 END(ret_from_fork)
@@ -409,29 +382,23 @@
 	 * enough kernel state to call TRACE_IRQS_OFF can be called - but
 	 * we immediately enable interrupts at that point anyway.
 	 */
-	pushl $(__USER_DS)
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $__USER_DS
 	/*CFI_REL_OFFSET ss, 0*/
-	pushl %ebp
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebp
 	CFI_REL_OFFSET esp, 0
-	pushfl
+	pushfl_cfi
 	orl $X86_EFLAGS_IF, (%esp)
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl $(__USER_CS)
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $__USER_CS
 	/*CFI_REL_OFFSET cs, 0*/
 	/*
 	 * Push current_thread_info()->sysenter_return to the stack.
 	 * 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 (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi (TI_sysenter_return-THREAD_SIZE_asm+8+4*4)(%esp)
 	CFI_REL_OFFSET eip, 0
 
-	pushl %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %eax
 	SAVE_ALL
 	ENABLE_INTERRUPTS(CLBR_NONE)
 
@@ -486,8 +453,7 @@
 	movl %eax,%edx			/* 2nd arg: syscall number */
 	movl $AUDIT_ARCH_I386,%eax	/* 1st arg: audit arch */
 	call audit_syscall_entry
-	pushl %ebx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebx
 	movl PT_EAX(%esp),%eax		/* reload syscall number */
 	jmp sysenter_do_call
 
@@ -529,8 +495,7 @@
 	# system call handler stub
 ENTRY(system_call)
 	RING0_INT_FRAME			# can't unwind into user space anyway
-	pushl %eax			# save orig_eax
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %eax			# save orig_eax
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
 					# system call tracing in operation / emulation
@@ -566,7 +531,6 @@
 	je ldt_ss			# returning to user-space with LDT SS
 restore_nocheck:
 	RESTORE_REGS 4			# skip orig_eax/error_code
-	CFI_ADJUST_CFA_OFFSET -4
 irq_return:
 	INTERRUPT_RETURN
 .section .fixup,"ax"
@@ -619,10 +583,8 @@
 	shr $16, %edx
 	mov %dl, GDT_ESPFIX_SS + 4 /* bits 16..23 */
 	mov %dh, GDT_ESPFIX_SS + 7 /* bits 24..31 */
-	pushl $__ESPFIX_SS
-	CFI_ADJUST_CFA_OFFSET 4
-	push %eax			/* new kernel esp */
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $__ESPFIX_SS
+	pushl_cfi %eax			/* new kernel esp */
 	/* Disable interrupts, but do not irqtrace this section: we
 	 * will soon execute iret and the tracer was already set to
 	 * the irqstate after the iret */
@@ -666,11 +628,9 @@
 
 	ALIGN
 work_notifysig_v86:
-	pushl %ecx			# save ti_flags for do_notify_resume
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ecx			# save ti_flags for do_notify_resume
 	call save_v86_state		# %eax contains pt_regs pointer
-	popl %ecx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ecx
 	movl %eax, %esp
 #else
 	movl %esp, %eax
@@ -750,14 +710,18 @@
 #define PTREGSCALL3(name) \
 	ALIGN; \
 ptregs_##name: \
+	CFI_STARTPROC; \
 	leal 4(%esp),%eax; \
-	pushl %eax; \
+	pushl_cfi %eax; \
 	movl PT_EDX(%eax),%ecx; \
 	movl PT_ECX(%eax),%edx; \
 	movl PT_EBX(%eax),%eax; \
 	call sys_##name; \
 	addl $4,%esp; \
-	ret
+	CFI_ADJUST_CFA_OFFSET -4; \
+	ret; \
+	CFI_ENDPROC; \
+ENDPROC(ptregs_##name)
 
 PTREGSCALL1(iopl)
 PTREGSCALL0(fork)
@@ -772,15 +736,19 @@
 /* Clone is an oddball.  The 4th arg is in %edi */
 	ALIGN;
 ptregs_clone:
+	CFI_STARTPROC
 	leal 4(%esp),%eax
-	pushl %eax
-	pushl PT_EDI(%eax)
+	pushl_cfi %eax
+	pushl_cfi PT_EDI(%eax)
 	movl PT_EDX(%eax),%ecx
 	movl PT_ECX(%eax),%edx
 	movl PT_EBX(%eax),%eax
 	call sys_clone
 	addl $8,%esp
+	CFI_ADJUST_CFA_OFFSET -8
 	ret
+	CFI_ENDPROC
+ENDPROC(ptregs_clone)
 
 .macro FIXUP_ESPFIX_STACK
 /*
@@ -795,10 +763,8 @@
 	mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */
 	shl $16, %eax
 	addl %esp, %eax			/* the adjusted stack pointer */
-	pushl $__KERNEL_DS
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $__KERNEL_DS
+	pushl_cfi %eax
 	lss (%esp), %esp		/* switch to the normal stack segment */
 	CFI_ADJUST_CFA_OFFSET -8
 .endm
@@ -835,8 +801,7 @@
       .if vector <> FIRST_EXTERNAL_VECTOR
 	CFI_ADJUST_CFA_OFFSET -4
       .endif
-1:	pushl $(~vector+0x80)	/* Note: always in signed byte range */
-	CFI_ADJUST_CFA_OFFSET 4
+1:	pushl_cfi $(~vector+0x80)	/* Note: always in signed byte range */
       .if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6
 	jmp 2f
       .endif
@@ -876,8 +841,7 @@
 #define BUILD_INTERRUPT3(name, nr, fn)	\
 ENTRY(name)				\
 	RING0_INT_FRAME;		\
-	pushl $~(nr);			\
-	CFI_ADJUST_CFA_OFFSET 4;	\
+	pushl_cfi $~(nr);		\
 	SAVE_ALL;			\
 	TRACE_IRQS_OFF			\
 	movl %esp,%eax;			\
@@ -893,21 +857,18 @@
 
 ENTRY(coprocessor_error)
 	RING0_INT_FRAME
-	pushl $0
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl $do_coprocessor_error
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $0
+	pushl_cfi $do_coprocessor_error
 	jmp error_code
 	CFI_ENDPROC
 END(coprocessor_error)
 
 ENTRY(simd_coprocessor_error)
 	RING0_INT_FRAME
-	pushl $0
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $0
 #ifdef CONFIG_X86_INVD_BUG
 	/* AMD 486 bug: invd from userspace calls exception 19 instead of #GP */
-661:	pushl $do_general_protection
+661:	pushl_cfi $do_general_protection
 662:
 .section .altinstructions,"a"
 	.balign 4
@@ -922,19 +883,16 @@
 664:
 .previous
 #else
-	pushl $do_simd_coprocessor_error
+	pushl_cfi $do_simd_coprocessor_error
 #endif
-	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
 	CFI_ENDPROC
 END(simd_coprocessor_error)
 
 ENTRY(device_not_available)
 	RING0_INT_FRAME
-	pushl $-1			# mark this as an int
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl $do_device_not_available
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $-1			# mark this as an int
+	pushl_cfi $do_device_not_available
 	jmp error_code
 	CFI_ENDPROC
 END(device_not_available)
@@ -956,82 +914,68 @@
 
 ENTRY(overflow)
 	RING0_INT_FRAME
-	pushl $0
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl $do_overflow
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $0
+	pushl_cfi $do_overflow
 	jmp error_code
 	CFI_ENDPROC
 END(overflow)
 
 ENTRY(bounds)
 	RING0_INT_FRAME
-	pushl $0
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl $do_bounds
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $0
+	pushl_cfi $do_bounds
 	jmp error_code
 	CFI_ENDPROC
 END(bounds)
 
 ENTRY(invalid_op)
 	RING0_INT_FRAME
-	pushl $0
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl $do_invalid_op
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $0
+	pushl_cfi $do_invalid_op
 	jmp error_code
 	CFI_ENDPROC
 END(invalid_op)
 
 ENTRY(coprocessor_segment_overrun)
 	RING0_INT_FRAME
-	pushl $0
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl $do_coprocessor_segment_overrun
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $0
+	pushl_cfi $do_coprocessor_segment_overrun
 	jmp error_code
 	CFI_ENDPROC
 END(coprocessor_segment_overrun)
 
 ENTRY(invalid_TSS)
 	RING0_EC_FRAME
-	pushl $do_invalid_TSS
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $do_invalid_TSS
 	jmp error_code
 	CFI_ENDPROC
 END(invalid_TSS)
 
 ENTRY(segment_not_present)
 	RING0_EC_FRAME
-	pushl $do_segment_not_present
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $do_segment_not_present
 	jmp error_code
 	CFI_ENDPROC
 END(segment_not_present)
 
 ENTRY(stack_segment)
 	RING0_EC_FRAME
-	pushl $do_stack_segment
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $do_stack_segment
 	jmp error_code
 	CFI_ENDPROC
 END(stack_segment)
 
 ENTRY(alignment_check)
 	RING0_EC_FRAME
-	pushl $do_alignment_check
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $do_alignment_check
 	jmp error_code
 	CFI_ENDPROC
 END(alignment_check)
 
 ENTRY(divide_error)
 	RING0_INT_FRAME
-	pushl $0			# no error code
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl $do_divide_error
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $0			# no error code
+	pushl_cfi $do_divide_error
 	jmp error_code
 	CFI_ENDPROC
 END(divide_error)
@@ -1039,10 +983,8 @@
 #ifdef CONFIG_X86_MCE
 ENTRY(machine_check)
 	RING0_INT_FRAME
-	pushl $0
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl machine_check_vector
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $0
+	pushl_cfi machine_check_vector
 	jmp error_code
 	CFI_ENDPROC
 END(machine_check)
@@ -1050,10 +992,8 @@
 
 ENTRY(spurious_interrupt_bug)
 	RING0_INT_FRAME
-	pushl $0
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl $do_spurious_interrupt_bug
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $0
+	pushl_cfi $do_spurious_interrupt_bug
 	jmp error_code
 	CFI_ENDPROC
 END(spurious_interrupt_bug)
@@ -1084,8 +1024,7 @@
 
 ENTRY(xen_hypervisor_callback)
 	CFI_STARTPROC
-	pushl $0
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $0
 	SAVE_ALL
 	TRACE_IRQS_OFF
 
@@ -1121,23 +1060,20 @@
 # We distinguish between categories by maintaining a status value in EAX.
 ENTRY(xen_failsafe_callback)
 	CFI_STARTPROC
-	pushl %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %eax
 	movl $1,%eax
 1:	mov 4(%esp),%ds
 2:	mov 8(%esp),%es
 3:	mov 12(%esp),%fs
 4:	mov 16(%esp),%gs
 	testl %eax,%eax
-	popl %eax
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %eax
 	lea 16(%esp),%esp
 	CFI_ADJUST_CFA_OFFSET -16
 	jz 5f
 	addl $16,%esp
 	jmp iret_exc		# EAX != 0 => Category 2 (Bad IRET)
-5:	pushl $0		# EAX == 0 => Category 1 (Bad segment)
-	CFI_ADJUST_CFA_OFFSET 4
+5:	pushl_cfi $0		# EAX == 0 => Category 1 (Bad segment)
 	SAVE_ALL
 	jmp ret_from_exception
 	CFI_ENDPROC
@@ -1287,40 +1223,29 @@
 
 ENTRY(page_fault)
 	RING0_EC_FRAME
-	pushl $do_page_fault
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $do_page_fault
 	ALIGN
 error_code:
 	/* the function address is in %gs's slot on the stack */
-	pushl %fs
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %fs
 	/*CFI_REL_OFFSET fs, 0*/
-	pushl %es
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %es
 	/*CFI_REL_OFFSET es, 0*/
-	pushl %ds
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ds
 	/*CFI_REL_OFFSET ds, 0*/
-	pushl %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %eax
 	CFI_REL_OFFSET eax, 0
-	pushl %ebp
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebp
 	CFI_REL_OFFSET ebp, 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
-	pushl %edx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %edx
 	CFI_REL_OFFSET edx, 0
-	pushl %ecx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ecx
 	CFI_REL_OFFSET ecx, 0
-	pushl %ebx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebx
 	CFI_REL_OFFSET ebx, 0
 	cld
 	movl $(__KERNEL_PERCPU), %ecx
@@ -1362,12 +1287,9 @@
 	movl TSS_sysenter_sp0 + \offset(%esp), %esp
 	CFI_DEF_CFA esp, 0
 	CFI_UNDEFINED eip
-	pushfl
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl $__KERNEL_CS
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl $sysenter_past_esp
-	CFI_ADJUST_CFA_OFFSET 4
+	pushfl_cfi
+	pushl_cfi $__KERNEL_CS
+	pushl_cfi $sysenter_past_esp
 	CFI_REL_OFFSET eip, 0
 .endm
 
@@ -1377,8 +1299,7 @@
 	jne debug_stack_correct
 	FIX_STACK 12, debug_stack_correct, debug_esp_fix_insn
 debug_stack_correct:
-	pushl $-1			# mark this as an int
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $-1			# mark this as an int
 	SAVE_ALL
 	TRACE_IRQS_OFF
 	xorl %edx,%edx			# error code 0
@@ -1398,32 +1319,27 @@
  */
 ENTRY(nmi)
 	RING0_INT_FRAME
-	pushl %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %eax
 	movl %ss, %eax
 	cmpw $__ESPFIX_SS, %ax
-	popl %eax
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %eax
 	je nmi_espfix_stack
 	cmpl $ia32_sysenter_target,(%esp)
 	je nmi_stack_fixup
-	pushl %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %eax
 	movl %esp,%eax
 	/* Do not access memory above the end of our stack page,
 	 * it might not exist.
 	 */
 	andl $(THREAD_SIZE-1),%eax
 	cmpl $(THREAD_SIZE-20),%eax
-	popl %eax
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %eax
 	jae nmi_stack_correct
 	cmpl $ia32_sysenter_target,12(%esp)
 	je nmi_debug_stack_check
 nmi_stack_correct:
 	/* We have a RING0_INT_FRAME here */
-	pushl %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %eax
 	SAVE_ALL
 	xorl %edx,%edx		# zero error code
 	movl %esp,%eax		# pt_regs pointer
@@ -1452,18 +1368,14 @@
 	 *
 	 * create the pointer to lss back
 	 */
-	pushl %ss
-	CFI_ADJUST_CFA_OFFSET 4
-	pushl %esp
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ss
+	pushl_cfi %esp
 	addl $4, (%esp)
 	/* copy the iret frame of 12 bytes */
 	.rept 3
-	pushl 16(%esp)
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi 16(%esp)
 	.endr
-	pushl %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %eax
 	SAVE_ALL
 	FIXUP_ESPFIX_STACK		# %eax == %esp
 	xorl %edx,%edx			# zero error code
@@ -1477,8 +1389,7 @@
 
 ENTRY(int3)
 	RING0_INT_FRAME
-	pushl $-1			# mark this as an int
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $-1			# mark this as an int
 	SAVE_ALL
 	TRACE_IRQS_OFF
 	xorl %edx,%edx		# zero error code
@@ -1490,8 +1401,7 @@
 
 ENTRY(general_protection)
 	RING0_EC_FRAME
-	pushl $do_general_protection
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $do_general_protection
 	jmp error_code
 	CFI_ENDPROC
 END(general_protection)
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 17be5ec..fe2690d 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -213,23 +213,17 @@
 	.macro FAKE_STACK_FRAME child_rip
 	/* push in order ss, rsp, eflags, cs, rip */
 	xorl %eax, %eax
-	pushq $__KERNEL_DS /* ss */
-	CFI_ADJUST_CFA_OFFSET	8
+	pushq_cfi $__KERNEL_DS /* ss */
 	/*CFI_REL_OFFSET	ss,0*/
-	pushq %rax /* rsp */
-	CFI_ADJUST_CFA_OFFSET	8
+	pushq_cfi %rax /* rsp */
 	CFI_REL_OFFSET	rsp,0
-	pushq $X86_EFLAGS_IF /* eflags - interrupts on */
-	CFI_ADJUST_CFA_OFFSET	8
+	pushq_cfi $X86_EFLAGS_IF /* eflags - interrupts on */
 	/*CFI_REL_OFFSET	rflags,0*/
-	pushq $__KERNEL_CS /* cs */
-	CFI_ADJUST_CFA_OFFSET	8
+	pushq_cfi $__KERNEL_CS /* cs */
 	/*CFI_REL_OFFSET	cs,0*/
-	pushq \child_rip /* rip */
-	CFI_ADJUST_CFA_OFFSET	8
+	pushq_cfi \child_rip /* rip */
 	CFI_REL_OFFSET	rip,0
-	pushq	%rax /* orig rax */
-	CFI_ADJUST_CFA_OFFSET	8
+	pushq_cfi %rax /* orig rax */
 	.endm
 
 	.macro UNFAKE_STACK_FRAME
@@ -398,10 +392,8 @@
 
 	LOCK ; btr $TIF_FORK,TI_flags(%r8)
 
-	push kernel_eflags(%rip)
-	CFI_ADJUST_CFA_OFFSET 8
-	popf					# reset kernel eflags
-	CFI_ADJUST_CFA_OFFSET -8
+	pushq_cfi kernel_eflags(%rip)
+	popfq_cfi				# reset kernel eflags
 
 	call schedule_tail			# rdi: 'prev' task parameter
 
@@ -521,11 +513,9 @@
 	jnc sysret_signal
 	TRACE_IRQS_ON
 	ENABLE_INTERRUPTS(CLBR_NONE)
-	pushq %rdi
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi %rdi
 	call schedule
-	popq  %rdi
-	CFI_ADJUST_CFA_OFFSET -8
+	popq_cfi %rdi
 	jmp sysret_check
 
 	/* Handle a signal */
@@ -634,11 +624,9 @@
 	jnc  int_very_careful
 	TRACE_IRQS_ON
 	ENABLE_INTERRUPTS(CLBR_NONE)
-	pushq %rdi
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi %rdi
 	call schedule
-	popq %rdi
-	CFI_ADJUST_CFA_OFFSET -8
+	popq_cfi %rdi
 	DISABLE_INTERRUPTS(CLBR_NONE)
 	TRACE_IRQS_OFF
 	jmp int_with_check
@@ -652,12 +640,10 @@
 	/* Check for syscall exit trace */
 	testl $_TIF_WORK_SYSCALL_EXIT,%edx
 	jz int_signal
-	pushq %rdi
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi %rdi
 	leaq 8(%rsp),%rdi	# &ptregs -> arg1
 	call syscall_trace_leave
-	popq %rdi
-	CFI_ADJUST_CFA_OFFSET -8
+	popq_cfi %rdi
 	andl $~(_TIF_WORK_SYSCALL_EXIT|_TIF_SYSCALL_EMU),%edi
 	jmp int_restore_rest
 
@@ -714,9 +700,8 @@
 
 ENTRY(stub_execve)
 	CFI_STARTPROC
-	popq %r11
-	CFI_ADJUST_CFA_OFFSET -8
-	CFI_REGISTER rip, r11
+	addq $8, %rsp
+	PARTIAL_FRAME 0
 	SAVE_REST
 	FIXUP_TOP_OF_STACK %r11
 	movq %rsp, %rcx
@@ -735,7 +720,7 @@
 ENTRY(stub_rt_sigreturn)
 	CFI_STARTPROC
 	addq $8, %rsp
-	CFI_ADJUST_CFA_OFFSET	-8
+	PARTIAL_FRAME 0
 	SAVE_REST
 	movq %rsp,%rdi
 	FIXUP_TOP_OF_STACK %r11
@@ -766,8 +751,7 @@
       .if vector <> FIRST_EXTERNAL_VECTOR
 	CFI_ADJUST_CFA_OFFSET -8
       .endif
-1:	pushq $(~vector+0x80)	/* Note: always in signed byte range */
-	CFI_ADJUST_CFA_OFFSET 8
+1:	pushq_cfi $(~vector+0x80)	/* Note: always in signed byte range */
       .if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6
 	jmp 2f
       .endif
@@ -796,8 +780,8 @@
 
 /* 0(%rsp): ~(interrupt number) */
 	.macro interrupt func
-	subq $10*8, %rsp
-	CFI_ADJUST_CFA_OFFSET 10*8
+	subq $ORIG_RAX-ARGOFFSET+8, %rsp
+	CFI_ADJUST_CFA_OFFSET ORIG_RAX-ARGOFFSET+8
 	call save_args
 	PARTIAL_FRAME 0
 	call \func
@@ -822,6 +806,7 @@
 	TRACE_IRQS_OFF
 	decl PER_CPU_VAR(irq_count)
 	leaveq
+	CFI_RESTORE		rbp
 	CFI_DEF_CFA_REGISTER	rsp
 	CFI_ADJUST_CFA_OFFSET	-8
 exit_intr:
@@ -903,11 +888,9 @@
 	jnc   retint_signal
 	TRACE_IRQS_ON
 	ENABLE_INTERRUPTS(CLBR_NONE)
-	pushq %rdi
-	CFI_ADJUST_CFA_OFFSET	8
+	pushq_cfi %rdi
 	call  schedule
-	popq %rdi
-	CFI_ADJUST_CFA_OFFSET	-8
+	popq_cfi %rdi
 	GET_THREAD_INFO(%rcx)
 	DISABLE_INTERRUPTS(CLBR_NONE)
 	TRACE_IRQS_OFF
@@ -956,8 +939,7 @@
 .macro apicinterrupt num sym do_sym
 ENTRY(\sym)
 	INTR_FRAME
-	pushq $~(\num)
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi $~(\num)
 	interrupt \do_sym
 	jmp ret_from_intr
 	CFI_ENDPROC
@@ -981,22 +963,10 @@
 	x86_platform_ipi smp_x86_platform_ipi
 
 #ifdef CONFIG_SMP
-apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \
-	invalidate_interrupt0 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+1 \
-	invalidate_interrupt1 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+2 \
-	invalidate_interrupt2 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+3 \
-	invalidate_interrupt3 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+4 \
-	invalidate_interrupt4 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+5 \
-	invalidate_interrupt5 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+6 \
-	invalidate_interrupt6 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+7 \
-	invalidate_interrupt7 smp_invalidate_interrupt
+.irpc idx, "01234567"
+apicinterrupt (INVALIDATE_TLB_VECTOR_START)+\idx \
+	invalidate_interrupt\idx smp_invalidate_interrupt
+.endr
 #endif
 
 apicinterrupt THRESHOLD_APIC_VECTOR \
@@ -1023,9 +993,9 @@
 apicinterrupt SPURIOUS_APIC_VECTOR \
 	spurious_interrupt smp_spurious_interrupt
 
-#ifdef CONFIG_PERF_EVENTS
-apicinterrupt LOCAL_PENDING_VECTOR \
-	perf_pending_interrupt smp_perf_pending_interrupt
+#ifdef CONFIG_IRQ_WORK
+apicinterrupt IRQ_WORK_VECTOR \
+	irq_work_interrupt smp_irq_work_interrupt
 #endif
 
 /*
@@ -1036,8 +1006,8 @@
 	INTR_FRAME
 	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	pushq_cfi $-1		/* ORIG_RAX: no syscall to restart */
-	subq $15*8,%rsp
-	CFI_ADJUST_CFA_OFFSET 15*8
+	subq $ORIG_RAX-R15, %rsp
+	CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
 	call error_entry
 	DEFAULT_FRAME 0
 	movq %rsp,%rdi		/* pt_regs pointer */
@@ -1052,9 +1022,9 @@
 ENTRY(\sym)
 	INTR_FRAME
 	PARAVIRT_ADJUST_EXCEPTION_FRAME
-	pushq $-1		/* ORIG_RAX: no syscall to restart */
-	CFI_ADJUST_CFA_OFFSET 8
-	subq $15*8, %rsp
+	pushq_cfi $-1		/* ORIG_RAX: no syscall to restart */
+	subq $ORIG_RAX-R15, %rsp
+	CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
 	call save_paranoid
 	TRACE_IRQS_OFF
 	movq %rsp,%rdi		/* pt_regs pointer */
@@ -1070,9 +1040,9 @@
 ENTRY(\sym)
 	INTR_FRAME
 	PARAVIRT_ADJUST_EXCEPTION_FRAME
-	pushq $-1		/* ORIG_RAX: no syscall to restart */
-	CFI_ADJUST_CFA_OFFSET 8
-	subq $15*8, %rsp
+	pushq_cfi $-1		/* ORIG_RAX: no syscall to restart */
+	subq $ORIG_RAX-R15, %rsp
+	CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
 	call save_paranoid
 	TRACE_IRQS_OFF
 	movq %rsp,%rdi		/* pt_regs pointer */
@@ -1089,8 +1059,8 @@
 ENTRY(\sym)
 	XCPT_FRAME
 	PARAVIRT_ADJUST_EXCEPTION_FRAME
-	subq $15*8,%rsp
-	CFI_ADJUST_CFA_OFFSET 15*8
+	subq $ORIG_RAX-R15, %rsp
+	CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
 	call error_entry
 	DEFAULT_FRAME 0
 	movq %rsp,%rdi			/* pt_regs pointer */
@@ -1107,8 +1077,8 @@
 ENTRY(\sym)
 	XCPT_FRAME
 	PARAVIRT_ADJUST_EXCEPTION_FRAME
-	subq $15*8,%rsp
-	CFI_ADJUST_CFA_OFFSET 15*8
+	subq $ORIG_RAX-R15, %rsp
+	CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
 	call save_paranoid
 	DEFAULT_FRAME 0
 	TRACE_IRQS_OFF
@@ -1139,16 +1109,14 @@
 	/* edi:  new selector */
 ENTRY(native_load_gs_index)
 	CFI_STARTPROC
-	pushf
-	CFI_ADJUST_CFA_OFFSET 8
+	pushfq_cfi
 	DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI)
 	SWAPGS
 gs_change:
 	movl %edi,%gs
 2:	mfence		/* workaround */
 	SWAPGS
-	popf
-	CFI_ADJUST_CFA_OFFSET -8
+	popfq_cfi
 	ret
 	CFI_ENDPROC
 END(native_load_gs_index)
@@ -1215,8 +1183,7 @@
 /* Call softirq on interrupt stack. Interrupts are off. */
 ENTRY(call_softirq)
 	CFI_STARTPROC
-	push %rbp
-	CFI_ADJUST_CFA_OFFSET	8
+	pushq_cfi %rbp
 	CFI_REL_OFFSET rbp,0
 	mov  %rsp,%rbp
 	CFI_DEF_CFA_REGISTER rbp
@@ -1225,6 +1192,7 @@
 	push  %rbp			# backlink for old unwinder
 	call __do_softirq
 	leaveq
+	CFI_RESTORE		rbp
 	CFI_DEF_CFA_REGISTER	rsp
 	CFI_ADJUST_CFA_OFFSET   -8
 	decl PER_CPU_VAR(irq_count)
@@ -1368,7 +1336,7 @@
 
 	/* ebx:	no swapgs flag */
 ENTRY(paranoid_exit)
-	INTR_FRAME
+	DEFAULT_FRAME
 	DISABLE_INTERRUPTS(CLBR_NONE)
 	TRACE_IRQS_OFF
 	testl %ebx,%ebx				/* swapgs needed? */
@@ -1445,7 +1413,6 @@
 error_sti:
 	TRACE_IRQS_OFF
 	ret
-	CFI_ENDPROC
 
 /*
  * There are two places in the kernel that can potentially fault with
@@ -1470,6 +1437,7 @@
 	/* Fix truncated RIP */
 	movq %rcx,RIP+8(%rsp)
 	jmp error_swapgs
+	CFI_ENDPROC
 END(error_entry)
 
 
@@ -1498,8 +1466,8 @@
 	INTR_FRAME
 	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	pushq_cfi $-1
-	subq $15*8, %rsp
-	CFI_ADJUST_CFA_OFFSET 15*8
+	subq $ORIG_RAX-R15, %rsp
+	CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
 	call save_paranoid
 	DEFAULT_FRAME 0
 	/* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index cd37469..3afb33f 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -257,14 +257,9 @@
 	return mod_code_status;
 }
 
-
-
-
-static unsigned char ftrace_nop[MCOUNT_INSN_SIZE];
-
 static unsigned char *ftrace_nop_replace(void)
 {
-	return ftrace_nop;
+	return ideal_nop5;
 }
 
 static int
@@ -338,62 +333,6 @@
 
 int __init ftrace_dyn_arch_init(void *data)
 {
-	extern const unsigned char ftrace_test_p6nop[];
-	extern const unsigned char ftrace_test_nop5[];
-	extern const unsigned char ftrace_test_jmp[];
-	int faulted = 0;
-
-	/*
-	 * There is no good nop for all x86 archs.
-	 * We will default to using the P6_NOP5, but first we
-	 * will test to make sure that the nop will actually
-	 * work on this CPU. If it faults, we will then
-	 * go to a lesser efficient 5 byte nop. If that fails
-	 * we then just use a jmp as our nop. This isn't the most
-	 * efficient nop, but we can not use a multi part nop
-	 * since we would then risk being preempted in the middle
-	 * of that nop, and if we enabled tracing then, it might
-	 * cause a system crash.
-	 *
-	 * TODO: check the cpuid to determine the best nop.
-	 */
-	asm volatile (
-		"ftrace_test_jmp:"
-		"jmp ftrace_test_p6nop\n"
-		"nop\n"
-		"nop\n"
-		"nop\n"  /* 2 byte jmp + 3 bytes */
-		"ftrace_test_p6nop:"
-		P6_NOP5
-		"jmp 1f\n"
-		"ftrace_test_nop5:"
-		".byte 0x66,0x66,0x66,0x66,0x90\n"
-		"1:"
-		".section .fixup, \"ax\"\n"
-		"2:	movl $1, %0\n"
-		"	jmp ftrace_test_nop5\n"
-		"3:	movl $2, %0\n"
-		"	jmp 1b\n"
-		".previous\n"
-		_ASM_EXTABLE(ftrace_test_p6nop, 2b)
-		_ASM_EXTABLE(ftrace_test_nop5, 3b)
-		: "=r"(faulted) : "0" (faulted));
-
-	switch (faulted) {
-	case 0:
-		pr_info("converting mcount calls to 0f 1f 44 00 00\n");
-		memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE);
-		break;
-	case 1:
-		pr_info("converting mcount calls to 66 66 66 66 90\n");
-		memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE);
-		break;
-	case 2:
-		pr_info("converting mcount calls to jmp . + 5\n");
-		memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE);
-		break;
-	}
-
 	/* The return code is retured via data */
 	*(unsigned long *)data = 0;
 
diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c
index 3e66bd3..af0699b 100644
--- a/arch/x86/kernel/head.c
+++ b/arch/x86/kernel/head.c
@@ -1,5 +1,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/memblock.h>
 
 #include <asm/setup.h>
 #include <asm/bios_ebda.h>
@@ -51,5 +52,5 @@
 		lowmem = 0x9f000;
 
 	/* reserve all memory between lowmem and the 1MB mark */
-	reserve_early_overlap_ok(lowmem, 0x100000, "BIOS reserved");
+	memblock_x86_reserve_range(lowmem, 0x100000, "* BIOS reserved");
 }
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 784360c..7633101 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/start_kernel.h>
 #include <linux/mm.h>
+#include <linux/memblock.h>
 
 #include <asm/setup.h>
 #include <asm/sections.h>
@@ -17,6 +18,7 @@
 #include <asm/apic.h>
 #include <asm/io_apic.h>
 #include <asm/bios_ebda.h>
+#include <asm/tlbflush.h>
 
 static void __init i386_default_early_setup(void)
 {
@@ -30,17 +32,18 @@
 
 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)
 	 */
-	reserve_early_overlap_ok(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE,
-					 "EX TRAMPOLINE");
+	memblock_x86_reserve_range(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE");
 #endif
 
-	reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+	memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Reserve INITRD */
@@ -49,7 +52,7 @@
 		u64 ramdisk_image = boot_params.hdr.ramdisk_image;
 		u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
 		u64 ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size);
-		reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
+		memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK");
 	}
 #endif
 
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 7147143..2d2673c 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -12,6 +12,7 @@
 #include <linux/percpu.h>
 #include <linux/start_kernel.h>
 #include <linux/io.h>
+#include <linux/memblock.h>
 
 #include <asm/processor.h>
 #include <asm/proto.h>
@@ -79,6 +80,8 @@
 	/* Cleanup the over mapped high alias */
 	cleanup_highmap();
 
+	max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
+
 	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
 #ifdef CONFIG_EARLY_PRINTK
 		set_intr_gate(i, &early_idt_handlers[i]);
@@ -98,7 +101,9 @@
 {
 	copy_bootdata(__va(real_mode_data));
 
-	reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+	memblock_init();
+
+	memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Reserve INITRD */
@@ -107,7 +112,7 @@
 		unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
 		unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
 		unsigned long ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size);
-		reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
+		memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK");
 	}
 #endif
 
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index fa8c1b8..bcece91 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -183,13 +183,12 @@
 #ifdef CONFIG_X86_PAE
 
 	/*
-	 * In PAE mode swapper_pg_dir is statically defined to contain enough
-	 * entries to cover the VMSPLIT option (that is the top 1, 2 or 3
-	 * entries). The identity mapping is handled by pointing two PGD
-	 * entries to the first kernel PMD.
+	 * In PAE mode initial_page_table is statically defined to contain
+	 * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
+	 * entries). The identity mapping is handled by pointing two PGD entries
+	 * to the first kernel PMD.
 	 *
-	 * Note the upper half of each PMD or PTE are always zero at
-	 * this stage.
+	 * Note the upper half of each PMD or PTE are always zero at this stage.
 	 */
 
 #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
@@ -197,7 +196,7 @@
 	xorl %ebx,%ebx				/* %ebx is kept at zero */
 
 	movl $pa(__brk_base), %edi
-	movl $pa(swapper_pg_pmd), %edx
+	movl $pa(initial_pg_pmd), %edx
 	movl $PTE_IDENT_ATTR, %eax
 10:
 	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PMD entry */
@@ -226,14 +225,14 @@
 	movl %eax, pa(max_pfn_mapped)
 
 	/* Do early initialization of the fixmap area */
-	movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
-	movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8)
+	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+	movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
 #else	/* Not PAE */
 
 page_pde_offset = (__PAGE_OFFSET >> 20);
 
 	movl $pa(__brk_base), %edi
-	movl $pa(swapper_pg_dir), %edx
+	movl $pa(initial_page_table), %edx
 	movl $PTE_IDENT_ATTR, %eax
 10:
 	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PDE entry */
@@ -257,8 +256,8 @@
 	movl %eax, pa(max_pfn_mapped)
 
 	/* Do early initialization of the fixmap area */
-	movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
-	movl %eax,pa(swapper_pg_dir+0xffc)
+	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+	movl %eax,pa(initial_page_table+0xffc)
 #endif
 	jmp 3f
 /*
@@ -334,7 +333,7 @@
 /*
  * Enable paging
  */
-	movl pa(initial_page_table), %eax
+	movl $pa(initial_page_table), %eax
 	movl %eax,%cr3		/* set the page table pointer.. */
 	movl %cr0,%eax
 	orl  $X86_CR0_PG,%eax
@@ -614,8 +613,6 @@
 .align 4
 ENTRY(initial_code)
 	.long i386_start_kernel
-ENTRY(initial_page_table)
-	.long pa(swapper_pg_dir)
 
 /*
  * BSS section
@@ -623,20 +620,18 @@
 __PAGE_ALIGNED_BSS
 	.align PAGE_SIZE_asm
 #ifdef CONFIG_X86_PAE
-swapper_pg_pmd:
+initial_pg_pmd:
 	.fill 1024*KPMDS,4,0
 #else
-ENTRY(swapper_pg_dir)
+ENTRY(initial_page_table)
 	.fill 1024,4,0
 #endif
-swapper_pg_fixmap:
+initial_pg_fixmap:
 	.fill 1024,4,0
-#ifdef CONFIG_X86_TRAMPOLINE
-ENTRY(trampoline_pg_dir)
-	.fill 1024,4,0
-#endif
 ENTRY(empty_zero_page)
 	.fill 4096,1,0
+ENTRY(swapper_pg_dir)
+	.fill 1024,4,0
 
 /*
  * This starts the data section.
@@ -645,20 +640,20 @@
 __PAGE_ALIGNED_DATA
 	/* Page-aligned for the benefit of paravirt? */
 	.align PAGE_SIZE_asm
-ENTRY(swapper_pg_dir)
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR),0	/* low identity map */
+ENTRY(initial_page_table)
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0	/* low identity map */
 # if KPMDS == 3
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x2000),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR+0x2000),0
 # elif KPMDS == 2
 	.long	0,0
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
 # elif KPMDS == 1
 	.long	0,0
 	.long	0,0
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
 # else
 #  error "Kernel PMDs should be 1, 2 or 3"
 # endif
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 410fdb3..aff0b3c 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -380,44 +380,35 @@
 			   struct clock_event_device *evt, int timer)
 {
 	u32 cnt;
+	s32 res;
 
 	cnt = hpet_readl(HPET_COUNTER);
 	cnt += (u32) delta;
 	hpet_writel(cnt, HPET_Tn_CMP(timer));
 
 	/*
-	 * We need to read back the CMP register on certain HPET
-	 * implementations (ATI chipsets) which seem to delay the
-	 * transfer of the compare register into the internal compare
-	 * logic. With small deltas this might actually be too late as
-	 * the counter could already be higher than the compare value
-	 * at that point and we would wait for the next hpet interrupt
-	 * forever. We found out that reading the CMP register back
-	 * forces the transfer so we can rely on the comparison with
-	 * the counter register below. If the read back from the
-	 * compare register does not match the value we programmed
-	 * then we might have a real hardware problem. We can not do
-	 * much about it here, but at least alert the user/admin with
-	 * a prominent warning.
-	 *
-	 * An erratum on some chipsets (ICH9,..), results in
-	 * comparator read immediately following a write returning old
-	 * value. Workaround for this is to read this value second
-	 * time, when first read returns old value.
-	 *
-	 * In fact the write to the comparator register is delayed up
-	 * to two HPET cycles so the workaround we tried to restrict
-	 * the readback to those known to be borked ATI chipsets
-	 * failed miserably. So we give up on optimizations forever
-	 * and penalize all HPET incarnations unconditionally.
+	 * HPETs are a complete disaster. The compare register is
+	 * based on a equal comparison and neither provides a less
+	 * than or equal functionality (which would require to take
+	 * the wraparound into account) nor a simple count down event
+	 * mode. Further the write to the comparator register is
+	 * delayed internally up to two HPET clock cycles in certain
+	 * chipsets (ATI, ICH9,10). We worked around that by reading
+	 * back the compare register, but that required another
+	 * workaround for ICH9,10 chips where the first readout after
+	 * write can return the old stale value. We already have a
+	 * minimum delta of 5us enforced, but a NMI or SMI hitting
+	 * between the counter readout and the comparator write can
+	 * move us behind that point easily. Now instead of reading
+	 * the compare register back several times, we make the ETIME
+	 * decision based on the following: Return ETIME if the
+	 * counter value after the write is less than 8 HPET cycles
+	 * away from the event or if the counter is already ahead of
+	 * the event.
 	 */
-	if (unlikely((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt)) {
-		if (hpet_readl(HPET_Tn_CMP(timer)) != cnt)
-			printk_once(KERN_WARNING
-				"hpet: compare register read back failed.\n");
-	}
+	res = (s32)(cnt - hpet_readl(HPET_COUNTER));
 
-	return (s32)(hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
+	return res < 8 ? -ETIME : 0;
 }
 
 static void hpet_legacy_set_mode(enum clock_event_mode mode,
@@ -440,9 +431,9 @@
 static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
 static struct hpet_dev	*hpet_devs;
 
-void hpet_msi_unmask(unsigned int irq)
+void hpet_msi_unmask(struct irq_data *data)
 {
-	struct hpet_dev *hdev = get_irq_data(irq);
+	struct hpet_dev *hdev = data->handler_data;
 	unsigned int cfg;
 
 	/* unmask it */
@@ -451,10 +442,10 @@
 	hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
 }
 
-void hpet_msi_mask(unsigned int irq)
+void hpet_msi_mask(struct irq_data *data)
 {
+	struct hpet_dev *hdev = data->handler_data;
 	unsigned int cfg;
-	struct hpet_dev *hdev = get_irq_data(irq);
 
 	/* mask it */
 	cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
@@ -462,18 +453,14 @@
 	hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
 }
 
-void hpet_msi_write(unsigned int irq, struct msi_msg *msg)
+void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg)
 {
-	struct hpet_dev *hdev = get_irq_data(irq);
-
 	hpet_writel(msg->data, HPET_Tn_ROUTE(hdev->num));
 	hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hdev->num) + 4);
 }
 
-void hpet_msi_read(unsigned int irq, struct msi_msg *msg)
+void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg)
 {
-	struct hpet_dev *hdev = get_irq_data(irq);
-
 	msg->data = hpet_readl(HPET_Tn_ROUTE(hdev->num));
 	msg->address_lo = hpet_readl(HPET_Tn_ROUTE(hdev->num) + 4);
 	msg->address_hi = 0;
@@ -506,7 +493,7 @@
 {
 	unsigned int irq;
 
-	irq = create_irq();
+	irq = create_irq_nr(0, -1);
 	if (!irq)
 		return -EINVAL;
 
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index a46cb35..58bb239 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -68,19 +68,22 @@
 	 */
 
 	if (!HAVE_HWFP) {
+		/*
+		 * Disable xsave as we do not support it if i387
+		 * emulation is enabled.
+		 */
+		setup_clear_cpu_cap(X86_FEATURE_XSAVE);
+		setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
 		xstate_size = sizeof(struct i387_soft_struct);
 		return;
 	}
 
 	if (cpu_has_fxsr)
 		xstate_size = sizeof(struct i387_fxsave_struct);
-#ifdef CONFIG_X86_32
 	else
 		xstate_size = sizeof(struct i387_fsave_struct);
-#endif
 }
 
-#ifdef CONFIG_X86_64
 /*
  * Called at bootup to set up the initial FPU state that is later cloned
  * into all processes.
@@ -88,12 +91,21 @@
 
 void __cpuinit fpu_init(void)
 {
-	unsigned long oldcr0 = read_cr0();
+	unsigned long cr0;
+	unsigned long cr4_mask = 0;
 
-	set_in_cr4(X86_CR4_OSFXSR);
-	set_in_cr4(X86_CR4_OSXMMEXCPT);
+	if (cpu_has_fxsr)
+		cr4_mask |= X86_CR4_OSFXSR;
+	if (cpu_has_xmm)
+		cr4_mask |= X86_CR4_OSXMMEXCPT;
+	if (cr4_mask)
+		set_in_cr4(cr4_mask);
 
-	write_cr0(oldcr0 & ~(X86_CR0_TS|X86_CR0_EM)); /* clear TS and EM */
+	cr0 = read_cr0();
+	cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */
+	if (!HAVE_HWFP)
+		cr0 |= X86_CR0_EM;
+	write_cr0(cr0);
 
 	if (!smp_processor_id())
 		init_thread_xstate();
@@ -104,24 +116,12 @@
 	clear_used_math();
 }
 
-#else	/* CONFIG_X86_64 */
-
-void __cpuinit fpu_init(void)
-{
-	if (!smp_processor_id())
-		init_thread_xstate();
-}
-
-#endif	/* CONFIG_X86_32 */
-
 void fpu_finit(struct fpu *fpu)
 {
-#ifdef CONFIG_X86_32
 	if (!HAVE_HWFP) {
 		finit_soft_fpu(&fpu->state->soft);
 		return;
 	}
-#endif
 
 	if (cpu_has_fxsr) {
 		struct i387_fxsave_struct *fx = &fpu->state->fxsave;
@@ -386,19 +386,17 @@
 #ifdef CONFIG_X86_64
 	env->fip = fxsave->rip;
 	env->foo = fxsave->rdp;
+	/*
+	 * should be actually ds/cs at fpu exception time, but
+	 * that information is not available in 64bit mode.
+	 */
+	env->fcs = task_pt_regs(tsk)->cs;
 	if (tsk == current) {
-		/*
-		 * should be actually ds/cs at fpu exception time, but
-		 * that information is not available in 64bit mode.
-		 */
-		asm("mov %%ds, %[fos]" : [fos] "=r" (env->fos));
-		asm("mov %%cs, %[fcs]" : [fcs] "=r" (env->fcs));
+		savesegment(ds, env->fos);
 	} else {
-		struct pt_regs *regs = task_pt_regs(tsk);
-
-		env->fos = 0xffff0000 | tsk->thread.ds;
-		env->fcs = regs->cs;
+		env->fos = tsk->thread.ds;
 	}
+	env->fos |= 0xffff0000;
 #else
 	env->fip = fxsave->fip;
 	env->fcs = (u16) fxsave->fcs | ((u32) fxsave->fop << 16);
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index cafa7c8..20757cb 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -29,24 +29,10 @@
  * plus some generic x86 specific things if generic specifics makes
  * any sense at all.
  */
+static void init_8259A(int auto_eoi);
 
 static int i8259A_auto_eoi;
 DEFINE_RAW_SPINLOCK(i8259A_lock);
-static void mask_and_ack_8259A(unsigned int);
-static void mask_8259A(void);
-static void unmask_8259A(void);
-static void disable_8259A_irq(unsigned int irq);
-static void enable_8259A_irq(unsigned int irq);
-static void init_8259A(int auto_eoi);
-static int i8259A_irq_pending(unsigned int irq);
-
-struct irq_chip i8259A_chip = {
-	.name		= "XT-PIC",
-	.mask		= disable_8259A_irq,
-	.disable	= disable_8259A_irq,
-	.unmask		= enable_8259A_irq,
-	.mask_ack	= mask_and_ack_8259A,
-};
 
 /*
  * 8259A PIC functions to handle ISA devices:
@@ -68,7 +54,7 @@
  */
 unsigned long io_apic_irqs;
 
-static void disable_8259A_irq(unsigned int irq)
+static void mask_8259A_irq(unsigned int irq)
 {
 	unsigned int mask = 1 << irq;
 	unsigned long flags;
@@ -82,7 +68,12 @@
 	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
-static void enable_8259A_irq(unsigned int irq)
+static void disable_8259A_irq(struct irq_data *data)
+{
+	mask_8259A_irq(data->irq);
+}
+
+static void unmask_8259A_irq(unsigned int irq)
 {
 	unsigned int mask = ~(1 << irq);
 	unsigned long flags;
@@ -96,6 +87,11 @@
 	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
+static void enable_8259A_irq(struct irq_data *data)
+{
+	unmask_8259A_irq(data->irq);
+}
+
 static int i8259A_irq_pending(unsigned int irq)
 {
 	unsigned int mask = 1<<irq;
@@ -117,7 +113,7 @@
 	disable_irq_nosync(irq);
 	io_apic_irqs &= ~(1<<irq);
 	set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
-				      "XT");
+				      i8259A_chip.name);
 	enable_irq(irq);
 }
 
@@ -150,8 +146,9 @@
  * first, _then_ send the EOI, and the order of EOI
  * to the two 8259s is important!
  */
-static void mask_and_ack_8259A(unsigned int irq)
+static void mask_and_ack_8259A(struct irq_data *data)
 {
+	unsigned int irq = data->irq;
 	unsigned int irqmask = 1 << irq;
 	unsigned long flags;
 
@@ -223,6 +220,14 @@
 	}
 }
 
+struct irq_chip i8259A_chip = {
+	.name		= "XT-PIC",
+	.irq_mask	= disable_8259A_irq,
+	.irq_disable	= disable_8259A_irq,
+	.irq_unmask	= enable_8259A_irq,
+	.irq_mask_ack	= mask_and_ack_8259A,
+};
+
 static char irq_trigger[2];
 /**
  * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
@@ -342,9 +347,9 @@
 		 * In AEOI mode we just have to mask the interrupt
 		 * when acking.
 		 */
-		i8259A_chip.mask_ack = disable_8259A_irq;
+		i8259A_chip.irq_mask_ack = disable_8259A_irq;
 	else
-		i8259A_chip.mask_ack = mask_and_ack_8259A;
+		i8259A_chip.irq_mask_ack = mask_and_ack_8259A;
 
 	udelay(100);		/* wait for 8259A to initialize */
 
@@ -363,14 +368,6 @@
 static void legacy_pic_noop(void) { };
 static void legacy_pic_uint_noop(unsigned int unused) { };
 static void legacy_pic_int_noop(int unused) { };
-
-static struct irq_chip dummy_pic_chip  = {
-	.name = "dummy pic",
-	.mask = legacy_pic_uint_noop,
-	.unmask = legacy_pic_uint_noop,
-	.disable = legacy_pic_uint_noop,
-	.mask_ack = legacy_pic_uint_noop,
-};
 static int legacy_pic_irq_pending_noop(unsigned int irq)
 {
 	return 0;
@@ -378,7 +375,9 @@
 
 struct legacy_pic null_legacy_pic = {
 	.nr_legacy_irqs = 0,
-	.chip = &dummy_pic_chip,
+	.chip = &dummy_irq_chip,
+	.mask = legacy_pic_uint_noop,
+	.unmask = legacy_pic_uint_noop,
 	.mask_all = legacy_pic_noop,
 	.restore_mask = legacy_pic_noop,
 	.init = legacy_pic_int_noop,
@@ -389,7 +388,9 @@
 struct legacy_pic default_legacy_pic = {
 	.nr_legacy_irqs = NR_IRQS_LEGACY,
 	.chip  = &i8259A_chip,
-	.mask_all  = mask_8259A,
+	.mask = mask_8259A_irq,
+	.unmask = unmask_8259A_irq,
+	.mask_all = mask_8259A,
 	.restore_mask = unmask_8259A,
 	.init = init_8259A,
 	.irq_pending = i8259A_irq_pending,
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 91fd0c7..83ec017 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -67,10 +67,10 @@
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
 	seq_printf(p, "  Performance monitoring interrupts\n");
-	seq_printf(p, "%*s: ", prec, "PND");
+	seq_printf(p, "%*s: ", prec, "IWI");
 	for_each_online_cpu(j)
-		seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
-	seq_printf(p, "  Performance pending work\n");
+		seq_printf(p, "%10u ", irq_stats(j)->apic_irq_work_irqs);
+	seq_printf(p, "  IRQ work interrupts\n");
 #endif
 	if (x86_platform_ipi_callback) {
 		seq_printf(p, "%*s: ", prec, "PLT");
@@ -159,7 +159,7 @@
 	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->chip->name);
+	seq_printf(p, " %8s", desc->irq_data.chip->name);
 	seq_printf(p, "-%-8s", desc->name);
 
 	if (action) {
@@ -185,7 +185,7 @@
 	sum += irq_stats(cpu)->apic_timer_irqs;
 	sum += irq_stats(cpu)->irq_spurious_count;
 	sum += irq_stats(cpu)->apic_perf_irqs;
-	sum += irq_stats(cpu)->apic_pending_irqs;
+	sum += irq_stats(cpu)->apic_irq_work_irqs;
 #endif
 	if (x86_platform_ipi_callback)
 		sum += irq_stats(cpu)->x86_platform_ipis;
@@ -282,6 +282,7 @@
 	unsigned int irq, vector;
 	static int warned;
 	struct irq_desc *desc;
+	struct irq_data *data;
 
 	for_each_irq_desc(irq, desc) {
 		int break_affinity = 0;
@@ -296,7 +297,8 @@
 		/* interrupt's are disabled at this point */
 		raw_spin_lock(&desc->lock);
 
-		affinity = desc->affinity;
+		data = &desc->irq_data;
+		affinity = data->affinity;
 		if (!irq_has_action(irq) ||
 		    cpumask_equal(affinity, cpu_online_mask)) {
 			raw_spin_unlock(&desc->lock);
@@ -315,16 +317,16 @@
 			affinity = cpu_all_mask;
 		}
 
-		if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->mask)
-			desc->chip->mask(irq);
+		if (!(desc->status & IRQ_MOVE_PCNTXT) && data->chip->irq_mask)
+			data->chip->irq_mask(data);
 
-		if (desc->chip->set_affinity)
-			desc->chip->set_affinity(irq, affinity);
+		if (data->chip->irq_set_affinity)
+			data->chip->irq_set_affinity(data, affinity, true);
 		else if (!(warned++))
 			set_affinity = 0;
 
-		if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->unmask)
-			desc->chip->unmask(irq);
+		if (!(desc->status & IRQ_MOVE_PCNTXT) && data->chip->irq_unmask)
+			data->chip->irq_unmask(data);
 
 		raw_spin_unlock(&desc->lock);
 
@@ -355,10 +357,10 @@
 		if (irr  & (1 << (vector % 32))) {
 			irq = __get_cpu_var(vector_irq)[vector];
 
-			desc = irq_to_desc(irq);
+			data = irq_get_irq_data(irq);
 			raw_spin_lock(&desc->lock);
-			if (desc->chip->retrigger)
-				desc->chip->retrigger(irq);
+			if (data->chip->irq_retrigger)
+				data->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 10709f2..50fbbe6 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -49,20 +49,19 @@
 static inline void print_stack_overflow(void) { }
 #endif
 
-#ifdef CONFIG_4KSTACKS
 /*
  * per-CPU IRQ handling contexts (thread information and stack)
  */
 union irq_ctx {
 	struct thread_info      tinfo;
 	u32                     stack[THREAD_SIZE/sizeof(u32)];
-} __attribute__((aligned(PAGE_SIZE)));
+} __attribute__((aligned(THREAD_SIZE)));
 
 static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx);
 static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx);
 
-static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, hardirq_stack);
-static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, softirq_stack);
+static DEFINE_PER_CPU_MULTIPAGE_ALIGNED(union irq_ctx, hardirq_stack, THREAD_SIZE);
+static DEFINE_PER_CPU_MULTIPAGE_ALIGNED(union irq_ctx, softirq_stack, THREAD_SIZE);
 
 static void call_on_stack(void *func, void *stack)
 {
@@ -187,11 +186,6 @@
 	local_irq_restore(flags);
 }
 
-#else
-static inline int
-execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; }
-#endif
-
 bool handle_irq(unsigned irq, struct pt_regs *regs)
 {
 	struct irq_desc *desc;
diff --git a/arch/x86/kernel/irq_work.c b/arch/x86/kernel/irq_work.c
new file mode 100644
index 0000000..ca8f703
--- /dev/null
+++ b/arch/x86/kernel/irq_work.c
@@ -0,0 +1,30 @@
+/*
+ * x86 specific code for irq_work
+ *
+ * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq_work.h>
+#include <linux/hardirq.h>
+#include <asm/apic.h>
+
+void smp_irq_work_interrupt(struct pt_regs *regs)
+{
+	irq_enter();
+	ack_APIC_irq();
+	inc_irq_stat(apic_irq_work_irqs);
+	irq_work_run();
+	irq_exit();
+}
+
+void arch_irq_work_raise(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	if (!cpu_has_apic)
+		return;
+
+	apic->send_IPI_self(IRQ_WORK_VECTOR);
+	apic_wait_icr_idle();
+#endif
+}
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 990ae7c..c752e97 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -100,6 +100,8 @@
 
 void __init init_ISA_irqs(void)
 {
+	struct irq_chip *chip = legacy_pic->chip;
+	const char *name = chip->name;
 	int i;
 
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
@@ -107,19 +109,8 @@
 #endif
 	legacy_pic->init(0);
 
-	/*
-	 * 16 old-style INTA-cycle interrupts:
-	 */
-	for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) {
-		struct irq_desc *desc = irq_to_desc(i);
-
-		desc->status = IRQ_DISABLED;
-		desc->action = NULL;
-		desc->depth = 1;
-
-		set_irq_chip_and_handler_name(i, &i8259A_chip,
-					      handle_level_irq, "XT");
-	}
+	for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+		set_irq_chip_and_handler_name(i, chip, handle_level_irq, name);
 }
 
 void __init init_IRQ(void)
@@ -224,9 +215,9 @@
 	alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
 	alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
 
-	/* Performance monitoring interrupts: */
-# ifdef CONFIG_PERF_EVENTS
-	alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt);
+	/* IRQ work interrupts: */
+# ifdef CONFIG_IRQ_WORK
+	alloc_intr_gate(IRQ_WORK_VECTOR, irq_work_interrupt);
 # endif
 
 #endif
diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c
new file mode 100644
index 0000000..961b6b3
--- /dev/null
+++ b/arch/x86/kernel/jump_label.c
@@ -0,0 +1,50 @@
+/*
+ * jump label x86 support
+ *
+ * Copyright (C) 2009 Jason Baron <jbaron@redhat.com>
+ *
+ */
+#include <linux/jump_label.h>
+#include <linux/memory.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/jhash.h>
+#include <linux/cpu.h>
+#include <asm/kprobes.h>
+#include <asm/alternative.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+union jump_code_union {
+	char code[JUMP_LABEL_NOP_SIZE];
+	struct {
+		char jump;
+		int offset;
+	} __attribute__((packed));
+};
+
+void arch_jump_label_transform(struct jump_entry *entry,
+			       enum jump_label_type type)
+{
+	union jump_code_union code;
+
+	if (type == JUMP_LABEL_ENABLE) {
+		code.jump = 0xe9;
+		code.offset = entry->target -
+				(entry->code + JUMP_LABEL_NOP_SIZE);
+	} else
+		memcpy(&code, ideal_nop5, JUMP_LABEL_NOP_SIZE);
+	get_online_cpus();
+	mutex_lock(&text_mutex);
+	text_poke_smp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
+	mutex_unlock(&text_mutex);
+	put_online_cpus();
+}
+
+void arch_jump_label_text_poke_early(jump_label_t addr)
+{
+	text_poke_early((void *)addr, ideal_nop5, JUMP_LABEL_NOP_SIZE);
+}
+
+#endif
diff --git a/arch/x86/kernel/k8.c b/arch/x86/kernel/k8.c
deleted file mode 100644
index 0f7bc20..0000000
--- a/arch/x86/kernel/k8.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Shared support code for AMD K8 northbridges and derivates.
- * Copyright 2006 Andi Kleen, SUSE Labs. Subject to GPLv2.
- */
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/k8.h>
-
-int num_k8_northbridges;
-EXPORT_SYMBOL(num_k8_northbridges);
-
-static u32 *flush_words;
-
-struct pci_device_id k8_nb_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) },
-	{}
-};
-EXPORT_SYMBOL(k8_nb_ids);
-
-struct pci_dev **k8_northbridges;
-EXPORT_SYMBOL(k8_northbridges);
-
-static struct pci_dev *next_k8_northbridge(struct pci_dev *dev)
-{
-	do {
-		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
-		if (!dev)
-			break;
-	} while (!pci_match_id(&k8_nb_ids[0], dev));
-	return dev;
-}
-
-int cache_k8_northbridges(void)
-{
-	int i;
-	struct pci_dev *dev;
-
-	if (num_k8_northbridges)
-		return 0;
-
-	dev = NULL;
-	while ((dev = next_k8_northbridge(dev)) != NULL)
-		num_k8_northbridges++;
-
-	k8_northbridges = kmalloc((num_k8_northbridges + 1) * sizeof(void *),
-				  GFP_KERNEL);
-	if (!k8_northbridges)
-		return -ENOMEM;
-
-	if (!num_k8_northbridges) {
-		k8_northbridges[0] = NULL;
-		return 0;
-	}
-
-	flush_words = kmalloc(num_k8_northbridges * sizeof(u32), GFP_KERNEL);
-	if (!flush_words) {
-		kfree(k8_northbridges);
-		return -ENOMEM;
-	}
-
-	dev = NULL;
-	i = 0;
-	while ((dev = next_k8_northbridge(dev)) != NULL) {
-		k8_northbridges[i] = dev;
-		pci_read_config_dword(dev, 0x9c, &flush_words[i++]);
-	}
-	k8_northbridges[i] = NULL;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cache_k8_northbridges);
-
-/* Ignores subdevice/subvendor but as far as I can figure out
-   they're useless anyways */
-int __init early_is_k8_nb(u32 device)
-{
-	struct pci_device_id *id;
-	u32 vendor = device & 0xffff;
-	device >>= 16;
-	for (id = k8_nb_ids; id->vendor; id++)
-		if (vendor == id->vendor && device == id->device)
-			return 1;
-	return 0;
-}
-
-void k8_flush_garts(void)
-{
-	int flushed, i;
-	unsigned long flags;
-	static DEFINE_SPINLOCK(gart_lock);
-
-	/* Avoid races between AGP and IOMMU. In theory it's not needed
-	   but I'm not sure if the hardware won't lose flush requests
-	   when another is pending. This whole thing is so expensive anyways
-	   that it doesn't matter to serialize more. -AK */
-	spin_lock_irqsave(&gart_lock, flags);
-	flushed = 0;
-	for (i = 0; i < num_k8_northbridges; i++) {
-		pci_write_config_dword(k8_northbridges[i], 0x9c,
-				       flush_words[i]|1);
-		flushed++;
-	}
-	for (i = 0; i < num_k8_northbridges; i++) {
-		u32 w;
-		/* Make sure the hardware actually executed the flush*/
-		for (;;) {
-			pci_read_config_dword(k8_northbridges[i],
-					      0x9c, &w);
-			if (!(w & 1))
-				break;
-			cpu_relax();
-		}
-	}
-	spin_unlock_irqrestore(&gart_lock, flags);
-	if (!flushed)
-		printk("nothing to flush?\n");
-}
-EXPORT_SYMBOL_GPL(k8_flush_garts);
-
-static __init int init_k8_nbs(void)
-{
-	int err = 0;
-
-	err = cache_k8_northbridges();
-
-	if (err < 0)
-		printk(KERN_NOTICE "K8 NB: Cannot enumerate AMD northbridges.\n");
-
-	return err;
-}
-
-/* This has to go after the PCI subsystem */
-fs_initcall(init_k8_nbs);
diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index 8afd9f3..90fcf62 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -78,6 +78,7 @@
 static const struct file_operations fops_setup_data = {
 	.read		= setup_data_read,
 	.open		= setup_data_open,
+	.llseek		= default_llseek,
 };
 
 static int __init
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 852b819..d81cfeb 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -477,8 +477,6 @@
 				   raw_smp_processor_id());
 		}
 
-		kgdb_correct_hw_break();
-
 		return 0;
 	}
 
@@ -621,7 +619,12 @@
 static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi,
 		struct perf_sample_data *data, struct pt_regs *regs)
 {
-	kgdb_ll_trap(DIE_DEBUG, "debug", regs, 0, 0, SIGTRAP);
+	struct task_struct *tsk = current;
+	int i;
+
+	for (i = 0; i < 4; i++)
+		if (breakinfo[i].enabled)
+			tsk->thread.debugreg6 |= (DR_TRAP0 << i);
 }
 
 void kgdb_arch_late(void)
@@ -644,7 +647,7 @@
 		if (breakinfo[i].pev)
 			continue;
 		breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL);
-		if (IS_ERR(breakinfo[i].pev)) {
+		if (IS_ERR((void * __force)breakinfo[i].pev)) {
 			printk(KERN_ERR "kgdb: Could not allocate hw"
 			       "breakpoints\nDisabling the kernel debugger\n");
 			breakinfo[i].pev = NULL;
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index 770ebfb3..1cbd54c 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -230,9 +230,6 @@
 	return 0;
 }
 
-/* Dummy buffers for kallsyms_lookup */
-static char __dummy_buf[KSYM_NAME_LEN];
-
 /* Check if paddr is at an instruction boundary */
 static int __kprobes can_probe(unsigned long paddr)
 {
@@ -241,7 +238,7 @@
 	struct insn insn;
 	kprobe_opcode_t buf[MAX_INSN_SIZE];
 
-	if (!kallsyms_lookup(paddr, NULL, &offset, NULL, __dummy_buf))
+	if (!kallsyms_lookup_size_offset(paddr, NULL, &offset))
 		return 0;
 
 	/* Decode instructions */
@@ -1129,7 +1126,7 @@
 	*(unsigned long *)addr = val;
 }
 
-void __kprobes kprobes_optinsn_template_holder(void)
+static void __used __kprobes kprobes_optinsn_template_holder(void)
 {
 	asm volatile (
 			".global optprobe_template_entry\n"
@@ -1221,7 +1218,8 @@
 	}
 	/* Check whether the address range is reserved */
 	if (ftrace_text_reserved(src, src + len - 1) ||
-	    alternatives_text_reserved(src, src + len - 1))
+	    alternatives_text_reserved(src, src + len - 1) ||
+	    jump_label_text_reserved(src, src + len - 1))
 		return -EBUSY;
 
 	return len;
@@ -1269,11 +1267,9 @@
 	unsigned long addr, size = 0, offset = 0;
 	struct insn insn;
 	kprobe_opcode_t buf[MAX_INSN_SIZE];
-	/* Dummy buffers for lookup_symbol_attrs */
-	static char __dummy_buf[KSYM_NAME_LEN];
 
 	/* Lookup symbol including addr */
-	if (!kallsyms_lookup(paddr, &size, &offset, NULL, __dummy_buf))
+	if (!kallsyms_lookup_size_offset(paddr, &size, &offset))
 		return 0;
 
 	/* Check there is enough space for a relative jump. */
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 035c8c5..b3ea9db 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -36,7 +36,7 @@
 		if (!page)
 			goto out;
 		pud = (pud_t *)page_address(page);
-		memset(pud, 0, PAGE_SIZE);
+		clear_page(pud);
 		set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
 	}
 	pud = pud_offset(pgd, addr);
@@ -45,7 +45,7 @@
 		if (!page)
 			goto out;
 		pmd = (pmd_t *)page_address(page);
-		memset(pmd, 0, PAGE_SIZE);
+		clear_page(pmd);
 		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
 	}
 	pmd = pmd_offset(pud, addr);
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index fa6551d..0b3d37e 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -232,6 +232,7 @@
 	.owner			= THIS_MODULE,
 	.write			= microcode_write,
 	.open			= microcode_open,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice microcode_dev = {
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index e0bc186..8f29560 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -239,11 +239,13 @@
 		apply_paravirt(pseg, pseg + para->sh_size);
 	}
 
-	return module_bug_finalize(hdr, sechdrs, me);
+	/* make jump label nops */
+	jump_label_apply_nops(me);
+
+	return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
 	alternatives_smp_module_del(mod);
-	module_bug_cleanup(mod);
 }
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index d7b6f7f..9af64d9 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/bitops.h>
@@ -657,7 +658,7 @@
 {
 	unsigned long size = get_mpc_size(mpf->physptr);
 
-	reserve_early_overlap_ok(mpf->physptr, mpf->physptr+size, "MP-table mpc");
+	memblock_x86_reserve_range(mpf->physptr, mpf->physptr+size, "* MP-table mpc");
 }
 
 static int __init smp_scan_config(unsigned long base, unsigned long length)
@@ -686,7 +687,7 @@
 			       mpf, (u64)virt_to_phys(mpf));
 
 			mem = virt_to_phys(mpf);
-			reserve_early_overlap_ok(mem, mem + sizeof(*mpf), "MP-table mpf");
+			memblock_x86_reserve_range(mem, mem + sizeof(*mpf), "* MP-table mpf");
 			if (mpf->physptr)
 				smp_reserve_memory(mpf);
 
diff --git a/arch/x86/kernel/olpc-xo1.c b/arch/x86/kernel/olpc-xo1.c
new file mode 100644
index 0000000..f5442c0
--- /dev/null
+++ b/arch/x86/kernel/olpc-xo1.c
@@ -0,0 +1,140 @@
+/*
+ * Support for features of the OLPC XO-1 laptop
+ *
+ * Copyright (C) 2010 One Laptop per Child
+ * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+
+#include <asm/io.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME "olpc-xo1"
+
+#define PMS_BAR		4
+#define ACPI_BAR	5
+
+/* PMC registers (PMS block) */
+#define PM_SCLK		0x10
+#define PM_IN_SLPCTL	0x20
+#define PM_WKXD		0x34
+#define PM_WKD		0x30
+#define PM_SSC		0x54
+
+/* PM registers (ACPI block) */
+#define PM1_CNT		0x08
+#define PM_GPE0_STS	0x18
+
+static unsigned long acpi_base;
+static unsigned long pms_base;
+
+static void xo1_power_off(void)
+{
+	printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
+
+	/* Enable all of these controls with 0 delay */
+	outl(0x40000000, pms_base + PM_SCLK);
+	outl(0x40000000, pms_base + PM_IN_SLPCTL);
+	outl(0x40000000, pms_base + PM_WKXD);
+	outl(0x40000000, pms_base + PM_WKD);
+
+	/* Clear status bits (possibly unnecessary) */
+	outl(0x0002ffff, pms_base  + PM_SSC);
+	outl(0xffffffff, acpi_base + PM_GPE0_STS);
+
+	/* Write SLP_EN bit to start the machinery */
+	outl(0x00002000, acpi_base + PM1_CNT);
+}
+
+/* Read the base addresses from the PCI BAR info */
+static int __devinit setup_bases(struct pci_dev *pdev)
+{
+	int r;
+
+	r = pci_enable_device_io(pdev);
+	if (r) {
+		dev_err(&pdev->dev, "can't enable device IO\n");
+		return r;
+	}
+
+	r = pci_request_region(pdev, ACPI_BAR, DRV_NAME);
+	if (r) {
+		dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", ACPI_BAR);
+		return r;
+	}
+
+	r = pci_request_region(pdev, PMS_BAR, DRV_NAME);
+	if (r) {
+		dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", PMS_BAR);
+		pci_release_region(pdev, ACPI_BAR);
+		return r;
+	}
+
+	acpi_base = pci_resource_start(pdev, ACPI_BAR);
+	pms_base = pci_resource_start(pdev, PMS_BAR);
+
+	return 0;
+}
+
+static int __devinit olpc_xo1_probe(struct platform_device *pdev)
+{
+	struct pci_dev *pcidev;
+	int r;
+
+	pcidev = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA,
+				NULL);
+	if (!pdev)
+		return -ENODEV;
+
+	r = setup_bases(pcidev);
+	if (r)
+		return r;
+
+	pm_power_off = xo1_power_off;
+
+	printk(KERN_INFO "OLPC XO-1 support registered\n");
+	return 0;
+}
+
+static int __devexit olpc_xo1_remove(struct platform_device *pdev)
+{
+	pm_power_off = NULL;
+	return 0;
+}
+
+static struct platform_driver olpc_xo1_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = olpc_xo1_probe,
+	.remove = __devexit_p(olpc_xo1_remove),
+};
+
+static int __init olpc_xo1_init(void)
+{
+	return platform_driver_register(&olpc_xo1_driver);
+}
+
+static void __exit olpc_xo1_exit(void)
+{
+	platform_driver_unregister(&olpc_xo1_driver);
+}
+
+MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:olpc-xo1");
+
+module_init(olpc_xo1_init);
+module_exit(olpc_xo1_exit);
diff --git a/arch/x86/kernel/olpc.c b/arch/x86/kernel/olpc.c
index 0e0cdde..edaf3fe 100644
--- a/arch/x86/kernel/olpc.c
+++ b/arch/x86/kernel/olpc.c
@@ -17,6 +17,7 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/string.h>
+#include <linux/platform_device.h>
 
 #include <asm/geode.h>
 #include <asm/setup.h>
@@ -114,6 +115,7 @@
 	unsigned long flags;
 	int ret = -EIO;
 	int i;
+	int restarts = 0;
 
 	spin_lock_irqsave(&ec_lock, flags);
 
@@ -169,7 +171,9 @@
 			if (wait_on_obf(0x6c, 1)) {
 				printk(KERN_ERR "olpc-ec:  timeout waiting for"
 						" EC to provide data!\n");
-				goto restart;
+				if (restarts++ < 10)
+					goto restart;
+				goto err;
 			}
 			outbuf[i] = inb(0x68);
 			pr_devel("olpc-ec:  received 0x%x\n", outbuf[i]);
@@ -183,8 +187,21 @@
 }
 EXPORT_SYMBOL_GPL(olpc_ec_cmd);
 
-#ifdef CONFIG_OLPC_OPENFIRMWARE
-static void __init platform_detect(void)
+static bool __init check_ofw_architecture(void)
+{
+	size_t propsize;
+	char olpc_arch[5];
+	const void *args[] = { NULL, "architecture", olpc_arch, (void *)5 };
+	void *res[] = { &propsize };
+
+	if (olpc_ofw("getprop", args, res)) {
+		printk(KERN_ERR "ofw: getprop call failed!\n");
+		return false;
+	}
+	return propsize == 5 && strncmp("OLPC", olpc_arch, 5) == 0;
+}
+
+static u32 __init get_board_revision(void)
 {
 	size_t propsize;
 	__be32 rev;
@@ -193,46 +210,44 @@
 
 	if (olpc_ofw("getprop", args, res) || propsize != 4) {
 		printk(KERN_ERR "ofw: getprop call failed!\n");
-		rev = cpu_to_be32(0);
+		return cpu_to_be32(0);
 	}
-	olpc_platform_info.boardrev = be32_to_cpu(rev);
+	return be32_to_cpu(rev);
 }
-#else
-static void __init platform_detect(void)
+
+static bool __init platform_detect(void)
 {
-	/* stopgap until OFW support is added to the kernel */
-	olpc_platform_info.boardrev = olpc_board(0xc2);
+	if (!check_ofw_architecture())
+		return false;
+	olpc_platform_info.flags |= OLPC_F_PRESENT;
+	olpc_platform_info.boardrev = get_board_revision();
+	return true;
 }
-#endif
+
+static int __init add_xo1_platform_devices(void)
+{
+	struct platform_device *pdev;
+
+	pdev = platform_device_register_simple("xo1-rfkill", -1, NULL, 0);
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+
+	pdev = platform_device_register_simple("olpc-xo1", -1, NULL, 0);
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+
+	return 0;
+}
 
 static int __init olpc_init(void)
 {
-	unsigned char *romsig;
+	int r = 0;
 
-	/* The ioremap check is dangerous; limit what we run it on */
-	if (!is_geode() || cs5535_has_vsa2())
+	if (!olpc_ofw_present() || !platform_detect())
 		return 0;
 
 	spin_lock_init(&ec_lock);
 
-	romsig = ioremap(0xffffffc0, 16);
-	if (!romsig)
-		return 0;
-
-	if (strncmp(romsig, "CL1   Q", 7))
-		goto unmap;
-	if (strncmp(romsig+6, romsig+13, 3)) {
-		printk(KERN_INFO "OLPC BIOS signature looks invalid.  "
-				"Assuming not OLPC\n");
-		goto unmap;
-	}
-
-	printk(KERN_INFO "OLPC board with OpenFirmware %.16s\n", romsig);
-	olpc_platform_info.flags |= OLPC_F_PRESENT;
-
-	/* get the platform revision */
-	platform_detect();
-
 	/* assume B1 and above models always have a DCON */
 	if (olpc_board_at_least(olpc_board(0xb1)))
 		olpc_platform_info.flags |= OLPC_F_DCON;
@@ -242,8 +257,10 @@
 			(unsigned char *) &olpc_platform_info.ecver, 1);
 
 #ifdef CONFIG_PCI_OLPC
-	/* If the VSA exists let it emulate PCI, if not emulate in kernel */
-	if (!cs5535_has_vsa2())
+	/* If the VSA exists let it emulate PCI, if not emulate in kernel.
+	 * XO-1 only. */
+	if (olpc_platform_info.boardrev < olpc_board_pre(0xd0) &&
+			!cs5535_has_vsa2())
 		x86_init.pci.arch_init = pci_olpc_init;
 #endif
 
@@ -252,8 +269,12 @@
 			olpc_platform_info.boardrev >> 4,
 			olpc_platform_info.ecver);
 
-unmap:
-	iounmap(romsig);
+	if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) { /* XO-1 */
+		r = add_xo1_platform_devices();
+		if (r)
+			return r;
+	}
+
 	return 0;
 }
 
diff --git a/arch/x86/kernel/olpc_ofw.c b/arch/x86/kernel/olpc_ofw.c
index 3218aa7..7873204 100644
--- a/arch/x86/kernel/olpc_ofw.c
+++ b/arch/x86/kernel/olpc_ofw.c
@@ -74,6 +74,12 @@
 }
 EXPORT_SYMBOL_GPL(__olpc_ofw);
 
+bool olpc_ofw_present(void)
+{
+	return olpc_ofw_cif != NULL;
+}
+EXPORT_SYMBOL_GPL(olpc_ofw_present);
+
 /* OFW cif _should_ be above this address */
 #define OFW_MIN 0xff000000
 
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 1db183e..c5b2500 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -413,7 +413,6 @@
 
 	.alloc_pte = paravirt_nop,
 	.alloc_pmd = paravirt_nop,
-	.alloc_pmd_clone = paravirt_nop,
 	.alloc_pud = paravirt_nop,
 	.release_pte = paravirt_nop,
 	.release_pmd = paravirt_nop,
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 078d4ec..f56a117 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -47,6 +47,7 @@
 #include <asm/rio.h>
 #include <asm/bios_ebda.h>
 #include <asm/x86_init.h>
+#include <asm/iommu_table.h>
 
 #ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
 int use_calgary __read_mostly = 1;
@@ -1364,7 +1365,7 @@
 	return 0;
 }
 
-void __init detect_calgary(void)
+int __init detect_calgary(void)
 {
 	int bus;
 	void *tbl;
@@ -1378,13 +1379,13 @@
 	 * another HW IOMMU already, bail out.
 	 */
 	if (no_iommu || iommu_detected)
-		return;
+		return -ENODEV;
 
 	if (!use_calgary)
-		return;
+		return -ENODEV;
 
 	if (!early_pci_allowed())
-		return;
+		return -ENODEV;
 
 	printk(KERN_DEBUG "Calgary: detecting Calgary via BIOS EBDA area\n");
 
@@ -1410,13 +1411,13 @@
 	if (!rio_table_hdr) {
 		printk(KERN_DEBUG "Calgary: Unable to locate Rio Grande table "
 		       "in EBDA - bailing!\n");
-		return;
+		return -ENODEV;
 	}
 
 	ret = build_detail_arrays();
 	if (ret) {
 		printk(KERN_DEBUG "Calgary: build_detail_arrays ret %d\n", ret);
-		return;
+		return -ENOMEM;
 	}
 
 	specified_table_size = determine_tce_table_size((is_kdump_kernel() ?
@@ -1464,7 +1465,7 @@
 
 		x86_init.iommu.iommu_init = calgary_iommu_init;
 	}
-	return;
+	return calgary_found;
 
 cleanup:
 	for (--bus; bus >= 0; --bus) {
@@ -1473,6 +1474,7 @@
 		if (info->tce_space)
 			free_tce_table(info->tce_space);
 	}
+	return -ENOMEM;
 }
 
 static int __init calgary_parse_options(char *p)
@@ -1594,3 +1596,5 @@
  * and before device_initcall.
  */
 rootfs_initcall(calgary_fixup_tce_spaces);
+
+IOMMU_INIT_POST(detect_calgary);
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 9f07cfc..9ea999a 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -11,9 +11,8 @@
 #include <asm/iommu.h>
 #include <asm/gart.h>
 #include <asm/calgary.h>
-#include <asm/amd_iommu.h>
 #include <asm/x86_init.h>
-#include <asm/xen/swiotlb-xen.h>
+#include <asm/iommu_table.h>
 
 static int forbid_dac __read_mostly;
 
@@ -45,6 +44,8 @@
  */
 int iommu_pass_through __read_mostly;
 
+extern struct iommu_table_entry __iommu_table[], __iommu_table_end[];
+
 /* Dummy device used for NULL arguments (normally ISA). */
 struct device x86_dma_fallback_dev = {
 	.init_name = "fallback device",
@@ -130,26 +131,24 @@
 
 void __init pci_iommu_alloc(void)
 {
+	struct iommu_table_entry *p;
+
 	/* free the range so iommu could get some range less than 4G */
 	dma32_free_bootmem();
 
-	if (pci_xen_swiotlb_detect() || pci_swiotlb_detect())
-		goto out;
+	sort_iommu_table(__iommu_table, __iommu_table_end);
+	check_iommu_entries(__iommu_table, __iommu_table_end);
 
-	gart_iommu_hole_init();
-
-	detect_calgary();
-
-	detect_intel_iommu();
-
-	/* needs to be called after gart_iommu_hole_init */
-	amd_iommu_detect();
-out:
-	pci_xen_swiotlb_init();
-
-	pci_swiotlb_init();
+	for (p = __iommu_table; p < __iommu_table_end; p++) {
+		if (p && p->detect && p->detect() > 0) {
+			p->flags |= IOMMU_DETECTED;
+			if (p->early_init)
+				p->early_init();
+			if (p->flags & IOMMU_FINISH_IF_DETECTED)
+				break;
+		}
+	}
 }
-
 void *dma_generic_alloc_coherent(struct device *dev, size_t size,
 				 dma_addr_t *dma_addr, gfp_t flag)
 {
@@ -292,6 +291,7 @@
 
 static int __init pci_iommu_init(void)
 {
+	struct iommu_table_entry *p;
 	dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
 
 #ifdef CONFIG_PCI
@@ -299,12 +299,10 @@
 #endif
 	x86_init.iommu.iommu_init();
 
-	if (swiotlb || xen_swiotlb) {
-		printk(KERN_INFO "PCI-DMA: "
-		       "Using software bounce buffering for IO (SWIOTLB)\n");
-		swiotlb_print_info();
-	} else
-		swiotlb_free();
+	for (p = __iommu_table; p < __iommu_table_end; p++) {
+		if (p && (p->flags & IOMMU_DETECTED) && p->late_init)
+			p->late_init();
+	}
 
 	return 0;
 }
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 0f7f130..ba0f0ca 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -39,8 +39,9 @@
 #include <asm/cacheflush.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 #include <asm/x86_init.h>
+#include <asm/iommu_table.h>
 
 static unsigned long iommu_bus_base;	/* GART remapping area (physical) */
 static unsigned long iommu_size;	/* size of remapping area bytes */
@@ -560,8 +561,11 @@
 {
 	int i;
 
-	for (i = 0; i < num_k8_northbridges; i++) {
-		struct pci_dev *dev = k8_northbridges[i];
+	if (!k8_northbridges.gart_supported)
+		return;
+
+	for (i = 0; i < k8_northbridges.num; i++) {
+		struct pci_dev *dev = k8_northbridges.nb_misc[i];
 
 		enable_gart_translation(dev, __pa(agp_gatt_table));
 	}
@@ -592,16 +596,19 @@
 	if (!fix_up_north_bridges)
 		return;
 
+	if (!k8_northbridges.gart_supported)
+		return;
+
 	pr_info("PCI-DMA: Restoring GART aperture settings\n");
 
-	for (i = 0; i < num_k8_northbridges; i++) {
-		struct pci_dev *dev = k8_northbridges[i];
+	for (i = 0; i < k8_northbridges.num; i++) {
+		struct pci_dev *dev = k8_northbridges.nb_misc[i];
 
 		/*
 		 * Don't enable translations just yet.  That is the next
 		 * step.  Restore the pre-suspend aperture settings.
 		 */
-		pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, aperture_order << 1);
+		gart_set_size_and_enable(dev, aperture_order);
 		pci_write_config_dword(dev, AMD64_GARTAPERTUREBASE, aperture_alloc >> 25);
 	}
 }
@@ -649,8 +656,8 @@
 
 	aper_size = aper_base = info->aper_size = 0;
 	dev = NULL;
-	for (i = 0; i < num_k8_northbridges; i++) {
-		dev = k8_northbridges[i];
+	for (i = 0; i < k8_northbridges.num; i++) {
+		dev = k8_northbridges.nb_misc[i];
 		new_aper_base = read_aperture(dev, &new_aper_size);
 		if (!new_aper_base)
 			goto nommu;
@@ -718,10 +725,13 @@
 	if (!no_agp)
 		return;
 
-	for (i = 0; i < num_k8_northbridges; i++) {
+	if (!k8_northbridges.gart_supported)
+		return;
+
+	for (i = 0; i < k8_northbridges.num; i++) {
 		u32 ctl;
 
-		dev = k8_northbridges[i];
+		dev = k8_northbridges.nb_misc[i];
 		pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
 
 		ctl &= ~GARTEN;
@@ -739,7 +749,7 @@
 	unsigned long scratch;
 	long i;
 
-	if (num_k8_northbridges == 0)
+	if (!k8_northbridges.gart_supported)
 		return 0;
 
 #ifndef CONFIG_AGP_AMD64
@@ -896,3 +906,4 @@
 		}
 	}
 }
+IOMMU_INIT_POST(gart_iommu_hole_init);
diff --git a/arch/x86/kernel/pci-iommu_table.c b/arch/x86/kernel/pci-iommu_table.c
new file mode 100644
index 0000000..55d745e
--- /dev/null
+++ b/arch/x86/kernel/pci-iommu_table.c
@@ -0,0 +1,89 @@
+#include <linux/dma-mapping.h>
+#include <asm/iommu_table.h>
+#include <linux/string.h>
+#include <linux/kallsyms.h>
+
+
+#define DEBUG 1
+
+static struct iommu_table_entry * __init
+find_dependents_of(struct iommu_table_entry *start,
+		   struct iommu_table_entry *finish,
+		   struct iommu_table_entry *q)
+{
+	struct iommu_table_entry *p;
+
+	if (!q)
+		return NULL;
+
+	for (p = start; p < finish; p++)
+		if (p->detect == q->depend)
+			return p;
+
+	return NULL;
+}
+
+
+void __init sort_iommu_table(struct iommu_table_entry *start,
+			     struct iommu_table_entry *finish) {
+
+	struct iommu_table_entry *p, *q, tmp;
+
+	for (p = start; p < finish; p++) {
+again:
+		q = find_dependents_of(start, finish, p);
+		/* We are bit sneaky here. We use the memory address to figure
+		 * out if the node we depend on is past our point, if so, swap.
+		 */
+		if (q > p) {
+			tmp = *p;
+			memmove(p, q, sizeof(*p));
+			*q = tmp;
+			goto again;
+		}
+	}
+
+}
+
+#ifdef DEBUG
+void __init check_iommu_entries(struct iommu_table_entry *start,
+				struct iommu_table_entry *finish)
+{
+	struct iommu_table_entry *p, *q, *x;
+	char sym_p[KSYM_SYMBOL_LEN];
+	char sym_q[KSYM_SYMBOL_LEN];
+
+	/* Simple cyclic dependency checker. */
+	for (p = start; p < finish; p++) {
+		q = find_dependents_of(start, finish, p);
+		x = find_dependents_of(start, finish, q);
+		if (p == x) {
+			sprint_symbol(sym_p, (unsigned long)p->detect);
+			sprint_symbol(sym_q, (unsigned long)q->detect);
+
+			printk(KERN_ERR "CYCLIC DEPENDENCY FOUND! %s depends" \
+					" on %s and vice-versa. BREAKING IT.\n",
+					sym_p, sym_q);
+			/* Heavy handed way..*/
+			x->depend = 0;
+		}
+	}
+
+	for (p = start; p < finish; p++) {
+		q = find_dependents_of(p, finish, p);
+		if (q && q > p) {
+			sprint_symbol(sym_p, (unsigned long)p->detect);
+			sprint_symbol(sym_q, (unsigned long)q->detect);
+
+			printk(KERN_ERR "EXECUTION ORDER INVALID! %s "\
+					"should be called before %s!\n",
+					sym_p, sym_q);
+		}
+	}
+}
+#else
+inline void check_iommu_entries(struct iommu_table_entry *start,
+				       struct iommu_table_entry *finish)
+{
+}
+#endif
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index a5bc528..8f972cb 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -10,7 +10,8 @@
 #include <asm/iommu.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
-
+#include <asm/xen/swiotlb-xen.h>
+#include <asm/iommu_table.h>
 int swiotlb __read_mostly;
 
 static void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
@@ -41,25 +42,42 @@
 };
 
 /*
- * pci_swiotlb_detect - set swiotlb to 1 if necessary
+ * pci_swiotlb_detect_override - set swiotlb to 1 if necessary
  *
  * This returns non-zero if we are forced to use swiotlb (by the boot
  * option).
  */
-int __init pci_swiotlb_detect(void)
+int __init pci_swiotlb_detect_override(void)
 {
 	int use_swiotlb = swiotlb | swiotlb_force;
 
-	/* don't initialize swiotlb if iommu=off (no_iommu=1) */
-#ifdef CONFIG_X86_64
-	if (!no_iommu && max_pfn > MAX_DMA32_PFN)
-		swiotlb = 1;
-#endif
 	if (swiotlb_force)
 		swiotlb = 1;
 
 	return use_swiotlb;
 }
+IOMMU_INIT_FINISH(pci_swiotlb_detect_override,
+		  pci_xen_swiotlb_detect,
+		  pci_swiotlb_init,
+		  pci_swiotlb_late_init);
+
+/*
+ * if 4GB or more detected (and iommu=off not set) return 1
+ * and set swiotlb to 1.
+ */
+int __init pci_swiotlb_detect_4gb(void)
+{
+	/* don't initialize swiotlb if iommu=off (no_iommu=1) */
+#ifdef CONFIG_X86_64
+	if (!no_iommu && max_pfn > MAX_DMA32_PFN)
+		swiotlb = 1;
+#endif
+	return swiotlb;
+}
+IOMMU_INIT(pci_swiotlb_detect_4gb,
+	   pci_swiotlb_detect_override,
+	   pci_swiotlb_init,
+	   pci_swiotlb_late_init);
 
 void __init pci_swiotlb_init(void)
 {
@@ -68,3 +86,15 @@
 		dma_ops = &swiotlb_dma_ops;
 	}
 }
+
+void __init pci_swiotlb_late_init(void)
+{
+	/* An IOMMU turned us off. */
+	if (!swiotlb)
+		swiotlb_free();
+	else {
+		printk(KERN_INFO "PCI-DMA: "
+		       "Using software bounce buffering for IO (SWIOTLB)\n");
+		swiotlb_print_info();
+	}
+}
diff --git a/arch/x86/kernel/pmtimer_64.c b/arch/x86/kernel/pmtimer_64.c
deleted file mode 100644
index b112406..0000000
--- a/arch/x86/kernel/pmtimer_64.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Ported over from i386 by AK, original copyright was:
- *
- * (C) Dominik Brodowski <linux@brodo.de> 2003
- *
- * Driver to use the Power Management Timer (PMTMR) available in some
- * southbridges as primary timing source for the Linux kernel.
- *
- * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
- * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
- *
- * This file is licensed under the GPL v2.
- *
- * Dropped all the hardware bug workarounds for now. Hopefully they
- * are not needed on 64bit chipsets.
- */
-
-#include <linux/jiffies.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/cpumask.h>
-#include <linux/acpi_pmtmr.h>
-
-#include <asm/io.h>
-#include <asm/proto.h>
-#include <asm/msr.h>
-#include <asm/vsyscall.h>
-
-static inline u32 cyc2us(u32 cycles)
-{
-	/* The Power Management Timer ticks at 3.579545 ticks per microsecond.
-	 * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
-	 *
-	 * Even with HZ = 100, delta is at maximum 35796 ticks, so it can
-	 * easily be multiplied with 286 (=0x11E) without having to fear
-	 * u32 overflows.
-	 */
-	cycles *= 286;
-	return (cycles >> 10);
-}
-
-static unsigned pmtimer_wait_tick(void)
-{
-	u32 a, b;
-	for (a = b = inl(pmtmr_ioport) & ACPI_PM_MASK;
-	     a == b;
-	     b = inl(pmtmr_ioport) & ACPI_PM_MASK)
-		cpu_relax();
-	return b;
-}
-
-/* note: wait time is rounded up to one tick */
-void pmtimer_wait(unsigned us)
-{
-	u32 a, b;
-	a = pmtimer_wait_tick();
-	do {
-		b = inl(pmtmr_ioport);
-		cpu_relax();
-	} while (cyc2us(b - a) < us);
-}
-
-static int __init nopmtimer_setup(char *s)
-{
-	pmtmr_ioport = 0;
-	return 1;
-}
-
-__setup("nopmtimer", nopmtimer_setup);
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 3d9ea53..b3d7a3a 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -424,7 +424,7 @@
 	load_TLS(next, cpu);
 
 	/* Must be after DS reload */
-	unlazy_fpu(prev_p);
+	__unlazy_fpu(prev_p);
 
 	/* Make sure cpu is ready for new context */
 	if (preload_fpu)
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 939b9e9..8bbe8c5 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -344,6 +344,8 @@
 			 vt8237_force_enable_hpet);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
 			 vt8237_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700,
+			 vt8237_force_enable_hpet);
 
 static void ati_force_hpet_resume(void)
 {
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index e3af342..f7f53dc 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -84,7 +84,7 @@
 			}
 				/* we will leave sorting out the final value
 				   when we are ready to reboot, since we might not
-				   have set up boot_cpu_id or smp_num_cpu */
+				   have detected BSP APIC ID or smp_num_cpu */
 			break;
 #endif /* CONFIG_SMP */
 
@@ -371,16 +371,10 @@
 	CMOS_WRITE(0x00, 0x8f);
 	spin_unlock(&rtc_lock);
 
-	/* Remap the kernel at virtual address zero, as well as offset zero
-	   from the kernel segment.  This assumes the kernel segment starts at
-	   virtual address PAGE_OFFSET. */
-	memcpy(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
-		sizeof(swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
-
 	/*
-	 * Use `swapper_pg_dir' as our page directory.
+	 * Switch back to the initial page table.
 	 */
-	load_cr3(swapper_pg_dir);
+	load_cr3(initial_page_table);
 
 	/* Write 0x1234 to absolute memory location 0x472.  The BIOS reads
 	   this on booting to tell it to "Bypass memory test (also warm
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index c3a4fbb..95a3274 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -31,6 +31,7 @@
 #include <linux/apm_bios.h>
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/seq_file.h>
 #include <linux/console.h>
 #include <linux/mca.h>
@@ -83,7 +84,6 @@
 #include <asm/dmi.h>
 #include <asm/io_apic.h>
 #include <asm/ist.h>
-#include <asm/vmi.h>
 #include <asm/setup_arch.h>
 #include <asm/bios_ebda.h>
 #include <asm/cacheflush.h>
@@ -107,11 +107,12 @@
 #include <asm/percpu.h>
 #include <asm/topology.h>
 #include <asm/apicdef.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 #ifdef CONFIG_X86_64
 #include <asm/numa_64.h>
 #endif
 #include <asm/mce.h>
+#include <asm/alternative.h>
 
 /*
  * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
@@ -125,7 +126,6 @@
 RESERVE_BRK(dmi_alloc, 65536);
 #endif
 
-unsigned int boot_cpu_id __read_mostly;
 
 static __initdata unsigned long _brk_start = (unsigned long)__brk_base;
 unsigned long _brk_end = (unsigned long)__brk_base;
@@ -302,7 +302,7 @@
 static void __init reserve_brk(void)
 {
 	if (_brk_end > _brk_start)
-		reserve_early(__pa(_brk_start), __pa(_brk_end), "BRK");
+		memblock_x86_reserve_range(__pa(_brk_start), __pa(_brk_end), "BRK");
 
 	/* Mark brk area as locked down and no longer taking any
 	   new allocations */
@@ -324,17 +324,16 @@
 	char *p, *q;
 
 	/* We need to move the initrd down into lowmem */
-	ramdisk_here = find_e820_area(0, end_of_lowmem, area_size,
+	ramdisk_here = memblock_find_in_range(0, end_of_lowmem, area_size,
 					 PAGE_SIZE);
 
-	if (ramdisk_here == -1ULL)
+	if (ramdisk_here == MEMBLOCK_ERROR)
 		panic("Cannot find place for new RAMDISK of size %lld\n",
 			 ramdisk_size);
 
 	/* Note: this includes all the lowmem currently occupied by
 	   the initrd, we rely on that fact to keep the data intact. */
-	reserve_early(ramdisk_here, ramdisk_here + area_size,
-			 "NEW RAMDISK");
+	memblock_x86_reserve_range(ramdisk_here, ramdisk_here + area_size, "NEW RAMDISK");
 	initrd_start = ramdisk_here + PAGE_OFFSET;
 	initrd_end   = initrd_start + ramdisk_size;
 	printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n",
@@ -390,7 +389,7 @@
 	initrd_start = 0;
 
 	if (ramdisk_size >= (end_of_lowmem>>1)) {
-		free_early(ramdisk_image, ramdisk_end);
+		memblock_x86_free_range(ramdisk_image, ramdisk_end);
 		printk(KERN_ERR "initrd too large to handle, "
 		       "disabling initrd\n");
 		return;
@@ -413,7 +412,7 @@
 
 	relocate_initrd();
 
-	free_early(ramdisk_image, ramdisk_end);
+	memblock_x86_free_range(ramdisk_image, ramdisk_end);
 }
 #else
 static void __init reserve_initrd(void)
@@ -469,7 +468,7 @@
 	e820_print_map("reserve setup_data");
 }
 
-static void __init reserve_early_setup_data(void)
+static void __init memblock_x86_reserve_range_setup_data(void)
 {
 	struct setup_data *data;
 	u64 pa_data;
@@ -481,7 +480,7 @@
 	while (pa_data) {
 		data = early_memremap(pa_data, sizeof(*data));
 		sprintf(buf, "setup data %x", data->type);
-		reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
+		memblock_x86_reserve_range(pa_data, pa_data+sizeof(*data)+data->len, buf);
 		pa_data = data->next;
 		early_iounmap(data, sizeof(*data));
 	}
@@ -502,6 +501,7 @@
 	return total << PAGE_SHIFT;
 }
 
+#define DEFAULT_BZIMAGE_ADDR_MAX 0x37FFFFFF
 static void __init reserve_crashkernel(void)
 {
 	unsigned long long total_mem;
@@ -519,23 +519,27 @@
 	if (crash_base <= 0) {
 		const unsigned long long alignment = 16<<20;	/* 16M */
 
-		crash_base = find_e820_area(alignment, ULONG_MAX, crash_size,
-				 alignment);
-		if (crash_base == -1ULL) {
+		/*
+		 *  kexec want bzImage is below DEFAULT_BZIMAGE_ADDR_MAX
+		 */
+		crash_base = memblock_find_in_range(alignment,
+			       DEFAULT_BZIMAGE_ADDR_MAX, crash_size, alignment);
+
+		if (crash_base == MEMBLOCK_ERROR) {
 			pr_info("crashkernel reservation failed - No suitable area found.\n");
 			return;
 		}
 	} else {
 		unsigned long long start;
 
-		start = find_e820_area(crash_base, ULONG_MAX, crash_size,
-				 1<<20);
+		start = memblock_find_in_range(crash_base,
+				 crash_base + crash_size, crash_size, 1<<20);
 		if (start != crash_base) {
 			pr_info("crashkernel reservation failed - memory is in use.\n");
 			return;
 		}
 	}
-	reserve_early(crash_base, crash_base + crash_size, "CRASH KERNEL");
+	memblock_x86_reserve_range(crash_base, crash_base + crash_size, "CRASH KERNEL");
 
 	printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
 			"for crashkernel (System RAM: %ldMB)\n",
@@ -615,82 +619,10 @@
 	addr = find_ibft_region(&size);
 
 	if (size)
-		reserve_early_overlap_ok(addr, addr + size, "ibft");
+		memblock_x86_reserve_range(addr, addr + size, "* ibft");
 }
 
-#ifdef CONFIG_X86_RESERVE_LOW_64K
-static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
-{
-	printk(KERN_NOTICE
-		"%s detected: BIOS may corrupt low RAM, working around it.\n",
-		d->ident);
-
-	e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED);
-	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
-
-	return 0;
-}
-#endif
-
-/* List of systems that have known low memory corruption BIOS problems */
-static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
-#ifdef CONFIG_X86_RESERVE_LOW_64K
-	{
-		.callback = dmi_low_memory_corruption,
-		.ident = "AMI BIOS",
-		.matches = {
-			DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
-		},
-	},
-	{
-		.callback = dmi_low_memory_corruption,
-		.ident = "Phoenix BIOS",
-		.matches = {
-			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
-		},
-	},
-	{
-		.callback = dmi_low_memory_corruption,
-		.ident = "Phoenix/MSC BIOS",
-		.matches = {
-			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"),
-		},
-	},
-	/*
-	 * AMI BIOS with low memory corruption was found on Intel DG45ID and
-	 * DG45FC boards.
-	 * It has a different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
-	 * match only DMI_BOARD_NAME and see if there is more bad products
-	 * with this vendor.
-	 */
-	{
-		.callback = dmi_low_memory_corruption,
-		.ident = "AMI BIOS",
-		.matches = {
-			DMI_MATCH(DMI_BOARD_NAME, "DG45ID"),
-		},
-	},
-	{
-		.callback = dmi_low_memory_corruption,
-		.ident = "AMI BIOS",
-		.matches = {
-			DMI_MATCH(DMI_BOARD_NAME, "DG45FC"),
-		},
-	},
-	/*
-	 * The Dell Inspiron Mini 1012 has DMI_BIOS_VENDOR = "Dell Inc.", so
-	 * match on the product name.
-	 */
-	{
-		.callback = dmi_low_memory_corruption,
-		.ident = "Phoenix BIOS",
-		.matches = {
-			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
-		},
-	},
-#endif
-	{}
-};
+static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10;
 
 static void __init trim_bios_range(void)
 {
@@ -698,8 +630,14 @@
 	 * A special case is the first 4Kb of memory;
 	 * This is a BIOS owned area, not kernel ram, but generally
 	 * not listed as such in the E820 table.
+	 *
+	 * This typically reserves additional memory (64KiB by default)
+	 * since some BIOSes are known to corrupt low memory.  See the
+	 * Kconfig help text for X86_RESERVE_LOW.
 	 */
-	e820_update_range(0, PAGE_SIZE, E820_RAM, E820_RESERVED);
+	e820_update_range(0, ALIGN(reserve_low, PAGE_SIZE),
+			  E820_RAM, E820_RESERVED);
+
 	/*
 	 * special case: Some BIOSen report the PC BIOS
 	 * area (640->1Mb) as ram even though it is not.
@@ -709,6 +647,37 @@
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 }
 
+static int __init parse_reservelow(char *p)
+{
+	unsigned long long size;
+
+	if (!p)
+		return -EINVAL;
+
+	size = memparse(p, &p);
+
+	if (size < 4096)
+		size = 4096;
+
+	if (size > 640*1024)
+		size = 640*1024;
+
+	reserve_low = size;
+
+	return 0;
+}
+
+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
@@ -726,18 +695,30 @@
 {
 	int acpi = 0;
 	int k8 = 0;
+	unsigned long flags;
 
 #ifdef CONFIG_X86_32
 	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
 	visws_early_detect();
+
+	/*
+	 * copy kernel address range established so far and switch
+	 * to the proper swapper page table
+	 */
+	clone_pgd_range(swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
+			initial_page_table + KERNEL_PGD_BOUNDARY,
+			KERNEL_PGD_PTRS);
+
+	load_cr3(swapper_pg_dir);
+	__flush_tlb_all();
 #else
 	printk(KERN_INFO "Command line: %s\n", boot_command_line);
 #endif
 
-	/* VMI may relocate the fixmap; do this before touching ioremap area */
-	vmi_init();
-
-	/* OFW also may relocate the fixmap */
+	/*
+	 * If we have OLPC OFW, we might end up relocating the fixmap due to
+	 * reserve_top(), so do this before touching the ioremap area.
+	 */
 	olpc_ofw_detect();
 
 	early_trap_init();
@@ -782,7 +763,7 @@
 #endif
 	 4)) {
 		efi_enabled = 1;
-		efi_reserve_early();
+		efi_memblock_x86_reserve_range();
 	}
 #endif
 
@@ -838,11 +819,8 @@
 
 	x86_report_nx();
 
-	/* Must be before kernel pagetables are setup */
-	vmi_activate();
-
 	/* after early param, so could get panic from serial */
-	reserve_early_setup_data();
+	memblock_x86_reserve_range_setup_data();
 
 	if (acpi_mps_check()) {
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -863,8 +841,6 @@
 
 	dmi_scan_machine();
 
-	dmi_check_system(bad_bios_dmi_table);
-
 	/*
 	 * VMware detection requires dmi to be available, so this
 	 * needs to be done after dmi_scan_machine, for the BP.
@@ -897,8 +873,6 @@
 	 */
 	max_pfn = e820_end_of_ram_pfn();
 
-	/* preallocate 4k for mptable mpc */
-	early_reserve_e820_mpc_new();
 	/* update e820 for memory not covered by WB MTRRs */
 	mtrr_bp_init();
 	if (mtrr_trim_uncached_memory(max_pfn))
@@ -920,18 +894,8 @@
 		max_low_pfn = max_pfn;
 
 	high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
-	max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
 #endif
 
-#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
-	setup_bios_corruption_check();
-#endif
-
-	printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
-			max_pfn_mapped<<PAGE_SHIFT);
-
-	reserve_brk();
-
 	/*
 	 * Find and reserve possible boot-time SMP configuration:
 	 */
@@ -939,6 +903,26 @@
 
 	reserve_ibft_region();
 
+	/*
+	 * Need to conclude brk, before memblock_x86_fill()
+	 *  it could use memblock_find_in_range, could overlap with
+	 *  brk area.
+	 */
+	reserve_brk();
+
+	memblock.current_limit = get_max_mapped();
+	memblock_x86_fill();
+
+	/* preallocate 4k for mptable mpc */
+	early_reserve_e820_mpc_new();
+
+#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
+	setup_bios_corruption_check();
+#endif
+
+	printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
+			max_pfn_mapped<<PAGE_SHIFT);
+
 	reserve_trampoline_memory();
 
 #ifdef CONFIG_ACPI_SLEEP
@@ -962,6 +946,7 @@
 		max_low_pfn = max_pfn;
 	}
 #endif
+	memblock.current_limit = get_max_mapped();
 
 	/*
 	 * NOTE: On x86-32, only from this point on, fixmaps are ready for use.
@@ -1000,10 +985,7 @@
 #endif
 
 	initmem_init(0, max_pfn, acpi, k8);
-#ifndef CONFIG_NO_BOOTMEM
-	early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT);
-#endif
-
+	memblock_find_dma_reserve();
 	dma32_reserve_bootmem();
 
 #ifdef CONFIG_KVM_CLOCK
@@ -1014,7 +996,12 @@
 	paging_init();
 	x86_init.paging.pagetable_setup_done(swapper_pg_dir);
 
-	setup_trampoline_page_table();
+#ifdef CONFIG_X86_32
+	/* sync back kernel address range */
+	clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
+			swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
+			KERNEL_PGD_PTRS);
+#endif
 
 	tboot_probe();
 
@@ -1071,6 +1058,10 @@
 	x86_init.oem.banner();
 
 	mcheck_init();
+
+	local_irq_save(flags);
+	arch_init_ideal_nop5();
+	local_irq_restore(flags);
 }
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index a60df9a..002b796 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -131,13 +131,7 @@
 
 static void __init pcpu_fc_free(void *ptr, size_t size)
 {
-#ifdef CONFIG_NO_BOOTMEM
-	u64 start = __pa(ptr);
-	u64 end = start + size;
-	free_early_partial(start, end);
-#else
 	free_bootmem(__pa(ptr), size);
-#endif
 }
 
 static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
@@ -253,7 +247,7 @@
 		 * Up to this point, the boot CPU has been using .init.data
 		 * area.  Reload any changed state for the boot CPU.
 		 */
-		if (cpu == boot_cpu_id)
+		if (!cpu)
 			switch_to_new_gdt(cpu);
 	}
 
diff --git a/arch/x86/kernel/sfi.c b/arch/x86/kernel/sfi.c
index cb22acf..dd4c281 100644
--- a/arch/x86/kernel/sfi.c
+++ b/arch/x86/kernel/sfi.c
@@ -34,7 +34,7 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 
-void __init mp_sfi_register_lapic_address(unsigned long address)
+static void __init mp_sfi_register_lapic_address(unsigned long address)
 {
 	mp_lapic_addr = address;
 
@@ -46,7 +46,7 @@
 }
 
 /* All CPUs enumerated by SFI must be present and enabled */
-void __cpuinit mp_sfi_register_lapic(u8 id)
+static void __cpuinit mp_sfi_register_lapic(u8 id)
 {
 	if (MAX_APICS - id <= 0) {
 		pr_warning("Processor #%d invalid (max %d)\n",
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 8b3bfc4..6af1185 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -62,7 +62,7 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 #include <asm/mtrr.h>
-#include <asm/vmi.h>
+#include <asm/mwait.h>
 #include <asm/apic.h>
 #include <asm/setup.h>
 #include <asm/uv/uv.h>
@@ -299,23 +299,16 @@
 	 * fragile that we want to limit the things done here to the
 	 * most necessary things.
 	 */
-
-#ifdef CONFIG_X86_32
-	/*
-	 * Switch away from the trampoline page-table
-	 *
-	 * Do this before cpu_init() because it needs to access per-cpu
-	 * data which may not be mapped in the trampoline page-table.
-	 */
-	load_cr3(swapper_pg_dir);
-	__flush_tlb_all();
-#endif
-
-	vmi_bringup();
 	cpu_init();
 	preempt_disable();
 	smp_callin();
 
+#ifdef CONFIG_X86_32
+	/* switch away from the initial page table */
+	load_cr3(swapper_pg_dir);
+	__flush_tlb_all();
+#endif
+
 	/* otherwise gcc will move up smp_processor_id before the cpu_init */
 	barrier();
 	/*
@@ -324,9 +317,9 @@
 	check_tsc_sync_target();
 
 	if (nmi_watchdog == NMI_IO_APIC) {
-		legacy_pic->chip->mask(0);
+		legacy_pic->mask(0);
 		enable_NMI_through_LVT0();
-		legacy_pic->chip->unmask(0);
+		legacy_pic->unmask(0);
 	}
 
 	/* This must be done before setting cpu_online_mask */
@@ -397,6 +390,19 @@
 		identify_secondary_cpu(c);
 }
 
+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);
+}
+
 
 void __cpuinit set_cpu_sibling_map(int cpu)
 {
@@ -409,14 +415,13 @@
 		for_each_cpu(i, cpu_sibling_setup_mask) {
 			struct cpuinfo_x86 *o = &cpu_data(i);
 
-			if (c->phys_proc_id == o->phys_proc_id &&
-			    c->cpu_core_id == o->cpu_core_id) {
-				cpumask_set_cpu(i, cpu_sibling_mask(cpu));
-				cpumask_set_cpu(cpu, cpu_sibling_mask(i));
-				cpumask_set_cpu(i, cpu_core_mask(cpu));
-				cpumask_set_cpu(cpu, cpu_core_mask(i));
-				cpumask_set_cpu(i, c->llc_shared_map);
-				cpumask_set_cpu(cpu, o->llc_shared_map);
+			if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
+				if (c->phys_proc_id == o->phys_proc_id &&
+				    c->compute_unit_id == o->compute_unit_id)
+					link_thread_siblings(cpu, i);
+			} else if (c->phys_proc_id == o->phys_proc_id &&
+				   c->cpu_core_id == o->cpu_core_id) {
+				link_thread_siblings(cpu, i);
 			}
 		}
 	} else {
@@ -774,7 +779,6 @@
 #ifdef CONFIG_X86_32
 	/* Stack for startup_32 can be just as for start_secondary onwards */
 	irq_ctx_init(cpu);
-	initial_page_table = __pa(&trampoline_pg_dir);
 #else
 	clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
 	initial_gs = per_cpu_offset(cpu);
@@ -923,7 +927,6 @@
 	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
 
 	err = do_boot_cpu(apicid, cpu);
-
 	if (err) {
 		pr_debug("do_boot_cpu failed %d\n", err);
 		return -EIO;
@@ -1109,8 +1112,6 @@
 	}
 	set_cpu_sibling_map(0);
 
-	enable_IR_x2apic();
-	default_setup_apic_routing();
 
 	if (smp_sanity_check(max_cpus) < 0) {
 		printk(KERN_INFO "SMP disabled\n");
@@ -1118,6 +1119,8 @@
 		goto out;
 	}
 
+	default_setup_apic_routing();
+
 	preempt_disable();
 	if (read_apic_id() != boot_cpu_physical_apicid) {
 		panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
@@ -1383,11 +1386,88 @@
 	local_irq_disable();
 }
 
+/*
+ * We need to flush the caches before going to sleep, lest we have
+ * dirty data in our caches when we come back up.
+ */
+static inline void mwait_play_dead(void)
+{
+	unsigned int eax, ebx, ecx, edx;
+	unsigned int highest_cstate = 0;
+	unsigned int highest_subcstate = 0;
+	int i;
+	void *mwait_ptr;
+
+	if (!cpu_has(&current_cpu_data, X86_FEATURE_MWAIT))
+		return;
+	if (!cpu_has(&current_cpu_data, X86_FEATURE_CLFLSH))
+		return;
+	if (current_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
+		return;
+
+	eax = CPUID_MWAIT_LEAF;
+	ecx = 0;
+	native_cpuid(&eax, &ebx, &ecx, &edx);
+
+	/*
+	 * eax will be 0 if EDX enumeration is not valid.
+	 * Initialized below to cstate, sub_cstate value when EDX is valid.
+	 */
+	if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED)) {
+		eax = 0;
+	} else {
+		edx >>= MWAIT_SUBSTATE_SIZE;
+		for (i = 0; i < 7 && edx; i++, edx >>= MWAIT_SUBSTATE_SIZE) {
+			if (edx & MWAIT_SUBSTATE_MASK) {
+				highest_cstate = i;
+				highest_subcstate = edx & MWAIT_SUBSTATE_MASK;
+			}
+		}
+		eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
+			(highest_subcstate - 1);
+	}
+
+	/*
+	 * This should be a memory location in a cache line which is
+	 * unlikely to be touched by other processors.  The actual
+	 * content is immaterial as it is not actually modified in any way.
+	 */
+	mwait_ptr = &current_thread_info()->flags;
+
+	wbinvd();
+
+	while (1) {
+		/*
+		 * The CLFLUSH is a workaround for erratum AAI65 for
+		 * the Xeon 7400 series.  It's not clear it is actually
+		 * needed, but it should be harmless in either case.
+		 * The WBINVD is insufficient due to the spurious-wakeup
+		 * case where we return around the loop.
+		 */
+		clflush(mwait_ptr);
+		__monitor(mwait_ptr, 0, 0);
+		mb();
+		__mwait(eax, 0);
+	}
+}
+
+static inline void hlt_play_dead(void)
+{
+	if (current_cpu_data.x86 >= 4)
+		wbinvd();
+
+	while (1) {
+		native_halt();
+	}
+}
+
 void native_play_dead(void)
 {
 	play_dead_common();
 	tboot_shutdown(TB_SHUTDOWN_WFS);
-	wbinvd_halt();
+
+	mwait_play_dead();	/* Only returns on failure */
+	hlt_play_dead();
 }
 
 #else /* ... !CONFIG_HOTPLUG_CPU */
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c
index d5e0662..0b0cb5f 100644
--- a/arch/x86/kernel/sys_i386_32.c
+++ b/arch/x86/kernel/sys_i386_32.c
@@ -33,8 +33,8 @@
 		  const char *const envp[])
 {
 	long __res;
-	asm volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx"
+	asm volatile ("int $0x80"
 	: "=a" (__res)
-	: "0" (__NR_execve), "ri" (filename), "c" (argv), "d" (envp) : "memory");
+	: "0" (__NR_execve), "b" (filename), "c" (argv), "d" (envp) : "memory");
 	return __res;
 }
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c
index 312ef02..20ea20a 100644
--- a/arch/x86/kernel/tlb_uv.c
+++ b/arch/x86/kernel/tlb_uv.c
@@ -1001,10 +1001,10 @@
 static ssize_t tunables_read(struct file *file, char __user *userbuf,
 						size_t count, loff_t *ppos)
 {
-	char buf[300];
+	char *buf;
 	int ret;
 
-	ret = snprintf(buf, 300, "%s %s %s\n%d %d %d %d %d %d %d %d %d\n",
+	buf = kasprintf(GFP_KERNEL, "%s %s %s\n%d %d %d %d %d %d %d %d %d\n",
 		"max_bau_concurrent plugged_delay plugsb4reset",
 		"timeoutsb4reset ipi_reset_limit complete_threshold",
 		"congested_response_us congested_reps congested_period",
@@ -1012,7 +1012,12 @@
 		timeoutsb4reset, ipi_reset_limit, complete_threshold,
 		congested_response_us, congested_reps, congested_period);
 
-	return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+	kfree(buf);
+	return ret;
 }
 
 /*
@@ -1285,6 +1290,7 @@
 	.open		= tunables_open,
 	.read		= tunables_read,
 	.write		= tunables_write,
+	.llseek		= default_llseek,
 };
 
 static int __init uv_ptc_init(void)
diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c
index e2a5952..a375616 100644
--- a/arch/x86/kernel/trampoline.c
+++ b/arch/x86/kernel/trampoline.c
@@ -1,8 +1,8 @@
 #include <linux/io.h>
+#include <linux/memblock.h>
 
 #include <asm/trampoline.h>
 #include <asm/pgtable.h>
-#include <asm/e820.h>
 
 #if defined(CONFIG_X86_64) && defined(CONFIG_ACPI_SLEEP)
 #define __trampinit
@@ -17,15 +17,15 @@
 
 void __init reserve_trampoline_memory(void)
 {
-	unsigned long mem;
+	phys_addr_t mem;
 
 	/* Has to be in very low memory so we can execute real-mode AP code. */
-	mem = find_e820_area(0, 1<<20, TRAMPOLINE_SIZE, PAGE_SIZE);
-	if (mem == -1L)
+	mem = memblock_find_in_range(0, 1<<20, TRAMPOLINE_SIZE, PAGE_SIZE);
+	if (mem == MEMBLOCK_ERROR)
 		panic("Cannot allocate trampoline\n");
 
 	trampoline_base = __va(mem);
-	reserve_early(mem, mem + TRAMPOLINE_SIZE, "TRAMPOLINE");
+	memblock_x86_reserve_range(mem, mem + TRAMPOLINE_SIZE, "TRAMPOLINE");
 }
 
 /*
@@ -38,19 +38,3 @@
 	memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE);
 	return virt_to_phys(trampoline_base);
 }
-
-void __init setup_trampoline_page_table(void)
-{
-#ifdef CONFIG_X86_32
-	/* Copy kernel address range */
-	clone_pgd_range(trampoline_pg_dir + KERNEL_PGD_BOUNDARY,
-			swapper_pg_dir + KERNEL_PGD_BOUNDARY,
-			KERNEL_PGD_PTRS);
-
-	/* Initialize low mappings */
-	clone_pgd_range(trampoline_pg_dir,
-			swapper_pg_dir + KERNEL_PGD_BOUNDARY,
-			min_t(unsigned long, KERNEL_PGD_PTRS,
-			      KERNEL_PGD_BOUNDARY));
-#endif
-}
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 60788de..cb838ca 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -575,6 +575,7 @@
 	if (regs->flags & X86_VM_MASK) {
 		handle_vm86_trap((struct kernel_vm86_regs *) regs,
 				error_code, 1);
+		preempt_conditional_cli(regs);
 		return;
 	}
 
@@ -776,21 +777,10 @@
 }
 EXPORT_SYMBOL_GPL(math_state_restore);
 
-#ifndef CONFIG_MATH_EMULATION
-void math_emulate(struct math_emu_info *info)
-{
-	printk(KERN_EMERG
-		"math-emulation not enabled and no coprocessor found.\n");
-	printk(KERN_EMERG "killing %s.\n", current->comm);
-	force_sig(SIGFPE, current);
-	schedule();
-}
-#endif /* CONFIG_MATH_EMULATION */
-
 dotraplinkage void __kprobes
 do_device_not_available(struct pt_regs *regs, long error_code)
 {
-#ifdef CONFIG_X86_32
+#ifdef CONFIG_MATH_EMULATION
 	if (read_cr0() & X86_CR0_EM) {
 		struct math_emu_info info = { };
 
@@ -798,12 +788,12 @@
 
 		info.regs = regs;
 		math_emulate(&info);
-	} else {
-		math_state_restore(); /* interrupts still off */
-		conditional_sti(regs);
+		return;
 	}
-#else
-	math_state_restore();
+#endif
+	math_state_restore(); /* interrupts still off */
+#ifdef CONFIG_X86_32
+	conditional_sti(regs);
 #endif
 }
 
@@ -881,18 +871,6 @@
 #endif
 
 #ifdef CONFIG_X86_32
-	if (cpu_has_fxsr) {
-		printk(KERN_INFO "Enabling fast FPU save and restore... ");
-		set_in_cr4(X86_CR4_OSFXSR);
-		printk("done.\n");
-	}
-	if (cpu_has_xmm) {
-		printk(KERN_INFO
-			"Enabling unmasked SIMD FPU exception support... ");
-		set_in_cr4(X86_CR4_OSXMMEXCPT);
-		printk("done.\n");
-	}
-
 	set_system_trap_gate(SYSCALL_VECTOR, &system_call);
 	set_bit(SYSCALL_VECTOR, used_vectors);
 #endif
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 26a863a..0c40d8b 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -104,10 +104,14 @@
 
 __setup("notsc", notsc_setup);
 
+static int no_sched_irq_time;
+
 static int __init tsc_setup(char *str)
 {
 	if (!strcmp(str, "reliable"))
 		tsc_clocksource_reliable = 1;
+	if (!strncmp(str, "noirqtime", 9))
+		no_sched_irq_time = 1;
 	return 1;
 }
 
@@ -801,6 +805,7 @@
 	if (!tsc_unstable) {
 		tsc_unstable = 1;
 		sched_clock_stable = 0;
+		disable_sched_clock_irqtime();
 		printk(KERN_INFO "Marking TSC unstable due to %s\n", reason);
 		/* Change only the rating, when not registered */
 		if (clocksource_tsc.mult)
@@ -892,60 +897,6 @@
 	clocksource_register_khz(&clocksource_tsc, tsc_khz);
 }
 
-#ifdef CONFIG_X86_64
-/*
- * calibrate_cpu is used on systems with fixed rate TSCs to determine
- * processor frequency
- */
-#define TICK_COUNT 100000000
-static unsigned long __init calibrate_cpu(void)
-{
-	int tsc_start, tsc_now;
-	int i, no_ctr_free;
-	unsigned long evntsel3 = 0, pmc3 = 0, pmc_now = 0;
-	unsigned long flags;
-
-	for (i = 0; i < 4; i++)
-		if (avail_to_resrv_perfctr_nmi_bit(i))
-			break;
-	no_ctr_free = (i == 4);
-	if (no_ctr_free) {
-		WARN(1, KERN_WARNING "Warning: AMD perfctrs busy ... "
-		     "cpu_khz value may be incorrect.\n");
-		i = 3;
-		rdmsrl(MSR_K7_EVNTSEL3, evntsel3);
-		wrmsrl(MSR_K7_EVNTSEL3, 0);
-		rdmsrl(MSR_K7_PERFCTR3, pmc3);
-	} else {
-		reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i);
-		reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
-	}
-	local_irq_save(flags);
-	/* start measuring cycles, incrementing from 0 */
-	wrmsrl(MSR_K7_PERFCTR0 + i, 0);
-	wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76);
-	rdtscl(tsc_start);
-	do {
-		rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now);
-		tsc_now = get_cycles();
-	} while ((tsc_now - tsc_start) < TICK_COUNT);
-
-	local_irq_restore(flags);
-	if (no_ctr_free) {
-		wrmsrl(MSR_K7_EVNTSEL3, 0);
-		wrmsrl(MSR_K7_PERFCTR3, pmc3);
-		wrmsrl(MSR_K7_EVNTSEL3, evntsel3);
-	} else {
-		release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
-		release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
-	}
-
-	return pmc_now * tsc_khz / (tsc_now - tsc_start);
-}
-#else
-static inline unsigned long calibrate_cpu(void) { return cpu_khz; }
-#endif
-
 void __init tsc_init(void)
 {
 	u64 lpj;
@@ -964,10 +915,6 @@
 		return;
 	}
 
-	if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&
-			(boot_cpu_data.x86_vendor == X86_VENDOR_AMD))
-		cpu_khz = calibrate_cpu();
-
 	printk("Detected %lu.%03lu MHz processor.\n",
 			(unsigned long)cpu_khz / 1000,
 			(unsigned long)cpu_khz % 1000);
@@ -987,6 +934,9 @@
 	/* now allow native_sched_clock() to use rdtsc */
 	tsc_disabled = 0;
 
+	if (!no_sched_irq_time)
+		enable_sched_clock_irqtime();
+
 	lpj = ((u64)tsc_khz * 1000);
 	do_div(lpj, HZ);
 	lpj_fine = lpj;
diff --git a/arch/x86/kernel/uv_irq.c b/arch/x86/kernel/uv_irq.c
index 1132129..7b24460 100644
--- a/arch/x86/kernel/uv_irq.c
+++ b/arch/x86/kernel/uv_irq.c
@@ -28,34 +28,21 @@
 static spinlock_t		uv_irq_lock;
 static struct rb_root		uv_irq_root;
 
-static int uv_set_irq_affinity(unsigned int, const struct cpumask *);
+static int uv_set_irq_affinity(struct irq_data *, const struct cpumask *, bool);
 
-static void uv_noop(unsigned int irq)
-{
-}
+static void uv_noop(struct irq_data *data) { }
 
-static unsigned int uv_noop_ret(unsigned int irq)
-{
-	return 0;
-}
-
-static void uv_ack_apic(unsigned int irq)
+static void uv_ack_apic(struct irq_data *data)
 {
 	ack_APIC_irq();
 }
 
 static struct irq_chip uv_irq_chip = {
-	.name		= "UV-CORE",
-	.startup	= uv_noop_ret,
-	.shutdown	= uv_noop,
-	.enable		= uv_noop,
-	.disable	= uv_noop,
-	.ack		= uv_noop,
-	.mask		= uv_noop,
-	.unmask		= uv_noop,
-	.eoi		= uv_ack_apic,
-	.end		= uv_noop,
-	.set_affinity	= uv_set_irq_affinity,
+	.name			= "UV-CORE",
+	.irq_mask		= uv_noop,
+	.irq_unmask		= uv_noop,
+	.irq_eoi		= uv_ack_apic,
+	.irq_set_affinity	= uv_set_irq_affinity,
 };
 
 /*
@@ -144,26 +131,22 @@
 		       unsigned long mmr_offset, int limit)
 {
 	const struct cpumask *eligible_cpu = cpumask_of(cpu);
-	struct irq_desc *desc = irq_to_desc(irq);
-	struct irq_cfg *cfg;
-	int mmr_pnode;
+	struct irq_cfg *cfg = get_irq_chip_data(irq);
 	unsigned long mmr_value;
 	struct uv_IO_APIC_route_entry *entry;
-	int err;
+	int mmr_pnode, err;
 
 	BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
 			sizeof(unsigned long));
 
-	cfg = irq_cfg(irq);
-
 	err = assign_irq_vector(irq, cfg, eligible_cpu);
 	if (err != 0)
 		return err;
 
 	if (limit == UV_AFFINITY_CPU)
-		desc->status |= IRQ_NO_BALANCING;
+		irq_set_status_flags(irq, IRQ_NO_BALANCING);
 	else
-		desc->status |= IRQ_MOVE_PCNTXT;
+		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
 
 	set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
 				      irq_name);
@@ -206,17 +189,17 @@
 	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
 }
 
-static int uv_set_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
+		    bool force)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	struct irq_cfg *cfg = desc->chip_data;
+	struct irq_cfg *cfg = data->chip_data;
 	unsigned int dest;
-	unsigned long mmr_value;
+	unsigned long mmr_value, mmr_offset;
 	struct uv_IO_APIC_route_entry *entry;
-	unsigned long mmr_offset;
 	int mmr_pnode;
 
-	if (set_desc_affinity(desc, mask, &dest))
+	if (__ioapic_set_affinity(data, mask, &dest))
 		return -1;
 
 	mmr_value = 0;
@@ -231,7 +214,7 @@
 	entry->dest		= dest;
 
 	/* Get previously stored MMR and pnode of hub sourcing interrupts */
-	if (uv_irq_2_mmr_info(irq, &mmr_offset, &mmr_pnode))
+	if (uv_irq_2_mmr_info(data->irq, &mmr_offset, &mmr_pnode))
 		return -1;
 
 	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c
index e680ea5..3371bd0 100644
--- a/arch/x86/kernel/visws_quirks.c
+++ b/arch/x86/kernel/visws_quirks.c
@@ -66,10 +66,7 @@
 }
 
 /* Replaces the default init_ISA_irqs in the generic setup */
-static void __init visws_pre_intr_init(void)
-{
-	init_VISWS_APIC_irqs();
-}
+static void __init visws_pre_intr_init(void);
 
 /* Quirk for machine specific memory setup. */
 
@@ -429,67 +426,34 @@
 /*
  * This is the SGI Cobalt (IO-)APIC:
  */
-
-static void enable_cobalt_irq(unsigned int irq)
+static void enable_cobalt_irq(struct irq_data *data)
 {
-	co_apic_set(is_co_apic(irq), irq);
+	co_apic_set(is_co_apic(data->irq), data->irq);
 }
 
-static void disable_cobalt_irq(unsigned int irq)
+static void disable_cobalt_irq(struct irq_data *data)
 {
-	int entry = is_co_apic(irq);
+	int entry = is_co_apic(data->irq);
 
 	co_apic_write(CO_APIC_LO(entry), CO_APIC_MASK);
 	co_apic_read(CO_APIC_LO(entry));
 }
 
-/*
- * "irq" really just serves to identify the device.  Here is where we
- * map this to the Cobalt APIC entry where it's physically wired.
- * This is called via request_irq -> setup_irq -> irq_desc->startup()
- */
-static unsigned int startup_cobalt_irq(unsigned int irq)
-{
-	unsigned long flags;
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	spin_lock_irqsave(&cobalt_lock, flags);
-	if ((desc->status & (IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING)))
-		desc->status &= ~(IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING);
-	enable_cobalt_irq(irq);
-	spin_unlock_irqrestore(&cobalt_lock, flags);
-	return 0;
-}
-
-static void ack_cobalt_irq(unsigned int irq)
+static void ack_cobalt_irq(struct irq_data *data)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&cobalt_lock, flags);
-	disable_cobalt_irq(irq);
+	disable_cobalt_irq(data);
 	apic_write(APIC_EOI, APIC_EIO_ACK);
 	spin_unlock_irqrestore(&cobalt_lock, flags);
 }
 
-static void end_cobalt_irq(unsigned int irq)
-{
-	unsigned long flags;
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	spin_lock_irqsave(&cobalt_lock, flags);
-	if (!(desc->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		enable_cobalt_irq(irq);
-	spin_unlock_irqrestore(&cobalt_lock, flags);
-}
-
 static struct irq_chip cobalt_irq_type = {
-	.name =		"Cobalt-APIC",
-	.startup =	startup_cobalt_irq,
-	.shutdown =	disable_cobalt_irq,
-	.enable =	enable_cobalt_irq,
-	.disable =	disable_cobalt_irq,
-	.ack =		ack_cobalt_irq,
-	.end =		end_cobalt_irq,
+	.name		= "Cobalt-APIC",
+	.irq_enable	= enable_cobalt_irq,
+	.irq_disable	= disable_cobalt_irq,
+	.irq_ack	= ack_cobalt_irq,
 };
 
 
@@ -503,35 +467,34 @@
  * interrupt controller type, and through a special virtual interrupt-
  * controller. Device drivers only see the virtual interrupt sources.
  */
-static unsigned int startup_piix4_master_irq(unsigned int irq)
+static unsigned int startup_piix4_master_irq(struct irq_data *data)
 {
 	legacy_pic->init(0);
-
-	return startup_cobalt_irq(irq);
+	enable_cobalt_irq(data);
 }
 
-static void end_piix4_master_irq(unsigned int irq)
+static void end_piix4_master_irq(struct irq_data *data)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&cobalt_lock, flags);
-	enable_cobalt_irq(irq);
+	enable_cobalt_irq(data);
 	spin_unlock_irqrestore(&cobalt_lock, flags);
 }
 
 static struct irq_chip piix4_master_irq_type = {
-	.name =		"PIIX4-master",
-	.startup =	startup_piix4_master_irq,
-	.ack =		ack_cobalt_irq,
-	.end =		end_piix4_master_irq,
+	.name		= "PIIX4-master",
+	.irq_startup	= startup_piix4_master_irq,
+	.irq_ack	= ack_cobalt_irq,
 };
 
+static void pii4_mask(struct irq_data *data) { }
 
 static struct irq_chip piix4_virtual_irq_type = {
-	.name =		"PIIX4-virtual",
+	.name		= "PIIX4-virtual",
+	.mask		= pii4_mask,
 };
 
-
 /*
  * PIIX4-8259 master/virtual functions to handle interrupt requests
  * from legacy devices: floppy, parallel, serial, rtc.
@@ -549,9 +512,8 @@
  */
 static irqreturn_t piix4_master_intr(int irq, void *dev_id)
 {
-	int realirq;
-	struct irq_desc *desc;
 	unsigned long flags;
+	int realirq;
 
 	raw_spin_lock_irqsave(&i8259A_lock, flags);
 
@@ -592,18 +554,10 @@
 
 	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 
-	desc = irq_to_desc(realirq);
-
 	/*
 	 * handle this 'virtual interrupt' as a Cobalt one now.
 	 */
-	kstat_incr_irqs_this_cpu(realirq, desc);
-
-	if (likely(desc->action != NULL))
-		handle_IRQ_event(realirq, desc->action);
-
-	if (!(desc->status & IRQ_DISABLED))
-		legacy_pic->chip->unmask(realirq);
+	generic_handle_irq(realirq);
 
 	return IRQ_HANDLED;
 
@@ -624,41 +578,35 @@
 
 static inline void set_piix4_virtual_irq_type(void)
 {
-	piix4_virtual_irq_type.shutdown = i8259A_chip.mask;
 	piix4_virtual_irq_type.enable =	i8259A_chip.unmask;
 	piix4_virtual_irq_type.disable = i8259A_chip.mask;
+	piix4_virtual_irq_type.unmask =	i8259A_chip.unmask;
 }
 
-void init_VISWS_APIC_irqs(void)
+static void __init visws_pre_intr_init(void)
 {
 	int i;
 
+	set_piix4_virtual_irq_type();
+
 	for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
-		struct irq_desc *desc = irq_to_desc(i);
+		struct irq_chip *chip = NULL;
 
-		desc->status = IRQ_DISABLED;
-		desc->action = 0;
-		desc->depth = 1;
+		if (i == 0)
+			chip = &cobalt_irq_type;
+		else if (i == CO_IRQ_IDE0)
+			chip = &cobalt_irq_type;
+		else if (i == CO_IRQ_IDE1)
+			>chip = &cobalt_irq_type;
+		else if (i == CO_IRQ_8259)
+			chip = &piix4_master_irq_type;
+		else if (i < CO_IRQ_APIC0)
+			chip = &piix4_virtual_irq_type;
+		else if (IS_CO_APIC(i))
+			chip = &cobalt_irq_type;
 
-		if (i == 0) {
-			desc->chip = &cobalt_irq_type;
-		}
-		else if (i == CO_IRQ_IDE0) {
-			desc->chip = &cobalt_irq_type;
-		}
-		else if (i == CO_IRQ_IDE1) {
-			desc->chip = &cobalt_irq_type;
-		}
-		else if (i == CO_IRQ_8259) {
-			desc->chip = &piix4_master_irq_type;
-		}
-		else if (i < CO_IRQ_APIC0) {
-			set_piix4_virtual_irq_type();
-			desc->chip = &piix4_virtual_irq_type;
-		}
-		else if (IS_CO_APIC(i)) {
-			desc->chip = &cobalt_irq_type;
-		}
+		if (chip)
+			set_irq_chip(i, chip);
 	}
 
 	setup_irq(CO_IRQ_8259, &master_action);
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index 5ffb5622..61fb985 100644
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -551,8 +551,14 @@
 int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int trapno)
 {
 	if (VMPI.is_vm86pus) {
-		if ((trapno == 3) || (trapno == 1))
-			return_to_32bit(regs, VM86_TRAP + (trapno << 8));
+		if ((trapno == 3) || (trapno == 1)) {
+			KVM86->regs32->ax = VM86_TRAP + (trapno << 8);
+			/* setting this flag forces the code in entry_32.S to
+			   call save_v86_state() and change the stack pointer
+			   to KVM86->regs32 */
+			set_thread_flag(TIF_IRET);
+			return 0;
+		}
 		do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs));
 		return 0;
 	}
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
deleted file mode 100644
index ce9fbac..0000000
--- a/arch/x86/kernel/vmi_32.c
+++ /dev/null
@@ -1,893 +0,0 @@
-/*
- * VMI specific paravirt-ops implementation
- *
- * Copyright (C) 2005, VMware, 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to zach@vmware.com
- *
- */
-
-#include <linux/module.h>
-#include <linux/cpu.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/sched.h>
-#include <linux/gfp.h>
-#include <asm/vmi.h>
-#include <asm/io.h>
-#include <asm/fixmap.h>
-#include <asm/apicdef.h>
-#include <asm/apic.h>
-#include <asm/pgalloc.h>
-#include <asm/processor.h>
-#include <asm/timer.h>
-#include <asm/vmi_time.h>
-#include <asm/kmap_types.h>
-#include <asm/setup.h>
-
-/* Convenient for calling VMI functions indirectly in the ROM */
-typedef u32 __attribute__((regparm(1))) (VROMFUNC)(void);
-typedef u64 __attribute__((regparm(2))) (VROMLONGFUNC)(int);
-
-#define call_vrom_func(rom,func) \
-   (((VROMFUNC *)(rom->func))())
-
-#define call_vrom_long_func(rom,func,arg) \
-   (((VROMLONGFUNC *)(rom->func)) (arg))
-
-static struct vrom_header *vmi_rom;
-static int disable_pge;
-static int disable_pse;
-static int disable_sep;
-static int disable_tsc;
-static int disable_mtrr;
-static int disable_noidle;
-static int disable_vmi_timer;
-
-/* Cached VMI operations */
-static struct {
-	void (*cpuid)(void /* non-c */);
-	void (*_set_ldt)(u32 selector);
-	void (*set_tr)(u32 selector);
-	void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
-	void (*write_gdt_entry)(struct desc_struct *, int, u32, u32);
-	void (*write_ldt_entry)(struct desc_struct *, int, u32, u32);
-	void (*set_kernel_stack)(u32 selector, u32 sp0);
-	void (*allocate_page)(u32, u32, u32, u32, u32);
-	void (*release_page)(u32, u32);
-	void (*set_pte)(pte_t, pte_t *, unsigned);
-	void (*update_pte)(pte_t *, unsigned);
-	void (*set_linear_mapping)(int, void *, u32, u32);
-	void (*_flush_tlb)(int);
-	void (*set_initial_ap_state)(int, int);
-	void (*halt)(void);
-  	void (*set_lazy_mode)(int mode);
-} vmi_ops;
-
-/* Cached VMI operations */
-struct vmi_timer_ops vmi_timer_ops;
-
-/*
- * VMI patching routines.
- */
-#define MNEM_CALL 0xe8
-#define MNEM_JMP  0xe9
-#define MNEM_RET  0xc3
-
-#define IRQ_PATCH_INT_MASK 0
-#define IRQ_PATCH_DISABLE  5
-
-static inline void patch_offset(void *insnbuf,
-				unsigned long ip, unsigned long dest)
-{
-        *(unsigned long *)(insnbuf+1) = dest-ip-5;
-}
-
-static unsigned patch_internal(int call, unsigned len, void *insnbuf,
-			       unsigned long ip)
-{
-	u64 reloc;
-	struct vmi_relocation_info *const rel = (struct vmi_relocation_info *)&reloc;
-	reloc = call_vrom_long_func(vmi_rom, get_reloc,	call);
-	switch(rel->type) {
-		case VMI_RELOCATION_CALL_REL:
-			BUG_ON(len < 5);
-			*(char *)insnbuf = MNEM_CALL;
-			patch_offset(insnbuf, ip, (unsigned long)rel->eip);
-			return 5;
-
-		case VMI_RELOCATION_JUMP_REL:
-			BUG_ON(len < 5);
-			*(char *)insnbuf = MNEM_JMP;
-			patch_offset(insnbuf, ip, (unsigned long)rel->eip);
-			return 5;
-
-		case VMI_RELOCATION_NOP:
-			/* obliterate the whole thing */
-			return 0;
-
-		case VMI_RELOCATION_NONE:
-			/* leave native code in place */
-			break;
-
-		default:
-			BUG();
-	}
-	return len;
-}
-
-/*
- * Apply patch if appropriate, return length of new instruction
- * sequence.  The callee does nop padding for us.
- */
-static unsigned vmi_patch(u8 type, u16 clobbers, void *insns,
-			  unsigned long ip, unsigned len)
-{
-	switch (type) {
-		case PARAVIRT_PATCH(pv_irq_ops.irq_disable):
-			return patch_internal(VMI_CALL_DisableInterrupts, len,
-					      insns, ip);
-		case PARAVIRT_PATCH(pv_irq_ops.irq_enable):
-			return patch_internal(VMI_CALL_EnableInterrupts, len,
-					      insns, ip);
-		case PARAVIRT_PATCH(pv_irq_ops.restore_fl):
-			return patch_internal(VMI_CALL_SetInterruptMask, len,
-					      insns, ip);
-		case PARAVIRT_PATCH(pv_irq_ops.save_fl):
-			return patch_internal(VMI_CALL_GetInterruptMask, len,
-					      insns, ip);
-		case PARAVIRT_PATCH(pv_cpu_ops.iret):
-			return patch_internal(VMI_CALL_IRET, len, insns, ip);
-		case PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit):
-			return patch_internal(VMI_CALL_SYSEXIT, len, insns, ip);
-		default:
-			break;
-	}
-	return len;
-}
-
-/* CPUID has non-C semantics, and paravirt-ops API doesn't match hardware ISA */
-static void vmi_cpuid(unsigned int *ax, unsigned int *bx,
-                               unsigned int *cx, unsigned int *dx)
-{
-	int override = 0;
-	if (*ax == 1)
-		override = 1;
-        asm volatile ("call *%6"
-                      : "=a" (*ax),
-                        "=b" (*bx),
-                        "=c" (*cx),
-                        "=d" (*dx)
-                      : "0" (*ax), "2" (*cx), "r" (vmi_ops.cpuid));
-	if (override) {
-		if (disable_pse)
-			*dx &= ~X86_FEATURE_PSE;
-		if (disable_pge)
-			*dx &= ~X86_FEATURE_PGE;
-		if (disable_sep)
-			*dx &= ~X86_FEATURE_SEP;
-		if (disable_tsc)
-			*dx &= ~X86_FEATURE_TSC;
-		if (disable_mtrr)
-			*dx &= ~X86_FEATURE_MTRR;
-	}
-}
-
-static inline void vmi_maybe_load_tls(struct desc_struct *gdt, int nr, struct desc_struct *new)
-{
-	if (gdt[nr].a != new->a || gdt[nr].b != new->b)
-		write_gdt_entry(gdt, nr, new, 0);
-}
-
-static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
-{
-	struct desc_struct *gdt = get_cpu_gdt_table(cpu);
-	vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 0, &t->tls_array[0]);
-	vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 1, &t->tls_array[1]);
-	vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 2, &t->tls_array[2]);
-}
-
-static void vmi_set_ldt(const void *addr, unsigned entries)
-{
-	unsigned cpu = smp_processor_id();
-	struct desc_struct desc;
-
-	pack_descriptor(&desc, (unsigned long)addr,
-			entries * sizeof(struct desc_struct) - 1,
-			DESC_LDT, 0);
-	write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, &desc, DESC_LDT);
-	vmi_ops._set_ldt(entries ? GDT_ENTRY_LDT*sizeof(struct desc_struct) : 0);
-}
-
-static void vmi_set_tr(void)
-{
-	vmi_ops.set_tr(GDT_ENTRY_TSS*sizeof(struct desc_struct));
-}
-
-static void vmi_write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
-{
-	u32 *idt_entry = (u32 *)g;
-	vmi_ops.write_idt_entry(dt, entry, idt_entry[0], idt_entry[1]);
-}
-
-static void vmi_write_gdt_entry(struct desc_struct *dt, int entry,
-				const void *desc, int type)
-{
-	u32 *gdt_entry = (u32 *)desc;
-	vmi_ops.write_gdt_entry(dt, entry, gdt_entry[0], gdt_entry[1]);
-}
-
-static void vmi_write_ldt_entry(struct desc_struct *dt, int entry,
-				const void *desc)
-{
-	u32 *ldt_entry = (u32 *)desc;
-	vmi_ops.write_ldt_entry(dt, entry, ldt_entry[0], ldt_entry[1]);
-}
-
-static void vmi_load_sp0(struct tss_struct *tss,
-				   struct thread_struct *thread)
-{
-	tss->x86_tss.sp0 = thread->sp0;
-
-	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
-	if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
-		tss->x86_tss.ss1 = thread->sysenter_cs;
-		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
-	}
-	vmi_ops.set_kernel_stack(__KERNEL_DS, tss->x86_tss.sp0);
-}
-
-static void vmi_flush_tlb_user(void)
-{
-	vmi_ops._flush_tlb(VMI_FLUSH_TLB);
-}
-
-static void vmi_flush_tlb_kernel(void)
-{
-	vmi_ops._flush_tlb(VMI_FLUSH_TLB | VMI_FLUSH_GLOBAL);
-}
-
-/* Stub to do nothing at all; used for delays and unimplemented calls */
-static void vmi_nop(void)
-{
-}
-
-static void vmi_allocate_pte(struct mm_struct *mm, unsigned long pfn)
-{
-	vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0);
-}
-
-static void vmi_allocate_pmd(struct mm_struct *mm, unsigned long pfn)
-{
- 	/*
-	 * This call comes in very early, before mem_map is setup.
-	 * It is called only for swapper_pg_dir, which already has
-	 * data on it.
-	 */
-	vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0);
-}
-
-static void vmi_allocate_pmd_clone(unsigned long pfn, unsigned long clonepfn, unsigned long start, unsigned long count)
-{
-	vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count);
-}
-
-static void vmi_release_pte(unsigned long pfn)
-{
-	vmi_ops.release_page(pfn, VMI_PAGE_L1);
-}
-
-static void vmi_release_pmd(unsigned long pfn)
-{
-	vmi_ops.release_page(pfn, VMI_PAGE_L2);
-}
-
-/*
- * We use the pgd_free hook for releasing the pgd page:
- */
-static void vmi_pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
-	unsigned long pfn = __pa(pgd) >> PAGE_SHIFT;
-
-	vmi_ops.release_page(pfn, VMI_PAGE_L2);
-}
-
-/*
- * Helper macros for MMU update flags.  We can defer updates until a flush
- * or page invalidation only if the update is to the current address space
- * (otherwise, there is no flush).  We must check against init_mm, since
- * this could be a kernel update, which usually passes init_mm, although
- * sometimes this check can be skipped if we know the particular function
- * is only called on user mode PTEs.  We could change the kernel to pass
- * current->active_mm here, but in particular, I was unsure if changing
- * mm/highmem.c to do this would still be correct on other architectures.
- */
-#define is_current_as(mm, mustbeuser) ((mm) == current->active_mm ||    \
-                                       (!mustbeuser && (mm) == &init_mm))
-#define vmi_flags_addr(mm, addr, level, user)                           \
-        ((level) | (is_current_as(mm, user) ?                           \
-                (VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0))
-#define vmi_flags_addr_defer(mm, addr, level, user)                     \
-        ((level) | (is_current_as(mm, user) ?                           \
-                (VMI_PAGE_DEFER | VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0))
-
-static void vmi_update_pte(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-	vmi_ops.update_pte(ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_update_pte_defer(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-	vmi_ops.update_pte(ptep, vmi_flags_addr_defer(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_set_pte(pte_t *ptep, pte_t pte)
-{
-	/* XXX because of set_pmd_pte, this can be called on PT or PD layers */
-	vmi_ops.set_pte(pte, ptep, VMI_PAGE_PT);
-}
-
-static void vmi_set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
-{
-	vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_set_pmd(pmd_t *pmdp, pmd_t pmdval)
-{
-#ifdef CONFIG_X86_PAE
-	const pte_t pte = { .pte = pmdval.pmd };
-#else
-	const pte_t pte = { pmdval.pud.pgd.pgd };
-#endif
-	vmi_ops.set_pte(pte, (pte_t *)pmdp, VMI_PAGE_PD);
-}
-
-#ifdef CONFIG_X86_PAE
-
-static void vmi_set_pte_atomic(pte_t *ptep, pte_t pteval)
-{
-	/*
-	 * XXX This is called from set_pmd_pte, but at both PT
-	 * and PD layers so the VMI_PAGE_PT flag is wrong.  But
-	 * it is only called for large page mapping changes,
-	 * the Xen backend, doesn't support large pages, and the
-	 * ESX backend doesn't depend on the flag.
-	 */
-	set_64bit((unsigned long long *)ptep,pte_val(pteval));
-	vmi_ops.update_pte(ptep, VMI_PAGE_PT);
-}
-
-static void vmi_set_pud(pud_t *pudp, pud_t pudval)
-{
-	/* Um, eww */
-	const pte_t pte = { .pte = pudval.pgd.pgd };
-	vmi_ops.set_pte(pte, (pte_t *)pudp, VMI_PAGE_PDP);
-}
-
-static void vmi_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
-	const pte_t pte = { .pte = 0 };
-	vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_pmd_clear(pmd_t *pmd)
-{
-	const pte_t pte = { .pte = 0 };
-	vmi_ops.set_pte(pte, (pte_t *)pmd, VMI_PAGE_PD);
-}
-#endif
-
-#ifdef CONFIG_SMP
-static void __devinit
-vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
-		     unsigned long start_esp)
-{
-	struct vmi_ap_state ap;
-
-	/* Default everything to zero.  This is fine for most GPRs. */
-	memset(&ap, 0, sizeof(struct vmi_ap_state));
-
-	ap.gdtr_limit = GDT_SIZE - 1;
-	ap.gdtr_base = (unsigned long) get_cpu_gdt_table(phys_apicid);
-
-	ap.idtr_limit = IDT_ENTRIES * 8 - 1;
-	ap.idtr_base = (unsigned long) idt_table;
-
-	ap.ldtr = 0;
-
-	ap.cs = __KERNEL_CS;
-	ap.eip = (unsigned long) start_eip;
-	ap.ss = __KERNEL_DS;
-	ap.esp = (unsigned long) start_esp;
-
-	ap.ds = __USER_DS;
-	ap.es = __USER_DS;
-	ap.fs = __KERNEL_PERCPU;
-	ap.gs = __KERNEL_STACK_CANARY;
-
-	ap.eflags = 0;
-
-#ifdef CONFIG_X86_PAE
-	/* efer should match BSP efer. */
-	if (cpu_has_nx) {
-		unsigned l, h;
-		rdmsr(MSR_EFER, l, h);
-		ap.efer = (unsigned long long) h << 32 | l;
-	}
-#endif
-
-	ap.cr3 = __pa(swapper_pg_dir);
-	/* Protected mode, paging, AM, WP, NE, MP. */
-	ap.cr0 = 0x80050023;
-	ap.cr4 = mmu_cr4_features;
-	vmi_ops.set_initial_ap_state((u32)&ap, phys_apicid);
-}
-#endif
-
-static void vmi_start_context_switch(struct task_struct *prev)
-{
-	paravirt_start_context_switch(prev);
-	vmi_ops.set_lazy_mode(2);
-}
-
-static void vmi_end_context_switch(struct task_struct *next)
-{
-	vmi_ops.set_lazy_mode(0);
-	paravirt_end_context_switch(next);
-}
-
-static void vmi_enter_lazy_mmu(void)
-{
-	paravirt_enter_lazy_mmu();
-	vmi_ops.set_lazy_mode(1);
-}
-
-static void vmi_leave_lazy_mmu(void)
-{
-	vmi_ops.set_lazy_mode(0);
-	paravirt_leave_lazy_mmu();
-}
-
-static inline int __init check_vmi_rom(struct vrom_header *rom)
-{
-	struct pci_header *pci;
-	struct pnp_header *pnp;
-	const char *manufacturer = "UNKNOWN";
-	const char *product = "UNKNOWN";
-	const char *license = "unspecified";
-
-	if (rom->rom_signature != 0xaa55)
-		return 0;
-	if (rom->vrom_signature != VMI_SIGNATURE)
-		return 0;
-	if (rom->api_version_maj != VMI_API_REV_MAJOR ||
-	    rom->api_version_min+1 < VMI_API_REV_MINOR+1) {
-		printk(KERN_WARNING "VMI: Found mismatched rom version %d.%d\n",
-				rom->api_version_maj,
-				rom->api_version_min);
-		return 0;
-	}
-
-	/*
-	 * Relying on the VMI_SIGNATURE field is not 100% safe, so check
-	 * the PCI header and device type to make sure this is really a
-	 * VMI device.
-	 */
-	if (!rom->pci_header_offs) {
-		printk(KERN_WARNING "VMI: ROM does not contain PCI header.\n");
-		return 0;
-	}
-
-	pci = (struct pci_header *)((char *)rom+rom->pci_header_offs);
-	if (pci->vendorID != PCI_VENDOR_ID_VMWARE ||
-	    pci->deviceID != PCI_DEVICE_ID_VMWARE_VMI) {
-		/* Allow it to run... anyways, but warn */
-		printk(KERN_WARNING "VMI: ROM from unknown manufacturer\n");
-	}
-
-	if (rom->pnp_header_offs) {
-		pnp = (struct pnp_header *)((char *)rom+rom->pnp_header_offs);
-		if (pnp->manufacturer_offset)
-			manufacturer = (const char *)rom+pnp->manufacturer_offset;
-		if (pnp->product_offset)
-			product = (const char *)rom+pnp->product_offset;
-	}
-
-	if (rom->license_offs)
-		license = (char *)rom+rom->license_offs;
-
-	printk(KERN_INFO "VMI: Found %s %s, API version %d.%d, ROM version %d.%d\n",
-		manufacturer, product,
-		rom->api_version_maj, rom->api_version_min,
-		pci->rom_version_maj, pci->rom_version_min);
-
-	/* Don't allow BSD/MIT here for now because we don't want to end up
-	   with any binary only shim layers */
-	if (strcmp(license, "GPL") && strcmp(license, "GPL v2")) {
-		printk(KERN_WARNING "VMI: Non GPL license `%s' found for ROM. Not used.\n",
-			license);
-		return 0;
-	}
-
-	return 1;
-}
-
-/*
- * Probe for the VMI option ROM
- */
-static inline int __init probe_vmi_rom(void)
-{
-	unsigned long base;
-
-	/* VMI ROM is in option ROM area, check signature */
-	for (base = 0xC0000; base < 0xE0000; base += 2048) {
-		struct vrom_header *romstart;
-		romstart = (struct vrom_header *)isa_bus_to_virt(base);
-		if (check_vmi_rom(romstart)) {
-			vmi_rom = romstart;
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/*
- * VMI setup common to all processors
- */
-void vmi_bringup(void)
-{
- 	/* We must establish the lowmem mapping for MMU ops to work */
-	if (vmi_ops.set_linear_mapping)
-		vmi_ops.set_linear_mapping(0, (void *)__PAGE_OFFSET, MAXMEM_PFN, 0);
-}
-
-/*
- * Return a pointer to a VMI function or NULL if unimplemented
- */
-static void *vmi_get_function(int vmicall)
-{
-	u64 reloc;
-	const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
-	reloc = call_vrom_long_func(vmi_rom, get_reloc,	vmicall);
-	BUG_ON(rel->type == VMI_RELOCATION_JUMP_REL);
-	if (rel->type == VMI_RELOCATION_CALL_REL)
-		return (void *)rel->eip;
-	else
-		return NULL;
-}
-
-/*
- * Helper macro for making the VMI paravirt-ops fill code readable.
- * For unimplemented operations, fall back to default, unless nop
- * is returned by the ROM.
- */
-#define para_fill(opname, vmicall)				\
-do {								\
-	reloc = call_vrom_long_func(vmi_rom, get_reloc,		\
-				    VMI_CALL_##vmicall);	\
-	if (rel->type == VMI_RELOCATION_CALL_REL) 		\
-		opname = (void *)rel->eip;			\
-	else if (rel->type == VMI_RELOCATION_NOP) 		\
-		opname = (void *)vmi_nop;			\
-	else if (rel->type != VMI_RELOCATION_NONE)		\
-		printk(KERN_WARNING "VMI: Unknown relocation "	\
-				    "type %d for " #vmicall"\n",\
-					rel->type);		\
-} while (0)
-
-/*
- * Helper macro for making the VMI paravirt-ops fill code readable.
- * For cached operations which do not match the VMI ROM ABI and must
- * go through a tranlation stub.  Ignore NOPs, since it is not clear
- * a NOP * VMI function corresponds to a NOP paravirt-op when the
- * functions are not in 1-1 correspondence.
- */
-#define para_wrap(opname, wrapper, cache, vmicall)		\
-do {								\
-	reloc = call_vrom_long_func(vmi_rom, get_reloc,		\
-				    VMI_CALL_##vmicall);	\
-	BUG_ON(rel->type == VMI_RELOCATION_JUMP_REL);		\
-	if (rel->type == VMI_RELOCATION_CALL_REL) {		\
-		opname = wrapper;				\
-		vmi_ops.cache = (void *)rel->eip;		\
-	}							\
-} while (0)
-
-/*
- * Activate the VMI interface and switch into paravirtualized mode
- */
-static inline int __init activate_vmi(void)
-{
-	short kernel_cs;
-	u64 reloc;
-	const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
-
-	/*
-	 * Prevent page tables from being allocated in highmem, even if
-	 * CONFIG_HIGHPTE is enabled.
-	 */
-	__userpte_alloc_gfp &= ~__GFP_HIGHMEM;
-
-	if (call_vrom_func(vmi_rom, vmi_init) != 0) {
-		printk(KERN_ERR "VMI ROM failed to initialize!");
-		return 0;
-	}
-	savesegment(cs, kernel_cs);
-
-	pv_info.paravirt_enabled = 1;
-	pv_info.kernel_rpl = kernel_cs & SEGMENT_RPL_MASK;
-	pv_info.name = "vmi [deprecated]";
-
-	pv_init_ops.patch = vmi_patch;
-
-	/*
-	 * Many of these operations are ABI compatible with VMI.
-	 * This means we can fill in the paravirt-ops with direct
-	 * pointers into the VMI ROM.  If the calling convention for
-	 * these operations changes, this code needs to be updated.
-	 *
-	 * Exceptions
-	 *  CPUID paravirt-op uses pointers, not the native ISA
-	 *  halt has no VMI equivalent; all VMI halts are "safe"
-	 *  no MSR support yet - just trap and emulate.  VMI uses the
-	 *    same ABI as the native ISA, but Linux wants exceptions
-	 *    from bogus MSR read / write handled
-	 *  rdpmc is not yet used in Linux
-	 */
-
-	/* CPUID is special, so very special it gets wrapped like a present */
-	para_wrap(pv_cpu_ops.cpuid, vmi_cpuid, cpuid, CPUID);
-
-	para_fill(pv_cpu_ops.clts, CLTS);
-	para_fill(pv_cpu_ops.get_debugreg, GetDR);
-	para_fill(pv_cpu_ops.set_debugreg, SetDR);
-	para_fill(pv_cpu_ops.read_cr0, GetCR0);
-	para_fill(pv_mmu_ops.read_cr2, GetCR2);
-	para_fill(pv_mmu_ops.read_cr3, GetCR3);
-	para_fill(pv_cpu_ops.read_cr4, GetCR4);
-	para_fill(pv_cpu_ops.write_cr0, SetCR0);
-	para_fill(pv_mmu_ops.write_cr2, SetCR2);
-	para_fill(pv_mmu_ops.write_cr3, SetCR3);
-	para_fill(pv_cpu_ops.write_cr4, SetCR4);
-
-	para_fill(pv_irq_ops.save_fl.func, GetInterruptMask);
-	para_fill(pv_irq_ops.restore_fl.func, SetInterruptMask);
-	para_fill(pv_irq_ops.irq_disable.func, DisableInterrupts);
-	para_fill(pv_irq_ops.irq_enable.func, EnableInterrupts);
-
-	para_fill(pv_cpu_ops.wbinvd, WBINVD);
-	para_fill(pv_cpu_ops.read_tsc, RDTSC);
-
-	/* The following we emulate with trap and emulate for now */
-	/* paravirt_ops.read_msr = vmi_rdmsr */
-	/* paravirt_ops.write_msr = vmi_wrmsr */
-	/* paravirt_ops.rdpmc = vmi_rdpmc */
-
-	/* TR interface doesn't pass TR value, wrap */
-	para_wrap(pv_cpu_ops.load_tr_desc, vmi_set_tr, set_tr, SetTR);
-
-	/* LDT is special, too */
-	para_wrap(pv_cpu_ops.set_ldt, vmi_set_ldt, _set_ldt, SetLDT);
-
-	para_fill(pv_cpu_ops.load_gdt, SetGDT);
-	para_fill(pv_cpu_ops.load_idt, SetIDT);
-	para_fill(pv_cpu_ops.store_gdt, GetGDT);
-	para_fill(pv_cpu_ops.store_idt, GetIDT);
-	para_fill(pv_cpu_ops.store_tr, GetTR);
-	pv_cpu_ops.load_tls = vmi_load_tls;
-	para_wrap(pv_cpu_ops.write_ldt_entry, vmi_write_ldt_entry,
-		  write_ldt_entry, WriteLDTEntry);
-	para_wrap(pv_cpu_ops.write_gdt_entry, vmi_write_gdt_entry,
-		  write_gdt_entry, WriteGDTEntry);
-	para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
-		  write_idt_entry, WriteIDTEntry);
-	para_wrap(pv_cpu_ops.load_sp0, vmi_load_sp0, set_kernel_stack, UpdateKernelStack);
-	para_fill(pv_cpu_ops.set_iopl_mask, SetIOPLMask);
-	para_fill(pv_cpu_ops.io_delay, IODelay);
-
-	para_wrap(pv_cpu_ops.start_context_switch, vmi_start_context_switch,
-		  set_lazy_mode, SetLazyMode);
-	para_wrap(pv_cpu_ops.end_context_switch, vmi_end_context_switch,
-		  set_lazy_mode, SetLazyMode);
-
-	para_wrap(pv_mmu_ops.lazy_mode.enter, vmi_enter_lazy_mmu,
-		  set_lazy_mode, SetLazyMode);
-	para_wrap(pv_mmu_ops.lazy_mode.leave, vmi_leave_lazy_mmu,
-		  set_lazy_mode, SetLazyMode);
-
-	/* user and kernel flush are just handled with different flags to FlushTLB */
-	para_wrap(pv_mmu_ops.flush_tlb_user, vmi_flush_tlb_user, _flush_tlb, FlushTLB);
-	para_wrap(pv_mmu_ops.flush_tlb_kernel, vmi_flush_tlb_kernel, _flush_tlb, FlushTLB);
-	para_fill(pv_mmu_ops.flush_tlb_single, InvalPage);
-
-	/*
-	 * Until a standard flag format can be agreed on, we need to
-	 * implement these as wrappers in Linux.  Get the VMI ROM
-	 * function pointers for the two backend calls.
-	 */
-#ifdef CONFIG_X86_PAE
-	vmi_ops.set_pte = vmi_get_function(VMI_CALL_SetPxELong);
-	vmi_ops.update_pte = vmi_get_function(VMI_CALL_UpdatePxELong);
-#else
-	vmi_ops.set_pte = vmi_get_function(VMI_CALL_SetPxE);
-	vmi_ops.update_pte = vmi_get_function(VMI_CALL_UpdatePxE);
-#endif
-
-	if (vmi_ops.set_pte) {
-		pv_mmu_ops.set_pte = vmi_set_pte;
-		pv_mmu_ops.set_pte_at = vmi_set_pte_at;
-		pv_mmu_ops.set_pmd = vmi_set_pmd;
-#ifdef CONFIG_X86_PAE
-		pv_mmu_ops.set_pte_atomic = vmi_set_pte_atomic;
-		pv_mmu_ops.set_pud = vmi_set_pud;
-		pv_mmu_ops.pte_clear = vmi_pte_clear;
-		pv_mmu_ops.pmd_clear = vmi_pmd_clear;
-#endif
-	}
-
-	if (vmi_ops.update_pte) {
-		pv_mmu_ops.pte_update = vmi_update_pte;
-		pv_mmu_ops.pte_update_defer = vmi_update_pte_defer;
-	}
-
-	vmi_ops.allocate_page = vmi_get_function(VMI_CALL_AllocatePage);
-	if (vmi_ops.allocate_page) {
-		pv_mmu_ops.alloc_pte = vmi_allocate_pte;
-		pv_mmu_ops.alloc_pmd = vmi_allocate_pmd;
-		pv_mmu_ops.alloc_pmd_clone = vmi_allocate_pmd_clone;
-	}
-
-	vmi_ops.release_page = vmi_get_function(VMI_CALL_ReleasePage);
-	if (vmi_ops.release_page) {
-		pv_mmu_ops.release_pte = vmi_release_pte;
-		pv_mmu_ops.release_pmd = vmi_release_pmd;
-		pv_mmu_ops.pgd_free = vmi_pgd_free;
-	}
-
-	/* Set linear is needed in all cases */
-	vmi_ops.set_linear_mapping = vmi_get_function(VMI_CALL_SetLinearMapping);
-
-	/*
-	 * These MUST always be patched.  Don't support indirect jumps
-	 * through these operations, as the VMI interface may use either
-	 * a jump or a call to get to these operations, depending on
-	 * the backend.  They are performance critical anyway, so requiring
-	 * a patch is not a big problem.
-	 */
-	pv_cpu_ops.irq_enable_sysexit = (void *)0xfeedbab0;
-	pv_cpu_ops.iret = (void *)0xbadbab0;
-
-#ifdef CONFIG_SMP
-	para_wrap(pv_apic_ops.startup_ipi_hook, vmi_startup_ipi_hook, set_initial_ap_state, SetInitialAPState);
-#endif
-
-#ifdef CONFIG_X86_LOCAL_APIC
-       para_fill(apic->read, APICRead);
-       para_fill(apic->write, APICWrite);
-#endif
-
-	/*
-	 * Check for VMI timer functionality by probing for a cycle frequency method
-	 */
-	reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_GetCycleFrequency);
-	if (!disable_vmi_timer && rel->type != VMI_RELOCATION_NONE) {
-		vmi_timer_ops.get_cycle_frequency = (void *)rel->eip;
-		vmi_timer_ops.get_cycle_counter =
-			vmi_get_function(VMI_CALL_GetCycleCounter);
-		vmi_timer_ops.get_wallclock =
-			vmi_get_function(VMI_CALL_GetWallclockTime);
-		vmi_timer_ops.wallclock_updated =
-			vmi_get_function(VMI_CALL_WallclockUpdated);
-		vmi_timer_ops.set_alarm = vmi_get_function(VMI_CALL_SetAlarm);
-		vmi_timer_ops.cancel_alarm =
-			 vmi_get_function(VMI_CALL_CancelAlarm);
-		x86_init.timers.timer_init = vmi_time_init;
-#ifdef CONFIG_X86_LOCAL_APIC
-		x86_init.timers.setup_percpu_clockev = vmi_time_bsp_init;
-		x86_cpuinit.setup_percpu_clockev = vmi_time_ap_init;
-#endif
-		pv_time_ops.sched_clock = vmi_sched_clock;
-		x86_platform.calibrate_tsc = vmi_tsc_khz;
-		x86_platform.get_wallclock = vmi_get_wallclock;
-		x86_platform.set_wallclock = vmi_set_wallclock;
-
-		/* We have true wallclock functions; disable CMOS clock sync */
-		no_sync_cmos_clock = 1;
-	} else {
-		disable_noidle = 1;
-		disable_vmi_timer = 1;
-	}
-
-	para_fill(pv_irq_ops.safe_halt, Halt);
-
-	/*
-	 * Alternative instruction rewriting doesn't happen soon enough
-	 * to convert VMI_IRET to a call instead of a jump; so we have
-	 * to do this before IRQs get reenabled.  Fortunately, it is
-	 * idempotent.
-	 */
-	apply_paravirt(__parainstructions, __parainstructions_end);
-
-	vmi_bringup();
-
-	return 1;
-}
-
-#undef para_fill
-
-void __init vmi_init(void)
-{
-	if (!vmi_rom)
-		probe_vmi_rom();
-	else
-		check_vmi_rom(vmi_rom);
-
-	/* In case probing for or validating the ROM failed, basil */
-	if (!vmi_rom)
-		return;
-
-	reserve_top_address(-vmi_rom->virtual_top);
-
-#ifdef CONFIG_X86_IO_APIC
-	/* This is virtual hardware; timer routing is wired correctly */
-	no_timer_check = 1;
-#endif
-}
-
-void __init vmi_activate(void)
-{
-	unsigned long flags;
-
-	if (!vmi_rom)
-		return;
-
-	local_irq_save(flags);
-	activate_vmi();
-	local_irq_restore(flags & X86_EFLAGS_IF);
-}
-
-static int __init parse_vmi(char *arg)
-{
-	if (!arg)
-		return -EINVAL;
-
-	if (!strcmp(arg, "disable_pge")) {
-		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
-		disable_pge = 1;
-	} else if (!strcmp(arg, "disable_pse")) {
-		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PSE);
-		disable_pse = 1;
-	} else if (!strcmp(arg, "disable_sep")) {
-		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_SEP);
-		disable_sep = 1;
-	} else if (!strcmp(arg, "disable_tsc")) {
-		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC);
-		disable_tsc = 1;
-	} else if (!strcmp(arg, "disable_mtrr")) {
-		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_MTRR);
-		disable_mtrr = 1;
-	} else if (!strcmp(arg, "disable_timer")) {
-		disable_vmi_timer = 1;
-		disable_noidle = 1;
-	} else if (!strcmp(arg, "disable_noidle"))
-		disable_noidle = 1;
-	return 0;
-}
-
-early_param("vmi", parse_vmi);
diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c
deleted file mode 100644
index 5e1ff66..0000000
--- a/arch/x86/kernel/vmiclock_32.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * VMI paravirtual timer support routines.
- *
- * Copyright (C) 2007, VMware, 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/cpumask.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-
-#include <asm/vmi.h>
-#include <asm/vmi_time.h>
-#include <asm/apicdef.h>
-#include <asm/apic.h>
-#include <asm/timer.h>
-#include <asm/i8253.h>
-#include <asm/irq_vectors.h>
-
-#define VMI_ONESHOT  (VMI_ALARM_IS_ONESHOT  | VMI_CYCLES_REAL | vmi_get_alarm_wiring())
-#define VMI_PERIODIC (VMI_ALARM_IS_PERIODIC | VMI_CYCLES_REAL | vmi_get_alarm_wiring())
-
-static DEFINE_PER_CPU(struct clock_event_device, local_events);
-
-static inline u32 vmi_counter(u32 flags)
-{
-	/* Given VMI_ONESHOT or VMI_PERIODIC, return the corresponding
-	 * cycle counter. */
-	return flags & VMI_ALARM_COUNTER_MASK;
-}
-
-/* paravirt_ops.get_wallclock = vmi_get_wallclock */
-unsigned long vmi_get_wallclock(void)
-{
-	unsigned long long wallclock;
-	wallclock = vmi_timer_ops.get_wallclock(); // nsec
-	(void)do_div(wallclock, 1000000000);       // sec
-
-	return wallclock;
-}
-
-/* paravirt_ops.set_wallclock = vmi_set_wallclock */
-int vmi_set_wallclock(unsigned long now)
-{
-	return 0;
-}
-
-/* paravirt_ops.sched_clock = vmi_sched_clock */
-unsigned long long vmi_sched_clock(void)
-{
-	return cycles_2_ns(vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE));
-}
-
-/* x86_platform.calibrate_tsc = vmi_tsc_khz */
-unsigned long vmi_tsc_khz(void)
-{
-	unsigned long long khz;
-	khz = vmi_timer_ops.get_cycle_frequency();
-	(void)do_div(khz, 1000);
-	return khz;
-}
-
-static inline unsigned int vmi_get_timer_vector(void)
-{
-	return IRQ0_VECTOR;
-}
-
-/** vmi clockchip */
-#ifdef CONFIG_X86_LOCAL_APIC
-static unsigned int startup_timer_irq(unsigned int irq)
-{
-	unsigned long val = apic_read(APIC_LVTT);
-	apic_write(APIC_LVTT, vmi_get_timer_vector());
-
-	return (val & APIC_SEND_PENDING);
-}
-
-static void mask_timer_irq(unsigned int irq)
-{
-	unsigned long val = apic_read(APIC_LVTT);
-	apic_write(APIC_LVTT, val | APIC_LVT_MASKED);
-}
-
-static void unmask_timer_irq(unsigned int irq)
-{
-	unsigned long val = apic_read(APIC_LVTT);
-	apic_write(APIC_LVTT, val & ~APIC_LVT_MASKED);
-}
-
-static void ack_timer_irq(unsigned int irq)
-{
-	ack_APIC_irq();
-}
-
-static struct irq_chip vmi_chip __read_mostly = {
-	.name 		= "VMI-LOCAL",
-	.startup 	= startup_timer_irq,
-	.mask	 	= mask_timer_irq,
-	.unmask	 	= unmask_timer_irq,
-	.ack 		= ack_timer_irq
-};
-#endif
-
-/** vmi clockevent */
-#define VMI_ALARM_WIRED_IRQ0    0x00000000
-#define VMI_ALARM_WIRED_LVTT    0x00010000
-static int vmi_wiring = VMI_ALARM_WIRED_IRQ0;
-
-static inline int vmi_get_alarm_wiring(void)
-{
-	return vmi_wiring;
-}
-
-static void vmi_timer_set_mode(enum clock_event_mode mode,
-			       struct clock_event_device *evt)
-{
-	cycle_t now, cycles_per_hz;
-	BUG_ON(!irqs_disabled());
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_ONESHOT:
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	case CLOCK_EVT_MODE_PERIODIC:
-		cycles_per_hz = vmi_timer_ops.get_cycle_frequency();
-		(void)do_div(cycles_per_hz, HZ);
-		now = vmi_timer_ops.get_cycle_counter(vmi_counter(VMI_PERIODIC));
-		vmi_timer_ops.set_alarm(VMI_PERIODIC, now, cycles_per_hz);
-		break;
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-		switch (evt->mode) {
-		case CLOCK_EVT_MODE_ONESHOT:
-			vmi_timer_ops.cancel_alarm(VMI_ONESHOT);
-			break;
-		case CLOCK_EVT_MODE_PERIODIC:
-			vmi_timer_ops.cancel_alarm(VMI_PERIODIC);
-			break;
-		default:
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static int vmi_timer_next_event(unsigned long delta,
-				struct clock_event_device *evt)
-{
-	/* Unfortunately, set_next_event interface only passes relative
-	 * expiry, but we want absolute expiry.  It'd be better if were
-	 * were passed an absolute expiry, since a bunch of time may
-	 * have been stolen between the time the delta is computed and
-	 * when we set the alarm below. */
-	cycle_t now = vmi_timer_ops.get_cycle_counter(vmi_counter(VMI_ONESHOT));
-
-	BUG_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
-	vmi_timer_ops.set_alarm(VMI_ONESHOT, now + delta, 0);
-	return 0;
-}
-
-static struct clock_event_device vmi_clockevent = {
-	.name		= "vmi-timer",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.shift		= 22,
-	.set_mode	= vmi_timer_set_mode,
-	.set_next_event = vmi_timer_next_event,
-	.rating         = 1000,
-	.irq		= 0,
-};
-
-static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = &__get_cpu_var(local_events);
-	evt->event_handler(evt);
-	return IRQ_HANDLED;
-}
-
-static struct irqaction vmi_clock_action  = {
-	.name 		= "vmi-timer",
-	.handler 	= vmi_timer_interrupt,
-	.flags 		= IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
-};
-
-static void __devinit vmi_time_init_clockevent(void)
-{
-	cycle_t cycles_per_msec;
-	struct clock_event_device *evt;
-
-	int cpu = smp_processor_id();
-	evt = &__get_cpu_var(local_events);
-
-	/* Use cycles_per_msec since div_sc params are 32-bits. */
-	cycles_per_msec = vmi_timer_ops.get_cycle_frequency();
-	(void)do_div(cycles_per_msec, 1000);
-
-	memcpy(evt, &vmi_clockevent, sizeof(*evt));
-	/* Must pick .shift such that .mult fits in 32-bits.  Choosing
-	 * .shift to be 22 allows 2^(32-22) cycles per nano-seconds
-	 * before overflow. */
-	evt->mult = div_sc(cycles_per_msec, NSEC_PER_MSEC, evt->shift);
-	/* Upper bound is clockevent's use of ulong for cycle deltas. */
-	evt->max_delta_ns = clockevent_delta2ns(ULONG_MAX, evt);
-	evt->min_delta_ns = clockevent_delta2ns(1, evt);
-	evt->cpumask = cpumask_of(cpu);
-
-	printk(KERN_WARNING "vmi: registering clock event %s. mult=%u shift=%u\n",
-	       evt->name, evt->mult, evt->shift);
-	clockevents_register_device(evt);
-}
-
-void __init vmi_time_init(void)
-{
-	unsigned int cpu;
-	/* Disable PIT: BIOSes start PIT CH0 with 18.2hz peridic. */
-	outb_pit(0x3a, PIT_MODE); /* binary, mode 5, LSB/MSB, ch 0 */
-
-	vmi_time_init_clockevent();
-	setup_irq(0, &vmi_clock_action);
-	for_each_possible_cpu(cpu)
-		per_cpu(vector_irq, cpu)[vmi_get_timer_vector()] = 0;
-}
-
-#ifdef CONFIG_X86_LOCAL_APIC
-void __devinit vmi_time_bsp_init(void)
-{
-	/*
-	 * On APIC systems, we want local timers to fire on each cpu.  We do
-	 * this by programming LVTT to deliver timer events to the IRQ handler
-	 * for IRQ-0, since we can't re-use the APIC local timer handler
-	 * without interfering with that code.
-	 */
-	clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
-	local_irq_disable();
-#ifdef CONFIG_SMP
-	/*
-	 * XXX handle_percpu_irq only defined for SMP; we need to switch over
-	 * to using it, since this is a local interrupt, which each CPU must
-	 * handle individually without locking out or dropping simultaneous
-	 * local timers on other CPUs.  We also don't want to trigger the
-	 * quirk workaround code for interrupts which gets invoked from
-	 * handle_percpu_irq via eoi, so we use our own IRQ chip.
-	 */
-	set_irq_chip_and_handler_name(0, &vmi_chip, handle_percpu_irq, "lvtt");
-#else
-	set_irq_chip_and_handler_name(0, &vmi_chip, handle_edge_irq, "lvtt");
-#endif
-	vmi_wiring = VMI_ALARM_WIRED_LVTT;
-	apic_write(APIC_LVTT, vmi_get_timer_vector());
-	local_irq_enable();
-	clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
-}
-
-void __devinit vmi_time_ap_init(void)
-{
-	vmi_time_init_clockevent();
-	apic_write(APIC_LVTT, vmi_get_timer_vector());
-}
-#endif
-
-/** vmi clocksource */
-static struct clocksource clocksource_vmi;
-
-static cycle_t read_real_cycles(struct clocksource *cs)
-{
-	cycle_t ret = (cycle_t)vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
-	return max(ret, clocksource_vmi.cycle_last);
-}
-
-static struct clocksource clocksource_vmi = {
-	.name			= "vmi-timer",
-	.rating			= 450,
-	.read			= read_real_cycles,
-	.mask			= CLOCKSOURCE_MASK(64),
-	.mult			= 0, /* to be set */
-	.shift			= 22,
-	.flags			= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int __init init_vmi_clocksource(void)
-{
-	cycle_t cycles_per_msec;
-
-	if (!vmi_timer_ops.get_cycle_frequency)
-		return 0;
-	/* Use khz2mult rather than hz2mult since hz arg is only 32-bits. */
-	cycles_per_msec = vmi_timer_ops.get_cycle_frequency();
-	(void)do_div(cycles_per_msec, 1000);
-
-	/* Note that clocksource.{mult, shift} converts in the opposite direction
-	 * as clockevents.  */
-	clocksource_vmi.mult = clocksource_khz2mult(cycles_per_msec,
-						    clocksource_vmi.shift);
-
-	printk(KERN_WARNING "vmi: registering clock source khz=%lld\n", cycles_per_msec);
-	return clocksource_register(&clocksource_vmi);
-
-}
-module_init(init_vmi_clocksource);
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index d0bb522..e03530a 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -242,6 +242,12 @@
 		__x86_cpu_dev_end = .;
 	}
 
+	/*
+	 * start address and size of operations which during runtime
+	 * can be patched with virtualization friendly instructions or
+	 * baremetal native ones. Think page table operations.
+	 * Details in paravirt_types.h
+	 */
 	. = ALIGN(8);
 	.parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
 		__parainstructions = .;
@@ -249,6 +255,11 @@
 		__parainstructions_end = .;
 	}
 
+	/*
+	 * struct alt_inst entries. From the header (alternative.h):
+	 * "Alternative instructions for different CPU types or capabilities"
+	 * Think locking instructions on spinlocks.
+	 */
 	. = ALIGN(8);
 	.altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
 		__alt_instructions = .;
@@ -256,11 +267,28 @@
 		__alt_instructions_end = .;
 	}
 
+	/*
+	 * And here are the replacement instructions. The linker sticks
+	 * them as binary blobs. The .altinstructions has enough data to
+	 * get the address and the length of them to patch the kernel safely.
+	 */
 	.altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
 		*(.altinstr_replacement)
 	}
 
 	/*
+	 * struct iommu_table_entry entries are injected in this section.
+	 * It is an array of IOMMUs which during run time gets sorted depending
+	 * on its dependency order. After rootfs_initcall is complete
+	 * this section can be safely removed.
+	 */
+	.iommu_table : AT(ADDR(.iommu_table) - LOAD_OFFSET) {
+		__iommu_table = .;
+		*(.iommu_table)
+		__iommu_table_end = .;
+	}
+	. = ALIGN(8);
+	/*
 	 * .exit.text is discard at runtime, not link time, to deal with
 	 *  references from .altinstructions and .eh_frame
 	 */
@@ -273,7 +301,7 @@
 	}
 
 #if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP)
-	PERCPU(PAGE_SIZE)
+	PERCPU(THREAD_SIZE)
 #endif
 
 	. = ALIGN(PAGE_SIZE);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 77d8c0f..22b06f7 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1056,14 +1056,13 @@
 
 	vcpu->arch.apic = apic;
 
-	apic->regs_page = alloc_page(GFP_KERNEL);
+	apic->regs_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
 	if (apic->regs_page == NULL) {
 		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);
-	memset(apic->regs, 0, PAGE_SIZE);
 	apic->vcpu = vcpu;
 
 	hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index bc5b9b8..8a3f9f6 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -766,7 +766,6 @@
 
 	control->iopm_base_pa = iopm_base;
 	control->msrpm_base_pa = __pa(svm->msrpm);
-	control->tsc_offset = 0;
 	control->int_ctl = V_INTR_MASKING_MASK;
 
 	init_seg(&save->es);
@@ -902,6 +901,7 @@
 	svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
 	svm->asid_generation = 0;
 	init_vmcb(svm);
+	svm->vmcb->control.tsc_offset = 0-native_read_tsc();
 
 	err = fx_init(&svm->vcpu);
 	if (err)
@@ -3163,8 +3163,8 @@
 	sync_lapic_to_cr8(vcpu);
 
 	save_host_msrs(vcpu);
-	fs_selector = kvm_read_fs();
-	gs_selector = kvm_read_gs();
+	savesegment(fs, fs_selector);
+	savesegment(gs, gs_selector);
 	ldt_selector = kvm_read_ldt();
 	svm->vmcb->save.cr2 = vcpu->arch.cr2;
 	/* required for live migration with NPT */
@@ -3251,10 +3251,15 @@
 	vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
 	vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
-	kvm_load_fs(fs_selector);
-	kvm_load_gs(gs_selector);
-	kvm_load_ldt(ldt_selector);
 	load_host_msrs(vcpu);
+	loadsegment(fs, fs_selector);
+#ifdef CONFIG_X86_64
+	load_gs_index(gs_selector);
+	wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
+#else
+	loadsegment(gs, gs_selector);
+#endif
+	kvm_load_ldt(ldt_selector);
 
 	reload_tss(vcpu);
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 49b25ee..7bddfab 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -803,7 +803,7 @@
 	 */
 	vmx->host_state.ldt_sel = kvm_read_ldt();
 	vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel;
-	vmx->host_state.fs_sel = kvm_read_fs();
+	savesegment(fs, vmx->host_state.fs_sel);
 	if (!(vmx->host_state.fs_sel & 7)) {
 		vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel);
 		vmx->host_state.fs_reload_needed = 0;
@@ -811,7 +811,7 @@
 		vmcs_write16(HOST_FS_SELECTOR, 0);
 		vmx->host_state.fs_reload_needed = 1;
 	}
-	vmx->host_state.gs_sel = kvm_read_gs();
+	savesegment(gs, vmx->host_state.gs_sel);
 	if (!(vmx->host_state.gs_sel & 7))
 		vmcs_write16(HOST_GS_SELECTOR, vmx->host_state.gs_sel);
 	else {
@@ -841,27 +841,21 @@
 
 static void __vmx_load_host_state(struct vcpu_vmx *vmx)
 {
-	unsigned long flags;
-
 	if (!vmx->host_state.loaded)
 		return;
 
 	++vmx->vcpu.stat.host_state_reload;
 	vmx->host_state.loaded = 0;
 	if (vmx->host_state.fs_reload_needed)
-		kvm_load_fs(vmx->host_state.fs_sel);
+		loadsegment(fs, vmx->host_state.fs_sel);
 	if (vmx->host_state.gs_ldt_reload_needed) {
 		kvm_load_ldt(vmx->host_state.ldt_sel);
-		/*
-		 * If we have to reload gs, we must take care to
-		 * preserve our gs base.
-		 */
-		local_irq_save(flags);
-		kvm_load_gs(vmx->host_state.gs_sel);
 #ifdef CONFIG_X86_64
-		wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
+		load_gs_index(vmx->host_state.gs_sel);
+		wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
+#else
+		loadsegment(gs, vmx->host_state.gs_sel);
 #endif
-		local_irq_restore(flags);
 	}
 	reload_tss();
 #ifdef CONFIG_X86_64
@@ -2589,8 +2583,8 @@
 	vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS);  /* 22.2.4 */
 	vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
 	vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
-	vmcs_write16(HOST_FS_SELECTOR, kvm_read_fs());    /* 22.2.4 */
-	vmcs_write16(HOST_GS_SELECTOR, kvm_read_gs());    /* 22.2.4 */
+	vmcs_write16(HOST_FS_SELECTOR, 0);            /* 22.2.4 */
+	vmcs_write16(HOST_GS_SELECTOR, 0);            /* 22.2.4 */
 	vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
 #ifdef CONFIG_X86_64
 	rdmsrl(MSR_FS_BASE, a);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 3a09c62..6c2ecf0 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1991,13 +1991,14 @@
 		0 /* Reserved */ | F(CX16) | 0 /* xTPR Update, PDCM */ |
 		0 /* Reserved, DCA */ | F(XMM4_1) |
 		F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) |
-		0 /* Reserved, AES */ | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX);
+		0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) |
+		F(F16C);
 	/* cpuid 0x80000001.ecx */
 	const u32 kvm_supported_word6_x86_features =
 		F(LAHF_LM) | F(CMP_LEGACY) | F(SVM) | 0 /* ExtApicSpace */ |
 		F(CR8_LEGACY) | F(ABM) | F(SSE4A) | F(MISALIGNSSE) |
-		F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(SSE5) |
-		0 /* SKINIT */ | 0 /* WDT */;
+		F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(XOP) |
+		0 /* SKINIT, WDT, LWP */ | F(FMA4) | F(TBM);
 
 	/* all calls to cpuid_count() should be made on the same cpu */
 	get_cpu();
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 9d5f558..73b1e1a 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -791,22 +791,22 @@
  * simple as setting a bit.  We don't actually "ack" interrupts as such, we
  * just mask and unmask them.  I wonder if we should be cleverer?
  */
-static void disable_lguest_irq(unsigned int irq)
+static void disable_lguest_irq(struct irq_data *data)
 {
-	set_bit(irq, lguest_data.blocked_interrupts);
+	set_bit(data->irq, lguest_data.blocked_interrupts);
 }
 
-static void enable_lguest_irq(unsigned int irq)
+static void enable_lguest_irq(struct irq_data *data)
 {
-	clear_bit(irq, lguest_data.blocked_interrupts);
+	clear_bit(data->irq, lguest_data.blocked_interrupts);
 }
 
 /* This structure describes the lguest IRQ controller. */
 static struct irq_chip lguest_irq_controller = {
 	.name		= "lguest",
-	.mask		= disable_lguest_irq,
-	.mask_ack	= disable_lguest_irq,
-	.unmask		= enable_lguest_irq,
+	.irq_mask	= disable_lguest_irq,
+	.irq_mask_ack	= disable_lguest_irq,
+	.irq_unmask	= enable_lguest_irq,
 };
 
 /*
@@ -838,12 +838,12 @@
  * rather than set them in lguest_init_IRQ we are called here every time an
  * lguest device needs an interrupt.
  *
- * FIXME: irq_to_desc_alloc_node() can fail due to lack of memory, we should
+ * FIXME: irq_alloc_desc_at() can fail due to lack of memory, we should
  * pass that up!
  */
 void lguest_setup_irq(unsigned int irq)
 {
-	irq_to_desc_alloc_node(irq, 0);
+	irq_alloc_desc_at(irq, 0);
 	set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
 				      handle_level_irq, "level");
 }
diff --git a/arch/x86/lib/memcpy_32.c b/arch/x86/lib/memcpy_32.c
index 5415a9d..b908a59 100644
--- a/arch/x86/lib/memcpy_32.c
+++ b/arch/x86/lib/memcpy_32.c
@@ -22,22 +22,187 @@
 
 void *memmove(void *dest, const void *src, size_t n)
 {
-	int d0, d1, d2;
+	int d0,d1,d2,d3,d4,d5;
+	char *ret = dest;
 
-	if (dest < src) {
-		memcpy(dest, src, n);
-	} else {
-		__asm__ __volatile__(
-			"std\n\t"
-			"rep\n\t"
-			"movsb\n\t"
-			"cld"
-			: "=&c" (d0), "=&S" (d1), "=&D" (d2)
-			:"0" (n),
-			 "1" (n-1+src),
-			 "2" (n-1+dest)
-			:"memory");
-	}
-	return dest;
+	__asm__ __volatile__(
+		/* Handle more 16bytes in loop */
+		"cmp $0x10, %0\n\t"
+		"jb	1f\n\t"
+
+		/* Decide forward/backward copy mode */
+		"cmp %2, %1\n\t"
+		"jb	2f\n\t"
+
+		/*
+		 * movs instruction have many startup latency
+		 * so we handle small size by general register.
+		 */
+		"cmp  $680, %0\n\t"
+		"jb 3f\n\t"
+		/*
+		 * movs instruction is only good for aligned case.
+		 */
+		"mov %1, %3\n\t"
+		"xor %2, %3\n\t"
+		"and $0xff, %3\n\t"
+		"jz 4f\n\t"
+		"3:\n\t"
+		"sub $0x10, %0\n\t"
+
+		/*
+		 * We gobble 16byts forward in each loop.
+		 */
+		"3:\n\t"
+		"sub $0x10, %0\n\t"
+		"mov 0*4(%1), %3\n\t"
+		"mov 1*4(%1), %4\n\t"
+		"mov  %3, 0*4(%2)\n\t"
+		"mov  %4, 1*4(%2)\n\t"
+		"mov 2*4(%1), %3\n\t"
+		"mov 3*4(%1), %4\n\t"
+		"mov  %3, 2*4(%2)\n\t"
+		"mov  %4, 3*4(%2)\n\t"
+		"lea  0x10(%1), %1\n\t"
+		"lea  0x10(%2), %2\n\t"
+		"jae 3b\n\t"
+		"add $0x10, %0\n\t"
+		"jmp 1f\n\t"
+
+		/*
+		 * Handle data forward by movs.
+		 */
+		".p2align 4\n\t"
+		"4:\n\t"
+		"mov -4(%1, %0), %3\n\t"
+		"lea -4(%2, %0), %4\n\t"
+		"shr $2, %0\n\t"
+		"rep movsl\n\t"
+		"mov %3, (%4)\n\t"
+		"jmp 11f\n\t"
+		/*
+		 * Handle data backward by movs.
+		 */
+		".p2align 4\n\t"
+		"6:\n\t"
+		"mov (%1), %3\n\t"
+		"mov %2, %4\n\t"
+		"lea -4(%1, %0), %1\n\t"
+		"lea -4(%2, %0), %2\n\t"
+		"shr $2, %0\n\t"
+		"std\n\t"
+		"rep movsl\n\t"
+		"mov %3,(%4)\n\t"
+		"cld\n\t"
+		"jmp 11f\n\t"
+
+		/*
+		 * Start to prepare for backward copy.
+		 */
+		".p2align 4\n\t"
+		"2:\n\t"
+		"cmp  $680, %0\n\t"
+		"jb 5f\n\t"
+		"mov %1, %3\n\t"
+		"xor %2, %3\n\t"
+		"and $0xff, %3\n\t"
+		"jz 6b\n\t"
+
+		/*
+		 * Calculate copy position to tail.
+		 */
+		"5:\n\t"
+		"add %0, %1\n\t"
+		"add %0, %2\n\t"
+		"sub $0x10, %0\n\t"
+
+		/*
+		 * We gobble 16byts backward in each loop.
+		 */
+		"7:\n\t"
+		"sub $0x10, %0\n\t"
+
+		"mov -1*4(%1), %3\n\t"
+		"mov -2*4(%1), %4\n\t"
+		"mov  %3, -1*4(%2)\n\t"
+		"mov  %4, -2*4(%2)\n\t"
+		"mov -3*4(%1), %3\n\t"
+		"mov -4*4(%1), %4\n\t"
+		"mov  %3, -3*4(%2)\n\t"
+		"mov  %4, -4*4(%2)\n\t"
+		"lea  -0x10(%1), %1\n\t"
+		"lea  -0x10(%2), %2\n\t"
+		"jae 7b\n\t"
+		/*
+		 * Calculate copy position to head.
+		 */
+		"add $0x10, %0\n\t"
+		"sub %0, %1\n\t"
+		"sub %0, %2\n\t"
+
+		/*
+		 * Move data from 8 bytes to 15 bytes.
+		 */
+		".p2align 4\n\t"
+		"1:\n\t"
+		"cmp $8, %0\n\t"
+		"jb 8f\n\t"
+		"mov 0*4(%1), %3\n\t"
+		"mov 1*4(%1), %4\n\t"
+		"mov -2*4(%1, %0), %5\n\t"
+		"mov -1*4(%1, %0), %1\n\t"
+
+		"mov  %3, 0*4(%2)\n\t"
+		"mov  %4, 1*4(%2)\n\t"
+		"mov  %5, -2*4(%2, %0)\n\t"
+		"mov  %1, -1*4(%2, %0)\n\t"
+		"jmp 11f\n\t"
+
+		/*
+		 * Move data from 4 bytes to 7 bytes.
+		 */
+		".p2align 4\n\t"
+		"8:\n\t"
+		"cmp $4, %0\n\t"
+		"jb 9f\n\t"
+		"mov 0*4(%1), %3\n\t"
+		"mov -1*4(%1, %0), %4\n\t"
+		"mov  %3, 0*4(%2)\n\t"
+		"mov  %4, -1*4(%2, %0)\n\t"
+		"jmp 11f\n\t"
+
+		/*
+		 * Move data from 2 bytes to 3 bytes.
+		 */
+		".p2align 4\n\t"
+		"9:\n\t"
+		"cmp $2, %0\n\t"
+		"jb 10f\n\t"
+		"movw 0*2(%1), %%dx\n\t"
+		"movw -1*2(%1, %0), %%bx\n\t"
+		"movw %%dx, 0*2(%2)\n\t"
+		"movw %%bx, -1*2(%2, %0)\n\t"
+		"jmp 11f\n\t"
+
+		/*
+		 * Move data for 1 byte.
+		 */
+		".p2align 4\n\t"
+		"10:\n\t"
+		"cmp $1, %0\n\t"
+		"jb 11f\n\t"
+		"movb (%1), %%cl\n\t"
+		"movb %%cl, (%2)\n\t"
+		".p2align 4\n\t"
+		"11:"
+		: "=&c" (d0), "=&S" (d1), "=&D" (d2),
+		  "=r" (d3),"=r" (d4), "=r"(d5)
+		:"0" (n),
+		 "1" (src),
+		 "2" (dest)
+		:"memory");
+
+	return ret;
+
 }
 EXPORT_SYMBOL(memmove);
diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S
index bcbcd1e..75ef61e 100644
--- a/arch/x86/lib/memcpy_64.S
+++ b/arch/x86/lib/memcpy_64.S
@@ -40,84 +40,132 @@
 ENTRY(__memcpy)
 ENTRY(memcpy)
 	CFI_STARTPROC
-
-	/*
-	 * Put the number of full 64-byte blocks into %ecx.
-	 * Tail portion is handled at the end:
-	 */
 	movq %rdi, %rax
-	movl %edx, %ecx
-	shrl   $6, %ecx
-	jz .Lhandle_tail
 
+	/*
+	 * Use 32bit CMP here to avoid long NOP padding.
+	 */
+	cmp  $0x20, %edx
+	jb .Lhandle_tail
+
+	/*
+	 * We check whether memory false dependece could occur,
+	 * then jump to corresponding copy mode.
+	 */
+	cmp  %dil, %sil
+	jl .Lcopy_backward
+	subl $0x20, %edx
+.Lcopy_forward_loop:
+	subq $0x20,	%rdx
+
+	/*
+	 * Move in blocks of 4x8 bytes:
+	 */
+	movq 0*8(%rsi),	%r8
+	movq 1*8(%rsi),	%r9
+	movq 2*8(%rsi),	%r10
+	movq 3*8(%rsi),	%r11
+	leaq 4*8(%rsi),	%rsi
+
+	movq %r8,	0*8(%rdi)
+	movq %r9,	1*8(%rdi)
+	movq %r10,	2*8(%rdi)
+	movq %r11,	3*8(%rdi)
+	leaq 4*8(%rdi),	%rdi
+	jae  .Lcopy_forward_loop
+	addq $0x20,	%rdx
+	jmp  .Lhandle_tail
+
+.Lcopy_backward:
+	/*
+	 * Calculate copy position to tail.
+	 */
+	addq %rdx,	%rsi
+	addq %rdx,	%rdi
+	subq $0x20,	%rdx
+	/*
+	 * At most 3 ALU operations in one cycle,
+	 * so append NOPS in the same 16bytes trunk.
+	 */
 	.p2align 4
-.Lloop_64:
-	/*
-	 * We decrement the loop index here - and the zero-flag is
-	 * checked at the end of the loop (instructions inbetween do
-	 * not change the zero flag):
-	 */
-	decl %ecx
+.Lcopy_backward_loop:
+	subq $0x20,	%rdx
+	movq -1*8(%rsi),	%r8
+	movq -2*8(%rsi),	%r9
+	movq -3*8(%rsi),	%r10
+	movq -4*8(%rsi),	%r11
+	leaq -4*8(%rsi),	%rsi
+	movq %r8,		-1*8(%rdi)
+	movq %r9,		-2*8(%rdi)
+	movq %r10,		-3*8(%rdi)
+	movq %r11,		-4*8(%rdi)
+	leaq -4*8(%rdi),	%rdi
+	jae  .Lcopy_backward_loop
 
 	/*
-	 * Move in blocks of 4x16 bytes:
+	 * Calculate copy position to head.
 	 */
-	movq 0*8(%rsi),		%r11
-	movq 1*8(%rsi),		%r8
-	movq %r11,		0*8(%rdi)
-	movq %r8,		1*8(%rdi)
-
-	movq 2*8(%rsi),		%r9
-	movq 3*8(%rsi),		%r10
-	movq %r9,		2*8(%rdi)
-	movq %r10,		3*8(%rdi)
-
-	movq 4*8(%rsi),		%r11
-	movq 5*8(%rsi),		%r8
-	movq %r11,		4*8(%rdi)
-	movq %r8,		5*8(%rdi)
-
-	movq 6*8(%rsi),		%r9
-	movq 7*8(%rsi),		%r10
-	movq %r9,		6*8(%rdi)
-	movq %r10,		7*8(%rdi)
-
-	leaq 64(%rsi), %rsi
-	leaq 64(%rdi), %rdi
-
-	jnz  .Lloop_64
-
+	addq $0x20,	%rdx
+	subq %rdx,	%rsi
+	subq %rdx,	%rdi
 .Lhandle_tail:
-	movl %edx, %ecx
-	andl  $63, %ecx
-	shrl   $3, %ecx
-	jz   .Lhandle_7
+	cmpq $16,	%rdx
+	jb   .Lless_16bytes
 
+	/*
+	 * Move data from 16 bytes to 31 bytes.
+	 */
+	movq 0*8(%rsi), %r8
+	movq 1*8(%rsi),	%r9
+	movq -2*8(%rsi, %rdx),	%r10
+	movq -1*8(%rsi, %rdx),	%r11
+	movq %r8,	0*8(%rdi)
+	movq %r9,	1*8(%rdi)
+	movq %r10,	-2*8(%rdi, %rdx)
+	movq %r11,	-1*8(%rdi, %rdx)
+	retq
 	.p2align 4
-.Lloop_8:
-	decl %ecx
-	movq (%rsi),		%r8
-	movq %r8,		(%rdi)
-	leaq 8(%rdi),		%rdi
-	leaq 8(%rsi),		%rsi
-	jnz  .Lloop_8
-
-.Lhandle_7:
-	movl %edx, %ecx
-	andl $7, %ecx
-	jz .Lend
-
+.Lless_16bytes:
+	cmpq $8,	%rdx
+	jb   .Lless_8bytes
+	/*
+	 * Move data from 8 bytes to 15 bytes.
+	 */
+	movq 0*8(%rsi),	%r8
+	movq -1*8(%rsi, %rdx),	%r9
+	movq %r8,	0*8(%rdi)
+	movq %r9,	-1*8(%rdi, %rdx)
+	retq
 	.p2align 4
+.Lless_8bytes:
+	cmpq $4,	%rdx
+	jb   .Lless_3bytes
+
+	/*
+	 * Move data from 4 bytes to 7 bytes.
+	 */
+	movl (%rsi), %ecx
+	movl -4(%rsi, %rdx), %r8d
+	movl %ecx, (%rdi)
+	movl %r8d, -4(%rdi, %rdx)
+	retq
+	.p2align 4
+.Lless_3bytes:
+	cmpl $0, %edx
+	je .Lend
+	/*
+	 * Move data from 1 bytes to 3 bytes.
+	 */
 .Lloop_1:
 	movb (%rsi), %r8b
 	movb %r8b, (%rdi)
 	incq %rdi
 	incq %rsi
-	decl %ecx
+	decl %edx
 	jnz .Lloop_1
 
 .Lend:
-	ret
+	retq
 	CFI_ENDPROC
 ENDPROC(memcpy)
 ENDPROC(__memcpy)
diff --git a/arch/x86/lib/memmove_64.c b/arch/x86/lib/memmove_64.c
index 0a33909..6d0f0ec 100644
--- a/arch/x86/lib/memmove_64.c
+++ b/arch/x86/lib/memmove_64.c
@@ -8,14 +8,185 @@
 #undef memmove
 void *memmove(void *dest, const void *src, size_t count)
 {
-	if (dest < src) {
-		return memcpy(dest, src, count);
-	} else {
-		char *p = dest + count;
-		const char *s = src + count;
-		while (count--)
-			*--p = *--s;
-	}
-	return dest;
+	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/mm/Makefile b/arch/x86/mm/Makefile
index a4c7683..5554339 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -26,4 +26,6 @@
 obj-$(CONFIG_K8_NUMA)		+= k8topology_64.o
 obj-$(CONFIG_ACPI_NUMA)		+= srat_$(BITS).o
 
+obj-$(CONFIG_HAVE_MEMBLOCK)		+= memblock.o
+
 obj-$(CONFIG_MEMTEST)		+= memtest.o
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 4c4508e..79b0b37 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -229,7 +229,16 @@
 
 		spin_lock_irqsave(&pgd_lock, flags);
 		list_for_each_entry(page, &pgd_list, lru) {
-			if (!vmalloc_sync_one(page_address(page), address))
+			spinlock_t *pgt_lock;
+			pmd_t *ret;
+
+			pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
+
+			spin_lock(pgt_lock);
+			ret = vmalloc_sync_one(page_address(page), address);
+			spin_unlock(pgt_lock);
+
+			if (!ret)
 				break;
 		}
 		spin_unlock_irqrestore(&pgd_lock, flags);
@@ -251,6 +260,8 @@
 	if (!(address >= VMALLOC_START && address < VMALLOC_END))
 		return -1;
 
+	WARN_ON_ONCE(in_nmi());
+
 	/*
 	 * Synchronize this task's top level page-table
 	 * with the 'reference' page table.
@@ -326,29 +337,7 @@
 
 void vmalloc_sync_all(void)
 {
-	unsigned long address;
-
-	for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
-	     address += PGDIR_SIZE) {
-
-		const pgd_t *pgd_ref = pgd_offset_k(address);
-		unsigned long flags;
-		struct page *page;
-
-		if (pgd_none(*pgd_ref))
-			continue;
-
-		spin_lock_irqsave(&pgd_lock, flags);
-		list_for_each_entry(page, &pgd_list, lru) {
-			pgd_t *pgd;
-			pgd = (pgd_t *)page_address(page) + pgd_index(address);
-			if (pgd_none(*pgd))
-				set_pgd(pgd, *pgd_ref);
-			else
-				BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
-		}
-		spin_unlock_irqrestore(&pgd_lock, flags);
-	}
+	sync_global_pgds(VMALLOC_START & PGDIR_MASK, VMALLOC_END);
 }
 
 /*
@@ -369,6 +358,8 @@
 	if (!(address >= VMALLOC_START && address < VMALLOC_END))
 		return -1;
 
+	WARN_ON_ONCE(in_nmi());
+
 	/*
 	 * Copy kernel mappings over when needed. This can also
 	 * happen within a race in page table update. In the later
@@ -894,8 +885,14 @@
 	if (pmd_large(*pmd))
 		return spurious_fault_check(error_code, (pte_t *) pmd);
 
+	/*
+	 * Note: don't use pte_present() here, since it returns true
+	 * if the _PAGE_PROTNONE bit is set.  However, this aliases the
+	 * _PAGE_GLOBAL bit, which for kernel pages give false positives
+	 * when CONFIG_DEBUG_PAGEALLOC is used.
+	 */
 	pte = pte_offset_kernel(pmd, address);
-	if (!pte_present(*pte))
+	if (!(pte_flags(*pte) & _PAGE_PRESENT))
 		return 0;
 
 	ret = spurious_fault_check(error_code, pte);
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index b278535..c0e28a1 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -2,6 +2,7 @@
 #include <linux/initrd.h>
 #include <linux/ioport.h>
 #include <linux/swap.h>
+#include <linux/memblock.h>
 
 #include <asm/cacheflush.h>
 #include <asm/e820.h>
@@ -33,6 +34,7 @@
 					  int use_gbpages)
 {
 	unsigned long puds, pmds, ptes, tables, start;
+	phys_addr_t base;
 
 	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
 	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
@@ -75,12 +77,12 @@
 #else
 	start = 0x8000;
 #endif
-	e820_table_start = find_e820_area(start, max_pfn_mapped<<PAGE_SHIFT,
+	base = memblock_find_in_range(start, max_pfn_mapped<<PAGE_SHIFT,
 					tables, PAGE_SIZE);
-	if (e820_table_start == -1UL)
+	if (base == MEMBLOCK_ERROR)
 		panic("Cannot find space for the kernel page tables");
 
-	e820_table_start >>= PAGE_SHIFT;
+	e820_table_start = base >> PAGE_SHIFT;
 	e820_table_end = e820_table_start;
 	e820_table_top = e820_table_start + (tables >> PAGE_SHIFT);
 
@@ -299,7 +301,7 @@
 	__flush_tlb_all();
 
 	if (!after_bootmem && e820_table_end > e820_table_start)
-		reserve_early(e820_table_start << PAGE_SHIFT,
+		memblock_x86_reserve_range(e820_table_start << PAGE_SHIFT,
 				 e820_table_end << PAGE_SHIFT, "PGTABLE");
 
 	if (!after_bootmem)
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index bca7909..0e969f9 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -25,6 +25,7 @@
 #include <linux/pfn.h>
 #include <linux/poison.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/proc_fs.h>
 #include <linux/memory_hotplug.h>
 #include <linux/initrd.h>
@@ -67,7 +68,7 @@
 		panic("alloc_low_page: ran out of memory");
 
 	adr = __va(pfn * PAGE_SIZE);
-	memset(adr, 0, PAGE_SIZE);
+	clear_page(adr);
 	return adr;
 }
 
@@ -422,49 +423,28 @@
 	totalhigh_pages++;
 }
 
-struct add_highpages_data {
-	unsigned long start_pfn;
-	unsigned long end_pfn;
-};
-
-static int __init add_highpages_work_fn(unsigned long start_pfn,
-					 unsigned long end_pfn, void *datax)
+void __init add_highpages_with_active_regions(int nid,
+			 unsigned long start_pfn, unsigned long end_pfn)
 {
-	int node_pfn;
-	struct page *page;
-	unsigned long final_start_pfn, final_end_pfn;
-	struct add_highpages_data *data;
+	struct range *range;
+	int nr_range;
+	int i;
 
-	data = (struct add_highpages_data *)datax;
+	nr_range = __get_free_all_memory_range(&range, nid, start_pfn, end_pfn);
 
-	final_start_pfn = max(start_pfn, data->start_pfn);
-	final_end_pfn = min(end_pfn, data->end_pfn);
-	if (final_start_pfn >= final_end_pfn)
-		return 0;
+	for (i = 0; i < nr_range; i++) {
+		struct page *page;
+		int node_pfn;
 
-	for (node_pfn = final_start_pfn; node_pfn < final_end_pfn;
-	     node_pfn++) {
-		if (!pfn_valid(node_pfn))
-			continue;
-		page = pfn_to_page(node_pfn);
-		add_one_highpage_init(page);
+		for (node_pfn = range[i].start; node_pfn < range[i].end;
+		     node_pfn++) {
+			if (!pfn_valid(node_pfn))
+				continue;
+			page = pfn_to_page(node_pfn);
+			add_one_highpage_init(page);
+		}
 	}
-
-	return 0;
-
 }
-
-void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn,
-					      unsigned long end_pfn)
-{
-	struct add_highpages_data data;
-
-	data.start_pfn = start_pfn;
-	data.end_pfn = end_pfn;
-
-	work_with_active_regions(nid, add_highpages_work_fn, &data);
-}
-
 #else
 static inline void permanent_kmaps_init(pgd_t *pgd_base)
 {
@@ -548,48 +528,6 @@
 	permanent_kmaps_init(pgd_base);
 }
 
-#ifdef CONFIG_ACPI_SLEEP
-/*
- * ACPI suspend needs this for resume, because things like the intel-agp
- * driver might have split up a kernel 4MB mapping.
- */
-char swsusp_pg_dir[PAGE_SIZE]
-	__attribute__ ((aligned(PAGE_SIZE)));
-
-static inline void save_pg_dir(void)
-{
-	memcpy(swsusp_pg_dir, swapper_pg_dir, PAGE_SIZE);
-}
-#else /* !CONFIG_ACPI_SLEEP */
-static inline void save_pg_dir(void)
-{
-}
-#endif /* !CONFIG_ACPI_SLEEP */
-
-void zap_low_mappings(bool early)
-{
-	int i;
-
-	/*
-	 * Zap initial low-memory mappings.
-	 *
-	 * Note that "pgd_clear()" doesn't do it for
-	 * us, because pgd_clear() is a no-op on i386.
-	 */
-	for (i = 0; i < KERNEL_PGD_BOUNDARY; i++) {
-#ifdef CONFIG_X86_PAE
-		set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
-#else
-		set_pgd(swapper_pg_dir+i, __pgd(0));
-#endif
-	}
-
-	if (early)
-		__flush_tlb();
-	else
-		flush_tlb_all();
-}
-
 pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP);
 EXPORT_SYMBOL_GPL(__supported_pte_mask);
 
@@ -712,14 +650,14 @@
 	highstart_pfn = highend_pfn = max_pfn;
 	if (max_pfn > max_low_pfn)
 		highstart_pfn = max_low_pfn;
-	e820_register_active_regions(0, 0, highend_pfn);
+	memblock_x86_register_active_regions(0, 0, highend_pfn);
 	sparse_memory_present_with_active_regions(0);
 	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
 		pages_to_mb(highend_pfn - highstart_pfn));
 	num_physpages = highend_pfn;
 	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
 #else
-	e820_register_active_regions(0, 0, max_low_pfn);
+	memblock_x86_register_active_regions(0, 0, max_low_pfn);
 	sparse_memory_present_with_active_regions(0);
 	num_physpages = max_low_pfn;
 	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
@@ -750,68 +688,12 @@
 	free_area_init_nodes(max_zone_pfns);
 }
 
-#ifndef CONFIG_NO_BOOTMEM
-static unsigned long __init setup_node_bootmem(int nodeid,
-				 unsigned long start_pfn,
-				 unsigned long end_pfn,
-				 unsigned long bootmap)
-{
-	unsigned long bootmap_size;
-
-	/* don't touch min_low_pfn */
-	bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
-					 bootmap >> PAGE_SHIFT,
-					 start_pfn, end_pfn);
-	printk(KERN_INFO "  node %d low ram: %08lx - %08lx\n",
-		nodeid, start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
-	printk(KERN_INFO "  node %d bootmap %08lx - %08lx\n",
-		 nodeid, bootmap, bootmap + bootmap_size);
-	free_bootmem_with_active_regions(nodeid, end_pfn);
-
-	return bootmap + bootmap_size;
-}
-#endif
-
 void __init setup_bootmem_allocator(void)
 {
-#ifndef CONFIG_NO_BOOTMEM
-	int nodeid;
-	unsigned long bootmap_size, bootmap;
-	/*
-	 * Initialize the boot-time allocator (with low memory only):
-	 */
-	bootmap_size = bootmem_bootmap_pages(max_low_pfn)<<PAGE_SHIFT;
-	bootmap = find_e820_area(0, max_pfn_mapped<<PAGE_SHIFT, bootmap_size,
-				 PAGE_SIZE);
-	if (bootmap == -1L)
-		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
-	reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
-#endif
-
 	printk(KERN_INFO "  mapped low ram: 0 - %08lx\n",
 		 max_pfn_mapped<<PAGE_SHIFT);
 	printk(KERN_INFO "  low ram: 0 - %08lx\n", max_low_pfn<<PAGE_SHIFT);
 
-#ifndef CONFIG_NO_BOOTMEM
-	for_each_online_node(nodeid) {
-		 unsigned long start_pfn, end_pfn;
-
-#ifdef CONFIG_NEED_MULTIPLE_NODES
-		start_pfn = node_start_pfn[nodeid];
-		end_pfn = node_end_pfn[nodeid];
-		if (start_pfn > max_low_pfn)
-			continue;
-		if (end_pfn > max_low_pfn)
-			end_pfn = max_low_pfn;
-#else
-		start_pfn = 0;
-		end_pfn = max_low_pfn;
-#endif
-		bootmap = setup_node_bootmem(nodeid, start_pfn, end_pfn,
-						 bootmap);
-	}
-#endif
-
 	after_bootmem = 1;
 }
 
@@ -958,9 +840,6 @@
 
 	if (boot_cpu_data.wp_works_ok < 0)
 		test_wp_bit();
-
-	save_pg_dir();
-	zap_low_mappings(true);
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
@@ -1070,8 +949,3 @@
 }
 #endif
 
-int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
-				   int flags)
-{
-	return reserve_bootmem(phys, len, flags);
-}
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 9a66746..8434620 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -21,6 +21,7 @@
 #include <linux/initrd.h>
 #include <linux/pagemap.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/proc_fs.h>
 #include <linux/pci.h>
 #include <linux/pfn.h>
@@ -52,8 +53,6 @@
 #include <asm/init.h>
 #include <linux/bootmem.h>
 
-static unsigned long dma_reserve __initdata;
-
 static int __init parse_direct_gbpages_off(char *arg)
 {
 	direct_gbpages = 0;
@@ -98,6 +97,43 @@
 __setup("noexec32=", nonx32_setup);
 
 /*
+ * When memory was added/removed make sure all the processes MM have
+ * suitable PGD entries in the local PGD level page.
+ */
+void sync_global_pgds(unsigned long start, unsigned long end)
+{
+	unsigned long address;
+
+	for (address = start; address <= end; address += PGDIR_SIZE) {
+		const pgd_t *pgd_ref = pgd_offset_k(address);
+		unsigned long flags;
+		struct page *page;
+
+		if (pgd_none(*pgd_ref))
+			continue;
+
+		spin_lock_irqsave(&pgd_lock, flags);
+		list_for_each_entry(page, &pgd_list, lru) {
+			pgd_t *pgd;
+			spinlock_t *pgt_lock;
+
+			pgd = (pgd_t *)page_address(page) + pgd_index(address);
+			pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
+			spin_lock(pgt_lock);
+
+			if (pgd_none(*pgd))
+				set_pgd(pgd, *pgd_ref);
+			else
+				BUG_ON(pgd_page_vaddr(*pgd)
+				       != pgd_page_vaddr(*pgd_ref));
+
+			spin_unlock(pgt_lock);
+		}
+		spin_unlock_irqrestore(&pgd_lock, flags);
+	}
+}
+
+/*
  * NOTE: This function is marked __ref because it calls __init function
  * (alloc_bootmem_pages). It's safe to do it ONLY when after_bootmem == 0.
  */
@@ -293,7 +329,7 @@
 		panic("alloc_low_page: ran out of memory");
 
 	adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE);
-	memset(adr, 0, PAGE_SIZE);
+	clear_page(adr);
 	*phys  = pfn * PAGE_SIZE;
 	return adr;
 }
@@ -534,11 +570,13 @@
 			     unsigned long end,
 			     unsigned long page_size_mask)
 {
-
+	bool pgd_changed = false;
 	unsigned long next, last_map_addr = end;
+	unsigned long addr;
 
 	start = (unsigned long)__va(start);
 	end = (unsigned long)__va(end);
+	addr = start;
 
 	for (; start < end; start = next) {
 		pgd_t *pgd = pgd_offset_k(start);
@@ -563,7 +601,12 @@
 		spin_lock(&init_mm.page_table_lock);
 		pgd_populate(&init_mm, pgd, __va(pud_phys));
 		spin_unlock(&init_mm.page_table_lock);
+		pgd_changed = true;
 	}
+
+	if (pgd_changed)
+		sync_global_pgds(addr, end);
+
 	__flush_tlb_all();
 
 	return last_map_addr;
@@ -573,23 +616,7 @@
 void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
 				int acpi, int k8)
 {
-#ifndef CONFIG_NO_BOOTMEM
-	unsigned long bootmap_size, bootmap;
-
-	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
-	bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size,
-				 PAGE_SIZE);
-	if (bootmap == -1L)
-		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
-	reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
-	/* don't touch min_low_pfn */
-	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT,
-					 0, end_pfn);
-	e820_register_active_regions(0, start_pfn, end_pfn);
-	free_bootmem_with_active_regions(0, end_pfn);
-#else
-	e820_register_active_regions(0, start_pfn, end_pfn);
-#endif
+	memblock_x86_register_active_regions(0, start_pfn, end_pfn);
 }
 #endif
 
@@ -799,52 +826,6 @@
 
 #endif
 
-int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
-				   int flags)
-{
-#ifdef CONFIG_NUMA
-	int nid, next_nid;
-	int ret;
-#endif
-	unsigned long pfn = phys >> PAGE_SHIFT;
-
-	if (pfn >= max_pfn) {
-		/*
-		 * This can happen with kdump kernels when accessing
-		 * firmware tables:
-		 */
-		if (pfn < max_pfn_mapped)
-			return -EFAULT;
-
-		printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %lu\n",
-				phys, len);
-		return -EFAULT;
-	}
-
-	/* Should check here against the e820 map to avoid double free */
-#ifdef CONFIG_NUMA
-	nid = phys_to_nid(phys);
-	next_nid = phys_to_nid(phys + len - 1);
-	if (nid == next_nid)
-		ret = reserve_bootmem_node(NODE_DATA(nid), phys, len, flags);
-	else
-		ret = reserve_bootmem(phys, len, flags);
-
-	if (ret != 0)
-		return ret;
-
-#else
-	reserve_bootmem(phys, len, flags);
-#endif
-
-	if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
-		dma_reserve += len / PAGE_SIZE;
-		set_dma_reserve(dma_reserve);
-	}
-
-	return 0;
-}
-
 int kern_addr_valid(unsigned long addr)
 {
 	unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
@@ -1003,6 +984,7 @@
 		}
 
 	}
+	sync_global_pgds((unsigned long)start_page, end);
 	return 0;
 }
 
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 3ba6e06..0369843 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -362,6 +362,11 @@
 	return &bm_pte[pte_index(addr)];
 }
 
+bool __init is_early_ioremap_ptep(pte_t *ptep)
+{
+	return ptep >= &bm_pte[0] && ptep < &bm_pte[PAGE_SIZE/sizeof(pte_t)];
+}
+
 static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
 
 void __init early_ioremap_init(void)
diff --git a/arch/x86/mm/k8topology_64.c b/arch/x86/mm/k8topology_64.c
index 970ed57..804a3b6 100644
--- a/arch/x86/mm/k8topology_64.c
+++ b/arch/x86/mm/k8topology_64.c
@@ -11,6 +11,8 @@
 #include <linux/string.h>
 #include <linux/module.h>
 #include <linux/nodemask.h>
+#include <linux/memblock.h>
+
 #include <asm/io.h>
 #include <linux/pci_ids.h>
 #include <linux/acpi.h>
@@ -22,7 +24,7 @@
 #include <asm/numa.h>
 #include <asm/mpspec.h>
 #include <asm/apic.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 
 static struct bootnode __initdata nodes[8];
 static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE;
@@ -54,8 +56,8 @@
 static __init void early_get_boot_cpu_id(void)
 {
 	/*
-	 * need to get boot_cpu_id so can use that to create apicid_to_node
-	 * in k8_scan_nodes()
+	 * need to get the APIC ID of the BSP so can use that to
+	 * create apicid_to_node in k8_scan_nodes()
 	 */
 #ifdef CONFIG_X86_MPPARSE
 	/*
@@ -212,7 +214,7 @@
 	bits = boot_cpu_data.x86_coreid_bits;
 	cores = (1<<bits);
 	apicid_base = 0;
-	/* need to get boot_cpu_id early for system with apicid lifting */
+	/* get the APIC ID of the BSP early for systems with apicid lifting */
 	early_get_boot_cpu_id();
 	if (boot_cpu_physical_apicid > 0) {
 		pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
@@ -222,7 +224,7 @@
 	for_each_node_mask(i, node_possible_map) {
 		int j;
 
-		e820_register_active_regions(i,
+		memblock_x86_register_active_regions(i,
 				nodes[i].start >> PAGE_SHIFT,
 				nodes[i].end >> PAGE_SHIFT);
 		for (j = apicid_base; j < cores + apicid_base; j++)
diff --git a/arch/x86/mm/kmemcheck/kmemcheck.c b/arch/x86/mm/kmemcheck/kmemcheck.c
index b3b531a..d87dd6d 100644
--- a/arch/x86/mm/kmemcheck/kmemcheck.c
+++ b/arch/x86/mm/kmemcheck/kmemcheck.c
@@ -631,6 +631,8 @@
 	if (!pte)
 		return false;
 
+	WARN_ON_ONCE(in_nmi());
+
 	if (error_code & 2)
 		kmemcheck_access(regs, address, KMEMCHECK_WRITE);
 	else
diff --git a/arch/x86/mm/kmemcheck/opcode.c b/arch/x86/mm/kmemcheck/opcode.c
index 63c19e2..324aa3f 100644
--- a/arch/x86/mm/kmemcheck/opcode.c
+++ b/arch/x86/mm/kmemcheck/opcode.c
@@ -9,7 +9,7 @@
 		b == 0xf0 || b == 0xf2 || b == 0xf3
 		/* Group 2 */
 		|| b == 0x2e || b == 0x36 || b == 0x3e || b == 0x26
-		|| b == 0x64 || b == 0x65 || b == 0x2e || b == 0x3e
+		|| b == 0x64 || b == 0x65
 		/* Group 3 */
 		|| b == 0x66
 		/* Group 4 */
diff --git a/arch/x86/mm/memblock.c b/arch/x86/mm/memblock.c
new file mode 100644
index 0000000..aa11693
--- /dev/null
+++ b/arch/x86/mm/memblock.c
@@ -0,0 +1,348 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/range.h>
+
+/* Check for already reserved areas */
+static bool __init check_with_memblock_reserved_size(u64 *addrp, u64 *sizep, u64 align)
+{
+	struct memblock_region *r;
+	u64 addr = *addrp, last;
+	u64 size = *sizep;
+	bool changed = false;
+
+again:
+	last = addr + size;
+	for_each_memblock(reserved, r) {
+		if (last > r->base && addr < r->base) {
+			size = r->base - addr;
+			changed = true;
+			goto again;
+		}
+		if (last > (r->base + r->size) && addr < (r->base + r->size)) {
+			addr = round_up(r->base + r->size, align);
+			size = last - addr;
+			changed = true;
+			goto again;
+		}
+		if (last <= (r->base + r->size) && addr >= r->base) {
+			*sizep = 0;
+			return false;
+		}
+	}
+	if (changed) {
+		*addrp = addr;
+		*sizep = size;
+	}
+	return changed;
+}
+
+/*
+ * Find next free range after start, and size is returned in *sizep
+ */
+u64 __init memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align)
+{
+	struct memblock_region *r;
+
+	for_each_memblock(memory, r) {
+		u64 ei_start = r->base;
+		u64 ei_last = ei_start + r->size;
+		u64 addr;
+
+		addr = round_up(ei_start, align);
+		if (addr < start)
+			addr = round_up(start, align);
+		if (addr >= ei_last)
+			continue;
+		*sizep = ei_last - addr;
+		while (check_with_memblock_reserved_size(&addr, sizep, align))
+			;
+
+		if (*sizep)
+			return addr;
+	}
+
+	return MEMBLOCK_ERROR;
+}
+
+static __init struct range *find_range_array(int count)
+{
+	u64 end, size, mem;
+	struct range *range;
+
+	size = sizeof(struct range) * count;
+	end = memblock.current_limit;
+
+	mem = memblock_find_in_range(0, end, size, sizeof(struct range));
+	if (mem == MEMBLOCK_ERROR)
+		panic("can not find more space for range array");
+
+	/*
+	 * This range is tempoaray, so don't reserve it, it will not be
+	 * overlapped because We will not alloccate new buffer before
+	 * We discard this one
+	 */
+	range = __va(mem);
+	memset(range, 0, size);
+
+	return range;
+}
+
+static void __init memblock_x86_subtract_reserved(struct range *range, int az)
+{
+	u64 final_start, final_end;
+	struct memblock_region *r;
+
+	/* Take out region array itself at first*/
+	memblock_free_reserved_regions();
+
+	memblock_dbg("Subtract (%ld early reservations)\n", memblock.reserved.cnt);
+
+	for_each_memblock(reserved, r) {
+		memblock_dbg("  [%010llx-%010llx]\n", (u64)r->base, (u64)r->base + r->size - 1);
+		final_start = PFN_DOWN(r->base);
+		final_end = PFN_UP(r->base + r->size);
+		if (final_start >= final_end)
+			continue;
+		subtract_range(range, az, final_start, final_end);
+	}
+
+	/* Put region array back ? */
+	memblock_reserve_reserved_regions();
+}
+
+struct count_data {
+	int nr;
+};
+
+static int __init count_work_fn(unsigned long start_pfn,
+				unsigned long end_pfn, void *datax)
+{
+	struct count_data *data = datax;
+
+	data->nr++;
+
+	return 0;
+}
+
+static int __init count_early_node_map(int nodeid)
+{
+	struct count_data data;
+
+	data.nr = 0;
+	work_with_active_regions(nodeid, count_work_fn, &data);
+
+	return data.nr;
+}
+
+int __init __get_free_all_memory_range(struct range **rangep, int nodeid,
+			 unsigned long start_pfn, unsigned long end_pfn)
+{
+	int count;
+	struct range *range;
+	int nr_range;
+
+	count = (memblock.reserved.cnt + count_early_node_map(nodeid)) * 2;
+
+	range = find_range_array(count);
+	nr_range = 0;
+
+	/*
+	 * Use early_node_map[] and memblock.reserved.region to get range array
+	 * at first
+	 */
+	nr_range = add_from_early_node_map(range, count, nr_range, nodeid);
+	subtract_range(range, count, 0, start_pfn);
+	subtract_range(range, count, end_pfn, -1ULL);
+
+	memblock_x86_subtract_reserved(range, count);
+	nr_range = clean_sort_range(range, count);
+
+	*rangep = range;
+	return nr_range;
+}
+
+int __init get_free_all_memory_range(struct range **rangep, int nodeid)
+{
+	unsigned long end_pfn = -1UL;
+
+#ifdef CONFIG_X86_32
+	end_pfn = max_low_pfn;
+#endif
+	return __get_free_all_memory_range(rangep, nodeid, 0, end_pfn);
+}
+
+static u64 __init __memblock_x86_memory_in_range(u64 addr, u64 limit, bool get_free)
+{
+	int i, count;
+	struct range *range;
+	int nr_range;
+	u64 final_start, final_end;
+	u64 free_size;
+	struct memblock_region *r;
+
+	count = (memblock.reserved.cnt + memblock.memory.cnt) * 2;
+
+	range = find_range_array(count);
+	nr_range = 0;
+
+	addr = PFN_UP(addr);
+	limit = PFN_DOWN(limit);
+
+	for_each_memblock(memory, r) {
+		final_start = PFN_UP(r->base);
+		final_end = PFN_DOWN(r->base + r->size);
+		if (final_start >= final_end)
+			continue;
+		if (final_start >= limit || final_end <= addr)
+			continue;
+
+		nr_range = add_range(range, count, nr_range, final_start, final_end);
+	}
+	subtract_range(range, count, 0, addr);
+	subtract_range(range, count, limit, -1ULL);
+
+	/* Subtract memblock.reserved.region in range ? */
+	if (!get_free)
+		goto sort_and_count_them;
+	for_each_memblock(reserved, r) {
+		final_start = PFN_DOWN(r->base);
+		final_end = PFN_UP(r->base + r->size);
+		if (final_start >= final_end)
+			continue;
+		if (final_start >= limit || final_end <= addr)
+			continue;
+
+		subtract_range(range, count, final_start, final_end);
+	}
+
+sort_and_count_them:
+	nr_range = clean_sort_range(range, count);
+
+	free_size = 0;
+	for (i = 0; i < nr_range; i++)
+		free_size += range[i].end - range[i].start;
+
+	return free_size << PAGE_SHIFT;
+}
+
+u64 __init memblock_x86_free_memory_in_range(u64 addr, u64 limit)
+{
+	return __memblock_x86_memory_in_range(addr, limit, true);
+}
+
+u64 __init memblock_x86_memory_in_range(u64 addr, u64 limit)
+{
+	return __memblock_x86_memory_in_range(addr, limit, false);
+}
+
+void __init memblock_x86_reserve_range(u64 start, u64 end, char *name)
+{
+	if (start == end)
+		return;
+
+	if (WARN_ONCE(start > end, "memblock_x86_reserve_range: wrong range [%#llx, %#llx)\n", start, end))
+		return;
+
+	memblock_dbg("    memblock_x86_reserve_range: [%#010llx-%#010llx] %16s\n", start, end - 1, name);
+
+	memblock_reserve(start, end - start);
+}
+
+void __init memblock_x86_free_range(u64 start, u64 end)
+{
+	if (start == end)
+		return;
+
+	if (WARN_ONCE(start > end, "memblock_x86_free_range: wrong range [%#llx, %#llx)\n", start, end))
+		return;
+
+	memblock_dbg("       memblock_x86_free_range: [%#010llx-%#010llx]\n", start, end - 1);
+
+	memblock_free(start, end - start);
+}
+
+/*
+ * Need to call this function after memblock_x86_register_active_regions,
+ * so early_node_map[] is filled already.
+ */
+u64 __init memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align)
+{
+	u64 addr;
+	addr = find_memory_core_early(nid, size, align, start, end);
+	if (addr != MEMBLOCK_ERROR)
+		return addr;
+
+	/* Fallback, should already have start end within node range */
+	return memblock_find_in_range(start, end, size, align);
+}
+
+/*
+ * Finds an active region in the address range from start_pfn to last_pfn and
+ * returns its range in ei_startpfn and ei_endpfn for the memblock entry.
+ */
+static int __init memblock_x86_find_active_region(const struct memblock_region *ei,
+				  unsigned long start_pfn,
+				  unsigned long last_pfn,
+				  unsigned long *ei_startpfn,
+				  unsigned long *ei_endpfn)
+{
+	u64 align = PAGE_SIZE;
+
+	*ei_startpfn = round_up(ei->base, align) >> PAGE_SHIFT;
+	*ei_endpfn = round_down(ei->base + ei->size, align) >> PAGE_SHIFT;
+
+	/* Skip map entries smaller than a page */
+	if (*ei_startpfn >= *ei_endpfn)
+		return 0;
+
+	/* Skip if map is outside the node */
+	if (*ei_endpfn <= start_pfn || *ei_startpfn >= last_pfn)
+		return 0;
+
+	/* Check for overlaps */
+	if (*ei_startpfn < start_pfn)
+		*ei_startpfn = start_pfn;
+	if (*ei_endpfn > last_pfn)
+		*ei_endpfn = last_pfn;
+
+	return 1;
+}
+
+/* Walk the memblock.memory map and register active regions within a node */
+void __init memblock_x86_register_active_regions(int nid, unsigned long start_pfn,
+					 unsigned long last_pfn)
+{
+	unsigned long ei_startpfn;
+	unsigned long ei_endpfn;
+	struct memblock_region *r;
+
+	for_each_memblock(memory, r)
+		if (memblock_x86_find_active_region(r, start_pfn, last_pfn,
+					   &ei_startpfn, &ei_endpfn))
+			add_active_range(nid, ei_startpfn, ei_endpfn);
+}
+
+/*
+ * Find the hole size (in bytes) in the memory range.
+ * @start: starting address of the memory range to scan
+ * @end: ending address of the memory range to scan
+ */
+u64 __init memblock_x86_hole_size(u64 start, u64 end)
+{
+	unsigned long start_pfn = start >> PAGE_SHIFT;
+	unsigned long last_pfn = end >> PAGE_SHIFT;
+	unsigned long ei_startpfn, ei_endpfn, ram = 0;
+	struct memblock_region *r;
+
+	for_each_memblock(memory, r)
+		if (memblock_x86_find_active_region(r, start_pfn, last_pfn,
+					   &ei_startpfn, &ei_endpfn))
+			ram += ei_endpfn - ei_startpfn;
+
+	return end - start - ((u64)ram << PAGE_SHIFT);
+}
diff --git a/arch/x86/mm/memtest.c b/arch/x86/mm/memtest.c
index 18d244f..92faf3a 100644
--- a/arch/x86/mm/memtest.c
+++ b/arch/x86/mm/memtest.c
@@ -6,8 +6,7 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/pfn.h>
-
-#include <asm/e820.h>
+#include <linux/memblock.h>
 
 static u64 patterns[] __initdata = {
 	0,
@@ -35,7 +34,7 @@
 	       (unsigned long long) pattern,
 	       (unsigned long long) start_bad,
 	       (unsigned long long) end_bad);
-	reserve_early(start_bad, end_bad, "BAD RAM");
+	memblock_x86_reserve_range(start_bad, end_bad, "BAD RAM");
 }
 
 static void __init memtest(u64 pattern, u64 start_phys, u64 size)
@@ -74,7 +73,7 @@
 	u64 size = 0;
 
 	while (start < end) {
-		start = find_e820_area_size(start, &size, 1);
+		start = memblock_x86_find_in_range_size(start, &size, 1);
 
 		/* done ? */
 		if (start >= end)
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index 809baaa..84a3e4c 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -24,6 +24,7 @@
 
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/mmzone.h>
 #include <linux/highmem.h>
 #include <linux/initrd.h>
@@ -120,7 +121,7 @@
 
 	node_start_pfn[0] = 0;
 	node_end_pfn[0] = max_pfn;
-	e820_register_active_regions(0, 0, max_pfn);
+	memblock_x86_register_active_regions(0, 0, max_pfn);
 	memory_present(0, 0, max_pfn);
 	node_remap_size[0] = node_memmap_size_bytes(0, 0, max_pfn);
 
@@ -161,14 +162,14 @@
 		NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid];
 	else {
 		unsigned long pgdat_phys;
-		pgdat_phys = find_e820_area(min_low_pfn<<PAGE_SHIFT,
+		pgdat_phys = memblock_find_in_range(min_low_pfn<<PAGE_SHIFT,
 				 max_pfn_mapped<<PAGE_SHIFT,
 				 sizeof(pg_data_t),
 				 PAGE_SIZE);
 		NODE_DATA(nid) = (pg_data_t *)(pfn_to_kaddr(pgdat_phys>>PAGE_SHIFT));
 		memset(buf, 0, sizeof(buf));
 		sprintf(buf, "NODE_DATA %d",  nid);
-		reserve_early(pgdat_phys, pgdat_phys + sizeof(pg_data_t), buf);
+		memblock_x86_reserve_range(pgdat_phys, pgdat_phys + sizeof(pg_data_t), buf);
 	}
 	printk(KERN_DEBUG "allocate_pgdat: node %d NODE_DATA %08lx\n",
 		nid, (unsigned long)NODE_DATA(nid));
@@ -291,15 +292,15 @@
 						 PTRS_PER_PTE);
 		node_kva_target <<= PAGE_SHIFT;
 		do {
-			node_kva_final = find_e820_area(node_kva_target,
+			node_kva_final = memblock_find_in_range(node_kva_target,
 					((u64)node_end_pfn[nid])<<PAGE_SHIFT,
 						((u64)size)<<PAGE_SHIFT,
 						LARGE_PAGE_BYTES);
 			node_kva_target -= LARGE_PAGE_BYTES;
-		} while (node_kva_final == -1ULL &&
+		} while (node_kva_final == MEMBLOCK_ERROR &&
 			 (node_kva_target>>PAGE_SHIFT) > (node_start_pfn[nid]));
 
-		if (node_kva_final == -1ULL)
+		if (node_kva_final == MEMBLOCK_ERROR)
 			panic("Can not get kva ram\n");
 
 		node_remap_size[nid] = size;
@@ -318,15 +319,13 @@
 		 *  but we could have some hole in high memory, and it will only
 		 *  check page_is_ram(pfn) && !page_is_reserved_early(pfn) to decide
 		 *  to use it as free.
-		 *  So reserve_early here, hope we don't run out of that array
+		 *  So memblock_x86_reserve_range here, hope we don't run out of that array
 		 */
-		reserve_early(node_kva_final,
+		memblock_x86_reserve_range(node_kva_final,
 			      node_kva_final+(((u64)size)<<PAGE_SHIFT),
 			      "KVA RAM");
 
 		node_remap_start_pfn[nid] = node_kva_final>>PAGE_SHIFT;
-		remove_active_range(nid, node_remap_start_pfn[nid],
-					 node_remap_start_pfn[nid] + size);
 	}
 	printk(KERN_INFO "Reserving total of %lx pages for numa KVA remap\n",
 			reserve_pages);
@@ -367,14 +366,14 @@
 
 	kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE);
 	do {
-		kva_start_pfn = find_e820_area(kva_target_pfn<<PAGE_SHIFT,
+		kva_start_pfn = memblock_find_in_range(kva_target_pfn<<PAGE_SHIFT,
 					max_low_pfn<<PAGE_SHIFT,
 					kva_pages<<PAGE_SHIFT,
 					PTRS_PER_PTE<<PAGE_SHIFT) >> PAGE_SHIFT;
 		kva_target_pfn -= PTRS_PER_PTE;
-	} while (kva_start_pfn == -1UL && kva_target_pfn > min_low_pfn);
+	} while (kva_start_pfn == MEMBLOCK_ERROR && kva_target_pfn > min_low_pfn);
 
-	if (kva_start_pfn == -1UL)
+	if (kva_start_pfn == MEMBLOCK_ERROR)
 		panic("Can not get kva space\n");
 
 	printk(KERN_INFO "kva_start_pfn ~ %lx max_low_pfn ~ %lx\n",
@@ -382,7 +381,7 @@
 	printk(KERN_INFO "max_pfn = %lx\n", max_pfn);
 
 	/* avoid clash with initrd */
-	reserve_early(kva_start_pfn<<PAGE_SHIFT,
+	memblock_x86_reserve_range(kva_start_pfn<<PAGE_SHIFT,
 		      (kva_start_pfn + kva_pages)<<PAGE_SHIFT,
 		     "KVA PG");
 #ifdef CONFIG_HIGHMEM
@@ -419,9 +418,6 @@
 	for_each_online_node(nid) {
 		memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
 		NODE_DATA(nid)->node_id = nid;
-#ifndef CONFIG_NO_BOOTMEM
-		NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
-#endif
 	}
 
 	setup_bootmem_allocator();
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index a7bcc23..60f4985 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -7,6 +7,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/mmzone.h>
 #include <linux/ctype.h>
 #include <linux/module.h>
@@ -18,7 +19,7 @@
 #include <asm/dma.h>
 #include <asm/numa.h>
 #include <asm/acpi.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
@@ -86,16 +87,16 @@
 
 	addr = 0x8000;
 	nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES);
-	nodemap_addr = find_e820_area(addr, max_pfn<<PAGE_SHIFT,
+	nodemap_addr = memblock_find_in_range(addr, max_pfn<<PAGE_SHIFT,
 				      nodemap_size, L1_CACHE_BYTES);
-	if (nodemap_addr == -1UL) {
+	if (nodemap_addr == MEMBLOCK_ERROR) {
 		printk(KERN_ERR
 		       "NUMA: Unable to allocate Memory to Node hash map\n");
 		nodemap_addr = nodemap_size = 0;
 		return -1;
 	}
 	memnodemap = phys_to_virt(nodemap_addr);
-	reserve_early(nodemap_addr, nodemap_addr + nodemap_size, "MEMNODEMAP");
+	memblock_x86_reserve_range(nodemap_addr, nodemap_addr + nodemap_size, "MEMNODEMAP");
 
 	printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
 	       nodemap_addr, nodemap_addr + nodemap_size);
@@ -171,8 +172,8 @@
 	if (start < (MAX_DMA32_PFN<<PAGE_SHIFT) &&
 	    end > (MAX_DMA32_PFN<<PAGE_SHIFT))
 		start = MAX_DMA32_PFN<<PAGE_SHIFT;
-	mem = find_e820_area(start, end, size, align);
-	if (mem != -1L)
+	mem = memblock_x86_find_in_range_node(nodeid, start, end, size, align);
+	if (mem != MEMBLOCK_ERROR)
 		return __va(mem);
 
 	/* extend the search scope */
@@ -181,8 +182,8 @@
 		start = MAX_DMA32_PFN<<PAGE_SHIFT;
 	else
 		start = MAX_DMA_PFN<<PAGE_SHIFT;
-	mem = find_e820_area(start, end, size, align);
-	if (mem != -1L)
+	mem = memblock_x86_find_in_range_node(nodeid, start, end, size, align);
+	if (mem != MEMBLOCK_ERROR)
 		return __va(mem);
 
 	printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
@@ -198,10 +199,6 @@
 	unsigned long start_pfn, last_pfn, nodedata_phys;
 	const int pgdat_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
 	int nid;
-#ifndef CONFIG_NO_BOOTMEM
-	unsigned long bootmap_start, bootmap_pages, bootmap_size;
-	void *bootmap;
-#endif
 
 	if (!end)
 		return;
@@ -226,7 +223,7 @@
 	if (node_data[nodeid] == NULL)
 		return;
 	nodedata_phys = __pa(node_data[nodeid]);
-	reserve_early(nodedata_phys, nodedata_phys + pgdat_size, "NODE_DATA");
+	memblock_x86_reserve_range(nodedata_phys, nodedata_phys + pgdat_size, "NODE_DATA");
 	printk(KERN_INFO "  NODE_DATA [%016lx - %016lx]\n", nodedata_phys,
 		nodedata_phys + pgdat_size - 1);
 	nid = phys_to_nid(nodedata_phys);
@@ -238,47 +235,6 @@
 	NODE_DATA(nodeid)->node_start_pfn = start_pfn;
 	NODE_DATA(nodeid)->node_spanned_pages = last_pfn - start_pfn;
 
-#ifndef CONFIG_NO_BOOTMEM
-	NODE_DATA(nodeid)->bdata = &bootmem_node_data[nodeid];
-
-	/*
-	 * Find a place for the bootmem map
-	 * nodedata_phys could be on other nodes by alloc_bootmem,
-	 * so need to sure bootmap_start not to be small, otherwise
-	 * early_node_mem will get that with find_e820_area instead
-	 * of alloc_bootmem, that could clash with reserved range
-	 */
-	bootmap_pages = bootmem_bootmap_pages(last_pfn - start_pfn);
-	bootmap_start = roundup(nodedata_phys + pgdat_size, PAGE_SIZE);
-	/*
-	 * SMP_CACHE_BYTES could be enough, but init_bootmem_node like
-	 * to use that to align to PAGE_SIZE
-	 */
-	bootmap = early_node_mem(nodeid, bootmap_start, end,
-				 bootmap_pages<<PAGE_SHIFT, PAGE_SIZE);
-	if (bootmap == NULL)  {
-		free_early(nodedata_phys, nodedata_phys + pgdat_size);
-		node_data[nodeid] = NULL;
-		return;
-	}
-	bootmap_start = __pa(bootmap);
-	reserve_early(bootmap_start, bootmap_start+(bootmap_pages<<PAGE_SHIFT),
-			"BOOTMAP");
-
-	bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
-					 bootmap_start >> PAGE_SHIFT,
-					 start_pfn, last_pfn);
-
-	printk(KERN_INFO "  bootmap [%016lx -  %016lx] pages %lx\n",
-		 bootmap_start, bootmap_start + bootmap_size - 1,
-		 bootmap_pages);
-	nid = phys_to_nid(bootmap_start);
-	if (nid != nodeid)
-		printk(KERN_INFO "    bootmap(%d) on node %d\n", nodeid, nid);
-
-	free_bootmem_with_active_regions(nodeid, end);
-#endif
-
 	node_set_online(nodeid);
 }
 
@@ -416,7 +372,7 @@
 		nr_nodes = MAX_NUMNODES;
 	}
 
-	size = (max_addr - addr - e820_hole_size(addr, max_addr)) / nr_nodes;
+	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.
@@ -452,7 +408,7 @@
 			 * non-reserved memory is less than the per-node size.
 			 */
 			while (end - physnodes[i].start -
-				e820_hole_size(physnodes[i].start, end) < size) {
+				memblock_x86_hole_size(physnodes[i].start, end) < size) {
 				end += FAKE_NODE_MIN_SIZE;
 				if (end > physnodes[i].end) {
 					end = physnodes[i].end;
@@ -466,7 +422,7 @@
 			 * this one must extend to the boundary.
 			 */
 			if (end < dma32_end && dma32_end - end -
-			    e820_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+			    memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
 				end = dma32_end;
 
 			/*
@@ -475,7 +431,7 @@
 			 * physical node.
 			 */
 			if (physnodes[i].end - end -
-			    e820_hole_size(end, physnodes[i].end) < size)
+			    memblock_x86_hole_size(end, physnodes[i].end) < size)
 				end = physnodes[i].end;
 
 			/*
@@ -503,7 +459,7 @@
 {
 	u64 end = start + size;
 
-	while (end - start - e820_hole_size(start, end) < size) {
+	while (end - start - memblock_x86_hole_size(start, end) < size) {
 		end += FAKE_NODE_MIN_SIZE;
 		if (end > max_addr) {
 			end = max_addr;
@@ -532,7 +488,7 @@
 	 * creates a uniform distribution of node sizes across the entire
 	 * machine (but not necessarily over physical nodes).
 	 */
-	min_size = (max_addr - addr - e820_hole_size(addr, max_addr)) /
+	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)
@@ -565,7 +521,7 @@
 			 * this one must extend to the boundary.
 			 */
 			if (end < dma32_end && dma32_end - end -
-			    e820_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+			    memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
 				end = dma32_end;
 
 			/*
@@ -574,7 +530,7 @@
 			 * physical node.
 			 */
 			if (physnodes[i].end - end -
-			    e820_hole_size(end, physnodes[i].end) < size)
+			    memblock_x86_hole_size(end, physnodes[i].end) < size)
 				end = physnodes[i].end;
 
 			/*
@@ -638,7 +594,7 @@
 	 */
 	remove_all_active_ranges();
 	for_each_node_mask(i, node_possible_map) {
-		e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
+		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);
 	}
@@ -691,7 +647,7 @@
 	node_set(0, node_possible_map);
 	for (i = 0; i < nr_cpu_ids; i++)
 		numa_set_node(i, 0);
-	e820_register_active_regions(0, start_pfn, last_pfn);
+	memblock_x86_register_active_regions(0, start_pfn, last_pfn);
 	setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT);
 }
 
@@ -703,9 +659,7 @@
 	for_each_online_node(i)
 		pages += free_all_bootmem_node(NODE_DATA(i));
 
-#ifdef CONFIG_NO_BOOTMEM
 	pages += free_all_memory_core_early(MAX_NUMNODES);
-#endif
 
 	return pages;
 }
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 5c4ee42..8be8c7d 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -87,7 +87,19 @@
 #define UNSHARED_PTRS_PER_PGD				\
 	(SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
 
-static void pgd_ctor(pgd_t *pgd)
+
+static void pgd_set_mm(pgd_t *pgd, struct mm_struct *mm)
+{
+	BUILD_BUG_ON(sizeof(virt_to_page(pgd)->index) < sizeof(mm));
+	virt_to_page(pgd)->index = (pgoff_t)mm;
+}
+
+struct mm_struct *pgd_page_get_mm(struct page *page)
+{
+	return (struct mm_struct *)page->index;
+}
+
+static void pgd_ctor(struct mm_struct *mm, pgd_t *pgd)
 {
 	/* If the pgd points to a shared pagetable level (either the
 	   ptes in non-PAE, or shared PMD in PAE), then just copy the
@@ -98,15 +110,13 @@
 		clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY,
 				swapper_pg_dir + KERNEL_PGD_BOUNDARY,
 				KERNEL_PGD_PTRS);
-		paravirt_alloc_pmd_clone(__pa(pgd) >> PAGE_SHIFT,
-					 __pa(swapper_pg_dir) >> PAGE_SHIFT,
-					 KERNEL_PGD_BOUNDARY,
-					 KERNEL_PGD_PTRS);
 	}
 
 	/* list required to sync kernel mapping updates */
-	if (!SHARED_KERNEL_PMD)
+	if (!SHARED_KERNEL_PMD) {
+		pgd_set_mm(pgd, mm);
 		pgd_list_add(pgd);
+	}
 }
 
 static void pgd_dtor(pgd_t *pgd)
@@ -272,7 +282,7 @@
 	 */
 	spin_lock_irqsave(&pgd_lock, flags);
 
-	pgd_ctor(pgd);
+	pgd_ctor(mm, pgd);
 	pgd_prepopulate_pmd(mm, pgd, pmds);
 
 	spin_unlock_irqrestore(&pgd_lock, flags);
diff --git a/arch/x86/mm/srat_32.c b/arch/x86/mm/srat_32.c
index 9324f13..a17dffd 100644
--- a/arch/x86/mm/srat_32.c
+++ b/arch/x86/mm/srat_32.c
@@ -25,6 +25,7 @@
  */
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/mmzone.h>
 #include <linux/acpi.h>
 #include <linux/nodemask.h>
@@ -264,7 +265,7 @@
 		if (node_read_chunk(chunk->nid, chunk))
 			continue;
 
-		e820_register_active_regions(chunk->nid, chunk->start_pfn,
+		memblock_x86_register_active_regions(chunk->nid, chunk->start_pfn,
 					     min(chunk->end_pfn, max_pfn));
 	}
 	/* for out of order entries in SRAT */
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index f9897f7..a35cb9d 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/topology.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/mm.h>
 #include <asm/proto.h>
 #include <asm/numa.h>
@@ -98,15 +99,15 @@
 	unsigned long phys;
 
 	length = slit->header.length;
-	phys = find_e820_area(0, max_pfn_mapped<<PAGE_SHIFT, length,
+	phys = memblock_find_in_range(0, max_pfn_mapped<<PAGE_SHIFT, length,
 		 PAGE_SIZE);
 
-	if (phys == -1L)
+	if (phys == MEMBLOCK_ERROR)
 		panic(" Can not save slit!\n");
 
 	acpi_slit = __va(phys);
 	memcpy(acpi_slit, slit, length);
-	reserve_early(phys, phys + length, "ACPI SLIT");
+	memblock_x86_reserve_range(phys, phys + length, "ACPI SLIT");
 }
 
 /* Callback for Proximity Domain -> x2APIC mapping */
@@ -324,7 +325,7 @@
 			pxmram = 0;
 	}
 
-	e820ram = max_pfn - (e820_hole_size(0, max_pfn<<PAGE_SHIFT)>>PAGE_SHIFT);
+	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
@@ -420,9 +421,11 @@
 		return -1;
 	}
 
-	for_each_node_mask(i, nodes_parsed)
-		e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
-						nodes[i].end >> PAGE_SHIFT);
+	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)) {
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index c03f14a..4935848 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -5,6 +5,7 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/cpu.h>
 
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
@@ -52,6 +53,8 @@
    want false sharing in the per cpu data segment. */
 static union smp_flush_state flush_state[NUM_INVALIDATE_TLB_VECTORS];
 
+static DEFINE_PER_CPU_READ_MOSTLY(int, tlb_vector_offset);
+
 /*
  * We cannot call mmdrop() because we are in interrupt context,
  * instead update mm->cpu_vm_mask.
@@ -173,7 +176,7 @@
 	union smp_flush_state *f;
 
 	/* Caller has disabled preemption */
-	sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
+	sender = this_cpu_read(tlb_vector_offset);
 	f = &flush_state[sender];
 
 	/*
@@ -218,6 +221,47 @@
 	flush_tlb_others_ipi(cpumask, mm, va);
 }
 
+static void __cpuinit calculate_tlb_offset(void)
+{
+	int cpu, node, nr_node_vecs;
+	/*
+	 * we are changing tlb_vector_offset for each CPU in runtime, but this
+	 * will not cause inconsistency, as the write is atomic under X86. we
+	 * might see more lock contentions in a short time, but after all CPU's
+	 * tlb_vector_offset are changed, everything should go normal
+	 *
+	 * Note: if NUM_INVALIDATE_TLB_VECTORS % nr_online_nodes !=0, we might
+	 * waste some vectors.
+	 **/
+	if (nr_online_nodes > NUM_INVALIDATE_TLB_VECTORS)
+		nr_node_vecs = 1;
+	else
+		nr_node_vecs = NUM_INVALIDATE_TLB_VECTORS/nr_online_nodes;
+
+	for_each_online_node(node) {
+		int node_offset = (node % NUM_INVALIDATE_TLB_VECTORS) *
+			nr_node_vecs;
+		int cpu_offset = 0;
+		for_each_cpu(cpu, cpumask_of_node(node)) {
+			per_cpu(tlb_vector_offset, cpu) = node_offset +
+				cpu_offset;
+			cpu_offset++;
+			cpu_offset = cpu_offset % nr_node_vecs;
+		}
+	}
+}
+
+static int tlb_cpuhp_notify(struct notifier_block *n,
+		unsigned long action, void *hcpu)
+{
+	switch (action & 0xf) {
+	case CPU_ONLINE:
+	case CPU_DEAD:
+		calculate_tlb_offset();
+	}
+	return NOTIFY_OK;
+}
+
 static int __cpuinit init_smp_flush(void)
 {
 	int i;
@@ -225,6 +269,8 @@
 	for (i = 0; i < ARRAY_SIZE(flush_state); i++)
 		raw_spin_lock_init(&flush_state[i].tlbstate_lock);
 
+	calculate_tlb_offset();
+	hotcpu_notifier(tlb_cpuhp_notify, 0);
 	return 0;
 }
 core_initcall(init_smp_flush);
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
index 3855096..2d49d4e 100644
--- a/arch/x86/oprofile/backtrace.c
+++ b/arch/x86/oprofile/backtrace.c
@@ -14,6 +14,7 @@
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 #include <asm/stacktrace.h>
+#include <linux/compat.h>
 
 static void backtrace_warning_symbol(void *data, char *msg,
 				     unsigned long symbol)
@@ -48,14 +49,12 @@
 	.walk_stack	= print_context_stack,
 };
 
-struct frame_head {
-	struct frame_head *bp;
-	unsigned long ret;
-} __attribute__((packed));
-
-static struct frame_head *dump_user_backtrace(struct frame_head *head)
+#ifdef CONFIG_COMPAT
+static struct stack_frame_ia32 *
+dump_user_backtrace_32(struct stack_frame_ia32 *head)
 {
-	struct frame_head bufhead[2];
+	struct stack_frame_ia32 bufhead[2];
+	struct stack_frame_ia32 *fp;
 
 	/* Also check accessibility of one struct frame_head beyond */
 	if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
@@ -63,20 +62,66 @@
 	if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
 		return NULL;
 
-	oprofile_add_trace(bufhead[0].ret);
+	fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame);
+
+	oprofile_add_trace(bufhead[0].return_address);
+
+	/* frame pointers should strictly progress back up the stack
+	* (towards higher addresses) */
+	if (head >= fp)
+		return NULL;
+
+	return fp;
+}
+
+static inline int
+x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
+{
+	struct stack_frame_ia32 *head;
+
+	/* User process is 32-bit */
+	if (!current || !test_thread_flag(TIF_IA32))
+		return 0;
+
+	head = (struct stack_frame_ia32 *) regs->bp;
+	while (depth-- && head)
+		head = dump_user_backtrace_32(head);
+
+	return 1;
+}
+
+#else
+static inline int
+x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
+{
+	return 0;
+}
+#endif /* CONFIG_COMPAT */
+
+static struct stack_frame *dump_user_backtrace(struct stack_frame *head)
+{
+	struct stack_frame bufhead[2];
+
+	/* Also check accessibility of one struct stack_frame beyond */
+	if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
+		return NULL;
+	if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
+		return NULL;
+
+	oprofile_add_trace(bufhead[0].return_address);
 
 	/* frame pointers should strictly progress back up the stack
 	 * (towards higher addresses) */
-	if (head >= bufhead[0].bp)
+	if (head >= bufhead[0].next_frame)
 		return NULL;
 
-	return bufhead[0].bp;
+	return bufhead[0].next_frame;
 }
 
 void
 x86_backtrace(struct pt_regs * const regs, unsigned int depth)
 {
-	struct frame_head *head = (struct frame_head *)frame_pointer(regs);
+	struct stack_frame *head = (struct stack_frame *)frame_pointer(regs);
 
 	if (!user_mode_vm(regs)) {
 		unsigned long stack = kernel_stack_pointer(regs);
@@ -86,6 +131,9 @@
 		return;
 	}
 
+	if (x86_backtrace_32(regs, depth))
+		return;
+
 	while (depth-- && head)
 		head = dump_user_backtrace(head);
 }
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 009b819..bd1489c 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -674,6 +674,7 @@
 	case 0x0f:
 	case 0x16:
 	case 0x17:
+	case 0x1d:
 		*cpu_type = "i386/core_2";
 		break;
 	case 0x1a:
@@ -694,9 +695,6 @@
 	return 1;
 }
 
-/* in order to get sysfs right */
-static int using_nmi;
-
 int __init op_nmi_init(struct oprofile_operations *ops)
 {
 	__u8 vendor = boot_cpu_data.x86_vendor;
@@ -704,8 +702,6 @@
 	char *cpu_type = NULL;
 	int ret = 0;
 
-	using_nmi = 0;
-
 	if (!cpu_has_apic)
 		return -ENODEV;
 
@@ -789,13 +785,11 @@
 	if (ret)
 		return ret;
 
-	using_nmi = 1;
 	printk(KERN_INFO "oprofile: using NMI interrupt.\n");
 	return 0;
 }
 
 void op_nmi_exit(void)
 {
-	if (using_nmi)
-		exit_sysfs();
+	exit_sysfs();
 }
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index b67a6b5..42fb46f 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -64,15 +64,22 @@
  * IBS cpuid feature detection
  */
 
-#define IBS_CPUID_FEATURES      0x8000001b
+#define IBS_CPUID_FEATURES		0x8000001b
 
 /*
  * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
  * bit 0 is used to indicate the existence of IBS.
  */
-#define IBS_CAPS_AVAIL			(1LL<<0)
-#define IBS_CAPS_RDWROPCNT		(1LL<<3)
-#define IBS_CAPS_OPCNT			(1LL<<4)
+#define IBS_CAPS_AVAIL			(1U<<0)
+#define IBS_CAPS_RDWROPCNT		(1U<<3)
+#define IBS_CAPS_OPCNT			(1U<<4)
+
+/*
+ * IBS APIC setup
+ */
+#define IBSCTL				0x1cc
+#define IBSCTL_LVT_OFFSET_VALID		(1ULL<<8)
+#define IBSCTL_LVT_OFFSET_MASK		0x0F
 
 /*
  * IBS randomization macros
@@ -266,6 +273,74 @@
 		wrmsrl(MSR_AMD64_IBSOPCTL, 0);
 }
 
+static inline int eilvt_is_available(int offset)
+{
+	/* check if we may assign a vector */
+	return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
+}
+
+static inline int ibs_eilvt_valid(void)
+{
+	u64 val;
+	int offset;
+
+	rdmsrl(MSR_AMD64_IBSCTL, val);
+	if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
+		pr_err(FW_BUG "cpu %d, invalid IBS "
+		       "interrupt offset %d (MSR%08X=0x%016llx)",
+		       smp_processor_id(), offset,
+		       MSR_AMD64_IBSCTL, val);
+		return 0;
+	}
+
+	offset = val & IBSCTL_LVT_OFFSET_MASK;
+
+	if (eilvt_is_available(offset))
+		return !0;
+
+	pr_err(FW_BUG "cpu %d, IBS interrupt offset %d "
+	       "not available (MSR%08X=0x%016llx)",
+	       smp_processor_id(), offset,
+	       MSR_AMD64_IBSCTL, val);
+
+	return 0;
+}
+
+static inline int get_ibs_offset(void)
+{
+	u64 val;
+
+	rdmsrl(MSR_AMD64_IBSCTL, val);
+	if (!(val & IBSCTL_LVT_OFFSET_VALID))
+		return -EINVAL;
+
+	return val & IBSCTL_LVT_OFFSET_MASK;
+}
+
+static void setup_APIC_ibs(void)
+{
+	int offset;
+
+	offset = get_ibs_offset();
+	if (offset < 0)
+		goto failed;
+
+	if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
+		return;
+failed:
+	pr_warn("oprofile: IBS APIC setup failed on cpu #%d\n",
+		smp_processor_id());
+}
+
+static void clear_APIC_ibs(void)
+{
+	int offset;
+
+	offset = get_ibs_offset();
+	if (offset >= 0)
+		setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
+}
+
 #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
 
 static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
@@ -376,13 +451,13 @@
 	}
 
 	if (ibs_caps)
-		setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
+		setup_APIC_ibs();
 }
 
 static void op_amd_cpu_shutdown(void)
 {
 	if (ibs_caps)
-		setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
+		clear_APIC_ibs();
 }
 
 static int op_amd_check_ctrs(struct pt_regs * const regs,
@@ -445,16 +520,11 @@
 	op_amd_stop_ibs();
 }
 
-static int __init_ibs_nmi(void)
+static int setup_ibs_ctl(int ibs_eilvt_off)
 {
-#define IBSCTL_LVTOFFSETVAL		(1 << 8)
-#define IBSCTL				0x1cc
 	struct pci_dev *cpu_cfg;
 	int nodes;
 	u32 value = 0;
-	u8 ibs_eilvt_off;
-
-	ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
 
 	nodes = 0;
 	cpu_cfg = NULL;
@@ -466,24 +536,63 @@
 			break;
 		++nodes;
 		pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
-				       | IBSCTL_LVTOFFSETVAL);
+				       | IBSCTL_LVT_OFFSET_VALID);
 		pci_read_config_dword(cpu_cfg, IBSCTL, &value);
-		if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) {
+		if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
 			pci_dev_put(cpu_cfg);
 			printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
-				"IBSCTL = 0x%08x", value);
-			return 1;
+			       "IBSCTL = 0x%08x\n", value);
+			return -EINVAL;
 		}
 	} while (1);
 
 	if (!nodes) {
-		printk(KERN_DEBUG "No CPU node configured for IBS");
-		return 1;
+		printk(KERN_DEBUG "No CPU node configured for IBS\n");
+		return -ENODEV;
 	}
 
 	return 0;
 }
 
+static int force_ibs_eilvt_setup(void)
+{
+	int i;
+	int ret;
+
+	/* find the next free available EILVT entry */
+	for (i = 1; i < 4; i++) {
+		if (!eilvt_is_available(i))
+			continue;
+		ret = setup_ibs_ctl(i);
+		if (ret)
+			return ret;
+		return 0;
+	}
+
+	printk(KERN_DEBUG "No EILVT entry available\n");
+
+	return -EBUSY;
+}
+
+static int __init_ibs_nmi(void)
+{
+	int ret;
+
+	if (ibs_eilvt_valid())
+		return 0;
+
+	ret = force_ibs_eilvt_setup();
+	if (ret)
+		return ret;
+
+	if (!ibs_eilvt_valid())
+		return -EFAULT;
+
+	pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
+
+	return 0;
+}
+
 /* initialize the APIC for the IBS interrupts if available */
 static void init_ibs(void)
 {
diff --git a/arch/x86/pci/olpc.c b/arch/x86/pci/olpc.c
index b348154..13700ec 100644
--- a/arch/x86/pci/olpc.c
+++ b/arch/x86/pci/olpc.c
@@ -304,7 +304,7 @@
 
 int __init pci_olpc_init(void)
 {
-	printk(KERN_INFO "PCI: Using configuration type OLPC\n");
+	printk(KERN_INFO "PCI: Using configuration type OLPC XO-1\n");
 	raw_pci_ops = &pci_olpc_conf;
 	is_lx = is_geode_lx();
 	return 0;
diff --git a/arch/x86/xen/debugfs.c b/arch/x86/xen/debugfs.c
index 1304bce..7c0fedd 100644
--- a/arch/x86/xen/debugfs.c
+++ b/arch/x86/xen/debugfs.c
@@ -106,6 +106,7 @@
 	.open	= u32_array_open,
 	.release= xen_array_release,
 	.read	= u32_array_read,
+	.llseek = no_llseek,
 };
 
 struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 7d46c84..63b83ce 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -30,6 +30,7 @@
 #include <linux/console.h>
 #include <linux/pci.h>
 #include <linux/gfp.h>
+#include <linux/memblock.h>
 
 #include <xen/xen.h>
 #include <xen/interface/xen.h>
@@ -1183,6 +1184,8 @@
 	local_irq_disable();
 	early_boot_irqs_off();
 
+	memblock_init();
+
 	xen_raw_console_write("mapping kernel into physical memory\n");
 	pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages);
 
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 42086ac..f72d18c 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -45,6 +45,7 @@
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/gfp.h>
+#include <linux/memblock.h>
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -55,6 +56,7 @@
 #include <asm/e820.h>
 #include <asm/linkage.h>
 #include <asm/page.h>
+#include <asm/init.h>
 
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
@@ -359,7 +361,8 @@
 	unsigned int level;
 
 	pte = lookup_address(address, &level);
-	BUG_ON(pte == NULL);
+	if (pte == NULL)
+		return;		/* vaddr missing */
 
 	ptev = pte_wrprotect(*pte);
 
@@ -374,7 +377,8 @@
 	unsigned int level;
 
 	pte = lookup_address(address, &level);
-	BUG_ON(pte == NULL);
+	if (pte == NULL)
+		return;		/* vaddr missing */
 
 	ptev = pte_mkwrite(*pte);
 
@@ -1508,13 +1512,25 @@
 #endif
 }
 
-#ifdef CONFIG_X86_32
 static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
 {
+	unsigned long pfn = pte_pfn(pte);
+
+#ifdef CONFIG_X86_32
 	/* If there's an existing pte, then don't allow _PAGE_RW to be set */
 	if (pte_val_ma(*ptep) & _PAGE_PRESENT)
 		pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
 			       pte_val_ma(pte));
+#endif
+
+	/*
+	 * 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.
+	 */
+	if (!is_early_ioremap_ptep(ptep) &&
+	    pfn >= e820_table_start && pfn < e820_table_end)
+		pte = pte_wrprotect(pte);
 
 	return pte;
 }
@@ -1527,7 +1543,6 @@
 
 	xen_set_pte(ptep, pte);
 }
-#endif
 
 static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
 {
@@ -1814,7 +1829,7 @@
 	__xen_write_cr3(true, __pa(pgd));
 	xen_mc_issue(PARAVIRT_LAZY_CPU);
 
-	reserve_early(__pa(xen_start_info->pt_base),
+	memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
 		      __pa(xen_start_info->pt_base +
 			   xen_start_info->nr_pt_frames * PAGE_SIZE),
 		      "XEN PAGETABLES");
@@ -1852,7 +1867,7 @@
 
 	pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
 
-	reserve_early(__pa(xen_start_info->pt_base),
+	memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
 		      __pa(xen_start_info->pt_base +
 			   xen_start_info->nr_pt_frames * PAGE_SIZE),
 		      "XEN PAGETABLES");
@@ -1969,14 +1984,9 @@
 	.alloc_pte = xen_alloc_pte_init,
 	.release_pte = xen_release_pte_init,
 	.alloc_pmd = xen_alloc_pmd_init,
-	.alloc_pmd_clone = paravirt_nop,
 	.release_pmd = xen_release_pmd_init,
 
-#ifdef CONFIG_X86_64
-	.set_pte = xen_set_pte,
-#else
 	.set_pte = xen_set_pte_init,
-#endif
 	.set_pte_at = xen_set_pte_at,
 	.set_pmd = xen_set_pmd_hyper,
 
diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c
index a013ec9..2247100 100644
--- a/arch/x86/xen/pci-swiotlb-xen.c
+++ b/arch/x86/xen/pci-swiotlb-xen.c
@@ -5,6 +5,7 @@
 
 #include <asm/xen/hypervisor.h>
 #include <xen/xen.h>
+#include <asm/iommu_table.h>
 
 int xen_swiotlb __read_mostly;
 
@@ -56,3 +57,7 @@
 		dma_ops = &xen_swiotlb_dma_ops;
 	}
 }
+IOMMU_INIT_FINISH(pci_xen_swiotlb_detect,
+		  0,
+		  pci_xen_swiotlb_init,
+		  0);
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 328b003..9729c90 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -8,6 +8,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/pm.h>
+#include <linux/memblock.h>
 
 #include <asm/elf.h>
 #include <asm/vdso.h>
@@ -129,7 +130,7 @@
 	 *  - xen_start_info
 	 * See comment above "struct start_info" in <xen/interface/xen.h>
 	 */
-	reserve_early(__pa(xen_start_info->mfn_list),
+	memblock_x86_reserve_range(__pa(xen_start_info->mfn_list),
 		      __pa(xen_start_info->pt_base),
 			"XEN START INFO");
 
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index e0500646..23e061b 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -224,7 +224,7 @@
 			goto out;
 		}
 
-		flags = __raw_local_save_flags();
+		flags = arch_local_save_flags();
 		if (irq_enable) {
 			ADD_STATS(taken_slow_irqenable, 1);
 			raw_local_irq_enable();
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 1a5353a..b2bb5aa3 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -489,8 +489,9 @@
 __init void xen_hvm_init_time_ops(void)
 {
 	/* vector callback is needed otherwise we cannot receive interrupts
-	 * on cpu > 0 */
-	if (!xen_have_vector_callback && num_present_cpus() > 1)
+	 * on cpu > 0 and at this point we don't know how many cpus are
+	 * available */
+	if (!xen_have_vector_callback)
 		return;
 	if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
 		printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
diff --git a/arch/xtensa/include/asm/irqflags.h b/arch/xtensa/include/asm/irqflags.h
new file mode 100644
index 0000000..dae9a8b
--- /dev/null
+++ b/arch/xtensa/include/asm/irqflags.h
@@ -0,0 +1,58 @@
+/*
+ * Xtensa IRQ flags handling functions
+ *
+ * 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 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IRQFLAGS_H
+#define _XTENSA_IRQFLAGS_H
+
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile("rsr %0,"__stringify(PS) : "=a" (flags));
+	return flags;
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+	asm volatile("rsil %0, "__stringify(LOCKLEVEL)
+		     : "=a" (flags) :: "memory");
+	return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	arch_local_irq_save();
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	unsigned long flags;
+	asm volatile("rsil %0, 0" : "=a" (flags) :: "memory");
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile("wsr %0, "__stringify(PS)" ; rsync"
+		     :: "a" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags & 0xf) != 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _XTENSA_IRQFLAGS_H */
diff --git a/arch/xtensa/include/asm/system.h b/arch/xtensa/include/asm/system.h
index 62b1e8f..1e7e09a 100644
--- a/arch/xtensa/include/asm/system.h
+++ b/arch/xtensa/include/asm/system.h
@@ -12,41 +12,10 @@
 #define _XTENSA_SYSTEM_H
 
 #include <linux/stringify.h>
+#include <linux/irqflags.h>
 
 #include <asm/processor.h>
 
-/* interrupt control */
-
-#define local_save_flags(x)						\
-	__asm__ __volatile__ ("rsr %0,"__stringify(PS) : "=a" (x));
-#define local_irq_restore(x)	do {					\
-	__asm__ __volatile__ ("wsr %0, "__stringify(PS)" ; rsync" 	\
-	    		      :: "a" (x) : "memory"); } while(0);
-#define local_irq_save(x)	do {					\
-	__asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL) 	\
-	    		      : "=a" (x) :: "memory");} while(0);
-
-static inline void local_irq_disable(void)
-{
-	unsigned long flags;
-	__asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL)
-	    		      : "=a" (flags) :: "memory");
-}
-static inline void local_irq_enable(void)
-{
-	unsigned long flags;
-	__asm__ __volatile__ ("rsil %0, 0" : "=a" (flags) :: "memory");
-
-}
-
-static inline int irqs_disabled(void)
-{
-	unsigned long flags;
-	local_save_flags(flags);
-	return flags & 0xf;
-}
-
-
 #define smp_read_barrier_depends() do { } while(0)
 #define read_barrier_depends() do { } while(0)
 
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index c64a5d3..8750888 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -92,7 +92,7 @@
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", irq_desc[i].chip->typename);
+		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
diff --git a/block/Kconfig b/block/Kconfig
index 9be0b56..6c9213e 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -77,6 +77,18 @@
 	T10/SCSI Data Integrity Field or the T13/ATA External Path
 	Protection.  If in doubt, say N.
 
+config BLK_DEV_THROTTLING
+	bool "Block layer bio throttling support"
+	depends on BLK_CGROUP=y && EXPERIMENTAL
+	default n
+	---help---
+	Block layer bio throttling support. It can be used to limit
+	the IO rate to a device. IO rate policies are per cgroup and
+	one needs to mount and use blkio cgroup controller for creating
+	cgroups and specifying per device IO rate policies.
+
+	See Documentation/cgroups/blkio-controller.txt for more information.
+
 endif # BLOCK
 
 config BLOCK_COMPAT
diff --git a/block/Makefile b/block/Makefile
index 0bb499a..0fec4b3 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -3,12 +3,13 @@
 #
 
 obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \
-			blk-barrier.o blk-settings.o blk-ioc.o blk-map.o \
+			blk-flush.o blk-settings.o blk-ioc.o blk-map.o \
 			blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \
 			blk-iopoll.o blk-lib.o ioctl.o genhd.o scsi_ioctl.o
 
 obj-$(CONFIG_BLK_DEV_BSG)	+= bsg.o
 obj-$(CONFIG_BLK_CGROUP)	+= blk-cgroup.o
+obj-$(CONFIG_BLK_DEV_THROTTLING)	+= blk-throttle.o
 obj-$(CONFIG_IOSCHED_NOOP)	+= noop-iosched.o
 obj-$(CONFIG_IOSCHED_DEADLINE)	+= deadline-iosched.o
 obj-$(CONFIG_IOSCHED_CFQ)	+= cfq-iosched.o
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
deleted file mode 100644
index f0faefc..0000000
--- a/block/blk-barrier.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Functions related to barrier IO handling
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/bio.h>
-#include <linux/blkdev.h>
-#include <linux/gfp.h>
-
-#include "blk.h"
-
-/**
- * blk_queue_ordered - does this queue support ordered writes
- * @q:        the request queue
- * @ordered:  one of QUEUE_ORDERED_*
- *
- * Description:
- *   For journalled file systems, doing ordered writes on a commit
- *   block instead of explicitly doing wait_on_buffer (which is bad
- *   for performance) can be a big win. Block drivers supporting this
- *   feature should call this function and indicate so.
- *
- **/
-int blk_queue_ordered(struct request_queue *q, unsigned ordered)
-{
-	if (ordered != QUEUE_ORDERED_NONE &&
-	    ordered != QUEUE_ORDERED_DRAIN &&
-	    ordered != QUEUE_ORDERED_DRAIN_FLUSH &&
-	    ordered != QUEUE_ORDERED_DRAIN_FUA &&
-	    ordered != QUEUE_ORDERED_TAG &&
-	    ordered != QUEUE_ORDERED_TAG_FLUSH &&
-	    ordered != QUEUE_ORDERED_TAG_FUA) {
-		printk(KERN_ERR "blk_queue_ordered: bad value %d\n", ordered);
-		return -EINVAL;
-	}
-
-	q->ordered = ordered;
-	q->next_ordered = ordered;
-
-	return 0;
-}
-EXPORT_SYMBOL(blk_queue_ordered);
-
-/*
- * Cache flushing for ordered writes handling
- */
-unsigned blk_ordered_cur_seq(struct request_queue *q)
-{
-	if (!q->ordseq)
-		return 0;
-	return 1 << ffz(q->ordseq);
-}
-
-unsigned blk_ordered_req_seq(struct request *rq)
-{
-	struct request_queue *q = rq->q;
-
-	BUG_ON(q->ordseq == 0);
-
-	if (rq == &q->pre_flush_rq)
-		return QUEUE_ORDSEQ_PREFLUSH;
-	if (rq == &q->bar_rq)
-		return QUEUE_ORDSEQ_BAR;
-	if (rq == &q->post_flush_rq)
-		return QUEUE_ORDSEQ_POSTFLUSH;
-
-	/*
-	 * !fs requests don't need to follow barrier ordering.  Always
-	 * put them at the front.  This fixes the following deadlock.
-	 *
-	 * http://thread.gmane.org/gmane.linux.kernel/537473
-	 */
-	if (rq->cmd_type != REQ_TYPE_FS)
-		return QUEUE_ORDSEQ_DRAIN;
-
-	if ((rq->cmd_flags & REQ_ORDERED_COLOR) ==
-	    (q->orig_bar_rq->cmd_flags & REQ_ORDERED_COLOR))
-		return QUEUE_ORDSEQ_DRAIN;
-	else
-		return QUEUE_ORDSEQ_DONE;
-}
-
-bool blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error)
-{
-	struct request *rq;
-
-	if (error && !q->orderr)
-		q->orderr = error;
-
-	BUG_ON(q->ordseq & seq);
-	q->ordseq |= seq;
-
-	if (blk_ordered_cur_seq(q) != QUEUE_ORDSEQ_DONE)
-		return false;
-
-	/*
-	 * Okay, sequence complete.
-	 */
-	q->ordseq = 0;
-	rq = q->orig_bar_rq;
-	__blk_end_request_all(rq, q->orderr);
-	return true;
-}
-
-static void pre_flush_end_io(struct request *rq, int error)
-{
-	elv_completed_request(rq->q, rq);
-	blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_PREFLUSH, error);
-}
-
-static void bar_end_io(struct request *rq, int error)
-{
-	elv_completed_request(rq->q, rq);
-	blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_BAR, error);
-}
-
-static void post_flush_end_io(struct request *rq, int error)
-{
-	elv_completed_request(rq->q, rq);
-	blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_POSTFLUSH, error);
-}
-
-static void queue_flush(struct request_queue *q, unsigned which)
-{
-	struct request *rq;
-	rq_end_io_fn *end_io;
-
-	if (which == QUEUE_ORDERED_DO_PREFLUSH) {
-		rq = &q->pre_flush_rq;
-		end_io = pre_flush_end_io;
-	} else {
-		rq = &q->post_flush_rq;
-		end_io = post_flush_end_io;
-	}
-
-	blk_rq_init(q, rq);
-	rq->cmd_type = REQ_TYPE_FS;
-	rq->cmd_flags = REQ_HARDBARRIER | REQ_FLUSH;
-	rq->rq_disk = q->orig_bar_rq->rq_disk;
-	rq->end_io = end_io;
-
-	elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
-}
-
-static inline bool start_ordered(struct request_queue *q, struct request **rqp)
-{
-	struct request *rq = *rqp;
-	unsigned skip = 0;
-
-	q->orderr = 0;
-	q->ordered = q->next_ordered;
-	q->ordseq |= QUEUE_ORDSEQ_STARTED;
-
-	/*
-	 * For an empty barrier, there's no actual BAR request, which
-	 * in turn makes POSTFLUSH unnecessary.  Mask them off.
-	 */
-	if (!blk_rq_sectors(rq)) {
-		q->ordered &= ~(QUEUE_ORDERED_DO_BAR |
-				QUEUE_ORDERED_DO_POSTFLUSH);
-		/*
-		 * Empty barrier on a write-through device w/ ordered
-		 * tag has no command to issue and without any command
-		 * to issue, ordering by tag can't be used.  Drain
-		 * instead.
-		 */
-		if ((q->ordered & QUEUE_ORDERED_BY_TAG) &&
-		    !(q->ordered & QUEUE_ORDERED_DO_PREFLUSH)) {
-			q->ordered &= ~QUEUE_ORDERED_BY_TAG;
-			q->ordered |= QUEUE_ORDERED_BY_DRAIN;
-		}
-	}
-
-	/* stash away the original request */
-	blk_dequeue_request(rq);
-	q->orig_bar_rq = rq;
-	rq = NULL;
-
-	/*
-	 * Queue ordered sequence.  As we stack them at the head, we
-	 * need to queue in reverse order.  Note that we rely on that
-	 * no fs request uses ELEVATOR_INSERT_FRONT and thus no fs
-	 * request gets inbetween ordered sequence.
-	 */
-	if (q->ordered & QUEUE_ORDERED_DO_POSTFLUSH) {
-		queue_flush(q, QUEUE_ORDERED_DO_POSTFLUSH);
-		rq = &q->post_flush_rq;
-	} else
-		skip |= QUEUE_ORDSEQ_POSTFLUSH;
-
-	if (q->ordered & QUEUE_ORDERED_DO_BAR) {
-		rq = &q->bar_rq;
-
-		/* initialize proxy request and queue it */
-		blk_rq_init(q, rq);
-		if (bio_data_dir(q->orig_bar_rq->bio) == WRITE)
-			rq->cmd_flags |= REQ_WRITE;
-		if (q->ordered & QUEUE_ORDERED_DO_FUA)
-			rq->cmd_flags |= REQ_FUA;
-		init_request_from_bio(rq, q->orig_bar_rq->bio);
-		rq->end_io = bar_end_io;
-
-		elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
-	} else
-		skip |= QUEUE_ORDSEQ_BAR;
-
-	if (q->ordered & QUEUE_ORDERED_DO_PREFLUSH) {
-		queue_flush(q, QUEUE_ORDERED_DO_PREFLUSH);
-		rq = &q->pre_flush_rq;
-	} else
-		skip |= QUEUE_ORDSEQ_PREFLUSH;
-
-	if ((q->ordered & QUEUE_ORDERED_BY_DRAIN) && queue_in_flight(q))
-		rq = NULL;
-	else
-		skip |= QUEUE_ORDSEQ_DRAIN;
-
-	*rqp = rq;
-
-	/*
-	 * Complete skipped sequences.  If whole sequence is complete,
-	 * return false to tell elevator that this request is gone.
-	 */
-	return !blk_ordered_complete_seq(q, skip, 0);
-}
-
-bool blk_do_ordered(struct request_queue *q, struct request **rqp)
-{
-	struct request *rq = *rqp;
-	const int is_barrier = rq->cmd_type == REQ_TYPE_FS &&
-				(rq->cmd_flags & REQ_HARDBARRIER);
-
-	if (!q->ordseq) {
-		if (!is_barrier)
-			return true;
-
-		if (q->next_ordered != QUEUE_ORDERED_NONE)
-			return start_ordered(q, rqp);
-		else {
-			/*
-			 * Queue ordering not supported.  Terminate
-			 * with prejudice.
-			 */
-			blk_dequeue_request(rq);
-			__blk_end_request_all(rq, -EOPNOTSUPP);
-			*rqp = NULL;
-			return false;
-		}
-	}
-
-	/*
-	 * Ordered sequence in progress
-	 */
-
-	/* Special requests are not subject to ordering rules. */
-	if (rq->cmd_type != REQ_TYPE_FS &&
-	    rq != &q->pre_flush_rq && rq != &q->post_flush_rq)
-		return true;
-
-	if (q->ordered & QUEUE_ORDERED_BY_TAG) {
-		/* Ordered by tag.  Blocking the next barrier is enough. */
-		if (is_barrier && rq != &q->bar_rq)
-			*rqp = NULL;
-	} else {
-		/* Ordered by draining.  Wait for turn. */
-		WARN_ON(blk_ordered_req_seq(rq) < blk_ordered_cur_seq(q));
-		if (blk_ordered_req_seq(rq) > blk_ordered_cur_seq(q))
-			*rqp = NULL;
-	}
-
-	return true;
-}
-
-static void bio_end_empty_barrier(struct bio *bio, int err)
-{
-	if (err) {
-		if (err == -EOPNOTSUPP)
-			set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
-		clear_bit(BIO_UPTODATE, &bio->bi_flags);
-	}
-	if (bio->bi_private)
-		complete(bio->bi_private);
-	bio_put(bio);
-}
-
-/**
- * blkdev_issue_flush - queue a flush
- * @bdev:	blockdev to issue flush for
- * @gfp_mask:	memory allocation flags (for bio_alloc)
- * @error_sector:	error sector
- * @flags:	BLKDEV_IFL_* flags to control behaviour
- *
- * Description:
- *    Issue a flush for the block device in question. Caller can supply
- *    room for storing the error offset in case of a flush error, if they
- *    wish to. If WAIT flag is not passed then caller may check only what
- *    request was pushed in some internal queue for later handling.
- */
-int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
-		sector_t *error_sector, unsigned long flags)
-{
-	DECLARE_COMPLETION_ONSTACK(wait);
-	struct request_queue *q;
-	struct bio *bio;
-	int ret = 0;
-
-	if (bdev->bd_disk == NULL)
-		return -ENXIO;
-
-	q = bdev_get_queue(bdev);
-	if (!q)
-		return -ENXIO;
-
-	/*
-	 * some block devices may not have their queue correctly set up here
-	 * (e.g. loop device without a backing file) and so issuing a flush
-	 * here will panic. Ensure there is a request function before issuing
-	 * the barrier.
-	 */
-	if (!q->make_request_fn)
-		return -ENXIO;
-
-	bio = bio_alloc(gfp_mask, 0);
-	bio->bi_end_io = bio_end_empty_barrier;
-	bio->bi_bdev = bdev;
-	if (test_bit(BLKDEV_WAIT, &flags))
-		bio->bi_private = &wait;
-
-	bio_get(bio);
-	submit_bio(WRITE_BARRIER, bio);
-	if (test_bit(BLKDEV_WAIT, &flags)) {
-		wait_for_completion(&wait);
-		/*
-		 * The driver must store the error location in ->bi_sector, if
-		 * it supports it. For non-stacked drivers, this should be
-		 * copied from blk_rq_pos(rq).
-		 */
-		if (error_sector)
-			*error_sector = bio->bi_sector;
-	}
-
-	if (bio_flagged(bio, BIO_EOPNOTSUPP))
-		ret = -EOPNOTSUPP;
-	else if (!bio_flagged(bio, BIO_UPTODATE))
-		ret = -EIO;
-
-	bio_put(bio);
-	return ret;
-}
-EXPORT_SYMBOL(blkdev_issue_flush);
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 2fef1ef..b1febd0 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -37,6 +37,12 @@
 static void blkiocg_destroy(struct cgroup_subsys *, struct cgroup *);
 static int blkiocg_populate(struct cgroup_subsys *, struct cgroup *);
 
+/* for encoding cft->private value on file */
+#define BLKIOFILE_PRIVATE(x, val)	(((x) << 16) | (val))
+/* What policy owns the file, proportional or throttle */
+#define BLKIOFILE_POLICY(val)		(((val) >> 16) & 0xffff)
+#define BLKIOFILE_ATTR(val)		((val) & 0xffff)
+
 struct cgroup_subsys blkio_subsys = {
 	.name = "blkio",
 	.create = blkiocg_create,
@@ -59,6 +65,27 @@
 	list_add(&pn->node, &blkcg->policy_list);
 }
 
+static inline bool cftype_blkg_same_policy(struct cftype *cft,
+			struct blkio_group *blkg)
+{
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+
+	if (blkg->plid == plid)
+		return 1;
+
+	return 0;
+}
+
+/* Determines if policy node matches cgroup file being accessed */
+static inline bool pn_matches_cftype(struct cftype *cft,
+			struct blkio_policy_node *pn)
+{
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int fileid = BLKIOFILE_ATTR(cft->private);
+
+	return (plid == pn->plid && fileid == pn->fileid);
+}
+
 /* Must be called with blkcg->lock held */
 static inline void blkio_policy_delete_node(struct blkio_policy_node *pn)
 {
@@ -67,12 +94,13 @@
 
 /* Must be called with blkcg->lock held */
 static struct blkio_policy_node *
-blkio_policy_search_node(const struct blkio_cgroup *blkcg, dev_t dev)
+blkio_policy_search_node(const struct blkio_cgroup *blkcg, dev_t dev,
+		enum blkio_policy_id plid, int fileid)
 {
 	struct blkio_policy_node *pn;
 
 	list_for_each_entry(pn, &blkcg->policy_list, node) {
-		if (pn->dev == dev)
+		if (pn->dev == dev && pn->plid == plid && pn->fileid == fileid)
 			return pn;
 	}
 
@@ -86,6 +114,67 @@
 }
 EXPORT_SYMBOL_GPL(cgroup_to_blkio_cgroup);
 
+static inline void
+blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight)
+{
+	struct blkio_policy_type *blkiop;
+
+	list_for_each_entry(blkiop, &blkio_list, list) {
+		/* If this policy does not own the blkg, do not send updates */
+		if (blkiop->plid != blkg->plid)
+			continue;
+		if (blkiop->ops.blkio_update_group_weight_fn)
+			blkiop->ops.blkio_update_group_weight_fn(blkg->key,
+							blkg, weight);
+	}
+}
+
+static inline void blkio_update_group_bps(struct blkio_group *blkg, u64 bps,
+				int fileid)
+{
+	struct blkio_policy_type *blkiop;
+
+	list_for_each_entry(blkiop, &blkio_list, list) {
+
+		/* If this policy does not own the blkg, do not send updates */
+		if (blkiop->plid != blkg->plid)
+			continue;
+
+		if (fileid == BLKIO_THROTL_read_bps_device
+		    && blkiop->ops.blkio_update_group_read_bps_fn)
+			blkiop->ops.blkio_update_group_read_bps_fn(blkg->key,
+								blkg, bps);
+
+		if (fileid == BLKIO_THROTL_write_bps_device
+		    && blkiop->ops.blkio_update_group_write_bps_fn)
+			blkiop->ops.blkio_update_group_write_bps_fn(blkg->key,
+								blkg, bps);
+	}
+}
+
+static inline void blkio_update_group_iops(struct blkio_group *blkg,
+			unsigned int iops, int fileid)
+{
+	struct blkio_policy_type *blkiop;
+
+	list_for_each_entry(blkiop, &blkio_list, list) {
+
+		/* If this policy does not own the blkg, do not send updates */
+		if (blkiop->plid != blkg->plid)
+			continue;
+
+		if (fileid == BLKIO_THROTL_read_iops_device
+		    && blkiop->ops.blkio_update_group_read_iops_fn)
+			blkiop->ops.blkio_update_group_read_iops_fn(blkg->key,
+								blkg, iops);
+
+		if (fileid == BLKIO_THROTL_write_iops_device
+		    && blkiop->ops.blkio_update_group_write_iops_fn)
+			blkiop->ops.blkio_update_group_write_iops_fn(blkg->key,
+								blkg,iops);
+	}
+}
+
 /*
  * Add to the appropriate stat variable depending on the request type.
  * This should be called with the blkg->stats_lock held.
@@ -341,7 +430,8 @@
 EXPORT_SYMBOL_GPL(blkiocg_update_io_merged_stats);
 
 void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
-			struct blkio_group *blkg, void *key, dev_t dev)
+		struct blkio_group *blkg, void *key, dev_t dev,
+		enum blkio_policy_id plid)
 {
 	unsigned long flags;
 
@@ -350,6 +440,7 @@
 	rcu_assign_pointer(blkg->key, key);
 	blkg->blkcg_id = css_id(&blkcg->css);
 	hlist_add_head_rcu(&blkg->blkcg_node, &blkcg->blkg_list);
+	blkg->plid = plid;
 	spin_unlock_irqrestore(&blkcg->lock, flags);
 	/* Need to take css reference ? */
 	cgroup_path(blkcg->css.cgroup, blkg->path, sizeof(blkg->path));
@@ -408,51 +499,6 @@
 }
 EXPORT_SYMBOL_GPL(blkiocg_lookup_group);
 
-#define SHOW_FUNCTION(__VAR)						\
-static u64 blkiocg_##__VAR##_read(struct cgroup *cgroup,		\
-				       struct cftype *cftype)		\
-{									\
-	struct blkio_cgroup *blkcg;					\
-									\
-	blkcg = cgroup_to_blkio_cgroup(cgroup);				\
-	return (u64)blkcg->__VAR;					\
-}
-
-SHOW_FUNCTION(weight);
-#undef SHOW_FUNCTION
-
-static int
-blkiocg_weight_write(struct cgroup *cgroup, struct cftype *cftype, u64 val)
-{
-	struct blkio_cgroup *blkcg;
-	struct blkio_group *blkg;
-	struct hlist_node *n;
-	struct blkio_policy_type *blkiop;
-	struct blkio_policy_node *pn;
-
-	if (val < BLKIO_WEIGHT_MIN || val > BLKIO_WEIGHT_MAX)
-		return -EINVAL;
-
-	blkcg = cgroup_to_blkio_cgroup(cgroup);
-	spin_lock(&blkio_list_lock);
-	spin_lock_irq(&blkcg->lock);
-	blkcg->weight = (unsigned int)val;
-
-	hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
-		pn = blkio_policy_search_node(blkcg, blkg->dev);
-
-		if (pn)
-			continue;
-
-		list_for_each_entry(blkiop, &blkio_list, list)
-			blkiop->ops.blkio_update_group_weight_fn(blkg,
-					blkcg->weight);
-	}
-	spin_unlock_irq(&blkcg->lock);
-	spin_unlock(&blkio_list_lock);
-	return 0;
-}
-
 static int
 blkiocg_reset_stats(struct cgroup *cgroup, struct cftype *cftype, u64 val)
 {
@@ -593,52 +639,6 @@
 	return disk_total;
 }
 
-#define SHOW_FUNCTION_PER_GROUP(__VAR, type, show_total)		\
-static int blkiocg_##__VAR##_read(struct cgroup *cgroup,		\
-		struct cftype *cftype, struct cgroup_map_cb *cb)	\
-{									\
-	struct blkio_cgroup *blkcg;					\
-	struct blkio_group *blkg;					\
-	struct hlist_node *n;						\
-	uint64_t cgroup_total = 0;					\
-									\
-	if (!cgroup_lock_live_group(cgroup))				\
-		return -ENODEV;						\
-									\
-	blkcg = cgroup_to_blkio_cgroup(cgroup);				\
-	rcu_read_lock();						\
-	hlist_for_each_entry_rcu(blkg, n, &blkcg->blkg_list, blkcg_node) {\
-		if (blkg->dev) {					\
-			spin_lock_irq(&blkg->stats_lock);		\
-			cgroup_total += blkio_get_stat(blkg, cb,	\
-						blkg->dev, type);	\
-			spin_unlock_irq(&blkg->stats_lock);		\
-		}							\
-	}								\
-	if (show_total)							\
-		cb->fill(cb, "Total", cgroup_total);			\
-	rcu_read_unlock();						\
-	cgroup_unlock();						\
-	return 0;							\
-}
-
-SHOW_FUNCTION_PER_GROUP(time, BLKIO_STAT_TIME, 0);
-SHOW_FUNCTION_PER_GROUP(sectors, BLKIO_STAT_SECTORS, 0);
-SHOW_FUNCTION_PER_GROUP(io_service_bytes, BLKIO_STAT_SERVICE_BYTES, 1);
-SHOW_FUNCTION_PER_GROUP(io_serviced, BLKIO_STAT_SERVICED, 1);
-SHOW_FUNCTION_PER_GROUP(io_service_time, BLKIO_STAT_SERVICE_TIME, 1);
-SHOW_FUNCTION_PER_GROUP(io_wait_time, BLKIO_STAT_WAIT_TIME, 1);
-SHOW_FUNCTION_PER_GROUP(io_merged, BLKIO_STAT_MERGED, 1);
-SHOW_FUNCTION_PER_GROUP(io_queued, BLKIO_STAT_QUEUED, 1);
-#ifdef CONFIG_DEBUG_BLK_CGROUP
-SHOW_FUNCTION_PER_GROUP(dequeue, BLKIO_STAT_DEQUEUE, 0);
-SHOW_FUNCTION_PER_GROUP(avg_queue_size, BLKIO_STAT_AVG_QUEUE_SIZE, 0);
-SHOW_FUNCTION_PER_GROUP(group_wait_time, BLKIO_STAT_GROUP_WAIT_TIME, 0);
-SHOW_FUNCTION_PER_GROUP(idle_time, BLKIO_STAT_IDLE_TIME, 0);
-SHOW_FUNCTION_PER_GROUP(empty_time, BLKIO_STAT_EMPTY_TIME, 0);
-#endif
-#undef SHOW_FUNCTION_PER_GROUP
-
 static int blkio_check_dev_num(dev_t dev)
 {
 	int part = 0;
@@ -652,13 +652,14 @@
 }
 
 static int blkio_policy_parse_and_set(char *buf,
-				      struct blkio_policy_node *newpn)
+	struct blkio_policy_node *newpn, enum blkio_policy_id plid, int fileid)
 {
 	char *s[4], *p, *major_s = NULL, *minor_s = NULL;
 	int ret;
 	unsigned long major, minor, temp;
 	int i = 0;
 	dev_t dev;
+	u64 bps, iops;
 
 	memset(s, 0, sizeof(s));
 
@@ -705,12 +706,47 @@
 	if (s[1] == NULL)
 		return -EINVAL;
 
-	ret = strict_strtoul(s[1], 10, &temp);
-	if (ret || (temp < BLKIO_WEIGHT_MIN && temp > 0) ||
-	    temp > BLKIO_WEIGHT_MAX)
-		return -EINVAL;
+	switch (plid) {
+	case BLKIO_POLICY_PROP:
+		ret = strict_strtoul(s[1], 10, &temp);
+		if (ret || (temp < BLKIO_WEIGHT_MIN && temp > 0) ||
+			temp > BLKIO_WEIGHT_MAX)
+			return -EINVAL;
 
-	newpn->weight =  temp;
+		newpn->plid = plid;
+		newpn->fileid = fileid;
+		newpn->val.weight = temp;
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(fileid) {
+		case BLKIO_THROTL_read_bps_device:
+		case BLKIO_THROTL_write_bps_device:
+			ret = strict_strtoull(s[1], 10, &bps);
+			if (ret)
+				return -EINVAL;
+
+			newpn->plid = plid;
+			newpn->fileid = fileid;
+			newpn->val.bps = bps;
+			break;
+		case BLKIO_THROTL_read_iops_device:
+		case BLKIO_THROTL_write_iops_device:
+			ret = strict_strtoull(s[1], 10, &iops);
+			if (ret)
+				return -EINVAL;
+
+			if (iops > THROTL_IOPS_MAX)
+				return -EINVAL;
+
+			newpn->plid = plid;
+			newpn->fileid = fileid;
+			newpn->val.iops = (unsigned int)iops;
+			break;
+		}
+		break;
+	default:
+		BUG();
+	}
 
 	return 0;
 }
@@ -720,26 +756,180 @@
 {
 	struct blkio_policy_node *pn;
 
-	pn = blkio_policy_search_node(blkcg, dev);
+	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_PROP,
+				BLKIO_PROP_weight_device);
 	if (pn)
-		return pn->weight;
+		return pn->val.weight;
 	else
 		return blkcg->weight;
 }
 EXPORT_SYMBOL_GPL(blkcg_get_weight);
 
+uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg, dev_t dev)
+{
+	struct blkio_policy_node *pn;
 
-static int blkiocg_weight_device_write(struct cgroup *cgrp, struct cftype *cft,
-				       const char *buffer)
+	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_read_bps_device);
+	if (pn)
+		return pn->val.bps;
+	else
+		return -1;
+}
+
+uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg, dev_t dev)
+{
+	struct blkio_policy_node *pn;
+	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_write_bps_device);
+	if (pn)
+		return pn->val.bps;
+	else
+		return -1;
+}
+
+unsigned int blkcg_get_read_iops(struct blkio_cgroup *blkcg, dev_t dev)
+{
+	struct blkio_policy_node *pn;
+
+	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_read_iops_device);
+	if (pn)
+		return pn->val.iops;
+	else
+		return -1;
+}
+
+unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg, dev_t dev)
+{
+	struct blkio_policy_node *pn;
+	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_write_iops_device);
+	if (pn)
+		return pn->val.iops;
+	else
+		return -1;
+}
+
+/* Checks whether user asked for deleting a policy rule */
+static bool blkio_delete_rule_command(struct blkio_policy_node *pn)
+{
+	switch(pn->plid) {
+	case BLKIO_POLICY_PROP:
+		if (pn->val.weight == 0)
+			return 1;
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(pn->fileid) {
+		case BLKIO_THROTL_read_bps_device:
+		case BLKIO_THROTL_write_bps_device:
+			if (pn->val.bps == 0)
+				return 1;
+			break;
+		case BLKIO_THROTL_read_iops_device:
+		case BLKIO_THROTL_write_iops_device:
+			if (pn->val.iops == 0)
+				return 1;
+		}
+		break;
+	default:
+		BUG();
+	}
+
+	return 0;
+}
+
+static void blkio_update_policy_rule(struct blkio_policy_node *oldpn,
+					struct blkio_policy_node *newpn)
+{
+	switch(oldpn->plid) {
+	case BLKIO_POLICY_PROP:
+		oldpn->val.weight = newpn->val.weight;
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(newpn->fileid) {
+		case BLKIO_THROTL_read_bps_device:
+		case BLKIO_THROTL_write_bps_device:
+			oldpn->val.bps = newpn->val.bps;
+			break;
+		case BLKIO_THROTL_read_iops_device:
+		case BLKIO_THROTL_write_iops_device:
+			oldpn->val.iops = newpn->val.iops;
+		}
+		break;
+	default:
+		BUG();
+	}
+}
+
+/*
+ * Some rules/values in blkg have changed. Propogate those to respective
+ * policies.
+ */
+static void blkio_update_blkg_policy(struct blkio_cgroup *blkcg,
+		struct blkio_group *blkg, struct blkio_policy_node *pn)
+{
+	unsigned int weight, iops;
+	u64 bps;
+
+	switch(pn->plid) {
+	case BLKIO_POLICY_PROP:
+		weight = pn->val.weight ? pn->val.weight :
+				blkcg->weight;
+		blkio_update_group_weight(blkg, weight);
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(pn->fileid) {
+		case BLKIO_THROTL_read_bps_device:
+		case BLKIO_THROTL_write_bps_device:
+			bps = pn->val.bps ? pn->val.bps : (-1);
+			blkio_update_group_bps(blkg, bps, pn->fileid);
+			break;
+		case BLKIO_THROTL_read_iops_device:
+		case BLKIO_THROTL_write_iops_device:
+			iops = pn->val.iops ? pn->val.iops : (-1);
+			blkio_update_group_iops(blkg, iops, pn->fileid);
+			break;
+		}
+		break;
+	default:
+		BUG();
+	}
+}
+
+/*
+ * A policy node rule has been updated. Propogate this update to all the
+ * block groups which might be affected by this update.
+ */
+static void blkio_update_policy_node_blkg(struct blkio_cgroup *blkcg,
+				struct blkio_policy_node *pn)
+{
+	struct blkio_group *blkg;
+	struct hlist_node *n;
+
+	spin_lock(&blkio_list_lock);
+	spin_lock_irq(&blkcg->lock);
+
+	hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
+		if (pn->dev != blkg->dev || pn->plid != blkg->plid)
+			continue;
+		blkio_update_blkg_policy(blkcg, blkg, pn);
+	}
+
+	spin_unlock_irq(&blkcg->lock);
+	spin_unlock(&blkio_list_lock);
+}
+
+static int blkiocg_file_write(struct cgroup *cgrp, struct cftype *cft,
+ 				       const char *buffer)
 {
 	int ret = 0;
 	char *buf;
 	struct blkio_policy_node *newpn, *pn;
 	struct blkio_cgroup *blkcg;
-	struct blkio_group *blkg;
 	int keep_newpn = 0;
-	struct hlist_node *n;
-	struct blkio_policy_type *blkiop;
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int fileid = BLKIOFILE_ATTR(cft->private);
 
 	buf = kstrdup(buffer, GFP_KERNEL);
 	if (!buf)
@@ -751,7 +941,7 @@
 		goto free_buf;
 	}
 
-	ret = blkio_policy_parse_and_set(buf, newpn);
+	ret = blkio_policy_parse_and_set(buf, newpn, plid, fileid);
 	if (ret)
 		goto free_newpn;
 
@@ -759,9 +949,9 @@
 
 	spin_lock_irq(&blkcg->lock);
 
-	pn = blkio_policy_search_node(blkcg, newpn->dev);
+	pn = blkio_policy_search_node(blkcg, newpn->dev, plid, fileid);
 	if (!pn) {
-		if (newpn->weight != 0) {
+		if (!blkio_delete_rule_command(newpn)) {
 			blkio_policy_insert_node(blkcg, newpn);
 			keep_newpn = 1;
 		}
@@ -769,33 +959,17 @@
 		goto update_io_group;
 	}
 
-	if (newpn->weight == 0) {
-		/* weight == 0 means deleteing a specific weight */
+	if (blkio_delete_rule_command(newpn)) {
 		blkio_policy_delete_node(pn);
 		spin_unlock_irq(&blkcg->lock);
 		goto update_io_group;
 	}
 	spin_unlock_irq(&blkcg->lock);
 
-	pn->weight = newpn->weight;
+	blkio_update_policy_rule(pn, newpn);
 
 update_io_group:
-	/* update weight for each cfqg */
-	spin_lock(&blkio_list_lock);
-	spin_lock_irq(&blkcg->lock);
-
-	hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
-		if (newpn->dev == blkg->dev) {
-			list_for_each_entry(blkiop, &blkio_list, list)
-				blkiop->ops.blkio_update_group_weight_fn(blkg,
-							 newpn->weight ?
-							 newpn->weight :
-							 blkcg->weight);
-		}
-	}
-
-	spin_unlock_irq(&blkcg->lock);
-	spin_unlock(&blkio_list_lock);
+	blkio_update_policy_node_blkg(blkcg, newpn);
 
 free_newpn:
 	if (!keep_newpn)
@@ -805,23 +979,256 @@
 	return ret;
 }
 
-static int blkiocg_weight_device_read(struct cgroup *cgrp, struct cftype *cft,
-				      struct seq_file *m)
+static void
+blkio_print_policy_node(struct seq_file *m, struct blkio_policy_node *pn)
 {
-	struct blkio_cgroup *blkcg;
+	switch(pn->plid) {
+		case BLKIO_POLICY_PROP:
+			if (pn->fileid == BLKIO_PROP_weight_device)
+				seq_printf(m, "%u:%u\t%u\n", MAJOR(pn->dev),
+					MINOR(pn->dev), pn->val.weight);
+			break;
+		case BLKIO_POLICY_THROTL:
+			switch(pn->fileid) {
+			case BLKIO_THROTL_read_bps_device:
+			case BLKIO_THROTL_write_bps_device:
+				seq_printf(m, "%u:%u\t%llu\n", MAJOR(pn->dev),
+					MINOR(pn->dev), pn->val.bps);
+				break;
+			case BLKIO_THROTL_read_iops_device:
+			case BLKIO_THROTL_write_iops_device:
+				seq_printf(m, "%u:%u\t%u\n", MAJOR(pn->dev),
+					MINOR(pn->dev), pn->val.iops);
+				break;
+			}
+			break;
+		default:
+			BUG();
+	}
+}
+
+/* cgroup files which read their data from policy nodes end up here */
+static void blkio_read_policy_node_files(struct cftype *cft,
+			struct blkio_cgroup *blkcg, struct seq_file *m)
+{
 	struct blkio_policy_node *pn;
 
-	seq_printf(m, "dev\tweight\n");
-
-	blkcg = cgroup_to_blkio_cgroup(cgrp);
 	if (!list_empty(&blkcg->policy_list)) {
 		spin_lock_irq(&blkcg->lock);
 		list_for_each_entry(pn, &blkcg->policy_list, node) {
-			seq_printf(m, "%u:%u\t%u\n", MAJOR(pn->dev),
-				   MINOR(pn->dev), pn->weight);
+			if (!pn_matches_cftype(cft, pn))
+				continue;
+			blkio_print_policy_node(m, pn);
 		}
 		spin_unlock_irq(&blkcg->lock);
 	}
+}
+
+static int blkiocg_file_read(struct cgroup *cgrp, struct cftype *cft,
+				struct seq_file *m)
+{
+	struct blkio_cgroup *blkcg;
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int name = BLKIOFILE_ATTR(cft->private);
+
+	blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+	switch(plid) {
+	case BLKIO_POLICY_PROP:
+		switch(name) {
+		case BLKIO_PROP_weight_device:
+			blkio_read_policy_node_files(cft, blkcg, m);
+			return 0;
+		default:
+			BUG();
+		}
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(name){
+		case BLKIO_THROTL_read_bps_device:
+		case BLKIO_THROTL_write_bps_device:
+		case BLKIO_THROTL_read_iops_device:
+		case BLKIO_THROTL_write_iops_device:
+			blkio_read_policy_node_files(cft, blkcg, m);
+			return 0;
+		default:
+			BUG();
+		}
+		break;
+	default:
+		BUG();
+	}
+
+	return 0;
+}
+
+static int blkio_read_blkg_stats(struct blkio_cgroup *blkcg,
+		struct cftype *cft, struct cgroup_map_cb *cb, enum stat_type type,
+		bool show_total)
+{
+	struct blkio_group *blkg;
+	struct hlist_node *n;
+	uint64_t cgroup_total = 0;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(blkg, n, &blkcg->blkg_list, blkcg_node) {
+		if (blkg->dev) {
+			if (!cftype_blkg_same_policy(cft, blkg))
+				continue;
+			spin_lock_irq(&blkg->stats_lock);
+			cgroup_total += blkio_get_stat(blkg, cb, blkg->dev,
+						type);
+			spin_unlock_irq(&blkg->stats_lock);
+		}
+	}
+	if (show_total)
+		cb->fill(cb, "Total", cgroup_total);
+	rcu_read_unlock();
+	return 0;
+}
+
+/* All map kind of cgroup file get serviced by this function */
+static int blkiocg_file_read_map(struct cgroup *cgrp, struct cftype *cft,
+				struct cgroup_map_cb *cb)
+{
+	struct blkio_cgroup *blkcg;
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int name = BLKIOFILE_ATTR(cft->private);
+
+	blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+	switch(plid) {
+	case BLKIO_POLICY_PROP:
+		switch(name) {
+		case BLKIO_PROP_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_TIME, 0);
+		case BLKIO_PROP_sectors:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SECTORS, 0);
+		case BLKIO_PROP_io_service_bytes:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SERVICE_BYTES, 1);
+		case BLKIO_PROP_io_serviced:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SERVICED, 1);
+		case BLKIO_PROP_io_service_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SERVICE_TIME, 1);
+		case BLKIO_PROP_io_wait_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_WAIT_TIME, 1);
+		case BLKIO_PROP_io_merged:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_MERGED, 1);
+		case BLKIO_PROP_io_queued:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_QUEUED, 1);
+#ifdef CONFIG_DEBUG_BLK_CGROUP
+		case BLKIO_PROP_dequeue:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_DEQUEUE, 0);
+		case BLKIO_PROP_avg_queue_size:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_AVG_QUEUE_SIZE, 0);
+		case BLKIO_PROP_group_wait_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_GROUP_WAIT_TIME, 0);
+		case BLKIO_PROP_idle_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_IDLE_TIME, 0);
+		case BLKIO_PROP_empty_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_EMPTY_TIME, 0);
+#endif
+		default:
+			BUG();
+		}
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(name){
+		case BLKIO_THROTL_io_service_bytes:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SERVICE_BYTES, 1);
+		case BLKIO_THROTL_io_serviced:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SERVICED, 1);
+		default:
+			BUG();
+		}
+		break;
+	default:
+		BUG();
+	}
+
+	return 0;
+}
+
+static int blkio_weight_write(struct blkio_cgroup *blkcg, u64 val)
+{
+	struct blkio_group *blkg;
+	struct hlist_node *n;
+	struct blkio_policy_node *pn;
+
+	if (val < BLKIO_WEIGHT_MIN || val > BLKIO_WEIGHT_MAX)
+		return -EINVAL;
+
+	spin_lock(&blkio_list_lock);
+	spin_lock_irq(&blkcg->lock);
+	blkcg->weight = (unsigned int)val;
+
+	hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
+		pn = blkio_policy_search_node(blkcg, blkg->dev,
+				BLKIO_POLICY_PROP, BLKIO_PROP_weight_device);
+		if (pn)
+			continue;
+
+		blkio_update_group_weight(blkg, blkcg->weight);
+	}
+	spin_unlock_irq(&blkcg->lock);
+	spin_unlock(&blkio_list_lock);
+	return 0;
+}
+
+static u64 blkiocg_file_read_u64 (struct cgroup *cgrp, struct cftype *cft) {
+	struct blkio_cgroup *blkcg;
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int name = BLKIOFILE_ATTR(cft->private);
+
+	blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+	switch(plid) {
+	case BLKIO_POLICY_PROP:
+		switch(name) {
+		case BLKIO_PROP_weight:
+			return (u64)blkcg->weight;
+		}
+		break;
+	default:
+		BUG();
+	}
+	return 0;
+}
+
+static int
+blkiocg_file_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
+{
+	struct blkio_cgroup *blkcg;
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int name = BLKIOFILE_ATTR(cft->private);
+
+	blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+	switch(plid) {
+	case BLKIO_POLICY_PROP:
+		switch(name) {
+		case BLKIO_PROP_weight:
+			return blkio_weight_write(blkcg, val);
+		}
+		break;
+	default:
+		BUG();
+	}
 
 	return 0;
 }
@@ -829,71 +1236,151 @@
 struct cftype blkio_files[] = {
 	{
 		.name = "weight_device",
-		.read_seq_string = blkiocg_weight_device_read,
-		.write_string = blkiocg_weight_device_write,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_weight_device),
+		.read_seq_string = blkiocg_file_read,
+		.write_string = blkiocg_file_write,
 		.max_write_len = 256,
 	},
 	{
 		.name = "weight",
-		.read_u64 = blkiocg_weight_read,
-		.write_u64 = blkiocg_weight_write,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_weight),
+		.read_u64 = blkiocg_file_read_u64,
+		.write_u64 = blkiocg_file_write_u64,
 	},
 	{
 		.name = "time",
-		.read_map = blkiocg_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "sectors",
-		.read_map = blkiocg_sectors_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_sectors),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_service_bytes",
-		.read_map = blkiocg_io_service_bytes_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_service_bytes),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_serviced",
-		.read_map = blkiocg_io_serviced_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_serviced),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_service_time",
-		.read_map = blkiocg_io_service_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_service_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_wait_time",
-		.read_map = blkiocg_io_wait_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_wait_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_merged",
-		.read_map = blkiocg_io_merged_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_merged),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_queued",
-		.read_map = blkiocg_io_queued_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_queued),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "reset_stats",
 		.write_u64 = blkiocg_reset_stats,
 	},
+#ifdef CONFIG_BLK_DEV_THROTTLING
+	{
+		.name = "throttle.read_bps_device",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_read_bps_device),
+		.read_seq_string = blkiocg_file_read,
+		.write_string = blkiocg_file_write,
+		.max_write_len = 256,
+	},
+
+	{
+		.name = "throttle.write_bps_device",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_write_bps_device),
+		.read_seq_string = blkiocg_file_read,
+		.write_string = blkiocg_file_write,
+		.max_write_len = 256,
+	},
+
+	{
+		.name = "throttle.read_iops_device",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_read_iops_device),
+		.read_seq_string = blkiocg_file_read,
+		.write_string = blkiocg_file_write,
+		.max_write_len = 256,
+	},
+
+	{
+		.name = "throttle.write_iops_device",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_write_iops_device),
+		.read_seq_string = blkiocg_file_read,
+		.write_string = blkiocg_file_write,
+		.max_write_len = 256,
+	},
+	{
+		.name = "throttle.io_service_bytes",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_io_service_bytes),
+		.read_map = blkiocg_file_read_map,
+	},
+	{
+		.name = "throttle.io_serviced",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_io_serviced),
+		.read_map = blkiocg_file_read_map,
+	},
+#endif /* CONFIG_BLK_DEV_THROTTLING */
+
 #ifdef CONFIG_DEBUG_BLK_CGROUP
 	{
 		.name = "avg_queue_size",
-		.read_map = blkiocg_avg_queue_size_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_avg_queue_size),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "group_wait_time",
-		.read_map = blkiocg_group_wait_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_group_wait_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "idle_time",
-		.read_map = blkiocg_idle_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_idle_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "empty_time",
-		.read_map = blkiocg_empty_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_empty_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "dequeue",
-		.read_map = blkiocg_dequeue_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_dequeue),
+		.read_map = blkiocg_file_read_map,
 	},
 #endif
 };
@@ -932,13 +1419,14 @@
 		/*
 		 * This blkio_group is being unlinked as associated cgroup is
 		 * going away. Let all the IO controlling policies know about
-		 * this event. Currently this is static call to one io
-		 * controlling policy. Once we have more policies in place, we
-		 * need some dynamic registration of callback function.
+		 * this event.
 		 */
 		spin_lock(&blkio_list_lock);
-		list_for_each_entry(blkiop, &blkio_list, list)
+		list_for_each_entry(blkiop, &blkio_list, list) {
+			if (blkiop->plid != blkg->plid)
+				continue;
 			blkiop->ops.blkio_unlink_group_fn(key, blkg);
+		}
 		spin_unlock(&blkio_list_lock);
 	} while (1);
 
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 2b866ec..ea4861b 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -15,6 +15,14 @@
 
 #include <linux/cgroup.h>
 
+enum blkio_policy_id {
+	BLKIO_POLICY_PROP = 0,		/* Proportional Bandwidth division */
+	BLKIO_POLICY_THROTL,		/* Throttling */
+};
+
+/* Max limits for throttle policy */
+#define THROTL_IOPS_MAX		UINT_MAX
+
 #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
 
 #ifndef CONFIG_BLK_CGROUP
@@ -65,6 +73,35 @@
 	BLKG_empty,
 };
 
+/* cgroup files owned by proportional weight policy */
+enum blkcg_file_name_prop {
+	BLKIO_PROP_weight = 1,
+	BLKIO_PROP_weight_device,
+	BLKIO_PROP_io_service_bytes,
+	BLKIO_PROP_io_serviced,
+	BLKIO_PROP_time,
+	BLKIO_PROP_sectors,
+	BLKIO_PROP_io_service_time,
+	BLKIO_PROP_io_wait_time,
+	BLKIO_PROP_io_merged,
+	BLKIO_PROP_io_queued,
+	BLKIO_PROP_avg_queue_size,
+	BLKIO_PROP_group_wait_time,
+	BLKIO_PROP_idle_time,
+	BLKIO_PROP_empty_time,
+	BLKIO_PROP_dequeue,
+};
+
+/* cgroup files owned by throttle policy */
+enum blkcg_file_name_throtl {
+	BLKIO_THROTL_read_bps_device,
+	BLKIO_THROTL_write_bps_device,
+	BLKIO_THROTL_read_iops_device,
+	BLKIO_THROTL_write_iops_device,
+	BLKIO_THROTL_io_service_bytes,
+	BLKIO_THROTL_io_serviced,
+};
+
 struct blkio_cgroup {
 	struct cgroup_subsys_state css;
 	unsigned int weight;
@@ -112,6 +149,8 @@
 	char path[128];
 	/* The device MKDEV(major, minor), this group has been created for */
 	dev_t dev;
+	/* policy which owns this blk group */
+	enum blkio_policy_id plid;
 
 	/* Need to serialize the stats in the case of reset/update */
 	spinlock_t stats_lock;
@@ -121,24 +160,60 @@
 struct blkio_policy_node {
 	struct list_head node;
 	dev_t dev;
-	unsigned int weight;
+	/* This node belongs to max bw policy or porportional weight policy */
+	enum blkio_policy_id plid;
+	/* cgroup file to which this rule belongs to */
+	int fileid;
+
+	union {
+		unsigned int weight;
+		/*
+		 * Rate read/write in terms of byptes per second
+		 * Whether this rate represents read or write is determined
+		 * by file type "fileid".
+		 */
+		u64 bps;
+		unsigned int iops;
+	} val;
 };
 
 extern unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg,
 				     dev_t dev);
+extern uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg,
+				     dev_t dev);
+extern uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg,
+				     dev_t dev);
+extern unsigned int blkcg_get_read_iops(struct blkio_cgroup *blkcg,
+				     dev_t dev);
+extern unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg,
+				     dev_t dev);
 
 typedef void (blkio_unlink_group_fn) (void *key, struct blkio_group *blkg);
-typedef void (blkio_update_group_weight_fn) (struct blkio_group *blkg,
-						unsigned int weight);
+
+typedef void (blkio_update_group_weight_fn) (void *key,
+			struct blkio_group *blkg, unsigned int weight);
+typedef void (blkio_update_group_read_bps_fn) (void * key,
+			struct blkio_group *blkg, u64 read_bps);
+typedef void (blkio_update_group_write_bps_fn) (void *key,
+			struct blkio_group *blkg, u64 write_bps);
+typedef void (blkio_update_group_read_iops_fn) (void *key,
+			struct blkio_group *blkg, unsigned int read_iops);
+typedef void (blkio_update_group_write_iops_fn) (void *key,
+			struct blkio_group *blkg, unsigned int write_iops);
 
 struct blkio_policy_ops {
 	blkio_unlink_group_fn *blkio_unlink_group_fn;
 	blkio_update_group_weight_fn *blkio_update_group_weight_fn;
+	blkio_update_group_read_bps_fn *blkio_update_group_read_bps_fn;
+	blkio_update_group_write_bps_fn *blkio_update_group_write_bps_fn;
+	blkio_update_group_read_iops_fn *blkio_update_group_read_iops_fn;
+	blkio_update_group_write_iops_fn *blkio_update_group_write_iops_fn;
 };
 
 struct blkio_policy_type {
 	struct list_head list;
 	struct blkio_policy_ops ops;
+	enum blkio_policy_id plid;
 };
 
 /* Blkio controller policy registration */
@@ -212,7 +287,8 @@
 extern struct blkio_cgroup blkio_root_cgroup;
 extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup);
 extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
-			struct blkio_group *blkg, void *key, dev_t dev);
+	struct blkio_group *blkg, void *key, dev_t dev,
+	enum blkio_policy_id plid);
 extern int blkiocg_del_blkio_group(struct blkio_group *blkg);
 extern struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg,
 						void *key);
@@ -234,7 +310,8 @@
 cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; }
 
 static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
-			struct blkio_group *blkg, void *key, dev_t dev) {}
+		struct blkio_group *blkg, void *key, dev_t dev,
+		enum blkio_policy_id plid) {}
 
 static inline int
 blkiocg_del_blkio_group(struct blkio_group *blkg) { return 0; }
diff --git a/block/blk-core.c b/block/blk-core.c
index 32a1c12..51efd83 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -64,13 +64,15 @@
 		return;
 
 	cpu = part_stat_lock();
-	part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
 
-	if (!new_io)
+	if (!new_io) {
+		part = rq->part;
 		part_stat_inc(cpu, part, merges[rw]);
-	else {
+	} else {
+		part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
 		part_round_stats(cpu, part);
 		part_inc_in_flight(part, rw);
+		rq->part = part;
 	}
 
 	part_stat_unlock();
@@ -128,6 +130,7 @@
 	rq->ref_count = 1;
 	rq->start_time = jiffies;
 	set_start_time_ns(rq);
+	rq->part = NULL;
 }
 EXPORT_SYMBOL(blk_rq_init);
 
@@ -136,7 +139,7 @@
 {
 	struct request_queue *q = rq->q;
 
-	if (&q->bar_rq != rq) {
+	if (&q->flush_rq != rq) {
 		if (error)
 			clear_bit(BIO_UPTODATE, &bio->bi_flags);
 		else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
@@ -160,13 +163,12 @@
 		if (bio->bi_size == 0)
 			bio_endio(bio, error);
 	} else {
-
 		/*
-		 * Okay, this is the barrier request in progress, just
-		 * record the error;
+		 * Okay, this is the sequenced flush request in
+		 * progress, just record the error;
 		 */
-		if (error && !q->orderr)
-			q->orderr = error;
+		if (error && !q->flush_err)
+			q->flush_err = error;
 	}
 }
 
@@ -382,6 +384,7 @@
 	del_timer_sync(&q->unplug_timer);
 	del_timer_sync(&q->timeout);
 	cancel_work_sync(&q->unplug_work);
+	throtl_shutdown_timer_wq(q);
 }
 EXPORT_SYMBOL(blk_sync_queue);
 
@@ -515,11 +518,17 @@
 		return NULL;
 	}
 
+	if (blk_throtl_init(q)) {
+		kmem_cache_free(blk_requestq_cachep, q);
+		return NULL;
+	}
+
 	setup_timer(&q->backing_dev_info.laptop_mode_wb_timer,
 		    laptop_mode_timer_fn, (unsigned long) q);
 	init_timer(&q->unplug_timer);
 	setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q);
 	INIT_LIST_HEAD(&q->timeout_list);
+	INIT_LIST_HEAD(&q->pending_flushes);
 	INIT_WORK(&q->unplug_work, blk_unplug_work);
 
 	kobject_init(&q->kobj, &blk_queue_ktype);
@@ -796,11 +805,16 @@
 	rl->starved[is_sync] = 0;
 
 	priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-	if (priv)
+	if (priv) {
 		rl->elvpriv++;
 
-	if (blk_queue_io_stat(q))
-		rw_flags |= REQ_IO_STAT;
+		/*
+		 * Don't do stats for non-priv requests
+		 */
+		if (blk_queue_io_stat(q))
+			rw_flags |= REQ_IO_STAT;
+	}
+
 	spin_unlock_irq(q->queue_lock);
 
 	rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
@@ -1037,22 +1051,6 @@
 }
 EXPORT_SYMBOL(blk_insert_request);
 
-/*
- * add-request adds a request to the linked list.
- * queue lock is held and interrupts disabled, as we muck with the
- * request queue list.
- */
-static inline void add_request(struct request_queue *q, struct request *req)
-{
-	drive_stat_acct(req, 1);
-
-	/*
-	 * elevator indicated where it wants this request to be
-	 * inserted at elevator_merge time
-	 */
-	__elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0);
-}
-
 static void part_round_stats_single(int cpu, struct hd_struct *part,
 				    unsigned long now)
 {
@@ -1201,13 +1199,16 @@
 	const bool sync = !!(bio->bi_rw & REQ_SYNC);
 	const bool unplug = !!(bio->bi_rw & REQ_UNPLUG);
 	const unsigned long ff = bio->bi_rw & REQ_FAILFAST_MASK;
+	int where = ELEVATOR_INSERT_SORT;
 	int rw_flags;
 
-	if ((bio->bi_rw & REQ_HARDBARRIER) &&
-	    (q->next_ordered == QUEUE_ORDERED_NONE)) {
+	/* REQ_HARDBARRIER is no more */
+	if (WARN_ONCE(bio->bi_rw & REQ_HARDBARRIER,
+		"block: HARDBARRIER is deprecated, use FLUSH/FUA instead\n")) {
 		bio_endio(bio, -EOPNOTSUPP);
 		return 0;
 	}
+
 	/*
 	 * low level driver can indicate that it wants pages above a
 	 * certain limit bounced to low memory (ie for highmem, or even
@@ -1217,7 +1218,12 @@
 
 	spin_lock_irq(q->queue_lock);
 
-	if (unlikely((bio->bi_rw & REQ_HARDBARRIER)) || elv_queue_empty(q))
+	if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+		where = ELEVATOR_INSERT_FRONT;
+		goto get_rq;
+	}
+
+	if (elv_queue_empty(q))
 		goto get_rq;
 
 	el_ret = elv_merge(q, &req, bio);
@@ -1314,7 +1320,10 @@
 		req->cpu = blk_cpu_to_group(smp_processor_id());
 	if (queue_should_plug(q) && elv_queue_empty(q))
 		blk_plug_device(q);
-	add_request(q, req);
+
+	/* insert the request into the elevator */
+	drive_stat_acct(req, 1);
+	__elv_add_request(q, req, where, 0);
 out:
 	if (unplug || !queue_should_plug(q))
 		__generic_unplug_device(q);
@@ -1514,6 +1523,19 @@
 		if (bio_check_eod(bio, nr_sectors))
 			goto end_io;
 
+		/*
+		 * Filter flush bio's early so that make_request based
+		 * drivers without flush support don't have to worry
+		 * about them.
+		 */
+		if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) {
+			bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA);
+			if (!nr_sectors) {
+				err = 0;
+				goto end_io;
+			}
+		}
+
 		if ((bio->bi_rw & REQ_DISCARD) &&
 		    (!blk_queue_discard(q) ||
 		     ((bio->bi_rw & REQ_SECURE) &&
@@ -1522,6 +1544,15 @@
 			goto end_io;
 		}
 
+		blk_throtl_bio(q, &bio);
+
+		/*
+		 * If bio = NULL, bio has been throttled and will be submitted
+		 * later.
+		 */
+		if (!bio)
+			break;
+
 		trace_block_bio_queue(q, bio);
 
 		ret = q->make_request_fn(q, bio);
@@ -1612,11 +1643,12 @@
 
 		if (unlikely(block_dump)) {
 			char b[BDEVNAME_SIZE];
-			printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n",
+			printk(KERN_DEBUG "%s(%d): %s block %Lu on %s (%u sectors)\n",
 			current->comm, task_pid_nr(current),
 				(rw & WRITE) ? "WRITE" : "READ",
 				(unsigned long long)bio->bi_sector,
-				bdevname(bio->bi_bdev, b));
+				bdevname(bio->bi_bdev, b),
+				count);
 		}
 	}
 
@@ -1759,7 +1791,7 @@
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+		part = req->part;
 		part_stat_add(cpu, part, sectors[rw], bytes >> 9);
 		part_stat_unlock();
 	}
@@ -1768,18 +1800,18 @@
 static void blk_account_io_done(struct request *req)
 {
 	/*
-	 * Account IO completion.  bar_rq isn't accounted as a normal
-	 * IO on queueing nor completion.  Accounting the containing
-	 * request is enough.
+	 * Account IO completion.  flush_rq isn't accounted as a
+	 * normal IO on queueing nor completion.  Accounting the
+	 * containing request is enough.
 	 */
-	if (blk_do_io_stat(req) && req != &req->q->bar_rq) {
+	if (blk_do_io_stat(req) && req != &req->q->flush_rq) {
 		unsigned long duration = jiffies - req->start_time;
 		const int rw = rq_data_dir(req);
 		struct hd_struct *part;
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+		part = req->part;
 
 		part_stat_inc(cpu, part, ios[rw]);
 		part_stat_add(cpu, part, ticks[rw], duration);
@@ -2497,9 +2529,7 @@
 static void __blk_rq_prep_clone(struct request *dst, struct request *src)
 {
 	dst->cpu = src->cpu;
-	dst->cmd_flags = (rq_data_dir(src) | REQ_NOMERGE);
-	if (src->cmd_flags & REQ_DISCARD)
-		dst->cmd_flags |= REQ_DISCARD;
+	dst->cmd_flags = (src->cmd_flags & REQ_CLONE_MASK) | REQ_NOMERGE;
 	dst->cmd_type = src->cmd_type;
 	dst->__sector = blk_rq_pos(src);
 	dst->__data_len = blk_rq_bytes(src);
@@ -2579,6 +2609,13 @@
 }
 EXPORT_SYMBOL(kblockd_schedule_work);
 
+int kblockd_schedule_delayed_work(struct request_queue *q,
+			struct delayed_work *dwork, unsigned long delay)
+{
+	return queue_delayed_work(kblockd_workqueue, dwork, delay);
+}
+EXPORT_SYMBOL(kblockd_schedule_delayed_work);
+
 int __init blk_dev_init(void)
 {
 	BUILD_BUG_ON(__REQ_NR_BITS > 8 *
diff --git a/block/blk-exec.c b/block/blk-exec.c
index e1672f1..cf1456a 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -80,6 +80,7 @@
 	DECLARE_COMPLETION_ONSTACK(wait);
 	char sense[SCSI_SENSE_BUFFERSIZE];
 	int err = 0;
+	unsigned long hang_check;
 
 	/*
 	 * we need an extra reference to the request, so we can look at
@@ -95,7 +96,13 @@
 
 	rq->end_io_data = &wait;
 	blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
-	wait_for_completion(&wait);
+
+	/* Prevent hang_check timer from firing at us during very long I/O */
+	hang_check = sysctl_hung_task_timeout_secs;
+	if (hang_check)
+		while (!wait_for_completion_timeout(&wait, hang_check * (HZ/2)));
+	else
+		wait_for_completion(&wait);
 
 	if (rq->errors)
 		err = -EIO;
diff --git a/block/blk-flush.c b/block/blk-flush.c
new file mode 100644
index 0000000..54b123d
--- /dev/null
+++ b/block/blk-flush.c
@@ -0,0 +1,262 @@
+/*
+ * Functions to sequence FLUSH and FUA writes.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/gfp.h>
+
+#include "blk.h"
+
+/* FLUSH/FUA sequences */
+enum {
+	QUEUE_FSEQ_STARTED	= (1 << 0), /* flushing in progress */
+	QUEUE_FSEQ_PREFLUSH	= (1 << 1), /* pre-flushing in progress */
+	QUEUE_FSEQ_DATA		= (1 << 2), /* data write in progress */
+	QUEUE_FSEQ_POSTFLUSH	= (1 << 3), /* post-flushing in progress */
+	QUEUE_FSEQ_DONE		= (1 << 4),
+};
+
+static struct request *queue_next_fseq(struct request_queue *q);
+
+unsigned blk_flush_cur_seq(struct request_queue *q)
+{
+	if (!q->flush_seq)
+		return 0;
+	return 1 << ffz(q->flush_seq);
+}
+
+static struct request *blk_flush_complete_seq(struct request_queue *q,
+					      unsigned seq, int error)
+{
+	struct request *next_rq = NULL;
+
+	if (error && !q->flush_err)
+		q->flush_err = error;
+
+	BUG_ON(q->flush_seq & seq);
+	q->flush_seq |= seq;
+
+	if (blk_flush_cur_seq(q) != QUEUE_FSEQ_DONE) {
+		/* not complete yet, queue the next flush sequence */
+		next_rq = queue_next_fseq(q);
+	} else {
+		/* complete this flush request */
+		__blk_end_request_all(q->orig_flush_rq, q->flush_err);
+		q->orig_flush_rq = NULL;
+		q->flush_seq = 0;
+
+		/* dispatch the next flush if there's one */
+		if (!list_empty(&q->pending_flushes)) {
+			next_rq = list_entry_rq(q->pending_flushes.next);
+			list_move(&next_rq->queuelist, &q->queue_head);
+		}
+	}
+	return next_rq;
+}
+
+static void blk_flush_complete_seq_end_io(struct request_queue *q,
+					  unsigned seq, int error)
+{
+	bool was_empty = elv_queue_empty(q);
+	struct request *next_rq;
+
+	next_rq = blk_flush_complete_seq(q, seq, error);
+
+	/*
+	 * Moving a request silently to empty queue_head may stall the
+	 * queue.  Kick the queue in those cases.
+	 */
+	if (was_empty && next_rq)
+		__blk_run_queue(q);
+}
+
+static void pre_flush_end_io(struct request *rq, int error)
+{
+	elv_completed_request(rq->q, rq);
+	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_PREFLUSH, error);
+}
+
+static void flush_data_end_io(struct request *rq, int error)
+{
+	elv_completed_request(rq->q, rq);
+	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_DATA, error);
+}
+
+static void post_flush_end_io(struct request *rq, int error)
+{
+	elv_completed_request(rq->q, rq);
+	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_POSTFLUSH, error);
+}
+
+static void init_flush_request(struct request *rq, struct gendisk *disk)
+{
+	rq->cmd_type = REQ_TYPE_FS;
+	rq->cmd_flags = WRITE_FLUSH;
+	rq->rq_disk = disk;
+}
+
+static struct request *queue_next_fseq(struct request_queue *q)
+{
+	struct request *orig_rq = q->orig_flush_rq;
+	struct request *rq = &q->flush_rq;
+
+	blk_rq_init(q, rq);
+
+	switch (blk_flush_cur_seq(q)) {
+	case QUEUE_FSEQ_PREFLUSH:
+		init_flush_request(rq, orig_rq->rq_disk);
+		rq->end_io = pre_flush_end_io;
+		break;
+	case QUEUE_FSEQ_DATA:
+		init_request_from_bio(rq, orig_rq->bio);
+		/*
+		 * orig_rq->rq_disk may be different from
+		 * bio->bi_bdev->bd_disk if orig_rq got here through
+		 * remapping drivers.  Make sure rq->rq_disk points
+		 * to the same one as orig_rq.
+		 */
+		rq->rq_disk = orig_rq->rq_disk;
+		rq->cmd_flags &= ~(REQ_FLUSH | REQ_FUA);
+		rq->cmd_flags |= orig_rq->cmd_flags & (REQ_FLUSH | REQ_FUA);
+		rq->end_io = flush_data_end_io;
+		break;
+	case QUEUE_FSEQ_POSTFLUSH:
+		init_flush_request(rq, orig_rq->rq_disk);
+		rq->end_io = post_flush_end_io;
+		break;
+	default:
+		BUG();
+	}
+
+	elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
+	return rq;
+}
+
+struct request *blk_do_flush(struct request_queue *q, struct request *rq)
+{
+	unsigned int fflags = q->flush_flags; /* may change, cache it */
+	bool has_flush = fflags & REQ_FLUSH, has_fua = fflags & REQ_FUA;
+	bool do_preflush = has_flush && (rq->cmd_flags & REQ_FLUSH);
+	bool do_postflush = has_flush && !has_fua && (rq->cmd_flags & REQ_FUA);
+	unsigned skip = 0;
+
+	/*
+	 * Special case.  If there's data but flush is not necessary,
+	 * the request can be issued directly.
+	 *
+	 * Flush w/o data should be able to be issued directly too but
+	 * currently some drivers assume that rq->bio contains
+	 * non-zero data if it isn't NULL and empty FLUSH requests
+	 * getting here usually have bio's without data.
+	 */
+	if (blk_rq_sectors(rq) && !do_preflush && !do_postflush) {
+		rq->cmd_flags &= ~REQ_FLUSH;
+		if (!has_fua)
+			rq->cmd_flags &= ~REQ_FUA;
+		return rq;
+	}
+
+	/*
+	 * Sequenced flushes can't be processed in parallel.  If
+	 * another one is already in progress, queue for later
+	 * processing.
+	 */
+	if (q->flush_seq) {
+		list_move_tail(&rq->queuelist, &q->pending_flushes);
+		return NULL;
+	}
+
+	/*
+	 * Start a new flush sequence
+	 */
+	q->flush_err = 0;
+	q->flush_seq |= QUEUE_FSEQ_STARTED;
+
+	/* adjust FLUSH/FUA of the original request and stash it away */
+	rq->cmd_flags &= ~REQ_FLUSH;
+	if (!has_fua)
+		rq->cmd_flags &= ~REQ_FUA;
+	blk_dequeue_request(rq);
+	q->orig_flush_rq = rq;
+
+	/* skip unneded sequences and return the first one */
+	if (!do_preflush)
+		skip |= QUEUE_FSEQ_PREFLUSH;
+	if (!blk_rq_sectors(rq))
+		skip |= QUEUE_FSEQ_DATA;
+	if (!do_postflush)
+		skip |= QUEUE_FSEQ_POSTFLUSH;
+	return blk_flush_complete_seq(q, skip, 0);
+}
+
+static void bio_end_flush(struct bio *bio, int err)
+{
+	if (err)
+		clear_bit(BIO_UPTODATE, &bio->bi_flags);
+	if (bio->bi_private)
+		complete(bio->bi_private);
+	bio_put(bio);
+}
+
+/**
+ * blkdev_issue_flush - queue a flush
+ * @bdev:	blockdev to issue flush for
+ * @gfp_mask:	memory allocation flags (for bio_alloc)
+ * @error_sector:	error sector
+ *
+ * Description:
+ *    Issue a flush for the block device in question. Caller can supply
+ *    room for storing the error offset in case of a flush error, if they
+ *    wish to. If WAIT flag is not passed then caller may check only what
+ *    request was pushed in some internal queue for later handling.
+ */
+int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
+		sector_t *error_sector)
+{
+	DECLARE_COMPLETION_ONSTACK(wait);
+	struct request_queue *q;
+	struct bio *bio;
+	int ret = 0;
+
+	if (bdev->bd_disk == NULL)
+		return -ENXIO;
+
+	q = bdev_get_queue(bdev);
+	if (!q)
+		return -ENXIO;
+
+	/*
+	 * some block devices may not have their queue correctly set up here
+	 * (e.g. loop device without a backing file) and so issuing a flush
+	 * here will panic. Ensure there is a request function before issuing
+	 * the flush.
+	 */
+	if (!q->make_request_fn)
+		return -ENXIO;
+
+	bio = bio_alloc(gfp_mask, 0);
+	bio->bi_end_io = bio_end_flush;
+	bio->bi_bdev = bdev;
+	bio->bi_private = &wait;
+
+	bio_get(bio);
+	submit_bio(WRITE_FLUSH, bio);
+	wait_for_completion(&wait);
+
+	/*
+	 * The driver must store the error location in ->bi_sector, if
+	 * it supports it. For non-stacked drivers, this should be
+	 * copied from blk_rq_pos(rq).
+	 */
+	if (error_sector)
+               *error_sector = bio->bi_sector;
+
+	if (!bio_flagged(bio, BIO_UPTODATE))
+		ret = -EIO;
+
+	bio_put(bio);
+	return ret;
+}
+EXPORT_SYMBOL(blkdev_issue_flush);
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index edce1ef..54bcba6 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -32,24 +32,37 @@
 
 /**
  * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements
- * @rq:		request with integrity metadata attached
+ * @q:		request queue
+ * @bio:	bio with integrity metadata attached
  *
  * Description: Returns the number of elements required in a
- * scatterlist corresponding to the integrity metadata in a request.
+ * scatterlist corresponding to the integrity metadata in a bio.
  */
-int blk_rq_count_integrity_sg(struct request *rq)
+int blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio)
 {
-	struct bio_vec *iv, *ivprv;
-	struct req_iterator iter;
-	unsigned int segments;
+	struct bio_vec *iv, *ivprv = NULL;
+	unsigned int segments = 0;
+	unsigned int seg_size = 0;
+	unsigned int i = 0;
 
-	ivprv = NULL;
-	segments = 0;
+	bio_for_each_integrity_vec(iv, bio, i) {
 
-	rq_for_each_integrity_segment(iv, rq, iter) {
+		if (ivprv) {
+			if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv))
+				goto new_segment;
 
-		if (!ivprv || !BIOVEC_PHYS_MERGEABLE(ivprv, iv))
+			if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv))
+				goto new_segment;
+
+			if (seg_size + iv->bv_len > queue_max_segment_size(q))
+				goto new_segment;
+
+			seg_size += iv->bv_len;
+		} else {
+new_segment:
 			segments++;
+			seg_size = iv->bv_len;
+		}
 
 		ivprv = iv;
 	}
@@ -60,30 +73,34 @@
 
 /**
  * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
- * @rq:		request with integrity metadata attached
+ * @q:		request queue
+ * @bio:	bio with integrity metadata attached
  * @sglist:	target scatterlist
  *
  * Description: Map the integrity vectors in request into a
  * scatterlist.  The scatterlist must be big enough to hold all
  * elements.  I.e. sized using blk_rq_count_integrity_sg().
  */
-int blk_rq_map_integrity_sg(struct request *rq, struct scatterlist *sglist)
+int blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio,
+			    struct scatterlist *sglist)
 {
-	struct bio_vec *iv, *ivprv;
-	struct req_iterator iter;
-	struct scatterlist *sg;
-	unsigned int segments;
+	struct bio_vec *iv, *ivprv = NULL;
+	struct scatterlist *sg = NULL;
+	unsigned int segments = 0;
+	unsigned int i = 0;
 
-	ivprv = NULL;
-	sg = NULL;
-	segments = 0;
-
-	rq_for_each_integrity_segment(iv, rq, iter) {
+	bio_for_each_integrity_vec(iv, bio, i) {
 
 		if (ivprv) {
 			if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv))
 				goto new_segment;
 
+			if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv))
+				goto new_segment;
+
+			if (sg->length + iv->bv_len > queue_max_segment_size(q))
+				goto new_segment;
+
 			sg->length += iv->bv_len;
 		} else {
 new_segment:
@@ -162,6 +179,40 @@
 }
 EXPORT_SYMBOL(blk_integrity_compare);
 
+int blk_integrity_merge_rq(struct request_queue *q, struct request *req,
+			   struct request *next)
+{
+	if (blk_integrity_rq(req) != blk_integrity_rq(next))
+		return -1;
+
+	if (req->nr_integrity_segments + next->nr_integrity_segments >
+	    q->limits.max_integrity_segments)
+		return -1;
+
+	return 0;
+}
+EXPORT_SYMBOL(blk_integrity_merge_rq);
+
+int blk_integrity_merge_bio(struct request_queue *q, struct request *req,
+			    struct bio *bio)
+{
+	int nr_integrity_segs;
+	struct bio *next = bio->bi_next;
+
+	bio->bi_next = NULL;
+	nr_integrity_segs = blk_rq_count_integrity_sg(q, bio);
+	bio->bi_next = next;
+
+	if (req->nr_integrity_segments + nr_integrity_segs >
+	    q->limits.max_integrity_segments)
+		return -1;
+
+	req->nr_integrity_segments += nr_integrity_segs;
+
+	return 0;
+}
+EXPORT_SYMBOL(blk_integrity_merge_bio);
+
 struct integrity_sysfs_entry {
 	struct attribute attr;
 	ssize_t (*show)(struct blk_integrity *, char *);
@@ -381,7 +432,6 @@
 	kobject_uevent(&bi->kobj, KOBJ_REMOVE);
 	kobject_del(&bi->kobj);
 	kobject_put(&bi->kobj);
-	kmem_cache_free(integrity_cachep, bi);
 	disk->integrity = NULL;
 }
 EXPORT_SYMBOL(blk_integrity_unregister);
diff --git a/block/blk-lib.c b/block/blk-lib.c
index c392029..1a320d2 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -39,8 +39,7 @@
 {
 	DECLARE_COMPLETION_ONSTACK(wait);
 	struct request_queue *q = bdev_get_queue(bdev);
-	int type = flags & BLKDEV_IFL_BARRIER ?
-		DISCARD_BARRIER : DISCARD_NOBARRIER;
+	int type = REQ_WRITE | REQ_DISCARD;
 	unsigned int max_discard_sectors;
 	struct bio *bio;
 	int ret = 0;
@@ -62,10 +61,10 @@
 		max_discard_sectors &= ~(disc_sects - 1);
 	}
 
-	if (flags & BLKDEV_IFL_SECURE) {
+	if (flags & BLKDEV_DISCARD_SECURE) {
 		if (!blk_queue_secdiscard(q))
 			return -EOPNOTSUPP;
-		type |= DISCARD_SECURE;
+		type |= REQ_SECURE;
 	}
 
 	while (nr_sects && !ret) {
@@ -78,8 +77,7 @@
 		bio->bi_sector = sector;
 		bio->bi_end_io = blkdev_discard_end_io;
 		bio->bi_bdev = bdev;
-		if (flags & BLKDEV_IFL_WAIT)
-			bio->bi_private = &wait;
+		bio->bi_private = &wait;
 
 		if (nr_sects > max_discard_sectors) {
 			bio->bi_size = max_discard_sectors << 9;
@@ -93,8 +91,7 @@
 		bio_get(bio);
 		submit_bio(type, bio);
 
-		if (flags & BLKDEV_IFL_WAIT)
-			wait_for_completion(&wait);
+		wait_for_completion(&wait);
 
 		if (bio_flagged(bio, BIO_EOPNOTSUPP))
 			ret = -EOPNOTSUPP;
@@ -140,7 +137,6 @@
  * @sector:	start sector
  * @nr_sects:	number of sectors to write
  * @gfp_mask:	memory allocation flags (for bio_alloc)
- * @flags:	BLKDEV_IFL_* flags to control behaviour
  *
  * Description:
  *  Generate and issue number of bios with zerofiled pages.
@@ -149,7 +145,7 @@
  */
 
 int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
-			sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
+			sector_t nr_sects, gfp_t gfp_mask)
 {
 	int ret;
 	struct bio *bio;
@@ -162,12 +158,6 @@
 	bb.wait = &wait;
 	bb.end_io = NULL;
 
-	if (flags & BLKDEV_IFL_BARRIER) {
-		/* issue async barrier before the data */
-		ret = blkdev_issue_flush(bdev, gfp_mask, NULL, 0);
-		if (ret)
-			return ret;
-	}
 submit:
 	ret = 0;
 	while (nr_sects != 0) {
@@ -181,8 +171,7 @@
 		bio->bi_sector = sector;
 		bio->bi_bdev   = bdev;
 		bio->bi_end_io = bio_batch_end_io;
-		if (flags & BLKDEV_IFL_WAIT)
-			bio->bi_private = &bb;
+		bio->bi_private = &bb;
 
 		while (nr_sects != 0) {
 			sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects);
@@ -199,18 +188,10 @@
 		issued++;
 		submit_bio(WRITE, bio);
 	}
-	/*
-	 * When all data bios are in flight. Send final barrier if requeted.
-	 */
-	if (nr_sects == 0 && flags & BLKDEV_IFL_BARRIER)
-		ret = blkdev_issue_flush(bdev, gfp_mask, NULL,
-					flags & BLKDEV_IFL_WAIT);
 
-
-	if (flags & BLKDEV_IFL_WAIT)
-		/* Wait for bios in-flight */
-		while ( issued != atomic_read(&bb.done))
-			wait_for_completion(&wait);
+	/* Wait for bios in-flight */
+	while (issued != atomic_read(&bb.done))
+		wait_for_completion(&wait);
 
 	if (!test_bit(BIO_UPTODATE, &bb.flags))
 		/* One of bios in the batch was completed with error.*/
diff --git a/block/blk-map.c b/block/blk-map.c
index ade0a08..d4a586d 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -54,7 +54,7 @@
 	 * direct dma. else, set up kernel bounce buffers
 	 */
 	uaddr = (unsigned long) ubuf;
-	if (blk_rq_aligned(q, ubuf, len) && !map_data)
+	if (blk_rq_aligned(q, uaddr, len) && !map_data)
 		bio = bio_map_user(q, NULL, uaddr, len, reading, gfp_mask);
 	else
 		bio = bio_copy_user(q, map_data, uaddr, len, reading, gfp_mask);
@@ -288,6 +288,7 @@
 		    unsigned int len, gfp_t gfp_mask)
 {
 	int reading = rq_data_dir(rq) == READ;
+	unsigned long addr = (unsigned long) kbuf;
 	int do_copy = 0;
 	struct bio *bio;
 	int ret;
@@ -297,7 +298,7 @@
 	if (!len || !kbuf)
 		return -EINVAL;
 
-	do_copy = !blk_rq_aligned(q, kbuf, len) || object_is_on_stack(kbuf);
+	do_copy = !blk_rq_aligned(q, addr, len) || object_is_on_stack(kbuf);
 	if (do_copy)
 		bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading);
 	else
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 3b0cd42..0a2fd8a 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -205,12 +205,11 @@
 {
 	int nr_phys_segs = bio_phys_segments(q, bio);
 
-	if (req->nr_phys_segments + nr_phys_segs > queue_max_segments(q)) {
-		req->cmd_flags |= REQ_NOMERGE;
-		if (req == q->last_merge)
-			q->last_merge = NULL;
-		return 0;
-	}
+	if (req->nr_phys_segments + nr_phys_segs > queue_max_segments(q))
+		goto no_merge;
+
+	if (bio_integrity(bio) && blk_integrity_merge_bio(q, req, bio))
+		goto no_merge;
 
 	/*
 	 * This will form the start of a new hw segment.  Bump both
@@ -218,6 +217,12 @@
 	 */
 	req->nr_phys_segments += nr_phys_segs;
 	return 1;
+
+no_merge:
+	req->cmd_flags |= REQ_NOMERGE;
+	if (req == q->last_merge)
+		q->last_merge = NULL;
+	return 0;
 }
 
 int ll_back_merge_fn(struct request_queue *q, struct request *req,
@@ -301,6 +306,9 @@
 	if (total_phys_segments > queue_max_segments(q))
 		return 0;
 
+	if (blk_integrity_rq(req) && blk_integrity_merge_rq(q, req, next))
+		return 0;
+
 	/* Merge is OK... */
 	req->nr_phys_segments = total_phys_segments;
 	return 1;
@@ -343,7 +351,7 @@
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+		part = req->part;
 
 		part_round_stats(cpu, part);
 		part_dec_in_flight(part, rq_data_dir(req));
@@ -362,6 +370,18 @@
 		return 0;
 
 	/*
+	 * Don't merge file system requests and discard requests
+	 */
+	if ((req->cmd_flags & REQ_DISCARD) != (next->cmd_flags & REQ_DISCARD))
+		return 0;
+
+	/*
+	 * Don't merge discard requests and secure discard requests
+	 */
+	if ((req->cmd_flags & REQ_SECURE) != (next->cmd_flags & REQ_SECURE))
+		return 0;
+
+	/*
 	 * not contiguous
 	 */
 	if (blk_rq_pos(req) + blk_rq_sectors(req) != blk_rq_pos(next))
@@ -372,9 +392,6 @@
 	    || next->special)
 		return 0;
 
-	if (blk_integrity_rq(req) != blk_integrity_rq(next))
-		return 0;
-
 	/*
 	 * If we are allowed to merge, then append bio list
 	 * from next to rq and release next. merge_requests_fn
diff --git a/block/blk-settings.c b/block/blk-settings.c
index a234f4b..701859f 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -111,6 +111,7 @@
 void blk_set_default_limits(struct queue_limits *lim)
 {
 	lim->max_segments = BLK_MAX_SEGMENTS;
+	lim->max_integrity_segments = 0;
 	lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
 	lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
 	lim->max_sectors = BLK_DEF_MAX_SECTORS;
@@ -213,7 +214,7 @@
 	 */
 	if (b_pfn < (min_t(u64, 0xffffffffUL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
 		dma = 1;
-	q->limits.bounce_pfn = max_low_pfn;
+	q->limits.bounce_pfn = max(max_low_pfn, b_pfn);
 #else
 	if (b_pfn < blk_max_low_pfn)
 		dma = 1;
@@ -343,7 +344,7 @@
  *   hardware can operate on without reverting to read-modify-write
  *   operations.
  */
-void blk_queue_physical_block_size(struct request_queue *q, unsigned short size)
+void blk_queue_physical_block_size(struct request_queue *q, unsigned int size)
 {
 	q->limits.physical_block_size = size;
 
@@ -455,11 +456,6 @@
 }
 EXPORT_SYMBOL(blk_queue_io_opt);
 
-/*
- * Returns the minimum that is _not_ zero, unless both are zero.
- */
-#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
-
 /**
  * blk_queue_stack_limits - inherit underlying queue limits for stacked drivers
  * @t:	the stacking driver (top)
@@ -514,6 +510,8 @@
 					    b->seg_boundary_mask);
 
 	t->max_segments = min_not_zero(t->max_segments, b->max_segments);
+	t->max_integrity_segments = min_not_zero(t->max_integrity_segments,
+						 b->max_integrity_segments);
 
 	t->max_segment_size = min_not_zero(t->max_segment_size,
 					   b->max_segment_size);
@@ -794,6 +792,26 @@
 }
 EXPORT_SYMBOL(blk_queue_update_dma_alignment);
 
+/**
+ * blk_queue_flush - configure queue's cache flush capability
+ * @q:		the request queue for the device
+ * @flush:	0, REQ_FLUSH or REQ_FLUSH | REQ_FUA
+ *
+ * Tell block layer cache flush capability of @q.  If it supports
+ * flushing, REQ_FLUSH should be set.  If it supports bypassing
+ * write cache for individual writes, REQ_FUA should be set.
+ */
+void blk_queue_flush(struct request_queue *q, unsigned int flush)
+{
+	WARN_ON_ONCE(flush & ~(REQ_FLUSH | REQ_FUA));
+
+	if (WARN_ON_ONCE(!(flush & REQ_FLUSH) && (flush & REQ_FUA)))
+		flush &= ~REQ_FUA;
+
+	q->flush_flags = flush & (REQ_FLUSH | REQ_FUA);
+}
+EXPORT_SYMBOL_GPL(blk_queue_flush);
+
 static int __init blk_settings_init(void)
 {
 	blk_max_low_pfn = max_low_pfn - 1;
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 0749b89..013457f 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -112,6 +112,11 @@
 	return queue_var_show(queue_max_segments(q), (page));
 }
 
+static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *page)
+{
+	return queue_var_show(q->limits.max_integrity_segments, (page));
+}
+
 static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)
 {
 	if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
@@ -288,6 +293,11 @@
 	.show = queue_max_segments_show,
 };
 
+static struct queue_sysfs_entry queue_max_integrity_segments_entry = {
+	.attr = {.name = "max_integrity_segments", .mode = S_IRUGO },
+	.show = queue_max_integrity_segments_show,
+};
+
 static struct queue_sysfs_entry queue_max_segment_size_entry = {
 	.attr = {.name = "max_segment_size", .mode = S_IRUGO },
 	.show = queue_max_segment_size_show,
@@ -375,6 +385,7 @@
 	&queue_max_hw_sectors_entry.attr,
 	&queue_max_sectors_entry.attr,
 	&queue_max_segments_entry.attr,
+	&queue_max_integrity_segments_entry.attr,
 	&queue_max_segment_size_entry.attr,
 	&queue_iosched_entry.attr,
 	&queue_hw_sector_size_entry.attr,
@@ -460,6 +471,8 @@
 
 	blk_sync_queue(q);
 
+	blk_throtl_exit(q);
+
 	if (rl->rq_pool)
 		mempool_destroy(rl->rq_pool);
 
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
new file mode 100644
index 0000000..56ad453
--- /dev/null
+++ b/block/blk-throttle.c
@@ -0,0 +1,1123 @@
+/*
+ * Interface for controlling IO bandwidth on a request queue
+ *
+ * Copyright (C) 2010 Vivek Goyal <vgoyal@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/bio.h>
+#include <linux/blktrace_api.h>
+#include "blk-cgroup.h"
+
+/* Max dispatch from a group in 1 round */
+static int throtl_grp_quantum = 8;
+
+/* Total max dispatch from all groups in one round */
+static int throtl_quantum = 32;
+
+/* Throttling is performed over 100ms slice and after that slice is renewed */
+static unsigned long throtl_slice = HZ/10;	/* 100 ms */
+
+struct throtl_rb_root {
+	struct rb_root rb;
+	struct rb_node *left;
+	unsigned int count;
+	unsigned long min_disptime;
+};
+
+#define THROTL_RB_ROOT	(struct throtl_rb_root) { .rb = RB_ROOT, .left = NULL, \
+			.count = 0, .min_disptime = 0}
+
+#define rb_entry_tg(node)	rb_entry((node), struct throtl_grp, rb_node)
+
+struct throtl_grp {
+	/* List of throtl groups on the request queue*/
+	struct hlist_node tg_node;
+
+	/* active throtl group service_tree member */
+	struct rb_node rb_node;
+
+	/*
+	 * Dispatch time in jiffies. This is the estimated time when group
+	 * will unthrottle and is ready to dispatch more bio. It is used as
+	 * key to sort active groups in service tree.
+	 */
+	unsigned long disptime;
+
+	struct blkio_group blkg;
+	atomic_t ref;
+	unsigned int flags;
+
+	/* Two lists for READ and WRITE */
+	struct bio_list bio_lists[2];
+
+	/* Number of queued bios on READ and WRITE lists */
+	unsigned int nr_queued[2];
+
+	/* bytes per second rate limits */
+	uint64_t bps[2];
+
+	/* IOPS limits */
+	unsigned int iops[2];
+
+	/* Number of bytes disptached in current slice */
+	uint64_t bytes_disp[2];
+	/* Number of bio's dispatched in current slice */
+	unsigned int io_disp[2];
+
+	/* When did we start a new slice */
+	unsigned long slice_start[2];
+	unsigned long slice_end[2];
+
+	/* Some throttle limits got updated for the group */
+	bool limits_changed;
+};
+
+struct throtl_data
+{
+	/* List of throtl groups */
+	struct hlist_head tg_list;
+
+	/* service tree for active throtl groups */
+	struct throtl_rb_root tg_service_tree;
+
+	struct throtl_grp root_tg;
+	struct request_queue *queue;
+
+	/* Total Number of queued bios on READ and WRITE lists */
+	unsigned int nr_queued[2];
+
+	/*
+	 * number of total undestroyed groups
+	 */
+	unsigned int nr_undestroyed_grps;
+
+	/* Work for dispatching throttled bios */
+	struct delayed_work throtl_work;
+
+	atomic_t limits_changed;
+};
+
+enum tg_state_flags {
+	THROTL_TG_FLAG_on_rr = 0,	/* on round-robin busy list */
+};
+
+#define THROTL_TG_FNS(name)						\
+static inline void throtl_mark_tg_##name(struct throtl_grp *tg)		\
+{									\
+	(tg)->flags |= (1 << THROTL_TG_FLAG_##name);			\
+}									\
+static inline void throtl_clear_tg_##name(struct throtl_grp *tg)	\
+{									\
+	(tg)->flags &= ~(1 << THROTL_TG_FLAG_##name);			\
+}									\
+static inline int throtl_tg_##name(const struct throtl_grp *tg)		\
+{									\
+	return ((tg)->flags & (1 << THROTL_TG_FLAG_##name)) != 0;	\
+}
+
+THROTL_TG_FNS(on_rr);
+
+#define throtl_log_tg(td, tg, fmt, args...)				\
+	blk_add_trace_msg((td)->queue, "throtl %s " fmt,		\
+				blkg_path(&(tg)->blkg), ##args);      	\
+
+#define throtl_log(td, fmt, args...)	\
+	blk_add_trace_msg((td)->queue, "throtl " fmt, ##args)
+
+static inline struct throtl_grp *tg_of_blkg(struct blkio_group *blkg)
+{
+	if (blkg)
+		return container_of(blkg, struct throtl_grp, blkg);
+
+	return NULL;
+}
+
+static inline int total_nr_queued(struct throtl_data *td)
+{
+	return (td->nr_queued[0] + td->nr_queued[1]);
+}
+
+static inline struct throtl_grp *throtl_ref_get_tg(struct throtl_grp *tg)
+{
+	atomic_inc(&tg->ref);
+	return tg;
+}
+
+static void throtl_put_tg(struct throtl_grp *tg)
+{
+	BUG_ON(atomic_read(&tg->ref) <= 0);
+	if (!atomic_dec_and_test(&tg->ref))
+		return;
+	kfree(tg);
+}
+
+static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td,
+			struct cgroup *cgroup)
+{
+	struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
+	struct throtl_grp *tg = NULL;
+	void *key = td;
+	struct backing_dev_info *bdi = &td->queue->backing_dev_info;
+	unsigned int major, minor;
+
+	/*
+	 * TODO: Speed up blkiocg_lookup_group() by maintaining a radix
+	 * tree of blkg (instead of traversing through hash list all
+	 * the time.
+	 */
+	tg = tg_of_blkg(blkiocg_lookup_group(blkcg, key));
+
+	/* Fill in device details for root group */
+	if (tg && !tg->blkg.dev && bdi->dev && dev_name(bdi->dev)) {
+		sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
+		tg->blkg.dev = MKDEV(major, minor);
+		goto done;
+	}
+
+	if (tg)
+		goto done;
+
+	tg = kzalloc_node(sizeof(*tg), GFP_ATOMIC, td->queue->node);
+	if (!tg)
+		goto done;
+
+	INIT_HLIST_NODE(&tg->tg_node);
+	RB_CLEAR_NODE(&tg->rb_node);
+	bio_list_init(&tg->bio_lists[0]);
+	bio_list_init(&tg->bio_lists[1]);
+
+	/*
+	 * Take the initial reference that will be released on destroy
+	 * This can be thought of a joint reference by cgroup and
+	 * request queue which will be dropped by either request queue
+	 * exit or cgroup deletion path depending on who is exiting first.
+	 */
+	atomic_set(&tg->ref, 1);
+
+	/* Add group onto cgroup list */
+	sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
+	blkiocg_add_blkio_group(blkcg, &tg->blkg, (void *)td,
+				MKDEV(major, minor), BLKIO_POLICY_THROTL);
+
+	tg->bps[READ] = blkcg_get_read_bps(blkcg, tg->blkg.dev);
+	tg->bps[WRITE] = blkcg_get_write_bps(blkcg, tg->blkg.dev);
+	tg->iops[READ] = blkcg_get_read_iops(blkcg, tg->blkg.dev);
+	tg->iops[WRITE] = blkcg_get_write_iops(blkcg, tg->blkg.dev);
+
+	hlist_add_head(&tg->tg_node, &td->tg_list);
+	td->nr_undestroyed_grps++;
+done:
+	return tg;
+}
+
+static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
+{
+	struct cgroup *cgroup;
+	struct throtl_grp *tg = NULL;
+
+	rcu_read_lock();
+	cgroup = task_cgroup(current, blkio_subsys_id);
+	tg = throtl_find_alloc_tg(td, cgroup);
+	if (!tg)
+		tg = &td->root_tg;
+	rcu_read_unlock();
+	return tg;
+}
+
+static struct throtl_grp *throtl_rb_first(struct throtl_rb_root *root)
+{
+	/* Service tree is empty */
+	if (!root->count)
+		return NULL;
+
+	if (!root->left)
+		root->left = rb_first(&root->rb);
+
+	if (root->left)
+		return rb_entry_tg(root->left);
+
+	return NULL;
+}
+
+static void rb_erase_init(struct rb_node *n, struct rb_root *root)
+{
+	rb_erase(n, root);
+	RB_CLEAR_NODE(n);
+}
+
+static void throtl_rb_erase(struct rb_node *n, struct throtl_rb_root *root)
+{
+	if (root->left == n)
+		root->left = NULL;
+	rb_erase_init(n, &root->rb);
+	--root->count;
+}
+
+static void update_min_dispatch_time(struct throtl_rb_root *st)
+{
+	struct throtl_grp *tg;
+
+	tg = throtl_rb_first(st);
+	if (!tg)
+		return;
+
+	st->min_disptime = tg->disptime;
+}
+
+static void
+tg_service_tree_add(struct throtl_rb_root *st, struct throtl_grp *tg)
+{
+	struct rb_node **node = &st->rb.rb_node;
+	struct rb_node *parent = NULL;
+	struct throtl_grp *__tg;
+	unsigned long key = tg->disptime;
+	int left = 1;
+
+	while (*node != NULL) {
+		parent = *node;
+		__tg = rb_entry_tg(parent);
+
+		if (time_before(key, __tg->disptime))
+			node = &parent->rb_left;
+		else {
+			node = &parent->rb_right;
+			left = 0;
+		}
+	}
+
+	if (left)
+		st->left = &tg->rb_node;
+
+	rb_link_node(&tg->rb_node, parent, node);
+	rb_insert_color(&tg->rb_node, &st->rb);
+}
+
+static void __throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+	struct throtl_rb_root *st = &td->tg_service_tree;
+
+	tg_service_tree_add(st, tg);
+	throtl_mark_tg_on_rr(tg);
+	st->count++;
+}
+
+static void throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+	if (!throtl_tg_on_rr(tg))
+		__throtl_enqueue_tg(td, tg);
+}
+
+static void __throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+	throtl_rb_erase(&tg->rb_node, &td->tg_service_tree);
+	throtl_clear_tg_on_rr(tg);
+}
+
+static void throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+	if (throtl_tg_on_rr(tg))
+		__throtl_dequeue_tg(td, tg);
+}
+
+static void throtl_schedule_next_dispatch(struct throtl_data *td)
+{
+	struct throtl_rb_root *st = &td->tg_service_tree;
+
+	/*
+	 * If there are more bios pending, schedule more work.
+	 */
+	if (!total_nr_queued(td))
+		return;
+
+	BUG_ON(!st->count);
+
+	update_min_dispatch_time(st);
+
+	if (time_before_eq(st->min_disptime, jiffies))
+		throtl_schedule_delayed_work(td->queue, 0);
+	else
+		throtl_schedule_delayed_work(td->queue,
+				(st->min_disptime - jiffies));
+}
+
+static inline void
+throtl_start_new_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
+{
+	tg->bytes_disp[rw] = 0;
+	tg->io_disp[rw] = 0;
+	tg->slice_start[rw] = jiffies;
+	tg->slice_end[rw] = jiffies + throtl_slice;
+	throtl_log_tg(td, tg, "[%c] new slice start=%lu end=%lu jiffies=%lu",
+			rw == READ ? 'R' : 'W', tg->slice_start[rw],
+			tg->slice_end[rw], jiffies);
+}
+
+static inline void throtl_extend_slice(struct throtl_data *td,
+		struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
+{
+	tg->slice_end[rw] = roundup(jiffy_end, throtl_slice);
+	throtl_log_tg(td, tg, "[%c] extend slice start=%lu end=%lu jiffies=%lu",
+			rw == READ ? 'R' : 'W', tg->slice_start[rw],
+			tg->slice_end[rw], jiffies);
+}
+
+/* Determine if previously allocated or extended slice is complete or not */
+static bool
+throtl_slice_used(struct throtl_data *td, struct throtl_grp *tg, bool rw)
+{
+	if (time_in_range(jiffies, tg->slice_start[rw], tg->slice_end[rw]))
+		return 0;
+
+	return 1;
+}
+
+/* Trim the used slices and adjust slice start accordingly */
+static inline void
+throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
+{
+	unsigned long nr_slices, time_elapsed, io_trim;
+	u64 bytes_trim, tmp;
+
+	BUG_ON(time_before(tg->slice_end[rw], tg->slice_start[rw]));
+
+	/*
+	 * If bps are unlimited (-1), then time slice don't get
+	 * renewed. Don't try to trim the slice if slice is used. A new
+	 * slice will start when appropriate.
+	 */
+	if (throtl_slice_used(td, tg, rw))
+		return;
+
+	time_elapsed = jiffies - tg->slice_start[rw];
+
+	nr_slices = time_elapsed / throtl_slice;
+
+	if (!nr_slices)
+		return;
+	tmp = tg->bps[rw] * throtl_slice * nr_slices;
+	do_div(tmp, HZ);
+	bytes_trim = tmp;
+
+	io_trim = (tg->iops[rw] * throtl_slice * nr_slices)/HZ;
+
+	if (!bytes_trim && !io_trim)
+		return;
+
+	if (tg->bytes_disp[rw] >= bytes_trim)
+		tg->bytes_disp[rw] -= bytes_trim;
+	else
+		tg->bytes_disp[rw] = 0;
+
+	if (tg->io_disp[rw] >= io_trim)
+		tg->io_disp[rw] -= io_trim;
+	else
+		tg->io_disp[rw] = 0;
+
+	tg->slice_start[rw] += nr_slices * throtl_slice;
+
+	throtl_log_tg(td, tg, "[%c] trim slice nr=%lu bytes=%llu io=%lu"
+			" start=%lu end=%lu jiffies=%lu",
+			rw == READ ? 'R' : 'W', nr_slices, bytes_trim, io_trim,
+			tg->slice_start[rw], tg->slice_end[rw], jiffies);
+}
+
+static bool tg_with_in_iops_limit(struct throtl_data *td, struct throtl_grp *tg,
+		struct bio *bio, unsigned long *wait)
+{
+	bool rw = bio_data_dir(bio);
+	unsigned int io_allowed;
+	unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd;
+	u64 tmp;
+
+	jiffy_elapsed = jiffy_elapsed_rnd = jiffies - tg->slice_start[rw];
+
+	/* Slice has just started. Consider one slice interval */
+	if (!jiffy_elapsed)
+		jiffy_elapsed_rnd = throtl_slice;
+
+	jiffy_elapsed_rnd = roundup(jiffy_elapsed_rnd, throtl_slice);
+
+	/*
+	 * jiffy_elapsed_rnd should not be a big value as minimum iops can be
+	 * 1 then at max jiffy elapsed should be equivalent of 1 second as we
+	 * will allow dispatch after 1 second and after that slice should
+	 * have been trimmed.
+	 */
+
+	tmp = (u64)tg->iops[rw] * jiffy_elapsed_rnd;
+	do_div(tmp, HZ);
+
+	if (tmp > UINT_MAX)
+		io_allowed = UINT_MAX;
+	else
+		io_allowed = tmp;
+
+	if (tg->io_disp[rw] + 1 <= io_allowed) {
+		if (wait)
+			*wait = 0;
+		return 1;
+	}
+
+	/* Calc approx time to dispatch */
+	jiffy_wait = ((tg->io_disp[rw] + 1) * HZ)/tg->iops[rw] + 1;
+
+	if (jiffy_wait > jiffy_elapsed)
+		jiffy_wait = jiffy_wait - jiffy_elapsed;
+	else
+		jiffy_wait = 1;
+
+	if (wait)
+		*wait = jiffy_wait;
+	return 0;
+}
+
+static bool tg_with_in_bps_limit(struct throtl_data *td, struct throtl_grp *tg,
+		struct bio *bio, unsigned long *wait)
+{
+	bool rw = bio_data_dir(bio);
+	u64 bytes_allowed, extra_bytes, tmp;
+	unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd;
+
+	jiffy_elapsed = jiffy_elapsed_rnd = jiffies - tg->slice_start[rw];
+
+	/* Slice has just started. Consider one slice interval */
+	if (!jiffy_elapsed)
+		jiffy_elapsed_rnd = throtl_slice;
+
+	jiffy_elapsed_rnd = roundup(jiffy_elapsed_rnd, throtl_slice);
+
+	tmp = tg->bps[rw] * jiffy_elapsed_rnd;
+	do_div(tmp, HZ);
+	bytes_allowed = tmp;
+
+	if (tg->bytes_disp[rw] + bio->bi_size <= bytes_allowed) {
+		if (wait)
+			*wait = 0;
+		return 1;
+	}
+
+	/* Calc approx time to dispatch */
+	extra_bytes = tg->bytes_disp[rw] + bio->bi_size - bytes_allowed;
+	jiffy_wait = div64_u64(extra_bytes * HZ, tg->bps[rw]);
+
+	if (!jiffy_wait)
+		jiffy_wait = 1;
+
+	/*
+	 * This wait time is without taking into consideration the rounding
+	 * up we did. Add that time also.
+	 */
+	jiffy_wait = jiffy_wait + (jiffy_elapsed_rnd - jiffy_elapsed);
+	if (wait)
+		*wait = jiffy_wait;
+	return 0;
+}
+
+/*
+ * Returns whether one can dispatch a bio or not. Also returns approx number
+ * of jiffies to wait before this bio is with-in IO rate and can be dispatched
+ */
+static bool tg_may_dispatch(struct throtl_data *td, struct throtl_grp *tg,
+				struct bio *bio, unsigned long *wait)
+{
+	bool rw = bio_data_dir(bio);
+	unsigned long bps_wait = 0, iops_wait = 0, max_wait = 0;
+
+	/*
+ 	 * Currently whole state machine of group depends on first bio
+	 * queued in the group bio list. So one should not be calling
+	 * this function with a different bio if there are other bios
+	 * queued.
+	 */
+	BUG_ON(tg->nr_queued[rw] && bio != bio_list_peek(&tg->bio_lists[rw]));
+
+	/* If tg->bps = -1, then BW is unlimited */
+	if (tg->bps[rw] == -1 && tg->iops[rw] == -1) {
+		if (wait)
+			*wait = 0;
+		return 1;
+	}
+
+	/*
+	 * If previous slice expired, start a new one otherwise renew/extend
+	 * existing slice to make sure it is at least throtl_slice interval
+	 * long since now.
+	 */
+	if (throtl_slice_used(td, tg, rw))
+		throtl_start_new_slice(td, tg, rw);
+	else {
+		if (time_before(tg->slice_end[rw], jiffies + throtl_slice))
+			throtl_extend_slice(td, tg, rw, jiffies + throtl_slice);
+	}
+
+	if (tg_with_in_bps_limit(td, tg, bio, &bps_wait)
+	    && tg_with_in_iops_limit(td, tg, bio, &iops_wait)) {
+		if (wait)
+			*wait = 0;
+		return 1;
+	}
+
+	max_wait = max(bps_wait, iops_wait);
+
+	if (wait)
+		*wait = max_wait;
+
+	if (time_before(tg->slice_end[rw], jiffies + max_wait))
+		throtl_extend_slice(td, tg, rw, jiffies + max_wait);
+
+	return 0;
+}
+
+static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio)
+{
+	bool rw = bio_data_dir(bio);
+	bool sync = bio->bi_rw & REQ_SYNC;
+
+	/* Charge the bio to the group */
+	tg->bytes_disp[rw] += bio->bi_size;
+	tg->io_disp[rw]++;
+
+	/*
+	 * TODO: This will take blkg->stats_lock. Figure out a way
+	 * to avoid this cost.
+	 */
+	blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size, rw, sync);
+}
+
+static void throtl_add_bio_tg(struct throtl_data *td, struct throtl_grp *tg,
+			struct bio *bio)
+{
+	bool rw = bio_data_dir(bio);
+
+	bio_list_add(&tg->bio_lists[rw], bio);
+	/* Take a bio reference on tg */
+	throtl_ref_get_tg(tg);
+	tg->nr_queued[rw]++;
+	td->nr_queued[rw]++;
+	throtl_enqueue_tg(td, tg);
+}
+
+static void tg_update_disptime(struct throtl_data *td, struct throtl_grp *tg)
+{
+	unsigned long read_wait = -1, write_wait = -1, min_wait = -1, disptime;
+	struct bio *bio;
+
+	if ((bio = bio_list_peek(&tg->bio_lists[READ])))
+		tg_may_dispatch(td, tg, bio, &read_wait);
+
+	if ((bio = bio_list_peek(&tg->bio_lists[WRITE])))
+		tg_may_dispatch(td, tg, bio, &write_wait);
+
+	min_wait = min(read_wait, write_wait);
+	disptime = jiffies + min_wait;
+
+	/* Update dispatch time */
+	throtl_dequeue_tg(td, tg);
+	tg->disptime = disptime;
+	throtl_enqueue_tg(td, tg);
+}
+
+static void tg_dispatch_one_bio(struct throtl_data *td, struct throtl_grp *tg,
+				bool rw, struct bio_list *bl)
+{
+	struct bio *bio;
+
+	bio = bio_list_pop(&tg->bio_lists[rw]);
+	tg->nr_queued[rw]--;
+	/* Drop bio reference on tg */
+	throtl_put_tg(tg);
+
+	BUG_ON(td->nr_queued[rw] <= 0);
+	td->nr_queued[rw]--;
+
+	throtl_charge_bio(tg, bio);
+	bio_list_add(bl, bio);
+	bio->bi_rw |= REQ_THROTTLED;
+
+	throtl_trim_slice(td, tg, rw);
+}
+
+static int throtl_dispatch_tg(struct throtl_data *td, struct throtl_grp *tg,
+				struct bio_list *bl)
+{
+	unsigned int nr_reads = 0, nr_writes = 0;
+	unsigned int max_nr_reads = throtl_grp_quantum*3/4;
+	unsigned int max_nr_writes = throtl_grp_quantum - nr_reads;
+	struct bio *bio;
+
+	/* Try to dispatch 75% READS and 25% WRITES */
+
+	while ((bio = bio_list_peek(&tg->bio_lists[READ]))
+		&& tg_may_dispatch(td, tg, bio, NULL)) {
+
+		tg_dispatch_one_bio(td, tg, bio_data_dir(bio), bl);
+		nr_reads++;
+
+		if (nr_reads >= max_nr_reads)
+			break;
+	}
+
+	while ((bio = bio_list_peek(&tg->bio_lists[WRITE]))
+		&& tg_may_dispatch(td, tg, bio, NULL)) {
+
+		tg_dispatch_one_bio(td, tg, bio_data_dir(bio), bl);
+		nr_writes++;
+
+		if (nr_writes >= max_nr_writes)
+			break;
+	}
+
+	return nr_reads + nr_writes;
+}
+
+static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl)
+{
+	unsigned int nr_disp = 0;
+	struct throtl_grp *tg;
+	struct throtl_rb_root *st = &td->tg_service_tree;
+
+	while (1) {
+		tg = throtl_rb_first(st);
+
+		if (!tg)
+			break;
+
+		if (time_before(jiffies, tg->disptime))
+			break;
+
+		throtl_dequeue_tg(td, tg);
+
+		nr_disp += throtl_dispatch_tg(td, tg, bl);
+
+		if (tg->nr_queued[0] || tg->nr_queued[1]) {
+			tg_update_disptime(td, tg);
+			throtl_enqueue_tg(td, tg);
+		}
+
+		if (nr_disp >= throtl_quantum)
+			break;
+	}
+
+	return nr_disp;
+}
+
+static void throtl_process_limit_change(struct throtl_data *td)
+{
+	struct throtl_grp *tg;
+	struct hlist_node *pos, *n;
+
+	/*
+	 * Make sure atomic_inc() effects from
+	 * throtl_update_blkio_group_read_bps(), group of functions are
+	 * visible.
+	 * Is this required or smp_mb__after_atomic_inc() was suffcient
+	 * after the atomic_inc().
+	 */
+	smp_rmb();
+	if (!atomic_read(&td->limits_changed))
+		return;
+
+	throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed));
+
+	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
+		/*
+		 * Do I need an smp_rmb() here to make sure tg->limits_changed
+		 * update is visible. I am relying on smp_rmb() at the
+		 * beginning of function and not putting a new one here.
+		 */
+
+		if (throtl_tg_on_rr(tg) && tg->limits_changed) {
+			throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
+				" riops=%u wiops=%u", tg->bps[READ],
+				tg->bps[WRITE], tg->iops[READ],
+				tg->iops[WRITE]);
+			tg_update_disptime(td, tg);
+			tg->limits_changed = false;
+		}
+	}
+
+	smp_mb__before_atomic_dec();
+	atomic_dec(&td->limits_changed);
+	smp_mb__after_atomic_dec();
+}
+
+/* Dispatch throttled bios. Should be called without queue lock held. */
+static int throtl_dispatch(struct request_queue *q)
+{
+	struct throtl_data *td = q->td;
+	unsigned int nr_disp = 0;
+	struct bio_list bio_list_on_stack;
+	struct bio *bio;
+
+	spin_lock_irq(q->queue_lock);
+
+	throtl_process_limit_change(td);
+
+	if (!total_nr_queued(td))
+		goto out;
+
+	bio_list_init(&bio_list_on_stack);
+
+	throtl_log(td, "dispatch nr_queued=%lu read=%u write=%u",
+			total_nr_queued(td), td->nr_queued[READ],
+			td->nr_queued[WRITE]);
+
+	nr_disp = throtl_select_dispatch(td, &bio_list_on_stack);
+
+	if (nr_disp)
+		throtl_log(td, "bios disp=%u", nr_disp);
+
+	throtl_schedule_next_dispatch(td);
+out:
+	spin_unlock_irq(q->queue_lock);
+
+	/*
+	 * If we dispatched some requests, unplug the queue to make sure
+	 * immediate dispatch
+	 */
+	if (nr_disp) {
+		while((bio = bio_list_pop(&bio_list_on_stack)))
+			generic_make_request(bio);
+		blk_unplug(q);
+	}
+	return nr_disp;
+}
+
+void blk_throtl_work(struct work_struct *work)
+{
+	struct throtl_data *td = container_of(work, struct throtl_data,
+					throtl_work.work);
+	struct request_queue *q = td->queue;
+
+	throtl_dispatch(q);
+}
+
+/* Call with queue lock held */
+void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay)
+{
+
+	struct throtl_data *td = q->td;
+	struct delayed_work *dwork = &td->throtl_work;
+
+	if (total_nr_queued(td) > 0) {
+		/*
+		 * We might have a work scheduled to be executed in future.
+		 * Cancel that and schedule a new one.
+		 */
+		__cancel_delayed_work(dwork);
+		kblockd_schedule_delayed_work(q, dwork, delay);
+		throtl_log(td, "schedule work. delay=%lu jiffies=%lu",
+				delay, jiffies);
+	}
+}
+EXPORT_SYMBOL(throtl_schedule_delayed_work);
+
+static void
+throtl_destroy_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+	/* Something wrong if we are trying to remove same group twice */
+	BUG_ON(hlist_unhashed(&tg->tg_node));
+
+	hlist_del_init(&tg->tg_node);
+
+	/*
+	 * Put the reference taken at the time of creation so that when all
+	 * queues are gone, group can be destroyed.
+	 */
+	throtl_put_tg(tg);
+	td->nr_undestroyed_grps--;
+}
+
+static void throtl_release_tgs(struct throtl_data *td)
+{
+	struct hlist_node *pos, *n;
+	struct throtl_grp *tg;
+
+	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
+		/*
+		 * If cgroup removal path got to blk_group first and removed
+		 * it from cgroup list, then it will take care of destroying
+		 * cfqg also.
+		 */
+		if (!blkiocg_del_blkio_group(&tg->blkg))
+			throtl_destroy_tg(td, tg);
+	}
+}
+
+static void throtl_td_free(struct throtl_data *td)
+{
+	kfree(td);
+}
+
+/*
+ * Blk cgroup controller notification saying that blkio_group object is being
+ * delinked as associated cgroup object is going away. That also means that
+ * no new IO will come in this group. So get rid of this group as soon as
+ * any pending IO in the group is finished.
+ *
+ * This function is called under rcu_read_lock(). key is the rcu protected
+ * pointer. That means "key" is a valid throtl_data pointer as long as we are
+ * rcu read lock.
+ *
+ * "key" was fetched from blkio_group under blkio_cgroup->lock. That means
+ * it should not be NULL as even if queue was going away, cgroup deltion
+ * path got to it first.
+ */
+void throtl_unlink_blkio_group(void *key, struct blkio_group *blkg)
+{
+	unsigned long flags;
+	struct throtl_data *td = key;
+
+	spin_lock_irqsave(td->queue->queue_lock, flags);
+	throtl_destroy_tg(td, tg_of_blkg(blkg));
+	spin_unlock_irqrestore(td->queue->queue_lock, flags);
+}
+
+/*
+ * For all update functions, key should be a valid pointer because these
+ * update functions are called under blkcg_lock, that means, blkg is
+ * valid and in turn key is valid. queue exit path can not race becuase
+ * of blkcg_lock
+ *
+ * Can not take queue lock in update functions as queue lock under blkcg_lock
+ * is not allowed. Under other paths we take blkcg_lock under queue_lock.
+ */
+static void throtl_update_blkio_group_read_bps(void *key,
+				struct blkio_group *blkg, u64 read_bps)
+{
+	struct throtl_data *td = key;
+
+	tg_of_blkg(blkg)->bps[READ] = read_bps;
+	/* Make sure read_bps is updated before setting limits_changed */
+	smp_wmb();
+	tg_of_blkg(blkg)->limits_changed = true;
+
+	/* Make sure tg->limits_changed is updated before td->limits_changed */
+	smp_mb__before_atomic_inc();
+	atomic_inc(&td->limits_changed);
+	smp_mb__after_atomic_inc();
+
+	/* Schedule a work now to process the limit change */
+	throtl_schedule_delayed_work(td->queue, 0);
+}
+
+static void throtl_update_blkio_group_write_bps(void *key,
+				struct blkio_group *blkg, u64 write_bps)
+{
+	struct throtl_data *td = key;
+
+	tg_of_blkg(blkg)->bps[WRITE] = write_bps;
+	smp_wmb();
+	tg_of_blkg(blkg)->limits_changed = true;
+	smp_mb__before_atomic_inc();
+	atomic_inc(&td->limits_changed);
+	smp_mb__after_atomic_inc();
+	throtl_schedule_delayed_work(td->queue, 0);
+}
+
+static void throtl_update_blkio_group_read_iops(void *key,
+			struct blkio_group *blkg, unsigned int read_iops)
+{
+	struct throtl_data *td = key;
+
+	tg_of_blkg(blkg)->iops[READ] = read_iops;
+	smp_wmb();
+	tg_of_blkg(blkg)->limits_changed = true;
+	smp_mb__before_atomic_inc();
+	atomic_inc(&td->limits_changed);
+	smp_mb__after_atomic_inc();
+	throtl_schedule_delayed_work(td->queue, 0);
+}
+
+static void throtl_update_blkio_group_write_iops(void *key,
+			struct blkio_group *blkg, unsigned int write_iops)
+{
+	struct throtl_data *td = key;
+
+	tg_of_blkg(blkg)->iops[WRITE] = write_iops;
+	smp_wmb();
+	tg_of_blkg(blkg)->limits_changed = true;
+	smp_mb__before_atomic_inc();
+	atomic_inc(&td->limits_changed);
+	smp_mb__after_atomic_inc();
+	throtl_schedule_delayed_work(td->queue, 0);
+}
+
+void throtl_shutdown_timer_wq(struct request_queue *q)
+{
+	struct throtl_data *td = q->td;
+
+	cancel_delayed_work_sync(&td->throtl_work);
+}
+
+static struct blkio_policy_type blkio_policy_throtl = {
+	.ops = {
+		.blkio_unlink_group_fn = throtl_unlink_blkio_group,
+		.blkio_update_group_read_bps_fn =
+					throtl_update_blkio_group_read_bps,
+		.blkio_update_group_write_bps_fn =
+					throtl_update_blkio_group_write_bps,
+		.blkio_update_group_read_iops_fn =
+					throtl_update_blkio_group_read_iops,
+		.blkio_update_group_write_iops_fn =
+					throtl_update_blkio_group_write_iops,
+	},
+	.plid = BLKIO_POLICY_THROTL,
+};
+
+int blk_throtl_bio(struct request_queue *q, struct bio **biop)
+{
+	struct throtl_data *td = q->td;
+	struct throtl_grp *tg;
+	struct bio *bio = *biop;
+	bool rw = bio_data_dir(bio), update_disptime = true;
+
+	if (bio->bi_rw & REQ_THROTTLED) {
+		bio->bi_rw &= ~REQ_THROTTLED;
+		return 0;
+	}
+
+	spin_lock_irq(q->queue_lock);
+	tg = throtl_get_tg(td);
+
+	if (tg->nr_queued[rw]) {
+		/*
+		 * There is already another bio queued in same dir. No
+		 * need to update dispatch time.
+		 * Still update the disptime if rate limits on this group
+		 * were changed.
+		 */
+		if (!tg->limits_changed)
+			update_disptime = false;
+		else
+			tg->limits_changed = false;
+
+		goto queue_bio;
+	}
+
+	/* Bio is with-in rate limit of group */
+	if (tg_may_dispatch(td, tg, bio, NULL)) {
+		throtl_charge_bio(tg, bio);
+		goto out;
+	}
+
+queue_bio:
+	throtl_log_tg(td, tg, "[%c] bio. bdisp=%u sz=%u bps=%llu"
+			" iodisp=%u iops=%u queued=%d/%d",
+			rw == READ ? 'R' : 'W',
+			tg->bytes_disp[rw], bio->bi_size, tg->bps[rw],
+			tg->io_disp[rw], tg->iops[rw],
+			tg->nr_queued[READ], tg->nr_queued[WRITE]);
+
+	throtl_add_bio_tg(q->td, tg, bio);
+	*biop = NULL;
+
+	if (update_disptime) {
+		tg_update_disptime(td, tg);
+		throtl_schedule_next_dispatch(td);
+	}
+
+out:
+	spin_unlock_irq(q->queue_lock);
+	return 0;
+}
+
+int blk_throtl_init(struct request_queue *q)
+{
+	struct throtl_data *td;
+	struct throtl_grp *tg;
+
+	td = kzalloc_node(sizeof(*td), GFP_KERNEL, q->node);
+	if (!td)
+		return -ENOMEM;
+
+	INIT_HLIST_HEAD(&td->tg_list);
+	td->tg_service_tree = THROTL_RB_ROOT;
+	atomic_set(&td->limits_changed, 0);
+
+	/* Init root group */
+	tg = &td->root_tg;
+	INIT_HLIST_NODE(&tg->tg_node);
+	RB_CLEAR_NODE(&tg->rb_node);
+	bio_list_init(&tg->bio_lists[0]);
+	bio_list_init(&tg->bio_lists[1]);
+
+	/* Practically unlimited BW */
+	tg->bps[0] = tg->bps[1] = -1;
+	tg->iops[0] = tg->iops[1] = -1;
+
+	/*
+	 * Set root group reference to 2. One reference will be dropped when
+	 * all groups on tg_list are being deleted during queue exit. Other
+	 * reference will remain there as we don't want to delete this group
+	 * as it is statically allocated and gets destroyed when throtl_data
+	 * goes away.
+	 */
+	atomic_set(&tg->ref, 2);
+	hlist_add_head(&tg->tg_node, &td->tg_list);
+	td->nr_undestroyed_grps++;
+
+	INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work);
+
+	rcu_read_lock();
+	blkiocg_add_blkio_group(&blkio_root_cgroup, &tg->blkg, (void *)td,
+					0, BLKIO_POLICY_THROTL);
+	rcu_read_unlock();
+
+	/* Attach throtl data to request queue */
+	td->queue = q;
+	q->td = td;
+	return 0;
+}
+
+void blk_throtl_exit(struct request_queue *q)
+{
+	struct throtl_data *td = q->td;
+	bool wait = false;
+
+	BUG_ON(!td);
+
+	throtl_shutdown_timer_wq(q);
+
+	spin_lock_irq(q->queue_lock);
+	throtl_release_tgs(td);
+
+	/* If there are other groups */
+	if (td->nr_undestroyed_grps > 0)
+		wait = true;
+
+	spin_unlock_irq(q->queue_lock);
+
+	/*
+	 * Wait for tg->blkg->key accessors to exit their grace periods.
+	 * Do this wait only if there are other undestroyed groups out
+	 * there (other than root group). This can happen if cgroup deletion
+	 * path claimed the responsibility of cleaning up a group before
+	 * queue cleanup code get to the group.
+	 *
+	 * Do not call synchronize_rcu() unconditionally as there are drivers
+	 * which create/delete request queue hundreds of times during scan/boot
+	 * and synchronize_rcu() can take significant time and slow down boot.
+	 */
+	if (wait)
+		synchronize_rcu();
+
+	/*
+	 * Just being safe to make sure after previous flush if some body did
+	 * update limits through cgroup and another work got queued, cancel
+	 * it.
+	 */
+	throtl_shutdown_timer_wq(q);
+	throtl_td_free(td);
+}
+
+static int __init throtl_init(void)
+{
+	blkio_policy_register(&blkio_policy_throtl);
+	return 0;
+}
+
+module_init(throtl_init);
diff --git a/block/blk.h b/block/blk.h
index d6b911a..1e675e5 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -51,6 +51,8 @@
  */
 #define ELV_ON_HASH(rq)		(!hlist_unhashed(&(rq)->hash))
 
+struct request *blk_do_flush(struct request_queue *q, struct request *rq);
+
 static inline struct request *__elv_next_request(struct request_queue *q)
 {
 	struct request *rq;
@@ -58,7 +60,11 @@
 	while (1) {
 		while (!list_empty(&q->queue_head)) {
 			rq = list_entry_rq(q->queue_head.next);
-			if (blk_do_ordered(q, &rq))
+			if (!(rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) ||
+			    rq == &q->flush_rq)
+				return rq;
+			rq = blk_do_flush(q, rq);
+			if (rq)
 				return rq;
 		}
 
@@ -110,10 +116,6 @@
 
 int blk_dev_init(void);
 
-void elv_quiesce_start(struct request_queue *q);
-void elv_quiesce_end(struct request_queue *q);
-
-
 /*
  * Return the threshold (number of used requests) at which the queue is
  * considered to be congested.  It include a little hysteresis to keep the
@@ -132,14 +134,6 @@
 	return q->nr_congestion_off;
 }
 
-#if defined(CONFIG_BLK_DEV_INTEGRITY)
-
-#define rq_for_each_integrity_segment(bvl, _rq, _iter)		\
-	__rq_for_each_bio(_iter.bio, _rq)			\
-		bip_for_each_vec(bvl, _iter.bio->bi_integrity, _iter.i)
-
-#endif /* BLK_DEV_INTEGRITY */
-
 static inline int blk_cpu_to_group(int cpu)
 {
 	int group = NR_CPUS;
diff --git a/block/bsg.c b/block/bsg.c
index 82d5882..f20d6a7 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -20,7 +20,6 @@
 #include <linux/uio.h>
 #include <linux/idr.h>
 #include <linux/bsg.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 
 #include <scsi/scsi.h>
@@ -426,7 +425,7 @@
 	/*
 	 * fill in all the output members
 	 */
-	hdr->device_status = status_byte(rq->errors);
+	hdr->device_status = rq->errors & 0xff;
 	hdr->transport_status = host_byte(rq->errors);
 	hdr->driver_status = driver_byte(rq->errors);
 	hdr->info = 0;
@@ -843,9 +842,7 @@
 {
 	struct bsg_device *bd;
 
-	lock_kernel();
 	bd = bsg_get_device(inode, file);
-	unlock_kernel();
 
 	if (IS_ERR(bd))
 		return PTR_ERR(bd);
@@ -968,6 +965,7 @@
 	.release	=	bsg_release,
 	.unlocked_ioctl	=	bsg_ioctl,
 	.owner		=	THIS_MODULE,
+	.llseek		=	default_llseek,
 };
 
 void bsg_unregister_queue(struct request_queue *q)
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 9eba291..4cd59b0 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -160,6 +160,7 @@
 	BE_WORKLOAD = 0,
 	RT_WORKLOAD = 1,
 	IDLE_WORKLOAD = 2,
+	CFQ_PRIO_NR,
 };
 
 /*
@@ -184,10 +185,19 @@
 	/* number of cfqq currently on this group */
 	int nr_cfqq;
 
-	/* Per group busy queus average. Useful for workload slice calc. */
-	unsigned int busy_queues_avg[2];
 	/*
-	 * rr lists of queues with requests, onle rr for each priority class.
+	 * Per group busy queus average. Useful for workload slice calc. We
+	 * create the array for each prio class but at run time it is used
+	 * only for RT and BE class and slot for IDLE class remains unused.
+	 * This is primarily done to avoid confusion and a gcc warning.
+	 */
+	unsigned int busy_queues_avg[CFQ_PRIO_NR];
+	/*
+	 * rr lists of queues with requests. We maintain service trees for
+	 * RT and BE classes. These trees are subdivided in subclasses
+	 * of SYNC, SYNC_NOIDLE and ASYNC based on workload type. For IDLE
+	 * class there is no subclassification and all the cfq queues go on
+	 * a single tree service_tree_idle.
 	 * Counts are embedded in the cfq_rb_root
 	 */
 	struct cfq_rb_root service_trees[2][3];
@@ -221,7 +231,6 @@
 	enum wl_type_t serving_type;
 	unsigned long workload_expires;
 	struct cfq_group *serving_group;
-	bool noidle_tree_requires_idle;
 
 	/*
 	 * Each priority tree is sorted by next_request position.  These
@@ -977,8 +986,8 @@
 	return NULL;
 }
 
-void
-cfq_update_blkio_group_weight(struct blkio_group *blkg, unsigned int weight)
+void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
+					unsigned int weight)
 {
 	cfqg_of_blkg(blkg)->weight = weight;
 }
@@ -2180,7 +2189,6 @@
 	slice = max_t(unsigned, slice, CFQ_MIN_TT);
 	cfq_log(cfqd, "workload slice:%d", slice);
 	cfqd->workload_expires = jiffies + slice;
-	cfqd->noidle_tree_requires_idle = false;
 }
 
 static struct cfq_group *cfq_get_next_cfqg(struct cfq_data *cfqd)
@@ -3177,7 +3185,9 @@
 	if (cfqq->queued[0] + cfqq->queued[1] >= 4)
 		cfq_mark_cfqq_deep(cfqq);
 
-	if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
+	if (cfqq->next_rq && (cfqq->next_rq->cmd_flags & REQ_NOIDLE))
+		enable_idle = 0;
+	else if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
 	    (!cfq_cfqq_deep(cfqq) && CFQQ_SEEKY(cfqq)))
 		enable_idle = 0;
 	else if (sample_valid(cic->ttime_samples)) {
@@ -3494,17 +3504,7 @@
 			cfq_slice_expired(cfqd, 1);
 		else if (sync && cfqq_empty &&
 			 !cfq_close_cooperator(cfqd, cfqq)) {
-			cfqd->noidle_tree_requires_idle |=
-				!(rq->cmd_flags & REQ_NOIDLE);
-			/*
-			 * Idling is enabled for SYNC_WORKLOAD.
-			 * SYNC_NOIDLE_WORKLOAD idles at the end of the tree
-			 * only if we processed at least one !REQ_NOIDLE request
-			 */
-			if (cfqd->serving_type == SYNC_WORKLOAD
-			    || cfqd->noidle_tree_requires_idle
-			    || cfqq->cfqg->nr_cfqq == 1)
-				cfq_arm_slice_timer(cfqd);
+			cfq_arm_slice_timer(cfqd);
 		}
 	}
 
@@ -4090,6 +4090,7 @@
 		.blkio_unlink_group_fn =	cfq_unlink_blkio_group,
 		.blkio_update_group_weight_fn =	cfq_update_blkio_group_weight,
 	},
+	.plid = BLKIO_POLICY_PROP,
 };
 #else
 static struct blkio_policy_type blkio_policy_cfq;
diff --git a/block/cfq.h b/block/cfq.h
index 93448e5..54a6d90 100644
--- a/block/cfq.h
+++ b/block/cfq.h
@@ -69,7 +69,7 @@
 
 static inline void cfq_blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
 			struct blkio_group *blkg, void *key, dev_t dev) {
-	blkiocg_add_blkio_group(blkcg, blkg, key, dev);
+	blkiocg_add_blkio_group(blkcg, blkg, key, dev, BLKIO_POLICY_PROP);
 }
 
 static inline int cfq_blkiocg_del_blkio_group(struct blkio_group *blkg)
diff --git a/block/elevator.c b/block/elevator.c
index 205b09a..282e830 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -617,8 +617,6 @@
 
 void elv_insert(struct request_queue *q, struct request *rq, int where)
 {
-	struct list_head *pos;
-	unsigned ordseq;
 	int unplug_it = 1;
 
 	trace_block_rq_insert(q, rq);
@@ -626,9 +624,16 @@
 	rq->q = q;
 
 	switch (where) {
+	case ELEVATOR_INSERT_REQUEUE:
+		/*
+		 * Most requeues happen because of a busy condition,
+		 * don't force unplug of the queue for that case.
+		 * Clear unplug_it and fall through.
+		 */
+		unplug_it = 0;
+
 	case ELEVATOR_INSERT_FRONT:
 		rq->cmd_flags |= REQ_SOFTBARRIER;
-
 		list_add(&rq->queuelist, &q->queue_head);
 		break;
 
@@ -668,36 +673,6 @@
 		q->elevator->ops->elevator_add_req_fn(q, rq);
 		break;
 
-	case ELEVATOR_INSERT_REQUEUE:
-		/*
-		 * If ordered flush isn't in progress, we do front
-		 * insertion; otherwise, requests should be requeued
-		 * in ordseq order.
-		 */
-		rq->cmd_flags |= REQ_SOFTBARRIER;
-
-		/*
-		 * Most requeues happen because of a busy condition,
-		 * don't force unplug of the queue for that case.
-		 */
-		unplug_it = 0;
-
-		if (q->ordseq == 0) {
-			list_add(&rq->queuelist, &q->queue_head);
-			break;
-		}
-
-		ordseq = blk_ordered_req_seq(rq);
-
-		list_for_each(pos, &q->queue_head) {
-			struct request *pos_rq = list_entry_rq(pos);
-			if (ordseq <= blk_ordered_req_seq(pos_rq))
-				break;
-		}
-
-		list_add_tail(&rq->queuelist, pos);
-		break;
-
 	default:
 		printk(KERN_ERR "%s: bad insertion point %d\n",
 		       __func__, where);
@@ -716,26 +691,8 @@
 void __elv_add_request(struct request_queue *q, struct request *rq, int where,
 		       int plug)
 {
-	if (q->ordcolor)
-		rq->cmd_flags |= REQ_ORDERED_COLOR;
-
 	if (rq->cmd_flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
-		/*
-		 * toggle ordered color
-		 */
-		if (rq->cmd_flags & REQ_HARDBARRIER)
-			q->ordcolor ^= 1;
-
-		/*
-		 * barriers implicitly indicate back insertion
-		 */
-		if (where == ELEVATOR_INSERT_SORT)
-			where = ELEVATOR_INSERT_BACK;
-
-		/*
-		 * this request is scheduling boundary, update
-		 * end_sector
-		 */
+		/* barriers are scheduling boundary, update end_sector */
 		if (rq->cmd_type == REQ_TYPE_FS ||
 		    (rq->cmd_flags & REQ_DISCARD)) {
 			q->end_sector = rq_end_sector(rq);
@@ -855,24 +812,6 @@
 		    e->ops->elevator_completed_req_fn)
 			e->ops->elevator_completed_req_fn(q, rq);
 	}
-
-	/*
-	 * Check if the queue is waiting for fs requests to be
-	 * drained for flush sequence.
-	 */
-	if (unlikely(q->ordseq)) {
-		struct request *next = NULL;
-
-		if (!list_empty(&q->queue_head))
-			next = list_entry_rq(q->queue_head.next);
-
-		if (!queue_in_flight(q) &&
-		    blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN &&
-		    (!next || blk_ordered_req_seq(next) > QUEUE_ORDSEQ_DRAIN)) {
-			blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0);
-			__blk_run_queue(q);
-		}
-	}
 }
 
 #define to_elv(atr) container_of((atr), struct elv_fs_entry, attr)
@@ -938,6 +877,7 @@
 			}
 		}
 		kobject_uevent(&e->kobj, KOBJ_ADD);
+		e->registered = 1;
 	}
 	return error;
 }
@@ -947,6 +887,7 @@
 {
 	kobject_uevent(&e->kobj, KOBJ_REMOVE);
 	kobject_del(&e->kobj);
+	e->registered = 0;
 }
 
 void elv_unregister_queue(struct request_queue *q)
@@ -1042,11 +983,13 @@
 
 	spin_unlock_irq(q->queue_lock);
 
-	__elv_unregister_queue(old_elevator);
+	if (old_elevator->registered) {
+		__elv_unregister_queue(old_elevator);
 
-	err = elv_register_queue(q);
-	if (err)
-		goto fail_register;
+		err = elv_register_queue(q);
+		if (err)
+			goto fail_register;
+	}
 
 	/*
 	 * finally exit old elevator and turn off BYPASS.
diff --git a/block/genhd.c b/block/genhd.c
index 59a2db6..a8adf96 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -22,9 +22,7 @@
 #include "blk.h"
 
 static DEFINE_MUTEX(block_class_lock);
-#ifndef CONFIG_SYSFS_DEPRECATED
 struct kobject *block_depr;
-#endif
 
 /* for extended dynamic devt allocation, currently only one major is used */
 #define MAX_EXT_DEVT		(1 << MINORBITS)
@@ -541,13 +539,15 @@
 	disk->major = MAJOR(devt);
 	disk->first_minor = MINOR(devt);
 
+	/* Register BDI before referencing it from bdev */ 
+	bdi = &disk->queue->backing_dev_info;
+	bdi_register_dev(bdi, disk_devt(disk));
+
 	blk_register_region(disk_devt(disk), disk->minors, NULL,
 			    exact_match, exact_lock, disk);
 	register_disk(disk);
 	blk_register_queue(disk);
 
-	bdi = &disk->queue->backing_dev_info;
-	bdi_register_dev(bdi, disk_devt(disk));
 	retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,
 				   "bdi");
 	WARN_ON(retval);
@@ -642,6 +642,7 @@
 		struct hd_struct *part;
 		char name_buf[BDEVNAME_SIZE];
 		char devt_buf[BDEVT_SIZE];
+		u8 uuid[PARTITION_META_INFO_UUIDLTH * 2 + 1];
 
 		/*
 		 * Don't show empty devices or things that have been
@@ -660,10 +661,14 @@
 		while ((part = disk_part_iter_next(&piter))) {
 			bool is_part0 = part == &disk->part0;
 
-			printk("%s%s %10llu %s", is_part0 ? "" : "  ",
+			uuid[0] = 0;
+			if (part->info)
+				part_unpack_uuid(part->info->uuid, uuid);
+
+			printk("%s%s %10llu %s %s", is_part0 ? "" : "  ",
 			       bdevt_str(part_devt(part), devt_buf),
 			       (unsigned long long)part->nr_sects >> 1,
-			       disk_name(disk, part->partno, name_buf));
+			       disk_name(disk, part->partno, name_buf), uuid);
 			if (is_part0) {
 				if (disk->driverfs_dev != NULL &&
 				    disk->driverfs_dev->driver != NULL)
@@ -803,10 +808,9 @@
 
 	register_blkdev(BLOCK_EXT_MAJOR, "blkext");
 
-#ifndef CONFIG_SYSFS_DEPRECATED
 	/* create top-level block dir */
-	block_depr = kobject_create_and_add("block", NULL);
-#endif
+	if (!sysfs_deprecated)
+		block_depr = kobject_create_and_add("block", NULL);
 	return 0;
 }
 
@@ -925,8 +929,15 @@
 {
 	struct disk_part_tbl *ptbl =
 		container_of(head, struct disk_part_tbl, rcu_head);
+	struct gendisk *disk = ptbl->disk;
+	struct request_queue *q = disk->queue;
+	unsigned long flags;
 
 	kfree(ptbl);
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	elv_quiesce_end(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
 /**
@@ -944,11 +955,17 @@
 				  struct disk_part_tbl *new_ptbl)
 {
 	struct disk_part_tbl *old_ptbl = disk->part_tbl;
+	struct request_queue *q = disk->queue;
 
 	rcu_assign_pointer(disk->part_tbl, new_ptbl);
 
 	if (old_ptbl) {
 		rcu_assign_pointer(old_ptbl->last_lookup, NULL);
+
+		spin_lock_irq(q->queue_lock);
+		elv_quiesce_start(q);
+		spin_unlock_irq(q->queue_lock);
+
 		call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb);
 	}
 }
@@ -989,6 +1006,7 @@
 		return -ENOMEM;
 
 	new_ptbl->len = target;
+	new_ptbl->disk = disk;
 
 	for (i = 0; i < len; i++)
 		rcu_assign_pointer(new_ptbl->part[i], old_ptbl->part[i]);
@@ -1004,6 +1022,7 @@
 	kfree(disk->random);
 	disk_replace_part_tbl(disk, NULL);
 	free_part_stats(&disk->part0);
+	free_part_info(&disk->part0);
 	kfree(disk);
 }
 struct class block_class = {
diff --git a/block/ioctl.c b/block/ioctl.c
index d8052f0..d724ceb 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -62,7 +62,7 @@
 
 			/* all seems OK */
 			part = add_partition(disk, partno, start, length,
-					     ADDPART_FLAG_NONE);
+					     ADDPART_FLAG_NONE, NULL);
 			mutex_unlock(&bdev->bd_mutex);
 			return IS_ERR(part) ? PTR_ERR(part) : 0;
 		case BLKPG_DEL_PARTITION:
@@ -116,7 +116,7 @@
 static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
 			     uint64_t len, int secure)
 {
-	unsigned long flags = BLKDEV_IFL_WAIT;
+	unsigned long flags = 0;
 
 	if (start & 511)
 		return -EINVAL;
@@ -128,7 +128,7 @@
 	if (start + len > (bdev->bd_inode->i_size >> 9))
 		return -EINVAL;
 	if (secure)
-		flags |= BLKDEV_IFL_SECURE;
+		flags |= BLKDEV_DISCARD_SECURE;
 	return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, flags);
 }
 
diff --git a/crypto/des_generic.c b/crypto/des_generic.c
index 249f903..873818d 100644
--- a/crypto/des_generic.c
+++ b/crypto/des_generic.c
@@ -614,7 +614,7 @@
 #define T3(x) pt[2 * (x) + 2]
 #define T4(x) pt[2 * (x) + 3]
 
-#define PC2(a, b, c, d) (T4(d) | T3(c) | T2(b) | T1(a))
+#define DES_PC2(a, b, c, d) (T4(d) | T3(c) | T2(b) | T1(a))
 
 /*
  * Encryption key expansion
@@ -639,22 +639,22 @@
 	b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b];
 	a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a];
 
-	pe[15 * 2 + 0] = PC2(a, b, c, d); d = rs[d];
-	pe[14 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[13 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[12 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[11 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[10 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[ 9 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[ 8 * 2 + 0] = PC2(d, a, b, c); c = rs[c];
-	pe[ 7 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[ 6 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[ 5 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[ 4 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[ 3 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[ 2 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[ 1 * 2 + 0] = PC2(c, d, a, b); b = rs[b];
-	pe[ 0 * 2 + 0] = PC2(b, c, d, a);
+	pe[15 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d];
+	pe[14 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[13 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[12 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[11 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[10 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[ 9 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[ 8 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c];
+	pe[ 7 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[ 6 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[ 5 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[ 4 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[ 3 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[ 2 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[ 1 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b];
+	pe[ 0 * 2 + 0] = DES_PC2(b, c, d, a);
 
 	/* Check if first half is weak */
 	w  = (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]);
@@ -670,22 +670,22 @@
 	/* Check if second half is weak */
 	w |= (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]);
 
-	pe[15 * 2 + 1] = PC2(a, b, c, d); d = rs[d];
-	pe[14 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[13 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[12 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[11 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[10 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[ 9 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[ 8 * 2 + 1] = PC2(d, a, b, c); c = rs[c];
-	pe[ 7 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[ 6 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[ 5 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[ 4 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[ 3 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[ 2 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[ 1 * 2 + 1] = PC2(c, d, a, b); b = rs[b];
-	pe[ 0 * 2 + 1] = PC2(b, c, d, a);
+	pe[15 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d];
+	pe[14 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[13 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[12 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[11 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[10 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[ 9 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[ 8 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c];
+	pe[ 7 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[ 6 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[ 5 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[ 4 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[ 3 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[ 2 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[ 1 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b];
+	pe[ 0 * 2 + 1] = DES_PC2(b, c, d, a);
 
 	/* Fixup: 2413 5768 -> 1357 2468 */
 	for (d = 0; d < 16; ++d) {
@@ -722,22 +722,22 @@
 	b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b];
 	a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a];
 
-	pe[ 0 * 2] = PC2(a, b, c, d); d = rs[d];
-	pe[ 1 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[ 2 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[ 3 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[ 4 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[ 5 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[ 6 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[ 7 * 2] = PC2(d, a, b, c); c = rs[c];
-	pe[ 8 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[ 9 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[10 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[11 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[12 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[13 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[14 * 2] = PC2(c, d, a, b); b = rs[b];
-	pe[15 * 2] = PC2(b, c, d, a);
+	pe[ 0 * 2] = DES_PC2(a, b, c, d); d = rs[d];
+	pe[ 1 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[ 2 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[ 3 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[ 4 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[ 5 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[ 6 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[ 7 * 2] = DES_PC2(d, a, b, c); c = rs[c];
+	pe[ 8 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[ 9 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[10 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[11 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[12 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[13 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[14 * 2] = DES_PC2(c, d, a, b); b = rs[b];
+	pe[15 * 2] = DES_PC2(b, c, d, a);
 
 	/* Skip to next table set */
 	pt += 512;
@@ -747,22 +747,22 @@
 	b = k[2]; b &= 0xe0; b >>= 4; b |= k[6] & 0xf0; b = pc1[b + 1];
 	a = k[3]; a &= 0xe0; a >>= 4; a |= k[7] & 0xf0; a = pc1[a + 1];
 
-	pe[ 0 * 2 + 1] = PC2(a, b, c, d); d = rs[d];
-	pe[ 1 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[ 2 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[ 3 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[ 4 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[ 5 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
-	pe[ 6 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
-	pe[ 7 * 2 + 1] = PC2(d, a, b, c); c = rs[c];
-	pe[ 8 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[ 9 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[10 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[11 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[12 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
-	pe[13 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
-	pe[14 * 2 + 1] = PC2(c, d, a, b); b = rs[b];
-	pe[15 * 2 + 1] = PC2(b, c, d, a);
+	pe[ 0 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d];
+	pe[ 1 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[ 2 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[ 3 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[ 4 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[ 5 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+	pe[ 6 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+	pe[ 7 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c];
+	pe[ 8 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[ 9 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[10 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[11 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[12 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+	pe[13 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+	pe[14 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b];
+	pe[15 * 2 + 1] = DES_PC2(b, c, d, a);
 
 	/* Fixup: 2413 5768 -> 1357 2468 */
 	for (d = 0; d < 16; ++d) {
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index b811f21..88681ac 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -105,7 +105,7 @@
 
 	  Be aware that using this interface can confuse your Embedded
 	  Controller in a way that a normal reboot is not enough. You then
-	  have to power of your system, and remove the laptop battery for
+	  have to power off your system, and remove the laptop battery for
 	  some seconds.
 	  An Embedded Controller typically is available on laptops and reads
 	  sensor values like battery state and temperature.
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index b76848c..6afceb3 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -30,18 +30,13 @@
 #include <linux/slab.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
+#include <asm/mwait.h>
 
 #define ACPI_PROCESSOR_AGGREGATOR_CLASS	"acpi_pad"
 #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator"
 #define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80
 static DEFINE_MUTEX(isolated_cpus_lock);
 
-#define MWAIT_SUBSTATE_MASK	(0xf)
-#define MWAIT_CSTATE_MASK	(0xf)
-#define MWAIT_SUBSTATE_SIZE	(4)
-#define CPUID_MWAIT_LEAF (5)
-#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
-#define CPUID5_ECX_INTERRUPT_BREAK	(0x2)
 static unsigned long power_saving_mwait_eax;
 
 static unsigned char tsc_detected_unstable;
@@ -382,31 +377,32 @@
 	device_remove_file(&device->dev, &dev_attr_rrtime);
 }
 
-/* Query firmware how many CPUs should be idle */
-static int acpi_pad_pur(acpi_handle handle, int *num_cpus)
+/*
+ * Query firmware how many CPUs should be idle
+ * return -1 on failure
+ */
+static int acpi_pad_pur(acpi_handle handle)
 {
 	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	union acpi_object *package;
-	int rev, num, ret = -EINVAL;
+	int num = -1;
 
 	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer)))
-		return -EINVAL;
+		return num;
 
 	if (!buffer.length || !buffer.pointer)
-		return -EINVAL;
+		return num;
 
 	package = buffer.pointer;
-	if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2)
-		goto out;
-	rev = package->package.elements[0].integer.value;
-	num = package->package.elements[1].integer.value;
-	if (rev != 1 || num < 0)
-		goto out;
-	*num_cpus = num;
-	ret = 0;
-out:
+
+	if (package->type == ACPI_TYPE_PACKAGE &&
+		package->package.count == 2 &&
+		package->package.elements[0].integer.value == 1) /* rev 1 */
+
+		num = package->package.elements[1].integer.value;
+
 	kfree(buffer.pointer);
-	return ret;
+	return num;
 }
 
 /* Notify firmware how many CPUs are idle */
@@ -433,7 +429,8 @@
 	uint32_t idle_cpus;
 
 	mutex_lock(&isolated_cpus_lock);
-	if (acpi_pad_pur(handle, &num_cpus)) {
+	num_cpus = acpi_pad_pur(handle);
+	if (num_cpus < 0) {
 		mutex_unlock(&isolated_cpus_lock);
 		return;
 	}
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index df85b53..7dad916 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -854,6 +854,7 @@
 	ACPI_BITMASK_POWER_BUTTON_STATUS   | \
 	ACPI_BITMASK_SLEEP_BUTTON_STATUS   | \
 	ACPI_BITMASK_RT_CLOCK_STATUS       | \
+	ACPI_BITMASK_PCIEXP_WAKE_DISABLE   | \
 	ACPI_BITMASK_WAKE_STATUS)
 
 #define ACPI_BITMASK_TIMER_ENABLE               0x0001
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c
index 74c24d5..4093522 100644
--- a/drivers/acpi/acpica/exutils.c
+++ b/drivers/acpi/acpica/exutils.c
@@ -109,7 +109,7 @@
  *
  * DESCRIPTION: Reacquire the interpreter execution region from within the
  *              interpreter code. Failure to enter the interpreter region is a
- *              fatal system error. Used in  conjuction with
+ *              fatal system error. Used in  conjunction with
  *              relinquish_interpreter
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c
index 22cfcfb..491191e 100644
--- a/drivers/acpi/acpica/rsutils.c
+++ b/drivers/acpi/acpica/rsutils.c
@@ -149,7 +149,7 @@
 
 			/*
 			 * 16-, 32-, and 64-bit cases must use the move macros that perform
-			 * endian conversion and/or accomodate hardware that cannot perform
+			 * endian conversion and/or accommodate hardware that cannot perform
 			 * misaligned memory transfers
 			 */
 		case ACPI_RSC_MOVE16:
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index 907e350..fca34cc 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -34,6 +34,6 @@
 	depends on ACPI_APEI
 	help
 	  ERST is a way provided by APEI to save and retrieve hardware
-	  error infomation to and from a persistent store. Enable this
+	  error information to and from a persistent store. Enable this
 	  if you want to debugging and testing the ERST kernel support
 	  and firmware implementation.
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index 73fd0c7..4a904a4 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -445,11 +445,15 @@
 int apei_resources_request(struct apei_resources *resources,
 			   const char *desc)
 {
-	struct apei_res *res, *res_bak;
+	struct apei_res *res, *res_bak = NULL;
 	struct resource *r;
+	int rc;
 
-	apei_resources_sub(resources, &apei_resources_all);
+	rc = apei_resources_sub(resources, &apei_resources_all);
+	if (rc)
+		return rc;
 
+	rc = -EINVAL;
 	list_for_each_entry(res, &resources->iomem, list) {
 		r = request_mem_region(res->start, res->end - res->start,
 				       desc);
@@ -475,7 +479,11 @@
 		}
 	}
 
-	apei_resources_merge(&apei_resources_all, resources);
+	rc = apei_resources_merge(&apei_resources_all, resources);
+	if (rc) {
+		pr_err(APEI_PFX "Fail to merge resources!\n");
+		goto err_unmap_ioport;
+	}
 
 	return 0;
 err_unmap_ioport:
@@ -491,12 +499,13 @@
 			break;
 		release_mem_region(res->start, res->end - res->start);
 	}
-	return -EINVAL;
+	return rc;
 }
 EXPORT_SYMBOL_GPL(apei_resources_request);
 
 void apei_resources_release(struct apei_resources *resources)
 {
+	int rc;
 	struct apei_res *res;
 
 	list_for_each_entry(res, &resources->iomem, list)
@@ -504,7 +513,9 @@
 	list_for_each_entry(res, &resources->ioport, list)
 		release_region(res->start, res->end - res->start);
 
-	apei_resources_sub(&apei_resources_all, resources);
+	rc = apei_resources_sub(&apei_resources_all, resources);
+	if (rc)
+		pr_err(APEI_PFX "Fail to sub resources!\n");
 }
 EXPORT_SYMBOL_GPL(apei_resources_release);
 
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index 465c885..cf29df6 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -426,7 +426,9 @@
 
 static int einj_check_table(struct acpi_table_einj *einj_tab)
 {
-	if (einj_tab->header_length != sizeof(struct acpi_table_einj))
+	if ((einj_tab->header_length !=
+	     (sizeof(struct acpi_table_einj) - sizeof(einj_tab->header)))
+	    && (einj_tab->header_length != sizeof(struct acpi_table_einj)))
 		return -EINVAL;
 	if (einj_tab->header.length < sizeof(struct acpi_table_einj))
 		return -EINVAL;
diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c
index 5281ddd..de73caf 100644
--- a/drivers/acpi/apei/erst-dbg.c
+++ b/drivers/acpi/apei/erst-dbg.c
@@ -2,7 +2,7 @@
  * APEI Error Record Serialization Table debug support
  *
  * ERST is a way provided by APEI to save and retrieve hardware error
- * infomation to and from a persistent store. This file provide the
+ * information to and from a persistent store. This file provide the
  * debugging/testing support for ERST kernel support and firmware
  * implementation.
  *
@@ -111,11 +111,13 @@
 		goto out;
 	}
 	if (len > erst_dbg_buf_len) {
-		kfree(erst_dbg_buf);
+		void *p;
 		rc = -ENOMEM;
-		erst_dbg_buf = kmalloc(len, GFP_KERNEL);
-		if (!erst_dbg_buf)
+		p = kmalloc(len, GFP_KERNEL);
+		if (!p)
 			goto out;
+		kfree(erst_dbg_buf);
+		erst_dbg_buf = p;
 		erst_dbg_buf_len = len;
 		goto retry;
 	}
@@ -150,11 +152,13 @@
 	if (mutex_lock_interruptible(&erst_dbg_mutex))
 		return -EINTR;
 	if (usize > erst_dbg_buf_len) {
-		kfree(erst_dbg_buf);
+		void *p;
 		rc = -ENOMEM;
-		erst_dbg_buf = kmalloc(usize, GFP_KERNEL);
-		if (!erst_dbg_buf)
+		p = kmalloc(usize, GFP_KERNEL);
+		if (!p)
 			goto out;
+		kfree(erst_dbg_buf);
+		erst_dbg_buf = p;
 		erst_dbg_buf_len = usize;
 	}
 	rc = copy_from_user(erst_dbg_buf, ubuf, usize);
@@ -180,6 +184,7 @@
 	.read		= erst_dbg_read,
 	.write		= erst_dbg_write,
 	.unlocked_ioctl	= erst_dbg_ioctl,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice erst_dbg_dev = {
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 18645f4..1211c03 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -2,7 +2,7 @@
  * APEI Error Record Serialization Table support
  *
  * ERST is a way provided by APEI to save and retrieve hardware error
- * infomation to and from a persistent store.
+ * information to and from a persistent store.
  *
  * For more information about ERST, please refer to ACPI Specification
  * version 4.0, section 17.4.
@@ -266,13 +266,30 @@
 {
 	int rc;
 	u64 offset;
+	void *src, *dst;
+
+	/* ioremap does not work in interrupt context */
+	if (in_interrupt()) {
+		pr_warning(ERST_PFX
+			   "MOVE_DATA can not be used in interrupt context");
+		return -EBUSY;
+	}
 
 	rc = __apei_exec_read_register(entry, &offset);
 	if (rc)
 		return rc;
-	memmove((void *)ctx->dst_base + offset,
-		(void *)ctx->src_base + offset,
-		ctx->var2);
+
+	src = ioremap(ctx->src_base + offset, ctx->var2);
+	if (!src)
+		return -ENOMEM;
+	dst = ioremap(ctx->dst_base + offset, ctx->var2);
+	if (!dst)
+		return -ENOMEM;
+
+	memmove(dst, src, ctx->var2);
+
+	iounmap(src);
+	iounmap(dst);
 
 	return 0;
 }
@@ -750,7 +767,9 @@
 
 static int erst_check_table(struct acpi_table_erst *erst_tab)
 {
-	if (erst_tab->header_length != sizeof(struct acpi_table_erst))
+	if ((erst_tab->header_length !=
+	     (sizeof(struct acpi_table_erst) - sizeof(erst_tab->header)))
+	    && (erst_tab->header_length != sizeof(struct acpi_table_einj)))
 		return -EINVAL;
 	if (erst_tab->header.length < sizeof(struct acpi_table_erst))
 		return -EINVAL;
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 385a605..0d505e5 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -302,7 +302,7 @@
 	struct ghes *ghes = NULL;
 	int rc = -EINVAL;
 
-	generic = ghes_dev->dev.platform_data;
+	generic = *(struct acpi_hest_generic **)ghes_dev->dev.platform_data;
 	if (!generic->enabled)
 		return -ENODEV;
 
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index 343168d..1a3508a 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -137,20 +137,23 @@
 
 static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
 {
-	struct acpi_hest_generic *generic;
 	struct platform_device *ghes_dev;
 	struct ghes_arr *ghes_arr = data;
 	int rc;
 
 	if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR)
 		return 0;
-	generic = (struct acpi_hest_generic *)hest_hdr;
-	if (!generic->enabled)
+
+	if (!((struct acpi_hest_generic *)hest_hdr)->enabled)
 		return 0;
 	ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id);
 	if (!ghes_dev)
 		return -ENOMEM;
-	ghes_dev->dev.platform_data = generic;
+
+	rc = platform_device_add_data(ghes_dev, &hest_hdr, sizeof(void *));
+	if (rc)
+		goto err;
+
 	rc = platform_device_add(ghes_dev);
 	if (rc)
 		goto err;
diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c
index 8f8bd73..542e539 100644
--- a/drivers/acpi/atomicio.c
+++ b/drivers/acpi/atomicio.c
@@ -142,7 +142,7 @@
 	list_add_tail_rcu(&map->list, &acpi_iomaps);
 	spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
 
-	return vaddr + (paddr - pg_off);
+	return map->vaddr + (paddr - map->paddr);
 err_unmap:
 	iounmap(vaddr);
 	return NULL;
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index dc58402..9841720 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -273,7 +273,6 @@
 	POWER_SUPPLY_PROP_CYCLE_COUNT,
 	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
-	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_POWER_NOW,
 	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
 	POWER_SUPPLY_PROP_ENERGY_FULL,
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 2bb28b9..af308d0 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -183,6 +183,8 @@
 {
 	printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
 	acpi_osi_setup("!Windows 2006");
+	acpi_osi_setup("!Windows 2006 SP1");
+	acpi_osi_setup("!Windows 2006 SP2");
 	return 0;
 }
 static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
@@ -202,6 +204,23 @@
 		},
 	},
 	{
+	/*
+	 * There have a NVIF method in MSI GX723 DSDT need call by Nvidia
+	 * driver (e.g. nouveau) when user press brightness hotkey.
+	 * Currently, nouveau driver didn't do the job and it causes there
+	 * have a infinite while loop in DSDT when user press hotkey.
+	 * We add MSI GX723's dmi information to this table for workaround
+	 * this issue.
+	 * Will remove MSI GX723 from the table after nouveau grows support.
+	 */
+	.callback = dmi_disable_osi_vista,
+	.ident = "MSI GX723",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
+		},
+	},
+	{
 	.callback = dmi_disable_osi_vista,
 	.ident = "Sony VGN-NS10J_S",
 	.matches = {
@@ -226,6 +245,14 @@
 		},
 	},
 	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Toshiba Satellite L355",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
+		},
+	},
+	{
 	.callback = dmi_disable_osi_win7,
 	.ident = "ASUS K50IJ",
 	.matches = {
@@ -233,6 +260,14 @@
 		     DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
 		},
 	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Toshiba P305D",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
+		},
+	},
 
 	/*
 	 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 5c221ab..310e3b9 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -55,7 +55,7 @@
 static int set_power_nocheck(const struct dmi_system_id *id)
 {
 	printk(KERN_NOTICE PREFIX "%s detected - "
-		"disable power check in power transistion\n", id->ident);
+		"disable power check in power transition\n", id->ident);
 	acpi_power_nocheck = 1;
 	return 0;
 }
@@ -80,23 +80,15 @@
 
 static struct dmi_system_id dsdt_dmi_table[] __initdata = {
 	/*
-	 * Insyde BIOS on some TOSHIBA machines corrupt the DSDT.
+	 * Invoke DSDT corruption work-around on all Toshiba Satellite.
 	 * https://bugzilla.kernel.org/show_bug.cgi?id=14679
 	 */
 	{
 	 .callback = set_copy_dsdt,
-	 .ident = "TOSHIBA Satellite A505",
+	 .ident = "TOSHIBA Satellite",
 	 .matches = {
 		DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A505"),
-		},
-	},
-	{
-	 .callback = set_copy_dsdt,
-	 .ident = "TOSHIBA Satellite L505D",
-	 .matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L505D"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
 		},
 	},
 	{}
@@ -1027,7 +1019,7 @@
 
 	/*
 	 * If the laptop falls into the DMI check table, the power state check
-	 * will be disabled in the course of device power transistion.
+	 * will be disabled in the course of device power transition.
 	 */
 	dmi_check_system(power_nocheck_dmi_table);
 
diff --git a/drivers/acpi/debugfs.c b/drivers/acpi/debugfs.c
index 7de27d4..6355b57 100644
--- a/drivers/acpi/debugfs.c
+++ b/drivers/acpi/debugfs.c
@@ -69,6 +69,7 @@
 
 static const struct file_operations cm_fops = {
 	.write = cm_write,
+	.llseek = default_llseek,
 };
 
 int __init acpi_debugfs_init(void)
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
index 0e869b3..411620e 100644
--- a/drivers/acpi/ec_sys.c
+++ b/drivers/acpi/ec_sys.c
@@ -101,6 +101,7 @@
 	.open  = acpi_ec_open_io,
 	.read  = acpi_ec_read_io,
 	.write = acpi_ec_write_io,
+	.llseek = default_llseek,
 };
 
 int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count)
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index d439314..85d9089 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -110,6 +110,7 @@
 	.read = acpi_system_read_event,
 	.release = acpi_system_close_event,
 	.poll = acpi_system_poll_event,
+	.llseek = default_llseek,
 };
 #endif	/* CONFIG_ACPI_PROC_EVENT */
 
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 8a3b840..d94d295 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -369,7 +369,9 @@
 
 	acpi_bus_unregister_driver(&acpi_fan_driver);
 
+#ifdef CONFIG_ACPI_PROCFS
 	remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
+#endif
 
 	return;
 }
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index e9699aae..bec561c 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -29,12 +29,6 @@
 
 static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
 	{
-	set_no_mwait, "IFL91 board", {
-	DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
-	DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
-	DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
-	DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
-	{
 	set_no_mwait, "Extensa 5220", {
 	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 	DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -352,4 +346,5 @@
 	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
 			    ACPI_UINT32_MAX,
 			    early_init_pdc, NULL, NULL, NULL);
+	acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL);
 }
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 1560218..347eb21 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -850,7 +850,7 @@
 		printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
 			acpi_idle_driver.name);
 	} else {
-		printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s",
+		printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s\n",
 			cpuidle_get_driver()->name);
 	}
 
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index ba1bd26..3a73a93 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -447,8 +447,8 @@
 	if (!try_module_get(calling_module))
 		return -EINVAL;
 
-	/* is_done is set to negative if an error occured,
-	 * and to postitive if _no_ error occured, but SMM
+	/* is_done is set to negative if an error occurred,
+	 * and to postitive if _no_ error occurred, but SMM
 	 * was already notified. This avoids double notification
 	 * which might lead to unexpected results...
 	 */
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index cf82989..4754ff6 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -363,6 +363,12 @@
 	return 0;
 }
 
+static int __init init_nvs_nosave(const struct dmi_system_id *d)
+{
+	acpi_nvs_nosave();
+	return 0;
+}
+
 static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
 	{
 	.callback = init_old_suspend_ordering,
@@ -397,6 +403,22 @@
 		DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
 		},
 	},
+	{
+	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VGN-SR11M",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"),
+		},
+	},
+	{
+	.callback = init_nvs_nosave,
+	.ident = "Everex StepNote Series",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
+		},
+	},
 	{},
 };
 #endif /* CONFIG_SUSPEND */
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 68e2e45..f8588f8 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -100,7 +100,7 @@
 	ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
 };
 
-static int param_get_debug_layer(char *buffer, struct kernel_param *kp)
+static int param_get_debug_layer(char *buffer, const struct kernel_param *kp)
 {
 	int result = 0;
 	int i;
@@ -128,7 +128,7 @@
 	return result;
 }
 
-static int param_get_debug_level(char *buffer, struct kernel_param *kp)
+static int param_get_debug_level(char *buffer, const struct kernel_param *kp)
 {
 	int result = 0;
 	int i;
@@ -149,10 +149,18 @@
 	return result;
 }
 
-module_param_call(debug_layer, param_set_uint, param_get_debug_layer,
-		  &acpi_dbg_layer, 0644);
-module_param_call(debug_level, param_set_uint, param_get_debug_level,
-		  &acpi_dbg_level, 0644);
+static struct kernel_param_ops param_ops_debug_layer = {
+	.set = param_set_uint,
+	.get = param_get_debug_layer,
+};
+
+static struct kernel_param_ops param_ops_debug_level = {
+	.set = param_set_uint,
+	.get = param_get_debug_level,
+};
+
+module_param_cb(debug_layer, &param_ops_debug_layer, &acpi_dbg_layer, 0644);
+module_param_cb(debug_level, &param_ops_debug_level, &acpi_dbg_level, 0644);
 
 static char trace_method_name[6];
 module_param_string(trace_method_name, trace_method_name, 6, 0644);
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index c5fef01..b836761 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -59,8 +59,8 @@
 				  "support\n"));
 		*cap |= ACPI_VIDEO_BACKLIGHT;
 		if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy)))
-			printk(KERN_WARNING FW_BUG PREFIX "ACPI brightness "
-					"control misses _BQC function\n");
+			printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, "
+				"cannot determine initial brightness\n");
 		/* We have backlight support, no need to scan further */
 		return AE_CTRL_TERMINATE;
 	}
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index d31590e..2737b97 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -298,7 +298,7 @@
 
 		amba_put_disable_pclk(dev);
 
-		if (cid == 0xb105f00d)
+		if (cid == AMBA_CID)
 			dev->periphid = pid;
 
 		if (!dev->periphid)
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index d5df04a..c501af5 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -99,7 +99,7 @@
 # Should be last libata driver
 obj-$(CONFIG_PATA_LEGACY)	+= pata_legacy.o
 
-libata-objs	:= libata-core.o libata-scsi.o libata-eh.o
+libata-y	:= libata-core.o libata-scsi.o libata-eh.o libata-transport.o
 libata-$(CONFIG_ATA_SFF)	+= libata-sff.o
 libata-$(CONFIG_SATA_PMP)	+= libata-pmp.o
 libata-$(CONFIG_ATA_ACPI)	+= libata-acpi.o
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index ff1c945..3288263 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -90,6 +90,10 @@
 static int ahci_pci_device_resume(struct pci_dev *pdev);
 #endif
 
+static struct scsi_host_template ahci_sht = {
+	AHCI_SHT("ahci"),
+};
+
 static struct ata_port_operations ahci_vt8251_ops = {
 	.inherits		= &ahci_ops,
 	.hardreset		= ahci_vt8251_hardreset,
@@ -1204,9 +1208,6 @@
 		ata_port_pbar_desc(ap, AHCI_PCI_BAR,
 				   0x100 + ap->port_no * 0x80, "port");
 
-		/* set initial link pm policy */
-		ap->pm_policy = NOT_AVAILABLE;
-
 		/* set enclosure management message type */
 		if (ap->flags & ATA_FLAG_EM)
 			ap->em_message_type = hpriv->em_msg_type;
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 474427b..329cbbb 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -72,6 +72,7 @@
 	AHCI_CMD_RESET		= (1 << 8),
 	AHCI_CMD_CLR_BUSY	= (1 << 10),
 
+	RX_FIS_PIO_SETUP	= 0x20,	/* offset of PIO Setup FIS data */
 	RX_FIS_D2H_REG		= 0x40,	/* offset of D2H Register FIS data */
 	RX_FIS_SDB		= 0x58, /* offset of SDB FIS data */
 	RX_FIS_UNK		= 0x60, /* offset of Unknown FIS data */
@@ -201,7 +202,6 @@
 	AHCI_HFLAG_MV_PATA		= (1 << 4), /* PATA port */
 	AHCI_HFLAG_NO_MSI		= (1 << 5), /* no PCI MSI */
 	AHCI_HFLAG_NO_PMP		= (1 << 6), /* no PMP */
-	AHCI_HFLAG_NO_HOTPLUG		= (1 << 7), /* ignore PxSERR.DIAG.N */
 	AHCI_HFLAG_SECT255		= (1 << 8), /* max 255 sectors */
 	AHCI_HFLAG_YES_NCQ		= (1 << 9), /* force NCQ cap on */
 	AHCI_HFLAG_NO_SUSPEND		= (1 << 10), /* don't suspend */
@@ -216,7 +216,7 @@
 	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_IPM,
+					  ATA_FLAG_LPM,
 
 	ICH_MAP				= 0x90, /* ICH MAP register */
 
@@ -298,7 +298,17 @@
 
 extern int ahci_ignore_sss;
 
-extern struct scsi_host_template ahci_sht;
+extern struct device_attribute *ahci_shost_attrs[];
+extern struct device_attribute *ahci_sdev_attrs[];
+
+#define AHCI_SHT(drv_name)						\
+	ATA_NCQ_SHT(drv_name),						\
+	.can_queue		= AHCI_MAX_CMDS - 1,			\
+	.sg_tablesize		= AHCI_MAX_SG,				\
+	.dma_boundary		= AHCI_DMA_BOUNDARY,			\
+	.shost_attrs		= ahci_shost_attrs,			\
+	.sdev_attrs		= ahci_sdev_attrs
+
 extern struct ata_port_operations ahci_ops;
 
 void ahci_save_initial_config(struct device *dev,
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 4e97f33..6fef1fa 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -23,6 +23,10 @@
 #include <linux/ahci_platform.h>
 #include "ahci.h"
 
+static struct scsi_host_template ahci_platform_sht = {
+	AHCI_SHT("ahci_platform"),
+};
+
 static int __init ahci_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -125,9 +129,6 @@
 		ata_port_desc(ap, "mmio %pR", mem);
 		ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
 
-		/* set initial link pm policy */
-		ap->pm_policy = NOT_AVAILABLE;
-
 		/* set enclosure management message type */
 		if (ap->flags & ATA_FLAG_EM)
 			ap->em_message_type = hpriv->em_msg_type;
@@ -145,7 +146,7 @@
 	ahci_print_info(host, "platform");
 
 	rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
-			       &ahci_sht);
+			       &ahci_platform_sht);
 	if (rc)
 		goto err0;
 
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index cc5f772..6981f76 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -35,6 +35,7 @@
 enum {
 	ATA_GEN_CLASS_MATCH		= (1 << 0),
 	ATA_GEN_FORCE_DMA		= (1 << 1),
+	ATA_GEN_INTEL_IDER		= (1 << 2),
 };
 
 /**
@@ -109,6 +110,49 @@
 static int all_generic_ide;		/* Set to claim all devices */
 
 /**
+ *	is_intel_ider		-	identify intel IDE-R devices
+ *	@dev: PCI device
+ *
+ *	Distinguish Intel IDE-R controller devices from other Intel IDE
+ *	devices. IDE-R devices have no timing registers and are in
+ *	most respects virtual. They should be driven by the ata_generic
+ *	driver.
+ *
+ *	IDE-R devices have PCI offset 0xF8.L as zero, later Intel ATA has
+ *	it non zero. All Intel ATA has 0x40 writable (timing), but it is
+ *	not writable on IDE-R devices (this is guaranteed).
+ */
+
+static int is_intel_ider(struct pci_dev *dev)
+{
+	/* For Intel IDE the value at 0xF8 is only zero on IDE-R
+	   interfaces */
+	u32 r;
+	u16 t;
+
+	/* Check the manufacturing ID, it will be zero for IDE-R */
+	pci_read_config_dword(dev, 0xF8, &r);
+	/* Not IDE-R: punt so that ata_(old)piix gets it */
+	if (r != 0)
+		return 0;
+	/* 0xF8 will also be zero on some early Intel IDE devices
+	   but they will have a sane timing register */
+	pci_read_config_word(dev, 0x40, &t);
+	if (t != 0)
+		return 0;
+	/* Finally check if the timing register is writable so that
+	   we eliminate any early devices hot-docked in a docking
+	   station */
+	pci_write_config_word(dev, 0x40, 1);
+	pci_read_config_word(dev, 0x40, &t);
+	if (t) {
+		pci_write_config_word(dev, 0x40, 0);
+		return 0;
+	}
+	return 1;
+}
+
+/**
  *	ata_generic_init		-	attach generic IDE
  *	@dev: PCI device found
  *	@id: match entry
@@ -134,6 +178,10 @@
 	if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0)
 		return -ENODEV;
 
+	if (id->driver_data & ATA_GEN_INTEL_IDER)
+		if (!is_intel_ider(dev))
+			return -ENODEV;
+
 	/* Devices that need care */
 	if (dev->vendor == PCI_VENDOR_ID_UMC &&
 	    dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
@@ -186,7 +234,11 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),  },
 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_3),  },
 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5),  },
-#endif	
+#endif
+	/* Intel, IDE class device */
+	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+	  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),
 	  .driver_data = ATA_GEN_CLASS_MATCH },
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index d712675..6cb14ca 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -158,7 +158,6 @@
 struct piix_host_priv {
 	const int *map;
 	u32 saved_iocfg;
-	spinlock_t sidpr_lock;	/* FIXME: remove once locking in EH is fixed */
 	void __iomem *sidpr;
 };
 
@@ -175,6 +174,8 @@
 			       unsigned int reg, u32 *val);
 static int piix_sidpr_scr_write(struct ata_link *link,
 				unsigned int reg, u32 val);
+static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+			      unsigned hints);
 static bool piix_irq_check(struct ata_port *ap);
 #ifdef CONFIG_PM
 static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
@@ -209,6 +210,8 @@
 	{ 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
 	/* Intel ICH3 (E7500/1) UDMA 100 */
 	{ 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+	/* Intel ICH4-L */
+	{ 0x8086, 0x24C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
 	/* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */
 	{ 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
 	{ 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
@@ -348,11 +351,22 @@
 	.set_dmamode		= ich_set_dmamode,
 };
 
+static struct device_attribute *piix_sidpr_shost_attrs[] = {
+	&dev_attr_link_power_management_policy,
+	NULL
+};
+
+static struct scsi_host_template piix_sidpr_sht = {
+	ATA_BMDMA_SHT(DRV_NAME),
+	.shost_attrs		= piix_sidpr_shost_attrs,
+};
+
 static struct ata_port_operations piix_sidpr_sata_ops = {
 	.inherits		= &piix_sata_ops,
 	.hardreset		= sata_std_hardreset,
 	.scr_read		= piix_sidpr_scr_read,
 	.scr_write		= piix_sidpr_scr_write,
+	.set_lpm		= piix_sidpr_set_lpm,
 };
 
 static const struct piix_map_db ich5_map_db = {
@@ -956,15 +970,12 @@
 			       unsigned int reg, u32 *val)
 {
 	struct piix_host_priv *hpriv = link->ap->host->private_data;
-	unsigned long flags;
 
 	if (reg >= ARRAY_SIZE(piix_sidx_map))
 		return -EINVAL;
 
-	spin_lock_irqsave(&hpriv->sidpr_lock, flags);
 	piix_sidpr_sel(link, reg);
 	*val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
-	spin_unlock_irqrestore(&hpriv->sidpr_lock, flags);
 	return 0;
 }
 
@@ -972,18 +983,21 @@
 				unsigned int reg, u32 val)
 {
 	struct piix_host_priv *hpriv = link->ap->host->private_data;
-	unsigned long flags;
 
 	if (reg >= ARRAY_SIZE(piix_sidx_map))
 		return -EINVAL;
 
-	spin_lock_irqsave(&hpriv->sidpr_lock, flags);
 	piix_sidpr_sel(link, reg);
 	iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
-	spin_unlock_irqrestore(&hpriv->sidpr_lock, flags);
 	return 0;
 }
 
+static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+			      unsigned hints)
+{
+	return sata_link_scr_lpm(link, policy, false);
+}
+
 static bool piix_irq_check(struct ata_port *ap)
 {
 	if (unlikely(!ap->ioaddr.bmdma_addr))
@@ -1543,6 +1557,7 @@
 	struct device *dev = &pdev->dev;
 	struct ata_port_info port_info[2];
 	const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
+	struct scsi_host_template *sht = &piix_sht;
 	unsigned long port_flags;
 	struct ata_host *host;
 	struct piix_host_priv *hpriv;
@@ -1577,7 +1592,6 @@
 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
 	if (!hpriv)
 		return -ENOMEM;
-	spin_lock_init(&hpriv->sidpr_lock);
 
 	/* Save IOCFG, this will be used for cable detection, quirk
 	 * detection and restoration on detach.  This is necessary
@@ -1612,6 +1626,8 @@
 		rc = piix_init_sidpr(host);
 		if (rc)
 			return rc;
+		if (host->ports[0]->ops == &piix_sidpr_sata_ops)
+			sht = &piix_sidpr_sht;
 	}
 
 	/* apply IOCFG bit18 quirk */
@@ -1638,7 +1654,7 @@
 	host->flags |= ATA_HOST_PARALLEL_SCAN;
 
 	pci_set_master(pdev);
-	return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &piix_sht);
+	return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
 }
 
 static void piix_remove_one(struct pci_dev *pdev)
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 68dc678..ebc08d65 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -56,9 +56,8 @@
 module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
 MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");
 
-static int ahci_enable_alpm(struct ata_port *ap,
-		enum link_pm policy);
-static void ahci_disable_alpm(struct ata_port *ap);
+static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+			unsigned hints);
 static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
 static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
 			      size_t size);
@@ -121,7 +120,7 @@
 static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
 		   ahci_read_em_buffer, ahci_store_em_buffer);
 
-static struct device_attribute *ahci_shost_attrs[] = {
+struct device_attribute *ahci_shost_attrs[] = {
 	&dev_attr_link_power_management_policy,
 	&dev_attr_em_message_type,
 	&dev_attr_em_message,
@@ -132,22 +131,14 @@
 	&dev_attr_em_buffer,
 	NULL
 };
+EXPORT_SYMBOL_GPL(ahci_shost_attrs);
 
-static struct device_attribute *ahci_sdev_attrs[] = {
+struct device_attribute *ahci_sdev_attrs[] = {
 	&dev_attr_sw_activity,
 	&dev_attr_unload_heads,
 	NULL
 };
-
-struct scsi_host_template ahci_sht = {
-	ATA_NCQ_SHT("ahci"),
-	.can_queue		= AHCI_MAX_CMDS - 1,
-	.sg_tablesize		= AHCI_MAX_SG,
-	.dma_boundary		= AHCI_DMA_BOUNDARY,
-	.shost_attrs		= ahci_shost_attrs,
-	.sdev_attrs		= ahci_sdev_attrs,
-};
-EXPORT_SYMBOL_GPL(ahci_sht);
+EXPORT_SYMBOL_GPL(ahci_sdev_attrs);
 
 struct ata_port_operations ahci_ops = {
 	.inherits		= &sata_pmp_port_ops,
@@ -172,8 +163,7 @@
 	.pmp_attach		= ahci_pmp_attach,
 	.pmp_detach		= ahci_pmp_detach,
 
-	.enable_pm		= ahci_enable_alpm,
-	.disable_pm		= ahci_disable_alpm,
+	.set_lpm		= ahci_set_lpm,
 	.em_show		= ahci_led_show,
 	.em_store		= ahci_led_store,
 	.sw_activity_show	= ahci_activity_show,
@@ -577,7 +567,7 @@
 	writel(tmp, port_mmio + PORT_CMD);
 
 	/* wait for engine to stop. This could be as long as 500 msec */
-	tmp = ata_wait_register(port_mmio + PORT_CMD,
+	tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
 				PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
 	if (tmp & PORT_CMD_LIST_ON)
 		return -EIO;
@@ -624,7 +614,7 @@
 	writel(tmp, port_mmio + PORT_CMD);
 
 	/* wait for completion, spec says 500ms, give it 1000 */
-	tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
+	tmp = ata_wait_register(ap, port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
 				PORT_CMD_FIS_ON, 10, 1000);
 	if (tmp & PORT_CMD_FIS_ON)
 		return -EBUSY;
@@ -650,127 +640,56 @@
 	writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
 }
 
-static void ahci_disable_alpm(struct ata_port *ap)
+static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+			unsigned int hints)
 {
+	struct ata_port *ap = link->ap;
 	struct ahci_host_priv *hpriv = ap->host->private_data;
-	void __iomem *port_mmio = ahci_port_base(ap);
-	u32 cmd;
 	struct ahci_port_priv *pp = ap->private_data;
-
-	/* IPM bits should be disabled by libata-core */
-	/* get the existing command bits */
-	cmd = readl(port_mmio + PORT_CMD);
-
-	/* disable ALPM and ASP */
-	cmd &= ~PORT_CMD_ASP;
-	cmd &= ~PORT_CMD_ALPE;
-
-	/* force the interface back to active */
-	cmd |= PORT_CMD_ICC_ACTIVE;
-
-	/* write out new cmd value */
-	writel(cmd, port_mmio + PORT_CMD);
-	cmd = readl(port_mmio + PORT_CMD);
-
-	/* wait 10ms to be sure we've come out of any low power state */
-	msleep(10);
-
-	/* clear out any PhyRdy stuff from interrupt status */
-	writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
-
-	/* go ahead and clean out PhyRdy Change from Serror too */
-	ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
-
-	/*
-	 * Clear flag to indicate that we should ignore all PhyRdy
-	 * state changes
-	 */
-	hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
-
-	/*
-	 * Enable interrupts on Phy Ready.
-	 */
-	pp->intr_mask |= PORT_IRQ_PHYRDY;
-	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
-
-	/*
-	 * don't change the link pm policy - we can be called
-	 * just to turn of link pm temporarily
-	 */
-}
-
-static int ahci_enable_alpm(struct ata_port *ap,
-	enum link_pm policy)
-{
-	struct ahci_host_priv *hpriv = ap->host->private_data;
 	void __iomem *port_mmio = ahci_port_base(ap);
-	u32 cmd;
-	struct ahci_port_priv *pp = ap->private_data;
-	u32 asp;
 
-	/* Make sure the host is capable of link power management */
-	if (!(hpriv->cap & HOST_CAP_ALPM))
-		return -EINVAL;
-
-	switch (policy) {
-	case MAX_PERFORMANCE:
-	case NOT_AVAILABLE:
+	if (policy != ATA_LPM_MAX_POWER) {
 		/*
-		 * if we came here with NOT_AVAILABLE,
-		 * it just means this is the first time we
-		 * have tried to enable - default to max performance,
-		 * and let the user go to lower power modes on request.
+		 * Disable interrupts on Phy Ready. This keeps us from
+		 * getting woken up due to spurious phy ready
+		 * interrupts.
 		 */
-		ahci_disable_alpm(ap);
-		return 0;
-	case MIN_POWER:
-		/* configure HBA to enter SLUMBER */
-		asp = PORT_CMD_ASP;
-		break;
-	case MEDIUM_POWER:
-		/* configure HBA to enter PARTIAL */
-		asp = 0;
-		break;
-	default:
-		return -EINVAL;
+		pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+		writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+		sata_link_scr_lpm(link, policy, false);
 	}
 
-	/*
-	 * Disable interrupts on Phy Ready. This keeps us from
-	 * getting woken up due to spurious phy ready interrupts
-	 * TBD - Hot plug should be done via polling now, is
-	 * that even supported?
-	 */
-	pp->intr_mask &= ~PORT_IRQ_PHYRDY;
-	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+	if (hpriv->cap & HOST_CAP_ALPM) {
+		u32 cmd = readl(port_mmio + PORT_CMD);
 
-	/*
-	 * Set a flag to indicate that we should ignore all PhyRdy
-	 * state changes since these can happen now whenever we
-	 * change link state
-	 */
-	hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
+		if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) {
+			cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
+			cmd |= PORT_CMD_ICC_ACTIVE;
 
-	/* get the existing command bits */
-	cmd = readl(port_mmio + PORT_CMD);
+			writel(cmd, port_mmio + PORT_CMD);
+			readl(port_mmio + PORT_CMD);
 
-	/*
-	 * Set ASP based on Policy
-	 */
-	cmd |= asp;
+			/* wait 10ms to be sure we've come out of LPM state */
+			ata_msleep(ap, 10);
+		} else {
+			cmd |= PORT_CMD_ALPE;
+			if (policy == ATA_LPM_MIN_POWER)
+				cmd |= PORT_CMD_ASP;
 
-	/*
-	 * Setting this bit will instruct the HBA to aggressively
-	 * enter a lower power link state when it's appropriate and
-	 * based on the value set above for ASP
-	 */
-	cmd |= PORT_CMD_ALPE;
+			/* write out new cmd value */
+			writel(cmd, port_mmio + PORT_CMD);
+		}
+	}
 
-	/* write out new cmd value */
-	writel(cmd, port_mmio + PORT_CMD);
-	cmd = readl(port_mmio + PORT_CMD);
+	if (policy == ATA_LPM_MAX_POWER) {
+		sata_link_scr_lpm(link, policy, false);
 
-	/* IPM bits should be set by libata-core */
+		/* turn PHYRDY IRQ back on */
+		pp->intr_mask |= PORT_IRQ_PHYRDY;
+		writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+	}
+
 	return 0;
 }
 
@@ -821,7 +740,7 @@
 							       emp->led_state,
 							       4);
 				if (rc == -EBUSY)
-					msleep(1);
+					ata_msleep(ap, 1);
 				else
 					break;
 			}
@@ -880,7 +799,7 @@
 		 * reset must complete within 1 second, or
 		 * the hardware should be considered fried.
 		 */
-		tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET,
+		tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET,
 					HOST_RESET, 10, 1000);
 
 		if (tmp & HOST_RESET) {
@@ -1260,7 +1179,7 @@
 	writel(tmp, port_mmio + PORT_CMD);
 
 	rc = 0;
-	tmp = ata_wait_register(port_mmio + PORT_CMD,
+	tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
 				PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
 	if (tmp & PORT_CMD_CLO)
 		rc = -EIO;
@@ -1290,8 +1209,8 @@
 	writel(1, port_mmio + PORT_CMD_ISSUE);
 
 	if (timeout_msec) {
-		tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1,
-					1, timeout_msec);
+		tmp = ata_wait_register(ap, port_mmio + PORT_CMD_ISSUE,
+					0x1, 0x1, 1, timeout_msec);
 		if (tmp & 0x1) {
 			ahci_kick_engine(ap);
 			return -EBUSY;
@@ -1338,7 +1257,7 @@
 	}
 
 	/* spec says at least 5us, but be generous and sleep for 1ms */
-	msleep(1);
+	ata_msleep(ap, 1);
 
 	/* issue the second D2H Register FIS */
 	tf.ctl &= ~ATA_SRST;
@@ -1668,15 +1587,10 @@
 	if (unlikely(resetting))
 		status &= ~PORT_IRQ_BAD_PMP;
 
-	/* If we are getting PhyRdy, this is
-	 * just a power state change, we should
-	 * clear out this, plus the PhyRdy/Comm
-	 * Wake bits from Serror
-	 */
-	if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
-		(status & PORT_IRQ_PHYRDY)) {
+	/* if LPM is enabled, PHYRDY doesn't mean anything */
+	if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
 		status &= ~PORT_IRQ_PHYRDY;
-		ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
+		ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
 	}
 
 	if (unlikely(status & PORT_IRQ_ERROR)) {
@@ -1838,12 +1752,24 @@
 static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
 {
 	struct ahci_port_priv *pp = qc->ap->private_data;
-	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+	u8 *rx_fis = pp->rx_fis;
 
 	if (pp->fbs_enabled)
-		d2h_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
+		rx_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
 
-	ata_tf_from_fis(d2h_fis, &qc->result_tf);
+	/*
+	 * After a successful execution of an ATA PIO data-in command,
+	 * the device doesn't send D2H Reg FIS to update the TF and
+	 * the host should take TF and E_Status from the preceding PIO
+	 * Setup FIS.
+	 */
+	if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE &&
+	    !(qc->flags & ATA_QCFLAG_FAILED)) {
+		ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf);
+		qc->result_tf.command = (rx_fis + RX_FIS_PIO_SETUP)[15];
+	} else
+		ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf);
+
 	return true;
 }
 
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 932eaee..7f77c67 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -68,7 +68,7 @@
 #include <linux/ratelimit.h>
 
 #include "libata.h"
-
+#include "libata-transport.h"
 
 /* debounce timing parameters in msecs { interval, duration, timeout } */
 const unsigned long sata_deb_timing_normal[]		= {   5,  100, 2000 };
@@ -91,8 +91,6 @@
 static unsigned int ata_dev_init_params(struct ata_device *dev,
 					u16 heads, u16 sectors);
 static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
-static unsigned int ata_dev_set_feature(struct ata_device *dev,
-					u8 enable, u8 feature);
 static void ata_dev_xfermask(struct ata_device *dev);
 static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
 
@@ -1017,7 +1015,7 @@
 	return "<n/a>";
 }
 
-static const char *sata_spd_string(unsigned int spd)
+const char *sata_spd_string(unsigned int spd)
 {
 	static const char * const spd_str[] = {
 		"1.5 Gbps",
@@ -1030,182 +1028,6 @@
 	return spd_str[spd - 1];
 }
 
-static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)
-{
-	struct ata_link *link = dev->link;
-	struct ata_port *ap = link->ap;
-	u32 scontrol;
-	unsigned int err_mask;
-	int rc;
-
-	/*
-	 * disallow DIPM for drivers which haven't set
-	 * ATA_FLAG_IPM.  This is because when DIPM is enabled,
-	 * phy ready will be set in the interrupt status on
-	 * state changes, which will cause some drivers to
-	 * think there are errors - additionally drivers will
-	 * need to disable hot plug.
-	 */
-	if (!(ap->flags & ATA_FLAG_IPM) || !ata_dev_enabled(dev)) {
-		ap->pm_policy = NOT_AVAILABLE;
-		return -EINVAL;
-	}
-
-	/*
-	 * For DIPM, we will only enable it for the
-	 * min_power setting.
-	 *
-	 * Why?  Because Disks are too stupid to know that
-	 * If the host rejects a request to go to SLUMBER
-	 * they should retry at PARTIAL, and instead it
-	 * just would give up.  So, for medium_power to
-	 * work at all, we need to only allow HIPM.
-	 */
-	rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
-	if (rc)
-		return rc;
-
-	switch (policy) {
-	case MIN_POWER:
-		/* no restrictions on IPM transitions */
-		scontrol &= ~(0x3 << 8);
-		rc = sata_scr_write(link, SCR_CONTROL, scontrol);
-		if (rc)
-			return rc;
-
-		/* enable DIPM */
-		if (dev->flags & ATA_DFLAG_DIPM)
-			err_mask = ata_dev_set_feature(dev,
-					SETFEATURES_SATA_ENABLE, SATA_DIPM);
-		break;
-	case MEDIUM_POWER:
-		/* allow IPM to PARTIAL */
-		scontrol &= ~(0x1 << 8);
-		scontrol |= (0x2 << 8);
-		rc = sata_scr_write(link, SCR_CONTROL, scontrol);
-		if (rc)
-			return rc;
-
-		/*
-		 * we don't have to disable DIPM since IPM flags
-		 * disallow transitions to SLUMBER, which effectively
-		 * disable DIPM if it does not support PARTIAL
-		 */
-		break;
-	case NOT_AVAILABLE:
-	case MAX_PERFORMANCE:
-		/* disable all IPM transitions */
-		scontrol |= (0x3 << 8);
-		rc = sata_scr_write(link, SCR_CONTROL, scontrol);
-		if (rc)
-			return rc;
-
-		/*
-		 * we don't have to disable DIPM since IPM flags
-		 * disallow all transitions which effectively
-		 * disable DIPM anyway.
-		 */
-		break;
-	}
-
-	/* FIXME: handle SET FEATURES failure */
-	(void) err_mask;
-
-	return 0;
-}
-
-/**
- *	ata_dev_enable_pm - enable SATA interface power management
- *	@dev:  device to enable power management
- *	@policy: the link power management policy
- *
- *	Enable SATA Interface power management.  This will enable
- *	Device Interface Power Management (DIPM) for min_power
- * 	policy, and then call driver specific callbacks for
- *	enabling Host Initiated Power management.
- *
- *	Locking: Caller.
- *	Returns: -EINVAL if IPM is not supported, 0 otherwise.
- */
-void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy)
-{
-	int rc = 0;
-	struct ata_port *ap = dev->link->ap;
-
-	/* set HIPM first, then DIPM */
-	if (ap->ops->enable_pm)
-		rc = ap->ops->enable_pm(ap, policy);
-	if (rc)
-		goto enable_pm_out;
-	rc = ata_dev_set_dipm(dev, policy);
-
-enable_pm_out:
-	if (rc)
-		ap->pm_policy = MAX_PERFORMANCE;
-	else
-		ap->pm_policy = policy;
-	return /* rc */;	/* hopefully we can use 'rc' eventually */
-}
-
-#ifdef CONFIG_PM
-/**
- *	ata_dev_disable_pm - disable SATA interface power management
- *	@dev: device to disable power management
- *
- *	Disable SATA Interface power management.  This will disable
- *	Device Interface Power Management (DIPM) without changing
- * 	policy,  call driver specific callbacks for disabling Host
- * 	Initiated Power management.
- *
- *	Locking: Caller.
- *	Returns: void
- */
-static void ata_dev_disable_pm(struct ata_device *dev)
-{
-	struct ata_port *ap = dev->link->ap;
-
-	ata_dev_set_dipm(dev, MAX_PERFORMANCE);
-	if (ap->ops->disable_pm)
-		ap->ops->disable_pm(ap);
-}
-#endif	/* CONFIG_PM */
-
-void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy)
-{
-	ap->pm_policy = policy;
-	ap->link.eh_info.action |= ATA_EH_LPM;
-	ap->link.eh_info.flags |= ATA_EHI_NO_AUTOPSY;
-	ata_port_schedule_eh(ap);
-}
-
-#ifdef CONFIG_PM
-static void ata_lpm_enable(struct ata_host *host)
-{
-	struct ata_link *link;
-	struct ata_port *ap;
-	struct ata_device *dev;
-	int i;
-
-	for (i = 0; i < host->n_ports; i++) {
-		ap = host->ports[i];
-		ata_for_each_link(link, ap, EDGE) {
-			ata_for_each_dev(dev, link, ALL)
-				ata_dev_disable_pm(dev);
-		}
-	}
-}
-
-static void ata_lpm_disable(struct ata_host *host)
-{
-	int i;
-
-	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
-		ata_lpm_schedule(ap, ap->pm_policy);
-	}
-}
-#endif	/* CONFIG_PM */
-
 /**
  *	ata_dev_classify - determine device type based on ATA-spec signature
  *	@tf: ATA taskfile register set for device to be identified
@@ -1806,8 +1628,14 @@
 		}
 	}
 
+	if (ap->ops->error_handler)
+		ata_eh_release(ap);
+
 	rc = wait_for_completion_timeout(&wait, msecs_to_jiffies(timeout));
 
+	if (ap->ops->error_handler)
+		ata_eh_acquire(ap);
+
 	ata_sff_flush_pio_task(ap);
 
 	if (!rc) {
@@ -2564,13 +2392,6 @@
 	if (dev->flags & ATA_DFLAG_LBA48)
 		dev->max_sectors = ATA_MAX_SECTORS_LBA48;
 
-	if (!(dev->horkage & ATA_HORKAGE_IPM)) {
-		if (ata_id_has_hipm(dev->id))
-			dev->flags |= ATA_DFLAG_HIPM;
-		if (ata_id_has_dipm(dev->id))
-			dev->flags |= ATA_DFLAG_DIPM;
-	}
-
 	/* Limit PATA drive on SATA cable bridge transfers to udma5,
 	   200 sectors */
 	if (ata_dev_knobble(dev)) {
@@ -2591,13 +2412,6 @@
 		dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
 					 dev->max_sectors);
 
-	if (ata_dev_blacklisted(dev) & ATA_HORKAGE_IPM) {
-		dev->horkage |= ATA_HORKAGE_IPM;
-
-		/* reset link pm_policy for this port to no pm */
-		ap->pm_policy = MAX_PERFORMANCE;
-	}
-
 	if (ap->ops->dev_config)
 		ap->ops->dev_config(dev);
 
@@ -3596,7 +3410,7 @@
 			warned = 1;
 		}
 
-		msleep(50);
+		ata_msleep(link->ap, 50);
 	}
 }
 
@@ -3617,7 +3431,7 @@
 int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
 				int (*check_ready)(struct ata_link *link))
 {
-	msleep(ATA_WAIT_AFTER_RESET);
+	ata_msleep(link->ap, ATA_WAIT_AFTER_RESET);
 
 	return ata_wait_ready(link, deadline, check_ready);
 }
@@ -3628,7 +3442,7 @@
  *	@params: timing parameters { interval, duratinon, timeout } in msec
  *	@deadline: deadline jiffies for the operation
  *
-*	Make sure SStatus of @link reaches stable state, determined by
+ *	Make sure SStatus of @link reaches stable state, determined by
  *	holding the same value where DET is not 1 for @duration polled
  *	every @interval, before @timeout.  Timeout constraints the
  *	beginning of the stable state.  Because DET gets stuck at 1 on
@@ -3665,7 +3479,7 @@
 	last_jiffies = jiffies;
 
 	while (1) {
-		msleep(interval);
+		ata_msleep(link->ap, interval);
 		if ((rc = sata_scr_read(link, SCR_STATUS, &cur)))
 			return rc;
 		cur &= 0xf;
@@ -3730,7 +3544,7 @@
 		 * immediately after resuming.  Delay 200ms before
 		 * debouncing.
 		 */
-		msleep(200);
+		ata_msleep(link->ap, 200);
 
 		/* is SControl restored correctly? */
 		if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
@@ -3760,6 +3574,72 @@
 }
 
 /**
+ *	sata_link_scr_lpm - manipulate SControl IPM and SPM fields
+ *	@link: ATA link to manipulate SControl for
+ *	@policy: LPM policy to configure
+ *	@spm_wakeup: initiate LPM transition to active state
+ *
+ *	Manipulate the IPM field of the SControl register of @link
+ *	according to @policy.  If @policy is ATA_LPM_MAX_POWER and
+ *	@spm_wakeup is %true, the SPM field is manipulated to wake up
+ *	the link.  This function also clears PHYRDY_CHG before
+ *	returning.
+ *
+ *	LOCKING:
+ *	EH context.
+ *
+ *	RETURNS:
+ *	0 on succes, -errno otherwise.
+ */
+int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+		      bool spm_wakeup)
+{
+	struct ata_eh_context *ehc = &link->eh_context;
+	bool woken_up = false;
+	u32 scontrol;
+	int rc;
+
+	rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
+	if (rc)
+		return rc;
+
+	switch (policy) {
+	case ATA_LPM_MAX_POWER:
+		/* disable all LPM transitions */
+		scontrol |= (0x3 << 8);
+		/* initiate transition to active state */
+		if (spm_wakeup) {
+			scontrol |= (0x4 << 12);
+			woken_up = true;
+		}
+		break;
+	case ATA_LPM_MED_POWER:
+		/* allow LPM to PARTIAL */
+		scontrol &= ~(0x1 << 8);
+		scontrol |= (0x2 << 8);
+		break;
+	case ATA_LPM_MIN_POWER:
+		/* no restrictions on LPM transitions */
+		scontrol &= ~(0x3 << 8);
+		break;
+	default:
+		WARN_ON(1);
+	}
+
+	rc = sata_scr_write(link, SCR_CONTROL, scontrol);
+	if (rc)
+		return rc;
+
+	/* give the link time to transit out of LPM state */
+	if (woken_up)
+		msleep(10);
+
+	/* clear PHYRDY_CHG from SError */
+	ehc->i.serror &= ~SERR_PHYRDY_CHG;
+	return sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
+}
+
+/**
  *	ata_std_prereset - prepare for reset
  *	@link: ATA link to be reset
  *	@deadline: deadline jiffies for the operation
@@ -3868,7 +3748,7 @@
 	/* Couldn't find anything in SATA I/II specs, but AHCI-1.1
 	 * 10.4.2 says at least 1 ms.
 	 */
-	msleep(1);
+	ata_msleep(link->ap, 1);
 
 	/* bring link back */
 	rc = sata_link_resume(link, timing, deadline);
@@ -4551,6 +4431,7 @@
 	DPRINTK("EXIT, err_mask=%x\n", err_mask);
 	return err_mask;
 }
+
 /**
  *	ata_dev_set_feature - Issue SET FEATURES - SATA FEATURES
  *	@dev: Device to which command will be sent
@@ -4566,8 +4447,7 @@
  *	RETURNS:
  *	0 on success, AC_ERR_* mask otherwise.
  */
-static unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable,
-					u8 feature)
+unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, u8 feature)
 {
 	struct ata_taskfile tf;
 	unsigned int err_mask;
@@ -4943,8 +4823,13 @@
  *	ata_qc_complete - Complete an active ATA command
  *	@qc: Command to complete
  *
- *	Indicate to the mid and upper layers that an ATA
- *	command has completed, with either an ok or not-ok status.
+ *	Indicate to the mid and upper layers that an ATA command has
+ *	completed, with either an ok or not-ok status.
+ *
+ *	Refrain from calling this function multiple times when
+ *	successfully completing multiple NCQ commands.
+ *	ata_qc_complete_multiple() should be used instead, which will
+ *	properly update IRQ expect state.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
@@ -5037,6 +4922,10 @@
  *	requests normally.  ap->qc_active and @qc_active is compared
  *	and commands are completed accordingly.
  *
+ *	Always use this function when completing multiple NCQ commands
+ *	from IRQ handlers instead of calling ata_qc_complete()
+ *	multiple times to keep IRQ expect status properly in sync.
+ *
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
  *
@@ -5422,12 +5311,6 @@
 	int rc;
 
 	/*
-	 * disable link pm on all ports before requesting
-	 * any pm activity
-	 */
-	ata_lpm_enable(host);
-
-	/*
 	 * On some hardware, device fails to respond after spun down
 	 * for suspend.  As the device won't be used before being
 	 * resumed, we don't need to touch the device.  Ask EH to skip
@@ -5460,9 +5343,6 @@
 	ata_host_request_pm(host, PMSG_ON, ATA_EH_RESET,
 			    ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
 	host->dev->power.power_state = PMSG_ON;
-
-	/* reenable link pm */
-	ata_lpm_disable(host);
 }
 #endif
 
@@ -5517,7 +5397,8 @@
 	int i;
 
 	/* clear everything except for devices */
-	memset(link, 0, offsetof(struct ata_link, device[0]));
+	memset((void *)link + ATA_LINK_CLEAR_BEGIN, 0,
+	       ATA_LINK_CLEAR_END - ATA_LINK_CLEAR_BEGIN);
 
 	link->ap = ap;
 	link->pmp = pmp;
@@ -5591,7 +5472,7 @@
 	ap = kzalloc(sizeof(*ap), GFP_KERNEL);
 	if (!ap)
 		return NULL;
-
+	
 	ap->pflags |= ATA_PFLAG_INITIALIZING;
 	ap->lock = &host->lock;
 	ap->print_id = -1;
@@ -5695,6 +5576,7 @@
 	dev_set_drvdata(dev, host);
 
 	spin_lock_init(&host->lock);
+	mutex_init(&host->eh_mutex);
 	host->dev = dev;
 	host->n_ports = max_ports;
 
@@ -5992,6 +5874,7 @@
 		   unsigned long flags, struct ata_port_operations *ops)
 {
 	spin_lock_init(&host->lock);
+	mutex_init(&host->eh_mutex);
 	host->dev = dev;
 	host->flags = flags;
 	host->ops = ops;
@@ -6022,7 +5905,7 @@
 		spin_lock_irqsave(ap->lock, flags);
 
 		ehi->probe_mask |= ATA_ALL_DEVICES;
-		ehi->action |= ATA_EH_RESET | ATA_EH_LPM;
+		ehi->action |= ATA_EH_RESET;
 		ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
 
 		ap->pflags &= ~ATA_PFLAG_INITIALIZING;
@@ -6093,9 +5976,18 @@
 	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]);
+		if (rc) {
+			goto err_tadd;
+		}
+	}
+
 	rc = ata_scsi_add_hosts(host, sht);
 	if (rc)
-		return rc;
+		goto err_tadd;
 
 	/* associate with ACPI nodes */
 	ata_acpi_associate(host);
@@ -6136,6 +6028,13 @@
 	}
 
 	return 0;
+
+ err_tadd:
+	while (--i >= 0) {
+		ata_tport_delete(host->ports[i]);
+	}
+	return rc;
+
 }
 
 /**
@@ -6226,6 +6125,13 @@
 	cancel_rearming_delayed_work(&ap->hotplug_task);
 
  skip_eh:
+	if (ap->pmp_link) {
+		int i;
+		for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
+			ata_tlink_delete(&ap->pmp_link[i]);
+	}
+	ata_tport_delete(ap);
+
 	/* remove the associated SCSI host */
 	scsi_remove_host(ap->scsi_host);
 }
@@ -6542,7 +6448,7 @@
 
 static int __init ata_init(void)
 {
-	int rc = -ENOMEM;
+	int rc;
 
 	ata_parse_force_param();
 
@@ -6552,12 +6458,25 @@
 		return rc;
 	}
 
+	libata_transport_init();
+	ata_scsi_transport_template = ata_attach_transport();
+	if (!ata_scsi_transport_template) {
+		ata_sff_exit();
+		rc = -ENOMEM;
+		goto err_out;
+	}		
+
 	printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
 	return 0;
+
+err_out:
+	return rc;
 }
 
 static void __exit ata_exit(void)
 {
+	ata_release_transport(ata_scsi_transport_template);
+	libata_transport_exit();
 	ata_sff_exit();
 	kfree(ata_force_tbl);
 }
@@ -6573,7 +6492,35 @@
 }
 
 /**
+ *	ata_msleep - ATA EH owner aware msleep
+ *	@ap: ATA port to attribute the sleep to
+ *	@msecs: duration to sleep in milliseconds
+ *
+ *	Sleeps @msecs.  If the current task is owner of @ap's EH, the
+ *	ownership is released before going to sleep and reacquired
+ *	after the sleep is complete.  IOW, other ports sharing the
+ *	@ap->host will be allowed to own the EH while this task is
+ *	sleeping.
+ *
+ *	LOCKING:
+ *	Might sleep.
+ */
+void ata_msleep(struct ata_port *ap, unsigned int msecs)
+{
+	bool owns_eh = ap && ap->host->eh_owner == current;
+
+	if (owns_eh)
+		ata_eh_release(ap);
+
+	msleep(msecs);
+
+	if (owns_eh)
+		ata_eh_acquire(ap);
+}
+
+/**
  *	ata_wait_register - wait until register value changes
+ *	@ap: ATA port to wait register for, can be NULL
  *	@reg: IO-mapped register
  *	@mask: Mask to apply to read register value
  *	@val: Wait condition
@@ -6595,7 +6542,7 @@
  *	RETURNS:
  *	The final register value.
  */
-u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask, u32 val,
 		      unsigned long interval, unsigned long timeout)
 {
 	unsigned long deadline;
@@ -6610,7 +6557,7 @@
 	deadline = ata_deadline(jiffies, timeout);
 
 	while ((tmp & mask) == val && time_before(jiffies, deadline)) {
-		msleep(interval);
+		ata_msleep(ap, interval);
 		tmp = ioread32(reg);
 	}
 
@@ -6686,6 +6633,7 @@
 EXPORT_SYMBOL_GPL(ata_wait_after_reset);
 EXPORT_SYMBOL_GPL(sata_link_debounce);
 EXPORT_SYMBOL_GPL(sata_link_resume);
+EXPORT_SYMBOL_GPL(sata_link_scr_lpm);
 EXPORT_SYMBOL_GPL(ata_std_prereset);
 EXPORT_SYMBOL_GPL(sata_link_hardreset);
 EXPORT_SYMBOL_GPL(sata_std_hardreset);
@@ -6693,6 +6641,7 @@
 EXPORT_SYMBOL_GPL(ata_dev_classify);
 EXPORT_SYMBOL_GPL(ata_dev_pair);
 EXPORT_SYMBOL_GPL(ata_ratelimit);
+EXPORT_SYMBOL_GPL(ata_msleep);
 EXPORT_SYMBOL_GPL(ata_wait_register);
 EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index e48302e..5e59050 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -57,6 +57,7 @@
 	/* error flags */
 	ATA_EFLAG_IS_IO			= (1 << 0),
 	ATA_EFLAG_DUBIOUS_XFER		= (1 << 1),
+	ATA_EFLAG_OLD_ER                = (1 << 31),
 
 	/* error categories */
 	ATA_ECAT_NONE			= 0,
@@ -396,14 +397,9 @@
 	return NULL;
 }
 
-static void ata_ering_clear(struct ata_ering *ering)
-{
-	memset(ering, 0, sizeof(*ering));
-}
-
-static int ata_ering_map(struct ata_ering *ering,
-			 int (*map_fn)(struct ata_ering_entry *, void *),
-			 void *arg)
+int ata_ering_map(struct ata_ering *ering,
+		  int (*map_fn)(struct ata_ering_entry *, void *),
+		  void *arg)
 {
 	int idx, rc = 0;
 	struct ata_ering_entry *ent;
@@ -422,6 +418,17 @@
 	return rc;
 }
 
+int ata_ering_clear_cb(struct ata_ering_entry *ent, void *void_arg)
+{
+	ent->eflags |= ATA_EFLAG_OLD_ER;
+	return 0;
+}
+
+static void ata_ering_clear(struct ata_ering *ering)
+{
+	ata_ering_map(ering, ata_ering_clear_cb, NULL);
+}
+
 static unsigned int ata_eh_dev_action(struct ata_device *dev)
 {
 	struct ata_eh_context *ehc = &dev->link->eh_context;
@@ -456,6 +463,41 @@
 }
 
 /**
+ *	ata_eh_acquire - acquire EH ownership
+ *	@ap: ATA port to acquire EH ownership for
+ *
+ *	Acquire EH ownership for @ap.  This is the basic exclusion
+ *	mechanism for ports sharing a host.  Only one port hanging off
+ *	the same host can claim the ownership of EH.
+ *
+ *	LOCKING:
+ *	EH context.
+ */
+void ata_eh_acquire(struct ata_port *ap)
+{
+	mutex_lock(&ap->host->eh_mutex);
+	WARN_ON_ONCE(ap->host->eh_owner);
+	ap->host->eh_owner = current;
+}
+
+/**
+ *	ata_eh_release - release EH ownership
+ *	@ap: ATA port to release EH ownership for
+ *
+ *	Release EH ownership for @ap if the caller.  The caller must
+ *	have acquired EH ownership using ata_eh_acquire() previously.
+ *
+ *	LOCKING:
+ *	EH context.
+ */
+void ata_eh_release(struct ata_port *ap)
+{
+	WARN_ON_ONCE(ap->host->eh_owner != current);
+	ap->host->eh_owner = NULL;
+	mutex_unlock(&ap->host->eh_mutex);
+}
+
+/**
  *	ata_scsi_timed_out - SCSI layer time out callback
  *	@cmd: timed out SCSI command
  *
@@ -572,19 +614,19 @@
 		int nr_timedout = 0;
 
 		spin_lock_irqsave(ap->lock, flags);
-		
+
 		/* This must occur under the ap->lock as we don't want
 		   a polled recovery to race the real interrupt handler
-		   
+
 		   The lost_interrupt handler checks for any completed but
 		   non-notified command and completes much like an IRQ handler.
-		   
+
 		   We then fall into the error recovery code which will treat
 		   this as if normal completion won the race */
 
 		if (ap->ops->lost_interrupt)
 			ap->ops->lost_interrupt(ap);
-			
+
 		list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
 			struct ata_queued_cmd *qc;
 
@@ -628,15 +670,17 @@
 		ap->eh_tries = ATA_EH_MAX_TRIES;
 	} 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 ? */
 
- repeat:
 	/* invoke error handler */
 	if (ap->ops->error_handler) {
 		struct ata_link *link;
 
+		/* acquire EH ownership */
+		ata_eh_acquire(ap);
+ repeat:
 		/* kill fast drain timer */
 		del_timer_sync(&ap->fastdrain_timer);
 
@@ -711,6 +755,7 @@
 		host->host_eh_scheduled = 0;
 
 		spin_unlock_irqrestore(ap->lock, flags);
+		ata_eh_release(ap);
 	} else {
 		WARN_ON(ata_qc_from_tag(ap, ap->link.active_tag) == NULL);
 		ap->ops->eng_timeout(ap);
@@ -772,7 +817,7 @@
 
 	/* make sure SCSI EH is complete */
 	if (scsi_host_in_recovery(ap->scsi_host)) {
-		msleep(10);
+		ata_msleep(ap, 10);
 		goto retry;
 	}
 }
@@ -1573,9 +1618,9 @@
 	 * host links.  For disabled PMP links, only N bit is
 	 * considered as X bit is left at 1 for link plugging.
 	 */
-	hotplug_mask = 0;
-
-	if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link))
+	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;
 	else
 		hotplug_mask = SERR_PHYRDY_CHG;
@@ -1755,7 +1800,7 @@
 	struct speed_down_verdict_arg *arg = void_arg;
 	int cat;
 
-	if (ent->timestamp < arg->since)
+	if ((ent->eflags & ATA_EFLAG_OLD_ER) || (ent->timestamp < arg->since))
 		return -1;
 
 	cat = ata_eh_categorize_error(ent->eflags, ent->err_mask,
@@ -2777,8 +2822,9 @@
 	ata_eh_done(link, NULL, ATA_EH_RESET);
 	if (slave)
 		ata_eh_done(slave, NULL, ATA_EH_RESET);
-	ehc->last_reset = jiffies;	/* update to completion time */
+	ehc->last_reset = jiffies;		/* update to completion time */
 	ehc->i.action |= ATA_EH_REVALIDATE;
+	link->lpm_policy = ATA_LPM_UNKNOWN;	/* reset LPM state */
 
 	rc = 0;
  out:
@@ -2810,8 +2856,10 @@
 			"reset failed (errno=%d), retrying in %u secs\n",
 			rc, DIV_ROUND_UP(jiffies_to_msecs(delta), 1000));
 
+		ata_eh_release(ap);
 		while (delta)
 			delta = schedule_timeout_uninterruptible(delta);
+		ata_eh_acquire(ap);
 	}
 
 	if (try == max_tries - 1) {
@@ -3204,6 +3252,124 @@
 	return rc;
 }
 
+/**
+ *	ata_eh_set_lpm - configure SATA interface power management
+ *	@link: link to configure power management
+ *	@policy: the link power management policy
+ *	@r_failed_dev: out parameter for failed device
+ *
+ *	Enable SATA Interface power management.  This will enable
+ *	Device Interface Power Management (DIPM) for min_power
+ * 	policy, and then call driver specific callbacks for
+ *	enabling Host Initiated Power management.
+ *
+ *	LOCKING:
+ *	EH context.
+ *
+ *	RETURNS:
+ *	0 on success, -errno on failure.
+ */
+static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+			  struct ata_device **r_failed_dev)
+{
+	struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;
+	struct ata_eh_context *ehc = &link->eh_context;
+	struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
+	unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
+	unsigned int err_mask;
+	int rc;
+
+	/* if the link or host doesn't do LPM, noop */
+	if ((link->flags & ATA_LFLAG_NO_LPM) || (ap && !ap->ops->set_lpm))
+		return 0;
+
+	/*
+	 * DIPM is enabled only for MIN_POWER as some devices
+	 * misbehave when the host NACKs transition to SLUMBER.  Order
+	 * device and link configurations such that the host always
+	 * allows DIPM requests.
+	 */
+	ata_for_each_dev(dev, link, ENABLED) {
+		bool hipm = ata_id_has_hipm(dev->id);
+		bool dipm = ata_id_has_dipm(dev->id);
+
+		/* find the first enabled and LPM enabled devices */
+		if (!link_dev)
+			link_dev = dev;
+
+		if (!lpm_dev && (hipm || dipm))
+			lpm_dev = dev;
+
+		hints &= ~ATA_LPM_EMPTY;
+		if (!hipm)
+			hints &= ~ATA_LPM_HIPM;
+
+		/* disable DIPM before changing link config */
+		if (policy != ATA_LPM_MIN_POWER && dipm) {
+			err_mask = ata_dev_set_feature(dev,
+					SETFEATURES_SATA_DISABLE, SATA_DIPM);
+			if (err_mask && err_mask != AC_ERR_DEV) {
+				ata_dev_printk(dev, KERN_WARNING,
+					"failed to disable DIPM, Emask 0x%x\n",
+					err_mask);
+				rc = -EIO;
+				goto fail;
+			}
+		}
+	}
+
+	if (ap) {
+		rc = ap->ops->set_lpm(link, policy, hints);
+		if (!rc && ap->slave_link)
+			rc = ap->ops->set_lpm(ap->slave_link, policy, hints);
+	} else
+		rc = sata_pmp_set_lpm(link, policy, hints);
+
+	/*
+	 * Attribute link config failure to the first (LPM) enabled
+	 * device on the link.
+	 */
+	if (rc) {
+		if (rc == -EOPNOTSUPP) {
+			link->flags |= ATA_LFLAG_NO_LPM;
+			return 0;
+		}
+		dev = lpm_dev ? lpm_dev : link_dev;
+		goto fail;
+	}
+
+	/* host config updated, enable DIPM if transitioning to MIN_POWER */
+	ata_for_each_dev(dev, link, ENABLED) {
+		if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) {
+			err_mask = ata_dev_set_feature(dev,
+					SETFEATURES_SATA_ENABLE, SATA_DIPM);
+			if (err_mask && err_mask != AC_ERR_DEV) {
+				ata_dev_printk(dev, KERN_WARNING,
+					"failed to enable DIPM, Emask 0x%x\n",
+					err_mask);
+				rc = -EIO;
+				goto fail;
+			}
+		}
+	}
+
+	link->lpm_policy = policy;
+	if (ap && ap->slave_link)
+		ap->slave_link->lpm_policy = policy;
+	return 0;
+
+fail:
+	/* if no device or only one more chance is left, disable LPM */
+	if (!dev || ehc->tries[dev->devno] <= 2) {
+		ata_link_printk(link, KERN_WARNING,
+				"disabling LPM on the link\n");
+		link->flags |= ATA_LFLAG_NO_LPM;
+	}
+	if (r_failed_dev)
+		*r_failed_dev = dev;
+	return rc;
+}
+
 static int ata_link_nr_enabled(struct ata_link *link)
 {
 	struct ata_device *dev;
@@ -3288,6 +3454,16 @@
 	ehc->saved_xfer_mode[dev->devno] = 0;
 	ehc->saved_ncq_enabled &= ~(1 << dev->devno);
 
+	/* the link maybe in a deep sleep, wake it up */
+	if (link->lpm_policy > ATA_LPM_MAX_POWER) {
+		if (ata_is_host_link(link))
+			link->ap->ops->set_lpm(link, ATA_LPM_MAX_POWER,
+					       ATA_LPM_EMPTY);
+		else
+			sata_pmp_set_lpm(link, ATA_LPM_MAX_POWER,
+					 ATA_LPM_EMPTY);
+	}
+
 	/* Record and count probe trials on the ering.  The specific
 	 * error mask used is irrelevant.  Because a successful device
 	 * detection clears the ering, this count accumulates only if
@@ -3389,8 +3565,7 @@
 {
 	struct ata_link *link;
 	struct ata_device *dev;
-	int nr_failed_devs;
-	int rc;
+	int rc, nr_fails;
 	unsigned long flags, deadline;
 
 	DPRINTK("ENTER\n");
@@ -3431,7 +3606,6 @@
 
  retry:
 	rc = 0;
-	nr_failed_devs = 0;
 
 	/* if UNLOADING, finish immediately */
 	if (ap->pflags & ATA_PFLAG_UNLOADING)
@@ -3501,8 +3675,10 @@
 		if (time_before_eq(deadline, now))
 			break;
 
+		ata_eh_release(ap);
 		deadline = wait_for_completion_timeout(&ap->park_req_pending,
 						       deadline - now);
+		ata_eh_acquire(ap);
 	} while (deadline);
 	ata_for_each_link(link, ap, EDGE) {
 		ata_for_each_dev(dev, link, ALL) {
@@ -3516,13 +3692,17 @@
 	}
 
 	/* the rest */
-	ata_for_each_link(link, ap, EDGE) {
+	nr_fails = 0;
+	ata_for_each_link(link, ap, PMP_FIRST) {
 		struct ata_eh_context *ehc = &link->eh_context;
 
+		if (sata_pmp_attached(ap) && ata_is_host_link(link))
+			goto config_lpm;
+
 		/* revalidate existing devices and attach new ones */
 		rc = ata_eh_revalidate_and_attach(link, &dev);
 		if (rc)
-			goto dev_fail;
+			goto rest_fail;
 
 		/* if PMP got attached, return, pmp EH will take care of it */
 		if (link->device->class == ATA_DEV_PMP) {
@@ -3534,7 +3714,7 @@
 		if (ehc->i.flags & ATA_EHI_SETMODE) {
 			rc = ata_set_mode(link, &dev);
 			if (rc)
-				goto dev_fail;
+				goto rest_fail;
 			ehc->i.flags &= ~ATA_EHI_SETMODE;
 		}
 
@@ -3547,7 +3727,7 @@
 					continue;
 				rc = atapi_eh_clear_ua(dev);
 				if (rc)
-					goto dev_fail;
+					goto rest_fail;
 			}
 		}
 
@@ -3557,21 +3737,25 @@
 				continue;
 			rc = ata_eh_maybe_retry_flush(dev);
 			if (rc)
-				goto dev_fail;
+				goto rest_fail;
 		}
 
+	config_lpm:
 		/* configure link power saving */
-		if (ehc->i.action & ATA_EH_LPM)
-			ata_for_each_dev(dev, link, ALL)
-				ata_dev_enable_pm(dev, ap->pm_policy);
+		if (link->lpm_policy != ap->target_lpm_policy) {
+			rc = ata_eh_set_lpm(link, ap->target_lpm_policy, &dev);
+			if (rc)
+				goto rest_fail;
+		}
 
 		/* this link is okay now */
 		ehc->i.flags = 0;
 		continue;
 
-dev_fail:
-		nr_failed_devs++;
-		ata_eh_handle_dev_fail(dev, rc);
+	rest_fail:
+		nr_fails++;
+		if (dev)
+			ata_eh_handle_dev_fail(dev, rc);
 
 		if (ap->pflags & ATA_PFLAG_FROZEN) {
 			/* PMP reset requires working host port.
@@ -3583,7 +3767,7 @@
 		}
 	}
 
-	if (nr_failed_devs)
+	if (nr_fails)
 		goto retry;
 
  out:
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 224faab..3120596 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -11,6 +11,7 @@
 #include <linux/libata.h>
 #include <linux/slab.h>
 #include "libata.h"
+#include "libata-transport.h"
 
 const struct ata_port_operations sata_pmp_port_ops = {
 	.inherits		= &sata_port_ops,
@@ -185,6 +186,27 @@
 }
 
 /**
+ *	sata_pmp_set_lpm - configure LPM for a PMP link
+ *	@link: PMP link to configure LPM for
+ *	@policy: target LPM policy
+ *	@hints: LPM hints
+ *
+ *	Configure LPM for @link.  This function will contain any PMP
+ *	specific workarounds if necessary.
+ *
+ *	LOCKING:
+ *	EH context.
+ *
+ *	RETURNS:
+ *	0 on success, -errno on failure.
+ */
+int sata_pmp_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+		     unsigned hints)
+{
+	return sata_link_scr_lpm(link, policy, true);
+}
+
+/**
  *	sata_pmp_read_gscr - read GSCR block of SATA PMP
  *	@dev: PMP device
  *	@gscr: buffer to read GSCR block into
@@ -312,10 +334,10 @@
 	return rc;
 }
 
-static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
+static int sata_pmp_init_links (struct ata_port *ap, int nr_ports)
 {
 	struct ata_link *pmp_link = ap->pmp_link;
-	int i;
+	int i, err;
 
 	if (!pmp_link) {
 		pmp_link = kzalloc(sizeof(pmp_link[0]) * SATA_PMP_MAX_PORTS,
@@ -327,6 +349,13 @@
 			ata_link_init(ap, &pmp_link[i], i);
 
 		ap->pmp_link = pmp_link;
+
+		for (i = 0; i < SATA_PMP_MAX_PORTS; i++) {
+			err = ata_tlink_add(&pmp_link[i]);
+			if (err) {
+				goto err_tlink;
+			}
+		}
 	}
 
 	for (i = 0; i < nr_ports; i++) {
@@ -339,6 +368,12 @@
 	}
 
 	return 0;
+  err_tlink:
+	while (--i >= 0)
+		ata_tlink_delete(&pmp_link[i]);
+	kfree(pmp_link);
+	ap->pmp_link = NULL;
+	return err;
 }
 
 static void sata_pmp_quirks(struct ata_port *ap)
@@ -351,6 +386,9 @@
 	if (vendor == 0x1095 && devid == 0x3726) {
 		/* sil3726 quirks */
 		ata_for_each_link(link, ap, EDGE) {
+			/* link reports offline after LPM */
+			link->flags |= ATA_LFLAG_NO_LPM;
+
 			/* Class code report is unreliable and SRST
 			 * times out under certain configurations.
 			 */
@@ -366,6 +404,9 @@
 	} else if (vendor == 0x1095 && devid == 0x4723) {
 		/* sil4723 quirks */
 		ata_for_each_link(link, ap, EDGE) {
+			/* link reports offline after LPM */
+			link->flags |= ATA_LFLAG_NO_LPM;
+
 			/* class code report is unreliable */
 			if (link->pmp < 2)
 				link->flags |= ATA_LFLAG_ASSUME_ATA;
@@ -378,6 +419,9 @@
 	} else if (vendor == 0x1095 && devid == 0x4726) {
 		/* sil4726 quirks */
 		ata_for_each_link(link, ap, EDGE) {
+			/* link reports offline after LPM */
+			link->flags |= ATA_LFLAG_NO_LPM;
+
 			/* Class code report is unreliable and SRST
 			 * times out under certain configurations.
 			 * Config device can be at port 0 or 5 and
@@ -938,15 +982,25 @@
 	if (rc)
 		goto link_fail;
 
-	/* Connection status might have changed while resetting other
-	 * links, check SATA_PMP_GSCR_ERROR before returning.
-	 */
-
 	/* clear SNotification */
 	rc = sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf);
 	if (rc == 0)
 		sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf);
 
+	/*
+	 * If LPM is active on any fan-out port, hotplug wouldn't
+	 * work.  Return w/ PHY event notification disabled.
+	 */
+	ata_for_each_link(link, ap, EDGE)
+		if (link->lpm_policy > ATA_LPM_MAX_POWER)
+			return 0;
+
+	/*
+	 * Connection status might have changed while resetting other
+	 * links, enable notification and check SATA_PMP_GSCR_ERROR
+	 * before returning.
+	 */
+
 	/* enable notification */
 	if (pmp_dev->flags & ATA_DFLAG_AN) {
 		gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index a89172c..d050e07 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -51,8 +51,8 @@
 #include <asm/unaligned.h>
 
 #include "libata.h"
+#include "libata-transport.h"
 
-#define SECTOR_SIZE		512
 #define ATA_SCSI_RBUF_SIZE	4096
 
 static DEFINE_SPINLOCK(ata_scsi_rbuf_lock);
@@ -64,9 +64,6 @@
 					const struct scsi_device *scsidev);
 static struct ata_device *ata_scsi_find_dev(struct ata_port *ap,
 					    const struct scsi_device *scsidev);
-static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
-			      unsigned int id, unsigned int lun);
-
 
 #define RW_RECOVERY_MPAGE 0x1
 #define RW_RECOVERY_MPAGE_LEN 12
@@ -106,83 +103,55 @@
 	0, 30	/* extended self test time, see 05-359r1 */
 };
 
-/*
- * libata transport template.  libata doesn't do real transport stuff.
- * It just needs the eh_timed_out hook.
- */
-static struct scsi_transport_template ata_scsi_transport_template = {
-	.eh_strategy_handler	= ata_scsi_error,
-	.eh_timed_out		= ata_scsi_timed_out,
-	.user_scan		= ata_scsi_user_scan,
+static const char *ata_lpm_policy_names[] = {
+	[ATA_LPM_UNKNOWN]	= "max_performance",
+	[ATA_LPM_MAX_POWER]	= "max_performance",
+	[ATA_LPM_MED_POWER]	= "medium_power",
+	[ATA_LPM_MIN_POWER]	= "min_power",
 };
 
-
-static const struct {
-	enum link_pm	value;
-	const char	*name;
-} link_pm_policy[] = {
-	{ NOT_AVAILABLE, "max_performance" },
-	{ MIN_POWER, "min_power" },
-	{ MAX_PERFORMANCE, "max_performance" },
-	{ MEDIUM_POWER, "medium_power" },
-};
-
-static const char *ata_scsi_lpm_get(enum link_pm policy)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(link_pm_policy); i++)
-		if (link_pm_policy[i].value == policy)
-			return link_pm_policy[i].name;
-
-	return NULL;
-}
-
-static ssize_t ata_scsi_lpm_put(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
+static ssize_t ata_scsi_lpm_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
 {
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct ata_port *ap = ata_shost_to_port(shost);
-	enum link_pm policy = 0;
-	int i;
+	enum ata_lpm_policy policy;
+	unsigned long flags;
 
-	/*
-	 * we are skipping array location 0 on purpose - this
-	 * is because a value of NOT_AVAILABLE is displayed
-	 * to the user as max_performance, but when the user
-	 * writes "max_performance", they actually want the
-	 * value to match MAX_PERFORMANCE.
-	 */
-	for (i = 1; i < ARRAY_SIZE(link_pm_policy); i++) {
-		const int len = strlen(link_pm_policy[i].name);
-		if (strncmp(link_pm_policy[i].name, buf, len) == 0) {
-			policy = link_pm_policy[i].value;
+	/* UNKNOWN is internal state, iterate from MAX_POWER */
+	for (policy = ATA_LPM_MAX_POWER;
+	     policy < ARRAY_SIZE(ata_lpm_policy_names); policy++) {
+		const char *name = ata_lpm_policy_names[policy];
+
+		if (strncmp(name, buf, strlen(name)) == 0)
 			break;
-		}
 	}
-	if (!policy)
+	if (policy == ARRAY_SIZE(ata_lpm_policy_names))
 		return -EINVAL;
 
-	ata_lpm_schedule(ap, policy);
+	spin_lock_irqsave(ap->lock, flags);
+	ap->target_lpm_policy = policy;
+	ata_port_schedule_eh(ap);
+	spin_unlock_irqrestore(ap->lock, flags);
+
 	return count;
 }
 
-static ssize_t
-ata_scsi_lpm_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t ata_scsi_lpm_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
 {
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct ata_port *ap = ata_shost_to_port(shost);
-	const char *policy =
-		ata_scsi_lpm_get(ap->pm_policy);
 
-	if (!policy)
+	if (ap->target_lpm_policy >= ARRAY_SIZE(ata_lpm_policy_names))
 		return -EINVAL;
 
-	return snprintf(buf, 23, "%s\n", policy);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			ata_lpm_policy_names[ap->target_lpm_policy]);
 }
 DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
-		ata_scsi_lpm_show, ata_scsi_lpm_put);
+	    ata_scsi_lpm_show, ata_scsi_lpm_store);
 EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
 
 static ssize_t ata_scsi_park_show(struct device *device,
@@ -516,7 +485,7 @@
 	memset(scsi_cmd, 0, sizeof(scsi_cmd));
 
 	if (args[3]) {
-		argsize = SECTOR_SIZE * args[3];
+		argsize = ATA_SECT_SIZE * args[3];
 		argbuf = kmalloc(argsize, GFP_KERNEL);
 		if (argbuf == NULL) {
 			rc = -ENOMEM;
@@ -1150,8 +1119,9 @@
 		blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN);
 	} else {
 		/* ATA devices must be sector aligned */
+		sdev->sector_size = ata_id_logical_sector_size(dev->id);
 		blk_queue_update_dma_alignment(sdev->request_queue,
-					       ATA_SECT_SIZE - 1);
+					       sdev->sector_size - 1);
 		sdev->manage_start_stop = 1;
 	}
 
@@ -1166,6 +1136,7 @@
 		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
 	}
 
+	dev->sdev = sdev;
 	return 0;
 }
 
@@ -1696,7 +1667,7 @@
 		goto nothing_to_do;
 
 	qc->flags |= ATA_QCFLAG_IO;
-	qc->nbytes = n_block * ATA_SECT_SIZE;
+	qc->nbytes = n_block * scmd->device->sector_size;
 
 	rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags,
 			     qc->tag);
@@ -2001,6 +1972,7 @@
 		0x89,	/* page 0x89, ata info page */
 		0xb0,	/* page 0xb0, block limits page */
 		0xb1,	/* page 0xb1, block device characteristics page */
+		0xb2,	/* page 0xb2, thin provisioning page */
 	};
 
 	rbuf[3] = sizeof(pages);	/* number of supported VPD pages */
@@ -2123,7 +2095,7 @@
 
 static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
 {
-	u32 min_io_sectors;
+	u16 min_io_sectors;
 
 	rbuf[1] = 0xb0;
 	rbuf[3] = 0x3c;		/* required VPD size with unmap support */
@@ -2135,10 +2107,7 @@
 	 * logical than physical sector size we need to figure out what the
 	 * latter is.
 	 */
-	if (ata_id_has_large_logical_sectors(args->id))
-		min_io_sectors = ata_id_logical_per_physical_sectors(args->id);
-	else
-		min_io_sectors = 1;
+	min_io_sectors = 1 << ata_id_log2_per_physical_sector(args->id);
 	put_unaligned_be16(min_io_sectors, &rbuf[6]);
 
 	/*
@@ -2172,6 +2141,16 @@
 	return 0;
 }
 
+static unsigned int ata_scsiop_inq_b2(struct ata_scsi_args *args, u8 *rbuf)
+{
+	/* SCSI Thin Provisioning VPD page: SBC-3 rev 22 or later */
+	rbuf[1] = 0xb2;
+	rbuf[3] = 0x4;
+	rbuf[5] = 1 << 6;	/* TPWS */
+
+	return 0;
+}
+
 /**
  *	ata_scsiop_noop - Command handler that simply returns success.
  *	@args: device IDENTIFY data / SCSI command of interest.
@@ -2397,21 +2376,13 @@
 {
 	struct ata_device *dev = args->dev;
 	u64 last_lba = dev->n_sectors - 1; /* LBA of the last block */
-	u8 log_per_phys = 0;
-	u16 lowest_aligned = 0;
-	u16 word_106 = dev->id[106];
-	u16 word_209 = dev->id[209];
+	u32 sector_size; /* physical sector size in bytes */
+	u8 log2_per_phys;
+	u16 lowest_aligned;
 
-	if ((word_106 & 0xc000) == 0x4000) {
-		/* Number and offset of logical sectors per physical sector */
-		if (word_106 & (1 << 13))
-			log_per_phys = word_106 & 0xf;
-		if ((word_209 & 0xc000) == 0x4000) {
-			u16 first = dev->id[209] & 0x3fff;
-			if (first > 0)
-				lowest_aligned = (1 << log_per_phys) - first;
-		}
-	}
+	sector_size = ata_id_logical_sector_size(dev->id);
+	log2_per_phys = ata_id_log2_per_physical_sector(dev->id);
+	lowest_aligned = ata_id_logical_sector_offset(dev->id, log2_per_phys);
 
 	VPRINTK("ENTER\n");
 
@@ -2426,8 +2397,10 @@
 		rbuf[3] = last_lba;
 
 		/* sector size */
-		rbuf[6] = ATA_SECT_SIZE >> 8;
-		rbuf[7] = ATA_SECT_SIZE & 0xff;
+		rbuf[4] = sector_size >> (8 * 3);
+		rbuf[5] = sector_size >> (8 * 2);
+		rbuf[6] = sector_size >> (8 * 1);
+		rbuf[7] = sector_size;
 	} else {
 		/* sector count, 64-bit */
 		rbuf[0] = last_lba >> (8 * 7);
@@ -2440,11 +2413,13 @@
 		rbuf[7] = last_lba;
 
 		/* sector size */
-		rbuf[10] = ATA_SECT_SIZE >> 8;
-		rbuf[11] = ATA_SECT_SIZE & 0xff;
+		rbuf[ 8] = sector_size >> (8 * 3);
+		rbuf[ 9] = sector_size >> (8 * 2);
+		rbuf[10] = sector_size >> (8 * 1);
+		rbuf[11] = sector_size;
 
 		rbuf[12] = 0;
-		rbuf[13] = log_per_phys;
+		rbuf[13] = log2_per_phys;
 		rbuf[14] = (lowest_aligned >> 8) & 0x3f;
 		rbuf[15] = lowest_aligned;
 
@@ -2888,9 +2863,8 @@
 	tf->device = dev->devno ?
 		tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
 
-	/* READ/WRITE LONG use a non-standard sect_size */
-	qc->sect_size = ATA_SECT_SIZE;
 	switch (tf->command) {
+	/* READ/WRITE LONG use a non-standard sect_size */
 	case ATA_CMD_READ_LONG:
 	case ATA_CMD_READ_LONG_ONCE:
 	case ATA_CMD_WRITE_LONG:
@@ -2898,6 +2872,45 @@
 		if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1)
 			goto invalid_fld;
 		qc->sect_size = scsi_bufflen(scmd);
+		break;
+
+	/* commands using reported Logical Block size (e.g. 512 or 4K) */
+	case ATA_CMD_CFA_WRITE_NE:
+	case ATA_CMD_CFA_TRANS_SECT:
+	case ATA_CMD_CFA_WRITE_MULT_NE:
+	/* XXX: case ATA_CMD_CFA_WRITE_SECTORS_WITHOUT_ERASE: */
+	case ATA_CMD_READ:
+	case ATA_CMD_READ_EXT:
+	case ATA_CMD_READ_QUEUED:
+	/* XXX: case ATA_CMD_READ_QUEUED_EXT: */
+	case ATA_CMD_FPDMA_READ:
+	case ATA_CMD_READ_MULTI:
+	case ATA_CMD_READ_MULTI_EXT:
+	case ATA_CMD_PIO_READ:
+	case ATA_CMD_PIO_READ_EXT:
+	case ATA_CMD_READ_STREAM_DMA_EXT:
+	case ATA_CMD_READ_STREAM_EXT:
+	case ATA_CMD_VERIFY:
+	case ATA_CMD_VERIFY_EXT:
+	case ATA_CMD_WRITE:
+	case ATA_CMD_WRITE_EXT:
+	case ATA_CMD_WRITE_FUA_EXT:
+	case ATA_CMD_WRITE_QUEUED:
+	case ATA_CMD_WRITE_QUEUED_FUA_EXT:
+	case ATA_CMD_FPDMA_WRITE:
+	case ATA_CMD_WRITE_MULTI:
+	case ATA_CMD_WRITE_MULTI_EXT:
+	case ATA_CMD_WRITE_MULTI_FUA_EXT:
+	case ATA_CMD_PIO_WRITE:
+	case ATA_CMD_PIO_WRITE_EXT:
+	case ATA_CMD_WRITE_STREAM_DMA_EXT:
+	case ATA_CMD_WRITE_STREAM_EXT:
+		qc->sect_size = scmd->device->sector_size;
+		break;
+
+	/* Everything else uses 512 byte "sectors" */
+	default:
+		qc->sect_size = ATA_SECT_SIZE;
 	}
 
 	/*
@@ -3250,6 +3263,9 @@
 		case 0xb1:
 			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b1);
 			break;
+		case 0xb2:
+			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2);
+			break;
 		default:
 			ata_scsi_invalid_field(cmd, done);
 			break;
@@ -3334,7 +3350,7 @@
 		*(struct ata_port **)&shost->hostdata[0] = ap;
 		ap->scsi_host = shost;
 
-		shost->transportt = &ata_scsi_transport_template;
+		shost->transportt = ata_scsi_transport_template;
 		shost->unique_id = ap->print_id;
 		shost->max_id = 16;
 		shost->max_lun = 1;
@@ -3393,6 +3409,8 @@
 			if (!IS_ERR(sdev)) {
 				dev->sdev = sdev;
 				scsi_device_put(sdev);
+			} else {
+				dev->sdev = NULL;
 			}
 		}
 	}
@@ -3616,8 +3634,8 @@
  *	RETURNS:
  *	Zero.
  */
-static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
-			      unsigned int id, unsigned int lun)
+int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+		       unsigned int id, unsigned int lun)
 {
 	struct ata_port *ap = ata_shost_to_port(shost);
 	unsigned long flags;
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index e30c537..d05387d 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -222,7 +222,7 @@
 	timeout = ata_deadline(timer_start, tmout_pat);
 	while (status != 0xff && (status & ATA_BUSY) &&
 	       time_before(jiffies, timeout)) {
-		msleep(50);
+		ata_msleep(ap, 50);
 		status = ata_sff_busy_wait(ap, ATA_BUSY, 3);
 	}
 
@@ -234,7 +234,7 @@
 	timeout = ata_deadline(timer_start, tmout);
 	while (status != 0xff && (status & ATA_BUSY) &&
 	       time_before(jiffies, timeout)) {
-		msleep(50);
+		ata_msleep(ap, 50);
 		status = ap->ops->sff_check_status(ap);
 	}
 
@@ -360,7 +360,7 @@
 
 	if (wait) {
 		if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI)
-			msleep(150);
+			ata_msleep(ap, 150);
 		ata_wait_idle(ap);
 	}
 }
@@ -1356,7 +1356,7 @@
 	 */
 	status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
 	if (status & ATA_BUSY) {
-		msleep(2);
+		ata_msleep(ap, 2);
 		status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
 		if (status & ATA_BUSY) {
 			ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
@@ -1937,7 +1937,7 @@
 	unsigned int dev1 = devmask & (1 << 1);
 	int rc, ret = 0;
 
-	msleep(ATA_WAIT_AFTER_RESET);
+	ata_msleep(ap, ATA_WAIT_AFTER_RESET);
 
 	/* always check readiness of the master device */
 	rc = ata_sff_wait_ready(link, deadline);
@@ -1966,7 +1966,7 @@
 			lbal = ioread8(ioaddr->lbal_addr);
 			if ((nsect == 1) && (lbal == 1))
 				break;
-			msleep(50);	/* give drive a breather */
+			ata_msleep(ap, 50);	/* give drive a breather */
 		}
 
 		rc = ata_sff_wait_ready(link, deadline);
@@ -3335,14 +3335,14 @@
 
 int __init ata_sff_init(void)
 {
-	ata_sff_wq = alloc_workqueue("ata_sff", WQ_RESCUER, WQ_MAX_ACTIVE);
+	ata_sff_wq = alloc_workqueue("ata_sff", WQ_MEM_RECLAIM, WQ_MAX_ACTIVE);
 	if (!ata_sff_wq)
 		return -ENOMEM;
 
 	return 0;
 }
 
-void __exit ata_sff_exit(void)
+void ata_sff_exit(void)
 {
 	destroy_workqueue(ata_sff_wq);
 }
diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c
new file mode 100644
index 0000000..ce9dc62
--- /dev/null
+++ b/drivers/ata/libata-transport.c
@@ -0,0 +1,774 @@
+/*
+ *  Copyright 2008 ioogle, Inc.  All rights reserved.
+ *	Released under GPL v2.
+ *
+ * Libata transport class.
+ *
+ * The ATA transport class contains common code to deal with ATA HBAs,
+ * an approximated representation of ATA topologies in the driver model,
+ * and various sysfs attributes to expose these topologies and management
+ * interfaces to user-space.
+ *
+ * There are 3 objects defined in in this class:
+ * - ata_port
+ * - ata_link
+ * - ata_device
+ * Each port has a link object. Each link can have up to two devices for PATA
+ * and generally one for SATA.
+ * If there is SATA port multiplier [PMP], 15 additional ata_link object are
+ * created.
+ *
+ * These objects are created when the ata host is initialized and when a PMP is
+ * found. They are removed only when the HBA is removed, cleaned before the
+ * error handler runs.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/blkdev.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <scsi/scsi_transport.h>
+#include <linux/libata.h>
+#include <linux/hdreg.h>
+#include <linux/uaccess.h>
+
+#include "libata.h"
+#include "libata-transport.h"
+
+#define ATA_PORT_ATTRS		2
+#define ATA_LINK_ATTRS		3
+#define ATA_DEV_ATTRS		9
+
+struct scsi_transport_template;
+struct scsi_transport_template *ata_scsi_transport_template;
+
+struct ata_internal {
+	struct scsi_transport_template t;
+
+	struct device_attribute private_port_attrs[ATA_PORT_ATTRS];
+	struct device_attribute private_link_attrs[ATA_LINK_ATTRS];
+	struct device_attribute private_dev_attrs[ATA_DEV_ATTRS];
+
+	struct transport_container link_attr_cont;
+	struct transport_container dev_attr_cont;
+
+	/*
+	 * The array of null terminated pointers to attributes
+	 * needed by scsi_sysfs.c
+	 */
+	struct device_attribute *link_attrs[ATA_LINK_ATTRS + 1];
+	struct device_attribute *port_attrs[ATA_PORT_ATTRS + 1];
+	struct device_attribute *dev_attrs[ATA_DEV_ATTRS + 1];
+};
+#define to_ata_internal(tmpl)	container_of(tmpl, struct ata_internal, t)
+
+
+#define tdev_to_device(d)					\
+	container_of((d), struct ata_device, tdev)
+#define transport_class_to_dev(dev)				\
+	tdev_to_device((dev)->parent)
+
+#define tdev_to_link(d)						\
+	container_of((d), struct ata_link, tdev)
+#define transport_class_to_link(dev)				\
+	tdev_to_link((dev)->parent)
+
+#define tdev_to_port(d)						\
+	container_of((d), struct ata_port, tdev)
+#define transport_class_to_port(dev)				\
+	tdev_to_port((dev)->parent)
+
+
+/* Device objects are always created whit link objects */
+static int ata_tdev_add(struct ata_device *dev);
+static void ata_tdev_delete(struct ata_device *dev);
+
+
+/*
+ * Hack to allow attributes of the same name in different objects.
+ */
+#define ATA_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
+	struct device_attribute device_attr_##_prefix##_##_name = \
+	__ATTR(_name,_mode,_show,_store)
+
+#define ata_bitfield_name_match(title, table)			\
+static ssize_t							\
+get_ata_##title##_names(u32 table_key, char *buf)		\
+{								\
+	char *prefix = "";					\
+	ssize_t len = 0;					\
+	int i;							\
+								\
+	for (i = 0; i < ARRAY_SIZE(table); i++) {		\
+		if (table[i].value & table_key) {		\
+			len += sprintf(buf + len, "%s%s",	\
+				prefix, table[i].name);		\
+			prefix = ", ";				\
+		}						\
+	}							\
+	len += sprintf(buf + len, "\n");			\
+	return len;						\
+}
+
+#define ata_bitfield_name_search(title, table)			\
+static ssize_t							\
+get_ata_##title##_names(u32 table_key, char *buf)		\
+{								\
+	ssize_t len = 0;					\
+	int i;							\
+								\
+	for (i = 0; i < ARRAY_SIZE(table); i++) {		\
+		if (table[i].value == table_key) {		\
+			len += sprintf(buf + len, "%s",		\
+				table[i].name);			\
+			break;					\
+		}						\
+	}							\
+	len += sprintf(buf + len, "\n");			\
+	return len;						\
+}
+
+static struct {
+	u32		value;
+	char		*name;
+} ata_class_names[] = {
+	{ ATA_DEV_UNKNOWN,		"unknown" },
+	{ ATA_DEV_ATA,			"ata" },
+	{ ATA_DEV_ATA_UNSUP,		"ata" },
+	{ ATA_DEV_ATAPI,		"atapi" },
+	{ ATA_DEV_ATAPI_UNSUP,		"atapi" },
+	{ ATA_DEV_PMP,			"pmp" },
+	{ ATA_DEV_PMP_UNSUP,		"pmp" },
+	{ ATA_DEV_SEMB,			"semb" },
+	{ ATA_DEV_SEMB_UNSUP,		"semb" },
+	{ ATA_DEV_NONE,			"none" }
+};
+ata_bitfield_name_search(class, ata_class_names)
+
+
+static struct {
+	u32		value;
+	char		*name;
+} ata_err_names[] = {
+	{ AC_ERR_DEV,			"DeviceError" },
+	{ AC_ERR_HSM,			"HostStateMachineError" },
+	{ AC_ERR_TIMEOUT,		"Timeout" },
+	{ AC_ERR_MEDIA,			"MediaError" },
+	{ AC_ERR_ATA_BUS,		"BusError" },
+	{ AC_ERR_HOST_BUS,		"HostBusError" },
+	{ AC_ERR_SYSTEM,		"SystemError" },
+	{ AC_ERR_INVALID,		"InvalidArg" },
+	{ AC_ERR_OTHER,			"Unknown" },
+	{ AC_ERR_NODEV_HINT,		"NoDeviceHint" },
+	{ AC_ERR_NCQ,		 	"NCQError" }
+};
+ata_bitfield_name_match(err, ata_err_names)
+
+static struct {
+	u32		value;
+	char		*name;
+} ata_xfer_names[] = {
+	{ XFER_UDMA_7,			"XFER_UDMA_7" },
+	{ XFER_UDMA_6,			"XFER_UDMA_6" },
+	{ XFER_UDMA_5,			"XFER_UDMA_5" },
+	{ XFER_UDMA_4,			"XFER_UDMA_4" },
+	{ XFER_UDMA_3,			"XFER_UDMA_3" },
+	{ XFER_UDMA_2,			"XFER_UDMA_2" },
+	{ XFER_UDMA_1,			"XFER_UDMA_1" },
+	{ XFER_UDMA_0,			"XFER_UDMA_0" },
+	{ XFER_MW_DMA_4,		"XFER_MW_DMA_4" },
+	{ XFER_MW_DMA_3,		"XFER_MW_DMA_3" },
+	{ XFER_MW_DMA_2,		"XFER_MW_DMA_2" },
+	{ XFER_MW_DMA_1,		"XFER_MW_DMA_1" },
+	{ XFER_MW_DMA_0,		"XFER_MW_DMA_0" },
+	{ XFER_SW_DMA_2,		"XFER_SW_DMA_2" },
+	{ XFER_SW_DMA_1,		"XFER_SW_DMA_1" },
+	{ XFER_SW_DMA_0,		"XFER_SW_DMA_0" },
+	{ XFER_PIO_6,			"XFER_PIO_6" },
+	{ XFER_PIO_5,			"XFER_PIO_5" },
+	{ XFER_PIO_4,			"XFER_PIO_4" },
+	{ XFER_PIO_3,			"XFER_PIO_3" },
+	{ XFER_PIO_2,			"XFER_PIO_2" },
+	{ XFER_PIO_1,			"XFER_PIO_1" },
+	{ XFER_PIO_0,			"XFER_PIO_0" },
+	{ XFER_PIO_SLOW,		"XFER_PIO_SLOW" }
+};
+ata_bitfield_name_match(xfer,ata_xfer_names)
+
+/*
+ * ATA Port attributes
+ */
+#define ata_port_show_simple(field, name, format_string, cast)		\
+static ssize_t								\
+show_ata_port_##name(struct device *dev,				\
+		     struct device_attribute *attr, char *buf)		\
+{									\
+	struct ata_port *ap = transport_class_to_port(dev);		\
+									\
+	return snprintf(buf, 20, format_string, cast ap->field);	\
+}
+
+#define ata_port_simple_attr(field, name, format_string, type)		\
+	ata_port_show_simple(field, name, format_string, (type))	\
+static DEVICE_ATTR(name, S_IRUGO, show_ata_port_##name, NULL)
+
+ata_port_simple_attr(nr_pmp_links, nr_pmp_links, "%d\n", int);
+ata_port_simple_attr(stats.idle_irq, idle_irq, "%ld\n", unsigned long);
+
+static DECLARE_TRANSPORT_CLASS(ata_port_class,
+			       "ata_port", NULL, NULL, NULL);
+
+static void ata_tport_release(struct device *dev)
+{
+	put_device(dev->parent);
+}
+
+/**
+ * ata_is_port --  check if a struct device represents a ATA port
+ * @dev:	device to check
+ *
+ * Returns:
+ *	%1 if the device represents a ATA Port, %0 else
+ */
+int ata_is_port(const struct device *dev)
+{
+	return dev->release == ata_tport_release;
+}
+
+static int ata_tport_match(struct attribute_container *cont,
+			   struct device *dev)
+{
+	if (!ata_is_port(dev))
+		return 0;
+	return &ata_scsi_transport_template->host_attrs.ac == cont;
+}
+
+/**
+ * ata_tport_delete  --  remove ATA PORT
+ * @port:	ATA PORT to remove
+ *
+ * Removes the specified ATA PORT.  Remove the associated link as well.
+ */
+void ata_tport_delete(struct ata_port *ap)
+{
+	struct device *dev = &ap->tdev;
+
+	ata_tlink_delete(&ap->link);
+
+	transport_remove_device(dev);
+	device_del(dev);
+	transport_destroy_device(dev);
+	put_device(dev);
+}
+
+/** ata_tport_add - initialize a transport ATA port structure
+ *
+ * @parent:	parent device
+ * @ap:		existing ata_port structure
+ *
+ * Initialize a ATA port structure for sysfs.  It will be added to the device
+ * tree below the device specified by @parent which could be a PCI device.
+ *
+ * Returns %0 on success
+ */
+int ata_tport_add(struct device *parent,
+		  struct ata_port *ap)
+{
+	int error;
+	struct device *dev = &ap->tdev;
+
+	device_initialize(dev);
+
+	dev->parent = get_device(parent);
+	dev->release = ata_tport_release;
+	dev_set_name(dev, "ata%d", ap->print_id);
+	transport_setup_device(dev);
+	error = device_add(dev);
+	if (error) {
+		goto tport_err;
+	}
+
+	transport_add_device(dev);
+	transport_configure_device(dev);
+
+	error = ata_tlink_add(&ap->link);
+	if (error) {
+		goto tport_link_err;
+	}
+	return 0;
+
+ tport_link_err:
+	transport_remove_device(dev);
+	device_del(dev);
+
+ tport_err:
+	transport_destroy_device(dev);
+	put_device(dev);
+	return error;
+}
+
+
+/*
+ * ATA link attributes
+ */
+
+
+#define ata_link_show_linkspeed(field)					\
+static ssize_t								\
+show_ata_link_##field(struct device *dev,				\
+		      struct device_attribute *attr, char *buf)		\
+{									\
+	struct ata_link *link = transport_class_to_link(dev);		\
+									\
+	return sprintf(buf,"%s\n", sata_spd_string(fls(link->field)));	\
+}
+
+#define ata_link_linkspeed_attr(field)					\
+	ata_link_show_linkspeed(field)					\
+static DEVICE_ATTR(field, S_IRUGO, show_ata_link_##field, NULL)
+
+ata_link_linkspeed_attr(hw_sata_spd_limit);
+ata_link_linkspeed_attr(sata_spd_limit);
+ata_link_linkspeed_attr(sata_spd);
+
+
+static DECLARE_TRANSPORT_CLASS(ata_link_class,
+		"ata_link", NULL, NULL, NULL);
+
+static void ata_tlink_release(struct device *dev)
+{
+	put_device(dev->parent);
+}
+
+/**
+ * ata_is_link --  check if a struct device represents a ATA link
+ * @dev:	device to check
+ *
+ * Returns:
+ *	%1 if the device represents a ATA link, %0 else
+ */
+int ata_is_link(const struct device *dev)
+{
+	return dev->release == ata_tlink_release;
+}
+
+static int ata_tlink_match(struct attribute_container *cont,
+			   struct device *dev)
+{
+	struct ata_internal* i = to_ata_internal(ata_scsi_transport_template);
+	if (!ata_is_link(dev))
+		return 0;
+	return &i->link_attr_cont.ac == cont;
+}
+
+/**
+ * ata_tlink_delete  --  remove ATA LINK
+ * @port:	ATA LINK to remove
+ *
+ * Removes the specified ATA LINK.  remove associated ATA device(s) as well.
+ */
+void ata_tlink_delete(struct ata_link *link)
+{
+	struct device *dev = &link->tdev;
+	struct ata_device *ata_dev;
+
+	ata_for_each_dev(ata_dev, link, ALL) {
+		ata_tdev_delete(ata_dev);
+	}
+
+	transport_remove_device(dev);
+	device_del(dev);
+	transport_destroy_device(dev);
+	put_device(dev);
+}
+
+/**
+ * ata_tlink_add  --  initialize a transport ATA link structure
+ * @link:	allocated ata_link structure.
+ *
+ * Initialize an ATA LINK structure for sysfs.  It will be added in the
+ * device tree below the ATA PORT it belongs to.
+ *
+ * Returns %0 on success
+ */
+int ata_tlink_add(struct ata_link *link)
+{
+	struct device *dev = &link->tdev;
+	struct ata_port *ap = link->ap;
+	struct ata_device *ata_dev;
+	int error;
+
+	device_initialize(dev);
+	dev->parent = get_device(&ap->tdev);
+	dev->release = ata_tlink_release;
+	if (ata_is_host_link(link))
+		dev_set_name(dev, "link%d", ap->print_id);
+        else
+		dev_set_name(dev, "link%d.%d", ap->print_id, link->pmp);
+
+	transport_setup_device(dev);
+
+	error = device_add(dev);
+	if (error) {
+		goto tlink_err;
+	}
+
+	transport_add_device(dev);
+	transport_configure_device(dev);
+
+	ata_for_each_dev(ata_dev, link, ALL) {
+		error = ata_tdev_add(ata_dev);
+		if (error) {
+			goto tlink_dev_err;
+		}
+	}
+	return 0;
+  tlink_dev_err:
+	while (--ata_dev >= link->device) {
+		ata_tdev_delete(ata_dev);
+	}
+	transport_remove_device(dev);
+	device_del(dev);
+  tlink_err:
+	transport_destroy_device(dev);
+	put_device(dev);
+	return error;
+}
+
+/*
+ * ATA device attributes
+ */
+
+#define ata_dev_show_class(title, field)				\
+static ssize_t								\
+show_ata_dev_##field(struct device *dev,				\
+		     struct device_attribute *attr, char *buf)		\
+{									\
+	struct ata_device *ata_dev = transport_class_to_dev(dev);	\
+									\
+	return get_ata_##title##_names(ata_dev->field, buf);		\
+}
+
+#define ata_dev_attr(title, field)					\
+	ata_dev_show_class(title, field)				\
+static DEVICE_ATTR(field, S_IRUGO, show_ata_dev_##field, NULL)
+
+ata_dev_attr(class, class);
+ata_dev_attr(xfer, pio_mode);
+ata_dev_attr(xfer, dma_mode);
+ata_dev_attr(xfer, xfer_mode);
+
+
+#define ata_dev_show_simple(field, format_string, cast)		\
+static ssize_t								\
+show_ata_dev_##field(struct device *dev,				\
+		     struct device_attribute *attr, char *buf)		\
+{									\
+	struct ata_device *ata_dev = transport_class_to_dev(dev);	\
+									\
+	return snprintf(buf, 20, format_string, cast ata_dev->field);	\
+}
+
+#define ata_dev_simple_attr(field, format_string, type)	\
+	ata_dev_show_simple(field, format_string, (type))	\
+static DEVICE_ATTR(field, S_IRUGO, 			\
+		   show_ata_dev_##field, NULL)
+
+ata_dev_simple_attr(spdn_cnt, "%d\n", int);
+
+struct ata_show_ering_arg {
+	char* buf;
+	int written;
+};
+
+static int ata_show_ering(struct ata_ering_entry *ent, void *void_arg)
+{
+	struct ata_show_ering_arg* arg = void_arg;
+	struct timespec time;
+
+	jiffies_to_timespec(ent->timestamp,&time);
+	arg->written += sprintf(arg->buf + arg->written,
+			       "[%5lu.%06lu]",
+			       time.tv_sec, time.tv_nsec);
+	arg->written += get_ata_err_names(ent->err_mask,
+					  arg->buf + arg->written);
+	return 0;
+}
+
+static ssize_t
+show_ata_dev_ering(struct device *dev,
+		   struct device_attribute *attr, char *buf)
+{
+	struct ata_device *ata_dev = transport_class_to_dev(dev);
+	struct ata_show_ering_arg arg = { buf, 0 };
+
+	ata_ering_map(&ata_dev->ering, ata_show_ering, &arg);
+	return arg.written;
+}
+
+
+static DEVICE_ATTR(ering, S_IRUGO, show_ata_dev_ering, NULL);
+
+static ssize_t
+show_ata_dev_id(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct ata_device *ata_dev = transport_class_to_dev(dev);
+	int written = 0, i = 0;
+
+	if (ata_dev->class == ATA_DEV_PMP)
+		return 0;
+	for(i=0;i<ATA_ID_WORDS;i++)  {
+		written += snprintf(buf+written, 20, "%04x%c",
+				    ata_dev->id[i],
+				    ((i+1) & 7) ? ' ' : '\n');
+	}
+	return written;
+}
+
+static DEVICE_ATTR(id, S_IRUGO, show_ata_dev_id, NULL);
+
+static ssize_t
+show_ata_dev_gscr(struct device *dev,
+		  struct device_attribute *attr, char *buf)
+{
+	struct ata_device *ata_dev = transport_class_to_dev(dev);
+	int written = 0, i = 0;
+
+	if (ata_dev->class != ATA_DEV_PMP)
+		return 0;
+	for(i=0;i<SATA_PMP_GSCR_DWORDS;i++)  {
+		written += snprintf(buf+written, 20, "%08x%c",
+				    ata_dev->gscr[i],
+				    ((i+1) & 3) ? ' ' : '\n');
+	}
+	if (SATA_PMP_GSCR_DWORDS & 3)
+		buf[written-1] = '\n';
+	return written;
+}
+
+static DEVICE_ATTR(gscr, S_IRUGO, show_ata_dev_gscr, NULL);
+
+static DECLARE_TRANSPORT_CLASS(ata_dev_class,
+			       "ata_device", NULL, NULL, NULL);
+
+static void ata_tdev_release(struct device *dev)
+{
+	put_device(dev->parent);
+}
+
+/**
+ * ata_is_ata_dev  --  check if a struct device represents a ATA device
+ * @dev:	device to check
+ *
+ * Returns:
+ *	%1 if the device represents a ATA device, %0 else
+ */
+int ata_is_ata_dev(const struct device *dev)
+{
+	return dev->release == ata_tdev_release;
+}
+
+static int ata_tdev_match(struct attribute_container *cont,
+			  struct device *dev)
+{
+	struct ata_internal* i = to_ata_internal(ata_scsi_transport_template);
+	if (!ata_is_ata_dev(dev))
+		return 0;
+	return &i->dev_attr_cont.ac == cont;
+}
+
+/**
+ * ata_tdev_free  --  free a ATA LINK
+ * @dev:	ATA PHY to free
+ *
+ * Frees the specified ATA PHY.
+ *
+ * Note:
+ *   This function must only be called on a PHY that has not
+ *   successfully been added using ata_tdev_add().
+ */
+static void ata_tdev_free(struct ata_device *dev)
+{
+	transport_destroy_device(&dev->tdev);
+	put_device(&dev->tdev);
+}
+
+/**
+ * ata_tdev_delete  --  remove ATA device
+ * @port:	ATA PORT to remove
+ *
+ * Removes the specified ATA device.
+ */
+static void ata_tdev_delete(struct ata_device *ata_dev)
+{
+	struct device *dev = &ata_dev->tdev;
+
+	transport_remove_device(dev);
+	device_del(dev);
+	ata_tdev_free(ata_dev);
+}
+
+
+/**
+ * ata_tdev_add  --  initialize a transport ATA device structure.
+ * @ata_dev:	ata_dev structure.
+ *
+ * Initialize an ATA device structure for sysfs.  It will be added in the
+ * device tree below the ATA LINK device it belongs to.
+ *
+ * Returns %0 on success
+ */
+static int ata_tdev_add(struct ata_device *ata_dev)
+{
+	struct device *dev = &ata_dev->tdev;
+	struct ata_link *link = ata_dev->link;
+	struct ata_port *ap = link->ap;
+	int error;
+
+	device_initialize(dev);
+	dev->parent = get_device(&link->tdev);
+	dev->release = ata_tdev_release;
+	if (ata_is_host_link(link))
+		dev_set_name(dev, "dev%d.%d", ap->print_id,ata_dev->devno);
+        else
+		dev_set_name(dev, "dev%d.%d.0", ap->print_id, link->pmp);
+
+	transport_setup_device(dev);
+	error = device_add(dev);
+	if (error) {
+		ata_tdev_free(ata_dev);
+		return error;
+	}
+
+	transport_add_device(dev);
+	transport_configure_device(dev);
+	return 0;
+}
+
+
+/*
+ * Setup / Teardown code
+ */
+
+#define SETUP_TEMPLATE(attrb, field, perm, test)			\
+	i->private_##attrb[count] = dev_attr_##field;		       	\
+	i->private_##attrb[count].attr.mode = perm;			\
+	i->attrb[count] = &i->private_##attrb[count];			\
+	if (test)							\
+		count++
+
+#define SETUP_LINK_ATTRIBUTE(field)					\
+	SETUP_TEMPLATE(link_attrs, field, S_IRUGO, 1)
+
+#define SETUP_PORT_ATTRIBUTE(field)					\
+	SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
+
+#define SETUP_DEV_ATTRIBUTE(field)					\
+	SETUP_TEMPLATE(dev_attrs, field, S_IRUGO, 1)
+
+/**
+ * ata_attach_transport  --  instantiate ATA transport template
+ */
+struct scsi_transport_template *ata_attach_transport(void)
+{
+	struct ata_internal *i;
+	int count;
+
+	i = kzalloc(sizeof(struct ata_internal), GFP_KERNEL);
+	if (!i)
+		return NULL;
+
+	i->t.eh_strategy_handler	= ata_scsi_error;
+	i->t.eh_timed_out		= ata_scsi_timed_out;
+	i->t.user_scan			= ata_scsi_user_scan;
+
+	i->t.host_attrs.ac.attrs = &i->port_attrs[0];
+	i->t.host_attrs.ac.class = &ata_port_class.class;
+	i->t.host_attrs.ac.match = ata_tport_match;
+	transport_container_register(&i->t.host_attrs);
+
+	i->link_attr_cont.ac.class = &ata_link_class.class;
+	i->link_attr_cont.ac.attrs = &i->link_attrs[0];
+	i->link_attr_cont.ac.match = ata_tlink_match;
+	transport_container_register(&i->link_attr_cont);
+
+	i->dev_attr_cont.ac.class = &ata_dev_class.class;
+	i->dev_attr_cont.ac.attrs = &i->dev_attrs[0];
+	i->dev_attr_cont.ac.match = ata_tdev_match;
+	transport_container_register(&i->dev_attr_cont);
+
+	count = 0;
+	SETUP_PORT_ATTRIBUTE(nr_pmp_links);
+	SETUP_PORT_ATTRIBUTE(idle_irq);
+	BUG_ON(count > ATA_PORT_ATTRS);
+	i->port_attrs[count] = NULL;
+
+	count = 0;
+	SETUP_LINK_ATTRIBUTE(hw_sata_spd_limit);
+	SETUP_LINK_ATTRIBUTE(sata_spd_limit);
+	SETUP_LINK_ATTRIBUTE(sata_spd);
+	BUG_ON(count > ATA_LINK_ATTRS);
+	i->link_attrs[count] = NULL;
+
+	count = 0;
+	SETUP_DEV_ATTRIBUTE(class);
+	SETUP_DEV_ATTRIBUTE(pio_mode);
+	SETUP_DEV_ATTRIBUTE(dma_mode);
+	SETUP_DEV_ATTRIBUTE(xfer_mode);
+	SETUP_DEV_ATTRIBUTE(spdn_cnt);
+	SETUP_DEV_ATTRIBUTE(ering);
+	SETUP_DEV_ATTRIBUTE(id);
+	SETUP_DEV_ATTRIBUTE(gscr);
+	BUG_ON(count > ATA_DEV_ATTRS);
+	i->dev_attrs[count] = NULL;
+
+	return &i->t;
+}
+
+/**
+ * ata_release_transport  --  release ATA transport template instance
+ * @t:		transport template instance
+ */
+void ata_release_transport(struct scsi_transport_template *t)
+{
+	struct ata_internal *i = to_ata_internal(t);
+
+	transport_container_unregister(&i->t.host_attrs);
+	transport_container_unregister(&i->link_attr_cont);
+	transport_container_unregister(&i->dev_attr_cont);
+
+	kfree(i);
+}
+
+__init int libata_transport_init(void)
+{
+	int error;
+
+	error = transport_class_register(&ata_link_class);
+	if (error)
+		goto out_unregister_transport;
+	error = transport_class_register(&ata_port_class);
+	if (error)
+		goto out_unregister_link;
+	error = transport_class_register(&ata_dev_class);
+	if (error)
+		goto out_unregister_port;
+	return 0;
+
+ out_unregister_port:
+	transport_class_unregister(&ata_port_class);
+ out_unregister_link:
+	transport_class_unregister(&ata_link_class);
+ out_unregister_transport:
+	return error;
+
+}
+
+void __exit libata_transport_exit(void)
+{
+	transport_class_unregister(&ata_link_class);
+	transport_class_unregister(&ata_port_class);
+	transport_class_unregister(&ata_dev_class);
+}
diff --git a/drivers/ata/libata-transport.h b/drivers/ata/libata-transport.h
new file mode 100644
index 0000000..2820cf8
--- /dev/null
+++ b/drivers/ata/libata-transport.h
@@ -0,0 +1,18 @@
+#ifndef _LIBATA_TRANSPORT_H
+#define _LIBATA_TRANSPORT_H
+
+
+extern struct scsi_transport_template *ata_scsi_transport_template;
+
+int ata_tlink_add(struct ata_link *link);
+void ata_tlink_delete(struct ata_link *link);
+
+int ata_tport_add(struct device *parent, struct ata_port *ap);
+void ata_tport_delete(struct ata_port *ap);
+
+struct scsi_transport_template *ata_attach_transport(void);
+void ata_release_transport(struct scsi_transport_template *t);
+
+__init int libata_transport_init(void);
+void __exit libata_transport_exit(void);
+#endif
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 9ce1ecc..a9be110 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -86,6 +86,8 @@
 extern int ata_dev_configure(struct ata_device *dev);
 extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit);
 extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
+extern unsigned int ata_dev_set_feature(struct ata_device *dev,
+					u8 enable, u8 feature);
 extern void ata_sg_clean(struct ata_queued_cmd *qc);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
 extern void ata_qc_issue(struct ata_queued_cmd *qc);
@@ -100,8 +102,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 void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy);
-extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
+extern const char *sata_spd_string(unsigned int spd);
 
 /* libata-acpi.c */
 #ifdef CONFIG_ATA_ACPI
@@ -137,10 +138,15 @@
 extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
 extern void ata_scsi_dev_rescan(struct work_struct *work);
 extern int ata_bus_probe(struct ata_port *ap);
+extern int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+			      unsigned int id, unsigned int lun);
+
 
 /* libata-eh.c */
 extern unsigned long ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd);
 extern void ata_internal_cmd_timed_out(struct ata_device *dev, u8 cmd);
+extern void ata_eh_acquire(struct ata_port *ap);
+extern void ata_eh_release(struct ata_port *ap);
 extern enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
 extern void ata_scsi_error(struct Scsi_Host *host);
 extern void ata_port_wait_eh(struct ata_port *ap);
@@ -164,11 +170,16 @@
 			  ata_postreset_fn_t postreset,
 			  struct ata_link **r_failed_disk);
 extern void ata_eh_finish(struct ata_port *ap);
+extern int ata_ering_map(struct ata_ering *ering,
+			 int (*map_fn)(struct ata_ering_entry *, void *),
+		  	 void *arg);
 
 /* libata-pmp.c */
 #ifdef CONFIG_SATA_PMP
 extern int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val);
 extern int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val);
+extern int sata_pmp_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+			    unsigned hints);
 extern int sata_pmp_attach(struct ata_device *dev);
 #else /* CONFIG_SATA_PMP */
 static inline int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val)
@@ -181,6 +192,12 @@
 	return -EINVAL;
 }
 
+static inline int sata_pmp_set_lpm(struct ata_link *link,
+				   enum ata_lpm_policy policy, unsigned hints)
+{
+	return -EINVAL;
+}
+
 static inline int sata_pmp_attach(struct ata_device *dev)
 {
 	return -EINVAL;
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index 9cae65d..ec2c777 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -826,7 +826,7 @@
  *	@ctl: value to write
  */
 
-static u8 bfin_set_devctl(struct ata_port *ap, u8 ctl)
+static void bfin_set_devctl(struct ata_port *ap, u8 ctl)
 {
 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
 	write_atapi_register(base, ATA_REG_CTRL, ctl);
@@ -1046,7 +1046,7 @@
 			dev1 = 0;
 			break;
 		}
-		msleep(50);	/* give drive a breather */
+		ata_msleep(ap, 50);	/* give drive a breather */
 	}
 	if (dev1)
 		ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
@@ -1087,7 +1087,7 @@
 	 *
 	 * Old drivers/ide uses the 2mS rule and then waits for ready
 	 */
-	msleep(150);
+	ata_msleep(ap, 150);
 
 	/* Before we perform post reset processing we want to see if
 	 * the bus shows 0xFF because the odd clown forgets the D7
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index e5f289f..549d28d 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -161,6 +161,17 @@
 	return 0;
 }
 
+static bool cmd640_sff_irq_check(struct ata_port *ap)
+{
+	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	int irq_reg		= ap->port_no ? ARTIM23 : CFR;
+	u8  irq_stat, irq_mask	= ap->port_no ? 0x10 : 0x04;
+
+	pci_read_config_byte(pdev, irq_reg, &irq_stat);
+
+	return irq_stat & irq_mask;
+}
+
 static struct scsi_host_template cmd640_sht = {
 	ATA_PIO_SHT(DRV_NAME),
 };
@@ -169,6 +180,7 @@
 	.inherits	= &ata_sff_port_ops,
 	/* In theory xfer_noirq is not needed once we kill the prefetcher */
 	.sff_data_xfer	= ata_sff_data_xfer_noirq,
+	.sff_irq_check	= cmd640_sff_irq_check,
 	.qc_issue	= cmd640_qc_issue,
 	.cable_detect	= ata_cable_40wire,
 	.set_piomode	= cmd640_set_piomode,
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index e944aa0..8062921 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -34,7 +34,6 @@
 #include <linux/ata.h>
 #include <linux/libata.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/cisreg.h>
@@ -168,63 +167,26 @@
 };
 
 
-struct pcmcia_config_check {
-	unsigned long ctl_base;
-	int skip_vcc;
-	int is_kme;
-};
-
-static int pcmcia_check_one_config(struct pcmcia_device *pdev,
-				   cistpl_cftable_entry_t *cfg,
-				   cistpl_cftable_entry_t *dflt,
-				   unsigned int vcc,
-				   void *priv_data)
+static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
 {
-	struct pcmcia_config_check *stk = priv_data;
+	int *is_kme = priv_data;
 
-	/* Check for matching Vcc, unless we're desperate */
-	if (!stk->skip_vcc) {
-		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-			if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
-				return -ENODEV;
-		} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-			if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
-				return -ENODEV;
-		}
+	if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
+		pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	}
+	pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 
-	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		pdev->resource[0]->start = io->win[0].base;
-		if (!(io->flags & CISTPL_IO_16BIT)) {
-			pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-			pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-		}
-		if (io->nwin == 2) {
-			pdev->resource[0]->end = 8;
-			pdev->resource[1]->start = io->win[1].base;
-			pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
-			if (pcmcia_request_io(pdev) != 0)
-				return -ENODEV;
-			stk->ctl_base = pdev->resource[1]->start;
-		} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
-			pdev->resource[0]->end = io->win[0].len;
-			pdev->resource[1]->end = 0;
-			if (pcmcia_request_io(pdev) != 0)
-				return -ENODEV;
-			stk->ctl_base = pdev->resource[0]->start + 0x0e;
-		} else
+	if (pdev->resource[1]->end) {
+		pdev->resource[0]->end = 8;
+		pdev->resource[1]->end = (*is_kme) ? 2 : 1;
+	} else {
+		if (pdev->resource[0]->end < 16)
 			return -ENODEV;
-		/* If we've got this far, we're done */
-		return 0;
 	}
-	return -ENODEV;
+
+	return pcmcia_request_io(pdev);
 }
 
 /**
@@ -239,7 +201,6 @@
 {
 	struct ata_host *host;
 	struct ata_port *ap;
-	struct pcmcia_config_check *stk = NULL;
 	int is_kme = 0, ret = -ENOMEM, p;
 	unsigned long io_base, ctl_base;
 	void __iomem *io_addr, *ctl_addr;
@@ -247,10 +208,8 @@
 	struct ata_port_operations *ops = &pcmcia_port_ops;
 
 	/* Set up attributes in order to probe card and get resources */
-	pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-	pdev->conf.Attributes = CONF_ENABLE_IRQ;
-	pdev->conf.IntType = INT_MEMORY_AND_IO;
+	pdev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
+		CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
 
 	/* See if we have a manufacturer identifier. Use it to set is_kme for
 	   vendor quirks */
@@ -258,25 +217,21 @@
 		  ((pdev->card_id == PRODID_KME_KXLC005_A) ||
 		   (pdev->card_id == PRODID_KME_KXLC005_B)));
 
-	/* Allocate resoure probing structures */
-
-	stk = kzalloc(sizeof(*stk), GFP_KERNEL);
-	if (!stk)
-		goto out1;
-	stk->is_kme = is_kme;
-	stk->skip_vcc = io_base = ctl_base = 0;
-
-	if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) {
-		stk->skip_vcc = 1;
-		if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
+	if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) {
+		pdev->config_flags &= ~CONF_AUTO_CHECK_VCC;
+		if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme))
 			goto failed; /* No suitable config found */
 	}
 	io_base = pdev->resource[0]->start;
-	ctl_base = stk->ctl_base;
+	if (pdev->resource[1]->end)
+		ctl_base = pdev->resource[1]->start;
+	else
+		ctl_base = pdev->resource[0]->start + 0x0e;
+
 	if (!pdev->irq)
 		goto failed;
 
-	ret = pcmcia_request_configuration(pdev, &pdev->conf);
+	ret = pcmcia_enable_device(pdev);
 	if (ret)
 		goto failed;
 
@@ -329,13 +284,10 @@
 		goto failed;
 
 	pdev->priv = host;
-	kfree(stk);
 	return 0;
 
 failed:
-	kfree(stk);
 	pcmcia_disable_device(pdev);
-out1:
 	return ret;
 }
 
@@ -430,9 +382,7 @@
 
 static struct pcmcia_driver pcmcia_driver = {
 	.owner		= THIS_MODULE,
-	.drv = {
-		.name		= DRV_NAME,
-	},
+	.name		= DRV_NAME,
 	.id_table	= pcmcia_devices,
 	.probe		= pcmcia_init_one,
 	.remove		= pcmcia_remove_one,
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index c39f213..c2ed586 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -44,6 +44,27 @@
 	ndelay(400);
 }
 
+static bool pdc202xx_irq_check(struct ata_port *ap)
+{
+	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	unsigned long master	= pci_resource_start(pdev, 4);
+	u8 sc1d			= inb(master + 0x1d);
+
+	if (ap->port_no) {
+		/*
+		 * bit 7: error, bit 6: interrupting,
+		 * bit 5: FIFO full, bit 4: FIFO empty
+		 */
+		return sc1d & 0x40;
+	} else	{
+		/*
+		 * bit 3: error, bit 2: interrupting,
+		 * bit 1: FIFO full, bit 0: FIFO empty
+		 */
+		return sc1d & 0x04;
+	}
+}
+
 /**
  *	pdc202xx_configure_piomode	-	set chip PIO timing
  *	@ap: ATA interface
@@ -282,6 +303,7 @@
 	.set_dmamode		= pdc202xx_set_dmamode,
 
 	.sff_exec_command	= pdc202xx_exec_command,
+	.sff_irq_check		= pdc202xx_irq_check,
 };
 
 static struct ata_port_operations pdc2026x_port_ops = {
@@ -297,6 +319,7 @@
 	.port_start		= pdc2026x_port_start,
 
 	.sff_exec_command	= pdc202xx_exec_command,
+	.sff_irq_check		= pdc202xx_irq_check,
 };
 
 static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index 6f9cfb2..8a51d67 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -322,7 +322,7 @@
 {
 	int rc;
 
-	msleep(ATA_WAIT_AFTER_RESET);
+	ata_msleep(link->ap, ATA_WAIT_AFTER_RESET);
 
 	/* always check readiness of the master device */
 	rc = ata_sff_wait_ready(link, deadline);
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index fe36966..093715c 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -530,7 +530,7 @@
 	 *
 	 * Old drivers/ide uses the 2mS rule and then waits for ready.
 	 */
-	msleep(150);
+	ata_msleep(ap, 150);
 
 	/* always check readiness of the master device */
 	rc = ata_sff_wait_ready(link, deadline);
@@ -559,7 +559,7 @@
 			lbal = in_be32(ioaddr->lbal_addr);
 			if ((nsect == 1) && (lbal == 1))
 				break;
-			msleep(50);	/* give drive a breather */
+			ata_msleep(ap, 50);	/* give drive a breather */
 		}
 
 		rc = ata_sff_wait_ready(link, deadline);
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index d3190d7..00eefbd 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -202,14 +202,25 @@
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
  */
-void sil680_sff_exec_command(struct ata_port *ap,
-					const struct ata_taskfile *tf)
+static void sil680_sff_exec_command(struct ata_port *ap,
+				    const struct ata_taskfile *tf)
 {
 	DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
 	iowrite8(tf->command, ap->ioaddr.command_addr);
 	ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 }
 
+static bool sil680_sff_irq_check(struct ata_port *ap)
+{
+	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	unsigned long addr	= sil680_selreg(ap, 1);
+	u8 val;
+
+	pci_read_config_byte(pdev, addr, &val);
+
+	return val & 0x08;
+}
+
 static struct scsi_host_template sil680_sht = {
 	ATA_BMDMA_SHT(DRV_NAME),
 };
@@ -218,6 +229,7 @@
 static struct ata_port_operations sil680_port_ops = {
 	.inherits		= &ata_bmdma32_port_ops,
 	.sff_exec_command	= sil680_sff_exec_command,
+	.sff_irq_check		= sil680_sff_irq_check,
 	.cable_detect		= sil680_cable_detect,
 	.set_piomode		= sil680_set_piomode,
 	.set_dmamode		= sil680_set_dmamode,
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 98548f6..7f5d020 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -227,6 +227,16 @@
 	return 0;
 }
 
+static bool sl82c105_sff_irq_check(struct ata_port *ap)
+{
+	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
+	u32 val, mask		= ap->port_no ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
+
+	pci_read_config_dword(pdev, 0x40, &val);
+
+	return val & mask;
+}
+
 static struct scsi_host_template sl82c105_sht = {
 	ATA_BMDMA_SHT(DRV_NAME),
 };
@@ -239,6 +249,7 @@
 	.cable_detect	= ata_cable_40wire,
 	.set_piomode	= sl82c105_set_piomode,
 	.prereset	= sl82c105_pre_reset,
+	.sff_irq_check	= sl82c105_sff_irq_check,
 };
 
 /**
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 7325f77..b0214d0 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -678,7 +678,7 @@
 	iowrite32(temp, hcr_base + HCONTROL);
 
 	/* Poll for controller to go offline - should happen immediately */
-	ata_wait_register(hcr_base + HSTATUS, ONLINE, ONLINE, 1, 1);
+	ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, ONLINE, 1, 1);
 
 	ap->private_data = NULL;
 	dma_free_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ,
@@ -729,7 +729,8 @@
 	iowrite32(temp, hcr_base + HCONTROL);
 
 	/* Poll for controller to go offline */
-	temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, ONLINE, 1, 500);
+	temp = ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, ONLINE,
+				 1, 500);
 
 	if (temp & ONLINE) {
 		ata_port_printk(ap, KERN_ERR,
@@ -752,7 +753,7 @@
 	/*
 	 * PHY reset should remain asserted for atleast 1ms
 	 */
-	msleep(1);
+	ata_msleep(ap, 1);
 
 	/*
 	 * Now, bring the host controller online again, this can take time
@@ -766,7 +767,7 @@
 	temp |= HCONTROL_PMP_ATTACHED;
 	iowrite32(temp, hcr_base + HCONTROL);
 
-	temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, 0, 1, 500);
+	temp = ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, 0, 1, 500);
 
 	if (!(temp & ONLINE)) {
 		ata_port_printk(ap, KERN_ERR,
@@ -784,7 +785,7 @@
 	 * presence
 	 */
 
-	temp = ata_wait_register(hcr_base + HSTATUS, 0xFF, 0, 1, 500);
+	temp = ata_wait_register(ap, hcr_base + HSTATUS, 0xFF, 0, 1, 500);
 	if ((!(temp & 0x10)) || ata_link_offline(link)) {
 		ata_port_printk(ap, KERN_WARNING,
 				"No Device OR PHYRDY change,Hstatus = 0x%x\n",
@@ -797,7 +798,7 @@
 	 * Wait for the first D2H from device,i.e,signature update notification
 	 */
 	start_jiffies = jiffies;
-	temp = ata_wait_register(hcr_base + HSTATUS, 0xFF, 0x10,
+	temp = ata_wait_register(ap, hcr_base + HSTATUS, 0xFF, 0x10,
 			500, jiffies_to_msecs(deadline - start_jiffies));
 
 	if ((temp & 0xFF) != 0x18) {
@@ -880,7 +881,7 @@
 		iowrite32(pmp, CQPMP + hcr_base);
 	iowrite32(1, CQ + hcr_base);
 
-	temp = ata_wait_register(CQ + hcr_base, 0x1, 0x1, 1, 5000);
+	temp = ata_wait_register(ap, CQ + hcr_base, 0x1, 0x1, 1, 5000);
 	if (temp & 0x1) {
 		ata_port_printk(ap, KERN_WARNING, "ATA_SRST issue failed\n");
 
@@ -896,7 +897,7 @@
 		goto err;
 	}
 
-	msleep(1);
+	ata_msleep(ap, 1);
 
 	/*
 	 * SATA device enters reset state after receving a Control register
@@ -915,7 +916,7 @@
 	if (pmp != SATA_PMP_CTRL_PORT)
 		iowrite32(pmp, CQPMP + hcr_base);
 	iowrite32(1, CQ + hcr_base);
-	msleep(150);		/* ?? */
+	ata_msleep(ap, 150);		/* ?? */
 
 	/*
 	 * The above command would have signalled an interrupt on command
@@ -1137,17 +1138,13 @@
 			ioread32(hcr_base + CE));
 
 		for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
-			if (done_mask & (1 << i)) {
-				qc = ata_qc_from_tag(ap, i);
-				if (qc) {
-					ata_qc_complete(qc);
-				}
+			if (done_mask & (1 << i))
 				DPRINTK
 				    ("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
 				     i, ioread32(hcr_base + CC),
 				     ioread32(hcr_base + CA));
-			}
 		}
+		ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
 		return;
 
 	} else if ((ap->qc_active & (1 << ATA_TAG_INTERNAL))) {
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index a36149e..83a4447 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -614,7 +614,7 @@
 
 	writew(IDMA_CTL_RST_ATA, idma_ctl);
 	readw(idma_ctl);	/* flush */
-	msleep(1);
+	ata_msleep(ap, 1);
 	writew(0, idma_ctl);
 
 	rc = sata_link_resume(link, timing, deadline);
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index a9fd970..bf74a36 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -2743,18 +2743,11 @@
 	}
 }
 
-static void mv_process_crpb_response(struct ata_port *ap,
+static bool mv_process_crpb_response(struct ata_port *ap,
 		struct mv_crpb *response, unsigned int tag, int ncq_enabled)
 {
 	u8 ata_status;
 	u16 edma_status = le16_to_cpu(response->flags);
-	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
-
-	if (unlikely(!qc)) {
-		ata_port_printk(ap, KERN_ERR, "%s: no qc for tag=%d\n",
-				__func__, tag);
-		return;
-	}
 
 	/*
 	 * edma_status from a response queue entry:
@@ -2768,13 +2761,14 @@
 			 * Error will be seen/handled by
 			 * mv_err_intr().  So do nothing at all here.
 			 */
-			return;
+			return false;
 		}
 	}
 	ata_status = edma_status >> CRPB_FLAG_STATUS_SHIFT;
 	if (!ac_err_mask(ata_status))
-		ata_qc_complete(qc);
+		return true;
 	/* else: leave it for mv_err_intr() */
+	return false;
 }
 
 static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp)
@@ -2783,6 +2777,7 @@
 	struct mv_host_priv *hpriv = ap->host->private_data;
 	u32 in_index;
 	bool work_done = false;
+	u32 done_mask = 0;
 	int ncq_enabled = (pp->pp_flags & MV_PP_FLAG_NCQ_EN);
 
 	/* Get the hardware queue position index */
@@ -2803,15 +2798,19 @@
 			/* Gen II/IIE: get command tag from CRPB entry */
 			tag = le16_to_cpu(response->id) & 0x1f;
 		}
-		mv_process_crpb_response(ap, response, tag, ncq_enabled);
+		if (mv_process_crpb_response(ap, response, tag, ncq_enabled))
+			done_mask |= 1 << tag;
 		work_done = true;
 	}
 
-	/* Update the software queue position index in hardware */
-	if (work_done)
+	if (work_done) {
+		ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+
+		/* Update the software queue position index in hardware */
 		writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
 			 (pp->resp_idx << EDMA_RSP_Q_PTR_SHIFT),
 			 port_mmio + EDMA_RSP_Q_OUT_PTR);
+	}
 }
 
 static void mv_port_intr(struct ata_port *ap, u32 port_cause)
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index cb89ef8..7254e25 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -873,29 +873,11 @@
 			ata_port_freeze(ap);
 		else
 			ata_port_abort(ap);
-		return 1;
+		return -1;
 	}
 
-	if (likely(flags & NV_CPB_RESP_DONE)) {
-		struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
-		VPRINTK("CPB flags done, flags=0x%x\n", flags);
-		if (likely(qc)) {
-			DPRINTK("Completing qc from tag %d\n", cpb_num);
-			ata_qc_complete(qc);
-		} else {
-			struct ata_eh_info *ehi = &ap->link.eh_info;
-			/* Notifier bits set without a command may indicate the drive
-			   is misbehaving. Raise host state machine violation on this
-			   condition. */
-			ata_port_printk(ap, KERN_ERR,
-					"notifier for tag %d with no cmd?\n",
-					cpb_num);
-			ehi->err_mask |= AC_ERR_HSM;
-			ehi->action |= ATA_EH_RESET;
-			ata_port_freeze(ap);
-			return 1;
-		}
-	}
+	if (likely(flags & NV_CPB_RESP_DONE))
+		return 1;
 	return 0;
 }
 
@@ -1018,6 +1000,7 @@
 			      NV_ADMA_STAT_CPBERR |
 			      NV_ADMA_STAT_CMD_COMPLETE)) {
 			u32 check_commands = notifier_clears[i];
+			u32 done_mask = 0;
 			int pos, rc;
 
 			if (status & NV_ADMA_STAT_CPBERR) {
@@ -1034,10 +1017,13 @@
 				pos--;
 				rc = nv_adma_check_cpb(ap, pos,
 						notifier_error & (1 << pos));
-				if (unlikely(rc))
+				if (rc > 0)
+					done_mask |= 1 << pos;
+				else if (unlikely(rc < 0))
 					check_commands = 0;
 				check_commands &= ~(1 << pos);
 			}
+			ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
 		}
 	}
 
@@ -2132,7 +2118,6 @@
 	struct ata_eh_info *ehi = &ap->link.eh_info;
 	u32 sactive;
 	u32 done_mask;
-	int i;
 	u8 host_stat;
 	u8 lack_dhfis = 0;
 
@@ -2152,27 +2137,11 @@
 	sactive = readl(pp->sactive_block);
 	done_mask = pp->qc_active ^ sactive;
 
-	if (unlikely(done_mask & sactive)) {
-		ata_ehi_clear_desc(ehi);
-		ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition"
-				  "(%08x->%08x)", pp->qc_active, sactive);
-		ehi->err_mask |= AC_ERR_HSM;
-		ehi->action |= ATA_EH_RESET;
-		return -EINVAL;
-	}
-	for (i = 0; i < ATA_MAX_QUEUE; i++) {
-		if (!(done_mask & (1 << i)))
-			continue;
-
-		qc = ata_qc_from_tag(ap, i);
-		if (qc) {
-			ata_qc_complete(qc);
-			pp->qc_active &= ~(1 << i);
-			pp->dhfis_bits &= ~(1 << i);
-			pp->dmafis_bits &= ~(1 << i);
-			pp->sdbfis_bits |= (1 << i);
-		}
-	}
+	pp->qc_active &= ~done_mask;
+	pp->dhfis_bits &= ~done_mask;
+	pp->dmafis_bits &= ~done_mask;
+	pp->sdbfis_bits |= done_mask;
+	ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
 
 	if (!ap->qc_active) {
 		DPRINTK("over\n");
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index be7726d..af41c6f 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -589,9 +589,9 @@
 		sil24_clear_pmp(ap);
 
 	writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
-	ata_wait_register(port + PORT_CTRL_STAT,
+	ata_wait_register(ap, port + PORT_CTRL_STAT,
 			  PORT_CS_INIT, PORT_CS_INIT, 10, 100);
-	tmp = ata_wait_register(port + PORT_CTRL_STAT,
+	tmp = ata_wait_register(ap, port + PORT_CTRL_STAT,
 				PORT_CS_RDY, 0, 10, 100);
 
 	if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) {
@@ -631,7 +631,7 @@
 	writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
 
 	irq_mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT;
-	irq_stat = ata_wait_register(port + PORT_IRQ_STAT, irq_mask, 0x0,
+	irq_stat = ata_wait_register(ap, port + PORT_IRQ_STAT, irq_mask, 0x0,
 				     10, timeout_msec);
 
 	writel(irq_mask, port + PORT_IRQ_STAT); /* clear IRQs */
@@ -719,9 +719,9 @@
 				"state, performing PORT_RST\n");
 
 		writel(PORT_CS_PORT_RST, port + PORT_CTRL_STAT);
-		msleep(10);
+		ata_msleep(ap, 10);
 		writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
-		ata_wait_register(port + PORT_CTRL_STAT, PORT_CS_RDY, 0,
+		ata_wait_register(ap, port + PORT_CTRL_STAT, PORT_CS_RDY, 0,
 				  10, 5000);
 
 		/* restore port configuration */
@@ -740,7 +740,7 @@
 		tout_msec = 5000;
 
 	writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
-	tmp = ata_wait_register(port + PORT_CTRL_STAT,
+	tmp = ata_wait_register(ap, port + PORT_CTRL_STAT,
 				PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10,
 				tout_msec);
 
@@ -1253,7 +1253,7 @@
 		tmp = readl(port + PORT_CTRL_STAT);
 		if (tmp & PORT_CS_PORT_RST) {
 			writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
-			tmp = ata_wait_register(port + PORT_CTRL_STAT,
+			tmp = ata_wait_register(NULL, port + PORT_CTRL_STAT,
 						PORT_CS_PORT_RST,
 						PORT_CS_PORT_RST, 10, 100);
 			if (tmp & PORT_CS_PORT_RST)
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 4730c42..c215899 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -349,7 +349,7 @@
 
 	/* wait for phy to become ready, if necessary */
 	do {
-		msleep(200);
+		ata_msleep(link->ap, 200);
 		svia_scr_read(link, SCR_STATUS, &sstatus);
 		if ((sstatus & 0xf) != 1)
 			break;
diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile
index 62c3cc10..c6c9ee9 100644
--- a/drivers/atm/Makefile
+++ b/drivers/atm/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Linux network (ATM) device drivers.
 #
 
-fore_200e-objs	:= fore200e.o
+fore_200e-y	:= fore200e.o
 
 obj-$(CONFIG_ATM_ZATM)		+= zatm.o uPD98402.o
 obj-$(CONFIG_ATM_NICSTAR)	+= nicstar.o
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 8717809..5d86bb8 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -444,8 +444,8 @@
 #define ROUND_NEAREST 3
 /********** make rate (not quite as much fun as Horizon) **********/
 
-static unsigned int make_rate (unsigned int rate, int r,
-			       u16 * bits, unsigned int * actual) 
+static int make_rate(unsigned int rate, int r,
+		      u16 *bits, unsigned int *actual)
 {
 	unsigned char exp = -1; /* hush gcc */
 	unsigned int man = -1;  /* hush gcc */
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 54720ba..a957904 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -1645,10 +1645,8 @@
     unsigned short d = 0;
     char * s = skb->data;
     if (*s++ == 'D') {
-      for (i = 0; i < 4; ++i) {
-	d = (d<<4) | ((*s <= '9') ? (*s - '0') : (*s - 'a' + 10));
-	++s;
-      }
+	for (i = 0; i < 4; ++i)
+		d = (d << 4) | hex_to_bin(*s++);
       PRINTK (KERN_INFO, "debug bitmap is now %hx", debug = d);
     }
   }
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 1679cbf..bce5732 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -3152,7 +3152,7 @@
 }
 
 
-static int __devinit
+static void __devinit
 init_sram(struct idt77252_dev *card)
 {
 	int i;
@@ -3298,7 +3298,6 @@
 	       SAR_REG_RXFD);
 
 	IPRINTK("%s: SRAM initialization complete.\n", card->name);
-	return 0;
 }
 
 static int __devinit
@@ -3410,8 +3409,7 @@
 
 	writel(readl(SAR_REG_CFG) | conf, SAR_REG_CFG);
 
-	if (init_sram(card) < 0)
-		return -1;
+	init_sram(card);
 
 /********************************************************************/
 /*  A L L O C   R A M   A N D   S E T   V A R I O U S   T H I N G S */
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index ee9ddeb..9309d47 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -220,7 +220,7 @@
   while (!desc_num || (dev->desc_tbl[desc_num -1]).timestamp) {
      dev->ffL.tcq_rd += 2;
      if (dev->ffL.tcq_rd > dev->ffL.tcq_ed) 
-     dev->ffL.tcq_rd = dev->ffL.tcq_st;
+	dev->ffL.tcq_rd = dev->ffL.tcq_st;
      if (dev->ffL.tcq_rd == dev->host_tcq_wr) 
         return 0xFFFF; 
      desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd);
@@ -3156,7 +3156,6 @@
 {  
 	struct atm_dev *dev;  
 	IADEV *iadev;  
-        unsigned long flags;
 	int ret;
 
 	iadev = kzalloc(sizeof(*iadev), GFP_KERNEL);
@@ -3188,19 +3187,14 @@
 	ia_dev[iadev_count] = iadev;
 	_ia_dev[iadev_count] = dev;
 	iadev_count++;
-	spin_lock_init(&iadev->misc_lock);
-	/* First fixes first. I don't want to think about this now. */
-	spin_lock_irqsave(&iadev->misc_lock, flags); 
 	if (ia_init(dev) || ia_start(dev)) {  
 		IF_INIT(printk("IA register failed!\n");)
 		iadev_count--;
 		ia_dev[iadev_count] = NULL;
 		_ia_dev[iadev_count] = NULL;
-		spin_unlock_irqrestore(&iadev->misc_lock, flags); 
 		ret = -EINVAL;
 		goto err_out_deregister_dev;
 	}
-	spin_unlock_irqrestore(&iadev->misc_lock, flags); 
 	IF_EVENT(printk("iadev_count = %d\n", iadev_count);)
 
 	iadev->next_board = ia_boards;  
diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h
index b2cd20f..077735e 100644
--- a/drivers/atm/iphase.h
+++ b/drivers/atm/iphase.h
@@ -1022,7 +1022,7 @@
 	struct dle_q rx_dle_q;  
 	struct free_desc_q *rx_free_desc_qhead;  
 	struct sk_buff_head rx_dma_q;  
-        spinlock_t rx_lock, misc_lock;
+	spinlock_t rx_lock;
 	struct atm_vcc **rx_open;	/* list of all open VCs */  
         u16 num_rx_desc, rx_buf_sz, rxing;
         u32 rx_pkt_ram, rx_tmp_cnt;
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index f916ddf..f46138a 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -444,6 +444,7 @@
 	struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev);
 	struct solos_card *card = atmdev->dev_data;
 	struct sk_buff *skb;
+	unsigned int len;
 
 	spin_lock(&card->cli_queue_lock);
 	skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]);
@@ -451,11 +452,12 @@
 	if(skb == NULL)
 		return sprintf(buf, "No data.\n");
 
-	memcpy(buf, skb->data, skb->len);
-	dev_dbg(&card->dev->dev, "len: %d\n", skb->len);
+	len = skb->len;
+	memcpy(buf, skb->data, len);
+	dev_dbg(&card->dev->dev, "len: %d\n", len);
 
 	kfree_skb(skb);
-	return skb->len;
+	return len;
 }
 
 static int send_command(struct solos_card *card, int dev, const char *buf, size_t size)
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index ef38aff..fd96345 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -71,7 +71,6 @@
 
 config FW_LOADER
 	tristate "Userspace firmware loading support" if EMBEDDED
-	depends on HOTPLUG
 	default y
 	---help---
 	  This option is provided for the case where no in-kernel-tree modules
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index c12c7f2..5f51c3b 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -19,7 +19,5 @@
 endif
 obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
 
-ifeq ($(CONFIG_DEBUG_DRIVER),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index eb1b7fa..33c270a 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -440,22 +440,6 @@
 	}
 }
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-static int make_deprecated_bus_links(struct device *dev)
-{
-	return sysfs_create_link(&dev->kobj,
-				 &dev->bus->p->subsys.kobj, "bus");
-}
-
-static void remove_deprecated_bus_links(struct device *dev)
-{
-	sysfs_remove_link(&dev->kobj, "bus");
-}
-#else
-static inline int make_deprecated_bus_links(struct device *dev) { return 0; }
-static inline void remove_deprecated_bus_links(struct device *dev) { }
-#endif
-
 /**
  * bus_add_device - add device to bus
  * @dev: device being added
@@ -482,15 +466,10 @@
 				&dev->bus->p->subsys.kobj, "subsystem");
 		if (error)
 			goto out_subsys;
-		error = make_deprecated_bus_links(dev);
-		if (error)
-			goto out_deprecated;
 		klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
 	}
 	return 0;
 
-out_deprecated:
-	sysfs_remove_link(&dev->kobj, "subsystem");
 out_subsys:
 	sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
 out_id:
@@ -530,7 +509,6 @@
 {
 	if (dev->bus) {
 		sysfs_remove_link(&dev->kobj, "subsystem");
-		remove_deprecated_bus_links(dev);
 		sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
 				  dev_name(dev));
 		device_remove_attrs(dev->bus, dev);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 8e231d0..9c63a56 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -184,9 +184,9 @@
 	if (!cls->dev_kobj)
 		cls->dev_kobj = sysfs_dev_char_kobj;
 
-#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
+#if defined(CONFIG_BLOCK)
 	/* let the block class directory show up in the root of sysfs */
-	if (cls != &block_class)
+	if (!sysfs_deprecated || cls != &block_class)
 		cp->class_subsys.kobj.kset = class_kset;
 #else
 	cp->class_subsys.kobj.kset = class_kset;
@@ -276,25 +276,6 @@
 	class_unregister(cls);
 }
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-char *make_class_name(const char *name, struct kobject *kobj)
-{
-	char *class_name;
-	int size;
-
-	size = strlen(name) + strlen(kobject_name(kobj)) + 2;
-
-	class_name = kmalloc(size, GFP_KERNEL);
-	if (!class_name)
-		return NULL;
-
-	strcpy(class_name, name);
-	strcat(class_name, ":");
-	strcat(class_name, kobject_name(kobj));
-	return class_name;
-}
-#endif
-
 /**
  * class_dev_iter_init - initialize class device iterator
  * @iter: class iterator to initialize
diff --git a/drivers/base/core.c b/drivers/base/core.c
index d1b2c9a..2cb49a9 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -26,6 +26,19 @@
 #include "base.h"
 #include "power/power.h"
 
+#ifdef CONFIG_SYSFS_DEPRECATED
+#ifdef CONFIG_SYSFS_DEPRECATED_V2
+long sysfs_deprecated = 1;
+#else
+long sysfs_deprecated = 0;
+#endif
+static __init int sysfs_deprecated_setup(char *arg)
+{
+	return strict_strtol(arg, 10, &sysfs_deprecated);
+}
+early_param("sysfs.deprecated", sysfs_deprecated_setup);
+#endif
+
 int (*platform_notify)(struct device *dev) = NULL;
 int (*platform_notify_remove)(struct device *dev) = NULL;
 static struct kobject *dev_kobj;
@@ -203,37 +216,6 @@
 	if (dev->driver)
 		add_uevent_var(env, "DRIVER=%s", dev->driver->name);
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-	if (dev->class) {
-		struct device *parent = dev->parent;
-
-		/* find first bus device in parent chain */
-		while (parent && !parent->bus)
-			parent = parent->parent;
-		if (parent && parent->bus) {
-			const char *path;
-
-			path = kobject_get_path(&parent->kobj, GFP_KERNEL);
-			if (path) {
-				add_uevent_var(env, "PHYSDEVPATH=%s", path);
-				kfree(path);
-			}
-
-			add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name);
-
-			if (parent->driver)
-				add_uevent_var(env, "PHYSDEVDRIVER=%s",
-					       parent->driver->name);
-		}
-	} else if (dev->bus) {
-		add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
-
-		if (dev->driver)
-			add_uevent_var(env, "PHYSDEVDRIVER=%s",
-				       dev->driver->name);
-	}
-#endif
-
 	/* have the bus specific function add its stuff */
 	if (dev->bus && dev->bus->uevent) {
 		retval = dev->bus->uevent(dev, env);
@@ -578,24 +560,6 @@
 	set_dev_node(dev, -1);
 }
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-static struct kobject *get_device_parent(struct device *dev,
-					 struct device *parent)
-{
-	/* class devices without a parent live in /sys/class/<classname>/ */
-	if (dev->class && (!parent || parent->class != dev->class))
-		return &dev->class->p->class_subsys.kobj;
-	/* all other devices keep their parent */
-	else if (parent)
-		return &parent->kobj;
-
-	return NULL;
-}
-
-static inline void cleanup_device_parent(struct device *dev) {}
-static inline void cleanup_glue_dir(struct device *dev,
-				    struct kobject *glue_dir) {}
-#else
 static struct kobject *virtual_device_parent(struct device *dev)
 {
 	static struct kobject *virtual_dir = NULL;
@@ -666,6 +630,15 @@
 		struct kobject *parent_kobj;
 		struct kobject *k;
 
+#ifdef CONFIG_BLOCK
+		/* block disks show up in /sys/block */
+		if (sysfs_deprecated && dev->class == &block_class) {
+			if (parent && parent->class == &block_class)
+				return &parent->kobj;
+			return &block_class.p->class_subsys.kobj;
+		}
+#endif
+
 		/*
 		 * If we have no parent, we live in "virtual".
 		 * Class-devices with a non class-device as parent, live
@@ -719,7 +692,6 @@
 {
 	cleanup_glue_dir(dev, dev->kobj.parent);
 }
-#endif
 
 static void setup_parent(struct device *dev, struct device *parent)
 {
@@ -742,70 +714,29 @@
 	if (error)
 		goto out;
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-	/* stacked class devices need a symlink in the class directory */
-	if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
-	    device_is_not_partition(dev)) {
-		error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
-					  &dev->kobj, dev_name(dev));
-		if (error)
-			goto out_subsys;
-	}
-
-	if (dev->parent && device_is_not_partition(dev)) {
-		struct device *parent = dev->parent;
-		char *class_name;
-
-		/*
-		 * stacked class devices have the 'device' link
-		 * pointing to the bus device instead of the parent
-		 */
-		while (parent->class && !parent->bus && parent->parent)
-			parent = parent->parent;
-
-		error = sysfs_create_link(&dev->kobj,
-					  &parent->kobj,
-					  "device");
-		if (error)
-			goto out_busid;
-
-		class_name = make_class_name(dev->class->name,
-						&dev->kobj);
-		if (class_name)
-			error = sysfs_create_link(&dev->parent->kobj,
-						&dev->kobj, class_name);
-		kfree(class_name);
-		if (error)
-			goto out_device;
-	}
-	return 0;
-
-out_device:
-	if (dev->parent && device_is_not_partition(dev))
-		sysfs_remove_link(&dev->kobj, "device");
-out_busid:
-	if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
-	    device_is_not_partition(dev))
-		sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj,
-				  dev_name(dev));
-#else
-	/* link in the class directory pointing to the device */
-	error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
-				  &dev->kobj, dev_name(dev));
-	if (error)
-		goto out_subsys;
-
 	if (dev->parent && device_is_not_partition(dev)) {
 		error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
 					  "device");
 		if (error)
-			goto out_busid;
+			goto out_subsys;
 	}
+
+#ifdef CONFIG_BLOCK
+	/* /sys/block has directories and does not need symlinks */
+	if (sysfs_deprecated && dev->class == &block_class)
+		return 0;
+#endif
+
+	/* link in the class directory pointing to the device */
+	error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
+				  &dev->kobj, dev_name(dev));
+	if (error)
+		goto out_device;
+
 	return 0;
 
-out_busid:
-	sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
-#endif
+out_device:
+	sysfs_remove_link(&dev->kobj, "device");
 
 out_subsys:
 	sysfs_remove_link(&dev->kobj, "subsystem");
@@ -818,30 +749,14 @@
 	if (!dev->class)
 		return;
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-	if (dev->parent && device_is_not_partition(dev)) {
-		char *class_name;
-
-		class_name = make_class_name(dev->class->name, &dev->kobj);
-		if (class_name) {
-			sysfs_remove_link(&dev->parent->kobj, class_name);
-			kfree(class_name);
-		}
-		sysfs_remove_link(&dev->kobj, "device");
-	}
-
-	if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
-	    device_is_not_partition(dev))
-		sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj,
-				  dev_name(dev));
-#else
 	if (dev->parent && device_is_not_partition(dev))
 		sysfs_remove_link(&dev->kobj, "device");
-
-	sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
-#endif
-
 	sysfs_remove_link(&dev->kobj, "subsystem");
+#ifdef CONFIG_BLOCK
+	if (sysfs_deprecated && dev->class == &block_class)
+		return;
+#endif
+	sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
 }
 
 /**
@@ -1613,41 +1528,23 @@
 	pr_debug("device: '%s': %s: renaming to '%s'\n", dev_name(dev),
 		 __func__, new_name);
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-	if ((dev->class) && (dev->parent))
-		old_class_name = make_class_name(dev->class->name, &dev->kobj);
-#endif
-
 	old_device_name = kstrdup(dev_name(dev), GFP_KERNEL);
 	if (!old_device_name) {
 		error = -ENOMEM;
 		goto out;
 	}
 
-#ifndef CONFIG_SYSFS_DEPRECATED
 	if (dev->class) {
 		error = sysfs_rename_link(&dev->class->p->class_subsys.kobj,
 			&dev->kobj, old_device_name, new_name);
 		if (error)
 			goto out;
 	}
-#endif
+
 	error = kobject_rename(&dev->kobj, new_name);
 	if (error)
 		goto out;
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-	if (old_class_name) {
-		new_class_name = make_class_name(dev->class->name, &dev->kobj);
-		if (new_class_name) {
-			error = sysfs_rename_link(&dev->parent->kobj,
-						  &dev->kobj,
-						  old_class_name,
-						  new_class_name);
-		}
-	}
-#endif
-
 out:
 	put_device(dev);
 
@@ -1664,40 +1561,13 @@
 				   struct device *new_parent)
 {
 	int error = 0;
-#ifdef CONFIG_SYSFS_DEPRECATED
-	char *class_name;
 
-	class_name = make_class_name(dev->class->name, &dev->kobj);
-	if (!class_name) {
-		error = -ENOMEM;
-		goto out;
-	}
-	if (old_parent) {
-		sysfs_remove_link(&dev->kobj, "device");
-		sysfs_remove_link(&old_parent->kobj, class_name);
-	}
-	if (new_parent) {
-		error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
-					  "device");
-		if (error)
-			goto out;
-		error = sysfs_create_link(&new_parent->kobj, &dev->kobj,
-					  class_name);
-		if (error)
-			sysfs_remove_link(&dev->kobj, "device");
-	} else
-		error = 0;
-out:
-	kfree(class_name);
-	return error;
-#else
 	if (old_parent)
 		sysfs_remove_link(&dev->kobj, "device");
 	if (new_parent)
 		error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
 					  "device");
 	return error;
-#endif
 }
 
 /**
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 933442f..cafeaaf 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -27,6 +27,8 @@
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(mem_sysfs_mutex);
+
 #define MEMORY_CLASS_NAME	"memory"
 
 static struct sysdev_class memory_sysdev_class = {
@@ -435,6 +437,45 @@
 	return 0;
 }
 
+struct memory_block *find_memory_block_hinted(struct mem_section *section,
+					      struct memory_block *hint)
+{
+	struct kobject *kobj;
+	struct sys_device *sysdev;
+	struct memory_block *mem;
+	char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
+
+	kobj = hint ? &hint->sysdev.kobj : NULL;
+
+	/*
+	 * 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));
+
+	kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
+	if (!kobj)
+		return NULL;
+
+	sysdev = container_of(kobj, struct sys_device, kobj);
+	mem = container_of(sysdev, struct memory_block, sysdev);
+
+	return mem;
+}
+
+/*
+ * For now, we have a linear search to go find the appropriate
+ * memory_block corresponding to a particular phys_index. If
+ * this gets to be a real problem, we can always use a radix
+ * tree or something here.
+ *
+ * This could be made generic for all sysdev classes.
+ */
+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)
 {
@@ -445,8 +486,11 @@
 	if (!mem)
 		return -ENOMEM;
 
+	mutex_lock(&mem_sysfs_mutex);
+
 	mem->phys_index = __section_nr(section);
 	mem->state = state;
+	mem->section_count++;
 	mutex_init(&mem->state_mutex);
 	start_pfn = section_nr_to_pfn(mem->phys_index);
 	mem->phys_device = arch_get_memory_phys_device(start_pfn);
@@ -465,53 +509,29 @@
 			ret = register_mem_sect_under_node(mem, nid);
 	}
 
+	mutex_unlock(&mem_sysfs_mutex);
 	return ret;
 }
 
-/*
- * For now, we have a linear search to go find the appropriate
- * memory_block corresponding to a particular phys_index. If
- * this gets to be a real problem, we can always use a radix
- * tree or something here.
- *
- * This could be made generic for all sysdev classes.
- */
-struct memory_block *find_memory_block(struct mem_section *section)
-{
-	struct kobject *kobj;
-	struct sys_device *sysdev;
-	struct memory_block *mem;
-	char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
-
-	/*
-	 * 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));
-
-	kobj = kset_find_obj(&memory_sysdev_class.kset, name);
-	if (!kobj)
-		return NULL;
-
-	sysdev = container_of(kobj, struct sys_device, kobj);
-	mem = container_of(sysdev, struct memory_block, sysdev);
-
-	return mem;
-}
-
 int remove_memory_block(unsigned long node_id, struct mem_section *section,
 		int phys_device)
 {
 	struct memory_block *mem;
 
+	mutex_lock(&mem_sysfs_mutex);
 	mem = find_memory_block(section);
-	unregister_mem_sect_under_nodes(mem);
-	mem_remove_simple_file(mem, 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);
 
+	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, state);
+		mem_remove_simple_file(mem, phys_device);
+		mem_remove_simple_file(mem, removable);
+		unregister_memory(mem, section);
+	}
+
+	mutex_unlock(&mem_sysfs_mutex);
 	return 0;
 }
 
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 2872e86..ee53558 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -409,25 +409,27 @@
 	unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
 	unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages;
 	unsigned long pfn;
+	struct memory_block *mem_blk = NULL;
 	int err = 0;
 
 	for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
 		unsigned long section_nr = pfn_to_section_nr(pfn);
 		struct mem_section *mem_sect;
-		struct memory_block *mem_blk;
 		int ret;
 
 		if (!present_section_nr(section_nr))
 			continue;
 		mem_sect = __nr_to_section(section_nr);
-		mem_blk = find_memory_block(mem_sect);
+		mem_blk = find_memory_block_hinted(mem_sect, mem_blk);
 		ret = register_mem_sect_under_node(mem_blk, nid);
 		if (!err)
 			err = ret;
 
 		/* discard ref obtained in find_memory_block() */
-		kobject_put(&mem_blk->sysdev.kobj);
 	}
+
+	if (mem_blk)
+		kobject_put(&mem_blk->sysdev.kobj);
 	return err;
 }
 
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index c6c933f..3966e62 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -192,6 +192,9 @@
 {
 	struct resource *r;
 
+	if (!res)
+		return 0;
+
 	r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL);
 	if (r) {
 		pdev->resource = r;
@@ -215,8 +218,12 @@
 int platform_device_add_data(struct platform_device *pdev, const void *data,
 			     size_t size)
 {
-	void *d = kmemdup(data, size, GFP_KERNEL);
+	void *d;
 
+	if (!data)
+		return 0;
+
+	d = kmemdup(data, size, GFP_KERNEL);
 	if (d) {
 		pdev->dev.platform_data = d;
 		return 0;
@@ -373,17 +380,13 @@
 
 	pdev->dev.parent = parent;
 
-	if (res) {
-		ret = platform_device_add_resources(pdev, res, num);
-		if (ret)
-			goto err;
-	}
+	ret = platform_device_add_resources(pdev, res, num);
+	if (ret)
+		goto err;
 
-	if (data) {
-		ret = platform_device_add_data(pdev, data, size);
-		if (ret)
-			goto err;
-	}
+	ret = platform_device_add_data(pdev, data, size);
+	if (ret)
+		goto err;
 
 	ret = platform_device_add(pdev);
 	if (ret) {
@@ -488,12 +491,12 @@
 	 * if the probe was successful, and make sure any forced probes of
 	 * new devices fail.
 	 */
-	spin_lock(&platform_bus_type.p->klist_drivers.k_lock);
+	spin_lock(&drv->driver.bus->p->klist_drivers.k_lock);
 	drv->probe = NULL;
 	if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
 		retval = -ENODEV;
 	drv->driver.probe = platform_drv_probe_fail;
-	spin_unlock(&platform_bus_type.p->klist_drivers.k_lock);
+	spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock);
 
 	if (code != retval)
 		platform_driver_unregister(drv);
@@ -530,17 +533,13 @@
 		goto err_out;
 	}
 
-	if (res) {
-		error = platform_device_add_resources(pdev, res, n_res);
-		if (error)
-			goto err_pdev_put;
-	}
+	error = platform_device_add_resources(pdev, res, n_res);
+	if (error)
+		goto err_pdev_put;
 
-	if (data) {
-		error = platform_device_add_data(pdev, data, size);
-		if (error)
-			goto err_pdev_put;
-	}
+	error = platform_device_add_data(pdev, data, size);
+	if (error)
+		goto err_pdev_put;
 
 	error = platform_device_add(pdev);
 	if (error)
@@ -976,6 +975,41 @@
 };
 EXPORT_SYMBOL_GPL(platform_bus_type);
 
+/**
+ * platform_bus_get_pm_ops() - return pointer to busses dev_pm_ops
+ *
+ * This function can be used by platform code to get the current
+ * set of dev_pm_ops functions used by the platform_bus_type.
+ */
+const struct dev_pm_ops * __init platform_bus_get_pm_ops(void)
+{
+	return platform_bus_type.pm;
+}
+
+/**
+ * platform_bus_set_pm_ops() - update dev_pm_ops for the platform_bus_type
+ *
+ * @pm: pointer to new dev_pm_ops struct to be used for platform_bus_type
+ *
+ * Platform code can override the dev_pm_ops methods of
+ * platform_bus_type by using this function.  It is expected that
+ * platform code will first do a platform_bus_get_pm_ops(), then
+ * kmemdup it, then customize selected methods and pass a pointer to
+ * the new struct dev_pm_ops to this function.
+ *
+ * Since platform-specific code is customizing methods for *all*
+ * devices (not just platform-specific devices) it is expected that
+ * any custom overrides of these functions will keep existing behavior
+ * and simply extend it.  For example, any customization of the
+ * runtime PM methods should continue to call the pm_generic_*
+ * functions as the default ones do in addition to the
+ * platform-specific behavior.
+ */
+void __init platform_bus_set_pm_ops(const struct dev_pm_ops *pm)
+{
+	platform_bus_type.pm = pm;
+}
+
 int __init platform_bus_init(void)
 {
 	int error;
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index cbccf9a..abe46ed 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -3,6 +3,7 @@
 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
 
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 ccflags-$(CONFIG_PM_VERBOSE)   += -DDEBUG
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c
index 4b29d49..81f2c84 100644
--- a/drivers/base/power/generic_ops.c
+++ b/drivers/base/power/generic_ops.c
@@ -46,7 +46,7 @@
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 	int ret;
 
-	ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : -EINVAL;
+	ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : 0;
 
 	return ret;
 }
@@ -65,7 +65,7 @@
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 	int ret;
 
-	ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : -EINVAL;
+	ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : 0;
 
 	return ret;
 }
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 276d5a7..31b5266 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -51,6 +51,8 @@
  */
 static bool transition_started;
 
+static int async_error;
+
 /**
  * device_pm_init - Initialize the PM-related part of a device object.
  * @dev: Device object being initialized.
@@ -60,7 +62,8 @@
 	dev->power.status = DPM_ON;
 	init_completion(&dev->power.completion);
 	complete_all(&dev->power.completion);
-	dev->power.wakeup_count = 0;
+	dev->power.wakeup = NULL;
+	spin_lock_init(&dev->power.lock);
 	pm_runtime_init(dev);
 }
 
@@ -120,6 +123,7 @@
 	mutex_lock(&dpm_list_mtx);
 	list_del_init(&dev->power.entry);
 	mutex_unlock(&dpm_list_mtx);
+	device_wakeup_disable(dev);
 	pm_runtime_remove(dev);
 }
 
@@ -407,7 +411,7 @@
 static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
 {
 	ktime_t calltime;
-	s64 usecs64;
+	u64 usecs64;
 	int usecs;
 
 	calltime = ktime_get();
@@ -600,6 +604,7 @@
 	INIT_LIST_HEAD(&list);
 	mutex_lock(&dpm_list_mtx);
 	pm_transition = state;
+	async_error = 0;
 
 	list_for_each_entry(dev, &dpm_list, power.entry) {
 		if (dev->power.status < DPM_OFF)
@@ -829,8 +834,6 @@
 	return error;
 }
 
-static int async_error;
-
 /**
  * device_suspend - Execute "suspend" callbacks for given device.
  * @dev: Device to handle.
@@ -885,6 +888,9 @@
 	device_unlock(dev);
 	complete_all(&dev->power.completion);
 
+	if (error)
+		async_error = error;
+
 	return error;
 }
 
@@ -894,10 +900,8 @@
 	int error;
 
 	error = __device_suspend(dev, pm_transition, true);
-	if (error) {
+	if (error)
 		pm_dev_err(dev, pm_transition, " async", error);
-		async_error = error;
-	}
 
 	put_device(dev);
 }
@@ -1085,8 +1089,9 @@
  * @dev: Device to wait for.
  * @subordinate: Device that needs to wait for @dev.
  */
-void device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
+int device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
 {
 	dpm_wait(dev, subordinate->power.async_suspend);
+	return async_error;
 }
 EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
new file mode 100644
index 0000000..2bb9b4c
--- /dev/null
+++ b/drivers/base/power/opp.c
@@ -0,0 +1,628 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ *	Nishanth Menon
+ *	Romit Dasgupta
+ *	Kevin Hilman
+ *
+ * This program is free software; you can redistribute it 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/err.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <linux/list.h>
+#include <linux/rculist.h>
+#include <linux/rcupdate.h>
+#include <linux/opp.h>
+
+/*
+ * Internal data structure organization with the OPP layer library is as
+ * follows:
+ * dev_opp_list (root)
+ *	|- device 1 (represents voltage domain 1)
+ *	|	|- opp 1 (availability, freq, voltage)
+ *	|	|- opp 2 ..
+ *	...	...
+ *	|	`- opp n ..
+ *	|- device 2 (represents the next voltage domain)
+ *	...
+ *	`- device m (represents mth voltage domain)
+ * device 1, 2.. are represented by dev_opp structure while each opp
+ * is represented by the opp structure.
+ */
+
+/**
+ * struct opp - Generic OPP description structure
+ * @node:	opp list node. The nodes are maintained throughout the lifetime
+ *		of boot. It is expected only an optimal set of OPPs are
+ *		added to the library by the SoC framework.
+ *		RCU usage: opp list is traversed with RCU locks. node
+ *		modification is possible realtime, hence the modifications
+ *		are protected by the dev_opp_list_lock for integrity.
+ *		IMPORTANT: the opp nodes should be maintained in increasing
+ *		order.
+ * @available:	true/false - marks if this OPP as available or not
+ * @rate:	Frequency in hertz
+ * @u_volt:	Nominal voltage in microvolts corresponding to this OPP
+ * @dev_opp:	points back to the device_opp struct this opp belongs to
+ *
+ * This structure stores the OPP information for a given device.
+ */
+struct opp {
+	struct list_head node;
+
+	bool available;
+	unsigned long rate;
+	unsigned long u_volt;
+
+	struct device_opp *dev_opp;
+};
+
+/**
+ * struct device_opp - Device opp structure
+ * @node:	list node - contains the devices with OPPs that
+ *		have been registered. Nodes once added are not modified in this
+ *		list.
+ *		RCU usage: nodes are not modified in the list of device_opp,
+ *		however addition is possible and is secured by dev_opp_list_lock
+ * @dev:	device pointer
+ * @opp_list:	list of opps
+ *
+ * This is an internal data structure maintaining the link to opps attached to
+ * a device. This structure is not meant to be shared to users as it is
+ * meant for book keeping and private to OPP library
+ */
+struct device_opp {
+	struct list_head node;
+
+	struct device *dev;
+	struct list_head opp_list;
+};
+
+/*
+ * The root of the list of all devices. All device_opp structures branch off
+ * from here, with each device_opp containing the list of opp it supports in
+ * various states of availability.
+ */
+static LIST_HEAD(dev_opp_list);
+/* Lock to allow exclusive modification to the device and opp lists */
+static DEFINE_MUTEX(dev_opp_list_lock);
+
+/**
+ * find_device_opp() - find device_opp struct using device pointer
+ * @dev:	device pointer used to lookup device OPPs
+ *
+ * Search list of device OPPs for one containing matching device. Does a RCU
+ * reader operation to grab the pointer needed.
+ *
+ * Returns pointer to 'struct device_opp' if found, otherwise -ENODEV or
+ * -EINVAL based on type of error.
+ *
+ * Locking: This function must be called under rcu_read_lock(). device_opp
+ * is a RCU protected pointer. This means that device_opp is valid as long
+ * as we are under RCU lock.
+ */
+static struct device_opp *find_device_opp(struct device *dev)
+{
+	struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
+
+	if (unlikely(IS_ERR_OR_NULL(dev))) {
+		pr_err("%s: Invalid parameters\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) {
+		if (tmp_dev_opp->dev == dev) {
+			dev_opp = tmp_dev_opp;
+			break;
+		}
+	}
+
+	return dev_opp;
+}
+
+/**
+ * opp_get_voltage() - Gets the voltage corresponding to an available opp
+ * @opp:	opp for which voltage has to be returned for
+ *
+ * Return voltage in micro volt corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_voltage(struct opp *opp)
+{
+	struct opp *tmp_opp;
+	unsigned long v = 0;
+
+	tmp_opp = rcu_dereference(opp);
+	if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+		pr_err("%s: Invalid parameters\n", __func__);
+	else
+		v = tmp_opp->u_volt;
+
+	return v;
+}
+
+/**
+ * opp_get_freq() - Gets the frequency corresponding to an available opp
+ * @opp:	opp for which frequency has to be returned for
+ *
+ * Return frequency in hertz corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_freq(struct opp *opp)
+{
+	struct opp *tmp_opp;
+	unsigned long f = 0;
+
+	tmp_opp = rcu_dereference(opp);
+	if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+		pr_err("%s: Invalid parameters\n", __func__);
+	else
+		f = tmp_opp->rate;
+
+	return f;
+}
+
+/**
+ * opp_get_opp_count() - Get number of opps available in the opp list
+ * @dev:	device for which we do this operation
+ *
+ * This function returns the number of available opps if there are any,
+ * else returns 0 if none or the corresponding error value.
+ *
+ * Locking: This function must be called under rcu_read_lock(). This function
+ * internally references two RCU protected structures: device_opp and opp which
+ * are safe as long as we are under a common RCU locked section.
+ */
+int opp_get_opp_count(struct device *dev)
+{
+	struct device_opp *dev_opp;
+	struct opp *temp_opp;
+	int count = 0;
+
+	dev_opp = find_device_opp(dev);
+	if (IS_ERR(dev_opp)) {
+		int r = PTR_ERR(dev_opp);
+		dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r);
+		return r;
+	}
+
+	list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+		if (temp_opp->available)
+			count++;
+	}
+
+	return count;
+}
+
+/**
+ * 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
+ *
+ * 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
+ * using IS_ERR.
+ *
+ * Note: available is a modifier for the search. if available=true, then the
+ * match is for exact matching frequency and is available in the stored OPP
+ * table. if false, the match is for exact frequency which is not available.
+ *
+ * This provides a mechanism to enable an opp which is not available currently
+ * or the opposite as well.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
+				bool available)
+{
+	struct device_opp *dev_opp;
+	struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+	dev_opp = find_device_opp(dev);
+	if (IS_ERR(dev_opp)) {
+		int r = PTR_ERR(dev_opp);
+		dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r);
+		return ERR_PTR(r);
+	}
+
+	list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+		if (temp_opp->available == available &&
+				temp_opp->rate == freq) {
+			opp = temp_opp;
+			break;
+		}
+	}
+
+	return opp;
+}
+
+/**
+ * opp_find_freq_ceil() - Search for an rounded ceil freq
+ * @dev:	device for which we do this operation
+ * @freq:	Start frequency
+ *
+ * Search for the matching ceil *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
+{
+	struct device_opp *dev_opp;
+	struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+	if (!dev || !freq) {
+		dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
+		return ERR_PTR(-EINVAL);
+	}
+
+	dev_opp = find_device_opp(dev);
+	if (IS_ERR(dev_opp))
+		return opp;
+
+	list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+		if (temp_opp->available && temp_opp->rate >= *freq) {
+			opp = temp_opp;
+			*freq = opp->rate;
+			break;
+		}
+	}
+
+	return opp;
+}
+
+/**
+ * opp_find_freq_floor() - Search for a rounded floor freq
+ * @dev:	device for which we do this operation
+ * @freq:	Start frequency
+ *
+ * Search for the matching floor *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
+{
+	struct device_opp *dev_opp;
+	struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+	if (!dev || !freq) {
+		dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
+		return ERR_PTR(-EINVAL);
+	}
+
+	dev_opp = find_device_opp(dev);
+	if (IS_ERR(dev_opp))
+		return opp;
+
+	list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+		if (temp_opp->available) {
+			/* go to the next node, before choosing prev */
+			if (temp_opp->rate > *freq)
+				break;
+			else
+				opp = temp_opp;
+		}
+	}
+	if (!IS_ERR(opp))
+		*freq = opp->rate;
+
+	return opp;
+}
+
+/**
+ * opp_add()  - Add an OPP table from a table definitions
+ * @dev:	device for which we do this operation
+ * @freq:	Frequency in Hz for this OPP
+ * @u_volt:	Voltage in uVolts for this OPP
+ *
+ * This function adds an opp definition to the opp list and returns status.
+ * The opp is made available by default and it can be controlled using
+ * opp_enable/disable functions.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
+{
+	struct device_opp *dev_opp = NULL;
+	struct opp *opp, *new_opp;
+	struct list_head *head;
+
+	/* allocate new OPP node */
+	new_opp = kzalloc(sizeof(struct opp), GFP_KERNEL);
+	if (!new_opp) {
+		dev_warn(dev, "%s: Unable to create new OPP node\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	/* Check for existing list for 'dev' */
+	dev_opp = find_device_opp(dev);
+	if (IS_ERR(dev_opp)) {
+		/*
+		 * Allocate a new device OPP table. In the infrequent case
+		 * where a new device is needed to be added, we pay this
+		 * penalty.
+		 */
+		dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
+		if (!dev_opp) {
+			mutex_unlock(&dev_opp_list_lock);
+			kfree(new_opp);
+			dev_warn(dev,
+				"%s: Unable to create device OPP structure\n",
+				__func__);
+			return -ENOMEM;
+		}
+
+		dev_opp->dev = dev;
+		INIT_LIST_HEAD(&dev_opp->opp_list);
+
+		/* Secure the device list modification */
+		list_add_rcu(&dev_opp->node, &dev_opp_list);
+	}
+
+	/* populate the opp table */
+	new_opp->dev_opp = dev_opp;
+	new_opp->rate = freq;
+	new_opp->u_volt = u_volt;
+	new_opp->available = true;
+
+	/* Insert new OPP in order of increasing frequency */
+	head = &dev_opp->opp_list;
+	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
+		if (new_opp->rate < opp->rate)
+			break;
+		else
+			head = &opp->node;
+	}
+
+	list_add_rcu(&new_opp->node, head);
+	mutex_unlock(&dev_opp_list_lock);
+
+	return 0;
+}
+
+/**
+ * opp_set_availability() - helper to set the availability of an opp
+ * @dev:		device for which we do this operation
+ * @freq:		OPP frequency to modify availability
+ * @availability_req:	availability status requested for this opp
+ *
+ * Set the availability of an OPP with an RCU operation, opp_{enable,disable}
+ * share a common logic which is isolated here.
+ *
+ * Returns -EINVAL for bad pointers, -ENOMEM if no memory available for the
+ * copy operation, returns 0 if no modifcation was done OR modification was
+ * successful.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks to
+ * keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+static int opp_set_availability(struct device *dev, unsigned long freq,
+		bool availability_req)
+{
+	struct device_opp *tmp_dev_opp, *dev_opp = NULL;
+	struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+	int r = 0;
+
+	/* keep the node allocated */
+	new_opp = kmalloc(sizeof(struct opp), GFP_KERNEL);
+	if (!new_opp) {
+		dev_warn(dev, "%s: Unable to create OPP\n", __func__);
+		return -ENOMEM;
+	}
+
+	mutex_lock(&dev_opp_list_lock);
+
+	/* Find the device_opp */
+	list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) {
+		if (dev == tmp_dev_opp->dev) {
+			dev_opp = tmp_dev_opp;
+			break;
+		}
+	}
+	if (IS_ERR(dev_opp)) {
+		r = PTR_ERR(dev_opp);
+		dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
+		goto unlock;
+	}
+
+	/* Do we have the frequency? */
+	list_for_each_entry(tmp_opp, &dev_opp->opp_list, node) {
+		if (tmp_opp->rate == freq) {
+			opp = tmp_opp;
+			break;
+		}
+	}
+	if (IS_ERR(opp)) {
+		r = PTR_ERR(opp);
+		goto unlock;
+	}
+
+	/* Is update really needed? */
+	if (opp->available == availability_req)
+		goto unlock;
+	/* copy the old data over */
+	*new_opp = *opp;
+
+	/* plug in new node */
+	new_opp->available = availability_req;
+
+	list_replace_rcu(&opp->node, &new_opp->node);
+	mutex_unlock(&dev_opp_list_lock);
+	synchronize_rcu();
+
+	/* clean up old opp */
+	new_opp = opp;
+	goto out;
+
+unlock:
+	mutex_unlock(&dev_opp_list_lock);
+out:
+	kfree(new_opp);
+	return r;
+}
+
+/**
+ * opp_enable() - Enable a specific OPP
+ * @dev:	device for which we do this operation
+ * @freq:	OPP frequency to enable
+ *
+ * Enables a provided opp. If the operation is valid, this returns 0, else the
+ * corresponding error value. It is meant to be used for users an OPP available
+ * after being temporarily made unavailable with opp_disable.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_enable(struct device *dev, unsigned long freq)
+{
+	return opp_set_availability(dev, freq, true);
+}
+
+/**
+ * opp_disable() - Disable a specific OPP
+ * @dev:	device for which we do this operation
+ * @freq:	OPP frequency to disable
+ *
+ * Disables a provided opp. If the operation is valid, this returns
+ * 0, else the corresponding error value. It is meant to be a temporary
+ * control by users to make this OPP not available until the circumstances are
+ * right to make it available again (with a call to opp_enable).
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_disable(struct device *dev, unsigned long freq)
+{
+	return opp_set_availability(dev, freq, false);
+}
+
+#ifdef CONFIG_CPU_FREQ
+/**
+ * opp_init_cpufreq_table() - create a cpufreq table for a device
+ * @dev:	device for which we do this operation
+ * @table:	Cpufreq table returned back to caller
+ *
+ * Generate a cpufreq table for a provided device- this assumes that the
+ * opp list is already initialized and ready for usage.
+ *
+ * This function allocates required memory for the cpufreq table. It is
+ * expected that the caller does the required maintenance such as freeing
+ * the table as required.
+ *
+ * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
+ * if no memory available for the operation (table is not populated), returns 0
+ * if successful and table is populated.
+ *
+ * WARNING: It is  important for the callers to ensure refreshing their copy of
+ * the table if any of the mentioned functions have been invoked in the interim.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * To simplify the logic, we pretend we are updater and hold relevant mutex here
+ * Callers should ensure that this function is *NOT* called under RCU protection
+ * or in contexts where mutex locking cannot be used.
+ */
+int opp_init_cpufreq_table(struct device *dev,
+			    struct cpufreq_frequency_table **table)
+{
+	struct device_opp *dev_opp;
+	struct opp *opp;
+	struct cpufreq_frequency_table *freq_table;
+	int i = 0;
+
+	/* Pretend as if I am an updater */
+	mutex_lock(&dev_opp_list_lock);
+
+	dev_opp = find_device_opp(dev);
+	if (IS_ERR(dev_opp)) {
+		int r = PTR_ERR(dev_opp);
+		mutex_unlock(&dev_opp_list_lock);
+		dev_err(dev, "%s: Device OPP not found (%d)\n", __func__, r);
+		return r;
+	}
+
+	freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) *
+			     (opp_get_opp_count(dev) + 1), GFP_KERNEL);
+	if (!freq_table) {
+		mutex_unlock(&dev_opp_list_lock);
+		dev_warn(dev, "%s: Unable to allocate frequency table\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	list_for_each_entry(opp, &dev_opp->opp_list, node) {
+		if (opp->available) {
+			freq_table[i].index = i;
+			freq_table[i].frequency = opp->rate / 1000;
+			i++;
+		}
+	}
+	mutex_unlock(&dev_opp_list_lock);
+
+	freq_table[i].index = i;
+	freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+	*table = &freq_table[0];
+
+	return 0;
+}
+#endif		/* CONFIG_CPU_FREQ */
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index c0bd03c..698dde7 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -34,6 +34,7 @@
 
 static inline void device_pm_init(struct device *dev)
 {
+	spin_lock_init(&dev->power.lock);
 	pm_runtime_init(dev);
 }
 
@@ -59,6 +60,7 @@
 
 extern int dpm_sysfs_add(struct device *);
 extern void dpm_sysfs_remove(struct device *);
+extern void rpm_sysfs_remove(struct device *);
 
 #else /* CONFIG_PM */
 
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index b78c401..1dd8676 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -2,127 +2,17 @@
  * drivers/base/power/runtime.c - Helper functions for device run-time PM
  *
  * Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ * Copyright (C) 2010 Alan Stern <stern@rowland.harvard.edu>
  *
  * This file is released under the GPLv2.
  */
 
 #include <linux/sched.h>
 #include <linux/pm_runtime.h>
-#include <linux/jiffies.h>
+#include "power.h"
 
-static int __pm_runtime_resume(struct device *dev, bool from_wq);
-static int __pm_request_idle(struct device *dev);
-static int __pm_request_resume(struct device *dev);
-
-/**
- * pm_runtime_deactivate_timer - Deactivate given device's suspend timer.
- * @dev: Device to handle.
- */
-static void pm_runtime_deactivate_timer(struct device *dev)
-{
-	if (dev->power.timer_expires > 0) {
-		del_timer(&dev->power.suspend_timer);
-		dev->power.timer_expires = 0;
-	}
-}
-
-/**
- * pm_runtime_cancel_pending - Deactivate suspend timer and cancel requests.
- * @dev: Device to handle.
- */
-static void pm_runtime_cancel_pending(struct device *dev)
-{
-	pm_runtime_deactivate_timer(dev);
-	/*
-	 * In case there's a request pending, make sure its work function will
-	 * return without doing anything.
-	 */
-	dev->power.request = RPM_REQ_NONE;
-}
-
-/**
- * __pm_runtime_idle - Notify device bus type if the device can be suspended.
- * @dev: Device to notify the bus type about.
- *
- * This function must be called under dev->power.lock with interrupts disabled.
- */
-static int __pm_runtime_idle(struct device *dev)
-	__releases(&dev->power.lock) __acquires(&dev->power.lock)
-{
-	int retval = 0;
-
-	if (dev->power.runtime_error)
-		retval = -EINVAL;
-	else if (dev->power.idle_notification)
-		retval = -EINPROGRESS;
-	else if (atomic_read(&dev->power.usage_count) > 0
-	    || dev->power.disable_depth > 0
-	    || dev->power.runtime_status != RPM_ACTIVE)
-		retval = -EAGAIN;
-	else if (!pm_children_suspended(dev))
-		retval = -EBUSY;
-	if (retval)
-		goto out;
-
-	if (dev->power.request_pending) {
-		/*
-		 * If an idle notification request is pending, cancel it.  Any
-		 * other pending request takes precedence over us.
-		 */
-		if (dev->power.request == RPM_REQ_IDLE) {
-			dev->power.request = RPM_REQ_NONE;
-		} else if (dev->power.request != RPM_REQ_NONE) {
-			retval = -EAGAIN;
-			goto out;
-		}
-	}
-
-	dev->power.idle_notification = true;
-
-	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) {
-		spin_unlock_irq(&dev->power.lock);
-
-		dev->bus->pm->runtime_idle(dev);
-
-		spin_lock_irq(&dev->power.lock);
-	} else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) {
-		spin_unlock_irq(&dev->power.lock);
-
-		dev->type->pm->runtime_idle(dev);
-
-		spin_lock_irq(&dev->power.lock);
-	} else if (dev->class && dev->class->pm
-	    && dev->class->pm->runtime_idle) {
-		spin_unlock_irq(&dev->power.lock);
-
-		dev->class->pm->runtime_idle(dev);
-
-		spin_lock_irq(&dev->power.lock);
-	}
-
-	dev->power.idle_notification = false;
-	wake_up_all(&dev->power.wait_queue);
-
- out:
-	return retval;
-}
-
-/**
- * pm_runtime_idle - Notify device bus type if the device can be suspended.
- * @dev: Device to notify the bus type about.
- */
-int pm_runtime_idle(struct device *dev)
-{
-	int retval;
-
-	spin_lock_irq(&dev->power.lock);
-	retval = __pm_runtime_idle(dev);
-	spin_unlock_irq(&dev->power.lock);
-
-	return retval;
-}
-EXPORT_SYMBOL_GPL(pm_runtime_idle);
-
+static int rpm_resume(struct device *dev, int rpmflags);
+static int rpm_suspend(struct device *dev, int rpmflags);
 
 /**
  * update_pm_runtime_accounting - Update the time accounting of power states
@@ -163,58 +53,284 @@
 }
 
 /**
- * __pm_runtime_suspend - Carry out run-time suspend of given device.
- * @dev: Device to suspend.
- * @from_wq: If set, the function has been called via pm_wq.
+ * pm_runtime_deactivate_timer - Deactivate given device's suspend timer.
+ * @dev: Device to handle.
+ */
+static void pm_runtime_deactivate_timer(struct device *dev)
+{
+	if (dev->power.timer_expires > 0) {
+		del_timer(&dev->power.suspend_timer);
+		dev->power.timer_expires = 0;
+	}
+}
+
+/**
+ * pm_runtime_cancel_pending - Deactivate suspend timer and cancel requests.
+ * @dev: Device to handle.
+ */
+static void pm_runtime_cancel_pending(struct device *dev)
+{
+	pm_runtime_deactivate_timer(dev);
+	/*
+	 * In case there's a request pending, make sure its work function will
+	 * return without doing anything.
+	 */
+	dev->power.request = RPM_REQ_NONE;
+}
+
+/*
+ * pm_runtime_autosuspend_expiration - Get a device's autosuspend-delay expiration time.
+ * @dev: Device to handle.
  *
- * Check if the device can be suspended and run the ->runtime_suspend() callback
- * provided by its bus type.  If another suspend has been started earlier, wait
- * for it to finish.  If an idle notification or suspend request is pending or
- * scheduled, cancel it.
+ * Compute the autosuspend-delay expiration time based on the device's
+ * power.last_busy time.  If the delay has already expired or is disabled
+ * (negative) or the power.use_autosuspend flag isn't set, return 0.
+ * Otherwise return the expiration time in jiffies (adjusted to be nonzero).
+ *
+ * This function may be called either with or without dev->power.lock held.
+ * Either way it can be racy, since power.last_busy may be updated at any time.
+ */
+unsigned long pm_runtime_autosuspend_expiration(struct device *dev)
+{
+	int autosuspend_delay;
+	long elapsed;
+	unsigned long last_busy;
+	unsigned long expires = 0;
+
+	if (!dev->power.use_autosuspend)
+		goto out;
+
+	autosuspend_delay = ACCESS_ONCE(dev->power.autosuspend_delay);
+	if (autosuspend_delay < 0)
+		goto out;
+
+	last_busy = ACCESS_ONCE(dev->power.last_busy);
+	elapsed = jiffies - last_busy;
+	if (elapsed < 0)
+		goto out;	/* jiffies has wrapped around. */
+
+	/*
+	 * If the autosuspend_delay is >= 1 second, align the timer by rounding
+	 * up to the nearest second.
+	 */
+	expires = last_busy + msecs_to_jiffies(autosuspend_delay);
+	if (autosuspend_delay >= 1000)
+		expires = round_jiffies(expires);
+	expires += !expires;
+	if (elapsed >= expires - last_busy)
+		expires = 0;	/* Already expired. */
+
+ out:
+	return expires;
+}
+EXPORT_SYMBOL_GPL(pm_runtime_autosuspend_expiration);
+
+/**
+ * rpm_check_suspend_allowed - Test whether a device may be suspended.
+ * @dev: Device to test.
+ */
+static int rpm_check_suspend_allowed(struct device *dev)
+{
+	int retval = 0;
+
+	if (dev->power.runtime_error)
+		retval = -EINVAL;
+	else if (atomic_read(&dev->power.usage_count) > 0
+	    || dev->power.disable_depth > 0)
+		retval = -EAGAIN;
+	else if (!pm_children_suspended(dev))
+		retval = -EBUSY;
+
+	/* Pending resume requests take precedence over suspends. */
+	else if ((dev->power.deferred_resume
+			&& dev->power.status == RPM_SUSPENDING)
+	    || (dev->power.request_pending
+			&& dev->power.request == RPM_REQ_RESUME))
+		retval = -EAGAIN;
+	else if (dev->power.runtime_status == RPM_SUSPENDED)
+		retval = 1;
+
+	return retval;
+}
+
+/**
+ * rpm_idle - Notify device bus type if the device can be suspended.
+ * @dev: Device to notify the bus type about.
+ * @rpmflags: Flag bits.
+ *
+ * Check if the device's run-time PM status allows it to be suspended.  If
+ * another idle notification has been started earlier, return immediately.  If
+ * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise
+ * run the ->runtime_idle() callback directly.
  *
  * This function must be called under dev->power.lock with interrupts disabled.
  */
-int __pm_runtime_suspend(struct device *dev, bool from_wq)
-	__releases(&dev->power.lock) __acquires(&dev->power.lock)
+static int rpm_idle(struct device *dev, int rpmflags)
 {
-	struct device *parent = NULL;
-	bool notify = false;
-	int retval = 0;
+	int (*callback)(struct device *);
+	int retval;
 
-	dev_dbg(dev, "__pm_runtime_suspend()%s!\n",
-		from_wq ? " from workqueue" : "");
+	retval = rpm_check_suspend_allowed(dev);
+	if (retval < 0)
+		;	/* Conditions are wrong. */
 
- repeat:
-	if (dev->power.runtime_error) {
-		retval = -EINVAL;
+	/* Idle notifications are allowed only in the RPM_ACTIVE state. */
+	else if (dev->power.runtime_status != RPM_ACTIVE)
+		retval = -EAGAIN;
+
+	/*
+	 * Any pending request other than an idle notification takes
+	 * precedence over us, except that the timer may be running.
+	 */
+	else if (dev->power.request_pending &&
+	    dev->power.request > RPM_REQ_IDLE)
+		retval = -EAGAIN;
+
+	/* Act as though RPM_NOWAIT is always set. */
+	else if (dev->power.idle_notification)
+		retval = -EINPROGRESS;
+	if (retval)
+		goto out;
+
+	/* Pending requests need to be canceled. */
+	dev->power.request = RPM_REQ_NONE;
+
+	if (dev->power.no_callbacks) {
+		/* Assume ->runtime_idle() callback would have suspended. */
+		retval = rpm_suspend(dev, rpmflags);
 		goto out;
 	}
 
-	/* Pending resume requests take precedence over us. */
-	if (dev->power.request_pending
-	    && dev->power.request == RPM_REQ_RESUME) {
-		retval = -EAGAIN;
+	/* Carry out an asynchronous or a synchronous idle notification. */
+	if (rpmflags & RPM_ASYNC) {
+		dev->power.request = RPM_REQ_IDLE;
+		if (!dev->power.request_pending) {
+			dev->power.request_pending = true;
+			queue_work(pm_wq, &dev->power.work);
+		}
 		goto out;
 	}
 
+	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)
+		callback = dev->type->pm->runtime_idle;
+	else if (dev->class && dev->class->pm)
+		callback = dev->class->pm->runtime_idle;
+	else
+		callback = NULL;
+
+	if (callback) {
+		spin_unlock_irq(&dev->power.lock);
+
+		callback(dev);
+
+		spin_lock_irq(&dev->power.lock);
+	}
+
+	dev->power.idle_notification = false;
+	wake_up_all(&dev->power.wait_queue);
+
+ out:
+	return retval;
+}
+
+/**
+ * rpm_callback - Run a given runtime PM callback for a given device.
+ * @cb: Runtime PM callback to run.
+ * @dev: Device to run the callback for.
+ */
+static int rpm_callback(int (*cb)(struct device *), struct device *dev)
+	__releases(&dev->power.lock) __acquires(&dev->power.lock)
+{
+	int retval;
+
+	if (!cb)
+		return -ENOSYS;
+
+	spin_unlock_irq(&dev->power.lock);
+
+	retval = cb(dev);
+
+	spin_lock_irq(&dev->power.lock);
+	dev->power.runtime_error = retval;
+
+	return retval;
+}
+
+/**
+ * rpm_suspend - Carry out run-time suspend of given device.
+ * @dev: Device to suspend.
+ * @rpmflags: Flag bits.
+ *
+ * Check if the device's run-time PM status allows it to be suspended.  If
+ * another suspend has been started earlier, either return immediately or wait
+ * for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC flags.  Cancel a
+ * pending idle notification.  If the RPM_ASYNC flag is set then queue a
+ * suspend request; otherwise run the ->runtime_suspend() callback directly.
+ * If a deferred resume was requested while the callback was running then carry
+ * it out; otherwise send an idle notification for the device (if the suspend
+ * failed) or for its parent (if the suspend succeeded).
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+static int rpm_suspend(struct device *dev, int rpmflags)
+	__releases(&dev->power.lock) __acquires(&dev->power.lock)
+{
+	int (*callback)(struct device *);
+	struct device *parent = NULL;
+	int retval;
+
+	dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+
+ repeat:
+	retval = rpm_check_suspend_allowed(dev);
+
+	if (retval < 0)
+		;	/* Conditions are wrong. */
+
+	/* Synchronous suspends are not allowed in the RPM_RESUMING state. */
+	else if (dev->power.runtime_status == RPM_RESUMING &&
+	    !(rpmflags & RPM_ASYNC))
+		retval = -EAGAIN;
+	if (retval)
+		goto out;
+
+	/* If the autosuspend_delay time hasn't expired yet, reschedule. */
+	if ((rpmflags & RPM_AUTO)
+	    && dev->power.runtime_status != RPM_SUSPENDING) {
+		unsigned long expires = pm_runtime_autosuspend_expiration(dev);
+
+		if (expires != 0) {
+			/* Pending requests need to be canceled. */
+			dev->power.request = RPM_REQ_NONE;
+
+			/*
+			 * Optimization: If the timer is already running and is
+			 * set to expire at or before the autosuspend delay,
+			 * avoid the overhead of resetting it.  Just let it
+			 * expire; pm_suspend_timer_fn() will take care of the
+			 * rest.
+			 */
+			if (!(dev->power.timer_expires && time_before_eq(
+			    dev->power.timer_expires, expires))) {
+				dev->power.timer_expires = expires;
+				mod_timer(&dev->power.suspend_timer, expires);
+			}
+			dev->power.timer_autosuspends = 1;
+			goto out;
+		}
+	}
+
 	/* Other scheduled or pending requests need to be canceled. */
 	pm_runtime_cancel_pending(dev);
 
-	if (dev->power.runtime_status == RPM_SUSPENDED)
-		retval = 1;
-	else if (dev->power.runtime_status == RPM_RESUMING
-	    || dev->power.disable_depth > 0
-	    || atomic_read(&dev->power.usage_count) > 0)
-		retval = -EAGAIN;
-	else if (!pm_children_suspended(dev))
-		retval = -EBUSY;
-	if (retval)
-		goto out;
-
 	if (dev->power.runtime_status == RPM_SUSPENDING) {
 		DEFINE_WAIT(wait);
 
-		if (from_wq) {
+		if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
 			retval = -EINPROGRESS;
 			goto out;
 		}
@@ -236,46 +352,42 @@
 		goto repeat;
 	}
 
-	__update_runtime_status(dev, RPM_SUSPENDING);
 	dev->power.deferred_resume = false;
+	if (dev->power.no_callbacks)
+		goto no_callback;	/* Assume success. */
 
-	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
-		spin_unlock_irq(&dev->power.lock);
-
-		retval = dev->bus->pm->runtime_suspend(dev);
-
-		spin_lock_irq(&dev->power.lock);
-		dev->power.runtime_error = retval;
-	} else if (dev->type && dev->type->pm
-	    && dev->type->pm->runtime_suspend) {
-		spin_unlock_irq(&dev->power.lock);
-
-		retval = dev->type->pm->runtime_suspend(dev);
-
-		spin_lock_irq(&dev->power.lock);
-		dev->power.runtime_error = retval;
-	} else if (dev->class && dev->class->pm
-	    && dev->class->pm->runtime_suspend) {
-		spin_unlock_irq(&dev->power.lock);
-
-		retval = dev->class->pm->runtime_suspend(dev);
-
-		spin_lock_irq(&dev->power.lock);
-		dev->power.runtime_error = retval;
-	} else {
-		retval = -ENOSYS;
+	/* Carry out an asynchronous or a synchronous suspend. */
+	if (rpmflags & RPM_ASYNC) {
+		dev->power.request = (rpmflags & RPM_AUTO) ?
+		    RPM_REQ_AUTOSUSPEND : RPM_REQ_SUSPEND;
+		if (!dev->power.request_pending) {
+			dev->power.request_pending = true;
+			queue_work(pm_wq, &dev->power.work);
+		}
+		goto out;
 	}
 
+	__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)
+		callback = dev->type->pm->runtime_suspend;
+	else if (dev->class && dev->class->pm)
+		callback = dev->class->pm->runtime_suspend;
+	else
+		callback = NULL;
+
+	retval = rpm_callback(callback, dev);
 	if (retval) {
 		__update_runtime_status(dev, RPM_ACTIVE);
-		if (retval == -EAGAIN || retval == -EBUSY) {
-			if (dev->power.timer_expires == 0)
-				notify = true;
+		dev->power.deferred_resume = 0;
+		if (retval == -EAGAIN || retval == -EBUSY)
 			dev->power.runtime_error = 0;
-		} else {
+		else
 			pm_runtime_cancel_pending(dev);
-		}
 	} else {
+ no_callback:
 		__update_runtime_status(dev, RPM_SUSPENDED);
 		pm_runtime_deactivate_timer(dev);
 
@@ -287,14 +399,11 @@
 	wake_up_all(&dev->power.wait_queue);
 
 	if (dev->power.deferred_resume) {
-		__pm_runtime_resume(dev, false);
+		rpm_resume(dev, 0);
 		retval = -EAGAIN;
 		goto out;
 	}
 
-	if (notify)
-		__pm_runtime_idle(dev);
-
 	if (parent && !parent->power.ignore_children) {
 		spin_unlock_irq(&dev->power.lock);
 
@@ -304,72 +413,69 @@
 	}
 
  out:
-	dev_dbg(dev, "__pm_runtime_suspend() returns %d!\n", retval);
+	dev_dbg(dev, "%s returns %d\n", __func__, retval);
 
 	return retval;
 }
 
 /**
- * pm_runtime_suspend - Carry out run-time suspend of given device.
- * @dev: Device to suspend.
- */
-int pm_runtime_suspend(struct device *dev)
-{
-	int retval;
-
-	spin_lock_irq(&dev->power.lock);
-	retval = __pm_runtime_suspend(dev, false);
-	spin_unlock_irq(&dev->power.lock);
-
-	return retval;
-}
-EXPORT_SYMBOL_GPL(pm_runtime_suspend);
-
-/**
- * __pm_runtime_resume - Carry out run-time resume of given device.
+ * rpm_resume - Carry out run-time resume of given device.
  * @dev: Device to resume.
- * @from_wq: If set, the function has been called via pm_wq.
+ * @rpmflags: Flag bits.
  *
- * Check if the device can be woken up and run the ->runtime_resume() callback
- * provided by its bus type.  If another resume has been started earlier, wait
- * for it to finish.  If there's a suspend running in parallel with this
- * function, wait for it to finish and resume the device.  Cancel any scheduled
- * or pending requests.
+ * Check if the device's run-time PM status allows it to be resumed.  Cancel
+ * any scheduled or pending requests.  If another resume has been started
+ * earlier, either return imediately or wait for it to finish, depending on the
+ * RPM_NOWAIT and RPM_ASYNC flags.  Similarly, if there's a suspend running in
+ * parallel with this function, either tell the other process to resume after
+ * suspending (deferred_resume) or wait for it to finish.  If the RPM_ASYNC
+ * flag is set then queue a resume request; otherwise run the
+ * ->runtime_resume() callback directly.  Queue an idle notification for the
+ * device if the resume succeeded.
  *
  * This function must be called under dev->power.lock with interrupts disabled.
  */
-int __pm_runtime_resume(struct device *dev, bool from_wq)
+static int rpm_resume(struct device *dev, int rpmflags)
 	__releases(&dev->power.lock) __acquires(&dev->power.lock)
 {
+	int (*callback)(struct device *);
 	struct device *parent = NULL;
 	int retval = 0;
 
-	dev_dbg(dev, "__pm_runtime_resume()%s!\n",
-		from_wq ? " from workqueue" : "");
+	dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
 
  repeat:
-	if (dev->power.runtime_error) {
+	if (dev->power.runtime_error)
 		retval = -EINVAL;
-		goto out;
-	}
-
-	pm_runtime_cancel_pending(dev);
-
-	if (dev->power.runtime_status == RPM_ACTIVE)
-		retval = 1;
 	else if (dev->power.disable_depth > 0)
 		retval = -EAGAIN;
 	if (retval)
 		goto out;
 
+	/*
+	 * Other scheduled or pending requests need to be canceled.  Small
+	 * optimization: If an autosuspend timer is running, leave it running
+	 * rather than cancelling it now only to restart it again in the near
+	 * future.
+	 */
+	dev->power.request = RPM_REQ_NONE;
+	if (!dev->power.timer_autosuspends)
+		pm_runtime_deactivate_timer(dev);
+
+	if (dev->power.runtime_status == RPM_ACTIVE) {
+		retval = 1;
+		goto out;
+	}
+
 	if (dev->power.runtime_status == RPM_RESUMING
 	    || dev->power.runtime_status == RPM_SUSPENDING) {
 		DEFINE_WAIT(wait);
 
-		if (from_wq) {
+		if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
 			if (dev->power.runtime_status == RPM_SUSPENDING)
 				dev->power.deferred_resume = true;
-			retval = -EINPROGRESS;
+			else
+				retval = -EINPROGRESS;
 			goto out;
 		}
 
@@ -391,6 +497,34 @@
 		goto repeat;
 	}
 
+	/*
+	 * See if we can skip waking up the parent.  This is safe only if
+	 * power.no_callbacks is set, because otherwise we don't know whether
+	 * the resume will actually succeed.
+	 */
+	if (dev->power.no_callbacks && !parent && dev->parent) {
+		spin_lock(&dev->parent->power.lock);
+		if (dev->parent->power.disable_depth > 0
+		    || dev->parent->power.ignore_children
+		    || dev->parent->power.runtime_status == RPM_ACTIVE) {
+			atomic_inc(&dev->parent->power.child_count);
+			spin_unlock(&dev->parent->power.lock);
+			goto no_callback;	/* Assume success. */
+		}
+		spin_unlock(&dev->parent->power.lock);
+	}
+
+	/* Carry out an asynchronous or a synchronous resume. */
+	if (rpmflags & RPM_ASYNC) {
+		dev->power.request = RPM_REQ_RESUME;
+		if (!dev->power.request_pending) {
+			dev->power.request_pending = true;
+			queue_work(pm_wq, &dev->power.work);
+		}
+		retval = 0;
+		goto out;
+	}
+
 	if (!parent && dev->parent) {
 		/*
 		 * Increment the parent's resume counter and resume it if
@@ -408,7 +542,7 @@
 		 */
 		if (!parent->power.disable_depth
 		    && !parent->power.ignore_children) {
-			__pm_runtime_resume(parent, false);
+			rpm_resume(parent, 0);
 			if (parent->power.runtime_status != RPM_ACTIVE)
 				retval = -EBUSY;
 		}
@@ -420,39 +554,26 @@
 		goto repeat;
 	}
 
+	if (dev->power.no_callbacks)
+		goto no_callback;	/* Assume success. */
+
 	__update_runtime_status(dev, RPM_RESUMING);
 
-	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) {
-		spin_unlock_irq(&dev->power.lock);
+	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)
+		callback = dev->type->pm->runtime_resume;
+	else if (dev->class && dev->class->pm)
+		callback = dev->class->pm->runtime_resume;
+	else
+		callback = NULL;
 
-		retval = dev->bus->pm->runtime_resume(dev);
-
-		spin_lock_irq(&dev->power.lock);
-		dev->power.runtime_error = retval;
-	} else if (dev->type && dev->type->pm
-	    && dev->type->pm->runtime_resume) {
-		spin_unlock_irq(&dev->power.lock);
-
-		retval = dev->type->pm->runtime_resume(dev);
-
-		spin_lock_irq(&dev->power.lock);
-		dev->power.runtime_error = retval;
-	} else if (dev->class && dev->class->pm
-	    && dev->class->pm->runtime_resume) {
-		spin_unlock_irq(&dev->power.lock);
-
-		retval = dev->class->pm->runtime_resume(dev);
-
-		spin_lock_irq(&dev->power.lock);
-		dev->power.runtime_error = retval;
-	} else {
-		retval = -ENOSYS;
-	}
-
+	retval = rpm_callback(callback, dev);
 	if (retval) {
 		__update_runtime_status(dev, RPM_SUSPENDED);
 		pm_runtime_cancel_pending(dev);
 	} else {
+ no_callback:
 		__update_runtime_status(dev, RPM_ACTIVE);
 		if (parent)
 			atomic_inc(&parent->power.child_count);
@@ -460,7 +581,7 @@
 	wake_up_all(&dev->power.wait_queue);
 
 	if (!retval)
-		__pm_request_idle(dev);
+		rpm_idle(dev, RPM_ASYNC);
 
  out:
 	if (parent) {
@@ -471,28 +592,12 @@
 		spin_lock_irq(&dev->power.lock);
 	}
 
-	dev_dbg(dev, "__pm_runtime_resume() returns %d!\n", retval);
+	dev_dbg(dev, "%s returns %d\n", __func__, retval);
 
 	return retval;
 }
 
 /**
- * pm_runtime_resume - Carry out run-time resume of given device.
- * @dev: Device to suspend.
- */
-int pm_runtime_resume(struct device *dev)
-{
-	int retval;
-
-	spin_lock_irq(&dev->power.lock);
-	retval = __pm_runtime_resume(dev, false);
-	spin_unlock_irq(&dev->power.lock);
-
-	return retval;
-}
-EXPORT_SYMBOL_GPL(pm_runtime_resume);
-
-/**
  * pm_runtime_work - Universal run-time PM work function.
  * @work: Work structure used for scheduling the execution of this function.
  *
@@ -517,13 +622,16 @@
 	case RPM_REQ_NONE:
 		break;
 	case RPM_REQ_IDLE:
-		__pm_runtime_idle(dev);
+		rpm_idle(dev, RPM_NOWAIT);
 		break;
 	case RPM_REQ_SUSPEND:
-		__pm_runtime_suspend(dev, true);
+		rpm_suspend(dev, RPM_NOWAIT);
+		break;
+	case RPM_REQ_AUTOSUSPEND:
+		rpm_suspend(dev, RPM_NOWAIT | RPM_AUTO);
 		break;
 	case RPM_REQ_RESUME:
-		__pm_runtime_resume(dev, true);
+		rpm_resume(dev, RPM_NOWAIT);
 		break;
 	}
 
@@ -532,117 +640,10 @@
 }
 
 /**
- * __pm_request_idle - Submit an idle notification request for given device.
- * @dev: Device to handle.
- *
- * Check if the device's run-time PM status is correct for suspending the device
- * and queue up a request to run __pm_runtime_idle() for it.
- *
- * This function must be called under dev->power.lock with interrupts disabled.
- */
-static int __pm_request_idle(struct device *dev)
-{
-	int retval = 0;
-
-	if (dev->power.runtime_error)
-		retval = -EINVAL;
-	else if (atomic_read(&dev->power.usage_count) > 0
-	    || dev->power.disable_depth > 0
-	    || dev->power.runtime_status == RPM_SUSPENDED
-	    || dev->power.runtime_status == RPM_SUSPENDING)
-		retval = -EAGAIN;
-	else if (!pm_children_suspended(dev))
-		retval = -EBUSY;
-	if (retval)
-		return retval;
-
-	if (dev->power.request_pending) {
-		/* Any requests other then RPM_REQ_IDLE take precedence. */
-		if (dev->power.request == RPM_REQ_NONE)
-			dev->power.request = RPM_REQ_IDLE;
-		else if (dev->power.request != RPM_REQ_IDLE)
-			retval = -EAGAIN;
-		return retval;
-	}
-
-	dev->power.request = RPM_REQ_IDLE;
-	dev->power.request_pending = true;
-	queue_work(pm_wq, &dev->power.work);
-
-	return retval;
-}
-
-/**
- * pm_request_idle - Submit an idle notification request for given device.
- * @dev: Device to handle.
- */
-int pm_request_idle(struct device *dev)
-{
-	unsigned long flags;
-	int retval;
-
-	spin_lock_irqsave(&dev->power.lock, flags);
-	retval = __pm_request_idle(dev);
-	spin_unlock_irqrestore(&dev->power.lock, flags);
-
-	return retval;
-}
-EXPORT_SYMBOL_GPL(pm_request_idle);
-
-/**
- * __pm_request_suspend - Submit a suspend request for given device.
- * @dev: Device to suspend.
- *
- * This function must be called under dev->power.lock with interrupts disabled.
- */
-static int __pm_request_suspend(struct device *dev)
-{
-	int retval = 0;
-
-	if (dev->power.runtime_error)
-		return -EINVAL;
-
-	if (dev->power.runtime_status == RPM_SUSPENDED)
-		retval = 1;
-	else if (atomic_read(&dev->power.usage_count) > 0
-	    || dev->power.disable_depth > 0)
-		retval = -EAGAIN;
-	else if (dev->power.runtime_status == RPM_SUSPENDING)
-		retval = -EINPROGRESS;
-	else if (!pm_children_suspended(dev))
-		retval = -EBUSY;
-	if (retval < 0)
-		return retval;
-
-	pm_runtime_deactivate_timer(dev);
-
-	if (dev->power.request_pending) {
-		/*
-		 * Pending resume requests take precedence over us, but we can
-		 * overtake any other pending request.
-		 */
-		if (dev->power.request == RPM_REQ_RESUME)
-			retval = -EAGAIN;
-		else if (dev->power.request != RPM_REQ_SUSPEND)
-			dev->power.request = retval ?
-						RPM_REQ_NONE : RPM_REQ_SUSPEND;
-		return retval;
-	} else if (retval) {
-		return retval;
-	}
-
-	dev->power.request = RPM_REQ_SUSPEND;
-	dev->power.request_pending = true;
-	queue_work(pm_wq, &dev->power.work);
-
-	return 0;
-}
-
-/**
  * pm_suspend_timer_fn - Timer function for pm_schedule_suspend().
  * @data: Device pointer passed by pm_schedule_suspend().
  *
- * Check if the time is right and execute __pm_request_suspend() in that case.
+ * Check if the time is right and queue a suspend request.
  */
 static void pm_suspend_timer_fn(unsigned long data)
 {
@@ -656,7 +657,8 @@
 	/* If 'expire' is after 'jiffies' we've been called too early. */
 	if (expires > 0 && !time_after(expires, jiffies)) {
 		dev->power.timer_expires = 0;
-		__pm_request_suspend(dev);
+		rpm_suspend(dev, dev->power.timer_autosuspends ?
+		    (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
 	}
 
 	spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -670,47 +672,25 @@
 int pm_schedule_suspend(struct device *dev, unsigned int delay)
 {
 	unsigned long flags;
-	int retval = 0;
+	int retval;
 
 	spin_lock_irqsave(&dev->power.lock, flags);
 
-	if (dev->power.runtime_error) {
-		retval = -EINVAL;
-		goto out;
-	}
-
 	if (!delay) {
-		retval = __pm_request_suspend(dev);
+		retval = rpm_suspend(dev, RPM_ASYNC);
 		goto out;
 	}
 
-	pm_runtime_deactivate_timer(dev);
-
-	if (dev->power.request_pending) {
-		/*
-		 * Pending resume requests take precedence over us, but any
-		 * other pending requests have to be canceled.
-		 */
-		if (dev->power.request == RPM_REQ_RESUME) {
-			retval = -EAGAIN;
-			goto out;
-		}
-		dev->power.request = RPM_REQ_NONE;
-	}
-
-	if (dev->power.runtime_status == RPM_SUSPENDED)
-		retval = 1;
-	else if (atomic_read(&dev->power.usage_count) > 0
-	    || dev->power.disable_depth > 0)
-		retval = -EAGAIN;
-	else if (!pm_children_suspended(dev))
-		retval = -EBUSY;
+	retval = rpm_check_suspend_allowed(dev);
 	if (retval)
 		goto out;
 
+	/* Other scheduled or pending requests need to be canceled. */
+	pm_runtime_cancel_pending(dev);
+
 	dev->power.timer_expires = jiffies + msecs_to_jiffies(delay);
-	if (!dev->power.timer_expires)
-		dev->power.timer_expires = 1;
+	dev->power.timer_expires += !dev->power.timer_expires;
+	dev->power.timer_autosuspends = 0;
 	mod_timer(&dev->power.suspend_timer, dev->power.timer_expires);
 
  out:
@@ -721,103 +701,88 @@
 EXPORT_SYMBOL_GPL(pm_schedule_suspend);
 
 /**
- * pm_request_resume - Submit a resume request for given device.
- * @dev: Device to resume.
+ * __pm_runtime_idle - Entry point for run-time idle operations.
+ * @dev: Device to send idle notification for.
+ * @rpmflags: Flag bits.
  *
- * This function must be called under dev->power.lock with interrupts disabled.
+ * If the RPM_GET_PUT flag is set, decrement the device's usage count and
+ * return immediately if it is larger than zero.  Then carry out an idle
+ * notification, either synchronous or asynchronous.
+ *
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
  */
-static int __pm_request_resume(struct device *dev)
-{
-	int retval = 0;
-
-	if (dev->power.runtime_error)
-		return -EINVAL;
-
-	if (dev->power.runtime_status == RPM_ACTIVE)
-		retval = 1;
-	else if (dev->power.runtime_status == RPM_RESUMING)
-		retval = -EINPROGRESS;
-	else if (dev->power.disable_depth > 0)
-		retval = -EAGAIN;
-	if (retval < 0)
-		return retval;
-
-	pm_runtime_deactivate_timer(dev);
-
-	if (dev->power.runtime_status == RPM_SUSPENDING) {
-		dev->power.deferred_resume = true;
-		return retval;
-	}
-	if (dev->power.request_pending) {
-		/* If non-resume request is pending, we can overtake it. */
-		dev->power.request = retval ? RPM_REQ_NONE : RPM_REQ_RESUME;
-		return retval;
-	}
-	if (retval)
-		return retval;
-
-	dev->power.request = RPM_REQ_RESUME;
-	dev->power.request_pending = true;
-	queue_work(pm_wq, &dev->power.work);
-
-	return retval;
-}
-
-/**
- * pm_request_resume - Submit a resume request for given device.
- * @dev: Device to resume.
- */
-int pm_request_resume(struct device *dev)
+int __pm_runtime_idle(struct device *dev, int rpmflags)
 {
 	unsigned long flags;
 	int retval;
 
+	if (rpmflags & RPM_GET_PUT) {
+		if (!atomic_dec_and_test(&dev->power.usage_count))
+			return 0;
+	}
+
 	spin_lock_irqsave(&dev->power.lock, flags);
-	retval = __pm_request_resume(dev);
+	retval = rpm_idle(dev, rpmflags);
 	spin_unlock_irqrestore(&dev->power.lock, flags);
 
 	return retval;
 }
-EXPORT_SYMBOL_GPL(pm_request_resume);
+EXPORT_SYMBOL_GPL(__pm_runtime_idle);
 
 /**
- * __pm_runtime_get - Reference count a device and wake it up, if necessary.
- * @dev: Device to handle.
- * @sync: If set and the device is suspended, resume it synchronously.
+ * __pm_runtime_suspend - Entry point for run-time put/suspend operations.
+ * @dev: Device to suspend.
+ * @rpmflags: Flag bits.
  *
- * Increment the usage count of the device and resume it or submit a resume
- * request for it, depending on the value of @sync.
+ * If the RPM_GET_PUT flag is set, decrement the device's usage count and
+ * return immediately if it is larger than zero.  Then carry out a suspend,
+ * either synchronous or asynchronous.
+ *
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
  */
-int __pm_runtime_get(struct device *dev, bool sync)
+int __pm_runtime_suspend(struct device *dev, int rpmflags)
 {
+	unsigned long flags;
 	int retval;
 
-	atomic_inc(&dev->power.usage_count);
-	retval = sync ? pm_runtime_resume(dev) : pm_request_resume(dev);
+	if (rpmflags & RPM_GET_PUT) {
+		if (!atomic_dec_and_test(&dev->power.usage_count))
+			return 0;
+	}
+
+	spin_lock_irqsave(&dev->power.lock, flags);
+	retval = rpm_suspend(dev, rpmflags);
+	spin_unlock_irqrestore(&dev->power.lock, flags);
 
 	return retval;
 }
-EXPORT_SYMBOL_GPL(__pm_runtime_get);
+EXPORT_SYMBOL_GPL(__pm_runtime_suspend);
 
 /**
- * __pm_runtime_put - Decrement the device's usage counter and notify its bus.
- * @dev: Device to handle.
- * @sync: If the device's bus type is to be notified, do that synchronously.
+ * __pm_runtime_resume - Entry point for run-time resume operations.
+ * @dev: Device to resume.
+ * @rpmflags: Flag bits.
  *
- * Decrement the usage count of the device and if it reaches zero, carry out a
- * synchronous idle notification or submit an idle notification request for it,
- * depending on the value of @sync.
+ * If the RPM_GET_PUT flag is set, increment the device's usage count.  Then
+ * carry out a resume, either synchronous or asynchronous.
+ *
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
  */
-int __pm_runtime_put(struct device *dev, bool sync)
+int __pm_runtime_resume(struct device *dev, int rpmflags)
 {
-	int retval = 0;
+	unsigned long flags;
+	int retval;
 
-	if (atomic_dec_and_test(&dev->power.usage_count))
-		retval = sync ? pm_runtime_idle(dev) : pm_request_idle(dev);
+	if (rpmflags & RPM_GET_PUT)
+		atomic_inc(&dev->power.usage_count);
+
+	spin_lock_irqsave(&dev->power.lock, flags);
+	retval = rpm_resume(dev, rpmflags);
+	spin_unlock_irqrestore(&dev->power.lock, flags);
 
 	return retval;
 }
-EXPORT_SYMBOL_GPL(__pm_runtime_put);
+EXPORT_SYMBOL_GPL(__pm_runtime_resume);
 
 /**
  * __pm_runtime_set_status - Set run-time PM status of a device.
@@ -968,7 +933,7 @@
 
 	if (dev->power.request_pending
 	    && dev->power.request == RPM_REQ_RESUME) {
-		__pm_runtime_resume(dev, false);
+		rpm_resume(dev, 0);
 		retval = 1;
 	}
 
@@ -1017,7 +982,7 @@
 		 */
 		pm_runtime_get_noresume(dev);
 
-		__pm_runtime_resume(dev, false);
+		rpm_resume(dev, 0);
 
 		pm_runtime_put_noidle(dev);
 	}
@@ -1065,7 +1030,7 @@
 
 	dev->power.runtime_auto = false;
 	atomic_inc(&dev->power.usage_count);
-	__pm_runtime_resume(dev, false);
+	rpm_resume(dev, 0);
 
  out:
 	spin_unlock_irq(&dev->power.lock);
@@ -1086,7 +1051,7 @@
 
 	dev->power.runtime_auto = true;
 	if (atomic_dec_and_test(&dev->power.usage_count))
-		__pm_runtime_idle(dev);
+		rpm_idle(dev, RPM_AUTO);
 
  out:
 	spin_unlock_irq(&dev->power.lock);
@@ -1094,13 +1059,110 @@
 EXPORT_SYMBOL_GPL(pm_runtime_allow);
 
 /**
+ * pm_runtime_no_callbacks - Ignore run-time PM callbacks for a device.
+ * @dev: Device to handle.
+ *
+ * Set the power.no_callbacks flag, which tells the PM core that this
+ * device is power-managed through its parent and has no run-time PM
+ * callbacks of its own.  The run-time sysfs attributes will be removed.
+ *
+ */
+void pm_runtime_no_callbacks(struct device *dev)
+{
+	spin_lock_irq(&dev->power.lock);
+	dev->power.no_callbacks = 1;
+	spin_unlock_irq(&dev->power.lock);
+	if (device_is_registered(dev))
+		rpm_sysfs_remove(dev);
+}
+EXPORT_SYMBOL_GPL(pm_runtime_no_callbacks);
+
+/**
+ * update_autosuspend - Handle a change to a device's autosuspend settings.
+ * @dev: Device to handle.
+ * @old_delay: The former autosuspend_delay value.
+ * @old_use: The former use_autosuspend value.
+ *
+ * Prevent runtime suspend if the new delay is negative and use_autosuspend is
+ * set; otherwise allow it.  Send an idle notification if suspends are allowed.
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+static void update_autosuspend(struct device *dev, int old_delay, int old_use)
+{
+	int delay = dev->power.autosuspend_delay;
+
+	/* Should runtime suspend be prevented now? */
+	if (dev->power.use_autosuspend && delay < 0) {
+
+		/* If it used to be allowed then prevent it. */
+		if (!old_use || old_delay >= 0) {
+			atomic_inc(&dev->power.usage_count);
+			rpm_resume(dev, 0);
+		}
+	}
+
+	/* Runtime suspend should be allowed now. */
+	else {
+
+		/* If it used to be prevented then allow it. */
+		if (old_use && old_delay < 0)
+			atomic_dec(&dev->power.usage_count);
+
+		/* Maybe we can autosuspend now. */
+		rpm_idle(dev, RPM_AUTO);
+	}
+}
+
+/**
+ * pm_runtime_set_autosuspend_delay - Set a device's autosuspend_delay value.
+ * @dev: Device to handle.
+ * @delay: Value of the new delay in milliseconds.
+ *
+ * Set the device's power.autosuspend_delay value.  If it changes to negative
+ * and the power.use_autosuspend flag is set, prevent run-time suspends.  If it
+ * changes the other way, allow run-time suspends.
+ */
+void pm_runtime_set_autosuspend_delay(struct device *dev, int delay)
+{
+	int old_delay, old_use;
+
+	spin_lock_irq(&dev->power.lock);
+	old_delay = dev->power.autosuspend_delay;
+	old_use = dev->power.use_autosuspend;
+	dev->power.autosuspend_delay = delay;
+	update_autosuspend(dev, old_delay, old_use);
+	spin_unlock_irq(&dev->power.lock);
+}
+EXPORT_SYMBOL_GPL(pm_runtime_set_autosuspend_delay);
+
+/**
+ * __pm_runtime_use_autosuspend - Set a device's use_autosuspend flag.
+ * @dev: Device to handle.
+ * @use: New value for use_autosuspend.
+ *
+ * Set the device's power.use_autosuspend flag, and allow or prevent run-time
+ * suspends as needed.
+ */
+void __pm_runtime_use_autosuspend(struct device *dev, bool use)
+{
+	int old_delay, old_use;
+
+	spin_lock_irq(&dev->power.lock);
+	old_delay = dev->power.autosuspend_delay;
+	old_use = dev->power.use_autosuspend;
+	dev->power.use_autosuspend = use;
+	update_autosuspend(dev, old_delay, old_use);
+	spin_unlock_irq(&dev->power.lock);
+}
+EXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend);
+
+/**
  * pm_runtime_init - Initialize run-time PM fields in given device object.
  * @dev: Device object to initialize.
  */
 void pm_runtime_init(struct device *dev)
 {
-	spin_lock_init(&dev->power.lock);
-
 	dev->power.runtime_status = RPM_SUSPENDED;
 	dev->power.idle_notification = false;
 
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index e56b438..0b1e46b 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -75,12 +75,27 @@
  *	attribute is set to "enabled" by bus type code or device drivers and in
  *	that cases it should be safe to leave the default value.
  *
+ *	autosuspend_delay_ms - Report/change a device's autosuspend_delay value
+ *
+ *	Some drivers don't want to carry out a runtime suspend as soon as a
+ *	device becomes idle; they want it always to remain idle for some period
+ *	of time before suspending it.  This period is the autosuspend_delay
+ *	value (expressed in milliseconds) and it can be controlled by the user.
+ *	If the value is negative then the device will never be runtime
+ *	suspended.
+ *
+ *	NOTE: The autosuspend_delay_ms attribute and the autosuspend_delay
+ *	value are used only if the driver calls pm_runtime_use_autosuspend().
+ *
  *	wakeup_count - Report the number of wakeup events related to the device
  */
 
 static const char enabled[] = "enabled";
 static const char disabled[] = "disabled";
 
+const char power_group_name[] = "power";
+EXPORT_SYMBOL_GPL(power_group_name);
+
 #ifdef CONFIG_PM_RUNTIME
 static const char ctrl_auto[] = "auto";
 static const char ctrl_on[] = "on";
@@ -170,6 +185,33 @@
 }
 
 static DEVICE_ATTR(runtime_status, 0444, rtpm_status_show, NULL);
+
+static ssize_t autosuspend_delay_ms_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	if (!dev->power.use_autosuspend)
+		return -EIO;
+	return sprintf(buf, "%d\n", dev->power.autosuspend_delay);
+}
+
+static ssize_t autosuspend_delay_ms_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t n)
+{
+	long delay;
+
+	if (!dev->power.use_autosuspend)
+		return -EIO;
+
+	if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
+		return -EINVAL;
+
+	pm_runtime_set_autosuspend_delay(dev, delay);
+	return n;
+}
+
+static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show,
+		autosuspend_delay_ms_store);
+
 #endif
 
 static ssize_t
@@ -210,11 +252,122 @@
 static ssize_t wakeup_count_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%lu\n", dev->power.wakeup_count);
+	unsigned long count = 0;
+	bool enabled = false;
+
+	spin_lock_irq(&dev->power.lock);
+	if (dev->power.wakeup) {
+		count = dev->power.wakeup->event_count;
+		enabled = true;
+	}
+	spin_unlock_irq(&dev->power.lock);
+	return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
 }
 
 static DEVICE_ATTR(wakeup_count, 0444, wakeup_count_show, NULL);
-#endif
+
+static ssize_t wakeup_active_count_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	unsigned long count = 0;
+	bool enabled = false;
+
+	spin_lock_irq(&dev->power.lock);
+	if (dev->power.wakeup) {
+		count = dev->power.wakeup->active_count;
+		enabled = true;
+	}
+	spin_unlock_irq(&dev->power.lock);
+	return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_active_count, 0444, wakeup_active_count_show, NULL);
+
+static ssize_t wakeup_hit_count_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	unsigned long count = 0;
+	bool enabled = false;
+
+	spin_lock_irq(&dev->power.lock);
+	if (dev->power.wakeup) {
+		count = dev->power.wakeup->hit_count;
+		enabled = true;
+	}
+	spin_unlock_irq(&dev->power.lock);
+	return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_hit_count, 0444, wakeup_hit_count_show, NULL);
+
+static ssize_t wakeup_active_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	unsigned int active = 0;
+	bool enabled = false;
+
+	spin_lock_irq(&dev->power.lock);
+	if (dev->power.wakeup) {
+		active = dev->power.wakeup->active;
+		enabled = true;
+	}
+	spin_unlock_irq(&dev->power.lock);
+	return enabled ? sprintf(buf, "%u\n", active) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_active, 0444, wakeup_active_show, NULL);
+
+static ssize_t wakeup_total_time_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	s64 msec = 0;
+	bool enabled = false;
+
+	spin_lock_irq(&dev->power.lock);
+	if (dev->power.wakeup) {
+		msec = ktime_to_ms(dev->power.wakeup->total_time);
+		enabled = true;
+	}
+	spin_unlock_irq(&dev->power.lock);
+	return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_total_time_ms, 0444, wakeup_total_time_show, NULL);
+
+static ssize_t wakeup_max_time_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	s64 msec = 0;
+	bool enabled = false;
+
+	spin_lock_irq(&dev->power.lock);
+	if (dev->power.wakeup) {
+		msec = ktime_to_ms(dev->power.wakeup->max_time);
+		enabled = true;
+	}
+	spin_unlock_irq(&dev->power.lock);
+	return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_max_time_ms, 0444, wakeup_max_time_show, NULL);
+
+static ssize_t wakeup_last_time_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	s64 msec = 0;
+	bool enabled = false;
+
+	spin_lock_irq(&dev->power.lock);
+	if (dev->power.wakeup) {
+		msec = ktime_to_ms(dev->power.wakeup->last_time);
+		enabled = true;
+	}
+	spin_unlock_irq(&dev->power.lock);
+	return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL);
+#endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_PM_ADVANCED_DEBUG
 #ifdef CONFIG_PM_RUNTIME
@@ -279,19 +432,20 @@
 #endif /* CONFIG_PM_ADVANCED_DEBUG */
 
 static struct attribute * power_attrs[] = {
-#ifdef CONFIG_PM_RUNTIME
-	&dev_attr_control.attr,
-	&dev_attr_runtime_status.attr,
-	&dev_attr_runtime_suspended_time.attr,
-	&dev_attr_runtime_active_time.attr,
-#endif
 	&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
 #ifdef CONFIG_PM_ADVANCED_DEBUG
 	&dev_attr_async.attr,
 #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,
@@ -300,10 +454,53 @@
 	NULL,
 };
 static struct attribute_group pm_attr_group = {
-	.name	= "power",
+	.name	= power_group_name,
 	.attrs	= power_attrs,
 };
 
+#ifdef CONFIG_PM_RUNTIME
+
+static struct attribute *runtime_attrs[] = {
+#ifndef CONFIG_PM_ADVANCED_DEBUG
+	&dev_attr_runtime_status.attr,
+#endif
+	&dev_attr_control.attr,
+	&dev_attr_runtime_suspended_time.attr,
+	&dev_attr_runtime_active_time.attr,
+	&dev_attr_autosuspend_delay_ms.attr,
+	NULL,
+};
+static struct attribute_group pm_runtime_attr_group = {
+	.name	= power_group_name,
+	.attrs	= runtime_attrs,
+};
+
+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) {
+		rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group);
+		if (rc)
+			sysfs_remove_group(&dev->kobj, &pm_attr_group);
+	}
+	return rc;
+}
+
+void rpm_sysfs_remove(struct device *dev)
+{
+	sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
+}
+
+void dpm_sysfs_remove(struct device *dev)
+{
+	rpm_sysfs_remove(dev);
+	sysfs_remove_group(&dev->kobj, &pm_attr_group);
+}
+
+#else /* CONFIG_PM_RUNTIME */
+
 int dpm_sysfs_add(struct device * dev)
 {
 	return sysfs_create_group(&dev->kobj, &pm_attr_group);
@@ -313,3 +510,5 @@
 {
 	sysfs_remove_group(&dev->kobj, &pm_attr_group);
 }
+
+#endif
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index 0a1a2c4..9f4258d 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -188,8 +188,10 @@
 static int show_dev_hash(unsigned int value)
 {
 	int match = 0;
-	struct list_head *entry = dpm_list.prev;
+	struct list_head *entry;
 
+	device_pm_lock();
+	entry = dpm_list.prev;
 	while (entry != &dpm_list) {
 		struct device * dev = to_device(entry);
 		unsigned int hash = hash_string(DEVSEED, dev_name(dev), DEVHASH);
@@ -199,11 +201,43 @@
 		}
 		entry = entry->prev;
 	}
+	device_pm_unlock();
 	return match;
 }
 
 static unsigned int hash_value_early_read;
 
+int show_trace_dev_match(char *buf, size_t size)
+{
+	unsigned int value = hash_value_early_read / (USERHASH * FILEHASH);
+	int ret = 0;
+	struct list_head *entry;
+
+	/*
+	 * It's possible that multiple devices will match the hash and we can't
+	 * tell which is the culprit, so it's best to output them all.
+	 */
+	device_pm_lock();
+	entry = dpm_list.prev;
+	while (size && entry != &dpm_list) {
+		struct device *dev = to_device(entry);
+		unsigned int hash = hash_string(DEVSEED, dev_name(dev),
+						DEVHASH);
+		if (hash == value) {
+			int len = snprintf(buf, size, "%s\n",
+					    dev_driver_string(dev));
+			if (len > size)
+				len = size;
+			buf += len;
+			ret += len;
+			size -= len;
+		}
+		entry = entry->prev;
+	}
+	device_pm_unlock();
+	return ret;
+}
+
 static int early_resume_init(void)
 {
 	hash_value_early_read = read_magic_time();
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index eb594fa..71c5528 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -11,7 +11,12 @@
 #include <linux/sched.h>
 #include <linux/capability.h>
 #include <linux/suspend.h>
-#include <linux/pm.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+
+#include "power.h"
+
+#define TIMEOUT		100
 
 /*
  * If set, the suspend/hibernate code will abort transitions to a sleep state
@@ -20,18 +25,244 @@
 bool events_check_enabled;
 
 /* The counter of registered wakeup events. */
-static unsigned long event_count;
+static atomic_t event_count = ATOMIC_INIT(0);
 /* A preserved old value of event_count. */
-static unsigned long saved_event_count;
+static unsigned int saved_count;
 /* The counter of wakeup events being processed. */
-static unsigned long events_in_progress;
+static atomic_t events_in_progress = ATOMIC_INIT(0);
 
 static DEFINE_SPINLOCK(events_lock);
 
 static void pm_wakeup_timer_fn(unsigned long data);
 
-static DEFINE_TIMER(events_timer, pm_wakeup_timer_fn, 0, 0);
-static unsigned long events_timer_expires;
+static LIST_HEAD(wakeup_sources);
+
+/**
+ * wakeup_source_create - Create a struct wakeup_source object.
+ * @name: Name of the new wakeup source.
+ */
+struct wakeup_source *wakeup_source_create(const char *name)
+{
+	struct wakeup_source *ws;
+
+	ws = kzalloc(sizeof(*ws), GFP_KERNEL);
+	if (!ws)
+		return NULL;
+
+	spin_lock_init(&ws->lock);
+	if (name)
+		ws->name = kstrdup(name, GFP_KERNEL);
+
+	return ws;
+}
+EXPORT_SYMBOL_GPL(wakeup_source_create);
+
+/**
+ * wakeup_source_destroy - Destroy a struct wakeup_source object.
+ * @ws: Wakeup source to destroy.
+ */
+void wakeup_source_destroy(struct wakeup_source *ws)
+{
+	if (!ws)
+		return;
+
+	spin_lock_irq(&ws->lock);
+	while (ws->active) {
+		spin_unlock_irq(&ws->lock);
+
+		schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
+
+		spin_lock_irq(&ws->lock);
+	}
+	spin_unlock_irq(&ws->lock);
+
+	kfree(ws->name);
+	kfree(ws);
+}
+EXPORT_SYMBOL_GPL(wakeup_source_destroy);
+
+/**
+ * wakeup_source_add - Add given object to the list of wakeup sources.
+ * @ws: Wakeup source object to add to the list.
+ */
+void wakeup_source_add(struct wakeup_source *ws)
+{
+	if (WARN_ON(!ws))
+		return;
+
+	setup_timer(&ws->timer, pm_wakeup_timer_fn, (unsigned long)ws);
+	ws->active = false;
+
+	spin_lock_irq(&events_lock);
+	list_add_rcu(&ws->entry, &wakeup_sources);
+	spin_unlock_irq(&events_lock);
+	synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(wakeup_source_add);
+
+/**
+ * wakeup_source_remove - Remove given object from the wakeup sources list.
+ * @ws: Wakeup source object to remove from the list.
+ */
+void wakeup_source_remove(struct wakeup_source *ws)
+{
+	if (WARN_ON(!ws))
+		return;
+
+	spin_lock_irq(&events_lock);
+	list_del_rcu(&ws->entry);
+	spin_unlock_irq(&events_lock);
+	synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(wakeup_source_remove);
+
+/**
+ * wakeup_source_register - Create wakeup source and add it to the list.
+ * @name: Name of the wakeup source to register.
+ */
+struct wakeup_source *wakeup_source_register(const char *name)
+{
+	struct wakeup_source *ws;
+
+	ws = wakeup_source_create(name);
+	if (ws)
+		wakeup_source_add(ws);
+
+	return ws;
+}
+EXPORT_SYMBOL_GPL(wakeup_source_register);
+
+/**
+ * wakeup_source_unregister - Remove wakeup source from the list and remove it.
+ * @ws: Wakeup source object to unregister.
+ */
+void wakeup_source_unregister(struct wakeup_source *ws)
+{
+	wakeup_source_remove(ws);
+	wakeup_source_destroy(ws);
+}
+EXPORT_SYMBOL_GPL(wakeup_source_unregister);
+
+/**
+ * device_wakeup_attach - Attach a wakeup source object to a device object.
+ * @dev: Device to handle.
+ * @ws: Wakeup source object to attach to @dev.
+ *
+ * This causes @dev to be treated as a wakeup device.
+ */
+static int device_wakeup_attach(struct device *dev, struct wakeup_source *ws)
+{
+	spin_lock_irq(&dev->power.lock);
+	if (dev->power.wakeup) {
+		spin_unlock_irq(&dev->power.lock);
+		return -EEXIST;
+	}
+	dev->power.wakeup = ws;
+	spin_unlock_irq(&dev->power.lock);
+	return 0;
+}
+
+/**
+ * device_wakeup_enable - Enable given device to be a wakeup source.
+ * @dev: Device to handle.
+ *
+ * Create a wakeup source object, register it and attach it to @dev.
+ */
+int device_wakeup_enable(struct device *dev)
+{
+	struct wakeup_source *ws;
+	int ret;
+
+	if (!dev || !dev->power.can_wakeup)
+		return -EINVAL;
+
+	ws = wakeup_source_register(dev_name(dev));
+	if (!ws)
+		return -ENOMEM;
+
+	ret = device_wakeup_attach(dev, ws);
+	if (ret)
+		wakeup_source_unregister(ws);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(device_wakeup_enable);
+
+/**
+ * device_wakeup_detach - Detach a device's wakeup source object from it.
+ * @dev: Device to detach the wakeup source object from.
+ *
+ * After it returns, @dev will not be treated as a wakeup device any more.
+ */
+static struct wakeup_source *device_wakeup_detach(struct device *dev)
+{
+	struct wakeup_source *ws;
+
+	spin_lock_irq(&dev->power.lock);
+	ws = dev->power.wakeup;
+	dev->power.wakeup = NULL;
+	spin_unlock_irq(&dev->power.lock);
+	return ws;
+}
+
+/**
+ * device_wakeup_disable - Do not regard a device as a wakeup source any more.
+ * @dev: Device to handle.
+ *
+ * Detach the @dev's wakeup source object from it, unregister this wakeup source
+ * object and destroy it.
+ */
+int device_wakeup_disable(struct device *dev)
+{
+	struct wakeup_source *ws;
+
+	if (!dev || !dev->power.can_wakeup)
+		return -EINVAL;
+
+	ws = device_wakeup_detach(dev);
+	if (ws)
+		wakeup_source_unregister(ws);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(device_wakeup_disable);
+
+/**
+ * device_init_wakeup - Device wakeup initialization.
+ * @dev: Device to handle.
+ * @enable: Whether or not to enable @dev as a wakeup device.
+ *
+ * By default, most devices should leave wakeup disabled.  The exceptions are
+ * devices that everyone expects to be wakeup sources: keyboards, power buttons,
+ * possibly network interfaces, etc.
+ */
+int device_init_wakeup(struct device *dev, bool enable)
+{
+	int ret = 0;
+
+	if (enable) {
+		device_set_wakeup_capable(dev, true);
+		ret = device_wakeup_enable(dev);
+	} else {
+		device_set_wakeup_capable(dev, false);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(device_init_wakeup);
+
+/**
+ * device_set_wakeup_enable - Enable or disable a device to wake up the system.
+ * @dev: Device to handle.
+ */
+int device_set_wakeup_enable(struct device *dev, bool enable)
+{
+	if (!dev || !dev->power.can_wakeup)
+		return -EINVAL;
+
+	return enable ? device_wakeup_enable(dev) : device_wakeup_disable(dev);
+}
+EXPORT_SYMBOL_GPL(device_set_wakeup_enable);
 
 /*
  * The functions below use the observation that each wakeup event starts a
@@ -55,118 +286,259 @@
  * knowledge, however, may not be available to it, so it can simply specify time
  * to wait before the system can be suspended and pass it as the second
  * argument of pm_wakeup_event().
+ *
+ * It is valid to call pm_relax() after pm_wakeup_event(), in which case the
+ * "no suspend" period will be ended either by the pm_relax(), or by the timer
+ * function executed when the timer expires, whichever comes first.
  */
 
 /**
+ * wakup_source_activate - Mark given wakeup source as active.
+ * @ws: Wakeup source to handle.
+ *
+ * Update the @ws' statistics and, if @ws has just been activated, notify the PM
+ * core of the event by incrementing the counter of of wakeup events being
+ * processed.
+ */
+static void wakeup_source_activate(struct wakeup_source *ws)
+{
+	ws->active = true;
+	ws->active_count++;
+	ws->timer_expires = jiffies;
+	ws->last_time = ktime_get();
+
+	atomic_inc(&events_in_progress);
+}
+
+/**
+ * __pm_stay_awake - Notify the PM core of a wakeup event.
+ * @ws: Wakeup source object associated with the source of the event.
+ *
+ * It is safe to call this function from interrupt context.
+ */
+void __pm_stay_awake(struct wakeup_source *ws)
+{
+	unsigned long flags;
+
+	if (!ws)
+		return;
+
+	spin_lock_irqsave(&ws->lock, flags);
+	ws->event_count++;
+	if (!ws->active)
+		wakeup_source_activate(ws);
+	spin_unlock_irqrestore(&ws->lock, flags);
+}
+EXPORT_SYMBOL_GPL(__pm_stay_awake);
+
+/**
  * pm_stay_awake - Notify the PM core that a wakeup event is being processed.
  * @dev: Device the wakeup event is related to.
  *
- * Notify the PM core of a wakeup event (signaled by @dev) by incrementing the
- * counter of wakeup events being processed.  If @dev is not NULL, the counter
- * of wakeup events related to @dev is incremented too.
+ * Notify the PM core of a wakeup event (signaled by @dev) by calling
+ * __pm_stay_awake for the @dev's wakeup source object.
  *
  * Call this function after detecting of a wakeup event if pm_relax() is going
  * to be called directly after processing the event (and possibly passing it to
  * user space for further processing).
- *
- * It is safe to call this function from interrupt context.
  */
 void pm_stay_awake(struct device *dev)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&events_lock, flags);
-	if (dev)
-		dev->power.wakeup_count++;
+	if (!dev)
+		return;
 
-	events_in_progress++;
-	spin_unlock_irqrestore(&events_lock, flags);
+	spin_lock_irqsave(&dev->power.lock, flags);
+	__pm_stay_awake(dev->power.wakeup);
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+}
+EXPORT_SYMBOL_GPL(pm_stay_awake);
+
+/**
+ * wakup_source_deactivate - Mark given wakeup source as inactive.
+ * @ws: Wakeup source to handle.
+ *
+ * Update the @ws' statistics and notify the PM core that the wakeup source has
+ * become inactive by decrementing the counter of wakeup events being processed
+ * and incrementing the counter of registered wakeup events.
+ */
+static void wakeup_source_deactivate(struct wakeup_source *ws)
+{
+	ktime_t duration;
+	ktime_t now;
+
+	ws->relax_count++;
+	/*
+	 * __pm_relax() may be called directly or from a timer function.
+	 * If it is called directly right after the timer function has been
+	 * started, but before the timer function calls __pm_relax(), it is
+	 * possible that __pm_stay_awake() will be called in the meantime and
+	 * will set ws->active.  Then, ws->active may be cleared immediately
+	 * by the __pm_relax() called from the timer function, but in such a
+	 * case ws->relax_count will be different from ws->active_count.
+	 */
+	if (ws->relax_count != ws->active_count) {
+		ws->relax_count--;
+		return;
+	}
+
+	ws->active = false;
+
+	now = ktime_get();
+	duration = ktime_sub(now, ws->last_time);
+	ws->total_time = ktime_add(ws->total_time, duration);
+	if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
+		ws->max_time = duration;
+
+	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.
+	 */
+	atomic_inc(&event_count);
+	smp_mb__before_atomic_dec();
+	atomic_dec(&events_in_progress);
 }
 
 /**
- * pm_relax - Notify the PM core that processing of a wakeup event has ended.
- *
- * Notify the PM core that a wakeup event has been processed by decrementing
- * the counter of wakeup events being processed and incrementing the counter
- * of registered wakeup events.
+ * __pm_relax - Notify the PM core that processing of a wakeup event has ended.
+ * @ws: Wakeup source object associated with the source of the event.
  *
  * Call this function for wakeup events whose processing started with calling
- * pm_stay_awake().
+ * __pm_stay_awake().
  *
  * It is safe to call it from interrupt context.
  */
-void pm_relax(void)
+void __pm_relax(struct wakeup_source *ws)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&events_lock, flags);
-	if (events_in_progress) {
-		events_in_progress--;
-		event_count++;
-	}
-	spin_unlock_irqrestore(&events_lock, flags);
+	if (!ws)
+		return;
+
+	spin_lock_irqsave(&ws->lock, flags);
+	if (ws->active)
+		wakeup_source_deactivate(ws);
+	spin_unlock_irqrestore(&ws->lock, flags);
 }
+EXPORT_SYMBOL_GPL(__pm_relax);
+
+/**
+ * pm_relax - Notify the PM core that processing of a wakeup event has ended.
+ * @dev: Device that signaled the event.
+ *
+ * Execute __pm_relax() for the @dev's wakeup source object.
+ */
+void pm_relax(struct device *dev)
+{
+	unsigned long flags;
+
+	if (!dev)
+		return;
+
+	spin_lock_irqsave(&dev->power.lock, flags);
+	__pm_relax(dev->power.wakeup);
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+}
+EXPORT_SYMBOL_GPL(pm_relax);
 
 /**
  * pm_wakeup_timer_fn - Delayed finalization of a wakeup event.
+ * @data: Address of the wakeup source object associated with the event source.
  *
- * Decrease the counter of wakeup events being processed after it was increased
- * by pm_wakeup_event().
+ * Call __pm_relax() for the wakeup source whose address is stored in @data.
  */
 static void pm_wakeup_timer_fn(unsigned long data)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&events_lock, flags);
-	if (events_timer_expires
-	    && time_before_eq(events_timer_expires, jiffies)) {
-		events_in_progress--;
-		events_timer_expires = 0;
-	}
-	spin_unlock_irqrestore(&events_lock, flags);
+	__pm_relax((struct wakeup_source *)data);
 }
 
 /**
+ * __pm_wakeup_event - Notify the PM core of a wakeup event.
+ * @ws: Wakeup source object associated with the event source.
+ * @msec: Anticipated event processing time (in milliseconds).
+ *
+ * Notify the PM core of a wakeup event whose source is @ws that will take
+ * approximately @msec milliseconds to be processed by the kernel.  If @ws is
+ * not active, activate it.  If @msec is nonzero, set up the @ws' timer to
+ * execute pm_wakeup_timer_fn() in future.
+ *
+ * It is safe to call this function from interrupt context.
+ */
+void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
+{
+	unsigned long flags;
+	unsigned long expires;
+
+	if (!ws)
+		return;
+
+	spin_lock_irqsave(&ws->lock, flags);
+
+	ws->event_count++;
+	if (!ws->active)
+		wakeup_source_activate(ws);
+
+	if (!msec) {
+		wakeup_source_deactivate(ws);
+		goto unlock;
+	}
+
+	expires = jiffies + msecs_to_jiffies(msec);
+	if (!expires)
+		expires = 1;
+
+	if (time_after(expires, ws->timer_expires)) {
+		mod_timer(&ws->timer, expires);
+		ws->timer_expires = expires;
+	}
+
+ unlock:
+	spin_unlock_irqrestore(&ws->lock, flags);
+}
+EXPORT_SYMBOL_GPL(__pm_wakeup_event);
+
+
+/**
  * pm_wakeup_event - Notify the PM core of a wakeup event.
  * @dev: Device the wakeup event is related to.
  * @msec: Anticipated event processing time (in milliseconds).
  *
- * Notify the PM core of a wakeup event (signaled by @dev) that will take
- * approximately @msec milliseconds to be processed by the kernel.  Increment
- * the counter of registered wakeup events and (if @msec is nonzero) set up
- * the wakeup events timer to execute pm_wakeup_timer_fn() in future (if the
- * timer has not been set up already, increment the counter of wakeup events
- * being processed).  If @dev is not NULL, the counter of wakeup events related
- * to @dev is incremented too.
- *
- * It is safe to call this function from interrupt context.
+ * Call __pm_wakeup_event() for the @dev's wakeup source object.
  */
 void pm_wakeup_event(struct device *dev, unsigned int msec)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&events_lock, flags);
-	event_count++;
-	if (dev)
-		dev->power.wakeup_count++;
+	if (!dev)
+		return;
 
-	if (msec) {
-		unsigned long expires;
+	spin_lock_irqsave(&dev->power.lock, flags);
+	__pm_wakeup_event(dev->power.wakeup, msec);
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+}
+EXPORT_SYMBOL_GPL(pm_wakeup_event);
 
-		expires = jiffies + msecs_to_jiffies(msec);
-		if (!expires)
-			expires = 1;
+/**
+ * pm_wakeup_update_hit_counts - Update hit counts of all active wakeup sources.
+ */
+static void pm_wakeup_update_hit_counts(void)
+{
+	unsigned long flags;
+	struct wakeup_source *ws;
 
-		if (!events_timer_expires
-		    || time_after(expires, events_timer_expires)) {
-			if (!events_timer_expires)
-				events_in_progress++;
-
-			mod_timer(&events_timer, expires);
-			events_timer_expires = expires;
-		}
+	rcu_read_lock();
+	list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
+		spin_lock_irqsave(&ws->lock, flags);
+		if (ws->active)
+			ws->hit_count++;
+		spin_unlock_irqrestore(&ws->lock, flags);
 	}
-	spin_unlock_irqrestore(&events_lock, flags);
+	rcu_read_unlock();
 }
 
 /**
@@ -184,10 +556,13 @@
 
 	spin_lock_irqsave(&events_lock, flags);
 	if (events_check_enabled) {
-		ret = (event_count == saved_event_count) && !events_in_progress;
+		ret = ((unsigned int)atomic_read(&event_count) == saved_count)
+			&& !atomic_read(&events_in_progress);
 		events_check_enabled = ret;
 	}
 	spin_unlock_irqrestore(&events_lock, flags);
+	if (!ret)
+		pm_wakeup_update_hit_counts();
 	return ret;
 }
 
@@ -202,24 +577,20 @@
  * 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.
  */
-bool pm_get_wakeup_count(unsigned long *count)
+bool pm_get_wakeup_count(unsigned int *count)
 {
 	bool ret;
 
-	spin_lock_irq(&events_lock);
 	if (capable(CAP_SYS_ADMIN))
 		events_check_enabled = false;
 
-	while (events_in_progress && !signal_pending(current)) {
-		spin_unlock_irq(&events_lock);
-
-		schedule_timeout_interruptible(msecs_to_jiffies(100));
-
-		spin_lock_irq(&events_lock);
+	while (atomic_read(&events_in_progress) && !signal_pending(current)) {
+		pm_wakeup_update_hit_counts();
+		schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
 	}
-	*count = event_count;
-	ret = !events_in_progress;
-	spin_unlock_irq(&events_lock);
+
+	ret = !atomic_read(&events_in_progress);
+	*count = atomic_read(&event_count);
 	return ret;
 }
 
@@ -232,16 +603,102 @@
  * old number of registered wakeup events to be used by pm_check_wakeup_events()
  * and return true.  Otherwise return false.
  */
-bool pm_save_wakeup_count(unsigned long count)
+bool pm_save_wakeup_count(unsigned int count)
 {
 	bool ret = false;
 
 	spin_lock_irq(&events_lock);
-	if (count == event_count && !events_in_progress) {
-		saved_event_count = count;
+	if (count == (unsigned int)atomic_read(&event_count)
+	    && !atomic_read(&events_in_progress)) {
+		saved_count = count;
 		events_check_enabled = true;
 		ret = true;
 	}
 	spin_unlock_irq(&events_lock);
+	if (!ret)
+		pm_wakeup_update_hit_counts();
 	return ret;
 }
+
+static struct dentry *wakeup_sources_stats_dentry;
+
+/**
+ * print_wakeup_source_stats - Print wakeup source statistics information.
+ * @m: seq_file to print the statistics into.
+ * @ws: Wakeup source object to print the statistics for.
+ */
+static int print_wakeup_source_stats(struct seq_file *m,
+				     struct wakeup_source *ws)
+{
+	unsigned long flags;
+	ktime_t total_time;
+	ktime_t max_time;
+	unsigned long active_count;
+	ktime_t active_time;
+	int ret;
+
+	spin_lock_irqsave(&ws->lock, flags);
+
+	total_time = ws->total_time;
+	max_time = ws->max_time;
+	active_count = ws->active_count;
+	if (ws->active) {
+		active_time = ktime_sub(ktime_get(), ws->last_time);
+		total_time = ktime_add(total_time, active_time);
+		if (active_time.tv64 > max_time.tv64)
+			max_time = active_time;
+	} else {
+		active_time = ktime_set(0, 0);
+	}
+
+	ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t"
+			"%lld\t\t%lld\t\t%lld\t\t%lld\n",
+			ws->name, active_count, ws->event_count, ws->hit_count,
+			ktime_to_ms(active_time), ktime_to_ms(total_time),
+			ktime_to_ms(max_time), ktime_to_ms(ws->last_time));
+
+	spin_unlock_irqrestore(&ws->lock, flags);
+
+	return ret;
+}
+
+/**
+ * wakeup_sources_stats_show - Print wakeup sources statistics information.
+ * @m: seq_file to print the statistics into.
+ */
+static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
+{
+	struct wakeup_source *ws;
+
+	seq_puts(m, "name\t\tactive_count\tevent_count\thit_count\t"
+		"active_since\ttotal_time\tmax_time\tlast_change\n");
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(ws, &wakeup_sources, entry)
+		print_wakeup_source_stats(m, ws);
+	rcu_read_unlock();
+
+	return 0;
+}
+
+static int wakeup_sources_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wakeup_sources_stats_show, NULL);
+}
+
+static const struct file_operations wakeup_sources_stats_fops = {
+	.owner = THIS_MODULE,
+	.open = wakeup_sources_stats_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int __init wakeup_sources_debugfs_init(void)
+{
+	wakeup_sources_stats_dentry = debugfs_create_file("wakeup_sources",
+			S_IRUGO, NULL, NULL, &wakeup_sources_stats_fops);
+	return 0;
+}
+
+postcore_initcall(wakeup_sources_debugfs_init);
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 9354dc1..1667aaf 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -432,13 +432,13 @@
 	/* resume current sysdev */
 cls_driver:
 	drv = NULL;
-	printk(KERN_ERR "Class suspend failed for %s\n",
-		kobject_name(&sysdev->kobj));
+	printk(KERN_ERR "Class suspend failed for %s: %d\n",
+		kobject_name(&sysdev->kobj), ret);
 
 aux_driver:
 	if (drv)
-		printk(KERN_ERR "Class driver suspend failed for %s\n",
-				kobject_name(&sysdev->kobj));
+		printk(KERN_ERR "Class driver suspend failed for %s: %d\n",
+				kobject_name(&sysdev->kobj), ret);
 	list_for_each_entry(err_drv, &cls->drivers, entry) {
 		if (err_drv == drv)
 			break;
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 9fc630c..f6f37a0 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -45,7 +45,8 @@
 	return sprintf(buf, "%d\n", topology_##name(cpu));	\
 }
 
-#if defined(topology_thread_cpumask) || defined(topology_core_cpumask)
+#if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \
+    defined(topology_book_cpumask)
 static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf)
 {
 	ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
@@ -114,6 +115,14 @@
 define_one_ro_named(core_siblings, show_core_cpumask);
 define_one_ro_named(core_siblings_list, show_core_cpumask_list);
 
+#ifdef CONFIG_SCHED_BOOK
+define_id_show_func(book_id);
+define_one_ro(book_id);
+define_siblings_show_func(book_cpumask);
+define_one_ro_named(book_siblings, show_book_cpumask);
+define_one_ro_named(book_siblings_list, show_book_cpumask_list);
+#endif
+
 static struct attribute *default_attrs[] = {
 	&attr_physical_package_id.attr,
 	&attr_core_id.attr,
@@ -121,6 +130,11 @@
 	&attr_thread_siblings_list.attr,
 	&attr_core_siblings.attr,
 	&attr_core_siblings_list.attr,
+#ifdef CONFIG_SCHED_BOOK
+	&attr_book_id.attr,
+	&attr_book_siblings.attr,
+	&attr_book_siblings_list.attr,
+#endif
 	NULL
 };
 
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 4e2c367..1f286ab 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -36,7 +36,7 @@
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/reboot.h>
@@ -54,6 +54,7 @@
 #define DAC960_GAM_MINOR	252
 
 
+static DEFINE_MUTEX(DAC960_mutex);
 static DAC960_Controller_T *DAC960_Controllers[DAC960_MaxControllers];
 static int DAC960_ControllerCount;
 static struct proc_dir_entry *DAC960_ProcDirectoryEntry;
@@ -81,7 +82,7 @@
 	int drive_nr = (long)disk->private_data;
 	int ret = -ENXIO;
 
-	lock_kernel();
+	mutex_lock(&DAC960_mutex);
 	if (p->FirmwareType == DAC960_V1_Controller) {
 		if (p->V1.LogicalDriveInformation[drive_nr].
 		    LogicalDriveState == DAC960_V1_LogicalDrive_Offline)
@@ -99,7 +100,7 @@
 		goto out;
 	ret = 0;
 out:
-	unlock_kernel();
+	mutex_unlock(&DAC960_mutex);
 	return ret;
 }
 
@@ -6625,7 +6626,7 @@
   long ErrorCode = 0;
   if (!capable(CAP_SYS_ADMIN)) return -EACCES;
 
-  lock_kernel();
+  mutex_lock(&DAC960_mutex);
   switch (Request)
     {
     case DAC960_IOCTL_GET_CONTROLLER_COUNT:
@@ -7056,13 +7057,14 @@
       default:
 	ErrorCode = -ENOTTY;
     }
-  unlock_kernel();
+  mutex_unlock(&DAC960_mutex);
   return ErrorCode;
 }
 
 static const struct file_operations DAC960_gam_fops = {
 	.owner		= THIS_MODULE,
-	.unlocked_ioctl	= DAC960_gam_ioctl
+	.unlocked_ioctl	= DAC960_gam_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice DAC960_gam_dev = {
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index de27768..4b9359a 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -488,4 +488,21 @@
 
 	  If unsure, say N.
 
+config BLK_DEV_RBD
+	tristate "Rados block device (RBD)"
+	depends on INET && EXPERIMENTAL && BLOCK
+	select CEPH_LIB
+	select LIBCRC32C
+	select CRYPTO_AES
+	select CRYPTO
+	default n
+	help
+	  Say Y here if you want include the Rados block device, which stripes
+	  a block device over objects stored in the Ceph distributed object
+	  store.
+
+	  More information at http://ceph.newdream.net/.
+
+	  If unsure, say N.
+
 endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index aff5ac9..d7f463d 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -37,5 +37,6 @@
 
 obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+= xen-blkfront.o
 obj-$(CONFIG_BLK_DEV_DRBD)     += drbd/
+obj-$(CONFIG_BLK_DEV_RBD)     += rbd.o
 
 swim_mod-objs	:= swim.o swim_asm.o
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 76f114f..a1725e6 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -60,7 +60,7 @@
 #include <linux/hdreg.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/amifdreg.h>
 #include <linux/amifd.h>
 #include <linux/buffer_head.h>
@@ -109,13 +109,12 @@
 #define FD_HD_3 	0x55555555  /* high-density 3.5" (1760K) drive */
 #define FD_DD_5 	0xaaaaaaaa  /* double-density 5.25" (440K) drive */
 
+static DEFINE_MUTEX(amiflop_mutex);
 static unsigned long int fd_def_df0 = FD_DD_3;     /* default for df0 if it doesn't identify */
 
 module_param(fd_def_df0, ulong, 0);
 MODULE_LICENSE("GPL");
 
-static struct request_queue *floppy_queue;
-
 /*
  *  Macros
  */
@@ -164,6 +163,7 @@
 static int writepending;
 static int writefromint;
 static char *raw_buf;
+static int fdc_queue;
 
 static DEFINE_SPINLOCK(amiflop_lock);
 
@@ -1334,6 +1334,42 @@
 	return -1;
 }
 
+/*
+ * Round-robin between our available drives, doing one request from each
+ */
+static struct request *set_next_request(void)
+{
+	struct request_queue *q;
+	int cnt = FD_MAX_UNITS;
+	struct request *rq;
+
+	/* Find next queue we can dispatch from */
+	fdc_queue = fdc_queue + 1;
+	if (fdc_queue == FD_MAX_UNITS)
+		fdc_queue = 0;
+
+	for(cnt = FD_MAX_UNITS; cnt > 0; cnt--) {
+
+		if (unit[fdc_queue].type->code == FD_NODRIVE) {
+			if (++fdc_queue == FD_MAX_UNITS)
+				fdc_queue = 0;
+			continue;
+		}
+
+		q = unit[fdc_queue].gendisk->queue;
+		if (q) {
+			rq = blk_fetch_request(q);
+			if (rq)
+				break;
+		}
+
+		if (++fdc_queue == FD_MAX_UNITS)
+			fdc_queue = 0;
+	}
+
+	return rq;
+}
+
 static void redo_fd_request(void)
 {
 	struct request *rq;
@@ -1345,7 +1381,7 @@
 	int err;
 
 next_req:
-	rq = blk_fetch_request(floppy_queue);
+	rq = set_next_request();
 	if (!rq) {
 		/* Nothing left to do */
 		return;
@@ -1506,9 +1542,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&amiflop_mutex);
 	ret = fd_locked_ioctl(bdev, mode, cmd, param);
-	unlock_kernel();
+	mutex_unlock(&amiflop_mutex);
 
 	return ret;
 }
@@ -1555,11 +1591,11 @@
 	int old_dev;
 	unsigned long flags;
 
-	lock_kernel();
+	mutex_lock(&amiflop_mutex);
 	old_dev = fd_device[drive];
 
 	if (fd_ref[drive] && old_dev != system) {
-		unlock_kernel();
+		mutex_unlock(&amiflop_mutex);
 		return -EBUSY;
 	}
 
@@ -1575,7 +1611,7 @@
 			rel_fdc();
 
 			if (wrprot) {
-				unlock_kernel();
+				mutex_unlock(&amiflop_mutex);
 				return -EROFS;
 			}
 		}
@@ -1594,7 +1630,7 @@
 	printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive,
 	       unit[drive].type->name, data_types[system].name);
 
-	unlock_kernel();
+	mutex_unlock(&amiflop_mutex);
 	return 0;
 }
 
@@ -1603,7 +1639,7 @@
 	struct amiga_floppy_struct *p = disk->private_data;
 	int drive = p - unit;
 
-	lock_kernel();
+	mutex_lock(&amiflop_mutex);
 	if (unit[drive].dirty == 1) {
 		del_timer (flush_track_timer + drive);
 		non_int_flush_track (drive);
@@ -1617,7 +1653,7 @@
 /* the mod_use counter is handled this way */
 	floppy_off (drive | 0x40000000);
 #endif
-	unlock_kernel();
+	mutex_unlock(&amiflop_mutex);
 	return 0;
 }
 
@@ -1682,6 +1718,13 @@
 			continue;
 		}
 		unit[drive].gendisk = disk;
+
+		disk->queue = blk_init_queue(do_fd_request, &amiflop_lock);
+		if (!disk->queue) {
+			unit[drive].type->code = FD_NODRIVE;
+			continue;
+		}
+
 		drives++;
 		if ((unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL)) == NULL) {
 			printk("no mem for ");
@@ -1695,7 +1738,6 @@
 		disk->fops = &floppy_fops;
 		sprintf(disk->disk_name, "fd%d", drive);
 		disk->private_data = &unit[drive];
-		disk->queue = floppy_queue;
 		set_capacity(disk, 880*2);
 		add_disk(disk);
 	}
@@ -1743,11 +1785,6 @@
 		goto out_irq2;
 	}
 
-	ret = -ENOMEM;
-	floppy_queue = blk_init_queue(do_fd_request, &amiflop_lock);
-	if (!floppy_queue)
-		goto out_queue;
-
 	ret = -ENODEV;
 	if (fd_probe_drives() < 1) /* No usable drives */
 		goto out_probe;
@@ -1791,8 +1828,6 @@
 	return 0;
 
 out_probe:
-	blk_cleanup_queue(floppy_queue);
-out_queue:
 	free_irq(IRQ_AMIGA_CIAA_TB, NULL);
 out_irq2:
 	free_irq(IRQ_AMIGA_DSKBLK, NULL);
@@ -1810,9 +1845,12 @@
 
 	for( i = 0; i < FD_MAX_UNITS; i++) {
 		if (unit[i].type->code != FD_NODRIVE) {
+			struct request_queue *q = unit[i].gendisk->queue;
 			del_gendisk(unit[i].gendisk);
 			put_disk(unit[i].gendisk);
 			kfree(unit[i].trackbuf);
+			if (q)
+				blk_cleanup_queue(q);
 		}
 	}
 	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
@@ -1820,7 +1858,6 @@
 	free_irq(IRQ_AMIGA_DSKBLK, NULL);
 	custom.dmacon = DMAF_DISK; /* disable DMA */
 	amiga_chip_free(raw_buf);
-	blk_cleanup_queue(floppy_queue);
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
 }
 #endif
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index a946929..f21c237 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -12,9 +12,10 @@
 #include <linux/slab.h>
 #include <linux/genhd.h>
 #include <linux/netdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include "aoe.h"
 
+static DEFINE_MUTEX(aoeblk_mutex);
 static struct kmem_cache *buf_pool_cache;
 
 static ssize_t aoedisk_show_state(struct device *dev,
@@ -125,16 +126,16 @@
 	struct aoedev *d = bdev->bd_disk->private_data;
 	ulong flags;
 
-	lock_kernel();
+	mutex_lock(&aoeblk_mutex);
 	spin_lock_irqsave(&d->lock, flags);
 	if (d->flags & DEVFL_UP) {
 		d->nopen++;
 		spin_unlock_irqrestore(&d->lock, flags);
-		unlock_kernel();
+		mutex_unlock(&aoeblk_mutex);
 		return 0;
 	}
 	spin_unlock_irqrestore(&d->lock, flags);
-	unlock_kernel();
+	mutex_unlock(&aoeblk_mutex);
 	return -ENODEV;
 }
 
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 4a1b9e74..146296c 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -9,7 +9,7 @@
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/skbuff.h>
 #include "aoe.h"
 
@@ -37,6 +37,7 @@
 	char *msg;
 };
 
+static DEFINE_MUTEX(aoechr_mutex);
 static struct ErrMsg emsgs[NMSG];
 static int emsgs_head_idx, emsgs_tail_idx;
 static struct completion emsgs_comp;
@@ -183,16 +184,16 @@
 {
 	int n, i;
 
-	lock_kernel();
+	mutex_lock(&aoechr_mutex);
 	n = iminor(inode);
 	filp->private_data = (void *) (unsigned long) n;
 
 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
 		if (chardevs[i].minor == n) {
-			unlock_kernel();
+			mutex_unlock(&aoechr_mutex);
 			return 0;
 		}
-	unlock_kernel();
+	mutex_unlock(&aoechr_mutex);
 	return -EINVAL;
 }
 
@@ -265,6 +266,7 @@
 	.open = aoechr_open,
 	.release = aoechr_rel,
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static char *aoe_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index aceb964..4e4cc6c 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -67,7 +67,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/atafd.h>
 #include <asm/atafdreg.h>
@@ -79,8 +79,9 @@
 
 #undef DEBUG
 
-static struct request_queue *floppy_queue;
+static DEFINE_MUTEX(ataflop_mutex);
 static struct request *fd_request;
+static int fdc_queue;
 
 /* Disk types: DD, HD, ED */
 static struct atari_disk_type {
@@ -1391,6 +1392,29 @@
 			ReqTrack, ReqSector, (unsigned long)ReqData ));
 }
 
+/*
+ * Round-robin between our available drives, doing one request from each
+ */
+static struct request *set_next_request(void)
+{
+	struct request_queue *q;
+	int old_pos = fdc_queue;
+	struct request *rq;
+
+	do {
+		q = unit[fdc_queue].disk->queue;
+		if (++fdc_queue == FD_MAX_UNITS)
+			fdc_queue = 0;
+		if (q) {
+			rq = blk_fetch_request(q);
+			if (rq)
+				break;
+		}
+	} while (fdc_queue != old_pos);
+
+	return rq;
+}
+
 
 static void redo_fd_request(void)
 {
@@ -1405,7 +1429,7 @@
 
 repeat:
 	if (!fd_request) {
-		fd_request = blk_fetch_request(floppy_queue);
+		fd_request = set_next_request();
 		if (!fd_request)
 			goto the_end;
 	}
@@ -1671,9 +1695,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ataflop_mutex);
 	ret = fd_locked_ioctl(bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ataflop_mutex);
 
 	return ret;
 }
@@ -1854,9 +1878,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ataflop_mutex);
 	ret = floppy_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&ataflop_mutex);
 
 	return ret;
 }
@@ -1864,14 +1888,14 @@
 static int floppy_release(struct gendisk *disk, fmode_t mode)
 {
 	struct atari_floppy_struct *p = disk->private_data;
-	lock_kernel();
+	mutex_lock(&ataflop_mutex);
 	if (p->ref < 0)
 		p->ref = 0;
 	else if (!p->ref--) {
 		printk(KERN_ERR "floppy_release with fd_ref == 0");
 		p->ref = 0;
 	}
-	unlock_kernel();
+	mutex_unlock(&ataflop_mutex);
 	return 0;
 }
 
@@ -1932,10 +1956,6 @@
 	PhysTrackBuffer = virt_to_phys(TrackBuffer);
 	BufferDrive = BufferSide = BufferTrack = -1;
 
-	floppy_queue = blk_init_queue(do_fd_request, &ataflop_lock);
-	if (!floppy_queue)
-		goto Enomem;
-
 	for (i = 0; i < FD_MAX_UNITS; i++) {
 		unit[i].track = -1;
 		unit[i].flags = 0;
@@ -1944,7 +1964,10 @@
 		sprintf(unit[i].disk->disk_name, "fd%d", i);
 		unit[i].disk->fops = &floppy_fops;
 		unit[i].disk->private_data = &unit[i];
-		unit[i].disk->queue = floppy_queue;
+		unit[i].disk->queue = blk_init_queue(do_fd_request,
+					&ataflop_lock);
+		if (!unit[i].disk->queue)
+			goto Enomem;
 		set_capacity(unit[i].disk, MAX_DISK_SIZE * 2);
 		add_disk(unit[i].disk);
 	}
@@ -1959,10 +1982,14 @@
 
 	return 0;
 Enomem:
-	while (i--)
+	while (i--) {
+		struct request_queue *q = unit[i].disk->queue;
+
 		put_disk(unit[i].disk);
-	if (floppy_queue)
-		blk_cleanup_queue(floppy_queue);
+		if (q)
+			blk_cleanup_queue(q);
+	}
+
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
 	return -ENOMEM;
 }
@@ -2011,12 +2038,14 @@
 	int i;
 	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
 	for (i = 0; i < FD_MAX_UNITS; i++) {
+		struct request_queue *q = unit[i].disk->queue;
+
 		del_gendisk(unit[i].disk);
 		put_disk(unit[i].disk);
+		blk_cleanup_queue(q);
 	}
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
 
-	blk_cleanup_queue(floppy_queue);
 	del_timer_sync(&fd_timer);
 	atari_stram_free( DMABuffer );
 }
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 1c7f637..b7f51e4 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -15,7 +15,7 @@
 #include <linux/blkdev.h>
 #include <linux/bio.h>
 #include <linux/highmem.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/radix-tree.h>
 #include <linux/buffer_head.h> /* invalidate_bh_lrus() */
 #include <linux/slab.h>
@@ -55,6 +55,7 @@
 /*
  * Look up and return a brd's page for a given sector.
  */
+static DEFINE_MUTEX(brd_mutex);
 static struct page *brd_lookup_page(struct brd_device *brd, sector_t sector)
 {
 	pgoff_t idx;
@@ -402,7 +403,7 @@
 	 * ram device BLKFLSBUF has special semantics, we want to actually
 	 * release and destroy the ramdisk data.
 	 */
-	lock_kernel();
+	mutex_lock(&brd_mutex);
 	mutex_lock(&bdev->bd_mutex);
 	error = -EBUSY;
 	if (bdev->bd_openers <= 1) {
@@ -419,7 +420,7 @@
 		error = 0;
 	}
 	mutex_unlock(&bdev->bd_mutex);
-	unlock_kernel();
+	mutex_unlock(&brd_mutex);
 
 	return error;
 }
@@ -482,7 +483,6 @@
 	if (!brd->brd_queue)
 		goto out_free_dev;
 	blk_queue_make_request(brd->brd_queue, brd_make_request);
-	blk_queue_ordered(brd->brd_queue, QUEUE_ORDERED_TAG);
 	blk_queue_max_hw_sectors(brd->brd_queue, 1024);
 	blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY);
 
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5e4fadc..f09e6df 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -26,7 +26,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/major.h>
 #include <linux/fs.h>
@@ -66,6 +65,7 @@
 MODULE_VERSION("3.6.26");
 MODULE_LICENSE("GPL");
 
+static DEFINE_MUTEX(cciss_mutex);
 static int cciss_allow_hpsa;
 module_param(cciss_allow_hpsa, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(cciss_allow_hpsa,
@@ -105,11 +105,12 @@
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3249},
 	{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, 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},
 	{0,}
 };
 
@@ -149,11 +150,12 @@
 	{0x3249103C, "Smart Array P812", &SA5_access},
 	{0x324A103C, "Smart Array P712m", &SA5_access},
 	{0x324B103C, "Smart Array P711m", &SA5_access},
-	{0x3250103C, "Smart Array", &SA5_access},
-	{0x3251103C, "Smart Array", &SA5_access},
-	{0x3252103C, "Smart Array", &SA5_access},
-	{0x3253103C, "Smart Array", &SA5_access},
-	{0x3254103C, "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},
 };
 
 /* How long to wait (in milliseconds) for board to go into simple mode */
@@ -1059,9 +1061,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&cciss_mutex);
 	ret = cciss_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&cciss_mutex);
 
 	return ret;
 }
@@ -1074,13 +1076,13 @@
 	ctlr_info_t *h;
 	drive_info_struct *drv;
 
-	lock_kernel();
+	mutex_lock(&cciss_mutex);
 	h = get_host(disk);
 	drv = get_drv(disk);
 	dev_dbg(&h->pdev->dev, "cciss_release %s\n", disk->disk_name);
 	drv->usage_count--;
 	h->usage_count--;
-	unlock_kernel();
+	mutex_unlock(&cciss_mutex);
 	return 0;
 }
 
@@ -1088,9 +1090,9 @@
 		    unsigned cmd, unsigned long arg)
 {
 	int ret;
-	lock_kernel();
+	mutex_lock(&cciss_mutex);
 	ret = cciss_ioctl(bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&cciss_mutex);
 	return ret;
 }
 
@@ -1232,470 +1234,452 @@
 			c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
 		(void)check_for_unit_attention(h, c);
 }
-/*
- * ioctl
- */
+
+static int cciss_getpciinfo(ctlr_info_t *h, void __user *argp)
+{
+	cciss_pci_info_struct pciinfo;
+
+	if (!argp)
+		return -EINVAL;
+	pciinfo.domain = pci_domain_nr(h->pdev->bus);
+	pciinfo.bus = h->pdev->bus->number;
+	pciinfo.dev_fn = h->pdev->devfn;
+	pciinfo.board_id = h->board_id;
+	if (copy_to_user(argp, &pciinfo, sizeof(cciss_pci_info_struct)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_getintinfo(ctlr_info_t *h, void __user *argp)
+{
+	cciss_coalint_struct intinfo;
+
+	if (!argp)
+		return -EINVAL;
+	intinfo.delay = readl(&h->cfgtable->HostWrite.CoalIntDelay);
+	intinfo.count = readl(&h->cfgtable->HostWrite.CoalIntCount);
+	if (copy_to_user
+	    (argp, &intinfo, sizeof(cciss_coalint_struct)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_setintinfo(ctlr_info_t *h, void __user *argp)
+{
+	cciss_coalint_struct intinfo;
+	unsigned long flags;
+	int i;
+
+	if (!argp)
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (copy_from_user(&intinfo, argp, sizeof(intinfo)))
+		return -EFAULT;
+	if ((intinfo.delay == 0) && (intinfo.count == 0))
+		return -EINVAL;
+	spin_lock_irqsave(&h->lock, flags);
+	/* Update the field, and then ring the doorbell */
+	writel(intinfo.delay, &(h->cfgtable->HostWrite.CoalIntDelay));
+	writel(intinfo.count, &(h->cfgtable->HostWrite.CoalIntCount));
+	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+
+	for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+		if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+			break;
+		udelay(1000); /* delay and try again */
+	}
+	spin_unlock_irqrestore(&h->lock, flags);
+	if (i >= MAX_IOCTL_CONFIG_WAIT)
+		return -EAGAIN;
+	return 0;
+}
+
+static int cciss_getnodename(ctlr_info_t *h, void __user *argp)
+{
+	NodeName_type NodeName;
+	int i;
+
+	if (!argp)
+		return -EINVAL;
+	for (i = 0; i < 16; i++)
+		NodeName[i] = readb(&h->cfgtable->ServerName[i]);
+	if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_setnodename(ctlr_info_t *h, void __user *argp)
+{
+	NodeName_type NodeName;
+	unsigned long flags;
+	int i;
+
+	if (!argp)
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (copy_from_user(NodeName, argp, sizeof(NodeName_type)))
+		return -EFAULT;
+	spin_lock_irqsave(&h->lock, flags);
+	/* Update the field, and then ring the doorbell */
+	for (i = 0; i < 16; i++)
+		writeb(NodeName[i], &h->cfgtable->ServerName[i]);
+	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+	for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+		if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+			break;
+		udelay(1000); /* delay and try again */
+	}
+	spin_unlock_irqrestore(&h->lock, flags);
+	if (i >= MAX_IOCTL_CONFIG_WAIT)
+		return -EAGAIN;
+	return 0;
+}
+
+static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp)
+{
+	Heartbeat_type heartbeat;
+
+	if (!argp)
+		return -EINVAL;
+	heartbeat = readl(&h->cfgtable->HeartBeat);
+	if (copy_to_user(argp, &heartbeat, sizeof(Heartbeat_type)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_getbustypes(ctlr_info_t *h, void __user *argp)
+{
+	BusTypes_type BusTypes;
+
+	if (!argp)
+		return -EINVAL;
+	BusTypes = readl(&h->cfgtable->BusTypes);
+	if (copy_to_user(argp, &BusTypes, sizeof(BusTypes_type)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_getfirmver(ctlr_info_t *h, void __user *argp)
+{
+	FirmwareVer_type firmware;
+
+	if (!argp)
+		return -EINVAL;
+	memcpy(firmware, h->firm_ver, 4);
+
+	if (copy_to_user
+	    (argp, firmware, sizeof(FirmwareVer_type)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_getdrivver(ctlr_info_t *h, void __user *argp)
+{
+	DriverVer_type DriverVer = DRIVER_VERSION;
+
+	if (!argp)
+		return -EINVAL;
+	if (copy_to_user(argp, &DriverVer, sizeof(DriverVer_type)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_getluninfo(ctlr_info_t *h,
+	struct gendisk *disk, void __user *argp)
+{
+	LogvolInfo_struct luninfo;
+	drive_info_struct *drv = get_drv(disk);
+
+	if (!argp)
+		return -EINVAL;
+	memcpy(&luninfo.LunID, drv->LunID, sizeof(luninfo.LunID));
+	luninfo.num_opens = drv->usage_count;
+	luninfo.num_parts = 0;
+	if (copy_to_user(argp, &luninfo, sizeof(LogvolInfo_struct)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_passthru(ctlr_info_t *h, void __user *argp)
+{
+	IOCTL_Command_struct iocommand;
+	CommandList_struct *c;
+	char *buff = NULL;
+	u64bit temp64;
+	DECLARE_COMPLETION_ONSTACK(wait);
+
+	if (!argp)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	if (copy_from_user
+	    (&iocommand, argp, sizeof(IOCTL_Command_struct)))
+		return -EFAULT;
+	if ((iocommand.buf_size < 1) &&
+	    (iocommand.Request.Type.Direction != XFER_NONE)) {
+		return -EINVAL;
+	}
+	if (iocommand.buf_size > 0) {
+		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;
+		}
+	} else {
+		memset(buff, 0, iocommand.buf_size);
+	}
+	c = cmd_special_alloc(h);
+	if (!c) {
+		kfree(buff);
+		return -ENOMEM;
+	}
+	/* Fill in the command type */
+	c->cmd_type = CMD_IOCTL_PEND;
+	/* Fill in Command Header */
+	c->Header.ReplyQueue = 0;   /* unused in simple mode */
+	if (iocommand.buf_size > 0) { /* buffer to fill */
+		c->Header.SGList = 1;
+		c->Header.SGTotal = 1;
+	} else { /* no buffers to fill */
+		c->Header.SGList = 0;
+		c->Header.SGTotal = 0;
+	}
+	c->Header.LUN = iocommand.LUN_info;
+	/* use the kernel address the cmd block for tag */
+	c->Header.Tag.lower = c->busaddr;
+
+	/* Fill in Request block */
+	c->Request = iocommand.Request;
+
+	/* Fill in the scatter gather information */
+	if (iocommand.buf_size > 0) {
+		temp64.val = pci_map_single(h->pdev, buff,
+			iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
+		c->SG[0].Addr.lower = temp64.val32.lower;
+		c->SG[0].Addr.upper = temp64.val32.upper;
+		c->SG[0].Len = iocommand.buf_size;
+		c->SG[0].Ext = 0;  /* we are not chaining */
+	}
+	c->waiting = &wait;
+
+	enqueue_cmd_and_start_io(h, c);
+	wait_for_completion(&wait);
+
+	/* unlock the buffers from DMA */
+	temp64.val32.lower = c->SG[0].Addr.lower;
+	temp64.val32.upper = c->SG[0].Addr.upper;
+	pci_unmap_single(h->pdev, (dma_addr_t) temp64.val, iocommand.buf_size,
+			 PCI_DMA_BIDIRECTIONAL);
+	check_ioctl_unit_attention(h, c);
+
+	/* Copy the error information out */
+	iocommand.error_info = *(c->err_info);
+	if (copy_to_user(argp, &iocommand, sizeof(IOCTL_Command_struct))) {
+		kfree(buff);
+		cmd_special_free(h, c);
+		return -EFAULT;
+	}
+
+	if (iocommand.Request.Type.Direction == XFER_READ) {
+		/* Copy the data out of the buffer we created */
+		if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
+			kfree(buff);
+			cmd_special_free(h, c);
+			return -EFAULT;
+		}
+	}
+	kfree(buff);
+	cmd_special_free(h, c);
+	return 0;
+}
+
+static int cciss_bigpassthru(ctlr_info_t *h, void __user *argp)
+{
+	BIG_IOCTL_Command_struct *ioc;
+	CommandList_struct *c;
+	unsigned char **buff = NULL;
+	int *buff_size = NULL;
+	u64bit temp64;
+	BYTE sg_used = 0;
+	int status = 0;
+	int i;
+	DECLARE_COMPLETION_ONSTACK(wait);
+	__u32 left;
+	__u32 sz;
+	BYTE __user *data_ptr;
+
+	if (!argp)
+		return -EINVAL;
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+	ioc = (BIG_IOCTL_Command_struct *)
+	    kmalloc(sizeof(*ioc), GFP_KERNEL);
+	if (!ioc) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	if (copy_from_user(ioc, argp, sizeof(*ioc))) {
+		status = -EFAULT;
+		goto cleanup1;
+	}
+	if ((ioc->buf_size < 1) &&
+	    (ioc->Request.Type.Direction != XFER_NONE)) {
+		status = -EINVAL;
+		goto cleanup1;
+	}
+	/* Check kmalloc limits  using all SGs */
+	if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
+		status = -EINVAL;
+		goto cleanup1;
+	}
+	if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
+		status = -EINVAL;
+		goto cleanup1;
+	}
+	buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
+	if (!buff) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	buff_size = kmalloc(MAXSGENTRIES * sizeof(int), GFP_KERNEL);
+	if (!buff_size) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	left = ioc->buf_size;
+	data_ptr = ioc->buf;
+	while (left) {
+		sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
+		buff_size[sg_used] = sz;
+		buff[sg_used] = kmalloc(sz, GFP_KERNEL);
+		if (buff[sg_used] == NULL) {
+			status = -ENOMEM;
+			goto cleanup1;
+		}
+		if (ioc->Request.Type.Direction == XFER_WRITE) {
+			if (copy_from_user(buff[sg_used], data_ptr, sz)) {
+				status = -EFAULT;
+				goto cleanup1;
+			}
+		} else {
+			memset(buff[sg_used], 0, sz);
+		}
+		left -= sz;
+		data_ptr += sz;
+		sg_used++;
+	}
+	c = cmd_special_alloc(h);
+	if (!c) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	c->cmd_type = CMD_IOCTL_PEND;
+	c->Header.ReplyQueue = 0;
+	c->Header.SGList = sg_used;
+	c->Header.SGTotal = sg_used;
+	c->Header.LUN = ioc->LUN_info;
+	c->Header.Tag.lower = c->busaddr;
+
+	c->Request = ioc->Request;
+	for (i = 0; i < sg_used; i++) {
+		temp64.val = pci_map_single(h->pdev, buff[i], buff_size[i],
+				    PCI_DMA_BIDIRECTIONAL);
+		c->SG[i].Addr.lower = temp64.val32.lower;
+		c->SG[i].Addr.upper = temp64.val32.upper;
+		c->SG[i].Len = buff_size[i];
+		c->SG[i].Ext = 0;	/* we are not chaining */
+	}
+	c->waiting = &wait;
+	enqueue_cmd_and_start_io(h, c);
+	wait_for_completion(&wait);
+	/* unlock the buffers from DMA */
+	for (i = 0; i < sg_used; i++) {
+		temp64.val32.lower = c->SG[i].Addr.lower;
+		temp64.val32.upper = c->SG[i].Addr.upper;
+		pci_unmap_single(h->pdev,
+			(dma_addr_t) temp64.val, buff_size[i],
+			PCI_DMA_BIDIRECTIONAL);
+	}
+	check_ioctl_unit_attention(h, c);
+	/* Copy the error information out */
+	ioc->error_info = *(c->err_info);
+	if (copy_to_user(argp, ioc, sizeof(*ioc))) {
+		cmd_special_free(h, c);
+		status = -EFAULT;
+		goto cleanup1;
+	}
+	if (ioc->Request.Type.Direction == XFER_READ) {
+		/* Copy the data out of the buffer we created */
+		BYTE __user *ptr = ioc->buf;
+		for (i = 0; i < sg_used; i++) {
+			if (copy_to_user(ptr, buff[i], buff_size[i])) {
+				cmd_special_free(h, c);
+				status = -EFAULT;
+				goto cleanup1;
+			}
+			ptr += buff_size[i];
+		}
+	}
+	cmd_special_free(h, c);
+	status = 0;
+cleanup1:
+	if (buff) {
+		for (i = 0; i < sg_used; i++)
+			kfree(buff[i]);
+		kfree(buff);
+	}
+	kfree(buff_size);
+	kfree(ioc);
+	return status;
+}
+
 static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
-		       unsigned int cmd, unsigned long arg)
+	unsigned int cmd, unsigned long arg)
 {
 	struct gendisk *disk = bdev->bd_disk;
 	ctlr_info_t *h = get_host(disk);
-	drive_info_struct *drv = get_drv(disk);
 	void __user *argp = (void __user *)arg;
 
 	dev_dbg(&h->pdev->dev, "cciss_ioctl: Called with cmd=%x %lx\n",
 		cmd, arg);
 	switch (cmd) {
 	case CCISS_GETPCIINFO:
-		{
-			cciss_pci_info_struct pciinfo;
-
-			if (!arg)
-				return -EINVAL;
-			pciinfo.domain = pci_domain_nr(h->pdev->bus);
-			pciinfo.bus = h->pdev->bus->number;
-			pciinfo.dev_fn = h->pdev->devfn;
-			pciinfo.board_id = h->board_id;
-			if (copy_to_user
-			    (argp, &pciinfo, sizeof(cciss_pci_info_struct)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getpciinfo(h, argp);
 	case CCISS_GETINTINFO:
-		{
-			cciss_coalint_struct intinfo;
-			if (!arg)
-				return -EINVAL;
-			intinfo.delay =
-			    readl(&h->cfgtable->HostWrite.CoalIntDelay);
-			intinfo.count =
-			    readl(&h->cfgtable->HostWrite.CoalIntCount);
-			if (copy_to_user
-			    (argp, &intinfo, sizeof(cciss_coalint_struct)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getintinfo(h, argp);
 	case CCISS_SETINTINFO:
-		{
-			cciss_coalint_struct intinfo;
-			unsigned long flags;
-			int i;
-
-			if (!arg)
-				return -EINVAL;
-			if (!capable(CAP_SYS_ADMIN))
-				return -EPERM;
-			if (copy_from_user
-			    (&intinfo, argp, sizeof(cciss_coalint_struct)))
-				return -EFAULT;
-			if ((intinfo.delay == 0) && (intinfo.count == 0))
-				return -EINVAL;
-			spin_lock_irqsave(&h->lock, flags);
-			/* Update the field, and then ring the doorbell */
-			writel(intinfo.delay,
-			       &(h->cfgtable->HostWrite.CoalIntDelay));
-			writel(intinfo.count,
-			       &(h->cfgtable->HostWrite.CoalIntCount));
-			writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
-
-			for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
-				if (!(readl(h->vaddr + SA5_DOORBELL)
-				      & CFGTBL_ChangeReq))
-					break;
-				/* delay and try again */
-				udelay(1000);
-			}
-			spin_unlock_irqrestore(&h->lock, flags);
-			if (i >= MAX_IOCTL_CONFIG_WAIT)
-				return -EAGAIN;
-			return 0;
-		}
+		return cciss_setintinfo(h, argp);
 	case CCISS_GETNODENAME:
-		{
-			NodeName_type NodeName;
-			int i;
-
-			if (!arg)
-				return -EINVAL;
-			for (i = 0; i < 16; i++)
-				NodeName[i] =
-				    readb(&h->cfgtable->ServerName[i]);
-			if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getnodename(h, argp);
 	case CCISS_SETNODENAME:
-		{
-			NodeName_type NodeName;
-			unsigned long flags;
-			int i;
-
-			if (!arg)
-				return -EINVAL;
-			if (!capable(CAP_SYS_ADMIN))
-				return -EPERM;
-
-			if (copy_from_user
-			    (NodeName, argp, sizeof(NodeName_type)))
-				return -EFAULT;
-
-			spin_lock_irqsave(&h->lock, flags);
-
-			/* Update the field, and then ring the doorbell */
-			for (i = 0; i < 16; i++)
-				writeb(NodeName[i],
-				       &h->cfgtable->ServerName[i]);
-
-			writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
-
-			for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
-				if (!(readl(h->vaddr + SA5_DOORBELL)
-				      & CFGTBL_ChangeReq))
-					break;
-				/* delay and try again */
-				udelay(1000);
-			}
-			spin_unlock_irqrestore(&h->lock, flags);
-			if (i >= MAX_IOCTL_CONFIG_WAIT)
-				return -EAGAIN;
-			return 0;
-		}
-
+		return cciss_setnodename(h, argp);
 	case CCISS_GETHEARTBEAT:
-		{
-			Heartbeat_type heartbeat;
-
-			if (!arg)
-				return -EINVAL;
-			heartbeat = readl(&h->cfgtable->HeartBeat);
-			if (copy_to_user
-			    (argp, &heartbeat, sizeof(Heartbeat_type)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getheartbeat(h, argp);
 	case CCISS_GETBUSTYPES:
-		{
-			BusTypes_type BusTypes;
-
-			if (!arg)
-				return -EINVAL;
-			BusTypes = readl(&h->cfgtable->BusTypes);
-			if (copy_to_user
-			    (argp, &BusTypes, sizeof(BusTypes_type)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getbustypes(h, argp);
 	case CCISS_GETFIRMVER:
-		{
-			FirmwareVer_type firmware;
-
-			if (!arg)
-				return -EINVAL;
-			memcpy(firmware, h->firm_ver, 4);
-
-			if (copy_to_user
-			    (argp, firmware, sizeof(FirmwareVer_type)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getfirmver(h, argp);
 	case CCISS_GETDRIVVER:
-		{
-			DriverVer_type DriverVer = DRIVER_VERSION;
-
-			if (!arg)
-				return -EINVAL;
-
-			if (copy_to_user
-			    (argp, &DriverVer, sizeof(DriverVer_type)))
-				return -EFAULT;
-			return 0;
-		}
-
+		return cciss_getdrivver(h, argp);
 	case CCISS_DEREGDISK:
 	case CCISS_REGNEWD:
 	case CCISS_REVALIDVOLS:
 		return rebuild_lun_table(h, 0, 1);
-
-	case CCISS_GETLUNINFO:{
-			LogvolInfo_struct luninfo;
-
-			memcpy(&luninfo.LunID, drv->LunID,
-				sizeof(luninfo.LunID));
-			luninfo.num_opens = drv->usage_count;
-			luninfo.num_parts = 0;
-			if (copy_to_user(argp, &luninfo,
-					 sizeof(LogvolInfo_struct)))
-				return -EFAULT;
-			return 0;
-		}
+	case CCISS_GETLUNINFO:
+		return cciss_getluninfo(h, disk, argp);
 	case CCISS_PASSTHRU:
-		{
-			IOCTL_Command_struct iocommand;
-			CommandList_struct *c;
-			char *buff = NULL;
-			u64bit temp64;
-			DECLARE_COMPLETION_ONSTACK(wait);
-
-			if (!arg)
-				return -EINVAL;
-
-			if (!capable(CAP_SYS_RAWIO))
-				return -EPERM;
-
-			if (copy_from_user
-			    (&iocommand, argp, sizeof(IOCTL_Command_struct)))
-				return -EFAULT;
-			if ((iocommand.buf_size < 1) &&
-			    (iocommand.Request.Type.Direction != XFER_NONE)) {
-				return -EINVAL;
-			}
-#if 0				/* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */
-			/* Check kmalloc limits */
-			if (iocommand.buf_size > 128000)
-				return -EINVAL;
-#endif
-			if (iocommand.buf_size > 0) {
-				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;
-				}
-			} else {
-				memset(buff, 0, iocommand.buf_size);
-			}
-			c = cmd_special_alloc(h);
-			if (!c) {
-				kfree(buff);
-				return -ENOMEM;
-			}
-			/* Fill in the command type */
-			c->cmd_type = CMD_IOCTL_PEND;
-			/* Fill in Command Header */
-			c->Header.ReplyQueue = 0;   /* unused in simple mode */
-			if (iocommand.buf_size > 0) /* buffer to fill */
-			{
-				c->Header.SGList = 1;
-				c->Header.SGTotal = 1;
-			} else /* no buffers to fill */
-			{
-				c->Header.SGList = 0;
-				c->Header.SGTotal = 0;
-			}
-			c->Header.LUN = iocommand.LUN_info;
-			/* use the kernel address the cmd block for tag */
-			c->Header.Tag.lower = c->busaddr;
-
-			/* Fill in Request block */
-			c->Request = iocommand.Request;
-
-			/* Fill in the scatter gather information */
-			if (iocommand.buf_size > 0) {
-				temp64.val = pci_map_single(h->pdev, buff,
-					iocommand.buf_size,
-					PCI_DMA_BIDIRECTIONAL);
-				c->SG[0].Addr.lower = temp64.val32.lower;
-				c->SG[0].Addr.upper = temp64.val32.upper;
-				c->SG[0].Len = iocommand.buf_size;
-				c->SG[0].Ext = 0;  /* we are not chaining */
-			}
-			c->waiting = &wait;
-
-			enqueue_cmd_and_start_io(h, c);
-			wait_for_completion(&wait);
-
-			/* unlock the buffers from DMA */
-			temp64.val32.lower = c->SG[0].Addr.lower;
-			temp64.val32.upper = c->SG[0].Addr.upper;
-			pci_unmap_single(h->pdev, (dma_addr_t) temp64.val,
-					 iocommand.buf_size,
-					 PCI_DMA_BIDIRECTIONAL);
-
-			check_ioctl_unit_attention(h, c);
-
-			/* Copy the error information out */
-			iocommand.error_info = *(c->err_info);
-			if (copy_to_user
-			    (argp, &iocommand, sizeof(IOCTL_Command_struct))) {
-				kfree(buff);
-				cmd_special_free(h, c);
-				return -EFAULT;
-			}
-
-			if (iocommand.Request.Type.Direction == XFER_READ) {
-				/* Copy the data out of the buffer we created */
-				if (copy_to_user
-				    (iocommand.buf, buff, iocommand.buf_size)) {
-					kfree(buff);
-					cmd_special_free(h, c);
-					return -EFAULT;
-				}
-			}
-			kfree(buff);
-			cmd_special_free(h, c);
-			return 0;
-		}
-	case CCISS_BIG_PASSTHRU:{
-			BIG_IOCTL_Command_struct *ioc;
-			CommandList_struct *c;
-			unsigned char **buff = NULL;
-			int *buff_size = NULL;
-			u64bit temp64;
-			BYTE sg_used = 0;
-			int status = 0;
-			int i;
-			DECLARE_COMPLETION_ONSTACK(wait);
-			__u32 left;
-			__u32 sz;
-			BYTE __user *data_ptr;
-
-			if (!arg)
-				return -EINVAL;
-			if (!capable(CAP_SYS_RAWIO))
-				return -EPERM;
-			ioc = (BIG_IOCTL_Command_struct *)
-			    kmalloc(sizeof(*ioc), GFP_KERNEL);
-			if (!ioc) {
-				status = -ENOMEM;
-				goto cleanup1;
-			}
-			if (copy_from_user(ioc, argp, sizeof(*ioc))) {
-				status = -EFAULT;
-				goto cleanup1;
-			}
-			if ((ioc->buf_size < 1) &&
-			    (ioc->Request.Type.Direction != XFER_NONE)) {
-				status = -EINVAL;
-				goto cleanup1;
-			}
-			/* Check kmalloc limits  using all SGs */
-			if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
-				status = -EINVAL;
-				goto cleanup1;
-			}
-			if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
-				status = -EINVAL;
-				goto cleanup1;
-			}
-			buff =
-			    kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
-			if (!buff) {
-				status = -ENOMEM;
-				goto cleanup1;
-			}
-			buff_size = kmalloc(MAXSGENTRIES * sizeof(int),
-						   GFP_KERNEL);
-			if (!buff_size) {
-				status = -ENOMEM;
-				goto cleanup1;
-			}
-			left = ioc->buf_size;
-			data_ptr = ioc->buf;
-			while (left) {
-				sz = (left >
-				      ioc->malloc_size) ? ioc->
-				    malloc_size : left;
-				buff_size[sg_used] = sz;
-				buff[sg_used] = kmalloc(sz, GFP_KERNEL);
-				if (buff[sg_used] == NULL) {
-					status = -ENOMEM;
-					goto cleanup1;
-				}
-				if (ioc->Request.Type.Direction == XFER_WRITE) {
-					if (copy_from_user
-					    (buff[sg_used], data_ptr, sz)) {
-						status = -EFAULT;
-						goto cleanup1;
-					}
-				} else {
-					memset(buff[sg_used], 0, sz);
-				}
-				left -= sz;
-				data_ptr += sz;
-				sg_used++;
-			}
-			c = cmd_special_alloc(h);
-			if (!c) {
-				status = -ENOMEM;
-				goto cleanup1;
-			}
-			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.LUN = ioc->LUN_info;
-			c->Header.Tag.lower = c->busaddr;
-
-			c->Request = ioc->Request;
-			if (ioc->buf_size > 0) {
-				for (i = 0; i < sg_used; i++) {
-					temp64.val =
-					    pci_map_single(h->pdev, buff[i],
-						    buff_size[i],
-						    PCI_DMA_BIDIRECTIONAL);
-					c->SG[i].Addr.lower =
-					    temp64.val32.lower;
-					c->SG[i].Addr.upper =
-					    temp64.val32.upper;
-					c->SG[i].Len = buff_size[i];
-					c->SG[i].Ext = 0;	/* we are not chaining */
-				}
-			}
-			c->waiting = &wait;
-			enqueue_cmd_and_start_io(h, c);
-			wait_for_completion(&wait);
-			/* unlock the buffers from DMA */
-			for (i = 0; i < sg_used; i++) {
-				temp64.val32.lower = c->SG[i].Addr.lower;
-				temp64.val32.upper = c->SG[i].Addr.upper;
-				pci_unmap_single(h->pdev,
-					(dma_addr_t) temp64.val, buff_size[i],
-					PCI_DMA_BIDIRECTIONAL);
-			}
-			check_ioctl_unit_attention(h, c);
-			/* Copy the error information out */
-			ioc->error_info = *(c->err_info);
-			if (copy_to_user(argp, ioc, sizeof(*ioc))) {
-				cmd_special_free(h, c);
-				status = -EFAULT;
-				goto cleanup1;
-			}
-			if (ioc->Request.Type.Direction == XFER_READ) {
-				/* Copy the data out of the buffer we created */
-				BYTE __user *ptr = ioc->buf;
-				for (i = 0; i < sg_used; i++) {
-					if (copy_to_user
-					    (ptr, buff[i], buff_size[i])) {
-						cmd_special_free(h, c);
-						status = -EFAULT;
-						goto cleanup1;
-					}
-					ptr += buff_size[i];
-				}
-			}
-			cmd_special_free(h, c);
-			status = 0;
-		      cleanup1:
-			if (buff) {
-				for (i = 0; i < sg_used; i++)
-					kfree(buff[i]);
-				kfree(buff);
-			}
-			kfree(buff_size);
-			kfree(ioc);
-			return status;
-		}
+		return cciss_passthru(h, argp);
+	case CCISS_BIG_PASSTHRU:
+		return cciss_bigpassthru(h, argp);
 
 	/* scsi_cmd_ioctl handles these, below, though some are not */
 	/* very meaningful for cciss.  SG_IO is the main one people want. */
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index d53b029..946dad4 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -35,7 +35,7 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/hdreg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
 #include <linux/genhd.h>
@@ -68,6 +68,7 @@
 
 #define CPQARRAY_DMA_MASK	0xFFFFFFFF	/* 32 bit DMA */
 
+static DEFINE_MUTEX(cpqarray_mutex);
 static int nr_ctlr;
 static ctlr_info_t *hba[MAX_CTLR];
 
@@ -845,9 +846,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&cpqarray_mutex);
 	ret = ida_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&cpqarray_mutex);
 
 	return ret;
 }
@@ -859,10 +860,10 @@
 {
 	ctlr_info_t *host;
 
-	lock_kernel();
+	mutex_lock(&cpqarray_mutex);
 	host = get_host(disk);
 	host->usage_count--;
-	unlock_kernel();
+	mutex_unlock(&cpqarray_mutex);
 
 	return 0;
 }
@@ -1217,9 +1218,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&cpqarray_mutex);
 	ret = ida_locked_ioctl(bdev, mode, cmd, param);
-	unlock_kernel();
+	mutex_unlock(&cpqarray_mutex);
 
 	return ret;
 }
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 9400845..ac04ef9 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -965,29 +965,30 @@
 	 * ok, (capacity & 7) != 0 sometimes, but who cares...
 	 * we count rs_{total,left} in bits, not sectors.
 	 */
-	spin_lock_irqsave(&mdev->al_lock, flags);
 	count = drbd_bm_clear_bits(mdev, sbnr, ebnr);
-	if (count) {
-		/* we need the lock for drbd_try_clear_on_disk_bm */
-		if (jiffies - mdev->rs_mark_time > HZ*10) {
-			/* should be rolling marks,
-			 * but we estimate only anyways. */
-			if (mdev->rs_mark_left != drbd_bm_total_weight(mdev) &&
+	if (count && get_ldev(mdev)) {
+		unsigned long now = jiffies;
+		unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark];
+		int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS;
+		if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) {
+			unsigned long tw = drbd_bm_total_weight(mdev);
+			if (mdev->rs_mark_left[mdev->rs_last_mark] != tw &&
 			    mdev->state.conn != C_PAUSED_SYNC_T &&
 			    mdev->state.conn != C_PAUSED_SYNC_S) {
-				mdev->rs_mark_time = jiffies;
-				mdev->rs_mark_left = drbd_bm_total_weight(mdev);
+				mdev->rs_mark_time[next] = now;
+				mdev->rs_mark_left[next] = tw;
+				mdev->rs_last_mark = next;
 			}
 		}
-		if (get_ldev(mdev)) {
-			drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE);
-			put_ldev(mdev);
-		}
+		spin_lock_irqsave(&mdev->al_lock, flags);
+		drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE);
+		spin_unlock_irqrestore(&mdev->al_lock, flags);
+
 		/* just wake_up unconditional now, various lc_chaged(),
 		 * lc_put() in drbd_try_clear_on_disk_bm(). */
 		wake_up = 1;
+		put_ldev(mdev);
 	}
-	spin_unlock_irqrestore(&mdev->al_lock, flags);
 	if (wake_up)
 		wake_up(&mdev->al_wait);
 }
@@ -1118,7 +1119,7 @@
  * @mdev:	DRBD device.
  * @sector:	The sector number.
  *
- * This functions sleeps on al_wait. Returns 1 on success, 0 if interrupted.
+ * This functions sleeps on al_wait. Returns 0 on success, -EINTR if interrupted.
  */
 int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
 {
@@ -1129,10 +1130,10 @@
 	sig = wait_event_interruptible(mdev->al_wait,
 			(bm_ext = _bme_get(mdev, enr)));
 	if (sig)
-		return 0;
+		return -EINTR;
 
 	if (test_bit(BME_LOCKED, &bm_ext->flags))
-		return 1;
+		return 0;
 
 	for (i = 0; i < AL_EXT_PER_BM_SECT; i++) {
 		sig = wait_event_interruptible(mdev->al_wait,
@@ -1145,13 +1146,11 @@
 				wake_up(&mdev->al_wait);
 			}
 			spin_unlock_irq(&mdev->al_lock);
-			return 0;
+			return -EINTR;
 		}
 	}
-
 	set_bit(BME_LOCKED, &bm_ext->flags);
-
-	return 1;
+	return 0;
 }
 
 /**
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index e3f88d6..fd42832 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -569,7 +569,7 @@
  *
  * maybe bm_set should be atomic_t ?
  */
-static unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev)
+unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
 	unsigned long s;
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 352441b..9bdcf43 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -337,13 +337,25 @@
  * NOTE that the payload starts at a long aligned offset,
  * regardless of 32 or 64 bit arch!
  */
-struct p_header {
+struct p_header80 {
 	u32	  magic;
 	u16	  command;
 	u16	  length;	/* bytes of data after this header */
 	u8	  payload[0];
 } __packed;
-/* 8 bytes. packet FIXED for the next century! */
+
+/* Header for big packets, Used for data packets exceeding 64kB */
+struct p_header95 {
+	u16	  magic;	/* use DRBD_MAGIC_BIG here */
+	u16	  command;
+	u32	  length;	/* Use only 24 bits of that. Ignore the highest 8 bit. */
+	u8	  payload[0];
+} __packed;
+
+union p_header {
+	struct p_header80 h80;
+	struct p_header95 h95;
+};
 
 /*
  * short commands, packets without payload, plain p_header:
@@ -362,12 +374,16 @@
  */
 
 /* these defines must not be changed without changing the protocol version */
-#define DP_HARDBARRIER	      1
-#define DP_RW_SYNC	      2
+#define DP_HARDBARRIER	      1 /* depricated */
+#define DP_RW_SYNC	      2 /* equals REQ_SYNC    */
 #define DP_MAY_SET_IN_SYNC    4
+#define DP_UNPLUG             8 /* equals REQ_UNPLUG  */
+#define DP_FUA               16 /* equals REQ_FUA     */
+#define DP_FLUSH             32 /* equals REQ_FLUSH   */
+#define DP_DISCARD           64 /* equals REQ_DISCARD */
 
 struct p_data {
-	struct p_header head;
+	union p_header head;
 	u64	    sector;    /* 64 bits sector number */
 	u64	    block_id;  /* to identify the request in protocol B&C */
 	u32	    seq_num;
@@ -383,7 +399,7 @@
  *   P_DATA_REQUEST, P_RS_DATA_REQUEST
  */
 struct p_block_ack {
-	struct p_header head;
+	struct p_header80 head;
 	u64	    sector;
 	u64	    block_id;
 	u32	    blksize;
@@ -392,7 +408,7 @@
 
 
 struct p_block_req {
-	struct p_header head;
+	struct p_header80 head;
 	u64 sector;
 	u64 block_id;
 	u32 blksize;
@@ -409,7 +425,7 @@
  */
 
 struct p_handshake {
-	struct p_header head;	/* 8 bytes */
+	struct p_header80 head;	/* 8 bytes */
 	u32 protocol_min;
 	u32 feature_flags;
 	u32 protocol_max;
@@ -424,19 +440,19 @@
 /* 80 bytes, FIXED for the next century */
 
 struct p_barrier {
-	struct p_header head;
+	struct p_header80 head;
 	u32 barrier;	/* barrier number _handle_ only */
 	u32 pad;	/* to multiple of 8 Byte */
 } __packed;
 
 struct p_barrier_ack {
-	struct p_header head;
+	struct p_header80 head;
 	u32 barrier;
 	u32 set_size;
 } __packed;
 
 struct p_rs_param {
-	struct p_header head;
+	struct p_header80 head;
 	u32 rate;
 
 	      /* Since protocol version 88 and higher. */
@@ -444,20 +460,31 @@
 } __packed;
 
 struct p_rs_param_89 {
-	struct p_header head;
+	struct p_header80 head;
 	u32 rate;
         /* protocol version 89: */
 	char verify_alg[SHARED_SECRET_MAX];
 	char csums_alg[SHARED_SECRET_MAX];
 } __packed;
 
+struct p_rs_param_95 {
+	struct p_header80 head;
+	u32 rate;
+	char verify_alg[SHARED_SECRET_MAX];
+	char csums_alg[SHARED_SECRET_MAX];
+	u32 c_plan_ahead;
+	u32 c_delay_target;
+	u32 c_fill_target;
+	u32 c_max_rate;
+} __packed;
+
 enum drbd_conn_flags {
 	CF_WANT_LOSE = 1,
 	CF_DRY_RUN = 2,
 };
 
 struct p_protocol {
-	struct p_header head;
+	struct p_header80 head;
 	u32 protocol;
 	u32 after_sb_0p;
 	u32 after_sb_1p;
@@ -471,17 +498,17 @@
 } __packed;
 
 struct p_uuids {
-	struct p_header head;
+	struct p_header80 head;
 	u64 uuid[UI_EXTENDED_SIZE];
 } __packed;
 
 struct p_rs_uuid {
-	struct p_header head;
+	struct p_header80 head;
 	u64	    uuid;
 } __packed;
 
 struct p_sizes {
-	struct p_header head;
+	struct p_header80 head;
 	u64	    d_size;  /* size of disk */
 	u64	    u_size;  /* user requested size */
 	u64	    c_size;  /* current exported size */
@@ -491,18 +518,18 @@
 } __packed;
 
 struct p_state {
-	struct p_header head;
+	struct p_header80 head;
 	u32	    state;
 } __packed;
 
 struct p_req_state {
-	struct p_header head;
+	struct p_header80 head;
 	u32	    mask;
 	u32	    val;
 } __packed;
 
 struct p_req_state_reply {
-	struct p_header head;
+	struct p_header80 head;
 	u32	    retcode;
 } __packed;
 
@@ -517,7 +544,7 @@
 } __packed;
 
 struct p_discard {
-	struct p_header head;
+	struct p_header80 head;
 	u64	    block_id;
 	u32	    seq_num;
 	u32	    pad;
@@ -533,7 +560,7 @@
 };
 
 struct p_compressed_bm {
-	struct p_header head;
+	struct p_header80 head;
 	/* (encoding & 0x0f): actual encoding, see enum drbd_bitmap_code
 	 * (encoding & 0x80): polarity (set/unset) of first runlength
 	 * ((encoding >> 4) & 0x07): pad_bits, number of trailing zero bits
@@ -544,10 +571,10 @@
 	u8 code[0];
 } __packed;
 
-struct p_delay_probe {
-	struct p_header head;
-	u32	seq_num; /* sequence number to match the two probe packets */
-	u32	offset;	 /* usecs the probe got sent after the reference time point */
+struct p_delay_probe93 {
+	struct p_header80 head;
+	u32     seq_num; /* sequence number to match the two probe packets */
+	u32     offset;  /* usecs the probe got sent after the reference time point */
 } __packed;
 
 /* DCBP: Drbd Compressed Bitmap Packet ... */
@@ -594,7 +621,7 @@
  * so we need to use the fixed size 4KiB page size
  * most architechtures have used for a long time.
  */
-#define BM_PACKET_PAYLOAD_BYTES (4096 - sizeof(struct p_header))
+#define BM_PACKET_PAYLOAD_BYTES (4096 - sizeof(struct p_header80))
 #define BM_PACKET_WORDS (BM_PACKET_PAYLOAD_BYTES/sizeof(long))
 #define BM_PACKET_VLI_BYTES_MAX (4096 - sizeof(struct p_compressed_bm))
 #if (PAGE_SIZE < 4096)
@@ -603,13 +630,14 @@
 #endif
 
 union p_polymorph {
-        struct p_header          header;
+        union p_header           header;
         struct p_handshake       handshake;
         struct p_data            data;
         struct p_block_ack       block_ack;
         struct p_barrier         barrier;
         struct p_barrier_ack     barrier_ack;
         struct p_rs_param_89     rs_param_89;
+        struct p_rs_param_95     rs_param_95;
         struct p_protocol        protocol;
         struct p_sizes           sizes;
         struct p_uuids           uuids;
@@ -617,6 +645,8 @@
         struct p_req_state       req_state;
         struct p_req_state_reply req_state_reply;
         struct p_block_req       block_req;
+	struct p_delay_probe93   delay_probe93;
+	struct p_rs_uuid         rs_uuid;
 } __packed;
 
 /**********************************************************************/
@@ -697,7 +727,7 @@
 	struct list_head requests; /* requests before */
 	struct drbd_tl_epoch *next; /* pointer to the next barrier */
 	unsigned int br_number;  /* the barriers identifier. */
-	int n_req;	/* number of requests attached before this barrier */
+	int n_writes;	/* number of requests attached before this barrier */
 };
 
 struct drbd_request;
@@ -747,7 +777,7 @@
 struct drbd_epoch_entry {
 	struct drbd_work w;
 	struct hlist_node colision;
-	struct drbd_epoch *epoch;
+	struct drbd_epoch *epoch; /* for writes */
 	struct drbd_conf *mdev;
 	struct page *pages;
 	atomic_t pending_bios;
@@ -755,7 +785,10 @@
 	/* see comments on ee flag bits below */
 	unsigned long flags;
 	sector_t sector;
-	u64 block_id;
+	union {
+		u64 block_id;
+		struct digest_info *digest;
+	};
 };
 
 /* ee flag bits.
@@ -781,12 +814,16 @@
 	 * if any of those fail, we set this flag atomically
 	 * from the endio callback */
 	__EE_WAS_ERROR,
+
+	/* This ee has a pointer to a digest instead of a block id */
+	__EE_HAS_DIGEST,
 };
 #define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO)
 #define EE_MAY_SET_IN_SYNC     (1<<__EE_MAY_SET_IN_SYNC)
 #define EE_IS_BARRIER          (1<<__EE_IS_BARRIER)
 #define	EE_RESUBMITTED         (1<<__EE_RESUBMITTED)
 #define EE_WAS_ERROR           (1<<__EE_WAS_ERROR)
+#define EE_HAS_DIGEST          (1<<__EE_HAS_DIGEST)
 
 /* global flag bits */
 enum {
@@ -794,7 +831,6 @@
 	SIGNAL_ASENDER,		/* whether asender wants to be interrupted */
 	SEND_PING,		/* whether asender should send a ping asap */
 
-	STOP_SYNC_TIMER,	/* tell timer to cancel itself */
 	UNPLUG_QUEUED,		/* only relevant with kernel 2.4 */
 	UNPLUG_REMOTE,		/* sending a "UnplugRemote" could help */
 	MD_DIRTY,		/* current uuids and flags not yet on disk */
@@ -816,6 +852,7 @@
 	BITMAP_IO,		/* suspend application io;
 				   once no more io in flight, start bitmap io */
 	BITMAP_IO_QUEUED,       /* Started bitmap IO */
+	GO_DISKLESS,		/* Disk failed, local_cnt reached zero, we are going diskless */
 	RESYNC_AFTER_NEG,       /* Resync after online grow after the attach&negotiate finished. */
 	NET_CONGESTED,		/* The data socket is congested */
 
@@ -829,6 +866,8 @@
 				 * the peer, if it changed there as well. */
 	CONN_DRY_RUN,		/* Expect disconnect after resync handshake. */
 	GOT_PING_ACK,		/* set when we receive a ping_ack packet, misc wait gets woken */
+	NEW_CUR_UUID,		/* Create new current UUID when thawing IO */
+	AL_SUSPENDED,		/* Activity logging is currently suspended. */
 };
 
 struct drbd_bitmap; /* opaque for drbd_conf */
@@ -838,10 +877,6 @@
 
 /* THINK maybe we actually want to use the default "event/%s" worker threads
  * or similar in linux 2.6, which uses per cpu data and threads.
- *
- * To be general, this might need a spin_lock member.
- * For now, please use the mdev->req_lock to protect list_head,
- * see drbd_queue_work below.
  */
 struct drbd_work_queue {
 	struct list_head q;
@@ -915,6 +950,12 @@
 	WO_bio_barrier
 };
 
+struct fifo_buffer {
+	int *values;
+	unsigned int head_index;
+	unsigned int size;
+};
+
 struct drbd_conf {
 	/* things that are stored as / read from meta data on disk */
 	unsigned long flags;
@@ -936,9 +977,16 @@
 	unsigned int ko_count;
 	struct drbd_work  resync_work,
 			  unplug_work,
+			  go_diskless,
 			  md_sync_work;
 	struct timer_list resync_timer;
 	struct timer_list md_sync_timer;
+#ifdef DRBD_DEBUG_MD_SYNC
+	struct {
+		unsigned int line;
+		const char* func;
+	} last_md_mark_dirty;
+#endif
 
 	/* Used after attach while negotiating new disk state. */
 	union drbd_state new_state_tmp;
@@ -946,6 +994,7 @@
 	union drbd_state state;
 	wait_queue_head_t misc_wait;
 	wait_queue_head_t state_wait;  /* upon each state change. */
+	wait_queue_head_t net_cnt_wait;
 	unsigned int send_cnt;
 	unsigned int recv_cnt;
 	unsigned int read_cnt;
@@ -974,12 +1023,16 @@
 	unsigned long rs_start;
 	/* cumulated time in PausedSyncX state [unit jiffies] */
 	unsigned long rs_paused;
-	/* block not up-to-date at mark [unit BM_BLOCK_SIZE] */
-	unsigned long rs_mark_left;
-	/* marks's time [unit jiffies] */
-	unsigned long rs_mark_time;
-	/* skipped because csum was equeal [unit BM_BLOCK_SIZE] */
+	/* skipped because csum was equal [unit BM_BLOCK_SIZE] */
 	unsigned long rs_same_csum;
+#define DRBD_SYNC_MARKS 8
+#define DRBD_SYNC_MARK_STEP (3*HZ)
+	/* block not up-to-date at mark [unit BM_BLOCK_SIZE] */
+	unsigned long rs_mark_left[DRBD_SYNC_MARKS];
+	/* marks's time [unit jiffies] */
+	unsigned long rs_mark_time[DRBD_SYNC_MARKS];
+	/* current index into rs_mark_{left,time} */
+	int rs_last_mark;
 
 	/* where does the admin want us to start? (sector) */
 	sector_t ov_start_sector;
@@ -1012,10 +1065,10 @@
 	spinlock_t epoch_lock;
 	unsigned int epochs;
 	enum write_ordering_e write_ordering;
-	struct list_head active_ee; /* IO in progress */
-	struct list_head sync_ee;   /* IO in progress */
+	struct list_head active_ee; /* IO in progress (P_DATA gets written to disk) */
+	struct list_head sync_ee;   /* IO in progress (P_RS_DATA_REPLY gets written to disk) */
 	struct list_head done_ee;   /* send ack */
-	struct list_head read_ee;   /* IO in progress */
+	struct list_head read_ee;   /* IO in progress (any read) */
 	struct list_head net_ee;    /* zero-copy network send in progress */
 	struct hlist_head *ee_hash; /* is proteced by req_lock! */
 	unsigned int ee_hash_s;
@@ -1026,7 +1079,8 @@
 	int next_barrier_nr;
 	struct hlist_head *app_reads_hash; /* is proteced by req_lock */
 	struct list_head resync_reads;
-	atomic_t pp_in_use;
+	atomic_t pp_in_use;		/* allocated from page pool */
+	atomic_t pp_in_use_by_net;	/* sendpage()d, still referenced by tcp */
 	wait_queue_head_t ee_wait;
 	struct page *md_io_page;	/* one page buffer for md_io */
 	struct page *md_io_tmpp;	/* for logical_block_size != 512 */
@@ -1054,6 +1108,15 @@
 	u64 ed_uuid; /* UUID of the exposed data */
 	struct mutex state_mutex;
 	char congestion_reason;  /* Why we where congested... */
+	atomic_t rs_sect_in; /* for incoming resync data rate, SyncTarget */
+	atomic_t rs_sect_ev; /* for submitted resync data rate, both */
+	int rs_last_sect_ev; /* counter to compare with */
+	int rs_last_events;  /* counter of read or write "events" (unit sectors)
+			      * on the lower level device when we last looked. */
+	int c_sync_rate; /* current resync rate after syncer throttle magic */
+	struct fifo_buffer rs_plan_s; /* correction values of resync planer */
+	int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */
+	int rs_planed;    /* resync sectors already planed */
 };
 
 static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
@@ -1138,6 +1201,8 @@
 extern void tl_release(struct drbd_conf *mdev, unsigned int barrier_nr,
 		       unsigned int set_size);
 extern void tl_clear(struct drbd_conf *mdev);
+enum drbd_req_event;
+extern void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what);
 extern void _tl_add_barrier(struct drbd_conf *, struct drbd_tl_epoch *);
 extern void drbd_free_sock(struct drbd_conf *mdev);
 extern int drbd_send(struct drbd_conf *mdev, struct socket *sock,
@@ -1150,12 +1215,12 @@
 extern int _drbd_send_state(struct drbd_conf *mdev);
 extern int drbd_send_state(struct drbd_conf *mdev);
 extern int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
-			enum drbd_packets cmd, struct p_header *h,
+			enum drbd_packets cmd, struct p_header80 *h,
 			size_t size, unsigned msg_flags);
 #define USE_DATA_SOCKET 1
 #define USE_META_SOCKET 0
 extern int drbd_send_cmd(struct drbd_conf *mdev, int use_data_socket,
-			enum drbd_packets cmd, struct p_header *h,
+			enum drbd_packets cmd, struct p_header80 *h,
 			size_t size);
 extern int drbd_send_cmd2(struct drbd_conf *mdev, enum drbd_packets cmd,
 			char *data, size_t size);
@@ -1167,7 +1232,7 @@
 extern int drbd_send_ack_rp(struct drbd_conf *mdev, enum drbd_packets cmd,
 			struct p_block_req *rp);
 extern int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd,
-			struct p_data *dp);
+			struct p_data *dp, int data_size);
 extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd,
 			    sector_t sector, int blksize, u64 block_id);
 extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
@@ -1201,7 +1266,13 @@
 extern void drbd_md_set_flag(struct drbd_conf *mdev, int flags) __must_hold(local);
 extern void drbd_md_clear_flag(struct drbd_conf *mdev, int flags)__must_hold(local);
 extern int drbd_md_test_flag(struct drbd_backing_dev *, int);
+#ifndef DRBD_DEBUG_MD_SYNC
 extern void drbd_md_mark_dirty(struct drbd_conf *mdev);
+#else
+#define drbd_md_mark_dirty(m)	drbd_md_mark_dirty_(m, __LINE__ , __func__ )
+extern void drbd_md_mark_dirty_(struct drbd_conf *mdev,
+		unsigned int line, const char *func);
+#endif
 extern void drbd_queue_bitmap_io(struct drbd_conf *mdev,
 				 int (*io_fn)(struct drbd_conf *),
 				 void (*done)(struct drbd_conf *, int),
@@ -1209,6 +1280,7 @@
 extern int drbd_bmio_set_n_write(struct drbd_conf *mdev);
 extern int drbd_bmio_clear_n_write(struct drbd_conf *mdev);
 extern int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), char *why);
+extern void drbd_go_diskless(struct drbd_conf *mdev);
 
 
 /* Meta data layout
@@ -1264,6 +1336,8 @@
  * Bit 1 ==> local node thinks this block needs to be synced.
  */
 
+#define SLEEP_TIME (HZ/10)
+
 #define BM_BLOCK_SHIFT  12			 /* 4k per bit */
 #define BM_BLOCK_SIZE	 (1<<BM_BLOCK_SHIFT)
 /* (9+3) : 512 bytes @ 8 bits; representing 16M storage
@@ -1335,11 +1409,13 @@
 #endif
 
 /* Sector shift value for the "hash" functions of tl_hash and ee_hash tables.
- * With a value of 6 all IO in one 32K block make it to the same slot of the
+ * With a value of 8 all IO in one 128K block make it to the same slot of the
  * hash table. */
-#define HT_SHIFT 6
+#define HT_SHIFT 8
 #define DRBD_MAX_SEGMENT_SIZE (1U<<(9+HT_SHIFT))
 
+#define DRBD_MAX_SIZE_H80_PACKET (1 << 15) /* The old header only allows packets up to 32Kib data */
+
 /* Number of elements in the app_reads_hash */
 #define APP_R_HSIZE 15
 
@@ -1369,6 +1445,7 @@
 /* bm_find_next variants for use while you hold drbd_bm_lock() */
 extern unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo);
 extern unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo);
+extern unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev);
 extern unsigned long drbd_bm_total_weight(struct drbd_conf *mdev);
 extern int drbd_bm_rs_done(struct drbd_conf *mdev);
 /* for receive_bitmap */
@@ -1421,7 +1498,8 @@
 extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local);
 extern int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role,
 		int force);
-enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev);
+extern enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev);
+extern void drbd_try_outdate_peer_async(struct drbd_conf *mdev);
 extern int drbd_khelper(struct drbd_conf *mdev, char *cmd);
 
 /* drbd_worker.c */
@@ -1467,10 +1545,12 @@
 extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int);
 extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int);
 extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int);
+extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int);
 
 extern void resync_timer_fn(unsigned long data);
 
 /* drbd_receiver.c */
+extern int drbd_rs_should_slow_down(struct drbd_conf *mdev);
 extern int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
 		const unsigned rw, const int fault_type);
 extern int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list);
@@ -1479,7 +1559,10 @@
 					    sector_t sector,
 					    unsigned int data_size,
 					    gfp_t gfp_mask) __must_hold(local);
-extern void drbd_free_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e);
+extern void drbd_free_some_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
+		int is_net);
+#define drbd_free_ee(m,e)	drbd_free_some_ee(m, e, 0)
+#define drbd_free_net_ee(m,e)	drbd_free_some_ee(m, e, 1)
 extern void drbd_wait_ee_list_empty(struct drbd_conf *mdev,
 		struct list_head *head);
 extern void _drbd_wait_ee_list_empty(struct drbd_conf *mdev,
@@ -1487,6 +1570,7 @@
 extern void drbd_set_recv_tcq(struct drbd_conf *mdev, int tcq_enabled);
 extern void _drbd_clear_done_ee(struct drbd_conf *mdev, struct list_head *to_be_freed);
 extern void drbd_flush_workqueue(struct drbd_conf *mdev);
+extern void drbd_free_tl_hash(struct drbd_conf *mdev);
 
 /* yes, there is kernel_setsockopt, but only since 2.6.18. we don't need to
  * mess with get_fs/set_fs, we know we are KERNEL_DS always. */
@@ -1600,6 +1684,8 @@
 #define susp_MASK 1
 #define user_isp_MASK 1
 #define aftr_isp_MASK 1
+#define susp_nod_MASK 1
+#define susp_fen_MASK 1
 
 #define NS(T, S) \
 	({ union drbd_state mask; mask.i = 0; mask.T = T##_MASK; mask; }), \
@@ -1856,13 +1942,6 @@
 }
 
 static inline void
-_drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
-{
-	list_add_tail(&w->list, &q->q);
-	up(&q->s);
-}
-
-static inline void
 drbd_queue_work_front(struct drbd_work_queue *q, struct drbd_work *w)
 {
 	unsigned long flags;
@@ -1899,19 +1978,19 @@
 static inline int drbd_send_short_cmd(struct drbd_conf *mdev,
 	enum drbd_packets cmd)
 {
-	struct p_header h;
+	struct p_header80 h;
 	return drbd_send_cmd(mdev, USE_DATA_SOCKET, cmd, &h, sizeof(h));
 }
 
 static inline int drbd_send_ping(struct drbd_conf *mdev)
 {
-	struct p_header h;
+	struct p_header80 h;
 	return drbd_send_cmd(mdev, USE_META_SOCKET, P_PING, &h, sizeof(h));
 }
 
 static inline int drbd_send_ping_ack(struct drbd_conf *mdev)
 {
-	struct p_header h;
+	struct p_header80 h;
 	return drbd_send_cmd(mdev, USE_META_SOCKET, P_PING_ACK, &h, sizeof(h));
 }
 
@@ -2013,7 +2092,7 @@
 static inline void put_net_conf(struct drbd_conf *mdev)
 {
 	if (atomic_dec_and_test(&mdev->net_cnt))
-		wake_up(&mdev->misc_wait);
+		wake_up(&mdev->net_cnt_wait);
 }
 
 /**
@@ -2044,10 +2123,14 @@
 
 static inline void put_ldev(struct drbd_conf *mdev)
 {
+	int i = atomic_dec_return(&mdev->local_cnt);
 	__release(local);
-	if (atomic_dec_and_test(&mdev->local_cnt))
+	D_ASSERT(i >= 0);
+	if (i == 0) {
+		if (mdev->state.disk == D_FAILED)
+			drbd_go_diskless(mdev);
 		wake_up(&mdev->misc_wait);
-	D_ASSERT(atomic_read(&mdev->local_cnt) >= 0);
+	}
 }
 
 #ifndef __CHECKER__
@@ -2179,11 +2262,16 @@
 	return 1;
 }
 
+static inline int is_susp(union drbd_state s)
+{
+	return s.susp || s.susp_nod || s.susp_fen;
+}
+
 static inline int __inc_ap_bio_cond(struct drbd_conf *mdev)
 {
 	int mxb = drbd_get_max_buffers(mdev);
 
-	if (mdev->state.susp)
+	if (is_susp(mdev->state))
 		return 0;
 	if (test_bit(SUSPEND_IO, &mdev->flags))
 		return 0;
@@ -2321,8 +2409,7 @@
 	if (test_bit(MD_NO_BARRIER, &mdev->flags))
 		return;
 
-	r = blkdev_issue_flush(mdev->ldev->md_bdev, GFP_KERNEL, NULL,
-			BLKDEV_IFL_WAIT);
+	r = blkdev_issue_flush(mdev->ldev->md_bdev, GFP_KERNEL, NULL);
 	if (r) {
 		set_bit(MD_NO_BARRIER, &mdev->flags);
 		dev_err(DEV, "meta data flush failed with status %d, disabling md-flushes\n", r);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index fa650dd..c5dfe64 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -32,7 +32,7 @@
 #include <asm/types.h>
 #include <net/sock.h>
 #include <linux/ctype.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/proc_fs.h>
@@ -64,6 +64,7 @@
 	struct completion *done;
 };
 
+static DEFINE_MUTEX(drbd_main_mutex);
 int drbdd_init(struct drbd_thread *);
 int drbd_worker(struct drbd_thread *);
 int drbd_asender(struct drbd_thread *);
@@ -77,6 +78,7 @@
 static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused);
 static void md_sync_timer_fn(unsigned long data);
 static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused);
+static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused);
 
 MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, "
 	      "Lars Ellenberg <lars@linbit.com>");
@@ -199,7 +201,7 @@
 	INIT_LIST_HEAD(&b->w.list);
 	b->next = NULL;
 	b->br_number = 4711;
-	b->n_req = 0;
+	b->n_writes = 0;
 	b->w.cb = NULL; /* if this is != NULL, we need to dec_ap_pending in tl_clear */
 
 	mdev->oldest_tle = b;
@@ -240,7 +242,7 @@
 	INIT_LIST_HEAD(&new->w.list);
 	new->w.cb = NULL; /* if this is != NULL, we need to dec_ap_pending in tl_clear */
 	new->next = NULL;
-	new->n_req = 0;
+	new->n_writes = 0;
 
 	newest_before = mdev->newest_tle;
 	/* never send a barrier number == 0, because that is special-cased
@@ -284,9 +286,9 @@
 			barrier_nr, b->br_number);
 		goto bail;
 	}
-	if (b->n_req != set_size) {
-		dev_err(DEV, "BAD! BarrierAck #%u received with n_req=%u, expected n_req=%u!\n",
-			barrier_nr, set_size, b->n_req);
+	if (b->n_writes != set_size) {
+		dev_err(DEV, "BAD! BarrierAck #%u received with n_writes=%u, expected n_writes=%u!\n",
+			barrier_nr, set_size, b->n_writes);
 		goto bail;
 	}
 
@@ -333,6 +335,82 @@
 	drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
 }
 
+/**
+ * _tl_restart() - Walks the transfer log, and applies an action to all requests
+ * @mdev:	DRBD device.
+ * @what:       The action/event to perform with all request objects
+ *
+ * @what might be one of connection_lost_while_pending, resend, fail_frozen_disk_io,
+ * restart_frozen_disk_io.
+ */
+static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
+{
+	struct drbd_tl_epoch *b, *tmp, **pn;
+	struct list_head *le, *tle, carry_reads;
+	struct drbd_request *req;
+	int rv, n_writes, n_reads;
+
+	b = mdev->oldest_tle;
+	pn = &mdev->oldest_tle;
+	while (b) {
+		n_writes = 0;
+		n_reads = 0;
+		INIT_LIST_HEAD(&carry_reads);
+		list_for_each_safe(le, tle, &b->requests) {
+			req = list_entry(le, struct drbd_request, tl_requests);
+			rv = _req_mod(req, what);
+
+			n_writes += (rv & MR_WRITE) >> MR_WRITE_SHIFT;
+			n_reads  += (rv & MR_READ) >> MR_READ_SHIFT;
+		}
+		tmp = b->next;
+
+		if (n_writes) {
+			if (what == resend) {
+				b->n_writes = n_writes;
+				if (b->w.cb == NULL) {
+					b->w.cb = w_send_barrier;
+					inc_ap_pending(mdev);
+					set_bit(CREATE_BARRIER, &mdev->flags);
+				}
+
+				drbd_queue_work(&mdev->data.work, &b->w);
+			}
+			pn = &b->next;
+		} else {
+			if (n_reads)
+				list_add(&carry_reads, &b->requests);
+			/* there could still be requests on that ring list,
+			 * in case local io is still pending */
+			list_del(&b->requests);
+
+			/* dec_ap_pending corresponding to queue_barrier.
+			 * the newest barrier may not have been queued yet,
+			 * in which case w.cb is still NULL. */
+			if (b->w.cb != NULL)
+				dec_ap_pending(mdev);
+
+			if (b == mdev->newest_tle) {
+				/* recycle, but reinit! */
+				D_ASSERT(tmp == NULL);
+				INIT_LIST_HEAD(&b->requests);
+				list_splice(&carry_reads, &b->requests);
+				INIT_LIST_HEAD(&b->w.list);
+				b->w.cb = NULL;
+				b->br_number = net_random();
+				b->n_writes = 0;
+
+				*pn = b;
+				break;
+			}
+			*pn = tmp;
+			kfree(b);
+		}
+		b = tmp;
+		list_splice(&carry_reads, &b->requests);
+	}
+}
+
 
 /**
  * tl_clear() - Clears all requests and &struct drbd_tl_epoch objects out of the TL
@@ -344,48 +422,12 @@
  */
 void tl_clear(struct drbd_conf *mdev)
 {
-	struct drbd_tl_epoch *b, *tmp;
 	struct list_head *le, *tle;
 	struct drbd_request *r;
-	int new_initial_bnr = net_random();
 
 	spin_lock_irq(&mdev->req_lock);
 
-	b = mdev->oldest_tle;
-	while (b) {
-		list_for_each_safe(le, tle, &b->requests) {
-			r = list_entry(le, struct drbd_request, tl_requests);
-			/* It would be nice to complete outside of spinlock.
-			 * But this is easier for now. */
-			_req_mod(r, connection_lost_while_pending);
-		}
-		tmp = b->next;
-
-		/* there could still be requests on that ring list,
-		 * in case local io is still pending */
-		list_del(&b->requests);
-
-		/* dec_ap_pending corresponding to queue_barrier.
-		 * the newest barrier may not have been queued yet,
-		 * in which case w.cb is still NULL. */
-		if (b->w.cb != NULL)
-			dec_ap_pending(mdev);
-
-		if (b == mdev->newest_tle) {
-			/* recycle, but reinit! */
-			D_ASSERT(tmp == NULL);
-			INIT_LIST_HEAD(&b->requests);
-			INIT_LIST_HEAD(&b->w.list);
-			b->w.cb = NULL;
-			b->br_number = new_initial_bnr;
-			b->n_req = 0;
-
-			mdev->oldest_tle = b;
-			break;
-		}
-		kfree(b);
-		b = tmp;
-	}
+	_tl_restart(mdev, connection_lost_while_pending);
 
 	/* we expect this list to be empty. */
 	D_ASSERT(list_empty(&mdev->out_of_sequence_requests));
@@ -401,6 +443,15 @@
 	/* ensure bit indicating barrier is required is clear */
 	clear_bit(CREATE_BARRIER, &mdev->flags);
 
+	memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *));
+
+	spin_unlock_irq(&mdev->req_lock);
+}
+
+void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
+{
+	spin_lock_irq(&mdev->req_lock);
+	_tl_restart(mdev, what);
 	spin_unlock_irq(&mdev->req_lock);
 }
 
@@ -455,7 +506,7 @@
 static int is_valid_state_transition(struct drbd_conf *,
 				     union drbd_state, union drbd_state);
 static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state os,
-				       union drbd_state ns, int *warn_sync_abort);
+				       union drbd_state ns, const char **warn_sync_abort);
 int drbd_send_state_req(struct drbd_conf *,
 			union drbd_state, union drbd_state);
 
@@ -605,7 +656,7 @@
 	    drbd_role_str(ns.peer),
 	    drbd_disk_str(ns.disk),
 	    drbd_disk_str(ns.pdsk),
-	    ns.susp ? 's' : 'r',
+	    is_susp(ns) ? 's' : 'r',
 	    ns.aftr_isp ? 'a' : '-',
 	    ns.peer_isp ? 'p' : '-',
 	    ns.user_isp ? 'u' : '-'
@@ -763,7 +814,7 @@
  * to D_UNKNOWN. This rule and many more along those lines are in this function.
  */
 static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state os,
-				       union drbd_state ns, int *warn_sync_abort)
+				       union drbd_state ns, const char **warn_sync_abort)
 {
 	enum drbd_fencing_p fp;
 
@@ -778,9 +829,10 @@
 	    os.conn <= C_DISCONNECTING)
 		ns.conn = os.conn;
 
-	/* After a network error (+C_TEAR_DOWN) only C_UNCONNECTED or C_DISCONNECTING can follow */
+	/* After a network error (+C_TEAR_DOWN) only C_UNCONNECTED or C_DISCONNECTING can follow.
+	 * If you try to go into some Sync* state, that shall fail (elsewhere). */
 	if (os.conn >= C_TIMEOUT && os.conn <= C_TEAR_DOWN &&
-	    ns.conn != C_UNCONNECTED && ns.conn != C_DISCONNECTING)
+	    ns.conn != C_UNCONNECTED && ns.conn != C_DISCONNECTING && ns.conn <= C_TEAR_DOWN)
 		ns.conn = os.conn;
 
 	/* After C_DISCONNECTING only C_STANDALONE may follow */
@@ -798,14 +850,13 @@
 	if (ns.conn == C_STANDALONE && ns.disk == D_DISKLESS && ns.role == R_SECONDARY)
 		ns.aftr_isp = 0;
 
-	if (ns.conn <= C_DISCONNECTING && ns.disk == D_DISKLESS)
-		ns.pdsk = D_UNKNOWN;
-
 	/* Abort resync if a disk fails/detaches */
 	if (os.conn > C_CONNECTED && ns.conn > C_CONNECTED &&
 	    (ns.disk <= D_FAILED || ns.pdsk <= D_FAILED)) {
 		if (warn_sync_abort)
-			*warn_sync_abort = 1;
+			*warn_sync_abort =
+				os.conn == C_VERIFY_S || os.conn == C_VERIFY_T ?
+				"Online-verify" : "Resync";
 		ns.conn = C_CONNECTED;
 	}
 
@@ -876,7 +927,12 @@
 	if (fp == FP_STONITH &&
 	    (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED) &&
 	    !(os.role == R_PRIMARY && os.conn < C_CONNECTED && os.pdsk > D_OUTDATED))
-		ns.susp = 1;
+		ns.susp_fen = 1; /* Suspend IO while fence-peer handler runs (peer lost) */
+
+	if (mdev->sync_conf.on_no_data == OND_SUSPEND_IO &&
+	    (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE) &&
+	    !(os.role == R_PRIMARY && os.disk < D_UP_TO_DATE && os.pdsk < D_UP_TO_DATE))
+		ns.susp_nod = 1; /* Suspend IO while no data available (no accessible data available) */
 
 	if (ns.aftr_isp || ns.peer_isp || ns.user_isp) {
 		if (ns.conn == C_SYNC_SOURCE)
@@ -912,6 +968,12 @@
 	}
 }
 
+static void drbd_resume_al(struct drbd_conf *mdev)
+{
+	if (test_and_clear_bit(AL_SUSPENDED, &mdev->flags))
+		dev_info(DEV, "Resumed AL updates\n");
+}
+
 /**
  * __drbd_set_state() - Set a new DRBD state
  * @mdev:	DRBD device.
@@ -927,7 +989,7 @@
 {
 	union drbd_state os;
 	int rv = SS_SUCCESS;
-	int warn_sync_abort = 0;
+	const char *warn_sync_abort = NULL;
 	struct after_state_chg_work *ascw;
 
 	os = mdev->state;
@@ -946,14 +1008,8 @@
 			/* If the old state was illegal as well, then let
 			   this happen...*/
 
-			if (is_valid_state(mdev, os) == rv) {
-				dev_err(DEV, "Considering state change from bad state. "
-				    "Error would be: '%s'\n",
-				    drbd_set_st_err_str(rv));
-				print_st(mdev, "old", os);
-				print_st(mdev, "new", ns);
+			if (is_valid_state(mdev, os) == rv)
 				rv = is_valid_state_transition(mdev, ns, os);
-			}
 		} else
 			rv = is_valid_state_transition(mdev, ns, os);
 	}
@@ -965,7 +1021,7 @@
 	}
 
 	if (warn_sync_abort)
-		dev_warn(DEV, "Resync aborted.\n");
+		dev_warn(DEV, "%s aborted.\n", warn_sync_abort);
 
 	{
 		char *pbp, pb[300];
@@ -976,7 +1032,10 @@
 		PSC(conn);
 		PSC(disk);
 		PSC(pdsk);
-		PSC(susp);
+		if (is_susp(ns) != is_susp(os))
+			pbp += sprintf(pbp, "susp( %s -> %s ) ",
+				       drbd_susp_str(is_susp(os)),
+				       drbd_susp_str(is_susp(ns)));
 		PSC(aftr_isp);
 		PSC(peer_isp);
 		PSC(user_isp);
@@ -1001,12 +1060,6 @@
 	wake_up(&mdev->misc_wait);
 	wake_up(&mdev->state_wait);
 
-	/*   post-state-change actions   */
-	if (os.conn >= C_SYNC_SOURCE   && ns.conn <= C_CONNECTED) {
-		set_bit(STOP_SYNC_TIMER, &mdev->flags);
-		mod_timer(&mdev->resync_timer, jiffies);
-	}
-
 	/* aborted verify run. log the last position */
 	if ((os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) &&
 	    ns.conn < C_CONNECTED) {
@@ -1019,41 +1072,42 @@
 	if ((os.conn == C_PAUSED_SYNC_T || os.conn == C_PAUSED_SYNC_S) &&
 	    (ns.conn == C_SYNC_TARGET  || ns.conn == C_SYNC_SOURCE)) {
 		dev_info(DEV, "Syncer continues.\n");
-		mdev->rs_paused += (long)jiffies-(long)mdev->rs_mark_time;
-		if (ns.conn == C_SYNC_TARGET) {
-			if (!test_and_clear_bit(STOP_SYNC_TIMER, &mdev->flags))
-				mod_timer(&mdev->resync_timer, jiffies);
-			/* This if (!test_bit) is only needed for the case
-			   that a device that has ceased to used its timer,
-			   i.e. it is already in drbd_resync_finished() gets
-			   paused and resumed. */
-		}
+		mdev->rs_paused += (long)jiffies
+				  -(long)mdev->rs_mark_time[mdev->rs_last_mark];
+		if (ns.conn == C_SYNC_TARGET)
+			mod_timer(&mdev->resync_timer, jiffies);
 	}
 
 	if ((os.conn == C_SYNC_TARGET  || os.conn == C_SYNC_SOURCE) &&
 	    (ns.conn == C_PAUSED_SYNC_T || ns.conn == C_PAUSED_SYNC_S)) {
 		dev_info(DEV, "Resync suspended\n");
-		mdev->rs_mark_time = jiffies;
-		if (ns.conn == C_PAUSED_SYNC_T)
-			set_bit(STOP_SYNC_TIMER, &mdev->flags);
+		mdev->rs_mark_time[mdev->rs_last_mark] = jiffies;
 	}
 
 	if (os.conn == C_CONNECTED &&
 	    (ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T)) {
+		unsigned long now = jiffies;
+		int i;
+
 		mdev->ov_position = 0;
-		mdev->rs_total =
-		mdev->rs_mark_left = drbd_bm_bits(mdev);
+		mdev->rs_total = drbd_bm_bits(mdev);
 		if (mdev->agreed_pro_version >= 90)
 			set_ov_position(mdev, ns.conn);
 		else
 			mdev->ov_start_sector = 0;
 		mdev->ov_left = mdev->rs_total
 			      - BM_SECT_TO_BIT(mdev->ov_position);
-		mdev->rs_start     =
-		mdev->rs_mark_time = jiffies;
+		mdev->rs_start = now;
+		mdev->rs_last_events = 0;
+		mdev->rs_last_sect_ev = 0;
 		mdev->ov_last_oos_size = 0;
 		mdev->ov_last_oos_start = 0;
 
+		for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+			mdev->rs_mark_left[i] = mdev->rs_total;
+			mdev->rs_mark_time[i] = now;
+		}
+
 		if (ns.conn == C_VERIFY_S) {
 			dev_info(DEV, "Starting Online Verify from sector %llu\n",
 					(unsigned long long)mdev->ov_position);
@@ -1106,6 +1160,10 @@
 	    ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT)
 		drbd_thread_restart_nowait(&mdev->receiver);
 
+	/* Resume AL writing if we get a connection */
+	if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)
+		drbd_resume_al(mdev);
+
 	ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC);
 	if (ascw) {
 		ascw->os = os;
@@ -1164,6 +1222,8 @@
 			   union drbd_state ns, enum chg_state_flags flags)
 {
 	enum drbd_fencing_p fp;
+	enum drbd_req_event what = nothing;
+	union drbd_state nsm = (union drbd_state){ .i = -1 };
 
 	if (os.conn != C_CONNECTED && ns.conn == C_CONNECTED) {
 		clear_bit(CRASHED_PRIMARY, &mdev->flags);
@@ -1187,17 +1247,49 @@
 	/* Here we have the actions that are performed after a
 	   state change. This function might sleep */
 
-	if (fp == FP_STONITH && ns.susp) {
-		/* case1: The outdate peer handler is successful:
-		 * case2: The connection was established again: */
-		if ((os.pdsk > D_OUTDATED  && ns.pdsk <= D_OUTDATED) ||
-		    (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)) {
+	nsm.i = -1;
+	if (ns.susp_nod) {
+		if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
+			if (ns.conn == C_CONNECTED)
+				what = resend, nsm.susp_nod = 0;
+			else /* ns.conn > C_CONNECTED */
+				dev_err(DEV, "Unexpected Resynd going on!\n");
+		}
+
+		if (os.disk == D_ATTACHING && ns.disk > D_ATTACHING)
+			what = restart_frozen_disk_io, nsm.susp_nod = 0;
+
+	}
+
+	if (ns.susp_fen) {
+		/* case1: The outdate peer handler is successful: */
+		if (os.pdsk > D_OUTDATED  && ns.pdsk <= D_OUTDATED) {
 			tl_clear(mdev);
+			if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
+				drbd_uuid_new_current(mdev);
+				clear_bit(NEW_CUR_UUID, &mdev->flags);
+				drbd_md_sync(mdev);
+			}
 			spin_lock_irq(&mdev->req_lock);
-			_drbd_set_state(_NS(mdev, susp, 0), CS_VERBOSE, NULL);
+			_drbd_set_state(_NS(mdev, susp_fen, 0), CS_VERBOSE, NULL);
 			spin_unlock_irq(&mdev->req_lock);
 		}
+		/* case2: The connection was established again: */
+		if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
+			clear_bit(NEW_CUR_UUID, &mdev->flags);
+			what = resend;
+			nsm.susp_fen = 0;
+		}
 	}
+
+	if (what != nothing) {
+		spin_lock_irq(&mdev->req_lock);
+		_tl_restart(mdev, what);
+		nsm.i &= mdev->state.i;
+		_drbd_set_state(mdev, nsm, CS_VERBOSE, NULL);
+		spin_unlock_irq(&mdev->req_lock);
+	}
+
 	/* Do not change the order of the if above and the two below... */
 	if (os.pdsk == D_DISKLESS && ns.pdsk > D_DISKLESS) {      /* attach on the peer */
 		drbd_send_uuids(mdev);
@@ -1216,16 +1308,22 @@
 		if (get_ldev(mdev)) {
 			if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) &&
 			    mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
-				drbd_uuid_new_current(mdev);
-				drbd_send_uuids(mdev);
+				if (is_susp(mdev->state)) {
+					set_bit(NEW_CUR_UUID, &mdev->flags);
+				} else {
+					drbd_uuid_new_current(mdev);
+					drbd_send_uuids(mdev);
+				}
 			}
 			put_ldev(mdev);
 		}
 	}
 
 	if (ns.pdsk < D_INCONSISTENT && get_ldev(mdev)) {
-		if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0)
+		if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0) {
 			drbd_uuid_new_current(mdev);
+			drbd_send_uuids(mdev);
+		}
 
 		/* D_DISKLESS Peer becomes secondary */
 		if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
@@ -1267,42 +1365,51 @@
 	    os.disk > D_INCONSISTENT && ns.disk == D_INCONSISTENT)
 		drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL, "set_n_write from invalidate");
 
+	/* first half of local IO error */
 	if (os.disk > D_FAILED && ns.disk == D_FAILED) {
-		enum drbd_io_error_p eh;
+		enum drbd_io_error_p eh = EP_PASS_ON;
 
-		eh = EP_PASS_ON;
+		if (drbd_send_state(mdev))
+			dev_warn(DEV, "Notified peer that my disk is broken.\n");
+		else
+			dev_err(DEV, "Sending state for drbd_io_error() failed\n");
+
+		drbd_rs_cancel_all(mdev);
+
 		if (get_ldev_if_state(mdev, D_FAILED)) {
 			eh = mdev->ldev->dc.on_io_error;
 			put_ldev(mdev);
 		}
-
-		drbd_rs_cancel_all(mdev);
-		/* since get_ldev() only works as long as disk>=D_INCONSISTENT,
-		   and it is D_DISKLESS here, local_cnt can only go down, it can
-		   not increase... It will reach zero */
-		wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));
-		mdev->rs_total = 0;
-		mdev->rs_failed = 0;
-		atomic_set(&mdev->rs_pending_cnt, 0);
-
-		spin_lock_irq(&mdev->req_lock);
-		_drbd_set_state(_NS(mdev, disk, D_DISKLESS), CS_HARD, NULL);
-		spin_unlock_irq(&mdev->req_lock);
-
 		if (eh == EP_CALL_HELPER)
 			drbd_khelper(mdev, "local-io-error");
 	}
 
+
+	/* second half of local IO error handling,
+	 * after local_cnt references have reached zero: */
+	if (os.disk == D_FAILED && ns.disk == D_DISKLESS) {
+		mdev->rs_total = 0;
+		mdev->rs_failed = 0;
+		atomic_set(&mdev->rs_pending_cnt, 0);
+	}
+
 	if (os.disk > D_DISKLESS && ns.disk == D_DISKLESS) {
+		/* We must still be diskless,
+		 * re-attach has to be serialized with this! */
+		if (mdev->state.disk != D_DISKLESS)
+			dev_err(DEV,
+				"ASSERT FAILED: disk is %s while going diskless\n",
+				drbd_disk_str(mdev->state.disk));
 
-		if (os.disk == D_FAILED) /* && ns.disk == D_DISKLESS*/ {
-			if (drbd_send_state(mdev))
-				dev_warn(DEV, "Notified peer that my disk is broken.\n");
-			else
-				dev_err(DEV, "Sending state in drbd_io_error() failed\n");
-		}
+		/* we cannot assert local_cnt == 0 here, as get_ldev_if_state
+		 * will inc/dec it frequently. Since we became D_DISKLESS, no
+		 * one has touched the protected members anymore, though, so we
+		 * are safe to free them here. */
+		if (drbd_send_state(mdev))
+			dev_warn(DEV, "Notified peer that I detached my disk.\n");
+		else
+			dev_err(DEV, "Sending state for detach failed\n");
 
-		wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));
 		lc_destroy(mdev->resync);
 		mdev->resync = NULL;
 		lc_destroy(mdev->act_log);
@@ -1311,8 +1418,10 @@
 			drbd_free_bc(mdev->ldev);
 			mdev->ldev = NULL;);
 
-		if (mdev->md_io_tmpp)
+		if (mdev->md_io_tmpp) {
 			__free_page(mdev->md_io_tmpp);
+			mdev->md_io_tmpp = NULL;
+		}
 	}
 
 	/* Disks got bigger while they were detached */
@@ -1328,6 +1437,15 @@
 	    (os.user_isp && !ns.user_isp))
 		resume_next_sg(mdev);
 
+	/* sync target done with resync.  Explicitly notify peer, even though
+	 * it should (at least for non-empty resyncs) already know itself. */
+	if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED)
+		drbd_send_state(mdev);
+
+	/* free tl_hash if we Got thawed and are C_STANDALONE */
+	if (ns.conn == C_STANDALONE && !is_susp(ns) && mdev->tl_hash)
+		drbd_free_tl_hash(mdev);
+
 	/* Upon network connection, we need to start the receiver */
 	if (os.conn == C_STANDALONE && ns.conn == C_UNCONNECTED)
 		drbd_thread_start(&mdev->receiver);
@@ -1554,7 +1672,7 @@
 
 /* the appropriate socket mutex must be held already */
 int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
-			  enum drbd_packets cmd, struct p_header *h,
+			  enum drbd_packets cmd, struct p_header80 *h,
 			  size_t size, unsigned msg_flags)
 {
 	int sent, ok;
@@ -1564,7 +1682,7 @@
 
 	h->magic   = BE_DRBD_MAGIC;
 	h->command = cpu_to_be16(cmd);
-	h->length  = cpu_to_be16(size-sizeof(struct p_header));
+	h->length  = cpu_to_be16(size-sizeof(struct p_header80));
 
 	sent = drbd_send(mdev, sock, h, size, msg_flags);
 
@@ -1579,7 +1697,7 @@
  * when we hold the appropriate socket mutex.
  */
 int drbd_send_cmd(struct drbd_conf *mdev, int use_data_socket,
-		  enum drbd_packets cmd, struct p_header *h, size_t size)
+		  enum drbd_packets cmd, struct p_header80 *h, size_t size)
 {
 	int ok = 0;
 	struct socket *sock;
@@ -1607,7 +1725,7 @@
 int drbd_send_cmd2(struct drbd_conf *mdev, enum drbd_packets cmd, char *data,
 		   size_t size)
 {
-	struct p_header h;
+	struct p_header80 h;
 	int ok;
 
 	h.magic   = BE_DRBD_MAGIC;
@@ -1629,7 +1747,7 @@
 
 int drbd_send_sync_param(struct drbd_conf *mdev, struct syncer_conf *sc)
 {
-	struct p_rs_param_89 *p;
+	struct p_rs_param_95 *p;
 	struct socket *sock;
 	int size, rv;
 	const int apv = mdev->agreed_pro_version;
@@ -1637,7 +1755,8 @@
 	size = apv <= 87 ? sizeof(struct p_rs_param)
 		: apv == 88 ? sizeof(struct p_rs_param)
 			+ strlen(mdev->sync_conf.verify_alg) + 1
-		: /* 89 */    sizeof(struct p_rs_param_89);
+		: apv <= 94 ? sizeof(struct p_rs_param_89)
+		: /* apv >= 95 */ sizeof(struct p_rs_param_95);
 
 	/* used from admin command context and receiver/worker context.
 	 * to avoid kmalloc, grab the socket right here,
@@ -1648,12 +1767,16 @@
 	if (likely(sock != NULL)) {
 		enum drbd_packets cmd = apv >= 89 ? P_SYNC_PARAM89 : P_SYNC_PARAM;
 
-		p = &mdev->data.sbuf.rs_param_89;
+		p = &mdev->data.sbuf.rs_param_95;
 
 		/* initialize verify_alg and csums_alg */
 		memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
 
 		p->rate = cpu_to_be32(sc->rate);
+		p->c_plan_ahead = cpu_to_be32(sc->c_plan_ahead);
+		p->c_delay_target = cpu_to_be32(sc->c_delay_target);
+		p->c_fill_target = cpu_to_be32(sc->c_fill_target);
+		p->c_max_rate = cpu_to_be32(sc->c_max_rate);
 
 		if (apv >= 88)
 			strcpy(p->verify_alg, mdev->sync_conf.verify_alg);
@@ -1709,7 +1832,7 @@
 		strcpy(p->integrity_alg, mdev->net_conf->integrity_alg);
 
 	rv = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_PROTOCOL,
-			   (struct p_header *)p, size);
+			   (struct p_header80 *)p, size);
 	kfree(p);
 	return rv;
 }
@@ -1735,7 +1858,7 @@
 	put_ldev(mdev);
 
 	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_UUIDS,
-			     (struct p_header *)&p, sizeof(p));
+			     (struct p_header80 *)&p, sizeof(p));
 }
 
 int drbd_send_uuids(struct drbd_conf *mdev)
@@ -1756,7 +1879,7 @@
 	p.uuid = cpu_to_be64(val);
 
 	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_SYNC_UUID,
-			     (struct p_header *)&p, sizeof(p));
+			     (struct p_header80 *)&p, sizeof(p));
 }
 
 int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags flags)
@@ -1786,7 +1909,7 @@
 	p.dds_flags = cpu_to_be16(flags);
 
 	ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_SIZES,
-			   (struct p_header *)&p, sizeof(p));
+			   (struct p_header80 *)&p, sizeof(p));
 	return ok;
 }
 
@@ -1811,7 +1934,7 @@
 
 	if (likely(sock != NULL)) {
 		ok = _drbd_send_cmd(mdev, sock, P_STATE,
-				    (struct p_header *)&p, sizeof(p), 0);
+				    (struct p_header80 *)&p, sizeof(p), 0);
 	}
 
 	mutex_unlock(&mdev->data.mutex);
@@ -1829,7 +1952,7 @@
 	p.val     = cpu_to_be32(val.i);
 
 	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_STATE_CHG_REQ,
-			     (struct p_header *)&p, sizeof(p));
+			     (struct p_header80 *)&p, sizeof(p));
 }
 
 int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode)
@@ -1839,7 +1962,7 @@
 	p.retcode    = cpu_to_be32(retcode);
 
 	return drbd_send_cmd(mdev, USE_META_SOCKET, P_STATE_CHG_REPLY,
-			     (struct p_header *)&p, sizeof(p));
+			     (struct p_header80 *)&p, sizeof(p));
 }
 
 int fill_bitmap_rle_bits(struct drbd_conf *mdev,
@@ -1938,7 +2061,7 @@
 
 enum { OK, FAILED, DONE }
 send_bitmap_rle_or_plain(struct drbd_conf *mdev,
-	struct p_header *h, struct bm_xfer_ctx *c)
+	struct p_header80 *h, struct bm_xfer_ctx *c)
 {
 	struct p_compressed_bm *p = (void*)h;
 	unsigned long num_words;
@@ -1968,12 +2091,12 @@
 		if (len)
 			drbd_bm_get_lel(mdev, c->word_offset, num_words, (unsigned long*)h->payload);
 		ok = _drbd_send_cmd(mdev, mdev->data.socket, P_BITMAP,
-				   h, sizeof(struct p_header) + len, 0);
+				   h, sizeof(struct p_header80) + len, 0);
 		c->word_offset += num_words;
 		c->bit_offset = c->word_offset * BITS_PER_LONG;
 
 		c->packets[1]++;
-		c->bytes[1] += sizeof(struct p_header) + len;
+		c->bytes[1] += sizeof(struct p_header80) + len;
 
 		if (c->bit_offset > c->bm_bits)
 			c->bit_offset = c->bm_bits;
@@ -1989,14 +2112,14 @@
 int _drbd_send_bitmap(struct drbd_conf *mdev)
 {
 	struct bm_xfer_ctx c;
-	struct p_header *p;
+	struct p_header80 *p;
 	int ret;
 
 	ERR_IF(!mdev->bitmap) return FALSE;
 
 	/* maybe we should use some per thread scratch page,
 	 * and allocate that during initial device creation? */
-	p = (struct p_header *) __get_free_page(GFP_NOIO);
+	p = (struct p_header80 *) __get_free_page(GFP_NOIO);
 	if (!p) {
 		dev_err(DEV, "failed to allocate one page buffer in %s\n", __func__);
 		return FALSE;
@@ -2054,7 +2177,7 @@
 	if (mdev->state.conn < C_CONNECTED)
 		return FALSE;
 	ok = drbd_send_cmd(mdev, USE_META_SOCKET, P_BARRIER_ACK,
-			(struct p_header *)&p, sizeof(p));
+			(struct p_header80 *)&p, sizeof(p));
 	return ok;
 }
 
@@ -2082,17 +2205,18 @@
 	if (!mdev->meta.socket || mdev->state.conn < C_CONNECTED)
 		return FALSE;
 	ok = drbd_send_cmd(mdev, USE_META_SOCKET, cmd,
-				(struct p_header *)&p, sizeof(p));
+				(struct p_header80 *)&p, sizeof(p));
 	return ok;
 }
 
+/* dp->sector and dp->block_id already/still in network byte order,
+ * data_size is payload size according to dp->head,
+ * and may need to be corrected for digest size. */
 int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd,
-		     struct p_data *dp)
+		     struct p_data *dp, int data_size)
 {
-	const int header_size = sizeof(struct p_data)
-			      - sizeof(struct p_header);
-	int data_size  = ((struct p_header *)dp)->length - header_size;
-
+	data_size -= (mdev->agreed_pro_version >= 87 && mdev->integrity_r_tfm) ?
+		crypto_hash_digestsize(mdev->integrity_r_tfm) : 0;
 	return _drbd_send_ack(mdev, cmd, dp->sector, cpu_to_be32(data_size),
 			      dp->block_id);
 }
@@ -2140,7 +2264,7 @@
 	p.blksize  = cpu_to_be32(size);
 
 	ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, cmd,
-				(struct p_header *)&p, sizeof(p));
+				(struct p_header80 *)&p, sizeof(p));
 	return ok;
 }
 
@@ -2158,7 +2282,7 @@
 
 	p.head.magic   = BE_DRBD_MAGIC;
 	p.head.command = cpu_to_be16(cmd);
-	p.head.length  = cpu_to_be16(sizeof(p) - sizeof(struct p_header) + digest_size);
+	p.head.length  = cpu_to_be16(sizeof(p) - sizeof(struct p_header80) + digest_size);
 
 	mutex_lock(&mdev->data.mutex);
 
@@ -2180,7 +2304,7 @@
 	p.blksize  = cpu_to_be32(size);
 
 	ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_OV_REQUEST,
-			   (struct p_header *)&p, sizeof(p));
+			   (struct p_header80 *)&p, sizeof(p));
 	return ok;
 }
 
@@ -2332,6 +2456,18 @@
 	return 1;
 }
 
+static u32 bio_flags_to_wire(struct drbd_conf *mdev, unsigned long bi_rw)
+{
+	if (mdev->agreed_pro_version >= 95)
+		return  (bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) |
+			(bi_rw & REQ_UNPLUG ? DP_UNPLUG : 0) |
+			(bi_rw & REQ_FUA ? DP_FUA : 0) |
+			(bi_rw & REQ_FLUSH ? DP_FLUSH : 0) |
+			(bi_rw & REQ_DISCARD ? DP_DISCARD : 0);
+	else
+		return bi_rw & (REQ_SYNC | REQ_UNPLUG) ? DP_RW_SYNC : 0;
+}
+
 /* Used to send write requests
  * R_PRIMARY -> Peer	(P_DATA)
  */
@@ -2349,30 +2485,25 @@
 	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_w_tfm) ?
 		crypto_hash_digestsize(mdev->integrity_w_tfm) : 0;
 
-	p.head.magic   = BE_DRBD_MAGIC;
-	p.head.command = cpu_to_be16(P_DATA);
-	p.head.length  =
-		cpu_to_be16(sizeof(p) - sizeof(struct p_header) + dgs + req->size);
+	if (req->size <= DRBD_MAX_SIZE_H80_PACKET) {
+		p.head.h80.magic   = BE_DRBD_MAGIC;
+		p.head.h80.command = cpu_to_be16(P_DATA);
+		p.head.h80.length  =
+			cpu_to_be16(sizeof(p) - sizeof(union p_header) + dgs + req->size);
+	} else {
+		p.head.h95.magic   = BE_DRBD_MAGIC_BIG;
+		p.head.h95.command = cpu_to_be16(P_DATA);
+		p.head.h95.length  =
+			cpu_to_be32(sizeof(p) - sizeof(union p_header) + dgs + req->size);
+	}
 
 	p.sector   = cpu_to_be64(req->sector);
 	p.block_id = (unsigned long)req;
 	p.seq_num  = cpu_to_be32(req->seq_num =
 				 atomic_add_return(1, &mdev->packet_seq));
-	dp_flags = 0;
 
-	/* NOTE: no need to check if barriers supported here as we would
-	 *       not pass the test in make_request_common in that case
-	 */
-	if (req->master_bio->bi_rw & REQ_HARDBARRIER) {
-		dev_err(DEV, "ASSERT FAILED would have set DP_HARDBARRIER\n");
-		/* dp_flags |= DP_HARDBARRIER; */
-	}
-	if (req->master_bio->bi_rw & REQ_SYNC)
-		dp_flags |= DP_RW_SYNC;
-	/* for now handle SYNCIO and UNPLUG
-	 * as if they still were one and the same flag */
-	if (req->master_bio->bi_rw & REQ_UNPLUG)
-		dp_flags |= DP_RW_SYNC;
+	dp_flags = bio_flags_to_wire(mdev, req->master_bio->bi_rw);
+
 	if (mdev->state.conn >= C_SYNC_SOURCE &&
 	    mdev->state.conn <= C_PAUSED_SYNC_T)
 		dp_flags |= DP_MAY_SET_IN_SYNC;
@@ -2413,10 +2544,17 @@
 	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_w_tfm) ?
 		crypto_hash_digestsize(mdev->integrity_w_tfm) : 0;
 
-	p.head.magic   = BE_DRBD_MAGIC;
-	p.head.command = cpu_to_be16(cmd);
-	p.head.length  =
-		cpu_to_be16(sizeof(p) - sizeof(struct p_header) + dgs + e->size);
+	if (e->size <= DRBD_MAX_SIZE_H80_PACKET) {
+		p.head.h80.magic   = BE_DRBD_MAGIC;
+		p.head.h80.command = cpu_to_be16(cmd);
+		p.head.h80.length  =
+			cpu_to_be16(sizeof(p) - sizeof(struct p_header80) + dgs + e->size);
+	} else {
+		p.head.h95.magic   = BE_DRBD_MAGIC_BIG;
+		p.head.h95.command = cpu_to_be16(cmd);
+		p.head.h95.length  =
+			cpu_to_be32(sizeof(p) - sizeof(struct p_header80) + dgs + e->size);
+	}
 
 	p.sector   = cpu_to_be64(e->sector);
 	p.block_id = e->block_id;
@@ -2429,8 +2567,7 @@
 	if (!drbd_get_data_sock(mdev))
 		return 0;
 
-	ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p,
-					sizeof(p), dgs ? MSG_MORE : 0);
+	ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p, sizeof(p), dgs ? MSG_MORE : 0);
 	if (ok && dgs) {
 		dgb = mdev->int_dig_out;
 		drbd_csum_ee(mdev, mdev->integrity_w_tfm, e, dgb);
@@ -2536,7 +2673,7 @@
 	unsigned long flags;
 	int rv = 0;
 
-	lock_kernel();
+	mutex_lock(&drbd_main_mutex);
 	spin_lock_irqsave(&mdev->req_lock, flags);
 	/* to have a stable mdev->state.role
 	 * and no race with updating open_cnt */
@@ -2551,7 +2688,7 @@
 	if (!rv)
 		mdev->open_cnt++;
 	spin_unlock_irqrestore(&mdev->req_lock, flags);
-	unlock_kernel();
+	mutex_unlock(&drbd_main_mutex);
 
 	return rv;
 }
@@ -2559,9 +2696,9 @@
 static int drbd_release(struct gendisk *gd, fmode_t mode)
 {
 	struct drbd_conf *mdev = gd->private_data;
-	lock_kernel();
+	mutex_lock(&drbd_main_mutex);
 	mdev->open_cnt--;
-	unlock_kernel();
+	mutex_unlock(&drbd_main_mutex);
 	return 0;
 }
 
@@ -2605,7 +2742,13 @@
 		/* .verify_alg = */	{}, 0,
 		/* .cpu_mask = */	{}, 0,
 		/* .csums_alg = */	{}, 0,
-		/* .use_rle = */	0
+		/* .use_rle = */	0,
+		/* .on_no_data = */	DRBD_ON_NO_DATA_DEF,
+		/* .c_plan_ahead = */	DRBD_C_PLAN_AHEAD_DEF,
+		/* .c_delay_target = */	DRBD_C_DELAY_TARGET_DEF,
+		/* .c_fill_target = */	DRBD_C_FILL_TARGET_DEF,
+		/* .c_max_rate = */	DRBD_C_MAX_RATE_DEF,
+		/* .c_min_rate = */	DRBD_C_MIN_RATE_DEF
 	};
 
 	/* Have to use that way, because the layout differs between
@@ -2616,7 +2759,9 @@
 		  .conn = C_STANDALONE,
 		  .disk = D_DISKLESS,
 		  .pdsk = D_UNKNOWN,
-		  .susp = 0
+		  .susp = 0,
+		  .susp_nod = 0,
+		  .susp_fen = 0
 		} };
 }
 
@@ -2640,6 +2785,9 @@
 	atomic_set(&mdev->net_cnt, 0);
 	atomic_set(&mdev->packet_seq, 0);
 	atomic_set(&mdev->pp_in_use, 0);
+	atomic_set(&mdev->pp_in_use_by_net, 0);
+	atomic_set(&mdev->rs_sect_in, 0);
+	atomic_set(&mdev->rs_sect_ev, 0);
 
 	mutex_init(&mdev->md_io_mutex);
 	mutex_init(&mdev->data.mutex);
@@ -2666,11 +2814,13 @@
 	INIT_LIST_HEAD(&mdev->meta.work.q);
 	INIT_LIST_HEAD(&mdev->resync_work.list);
 	INIT_LIST_HEAD(&mdev->unplug_work.list);
+	INIT_LIST_HEAD(&mdev->go_diskless.list);
 	INIT_LIST_HEAD(&mdev->md_sync_work.list);
 	INIT_LIST_HEAD(&mdev->bm_io_work.w.list);
 
 	mdev->resync_work.cb  = w_resync_inactive;
 	mdev->unplug_work.cb  = w_send_write_hint;
+	mdev->go_diskless.cb  = w_go_diskless;
 	mdev->md_sync_work.cb = w_md_sync;
 	mdev->bm_io_work.w.cb = w_bitmap_io;
 	init_timer(&mdev->resync_timer);
@@ -2682,6 +2832,7 @@
 
 	init_waitqueue_head(&mdev->misc_wait);
 	init_waitqueue_head(&mdev->state_wait);
+	init_waitqueue_head(&mdev->net_cnt_wait);
 	init_waitqueue_head(&mdev->ee_wait);
 	init_waitqueue_head(&mdev->al_wait);
 	init_waitqueue_head(&mdev->seq_wait);
@@ -2697,6 +2848,7 @@
 
 void drbd_mdev_cleanup(struct drbd_conf *mdev)
 {
+	int i;
 	if (mdev->receiver.t_state != None)
 		dev_err(DEV, "ASSERT FAILED: receiver t_state == %d expected 0.\n",
 				mdev->receiver.t_state);
@@ -2713,9 +2865,13 @@
 	mdev->p_size       =
 	mdev->rs_start     =
 	mdev->rs_total     =
-	mdev->rs_failed    =
-	mdev->rs_mark_left =
-	mdev->rs_mark_time = 0;
+	mdev->rs_failed    = 0;
+	mdev->rs_last_events = 0;
+	mdev->rs_last_sect_ev = 0;
+	for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+		mdev->rs_mark_left[i] = 0;
+		mdev->rs_mark_time[i] = 0;
+	}
 	D_ASSERT(mdev->net_conf == NULL);
 
 	drbd_set_my_capacity(mdev, 0);
@@ -2726,6 +2882,7 @@
 	}
 
 	drbd_free_resources(mdev);
+	clear_bit(AL_SUSPENDED, &mdev->flags);
 
 	/*
 	 * currently we drbd_init_ee only on module load, so
@@ -2741,6 +2898,7 @@
 	D_ASSERT(list_empty(&mdev->meta.work.q));
 	D_ASSERT(list_empty(&mdev->resync_work.list));
 	D_ASSERT(list_empty(&mdev->unplug_work.list));
+	D_ASSERT(list_empty(&mdev->go_diskless.list));
 
 }
 
@@ -3280,9 +3438,10 @@
 	sector_t sector;
 	int i;
 
+	del_timer(&mdev->md_sync_timer);
+	/* timer may be rearmed by drbd_md_mark_dirty() now. */
 	if (!test_and_clear_bit(MD_DIRTY, &mdev->flags))
 		return;
-	del_timer(&mdev->md_sync_timer);
 
 	/* We use here D_FAILED and not D_ATTACHING because we try to write
 	 * metadata even if we detach due to a disk failure! */
@@ -3310,12 +3469,9 @@
 	D_ASSERT(drbd_md_ss__(mdev, mdev->ldev) == mdev->ldev->md.md_offset);
 	sector = mdev->ldev->md.md_offset;
 
-	if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
-		clear_bit(MD_DIRTY, &mdev->flags);
-	} else {
+	if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
 		/* this was a try anyways ... */
 		dev_err(DEV, "meta data update failed!\n");
-
 		drbd_chk_io_error(mdev, 1, TRUE);
 	}
 
@@ -3402,6 +3558,28 @@
 	return rv;
 }
 
+static void debug_drbd_uuid(struct drbd_conf *mdev, enum drbd_uuid_index index)
+{
+	static char *uuid_str[UI_EXTENDED_SIZE] = {
+		[UI_CURRENT] = "CURRENT",
+		[UI_BITMAP] = "BITMAP",
+		[UI_HISTORY_START] = "HISTORY_START",
+		[UI_HISTORY_END] = "HISTORY_END",
+		[UI_SIZE] = "SIZE",
+		[UI_FLAGS] = "FLAGS",
+	};
+
+	if (index >= UI_EXTENDED_SIZE) {
+		dev_warn(DEV, " uuid_index >= EXTENDED_SIZE\n");
+		return;
+	}
+
+	dynamic_dev_dbg(DEV, " uuid[%s] now %016llX\n",
+		 uuid_str[index],
+		 (unsigned long long)mdev->ldev->md.uuid[index]);
+}
+
+
 /**
  * drbd_md_mark_dirty() - Mark meta data super block as dirty
  * @mdev:	DRBD device.
@@ -3410,19 +3588,31 @@
  * the meta-data super block. This function sets MD_DIRTY, and starts a
  * timer that ensures that within five seconds you have to call drbd_md_sync().
  */
+#ifdef DEBUG
+void drbd_md_mark_dirty_(struct drbd_conf *mdev, unsigned int line, const char *func)
+{
+	if (!test_and_set_bit(MD_DIRTY, &mdev->flags)) {
+		mod_timer(&mdev->md_sync_timer, jiffies + HZ);
+		mdev->last_md_mark_dirty.line = line;
+		mdev->last_md_mark_dirty.func = func;
+	}
+}
+#else
 void drbd_md_mark_dirty(struct drbd_conf *mdev)
 {
-	set_bit(MD_DIRTY, &mdev->flags);
-	mod_timer(&mdev->md_sync_timer, jiffies + 5*HZ);
+	if (!test_and_set_bit(MD_DIRTY, &mdev->flags))
+		mod_timer(&mdev->md_sync_timer, jiffies + 5*HZ);
 }
-
+#endif
 
 static void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local)
 {
 	int i;
 
-	for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++)
+	for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++) {
 		mdev->ldev->md.uuid[i+1] = mdev->ldev->md.uuid[i];
+		debug_drbd_uuid(mdev, i+1);
+	}
 }
 
 void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
@@ -3437,6 +3627,7 @@
 	}
 
 	mdev->ldev->md.uuid[idx] = val;
+	debug_drbd_uuid(mdev, idx);
 	drbd_md_mark_dirty(mdev);
 }
 
@@ -3446,6 +3637,7 @@
 	if (mdev->ldev->md.uuid[idx]) {
 		drbd_uuid_move_history(mdev);
 		mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[idx];
+		debug_drbd_uuid(mdev, UI_HISTORY_START);
 	}
 	_drbd_uuid_set(mdev, idx, val);
 }
@@ -3464,6 +3656,7 @@
 	dev_info(DEV, "Creating new current UUID\n");
 	D_ASSERT(mdev->ldev->md.uuid[UI_BITMAP] == 0);
 	mdev->ldev->md.uuid[UI_BITMAP] = mdev->ldev->md.uuid[UI_CURRENT];
+	debug_drbd_uuid(mdev, UI_BITMAP);
 
 	get_random_bytes(&val, sizeof(u64));
 	_drbd_uuid_set(mdev, UI_CURRENT, val);
@@ -3478,6 +3671,8 @@
 		drbd_uuid_move_history(mdev);
 		mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP];
 		mdev->ldev->md.uuid[UI_BITMAP] = 0;
+		debug_drbd_uuid(mdev, UI_HISTORY_START);
+		debug_drbd_uuid(mdev, UI_BITMAP);
 	} else {
 		if (mdev->ldev->md.uuid[UI_BITMAP])
 			dev_warn(DEV, "bm UUID already set");
@@ -3485,6 +3680,7 @@
 		mdev->ldev->md.uuid[UI_BITMAP] = val;
 		mdev->ldev->md.uuid[UI_BITMAP] &= ~((u64)1);
 
+		debug_drbd_uuid(mdev, UI_BITMAP);
 	}
 	drbd_md_mark_dirty(mdev);
 }
@@ -3527,6 +3723,7 @@
 {
 	int rv = -EIO;
 
+	drbd_resume_al(mdev);
 	if (get_ldev_if_state(mdev, D_ATTACHING)) {
 		drbd_bm_clear_all(mdev);
 		rv = drbd_bm_write(mdev);
@@ -3559,6 +3756,32 @@
 	return 1;
 }
 
+static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused)
+{
+	D_ASSERT(mdev->state.disk == D_FAILED);
+	/* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
+	 * inc/dec it frequently. Once we are D_DISKLESS, no one will touch
+	 * the protected members anymore, though, so in the after_state_ch work
+	 * it will be safe to free them. */
+	drbd_force_state(mdev, NS(disk, D_DISKLESS));
+	/* We need to wait for return of references checked out while we still
+	 * have been D_FAILED, though (drbd_md_sync, bitmap io). */
+	wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));
+
+	clear_bit(GO_DISKLESS, &mdev->flags);
+	return 1;
+}
+
+void drbd_go_diskless(struct drbd_conf *mdev)
+{
+	D_ASSERT(mdev->state.disk == D_FAILED);
+	if (!test_and_set_bit(GO_DISKLESS, &mdev->flags))
+		drbd_queue_work(&mdev->data.work, &mdev->go_diskless);
+		/* don't drbd_queue_work_front,
+		 * we need to serialize with the after_state_ch work
+		 * of the -> D_FAILED transition. */
+}
+
 /**
  * drbd_queue_bitmap_io() - Queues an IO operation on the whole bitmap
  * @mdev:	DRBD device.
@@ -3655,8 +3878,11 @@
 static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused)
 {
 	dev_warn(DEV, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
+#ifdef DEBUG
+	dev_warn(DEV, "last md_mark_dirty: %s:%u\n",
+		mdev->last_md_mark_dirty.func, mdev->last_md_mark_dirty.line);
+#endif
 	drbd_md_sync(mdev);
-
 	return 1;
 }
 
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 73131c5..87925e9 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -33,10 +33,13 @@
 #include <linux/blkpg.h>
 #include <linux/cpumask.h>
 #include "drbd_int.h"
+#include "drbd_req.h"
 #include "drbd_wrappers.h"
 #include <asm/unaligned.h>
 #include <linux/drbd_tag_magic.h>
 #include <linux/drbd_limits.h>
+#include <linux/compiler.h>
+#include <linux/kthread.h>
 
 static unsigned short *tl_add_blob(unsigned short *, enum drbd_tags, const void *, int);
 static unsigned short *tl_add_str(unsigned short *, enum drbd_tags, const char *);
@@ -169,6 +172,10 @@
 		put_net_conf(mdev);
 	}
 
+	/* The helper may take some time.
+	 * write out any unsynced meta data changes now */
+	drbd_md_sync(mdev);
+
 	dev_info(DEV, "helper command: %s %s %s\n", usermode_helper, cmd, mb);
 
 	drbd_bcast_ev_helper(mdev, cmd);
@@ -202,12 +209,10 @@
 		put_ldev(mdev);
 	} else {
 		dev_warn(DEV, "Not fencing peer, I'm not even Consistent myself.\n");
-		return mdev->state.pdsk;
+		nps = mdev->state.pdsk;
+		goto out;
 	}
 
-	if (fp == FP_STONITH)
-		_drbd_request_state(mdev, NS(susp, 1), CS_WAIT_COMPLETE);
-
 	r = drbd_khelper(mdev, "fence-peer");
 
 	switch ((r>>8) & 0xff) {
@@ -252,9 +257,36 @@
 
 	dev_info(DEV, "fence-peer helper returned %d (%s)\n",
 			(r>>8) & 0xff, ex_to_string);
+
+out:
+	if (mdev->state.susp_fen && nps >= D_UNKNOWN) {
+		/* The handler was not successful... unfreeze here, the
+		   state engine can not unfreeze... */
+		_drbd_request_state(mdev, NS(susp_fen, 0), CS_VERBOSE);
+	}
+
 	return nps;
 }
 
+static int _try_outdate_peer_async(void *data)
+{
+	struct drbd_conf *mdev = (struct drbd_conf *)data;
+	enum drbd_disk_state nps;
+
+	nps = drbd_try_outdate_peer(mdev);
+	drbd_request_state(mdev, NS(pdsk, nps));
+
+	return 0;
+}
+
+void drbd_try_outdate_peer_async(struct drbd_conf *mdev)
+{
+	struct task_struct *opa;
+
+	opa = kthread_run(_try_outdate_peer_async, mdev, "drbd%d_a_helper", mdev_to_minor(mdev));
+	if (IS_ERR(opa))
+		dev_err(DEV, "out of mem, failed to invoke fence-peer helper\n");
+}
 
 int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 {
@@ -394,6 +426,39 @@
 	return r;
 }
 
+static struct drbd_conf *ensure_mdev(int minor, int create)
+{
+	struct drbd_conf *mdev;
+
+	if (minor >= minor_count)
+		return NULL;
+
+	mdev = minor_to_mdev(minor);
+
+	if (!mdev && create) {
+		struct gendisk *disk = NULL;
+		mdev = drbd_new_device(minor);
+
+		spin_lock_irq(&drbd_pp_lock);
+		if (minor_table[minor] == NULL) {
+			minor_table[minor] = mdev;
+			disk = mdev->vdisk;
+			mdev = NULL;
+		} /* else: we lost the race */
+		spin_unlock_irq(&drbd_pp_lock);
+
+		if (disk) /* we won the race above */
+			/* in case we ever add a drbd_delete_device(),
+			 * don't forget the del_gendisk! */
+			add_disk(disk);
+		else /* we lost the race above */
+			drbd_free_mdev(mdev);
+
+		mdev = minor_to_mdev(minor);
+	}
+
+	return mdev;
+}
 
 static int drbd_nl_primary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
 			   struct drbd_nl_cfg_reply *reply)
@@ -494,6 +559,8 @@
 void drbd_suspend_io(struct drbd_conf *mdev)
 {
 	set_bit(SUSPEND_IO, &mdev->flags);
+	if (is_susp(mdev->state))
+		return;
 	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
 }
 
@@ -713,9 +780,6 @@
 	blk_queue_segment_boundary(q, PAGE_SIZE-1);
 	blk_stack_limits(&q->limits, &b->limits, 0);
 
-	if (b->merge_bvec_fn)
-		dev_warn(DEV, "Backing device's merge_bvec_fn() = %p\n",
-		     b->merge_bvec_fn);
 	dev_info(DEV, "max_segment_size ( = BIO size ) = %u\n", queue_max_segment_size(q));
 
 	if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) {
@@ -729,14 +793,16 @@
 /* serialize deconfig (worker exiting, doing cleanup)
  * and reconfig (drbdsetup disk, drbdsetup net)
  *
- * wait for a potentially exiting worker, then restart it,
- * or start a new one.
+ * Wait for a potentially exiting worker, then restart it,
+ * or start a new one.  Flush any pending work, there may still be an
+ * after_state_change queued.
  */
 static void drbd_reconfig_start(struct drbd_conf *mdev)
 {
 	wait_event(mdev->state_wait, !test_and_set_bit(CONFIG_PENDING, &mdev->flags));
 	wait_event(mdev->state_wait, !test_bit(DEVICE_DYING, &mdev->flags));
 	drbd_thread_start(&mdev->worker);
+	drbd_flush_workqueue(mdev);
 }
 
 /* if still unconfigured, stops worker again.
@@ -756,6 +822,29 @@
 	wake_up(&mdev->state_wait);
 }
 
+/* Make sure IO is suspended before calling this function(). */
+static void drbd_suspend_al(struct drbd_conf *mdev)
+{
+	int s = 0;
+
+	if (lc_try_lock(mdev->act_log)) {
+		drbd_al_shrink(mdev);
+		lc_unlock(mdev->act_log);
+	} else {
+		dev_warn(DEV, "Failed to lock al in drbd_suspend_al()\n");
+		return;
+	}
+
+	spin_lock_irq(&mdev->req_lock);
+	if (mdev->state.conn < C_CONNECTED)
+		s = !test_and_set_bit(AL_SUSPENDED, &mdev->flags);
+
+	spin_unlock_irq(&mdev->req_lock);
+
+	if (s)
+		dev_info(DEV, "Suspended AL updates\n");
+}
+
 /* does always return 0;
  * interesting return code is in reply->ret_code */
 static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
@@ -769,6 +858,7 @@
 	struct inode *inode, *inode2;
 	struct lru_cache *resync_lru = NULL;
 	union drbd_state ns, os;
+	unsigned int max_seg_s;
 	int rv;
 	int cp_discovered = 0;
 	int logical_block_size;
@@ -803,6 +893,15 @@
 		goto fail;
 	}
 
+	if (get_net_conf(mdev)) {
+		int prot = mdev->net_conf->wire_protocol;
+		put_net_conf(mdev);
+		if (nbc->dc.fencing == FP_STONITH && prot == DRBD_PROT_A) {
+			retcode = ERR_STONITH_AND_PROT_A;
+			goto fail;
+		}
+	}
+
 	nbc->lo_file = filp_open(nbc->dc.backing_dev, O_RDWR, 0);
 	if (IS_ERR(nbc->lo_file)) {
 		dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.backing_dev,
@@ -924,7 +1023,7 @@
 
 	drbd_suspend_io(mdev);
 	/* also wait for the last barrier ack. */
-	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt));
+	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt) || is_susp(mdev->state));
 	/* and for any other previously queued work */
 	drbd_flush_workqueue(mdev);
 
@@ -1021,7 +1120,8 @@
 	else
 		clear_bit(CRASHED_PRIMARY, &mdev->flags);
 
-	if (drbd_md_test_flag(mdev->ldev, MDF_PRIMARY_IND)) {
+	if (drbd_md_test_flag(mdev->ldev, MDF_PRIMARY_IND) &&
+	    !(mdev->state.role == R_PRIMARY && mdev->state.susp_nod)) {
 		set_bit(CRASHED_PRIMARY, &mdev->flags);
 		cp_discovered = 1;
 	}
@@ -1031,7 +1131,20 @@
 	mdev->read_cnt = 0;
 	mdev->writ_cnt = 0;
 
-	drbd_setup_queue_param(mdev, DRBD_MAX_SEGMENT_SIZE);
+	max_seg_s = DRBD_MAX_SEGMENT_SIZE;
+	if (mdev->state.conn == C_CONNECTED) {
+		/* We are Primary, Connected, and now attach a new local
+		 * backing store. We must not increase the user visible maximum
+		 * bio size on this device to something the peer may not be
+		 * able to handle. */
+		if (mdev->agreed_pro_version < 94)
+			max_seg_s = queue_max_segment_size(mdev->rq_queue);
+		else if (mdev->agreed_pro_version == 94)
+			max_seg_s = DRBD_MAX_SIZE_H80_PACKET;
+		/* else: drbd 8.3.9 and later, stay with default */
+	}
+
+	drbd_setup_queue_param(mdev, max_seg_s);
 
 	/* If I am currently not R_PRIMARY,
 	 * but meta data primary indicator is set,
@@ -1079,6 +1192,9 @@
 		drbd_al_to_on_disk_bm(mdev);
 	}
 
+	if (_drbd_bm_total_weight(mdev) == drbd_bm_bits(mdev))
+		drbd_suspend_al(mdev); /* IO is still suspended here... */
+
 	spin_lock_irq(&mdev->req_lock);
 	os = mdev->state;
 	ns.i = os.i;
@@ -1235,7 +1351,16 @@
 	    && (new_conf->wire_protocol != DRBD_PROT_C)) {
 		retcode = ERR_NOT_PROTO_C;
 		goto fail;
-	};
+	}
+
+	if (get_ldev(mdev)) {
+		enum drbd_fencing_p fp = mdev->ldev->dc.fencing;
+		put_ldev(mdev);
+		if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH) {
+			retcode = ERR_STONITH_AND_PROT_A;
+			goto fail;
+		}
+	}
 
 	if (mdev->state.role == R_PRIMARY && new_conf->want_lose) {
 		retcode = ERR_DISCARD;
@@ -1350,6 +1475,7 @@
 		}
 	}
 
+	drbd_flush_workqueue(mdev);
 	spin_lock_irq(&mdev->req_lock);
 	if (mdev->net_conf != NULL) {
 		retcode = ERR_NET_CONFIGURED;
@@ -1388,10 +1514,9 @@
 	mdev->int_dig_out=int_dig_out;
 	mdev->int_dig_in=int_dig_in;
 	mdev->int_dig_vv=int_dig_vv;
+	retcode = _drbd_set_state(_NS(mdev, conn, C_UNCONNECTED), CS_VERBOSE, NULL);
 	spin_unlock_irq(&mdev->req_lock);
 
-	retcode = _drbd_request_state(mdev, NS(conn, C_UNCONNECTED), CS_VERBOSE);
-
 	kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
 	reply->ret_code = retcode;
 	drbd_reconfig_done(mdev);
@@ -1546,6 +1671,8 @@
 	struct crypto_hash *csums_tfm = NULL;
 	struct syncer_conf sc;
 	cpumask_var_t new_cpu_mask;
+	int *rs_plan_s = NULL;
+	int fifo_size;
 
 	if (!zalloc_cpumask_var(&new_cpu_mask, GFP_KERNEL)) {
 		retcode = ERR_NOMEM;
@@ -1557,6 +1684,12 @@
 		sc.rate       = DRBD_RATE_DEF;
 		sc.after      = DRBD_AFTER_DEF;
 		sc.al_extents = DRBD_AL_EXTENTS_DEF;
+		sc.on_no_data  = DRBD_ON_NO_DATA_DEF;
+		sc.c_plan_ahead = DRBD_C_PLAN_AHEAD_DEF;
+		sc.c_delay_target = DRBD_C_DELAY_TARGET_DEF;
+		sc.c_fill_target = DRBD_C_FILL_TARGET_DEF;
+		sc.c_max_rate = DRBD_C_MAX_RATE_DEF;
+		sc.c_min_rate = DRBD_C_MIN_RATE_DEF;
 	} else
 		memcpy(&sc, &mdev->sync_conf, sizeof(struct syncer_conf));
 
@@ -1634,6 +1767,12 @@
 	}
 #undef AL_MAX
 
+	/* to avoid spurious errors when configuring minors before configuring
+	 * the minors they depend on: if necessary, first create the minor we
+	 * depend on */
+	if (sc.after >= 0)
+		ensure_mdev(sc.after, 1);
+
 	/* most sanity checks done, try to assign the new sync-after
 	 * dependency.  need to hold the global lock in there,
 	 * to avoid a race in the dependency loop check. */
@@ -1641,6 +1780,16 @@
 	if (retcode != NO_ERROR)
 		goto fail;
 
+	fifo_size = (sc.c_plan_ahead * 10 * SLEEP_TIME) / HZ;
+	if (fifo_size != mdev->rs_plan_s.size && fifo_size > 0) {
+		rs_plan_s   = kzalloc(sizeof(int) * fifo_size, GFP_KERNEL);
+		if (!rs_plan_s) {
+			dev_err(DEV, "kmalloc of fifo_buffer failed");
+			retcode = ERR_NOMEM;
+			goto fail;
+		}
+	}
+
 	/* ok, assign the rest of it as well.
 	 * lock against receive_SyncParam() */
 	spin_lock(&mdev->peer_seq_lock);
@@ -1657,6 +1806,15 @@
 		mdev->verify_tfm = verify_tfm;
 		verify_tfm = NULL;
 	}
+
+	if (fifo_size != mdev->rs_plan_s.size) {
+		kfree(mdev->rs_plan_s.values);
+		mdev->rs_plan_s.values = rs_plan_s;
+		mdev->rs_plan_s.size   = fifo_size;
+		mdev->rs_planed = 0;
+		rs_plan_s = NULL;
+	}
+
 	spin_unlock(&mdev->peer_seq_lock);
 
 	if (get_ldev(mdev)) {
@@ -1688,6 +1846,7 @@
 
 	kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
 fail:
+	kfree(rs_plan_s);
 	free_cpumask_var(new_cpu_mask);
 	crypto_free_hash(csums_tfm);
 	crypto_free_hash(verify_tfm);
@@ -1721,12 +1880,38 @@
 	return 0;
 }
 
+static int drbd_bmio_set_susp_al(struct drbd_conf *mdev)
+{
+	int rv;
+
+	rv = drbd_bmio_set_n_write(mdev);
+	drbd_suspend_al(mdev);
+	return rv;
+}
+
 static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
 				   struct drbd_nl_cfg_reply *reply)
 {
+	int retcode;
 
-	reply->ret_code = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S));
+	retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S), CS_ORDERED);
 
+	if (retcode < SS_SUCCESS) {
+		if (retcode == SS_NEED_CONNECTION && mdev->state.role == R_PRIMARY) {
+			/* The peer will get a resync upon connect anyways. Just make that
+			   into a full resync. */
+			retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT));
+			if (retcode >= SS_SUCCESS) {
+				/* open coded drbd_bitmap_io() */
+				if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al,
+						   "set_n_write from invalidate_peer"))
+					retcode = ERR_IO_MD_DISK;
+			}
+		} else
+			retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S));
+	}
+
+	reply->ret_code = retcode;
 	return 0;
 }
 
@@ -1765,7 +1950,21 @@
 static int drbd_nl_resume_io(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
 			     struct drbd_nl_cfg_reply *reply)
 {
-	reply->ret_code = drbd_request_state(mdev, NS(susp, 0));
+	if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
+		drbd_uuid_new_current(mdev);
+		clear_bit(NEW_CUR_UUID, &mdev->flags);
+		drbd_md_sync(mdev);
+	}
+	drbd_suspend_io(mdev);
+	reply->ret_code = drbd_request_state(mdev, NS3(susp, 0, susp_nod, 0, susp_fen, 0));
+	if (reply->ret_code == SS_SUCCESS) {
+		if (mdev->state.conn < C_CONNECTED)
+			tl_clear(mdev);
+		if (mdev->state.disk == D_DISKLESS || mdev->state.disk == D_FAILED)
+			tl_restart(mdev, fail_frozen_disk_io);
+	}
+	drbd_resume_io(mdev);
+
 	return 0;
 }
 
@@ -1941,40 +2140,6 @@
 	return 0;
 }
 
-static struct drbd_conf *ensure_mdev(struct drbd_nl_cfg_req *nlp)
-{
-	struct drbd_conf *mdev;
-
-	if (nlp->drbd_minor >= minor_count)
-		return NULL;
-
-	mdev = minor_to_mdev(nlp->drbd_minor);
-
-	if (!mdev && (nlp->flags & DRBD_NL_CREATE_DEVICE)) {
-		struct gendisk *disk = NULL;
-		mdev = drbd_new_device(nlp->drbd_minor);
-
-		spin_lock_irq(&drbd_pp_lock);
-		if (minor_table[nlp->drbd_minor] == NULL) {
-			minor_table[nlp->drbd_minor] = mdev;
-			disk = mdev->vdisk;
-			mdev = NULL;
-		} /* else: we lost the race */
-		spin_unlock_irq(&drbd_pp_lock);
-
-		if (disk) /* we won the race above */
-			/* in case we ever add a drbd_delete_device(),
-			 * don't forget the del_gendisk! */
-			add_disk(disk);
-		else /* we lost the race above */
-			drbd_free_mdev(mdev);
-
-		mdev = minor_to_mdev(nlp->drbd_minor);
-	}
-
-	return mdev;
-}
-
 struct cn_handler_struct {
 	int (*function)(struct drbd_conf *,
 			 struct drbd_nl_cfg_req *,
@@ -2035,7 +2200,8 @@
 		goto fail;
 	}
 
-	mdev = ensure_mdev(nlp);
+	mdev = ensure_mdev(nlp->drbd_minor,
+			(nlp->flags & DRBD_NL_CREATE_DEVICE));
 	if (!mdev) {
 		retcode = ERR_MINOR_INVALID;
 		goto fail;
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index be3374b..ad325c5 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -57,6 +57,7 @@
 	unsigned long db, dt, dbdt, rt, rs_left;
 	unsigned int res;
 	int i, x, y;
+	int stalled = 0;
 
 	drbd_get_syncer_progress(mdev, &rs_left, &res);
 
@@ -90,18 +91,17 @@
 	 * db: blocks written from mark until now
 	 * rt: remaining time
 	 */
-	dt = (jiffies - mdev->rs_mark_time) / HZ;
-
-	if (dt > 20) {
-		/* if we made no update to rs_mark_time for too long,
-		 * we are stalled. show that. */
-		seq_printf(seq, "stalled\n");
-		return;
-	}
+	/* Rolling marks. last_mark+1 may just now be modified.  last_mark+2 is
+	 * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
+	 * least DRBD_SYNC_MARK_STEP time before it will be modified. */
+	i = (mdev->rs_last_mark + 2) % DRBD_SYNC_MARKS;
+	dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
+	if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS))
+		stalled = 1;
 
 	if (!dt)
 		dt++;
-	db = mdev->rs_mark_left - rs_left;
+	db = mdev->rs_mark_left[i] - rs_left;
 	rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
 
 	seq_printf(seq, "finish: %lu:%02lu:%02lu",
@@ -118,7 +118,7 @@
 	/* mean speed since syncer started
 	 * we do account for PausedSync periods */
 	dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ;
-	if (dt <= 0)
+	if (dt == 0)
 		dt = 1;
 	db = mdev->rs_total - rs_left;
 	dbdt = Bit2KB(db/dt);
@@ -128,7 +128,14 @@
 	else
 		seq_printf(seq, " (%ld)", dbdt);
 
-	seq_printf(seq, " K/sec\n");
+	if (mdev->state.conn == C_SYNC_TARGET) {
+		if (mdev->c_sync_rate > 1000)
+			seq_printf(seq, " want: %d,%03d",
+				   mdev->c_sync_rate / 1000, mdev->c_sync_rate % 1000);
+		else
+			seq_printf(seq, " want: %d", mdev->c_sync_rate);
+	}
+	seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
 }
 
 static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
@@ -196,7 +203,7 @@
 			seq_printf(seq, "%2d: cs:Unconfigured\n", i);
 		} else {
 			seq_printf(seq,
-			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c\n"
+			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
 			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
 			   "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
 			   i, sn,
@@ -206,11 +213,12 @@
 			   drbd_disk_str(mdev->state.pdsk),
 			   (mdev->net_conf == NULL ? ' ' :
 			    (mdev->net_conf->wire_protocol - DRBD_PROT_A+'A')),
-			   mdev->state.susp ? 's' : 'r',
+			   is_susp(mdev->state) ? 's' : 'r',
 			   mdev->state.aftr_isp ? 'a' : '-',
 			   mdev->state.peer_isp ? 'p' : '-',
 			   mdev->state.user_isp ? 'u' : '-',
 			   mdev->congestion_reason ?: '-',
+			   test_bit(AL_SUSPENDED, &mdev->flags) ? 's' : '-',
 			   mdev->send_cnt/2,
 			   mdev->recv_cnt/2,
 			   mdev->writ_cnt/2,
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 081522d..efd6169 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -241,7 +241,7 @@
 	spin_unlock_irq(&mdev->req_lock);
 
 	list_for_each_entry_safe(e, t, &reclaimed, w.list)
-		drbd_free_ee(mdev, e);
+		drbd_free_net_ee(mdev, e);
 }
 
 /**
@@ -298,9 +298,11 @@
  * Is also used from inside an other spin_lock_irq(&mdev->req_lock);
  * Either links the page chain back to the global pool,
  * or returns all pages to the system. */
-static void drbd_pp_free(struct drbd_conf *mdev, struct page *page)
+static void drbd_pp_free(struct drbd_conf *mdev, struct page *page, int is_net)
 {
+	atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use;
 	int i;
+
 	if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count)
 		i = page_chain_free(page);
 	else {
@@ -311,10 +313,10 @@
 		drbd_pp_vacant += i;
 		spin_unlock(&drbd_pp_lock);
 	}
-	atomic_sub(i, &mdev->pp_in_use);
-	i = atomic_read(&mdev->pp_in_use);
+	i = atomic_sub_return(i, a);
 	if (i < 0)
-		dev_warn(DEV, "ASSERTION FAILED: pp_in_use: %d < 0\n", i);
+		dev_warn(DEV, "ASSERTION FAILED: %s: %d < 0\n",
+			is_net ? "pp_in_use_by_net" : "pp_in_use", i);
 	wake_up(&drbd_pp_wait);
 }
 
@@ -365,7 +367,6 @@
 	e->size = data_size;
 	e->flags = 0;
 	e->sector = sector;
-	e->sector = sector;
 	e->block_id = id;
 
 	return e;
@@ -375,9 +376,11 @@
 	return NULL;
 }
 
-void drbd_free_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e)
+void drbd_free_some_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e, int is_net)
 {
-	drbd_pp_free(mdev, e->pages);
+	if (e->flags & EE_HAS_DIGEST)
+		kfree(e->digest);
+	drbd_pp_free(mdev, e->pages, is_net);
 	D_ASSERT(atomic_read(&e->pending_bios) == 0);
 	D_ASSERT(hlist_unhashed(&e->colision));
 	mempool_free(e, drbd_ee_mempool);
@@ -388,13 +391,14 @@
 	LIST_HEAD(work_list);
 	struct drbd_epoch_entry *e, *t;
 	int count = 0;
+	int is_net = list == &mdev->net_ee;
 
 	spin_lock_irq(&mdev->req_lock);
 	list_splice_init(list, &work_list);
 	spin_unlock_irq(&mdev->req_lock);
 
 	list_for_each_entry_safe(e, t, &work_list, w.list) {
-		drbd_free_ee(mdev, e);
+		drbd_free_some_ee(mdev, e, is_net);
 		count++;
 	}
 	return count;
@@ -423,7 +427,7 @@
 	spin_unlock_irq(&mdev->req_lock);
 
 	list_for_each_entry_safe(e, t, &reclaimed, w.list)
-		drbd_free_ee(mdev, e);
+		drbd_free_net_ee(mdev, e);
 
 	/* possible callbacks here:
 	 * e_end_block, and e_end_resync_block, e_send_discard_ack.
@@ -719,14 +723,14 @@
 static int drbd_send_fp(struct drbd_conf *mdev,
 	struct socket *sock, enum drbd_packets cmd)
 {
-	struct p_header *h = (struct p_header *) &mdev->data.sbuf.header;
+	struct p_header80 *h = &mdev->data.sbuf.header.h80;
 
 	return _drbd_send_cmd(mdev, sock, cmd, h, sizeof(*h), 0);
 }
 
 static enum drbd_packets drbd_recv_fp(struct drbd_conf *mdev, struct socket *sock)
 {
-	struct p_header *h = (struct p_header *) &mdev->data.sbuf.header;
+	struct p_header80 *h = &mdev->data.rbuf.header.h80;
 	int rr;
 
 	rr = drbd_recv_short(mdev, sock, h, sizeof(*h), 0);
@@ -776,9 +780,6 @@
 
 	D_ASSERT(!mdev->data.socket);
 
-	if (test_and_clear_bit(CREATE_BARRIER, &mdev->flags))
-		dev_err(DEV, "CREATE_BARRIER flag was set in drbd_connect - now cleared!\n");
-
 	if (drbd_request_state(mdev, NS(conn, C_WF_CONNECTION)) < SS_SUCCESS)
 		return -2;
 
@@ -927,6 +928,11 @@
 
 	drbd_thread_start(&mdev->asender);
 
+	if (mdev->agreed_pro_version < 95 && get_ldev(mdev)) {
+		drbd_setup_queue_param(mdev, DRBD_MAX_SIZE_H80_PACKET);
+		put_ldev(mdev);
+	}
+
 	if (!drbd_send_protocol(mdev))
 		return -1;
 	drbd_send_sync_param(mdev, &mdev->sync_conf);
@@ -946,22 +952,28 @@
 	return -1;
 }
 
-static int drbd_recv_header(struct drbd_conf *mdev, struct p_header *h)
+static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsigned int *packet_size)
 {
+	union p_header *h = &mdev->data.rbuf.header;
 	int r;
 
 	r = drbd_recv(mdev, h, sizeof(*h));
-
 	if (unlikely(r != sizeof(*h))) {
 		dev_err(DEV, "short read expecting header on sock: r=%d\n", r);
 		return FALSE;
-	};
-	h->command = be16_to_cpu(h->command);
-	h->length  = be16_to_cpu(h->length);
-	if (unlikely(h->magic != BE_DRBD_MAGIC)) {
-		dev_err(DEV, "magic?? on data m: 0x%lx c: %d l: %d\n",
-		    (long)be32_to_cpu(h->magic),
-		    h->command, h->length);
+	}
+
+	if (likely(h->h80.magic == BE_DRBD_MAGIC)) {
+		*cmd = be16_to_cpu(h->h80.command);
+		*packet_size = be16_to_cpu(h->h80.length);
+	} else if (h->h95.magic == BE_DRBD_MAGIC_BIG) {
+		*cmd = be16_to_cpu(h->h95.command);
+		*packet_size = be32_to_cpu(h->h95.length);
+	} else {
+		dev_err(DEV, "magic?? on data m: 0x%08x c: %d l: %d\n",
+		    be32_to_cpu(h->h80.magic),
+		    be16_to_cpu(h->h80.command),
+		    be16_to_cpu(h->h80.length));
 		return FALSE;
 	}
 	mdev->last_received = jiffies;
@@ -975,7 +987,7 @@
 
 	if (mdev->write_ordering >= WO_bdev_flush && get_ldev(mdev)) {
 		rv = blkdev_issue_flush(mdev->ldev->backing_bdev, GFP_KERNEL,
-					NULL, BLKDEV_IFL_WAIT);
+					NULL);
 		if (rv) {
 			dev_err(DEV, "local disk flush failed with status %d\n", rv);
 			/* would rather check on EOPNOTSUPP, but that is not reliable.
@@ -1268,17 +1280,12 @@
 	return 1;
 }
 
-static int receive_Barrier(struct drbd_conf *mdev, struct p_header *h)
+static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	int rv, issue_flush;
-	struct p_barrier *p = (struct p_barrier *)h;
+	struct p_barrier *p = &mdev->data.rbuf.barrier;
 	struct drbd_epoch *epoch;
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
-
-	rv = drbd_recv(mdev, h->payload, h->length);
-	ERR_IF(rv != h->length) return FALSE;
-
 	inc_unacked(mdev);
 
 	if (mdev->net_conf->wire_protocol != DRBD_PROT_C)
@@ -1457,7 +1464,7 @@
 		data_size -= rr;
 	}
 	kunmap(page);
-	drbd_pp_free(mdev, page);
+	drbd_pp_free(mdev, page, 0);
 	return rv;
 }
 
@@ -1562,30 +1569,29 @@
 	list_add(&e->w.list, &mdev->sync_ee);
 	spin_unlock_irq(&mdev->req_lock);
 
+	atomic_add(data_size >> 9, &mdev->rs_sect_ev);
 	if (drbd_submit_ee(mdev, e, WRITE, DRBD_FAULT_RS_WR) == 0)
 		return TRUE;
 
+	/* drbd_submit_ee currently fails for one reason only:
+	 * not being able to allocate enough bios.
+	 * Is dropping the connection going to help? */
+	spin_lock_irq(&mdev->req_lock);
+	list_del(&e->w.list);
+	spin_unlock_irq(&mdev->req_lock);
+
 	drbd_free_ee(mdev, e);
 fail:
 	put_ldev(mdev);
 	return FALSE;
 }
 
-static int receive_DataReply(struct drbd_conf *mdev, struct p_header *h)
+static int receive_DataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	struct drbd_request *req;
 	sector_t sector;
-	unsigned int header_size, data_size;
 	int ok;
-	struct p_data *p = (struct p_data *)h;
-
-	header_size = sizeof(*p) - sizeof(*h);
-	data_size   = h->length  - header_size;
-
-	ERR_IF(data_size == 0) return FALSE;
-
-	if (drbd_recv(mdev, h->payload, header_size) != header_size)
-		return FALSE;
+	struct p_data *p = &mdev->data.rbuf.data;
 
 	sector = be64_to_cpu(p->sector);
 
@@ -1611,20 +1617,11 @@
 	return ok;
 }
 
-static int receive_RSDataReply(struct drbd_conf *mdev, struct p_header *h)
+static int receive_RSDataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	sector_t sector;
-	unsigned int header_size, data_size;
 	int ok;
-	struct p_data *p = (struct p_data *)h;
-
-	header_size = sizeof(*p) - sizeof(*h);
-	data_size   = h->length  - header_size;
-
-	ERR_IF(data_size == 0) return FALSE;
-
-	if (drbd_recv(mdev, h->payload, header_size) != header_size)
-		return FALSE;
+	struct p_data *p = &mdev->data.rbuf.data;
 
 	sector = be64_to_cpu(p->sector);
 	D_ASSERT(p->block_id == ID_SYNCER);
@@ -1640,9 +1637,11 @@
 
 		ok = drbd_drain_block(mdev, data_size);
 
-		drbd_send_ack_dp(mdev, P_NEG_ACK, p);
+		drbd_send_ack_dp(mdev, P_NEG_ACK, p, data_size);
 	}
 
+	atomic_add(data_size >> 9, &mdev->rs_sect_in);
+
 	return ok;
 }
 
@@ -1765,24 +1764,27 @@
 	return ret;
 }
 
+static unsigned long write_flags_to_bio(struct drbd_conf *mdev, u32 dpf)
+{
+	if (mdev->agreed_pro_version >= 95)
+		return  (dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
+			(dpf & DP_UNPLUG ? REQ_UNPLUG : 0) |
+			(dpf & DP_FUA ? REQ_FUA : 0) |
+			(dpf & DP_FLUSH ? REQ_FUA : 0) |
+			(dpf & DP_DISCARD ? REQ_DISCARD : 0);
+	else
+		return dpf & DP_RW_SYNC ? (REQ_SYNC | REQ_UNPLUG) : 0;
+}
+
 /* mirrored write */
-static int receive_Data(struct drbd_conf *mdev, struct p_header *h)
+static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	sector_t sector;
 	struct drbd_epoch_entry *e;
-	struct p_data *p = (struct p_data *)h;
-	int header_size, data_size;
+	struct p_data *p = &mdev->data.rbuf.data;
 	int rw = WRITE;
 	u32 dp_flags;
 
-	header_size = sizeof(*p) - sizeof(*h);
-	data_size   = h->length  - header_size;
-
-	ERR_IF(data_size == 0) return FALSE;
-
-	if (drbd_recv(mdev, h->payload, header_size) != header_size)
-		return FALSE;
-
 	if (!get_ldev(mdev)) {
 		if (__ratelimit(&drbd_ratelimit_state))
 			dev_err(DEV, "Can not write mirrored data block "
@@ -1792,7 +1794,7 @@
 			mdev->peer_seq++;
 		spin_unlock(&mdev->peer_seq_lock);
 
-		drbd_send_ack_dp(mdev, P_NEG_ACK, p);
+		drbd_send_ack_dp(mdev, P_NEG_ACK, p, data_size);
 		atomic_inc(&mdev->current_epoch->epoch_size);
 		return drbd_drain_block(mdev, data_size);
 	}
@@ -1839,12 +1841,8 @@
 	spin_unlock(&mdev->epoch_lock);
 
 	dp_flags = be32_to_cpu(p->dp_flags);
-	if (dp_flags & DP_HARDBARRIER) {
-		dev_err(DEV, "ASSERT FAILED would have submitted barrier request\n");
-		/* rw |= REQ_HARDBARRIER; */
-	}
-	if (dp_flags & DP_RW_SYNC)
-		rw |= REQ_SYNC | REQ_UNPLUG;
+	rw |= write_flags_to_bio(mdev, dp_flags);
+
 	if (dp_flags & DP_MAY_SET_IN_SYNC)
 		e->flags |= EE_MAY_SET_IN_SYNC;
 
@@ -2007,6 +2005,16 @@
 	if (drbd_submit_ee(mdev, e, rw, DRBD_FAULT_DT_WR) == 0)
 		return TRUE;
 
+	/* drbd_submit_ee currently fails for one reason only:
+	 * not being able to allocate enough bios.
+	 * Is dropping the connection going to help? */
+	spin_lock_irq(&mdev->req_lock);
+	list_del(&e->w.list);
+	hlist_del_init(&e->colision);
+	spin_unlock_irq(&mdev->req_lock);
+	if (e->flags & EE_CALL_AL_COMPLETE_IO)
+		drbd_al_complete_io(mdev, e->sector);
+
 out_interrupted:
 	/* yes, the epoch_size now is imbalanced.
 	 * but we drop the connection anyways, so we don't have a chance to
@@ -2016,20 +2024,64 @@
 	return FALSE;
 }
 
-static int receive_DataRequest(struct drbd_conf *mdev, struct p_header *h)
+/* We may throttle resync, if the lower device seems to be busy,
+ * and current sync rate is above c_min_rate.
+ *
+ * To decide whether or not the lower device is busy, we use a scheme similar
+ * to MD RAID is_mddev_idle(): if the partition stats reveal "significant"
+ * (more than 64 sectors) of activity we cannot account for with our own resync
+ * activity, it obviously is "busy".
+ *
+ * The current sync rate used here uses only the most recent two step marks,
+ * to have a short time average so we can react faster.
+ */
+int drbd_rs_should_slow_down(struct drbd_conf *mdev)
+{
+	struct gendisk *disk = mdev->ldev->backing_bdev->bd_contains->bd_disk;
+	unsigned long db, dt, dbdt;
+	int curr_events;
+	int throttle = 0;
+
+	/* feature disabled? */
+	if (mdev->sync_conf.c_min_rate == 0)
+		return 0;
+
+	curr_events = (int)part_stat_read(&disk->part0, sectors[0]) +
+		      (int)part_stat_read(&disk->part0, sectors[1]) -
+			atomic_read(&mdev->rs_sect_ev);
+	if (!mdev->rs_last_events || curr_events - mdev->rs_last_events > 64) {
+		unsigned long rs_left;
+		int i;
+
+		mdev->rs_last_events = curr_events;
+
+		/* sync speed average over the last 2*DRBD_SYNC_MARK_STEP,
+		 * approx. */
+		i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-2) % DRBD_SYNC_MARKS;
+		rs_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
+
+		dt = ((long)jiffies - (long)mdev->rs_mark_time[i]) / HZ;
+		if (!dt)
+			dt++;
+		db = mdev->rs_mark_left[i] - rs_left;
+		dbdt = Bit2KB(db/dt);
+
+		if (dbdt > mdev->sync_conf.c_min_rate)
+			throttle = 1;
+	}
+	return throttle;
+}
+
+
+static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int digest_size)
 {
 	sector_t sector;
 	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
 	struct drbd_epoch_entry *e;
 	struct digest_info *di = NULL;
-	int size, digest_size;
+	int size, verb;
 	unsigned int fault_type;
-	struct p_block_req *p =
-		(struct p_block_req *)h;
-	const int brps = sizeof(*p)-sizeof(*h);
-
-	if (drbd_recv(mdev, h->payload, brps) != brps)
-		return FALSE;
+	struct p_block_req *p =	&mdev->data.rbuf.block_req;
 
 	sector = be64_to_cpu(p->sector);
 	size   = be32_to_cpu(p->blksize);
@@ -2046,12 +2098,31 @@
 	}
 
 	if (!get_ldev_if_state(mdev, D_UP_TO_DATE)) {
-		if (__ratelimit(&drbd_ratelimit_state))
+		verb = 1;
+		switch (cmd) {
+		case P_DATA_REQUEST:
+			drbd_send_ack_rp(mdev, P_NEG_DREPLY, p);
+			break;
+		case P_RS_DATA_REQUEST:
+		case P_CSUM_RS_REQUEST:
+		case P_OV_REQUEST:
+			drbd_send_ack_rp(mdev, P_NEG_RS_DREPLY , p);
+			break;
+		case P_OV_REPLY:
+			verb = 0;
+			dec_rs_pending(mdev);
+			drbd_send_ack_ex(mdev, P_OV_RESULT, sector, size, ID_IN_SYNC);
+			break;
+		default:
+			dev_err(DEV, "unexpected command (%s) in receive_DataRequest\n",
+				cmdname(cmd));
+		}
+		if (verb && __ratelimit(&drbd_ratelimit_state))
 			dev_err(DEV, "Can not satisfy peer's read request, "
 			    "no local data.\n");
-		drbd_send_ack_rp(mdev, h->command == P_DATA_REQUEST ? P_NEG_DREPLY :
-				 P_NEG_RS_DREPLY , p);
-		return drbd_drain_block(mdev, h->length - brps);
+
+		/* drain possibly payload */
+		return drbd_drain_block(mdev, digest_size);
 	}
 
 	/* GFP_NOIO, because we must not cause arbitrary write-out: in a DRBD
@@ -2063,31 +2134,21 @@
 		return FALSE;
 	}
 
-	switch (h->command) {
+	switch (cmd) {
 	case P_DATA_REQUEST:
 		e->w.cb = w_e_end_data_req;
 		fault_type = DRBD_FAULT_DT_RD;
-		break;
+		/* application IO, don't drbd_rs_begin_io */
+		goto submit;
+
 	case P_RS_DATA_REQUEST:
 		e->w.cb = w_e_end_rsdata_req;
 		fault_type = DRBD_FAULT_RS_RD;
-		/* Eventually this should become asynchronously. Currently it
-		 * blocks the whole receiver just to delay the reading of a
-		 * resync data block.
-		 * the drbd_work_queue mechanism is made for this...
-		 */
-		if (!drbd_rs_begin_io(mdev, sector)) {
-			/* we have been interrupted,
-			 * probably connection lost! */
-			D_ASSERT(signal_pending(current));
-			goto out_free_e;
-		}
 		break;
 
 	case P_OV_REPLY:
 	case P_CSUM_RS_REQUEST:
 		fault_type = DRBD_FAULT_RS_RD;
-		digest_size = h->length - brps ;
 		di = kmalloc(sizeof(*di) + digest_size, GFP_NOIO);
 		if (!di)
 			goto out_free_e;
@@ -2095,31 +2156,25 @@
 		di->digest_size = digest_size;
 		di->digest = (((char *)di)+sizeof(struct digest_info));
 
+		e->digest = di;
+		e->flags |= EE_HAS_DIGEST;
+
 		if (drbd_recv(mdev, di->digest, digest_size) != digest_size)
 			goto out_free_e;
 
-		e->block_id = (u64)(unsigned long)di;
-		if (h->command == P_CSUM_RS_REQUEST) {
+		if (cmd == P_CSUM_RS_REQUEST) {
 			D_ASSERT(mdev->agreed_pro_version >= 89);
 			e->w.cb = w_e_end_csum_rs_req;
-		} else if (h->command == P_OV_REPLY) {
+		} else if (cmd == P_OV_REPLY) {
 			e->w.cb = w_e_end_ov_reply;
 			dec_rs_pending(mdev);
-			break;
-		}
-
-		if (!drbd_rs_begin_io(mdev, sector)) {
-			/* we have been interrupted, probably connection lost! */
-			D_ASSERT(signal_pending(current));
-			goto out_free_e;
+			/* drbd_rs_begin_io done when we sent this request,
+			 * but accounting still needs to be done. */
+			goto submit_for_resync;
 		}
 		break;
 
 	case P_OV_REQUEST:
-		if (mdev->state.conn >= C_CONNECTED &&
-		    mdev->state.conn != C_VERIFY_T)
-			dev_warn(DEV, "ASSERT FAILED: got P_OV_REQUEST while being %s\n",
-				drbd_conn_str(mdev->state.conn));
 		if (mdev->ov_start_sector == ~(sector_t)0 &&
 		    mdev->agreed_pro_version >= 90) {
 			mdev->ov_start_sector = sector;
@@ -2130,37 +2185,63 @@
 		}
 		e->w.cb = w_e_end_ov_req;
 		fault_type = DRBD_FAULT_RS_RD;
-		/* Eventually this should become asynchronous. Currently it
-		 * blocks the whole receiver just to delay the reading of a
-		 * resync data block.
-		 * the drbd_work_queue mechanism is made for this...
-		 */
-		if (!drbd_rs_begin_io(mdev, sector)) {
-			/* we have been interrupted,
-			 * probably connection lost! */
-			D_ASSERT(signal_pending(current));
-			goto out_free_e;
-		}
 		break;
 
-
 	default:
 		dev_err(DEV, "unexpected command (%s) in receive_DataRequest\n",
-		    cmdname(h->command));
+		    cmdname(cmd));
 		fault_type = DRBD_FAULT_MAX;
+		goto out_free_e;
 	}
 
-	spin_lock_irq(&mdev->req_lock);
-	list_add(&e->w.list, &mdev->read_ee);
-	spin_unlock_irq(&mdev->req_lock);
+	/* Throttle, drbd_rs_begin_io and submit should become asynchronous
+	 * wrt the receiver, but it is not as straightforward as it may seem.
+	 * Various places in the resync start and stop logic assume resync
+	 * requests are processed in order, requeuing this on the worker thread
+	 * introduces a bunch of new code for synchronization between threads.
+	 *
+	 * Unlimited throttling before drbd_rs_begin_io may stall the resync
+	 * "forever", throttling after drbd_rs_begin_io will lock that extent
+	 * for application writes for the same time.  For now, just throttle
+	 * here, where the rest of the code expects the receiver to sleep for
+	 * a while, anyways.
+	 */
 
+	/* Throttle before drbd_rs_begin_io, as that locks out application IO;
+	 * this defers syncer requests for some time, before letting at least
+	 * on request through.  The resync controller on the receiving side
+	 * will adapt to the incoming rate accordingly.
+	 *
+	 * We cannot throttle here if remote is Primary/SyncTarget:
+	 * we would also throttle its application reads.
+	 * In that case, throttling is done on the SyncTarget only.
+	 */
+	if (mdev->state.peer != R_PRIMARY && drbd_rs_should_slow_down(mdev))
+		msleep(100);
+	if (drbd_rs_begin_io(mdev, e->sector))
+		goto out_free_e;
+
+submit_for_resync:
+	atomic_add(size >> 9, &mdev->rs_sect_ev);
+
+submit:
 	inc_unacked(mdev);
+	spin_lock_irq(&mdev->req_lock);
+	list_add_tail(&e->w.list, &mdev->read_ee);
+	spin_unlock_irq(&mdev->req_lock);
 
 	if (drbd_submit_ee(mdev, e, READ, fault_type) == 0)
 		return TRUE;
 
+	/* drbd_submit_ee currently fails for one reason only:
+	 * not being able to allocate enough bios.
+	 * Is dropping the connection going to help? */
+	spin_lock_irq(&mdev->req_lock);
+	list_del(&e->w.list);
+	spin_unlock_irq(&mdev->req_lock);
+	/* no drbd_rs_complete_io(), we are dropping the connection anyways */
+
 out_free_e:
-	kfree(di);
 	put_ldev(mdev);
 	drbd_free_ee(mdev, e);
 	return FALSE;
@@ -2699,20 +2780,13 @@
 	return 1;
 }
 
-static int receive_protocol(struct drbd_conf *mdev, struct p_header *h)
+static int receive_protocol(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_protocol *p = (struct p_protocol *)h;
-	int header_size, data_size;
+	struct p_protocol *p = &mdev->data.rbuf.protocol;
 	int p_proto, p_after_sb_0p, p_after_sb_1p, p_after_sb_2p;
 	int p_want_lose, p_two_primaries, cf;
 	char p_integrity_alg[SHARED_SECRET_MAX] = "";
 
-	header_size = sizeof(*p) - sizeof(*h);
-	data_size   = h->length  - header_size;
-
-	if (drbd_recv(mdev, h->payload, header_size) != header_size)
-		return FALSE;
-
 	p_proto		= be32_to_cpu(p->protocol);
 	p_after_sb_0p	= be32_to_cpu(p->after_sb_0p);
 	p_after_sb_1p	= be32_to_cpu(p->after_sb_1p);
@@ -2805,39 +2879,46 @@
 	return tfm;
 }
 
-static int receive_SyncParam(struct drbd_conf *mdev, struct p_header *h)
+static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int packet_size)
 {
 	int ok = TRUE;
-	struct p_rs_param_89 *p = (struct p_rs_param_89 *)h;
+	struct p_rs_param_95 *p = &mdev->data.rbuf.rs_param_95;
 	unsigned int header_size, data_size, exp_max_sz;
 	struct crypto_hash *verify_tfm = NULL;
 	struct crypto_hash *csums_tfm = NULL;
 	const int apv = mdev->agreed_pro_version;
+	int *rs_plan_s = NULL;
+	int fifo_size = 0;
 
 	exp_max_sz  = apv <= 87 ? sizeof(struct p_rs_param)
 		    : apv == 88 ? sizeof(struct p_rs_param)
 					+ SHARED_SECRET_MAX
-		    : /* 89 */    sizeof(struct p_rs_param_89);
+		    : apv <= 94 ? sizeof(struct p_rs_param_89)
+		    : /* apv >= 95 */ sizeof(struct p_rs_param_95);
 
-	if (h->length > exp_max_sz) {
+	if (packet_size > exp_max_sz) {
 		dev_err(DEV, "SyncParam packet too long: received %u, expected <= %u bytes\n",
-		    h->length, exp_max_sz);
+		    packet_size, exp_max_sz);
 		return FALSE;
 	}
 
 	if (apv <= 88) {
-		header_size = sizeof(struct p_rs_param) - sizeof(*h);
-		data_size   = h->length  - header_size;
-	} else /* apv >= 89 */ {
-		header_size = sizeof(struct p_rs_param_89) - sizeof(*h);
-		data_size   = h->length  - header_size;
+		header_size = sizeof(struct p_rs_param) - sizeof(struct p_header80);
+		data_size   = packet_size  - header_size;
+	} else if (apv <= 94) {
+		header_size = sizeof(struct p_rs_param_89) - sizeof(struct p_header80);
+		data_size   = packet_size  - header_size;
+		D_ASSERT(data_size == 0);
+	} else {
+		header_size = sizeof(struct p_rs_param_95) - sizeof(struct p_header80);
+		data_size   = packet_size  - header_size;
 		D_ASSERT(data_size == 0);
 	}
 
 	/* initialize verify_alg and csums_alg */
 	memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
 
-	if (drbd_recv(mdev, h->payload, header_size) != header_size)
+	if (drbd_recv(mdev, &p->head.payload, header_size) != header_size)
 		return FALSE;
 
 	mdev->sync_conf.rate	  = be32_to_cpu(p->rate);
@@ -2896,6 +2977,22 @@
 			}
 		}
 
+		if (apv > 94) {
+			mdev->sync_conf.rate	  = be32_to_cpu(p->rate);
+			mdev->sync_conf.c_plan_ahead = be32_to_cpu(p->c_plan_ahead);
+			mdev->sync_conf.c_delay_target = be32_to_cpu(p->c_delay_target);
+			mdev->sync_conf.c_fill_target = be32_to_cpu(p->c_fill_target);
+			mdev->sync_conf.c_max_rate = be32_to_cpu(p->c_max_rate);
+
+			fifo_size = (mdev->sync_conf.c_plan_ahead * 10 * SLEEP_TIME) / HZ;
+			if (fifo_size != mdev->rs_plan_s.size && fifo_size > 0) {
+				rs_plan_s   = kzalloc(sizeof(int) * fifo_size, GFP_KERNEL);
+				if (!rs_plan_s) {
+					dev_err(DEV, "kmalloc of fifo_buffer failed");
+					goto disconnect;
+				}
+			}
+		}
 
 		spin_lock(&mdev->peer_seq_lock);
 		/* lock against drbd_nl_syncer_conf() */
@@ -2913,6 +3010,12 @@
 			mdev->csums_tfm = csums_tfm;
 			dev_info(DEV, "using csums-alg: \"%s\"\n", p->csums_alg);
 		}
+		if (fifo_size != mdev->rs_plan_s.size) {
+			kfree(mdev->rs_plan_s.values);
+			mdev->rs_plan_s.values = rs_plan_s;
+			mdev->rs_plan_s.size   = fifo_size;
+			mdev->rs_planed = 0;
+		}
 		spin_unlock(&mdev->peer_seq_lock);
 	}
 
@@ -2946,19 +3049,15 @@
 		     (unsigned long long)a, (unsigned long long)b);
 }
 
-static int receive_sizes(struct drbd_conf *mdev, struct p_header *h)
+static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_sizes *p = (struct p_sizes *)h;
+	struct p_sizes *p = &mdev->data.rbuf.sizes;
 	enum determine_dev_size dd = unchanged;
 	unsigned int max_seg_s;
 	sector_t p_size, p_usize, my_usize;
 	int ldsc = 0; /* local disk size changed */
 	enum dds_flags ddsf;
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
-	if (drbd_recv(mdev, h->payload, h->length) != h->length)
-		return FALSE;
-
 	p_size = be64_to_cpu(p->d_size);
 	p_usize = be64_to_cpu(p->u_size);
 
@@ -2972,7 +3071,6 @@
 	 * we still need to figure out whether we accept that. */
 	mdev->p_size = p_size;
 
-#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
 	if (get_ldev(mdev)) {
 		warn_if_differ_considerably(mdev, "lower level device sizes",
 			   p_size, drbd_get_max_capacity(mdev->ldev));
@@ -3029,6 +3127,8 @@
 
 		if (mdev->agreed_pro_version < 94)
 			max_seg_s = be32_to_cpu(p->max_segment_size);
+		else if (mdev->agreed_pro_version == 94)
+			max_seg_s = DRBD_MAX_SIZE_H80_PACKET;
 		else /* drbd 8.3.8 onwards */
 			max_seg_s = DRBD_MAX_SEGMENT_SIZE;
 
@@ -3062,16 +3162,12 @@
 	return TRUE;
 }
 
-static int receive_uuids(struct drbd_conf *mdev, struct p_header *h)
+static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_uuids *p = (struct p_uuids *)h;
+	struct p_uuids *p = &mdev->data.rbuf.uuids;
 	u64 *p_uuid;
 	int i;
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
-	if (drbd_recv(mdev, h->payload, h->length) != h->length)
-		return FALSE;
-
 	p_uuid = kmalloc(sizeof(u64)*UI_EXTENDED_SIZE, GFP_NOIO);
 
 	for (i = UI_CURRENT; i < UI_EXTENDED_SIZE; i++)
@@ -3107,6 +3203,11 @@
 			drbd_md_sync(mdev);
 		}
 		put_ldev(mdev);
+	} else if (mdev->state.disk < D_INCONSISTENT &&
+		   mdev->state.role == R_PRIMARY) {
+		/* I am a diskless primary, the peer just created a new current UUID
+		   for me. */
+		drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
 	}
 
 	/* Before we test for the disk state, we should wait until an eventually
@@ -3150,16 +3251,12 @@
 	return ms;
 }
 
-static int receive_req_state(struct drbd_conf *mdev, struct p_header *h)
+static int receive_req_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_req_state *p = (struct p_req_state *)h;
+	struct p_req_state *p = &mdev->data.rbuf.req_state;
 	union drbd_state mask, val;
 	int rv;
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
-	if (drbd_recv(mdev, h->payload, h->length) != h->length)
-		return FALSE;
-
 	mask.i = be32_to_cpu(p->mask);
 	val.i = be32_to_cpu(p->val);
 
@@ -3180,20 +3277,14 @@
 	return TRUE;
 }
 
-static int receive_state(struct drbd_conf *mdev, struct p_header *h)
+static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_state *p = (struct p_state *)h;
-	enum drbd_conns nconn, oconn;
-	union drbd_state ns, peer_state;
+	struct p_state *p = &mdev->data.rbuf.state;
+	union drbd_state os, ns, peer_state;
 	enum drbd_disk_state real_peer_disk;
+	enum chg_state_flags cs_flags;
 	int rv;
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h)))
-		return FALSE;
-
-	if (drbd_recv(mdev, h->payload, h->length) != h->length)
-		return FALSE;
-
 	peer_state.i = be32_to_cpu(p->state);
 
 	real_peer_disk = peer_state.disk;
@@ -3204,38 +3295,72 @@
 
 	spin_lock_irq(&mdev->req_lock);
  retry:
-	oconn = nconn = mdev->state.conn;
+	os = ns = mdev->state;
 	spin_unlock_irq(&mdev->req_lock);
 
-	if (nconn == C_WF_REPORT_PARAMS)
-		nconn = C_CONNECTED;
+	/* peer says his disk is uptodate, while we think it is inconsistent,
+	 * and this happens while we think we have a sync going on. */
+	if (os.pdsk == D_INCONSISTENT && real_peer_disk == D_UP_TO_DATE &&
+	    os.conn > C_CONNECTED && os.disk == D_UP_TO_DATE) {
+		/* If we are (becoming) SyncSource, but peer is still in sync
+		 * preparation, ignore its uptodate-ness to avoid flapping, it
+		 * will change to inconsistent once the peer reaches active
+		 * syncing states.
+		 * It may have changed syncer-paused flags, however, so we
+		 * cannot ignore this completely. */
+		if (peer_state.conn > C_CONNECTED &&
+		    peer_state.conn < C_SYNC_SOURCE)
+			real_peer_disk = D_INCONSISTENT;
+
+		/* if peer_state changes to connected at the same time,
+		 * it explicitly notifies us that it finished resync.
+		 * Maybe we should finish it up, too? */
+		else if (os.conn >= C_SYNC_SOURCE &&
+			 peer_state.conn == C_CONNECTED) {
+			if (drbd_bm_total_weight(mdev) <= mdev->rs_failed)
+				drbd_resync_finished(mdev);
+			return TRUE;
+		}
+	}
+
+	/* peer says his disk is inconsistent, while we think it is uptodate,
+	 * and this happens while the peer still thinks we have a sync going on,
+	 * but we think we are already done with the sync.
+	 * We ignore this to avoid flapping pdsk.
+	 * This should not happen, if the peer is a recent version of drbd. */
+	if (os.pdsk == D_UP_TO_DATE && real_peer_disk == D_INCONSISTENT &&
+	    os.conn == C_CONNECTED && peer_state.conn > C_SYNC_SOURCE)
+		real_peer_disk = D_UP_TO_DATE;
+
+	if (ns.conn == C_WF_REPORT_PARAMS)
+		ns.conn = C_CONNECTED;
 
 	if (mdev->p_uuid && peer_state.disk >= D_NEGOTIATING &&
 	    get_ldev_if_state(mdev, D_NEGOTIATING)) {
 		int cr; /* consider resync */
 
 		/* if we established a new connection */
-		cr  = (oconn < C_CONNECTED);
+		cr  = (os.conn < C_CONNECTED);
 		/* if we had an established connection
 		 * and one of the nodes newly attaches a disk */
-		cr |= (oconn == C_CONNECTED &&
+		cr |= (os.conn == C_CONNECTED &&
 		       (peer_state.disk == D_NEGOTIATING ||
-			mdev->state.disk == D_NEGOTIATING));
+			os.disk == D_NEGOTIATING));
 		/* if we have both been inconsistent, and the peer has been
 		 * forced to be UpToDate with --overwrite-data */
 		cr |= test_bit(CONSIDER_RESYNC, &mdev->flags);
 		/* if we had been plain connected, and the admin requested to
 		 * start a sync by "invalidate" or "invalidate-remote" */
-		cr |= (oconn == C_CONNECTED &&
+		cr |= (os.conn == C_CONNECTED &&
 				(peer_state.conn >= C_STARTING_SYNC_S &&
 				 peer_state.conn <= C_WF_BITMAP_T));
 
 		if (cr)
-			nconn = drbd_sync_handshake(mdev, peer_state.role, real_peer_disk);
+			ns.conn = drbd_sync_handshake(mdev, peer_state.role, real_peer_disk);
 
 		put_ldev(mdev);
-		if (nconn == C_MASK) {
-			nconn = C_CONNECTED;
+		if (ns.conn == C_MASK) {
+			ns.conn = C_CONNECTED;
 			if (mdev->state.disk == D_NEGOTIATING) {
 				drbd_force_state(mdev, NS(disk, D_DISKLESS));
 			} else if (peer_state.disk == D_NEGOTIATING) {
@@ -3245,7 +3370,7 @@
 			} else {
 				if (test_and_clear_bit(CONN_DRY_RUN, &mdev->flags))
 					return FALSE;
-				D_ASSERT(oconn == C_WF_REPORT_PARAMS);
+				D_ASSERT(os.conn == C_WF_REPORT_PARAMS);
 				drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
 				return FALSE;
 			}
@@ -3253,18 +3378,28 @@
 	}
 
 	spin_lock_irq(&mdev->req_lock);
-	if (mdev->state.conn != oconn)
+	if (mdev->state.i != os.i)
 		goto retry;
 	clear_bit(CONSIDER_RESYNC, &mdev->flags);
-	ns.i = mdev->state.i;
-	ns.conn = nconn;
 	ns.peer = peer_state.role;
 	ns.pdsk = real_peer_disk;
 	ns.peer_isp = (peer_state.aftr_isp | peer_state.user_isp);
-	if ((nconn == C_CONNECTED || nconn == C_WF_BITMAP_S) && ns.disk == D_NEGOTIATING)
+	if ((ns.conn == C_CONNECTED || ns.conn == C_WF_BITMAP_S) && ns.disk == D_NEGOTIATING)
 		ns.disk = mdev->new_state_tmp.disk;
-
-	rv = _drbd_set_state(mdev, ns, CS_VERBOSE | CS_HARD, NULL);
+	cs_flags = CS_VERBOSE + (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED ? 0 : CS_HARD);
+	if (ns.pdsk == D_CONSISTENT && is_susp(ns) && ns.conn == C_CONNECTED && os.conn < C_CONNECTED &&
+	    test_bit(NEW_CUR_UUID, &mdev->flags)) {
+		/* Do not allow tl_restart(resend) for a rebooted peer. We can only allow this
+		   for temporal network outages! */
+		spin_unlock_irq(&mdev->req_lock);
+		dev_err(DEV, "Aborting Connect, can not thaw IO with an only Consistent peer\n");
+		tl_clear(mdev);
+		drbd_uuid_new_current(mdev);
+		clear_bit(NEW_CUR_UUID, &mdev->flags);
+		drbd_force_state(mdev, NS2(conn, C_PROTOCOL_ERROR, susp, 0));
+		return FALSE;
+	}
+	rv = _drbd_set_state(mdev, ns, cs_flags, NULL);
 	ns = mdev->state;
 	spin_unlock_irq(&mdev->req_lock);
 
@@ -3273,8 +3408,8 @@
 		return FALSE;
 	}
 
-	if (oconn > C_WF_REPORT_PARAMS) {
-		if (nconn > C_CONNECTED && peer_state.conn <= C_CONNECTED &&
+	if (os.conn > C_WF_REPORT_PARAMS) {
+		if (ns.conn > C_CONNECTED && peer_state.conn <= C_CONNECTED &&
 		    peer_state.disk != D_NEGOTIATING ) {
 			/* we want resync, peer has not yet decided to sync... */
 			/* Nowadays only used when forcing a node into primary role and
@@ -3291,9 +3426,9 @@
 	return TRUE;
 }
 
-static int receive_sync_uuid(struct drbd_conf *mdev, struct p_header *h)
+static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_rs_uuid *p = (struct p_rs_uuid *)h;
+	struct p_rs_uuid *p = &mdev->data.rbuf.rs_uuid;
 
 	wait_event(mdev->misc_wait,
 		   mdev->state.conn == C_WF_SYNC_UUID ||
@@ -3302,10 +3437,6 @@
 
 	/* D_ASSERT( mdev->state.conn == C_WF_SYNC_UUID ); */
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
-	if (drbd_recv(mdev, h->payload, h->length) != h->length)
-		return FALSE;
-
 	/* Here the _drbd_uuid_ functions are right, current should
 	   _not_ be rotated into the history */
 	if (get_ldev_if_state(mdev, D_NEGOTIATING)) {
@@ -3324,14 +3455,14 @@
 enum receive_bitmap_ret { OK, DONE, FAILED };
 
 static enum receive_bitmap_ret
-receive_bitmap_plain(struct drbd_conf *mdev, struct p_header *h,
-	unsigned long *buffer, struct bm_xfer_ctx *c)
+receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size,
+		     unsigned long *buffer, struct bm_xfer_ctx *c)
 {
 	unsigned num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset);
 	unsigned want = num_words * sizeof(long);
 
-	if (want != h->length) {
-		dev_err(DEV, "%s:want (%u) != h->length (%u)\n", __func__, want, h->length);
+	if (want != data_size) {
+		dev_err(DEV, "%s:want (%u) != data_size (%u)\n", __func__, want, data_size);
 		return FAILED;
 	}
 	if (want == 0)
@@ -3360,7 +3491,7 @@
 	u64 tmp;
 	unsigned long s = c->bit_offset;
 	unsigned long e;
-	int len = p->head.length - (sizeof(*p) - sizeof(p->head));
+	int len = be16_to_cpu(p->head.length) - (sizeof(*p) - sizeof(p->head));
 	int toggle = DCBP_get_start(p);
 	int have;
 	int bits;
@@ -3429,7 +3560,7 @@
 		const char *direction, struct bm_xfer_ctx *c)
 {
 	/* what would it take to transfer it "plaintext" */
-	unsigned plain = sizeof(struct p_header) *
+	unsigned plain = sizeof(struct p_header80) *
 		((c->bm_words+BM_PACKET_WORDS-1)/BM_PACKET_WORDS+1)
 		+ c->bm_words * sizeof(long);
 	unsigned total = c->bytes[0] + c->bytes[1];
@@ -3467,12 +3598,13 @@
    in order to be agnostic to the 32 vs 64 bits issue.
 
    returns 0 on failure, 1 if we successfully received it. */
-static int receive_bitmap(struct drbd_conf *mdev, struct p_header *h)
+static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	struct bm_xfer_ctx c;
 	void *buffer;
 	enum receive_bitmap_ret ret;
 	int ok = FALSE;
+	struct p_header80 *h = &mdev->data.rbuf.header.h80;
 
 	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
 
@@ -3492,39 +3624,39 @@
 	};
 
 	do {
-		if (h->command == P_BITMAP) {
-			ret = receive_bitmap_plain(mdev, h, buffer, &c);
-		} else if (h->command == P_COMPRESSED_BITMAP) {
+		if (cmd == P_BITMAP) {
+			ret = receive_bitmap_plain(mdev, data_size, buffer, &c);
+		} else if (cmd == P_COMPRESSED_BITMAP) {
 			/* MAYBE: sanity check that we speak proto >= 90,
 			 * and the feature is enabled! */
 			struct p_compressed_bm *p;
 
-			if (h->length > BM_PACKET_PAYLOAD_BYTES) {
+			if (data_size > BM_PACKET_PAYLOAD_BYTES) {
 				dev_err(DEV, "ReportCBitmap packet too large\n");
 				goto out;
 			}
 			/* use the page buff */
 			p = buffer;
 			memcpy(p, h, sizeof(*h));
-			if (drbd_recv(mdev, p->head.payload, h->length) != h->length)
+			if (drbd_recv(mdev, p->head.payload, data_size) != data_size)
 				goto out;
-			if (p->head.length <= (sizeof(*p) - sizeof(p->head))) {
-				dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", p->head.length);
+			if (data_size <= (sizeof(*p) - sizeof(p->head))) {
+				dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", data_size);
 				return FAILED;
 			}
 			ret = decode_bitmap_c(mdev, p, &c);
 		} else {
-			dev_warn(DEV, "receive_bitmap: h->command neither ReportBitMap nor ReportCBitMap (is 0x%x)", h->command);
+			dev_warn(DEV, "receive_bitmap: cmd neither ReportBitMap nor ReportCBitMap (is 0x%x)", cmd);
 			goto out;
 		}
 
-		c.packets[h->command == P_BITMAP]++;
-		c.bytes[h->command == P_BITMAP] += sizeof(struct p_header) + h->length;
+		c.packets[cmd == P_BITMAP]++;
+		c.bytes[cmd == P_BITMAP] += sizeof(struct p_header80) + data_size;
 
 		if (ret != OK)
 			break;
 
-		if (!drbd_recv_header(mdev, h))
+		if (!drbd_recv_header(mdev, &cmd, &data_size))
 			goto out;
 	} while (ret == OK);
 	if (ret == FAILED)
@@ -3555,17 +3687,16 @@
 	return ok;
 }
 
-static int receive_skip_(struct drbd_conf *mdev, struct p_header *h, int silent)
+static int receive_skip(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	/* TODO zero copy sink :) */
 	static char sink[128];
 	int size, want, r;
 
-	if (!silent)
-		dev_warn(DEV, "skipping unknown optional packet type %d, l: %d!\n",
-		     h->command, h->length);
+	dev_warn(DEV, "skipping unknown optional packet type %d, l: %d!\n",
+		 cmd, data_size);
 
-	size = h->length;
+	size = data_size;
 	while (size > 0) {
 		want = min_t(int, size, sizeof(sink));
 		r = drbd_recv(mdev, sink, want);
@@ -3575,17 +3706,7 @@
 	return size == 0;
 }
 
-static int receive_skip(struct drbd_conf *mdev, struct p_header *h)
-{
-	return receive_skip_(mdev, h, 0);
-}
-
-static int receive_skip_silent(struct drbd_conf *mdev, struct p_header *h)
-{
-	return receive_skip_(mdev, h, 1);
-}
-
-static int receive_UnplugRemote(struct drbd_conf *mdev, struct p_header *h)
+static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	if (mdev->state.disk >= D_INCONSISTENT)
 		drbd_kick_lo(mdev);
@@ -3597,108 +3718,94 @@
 	return TRUE;
 }
 
-typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, struct p_header *);
+typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive);
 
-static drbd_cmd_handler_f drbd_default_handler[] = {
-	[P_DATA]	    = receive_Data,
-	[P_DATA_REPLY]	    = receive_DataReply,
-	[P_RS_DATA_REPLY]   = receive_RSDataReply,
-	[P_BARRIER]	    = receive_Barrier,
-	[P_BITMAP]	    = receive_bitmap,
-	[P_COMPRESSED_BITMAP]    = receive_bitmap,
-	[P_UNPLUG_REMOTE]   = receive_UnplugRemote,
-	[P_DATA_REQUEST]    = receive_DataRequest,
-	[P_RS_DATA_REQUEST] = receive_DataRequest,
-	[P_SYNC_PARAM]	    = receive_SyncParam,
-	[P_SYNC_PARAM89]	   = receive_SyncParam,
-	[P_PROTOCOL]        = receive_protocol,
-	[P_UUIDS]	    = receive_uuids,
-	[P_SIZES]	    = receive_sizes,
-	[P_STATE]	    = receive_state,
-	[P_STATE_CHG_REQ]   = receive_req_state,
-	[P_SYNC_UUID]       = receive_sync_uuid,
-	[P_OV_REQUEST]      = receive_DataRequest,
-	[P_OV_REPLY]        = receive_DataRequest,
-	[P_CSUM_RS_REQUEST]    = receive_DataRequest,
-	[P_DELAY_PROBE]     = receive_skip_silent,
-	/* anything missing from this table is in
-	 * the asender_tbl, see get_asender_cmd */
-	[P_MAX_CMD]	    = NULL,
+struct data_cmd {
+	int expect_payload;
+	size_t pkt_size;
+	drbd_cmd_handler_f function;
 };
 
-static drbd_cmd_handler_f *drbd_cmd_handler = drbd_default_handler;
-static drbd_cmd_handler_f *drbd_opt_cmd_handler;
+static struct data_cmd drbd_cmd_handler[] = {
+	[P_DATA]	    = { 1, sizeof(struct p_data), receive_Data },
+	[P_DATA_REPLY]	    = { 1, sizeof(struct p_data), receive_DataReply },
+	[P_RS_DATA_REPLY]   = { 1, sizeof(struct p_data), receive_RSDataReply } ,
+	[P_BARRIER]	    = { 0, sizeof(struct p_barrier), receive_Barrier } ,
+	[P_BITMAP]	    = { 1, sizeof(struct p_header80), receive_bitmap } ,
+	[P_COMPRESSED_BITMAP] = { 1, sizeof(struct p_header80), receive_bitmap } ,
+	[P_UNPLUG_REMOTE]   = { 0, sizeof(struct p_header80), receive_UnplugRemote },
+	[P_DATA_REQUEST]    = { 0, sizeof(struct p_block_req), receive_DataRequest },
+	[P_RS_DATA_REQUEST] = { 0, sizeof(struct p_block_req), receive_DataRequest },
+	[P_SYNC_PARAM]	    = { 1, sizeof(struct p_header80), receive_SyncParam },
+	[P_SYNC_PARAM89]    = { 1, sizeof(struct p_header80), receive_SyncParam },
+	[P_PROTOCOL]        = { 1, sizeof(struct p_protocol), receive_protocol },
+	[P_UUIDS]	    = { 0, sizeof(struct p_uuids), receive_uuids },
+	[P_SIZES]	    = { 0, sizeof(struct p_sizes), receive_sizes },
+	[P_STATE]	    = { 0, sizeof(struct p_state), receive_state },
+	[P_STATE_CHG_REQ]   = { 0, sizeof(struct p_req_state), receive_req_state },
+	[P_SYNC_UUID]       = { 0, sizeof(struct p_rs_uuid), receive_sync_uuid },
+	[P_OV_REQUEST]      = { 0, sizeof(struct p_block_req), receive_DataRequest },
+	[P_OV_REPLY]        = { 1, sizeof(struct p_block_req), receive_DataRequest },
+	[P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest },
+	[P_DELAY_PROBE]     = { 0, sizeof(struct p_delay_probe93), receive_skip },
+	/* anything missing from this table is in
+	 * the asender_tbl, see get_asender_cmd */
+	[P_MAX_CMD]	    = { 0, 0, NULL },
+};
+
+/* All handler functions that expect a sub-header get that sub-heder in
+   mdev->data.rbuf.header.head.payload.
+
+   Usually in mdev->data.rbuf.header.head the callback can find the usual
+   p_header, but they may not rely on that. Since there is also p_header95 !
+ */
 
 static void drbdd(struct drbd_conf *mdev)
 {
-	drbd_cmd_handler_f handler;
-	struct p_header *header = &mdev->data.rbuf.header;
+	union p_header *header = &mdev->data.rbuf.header;
+	unsigned int packet_size;
+	enum drbd_packets cmd;
+	size_t shs; /* sub header size */
+	int rv;
 
 	while (get_t_state(&mdev->receiver) == Running) {
 		drbd_thread_current_set_cpu(mdev);
-		if (!drbd_recv_header(mdev, header)) {
-			drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
-			break;
+		if (!drbd_recv_header(mdev, &cmd, &packet_size))
+			goto err_out;
+
+		if (unlikely(cmd >= P_MAX_CMD || !drbd_cmd_handler[cmd].function)) {
+			dev_err(DEV, "unknown packet type %d, l: %d!\n", cmd, packet_size);
+			goto err_out;
 		}
 
-		if (header->command < P_MAX_CMD)
-			handler = drbd_cmd_handler[header->command];
-		else if (P_MAY_IGNORE < header->command
-		     && header->command < P_MAX_OPT_CMD)
-			handler = drbd_opt_cmd_handler[header->command-P_MAY_IGNORE];
-		else if (header->command > P_MAX_OPT_CMD)
-			handler = receive_skip;
-		else
-			handler = NULL;
-
-		if (unlikely(!handler)) {
-			dev_err(DEV, "unknown packet type %d, l: %d!\n",
-			    header->command, header->length);
-			drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
-			break;
+		shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header);
+		rv = drbd_recv(mdev, &header->h80.payload, shs);
+		if (unlikely(rv != shs)) {
+			dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
+			goto err_out;
 		}
-		if (unlikely(!handler(mdev, header))) {
+
+		if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) {
+			dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size);
+			goto err_out;
+		}
+
+		rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs);
+
+		if (unlikely(!rv)) {
 			dev_err(DEV, "error receiving %s, l: %d!\n",
-			    cmdname(header->command), header->length);
-			drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
-			break;
+			    cmdname(cmd), packet_size);
+			goto err_out;
 		}
 	}
-}
 
-static void drbd_fail_pending_reads(struct drbd_conf *mdev)
-{
-	struct hlist_head *slot;
-	struct hlist_node *pos;
-	struct hlist_node *tmp;
-	struct drbd_request *req;
-	int i;
-
-	/*
-	 * Application READ requests
-	 */
-	spin_lock_irq(&mdev->req_lock);
-	for (i = 0; i < APP_R_HSIZE; i++) {
-		slot = mdev->app_reads_hash+i;
-		hlist_for_each_entry_safe(req, pos, tmp, slot, colision) {
-			/* it may (but should not any longer!)
-			 * be on the work queue; if that assert triggers,
-			 * we need to also grab the
-			 * spin_lock_irq(&mdev->data.work.q_lock);
-			 * and list_del_init here. */
-			D_ASSERT(list_empty(&req->w.list));
-			/* It would be nice to complete outside of spinlock.
-			 * But this is easier for now. */
-			_req_mod(req, connection_lost_while_pending);
-		}
+	if (0) {
+	err_out:
+		drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
 	}
-	for (i = 0; i < APP_R_HSIZE; i++)
-		if (!hlist_empty(mdev->app_reads_hash+i))
-			dev_warn(DEV, "ASSERT FAILED: app_reads_hash[%d].first: "
-				"%p, should be NULL\n", i, mdev->app_reads_hash[i].first);
-
-	memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *));
-	spin_unlock_irq(&mdev->req_lock);
+	/* If we leave here, we probably want to update at least the
+	 * "Connected" indicator on stable storage. Do so explicitly here. */
+	drbd_md_sync(mdev);
 }
 
 void drbd_flush_workqueue(struct drbd_conf *mdev)
@@ -3711,6 +3818,36 @@
 	wait_for_completion(&barr.done);
 }
 
+void drbd_free_tl_hash(struct drbd_conf *mdev)
+{
+	struct hlist_head *h;
+
+	spin_lock_irq(&mdev->req_lock);
+
+	if (!mdev->tl_hash || mdev->state.conn != C_STANDALONE) {
+		spin_unlock_irq(&mdev->req_lock);
+		return;
+	}
+	/* paranoia code */
+	for (h = mdev->ee_hash; h < mdev->ee_hash + mdev->ee_hash_s; h++)
+		if (h->first)
+			dev_err(DEV, "ASSERT FAILED ee_hash[%u].first == %p, expected NULL\n",
+				(int)(h - mdev->ee_hash), h->first);
+	kfree(mdev->ee_hash);
+	mdev->ee_hash = NULL;
+	mdev->ee_hash_s = 0;
+
+	/* paranoia code */
+	for (h = mdev->tl_hash; h < mdev->tl_hash + mdev->tl_hash_s; h++)
+		if (h->first)
+			dev_err(DEV, "ASSERT FAILED tl_hash[%u] == %p, expected NULL\n",
+				(int)(h - mdev->tl_hash), h->first);
+	kfree(mdev->tl_hash);
+	mdev->tl_hash = NULL;
+	mdev->tl_hash_s = 0;
+	spin_unlock_irq(&mdev->req_lock);
+}
+
 static void drbd_disconnect(struct drbd_conf *mdev)
 {
 	enum drbd_fencing_p fp;
@@ -3728,6 +3865,7 @@
 	drbd_thread_stop(&mdev->asender);
 	drbd_free_sock(mdev);
 
+	/* wait for current activity to cease. */
 	spin_lock_irq(&mdev->req_lock);
 	_drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
 	_drbd_wait_ee_list_empty(mdev, &mdev->sync_ee);
@@ -3752,7 +3890,6 @@
 
 	/* make sure syncer is stopped and w_resume_next_sg queued */
 	del_timer_sync(&mdev->resync_timer);
-	set_bit(STOP_SYNC_TIMER, &mdev->flags);
 	resync_timer_fn((unsigned long)mdev);
 
 	/* wait for all w_e_end_data_req, w_e_end_rsdata_req, w_send_barrier,
@@ -3767,11 +3904,9 @@
 	kfree(mdev->p_uuid);
 	mdev->p_uuid = NULL;
 
-	if (!mdev->state.susp)
+	if (!is_susp(mdev->state))
 		tl_clear(mdev);
 
-	drbd_fail_pending_reads(mdev);
-
 	dev_info(DEV, "Connection closed\n");
 
 	drbd_md_sync(mdev);
@@ -3782,12 +3917,8 @@
 		put_ldev(mdev);
 	}
 
-	if (mdev->state.role == R_PRIMARY) {
-		if (fp >= FP_RESOURCE && mdev->state.pdsk >= D_UNKNOWN) {
-			enum drbd_disk_state nps = drbd_try_outdate_peer(mdev);
-			drbd_request_state(mdev, NS(pdsk, nps));
-		}
-	}
+	if (mdev->state.role == R_PRIMARY && fp >= FP_RESOURCE && mdev->state.pdsk >= D_UNKNOWN)
+		drbd_try_outdate_peer_async(mdev);
 
 	spin_lock_irq(&mdev->req_lock);
 	os = mdev->state;
@@ -3800,32 +3931,14 @@
 	spin_unlock_irq(&mdev->req_lock);
 
 	if (os.conn == C_DISCONNECTING) {
-		struct hlist_head *h;
-		wait_event(mdev->misc_wait, atomic_read(&mdev->net_cnt) == 0);
+		wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0);
 
-		/* we must not free the tl_hash
-		 * while application io is still on the fly */
-		wait_event(mdev->misc_wait, atomic_read(&mdev->ap_bio_cnt) == 0);
-
-		spin_lock_irq(&mdev->req_lock);
-		/* paranoia code */
-		for (h = mdev->ee_hash; h < mdev->ee_hash + mdev->ee_hash_s; h++)
-			if (h->first)
-				dev_err(DEV, "ASSERT FAILED ee_hash[%u].first == %p, expected NULL\n",
-						(int)(h - mdev->ee_hash), h->first);
-		kfree(mdev->ee_hash);
-		mdev->ee_hash = NULL;
-		mdev->ee_hash_s = 0;
-
-		/* paranoia code */
-		for (h = mdev->tl_hash; h < mdev->tl_hash + mdev->tl_hash_s; h++)
-			if (h->first)
-				dev_err(DEV, "ASSERT FAILED tl_hash[%u] == %p, expected NULL\n",
-						(int)(h - mdev->tl_hash), h->first);
-		kfree(mdev->tl_hash);
-		mdev->tl_hash = NULL;
-		mdev->tl_hash_s = 0;
-		spin_unlock_irq(&mdev->req_lock);
+		if (!is_susp(mdev->state)) {
+			/* we must not free the tl_hash
+			 * while application io is still on the fly */
+			wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
+			drbd_free_tl_hash(mdev);
+		}
 
 		crypto_free_hash(mdev->cram_hmac_tfm);
 		mdev->cram_hmac_tfm = NULL;
@@ -3845,6 +3958,9 @@
 	i = drbd_release_ee(mdev, &mdev->net_ee);
 	if (i)
 		dev_info(DEV, "net_ee not empty, killed %u entries\n", i);
+	i = atomic_read(&mdev->pp_in_use_by_net);
+	if (i)
+		dev_info(DEV, "pp_in_use_by_net = %d, expected 0\n", i);
 	i = atomic_read(&mdev->pp_in_use);
 	if (i)
 		dev_info(DEV, "pp_in_use = %d, expected 0\n", i);
@@ -3888,7 +4004,7 @@
 	p->protocol_min = cpu_to_be32(PRO_VERSION_MIN);
 	p->protocol_max = cpu_to_be32(PRO_VERSION_MAX);
 	ok = _drbd_send_cmd( mdev, mdev->data.socket, P_HAND_SHAKE,
-			     (struct p_header *)p, sizeof(*p), 0 );
+			     (struct p_header80 *)p, sizeof(*p), 0 );
 	mutex_unlock(&mdev->data.mutex);
 	return ok;
 }
@@ -3904,27 +4020,28 @@
 {
 	/* ASSERT current == mdev->receiver ... */
 	struct p_handshake *p = &mdev->data.rbuf.handshake;
-	const int expect = sizeof(struct p_handshake)
-			  -sizeof(struct p_header);
+	const int expect = sizeof(struct p_handshake) - sizeof(struct p_header80);
+	unsigned int length;
+	enum drbd_packets cmd;
 	int rv;
 
 	rv = drbd_send_handshake(mdev);
 	if (!rv)
 		return 0;
 
-	rv = drbd_recv_header(mdev, &p->head);
+	rv = drbd_recv_header(mdev, &cmd, &length);
 	if (!rv)
 		return 0;
 
-	if (p->head.command != P_HAND_SHAKE) {
+	if (cmd != P_HAND_SHAKE) {
 		dev_err(DEV, "expected HandShake packet, received: %s (0x%04x)\n",
-		     cmdname(p->head.command), p->head.command);
+		     cmdname(cmd), cmd);
 		return -1;
 	}
 
-	if (p->head.length != expect) {
+	if (length != expect) {
 		dev_err(DEV, "expected HandShake length: %u, received: %u\n",
-		     expect, p->head.length);
+		     expect, length);
 		return -1;
 	}
 
@@ -3982,10 +4099,11 @@
 	char *response = NULL;
 	char *right_response = NULL;
 	char *peers_ch = NULL;
-	struct p_header p;
 	unsigned int key_len = strlen(mdev->net_conf->shared_secret);
 	unsigned int resp_size;
 	struct hash_desc desc;
+	enum drbd_packets cmd;
+	unsigned int length;
 	int rv;
 
 	desc.tfm = mdev->cram_hmac_tfm;
@@ -4005,33 +4123,33 @@
 	if (!rv)
 		goto fail;
 
-	rv = drbd_recv_header(mdev, &p);
+	rv = drbd_recv_header(mdev, &cmd, &length);
 	if (!rv)
 		goto fail;
 
-	if (p.command != P_AUTH_CHALLENGE) {
+	if (cmd != P_AUTH_CHALLENGE) {
 		dev_err(DEV, "expected AuthChallenge packet, received: %s (0x%04x)\n",
-		    cmdname(p.command), p.command);
+		    cmdname(cmd), cmd);
 		rv = 0;
 		goto fail;
 	}
 
-	if (p.length > CHALLENGE_LEN*2) {
+	if (length > CHALLENGE_LEN * 2) {
 		dev_err(DEV, "expected AuthChallenge payload too big.\n");
 		rv = -1;
 		goto fail;
 	}
 
-	peers_ch = kmalloc(p.length, GFP_NOIO);
+	peers_ch = kmalloc(length, GFP_NOIO);
 	if (peers_ch == NULL) {
 		dev_err(DEV, "kmalloc of peers_ch failed\n");
 		rv = -1;
 		goto fail;
 	}
 
-	rv = drbd_recv(mdev, peers_ch, p.length);
+	rv = drbd_recv(mdev, peers_ch, length);
 
-	if (rv != p.length) {
+	if (rv != length) {
 		dev_err(DEV, "short read AuthChallenge: l=%u\n", rv);
 		rv = 0;
 		goto fail;
@@ -4046,7 +4164,7 @@
 	}
 
 	sg_init_table(&sg, 1);
-	sg_set_buf(&sg, peers_ch, p.length);
+	sg_set_buf(&sg, peers_ch, length);
 
 	rv = crypto_hash_digest(&desc, &sg, sg.length, response);
 	if (rv) {
@@ -4059,18 +4177,18 @@
 	if (!rv)
 		goto fail;
 
-	rv = drbd_recv_header(mdev, &p);
+	rv = drbd_recv_header(mdev, &cmd, &length);
 	if (!rv)
 		goto fail;
 
-	if (p.command != P_AUTH_RESPONSE) {
+	if (cmd != P_AUTH_RESPONSE) {
 		dev_err(DEV, "expected AuthResponse packet, received: %s (0x%04x)\n",
-		    cmdname(p.command), p.command);
+			cmdname(cmd), cmd);
 		rv = 0;
 		goto fail;
 	}
 
-	if (p.length != resp_size) {
+	if (length != resp_size) {
 		dev_err(DEV, "expected AuthResponse payload of wrong size\n");
 		rv = 0;
 		goto fail;
@@ -4155,7 +4273,7 @@
 
 /* ********* acknowledge sender ******** */
 
-static int got_RqSReply(struct drbd_conf *mdev, struct p_header *h)
+static int got_RqSReply(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_req_state_reply *p = (struct p_req_state_reply *)h;
 
@@ -4173,13 +4291,13 @@
 	return TRUE;
 }
 
-static int got_Ping(struct drbd_conf *mdev, struct p_header *h)
+static int got_Ping(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	return drbd_send_ping_ack(mdev);
 
 }
 
-static int got_PingAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_PingAck(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	/* restore idle timeout */
 	mdev->meta.socket->sk->sk_rcvtimeo = mdev->net_conf->ping_int*HZ;
@@ -4189,7 +4307,7 @@
 	return TRUE;
 }
 
-static int got_IsInSync(struct drbd_conf *mdev, struct p_header *h)
+static int got_IsInSync(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_block_ack *p = (struct p_block_ack *)h;
 	sector_t sector = be64_to_cpu(p->sector);
@@ -4199,11 +4317,15 @@
 
 	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
 
-	drbd_rs_complete_io(mdev, sector);
-	drbd_set_in_sync(mdev, sector, blksize);
-	/* rs_same_csums is supposed to count in units of BM_BLOCK_SIZE */
-	mdev->rs_same_csum += (blksize >> BM_BLOCK_SHIFT);
+	if (get_ldev(mdev)) {
+		drbd_rs_complete_io(mdev, sector);
+		drbd_set_in_sync(mdev, sector, blksize);
+		/* rs_same_csums is supposed to count in units of BM_BLOCK_SIZE */
+		mdev->rs_same_csum += (blksize >> BM_BLOCK_SHIFT);
+		put_ldev(mdev);
+	}
 	dec_rs_pending(mdev);
+	atomic_add(blksize >> 9, &mdev->rs_sect_in);
 
 	return TRUE;
 }
@@ -4259,7 +4381,7 @@
 	return TRUE;
 }
 
-static int got_BlockAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_block_ack *p = (struct p_block_ack *)h;
 	sector_t sector = be64_to_cpu(p->sector);
@@ -4299,7 +4421,7 @@
 		_ack_id_to_req, __func__ , what);
 }
 
-static int got_NegAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_NegAck(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_block_ack *p = (struct p_block_ack *)h;
 	sector_t sector = be64_to_cpu(p->sector);
@@ -4319,7 +4441,7 @@
 		_ack_id_to_req, __func__ , neg_acked);
 }
 
-static int got_NegDReply(struct drbd_conf *mdev, struct p_header *h)
+static int got_NegDReply(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_block_ack *p = (struct p_block_ack *)h;
 	sector_t sector = be64_to_cpu(p->sector);
@@ -4332,7 +4454,7 @@
 		_ar_id_to_req, __func__ , neg_acked);
 }
 
-static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header *h)
+static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	sector_t sector;
 	int size;
@@ -4354,7 +4476,7 @@
 	return TRUE;
 }
 
-static int got_BarrierAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_barrier_ack *p = (struct p_barrier_ack *)h;
 
@@ -4363,7 +4485,7 @@
 	return TRUE;
 }
 
-static int got_OVResult(struct drbd_conf *mdev, struct p_header *h)
+static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_block_ack *p = (struct p_block_ack *)h;
 	struct drbd_work *w;
@@ -4380,6 +4502,9 @@
 	else
 		ov_oos_print(mdev);
 
+	if (!get_ldev(mdev))
+		return TRUE;
+
 	drbd_rs_complete_io(mdev, sector);
 	dec_rs_pending(mdev);
 
@@ -4394,18 +4519,18 @@
 			drbd_resync_finished(mdev);
 		}
 	}
+	put_ldev(mdev);
 	return TRUE;
 }
 
-static int got_something_to_ignore_m(struct drbd_conf *mdev, struct p_header *h)
+static int got_skip(struct drbd_conf *mdev, struct p_header80 *h)
 {
-	/* IGNORE */
 	return TRUE;
 }
 
 struct asender_cmd {
 	size_t pkt_size;
-	int (*process)(struct drbd_conf *mdev, struct p_header *h);
+	int (*process)(struct drbd_conf *mdev, struct p_header80 *h);
 };
 
 static struct asender_cmd *get_asender_cmd(int cmd)
@@ -4414,8 +4539,8 @@
 		/* anything missing from this table is in
 		 * the drbd_cmd_handler (drbd_default_handler) table,
 		 * see the beginning of drbdd() */
-	[P_PING]	    = { sizeof(struct p_header), got_Ping },
-	[P_PING_ACK]	    = { sizeof(struct p_header), got_PingAck },
+	[P_PING]	    = { sizeof(struct p_header80), got_Ping },
+	[P_PING_ACK]	    = { sizeof(struct p_header80), got_PingAck },
 	[P_RECV_ACK]	    = { sizeof(struct p_block_ack), got_BlockAck },
 	[P_WRITE_ACK]	    = { sizeof(struct p_block_ack), got_BlockAck },
 	[P_RS_WRITE_ACK]    = { sizeof(struct p_block_ack), got_BlockAck },
@@ -4427,7 +4552,7 @@
 	[P_BARRIER_ACK]	    = { sizeof(struct p_barrier_ack), got_BarrierAck },
 	[P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply },
 	[P_RS_IS_IN_SYNC]   = { sizeof(struct p_block_ack), got_IsInSync },
-	[P_DELAY_PROBE]     = { sizeof(struct p_delay_probe), got_something_to_ignore_m },
+	[P_DELAY_PROBE]     = { sizeof(struct p_delay_probe93), got_skip },
 	[P_MAX_CMD]	    = { 0, NULL },
 	};
 	if (cmd > P_MAX_CMD || asender_tbl[cmd].process == NULL)
@@ -4438,13 +4563,13 @@
 int drbd_asender(struct drbd_thread *thi)
 {
 	struct drbd_conf *mdev = thi->mdev;
-	struct p_header *h = &mdev->meta.rbuf.header;
+	struct p_header80 *h = &mdev->meta.rbuf.header.h80;
 	struct asender_cmd *cmd = NULL;
 
 	int rv, len;
 	void *buf    = h;
 	int received = 0;
-	int expect   = sizeof(struct p_header);
+	int expect   = sizeof(struct p_header80);
 	int empty;
 
 	sprintf(current->comm, "drbd%d_asender", mdev_to_minor(mdev));
@@ -4468,10 +4593,8 @@
 		while (1) {
 			clear_bit(SIGNAL_ASENDER, &mdev->flags);
 			flush_signals(current);
-			if (!drbd_process_done_ee(mdev)) {
-				dev_err(DEV, "process_done_ee() = NOT_OK\n");
+			if (!drbd_process_done_ee(mdev))
 				goto reconnect;
-			}
 			/* to avoid race with newly queued ACKs */
 			set_bit(SIGNAL_ASENDER, &mdev->flags);
 			spin_lock_irq(&mdev->req_lock);
@@ -4530,21 +4653,23 @@
 
 		if (received == expect && cmd == NULL) {
 			if (unlikely(h->magic != BE_DRBD_MAGIC)) {
-				dev_err(DEV, "magic?? on meta m: 0x%lx c: %d l: %d\n",
-				    (long)be32_to_cpu(h->magic),
-				    h->command, h->length);
+				dev_err(DEV, "magic?? on meta m: 0x%08x c: %d l: %d\n",
+				    be32_to_cpu(h->magic),
+				    be16_to_cpu(h->command),
+				    be16_to_cpu(h->length));
 				goto reconnect;
 			}
 			cmd = get_asender_cmd(be16_to_cpu(h->command));
 			len = be16_to_cpu(h->length);
 			if (unlikely(cmd == NULL)) {
-				dev_err(DEV, "unknown command?? on meta m: 0x%lx c: %d l: %d\n",
-				    (long)be32_to_cpu(h->magic),
-				    h->command, h->length);
+				dev_err(DEV, "unknown command?? on meta m: 0x%08x c: %d l: %d\n",
+				    be32_to_cpu(h->magic),
+				    be16_to_cpu(h->command),
+				    be16_to_cpu(h->length));
 				goto disconnect;
 			}
 			expect = cmd->pkt_size;
-			ERR_IF(len != expect-sizeof(struct p_header))
+			ERR_IF(len != expect-sizeof(struct p_header80))
 				goto reconnect;
 		}
 		if (received == expect) {
@@ -4554,7 +4679,7 @@
 
 			buf	 = h;
 			received = 0;
-			expect	 = sizeof(struct p_header);
+			expect	 = sizeof(struct p_header80);
 			cmd	 = NULL;
 		}
 	}
@@ -4562,10 +4687,12 @@
 	if (0) {
 reconnect:
 		drbd_force_state(mdev, NS(conn, C_NETWORK_FAILURE));
+		drbd_md_sync(mdev);
 	}
 	if (0) {
 disconnect:
 		drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
+		drbd_md_sync(mdev);
 	}
 	clear_bit(SIGNAL_ASENDER, &mdev->flags);
 
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index f761d98..9e91a25 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -59,17 +59,19 @@
 static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const int rw)
 {
 	const unsigned long s = req->rq_state;
+
+	/* remove it from the transfer log.
+	 * well, only if it had been there in the first
+	 * place... if it had not (local only or conflicting
+	 * and never sent), it should still be "empty" as
+	 * initialized in drbd_req_new(), so we can list_del() it
+	 * here unconditionally */
+	list_del(&req->tl_requests);
+
 	/* if it was a write, we may have to set the corresponding
 	 * bit(s) out-of-sync first. If it had a local part, we need to
 	 * release the reference to the activity log. */
 	if (rw == WRITE) {
-		/* remove it from the transfer log.
-		 * well, only if it had been there in the first
-		 * place... if it had not (local only or conflicting
-		 * and never sent), it should still be "empty" as
-		 * initialized in drbd_req_new(), so we can list_del() it
-		 * here unconditionally */
-		list_del(&req->tl_requests);
 		/* Set out-of-sync unless both OK flags are set
 		 * (local only or remote failed).
 		 * Other places where we set out-of-sync:
@@ -92,7 +94,8 @@
 		 */
 		if (s & RQ_LOCAL_MASK) {
 			if (get_ldev_if_state(mdev, D_FAILED)) {
-				drbd_al_complete_io(mdev, req->sector);
+				if (s & RQ_IN_ACT_LOG)
+					drbd_al_complete_io(mdev, req->sector);
 				put_ldev(mdev);
 			} else if (__ratelimit(&drbd_ratelimit_state)) {
 				dev_warn(DEV, "Should have called drbd_al_complete_io(, %llu), "
@@ -280,6 +283,14 @@
 	 * protocol A or B, barrier ack still pending... */
 }
 
+static void _req_may_be_done_not_susp(struct drbd_request *req, struct bio_and_error *m)
+{
+	struct drbd_conf *mdev = req->mdev;
+
+	if (!is_susp(mdev->state))
+		_req_may_be_done(req, m);
+}
+
 /*
  * checks whether there was an overlapping request
  * or ee already registered.
@@ -380,10 +391,11 @@
  *  and it enforces that we have to think in a very structured manner
  *  about the "events" that may happen to a request during its life time ...
  */
-void __req_mod(struct drbd_request *req, enum drbd_req_event what,
+int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		struct bio_and_error *m)
 {
 	struct drbd_conf *mdev = req->mdev;
+	int rv = 0;
 	m->bio = NULL;
 
 	switch (what) {
@@ -420,7 +432,7 @@
 		req->rq_state |= (RQ_LOCAL_COMPLETED|RQ_LOCAL_OK);
 		req->rq_state &= ~RQ_LOCAL_PENDING;
 
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		put_ldev(mdev);
 		break;
 
@@ -429,7 +441,7 @@
 		req->rq_state &= ~RQ_LOCAL_PENDING;
 
 		__drbd_chk_io_error(mdev, FALSE);
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		put_ldev(mdev);
 		break;
 
@@ -437,7 +449,7 @@
 		/* it is legal to fail READA */
 		req->rq_state |= RQ_LOCAL_COMPLETED;
 		req->rq_state &= ~RQ_LOCAL_PENDING;
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		put_ldev(mdev);
 		break;
 
@@ -455,7 +467,7 @@
 		/* no point in retrying if there is no good remote data,
 		 * or we have no connection. */
 		if (mdev->state.pdsk != D_UP_TO_DATE) {
-			_req_may_be_done(req, m);
+			_req_may_be_done_not_susp(req, m);
 			break;
 		}
 
@@ -517,11 +529,9 @@
 		D_ASSERT(test_bit(CREATE_BARRIER, &mdev->flags) == 0);
 
 		req->epoch = mdev->newest_tle->br_number;
-		list_add_tail(&req->tl_requests,
-				&mdev->newest_tle->requests);
 
 		/* increment size of current epoch */
-		mdev->newest_tle->n_req++;
+		mdev->newest_tle->n_writes++;
 
 		/* queue work item to send data */
 		D_ASSERT(req->rq_state & RQ_NET_PENDING);
@@ -530,7 +540,7 @@
 		drbd_queue_work(&mdev->data.work, &req->w);
 
 		/* close the epoch, in case it outgrew the limit */
-		if (mdev->newest_tle->n_req >= mdev->net_conf->max_epoch_size)
+		if (mdev->newest_tle->n_writes >= mdev->net_conf->max_epoch_size)
 			queue_barrier(mdev);
 
 		break;
@@ -543,7 +553,7 @@
 		req->rq_state &= ~RQ_NET_QUEUED;
 		/* if we did it right, tl_clear should be scheduled only after
 		 * this, so this should not be necessary! */
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		break;
 
 	case handed_over_to_network:
@@ -568,7 +578,7 @@
 		 * "completed_ok" events came in, once we return from
 		 * _drbd_send_zc_bio (drbd_send_dblock), we have to check
 		 * whether it is done already, and end it.  */
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		break;
 
 	case read_retry_remote_canceled:
@@ -584,7 +594,7 @@
 		/* if it is still queued, we may not complete it here.
 		 * it will be canceled soon. */
 		if (!(req->rq_state & RQ_NET_QUEUED))
-			_req_may_be_done(req, m);
+			_req_may_be_done(req, m); /* Allowed while state.susp */
 		break;
 
 	case write_acked_by_peer_and_sis:
@@ -619,7 +629,7 @@
 		D_ASSERT(req->rq_state & RQ_NET_PENDING);
 		dec_ap_pending(mdev);
 		req->rq_state &= ~RQ_NET_PENDING;
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		break;
 
 	case neg_acked:
@@ -629,11 +639,50 @@
 		req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING);
 
 		req->rq_state |= RQ_NET_DONE;
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		/* else: done by handed_over_to_network */
 		break;
 
+	case fail_frozen_disk_io:
+		if (!(req->rq_state & RQ_LOCAL_COMPLETED))
+			break;
+
+		_req_may_be_done(req, m); /* Allowed while state.susp */
+		break;
+
+	case restart_frozen_disk_io:
+		if (!(req->rq_state & RQ_LOCAL_COMPLETED))
+			break;
+
+		req->rq_state &= ~RQ_LOCAL_COMPLETED;
+
+		rv = MR_READ;
+		if (bio_data_dir(req->master_bio) == WRITE)
+			rv = MR_WRITE;
+
+		get_ldev(mdev);
+		req->w.cb = w_restart_disk_io;
+		drbd_queue_work(&mdev->data.work, &req->w);
+		break;
+
+	case resend:
+		/* If RQ_NET_OK is already set, we got a P_WRITE_ACK or P_RECV_ACK
+		   before the connection loss (B&C only); only P_BARRIER_ACK was missing.
+		   Trowing them out of the TL here by pretending we got a BARRIER_ACK
+		   We ensure that the peer was not rebooted */
+		if (!(req->rq_state & RQ_NET_OK)) {
+			if (req->w.cb) {
+				drbd_queue_work(&mdev->data.work, &req->w);
+				rv = req->rq_state & RQ_WRITE ? MR_WRITE : MR_READ;
+			}
+			break;
+		}
+		/* else, fall through to barrier_acked */
+
 	case barrier_acked:
+		if (!(req->rq_state & RQ_WRITE))
+			break;
+
 		if (req->rq_state & RQ_NET_PENDING) {
 			/* barrier came in before all requests have been acked.
 			 * this is bad, because if the connection is lost now,
@@ -643,7 +692,7 @@
 		}
 		D_ASSERT(req->rq_state & RQ_NET_SENT);
 		req->rq_state |= RQ_NET_DONE;
-		_req_may_be_done(req, m);
+		_req_may_be_done(req, m); /* Allowed while state.susp */
 		break;
 
 	case data_received:
@@ -651,9 +700,11 @@
 		dec_ap_pending(mdev);
 		req->rq_state &= ~RQ_NET_PENDING;
 		req->rq_state |= (RQ_NET_OK|RQ_NET_DONE);
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		break;
 	};
+
+	return rv;
 }
 
 /* we may do a local read if:
@@ -752,14 +803,16 @@
 	 * resync extent to finish, and, if necessary, pulls in the target
 	 * extent into the activity log, which involves further disk io because
 	 * of transactional on-disk meta data updates. */
-	if (rw == WRITE && local)
+	if (rw == WRITE && local && !test_bit(AL_SUSPENDED, &mdev->flags)) {
+		req->rq_state |= RQ_IN_ACT_LOG;
 		drbd_al_begin_io(mdev, sector);
+	}
 
 	remote = remote && (mdev->state.pdsk == D_UP_TO_DATE ||
 			    (mdev->state.pdsk == D_INCONSISTENT &&
 			     mdev->state.conn >= C_CONNECTED));
 
-	if (!(local || remote) && !mdev->state.susp) {
+	if (!(local || remote) && !is_susp(mdev->state)) {
 		dev_err(DEV, "IO ERROR: neither local nor remote disk\n");
 		goto fail_free_complete;
 	}
@@ -785,7 +838,7 @@
 	/* GOOD, everything prepared, grab the spin_lock */
 	spin_lock_irq(&mdev->req_lock);
 
-	if (mdev->state.susp) {
+	if (is_susp(mdev->state)) {
 		/* If we got suspended, use the retry mechanism of
 		   generic_make_request() to restart processing of this
 		   bio. In the next call to drbd_make_request_26
@@ -867,30 +920,10 @@
 	/* check this request on the collision detection hash tables.
 	 * if we have a conflict, just complete it here.
 	 * THINK do we want to check reads, too? (I don't think so...) */
-	if (rw == WRITE && _req_conflicts(req)) {
-		/* this is a conflicting request.
-		 * even though it may have been only _partially_
-		 * overlapping with one of the currently pending requests,
-		 * without even submitting or sending it, we will
-		 * pretend that it was successfully served right now.
-		 */
-		if (local) {
-			bio_put(req->private_bio);
-			req->private_bio = NULL;
-			drbd_al_complete_io(mdev, req->sector);
-			put_ldev(mdev);
-			local = 0;
-		}
-		if (remote)
-			dec_ap_pending(mdev);
-		_drbd_end_io_acct(mdev, req);
-		/* THINK: do we want to fail it (-EIO), or pretend success? */
-		bio_endio(req->master_bio, 0);
-		req->master_bio = NULL;
-		dec_ap_bio(mdev);
-		drbd_req_free(req);
-		remote = 0;
-	}
+	if (rw == WRITE && _req_conflicts(req))
+		goto fail_conflicting;
+
+	list_add_tail(&req->tl_requests, &mdev->newest_tle->requests);
 
 	/* NOTE remote first: to get the concurrent write detection right,
 	 * we must register the request before start of local IO.  */
@@ -923,6 +956,21 @@
 
 	return 0;
 
+fail_conflicting:
+	/* this is a conflicting request.
+	 * even though it may have been only _partially_
+	 * overlapping with one of the currently pending requests,
+	 * without even submitting or sending it, we will
+	 * pretend that it was successfully served right now.
+	 */
+	_drbd_end_io_acct(mdev, req);
+	spin_unlock_irq(&mdev->req_lock);
+	if (remote)
+		dec_ap_pending(mdev);
+	/* THINK: do we want to fail it (-EIO), or pretend success?
+	 * this pretends success. */
+	err = 0;
+
 fail_free_complete:
 	if (rw == WRITE && local)
 		drbd_al_complete_io(mdev, sector);
@@ -961,21 +1009,6 @@
 		return 1;
 	}
 
-	/*
-	 * Paranoia: we might have been primary, but sync target, or
-	 * even diskless, then lost the connection.
-	 * This should have been handled (panic? suspend?) somewhere
-	 * else. But maybe it was not, so check again here.
-	 * Caution: as long as we do not have a read/write lock on mdev,
-	 * to serialize state changes, this is racy, since we may lose
-	 * the connection *after* we test for the cstate.
-	 */
-	if (mdev->state.disk < D_UP_TO_DATE && mdev->state.pdsk < D_UP_TO_DATE) {
-		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "Sorry, I have no access to good data anymore.\n");
-		return 1;
-	}
-
 	return 0;
 }
 
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index 02d575d..181ea03 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -104,6 +104,9 @@
 	read_ahead_completed_with_error,
 	write_completed_with_error,
 	completed_ok,
+	resend,
+	fail_frozen_disk_io,
+	restart_frozen_disk_io,
 	nothing, /* for tracing only */
 };
 
@@ -183,6 +186,12 @@
 
 	/* keep this last, its for the RQ_NET_MASK */
 	__RQ_NET_MAX,
+
+	/* Set when this is a write, clear for a read */
+	__RQ_WRITE,
+
+	/* Should call drbd_al_complete_io() for this request... */
+	__RQ_IN_ACT_LOG,
 };
 
 #define RQ_LOCAL_PENDING   (1UL << __RQ_LOCAL_PENDING)
@@ -201,6 +210,16 @@
 /* 0x1f8 */
 #define RQ_NET_MASK        (((1UL << __RQ_NET_MAX)-1) & ~RQ_LOCAL_MASK)
 
+#define RQ_WRITE           (1UL << __RQ_WRITE)
+#define RQ_IN_ACT_LOG      (1UL << __RQ_IN_ACT_LOG)
+
+/* For waking up the frozen transfer log mod_req() has to return if the request
+   should be counted in the epoch object*/
+#define MR_WRITE_SHIFT 0
+#define MR_WRITE       (1 << MR_WRITE_SHIFT)
+#define MR_READ_SHIFT  1
+#define MR_READ        (1 << MR_READ_SHIFT)
+
 /* epoch entries */
 static inline
 struct hlist_head *ee_hash_slot(struct drbd_conf *mdev, sector_t sector)
@@ -244,30 +263,36 @@
 	return NULL;
 }
 
+static inline void drbd_req_make_private_bio(struct drbd_request *req, struct bio *bio_src)
+{
+	struct bio *bio;
+	bio = bio_clone(bio_src, GFP_NOIO); /* XXX cannot fail?? */
+
+	req->private_bio = bio;
+
+	bio->bi_private  = req;
+	bio->bi_end_io   = drbd_endio_pri;
+	bio->bi_next     = NULL;
+}
+
 static inline struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
 	struct bio *bio_src)
 {
-	struct bio *bio;
 	struct drbd_request *req =
 		mempool_alloc(drbd_request_mempool, GFP_NOIO);
 	if (likely(req)) {
-		bio = bio_clone(bio_src, GFP_NOIO); /* XXX cannot fail?? */
+		drbd_req_make_private_bio(req, bio_src);
 
-		req->rq_state    = 0;
+		req->rq_state    = bio_data_dir(bio_src) == WRITE ? RQ_WRITE : 0;
 		req->mdev        = mdev;
 		req->master_bio  = bio_src;
-		req->private_bio = bio;
 		req->epoch       = 0;
-		req->sector      = bio->bi_sector;
-		req->size        = bio->bi_size;
+		req->sector      = bio_src->bi_sector;
+		req->size        = bio_src->bi_size;
 		req->start_time  = jiffies;
 		INIT_HLIST_NODE(&req->colision);
 		INIT_LIST_HEAD(&req->tl_requests);
 		INIT_LIST_HEAD(&req->w.list);
-
-		bio->bi_private  = req;
-		bio->bi_end_io   = drbd_endio_pri;
-		bio->bi_next     = NULL;
 	}
 	return req;
 }
@@ -292,36 +317,43 @@
 
 extern void _req_may_be_done(struct drbd_request *req,
 		struct bio_and_error *m);
-extern void __req_mod(struct drbd_request *req, enum drbd_req_event what,
+extern int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		struct bio_and_error *m);
 extern void complete_master_bio(struct drbd_conf *mdev,
 		struct bio_and_error *m);
 
 /* use this if you don't want to deal with calling complete_master_bio()
  * outside the spinlock, e.g. when walking some list on cleanup. */
-static inline void _req_mod(struct drbd_request *req, enum drbd_req_event what)
+static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)
 {
 	struct drbd_conf *mdev = req->mdev;
 	struct bio_and_error m;
+	int rv;
 
 	/* __req_mod possibly frees req, do not touch req after that! */
-	__req_mod(req, what, &m);
+	rv = __req_mod(req, what, &m);
 	if (m.bio)
 		complete_master_bio(mdev, &m);
+
+	return rv;
 }
 
 /* completion of master bio is outside of spinlock.
  * If you need it irqsave, do it your self! */
-static inline void req_mod(struct drbd_request *req,
+static inline int req_mod(struct drbd_request *req,
 		enum drbd_req_event what)
 {
 	struct drbd_conf *mdev = req->mdev;
 	struct bio_and_error m;
+	int rv;
+
 	spin_lock_irq(&mdev->req_lock);
-	__req_mod(req, what, &m);
+	rv = __req_mod(req, what, &m);
 	spin_unlock_irq(&mdev->req_lock);
 
 	if (m.bio)
 		complete_master_bio(mdev, &m);
+
+	return rv;
 }
 #endif
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index ca4a16c..108d580 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -39,8 +39,6 @@
 #include "drbd_int.h"
 #include "drbd_req.h"
 
-#define SLEEP_TIME (HZ/10)
-
 static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int cancel);
 
 
@@ -217,10 +215,8 @@
  */
 void drbd_endio_pri(struct bio *bio, int error)
 {
-	unsigned long flags;
 	struct drbd_request *req = bio->bi_private;
 	struct drbd_conf *mdev = req->mdev;
-	struct bio_and_error m;
 	enum drbd_req_event what;
 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
 
@@ -246,12 +242,7 @@
 	bio_put(req->private_bio);
 	req->private_bio = ERR_PTR(error);
 
-	spin_lock_irqsave(&mdev->req_lock, flags);
-	__req_mod(req, what, &m);
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
-
-	if (m.bio)
-		complete_master_bio(mdev, &m);
+	req_mod(req, what);
 }
 
 int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
@@ -376,54 +367,145 @@
 	struct drbd_epoch_entry *e;
 
 	if (!get_ldev(mdev))
-		return 0;
+		return -EIO;
+
+	if (drbd_rs_should_slow_down(mdev))
+		goto defer;
 
 	/* GFP_TRY, because if there is no memory available right now, this may
 	 * be rescheduled for later. It is "only" background resync, after all. */
 	e = drbd_alloc_ee(mdev, DRBD_MAGIC+0xbeef, sector, size, GFP_TRY);
 	if (!e)
-		goto fail;
+		goto defer;
 
+	e->w.cb = w_e_send_csum;
 	spin_lock_irq(&mdev->req_lock);
 	list_add(&e->w.list, &mdev->read_ee);
 	spin_unlock_irq(&mdev->req_lock);
 
-	e->w.cb = w_e_send_csum;
+	atomic_add(size >> 9, &mdev->rs_sect_ev);
 	if (drbd_submit_ee(mdev, e, READ, DRBD_FAULT_RS_RD) == 0)
-		return 1;
+		return 0;
+
+	/* drbd_submit_ee currently fails for one reason only:
+	 * not being able to allocate enough bios.
+	 * Is dropping the connection going to help? */
+	spin_lock_irq(&mdev->req_lock);
+	list_del(&e->w.list);
+	spin_unlock_irq(&mdev->req_lock);
 
 	drbd_free_ee(mdev, e);
-fail:
+defer:
 	put_ldev(mdev);
-	return 2;
+	return -EAGAIN;
 }
 
 void resync_timer_fn(unsigned long data)
 {
-	unsigned long flags;
 	struct drbd_conf *mdev = (struct drbd_conf *) data;
 	int queue;
 
-	spin_lock_irqsave(&mdev->req_lock, flags);
-
-	if (likely(!test_and_clear_bit(STOP_SYNC_TIMER, &mdev->flags))) {
-		queue = 1;
-		if (mdev->state.conn == C_VERIFY_S)
-			mdev->resync_work.cb = w_make_ov_request;
-		else
-			mdev->resync_work.cb = w_make_resync_request;
-	} else {
+	queue = 1;
+	switch (mdev->state.conn) {
+	case C_VERIFY_S:
+		mdev->resync_work.cb = w_make_ov_request;
+		break;
+	case C_SYNC_TARGET:
+		mdev->resync_work.cb = w_make_resync_request;
+		break;
+	default:
 		queue = 0;
 		mdev->resync_work.cb = w_resync_inactive;
 	}
 
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
-
 	/* harmless race: list_empty outside data.work.q_lock */
 	if (list_empty(&mdev->resync_work.list) && queue)
 		drbd_queue_work(&mdev->data.work, &mdev->resync_work);
 }
 
+static void fifo_set(struct fifo_buffer *fb, int value)
+{
+	int i;
+
+	for (i = 0; i < fb->size; i++)
+		fb->values[i] = value;
+}
+
+static int fifo_push(struct fifo_buffer *fb, int value)
+{
+	int ov;
+
+	ov = fb->values[fb->head_index];
+	fb->values[fb->head_index++] = value;
+
+	if (fb->head_index >= fb->size)
+		fb->head_index = 0;
+
+	return ov;
+}
+
+static void fifo_add_val(struct fifo_buffer *fb, int value)
+{
+	int i;
+
+	for (i = 0; i < fb->size; i++)
+		fb->values[i] += value;
+}
+
+int drbd_rs_controller(struct drbd_conf *mdev)
+{
+	unsigned int sect_in;  /* Number of sectors that came in since the last turn */
+	unsigned int want;     /* The number of sectors we want in the proxy */
+	int req_sect; /* Number of sectors to request in this turn */
+	int correction; /* Number of sectors more we need in the proxy*/
+	int cps; /* correction per invocation of drbd_rs_controller() */
+	int steps; /* Number of time steps to plan ahead */
+	int curr_corr;
+	int max_sect;
+
+	sect_in = atomic_xchg(&mdev->rs_sect_in, 0); /* Number of sectors that came in */
+	mdev->rs_in_flight -= sect_in;
+
+	spin_lock(&mdev->peer_seq_lock); /* get an atomic view on mdev->rs_plan_s */
+
+	steps = mdev->rs_plan_s.size; /* (mdev->sync_conf.c_plan_ahead * 10 * SLEEP_TIME) / HZ; */
+
+	if (mdev->rs_in_flight + sect_in == 0) { /* At start of resync */
+		want = ((mdev->sync_conf.rate * 2 * SLEEP_TIME) / HZ) * steps;
+	} else { /* normal path */
+		want = mdev->sync_conf.c_fill_target ? mdev->sync_conf.c_fill_target :
+			sect_in * mdev->sync_conf.c_delay_target * HZ / (SLEEP_TIME * 10);
+	}
+
+	correction = want - mdev->rs_in_flight - mdev->rs_planed;
+
+	/* Plan ahead */
+	cps = correction / steps;
+	fifo_add_val(&mdev->rs_plan_s, cps);
+	mdev->rs_planed += cps * steps;
+
+	/* What we do in this step */
+	curr_corr = fifo_push(&mdev->rs_plan_s, 0);
+	spin_unlock(&mdev->peer_seq_lock);
+	mdev->rs_planed -= curr_corr;
+
+	req_sect = sect_in + curr_corr;
+	if (req_sect < 0)
+		req_sect = 0;
+
+	max_sect = (mdev->sync_conf.c_max_rate * 2 * SLEEP_TIME) / HZ;
+	if (req_sect > max_sect)
+		req_sect = max_sect;
+
+	/*
+	dev_warn(DEV, "si=%u if=%d wa=%u co=%d st=%d cps=%d pl=%d cc=%d rs=%d\n",
+		 sect_in, mdev->rs_in_flight, want, correction,
+		 steps, cps, mdev->rs_planed, curr_corr, req_sect);
+	*/
+
+	return req_sect;
+}
+
 int w_make_resync_request(struct drbd_conf *mdev,
 		struct drbd_work *w, int cancel)
 {
@@ -431,8 +513,9 @@
 	sector_t sector;
 	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
 	int max_segment_size;
-	int number, i, size, pe, mx;
+	int number, rollback_i, size, pe, mx;
 	int align, queued, sndbuf;
+	int i = 0;
 
 	if (unlikely(cancel))
 		return 1;
@@ -446,6 +529,12 @@
 		dev_err(DEV, "%s in w_make_resync_request\n",
 			drbd_conn_str(mdev->state.conn));
 
+	if (mdev->rs_total == 0) {
+		/* empty resync? */
+		drbd_resync_finished(mdev);
+		return 1;
+	}
+
 	if (!get_ldev(mdev)) {
 		/* Since we only need to access mdev->rsync a
 		   get_ldev_if_state(mdev,D_FAILED) would be sufficient, but
@@ -458,11 +547,25 @@
 
 	/* starting with drbd 8.3.8, we can handle multi-bio EEs,
 	 * if it should be necessary */
-	max_segment_size = mdev->agreed_pro_version < 94 ?
-		queue_max_segment_size(mdev->rq_queue) : DRBD_MAX_SEGMENT_SIZE;
+	max_segment_size =
+		mdev->agreed_pro_version < 94 ? queue_max_segment_size(mdev->rq_queue) :
+		mdev->agreed_pro_version < 95 ?	DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_SEGMENT_SIZE;
 
-	number = SLEEP_TIME * mdev->sync_conf.rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
-	pe = atomic_read(&mdev->rs_pending_cnt);
+	if (mdev->rs_plan_s.size) { /* mdev->sync_conf.c_plan_ahead */
+		number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9);
+		mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
+	} else {
+		mdev->c_sync_rate = mdev->sync_conf.rate;
+		number = SLEEP_TIME * mdev->c_sync_rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
+	}
+
+	/* Throttle resync on lower level disk activity, which may also be
+	 * caused by application IO on Primary/SyncTarget.
+	 * Keep this after the call to drbd_rs_controller, as that assumes
+	 * to be called as precisely as possible every SLEEP_TIME,
+	 * and would be confused otherwise. */
+	if (drbd_rs_should_slow_down(mdev))
+		goto requeue;
 
 	mutex_lock(&mdev->data.mutex);
 	if (mdev->data.socket)
@@ -476,6 +579,7 @@
 		mx = number;
 
 	/* Limit the number of pending RS requests to no more than the peer's receive buffer */
+	pe = atomic_read(&mdev->rs_pending_cnt);
 	if ((pe + number) > mx) {
 		number = mx - pe;
 	}
@@ -526,6 +630,7 @@
 		 * be prepared for all stripe sizes of software RAIDs.
 		 */
 		align = 1;
+		rollback_i = i;
 		for (;;) {
 			if (size + BM_BLOCK_SIZE > max_segment_size)
 				break;
@@ -561,14 +666,19 @@
 			size = (capacity-sector)<<9;
 		if (mdev->agreed_pro_version >= 89 && mdev->csums_tfm) {
 			switch (read_for_csum(mdev, sector, size)) {
-			case 0: /* Disk failure*/
+			case -EIO: /* Disk failure */
 				put_ldev(mdev);
 				return 0;
-			case 2: /* Allocation failed */
+			case -EAGAIN: /* allocation failed, or ldev busy */
 				drbd_rs_complete_io(mdev, sector);
 				mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
+				i = rollback_i;
 				goto requeue;
-			/* case 1: everything ok */
+			case 0:
+				/* everything ok */
+				break;
+			default:
+				BUG();
 			}
 		} else {
 			inc_rs_pending(mdev);
@@ -595,6 +705,7 @@
 	}
 
  requeue:
+	mdev->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
 	mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME);
 	put_ldev(mdev);
 	return 1;
@@ -670,6 +781,14 @@
 	return 1;
 }
 
+static void ping_peer(struct drbd_conf *mdev)
+{
+	clear_bit(GOT_PING_ACK, &mdev->flags);
+	request_ping(mdev);
+	wait_event(mdev->misc_wait,
+		   test_bit(GOT_PING_ACK, &mdev->flags) || mdev->state.conn < C_CONNECTED);
+}
+
 int drbd_resync_finished(struct drbd_conf *mdev)
 {
 	unsigned long db, dt, dbdt;
@@ -709,6 +828,8 @@
 	if (!get_ldev(mdev))
 		goto out;
 
+	ping_peer(mdev);
+
 	spin_lock_irq(&mdev->req_lock);
 	os = mdev->state;
 
@@ -801,6 +922,8 @@
 	mdev->rs_paused = 0;
 	mdev->ov_start_sector = 0;
 
+	drbd_md_sync(mdev);
+
 	if (test_and_clear_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags)) {
 		dev_warn(DEV, "Writing the whole bitmap, due to failed kmalloc\n");
 		drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished");
@@ -817,9 +940,13 @@
 {
 	if (drbd_ee_has_active_page(e)) {
 		/* This might happen if sendpage() has not finished */
+		int i = (e->size + PAGE_SIZE -1) >> PAGE_SHIFT;
+		atomic_add(i, &mdev->pp_in_use_by_net);
+		atomic_sub(i, &mdev->pp_in_use);
 		spin_lock_irq(&mdev->req_lock);
 		list_add_tail(&e->w.list, &mdev->net_ee);
 		spin_unlock_irq(&mdev->req_lock);
+		wake_up(&drbd_pp_wait);
 	} else
 		drbd_free_ee(mdev, e);
 }
@@ -926,9 +1053,12 @@
 		return 1;
 	}
 
-	drbd_rs_complete_io(mdev, e->sector);
+	if (get_ldev(mdev)) {
+		drbd_rs_complete_io(mdev, e->sector);
+		put_ldev(mdev);
+	}
 
-	di = (struct digest_info *)(unsigned long)e->block_id;
+	di = e->digest;
 
 	if (likely((e->flags & EE_WAS_ERROR) == 0)) {
 		/* quick hack to try to avoid a race against reconfiguration.
@@ -952,7 +1082,9 @@
 			ok = drbd_send_ack(mdev, P_RS_IS_IN_SYNC, e);
 		} else {
 			inc_rs_pending(mdev);
-			e->block_id = ID_SYNCER;
+			e->block_id = ID_SYNCER; /* By setting block_id, digest pointer becomes invalid! */
+			e->flags &= ~EE_HAS_DIGEST; /* This e no longer has a digest pointer */
+			kfree(di);
 			ok = drbd_send_block(mdev, P_RS_DATA_REPLY, e);
 		}
 	} else {
@@ -962,9 +1094,6 @@
 	}
 
 	dec_unacked(mdev);
-
-	kfree(di);
-
 	move_to_net_ee_or_free(mdev, e);
 
 	if (unlikely(!ok))
@@ -1034,9 +1163,12 @@
 
 	/* after "cancel", because after drbd_disconnect/drbd_rs_cancel_all
 	 * the resync lru has been cleaned up already */
-	drbd_rs_complete_io(mdev, e->sector);
+	if (get_ldev(mdev)) {
+		drbd_rs_complete_io(mdev, e->sector);
+		put_ldev(mdev);
+	}
 
-	di = (struct digest_info *)(unsigned long)e->block_id;
+	di = e->digest;
 
 	if (likely((e->flags & EE_WAS_ERROR) == 0)) {
 		digest_size = crypto_hash_digestsize(mdev->verify_tfm);
@@ -1055,9 +1187,6 @@
 	}
 
 	dec_unacked(mdev);
-
-	kfree(di);
-
 	if (!eq)
 		drbd_ov_oos_found(mdev, e->sector, e->size);
 	else
@@ -1108,7 +1237,7 @@
 	 * dec_ap_pending will be done in got_BarrierAck
 	 * or (on connection loss) in w_clear_epoch.  */
 	ok = _drbd_send_cmd(mdev, mdev->data.socket, P_BARRIER,
-				(struct p_header *)p, sizeof(*p), 0);
+				(struct p_header80 *)p, sizeof(*p), 0);
 	drbd_put_data_sock(mdev);
 
 	return ok;
@@ -1173,6 +1302,24 @@
 	return ok;
 }
 
+int w_restart_disk_io(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+{
+	struct drbd_request *req = container_of(w, struct drbd_request, w);
+
+	if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
+		drbd_al_begin_io(mdev, req->sector);
+	/* Calling drbd_al_begin_io() out of the worker might deadlocks
+	   theoretically. Practically it can not deadlock, since this is
+	   only used when unfreezing IOs. All the extents of the requests
+	   that made it into the TL are already active */
+
+	drbd_req_make_private_bio(req, req->master_bio);
+	req->private_bio->bi_bdev = mdev->ldev->backing_bdev;
+	generic_make_request(req->private_bio);
+
+	return 1;
+}
+
 static int _drbd_may_sync_now(struct drbd_conf *mdev)
 {
 	struct drbd_conf *odev = mdev;
@@ -1298,14 +1445,6 @@
 	return retcode;
 }
 
-static void ping_peer(struct drbd_conf *mdev)
-{
-	clear_bit(GOT_PING_ACK, &mdev->flags);
-	request_ping(mdev);
-	wait_event(mdev->misc_wait,
-		   test_bit(GOT_PING_ACK, &mdev->flags) || mdev->state.conn < C_CONNECTED);
-}
-
 /**
  * drbd_start_resync() - Start the resync process
  * @mdev:	DRBD device.
@@ -1379,13 +1518,21 @@
 		r = SS_UNKNOWN_ERROR;
 
 	if (r == SS_SUCCESS) {
-		mdev->rs_total     =
-		mdev->rs_mark_left = drbd_bm_total_weight(mdev);
+		unsigned long tw = drbd_bm_total_weight(mdev);
+		unsigned long now = jiffies;
+		int i;
+
 		mdev->rs_failed    = 0;
 		mdev->rs_paused    = 0;
-		mdev->rs_start     =
-		mdev->rs_mark_time = jiffies;
 		mdev->rs_same_csum = 0;
+		mdev->rs_last_events = 0;
+		mdev->rs_last_sect_ev = 0;
+		mdev->rs_total     = tw;
+		mdev->rs_start     = now;
+		for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+			mdev->rs_mark_left[i] = tw;
+			mdev->rs_mark_time[i] = now;
+		}
 		_drbd_pause_after(mdev);
 	}
 	write_unlock_irq(&global_state_lock);
@@ -1397,12 +1544,31 @@
 		     (unsigned long) mdev->rs_total << (BM_BLOCK_SHIFT-10),
 		     (unsigned long) mdev->rs_total);
 
-		if (mdev->rs_total == 0) {
-			/* Peer still reachable? Beware of failing before-resync-target handlers! */
-			ping_peer(mdev);
+		if (mdev->agreed_pro_version < 95 && mdev->rs_total == 0) {
+			/* This still has a race (about when exactly the peers
+			 * detect connection loss) that can lead to a full sync
+			 * on next handshake. In 8.3.9 we fixed this with explicit
+			 * resync-finished notifications, but the fix
+			 * introduces a protocol change.  Sleeping for some
+			 * time longer than the ping interval + timeout on the
+			 * SyncSource, to give the SyncTarget the chance to
+			 * detect connection loss, then waiting for a ping
+			 * response (implicit in drbd_resync_finished) reduces
+			 * the race considerably, but does not solve it. */
+			if (side == C_SYNC_SOURCE)
+				schedule_timeout_interruptible(
+					mdev->net_conf->ping_int * HZ +
+					mdev->net_conf->ping_timeo*HZ/9);
 			drbd_resync_finished(mdev);
 		}
 
+		atomic_set(&mdev->rs_sect_in, 0);
+		atomic_set(&mdev->rs_sect_ev, 0);
+		mdev->rs_in_flight = 0;
+		mdev->rs_planed = 0;
+		spin_lock(&mdev->peer_seq_lock);
+		fifo_set(&mdev->rs_plan_s, 0);
+		spin_unlock(&mdev->peer_seq_lock);
 		/* ns.conn may already be != mdev->state.conn,
 		 * we may have been paused in between, or become paused until
 		 * the timer triggers.
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index cf04c1b..767107c 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -178,7 +178,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/bio.h>
-#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/jiffies.h>
 #include <linux/fcntl.h>
@@ -199,6 +198,7 @@
  * It's been recommended that take about 1/4 of the default speed
  * in some more extreme cases.
  */
+static DEFINE_MUTEX(floppy_mutex);
 static int slow_floppy;
 
 #include <asm/dma.h>
@@ -258,8 +258,8 @@
 #include <linux/completion.h>
 
 static struct request *current_req;
-static struct request_queue *floppy_queue;
 static void do_fd_request(struct request_queue *q);
+static int set_next_request(void);
 
 #ifndef fd_get_dma_residue
 #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
@@ -413,6 +413,7 @@
 static struct block_device *opened_bdev[N_DRIVE];
 static DEFINE_MUTEX(open_lock);
 static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
+static int fdc_queue;
 
 /*
  * This struct defines the different floppy types.
@@ -890,8 +891,8 @@
 	del_timer(&fd_timeout);
 	cont = NULL;
 	clear_bit(0, &fdc_busy);
-	if (current_req || blk_peek_request(floppy_queue))
-		do_fd_request(floppy_queue);
+	if (current_req || set_next_request())
+		do_fd_request(current_req->q);
 	spin_unlock_irqrestore(&floppy_lock, flags);
 	wake_up(&fdc_wait);
 }
@@ -2243,8 +2244,8 @@
  * logical buffer */
 static void request_done(int uptodate)
 {
-	struct request_queue *q = floppy_queue;
 	struct request *req = current_req;
+	struct request_queue *q;
 	unsigned long flags;
 	int block;
 	char msg[sizeof("request done ") + sizeof(int) * 3];
@@ -2258,6 +2259,8 @@
 		return;
 	}
 
+	q = req->q;
+
 	if (uptodate) {
 		/* maintain values for invalidation on geometry
 		 * change */
@@ -2811,6 +2814,28 @@
 	return 2;
 }
 
+/*
+ * Round-robin between our available drives, doing one request from each
+ */
+static int set_next_request(void)
+{
+	struct request_queue *q;
+	int old_pos = fdc_queue;
+
+	do {
+		q = disks[fdc_queue]->queue;
+		if (++fdc_queue == N_DRIVE)
+			fdc_queue = 0;
+		if (q) {
+			current_req = blk_fetch_request(q);
+			if (current_req)
+				break;
+		}
+	} while (fdc_queue != old_pos);
+
+	return current_req != NULL;
+}
+
 static void redo_fd_request(void)
 {
 	int drive;
@@ -2822,17 +2847,17 @@
 
 do_request:
 	if (!current_req) {
-		struct request *req;
+		int pending;
 
-		spin_lock_irq(floppy_queue->queue_lock);
-		req = blk_fetch_request(floppy_queue);
-		spin_unlock_irq(floppy_queue->queue_lock);
-		if (!req) {
+		spin_lock_irq(&floppy_lock);
+		pending = set_next_request();
+		spin_unlock_irq(&floppy_lock);
+
+		if (!pending) {
 			do_floppy = NULL;
 			unlock_fdc();
 			return;
 		}
-		current_req = req;
 	}
 	drive = (long)current_req->rq_disk->private_data;
 	set_fdc(drive);
@@ -3553,9 +3578,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&floppy_mutex);
 	ret = fd_locked_ioctl(bdev, mode, cmd, param);
-	unlock_kernel();
+	mutex_unlock(&floppy_mutex);
 
 	return ret;
 }
@@ -3616,7 +3641,7 @@
 {
 	int drive = (long)disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&floppy_mutex);
 	mutex_lock(&open_lock);
 	if (UDRS->fd_ref < 0)
 		UDRS->fd_ref = 0;
@@ -3627,7 +3652,7 @@
 	if (!UDRS->fd_ref)
 		opened_bdev[drive] = NULL;
 	mutex_unlock(&open_lock);
-	unlock_kernel();
+	mutex_unlock(&floppy_mutex);
 
 	return 0;
 }
@@ -3645,7 +3670,7 @@
 	int res = -EBUSY;
 	char *tmp;
 
-	lock_kernel();
+	mutex_lock(&floppy_mutex);
 	mutex_lock(&open_lock);
 	old_dev = UDRS->fd_device;
 	if (opened_bdev[drive] && opened_bdev[drive] != bdev)
@@ -3722,7 +3747,7 @@
 			goto out;
 	}
 	mutex_unlock(&open_lock);
-	unlock_kernel();
+	mutex_unlock(&floppy_mutex);
 	return 0;
 out:
 	if (UDRS->fd_ref < 0)
@@ -3733,7 +3758,7 @@
 		opened_bdev[drive] = NULL;
 out2:
 	mutex_unlock(&open_lock);
-	unlock_kernel();
+	mutex_unlock(&floppy_mutex);
 	return res;
 }
 
@@ -4165,6 +4190,13 @@
 			goto out_put_disk;
 		}
 
+		disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
+		if (!disks[dr]->queue) {
+			err = -ENOMEM;
+			goto out_put_disk;
+		}
+
+		blk_queue_max_hw_sectors(disks[dr]->queue, 64);
 		disks[dr]->major = FLOPPY_MAJOR;
 		disks[dr]->first_minor = TOMINOR(dr);
 		disks[dr]->fops = &floppy_fops;
@@ -4183,13 +4215,6 @@
 	if (err)
 		goto out_unreg_blkdev;
 
-	floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
-	if (!floppy_queue) {
-		err = -ENOMEM;
-		goto out_unreg_driver;
-	}
-	blk_queue_max_hw_sectors(floppy_queue, 64);
-
 	blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
 			    floppy_find, NULL, NULL);
 
@@ -4317,7 +4342,6 @@
 
 		/* to be cleaned up... */
 		disks[drive]->private_data = (void *)(long)drive;
-		disks[drive]->queue = floppy_queue;
 		disks[drive]->flags |= GENHD_FL_REMOVABLE;
 		disks[drive]->driverfs_dev = &floppy_device[drive].dev;
 		add_disk(disks[drive]);
@@ -4333,8 +4357,6 @@
 		floppy_release_irq_and_dma();
 out_unreg_region:
 	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
-	blk_cleanup_queue(floppy_queue);
-out_unreg_driver:
 	platform_driver_unregister(&floppy_driver);
 out_unreg_blkdev:
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
@@ -4342,6 +4364,8 @@
 	while (dr--) {
 		del_timer(&motor_off_timer[dr]);
 		put_disk(disks[dr]);
+		if (disks[dr]->queue)
+			blk_cleanup_queue(disks[dr]->queue);
 	}
 	return err;
 }
@@ -4550,11 +4574,11 @@
 			platform_device_unregister(&floppy_device[drive]);
 		}
 		put_disk(disks[drive]);
+		blk_cleanup_queue(disks[drive]->queue);
 	}
 
 	del_timer_sync(&fd_timeout);
 	del_timer_sync(&fd_timer);
-	blk_cleanup_queue(floppy_queue);
 
 	if (atomic_read(&usage_count))
 		floppy_release_irq_and_dma();
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 91797bb..6c48b35 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -67,16 +67,18 @@
 #include <linux/compat.h>
 #include <linux/suspend.h>
 #include <linux/freezer.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>		/* for invalidate_bdev() */
 #include <linux/completion.h>
 #include <linux/highmem.h>
 #include <linux/kthread.h>
 #include <linux/splice.h>
+#include <linux/sysfs.h>
 
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(loop_mutex);
 static LIST_HEAD(loop_devices);
 static DEFINE_MUTEX(loop_devices_mutex);
 
@@ -477,17 +479,17 @@
 	pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
 
 	if (bio_rw(bio) == WRITE) {
-		bool barrier = !!(bio->bi_rw & REQ_HARDBARRIER);
 		struct file *file = lo->lo_backing_file;
 
-		if (barrier) {
-			if (unlikely(!file->f_op->fsync)) {
-				ret = -EOPNOTSUPP;
-				goto out;
-			}
+		/* REQ_HARDBARRIER is deprecated */
+		if (bio->bi_rw & REQ_HARDBARRIER) {
+			ret = -EOPNOTSUPP;
+			goto out;
+		}
 
+		if (bio->bi_rw & REQ_FLUSH) {
 			ret = vfs_fsync(file, 0);
-			if (unlikely(ret)) {
+			if (unlikely(ret && ret != -EINVAL)) {
 				ret = -EIO;
 				goto out;
 			}
@@ -495,9 +497,9 @@
 
 		ret = lo_send(lo, bio, pos);
 
-		if (barrier && !ret) {
+		if ((bio->bi_rw & REQ_FUA) && !ret) {
 			ret = vfs_fsync(file, 0);
-			if (unlikely(ret))
+			if (unlikely(ret && ret != -EINVAL))
 				ret = -EIO;
 		}
 	} else
@@ -737,6 +739,103 @@
 	return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR;
 }
 
+/* loop sysfs attributes */
+
+static ssize_t loop_attr_show(struct device *dev, char *page,
+			      ssize_t (*callback)(struct loop_device *, char *))
+{
+	struct loop_device *l, *lo = NULL;
+
+	mutex_lock(&loop_devices_mutex);
+	list_for_each_entry(l, &loop_devices, lo_list)
+		if (disk_to_dev(l->lo_disk) == dev) {
+			lo = l;
+			break;
+		}
+	mutex_unlock(&loop_devices_mutex);
+
+	return lo ? callback(lo, page) : -EIO;
+}
+
+#define LOOP_ATTR_RO(_name)						\
+static ssize_t loop_attr_##_name##_show(struct loop_device *, char *);	\
+static ssize_t loop_attr_do_show_##_name(struct device *d,		\
+				struct device_attribute *attr, char *b)	\
+{									\
+	return loop_attr_show(d, b, loop_attr_##_name##_show);		\
+}									\
+static struct device_attribute loop_attr_##_name =			\
+	__ATTR(_name, S_IRUGO, loop_attr_do_show_##_name, NULL);
+
+static ssize_t loop_attr_backing_file_show(struct loop_device *lo, char *buf)
+{
+	ssize_t ret;
+	char *p = NULL;
+
+	mutex_lock(&lo->lo_ctl_mutex);
+	if (lo->lo_backing_file)
+		p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1);
+	mutex_unlock(&lo->lo_ctl_mutex);
+
+	if (IS_ERR_OR_NULL(p))
+		ret = PTR_ERR(p);
+	else {
+		ret = strlen(p);
+		memmove(buf, p, ret);
+		buf[ret++] = '\n';
+		buf[ret] = 0;
+	}
+
+	return ret;
+}
+
+static ssize_t loop_attr_offset_show(struct loop_device *lo, char *buf)
+{
+	return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_offset);
+}
+
+static ssize_t loop_attr_sizelimit_show(struct loop_device *lo, char *buf)
+{
+	return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_sizelimit);
+}
+
+static ssize_t loop_attr_autoclear_show(struct loop_device *lo, char *buf)
+{
+	int autoclear = (lo->lo_flags & LO_FLAGS_AUTOCLEAR);
+
+	return sprintf(buf, "%s\n", autoclear ? "1" : "0");
+}
+
+LOOP_ATTR_RO(backing_file);
+LOOP_ATTR_RO(offset);
+LOOP_ATTR_RO(sizelimit);
+LOOP_ATTR_RO(autoclear);
+
+static struct attribute *loop_attrs[] = {
+	&loop_attr_backing_file.attr,
+	&loop_attr_offset.attr,
+	&loop_attr_sizelimit.attr,
+	&loop_attr_autoclear.attr,
+	NULL,
+};
+
+static struct attribute_group loop_attribute_group = {
+	.name = "loop",
+	.attrs= loop_attrs,
+};
+
+static int loop_sysfs_init(struct loop_device *lo)
+{
+	return sysfs_create_group(&disk_to_dev(lo->lo_disk)->kobj,
+				  &loop_attribute_group);
+}
+
+static void loop_sysfs_exit(struct loop_device *lo)
+{
+	sysfs_remove_group(&disk_to_dev(lo->lo_disk)->kobj,
+			   &loop_attribute_group);
+}
+
 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 		       struct block_device *bdev, unsigned int arg)
 {
@@ -832,10 +931,11 @@
 	lo->lo_queue->unplug_fn = loop_unplug;
 
 	if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
-		blk_queue_ordered(lo->lo_queue, QUEUE_ORDERED_DRAIN);
+		blk_queue_flush(lo->lo_queue, REQ_FLUSH);
 
 	set_capacity(lo->lo_disk, size);
 	bd_set_size(bdev, size << 9);
+	loop_sysfs_init(lo);
 	/* let user-space know about the new size */
 	kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
 
@@ -854,6 +954,7 @@
 	return 0;
 
 out_clr:
+	loop_sysfs_exit(lo);
 	lo->lo_thread = NULL;
 	lo->lo_device = NULL;
 	lo->lo_backing_file = NULL;
@@ -950,6 +1051,7 @@
 	set_capacity(lo->lo_disk, 0);
 	if (bdev) {
 		bd_set_size(bdev, 0);
+		loop_sysfs_exit(lo);
 		/* let user-space know about this change */
 		kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
 	}
@@ -1409,11 +1511,11 @@
 {
 	struct loop_device *lo = bdev->bd_disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&loop_mutex);
 	mutex_lock(&lo->lo_ctl_mutex);
 	lo->lo_refcnt++;
 	mutex_unlock(&lo->lo_ctl_mutex);
-	unlock_kernel();
+	mutex_unlock(&loop_mutex);
 
 	return 0;
 }
@@ -1423,7 +1525,7 @@
 	struct loop_device *lo = disk->private_data;
 	int err;
 
-	lock_kernel();
+	mutex_lock(&loop_mutex);
 	mutex_lock(&lo->lo_ctl_mutex);
 
 	if (--lo->lo_refcnt)
@@ -1448,7 +1550,7 @@
 out:
 	mutex_unlock(&lo->lo_ctl_mutex);
 out_unlocked:
-	lock_kernel();
+	mutex_unlock(&loop_mutex);
 	return 0;
 }
 
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 0daa422..a32fb41 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -24,7 +24,7 @@
 #include <linux/errno.h>
 #include <linux/file.h>
 #include <linux/ioctl.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compiler.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
@@ -53,6 +53,7 @@
 #define DBG_BLKDEV      0x0100
 #define DBG_RX          0x0200
 #define DBG_TX          0x0400
+static DEFINE_MUTEX(nbd_mutex);
 static unsigned int debugflags;
 #endif /* NDEBUG */
 
@@ -717,11 +718,11 @@
 	dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
 			lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
 
-	lock_kernel();
+	mutex_lock(&nbd_mutex);
 	mutex_lock(&lo->tx_lock);
 	error = __nbd_ioctl(bdev, lo, cmd, arg);
 	mutex_unlock(&lo->tx_lock);
-	unlock_kernel();
+	mutex_unlock(&nbd_mutex);
 
 	return error;
 }
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c
index 2284b4f..87311eb 100644
--- a/drivers/block/osdblk.c
+++ b/drivers/block/osdblk.c
@@ -310,8 +310,7 @@
 			break;
 
 		/* filter out block requests we don't understand */
-		if (rq->cmd_type != REQ_TYPE_FS &&
-		    !(rq->cmd_flags & REQ_HARDBARRIER)) {
+		if (rq->cmd_type != REQ_TYPE_FS) {
 			blk_end_request_all(rq, 0);
 			continue;
 		}
@@ -439,7 +438,7 @@
 	blk_queue_stack_limits(q, osd_request_queue(osdev->osd));
 
 	blk_queue_prep_rq(q, blk_queue_start_tag);
-	blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH);
+	blk_queue_flush(q, REQ_FLUSH);
 
 	disk->queue = q;
 
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 76f8565..62cec6a 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -138,9 +138,10 @@
 #include <linux/cdrom.h>
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(pcd_mutex);
 static DEFINE_SPINLOCK(pcd_lock);
 
 module_param(verbose, bool, 0644);
@@ -227,9 +228,9 @@
 	struct pcd_unit *cd = bdev->bd_disk->private_data;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pcd_mutex);
 	ret = cdrom_open(&cd->info, bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&pcd_mutex);
 
 	return ret;
 }
@@ -237,9 +238,9 @@
 static int pcd_block_release(struct gendisk *disk, fmode_t mode)
 {
 	struct pcd_unit *cd = disk->private_data;
-	lock_kernel();
+	mutex_lock(&pcd_mutex);
 	cdrom_release(&cd->info, mode);
-	unlock_kernel();
+	mutex_unlock(&pcd_mutex);
 	return 0;
 }
 
@@ -249,9 +250,9 @@
 	struct pcd_unit *cd = bdev->bd_disk->private_data;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pcd_mutex);
 	ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&pcd_mutex);
 
 	return ret;
 }
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 985f0d4..c0ee155 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -153,10 +153,11 @@
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <linux/workqueue.h>
 
+static DEFINE_MUTEX(pd_mutex);
 static DEFINE_SPINLOCK(pd_lock);
 
 module_param(verbose, bool, 0);
@@ -736,14 +737,14 @@
 {
 	struct pd_unit *disk = bdev->bd_disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&pd_mutex);
 	disk->access++;
 
 	if (disk->removable) {
 		pd_special_command(disk, pd_media_check);
 		pd_special_command(disk, pd_door_lock);
 	}
-	unlock_kernel();
+	mutex_unlock(&pd_mutex);
 	return 0;
 }
 
@@ -771,10 +772,10 @@
 
 	switch (cmd) {
 	case CDROMEJECT:
-		lock_kernel();
+		mutex_lock(&pd_mutex);
 		if (disk->access == 1)
 			pd_special_command(disk, pd_eject);
-		unlock_kernel();
+		mutex_unlock(&pd_mutex);
 		return 0;
 	default:
 		return -EINVAL;
@@ -785,10 +786,10 @@
 {
 	struct pd_unit *disk = p->private_data;
 
-	lock_kernel();
+	mutex_lock(&pd_mutex);
 	if (!--disk->access && disk->removable)
 		pd_special_command(disk, pd_door_unlock);
-	unlock_kernel();
+	mutex_unlock(&pd_mutex);
 
 	return 0;
 }
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 4457b49..635f25d 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -152,9 +152,10 @@
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(pf_mutex);
 static DEFINE_SPINLOCK(pf_spin_lock);
 
 module_param(verbose, bool, 0644);
@@ -302,7 +303,7 @@
 	struct pf_unit *pf = bdev->bd_disk->private_data;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pf_mutex);
 	pf_identify(pf);
 
 	ret = -ENODEV;
@@ -318,7 +319,7 @@
 	if (pf->removable)
 		pf_lock(pf, 1);
 out:
-	unlock_kernel();
+	mutex_unlock(&pf_mutex);
 	return ret;
 }
 
@@ -349,9 +350,9 @@
 
 	if (pf->access != 1)
 		return -EBUSY;
-	lock_kernel();
+	mutex_lock(&pf_mutex);
 	pf_eject(pf);
-	unlock_kernel();
+	mutex_unlock(&pf_mutex);
 
 	return 0;
 }
@@ -360,9 +361,9 @@
 {
 	struct pf_unit *pf = disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&pf_mutex);
 	if (pf->access <= 0) {
-		unlock_kernel();
+		mutex_unlock(&pf_mutex);
 		return -EINVAL;
 	}
 
@@ -371,7 +372,7 @@
 	if (!pf->access && pf->removable)
 		pf_lock(pf, 0);
 
-	unlock_kernel();
+	mutex_unlock(&pf_mutex);
 	return 0;
 
 }
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index c397b3d..6b9a200 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -162,7 +162,7 @@
 #include <linux/pg.h>
 #include <linux/device.h>
 #include <linux/sched.h>	/* current, TASK_* */
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
@@ -193,6 +193,7 @@
 
 #define ATAPI_IDENTIFY		0x12
 
+static DEFINE_MUTEX(pg_mutex);
 static int pg_open(struct inode *inode, struct file *file);
 static int pg_release(struct inode *inode, struct file *file);
 static ssize_t pg_read(struct file *filp, char __user *buf,
@@ -234,6 +235,7 @@
 	.write = pg_write,
 	.open = pg_open,
 	.release = pg_release,
+	.llseek = noop_llseek,
 };
 
 static void pg_init_units(void)
@@ -518,7 +520,7 @@
 	struct pg *dev = &devices[unit];
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&pg_mutex);
 	if ((unit >= PG_UNITS) || (!dev->present)) {
 		ret = -ENODEV;
 		goto out;
@@ -547,7 +549,7 @@
 	file->private_data = dev;
 
 out:
-	unlock_kernel();
+	mutex_unlock(&pg_mutex);
 	return ret;
 }
 
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index bc5825f..7179f79 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -146,7 +146,7 @@
 #include <linux/mtio.h>
 #include <linux/device.h>
 #include <linux/sched.h>	/* current, TASK_*, schedule_timeout() */
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/uaccess.h>
 
@@ -189,6 +189,7 @@
 #define ATAPI_MODE_SENSE	0x1a
 #define ATAPI_LOG_SENSE		0x4d
 
+static DEFINE_MUTEX(pt_mutex);
 static int pt_open(struct inode *inode, struct file *file);
 static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 static int pt_release(struct inode *inode, struct file *file);
@@ -239,6 +240,7 @@
 	.unlocked_ioctl = pt_ioctl,
 	.open = pt_open,
 	.release = pt_release,
+	.llseek = noop_llseek,
 };
 
 /* sysfs class support */
@@ -650,9 +652,9 @@
 	struct pt_unit *tape = pt + unit;
 	int err;
 
-	lock_kernel();
+	mutex_lock(&pt_mutex);
 	if (unit >= PT_UNITS || (!tape->present)) {
-		unlock_kernel();
+		mutex_unlock(&pt_mutex);
 		return -ENODEV;
 	}
 
@@ -681,12 +683,12 @@
 	}
 
 	file->private_data = tape;
-	unlock_kernel();
+	mutex_unlock(&pt_mutex);
 	return 0;
 
 out:
 	atomic_inc(&tape->available);
-	unlock_kernel();
+	mutex_unlock(&pt_mutex);
 	return err;
 }
 
@@ -704,15 +706,15 @@
 		switch (mtop.mt_op) {
 
 		case MTREW:
-			lock_kernel();
+			mutex_lock(&pt_mutex);
 			pt_rewind(tape);
-			unlock_kernel();
+			mutex_unlock(&pt_mutex);
 			return 0;
 
 		case MTWEOF:
-			lock_kernel();
+			mutex_lock(&pt_mutex);
 			pt_write_fm(tape);
-			unlock_kernel();
+			mutex_unlock(&pt_mutex);
 			return 0;
 
 		default:
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index b1cbeb5..19b3568 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -57,7 +57,6 @@
 #include <linux/seq_file.h>
 #include <linux/miscdevice.h>
 #include <linux/freezer.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <scsi/scsi_cmnd.h>
@@ -86,6 +85,7 @@
 
 #define ZONE(sector, pd) (((sector) + (pd)->offset) & ~((pd)->settings.size - 1))
 
+static DEFINE_MUTEX(pktcdvd_mutex);
 static struct pktcdvd_device *pkt_devs[MAX_WRITERS];
 static struct proc_dir_entry *pkt_proc;
 static int pktdev_major;
@@ -753,7 +753,6 @@
 
 	rq->timeout = 60*HZ;
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
-	rq->cmd_flags |= REQ_HARDBARRIER;
 	if (cgc->quiet)
 		rq->cmd_flags |= REQ_QUIET;
 
@@ -2369,7 +2368,7 @@
 	pkt_shrink_pktlist(pd);
 }
 
-static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor)
+static struct pktcdvd_device *pkt_find_dev_from_minor(unsigned int dev_minor)
 {
 	if (dev_minor >= MAX_WRITERS)
 		return NULL;
@@ -2383,7 +2382,7 @@
 
 	VPRINTK(DRIVER_NAME": entering open\n");
 
-	lock_kernel();
+	mutex_lock(&pktcdvd_mutex);
 	mutex_lock(&ctl_mutex);
 	pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev));
 	if (!pd) {
@@ -2411,7 +2410,7 @@
 	}
 
 	mutex_unlock(&ctl_mutex);
-	unlock_kernel();
+	mutex_unlock(&pktcdvd_mutex);
 	return 0;
 
 out_dec:
@@ -2419,7 +2418,7 @@
 out:
 	VPRINTK(DRIVER_NAME": failed open (%d)\n", ret);
 	mutex_unlock(&ctl_mutex);
-	unlock_kernel();
+	mutex_unlock(&pktcdvd_mutex);
 	return ret;
 }
 
@@ -2428,7 +2427,7 @@
 	struct pktcdvd_device *pd = disk->private_data;
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&pktcdvd_mutex);
 	mutex_lock(&ctl_mutex);
 	pd->refcnt--;
 	BUG_ON(pd->refcnt < 0);
@@ -2437,7 +2436,7 @@
 		pkt_release_dev(pd, flush);
 	}
 	mutex_unlock(&ctl_mutex);
-	unlock_kernel();
+	mutex_unlock(&pktcdvd_mutex);
 	return ret;
 }
 
@@ -2773,7 +2772,7 @@
 	VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd,
 		MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
 
-	lock_kernel();
+	mutex_lock(&pktcdvd_mutex);
 	switch (cmd) {
 	case CDROMEJECT:
 		/*
@@ -2798,7 +2797,7 @@
 		VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd);
 		ret = -ENOTTY;
 	}
-	unlock_kernel();
+	mutex_unlock(&pktcdvd_mutex);
 
 	return ret;
 }
@@ -3046,6 +3045,7 @@
 	.compat_ioctl	= pkt_ctl_compat_ioctl,
 #endif
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice pkt_misc = {
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index e9da874..8e1ce2e 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -113,7 +113,7 @@
 			memcpy(buf, dev->bounce_buf+offset, size);
 		offset += size;
 		flush_kernel_dcache_page(bvec->bv_page);
-		bvec_kunmap_irq(bvec, &flags);
+		bvec_kunmap_irq(buf, &flags);
 		i++;
 	}
 }
@@ -468,7 +468,7 @@
 	blk_queue_dma_alignment(queue, dev->blk_size-1);
 	blk_queue_logical_block_size(queue, dev->blk_size);
 
-	blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH);
+	blk_queue_flush(queue, REQ_FLUSH);
 
 	blk_queue_max_segments(queue, -1);
 	blk_queue_max_segment_size(queue, dev->bounce_size);
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
new file mode 100644
index 0000000..6ec9d53
--- /dev/null
+++ b/drivers/block/rbd.c
@@ -0,0 +1,1841 @@
+/*
+   rbd.c -- Export ceph rados objects as a Linux block device
+
+
+   based on drivers/block/osdblk.c:
+
+   Copyright 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+
+   Instructions for use
+   --------------------
+
+   1) Map a Linux block device to an existing rbd image.
+
+      Usage: <mon ip addr> <options> <pool name> <rbd image name> [snap name]
+
+      $ echo "192.168.0.1 name=admin rbd foo" > /sys/class/rbd/add
+
+      The snapshot name can be "-" or omitted to map the image read/write.
+
+   2) List all active blkdev<->object mappings.
+
+      In this example, we have performed step #1 twice, creating two blkdevs,
+      mapped to two separate rados objects in the rados rbd pool
+
+      $ cat /sys/class/rbd/list
+      #id     major   client_name     pool    name    snap    KB
+      0       254     client4143      rbd     foo     -      1024000
+
+      The columns, in order, are:
+      - blkdev unique id
+      - blkdev assigned major
+      - rados client id
+      - rados pool name
+      - rados block device name
+      - mapped snapshot ("-" if none)
+      - device size in KB
+
+
+   3) Create a snapshot.
+
+      Usage: <blkdev id> <snapname>
+
+      $ echo "0 mysnap" > /sys/class/rbd/snap_create
+
+
+   4) Listing a snapshot.
+
+      $ cat /sys/class/rbd/snaps_list
+      #id     snap    KB
+      0       -       1024000 (*)
+      0       foo     1024000
+
+      The columns, in order, are:
+      - blkdev unique id
+      - snapshot name, '-' means none (active read/write version)
+      - size of device at time of snapshot
+      - the (*) indicates this is the active version
+
+   5) Rollback to snapshot.
+
+      Usage: <blkdev id> <snapname>
+
+      $ echo "0 mysnap" > /sys/class/rbd/snap_rollback
+
+
+   6) Mapping an image using snapshot.
+
+      A snapshot mapping is read-only. This is being done by passing
+      snap=<snapname> to the options when adding a device.
+
+      $ echo "192.168.0.1 name=admin,snap=mysnap rbd foo" > /sys/class/rbd/add
+
+
+   7) Remove an active blkdev<->rbd image mapping.
+
+      In this example, we remove the mapping with blkdev unique id 1.
+
+      $ echo 1 > /sys/class/rbd/remove
+
+
+   NOTE:  The actual creation and deletion of rados objects is outside the scope
+   of this driver.
+
+ */
+
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/osd_client.h>
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/decode.h>
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+
+#include "rbd_types.h"
+
+#define DRV_NAME "rbd"
+#define DRV_NAME_LONG "rbd (rados block device)"
+
+#define RBD_MINORS_PER_MAJOR	256		/* max minors per blkdev */
+
+#define RBD_MAX_MD_NAME_LEN	(96 + sizeof(RBD_SUFFIX))
+#define RBD_MAX_POOL_NAME_LEN	64
+#define RBD_MAX_SNAP_NAME_LEN	32
+#define RBD_MAX_OPT_LEN		1024
+
+#define RBD_SNAP_HEAD_NAME	"-"
+
+#define DEV_NAME_LEN		32
+
+/*
+ * block device image metadata (in-memory version)
+ */
+struct rbd_image_header {
+	u64 image_size;
+	char block_name[32];
+	__u8 obj_order;
+	__u8 crypt_type;
+	__u8 comp_type;
+	struct rw_semaphore snap_rwsem;
+	struct ceph_snap_context *snapc;
+	size_t snap_names_len;
+	u64 snap_seq;
+	u32 total_snaps;
+
+	char *snap_names;
+	u64 *snap_sizes;
+};
+
+/*
+ * an instance of the client.  multiple devices may share a client.
+ */
+struct rbd_client {
+	struct ceph_client	*client;
+	struct kref		kref;
+	struct list_head	node;
+};
+
+/*
+ * a single io request
+ */
+struct rbd_request {
+	struct request		*rq;		/* blk layer request */
+	struct bio		*bio;		/* cloned bio */
+	struct page		**pages;	/* list of used pages */
+	u64			len;
+};
+
+/*
+ * a single device
+ */
+struct rbd_device {
+	int			id;		/* blkdev unique id */
+
+	int			major;		/* blkdev assigned major */
+	struct gendisk		*disk;		/* blkdev's gendisk and rq */
+	struct request_queue	*q;
+
+	struct ceph_client	*client;
+	struct rbd_client	*rbd_client;
+
+	char			name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */
+
+	spinlock_t		lock;		/* queue lock */
+
+	struct rbd_image_header	header;
+	char			obj[RBD_MAX_OBJ_NAME_LEN]; /* rbd image name */
+	int			obj_len;
+	char			obj_md_name[RBD_MAX_MD_NAME_LEN]; /* hdr nm. */
+	char			pool_name[RBD_MAX_POOL_NAME_LEN];
+	int			poolid;
+
+	char                    snap_name[RBD_MAX_SNAP_NAME_LEN];
+	u32 cur_snap;	/* index+1 of current snapshot within snap context
+			   0 - for the head */
+	int read_only;
+
+	struct list_head	node;
+};
+
+static spinlock_t node_lock;      /* protects client get/put */
+
+static struct class *class_rbd;	  /* /sys/class/rbd */
+static DEFINE_MUTEX(ctl_mutex);	  /* Serialize open/close/setup/teardown */
+static LIST_HEAD(rbd_dev_list);    /* devices */
+static LIST_HEAD(rbd_client_list);      /* clients */
+
+
+static int rbd_open(struct block_device *bdev, fmode_t mode)
+{
+	struct gendisk *disk = bdev->bd_disk;
+	struct rbd_device *rbd_dev = disk->private_data;
+
+	set_device_ro(bdev, rbd_dev->read_only);
+
+	if ((mode & FMODE_WRITE) && rbd_dev->read_only)
+		return -EROFS;
+
+	return 0;
+}
+
+static const struct block_device_operations rbd_bd_ops = {
+	.owner			= THIS_MODULE,
+	.open			= rbd_open,
+};
+
+/*
+ * Initialize an rbd client instance.
+ * We own *opt.
+ */
+static struct rbd_client *rbd_client_create(struct ceph_options *opt)
+{
+	struct rbd_client *rbdc;
+	int ret = -ENOMEM;
+
+	dout("rbd_client_create\n");
+	rbdc = kmalloc(sizeof(struct rbd_client), GFP_KERNEL);
+	if (!rbdc)
+		goto out_opt;
+
+	kref_init(&rbdc->kref);
+	INIT_LIST_HEAD(&rbdc->node);
+
+	rbdc->client = ceph_create_client(opt, rbdc);
+	if (IS_ERR(rbdc->client))
+		goto out_rbdc;
+	opt = NULL; /* Now rbdc->client is responsible for opt */
+
+	ret = ceph_open_session(rbdc->client);
+	if (ret < 0)
+		goto out_err;
+
+	spin_lock(&node_lock);
+	list_add_tail(&rbdc->node, &rbd_client_list);
+	spin_unlock(&node_lock);
+
+	dout("rbd_client_create created %p\n", rbdc);
+	return rbdc;
+
+out_err:
+	ceph_destroy_client(rbdc->client);
+out_rbdc:
+	kfree(rbdc);
+out_opt:
+	if (opt)
+		ceph_destroy_options(opt);
+	return ERR_PTR(ret);
+}
+
+/*
+ * Find a ceph client with specific addr and configuration.
+ */
+static struct rbd_client *__rbd_client_find(struct ceph_options *opt)
+{
+	struct rbd_client *client_node;
+
+	if (opt->flags & CEPH_OPT_NOSHARE)
+		return NULL;
+
+	list_for_each_entry(client_node, &rbd_client_list, node)
+		if (ceph_compare_options(opt, client_node->client) == 0)
+			return client_node;
+	return NULL;
+}
+
+/*
+ * Get a ceph client with specific addr and configuration, if one does
+ * not exist create it.
+ */
+static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr,
+			  char *options)
+{
+	struct rbd_client *rbdc;
+	struct ceph_options *opt;
+	int ret;
+
+	ret = ceph_parse_options(&opt, options, mon_addr,
+				 mon_addr + strlen(mon_addr), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	spin_lock(&node_lock);
+	rbdc = __rbd_client_find(opt);
+	if (rbdc) {
+		ceph_destroy_options(opt);
+
+		/* using an existing client */
+		kref_get(&rbdc->kref);
+		rbd_dev->rbd_client = rbdc;
+		rbd_dev->client = rbdc->client;
+		spin_unlock(&node_lock);
+		return 0;
+	}
+	spin_unlock(&node_lock);
+
+	rbdc = rbd_client_create(opt);
+	if (IS_ERR(rbdc))
+		return PTR_ERR(rbdc);
+
+	rbd_dev->rbd_client = rbdc;
+	rbd_dev->client = rbdc->client;
+	return 0;
+}
+
+/*
+ * Destroy ceph client
+ */
+static void rbd_client_release(struct kref *kref)
+{
+	struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref);
+
+	dout("rbd_release_client %p\n", rbdc);
+	spin_lock(&node_lock);
+	list_del(&rbdc->node);
+	spin_unlock(&node_lock);
+
+	ceph_destroy_client(rbdc->client);
+	kfree(rbdc);
+}
+
+/*
+ * Drop reference to ceph client node. If it's not referenced anymore, release
+ * it.
+ */
+static void rbd_put_client(struct rbd_device *rbd_dev)
+{
+	kref_put(&rbd_dev->rbd_client->kref, rbd_client_release);
+	rbd_dev->rbd_client = NULL;
+	rbd_dev->client = NULL;
+}
+
+
+/*
+ * Create a new header structure, translate header format from the on-disk
+ * header.
+ */
+static int rbd_header_from_disk(struct rbd_image_header *header,
+				 struct rbd_image_header_ondisk *ondisk,
+				 int allocated_snaps,
+				 gfp_t gfp_flags)
+{
+	int i;
+	u32 snap_count = le32_to_cpu(ondisk->snap_count);
+	int ret = -ENOMEM;
+
+	init_rwsem(&header->snap_rwsem);
+
+	header->snap_names_len = le64_to_cpu(ondisk->snap_names_len);
+	header->snapc = kmalloc(sizeof(struct ceph_snap_context) +
+				snap_count *
+				 sizeof(struct rbd_image_snap_ondisk),
+				gfp_flags);
+	if (!header->snapc)
+		return -ENOMEM;
+	if (snap_count) {
+		header->snap_names = kmalloc(header->snap_names_len,
+					     GFP_KERNEL);
+		if (!header->snap_names)
+			goto err_snapc;
+		header->snap_sizes = kmalloc(snap_count * sizeof(u64),
+					     GFP_KERNEL);
+		if (!header->snap_sizes)
+			goto err_names;
+	} else {
+		header->snap_names = NULL;
+		header->snap_sizes = NULL;
+	}
+	memcpy(header->block_name, ondisk->block_name,
+	       sizeof(ondisk->block_name));
+
+	header->image_size = le64_to_cpu(ondisk->image_size);
+	header->obj_order = ondisk->options.order;
+	header->crypt_type = ondisk->options.crypt_type;
+	header->comp_type = ondisk->options.comp_type;
+
+	atomic_set(&header->snapc->nref, 1);
+	header->snap_seq = le64_to_cpu(ondisk->snap_seq);
+	header->snapc->num_snaps = snap_count;
+	header->total_snaps = snap_count;
+
+	if (snap_count &&
+	    allocated_snaps == snap_count) {
+		for (i = 0; i < snap_count; i++) {
+			header->snapc->snaps[i] =
+				le64_to_cpu(ondisk->snaps[i].id);
+			header->snap_sizes[i] =
+				le64_to_cpu(ondisk->snaps[i].image_size);
+		}
+
+		/* copy snapshot names */
+		memcpy(header->snap_names, &ondisk->snaps[i],
+			header->snap_names_len);
+	}
+
+	return 0;
+
+err_names:
+	kfree(header->snap_names);
+err_snapc:
+	kfree(header->snapc);
+	return ret;
+}
+
+static int snap_index(struct rbd_image_header *header, int snap_num)
+{
+	return header->total_snaps - snap_num;
+}
+
+static u64 cur_snap_id(struct rbd_device *rbd_dev)
+{
+	struct rbd_image_header *header = &rbd_dev->header;
+
+	if (!rbd_dev->cur_snap)
+		return 0;
+
+	return header->snapc->snaps[snap_index(header, rbd_dev->cur_snap)];
+}
+
+static int snap_by_name(struct rbd_image_header *header, const char *snap_name,
+			u64 *seq, u64 *size)
+{
+	int i;
+	char *p = header->snap_names;
+
+	for (i = 0; i < header->total_snaps; i++, p += strlen(p) + 1) {
+		if (strcmp(snap_name, p) == 0)
+			break;
+	}
+	if (i == header->total_snaps)
+		return -ENOENT;
+	if (seq)
+		*seq = header->snapc->snaps[i];
+
+	if (size)
+		*size = header->snap_sizes[i];
+
+	return i;
+}
+
+static int rbd_header_set_snap(struct rbd_device *dev,
+			       const char *snap_name,
+			       u64 *size)
+{
+	struct rbd_image_header *header = &dev->header;
+	struct ceph_snap_context *snapc = header->snapc;
+	int ret = -ENOENT;
+
+	down_write(&header->snap_rwsem);
+
+	if (!snap_name ||
+	    !*snap_name ||
+	    strcmp(snap_name, "-") == 0 ||
+	    strcmp(snap_name, RBD_SNAP_HEAD_NAME) == 0) {
+		if (header->total_snaps)
+			snapc->seq = header->snap_seq;
+		else
+			snapc->seq = 0;
+		dev->cur_snap = 0;
+		dev->read_only = 0;
+		if (size)
+			*size = header->image_size;
+	} else {
+		ret = snap_by_name(header, snap_name, &snapc->seq, size);
+		if (ret < 0)
+			goto done;
+
+		dev->cur_snap = header->total_snaps - ret;
+		dev->read_only = 1;
+	}
+
+	ret = 0;
+done:
+	up_write(&header->snap_rwsem);
+	return ret;
+}
+
+static void rbd_header_free(struct rbd_image_header *header)
+{
+	kfree(header->snapc);
+	kfree(header->snap_names);
+	kfree(header->snap_sizes);
+}
+
+/*
+ * get the actual striped segment name, offset and length
+ */
+static u64 rbd_get_segment(struct rbd_image_header *header,
+			   const char *block_name,
+			   u64 ofs, u64 len,
+			   char *seg_name, u64 *segofs)
+{
+	u64 seg = ofs >> header->obj_order;
+
+	if (seg_name)
+		snprintf(seg_name, RBD_MAX_SEG_NAME_LEN,
+			 "%s.%012llx", block_name, seg);
+
+	ofs = ofs & ((1 << header->obj_order) - 1);
+	len = min_t(u64, len, (1 << header->obj_order) - ofs);
+
+	if (segofs)
+		*segofs = ofs;
+
+	return len;
+}
+
+/*
+ * bio helpers
+ */
+
+static void bio_chain_put(struct bio *chain)
+{
+	struct bio *tmp;
+
+	while (chain) {
+		tmp = chain;
+		chain = chain->bi_next;
+		bio_put(tmp);
+	}
+}
+
+/*
+ * zeros a bio chain, starting at specific offset
+ */
+static void zero_bio_chain(struct bio *chain, int start_ofs)
+{
+	struct bio_vec *bv;
+	unsigned long flags;
+	void *buf;
+	int i;
+	int pos = 0;
+
+	while (chain) {
+		bio_for_each_segment(bv, chain, i) {
+			if (pos + bv->bv_len > start_ofs) {
+				int remainder = max(start_ofs - pos, 0);
+				buf = bvec_kmap_irq(bv, &flags);
+				memset(buf + remainder, 0,
+				       bv->bv_len - remainder);
+				bvec_kunmap_irq(buf, &flags);
+			}
+			pos += bv->bv_len;
+		}
+
+		chain = chain->bi_next;
+	}
+}
+
+/*
+ * bio_chain_clone - clone a chain of bios up to a certain length.
+ * might return a bio_pair that will need to be released.
+ */
+static struct bio *bio_chain_clone(struct bio **old, struct bio **next,
+				   struct bio_pair **bp,
+				   int len, gfp_t gfpmask)
+{
+	struct bio *tmp, *old_chain = *old, *new_chain = NULL, *tail = NULL;
+	int total = 0;
+
+	if (*bp) {
+		bio_pair_release(*bp);
+		*bp = NULL;
+	}
+
+	while (old_chain && (total < len)) {
+		tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs);
+		if (!tmp)
+			goto err_out;
+
+		if (total + old_chain->bi_size > len) {
+			struct bio_pair *bp;
+
+			/*
+			 * this split can only happen with a single paged bio,
+			 * split_bio will BUG_ON if this is not the case
+			 */
+			dout("bio_chain_clone split! total=%d remaining=%d"
+			     "bi_size=%d\n",
+			     (int)total, (int)len-total,
+			     (int)old_chain->bi_size);
+
+			/* split the bio. We'll release it either in the next
+			   call, or it will have to be released outside */
+			bp = bio_split(old_chain, (len - total) / 512ULL);
+			if (!bp)
+				goto err_out;
+
+			__bio_clone(tmp, &bp->bio1);
+
+			*next = &bp->bio2;
+		} else {
+			__bio_clone(tmp, old_chain);
+			*next = old_chain->bi_next;
+		}
+
+		tmp->bi_bdev = NULL;
+		gfpmask &= ~__GFP_WAIT;
+		tmp->bi_next = NULL;
+
+		if (!new_chain) {
+			new_chain = tail = tmp;
+		} else {
+			tail->bi_next = tmp;
+			tail = tmp;
+		}
+		old_chain = old_chain->bi_next;
+
+		total += tmp->bi_size;
+	}
+
+	BUG_ON(total < len);
+
+	if (tail)
+		tail->bi_next = NULL;
+
+	*old = old_chain;
+
+	return new_chain;
+
+err_out:
+	dout("bio_chain_clone with err\n");
+	bio_chain_put(new_chain);
+	return NULL;
+}
+
+/*
+ * helpers for osd request op vectors.
+ */
+static int rbd_create_rw_ops(struct ceph_osd_req_op **ops,
+			    int num_ops,
+			    int opcode,
+			    u32 payload_len)
+{
+	*ops = kzalloc(sizeof(struct ceph_osd_req_op) * (num_ops + 1),
+		       GFP_NOIO);
+	if (!*ops)
+		return -ENOMEM;
+	(*ops)[0].op = opcode;
+	/*
+	 * op extent offset and length will be set later on
+	 * in calc_raw_layout()
+	 */
+	(*ops)[0].payload_len = payload_len;
+	return 0;
+}
+
+static void rbd_destroy_ops(struct ceph_osd_req_op *ops)
+{
+	kfree(ops);
+}
+
+/*
+ * Send ceph osd request
+ */
+static int rbd_do_request(struct request *rq,
+			  struct rbd_device *dev,
+			  struct ceph_snap_context *snapc,
+			  u64 snapid,
+			  const char *obj, u64 ofs, u64 len,
+			  struct bio *bio,
+			  struct page **pages,
+			  int num_pages,
+			  int flags,
+			  struct ceph_osd_req_op *ops,
+			  int num_reply,
+			  void (*rbd_cb)(struct ceph_osd_request *req,
+					 struct ceph_msg *msg))
+{
+	struct ceph_osd_request *req;
+	struct ceph_file_layout *layout;
+	int ret;
+	u64 bno;
+	struct timespec mtime = CURRENT_TIME;
+	struct rbd_request *req_data;
+	struct ceph_osd_request_head *reqhead;
+	struct rbd_image_header *header = &dev->header;
+
+	ret = -ENOMEM;
+	req_data = kzalloc(sizeof(*req_data), GFP_NOIO);
+	if (!req_data)
+		goto done;
+
+	dout("rbd_do_request len=%lld ofs=%lld\n", len, ofs);
+
+	down_read(&header->snap_rwsem);
+
+	req = ceph_osdc_alloc_request(&dev->client->osdc, flags,
+				      snapc,
+				      ops,
+				      false,
+				      GFP_NOIO, pages, bio);
+	if (IS_ERR(req)) {
+		up_read(&header->snap_rwsem);
+		ret = PTR_ERR(req);
+		goto done_pages;
+	}
+
+	req->r_callback = rbd_cb;
+
+	req_data->rq = rq;
+	req_data->bio = bio;
+	req_data->pages = pages;
+	req_data->len = len;
+
+	req->r_priv = req_data;
+
+	reqhead = req->r_request->front.iov_base;
+	reqhead->snapid = cpu_to_le64(CEPH_NOSNAP);
+
+	strncpy(req->r_oid, obj, sizeof(req->r_oid));
+	req->r_oid_len = strlen(req->r_oid);
+
+	layout = &req->r_file_layout;
+	memset(layout, 0, sizeof(*layout));
+	layout->fl_stripe_unit = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
+	layout->fl_stripe_count = cpu_to_le32(1);
+	layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
+	layout->fl_pg_preferred = cpu_to_le32(-1);
+	layout->fl_pg_pool = cpu_to_le32(dev->poolid);
+	ceph_calc_raw_layout(&dev->client->osdc, layout, snapid,
+			     ofs, &len, &bno, req, ops);
+
+	ceph_osdc_build_request(req, ofs, &len,
+				ops,
+				snapc,
+				&mtime,
+				req->r_oid, req->r_oid_len);
+	up_read(&header->snap_rwsem);
+
+	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);
+		ceph_osdc_put_request(req);
+	}
+	return ret;
+
+done_err:
+	bio_chain_put(req_data->bio);
+	ceph_osdc_put_request(req);
+done_pages:
+	kfree(req_data);
+done:
+	if (rq)
+		blk_end_request(rq, ret, len);
+	return ret;
+}
+
+/*
+ * Ceph osd op callback
+ */
+static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg)
+{
+	struct rbd_request *req_data = req->r_priv;
+	struct ceph_osd_reply_head *replyhead;
+	struct ceph_osd_op *op;
+	__s32 rc;
+	u64 bytes;
+	int read_op;
+
+	/* parse reply */
+	replyhead = msg->front.iov_base;
+	WARN_ON(le32_to_cpu(replyhead->num_ops) == 0);
+	op = (void *)(replyhead + 1);
+	rc = le32_to_cpu(replyhead->result);
+	bytes = le64_to_cpu(op->extent.length);
+	read_op = (le32_to_cpu(op->op) == CEPH_OSD_OP_READ);
+
+	dout("rbd_req_cb bytes=%lld readop=%d rc=%d\n", bytes, read_op, rc);
+
+	if (rc == -ENOENT && read_op) {
+		zero_bio_chain(req_data->bio, 0);
+		rc = 0;
+	} else if (rc == 0 && read_op && bytes < req_data->len) {
+		zero_bio_chain(req_data->bio, bytes);
+		bytes = req_data->len;
+	}
+
+	blk_end_request(req_data->rq, rc, bytes);
+
+	if (req_data->bio)
+		bio_chain_put(req_data->bio);
+
+	ceph_osdc_put_request(req);
+	kfree(req_data);
+}
+
+/*
+ * Do a synchronous ceph osd operation
+ */
+static int rbd_req_sync_op(struct rbd_device *dev,
+			   struct ceph_snap_context *snapc,
+			   u64 snapid,
+			   int opcode,
+			   int flags,
+			   struct ceph_osd_req_op *orig_ops,
+			   int num_reply,
+			   const char *obj,
+			   u64 ofs, u64 len,
+			   char *buf)
+{
+	int ret;
+	struct page **pages;
+	int num_pages;
+	struct ceph_osd_req_op *ops = orig_ops;
+	u32 payload_len;
+
+	num_pages = calc_pages_for(ofs , len);
+	pages = ceph_alloc_page_vector(num_pages, GFP_KERNEL);
+	if (IS_ERR(pages))
+		return PTR_ERR(pages);
+
+	if (!orig_ops) {
+		payload_len = (flags & CEPH_OSD_FLAG_WRITE ? len : 0);
+		ret = rbd_create_rw_ops(&ops, 1, opcode, payload_len);
+		if (ret < 0)
+			goto done;
+
+		if ((flags & CEPH_OSD_FLAG_WRITE) && buf) {
+			ret = ceph_copy_to_page_vector(pages, buf, ofs, len);
+			if (ret < 0)
+				goto done_ops;
+		}
+	}
+
+	ret = rbd_do_request(NULL, dev, snapc, snapid,
+			  obj, ofs, len, NULL,
+			  pages, num_pages,
+			  flags,
+			  ops,
+			  2,
+			  NULL);
+	if (ret < 0)
+		goto done_ops;
+
+	if ((flags & CEPH_OSD_FLAG_READ) && buf)
+		ret = ceph_copy_from_page_vector(pages, buf, ofs, ret);
+
+done_ops:
+	if (!orig_ops)
+		rbd_destroy_ops(ops);
+done:
+	ceph_release_page_vector(pages, num_pages);
+	return ret;
+}
+
+/*
+ * Do an asynchronous ceph osd operation
+ */
+static int rbd_do_op(struct request *rq,
+		     struct rbd_device *rbd_dev ,
+		     struct ceph_snap_context *snapc,
+		     u64 snapid,
+		     int opcode, int flags, int num_reply,
+		     u64 ofs, u64 len,
+		     struct bio *bio)
+{
+	char *seg_name;
+	u64 seg_ofs;
+	u64 seg_len;
+	int ret;
+	struct ceph_osd_req_op *ops;
+	u32 payload_len;
+
+	seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
+	if (!seg_name)
+		return -ENOMEM;
+
+	seg_len = rbd_get_segment(&rbd_dev->header,
+				  rbd_dev->header.block_name,
+				  ofs, len,
+				  seg_name, &seg_ofs);
+
+	payload_len = (flags & CEPH_OSD_FLAG_WRITE ? seg_len : 0);
+
+	ret = rbd_create_rw_ops(&ops, 1, opcode, payload_len);
+	if (ret < 0)
+		goto done;
+
+	/* we've taken care of segment sizes earlier when we
+	   cloned the bios. We should never have a segment
+	   truncated at this point */
+	BUG_ON(seg_len < len);
+
+	ret = rbd_do_request(rq, rbd_dev, snapc, snapid,
+			     seg_name, seg_ofs, seg_len,
+			     bio,
+			     NULL, 0,
+			     flags,
+			     ops,
+			     num_reply,
+			     rbd_req_cb);
+done:
+	kfree(seg_name);
+	return ret;
+}
+
+/*
+ * Request async osd write
+ */
+static int rbd_req_write(struct request *rq,
+			 struct rbd_device *rbd_dev,
+			 struct ceph_snap_context *snapc,
+			 u64 ofs, u64 len,
+			 struct bio *bio)
+{
+	return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP,
+			 CEPH_OSD_OP_WRITE,
+			 CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+			 2,
+			 ofs, len, bio);
+}
+
+/*
+ * Request async osd read
+ */
+static int rbd_req_read(struct request *rq,
+			 struct rbd_device *rbd_dev,
+			 u64 snapid,
+			 u64 ofs, u64 len,
+			 struct bio *bio)
+{
+	return rbd_do_op(rq, rbd_dev, NULL,
+			 (snapid ? snapid : CEPH_NOSNAP),
+			 CEPH_OSD_OP_READ,
+			 CEPH_OSD_FLAG_READ,
+			 2,
+			 ofs, len, bio);
+}
+
+/*
+ * Request sync osd read
+ */
+static int rbd_req_sync_read(struct rbd_device *dev,
+			  struct ceph_snap_context *snapc,
+			  u64 snapid,
+			  const char *obj,
+			  u64 ofs, u64 len,
+			  char *buf)
+{
+	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);
+}
+
+/*
+ * Request sync osd read
+ */
+static int rbd_req_sync_rollback_obj(struct rbd_device *dev,
+				     u64 snapid,
+				     const char *obj)
+{
+	struct ceph_osd_req_op *ops;
+	int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_ROLLBACK, 0);
+	if (ret < 0)
+		return ret;
+
+	ops[0].snap.snapid = snapid;
+
+	ret = rbd_req_sync_op(dev, NULL,
+			       CEPH_NOSNAP,
+			       0,
+			       CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+			       ops,
+			       1, obj, 0, 0, NULL);
+
+	rbd_destroy_ops(ops);
+
+	if (ret < 0)
+		return ret;
+
+	return ret;
+}
+
+/*
+ * Request sync osd read
+ */
+static int rbd_req_sync_exec(struct rbd_device *dev,
+			     const char *obj,
+			     const char *cls,
+			     const char *method,
+			     const char *data,
+			     int len)
+{
+	struct ceph_osd_req_op *ops;
+	int cls_len = strlen(cls);
+	int method_len = strlen(method);
+	int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_CALL,
+				    cls_len + method_len + len);
+	if (ret < 0)
+		return ret;
+
+	ops[0].cls.class_name = cls;
+	ops[0].cls.class_len = (__u8)cls_len;
+	ops[0].cls.method_name = method;
+	ops[0].cls.method_len = (__u8)method_len;
+	ops[0].cls.argc = 0;
+	ops[0].cls.indata = data;
+	ops[0].cls.indata_len = len;
+
+	ret = rbd_req_sync_op(dev, NULL,
+			       CEPH_NOSNAP,
+			       0,
+			       CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+			       ops,
+			       1, obj, 0, 0, NULL);
+
+	rbd_destroy_ops(ops);
+
+	dout("cls_exec returned %d\n", ret);
+	return ret;
+}
+
+/*
+ * block device queue callback
+ */
+static void rbd_rq_fn(struct request_queue *q)
+{
+	struct rbd_device *rbd_dev = q->queuedata;
+	struct request *rq;
+	struct bio_pair *bp = NULL;
+
+	rq = blk_fetch_request(q);
+
+	while (1) {
+		struct bio *bio;
+		struct bio *rq_bio, *next_bio = NULL;
+		bool do_write;
+		int size, op_size = 0;
+		u64 ofs;
+
+		/* peek at request from block layer */
+		if (!rq)
+			break;
+
+		dout("fetched request\n");
+
+		/* filter out block requests we don't understand */
+		if ((rq->cmd_type != REQ_TYPE_FS)) {
+			__blk_end_request_all(rq, 0);
+			goto next;
+		}
+
+		/* deduce our operation (read, write) */
+		do_write = (rq_data_dir(rq) == WRITE);
+
+		size = blk_rq_bytes(rq);
+		ofs = blk_rq_pos(rq) * 512ULL;
+		rq_bio = rq->bio;
+		if (do_write && rbd_dev->read_only) {
+			__blk_end_request_all(rq, -EROFS);
+			goto next;
+		}
+
+		spin_unlock_irq(q->queue_lock);
+
+		dout("%s 0x%x bytes at 0x%llx\n",
+		     do_write ? "write" : "read",
+		     size, blk_rq_pos(rq) * 512ULL);
+
+		do {
+			/* a bio clone to be passed down to OSD req */
+			dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt);
+			op_size = rbd_get_segment(&rbd_dev->header,
+						  rbd_dev->header.block_name,
+						  ofs, size,
+						  NULL, NULL);
+			bio = bio_chain_clone(&rq_bio, &next_bio, &bp,
+					      op_size, GFP_ATOMIC);
+			if (!bio) {
+				spin_lock_irq(q->queue_lock);
+				__blk_end_request_all(rq, -ENOMEM);
+				goto next;
+			}
+
+			/* init OSD command: write or read */
+			if (do_write)
+				rbd_req_write(rq, rbd_dev,
+					      rbd_dev->header.snapc,
+					      ofs,
+					      op_size, bio);
+			else
+				rbd_req_read(rq, rbd_dev,
+					     cur_snap_id(rbd_dev),
+					     ofs,
+					     op_size, bio);
+
+			size -= op_size;
+			ofs += op_size;
+
+			rq_bio = next_bio;
+		} while (size > 0);
+
+		if (bp)
+			bio_pair_release(bp);
+
+		spin_lock_irq(q->queue_lock);
+next:
+		rq = blk_fetch_request(q);
+	}
+}
+
+/*
+ * a queue callback. Makes sure that we don't create a bio that spans across
+ * multiple osd objects. One exception would be with a single page bios,
+ * which we handle later at bio_chain_clone
+ */
+static int rbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
+			  struct bio_vec *bvec)
+{
+	struct rbd_device *rbd_dev = q->queuedata;
+	unsigned int chunk_sectors = 1 << (rbd_dev->header.obj_order - 9);
+	sector_t sector = bmd->bi_sector + get_start_sect(bmd->bi_bdev);
+	unsigned int bio_sectors = bmd->bi_size >> 9;
+	int max;
+
+	max =  (chunk_sectors - ((sector & (chunk_sectors - 1))
+				 + bio_sectors)) << 9;
+	if (max < 0)
+		max = 0; /* bio_add cannot handle a negative return */
+	if (max <= bvec->bv_len && bio_sectors == 0)
+		return bvec->bv_len;
+	return max;
+}
+
+static void rbd_free_disk(struct rbd_device *rbd_dev)
+{
+	struct gendisk *disk = rbd_dev->disk;
+
+	if (!disk)
+		return;
+
+	rbd_header_free(&rbd_dev->header);
+
+	if (disk->flags & GENHD_FL_UP)
+		del_gendisk(disk);
+	if (disk->queue)
+		blk_cleanup_queue(disk->queue);
+	put_disk(disk);
+}
+
+/*
+ * reload the ondisk the header 
+ */
+static int rbd_read_header(struct rbd_device *rbd_dev,
+			   struct rbd_image_header *header)
+{
+	ssize_t rc;
+	struct rbd_image_header_ondisk *dh;
+	int snap_count = 0;
+	u64 snap_names_len = 0;
+
+	while (1) {
+		int len = sizeof(*dh) +
+			  snap_count * sizeof(struct rbd_image_snap_ondisk) +
+			  snap_names_len;
+
+		rc = -ENOMEM;
+		dh = kmalloc(len, GFP_KERNEL);
+		if (!dh)
+			return -ENOMEM;
+
+		rc = rbd_req_sync_read(rbd_dev,
+				       NULL, CEPH_NOSNAP,
+				       rbd_dev->obj_md_name,
+				       0, len,
+				       (char *)dh);
+		if (rc < 0)
+			goto out_dh;
+
+		rc = rbd_header_from_disk(header, dh, snap_count, GFP_KERNEL);
+		if (rc < 0)
+			goto out_dh;
+
+		if (snap_count != header->total_snaps) {
+			snap_count = header->total_snaps;
+			snap_names_len = header->snap_names_len;
+			rbd_header_free(header);
+			kfree(dh);
+			continue;
+		}
+		break;
+	}
+
+out_dh:
+	kfree(dh);
+	return rc;
+}
+
+/*
+ * create a snapshot
+ */
+static int rbd_header_add_snap(struct rbd_device *dev,
+			       const char *snap_name,
+			       gfp_t gfp_flags)
+{
+	int name_len = strlen(snap_name);
+	u64 new_snapid;
+	int ret;
+	void *data, *data_start, *data_end;
+
+	/* we should create a snapshot only if we're pointing at the head */
+	if (dev->cur_snap)
+		return -EINVAL;
+
+	ret = ceph_monc_create_snapid(&dev->client->monc, dev->poolid,
+				      &new_snapid);
+	dout("created snapid=%lld\n", new_snapid);
+	if (ret < 0)
+		return ret;
+
+	data = kmalloc(name_len + 16, gfp_flags);
+	if (!data)
+		return -ENOMEM;
+
+	data_start = data;
+	data_end = data + name_len + 16;
+
+	ceph_encode_string_safe(&data, data_end, snap_name, name_len, bad);
+	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);
+
+	kfree(data_start);
+
+	if (ret < 0)
+		return ret;
+
+	dev->header.snapc->seq =  new_snapid;
+
+	return 0;
+bad:
+	return -ERANGE;
+}
+
+/*
+ * only read the first part of the ondisk header, without the snaps info
+ */
+static int rbd_update_snaps(struct rbd_device *rbd_dev)
+{
+	int ret;
+	struct rbd_image_header h;
+	u64 snap_seq;
+
+	ret = rbd_read_header(rbd_dev, &h);
+	if (ret < 0)
+		return ret;
+
+	down_write(&rbd_dev->header.snap_rwsem);
+
+	snap_seq = rbd_dev->header.snapc->seq;
+
+	kfree(rbd_dev->header.snapc);
+	kfree(rbd_dev->header.snap_names);
+	kfree(rbd_dev->header.snap_sizes);
+
+	rbd_dev->header.total_snaps = h.total_snaps;
+	rbd_dev->header.snapc = h.snapc;
+	rbd_dev->header.snap_names = h.snap_names;
+	rbd_dev->header.snap_sizes = h.snap_sizes;
+	rbd_dev->header.snapc->seq = snap_seq;
+
+	up_write(&rbd_dev->header.snap_rwsem);
+
+	return 0;
+}
+
+static int rbd_init_disk(struct rbd_device *rbd_dev)
+{
+	struct gendisk *disk;
+	struct request_queue *q;
+	int rc;
+	u64 total_size = 0;
+
+	/* contact OSD, request size info about the object being mapped */
+	rc = rbd_read_header(rbd_dev, &rbd_dev->header);
+	if (rc)
+		return rc;
+
+	rc = rbd_header_set_snap(rbd_dev, rbd_dev->snap_name, &total_size);
+	if (rc)
+		return rc;
+
+	/* create gendisk info */
+	rc = -ENOMEM;
+	disk = alloc_disk(RBD_MINORS_PER_MAJOR);
+	if (!disk)
+		goto out;
+
+	sprintf(disk->disk_name, DRV_NAME "%d", rbd_dev->id);
+	disk->major = rbd_dev->major;
+	disk->first_minor = 0;
+	disk->fops = &rbd_bd_ops;
+	disk->private_data = rbd_dev;
+
+	/* init rq */
+	rc = -ENOMEM;
+	q = blk_init_queue(rbd_rq_fn, &rbd_dev->lock);
+	if (!q)
+		goto out_disk;
+	blk_queue_merge_bvec(q, rbd_merge_bvec);
+	disk->queue = q;
+
+	q->queuedata = rbd_dev;
+
+	rbd_dev->disk = disk;
+	rbd_dev->q = q;
+
+	/* finally, announce the disk to the world */
+	set_capacity(disk, total_size / 512ULL);
+	add_disk(disk);
+
+	pr_info("%s: added with size 0x%llx\n",
+		disk->disk_name, (unsigned long long)total_size);
+	return 0;
+
+out_disk:
+	put_disk(disk);
+out:
+	return rc;
+}
+
+/********************************************************************
+ * /sys/class/rbd/
+ *                   add	map rados objects to blkdev
+ *                   remove	unmap rados objects
+ *                   list	show mappings
+ *******************************************************************/
+
+static void class_rbd_release(struct class *cls)
+{
+	kfree(cls);
+}
+
+static ssize_t class_rbd_list(struct class *c,
+			      struct class_attribute *attr,
+			      char *data)
+{
+	int n = 0;
+	struct list_head *tmp;
+	int max = PAGE_SIZE;
+
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+	n += snprintf(data, max,
+		      "#id\tmajor\tclient_name\tpool\tname\tsnap\tKB\n");
+
+	list_for_each(tmp, &rbd_dev_list) {
+		struct rbd_device *rbd_dev;
+
+		rbd_dev = list_entry(tmp, struct rbd_device, node);
+		n += snprintf(data+n, max-n,
+			      "%d\t%d\tclient%lld\t%s\t%s\t%s\t%lld\n",
+			      rbd_dev->id,
+			      rbd_dev->major,
+			      ceph_client_id(rbd_dev->client),
+			      rbd_dev->pool_name,
+			      rbd_dev->obj, rbd_dev->snap_name,
+			      rbd_dev->header.image_size >> 10);
+		if (n == max)
+			break;
+	}
+
+	mutex_unlock(&ctl_mutex);
+	return n;
+}
+
+static ssize_t class_rbd_add(struct class *c,
+			     struct class_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct ceph_osd_client *osdc;
+	struct rbd_device *rbd_dev;
+	ssize_t rc = -ENOMEM;
+	int irc, new_id = 0;
+	struct list_head *tmp;
+	char *mon_dev_name;
+	char *options;
+
+	if (!try_module_get(THIS_MODULE))
+		return -ENODEV;
+
+	mon_dev_name = kmalloc(RBD_MAX_OPT_LEN, GFP_KERNEL);
+	if (!mon_dev_name)
+		goto err_out_mod;
+
+	options = kmalloc(RBD_MAX_OPT_LEN, GFP_KERNEL);
+	if (!options)
+		goto err_mon_dev;
+
+	/* new rbd_device object */
+	rbd_dev = kzalloc(sizeof(*rbd_dev), GFP_KERNEL);
+	if (!rbd_dev)
+		goto err_out_opt;
+
+	/* static rbd_device initialization */
+	spin_lock_init(&rbd_dev->lock);
+	INIT_LIST_HEAD(&rbd_dev->node);
+
+	/* generate unique id: find highest unique id, add one */
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+	list_for_each(tmp, &rbd_dev_list) {
+		struct rbd_device *rbd_dev;
+
+		rbd_dev = list_entry(tmp, struct rbd_device, node);
+		if (rbd_dev->id >= new_id)
+			new_id = rbd_dev->id + 1;
+	}
+
+	rbd_dev->id = new_id;
+
+	/* add to global list */
+	list_add_tail(&rbd_dev->node, &rbd_dev_list);
+
+	/* parse add command */
+	if (sscanf(buf, "%" __stringify(RBD_MAX_OPT_LEN) "s "
+		   "%" __stringify(RBD_MAX_OPT_LEN) "s "
+		   "%" __stringify(RBD_MAX_POOL_NAME_LEN) "s "
+		   "%" __stringify(RBD_MAX_OBJ_NAME_LEN) "s"
+		   "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s",
+		   mon_dev_name, options, rbd_dev->pool_name,
+		   rbd_dev->obj, rbd_dev->snap_name) < 4) {
+		rc = -EINVAL;
+		goto err_out_slot;
+	}
+
+	if (rbd_dev->snap_name[0] == 0)
+		rbd_dev->snap_name[0] = '-';
+
+	rbd_dev->obj_len = strlen(rbd_dev->obj);
+	snprintf(rbd_dev->obj_md_name, sizeof(rbd_dev->obj_md_name), "%s%s",
+		 rbd_dev->obj, RBD_SUFFIX);
+
+	/* initialize rest of new object */
+	snprintf(rbd_dev->name, DEV_NAME_LEN, DRV_NAME "%d", rbd_dev->id);
+	rc = rbd_get_client(rbd_dev, mon_dev_name, options);
+	if (rc < 0)
+		goto err_out_slot;
+
+	mutex_unlock(&ctl_mutex);
+
+	/* pick the pool */
+	osdc = &rbd_dev->client->osdc;
+	rc = ceph_pg_poolid_by_name(osdc->osdmap, rbd_dev->pool_name);
+	if (rc < 0)
+		goto err_out_client;
+	rbd_dev->poolid = rc;
+
+	/* register our block device */
+	irc = register_blkdev(0, rbd_dev->name);
+	if (irc < 0) {
+		rc = irc;
+		goto err_out_client;
+	}
+	rbd_dev->major = irc;
+
+	/* set up and announce blkdev mapping */
+	rc = rbd_init_disk(rbd_dev);
+	if (rc)
+		goto err_out_blkdev;
+
+	return count;
+
+err_out_blkdev:
+	unregister_blkdev(rbd_dev->major, rbd_dev->name);
+err_out_client:
+	rbd_put_client(rbd_dev);
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+err_out_slot:
+	list_del_init(&rbd_dev->node);
+	mutex_unlock(&ctl_mutex);
+
+	kfree(rbd_dev);
+err_out_opt:
+	kfree(options);
+err_mon_dev:
+	kfree(mon_dev_name);
+err_out_mod:
+	dout("Error adding device %s\n", buf);
+	module_put(THIS_MODULE);
+	return rc;
+}
+
+static struct rbd_device *__rbd_get_dev(unsigned long id)
+{
+	struct list_head *tmp;
+	struct rbd_device *rbd_dev;
+
+	list_for_each(tmp, &rbd_dev_list) {
+		rbd_dev = list_entry(tmp, struct rbd_device, node);
+		if (rbd_dev->id == id)
+			return rbd_dev;
+	}
+	return NULL;
+}
+
+static ssize_t class_rbd_remove(struct class *c,
+				struct class_attribute *attr,
+				const char *buf,
+				size_t count)
+{
+	struct rbd_device *rbd_dev = NULL;
+	int target_id, rc;
+	unsigned long ul;
+
+	rc = strict_strtoul(buf, 10, &ul);
+	if (rc)
+		return rc;
+
+	/* convert to int; abort if we lost anything in the conversion */
+	target_id = (int) ul;
+	if (target_id != ul)
+		return -EINVAL;
+
+	/* remove object from list immediately */
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+	rbd_dev = __rbd_get_dev(target_id);
+	if (rbd_dev)
+		list_del_init(&rbd_dev->node);
+
+	mutex_unlock(&ctl_mutex);
+
+	if (!rbd_dev)
+		return -ENOENT;
+
+	rbd_put_client(rbd_dev);
+
+	/* clean up and free blkdev */
+	rbd_free_disk(rbd_dev);
+	unregister_blkdev(rbd_dev->major, rbd_dev->name);
+	kfree(rbd_dev);
+
+	/* release module ref */
+	module_put(THIS_MODULE);
+
+	return count;
+}
+
+static ssize_t class_rbd_snaps_list(struct class *c,
+			      struct class_attribute *attr,
+			      char *data)
+{
+	struct rbd_device *rbd_dev = NULL;
+	struct list_head *tmp;
+	struct rbd_image_header *header;
+	int i, n = 0, max = PAGE_SIZE;
+	int ret;
+
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+	n += snprintf(data, max, "#id\tsnap\tKB\n");
+
+	list_for_each(tmp, &rbd_dev_list) {
+		char *names, *p;
+		struct ceph_snap_context *snapc;
+
+		rbd_dev = list_entry(tmp, struct rbd_device, node);
+		header = &rbd_dev->header;
+
+		down_read(&header->snap_rwsem);
+
+		names = header->snap_names;
+		snapc = header->snapc;
+
+		n += snprintf(data + n, max - n, "%d\t%s\t%lld%s\n",
+			      rbd_dev->id, RBD_SNAP_HEAD_NAME,
+			      header->image_size >> 10,
+			      (!rbd_dev->cur_snap ? " (*)" : ""));
+		if (n == max)
+			break;
+
+		p = names;
+		for (i = 0; i < header->total_snaps; i++, p += strlen(p) + 1) {
+			n += snprintf(data + n, max - n, "%d\t%s\t%lld%s\n",
+			      rbd_dev->id, p, header->snap_sizes[i] >> 10,
+			      (rbd_dev->cur_snap &&
+			       (snap_index(header, i) == rbd_dev->cur_snap) ?
+			       " (*)" : ""));
+			if (n == max)
+				break;
+		}
+
+		up_read(&header->snap_rwsem);
+	}
+
+
+	ret = n;
+	mutex_unlock(&ctl_mutex);
+	return ret;
+}
+
+static ssize_t class_rbd_snaps_refresh(struct class *c,
+				struct class_attribute *attr,
+				const char *buf,
+				size_t count)
+{
+	struct rbd_device *rbd_dev = NULL;
+	int target_id, rc;
+	unsigned long ul;
+	int ret = count;
+
+	rc = strict_strtoul(buf, 10, &ul);
+	if (rc)
+		return rc;
+
+	/* convert to int; abort if we lost anything in the conversion */
+	target_id = (int) ul;
+	if (target_id != ul)
+		return -EINVAL;
+
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+	rbd_dev = __rbd_get_dev(target_id);
+	if (!rbd_dev) {
+		ret = -ENOENT;
+		goto done;
+	}
+
+	rc = rbd_update_snaps(rbd_dev);
+	if (rc < 0)
+		ret = rc;
+
+done:
+	mutex_unlock(&ctl_mutex);
+	return ret;
+}
+
+static ssize_t class_rbd_snap_create(struct class *c,
+				struct class_attribute *attr,
+				const char *buf,
+				size_t count)
+{
+	struct rbd_device *rbd_dev = NULL;
+	int target_id, ret;
+	char *name;
+
+	name = kmalloc(RBD_MAX_SNAP_NAME_LEN + 1, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	/* parse snaps add command */
+	if (sscanf(buf, "%d "
+		   "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s",
+		   &target_id,
+		   name) != 2) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+	rbd_dev = __rbd_get_dev(target_id);
+	if (!rbd_dev) {
+		ret = -ENOENT;
+		goto done_unlock;
+	}
+
+	ret = rbd_header_add_snap(rbd_dev,
+				  name, GFP_KERNEL);
+	if (ret < 0)
+		goto done_unlock;
+
+	ret = rbd_update_snaps(rbd_dev);
+	if (ret < 0)
+		goto done_unlock;
+
+	ret = count;
+done_unlock:
+	mutex_unlock(&ctl_mutex);
+done:
+	kfree(name);
+	return ret;
+}
+
+static ssize_t class_rbd_rollback(struct class *c,
+				struct class_attribute *attr,
+				const char *buf,
+				size_t count)
+{
+	struct rbd_device *rbd_dev = NULL;
+	int target_id, ret;
+	u64 snapid;
+	char snap_name[RBD_MAX_SNAP_NAME_LEN];
+	u64 cur_ofs;
+	char *seg_name;
+
+	/* parse snaps add command */
+	if (sscanf(buf, "%d "
+		   "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s",
+		   &target_id,
+		   snap_name) != 2) {
+		return -EINVAL;
+	}
+
+	ret = -ENOMEM;
+	seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
+	if (!seg_name)
+		return ret;
+
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+	rbd_dev = __rbd_get_dev(target_id);
+	if (!rbd_dev) {
+		ret = -ENOENT;
+		goto done_unlock;
+	}
+
+	ret = snap_by_name(&rbd_dev->header, snap_name, &snapid, NULL);
+	if (ret < 0)
+		goto done_unlock;
+
+	dout("snapid=%lld\n", snapid);
+
+	cur_ofs = 0;
+	while (cur_ofs < rbd_dev->header.image_size) {
+		cur_ofs += rbd_get_segment(&rbd_dev->header,
+					   rbd_dev->obj,
+					   cur_ofs, (u64)-1,
+					   seg_name, NULL);
+		dout("seg_name=%s\n", seg_name);
+
+		ret = rbd_req_sync_rollback_obj(rbd_dev, snapid, seg_name);
+		if (ret < 0)
+			pr_warning("could not roll back obj %s err=%d\n",
+				   seg_name, ret);
+	}
+
+	ret = rbd_update_snaps(rbd_dev);
+	if (ret < 0)
+		goto done_unlock;
+
+	ret = count;
+
+done_unlock:
+	mutex_unlock(&ctl_mutex);
+	kfree(seg_name);
+
+	return ret;
+}
+
+static struct class_attribute class_rbd_attrs[] = {
+	__ATTR(add,		0200, NULL, class_rbd_add),
+	__ATTR(remove,		0200, NULL, class_rbd_remove),
+	__ATTR(list,		0444, class_rbd_list, NULL),
+	__ATTR(snaps_refresh,	0200, NULL, class_rbd_snaps_refresh),
+	__ATTR(snap_create,	0200, NULL, class_rbd_snap_create),
+	__ATTR(snaps_list,	0444, class_rbd_snaps_list, NULL),
+	__ATTR(snap_rollback,	0200, NULL, class_rbd_rollback),
+	__ATTR_NULL
+};
+
+/*
+ * create control files in sysfs
+ * /sys/class/rbd/...
+ */
+static int rbd_sysfs_init(void)
+{
+	int ret = -ENOMEM;
+
+	class_rbd = kzalloc(sizeof(*class_rbd), GFP_KERNEL);
+	if (!class_rbd)
+		goto out;
+
+	class_rbd->name = DRV_NAME;
+	class_rbd->owner = THIS_MODULE;
+	class_rbd->class_release = class_rbd_release;
+	class_rbd->class_attrs = class_rbd_attrs;
+
+	ret = class_register(class_rbd);
+	if (ret)
+		goto out_class;
+	return 0;
+
+out_class:
+	kfree(class_rbd);
+	class_rbd = NULL;
+	pr_err(DRV_NAME ": failed to create class rbd\n");
+out:
+	return ret;
+}
+
+static void rbd_sysfs_cleanup(void)
+{
+	if (class_rbd)
+		class_destroy(class_rbd);
+	class_rbd = NULL;
+}
+
+int __init rbd_init(void)
+{
+	int rc;
+
+	rc = rbd_sysfs_init();
+	if (rc)
+		return rc;
+	spin_lock_init(&node_lock);
+	pr_info("loaded " DRV_NAME_LONG "\n");
+	return 0;
+}
+
+void __exit rbd_exit(void)
+{
+	rbd_sysfs_cleanup();
+}
+
+module_init(rbd_init);
+module_exit(rbd_exit);
+
+MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
+MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
+MODULE_DESCRIPTION("rados block device");
+
+/* following authorship retained from original osdblk.c */
+MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>");
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/block/rbd_types.h b/drivers/block/rbd_types.h
new file mode 100644
index 0000000..fc6c678
--- /dev/null
+++ b/drivers/block/rbd_types.h
@@ -0,0 +1,73 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#ifndef CEPH_RBD_TYPES_H
+#define CEPH_RBD_TYPES_H
+
+#include <linux/types.h>
+
+/*
+ * rbd image 'foo' consists of objects
+ *   foo.rbd      - image metadata
+ *   foo.00000000
+ *   foo.00000001
+ *   ...          - data
+ */
+
+#define RBD_SUFFIX		".rbd"
+#define RBD_DIRECTORY           "rbd_directory"
+#define RBD_INFO                "rbd_info"
+
+#define RBD_DEFAULT_OBJ_ORDER	22   /* 4MB */
+#define RBD_MIN_OBJ_ORDER       16
+#define RBD_MAX_OBJ_ORDER       30
+
+#define RBD_MAX_OBJ_NAME_LEN	96
+#define RBD_MAX_SEG_NAME_LEN	128
+
+#define RBD_COMP_NONE		0
+#define RBD_CRYPT_NONE		0
+
+#define RBD_HEADER_TEXT		"<<< Rados Block Device Image >>>\n"
+#define RBD_HEADER_SIGNATURE	"RBD"
+#define RBD_HEADER_VERSION	"001.005"
+
+struct rbd_info {
+	__le64 max_id;
+} __attribute__ ((packed));
+
+struct rbd_image_snap_ondisk {
+	__le64 id;
+	__le64 image_size;
+} __attribute__((packed));
+
+struct rbd_image_header_ondisk {
+	char text[40];
+	char block_name[24];
+	char signature[4];
+	char version[8];
+	struct {
+		__u8 order;
+		__u8 crypt_type;
+		__u8 comp_type;
+		__u8 unused;
+	} __attribute__((packed)) options;
+	__le64 image_size;
+	__le64 snap_seq;
+	__le32 snap_count;
+	__le32 reserved;
+	__le64 snap_names_len;
+	struct rbd_image_snap_ondisk snaps[0];
+} __attribute__((packed));
+
+
+#endif
diff --git a/drivers/block/swim.c b/drivers/block/swim.c
index 2e46815..75333d0 100644
--- a/drivers/block/swim.c
+++ b/drivers/block/swim.c
@@ -20,7 +20,7 @@
 #include <linux/fd.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/hdreg.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
@@ -222,6 +222,7 @@
 extern int swim_read_sector_data(struct swim __iomem *base,
 				 unsigned char *data);
 
+static DEFINE_MUTEX(swim_mutex);
 static inline void set_swim_mode(struct swim __iomem *base, int enable)
 {
 	struct iwm __iomem *iwm_base;
@@ -666,9 +667,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&swim_mutex);
 	ret = floppy_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&swim_mutex);
 
 	return ret;
 }
@@ -678,7 +679,7 @@
 	struct floppy_state *fs = disk->private_data;
 	struct swim __iomem *base = fs->swd->base;
 
-	lock_kernel();
+	mutex_lock(&swim_mutex);
 	if (fs->ref_count < 0)
 		fs->ref_count = 0;
 	else if (fs->ref_count > 0)
@@ -686,7 +687,7 @@
 
 	if (fs->ref_count == 0)
 		swim_motor(base, OFF);
-	unlock_kernel();
+	mutex_unlock(&swim_mutex);
 
 	return 0;
 }
@@ -704,9 +705,9 @@
 	case FDEJECT:
 		if (fs->ref_count != 1)
 			return -EBUSY;
-		lock_kernel();
+		mutex_lock(&swim_mutex);
 		err = floppy_eject(fs);
-		unlock_kernel();
+		mutex_unlock(&swim_mutex);
 		return err;
 
 	case FDGETPRM:
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index cc6a386..bf3a5b8 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -25,7 +25,7 @@
 #include <linux/ioctl.h>
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
@@ -36,6 +36,7 @@
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 
+static DEFINE_MUTEX(swim3_mutex);
 static struct request_queue *swim3_queue;
 static struct gendisk *disks[2];
 static struct request *fd_req;
@@ -873,9 +874,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&swim3_mutex);
 	ret = floppy_locked_ioctl(bdev, mode, cmd, param);
-	unlock_kernel();
+	mutex_unlock(&swim3_mutex);
 
 	return ret;
 }
@@ -953,9 +954,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&swim3_mutex);
 	ret = floppy_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&swim3_mutex);
 
 	return ret;
 }
@@ -964,13 +965,13 @@
 {
 	struct floppy_state *fs = disk->private_data;
 	struct swim3 __iomem *sw = fs->swim3;
-	lock_kernel();
+	mutex_lock(&swim3_mutex);
 	if (fs->ref_count > 0 && --fs->ref_count == 0) {
 		swim3_action(fs, MOTOR_OFF);
 		out_8(&sw->control_bic, 0xff);
 		swim3_select(fs, RELAX);
 	}
-	unlock_kernel();
+	mutex_unlock(&swim3_mutex);
 	return 0;
 }
 
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index c48e148..9ae3bb7 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -28,7 +28,7 @@
 #include <linux/timer.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <scsi/scsi.h>
 
 #define DRV_NAME "ub"
@@ -248,6 +248,7 @@
 	spinlock_t lock;
 };
 
+static DEFINE_MUTEX(ub_mutex);
 static inline void ub_init_completion(struct ub_completion *x)
 {
 	x->done = 0;
@@ -396,7 +397,7 @@
 #else
 
 static const struct usb_device_id ub_usb_ids[] = {
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) },
 	{ }
 };
 
@@ -1715,9 +1716,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ub_mutex);
 	ret = ub_bd_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&ub_mutex);
 
 	return ret;
 }
@@ -1730,9 +1731,9 @@
 	struct ub_lun *lun = disk->private_data;
 	struct ub_dev *sc = lun->udev;
 
-	lock_kernel();
+	mutex_lock(&ub_mutex);
 	ub_put(sc);
-	unlock_kernel();
+	mutex_unlock(&ub_mutex);
 
 	return 0;
 }
@@ -1747,9 +1748,9 @@
 	void __user *usermem = (void __user *) arg;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ub_mutex);
 	ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem);
-	unlock_kernel();
+	mutex_unlock(&ub_mutex);
 
 	return ret;
 }
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index f651e51..e2ff697 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -41,7 +41,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/dma-mapping.h>
 #include <linux/completion.h>
 #include <linux/device.h>
@@ -73,6 +73,7 @@
 	MAX_DISK_NAME = FIELD_SIZEOF(struct gendisk, disk_name)
 };
 
+static DEFINE_MUTEX(viodasd_mutex);
 static DEFINE_SPINLOCK(viodasd_spinlock);
 
 #define VIOMAXREQ		16
@@ -180,9 +181,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&viodasd_mutex);
 	ret = viodasd_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&viodasd_mutex);
 
 	return ret;
 }
@@ -196,7 +197,7 @@
 	struct viodasd_device *d = disk->private_data;
 	HvLpEvent_Rc hvrc;
 
-	lock_kernel();
+	mutex_lock(&viodasd_mutex);
 	/* Send the event to OS/400.  We DON'T expect a response */
 	hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
 			HvLpEvent_Type_VirtualIo,
@@ -210,7 +211,7 @@
 	if (hvrc != 0)
 		pr_warning("HV close call failed %d\n", (int)hvrc);
 
-	unlock_kernel();
+	mutex_unlock(&viodasd_mutex);
 
 	return 0;
 }
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 2aafafc..6ecf89c 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -2,7 +2,6 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
 #include <linux/hdreg.h>
 #include <linux/virtio.h>
 #include <linux/virtio_blk.h>
@@ -128,9 +127,6 @@
 		}
 	}
 
-	if (vbr->req->cmd_flags & REQ_HARDBARRIER)
-		vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER;
-
 	sg_set_buf(&vblk->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr));
 
 	/*
@@ -202,6 +198,7 @@
 	struct virtio_blk *vblk = disk->private_data;
 	struct request *req;
 	struct bio *bio;
+	int err;
 
 	bio = bio_map_kern(vblk->disk->queue, id_str, VIRTIO_BLK_ID_BYTES,
 			   GFP_KERNEL);
@@ -215,11 +212,14 @@
 	}
 
 	req->cmd_type = REQ_TYPE_SPECIAL;
-	return blk_execute_rq(vblk->disk->queue, vblk->disk, req, false);
+	err = blk_execute_rq(vblk->disk->queue, vblk->disk, req, false);
+	blk_put_request(req);
+
+	return err;
 }
 
-static int virtblk_locked_ioctl(struct block_device *bdev, fmode_t mode,
-			 unsigned cmd, unsigned long data)
+static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
+			     unsigned int cmd, unsigned long data)
 {
 	struct gendisk *disk = bdev->bd_disk;
 	struct virtio_blk *vblk = disk->private_data;
@@ -234,18 +234,6 @@
 			      (void __user *)data);
 }
 
-static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
-			     unsigned int cmd, unsigned long param)
-{
-	int ret;
-
-	lock_kernel();
-	ret = virtblk_locked_ioctl(bdev, mode, cmd, param);
-	unlock_kernel();
-
-	return ret;
-}
-
 /* We provide getgeo only to please some old bootloader/partitioning tools */
 static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
 {
@@ -388,31 +376,9 @@
 	vblk->disk->driverfs_dev = &vdev->dev;
 	index++;
 
-	if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) {
-		/*
-		 * If the FLUSH feature is supported we do have support for
-		 * flushing a volatile write cache on the host.  Use that
-		 * to implement write barrier support.
-		 */
-		blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH);
-	} else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) {
-		/*
-		 * If the BARRIER feature is supported the host expects us
-		 * to order request by tags.  This implies there is not
-		 * volatile write cache on the host, and that the host
-		 * never re-orders outstanding I/O.  This feature is not
-		 * useful for real life scenarious and deprecated.
-		 */
-		blk_queue_ordered(q, QUEUE_ORDERED_TAG);
-	} else {
-		/*
-		 * If the FLUSH feature is not supported we must assume that
-		 * the host does not perform any kind of volatile write
-		 * caching. We still need to drain the queue to provider
-		 * proper barrier semantics.
-		 */
-		blk_queue_ordered(q, QUEUE_ORDERED_DRAIN);
-	}
+	/* configure queue flush support */
+	if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH))
+		blk_queue_flush(q, REQ_FLUSH);
 
 	/* If disk is read-only in the host, the guest should obey */
 	if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
@@ -531,9 +497,9 @@
 };
 
 static unsigned int features[] = {
-	VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
-	VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
-	VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY
+	VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
+	VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI,
+	VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY
 };
 
 /*
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index d5a3cd7..4abd2bc 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -46,7 +46,7 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/blkpg.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -58,6 +58,7 @@
 
 #include "xd.h"
 
+static DEFINE_MUTEX(xd_mutex);
 static void __init do_xd_setup (int *integers);
 #ifdef MODULE
 static int xd[5] = { -1,-1,-1,-1, };
@@ -381,9 +382,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&xd_mutex);
 	ret = xd_locked_ioctl(bdev, mode, cmd, param);
-	unlock_kernel();
+	mutex_unlock(&xd_mutex);
 
 	return ret;
 }
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index ab735a6..4b33a18 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -41,7 +41,7 @@
 #include <linux/cdrom.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/scatterlist.h>
 
 #include <xen/xen.h>
@@ -69,6 +69,7 @@
 	unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
 
+static DEFINE_MUTEX(blkfront_mutex);
 static const struct block_device_operations xlvbd_block_fops;
 
 #define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
@@ -95,7 +96,7 @@
 	struct gnttab_free_callback callback;
 	struct blk_shadow shadow[BLK_RING_SIZE];
 	unsigned long shadow_free;
-	int feature_barrier;
+	unsigned int feature_flush;
 	int is_ready;
 };
 
@@ -418,26 +419,12 @@
 }
 
 
-static int xlvbd_barrier(struct blkfront_info *info)
+static void xlvbd_flush(struct blkfront_info *info)
 {
-	int err;
-	const char *barrier;
-
-	switch (info->feature_barrier) {
-	case QUEUE_ORDERED_DRAIN:	barrier = "enabled (drain)"; break;
-	case QUEUE_ORDERED_TAG:		barrier = "enabled (tag)"; break;
-	case QUEUE_ORDERED_NONE:	barrier = "disabled"; break;
-	default:			return -EINVAL;
-	}
-
-	err = blk_queue_ordered(info->rq, info->feature_barrier);
-
-	if (err)
-		return err;
-
+	blk_queue_flush(info->rq, info->feature_flush);
 	printk(KERN_INFO "blkfront: %s: barriers %s\n",
-	       info->gd->disk_name, barrier);
-	return 0;
+	       info->gd->disk_name,
+	       info->feature_flush ? "enabled" : "disabled");
 }
 
 
@@ -516,7 +503,7 @@
 	info->rq = gd->queue;
 	info->gd = gd;
 
-	xlvbd_barrier(info);
+	xlvbd_flush(info);
 
 	if (vdisk_info & VDISK_READONLY)
 		set_disk_ro(gd, 1);
@@ -662,8 +649,8 @@
 				printk(KERN_WARNING "blkfront: %s: write barrier op failed\n",
 				       info->gd->disk_name);
 				error = -EOPNOTSUPP;
-				info->feature_barrier = QUEUE_ORDERED_NONE;
-				xlvbd_barrier(info);
+				info->feature_flush = 0;
+				xlvbd_flush(info);
 			}
 			/* fall through */
 		case BLKIF_OP_READ:
@@ -1076,20 +1063,20 @@
 	/*
 	 * If there's no "feature-barrier" defined, then it means
 	 * we're dealing with a very old backend which writes
-	 * synchronously; draining will do what needs to get done.
+	 * synchronously; nothing to do.
 	 *
-	 * If there are barriers, then we can do full queued writes
-	 * with tagged barriers.
-	 *
-	 * If barriers are not supported, then there's no much we can
-	 * do, so just set ordering to NONE.
+	 * If there are barriers, then we use flush.
 	 */
-	if (err)
-		info->feature_barrier = QUEUE_ORDERED_DRAIN;
-	else if (barrier)
-		info->feature_barrier = QUEUE_ORDERED_TAG;
-	else
-		info->feature_barrier = QUEUE_ORDERED_NONE;
+	info->feature_flush = 0;
+
+	/*
+	 * The driver doesn't properly handled empty flushes, so
+	 * lets disable barrier support for now.
+	 */
+#if 0
+	if (!err && barrier)
+		info->feature_flush = REQ_FLUSH;
+#endif
 
 	err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
 	if (err) {
@@ -1201,7 +1188,7 @@
 	struct blkfront_info *info;
 	int err = 0;
 
-	lock_kernel();
+	mutex_lock(&blkfront_mutex);
 
 	info = disk->private_data;
 	if (!info) {
@@ -1219,7 +1206,7 @@
 	mutex_unlock(&info->mutex);
 
 out:
-	unlock_kernel();
+	mutex_unlock(&blkfront_mutex);
 	return err;
 }
 
@@ -1229,7 +1216,7 @@
 	struct block_device *bdev;
 	struct xenbus_device *xbdev;
 
-	lock_kernel();
+	mutex_lock(&blkfront_mutex);
 
 	bdev = bdget_disk(disk, 0);
 	bdput(bdev);
@@ -1263,7 +1250,7 @@
 	}
 
 out:
-	unlock_kernel();
+	mutex_unlock(&blkfront_mutex);
 	return 0;
 }
 
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 057413b..6e968cd 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -89,7 +89,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/ata.h>
 #include <linux/hdreg.h>
 #include <linux/platform_device.h>
@@ -214,6 +214,7 @@
 	u16 cf_id[ATA_ID_WORDS];
 };
 
+static DEFINE_MUTEX(xsysace_mutex);
 static int ace_major;
 
 /* ---------------------------------------------------------------------
@@ -903,13 +904,13 @@
 
 	dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1);
 
-	lock_kernel();
+	mutex_lock(&xsysace_mutex);
 	spin_lock_irqsave(&ace->lock, flags);
 	ace->users++;
 	spin_unlock_irqrestore(&ace->lock, flags);
 
 	check_disk_change(bdev);
-	unlock_kernel();
+	mutex_unlock(&xsysace_mutex);
 
 	return 0;
 }
@@ -922,7 +923,7 @@
 
 	dev_dbg(ace->dev, "ace_release() users=%i\n", ace->users - 1);
 
-	lock_kernel();
+	mutex_lock(&xsysace_mutex);
 	spin_lock_irqsave(&ace->lock, flags);
 	ace->users--;
 	if (ace->users == 0) {
@@ -930,7 +931,7 @@
 		ace_out(ace, ACE_CTRL, val & ~ACE_CTRL_LOCKREQ);
 	}
 	spin_unlock_irqrestore(&ace->lock, flags);
-	unlock_kernel();
+	mutex_unlock(&xsysace_mutex);
 	return 0;
 }
 
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index d75b2bb..dcd4cfc 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -33,7 +33,7 @@
 #include <linux/module.h>
 #include <linux/blkdev.h>
 #include <linux/bitops.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #include <asm/setup.h>
@@ -57,6 +57,7 @@
 
 #define Z2RAM_CHUNK1024       ( Z2RAM_CHUNKSIZE >> 10 )
 
+static DEFINE_MUTEX(z2ram_mutex);
 static u_long *z2ram_map    = NULL;
 static u_long z2ram_size    = 0;
 static int z2_count         = 0;
@@ -154,7 +155,7 @@
 
     device = MINOR(bdev->bd_dev);
 
-    lock_kernel();
+    mutex_lock(&z2ram_mutex);
     if ( current_device != -1 && current_device != device )
     {
 	rc = -EBUSY;
@@ -296,25 +297,25 @@
 	set_capacity(z2ram_gendisk, z2ram_size >> 9);
     }
 
-    unlock_kernel();
+    mutex_unlock(&z2ram_mutex);
     return 0;
 
 err_out_kfree:
     kfree(z2ram_map);
 err_out:
-    unlock_kernel();
+    mutex_unlock(&z2ram_mutex);
     return rc;
 }
 
 static int
 z2_release(struct gendisk *disk, fmode_t mode)
 {
-    lock_kernel();
+    mutex_lock(&z2ram_mutex);
     if ( current_device == -1 ) {
-    	unlock_kernel();
+    	mutex_unlock(&z2ram_mutex);
     	return 0;
     }
-    unlock_kernel();
+    mutex_unlock(&z2ram_mutex);
     /*
      * FIXME: unmap memory
      */
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index d52e90a5..4104b7f 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -39,7 +39,6 @@
 #include <linux/skbuff.h>
 #include <linux/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -865,8 +864,7 @@
 	info->p_dev = link;
 	link->priv = info;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
+	link->config_flags |= CONF_ENABLE_IRQ;
 
 	return bluecard_config(link);
 }
@@ -886,7 +884,7 @@
 	bluecard_info_t *info = link->priv;
 	int i, n;
 
-	link->conf.ConfigIndex = 0x20;
+	link->config_index = 0x20;
 
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 	link->resource[0]->end = 64;
@@ -906,7 +904,7 @@
 	if (i != 0)
 		goto failed;
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		goto failed;
 
@@ -942,9 +940,7 @@
 
 static struct pcmcia_driver bluecard_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "bluecard_cs",
-	},
+	.name		= "bluecard_cs",
 	.probe		= bluecard_probe,
 	.remove		= bluecard_detach,
 	.id_table	= bluecard_ids,
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 7ab8f29..0c8a655 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -45,7 +45,6 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -657,11 +656,8 @@
 	info->p_dev = link;
 	link->priv = info;
 
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	link->resource[0]->end = 8;
-
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+		CONF_AUTO_SET_IO;
 
 	return bt3c_config(link);
 }
@@ -675,43 +671,41 @@
 	kfree(info);
 }
 
-static int bt3c_check_config(struct pcmcia_device *p_dev,
-			     cistpl_cftable_entry_t *cf,
-			     cistpl_cftable_entry_t *dflt,
-			     unsigned int vcc,
-			     void *priv_data)
+static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
 {
-	unsigned long try = (unsigned long) priv_data;
+	int *try = priv_data;
 
-	p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+	if (try == 0)
+		p_dev->io_lines = 16;
 
-	if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
-	    (cf->io.win[0].base != 0)) {
-		p_dev->resource[0]->start = cf->io.win[0].base;
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -ENODEV;
+	if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
+		return -EINVAL;
+
+	p_dev->resource[0]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
-				      cistpl_cftable_entry_t *cf,
-				      cistpl_cftable_entry_t *dflt,
-				      unsigned int vcc,
 				      void *priv_data)
 {
 	static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
 	int j;
 
-	if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-		for (j = 0; j < 5; j++) {
-			p_dev->resource[0]->start = base[j];
-			p_dev->io_lines = base[j] ? 16 : 3;
-			if (!pcmcia_request_io(p_dev))
-				return 0;
-		}
+	if (p_dev->io_lines > 3)
+		return -ENODEV;
+
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[0]->end = 8;
+
+	for (j = 0; j < 5; j++) {
+		p_dev->resource[0]->start = base[j];
+		p_dev->io_lines = base[j] ? 16 : 3;
+		if (!pcmcia_request_io(p_dev))
+			return 0;
 	}
 	return -ENODEV;
 }
@@ -742,7 +736,7 @@
 	if (i != 0)
 		goto failed;
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		goto failed;
 
@@ -775,9 +769,7 @@
 
 static struct pcmcia_driver bt3c_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "bt3c_cs",
-	},
+	.name		= "bt3c_cs",
 	.probe		= bt3c_probe,
 	.remove		= bt3c_detach,
 	.id_table	= bt3c_ids,
diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c
index 54739b0..fd6305b 100644
--- a/drivers/bluetooth/btmrvl_debugfs.c
+++ b/drivers/bluetooth/btmrvl_debugfs.c
@@ -92,6 +92,7 @@
 	.read	= btmrvl_hscfgcmd_read,
 	.write	= btmrvl_hscfgcmd_write,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf,
@@ -130,6 +131,7 @@
 	.read	= btmrvl_psmode_read,
 	.write	= btmrvl_psmode_write,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
@@ -173,6 +175,7 @@
 	.read = btmrvl_pscmd_read,
 	.write = btmrvl_pscmd_write,
 	.open = btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf,
@@ -211,6 +214,7 @@
 	.read	= btmrvl_gpiogap_read,
 	.write	= btmrvl_gpiogap_write,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
@@ -252,6 +256,7 @@
 	.read	= btmrvl_hscmd_read,
 	.write	= btmrvl_hscmd_write,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf,
@@ -289,6 +294,7 @@
 	.read	= btmrvl_hsmode_read,
 	.write	= btmrvl_hsmode_write,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf,
@@ -306,6 +312,7 @@
 static const struct file_operations btmrvl_curpsmode_fops = {
 	.read	= btmrvl_curpsmode_read,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf,
@@ -323,6 +330,7 @@
 static const struct file_operations btmrvl_psstate_fops = {
 	.read	= btmrvl_psstate_read,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf,
@@ -340,6 +348,7 @@
 static const struct file_operations btmrvl_hsstate_fops = {
 	.read	= btmrvl_hsstate_read,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf,
@@ -358,6 +367,7 @@
 static const struct file_operations btmrvl_txdnldready_fops = {
 	.read	= btmrvl_txdnldready_read,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 void btmrvl_debugfs_init(struct hci_dev *hdev)
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 0d32ec8..548d1d9 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -117,8 +117,8 @@
 				(event->data[2] == MODULE_ALREADY_UP)) ?
 				"Bring-up succeed" : "Bring-up failed");
 
-			if (event->length > 3)
-				priv->btmrvl_dev.dev_type = event->data[3];
+			if (event->length > 3 && event->data[3])
+				priv->btmrvl_dev.dev_type = HCI_AMP;
 			else
 				priv->btmrvl_dev.dev_type = HCI_BREDR;
 
diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
index 76e5127..792e32d 100644
--- a/drivers/bluetooth/btsdio.c
+++ b/drivers/bluetooth/btsdio.c
@@ -46,6 +46,9 @@
 	/* Generic Bluetooth Type-B SDIO device */
 	{ SDIO_DEVICE_CLASS(SDIO_CLASS_BT_B) },
 
+	/* Generic Bluetooth AMP controller */
+	{ SDIO_DEVICE_CLASS(SDIO_CLASS_BT_AMP) },
+
 	{ }	/* Terminating entry */
 };
 
@@ -329,6 +332,11 @@
 	hdev->bus = HCI_SDIO;
 	hdev->driver_data = data;
 
+	if (id->class == SDIO_CLASS_BT_AMP)
+		hdev->dev_type = HCI_AMP;
+	else
+		hdev->dev_type = HCI_BREDR;
+
 	data->hdev = hdev;
 
 	SET_HCIDEV_DEV(hdev, &func->dev);
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 1c4f5e8..f8a0708 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -41,7 +41,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -586,11 +585,8 @@
 	info->p_dev = link;
 	link->priv = info;
 
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	link->resource[0]->end = 8;
-
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+		CONF_AUTO_SET_IO;
 
 	return btuart_config(link);
 }
@@ -604,43 +600,41 @@
 	kfree(info);
 }
 
-static int btuart_check_config(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cf,
-			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
-			       void *priv_data)
+static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int *try = priv_data;
 
-	p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+	if (try == 0)
+		p_dev->io_lines = 16;
 
-	if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
-	    (cf->io.win[0].base != 0)) {
-		p_dev->resource[0]->start = cf->io.win[0].base;
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -ENODEV;
+	if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
+		return -EINVAL;
+
+	p_dev->resource[0]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
-					cistpl_cftable_entry_t *cf,
-					cistpl_cftable_entry_t *dflt,
-					unsigned int vcc,
 					void *priv_data)
 {
 	static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
 	int j;
 
-	if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-		for (j = 0; j < 5; j++) {
-			p_dev->resource[0]->start = base[j];
-			p_dev->io_lines = base[j] ? 16 : 3;
-			if (!pcmcia_request_io(p_dev))
-				return 0;
-		}
+	if (p_dev->io_lines > 3)
+		return -ENODEV;
+
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[0]->end = 8;
+
+	for (j = 0; j < 5; j++) {
+		p_dev->resource[0]->start = base[j];
+		p_dev->io_lines = base[j] ? 16 : 3;
+		if (!pcmcia_request_io(p_dev))
+			return 0;
 	}
 	return -ENODEV;
 }
@@ -671,7 +665,7 @@
 	if (i != 0)
 		goto failed;
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		goto failed;
 
@@ -703,9 +697,7 @@
 
 static struct pcmcia_driver btuart_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "btuart_cs",
-	},
+	.name		= "btuart_cs",
 	.probe		= btuart_probe,
 	.remove		= btuart_detach,
 	.id_table	= btuart_ids,
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index d22ce3c..d120a5c 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -59,9 +59,15 @@
 	/* Generic Bluetooth USB device */
 	{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
 
+	/* Apple MacBookPro 7,1 */
+	{ USB_DEVICE(0x05ac, 0x8213) },
+
 	/* Apple iMac11,1 */
 	{ USB_DEVICE(0x05ac, 0x8215) },
 
+	/* Apple MacBookPro6,2 */
+	{ USB_DEVICE(0x05ac, 0x8218) },
+
 	/* AVM BlueFRITZ! USB v2.0 */
 	{ USB_DEVICE(0x057c, 0x3800) },
 
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index db7c8db..26ee0cf 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -41,7 +41,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -572,11 +571,7 @@
 	info->p_dev = link;
 	link->priv = info;
 
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	link->resource[0]->end = 8;
-
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
 	return dtl1_config(link);
 }
@@ -591,18 +586,14 @@
 	kfree(info);
 }
 
-static int dtl1_confcheck(struct pcmcia_device *p_dev,
-			  cistpl_cftable_entry_t *cf,
-			  cistpl_cftable_entry_t *dflt,
-			  unsigned int vcc,
-			  void *priv_data)
+static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8))
+	if ((p_dev->resource[1]->end) || (p_dev->resource[1]->end < 8))
 		return -ENODEV;
 
-	p_dev->resource[0]->start = cf->io.win[0].base;
-	p_dev->resource[0]->end = cf->io.win[0].len;	/*yo */
-	p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
 	return pcmcia_request_io(p_dev);
 }
 
@@ -620,7 +611,7 @@
 	if (i != 0)
 		goto failed;
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		goto failed;
 
@@ -656,9 +647,7 @@
 
 static struct pcmcia_driver dtl1_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "dtl1_cs",
-	},
+	.name		= "dtl1_cs",
 	.probe		= dtl1_probe,
 	.remove		= dtl1_detach,
 	.id_table	= dtl1_ids,
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 998833d..7201482 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -101,7 +101,7 @@
 		break;
 
 	case HCI_SCODATA_PKT:
-		hdev->stat.cmd_tx++;
+		hdev->stat.sco_tx++;
 		break;
 	}
 }
@@ -256,9 +256,16 @@
 
 	BT_DBG("tty %p", tty);
 
+	/* FIXME: This btw is bogus, nothing requires the old ldisc to clear
+	   the pointer */
 	if (hu)
 		return -EEXIST;
 
+	/* Error if the tty has no write op instead of leaving an exploitable
+	   hole */
+	if (tty->ops->write == NULL)
+		return -EOPNOTSUPP;
+
 	if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
 		BT_ERR("Can't allocate control structure");
 		return -ENFILE;
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 3aa7b2a..67c180c 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -282,6 +282,7 @@
 	.poll		= vhci_poll,
 	.open		= vhci_open,
 	.release	= vhci_release,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice vhci_miscdev= {
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 261107d..3af6516 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -34,7 +34,7 @@
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <linux/platform_device.h>
@@ -81,6 +81,7 @@
 
 #define GDROM_DEFAULT_TIMEOUT	(HZ * 7)
 
+static DEFINE_MUTEX(gdrom_mutex);
 static const struct {
 	int sense_key;
 	const char * const text;
@@ -494,17 +495,17 @@
 static int gdrom_bdops_open(struct block_device *bdev, fmode_t mode)
 {
 	int ret;
-	lock_kernel();
+	mutex_lock(&gdrom_mutex);
 	ret = cdrom_open(gd.cd_info, bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&gdrom_mutex);
 	return ret;
 }
 
 static int gdrom_bdops_release(struct gendisk *disk, fmode_t mode)
 {
-	lock_kernel();
+	mutex_lock(&gdrom_mutex);
 	cdrom_release(gd.cd_info, mode);
-	unlock_kernel();
+	mutex_unlock(&gdrom_mutex);
 	return 0;
 }
 
@@ -518,9 +519,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&gdrom_mutex);
 	ret = cdrom_ioctl(gd.cd_info, bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&gdrom_mutex);
 
 	return ret;
 }
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 56bf9f4..be73a9b 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -42,7 +42,7 @@
 #include <linux/module.h>
 #include <linux/completion.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/seq_file.h>
 #include <linux/scatterlist.h>
 
@@ -61,6 +61,7 @@
  */
 #define VIOCD_MAX_CD	HVMAXARCHITECTEDVIRTUALCDROMS
 
+static DEFINE_MUTEX(viocd_mutex);
 static const struct vio_error_entry viocd_err_table[] = {
 	{0x0201, EINVAL, "Invalid Range"},
 	{0x0202, EINVAL, "Invalid Token"},
@@ -156,9 +157,9 @@
 	struct disk_info *di = bdev->bd_disk->private_data;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&viocd_mutex);
 	ret = cdrom_open(&di->viocd_info, bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&viocd_mutex);
 
 	return ret;
 }
@@ -166,9 +167,9 @@
 static int viocd_blk_release(struct gendisk *disk, fmode_t mode)
 {
 	struct disk_info *di = disk->private_data;
-	lock_kernel();
+	mutex_lock(&viocd_mutex);
 	cdrom_release(&di->viocd_info, mode);
-	unlock_kernel();
+	mutex_unlock(&viocd_mutex);
 	return 0;
 }
 
@@ -178,9 +179,9 @@
 	struct disk_info *di = bdev->bd_disk->private_data;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&viocd_mutex);
 	ret = cdrom_ioctl(&di->viocd_info, bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&viocd_mutex);
 
 	return ret;
 }
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3d44ec7..43d3395 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -493,6 +493,21 @@
 	  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 EMBEDDED
+	default n
+	---help---
+	  If you say Y here, the support for writing user messages (i.e.
+	  console messages) via printk is available.
+
+	  The feature is useful to inline user messages with kernel
+	  messages.
+	  In order to use this feature, you should output user messages
+	  to /dev/ttyprintk or redirect console to this TTY.
+
+	  If unsure, say N.
+
 config BRIQ_PANEL
 	tristate 'Total Impact briQ front panel driver'
 	depends on PPC_CHRP
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index dc96416..3a9c014 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -12,6 +12,7 @@
 obj-y				+= tty_mutex.o
 obj-$(CONFIG_LEGACY_PTYS)	+= pty.o
 obj-$(CONFIG_UNIX98_PTYS)	+= pty.o
+obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
 obj-y				+= misc.o
 obj-$(CONFIG_VT)		+= vt_ioctl.o vc_screen.o selection.o keyboard.o
 obj-$(CONFIG_BFIN_JTAG_COMM)	+= bfin_jtag_comm.o
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 4b66c69..5ddf67e 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -57,7 +57,7 @@
 
 config AGP_AMD64
 	tristate "AMD Opteron/Athlon64 on-CPU GART support"
-	depends on AGP && X86 && K8_NB
+	depends on AGP && X86 && AMD_NB
 	help
 	  This option gives you AGP support for the GLX component of
 	  X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 70312da..42396df 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -15,7 +15,7 @@
 #include <linux/mmzone.h>
 #include <asm/page.h>		/* PAGE_SIZE */
 #include <asm/e820.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 #include <asm/gart.h>
 #include "agp.h"
 
@@ -124,7 +124,7 @@
 	u32 temp;
 	struct aper_size_info_32 *values;
 
-	dev = k8_northbridges[0];
+	dev = k8_northbridges.nb_misc[0];
 	if (dev==NULL)
 		return 0;
 
@@ -181,10 +181,14 @@
 	unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
 	int i;
 
+	if (!k8_northbridges.gart_supported)
+		return 0;
+
 	/* Configure AGP regs in each x86-64 host bridge. */
-        for (i = 0; i < num_k8_northbridges; i++) {
+	for (i = 0; i < k8_northbridges.num; i++) {
 		agp_bridge->gart_bus_addr =
-				amd64_configure(k8_northbridges[i], gatt_bus);
+				amd64_configure(k8_northbridges.nb_misc[i],
+						gatt_bus);
 	}
 	k8_flush_garts();
 	return 0;
@@ -195,11 +199,15 @@
 {
 	u32 tmp;
 	int i;
-        for (i = 0; i < num_k8_northbridges; i++) {
-		struct pci_dev *dev = k8_northbridges[i];
+
+	if (!k8_northbridges.gart_supported)
+		return;
+
+	for (i = 0; i < k8_northbridges.num; i++) {
+		struct pci_dev *dev = k8_northbridges.nb_misc[i];
 		/* disable gart translation */
 		pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp);
-		tmp &= ~AMD64_GARTEN;
+		tmp &= ~GARTEN;
 		pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, tmp);
 	}
 }
@@ -313,22 +321,25 @@
 	if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order))
 		return -1;
 
-	pci_write_config_dword(nb, AMD64_GARTAPERTURECTL, order << 1);
+	gart_set_size_and_enable(nb, order);
 	pci_write_config_dword(nb, AMD64_GARTAPERTUREBASE, aper >> 25);
 
 	return 0;
 }
 
-static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
+static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr)
 {
 	int i;
 
 	if (cache_k8_northbridges() < 0)
 		return -ENODEV;
 
+	if (!k8_northbridges.gart_supported)
+		return -ENODEV;
+
 	i = 0;
-	for (i = 0; i < num_k8_northbridges; i++) {
-		struct pci_dev *dev = k8_northbridges[i];
+	for (i = 0; i < k8_northbridges.num; i++) {
+		struct pci_dev *dev = k8_northbridges.nb_misc[i];
 		if (fix_northbridge(dev, pdev, cap_ptr) < 0) {
 			dev_err(&dev->dev, "no usable aperture found\n");
 #ifdef __x86_64__
@@ -405,7 +416,8 @@
 	}
 
 	/* shadow x86-64 registers into ULi registers */
-	pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea);
+	pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE,
+			       &httfea);
 
 	/* if x86-64 aperture base is beyond 4G, exit here */
 	if ((httfea & 0x7fff) >> (32 - 25)) {
@@ -472,7 +484,8 @@
 	pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp);
 
 	/* shadow x86-64 registers into NVIDIA registers */
-	pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase);
+	pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE,
+			       &apbase);
 
 	/* if x86-64 aperture base is beyond 4G, exit here */
 	if ( (apbase & 0x7fff) >> (32 - 25) ) {
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index d2abf51..64255ce 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -984,7 +984,9 @@
 
 	bridge->driver->cache_flush();
 #ifdef CONFIG_X86
-	set_memory_uc((unsigned long)table, 1 << page_order);
+	if (set_memory_uc((unsigned long)table, 1 << page_order))
+		printk(KERN_WARNING "Could not set GATT table memory to UC!");
+
 	bridge->gatt_table = (void *)table;
 #else
 	bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index a11c8c9..b0a7046 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1263,6 +1263,36 @@
 	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)
@@ -1332,31 +1362,6 @@
 			}
 			/* NOTREACHED */
 
-		/* 
-		 * 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.
-		 */
-		case TIOCGICOUNT:
-			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;
-
-			if (copy_to_user(argp, &icount, sizeof(icount)))
-				return -EFAULT;
-			return 0;
 		case TIOCSERGWILD:
 		case TIOCSERSWILD:
 			/* "setserial -W" is called in Debian boot */
@@ -1958,6 +1963,7 @@
 	.wait_until_sent = rs_wait_until_sent,
 	.tiocmget = rs_tiocmget,
 	.tiocmset = rs_tiocmset,
+	.get_icount = rs_get_icount,
 	.proc_fops = &rs_proc_fops,
 };
 
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index 033e150..3022801 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -13,7 +13,7 @@
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/miscdevice.h>
@@ -126,6 +126,7 @@
 /*
  * Local variables
  */
+static DEFINE_MUTEX(apm_mutex);
 static atomic_t suspend_acks_pending = ATOMIC_INIT(0);
 static atomic_t userspace_notification_inhibit = ATOMIC_INIT(0);
 static int apm_disabled;
@@ -274,7 +275,7 @@
 	if (!as->suser || !as->writer)
 		return -EPERM;
 
-	lock_kernel();
+	mutex_lock(&apm_mutex);
 	switch (cmd) {
 	case APM_IOC_SUSPEND:
 		mutex_lock(&state_lock);
@@ -335,7 +336,7 @@
 		mutex_unlock(&state_lock);
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&apm_mutex);
 
 	return err;
 }
@@ -370,7 +371,7 @@
 {
 	struct apm_user *as;
 
-	lock_kernel();
+	mutex_lock(&apm_mutex);
 	as = kzalloc(sizeof(*as), GFP_KERNEL);
 	if (as) {
 		/*
@@ -390,7 +391,7 @@
 
 		filp->private_data = as;
 	}
-	unlock_kernel();
+	mutex_unlock(&apm_mutex);
 
 	return as ? 0 : -ENOMEM;
 }
@@ -402,6 +403,7 @@
 	.unlocked_ioctl	= apm_ioctl,
 	.open		= apm_open,
 	.release	= apm_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice apm_device = {
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index f4ae0e0..e7ba774 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -26,7 +26,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/miscdevice.h>
 #include <linux/pci.h>
 #include <linux/wait.h>
@@ -60,6 +60,7 @@
 #define PCI_DEVICE_ID_APPLICOM_PCI2000PFB     0x0003
 #endif
 
+static DEFINE_MUTEX(ac_mutex);
 static char *applicom_pci_devnames[] = {
 	"PCI board",
 	"PCI2000IBS / PCI2000CAN",
@@ -707,7 +708,7 @@
 	if (IS_ERR(adgl))
 		return PTR_ERR(adgl);
 
-	lock_kernel();	
+	mutex_lock(&ac_mutex);	
 	IndexCard = adgl->num_card-1;
 	 
 	if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
@@ -717,7 +718,7 @@
 			warncount--;
 		}
 		kfree(adgl);
-		unlock_kernel();
+		mutex_unlock(&ac_mutex);
 		return -EINVAL;
 	}
 
@@ -835,7 +836,7 @@
 	}
 	Dummy = readb(apbs[IndexCard].RamIO + VERS);
 	kfree(adgl);
-	unlock_kernel();
+	mutex_unlock(&ac_mutex);
 	return 0;
 }
 
diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c
index 836d4f0..44660f1 100644
--- a/drivers/char/bfin-otp.c
+++ b/drivers/char/bfin-otp.c
@@ -222,6 +222,7 @@
 	.unlocked_ioctl = bfin_otp_ioctl,
 	.read           = bfin_otp_read,
 	.write          = bfin_otp_write,
+	.llseek		= default_llseek,
 };
 
 static struct miscdevice bfin_otp_misc_device = {
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index d5fa113..f6718f0 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -186,6 +186,7 @@
 	.write		= briq_panel_write,
 	.open		= briq_panel_open,
 	.release	= briq_panel_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice briq_panel_miscdev = {
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 9191713..a4a6c2f 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -155,6 +155,7 @@
 	.owner = THIS_MODULE,
 	.mmap  = bsr_mmap,
 	.open  = bsr_open,
+	.llseek = noop_llseek,
 };
 
 static void bsr_cleanup_devs(void)
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
index 4d830dc..0cf1e5f 100644
--- a/drivers/char/cs5535_gpio.c
+++ b/drivers/char/cs5535_gpio.c
@@ -169,7 +169,8 @@
 	.owner	= THIS_MODULE,
 	.write	= cs5535_gpio_write,
 	.read	= cs5535_gpio_read,
-	.open	= cs5535_gpio_open
+	.open	= cs5535_gpio_open,
+	.llseek = no_llseek,
 };
 
 static int __init cs5535_gpio_init(void)
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 27aad94..4f152c2 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2790,29 +2790,6 @@
 		 * NB: both 1->0 and 0->1 transitions are counted except for
 		 *     RI where only 0->1 is counted.
 		 */
-	case TIOCGICOUNT: {
-		struct serial_icounter_struct sic = { };
-
-		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;
-
-		if (copy_to_user(argp, &sic, sizeof(sic)))
-			ret_val = -EFAULT;
-		break;
-	}
 	default:
 		ret_val = -ENOIOCTLCMD;
 	}
@@ -2823,6 +2800,31 @@
 	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
@@ -4084,6 +4086,7 @@
 	.wait_until_sent = cy_wait_until_sent,
 	.tiocmget = cy_tiocmget,
 	.tiocmset = cy_tiocmset,
+	.get_icount = cy_get_icount,
 	.proc_fops = &cyclades_proc_fops,
 };
 
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c
index 170693c..ed8303f9 100644
--- a/drivers/char/ds1302.c
+++ b/drivers/char/ds1302.c
@@ -20,7 +20,7 @@
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
 #include <linux/bcd.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
@@ -32,6 +32,7 @@
 
 #define RTC_MAJOR_NR 121 /* local major, change later */
 
+static DEFINE_MUTEX(rtc_mutex);
 static const char ds1302_name[] = "ds1302";
 
 /* Send 8 bits. */
@@ -164,9 +165,9 @@
 			struct rtc_time rtc_tm;
 
 			memset(&rtc_tm, 0, sizeof (struct rtc_time));
-			lock_kernel();
+			mutex_lock(&rtc_mutex);
 			get_rtc_time(&rtc_tm);
-			unlock_kernel();
+			mutex_unlock(&rtc_mutex);
 			if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
 				return -EFAULT;
 			return 0;
@@ -218,7 +219,7 @@
 			mon = bin2bcd(mon);
 			yrs = bin2bcd(yrs);
 
-			lock_kernel();
+			mutex_lock(&rtc_mutex);
 			local_irq_save(flags);
 			CMOS_WRITE(yrs, RTC_YEAR);
 			CMOS_WRITE(mon, RTC_MONTH);
@@ -227,7 +228,7 @@
 			CMOS_WRITE(min, RTC_MINUTES);
 			CMOS_WRITE(sec, RTC_SECONDS);
 			local_irq_restore(flags);
-			unlock_kernel();
+			mutex_unlock(&rtc_mutex);
 
 			/* Notice that at this point, the RTC is updated but
 			 * the kernel is still running with the old time.
@@ -247,10 +248,10 @@
 			if(copy_from_user(&tcs_val, (int*)arg, sizeof(int)))
 				return -EFAULT;
 
-			lock_kernel();
+			mutex_lock(&rtc_mutex);
 			tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F);
 			ds1302_writereg(RTC_TRICKLECHARGER, tcs_val);
-			unlock_kernel();
+			mutex_unlock(&rtc_mutex);
 			return 0;
 		}
 		default:
@@ -288,6 +289,7 @@
 static const struct file_operations rtc_fops = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= rtc_ioctl,
+	.llseek		= noop_llseek,
 };
 
 /* Probe for the chip by writing something to its RAM and try reading it back. */
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index dbee868..aab9605 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -8,7 +8,7 @@
 #include <linux/proc_fs.h>
 #include <linux/capability.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -34,6 +34,7 @@
 #define CFG_CPU			2
 #define CFG_1SHOT		1
 
+static DEFINE_MUTEX(ds1620_mutex);
 static const char *fan_state[] = { "off", "on", "on (hardwired)" };
 
 /*
@@ -210,7 +211,6 @@
 
 static int ds1620_open(struct inode *inode, struct file *file)
 {
-	cycle_kernel_lock();
 	return nonseekable_open(inode, file);
 }
 
@@ -321,9 +321,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ds1620_mutex);
 	ret = ds1620_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ds1620_mutex);
 
 	return ret;
 }
@@ -357,6 +357,7 @@
 	.open		= ds1620_open,
 	.read		= ds1620_read,
 	.unlocked_ioctl	= ds1620_unlocked_ioctl,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice ds1620_miscdev = {
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 8a1b28a..052797b 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -32,7 +32,7 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>	/* For put_user and get_user */
@@ -94,6 +94,7 @@
 	} \
 }
 
+static DEFINE_MUTEX(dsp56k_mutex);
 static struct dsp56k_device {
 	unsigned long in_use;
 	long maxio, timeout;
@@ -330,9 +331,9 @@
 			if (len > DSP56K_MAX_BINARY_LENGTH) {
 				return -EINVAL;
 			}
-			lock_kernel();
+			mutex_lock(&dsp56k_mutex);
 			r = dsp56k_upload(bin, len);
-			unlock_kernel();
+			mutex_unlock(&dsp56k_mutex);
 			if (r < 0) {
 				return r;
 			}
@@ -342,16 +343,16 @@
 		case DSP56K_SET_TX_WSIZE:
 			if (arg > 4 || arg < 1)
 				return -EINVAL;
-			lock_kernel();
+			mutex_lock(&dsp56k_mutex);
 			dsp56k.tx_wsize = (int) arg;
-			unlock_kernel();
+			mutex_unlock(&dsp56k_mutex);
 			break;
 		case DSP56K_SET_RX_WSIZE:
 			if (arg > 4 || arg < 1)
 				return -EINVAL;
-			lock_kernel();
+			mutex_lock(&dsp56k_mutex);
 			dsp56k.rx_wsize = (int) arg;
-			unlock_kernel();
+			mutex_unlock(&dsp56k_mutex);
 			break;
 		case DSP56K_HOST_FLAGS:
 		{
@@ -363,7 +364,7 @@
 			if(get_user(out, &hf->out) < 0)
 				return -EFAULT;
 
-			lock_kernel();
+			mutex_lock(&dsp56k_mutex);
 			if ((dir & 0x1) && (out & 0x1))
 				dsp56k_host_interface.icr |= DSP56K_ICR_HF0;
 			else if (dir & 0x1)
@@ -378,16 +379,16 @@
 			if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2;
 			if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4;
 			if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8;
-			unlock_kernel();
+			mutex_unlock(&dsp56k_mutex);
 			return put_user(status, &hf->status);
 		}
 		case DSP56K_HOST_CMD:
 			if (arg > 31 || arg < 0)
 				return -EINVAL;
-			lock_kernel();
+			mutex_lock(&dsp56k_mutex);
 			dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
 							     DSP56K_CVR_HC);
-			unlock_kernel();
+			mutex_unlock(&dsp56k_mutex);
 			break;
 		default:
 			return -EINVAL;
@@ -427,7 +428,7 @@
 	int dev = iminor(inode) & 0x0f;
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&dsp56k_mutex);
 	switch(dev)
 	{
 	case DSP56K_DEV_56001:
@@ -454,7 +455,7 @@
 		ret = -ENODEV;
 	}
 out:
-	unlock_kernel();
+	mutex_unlock(&dsp56k_mutex);
 	return ret;
 }
 
@@ -482,6 +483,7 @@
 	.unlocked_ioctl	= dsp56k_ioctl,
 	.open		= dsp56k_open,
 	.release	= dsp56k_release,
+	.llseek		= noop_llseek,
 };
 
 
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index e3859d4..85156dd 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -57,7 +57,7 @@
 #include <linux/ioport.h>	/* for request_region */
 #include <linux/delay.h>	/* for loops_per_jiffy */
 #include <linux/sched.h>
-#include <linux/smp_lock.h>	/* cycle_kernel_lock() */
+#include <linux/mutex.h>
 #include <asm/io.h>		/* for inb_p, outb_p, inb, outb, etc. */
 #include <asm/uaccess.h>	/* for get_user, etc. */
 #include <linux/wait.h>		/* for wait_queue */
@@ -73,6 +73,7 @@
 #define TRACE_RET ((void) 0)
 #endif				/* TRACING */
 
+static DEFINE_MUTEX(dtlk_mutex);
 static void dtlk_timer_tick(unsigned long data);
 
 static int dtlk_major;
@@ -105,6 +106,7 @@
 	.unlocked_ioctl	= dtlk_ioctl,
 	.open		= dtlk_open,
 	.release	= dtlk_release,
+	.llseek		= no_llseek,
 };
 
 /* local prototypes */
@@ -275,9 +277,9 @@
 	switch (cmd) {
 
 	case DTLK_INTERROGATE:
-		lock_kernel();
+		mutex_lock(&dtlk_mutex);
 		sp = dtlk_interrogate();
-		unlock_kernel();
+		mutex_unlock(&dtlk_mutex);
 		if (copy_to_user(argp, sp, sizeof(struct dtlk_settings)))
 			return -EINVAL;
 		return 0;
@@ -296,7 +298,6 @@
 {
 	TRACE_TEXT("(dtlk_open");
 
-	cycle_kernel_lock();
 	nonseekable_open(inode, file);
 	switch (iminor(inode)) {
 	case DTLK_MINOR:
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 82b5a88..0e941b5 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -19,7 +19,7 @@
 #include <linux/miscdevice.h>
 #include <linux/fcntl.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #ifdef CONFIG_PPC_PMAC
@@ -28,6 +28,7 @@
 
 #define NVRAM_SIZE	8192
 
+static DEFINE_MUTEX(nvram_mutex);
 static ssize_t nvram_len;
 
 static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
@@ -120,9 +121,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&nvram_mutex);
 	ret = nvram_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&nvram_mutex);
 
 	return ret;
 }
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index b6c2cc1..f773a9d 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -52,7 +52,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/workqueue.h>
 
 #include <asm/uaccess.h>
@@ -66,6 +66,7 @@
  *	ioctls.
  */
 
+static DEFINE_MUTEX(gen_rtc_mutex);
 static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait);
 
 /*
@@ -337,9 +338,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&gen_rtc_mutex);
 	ret = gen_rtc_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&gen_rtc_mutex);
 
 	return ret;
 }
@@ -352,16 +353,16 @@
 
 static int gen_rtc_open(struct inode *inode, struct file *file)
 {
-	lock_kernel();
+	mutex_lock(&gen_rtc_mutex);
 	if (gen_rtc_status & RTC_IS_OPEN) {
-		unlock_kernel();
+		mutex_unlock(&gen_rtc_mutex);
 		return -EBUSY;
 	}
 
 	gen_rtc_status |= RTC_IS_OPEN;
 	gen_rtc_irq_data = 0;
 	irq_active = 0;
-	unlock_kernel();
+	mutex_unlock(&gen_rtc_mutex);
 
 	return 0;
 }
@@ -497,6 +498,7 @@
 	.unlocked_ioctl	= gen_rtc_unlocked_ioctl,
 	.open		= gen_rtc_open,
 	.release	= gen_rtc_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice rtc_gen_dev =
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index a0a1829..a4eee32 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -30,6 +30,7 @@
 #include <linux/bcd.h>
 #include <linux/seq_file.h>
 #include <linux/bitops.h>
+#include <linux/compat.h>
 #include <linux/clocksource.h>
 #include <linux/slab.h>
 
@@ -67,6 +68,7 @@
 #define	read_counter(MC)	readl(MC)
 #endif
 
+static DEFINE_MUTEX(hpet_mutex); /* replaces BKL */
 static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
 
 /* This clocksource driver currently only works on ia64 */
@@ -250,7 +252,7 @@
 	if (file->f_mode & FMODE_WRITE)
 		return -EINVAL;
 
-	lock_kernel();
+	mutex_lock(&hpet_mutex);
 	spin_lock_irq(&hpet_lock);
 
 	for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
@@ -264,7 +266,7 @@
 
 	if (!devp) {
 		spin_unlock_irq(&hpet_lock);
-		unlock_kernel();
+		mutex_unlock(&hpet_mutex);
 		return -EBUSY;
 	}
 
@@ -272,7 +274,7 @@
 	devp->hd_irqdata = 0;
 	devp->hd_flags |= HPET_OPEN;
 	spin_unlock_irq(&hpet_lock);
-	unlock_kernel();
+	mutex_unlock(&hpet_mutex);
 
 	hpet_timer_set_irq(devp);
 
@@ -429,22 +431,6 @@
 	return 0;
 }
 
-static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int);
-
-static long hpet_ioctl(struct file *file, unsigned int cmd,
-			unsigned long arg)
-{
-	struct hpet_dev *devp;
-	int ret;
-
-	devp = file->private_data;
-	lock_kernel();
-	ret = hpet_ioctl_common(devp, cmd, arg, 0);
-	unlock_kernel();
-
-	return ret;
-}
-
 static int hpet_ioctl_ieon(struct hpet_dev *devp)
 {
 	struct hpet_timer __iomem *timer;
@@ -553,7 +539,8 @@
 }
 
 static int
-hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
+hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg,
+		  struct hpet_info *info)
 {
 	struct hpet_timer __iomem *timer;
 	struct hpet __iomem *hpet;
@@ -594,23 +581,15 @@
 		break;
 	case HPET_INFO:
 		{
-			struct hpet_info info;
-
 			if (devp->hd_ireqfreq)
-				info.hi_ireqfreq =
+				info->hi_ireqfreq =
 					hpet_time_div(hpetp, devp->hd_ireqfreq);
 			else
-				info.hi_ireqfreq = 0;
-			info.hi_flags =
+				info->hi_ireqfreq = 0;
+			info->hi_flags =
 			    readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
-			info.hi_hpet = hpetp->hp_which;
-			info.hi_timer = devp - hpetp->hp_dev;
-			if (kernel)
-				memcpy((void *)arg, &info, sizeof(info));
-			else
-				if (copy_to_user((void __user *)arg, &info,
-						 sizeof(info)))
-					err = -EFAULT;
+			info->hi_hpet = hpetp->hp_which;
+			info->hi_timer = devp - hpetp->hp_dev;
 			break;
 		}
 	case HPET_EPI:
@@ -636,7 +615,7 @@
 		devp->hd_flags &= ~HPET_PERIODIC;
 		break;
 	case HPET_IRQFREQ:
-		if (!kernel && (arg > hpet_max_freq) &&
+		if ((arg > hpet_max_freq) &&
 		    !capable(CAP_SYS_RESOURCE)) {
 			err = -EACCES;
 			break;
@@ -653,12 +632,63 @@
 	return err;
 }
 
+static long
+hpet_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct hpet_info info;
+	int err;
+
+	mutex_lock(&hpet_mutex);
+	err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
+	mutex_unlock(&hpet_mutex);
+
+	if ((cmd == HPET_INFO) && !err &&
+	    (copy_to_user((void __user *)arg, &info, sizeof(info))))
+		err = -EFAULT;
+
+	return err;
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_hpet_info {
+	compat_ulong_t hi_ireqfreq;	/* Hz */
+	compat_ulong_t hi_flags;	/* information */
+	unsigned short hi_hpet;
+	unsigned short hi_timer;
+};
+
+static long
+hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct hpet_info info;
+	int err;
+
+	mutex_lock(&hpet_mutex);
+	err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
+	mutex_unlock(&hpet_mutex);
+
+	if ((cmd == HPET_INFO) && !err) {
+		struct compat_hpet_info __user *u = compat_ptr(arg);
+		if (put_user(info.hi_ireqfreq, &u->hi_ireqfreq) ||
+		    put_user(info.hi_flags, &u->hi_flags) ||
+		    put_user(info.hi_hpet, &u->hi_hpet) ||
+		    put_user(info.hi_timer, &u->hi_timer))
+			err = -EFAULT;
+	}
+
+	return err;
+}
+#endif
+
 static const struct file_operations hpet_fops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
 	.read = hpet_read,
 	.poll = hpet_poll,
 	.unlocked_ioctl = hpet_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = hpet_compat_ioctl,
+#endif
 	.open = hpet_open,
 	.release = hpet_release,
 	.fasync = hpet_fasync,
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 3d9c61e..788da05 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -170,6 +170,7 @@
 	.owner		= THIS_MODULE,
 	.open		= rng_dev_open,
 	.read		= rng_dev_read,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice rng_miscdev = {
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index 4cd8b22..3bc0eef 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -23,7 +23,7 @@
 #include <linux/seq_file.h>
 #include <linux/dmi.h>
 #include <linux/capability.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
@@ -56,6 +56,7 @@
 
 #define I8K_TEMPERATURE_BUG	1
 
+static DEFINE_MUTEX(i8k_mutex);
 static char bios_version[4];
 
 MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
@@ -399,9 +400,9 @@
 {
 	long ret;
 
-	lock_kernel();
+	mutex_lock(&i8k_mutex);
 	ret = i8k_ioctl_unlocked(fp, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&i8k_mutex);
 
 	return ret;
 }
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index d4b71e8..fcd02ba 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -98,7 +98,7 @@
 #include <linux/major.h>
 #include <linux/wait.h>
 #include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 
@@ -138,6 +138,7 @@
 #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;
 
@@ -183,6 +184,8 @@
 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);
@@ -236,6 +239,7 @@
 	.write		= ip2_ipl_write,
 	.unlocked_ioctl	= ip2_ipl_ioctl,
 	.open		= ip2_ipl_open,
+	.llseek		= noop_llseek,
 }; 
 
 static unsigned long irq_counter;
@@ -454,6 +458,7 @@
 	.hangup          = ip2_hangup,
 	.tiocmget	 = ip2_tiocmget,
 	.tiocmset	 = ip2_tiocmset,
+	.get_icount	 = ip2_get_icount,
 	.proc_fops	 = &ip2_proc_fops,
 };
 
@@ -2128,7 +2133,6 @@
 	i2ChanStrPtr pCh = DevTable[tty->index];
 	i2eBordStrPtr pB;
 	struct async_icount cprev, cnow;	/* kernel counter temps */
-	struct serial_icounter_struct __user *p_cuser;
 	int rc = 0;
 	unsigned long flags;
 	void __user *argp = (void __user *)arg;
@@ -2297,34 +2301,6 @@
 		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. The controller is quite capable of counting
-	 * both, but this done to preserve compatibility with the standard
-	 * serial driver.
-	 */
-	case TIOCGICOUNT:
-		ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
-
-		write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-		cnow = pCh->icount;
-		write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-		p_cuser = argp;
-		rc = put_user(cnow.cts, &p_cuser->cts);
-		rc = put_user(cnow.dsr, &p_cuser->dsr);
-		rc = put_user(cnow.rng, &p_cuser->rng);
-		rc = put_user(cnow.dcd, &p_cuser->dcd);
-		rc = put_user(cnow.rx, &p_cuser->rx);
-		rc = put_user(cnow.tx, &p_cuser->tx);
-		rc = put_user(cnow.frame, &p_cuser->frame);
-		rc = put_user(cnow.overrun, &p_cuser->overrun);
-		rc = put_user(cnow.parity, &p_cuser->parity);
-		rc = put_user(cnow.brk, &p_cuser->brk);
-		rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
-		break;
-
-	/*
 	 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
 	 * will be passed to the line discipline for it to handle.
 	 */
@@ -2348,6 +2324,46 @@
 	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                                   */
@@ -2897,7 +2913,7 @@
 	printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
 #endif
 
-	lock_kernel();
+	mutex_lock(&ip2_mutex);
 
 	switch ( iplminor ) {
 	case 0:	    // IPL device
@@ -2961,7 +2977,7 @@
 		rc = -ENODEV;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&ip2_mutex);
 	return rc;
 }
 
@@ -2982,7 +2998,6 @@
 #ifdef IP2DEBUG_IPL
 	printk (KERN_DEBUG "IP2IPL: open\n" );
 #endif
-	cycle_kernel_lock();
 	return 0;
 }
 
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index d8ec92a..1fc8876 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -44,7 +44,6 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/compat.h>
-#include <linux/smp_lock.h>
 
 struct ipmi_file_private
 {
@@ -59,6 +58,7 @@
 	unsigned int         default_retry_time_ms;
 };
 
+static DEFINE_MUTEX(ipmi_mutex);
 static void file_receive_handler(struct ipmi_recv_msg *msg,
 				 void                 *handler_data)
 {
@@ -102,9 +102,9 @@
 	struct ipmi_file_private *priv = file->private_data;
 	int                      result;
 
-	lock_kernel(); /* could race against open() otherwise */
+	mutex_lock(&ipmi_mutex); /* could race against open() otherwise */
 	result = fasync_helper(fd, file, on, &priv->fasync_queue);
-	unlock_kernel();
+	mutex_unlock(&ipmi_mutex);
 
 	return (result);
 }
@@ -125,7 +125,7 @@
 	if (!priv)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&ipmi_mutex);
 	priv->file = file;
 
 	rv = ipmi_create_user(if_num,
@@ -150,7 +150,7 @@
 	priv->default_retry_time_ms = 0;
 
 out:
-	unlock_kernel();
+	mutex_unlock(&ipmi_mutex);
 	return rv;
 }
 
@@ -639,9 +639,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ipmi_mutex);
 	ret = ipmi_ioctl(file, cmd, data);
-	unlock_kernel();
+	mutex_unlock(&ipmi_mutex);
 
 	return ret;
 }
@@ -850,6 +850,7 @@
 	.release	= ipmi_release,
 	.fasync		= ipmi_fasync,
 	.poll		= ipmi_poll,
+	.llseek		= noop_llseek,
 };
 
 #define DEVICE_NAME     "ipmidev"
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 654d566..f4d334f 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -35,7 +35,7 @@
 #include <linux/moduleparam.h>
 #include <linux/ipmi.h>
 #include <linux/ipmi_smi.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/watchdog.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
@@ -149,6 +149,7 @@
 #define	WDIOC_GET_PRETIMEOUT     _IOW(WATCHDOG_IOCTL_BASE, 22, int)
 #endif
 
+static DEFINE_MUTEX(ipmi_watchdog_mutex);
 static int nowayout = WATCHDOG_NOWAYOUT;
 
 static ipmi_user_t watchdog_user;
@@ -748,9 +749,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ipmi_watchdog_mutex);
 	ret = ipmi_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ipmi_watchdog_mutex);
 
 	return ret;
 }
@@ -844,7 +845,6 @@
 		if (test_and_set_bit(0, &ipmi_wdog_open))
 			return -EBUSY;
 
-		cycle_kernel_lock();
 
 		/*
 		 * Don't start the timer now, let it start on the
@@ -909,6 +909,7 @@
 	.open    = ipmi_open,
 	.release = ipmi_close,
 	.fasync  = ipmi_fasync,
+	.llseek  = no_llseek,
 };
 
 static struct miscdevice ipmi_wdog_miscdev = {
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index be28391..667abd23 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -704,6 +704,7 @@
 	.read		= stli_memread,
 	.write		= stli_memwrite,
 	.unlocked_ioctl	= stli_memioctl,
+	.llseek		= default_llseek,
 };
 
 /*****************************************************************************/
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 938a3a2..97c3edb 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -126,7 +126,7 @@
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/jiffies.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 
 #include <linux/parport.h>
@@ -140,6 +140,7 @@
 /* if you have more than 8 printers, remember to increase LP_NO */
 #define LP_NO 8
 
+static DEFINE_MUTEX(lp_mutex);
 static struct lp_struct lp_table[LP_NO];
 
 static unsigned int lp_count = 0;
@@ -493,7 +494,7 @@
 	unsigned int minor = iminor(inode);
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&lp_mutex);
 	if (minor >= LP_NO) {
 		ret = -ENXIO;
 		goto out;
@@ -554,7 +555,7 @@
 	lp_release_parport (&lp_table[minor]);
 	lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
 out:
-	unlock_kernel();
+	mutex_unlock(&lp_mutex);
 	return ret;
 }
 
@@ -680,7 +681,7 @@
 	int ret;
 
 	minor = iminor(file->f_path.dentry->d_inode);
-	lock_kernel();
+	mutex_lock(&lp_mutex);
 	switch (cmd) {
 	case LPSETTIMEOUT:
 		if (copy_from_user(&par_timeout, (void __user *)arg,
@@ -694,7 +695,7 @@
 		ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg);
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&lp_mutex);
 
 	return ret;
 }
@@ -709,7 +710,7 @@
 	int ret;
 
 	minor = iminor(file->f_path.dentry->d_inode);
-	lock_kernel();
+	mutex_lock(&lp_mutex);
 	switch (cmd) {
 	case LPSETTIMEOUT:
 		tc = compat_ptr(arg);
@@ -730,7 +731,7 @@
 		ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg));
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&lp_mutex);
 
 	return ret;
 }
@@ -748,6 +749,7 @@
 #ifdef CONFIG_PARPORT_1284
 	.read		= lp_read,
 #endif
+	.llseek		= noop_llseek,
 };
 
 /* --- support for console on the line printer ----------------- */
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 83bef4e..1aeaaba 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -25,7 +25,6 @@
 #include <linux/mm.h>
 #include <linux/uio.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -42,6 +41,7 @@
 #else
 #define DBG(fmt...)
 #endif
+static DEFINE_MUTEX(mbcs_mutex);
 static int mbcs_major;
 
 static LIST_HEAD(soft_list);
@@ -385,19 +385,19 @@
 	struct mbcs_soft *soft;
 	int minor;
 
-	lock_kernel();
+	mutex_lock(&mbcs_mutex);
 	minor = iminor(ip);
 
 	/* Nothing protects access to this list... */
 	list_for_each_entry(soft, &soft_list, list) {
 		if (soft->nasid == minor) {
 			fp->private_data = soft->cxdev;
-			unlock_kernel();
+			mutex_unlock(&mbcs_mutex);
 			return 0;
 		}
 	}
 
-	unlock_kernel();
+	mutex_unlock(&mbcs_mutex);
 	return -ENODEV;
 }
 
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 1f528fa..e985b1c 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -805,6 +805,7 @@
 static const struct file_operations oldmem_fops = {
 	.read	= read_oldmem,
 	.open	= open_oldmem,
+	.llseek = default_llseek,
 };
 #endif
 
@@ -831,6 +832,7 @@
 
 static const struct file_operations kmsg_fops = {
 	.write = kmsg_write,
+	.llseek = noop_llseek,
 };
 
 static const struct memdev {
@@ -882,6 +884,7 @@
 
 static const struct file_operations memory_fops = {
 	.open = memory_open,
+	.llseek = noop_llseek,
 };
 
 static char *mem_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index abdafd4..778273c 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -162,6 +162,7 @@
 static const struct file_operations misc_fops = {
 	.owner		= THIS_MODULE,
 	.open		= misc_open,
+	.llseek		= noop_llseek,
 };
 
 /**
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index ea7c99f..c070b53 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -32,7 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/math64.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
@@ -59,6 +59,7 @@
 
 #define rtc_time()              (*RTC_COUNTER_ADDR)
 
+static DEFINE_MUTEX(mmtimer_mutex);
 static long mmtimer_ioctl(struct file *file, unsigned int cmd,
 						unsigned long arg);
 static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
@@ -72,6 +73,7 @@
 	.owner = THIS_MODULE,
 	.mmap =	mmtimer_mmap,
 	.unlocked_ioctl = mmtimer_ioctl,
+	.llseek = noop_llseek,
 };
 
 /*
@@ -371,7 +373,7 @@
 {
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&mmtimer_mutex);
 
 	switch (cmd) {
 	case MMTIMER_GETOFFSET:	/* offset of the counter */
@@ -414,7 +416,7 @@
 		ret = -ENOTTY;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&mmtimer_mutex);
 	return ret;
 }
 
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index ecb89d7..966a95b 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -316,7 +316,8 @@
 
 static const struct file_operations fetchop_fops = {
 	.owner = THIS_MODULE,
-	.mmap = fetchop_mmap
+	.mmap = fetchop_mmap,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice fetchop_miscdev = {
@@ -327,7 +328,8 @@
 
 static const struct file_operations cached_fops = {
 	.owner = THIS_MODULE,
-	.mmap = cached_mmap
+	.mmap = cached_mmap,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice cached_miscdev = {
@@ -338,7 +340,8 @@
 
 static const struct file_operations uncached_fops = {
 	.owner = THIS_MODULE,
-	.mmap = uncached_mmap
+	.mmap = uncached_mmap,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice uncached_miscdev = {
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index a4ec50c..1d82d58 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -56,7 +56,7 @@
 #include <linux/serial.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/serial_8250.h>
 #include "smapi.h"
@@ -73,6 +73,7 @@
 * checks are made against other devices (ie. superio) for conflicts.
 * We'll depend on users using the tpctl utility to do that for now
 */
+static DEFINE_MUTEX(mwave_mutex);
 int mwave_debug = 0;
 int mwave_3780i_irq = 0;
 int mwave_3780i_io = 0;
@@ -101,7 +102,6 @@
 	PRINTK_2(TRACE_MWAVE,
 		"mwavedd::mwave_open, exit return retval %x\n", retval);
 
-	cycle_kernel_lock();
 	return retval;
 }
 
@@ -136,9 +136,9 @@
 			PRINTK_1(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
 				" calling tp3780I_ResetDSP\n");
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_ResetDSP(&pDrvData->rBDData);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 			PRINTK_2(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
 				" retval %x from tp3780I_ResetDSP\n",
@@ -149,9 +149,9 @@
 			PRINTK_1(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
 				" calling tp3780I_StartDSP\n");
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_StartDSP(&pDrvData->rBDData);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 			PRINTK_2(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
 				" retval %x from tp3780I_StartDSP\n",
@@ -165,10 +165,10 @@
 				"mwavedd::mwave_ioctl,"
 				" IOCTL_MW_DSP_ABILITIES calling"
 				" tp3780I_QueryAbilities\n");
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
 					&rAbilities);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 			PRINTK_2(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
 				" retval %x from tp3780I_QueryAbilities\n",
@@ -199,13 +199,13 @@
 				"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
 				" size %lx, ioarg %lx pusBuffer %p\n",
 				rReadData.ulDataLength, ioarg, pusBuffer);
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
 					iocmd,
 					pusBuffer,
 					rReadData.ulDataLength,
 					rReadData.usDspAddress);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -223,12 +223,12 @@
 				" size %lx, ioarg %lx pusBuffer %p\n",
 				rReadData.ulDataLength / 2, ioarg,
 				pusBuffer);
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
 				iocmd, pusBuffer,
 				rReadData.ulDataLength / 2,
 				rReadData.usDspAddress);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -246,12 +246,12 @@
 				" size %lx, ioarg %lx pusBuffer %p\n",
 				rWriteData.ulDataLength, ioarg,
 				pusBuffer);
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
 					iocmd, pusBuffer,
 					rWriteData.ulDataLength,
 					rWriteData.usDspAddress);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -269,12 +269,12 @@
 				" size %lx, ioarg %lx pusBuffer %p\n",
 				rWriteData.ulDataLength, ioarg,
 				pusBuffer);
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
 					iocmd, pusBuffer,
 					rWriteData.ulDataLength,
 					rWriteData.usDspAddress);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -295,10 +295,10 @@
 				ipcnum,
 				pDrvData->IPCs[ipcnum].usIntCount);
 
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			pDrvData->IPCs[ipcnum].bIsHere = FALSE;
 			pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 	
 			PRINTK_2(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
@@ -323,7 +323,7 @@
 				ipcnum,
 				pDrvData->IPCs[ipcnum].usIntCount);
 	
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
 				DECLARE_WAITQUEUE(wait, current);
 
@@ -364,7 +364,7 @@
 					" processing\n",
 					ipcnum);
 			}
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -383,14 +383,14 @@
 						ipcnum);
 				return -EINVAL;
 			}
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
 				pDrvData->IPCs[ipcnum].bIsEnabled = FALSE;
 				if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) {
 					wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
 				}
 			}
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -479,7 +479,8 @@
 	.write		= mwave_write,
 	.unlocked_ioctl	= mwave_ioctl,
 	.open		= mwave_open,
-	.release	= mwave_close
+	.release	= mwave_close,
+	.llseek		= default_llseek,
 };
 
 
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 3fc89da..463df27 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -1700,7 +1700,7 @@
 		return 0;
 	}
 
-	if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
+	if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
 			test_bit(TTY_IO_ERROR, &tty->flags))
 		return -EIO;
 
@@ -1730,32 +1730,6 @@
 
 		return wait_event_interruptible(info->port.delta_msr_wait,
 				mxser_cflags_changed(info, arg, &cnow));
-	/*
-	 * 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.
-	 */
-	case TIOCGICOUNT: {
-		struct serial_icounter_struct icnt = { 0 };
-		spin_lock_irqsave(&info->slock, flags);
-		cnow = info->icount;
-		spin_unlock_irqrestore(&info->slock, flags);
-
-		icnt.frame = cnow.frame;
-		icnt.brk = cnow.brk;
-		icnt.overrun = cnow.overrun;
-		icnt.buf_overrun = cnow.buf_overrun;
-		icnt.parity = cnow.parity;
-		icnt.rx = cnow.rx;
-		icnt.tx = cnow.tx;
-		icnt.cts = cnow.cts;
-		icnt.dsr = cnow.dsr;
-		icnt.rng = cnow.rng;
-		icnt.dcd = cnow.dcd;
-
-		return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0;
-	}
 	case MOXA_HighSpeedOn:
 		return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
 	case MOXA_SDS_RSTICOUNTER:
@@ -1828,6 +1802,39 @@
 	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;
@@ -2326,6 +2333,7 @@
 	.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 = {
@@ -2339,20 +2347,11 @@
  * The MOXA Smartio/Industio serial driver boot-time initialization code!
  */
 
-static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev,
-		unsigned int irq)
+static void mxser_release_ISA_res(struct mxser_board *brd)
 {
-	if (irq)
-		free_irq(brd->irq, brd);
-	if (pdev != NULL) {	/* PCI */
-#ifdef CONFIG_PCI
-		pci_release_region(pdev, 2);
-		pci_release_region(pdev, 3);
-#endif
-	} else {
-		release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
-		release_region(brd->vector, 1);
-	}
+	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,
@@ -2397,13 +2396,11 @@
 
 	retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
 			brd);
-	if (retval) {
+	if (retval)
 		printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
 			"conflict with another device.\n",
 			brd->info->name, brd->irq);
-		/* We hold resources, we need to release them. */
-		mxser_release_res(brd, pdev, 0);
-	}
+
 	return retval;
 }
 
@@ -2555,7 +2552,7 @@
 	ioaddress = pci_resource_start(pdev, 2);
 	retval = pci_request_region(pdev, 2, "mxser(IO)");
 	if (retval)
-		goto err;
+		goto err_dis;
 
 	brd->info = &mxser_cards[ent->driver_data];
 	for (i = 0; i < brd->info->nports; i++)
@@ -2565,7 +2562,7 @@
 	ioaddress = pci_resource_start(pdev, 3);
 	retval = pci_request_region(pdev, 3, "mxser(vector)");
 	if (retval)
-		goto err_relio;
+		goto err_zero;
 	brd->vector = ioaddress;
 
 	/* irq */
@@ -2608,7 +2605,7 @@
 	/* mxser_initbrd will hook ISR. */
 	retval = mxser_initbrd(brd, pdev);
 	if (retval)
-		goto err_null;
+		goto err_rel3;
 
 	for (i = 0; i < brd->info->nports; i++)
 		tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
@@ -2616,10 +2613,13 @@
 	pci_set_drvdata(pdev, brd);
 
 	return 0;
-err_relio:
-	pci_release_region(pdev, 2);
-err_null:
+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
@@ -2629,14 +2629,19 @@
 
 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);
 
-	mxser_release_res(brd, pdev, 1);
+	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 = {
@@ -2741,7 +2746,7 @@
 
 	for (i = 0; i < MXSER_BOARDS; i++)
 		if (mxser_boards[i].info != NULL)
-			mxser_release_res(&mxser_boards[i], NULL, 1);
+			mxser_release_ISA_res(&mxser_boards[i]);
 }
 
 module_init(mxser_module_init);
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 817169c..dd3f9b1 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -1804,24 +1804,24 @@
 	return ret;
 }
 
-static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp)
+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;
-	struct serial_icounter_struct 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 copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
+	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,
@@ -1840,9 +1840,7 @@
 		rval = wait_event_interruptible(port->tty_wait,
 				ntty_cflags_changed(port, arg, &cprev));
 		break;
-	} case TIOCGICOUNT:
-		rval = ntty_ioctl_tiocgicount(port, argp);
-		break;
+	}
 	default:
 		DBG1("ERR: 0x%08X, %d", cmd, cmd);
 		break;
@@ -1922,6 +1920,7 @@
 	.chars_in_buffer = ntty_chars_in_buffer,
 	.tiocmget = ntty_tiocmget,
 	.tiocmset = ntty_tiocmset,
+	.get_icount = ntty_tiocgicount,
 	.install = ntty_install,
 	.cleanup = ntty_cleanup,
 };
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 66d2917..166f1e7 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -109,10 +109,11 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/system.h>
 
+static DEFINE_MUTEX(nvram_mutex);
 static DEFINE_SPINLOCK(nvram_state_lock);
 static int nvram_open_cnt;	/* #times opened */
 static int nvram_open_mode;	/* special open modes */
@@ -308,7 +309,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
 
-		lock_kernel();
+		mutex_lock(&nvram_mutex);
 		spin_lock_irq(&rtc_lock);
 
 		for (i = 0; i < NVRAM_BYTES; ++i)
@@ -316,7 +317,7 @@
 		__nvram_set_checksum();
 
 		spin_unlock_irq(&rtc_lock);
-		unlock_kernel();
+		mutex_unlock(&nvram_mutex);
 		return 0;
 
 	case NVRAM_SETCKS:
@@ -325,11 +326,11 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
 
-		lock_kernel();
+		mutex_lock(&nvram_mutex);
 		spin_lock_irq(&rtc_lock);
 		__nvram_set_checksum();
 		spin_unlock_irq(&rtc_lock);
-		unlock_kernel();
+		mutex_unlock(&nvram_mutex);
 		return 0;
 
 	default:
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c
index 2604246..8994ce3 100644
--- a/drivers/char/nwbutton.c
+++ b/drivers/char/nwbutton.c
@@ -182,6 +182,7 @@
 static const struct file_operations button_fops = {
 	.owner		= THIS_MODULE,
 	.read		= button_read,
+	.llseek		= noop_llseek,
 };
 
 /* 
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c
index 043a1c7..a12f524 100644
--- a/drivers/char/nwflash.c
+++ b/drivers/char/nwflash.c
@@ -25,7 +25,6 @@
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/jiffies.h>
 
@@ -41,6 +40,7 @@
 
 #define	NWFLASH_VERSION "6.4"
 
+static DEFINE_MUTEX(flash_mutex);
 static void kick_open(void);
 static int get_flash_id(void);
 static int erase_block(int nBlock);
@@ -96,7 +96,7 @@
 
 static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 {
-	lock_kernel();
+	mutex_lock(&flash_mutex);
 	switch (cmd) {
 	case CMD_WRITE_DISABLE:
 		gbWriteBase64Enable = 0;
@@ -114,10 +114,10 @@
 	default:
 		gbWriteBase64Enable = 0;
 		gbWriteEnable = 0;
-		unlock_kernel();
+		mutex_unlock(&flash_mutex);
 		return -EINVAL;
 	}
-	unlock_kernel();
+	mutex_unlock(&flash_mutex);
 	return 0;
 }
 
@@ -282,7 +282,7 @@
 {
 	loff_t ret;
 
-	lock_kernel();
+	mutex_lock(&flash_mutex);
 	if (flashdebug)
 		printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n",
 		       (unsigned int) offset, orig);
@@ -317,7 +317,7 @@
 	default:
 		ret = -EINVAL;
 	}
-	unlock_kernel();
+	mutex_unlock(&flash_mutex);
 	return ret;
 }
 
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index 8ecbcc1..b304ec0 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -234,6 +234,7 @@
 	.open	= pc8736x_gpio_open,
 	.write	= nsc_gpio_write,
 	.read	= nsc_gpio_read,
+	.llseek = no_llseek,
 };
 
 static void __init pc8736x_init_shadow(void)
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index ec73d9f..6835c23 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -30,11 +30,10 @@
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/bitrev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -55,7 +54,7 @@
 			   __func__ , ## args);		\
 	} while (0)
 
-static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte";
+static DEFINE_MUTEX(cmm_mutex);
 
 #define	T_1SEC		(HZ)
 #define	T_10MSEC	msecs_to_jiffies(10)
@@ -1418,7 +1417,7 @@
 	       iminor(inode), ioctl_names[_IOC_NR(cmd)]);
 #endif
 
-	lock_kernel();
+	mutex_lock(&cmm_mutex);
 	rc = -ENODEV;
 	link = dev_table[iminor(inode)];
 	if (!pcmcia_dev_present(link)) {
@@ -1626,7 +1625,7 @@
 		rc = -ENOTTY;
 	}
 out:
-	unlock_kernel();
+	mutex_unlock(&cmm_mutex);
 	return rc;
 }
 
@@ -1640,7 +1639,7 @@
 	if (minor >= CM4000_MAX_DEV)
 		return -ENODEV;
 
-	lock_kernel();
+	mutex_lock(&cmm_mutex);
 	link = dev_table[minor];
 	if (link == NULL || !pcmcia_dev_present(link)) {
 		ret = -ENODEV;
@@ -1685,7 +1684,7 @@
 	DEBUGP(2, dev, "<- cmm_open\n");
 	ret = nonseekable_open(inode, filp);
 out:
-	unlock_kernel();
+	mutex_unlock(&cmm_mutex);
 	return ret;
 }
 
@@ -1742,20 +1741,8 @@
 
 /*==== Interface to PCMCIA Layer =======================================*/
 
-static int cm4000_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cfg,
-			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
-			       void *priv_data)
+static int cm4000_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (!cfg->io.nwin)
-		return -ENODEV;
-
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
-	p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
-	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
 	return pcmcia_request_io(p_dev);
 }
 
@@ -1763,13 +1750,13 @@
 {
 	struct cm4000_dev *dev;
 
+	link->config_flags |= CONF_AUTO_SET_IO;
+
 	/* read the config-tuples */
 	if (pcmcia_loop_config(link, cm4000_config_check, NULL))
 		goto cs_release;
 
-	link->conf.IntType = 00000002;
-
-	if (pcmcia_request_configuration(link, &link->conf))
+	if (pcmcia_enable_device(link))
 		goto cs_release;
 
 	dev = link->priv;
@@ -1829,7 +1816,6 @@
 
 	dev->p_dev = link;
 	link->priv = dev;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 	dev_table[i] = link;
 
 	init_waitqueue_head(&dev->devq);
@@ -1880,6 +1866,7 @@
 	.unlocked_ioctl	= cmm_ioctl,
 	.open	= cmm_open,
 	.release= cmm_close,
+	.llseek = no_llseek,
 };
 
 static struct pcmcia_device_id cm4000_ids[] = {
@@ -1891,9 +1878,7 @@
 
 static struct pcmcia_driver cm4000_driver = {
 	.owner	  = THIS_MODULE,
-	.drv	  = {
-		.name = "cm4000_cs",
-		},
+	.name	  = "cm4000_cs",
 	.probe    = cm4000_probe,
 	.remove   = cm4000_detach,
 	.suspend  = cm4000_suspend,
@@ -1905,8 +1890,6 @@
 {
 	int rc;
 
-	printk(KERN_INFO "%s\n", version);
-
 	cmm_class = class_create(THIS_MODULE, "cardman_4000");
 	if (IS_ERR(cmm_class))
 		return PTR_ERR(cmm_class);
@@ -1931,7 +1914,6 @@
 
 static void __exit cmm_exit(void)
 {
-	printk(KERN_INFO MODULE_NAME ": unloading\n");
 	pcmcia_unregister_driver(&cm4000_driver);
 	unregister_chrdev(major, DEVICE_NAME);
 	class_destroy(cmm_class);
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 815cde1..5d8d59e 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -24,12 +24,11 @@
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -49,8 +48,7 @@
 			   __func__ , ## args);		\
 	} while (0)
 
-static char *version =
-"OMNIKEY CardMan 4040 v1.1.0gm5 - All bugs added by Harald Welte";
+static DEFINE_MUTEX(cm4040_mutex);
 
 #define	CCID_DRIVER_BULK_DEFAULT_TIMEOUT  	(150*HZ)
 #define	CCID_DRIVER_ASYNC_POWERUP_TIMEOUT 	(35*HZ)
@@ -444,7 +442,7 @@
 	if (minor >= CM_MAX_DEV)
 		return -ENODEV;
 
-	lock_kernel();
+	mutex_lock(&cm4040_mutex);
 	link = dev_table[minor];
 	if (link == NULL || !pcmcia_dev_present(link)) {
 		ret = -ENODEV;
@@ -473,7 +471,7 @@
 	DEBUGP(2, dev, "<- cm4040_open (successfully)\n");
 	ret = nonseekable_open(inode, filp);
 out:
-	unlock_kernel();
+	mutex_unlock(&cm4040_mutex);
 	return ret;
 }
 
@@ -516,26 +514,9 @@
 	return;
 }
 
-static int cm4040_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cfg,
-			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
-			       void *priv_data)
+static int cm4040_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	int rc;
-	if (!cfg->io.nwin)
-		return -ENODEV;
-
-	/* Get the IOaddr */
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
-	p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
-	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-	rc = pcmcia_request_io(p_dev);
-
-	dev_printk(KERN_INFO, &p_dev->dev,
-		   "pcmcia_request_io returned 0x%x\n", rc);
-	return rc;
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -544,15 +525,15 @@
 	struct reader_dev *dev;
 	int fail_rc;
 
+	link->config_flags |= CONF_AUTO_SET_IO;
+
 	if (pcmcia_loop_config(link, cm4040_config_check, NULL))
 		goto cs_release;
 
-	link->conf.IntType = 00000002;
-
-	fail_rc = pcmcia_request_configuration(link, &link->conf);
+	fail_rc = pcmcia_enable_device(link);
 	if (fail_rc != 0) {
 		dev_printk(KERN_INFO, &link->dev,
-			   "pcmcia_request_configuration failed 0x%x\n",
+			   "pcmcia_enable_device failed 0x%x\n",
 			   fail_rc);
 		goto cs_release;
 	}
@@ -599,7 +580,6 @@
 	link->priv = dev;
 	dev->p_dev = link;
 
-	link->conf.IntType = INT_MEMORY_AND_IO;
 	dev_table[i] = link;
 
 	init_waitqueue_head(&dev->devq);
@@ -650,6 +630,7 @@
 	.open		= cm4040_open,
 	.release	= cm4040_close,
 	.poll		= cm4040_poll,
+	.llseek		= no_llseek,
 };
 
 static struct pcmcia_device_id cm4040_ids[] = {
@@ -662,9 +643,7 @@
 
 static struct pcmcia_driver reader_driver = {
   	.owner		= THIS_MODULE,
-  	.drv		= {
-		.name	= "cm4040_cs",
-	},
+	.name		= "cm4040_cs",
 	.probe		= reader_probe,
 	.remove		= reader_detach,
 	.id_table	= cm4040_ids,
@@ -674,7 +653,6 @@
 {
 	int rc;
 
-	printk(KERN_INFO "%s\n", version);
 	cmx_class = class_create(THIS_MODULE, "cardman_4040");
 	if (IS_ERR(cmx_class))
 		return PTR_ERR(cmx_class);
@@ -699,7 +677,6 @@
 
 static void __exit cm4040_exit(void)
 {
-	printk(KERN_INFO MODULE_NAME ": unloading\n");
 	pcmcia_unregister_driver(&reader_driver);
 	unregister_chrdev(major, DEVICE_NAME);
 	class_destroy(cmx_class);
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 67bdb05..94b8eb4 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -32,7 +32,6 @@
 #include <pcmcia/device_id.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/ds.h>
-#include <pcmcia/cs.h>
 
 static struct pcmcia_device_id ipw_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
@@ -76,23 +75,18 @@
 	schedule_work(&ipw->work_reboot);
 }
 
-static int ipwireless_probe(struct pcmcia_device *p_dev,
-			    cistpl_cftable_entry_t *cfg,
-			    cistpl_cftable_entry_t *dflt,
-			    unsigned int vcc,
-			    void *priv_data)
+static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
 {
 	struct ipw_dev *ipw = priv_data;
 	struct resource *io_resource;
 	int ret;
 
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
 	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
 
 	/* 0x40 causes it to generate level mode interrupts. */
 	/* 0x04 enables IREQ pin. */
-	p_dev->conf.ConfigIndex = cfg->index | 0x44;
+	p_dev->config_index |= 0x44;
 	p_dev->io_lines = 16;
 	ret = pcmcia_request_io(p_dev);
 	if (ret)
@@ -102,65 +96,49 @@
 				resource_size(p_dev->resource[0]),
 				IPWIRELESS_PCCARD_NAME);
 
-	if (cfg->mem.nwin == 0)
-		return 0;
-
-	ipw->request_common_memory.Attributes =
+	p_dev->resource[2]->flags |=
 		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-	ipw->request_common_memory.Base = cfg->mem.win[0].host_addr;
-	ipw->request_common_memory.Size = cfg->mem.win[0].len;
-	if (ipw->request_common_memory.Size < 0x1000)
-		ipw->request_common_memory.Size = 0x1000;
-	ipw->request_common_memory.AccessSpeed = 0;
 
-	ret = pcmcia_request_window(p_dev, &ipw->request_common_memory,
-				&ipw->handle_common_memory);
-
+	ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
 	if (ret != 0)
 		goto exit1;
 
-	ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory,
-				cfg->mem.win[0].card_addr);
-
+	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
 	if (ret != 0)
 		goto exit2;
 
-	ipw->is_v2_card = cfg->mem.win[0].len == 0x100;
+	ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
 
-	ipw->common_memory = ioremap(ipw->request_common_memory.Base,
-				ipw->request_common_memory.Size);
-	request_mem_region(ipw->request_common_memory.Base,
-			ipw->request_common_memory.Size,
+	ipw->attr_memory = ioremap(p_dev->resource[2]->start,
+				resource_size(p_dev->resource[2]));
+	request_mem_region(p_dev->resource[2]->start,
+			resource_size(p_dev->resource[2]),
 			IPWIRELESS_PCCARD_NAME);
 
-	ipw->request_attr_memory.Attributes =
-		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
-	ipw->request_attr_memory.Base = 0;
-	ipw->request_attr_memory.Size = 0;	/* this used to be 0x1000 */
-	ipw->request_attr_memory.AccessSpeed = 0;
-
-	ret = pcmcia_request_window(p_dev, &ipw->request_attr_memory,
-				&ipw->handle_attr_memory);
-
+	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 exit2;
 
-	ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, 0);
+	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0);
 	if (ret != 0)
 		goto exit3;
 
-	ipw->attr_memory = ioremap(ipw->request_attr_memory.Base,
-				ipw->request_attr_memory.Size);
-	request_mem_region(ipw->request_attr_memory.Base,
-			ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME);
+	ipw->attr_memory = ioremap(p_dev->resource[3]->start,
+				resource_size(p_dev->resource[3]));
+	request_mem_region(p_dev->resource[3]->start,
+			resource_size(p_dev->resource[3]),
+			IPWIRELESS_PCCARD_NAME);
 
 	return 0;
 
 exit3:
 exit2:
 	if (ipw->common_memory) {
-		release_mem_region(ipw->request_common_memory.Base,
-				ipw->request_common_memory.Size);
+		release_mem_region(p_dev->resource[2]->start,
+				resource_size(p_dev->resource[2]));
 		iounmap(ipw->common_memory);
 	}
 exit1:
@@ -175,14 +153,13 @@
 	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;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
 
 	ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
@@ -201,13 +178,9 @@
 			(unsigned int) link->irq);
 	if (ipw->attr_memory && ipw->common_memory)
 		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n",
-			ipw->request_attr_memory.Base,
-			ipw->request_attr_memory.Base
-			+ ipw->request_attr_memory.Size - 1,
-			ipw->request_common_memory.Base,
-			ipw->request_common_memory.Base
-			+ ipw->request_common_memory.Size - 1);
+			": attr memory %pR, common memory %pR\n",
+			link->resource[3],
+			link->resource[2]);
 
 	ipw->network = ipwireless_network_create(ipw->hardware);
 	if (!ipw->network)
@@ -223,25 +196,23 @@
 	 * Do the RequestConfiguration last, because it enables interrupts.
 	 * Then we don't get any interrupts before we're ready for them.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
-
+	ret = pcmcia_enable_device(link);
 	if (ret != 0)
 		goto exit;
 
 	return 0;
 
 exit:
-	if (ipw->attr_memory) {
-		release_mem_region(ipw->request_attr_memory.Base,
-				ipw->request_attr_memory.Size);
-		iounmap(ipw->attr_memory);
-
-	}
 	if (ipw->common_memory) {
-		release_mem_region(ipw->request_common_memory.Base,
-				ipw->request_common_memory.Size);
+		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;
 }
@@ -249,13 +220,13 @@
 static void release_ipwireless(struct ipw_dev *ipw)
 {
 	if (ipw->common_memory) {
-		release_mem_region(ipw->request_common_memory.Base,
-				ipw->request_common_memory.Size);
+		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->request_attr_memory.Base,
-				ipw->request_attr_memory.Size);
+		release_mem_region(ipw->link->resource[3]->start,
+				resource_size(ipw->link->resource[3]));
 		iounmap(ipw->attr_memory);
 	}
 	pcmcia_disable_device(ipw->link);
@@ -324,7 +295,7 @@
 	.owner		= THIS_MODULE,
 	.probe          = ipwireless_attach,
 	.remove         = ipwireless_detach,
-	.drv = { .name  = IPWIRELESS_PCCARD_NAME },
+	.name		= IPWIRELESS_PCCARD_NAME,
 	.id_table       = ipw_ids
 };
 
@@ -336,9 +307,6 @@
 {
 	int ret;
 
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
-	       IPWIRELESS_PCMCIA_VERSION " by " IPWIRELESS_PCMCIA_AUTHOR "\n");
-
 	ret = ipwireless_tty_init();
 	if (ret != 0)
 		return ret;
@@ -355,9 +323,6 @@
  */
 static void __exit exit_ipwireless(void)
 {
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
-			IPWIRELESS_PCMCIA_VERSION " removed\n");
-
 	pcmcia_unregister_driver(&me);
 	ipwireless_tty_release();
 }
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h
index c207be8..f2cbb11 100644
--- a/drivers/char/pcmcia/ipwireless/main.h
+++ b/drivers/char/pcmcia/ipwireless/main.h
@@ -21,7 +21,6 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -45,13 +44,9 @@
 	struct pcmcia_device *link;
 	int is_v2_card;
 
-	window_handle_t handle_attr_memory;
 	void __iomem *attr_memory;
-	win_req_t request_attr_memory;
 
-	window_handle_t handle_common_memory;
 	void __iomem *common_memory;
-	win_req_t request_common_memory;
 
 	/* Reference to attribute memory, containing CIS data */
 	void *attribute_memory;
diff --git a/drivers/char/pcmcia/ipwireless/tty.h b/drivers/char/pcmcia/ipwireless/tty.h
index 3e163d4..747b2d6 100644
--- a/drivers/char/pcmcia/ipwireless/tty.h
+++ b/drivers/char/pcmcia/ipwireless/tty.h
@@ -21,7 +21,6 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 9ecd6be..bfc10f8 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -70,7 +70,6 @@
 #include <linux/workqueue.h>
 #include <linux/hdlc.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -550,9 +549,6 @@
 
     /* Initialize the struct pcmcia_device structure */
 
-    link->conf.Attributes = 0;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-
     ret = mgslpc_config(link);
     if (ret)
 	    return ret;
@@ -565,20 +561,8 @@
 /* Card has been inserted.
  */
 
-static int mgslpc_ioprobe(struct pcmcia_device *p_dev,
-			  cistpl_cftable_entry_t *cfg,
-			  cistpl_cftable_entry_t *dflt,
-			  unsigned int vcc,
-			  void *priv_data)
+static int mgslpc_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (!cfg->io.nwin)
-		return -ENODEV;
-
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
-	p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
-	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
 	return pcmcia_request_io(p_dev);
 }
 
@@ -590,32 +574,24 @@
     if (debug_level >= DEBUG_LEVEL_INFO)
 	    printk("mgslpc_config(0x%p)\n", link);
 
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
     ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL);
     if (ret != 0)
 	    goto failed;
 
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 8;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_index = 8;
+    link->config_regs = PRESENT_OPTION;
 
     ret = pcmcia_request_irq(link, mgslpc_isr);
     if (ret)
 	    goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
     info->io_base = link->resource[0]->start;
     info->irq_level = link->irq;
-
-    dev_info(&link->dev, "index 0x%02x:",
-	    link->conf.ConfigIndex);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-	    printk(", irq %d", link->irq);
-    if (link->resource[0])
-	    printk(", io %pR", link->resource[0]);
-    printk("\n");
     return 0;
 
 failed:
@@ -2215,6 +2191,32 @@
 	return 0;
 }
 
+static int mgslpc_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	MGSLPC_INFO * info = (MGSLPC_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;
+}
+
 /* Service an IOCTL request
  *
  * Arguments:
@@ -2230,11 +2232,7 @@
 			unsigned int cmd, unsigned long arg)
 {
 	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
-	int error;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	struct serial_icounter_struct __user *p_cuser;	/* user space */
 	void __user *argp = (void __user *)arg;
-	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
@@ -2244,7 +2242,7 @@
 		return -ENODEV;
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	    (cmd != TIOCMIWAIT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -2274,34 +2272,6 @@
 		return wait_events(info, argp);
 	case TIOCMIWAIT:
 		return modem_input_wait(info,(int)arg);
-	case TIOCGICOUNT:
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		spin_unlock_irqrestore(&info->lock,flags);
-		p_cuser = argp;
-		PUT_USER(error,cnow.cts, &p_cuser->cts);
-		if (error) return error;
-		PUT_USER(error,cnow.dsr, &p_cuser->dsr);
-		if (error) return error;
-		PUT_USER(error,cnow.rng, &p_cuser->rng);
-		if (error) return error;
-		PUT_USER(error,cnow.dcd, &p_cuser->dcd);
-		if (error) return error;
-		PUT_USER(error,cnow.rx, &p_cuser->rx);
-		if (error) return error;
-		PUT_USER(error,cnow.tx, &p_cuser->tx);
-		if (error) return error;
-		PUT_USER(error,cnow.frame, &p_cuser->frame);
-		if (error) return error;
-		PUT_USER(error,cnow.overrun, &p_cuser->overrun);
-		if (error) return error;
-		PUT_USER(error,cnow.parity, &p_cuser->parity);
-		if (error) return error;
-		PUT_USER(error,cnow.brk, &p_cuser->brk);
-		if (error) return error;
-		PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
-		if (error) return error;
-		return 0;
 	default:
 		return -ENOIOCTLCMD;
 	}
@@ -2797,9 +2767,7 @@
 
 static struct pcmcia_driver mgslpc_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "synclink_cs",
-	},
+	.name		= "synclink_cs",
 	.probe		= mgslpc_probe,
 	.remove		= mgslpc_detach,
 	.id_table	= mgslpc_ids,
@@ -2835,8 +2803,6 @@
 {
 	int rc;
 
-	printk("Unloading %s: version %s\n", driver_name, driver_version);
-
 	while(mgslpc_device_list)
 		mgslpc_remove_device(mgslpc_device_list);
 
@@ -2859,8 +2825,6 @@
 	    BREAKPOINT();
     }
 
-    printk("%s %s\n", driver_name, driver_version);
-
     if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0)
 	    return rc;
 
@@ -4127,6 +4091,8 @@
 	if (cmd != SIOCWANDEV)
 		return hdlc_ioctl(dev, ifr, cmd);
 
+	memset(&new_line, 0, size);
+
 	switch(ifr->ifr_settings.type) {
 	case IF_GET_IFACE: /* return current sync_serial_settings */
 
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 02abfdd..723152d 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -67,7 +67,7 @@
 #include <linux/slab.h>
 #include <linux/major.h>
 #include <linux/ppdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/uaccess.h>
 
 #define PP_VERSION "ppdev: user-space parallel port driver"
@@ -97,6 +97,7 @@
 /* ROUND_UP macro from fs/select.c */
 #define ROUND_UP(x,y) (((x)+(y)-1)/(y))
 
+static DEFINE_MUTEX(pp_do_mutex);
 static inline void pp_enable_irq (struct pp_struct *pp)
 {
 	struct parport *port = pp->pdev->port;
@@ -630,9 +631,9 @@
 static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&pp_do_mutex);
 	ret = pp_do_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&pp_do_mutex);
 	return ret;
 }
 
@@ -641,7 +642,6 @@
 	unsigned int minor = iminor(inode);
 	struct pp_struct *pp;
 
-	cycle_kernel_lock();
 	if (minor >= PARPORT_MAX)
 		return -ENXIO;
 
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index c350d01..923a485 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -676,7 +676,9 @@
 
 	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
 
-	tty_add_file(tty, filp);
+	retval = tty_add_file(tty, filp);
+	if (retval)
+		goto out;
 
 	retval = devpts_pty_new(inode, tty->link);
 	if (retval)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index caef35a..5a1aa64 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1165,6 +1165,7 @@
 	.poll  = random_poll,
 	.unlocked_ioctl = random_ioctl,
 	.fasync = random_fasync,
+	.llseek = noop_llseek,
 };
 
 const struct file_operations urandom_fops = {
@@ -1172,6 +1173,7 @@
 	.write = random_write,
 	.unlocked_ioctl = random_ioctl,
 	.fasync = random_fasync,
+	.llseek = noop_llseek,
 };
 
 /***************************************************************
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index b38942f..bfe25ea 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -19,8 +19,8 @@
 #include <linux/cdev.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/gfp.h>
+#include <linux/compat.h>
 
 #include <asm/uaccess.h>
 
@@ -55,7 +55,6 @@
 		return 0;
 	}
 
-	lock_kernel();
 	mutex_lock(&raw_mutex);
 
 	/*
@@ -82,7 +81,6 @@
 			bdev->bd_inode->i_mapping;
 	filp->private_data = bdev;
 	mutex_unlock(&raw_mutex);
-	unlock_kernel();
 	return 0;
 
 out2:
@@ -91,7 +89,6 @@
 	blkdev_put(bdev, filp->f_mode);
 out:
 	mutex_unlock(&raw_mutex);
-	unlock_kernel();
 	return err;
 }
 
@@ -125,20 +122,84 @@
 raw_ioctl(struct file *filp, unsigned int command, unsigned long arg)
 {
 	struct block_device *bdev = filp->private_data;
-	int ret;
-
-	lock_kernel();
-	ret = blkdev_ioctl(bdev, 0, command, arg);
-	unlock_kernel();
-
-	return ret;
+	return blkdev_ioctl(bdev, 0, command, arg);
 }
 
-static void bind_device(struct raw_config_request *rq)
+static int bind_set(int number, u64 major, u64 minor)
 {
-	device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
-	device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), NULL,
-		      "raw%d", rq->raw_minor);
+	dev_t dev = MKDEV(major, minor);
+	struct raw_device_data *rawdev;
+	int err = 0;
+
+	if (number <= 0 || number >= MAX_RAW_MINORS)
+		return -EINVAL;
+
+	if (MAJOR(dev) != major || MINOR(dev) != minor)
+		return -EINVAL;
+
+	rawdev = &raw_devices[number];
+
+	/*
+	 * This is like making block devices, so demand the
+	 * same capability
+	 */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	/*
+	 * For now, we don't need to check that the underlying
+	 * block device is present or not: we can do that when
+	 * the raw device is opened.  Just check that the
+	 * major/minor numbers make sense.
+	 */
+
+	if (MAJOR(dev) == 0 && dev != 0)
+		return -EINVAL;
+
+	mutex_lock(&raw_mutex);
+	if (rawdev->inuse) {
+		mutex_unlock(&raw_mutex);
+		return -EBUSY;
+	}
+	if (rawdev->binding) {
+		bdput(rawdev->binding);
+		module_put(THIS_MODULE);
+	}
+	if (!dev) {
+		/* unbind */
+		rawdev->binding = NULL;
+		device_destroy(raw_class, MKDEV(RAW_MAJOR, number));
+	} else {
+		rawdev->binding = bdget(dev);
+		if (rawdev->binding == NULL) {
+			err = -ENOMEM;
+		} else {
+			dev_t raw = MKDEV(RAW_MAJOR, number);
+			__module_get(THIS_MODULE);
+			device_destroy(raw_class, raw);
+			device_create(raw_class, NULL, raw, NULL,
+				      "raw%d", number);
+		}
+	}
+	mutex_unlock(&raw_mutex);
+	return err;
+}
+
+static int bind_get(int number, dev_t *dev)
+{
+	struct raw_device_data *rawdev;
+	struct block_device *bdev;
+
+	if (number <= 0 || number >= MAX_RAW_MINORS)
+		return -EINVAL;
+
+	rawdev = &raw_devices[number];
+
+	mutex_lock(&raw_mutex);
+	bdev = rawdev->binding;
+	*dev = bdev ? bdev->bd_dev : 0;
+	mutex_unlock(&raw_mutex);
+	return 0;
 }
 
 /*
@@ -149,106 +210,79 @@
 			  unsigned long arg)
 {
 	struct raw_config_request rq;
-	struct raw_device_data *rawdev;
-	int err = 0;
+	dev_t dev;
+	int err;
 
-	lock_kernel();
 	switch (command) {
 	case RAW_SETBIND:
+		if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
+			return -EFAULT;
+
+		return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
+
 	case RAW_GETBIND:
+		if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
+			return -EFAULT;
 
-		/* First, find out which raw minor we want */
+		err = bind_get(rq.raw_minor, &dev);
+		if (err)
+			return err;
 
-		if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) {
-			err = -EFAULT;
-			goto out;
-		}
+		rq.block_major = MAJOR(dev);
+		rq.block_minor = MINOR(dev);
 
-		if (rq.raw_minor <= 0 || rq.raw_minor >= MAX_RAW_MINORS) {
-			err = -EINVAL;
-			goto out;
-		}
-		rawdev = &raw_devices[rq.raw_minor];
+		if (copy_to_user((void __user *)arg, &rq, sizeof(rq)))
+			return -EFAULT;
 
-		if (command == RAW_SETBIND) {
-			dev_t dev;
-
-			/*
-			 * This is like making block devices, so demand the
-			 * same capability
-			 */
-			if (!capable(CAP_SYS_ADMIN)) {
-				err = -EPERM;
-				goto out;
-			}
-
-			/*
-			 * For now, we don't need to check that the underlying
-			 * block device is present or not: we can do that when
-			 * the raw device is opened.  Just check that the
-			 * major/minor numbers make sense.
-			 */
-
-			dev = MKDEV(rq.block_major, rq.block_minor);
-			if ((rq.block_major == 0 && rq.block_minor != 0) ||
-					MAJOR(dev) != rq.block_major ||
-					MINOR(dev) != rq.block_minor) {
-				err = -EINVAL;
-				goto out;
-			}
-
-			mutex_lock(&raw_mutex);
-			if (rawdev->inuse) {
-				mutex_unlock(&raw_mutex);
-				err = -EBUSY;
-				goto out;
-			}
-			if (rawdev->binding) {
-				bdput(rawdev->binding);
-				module_put(THIS_MODULE);
-			}
-			if (rq.block_major == 0 && rq.block_minor == 0) {
-				/* unbind */
-				rawdev->binding = NULL;
-				device_destroy(raw_class,
-						MKDEV(RAW_MAJOR, rq.raw_minor));
-			} else {
-				rawdev->binding = bdget(dev);
-				if (rawdev->binding == NULL)
-					err = -ENOMEM;
-				else {
-					__module_get(THIS_MODULE);
-					bind_device(&rq);
-				}
-			}
-			mutex_unlock(&raw_mutex);
-		} else {
-			struct block_device *bdev;
-
-			mutex_lock(&raw_mutex);
-			bdev = rawdev->binding;
-			if (bdev) {
-				rq.block_major = MAJOR(bdev->bd_dev);
-				rq.block_minor = MINOR(bdev->bd_dev);
-			} else {
-				rq.block_major = rq.block_minor = 0;
-			}
-			mutex_unlock(&raw_mutex);
-			if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) {
-				err = -EFAULT;
-				goto out;
-			}
-		}
-		break;
-	default:
-		err = -EINVAL;
-		break;
+		return 0;
 	}
-out:
-	unlock_kernel();
-	return err;
+
+	return -EINVAL;
 }
 
+#ifdef CONFIG_COMPAT
+struct raw32_config_request {
+	compat_int_t	raw_minor;
+	compat_u64	block_major;
+	compat_u64	block_minor;
+};
+
+static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	struct raw32_config_request __user *user_req = compat_ptr(arg);
+	struct raw32_config_request rq;
+	dev_t dev;
+	int err = 0;
+
+	switch (cmd) {
+	case RAW_SETBIND:
+		if (copy_from_user(&rq, user_req, sizeof(rq)))
+			return -EFAULT;
+
+		return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
+
+	case RAW_GETBIND:
+		if (copy_from_user(&rq, user_req, sizeof(rq)))
+			return -EFAULT;
+
+		err = bind_get(rq.raw_minor, &dev);
+		if (err)
+			return err;
+
+		rq.block_major = MAJOR(dev);
+		rq.block_minor = MINOR(dev);
+
+		if (copy_to_user(user_req, &rq, sizeof(rq)))
+			return -EFAULT;
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+#endif
+
 static const struct file_operations raw_fops = {
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
@@ -258,13 +292,18 @@
 	.open		= raw_open,
 	.release	= raw_release,
 	.unlocked_ioctl = raw_ioctl,
+	.llseek		= default_llseek,
 	.owner		= THIS_MODULE,
 };
 
 static const struct file_operations raw_ctl_fops = {
 	.unlocked_ioctl = raw_ctl_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= raw_ctl_compat_ioctl,
+#endif
 	.open		= raw_open,
 	.owner		= THIS_MODULE,
+	.llseek		= noop_llseek,
 };
 
 static struct cdev raw_cdev;
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index d58c2eb..5e33293 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -44,7 +44,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 
@@ -122,6 +122,7 @@
 
 
 /* These constants are derived from SCO Source */
+static DEFINE_MUTEX(rio_fw_mutex);
 static struct Conf
  RIOConf = {
 	/* locator */ "RIO Config here",
@@ -241,6 +242,7 @@
 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 = {
@@ -566,9 +568,9 @@
 	func_enter();
 
 	/* The "dev" argument isn't used. */
-	lock_kernel();
+	mutex_lock(&rio_fw_mutex);
 	rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
-	unlock_kernel();
+	mutex_unlock(&rio_fw_mutex);
 
 	func_exit();
 	return rc;
diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c
index 99e5272..0bc135b 100644
--- a/drivers/char/scx200_gpio.c
+++ b/drivers/char/scx200_gpio.c
@@ -67,6 +67,7 @@
 	.read    = nsc_gpio_read,
 	.open    = scx200_gpio_open,
 	.release = scx200_gpio_release,
+	.llseek  = no_llseek,
 };
 
 static struct cdev scx200_gpio_cdev;  /* use 1 cdev for all pins */
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 32b74de..5816b39 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -21,7 +21,7 @@
 #include <linux/poll.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/sn/io.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/module.h>
@@ -34,6 +34,7 @@
 #define SCDRV_BUFSZ	2048
 #define SCDRV_TIMEOUT	1000
 
+static DEFINE_MUTEX(scdrv_mutex);
 static irqreturn_t
 scdrv_interrupt(int irq, void *subch_data)
 {
@@ -105,7 +106,7 @@
 	file->private_data = sd;
 
 	/* hook this subchannel up to the system controller interrupt */
-	lock_kernel();
+	mutex_lock(&scdrv_mutex);
 	rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
 			 IRQF_SHARED | IRQF_DISABLED,
 			 SYSCTL_BASENAME, sd);
@@ -113,10 +114,10 @@
 		ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
 		kfree(sd);
 		printk("%s: irq request failed (%d)\n", __func__, rv);
-		unlock_kernel();
+		mutex_unlock(&scdrv_mutex);
 		return -EBUSY;
 	}
-	unlock_kernel();
+	mutex_unlock(&scdrv_mutex);
 	return 0;
 }
 
@@ -357,6 +358,7 @@
 	.poll =		scdrv_poll,
 	.open =		scdrv_open,
 	.release =	scdrv_release,
+	.llseek =	noop_llseek,
 };
 
 static struct class *snsc_class;
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index f2167f8..8ef1649 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -608,6 +608,7 @@
 static const struct file_operations	stl_fsiomem = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= stl_memioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct class *stallion_class;
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 5b24db4..e53f168 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -397,6 +397,7 @@
 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 = {
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index a2a5800..3a6824f 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2925,6 +2925,38 @@
 	
 }	/* 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:
@@ -2949,7 +2981,7 @@
 		return -ENODEV;
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	    (cmd != TIOCMIWAIT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -2959,11 +2991,7 @@
 
 static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
 {
-	int error;
-	struct mgsl_icount cnow;	/* kernel counter temps */
 	void __user *argp = (void __user *)arg;
-	struct serial_icounter_struct __user *p_cuser;	/* user space */
-	unsigned long flags;
 	
 	switch (cmd) {
 		case MGSL_IOCGPARAMS:
@@ -2992,40 +3020,6 @@
 		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.
-		 */
-		case TIOCGICOUNT:
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			cnow = info->icount;
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			p_cuser = argp;
-			PUT_USER(error,cnow.cts, &p_cuser->cts);
-			if (error) return error;
-			PUT_USER(error,cnow.dsr, &p_cuser->dsr);
-			if (error) return error;
-			PUT_USER(error,cnow.rng, &p_cuser->rng);
-			if (error) return error;
-			PUT_USER(error,cnow.dcd, &p_cuser->dcd);
-			if (error) return error;
-			PUT_USER(error,cnow.rx, &p_cuser->rx);
-			if (error) return error;
-			PUT_USER(error,cnow.tx, &p_cuser->tx);
-			if (error) return error;
-			PUT_USER(error,cnow.frame, &p_cuser->frame);
-			if (error) return error;
-			PUT_USER(error,cnow.overrun, &p_cuser->overrun);
-			if (error) return error;
-			PUT_USER(error,cnow.parity, &p_cuser->parity);
-			if (error) return error;
-			PUT_USER(error,cnow.brk, &p_cuser->brk);
-			if (error) return error;
-			PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
-			if (error) return error;
-			return 0;
 		default:
 			return -ENOIOCTLCMD;
 	}
@@ -4328,6 +4322,7 @@
 	.hangup = mgsl_hangup,
 	.tiocmget = tiocmget,
 	.tiocmset = tiocmset,
+	.get_icount = msgl_get_icount,
 	.proc_fops = &mgsl_proc_fops,
 };
 
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index e63b830..1746d91 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1032,9 +1032,6 @@
 		 unsigned int cmd, unsigned long arg)
 {
 	struct slgt_info *info = tty->driver_data;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	struct serial_icounter_struct __user *p_cuser;	/* user space */
-	unsigned long flags;
 	void __user *argp = (void __user *)arg;
 	int ret;
 
@@ -1043,7 +1040,7 @@
 	DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	    (cmd != TIOCMIWAIT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -1053,24 +1050,6 @@
 		return wait_mgsl_event(info, argp);
 	case TIOCMIWAIT:
 		return modem_input_wait(info,(int)arg);
-	case TIOCGICOUNT:
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		spin_unlock_irqrestore(&info->lock,flags);
-		p_cuser = argp;
-		if (put_user(cnow.cts, &p_cuser->cts) ||
-		    put_user(cnow.dsr, &p_cuser->dsr) ||
-		    put_user(cnow.rng, &p_cuser->rng) ||
-		    put_user(cnow.dcd, &p_cuser->dcd) ||
-		    put_user(cnow.rx, &p_cuser->rx) ||
-		    put_user(cnow.tx, &p_cuser->tx) ||
-		    put_user(cnow.frame, &p_cuser->frame) ||
-		    put_user(cnow.overrun, &p_cuser->overrun) ||
-		    put_user(cnow.parity, &p_cuser->parity) ||
-		    put_user(cnow.brk, &p_cuser->brk) ||
-		    put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
-			return -EFAULT;
-		return 0;
 	case MGSL_IOCSGPIO:
 		return set_gpio(info, argp);
 	case MGSL_IOCGGPIO:
@@ -1117,6 +1096,33 @@
 	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
  */
@@ -1206,10 +1212,6 @@
 	case MGSL_IOCSGPIO:
 	case MGSL_IOCGGPIO:
 	case MGSL_IOCWAITGPIO:
-	case TIOCGICOUNT:
-		rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
-		break;
-
 	case MGSL_IOCSTXIDLE:
 	case MGSL_IOCTXENABLE:
 	case MGSL_IOCRXENABLE:
@@ -3642,6 +3644,7 @@
 	.hangup = hangup,
 	.tiocmget = tiocmget,
 	.tiocmset = tiocmset,
+	.get_icount = get_icount,
 	.proc_fops = &synclink_gt_proc_fops,
 };
 
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index e56caf7..2f9eb4b 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1258,10 +1258,6 @@
 		 unsigned int cmd, unsigned long arg)
 {
 	SLMP_INFO *info = tty->driver_data;
-	int error;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	struct serial_icounter_struct __user *p_cuser;	/* user space */
-	unsigned long flags;
 	void __user *argp = (void __user *)arg;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1272,7 +1268,7 @@
 		return -ENODEV;
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	    (cmd != TIOCMIWAIT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -1310,40 +1306,38 @@
 		 * NB: both 1->0 and 0->1 transitions are counted except for
 		 *     RI where only 0->1 is counted.
 		 */
-	case TIOCGICOUNT:
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		spin_unlock_irqrestore(&info->lock,flags);
-		p_cuser = argp;
-		PUT_USER(error,cnow.cts, &p_cuser->cts);
-		if (error) return error;
-		PUT_USER(error,cnow.dsr, &p_cuser->dsr);
-		if (error) return error;
-		PUT_USER(error,cnow.rng, &p_cuser->rng);
-		if (error) return error;
-		PUT_USER(error,cnow.dcd, &p_cuser->dcd);
-		if (error) return error;
-		PUT_USER(error,cnow.rx, &p_cuser->rx);
-		if (error) return error;
-		PUT_USER(error,cnow.tx, &p_cuser->tx);
-		if (error) return error;
-		PUT_USER(error,cnow.frame, &p_cuser->frame);
-		if (error) return error;
-		PUT_USER(error,cnow.overrun, &p_cuser->overrun);
-		if (error) return error;
-		PUT_USER(error,cnow.parity, &p_cuser->parity);
-		if (error) return error;
-		PUT_USER(error,cnow.brk, &p_cuser->brk);
-		if (error) return error;
-		PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
-		if (error) return error;
-		return 0;
 	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....
  */
@@ -3909,6 +3903,7 @@
 	.hangup = hangup,
 	.tiocmget = tiocmget,
 	.tiocmset = tiocmset,
+	.get_icount = get_icount,
 	.proc_fops = &synclinkmp_proc_fops,
 };
 
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index ef31bb8..f3019f5 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -772,6 +772,7 @@
 
 static const struct file_operations proc_sysrq_trigger_operations = {
 	.write		= write_sysrq_trigger,
+	.llseek		= noop_llseek,
 };
 
 static void sysrq_init_procfs(void)
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index cad4eb6..ad26418 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -261,6 +261,7 @@
 	.write		= tanbac_tb0219_write,
 	.open		= tanbac_tb0219_open,
 	.release	= tanbac_tb0219_release,
+	.llseek		= no_llseek,
 };
 
 static void tb0219_restart(char *command)
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 80ea6bc..0c964cd 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -37,7 +37,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/timer.h>
 #include <linux/sysfs.h>
 #include <linux/device.h>
@@ -206,7 +206,7 @@
 {
 	int result;
 
-	lock_kernel();
+	mutex_lock(&tlclk_mutex);
 	if (test_and_set_bit(0, &useflags)) {
 		result = -EBUSY;
 		/* this legacy device is always one per system and it doesn't
@@ -229,7 +229,7 @@
 		inb(TLCLK_REG6);	/* Clear interrupt events */
 
 out:
-	unlock_kernel();
+	mutex_unlock(&tlclk_mutex);
 	return result;
 }
 
@@ -267,6 +267,7 @@
 	.read = tlclk_read,
 	.open = tlclk_open,
 	.release = tlclk_release,
+	.llseek = noop_llseek,
 
 };
 
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index f8bc79f..014c9d9 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -68,7 +68,7 @@
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/toshiba.h>
 
 #define TOSH_MINOR_DEV 181
@@ -78,6 +78,7 @@
 MODULE_DESCRIPTION("Toshiba laptop SMM driver");
 MODULE_SUPPORTED_DEVICE("toshiba");
 
+static DEFINE_MUTEX(tosh_mutex);
 static int tosh_fn;
 module_param_named(fn, tosh_fn, int, 0);
 MODULE_PARM_DESC(fn, "User specified Fn key detection port");
@@ -95,6 +96,7 @@
 static const struct file_operations tosh_fops = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= tosh_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice tosh_device = {
@@ -274,16 +276,16 @@
 				return -EINVAL;
 
 			/* do we need to emulate the fan ? */
-			lock_kernel();
+			mutex_lock(&tosh_mutex);
 			if (tosh_fan==1) {
 				if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) {
 					err = tosh_emulate_fan(&regs);
-					unlock_kernel();
+					mutex_unlock(&tosh_mutex);
 					break;
 				}
 			}
 			err = tosh_smm(&regs);
-			unlock_kernel();
+			mutex_unlock(&tosh_mutex);
 			break;
 		default:
 			return -EINVAL;
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 05ad4a1..7c41335 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -47,6 +47,16 @@
 #define TPM_MAX_PROTECTED_ORDINAL 12
 #define TPM_PROTECTED_ORDINAL_MASK 0xFF
 
+/*
+ * Bug workaround - some TPM's don't flush the most
+ * recently changed pcr on suspend, so force the flush
+ * with an extend to the selected _unused_ non-volatile pcr.
+ */
+static int tpm_suspend_pcr;
+module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);
+MODULE_PARM_DESC(suspend_pcr,
+		 "PCR to use for dummy writes to faciltate flush on suspend.");
+
 static LIST_HEAD(tpm_chip_list);
 static DEFINE_SPINLOCK(driver_lock);
 static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
@@ -1077,18 +1087,6 @@
 	.ordinal = TPM_ORD_SAVESTATE
 };
 
-/* Bug workaround - some TPM's don't flush the most
- * recently changed pcr on suspend, so force the flush
- * with an extend to the selected _unused_ non-volatile pcr.
- */
-static int tpm_suspend_pcr;
-static int __init tpm_suspend_setup(char *str)
-{
-	get_option(&str, &tpm_suspend_pcr);
-	return 1;
-}
-__setup("tpm_suspend_pcr=", tpm_suspend_setup);
-
 /*
  * We are about to suspend. Save the TPM state
  * so that it can be restored.
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 613c852..c05c5af 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -96,6 +96,7 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
+#include <linux/serial.h>
 
 #include <linux/uaccess.h>
 #include <asm/system.h>
@@ -183,6 +184,8 @@
 
 void free_tty_struct(struct tty_struct *tty)
 {
+	if (tty->dev)
+		put_device(tty->dev);
 	kfree(tty->write_buf);
 	tty_buffer_free_all(tty);
 	kfree(tty);
@@ -194,12 +197,13 @@
 }
 
 /* Associate a new file with the tty structure */
-void tty_add_file(struct tty_struct *tty, struct file *file)
+int tty_add_file(struct tty_struct *tty, struct file *file)
 {
 	struct tty_file_private *priv;
 
-	/* XXX: must implement proper error handling in callers */
-	priv = kmalloc(sizeof(*priv), GFP_KERNEL|__GFP_NOFAIL);
+	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
 
 	priv->tty = tty;
 	priv->file = file;
@@ -208,6 +212,8 @@
 	spin_lock(&tty_files_lock);
 	list_add(&priv->list, &tty->tty_files);
 	spin_unlock(&tty_files_lock);
+
+	return 0;
 }
 
 /* Delete file from its tty */
@@ -1875,7 +1881,11 @@
 		return PTR_ERR(tty);
 	}
 
-	tty_add_file(tty, filp);
+	retval = tty_add_file(tty, filp);
+	if (retval) {
+		tty_unlock();
+		return retval;
+	}
 
 	check_tty_count(tty, "tty_open");
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2502,6 +2512,20 @@
 	return tty->ops->tiocmset(tty, file, set, clear);
 }
 
+static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
+{
+	int retval = -EINVAL;
+	struct serial_icounter_struct icount;
+	memset(&icount, 0, sizeof(icount));
+	if (tty->ops->get_icount)
+		retval = tty->ops->get_icount(tty, &icount);
+	if (retval != 0)
+		return retval;
+	if (copy_to_user(arg, &icount, sizeof(icount)))
+		return -EFAULT;
+	return 0;
+}
+
 struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
 {
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2622,6 +2646,12 @@
 	case TIOCMBIC:
 	case TIOCMBIS:
 		return tty_tiocmset(tty, file, cmd, p);
+	case TIOCGICOUNT:
+		retval = tty_tiocgicount(tty, p);
+		/* For the moment allow fall through to the old method */
+        	if (retval != -EINVAL)
+			return retval;
+		break;
 	case TCFLSH:
 		switch (arg) {
 		case TCIFLUSH:
@@ -2783,6 +2813,20 @@
 
 EXPORT_SYMBOL(do_SAK);
 
+static int dev_match_devt(struct device *dev, void *data)
+{
+	dev_t *devt = data;
+	return dev->devt == *devt;
+}
+
+/* Must put_device() after it's unused! */
+static struct device *tty_get_device(struct tty_struct *tty)
+{
+	dev_t devt = tty_devnum(tty);
+	return class_find_device(tty_class, NULL, &devt, dev_match_devt);
+}
+
+
 /**
  *	initialize_tty_struct
  *	@tty: tty to initialize
@@ -2823,6 +2867,7 @@
 	tty->ops = driver->ops;
 	tty->index = idx;
 	tty_line_name(driver, idx, tty->name);
+	tty->dev = tty_get_device(tty);
 }
 
 /**
@@ -2980,6 +3025,7 @@
 	int i;
 	dev_t dev;
 	void **p = NULL;
+	struct device *d;
 
 	if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
 		p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
@@ -3027,12 +3073,31 @@
 	mutex_unlock(&tty_mutex);
 
 	if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
-		for (i = 0; i < driver->num; i++)
-		    tty_register_device(driver, i, NULL);
+		for (i = 0; i < driver->num; i++) {
+			d = tty_register_device(driver, i, NULL);
+			if (IS_ERR(d)) {
+				error = PTR_ERR(d);
+				goto err;
+			}
+		}
 	}
 	proc_tty_register_driver(driver);
 	driver->flags |= TTY_DRIVER_INSTALLED;
 	return 0;
+
+err:
+	for (i--; i >= 0; i--)
+		tty_unregister_device(driver, i);
+
+	mutex_lock(&tty_mutex);
+	list_del(&driver->tty_drivers);
+	mutex_unlock(&tty_mutex);
+
+	unregister_chrdev_region(dev, driver->num);
+	driver->ttys = NULL;
+	driver->termios = NULL;
+	kfree(p);
+	return error;
 }
 
 EXPORT_SYMBOL(tty_register_driver);
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
new file mode 100644
index 0000000..c40c161
--- /dev/null
+++ b/drivers/char/ttyprintk.c
@@ -0,0 +1,225 @@
+/*
+ *  linux/drivers/char/ttyprintk.c
+ *
+ *  Copyright (C) 2010  Samo Pogacnik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+/*
+ * This pseudo device allows user to make printk messages. It is possible
+ * to store "console" messages inline with kernel messages for better analyses
+ * of the boot process, for example.
+ */
+
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+
+struct ttyprintk_port {
+	struct tty_port port;
+	struct mutex port_write_mutex;
+};
+
+static struct ttyprintk_port tpk_port;
+
+/*
+ * Our simple preformatting supports transparent output of (time-stamped)
+ * printk messages (also suitable for logging service):
+ * - any cr is replaced by nl
+ * - adds a ttyprintk source tag in front of each line
+ * - too long message is fragmeted, with '\'nl between fragments
+ * - TPK_STR_SIZE isn't really the write_room limiting factor, bcause
+ *   it is emptied on the fly during preformatting.
+ */
+#define TPK_STR_SIZE 508 /* should be bigger then max expected line length */
+#define TPK_MAX_ROOM 4096 /* we could assume 4K for instance */
+static const char *tpk_tag = "[U] "; /* U for User */
+static int tpk_curr;
+
+static int tpk_printk(const unsigned char *buf, int count)
+{
+	static char tmp[TPK_STR_SIZE + 4];
+	int i = tpk_curr;
+
+	if (buf == NULL) {
+		/* flush tmp[] */
+		if (tpk_curr > 0) {
+			/* non nl or cr terminated message - add nl */
+			tmp[tpk_curr + 0] = '\n';
+			tmp[tpk_curr + 1] = '\0';
+			printk(KERN_INFO "%s%s", tpk_tag, tmp);
+			tpk_curr = 0;
+		}
+		return i;
+	}
+
+	for (i = 0; i < count; i++) {
+		tmp[tpk_curr] = buf[i];
+		if (tpk_curr < TPK_STR_SIZE) {
+			switch (buf[i]) {
+			case '\r':
+				/* replace cr with nl */
+				tmp[tpk_curr + 0] = '\n';
+				tmp[tpk_curr + 1] = '\0';
+				printk(KERN_INFO "%s%s", tpk_tag, tmp);
+				tpk_curr = 0;
+				if (buf[i + 1] == '\n')
+					i++;
+				break;
+			case '\n':
+				tmp[tpk_curr + 1] = '\0';
+				printk(KERN_INFO "%s%s", tpk_tag, tmp);
+				tpk_curr = 0;
+				break;
+			default:
+				tpk_curr++;
+			}
+		} else {
+			/* end of tmp buffer reached: cut the message in two */
+			tmp[tpk_curr + 1] = '\\';
+			tmp[tpk_curr + 2] = '\n';
+			tmp[tpk_curr + 3] = '\0';
+			printk(KERN_INFO "%s%s", tpk_tag, tmp);
+			tpk_curr = 0;
+		}
+	}
+
+	return count;
+}
+
+/*
+ * TTY operations open function.
+ */
+static int tpk_open(struct tty_struct *tty, struct file *filp)
+{
+	tty->driver_data = &tpk_port;
+
+	return tty_port_open(&tpk_port.port, tty, filp);
+}
+
+/*
+ * TTY operations close function.
+ */
+static void tpk_close(struct tty_struct *tty, struct file *filp)
+{
+	struct ttyprintk_port *tpkp = tty->driver_data;
+
+	mutex_lock(&tpkp->port_write_mutex);
+	/* flush tpk_printk buffer */
+	tpk_printk(NULL, 0);
+	mutex_unlock(&tpkp->port_write_mutex);
+
+	tty_port_close(&tpkp->port, tty, filp);
+}
+
+/*
+ * TTY operations write function.
+ */
+static int tpk_write(struct tty_struct *tty,
+		const unsigned char *buf, int count)
+{
+	struct ttyprintk_port *tpkp = tty->driver_data;
+	int ret;
+
+
+	/* exclusive use of tpk_printk within this tty */
+	mutex_lock(&tpkp->port_write_mutex);
+	ret = tpk_printk(buf, count);
+	mutex_unlock(&tpkp->port_write_mutex);
+
+	return ret;
+}
+
+/*
+ * TTY operations write_room function.
+ */
+static int tpk_write_room(struct tty_struct *tty)
+{
+	return TPK_MAX_ROOM;
+}
+
+/*
+ * TTY operations ioctl function.
+ */
+static int tpk_ioctl(struct tty_struct *tty, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	struct ttyprintk_port *tpkp = tty->driver_data;
+
+	if (!tpkp)
+		return -EINVAL;
+
+	switch (cmd) {
+	/* Stop TIOCCONS */
+	case TIOCCONS:
+		return -EOPNOTSUPP;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static const struct tty_operations ttyprintk_ops = {
+	.open = tpk_open,
+	.close = tpk_close,
+	.write = tpk_write,
+	.write_room = tpk_write_room,
+	.ioctl = tpk_ioctl,
+};
+
+struct tty_port_operations null_ops = { };
+
+static struct tty_driver *ttyprintk_driver;
+
+static int __init ttyprintk_init(void)
+{
+	int ret = -ENOMEM;
+	void *rp;
+
+	ttyprintk_driver = alloc_tty_driver(1);
+	if (!ttyprintk_driver)
+		return ret;
+
+	ttyprintk_driver->owner = THIS_MODULE;
+	ttyprintk_driver->driver_name = "ttyprintk";
+	ttyprintk_driver->name = "ttyprintk";
+	ttyprintk_driver->major = TTYAUX_MAJOR;
+	ttyprintk_driver->minor_start = 3;
+	ttyprintk_driver->num = 1;
+	ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE;
+	ttyprintk_driver->init_termios = tty_std_termios;
+	ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
+	ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS |
+		TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	tty_set_operations(ttyprintk_driver, &ttyprintk_ops);
+
+	ret = tty_register_driver(ttyprintk_driver);
+	if (ret < 0) {
+		printk(KERN_ERR "Couldn't register ttyprintk driver\n");
+		goto error;
+	}
+
+	/* create our unnumbered device */
+	rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL,
+				ttyprintk_driver->name);
+	if (IS_ERR(rp)) {
+		printk(KERN_ERR "Couldn't create ttyprintk device\n");
+		ret = PTR_ERR(rp);
+		goto error;
+	}
+
+	tty_port_init(&tpk_port.port);
+	tpk_port.port.ops = &null_ops;
+	mutex_init(&tpk_port.port_write_mutex);
+
+	return 0;
+
+error:
+	put_tty_driver(ttyprintk_driver);
+	ttyprintk_driver = NULL;
+	return ret;
+}
+module_init(ttyprintk_init);
diff --git a/drivers/char/uv_mmtimer.c b/drivers/char/uv_mmtimer.c
index c7072ba..493b47a 100644
--- a/drivers/char/uv_mmtimer.c
+++ b/drivers/char/uv_mmtimer.c
@@ -52,6 +52,7 @@
 	.owner = THIS_MODULE,
 	.mmap =	uv_mmtimer_mmap,
 	.unlocked_ioctl = uv_mmtimer_ioctl,
+	.llseek = noop_llseek,
 };
 
 /**
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index bcce46c..273ab44 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -35,6 +35,12 @@
 #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>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/notifier.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -45,6 +51,86 @@
 #undef addr
 #define HEADER_SIZE	4
 
+struct vcs_poll_data {
+	struct notifier_block notifier;
+	unsigned int cons_num;
+	bool seen_last_update;
+	wait_queue_head_t waitq;
+	struct fasync_struct *fasync;
+};
+
+static int
+vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param)
+{
+	struct vt_notifier_param *param = _param;
+	struct vc_data *vc = param->vc;
+	struct vcs_poll_data *poll =
+		container_of(nb, struct vcs_poll_data, notifier);
+	int currcons = poll->cons_num;
+
+	if (code != VT_UPDATE)
+		return NOTIFY_DONE;
+
+	if (currcons == 0)
+		currcons = fg_console;
+	else
+		currcons--;
+	if (currcons != vc->vc_num)
+		return NOTIFY_DONE;
+
+	poll->seen_last_update = false;
+	wake_up_interruptible(&poll->waitq);
+	kill_fasync(&poll->fasync, SIGIO, POLL_IN);
+	return NOTIFY_OK;
+}
+
+static void
+vcs_poll_data_free(struct vcs_poll_data *poll)
+{
+	unregister_vt_notifier(&poll->notifier);
+	kfree(poll);
+}
+
+static struct vcs_poll_data *
+vcs_poll_data_get(struct file *file)
+{
+	struct vcs_poll_data *poll = file->private_data;
+
+	if (poll)
+		return poll;
+
+	poll = kzalloc(sizeof(*poll), GFP_KERNEL);
+	if (!poll)
+		return NULL;
+	poll->cons_num = iminor(file->f_path.dentry->d_inode) & 127;
+	init_waitqueue_head(&poll->waitq);
+	poll->notifier.notifier_call = vcs_notifier;
+	if (register_vt_notifier(&poll->notifier) != 0) {
+		kfree(poll);
+		return NULL;
+	}
+
+	/*
+	 * This code may be called either through ->poll() or ->fasync().
+	 * If we have two threads using the same file descriptor, they could
+	 * both enter this function, both notice that the structure hasn't
+	 * been allocated yet and go ahead allocating it in parallel, but
+	 * only one of them must survive and be shared otherwise we'd leak
+	 * memory with a dangling notifier callback.
+	 */
+	spin_lock(&file->f_lock);
+	if (!file->private_data) {
+		file->private_data = poll;
+	} else {
+		/* someone else raced ahead of us */
+		vcs_poll_data_free(poll);
+		poll = file->private_data;
+	}
+	spin_unlock(&file->f_lock);
+
+	return poll;
+}
+
 static int
 vcs_size(struct inode *inode)
 {
@@ -102,6 +188,7 @@
 	struct inode *inode = file->f_path.dentry->d_inode;
 	unsigned int currcons = iminor(inode);
 	struct vc_data *vc;
+	struct vcs_poll_data *poll;
 	long pos;
 	long viewed, attr, read;
 	int col, maxcol;
@@ -134,6 +221,9 @@
 	ret = -EINVAL;
 	if (pos < 0)
 		goto unlock_out;
+	poll = file->private_data;
+	if (count && poll)
+		poll->seen_last_update = true;
 	read = 0;
 	ret = 0;
 	while (count) {
@@ -448,6 +538,8 @@
 	}
 	*ppos += written;
 	ret = written;
+	if (written)
+		vcs_scr_updated(vc);
 
 unlock_out:
 	release_console_sem();
@@ -457,6 +549,37 @@
 	return ret;
 }
 
+static unsigned int
+vcs_poll(struct file *file, poll_table *wait)
+{
+	struct vcs_poll_data *poll = vcs_poll_data_get(file);
+	int ret = 0;
+
+	if (poll) {
+		poll_wait(file, &poll->waitq, wait);
+		if (!poll->seen_last_update)
+			ret = POLLIN | POLLRDNORM;
+	}
+	return ret;
+}
+
+static int
+vcs_fasync(int fd, struct file *file, int on)
+{
+	struct vcs_poll_data *poll = file->private_data;
+
+	if (!poll) {
+		/* don't allocate anything if all we want is disable fasync */
+		if (!on)
+			return 0;
+		poll = vcs_poll_data_get(file);
+		if (!poll)
+			return -ENOMEM;
+	}
+
+	return fasync_helper(fd, file, on, &poll->fasync);
+}
+
 static int
 vcs_open(struct inode *inode, struct file *filp)
 {
@@ -470,11 +593,23 @@
 	return ret;
 }
 
+static int vcs_release(struct inode *inode, struct file *file)
+{
+	struct vcs_poll_data *poll = file->private_data;
+
+	if (poll)
+		vcs_poll_data_free(poll);
+	return 0;
+}
+
 static const struct file_operations vcs_fops = {
 	.llseek		= vcs_lseek,
 	.read		= vcs_read,
 	.write		= vcs_write,
+	.poll		= vcs_poll,
+	.fasync		= vcs_fasync,
 	.open		= vcs_open,
+	.release	= vcs_release,
 };
 
 static struct class *vc_class;
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 42f7fa4..ad6e64a 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -46,7 +46,7 @@
 #include <linux/completion.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
@@ -64,6 +64,7 @@
 #define VIOTAPE_KERN_WARN	KERN_WARNING "viotape: "
 #define VIOTAPE_KERN_INFO	KERN_INFO "viotape: "
 
+static DEFINE_MUTEX(proc_viotape_mutex);
 static int viotape_numdev;
 
 /*
@@ -684,9 +685,9 @@
 {
 	long rc;
 
-	lock_kernel();
+	mutex_lock(&proc_viotape_mutex);
 	rc = viotap_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&proc_viotape_mutex);
 	return rc;
 }
 
@@ -700,7 +701,7 @@
 	if (op == NULL)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&proc_viotape_mutex);
 	get_dev_info(file->f_path.dentry->d_inode, &devi);
 
 	/* Note: We currently only support one mode! */
@@ -731,7 +732,7 @@
 
 free_op:
 	free_op_struct(op);
-	unlock_kernel();
+	mutex_unlock(&proc_viotape_mutex);
 	return ret;
 }
 
@@ -804,6 +805,7 @@
 	.unlocked_ioctl =	viotap_unlocked_ioctl,
 	.open =			viotap_open,
 	.release =		viotap_release,
+	.llseek = 		noop_llseek,
 };
 
 /* Handle interrupt events for tape */
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index c810481..6c1b676 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -48,6 +48,9 @@
 	/* Used for exporting per-port information to debugfs */
 	struct dentry *debugfs_dir;
 
+	/* List of all the devices we're handling */
+	struct list_head portdevs;
+
 	/* Number of devices this driver is handling */
 	unsigned int index;
 
@@ -108,6 +111,9 @@
  * ports for that device (vdev->priv).
  */
 struct ports_device {
+	/* Next portdev in the list, head is in the pdrvdata struct */
+	struct list_head list;
+
 	/*
 	 * Workqueue handlers where we process deferred work after
 	 * notification
@@ -178,15 +184,21 @@
 	struct console cons;
 
 	/* Each port associates with a separate char device */
-	struct cdev cdev;
+	struct cdev *cdev;
 	struct device *dev;
 
+	/* Reference-counting to handle port hot-unplugs and file operations */
+	struct kref kref;
+
 	/* A waitqueue for poll() or blocking read operations */
 	wait_queue_head_t waitqueue;
 
 	/* The 'name' of the port that we expose via sysfs properties */
 	char *name;
 
+	/* We can notify apps of host connect / disconnect events via SIGIO */
+	struct fasync_struct *async_queue;
+
 	/* The 'id' to identify the port with the Host */
 	u32 id;
 
@@ -221,6 +233,41 @@
 	return port;
 }
 
+static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev,
+						 dev_t dev)
+{
+	struct port *port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&portdev->ports_lock, flags);
+	list_for_each_entry(port, &portdev->ports, list)
+		if (port->cdev->dev == dev)
+			goto out;
+	port = NULL;
+out:
+	spin_unlock_irqrestore(&portdev->ports_lock, flags);
+
+	return port;
+}
+
+static struct port *find_port_by_devt(dev_t dev)
+{
+	struct ports_device *portdev;
+	struct port *port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdrvdata_lock, flags);
+	list_for_each_entry(portdev, &pdrvdata.portdevs, list) {
+		port = find_port_by_devt_in_portdev(portdev, dev);
+		if (port)
+			goto out;
+	}
+	port = NULL;
+out:
+	spin_unlock_irqrestore(&pdrvdata_lock, flags);
+	return port;
+}
+
 static struct port *find_port_by_id(struct ports_device *portdev, u32 id)
 {
 	struct port *port;
@@ -410,7 +457,10 @@
 static ssize_t send_control_msg(struct port *port, unsigned int event,
 				unsigned int value)
 {
-	return __send_control_msg(port->portdev, port->id, event, value);
+	/* Did the port get unplugged before userspace closed it? */
+	if (port->portdev)
+		return __send_control_msg(port->portdev, port->id, event, value);
+	return 0;
 }
 
 /* Callers must take the port->outvq_lock */
@@ -459,9 +509,12 @@
 
 	/*
 	 * Wait till the host acknowledges it pushed out the data we
-	 * sent.  This is done for ports in blocking mode or for data
-	 * from the hvc_console; the tty operations are performed with
-	 * spinlocks held so we can't sleep here.
+	 * sent.  This is done for data from the hvc_console; the tty
+	 * operations are performed with spinlocks held so we can't
+	 * sleep here.  An alternative would be to copy the data to a
+	 * buffer and relax the spinning requirement.  The downside is
+	 * we need to kmalloc a GFP_ATOMIC buffer each time the
+	 * console driver writes something out.
 	 */
 	while (!virtqueue_get_buf(out_vq, &len))
 		cpu_relax();
@@ -522,6 +575,10 @@
 /* The condition that must be true for polling to end */
 static bool will_read_block(struct port *port)
 {
+	if (!port->guest_connected) {
+		/* Port got hot-unplugged. Let's exit. */
+		return false;
+	}
 	return !port_has_data(port) && port->host_connected;
 }
 
@@ -572,6 +629,9 @@
 		if (ret < 0)
 			return ret;
 	}
+	/* Port got hot-unplugged. */
+	if (!port->guest_connected)
+		return -ENODEV;
 	/*
 	 * We could've received a disconnection message while we were
 	 * waiting for more data.
@@ -613,6 +673,9 @@
 		if (ret < 0)
 			return ret;
 	}
+	/* Port got hot-unplugged. */
+	if (!port->guest_connected)
+		return -ENODEV;
 
 	count = min((size_t)(32 * 1024), count);
 
@@ -626,6 +689,14 @@
 		goto free_buf;
 	}
 
+	/*
+	 * We now ask send_buf() to not spin for generic ports -- we
+	 * can re-use the same code path that non-blocking file
+	 * descriptors take for blocking file descriptors since the
+	 * wait is already done and we're certain the write will go
+	 * through to the host.
+	 */
+	nonblock = true;
 	ret = send_buf(port, buf, count, nonblock);
 
 	if (nonblock && ret > 0)
@@ -645,6 +716,10 @@
 	port = filp->private_data;
 	poll_wait(filp, &port->waitqueue, wait);
 
+	if (!port->guest_connected) {
+		/* Port got unplugged */
+		return POLLHUP;
+	}
 	ret = 0;
 	if (!will_read_block(port))
 		ret |= POLLIN | POLLRDNORM;
@@ -656,6 +731,8 @@
 	return ret;
 }
 
+static void remove_port(struct kref *kref);
+
 static int port_fops_release(struct inode *inode, struct file *filp)
 {
 	struct port *port;
@@ -676,6 +753,16 @@
 	reclaim_consumed_buffers(port);
 	spin_unlock_irq(&port->outvq_lock);
 
+	/*
+	 * Locks aren't necessary here as a port can't be opened after
+	 * unplug, and if a port isn't unplugged, a kref would already
+	 * exist for the port.  Plus, taking ports_lock here would
+	 * create a dependency on other locks taken by functions
+	 * inside remove_port if we're the last holder of the port,
+	 * creating many problems.
+	 */
+	kref_put(&port->kref, remove_port);
+
 	return 0;
 }
 
@@ -683,22 +770,31 @@
 {
 	struct cdev *cdev = inode->i_cdev;
 	struct port *port;
+	int ret;
 
-	port = container_of(cdev, struct port, cdev);
+	port = find_port_by_devt(cdev->dev);
 	filp->private_data = port;
 
+	/* Prevent against a port getting hot-unplugged at the same time */
+	spin_lock_irq(&port->portdev->ports_lock);
+	kref_get(&port->kref);
+	spin_unlock_irq(&port->portdev->ports_lock);
+
 	/*
 	 * Don't allow opening of console port devices -- that's done
 	 * via /dev/hvc
 	 */
-	if (is_console_port(port))
-		return -ENXIO;
+	if (is_console_port(port)) {
+		ret = -ENXIO;
+		goto out;
+	}
 
 	/* Allow only one process to open a particular port at a time */
 	spin_lock_irq(&port->inbuf_lock);
 	if (port->guest_connected) {
 		spin_unlock_irq(&port->inbuf_lock);
-		return -EMFILE;
+		ret = -EMFILE;
+		goto out;
 	}
 
 	port->guest_connected = true;
@@ -713,10 +809,23 @@
 	reclaim_consumed_buffers(port);
 	spin_unlock_irq(&port->outvq_lock);
 
+	nonseekable_open(inode, filp);
+
 	/* Notify host of port being opened */
 	send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1);
 
 	return 0;
+out:
+	kref_put(&port->kref, remove_port);
+	return ret;
+}
+
+static int port_fops_fasync(int fd, struct file *filp, int mode)
+{
+	struct port *port;
+
+	port = filp->private_data;
+	return fasync_helper(fd, filp, mode, &port->async_queue);
 }
 
 /*
@@ -732,6 +841,8 @@
 	.write = port_fops_write,
 	.poll  = port_fops_poll,
 	.release = port_fops_release,
+	.fasync = port_fops_fasync,
+	.llseek = no_llseek,
 };
 
 /*
@@ -990,6 +1101,12 @@
 	return nr_added_bufs;
 }
 
+static void send_sigio_to_port(struct port *port)
+{
+	if (port->async_queue && port->guest_connected)
+		kill_fasync(&port->async_queue, SIGIO, POLL_OUT);
+}
+
 static int add_port(struct ports_device *portdev, u32 id)
 {
 	char debugfs_name[16];
@@ -1004,6 +1121,7 @@
 		err = -ENOMEM;
 		goto fail;
 	}
+	kref_init(&port->kref);
 
 	port->portdev = portdev;
 	port->id = id;
@@ -1011,6 +1129,7 @@
 	port->name = NULL;
 	port->inbuf = NULL;
 	port->cons.hvc = NULL;
+	port->async_queue = NULL;
 
 	port->cons.ws.ws_row = port->cons.ws.ws_col = 0;
 
@@ -1021,14 +1140,20 @@
 	port->in_vq = portdev->in_vqs[port->id];
 	port->out_vq = portdev->out_vqs[port->id];
 
-	cdev_init(&port->cdev, &port_fops);
+	port->cdev = cdev_alloc();
+	if (!port->cdev) {
+		dev_err(&port->portdev->vdev->dev, "Error allocating cdev\n");
+		err = -ENOMEM;
+		goto free_port;
+	}
+	port->cdev->ops = &port_fops;
 
 	devt = MKDEV(portdev->chr_major, id);
-	err = cdev_add(&port->cdev, devt, 1);
+	err = cdev_add(port->cdev, devt, 1);
 	if (err < 0) {
 		dev_err(&port->portdev->vdev->dev,
 			"Error %d adding cdev for port %u\n", err, id);
-		goto free_port;
+		goto free_cdev;
 	}
 	port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev,
 				  devt, port, "vport%up%u",
@@ -1093,7 +1218,7 @@
 free_device:
 	device_destroy(pdrvdata.class, port->dev->devt);
 free_cdev:
-	cdev_del(&port->cdev);
+	cdev_del(port->cdev);
 free_port:
 	kfree(port);
 fail:
@@ -1102,21 +1227,45 @@
 	return err;
 }
 
-/* Remove all port-specific data. */
-static int remove_port(struct port *port)
+/* No users remain, remove all port-specific data. */
+static void remove_port(struct kref *kref)
+{
+	struct port *port;
+
+	port = container_of(kref, struct port, kref);
+
+	sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
+	device_destroy(pdrvdata.class, port->dev->devt);
+	cdev_del(port->cdev);
+
+	kfree(port->name);
+
+	debugfs_remove(port->debugfs_file);
+
+	kfree(port);
+}
+
+/*
+ * Port got unplugged.  Remove port from portdev's list and drop the
+ * kref reference.  If no userspace has this port opened, it will
+ * result in immediate removal the port.
+ */
+static void unplug_port(struct port *port)
 {
 	struct port_buffer *buf;
 
+	spin_lock_irq(&port->portdev->ports_lock);
+	list_del(&port->list);
+	spin_unlock_irq(&port->portdev->ports_lock);
+
 	if (port->guest_connected) {
 		port->guest_connected = false;
 		port->host_connected = false;
 		wake_up_interruptible(&port->waitqueue);
-		send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
-	}
 
-	spin_lock_irq(&port->portdev->ports_lock);
-	list_del(&port->list);
-	spin_unlock_irq(&port->portdev->ports_lock);
+		/* Let the app know the port is going down. */
+		send_sigio_to_port(port);
+	}
 
 	if (is_console_port(port)) {
 		spin_lock_irq(&pdrvdata_lock);
@@ -1135,9 +1284,6 @@
 		hvc_remove(port->cons.hvc);
 #endif
 	}
-	sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
-	device_destroy(pdrvdata.class, port->dev->devt);
-	cdev_del(&port->cdev);
 
 	/* Remove unused data this port might have received. */
 	discard_port_data(port);
@@ -1148,12 +1294,19 @@
 	while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
 		free_buf(buf);
 
-	kfree(port->name);
+	/*
+	 * We should just assume the device itself has gone off --
+	 * else a close on an open port later will try to send out a
+	 * control message.
+	 */
+	port->portdev = NULL;
 
-	debugfs_remove(port->debugfs_file);
-
-	kfree(port);
-	return 0;
+	/*
+	 * Locks around here are not necessary - a port can't be
+	 * opened after we removed the port struct from ports_list
+	 * above.
+	 */
+	kref_put(&port->kref, remove_port);
 }
 
 /* Any private messages that the Host and Guest want to share */
@@ -1192,7 +1345,7 @@
 		add_port(portdev, cpkt->id);
 		break;
 	case VIRTIO_CONSOLE_PORT_REMOVE:
-		remove_port(port);
+		unplug_port(port);
 		break;
 	case VIRTIO_CONSOLE_CONSOLE_PORT:
 		if (!cpkt->value)
@@ -1234,6 +1387,12 @@
 		spin_lock_irq(&port->outvq_lock);
 		reclaim_consumed_buffers(port);
 		spin_unlock_irq(&port->outvq_lock);
+
+		/*
+		 * If the guest is connected, it'll be interested in
+		 * knowing the host connection state changed.
+		 */
+		send_sigio_to_port(port);
 		break;
 	case VIRTIO_CONSOLE_PORT_NAME:
 		/*
@@ -1330,6 +1489,9 @@
 
 	wake_up_interruptible(&port->waitqueue);
 
+	/* Send a SIGIO indicating new data in case the process asked for it */
+	send_sigio_to_port(port);
+
 	if (is_console_port(port) && hvc_poll(port->cons.hvc))
 		hvc_kick();
 }
@@ -1566,6 +1728,10 @@
 		add_port(portdev, 0);
 	}
 
+	spin_lock_irq(&pdrvdata_lock);
+	list_add_tail(&portdev->list, &pdrvdata.portdevs);
+	spin_unlock_irq(&pdrvdata_lock);
+
 	__send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
 			   VIRTIO_CONSOLE_DEVICE_READY, 1);
 	return 0;
@@ -1589,23 +1755,41 @@
 {
 	struct ports_device *portdev;
 	struct port *port, *port2;
-	struct port_buffer *buf;
-	unsigned int len;
 
 	portdev = vdev->priv;
 
+	spin_lock_irq(&pdrvdata_lock);
+	list_del(&portdev->list);
+	spin_unlock_irq(&pdrvdata_lock);
+
+	/* Disable interrupts for vqs */
+	vdev->config->reset(vdev);
+	/* Finish up work that's lined up */
 	cancel_work_sync(&portdev->control_work);
 
 	list_for_each_entry_safe(port, port2, &portdev->ports, list)
-		remove_port(port);
+		unplug_port(port);
 
 	unregister_chrdev(portdev->chr_major, "virtio-portsdev");
 
-	while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
-		free_buf(buf);
+	/*
+	 * When yanking out a device, we immediately lose the
+	 * (device-side) queues.  So there's no point in keeping the
+	 * guest side around till we drop our final reference.  This
+	 * also means that any ports which are in an open state will
+	 * have to just stop using the port, as the vqs are going
+	 * away.
+	 */
+	if (use_multiport(portdev)) {
+		struct port_buffer *buf;
+		unsigned int len;
 
-	while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
-		free_buf(buf);
+		while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
+			free_buf(buf);
+
+		while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
+			free_buf(buf);
+	}
 
 	vdev->config->del_vqs(vdev);
 	kfree(portdev->in_vqs);
@@ -1652,6 +1836,7 @@
 			   PTR_ERR(pdrvdata.debugfs_dir));
 	}
 	INIT_LIST_HEAD(&pdrvdata.consoles);
+	INIT_LIST_HEAD(&pdrvdata.portdevs);
 
 	return register_virtio_driver(&virtio_console);
 }
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 281aada..a8ec48e 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -4182,6 +4182,11 @@
 	}
 }
 
+void vcs_scr_updated(struct vc_data *vc)
+{
+	notify_update(vc);
+}
+
 /*
  *	Visible symbols for modules
  */
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index b663d57..9f2272e 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -81,7 +81,6 @@
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/sysctl.h>
 #include <linux/fs.h>
 #include <linux/cdev.h>
@@ -112,6 +111,7 @@
 #define HWICAP_DEVICES 1
 
 /* An array, which is set to true when the device is registered. */
+static DEFINE_MUTEX(hwicap_mutex);
 static bool probed_devices[HWICAP_DEVICES];
 static struct mutex icap_sem;
 
@@ -502,7 +502,7 @@
 	struct hwicap_drvdata *drvdata;
 	int status;
 
-	lock_kernel();
+	mutex_lock(&hwicap_mutex);
 	drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);
 
 	status = mutex_lock_interruptible(&drvdata->sem);
@@ -528,7 +528,7 @@
  error:
 	mutex_unlock(&drvdata->sem);
  out:
-	unlock_kernel();
+	mutex_unlock(&hwicap_mutex);
 	return status;
 }
 
@@ -567,6 +567,7 @@
 	.read = hwicap_read,
 	.open = hwicap_open,
 	.release = hwicap_release,
+	.llseek = noop_llseek,
 };
 
 static int __devinit hwicap_setup(struct device *dev, int id,
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index c2408bb..f508690 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -80,7 +80,7 @@
  * Limiting Performance Impact
  * ---------------------------
  * C states, especially those with large exit latencies, can have a real
- * noticable impact on workloads, which is not acceptable for most sysadmins,
+ * noticeable impact on workloads, which is not acceptable for most sysadmins,
  * and in addition, less performance has a power price of its own.
  *
  * As a general rule of thumb, menu assumes that the following heuristic
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index 557e227..ae2b871 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -157,6 +157,7 @@
 	.owner		= THIS_MODULE,
 	.open		= coh901318_debugfs_open,
 	.read		= coh901318_debugfs_read,
+	.llseek		= default_llseek,
 };
 
 
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c
index 216f9d3..effd140 100644
--- a/drivers/dma/ioat/dma_v2.c
+++ b/drivers/dma/ioat/dma_v2.c
@@ -879,7 +879,7 @@
 	dma->device_issue_pending = ioat2_issue_pending;
 	dma->device_alloc_chan_resources = ioat2_alloc_chan_resources;
 	dma->device_free_chan_resources = ioat2_free_chan_resources;
-	dma->device_tx_status = ioat_tx_status;
+	dma->device_tx_status = ioat_dma_tx_status;
 
 	err = ioat_probe(device);
 	if (err)
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 86c5ae9..411d5bf 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -162,7 +162,7 @@
 
 static void mv_xor_device_clear_eoc_cause(struct mv_xor_chan *chan)
 {
-	u32 val = (1 << (1 + (chan->idx * 16)));
+	u32 val = ~(1 << (chan->idx * 16));
 	dev_dbg(chan->device->common.dev, "%s, val 0x%08x\n", __func__, val);
 	__raw_writel(val, XOR_INTR_CAUSE(chan));
 }
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index fb64cf3..eb6b54d 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -580,7 +580,6 @@
 
 	sh_chan = to_sh_chan(chan);
 	param = chan->private;
-	slave_addr = param->config->addr;
 
 	/* Someone calling slave DMA on a public channel? */
 	if (!param || !sg_len) {
@@ -589,6 +588,8 @@
 		return NULL;
 	}
 
+	slave_addr = param->config->addr;
+
 	/*
 	 * if (param != NULL), this is a successfully requested slave channel,
 	 * therefore param->config != NULL too.
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 70bb350..9dbb28b 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -39,7 +39,7 @@
 	  there're four debug levels (x=0,1,2,3 from low to high).
 	  Usually you should select 'N'.
 
- config EDAC_DECODE_MCE
+config EDAC_DECODE_MCE
 	tristate "Decode MCEs in human-readable form (only on AMD for now)"
 	depends on CPU_SUP_AMD && X86_MCE
 	default y
@@ -51,6 +51,16 @@
 	  which occur really early upon boot, before the module infrastructure
 	  has been initialized.
 
+config EDAC_MCE_INJ
+	tristate "Simple MCE injection interface over /sysfs"
+	depends on EDAC_DECODE_MCE
+	default n
+	help
+	  This is a simple interface to inject MCEs over /sysfs and test
+	  the MCE decoding code in EDAC.
+
+	  This is currently AMD-only.
+
 config EDAC_MM_EDAC
 	tristate "Main Memory EDAC (Error Detection And Correction) reporting"
 	help
@@ -66,13 +76,13 @@
 
 config EDAC_AMD64
 	tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
-	depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
+	depends on EDAC_MM_EDAC && AMD_NB && X86_64 && PCI && EDAC_DECODE_MCE
 	help
 	  Support for error detection and correction on the AMD 64
 	  Families of Memory Controllers (K8, F10h and F11h)
 
 config EDAC_AMD64_ERROR_INJECTION
-	bool "Sysfs Error Injection facilities"
+	bool "Sysfs HW Error injection facilities"
 	depends on EDAC_AMD64
 	help
 	  Recent Opterons (Family 10h and later) provide for Memory Error
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index ca6b1bb..32c7bc9 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -17,6 +17,9 @@
 edac_core-objs	+= edac_pci.o edac_pci_sysfs.o
 endif
 
+obj-$(CONFIG_EDAC_MCE_INJ)		+= mce_amd_inj.o
+
+edac_mce_amd-objs			:= mce_amd.o
 obj-$(CONFIG_EDAC_DECODE_MCE)		+= edac_mce_amd.o
 
 obj-$(CONFIG_EDAC_AMD76X)		+= amd76x_edac.o
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index e7d5d6b..8521401 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -1,5 +1,5 @@
 #include "amd64_edac.h"
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
 
 static struct edac_pci_ctl_info *amd64_ctl_pci;
 
@@ -2073,11 +2073,18 @@
 		amd64_handle_ue(mci, info);
 }
 
-void amd64_decode_bus_error(int node_id, struct err_regs *regs)
+void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg)
 {
 	struct mem_ctl_info *mci = mci_lookup[node_id];
+	struct err_regs regs;
 
-	__amd64_decode_bus_error(mci, 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
@@ -2086,7 +2093,7 @@
 	 *
 	 * FIXME: this should go somewhere else, if at all.
 	 */
-	if (regs->nbsh & K8_NBSH_UC_ERR && !report_gart_errors)
+	if (regs.nbsh & K8_NBSH_UC_ERR && !report_gart_errors)
 		edac_mc_handle_ue_no_info(mci, "UE bit is set");
 
 }
@@ -2927,7 +2934,7 @@
 	 * to finish initialization of the MC instances.
 	 */
 	err = -ENODEV;
-	for (nb = 0; nb < num_k8_northbridges; nb++) {
+	for (nb = 0; nb < k8_northbridges.num; nb++) {
 		if (!pvt_lookup[nb])
 			continue;
 
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 613b938..044aee4 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -72,7 +72,7 @@
 #include <linux/edac.h>
 #include <asm/msr.h>
 #include "edac_core.h"
-#include "edac_mce_amd.h"
+#include "mce_amd.h"
 
 #define amd64_printk(level, fmt, arg...) \
 	edac_printk(level, "amd64", fmt, ##arg)
@@ -482,11 +482,10 @@
 extern const char *to_msgs[2];
 extern const char *pp_msgs[4];
 extern const char *ii_msgs[4];
-extern const char *ext_msgs[32];
 extern const char *htlink_msgs[8];
 
 #ifdef CONFIG_EDAC_DEBUG
-#define NUM_DBG_ATTRS 9
+#define NUM_DBG_ATTRS 5
 #else
 #define NUM_DBG_ATTRS 0
 #endif
diff --git a/drivers/edac/amd64_edac_dbg.c b/drivers/edac/amd64_edac_dbg.c
index 59cf2cf..e356228 100644
--- a/drivers/edac/amd64_edac_dbg.c
+++ b/drivers/edac/amd64_edac_dbg.c
@@ -1,167 +1,16 @@
 #include "amd64_edac.h"
 
-/*
- * accept a hex value and store it into the virtual error register file, field:
- * nbeal and nbeah. Assume virtual error values have already been set for: NBSL,
- * NBSH and NBCFG. Then proceed to map the error values to a MC, CSROW and
- * CHANNEL
- */
-static ssize_t amd64_nbea_store(struct mem_ctl_info *mci, const char *data,
-				size_t count)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-	unsigned long long value;
-	int ret = 0;
-
-	ret = strict_strtoull(data, 16, &value);
-	if (ret != -EINVAL) {
-		debugf0("received NBEA= 0x%llx\n", value);
-
-		/* place the value into the virtual error packet */
-		pvt->ctl_error_info.nbeal = (u32) value;
-		value >>= 32;
-		pvt->ctl_error_info.nbeah = (u32) value;
-
-		/* Process the Mapping request */
-		/* TODO: Add race prevention */
-		amd_decode_nb_mce(pvt->mc_node_id, &pvt->ctl_error_info, 1);
-
-		return count;
-	}
-	return ret;
+#define EDAC_DCT_ATTR_SHOW(reg)						\
+static ssize_t amd64_##reg##_show(struct mem_ctl_info *mci, char *data)	\
+{									\
+	struct amd64_pvt *pvt = mci->pvt_info;				\
+		return sprintf(data, "0x%016llx\n", (u64)pvt->reg);	\
 }
 
-/* display back what the last NBEA (MCA NB Address (MC4_ADDR)) was written */
-static ssize_t amd64_nbea_show(struct mem_ctl_info *mci, char *data)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-	u64 value;
-
-	value = pvt->ctl_error_info.nbeah;
-	value <<= 32;
-	value |= pvt->ctl_error_info.nbeal;
-
-	return sprintf(data, "%llx\n", value);
-}
-
-/* store the NBSL (MCA NB Status Low (MC4_STATUS)) value user desires */
-static ssize_t amd64_nbsl_store(struct mem_ctl_info *mci, const char *data,
-				size_t count)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-	unsigned long value;
-	int ret = 0;
-
-	ret = strict_strtoul(data, 16, &value);
-	if (ret != -EINVAL) {
-		debugf0("received NBSL= 0x%lx\n", value);
-
-		pvt->ctl_error_info.nbsl = (u32) value;
-
-		return count;
-	}
-	return ret;
-}
-
-/* display back what the last NBSL value written */
-static ssize_t amd64_nbsl_show(struct mem_ctl_info *mci, char *data)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-	u32 value;
-
-	value = pvt->ctl_error_info.nbsl;
-
-	return sprintf(data, "%x\n", value);
-}
-
-/* store the NBSH (MCA NB Status High) value user desires */
-static ssize_t amd64_nbsh_store(struct mem_ctl_info *mci, const char *data,
-				size_t count)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-	unsigned long value;
-	int ret = 0;
-
-	ret = strict_strtoul(data, 16, &value);
-	if (ret != -EINVAL) {
-		debugf0("received NBSH= 0x%lx\n", value);
-
-		pvt->ctl_error_info.nbsh = (u32) value;
-
-		return count;
-	}
-	return ret;
-}
-
-/* display back what the last NBSH value written */
-static ssize_t amd64_nbsh_show(struct mem_ctl_info *mci, char *data)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-	u32 value;
-
-	value = pvt->ctl_error_info.nbsh;
-
-	return sprintf(data, "%x\n", value);
-}
-
-/* accept and store the NBCFG (MCA NB Configuration) value user desires */
-static ssize_t amd64_nbcfg_store(struct mem_ctl_info *mci,
-					const char *data, size_t count)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-	unsigned long value;
-	int ret = 0;
-
-	ret = strict_strtoul(data, 16, &value);
-	if (ret != -EINVAL) {
-		debugf0("received NBCFG= 0x%lx\n", value);
-
-		pvt->ctl_error_info.nbcfg = (u32) value;
-
-		return count;
-	}
-	return ret;
-}
-
-/* various show routines for the controls of a MCI */
-static ssize_t amd64_nbcfg_show(struct mem_ctl_info *mci, char *data)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-
-	return sprintf(data, "%x\n", pvt->ctl_error_info.nbcfg);
-}
-
-
-static ssize_t amd64_dhar_show(struct mem_ctl_info *mci, char *data)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-
-	return sprintf(data, "%x\n", pvt->dhar);
-}
-
-
-static ssize_t amd64_dbam_show(struct mem_ctl_info *mci, char *data)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-
-	return sprintf(data, "%x\n", pvt->dbam0);
-}
-
-
-static ssize_t amd64_topmem_show(struct mem_ctl_info *mci, char *data)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-
-	return sprintf(data, "%llx\n", pvt->top_mem);
-}
-
-
-static ssize_t amd64_topmem2_show(struct mem_ctl_info *mci, char *data)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-
-	return sprintf(data, "%llx\n", pvt->top_mem2);
-}
+EDAC_DCT_ATTR_SHOW(dhar);
+EDAC_DCT_ATTR_SHOW(dbam0);
+EDAC_DCT_ATTR_SHOW(top_mem);
+EDAC_DCT_ATTR_SHOW(top_mem2);
 
 static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data)
 {
@@ -182,38 +31,6 @@
 
 	{
 		.attr = {
-			.name = "nbea_ctl",
-			.mode = (S_IRUGO | S_IWUSR)
-		},
-		.show = amd64_nbea_show,
-		.store = amd64_nbea_store,
-	},
-	{
-		.attr = {
-			.name = "nbsl_ctl",
-			.mode = (S_IRUGO | S_IWUSR)
-		},
-		.show = amd64_nbsl_show,
-		.store = amd64_nbsl_store,
-	},
-	{
-		.attr = {
-			.name = "nbsh_ctl",
-			.mode = (S_IRUGO | S_IWUSR)
-		},
-		.show = amd64_nbsh_show,
-		.store = amd64_nbsh_store,
-	},
-	{
-		.attr = {
-			.name = "nbcfg_ctl",
-			.mode = (S_IRUGO | S_IWUSR)
-		},
-		.show = amd64_nbcfg_show,
-		.store = amd64_nbcfg_store,
-	},
-	{
-		.attr = {
 			.name = "dhar",
 			.mode = (S_IRUGO)
 		},
@@ -225,7 +42,7 @@
 			.name = "dbam",
 			.mode = (S_IRUGO)
 		},
-		.show = amd64_dbam_show,
+		.show = amd64_dbam0_show,
 		.store = NULL,
 	},
 	{
@@ -233,7 +50,7 @@
 			.name = "topmem",
 			.mode = (S_IRUGO)
 		},
-		.show = amd64_topmem_show,
+		.show = amd64_top_mem_show,
 		.store = NULL,
 	},
 	{
@@ -241,7 +58,7 @@
 			.name = "topmem2",
 			.mode = (S_IRUGO)
 		},
-		.show = amd64_topmem2_show,
+		.show = amd64_top_mem2_show,
 		.store = NULL,
 	},
 	{
diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
index 0709681..2941dca 100644
--- a/drivers/edac/edac_device_sysfs.c
+++ b/drivers/edac/edac_device_sysfs.c
@@ -13,6 +13,7 @@
 #include <linux/ctype.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/edac.h>
 
 #include "edac_core.h"
 #include "edac_module.h"
@@ -235,7 +236,7 @@
 	debugf1("%s()\n", __func__);
 
 	/* get the /sys/devices/system/edac reference */
-	edac_class = edac_get_edac_class();
+	edac_class = edac_get_sysfs_class();
 	if (edac_class == NULL) {
 		debugf1("%s() no edac_class error\n", __func__);
 		err = -ENODEV;
@@ -255,7 +256,7 @@
 
 	if (!try_module_get(edac_dev->owner)) {
 		err = -ENODEV;
-		goto err_out;
+		goto err_mod_get;
 	}
 
 	/* register */
@@ -282,6 +283,9 @@
 err_kobj_reg:
 	module_put(edac_dev->owner);
 
+err_mod_get:
+	edac_put_sysfs_class();
+
 err_out:
 	return err;
 }
@@ -290,12 +294,11 @@
  * edac_device_unregister_sysfs_main_kobj:
  *	the '..../edac/<name>' kobject
  */
-void edac_device_unregister_sysfs_main_kobj(
-					struct edac_device_ctl_info *edac_dev)
+void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev)
 {
 	debugf0("%s()\n", __func__);
 	debugf4("%s() name of kobject is: %s\n",
-		__func__, kobject_name(&edac_dev->kobj));
+		__func__, kobject_name(&dev->kobj));
 
 	/*
 	 * Unregister the edac device's kobject and
@@ -304,7 +307,8 @@
 	 *   a) module_put() this module
 	 *   b) 'kfree' the memory
 	 */
-	kobject_put(&edac_dev->kobj);
+	kobject_put(&dev->kobj);
+	edac_put_sysfs_class();
 }
 
 /* edac_dev -> instance information */
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 3630308..6b21e25 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -339,6 +339,9 @@
 {
 	int status;
 
+	if (mci->op_state != OP_RUNNING_POLL)
+		return;
+
 	status = cancel_delayed_work(&mci->work);
 	if (status == 0) {
 		debugf0("%s() not canceled, flush the queue\n",
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 8aad94d..a413586 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -11,6 +11,7 @@
 
 #include <linux/ctype.h>
 #include <linux/slab.h>
+#include <linux/edac.h>
 #include <linux/bug.h>
 
 #include "edac_core.h"
@@ -1011,13 +1012,13 @@
  */
 int edac_sysfs_setup_mc_kset(void)
 {
-	int err = 0;
+	int err = -EINVAL;
 	struct sysdev_class *edac_class;
 
 	debugf1("%s()\n", __func__);
 
 	/* get the /sys/devices/system/edac class reference */
-	edac_class = edac_get_edac_class();
+	edac_class = edac_get_sysfs_class();
 	if (edac_class == NULL) {
 		debugf1("%s() no edac_class error=%d\n", __func__, err);
 		goto fail_out;
@@ -1028,15 +1029,16 @@
 	if (!mc_kset) {
 		err = -ENOMEM;
 		debugf1("%s() Failed to register '.../edac/mc'\n", __func__);
-		goto fail_out;
+		goto fail_kset;
 	}
 
 	debugf1("%s() Registered '.../edac/mc' kobject\n", __func__);
 
 	return 0;
 
+fail_kset:
+	edac_put_sysfs_class();
 
-	/* error unwind stack */
 fail_out:
 	return err;
 }
@@ -1049,5 +1051,6 @@
 void edac_sysfs_teardown_mc_kset(void)
 {
 	kset_unregister(mc_kset);
+	edac_put_sysfs_class();
 }
 
diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c
deleted file mode 100644
index 9014df6..0000000
--- a/drivers/edac/edac_mce_amd.c
+++ /dev/null
@@ -1,452 +0,0 @@
-#include <linux/module.h>
-#include "edac_mce_amd.h"
-
-static bool report_gart_errors;
-static void (*nb_bus_decoder)(int node_id, struct err_regs *regs);
-
-void amd_report_gart_errors(bool v)
-{
-	report_gart_errors = v;
-}
-EXPORT_SYMBOL_GPL(amd_report_gart_errors);
-
-void amd_register_ecc_decoder(void (*f)(int, struct err_regs *))
-{
-	nb_bus_decoder = f;
-}
-EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
-
-void amd_unregister_ecc_decoder(void (*f)(int, struct err_regs *))
-{
-	if (nb_bus_decoder) {
-		WARN_ON(nb_bus_decoder != f);
-
-		nb_bus_decoder = NULL;
-	}
-}
-EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
-
-/*
- * string representation for the different MCA reported error types, see F3x48
- * or MSR0000_0411.
- */
-const char *tt_msgs[] = {        /* transaction type */
-	"instruction",
-	"data",
-	"generic",
-	"reserved"
-};
-EXPORT_SYMBOL_GPL(tt_msgs);
-
-const char *ll_msgs[] = {	/* cache level */
-	"L0",
-	"L1",
-	"L2",
-	"L3/generic"
-};
-EXPORT_SYMBOL_GPL(ll_msgs);
-
-const char *rrrr_msgs[] = {
-	"generic",
-	"generic read",
-	"generic write",
-	"data read",
-	"data write",
-	"inst fetch",
-	"prefetch",
-	"evict",
-	"snoop",
-	"reserved RRRR= 9",
-	"reserved RRRR= 10",
-	"reserved RRRR= 11",
-	"reserved RRRR= 12",
-	"reserved RRRR= 13",
-	"reserved RRRR= 14",
-	"reserved RRRR= 15"
-};
-EXPORT_SYMBOL_GPL(rrrr_msgs);
-
-const char *pp_msgs[] = {	/* participating processor */
-	"local node originated (SRC)",
-	"local node responded to request (RES)",
-	"local node observed as 3rd party (OBS)",
-	"generic"
-};
-EXPORT_SYMBOL_GPL(pp_msgs);
-
-const char *to_msgs[] = {
-	"no timeout",
-	"timed out"
-};
-EXPORT_SYMBOL_GPL(to_msgs);
-
-const char *ii_msgs[] = {	/* memory or i/o */
-	"mem access",
-	"reserved",
-	"i/o access",
-	"generic"
-};
-EXPORT_SYMBOL_GPL(ii_msgs);
-
-/*
- * Map the 4 or 5 (family-specific) bits of Extended Error code to the
- * string table.
- */
-const char *ext_msgs[] = {
-	"K8 ECC error",					/* 0_0000b */
-	"CRC error on link",				/* 0_0001b */
-	"Sync error packets on link",			/* 0_0010b */
-	"Master Abort during link operation",		/* 0_0011b */
-	"Target Abort during link operation",		/* 0_0100b */
-	"Invalid GART PTE entry during table walk",	/* 0_0101b */
-	"Unsupported atomic RMW command received",	/* 0_0110b */
-	"WDT error: NB transaction timeout",		/* 0_0111b */
-	"ECC/ChipKill ECC error",			/* 0_1000b */
-	"SVM DEV Error",				/* 0_1001b */
-	"Link Data error",				/* 0_1010b */
-	"Link/L3/Probe Filter Protocol error",		/* 0_1011b */
-	"NB Internal Arrays Parity error",		/* 0_1100b */
-	"DRAM Address/Control Parity error",		/* 0_1101b */
-	"Link Transmission error",			/* 0_1110b */
-	"GART/DEV Table Walk Data error"		/* 0_1111b */
-	"Res 0x100 error",				/* 1_0000b */
-	"Res 0x101 error",				/* 1_0001b */
-	"Res 0x102 error",				/* 1_0010b */
-	"Res 0x103 error",				/* 1_0011b */
-	"Res 0x104 error",				/* 1_0100b */
-	"Res 0x105 error",				/* 1_0101b */
-	"Res 0x106 error",				/* 1_0110b */
-	"Res 0x107 error",				/* 1_0111b */
-	"Res 0x108 error",				/* 1_1000b */
-	"Res 0x109 error",				/* 1_1001b */
-	"Res 0x10A error",				/* 1_1010b */
-	"Res 0x10B error",				/* 1_1011b */
-	"ECC error in L3 Cache Data",			/* 1_1100b */
-	"L3 Cache Tag error",				/* 1_1101b */
-	"L3 Cache LRU Parity error",			/* 1_1110b */
-	"Probe Filter error"				/* 1_1111b */
-};
-EXPORT_SYMBOL_GPL(ext_msgs);
-
-static void amd_decode_dc_mce(u64 mc0_status)
-{
-	u32 ec  = mc0_status & 0xffff;
-	u32 xec = (mc0_status >> 16) & 0xf;
-
-	pr_emerg("Data Cache Error");
-
-	if (xec == 1 && TLB_ERROR(ec))
-		pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
-	else if (xec == 0) {
-		if (mc0_status & (1ULL << 40))
-			pr_cont(" during Data Scrub.\n");
-		else if (TLB_ERROR(ec))
-			pr_cont(": %s TLB parity error.\n", LL_MSG(ec));
-		else if (MEM_ERROR(ec)) {
-			u8 ll   = ec & 0x3;
-			u8 tt   = (ec >> 2) & 0x3;
-			u8 rrrr = (ec >> 4) & 0xf;
-
-			/* see F10h BKDG (31116), Table 92. */
-			if (ll == 0x1) {
-				if (tt != 0x1)
-					goto wrong_dc_mce;
-
-				pr_cont(": Data/Tag %s error.\n", RRRR_MSG(ec));
-
-			} else if (ll == 0x2 && rrrr == 0x3)
-				pr_cont(" during L1 linefill from L2.\n");
-			else
-				goto wrong_dc_mce;
-		} else if (BUS_ERROR(ec) && boot_cpu_data.x86 == 0xf)
-			pr_cont(" during system linefill.\n");
-		else
-			goto wrong_dc_mce;
-	} else
-		goto wrong_dc_mce;
-
-	return;
-
-wrong_dc_mce:
-	pr_warning("Corrupted DC MCE info?\n");
-}
-
-static void amd_decode_ic_mce(u64 mc1_status)
-{
-	u32 ec  = mc1_status & 0xffff;
-	u32 xec = (mc1_status >> 16) & 0xf;
-
-	pr_emerg("Instruction Cache Error");
-
-	if (xec == 1 && TLB_ERROR(ec))
-		pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
-	else if (xec == 0) {
-		if (TLB_ERROR(ec))
-			pr_cont(": %s TLB Parity error.\n", LL_MSG(ec));
-		else if (BUS_ERROR(ec)) {
-			if (boot_cpu_data.x86 == 0xf &&
-			    (mc1_status & (1ULL << 58)))
-				pr_cont(" during system linefill.\n");
-			else
-				pr_cont(" during attempted NB data read.\n");
-		} else if (MEM_ERROR(ec)) {
-			u8 ll   = ec & 0x3;
-			u8 rrrr = (ec >> 4) & 0xf;
-
-			if (ll == 0x2)
-				pr_cont(" during a linefill from L2.\n");
-			else if (ll == 0x1) {
-
-				switch (rrrr) {
-				case 0x5:
-					pr_cont(": Parity error during "
-					       "data load.\n");
-					break;
-
-				case 0x7:
-					pr_cont(": Copyback Parity/Victim"
-						" error.\n");
-					break;
-
-				case 0x8:
-					pr_cont(": Tag Snoop error.\n");
-					break;
-
-				default:
-					goto wrong_ic_mce;
-					break;
-				}
-			}
-		} else
-			goto wrong_ic_mce;
-	} else
-		goto wrong_ic_mce;
-
-	return;
-
-wrong_ic_mce:
-	pr_warning("Corrupted IC MCE info?\n");
-}
-
-static void amd_decode_bu_mce(u64 mc2_status)
-{
-	u32 ec = mc2_status & 0xffff;
-	u32 xec = (mc2_status >> 16) & 0xf;
-
-	pr_emerg("Bus Unit Error");
-
-	if (xec == 0x1)
-		pr_cont(" in the write data buffers.\n");
-	else if (xec == 0x3)
-		pr_cont(" in the victim data buffers.\n");
-	else if (xec == 0x2 && MEM_ERROR(ec))
-		pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
-	else if (xec == 0x0) {
-		if (TLB_ERROR(ec))
-			pr_cont(": %s error in a Page Descriptor Cache or "
-				"Guest TLB.\n", TT_MSG(ec));
-		else if (BUS_ERROR(ec))
-			pr_cont(": %s/ECC error in data read from NB: %s.\n",
-				RRRR_MSG(ec), PP_MSG(ec));
-		else if (MEM_ERROR(ec)) {
-			u8 rrrr = (ec >> 4) & 0xf;
-
-			if (rrrr >= 0x7)
-				pr_cont(": %s error during data copyback.\n",
-					RRRR_MSG(ec));
-			else if (rrrr <= 0x1)
-				pr_cont(": %s parity/ECC error during data "
-					"access from L2.\n", RRRR_MSG(ec));
-			else
-				goto wrong_bu_mce;
-		} else
-			goto wrong_bu_mce;
-	} else
-		goto wrong_bu_mce;
-
-	return;
-
-wrong_bu_mce:
-	pr_warning("Corrupted BU MCE info?\n");
-}
-
-static void amd_decode_ls_mce(u64 mc3_status)
-{
-	u32 ec  = mc3_status & 0xffff;
-	u32 xec = (mc3_status >> 16) & 0xf;
-
-	pr_emerg("Load Store Error");
-
-	if (xec == 0x0) {
-		u8 rrrr = (ec >> 4) & 0xf;
-
-		if (!BUS_ERROR(ec) || (rrrr != 0x3 && rrrr != 0x4))
-			goto wrong_ls_mce;
-
-		pr_cont(" during %s.\n", RRRR_MSG(ec));
-	}
-	return;
-
-wrong_ls_mce:
-	pr_warning("Corrupted LS MCE info?\n");
-}
-
-void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors)
-{
-	u32 ec  = ERROR_CODE(regs->nbsl);
-
-	if (!handle_errors)
-		return;
-
-	/*
-	 * GART TLB error reporting is disabled by default. Bail out early.
-	 */
-	if (TLB_ERROR(ec) && !report_gart_errors)
-		return;
-
-	pr_emerg("Northbridge Error, node %d", node_id);
-
-	/*
-	 * F10h, revD can disable ErrCpu[3:0] so check that first and also the
-	 * value encoding has changed so interpret those differently
-	 */
-	if ((boot_cpu_data.x86 == 0x10) &&
-	    (boot_cpu_data.x86_model > 7)) {
-		if (regs->nbsh & K8_NBSH_ERR_CPU_VAL)
-			pr_cont(", core: %u\n", (u8)(regs->nbsh & 0xf));
-	} else {
-		u8 assoc_cpus = regs->nbsh & 0xf;
-
-		if (assoc_cpus > 0)
-			pr_cont(", core: %d", fls(assoc_cpus) - 1);
-
-		pr_cont("\n");
-	}
-
-	pr_emerg("%s.\n", EXT_ERR_MSG(regs->nbsl));
-
-	if (BUS_ERROR(ec) && nb_bus_decoder)
-		nb_bus_decoder(node_id, regs);
-}
-EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
-
-static void amd_decode_fr_mce(u64 mc5_status)
-{
-	/* we have only one error signature so match all fields at once. */
-	if ((mc5_status & 0xffff) == 0x0f0f)
-		pr_emerg(" FR Error: CPU Watchdog timer expire.\n");
-	else
-		pr_warning("Corrupted FR MCE info?\n");
-}
-
-static inline void amd_decode_err_code(unsigned int ec)
-{
-	if (TLB_ERROR(ec)) {
-		pr_emerg("Transaction: %s, Cache Level %s\n",
-			 TT_MSG(ec), LL_MSG(ec));
-	} else if (MEM_ERROR(ec)) {
-		pr_emerg("Transaction: %s, Type: %s, Cache Level: %s",
-			 RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
-	} else if (BUS_ERROR(ec)) {
-		pr_emerg("Transaction type: %s(%s), %s, Cache Level: %s, "
-			 "Participating Processor: %s\n",
-			  RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
-			  PP_MSG(ec));
-	} else
-		pr_warning("Huh? Unknown MCE error 0x%x\n", ec);
-}
-
-static int amd_decode_mce(struct notifier_block *nb, unsigned long val,
-			   void *data)
-{
-	struct mce *m = (struct mce *)data;
-	struct err_regs regs;
-	int node, ecc;
-
-	pr_emerg("MC%d_STATUS: ", m->bank);
-
-	pr_cont("%sorrected error, other errors lost: %s, "
-		 "CPU context corrupt: %s",
-		 ((m->status & MCI_STATUS_UC) ? "Unc"  : "C"),
-		 ((m->status & MCI_STATUS_OVER) ? "yes"  : "no"),
-		 ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
-
-	/* do the two bits[14:13] together */
-	ecc = (m->status >> 45) & 0x3;
-	if (ecc)
-		pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
-
-	pr_cont("\n");
-
-	switch (m->bank) {
-	case 0:
-		amd_decode_dc_mce(m->status);
-		break;
-
-	case 1:
-		amd_decode_ic_mce(m->status);
-		break;
-
-	case 2:
-		amd_decode_bu_mce(m->status);
-		break;
-
-	case 3:
-		amd_decode_ls_mce(m->status);
-		break;
-
-	case 4:
-		regs.nbsl  = (u32) m->status;
-		regs.nbsh  = (u32)(m->status >> 32);
-		regs.nbeal = (u32) m->addr;
-		regs.nbeah = (u32)(m->addr >> 32);
-		node       = amd_get_nb_id(m->extcpu);
-
-		amd_decode_nb_mce(node, &regs, 1);
-		break;
-
-	case 5:
-		amd_decode_fr_mce(m->status);
-		break;
-
-	default:
-		break;
-	}
-
-	amd_decode_err_code(m->status & 0xffff);
-
-	return NOTIFY_STOP;
-}
-
-static struct notifier_block amd_mce_dec_nb = {
-	.notifier_call	= amd_decode_mce,
-};
-
-static int __init mce_amd_init(void)
-{
-	/*
-	 * We can decode MCEs for K8, F10h and F11h CPUs:
-	 */
-	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
-		return 0;
-
-	if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
-		return 0;
-
-	atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
-
-	return 0;
-}
-early_initcall(mce_amd_init);
-
-#ifdef MODULE
-static void __exit mce_amd_exit(void)
-{
-	atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
-}
-
-MODULE_DESCRIPTION("AMD MCE decoder");
-MODULE_ALIAS("edac-mce-amd");
-MODULE_LICENSE("GPL");
-module_exit(mce_amd_exit);
-#endif
diff --git a/drivers/edac/edac_mce_amd.h b/drivers/edac/edac_mce_amd.h
deleted file mode 100644
index df23ee0..0000000
--- a/drivers/edac/edac_mce_amd.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef _EDAC_MCE_AMD_H
-#define _EDAC_MCE_AMD_H
-
-#include <asm/mce.h>
-
-#define ERROR_CODE(x)			((x) & 0xffff)
-#define EXT_ERROR_CODE(x)		(((x) >> 16) & 0x1f)
-#define EXT_ERR_MSG(x)			ext_msgs[EXT_ERROR_CODE(x)]
-
-#define LOW_SYNDROME(x)			(((x) >> 15) & 0xff)
-#define HIGH_SYNDROME(x)		(((x) >> 24) & 0xff)
-
-#define TLB_ERROR(x)			(((x) & 0xFFF0) == 0x0010)
-#define MEM_ERROR(x)			(((x) & 0xFF00) == 0x0100)
-#define BUS_ERROR(x)			(((x) & 0xF800) == 0x0800)
-
-#define TT(x)				(((x) >> 2) & 0x3)
-#define TT_MSG(x)			tt_msgs[TT(x)]
-#define II(x)				(((x) >> 2) & 0x3)
-#define II_MSG(x)			ii_msgs[II(x)]
-#define LL(x)				(((x) >> 0) & 0x3)
-#define LL_MSG(x)			ll_msgs[LL(x)]
-#define RRRR(x)				(((x) >> 4) & 0xf)
-#define RRRR_MSG(x)			rrrr_msgs[RRRR(x)]
-#define TO(x)				(((x) >> 8) & 0x1)
-#define TO_MSG(x)			to_msgs[TO(x)]
-#define PP(x)				(((x) >> 9) & 0x3)
-#define PP_MSG(x)			pp_msgs[PP(x)]
-
-#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)
-
-extern const char *tt_msgs[];
-extern const char *ll_msgs[];
-extern const char *rrrr_msgs[];
-extern const char *pp_msgs[];
-extern const char *to_msgs[];
-extern const char *ii_msgs[];
-extern const char *ext_msgs[];
-
-/*
- * relevant NB regs
- */
-struct err_regs {
-	u32 nbcfg;
-	u32 nbsh;
-	u32 nbsl;
-	u32 nbeah;
-	u32 nbeal;
-};
-
-
-void amd_report_gart_errors(bool);
-void amd_register_ecc_decoder(void (*f)(int, struct err_regs *));
-void amd_unregister_ecc_decoder(void (*f)(int, struct err_regs *));
-void amd_decode_nb_mce(int, struct err_regs *, int);
-
-#endif /* _EDAC_MCE_AMD_H */
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c
index 7e1374a..be4b075 100644
--- a/drivers/edac/edac_module.c
+++ b/drivers/edac/edac_module.c
@@ -27,15 +27,6 @@
 struct workqueue_struct *edac_workqueue;
 
 /*
- * sysfs object: /sys/devices/system/edac
- *	need to export to other files in this modules
- */
-static struct sysdev_class edac_class = {
-	.name = "edac",
-};
-static int edac_class_valid;
-
-/*
  * edac_op_state_to_string()
  */
 char *edac_op_state_to_string(int opstate)
@@ -55,60 +46,6 @@
 }
 
 /*
- * edac_get_edac_class()
- *
- *	return pointer to the edac class of 'edac'
- */
-struct sysdev_class *edac_get_edac_class(void)
-{
-	struct sysdev_class *classptr = NULL;
-
-	if (edac_class_valid)
-		classptr = &edac_class;
-
-	return classptr;
-}
-
-/*
- * edac_register_sysfs_edac_name()
- *
- *	register the 'edac' into /sys/devices/system
- *
- * return:
- *	0  success
- *	!0 error
- */
-static int edac_register_sysfs_edac_name(void)
-{
-	int err;
-
-	/* create the /sys/devices/system/edac directory */
-	err = sysdev_class_register(&edac_class);
-
-	if (err) {
-		debugf1("%s() error=%d\n", __func__, err);
-		return err;
-	}
-
-	edac_class_valid = 1;
-	return 0;
-}
-
-/*
- * sysdev_class_unregister()
- *
- *	unregister the 'edac' from /sys/devices/system
- */
-static void edac_unregister_sysfs_edac_name(void)
-{
-	/* only if currently registered, then unregister it */
-	if (edac_class_valid)
-		sysdev_class_unregister(&edac_class);
-
-	edac_class_valid = 0;
-}
-
-/*
  * edac_workqueue_setup
  *	initialize the edac work queue for polling operations
  */
@@ -154,21 +91,11 @@
 	edac_pci_clear_parity_errors();
 
 	/*
-	 * perform the registration of the /sys/devices/system/edac class object
-	 */
-	if (edac_register_sysfs_edac_name()) {
-		edac_printk(KERN_ERR, EDAC_MC,
-			"Error initializing 'edac' kobject\n");
-		err = -ENODEV;
-		goto error;
-	}
-
-	/*
 	 * now set up the mc_kset under the edac class object
 	 */
 	err = edac_sysfs_setup_mc_kset();
 	if (err)
-		goto sysfs_setup_fail;
+		goto error;
 
 	/* Setup/Initialize the workq for this core */
 	err = edac_workqueue_setup();
@@ -183,9 +110,6 @@
 workq_fail:
 	edac_sysfs_teardown_mc_kset();
 
-sysfs_setup_fail:
-	edac_unregister_sysfs_edac_name();
-
 error:
 	return err;
 }
@@ -201,7 +125,6 @@
 	/* tear down the various subsystems */
 	edac_workqueue_teardown();
 	edac_sysfs_teardown_mc_kset();
-	edac_unregister_sysfs_edac_name();
 }
 
 /*
diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h
index 233d479..17aabb7 100644
--- a/drivers/edac/edac_module.h
+++ b/drivers/edac/edac_module.h
@@ -42,7 +42,6 @@
 				struct edac_device_ctl_info *edac_dev);
 extern int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev);
 extern void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev);
-extern struct sysdev_class *edac_get_edac_class(void);
 
 /* edac core workqueue: single CPU mode */
 extern struct workqueue_struct *edac_workqueue;
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index c39697d..023b01c 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -7,7 +7,7 @@
  *
  */
 #include <linux/module.h>
-#include <linux/sysdev.h>
+#include <linux/edac.h>
 #include <linux/slab.h>
 #include <linux/ctype.h>
 
@@ -354,7 +354,7 @@
 	/* First time, so create the main kobject and its
 	 * controls and atributes
 	 */
-	edac_class = edac_get_edac_class();
+	edac_class = edac_get_sysfs_class();
 	if (edac_class == NULL) {
 		debugf1("%s() no edac_class\n", __func__);
 		err = -ENODEV;
@@ -368,7 +368,7 @@
 	if (!try_module_get(THIS_MODULE)) {
 		debugf1("%s() try_module_get() failed\n", __func__);
 		err = -ENODEV;
-		goto decrement_count_fail;
+		goto mod_get_fail;
 	}
 
 	edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
@@ -403,6 +403,9 @@
 kzalloc_fail:
 	module_put(THIS_MODULE);
 
+mod_get_fail:
+	edac_put_sysfs_class();
+
 decrement_count_fail:
 	/* if are on this error exit, nothing to tear down */
 	atomic_dec(&edac_pci_sysfs_refcount);
@@ -429,6 +432,7 @@
 			__func__);
 		kobject_put(edac_pci_top_main_kobj);
 	}
+	edac_put_sysfs_class();
 }
 
 /*
diff --git a/drivers/edac/edac_stub.c b/drivers/edac/edac_stub.c
index 20b428a..aab9707 100644
--- a/drivers/edac/edac_stub.c
+++ b/drivers/edac/edac_stub.c
@@ -3,10 +3,13 @@
  *
  * Author: Dave Jiang <djiang@mvista.com>
  *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
+ * 2007 (c) MontaVista Software, Inc.
+ * 2010 (c) Advanced Micro Devices Inc.
+ *	    Borislav Petkov <borislav.petkov@amd.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/module.h>
@@ -23,6 +26,8 @@
 int edac_err_assert = 0;
 EXPORT_SYMBOL_GPL(edac_err_assert);
 
+static atomic_t edac_class_valid = ATOMIC_INIT(0);
+
 /*
  * called to determine if there is an EDAC driver interested in
  * knowing an event (such as NMI) occurred
@@ -44,3 +49,41 @@
 	edac_err_assert++;
 }
 EXPORT_SYMBOL_GPL(edac_atomic_assert_error);
+
+/*
+ * sysfs object: /sys/devices/system/edac
+ *	need to export to other files
+ */
+struct sysdev_class edac_class = {
+	.name = "edac",
+};
+EXPORT_SYMBOL_GPL(edac_class);
+
+/* return pointer to the 'edac' node in sysfs */
+struct sysdev_class *edac_get_sysfs_class(void)
+{
+	int err = 0;
+
+	if (atomic_read(&edac_class_valid))
+		goto out;
+
+	/* create the /sys/devices/system/edac directory */
+	err = sysdev_class_register(&edac_class);
+	if (err) {
+		printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n");
+		return NULL;
+	}
+
+out:
+	atomic_inc(&edac_class_valid);
+	return &edac_class;
+}
+EXPORT_SYMBOL_GPL(edac_get_sysfs_class);
+
+void edac_put_sysfs_class(void)
+{
+	/* last user unregisters it */
+	if (atomic_dec_and_test(&edac_class_valid))
+		sysdev_class_unregister(&edac_class);
+}
+EXPORT_SYMBOL_GPL(edac_put_sysfs_class);
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index e0187d1..0fd5b85 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -1140,6 +1140,7 @@
 	ATTR_COUNTER(0),
 	ATTR_COUNTER(1),
 	ATTR_COUNTER(2),
+	{ .attr = { .name = NULL } }
 };
 
 static struct mcidev_sysfs_group i7core_udimm_counters = {
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
new file mode 100644
index 0000000..c018109
--- /dev/null
+++ b/drivers/edac/mce_amd.c
@@ -0,0 +1,680 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "mce_amd.h"
+
+static struct amd_decoder_ops *fam_ops;
+
+static u8 nb_err_cpumask = 0xf;
+
+static bool report_gart_errors;
+static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
+
+void amd_report_gart_errors(bool v)
+{
+	report_gart_errors = v;
+}
+EXPORT_SYMBOL_GPL(amd_report_gart_errors);
+
+void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32))
+{
+	nb_bus_decoder = f;
+}
+EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
+
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32))
+{
+	if (nb_bus_decoder) {
+		WARN_ON(nb_bus_decoder != f);
+
+		nb_bus_decoder = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
+
+/*
+ * string representation for the different MCA reported error types, see F3x48
+ * or MSR0000_0411.
+ */
+
+/* transaction type */
+const char *tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" };
+EXPORT_SYMBOL_GPL(tt_msgs);
+
+/* cache level */
+const char *ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" };
+EXPORT_SYMBOL_GPL(ll_msgs);
+
+/* memory transaction type */
+const char *rrrr_msgs[] = {
+       "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP"
+};
+EXPORT_SYMBOL_GPL(rrrr_msgs);
+
+/* participating processor */
+const char *pp_msgs[] = { "SRC", "RES", "OBS", "GEN" };
+EXPORT_SYMBOL_GPL(pp_msgs);
+
+/* request timeout */
+const char *to_msgs[] = { "no timeout",	"timed out" };
+EXPORT_SYMBOL_GPL(to_msgs);
+
+/* memory or i/o */
+const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
+EXPORT_SYMBOL_GPL(ii_msgs);
+
+static const char *f10h_nb_mce_desc[] = {
+	"HT link data error",
+	"Protocol error (link, L3, probe filter, etc.)",
+	"Parity error in NB-internal arrays",
+	"Link Retry due to IO link transmission error",
+	"L3 ECC data cache error",
+	"ECC error in L3 cache tag",
+	"L3 LRU parity bits error",
+	"ECC Error in the Probe Filter directory"
+};
+
+static bool f12h_dc_mce(u16 ec)
+{
+	bool ret = false;
+
+	if (MEM_ERROR(ec)) {
+		u8 ll = ec & 0x3;
+		ret = true;
+
+		if (ll == LL_L2)
+			pr_cont("during L1 linefill from L2.\n");
+		else if (ll == LL_L1)
+			pr_cont("Data/Tag %s error.\n", RRRR_MSG(ec));
+		else
+			ret = false;
+	}
+	return ret;
+}
+
+static bool f10h_dc_mce(u16 ec)
+{
+	u8 r4  = (ec >> 4) & 0xf;
+	u8 ll  = ec & 0x3;
+
+	if (r4 == R4_GEN && ll == LL_L1) {
+		pr_cont("during data scrub.\n");
+		return true;
+	}
+	return f12h_dc_mce(ec);
+}
+
+static bool k8_dc_mce(u16 ec)
+{
+	if (BUS_ERROR(ec)) {
+		pr_cont("during system linefill.\n");
+		return true;
+	}
+
+	return f10h_dc_mce(ec);
+}
+
+static bool f14h_dc_mce(u16 ec)
+{
+	u8 r4	 = (ec >> 4) & 0xf;
+	u8 ll	 = ec & 0x3;
+	u8 tt	 = (ec >> 2) & 0x3;
+	u8 ii	 = tt;
+	bool ret = true;
+
+	if (MEM_ERROR(ec)) {
+
+		if (tt != TT_DATA || ll != LL_L1)
+			return false;
+
+		switch (r4) {
+		case R4_DRD:
+		case R4_DWR:
+			pr_cont("Data/Tag parity error due to %s.\n",
+				(r4 == R4_DRD ? "load/hw prf" : "store"));
+			break;
+		case R4_EVICT:
+			pr_cont("Copyback parity error on a tag miss.\n");
+			break;
+		case R4_SNOOP:
+			pr_cont("Tag parity error during snoop.\n");
+			break;
+		default:
+			ret = false;
+		}
+	} else if (BUS_ERROR(ec)) {
+
+		if ((ii != II_MEM && ii != II_IO) || ll != LL_LG)
+			return false;
+
+		pr_cont("System read data error on a ");
+
+		switch (r4) {
+		case R4_RD:
+			pr_cont("TLB reload.\n");
+			break;
+		case R4_DWR:
+			pr_cont("store.\n");
+			break;
+		case R4_DRD:
+			pr_cont("load.\n");
+			break;
+		default:
+			ret = false;
+		}
+	} else {
+		ret = false;
+	}
+
+	return ret;
+}
+
+static void amd_decode_dc_mce(struct mce *m)
+{
+	u16 ec = m->status & 0xffff;
+	u8 xec = (m->status >> 16) & 0xf;
+
+	pr_emerg(HW_ERR "Data Cache Error: ");
+
+	/* TLB error signatures are the same across families */
+	if (TLB_ERROR(ec)) {
+		u8 tt = (ec >> 2) & 0x3;
+
+		if (tt == TT_DATA) {
+			pr_cont("%s TLB %s.\n", LL_MSG(ec),
+				(xec ? "multimatch" : "parity error"));
+			return;
+		}
+		else
+			goto wrong_dc_mce;
+	}
+
+	if (!fam_ops->dc_mce(ec))
+		goto wrong_dc_mce;
+
+	return;
+
+wrong_dc_mce:
+	pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
+}
+
+static bool k8_ic_mce(u16 ec)
+{
+	u8 ll	 = ec & 0x3;
+	u8 r4	 = (ec >> 4) & 0xf;
+	bool ret = true;
+
+	if (!MEM_ERROR(ec))
+		return false;
+
+	if (ll == 0x2)
+		pr_cont("during a linefill from L2.\n");
+	else if (ll == 0x1) {
+		switch (r4) {
+		case R4_IRD:
+			pr_cont("Parity error during data load.\n");
+			break;
+
+		case R4_EVICT:
+			pr_cont("Copyback Parity/Victim error.\n");
+			break;
+
+		case R4_SNOOP:
+			pr_cont("Tag Snoop error.\n");
+			break;
+
+		default:
+			ret = false;
+			break;
+		}
+	} else
+		ret = false;
+
+	return ret;
+}
+
+static bool f14h_ic_mce(u16 ec)
+{
+	u8 ll    = ec & 0x3;
+	u8 tt    = (ec >> 2) & 0x3;
+	u8 r4  = (ec >> 4) & 0xf;
+	bool ret = true;
+
+	if (MEM_ERROR(ec)) {
+		if (tt != 0 || ll != 1)
+			ret = false;
+
+		if (r4 == R4_IRD)
+			pr_cont("Data/tag array parity error for a tag hit.\n");
+		else if (r4 == R4_SNOOP)
+			pr_cont("Tag error during snoop/victimization.\n");
+		else
+			ret = false;
+	}
+	return ret;
+}
+
+static void amd_decode_ic_mce(struct mce *m)
+{
+	u16 ec = m->status & 0xffff;
+	u8 xec = (m->status >> 16) & 0xf;
+
+	pr_emerg(HW_ERR "Instruction Cache Error: ");
+
+	if (TLB_ERROR(ec))
+		pr_cont("%s TLB %s.\n", LL_MSG(ec),
+			(xec ? "multimatch" : "parity error"));
+	else if (BUS_ERROR(ec)) {
+		bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
+
+		pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
+	} else if (fam_ops->ic_mce(ec))
+		;
+	else
+		pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
+}
+
+static void amd_decode_bu_mce(struct mce *m)
+{
+	u32 ec = m->status & 0xffff;
+	u32 xec = (m->status >> 16) & 0xf;
+
+	pr_emerg(HW_ERR "Bus Unit Error");
+
+	if (xec == 0x1)
+		pr_cont(" in the write data buffers.\n");
+	else if (xec == 0x3)
+		pr_cont(" in the victim data buffers.\n");
+	else if (xec == 0x2 && MEM_ERROR(ec))
+		pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
+	else if (xec == 0x0) {
+		if (TLB_ERROR(ec))
+			pr_cont(": %s error in a Page Descriptor Cache or "
+				"Guest TLB.\n", TT_MSG(ec));
+		else if (BUS_ERROR(ec))
+			pr_cont(": %s/ECC error in data read from NB: %s.\n",
+				RRRR_MSG(ec), PP_MSG(ec));
+		else if (MEM_ERROR(ec)) {
+			u8 rrrr = (ec >> 4) & 0xf;
+
+			if (rrrr >= 0x7)
+				pr_cont(": %s error during data copyback.\n",
+					RRRR_MSG(ec));
+			else if (rrrr <= 0x1)
+				pr_cont(": %s parity/ECC error during data "
+					"access from L2.\n", RRRR_MSG(ec));
+			else
+				goto wrong_bu_mce;
+		} else
+			goto wrong_bu_mce;
+	} else
+		goto wrong_bu_mce;
+
+	return;
+
+wrong_bu_mce:
+	pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
+}
+
+static void amd_decode_ls_mce(struct mce *m)
+{
+	u16 ec = m->status & 0xffff;
+	u8 xec = (m->status >> 16) & 0xf;
+
+	if (boot_cpu_data.x86 == 0x14) {
+		pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
+			 " please report on LKML.\n");
+		return;
+	}
+
+	pr_emerg(HW_ERR "Load Store Error");
+
+	if (xec == 0x0) {
+		u8 r4 = (ec >> 4) & 0xf;
+
+		if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
+			goto wrong_ls_mce;
+
+		pr_cont(" during %s.\n", RRRR_MSG(ec));
+	} else
+		goto wrong_ls_mce;
+
+	return;
+
+wrong_ls_mce:
+	pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
+}
+
+static bool k8_nb_mce(u16 ec, u8 xec)
+{
+	bool ret = true;
+
+	switch (xec) {
+	case 0x1:
+		pr_cont("CRC error detected on HT link.\n");
+		break;
+
+	case 0x5:
+		pr_cont("Invalid GART PTE entry during GART table walk.\n");
+		break;
+
+	case 0x6:
+		pr_cont("Unsupported atomic RMW received from an IO link.\n");
+		break;
+
+	case 0x0:
+	case 0x8:
+		if (boot_cpu_data.x86 == 0x11)
+			return false;
+
+		pr_cont("DRAM ECC error detected on the NB.\n");
+		break;
+
+	case 0xd:
+		pr_cont("Parity error on the DRAM addr/ctl signals.\n");
+		break;
+
+	default:
+		ret = false;
+		break;
+	}
+
+	return ret;
+}
+
+static bool f10h_nb_mce(u16 ec, u8 xec)
+{
+	bool ret = true;
+	u8 offset = 0;
+
+	if (k8_nb_mce(ec, xec))
+		return true;
+
+	switch(xec) {
+	case 0xa ... 0xc:
+		offset = 10;
+		break;
+
+	case 0xe:
+		offset = 11;
+		break;
+
+	case 0xf:
+		if (TLB_ERROR(ec))
+			pr_cont("GART Table Walk data error.\n");
+		else if (BUS_ERROR(ec))
+			pr_cont("DMA Exclusion Vector Table Walk error.\n");
+		else
+			ret = false;
+
+		goto out;
+		break;
+
+	case 0x1c ... 0x1f:
+		offset = 24;
+		break;
+
+	default:
+		ret = false;
+
+		goto out;
+		break;
+	}
+
+	pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]);
+
+out:
+	return ret;
+}
+
+static bool nb_noop_mce(u16 ec, u8 xec)
+{
+	return false;
+}
+
+void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
+{
+	u8 xec   = (m->status >> 16) & 0x1f;
+	u16 ec   = m->status & 0xffff;
+	u32 nbsh = (u32)(m->status >> 32);
+
+	pr_emerg(HW_ERR "Northbridge Error, node %d: ", node_id);
+
+	/*
+	 * F10h, revD can disable ErrCpu[3:0] so check that first and also the
+	 * value encoding has changed so interpret those differently
+	 */
+	if ((boot_cpu_data.x86 == 0x10) &&
+	    (boot_cpu_data.x86_model > 7)) {
+		if (nbsh & K8_NBSH_ERR_CPU_VAL)
+			pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask));
+	} else {
+		u8 assoc_cpus = nbsh & nb_err_cpumask;
+
+		if (assoc_cpus > 0)
+			pr_cont(", core: %d", fls(assoc_cpus) - 1);
+	}
+
+	switch (xec) {
+	case 0x2:
+		pr_cont("Sync error (sync packets on HT link detected).\n");
+		return;
+
+	case 0x3:
+		pr_cont("HT Master abort.\n");
+		return;
+
+	case 0x4:
+		pr_cont("HT Target abort.\n");
+		return;
+
+	case 0x7:
+		pr_cont("NB Watchdog timeout.\n");
+		return;
+
+	case 0x9:
+		pr_cont("SVM DMA Exclusion Vector error.\n");
+		return;
+
+	default:
+		break;
+	}
+
+	if (!fam_ops->nb_mce(ec, xec))
+		goto wrong_nb_mce;
+
+	if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10)
+		if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
+			nb_bus_decoder(node_id, m, nbcfg);
+
+	return;
+
+wrong_nb_mce:
+	pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
+}
+EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
+
+static void amd_decode_fr_mce(struct mce *m)
+{
+	if (boot_cpu_data.x86 == 0xf ||
+	    boot_cpu_data.x86 == 0x11)
+		goto wrong_fr_mce;
+
+	/* we have only one error signature so match all fields at once. */
+	if ((m->status & 0xffff) == 0x0f0f) {
+		pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n");
+		return;
+	}
+
+wrong_fr_mce:
+	pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
+}
+
+static inline void amd_decode_err_code(u16 ec)
+{
+	if (TLB_ERROR(ec)) {
+		pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n",
+			 TT_MSG(ec), LL_MSG(ec));
+	} else if (MEM_ERROR(ec)) {
+		pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n",
+			 RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
+	} else if (BUS_ERROR(ec)) {
+		pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, "
+			 "Participating Processor: %s\n",
+			  RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
+			  PP_MSG(ec));
+	} else
+		pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
+}
+
+/*
+ * Filter out unwanted MCE signatures here.
+ */
+static bool amd_filter_mce(struct mce *m)
+{
+	u8 xec = (m->status >> 16) & 0x1f;
+
+	/*
+	 * NB GART TLB error reporting is disabled by default.
+	 */
+	if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
+		return true;
+
+	return false;
+}
+
+int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
+{
+	struct mce *m = (struct mce *)data;
+	int node, ecc;
+
+	if (amd_filter_mce(m))
+		return NOTIFY_STOP;
+
+	pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
+
+	pr_cont("%sorrected error, other errors lost: %s, "
+		 "CPU context corrupt: %s",
+		 ((m->status & MCI_STATUS_UC) ? "Unc"  : "C"),
+		 ((m->status & MCI_STATUS_OVER) ? "yes"  : "no"),
+		 ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
+
+	/* do the two bits[14:13] together */
+	ecc = (m->status >> 45) & 0x3;
+	if (ecc)
+		pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
+
+	pr_cont("\n");
+
+	switch (m->bank) {
+	case 0:
+		amd_decode_dc_mce(m);
+		break;
+
+	case 1:
+		amd_decode_ic_mce(m);
+		break;
+
+	case 2:
+		amd_decode_bu_mce(m);
+		break;
+
+	case 3:
+		amd_decode_ls_mce(m);
+		break;
+
+	case 4:
+		node = amd_get_nb_id(m->extcpu);
+		amd_decode_nb_mce(node, m, 0);
+		break;
+
+	case 5:
+		amd_decode_fr_mce(m);
+		break;
+
+	default:
+		break;
+	}
+
+	amd_decode_err_code(m->status & 0xffff);
+
+	return NOTIFY_STOP;
+}
+EXPORT_SYMBOL_GPL(amd_decode_mce);
+
+static struct notifier_block amd_mce_dec_nb = {
+	.notifier_call	= amd_decode_mce,
+};
+
+static int __init mce_amd_init(void)
+{
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+		return 0;
+
+	if ((boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x12) &&
+	    (boot_cpu_data.x86 != 0x14 || boot_cpu_data.x86_model > 0xf))
+		return 0;
+
+	fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
+	if (!fam_ops)
+		return -ENOMEM;
+
+	switch (boot_cpu_data.x86) {
+	case 0xf:
+		fam_ops->dc_mce = k8_dc_mce;
+		fam_ops->ic_mce = k8_ic_mce;
+		fam_ops->nb_mce = k8_nb_mce;
+		break;
+
+	case 0x10:
+		fam_ops->dc_mce = f10h_dc_mce;
+		fam_ops->ic_mce = k8_ic_mce;
+		fam_ops->nb_mce = f10h_nb_mce;
+		break;
+
+	case 0x11:
+		fam_ops->dc_mce = k8_dc_mce;
+		fam_ops->ic_mce = k8_ic_mce;
+		fam_ops->nb_mce = f10h_nb_mce;
+		break;
+
+	case 0x12:
+		fam_ops->dc_mce = f12h_dc_mce;
+		fam_ops->ic_mce = k8_ic_mce;
+		fam_ops->nb_mce = nb_noop_mce;
+		break;
+
+	case 0x14:
+		nb_err_cpumask  = 0x3;
+		fam_ops->dc_mce = f14h_dc_mce;
+		fam_ops->ic_mce = f14h_ic_mce;
+		fam_ops->nb_mce = nb_noop_mce;
+		break;
+
+	default:
+		printk(KERN_WARNING "Huh? What family is that: %d?!\n",
+				    boot_cpu_data.x86);
+		kfree(fam_ops);
+		return -EINVAL;
+	}
+
+	pr_info("MCE: In-kernel MCE decoding enabled.\n");
+
+	atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
+
+	return 0;
+}
+early_initcall(mce_amd_init);
+
+#ifdef MODULE
+static void __exit mce_amd_exit(void)
+{
+	atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
+	kfree(fam_ops);
+}
+
+MODULE_DESCRIPTION("AMD MCE decoder");
+MODULE_ALIAS("edac-mce-amd");
+MODULE_LICENSE("GPL");
+module_exit(mce_amd_exit);
+#endif
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h
new file mode 100644
index 0000000..35f6e0e3
--- /dev/null
+++ b/drivers/edac/mce_amd.h
@@ -0,0 +1,114 @@
+#ifndef _EDAC_MCE_AMD_H
+#define _EDAC_MCE_AMD_H
+
+#include <linux/notifier.h>
+
+#include <asm/mce.h>
+
+#define BIT_64(n)			(U64_C(1) << (n))
+
+#define ERROR_CODE(x)			((x) & 0xffff)
+#define EXT_ERROR_CODE(x)		(((x) >> 16) & 0x1f)
+
+#define LOW_SYNDROME(x)			(((x) >> 15) & 0xff)
+#define HIGH_SYNDROME(x)		(((x) >> 24) & 0xff)
+
+#define TLB_ERROR(x)			(((x) & 0xFFF0) == 0x0010)
+#define MEM_ERROR(x)			(((x) & 0xFF00) == 0x0100)
+#define BUS_ERROR(x)			(((x) & 0xF800) == 0x0800)
+
+#define TT(x)				(((x) >> 2) & 0x3)
+#define TT_MSG(x)			tt_msgs[TT(x)]
+#define II(x)				(((x) >> 2) & 0x3)
+#define II_MSG(x)			ii_msgs[II(x)]
+#define LL(x)				(((x) >> 0) & 0x3)
+#define LL_MSG(x)			ll_msgs[LL(x)]
+#define TO(x)				(((x) >> 8) & 0x1)
+#define TO_MSG(x)			to_msgs[TO(x)]
+#define PP(x)				(((x) >> 9) & 0x3)
+#define PP_MSG(x)			pp_msgs[PP(x)]
+
+#define RRRR(x)				(((x) >> 4) & 0xf)
+#define RRRR_MSG(x)			((RRRR(x) < 9) ?  rrrr_msgs[RRRR(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)
+
+enum tt_ids {
+	TT_INSTR = 0,
+	TT_DATA,
+	TT_GEN,
+	TT_RESV,
+};
+
+enum ll_ids {
+	LL_RESV = 0,
+	LL_L1,
+	LL_L2,
+	LL_LG,
+};
+
+enum ii_ids {
+	II_MEM = 0,
+	II_RESV,
+	II_IO,
+	II_GEN,
+};
+
+enum rrrr_ids {
+	R4_GEN	= 0,
+	R4_RD,
+	R4_WR,
+	R4_DRD,
+	R4_DWR,
+	R4_IRD,
+	R4_PREF,
+	R4_EVICT,
+	R4_SNOOP,
+};
+
+extern const char *tt_msgs[];
+extern const char *ll_msgs[];
+extern const char *rrrr_msgs[];
+extern const char *pp_msgs[];
+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 {
+	bool (*dc_mce)(u16);
+	bool (*ic_mce)(u16);
+	bool (*nb_mce)(u16, u8);
+};
+
+void amd_report_gart_errors(bool);
+void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32));
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32));
+void amd_decode_nb_mce(int, struct mce *, u32);
+int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
+
+#endif /* _EDAC_MCE_AMD_H */
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
new file mode 100644
index 0000000..8d0688f
--- /dev/null
+++ b/drivers/edac/mce_amd_inj.c
@@ -0,0 +1,171 @@
+/*
+ * A simple MCE injection facility for testing the MCE decoding code. This
+ * driver should be built as module so that it can be loaded on production
+ * kernels for testing purposes.
+ *
+ * This file may be distributed under the terms of the GNU General Public
+ * License version 2.
+ *
+ * Copyright (c) 2010:  Borislav Petkov <borislav.petkov@amd.com>
+ *			Advanced Micro Devices Inc.
+ */
+
+#include <linux/kobject.h>
+#include <linux/sysdev.h>
+#include <linux/edac.h>
+#include <asm/mce.h>
+
+#include "mce_amd.h"
+
+struct edac_mce_attr {
+	struct attribute attr;
+	ssize_t (*show) (struct kobject *kobj, struct edac_mce_attr *attr, char *buf);
+	ssize_t (*store)(struct kobject *kobj, struct edac_mce_attr *attr,
+			 const char *buf, size_t count);
+};
+
+#define EDAC_MCE_ATTR(_name, _mode, _show, _store)			\
+static struct edac_mce_attr mce_attr_##_name = __ATTR(_name, _mode, _show, _store)
+
+static struct kobject *mce_kobj;
+
+/*
+ * Collect all the MCi_XXX settings
+ */
+static struct mce i_mce;
+
+#define MCE_INJECT_STORE(reg)						\
+static ssize_t edac_inject_##reg##_store(struct kobject *kobj,		\
+					 struct edac_mce_attr *attr,	\
+					 const char *data, size_t count)\
+{									\
+	int ret = 0;							\
+	unsigned long value;						\
+									\
+	ret = strict_strtoul(data, 16, &value);				\
+	if (ret < 0)							\
+		printk(KERN_ERR "Error writing MCE " #reg " field.\n");	\
+									\
+	i_mce.reg = value;						\
+									\
+	return count;							\
+}
+
+MCE_INJECT_STORE(status);
+MCE_INJECT_STORE(misc);
+MCE_INJECT_STORE(addr);
+
+#define MCE_INJECT_SHOW(reg)						\
+static ssize_t edac_inject_##reg##_show(struct kobject *kobj,		\
+					struct edac_mce_attr *attr,	\
+					char *buf)			\
+{									\
+	return sprintf(buf, "0x%016llx\n", i_mce.reg);			\
+}
+
+MCE_INJECT_SHOW(status);
+MCE_INJECT_SHOW(misc);
+MCE_INJECT_SHOW(addr);
+
+EDAC_MCE_ATTR(status, 0644, edac_inject_status_show, edac_inject_status_store);
+EDAC_MCE_ATTR(misc, 0644, edac_inject_misc_show, edac_inject_misc_store);
+EDAC_MCE_ATTR(addr, 0644, edac_inject_addr_show, edac_inject_addr_store);
+
+/*
+ * This denotes into which bank we're injecting and triggers
+ * the injection, at the same time.
+ */
+static ssize_t edac_inject_bank_store(struct kobject *kobj,
+				      struct edac_mce_attr *attr,
+				      const char *data, size_t count)
+{
+	int ret = 0;
+	unsigned long value;
+
+	ret = strict_strtoul(data, 10, &value);
+	if (ret < 0) {
+		printk(KERN_ERR "Invalid bank value!\n");
+		return -EINVAL;
+	}
+
+	if (value > 5) {
+		printk(KERN_ERR "Non-existant MCE bank: %lu\n", value);
+		return -EINVAL;
+	}
+
+	i_mce.bank = value;
+
+	amd_decode_mce(NULL, 0, &i_mce);
+
+	return count;
+}
+
+static ssize_t edac_inject_bank_show(struct kobject *kobj,
+				     struct edac_mce_attr *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", i_mce.bank);
+}
+
+EDAC_MCE_ATTR(bank, 0644, edac_inject_bank_show, edac_inject_bank_store);
+
+static struct edac_mce_attr *sysfs_attrs[] = { &mce_attr_status, &mce_attr_misc,
+					       &mce_attr_addr, &mce_attr_bank
+};
+
+static int __init edac_init_mce_inject(void)
+{
+	struct sysdev_class *edac_class = NULL;
+	int i, err = 0;
+
+	edac_class = edac_get_sysfs_class();
+	if (!edac_class)
+		return -EINVAL;
+
+	mce_kobj = kobject_create_and_add("mce", &edac_class->kset.kobj);
+	if (!mce_kobj) {
+		printk(KERN_ERR "Error creating a mce kset.\n");
+		err = -ENOMEM;
+		goto err_mce_kobj;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++) {
+		err = sysfs_create_file(mce_kobj, &sysfs_attrs[i]->attr);
+		if (err) {
+			printk(KERN_ERR "Error creating %s in sysfs.\n",
+					sysfs_attrs[i]->attr.name);
+			goto err_sysfs_create;
+		}
+	}
+	return 0;
+
+err_sysfs_create:
+	while (i-- >= 0)
+		sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+
+	kobject_del(mce_kobj);
+
+err_mce_kobj:
+	edac_put_sysfs_class();
+
+	return err;
+}
+
+static void __exit edac_exit_mce_inject(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++)
+		sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+
+	kobject_del(mce_kobj);
+
+	edac_put_sysfs_class();
+}
+
+module_init(edac_init_mce_inject);
+module_exit(edac_exit_mce_inject);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>");
+MODULE_AUTHOR("AMD Inc.");
+MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding");
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 33f8421..18fdd97 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -8,7 +8,6 @@
 
 #include <linux/bug.h>
 #include <linux/device.h>
-#include <linux/ethtool.h>
 #include <linux/firewire.h>
 #include <linux/firewire-constants.h>
 #include <linux/highmem.h>
@@ -1361,17 +1360,6 @@
 	return 0;
 }
 
-static void fwnet_get_drvinfo(struct net_device *net,
-			      struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, KBUILD_MODNAME);
-	strcpy(info->bus_info, "ieee1394");
-}
-
-static const struct ethtool_ops fwnet_ethtool_ops = {
-	.get_drvinfo = fwnet_get_drvinfo,
-};
-
 static const struct net_device_ops fwnet_netdev_ops = {
 	.ndo_open       = fwnet_open,
 	.ndo_stop	= fwnet_stop,
@@ -1390,7 +1378,6 @@
 	net->hard_header_len	= FWNET_HLEN;
 	net->type		= ARPHRD_IEEE1394;
 	net->tx_queue_len	= 10;
-	SET_ETHTOOL_OPS(net, &fwnet_ethtool_ops);
 }
 
 /* caller must hold fwnet_device_mutex */
diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
index 8528b10..bf184fb 100644
--- a/drivers/firewire/nosy.c
+++ b/drivers/firewire/nosy.c
@@ -405,6 +405,7 @@
 	.poll =			nosy_poll,
 	.open =			nosy_open,
 	.release =		nosy_release,
+	.llseek =		noop_llseek,
 };
 
 #define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 1b05896..9dcb17d 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2840,7 +2840,7 @@
 			       const struct pci_device_id *ent)
 {
 	struct fw_ohci *ohci;
-	u32 bus_options, max_receive, link_speed, version, link_enh;
+	u32 bus_options, max_receive, link_speed, version;
 	u64 guid;
 	int i, err, n_ir, n_it;
 	size_t size;
@@ -2894,23 +2894,6 @@
 	if (param_quirks)
 		ohci->quirks = param_quirks;
 
-	/* TI OHCI-Lynx and compatible: set recommended configuration bits. */
-	if (dev->vendor == PCI_VENDOR_ID_TI) {
-		pci_read_config_dword(dev, PCI_CFG_TI_LinkEnh, &link_enh);
-
-		/* adjust latency of ATx FIFO: use 1.7 KB threshold */
-		link_enh &= ~TI_LinkEnh_atx_thresh_mask;
-		link_enh |= TI_LinkEnh_atx_thresh_1_7K;
-
-		/* use priority arbitration for asynchronous responses */
-		link_enh |= TI_LinkEnh_enab_unfair;
-
-		/* required for aPhyEnhanceEnable to work */
-		link_enh |= TI_LinkEnh_enab_accel;
-
-		pci_write_config_dword(dev, PCI_CFG_TI_LinkEnh, link_enh);
-	}
-
 	ar_context_init(&ohci->ar_request_ctx, ohci,
 			OHCI1394_AsReqRcvContextControlSet);
 
diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h
index 0e6c5a4..ef5e733 100644
--- a/drivers/firewire/ohci.h
+++ b/drivers/firewire/ohci.h
@@ -155,12 +155,4 @@
 
 #define OHCI1394_phy_tcode		0xe
 
-/* TI extensions */
-
-#define PCI_CFG_TI_LinkEnh		0xf4
-#define  TI_LinkEnh_enab_accel		0x00000002
-#define  TI_LinkEnh_enab_unfair		0x00000080
-#define  TI_LinkEnh_atx_thresh_mask	0x00003000
-#define  TI_LinkEnh_atx_thresh_1_7K	0x00001000
-
 #endif /* _FIREWIRE_OHCI_H */
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 280c9b5..88a3ae6 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -125,7 +125,7 @@
 config ISCSI_IBFT
 	tristate "iSCSI Boot Firmware Table Attributes module"
 	select ISCSI_BOOT_SYSFS
-	depends on ISCSI_IBFT_FIND && SCSI
+	depends on ISCSI_IBFT_FIND && SCSI && SCSI_LOWLEVEL
 	default	n
 	help
 	  This option enables support for detection and exposing of iSCSI
diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc35892-gpio.c
index 1be6288..7e10c93 100644
--- a/drivers/gpio/tc35892-gpio.c
+++ b/drivers/gpio/tc35892-gpio.c
@@ -322,6 +322,9 @@
 		goto out_freeirq;
 	}
 
+	if (pdata->setup)
+		pdata->setup(tc35892, tc35892_gpio->chip.base);
+
 	platform_set_drvdata(pdev, tc35892_gpio);
 
 	return 0;
@@ -338,9 +341,14 @@
 static int __devexit tc35892_gpio_remove(struct platform_device *pdev)
 {
 	struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev);
+	struct tc35892 *tc35892 = tc35892_gpio->tc35892;
+	struct tc35892_gpio_platform_data *pdata = tc35892->pdata->gpio;
 	int irq = platform_get_irq(pdev, 0);
 	int ret;
 
+	if (pdata->remove)
+		pdata->remove(tc35892, tc35892_gpio->chip.base);
+
 	ret = gpiochip_remove(&tc35892_gpio->chip);
 	if (ret < 0) {
 		dev_err(tc35892_gpio->dev,
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 4cab0c6..7af4436 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -73,7 +73,8 @@
 
 config DRM_I810
 	tristate "Intel I810"
-	depends on DRM && AGP && AGP_INTEL
+	# BKL usage in order to avoid AB-BA deadlocks, may become BROKEN_ON_SMP
+	depends on DRM && AGP && AGP_INTEL && BKL
 	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
@@ -86,6 +87,8 @@
 
 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
diff --git a/drivers/gpu/drm/drm_buffer.c b/drivers/gpu/drm/drm_buffer.c
index 55d03ed..529a0db 100644
--- a/drivers/gpu/drm/drm_buffer.c
+++ b/drivers/gpu/drm/drm_buffer.c
@@ -98,8 +98,8 @@
  *   user_data: A pointer the data that is copied to the buffer.
  *   size: The Number of bytes to copy.
  */
-extern int drm_buffer_copy_from_user(struct drm_buffer *buf,
-		void __user *user_data, int size)
+int drm_buffer_copy_from_user(struct drm_buffer *buf,
+			      void __user *user_data, int size)
 {
 	int nr_pages = size / PAGE_SIZE + 1;
 	int idx;
@@ -163,7 +163,7 @@
 {
 	int idx = drm_buffer_index(buf);
 	int page = drm_buffer_page(buf);
-	void *obj = 0;
+	void *obj = NULL;
 
 	if (idx + objsize <= PAGE_SIZE) {
 		obj = &buf->data[page][idx];
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 84da748..ff6690f 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -284,7 +284,8 @@
 /** File operations structure */
 static const struct file_operations drm_stub_fops = {
 	.owner = THIS_MODULE,
-	.open = drm_stub_open
+	.open = drm_stub_open,
+	.llseek = noop_llseek,
 };
 
 static int __init drm_core_init(void)
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index bf92d07..5663d27 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -148,7 +148,7 @@
 		return -ENOMEM;
 
 	kref_init(&obj->refcount);
-	kref_init(&obj->handlecount);
+	atomic_set(&obj->handle_count, 0);
 	obj->size = size;
 
 	atomic_inc(&dev->object_count);
@@ -462,28 +462,6 @@
 }
 EXPORT_SYMBOL(drm_gem_object_free);
 
-/**
- * Called after the last reference to the object has been lost.
- * Must be called without holding struct_mutex
- *
- * Frees the object
- */
-void
-drm_gem_object_free_unlocked(struct kref *kref)
-{
-	struct drm_gem_object *obj = (struct drm_gem_object *) kref;
-	struct drm_device *dev = obj->dev;
-
-	if (dev->driver->gem_free_object_unlocked != NULL)
-		dev->driver->gem_free_object_unlocked(obj);
-	else if (dev->driver->gem_free_object != NULL) {
-		mutex_lock(&dev->struct_mutex);
-		dev->driver->gem_free_object(obj);
-		mutex_unlock(&dev->struct_mutex);
-	}
-}
-EXPORT_SYMBOL(drm_gem_object_free_unlocked);
-
 static void drm_gem_object_ref_bug(struct kref *list_kref)
 {
 	BUG();
@@ -496,12 +474,8 @@
  * called before drm_gem_object_free or we'll be touching
  * freed memory
  */
-void
-drm_gem_object_handle_free(struct kref *kref)
+void drm_gem_object_handle_free(struct drm_gem_object *obj)
 {
-	struct drm_gem_object *obj = container_of(kref,
-						  struct drm_gem_object,
-						  handlecount);
 	struct drm_device *dev = obj->dev;
 
 	/* Remove any name for this object */
@@ -528,6 +502,10 @@
 	struct drm_gem_object *obj = vma->vm_private_data;
 
 	drm_gem_object_reference(obj);
+
+	mutex_lock(&obj->dev->struct_mutex);
+	drm_vm_open_locked(vma);
+	mutex_unlock(&obj->dev->struct_mutex);
 }
 EXPORT_SYMBOL(drm_gem_vm_open);
 
@@ -535,7 +513,10 @@
 {
 	struct drm_gem_object *obj = vma->vm_private_data;
 
-	drm_gem_object_unreference_unlocked(obj);
+	mutex_lock(&obj->dev->struct_mutex);
+	drm_vm_close_locked(vma);
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&obj->dev->struct_mutex);
 }
 EXPORT_SYMBOL(drm_gem_vm_close);
 
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index 2ef2c78..974e970 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -255,7 +255,7 @@
 
 	seq_printf(m, "%6d %8zd %7d %8d\n",
 		   obj->name, obj->size,
-		   atomic_read(&obj->handlecount.refcount),
+		   atomic_read(&obj->handle_count),
 		   atomic_read(&obj->refcount.refcount));
 	return 0;
 }
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
index fda6746..5df4506 100644
--- a/drivers/gpu/drm/drm_vm.c
+++ b/drivers/gpu/drm/drm_vm.c
@@ -433,6 +433,25 @@
 	mutex_unlock(&dev->struct_mutex);
 }
 
+void drm_vm_close_locked(struct vm_area_struct *vma)
+{
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->minor->dev;
+	struct drm_vma_entry *pt, *temp;
+
+	DRM_DEBUG("0x%08lx,0x%08lx\n",
+		  vma->vm_start, vma->vm_end - vma->vm_start);
+	atomic_dec(&dev->vma_count);
+
+	list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
+		if (pt->vma == vma) {
+			list_del(&pt->head);
+			kfree(pt);
+			break;
+		}
+	}
+}
+
 /**
  * \c close method for all virtual memory types.
  *
@@ -445,20 +464,9 @@
 {
 	struct drm_file *priv = vma->vm_file->private_data;
 	struct drm_device *dev = priv->minor->dev;
-	struct drm_vma_entry *pt, *temp;
-
-	DRM_DEBUG("0x%08lx,0x%08lx\n",
-		  vma->vm_start, vma->vm_end - vma->vm_start);
-	atomic_dec(&dev->vma_count);
 
 	mutex_lock(&dev->struct_mutex);
-	list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
-		if (pt->vma == vma) {
-			list_del(&pt->head);
-			kfree(pt);
-			break;
-		}
-	}
+	drm_vm_close_locked(vma);
 	mutex_unlock(&dev->struct_mutex);
 }
 
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index 61b4caf..ff33e53 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -116,9 +116,10 @@
 static const struct file_operations i810_buffer_fops = {
 	.open = drm_open,
 	.release = drm_release,
-	.unlocked_ioctl = drm_ioctl,
+	.unlocked_ioctl = i810_ioctl,
 	.mmap = i810_mmap_buffers,
 	.fasync = drm_fasync,
+	.llseek = noop_llseek,
 };
 
 static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c
index b4250b2..fe69914c 100644
--- a/drivers/gpu/drm/i810/i810_drv.c
+++ b/drivers/gpu/drm/i810/i810_drv.c
@@ -63,6 +63,7 @@
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
+		 .llseek = noop_llseek,
 	},
 
 	.pci_driver = {
diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c
index 671aa18..ca6f31f 100644
--- a/drivers/gpu/drm/i830/i830_dma.c
+++ b/drivers/gpu/drm/i830/i830_dma.c
@@ -118,9 +118,10 @@
 static const struct file_operations i830_buffer_fops = {
 	.open = drm_open,
 	.release = drm_release,
-	.unlocked_ioctl = drm_ioctl,
+	.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)
diff --git a/drivers/gpu/drm/i830/i830_drv.c b/drivers/gpu/drm/i830/i830_drv.c
index a5c66aa..5b6298b 100644
--- a/drivers/gpu/drm/i830/i830_drv.c
+++ b/drivers/gpu/drm/i830/i830_drv.c
@@ -74,6 +74,7 @@
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
+		 .llseek = noop_llseek,
 	},
 
 	.pci_driver = {
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 5e43d70..0481497 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -782,6 +782,7 @@
 	.open = i915_wedged_open,
 	.read = i915_wedged_read,
 	.write = i915_wedged_write,
+	.llseek = default_llseek,
 };
 
 /* As the drm_debugfs_init() routines are called before dev->dev_private is
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 9d67b48..2dd2c93 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1787,9 +1787,9 @@
 		}
 	}
 
-	div_u64(diff, diff1);
+	diff = div_u64(diff, diff1);
 	ret = ((m * diff) + c);
-	div_u64(ret, 10);
+	ret = div_u64(ret, 10);
 
 	dev_priv->last_count1 = total_count;
 	dev_priv->last_time1 = now;
@@ -1858,7 +1858,7 @@
 
 	/* More magic constants... */
 	diff = diff * 1181;
-	div_u64(diff, diffms * 10);
+	diff = div_u64(diff, diffms * 10);
 	dev_priv->gfx_power = diff;
 }
 
@@ -2231,6 +2231,9 @@
 	dev_priv->mchdev_lock = &mchdev_lock;
 	spin_unlock(&mchdev_lock);
 
+	/* XXX Prevent module unload due to memory corruption bugs. */
+	__module_get(THIS_MODULE);
+
 	return 0;
 
 out_workqueue_free:
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 6dbe14c..895ab89 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -548,6 +548,7 @@
 #ifdef CONFIG_COMPAT
 		 .compat_ioctl = i915_compat_ioctl,
 #endif
+		 .llseek = noop_llseek,
 	},
 
 	.pci_driver = {
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index cf4ffbe..90b1d67 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -136,14 +136,12 @@
 		return -ENOMEM;
 
 	ret = drm_gem_handle_create(file_priv, obj, &handle);
+	/* drop reference from allocate - handle holds it now */
+	drm_gem_object_unreference_unlocked(obj);
 	if (ret) {
-		drm_gem_object_unreference_unlocked(obj);
 		return ret;
 	}
 
-	/* Sink the floating reference from kref_init(handlecount) */
-	drm_gem_object_handle_unreference_unlocked(obj);
-
 	args->handle = handle;
 	return 0;
 }
@@ -471,14 +469,17 @@
 		return -ENOENT;
 	obj_priv = to_intel_bo(obj);
 
-	/* Bounds check source.
-	 *
-	 * XXX: This could use review for overflow issues...
-	 */
-	if (args->offset > obj->size || args->size > obj->size ||
-	    args->offset + args->size > obj->size) {
-		drm_gem_object_unreference_unlocked(obj);
-		return -EINVAL;
+	/* Bounds check source.  */
+	if (args->offset > obj->size || args->size > obj->size - args->offset) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (!access_ok(VERIFY_WRITE,
+		       (char __user *)(uintptr_t)args->data_ptr,
+		       args->size)) {
+		ret = -EFAULT;
+		goto err;
 	}
 
 	if (i915_gem_object_needs_bit17_swizzle(obj)) {
@@ -490,8 +491,8 @@
 							file_priv);
 	}
 
+err:
 	drm_gem_object_unreference_unlocked(obj);
-
 	return ret;
 }
 
@@ -580,8 +581,6 @@
 
 	user_data = (char __user *) (uintptr_t) args->data_ptr;
 	remain = args->size;
-	if (!access_ok(VERIFY_READ, user_data, remain))
-		return -EFAULT;
 
 
 	mutex_lock(&dev->struct_mutex);
@@ -934,14 +933,17 @@
 		return -ENOENT;
 	obj_priv = to_intel_bo(obj);
 
-	/* Bounds check destination.
-	 *
-	 * XXX: This could use review for overflow issues...
-	 */
-	if (args->offset > obj->size || args->size > obj->size ||
-	    args->offset + args->size > obj->size) {
-		drm_gem_object_unreference_unlocked(obj);
-		return -EINVAL;
+	/* Bounds check destination. */
+	if (args->offset > obj->size || args->size > obj->size - args->offset) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (!access_ok(VERIFY_READ,
+		       (char __user *)(uintptr_t)args->data_ptr,
+		       args->size)) {
+		ret = -EFAULT;
+		goto err;
 	}
 
 	/* We can only do the GTT pwrite on untiled buffers, as otherwise
@@ -975,8 +977,8 @@
 		DRM_INFO("pwrite failed %d\n", ret);
 #endif
 
+err:
 	drm_gem_object_unreference_unlocked(obj);
-
 	return ret;
 }
 
@@ -2400,7 +2402,7 @@
 		I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
 		break;
 	case 3:
-		if (obj_priv->fence_reg > 8)
+		if (obj_priv->fence_reg >= 8)
 			fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - 8) * 4;
 		else
 	case 2:
@@ -3258,6 +3260,8 @@
 				  (int) reloc->offset,
 				  reloc->read_domains,
 				  reloc->write_domain);
+			drm_gem_object_unreference(target_obj);
+			i915_gem_object_unpin(obj);
 			return -EINVAL;
 		}
 		if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index e85246e..5c428fa 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -93,7 +93,7 @@
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct list_head eviction_list, unwind_list;
-	struct drm_i915_gem_object *obj_priv, *tmp_obj_priv;
+	struct drm_i915_gem_object *obj_priv;
 	struct list_head *render_iter, *bsd_iter;
 	int ret = 0;
 
@@ -175,39 +175,34 @@
 	return -ENOSPC;
 
 found:
+	/* drm_mm doesn't allow any other other operations while
+	 * scanning, therefore store to be evicted objects on a
+	 * temporary list. */
 	INIT_LIST_HEAD(&eviction_list);
-	list_for_each_entry_safe(obj_priv, tmp_obj_priv,
-				 &unwind_list, evict_list) {
+	while (!list_empty(&unwind_list)) {
+		obj_priv = list_first_entry(&unwind_list,
+					    struct drm_i915_gem_object,
+					    evict_list);
 		if (drm_mm_scan_remove_block(obj_priv->gtt_space)) {
-			/* drm_mm doesn't allow any other other operations while
-			 * scanning, therefore store to be evicted objects on a
-			 * temporary list. */
 			list_move(&obj_priv->evict_list, &eviction_list);
-		} else
-			drm_gem_object_unreference(&obj_priv->base);
-	}
-
-	/* Unbinding will emit any required flushes */
-	list_for_each_entry_safe(obj_priv, tmp_obj_priv,
-				 &eviction_list, evict_list) {
-#if WATCH_LRU
-		DRM_INFO("%s: evicting %p\n", __func__, &obj_priv->base);
-#endif
-		ret = i915_gem_object_unbind(&obj_priv->base);
-		if (ret)
-			return ret;
-
+			continue;
+		}
+		list_del(&obj_priv->evict_list);
 		drm_gem_object_unreference(&obj_priv->base);
 	}
 
-	/* The just created free hole should be on the top of the free stack
-	 * maintained by drm_mm, so this BUG_ON actually executes in O(1).
-	 * Furthermore all accessed data has just recently been used, so it
-	 * should be really fast, too. */
-	BUG_ON(!drm_mm_search_free(&dev_priv->mm.gtt_space, min_size,
-				   alignment, 0));
+	/* Unbinding will emit any required flushes */
+	while (!list_empty(&eviction_list)) {
+		obj_priv = list_first_entry(&eviction_list,
+					    struct drm_i915_gem_object,
+					    evict_list);
+		if (ret == 0)
+			ret = i915_gem_object_unbind(&obj_priv->base);
+		list_del(&obj_priv->evict_list);
+		drm_gem_object_unreference(&obj_priv->base);
+	}
 
-	return 0;
+	return ret;
 }
 
 int
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b5bf51a..9792285 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1013,8 +1013,8 @@
 		DRM_DEBUG_KMS("vblank wait timed out\n");
 }
 
-/**
- * intel_wait_for_vblank_off - wait for vblank after disabling a pipe
+/*
+ * intel_wait_for_pipe_off - wait for pipe to turn off
  * @dev: drm device
  * @pipe: pipe to wait for
  *
@@ -1022,25 +1022,39 @@
  * spinning on the vblank interrupt status bit, since we won't actually
  * see an interrupt when the pipe is disabled.
  *
- * So this function waits for the display line value to settle (it
- * usually ends up stopping at the start of the next frame).
+ * On Gen4 and above:
+ *   wait for the pipe register state bit to turn off
+ *
+ * Otherwise:
+ *   wait for the display line value to settle (it usually
+ *   ends up stopping at the start of the next frame).
+ *  
  */
-void intel_wait_for_vblank_off(struct drm_device *dev, int pipe)
+static void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL);
-	unsigned long timeout = jiffies + msecs_to_jiffies(100);
-	u32 last_line;
 
-	/* Wait for the display line to settle */
-	do {
-		last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK;
-		mdelay(5);
-	} while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) &&
-		 time_after(timeout, jiffies));
+	if (INTEL_INFO(dev)->gen >= 4) {
+		int pipeconf_reg = (pipe == 0 ? PIPEACONF : PIPEBCONF);
 
-	if (time_after(jiffies, timeout))
-		DRM_DEBUG_KMS("vblank wait timed out\n");
+		/* Wait for the Pipe State to go off */
+		if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0,
+			     100, 0))
+			DRM_DEBUG_KMS("pipe_off wait timed out\n");
+	} else {
+		u32 last_line;
+		int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL);
+		unsigned long timeout = jiffies + msecs_to_jiffies(100);
+
+		/* Wait for the display line to settle */
+		do {
+			last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK;
+			mdelay(5);
+		} while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) &&
+			 time_after(timeout, jiffies));
+		if (time_after(jiffies, timeout))
+			DRM_DEBUG_KMS("pipe_off wait timed out\n");
+	}
 }
 
 /* Parameters have changed, update FBC info */
@@ -2328,13 +2342,13 @@
 			I915_READ(dspbase_reg);
 		}
 
-		/* Wait for vblank for the disable to take effect */
-		intel_wait_for_vblank_off(dev, pipe);
-
 		/* Don't disable pipe A or pipe A PLLs if needed */
 		if (pipeconf_reg == PIPEACONF &&
-		    (dev_priv->quirks & QUIRK_PIPEA_FORCE))
+		    (dev_priv->quirks & QUIRK_PIPEA_FORCE)) {
+			/* Wait for vblank for the disable to take effect */
+			intel_wait_for_vblank(dev, pipe);
 			goto skip_pipe_off;
+		}
 
 		/* Next, disable display pipes */
 		temp = I915_READ(pipeconf_reg);
@@ -2343,8 +2357,8 @@
 			I915_READ(pipeconf_reg);
 		}
 
-		/* Wait for vblank for the disable to take effect. */
-		intel_wait_for_vblank_off(dev, pipe);
+		/* Wait for the pipe to turn off */
+		intel_wait_for_pipe_off(dev, pipe);
 
 		temp = I915_READ(dpll_reg);
 		if ((temp & DPLL_VCO_ENABLE) != 0) {
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1a51ee0..9ab8708 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1138,18 +1138,14 @@
 intel_dp_set_link_train(struct intel_dp *intel_dp,
 			uint32_t dp_reg_value,
 			uint8_t dp_train_pat,
-			uint8_t train_set[4],
-			bool first)
+			uint8_t train_set[4])
 {
 	struct drm_device *dev = intel_dp->base.enc.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc);
 	int ret;
 
 	I915_WRITE(intel_dp->output_reg, dp_reg_value);
 	POSTING_READ(intel_dp->output_reg);
-	if (first)
-		intel_wait_for_vblank(dev, intel_crtc->pipe);
 
 	intel_dp_aux_native_write_1(intel_dp,
 				    DP_TRAINING_PATTERN_SET,
@@ -1174,10 +1170,15 @@
 	uint8_t voltage;
 	bool clock_recovery = false;
 	bool channel_eq = false;
-	bool first = true;
 	int tries;
 	u32 reg;
 	uint32_t DP = intel_dp->DP;
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc);
+
+	/* Enable output, wait for it to become active */
+	I915_WRITE(intel_dp->output_reg, intel_dp->DP);
+	POSTING_READ(intel_dp->output_reg);
+	intel_wait_for_vblank(dev, intel_crtc->pipe);
 
 	/* Write the link configuration data */
 	intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
@@ -1210,9 +1211,8 @@
 			reg = DP | DP_LINK_TRAIN_PAT_1;
 
 		if (!intel_dp_set_link_train(intel_dp, reg,
-					     DP_TRAINING_PATTERN_1, train_set, first))
+					     DP_TRAINING_PATTERN_1, train_set))
 			break;
-		first = false;
 		/* Set training pattern 1 */
 
 		udelay(100);
@@ -1266,8 +1266,7 @@
 
 		/* channel eq pattern */
 		if (!intel_dp_set_link_train(intel_dp, reg,
-					     DP_TRAINING_PATTERN_2, train_set,
-					     false))
+					     DP_TRAINING_PATTERN_2, train_set))
 			break;
 
 		udelay(400);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ad312ca..8828b3a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -229,7 +229,6 @@
 						    struct drm_crtc *crtc);
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
-extern void intel_wait_for_vblank_off(struct drm_device *dev, int pipe);
 extern void intel_wait_for_vblank(struct drm_device *dev, int pipe);
 extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe);
 extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 7bdc962..b61966c 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -237,8 +237,10 @@
 	drm_fb_helper_fini(&ifbdev->helper);
 
 	drm_framebuffer_cleanup(&ifb->base);
-	if (ifb->obj)
+	if (ifb->obj) {
 		drm_gem_object_unreference(ifb->obj);
+		ifb->obj = NULL;
+	}
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index e8e902d..ee73e42 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2170,8 +2170,7 @@
         return true;
 
 err:
-	intel_sdvo_destroy_enhance_property(connector);
-	kfree(intel_sdvo_connector);
+	intel_sdvo_destroy(connector);
 	return false;
 }
 
@@ -2243,8 +2242,7 @@
 	return true;
 
 err:
-	intel_sdvo_destroy_enhance_property(connector);
-	kfree(intel_sdvo_connector);
+	intel_sdvo_destroy(connector);
 	return false;
 }
 
@@ -2522,11 +2520,10 @@
 		uint16_t response;
 	} enhancements;
 
-	if (!intel_sdvo_get_value(intel_sdvo,
-				  SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS,
-				  &enhancements, sizeof(enhancements)))
-		return false;
-
+	enhancements.response = 0;
+	intel_sdvo_get_value(intel_sdvo,
+			     SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS,
+			     &enhancements, sizeof(enhancements));
 	if (enhancements.response == 0) {
 		DRM_DEBUG_KMS("No enhancement is supported\n");
 		return true;
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c
index 26d0d8c..ac64f0b 100644
--- a/drivers/gpu/drm/mga/mga_drv.c
+++ b/drivers/gpu/drm/mga/mga_drv.c
@@ -75,6 +75,7 @@
 #ifdef CONFIG_COMPAT
 		.compat_ioctl = mga_compat_ioctl,
 #endif
+		.llseek = noop_llseek,
 	},
 	.pci_driver = {
 		.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 87186a4..fc73703 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -558,8 +558,10 @@
 	if (nv_encoder->dcb->type == OUTPUT_LVDS &&
 	    (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
 	     dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) {
-		nv_connector->native_mode = drm_mode_create(dev);
-		nouveau_bios_fp_mode(dev, nv_connector->native_mode);
+		struct drm_display_mode mode;
+
+		nouveau_bios_fp_mode(dev, &mode);
+		nv_connector->native_mode = drm_mode_duplicate(dev, &mode);
 	}
 
 	/* Find the native mode if this is a digital panel, if we didn't
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index 1de5eb5..eb15345 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -393,6 +393,7 @@
 #if defined(CONFIG_COMPAT)
 		.compat_ioctl = nouveau_compat_ioctl,
 #endif
+		.llseek = noop_llseek,
 	},
 	.pci_driver = {
 		.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index ead7b8f..19620a6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -167,11 +167,9 @@
 		goto out;
 
 	ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle);
+	/* drop reference from allocate - handle holds it now */
+	drm_gem_object_unreference_unlocked(nvbo->gem);
 out:
-	drm_gem_object_handle_unreference_unlocked(nvbo->gem);
-
-	if (ret)
-		drm_gem_object_unreference_unlocked(nvbo->gem);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c
index 1e2971f..d42c76c 100644
--- a/drivers/gpu/drm/r128/r128_drv.c
+++ b/drivers/gpu/drm/r128/r128_drv.c
@@ -71,6 +71,7 @@
 #ifdef CONFIG_COMPAT
 		.compat_ioctl = r128_compat_ioctl,
 #endif
+		.llseek = noop_llseek,
 	},
 	.pci_driver = {
 		.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h
index 1bc72c3..fe359a2 100644
--- a/drivers/gpu/drm/radeon/atombios.h
+++ b/drivers/gpu/drm/radeon/atombios.h
@@ -4999,7 +4999,7 @@
 #define SW_I2C_CNTL_WRITE1BIT 6
 
 //==============================VESA definition Portion===============================
-#define VESA_OEM_PRODUCT_REV			            '01.00'
+#define VESA_OEM_PRODUCT_REV			            "01.00"
 #define VESA_MODE_ATTRIBUTE_MODE_SUPPORT	     0xBB	//refer to VBE spec p.32, no TTY support
 #define VESA_MODE_WIN_ATTRIBUTE						     7
 #define VESA_WIN_SIZE											     64
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 79082d4..2f93d46 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1137,7 +1137,7 @@
 
 		WREG32(RCU_IND_INDEX, 0x203);
 		efuse_straps_3 = RREG32(RCU_IND_DATA);
-		efuse_box_bit_127_124 = (u8)(efuse_straps_3 & 0xF0000000) >> 28;
+		efuse_box_bit_127_124 = (u8)((efuse_straps_3 & 0xF0000000) >> 28);
 
 		switch(efuse_box_bit_127_124) {
 		case 0x0:
@@ -1407,6 +1407,7 @@
 	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
 	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
+	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	r600_vram_gtt_location(rdev, &rdev->mc);
 	radeon_update_bandwidth_info(rdev);
 
@@ -1520,7 +1521,7 @@
 {
 	u32 tmp;
 
-	WREG32(CP_INT_CNTL, 0);
+	WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
 	WREG32(GRBM_INT_CNTL, 0);
 	WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
 	WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index e151f16..e594223 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1030,6 +1030,7 @@
 		return r;
 	}
 	rdev->cp.ready = true;
+	rdev->mc.active_vram_size = rdev->mc.real_vram_size;
 	return 0;
 }
 
@@ -1047,6 +1048,7 @@
 void r100_cp_disable(struct radeon_device *rdev)
 {
 	/* Disable ring */
+	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	rdev->cp.ready = false;
 	WREG32(RADEON_CP_CSQ_MODE, 0);
 	WREG32(RADEON_CP_CSQ_CNTL, 0);
@@ -2295,6 +2297,7 @@
 	/* FIXME we don't use the second aperture yet when we could use it */
 	if (rdev->mc.visible_vram_size > rdev->mc.aper_size)
 		rdev->mc.visible_vram_size = rdev->mc.aper_size;
+	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
 	if (rdev->flags & RADEON_IS_IGP) {
 		uint32_t tom;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index afc18d8..7b65e4ef 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1248,6 +1248,7 @@
 	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
+	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	r600_vram_gtt_location(rdev, &rdev->mc);
 
 	if (rdev->flags & RADEON_IS_IGP) {
@@ -1917,6 +1918,7 @@
  */
 void r600_cp_stop(struct radeon_device *rdev)
 {
+	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
 }
 
@@ -2729,7 +2731,7 @@
 	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;
 	}
@@ -2910,7 +2912,7 @@
 {
 	u32 tmp;
 
-	WREG32(CP_INT_CNTL, 0);
+	WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
 	WREG32(GRBM_INT_CNTL, 0);
 	WREG32(DxMODE_INT_MASK, 0);
 	if (ASIC_IS_DCE3(rdev)) {
@@ -3528,7 +3530,8 @@
 	/* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
 	 * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
 	 */
-	if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
+	if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
+	    rdev->vram_scratch.ptr) {
 		void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
 		u32 tmp;
 
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c
index 9ceb2a1..3473c00 100644
--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -532,6 +532,7 @@
 	memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4);
 	radeon_bo_kunmap(rdev->r600_blit.shader_obj);
 	radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+	rdev->mc.active_vram_size = rdev->mc.real_vram_size;
 	return 0;
 }
 
@@ -539,6 +540,7 @@
 {
 	int r;
 
+	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	if (rdev->r600_blit.shader_obj == NULL)
 		return;
 	/* If we can't reserve the bo, unref should be enough to destroy
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index a168d64..9ff38c9 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -344,6 +344,7 @@
 	 * about vram size near mc fb location */
 	u64			mc_vram_size;
 	u64			visible_vram_size;
+	u64			active_vram_size;
 	u64			gtt_size;
 	u64			gtt_start;
 	u64			gtt_end;
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index ebae14c..8e43dda 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -317,6 +317,15 @@
 			*connector_type = DRM_MODE_CONNECTOR_DVID;
 	}
 
+	/* MSI K9A2GM V2/V3 board has no HDMI or DVI */
+	if ((dev->pdev->device == 0x796e) &&
+	    (dev->pdev->subsystem_vendor == 0x1462) &&
+	    (dev->pdev->subsystem_device == 0x7302)) {
+		if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) ||
+		    (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
+			return false;
+	}
+
 	/* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
 	if ((dev->pdev->device == 0x7941) &&
 	    (dev->pdev->subsystem_vendor == 0x147b) &&
@@ -1549,39 +1558,39 @@
 		switch (tv_info->ucTV_BootUpDefaultStandard) {
 		case ATOM_TV_NTSC:
 			tv_std = TV_STD_NTSC;
-			DRM_INFO("Default TV standard: NTSC\n");
+			DRM_DEBUG_KMS("Default TV standard: NTSC\n");
 			break;
 		case ATOM_TV_NTSCJ:
 			tv_std = TV_STD_NTSC_J;
-			DRM_INFO("Default TV standard: NTSC-J\n");
+			DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
 			break;
 		case ATOM_TV_PAL:
 			tv_std = TV_STD_PAL;
-			DRM_INFO("Default TV standard: PAL\n");
+			DRM_DEBUG_KMS("Default TV standard: PAL\n");
 			break;
 		case ATOM_TV_PALM:
 			tv_std = TV_STD_PAL_M;
-			DRM_INFO("Default TV standard: PAL-M\n");
+			DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
 			break;
 		case ATOM_TV_PALN:
 			tv_std = TV_STD_PAL_N;
-			DRM_INFO("Default TV standard: PAL-N\n");
+			DRM_DEBUG_KMS("Default TV standard: PAL-N\n");
 			break;
 		case ATOM_TV_PALCN:
 			tv_std = TV_STD_PAL_CN;
-			DRM_INFO("Default TV standard: PAL-CN\n");
+			DRM_DEBUG_KMS("Default TV standard: PAL-CN\n");
 			break;
 		case ATOM_TV_PAL60:
 			tv_std = TV_STD_PAL_60;
-			DRM_INFO("Default TV standard: PAL-60\n");
+			DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
 			break;
 		case ATOM_TV_SECAM:
 			tv_std = TV_STD_SECAM;
-			DRM_INFO("Default TV standard: SECAM\n");
+			DRM_DEBUG_KMS("Default TV standard: SECAM\n");
 			break;
 		default:
 			tv_std = TV_STD_NTSC;
-			DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
+			DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n");
 			break;
 		}
 	}
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index a04b7a6..7b7ea26 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -913,47 +913,47 @@
 			switch (RBIOS8(tv_info + 7) & 0xf) {
 			case 1:
 				tv_std = TV_STD_NTSC;
-				DRM_INFO("Default TV standard: NTSC\n");
+				DRM_DEBUG_KMS("Default TV standard: NTSC\n");
 				break;
 			case 2:
 				tv_std = TV_STD_PAL;
-				DRM_INFO("Default TV standard: PAL\n");
+				DRM_DEBUG_KMS("Default TV standard: PAL\n");
 				break;
 			case 3:
 				tv_std = TV_STD_PAL_M;
-				DRM_INFO("Default TV standard: PAL-M\n");
+				DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
 				break;
 			case 4:
 				tv_std = TV_STD_PAL_60;
-				DRM_INFO("Default TV standard: PAL-60\n");
+				DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
 				break;
 			case 5:
 				tv_std = TV_STD_NTSC_J;
-				DRM_INFO("Default TV standard: NTSC-J\n");
+				DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
 				break;
 			case 6:
 				tv_std = TV_STD_SCART_PAL;
-				DRM_INFO("Default TV standard: SCART-PAL\n");
+				DRM_DEBUG_KMS("Default TV standard: SCART-PAL\n");
 				break;
 			default:
 				tv_std = TV_STD_NTSC;
-				DRM_INFO
+				DRM_DEBUG_KMS
 				    ("Unknown TV standard; defaulting to NTSC\n");
 				break;
 			}
 
 			switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) {
 			case 0:
-				DRM_INFO("29.498928713 MHz TV ref clk\n");
+				DRM_DEBUG_KMS("29.498928713 MHz TV ref clk\n");
 				break;
 			case 1:
-				DRM_INFO("28.636360000 MHz TV ref clk\n");
+				DRM_DEBUG_KMS("28.636360000 MHz TV ref clk\n");
 				break;
 			case 2:
-				DRM_INFO("14.318180000 MHz TV ref clk\n");
+				DRM_DEBUG_KMS("14.318180000 MHz TV ref clk\n");
 				break;
 			case 3:
-				DRM_INFO("27.000000000 MHz TV ref clk\n");
+				DRM_DEBUG_KMS("27.000000000 MHz TV ref clk\n");
 				break;
 			default:
 				break;
@@ -1324,7 +1324,7 @@
 
 	if (tmds_info) {
 		ver = RBIOS8(tmds_info);
-		DRM_INFO("DFP table revision: %d\n", ver);
+		DRM_DEBUG_KMS("DFP table revision: %d\n", ver);
 		if (ver == 3) {
 			n = RBIOS8(tmds_info + 5) + 1;
 			if (n > 4)
@@ -1408,7 +1408,7 @@
 		offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
 		if (offset) {
 			ver = RBIOS8(offset);
-			DRM_INFO("External TMDS Table revision: %d\n", ver);
+			DRM_DEBUG_KMS("External TMDS Table revision: %d\n", ver);
 			tmds->slave_addr = RBIOS8(offset + 4 + 2);
 			tmds->slave_addr >>= 1; /* 7 bit addressing */
 			gpio = RBIOS8(offset + 4 + 3);
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index 5731fc9..3eef567 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -203,6 +203,7 @@
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct radeon_device *rdev = crtc->dev->dev_private;
 	int xorigin = 0, yorigin = 0;
+	int w = radeon_crtc->cursor_width;
 
 	if (x < 0)
 		xorigin = -x + 1;
@@ -213,22 +214,7 @@
 	if (yorigin >= CURSOR_HEIGHT)
 		yorigin = CURSOR_HEIGHT - 1;
 
-	radeon_lock_cursor(crtc, true);
-	if (ASIC_IS_DCE4(rdev)) {
-		/* cursors are offset into the total surface */
-		x += crtc->x;
-		y += crtc->y;
-		DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
-
-		/* XXX: check if evergreen has the same issues as avivo chips */
-		WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset,
-		       ((xorigin ? 0 : x) << 16) |
-		       (yorigin ? 0 : y));
-		WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
-		WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
-		       ((radeon_crtc->cursor_width - 1) << 16) | (radeon_crtc->cursor_height - 1));
-	} else if (ASIC_IS_AVIVO(rdev)) {
-		int w = radeon_crtc->cursor_width;
+	if (ASIC_IS_AVIVO(rdev)) {
 		int i = 0;
 		struct drm_crtc *crtc_p;
 
@@ -260,7 +246,17 @@
 			if (w <= 0)
 				w = 1;
 		}
+	}
 
+	radeon_lock_cursor(crtc, true);
+	if (ASIC_IS_DCE4(rdev)) {
+		WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset,
+		       ((xorigin ? 0 : x) << 16) |
+		       (yorigin ? 0 : y));
+		WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
+		WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
+		       ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
+	} else if (ASIC_IS_AVIVO(rdev)) {
 		WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset,
 			     ((xorigin ? 0 : x) << 16) |
 			     (yorigin ? 0 : y));
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 127a395f..b92d2f2 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -349,6 +349,8 @@
 					DRM_INFO("    DFP4: %s\n", encoder_names[radeon_encoder->encoder_id]);
 				if (devices & ATOM_DEVICE_DFP5_SUPPORT)
 					DRM_INFO("    DFP5: %s\n", encoder_names[radeon_encoder->encoder_id]);
+				if (devices & ATOM_DEVICE_DFP6_SUPPORT)
+					DRM_INFO("    DFP6: %s\n", encoder_names[radeon_encoder->encoder_id]);
 				if (devices & ATOM_DEVICE_TV1_SUPPORT)
 					DRM_INFO("    TV1: %s\n", encoder_names[radeon_encoder->encoder_id]);
 				if (devices & ATOM_DEVICE_CV_SUPPORT)
@@ -841,8 +843,9 @@
 {
 	struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
 
-	if (radeon_fb->obj)
+	if (radeon_fb->obj) {
 		drm_gem_object_unreference_unlocked(radeon_fb->obj);
+	}
 	drm_framebuffer_cleanup(fb);
 	kfree(radeon_fb);
 }
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 795403b..29c1237 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -219,6 +219,7 @@
 #ifdef CONFIG_COMPAT
 		 .compat_ioctl = radeon_compat_ioctl,
 #endif
+		 .llseek = noop_llseek,
 	},
 
 	.pci_driver = {
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index c74a8b2..40b0c08 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -94,6 +94,7 @@
 	ret = radeon_bo_reserve(rbo, false);
 	if (likely(ret == 0)) {
 		radeon_bo_kunmap(rbo);
+		radeon_bo_unpin(rbo);
 		radeon_bo_unreserve(rbo);
 	}
 	drm_gem_object_unreference_unlocked(gobj);
@@ -325,8 +326,6 @@
 {
 	struct fb_info *info;
 	struct radeon_framebuffer *rfb = &rfbdev->rfb;
-	struct radeon_bo *rbo;
-	int r;
 
 	if (rfbdev->helper.fbdev) {
 		info = rfbdev->helper.fbdev;
@@ -338,14 +337,8 @@
 	}
 
 	if (rfb->obj) {
-		rbo = rfb->obj->driver_private;
-		r = radeon_bo_reserve(rbo, false);
-		if (likely(r == 0)) {
-			radeon_bo_kunmap(rbo);
-			radeon_bo_unpin(rbo);
-			radeon_bo_unreserve(rbo);
-		}
-		drm_gem_object_unreference_unlocked(rfb->obj);
+		radeonfb_destroy_pinned_object(rfb->obj);
+		rfb->obj = NULL;
 	}
 	drm_fb_helper_fini(&rfbdev->helper);
 	drm_framebuffer_cleanup(&rfb->base);
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index c578f26..d1e595d 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -201,11 +201,11 @@
 		return r;
 	}
 	r = drm_gem_handle_create(filp, gobj, &handle);
+	/* drop reference from allocate - handle holds it now */
+	drm_gem_object_unreference_unlocked(gobj);
 	if (r) {
-		drm_gem_object_unreference_unlocked(gobj);
 		return r;
 	}
-	drm_gem_object_handle_unreference_unlocked(gobj);
 	args->handle = handle;
 	return 0;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 5eee3c4..8fbbe1c 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -203,6 +203,10 @@
  */
 int radeon_driver_firstopen_kms(struct drm_device *dev)
 {
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (rdev->powered_down)
+		return -EINVAL;
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 0afd1e6..b3b5306 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -69,7 +69,7 @@
 	u32 c = 0;
 
 	rbo->placement.fpfn = 0;
-	rbo->placement.lpfn = 0;
+	rbo->placement.lpfn = rbo->rdev->mc.active_vram_size >> PAGE_SHIFT;
 	rbo->placement.placement = rbo->placements;
 	rbo->placement.busy_placement = rbo->placements;
 	if (domain & RADEON_GEM_DOMAIN_VRAM)
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index 353998d..3481bc7 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -124,11 +124,8 @@
 	int r;
 
 	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
-	if (unlikely(r != 0)) {
-		if (r != -ERESTARTSYS)
-			dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo);
+	if (unlikely(r != 0))
 		return r;
-	}
 	spin_lock(&bo->tbo.lock);
 	if (mem_type)
 		*mem_type = bo->tbo.mem.mem_type;
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index cc05b23..51d5f7b 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -693,6 +693,7 @@
 	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
 	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
+	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
 	base = RREG32_MC(R_000004_MC_FB_LOCATION);
 	base = G_000004_MC_FB_START(base) << 16;
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c
index 3e3f757..4dc2a87 100644
--- a/drivers/gpu/drm/radeon/rs690.c
+++ b/drivers/gpu/drm/radeon/rs690.c
@@ -157,6 +157,7 @@
 	rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
 	rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
+	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
 	base = G_000100_MC_FB_START(base) << 16;
 	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index bfa59db..9490da7 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -267,6 +267,7 @@
  */
 void r700_cp_stop(struct radeon_device *rdev)
 {
+	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
 }
 
@@ -992,6 +993,7 @@
 	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
+	rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
 	r600_vram_gtt_location(rdev, &rdev->mc);
 	radeon_update_bandwidth_info(rdev);
 
diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c
index 021de44..2a2830f 100644
--- a/drivers/gpu/drm/savage/savage_drv.c
+++ b/drivers/gpu/drm/savage/savage_drv.c
@@ -54,6 +54,7 @@
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
+		 .llseek = noop_llseek,
 	},
 
 	.pci_driver = {
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c
index 776bf9e..4bb10ef 100644
--- a/drivers/gpu/drm/sis/sis_drv.c
+++ b/drivers/gpu/drm/sis/sis_drv.c
@@ -83,6 +83,7 @@
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
+		 .llseek = noop_llseek,
 	},
 	.pci_driver = {
 		 .name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c
index ec5a43e..640567e 100644
--- a/drivers/gpu/drm/tdfx/tdfx_drv.c
+++ b/drivers/gpu/drm/tdfx/tdfx_drv.c
@@ -52,6 +52,7 @@
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
+		 .llseek = noop_llseek,
 	},
 	.pci_driver = {
 		 .name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index cb4cf7e..db809e0 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -442,6 +442,43 @@
 }
 
 /**
+ * Call bo::reserved and with the lru lock held.
+ * Will release GPU memory type usage on destruction.
+ * This is the place to put in driver specific hooks.
+ * Will release the bo::reserved lock and the
+ * lru lock on exit.
+ */
+
+static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
+{
+	struct ttm_bo_global *glob = bo->glob;
+
+	if (bo->ttm) {
+
+		/**
+		 * Release the lru_lock, since we don't want to have
+		 * an atomic requirement on ttm_tt[unbind|destroy].
+		 */
+
+		spin_unlock(&glob->lru_lock);
+		ttm_tt_unbind(bo->ttm);
+		ttm_tt_destroy(bo->ttm);
+		bo->ttm = NULL;
+		spin_lock(&glob->lru_lock);
+	}
+
+	if (bo->mem.mm_node) {
+		drm_mm_put_block(bo->mem.mm_node);
+		bo->mem.mm_node = NULL;
+	}
+
+	atomic_set(&bo->reserved, 0);
+	wake_up_all(&bo->event_queue);
+	spin_unlock(&glob->lru_lock);
+}
+
+
+/**
  * If bo idle, remove from delayed- and lru lists, and unref.
  * If not idle, and already on delayed list, do nothing.
  * If not idle, and not on delayed list, put on delayed list,
@@ -456,6 +493,7 @@
 	int ret;
 
 	spin_lock(&bo->lock);
+retry:
 	(void) ttm_bo_wait(bo, false, false, !remove_all);
 
 	if (!bo->sync_obj) {
@@ -464,31 +502,52 @@
 		spin_unlock(&bo->lock);
 
 		spin_lock(&glob->lru_lock);
-		put_count = ttm_bo_del_from_lru(bo);
+		ret = ttm_bo_reserve_locked(bo, false, !remove_all, false, 0);
 
-		ret = ttm_bo_reserve_locked(bo, false, false, false, 0);
-		BUG_ON(ret);
-		if (bo->ttm)
-			ttm_tt_unbind(bo->ttm);
+		/**
+		 * Someone else has the object reserved. Bail and retry.
+		 */
+
+		if (unlikely(ret == -EBUSY)) {
+			spin_unlock(&glob->lru_lock);
+			spin_lock(&bo->lock);
+			goto requeue;
+		}
+
+		/**
+		 * We can re-check for sync object without taking
+		 * the bo::lock since setting the sync object requires
+		 * also bo::reserved. A busy object at this point may
+		 * be caused by another thread starting an accelerated
+		 * eviction.
+		 */
+
+		if (unlikely(bo->sync_obj)) {
+			atomic_set(&bo->reserved, 0);
+			wake_up_all(&bo->event_queue);
+			spin_unlock(&glob->lru_lock);
+			spin_lock(&bo->lock);
+			if (remove_all)
+				goto retry;
+			else
+				goto requeue;
+		}
+
+		put_count = ttm_bo_del_from_lru(bo);
 
 		if (!list_empty(&bo->ddestroy)) {
 			list_del_init(&bo->ddestroy);
 			++put_count;
 		}
-		if (bo->mem.mm_node) {
-			drm_mm_put_block(bo->mem.mm_node);
-			bo->mem.mm_node = NULL;
-		}
-		spin_unlock(&glob->lru_lock);
 
-		atomic_set(&bo->reserved, 0);
+		ttm_bo_cleanup_memtype_use(bo);
 
 		while (put_count--)
 			kref_put(&bo->list_kref, ttm_bo_ref_bug);
 
 		return 0;
 	}
-
+requeue:
 	spin_lock(&glob->lru_lock);
 	if (list_empty(&bo->ddestroy)) {
 		void *sync_obj = bo->sync_obj;
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 7cffb3e..3451a82 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -351,6 +351,7 @@
 	INIT_LIST_HEAD(&fbo->lru);
 	INIT_LIST_HEAD(&fbo->swap);
 	fbo->vm_node = NULL;
+	atomic_set(&fbo->cpu_writers, 0);
 
 	fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
 	kref_init(&fbo->list_kref);
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index ca90479..b1e02ff 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -69,7 +69,7 @@
 	spinlock_t		lock;
 	bool			fill_lock;
 	struct list_head	list;
-	int			gfp_flags;
+	gfp_t			gfp_flags;
 	unsigned		npages;
 	char			*name;
 	unsigned long		nfrees;
@@ -475,7 +475,7 @@
  * This function is reentrant if caller updates count depending on number of
  * pages returned in pages array.
  */
-static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags,
+static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags,
 		int ttm_flags, enum ttm_caching_state cstate, unsigned count)
 {
 	struct page **caching_array;
@@ -666,7 +666,7 @@
 {
 	struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
 	struct page *p = NULL;
-	int gfp_flags = GFP_USER;
+	gfp_t gfp_flags = GFP_USER;
 	int r;
 
 	/* set zero flag for page allocation if required */
@@ -818,7 +818,7 @@
 	return 0;
 }
 
-void ttm_page_alloc_fini()
+void ttm_page_alloc_fini(void)
 {
 	int i;
 
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
index 7a1b210..b8984a5 100644
--- a/drivers/gpu/drm/via/via_drv.c
+++ b/drivers/gpu/drm/via/via_drv.c
@@ -62,6 +62,7 @@
 		.mmap = drm_mmap,
 		.poll = drm_poll,
 		.fasync = drm_fasync,
+		.llseek = noop_llseek,
 		},
 	.pci_driver = {
 		.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 72ec2e2..2ef93df 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -148,13 +148,16 @@
 	{0, 0, 0}
 };
 
-static char *vmw_devname = "vmwgfx";
+static int enable_fbdev;
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmw_master_init(struct vmw_master *);
 static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
 			      void *ptr);
 
+MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
+module_param_named(enable_fbdev, enable_fbdev, int, 0600);
+
 static void vmw_print_capabilities(uint32_t capabilities)
 {
 	DRM_INFO("Capabilities:\n");
@@ -192,8 +195,6 @@
 {
 	int ret;
 
-	vmw_kms_save_vga(dev_priv);
-
 	ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("Unable to initialize FIFO.\n");
@@ -206,9 +207,35 @@
 static void vmw_release_device(struct vmw_private *dev_priv)
 {
 	vmw_fifo_release(dev_priv, &dev_priv->fifo);
-	vmw_kms_restore_vga(dev_priv);
 }
 
+int vmw_3d_resource_inc(struct vmw_private *dev_priv)
+{
+	int ret = 0;
+
+	mutex_lock(&dev_priv->release_mutex);
+	if (unlikely(dev_priv->num_3d_resources++ == 0)) {
+		ret = vmw_request_device(dev_priv);
+		if (unlikely(ret != 0))
+			--dev_priv->num_3d_resources;
+	}
+	mutex_unlock(&dev_priv->release_mutex);
+	return ret;
+}
+
+
+void vmw_3d_resource_dec(struct vmw_private *dev_priv)
+{
+	int32_t n3d;
+
+	mutex_lock(&dev_priv->release_mutex);
+	if (unlikely(--dev_priv->num_3d_resources == 0))
+		vmw_release_device(dev_priv);
+	n3d = (int32_t) dev_priv->num_3d_resources;
+	mutex_unlock(&dev_priv->release_mutex);
+
+	BUG_ON(n3d < 0);
+}
 
 static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 {
@@ -228,6 +255,7 @@
 	dev_priv->last_read_sequence = (uint32_t) -100;
 	mutex_init(&dev_priv->hw_mutex);
 	mutex_init(&dev_priv->cmdbuf_mutex);
+	mutex_init(&dev_priv->release_mutex);
 	rwlock_init(&dev_priv->resource_lock);
 	idr_init(&dev_priv->context_idr);
 	idr_init(&dev_priv->surface_idr);
@@ -244,6 +272,8 @@
 	dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
 	dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
 
+	dev_priv->enable_fb = enable_fbdev;
+
 	mutex_lock(&dev_priv->hw_mutex);
 
 	vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
@@ -343,17 +373,6 @@
 
 	dev->dev_private = dev_priv;
 
-	if (!dev->devname)
-		dev->devname = vmw_devname;
-
-	if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
-		ret = drm_irq_install(dev);
-		if (unlikely(ret != 0)) {
-			DRM_ERROR("Failed installing irq: %d\n", ret);
-			goto out_no_irq;
-		}
-	}
-
 	ret = pci_request_regions(dev->pdev, "vmwgfx probe");
 	dev_priv->stealth = (ret != 0);
 	if (dev_priv->stealth) {
@@ -369,26 +388,52 @@
 			goto out_no_device;
 		}
 	}
-	ret = vmw_request_device(dev_priv);
+	ret = vmw_kms_init(dev_priv);
 	if (unlikely(ret != 0))
-		goto out_no_device;
-	vmw_kms_init(dev_priv);
+		goto out_no_kms;
 	vmw_overlay_init(dev_priv);
-	vmw_fb_init(dev_priv);
+	if (dev_priv->enable_fb) {
+		ret = vmw_3d_resource_inc(dev_priv);
+		if (unlikely(ret != 0))
+			goto out_no_fifo;
+		vmw_kms_save_vga(dev_priv);
+		vmw_fb_init(dev_priv);
+		DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ?
+			 "Detected device 3D availability.\n" :
+			 "Detected no device 3D availability.\n");
+	} else {
+		DRM_INFO("Delayed 3D detection since we're not "
+			 "running the device in SVGA mode yet.\n");
+	}
+
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
+		ret = drm_irq_install(dev);
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Failed installing irq: %d\n", ret);
+			goto out_no_irq;
+		}
+	}
 
 	dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
 	register_pm_notifier(&dev_priv->pm_nb);
 
-	DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n");
-
 	return 0;
 
-out_no_device:
-	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
-		drm_irq_uninstall(dev_priv->dev);
-	if (dev->devname == vmw_devname)
-		dev->devname = NULL;
 out_no_irq:
+	if (dev_priv->enable_fb) {
+		vmw_fb_close(dev_priv);
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv);
+	}
+out_no_fifo:
+	vmw_overlay_close(dev_priv);
+	vmw_kms_close(dev_priv);
+out_no_kms:
+	if (dev_priv->stealth)
+		pci_release_region(dev->pdev, 2);
+	else
+		pci_release_regions(dev->pdev);
+out_no_device:
 	ttm_object_device_release(&dev_priv->tdev);
 out_err4:
 	iounmap(dev_priv->mmio_virt);
@@ -415,19 +460,20 @@
 
 	unregister_pm_notifier(&dev_priv->pm_nb);
 
-	vmw_fb_close(dev_priv);
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
+		drm_irq_uninstall(dev_priv->dev);
+	if (dev_priv->enable_fb) {
+		vmw_fb_close(dev_priv);
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv);
+	}
 	vmw_kms_close(dev_priv);
 	vmw_overlay_close(dev_priv);
-	vmw_release_device(dev_priv);
 	if (dev_priv->stealth)
 		pci_release_region(dev->pdev, 2);
 	else
 		pci_release_regions(dev->pdev);
 
-	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
-		drm_irq_uninstall(dev_priv->dev);
-	if (dev->devname == vmw_devname)
-		dev->devname = NULL;
 	ttm_object_device_release(&dev_priv->tdev);
 	iounmap(dev_priv->mmio_virt);
 	drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start,
@@ -500,7 +546,7 @@
 		struct drm_ioctl_desc *ioctl =
 		    &vmw_ioctls[nr - DRM_COMMAND_BASE];
 
-		if (unlikely(ioctl->cmd != cmd)) {
+		if (unlikely(ioctl->cmd_drv != cmd)) {
 			DRM_ERROR("Invalid command format, ioctl %d\n",
 				  nr - DRM_COMMAND_BASE);
 			return -EINVAL;
@@ -589,6 +635,16 @@
 	struct vmw_master *vmaster = vmw_master(file_priv->master);
 	int ret = 0;
 
+	if (!dev_priv->enable_fb) {
+		ret = vmw_3d_resource_inc(dev_priv);
+		if (unlikely(ret != 0))
+			return ret;
+		vmw_kms_save_vga(dev_priv);
+		mutex_lock(&dev_priv->hw_mutex);
+		vmw_write(dev_priv, SVGA_REG_TRACES, 0);
+		mutex_unlock(&dev_priv->hw_mutex);
+	}
+
 	if (active) {
 		BUG_ON(active != &dev_priv->fbdev_master);
 		ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
@@ -617,7 +673,13 @@
 	return 0;
 
 out_no_active_lock:
-	vmw_release_device(dev_priv);
+	if (!dev_priv->enable_fb) {
+		mutex_lock(&dev_priv->hw_mutex);
+		vmw_write(dev_priv, SVGA_REG_TRACES, 1);
+		mutex_unlock(&dev_priv->hw_mutex);
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv);
+	}
 	return ret;
 }
 
@@ -645,11 +707,23 @@
 
 	ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
 
+	if (!dev_priv->enable_fb) {
+		ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
+		if (unlikely(ret != 0))
+			DRM_ERROR("Unable to clean VRAM on master drop.\n");
+		mutex_lock(&dev_priv->hw_mutex);
+		vmw_write(dev_priv, SVGA_REG_TRACES, 1);
+		mutex_unlock(&dev_priv->hw_mutex);
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv);
+	}
+
 	dev_priv->active_master = &dev_priv->fbdev_master;
 	ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
 	ttm_vt_unlock(&dev_priv->fbdev_master.lock);
 
-	vmw_fb_on(dev_priv);
+	if (dev_priv->enable_fb)
+		vmw_fb_on(dev_priv);
 }
 
 
@@ -722,6 +796,7 @@
 	.irq_postinstall = vmw_irq_postinstall,
 	.irq_uninstall = vmw_irq_uninstall,
 	.irq_handler = vmw_irq_handler,
+	.get_vblank_counter = vmw_get_vblank_counter,
 	.reclaim_buffers_locked = NULL,
 	.get_map_ofs = drm_core_get_map_ofs,
 	.get_reg_ofs = drm_core_get_reg_ofs,
@@ -745,6 +820,7 @@
 #if defined(CONFIG_COMPAT)
 		 .compat_ioctl = drm_compat_ioctl,
 #endif
+		 .llseek = noop_llseek,
 		 },
 	.pci_driver = {
 		       .name = VMWGFX_DRIVER_NAME,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 429f917..58de639 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -277,6 +277,7 @@
 
 	bool stealth;
 	bool is_opened;
+	bool enable_fb;
 
 	/**
 	 * Master management.
@@ -285,6 +286,9 @@
 	struct vmw_master *active_master;
 	struct vmw_master fbdev_master;
 	struct notifier_block pm_nb;
+
+	struct mutex release_mutex;
+	uint32_t num_3d_resources;
 };
 
 static inline struct vmw_private *vmw_priv(struct drm_device *dev)
@@ -319,6 +323,9 @@
 	return val;
 }
 
+int vmw_3d_resource_inc(struct vmw_private *dev_priv);
+void vmw_3d_resource_dec(struct vmw_private *dev_priv);
+
 /**
  * GMR utilities - vmwgfx_gmr.c
  */
@@ -511,6 +518,7 @@
 			unsigned bbp, unsigned depth);
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
+u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc);
 
 /**
  * Overlay control - vmwgfx_overlay.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 870967a..409e172 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -615,6 +615,11 @@
 	if (unlikely(ret != 0))
 		goto err_unlock;
 
+	if (bo->mem.mem_type == TTM_PL_VRAM &&
+	    bo->mem.mm_node->start < bo->num_pages)
+		(void) ttm_bo_validate(bo, &vmw_sys_placement, false,
+				       false, false);
+
 	ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
 
 	/* Could probably bug on */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index e6a1eb7..0fe3176 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -106,6 +106,7 @@
 	mutex_lock(&dev_priv->hw_mutex);
 	dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
 	dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
+	dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
 	vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
 
 	min = 4;
@@ -175,6 +176,8 @@
 		  dev_priv->config_done_state);
 	vmw_write(dev_priv, SVGA_REG_ENABLE,
 		  dev_priv->enable_state);
+	vmw_write(dev_priv, SVGA_REG_TRACES,
+		  dev_priv->traces_state);
 
 	mutex_unlock(&dev_priv->hw_mutex);
 	vmw_fence_queue_takedown(&fifo->fence_queue);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 64d7f47..e882ba0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -898,7 +898,19 @@
 		save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
 		save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
 		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+		if (i == 0 && vmw_priv->num_displays == 1 &&
+		    save->width == 0 && save->height == 0) {
+
+			/*
+			 * It should be fairly safe to assume that these
+			 * values are uninitialized.
+			 */
+
+			save->width = vmw_priv->vga_width - save->pos_x;
+			save->height = vmw_priv->vga_height - save->pos_y;
+		}
 	}
+
 	return 0;
 }
 
@@ -984,3 +996,8 @@
 	ttm_read_unlock(&vmaster->lock);
 	return ret;
 }
+
+u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+	return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 7083b1a..11cb39e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -27,6 +27,8 @@
 
 #include "vmwgfx_kms.h"
 
+#define VMWGFX_LDU_NUM_DU 8
+
 #define vmw_crtc_to_ldu(x) \
 	container_of(x, struct vmw_legacy_display_unit, base.crtc)
 #define vmw_encoder_to_ldu(x) \
@@ -536,6 +538,10 @@
 
 int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
 {
+	struct drm_device *dev = dev_priv->dev;
+	int i;
+	int ret;
+
 	if (dev_priv->ldu_priv) {
 		DRM_INFO("ldu system already on\n");
 		return -EINVAL;
@@ -553,23 +559,24 @@
 
 	drm_mode_create_dirty_info_property(dev_priv->dev);
 
-	vmw_ldu_init(dev_priv, 0);
-	/* for old hardware without multimon only enable one display */
 	if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
-		vmw_ldu_init(dev_priv, 1);
-		vmw_ldu_init(dev_priv, 2);
-		vmw_ldu_init(dev_priv, 3);
-		vmw_ldu_init(dev_priv, 4);
-		vmw_ldu_init(dev_priv, 5);
-		vmw_ldu_init(dev_priv, 6);
-		vmw_ldu_init(dev_priv, 7);
+		for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i)
+			vmw_ldu_init(dev_priv, i);
+		ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU);
+	} else {
+		/* for old hardware without multimon only enable one display */
+		vmw_ldu_init(dev_priv, 0);
+		ret = drm_vblank_init(dev, 1);
 	}
 
-	return 0;
+	return ret;
 }
 
 int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
 {
+	struct drm_device *dev = dev_priv->dev;
+
+	drm_vblank_cleanup(dev);
 	if (!dev_priv->ldu_priv)
 		return -ENOSYS;
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 5f2d5df..c8c40e9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -211,6 +211,7 @@
 	cmd->body.cid = cpu_to_le32(res->id);
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	vmw_3d_resource_dec(dev_priv);
 }
 
 static int vmw_context_init(struct vmw_private *dev_priv,
@@ -247,6 +248,7 @@
 	cmd->body.cid = cpu_to_le32(res->id);
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	(void) vmw_3d_resource_inc(dev_priv);
 	vmw_resource_activate(res, vmw_hw_context_destroy);
 	return 0;
 }
@@ -406,6 +408,7 @@
 	cmd->body.sid = cpu_to_le32(res->id);
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	vmw_3d_resource_dec(dev_priv);
 }
 
 void vmw_surface_res_free(struct vmw_resource *res)
@@ -473,6 +476,7 @@
 	}
 
 	vmw_fifo_commit(dev_priv, submit_size);
+	(void) vmw_3d_resource_inc(dev_priv);
 	vmw_resource_activate(res, vmw_hw_surface_destroy);
 	return 0;
 }
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index b87569e..c380c65 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -598,7 +598,7 @@
 	pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count);
 }
 
-void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace)
+static void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace)
 {
 	struct vga_device *vgadev;
 	unsigned long flags;
@@ -1211,6 +1211,7 @@
 	.poll = vga_arb_fpoll,
 	.open = vga_arb_open,
 	.release = vga_arb_release,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice vga_arb_device = {
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 6369ba7..68a7e86 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -56,20 +56,20 @@
 	depends on HID
 
 config HID_3M_PCT
-	tristate "3M PCT"
+	tristate "3M PCT touchscreen"
 	depends on USB_HID
 	---help---
 	Support for 3M PCT touch screens.
 
 config HID_A4TECH
-	tristate "A4 tech" if EMBEDDED
+	tristate "A4 tech mice" if EMBEDDED
 	depends on USB_HID
 	default !EMBEDDED
 	---help---
 	Support for A4 tech X5 and WOP-35 / Trust 450L mice.
 
 config HID_ACRUX_FF
-	tristate "ACRUX force feedback support"
+	tristate "ACRUX force feedback"
 	depends on USB_HID
 	select INPUT_FF_MEMLESS
 	---help---
@@ -77,7 +77,7 @@
 	game controllers.
 
 config HID_APPLE
-	tristate "Apple" if EMBEDDED
+	tristate "Apple {i,Power,Mac}Books" if EMBEDDED
 	depends on (USB_HID || BT_HIDP)
 	default !EMBEDDED
 	---help---
@@ -88,7 +88,7 @@
 	MacBooks, MacBook Pros and Apple Aluminum.
 
 config HID_BELKIN
-	tristate "Belkin" if EMBEDDED
+	tristate "Belkin Flip KVM and Wireless keyboard" if EMBEDDED
 	depends on USB_HID
 	default !EMBEDDED
 	---help---
@@ -101,14 +101,14 @@
 	Support for Cando dual touch panel.
 
 config HID_CHERRY
-	tristate "Cherry" if EMBEDDED
+	tristate "Cherry Cymotion keyboard" if EMBEDDED
 	depends on USB_HID
 	default !EMBEDDED
 	---help---
 	Support for Cherry Cymotion keyboard.
 
 config HID_CHICONY
-	tristate "Chicony" if EMBEDDED
+	tristate "Chicony Tactical pad" if EMBEDDED
 	depends on USB_HID
 	default !EMBEDDED
 	---help---
@@ -130,20 +130,20 @@
 	  and some additional multimedia keys.
 
 config HID_CYPRESS
-	tristate "Cypress" if EMBEDDED
+	tristate "Cypress mouse and barcode readers" if EMBEDDED
 	depends on USB_HID
 	default !EMBEDDED
 	---help---
 	Support for cypress mouse and barcode readers.
 
 config HID_DRAGONRISE
-	tristate "DragonRise Inc. support"
+	tristate "DragonRise Inc. game controller"
 	depends on USB_HID
 	---help---
 	Say Y here if you have DragonRise Inc.game controllers.
 
 config DRAGONRISE_FF
-	bool "DragonRise Inc. force feedback support"
+	bool "DragonRise Inc. force feedback"
 	depends on HID_DRAGONRISE
 	select INPUT_FF_MEMLESS
 	---help---
@@ -157,46 +157,46 @@
 	Support for the eGalax dual-touch panel.
 
 config HID_ELECOM
-	tristate "ELECOM"
+	tristate "ELECOM BM084 bluetooth mouse"
 	depends on BT_HIDP
 	---help---
 	Support for the ELECOM BM084 (bluetooth mouse).
 
 config HID_EZKEY
-	tristate "Ezkey" if EMBEDDED
+	tristate "Ezkey BTC 8193 keyboard" if EMBEDDED
 	depends on USB_HID
 	default !EMBEDDED
 	---help---
 	Support for Ezkey BTC 8193 keyboard.
 
 config HID_KYE
-	tristate "Kye" if EMBEDDED
+	tristate "Kye/Genius Ergo Mouse" if EMBEDDED
 	depends on USB_HID
 	default !EMBEDDED
 	---help---
 	Support for Kye/Genius Ergo Mouse.
 
 config HID_GYRATION
-	tristate "Gyration"
+	tristate "Gyration remote control"
 	depends on USB_HID
 	---help---
 	Support for Gyration remote control.
 
 config HID_TWINHAN
-	tristate "Twinhan"
+	tristate "Twinhan IR remote control"
 	depends on USB_HID
 	---help---
 	Support for Twinhan IR remote control.
 
 config HID_KENSINGTON
-	tristate "Kensington" if EMBEDDED
+	tristate "Kensington Slimblade Trackball" if EMBEDDED
 	depends on USB_HID
 	default !EMBEDDED
 	---help---
 	Support for Kensington Slimblade Trackball.
 
 config HID_LOGITECH
-	tristate "Logitech" if EMBEDDED
+	tristate "Logitech devices" if EMBEDDED
 	depends on USB_HID
 	default !EMBEDDED
 	---help---
@@ -220,12 +220,12 @@
 	  force feedback.
 
 config LOGIRUMBLEPAD2_FF
-	bool "Logitech Rumblepad 2 force feedback support"
+	bool "Logitech RumblePad/Rumblepad 2 force feedback support"
 	depends on HID_LOGITECH
 	select INPUT_FF_MEMLESS
 	help
 	  Say Y here if you want to enable force feedback support for Logitech
-	  Rumblepad 2 devices.
+	  RumblePad and Rumblepad 2 devices.
 
 config LOGIG940_FF
 	bool "Logitech Flight System G940 force feedback support"
@@ -235,6 +235,14 @@
 	  Say Y here if you want to enable force feedback support for Logitech
 	  Flight System G940 devices.
 
+config LOGIWII_FF
+	bool "Logitech Speed Force Wireless force feedback support"
+	depends on HID_LOGITECH
+	select INPUT_FF_MEMLESS
+	help
+	  Say Y here if you want to enable force feedback support for Logitech
+	  Speed Force Wireless (Wii) devices.
+
 config HID_MAGICMOUSE
 	tristate "Apple MagicMouse multi-touch support"
 	depends on BT_HIDP
@@ -245,39 +253,39 @@
 	Apple Wireless "Magic" Mouse.
 
 config HID_MICROSOFT
-	tristate "Microsoft" if EMBEDDED
+	tristate "Microsoft non-fully HID-compliant devices" if EMBEDDED
 	depends on USB_HID
 	default !EMBEDDED
 	---help---
 	Support for Microsoft devices that are not fully compliant with HID standard.
 
 config HID_MOSART
-	tristate "MosArt"
+	tristate "MosArt dual-touch panels"
 	depends on USB_HID
 	---help---
 	Support for MosArt dual-touch panels.
 
 config HID_MONTEREY
-	tristate "Monterey" if EMBEDDED
+	tristate "Monterey Genius KB29E keyboard" if EMBEDDED
 	depends on USB_HID
 	default !EMBEDDED
 	---help---
 	Support for Monterey Genius KB29E.
 
 config HID_NTRIG
-	tristate "NTrig"
+	tristate "N-Trig touch screen"
 	depends on USB_HID
 	---help---
 	Support for N-Trig touch screen.
 
 config HID_ORTEK
-	tristate "Ortek"
+	tristate "Ortek WKB-2000 wireless keyboard and mouse trackpad"
 	depends on USB_HID
 	---help---
 	Support for Ortek WKB-2000 wireless keyboard + mouse trackpad.
 
 config HID_PANTHERLORD
-	tristate "Pantherlord support"
+	tristate "Pantherlord/GreenAsia game controller"
 	depends on USB_HID
 	---help---
 	  Say Y here if you have a PantherLord/GreenAsia based game controller
@@ -292,7 +300,7 @@
 	  or adapter and want to enable force feedback support for it.
 
 config HID_PETALYNX
-	tristate "Petalynx"
+	tristate "Petalynx Maxter remote control"
 	depends on USB_HID
 	---help---
 	Support for Petalynx Maxter remote control.
@@ -356,7 +364,7 @@
 	  Provide access to PicoLCD's GPO pins via leds class.
 
 config HID_QUANTA
-	tristate "Quanta Optical Touch"
+	tristate "Quanta Optical Touch panels"
 	depends on USB_HID
 	---help---
 	Support for Quanta Optical Touch dual-touch panels.
@@ -376,32 +384,39 @@
 	---help---
 	Support for Roccat Kone mouse.
 
+config HID_ROCCAT_PYRA
+	tristate "Roccat Pyra mouse support"
+	depends on USB_HID
+	select HID_ROCCAT
+	---help---
+	Support for Roccat Pyra mouse.
+
 config HID_SAMSUNG
-	tristate "Samsung"
+	tristate "Samsung InfraRed remote control or keyboards"
 	depends on USB_HID
 	---help---
 	Support for Samsung InfraRed remote control or keyboards.
 
 config HID_SONY
-	tristate "Sony"
+	tristate "Sony PS3 controller"
 	depends on USB_HID
 	---help---
 	Support for Sony PS3 controller.
 
 config HID_STANTUM
-	tristate "Stantum"
+	tristate "Stantum multitouch panel"
 	depends on USB_HID
 	---help---
 	Support for Stantum multitouch panel.
 
 config HID_SUNPLUS
-	tristate "Sunplus"
+	tristate "Sunplus wireless desktop"
 	depends on USB_HID
 	---help---
 	Support for Sunplus wireless desktop.
 
 config HID_GREENASIA
-	tristate "GreenAsia (Product ID 0x12) support"
+	tristate "GreenAsia (Product ID 0x12) game controller support"
 	depends on USB_HID
 	---help---
 	  Say Y here if you have a GreenAsia (Product ID 0x12) based game
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 46f037f..ad74abc 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -21,6 +21,9 @@
 ifdef CONFIG_LOGIG940_FF
 	hid-logitech-objs	+= hid-lg3ff.o
 endif
+ifdef CONFIG_LOGIWII_FF
+	hid-logitech-objs	+= hid-lg4ff.o
+endif
 
 obj-$(CONFIG_HID_3M_PCT)	+= hid-3m-pct.o
 obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
@@ -52,6 +55,7 @@
 obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
 obj-$(CONFIG_HID_ROCCAT)	+= hid-roccat.o
 obj-$(CONFIG_HID_ROCCAT_KONE)	+= hid-roccat-kone.o
+obj-$(CONFIG_HID_ROCCAT_PYRA)	+= hid-roccat-pyra.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
 obj-$(CONFIG_HID_SONY)		+= hid-sony.o
diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c
index 2a0d56b..02d8cd3 100644
--- a/drivers/hid/hid-3m-pct.c
+++ b/drivers/hid/hid-3m-pct.c
@@ -2,6 +2,8 @@
  *  HID driver for 3M PCT multitouch panels
  *
  *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
+ *  Copyright (c) 2010      Henrik Rydberg <rydberg@euromail.se>
+ *  Copyright (c) 2010      Canonical, Ltd.
  *
  */
 
@@ -24,15 +26,26 @@
 
 #include "hid-ids.h"
 
+#define MAX_SLOTS		60
+#define MAX_TRKID		USHRT_MAX
+#define MAX_EVENTS		360
+
+/* estimated signal-to-noise ratios */
+#define SN_MOVE			2048
+#define SN_WIDTH		128
+
 struct mmm_finger {
 	__s32 x, y, w, h;
-	__u8 rank;
+	__u16 id;
+	bool prev_touch;
 	bool touch, valid;
 };
 
 struct mmm_data {
-	struct mmm_finger f[10];
-	__u8 curid, num;
+	struct mmm_finger f[MAX_SLOTS];
+	__u16 id;
+	__u8 curid;
+	__u8 nexp, nreal;
 	bool touch, valid;
 };
 
@@ -40,6 +53,10 @@
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
+	int f1 = field->logical_minimum;
+	int f2 = field->logical_maximum;
+	int df = f2 - f1;
+
 	switch (usage->hid & HID_USAGE_PAGE) {
 
 	case HID_UP_BUTTON:
@@ -50,18 +67,20 @@
 		case HID_GD_X:
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_POSITION_X);
+			input_set_abs_params(hi->input, ABS_MT_POSITION_X,
+					     f1, f2, df / SN_MOVE, 0);
 			/* touchscreen emulation */
 			input_set_abs_params(hi->input, ABS_X,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
+					     f1, f2, df / SN_MOVE, 0);
 			return 1;
 		case HID_GD_Y:
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_POSITION_Y);
+			input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
+					     f1, f2, df / SN_MOVE, 0);
 			/* touchscreen emulation */
 			input_set_abs_params(hi->input, ABS_Y,
-						field->logical_minimum,
-						field->logical_maximum, 0, 0);
+					     f1, f2, df / SN_MOVE, 0);
 			return 1;
 		}
 		return 0;
@@ -81,21 +100,31 @@
 		case HID_DG_TIPSWITCH:
 			/* touchscreen emulation */
 			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
+			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
 			return 1;
 		case HID_DG_WIDTH:
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_TOUCH_MAJOR);
+			input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR,
+					     f1, f2, df / SN_WIDTH, 0);
 			return 1;
 		case HID_DG_HEIGHT:
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_TOUCH_MINOR);
+			input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR,
+					     f1, f2, df / SN_WIDTH, 0);
 			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
-					1, 1, 0, 0);
+					0, 1, 0, 0);
 			return 1;
 		case HID_DG_CONTACTID:
-			field->logical_maximum = 59;
+			field->logical_maximum = MAX_TRKID;
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_TRACKING_ID);
+			input_set_abs_params(hi->input, ABS_MT_TRACKING_ID,
+					     0, MAX_TRKID, 0, 0);
+			if (!hi->input->mt)
+				input_mt_create_slots(hi->input, MAX_SLOTS);
+			input_set_events_per_packet(hi->input, MAX_EVENTS);
 			return 1;
 		}
 		/* let hid-input decide for the others */
@@ -113,10 +142,10 @@
 		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)
-		clear_bit(usage->code, *bit);
-
-	return 0;
+		set_bit(usage->type, hi->input->evbit);
+	return -1;
 }
 
 /*
@@ -126,70 +155,49 @@
 static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
 {
 	struct mmm_finger *oldest = 0;
-	bool pressed = false, released = false;
 	int i;
-
-	/*
-	 * we need to iterate on all fingers to decide if we have a press
-	 * or a release event in our touchscreen emulation.
-	 */
-	for (i = 0; i < 10; ++i) {
+	for (i = 0; i < MAX_SLOTS; ++i) {
 		struct mmm_finger *f = &md->f[i];
 		if (!f->valid) {
 			/* this finger is just placeholder data, ignore */
-		} else if (f->touch) {
+			continue;
+		}
+		input_mt_slot(input, i);
+		if (f->touch) {
 			/* this finger is on the screen */
 			int wide = (f->w > f->h);
-			input_event(input, EV_ABS, ABS_MT_TRACKING_ID, i);
+			/* divided by two to match visual scale of touch */
+			int major = max(f->w, f->h) >> 1;
+			int minor = min(f->w, f->h) >> 1;
+
+			if (!f->prev_touch)
+				f->id = md->id++;
+			input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id);
 			input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
 			input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
 			input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
-			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR,
-						wide ? f->w : f->h);
-			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR,
-						wide ? f->h : f->w);
-			input_mt_sync(input);
-			/*
-			 * touchscreen emulation: maintain the age rank
-			 * of this finger, decide if we have a press
-			 */
-			if (f->rank == 0) {
-				f->rank = ++(md->num);
-				if (f->rank == 1)
-					pressed = true;
-			}
-			if (f->rank == 1)
+			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
+			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
+			/* touchscreen emulation: pick the oldest contact */
+			if (!oldest || ((f->id - oldest->id) & (SHRT_MAX + 1)))
 				oldest = f;
 		} else {
 			/* this finger took off the screen */
-			/* touchscreen emulation: maintain age rank of others */
-			int j;
-
-			for (j = 0; j < 10; ++j) {
-				struct mmm_finger *g = &md->f[j];
-				if (g->rank > f->rank) {
-					g->rank--;
-					if (g->rank == 1)
-						oldest = g;
-				}
-			}
-			f->rank = 0;
-			--(md->num);
-			if (md->num == 0)
-				released = true;
+			input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1);
 		}
+		f->prev_touch = f->touch;
 		f->valid = 0;
 	}
 
 	/* touchscreen emulation */
 	if (oldest) {
-		if (pressed)
-			input_event(input, EV_KEY, BTN_TOUCH, 1);
+		input_event(input, EV_KEY, BTN_TOUCH, 1);
 		input_event(input, EV_ABS, ABS_X, oldest->x);
 		input_event(input, EV_ABS, ABS_Y, oldest->y);
-	} else if (released) {
+	} else {
 		input_event(input, EV_KEY, BTN_TOUCH, 0);
 	}
+	input_sync(input);
 }
 
 /*
@@ -223,10 +231,12 @@
 				md->f[md->curid].h = value;
 			break;
 		case HID_DG_CONTACTID:
+			value = clamp_val(value, 0, MAX_SLOTS - 1);
 			if (md->valid) {
 				md->curid = value;
 				md->f[value].touch = md->touch;
 				md->f[value].valid = 1;
+				md->nreal++;
 			}
 			break;
 		case HID_GD_X:
@@ -238,7 +248,12 @@
 				md->f[md->curid].y = value;
 			break;
 		case HID_DG_CONTACTCOUNT:
-			mmm_filter_event(md, input);
+			if (value)
+				md->nexp = value;
+			if (md->nreal >= md->nexp) {
+				mmm_filter_event(md, input);
+				md->nreal = 0;
+			}
 			break;
 		}
 	}
@@ -255,6 +270,8 @@
 	int ret;
 	struct mmm_data *md;
 
+	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
+
 	md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL);
 	if (!md) {
 		dev_err(&hdev->dev, "cannot allocate 3M data\n");
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c
index 3a2b223..1666c16 100644
--- a/drivers/hid/hid-a4tech.c
+++ b/drivers/hid/hid-a4tech.c
@@ -133,6 +133,8 @@
 		.driver_data = A4_2WHEEL_MOUSE_HACK_7 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D),
 		.driver_data = A4_2WHEEL_MOUSE_HACK_B8 },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649),
+		.driver_data = A4_2WHEEL_MOUSE_HACK_B8 },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, a4_devices);
diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c
index 4267a6f..5925bdc 100644
--- a/drivers/hid/hid-cando.c
+++ b/drivers/hid/hid-cando.c
@@ -237,6 +237,8 @@
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+		USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, cando_devices);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 3f72924..cb7dc99 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1241,6 +1241,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
 	{ 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
@@ -1248,6 +1249,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) },
@@ -1292,6 +1294,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
@@ -1326,6 +1329,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
@@ -1335,6 +1339,7 @@
 	{ 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_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) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) },
@@ -1370,12 +1375,15 @@
 	{ 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_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) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
@@ -1661,6 +1669,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_YUREX) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 850d02a..75c5e23 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -570,6 +570,8 @@
 				buf[i];
 		list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE;
         }
+
+	wake_up_interruptible(&hdev->debug_wait);
 }
 EXPORT_SYMBOL_GPL(hid_debug_event);
 
@@ -1051,6 +1053,7 @@
 	.read           = hid_debug_events_read,
 	.poll		= hid_debug_events_poll,
 	.release        = hid_debug_events_release,
+	.llseek		= noop_llseek,
 };
 
 
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 765a4f5..ae8f744 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -25,6 +25,7 @@
 #define USB_VENDOR_ID_A4TECH		0x09da
 #define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
 #define USB_DEVICE_ID_A4TECH_X5_005D	0x000a
+#define USB_DEVICE_ID_A4TECH_RP_649	0x001a
 
 #define USB_VENDOR_ID_AASHIMA		0x06d6
 #define USB_DEVICE_ID_AASHIMA_GAMEPAD	0x0025
@@ -63,6 +64,7 @@
 #define USB_VENDOR_ID_APPLE		0x05ac
 #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE	0x0304
 #define USB_DEVICE_ID_APPLE_MAGICMOUSE	0x030d
+#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD	0x030e
 #define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI	0x020e
 #define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO	0x020f
 #define USB_DEVICE_ID_APPLE_GEYSER_ANSI	0x0214
@@ -134,6 +136,7 @@
 #define USB_VENDOR_ID_CANDO		0x2087
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH	0x0a01
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
+#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
 
 #define USB_VENDOR_ID_CH		0x068e
 #define USB_DEVICE_ID_CH_PRO_PEDALS	0x00f2
@@ -141,6 +144,7 @@
 #define USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE       0x0051
 #define USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE	0x00ff
 #define USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK	0x00d3
+#define USB_DEVICE_ID_CH_AXIS_295	0x001c
 
 #define USB_VENDOR_ID_CHERRY		0x046a
 #define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023
@@ -303,6 +307,9 @@
 #define USB_VENDOR_ID_IMATION		0x0718
 #define USB_DEVICE_ID_DISC_STAKKA	0xd000
 
+#define USB_VENDOR_ID_JESS		0x0c45
+#define USB_DEVICE_ID_JESS_YUREX	0x1010
+
 #define USB_VENDOR_ID_KBGEAR		0x084e
 #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO	0x1001
 
@@ -339,6 +346,7 @@
 #define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
 #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST  0xc110
 #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
+#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD	0xc20a
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD	0xc211
 #define USB_DEVICE_ID_LOGITECH_EXTREME_3D	0xc215
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2	0xc218
@@ -350,6 +358,7 @@
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG	0xc293
 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL	0xc295
 #define USB_DEVICE_ID_LOGITECH_G25_WHEEL	0xc299
+#define USB_DEVICE_ID_LOGITECH_WII_WHEEL	0xc29c
 #define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
 #define USB_DEVICE_ID_S510_RECEIVER	0xc50c
 #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
@@ -462,6 +471,8 @@
 
 #define USB_VENDOR_ID_ROCCAT		0x1e7d
 #define USB_DEVICE_ID_ROCCAT_KONE	0x2ced
+#define USB_DEVICE_ID_ROCCAT_PYRA_WIRED	0x2c24
+#define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS	0x2cf6
 
 #define USB_VENDOR_ID_SAITEK		0x06a3
 #define USB_DEVICE_ID_SAITEK_RUMBLEPAD	0xff17
@@ -481,6 +492,12 @@
 #define USB_VENDOR_ID_STANTUM		0x1f87
 #define USB_DEVICE_ID_MTP		0x0002
 
+#define USB_VENDOR_ID_STANTUM_STM		0x0483
+#define USB_DEVICE_ID_MTP_STM		0x3261
+
+#define USB_VENDOR_ID_STANTUM_SITRONIX		0x1403
+#define USB_DEVICE_ID_MTP_SITRONIX		0x5001
+
 #define USB_VENDOR_ID_SUN		0x0430
 #define USB_DEVICE_ID_RARITAN_KVM_DONGLE	0xcdab
 
@@ -503,6 +520,7 @@
 
 #define USB_VENDOR_ID_TURBOX		0x062a
 #define USB_DEVICE_ID_TURBOX_KEYBOARD	0x0201
+#define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART	0x7100
 
 #define USB_VENDOR_ID_TWINHAN		0x6253
 #define USB_DEVICE_ID_TWINHAN_IR_REMOTE	0x0100
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 6c03dcc..b9877a8 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -149,6 +149,83 @@
 }
 
 
+/**
+ * hidinput_calc_abs_res - calculate an absolute axis resolution
+ * @field: the HID report field to calculate resolution for
+ * @code: axis code
+ *
+ * The formula is:
+ *                         (logical_maximum - logical_minimum)
+ * resolution = ----------------------------------------------------------
+ *              (physical_maximum - physical_minimum) * 10 ^ unit_exponent
+ *
+ * as seen in the HID specification v1.11 6.2.2.7 Global Items.
+ *
+ * Only exponent 1 length units are processed. Centimeters are converted to
+ * inches. Degrees are converted to radians.
+ */
+static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
+{
+	__s32 unit_exponent = field->unit_exponent;
+	__s32 logical_extents = field->logical_maximum -
+					field->logical_minimum;
+	__s32 physical_extents = field->physical_maximum -
+					field->physical_minimum;
+	__s32 prev;
+
+	/* Check if the extents are sane */
+	if (logical_extents <= 0 || physical_extents <= 0)
+		return 0;
+
+	/*
+	 * Verify and convert units.
+	 * See HID specification v1.11 6.2.2.7 Global Items for unit decoding
+	 */
+	if (code == ABS_X || code == ABS_Y || code == ABS_Z) {
+		if (field->unit == 0x11) {		/* If centimeters */
+			/* Convert to inches */
+			prev = logical_extents;
+			logical_extents *= 254;
+			if (logical_extents < prev)
+				return 0;
+			unit_exponent += 2;
+		} else if (field->unit != 0x13) {	/* If not inches */
+			return 0;
+		}
+	} else if (code == ABS_RX || code == ABS_RY || code == ABS_RZ) {
+		if (field->unit == 0x14) {		/* If degrees */
+			/* Convert to radians */
+			prev = logical_extents;
+			logical_extents *= 573;
+			if (logical_extents < prev)
+				return 0;
+			unit_exponent += 1;
+		} else if (field->unit != 0x12) {	/* If not radians */
+			return 0;
+		}
+	} else {
+		return 0;
+	}
+
+	/* Apply negative unit exponent */
+	for (; unit_exponent < 0; unit_exponent++) {
+		prev = logical_extents;
+		logical_extents *= 10;
+		if (logical_extents < prev)
+			return 0;
+	}
+	/* Apply positive unit exponent */
+	for (; unit_exponent > 0; unit_exponent--) {
+		prev = physical_extents;
+		physical_extents *= 10;
+		if (physical_extents < prev)
+			return 0;
+	}
+
+	/* Calculate resolution */
+	return logical_extents / physical_extents;
+}
+
 static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
 				     struct hid_usage *usage)
 {
@@ -537,6 +614,9 @@
 			input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4);
 		else	input_set_abs_params(input, usage->code, a, b, 0, 0);
 
+		input_abs_set_res(input, usage->code,
+				  hidinput_calc_abs_res(field, usage->code));
+
 		/* use a larger default input buffer for MT devices */
 		if (usage->code == ABS_MT_POSITION_X && input->hint_events_per_packet == 0)
 			input_set_events_per_packet(input, 60);
@@ -659,6 +739,9 @@
 {
 	struct hid_input *hidinput;
 
+	if (hid->quirks & HID_QUIRK_NO_INPUT_SYNC)
+		return;
+
 	list_for_each_entry(hidinput, &hid->inputs, list)
 		input_sync(hidinput->input);
 }
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index f6433d8..9e92c27 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -7,6 +7,7 @@
  *  Copyright (c) 2006-2007 Jiri Kosina
  *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
+ *  Copyright (c) 2010 Hendrik Iben
  */
 
 /*
@@ -19,6 +20,9 @@
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
 
 #include "hid-ids.h"
 #include "hid-lg.h"
@@ -35,6 +39,7 @@
 #define LG_FF2			0x400
 #define LG_RDESC_REL_ABS	0x800
 #define LG_FF3			0x1000
+#define LG_FF4			0x2000
 
 /*
  * Certain Logitech keyboards send in report #3 keys which are far
@@ -60,6 +65,17 @@
 				"report descriptor\n");
 		rdesc[33] = rdesc[50] = 0x02;
 	}
+
+	if ((quirks & LG_FF4) && rsize >= 101 &&
+			rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
+			rdesc[47] == 0x05 && rdesc[48] == 0x09) {
+		dev_info(&hdev->dev, "fixing up Logitech Speed Force Wireless "
+			"button descriptor\n");
+		rdesc[41] = 0x05;
+		rdesc[42] = 0x09;
+		rdesc[47] = 0x95;
+		rdesc[48] = 0x0B;
+	}
 }
 
 #define lg_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
@@ -285,12 +301,33 @@
 		goto err_free;
 	}
 
+	if (quirks & LG_FF4) {
+		unsigned char buf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+		ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
+
+		if (ret >= 0) {
+			/* insert a little delay of 10 jiffies ~ 40ms */
+			wait_queue_head_t wait;
+			init_waitqueue_head (&wait);
+			wait_event_interruptible_timeout(wait, 0, 10);
+
+			/* Select random Address */
+			buf[1] = 0xB2;
+			get_random_bytes(&buf[2], 2);
+
+			ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
+		}
+	}
+
 	if (quirks & LG_FF)
 		lgff_init(hdev);
 	if (quirks & LG_FF2)
 		lg2ff_init(hdev);
 	if (quirks & LG_FF3)
 		lg3ff_init(hdev);
+	if (quirks & LG_FF4)
+		lg4ff_init(hdev);
 
 	return 0;
 err_free:
@@ -325,6 +362,8 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
 		.driver_data = LG_NOGET | LG_FF },
 
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD),
+		.driver_data = LG_FF2 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
 		.driver_data = LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
@@ -339,6 +378,8 @@
 		.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_WII_WHEEL),
+		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
 		.driver_data = LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h
index ce2ac86..b0100ba 100644
--- a/drivers/hid/hid-lg.h
+++ b/drivers/hid/hid-lg.h
@@ -19,4 +19,10 @@
 static inline int lg3ff_init(struct hid_device *hdev) { return -1; }
 #endif
 
+#ifdef CONFIG_LOGIWII_FF
+int lg4ff_init(struct hid_device *hdev);
+#else
+static inline int lg4ff_init(struct hid_device *hdev) { return -1; }
+#endif
+
 #endif
diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c
index d888f1e..4258253 100644
--- a/drivers/hid/hid-lg2ff.c
+++ b/drivers/hid/hid-lg2ff.c
@@ -1,5 +1,5 @@
 /*
- *  Force feedback support for Logitech Rumblepad 2
+ *  Force feedback support for Logitech RumblePad and Rumblepad 2
  *
  *  Copyright (c) 2008 Anssi Hannula <anssi.hannula@gmail.com>
  */
@@ -110,7 +110,7 @@
 
 	usbhid_submit_report(hid, report, USB_DIR_OUT);
 
-	dev_info(&hid->dev, "Force feedback for Logitech Rumblepad 2 by "
+	dev_info(&hid->dev, "Force feedback for Logitech RumblePad/Rumblepad 2 by "
 	       "Anssi Hannula <anssi.hannula@gmail.com>\n");
 
 	return 0;
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
new file mode 100644
index 0000000..7eef5a2
--- /dev/null
+++ b/drivers/hid/hid-lg4ff.c
@@ -0,0 +1,136 @@
+/*
+ *  Force feedback support for Logitech Speed Force Wireless
+ *
+ *  http://wiibrew.org/wiki/Logitech_USB_steering_wheel
+ *
+ *  Copyright (c) 2010 Simon Wood <simon@mungewell.org>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+
+#include "usbhid/usbhid.h"
+#include "hid-lg.h"
+
+struct lg4ff_device {
+	struct hid_report *report;
+};
+
+static const signed short ff4_wheel_ac[] = {
+	FF_CONSTANT,
+	FF_AUTOCENTER,
+	-1
+};
+
+static int hid_lg4ff_play(struct input_dev *dev, void *data,
+			 struct ff_effect *effect)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	int x;
+
+#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff
+
+	switch (effect->type) {
+	case FF_CONSTANT:
+		x = effect->u.ramp.start_level + 0x80;	/* 0x80 is no force */
+		CLAMP(x);
+		report->field[0]->value[0] = 0x11;	/* Slot 1 */
+		report->field[0]->value[1] = 0x10;
+		report->field[0]->value[2] = x;
+		report->field[0]->value[3] = 0x00;
+		report->field[0]->value[4] = 0x00;
+		report->field[0]->value[5] = 0x08;
+		report->field[0]->value[6] = 0x00;
+		dbg_hid("Autocenter, x=0x%02X\n", x);
+
+		usbhid_submit_report(hid, report, USB_DIR_OUT);
+		break;
+	}
+	return 0;
+}
+
+static void hid_lg4ff_set_autocenter(struct input_dev *dev, u16 magnitude)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	__s32 *value = report->field[0]->value;
+
+	*value++ = 0xfe;
+	*value++ = 0x0d;
+	*value++ = 0x07;
+	*value++ = 0x07;
+	*value++ = (magnitude >> 8) & 0xff;
+	*value++ = 0x00;
+	*value = 0x00;
+
+	usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+
+int lg4ff_init(struct hid_device *hid)
+{
+	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct input_dev *dev = hidinput->input;
+	struct hid_report *report;
+	struct hid_field *field;
+	const signed short *ff_bits = ff4_wheel_ac;
+	int error;
+	int i;
+
+	/* Find the report to use */
+	if (list_empty(report_list)) {
+		err_hid("No output report found");
+		return -1;
+	}
+
+	/* Check that the report looks ok */
+	report = list_entry(report_list->next, struct hid_report, list);
+	if (!report) {
+		err_hid("NULL output report");
+		return -1;
+	}
+
+	field = report->field[0];
+	if (!field) {
+		err_hid("NULL field");
+		return -1;
+	}
+
+	for (i = 0; ff_bits[i] >= 0; i++)
+		set_bit(ff_bits[i], dev->ffbit);
+
+	error = input_ff_create_memless(dev, NULL, hid_lg4ff_play);
+
+	if (error)
+		return error;
+
+	if (test_bit(FF_AUTOCENTER, dev->ffbit))
+		dev->ff->set_autocenter = hid_lg4ff_set_autocenter;
+
+	dev_info(&hid->dev, "Force feedback for Logitech Speed Force Wireless by "
+			"Simon Wood <simon@mungewell.org>\n");
+	return 0;
+}
+
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 319b0e5..e6dc151 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -2,6 +2,7 @@
  *   Apple "Magic" Wireless Mouse driver
  *
  *   Copyright (c) 2010 Michael Poole <mdpoole@troilus.org>
+ *   Copyright (c) 2010 Chase Douglas <chase.douglas@canonical.com>
  */
 
 /*
@@ -53,7 +54,9 @@
 module_param(report_undeciphered, bool, 0644);
 MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event");
 
-#define TOUCH_REPORT_ID   0x29
+#define TRACKPAD_REPORT_ID 0x28
+#define MOUSE_REPORT_ID    0x29
+#define DOUBLE_REPORT_ID   0xf7
 /* These definitions are not precise, but they're close enough.  (Bits
  * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem
  * to be some kind of bit mask -- 0x20 may be a near-field reading,
@@ -67,15 +70,19 @@
 
 #define SCROLL_ACCEL_DEFAULT 7
 
+/* Single touch emulation should only begin when no touches are currently down.
+ * This is true when single_touch_id is equal to NO_TOUCHES. If multiple touches
+ * are down and the touch providing for single touch emulation is lifted,
+ * single_touch_id is equal to SINGLE_TOUCH_UP. While single touch emulation is
+ * occuring, single_touch_id corresponds with the tracking id of the touch used.
+ */
+#define NO_TOUCHES -1
+#define SINGLE_TOUCH_UP -2
+
 /**
  * struct magicmouse_sc - Tracks Magic Mouse-specific data.
  * @input: Input device through which we report events.
  * @quirks: Currently unused.
- * @last_timestamp: Timestamp from most recent (18-bit) touch report
- *     (units of milliseconds over short windows, but seems to
- *     increase faster when there are no touches).
- * @delta_time: 18-bit difference between the two most recent touch
- *     reports from the mouse.
  * @ntouches: Number of touches in most recent touch report.
  * @scroll_accel: Number of consecutive scroll motions.
  * @scroll_jiffies: Time of last scroll motion.
@@ -86,8 +93,6 @@
 	struct input_dev *input;
 	unsigned long quirks;
 
-	int last_timestamp;
-	int delta_time;
 	int ntouches;
 	int scroll_accel;
 	unsigned long scroll_jiffies;
@@ -98,9 +103,9 @@
 		short scroll_x;
 		short scroll_y;
 		u8 size;
-		u8 down;
 	} touches[16];
 	int tracking_ids[16];
+	int single_touch_id;
 };
 
 static int magicmouse_firm_touch(struct magicmouse_sc *msc)
@@ -166,18 +171,35 @@
 static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata)
 {
 	struct input_dev *input = msc->input;
-	__s32 x_y = tdata[0] << 8 | tdata[1] << 16 | tdata[2] << 24;
-	int misc = tdata[5] | tdata[6] << 8;
-	int id = (misc >> 6) & 15;
-	int x = x_y << 12 >> 20;
-	int y = -(x_y >> 20);
-	int down = (tdata[7] & TOUCH_STATE_MASK) != TOUCH_STATE_NONE;
+	int id, x, y, size, orientation, touch_major, touch_minor, state, down;
+
+	if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
+		id = (tdata[6] << 2 | tdata[5] >> 6) & 0xf;
+		x = (tdata[1] << 28 | tdata[0] << 20) >> 20;
+		y = -((tdata[2] << 24 | tdata[1] << 16) >> 20);
+		size = tdata[5] & 0x3f;
+		orientation = (tdata[6] >> 2) - 32;
+		touch_major = tdata[3];
+		touch_minor = tdata[4];
+		state = tdata[7] & TOUCH_STATE_MASK;
+		down = state != TOUCH_STATE_NONE;
+	} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
+		id = (tdata[7] << 2 | tdata[6] >> 6) & 0xf;
+		x = (tdata[1] << 27 | tdata[0] << 19) >> 19;
+		y = -((tdata[3] << 30 | tdata[2] << 22 | tdata[1] << 14) >> 19);
+		size = tdata[6] & 0x3f;
+		orientation = (tdata[7] >> 2) - 32;
+		touch_major = tdata[4];
+		touch_minor = tdata[5];
+		state = tdata[8] & TOUCH_STATE_MASK;
+		down = state != TOUCH_STATE_NONE;
+	}
 
 	/* Store tracking ID and other fields. */
 	msc->tracking_ids[raw_id] = id;
 	msc->touches[id].x = x;
 	msc->touches[id].y = y;
-	msc->touches[id].size = misc & 63;
+	msc->touches[id].size = size;
 
 	/* If requested, emulate a scroll wheel by detecting small
 	 * vertical touch motions.
@@ -188,7 +210,7 @@
 		int step_y = msc->touches[id].scroll_y - y;
 
 		/* Calculate and apply the scroll motion. */
-		switch (tdata[7] & TOUCH_STATE_MASK) {
+		switch (state) {
 		case TOUCH_STATE_START:
 			msc->touches[id].scroll_x = x;
 			msc->touches[id].scroll_y = y;
@@ -222,21 +244,28 @@
 		}
 	}
 
+	if (down) {
+		msc->ntouches++;
+		if (msc->single_touch_id == NO_TOUCHES)
+			msc->single_touch_id = id;
+	} else if (msc->single_touch_id == id)
+		msc->single_touch_id = SINGLE_TOUCH_UP;
+
 	/* Generate the input events for this touch. */
 	if (report_touches && down) {
-		int orientation = (misc >> 10) - 32;
-
-		msc->touches[id].down = 1;
-
 		input_report_abs(input, ABS_MT_TRACKING_ID, id);
-		input_report_abs(input, ABS_MT_TOUCH_MAJOR, tdata[3]);
-		input_report_abs(input, ABS_MT_TOUCH_MINOR, tdata[4]);
+		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_POSITION_X, x);
 		input_report_abs(input, ABS_MT_POSITION_Y, y);
 
-		if (report_undeciphered)
-			input_event(input, EV_MSC, MSC_RAW, tdata[7]);
+		if (report_undeciphered) {
+			if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
+				input_event(input, EV_MSC, MSC_RAW, tdata[7]);
+			else /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
+				input_event(input, EV_MSC, MSC_RAW, tdata[8]);
+		}
 
 		input_mt_sync(input);
 	}
@@ -247,39 +276,43 @@
 {
 	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
 	struct input_dev *input = msc->input;
-	int x, y, ts, ii, clicks, last_up;
+	int x = 0, y = 0, ii, clicks = 0, npoints;
 
 	switch (data[0]) {
-	case 0x10:
-		if (size != 6)
+	case TRACKPAD_REPORT_ID:
+		/* Expect four bytes of prefix, and N*9 bytes of touch data. */
+		if (size < 4 || ((size - 4) % 9) != 0)
 			return 0;
-		x = (__s16)(data[2] | data[3] << 8);
-		y = (__s16)(data[4] | data[5] << 8);
+		npoints = (size - 4) / 9;
+		msc->ntouches = 0;
+		for (ii = 0; ii < npoints; ii++)
+			magicmouse_emit_touch(msc, ii, data + ii * 9 + 4);
+
+		/* We don't need an MT sync here because trackpad emits a
+		 * BTN_TOUCH event in a new frame when all touches are released.
+		 */
+		if (msc->ntouches == 0)
+			msc->single_touch_id = NO_TOUCHES;
+
 		clicks = data[1];
+
+		/* The following bits provide a device specific timestamp. They
+		 * are unused here.
+		 *
+		 * ts = data[1] >> 6 | data[2] << 2 | data[3] << 10;
+		 */
 		break;
-	case TOUCH_REPORT_ID:
+	case MOUSE_REPORT_ID:
 		/* Expect six bytes of prefix, and N*8 bytes of touch data. */
 		if (size < 6 || ((size - 6) % 8) != 0)
 			return 0;
-		ts = data[3] >> 6 | data[4] << 2 | data[5] << 10;
-		msc->delta_time = (ts - msc->last_timestamp) & 0x3ffff;
-		msc->last_timestamp = ts;
-		msc->ntouches = (size - 6) / 8;
-		for (ii = 0; ii < msc->ntouches; ii++)
+		npoints = (size - 6) / 8;
+		msc->ntouches = 0;
+		for (ii = 0; ii < npoints; ii++)
 			magicmouse_emit_touch(msc, ii, data + ii * 8 + 6);
 
-		if (report_touches) {
-			last_up = 1;
-			for (ii = 0; ii < ARRAY_SIZE(msc->touches); ii++) {
-				if (msc->touches[ii].down) {
-					last_up = 0;
-					msc->touches[ii].down = 0;
-				}
-			}
-			if (last_up) {
-				input_mt_sync(input);
-			}
-		}
+		if (report_touches && msc->ntouches == 0)
+			input_mt_sync(input);
 
 		/* When emulating three-button mode, it is important
 		 * to have the current touch information before
@@ -288,68 +321,72 @@
 		x = (int)(((data[3] & 0x0c) << 28) | (data[1] << 22)) >> 22;
 		y = (int)(((data[3] & 0x30) << 26) | (data[2] << 22)) >> 22;
 		clicks = data[3];
+
+		/* The following bits provide a device specific timestamp. They
+		 * are unused here.
+		 *
+		 * ts = data[3] >> 6 | data[4] << 2 | data[5] << 10;
+		 */
 		break;
-	case 0x20: /* Theoretically battery status (0-100), but I have
-		    * never seen it -- maybe it is only upon request.
-		    */
-	case 0x60: /* Unknown, maybe laser on/off. */
-	case 0x61: /* Laser reflection status change.
-		    * data[1]: 0 = spotted, 1 = lost
-		    */
+	case DOUBLE_REPORT_ID:
+		/* Sometimes the trackpad sends two touch reports in one
+		 * packet.
+		 */
+		magicmouse_raw_event(hdev, report, data + 2, data[1]);
+		magicmouse_raw_event(hdev, report, data + 2 + data[1],
+			size - 2 - data[1]);
+		break;
 	default:
 		return 0;
 	}
 
-	magicmouse_emit_buttons(msc, clicks & 3);
-	input_report_rel(input, REL_X, x);
-	input_report_rel(input, REL_Y, y);
+	if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
+		magicmouse_emit_buttons(msc, clicks & 3);
+		input_report_rel(input, REL_X, x);
+		input_report_rel(input, REL_Y, y);
+	} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
+		input_report_key(input, BTN_MOUSE, clicks & 1);
+		input_report_key(input, BTN_TOUCH, msc->ntouches > 0);
+		input_report_key(input, BTN_TOOL_FINGER, msc->ntouches == 1);
+		input_report_key(input, BTN_TOOL_DOUBLETAP, msc->ntouches == 2);
+		input_report_key(input, BTN_TOOL_TRIPLETAP, msc->ntouches == 3);
+		input_report_key(input, BTN_TOOL_QUADTAP, msc->ntouches == 4);
+		if (msc->single_touch_id >= 0) {
+			input_report_abs(input, ABS_X,
+				msc->touches[msc->single_touch_id].x);
+			input_report_abs(input, ABS_Y,
+				msc->touches[msc->single_touch_id].y);
+		}
+	}
+
 	input_sync(input);
 	return 1;
 }
 
-static int magicmouse_input_open(struct input_dev *dev)
-{
-	struct hid_device *hid = input_get_drvdata(dev);
-
-	return hid->ll_driver->open(hid);
-}
-
-static void magicmouse_input_close(struct input_dev *dev)
-{
-	struct hid_device *hid = input_get_drvdata(dev);
-
-	hid->ll_driver->close(hid);
-}
-
 static void magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev)
 {
-	input_set_drvdata(input, hdev);
-	input->event = hdev->ll_driver->hidinput_input_event;
-	input->open = magicmouse_input_open;
-	input->close = magicmouse_input_close;
-
-	input->name = hdev->name;
-	input->phys = hdev->phys;
-	input->uniq = hdev->uniq;
-	input->id.bustype = hdev->bus;
-	input->id.vendor = hdev->vendor;
-	input->id.product = hdev->product;
-	input->id.version = hdev->version;
-	input->dev.parent = hdev->dev.parent;
-
 	__set_bit(EV_KEY, input->evbit);
-	__set_bit(BTN_LEFT, input->keybit);
-	__set_bit(BTN_RIGHT, input->keybit);
-	if (emulate_3button)
-		__set_bit(BTN_MIDDLE, input->keybit);
-	__set_bit(BTN_TOOL_FINGER, input->keybit);
 
-	__set_bit(EV_REL, input->evbit);
-	__set_bit(REL_X, input->relbit);
-	__set_bit(REL_Y, input->relbit);
-	if (emulate_scroll_wheel) {
-		__set_bit(REL_WHEEL, input->relbit);
-		__set_bit(REL_HWHEEL, input->relbit);
+	if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
+		__set_bit(BTN_LEFT, input->keybit);
+		__set_bit(BTN_RIGHT, input->keybit);
+		if (emulate_3button)
+			__set_bit(BTN_MIDDLE, input->keybit);
+
+		__set_bit(EV_REL, input->evbit);
+		__set_bit(REL_X, input->relbit);
+		__set_bit(REL_Y, input->relbit);
+		if (emulate_scroll_wheel) {
+			__set_bit(REL_WHEEL, input->relbit);
+			__set_bit(REL_HWHEEL, input->relbit);
+		}
+	} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
+		__set_bit(BTN_MOUSE, input->keybit);
+		__set_bit(BTN_TOOL_FINGER, input->keybit);
+		__set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
+		__set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
+		__set_bit(BTN_TOOL_QUADTAP, input->keybit);
+		__set_bit(BTN_TOUCH, input->keybit);
 	}
 
 	if (report_touches) {
@@ -359,16 +396,26 @@
 		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_POSITION_X, -1100, 1358,
-				4, 0);
+
 		/* Note: Touch Y position from the device is inverted relative
 		 * to how pointer motion is reported (and relative to how USB
 		 * HID recommends the coordinates work).  This driver keeps
 		 * the origin at the same position, and just uses the additive
 		 * inverse of the reported Y.
 		 */
-		input_set_abs_params(input, ABS_MT_POSITION_Y, -1589, 2047,
-				4, 0);
+		if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
+			input_set_abs_params(input, ABS_MT_POSITION_X, -1100,
+				1358, 4, 0);
+			input_set_abs_params(input, ABS_MT_POSITION_Y, -1589,
+				2047, 4, 0);
+		} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
+			input_set_abs_params(input, ABS_X, -2909, 3167, 4, 0);
+			input_set_abs_params(input, ABS_Y, -2456, 2565, 4, 0);
+			input_set_abs_params(input, ABS_MT_POSITION_X, -2909,
+				3167, 4, 0);
+			input_set_abs_params(input, ABS_MT_POSITION_Y, -2456,
+				2565, 4, 0);
+		}
 	}
 
 	if (report_undeciphered) {
@@ -377,12 +424,22 @@
 	}
 }
 
+static int magicmouse_input_mapping(struct hid_device *hdev,
+		struct hid_input *hi, struct hid_field *field,
+		struct hid_usage *usage, unsigned long **bit, int *max)
+{
+	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
+
+	if (!msc->input)
+		msc->input = hi->input;
+
+	return 0;
+}
+
 static int magicmouse_probe(struct hid_device *hdev,
 	const struct hid_device_id *id)
 {
-	__u8 feature_1[] = { 0xd7, 0x01 };
-	__u8 feature_2[] = { 0xf8, 0x01, 0x32 };
-	struct input_dev *input;
+	__u8 feature[] = { 0xd7, 0x01 };
 	struct magicmouse_sc *msc;
 	struct hid_report *report;
 	int ret;
@@ -398,6 +455,8 @@
 	msc->quirks = id->driver_data;
 	hid_set_drvdata(hdev, msc);
 
+	msc->single_touch_id = NO_TOUCHES;
+
 	ret = hid_parse(hdev);
 	if (ret) {
 		dev_err(&hdev->dev, "magicmouse hid parse failed\n");
@@ -410,10 +469,22 @@
 		goto err_free;
 	}
 
-	/* we are handling the input ourselves */
-	hidinput_disconnect(hdev);
+	/* We do this after hid-input is done parsing reports so that
+	 * hid-input uses the most natural button and axis IDs.
+	 */
+	if (msc->input)
+		magicmouse_setup_input(msc->input, hdev);
 
-	report = hid_register_report(hdev, HID_INPUT_REPORT, TOUCH_REPORT_ID);
+	if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
+		report = hid_register_report(hdev, HID_INPUT_REPORT,
+			MOUSE_REPORT_ID);
+	else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
+		report = hid_register_report(hdev, HID_INPUT_REPORT,
+			TRACKPAD_REPORT_ID);
+		report = hid_register_report(hdev, HID_INPUT_REPORT,
+			DOUBLE_REPORT_ID);
+	}
+
 	if (!report) {
 		dev_err(&hdev->dev, "unable to register touch report\n");
 		ret = -ENOMEM;
@@ -421,39 +492,15 @@
 	}
 	report->size = 6;
 
-	ret = hdev->hid_output_raw_report(hdev, feature_1, sizeof(feature_1),
+	ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature),
 			HID_FEATURE_REPORT);
-	if (ret != sizeof(feature_1)) {
-		dev_err(&hdev->dev, "unable to request touch data (1:%d)\n",
+	if (ret != sizeof(feature)) {
+		dev_err(&hdev->dev, "unable to request touch data (%d)\n",
 				ret);
 		goto err_stop_hw;
 	}
-	ret = hdev->hid_output_raw_report(hdev, feature_2,
-			sizeof(feature_2), HID_FEATURE_REPORT);
-	if (ret != sizeof(feature_2)) {
-		dev_err(&hdev->dev, "unable to request touch data (2:%d)\n",
-				ret);
-		goto err_stop_hw;
-	}
-
-	input = input_allocate_device();
-	if (!input) {
-		dev_err(&hdev->dev, "can't alloc input device\n");
-		ret = -ENOMEM;
-		goto err_stop_hw;
-	}
-	magicmouse_setup_input(input, hdev);
-
-	ret = input_register_device(input);
-	if (ret) {
-		dev_err(&hdev->dev, "input device registration failed\n");
-		goto err_input;
-	}
-	msc->input = input;
 
 	return 0;
-err_input:
-	input_free_device(input);
 err_stop_hw:
 	hid_hw_stop(hdev);
 err_free:
@@ -466,13 +513,14 @@
 	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
 
 	hid_hw_stop(hdev);
-	input_unregister_device(msc->input);
 	kfree(msc);
 }
 
 static const struct hid_device_id magic_mice[] = {
-	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE),
-		.driver_data = 0 },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+		USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+		USB_DEVICE_ID_APPLE_MAGICTRACKPAD), .driver_data = 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, magic_mice);
@@ -483,6 +531,7 @@
 	.probe = magicmouse_probe,
 	.remove = magicmouse_remove,
 	.raw_event = magicmouse_raw_event,
+	.input_mapping = magicmouse_input_mapping,
 };
 
 static int __init magicmouse_init(void)
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index fb69b8c..69169ef 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -90,6 +90,55 @@
 };
 
 
+/*
+ * This function converts the 4 byte raw firmware code into
+ * a string containing 5 comma separated numbers.
+ */
+static int ntrig_version_string(unsigned char *raw, char *buf)
+{
+	__u8 a =  (raw[1] & 0x0e) >> 1;
+	__u8 b =  (raw[0] & 0x3c) >> 2;
+	__u8 c = ((raw[0] & 0x03) << 3) | ((raw[3] & 0xe0) >> 5);
+	__u8 d = ((raw[3] & 0x07) << 3) | ((raw[2] & 0xe0) >> 5);
+	__u8 e =   raw[2] & 0x07;
+
+	/*
+	 * As yet unmapped bits:
+	 * 0b11000000 0b11110001 0b00011000 0b00011000
+	 */
+
+	return sprintf(buf, "%u.%u.%u.%u.%u", a, b, c, d, e);
+}
+
+static void ntrig_report_version(struct hid_device *hdev)
+{
+	int ret;
+	char buf[20];
+	struct usb_device *usb_dev = hid_to_usb_dev(hdev);
+	unsigned char *data = kmalloc(8, GFP_KERNEL);
+
+	if (!data)
+		goto err_free;
+
+	ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+			      USB_REQ_CLEAR_FEATURE,
+			      USB_TYPE_CLASS | USB_RECIP_INTERFACE |
+			      USB_DIR_IN,
+			      0x30c, 1, data, 8,
+			      USB_CTRL_SET_TIMEOUT);
+
+	if (ret == 8) {
+		ret = ntrig_version_string(&data[2], buf);
+
+		dev_info(&hdev->dev,
+			 "Firmware version: %s (%02x%02x %02x%02x)\n",
+			 buf, data[2], data[3], data[4], data[5]);
+	}
+
+err_free:
+	kfree(data);
+}
+
 static ssize_t show_phys_width(struct device *dev,
 			       struct device_attribute *attr,
 			       char *buf)
@@ -377,8 +426,8 @@
  */
 
 static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
+			       struct hid_field *field, struct hid_usage *usage,
+			       unsigned long **bit, int *max)
 {
 	struct ntrig_data *nd = hid_get_drvdata(hdev);
 
@@ -448,13 +497,13 @@
 		/* width/height mapped on TouchMajor/TouchMinor/Orientation */
 		case HID_DG_WIDTH:
 			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TOUCH_MAJOR);
+				      EV_ABS, ABS_MT_TOUCH_MAJOR);
 			return 1;
 		case HID_DG_HEIGHT:
 			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_TOUCH_MINOR);
+				      EV_ABS, ABS_MT_TOUCH_MINOR);
 			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
-					0, 1, 0, 0);
+					     0, 1, 0, 0);
 			return 1;
 		}
 		return 0;
@@ -468,8 +517,8 @@
 }
 
 static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
+			      struct hid_field *field, struct hid_usage *usage,
+			      unsigned long **bit, int *max)
 {
 	/* No special mappings needed for the pen and single touch */
 	if (field->physical)
@@ -489,7 +538,7 @@
  * and call input_mt_sync after each point if necessary
  */
 static int ntrig_event (struct hid_device *hid, struct hid_field *field,
-		                        struct hid_usage *usage, __s32 value)
+			struct hid_usage *usage, __s32 value)
 {
 	struct input_dev *input = field->hidinput->input;
 	struct ntrig_data *nd = hid_get_drvdata(hid);
@@ -848,6 +897,8 @@
 	if (report)
 		usbhid_submit_report(hdev, report, USB_DIR_OUT);
 
+	ntrig_report_version(hdev);
+
 	ret = sysfs_create_group(&hdev->dev.kobj,
 			&ntrig_attribute_group);
 
@@ -860,7 +911,7 @@
 static void ntrig_remove(struct hid_device *hdev)
 {
 	sysfs_remove_group(&hdev->dev.kobj,
-			&ntrig_attribute_group);
+			   &ntrig_attribute_group);
 	hid_hw_stop(hdev);
 	kfree(hid_get_drvdata(hdev));
 }
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
new file mode 100644
index 0000000..9bf2304
--- /dev/null
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -0,0 +1,968 @@
+/*
+ * Roccat Pyra driver for Linux
+ *
+ * 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.
+ */
+
+/*
+ * Roccat Pyra is a mobile gamer mouse which comes in wired and wireless
+ * variant. Wireless variant is not tested.
+ * Userland tools can be found at http://sourceforge.net/projects/roccat
+ */
+
+#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 "hid-ids.h"
+#include "hid-roccat.h"
+#include "hid-roccat-pyra.h"
+
+static void profile_activated(struct pyra_device *pyra,
+		unsigned int new_profile)
+{
+	pyra->actual_profile = new_profile;
+	pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi;
+}
+
+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 ||
+			request == PYRA_CONTROL_REQUEST_PROFILE_BUTTONS) &&
+			(value < 0 || value > 4))
+		return -EINVAL;
+
+	control.command = PYRA_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,
+			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;
+}
+
+static int pyra_receive_control_status(struct usb_device *usb_dev)
+{
+	int len;
+	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);
+
+		/* requested too early, try again */
+	} while (len == -EPROTO);
+
+	if (len == sizeof(struct pyra_control) &&
+			control.command == PYRA_COMMAND_CONTROL &&
+			control.request == PYRA_CONTROL_REQUEST_STATUS &&
+			control.value == 1)
+			return 0;
+	else {
+		dev_err(&usb_dev->dev, "receive control status: "
+				"unknown response 0x%x 0x%x\n",
+				control.request, control.value);
+		return -EINVAL;
+	}
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count, int number)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+
+	if (off >= sizeof(struct pyra_profile_settings))
+		return 0;
+
+	if (off + count > sizeof(struct pyra_profile_settings))
+		count = sizeof(struct pyra_profile_settings) - off;
+
+	mutex_lock(&pyra->pyra_lock);
+	memcpy(buf, ((char const *)&pyra->profile_settings[number]) + off,
+			count);
+	mutex_unlock(&pyra->pyra_lock);
+
+	return count;
+}
+
+static ssize_t pyra_sysfs_read_profile1_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return pyra_sysfs_read_profilex_settings(fp, kobj,
+			attr, buf, off, count, 0);
+}
+
+static ssize_t pyra_sysfs_read_profile2_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return pyra_sysfs_read_profilex_settings(fp, kobj,
+			attr, buf, off, count, 1);
+}
+
+static ssize_t pyra_sysfs_read_profile3_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return pyra_sysfs_read_profilex_settings(fp, kobj,
+			attr, buf, off, count, 2);
+}
+
+static ssize_t pyra_sysfs_read_profile4_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return pyra_sysfs_read_profilex_settings(fp, kobj,
+			attr, buf, off, count, 3);
+}
+
+static ssize_t pyra_sysfs_read_profile5_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return pyra_sysfs_read_profilex_settings(fp, kobj,
+			attr, buf, off, count, 4);
+}
+
+static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count, int number)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+
+	if (off >= sizeof(struct pyra_profile_buttons))
+		return 0;
+
+	if (off + count > sizeof(struct pyra_profile_buttons))
+		count = sizeof(struct pyra_profile_buttons) - off;
+
+	mutex_lock(&pyra->pyra_lock);
+	memcpy(buf, ((char const *)&pyra->profile_buttons[number]) + off,
+			count);
+	mutex_unlock(&pyra->pyra_lock);
+
+	return count;
+}
+
+static ssize_t pyra_sysfs_read_profile1_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return pyra_sysfs_read_profilex_buttons(fp, kobj,
+			attr, buf, off, count, 0);
+}
+
+static ssize_t pyra_sysfs_read_profile2_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return pyra_sysfs_read_profilex_buttons(fp, kobj,
+			attr, buf, off, count, 1);
+}
+
+static ssize_t pyra_sysfs_read_profile3_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return pyra_sysfs_read_profilex_buttons(fp, kobj,
+			attr, buf, off, count, 2);
+}
+
+static ssize_t pyra_sysfs_read_profile4_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return pyra_sysfs_read_profilex_buttons(fp, kobj,
+			attr, buf, off, count, 3);
+}
+
+static ssize_t pyra_sysfs_read_profile5_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return pyra_sysfs_read_profilex_buttons(fp, kobj,
+			attr, buf, off, count, 4);
+}
+
+static ssize_t pyra_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);
+	struct pyra_device *pyra = 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_number;
+	struct pyra_profile_settings *profile_settings;
+
+	if (off != 0 || count != sizeof(struct pyra_profile_settings))
+		return -EINVAL;
+
+	profile_number = ((struct pyra_profile_settings const *)buf)->number;
+	profile_settings = &pyra->profile_settings[profile_number];
+
+	mutex_lock(&pyra->pyra_lock);
+	difference = memcmp(buf, profile_settings,
+			sizeof(struct pyra_profile_settings));
+	if (difference) {
+		retval = pyra_set_profile_settings(usb_dev,
+				(struct pyra_profile_settings const *)buf);
+		if (!retval)
+			memcpy(profile_settings, buf,
+					sizeof(struct pyra_profile_settings));
+	}
+	mutex_unlock(&pyra->pyra_lock);
+
+	if (retval)
+		return retval;
+
+	return sizeof(struct pyra_profile_settings);
+}
+
+static ssize_t pyra_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);
+	struct pyra_device *pyra = 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_number;
+	struct pyra_profile_buttons *profile_buttons;
+
+	if (off != 0 || count != sizeof(struct pyra_profile_buttons))
+		return -EINVAL;
+
+	profile_number = ((struct pyra_profile_buttons const *)buf)->number;
+	profile_buttons = &pyra->profile_buttons[profile_number];
+
+	mutex_lock(&pyra->pyra_lock);
+	difference = memcmp(buf, profile_buttons,
+			sizeof(struct pyra_profile_buttons));
+	if (difference) {
+		retval = pyra_set_profile_buttons(usb_dev,
+				(struct pyra_profile_buttons const *)buf);
+		if (!retval)
+			memcpy(profile_buttons, buf,
+					sizeof(struct pyra_profile_buttons));
+	}
+	mutex_unlock(&pyra->pyra_lock);
+
+	if (retval)
+		return retval;
+
+	return sizeof(struct pyra_profile_buttons);
+}
+
+static ssize_t pyra_sysfs_read_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);
+	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+
+	if (off >= sizeof(struct pyra_settings))
+		return 0;
+
+	if (off + count > sizeof(struct pyra_settings))
+		count = sizeof(struct pyra_settings) - off;
+
+	mutex_lock(&pyra->pyra_lock);
+	memcpy(buf, ((char const *)&pyra->settings) + off, count);
+	mutex_unlock(&pyra->pyra_lock);
+
+	return count;
+}
+
+static ssize_t pyra_sysfs_write_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);
+	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval = 0;
+	int difference;
+
+	if (off != 0 || count != sizeof(struct pyra_settings))
+		return -EINVAL;
+
+	mutex_lock(&pyra->pyra_lock);
+	difference = memcmp(buf, &pyra->settings, sizeof(struct pyra_settings));
+	if (difference) {
+		retval = pyra_set_settings(usb_dev,
+				(struct pyra_settings const *)buf);
+		if (!retval)
+			memcpy(&pyra->settings, buf,
+					sizeof(struct pyra_settings));
+	}
+	mutex_unlock(&pyra->pyra_lock);
+
+	if (retval)
+		return retval;
+
+	profile_activated(pyra, pyra->settings.startup_profile);
+
+	return sizeof(struct pyra_settings);
+}
+
+
+static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi);
+}
+
+static ssize_t pyra_sysfs_show_actual_profile(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_profile);
+}
+
+static ssize_t pyra_sysfs_show_firmware_version(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->firmware_version);
+}
+
+static ssize_t pyra_sysfs_show_startup_profile(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->settings.startup_profile);
+}
+
+static DEVICE_ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL);
+
+static DEVICE_ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL);
+
+static DEVICE_ATTR(firmware_version, 0440,
+		pyra_sysfs_show_firmware_version, NULL);
+
+static DEVICE_ATTR(startup_profile, 0440,
+		pyra_sysfs_show_startup_profile, NULL);
+
+static struct attribute *pyra_attributes[] = {
+		&dev_attr_actual_cpi.attr,
+		&dev_attr_actual_profile.attr,
+		&dev_attr_firmware_version.attr,
+		&dev_attr_startup_profile.attr,
+		NULL
+};
+
+static struct attribute_group pyra_attribute_group = {
+		.attrs = pyra_attributes
+};
+
+static struct bin_attribute pyra_profile_settings_attr = {
+		.attr = { .name = "profile_settings", .mode = 0220 },
+		.size = sizeof(struct pyra_profile_settings),
+		.write = pyra_sysfs_write_profile_settings
+};
+
+static struct bin_attribute pyra_profile1_settings_attr = {
+		.attr = { .name = "profile1_settings", .mode = 0440 },
+		.size = sizeof(struct pyra_profile_settings),
+		.read = pyra_sysfs_read_profile1_settings
+};
+
+static struct bin_attribute pyra_profile2_settings_attr = {
+		.attr = { .name = "profile2_settings", .mode = 0440 },
+		.size = sizeof(struct pyra_profile_settings),
+		.read = pyra_sysfs_read_profile2_settings
+};
+
+static struct bin_attribute pyra_profile3_settings_attr = {
+		.attr = { .name = "profile3_settings", .mode = 0440 },
+		.size = sizeof(struct pyra_profile_settings),
+		.read = pyra_sysfs_read_profile3_settings
+};
+
+static struct bin_attribute pyra_profile4_settings_attr = {
+		.attr = { .name = "profile4_settings", .mode = 0440 },
+		.size = sizeof(struct pyra_profile_settings),
+		.read = pyra_sysfs_read_profile4_settings
+};
+
+static struct bin_attribute pyra_profile5_settings_attr = {
+		.attr = { .name = "profile5_settings", .mode = 0440 },
+		.size = sizeof(struct pyra_profile_settings),
+		.read = pyra_sysfs_read_profile5_settings
+};
+
+static struct bin_attribute pyra_profile_buttons_attr = {
+		.attr = { .name = "profile_buttons", .mode = 0220 },
+		.size = sizeof(struct pyra_profile_buttons),
+		.write = pyra_sysfs_write_profile_buttons
+};
+
+static struct bin_attribute pyra_profile1_buttons_attr = {
+		.attr = { .name = "profile1_buttons", .mode = 0440 },
+		.size = sizeof(struct pyra_profile_buttons),
+		.read = pyra_sysfs_read_profile1_buttons
+};
+
+static struct bin_attribute pyra_profile2_buttons_attr = {
+		.attr = { .name = "profile2_buttons", .mode = 0440 },
+		.size = sizeof(struct pyra_profile_buttons),
+		.read = pyra_sysfs_read_profile2_buttons
+};
+
+static struct bin_attribute pyra_profile3_buttons_attr = {
+		.attr = { .name = "profile3_buttons", .mode = 0440 },
+		.size = sizeof(struct pyra_profile_buttons),
+		.read = pyra_sysfs_read_profile3_buttons
+};
+
+static struct bin_attribute pyra_profile4_buttons_attr = {
+		.attr = { .name = "profile4_buttons", .mode = 0440 },
+		.size = sizeof(struct pyra_profile_buttons),
+		.read = pyra_sysfs_read_profile4_buttons
+};
+
+static struct bin_attribute pyra_profile5_buttons_attr = {
+		.attr = { .name = "profile5_buttons", .mode = 0440 },
+		.size = sizeof(struct pyra_profile_buttons),
+		.read = pyra_sysfs_read_profile5_buttons
+};
+
+static struct bin_attribute pyra_settings_attr = {
+		.attr = { .name = "settings", .mode = 0660 },
+		.size = sizeof(struct pyra_settings),
+		.read = pyra_sysfs_read_settings,
+		.write = pyra_sysfs_write_settings
+};
+
+static int pyra_create_sysfs_attributes(struct usb_interface *intf)
+{
+	int retval;
+
+	retval = sysfs_create_group(&intf->dev.kobj, &pyra_attribute_group);
+	if (retval)
+		goto exit_1;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile_settings_attr);
+	if (retval)
+		goto exit_2;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile1_settings_attr);
+	if (retval)
+		goto exit_3;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile2_settings_attr);
+	if (retval)
+		goto exit_4;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile3_settings_attr);
+	if (retval)
+		goto exit_5;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile4_settings_attr);
+	if (retval)
+		goto exit_6;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile5_settings_attr);
+	if (retval)
+		goto exit_7;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile_buttons_attr);
+	if (retval)
+		goto exit_8;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile1_buttons_attr);
+	if (retval)
+		goto exit_9;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile2_buttons_attr);
+	if (retval)
+		goto exit_10;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile3_buttons_attr);
+	if (retval)
+		goto exit_11;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile4_buttons_attr);
+	if (retval)
+		goto exit_12;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_profile5_buttons_attr);
+	if (retval)
+		goto exit_13;
+
+	retval = sysfs_create_bin_file(&intf->dev.kobj,
+			&pyra_settings_attr);
+	if (retval)
+		goto exit_14;
+
+	return 0;
+
+exit_14:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr);
+exit_13:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr);
+exit_12:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr);
+exit_11:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr);
+exit_10:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr);
+exit_9:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr);
+exit_8:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr);
+exit_7:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr);
+exit_6:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr);
+exit_5:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr);
+exit_4:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr);
+exit_3:
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr);
+exit_2:
+	sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group);
+exit_1:
+	return retval;
+}
+
+static void pyra_remove_sysfs_attributes(struct usb_interface *intf)
+{
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_settings_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr);
+	sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr);
+	sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group);
+}
+
+static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
+		struct pyra_device *pyra)
+{
+	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);
+		return retval;
+	}
+	pyra->firmware_version = info->firmware_version;
+	kfree(info);
+
+	retval = pyra_get_settings(usb_dev, &pyra->settings);
+	if (retval)
+		return retval;
+
+	for (i = 0; i < 5; ++i) {
+		retval = pyra_get_profile_settings(usb_dev,
+				&pyra->profile_settings[i], i);
+		if (retval)
+			return retval;
+
+		retval = pyra_get_profile_buttons(usb_dev,
+				&pyra->profile_buttons[i], i);
+		if (retval)
+			return retval;
+	}
+
+	profile_activated(pyra, pyra->settings.startup_profile);
+
+	return 0;
+}
+
+static int pyra_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 pyra_device *pyra;
+	int retval;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_MOUSE) {
+
+		pyra = kzalloc(sizeof(*pyra), GFP_KERNEL);
+		if (!pyra) {
+			dev_err(&hdev->dev, "can't alloc device descriptor\n");
+			return -ENOMEM;
+		}
+		hid_set_drvdata(hdev, pyra);
+
+		retval = pyra_init_pyra_device_struct(usb_dev, pyra);
+		if (retval) {
+			dev_err(&hdev->dev,
+					"couldn't init struct pyra_device\n");
+			goto exit_free;
+		}
+
+		retval = roccat_connect(hdev);
+		if (retval < 0) {
+			dev_err(&hdev->dev, "couldn't init char dev\n");
+		} else {
+			pyra->chrdev_minor = retval;
+			pyra->roccat_claimed = 1;
+		}
+
+		retval = pyra_create_sysfs_attributes(intf);
+		if (retval) {
+			dev_err(&hdev->dev, "cannot create sysfs files\n");
+			goto exit_free;
+		}
+	} else {
+		hid_set_drvdata(hdev, NULL);
+	}
+
+	return 0;
+exit_free:
+	kfree(pyra);
+	return retval;
+}
+
+static void pyra_remove_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct pyra_device *pyra;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_MOUSE) {
+		pyra_remove_sysfs_attributes(intf);
+		pyra = hid_get_drvdata(hdev);
+		if (pyra->roccat_claimed)
+			roccat_disconnect(pyra->chrdev_minor);
+		kfree(hid_get_drvdata(hdev));
+	}
+}
+
+static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int retval;
+
+	retval = hid_parse(hdev);
+	if (retval) {
+		dev_err(&hdev->dev, "parse failed\n");
+		goto exit;
+	}
+
+	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (retval) {
+		dev_err(&hdev->dev, "hw start failed\n");
+		goto exit;
+	}
+
+	retval = pyra_init_specials(hdev);
+	if (retval) {
+		dev_err(&hdev->dev, "couldn't install mouse\n");
+		goto exit_stop;
+	}
+	return 0;
+
+exit_stop:
+	hid_hw_stop(hdev);
+exit:
+	return retval;
+}
+
+static void pyra_remove(struct hid_device *hdev)
+{
+	pyra_remove_specials(hdev);
+	hid_hw_stop(hdev);
+}
+
+static void pyra_keep_values_up_to_date(struct pyra_device *pyra,
+		u8 const *data)
+{
+	struct pyra_mouse_event_button const *button_event;
+
+	switch (data[0]) {
+	case PYRA_MOUSE_REPORT_NUMBER_BUTTON:
+		button_event = (struct pyra_mouse_event_button const *)data;
+		switch (button_event->type) {
+		case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2:
+			profile_activated(pyra, button_event->data1 - 1);
+			break;
+		case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI:
+			pyra->actual_cpi = button_event->data1;
+			break;
+		}
+		break;
+	}
+}
+
+static void pyra_report_to_chrdev(struct pyra_device const *pyra,
+		u8 const *data)
+{
+	struct pyra_roccat_report roccat_report;
+	struct pyra_mouse_event_button const *button_event;
+
+	if (data[0] != PYRA_MOUSE_REPORT_NUMBER_BUTTON)
+		return;
+
+	button_event = (struct pyra_mouse_event_button const *)data;
+
+	switch (button_event->type) {
+	case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2:
+	case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI:
+		roccat_report.type = button_event->type;
+		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));
+		break;
+	case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO:
+	case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT:
+	case PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH:
+		if (button_event->data2 == PYRA_MOUSE_EVENT_BUTTON_PRESS) {
+			roccat_report.type = button_event->type;
+			roccat_report.key = button_event->data1;
+			/*
+			 * pyra reports profile numbers with range 1-5.
+			 * Keeping this behaviour.
+			 */
+			roccat_report.value = pyra->actual_profile + 1;
+			roccat_report_event(pyra->chrdev_minor,
+					(uint8_t const *)&roccat_report,
+					sizeof(struct pyra_roccat_report));
+		}
+		break;
+	}
+}
+
+static int pyra_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 pyra_device *pyra = hid_get_drvdata(hdev);
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			!= USB_INTERFACE_PROTOCOL_MOUSE)
+		return 0;
+
+	pyra_keep_values_up_to_date(pyra, data);
+
+	if (pyra->roccat_claimed)
+		pyra_report_to_chrdev(pyra, data);
+
+	return 0;
+}
+
+static const struct hid_device_id pyra_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT,
+			USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
+	/* TODO add USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS after testing */
+	{ }
+};
+
+MODULE_DEVICE_TABLE(hid, pyra_devices);
+
+static struct hid_driver pyra_driver = {
+		.name = "pyra",
+		.id_table = pyra_devices,
+		.probe = pyra_probe,
+		.remove = pyra_remove,
+		.raw_event = pyra_raw_event
+};
+
+static int __init pyra_init(void)
+{
+	return hid_register_driver(&pyra_driver);
+}
+
+static void __exit pyra_exit(void)
+{
+	hid_unregister_driver(&pyra_driver);
+}
+
+module_init(pyra_init);
+module_exit(pyra_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat Pyra driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h
new file mode 100644
index 0000000..22f80a8
--- /dev/null
+++ b/drivers/hid/hid-roccat-pyra.h
@@ -0,0 +1,186 @@
+#ifndef __HID_ROCCAT_PYRA_H
+#define __HID_ROCCAT_PYRA_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>
+
+#pragma pack(push)
+#pragma pack(1)
+
+struct pyra_b {
+	uint8_t command; /* PYRA_COMMAND_B */
+	uint8_t size; /* always 3 */
+	uint8_t unknown; /* 1 */
+};
+
+struct pyra_control {
+	uint8_t command; /* PYRA_COMMAND_CONTROL */
+	/*
+	 * value is profile number for request_settings and request_buttons
+	 * 1 if status ok for request_status
+	 */
+	uint8_t value; /* Range 0-4 */
+	uint8_t request;
+};
+
+enum pyra_control_requests {
+	PYRA_CONTROL_REQUEST_STATUS = 0x00,
+	PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
+	PYRA_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20
+};
+
+struct pyra_settings {
+	uint8_t command; /* PYRA_COMMAND_SETTINGS */
+	uint8_t size; /* always 3 */
+	uint8_t startup_profile; /* Range 0-4! */
+};
+
+struct pyra_profile_settings {
+	uint8_t command; /* PYRA_COMMAND_PROFILE_SETTINGS */
+	uint8_t size; /* always 0xd */
+	uint8_t number; /* Range 0-4 */
+	uint8_t xysync;
+	uint8_t x_sensitivity; /* 0x1-0xa */
+	uint8_t y_sensitivity;
+	uint8_t x_cpi; /* unused */
+	uint8_t y_cpi; /* this value is for x and y */
+	uint8_t lightswitch; /* 0 = off, 1 = on */
+	uint8_t light_effect;
+	uint8_t handedness;
+	uint16_t checksum; /* byte sum */
+};
+
+struct pyra_profile_buttons {
+	uint8_t command; /* PYRA_COMMAND_PROFILE_BUTTONS */
+	uint8_t size; /* always 0x13 */
+	uint8_t number; /* Range 0-4 */
+	uint8_t buttons[14];
+	uint16_t checksum; /* byte sum */
+};
+
+struct pyra_info {
+	uint8_t command; /* PYRA_COMMAND_INFO */
+	uint8_t size; /* always 6 */
+	uint8_t firmware_version;
+	uint8_t unknown1; /* always 0 */
+	uint8_t unknown2; /* always 1 */
+	uint8_t unknown3; /* always 0 */
+};
+
+enum pyra_commands {
+	PYRA_COMMAND_CONTROL = 0x4,
+	PYRA_COMMAND_SETTINGS = 0x5,
+	PYRA_COMMAND_PROFILE_SETTINGS = 0x6,
+	PYRA_COMMAND_PROFILE_BUTTONS = 0x7,
+	PYRA_COMMAND_INFO = 0x9,
+	PYRA_COMMAND_B = 0xb
+};
+
+enum pyra_usb_commands {
+	PYRA_USB_COMMAND_CONTROL = 0x304,
+	PYRA_USB_COMMAND_SETTINGS = 0x305,
+	PYRA_USB_COMMAND_PROFILE_SETTINGS = 0x306,
+	PYRA_USB_COMMAND_PROFILE_BUTTONS = 0x307,
+	PYRA_USB_COMMAND_INFO = 0x309,
+	PYRA_USB_COMMAND_B = 0x30b /* writes 3 bytes */
+};
+
+enum pyra_mouse_report_numbers {
+	PYRA_MOUSE_REPORT_NUMBER_HID = 1,
+	PYRA_MOUSE_REPORT_NUMBER_AUDIO = 2,
+	PYRA_MOUSE_REPORT_NUMBER_BUTTON = 3,
+};
+
+struct pyra_mouse_event_button {
+	uint8_t report_number; /* always 3 */
+	uint8_t unknown; /* always 0 */
+	uint8_t type;
+	uint8_t data1;
+	uint8_t data2;
+};
+
+struct pyra_mouse_event_audio {
+	uint8_t report_number; /* always 2 */
+	uint8_t type;
+	uint8_t unused; /* always 0 */
+};
+
+/* hid audio controls */
+enum pyra_mouse_event_audio_types {
+	PYRA_MOUSE_EVENT_AUDIO_TYPE_MUTE = 0xe2,
+	PYRA_MOUSE_EVENT_AUDIO_TYPE_VOLUME_UP = 0xe9,
+	PYRA_MOUSE_EVENT_AUDIO_TYPE_VOLUME_DOWN = 0xea,
+};
+
+enum pyra_mouse_event_button_types {
+	/*
+	 * Mouse sends tilt events on report_number 1 and 3
+	 * Tilt events are sent repeatedly with 0.94s between first and second
+	 * event and 0.22s on subsequent
+	 */
+	PYRA_MOUSE_EVENT_BUTTON_TYPE_TILT = 0x10,
+
+	/*
+	 * These are sent sequentially
+	 * data1 contains new profile number in range 1-5
+	 */
+	PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_1 = 0x20,
+	PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2 = 0x30,
+
+	/*
+	 * data1 = button_number (rmp index)
+	 * data2 = pressed/released
+	 */
+	PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO = 0x40,
+	PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT = 0x50,
+
+	/*
+	 * data1 = button_number (rmp index)
+	 */
+	PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH = 0x60,
+
+	/* data1 = new cpi */
+	PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI = 0xb0,
+
+	/* data1 and data2 = new sensitivity */
+	PYRA_MOUSE_EVENT_BUTTON_TYPE_SENSITIVITY = 0xc0,
+
+	PYRA_MOUSE_EVENT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
+};
+
+enum {
+	PYRA_MOUSE_EVENT_BUTTON_PRESS = 0,
+	PYRA_MOUSE_EVENT_BUTTON_RELEASE = 1,
+};
+
+struct pyra_roccat_report {
+	uint8_t type;
+	uint8_t value;
+	uint8_t key;
+};
+
+#pragma pack(pop)
+
+struct pyra_device {
+	int actual_profile;
+	int actual_cpi;
+	int firmware_version;
+	int roccat_claimed;
+	int chrdev_minor;
+	struct mutex pyra_lock;
+	struct pyra_settings settings;
+	struct pyra_profile_settings profile_settings[5];
+	struct pyra_profile_buttons profile_buttons[5];
+};
+
+#endif
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index f6e80c7..5a6879e23 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -384,6 +384,7 @@
 	.poll = roccat_poll,
 	.open = roccat_open,
 	.release = roccat_release,
+	.llseek = noop_llseek,
 };
 
 static int __init roccat_init(void)
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 402d557..0c164b3 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -24,7 +24,9 @@
 
 #include "hid-ids.h"
 
-#define VAIO_RDESC_CONSTANT 0x0001
+#define VAIO_RDESC_CONSTANT     (1 << 0)
+#define SIXAXIS_CONTROLLER_USB  (1 << 1)
+#define SIXAXIS_CONTROLLER_BT   (1 << 2)
 
 struct sony_sc {
 	unsigned long quirks;
@@ -44,12 +46,31 @@
 	}
 }
 
+static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
+		size_t count, unsigned char report_type)
+{
+	struct usb_interface *intf = to_usb_interface(hid->dev.parent);
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_host_interface *interface = intf->cur_altsetting;
+	int report_id = buf[0];
+	int ret;
+
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		HID_REQ_SET_REPORT,
+		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		((report_type + 1) << 8) | report_id,
+		interface->desc.bInterfaceNumber, buf, count,
+		USB_CTRL_SET_TIMEOUT);
+
+	return ret;
+}
+
 /*
  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
  * to "operational".  Without this, the ps3 controller will not report any
  * events.
  */
-static int sony_set_operational_usb(struct hid_device *hdev)
+static int sixaxis_set_operational_usb(struct hid_device *hdev)
 {
 	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
 	struct usb_device *dev = interface_to_usbdev(intf);
@@ -74,7 +95,7 @@
 	return ret;
 }
 
-static int sony_set_operational_bt(struct hid_device *hdev)
+static int sixaxis_set_operational_bt(struct hid_device *hdev)
 {
 	unsigned char buf[] = { 0xf4,  0x42, 0x03, 0x00, 0x00 };
 	return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
@@ -108,16 +129,14 @@
 		goto err_free;
 	}
 
-	switch (hdev->bus) {
-	case BUS_USB:
-		ret = sony_set_operational_usb(hdev);
-		break;
-	case BUS_BLUETOOTH:
-		ret = sony_set_operational_bt(hdev);
-		break;
-	default:
-		ret = 0;
+	if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
+		hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
+		ret = sixaxis_set_operational_usb(hdev);
 	}
+	else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
+		ret = sixaxis_set_operational_bt(hdev);
+	else
+		ret = 0;
 
 	if (ret < 0)
 		goto err_stop;
@@ -137,8 +156,10 @@
 }
 
 static const struct hid_device_id sony_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
-	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
+		.driver_data = SIXAXIS_CONTROLLER_USB },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
+		.driver_data = SIXAXIS_CONTROLLER_BT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
 		.driver_data = VAIO_RDESC_CONSTANT },
 	{ }
diff --git a/drivers/hid/hid-stantum.c b/drivers/hid/hid-stantum.c
index 90df886..3171be2 100644
--- a/drivers/hid/hid-stantum.c
+++ b/drivers/hid/hid-stantum.c
@@ -249,6 +249,8 @@
 
 static const struct hid_device_id stantum_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, stantum_devices);
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 47d70c5..8a4b32d 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -109,6 +109,12 @@
 	int ret = 0;
 
 	mutex_lock(&minors_lock);
+
+	if (!hidraw_table[minor]) {
+		ret = -ENODEV;
+		goto out;
+	}
+
 	dev = hidraw_table[minor]->hid;
 
 	if (!dev->hid_output_raw_report) {
@@ -212,9 +218,13 @@
 	unsigned int minor = iminor(inode);
 	struct hidraw *dev;
 	struct hidraw_list *list = file->private_data;
+	int ret;
 
-	if (!hidraw_table[minor])
-		return -ENODEV;
+	mutex_lock(&minors_lock);
+	if (!hidraw_table[minor]) {
+		ret = -ENODEV;
+		goto unlock;
+	}
 
 	list_del(&list->node);
 	dev = hidraw_table[minor];
@@ -227,10 +237,12 @@
 			kfree(list->hidraw);
 		}
 	}
-
 	kfree(list);
+	ret = 0;
+unlock:
+	mutex_unlock(&minors_lock);
 
-	return 0;
+	return ret;
 }
 
 static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -244,6 +256,10 @@
 
 	mutex_lock(&minors_lock);
 	dev = hidraw_table[minor];
+	if (!dev) {
+		ret = -ENODEV;
+		goto out;
+	}
 
 	switch (cmd) {
 		case HIDIOCGRDESCSIZE:
@@ -317,6 +333,7 @@
 
 		ret = -ENOTTY;
 	}
+out:
 	mutex_unlock(&minors_lock);
 	return ret;
 }
@@ -329,6 +346,7 @@
 	.open =         hidraw_open,
 	.release =      hidraw_release,
 	.unlocked_ioctl = hidraw_ioctl,
+	.llseek =	noop_llseek,
 };
 
 void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 599041a..5489eab 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -807,9 +807,10 @@
 	struct usb_host_interface *interface = intf->cur_altsetting;
 	int ret;
 
-	if (usbhid->urbout) {
+	if (usbhid->urbout && report_type != HID_FEATURE_REPORT) {
 		int actual_length;
 		int skipped_report_id = 0;
+
 		if (buf[0] == 0x0) {
 			/* Don't send the Report ID */
 			buf++;
@@ -1469,9 +1470,6 @@
 	retval = usbhid_quirks_init(quirks_param);
 	if (retval)
 		goto usbhid_quirks_init_fail;
-	retval = hiddev_init();
-	if (retval)
-		goto hiddev_init_fail;
 	retval = usb_register(&hid_driver);
 	if (retval)
 		goto usb_register_fail;
@@ -1479,8 +1477,6 @@
 
 	return 0;
 usb_register_fail:
-	hiddev_exit();
-hiddev_init_fail:
 	usbhid_quirks_exit();
 usbhid_quirks_init_fail:
 	hid_unregister_driver(&hid_usb_driver);
@@ -1493,7 +1489,6 @@
 static void __exit hid_exit(void)
 {
 	usb_deregister(&hid_driver);
-	hiddev_exit();
 	usbhid_quirks_exit();
 	hid_unregister_driver(&hid_usb_driver);
 	destroy_workqueue(resumption_waker);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 7ff7e3d..836a874 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -35,6 +35,7 @@
 	{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -61,6 +62,7 @@
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 681e620..fedd88d 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -67,8 +67,6 @@
 	struct mutex thread_lock;
 };
 
-static struct usb_driver hiddev_driver;
-
 /*
  * Find a report, given the report's type and ID.  The ID can be specified
  * indirectly by REPORT_ID_FIRST (which returns the first report of the given
@@ -847,6 +845,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= hiddev_compat_ioctl,
 #endif
+	.llseek		= noop_llseek,
 };
 
 static char *hiddev_devnode(struct device *dev, mode_t *mode)
@@ -925,41 +924,3 @@
 		kfree(hiddev);
 	}
 }
-
-/* Currently this driver is a USB driver.  It's not a conventional one in
- * the sense that it doesn't probe at the USB level.  Instead it waits to
- * be connected by HID through the hiddev_connect / hiddev_disconnect
- * routines.  The reason to register as a USB device is to gain part of the
- * minor number space from the USB major.
- *
- * In theory, should the HID code be generalized to more than one physical
- * medium (say, IEEE 1384), this driver will probably need to register its
- * own major number, and in doing so, no longer need to register with USB.
- * At that point the probe routine and hiddev_driver struct below will no
- * longer be useful.
- */
-
-
-/* We never attach in this manner, and rely on HID to connect us.  This
- * is why there is no disconnect routine defined in the usb_driver either.
- */
-static int hiddev_usbd_probe(struct usb_interface *intf,
-			     const struct usb_device_id *hiddev_info)
-{
-	return -ENODEV;
-}
-
-static /* const */ struct usb_driver hiddev_driver = {
-	.name =		"hiddev",
-	.probe =	hiddev_usbd_probe,
-};
-
-int __init hiddev_init(void)
-{
-	return usb_register(&hiddev_driver);
-}
-
-void hiddev_exit(void)
-{
-	usb_deregister(&hiddev_driver);
-}
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4d4d09b..97499d0 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -409,7 +409,7 @@
 
 config SENSORS_PKGTEMP
 	tristate "Intel processor package temperature sensor"
-	depends on X86 && PCI && EXPERIMENTAL
+	depends on X86 && EXPERIMENTAL
 	help
 	  If you say yes here you get support for the package level temperature
 	  sensor inside your CPU. Check documentation/driver for details.
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 653db1b..23b8555 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -762,6 +762,7 @@
 	.read		= atk_debugfs_ggrp_read,
 	.open		= atk_debugfs_ggrp_open,
 	.release	= atk_debugfs_ggrp_release,
+	.llseek		= no_llseek,
 };
 
 static void atk_debugfs_init(struct atk_data *data)
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index de81111..a23b17a 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -36,6 +36,7 @@
 #include <linux/pci.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
+#include <asm/smp.h>
 
 #define DRVNAME	"coretemp"
 
@@ -423,9 +424,18 @@
 	int err;
 	struct platform_device *pdev;
 	struct pdev_entry *pdev_entry;
-#ifdef CONFIG_SMP
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
-#endif
+
+	/*
+	 * CPUID.06H.EAX[0] indicates whether the CPU has thermal
+	 * sensors. We check this bit only, all the early CPUs
+	 * without thermal sensors will be filtered out.
+	 */
+	if (!cpu_has(c, X86_FEATURE_DTS)) {
+		printk(KERN_INFO DRVNAME ": CPU (model=0x%x)"
+		       " has no thermal sensor.\n", c->x86_model);
+		return 0;
+	}
 
 	mutex_lock(&pdev_list_mutex);
 
@@ -482,14 +492,22 @@
 
 static void coretemp_device_remove(unsigned int cpu)
 {
-	struct pdev_entry *p, *n;
+	struct pdev_entry *p;
+	unsigned int i;
+
 	mutex_lock(&pdev_list_mutex);
-	list_for_each_entry_safe(p, n, &pdev_list, list) {
-		if (p->cpu == cpu) {
-			platform_device_unregister(p->pdev);
-			list_del(&p->list);
-			kfree(p);
-		}
+	list_for_each_entry(p, &pdev_list, list) {
+		if (p->cpu != cpu)
+			continue;
+
+		platform_device_unregister(p->pdev);
+		list_del(&p->list);
+		mutex_unlock(&pdev_list_mutex);
+		kfree(p);
+		for_each_cpu(i, cpu_sibling_mask(cpu))
+			if (i != cpu && !coretemp_device_add(i))
+				break;
+		return;
 	}
 	mutex_unlock(&pdev_list_mutex);
 }
@@ -527,30 +545,21 @@
 	if (err)
 		goto exit;
 
-	for_each_online_cpu(i) {
-		struct cpuinfo_x86 *c = &cpu_data(i);
-		/*
-		 * CPUID.06H.EAX[0] indicates whether the CPU has thermal
-		 * sensors. We check this bit only, all the early CPUs
-		 * without thermal sensors will be filtered out.
-		 */
-		if (c->cpuid_level >= 6 && (cpuid_eax(0x06) & 0x01))
-			coretemp_device_add(i);
-		else {
-			printk(KERN_INFO DRVNAME ": CPU (model=0x%x)"
-				" has no thermal sensor.\n", c->x86_model);
-		}
-	}
+	for_each_online_cpu(i)
+		coretemp_device_add(i);
+
+#ifndef CONFIG_HOTPLUG_CPU
 	if (list_empty(&pdev_list)) {
 		err = -ENODEV;
 		goto exit_driver_unreg;
 	}
+#endif
 
 	register_hotcpu_notifier(&coretemp_cpu_notifier);
 	return 0;
 
-exit_driver_unreg:
 #ifndef CONFIG_HOTPLUG_CPU
+exit_driver_unreg:
 	platform_driver_unregister(&coretemp_driver);
 #endif
 exit:
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 537841e..75afb3b 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -111,7 +111,7 @@
 /* Super-I/O Function prototypes */
 static inline int superio_inb(int base, int reg);
 static inline int superio_inw(int base, int reg);
-static inline void superio_enter(int base);
+static inline int superio_enter(int base);
 static inline void superio_select(int base, int ld);
 static inline void superio_exit(int base);
 
@@ -861,11 +861,20 @@
 	return val;
 }
 
-static inline void superio_enter(int base)
+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)) {
+		printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
+				base);
+		return -EBUSY;
+	}
+
 	/* according to the datasheet the key must be send twice! */
 	outb(SIO_UNLOCK_KEY, base);
 	outb(SIO_UNLOCK_KEY, base);
+
+	return 0;
 }
 
 static inline void superio_select(int base, int ld)
@@ -877,6 +886,7 @@
 static inline void superio_exit(int base)
 {
 	outb(SIO_LOCK_KEY, base);
+	release_region(base, 2);
 }
 
 static inline int fan_from_reg(u16 reg)
@@ -2175,21 +2185,15 @@
 static int __init f71882fg_find(int sioaddr, unsigned short *address,
 	struct f71882fg_sio_data *sio_data)
 {
-	int err = -ENODEV;
 	u16 devid;
-
-	/* Don't step on other drivers' I/O space by accident */
-	if (!request_region(sioaddr, 2, DRVNAME)) {
-		printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
-				(int)sioaddr);
-		return -EBUSY;
-	}
-
-	superio_enter(sioaddr);
+	int err = superio_enter(sioaddr);
+	if (err)
+		return err;
 
 	devid = superio_inw(sioaddr, SIO_REG_MANID);
 	if (devid != SIO_FINTEK_ID) {
 		pr_debug(DRVNAME ": Not a Fintek device\n");
+		err = -ENODEV;
 		goto exit;
 	}
 
@@ -2213,6 +2217,7 @@
 	default:
 		printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n",
 		       (unsigned int)devid);
+		err = -ENODEV;
 		goto exit;
 	}
 
@@ -2223,12 +2228,14 @@
 
 	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
 		printk(KERN_WARNING DRVNAME ": Device not activated\n");
+		err = -ENODEV;
 		goto exit;
 	}
 
 	*address = superio_inw(sioaddr, SIO_REG_ADDR);
 	if (*address == 0) {
 		printk(KERN_WARNING DRVNAME ": Base address not set\n");
+		err = -ENODEV;
 		goto exit;
 	}
 	*address &= ~(REGION_LENGTH - 1);	/* Ignore 3 LSB */
@@ -2239,7 +2246,6 @@
 		(int)superio_inb(sioaddr, SIO_REG_DEVREV));
 exit:
 	superio_exit(sioaddr);
-	release_region(sioaddr, 2);
 	return err;
 }
 
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index b7ca2a9..d4d4ca6 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -38,7 +38,6 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
-#include <linux/smp_lock.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
@@ -50,6 +49,7 @@
 #include <linux/kref.h>
 
 /* Addresses to scan */
+static DEFINE_MUTEX(watchdog_mutex);
 static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
 
 /* Insmod parameters */
@@ -858,7 +858,7 @@
 	int i, ret = 0;
 	struct fschmd_data *data = filp->private_data;
 
-	lock_kernel();
+	mutex_lock(&watchdog_mutex);
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
 		ident.firmware_version = data->revision;
@@ -915,7 +915,7 @@
 	default:
 		ret = -ENOTTY;
 	}
-	unlock_kernel();
+	mutex_unlock(&watchdog_mutex);
 	return ret;
 }
 
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index 6138f03..fc591ae 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -277,7 +277,7 @@
 	wake_up_interruptible(&lis3_dev.misc_wait);
 	kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
 out:
-	if (lis3_dev.whoami == WAI_8B && lis3_dev.idev &&
+	if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev &&
 	    lis3_dev.idev->input->users)
 		return IRQ_WAKE_THREAD;
 	return IRQ_HANDLED;
@@ -718,7 +718,7 @@
 	 * io-apic is not configurable (and generates a warning) but I keep it
 	 * in case of support for other hardware.
 	 */
-	if (dev->whoami == WAI_8B)
+	if (dev->pdata && dev->whoami == WAI_8B)
 		thread_fn = lis302dl_interrupt_thread1_8b;
 	else
 		thread_fn = NULL;
diff --git a/drivers/hwmon/pkgtemp.c b/drivers/hwmon/pkgtemp.c
index 74157fc..f119039 100644
--- a/drivers/hwmon/pkgtemp.c
+++ b/drivers/hwmon/pkgtemp.c
@@ -33,7 +33,6 @@
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
-#include <linux/pci.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
 
@@ -224,7 +223,7 @@
 
 	err = sysfs_create_group(&pdev->dev.kobj, &pkgtemp_group);
 	if (err)
-		goto exit_free;
+		goto exit_dev;
 
 	data->hwmon_dev = hwmon_device_register(&pdev->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -238,6 +237,8 @@
 
 exit_class:
 	sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
+exit_dev:
+	device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
 exit_free:
 	kfree(data);
 exit:
@@ -250,6 +251,7 @@
 
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
+	device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 	return 0;
@@ -281,9 +283,10 @@
 	int err;
 	struct platform_device *pdev;
 	struct pdev_entry *pdev_entry;
-#ifdef CONFIG_SMP
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
-#endif
+
+	if (!cpu_has(c, X86_FEATURE_PTS))
+		return 0;
 
 	mutex_lock(&pdev_list_mutex);
 
@@ -339,17 +342,18 @@
 #ifdef CONFIG_HOTPLUG_CPU
 static void pkgtemp_device_remove(unsigned int cpu)
 {
-	struct pdev_entry *p, *n;
+	struct pdev_entry *p;
 	unsigned int i;
 	int err;
 
 	mutex_lock(&pdev_list_mutex);
-	list_for_each_entry_safe(p, n, &pdev_list, list) {
+	list_for_each_entry(p, &pdev_list, list) {
 		if (p->cpu != cpu)
 			continue;
 
 		platform_device_unregister(p->pdev);
 		list_del(&p->list);
+		mutex_unlock(&pdev_list_mutex);
 		kfree(p);
 		for_each_cpu(i, cpu_core_mask(cpu)) {
 			if (i != cpu) {
@@ -358,7 +362,7 @@
 					break;
 			}
 		}
-		break;
+		return;
 	}
 	mutex_unlock(&pdev_list_mutex);
 }
@@ -399,11 +403,6 @@
 		goto exit;
 
 	for_each_online_cpu(i) {
-		struct cpuinfo_x86 *c = &cpu_data(i);
-
-		if (!cpu_has(c, X86_FEATURE_PTS))
-			continue;
-
 		err = pkgtemp_device_add(i);
 		if (err)
 			goto exit_devices_unreg;
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 697202e..8e540ad 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -35,7 +35,6 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
-#include <linux/smp_lock.h>
 #include <linux/hwmon-vid.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
@@ -52,6 +51,7 @@
 #define WATCHDOG_TIMEOUT 2	/* 2 minute default timeout */
 
 /* Addresses to scan */
+static DEFINE_MUTEX(watchdog_mutex);
 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
 						I2C_CLIENT_END };
 
@@ -1333,7 +1333,7 @@
 	int val, ret = 0;
 	struct w83793_data *data = filp->private_data;
 
-	lock_kernel();
+	mutex_lock(&watchdog_mutex);
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
 		if (!nowayout)
@@ -1387,7 +1387,7 @@
 	default:
 		ret = -ENOTTY;
 	}
-	unlock_kernel();
+	mutex_unlock(&watchdog_mutex);
 	return ret;
 }
 
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index f7bd261..f2de3be 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -677,6 +677,11 @@
 	dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
 		cpm->adap.name);
 
+	/*
+	 * register OF I2C devices
+	 */
+	of_i2c_register_devices(&cpm->adap);
+
 	return 0;
 out_shut:
 	cpm_i2c_shutdown(cpm);
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 2222c87..5795c83 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -331,21 +331,16 @@
 	INIT_COMPLETION(dev->cmd_complete);
 	dev->cmd_err = 0;
 
-	/* Take I2C out of reset, configure it as master and set the
-	 * start bit */
-	flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT;
+	/* Take I2C out of reset and configure it as master */
+	flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST;
 
 	/* if the slave address is ten bit address, enable XA bit */
 	if (msg->flags & I2C_M_TEN)
 		flag |= DAVINCI_I2C_MDR_XA;
 	if (!(msg->flags & I2C_M_RD))
 		flag |= DAVINCI_I2C_MDR_TRX;
-	if (stop)
-		flag |= DAVINCI_I2C_MDR_STP;
-	if (msg->len == 0) {
+	if (msg->len == 0)
 		flag |= DAVINCI_I2C_MDR_RM;
-		flag &= ~DAVINCI_I2C_MDR_STP;
-	}
 
 	/* Enable receive or transmit interrupts */
 	w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
@@ -357,7 +352,11 @@
 
 	dev->terminate = 0;
 
-	/* write the data into mode register */
+	/*
+	 * Write mode register first as needed for correct behaviour
+	 * on OMAP-L138, but don't set STT yet to avoid a race with XRDY
+	 * occuring before we have loaded DXR
+	 */
 	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
 
 	/*
@@ -365,12 +364,19 @@
 	 * because transmit-data-ready interrupt can come before
 	 * NACK-interrupt during sending of previous message and
 	 * ICDXR may have wrong data
+	 * It also saves us one interrupt, slightly faster
 	 */
 	if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
 		davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
 		dev->buf_len--;
 	}
 
+	/* Set STT to begin transmit now DXR is loaded */
+	flag |= DAVINCI_I2C_MDR_STT;
+	if (stop && msg->len != 0)
+		flag |= DAVINCI_I2C_MDR_STP;
+	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
+
 	r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
 						      dev->adapter.timeout);
 	if (r == 0) {
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 43ca32f..89eedf4 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -761,6 +761,9 @@
 	dev_info(&ofdev->dev, "using %s mode\n",
 		 dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
 
+	/* Now register all the child nodes */
+	of_i2c_register_devices(adap);
+
 	return 0;
 
 error_cleanup:
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index d1ff940..4c2a62b 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -159,15 +159,9 @@
 
 static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)
 {
-	int result;
+	wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
 
-	result = wait_event_interruptible_timeout(i2c_imx->queue,
-		i2c_imx->i2csr & I2SR_IIF, HZ / 10);
-
-	if (unlikely(result < 0)) {
-		dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__);
-		return result;
-	} else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
+	if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
 		dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
 		return -ETIMEDOUT;
 	}
@@ -295,7 +289,7 @@
 		i2c_imx->i2csr = temp;
 		temp &= ~I2SR_IIF;
 		writeb(temp, i2c_imx->base + IMX_I2C_I2SR);
-		wake_up_interruptible(&i2c_imx->queue);
+		wake_up(&i2c_imx->queue);
 		return IRQ_HANDLED;
 	}
 
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index a1c419a..b74e6dc 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -632,6 +632,7 @@
 		dev_err(i2c->dev, "failed to add adapter\n");
 		goto fail_add;
 	}
+	of_i2c_register_devices(&i2c->adap);
 
 	return result;
 
diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 0e9f85d..56dbe54 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -218,7 +218,7 @@
 		return result;
 	} else if (result == 0) {
 		dev_dbg(i2c->dev, "%s: timeout\n", __func__);
-		result = -ETIMEDOUT;
+		return -ETIMEDOUT;
 	}
 
 	return 0;
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index 4174101..837b8c1 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -88,7 +88,7 @@
 	reg_write(smbus, REG_SMSTA, status);
 }
 
-static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus)
+static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
 {
 	int timeout = 10;
 	unsigned int status;
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index bbd7760..29933f8 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -71,8 +71,8 @@
 
 static int pca_isa_waitforcompletion(void *pd)
 {
-	long ret = ~0;
 	unsigned long timeout;
+	long ret;
 
 	if (irq > -1) {
 		ret = wait_event_timeout(pca_wait,
@@ -81,11 +81,15 @@
 	} else {
 		/* Do polling */
 		timeout = jiffies + pca_isa_ops.timeout;
-		while (((pca_isa_readbyte(pd, I2C_PCA_CON)
-				& I2C_PCA_CON_SI) == 0)
-				&& (ret = time_before(jiffies, timeout)))
+		do {
+			ret = time_before(jiffies, timeout);
+			if (pca_isa_readbyte(pd, I2C_PCA_CON)
+					& I2C_PCA_CON_SI)
+				break;
 			udelay(100);
+		} while (ret);
 	}
+
 	return ret > 0;
 }
 
diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
index ef5c784..5f6d7f8 100644
--- a/drivers/i2c/busses/i2c-pca-platform.c
+++ b/drivers/i2c/busses/i2c-pca-platform.c
@@ -80,8 +80,8 @@
 static int i2c_pca_pf_waitforcompletion(void *pd)
 {
 	struct i2c_pca_pf_data *i2c = pd;
-	long ret = ~0;
 	unsigned long timeout;
+	long ret;
 
 	if (i2c->irq) {
 		ret = wait_event_timeout(i2c->wait,
@@ -90,10 +90,13 @@
 	} else {
 		/* Do polling */
 		timeout = jiffies + i2c->adap.timeout;
-		while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
-				& I2C_PCA_CON_SI) == 0)
-				&& (ret = time_before(jiffies, timeout)))
+		do {
+			ret = time_before(jiffies, timeout);
+			if (i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
+					& I2C_PCA_CON_SI)
+				break;
 			udelay(100);
+		} while (ret);
 	}
 
 	return ret > 0;
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 72902e0..bf831bf 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -662,8 +662,8 @@
 		unsigned long sda_delay;
 
 		if (pdata->sda_delay) {
-			sda_delay = (freq / 1000) * pdata->sda_delay;
-			sda_delay /= 1000000;
+			sda_delay = clkin * pdata->sda_delay;
+			sda_delay = DIV_ROUND_UP(sda_delay, 1000000);
 			sda_delay = DIV_ROUND_UP(sda_delay, 5);
 			if (sda_delay > 3)
 				sda_delay = 3;
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 6649176..bea4c50 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -32,7 +32,6 @@
 #include <linux/init.h>
 #include <linux/idr.h>
 #include <linux/mutex.h>
-#include <linux/of_i2c.h>
 #include <linux/of_device.h>
 #include <linux/completion.h>
 #include <linux/hardirq.h>
@@ -197,11 +196,12 @@
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-	if (pm_runtime_suspended(dev))
-		return 0;
-
-	if (pm)
-		return pm->suspend ? pm->suspend(dev) : 0;
+	if (pm) {
+		if (pm_runtime_suspended(dev))
+			return 0;
+		else
+			return pm->suspend ? pm->suspend(dev) : 0;
+	}
 
 	return i2c_legacy_suspend(dev, PMSG_SUSPEND);
 }
@@ -216,12 +216,6 @@
 	else
 		ret = i2c_legacy_resume(dev);
 
-	if (!ret) {
-		pm_runtime_disable(dev);
-		pm_runtime_set_active(dev);
-		pm_runtime_enable(dev);
-	}
-
 	return ret;
 }
 
@@ -229,11 +223,12 @@
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-	if (pm_runtime_suspended(dev))
-		return 0;
-
-	if (pm)
-		return pm->freeze ? pm->freeze(dev) : 0;
+	if (pm) {
+		if (pm_runtime_suspended(dev))
+			return 0;
+		else
+			return pm->freeze ? pm->freeze(dev) : 0;
+	}
 
 	return i2c_legacy_suspend(dev, PMSG_FREEZE);
 }
@@ -242,11 +237,12 @@
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-	if (pm_runtime_suspended(dev))
-		return 0;
-
-	if (pm)
-		return pm->thaw ? pm->thaw(dev) : 0;
+	if (pm) {
+		if (pm_runtime_suspended(dev))
+			return 0;
+		else
+			return pm->thaw ? pm->thaw(dev) : 0;
+	}
 
 	return i2c_legacy_resume(dev);
 }
@@ -255,11 +251,12 @@
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-	if (pm_runtime_suspended(dev))
-		return 0;
-
-	if (pm)
-		return pm->poweroff ? pm->poweroff(dev) : 0;
+	if (pm) {
+		if (pm_runtime_suspended(dev))
+			return 0;
+		else
+			return pm->poweroff ? pm->poweroff(dev) : 0;
+	}
 
 	return i2c_legacy_suspend(dev, PMSG_HIBERNATE);
 }
@@ -876,9 +873,6 @@
 	if (adap->nr < __i2c_first_dynamic_bus_num)
 		i2c_scan_static_board_info(adap);
 
-	/* Register devices from the device tree */
-	of_i2c_register_devices(adap);
-
 	/* Notify drivers */
 	mutex_lock(&core_lock);
 	bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 31fc769..0c73fe3 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -31,7 +31,6 @@
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
@@ -52,6 +51,7 @@
 
 #include "ide-cd.h"
 
+static DEFINE_MUTEX(ide_cd_mutex);
 static DEFINE_MUTEX(idecd_ref_mutex);
 
 static void ide_cd_release(struct device *);
@@ -1602,7 +1602,7 @@
 	struct cdrom_info *info;
 	int rc = -ENXIO;
 
-	lock_kernel();
+	mutex_lock(&ide_cd_mutex);
 	info = ide_cd_get(bdev->bd_disk);
 	if (!info)
 		goto out;
@@ -1611,7 +1611,7 @@
 	if (rc < 0)
 		ide_cd_put(info);
 out:
-	unlock_kernel();
+	mutex_unlock(&ide_cd_mutex);
 	return rc;
 }
 
@@ -1619,11 +1619,11 @@
 {
 	struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
 
-	lock_kernel();
+	mutex_lock(&ide_cd_mutex);
 	cdrom_release(&info->devinfo, mode);
 
 	ide_cd_put(info);
-	unlock_kernel();
+	mutex_unlock(&ide_cd_mutex);
 
 	return 0;
 }
@@ -1694,9 +1694,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ide_cd_mutex);
 	ret = idecd_locked_ioctl(bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ide_cd_mutex);
 
 	return ret;
 }
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index 2a4cb9c..404843e 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -43,7 +43,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/cisreg.h>
@@ -72,17 +71,6 @@
 
 static void ide_detach(struct pcmcia_device *p_dev);
 
-
-
-
-/*======================================================================
-
-    ide_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int ide_probe(struct pcmcia_device *link)
 {
     ide_info_t *info;
@@ -97,23 +85,12 @@
     info->p_dev = link;
     link->priv = info;
 
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
+	    CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
 
     return ide_config(link);
 } /* ide_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void ide_detach(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
@@ -187,79 +164,31 @@
     return NULL;
 }
 
-/*======================================================================
-
-    ide_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ide device available to the system.
-
-======================================================================*/
-
-struct pcmcia_config_check {
-	unsigned long ctl_base;
-	int skip_vcc;
-	int is_kme;
-};
-
-static int pcmcia_check_one_config(struct pcmcia_device *pdev,
-				   cistpl_cftable_entry_t *cfg,
-				   cistpl_cftable_entry_t *dflt,
-				   unsigned int vcc,
-				   void *priv_data)
+static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
 {
-	struct pcmcia_config_check *stk = priv_data;
+	int *is_kme = priv_data;
 
-	/* Check for matching Vcc, unless we're desperate */
-	if (!stk->skip_vcc) {
-		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-			if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
-				return -ENODEV;
-		} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-			if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
-				return -ENODEV;
-		}
+	if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
+		pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	}
+	pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 
-	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-
-		pdev->conf.ConfigIndex = cfg->index;
-		pdev->resource[0]->start = io->win[0].base;
-		if (!(io->flags & CISTPL_IO_16BIT)) {
-			pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-			pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-		}
-		if (io->nwin == 2) {
-			pdev->resource[0]->end = 8;
-			pdev->resource[1]->start = io->win[1].base;
-			pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
-			if (pcmcia_request_io(pdev) != 0)
-				return -ENODEV;
-			stk->ctl_base = pdev->resource[1]->start;
-		} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
-			pdev->resource[0]->end = io->win[0].len;
-			pdev->resource[1]->end = 0;
-			if (pcmcia_request_io(pdev) != 0)
-				return -ENODEV;
-			stk->ctl_base = pdev->resource[0]->start + 0x0e;
-		} else
+	if (pdev->resource[1]->end) {
+		pdev->resource[0]->end = 8;
+		pdev->resource[1]->end = (*is_kme) ? 2 : 1;
+	} else {
+		if (pdev->resource[0]->end < 16)
 			return -ENODEV;
-		/* If we've got this far, we're done */
-		return 0;
 	}
-	return -ENODEV;
+
+	return pcmcia_request_io(pdev);
 }
 
 static int ide_config(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
-    struct pcmcia_config_check *stk = NULL;
     int ret = 0, is_kme = 0;
     unsigned long io_base, ctl_base;
     struct ide_host *host;
@@ -270,23 +199,21 @@
 	      ((link->card_id == PRODID_KME_KXLC005_A) ||
 	       (link->card_id == PRODID_KME_KXLC005_B)));
 
-    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
-    if (!stk)
-	    goto err_mem;
-    stk->is_kme = is_kme;
-    stk->skip_vcc = io_base = ctl_base = 0;
-
-    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
-	    stk->skip_vcc = 1;
-	    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
+    if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) {
+	    link->config_flags &= ~CONF_AUTO_CHECK_VCC;
+	    if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme))
 		    goto failed; /* No suitable config found */
     }
     io_base = link->resource[0]->start;
-    ctl_base = stk->ctl_base;
+    if (link->resource[1]->end)
+	    ctl_base = link->resource[1]->start;
+    else
+	    ctl_base = link->resource[0]->start + 0x0e;
 
     if (!link->irq)
 	    goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
@@ -311,29 +238,15 @@
     info->host = host;
     dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n",
 	    'a' + host->ports[0]->index * 2,
-	    link->conf.Vpp / 10, link->conf.Vpp % 10);
+	    link->vpp / 10, link->vpp % 10);
 
-    kfree(stk);
     return 0;
 
-err_mem:
-    printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
-    goto failed;
-
 failed:
-    kfree(stk);
     ide_release(link);
     return -ENODEV;
 } /* ide_config */
 
-/*======================================================================
-
-    After a card is removed, ide_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void ide_release(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
@@ -359,15 +272,6 @@
 } /* ide_release */
 
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the ide drivers from
-    talking to the ports.
-
-======================================================================*/
-
 static struct pcmcia_device_id ide_ids[] = {
 	PCMCIA_DEVICE_FUNC_ID(4),
 	PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),	/* Corsair */
@@ -440,9 +344,7 @@
 
 static struct pcmcia_driver ide_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "ide-cs",
-	},
+	.name		= "ide-cs",
 	.probe		= ide_probe,
 	.remove		= ide_detach,
 	.id_table       = ide_ids,
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 7433e07..7c5b01c 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -516,10 +516,10 @@
 	return ide_no_data_taskfile(drive, &cmd);
 }
 
-static void update_ordered(ide_drive_t *drive)
+static void update_flush(ide_drive_t *drive)
 {
 	u16 *id = drive->id;
-	unsigned ordered = QUEUE_ORDERED_NONE;
+	unsigned flush = 0;
 
 	if (drive->dev_flags & IDE_DFLAG_WCACHE) {
 		unsigned long long capacity;
@@ -543,13 +543,12 @@
 		       drive->name, barrier ? "" : "not ");
 
 		if (barrier) {
-			ordered = QUEUE_ORDERED_DRAIN_FLUSH;
+			flush = REQ_FLUSH;
 			blk_queue_prep_rq(drive->queue, idedisk_prep_fn);
 		}
-	} else
-		ordered = QUEUE_ORDERED_DRAIN;
+	}
 
-	blk_queue_ordered(drive->queue, ordered);
+	blk_queue_flush(drive->queue, flush);
 }
 
 ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE);
@@ -572,7 +571,7 @@
 		}
 	}
 
-	update_ordered(drive);
+	update_flush(drive);
 
 	return err;
 }
diff --git a/drivers/ide/ide-disk_ioctl.c b/drivers/ide/ide-disk_ioctl.c
index ec94c66..da36f72 100644
--- a/drivers/ide/ide-disk_ioctl.c
+++ b/drivers/ide/ide-disk_ioctl.c
@@ -1,10 +1,11 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
 #include <linux/hdreg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include "ide-disk.h"
 
+static DEFINE_MUTEX(ide_disk_ioctl_mutex);
 static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
 { HDIO_GET_ADDRESS,	HDIO_SET_ADDRESS,   &ide_devset_address   },
 { HDIO_GET_MULTCOUNT,	HDIO_SET_MULTCOUNT, &ide_devset_multcount },
@@ -19,13 +20,13 @@
 {
 	int err;
 
-	lock_kernel();
+	mutex_lock(&ide_disk_ioctl_mutex);
 	err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
 	if (err != -EOPNOTSUPP)
 		goto out;
 
 	err = generic_ide_ioctl(drive, bdev, cmd, arg);
 out:
-	unlock_kernel();
+	mutex_unlock(&ide_disk_ioctl_mutex);
 	return err;
 }
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
index fd3d05a..d267b7a 100644
--- a/drivers/ide/ide-floppy_ioctl.c
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -5,7 +5,7 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
 #include <linux/cdrom.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/unaligned.h>
 
@@ -32,6 +32,7 @@
  * On exit we set nformats to the number of records we've actually initialized.
  */
 
+static DEFINE_MUTEX(ide_floppy_ioctl_mutex);
 static int ide_floppy_get_format_capacities(ide_drive_t *drive,
 					    struct ide_atapi_pc *pc,
 					    int __user *arg)
@@ -276,7 +277,7 @@
 	void __user *argp = (void __user *)arg;
 	int err;
 
-	lock_kernel();
+	mutex_lock(&ide_floppy_ioctl_mutex);
 	if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) {
 		err = ide_floppy_lockdoor(drive, &pc, arg, cmd);
 		goto out;
@@ -298,6 +299,6 @@
 		err = generic_ide_ioctl(drive, bdev, cmd, arg);
 
 out:
-	unlock_kernel();
+	mutex_unlock(&ide_floppy_ioctl_mutex);
 	return err;
 }
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index 70aeeb1..35c4b43 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -1,4 +1,3 @@
-#include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -23,6 +22,7 @@
 #define IDE_GD_VERSION	"1.18"
 
 /* module parameters */
+static DEFINE_MUTEX(ide_gd_mutex);
 static unsigned long debug_mask;
 module_param(debug_mask, ulong, 0644);
 
@@ -242,9 +242,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ide_gd_mutex);
 	ret = ide_gd_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&ide_gd_mutex);
 
 	return ret;
 }
@@ -257,7 +257,7 @@
 
 	ide_debug_log(IDE_DBG_FUNC, "enter");
 
-	lock_kernel();
+	mutex_lock(&ide_gd_mutex);
 	if (idkp->openers == 1)
 		drive->disk_ops->flush(drive);
 
@@ -269,7 +269,7 @@
 	idkp->openers--;
 
 	ide_disk_put(idkp);
-	unlock_kernel();
+	mutex_unlock(&ide_gd_mutex);
 
 	return 0;
 }
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index a381be8..999dac0 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -441,19 +441,6 @@
 	struct request	*rq = NULL;
 	ide_startstop_t	startstop;
 
-	/*
-	 * drive is doing pre-flush, ordered write, post-flush sequence. even
-	 * though that is 3 requests, it must be seen as a single transaction.
-	 * we must not preempt this drive until that is complete
-	 */
-	if (blk_queue_flushing(q))
-		/*
-		 * small race where queue could get replugged during
-		 * the 3-request flush cycle, just yank the plug since
-		 * we want it to finish asap
-		 */
-		blk_remove_plug(q);
-
 	spin_unlock_irq(q->queue_lock);
 
 	/* HLD do_request() callback might sleep, make sure it's okay */
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 6d622cb..7ecb1ad 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -32,11 +32,9 @@
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
-#include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
@@ -220,6 +218,7 @@
 	char write_prot;
 } idetape_tape_t;
 
+static DEFINE_MUTEX(ide_tape_mutex);
 static DEFINE_MUTEX(idetape_ref_mutex);
 
 static DEFINE_MUTEX(idetape_chrdev_mutex);
@@ -1426,9 +1425,9 @@
 				unsigned int cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&ide_tape_mutex);
 	ret = do_idetape_chrdev_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ide_tape_mutex);
 	return ret;
 }
 
@@ -1903,15 +1902,16 @@
 	.unlocked_ioctl	= idetape_chrdev_ioctl,
 	.open		= idetape_chrdev_open,
 	.release	= idetape_chrdev_release,
+	.llseek		= noop_llseek,
 };
 
 static int idetape_open(struct block_device *bdev, fmode_t mode)
 {
 	struct ide_tape_obj *tape;
 
-	lock_kernel();
+	mutex_lock(&ide_tape_mutex);
 	tape = ide_tape_get(bdev->bd_disk, false, 0);
-	unlock_kernel();
+	mutex_unlock(&ide_tape_mutex);
 
 	if (!tape)
 		return -ENXIO;
@@ -1923,9 +1923,9 @@
 {
 	struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
 
-	lock_kernel();
+	mutex_lock(&ide_tape_mutex);
 	ide_tape_put(tape);
-	unlock_kernel();
+	mutex_unlock(&ide_tape_mutex);
 
 	return 0;
 }
@@ -1937,11 +1937,11 @@
 	ide_drive_t *drive = tape->drive;
 	int err;
 
-	lock_kernel();
+	mutex_lock(&ide_tape_mutex);
 	err = generic_ide_ioctl(drive, bdev, cmd, arg);
 	if (err == -EINVAL)
 		err = idetape_blkdev_ioctl(drive, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ide_tape_mutex);
 
 	return err;
 }
diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c
index 15341fc..c976285 100644
--- a/drivers/idle/i7300_idle.c
+++ b/drivers/idle/i7300_idle.c
@@ -536,6 +536,7 @@
 static const struct file_operations idle_fops = {
 	.open	= stats_open_generic,
 	.read	= stats_read_ul,
+	.llseek = default_llseek,
 };
 
 struct debugfs_file_info {
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
old mode 100755
new mode 100644
index a10152b..cb3ccf3
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -59,18 +59,11 @@
 #include <linux/hrtimer.h>	/* ktime_get_real() */
 #include <trace/events/power.h>
 #include <linux/sched.h>
+#include <asm/mwait.h>
 
 #define INTEL_IDLE_VERSION "0.4"
 #define PREFIX "intel_idle: "
 
-#define MWAIT_SUBSTATE_MASK	(0xf)
-#define MWAIT_CSTATE_MASK	(0xf)
-#define MWAIT_SUBSTATE_SIZE	(4)
-#define MWAIT_MAX_NUM_CSTATES	8
-#define CPUID_MWAIT_LEAF (5)
-#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
-#define CPUID5_ECX_INTERRUPT_BREAK	(0x2)
-
 static struct cpuidle_driver intel_idle_driver = {
 	.name = "intel_idle",
 	.owner = THIS_MODULE,
@@ -83,7 +76,7 @@
 /* Reliable LAPIC Timer States, bit 1 for C1 etc.  */
 static unsigned int lapic_timer_reliable_states;
 
-static struct cpuidle_device *intel_idle_cpuidle_devices;
+static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
 static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
 
 static struct cpuidle_state *cpuidle_state_table;
@@ -108,7 +101,7 @@
 		.name = "NHM-C3",
 		.desc = "MWAIT 0x10",
 		.driver_data = (void *) 0x10,
-		.flags = CPUIDLE_FLAG_TIME_VALID,
+		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 20,
 		.power_usage = 500,
 		.target_residency = 80,
@@ -117,7 +110,7 @@
 		.name = "NHM-C6",
 		.desc = "MWAIT 0x20",
 		.driver_data = (void *) 0x20,
-		.flags = CPUIDLE_FLAG_TIME_VALID,
+		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 200,
 		.power_usage = 350,
 		.target_residency = 800,
@@ -149,7 +142,7 @@
 		.name = "ATM-C4",
 		.desc = "MWAIT 0x30",
 		.driver_data = (void *) 0x30,
-		.flags = CPUIDLE_FLAG_TIME_VALID,
+		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 100,
 		.power_usage = 250,
 		.target_residency = 400,
@@ -157,13 +150,13 @@
 	{ /* MWAIT C5 */ },
 	{ /* MWAIT C6 */
 		.name = "ATM-C6",
-		.desc = "MWAIT 0x40",
-		.driver_data = (void *) 0x40,
-		.flags = CPUIDLE_FLAG_TIME_VALID,
-		.exit_latency = 200,
+		.desc = "MWAIT 0x52",
+		.driver_data = (void *) 0x52,
+		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 140,
 		.power_usage = 150,
-		.target_residency = 800,
-		.enter = NULL },	/* disabled */
+		.target_residency = 560,
+		.enter = &intel_idle },
 };
 
 /**
@@ -185,6 +178,16 @@
 
 	local_irq_disable();
 
+	/*
+	 * If the state flag indicates that the TLB will be flushed or if this
+	 * is the deepest c-state supported, do a voluntary leave mm to avoid
+	 * costly and mostly unnecessary wakeups for flushing the user TLB's
+	 * associated with the active mm.
+	 */
+	if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED ||
+	    (&dev->states[dev->state_count - 1] == state))
+		leave_mm(cpu);
+
 	if (!(lapic_timer_reliable_states & (1 << (cstate))))
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index bc289e3..6340382 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -58,7 +58,6 @@
 #include <linux/tcp.h>
 #include <linux/skbuff.h>
 #include <linux/bitops.h>
-#include <linux/ethtool.h>
 #include <asm/uaccess.h>
 #include <asm/delay.h>
 #include <asm/unaligned.h>
@@ -173,8 +172,6 @@
 				struct net_device *dev);
 static void ether1394_iso(struct hpsb_iso *iso);
 
-static const struct ethtool_ops ethtool_ops;
-
 static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
 			   quadlet_t *data, u64 addr, size_t len, u16 flags);
 static void ether1394_add_host(struct hpsb_host *host);
@@ -525,8 +522,6 @@
 	dev->header_ops		= &ether1394_header_ops;
 	dev->netdev_ops		= &ether1394_netdev_ops;
 
-	SET_ETHTOOL_OPS(dev, &ethtool_ops);
-
 	dev->watchdog_timeo	= ETHER1394_TIMEOUT;
 	dev->flags		= IFF_BROADCAST | IFF_MULTICAST;
 	dev->features		= NETIF_F_HIGHDMA;
@@ -1695,17 +1690,6 @@
 	return NETDEV_TX_OK;
 }
 
-static void ether1394_get_drvinfo(struct net_device *dev,
-				  struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, driver_name);
-	strcpy(info->bus_info, "ieee1394"); /* FIXME provide more detail? */
-}
-
-static const struct ethtool_ops ethtool_ops = {
-	.get_drvinfo = ether1394_get_drvinfo
-};
-
 static int __init ether1394_init_module(void)
 {
 	int err;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index d88077a..13c8887 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -463,7 +463,8 @@
 	    V_MSS_IDX(mtu_idx) |
 	    V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx);
 	opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10);
-	opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor);
+	opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) |
+	       V_CONG_CONTROL_FLAVOR(cong_flavor);
 	skb->priority = CPL_PRIORITY_SETUP;
 	set_arp_failure_handler(skb, act_open_req_arp_failure);
 
@@ -1280,7 +1281,8 @@
 	    V_MSS_IDX(mtu_idx) |
 	    V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx);
 	opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10);
-	opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor);
+	opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) |
+	       V_CONG_CONTROL_FLAVOR(cong_flavor);
 
 	rpl = cplhdr(skb);
 	rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index d4ce8b6..daef61d 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -65,7 +65,8 @@
 	.write = ipath_diag_write,
 	.read = ipath_diag_read,
 	.open = ipath_diag_open,
-	.release = ipath_diag_release
+	.release = ipath_diag_release,
+	.llseek = default_llseek,
 };
 
 static ssize_t ipath_diagpkt_write(struct file *fp,
@@ -75,6 +76,7 @@
 static const struct file_operations diagpkt_file_ops = {
 	.owner = THIS_MODULE,
 	.write = ipath_diagpkt_write,
+	.llseek = noop_llseek,
 };
 
 static atomic_t diagpkt_count = ATOMIC_INIT(0);
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 65eb892..6078992 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -63,7 +63,8 @@
 	.open = ipath_open,
 	.release = ipath_close,
 	.poll = ipath_poll,
-	.mmap = ipath_mmap
+	.mmap = ipath_mmap,
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 2fca708..d13e726 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -103,6 +103,7 @@
 
 static const struct file_operations atomic_stats_ops = {
 	.read = atomic_stats_read,
+	.llseek = default_llseek,
 };
 
 static ssize_t atomic_counters_read(struct file *file, char __user *buf,
@@ -120,6 +121,7 @@
 
 static const struct file_operations atomic_counters_ops = {
 	.read = atomic_counters_read,
+	.llseek = default_llseek,
 };
 
 static ssize_t flash_read(struct file *file, char __user *buf,
@@ -224,6 +226,7 @@
 static const struct file_operations flash_ops = {
 	.read = flash_read,
 	.write = flash_write,
+	.llseek = default_llseek,
 };
 
 static int create_device_files(struct super_block *sb,
diff --git a/drivers/infiniband/hw/mlx4/Kconfig b/drivers/infiniband/hw/mlx4/Kconfig
index 4175a4b..bd995b2 100644
--- a/drivers/infiniband/hw/mlx4/Kconfig
+++ b/drivers/infiniband/hw/mlx4/Kconfig
@@ -1,5 +1,6 @@
 config MLX4_INFINIBAND
 	tristate "Mellanox ConnectX HCA support"
+	depends on NETDEVICES && NETDEV_10000 && PCI
 	select MLX4_CORE
 	---help---
 	  This driver provides low-level InfiniBand support for
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 61e0efd..6220d9d 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -2701,7 +2701,7 @@
 	nesibdev = nesvnic->nesibdev;
 
 	nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
-			atomic_read(&nesvnic->netdev->refcnt));
+			netdev_refcnt_read(nesvnic->netdev));
 
 	if (nesqp->active_conn) {
 
@@ -2791,7 +2791,7 @@
 	atomic_inc(&cm_accepts);
 
 	nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
-			atomic_read(&nesvnic->netdev->refcnt));
+			netdev_refcnt_read(nesvnic->netdev));
 
 	/* allocate the ietf frame and space for private data */
 	nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev,
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 9046e66..546fc22 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -785,7 +785,7 @@
 
 	nes_debug(NES_DBG_PD, "nesvnic=%p, netdev=%p %s, ibdev=%p, context=%p, netdev refcnt=%u\n",
 			nesvnic, nesdev->netdev[0], nesdev->netdev[0]->name, ibdev, context,
-			atomic_read(&nesvnic->netdev->refcnt));
+			netdev_refcnt_read(nesvnic->netdev));
 
 	err = nes_alloc_resource(nesadapter, nesadapter->allocated_pds,
 			nesadapter->max_pd, &pd_num, &nesadapter->next_pd);
@@ -1416,7 +1416,7 @@
 	/* update the QP table */
 	nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp;
 	nes_debug(NES_DBG_QP, "netdev refcnt=%u\n",
-			atomic_read(&nesvnic->netdev->refcnt));
+			netdev_refcnt_read(nesvnic->netdev));
 
 	return &nesqp->ibqp;
 }
diff --git a/drivers/infiniband/hw/qib/qib_diag.c b/drivers/infiniband/hw/qib/qib_diag.c
index 05dcf0d..204c4dd 100644
--- a/drivers/infiniband/hw/qib/qib_diag.c
+++ b/drivers/infiniband/hw/qib/qib_diag.c
@@ -136,7 +136,8 @@
 	.write = qib_diag_write,
 	.read = qib_diag_read,
 	.open = qib_diag_open,
-	.release = qib_diag_release
+	.release = qib_diag_release,
+	.llseek = default_llseek,
 };
 
 static atomic_t diagpkt_count = ATOMIC_INIT(0);
@@ -149,6 +150,7 @@
 static const struct file_operations diagpkt_file_ops = {
 	.owner = THIS_MODULE,
 	.write = qib_diagpkt_write,
+	.llseek = noop_llseek,
 };
 
 int qib_diag_add(struct qib_devdata *dd)
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index 6b11645..aa2be21 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -63,7 +63,8 @@
 	.open = qib_open,
 	.release = qib_close,
 	.poll = qib_poll,
-	.mmap = qib_mmapf
+	.mmap = qib_mmapf,
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index 9f989c0..a0e6613 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -367,6 +367,7 @@
 static const struct file_operations flash_ops = {
 	.read = flash_read,
 	.write = flash_write,
+	.llseek = default_llseek,
 };
 
 static int add_cntr_files(struct super_block *sb, struct qib_devdata *dd)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index c908c5f..535fea4 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -28,7 +28,7 @@
 	int minor;
 	struct input_handle handle;
 	wait_queue_head_t wait;
-	struct evdev_client *grab;
+	struct evdev_client __rcu *grab;
 	struct list_head client_list;
 	spinlock_t client_lock; /* protects client_list */
 	struct mutex mutex;
@@ -669,6 +669,9 @@
 
 		if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
 
+			if (!dev->absinfo)
+				return -EINVAL;
+
 			t = _IOC_NR(cmd) & ABS_MAX;
 			abs = dev->absinfo[t];
 
@@ -680,10 +683,13 @@
 		}
 	}
 
-	if (_IOC_DIR(cmd) == _IOC_READ) {
+	if (_IOC_DIR(cmd) == _IOC_WRITE) {
 
 		if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
 
+			if (!dev->absinfo)
+				return -EINVAL;
+
 			t = _IOC_NR(cmd) & ABS_MAX;
 
 			if (copy_from_user(&abs, p, min_t(size_t,
@@ -761,7 +767,8 @@
 	.compat_ioctl	= evdev_ioctl_compat,
 #endif
 	.fasync		= evdev_fasync,
-	.flush		= evdev_flush
+	.flush		= evdev_flush,
+	.llseek		= no_llseek,
 };
 
 static int evdev_install_chrdev(struct evdev *evdev)
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ab69820..7919c25 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -2047,6 +2047,7 @@
 static const struct file_operations input_fops = {
 	.owner = THIS_MODULE,
 	.open = input_open_file,
+	.llseek = noop_llseek,
 };
 
 static int __init input_init(void)
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index d85bd8a..9d424ceb 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -483,6 +483,9 @@
 
 	memcpy(joydev->abspam, abspam, len);
 
+	for (i = 0; i < joydev->nabs; i++)
+		joydev->absmap[joydev->abspam[i]] = i;
+
  out:
 	kfree(abspam);
 	return retval;
@@ -736,6 +739,7 @@
 	.compat_ioctl	= joydev_compat_ioctl,
 #endif
 	.fasync		= joydev_fasync,
+	.llseek		= no_llseek,
 };
 
 static int joydev_install_chrdev(struct joydev *joydev)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 9cc488d2..aa037fe 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -338,7 +338,7 @@
 
 config KEYBOARD_PXA27x
 	tristate "PXA27x/PXA3xx keypad support"
-	depends on PXA27x || PXA3xx
+	depends on PXA27x || PXA3xx || ARCH_MMP
 	help
 	  Enable support for PXA27x/PXA3xx keypad controller.
 
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index f32404f..4b0ec35 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -32,7 +32,7 @@
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
 /*
  * Keypad Controller registers
  */
@@ -330,11 +330,21 @@
 	keypad->direct_key_state = new_state;
 }
 
+static void clear_wakeup_event(struct pxa27x_keypad *keypad)
+{
+	struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
+
+	if (pdata->clear_wakeup_event)
+		(pdata->clear_wakeup_event)();
+}
+
 static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
 {
 	struct pxa27x_keypad *keypad = dev_id;
 	unsigned long kpc = keypad_readl(KPC);
 
+	clear_wakeup_event(keypad);
+
 	if (kpc & KPC_DI)
 		pxa27x_keypad_scan_direct(keypad);
 
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index c190664..0b4f542 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -43,7 +43,7 @@
 #include <linux/proc_fs.h>
 #include <linux/poll.h>
 #include <linux/rtc.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/semaphore.h>
 
 MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
@@ -52,6 +52,7 @@
 
 #define RTC_VERSION "1.10d"
 
+static DEFINE_MUTEX(hp_sdc_rtc_mutex);
 static unsigned long epoch = 2000;
 
 static struct semaphore i8042tregs;
@@ -104,7 +105,7 @@
 	t.endidx =		91;
 	t.seq =			tseq;
 	t.act.semaphore =	&tsem;
-	init_MUTEX_LOCKED(&tsem);
+	sema_init(&tsem, 0);
 	
 	if (hp_sdc_enqueue_transaction(&t)) return -1;
 	
@@ -665,9 +666,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&hp_sdc_rtc_mutex);
 	ret = hp_sdc_rtc_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&hp_sdc_rtc_mutex);
 
 	return ret;
 }
@@ -698,7 +699,7 @@
 		return -ENODEV;
 #endif
 
-	init_MUTEX(&i8042tregs);
+	sema_init(&i8042tregs, 1);
 
 	if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
 		return ret;
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 0d4266a..b941078 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -404,6 +404,13 @@
 		retval = uinput_validate_absbits(dev);
 		if (retval < 0)
 			goto exit;
+		if (test_bit(ABS_MT_SLOT, dev->absbit)) {
+			int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
+			input_mt_create_slots(dev, nslot);
+			input_set_events_per_packet(dev, 6 * nslot);
+		} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
+			input_set_events_per_packet(dev, 60);
+		}
 	}
 
 	udev->state = UIST_SETUP_COMPLETE;
@@ -804,6 +811,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= uinput_compat_ioctl,
 #endif
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice uinput_misc = {
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index d528a2d..31ec726 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -792,6 +792,7 @@
 	.open =		mousedev_open,
 	.release =	mousedev_release,
 	.fasync =	mousedev_fasync,
+	.llseek = noop_llseek,
 };
 
 static int mousedev_install_chrdev(struct mousedev *mousedev)
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index c92f4ed..e5624d8 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -915,15 +915,15 @@
 	mlc->ostarted = 0;
 
 	rwlock_init(&mlc->lock);
-	init_MUTEX(&mlc->osem);
+	sema_init(&mlc->osem, 1);
 
-	init_MUTEX(&mlc->isem);
+	sema_init(&mlc->isem, 1);
 	mlc->icount = -1;
 	mlc->imatch = 0;
 
 	mlc->opercnt = 0;
 
-	init_MUTEX_LOCKED(&(mlc->csem));
+	sema_init(&(mlc->csem), 0);
 
 	hil_mlc_clear_di_scratch(mlc);
 	hil_mlc_clear_di_map(mlc, 0);
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index bcc2d30..8c0b51c 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -905,7 +905,7 @@
 	ts_sync[1]	= 0x0f;
 	ts_sync[2] = ts_sync[3]	= ts_sync[4] = ts_sync[5] = 0;
 	t_sync.act.semaphore = &s_sync;
-	init_MUTEX_LOCKED(&s_sync);
+	sema_init(&s_sync, 0);
 	hp_sdc_enqueue_transaction(&t_sync);
 	down(&s_sync); /* Wait for t_sync to complete */
 
@@ -1039,7 +1039,7 @@
 		return hp_sdc.dev_err;
 	}
 
-	init_MUTEX_LOCKED(&tq_init_sem);
+	sema_init(&tq_init_sem, 0);
 
 	tq_init.actidx		= 0;
 	tq_init.idx		= 1;
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 9986648..cd82bb1 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -243,6 +243,7 @@
 	.write =	serio_raw_write,
 	.poll =		serio_raw_poll,
 	.fasync =	serio_raw_fasync,
+	.llseek = noop_llseek,
 };
 
 
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 6d345112..6e362de 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -165,6 +165,7 @@
 	serio->open = serport_serio_open;
 	serio->close = serport_serio_close;
 	serio->port_data = serport;
+	serio->dev.parent = tty->dev;
 
 	serio_register_port(serport->serio);
 	printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 42ba369..b35876e 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -103,27 +103,26 @@
 static int wacom_open(struct input_dev *dev)
 {
 	struct wacom *wacom = input_get_drvdata(dev);
+	int retval = 0;
+
+	if (usb_autopm_get_interface(wacom->intf) < 0)
+		return -EIO;
 
 	mutex_lock(&wacom->lock);
 
-	wacom->irq->dev = wacom->usbdev;
-
-	if (usb_autopm_get_interface(wacom->intf) < 0) {
-		mutex_unlock(&wacom->lock);
-		return -EIO;
-	}
-
 	if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
-		usb_autopm_put_interface(wacom->intf);
-		mutex_unlock(&wacom->lock);
-		return -EIO;
+		retval = -EIO;
+		goto out;
 	}
 
 	wacom->open = true;
 	wacom->intf->needs_remote_wakeup = 1;
 
+out:
 	mutex_unlock(&wacom->lock);
-	return 0;
+	if (retval)
+		usb_autopm_put_interface(wacom->intf);
+	return retval;
 }
 
 static void wacom_close(struct input_dev *dev)
@@ -135,6 +134,8 @@
 	wacom->open = false;
 	wacom->intf->needs_remote_wakeup = 0;
 	mutex_unlock(&wacom->lock);
+
+	usb_autopm_put_interface(wacom->intf);
 }
 
 static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 6e29bad..47fd7a0 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -442,8 +442,10 @@
 	/* general pen packet */
 	if ((data[1] & 0xb8) == 0xa0) {
 		t = (data[6] << 2) | ((data[7] >> 6) & 3);
-		if (features->type >= INTUOS4S && features->type <= INTUOS4L)
+		if ((features->type >= INTUOS4S && features->type <= INTUOS4L) ||
+		    features->type == WACOM_21UX2) {
 			t = (t << 1) | (data[1] & 1);
+		}
 		input_report_abs(input, ABS_PRESSURE, t);
 		input_report_abs(input, ABS_TILT_X,
 				((data[7] << 1) & 0x7e) | (data[8] >> 7));
diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h
index d4c5051..88c9423 100644
--- a/drivers/isdn/act2000/act2000.h
+++ b/drivers/isdn/act2000/act2000.h
@@ -141,9 +141,9 @@
 	__u8            rcvhdr[8];
 } irq_data_isa;
 
-typedef union irq_data {
+typedef union act2000_irq_data {
 	irq_data_isa isa;
-} irq_data;
+} act2000_irq_data;
 
 /*
  * Per card driver data
@@ -176,7 +176,7 @@
 	char   *status_buf_read;
 	char   *status_buf_write;
 	char   *status_buf_end;
-	irq_data idat;			/* Data used for IRQ handler        */
+	act2000_irq_data idat;		/* Data used for IRQ handler        */
 	isdn_if interface;		/* Interface to upper layer         */
 	char regname[35];		/* Name used for request_region     */
 } act2000_card;
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index 2978bda..e54e79d 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -1515,8 +1515,13 @@
 	while (*s) {
 		int digit1 = 0;
 		int digit2 = 0;
-		if (!isdigit(*s)) return -3;
-		while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; }
+		char *endp;
+
+		digit1 = simple_strtoul(s, &endp, 10);
+		if (s == endp)
+			return -3;
+		s = endp;
+
 		if (digit1 <= 0 || digit1 > 30) return -4;
 		if (*s == 0 || *s == ',' || *s == ' ') {
 			bmask |= (1 << digit1);
@@ -1526,8 +1531,12 @@
 		}
 		if (*s != '-') return -5;
 		s++;
-		if (!isdigit(*s)) return -3;
-		while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; }
+
+		digit2 = simple_strtoul(s, &endp, 10);
+		if (s == endp)
+			return -3;
+		s = endp;
+
 		if (digit2 <= 0 || digit2 > 30) return -4;
 		if (*s == 0 || *s == ',' || *s == ' ') {
 			if (digit1 > digit2)
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index b054494..3acf94c 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -98,6 +98,16 @@
 	return capi_controller[contr - 1];
 }
 
+static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
+{
+	lockdep_assert_held(&capi_controller_lock);
+
+	if (applid - 1 >= CAPI_MAXAPPL)
+		return NULL;
+
+	return capi_applications[applid - 1];
+}
+
 static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
 {
 	if (applid - 1 >= CAPI_MAXAPPL)
@@ -185,10 +195,9 @@
 		ctr->state = CAPI_CTR_RUNNING;
 
 		for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
-			ap = get_capi_appl_by_nr(applid);
-			if (!ap)
-				continue;
-			register_appl(ctr, applid, &ap->rparam);
+			ap = __get_capi_appl_by_nr(applid);
+			if (ap)
+				register_appl(ctr, applid, &ap->rparam);
 		}
 
 		wake_up_interruptible_all(&ctr->state_wait_queue);
@@ -215,7 +224,7 @@
 	memset(ctr->serial, 0, sizeof(ctr->serial));
 
 	for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
-		ap = get_capi_appl_by_nr(applid);
+		ap = __get_capi_appl_by_nr(applid);
 		if (ap)
 			capi_ctr_put(ctr);
 	}
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
index 70cf6ba..48e6d22 100644
--- a/drivers/isdn/divert/isdn_divert.c
+++ b/drivers/isdn/divert/isdn_divert.c
@@ -77,7 +77,7 @@
 
      case DEFLECT_ALERT:
        cs->ics.command = ISDN_CMD_REDIR; /* protocol */
-       strcpy(cs->ics.parm.setup.phone,cs->deflect_dest);
+       strlcpy(cs->ics.parm.setup.phone, cs->deflect_dest, sizeof(cs->ics.parm.setup.phone));
        strcpy(cs->ics.parm.setup.eazmsn,"Testtext delayed");
        divert_if.ll_cmd(&cs->ics);
        spin_lock_irqsave(&divert_lock, flags);
@@ -251,7 +251,7 @@
 
      case 2: /* redir */
        del_timer(&cs->timer); 
-       strcpy(cs->ics.parm.setup.phone, to_nr);
+       strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone));
        strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual");
        ic.command = ISDN_CMD_REDIR;
        if ((i = divert_if.ll_cmd(&ic)))
@@ -480,7 +480,7 @@
                if (!cs->timer.expires)
 		 { strcpy(ic->parm.setup.eazmsn,"Testtext direct");
                    ic->parm.setup.screen = dv->rule.screen;
-                   strcpy(ic->parm.setup.phone,dv->rule.to_nr);
+                   strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone));
                    cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
                    cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
                    retval = 5; 
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 707d9c9..178942a 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -109,6 +109,9 @@
 
 	struct urb		*urb_int_in;	/* URB for interrupt pipe */
 	unsigned char		*int_in_buf;
+	struct work_struct	int_in_wq;	/* for usb_clear_halt() */
+	struct timer_list	timer_int_in;	/* int read retry delay */
+	int			retry_int_in;
 
 	spinlock_t		lock;		/* locks all following */
 	int			basstate;	/* bitmap (BS_*) */
@@ -169,7 +172,7 @@
 	case -EAGAIN:
 		return "start frame too early or too much scheduled";
 	case -EFBIG:
-		return "too many isochronous frames requested";
+		return "too many isoc frames requested";
 	case -EPIPE:
 		return "endpoint stalled";
 	case -EMSGSIZE:
@@ -200,13 +203,13 @@
 	case -ENOENT:
 		return "unlinked (sync)";
 	case -EINPROGRESS:
-		return "pending";
+		return "URB still pending";
 	case -EPROTO:
-		return "bit stuffing error, timeout, or unknown USB error";
+		return "bitstuff error, timeout, or unknown USB error";
 	case -EILSEQ:
 		return "CRC mismatch, timeout, or unknown USB error";
 	case -ETIME:
-		return "timed out";
+		return "USB response timeout";
 	case -EPIPE:
 		return "endpoint stalled";
 	case -ECOMM:
@@ -214,15 +217,15 @@
 	case -ENOSR:
 		return "OUT buffer underrun";
 	case -EOVERFLOW:
-		return "too much data";
+		return "endpoint babble";
 	case -EREMOTEIO:
-		return "short packet detected";
+		return "short packet";
 	case -ENODEV:
 		return "device removed";
 	case -EXDEV:
-		return "partial isochronous transfer";
+		return "partial isoc transfer";
 	case -EINVAL:
-		return "invalid argument";
+		return "ISO madness";
 	case -ECONNRESET:
 		return "unlinked (async)";
 	case -ESHUTDOWN:
@@ -350,7 +353,7 @@
  * reset Gigaset device because of an unrecoverable error
  * This function may be called from any context, and takes care of
  * scheduling the necessary actions for execution outside of interrupt context.
- * cs->lock must not be held.
+ * cs->hw.bas->lock must not be held.
  * argument:
  *	controller state structure
  */
@@ -358,7 +361,9 @@
 {
 	/* reset interrupt pipe to recover (ignore errors) */
 	update_basstate(cs->hw.bas, BS_RESETTING, 0);
-	req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT);
+	if (req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT))
+		/* submission failed, escalate to USB port reset */
+		usb_queue_reset_device(cs->hw.bas->interface);
 }
 
 /* check_pending
@@ -438,23 +443,27 @@
 		return;
 	}
 
-	if (ucs->retry_cmd_in++ < BAS_RETRY) {
-		dev_notice(cs->dev, "control read: timeout, retry %d\n",
-			   ucs->retry_cmd_in);
-		rc = atread_submit(cs, BAS_TIMEOUT);
-		if (rc >= 0 || rc == -ENODEV)
-			/* resubmitted or disconnected */
-			/* - bypass regular exit block */
-			return;
-	} else {
+	if (ucs->retry_cmd_in++ >= BAS_RETRY) {
 		dev_err(cs->dev,
 			"control read: timeout, giving up after %d tries\n",
 			ucs->retry_cmd_in);
+		kfree(ucs->rcvbuf);
+		ucs->rcvbuf = NULL;
+		ucs->rcvbuf_size = 0;
+		error_reset(cs);
+		return;
 	}
-	kfree(ucs->rcvbuf);
-	ucs->rcvbuf = NULL;
-	ucs->rcvbuf_size = 0;
-	error_reset(cs);
+
+	gig_dbg(DEBUG_USBREQ, "%s: timeout, retry %d",
+		__func__, ucs->retry_cmd_in);
+	rc = atread_submit(cs, BAS_TIMEOUT);
+	if (rc < 0) {
+		kfree(ucs->rcvbuf);
+		ucs->rcvbuf = NULL;
+		ucs->rcvbuf_size = 0;
+		if (rc != -ENODEV)
+			error_reset(cs);
+	}
 }
 
 /* read_ctrl_callback
@@ -470,18 +479,11 @@
 	struct cardstate *cs = inbuf->cs;
 	struct bas_cardstate *ucs = cs->hw.bas;
 	int status = urb->status;
-	int have_data = 0;
 	unsigned numbytes;
 	int rc;
 
 	update_basstate(ucs, 0, BS_ATRDPEND);
 	wake_up(&ucs->waitqueue);
-
-	if (!ucs->rcvbuf_size) {
-		dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
-		return;
-	}
-
 	del_timer(&ucs->timer_cmd_in);
 
 	switch (status) {
@@ -495,19 +497,10 @@
 				numbytes = ucs->rcvbuf_size;
 		}
 
-		/* copy received bytes to inbuf */
-		have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes);
-
-		if (unlikely(numbytes < ucs->rcvbuf_size)) {
-			/* incomplete - resubmit for remaining bytes */
-			ucs->rcvbuf_size -= numbytes;
-			ucs->retry_cmd_in = 0;
-			rc = atread_submit(cs, BAS_TIMEOUT);
-			if (rc >= 0 || rc == -ENODEV)
-				/* resubmitted or disconnected */
-				/* - bypass regular exit block */
-				return;
-			error_reset(cs);
+		/* copy received bytes to inbuf, notify event layer */
+		if (gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes)) {
+			gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
+			gigaset_schedule_event(cs);
 		}
 		break;
 
@@ -516,37 +509,32 @@
 	case -EINPROGRESS:		/* pending */
 	case -ENODEV:			/* device removed */
 	case -ESHUTDOWN:		/* device shut down */
-		/* no action necessary */
+		/* no further action necessary */
 		gig_dbg(DEBUG_USBREQ, "%s: %s",
 			__func__, get_usb_statmsg(status));
 		break;
 
-	default:			/* severe trouble */
-		dev_warn(cs->dev, "control read: %s\n",
-			 get_usb_statmsg(status));
+	default:			/* other errors: retry */
 		if (ucs->retry_cmd_in++ < BAS_RETRY) {
-			dev_notice(cs->dev, "control read: retry %d\n",
-				   ucs->retry_cmd_in);
+			gig_dbg(DEBUG_USBREQ, "%s: %s, retry %d", __func__,
+				get_usb_statmsg(status), ucs->retry_cmd_in);
 			rc = atread_submit(cs, BAS_TIMEOUT);
-			if (rc >= 0 || rc == -ENODEV)
-				/* resubmitted or disconnected */
-				/* - bypass regular exit block */
+			if (rc >= 0)
+				/* successfully resubmitted, skip freeing */
 				return;
-		} else {
-			dev_err(cs->dev,
-				"control read: giving up after %d tries\n",
-				ucs->retry_cmd_in);
+			if (rc == -ENODEV)
+				/* disconnect, no further action necessary */
+				break;
 		}
+		dev_err(cs->dev, "control read: %s, giving up after %d tries\n",
+			get_usb_statmsg(status), ucs->retry_cmd_in);
 		error_reset(cs);
 	}
 
+	/* read finished, free buffer */
 	kfree(ucs->rcvbuf);
 	ucs->rcvbuf = NULL;
 	ucs->rcvbuf_size = 0;
-	if (have_data) {
-		gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
-		gigaset_schedule_event(cs);
-	}
 }
 
 /* atread_submit
@@ -605,14 +593,67 @@
 
 	if (timeout > 0) {
 		gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
-		ucs->timer_cmd_in.expires = jiffies + timeout * HZ / 10;
-		ucs->timer_cmd_in.data = (unsigned long) cs;
-		ucs->timer_cmd_in.function = cmd_in_timeout;
-		add_timer(&ucs->timer_cmd_in);
+		mod_timer(&ucs->timer_cmd_in, jiffies + timeout * HZ / 10);
 	}
 	return 0;
 }
 
+/* int_in_work
+ * workqueue routine to clear halt on interrupt in endpoint
+ */
+
+static void int_in_work(struct work_struct *work)
+{
+	struct bas_cardstate *ucs =
+		container_of(work, struct bas_cardstate, int_in_wq);
+	struct urb *urb = ucs->urb_int_in;
+	struct cardstate *cs = urb->context;
+	int rc;
+
+	/* clear halt condition */
+	rc = usb_clear_halt(ucs->udev, urb->pipe);
+	gig_dbg(DEBUG_USBREQ, "clear_halt: %s", get_usb_rcmsg(rc));
+	if (rc == 0)
+		/* success, resubmit interrupt read URB */
+		rc = usb_submit_urb(urb, GFP_ATOMIC);
+	if (rc != 0 && rc != -ENODEV) {
+		dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc));
+		rc = usb_lock_device_for_reset(ucs->udev, ucs->interface);
+		if (rc == 0) {
+			rc = usb_reset_device(ucs->udev);
+			usb_unlock_device(ucs->udev);
+		}
+	}
+	ucs->retry_int_in = 0;
+}
+
+/* int_in_resubmit
+ * timer routine for interrupt read delayed resubmit
+ * argument:
+ *	controller state structure
+ */
+static void int_in_resubmit(unsigned long data)
+{
+	struct cardstate *cs = (struct cardstate *) data;
+	struct bas_cardstate *ucs = cs->hw.bas;
+	int rc;
+
+	if (ucs->retry_int_in++ >= BAS_RETRY) {
+		dev_err(cs->dev, "interrupt read: giving up after %d tries\n",
+			ucs->retry_int_in);
+		usb_queue_reset_device(ucs->interface);
+		return;
+	}
+
+	gig_dbg(DEBUG_USBREQ, "%s: retry %d", __func__, ucs->retry_int_in);
+	rc = usb_submit_urb(ucs->urb_int_in, GFP_ATOMIC);
+	if (rc != 0 && rc != -ENODEV) {
+		dev_err(cs->dev, "could not resubmit interrupt URB: %s\n",
+			get_usb_rcmsg(rc));
+		usb_queue_reset_device(ucs->interface);
+	}
+}
+
 /* read_int_callback
  * USB completion handler for interrupt pipe input
  * called by the USB subsystem in interrupt context
@@ -633,19 +674,29 @@
 
 	switch (status) {
 	case 0:			/* success */
+		ucs->retry_int_in = 0;
 		break;
+	case -EPIPE:			/* endpoint stalled */
+		schedule_work(&ucs->int_in_wq);
+		/* fall through */
 	case -ENOENT:			/* cancelled */
 	case -ECONNRESET:		/* cancelled (async) */
 	case -EINPROGRESS:		/* pending */
-		/* ignore silently */
+	case -ENODEV:			/* device removed */
+	case -ESHUTDOWN:		/* device shut down */
+		/* no further action necessary */
 		gig_dbg(DEBUG_USBREQ, "%s: %s",
 			__func__, get_usb_statmsg(status));
 		return;
-	case -ENODEV:			/* device removed */
-	case -ESHUTDOWN:		/* device shut down */
-		gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__);
+	case -EPROTO:			/* protocol error or unplug */
+	case -EILSEQ:
+	case -ETIME:
+		/* resubmit after delay */
+		gig_dbg(DEBUG_USBREQ, "%s: %s",
+			__func__, get_usb_statmsg(status));
+		mod_timer(&ucs->timer_int_in, jiffies + HZ / 10);
 		return;
-	default:		/* severe trouble */
+	default:		/* other errors: just resubmit */
 		dev_warn(cs->dev, "interrupt read: %s\n",
 			 get_usb_statmsg(status));
 		goto resubmit;
@@ -723,6 +774,13 @@
 			break;
 		}
 		spin_lock_irqsave(&cs->lock, flags);
+		if (ucs->basstate & BS_ATRDPEND) {
+			spin_unlock_irqrestore(&cs->lock, flags);
+			dev_warn(cs->dev,
+	"HD_RECEIVEATDATA_ACK(%d) during HD_READ_ATMESSAGE(%d) ignored\n",
+				 l, ucs->rcvbuf_size);
+			break;
+		}
 		if (ucs->rcvbuf_size) {
 			/* throw away previous buffer - we have no queue */
 			dev_err(cs->dev,
@@ -735,7 +793,6 @@
 		if (ucs->rcvbuf == NULL) {
 			spin_unlock_irqrestore(&cs->lock, flags);
 			dev_err(cs->dev, "out of memory receiving AT data\n");
-			error_reset(cs);
 			break;
 		}
 		ucs->rcvbuf_size = l;
@@ -745,13 +802,10 @@
 			kfree(ucs->rcvbuf);
 			ucs->rcvbuf = NULL;
 			ucs->rcvbuf_size = 0;
-			if (rc != -ENODEV) {
-				spin_unlock_irqrestore(&cs->lock, flags);
-				error_reset(cs);
-				break;
-			}
 		}
 		spin_unlock_irqrestore(&cs->lock, flags);
+		if (rc < 0 && rc != -ENODEV)
+			error_reset(cs);
 		break;
 
 	case HD_RESET_INTERRUPT_PIPE_ACK:
@@ -818,6 +872,7 @@
 		tasklet_hi_schedule(&ubc->rcvd_tasklet);
 	} else {
 		/* tasklet still busy, drop data and resubmit URB */
+		gig_dbg(DEBUG_ISO, "%s: overrun", __func__);
 		ubc->loststatus = status;
 		for (i = 0; i < BAS_NUMFRAMES; i++) {
 			ubc->isoinlost += urb->iso_frame_desc[i].actual_length;
@@ -833,13 +888,11 @@
 			urb->dev = bcs->cs->hw.bas->udev;
 			urb->transfer_flags = URB_ISO_ASAP;
 			urb->number_of_packets = BAS_NUMFRAMES;
-			gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit",
-				__func__);
 			rc = usb_submit_urb(urb, GFP_ATOMIC);
 			if (unlikely(rc != 0 && rc != -ENODEV)) {
 				dev_err(bcs->cs->dev,
-					"could not resubmit isochronous read "
-					"URB: %s\n", get_usb_rcmsg(rc));
+				       "could not resubmit isoc read URB: %s\n",
+					get_usb_rcmsg(rc));
 				dump_urb(DEBUG_ISO, "isoc read", urb);
 				error_hangup(bcs);
 			}
@@ -1081,7 +1134,7 @@
 			gig_dbg(DEBUG_ISO, "%s: disconnected", __func__);
 		else
 			dev_err(ucx->bcs->cs->dev,
-				"could not submit isochronous write URB: %s\n",
+				"could not submit isoc write URB: %s\n",
 				get_usb_rcmsg(rc));
 		return rc;
 	}
@@ -1126,7 +1179,7 @@
 		ubc->isooutovfl = NULL;
 		spin_unlock_irqrestore(&ubc->isooutlock, flags);
 		if (ovfl) {
-			dev_err(cs->dev, "isochronous write buffer underrun\n");
+			dev_err(cs->dev, "isoc write underrun\n");
 			error_hangup(bcs);
 			break;
 		}
@@ -1151,7 +1204,7 @@
 				if (next) {
 					/* couldn't put it back */
 					dev_err(cs->dev,
-					      "losing isochronous write URB\n");
+						"losing isoc write URB\n");
 					error_hangup(bcs);
 				}
 			}
@@ -1178,10 +1231,10 @@
 				if (ifd->status ||
 				    ifd->actual_length != ifd->length) {
 					dev_warn(cs->dev,
-					     "isochronous write: frame %d: %s, "
-					     "only %d of %d bytes sent\n",
-					     i, get_usb_statmsg(ifd->status),
-					     ifd->actual_length, ifd->length);
+					    "isoc write: frame %d[%d/%d]: %s\n",
+						 i, ifd->actual_length,
+						 ifd->length,
+						 get_usb_statmsg(ifd->status));
 					offset = (ifd->offset +
 						  ifd->actual_length)
 						 % BAS_OUTBUFSIZE;
@@ -1190,11 +1243,11 @@
 			}
 			break;
 		case -EPIPE:			/* stall - probably underrun */
-			dev_err(cs->dev, "isochronous write stalled\n");
+			dev_err(cs->dev, "isoc write: stalled\n");
 			error_hangup(bcs);
 			break;
-		default:			/* severe trouble */
-			dev_warn(cs->dev, "isochronous write: %s\n",
+		default:			/* other errors */
+			dev_warn(cs->dev, "isoc write: %s\n",
 				 get_usb_statmsg(status));
 		}
 
@@ -1250,6 +1303,7 @@
 	struct cardstate *cs = bcs->cs;
 	struct urb *urb;
 	int status;
+	struct usb_iso_packet_descriptor *ifd;
 	char *rcvbuf;
 	unsigned long flags;
 	int totleft, numbytes, offset, frame, rc;
@@ -1267,8 +1321,7 @@
 		ubc->isoindone = NULL;
 		if (unlikely(ubc->loststatus != -EINPROGRESS)) {
 			dev_warn(cs->dev,
-				 "isochronous read overrun, "
-				 "dropped URB with status: %s, %d bytes lost\n",
+		"isoc read overrun, URB dropped (status: %s, %d bytes)\n",
 				 get_usb_statmsg(ubc->loststatus),
 				 ubc->isoinlost);
 			ubc->loststatus = -EINPROGRESS;
@@ -1298,11 +1351,11 @@
 				__func__, get_usb_statmsg(status));
 			continue;		/* -> skip */
 		case -EPIPE:
-			dev_err(cs->dev, "isochronous read stalled\n");
+			dev_err(cs->dev, "isoc read: stalled\n");
 			error_hangup(bcs);
 			continue;		/* -> skip */
-		default:			/* severe trouble */
-			dev_warn(cs->dev, "isochronous read: %s\n",
+		default:			/* other error */
+			dev_warn(cs->dev, "isoc read: %s\n",
 				 get_usb_statmsg(status));
 			goto error;
 		}
@@ -1310,40 +1363,52 @@
 		rcvbuf = urb->transfer_buffer;
 		totleft = urb->actual_length;
 		for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) {
-			numbytes = urb->iso_frame_desc[frame].actual_length;
-			if (unlikely(urb->iso_frame_desc[frame].status))
+			ifd = &urb->iso_frame_desc[frame];
+			numbytes = ifd->actual_length;
+			switch (ifd->status) {
+			case 0:			/* success */
+				break;
+			case -EPROTO:		/* protocol error or unplug */
+			case -EILSEQ:
+			case -ETIME:
+				/* probably just disconnected, ignore */
+				gig_dbg(DEBUG_ISO,
+					"isoc read: frame %d[%d]: %s\n",
+					frame, numbytes,
+					get_usb_statmsg(ifd->status));
+				break;
+			default:		/* other error */
+				/* report, assume transferred bytes are ok */
 				dev_warn(cs->dev,
-					 "isochronous read: frame %d[%d]: %s\n",
+					 "isoc read: frame %d[%d]: %s\n",
 					 frame, numbytes,
-					 get_usb_statmsg(
-					    urb->iso_frame_desc[frame].status));
+					 get_usb_statmsg(ifd->status));
+			}
 			if (unlikely(numbytes > BAS_MAXFRAME))
 				dev_warn(cs->dev,
-					 "isochronous read: frame %d: "
-					 "numbytes (%d) > BAS_MAXFRAME\n",
-					 frame, numbytes);
+					 "isoc read: frame %d[%d]: %s\n",
+					 frame, numbytes,
+					 "exceeds max frame size");
 			if (unlikely(numbytes > totleft)) {
 				dev_warn(cs->dev,
-					 "isochronous read: frame %d: "
-					 "numbytes (%d) > totleft (%d)\n",
-					 frame, numbytes, totleft);
+					 "isoc read: frame %d[%d]: %s\n",
+					 frame, numbytes,
+					 "exceeds total transfer length");
 				numbytes = totleft;
 			}
-			offset = urb->iso_frame_desc[frame].offset;
+			offset = ifd->offset;
 			if (unlikely(offset + numbytes > BAS_INBUFSIZE)) {
 				dev_warn(cs->dev,
-					 "isochronous read: frame %d: "
-					 "offset (%d) + numbytes (%d) "
-					 "> BAS_INBUFSIZE\n",
-					 frame, offset, numbytes);
+					 "isoc read: frame %d[%d]: %s\n",
+					 frame, numbytes,
+					 "exceeds end of buffer");
 				numbytes = BAS_INBUFSIZE - offset;
 			}
 			gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs);
 			totleft -= numbytes;
 		}
 		if (unlikely(totleft > 0))
-			dev_warn(cs->dev,
-				 "isochronous read: %d data bytes missing\n",
+			dev_warn(cs->dev, "isoc read: %d data bytes missing\n",
 				 totleft);
 
 error:
@@ -1359,9 +1424,9 @@
 		rc = usb_submit_urb(urb, GFP_ATOMIC);
 		if (unlikely(rc != 0 && rc != -ENODEV)) {
 			dev_err(cs->dev,
-				"could not resubmit isochronous read URB: %s\n",
+				"could not resubmit isoc read URB: %s\n",
 				get_usb_rcmsg(rc));
-			dump_urb(DEBUG_ISO, "resubmit iso read", urb);
+			dump_urb(DEBUG_ISO, "resubmit isoc read", urb);
 			error_hangup(bcs);
 		}
 	}
@@ -1373,12 +1438,12 @@
 /* req_timeout
  * timeout routine for control output request
  * argument:
- *	B channel control structure
+ *	controller state structure
  */
 static void req_timeout(unsigned long data)
 {
-	struct bc_state *bcs = (struct bc_state *) data;
-	struct bas_cardstate *ucs = bcs->cs->hw.bas;
+	struct cardstate *cs = (struct cardstate *) data;
+	struct bas_cardstate *ucs = cs->hw.bas;
 	int pending;
 	unsigned long flags;
 
@@ -1395,38 +1460,44 @@
 		break;
 
 	case HD_OPEN_ATCHANNEL:
-		dev_err(bcs->cs->dev, "timeout opening AT channel\n");
-		error_reset(bcs->cs);
+		dev_err(cs->dev, "timeout opening AT channel\n");
+		error_reset(cs);
+		break;
+
+	case HD_OPEN_B1CHANNEL:
+		dev_err(cs->dev, "timeout opening channel 1\n");
+		error_hangup(&cs->bcs[0]);
 		break;
 
 	case HD_OPEN_B2CHANNEL:
-	case HD_OPEN_B1CHANNEL:
-		dev_err(bcs->cs->dev, "timeout opening channel %d\n",
-			bcs->channel + 1);
-		error_hangup(bcs);
+		dev_err(cs->dev, "timeout opening channel 2\n");
+		error_hangup(&cs->bcs[1]);
 		break;
 
 	case HD_CLOSE_ATCHANNEL:
-		dev_err(bcs->cs->dev, "timeout closing AT channel\n");
-		error_reset(bcs->cs);
+		dev_err(cs->dev, "timeout closing AT channel\n");
+		error_reset(cs);
+		break;
+
+	case HD_CLOSE_B1CHANNEL:
+		dev_err(cs->dev, "timeout closing channel 1\n");
+		error_reset(cs);
 		break;
 
 	case HD_CLOSE_B2CHANNEL:
-	case HD_CLOSE_B1CHANNEL:
-		dev_err(bcs->cs->dev, "timeout closing channel %d\n",
-			bcs->channel + 1);
-		error_reset(bcs->cs);
+		dev_err(cs->dev, "timeout closing channel 2\n");
+		error_reset(cs);
 		break;
 
 	case HD_RESET_INTERRUPT_PIPE:
 		/* error recovery escalation */
-		dev_err(bcs->cs->dev,
+		dev_err(cs->dev,
 			"reset interrupt pipe timeout, attempting USB reset\n");
-		usb_queue_reset_device(bcs->cs->hw.bas->interface);
+		usb_queue_reset_device(ucs->interface);
 		break;
 
 	default:
-		dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n",
+		dev_warn(cs->dev, "request 0x%02x timed out, clearing\n",
 			 pending);
 	}
 
@@ -1557,10 +1628,7 @@
 
 	if (timeout > 0) {
 		gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
-		ucs->timer_ctrl.expires = jiffies + timeout * HZ / 10;
-		ucs->timer_ctrl.data = (unsigned long) bcs;
-		ucs->timer_ctrl.function = req_timeout;
-		add_timer(&ucs->timer_ctrl);
+		mod_timer(&ucs->timer_ctrl, jiffies + timeout * HZ / 10);
 	}
 
 	spin_unlock_irqrestore(&ucs->lock, flags);
@@ -1590,21 +1658,20 @@
 
 	if (cs->hw.bas->basstate & BS_SUSPEND) {
 		dev_notice(cs->dev,
-			   "not starting isochronous I/O, "
-			   "suspend in progress\n");
+			   "not starting isoc I/O, suspend in progress\n");
 		spin_unlock_irqrestore(&cs->lock, flags);
 		return -EHOSTUNREACH;
 	}
 
 	ret = starturbs(bcs);
 	if (ret < 0) {
+		spin_unlock_irqrestore(&cs->lock, flags);
 		dev_err(cs->dev,
-			"could not start isochronous I/O for channel B%d: %s\n",
+			"could not start isoc I/O for channel B%d: %s\n",
 			bcs->channel + 1,
 			ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret));
 		if (ret != -ENODEV)
 			error_hangup(bcs);
-		spin_unlock_irqrestore(&cs->lock, flags);
 		return ret;
 	}
 
@@ -1614,11 +1681,11 @@
 		dev_err(cs->dev, "could not open channel B%d\n",
 			bcs->channel + 1);
 		stopurbs(bcs->hw.bas);
-		if (ret != -ENODEV)
-			error_hangup(bcs);
 	}
 
 	spin_unlock_irqrestore(&cs->lock, flags);
+	if (ret < 0 && ret != -ENODEV)
+		error_hangup(bcs);
 	return ret;
 }
 
@@ -1826,10 +1893,7 @@
 	if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) {
 		gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs",
 			ATRDY_TIMEOUT);
-		ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10;
-		ucs->timer_atrdy.data = (unsigned long) cs;
-		ucs->timer_atrdy.function = atrdy_timeout;
-		add_timer(&ucs->timer_atrdy);
+		mod_timer(&ucs->timer_atrdy, jiffies + ATRDY_TIMEOUT * HZ / 10);
 	}
 	return 0;
 }
@@ -1914,6 +1978,28 @@
 	 * The next command will reopen the AT channel automatically.
 	 */
 	if (cb->len == 3 && !memcmp(cb->buf, "+++", 3)) {
+		/* If an HD_RECEIVEATDATA_ACK message remains unhandled
+		 * because of an error, the base never sends another one.
+		 * The response channel is thus effectively blocked.
+		 * Closing and reopening the AT channel does *not* clear
+		 * this condition.
+		 * As a stopgap measure, submit a zero-length AT read
+		 * before closing the AT channel. This has the undocumented
+		 * effect of triggering a new HD_RECEIVEATDATA_ACK message
+		 * from the base if necessary.
+		 * The subsequent AT channel close then discards any pending
+		 * messages.
+		 */
+		spin_lock_irqsave(&cs->lock, flags);
+		if (!(cs->hw.bas->basstate & BS_ATRDPEND)) {
+			kfree(cs->hw.bas->rcvbuf);
+			cs->hw.bas->rcvbuf = NULL;
+			cs->hw.bas->rcvbuf_size = 0;
+			cs->hw.bas->retry_cmd_in = 0;
+			atread_submit(cs, 0);
+		}
+		spin_unlock_irqrestore(&cs->lock, flags);
+
 		rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
 		if (cb->wake_tasklet)
 			tasklet_schedule(cb->wake_tasklet);
@@ -2010,7 +2096,7 @@
 
 	/* kill URBs and tasklets before freeing - better safe than sorry */
 	ubc->running = 0;
-	gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__);
+	gig_dbg(DEBUG_INIT, "%s: killing isoc URBs", __func__);
 	for (i = 0; i < BAS_OUTURBS; ++i) {
 		usb_kill_urb(ubc->isoouturbs[i].urb);
 		usb_free_urb(ubc->isoouturbs[i].urb);
@@ -2131,10 +2217,12 @@
 	ucs->pending = 0;
 
 	ucs->basstate = 0;
-	init_timer(&ucs->timer_ctrl);
-	init_timer(&ucs->timer_atrdy);
-	init_timer(&ucs->timer_cmd_in);
+	setup_timer(&ucs->timer_ctrl, req_timeout, (unsigned long) cs);
+	setup_timer(&ucs->timer_atrdy, atrdy_timeout, (unsigned long) cs);
+	setup_timer(&ucs->timer_cmd_in, cmd_in_timeout, (unsigned long) cs);
+	setup_timer(&ucs->timer_int_in, int_in_resubmit, (unsigned long) cs);
 	init_waitqueue_head(&ucs->waitqueue);
+	INIT_WORK(&ucs->int_in_wq, int_in_work);
 
 	return 1;
 }
@@ -2282,6 +2370,7 @@
 			get_usb_rcmsg(rc));
 		goto error;
 	}
+	ucs->retry_int_in = 0;
 
 	/* tell the device that the driver is ready */
 	rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0);
@@ -2334,10 +2423,12 @@
 	/* stop driver (common part) */
 	gigaset_stop(cs);
 
-	/* stop timers and URBs, free ressources */
+	/* stop delayed work and URBs, free ressources */
 	del_timer_sync(&ucs->timer_ctrl);
 	del_timer_sync(&ucs->timer_atrdy);
 	del_timer_sync(&ucs->timer_cmd_in);
+	del_timer_sync(&ucs->timer_int_in);
+	cancel_work_sync(&ucs->int_in_wq);
 	freeurbs(cs);
 	usb_set_intfdata(interface, NULL);
 	kfree(ucs->rcvbuf);
@@ -2400,10 +2491,14 @@
 		/* in case of timeout, proceed anyway */
 	}
 
-	/* kill all URBs and timers that might still be pending */
+	/* kill all URBs and delayed work that might still be pending */
 	usb_kill_urb(ucs->urb_ctrl);
 	usb_kill_urb(ucs->urb_int_in);
 	del_timer_sync(&ucs->timer_ctrl);
+	del_timer_sync(&ucs->timer_atrdy);
+	del_timer_sync(&ucs->timer_cmd_in);
+	del_timer_sync(&ucs->timer_int_in);
+	cancel_work_sync(&ucs->int_in_wq);
 
 	gig_dbg(DEBUG_SUSPEND, "suspend complete");
 	return 0;
@@ -2425,6 +2520,7 @@
 			get_usb_rcmsg(rc));
 		return rc;
 	}
+	ucs->retry_int_in = 0;
 
 	/* clear suspend flag to reallow activity */
 	update_basstate(ucs, 0, BS_SUSPEND);
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 3ca561e..db621db 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -1026,32 +1026,6 @@
 	return ret;
 }
 
-void gigaset_debugdrivers(void)
-{
-	unsigned long flags;
-	static struct cardstate *cs;
-	struct gigaset_driver *drv;
-	unsigned i;
-
-	spin_lock_irqsave(&driver_lock, flags);
-	list_for_each_entry(drv, &drivers, list) {
-		gig_dbg(DEBUG_DRIVER, "driver %p", drv);
-		spin_lock(&drv->lock);
-		for (i = 0; i < drv->minors; ++i) {
-			gig_dbg(DEBUG_DRIVER, "  index %u", i);
-			cs = drv->cs + i;
-			gig_dbg(DEBUG_DRIVER, "    cardstate %p", cs);
-			gig_dbg(DEBUG_DRIVER, "    flags 0x%02x", cs->flags);
-			gig_dbg(DEBUG_DRIVER, "    minor_index %u",
-				cs->minor_index);
-			gig_dbg(DEBUG_DRIVER, "    driver %p", cs->driver);
-			gig_dbg(DEBUG_DRIVER, "    i4l id %d", cs->myid);
-		}
-		spin_unlock(&drv->lock);
-	}
-	spin_unlock_irqrestore(&driver_lock, flags);
-}
-
 static struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
 {
 	unsigned long flags;
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index a69512f..6dd3607 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -70,7 +70,6 @@
 	DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */
 	DEBUG_LLDATA	  = 0x00100, /* sent/received LL data */
 	DEBUG_EVENT	  = 0x00200, /* event processing */
-	DEBUG_DRIVER	  = 0x00400, /* driver structure */
 	DEBUG_HDLC	  = 0x00800, /* M10x HDLC processing */
 	DEBUG_CHANNEL	  = 0x01000, /* channel allocation/deallocation */
 	DEBUG_TRANSCMD	  = 0x02000, /* AT-COMMANDS+RESPONSES */
@@ -727,7 +726,7 @@
 
 /* Deallocate driver structure. */
 void gigaset_freedriver(struct gigaset_driver *drv);
-void gigaset_debugdrivers(void);
+
 struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty);
 struct cardstate *gigaset_get_cs_by_id(int id);
 void gigaset_blockdriver(struct gigaset_driver *drv);
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 34bca37..9bec8b9 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -201,8 +201,6 @@
 	int i;
 	size_t l;
 
-	gigaset_debugdrivers();
-
 	gig_dbg(DEBUG_CMD, "driver: %d, command: %d, arg: 0x%lx",
 		cntrl->driver, cntrl->command, cntrl->arg);
 
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 2dfd346..f39ccdf 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -842,13 +842,14 @@
 
 	if (unlikely(bcs->ignore)) {
 		bcs->ignore--;
-		hdlc_flush(bcs);
 		return;
 	}
 	skb = bcs->rx_skb;
-	if (skb == NULL)
+	if (skb == NULL) {
 		skb = gigaset_new_rx_skb(bcs);
-	bcs->hw.bas->goodbytes += skb->len;
+		if (skb == NULL)
+			return;
+	}
 	dobytes = bcs->rx_bufsize - skb->len;
 	while (count > 0) {
 		dst = skb_put(skb, count < dobytes ? count : dobytes);
@@ -860,6 +861,7 @@
 		if (dobytes == 0) {
 			dump_bytes(DEBUG_STREAM_DUMP,
 				   "rcv data", skb->data, skb->len);
+			bcs->hw.bas->goodbytes += skb->len;
 			gigaset_skb_rcvd(bcs, skb);
 			skb = gigaset_new_rx_skb(bcs);
 			if (skb == NULL)
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 09b1795..91f06a3 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -20,7 +20,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -39,87 +38,32 @@
 
 /*====================================================================*/
 
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card insertion
-   and ejection events.  They are invoked from the skeleton event
-   handler.
-*/
-
 static int avmcs_config(struct pcmcia_device *link);
 static void avmcs_release(struct pcmcia_device *link);
-
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void avmcs_detach(struct pcmcia_device *p_dev);
 
-/*======================================================================
-
-    avmcs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link 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 avmcs_probe(struct pcmcia_device *p_dev)
 {
-
-    /* The io structure describes IO port mapping */
-    p_dev->resource[0]->end = 16;
-    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
     /* General socket configuration */
-    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-    p_dev->conf.IntType = INT_MEMORY_AND_IO;
-    p_dev->conf.ConfigIndex = 1;
-    p_dev->conf.Present = PRESENT_OPTION;
+    p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+    p_dev->config_index = 1;
+    p_dev->config_regs = PRESENT_OPTION;
 
     return avmcs_config(p_dev);
 } /* avmcs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
 
 static void avmcs_detach(struct pcmcia_device *link)
 {
 	avmcs_release(link);
 } /* avmcs_detach */
 
-/*======================================================================
-
-    avmcs_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-    
-======================================================================*/
-
-static int avmcs_configcheck(struct pcmcia_device *p_dev,
-			     cistpl_cftable_entry_t *cf,
-			     cistpl_cftable_entry_t *dflt,
-			     unsigned int vcc,
-			     void *priv_data)
+static int avmcs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cf->io.nwin <= 0)
-		return -ENODEV;
+	p_dev->resource[0]->end = 16;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
-	p_dev->resource[0]->start = cf->io.win[0].base;
-	p_dev->resource[0]->end = cf->io.win[0].len;
 	return pcmcia_request_io(p_dev);
 }
 
@@ -150,7 +94,7 @@
 	/*
          * configure the PCMCIA socket
 	  */
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0) {
 	    pcmcia_disable_device(link);
 	    break;
@@ -197,13 +141,6 @@
 
 } /* avmcs_config */
 
-/*======================================================================
-
-    After a card is removed, avmcs_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-    
-======================================================================*/
 
 static void avmcs_release(struct pcmcia_device *link)
 {
@@ -222,9 +159,7 @@
 
 static struct pcmcia_driver avmcs_driver = {
 	.owner	= THIS_MODULE,
-	.drv	= {
-		.name	= "avm_cs",
-	},
+	.name		= "avm_cs",
 	.probe = avmcs_probe,
 	.remove	= avmcs_detach,
 	.id_table = avmcs_ids,
diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c
index 33ce89e..3626401 100644
--- a/drivers/isdn/hardware/eicon/debug.c
+++ b/drivers/isdn/hardware/eicon/debug.c
@@ -862,7 +862,7 @@
   diva_os_spin_lock_magic_t old_irql, old_irql1;
   dword sec, usec, logical, serial, org_mask;
   int id, best_id = 0, free_id = -1;
-  char tmp[256];
+  char tmp[128];
   diva_dbg_entry_head_t* pmsg = NULL;
   int len;
   word size;
diff --git a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h
index 8ea5877..02eed6b 100644
--- a/drivers/isdn/hardware/eicon/debuglib.h
+++ b/drivers/isdn/hardware/eicon/debuglib.h
@@ -249,7 +249,7 @@
  }     regTime ;  /* timestamp for registration       */
  void               *pIrp ;   /* ptr to pending i/o request       */
  unsigned long       dbgMask ;  /* current debug mask               */
- char                drvName[16] ; /* ASCII name of registered driver  */
+ char                drvName[128] ; /* ASCII name of registered driver  */
  char                drvTag[64] ; /* revision string     */
  DbgEnd              dbg_end ;  /* function for debug closing       */
  DbgLog              dbg_prt ;  /* function for debug appending     */
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index ed9c555..f332b60 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -15,7 +15,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/ioport.h>
-#include <linux/workqueue.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/list.h>
@@ -546,7 +545,6 @@
 		void *mem;
 
 		tasklet_kill(&pdpc->divas_task);
-		flush_scheduled_work();
 		mem = psoft_isr->object;
 		psoft_isr->object = NULL;
 		diva_os_free(0, mem);
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 94263c2..ac4dd78 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -20,7 +20,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include "hisax_cfg.h"
@@ -40,67 +39,22 @@
 
 /*====================================================================*/
 
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card insertion
-   and ejection events.  They are invoked from the skeleton event
-   handler.
-*/
-
 static int avma1cs_config(struct pcmcia_device *link) __devinit ;
 static void avma1cs_release(struct pcmcia_device *link);
-
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void avma1cs_detach(struct pcmcia_device *p_dev) __devexit ;
 
-
-/*======================================================================
-
-    avma1cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link 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 __devinit avma1cs_probe(struct pcmcia_device *p_dev)
 {
     dev_dbg(&p_dev->dev, "avma1cs_attach()\n");
 
-    /* The io structure describes IO port mapping */
-    p_dev->resource[0]->end = 16;
-    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-    p_dev->resource[1]->end = 16;
-    p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
-
     /* General socket configuration */
-    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-    p_dev->conf.IntType = INT_MEMORY_AND_IO;
-    p_dev->conf.ConfigIndex = 1;
-    p_dev->conf.Present = PRESENT_OPTION;
+    p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+    p_dev->config_index = 1;
+    p_dev->config_regs = PRESENT_OPTION;
 
     return avma1cs_config(p_dev);
 } /* avma1cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void __devexit avma1cs_detach(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link);
@@ -108,26 +62,13 @@
 	kfree(link->priv);
 } /* avma1cs_detach */
 
-/*======================================================================
-
-    avma1cs_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-    
-======================================================================*/
-
-static int avma1cs_configcheck(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cf,
-			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
-			       void *priv_data)
+static int avma1cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cf->io.nwin <= 0)
-		return -ENODEV;
-
-	p_dev->resource[0]->start = cf->io.win[0].base;
-	p_dev->resource[0]->end = cf->io.win[0].len;
+	p_dev->resource[0]->end = 16;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 	p_dev->io_lines = 5;
+
 	return pcmcia_request_io(p_dev);
 }
 
@@ -161,7 +102,7 @@
 	/*
 	 * configure the PCMCIA socket
 	 */
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0) {
 	    pcmcia_disable_device(link);
 	    break;
@@ -175,9 +116,6 @@
 	return -ENODEV;
     }
 
-    printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
-		(unsigned int) link->resource[0]->start, link->irq);
-
     icard.para[0] = link->irq;
     icard.para[1] = link->resource[0]->start;
     icard.protocol = isdnprot;
@@ -196,14 +134,6 @@
     return 0;
 } /* avma1cs_config */
 
-/*======================================================================
-
-    After a card is removed, avma1cs_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-    
-======================================================================*/
-
 static void avma1cs_release(struct pcmcia_device *link)
 {
 	unsigned long minor = (unsigned long) link->priv;
@@ -216,7 +146,6 @@
 	pcmcia_disable_device(link);
 } /* avma1cs_release */
 
-
 static struct pcmcia_device_id avma1cs_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
 	PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b),
@@ -226,19 +155,15 @@
 
 static struct pcmcia_driver avma1cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "avma1_cs",
-	},
+	.name		= "avma1_cs",
 	.probe		= avma1cs_probe,
 	.remove		= __devexit_p(avma1cs_detach),
 	.id_table	= avma1cs_ids,
 };
 
-/*====================================================================*/
-
 static int __init init_avma1_cs(void)
 {
-	return(pcmcia_register_driver(&avma1cs_driver));
+	return pcmcia_register_driver(&avma1cs_driver);
 }
 
 static void __exit exit_avma1_cs(void)
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 6f9afcd..b133378 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -801,6 +801,16 @@
 	ll_unload(csta);
 }
 
+static irqreturn_t card_irq(int intno, void *dev_id)
+{
+	struct IsdnCardState *cs = dev_id;
+	irqreturn_t ret = cs->irq_func(intno, cs);
+
+	if (ret == IRQ_HANDLED)
+		cs->irq_cnt++;
+	return ret;
+}
+
 static int init_card(struct IsdnCardState *cs)
 {
 	int 	irq_cnt, cnt = 3, ret;
@@ -809,10 +819,10 @@
 		ret = cs->cardmsg(cs, CARD_INIT, NULL);
 		return(ret);
 	}
-	irq_cnt = kstat_irqs(cs->irq);
+	irq_cnt = cs->irq_cnt = 0;
 	printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
 	       cs->irq, irq_cnt);
-	if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) {
+	if (request_irq(cs->irq, card_irq, cs->irq_flags, "HiSax", cs)) {
 		printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
 		       cs->irq);
 		return 1;
@@ -822,8 +832,8 @@
 		/* Timeout 10ms */
 		msleep(10);
 		printk(KERN_INFO "%s: IRQ %d count %d\n",
-		       CardType[cs->typ], cs->irq, kstat_irqs(cs->irq));
-		if (kstat_irqs(cs->irq) == irq_cnt) {
+		       CardType[cs->typ], cs->irq, cs->irq_cnt);
+		if (cs->irq_cnt == irq_cnt) {
 			printk(KERN_WARNING
 			       "%s: IRQ(%d) getting no interrupts during init %d\n",
 			       CardType[cs->typ], cs->irq, 4 - cnt);
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index b3c08aa..496d477 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -46,7 +46,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -64,26 +63,8 @@
 static int protocol = 2;        /* EURO-ISDN Default */
 module_param(protocol, int, 0);
 
-/*====================================================================*/
-
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card insertion
-   and ejection events.  They are invoked from the elsa_cs event
-   handler.
-*/
-
 static int elsa_cs_config(struct pcmcia_device *link) __devinit ;
 static void elsa_cs_release(struct pcmcia_device *link);
-
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void elsa_cs_detach(struct pcmcia_device *p_dev) __devexit;
 
 typedef struct local_info_t {
@@ -92,18 +73,6 @@
     int			cardnr;
 } local_info_t;
 
-/*======================================================================
-
-    elsa_cs_attach() creates an "instance" of the driver, allocatingx
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link 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 __devinit elsa_cs_probe(struct pcmcia_device *link)
 {
     local_info_t *local;
@@ -119,31 +88,9 @@
 
     local->cardnr = -1;
 
-    /*
-      General socket configuration defaults can go here.  In this
-      client, we assume very little, and rely on the CIS for almost
-      everything.  In most clients, many details (i.e., number, sizes,
-      and attributes of IO windows) are fixed by the nature of the
-      device, and can be hard-wired here.
-    */
-    link->resource[0]->end = 8;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-
     return elsa_cs_config(link);
 } /* elsa_cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void __devexit elsa_cs_detach(struct pcmcia_device *link)
 {
 	local_info_t *info = link->priv;
@@ -156,27 +103,17 @@
 	kfree(info);
 } /* elsa_cs_detach */
 
-/*======================================================================
-
-    elsa_cs_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.
-
-======================================================================*/
-
-static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cf,
-			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
-			       void *priv_data)
+static int elsa_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int j;
 
 	p_dev->io_lines = 3;
+	p_dev->resource[0]->end = 8;
+	p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
-	if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+	if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) {
 		printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
-		p_dev->resource[0]->start = cf->io.win[0].base;
 		if (!pcmcia_request_io(p_dev))
 			return 0;
 	} else {
@@ -199,6 +136,8 @@
     dev_dbg(&link->dev, "elsa_config(0x%p)\n", link);
     dev = link->priv;
 
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
     i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL);
     if (i != 0)
 	goto failed;
@@ -206,21 +145,10 @@
     if (!link->irq)
 	goto failed;
 
-    i = pcmcia_request_configuration(link, &link->conf);
+    i = pcmcia_enable_device(link);
     if (i != 0)
 	goto failed;
 
-    /* Finally, report what we've done */
-    dev_info(&link->dev, "index 0x%02x: ",
-	    link->conf.ConfigIndex);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-	printk(", irq %d", link->irq);
-    if (link->resource[0])
-	printk(" & %pR", link->resource[0]);
-    if (link->resource[1])
-	printk(" & %pR", link->resource[1]);
-    printk("\n");
-
     icard.para[0] = link->irq;
     icard.para[1] = link->resource[0]->start;
     icard.protocol = protocol;
@@ -240,14 +168,6 @@
     return -ENODEV;
 } /* elsa_cs_config */
 
-/*======================================================================
-
-    After a card is removed, elsa_cs_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void elsa_cs_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
@@ -291,9 +211,7 @@
 
 static struct pcmcia_driver elsa_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "elsa_cs",
-	},
+	.name		= "elsa_cs",
 	.probe		= elsa_cs_probe,
 	.remove		= __devexit_p(elsa_cs_detach),
 	.id_table	= elsa_ids,
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index be5faf4..5aa138e 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -234,13 +234,14 @@
 	  count++;
 	  if (count > trans_max) 
 	    count = trans_max; /* limit length */
-	    if ((skb = dev_alloc_skb(count))) {
-	      dst = skb_put(skb, count);
-	      while (count--) 
+	  skb = dev_alloc_skb(count);
+	  if (skb) {
+	    dst = skb_put(skb, count);
+	    while (count--)
 		*dst++ = Read_hfc(cs, HFCSX_FIF_DRD);
-	      return(skb);
-	    }
-	    else return(NULL); /* no memory */
+	    return skb;
+	  } else
+		return NULL; /* no memory */
 	}
 
 	do {
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 832a878..32ab392 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -959,6 +959,7 @@
 	u_long		event;
 	struct work_struct tqueue;
 	struct timer_list dbusytimer;
+	unsigned int	irq_cnt;
 #ifdef ERROR_STATISTIC
 	int		err_crc;
 	int		err_tx;
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index a024192..360204b 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -46,7 +46,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -64,26 +63,9 @@
 static int protocol = 2;        /* EURO-ISDN Default */
 module_param(protocol, int, 0);
 
-/*====================================================================*/
-
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card
-   insertion and ejection events.  They are invoked from the sedlbauer
-   event handler. 
-*/
-
 static int sedlbauer_config(struct pcmcia_device *link) __devinit ;
 static void sedlbauer_release(struct pcmcia_device *link);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void sedlbauer_detach(struct pcmcia_device *p_dev) __devexit;
 
 typedef struct local_info_t {
@@ -92,18 +74,6 @@
     int			cardnr;
 } local_info_t;
 
-/*======================================================================
-
-    sedlbauer_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link 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 __devinit sedlbauer_probe(struct pcmcia_device *link)
 {
     local_info_t *local;
@@ -118,35 +88,9 @@
     local->p_dev = link;
     link->priv = local;
 
-    /*
-      General socket configuration defaults can go here.  In this
-      client, we assume very little, and rely on the CIS for almost
-      everything.  In most clients, many details (i.e., number, sizes,
-      and attributes of IO windows) are fixed by the nature of the
-      device, and can be hard-wired here.
-    */
-
-    /* from old sedl_cs 
-    */
-    /* The io structure describes IO port mapping */
-    link->resource[0]->end = 8;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
-    link->conf.Attributes = 0;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-
     return sedlbauer_config(link);
 } /* sedlbauer_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void __devexit sedlbauer_detach(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link);
@@ -158,70 +102,15 @@
 	kfree(link->priv);
 } /* sedlbauer_detach */
 
-/*======================================================================
-
-    sedlbauer_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.
-    
-======================================================================*/
-static int sedlbauer_config_check(struct pcmcia_device *p_dev,
-				  cistpl_cftable_entry_t *cfg,
-				  cistpl_cftable_entry_t *dflt,
-				  unsigned int vcc,
-				  void *priv_data)
+static int sedlbauer_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-		p_dev->conf.Status = CCSR_AUDIO_ENA;
-	}
-
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-		if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
-			return -ENODEV;
-	} else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-		if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
-			return -ENODEV;
-	}
-
-	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-					pcmcia_io_cfg_data_width(io->flags);
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		p_dev->io_lines = 3;
-		if (pcmcia_request_io(p_dev) != 0)
-			return -ENODEV;
-	}
-
-	return 0;
+	p_dev->io_lines = 3;
+	return pcmcia_request_io(p_dev);
 }
 
-
-
 static int __devinit sedlbauer_config(struct pcmcia_device *link)
 {
     int ret;
@@ -229,44 +118,17 @@
 
     dev_dbg(&link->dev, "sedlbauer_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.
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
+	    CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
 
-      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.
-    */
     ret = pcmcia_loop_config(link, sedlbauer_config_check, NULL);
     if (ret)
 	    goto failed;
 
-    /*
-       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.
-    */
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
-    /* Finally, report what we've done */
-    dev_info(&link->dev, "index 0x%02x:",
-	   link->conf.ConfigIndex);
-    if (link->conf.Vpp)
-	printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-	printk(", irq %d", link->irq);
-    if (link->resource[0])
-	printk(" & %pR", link->resource[0]);
-    if (link->resource[1])
-	printk(" & %pR", link->resource[1]);
-    printk("\n");
-
     icard.para[0] = link->irq;
     icard.para[1] = link->resource[0]->start;
     icard.protocol = protocol;
@@ -290,14 +152,6 @@
 
 } /* sedlbauer_config */
 
-/*======================================================================
-
-    After a card is removed, sedlbauer_release() will unregister the
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-    
-======================================================================*/
-
 static void sedlbauer_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
@@ -346,9 +200,7 @@
 
 static struct pcmcia_driver sedlbauer_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "sedlbauer_cs",
-	},
+	.name		= "sedlbauer_cs",
 	.probe		= sedlbauer_probe,
 	.remove		= __devexit_p(sedlbauer_detach),
 	.id_table	= sedlbauer_ids,
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 7296102..282a446 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -27,7 +27,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -45,26 +44,8 @@
 static int protocol = 2;        /* EURO-ISDN Default */
 module_param(protocol, int, 0);
 
-/*====================================================================*/
-
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card insertion
-   and ejection events.  They are invoked from the teles_cs event
-   handler.
-*/
-
 static int teles_cs_config(struct pcmcia_device *link) __devinit ;
 static void teles_cs_release(struct pcmcia_device *link);
-
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void teles_detach(struct pcmcia_device *p_dev) __devexit ;
 
 typedef struct local_info_t {
@@ -73,18 +54,6 @@
     int			cardnr;
 } local_info_t;
 
-/*======================================================================
-
-    teles_attach() creates an "instance" of the driver, allocatingx
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link 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 __devinit teles_probe(struct pcmcia_device *link)
 {
     local_info_t *local;
@@ -99,31 +68,11 @@
     local->p_dev = link;
     link->priv = local;
 
-    /*
-      General socket configuration defaults can go here.  In this
-      client, we assume very little, and rely on the CIS for almost
-      everything.  In most clients, many details (i.e., number, sizes,
-      and attributes of IO windows) are fixed by the nature of the
-      device, and can be hard-wired here.
-    */
-    link->resource[0]->end = 96;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
     return teles_cs_config(link);
 } /* teles_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void __devexit teles_detach(struct pcmcia_device *link)
 {
 	local_info_t *info = link->priv;
@@ -136,27 +85,17 @@
 	kfree(info);
 } /* teles_detach */
 
-/*======================================================================
-
-    teles_cs_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.
-
-======================================================================*/
-
-static int teles_cs_configcheck(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cf,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
-				void *priv_data)
+static int teles_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int j;
 
 	p_dev->io_lines = 5;
+	p_dev->resource[0]->end = 96;
+	p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
-	if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+	if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) {
 		printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
-		p_dev->resource[0]->start = cf->io.win[0].base;
 		if (!pcmcia_request_io(p_dev))
 			return 0;
 	} else {
@@ -186,21 +125,10 @@
     if (!link->irq)
         goto cs_failed;
 
-    i = pcmcia_request_configuration(link, &link->conf);
+    i = pcmcia_enable_device(link);
     if (i != 0)
       goto cs_failed;
 
-    /* Finally, report what we've done */
-    dev_info(&link->dev, "index 0x%02x:",
-	    link->conf.ConfigIndex);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-	    printk(", irq %d", link->irq);
-    if (link->resource[0])
-	printk(" & %pR", link->resource[0]);
-    if (link->resource[1])
-	printk(" & %pR", link->resource[1]);
-    printk("\n");
-
     icard.para[0] = link->irq;
     icard.para[1] = link->resource[0]->start;
     icard.protocol = protocol;
@@ -222,14 +150,6 @@
     return -ENODEV;
 } /* teles_cs_config */
 
-/*======================================================================
-
-    After a card is removed, teles_cs_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void teles_cs_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
@@ -273,9 +193,7 @@
 
 static struct pcmcia_driver teles_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "teles_cs",
-	},
+	.name		= "teles_cs",
 	.probe		= teles_probe,
 	.remove		= __devexit_p(teles_detach),
 	.id_table       = teles_ids,
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 51dc60d..c463162 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -14,7 +14,7 @@
 #include <linux/isdn.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include "isdn_common.h"
 #include "isdn_tty.h"
 #ifdef CONFIG_ISDN_AUDIO
@@ -28,6 +28,7 @@
 
 /* Prototypes */
 
+static DEFINE_MUTEX(modem_info_mutex);
 static int isdn_tty_edit_at(const char *, int, modem_info *);
 static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *);
 static void isdn_tty_modem_reset_regs(modem_info *, int);
@@ -1354,14 +1355,14 @@
 	if (tty->flags & (1 << TTY_IO_ERROR))
 		return -EIO;
 
-	lock_kernel();
+	mutex_lock(&modem_info_mutex);
 #ifdef ISDN_DEBUG_MODEM_IOCTL
 	printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
 #endif
 
 	control = info->mcr;
 	status = info->msr;
-	unlock_kernel();
+	mutex_unlock(&modem_info_mutex);
 	return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
 	    | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
 	    | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
@@ -1385,7 +1386,7 @@
 	printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear);
 #endif
 
-	lock_kernel();
+	mutex_lock(&modem_info_mutex);
 	if (set & TIOCM_RTS)
 		info->mcr |= UART_MCR_RTS;
 	if (set & TIOCM_DTR) {
@@ -1407,7 +1408,7 @@
 			isdn_tty_modem_hup(info, 1);
 		}
 	}
-	unlock_kernel();
+	mutex_unlock(&modem_info_mutex);
 	return 0;
 }
 
@@ -3515,7 +3516,7 @@
 {
 	atemu *m = &info->emu;
 	char *p;
-	char ds[40];
+	char ds[ISDN_MSNLEN];
 
 #ifdef ISDN_DEBUG_AT
 	printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd);
@@ -3594,7 +3595,7 @@
 						break;
 					case '3':
                                                 p++;
-                                                sprintf(ds, "\r\n%d", info->emu.charge);
+                                                snprintf(ds, sizeof(ds), "\r\n%d", info->emu.charge);
                                                 isdn_tty_at_cout(ds, info);
                                                 break;
 					default:;
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index 713ef2b..76d9e67 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -1237,6 +1237,7 @@
 			if (dsp->cmx_delay)
 				dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
 					& CMX_BUFF_MASK;
+			else
 				dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
 					& CMX_BUFF_MASK;
 		} else {
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
index 22f38e4..5b59796 100644
--- a/drivers/isdn/mISDN/l1oip_core.c
+++ b/drivers/isdn/mISDN/l1oip_core.c
@@ -972,7 +972,7 @@
 		if (debug & DEBUG_L1OIP_SOCKET)
 			printk(KERN_DEBUG "%s: got new ip address from user "
 				"space.\n", __func__);
-			l1oip_socket_open(hc);
+		l1oip_socket_open(hc);
 		break;
 	case MISDN_CTRL_UNSETPEER:
 		if (debug & DEBUG_L1OIP_SOCKET)
diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c
index b159bd5..a5b632e6 100644
--- a/drivers/isdn/mISDN/stack.c
+++ b/drivers/isdn/mISDN/stack.c
@@ -18,7 +18,6 @@
 #include <linux/slab.h>
 #include <linux/mISDNif.h>
 #include <linux/kthread.h>
-#include <linux/smp_lock.h>
 #include "core.h"
 
 static u_int	*debug;
@@ -205,13 +204,7 @@
 	struct mISDNstack *st = data;
 	int err = 0;
 
-#ifdef CONFIG_SMP
-	lock_kernel();
-#endif
 	sigfillset(&current->blocked);
-#ifdef CONFIG_SMP
-	unlock_kernel();
-#endif
 	if (*debug & DEBUG_MSG_THREAD)
 		printk(KERN_DEBUG "mISDNStackd %s started\n",
 		    dev_name(&st->dev->dev));
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c
index de43c8c..859c81e 100644
--- a/drivers/isdn/mISDN/timerdev.c
+++ b/drivers/isdn/mISDN/timerdev.c
@@ -267,6 +267,7 @@
 	.unlocked_ioctl	= mISDN_ioctl,
 	.open		= mISDN_open,
 	.release	= mISDN_close,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice mISDNtimer = {
diff --git a/drivers/isdn/pcbit/edss1.c b/drivers/isdn/pcbit/edss1.c
index d5920ae..80c9c16 100644
--- a/drivers/isdn/pcbit/edss1.c
+++ b/drivers/isdn/pcbit/edss1.c
@@ -33,7 +33,7 @@
 #include "callbacks.h"
 
 
-char * isdn_state_table[] = {
+const char * const isdn_state_table[] = {
   "Closed",
   "Call initiated",
   "Overlap sending",
diff --git a/drivers/isdn/pcbit/edss1.h b/drivers/isdn/pcbit/edss1.h
index 0b64f97..39f8346 100644
--- a/drivers/isdn/pcbit/edss1.h
+++ b/drivers/isdn/pcbit/edss1.h
@@ -90,7 +90,7 @@
 	unsigned long timeout;          /* in seconds */
 };
 
-extern char * isdn_state_table[];
+extern const char * const isdn_state_table[];
 
 void pcbit_fsm_event(struct pcbit_dev *, struct pcbit_chan *,
 		     unsigned short event, struct callb_data *);
diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c
index 485be8b..f0225bc 100644
--- a/drivers/isdn/sc/interrupt.c
+++ b/drivers/isdn/sc/interrupt.c
@@ -112,11 +112,19 @@
 			}
 			else if(callid>=0x0000 && callid<=0x7FFF)
 			{
+				int len;
+
 				pr_debug("%s: Got Incoming Call\n",
 						sc_adapter[card]->devicename);
-				strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4]));
-				strcpy(setup.eazmsn,
-					sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn);
+				len = strlcpy(setup.phone, &(rcvmsg.msg_data.byte_array[4]),
+						sizeof(setup.phone));
+				if (len >= sizeof(setup.phone))
+					continue;
+				len = strlcpy(setup.eazmsn,
+						sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
+						sizeof(setup.eazmsn));
+				if (len >= sizeof(setup.eazmsn))
+					continue;
 				setup.si1 = 7;
 				setup.si2 = 0;
 				setup.plan = 0;
@@ -176,7 +184,9 @@
 		 * Handle a GetMyNumber Rsp
 		 */
 		if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){
-			strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array);
+			strlcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
+				rcvmsg.msg_data.byte_array,
+				sizeof(rcvmsg.msg_data.byte_array));
 			continue;
 		}
 			
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index e411262..cc2a88d 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -304,13 +304,22 @@
 
 config LEDS_NS2
 	tristate "LED support for Network Space v2 GPIO LEDs"
-	depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2
+	depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2 || D2NET_V2
 	default y
 	help
 	  This option enable support for the dual-GPIO LED found on the
 	  Network Space v2 board (and parents). This include Internet Space v2,
 	  Network Space (Max) v2 and d2 Network v2 boards.
 
+config LEDS_NETXBIG
+	tristate "LED support for Big Network series LEDs"
+	depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2
+	default y
+	help
+	  This option enable support for LEDs found on the LaCie 2Big
+	  and 5Big Network v2 boards. The LEDs are wired to a CPLD and are
+	  controlled through a GPIO extension bus.
+
 config LEDS_TRIGGERS
 	bool "LED Trigger support"
 	help
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 7d6b958..9c96db4 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -38,6 +38,7 @@
 obj-$(CONFIG_LEDS_DELL_NETBOOKS)	+= dell-led.o
 obj-$(CONFIG_LEDS_MC13783)		+= leds-mc13783.o
 obj-$(CONFIG_LEDS_NS2)			+= leds-ns2.o
+obj-$(CONFIG_LEDS_NETXBIG)		+= leds-netxbig.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
new file mode 100644
index 0000000..f2e51c1
--- /dev/null
+++ b/drivers/leds/leds-netxbig.c
@@ -0,0 +1,449 @@
+/*
+ * leds-netxbig.c - Driver for the 2Big and 5Big Network series LEDs
+ *
+ * Copyright (C) 2010 LaCie
+ *
+ * Author: Simon Guinot <sguinot@lacie.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/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <mach/leds-netxbig.h>
+
+/*
+ * GPIO extension bus.
+ */
+
+static DEFINE_SPINLOCK(gpio_ext_lock);
+
+static void gpio_ext_set_addr(struct netxbig_gpio_ext *gpio_ext, int addr)
+{
+	int pin;
+
+	for (pin = 0; pin < gpio_ext->num_addr; pin++)
+		gpio_set_value(gpio_ext->addr[pin], (addr >> pin) & 1);
+}
+
+static void gpio_ext_set_data(struct netxbig_gpio_ext *gpio_ext, int data)
+{
+	int pin;
+
+	for (pin = 0; pin < gpio_ext->num_data; pin++)
+		gpio_set_value(gpio_ext->data[pin], (data >> pin) & 1);
+}
+
+static void gpio_ext_enable_select(struct netxbig_gpio_ext *gpio_ext)
+{
+	/* Enable select is done on the raising edge. */
+	gpio_set_value(gpio_ext->enable, 0);
+	gpio_set_value(gpio_ext->enable, 1);
+}
+
+static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext,
+			       int addr, int value)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_ext_lock, flags);
+	gpio_ext_set_addr(gpio_ext, addr);
+	gpio_ext_set_data(gpio_ext, value);
+	gpio_ext_enable_select(gpio_ext);
+	spin_unlock_irqrestore(&gpio_ext_lock, flags);
+}
+
+static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
+{
+	int err;
+	int i;
+
+	if (unlikely(!gpio_ext))
+		return -EINVAL;
+
+	/* Configure address GPIOs. */
+	for (i = 0; i < gpio_ext->num_addr; i++) {
+		err = gpio_request(gpio_ext->addr[i], "GPIO extension addr");
+		if (err)
+			goto err_free_addr;
+		err = gpio_direction_output(gpio_ext->addr[i], 0);
+		if (err) {
+			gpio_free(gpio_ext->addr[i]);
+			goto err_free_addr;
+		}
+	}
+	/* Configure data GPIOs. */
+	for (i = 0; i < gpio_ext->num_data; i++) {
+		err = gpio_request(gpio_ext->data[i], "GPIO extension data");
+		if (err)
+			goto err_free_data;
+		err = gpio_direction_output(gpio_ext->data[i], 0);
+		if (err) {
+			gpio_free(gpio_ext->data[i]);
+			goto err_free_data;
+		}
+	}
+	/* Configure "enable select" GPIO. */
+	err = gpio_request(gpio_ext->enable, "GPIO extension enable");
+	if (err)
+		goto err_free_data;
+	err = gpio_direction_output(gpio_ext->enable, 0);
+	if (err) {
+		gpio_free(gpio_ext->enable);
+		goto err_free_data;
+	}
+
+	return 0;
+
+err_free_data:
+	for (i = i - 1; i >= 0; i--)
+		gpio_free(gpio_ext->data[i]);
+	i = gpio_ext->num_addr;
+err_free_addr:
+	for (i = i - 1; i >= 0; i--)
+		gpio_free(gpio_ext->addr[i]);
+
+	return err;
+}
+
+static void __devexit gpio_ext_free(struct netxbig_gpio_ext *gpio_ext)
+{
+	int i;
+
+	gpio_free(gpio_ext->enable);
+	for (i = gpio_ext->num_addr - 1; i >= 0; i--)
+		gpio_free(gpio_ext->addr[i]);
+	for (i = gpio_ext->num_data - 1; i >= 0; i--)
+		gpio_free(gpio_ext->data[i]);
+}
+
+/*
+ * Class LED driver.
+ */
+
+struct netxbig_led_data {
+	struct netxbig_gpio_ext	*gpio_ext;
+	struct led_classdev	cdev;
+	int			mode_addr;
+	int			*mode_val;
+	int			bright_addr;
+	int			bright_max;
+	struct			netxbig_led_timer *timer;
+	int			num_timer;
+	enum netxbig_led_mode	mode;
+	int			sata;
+	spinlock_t		lock;
+};
+
+static int netxbig_led_get_timer_mode(enum netxbig_led_mode *mode,
+				      unsigned long delay_on,
+				      unsigned long delay_off,
+				      struct netxbig_led_timer *timer,
+				      int num_timer)
+{
+	int i;
+
+	for (i = 0; i < num_timer; i++) {
+		if (timer[i].delay_on == delay_on &&
+		    timer[i].delay_off == delay_off) {
+			*mode = timer[i].mode;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static int netxbig_led_blink_set(struct led_classdev *led_cdev,
+				 unsigned long *delay_on,
+				 unsigned long *delay_off)
+{
+	struct netxbig_led_data *led_dat =
+		container_of(led_cdev, struct netxbig_led_data, cdev);
+	enum netxbig_led_mode mode;
+	int mode_val;
+	int ret;
+
+	/* Look for a LED mode with the requested timer frequency. */
+	ret = netxbig_led_get_timer_mode(&mode, *delay_on, *delay_off,
+					 led_dat->timer, led_dat->num_timer);
+	if (ret < 0)
+		return ret;
+
+	mode_val = led_dat->mode_val[mode];
+	if (mode_val == NETXBIG_LED_INVALID_MODE)
+		return -EINVAL;
+
+	spin_lock_irq(&led_dat->lock);
+
+	gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val);
+	led_dat->mode = mode;
+
+	spin_unlock_irq(&led_dat->lock);
+
+	return 0;
+}
+
+static void netxbig_led_set(struct led_classdev *led_cdev,
+			    enum led_brightness value)
+{
+	struct netxbig_led_data *led_dat =
+		container_of(led_cdev, struct netxbig_led_data, cdev);
+	enum netxbig_led_mode mode;
+	int mode_val, bright_val;
+	int set_brightness = 1;
+	unsigned long flags;
+
+	spin_lock_irqsave(&led_dat->lock, flags);
+
+	if (value == LED_OFF) {
+		mode = NETXBIG_LED_OFF;
+		set_brightness = 0;
+	} else {
+		if (led_dat->sata)
+			mode = NETXBIG_LED_SATA;
+		else if (led_dat->mode == NETXBIG_LED_OFF)
+			mode = NETXBIG_LED_ON;
+		else /* Keep 'timer' mode. */
+			mode = led_dat->mode;
+	}
+	mode_val = led_dat->mode_val[mode];
+
+	gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val);
+	led_dat->mode = mode;
+	/*
+	 * Note that the brightness register is shared between all the
+	 * SATA LEDs. So, change the brightness setting for a single
+	 * SATA LED will affect all the others.
+	 */
+	if (set_brightness) {
+		bright_val = DIV_ROUND_UP(value * led_dat->bright_max,
+					  LED_FULL);
+		gpio_ext_set_value(led_dat->gpio_ext,
+				   led_dat->bright_addr, bright_val);
+	}
+
+	spin_unlock_irqrestore(&led_dat->lock, flags);
+}
+
+static ssize_t netxbig_led_sata_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buff, size_t count)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct netxbig_led_data *led_dat =
+		container_of(led_cdev, struct netxbig_led_data, cdev);
+	unsigned long enable;
+	enum netxbig_led_mode mode;
+	int mode_val;
+	int ret;
+
+	ret = strict_strtoul(buff, 10, &enable);
+	if (ret < 0)
+		return ret;
+
+	enable = !!enable;
+
+	spin_lock_irq(&led_dat->lock);
+
+	if (led_dat->sata == enable) {
+		ret = count;
+		goto exit_unlock;
+	}
+
+	if (led_dat->mode != NETXBIG_LED_ON &&
+	    led_dat->mode != NETXBIG_LED_SATA)
+		mode = led_dat->mode; /* Keep modes 'off' and 'timer'. */
+	else if (enable)
+		mode = NETXBIG_LED_SATA;
+	else
+		mode = NETXBIG_LED_ON;
+
+	mode_val = led_dat->mode_val[mode];
+	if (mode_val == NETXBIG_LED_INVALID_MODE) {
+		ret = -EINVAL;
+		goto exit_unlock;
+	}
+
+	gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val);
+	led_dat->mode = mode;
+	led_dat->sata = enable;
+
+	ret = count;
+
+exit_unlock:
+	spin_unlock_irq(&led_dat->lock);
+
+	return ret;
+}
+
+static ssize_t netxbig_led_sata_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct netxbig_led_data *led_dat =
+		container_of(led_cdev, struct netxbig_led_data, cdev);
+
+	return sprintf(buf, "%d\n", led_dat->sata);
+}
+
+static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store);
+
+static void __devexit delete_netxbig_led(struct netxbig_led_data *led_dat)
+{
+	if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE)
+		device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
+	led_classdev_unregister(&led_dat->cdev);
+}
+
+static int __devinit
+create_netxbig_led(struct platform_device *pdev,
+		   struct netxbig_led_data *led_dat,
+		   const struct netxbig_led *template)
+{
+	struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+	int ret;
+
+	spin_lock_init(&led_dat->lock);
+	led_dat->gpio_ext = pdata->gpio_ext;
+	led_dat->cdev.name = template->name;
+	led_dat->cdev.default_trigger = template->default_trigger;
+	led_dat->cdev.blink_set = netxbig_led_blink_set;
+	led_dat->cdev.brightness_set = netxbig_led_set;
+	/*
+	 * Because the GPIO extension bus don't allow to read registers
+	 * value, there is no way to probe the LED initial state.
+	 * So, the initial sysfs LED value for the "brightness" and "sata"
+	 * attributes are inconsistent.
+	 *
+	 * Note that the initial LED state can't be reconfigured.
+	 * The reason is that the LED behaviour must stay uniform during
+	 * the whole boot process (bootloader+linux).
+	 */
+	led_dat->sata = 0;
+	led_dat->cdev.brightness = LED_OFF;
+	led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+	led_dat->mode_addr = template->mode_addr;
+	led_dat->mode_val = template->mode_val;
+	led_dat->bright_addr = template->bright_addr;
+	led_dat->bright_max = (1 << pdata->gpio_ext->num_data) - 1;
+	led_dat->timer = pdata->timer;
+	led_dat->num_timer = pdata->num_timer;
+
+	ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * If available, expose the SATA activity blink capability through
+	 * a "sata" sysfs attribute.
+	 */
+	if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) {
+		ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
+		if (ret)
+			led_classdev_unregister(&led_dat->cdev);
+	}
+
+	return ret;
+}
+
+static int __devinit netxbig_led_probe(struct platform_device *pdev)
+{
+	struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+	struct netxbig_led_data *leds_data;
+	int i;
+	int ret;
+
+	if (!pdata)
+		return -EINVAL;
+
+	leds_data = kzalloc(sizeof(struct netxbig_led_data) * pdata->num_leds,
+			    GFP_KERNEL);
+	if (!leds_data)
+		return -ENOMEM;
+
+	ret = gpio_ext_init(pdata->gpio_ext);
+	if (ret < 0)
+		goto err_free_data;
+
+	for (i = 0; i < pdata->num_leds; i++) {
+		ret = create_netxbig_led(pdev, &leds_data[i], &pdata->leds[i]);
+		if (ret < 0)
+			goto err_free_leds;
+	}
+
+	platform_set_drvdata(pdev, leds_data);
+
+	return 0;
+
+err_free_leds:
+	for (i = i - 1; i >= 0; i--)
+		delete_netxbig_led(&leds_data[i]);
+
+	gpio_ext_free(pdata->gpio_ext);
+err_free_data:
+	kfree(leds_data);
+
+	return ret;
+}
+
+static int __devexit netxbig_led_remove(struct platform_device *pdev)
+{
+	struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+	struct netxbig_led_data *leds_data;
+	int i;
+
+	leds_data = platform_get_drvdata(pdev);
+
+	for (i = 0; i < pdata->num_leds; i++)
+		delete_netxbig_led(&leds_data[i]);
+
+	gpio_ext_free(pdata->gpio_ext);
+	kfree(leds_data);
+
+	return 0;
+}
+
+static struct platform_driver netxbig_led_driver = {
+	.probe		= netxbig_led_probe,
+	.remove		= __devexit_p(netxbig_led_remove),
+	.driver		= {
+		.name	= "leds-netxbig",
+		.owner	= THIS_MODULE,
+	},
+};
+MODULE_ALIAS("platform:leds-netxbig");
+
+static int __init netxbig_led_init(void)
+{
+	return platform_driver_register(&netxbig_led_driver);
+}
+
+static void __exit netxbig_led_exit(void)
+{
+	platform_driver_unregister(&netxbig_led_driver);
+}
+
+module_init(netxbig_led_init);
+module_exit(netxbig_led_exit);
+
+MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
+MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index 74dce4b..f77d48d 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -81,7 +81,7 @@
 	int cmd_level;
 	int slow_level;
 
-	read_lock(&led_dat->rw_lock);
+	read_lock_irq(&led_dat->rw_lock);
 
 	cmd_level = gpio_get_value(led_dat->cmd);
 	slow_level = gpio_get_value(led_dat->slow);
@@ -95,7 +95,7 @@
 		}
 	}
 
-	read_unlock(&led_dat->rw_lock);
+	read_unlock_irq(&led_dat->rw_lock);
 
 	return ret;
 }
@@ -104,8 +104,9 @@
 			     enum ns2_led_modes mode)
 {
 	int i;
+	unsigned long flags;
 
-	write_lock(&led_dat->rw_lock);
+	write_lock_irqsave(&led_dat->rw_lock, flags);
 
 	for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) {
 		if (mode == ns2_led_modval[i].mode) {
@@ -116,7 +117,7 @@
 		}
 	}
 
-	write_unlock(&led_dat->rw_lock);
+	write_unlock_irqrestore(&led_dat->rw_lock, flags);
 }
 
 static void ns2_led_set(struct led_classdev *led_cdev,
@@ -140,10 +141,12 @@
 				  struct device_attribute *attr,
 				  const char *buff, size_t count)
 {
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct ns2_led_data *led_dat =
+		container_of(led_cdev, struct ns2_led_data, cdev);
 	int ret;
 	unsigned long enable;
 	enum ns2_led_modes mode;
-	struct ns2_led_data *led_dat = dev_get_drvdata(dev);
 
 	ret = strict_strtoul(buff, 10, &enable);
 	if (ret < 0)
@@ -171,7 +174,9 @@
 static ssize_t ns2_led_sata_show(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
-	struct ns2_led_data *led_dat = dev_get_drvdata(dev);
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct ns2_led_data *led_dat =
+		container_of(led_cdev, struct ns2_led_data, cdev);
 
 	return sprintf(buf, "%d\n", led_dat->sata);
 }
@@ -233,7 +238,6 @@
 	if (ret < 0)
 		goto err_free_slow;
 
-	dev_set_drvdata(led_dat->cdev.dev, led_dat);
 	ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
 	if (ret < 0)
 		goto err_free_cdev;
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 85b714d..3c781cd 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -514,6 +514,7 @@
 	.release = close,
 	.write	 = write,
 	.read	 = read,
+	.llseek  = default_llseek,
 };
 
 /*
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 1c4ee6e..75049e7 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -24,7 +24,6 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/pmu.h>
@@ -55,6 +54,7 @@
 extern struct adb_driver via_pmu_driver;
 extern struct adb_driver macio_adb_driver;
 
+static DEFINE_MUTEX(adb_mutex);
 static struct adb_driver *adb_driver_list[] = {
 #ifdef CONFIG_ADB_MACII
 	&via_macii_driver,
@@ -83,7 +83,7 @@
 BLOCKING_NOTIFIER_HEAD(adb_client_list);
 static int adb_got_sleep;
 static int adb_inited;
-static DECLARE_MUTEX(adb_probe_mutex);
+static DEFINE_SEMAPHORE(adb_probe_mutex);
 static int sleepy_trackpad;
 static int autopoll_devs;
 int __adb_probe_sync;
@@ -647,7 +647,7 @@
 	struct adbdev_state *state;
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&adb_mutex);
 	if (iminor(inode) > 0 || adb_controller == NULL) {
 		ret = -ENXIO;
 		goto out;
@@ -665,7 +665,7 @@
 	state->inuse = 1;
 
 out:
-	unlock_kernel();
+	mutex_unlock(&adb_mutex);
 	return ret;
 }
 
@@ -674,7 +674,7 @@
 	struct adbdev_state *state = file->private_data;
 	unsigned long flags;
 
-	lock_kernel();
+	mutex_lock(&adb_mutex);
 	if (state) {
 		file->private_data = NULL;
 		spin_lock_irqsave(&state->lock, flags);
@@ -687,7 +687,7 @@
 			spin_unlock_irqrestore(&state->lock, flags);
 		}
 	}
-	unlock_kernel();
+	mutex_unlock(&adb_mutex);
 	return 0;
 }
 
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index a3d25da..1a57e88 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -137,6 +137,7 @@
 	.write		= anslcd_write,
 	.unlocked_ioctl	= anslcd_ioctl,
 	.open		= anslcd_open,
+	.llseek		= default_llseek,
 };
 
 static struct miscdevice anslcd_dev = {
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index e58c3d3..290cb32 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -19,7 +19,6 @@
  *    the userland interface
  */
 
-#include <linux/smp_lock.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
@@ -97,6 +96,7 @@
  * I don't think there will ever be more than one SMU, so
  * for now, just hard code that
  */
+static DEFINE_MUTEX(smu_mutex);
 static struct smu_device	*smu;
 static DEFINE_MUTEX(smu_part_access);
 static int smu_irq_inited;
@@ -1095,12 +1095,12 @@
 	pp->mode = smu_file_commands;
 	init_waitqueue_head(&pp->wait);
 
-	lock_kernel();
+	mutex_lock(&smu_mutex);
 	spin_lock_irqsave(&smu_clist_lock, flags);
 	list_add(&pp->list, &smu_clist);
 	spin_unlock_irqrestore(&smu_clist_lock, flags);
 	file->private_data = pp;
-	unlock_kernel();
+	mutex_unlock(&smu_mutex);
 
 	return 0;
 }
diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c
index d242976..19c3718 100644
--- a/drivers/macintosh/via-pmu-led.c
+++ b/drivers/macintosh/via-pmu-led.c
@@ -92,8 +92,10 @@
 	if (dt == NULL)
 		return -ENODEV;
 	model = of_get_property(dt, "model", NULL);
-	if (model == NULL)
+	if (model == NULL) {
+		of_node_put(dt);
 		return -ENODEV;
+	}
 	if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
 	    strncmp(model, "iBook", strlen("iBook")) != 0 &&
 	    strcmp(model, "PowerMac7,2") != 0 &&
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 2d17e76..cd29c82 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -18,7 +18,7 @@
  *
  */
 #include <stdarg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -73,6 +73,7 @@
 /* How many iterations between battery polls */
 #define BATTERY_POLLING_COUNT	2
 
+static DEFINE_MUTEX(pmu_info_proc_mutex);
 static volatile unsigned char __iomem *via;
 
 /* VIA registers - spaced 0x200 bytes apart */
@@ -2078,7 +2079,7 @@
 	pp->rb_get = pp->rb_put = 0;
 	spin_lock_init(&pp->lock);
 	init_waitqueue_head(&pp->wait);
-	lock_kernel();
+	mutex_lock(&pmu_info_proc_mutex);
 	spin_lock_irqsave(&all_pvt_lock, flags);
 #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
 	pp->backlight_locker = 0;
@@ -2086,7 +2087,7 @@
 	list_add(&pp->list, &all_pmu_pvt);
 	spin_unlock_irqrestore(&all_pvt_lock, flags);
 	file->private_data = pp;
-	unlock_kernel();
+	mutex_unlock(&pmu_info_proc_mutex);
 	return 0;
 }
 
@@ -2343,9 +2344,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pmu_info_proc_mutex);
 	ret = pmu_ioctl(filp, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&pmu_info_proc_mutex);
 
 	return ret;
 }
@@ -2398,6 +2399,7 @@
 #endif
 	.open		= pmu_open,
 	.release	= pmu_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice pmu_device = {
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index ed4900a..e4fb58d 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1000,10 +1000,11 @@
 				page = bitmap->sb_page;
 				offset = sizeof(bitmap_super_t);
 				if (!file)
-					read_sb_page(bitmap->mddev,
-						     bitmap->mddev->bitmap_info.offset,
-						     page,
-						     index, count);
+					page = read_sb_page(
+						bitmap->mddev,
+						bitmap->mddev->bitmap_info.offset,
+						page,
+						index, count);
 			} else if (file) {
 				page = read_page(file, index, bitmap, count);
 				offset = 0;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 368e8e9..d5b0e4c 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1278,7 +1278,7 @@
 	struct dm_crypt_io *io;
 	struct crypt_config *cc;
 
-	if (unlikely(bio_empty_barrier(bio))) {
+	if (bio->bi_rw & REQ_FLUSH) {
 		cc = ti->private;
 		bio->bi_bdev = cc->dev->bdev;
 		return DM_MAPIO_REMAPPED;
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 0590c75..136d4f7 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -31,7 +31,6 @@
  */
 struct io {
 	unsigned long error_bits;
-	unsigned long eopnotsupp_bits;
 	atomic_t count;
 	struct task_struct *sleeper;
 	struct dm_io_client *client;
@@ -130,11 +129,8 @@
  *---------------------------------------------------------------*/
 static void dec_count(struct io *io, unsigned int region, int error)
 {
-	if (error) {
+	if (error)
 		set_bit(region, &io->error_bits);
-		if (error == -EOPNOTSUPP)
-			set_bit(region, &io->eopnotsupp_bits);
-	}
 
 	if (atomic_dec_and_test(&io->count)) {
 		if (io->sleeper)
@@ -310,8 +306,8 @@
 	sector_t remaining = where->count;
 
 	/*
-	 * where->count may be zero if rw holds a write barrier and we
-	 * need to send a zero-sized barrier.
+	 * where->count may be zero if rw holds a flush and we need to
+	 * send a zero-sized flush.
 	 */
 	do {
 		/*
@@ -364,7 +360,7 @@
 	 */
 	for (i = 0; i < num_regions; i++) {
 		*dp = old_pages;
-		if (where[i].count || (rw & REQ_HARDBARRIER))
+		if (where[i].count || (rw & REQ_FLUSH))
 			do_region(rw, i, where + i, dp, io);
 	}
 
@@ -393,9 +389,7 @@
 		return -EIO;
 	}
 
-retry:
 	io->error_bits = 0;
-	io->eopnotsupp_bits = 0;
 	atomic_set(&io->count, 1); /* see dispatch_io() */
 	io->sleeper = current;
 	io->client = client;
@@ -412,11 +406,6 @@
 	}
 	set_current_state(TASK_RUNNING);
 
-	if (io->eopnotsupp_bits && (rw & REQ_HARDBARRIER)) {
-		rw &= ~REQ_HARDBARRIER;
-		goto retry;
-	}
-
 	if (error_bits)
 		*error_bits = io->error_bits;
 
@@ -437,7 +426,6 @@
 
 	io = mempool_alloc(client->pool, GFP_NOIO);
 	io->error_bits = 0;
-	io->eopnotsupp_bits = 0;
 	atomic_set(&io->count, 1); /* see dispatch_io() */
 	io->sleeper = NULL;
 	io->client = client;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 3e39193..4b54618 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1596,6 +1596,7 @@
 	.unlocked_ioctl	 = dm_ctl_ioctl,
 	.compat_ioctl = dm_compat_ctl_ioctl,
 	.owner	 = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice _dm_misc = {
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 5a08be0..33420e6 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -300,7 +300,7 @@
 		.count = 0,
 	};
 
-	lc->io_req.bi_rw = WRITE_BARRIER;
+	lc->io_req.bi_rw = WRITE_FLUSH;
 
 	return dm_io(&lc->io_req, 1, &null_location, NULL);
 }
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 7c081bc..19a59b0 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -259,7 +259,7 @@
 	struct dm_io_region io[ms->nr_mirrors];
 	struct mirror *m;
 	struct dm_io_request io_req = {
-		.bi_rw = WRITE_BARRIER,
+		.bi_rw = WRITE_FLUSH,
 		.mem.type = DM_IO_KMEM,
 		.mem.ptr.bvec = NULL,
 		.client = ms->io_client,
@@ -629,7 +629,7 @@
 	struct dm_io_region io[ms->nr_mirrors], *dest = io;
 	struct mirror *m;
 	struct dm_io_request io_req = {
-		.bi_rw = WRITE | (bio->bi_rw & WRITE_BARRIER),
+		.bi_rw = WRITE | (bio->bi_rw & WRITE_FLUSH_FUA),
 		.mem.type = DM_IO_BVEC,
 		.mem.ptr.bvec = bio->bi_io_vec + bio->bi_idx,
 		.notify.fn = write_callback,
@@ -670,7 +670,7 @@
 	bio_list_init(&requeue);
 
 	while ((bio = bio_list_pop(writes))) {
-		if (unlikely(bio_empty_barrier(bio))) {
+		if (bio->bi_rw & REQ_FLUSH) {
 			bio_list_add(&sync, bio);
 			continue;
 		}
@@ -1203,7 +1203,7 @@
 	 * We need to dec pending if this was a write.
 	 */
 	if (rw == WRITE) {
-		if (likely(!bio_empty_barrier(bio)))
+		if (!(bio->bi_rw & REQ_FLUSH))
 			dm_rh_dec(ms->rh, map_context->ll);
 		return error;
 	}
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
index bd5c58b..dad011a 100644
--- a/drivers/md/dm-region-hash.c
+++ b/drivers/md/dm-region-hash.c
@@ -81,9 +81,9 @@
 	struct list_head failed_recovered_regions;
 
 	/*
-	 * If there was a barrier failure no regions can be marked clean.
+	 * If there was a flush failure no regions can be marked clean.
 	 */
-	int barrier_failure;
+	int flush_failure;
 
 	void *context;
 	sector_t target_begin;
@@ -217,7 +217,7 @@
 	INIT_LIST_HEAD(&rh->quiesced_regions);
 	INIT_LIST_HEAD(&rh->recovered_regions);
 	INIT_LIST_HEAD(&rh->failed_recovered_regions);
-	rh->barrier_failure = 0;
+	rh->flush_failure = 0;
 
 	rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
 						      sizeof(struct dm_region));
@@ -399,8 +399,8 @@
 	region_t region = dm_rh_bio_to_region(rh, bio);
 	int recovering = 0;
 
-	if (bio_empty_barrier(bio)) {
-		rh->barrier_failure = 1;
+	if (bio->bi_rw & REQ_FLUSH) {
+		rh->flush_failure = 1;
 		return;
 	}
 
@@ -524,7 +524,7 @@
 	struct bio *bio;
 
 	for (bio = bios->head; bio; bio = bio->bi_next) {
-		if (bio_empty_barrier(bio))
+		if (bio->bi_rw & REQ_FLUSH)
 			continue;
 		rh_inc(rh, dm_rh_bio_to_region(rh, bio));
 	}
@@ -555,9 +555,9 @@
 		 */
 
 		/* do nothing for DM_RH_NOSYNC */
-		if (unlikely(rh->barrier_failure)) {
+		if (unlikely(rh->flush_failure)) {
 			/*
-			 * If a write barrier failed some time ago, we
+			 * If a write flush failed some time ago, we
 			 * don't know whether or not this write made it
 			 * to the disk, so we must resync the device.
 			 */
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index cc2bdb8..0b61792 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -687,7 +687,7 @@
 	/*
 	 * Commit exceptions to disk.
 	 */
-	if (ps->valid && area_io(ps, WRITE_BARRIER))
+	if (ps->valid && area_io(ps, WRITE_FLUSH_FUA))
 		ps->valid = 0;
 
 	/*
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 5974d30..53cf79d 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -706,8 +706,6 @@
 	return 0;
 }
 
-#define min_not_zero(l, r) (((l) == 0) ? (r) : (((r) == 0) ? (l) : min(l, r)))
-
 /*
  * Return a minimum chunk size of all snapshots that have the specified origin.
  * Return zero if the origin has no snapshots.
@@ -1587,7 +1585,7 @@
 	chunk_t chunk;
 	struct dm_snap_pending_exception *pe = NULL;
 
-	if (unlikely(bio_empty_barrier(bio))) {
+	if (bio->bi_rw & REQ_FLUSH) {
 		bio->bi_bdev = s->cow->bdev;
 		return DM_MAPIO_REMAPPED;
 	}
@@ -1691,7 +1689,7 @@
 	int r = DM_MAPIO_REMAPPED;
 	chunk_t chunk;
 
-	if (unlikely(bio_empty_barrier(bio))) {
+	if (bio->bi_rw & REQ_FLUSH) {
 		if (!map_context->target_request_nr)
 			bio->bi_bdev = s->origin->bdev;
 		else
@@ -2135,7 +2133,7 @@
 	struct dm_dev *dev = ti->private;
 	bio->bi_bdev = dev->bdev;
 
-	if (unlikely(bio_empty_barrier(bio)))
+	if (bio->bi_rw & REQ_FLUSH)
 		return DM_MAPIO_REMAPPED;
 
 	/* Only tell snapshots if this is a write */
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index c297f6da..f0371b4 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -271,7 +271,7 @@
 	uint32_t stripe;
 	unsigned target_request_nr;
 
-	if (unlikely(bio_empty_barrier(bio))) {
+	if (bio->bi_rw & REQ_FLUSH) {
 		target_request_nr = map_context->target_request_nr;
 		BUG_ON(target_request_nr >= sc->stripes);
 		bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index f9fc07d..90267f8 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -486,11 +486,6 @@
 	return 0;
 }
 
-/*
- * Returns the minimum that is _not_ zero, unless both are zero.
- */
-#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
-
 int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
 			 sector_t start, sector_t len, void *data)
 {
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index ac384b2..7cb1352 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -15,7 +15,6 @@
 #include <linux/blkpg.h>
 #include <linux/bio.h>
 #include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
 #include <linux/mempool.h>
 #include <linux/slab.h>
 #include <linux/idr.h>
@@ -33,6 +32,7 @@
 #define DM_COOKIE_ENV_VAR_NAME "DM_COOKIE"
 #define DM_COOKIE_LENGTH 24
 
+static DEFINE_MUTEX(dm_mutex);
 static const char *_name = DM_NAME;
 
 static unsigned int major = 0;
@@ -110,7 +110,6 @@
 #define DMF_FREEING 3
 #define DMF_DELETING 4
 #define DMF_NOFLUSH_SUSPENDING 5
-#define DMF_QUEUE_IO_TO_THREAD 6
 
 /*
  * Work processed by per-device workqueue.
@@ -144,24 +143,9 @@
 	spinlock_t deferred_lock;
 
 	/*
-	 * An error from the barrier request currently being processed.
-	 */
-	int barrier_error;
-
-	/*
-	 * Protect barrier_error from concurrent endio processing
-	 * in request-based dm.
-	 */
-	spinlock_t barrier_error_lock;
-
-	/*
-	 * Processing queue (flush/barriers)
+	 * Processing queue (flush)
 	 */
 	struct workqueue_struct *wq;
-	struct work_struct barrier_work;
-
-	/* A pointer to the currently processing pre/post flush request */
-	struct request *flush_request;
 
 	/*
 	 * The current mapping.
@@ -200,8 +184,8 @@
 	/* sysfs handle */
 	struct kobject kobj;
 
-	/* zero-length barrier that will be cloned and submitted to targets */
-	struct bio barrier_bio;
+	/* zero-length flush that will be cloned and submitted to targets */
+	struct bio flush_bio;
 };
 
 /*
@@ -344,7 +328,7 @@
 {
 	struct mapped_device *md;
 
-	lock_kernel();
+	mutex_lock(&dm_mutex);
 	spin_lock(&_minor_lock);
 
 	md = bdev->bd_disk->private_data;
@@ -362,7 +346,7 @@
 
 out:
 	spin_unlock(&_minor_lock);
-	unlock_kernel();
+	mutex_unlock(&dm_mutex);
 
 	return md ? 0 : -ENXIO;
 }
@@ -371,10 +355,10 @@
 {
 	struct mapped_device *md = disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&dm_mutex);
 	atomic_dec(&md->open_count);
 	dm_put(md);
-	unlock_kernel();
+	mutex_unlock(&dm_mutex);
 
 	return 0;
 }
@@ -512,7 +496,7 @@
 
 	/*
 	 * After this is decremented the bio must not be touched if it is
-	 * a barrier.
+	 * a flush.
 	 */
 	dm_disk(md)->part0.in_flight[rw] = pending =
 		atomic_dec_return(&md->pending[rw]);
@@ -528,16 +512,12 @@
  */
 static void queue_io(struct mapped_device *md, struct bio *bio)
 {
-	down_write(&md->io_lock);
+	unsigned long flags;
 
-	spin_lock_irq(&md->deferred_lock);
+	spin_lock_irqsave(&md->deferred_lock, flags);
 	bio_list_add(&md->deferred, bio);
-	spin_unlock_irq(&md->deferred_lock);
-
-	if (!test_and_set_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags))
-		queue_work(md->wq, &md->work);
-
-	up_write(&md->io_lock);
+	spin_unlock_irqrestore(&md->deferred_lock, flags);
+	queue_work(md->wq, &md->work);
 }
 
 /*
@@ -625,11 +605,9 @@
 			 * Target requested pushing back the I/O.
 			 */
 			spin_lock_irqsave(&md->deferred_lock, flags);
-			if (__noflush_suspending(md)) {
-				if (!(io->bio->bi_rw & REQ_HARDBARRIER))
-					bio_list_add_head(&md->deferred,
-							  io->bio);
-			} else
+			if (__noflush_suspending(md))
+				bio_list_add_head(&md->deferred, io->bio);
+			else
 				/* noflush suspend was interrupted. */
 				io->error = -EIO;
 			spin_unlock_irqrestore(&md->deferred_lock, flags);
@@ -637,32 +615,23 @@
 
 		io_error = io->error;
 		bio = io->bio;
+		end_io_acct(io);
+		free_io(md, io);
 
-		if (bio->bi_rw & REQ_HARDBARRIER) {
+		if (io_error == DM_ENDIO_REQUEUE)
+			return;
+
+		if ((bio->bi_rw & REQ_FLUSH) && bio->bi_size) {
 			/*
-			 * There can be just one barrier request so we use
-			 * a per-device variable for error reporting.
-			 * Note that you can't touch the bio after end_io_acct
-			 *
-			 * We ignore -EOPNOTSUPP for empty flush reported by
-			 * underlying devices. We assume that if the device
-			 * doesn't support empty barriers, it doesn't need
-			 * cache flushing commands.
+			 * Preflush done for flush with data, reissue
+			 * without REQ_FLUSH.
 			 */
-			if (!md->barrier_error &&
-			    !(bio_empty_barrier(bio) && io_error == -EOPNOTSUPP))
-				md->barrier_error = io_error;
-			end_io_acct(io);
-			free_io(md, io);
+			bio->bi_rw &= ~REQ_FLUSH;
+			queue_io(md, bio);
 		} else {
-			end_io_acct(io);
-			free_io(md, io);
-
-			if (io_error != DM_ENDIO_REQUEUE) {
-				trace_block_bio_complete(md->queue, bio);
-
-				bio_endio(bio, io_error);
-			}
+			/* done with normal IO or empty flush */
+			trace_block_bio_complete(md->queue, bio);
+			bio_endio(bio, io_error);
 		}
 	}
 }
@@ -755,23 +724,6 @@
 	blk_update_request(tio->orig, 0, nr_bytes);
 }
 
-static void store_barrier_error(struct mapped_device *md, int error)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&md->barrier_error_lock, flags);
-	/*
-	 * Basically, the first error is taken, but:
-	 *   -EOPNOTSUPP supersedes any I/O error.
-	 *   Requeue request supersedes any I/O error but -EOPNOTSUPP.
-	 */
-	if (!md->barrier_error || error == -EOPNOTSUPP ||
-	    (md->barrier_error != -EOPNOTSUPP &&
-	     error == DM_ENDIO_REQUEUE))
-		md->barrier_error = error;
-	spin_unlock_irqrestore(&md->barrier_error_lock, flags);
-}
-
 /*
  * Don't touch any member of the md after calling this function because
  * the md may be freed in dm_put() at the end of this function.
@@ -809,13 +761,11 @@
 static void dm_end_request(struct request *clone, int error)
 {
 	int rw = rq_data_dir(clone);
-	int run_queue = 1;
-	bool is_barrier = clone->cmd_flags & REQ_HARDBARRIER;
 	struct dm_rq_target_io *tio = clone->end_io_data;
 	struct mapped_device *md = tio->md;
 	struct request *rq = tio->orig;
 
-	if (rq->cmd_type == REQ_TYPE_BLOCK_PC && !is_barrier) {
+	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
 		rq->errors = clone->errors;
 		rq->resid_len = clone->resid_len;
 
@@ -829,15 +779,8 @@
 	}
 
 	free_rq_clone(clone);
-
-	if (unlikely(is_barrier)) {
-		if (unlikely(error))
-			store_barrier_error(md, error);
-		run_queue = 0;
-	} else
-		blk_end_request_all(rq, error);
-
-	rq_completed(md, rw, run_queue);
+	blk_end_request_all(rq, error);
+	rq_completed(md, rw, true);
 }
 
 static void dm_unprep_request(struct request *rq)
@@ -862,16 +805,6 @@
 	struct request_queue *q = rq->q;
 	unsigned long flags;
 
-	if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) {
-		/*
-		 * Barrier clones share an original request.
-		 * Leave it to dm_end_request(), which handles this special
-		 * case.
-		 */
-		dm_end_request(clone, DM_ENDIO_REQUEUE);
-		return;
-	}
-
 	dm_unprep_request(rq);
 
 	spin_lock_irqsave(q->queue_lock, flags);
@@ -961,19 +894,6 @@
 	struct dm_rq_target_io *tio = clone->end_io_data;
 	struct request *rq = tio->orig;
 
-	if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) {
-		/*
-		 * Barrier clones share an original request.  So can't use
-		 * softirq_done with the original.
-		 * Pass the clone to dm_done() directly in this special case.
-		 * It is safe (even if clone->q->queue_lock is held here)
-		 * because there is no I/O dispatching during the completion
-		 * of barrier clone.
-		 */
-		dm_done(clone, error, true);
-		return;
-	}
-
 	tio->error = error;
 	rq->completion_data = clone;
 	blk_complete_request(rq);
@@ -990,17 +910,6 @@
 	struct dm_rq_target_io *tio = clone->end_io_data;
 	struct request *rq = tio->orig;
 
-	if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) {
-		/*
-		 * Barrier clones share an original request.
-		 * Leave it to dm_end_request(), which handles this special
-		 * case.
-		 */
-		BUG_ON(error > 0);
-		dm_end_request(clone, error);
-		return;
-	}
-
 	rq->cmd_flags |= REQ_FAILED;
 	dm_complete_request(clone, error);
 }
@@ -1119,7 +1028,7 @@
 }
 
 /*
- * Creates a little bio that is just does part of a bvec.
+ * Creates a little bio that just does part of a bvec.
  */
 static struct bio *split_bvec(struct bio *bio, sector_t sector,
 			      unsigned short idx, unsigned int offset,
@@ -1134,7 +1043,7 @@
 
 	clone->bi_sector = sector;
 	clone->bi_bdev = bio->bi_bdev;
-	clone->bi_rw = bio->bi_rw & ~REQ_HARDBARRIER;
+	clone->bi_rw = bio->bi_rw;
 	clone->bi_vcnt = 1;
 	clone->bi_size = to_bytes(len);
 	clone->bi_io_vec->bv_offset = offset;
@@ -1161,7 +1070,6 @@
 
 	clone = bio_alloc_bioset(GFP_NOIO, bio->bi_max_vecs, bs);
 	__bio_clone(clone, bio);
-	clone->bi_rw &= ~REQ_HARDBARRIER;
 	clone->bi_destructor = dm_bio_destructor;
 	clone->bi_sector = sector;
 	clone->bi_idx = idx;
@@ -1225,16 +1133,15 @@
 		__issue_target_request(ci, ti, request_nr, len);
 }
 
-static int __clone_and_map_empty_barrier(struct clone_info *ci)
+static int __clone_and_map_empty_flush(struct clone_info *ci)
 {
 	unsigned target_nr = 0;
 	struct dm_target *ti;
 
+	BUG_ON(bio_has_data(ci->bio));
 	while ((ti = dm_table_get_target(ci->map, target_nr++)))
 		__issue_target_requests(ci, ti, ti->num_flush_requests, 0);
 
-	ci->sector_count = 0;
-
 	return 0;
 }
 
@@ -1289,9 +1196,6 @@
 	sector_t len = 0, max;
 	struct dm_target_io *tio;
 
-	if (unlikely(bio_empty_barrier(bio)))
-		return __clone_and_map_empty_barrier(ci);
-
 	if (unlikely(bio->bi_rw & REQ_DISCARD))
 		return __clone_and_map_discard(ci);
 
@@ -1383,16 +1287,11 @@
 
 	ci.map = dm_get_live_table(md);
 	if (unlikely(!ci.map)) {
-		if (!(bio->bi_rw & REQ_HARDBARRIER))
-			bio_io_error(bio);
-		else
-			if (!md->barrier_error)
-				md->barrier_error = -EIO;
+		bio_io_error(bio);
 		return;
 	}
 
 	ci.md = md;
-	ci.bio = bio;
 	ci.io = alloc_io(md);
 	ci.io->error = 0;
 	atomic_set(&ci.io->io_count, 1);
@@ -1400,14 +1299,20 @@
 	ci.io->md = md;
 	spin_lock_init(&ci.io->endio_lock);
 	ci.sector = bio->bi_sector;
-	ci.sector_count = bio_sectors(bio);
-	if (unlikely(bio_empty_barrier(bio)))
-		ci.sector_count = 1;
 	ci.idx = bio->bi_idx;
 
 	start_io_acct(ci.io);
-	while (ci.sector_count && !error)
-		error = __clone_and_map(&ci);
+	if (bio->bi_rw & REQ_FLUSH) {
+		ci.bio = &ci.md->flush_bio;
+		ci.sector_count = 0;
+		error = __clone_and_map_empty_flush(&ci);
+		/* dec_pending submits any data associated with flush */
+	} else {
+		ci.bio = bio;
+		ci.sector_count = bio_sectors(bio);
+		while (ci.sector_count && !error)
+			error = __clone_and_map(&ci);
+	}
 
 	/* drop the extra reference count */
 	dec_pending(ci.io, error);
@@ -1491,22 +1396,14 @@
 	part_stat_add(cpu, &dm_disk(md)->part0, sectors[rw], bio_sectors(bio));
 	part_stat_unlock();
 
-	/*
-	 * If we're suspended or the thread is processing barriers
-	 * we have to queue this io for later.
-	 */
-	if (unlikely(test_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags)) ||
-	    unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
+	/* if we're suspended, we have to queue this io for later */
+	if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) {
 		up_read(&md->io_lock);
 
-		if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) &&
-		    bio_rw(bio) == READA) {
+		if (bio_rw(bio) != READA)
+			queue_io(md, bio);
+		else
 			bio_io_error(bio);
-			return 0;
-		}
-
-		queue_io(md, bio);
-
 		return 0;
 	}
 
@@ -1537,14 +1434,6 @@
 	return _dm_request(q, bio);
 }
 
-static bool dm_rq_is_flush_request(struct request *rq)
-{
-	if (rq->cmd_flags & REQ_FLUSH)
-		return true;
-	else
-		return false;
-}
-
 void dm_dispatch_request(struct request *rq)
 {
 	int r;
@@ -1592,22 +1481,15 @@
 {
 	int r;
 
-	if (dm_rq_is_flush_request(rq)) {
-		blk_rq_init(NULL, clone);
-		clone->cmd_type = REQ_TYPE_FS;
-		clone->cmd_flags |= (REQ_HARDBARRIER | WRITE);
-	} else {
-		r = blk_rq_prep_clone(clone, rq, tio->md->bs, GFP_ATOMIC,
-				      dm_rq_bio_constructor, tio);
-		if (r)
-			return r;
+	r = blk_rq_prep_clone(clone, rq, tio->md->bs, GFP_ATOMIC,
+			      dm_rq_bio_constructor, tio);
+	if (r)
+		return r;
 
-		clone->cmd = rq->cmd;
-		clone->cmd_len = rq->cmd_len;
-		clone->sense = rq->sense;
-		clone->buffer = rq->buffer;
-	}
-
+	clone->cmd = rq->cmd;
+	clone->cmd_len = rq->cmd_len;
+	clone->sense = rq->sense;
+	clone->buffer = rq->buffer;
 	clone->end_io = end_clone_request;
 	clone->end_io_data = tio;
 
@@ -1648,9 +1530,6 @@
 	struct mapped_device *md = q->queuedata;
 	struct request *clone;
 
-	if (unlikely(dm_rq_is_flush_request(rq)))
-		return BLKPREP_OK;
-
 	if (unlikely(rq->special)) {
 		DMWARN("Already has something in rq->special.");
 		return BLKPREP_KILL;
@@ -1727,6 +1606,7 @@
 	struct dm_table *map = dm_get_live_table(md);
 	struct dm_target *ti;
 	struct request *rq, *clone;
+	sector_t pos;
 
 	/*
 	 * For suspend, check blk_queue_stopped() and increment
@@ -1739,15 +1619,14 @@
 		if (!rq)
 			goto plug_and_out;
 
-		if (unlikely(dm_rq_is_flush_request(rq))) {
-			BUG_ON(md->flush_request);
-			md->flush_request = rq;
-			blk_start_request(rq);
-			queue_work(md->wq, &md->barrier_work);
-			goto out;
-		}
+		/* always use block 0 to find the target for flushes for now */
+		pos = 0;
+		if (!(rq->cmd_flags & REQ_FLUSH))
+			pos = blk_rq_pos(rq);
 
-		ti = dm_table_find_target(map, blk_rq_pos(rq));
+		ti = dm_table_find_target(map, pos);
+		BUG_ON(!dm_target_is_valid(ti));
+
 		if (ti->type->busy && ti->type->busy(ti))
 			goto plug_and_out;
 
@@ -1918,7 +1797,6 @@
 static const struct block_device_operations dm_blk_dops;
 
 static void dm_wq_work(struct work_struct *work);
-static void dm_rq_barrier_work(struct work_struct *work);
 
 static void dm_init_md_queue(struct mapped_device *md)
 {
@@ -1940,6 +1818,7 @@
 	blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
 	md->queue->unplug_fn = dm_unplug_all;
 	blk_queue_merge_bvec(md->queue, dm_merge_bvec);
+	blk_queue_flush(md->queue, REQ_FLUSH | REQ_FUA);
 }
 
 /*
@@ -1972,7 +1851,6 @@
 	mutex_init(&md->suspend_lock);
 	mutex_init(&md->type_lock);
 	spin_lock_init(&md->deferred_lock);
-	spin_lock_init(&md->barrier_error_lock);
 	rwlock_init(&md->map_lock);
 	atomic_set(&md->holders, 1);
 	atomic_set(&md->open_count, 0);
@@ -1995,7 +1873,6 @@
 	atomic_set(&md->pending[1], 0);
 	init_waitqueue_head(&md->wait);
 	INIT_WORK(&md->work, dm_wq_work);
-	INIT_WORK(&md->barrier_work, dm_rq_barrier_work);
 	init_waitqueue_head(&md->eventq);
 
 	md->disk->major = _major;
@@ -2015,6 +1892,10 @@
 	if (!md->bdev)
 		goto bad_bdev;
 
+	bio_init(&md->flush_bio);
+	md->flush_bio.bi_bdev = md->bdev;
+	md->flush_bio.bi_rw = WRITE_FLUSH;
+
 	/* Populate the mapping, nobody knows we exist yet */
 	spin_lock(&_minor_lock);
 	old_md = idr_replace(&_minor_idr, md, minor);
@@ -2245,7 +2126,6 @@
 	blk_queue_softirq_done(md->queue, dm_softirq_done);
 	blk_queue_prep_rq(md->queue, dm_prep_fn);
 	blk_queue_lld_busy(md->queue, dm_lld_busy);
-	blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN_FLUSH);
 
 	elv_register_queue(md->queue);
 
@@ -2406,43 +2286,6 @@
 	return r;
 }
 
-static void dm_flush(struct mapped_device *md)
-{
-	dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
-
-	bio_init(&md->barrier_bio);
-	md->barrier_bio.bi_bdev = md->bdev;
-	md->barrier_bio.bi_rw = WRITE_BARRIER;
-	__split_and_process_bio(md, &md->barrier_bio);
-
-	dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
-}
-
-static void process_barrier(struct mapped_device *md, struct bio *bio)
-{
-	md->barrier_error = 0;
-
-	dm_flush(md);
-
-	if (!bio_empty_barrier(bio)) {
-		__split_and_process_bio(md, bio);
-		/*
-		 * If the request isn't supported, don't waste time with
-		 * the second flush.
-		 */
-		if (md->barrier_error != -EOPNOTSUPP)
-			dm_flush(md);
-	}
-
-	if (md->barrier_error != DM_ENDIO_REQUEUE)
-		bio_endio(bio, md->barrier_error);
-	else {
-		spin_lock_irq(&md->deferred_lock);
-		bio_list_add_head(&md->deferred, bio);
-		spin_unlock_irq(&md->deferred_lock);
-	}
-}
-
 /*
  * Process the deferred bios
  */
@@ -2452,33 +2295,27 @@
 						work);
 	struct bio *c;
 
-	down_write(&md->io_lock);
+	down_read(&md->io_lock);
 
 	while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
 		spin_lock_irq(&md->deferred_lock);
 		c = bio_list_pop(&md->deferred);
 		spin_unlock_irq(&md->deferred_lock);
 
-		if (!c) {
-			clear_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags);
+		if (!c)
 			break;
-		}
 
-		up_write(&md->io_lock);
+		up_read(&md->io_lock);
 
 		if (dm_request_based(md))
 			generic_make_request(c);
-		else {
-			if (c->bi_rw & REQ_HARDBARRIER)
-				process_barrier(md, c);
-			else
-				__split_and_process_bio(md, c);
-		}
+		else
+			__split_and_process_bio(md, c);
 
-		down_write(&md->io_lock);
+		down_read(&md->io_lock);
 	}
 
-	up_write(&md->io_lock);
+	up_read(&md->io_lock);
 }
 
 static void dm_queue_flush(struct mapped_device *md)
@@ -2488,73 +2325,6 @@
 	queue_work(md->wq, &md->work);
 }
 
-static void dm_rq_set_target_request_nr(struct request *clone, unsigned request_nr)
-{
-	struct dm_rq_target_io *tio = clone->end_io_data;
-
-	tio->info.target_request_nr = request_nr;
-}
-
-/* Issue barrier requests to targets and wait for their completion. */
-static int dm_rq_barrier(struct mapped_device *md)
-{
-	int i, j;
-	struct dm_table *map = dm_get_live_table(md);
-	unsigned num_targets = dm_table_get_num_targets(map);
-	struct dm_target *ti;
-	struct request *clone;
-
-	md->barrier_error = 0;
-
-	for (i = 0; i < num_targets; i++) {
-		ti = dm_table_get_target(map, i);
-		for (j = 0; j < ti->num_flush_requests; j++) {
-			clone = clone_rq(md->flush_request, md, GFP_NOIO);
-			dm_rq_set_target_request_nr(clone, j);
-			atomic_inc(&md->pending[rq_data_dir(clone)]);
-			map_request(ti, clone, md);
-		}
-	}
-
-	dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
-	dm_table_put(map);
-
-	return md->barrier_error;
-}
-
-static void dm_rq_barrier_work(struct work_struct *work)
-{
-	int error;
-	struct mapped_device *md = container_of(work, struct mapped_device,
-						barrier_work);
-	struct request_queue *q = md->queue;
-	struct request *rq;
-	unsigned long flags;
-
-	/*
-	 * Hold the md reference here and leave it at the last part so that
-	 * the md can't be deleted by device opener when the barrier request
-	 * completes.
-	 */
-	dm_get(md);
-
-	error = dm_rq_barrier(md);
-
-	rq = md->flush_request;
-	md->flush_request = NULL;
-
-	if (error == DM_ENDIO_REQUEUE) {
-		spin_lock_irqsave(q->queue_lock, flags);
-		blk_requeue_request(q, rq);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-	} else
-		blk_end_request_all(rq, error);
-
-	blk_run_queue(q);
-
-	dm_put(md);
-}
-
 /*
  * Swap in a new table, returning the old one for the caller to destroy.
  */
@@ -2677,23 +2447,17 @@
 	 *
 	 * To get all processes out of __split_and_process_bio in dm_request,
 	 * we take the write lock. To prevent any process from reentering
-	 * __split_and_process_bio from dm_request, we set
-	 * DMF_QUEUE_IO_TO_THREAD.
-	 *
-	 * To quiesce the thread (dm_wq_work), we set DMF_BLOCK_IO_FOR_SUSPEND
-	 * and call flush_workqueue(md->wq). flush_workqueue will wait until
-	 * dm_wq_work exits and DMF_BLOCK_IO_FOR_SUSPEND will prevent any
-	 * further calls to __split_and_process_bio from dm_wq_work.
+	 * __split_and_process_bio from dm_request and quiesce the thread
+	 * (dm_wq_work), we set BMF_BLOCK_IO_FOR_SUSPEND and call
+	 * flush_workqueue(md->wq).
 	 */
 	down_write(&md->io_lock);
 	set_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags);
-	set_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags);
 	up_write(&md->io_lock);
 
 	/*
-	 * Request-based dm uses md->wq for barrier (dm_rq_barrier_work) which
-	 * can be kicked until md->queue is stopped.  So stop md->queue before
-	 * flushing md->wq.
+	 * Stop md->queue before flushing md->wq in case request-based
+	 * dm defers requests to md->wq from md->queue.
 	 */
 	if (dm_request_based(md))
 		stop_queue(md->queue);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index ba19060..8a2f767 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -294,8 +294,8 @@
 	dev_info_t *tmp_dev;
 	sector_t start_sector;
 
-	if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
-		md_barrier_request(mddev, bio);
+	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+		md_flush_request(mddev, bio);
 		return 0;
 	}
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index f20d13e..2258151 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -36,7 +36,7 @@
 #include <linux/blkdev.h>
 #include <linux/sysctl.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/buffer_head.h> /* for invalidate_bdev */
 #include <linux/poll.h>
 #include <linux/ctype.h>
@@ -57,6 +57,7 @@
 #define DEBUG 0
 #define dprintk(x...) ((void)(DEBUG && printk(x)))
 
+static DEFINE_MUTEX(md_mutex);
 
 #ifndef MODULE
 static void autostart_arrays(int part);
@@ -226,12 +227,12 @@
 		return 0;
 	}
 	rcu_read_lock();
-	if (mddev->suspended || mddev->barrier) {
+	if (mddev->suspended) {
 		DEFINE_WAIT(__wait);
 		for (;;) {
 			prepare_to_wait(&mddev->sb_wait, &__wait,
 					TASK_UNINTERRUPTIBLE);
-			if (!mddev->suspended && !mddev->barrier)
+			if (!mddev->suspended)
 				break;
 			rcu_read_unlock();
 			schedule();
@@ -282,40 +283,29 @@
 
 int mddev_congested(mddev_t *mddev, int bits)
 {
-	if (mddev->barrier)
-		return 1;
 	return mddev->suspended;
 }
 EXPORT_SYMBOL(mddev_congested);
 
 /*
- * Generic barrier handling for md
+ * Generic flush handling for md
  */
 
-#define POST_REQUEST_BARRIER ((void*)1)
-
-static void md_end_barrier(struct bio *bio, int err)
+static void md_end_flush(struct bio *bio, int err)
 {
 	mdk_rdev_t *rdev = bio->bi_private;
 	mddev_t *mddev = rdev->mddev;
-	if (err == -EOPNOTSUPP && mddev->barrier != POST_REQUEST_BARRIER)
-		set_bit(BIO_EOPNOTSUPP, &mddev->barrier->bi_flags);
 
 	rdev_dec_pending(rdev, mddev);
 
 	if (atomic_dec_and_test(&mddev->flush_pending)) {
-		if (mddev->barrier == POST_REQUEST_BARRIER) {
-			/* This was a post-request barrier */
-			mddev->barrier = NULL;
-			wake_up(&mddev->sb_wait);
-		} else
-			/* The pre-request barrier has finished */
-			schedule_work(&mddev->barrier_work);
+		/* The pre-request flush has finished */
+		schedule_work(&mddev->flush_work);
 	}
 	bio_put(bio);
 }
 
-static void submit_barriers(mddev_t *mddev)
+static void submit_flushes(mddev_t *mddev)
 {
 	mdk_rdev_t *rdev;
 
@@ -332,60 +322,56 @@
 			atomic_inc(&rdev->nr_pending);
 			rcu_read_unlock();
 			bi = bio_alloc(GFP_KERNEL, 0);
-			bi->bi_end_io = md_end_barrier;
+			bi->bi_end_io = md_end_flush;
 			bi->bi_private = rdev;
 			bi->bi_bdev = rdev->bdev;
 			atomic_inc(&mddev->flush_pending);
-			submit_bio(WRITE_BARRIER, bi);
+			submit_bio(WRITE_FLUSH, bi);
 			rcu_read_lock();
 			rdev_dec_pending(rdev, mddev);
 		}
 	rcu_read_unlock();
 }
 
-static void md_submit_barrier(struct work_struct *ws)
+static void md_submit_flush_data(struct work_struct *ws)
 {
-	mddev_t *mddev = container_of(ws, mddev_t, barrier_work);
-	struct bio *bio = mddev->barrier;
+	mddev_t *mddev = container_of(ws, mddev_t, flush_work);
+	struct bio *bio = mddev->flush_bio;
 
 	atomic_set(&mddev->flush_pending, 1);
 
-	if (test_bit(BIO_EOPNOTSUPP, &bio->bi_flags))
-		bio_endio(bio, -EOPNOTSUPP);
-	else if (bio->bi_size == 0)
+	if (bio->bi_size == 0)
 		/* an empty barrier - all done */
 		bio_endio(bio, 0);
 	else {
-		bio->bi_rw &= ~REQ_HARDBARRIER;
+		bio->bi_rw &= ~REQ_FLUSH;
 		if (mddev->pers->make_request(mddev, bio))
 			generic_make_request(bio);
-		mddev->barrier = POST_REQUEST_BARRIER;
-		submit_barriers(mddev);
 	}
 	if (atomic_dec_and_test(&mddev->flush_pending)) {
-		mddev->barrier = NULL;
+		mddev->flush_bio = NULL;
 		wake_up(&mddev->sb_wait);
 	}
 }
 
-void md_barrier_request(mddev_t *mddev, struct bio *bio)
+void md_flush_request(mddev_t *mddev, struct bio *bio)
 {
 	spin_lock_irq(&mddev->write_lock);
 	wait_event_lock_irq(mddev->sb_wait,
-			    !mddev->barrier,
+			    !mddev->flush_bio,
 			    mddev->write_lock, /*nothing*/);
-	mddev->barrier = bio;
+	mddev->flush_bio = bio;
 	spin_unlock_irq(&mddev->write_lock);
 
 	atomic_set(&mddev->flush_pending, 1);
-	INIT_WORK(&mddev->barrier_work, md_submit_barrier);
+	INIT_WORK(&mddev->flush_work, md_submit_flush_data);
 
-	submit_barriers(mddev);
+	submit_flushes(mddev);
 
 	if (atomic_dec_and_test(&mddev->flush_pending))
-		schedule_work(&mddev->barrier_work);
+		schedule_work(&mddev->flush_work);
 }
-EXPORT_SYMBOL(md_barrier_request);
+EXPORT_SYMBOL(md_flush_request);
 
 /* Support for plugging.
  * This mirrors the plugging support in request_queue, but does not
@@ -696,31 +682,6 @@
 	bio_put(bio);
 }
 
-static void super_written_barrier(struct bio *bio, int error)
-{
-	struct bio *bio2 = bio->bi_private;
-	mdk_rdev_t *rdev = bio2->bi_private;
-	mddev_t *mddev = rdev->mddev;
-
-	if (!test_bit(BIO_UPTODATE, &bio->bi_flags) &&
-	    error == -EOPNOTSUPP) {
-		unsigned long flags;
-		/* barriers don't appear to be supported :-( */
-		set_bit(BarriersNotsupp, &rdev->flags);
-		mddev->barriers_work = 0;
-		spin_lock_irqsave(&mddev->write_lock, flags);
-		bio2->bi_next = mddev->biolist;
-		mddev->biolist = bio2;
-		spin_unlock_irqrestore(&mddev->write_lock, flags);
-		wake_up(&mddev->sb_wait);
-		bio_put(bio);
-	} else {
-		bio_put(bio2);
-		bio->bi_private = rdev;
-		super_written(bio, error);
-	}
-}
-
 void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
 		   sector_t sector, int size, struct page *page)
 {
@@ -729,51 +690,28 @@
 	 * and decrement it on completion, waking up sb_wait
 	 * if zero is reached.
 	 * If an error occurred, call md_error
-	 *
-	 * As we might need to resubmit the request if REQ_HARDBARRIER
-	 * causes ENOTSUPP, we allocate a spare bio...
 	 */
 	struct bio *bio = bio_alloc(GFP_NOIO, 1);
-	int rw = REQ_WRITE | REQ_SYNC | REQ_UNPLUG;
 
 	bio->bi_bdev = rdev->bdev;
 	bio->bi_sector = sector;
 	bio_add_page(bio, page, size, 0);
 	bio->bi_private = rdev;
 	bio->bi_end_io = super_written;
-	bio->bi_rw = rw;
 
 	atomic_inc(&mddev->pending_writes);
-	if (!test_bit(BarriersNotsupp, &rdev->flags)) {
-		struct bio *rbio;
-		rw |= REQ_HARDBARRIER;
-		rbio = bio_clone(bio, GFP_NOIO);
-		rbio->bi_private = bio;
-		rbio->bi_end_io = super_written_barrier;
-		submit_bio(rw, rbio);
-	} else
-		submit_bio(rw, bio);
+	submit_bio(REQ_WRITE | REQ_SYNC | REQ_UNPLUG | REQ_FLUSH | REQ_FUA,
+		   bio);
 }
 
 void md_super_wait(mddev_t *mddev)
 {
-	/* wait for all superblock writes that were scheduled to complete.
-	 * if any had to be retried (due to BARRIER problems), retry them
-	 */
+	/* wait for all superblock writes that were scheduled to complete */
 	DEFINE_WAIT(wq);
 	for(;;) {
 		prepare_to_wait(&mddev->sb_wait, &wq, TASK_UNINTERRUPTIBLE);
 		if (atomic_read(&mddev->pending_writes)==0)
 			break;
-		while (mddev->biolist) {
-			struct bio *bio;
-			spin_lock_irq(&mddev->write_lock);
-			bio = mddev->biolist;
-			mddev->biolist = bio->bi_next ;
-			bio->bi_next = NULL;
-			spin_unlock_irq(&mddev->write_lock);
-			submit_bio(bio->bi_rw, bio);
-		}
 		schedule();
 	}
 	finish_wait(&mddev->sb_wait, &wq);
@@ -1070,7 +1008,6 @@
 	clear_bit(Faulty, &rdev->flags);
 	clear_bit(In_sync, &rdev->flags);
 	clear_bit(WriteMostly, &rdev->flags);
-	clear_bit(BarriersNotsupp, &rdev->flags);
 
 	if (mddev->raid_disks == 0) {
 		mddev->major_version = 0;
@@ -1485,7 +1422,6 @@
 	clear_bit(Faulty, &rdev->flags);
 	clear_bit(In_sync, &rdev->flags);
 	clear_bit(WriteMostly, &rdev->flags);
-	clear_bit(BarriersNotsupp, &rdev->flags);
 
 	if (mddev->raid_disks == 0) {
 		mddev->major_version = 1;
@@ -4504,7 +4440,6 @@
 	/* may be over-ridden by personality */
 	mddev->resync_max_sectors = mddev->dev_sectors;
 
-	mddev->barriers_work = 1;
 	mddev->ok_start_degraded = start_dirty_degraded;
 
 	if (start_readonly && mddev->ro == 0)
@@ -4683,7 +4618,6 @@
 	mddev->recovery = 0;
 	mddev->in_sync = 0;
 	mddev->degraded = 0;
-	mddev->barriers_work = 0;
 	mddev->safemode = 0;
 	mddev->bitmap_info.offset = 0;
 	mddev->bitmap_info.default_offset = 0;
@@ -5951,7 +5885,7 @@
 	mddev_t *mddev = mddev_find(bdev->bd_dev);
 	int err;
 
-	lock_kernel();
+	mutex_lock(&md_mutex);
 	if (mddev->gendisk != bdev->bd_disk) {
 		/* we are racing with mddev_put which is discarding this
 		 * bd_disk.
@@ -5960,7 +5894,7 @@
 		/* Wait until bdev->bd_disk is definitely gone */
 		flush_scheduled_work();
 		/* Then retry the open from the top */
-		unlock_kernel();
+		mutex_unlock(&md_mutex);
 		return -ERESTARTSYS;
 	}
 	BUG_ON(mddev != bdev->bd_disk->private_data);
@@ -5974,7 +5908,7 @@
 
 	check_disk_size_change(mddev->gendisk, bdev);
  out:
-	unlock_kernel();
+	mutex_unlock(&md_mutex);
 	return err;
 }
 
@@ -5983,10 +5917,10 @@
  	mddev_t *mddev = disk->private_data;
 
 	BUG_ON(!mddev);
-	lock_kernel();
+	mutex_lock(&md_mutex);
 	atomic_dec(&mddev->openers);
 	mddev_put(mddev);
-	unlock_kernel();
+	mutex_unlock(&md_mutex);
 
 	return 0;
 }
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 3931299..112a2c3 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -87,7 +87,6 @@
 #define	Faulty		1		/* device is known to have a fault */
 #define	In_sync		2		/* device is in_sync with rest of array */
 #define	WriteMostly	4		/* Avoid reading if at all possible */
-#define	BarriersNotsupp	5		/* REQ_HARDBARRIER is not supported */
 #define	AllReserved	6		/* If whole device is reserved for
 					 * one array */
 #define	AutoDetected	7		/* added by auto-detect */
@@ -273,13 +272,6 @@
 	int				degraded;	/* whether md should consider
 							 * adding a spare
 							 */
-	int				barriers_work;	/* initialised to true, cleared as soon
-							 * as a barrier request to slave
-							 * fails.  Only supported
-							 */
-	struct bio			*biolist; 	/* bios that need to be retried
-							 * because REQ_HARDBARRIER is not supported
-							 */
 
 	atomic_t			recovery_active; /* blocks scheduled, but not written */
 	wait_queue_head_t		recovery_wait;
@@ -339,16 +331,13 @@
 	struct attribute_group		*to_remove;
 	struct plug_handle		*plug; /* if used by personality */
 
-	/* Generic barrier handling.
-	 * If there is a pending barrier request, all other
-	 * writes are blocked while the devices are flushed.
-	 * The last to finish a flush schedules a worker to
-	 * submit the barrier request (without the barrier flag),
-	 * then submit more flush requests.
+	/* Generic flush handling.
+	 * The last to finish preflush schedules a worker to submit
+	 * the rest of the request (without the REQ_FLUSH flag).
 	 */
-	struct bio *barrier;
+	struct bio *flush_bio;
 	atomic_t flush_pending;
-	struct work_struct barrier_work;
+	struct work_struct flush_work;
 	struct work_struct event_work;	/* used by dm to report failure event */
 };
 
@@ -502,7 +491,7 @@
 extern void md_error(mddev_t *mddev, mdk_rdev_t *rdev);
 
 extern int mddev_congested(mddev_t *mddev, int bits);
-extern void md_barrier_request(mddev_t *mddev, struct bio *bio);
+extern void md_flush_request(mddev_t *mddev, struct bio *bio);
 extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
 			   sector_t sector, int size, struct page *page);
 extern void md_super_wait(mddev_t *mddev);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 0307d21..6d7ddf3 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -142,8 +142,8 @@
 	struct multipath_bh * mp_bh;
 	struct multipath_info *multipath;
 
-	if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
-		md_barrier_request(mddev, bio);
+	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+		md_flush_request(mddev, bio);
 		return 0;
 	}
 
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 6f7af46..a39f4c3 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -483,8 +483,8 @@
 	struct strip_zone *zone;
 	mdk_rdev_t *tmp_dev;
 
-	if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
-		md_barrier_request(mddev, bio);
+	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+		md_flush_request(mddev, bio);
 		return 0;
 	}
 
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index ad83a4d..378a258 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -319,83 +319,74 @@
 		if (r1_bio->bios[mirror] == bio)
 			break;
 
-	if (error == -EOPNOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) {
-		set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags);
-		set_bit(R1BIO_BarrierRetry, &r1_bio->state);
-		r1_bio->mddev->barriers_work = 0;
-		/* Don't rdev_dec_pending in this branch - keep it for the retry */
-	} else {
+	/*
+	 * 'one mirror IO has finished' event handler:
+	 */
+	r1_bio->bios[mirror] = NULL;
+	to_put = bio;
+	if (!uptodate) {
+		md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
+		/* an I/O failed, we can't clear the bitmap */
+		set_bit(R1BIO_Degraded, &r1_bio->state);
+	} else
 		/*
-		 * this branch is our 'one mirror IO has finished' event handler:
+		 * Set R1BIO_Uptodate in our master bio, so that we
+		 * will return a good error code for to the higher
+		 * levels even if IO on some other mirrored buffer
+		 * fails.
+		 *
+		 * The 'master' represents the composite IO operation
+		 * to user-side. So if something waits for IO, then it
+		 * will wait for the 'master' bio.
 		 */
-		r1_bio->bios[mirror] = NULL;
-		to_put = bio;
-		if (!uptodate) {
-			md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
-			/* an I/O failed, we can't clear the bitmap */
-			set_bit(R1BIO_Degraded, &r1_bio->state);
-		} else
-			/*
-			 * Set R1BIO_Uptodate in our master bio, so that
-			 * we will return a good error code for to the higher
-			 * levels even if IO on some other mirrored buffer fails.
-			 *
-			 * The 'master' represents the composite IO operation to
-			 * user-side. So if something waits for IO, then it will
-			 * wait for the 'master' bio.
-			 */
-			set_bit(R1BIO_Uptodate, &r1_bio->state);
+		set_bit(R1BIO_Uptodate, &r1_bio->state);
 
-		update_head_pos(mirror, r1_bio);
+	update_head_pos(mirror, r1_bio);
 
-		if (behind) {
-			if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
-				atomic_dec(&r1_bio->behind_remaining);
+	if (behind) {
+		if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
+			atomic_dec(&r1_bio->behind_remaining);
 
-			/* In behind mode, we ACK the master bio once the I/O has safely
-			 * reached all non-writemostly disks. Setting the Returned bit
-			 * ensures that this gets done only once -- we don't ever want to
-			 * return -EIO here, instead we'll wait */
-
-			if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) &&
-			    test_bit(R1BIO_Uptodate, &r1_bio->state)) {
-				/* Maybe we can return now */
-				if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
-					struct bio *mbio = r1_bio->master_bio;
-					PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
-					       (unsigned long long) mbio->bi_sector,
-					       (unsigned long long) mbio->bi_sector +
-					       (mbio->bi_size >> 9) - 1);
-					bio_endio(mbio, 0);
-				}
+		/*
+		 * In behind mode, we ACK the master bio once the I/O
+		 * has safely reached all non-writemostly
+		 * disks. Setting the Returned bit ensures that this
+		 * gets done only once -- we don't ever want to return
+		 * -EIO here, instead we'll wait
+		 */
+		if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) &&
+		    test_bit(R1BIO_Uptodate, &r1_bio->state)) {
+			/* Maybe we can return now */
+			if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
+				struct bio *mbio = r1_bio->master_bio;
+				PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
+				       (unsigned long long) mbio->bi_sector,
+				       (unsigned long long) mbio->bi_sector +
+				       (mbio->bi_size >> 9) - 1);
+				bio_endio(mbio, 0);
 			}
 		}
-		rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
 	}
+	rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
+
 	/*
-	 *
 	 * Let's see if all mirrored write operations have finished
 	 * already.
 	 */
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
-		if (test_bit(R1BIO_BarrierRetry, &r1_bio->state))
-			reschedule_retry(r1_bio);
-		else {
-			/* it really is the end of this request */
-			if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
-				/* free extra copy of the data pages */
-				int i = bio->bi_vcnt;
-				while (i--)
-					safe_put_page(bio->bi_io_vec[i].bv_page);
-			}
-			/* clear the bitmap if all writes complete successfully */
-			bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
-					r1_bio->sectors,
-					!test_bit(R1BIO_Degraded, &r1_bio->state),
-					behind);
-			md_write_end(r1_bio->mddev);
-			raid_end_bio_io(r1_bio);
+		if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
+			/* free extra copy of the data pages */
+			int i = bio->bi_vcnt;
+			while (i--)
+				safe_put_page(bio->bi_io_vec[i].bv_page);
 		}
+		/* clear the bitmap if all writes complete successfully */
+		bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
+				r1_bio->sectors,
+				!test_bit(R1BIO_Degraded, &r1_bio->state),
+				behind);
+		md_write_end(r1_bio->mddev);
+		raid_end_bio_io(r1_bio);
 	}
 
 	if (to_put)
@@ -788,16 +779,13 @@
 	struct page **behind_pages = NULL;
 	const int rw = bio_data_dir(bio);
 	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
-	unsigned long do_barriers;
+	const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
 	mdk_rdev_t *blocked_rdev;
 
 	/*
 	 * Register the new request and wait if the reconstruction
 	 * thread has put up a bar for new requests.
 	 * Continue immediately if no resync is active currently.
-	 * We test barriers_work *after* md_write_start as md_write_start
-	 * may cause the first superblock write, and that will check out
-	 * if barriers work.
 	 */
 
 	md_write_start(mddev, bio); /* wait on superblock update early */
@@ -821,13 +809,6 @@
 		}
 		finish_wait(&conf->wait_barrier, &w);
 	}
-	if (unlikely(!mddev->barriers_work &&
-		     (bio->bi_rw & REQ_HARDBARRIER))) {
-		if (rw == WRITE)
-			md_write_end(mddev);
-		bio_endio(bio, -EOPNOTSUPP);
-		return 0;
-	}
 
 	wait_barrier(conf);
 
@@ -959,10 +940,6 @@
 	atomic_set(&r1_bio->remaining, 0);
 	atomic_set(&r1_bio->behind_remaining, 0);
 
-	do_barriers = bio->bi_rw & REQ_HARDBARRIER;
-	if (do_barriers)
-		set_bit(R1BIO_Barrier, &r1_bio->state);
-
 	bio_list_init(&bl);
 	for (i = 0; i < disks; i++) {
 		struct bio *mbio;
@@ -975,7 +952,7 @@
 		mbio->bi_sector	= r1_bio->sector + conf->mirrors[i].rdev->data_offset;
 		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
 		mbio->bi_end_io	= raid1_end_write_request;
-		mbio->bi_rw = WRITE | do_barriers | do_sync;
+		mbio->bi_rw = WRITE | do_flush_fua | do_sync;
 		mbio->bi_private = r1_bio;
 
 		if (behind_pages) {
@@ -1634,41 +1611,6 @@
 		if (test_bit(R1BIO_IsSync, &r1_bio->state)) {
 			sync_request_write(mddev, r1_bio);
 			unplug = 1;
-		} else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) {
-			/* some requests in the r1bio were REQ_HARDBARRIER
-			 * requests which failed with -EOPNOTSUPP.  Hohumm..
-			 * Better resubmit without the barrier.
-			 * We know which devices to resubmit for, because
-			 * all others have had their bios[] entry cleared.
-			 * We already have a nr_pending reference on these rdevs.
-			 */
-			int i;
-			const unsigned long do_sync = (r1_bio->master_bio->bi_rw & REQ_SYNC);
-			clear_bit(R1BIO_BarrierRetry, &r1_bio->state);
-			clear_bit(R1BIO_Barrier, &r1_bio->state);
-			for (i=0; i < conf->raid_disks; i++)
-				if (r1_bio->bios[i])
-					atomic_inc(&r1_bio->remaining);
-			for (i=0; i < conf->raid_disks; i++)
-				if (r1_bio->bios[i]) {
-					struct bio_vec *bvec;
-					int j;
-
-					bio = bio_clone(r1_bio->master_bio, GFP_NOIO);
-					/* copy pages from the failed bio, as
-					 * this might be a write-behind device */
-					__bio_for_each_segment(bvec, bio, j, 0)
-						bvec->bv_page = bio_iovec_idx(r1_bio->bios[i], j)->bv_page;
-					bio_put(r1_bio->bios[i]);
-					bio->bi_sector = r1_bio->sector +
-						conf->mirrors[i].rdev->data_offset;
-					bio->bi_bdev = conf->mirrors[i].rdev->bdev;
-					bio->bi_end_io = raid1_end_write_request;
-					bio->bi_rw = WRITE | do_sync;
-					bio->bi_private = r1_bio;
-					r1_bio->bios[i] = bio;
-					generic_make_request(bio);
-				}
 		} else {
 			int disk;
 
@@ -1839,7 +1781,9 @@
 
 		/* take from bio_init */
 		bio->bi_next = NULL;
+		bio->bi_flags &= ~(BIO_POOL_MASK-1);
 		bio->bi_flags |= 1 << BIO_UPTODATE;
+		bio->bi_comp_cpu = -1;
 		bio->bi_rw = READ;
 		bio->bi_vcnt = 0;
 		bio->bi_idx = 0;
@@ -1912,7 +1856,7 @@
 			    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
 				break;
 			BUG_ON(sync_blocks < (PAGE_SIZE>>9));
-			if (len > (sync_blocks<<9))
+			if ((len >> 9) > sync_blocks)
 				len = sync_blocks<<9;
 		}
 
diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h
index 5f2d443..adf8cfd 100644
--- a/drivers/md/raid1.h
+++ b/drivers/md/raid1.h
@@ -117,8 +117,6 @@
 #define	R1BIO_IsSync	1
 #define	R1BIO_Degraded	2
 #define	R1BIO_BehindIO	3
-#define	R1BIO_Barrier	4
-#define R1BIO_BarrierRetry 5
 /* For write-behind requests, we call bi_end_io when
  * the last non-write-behind device completes, providing
  * any write was successful.  Otherwise we call when
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 8471838..f0d082f 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -800,12 +800,13 @@
 	int chunk_sects = conf->chunk_mask + 1;
 	const int rw = bio_data_dir(bio);
 	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
+	const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
 	struct bio_list bl;
 	unsigned long flags;
 	mdk_rdev_t *blocked_rdev;
 
-	if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
-		md_barrier_request(mddev, bio);
+	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+		md_flush_request(mddev, bio);
 		return 0;
 	}
 
@@ -965,7 +966,7 @@
 			conf->mirrors[d].rdev->data_offset;
 		mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
 		mbio->bi_end_io	= raid10_end_write_request;
-		mbio->bi_rw = WRITE | do_sync;
+		mbio->bi_rw = WRITE | do_sync | do_fua;
 		mbio->bi_private = r10_bio;
 
 		atomic_inc(&r10_bio->remaining);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 69b0a16..31140d1 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -506,9 +506,12 @@
 		int rw;
 		struct bio *bi;
 		mdk_rdev_t *rdev;
-		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
-			rw = WRITE;
-		else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
+		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) {
+			if (test_and_clear_bit(R5_WantFUA, &sh->dev[i].flags))
+				rw = WRITE_FUA;
+			else
+				rw = WRITE;
+		} else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
 			rw = READ;
 		else
 			continue;
@@ -1031,6 +1034,8 @@
 
 			while (wbi && wbi->bi_sector <
 				dev->sector + STRIPE_SECTORS) {
+				if (wbi->bi_rw & REQ_FUA)
+					set_bit(R5_WantFUA, &dev->flags);
 				tx = async_copy_data(1, wbi, dev->page,
 					dev->sector, tx);
 				wbi = r5_next_bio(wbi, dev->sector);
@@ -1048,15 +1053,22 @@
 	int pd_idx = sh->pd_idx;
 	int qd_idx = sh->qd_idx;
 	int i;
+	bool fua = false;
 
 	pr_debug("%s: stripe %llu\n", __func__,
 		(unsigned long long)sh->sector);
 
+	for (i = disks; i--; )
+		fua |= test_bit(R5_WantFUA, &sh->dev[i].flags);
+
 	for (i = disks; i--; ) {
 		struct r5dev *dev = &sh->dev[i];
 
-		if (dev->written || i == pd_idx || i == qd_idx)
+		if (dev->written || i == pd_idx || i == qd_idx) {
 			set_bit(R5_UPTODATE, &dev->flags);
+			if (fua)
+				set_bit(R5_WantFUA, &dev->flags);
+		}
 	}
 
 	if (sh->reconstruct_state == reconstruct_state_drain_run)
@@ -3281,7 +3293,7 @@
 
 	if (dec_preread_active) {
 		/* We delay this until after ops_run_io so that if make_request
-		 * is waiting on a barrier, it won't continue until the writes
+		 * is waiting on a flush, it won't continue until the writes
 		 * have actually been submitted.
 		 */
 		atomic_dec(&conf->preread_active_stripes);
@@ -3583,7 +3595,7 @@
 
 	if (dec_preread_active) {
 		/* We delay this until after ops_run_io so that if make_request
-		 * is waiting on a barrier, it won't continue until the writes
+		 * is waiting on a flush, it won't continue until the writes
 		 * have actually been submitted.
 		 */
 		atomic_dec(&conf->preread_active_stripes);
@@ -3978,14 +3990,8 @@
 	const int rw = bio_data_dir(bi);
 	int remaining;
 
-	if (unlikely(bi->bi_rw & REQ_HARDBARRIER)) {
-		/* Drain all pending writes.  We only really need
-		 * to ensure they have been submitted, but this is
-		 * easier.
-		 */
-		mddev->pers->quiesce(mddev, 1);
-		mddev->pers->quiesce(mddev, 0);
-		md_barrier_request(mddev, bi);
+	if (unlikely(bi->bi_rw & REQ_FLUSH)) {
+		md_flush_request(mddev, bi);
 		return 0;
 	}
 
@@ -4103,7 +4109,7 @@
 			finish_wait(&conf->wait_for_overlap, &w);
 			set_bit(STRIPE_HANDLE, &sh->state);
 			clear_bit(STRIPE_DELAYED, &sh->state);
-			if (mddev->barrier && 
+			if ((bi->bi_rw & REQ_SYNC) &&
 			    !test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
 				atomic_inc(&conf->preread_active_stripes);
 			release_stripe(sh);
@@ -4126,13 +4132,6 @@
 		bio_endio(bi, 0);
 	}
 
-	if (mddev->barrier) {
-		/* We need to wait for the stripes to all be handled.
-		 * So: wait for preread_active_stripes to drop to 0.
-		 */
-		wait_event(mddev->thread->wqueue,
-			   atomic_read(&conf->preread_active_stripes) == 0);
-	}
 	return 0;
 }
 
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 36eaed5..2ace058 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -275,6 +275,7 @@
 				    * filling
 				    */
 #define R5_Wantdrain	13 /* dev->towrite needs to be drained */
+#define R5_WantFUA	14	/* Write should be FUA */
 /*
  * Write method
  */
diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c
index c185422..faed5a3 100644
--- a/drivers/media/IR/imon.c
+++ b/drivers/media/IR/imon.c
@@ -151,7 +151,8 @@
 	.owner		= THIS_MODULE,
 	.open		= &display_open,
 	.write		= &vfd_write,
-	.release	= &display_close
+	.release	= &display_close,
+	.llseek		= noop_llseek,
 };
 
 /* lcd character device file operations */
@@ -159,7 +160,8 @@
 	.owner		= THIS_MODULE,
 	.open		= &display_open,
 	.write		= &lcd_write,
-	.release	= &display_close
+	.release	= &display_close,
+	.llseek		= noop_llseek,
 };
 
 enum {
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c
index 7e82a9d..7961d59 100644
--- a/drivers/media/IR/ir-keytable.c
+++ b/drivers/media/IR/ir-keytable.c
@@ -319,7 +319,7 @@
 	 * a keyup event might follow immediately after the keydown.
 	 */
 	spin_lock_irqsave(&ir->keylock, flags);
-	if (time_is_after_eq_jiffies(ir->keyup_jiffies))
+	if (time_is_before_eq_jiffies(ir->keyup_jiffies))
 		ir_keyup(ir);
 	spin_unlock_irqrestore(&ir->keylock, flags);
 }
@@ -510,6 +510,13 @@
 		   (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
 			" in raw mode" : "");
 
+	/*
+	 * Default delay of 250ms is too short for some protocols, expecially
+	 * since the timeout is currently set to 250ms. Increase it to 500ms,
+	 * to avoid wrong repetition of the keycodes.
+	 */
+	input_dev->rep[REP_DELAY] = 500;
+
 	return 0;
 
 out_event:
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c
index 77b5946..1983cd3 100644
--- a/drivers/media/IR/ir-lirc-codec.c
+++ b/drivers/media/IR/ir-lirc-codec.c
@@ -235,6 +235,7 @@
 	.poll		= lirc_dev_fop_poll,
 	.open		= lirc_dev_fop_open,
 	.release	= lirc_dev_fop_close,
+	.llseek		= no_llseek,
 };
 
 static int ir_lirc_register(struct input_dev *input_dev)
@@ -267,7 +268,7 @@
 			features |= LIRC_CAN_SET_SEND_CARRIER;
 
 		if (ir_dev->props->s_tx_duty_cycle)
-			features |= LIRC_CAN_SET_REC_DUTY_CYCLE;
+			features |= LIRC_CAN_SET_SEND_DUTY_CYCLE;
 	}
 
 	if (ir_dev->props->s_rx_carrier_range)
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index 43094e7..8e0e1b1 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -279,9 +279,11 @@
 			"rc%u",  (unsigned int)ir->devno);
 
 	if (IS_ERR(ir->raw->thread)) {
+		int ret = PTR_ERR(ir->raw->thread);
+
 		kfree(ir->raw);
 		ir->raw = NULL;
-		return PTR_ERR(ir->raw->thread);
+		return ret;
 	}
 
 	mutex_lock(&ir_raw_handler_lock);
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index 96dafc4..46d4246 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -67,13 +67,14 @@
 	char *tmp = buf;
 	int i;
 
-	if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
+	if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
 		enabled = ir_dev->rc_tab.ir_type;
 		allowed = ir_dev->props->allowed_protos;
-	} else {
+	} else if (ir_dev->raw) {
 		enabled = ir_dev->raw->enabled_protocols;
 		allowed = ir_raw_get_allowed_protocols();
-	}
+	} else
+		return sprintf(tmp, "[builtin]\n");
 
 	IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
 		   (long long)allowed,
@@ -121,10 +122,14 @@
 	int rc, i, count = 0;
 	unsigned long flags;
 
-	if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
+	if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
 		type = ir_dev->rc_tab.ir_type;
-	else
+	else if (ir_dev->raw)
 		type = ir_dev->raw->enabled_protocols;
+	else {
+		IR_dprintk(1, "Protocol switching not supported\n");
+		return -EINVAL;
+	}
 
 	while ((tmp = strsep((char **) &data, " \n")) != NULL) {
 		if (!*tmp)
@@ -185,7 +190,7 @@
 		}
 	}
 
-	if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
+	if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
 		spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
 		ir_dev->rc_tab.ir_type = type;
 		spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
diff --git a/drivers/media/IR/keymaps/rc-rc6-mce.c b/drivers/media/IR/keymaps/rc-rc6-mce.c
index 64264f7..39557ad 100644
--- a/drivers/media/IR/keymaps/rc-rc6-mce.c
+++ b/drivers/media/IR/keymaps/rc-rc6-mce.c
@@ -19,6 +19,7 @@
 
 	{ 0x800f0416, KEY_PLAY },
 	{ 0x800f0418, KEY_PAUSE },
+	{ 0x800f046e, KEY_PLAYPAUSE },
 	{ 0x800f0419, KEY_STOP },
 	{ 0x800f0417, KEY_RECORD },
 
@@ -37,6 +38,8 @@
 	{ 0x800f0411, KEY_VOLUMEDOWN },
 	{ 0x800f0412, KEY_CHANNELUP },
 	{ 0x800f0413, KEY_CHANNELDOWN },
+	{ 0x800f043a, KEY_BRIGHTNESSUP },
+	{ 0x800f0480, KEY_BRIGHTNESSDOWN },
 
 	{ 0x800f0401, KEY_NUMERIC_1 },
 	{ 0x800f0402, KEY_NUMERIC_2 },
diff --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c
index 899891b..0acf639 100644
--- a/drivers/media/IR/lirc_dev.c
+++ b/drivers/media/IR/lirc_dev.c
@@ -163,6 +163,7 @@
 	.unlocked_ioctl	= lirc_dev_fop_ioctl,
 	.open		= lirc_dev_fop_open,
 	.release	= lirc_dev_fop_close,
+	.llseek		= noop_llseek,
 };
 
 static int lirc_cdev_add(struct irctl *ir)
@@ -460,6 +461,8 @@
 
 	mutex_unlock(&lirc_dev_lock);
 
+	nonseekable_open(inode, file);
+
 	return retval;
 }
 EXPORT_SYMBOL(lirc_dev_fop_open);
diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c
index ac6bb2c..bc620e1 100644
--- a/drivers/media/IR/mceusb.c
+++ b/drivers/media/IR/mceusb.c
@@ -120,6 +120,10 @@
 	{ USB_DEVICE(VENDOR_PHILIPS, 0x0613) },
 	/* Philips eHome Infrared Transceiver */
 	{ USB_DEVICE(VENDOR_PHILIPS, 0x0815) },
+	/* Philips/Spinel plus IR transceiver for ASUS */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x206c) },
+	/* Philips/Spinel plus IR transceiver for ASUS */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x2088) },
 	/* Realtek MCE IR Receiver */
 	{ USB_DEVICE(VENDOR_REALTEK, 0x0161) },
 	/* SMK/Toshiba G83C0004D410 */
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index a28541b..bad2ced 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -19,6 +19,7 @@
 
 config VIDEO_DEV
 	tristate "Video For Linux"
+	depends on BKL # used in many drivers for ioctl handling, need to kill
 	---help---
 	  V4L core support for video capture and overlay devices, webcams and
 	  AM/FM radio cards.
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index cf87051..48e48e8 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -22,7 +22,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/string.h>
 #include <linux/dvb/ca.h>
 #include "dvbdev.h"
@@ -52,6 +52,7 @@
 } while(0)
 
 
+static DEFINE_MUTEX(dst_ca_mutex);
 static unsigned int verbose = 5;
 module_param(verbose, int, 0644);
 MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
@@ -564,7 +565,7 @@
 	void __user *arg = (void __user *)ioctl_arg;
 	int result = 0;
 
-	lock_kernel();
+	mutex_lock(&dst_ca_mutex);
 	dvbdev = file->private_data;
 	state = (struct dst_state *)dvbdev->priv;
 	p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
@@ -652,7 +653,7 @@
 	kfree (p_ca_slot_info);
 	kfree (p_ca_caps);
 
-	unlock_kernel();
+	mutex_unlock(&dst_ca_mutex);
 	return result;
 }
 
@@ -694,7 +695,8 @@
 	.open = dst_ca_open,
 	.release = dst_ca_release,
 	.read = dst_ca_read,
-	.write = dst_ca_write
+	.write = dst_ca_write,
+	.llseek = noop_llseek,
 };
 
 static struct dvb_device dvbdev_ca = {
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 0042306..ad1f61d 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -25,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <linux/ioctl.h>
 #include <linux/wait.h>
@@ -1088,13 +1087,7 @@
 static long dvb_demux_ioctl(struct file *file, unsigned int cmd,
 			    unsigned long arg)
 {
-	int ret;
-
-	lock_kernel();
-	ret = dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
-	unlock_kernel();
-
-	return ret;
+	return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
 }
 
 static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
@@ -1150,6 +1143,7 @@
 	.open = dvb_demux_open,
 	.release = dvb_demux_release,
 	.poll = dvb_demux_poll,
+	.llseek = default_llseek,
 };
 
 static struct dvb_device dvbdev_demux = {
@@ -1186,13 +1180,7 @@
 static long dvb_dvr_ioctl(struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
-	int ret;
-
-	lock_kernel();
-	ret = dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
-	unlock_kernel();
-
-	return ret;
+	return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
 }
 
 static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
@@ -1225,6 +1213,7 @@
 	.open = dvb_dvr_open,
 	.release = dvb_dvr_release,
 	.poll = dvb_dvr_poll,
+	.llseek = default_llseek,
 };
 
 static struct dvb_device dvbdev_dvr = {
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index cb97e6b..4d0646d 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1259,13 +1259,7 @@
 static long dvb_ca_en50221_io_ioctl(struct file *file,
 				    unsigned int cmd, unsigned long arg)
 {
-	int ret;
-
-	lock_kernel();
-	ret = dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
-	unlock_kernel();
-
-	return ret;
+	return dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
 }
 
 
@@ -1628,6 +1622,7 @@
 	.open = dvb_ca_en50221_io_open,
 	.release = dvb_ca_en50221_io_release,
 	.poll = dvb_ca_en50221_io_poll,
+	.llseek = noop_llseek,
 };
 
 static struct dvb_device dvbdev_ca = {
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 4d45b7d..970c9b8 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -2034,7 +2034,8 @@
 	.unlocked_ioctl	= dvb_generic_ioctl,
 	.poll		= dvb_frontend_poll,
 	.open		= dvb_frontend_open,
-	.release	= dvb_frontend_release
+	.release	= dvb_frontend_release,
+	.llseek		= noop_llseek,
 };
 
 int dvb_register_frontend(struct dvb_adapter* dvb,
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 6c3a8a0..4df42aa 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -59,7 +59,6 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/dvb/net.h>
-#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <asm/uaccess.h>
 #include <linux/crc32.h>
@@ -1445,13 +1444,7 @@
 static long dvb_net_ioctl(struct file *file,
 	      unsigned int cmd, unsigned long arg)
 {
-	int ret;
-
-	lock_kernel();
-	ret = dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
-	unlock_kernel();
-
-	return ret;
+	return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
 }
 
 static int dvb_net_close(struct inode *inode, struct file *file)
@@ -1475,6 +1468,7 @@
 	.unlocked_ioctl = dvb_net_ioctl,
 	.open =	dvb_generic_open,
 	.release = dvb_net_close,
+	.llseek = noop_llseek,
 };
 
 static struct dvb_device dvbdev_net = {
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index b915c39..f732877 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -32,9 +32,9 @@
 #include <linux/fs.h>
 #include <linux/cdev.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include "dvbdev.h"
 
+static DEFINE_MUTEX(dvbdev_mutex);
 static int dvbdev_debug;
 
 module_param(dvbdev_debug, int, 0644);
@@ -68,7 +68,7 @@
 {
 	struct dvb_device *dvbdev;
 
-	lock_kernel();
+	mutex_lock(&dvbdev_mutex);
 	down_read(&minor_rwsem);
 	dvbdev = dvb_minors[iminor(inode)];
 
@@ -91,12 +91,12 @@
 		}
 		fops_put(old_fops);
 		up_read(&minor_rwsem);
-		unlock_kernel();
+		mutex_unlock(&dvbdev_mutex);
 		return err;
 	}
 fail:
 	up_read(&minor_rwsem);
-	unlock_kernel();
+	mutex_unlock(&dvbdev_mutex);
 	return -ENODEV;
 }
 
@@ -105,6 +105,7 @@
 {
 	.owner =	THIS_MODULE,
 	.open =		dvb_device_open,
+	.llseek =	noop_llseek,
 };
 
 static struct cdev dvb_device_cdev;
@@ -158,7 +159,6 @@
 		       unsigned int cmd, unsigned long arg)
 {
 	struct dvb_device *dvbdev = file->private_data;
-	int ret;
 
 	if (!dvbdev)
 		return -ENODEV;
@@ -166,11 +166,7 @@
 	if (!dvbdev->kernel_ioctl)
 		return -EINVAL;
 
-	lock_kernel();
-	ret = dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
-	unlock_kernel();
-
-	return ret;
+	return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
 }
 EXPORT_SYMBOL(dvb_generic_ioctl);
 
@@ -421,8 +417,10 @@
 	}
 
 	/* call driver */
+	mutex_lock(&dvbdev_mutex);
 	if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
 		err = -EINVAL;
+	mutex_unlock(&dvbdev_mutex);
 
 	if (err < 0)
 		goto out;
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index fe81834..48397f1 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -673,9 +673,6 @@
 			else
 				dev->props.rc.core.bulk_mode = false;
 
-			/* Need a higher delay, to avoid wrong repeat */
-			dev->rc_input_dev->rep[REP_DELAY] = 500;
-
 			dib0700_rc_setup(dev);
 
 			return 0;
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index f634d2e..e06acd1 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -940,6 +940,58 @@
 	return adap->fe == NULL ? -ENODEV : 0;
 }
 
+/* STK7770P */
+static struct dib7000p_config dib7770p_dib7000p_config = {
+	.output_mpeg2_in_188_bytes = 1,
+
+	.agc_config_count = 1,
+	.agc = &dib7070_agc_config,
+	.bw  = &dib7070_bw_config_12_mhz,
+	.tuner_is_baseband = 1,
+	.spur_protect = 1,
+
+	.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+	.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+	.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+	.hostbus_diversity = 1,
+	.enable_current_mirror = 1,
+	.disable_sample_and_hold = 0,
+};
+
+static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+	if (p->idVendor  == cpu_to_le16(USB_VID_PINNACLE) &&
+	    p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
+		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+	else
+		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+	msleep(10);
+	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+	dib0700_ctrl_clock(adap->dev, 72, 1);
+
+	msleep(10);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+	msleep(10);
+	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+				     &dib7770p_dib7000p_config) != 0) {
+		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+		    __func__);
+		return -ENODEV;
+	}
+
+	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+		&dib7770p_dib7000p_config);
+	return adap->fe == NULL ? -ENODEV : 0;
+}
+
 /* DIB807x generic */
 static struct dibx000_agc_config dib807x_agc_config[2] = {
 	{
@@ -1781,7 +1833,7 @@
 /* 60 */{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_CINERGY_T_XXS_2) },
 	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK807XPVR) },
 	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK807XP) },
-	{ USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) },
+	{ USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x000, 0x3f00) },
 	{ USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) },
 /* 65 */{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV73ESE) },
 	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV282E) },
@@ -2406,7 +2458,7 @@
 				.pid_filter_count = 32,
 				.pid_filter       = stk70x0p_pid_filter,
 				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7070p_frontend_attach,
+				.frontend_attach  = stk7770p_frontend_attach,
 				.tuner_attach     = dib7770p_tuner_attach,
 
 				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c
index 6b22ec6..f896337 100644
--- a/drivers/media/dvb/dvb-usb/opera1.c
+++ b/drivers/media/dvb/dvb-usb/opera1.c
@@ -483,9 +483,7 @@
 		}
 	}
 	kfree(p);
-	if (fw) {
-		release_firmware(fw);
-	}
+	release_firmware(fw);
 	return ret;
 }
 
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c
index d3c2cf6..8ffb565 100644
--- a/drivers/media/dvb/firewire/firedtv-ci.c
+++ b/drivers/media/dvb/firewire/firedtv-ci.c
@@ -220,6 +220,7 @@
 	.open		= dvb_generic_open,
 	.release	= dvb_generic_release,
 	.poll		= fdtv_ca_io_poll,
+	.llseek		= noop_llseek,
 };
 
 static struct dvb_device fdtv_ca = {
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
index 2e28b97..3aed0d4 100644
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -260,6 +260,9 @@
 
 //	dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
 
+	reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4;
+	reg_908 |= (state->cfg.enable_current_mirror & 1) << 7;
+
 	dib7000p_write_word(state, 908, reg_908);
 	dib7000p_write_word(state, 909, reg_909);
 }
@@ -778,7 +781,10 @@
 		default:
 		case GUARD_INTERVAL_1_32: value *= 1; break;
 	}
-	state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
+	if (state->cfg.diversity_delay == 0)
+		state->div_sync_wait = (value * 3) / 2 + 48; // add 50% SFN margin + compensate for one DVSY-fifo
+	else
+		state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay; // add 50% SFN margin + compensate for one DVSY-fifo
 
 	/* deactive the possibility of diversity reception if extended interleaver */
 	state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K;
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
index 805dd13..da17345 100644
--- a/drivers/media/dvb/frontends/dib7000p.h
+++ b/drivers/media/dvb/frontends/dib7000p.h
@@ -33,6 +33,11 @@
 	int (*agc_control) (struct dvb_frontend *, u8 before);
 
 	u8 output_mode;
+	u8 disable_sample_and_hold : 1;
+
+	u8 enable_current_mirror : 1;
+	u8 diversity_delay;
+
 };
 
 #define DEFAULT_DIB7000P_I2C_ADDRESS 18
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
index d93468c..ff3b0fa 100644
--- a/drivers/media/dvb/siano/smscoreapi.c
+++ b/drivers/media/dvb/siano/smscoreapi.c
@@ -1098,33 +1098,26 @@
  *
  * @return pointer to descriptor on success, NULL on error.
  */
-struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
+
+struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
 {
 	struct smscore_buffer_t *cb = NULL;
 	unsigned long flags;
 
-	DEFINE_WAIT(wait);
-
 	spin_lock_irqsave(&coredev->bufferslock, flags);
-
-	/* This function must return a valid buffer, since the buffer list is
-	 * finite, we check that there is an available buffer, if not, we wait
-	 * until such buffer become available.
-	 */
-
-	prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE);
-	if (list_empty(&coredev->buffers)) {
-		spin_unlock_irqrestore(&coredev->bufferslock, flags);
-		schedule();
-		spin_lock_irqsave(&coredev->bufferslock, flags);
+	if (!list_empty(&coredev->buffers)) {
+		cb = (struct smscore_buffer_t *) coredev->buffers.next;
+		list_del(&cb->entry);
 	}
-
-	finish_wait(&coredev->buffer_mng_waitq, &wait);
-
-	cb = (struct smscore_buffer_t *) coredev->buffers.next;
-	list_del(&cb->entry);
-
 	spin_unlock_irqrestore(&coredev->bufferslock, flags);
+	return cb;
+}
+
+struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
+{
+	struct smscore_buffer_t *cb = NULL;
+
+	wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev)));
 
 	return cb;
 }
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index a6be529..893fbc5 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -730,6 +730,7 @@
 	.unlocked_ioctl	= dvb_generic_ioctl,
 	.open		= dvb_generic_open,
 	.release	= dvb_generic_release,
+	.llseek		= noop_llseek,
 };
 
 static struct dvb_device dvbdev_osd = {
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 13efba9..6ef3996 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -1521,6 +1521,7 @@
 	.open		= dvb_video_open,
 	.release	= dvb_video_release,
 	.poll		= dvb_video_poll,
+	.llseek		= noop_llseek,
 };
 
 static struct dvb_device dvbdev_video = {
@@ -1539,6 +1540,7 @@
 	.open		= dvb_audio_open,
 	.release	= dvb_audio_release,
 	.poll		= dvb_audio_poll,
+	.llseek		= noop_llseek,
 };
 
 static struct dvb_device dvbdev_audio = {
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
index 4eba35a..43f61f2 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
@@ -353,6 +353,7 @@
 	.open		= dvb_ca_open,
 	.release	= dvb_generic_release,
 	.poll		= dvb_ca_poll,
+	.llseek		= default_llseek,
 };
 
 static struct dvb_device dvbdev_ca = {
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index b070e88..908f272 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -312,6 +312,7 @@
 static const struct file_operations av7110_ir_proc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= av7110_ir_proc_write,
+	.llseek		= noop_llseek,
 };
 
 /* interrupt handler */
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c
index 67a4ec8..4ce541a 100644
--- a/drivers/media/radio/si470x/radio-si470x-i2c.c
+++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
@@ -395,7 +395,7 @@
 	radio->registers[POWERCFG] = POWERCFG_ENABLE;
 	if (si470x_set_register(radio, POWERCFG) < 0) {
 		retval = -EIO;
-		goto err_all;
+		goto err_video;
 	}
 	msleep(110);
 
diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile
index 755dd0c..6f2b573 100644
--- a/drivers/media/video/cx231xx/Makefile
+++ b/drivers/media/video/cx231xx/Makefile
@@ -11,4 +11,5 @@
 EXTRA_CFLAGS += -Idrivers/media/common/tuners
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb
 
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
index 6bdc0ef..f2a4900 100644
--- a/drivers/media/video/cx231xx/cx231xx-cards.c
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -32,6 +32,7 @@
 #include <media/v4l2-chip-ident.h>
 
 #include <media/cx25840.h>
+#include "dvb-usb-ids.h"
 #include "xc5000.h"
 
 #include "cx231xx.h"
@@ -175,6 +176,8 @@
 	 .driver_info = CX231XX_BOARD_CNXT_RDE_250},
 	{USB_DEVICE(0x0572, 0x58A1),
 	 .driver_info = CX231XX_BOARD_CNXT_RDU_250},
+	{USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000,0x4fff),
+	 .driver_info = CX231XX_BOARD_UNKNOWN},
 	{},
 };
 
@@ -226,14 +229,16 @@
 		     dev->board.name, dev->model);
 
 	/* set the direction for GPIO pins */
-	cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
-	cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
-	cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
+	if (dev->board.tuner_gpio) {
+		cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
+		cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
+		cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
 
-	/* request some modules if any required */
+		/* request some modules if any required */
 
-	/* reset the Tuner */
-	cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+		/* reset the Tuner */
+		cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+	}
 
 	/* set the mode to Analog mode initially */
 	cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 86ca8c2..f5a3e74 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -1996,7 +1996,7 @@
 
 		state->volume = v4l2_ctrl_new_std(&state->hdl,
 			&cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
-			0, 65335, 65535 / 100, default_volume);
+			0, 65535, 65535 / 100, default_volume);
 		state->mute = v4l2_ctrl_new_std(&state->hdl,
 			&cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_MUTE,
 			0, 1, 1, 0);
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 99dbae1..0fa85cb 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -17,7 +17,7 @@
 
 config VIDEO_CX88_ALSA
 	tristate "Conexant 2388x DMA audio support"
-	depends on VIDEO_CX88 && SND && EXPERIMENTAL
+	depends on VIDEO_CX88 && SND
 	select SND_PCM
 	---help---
 	  This is a video4linux driver for direct (DMA) audio on
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index 5b176bd..f3e25e9 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -32,7 +32,6 @@
 #include <linux/list.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
@@ -621,7 +620,6 @@
 	if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
 		return -EIO;
 
-	lock_kernel();
 	s = &dabusb[devnum - DABUSB_MINOR];
 
 	dbg("dabusb_open");
@@ -630,21 +628,17 @@
 	while (!s->usbdev || s->opened) {
 		mutex_unlock(&s->mutex);
 
-		if (file->f_flags & O_NONBLOCK) {
+		if (file->f_flags & O_NONBLOCK)
 			return -EBUSY;
-		}
 		msleep_interruptible(500);
 
-		if (signal_pending (current)) {
-			unlock_kernel();
+		if (signal_pending (current))
 			return -EAGAIN;
-		}
 		mutex_lock(&s->mutex);
 	}
 	if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
 		mutex_unlock(&s->mutex);
 		dev_err(&s->usbdev->dev, "set_interface failed\n");
-		unlock_kernel();
 		return -EINVAL;
 	}
 	s->opened = 1;
@@ -654,7 +648,6 @@
 	file->private_data = s;
 
 	r = nonseekable_open(inode, file);
-	unlock_kernel();
 	return r;
 }
 
@@ -689,17 +682,13 @@
 
 	dbg("dabusb_ioctl");
 
-	lock_kernel();
-	if (s->remove_pending) {
-		unlock_kernel();
+	if (s->remove_pending)
 		return -EIO;
-	}
 
 	mutex_lock(&s->mutex);
 
 	if (!s->usbdev) {
 		mutex_unlock(&s->mutex);
-		unlock_kernel();
 		return -EIO;
 	}
 
@@ -735,7 +724,6 @@
 		break;
 	}
 	mutex_unlock(&s->mutex);
-	unlock_kernel();
 	return ret;
 }
 
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index b984610..78abc1c 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -223,6 +223,7 @@
 		usb_rcvintpipe(dev, ep->bEndpointAddress),
 		buffer, buffer_len,
 		int_irq, (void *)gspca_dev, interval);
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	gspca_dev->int_urb = urb;
 	ret = usb_submit_urb(urb, GFP_KERNEL);
 	if (ret < 0) {
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
index 83a718f..9052d57 100644
--- a/drivers/media/video/gspca/sn9c20x.c
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -2357,8 +2357,7 @@
 			    (data[33] << 10);
 		avg_lum >>= 9;
 		atomic_set(&sd->avg_lum, avg_lum);
-		gspca_frame_add(gspca_dev, LAST_PACKET,
-				data, len);
+		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
 		return;
 	}
 	if (gspca_dev->last_packet_type == LAST_PACKET) {
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index be03a71..f0316d0 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -466,6 +466,8 @@
 			struct fb_vblank vblank;
 			u32 trace;
 
+			memset(&vblank, 0, sizeof(struct fb_vblank));
+
 			vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
 					FB_VBLANK_HAVE_VSYNC;
 			trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c
index 4525335..a7210d9 100644
--- a/drivers/media/video/mem2mem_testdev.c
+++ b/drivers/media/video/mem2mem_testdev.c
@@ -239,7 +239,7 @@
 		return -EFAULT;
 	}
 
-	if (in_buf->vb.size < out_buf->vb.size) {
+	if (in_buf->vb.size > out_buf->vb.size) {
 		v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n");
 		return -EINVAL;
 	}
@@ -1014,6 +1014,7 @@
 	v4l2_m2m_release(dev->m2m_dev);
 	del_timer_sync(&dev->timer);
 	video_unregister_device(dev->vfd);
+	video_device_release(dev->vfd);
 	v4l2_device_unregister(&dev->v4l2_dev);
 	kfree(dev);
 
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 758a4db..c71af4e 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -447,6 +447,9 @@
 	dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
 		__func__, rect.left, rect.top, rect.width, rect.height);
 
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
 	ret = mt9m111_make_rect(client, &rect);
 	if (!ret)
 		mt9m111->rect = rect;
@@ -466,12 +469,14 @@
 
 static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 {
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
 	a->bounds.left			= MT9M111_MIN_DARK_COLS;
 	a->bounds.top			= MT9M111_MIN_DARK_ROWS;
 	a->bounds.width			= MT9M111_MAX_WIDTH;
 	a->bounds.height		= MT9M111_MAX_HEIGHT;
 	a->defrect			= a->bounds;
-	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	a->pixelaspect.numerator	= 1;
 	a->pixelaspect.denominator	= 1;
 
@@ -487,6 +492,7 @@
 	mf->width	= mt9m111->rect.width;
 	mf->height	= mt9m111->rect.height;
 	mf->code	= mt9m111->fmt->code;
+	mf->colorspace	= mt9m111->fmt->colorspace;
 	mf->field	= V4L2_FIELD_NONE;
 
 	return 0;
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index e7cd23c..b48473c 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -402,9 +402,6 @@
 		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
 			return -EINVAL;
 		break;
-	case 0:
-		/* No format change, only geometry */
-		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
index 66ff174..b6ea672 100644
--- a/drivers/media/video/mx2_camera.c
+++ b/drivers/media/video/mx2_camera.c
@@ -378,6 +378,9 @@
 
 	spin_lock_irqsave(&pcdev->lock, flags);
 
+	if (*fb_active == NULL)
+		goto out;
+
 	vb = &(*fb_active)->vb;
 	dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
 		vb, vb->baddr, vb->bsize);
@@ -402,6 +405,7 @@
 
 	*fb_active = buf;
 
+out:
 	spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
index 1b992b8..55ea914 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -513,7 +513,7 @@
 			if (ret >= 0) {
 				ret = pvr2_ctrl_range_check(cptr,*valptr);
 			}
-			if (maskptr) *maskptr = ~0;
+			*maskptr = ~0;
 		} else if (cptr->info->type == pvr2_ctl_bool) {
 			ret = parse_token(ptr,len,valptr,boolNames,
 					  ARRAY_SIZE(boolNames));
@@ -522,7 +522,7 @@
 			} else if (ret == 0) {
 				*valptr = (*valptr & 1) ? !0 : 0;
 			}
-			if (maskptr) *maskptr = 1;
+			*maskptr = 1;
 		} else if (cptr->info->type == pvr2_ctl_enum) {
 			ret = parse_token(
 				ptr,len,valptr,
@@ -531,7 +531,7 @@
 			if (ret >= 0) {
 				ret = pvr2_ctrl_range_check(cptr,*valptr);
 			}
-			if (maskptr) *maskptr = ~0;
+			*maskptr = ~0;
 		} else if (cptr->info->type == pvr2_ctl_bitmask) {
 			ret = parse_tlist(
 				ptr,len,maskptr,valptr,
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index b151c7b..6961c55 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -393,6 +393,37 @@
 	dbg("ctx->out_order_1p= %d", ctx->out_order_1p);
 }
 
+static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
+{
+	struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
+
+	f->dma_offset.y_h = f->offs_h;
+	if (!variant->pix_hoff)
+		f->dma_offset.y_h *= (f->fmt->depth >> 3);
+
+	f->dma_offset.y_v = f->offs_v;
+
+	f->dma_offset.cb_h = f->offs_h;
+	f->dma_offset.cb_v = f->offs_v;
+
+	f->dma_offset.cr_h = f->offs_h;
+	f->dma_offset.cr_v = f->offs_v;
+
+	if (!variant->pix_hoff) {
+		if (f->fmt->planes_cnt == 3) {
+			f->dma_offset.cb_h >>= 1;
+			f->dma_offset.cr_h >>= 1;
+		}
+		if (f->fmt->color == S5P_FIMC_YCBCR420) {
+			f->dma_offset.cb_v >>= 1;
+			f->dma_offset.cr_v >>= 1;
+		}
+	}
+
+	dbg("in_offset: color= %d, y_h= %d, y_v= %d",
+	    f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v);
+}
+
 /**
  * fimc_prepare_config - check dimensions, operation and color mode
  *			 and pre-calculate offset and the scaling coefficients.
@@ -406,7 +437,6 @@
 {
 	struct fimc_frame *s_frame, *d_frame;
 	struct fimc_vid_buffer *buf = NULL;
-	struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
 	int ret = 0;
 
 	s_frame = &ctx->s_frame;
@@ -419,61 +449,16 @@
 			swap(d_frame->width, d_frame->height);
 		}
 
-		/* Prepare the output offset ratios for scaler. */
-		d_frame->dma_offset.y_h = d_frame->offs_h;
-		if (!variant->pix_hoff)
-			d_frame->dma_offset.y_h *= (d_frame->fmt->depth >> 3);
+		/* Prepare the DMA offset ratios for scaler. */
+		fimc_prepare_dma_offset(ctx, &ctx->s_frame);
+		fimc_prepare_dma_offset(ctx, &ctx->d_frame);
 
-		d_frame->dma_offset.y_v = d_frame->offs_v;
-
-		d_frame->dma_offset.cb_h = d_frame->offs_h;
-		d_frame->dma_offset.cb_v = d_frame->offs_v;
-
-		d_frame->dma_offset.cr_h = d_frame->offs_h;
-		d_frame->dma_offset.cr_v = d_frame->offs_v;
-
-		if (!variant->pix_hoff && d_frame->fmt->planes_cnt == 3) {
-			d_frame->dma_offset.cb_h >>= 1;
-			d_frame->dma_offset.cb_v >>= 1;
-			d_frame->dma_offset.cr_h >>= 1;
-			d_frame->dma_offset.cr_v >>= 1;
-		}
-
-		dbg("out offset: color= %d, y_h= %d, y_v= %d",
-			d_frame->fmt->color,
-			d_frame->dma_offset.y_h, d_frame->dma_offset.y_v);
-
-		/* Prepare the input offset ratios for scaler. */
-		s_frame->dma_offset.y_h = s_frame->offs_h;
-		if (!variant->pix_hoff)
-			s_frame->dma_offset.y_h *= (s_frame->fmt->depth >> 3);
-		s_frame->dma_offset.y_v = s_frame->offs_v;
-
-		s_frame->dma_offset.cb_h = s_frame->offs_h;
-		s_frame->dma_offset.cb_v = s_frame->offs_v;
-
-		s_frame->dma_offset.cr_h = s_frame->offs_h;
-		s_frame->dma_offset.cr_v = s_frame->offs_v;
-
-		if (!variant->pix_hoff && s_frame->fmt->planes_cnt == 3) {
-			s_frame->dma_offset.cb_h >>= 1;
-			s_frame->dma_offset.cb_v >>= 1;
-			s_frame->dma_offset.cr_h >>= 1;
-			s_frame->dma_offset.cr_v >>= 1;
-		}
-
-		dbg("in offset: color= %d, y_h= %d, y_v= %d",
-			s_frame->fmt->color, s_frame->dma_offset.y_h,
-			s_frame->dma_offset.y_v);
-
-		fimc_set_yuv_order(ctx);
-
-		/* Check against the scaler ratio. */
 		if (s_frame->height > (SCALER_MAX_VRATIO * d_frame->height) ||
 		    s_frame->width > (SCALER_MAX_HRATIO * d_frame->width)) {
 			err("out of scaler range");
 			return -EINVAL;
 		}
+		fimc_set_yuv_order(ctx);
 	}
 
 	/* Input DMA mode is not allowed when the scaler is disabled. */
@@ -822,7 +807,8 @@
 	} else {
 		v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
 			 "Wrong buffer/video queue type (%d)\n", f->type);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto s_fmt_out;
 	}
 
 	pix = &f->fmt.pix;
@@ -1414,8 +1400,10 @@
 	}
 
 	fimc->work_queue = create_workqueue(dev_name(&fimc->pdev->dev));
-	if (!fimc->work_queue)
+	if (!fimc->work_queue) {
+		ret = -ENOMEM;
 		goto err_irq;
+	}
 
 	ret = fimc_register_m2m_device(fimc);
 	if (ret)
@@ -1492,6 +1480,7 @@
 };
 
 static struct samsung_fimc_variant fimc01_variant_s5pv210 = {
+	.pix_hoff	= 1,
 	.has_inp_rot	= 1,
 	.has_out_rot	= 1,
 	.min_inp_pixsize = 16,
@@ -1506,6 +1495,7 @@
 };
 
 static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
+	.pix_hoff	 = 1,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 32,
 
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index ec697fc..bb8d83d 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -4323,13 +4323,13 @@
 	},
 	[SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
 		/*       Beholder Intl. Ltd. 2008      */
-		/*Dmitry Belimov <d.belimov@gmail.com> */
-		.name           = "Beholder BeholdTV Columbus TVFM",
+		/* Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV Columbus TV/FM",
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_ALPS_TSBE5_PAL,
-		.radio_type     = UNSET,
-		.tuner_addr     = ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr     = 0xc2 >> 1,
+		.radio_addr     = 0xc0 >> 1,
 		.tda9887_conf   = TDA9887_PRESENT,
 		.gpiomask       = 0x000A8004,
 		.inputs         = {{
diff --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/video/saa7164/saa7164-buffer.c
index 5713f3a..ddd25d3 100644
--- a/drivers/media/video/saa7164/saa7164-buffer.c
+++ b/drivers/media/video/saa7164/saa7164-buffer.c
@@ -136,10 +136,11 @@
 int saa7164_buffer_dealloc(struct saa7164_tsport *port,
 	struct saa7164_buffer *buf)
 {
-	struct saa7164_dev *dev = port->dev;
+	struct saa7164_dev *dev;
 
-	if ((buf == 0) || (port == 0))
+	if (!buf || !port)
 		return SAA_ERR_BAD_PARAMETER;
+	dev = port->dev;
 
 	dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n", __func__, buf);
 
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 8bdd940..2ac85d8 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -486,6 +486,12 @@
 			    max(frame->dwFrameInterval[0],
 				frame->dwDefaultFrameInterval));
 
+		if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) {
+			frame->bFrameIntervalType = 1;
+			frame->dwFrameInterval[0] =
+				frame->dwDefaultFrameInterval;
+		}
+
 		uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",
 			frame->wWidth, frame->wHeight,
 			10000000/frame->dwDefaultFrameInterval,
@@ -2026,6 +2032,15 @@
 	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0 },
+	/* Chicony CNF7129 (Asus EEE 100HE) */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x04f2,
+	  .idProduct		= 0xb071,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_RESTRICT_FRAME_RATE },
 	/* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2091,6 +2106,15 @@
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
 				| UVC_QUIRK_PROBE_DEF },
+	/* IMC Networks (Medion Akoya) */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x13d3,
+	  .idProduct		= 0x5103,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
 	/* Syntek (HP Spartan) */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index bdacf3b..892e0e5 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -182,6 +182,7 @@
 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT	0x00000020
 #define UVC_QUIRK_FIX_BANDWIDTH		0x00000080
 #define UVC_QUIRK_PROBE_DEF		0x00000100
+#define UVC_QUIRK_RESTRICT_FRAME_RATE	0x00000200
 
 /* Format flags */
 #define UVC_FMT_FLAG_COMPRESSED		0x00000001
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index 073f013..86294ed3 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -193,17 +193,24 @@
 struct video_code32 {
 	char		loadwhat[16];	/* name or tag of file being passed */
 	compat_int_t	datasize;
-	unsigned char	*data;
+	compat_uptr_t	data;
 };
 
-static int get_microcode32(struct video_code *kp, struct video_code32 __user *up)
+static struct video_code __user *get_microcode32(struct video_code32 *kp)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
-		copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
-		get_user(kp->datasize, &up->datasize) ||
-		copy_from_user(kp->data, up->data, up->datasize))
-			return -EFAULT;
-	return 0;
+	struct video_code __user *up;
+
+	up = compat_alloc_user_space(sizeof(*up));
+
+	/*
+	 * NOTE! We don't actually care if these fail. If the
+	 * user address is invalid, the native ioctl will do
+	 * the error handling for us
+	 */
+	(void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat));
+	(void) put_user(kp->datasize, &up->datasize);
+	(void) put_user(compat_ptr(kp->data), &up->data);
+	return up;
 }
 
 #define VIDIOCGTUNER32		_IOWR('v', 4, struct video_tuner32)
@@ -739,7 +746,7 @@
 		struct video_tuner vt;
 		struct video_buffer vb;
 		struct video_window vw;
-		struct video_code vc;
+		struct video_code32 vc;
 		struct video_audio va;
 #endif
 		struct v4l2_format v2f;
@@ -818,8 +825,11 @@
 		break;
 
 	case VIDIOCSMICROCODE:
-		err = get_microcode32(&karg.vc, up);
-		compatible_arg = 0;
+		/* Copy the 32-bit "video_code32" to kernel space */
+		if (copy_from_user(&karg.vc, up, sizeof(karg.vc)))
+			return -EFAULT;
+		/* Convert the 32-bit version to a 64-bit version in user space */
+		up = get_microcode32(&karg.vc);
 		break;
 
 	case VIDIOCSFREQ:
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c
index 372b87e..6ff9e4b 100644
--- a/drivers/media/video/videobuf-dma-contig.c
+++ b/drivers/media/video/videobuf-dma-contig.c
@@ -393,8 +393,10 @@
 	}
 
 	/* read() method */
-	dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle);
-	mem->vaddr = NULL;
+	if (mem->vaddr) {
+		dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle);
+		mem->vaddr = NULL;
+	}
 }
 EXPORT_SYMBOL_GPL(videobuf_dma_contig_free);
 
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c
index 06f9a9c..2ad0bc2 100644
--- a/drivers/media/video/videobuf-dma-sg.c
+++ b/drivers/media/video/videobuf-dma-sg.c
@@ -94,7 +94,7 @@
  * must free the memory.
  */
 static struct scatterlist *videobuf_pages_to_sg(struct page **pages,
-						int nr_pages, int offset)
+					int nr_pages, int offset, size_t size)
 {
 	struct scatterlist *sglist;
 	int i;
@@ -110,12 +110,14 @@
 		/* DMA to highmem pages might not work */
 		goto highmem;
 	sg_set_page(&sglist[0], pages[0], PAGE_SIZE - offset, offset);
+	size -= PAGE_SIZE - offset;
 	for (i = 1; i < nr_pages; i++) {
 		if (NULL == pages[i])
 			goto nopage;
 		if (PageHighMem(pages[i]))
 			goto highmem;
-		sg_set_page(&sglist[i], pages[i], PAGE_SIZE, 0);
+		sg_set_page(&sglist[i], pages[i], min(PAGE_SIZE, size), 0);
+		size -= min(PAGE_SIZE, size);
 	}
 	return sglist;
 
@@ -170,7 +172,8 @@
 
 	first = (data          & PAGE_MASK) >> PAGE_SHIFT;
 	last  = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT;
-	dma->offset   = data & ~PAGE_MASK;
+	dma->offset = data & ~PAGE_MASK;
+	dma->size = size;
 	dma->nr_pages = last-first+1;
 	dma->pages = kmalloc(dma->nr_pages * sizeof(struct page *), GFP_KERNEL);
 	if (NULL == dma->pages)
@@ -252,7 +255,7 @@
 
 	if (dma->pages) {
 		dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages,
-						   dma->offset);
+						   dma->offset, dma->size);
 	}
 	if (dma->vaddr) {
 		dma->sglist = videobuf_vmalloc_to_sg(dma->vaddr,
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index d3f1a08..02362ec 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -18,11 +18,12 @@
 #include <linux/kthread.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/memstick.h>
 
 #define DRIVER_NAME "mspro_block"
 
+static DEFINE_MUTEX(mspro_block_mutex);
 static int major;
 module_param(major, int, 0644);
 
@@ -180,7 +181,7 @@
 	struct mspro_block_data *msb = disk->private_data;
 	int rc = -ENXIO;
 
-	lock_kernel();
+	mutex_lock(&mspro_block_mutex);
 	mutex_lock(&mspro_block_disk_lock);
 
 	if (msb && msb->card) {
@@ -192,7 +193,7 @@
 	}
 
 	mutex_unlock(&mspro_block_disk_lock);
-	unlock_kernel();
+	mutex_unlock(&mspro_block_mutex);
 
 	return rc;
 }
@@ -225,9 +226,9 @@
 static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode)
 {
 	int ret;
-	lock_kernel();
+	mutex_lock(&mspro_block_mutex);
 	ret = mspro_block_disk_release(disk);
-	unlock_kernel();
+	mutex_unlock(&mspro_block_mutex);
 	return ret;
 }
 
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 6837a8e..3e57b61 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -5945,8 +5945,10 @@
 		goto out;
 
 	mem = kmalloc(iocpage2sz, GFP_KERNEL);
-	if (!mem)
+	if (!mem) {
+		rc = -ENOMEM;
 		goto out;
+	}
 
 	memcpy(mem, (u8 *)pIoc2, iocpage2sz);
 	ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index d8ddfdf..a3856ed 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -54,7 +54,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>	/* for mdelay */
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 
 #include <asm/io.h>
@@ -83,6 +83,7 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
+static DEFINE_MUTEX(mpctl_mutex);
 static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS;
 static u8 mptctl_taskmgmt_id = MPT_MAX_PROTOCOL_DRIVERS;
 
@@ -601,12 +602,12 @@
 	MPT_ADAPTER	*ioc;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&mpctl_mutex);
 	list_for_each_entry(ioc, &ioc_list, list)
 		ioc->aen_event_read_flag=0;
 
 	ret = fasync_helper(fd, filep, mode, &async_queue);
-	unlock_kernel();
+	mutex_unlock(&mpctl_mutex);
 	return ret;
 }
 
@@ -698,9 +699,9 @@
 mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&mpctl_mutex);
 	ret = __mptctl_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&mpctl_mutex);
 	return ret;
 }
 
@@ -2926,7 +2927,7 @@
 static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&mpctl_mutex);
 	switch (cmd) {
 	case MPTIOCINFO:
 	case MPTIOCINFO1:
@@ -2951,7 +2952,7 @@
 		ret = -ENOIOCTLCMD;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&mpctl_mutex);
 	return ret;
 }
 
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index f0f1e66..f87a9d4 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -53,7 +53,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2o.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <linux/mempool.h>
 
@@ -69,6 +69,7 @@
 #define OSM_VERSION	"1.325"
 #define OSM_DESCRIPTION	"I2O Block Device OSM"
 
+static DEFINE_MUTEX(i2o_block_mutex);
 static struct i2o_driver i2o_block_driver;
 
 /* global Block OSM request mempool */
@@ -578,7 +579,7 @@
 	if (!dev->i2o_dev)
 		return -ENODEV;
 
-	lock_kernel();
+	mutex_lock(&i2o_block_mutex);
 	if (dev->power > 0x1f)
 		i2o_block_device_power(dev, 0x02);
 
@@ -587,7 +588,7 @@
 	i2o_block_device_lock(dev->i2o_dev, -1);
 
 	osm_debug("Ready.\n");
-	unlock_kernel();
+	mutex_unlock(&i2o_block_mutex);
 
 	return 0;
 };
@@ -618,7 +619,7 @@
 	if (!dev->i2o_dev)
 		return 0;
 
-	lock_kernel();
+	mutex_lock(&i2o_block_mutex);
 	i2o_block_device_flush(dev->i2o_dev);
 
 	i2o_block_device_unlock(dev->i2o_dev, -1);
@@ -629,7 +630,7 @@
 		operation = 0x24;
 
 	i2o_block_device_power(dev, operation);
-	unlock_kernel();
+	mutex_unlock(&i2o_block_mutex);
 
 	return 0;
 }
@@ -664,7 +665,7 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	lock_kernel();
+	mutex_lock(&i2o_block_mutex);
 	switch (cmd) {
 	case BLKI2OGRSTRAT:
 		ret = put_user(dev->rcache, (int __user *)arg);
@@ -688,7 +689,7 @@
 		ret = 0;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&i2o_block_mutex);
 
 	return ret;
 };
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 068ba07..7d3cc57 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -31,7 +31,7 @@
  */
 
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 #include <linux/slab.h>
 
@@ -41,6 +41,7 @@
 
 #define SG_TABLESIZE		30
 
+static DEFINE_MUTEX(i2o_cfg_mutex);
 static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long);
 
 static spinlock_t i2o_config_lock;
@@ -741,7 +742,7 @@
 				 unsigned long arg)
 {
 	int ret;
-	lock_kernel();
+	mutex_lock(&i2o_cfg_mutex);
 	switch (cmd) {
 	case I2OGETIOPS:
 		ret = i2o_cfg_ioctl(file, cmd, arg);
@@ -753,7 +754,7 @@
 		ret = -ENOIOCTLCMD;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&i2o_cfg_mutex);
 	return ret;
 }
 
@@ -981,7 +982,7 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&i2o_cfg_mutex);
 	switch (cmd) {
 	case I2OGETIOPS:
 		ret = i2o_cfg_getiops(arg);
@@ -1037,7 +1038,7 @@
 		osm_debug("unknown ioctl called!\n");
 		ret = -EINVAL;
 	}
-	unlock_kernel();
+	mutex_unlock(&i2o_cfg_mutex);
 	return ret;
 }
 
@@ -1051,7 +1052,7 @@
 	if (!tmp)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&i2o_cfg_mutex);
 	file->private_data = (void *)(i2o_cfg_info_id++);
 	tmp->fp = file;
 	tmp->fasync = NULL;
@@ -1065,7 +1066,7 @@
 	spin_lock_irqsave(&i2o_config_lock, flags);
 	open_files = tmp;
 	spin_unlock_irqrestore(&i2o_config_lock, flags);
-	unlock_kernel();
+	mutex_unlock(&i2o_cfg_mutex);
 
 	return 0;
 }
@@ -1076,14 +1077,14 @@
 	struct i2o_cfg_info *p;
 	int ret = -EBADF;
 
-	lock_kernel();
+	mutex_lock(&i2o_cfg_mutex);
 	for (p = open_files; p; p = p->next)
 		if (p->q_id == id)
 			break;
 
 	if (p)
 		ret = fasync_helper(fd, fp, on, &p->fasync);
-	unlock_kernel();
+	mutex_unlock(&i2o_cfg_mutex);
 	return ret;
 }
 
@@ -1093,7 +1094,7 @@
 	struct i2o_cfg_info *p, **q;
 	unsigned long flags;
 
-	lock_kernel();
+	mutex_lock(&i2o_cfg_mutex);
 	spin_lock_irqsave(&i2o_config_lock, flags);
 	for (q = &open_files; (p = *q) != NULL; q = &p->next) {
 		if (p->q_id == id) {
@@ -1103,7 +1104,7 @@
 		}
 	}
 	spin_unlock_irqrestore(&i2o_config_lock, flags);
-	unlock_kernel();
+	mutex_unlock(&i2o_cfg_mutex);
 
 	return 0;
 }
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 66379b4..b048ecc 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -583,6 +583,7 @@
 static const struct file_operations ab3100_get_set_reg_fops = {
 	.open = ab3100_get_set_reg_open_file,
 	.write = ab3100_get_set_reg,
+	.llseek = noop_llseek,
 };
 
 static struct dentry *ab3100_dir;
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c
index e1c8b62..01b6d58 100644
--- a/drivers/mfd/ab8500-spi.c
+++ b/drivers/mfd/ab8500-spi.c
@@ -83,6 +83,11 @@
 	struct ab8500 *ab8500;
 	int ret;
 
+	spi->bits_per_word = 24;
+	ret = spi_setup(spi);
+	if (ret < 0)
+		return ret;
+
 	ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
 	if (!ab8500)
 		return -ENOMEM;
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index 04028a9..428377a 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -429,24 +429,25 @@
 	irq_tsc = cache_tsc;
 	for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
 		irq_data = &max8925_irqs[i];
+		/* 1 -- disable, 0 -- enable */
 		switch (irq_data->mask_reg) {
 		case MAX8925_CHG_IRQ1_MASK:
-			irq_chg[0] &= irq_data->enable;
+			irq_chg[0] &= ~irq_data->enable;
 			break;
 		case MAX8925_CHG_IRQ2_MASK:
-			irq_chg[1] &= irq_data->enable;
+			irq_chg[1] &= ~irq_data->enable;
 			break;
 		case MAX8925_ON_OFF_IRQ1_MASK:
-			irq_on[0] &= irq_data->enable;
+			irq_on[0] &= ~irq_data->enable;
 			break;
 		case MAX8925_ON_OFF_IRQ2_MASK:
-			irq_on[1] &= irq_data->enable;
+			irq_on[1] &= ~irq_data->enable;
 			break;
 		case MAX8925_RTC_IRQ_MASK:
-			irq_rtc &= irq_data->enable;
+			irq_rtc &= ~irq_data->enable;
 			break;
 		case MAX8925_TSC_IRQ_MASK:
-			irq_tsc &= irq_data->enable;
+			irq_tsc &= ~irq_data->enable;
 			break;
 		default:
 			dev_err(chip->dev, "wrong IRQ\n");
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index 097f24d..b9fda70 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -78,7 +78,7 @@
 	u8	irq_lines;		/* number of supported irq lines */
 
 	/* SIR ignored -- set interrupt, for testing only */
-	struct irq_data {
+	struct sih_irq_data {
 		u8	isr_offset;
 		u8	imr_offset;
 	} mask[2];
@@ -810,7 +810,7 @@
 	twl4030_irq_chip = dummy_irq_chip;
 	twl4030_irq_chip.name = "twl4030";
 
-	twl4030_sih_irq_chip.ack = dummy_irq_chip.ack;
+	twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack;
 
 	for (i = irq_base; i < irq_end; i++) {
 		set_irq_chip_and_handler(i, &twl4030_irq_chip,
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c
index 7dabe4d..294183b 100644
--- a/drivers/mfd/wm831x-irq.c
+++ b/drivers/mfd/wm831x-irq.c
@@ -394,8 +394,13 @@
 
 	irq = irq - wm831x->irq_base;
 
-	if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11)
-		return -EINVAL;
+	if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) {
+		/* Ignore internal-only IRQs */
+		if (irq >= 0 && irq < WM831X_NUM_IRQS)
+			return 0;
+		else
+			return -EINVAL;
+	}
 
 	switch (type) {
 	case IRQ_TYPE_EDGE_BOTH:
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b743312..db2fbe2 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -248,15 +248,15 @@
 	  generic PIT, and are suitable for use as high-res timers.
 
 config HP_ILO
-	tristate "Channel interface driver for HP iLO/iLO2 processor"
+	tristate "Channel interface driver for the HP iLO processor"
 	depends on PCI
 	default n
 	help
 	  The channel interface driver allows applications to communicate
-	  with iLO/iLO2 management processors present on HP ProLiant
-	  servers.  Upon loading, the driver creates /dev/hpilo/dXccbN files,
-	  which can be used to gather data from the management processor,
-	  via read and write system calls.
+	  with iLO management processors present on HP ProLiant servers.
+	  Upon loading, the driver creates /dev/hpilo/dXccbN files, which
+	  can be used to gather data from the management processor, via
+	  read and write system calls.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called hpilo.
@@ -390,6 +390,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called bmp085.
 
+config PCH_PHUB
+	tristate "PCH Packet Hub of Intel Topcliff"
+	depends on PCI
+	help
+	  This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
+	  Intel Topcliff which is an IOH(Input/Output Hub) for x86 embedded
+	  processor. The Topcliff has MAC address and Option ROM data in SROM.
+	  This driver can access MAC address and Option ROM data in SROM.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called pch_phub.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 42eab95..9f2986b 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -35,3 +35,4 @@
 obj-y				+= cb710/
 obj-$(CONFIG_VMWARE_BALLOON)	+= vmw_balloon.o
 obj-$(CONFIG_ARM_CHARLCD)	+= arm-charlcd.o
+obj-$(CONFIG_PCH_PHUB)		+= pch_phub.o
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
index 714c6b4..d5f3a3f 100644
--- a/drivers/misc/bh1780gli.c
+++ b/drivers/misc/bh1780gli.c
@@ -190,7 +190,6 @@
 
 	ddata = i2c_get_clientdata(client);
 	sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group);
-	i2c_set_clientdata(client, NULL);
 	kfree(ddata);
 
 	return 0;
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
index 557a8c2..fffc227 100644
--- a/drivers/misc/hpilo.c
+++ b/drivers/misc/hpilo.c
@@ -1,5 +1,5 @@
 /*
- * Driver for HP iLO/iLO2 management processor.
+ * Driver for the HP iLO management processor.
  *
  * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
  *	David Altobelli <david.altobelli@hp.com>
@@ -640,6 +640,7 @@
 	.poll		= ilo_poll,
 	.open 		= ilo_open,
 	.release 	= ilo_close,
+	.llseek		= noop_llseek,
 };
 
 static irqreturn_t ilo_isr(int irq, void *data)
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index 8844a3f..af2497a 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -584,6 +584,7 @@
 	.release =	command_file_close,
 	.read =		command_file_read,
 	.write =	command_file_write,
+	.llseek =	generic_file_llseek,
 };
 
 static const struct file_operations event_fops = {
@@ -591,6 +592,7 @@
 	.release =	event_file_close,
 	.read =		event_file_read,
 	.write =	event_file_write,
+	.llseek =	generic_file_llseek,
 };
 
 static const struct file_operations r_heartbeat_fops = {
@@ -598,6 +600,7 @@
 	.release =	r_heartbeat_file_close,
 	.read =		r_heartbeat_file_read,
 	.write =	r_heartbeat_file_write,
+	.llseek =	generic_file_llseek,
 };
 
 static const struct file_operations remote_settings_fops = {
@@ -605,6 +608,7 @@
 	.release =	remote_settings_file_close,
 	.read =		remote_settings_file_read,
 	.write =	remote_settings_file_write,
+	.llseek =	generic_file_llseek,
 };
 
 
diff --git a/drivers/misc/iwmc3200top/debugfs.c b/drivers/misc/iwmc3200top/debugfs.c
index e9eda47..62fbaec 100644
--- a/drivers/misc/iwmc3200top/debugfs.c
+++ b/drivers/misc/iwmc3200top/debugfs.c
@@ -71,6 +71,7 @@
 	static const struct file_operations iwmct_dbgfs_##name##_ops = {  \
 		.read = iwmct_dbgfs_##name##_read,			\
 		.open = iwmct_dbgfs_open_file_generic,			\
+		.llseek = generic_file_llseek,				\
 	};
 
 #define DEBUGFS_WRITE_FILE_OPS(name)					\
@@ -78,6 +79,7 @@
 	static const struct file_operations iwmct_dbgfs_##name##_ops = {  \
 		.write = iwmct_dbgfs_##name##_write,			\
 		.open = iwmct_dbgfs_open_file_generic,			\
+		.llseek = generic_file_llseek,				\
 	};
 
 #define DEBUGFS_READ_WRITE_FILE_OPS(name)				\
@@ -87,6 +89,7 @@
 		.write = iwmct_dbgfs_##name##_write,			\
 		.read = iwmct_dbgfs_##name##_read,			\
 		.open = iwmct_dbgfs_open_file_generic,			\
+		.llseek = generic_file_llseek,				\
 	};
 
 
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index ef34de7..343b5d8 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -575,30 +575,39 @@
 
 static const struct crash_entry crash_entries[] = {
 	{"DIRECT", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = direct_entry} },
 	{"INT_HARDWARE_ENTRY", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = int_hardware_entry} },
 	{"INT_HW_IRQ_EN", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = int_hw_irq_en} },
 	{"INT_TASKLET_ENTRY", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = int_tasklet_entry} },
 	{"FS_DEVRW", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = fs_devrw_entry} },
 	{"MEM_SWAPOUT", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = mem_swapout_entry} },
 	{"TIMERADD", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = timeradd_entry} },
 	{"SCSI_DISPATCH_CMD", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = scsi_dispatch_cmd_entry} },
 	{"IDE_CORE_CP",	{.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = ide_core_cp_entry} },
 };
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
new file mode 100644
index 0000000..744b804
--- /dev/null
+++ b/drivers/misc/pch_phub.c
@@ -0,0 +1,717 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/if_ether.h>
+#include <linux/ctype.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 */
+
+/* MAX number of INT_REDUCE_CONTROL registers */
+#define MAX_NUM_INT_REDUCE_CONTROL_REG 128
+#define PCI_DEVICE_ID_PCH1_PHUB 0x8801
+#define PCH_MINOR_NOS 1
+#define CLKCFG_CAN_50MHZ 0x12000000
+#define CLKCFG_CANCLK_MASK 0xFF000000
+
+/* SROM ACCESS Macro */
+#define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
+
+/* Registers address offset */
+#define PCH_PHUB_ID_REG				0x0000
+#define PCH_PHUB_QUEUE_PRI_VAL_REG		0x0004
+#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG		0x0008
+#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG		0x000C
+#define PCH_PHUB_COMP_RESP_TIMEOUT_REG		0x0010
+#define PCH_PHUB_BUS_SLAVE_CONTROL_REG		0x0014
+#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG	0x0018
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0	0x0020
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1	0x0024
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2	0x0028
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3	0x002C
+#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE	0x0040
+#define CLKCFG_REG_OFFSET			0x500
+
+#define PCH_PHUB_OROM_SIZE 15360
+
+/**
+ * struct pch_phub_reg - PHUB register structure
+ * @phub_id_reg:			PHUB_ID register val
+ * @q_pri_val_reg:			QUEUE_PRI_VAL register val
+ * @rc_q_maxsize_reg:			RC_QUEUE_MAXSIZE register val
+ * @bri_q_maxsize_reg:			BRI_QUEUE_MAXSIZE register val
+ * @comp_resp_timeout_reg:		COMP_RESP_TIMEOUT register val
+ * @bus_slave_control_reg:		BUS_SLAVE_CONTROL_REG register val
+ * @deadlock_avoid_type_reg:		DEADLOCK_AVOID_TYPE register val
+ * @intpin_reg_wpermit_reg0:		INTPIN_REG_WPERMIT register 0 val
+ * @intpin_reg_wpermit_reg1:		INTPIN_REG_WPERMIT register 1 val
+ * @intpin_reg_wpermit_reg2:		INTPIN_REG_WPERMIT register 2 val
+ * @intpin_reg_wpermit_reg3:		INTPIN_REG_WPERMIT register 3 val
+ * @int_reduce_control_reg:		INT_REDUCE_CONTROL registers val
+ * @clkcfg_reg:				CLK CFG register val
+ * @pch_phub_base_address:		Register base address
+ * @pch_phub_extrom_base_address:	external rom base address
+ */
+struct pch_phub_reg {
+	u32 phub_id_reg;
+	u32 q_pri_val_reg;
+	u32 rc_q_maxsize_reg;
+	u32 bri_q_maxsize_reg;
+	u32 comp_resp_timeout_reg;
+	u32 bus_slave_control_reg;
+	u32 deadlock_avoid_type_reg;
+	u32 intpin_reg_wpermit_reg0;
+	u32 intpin_reg_wpermit_reg1;
+	u32 intpin_reg_wpermit_reg2;
+	u32 intpin_reg_wpermit_reg3;
+	u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
+	u32 clkcfg_reg;
+	void __iomem *pch_phub_base_address;
+	void __iomem *pch_phub_extrom_base_address;
+};
+
+/* SROM SPEC for MAC address assignment offset */
+static const int pch_phub_mac_offset[ETH_ALEN] = {0x3, 0x2, 0x1, 0x0, 0xb, 0xa};
+
+static DEFINE_MUTEX(pch_phub_mutex);
+
+/**
+ * pch_phub_read_modify_write_reg() - Reading modifying and writing register
+ * @reg_addr_offset:	Register offset address value.
+ * @data:		Writing value.
+ * @mask:		Mask value.
+ */
+static void pch_phub_read_modify_write_reg(struct pch_phub_reg *chip,
+					   unsigned int reg_addr_offset,
+					   unsigned int data, unsigned int mask)
+{
+	void __iomem *reg_addr = chip->pch_phub_base_address + reg_addr_offset;
+	iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
+}
+
+/* pch_phub_save_reg_conf - saves register configuration */
+static void pch_phub_save_reg_conf(struct pci_dev *pdev)
+{
+	unsigned int i;
+	struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+
+	void __iomem *p = chip->pch_phub_base_address;
+
+	chip->phub_id_reg = ioread32(p + PCH_PHUB_ID_REG);
+	chip->q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+	chip->rc_q_maxsize_reg = ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	chip->bri_q_maxsize_reg = ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	chip->comp_resp_timeout_reg =
+				ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	chip->bus_slave_control_reg =
+				ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	chip->deadlock_avoid_type_reg =
+				ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	chip->intpin_reg_wpermit_reg0 =
+				ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	chip->intpin_reg_wpermit_reg1 =
+				ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	chip->intpin_reg_wpermit_reg2 =
+				ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	chip->intpin_reg_wpermit_reg3 =
+				ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "%s : "
+		"chip->phub_id_reg=%x, "
+		"chip->q_pri_val_reg=%x, "
+		"chip->rc_q_maxsize_reg=%x, "
+		"chip->bri_q_maxsize_reg=%x, "
+		"chip->comp_resp_timeout_reg=%x, "
+		"chip->bus_slave_control_reg=%x, "
+		"chip->deadlock_avoid_type_reg=%x, "
+		"chip->intpin_reg_wpermit_reg0=%x, "
+		"chip->intpin_reg_wpermit_reg1=%x, "
+		"chip->intpin_reg_wpermit_reg2=%x, "
+		"chip->intpin_reg_wpermit_reg3=%x\n", __func__,
+		chip->phub_id_reg,
+		chip->q_pri_val_reg,
+		chip->rc_q_maxsize_reg,
+		chip->bri_q_maxsize_reg,
+		chip->comp_resp_timeout_reg,
+		chip->bus_slave_control_reg,
+		chip->deadlock_avoid_type_reg,
+		chip->intpin_reg_wpermit_reg0,
+		chip->intpin_reg_wpermit_reg1,
+		chip->intpin_reg_wpermit_reg2,
+		chip->intpin_reg_wpermit_reg3);
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		chip->int_reduce_control_reg[i] =
+		    ioread32(p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "%s : "
+			"chip->int_reduce_control_reg[%d]=%x\n",
+			__func__, i, chip->int_reduce_control_reg[i]);
+	}
+	chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
+}
+
+/* pch_phub_restore_reg_conf - restore register configuration */
+static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
+{
+	unsigned int i;
+	struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+	void __iomem *p;
+	p = chip->pch_phub_base_address;
+
+	iowrite32(chip->phub_id_reg, p + PCH_PHUB_ID_REG);
+	iowrite32(chip->q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+	iowrite32(chip->rc_q_maxsize_reg, p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	iowrite32(chip->bri_q_maxsize_reg, p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	iowrite32(chip->comp_resp_timeout_reg,
+					p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	iowrite32(chip->bus_slave_control_reg,
+					p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	iowrite32(chip->deadlock_avoid_type_reg,
+					p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	iowrite32(chip->intpin_reg_wpermit_reg0,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	iowrite32(chip->intpin_reg_wpermit_reg1,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	iowrite32(chip->intpin_reg_wpermit_reg2,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	iowrite32(chip->intpin_reg_wpermit_reg3,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "%s : "
+		"chip->phub_id_reg=%x, "
+		"chip->q_pri_val_reg=%x, "
+		"chip->rc_q_maxsize_reg=%x, "
+		"chip->bri_q_maxsize_reg=%x, "
+		"chip->comp_resp_timeout_reg=%x, "
+		"chip->bus_slave_control_reg=%x, "
+		"chip->deadlock_avoid_type_reg=%x, "
+		"chip->intpin_reg_wpermit_reg0=%x, "
+		"chip->intpin_reg_wpermit_reg1=%x, "
+		"chip->intpin_reg_wpermit_reg2=%x, "
+		"chip->intpin_reg_wpermit_reg3=%x\n", __func__,
+		chip->phub_id_reg,
+		chip->q_pri_val_reg,
+		chip->rc_q_maxsize_reg,
+		chip->bri_q_maxsize_reg,
+		chip->comp_resp_timeout_reg,
+		chip->bus_slave_control_reg,
+		chip->deadlock_avoid_type_reg,
+		chip->intpin_reg_wpermit_reg0,
+		chip->intpin_reg_wpermit_reg1,
+		chip->intpin_reg_wpermit_reg2,
+		chip->intpin_reg_wpermit_reg3);
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		iowrite32(chip->int_reduce_control_reg[i],
+			p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "%s : "
+			"chip->int_reduce_control_reg[%d]=%x\n",
+			__func__, i, chip->int_reduce_control_reg[i]);
+	}
+
+	iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET);
+}
+
+/**
+ * pch_phub_read_serial_rom() - Reading Serial ROM
+ * @offset_address:	Serial ROM offset address to read.
+ * @data:		Read buffer for specified Serial ROM value.
+ */
+static void pch_phub_read_serial_rom(struct pch_phub_reg *chip,
+				     unsigned int offset_address, u8 *data)
+{
+	void __iomem *mem_addr = chip->pch_phub_extrom_base_address +
+								offset_address;
+
+	*data = ioread8(mem_addr);
+}
+
+/**
+ * pch_phub_write_serial_rom() - Writing Serial ROM
+ * @offset_address:	Serial ROM offset address.
+ * @data:		Serial ROM value to write.
+ */
+static int pch_phub_write_serial_rom(struct pch_phub_reg *chip,
+				     unsigned int offset_address, u8 data)
+{
+	void __iomem *mem_addr = chip->pch_phub_extrom_base_address +
+					(offset_address & PCH_WORD_ADDR_MASK);
+	int i;
+	unsigned int word_data;
+	unsigned int pos;
+	unsigned int mask;
+	pos = (offset_address % 4) * 8;
+	mask = ~(0xFF << pos);
+
+	iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
+			chip->pch_phub_extrom_base_address + PHUB_CONTROL);
+
+	word_data = ioread32(mem_addr);
+	iowrite32((word_data & mask) | (u32)data << pos, mem_addr);
+
+	i = 0;
+	while (ioread8(chip->pch_phub_extrom_base_address +
+						PHUB_STATUS) != 0x00) {
+		msleep(1);
+		if (i == PHUB_TIMEOUT)
+			return -ETIMEDOUT;
+		i++;
+	}
+
+	iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
+			chip->pch_phub_extrom_base_address + PHUB_CONTROL);
+
+	return 0;
+}
+
+/**
+ * pch_phub_read_serial_rom_val() - Read Serial ROM value
+ * @offset_address:	Serial ROM address offset value.
+ * @data:		Serial ROM value to read.
+ */
+static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip,
+					 unsigned int offset_address, u8 *data)
+{
+	unsigned int mem_addr;
+
+	mem_addr = PCH_PHUB_ROM_START_ADDR +
+			pch_phub_mac_offset[offset_address];
+
+	pch_phub_read_serial_rom(chip, mem_addr, data);
+}
+
+/**
+ * pch_phub_write_serial_rom_val() - writing Serial ROM value
+ * @offset_address:	Serial ROM address offset value.
+ * @data:		Serial ROM value.
+ */
+static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip,
+					 unsigned int offset_address, u8 data)
+{
+	int retval;
+	unsigned int mem_addr;
+
+	mem_addr = PCH_PHUB_ROM_START_ADDR +
+			pch_phub_mac_offset[offset_address];
+
+	retval = pch_phub_write_serial_rom(chip, mem_addr, data);
+
+	return retval;
+}
+
+/* pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration
+ * for Gigabit Ethernet MAC address
+ */
+static int pch_phub_gbe_serial_rom_conf(struct pch_phub_reg *chip)
+{
+	int retval;
+
+	retval = pch_phub_write_serial_rom(chip, 0x0b, 0xbc);
+	retval |= pch_phub_write_serial_rom(chip, 0x0a, 0x10);
+	retval |= pch_phub_write_serial_rom(chip, 0x09, 0x01);
+	retval |= pch_phub_write_serial_rom(chip, 0x08, 0x02);
+
+	retval |= pch_phub_write_serial_rom(chip, 0x0f, 0x00);
+	retval |= pch_phub_write_serial_rom(chip, 0x0e, 0x00);
+	retval |= pch_phub_write_serial_rom(chip, 0x0d, 0x00);
+	retval |= pch_phub_write_serial_rom(chip, 0x0c, 0x80);
+
+	retval |= pch_phub_write_serial_rom(chip, 0x13, 0xbc);
+	retval |= pch_phub_write_serial_rom(chip, 0x12, 0x10);
+	retval |= pch_phub_write_serial_rom(chip, 0x11, 0x01);
+	retval |= pch_phub_write_serial_rom(chip, 0x10, 0x18);
+
+	retval |= pch_phub_write_serial_rom(chip, 0x1b, 0xbc);
+	retval |= pch_phub_write_serial_rom(chip, 0x1a, 0x10);
+	retval |= pch_phub_write_serial_rom(chip, 0x19, 0x01);
+	retval |= pch_phub_write_serial_rom(chip, 0x18, 0x19);
+
+	retval |= pch_phub_write_serial_rom(chip, 0x23, 0xbc);
+	retval |= pch_phub_write_serial_rom(chip, 0x22, 0x10);
+	retval |= pch_phub_write_serial_rom(chip, 0x21, 0x01);
+	retval |= pch_phub_write_serial_rom(chip, 0x20, 0x3a);
+
+	retval |= pch_phub_write_serial_rom(chip, 0x27, 0x01);
+	retval |= pch_phub_write_serial_rom(chip, 0x26, 0x00);
+	retval |= pch_phub_write_serial_rom(chip, 0x25, 0x00);
+	retval |= pch_phub_write_serial_rom(chip, 0x24, 0x00);
+
+	return retval;
+}
+
+/**
+ * pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address
+ * @offset_address:	Gigabit Ethernet MAC address offset value.
+ * @data:		Buffer of the Gigabit Ethernet MAC address value.
+ */
+static void pch_phub_read_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
+{
+	int i;
+	for (i = 0; i < ETH_ALEN; i++)
+		pch_phub_read_serial_rom_val(chip, i, &data[i]);
+}
+
+/**
+ * pch_phub_write_gbe_mac_addr() - Write MAC address
+ * @offset_address:	Gigabit Ethernet MAC address offset value.
+ * @data:		Gigabit Ethernet MAC address value.
+ */
+static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
+{
+	int retval;
+	int i;
+
+	retval = pch_phub_gbe_serial_rom_conf(chip);
+	if (retval)
+		return retval;
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		retval = pch_phub_write_serial_rom_val(chip, i, data[i]);
+		if (retval)
+			return retval;
+	}
+
+	return retval;
+}
+
+static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
+				 struct bin_attribute *attr, char *buf,
+				 loff_t off, size_t count)
+{
+	unsigned int rom_signature;
+	unsigned char rom_length;
+	unsigned int tmp;
+	unsigned int addr_offset;
+	unsigned int orom_size;
+	int ret;
+	int err;
+
+	struct pch_phub_reg *chip =
+		dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+	ret = mutex_lock_interruptible(&pch_phub_mutex);
+	if (ret) {
+		err = -ERESTARTSYS;
+		goto return_err_nomutex;
+	}
+
+	/* Get Rom signature */
+	pch_phub_read_serial_rom(chip, 0x80, (unsigned char *)&rom_signature);
+	rom_signature &= 0xff;
+	pch_phub_read_serial_rom(chip, 0x81, (unsigned char *)&tmp);
+	rom_signature |= (tmp & 0xff) << 8;
+	if (rom_signature == 0xAA55) {
+		pch_phub_read_serial_rom(chip, 0x82, &rom_length);
+		orom_size = rom_length * 512;
+		if (orom_size < off) {
+			addr_offset = 0;
+			goto return_ok;
+		}
+		if (orom_size < count) {
+			addr_offset = 0;
+			goto return_ok;
+		}
+
+		for (addr_offset = 0; addr_offset < count; addr_offset++) {
+			pch_phub_read_serial_rom(chip, 0x80 + addr_offset + off,
+							 &buf[addr_offset]);
+		}
+	} else {
+		err = -ENODATA;
+		goto return_err;
+	}
+return_ok:
+	mutex_unlock(&pch_phub_mutex);
+	return addr_offset;
+
+return_err:
+	mutex_unlock(&pch_phub_mutex);
+return_err_nomutex:
+	return err;
+}
+
+static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
+				  struct bin_attribute *attr,
+				  char *buf, loff_t off, size_t count)
+{
+	int err;
+	unsigned int addr_offset;
+	int ret;
+	struct pch_phub_reg *chip =
+		dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+	ret = mutex_lock_interruptible(&pch_phub_mutex);
+	if (ret)
+		return -ERESTARTSYS;
+
+	if (off > PCH_PHUB_OROM_SIZE) {
+		addr_offset = 0;
+		goto return_ok;
+	}
+	if (count > PCH_PHUB_OROM_SIZE) {
+		addr_offset = 0;
+		goto return_ok;
+	}
+
+	for (addr_offset = 0; addr_offset < count; addr_offset++) {
+		if (PCH_PHUB_OROM_SIZE < off + addr_offset)
+			goto return_ok;
+
+		ret = pch_phub_write_serial_rom(chip, 0x80 + addr_offset + off,
+						       buf[addr_offset]);
+		if (ret) {
+			err = ret;
+			goto return_err;
+		}
+	}
+
+return_ok:
+	mutex_unlock(&pch_phub_mutex);
+	return addr_offset;
+
+return_err:
+	mutex_unlock(&pch_phub_mutex);
+	return err;
+}
+
+static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	u8 mac[8];
+	struct pch_phub_reg *chip = dev_get_drvdata(dev);
+
+	pch_phub_read_gbe_mac_addr(chip, mac);
+
+	return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+				mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	u8 mac[6];
+	struct pch_phub_reg *chip = dev_get_drvdata(dev);
+
+	if (count != 18)
+		return -EINVAL;
+
+	sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+		(u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],
+		(u32 *)&mac[4], (u32 *)&mac[5]);
+
+	pch_phub_write_gbe_mac_addr(chip, mac);
+
+	return count;
+}
+
+static DEVICE_ATTR(pch_mac, S_IRUGO | S_IWUSR, show_pch_mac, store_pch_mac);
+
+static struct bin_attribute pch_bin_attr = {
+	.attr = {
+		.name = "pch_firmware",
+		.mode = S_IRUGO | S_IWUSR,
+	},
+	.size = PCH_PHUB_OROM_SIZE + 1,
+	.read = pch_phub_bin_read,
+	.write = pch_phub_bin_write,
+};
+
+static int __devinit pch_phub_probe(struct pci_dev *pdev,
+				    const struct pci_device_id *id)
+{
+	int retval;
+
+	int ret;
+	ssize_t rom_size;
+	struct pch_phub_reg *chip;
+
+	chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+		"%s : pci_enable_device FAILED(ret=%d)", __func__, ret);
+		goto err_pci_enable_dev;
+	}
+	dev_dbg(&pdev->dev, "%s : pci_enable_device returns %d\n", __func__,
+		ret);
+
+	ret = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (ret) {
+		dev_err(&pdev->dev,
+		"%s : pci_request_regions FAILED(ret=%d)", __func__, ret);
+		goto err_req_regions;
+	}
+	dev_dbg(&pdev->dev, "%s : "
+		"pci_request_regions returns %d\n", __func__, ret);
+
+	chip->pch_phub_base_address = pci_iomap(pdev, 1, 0);
+
+
+	if (chip->pch_phub_base_address == 0) {
+		dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
+		ret = -ENOMEM;
+		goto err_pci_iomap;
+	}
+	dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value "
+		"in pch_phub_base_address variable is %p\n", __func__,
+		chip->pch_phub_base_address);
+	chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size);
+
+	if (chip->pch_phub_extrom_base_address == 0) {
+		dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__);
+		ret = -ENOMEM;
+		goto err_pci_map;
+	}
+	dev_dbg(&pdev->dev, "%s : "
+		"pci_map_rom SUCCESS and value in "
+		"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);
+
+	/* 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);
+
+	return 0;
+exit_bin_attr:
+	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
+
+err_sysfs_create:
+	pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
+err_pci_map:
+	pci_iounmap(pdev, chip->pch_phub_base_address);
+err_pci_iomap:
+	pci_release_regions(pdev);
+err_req_regions:
+	pci_disable_device(pdev);
+err_pci_enable_dev:
+	kfree(chip);
+	dev_err(&pdev->dev, "%s returns %d\n", __func__, ret);
+	return ret;
+}
+
+static void __devexit pch_phub_remove(struct pci_dev *pdev)
+{
+	struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+
+	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
+	sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+	pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
+	pci_iounmap(pdev, chip->pch_phub_base_address);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	kfree(chip);
+}
+
+#ifdef CONFIG_PM
+
+static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	int ret;
+
+	pch_phub_save_reg_conf(pdev);
+	ret = pci_save_state(pdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+			" %s -pci_save_state returns %d\n", __func__, ret);
+		return ret;
+	}
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return 0;
+}
+
+static int pch_phub_resume(struct pci_dev *pdev)
+{
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+		"%s-pci_enable_device failed(ret=%d) ", __func__, ret);
+		return ret;
+	}
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pch_phub_restore_reg_conf(pdev);
+
+	return 0;
+}
+#else
+#define pch_phub_suspend NULL
+#define pch_phub_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_device_id pch_phub_pcidev_id[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
+	{0,}
+};
+
+static struct pci_driver pch_phub_driver = {
+	.name = "pch_phub",
+	.id_table = pch_phub_pcidev_id,
+	.probe = pch_phub_probe,
+	.remove = __devexit_p(pch_phub_remove),
+	.suspend = pch_phub_suspend,
+	.resume = pch_phub_resume
+};
+
+static int __init pch_phub_pci_init(void)
+{
+	return pci_register_driver(&pch_phub_driver);
+}
+
+static void __exit pch_phub_pci_exit(void)
+{
+	pci_unregister_driver(&pch_phub_driver);
+}
+
+module_init(pch_phub_pci_init);
+module_exit(pch_phub_pci_exit);
+
+MODULE_DESCRIPTION("PCH Packet Hub PCI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 75ee0d3..4197a3c 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/phantom.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -38,6 +38,7 @@
 #define PHB_RUNNING		1
 #define PHB_NOT_OH		2
 
+static DEFINE_MUTEX(phantom_mutex);
 static struct class *phantom_class;
 static int phantom_major;
 
@@ -215,17 +216,17 @@
 	struct phantom_device *dev = container_of(inode->i_cdev,
 			struct phantom_device, cdev);
 
-	lock_kernel();
+	mutex_lock(&phantom_mutex);
 	nonseekable_open(inode, file);
 
 	if (mutex_lock_interruptible(&dev->open_lock)) {
-		unlock_kernel();
+		mutex_unlock(&phantom_mutex);
 		return -ERESTARTSYS;
 	}
 
 	if (dev->opened) {
 		mutex_unlock(&dev->open_lock);
-		unlock_kernel();
+		mutex_unlock(&phantom_mutex);
 		return -EINVAL;
 	}
 
@@ -236,7 +237,7 @@
 	atomic_set(&dev->counter, 0);
 	dev->opened++;
 	mutex_unlock(&dev->open_lock);
-	unlock_kernel();
+	mutex_unlock(&phantom_mutex);
 	return 0;
 }
 
@@ -279,6 +280,7 @@
 	.unlocked_ioctl = phantom_ioctl,
 	.compat_ioctl = phantom_compat_ioctl,
 	.poll = phantom_poll,
+	.llseek = no_llseek,
 };
 
 static irqreturn_t phantom_isr(int irq, void *data)
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c
index cb3b4d2..28852df 100644
--- a/drivers/misc/sgi-gru/grufile.c
+++ b/drivers/misc/sgi-gru/grufile.c
@@ -587,6 +587,7 @@
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= gru_file_unlocked_ioctl,
 	.mmap		= gru_file_mmap,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice gru_miscdev = {
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index d545f79..00073b7 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -29,7 +29,6 @@
 #include <linux/kdev_t.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/scatterlist.h>
 #include <linux/string_helpers.h>
 
@@ -51,6 +50,7 @@
 #define MMC_SHIFT	3
 #define MMC_NUM_MINORS	(256 >> MMC_SHIFT)
 
+static DEFINE_MUTEX(block_mutex);
 static DECLARE_BITMAP(dev_use, MMC_NUM_MINORS);
 
 /*
@@ -108,7 +108,7 @@
 	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
 	int ret = -ENXIO;
 
-	lock_kernel();
+	mutex_lock(&block_mutex);
 	if (md) {
 		if (md->usage == 2)
 			check_disk_change(bdev);
@@ -119,7 +119,7 @@
 			ret = -EROFS;
 		}
 	}
-	unlock_kernel();
+	mutex_unlock(&block_mutex);
 
 	return ret;
 }
@@ -128,9 +128,9 @@
 {
 	struct mmc_blk_data *md = disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&block_mutex);
 	mmc_blk_put(md);
-	unlock_kernel();
+	mutex_unlock(&block_mutex);
 	return 0;
 }
 
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index e876678..9c0b42b 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -128,7 +128,6 @@
 	mq->req = NULL;
 
 	blk_queue_prep_rq(mq->queue, mmc_prep_request);
-	blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN);
 	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
 	if (mmc_can_erase(card)) {
 		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq->queue);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 5db49b1..09eee6d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1631,6 +1631,19 @@
 	if (host->bus_ops && !host->bus_dead) {
 		if (host->bus_ops->suspend)
 			err = host->bus_ops->suspend(host);
+		if (err == -ENOSYS || !host->bus_ops->resume) {
+			/*
+			 * We simply "remove" the card in this case.
+			 * It will be redetected on resume.
+			 */
+			if (host->bus_ops->remove)
+				host->bus_ops->remove(host);
+			mmc_claim_host(host);
+			mmc_detach_bus(host);
+			mmc_release_host(host);
+			host->pm_flags = 0;
+			err = 0;
+		}
 	}
 	mmc_bus_put(host);
 
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 53cb380c..46bc6d7 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -245,6 +245,7 @@
 	.open		= mmc_ext_csd_open,
 	.read		= mmc_ext_csd_read,
 	.release	= mmc_ext_csd_release,
+	.llseek		= default_llseek,
 };
 
 void mmc_add_card_debugfs(struct mmc_card *card)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 840b301..f2e02d7 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -41,23 +41,35 @@
  * @clkreg: default value for MCICLOCK register
  * @clkreg_enable: enable value for MMCICLOCK register
  * @datalength_bits: number of bits in the MMCIDATALENGTH register
+ * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY
+ *	      is asserted (likewise for RX)
+ * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
+ *		  is asserted (likewise for RX)
  */
 struct variant_data {
 	unsigned int		clkreg;
 	unsigned int		clkreg_enable;
 	unsigned int		datalength_bits;
+	unsigned int		fifosize;
+	unsigned int		fifohalfsize;
 };
 
 static struct variant_data variant_arm = {
+	.fifosize		= 16 * 4,
+	.fifohalfsize		= 8 * 4,
 	.datalength_bits	= 16,
 };
 
 static struct variant_data variant_u300 = {
+	.fifosize		= 16 * 4,
+	.fifohalfsize		= 8 * 4,
 	.clkreg_enable		= 1 << 13, /* HWFCEN */
 	.datalength_bits	= 16,
 };
 
 static struct variant_data variant_ux500 = {
+	.fifosize		= 30 * 4,
+	.fifohalfsize		= 8 * 4,
 	.clkreg			= MCI_CLK_ENABLE,
 	.clkreg_enable		= 1 << 14, /* HWFCEN */
 	.datalength_bits	= 24,
@@ -138,6 +150,7 @@
 
 static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
 {
+	struct variant_data *variant = host->variant;
 	unsigned int datactrl, timeout, irqmask;
 	unsigned long long clks;
 	void __iomem *base;
@@ -173,7 +186,7 @@
 		 * If we have less than a FIFOSIZE of bytes to transfer,
 		 * trigger a PIO interrupt as soon as any data is available.
 		 */
-		if (host->size < MCI_FIFOSIZE)
+		if (host->size < variant->fifosize)
 			irqmask |= MCI_RXDATAAVLBLMASK;
 	} else {
 		/*
@@ -332,13 +345,15 @@
 
 static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status)
 {
+	struct variant_data *variant = host->variant;
 	void __iomem *base = host->base;
 	char *ptr = buffer;
 
 	do {
 		unsigned int count, maxcnt;
 
-		maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : MCI_FIFOHALFSIZE;
+		maxcnt = status & MCI_TXFIFOEMPTY ?
+			 variant->fifosize : variant->fifohalfsize;
 		count = min(remain, maxcnt);
 
 		writesl(base + MMCIFIFO, ptr, count >> 2);
@@ -362,6 +377,7 @@
 {
 	struct mmci_host *host = dev_id;
 	struct sg_mapping_iter *sg_miter = &host->sg_miter;
+	struct variant_data *variant = host->variant;
 	void __iomem *base = host->base;
 	unsigned long flags;
 	u32 status;
@@ -420,7 +436,7 @@
 	 * If we're nearing the end of the read, switch to
 	 * "any data available" mode.
 	 */
-	if (status & MCI_RXACTIVE && host->size < MCI_FIFOSIZE)
+	if (status & MCI_RXACTIVE && host->size < variant->fifosize)
 		writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1);
 
 	/*
@@ -564,18 +580,23 @@
 	if (host->gpio_wp == -ENOSYS)
 		return -ENOSYS;
 
-	return gpio_get_value(host->gpio_wp);
+	return gpio_get_value_cansleep(host->gpio_wp);
 }
 
 static int mmci_get_cd(struct mmc_host *mmc)
 {
 	struct mmci_host *host = mmc_priv(mmc);
+	struct mmci_platform_data *plat = host->plat;
 	unsigned int status;
 
-	if (host->gpio_cd == -ENOSYS)
-		status = host->plat->status(mmc_dev(host->mmc));
-	else
-		status = !gpio_get_value(host->gpio_cd);
+	if (host->gpio_cd == -ENOSYS) {
+		if (!plat->status)
+			return 1; /* Assume always present */
+
+		status = plat->status(mmc_dev(host->mmc));
+	} else
+		status = !!gpio_get_value_cansleep(host->gpio_cd)
+			^ plat->cd_invert;
 
 	/*
 	 * Use positive logic throughout - status is zero for no card,
@@ -584,6 +605,15 @@
 	return status;
 }
 
+static irqreturn_t mmci_cd_irq(int irq, void *dev_id)
+{
+	struct mmci_host *host = dev_id;
+
+	mmc_detect_change(host->mmc, msecs_to_jiffies(500));
+
+	return IRQ_HANDLED;
+}
+
 static const struct mmc_host_ops mmci_ops = {
 	.request	= mmci_request,
 	.set_ios	= mmci_set_ios,
@@ -620,6 +650,7 @@
 
 	host->gpio_wp = -ENOSYS;
 	host->gpio_cd = -ENOSYS;
+	host->gpio_cd_irq = -1;
 
 	host->hw_designer = amba_manf(dev);
 	host->hw_revision = amba_rev(dev);
@@ -699,7 +730,6 @@
 	if (host->vcc == NULL)
 		mmc->ocr_avail = plat->ocr_mask;
 	mmc->caps = plat->capabilities;
-	mmc->caps |= MMC_CAP_NEEDS_POLL;
 
 	/*
 	 * We can do SGIO
@@ -744,6 +774,12 @@
 			host->gpio_cd = plat->gpio_cd;
 		else if (ret != -ENOSYS)
 			goto err_gpio_cd;
+
+		ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd),
+					      mmci_cd_irq, 0,
+					      DRIVER_NAME " (cd)", host);
+		if (ret >= 0)
+			host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd);
 	}
 	if (gpio_is_valid(plat->gpio_wp)) {
 		ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)");
@@ -755,6 +791,10 @@
 			goto err_gpio_wp;
 	}
 
+	if ((host->plat->status || host->gpio_cd != -ENOSYS)
+	    && host->gpio_cd_irq < 0)
+		mmc->caps |= MMC_CAP_NEEDS_POLL;
+
 	ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
 	if (ret)
 		goto unmap;
@@ -781,6 +821,8 @@
 	if (host->gpio_wp != -ENOSYS)
 		gpio_free(host->gpio_wp);
  err_gpio_wp:
+	if (host->gpio_cd_irq >= 0)
+		free_irq(host->gpio_cd_irq, host);
 	if (host->gpio_cd != -ENOSYS)
 		gpio_free(host->gpio_cd);
  err_gpio_cd:
@@ -819,6 +861,8 @@
 
 		if (host->gpio_wp != -ENOSYS)
 			gpio_free(host->gpio_wp);
+		if (host->gpio_cd_irq >= 0)
+			free_irq(host->gpio_cd_irq, host);
 		if (host->gpio_cd != -ENOSYS)
 			gpio_free(host->gpio_cd);
 
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 68970cf..4ae887f 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -54,10 +54,16 @@
 #define MCI_DPSM_MODE		(1 << 2)
 #define MCI_DPSM_DMAENABLE	(1 << 3)
 #define MCI_DPSM_BLOCKSIZE	(1 << 4)
-#define MCI_DPSM_RWSTART	(1 << 8)
-#define MCI_DPSM_RWSTOP		(1 << 9)
-#define MCI_DPSM_RWMOD		(1 << 10)
-#define MCI_DPSM_SDIOEN		(1 << 11)
+/* Control register extensions in the ST Micro U300 and Ux500 versions */
+#define MCI_ST_DPSM_RWSTART	(1 << 8)
+#define MCI_ST_DPSM_RWSTOP	(1 << 9)
+#define MCI_ST_DPSM_RWMOD	(1 << 10)
+#define MCI_ST_DPSM_SDIOEN	(1 << 11)
+/* Control register extensions in the ST Micro Ux500 versions */
+#define MCI_ST_DPSM_DMAREQCTL	(1 << 12)
+#define MCI_ST_DPSM_DBOOTMODEEN	(1 << 13)
+#define MCI_ST_DPSM_BUSYMODE	(1 << 14)
+#define MCI_ST_DPSM_DDRMODE	(1 << 15)
 
 #define MMCIDATACNT		0x030
 #define MMCISTATUS		0x034
@@ -133,13 +139,6 @@
 	MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|	\
 	MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
 
-/*
- * The size of the FIFO in bytes.
- */
-#define MCI_FIFOSIZE	(16*4)
-	
-#define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2)
-
 #define NR_SG		16
 
 struct clk;
@@ -154,6 +153,7 @@
 	struct clk		*clk;
 	int			gpio_cd;
 	int			gpio_wp;
+	int			gpio_cd_irq;
 
 	unsigned int		data_xfered;
 
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 71ad416..aacb862 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -241,8 +241,10 @@
 static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
 {
 	struct sdhci_host *host = platform_get_drvdata(dev);
+	unsigned long flags;
+
 	if (host) {
-		spin_lock(&host->lock);
+		spin_lock_irqsave(&host->lock, flags);
 		if (state) {
 			dev_dbg(&dev->dev, "card inserted.\n");
 			host->flags &= ~SDHCI_DEVICE_DEAD;
@@ -253,7 +255,7 @@
 			host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
 		}
 		tasklet_schedule(&host->card_tasklet);
-		spin_unlock(&host->lock);
+		spin_unlock_irqrestore(&host->lock, flags);
 	}
 }
 
@@ -481,8 +483,10 @@
 	sdhci_remove_host(host, 1);
 
 	for (ptr = 0; ptr < 3; ptr++) {
-		clk_disable(sc->clk_bus[ptr]);
-		clk_put(sc->clk_bus[ptr]);
+		if (sc->clk_bus[ptr]) {
+			clk_disable(sc->clk_bus[ptr]);
+			clk_put(sc->clk_bus[ptr]);
+		}
 	}
 	clk_disable(sc->clk_io);
 	clk_put(sc->clk_io);
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c
index 7aa65bb..f472c27 100644
--- a/drivers/mmc/host/sdricoh_cs.c
+++ b/drivers/mmc/host/sdricoh_cs.c
@@ -30,7 +30,6 @@
 #include <linux/ioport.h>
 #include <linux/scatterlist.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <linux/io.h>
@@ -536,9 +535,7 @@
 #endif
 
 static struct pcmcia_driver sdricoh_driver = {
-	.drv = {
-		.name = DRIVER_NAME,
-		},
+	.name = DRIVER_NAME,
 	.probe = sdricoh_pcmcia_probe,
 	.remove = sdricoh_pcmcia_detach,
 	.id_table = pcmcia_ids,
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index e9ca5ba..57a1acf 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -16,7 +16,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -101,7 +100,7 @@
 static caddr_t remap_window(struct map_info *map, unsigned long to)
 {
 	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
-	window_handle_t win = (window_handle_t)map->map_priv_2;
+	struct resource *win = (struct resource *) map->map_priv_2;
 	unsigned int offset;
 	int ret;
 
@@ -316,30 +315,19 @@
 {
 	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 	struct pcmcia_device *link = dev->p_dev;
-	modconf_t mod;
-	int ret;
-
-	mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID;
-	mod.Vcc = 0;
-	mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
 
 	DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
-	ret = pcmcia_modify_configuration(link, &mod);
+	pcmcia_fixup_vpp(link, on ? dev->vpp : 0);
 }
 
 
-/* After a card is removed, pcmciamtd_release() will unregister the
- * device, and release the PCMCIA configuration.  If the device is
- * still open, this will be postponed until it is closed.
- */
-
 static void pcmciamtd_release(struct pcmcia_device *link)
 {
 	struct pcmciamtd_dev *dev = link->priv;
 
 	DEBUG(3, "link = 0x%p", link);
 
-	if (link->win) {
+	if (link->resource[2]->end) {
 		if(dev->win_base) {
 			iounmap(dev->win_base);
 			dev->win_base = NULL;
@@ -482,18 +470,12 @@
 }
 
 
-/* pcmciamtd_config() is scheduled to run after a CARD_INSERTION event
- * is received, to configure the PCMCIA socket, and to make the
- * MTD device available to the system.
- */
-
 static int pcmciamtd_config(struct pcmcia_device *link)
 {
 	struct pcmciamtd_dev *dev = link->priv;
 	struct mtd_info *mtd = NULL;
-	win_req_t req;
 	int ret;
-	int i;
+	int i, j = 0;
 	static char *probes[] = { "jedec_probe", "cfi_probe" };
 	int new_name = 0;
 
@@ -520,28 +502,34 @@
 	 * smaller windows until we succeed
 	 */
 
-	req.Attributes =  WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-	req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
-	req.Base = 0;
-	req.AccessSpeed = mem_speed;
-	link->win = (window_handle_t)link;
-	req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
+	link->resource[2]->flags |=  WIN_MEMORY_TYPE_CM | WIN_ENABLE;
+	link->resource[2]->flags |= (dev->pcmcia_map.bankwidth == 1) ?
+					WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
+	link->resource[2]->start = 0;
+	link->resource[2]->end = (force_size) ? force_size << 20 :
+					MAX_PCMCIA_ADDR;
 	dev->win_size = 0;
 
 	do {
 		int ret;
-		DEBUG(2, "requesting window with size = %dKiB memspeed = %d",
-		      req.Size >> 10, req.AccessSpeed);
-		ret = pcmcia_request_window(link, &req, &link->win);
+		DEBUG(2, "requesting window with size = %luKiB memspeed = %d",
+			(unsigned long) resource_size(link->resource[2]) >> 10,
+			mem_speed);
+		ret = pcmcia_request_window(link, link->resource[2], mem_speed);
 		DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
 		if(ret) {
-			req.Size >>= 1;
+			j++;
+			link->resource[2]->start = 0;
+			link->resource[2]->end = (force_size) ?
+					force_size << 20 : MAX_PCMCIA_ADDR;
+			link->resource[2]->end >>= j;
 		} else {
-			DEBUG(2, "Got window of size %dKiB", req.Size >> 10);
-			dev->win_size = req.Size;
+			DEBUG(2, "Got window of size %luKiB", (unsigned long)
+				resource_size(link->resource[2]) >> 10);
+			dev->win_size = resource_size(link->resource[2]);
 			break;
 		}
-	} while(req.Size >= 0x1000);
+	} while (link->resource[2]->end >= 0x1000);
 
 	DEBUG(2, "dev->win_size = %d", dev->win_size);
 
@@ -553,33 +541,31 @@
 	DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
 
 	/* Get write protect status */
-	DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win);
-	dev->win_base = ioremap(req.Base, req.Size);
+	dev->win_base = ioremap(link->resource[2]->start,
+				resource_size(link->resource[2]));
 	if(!dev->win_base) {
-		dev_err(&dev->p_dev->dev, "ioremap(%lu, %u) failed\n",
-			req.Base, req.Size);
+		dev_err(&dev->p_dev->dev, "ioremap(%pR) failed\n",
+			link->resource[2]);
 		pcmciamtd_release(link);
 		return -ENODEV;
 	}
-	DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
-	      dev, req.Base, dev->win_base, req.Size);
+	DEBUG(1, "mapped window dev = %p @ %pR, base = %p",
+	      dev, link->resource[2], dev->win_base);
 
 	dev->offset = 0;
 	dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
-	dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
+	dev->pcmcia_map.map_priv_2 = (unsigned long)link->resource[2];
 
 	dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp;
-	link->conf.Attributes = 0;
 	if(setvpp == 2) {
-		link->conf.Vpp = dev->vpp;
+		link->vpp = dev->vpp;
 	} else {
-		link->conf.Vpp = 0;
+		link->vpp = 0;
 	}
 
-	link->conf.IntType = INT_MEMORY;
-	link->conf.ConfigIndex = 0;
+	link->config_index = 0;
 	DEBUG(2, "Setting Configuration");
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret != 0) {
 		if (dev->win_base) {
 			iounmap(dev->win_base);
@@ -680,12 +666,6 @@
 }
 
 
-/* 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 pcmciamtd_detach(struct pcmcia_device *link)
 {
 	struct pcmciamtd_dev *dev = link->priv;
@@ -703,11 +683,6 @@
 }
 
 
-/* pcmciamtd_attach() creates an "instance" of the driver, allocating
- * local data structures for one device.  The device is registered
- * with Card Services.
- */
-
 static int pcmciamtd_probe(struct pcmcia_device *link)
 {
 	struct pcmciamtd_dev *dev;
@@ -720,9 +695,6 @@
 	dev->p_dev = link;
 	link->priv = dev;
 
-	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY;
-
 	return pcmciamtd_config(link);
 }
 
@@ -757,9 +729,7 @@
 MODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids);
 
 static struct pcmcia_driver pcmciamtd_driver = {
-	.drv		= {
-		.name	= "pcmciamtd"
-	},
+	.name		= "pcmciamtd",
 	.probe		= pcmciamtd_probe,
 	.remove		= pcmciamtd_detach,
 	.owner		= THIS_MODULE,
@@ -771,8 +741,6 @@
 
 static int __init init_pcmciamtd(void)
 {
-	info(DRIVER_DESC);
-
 	if(bankwidth && bankwidth != 1 && bankwidth != 2) {
 		info("bad bankwidth (%d), using default", bankwidth);
 		bankwidth = 2;
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 62e6870..50ab431 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -29,7 +29,6 @@
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/hdreg.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
@@ -38,6 +37,7 @@
 
 #include "mtdcore.h"
 
+static DEFINE_MUTEX(mtd_blkdevs_mutex);
 static LIST_HEAD(blktrans_majors);
 static DEFINE_MUTEX(blktrans_ref_mutex);
 
@@ -181,7 +181,7 @@
 	if (!dev)
 		return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
 
-	lock_kernel();
+	mutex_lock(&mtd_blkdevs_mutex);
 	mutex_lock(&dev->lock);
 
 	if (!dev->mtd) {
@@ -198,7 +198,7 @@
 unlock:
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
-	unlock_kernel();
+	mutex_unlock(&mtd_blkdevs_mutex);
 	return ret;
 }
 
@@ -210,7 +210,7 @@
 	if (!dev)
 		return ret;
 
-	lock_kernel();
+	mutex_lock(&mtd_blkdevs_mutex);
 	mutex_lock(&dev->lock);
 
 	/* Release one reference, we sure its not the last one here*/
@@ -223,7 +223,7 @@
 unlock:
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
-	unlock_kernel();
+	mutex_unlock(&mtd_blkdevs_mutex);
 	return ret;
 }
 
@@ -256,7 +256,7 @@
 	if (!dev)
 		return ret;
 
-	lock_kernel();
+	mutex_lock(&mtd_blkdevs_mutex);
 	mutex_lock(&dev->lock);
 
 	if (!dev->mtd)
@@ -271,7 +271,7 @@
 	}
 unlock:
 	mutex_unlock(&dev->lock);
-	unlock_kernel();
+	mutex_unlock(&mtd_blkdevs_mutex);
 	blktrans_dev_put(dev);
 	return ret;
 }
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index a825002..5ef4548 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -26,7 +26,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/backing-dev.h>
 #include <linux/compat.h>
 #include <linux/mount.h>
@@ -37,6 +37,7 @@
 #include <asm/uaccess.h>
 
 #define MTD_INODE_FS_MAGIC 0x11307854
+static DEFINE_MUTEX(mtd_mutex);
 static struct vfsmount *mtd_inode_mnt __read_mostly;
 
 /*
@@ -90,7 +91,7 @@
 	if ((file->f_mode & FMODE_WRITE) && (minor & 1))
 		return -EACCES;
 
-	lock_kernel();
+	mutex_lock(&mtd_mutex);
 	mtd = get_mtd_device(NULL, devnum);
 
 	if (IS_ERR(mtd)) {
@@ -138,7 +139,7 @@
 	file->private_data = mfi;
 
 out:
-	unlock_kernel();
+	mutex_unlock(&mtd_mutex);
 	return ret;
 } /* mtd_open */
 
@@ -866,9 +867,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&mtd_mutex);
 	ret = mtd_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&mtd_mutex);
 
 	return ret;
 }
@@ -892,7 +893,7 @@
 	void __user *argp = compat_ptr(arg);
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&mtd_mutex);
 
 	switch (cmd) {
 	case MEMWRITEOOB32:
@@ -927,7 +928,7 @@
 		ret = mtd_ioctl(file, cmd, (unsigned long)argp);
 	}
 
-	unlock_kernel();
+	mutex_unlock(&mtd_mutex);
 
 	return ret;
 }
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index b2828e8..214b03a 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -30,6 +30,8 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/completion.h>
 
 #include <asm/mach/flash.h>
 #include <mach/mxc_nand.h>
@@ -151,7 +153,7 @@
 	int			irq;
 	int			eccsize;
 
-	wait_queue_head_t	irq_waitq;
+	struct completion	op_completion;
 
 	uint8_t			*data_buf;
 	unsigned int		buf_start;
@@ -164,6 +166,7 @@
 	void			(*send_read_id)(struct mxc_nand_host *);
 	uint16_t		(*get_dev_status)(struct mxc_nand_host *);
 	int			(*check_int)(struct mxc_nand_host *);
+	void			(*irq_control)(struct mxc_nand_host *, int);
 };
 
 /* OOB placement block for use with hardware ecc generation */
@@ -216,9 +219,12 @@
 {
 	struct mxc_nand_host *host = dev_id;
 
-	disable_irq_nosync(irq);
+	if (!host->check_int(host))
+		return IRQ_NONE;
 
-	wake_up(&host->irq_waitq);
+	host->irq_control(host, 0);
+
+	complete(&host->op_completion);
 
 	return IRQ_HANDLED;
 }
@@ -245,11 +251,54 @@
 	if (!(tmp & NFC_V1_V2_CONFIG2_INT))
 		return 0;
 
-	writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
+	if (!cpu_is_mx21())
+		writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
 
 	return 1;
 }
 
+/*
+ * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit
+ * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the
+ * driver can enable/disable the irq line rather than simply masking the
+ * interrupts.
+ */
+static void irq_control_mx21(struct mxc_nand_host *host, int activate)
+{
+	if (activate)
+		enable_irq(host->irq);
+	else
+		disable_irq_nosync(host->irq);
+}
+
+static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
+{
+	uint16_t tmp;
+
+	tmp = readw(NFC_V1_V2_CONFIG1);
+
+	if (activate)
+		tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
+	else
+		tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
+
+	writew(tmp, NFC_V1_V2_CONFIG1);
+}
+
+static void irq_control_v3(struct mxc_nand_host *host, int activate)
+{
+	uint32_t tmp;
+
+	tmp = readl(NFC_V3_CONFIG2);
+
+	if (activate)
+		tmp &= ~NFC_V3_CONFIG2_INT_MSK;
+	else
+		tmp |= NFC_V3_CONFIG2_INT_MSK;
+
+	writel(tmp, NFC_V3_CONFIG2);
+}
+
 /* This function polls the NANDFC to wait for the basic operation to
  * complete by checking the INT bit of config2 register.
  */
@@ -259,10 +308,9 @@
 
 	if (useirq) {
 		if (!host->check_int(host)) {
-
-			enable_irq(host->irq);
-
-			wait_event(host->irq_waitq, host->check_int(host));
+			INIT_COMPLETION(host->op_completion);
+			host->irq_control(host, 1);
+			wait_for_completion(&host->op_completion);
 		}
 	} else {
 		while (max_retries-- > 0) {
@@ -799,6 +847,7 @@
 		NFC_V3_CONFIG2_2CMD_PHASES |
 		NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
 		NFC_V3_CONFIG2_ST_CMD(0x70) |
+		NFC_V3_CONFIG2_INT_MSK |
 		NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
 
 	if (chip->ecc.mode == NAND_ECC_HW)
@@ -1024,6 +1073,10 @@
 		host->send_read_id = send_read_id_v1_v2;
 		host->get_dev_status = get_dev_status_v1_v2;
 		host->check_int = check_int_v1_v2;
+		if (cpu_is_mx21())
+			host->irq_control = irq_control_mx21;
+		else
+			host->irq_control = irq_control_v1_v2;
 	}
 
 	if (nfc_is_v21()) {
@@ -1062,6 +1115,7 @@
 		host->send_read_id = send_read_id_v3;
 		host->check_int = check_int_v3;
 		host->get_dev_status = get_dev_status_v3;
+		host->irq_control = irq_control_v3;
 		oob_smallpage = &nandv2_hw_eccoob_smallpage;
 		oob_largepage = &nandv2_hw_eccoob_largepage;
 	} else
@@ -1093,14 +1147,34 @@
 		this->options |= NAND_USE_FLASH_BBT;
 	}
 
-	init_waitqueue_head(&host->irq_waitq);
+	init_completion(&host->op_completion);
 
 	host->irq = platform_get_irq(pdev, 0);
 
+	/*
+	 * mask the interrupt. For i.MX21 explicitely call
+	 * irq_control_v1_v2 to use the mask bit. We can't call
+	 * disable_irq_nosync() for an interrupt we do not own yet.
+	 */
+	if (cpu_is_mx21())
+		irq_control_v1_v2(host, 0);
+	else
+		host->irq_control(host, 0);
+
 	err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
 	if (err)
 		goto eirq;
 
+	host->irq_control(host, 0);
+
+	/*
+	 * Now that the interrupt is disabled make sure the interrupt
+	 * mask bit is cleared on i.MX21. Otherwise we can't read
+	 * the interrupt status bit on this machine.
+	 */
+	if (cpu_is_mx21())
+		irq_control_v1_v2(host, 1);
+
 	/* first scan to find the device and get the page size */
 	if (nand_scan_ident(mtd, 1, NULL)) {
 		err = -ENXIO;
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 133d515..513e0a7 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -413,7 +413,7 @@
 		prefetch_status = gpmc_read_status(GPMC_PREFETCH_COUNT);
 	} while (prefetch_status);
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset();
+	gpmc_prefetch_reset(info->gpmc_cs);
 
 	dma_unmap_single(&info->pdev->dev, dma_addr, len, dir);
 	return 0;
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index f702a16..3cf193f 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -1,9 +1,5 @@
-menu "UBI - Unsorted block images"
-	depends on MTD
-
-config MTD_UBI
-	tristate "Enable UBI"
-	depends on MTD
+menuconfig MTD_UBI
+	tristate "Enable UBI - Unsorted block images"
 	select CRC32
 	help
 	  UBI is a software layer above MTD layer which admits of LVM-like
@@ -12,11 +8,12 @@
 	  capabilities. Please, consult the MTD web site for more details
 	  (www.linux-mtd.infradead.org).
 
+if MTD_UBI
+
 config MTD_UBI_WL_THRESHOLD
 	int "UBI wear-leveling threshold"
 	default 4096
 	range 2 65536
-	depends on MTD_UBI
 	help
 	  This parameter defines the maximum difference between the highest
 	  erase counter value and the lowest erase counter value of eraseblocks
@@ -34,7 +31,6 @@
 	int "Percentage of reserved eraseblocks for bad eraseblocks handling"
 	default 1
 	range 0 25
-	depends on MTD_UBI
 	help
 	  If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI
 	  reserves some amount of physical eraseblocks to handle new bad
@@ -48,8 +44,6 @@
 
 config MTD_UBI_GLUEBI
 	tristate "MTD devices emulation driver (gluebi)"
-	default n
-	depends on MTD_UBI
 	help
 	   This option enables gluebi - an additional driver which emulates MTD
 	   devices on top of UBI volumes: for each UBI volumes an MTD device is
@@ -59,4 +53,5 @@
 	   software.
 
 source "drivers/mtd/ubi/Kconfig.debug"
-endmenu
+
+endif # MTD_UBI
diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug
index 61f6e5e..fad4adc 100644
--- a/drivers/mtd/ubi/Kconfig.debug
+++ b/drivers/mtd/ubi/Kconfig.debug
@@ -1,94 +1,73 @@
 comment "UBI debugging options"
-	depends on MTD_UBI
 
 config MTD_UBI_DEBUG
 	bool "UBI debugging"
 	depends on SYSFS
-	depends on MTD_UBI
 	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"
-	depends on MTD_UBI_DEBUG
-	default n
 	help
 	  This option enables UBI debugging messages.
 
 config MTD_UBI_DEBUG_PARANOID
 	bool "Extra self-checks"
-	default n
-	depends on MTD_UBI_DEBUG
 	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"
-	depends on MTD_UBI_DEBUG
-	default n
 	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"
-	depends on MTD_UBI_DEBUG
-	default n
 	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"
-	depends on MTD_UBI_DEBUG
-	default n
 	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"
-	depends on MTD_UBI_DEBUG
-	default n
 	help
 	  This option emulates erase failures with probability 1/100. Useful for
 	  debugging and testing how UBI handlines errors.
 
-menu "Additional UBI debugging messages"
-	depends on MTD_UBI_DEBUG
+comment "Additional UBI debugging messages"
 
 config MTD_UBI_DEBUG_MSG_BLD
 	bool "Additional UBI initialization and build messages"
-	default n
-	depends on MTD_UBI_DEBUG
 	help
 	  This option enables detailed UBI initialization and device build
 	  debugging messages.
 
 config MTD_UBI_DEBUG_MSG_EBA
 	bool "Eraseblock association unit messages"
-	default n
-	depends on MTD_UBI_DEBUG
 	help
 	  This option enables debugging messages from the UBI eraseblock
 	  association unit.
 
 config MTD_UBI_DEBUG_MSG_WL
 	bool "Wear-leveling unit messages"
-	default n
-	depends on MTD_UBI_DEBUG
 	help
 	  This option enables debugging messages from the UBI wear-leveling
 	  unit.
 
 config MTD_UBI_DEBUG_MSG_IO
 	bool "Input/output unit messages"
-	default n
-	depends on MTD_UBI_DEBUG
 	help
 	  This option enables debugging messages from the UBI input/output unit.
 
-endmenu # UBI debugging messages
+endif # MTD_UBI_DEBUG
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 78ae894..5ebe280 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -95,8 +95,8 @@
 static DEFINE_SPINLOCK(ubi_devices_lock);
 
 /* "Show" method for files in '/<sysfs>/class/ubi/' */
-static ssize_t ubi_version_show(struct class *class, struct class_attribute *attr,
-				char *buf)
+static ssize_t ubi_version_show(struct class *class,
+				struct class_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%d\n", UBI_VERSION);
 }
@@ -591,6 +591,7 @@
 
 	ubi->bad_peb_count = si->bad_peb_count;
 	ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
+	ubi->corr_peb_count = si->corr_peb_count;
 	ubi->max_ec = si->max_ec;
 	ubi->mean_ec = si->mean_ec;
 	ubi_msg("max. sequence number:       %llu", si->max_sqnum);
@@ -972,6 +973,7 @@
 	ubi_msg("MTD device size:            %llu MiB", ubi->flash_size >> 20);
 	ubi_msg("number of good PEBs:        %d", ubi->good_peb_count);
 	ubi_msg("number of bad PEBs:         %d", ubi->bad_peb_count);
+	ubi_msg("number of corrupted PEBs:   %d", ubi->corr_peb_count);
 	ubi_msg("max. allowed volumes:       %d", ubi->vtbl_slots);
 	ubi_msg("wear-leveling threshold:    %d", CONFIG_MTD_UBI_WL_THRESHOLD);
 	ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 3d2d1a6..af9fb0f 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -1100,4 +1100,5 @@
 	.owner          = THIS_MODULE,
 	.unlocked_ioctl = ctrl_cdev_ioctl,
 	.compat_ioctl   = ctrl_cdev_compat_ioctl,
+	.llseek		= noop_llseek,
 };
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 17a1071..9eca950 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -57,6 +57,9 @@
 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);
 
+#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__)
@@ -172,6 +175,7 @@
 #define ubi_dbg_dump_seb(seb, type)      ({})
 #define ubi_dbg_dump_mkvol_req(req)      ({})
 #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
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index fe74749..4be67181 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -418,7 +418,7 @@
 				 * may try to recover data. FIXME: but this is
 				 * not implemented.
 				 */
-				if (err == UBI_IO_BAD_HDR_READ ||
+				if (err == UBI_IO_BAD_HDR_EBADMSG ||
 				    err == UBI_IO_BAD_HDR) {
 					ubi_warn("corrupted VID header at PEB "
 						 "%d, LEB %d:%d", pnum, vol_id,
@@ -963,7 +963,7 @@
 static int is_error_sane(int err)
 {
 	if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR ||
-	    err == UBI_IO_BAD_HDR_READ || err == -ETIMEDOUT)
+	    err == UBI_IO_BAD_HDR_EBADMSG || err == -ETIMEDOUT)
 		return 0;
 	return 1;
 }
@@ -1201,6 +1201,9 @@
 
 	ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d,"
 		 " need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
+	if (ubi->corr_peb_count)
+		ubi_warn("%d PEBs are corrupted and not used",
+			ubi->corr_peb_count);
 }
 
 /**
@@ -1263,6 +1266,9 @@
 	if (ubi->avail_pebs < EBA_RESERVED_PEBS) {
 		ubi_err("no enough physical eraseblocks (%d, need %d)",
 			ubi->avail_pebs, EBA_RESERVED_PEBS);
+		if (ubi->corr_peb_count)
+			ubi_err("%d PEBs are corrupted and not used",
+				ubi->corr_peb_count);
 		err = -ENOSPC;
 		goto out_free;
 	}
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 332f992..c2960ac 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -376,25 +376,6 @@
 	return 0;
 }
 
-/**
- * check_pattern - check if buffer contains only a certain byte pattern.
- * @buf: buffer to check
- * @patt: the pattern to check
- * @size: buffer size in bytes
- *
- * This function returns %1 in there are only @patt bytes in @buf, and %0 if
- * something else was also found.
- */
-static int check_pattern(const void *buf, uint8_t patt, int size)
-{
-	int i;
-
-	for (i = 0; i < size; i++)
-		if (((const uint8_t *)buf)[i] != patt)
-			return 0;
-	return 1;
-}
-
 /* Patterns to write to a physical eraseblock when torturing it */
 static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
 
@@ -426,7 +407,7 @@
 		if (err)
 			goto out;
 
-		err = check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
+		err = ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
 		if (err == 0) {
 			ubi_err("erased PEB %d, but a non-0xFF byte found",
 				pnum);
@@ -445,7 +426,8 @@
 		if (err)
 			goto out;
 
-		err = check_pattern(ubi->peb_buf1, patterns[i], ubi->peb_size);
+		err = ubi_check_pattern(ubi->peb_buf1, patterns[i],
+					ubi->peb_size);
 		if (err == 0) {
 			ubi_err("pattern %x checking failed for PEB %d",
 				patterns[i], pnum);
@@ -517,7 +499,7 @@
 	 * In this case we probably anyway have garbage in this PEB.
 	 */
 	err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
-	if (err1 == UBI_IO_BAD_HDR_READ || err1 == UBI_IO_BAD_HDR)
+	if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
 		/*
 		 * The VID header is corrupted, so we can safely erase this
 		 * PEB and not afraid that it will be treated as a valid PEB in
@@ -712,47 +694,47 @@
  *   and corrected by the flash driver; this is harmless but may indicate that
  *   this eraseblock may become bad soon (but may be not);
  * o %UBI_IO_BAD_HDR if the erase counter header is corrupted (a CRC error);
- * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty;
+ * o %UBI_IO_BAD_HDR_EBADMSG is the same as %UBI_IO_BAD_HDR, but there also was
+ *   a data integrity error (uncorrectable ECC error in case of NAND);
+ * o %UBI_IO_FF if only 0xFF bytes were read (the PEB is supposedly empty)
  * o a negative error code in case of failure.
  */
 int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
 		       struct ubi_ec_hdr *ec_hdr, int verbose)
 {
-	int err, read_err = 0;
+	int err, read_err;
 	uint32_t crc, magic, hdr_crc;
 
 	dbg_io("read EC header from PEB %d", pnum);
 	ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
 
-	err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
-	if (err) {
-		if (err != UBI_IO_BITFLIPS && err != -EBADMSG)
-			return err;
+	read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
+	if (read_err) {
+		if (read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+			return read_err;
 
 		/*
 		 * We read all the data, but either a correctable bit-flip
-		 * occurred, or MTD reported about some data integrity error,
-		 * like an ECC error in case of NAND. The former is harmless,
-		 * the later may mean that the read data is corrupted. But we
-		 * have a CRC check-sum and we will detect this. If the EC
-		 * header is still OK, we just report this as there was a
-		 * bit-flip.
+		 * occurred, or MTD reported a data integrity error
+		 * (uncorrectable ECC error in case of NAND). The former is
+		 * harmless, the later may mean that the read data is
+		 * corrupted. But we have a CRC check-sum and we will detect
+		 * this. If the EC header is still OK, we just report this as
+		 * there was a bit-flip, to force scrubbing.
 		 */
-		if (err == -EBADMSG)
-			read_err = UBI_IO_BAD_HDR_READ;
 	}
 
 	magic = be32_to_cpu(ec_hdr->magic);
 	if (magic != UBI_EC_HDR_MAGIC) {
-		if (read_err)
-			return read_err;
+		if (read_err == -EBADMSG)
+			return UBI_IO_BAD_HDR_EBADMSG;
 
 		/*
 		 * The magic field is wrong. Let's check if we have read all
 		 * 0xFF. If yes, this physical eraseblock is assumed to be
 		 * empty.
 		 */
-		if (check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
+		if (ubi_check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
 			/* The physical eraseblock is supposedly empty */
 			if (verbose)
 				ubi_warn("no EC header found at PEB %d, "
@@ -760,7 +742,10 @@
 			else if (UBI_IO_DEBUG)
 				dbg_msg("no EC header found at PEB %d, "
 					"only 0xFF bytes", pnum);
-			return UBI_IO_PEB_EMPTY;
+			if (!read_err)
+				return UBI_IO_FF;
+			else
+				return UBI_IO_FF_BITFLIPS;
 		}
 
 		/*
@@ -788,7 +773,11 @@
 		} else if (UBI_IO_DEBUG)
 			dbg_msg("bad EC header CRC at PEB %d, calculated "
 				"%#08x, read %#08x", pnum, crc, hdr_crc);
-		return read_err ?: UBI_IO_BAD_HDR;
+
+		if (!read_err)
+			return UBI_IO_BAD_HDR;
+		else
+			return UBI_IO_BAD_HDR_EBADMSG;
 	}
 
 	/* And of course validate what has just been read from the media */
@@ -975,22 +964,16 @@
  *
  * This function reads the volume identifier header from physical eraseblock
  * @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read
- * volume identifier header. The following codes may be returned:
+ * volume identifier header. The error codes are the same as in
+ * 'ubi_io_read_ec_hdr()'.
  *
- * o %0 if the CRC checksum is correct and the header was successfully read;
- * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected
- *   and corrected by the flash driver; this is harmless but may indicate that
- *   this eraseblock may become bad soon;
- * o %UBI_IO_BAD_HDR if the volume identifier header is corrupted (a CRC
- *   error detected);
- * o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID
- *   header there);
- * o a negative error code in case of failure.
+ * Note, the implementation of this function is also very similar to
+ * 'ubi_io_read_ec_hdr()', so refer commentaries in 'ubi_io_read_ec_hdr()'.
  */
 int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
 			struct ubi_vid_hdr *vid_hdr, int verbose)
 {
-	int err, read_err = 0;
+	int err, read_err;
 	uint32_t crc, magic, hdr_crc;
 	void *p;
 
@@ -998,48 +981,29 @@
 	ubi_assert(pnum >= 0 &&  pnum < ubi->peb_count);
 
 	p = (char *)vid_hdr - ubi->vid_hdr_shift;
-	err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
+	read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
 			  ubi->vid_hdr_alsize);
-	if (err) {
-		if (err != UBI_IO_BITFLIPS && err != -EBADMSG)
-			return err;
-
-		/*
-		 * We read all the data, but either a correctable bit-flip
-		 * occurred, or MTD reported about some data integrity error,
-		 * like an ECC error in case of NAND. The former is harmless,
-		 * the later may mean the read data is corrupted. But we have a
-		 * CRC check-sum and we will identify this. If the VID header is
-		 * still OK, we just report this as there was a bit-flip.
-		 */
-		if (err == -EBADMSG)
-			read_err = UBI_IO_BAD_HDR_READ;
-	}
+	if (read_err && read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+		return read_err;
 
 	magic = be32_to_cpu(vid_hdr->magic);
 	if (magic != UBI_VID_HDR_MAGIC) {
-		if (read_err)
-			return read_err;
+		if (read_err == -EBADMSG)
+			return UBI_IO_BAD_HDR_EBADMSG;
 
-		/*
-		 * If we have read all 0xFF bytes, the VID header probably does
-		 * not exist and the physical eraseblock is assumed to be free.
-		 */
-		if (check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
-			/* The physical eraseblock is supposedly free */
+		if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
 			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);
-			return UBI_IO_PEB_FREE;
+			if (!read_err)
+				return UBI_IO_FF;
+			else
+				return UBI_IO_FF_BITFLIPS;
 		}
 
-		/*
-		 * This is not a valid VID header, and these are not 0xFF
-		 * bytes. Report that the header is corrupted.
-		 */
 		if (verbose) {
 			ubi_warn("bad magic number at PEB %d: %08x instead of "
 				 "%08x", pnum, magic, UBI_VID_HDR_MAGIC);
@@ -1061,20 +1025,18 @@
 		} else if (UBI_IO_DEBUG)
 			dbg_msg("bad CRC at PEB %d, calculated %#08x, "
 				"read %#08x", pnum, crc, hdr_crc);
-		return read_err ?: UBI_IO_BAD_HDR;
+		if (!read_err)
+			return UBI_IO_BAD_HDR;
+		else
+			return UBI_IO_BAD_HDR_EBADMSG;
 	}
 
-	/* Validate the VID header that we have just read */
 	err = validate_vid_hdr(ubi, vid_hdr);
 	if (err) {
 		ubi_err("validation failed for PEB %d", pnum);
 		return -EINVAL;
 	}
 
-	/*
-	 * If there was a read error (%-EBADMSG), but the header CRC is still
-	 * OK, report about a bit-flip to force scrubbing on this PEB.
-	 */
 	return read_err ? UBI_IO_BITFLIPS : 0;
 }
 
@@ -1383,7 +1345,7 @@
 		goto error;
 	}
 
-	err = check_pattern(ubi->dbg_peb_buf, 0xFF, len);
+	err = ubi_check_pattern(ubi->dbg_peb_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);
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c
index 22ad314..ff2a65c 100644
--- a/drivers/mtd/ubi/misc.c
+++ b/drivers/mtd/ubi/misc.c
@@ -103,3 +103,22 @@
 	if (ubi->beb_rsvd_level < MIN_RESEVED_PEBS)
 		ubi->beb_rsvd_level = MIN_RESEVED_PEBS;
 }
+
+/**
+ * ubi_check_pattern - check if buffer contains only a certain byte pattern.
+ * @buf: buffer to check
+ * @patt: the pattern to check
+ * @size: buffer size in bytes
+ *
+ * This function returns %1 in there are only @patt bytes in @buf, and %0 if
+ * something else was also found.
+ */
+int ubi_check_pattern(const void *buf, uint8_t patt, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		if (((const uint8_t *)buf)[i] != patt)
+			return 0;
+	return 1;
+}
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 69b52e9..3c63186 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -29,7 +29,7 @@
  * objects which are kept in volume RB-tree with root at the @volumes field.
  * The RB-tree is indexed by the volume ID.
  *
- * Found logical eraseblocks are represented by &struct ubi_scan_leb objects.
+ * Scanned logical eraseblocks are represented by &struct ubi_scan_leb objects.
  * These objects are kept in per-volume RB-trees with the root at the
  * corresponding &struct ubi_scan_volume object. To put it differently, we keep
  * an RB-tree of per-volume objects and each of these objects is the root of
@@ -38,6 +38,33 @@
  * Corrupted physical eraseblocks are put to the @corr list, free physical
  * eraseblocks are put to the @free list and the physical eraseblock to be
  * erased are put to the @erase list.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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
+ *     NAND), it is probably a PEB which was being erased when power cut
+ *     happened.
  */
 
 #include <linux/err.h>
@@ -62,26 +89,26 @@
  * @si: scanning information
  * @pnum: physical eraseblock number to add
  * @ec: erase counter of the physical eraseblock
+ * @to_head: if not zero, add to the head of the list
  * @list: the list to add to
  *
- * This function adds physical eraseblock @pnum to free, erase, corrupted or
- * alien lists. Returns zero in case of success and a negative error code in
- * case of failure.
+ * This function adds physical eraseblock @pnum to free, erase, or alien lists.
+ * If @to_head is not zero, PEB will be added to the head of the list, which
+ * basically means it will be processed first later. E.g., we add corrupted
+ * PEBs (corrupted due to power cuts) to the head of the erase list to make
+ * sure we erase them first and get rid of corruptions ASAP. This function
+ * returns zero in case of success and a negative error code in case of
+ * failure.
  */
-static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
+static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
 		       struct list_head *list)
 {
 	struct ubi_scan_leb *seb;
 
 	if (list == &si->free) {
 		dbg_bld("add to free: PEB %d, EC %d", pnum, ec);
-		si->free_peb_count += 1;
 	} else if (list == &si->erase) {
 		dbg_bld("add to erase: PEB %d, EC %d", pnum, ec);
-		si->erase_peb_count += 1;
-	} else if (list == &si->corr) {
-		dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
-		si->corr_peb_count += 1;
 	} else if (list == &si->alien) {
 		dbg_bld("add to alien: PEB %d, EC %d", pnum, ec);
 		si->alien_peb_count += 1;
@@ -94,7 +121,37 @@
 
 	seb->pnum = pnum;
 	seb->ec = ec;
-	list_add_tail(&seb->u.list, list);
+	if (to_head)
+		list_add(&seb->u.list, list);
+	else
+		list_add_tail(&seb->u.list, list);
+	return 0;
+}
+
+/**
+ * add_corrupted - add a corrupted physical eraseblock.
+ * @si: scanning information
+ * @pnum: physical eraseblock number to add
+ * @ec: erase counter of the physical eraseblock
+ *
+ * This function adds corrupted physical eraseblock @pnum to the 'corr' list.
+ * The corruption was presumably not caused by a power cut. Returns zero in
+ * case of success and a negative error code in case of failure.
+ */
+static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
+{
+	struct ubi_scan_leb *seb;
+
+	dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
+
+	seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
+	if (!seb)
+		return -ENOMEM;
+
+	si->corr_peb_count += 1;
+	seb->pnum = pnum;
+	seb->ec = ec;
+	list_add(&seb->u.list, &si->corr);
 	return 0;
 }
 
@@ -258,8 +315,8 @@
 		 * created before sequence numbers support has been added. At
 		 * that times we used 32-bit LEB versions stored in logical
 		 * eraseblocks. That was before UBI got into mainline. We do not
-		 * support these images anymore. Well, those images will work
-		 * still work, but only if no unclean reboots happened.
+		 * support these images anymore. Well, those images still work,
+		 * but only if no unclean reboots happened.
 		 */
 		ubi_err("unsupported on-flash UBI format\n");
 		return -EINVAL;
@@ -285,19 +342,25 @@
 			return 1;
 		}
 	} else {
-		pnum = seb->pnum;
+		if (!seb->copy_flag) {
+			/* It is not a copy, so it is newer */
+			dbg_bld("first PEB %d is newer, copy_flag is unset",
+				pnum);
+			return bitflips << 1;
+		}
 
 		vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
 		if (!vh)
 			return -ENOMEM;
 
+		pnum = seb->pnum;
 		err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
 		if (err) {
 			if (err == UBI_IO_BITFLIPS)
 				bitflips = 1;
 			else {
 				dbg_err("VID of PEB %d header is bad, but it "
-					"was OK earlier", pnum);
+					"was OK earlier, err %d", pnum, err);
 				if (err > 0)
 					err = -EIO;
 
@@ -305,14 +368,6 @@
 			}
 		}
 
-		if (!vh->copy_flag) {
-			/* It is not a copy, so it is newer */
-			dbg_bld("first PEB %d is newer, copy_flag is unset",
-				pnum);
-			err = bitflips << 1;
-			goto out_free_vidh;
-		}
-
 		vid_hdr = vh;
 	}
 
@@ -463,18 +518,15 @@
 			if (err)
 				return err;
 
-			if (cmp_res & 4)
-				err = add_to_list(si, seb->pnum, seb->ec,
-						  &si->corr);
-			else
-				err = add_to_list(si, seb->pnum, seb->ec,
-						  &si->erase);
+			err = add_to_list(si, seb->pnum, seb->ec, cmp_res & 4,
+					  &si->erase);
 			if (err)
 				return err;
 
 			seb->ec = ec;
 			seb->pnum = pnum;
 			seb->scrub = ((cmp_res & 2) || bitflips);
+			seb->copy_flag = vid_hdr->copy_flag;
 			seb->sqnum = sqnum;
 
 			if (sv->highest_lnum == lnum)
@@ -487,10 +539,8 @@
 			 * This logical eraseblock is older than the one found
 			 * previously.
 			 */
-			if (cmp_res & 4)
-				return add_to_list(si, pnum, ec, &si->corr);
-			else
-				return add_to_list(si, pnum, ec, &si->erase);
+			return add_to_list(si, pnum, ec, cmp_res & 4,
+					   &si->erase);
 		}
 	}
 
@@ -510,8 +560,9 @@
 	seb->ec = ec;
 	seb->pnum = pnum;
 	seb->lnum = lnum;
-	seb->sqnum = sqnum;
 	seb->scrub = bitflips;
+	seb->copy_flag = vid_hdr->copy_flag;
+	seb->sqnum = sqnum;
 
 	if (sv->highest_lnum <= lnum) {
 		sv->highest_lnum = lnum;
@@ -521,7 +572,6 @@
 	sv->leb_count += 1;
 	rb_link_node(&seb->u.rb, parent, p);
 	rb_insert_color(&seb->u.rb, &sv->root);
-	si->used_peb_count += 1;
 	return 0;
 }
 
@@ -668,8 +718,8 @@
 struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
 					   struct ubi_scan_info *si)
 {
-	int err = 0, i;
-	struct ubi_scan_leb *seb;
+	int err = 0;
+	struct ubi_scan_leb *seb, *tmp_seb;
 
 	if (!list_empty(&si->free)) {
 		seb = list_entry(si->free.next, struct ubi_scan_leb, u.list);
@@ -678,41 +728,89 @@
 		return seb;
 	}
 
-	for (i = 0; i < 2; i++) {
-		struct list_head *head;
-		struct ubi_scan_leb *tmp_seb;
+	/*
+	 * We try to erase the first physical eraseblock from the erase list
+	 * and pick it if we succeed, or try to erase the next one if not. And
+	 * so forth. We don't want to take care about bad eraseblocks here -
+	 * they'll be handled later.
+	 */
+	list_for_each_entry_safe(seb, tmp_seb, &si->erase, u.list) {
+		if (seb->ec == UBI_SCAN_UNKNOWN_EC)
+			seb->ec = si->mean_ec;
 
-		if (i == 0)
-			head = &si->erase;
-		else
-			head = &si->corr;
+		err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
+		if (err)
+			continue;
 
-		/*
-		 * We try to erase the first physical eraseblock from the @head
-		 * list and pick it if we succeed, or try to erase the
-		 * next one if not. And so forth. We don't want to take care
-		 * about bad eraseblocks here - they'll be handled later.
-		 */
-		list_for_each_entry_safe(seb, tmp_seb, head, u.list) {
-			if (seb->ec == UBI_SCAN_UNKNOWN_EC)
-				seb->ec = si->mean_ec;
-
-			err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
-			if (err)
-				continue;
-
-			seb->ec += 1;
-			list_del(&seb->u.list);
-			dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
-			return seb;
-		}
+		seb->ec += 1;
+		list_del(&seb->u.list);
+		dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
+		return seb;
 	}
 
-	ubi_err("no eraseblocks found");
+	ubi_err("no free eraseblocks");
 	return ERR_PTR(-ENOSPC);
 }
 
 /**
+ * check_corruption - check the data area of PEB.
+ * @ubi: UBI device description object
+ * @vid_hrd: the (corrupted) VID header of this PEB
+ * @pnum: the physical eraseblock number to check
+ *
+ * This is a helper function which is used to distinguish between VID header
+ * corruptions caused by power cuts and other reasons. If the PEB contains only
+ * 0xFF bytes in the data area, the VID header is most probably corrupted
+ * because of a power cut (%0 is returned in this case). Otherwise, it was
+ * probably corrupted for some other reasons (%1 is returned in this case). A
+ * negative error code is returned if a read error occurred.
+ *
+ * If the corruption reason was a power cut, UBI can safely erase this PEB.
+ * Otherwise, it should preserve it to avoid possibly destroying important
+ * information.
+ */
+static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
+			    int pnum)
+{
+	int err;
+
+	mutex_lock(&ubi->buf_mutex);
+	memset(ubi->peb_buf1, 0x00, ubi->leb_size);
+
+	err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
+			  ubi->leb_size);
+	if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
+		/*
+		 * Bit-flips or integrity errors while reading the data area.
+		 * It is difficult to say for sure what type of corruption is
+		 * this, but presumably a power cut happened while this PEB was
+		 * erased, so it became unstable and corrupted, and should be
+		 * erased.
+		 */
+		return 0;
+	}
+
+	if (err)
+		return err;
+
+	if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) {
+		mutex_unlock(&ubi->buf_mutex);
+		return 0;
+	}
+
+	ubi_err("PEB %d contains corrupted VID header, and the data does not "
+		"contain all 0xFF, this may be a non-UBI PEB or a severe VID "
+		"header corruption which requires manual inspection", pnum);
+	ubi_dbg_dump_vid_hdr(vid_hdr);
+	dbg_msg("hexdump of PEB %d offset %d, length %d",
+		pnum, ubi->leb_start, ubi->leb_size);
+	ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+			       ubi->peb_buf1, ubi->leb_size, 1);
+	mutex_unlock(&ubi->buf_mutex);
+	return 1;
+}
+
+/**
  * process_eb - read, check UBI headers, and add them to scanning information.
  * @ubi: UBI device description object
  * @si: scanning information
@@ -725,7 +823,7 @@
 		      int pnum)
 {
 	long long uninitialized_var(ec);
-	int err, bitflips = 0, vol_id, ec_corr = 0;
+	int err, bitflips = 0, vol_id, ec_err = 0;
 
 	dbg_bld("scan PEB %d", pnum);
 
@@ -746,22 +844,37 @@
 	err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
 	if (err < 0)
 		return err;
-	else if (err == UBI_IO_BITFLIPS)
+	switch (err) {
+	case 0:
+		break;
+	case UBI_IO_BITFLIPS:
 		bitflips = 1;
-	else if (err == UBI_IO_PEB_EMPTY)
-		return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase);
-	else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) {
+		break;
+	case UBI_IO_FF:
+		si->empty_peb_count += 1;
+		return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 0,
+				   &si->erase);
+	case UBI_IO_FF_BITFLIPS:
+		si->empty_peb_count += 1;
+		return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 1,
+				   &si->erase);
+	case UBI_IO_BAD_HDR_EBADMSG:
+	case UBI_IO_BAD_HDR:
 		/*
 		 * We have to also look at the VID header, possibly it is not
 		 * corrupted. Set %bitflips flag in order to make this PEB be
 		 * moved and EC be re-created.
 		 */
-		ec_corr = err;
+		ec_err = err;
 		ec = UBI_SCAN_UNKNOWN_EC;
 		bitflips = 1;
+		break;
+	default:
+		ubi_err("'ubi_io_read_ec_hdr()' returned unknown code %d", err);
+		return -EINVAL;
 	}
 
-	if (!ec_corr) {
+	if (!ec_err) {
 		int image_seq;
 
 		/* Make sure UBI version is OK */
@@ -814,24 +927,67 @@
 	err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0);
 	if (err < 0)
 		return err;
-	else if (err == UBI_IO_BITFLIPS)
+	switch (err) {
+	case 0:
+		break;
+	case UBI_IO_BITFLIPS:
 		bitflips = 1;
-	else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR ||
-		 (err == UBI_IO_PEB_FREE && ec_corr)) {
-		/* VID header is corrupted */
-		if (err == UBI_IO_BAD_HDR_READ ||
-		    ec_corr == UBI_IO_BAD_HDR_READ)
-			si->read_err_count += 1;
-		err = add_to_list(si, pnum, ec, &si->corr);
+		break;
+	case UBI_IO_BAD_HDR_EBADMSG:
+		if (ec_err == UBI_IO_BAD_HDR_EBADMSG)
+			/*
+			 * Both EC and VID headers are corrupted and were read
+			 * with data integrity error, probably this is a bad
+			 * PEB, bit it is not marked as bad yet. This may also
+			 * be a result of power cut during erasure.
+			 */
+			si->maybe_bad_peb_count += 1;
+	case UBI_IO_BAD_HDR:
+		if (ec_err)
+			/*
+			 * Both headers are corrupted. There is a possibility
+			 * that this a valid UBI PEB which has corresponding
+			 * LEB, but the headers are corrupted. However, it is
+			 * impossible to distinguish it from a PEB which just
+			 * contains garbage because of a power cut during erase
+			 * operation. So we just schedule this PEB for erasure.
+			 */
+			err = 0;
+		else
+			/*
+			 * The EC was OK, but the VID header is corrupted. We
+			 * have to check what is in the data area.
+			 */
+			err = check_corruption(ubi, vidh, pnum);
+
+		if (err < 0)
+			return err;
+		else if (!err)
+			/* This corruption is caused by a power cut */
+			err = add_to_list(si, pnum, ec, 1, &si->erase);
+		else
+			/* This is an unexpected corruption */
+			err = add_corrupted(si, pnum, ec);
 		if (err)
 			return err;
 		goto adjust_mean_ec;
-	} else if (err == UBI_IO_PEB_FREE) {
-		/* No VID header - the physical eraseblock is free */
-		err = add_to_list(si, pnum, ec, &si->free);
+	case UBI_IO_FF_BITFLIPS:
+		err = add_to_list(si, pnum, ec, 1, &si->erase);
 		if (err)
 			return err;
 		goto adjust_mean_ec;
+	case UBI_IO_FF:
+		if (ec_err)
+			err = add_to_list(si, pnum, ec, 1, &si->erase);
+		else
+			err = add_to_list(si, pnum, ec, 0, &si->free);
+		if (err)
+			return err;
+		goto adjust_mean_ec;
+	default:
+		ubi_err("'ubi_io_read_vid_hdr()' returned unknown code %d",
+			err);
+		return -EINVAL;
 	}
 
 	vol_id = be32_to_cpu(vidh->vol_id);
@@ -843,7 +999,7 @@
 		case UBI_COMPAT_DELETE:
 			ubi_msg("\"delete\" compatible internal volume %d:%d"
 				" found, will remove it", vol_id, lnum);
-			err = add_to_list(si, pnum, ec, &si->erase);
+			err = add_to_list(si, pnum, ec, 1, &si->erase);
 			if (err)
 				return err;
 			return 0;
@@ -858,7 +1014,7 @@
 		case UBI_COMPAT_PRESERVE:
 			ubi_msg("\"preserve\" compatible internal volume %d:%d"
 				" found", vol_id, lnum);
-			err = add_to_list(si, pnum, ec, &si->alien);
+			err = add_to_list(si, pnum, ec, 0, &si->alien);
 			if (err)
 				return err;
 			return 0;
@@ -870,7 +1026,7 @@
 		}
 	}
 
-	if (ec_corr)
+	if (ec_err)
 		ubi_warn("valid VID header but corrupted EC header at PEB %d",
 			 pnum);
 	err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips);
@@ -878,7 +1034,7 @@
 		return err;
 
 adjust_mean_ec:
-	if (!ec_corr) {
+	if (!ec_err) {
 		si->ec_sum += ec;
 		si->ec_count += 1;
 		if (ec > si->max_ec)
@@ -904,19 +1060,20 @@
 static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
 {
 	struct ubi_scan_leb *seb;
-	int max_corr;
+	int max_corr, peb_count;
 
-	max_corr = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
-	max_corr = max_corr / 20 ?: 8;
+	peb_count = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
+	max_corr = peb_count / 20 ?: 8;
 
 	/*
-	 * Few corrupted PEBs are not a problem and may be just a result of
+	 * Few corrupted PEBs is not a problem and may be just a result of
 	 * unclean reboots. However, many of them may indicate some problems
 	 * with the flash HW or driver.
 	 */
-	if (si->corr_peb_count >= 8) {
-		ubi_warn("%d PEBs are corrupted", si->corr_peb_count);
-		printk(KERN_WARNING "corrupted PEBs are:");
+	if (si->corr_peb_count) {
+		ubi_err("%d PEBs are corrupted and preserved",
+			si->corr_peb_count);
+		printk(KERN_ERR "Corrupted PEBs are:");
 		list_for_each_entry(seb, &si->corr, u.list)
 			printk(KERN_CONT " %d", seb->pnum);
 		printk(KERN_CONT "\n");
@@ -931,41 +1088,35 @@
 		}
 	}
 
-	if (si->free_peb_count + si->used_peb_count +
-	    si->alien_peb_count == 0) {
-		/* No UBI-formatted eraseblocks were found */
-		if (si->corr_peb_count == si->read_err_count &&
-		    si->corr_peb_count < 8) {
-			/* No or just few corrupted PEBs, and all of them had a
-			 * read error. We assume that those are bad PEBs, which
-			 * were just not marked as bad so far.
-			 *
-			 * This piece of code basically tries to distinguish
-			 * between the following 2 situations:
-			 *
-			 * 1. Flash is empty, but there are few bad PEBs, which
-			 *    are not marked as bad so far, and which were read
-			 *    with error. We want to go ahead and format this
-			 *    flash. While formating, the faulty PEBs will
-			 *    probably be marked as bad.
-			 *
-			 * 2. Flash probably contains non-UBI data and we do
-			 * not want to format it and destroy possibly needed
-			 * data (e.g., consider the case when the bootloader
-			 * MTD partition was accidentally fed to UBI).
-			 */
+	if (si->empty_peb_count + si->maybe_bad_peb_count == peb_count) {
+		/*
+		 * All PEBs are empty, or almost all - a couple PEBs look like
+		 * they may be bad PEBs which were not marked as bad yet.
+		 *
+		 * This piece of code basically tries to distinguish between
+		 * the following situations:
+		 *
+		 * 1. Flash is empty, but there are few bad PEBs, which are not
+		 *    marked as bad so far, and which were read with error. We
+		 *    want to go ahead and format this flash. While formatting,
+		 *    the faulty PEBs will probably be marked as bad.
+		 *
+		 * 2. Flash contains non-UBI data and we do not want to format
+		 *    it and destroy possibly important information.
+		 */
+		if (si->maybe_bad_peb_count <= 2) {
 			si->is_empty = 1;
 			ubi_msg("empty MTD device detected");
-			get_random_bytes(&ubi->image_seq, sizeof(ubi->image_seq));
+			get_random_bytes(&ubi->image_seq,
+					 sizeof(ubi->image_seq));
 		} else {
-			ubi_err("MTD device possibly contains non-UBI data, "
-				"refusing it");
+			ubi_err("MTD device is not UBI-formatted and possibly "
+				"contains non-UBI data - refusing it");
 			return -EINVAL;
 		}
+
 	}
 
-	if (si->corr_peb_count > 0)
-		ubi_msg("corrupted PEBs will be formatted");
 	return 0;
 }
 
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index 2576a8d..a3264f0 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -30,6 +30,7 @@
  * @pnum: physical eraseblock number
  * @lnum: logical eraseblock number
  * @scrub: if this physical eraseblock needs scrubbing
+ * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
  * @sqnum: sequence number
  * @u: unions RB-tree or @list links
  * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects
@@ -42,7 +43,8 @@
 	int ec;
 	int pnum;
 	int lnum;
-	int scrub;
+	unsigned int scrub:1;
+	unsigned int copy_flag:1;
 	unsigned long long sqnum;
 	union {
 		struct rb_node rb;
@@ -91,14 +93,13 @@
  * @erase: list of physical eraseblocks which have to be erased
  * @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
  *         those belonging to "preserve"-compatible internal volumes)
- * @used_peb_count: count of used PEBs
  * @corr_peb_count: count of PEBs in the @corr list
- * @read_err_count: count of PEBs read with error (%UBI_IO_BAD_HDR_READ was
- *                  returned)
- * @free_peb_count: count of PEBs in the @free list
- * @erase_peb_count: count of PEBs in the @erase list
+ * @empty_peb_count: count of PEBs which are presumably empty (contain only
+ *                   0xFF bytes)
  * @alien_peb_count: count of PEBs in the @alien list
  * @bad_peb_count: count of bad physical eraseblocks
+ * @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked
+ *                       as bad yet, but which look like bad
  * @vols_found: number of volumes found during scanning
  * @highest_vol_id: highest volume ID
  * @is_empty: flag indicating whether the MTD device is empty or not
@@ -119,13 +120,11 @@
 	struct list_head free;
 	struct list_head erase;
 	struct list_head alien;
-	int used_peb_count;
 	int corr_peb_count;
-	int read_err_count;
-	int free_peb_count;
-	int erase_peb_count;
+	int empty_peb_count;
 	int alien_peb_count;
 	int bad_peb_count;
+	int maybe_bad_peb_count;
 	int vols_found;
 	int highest_vol_id;
 	int is_empty;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 0359e0c..0b0149c 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -85,21 +85,26 @@
 /*
  * Error codes returned by the I/O sub-system.
  *
- * UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only
- *                   %0xFF bytes
- * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a
- *                  valid erase counter header, and the rest are %0xFF bytes
+ * UBI_IO_FF: the read region of flash contains only 0xFFs
+ * UBI_IO_FF_BITFLIPS: the same as %UBI_IO_FF, but also also there was a data
+ *                     integrity error reported by the MTD driver
+ *                     (uncorrectable ECC error in case of NAND)
  * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC)
- * UBI_IO_BAD_HDR_READ: the same as %UBI_IO_BAD_HDR, but also there was a read
- * 			error reported by the flash driver
+ * UBI_IO_BAD_HDR_EBADMSG: the same as %UBI_IO_BAD_HDR, but also there was a
+ *                         data integrity error reported by the MTD driver
+ *                         (uncorrectable ECC error in case of NAND)
  * UBI_IO_BITFLIPS: bit-flips were detected and corrected
+ *
+ * Note, it is probably better to have bit-flip and ebadmsg as flags which can
+ * be or'ed with other error code. But this is a big change because there are
+ * may callers, so it does not worth the risk of introducing a bug
  */
 enum {
-	UBI_IO_PEB_EMPTY = 1,
-	UBI_IO_PEB_FREE,
+	UBI_IO_FF = 1,
+	UBI_IO_FF_BITFLIPS,
 	UBI_IO_BAD_HDR,
-	UBI_IO_BAD_HDR_READ,
-	UBI_IO_BITFLIPS
+	UBI_IO_BAD_HDR_EBADMSG,
+	UBI_IO_BITFLIPS,
 };
 
 /*
@@ -356,6 +361,8 @@
  * @peb_size: physical eraseblock size
  * @bad_peb_count: count of bad physical eraseblocks
  * @good_peb_count: count of good physical eraseblocks
+ * @corr_peb_count: count of corrupted physical eraseblocks (preserved and not
+ *                  used by UBI)
  * @erroneous_peb_count: count of erroneous physical eraseblocks in @erroneous
  * @max_erroneous: maximum allowed amount of erroneous physical eraseblocks
  * @min_io_size: minimal input/output unit size of the underlying MTD device
@@ -442,6 +449,7 @@
 	int peb_size;
 	int bad_peb_count;
 	int good_peb_count;
+	int corr_peb_count;
 	int erroneous_peb_count;
 	int max_erroneous;
 	int min_io_size;
@@ -506,6 +514,7 @@
 		      int length);
 int ubi_check_volume(struct ubi_device *ubi, int vol_id);
 void ubi_calculate_reserved(struct ubi_device *ubi);
+int ubi_check_pattern(const void *buf, uint8_t patt, int size);
 
 /* eba.c */
 int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index e42afab..c47620d 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -261,6 +261,9 @@
 	/* Reserve physical eraseblocks */
 	if (vol->reserved_pebs > ubi->avail_pebs) {
 		dbg_err("not enough PEBs, only %d available", ubi->avail_pebs);
+		if (ubi->corr_peb_count)
+			dbg_err("%d PEBs are corrupted and not used",
+				ubi->corr_peb_count);
 		err = -ENOSPC;
 		goto out_unlock;
 	}
@@ -527,6 +530,9 @@
 		if (pebs > ubi->avail_pebs) {
 			dbg_err("not enough PEBs: requested %d, available %d",
 				pebs, ubi->avail_pebs);
+			if (ubi->corr_peb_count)
+				dbg_err("%d PEBs are corrupted and not used",
+					ubi->corr_peb_count);
 			spin_unlock(&ubi->volumes_lock);
 			err = -ENOSPC;
 			goto out_free;
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 14c10be..fcdb7f6 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -366,7 +366,7 @@
 		 * Probably this physical eraseblock went bad, try to pick
 		 * another one.
 		 */
-		list_add_tail(&new_seb->u.list, &si->corr);
+		list_add(&new_seb->u.list, &si->erase);
 		goto retry;
 	}
 	kfree(new_seb);
@@ -662,9 +662,13 @@
 	ubi->vol_count += 1;
 	vol->ubi = ubi;
 
-	if (reserved_pebs > ubi->avail_pebs)
+	if (reserved_pebs > ubi->avail_pebs) {
 		ubi_err("not enough PEBs, required %d, available %d",
 			reserved_pebs, ubi->avail_pebs);
+		if (ubi->corr_peb_count)
+			ubi_err("%d PEBs are corrupted and not used",
+				ubi->corr_peb_count);
+	}
 	ubi->rsvd_pebs += reserved_pebs;
 	ubi->avail_pebs -= reserved_pebs;
 
@@ -837,7 +841,7 @@
 			return PTR_ERR(ubi->vtbl);
 	}
 
-	ubi->avail_pebs = ubi->good_peb_count;
+	ubi->avail_pebs = ubi->good_peb_count - ubi->corr_peb_count;
 
 	/*
 	 * The layout volume is OK, initialize the corresponding in-RAM data
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 97a4356..655bbbe 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -745,7 +745,7 @@
 
 	err = ubi_io_read_vid_hdr(ubi, e1->pnum, vid_hdr, 0);
 	if (err && err != UBI_IO_BITFLIPS) {
-		if (err == UBI_IO_PEB_FREE) {
+		if (err == UBI_IO_FF) {
 			/*
 			 * We are trying to move PEB without a VID header. UBI
 			 * always write VID headers shortly after the PEB was
@@ -759,6 +759,16 @@
 			dbg_wl("PEB %d has no VID header", e1->pnum);
 			protect = 1;
 			goto out_not_moved;
+		} else if (err == UBI_IO_FF_BITFLIPS) {
+			/*
+			 * The same situation as %UBI_IO_FF, but bit-flips were
+			 * detected. It is better to schedule this PEB for
+			 * scrubbing.
+			 */
+			dbg_wl("PEB %d has no VID header but has bit-flips",
+			       e1->pnum);
+			scrubbing = 1;
+			goto out_not_moved;
 		}
 
 		ubi_err("error %d while reading VID header from PEB %d",
@@ -1468,22 +1478,6 @@
 		ubi->lookuptbl[e->pnum] = e;
 	}
 
-	list_for_each_entry(seb, &si->corr, u.list) {
-		cond_resched();
-
-		e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
-		if (!e)
-			goto out_free;
-
-		e->pnum = seb->pnum;
-		e->ec = seb->ec;
-		ubi->lookuptbl[e->pnum] = e;
-		if (schedule_erase(ubi, e, 0)) {
-			kmem_cache_free(ubi_wl_entry_slab, e);
-			goto out_free;
-		}
-	}
-
 	ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
 		ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
 			cond_resched();
@@ -1510,6 +1504,9 @@
 	if (ubi->avail_pebs < WL_RESERVED_PEBS) {
 		ubi_err("no enough physical eraseblocks (%d, need %d)",
 			ubi->avail_pebs, WL_RESERVED_PEBS);
+		if (ubi->corr_peb_count)
+			ubi_err("%d PEBs are corrupted and not used",
+				ubi->corr_peb_count);
 		goto out_free;
 	}
 	ubi->avail_pebs -= WL_RESERVED_PEBS;
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index baac246..4777a1c 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -337,10 +337,10 @@
     /* Finish setting the board's parameters. */
     ei_status.stop_page = EL2_MB1_STOP_PG;
     ei_status.word16 = wordlength;
-    ei_status.reset_8390 = &el2_reset_8390;
-    ei_status.get_8390_hdr = &el2_get_8390_hdr;
-    ei_status.block_input = &el2_block_input;
-    ei_status.block_output = &el2_block_output;
+    ei_status.reset_8390 = el2_reset_8390;
+    ei_status.get_8390_hdr = el2_get_8390_hdr;
+    ei_status.block_input = el2_block_input;
+    ei_status.block_output = el2_block_output;
 
     if (dev->irq == 2)
 	dev->irq = 9;
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index 3bba835..cdf7226 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -662,7 +662,9 @@
 		pr_warning(" *** Warning: this IRQ is unlikely to work! ***\n");
 
 	{
-		char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
+		static const char * const ram_split[] = {
+			"5:3", "3:1", "1:1", "3:5"
+		};
 		__u32 config;
 		EL3WINDOW(3);
 		vp->available_media = inw(ioaddr + Wn3_Options);
@@ -734,7 +736,7 @@
 		init_timer(&vp->timer);
 		vp->timer.expires = jiffies + media_tbl[dev->if_port].wait;
 		vp->timer.data = (unsigned long) dev;
-		vp->timer.function = &corkscrew_timer;	/* timer handler */
+		vp->timer.function = corkscrew_timer;	/* timer handler */
 		add_timer(&vp->timer);
 	} else
 		dev->if_port = vp->default_media;
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index a7b0e5e..de579d0 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -287,7 +287,7 @@
 
 	elmc_id_attn586();	/* disable interrupts */
 
-	ret = request_irq(dev->irq, elmc_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+	ret = request_irq(dev->irq, elmc_interrupt, IRQF_SHARED,
 			  dev->name, dev);
 	if (ret) {
 		pr_err("%s: couldn't get irq %d\n", dev->name, dev->irq);
@@ -463,7 +463,7 @@
 
 	/* we didn't find any 3c523 in the slots we checked for */
 	if (slot == MCA_NOTFOUND)
-		return ((base_addr || irq) ? -ENXIO : -ENODEV);
+		return (base_addr || irq) ? -ENXIO : -ENODEV;
 
 	mca_set_adapter_name(slot, "3Com 3c523 Etherlink/MC");
 	mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev);
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index 70705d1..013b7c3 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/3c527.c
@@ -443,7 +443,7 @@
 	 *	Grab the IRQ
 	 */
 
-	err = request_irq(dev->irq, mc32_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM, DRV_NAME, dev);
+	err = request_irq(dev->irq, mc32_interrupt, IRQF_SHARED, DRV_NAME, dev);
 	if (err) {
 		release_region(dev->base_addr, MC32_IO_EXTENT);
 		pr_err("%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq);
@@ -522,7 +522,7 @@
 	lp->tx_len 		= lp->exec_box->data[9];   /* Transmit list count */
 	lp->rx_len 		= lp->exec_box->data[11];  /* Receive list count */
 
-	init_MUTEX_LOCKED(&lp->cmd_mutex);
+	sema_init(&lp->cmd_mutex, 0);
 	init_completion(&lp->execution_cmd);
 	init_completion(&lp->xceiver_cmd);
 
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index fa42103..e1da258 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1742,7 +1742,7 @@
 
 	/* Use the now-standard shared IRQ implementation. */
 	if ((retval = request_irq(dev->irq, vp->full_bus_master_rx ?
-				&boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev))) {
+				boomerang_interrupt : vortex_interrupt, IRQF_SHARED, dev->name, dev))) {
 		pr_err("%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
 		goto err;
 	}
@@ -2942,6 +2942,9 @@
 {
 	struct vortex_private *vp = netdev_priv(dev);
 
+	if (!VORTEX_PCI(vp))
+		return;
+
 	wol->supported = WAKE_MAGIC;
 
 	wol->wolopts = 0;
@@ -2952,6 +2955,10 @@
 static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
 	struct vortex_private *vp = netdev_priv(dev);
+
+	if (!VORTEX_PCI(vp))
+		return -EOPNOTSUPP;
+
 	if (wol->wolopts & ~WAKE_MAGIC)
 		return -EINVAL;
 
@@ -3201,6 +3208,9 @@
 			return;
 		}
 
+		if (VORTEX_PCI(vp)->current_state < PCI_D3hot)
+			return;
+
 		/* Change the power state to D3; RxEnable doesn't take effect. */
 		pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot);
 	}
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 4a4f6b8..ac422cd 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -561,7 +561,7 @@
 		if (cp_rx_csum_ok(status))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
 
 		skb_put(skb, len);
 
@@ -754,7 +754,7 @@
 	}
 
 #if CP_VLAN_TAG_USED
-	if (cp->vlgrp && vlan_tx_tag_present(skb))
+	if (vlan_tx_tag_present(skb))
 		vlan_tag = TxVlanTag | swab16(vlan_tx_tag_get(skb));
 #endif
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2cc81a5..7ca1fc8 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2,6 +2,9 @@
 # Network device configuration
 #
 
+config HAVE_NET_MACB
+	bool
+
 menuconfig NETDEVICES
 	default y if UML
 	depends on NET
@@ -177,6 +180,13 @@
 
 source "drivers/net/arcnet/Kconfig"
 
+config MII
+	tristate "Generic Media Independent Interface device support"
+	help
+	  Most ethernet controllers have MII transceiver either as an external
+	  or internal device.  It is safe to say Y or M here even if your
+	  ethernet card lacks MII.
+
 source "drivers/net/phy/Kconfig"
 
 #
@@ -212,16 +222,9 @@
 
 if NET_ETHERNET
 
-config MII
-	tristate "Generic Media Independent Interface device support"
-	help
-	  Most ethernet controllers have MII transceiver either as an external
-	  or internal device.  It is safe to say Y or M here even if your
-	  ethernet card lack MII.
-
 config MACB
 	tristate "Atmel MACB support"
-	depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91SAM9G45 || ARCH_AT91CAP9
+	depends on HAVE_NET_MACB
 	select PHYLIB
 	help
 	  The Atmel MACB ethernet interface is found on many AT32 and AT91
@@ -2428,7 +2431,7 @@
 
 config MV643XX_ETH
 	tristate "Marvell Discovery (643XX) and Orion ethernet support"
-	depends on MV64X60 || PPC32 || PLAT_ORION
+	depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
 	select INET_LRO
 	select PHYLIB
 	help
@@ -2515,6 +2518,18 @@
 
 source "drivers/net/stmmac/Kconfig"
 
+config PCH_GBE
+	tristate "PCH Gigabit Ethernet"
+	depends on PCI
+	---help---
+	  This is a gigabit ethernet driver for Topcliff PCH.
+	  Topcliff PCH is the platform controller hub that is used in Intel's
+	  general embedded platform.
+	  Topcliff PCH has Gigabit Ethernet interface.
+	  Using this interface, it is able to access system devices connected
+	  to Gigabit Ethernet.
+	  This driver enables Gigabit Ethernet function.
+
 endif # NETDEV_1000
 
 #
@@ -2803,7 +2818,7 @@
 
 config PASEMI_MAC
 	tristate "PA Semi 1/10Gbit MAC"
-	depends on PPC_PASEMI && PCI
+	depends on PPC_PASEMI && PCI && INET
 	select PHYLIB
 	select INET_LRO
 	help
@@ -2869,6 +2884,20 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called qlge.
 
+config BNA
+        tristate "Brocade 1010/1020 10Gb Ethernet Driver support"
+        depends on PCI
+        ---help---
+          This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet
+          cards.
+          To compile this driver as a module, choose M here: the module
+          will be called bna.
+
+          For general information and support, go to the Brocade support
+          website at:
+
+          <http://support.brocade.com>
+
 source "drivers/net/sfc/Kconfig"
 
 source "drivers/net/benet/Kconfig"
@@ -3202,6 +3231,17 @@
 	  which contains instruction on how to use this driver (under 
 	  the heading "Kernel mode PPPoE").
 
+config PPTP
+	tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX
+	help
+	  Support for PPP over IPv4.(Point-to-Point Tunneling Protocol)
+
+	  This driver requires pppd plugin to work in client mode or
+	  modified pptpd (poptop) to work in server mode.
+	  See http://accel-pptp.sourceforge.net/ for information how to
+	  utilize this module.
+
 config PPPOATM
 	tristate "PPP over ATM"
 	depends on ATM && PPP
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 3e8f150..b8bf93d 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -34,6 +34,7 @@
 obj-$(CONFIG_JME) += jme.o
 obj-$(CONFIG_BE2NET) += benet/
 obj-$(CONFIG_VMXNET3) += vmxnet3/
+obj-$(CONFIG_BNA) += bna/
 
 gianfar_driver-objs := gianfar.o \
 		gianfar_ethtool.o \
@@ -162,6 +163,7 @@
 obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
 obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
 obj-$(CONFIG_PPPOL2TP) += pppox.o
+obj-$(CONFIG_PPTP) += pppox.o pptp.o
 
 obj-$(CONFIG_SLIP) += slip.o
 obj-$(CONFIG_SLHC) += slhc.o
@@ -296,3 +298,4 @@
 obj-$(CONFIG_CAIF) += caif/
 
 obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
+obj-$(CONFIG_PCH_GBE) += pch_gbe/
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index b9a59160..41d9911 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -2033,7 +2033,7 @@
 			skb->csum = htons(csum);
 			skb->ip_summed = CHECKSUM_COMPLETE;
 		} else {
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
 		}
 
 		/* send it up */
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 585c25f..2ca880b 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -396,7 +396,7 @@
 			event_count = coal_conf->rx_event_count;
 			if( timeout > MAX_TIMEOUT ||
 					event_count > MAX_EVENT_COUNT )
-			return -EINVAL;
+				return -EINVAL;
 
 			timeout = timeout * DELAY_TIMER_CONV;
 			writel(VAL0|STINTEN, mmio+INTEN0);
@@ -409,7 +409,7 @@
 			event_count = coal_conf->tx_event_count;
 			if( timeout > MAX_TIMEOUT ||
 					event_count > MAX_EVENT_COUNT )
-			return -EINVAL;
+				return -EINVAL;
 
 
 			timeout = timeout * DELAY_TIMER_CONV;
@@ -903,18 +903,18 @@
 }
 
 /*
-This function reads the mib registers and returns the hardware statistics. It  updates previous internal driver statistics with new values.
-*/
-static struct net_device_stats *amd8111e_get_stats(struct net_device * dev)
+ * This function reads the mib registers and returns the hardware statistics.
+ * It updates previous internal driver statistics with new values.
+ */
+static struct net_device_stats *amd8111e_get_stats(struct net_device *dev)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
 	void __iomem *mmio = lp->mmio;
 	unsigned long flags;
-	/* struct net_device_stats *prev_stats = &lp->prev_stats; */
-	struct net_device_stats* new_stats = &lp->stats;
+	struct net_device_stats *new_stats = &dev->stats;
 
-	if(!lp->opened)
-		return &lp->stats;
+	if (!lp->opened)
+		return new_stats;
 	spin_lock_irqsave (&lp->lock, flags);
 
 	/* stats.rx_packets */
@@ -1315,7 +1315,7 @@
 	lp->tx_ring[tx_index].tx_flags = 0;
 
 #if AMD8111E_VLAN_TAG_USED
-	if((lp->vlgrp != NULL) && vlan_tx_tag_present(skb)){
+	if (vlan_tx_tag_present(skb)) {
 		lp->tx_ring[tx_index].tag_ctrl_cmd |=
 				cpu_to_le16(TCC_VLAN_INSERT);
 		lp->tx_ring[tx_index].tag_ctrl_info =
diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h
index ac36eb6..b5926af 100644
--- a/drivers/net/amd8111e.h
+++ b/drivers/net/amd8111e.h
@@ -787,7 +787,6 @@
 	struct vlan_group		*vlgrp;
 #endif
 	char opened;
-	struct net_device_stats stats;
 	unsigned int drv_rx_errors;
 	struct amd8111e_coalesce_conf coal_conf;
 
diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig
index 0a0e0cd..20f97e7 100644
--- a/drivers/net/appletalk/Kconfig
+++ b/drivers/net/appletalk/Kconfig
@@ -3,6 +3,7 @@
 #
 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/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index 0362c8d..10d0dba 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -244,7 +244,7 @@
         }
 
 	spin_unlock_bh(&ipddp_route_lock);
-        return (-ENOENT);
+        return -ENOENT;
 }
 
 /*
@@ -259,10 +259,10 @@
                 if(f->ip == rt->ip &&
 		   f->at.s_net == rt->at.s_net &&
 		   f->at.s_node == rt->at.s_node)
-                        return (f);
+                        return f;
         }
 
-        return (NULL);
+        return NULL;
 }
 
 static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -279,7 +279,7 @@
         switch(cmd)
         {
 		case SIOCADDIPDDPRT:
-                        return (ipddp_create(&rcp));
+                        return ipddp_create(&rcp);
 
                 case SIOCFINDIPDDPRT:
 			spin_lock_bh(&ipddp_route_lock);
@@ -297,7 +297,7 @@
 				return -ENOENT;
 
                 case SIOCDELIPDDPRT:
-                        return (ipddp_delete(&rcp));
+                        return ipddp_delete(&rcp);
 
                 default:
                         return -EINVAL;
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index adc0755..e69eead 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -727,7 +727,7 @@
 
 	if (ltc->command != LT_RCVLAP) {
 		printk("unknown command 0x%02x from ltpc card\n",ltc->command);
-		return(-1);
+		return -1;
 	}
 	dnode = ltc->dnode;
 	snode = ltc->snode;
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 8c496fb..62f2110 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -300,8 +300,6 @@
 	struct dev_priv *priv = netdev_priv(dev);
 	int ret;
 
-	memset (&priv->stats, 0, sizeof (priv->stats));
-
 	ret = request_irq(dev->irq, am79c961_interrupt, 0, dev->name, dev);
 	if (ret)
 		return ret;
@@ -347,8 +345,7 @@
  */
 static struct net_device_stats *am79c961_getstats (struct net_device *dev)
 {
-	struct dev_priv *priv = netdev_priv(dev);
-	return &priv->stats;
+	return &dev->stats;
 }
 
 static void am79c961_mc_hash(char *addr, unsigned short *hash)
@@ -510,14 +507,14 @@
 
 		if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) {
 			am_writeword (dev, hdraddr + 2, RMD_OWN);
-			priv->stats.rx_errors ++;
+			dev->stats.rx_errors++;
 			if (status & RMD_ERR) {
 				if (status & RMD_FRAM)
-					priv->stats.rx_frame_errors ++;
+					dev->stats.rx_frame_errors++;
 				if (status & RMD_CRC)
-					priv->stats.rx_crc_errors ++;
+					dev->stats.rx_crc_errors++;
 			} else if (status & RMD_STP)
-				priv->stats.rx_length_errors ++;
+				dev->stats.rx_length_errors++;
 			continue;
 		}
 
@@ -531,12 +528,12 @@
 			am_writeword(dev, hdraddr + 2, RMD_OWN);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			priv->stats.rx_bytes += len;
-			priv->stats.rx_packets ++;
+			dev->stats.rx_bytes += len;
+			dev->stats.rx_packets++;
 		} else {
 			am_writeword (dev, hdraddr + 2, RMD_OWN);
 			printk (KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name);
-			priv->stats.rx_dropped ++;
+			dev->stats.rx_dropped++;
 			break;
 		}
 	} while (1);
@@ -565,7 +562,7 @@
 		if (status & TMD_ERR) {
 			u_int status2;
 
-			priv->stats.tx_errors ++;
+			dev->stats.tx_errors++;
 
 			status2 = am_readword (dev, hdraddr + 6);
 
@@ -575,18 +572,18 @@
 			am_writeword (dev, hdraddr + 6, 0);
 
 			if (status2 & TST_RTRY)
-				priv->stats.collisions += 16;
+				dev->stats.collisions += 16;
 			if (status2 & TST_LCOL)
-				priv->stats.tx_window_errors ++;
+				dev->stats.tx_window_errors++;
 			if (status2 & TST_LCAR)
-				priv->stats.tx_carrier_errors ++;
+				dev->stats.tx_carrier_errors++;
 			if (status2 & TST_UFLO)
-				priv->stats.tx_fifo_errors ++;
+				dev->stats.tx_fifo_errors++;
 			continue;
 		}
-		priv->stats.tx_packets ++;
+		dev->stats.tx_packets++;
 		len = am_readword (dev, hdraddr + 4);
-		priv->stats.tx_bytes += -len;
+		dev->stats.tx_bytes += -len;
 	} while (priv->txtail != priv->txhead);
 
 	netif_wake_queue(dev);
@@ -616,7 +613,7 @@
 		}
 		if (status & CSR0_MISS) {
 			handled = 1;
-			priv->stats.rx_dropped ++;
+			dev->stats.rx_dropped++;
 		}
 		if (status & CSR0_CERR) {
 			handled = 1;
diff --git a/drivers/net/arm/am79c961a.h b/drivers/net/arm/am79c961a.h
index 483009f..fd634d3 100644
--- a/drivers/net/arm/am79c961a.h
+++ b/drivers/net/arm/am79c961a.h
@@ -130,7 +130,6 @@
 #define ISALED0_LNKST	0x8000
 
 struct dev_priv {
-    struct net_device_stats stats;
     unsigned long	rxbuffer[RX_BUFFERS];
     unsigned long	txbuffer[TX_BUFFERS];
     unsigned char	txhead;
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 4a5ec94..5a77001 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -175,8 +175,6 @@
 	struct net_device	*dev;
 	struct napi_struct	napi;
 
-	struct net_device_stats	stats;
-
 	struct mii_if_info	mii;
 	u8			mdc_divisor;
 };
@@ -230,12 +228,6 @@
 		pr_info("mdio write timed out\n");
 }
 
-static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
-{
-	struct ep93xx_priv *ep = netdev_priv(dev);
-	return &(ep->stats);
-}
-
 static int ep93xx_rx(struct net_device *dev, int processed, int budget)
 {
 	struct ep93xx_priv *ep = netdev_priv(dev);
@@ -267,15 +259,15 @@
 			pr_crit("entry mismatch %.8x %.8x\n", rstat0, rstat1);
 
 		if (!(rstat0 & RSTAT0_RWE)) {
-			ep->stats.rx_errors++;
+			dev->stats.rx_errors++;
 			if (rstat0 & RSTAT0_OE)
-				ep->stats.rx_fifo_errors++;
+				dev->stats.rx_fifo_errors++;
 			if (rstat0 & RSTAT0_FE)
-				ep->stats.rx_frame_errors++;
+				dev->stats.rx_frame_errors++;
 			if (rstat0 & (RSTAT0_RUNT | RSTAT0_EDATA))
-				ep->stats.rx_length_errors++;
+				dev->stats.rx_length_errors++;
 			if (rstat0 & RSTAT0_CRCE)
-				ep->stats.rx_crc_errors++;
+				dev->stats.rx_crc_errors++;
 			goto err;
 		}
 
@@ -300,10 +292,10 @@
 
 			netif_receive_skb(skb);
 
-			ep->stats.rx_packets++;
-			ep->stats.rx_bytes += length;
+			dev->stats.rx_packets++;
+			dev->stats.rx_bytes += length;
 		} else {
-			ep->stats.rx_dropped++;
+			dev->stats.rx_dropped++;
 		}
 
 err:
@@ -359,7 +351,7 @@
 	int entry;
 
 	if (unlikely(skb->len > MAX_PKT_SIZE)) {
-		ep->stats.tx_dropped++;
+		dev->stats.tx_dropped++;
 		dev_kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
@@ -415,17 +407,17 @@
 		if (tstat0 & TSTAT0_TXWE) {
 			int length = ep->descs->tdesc[entry].tdesc1 & 0xfff;
 
-			ep->stats.tx_packets++;
-			ep->stats.tx_bytes += length;
+			dev->stats.tx_packets++;
+			dev->stats.tx_bytes += length;
 		} else {
-			ep->stats.tx_errors++;
+			dev->stats.tx_errors++;
 		}
 
 		if (tstat0 & TSTAT0_OW)
-			ep->stats.tx_window_errors++;
+			dev->stats.tx_window_errors++;
 		if (tstat0 & TSTAT0_TXU)
-			ep->stats.tx_fifo_errors++;
-		ep->stats.collisions += (tstat0 >> 16) & 0x1f;
+			dev->stats.tx_fifo_errors++;
+		dev->stats.collisions += (tstat0 >> 16) & 0x1f;
 
 		ep->tx_clean_pointer = (entry + 1) & (TX_QUEUE_ENTRIES - 1);
 		if (ep->tx_pending == TX_QUEUE_ENTRIES)
@@ -758,7 +750,6 @@
 	.ndo_open		= ep93xx_open,
 	.ndo_stop		= ep93xx_close,
 	.ndo_start_xmit		= ep93xx_xmit,
-	.ndo_get_stats		= ep93xx_get_stats,
 	.ndo_do_ioctl		= ep93xx_ioctl,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= eth_change_mtu,
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index b17ab51..b00781c 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -68,7 +68,6 @@
 static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t ether1_interrupt(int irq, void *dev_id);
 static int ether1_close(struct net_device *dev);
-static struct net_device_stats *ether1_getstats(struct net_device *dev);
 static void ether1_setmulticastlist(struct net_device *dev);
 static void ether1_timeout(struct net_device *dev);
 
@@ -649,8 +648,6 @@
 	if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
 		return -EAGAIN;
 
-	memset (&priv(dev)->stats, 0, sizeof (struct net_device_stats));
-
 	if (ether1_init_for_open (dev)) {
 		free_irq (dev->irq, dev);
 		return -EAGAIN;
@@ -673,7 +670,7 @@
 	if (ether1_init_for_open (dev))
 		printk (KERN_ERR "%s: unable to restart interface\n", dev->name);
 
-	priv(dev)->stats.tx_errors++;
+	dev->stats.tx_errors++;
 	netif_wake_queue(dev);
 }
 
@@ -802,21 +799,21 @@
 
 	while (nop.nop_status & STAT_COMPLETE) {
 		if (nop.nop_status & STAT_OK) {
-			priv(dev)->stats.tx_packets ++;
-			priv(dev)->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
+			dev->stats.tx_packets++;
+			dev->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
 		} else {
-			priv(dev)->stats.tx_errors ++;
+			dev->stats.tx_errors++;
 
 			if (nop.nop_status & STAT_COLLAFTERTX)
-				priv(dev)->stats.collisions ++;
+				dev->stats.collisions++;
 			if (nop.nop_status & STAT_NOCARRIER)
-				priv(dev)->stats.tx_carrier_errors ++;
+				dev->stats.tx_carrier_errors++;
 			if (nop.nop_status & STAT_TXLOSTCTS)
 				printk (KERN_WARNING "%s: cts lost\n", dev->name);
 			if (nop.nop_status & STAT_TXSLOWDMA)
-				priv(dev)->stats.tx_fifo_errors ++;
+				dev->stats.tx_fifo_errors++;
 			if (nop.nop_status & STAT_COLLEXCESSIVE)
-				priv(dev)->stats.collisions += 16;
+				dev->stats.collisions += 16;
 		}
 
 		if (nop.nop_link == caddr) {
@@ -879,13 +876,13 @@
 
 				skb->protocol = eth_type_trans (skb, dev);
 				netif_rx (skb);
-				priv(dev)->stats.rx_packets ++;
+				dev->stats.rx_packets++;
 			} else
-				priv(dev)->stats.rx_dropped ++;
+				dev->stats.rx_dropped++;
 		} else {
 			printk(KERN_WARNING "%s: %s\n", dev->name,
 				(rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid");
-			priv(dev)->stats.rx_dropped ++;
+			dev->stats.rx_dropped++;
 		}
 
 		nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS);
@@ -939,7 +936,7 @@
 				printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name);
 				ether1_writew(dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
 				writeb(CTRL_CA, REG_CONTROL);
-				priv(dev)->stats.rx_dropped ++;	/* we suspended due to lack of buffer space */
+				dev->stats.rx_dropped++;	/* we suspended due to lack of buffer space */
 			} else
 				printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name,
 					ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
@@ -962,12 +959,6 @@
 	return 0;
 }
 
-static struct net_device_stats *
-ether1_getstats (struct net_device *dev)
-{
-	return &priv(dev)->stats;
-}
-
 /*
  * Set or clear the multicast filter for this adaptor.
  * num_addrs == -1	Promiscuous mode, receive all packets.
@@ -994,7 +985,6 @@
 	.ndo_open		= ether1_open,
 	.ndo_stop		= ether1_close,
 	.ndo_start_xmit		= ether1_sendpacket,
-	.ndo_get_stats		= ether1_getstats,
 	.ndo_set_multicast_list	= ether1_setmulticastlist,
 	.ndo_tx_timeout		= ether1_timeout,
 	.ndo_validate_addr	= eth_validate_addr,
diff --git a/drivers/net/arm/ether1.h b/drivers/net/arm/ether1.h
index c8a4b23..3a5830a 100644
--- a/drivers/net/arm/ether1.h
+++ b/drivers/net/arm/ether1.h
@@ -38,7 +38,6 @@
 
 struct ether1_priv {
 	void __iomem *base;
-	struct net_device_stats stats;
 	unsigned int tx_link;
 	unsigned int tx_head;
 	volatile unsigned int tx_tail;
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 1361b73..44a8746 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -81,7 +81,6 @@
 static int	ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t ether3_interrupt (int irq, void *dev_id);
 static int	ether3_close (struct net_device *dev);
-static struct net_device_stats *ether3_getstats (struct net_device *dev);
 static void	ether3_setmulticastlist (struct net_device *dev);
 static void	ether3_timeout(struct net_device *dev);
 
@@ -323,8 +322,6 @@
 {
 	int i;
 
-	memset(&priv(dev)->stats, 0, sizeof(struct net_device_stats));
-
 	/* Reset the chip */
 	ether3_outw(CFG2_RESET, REG_CONFIG2);
 	udelay(4);
@@ -442,15 +439,6 @@
 }
 
 /*
- * Get the current statistics.	This may be called with the card open or
- * closed.
- */
-static struct net_device_stats *ether3_getstats(struct net_device *dev)
-{
-	return &priv(dev)->stats;
-}
-
-/*
  * Set or clear promiscuous/multicast mode filter for this adaptor.
  *
  * We don't attempt any packet filtering.  The card may have a SEEQ 8004
@@ -490,7 +478,7 @@
 	local_irq_restore(flags);
 
 	priv(dev)->regs.config2 |= CFG2_CTRLO;
-	priv(dev)->stats.tx_errors += 1;
+	dev->stats.tx_errors += 1;
 	ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
 	priv(dev)->tx_head = priv(dev)->tx_tail = 0;
 
@@ -509,7 +497,7 @@
 
 	if (priv(dev)->broken) {
 		dev_kfree_skb(skb);
-		priv(dev)->stats.tx_dropped ++;
+		dev->stats.tx_dropped++;
 		netif_start_queue(dev);
 		return NETDEV_TX_OK;
 	}
@@ -673,7 +661,7 @@
 			} else
 				goto dropping;
 		} else {
-			struct net_device_stats *stats = &priv(dev)->stats;
+			struct net_device_stats *stats = &dev->stats;
 			ether3_outw(next_ptr >> 8, REG_RECVEND);
 			if (status & RXSTAT_OVERSIZE)	  stats->rx_over_errors ++;
 			if (status & RXSTAT_CRCERROR)	  stats->rx_crc_errors ++;
@@ -685,14 +673,14 @@
 	while (-- maxcnt);
 
 done:
-	priv(dev)->stats.rx_packets += received;
+	dev->stats.rx_packets += received;
 	priv(dev)->rx_head = next_ptr;
 	/*
 	 * If rx went off line, then that means that the buffer may be full.  We
 	 * have dropped at least one packet.
 	 */
 	if (!(ether3_inw(REG_STATUS) & STAT_RXON)) {
-		priv(dev)->stats.rx_dropped ++;
+		dev->stats.rx_dropped++;
     		ether3_outw(next_ptr, REG_RECVPTR);
 		ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
 	}
@@ -710,7 +698,7 @@
 		last_warned = jiffies;
 		printk("%s: memory squeeze, dropping packet.\n", dev->name);
 	}
-	priv(dev)->stats.rx_dropped ++;
+	dev->stats.rx_dropped++;
 	goto done;
 	}
 }
@@ -743,13 +731,13 @@
 		 * Update errors
 		 */
 		if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS)))
-			priv(dev)->stats.tx_packets++;
+			dev->stats.tx_packets++;
 		else {
-			priv(dev)->stats.tx_errors ++;
+			dev->stats.tx_errors++;
 			if (status & TXSTAT_16COLLISIONS)
-				priv(dev)->stats.collisions += 16;
+				dev->stats.collisions += 16;
 			if (status & TXSTAT_BABBLED)
-				priv(dev)->stats.tx_fifo_errors ++;
+				dev->stats.tx_fifo_errors++;
 		}
 
 		tx_tail = (tx_tail + 1) & 15;
@@ -773,7 +761,6 @@
 	.ndo_open		= ether3_open,
 	.ndo_stop		= ether3_close,
 	.ndo_start_xmit		= ether3_sendpacket,
-	.ndo_get_stats		= ether3_getstats,
 	.ndo_set_multicast_list	= ether3_setmulticastlist,
 	.ndo_tx_timeout		= ether3_timeout,
 	.ndo_validate_addr	= eth_validate_addr,
diff --git a/drivers/net/arm/ether3.h b/drivers/net/arm/ether3.h
index 1921a3a..2db63b0 100644
--- a/drivers/net/arm/ether3.h
+++ b/drivers/net/arm/ether3.h
@@ -164,7 +164,6 @@
     unsigned char tx_head;		/* buffer nr to insert next packet	 */
     unsigned char tx_tail;		/* buffer nr of transmitting packet	 */
     unsigned int rx_head;		/* address to fetch next packet from	 */
-    struct net_device_stats stats;
     struct timer_list timer;
     int broken;				/* 0 = ok, 1 = something went wrong	 */
 };
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index b57d7de..3134e53 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -362,7 +362,7 @@
 		*cto++ = *cfrom++;
 		MFPDELAY();
 	}
-	return( dst );
+	return dst;
 }
 
 
@@ -449,7 +449,7 @@
 	vbr[2] = save_berr;
 	local_irq_restore(flags);
 
-	return( ret );
+	return ret;
 }
 
 static const struct net_device_ops lance_netdev_ops = {
@@ -526,7 +526,7 @@
 	goto probe_ok;
 
   probe_fail:
-	return( 0 );
+	return 0;
 
   probe_ok:
 	lp = netdev_priv(dev);
@@ -556,7 +556,7 @@
 		if (request_irq(IRQ_AUTO_5, lance_interrupt, IRQ_TYPE_PRIO,
 		            "PAM/Riebl-ST Ethernet", dev)) {
 			printk( "Lance: request for irq %d failed\n", IRQ_AUTO_5 );
-			return( 0 );
+			return 0;
 		}
 		dev->irq = (unsigned short)IRQ_AUTO_5;
 	}
@@ -568,12 +568,12 @@
 		unsigned long irq = atari_register_vme_int();
 		if (!irq) {
 			printk( "Lance: request for VME interrupt failed\n" );
-			return( 0 );
+			return 0;
 		}
 		if (request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO,
 		            "Riebl-VME Ethernet", dev)) {
 			printk( "Lance: request for irq %ld failed\n", irq );
-			return( 0 );
+			return 0;
 		}
 		dev->irq = irq;
 	}
@@ -637,7 +637,7 @@
 	/* XXX MSch */
 	dev->watchdog_timeo = TX_TIMEOUT;
 
-	return( 1 );
+	return 1;
 }
 
 
@@ -666,7 +666,7 @@
 		DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",
 					  dev->name, i, DREG ));
 		DREG = CSR0_STOP;
-		return( -EIO );
+		return -EIO;
 	}
 	DREG = CSR0_IDON;
 	DREG = CSR0_STRT;
@@ -676,7 +676,7 @@
 
 	DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
 
-	return( 0 );
+	return 0;
 }
 
 
@@ -1126,13 +1126,13 @@
 	int i;
 
 	if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL)
-		return( -EOPNOTSUPP );
+		return -EOPNOTSUPP;
 
 	if (netif_running(dev)) {
 		/* Only possible while card isn't started */
 		DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n",
 					  dev->name ));
-		return( -EIO );
+		return -EIO;
 	}
 
 	memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len );
@@ -1142,7 +1142,7 @@
 	/* set also the magic for future sessions */
 	*RIEBL_MAGIC_ADDR = RIEBL_MAGIC;
 
-	return( 0 );
+	return 0;
 }
 
 
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h
index 52abbbd..ef4115b 100644
--- a/drivers/net/atl1c/atl1c.h
+++ b/drivers/net/atl1c/atl1c.h
@@ -559,7 +559,6 @@
 	struct napi_struct  napi;
 	struct atl1c_hw        hw;
 	struct atl1c_hw_stats  hw_stats;
-	struct net_device_stats net_stats;
 	struct mii_if_info  mii;    /* MII interface info */
 	u16 rx_buffer_len;
 
diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/atl1c/atl1c_hw.c
index d8501f0..919080b 100644
--- a/drivers/net/atl1c/atl1c_hw.c
+++ b/drivers/net/atl1c/atl1c_hw.c
@@ -480,7 +480,7 @@
 		atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D);
 	}
 	if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2
-		|| hw->nic_type == athr_l2c || hw->nic_type == athr_l2c) {
+		|| hw->nic_type == athr_l2c) {
 		atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
 		atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD);
 	}
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
index c7b8ef5..99ffcf6 100644
--- a/drivers/net/atl1c/atl1c_main.c
+++ b/drivers/net/atl1c/atl1c_main.c
@@ -1562,7 +1562,7 @@
 {
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 	struct atl1c_hw_stats  *hw_stats = &adapter->hw_stats;
-	struct net_device_stats *net_stats = &adapter->net_stats;
+	struct net_device_stats *net_stats = &netdev->stats;
 
 	atl1c_update_hw_stats(adapter);
 	net_stats->rx_packets = hw_stats->rx_ok;
@@ -1590,7 +1590,7 @@
 	net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
 	net_stats->tx_window_errors  = hw_stats->tx_late_col;
 
-	return &adapter->net_stats;
+	return net_stats;
 }
 
 static inline void atl1c_clear_phy_int(struct atl1c_adapter *adapter)
@@ -1700,7 +1700,7 @@
 
 		/* link event */
 		if (status & (ISR_GPHY | ISR_MANUAL)) {
-			adapter->net_stats.tx_carrier_errors++;
+			netdev->stats.tx_carrier_errors++;
 			atl1c_link_chg_event(adapter);
 			break;
 		}
@@ -1719,7 +1719,7 @@
 	 * cannot figure out if the packet is fragmented or not,
 	 * so we tell the KERNEL CHECKSUM_NONE
 	 */
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 }
 
 static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid)
@@ -2243,7 +2243,7 @@
 		return NETDEV_TX_OK;
 	}
 
-	if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+	if (unlikely(vlan_tx_tag_present(skb))) {
 		u16 vlan = vlan_tx_tag_get(skb);
 		__le16 tag;
 
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 1acea57..ef6349bf 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -1331,7 +1331,7 @@
 	u16 pkt_flags;
 	u16 err_flags;
 
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 	pkt_flags = prrs->pkt_flag;
 	err_flags = prrs->err_flag;
 	if (((pkt_flags & RRS_IS_IPV4) || (pkt_flags & RRS_IS_IPV6)) &&
@@ -1814,7 +1814,7 @@
 
 	tpd = atl1e_get_tpd(adapter);
 
-	if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+	if (unlikely(vlan_tx_tag_present(skb))) {
 		u16 vlan_tag = vlan_tx_tag_get(skb);
 		u16 atl1e_vlan_tag;
 
@@ -2316,7 +2316,7 @@
 	netif_napi_add(netdev, &adapter->napi, atl1e_clean, 64);
 
 	init_timer(&adapter->phy_config_timer);
-	adapter->phy_config_timer.function = &atl1e_phy_config;
+	adapter->phy_config_timer.function = atl1e_phy_config;
 	adapter->phy_config_timer.data = (unsigned long) adapter;
 
 	/* get user settings */
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index 63b9ba0..dbd27b8 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -1251,6 +1251,12 @@
 
 	rrd_ring->desc = NULL;
 	rrd_ring->dma = 0;
+
+	adapter->cmb.dma = 0;
+	adapter->cmb.cmb = NULL;
+
+	adapter->smb.dma = 0;
+	adapter->smb.smb = NULL;
 }
 
 static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
@@ -1805,7 +1811,7 @@
 	 * the higher layers and let it be sorted out there.
 	 */
 
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 
 	if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
 		if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
@@ -2094,9 +2100,9 @@
 {
 	u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
 	u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
-	return ((next_to_clean > next_to_use) ?
+	return (next_to_clean > next_to_use) ?
 		next_to_clean - next_to_use - 1 :
-		tpd_ring->count + next_to_clean - next_to_use - 1);
+		tpd_ring->count + next_to_clean - next_to_use - 1;
 }
 
 static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
@@ -2402,7 +2408,7 @@
 		(u16) atomic_read(&tpd_ring->next_to_use));
 	memset(ptpd, 0, sizeof(struct tx_packet_desc));
 
-	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		vlan_tag = vlan_tx_tag_get(skb);
 		vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
 			((vlan_tag >> 9) & 0x8);
@@ -2847,10 +2853,11 @@
 	pci_enable_wake(pdev, PCI_D3cold, 0);
 
 	atl1_reset_hw(&adapter->hw);
-	adapter->cmb.cmb->int_stats = 0;
 
-	if (netif_running(netdev))
+	if (netif_running(netdev)) {
+		adapter->cmb.cmb->int_stats = 0;
 		atl1_up(adapter);
+	}
 	netif_device_attach(netdev);
 
 	return 0;
@@ -3036,7 +3043,7 @@
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
 
-	setup_timer(&adapter->phy_config_timer, &atl1_phy_config,
+	setup_timer(&adapter->phy_config_timer, atl1_phy_config,
 		    (unsigned long)adapter);
 	adapter->phy_timer_pending = false;
 
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
index 8da8738..35b14be 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/atlx/atl2.c
@@ -51,10 +51,10 @@
 
 #define ATL2_DRV_VERSION "2.2.3"
 
-static char atl2_driver_name[] = "atl2";
+static const char atl2_driver_name[] = "atl2";
 static const char atl2_driver_string[] = "Atheros(R) L2 Ethernet Driver";
-static char atl2_copyright[] = "Copyright (c) 2007 Atheros Corporation.";
-static char atl2_driver_version[] = ATL2_DRV_VERSION;
+static const char atl2_copyright[] = "Copyright (c) 2007 Atheros Corporation.";
+static const char atl2_driver_version[] = ATL2_DRV_VERSION;
 
 MODULE_AUTHOR("Atheros Corporation <xiong.huang@atheros.com>, Chris Snook <csnook@redhat.com>");
 MODULE_DESCRIPTION("Atheros Fast Ethernet Network Driver");
@@ -870,7 +870,7 @@
 		offset = ((u32)(skb->len-copy_len + 3) & ~3);
 	}
 #ifdef NETIF_F_HW_VLAN_TX
-	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		u16 vlan_tag = vlan_tx_tag_get(skb);
 		vlan_tag = (vlan_tag << 4) |
 			(vlan_tag >> 13) |
@@ -1444,11 +1444,11 @@
 	atl2_check_options(adapter);
 
 	init_timer(&adapter->watchdog_timer);
-	adapter->watchdog_timer.function = &atl2_watchdog;
+	adapter->watchdog_timer.function = atl2_watchdog;
 	adapter->watchdog_timer.data = (unsigned long) adapter;
 
 	init_timer(&adapter->phy_config_timer);
-	adapter->phy_config_timer.function = &atl2_phy_config;
+	adapter->phy_config_timer.function = atl2_phy_config;
 	adapter->phy_config_timer.data = (unsigned long) adapter;
 
 	INIT_WORK(&adapter->reset_task, atl2_reset_task);
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index bd2f9d3..dfd96b2 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -445,7 +445,7 @@
 	init_timer(&lp->timer);
 	lp->timer.expires = jiffies + TIMED_CHECKER;
 	lp->timer.data = (unsigned long)dev;
-	lp->timer.function = &atp_timed_checker;    /* timer handler */
+	lp->timer.function = atp_timed_checker;    /* timer handler */
 	add_timer(&lp->timer);
 
 	netif_start_queue(dev);
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 15ae6df..43489f8 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -13,7 +13,7 @@
  *  converted to use linux-2.6.x's PHY framework
  *
  * Author: MontaVista Software, Inc.
- *         	ppopov@mvista.com or source@mvista.com
+ *		ppopov@mvista.com or source@mvista.com
  *
  * ########################################################################
  *
@@ -34,6 +34,8 @@
  *
  *
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/capability.h>
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
@@ -56,11 +58,11 @@
 #include <linux/crc32.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
+#include <linux/cpu.h>
+#include <linux/io.h>
 
-#include <asm/cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/irq.h>
-#include <asm/io.h>
 #include <asm/processor.h>
 
 #include <au1000.h>
@@ -152,11 +154,11 @@
 
 	spin_lock_irqsave(&aup->lock, flags);
 
-	if(force_reset || (!aup->mac_enabled)) {
-		*aup->enable = MAC_EN_CLOCK_ENABLE;
+	if (force_reset || (!aup->mac_enabled)) {
+		writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
 		au_sync_delay(2);
-		*aup->enable = (MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
-				| MAC_EN_CLOCK_ENABLE);
+		writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
+				| MAC_EN_CLOCK_ENABLE), &aup->enable);
 		au_sync_delay(2);
 
 		aup->mac_enabled = 1;
@@ -171,12 +173,12 @@
 static int au1000_mdio_read(struct net_device *dev, int phy_addr, int reg)
 {
 	struct au1000_private *aup = netdev_priv(dev);
-	volatile u32 *const mii_control_reg = &aup->mac->mii_control;
-	volatile u32 *const mii_data_reg = &aup->mac->mii_data;
+	u32 *const mii_control_reg = &aup->mac->mii_control;
+	u32 *const mii_data_reg = &aup->mac->mii_data;
 	u32 timedout = 20;
 	u32 mii_control;
 
-	while (*mii_control_reg & MAC_MII_BUSY) {
+	while (readl(mii_control_reg) & MAC_MII_BUSY) {
 		mdelay(1);
 		if (--timedout == 0) {
 			netdev_err(dev, "read_MII busy timeout!!\n");
@@ -187,29 +189,29 @@
 	mii_control = MAC_SET_MII_SELECT_REG(reg) |
 		MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_READ;
 
-	*mii_control_reg = mii_control;
+	writel(mii_control, mii_control_reg);
 
 	timedout = 20;
-	while (*mii_control_reg & MAC_MII_BUSY) {
+	while (readl(mii_control_reg) & MAC_MII_BUSY) {
 		mdelay(1);
 		if (--timedout == 0) {
 			netdev_err(dev, "mdio_read busy timeout!!\n");
 			return -1;
 		}
 	}
-	return (int)*mii_data_reg;
+	return readl(mii_data_reg);
 }
 
 static void au1000_mdio_write(struct net_device *dev, int phy_addr,
 			      int reg, u16 value)
 {
 	struct au1000_private *aup = netdev_priv(dev);
-	volatile u32 *const mii_control_reg = &aup->mac->mii_control;
-	volatile u32 *const mii_data_reg = &aup->mac->mii_data;
+	u32 *const mii_control_reg = &aup->mac->mii_control;
+	u32 *const mii_data_reg = &aup->mac->mii_data;
 	u32 timedout = 20;
 	u32 mii_control;
 
-	while (*mii_control_reg & MAC_MII_BUSY) {
+	while (readl(mii_control_reg) & MAC_MII_BUSY) {
 		mdelay(1);
 		if (--timedout == 0) {
 			netdev_err(dev, "mdio_write busy timeout!!\n");
@@ -220,18 +222,22 @@
 	mii_control = MAC_SET_MII_SELECT_REG(reg) |
 		MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_WRITE;
 
-	*mii_data_reg = value;
-	*mii_control_reg = mii_control;
+	writel(value, mii_data_reg);
+	writel(mii_control, mii_control_reg);
 }
 
 static int au1000_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
 {
 	/* WARNING: bus->phy_map[phy_addr].attached_dev == dev does
-	 * _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus) */
+	 * _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus)
+	 */
 	struct net_device *const dev = bus->priv;
 
-	au1000_enable_mac(dev, 0); /* make sure the MAC associated with this
-			     * mii_bus is enabled */
+	/* make sure the MAC associated with this
+	 * mii_bus is enabled
+	 */
+	au1000_enable_mac(dev, 0);
+
 	return au1000_mdio_read(dev, phy_addr, regnum);
 }
 
@@ -240,8 +246,11 @@
 {
 	struct net_device *const dev = bus->priv;
 
-	au1000_enable_mac(dev, 0); /* make sure the MAC associated with this
-			     * mii_bus is enabled */
+	/* make sure the MAC associated with this
+	 * mii_bus is enabled
+	 */
+	au1000_enable_mac(dev, 0);
+
 	au1000_mdio_write(dev, phy_addr, regnum, value);
 	return 0;
 }
@@ -250,28 +259,37 @@
 {
 	struct net_device *const dev = bus->priv;
 
-	au1000_enable_mac(dev, 0); /* make sure the MAC associated with this
-			     * mii_bus is enabled */
+	/* make sure the MAC associated with this
+	 * mii_bus is enabled
+	 */
+	au1000_enable_mac(dev, 0);
+
 	return 0;
 }
 
 static void au1000_hard_stop(struct net_device *dev)
 {
 	struct au1000_private *aup = netdev_priv(dev);
+	u32 reg;
 
 	netif_dbg(aup, drv, dev, "hard stop\n");
 
-	aup->mac->control &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
+	reg = readl(&aup->mac->control);
+	reg &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
+	writel(reg, &aup->mac->control);
 	au_sync_delay(10);
 }
 
 static void au1000_enable_rx_tx(struct net_device *dev)
 {
 	struct au1000_private *aup = netdev_priv(dev);
+	u32 reg;
 
 	netif_dbg(aup, hw, dev, "enable_rx_tx\n");
 
-	aup->mac->control |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
+	reg = readl(&aup->mac->control);
+	reg |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
+	writel(reg, &aup->mac->control);
 	au_sync_delay(10);
 }
 
@@ -281,6 +299,7 @@
 	struct au1000_private *aup = netdev_priv(dev);
 	struct phy_device *phydev = aup->phy_dev;
 	unsigned long flags;
+	u32 reg;
 
 	int status_change = 0;
 
@@ -312,14 +331,15 @@
 		/* switching duplex mode requires to disable rx and tx! */
 		au1000_hard_stop(dev);
 
-		if (DUPLEX_FULL == phydev->duplex)
-			aup->mac->control = ((aup->mac->control
-					     | MAC_FULL_DUPLEX)
-					     & ~MAC_DISABLE_RX_OWN);
-		else
-			aup->mac->control = ((aup->mac->control
-					      & ~MAC_FULL_DUPLEX)
-					     | MAC_DISABLE_RX_OWN);
+		reg = readl(&aup->mac->control);
+		if (DUPLEX_FULL == phydev->duplex) {
+			reg |= MAC_FULL_DUPLEX;
+			reg &= ~MAC_DISABLE_RX_OWN;
+		} else {
+			reg &= ~MAC_FULL_DUPLEX;
+			reg |= MAC_DISABLE_RX_OWN;
+		}
+		writel(reg, &aup->mac->control);
 		au_sync_delay(1);
 
 		au1000_enable_rx_tx(dev);
@@ -353,10 +373,11 @@
 	}
 }
 
-static int au1000_mii_probe (struct net_device *dev)
+static int au1000_mii_probe(struct net_device *dev)
 {
 	struct au1000_private *const aup = netdev_priv(dev);
 	struct phy_device *phydev = NULL;
+	int phy_addr;
 
 	if (aup->phy_static_config) {
 		BUG_ON(aup->mac_id < 0 || aup->mac_id > 1);
@@ -366,42 +387,46 @@
 		else
 			netdev_info(dev, "using PHY-less setup\n");
 		return 0;
-	} else {
-		int phy_addr;
+	}
 
-		/* find the first (lowest address) PHY on the current MAC's MII bus */
-		for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
-			if (aup->mii_bus->phy_map[phy_addr]) {
-				phydev = aup->mii_bus->phy_map[phy_addr];
-				if (!aup->phy_search_highest_addr)
-					break; /* break out with first one found */
-			}
+	/* find the first (lowest address) PHY
+	 * on the current MAC's MII bus
+	 */
+	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
+		if (aup->mii_bus->phy_map[phy_addr]) {
+			phydev = aup->mii_bus->phy_map[phy_addr];
+			if (!aup->phy_search_highest_addr)
+				/* break out with first one found */
+				break;
+		}
 
-		if (aup->phy1_search_mac0) {
-			/* try harder to find a PHY */
-			if (!phydev && (aup->mac_id == 1)) {
-				/* no PHY found, maybe we have a dual PHY? */
-				dev_info(&dev->dev, ": no PHY found on MAC1, "
-					"let's see if it's attached to MAC0...\n");
+	if (aup->phy1_search_mac0) {
+		/* try harder to find a PHY */
+		if (!phydev && (aup->mac_id == 1)) {
+			/* no PHY found, maybe we have a dual PHY? */
+			dev_info(&dev->dev, ": no PHY found on MAC1, "
+				"let's see if it's attached to MAC0...\n");
 
-				/* find the first (lowest address) non-attached PHY on
-				 * the MAC0 MII bus */
-				for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
-					struct phy_device *const tmp_phydev =
-							aup->mii_bus->phy_map[phy_addr];
+			/* find the first (lowest address) non-attached
+			 * PHY on the MAC0 MII bus
+			 */
+			for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+				struct phy_device *const tmp_phydev =
+					aup->mii_bus->phy_map[phy_addr];
 
-					if (aup->mac_id == 1)
-						break;
+				if (aup->mac_id == 1)
+					break;
 
-					if (!tmp_phydev)
-						continue; /* no PHY here... */
+				/* no PHY here... */
+				if (!tmp_phydev)
+					continue;
 
-					if (tmp_phydev->attached_dev)
-						continue; /* already claimed by MAC0 */
+				/* already claimed by MAC0 */
+				if (tmp_phydev->attached_dev)
+					continue;
 
-					phydev = tmp_phydev;
-					break; /* found it */
-				}
+				phydev = tmp_phydev;
+				break; /* found it */
 			}
 		}
 	}
@@ -452,20 +477,20 @@
  * has the virtual and dma address of a buffer suitable for
  * both, receive and transmit operations.
  */
-static db_dest_t *au1000_GetFreeDB(struct au1000_private *aup)
+static struct db_dest *au1000_GetFreeDB(struct au1000_private *aup)
 {
-	db_dest_t *pDB;
+	struct db_dest *pDB;
 	pDB = aup->pDBfree;
 
-	if (pDB) {
+	if (pDB)
 		aup->pDBfree = pDB->pnext;
-	}
+
 	return pDB;
 }
 
-void au1000_ReleaseDB(struct au1000_private *aup, db_dest_t *pDB)
+void au1000_ReleaseDB(struct au1000_private *aup, struct db_dest *pDB)
 {
-	db_dest_t *pDBfree = aup->pDBfree;
+	struct db_dest *pDBfree = aup->pDBfree;
 	if (pDBfree)
 		pDBfree->pnext = pDB;
 	aup->pDBfree = pDB;
@@ -478,9 +503,9 @@
 
 	au1000_hard_stop(dev);
 
-	*aup->enable = MAC_EN_CLOCK_ENABLE;
+	writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
 	au_sync_delay(2);
-	*aup->enable = 0;
+	writel(0, &aup->enable);
 	au_sync_delay(2);
 
 	aup->tx_full = 0;
@@ -507,7 +532,7 @@
 
 	spin_lock_irqsave(&aup->lock, flags);
 
-	au1000_reset_mac_unlocked (dev);
+	au1000_reset_mac_unlocked(dev);
 
 	spin_unlock_irqrestore(&aup->lock, flags);
 }
@@ -524,11 +549,13 @@
 
 	for (i = 0; i < NUM_RX_DMA; i++) {
 		aup->rx_dma_ring[i] =
-			(volatile rx_dma_t *) (rx_base + sizeof(rx_dma_t)*i);
+			(struct rx_dma *)
+					(rx_base + sizeof(struct rx_dma)*i);
 	}
 	for (i = 0; i < NUM_TX_DMA; i++) {
 		aup->tx_dma_ring[i] =
-			(volatile tx_dma_t *) (tx_base + sizeof(tx_dma_t)*i);
+			(struct tx_dma *)
+					(tx_base + sizeof(struct tx_dma)*i);
 	}
 }
 
@@ -616,18 +643,21 @@
 
 	spin_lock_irqsave(&aup->lock, flags);
 
-	aup->mac->control = 0;
+	writel(0, &aup->mac->control);
 	aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2;
 	aup->tx_tail = aup->tx_head;
 	aup->rx_head = (aup->rx_dma_ring[0]->buff_stat & 0xC) >> 2;
 
-	aup->mac->mac_addr_high = dev->dev_addr[5]<<8 | dev->dev_addr[4];
-	aup->mac->mac_addr_low = dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 |
-		dev->dev_addr[1]<<8 | dev->dev_addr[0];
+	writel(dev->dev_addr[5]<<8 | dev->dev_addr[4],
+					&aup->mac->mac_addr_high);
+	writel(dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 |
+		dev->dev_addr[1]<<8 | dev->dev_addr[0],
+					&aup->mac->mac_addr_low);
 
-	for (i = 0; i < NUM_RX_DMA; i++) {
+
+	for (i = 0; i < NUM_RX_DMA; i++)
 		aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
-	}
+
 	au_sync();
 
 	control = MAC_RX_ENABLE | MAC_TX_ENABLE;
@@ -643,8 +673,8 @@
 		control |= MAC_FULL_DUPLEX;
 	}
 
-	aup->mac->control = control;
-	aup->mac->vlan1_tag = 0x8100; /* activate vlan support */
+	writel(control, &aup->mac->control);
+	writel(0x8100, &aup->mac->vlan1_tag); /* activate vlan support */
 	au_sync();
 
 	spin_unlock_irqrestore(&aup->lock, flags);
@@ -681,9 +711,9 @@
 {
 	struct au1000_private *aup = netdev_priv(dev);
 	struct sk_buff *skb;
-	volatile rx_dma_t *prxd;
+	struct rx_dma *prxd;
 	u32 buff_stat, status;
-	db_dest_t *pDB;
+	struct db_dest *pDB;
 	u32	frmlen;
 
 	netif_dbg(aup, rx_status, dev, "au1000_rx head %d\n", aup->rx_head);
@@ -713,24 +743,26 @@
 			netif_rx(skb);	/* pass the packet to upper layers */
 		} else {
 			if (au1000_debug > 4) {
+				pr_err("rx_error(s):");
 				if (status & RX_MISSED_FRAME)
-					printk("rx miss\n");
+					pr_cont(" miss");
 				if (status & RX_WDOG_TIMER)
-					printk("rx wdog\n");
+					pr_cont(" wdog");
 				if (status & RX_RUNT)
-					printk("rx runt\n");
+					pr_cont(" runt");
 				if (status & RX_OVERLEN)
-					printk("rx overlen\n");
+					pr_cont(" overlen");
 				if (status & RX_COLL)
-					printk("rx coll\n");
+					pr_cont(" coll");
 				if (status & RX_MII_ERROR)
-					printk("rx mii error\n");
+					pr_cont(" mii error");
 				if (status & RX_CRC_ERROR)
-					printk("rx crc error\n");
+					pr_cont(" crc error");
 				if (status & RX_LEN_ERROR)
-					printk("rx len error\n");
+					pr_cont(" len error");
 				if (status & RX_U_CNTRL_FRAME)
-					printk("rx u control frame\n");
+					pr_cont(" u control frame");
+				pr_cont("\n");
 			}
 		}
 		prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
@@ -753,7 +785,8 @@
 		if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) {
 			if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) {
 				/* any other tx errors are only valid
-				 * in half duplex mode */
+				 * in half duplex mode
+				 */
 				ps->tx_errors++;
 				ps->tx_aborted_errors++;
 			}
@@ -774,7 +807,7 @@
 static void au1000_tx_ack(struct net_device *dev)
 {
 	struct au1000_private *aup = netdev_priv(dev);
-	volatile tx_dma_t *ptxd;
+	struct tx_dma *ptxd;
 
 	ptxd = aup->tx_dma_ring[aup->tx_tail];
 
@@ -854,7 +887,7 @@
 
 	spin_lock_irqsave(&aup->lock, flags);
 
-	au1000_reset_mac_unlocked (dev);
+	au1000_reset_mac_unlocked(dev);
 
 	/* stop the device */
 	netif_stop_queue(dev);
@@ -873,9 +906,9 @@
 {
 	struct au1000_private *aup = netdev_priv(dev);
 	struct net_device_stats *ps = &dev->stats;
-	volatile tx_dma_t *ptxd;
+	struct tx_dma *ptxd;
 	u32 buff_stat;
-	db_dest_t *pDB;
+	struct db_dest *pDB;
 	int i;
 
 	netif_dbg(aup, tx_queued, dev, "tx: aup %x len=%d, data=%p, head %d\n",
@@ -902,9 +935,9 @@
 	pDB = aup->tx_db_inuse[aup->tx_head];
 	skb_copy_from_linear_data(skb, (void *)pDB->vaddr, skb->len);
 	if (skb->len < ETH_ZLEN) {
-		for (i = skb->len; i < ETH_ZLEN; i++) {
+		for (i = skb->len; i < ETH_ZLEN; i++)
 			((char *)pDB->vaddr)[i] = 0;
-		}
+
 		ptxd->len = ETH_ZLEN;
 	} else
 		ptxd->len = skb->len;
@@ -935,15 +968,16 @@
 static void au1000_multicast_list(struct net_device *dev)
 {
 	struct au1000_private *aup = netdev_priv(dev);
+	u32 reg;
 
-	netif_dbg(aup, drv, dev, "au1000_multicast_list: flags=%x\n", dev->flags);
-
+	netif_dbg(aup, drv, dev, "%s: flags=%x\n", __func__, dev->flags);
+	reg = readl(&aup->mac->control);
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		aup->mac->control |= MAC_PROMISCUOUS;
+		reg |= MAC_PROMISCUOUS;
 	} else if ((dev->flags & IFF_ALLMULTI)  ||
 			   netdev_mc_count(dev) > MULTICAST_FILTER_LIMIT) {
-		aup->mac->control |= MAC_PASS_ALL_MULTI;
-		aup->mac->control &= ~MAC_PROMISCUOUS;
+		reg |= MAC_PASS_ALL_MULTI;
+		reg &= ~MAC_PROMISCUOUS;
 		netdev_info(dev, "Pass all multicast\n");
 	} else {
 		struct netdev_hw_addr *ha;
@@ -953,11 +987,12 @@
 		netdev_for_each_mc_addr(ha, dev)
 			set_bit(ether_crc(ETH_ALEN, ha->addr)>>26,
 					(long *)mc_filter);
-		aup->mac->multi_hash_high = mc_filter[1];
-		aup->mac->multi_hash_low = mc_filter[0];
-		aup->mac->control &= ~MAC_PROMISCUOUS;
-		aup->mac->control |= MAC_HASH_MODE;
+		writel(mc_filter[1], &aup->mac->multi_hash_high);
+		writel(mc_filter[0], &aup->mac->multi_hash_low);
+		reg &= ~MAC_PROMISCUOUS;
+		reg |= MAC_HASH_MODE;
 	}
+	writel(reg, &aup->mac->control);
 }
 
 static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -991,7 +1026,7 @@
 	struct au1000_private *aup = NULL;
 	struct au1000_eth_platform_data *pd;
 	struct net_device *dev = NULL;
-	db_dest_t *pDB, *pDBfree;
+	struct db_dest *pDB, *pDBfree;
 	int irq, i, err = 0;
 	struct resource *base, *macen;
 
@@ -1016,13 +1051,15 @@
 		goto out;
 	}
 
-	if (!request_mem_region(base->start, resource_size(base), pdev->name)) {
+	if (!request_mem_region(base->start, resource_size(base),
+							pdev->name)) {
 		dev_err(&pdev->dev, "failed to request memory region for base registers\n");
 		err = -ENXIO;
 		goto out;
 	}
 
-	if (!request_mem_region(macen->start, resource_size(macen), pdev->name)) {
+	if (!request_mem_region(macen->start, resource_size(macen),
+							pdev->name)) {
 		dev_err(&pdev->dev, "failed to request memory region for MAC enable register\n");
 		err = -ENXIO;
 		goto err_request;
@@ -1040,10 +1077,12 @@
 	aup = netdev_priv(dev);
 
 	spin_lock_init(&aup->lock);
-	aup->msg_enable = (au1000_debug < 4 ? AU1000_DEF_MSG_ENABLE : au1000_debug);
+	aup->msg_enable = (au1000_debug < 4 ?
+				AU1000_DEF_MSG_ENABLE : au1000_debug);
 
-	/* Allocate the data buffers */
-	/* Snooping works fine with eth on all au1xxx */
+	/* Allocate the data buffers
+	 * Snooping works fine with eth on all au1xxx
+	 */
 	aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
 						(NUM_TX_BUFFS + NUM_RX_BUFFS),
 						&aup->dma_addr,	0);
@@ -1054,15 +1093,17 @@
 	}
 
 	/* aup->mac is the base address of the MAC's registers */
-	aup->mac = (volatile mac_reg_t *)ioremap_nocache(base->start, resource_size(base));
+	aup->mac = (struct mac_reg *)
+			ioremap_nocache(base->start, resource_size(base));
 	if (!aup->mac) {
 		dev_err(&pdev->dev, "failed to ioremap MAC registers\n");
 		err = -ENXIO;
 		goto err_remap1;
 	}
 
-        /* Setup some variables for quick register address access */
-	aup->enable = (volatile u32 *)ioremap_nocache(macen->start, resource_size(macen));
+	/* Setup some variables for quick register address access */
+	aup->enable = (u32 *)ioremap_nocache(macen->start,
+						resource_size(macen));
 	if (!aup->enable) {
 		dev_err(&pdev->dev, "failed to ioremap MAC enable register\n");
 		err = -ENXIO;
@@ -1078,12 +1119,13 @@
 	/* set a random MAC now in case platform_data doesn't provide one */
 	random_ether_addr(dev->dev_addr);
 
-	*aup->enable = 0;
+	writel(0, &aup->enable);
 	aup->mac_enabled = 0;
 
 	pd = pdev->dev.platform_data;
 	if (!pd) {
-		dev_info(&pdev->dev, "no platform_data passed, PHY search on MAC0\n");
+		dev_info(&pdev->dev, "no platform_data passed,"
+					" PHY search on MAC0\n");
 		aup->phy1_search_mac0 = 1;
 	} else {
 		if (is_valid_ether_addr(pd->mac))
@@ -1098,8 +1140,7 @@
 	}
 
 	if (aup->phy_busid && aup->phy_busid > 0) {
-		dev_err(&pdev->dev, "MAC0-associated PHY attached 2nd MACs MII"
-				"bus not supported yet\n");
+		dev_err(&pdev->dev, "MAC0-associated PHY attached 2nd MACs MII bus not supported yet\n");
 		err = -ENODEV;
 		goto err_mdiobus_alloc;
 	}
@@ -1151,17 +1192,17 @@
 
 	for (i = 0; i < NUM_RX_DMA; i++) {
 		pDB = au1000_GetFreeDB(aup);
-		if (!pDB) {
+		if (!pDB)
 			goto err_out;
-		}
+
 		aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
 		aup->rx_db_inuse[i] = pDB;
 	}
 	for (i = 0; i < NUM_TX_DMA; i++) {
 		pDB = au1000_GetFreeDB(aup);
-		if (!pDB) {
+		if (!pDB)
 			goto err_out;
-		}
+
 		aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
 		aup->tx_dma_ring[i]->len = 0;
 		aup->tx_db_inuse[i] = pDB;
@@ -1188,7 +1229,8 @@
 	netdev_info(dev, "Au1xx0 Ethernet found at 0x%lx, irq %d\n",
 			(unsigned long)base->start, irq);
 	if (version_printed++ == 0)
-		printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
+		pr_info("%s version %s %s\n",
+					DRV_NAME, DRV_VERSION, DRV_AUTHOR);
 
 	return 0;
 
@@ -1197,7 +1239,8 @@
 		mdiobus_unregister(aup->mii_bus);
 
 	/* here we should have a valid dev plus aup-> register addresses
-	 * so we can reset the mac properly.*/
+	 * so we can reset the mac properly.
+	 */
 	au1000_reset_mac(dev);
 
 	for (i = 0; i < NUM_RX_DMA; i++) {
diff --git a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h
index d06ec00..6229c77 100644
--- a/drivers/net/au1000_eth.h
+++ b/drivers/net/au1000_eth.h
@@ -44,34 +44,34 @@
  * Data Buffer Descriptor. Data buffers must be aligned on 32 byte
  * boundary for both, receive and transmit.
  */
-typedef struct db_dest {
+struct db_dest {
 	struct db_dest *pnext;
-	volatile u32 *vaddr;
+	u32 *vaddr;
 	dma_addr_t dma_addr;
-} db_dest_t;
+};
 
 /*
  * The transmit and receive descriptors are memory
  * mapped registers.
  */
-typedef struct tx_dma {
+struct tx_dma {
 	u32 status;
 	u32 buff_stat;
 	u32 len;
 	u32 pad;
-} tx_dma_t;
+};
 
-typedef struct rx_dma {
+struct rx_dma {
 	u32 status;
 	u32 buff_stat;
 	u32 pad[2];
-} rx_dma_t;
+};
 
 
 /*
  * MAC control registers, memory mapped.
  */
-typedef struct mac_reg {
+struct mac_reg {
 	u32 control;
 	u32 mac_addr_high;
 	u32 mac_addr_low;
@@ -82,16 +82,16 @@
 	u32 flow_control;
 	u32 vlan1_tag;
 	u32 vlan2_tag;
-} mac_reg_t;
+};
 
 
 struct au1000_private {
-	db_dest_t *pDBfree;
-	db_dest_t db[NUM_RX_BUFFS+NUM_TX_BUFFS];
-	volatile rx_dma_t *rx_dma_ring[NUM_RX_DMA];
-	volatile tx_dma_t *tx_dma_ring[NUM_TX_DMA];
-	db_dest_t *rx_db_inuse[NUM_RX_DMA];
-	db_dest_t *tx_db_inuse[NUM_TX_DMA];
+	struct db_dest *pDBfree;
+	struct db_dest db[NUM_RX_BUFFS+NUM_TX_BUFFS];
+	struct rx_dma *rx_dma_ring[NUM_RX_DMA];
+	struct tx_dma *tx_dma_ring[NUM_TX_DMA];
+	struct db_dest *rx_db_inuse[NUM_RX_DMA];
+	struct db_dest *tx_db_inuse[NUM_TX_DMA];
 	u32 rx_head;
 	u32 tx_head;
 	u32 tx_tail;
@@ -99,7 +99,9 @@
 
 	int mac_id;
 
-	int mac_enabled;       /* whether MAC is currently enabled and running (req. for mdio) */
+	int mac_enabled;       /* whether MAC is currently enabled and running
+				* (req. for mdio)
+				*/
 
 	int old_link;          /* used by au1000_adjust_link */
 	int old_speed;
@@ -117,9 +119,11 @@
 	int phy_busid;
 	int phy_irq;
 
-	/* These variables are just for quick access to certain regs addresses. */
-	volatile mac_reg_t *mac;  /* mac registers                      */
-	volatile u32 *enable;     /* address of MAC Enable Register     */
+	/* These variables are just for quick access
+	 * to certain regs addresses.
+	 */
+	struct mac_reg *mac;  /* mac registers                      */
+	u32 *enable;     /* address of MAC Enable Register     */
 
 	u32 vaddr;                /* virtual address of rx/tx buffers   */
 	dma_addr_t dma_addr;      /* dma address of rx/tx buffers       */
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
index 20e946b..b6da4cf 100644
--- a/drivers/net/ax88796.c
+++ b/drivers/net/ax88796.c
@@ -864,6 +864,7 @@
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (res == NULL) {
 		dev_err(&pdev->dev, "no IRQ specified\n");
+		ret = -ENXIO;
 		goto exit_mem;
 	}
 
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 1e620e2..c6e8631 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -818,7 +818,7 @@
 							 copy_skb->data, len);
 			skb = copy_skb;
 		}
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 		skb->protocol = eth_type_trans(skb, bp->dev);
 		netif_receive_skb(skb);
 		received++;
@@ -2170,8 +2170,6 @@
 	dev->irq = sdev->irq;
 	SET_ETHTOOL_OPS(dev, &b44_ethtool_ops);
 
-	netif_carrier_off(dev);
-
 	err = ssb_bus_powerup(sdev->bus, 0);
 	if (err) {
 		dev_err(sdev->dev,
@@ -2213,6 +2211,8 @@
 		goto err_out_powerdown;
 	}
 
+	netif_carrier_off(dev);
+
 	ssb_set_drvdata(sdev, dev);
 
 	/* Chip reset provides power to the b44 MAC & PCI cores, which
@@ -2296,18 +2296,27 @@
 	if (!netif_running(dev))
 		return 0;
 
+	spin_lock_irq(&bp->lock);
+	b44_init_rings(bp);
+	b44_init_hw(bp, B44_FULL_RESET);
+	spin_unlock_irq(&bp->lock);
+
+	/*
+	 * As a shared interrupt, the handler can be called immediately. To be
+	 * able to check the interrupt status the hardware must already be
+	 * powered back on (b44_init_hw).
+	 */
 	rc = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
 	if (rc) {
 		netdev_err(dev, "request_irq failed\n");
+		spin_lock_irq(&bp->lock);
+		b44_halt(bp);
+		b44_free_rings(bp);
+		spin_unlock_irq(&bp->lock);
 		return rc;
 	}
 
-	spin_lock_irq(&bp->lock);
-
-	b44_init_rings(bp);
-	b44_init_hw(bp, B44_FULL_RESET);
 	netif_device_attach(bp->dev);
-	spin_unlock_irq(&bp->lock);
 
 	b44_enable_ints(bp);
 	netif_wake_queue(dev);
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c
index 0d2c5da..ecfef24 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/bcm63xx_enet.c
@@ -293,22 +293,22 @@
 		/* if the packet does not have start of packet _and_
 		 * end of packet flag set, then just recycle it */
 		if ((len_stat & DMADESC_ESOP_MASK) != DMADESC_ESOP_MASK) {
-			priv->stats.rx_dropped++;
+			dev->stats.rx_dropped++;
 			continue;
 		}
 
 		/* recycle packet if it's marked as bad */
 		if (unlikely(len_stat & DMADESC_ERR_MASK)) {
-			priv->stats.rx_errors++;
+			dev->stats.rx_errors++;
 
 			if (len_stat & DMADESC_OVSIZE_MASK)
-				priv->stats.rx_length_errors++;
+				dev->stats.rx_length_errors++;
 			if (len_stat & DMADESC_CRC_MASK)
-				priv->stats.rx_crc_errors++;
+				dev->stats.rx_crc_errors++;
 			if (len_stat & DMADESC_UNDER_MASK)
-				priv->stats.rx_frame_errors++;
+				dev->stats.rx_frame_errors++;
 			if (len_stat & DMADESC_OV_MASK)
-				priv->stats.rx_fifo_errors++;
+				dev->stats.rx_fifo_errors++;
 			continue;
 		}
 
@@ -324,7 +324,7 @@
 			nskb = netdev_alloc_skb_ip_align(dev, len);
 			if (!nskb) {
 				/* forget packet, just rearm desc */
-				priv->stats.rx_dropped++;
+				dev->stats.rx_dropped++;
 				continue;
 			}
 
@@ -342,8 +342,8 @@
 
 		skb_put(skb, len);
 		skb->protocol = eth_type_trans(skb, dev);
-		priv->stats.rx_packets++;
-		priv->stats.rx_bytes += len;
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += len;
 		netif_receive_skb(skb);
 
 	} while (--budget > 0);
@@ -403,7 +403,7 @@
 		spin_unlock(&priv->tx_lock);
 
 		if (desc->len_stat & DMADESC_UNDER_MASK)
-			priv->stats.tx_errors++;
+			dev->stats.tx_errors++;
 
 		dev_kfree_skb(skb);
 		released++;
@@ -563,8 +563,8 @@
 	if (!priv->tx_desc_count)
 		netif_stop_queue(dev);
 
-	priv->stats.tx_bytes += skb->len;
-	priv->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+	dev->stats.tx_packets++;
 	ret = NETDEV_TX_OK;
 
 out_unlock:
@@ -798,7 +798,7 @@
 		snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
 			 priv->mac_id ? "1" : "0", priv->phy_id);
 
-		phydev = phy_connect(dev, phy_id, &bcm_enet_adjust_phy_link, 0,
+		phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, 0,
 				     PHY_INTERFACE_MODE_MII);
 
 		if (IS_ERR(phydev)) {
@@ -1141,17 +1141,6 @@
 }
 
 /*
- * core request to return device rx/tx stats
- */
-static struct net_device_stats *bcm_enet_get_stats(struct net_device *dev)
-{
-	struct bcm_enet_priv *priv;
-
-	priv = netdev_priv(dev);
-	return &priv->stats;
-}
-
-/*
  * ethtool callbacks
  */
 struct bcm_enet_stats {
@@ -1163,16 +1152,18 @@
 
 #define GEN_STAT(m) sizeof(((struct bcm_enet_priv *)0)->m),		\
 		     offsetof(struct bcm_enet_priv, m)
+#define DEV_STAT(m) sizeof(((struct net_device_stats *)0)->m),		\
+		     offsetof(struct net_device_stats, m)
 
 static const struct bcm_enet_stats bcm_enet_gstrings_stats[] = {
-	{ "rx_packets", GEN_STAT(stats.rx_packets), -1 },
-	{ "tx_packets",	GEN_STAT(stats.tx_packets), -1 },
-	{ "rx_bytes", GEN_STAT(stats.rx_bytes), -1 },
-	{ "tx_bytes", GEN_STAT(stats.tx_bytes), -1 },
-	{ "rx_errors", GEN_STAT(stats.rx_errors), -1 },
-	{ "tx_errors", GEN_STAT(stats.tx_errors), -1 },
-	{ "rx_dropped",	GEN_STAT(stats.rx_dropped), -1 },
-	{ "tx_dropped",	GEN_STAT(stats.tx_dropped), -1 },
+	{ "rx_packets", DEV_STAT(rx_packets), -1 },
+	{ "tx_packets",	DEV_STAT(tx_packets), -1 },
+	{ "rx_bytes", DEV_STAT(rx_bytes), -1 },
+	{ "tx_bytes", DEV_STAT(tx_bytes), -1 },
+	{ "rx_errors", DEV_STAT(rx_errors), -1 },
+	{ "tx_errors", DEV_STAT(tx_errors), -1 },
+	{ "rx_dropped",	DEV_STAT(rx_dropped), -1 },
+	{ "tx_dropped",	DEV_STAT(tx_dropped), -1 },
 
 	{ "rx_good_octets", GEN_STAT(mib.rx_gd_octets), ETH_MIB_RX_GD_OCTETS},
 	{ "rx_good_pkts", GEN_STAT(mib.rx_gd_pkts), ETH_MIB_RX_GD_PKTS },
@@ -1328,7 +1319,11 @@
 		char *p;
 
 		s = &bcm_enet_gstrings_stats[i];
-		p = (char *)priv + s->stat_offset;
+		if (s->mib_reg == -1)
+			p = (char *)&netdev->stats;
+		else
+			p = (char *)priv;
+		p += s->stat_offset;
 		data[i] = (s->sizeof_stat == sizeof(u64)) ?
 			*(u64 *)p : *(u32 *)p;
 	}
@@ -1605,7 +1600,6 @@
 	.ndo_open		= bcm_enet_open,
 	.ndo_stop		= bcm_enet_stop,
 	.ndo_start_xmit		= bcm_enet_start_xmit,
-	.ndo_get_stats		= bcm_enet_get_stats,
 	.ndo_set_mac_address	= bcm_enet_set_mac_address,
 	.ndo_set_multicast_list = bcm_enet_set_multicast_list,
 	.ndo_do_ioctl		= bcm_enet_ioctl,
diff --git a/drivers/net/bcm63xx_enet.h b/drivers/net/bcm63xx_enet.h
index bd3684d..0e3048b 100644
--- a/drivers/net/bcm63xx_enet.h
+++ b/drivers/net/bcm63xx_enet.h
@@ -274,7 +274,6 @@
 	int pause_tx;
 
 	/* stats */
-	struct net_device_stats stats;
 	struct bcm_enet_mib_counters mib;
 
 	/* after mib interrupt, mib registers update is done in this
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index 53306bf..4594a28 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -78,6 +78,8 @@
 #define MCC_Q_LEN		128	/* total size not to exceed 8 pages */
 #define MCC_CQ_LEN		256
 
+#define MAX_RSS_QS		4	/* BE limit is 4 queues/port */
+#define BE_MAX_MSIX_VECTORS	(MAX_RSS_QS + 1 + 1)/* RSS qs + 1 def Rx + Tx */
 #define BE_NAPI_WEIGHT		64
 #define MAX_RX_POST 		BE_NAPI_WEIGHT /* Frags posted at a time */
 #define RX_FRAGS_REFILL_WM	(RX_Q_LEN - MAX_RX_POST)
@@ -157,10 +159,9 @@
 	bool rearm_cq;
 };
 
-struct be_drvr_stats {
+struct be_tx_stats {
 	u32 be_tx_reqs;		/* number of TX requests initiated */
 	u32 be_tx_stops;	/* number of times TX Q was stopped */
-	u32 be_fwd_reqs;	/* number of send reqs through forwarding i/f */
 	u32 be_tx_wrbs;		/* number of tx WRBs used */
 	u32 be_tx_events;	/* number of tx completion events  */
 	u32 be_tx_compl;	/* number of tx completion entries processed */
@@ -169,35 +170,6 @@
 	u64 be_tx_bytes_prev;
 	u64 be_tx_pkts;
 	u32 be_tx_rate;
-
-	u32 cache_barrier[16];
-
-	u32 be_ethrx_post_fail;/* number of ethrx buffer alloc failures */
-	u32 be_rx_polls;	/* number of times NAPI called poll function */
-	u32 be_rx_events;	/* number of ucast rx completion events  */
-	u32 be_rx_compl;	/* number of rx completion entries processed */
-	ulong be_rx_jiffies;
-	u64 be_rx_bytes;
-	u64 be_rx_bytes_prev;
-	u64 be_rx_pkts;
-	u32 be_rx_rate;
-	u32 be_rx_mcast_pkt;
-	/* number of non ether type II frames dropped where
-	 * frame len > length field of Mac Hdr */
-	u32 be_802_3_dropped_frames;
-	/* number of non ether type II frames malformed where
-	 * in frame len < length field of Mac Hdr */
-	u32 be_802_3_malformed_frames;
-	u32 be_rxcp_err;	/* Num rx completion entries w/ err set. */
-	ulong rx_fps_jiffies;	/* jiffies at last FPS calc */
-	u32 be_rx_frags;
-	u32 be_prev_rx_frags;
-	u32 be_rx_fps;		/* Rx frags per second */
-};
-
-struct be_stats_obj {
-	struct be_drvr_stats drvr_stats;
-	struct be_dma_mem cmd;
 };
 
 struct be_tx_obj {
@@ -215,10 +187,34 @@
 	bool last_page_user;
 };
 
+struct be_rx_stats {
+	u32 rx_post_fail;/* number of ethrx buffer alloc failures */
+	u32 rx_polls;	/* number of times NAPI called poll function */
+	u32 rx_events;	/* number of ucast rx completion events  */
+	u32 rx_compl;	/* number of rx completion entries processed */
+	ulong rx_jiffies;
+	u64 rx_bytes;
+	u64 rx_bytes_prev;
+	u64 rx_pkts;
+	u32 rx_rate;
+	u32 rx_mcast_pkts;
+	u32 rxcp_err;	/* Num rx completion entries w/ err set. */
+	ulong rx_fps_jiffies;	/* jiffies at last FPS calc */
+	u32 rx_frags;
+	u32 prev_rx_frags;
+	u32 rx_fps;		/* Rx frags per second */
+};
+
 struct be_rx_obj {
+	struct be_adapter *adapter;
 	struct be_queue_info q;
 	struct be_queue_info cq;
 	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 */
+	u32 cache_line_barrier[16];
 };
 
 struct be_vf_cfg {
@@ -229,7 +225,6 @@
 	u32 vf_tx_rate;
 };
 
-#define BE_NUM_MSIX_VECTORS		2	/* 1 each for Tx and Rx */
 #define BE_INVALID_PMAC_ID		0xffffffff
 struct be_adapter {
 	struct pci_dev *pdev;
@@ -249,29 +244,31 @@
 	spinlock_t mcc_lock;	/* For serializing mcc cmds to BE card */
 	spinlock_t mcc_cq_lock;
 
-	struct msix_entry msix_entries[BE_NUM_MSIX_VECTORS];
+	struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS];
 	bool msix_enabled;
 	bool isr_registered;
 
 	/* TX Rings */
 	struct be_eq_obj tx_eq;
 	struct be_tx_obj tx_obj;
+	struct be_tx_stats tx_stats;
 
 	u32 cache_line_break[8];
 
 	/* Rx rings */
-	struct be_eq_obj rx_eq;
-	struct be_rx_obj rx_obj;
+	struct be_rx_obj rx_obj[MAX_RSS_QS + 1]; /* one default non-rss Q */
+	u32 num_rx_qs;
 	u32 big_page_size;	/* Compounded page size shared by rx wrbs */
-	bool rx_post_starved;	/* Zero rx frags have been posted to BE */
 
 	struct vlan_group *vlan_grp;
 	u16 vlans_added;
 	u16 max_vlans;	/* Number of vlans supported */
-	u8 vlan_tag[VLAN_GROUP_ARRAY_LEN];
+	u8 vlan_tag[VLAN_N_VID];
+	u8 vlan_prio_bmap;	/* Available Priority BitMap */
+	u16 recommended_prio;	/* Recommended Priority */
 	struct be_dma_mem mc_cmd_mem;
 
-	struct be_stats_obj stats;
+	struct be_dma_mem stats_cmd;
 	/* Work queue used to perform periodic tasks like getting statistics */
 	struct delayed_work work;
 
@@ -287,6 +284,7 @@
 	bool promiscuous;
 	bool wol;
 	u32 function_mode;
+	u32 function_caps;
 	u32 rx_fc;		/* Rx flow control */
 	u32 tx_fc;		/* Tx flow control */
 	bool ue_detected;
@@ -313,10 +311,20 @@
 
 extern const struct ethtool_ops be_ethtool_ops;
 
-#define drvr_stats(adapter)		(&adapter->stats.drvr_stats)
+#define tx_stats(adapter)		(&adapter->tx_stats)
+#define rx_stats(rxo)			(&rxo->stats)
 
 #define BE_SET_NETDEV_OPS(netdev, ops)	(netdev->netdev_ops = ops)
 
+#define for_all_rx_queues(adapter, rxo, i)				\
+	for (i = 0, rxo = &adapter->rx_obj[i]; i < adapter->num_rx_qs;	\
+		i++, rxo++)
+
+/* Just skip the first default non-rss queue */
+#define for_all_rss_queues(adapter, rxo, i)				\
+	for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\
+		i++, rxo++)
+
 #define PAGE_SHIFT_4K		12
 #define PAGE_SIZE_4K		(1 << PAGE_SHIFT_4K)
 
@@ -414,6 +422,20 @@
 	adapter->is_virtfn = (data != 0xAA);
 }
 
+static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
+{
+	u32 addr;
+
+	addr = jhash(adapter->netdev->dev_addr, ETH_ALEN, 0);
+
+	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;
+}
+
 extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
 		u16 num_popped);
 extern void be_link_status_update(struct be_adapter *adapter, bool link_up);
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 34abcc9..1e7f305 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -71,7 +71,7 @@
 	if (compl_status == MCC_STATUS_SUCCESS) {
 		if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) {
 			struct be_cmd_resp_get_stats *resp =
-						adapter->stats.cmd.va;
+						adapter->stats_cmd.va;
 			be_dws_le_to_cpu(&resp->hw_stats,
 						sizeof(resp->hw_stats));
 			netdev_stats_update(adapter);
@@ -96,11 +96,62 @@
 		evt->port_link_status == ASYNC_EVENT_LINK_UP);
 }
 
+/* Grp5 CoS Priority evt */
+static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
+		struct be_async_event_grp5_cos_priority *evt)
+{
+	if (evt->valid) {
+		adapter->vlan_prio_bmap = evt->available_priority_bmap;
+		adapter->recommended_prio =
+			evt->reco_default_priority << VLAN_PRIO_SHIFT;
+	}
+}
+
+/* Grp5 QOS Speed evt */
+static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
+		struct be_async_event_grp5_qos_link_speed *evt)
+{
+	if (evt->physical_port == adapter->port_num) {
+		/* qos_link_speed is in units of 10 Mbps */
+		adapter->link_speed = evt->qos_link_speed * 10;
+	}
+}
+
+static void be_async_grp5_evt_process(struct be_adapter *adapter,
+		u32 trailer, struct be_mcc_compl *evt)
+{
+	u8 event_type = 0;
+
+	event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) &
+		ASYNC_TRAILER_EVENT_TYPE_MASK;
+
+	switch (event_type) {
+	case ASYNC_EVENT_COS_PRIORITY:
+		be_async_grp5_cos_priority_process(adapter,
+		(struct be_async_event_grp5_cos_priority *)evt);
+	break;
+	case ASYNC_EVENT_QOS_SPEED:
+		be_async_grp5_qos_speed_process(adapter,
+		(struct be_async_event_grp5_qos_link_speed *)evt);
+	break;
+	default:
+		dev_warn(&adapter->pdev->dev, "Unknown grp5 event!\n");
+		break;
+	}
+}
+
 static inline bool is_link_state_evt(u32 trailer)
 {
+	return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
+		ASYNC_TRAILER_EVENT_CODE_MASK) ==
+				ASYNC_EVENT_CODE_LINK_STATE;
+}
+
+static inline bool is_grp5_evt(u32 trailer)
+{
 	return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
 		ASYNC_TRAILER_EVENT_CODE_MASK) ==
-				ASYNC_EVENT_CODE_LINK_STATE);
+				ASYNC_EVENT_CODE_GRP_5);
 }
 
 static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
@@ -143,6 +194,9 @@
 			if (is_link_state_evt(compl->flags))
 				be_async_link_state_process(adapter,
 				(struct be_async_event_link_state *) compl);
+			else if (is_grp5_evt(compl->flags))
+				be_async_grp5_evt_process(adapter,
+				compl->flags, compl);
 		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
 				*status = be_mcc_compl_process(adapter, compl);
 				atomic_dec(&mcc_obj->q.used);
@@ -677,10 +731,10 @@
 	ctxt = &req->context;
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
-			OPCODE_COMMON_MCC_CREATE);
+			OPCODE_COMMON_MCC_CREATE_EXT);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-			OPCODE_COMMON_MCC_CREATE, sizeof(*req));
+			OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req));
 
 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
 
@@ -688,7 +742,8 @@
 	AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt,
 		be_encoded_q_len(mccq->len));
 	AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id);
-
+	/* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */
+	req->async_event_bitmap[0] |= 0x00000022;
 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
 
 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
@@ -754,7 +809,7 @@
 /* Uses mbox */
 int be_cmd_rxq_create(struct be_adapter *adapter,
 		struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
-		u16 max_frame_size, u32 if_id, u32 rss)
+		u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_eth_rx_create *req;
@@ -785,6 +840,7 @@
 		struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
 		rxq->id = le16_to_cpu(resp->id);
 		rxq->created = true;
+		*rss_id = resp->rss_id;
 	}
 
 	spin_unlock(&adapter->mbox_lock);
@@ -1259,7 +1315,8 @@
 }
 
 /* Uses mbox */
-int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, u32 *mode)
+int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
+		u32 *mode, u32 *caps)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_query_fw_cfg *req;
@@ -1281,6 +1338,7 @@
 		struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
 		*port_num = le32_to_cpu(resp->phys_port);
 		*mode = le32_to_cpu(resp->function_mode);
+		*caps = le32_to_cpu(resp->function_caps);
 	}
 
 	spin_unlock(&adapter->mbox_lock);
@@ -1311,6 +1369,37 @@
 	return status;
 }
 
+int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_rss_config *req;
+	u32 myhash[10];
+	int status;
+
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+		OPCODE_ETH_RSS_CONFIG);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
+		OPCODE_ETH_RSS_CONFIG, sizeof(*req));
+
+	req->if_id = cpu_to_le32(adapter->if_handle);
+	req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4);
+	req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
+	memcpy(req->cpu_table, rsstable, table_size);
+	memcpy(req->hash, myhash, sizeof(myhash));
+	be_dws_cpu_to_le(req->hash, sizeof(req->hash));
+
+	status = be_mbox_notify_wait(adapter);
+
+	spin_unlock(&adapter->mbox_lock);
+	return status;
+}
+
 /* Uses sync mcc */
 int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
 			u8 bcn, u8 sts, u8 state)
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index ad1e6fa..c7f6cdf 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -82,7 +82,12 @@
  */
 #define ASYNC_TRAILER_EVENT_CODE_SHIFT	8	/* bits 8 - 15 */
 #define ASYNC_TRAILER_EVENT_CODE_MASK	0xFF
+#define ASYNC_TRAILER_EVENT_TYPE_SHIFT	16
+#define ASYNC_TRAILER_EVENT_TYPE_MASK	0xFF
 #define ASYNC_EVENT_CODE_LINK_STATE	0x1
+#define ASYNC_EVENT_CODE_GRP_5		0x5
+#define ASYNC_EVENT_QOS_SPEED		0x1
+#define ASYNC_EVENT_COS_PRIORITY	0x2
 struct be_async_event_trailer {
 	u32 code;
 };
@@ -105,6 +110,30 @@
 	struct be_async_event_trailer trailer;
 } __packed;
 
+/* When the event code of an async trailer is GRP-5 and event_type is QOS_SPEED
+ * the mcc_compl must be interpreted as follows
+ */
+struct be_async_event_grp5_qos_link_speed {
+	u8 physical_port;
+	u8 rsvd[5];
+	u16 qos_link_speed;
+	u32 event_tag;
+	struct be_async_event_trailer trailer;
+} __packed;
+
+/* When the event code of an async trailer is GRP5 and event type is
+ * CoS-Priority, the mcc_compl must be interpreted as follows
+ */
+struct be_async_event_grp5_cos_priority {
+	u8 physical_port;
+	u8 available_priority_bmap;
+	u8 reco_default_priority;
+	u8 valid;
+	u8 rsvd0;
+	u8 event_tag;
+	struct be_async_event_trailer trailer;
+} __packed;
+
 struct be_mcc_mailbox {
 	struct be_mcc_wrb wrb;
 	struct be_mcc_compl compl;
@@ -123,8 +152,9 @@
 #define OPCODE_COMMON_WRITE_FLASHROM			7
 #define OPCODE_COMMON_CQ_CREATE				12
 #define OPCODE_COMMON_EQ_CREATE				13
-#define OPCODE_COMMON_MCC_CREATE        		21
+#define OPCODE_COMMON_MCC_CREATE			21
 #define OPCODE_COMMON_SET_QOS				28
+#define OPCODE_COMMON_MCC_CREATE_EXT			90
 #define OPCODE_COMMON_SEEPROM_READ			30
 #define OPCODE_COMMON_NTWK_RX_FILTER    		34
 #define OPCODE_COMMON_GET_FW_VERSION			35
@@ -147,6 +177,7 @@
 #define OPCODE_COMMON_READ_TRANSRECV_DATA		73
 #define OPCODE_COMMON_GET_PHY_DETAILS			102
 
+#define OPCODE_ETH_RSS_CONFIG				1
 #define OPCODE_ETH_ACPI_CONFIG				2
 #define OPCODE_ETH_PROMISCUOUS				3
 #define OPCODE_ETH_GET_STATISTICS			4
@@ -337,6 +368,7 @@
 	struct be_cmd_req_hdr hdr;
 	u16 num_pages;
 	u16 rsvd0;
+	u32 async_event_bitmap[1];
 	u8 context[sizeof(struct amap_mcc_context) / 8];
 	struct phys_addr pages[8];
 } __packed;
@@ -409,7 +441,7 @@
 struct be_cmd_resp_eth_rx_create {
 	struct be_cmd_resp_hdr hdr;
 	u16 id;
-	u8 cpu_id;
+	u8 rss_id;
 	u8 rsvd0;
 } __packed;
 
@@ -739,9 +771,10 @@
 } __packed;
 
 /******************** Get FW Config *******************/
+#define BE_FUNCTION_CAPS_RSS			0x2
 struct be_cmd_req_query_fw_cfg {
 	struct be_cmd_req_hdr hdr;
-	u32 rsvd[30];
+	u32 rsvd[31];
 };
 
 struct be_cmd_resp_query_fw_cfg {
@@ -751,6 +784,26 @@
 	u32 phys_port;
 	u32 function_mode;
 	u32 rsvd[26];
+	u32 function_caps;
+};
+
+/******************** RSS Config *******************/
+/* RSS types */
+#define RSS_ENABLE_NONE				0x0
+#define RSS_ENABLE_IPV4				0x1
+#define RSS_ENABLE_TCP_IPV4			0x2
+#define RSS_ENABLE_IPV6				0x4
+#define RSS_ENABLE_TCP_IPV6			0x8
+
+struct be_cmd_req_rss_config {
+	struct be_cmd_req_hdr hdr;
+	u32 if_id;
+	u16 enable_rss;
+	u16 cpu_table_size_log2;
+	u32 hash[10];
+	u8 cpu_table[128];
+	u8 flush;
+	u8 rsvd0[3];
 };
 
 /******************** Port Beacon ***************************/
@@ -937,7 +990,7 @@
 extern int be_cmd_rxq_create(struct be_adapter *adapter,
 			struct be_queue_info *rxq, u16 cq_id,
 			u16 frag_size, u16 max_frame_size, u32 if_id,
-			u32 rss);
+			u32 rss, u8 *rss_id);
 extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
 			int type);
 extern int be_cmd_link_status_query(struct be_adapter *adapter,
@@ -960,8 +1013,10 @@
 extern int be_cmd_get_flow_control(struct be_adapter *adapter,
 			u32 *tx_fc, u32 *rx_fc);
 extern int be_cmd_query_fw_cfg(struct be_adapter *adapter,
-			u32 *port_num, u32 *cap);
+			u32 *port_num, u32 *function_mode, u32 *function_caps);
 extern int be_cmd_reset_function(struct be_adapter *adapter);
+extern int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
+			u16 table_size);
 extern int be_process_mcc(struct be_adapter *adapter, int *status);
 extern int be_cmd_set_beacon_state(struct be_adapter *adapter,
 			u8 port_num, u8 beacon, u8 status, u8 state);
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index 13f0abb..0f46366 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -26,14 +26,16 @@
 	int offset;
 };
 
-enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT, ERXSTAT};
+enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT};
 #define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
 					offsetof(_struct, field)
 #define NETSTAT_INFO(field) 	#field, NETSTAT,\
 					FIELDINFO(struct net_device_stats,\
 						field)
-#define DRVSTAT_INFO(field) 	#field, DRVSTAT,\
-					FIELDINFO(struct be_drvr_stats, field)
+#define DRVSTAT_TX_INFO(field)	#field, DRVSTAT_TX,\
+					FIELDINFO(struct be_tx_stats, field)
+#define DRVSTAT_RX_INFO(field)	#field, DRVSTAT_RX,\
+					FIELDINFO(struct be_rx_stats, field)
 #define MISCSTAT_INFO(field) 	#field, MISCSTAT,\
 					FIELDINFO(struct be_rxf_stats, field)
 #define PORTSTAT_INFO(field) 	#field, PORTSTAT,\
@@ -51,21 +53,12 @@
 	{NETSTAT_INFO(tx_errors)},
 	{NETSTAT_INFO(rx_dropped)},
 	{NETSTAT_INFO(tx_dropped)},
-	{DRVSTAT_INFO(be_tx_reqs)},
-	{DRVSTAT_INFO(be_tx_stops)},
-	{DRVSTAT_INFO(be_fwd_reqs)},
-	{DRVSTAT_INFO(be_tx_wrbs)},
-	{DRVSTAT_INFO(be_rx_polls)},
-	{DRVSTAT_INFO(be_tx_events)},
-	{DRVSTAT_INFO(be_rx_events)},
-	{DRVSTAT_INFO(be_tx_compl)},
-	{DRVSTAT_INFO(be_rx_compl)},
-	{DRVSTAT_INFO(be_rx_mcast_pkt)},
-	{DRVSTAT_INFO(be_ethrx_post_fail)},
-	{DRVSTAT_INFO(be_802_3_dropped_frames)},
-	{DRVSTAT_INFO(be_802_3_malformed_frames)},
-	{DRVSTAT_INFO(be_tx_rate)},
-	{DRVSTAT_INFO(be_rx_rate)},
+	{DRVSTAT_TX_INFO(be_tx_rate)},
+	{DRVSTAT_TX_INFO(be_tx_reqs)},
+	{DRVSTAT_TX_INFO(be_tx_wrbs)},
+	{DRVSTAT_TX_INFO(be_tx_stops)},
+	{DRVSTAT_TX_INFO(be_tx_events)},
+	{DRVSTAT_TX_INFO(be_tx_compl)},
 	{PORTSTAT_INFO(rx_unicast_frames)},
 	{PORTSTAT_INFO(rx_multicast_frames)},
 	{PORTSTAT_INFO(rx_broadcast_frames)},
@@ -91,6 +84,9 @@
 	{PORTSTAT_INFO(rx_non_rss_packets)},
 	{PORTSTAT_INFO(rx_ipv4_packets)},
 	{PORTSTAT_INFO(rx_ipv6_packets)},
+	{PORTSTAT_INFO(rx_switched_unicast_packets)},
+	{PORTSTAT_INFO(rx_switched_multicast_packets)},
+	{PORTSTAT_INFO(rx_switched_broadcast_packets)},
 	{PORTSTAT_INFO(tx_unicastframes)},
 	{PORTSTAT_INFO(tx_multicastframes)},
 	{PORTSTAT_INFO(tx_broadcastframes)},
@@ -103,11 +99,24 @@
 	{MISCSTAT_INFO(rx_drops_too_many_frags)},
 	{MISCSTAT_INFO(rx_drops_invalid_ring)},
 	{MISCSTAT_INFO(forwarded_packets)},
-	{MISCSTAT_INFO(rx_drops_mtu)},
-	{ERXSTAT_INFO(rx_drops_no_fragments)},
+	{MISCSTAT_INFO(rx_drops_mtu)}
 };
 #define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
 
+/* Stats related to multi RX queues */
+static const struct be_ethtool_stat et_rx_stats[] = {
+	{DRVSTAT_RX_INFO(rx_bytes)},
+	{DRVSTAT_RX_INFO(rx_pkts)},
+	{DRVSTAT_RX_INFO(rx_rate)},
+	{DRVSTAT_RX_INFO(rx_polls)},
+	{DRVSTAT_RX_INFO(rx_events)},
+	{DRVSTAT_RX_INFO(rx_compl)},
+	{DRVSTAT_RX_INFO(rx_mcast_pkts)},
+	{DRVSTAT_RX_INFO(rx_post_fail)},
+	{ERXSTAT_INFO(rx_drops_no_fragments)}
+};
+#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
+
 static const char et_self_tests[][ETH_GSTRING_LEN] = {
 	"MAC Loopback test",
 	"PHY Loopback test",
@@ -140,7 +149,7 @@
 be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_eq_obj *rx_eq = &adapter->rx_eq;
+	struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq;
 	struct be_eq_obj *tx_eq = &adapter->tx_eq;
 
 	coalesce->rx_coalesce_usecs = rx_eq->cur_eqd;
@@ -164,25 +173,49 @@
 be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_eq_obj *rx_eq = &adapter->rx_eq;
+	struct be_rx_obj *rxo;
+	struct be_eq_obj *rx_eq;
 	struct be_eq_obj *tx_eq = &adapter->tx_eq;
 	u32 tx_max, tx_min, tx_cur;
 	u32 rx_max, rx_min, rx_cur;
-	int status = 0;
+	int status = 0, i;
 
 	if (coalesce->use_adaptive_tx_coalesce == 1)
 		return -EINVAL;
 
-	/* if AIC is being turned on now, start with an EQD of 0 */
-	if (rx_eq->enable_aic == 0 &&
-		coalesce->use_adaptive_rx_coalesce == 1) {
-		rx_eq->cur_eqd = 0;
-	}
-	rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
+	for_all_rx_queues(adapter, rxo, i) {
+		rx_eq = &rxo->rx_eq;
 
-	rx_max = coalesce->rx_coalesce_usecs_high;
-	rx_min = coalesce->rx_coalesce_usecs_low;
-	rx_cur = coalesce->rx_coalesce_usecs;
+		if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce)
+			rx_eq->cur_eqd = 0;
+		rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
+
+		rx_max = coalesce->rx_coalesce_usecs_high;
+		rx_min = coalesce->rx_coalesce_usecs_low;
+		rx_cur = coalesce->rx_coalesce_usecs;
+
+		if (rx_eq->enable_aic) {
+			if (rx_max > BE_MAX_EQD)
+				rx_max = BE_MAX_EQD;
+			if (rx_min > rx_max)
+				rx_min = rx_max;
+			rx_eq->max_eqd = rx_max;
+			rx_eq->min_eqd = rx_min;
+			if (rx_eq->cur_eqd > rx_max)
+				rx_eq->cur_eqd = rx_max;
+			if (rx_eq->cur_eqd < rx_min)
+				rx_eq->cur_eqd = rx_min;
+		} else {
+			if (rx_cur > BE_MAX_EQD)
+				rx_cur = BE_MAX_EQD;
+			if (rx_eq->cur_eqd != rx_cur) {
+				status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
+						rx_cur);
+				if (!status)
+					rx_eq->cur_eqd = rx_cur;
+			}
+		}
+	}
 
 	tx_max = coalesce->tx_coalesce_usecs_high;
 	tx_min = coalesce->tx_coalesce_usecs_low;
@@ -196,27 +229,6 @@
 			tx_eq->cur_eqd = tx_cur;
 	}
 
-	if (rx_eq->enable_aic) {
-		if (rx_max > BE_MAX_EQD)
-			rx_max = BE_MAX_EQD;
-		if (rx_min > rx_max)
-			rx_min = rx_max;
-		rx_eq->max_eqd = rx_max;
-		rx_eq->min_eqd = rx_min;
-		if (rx_eq->cur_eqd > rx_max)
-			rx_eq->cur_eqd = rx_max;
-		if (rx_eq->cur_eqd < rx_min)
-			rx_eq->cur_eqd = rx_min;
-	} else {
-		if (rx_cur > BE_MAX_EQD)
-			rx_cur = BE_MAX_EQD;
-		if (rx_eq->cur_eqd != rx_cur) {
-			status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
-					rx_cur);
-			if (!status)
-				rx_eq->cur_eqd = rx_cur;
-		}
-	}
 	return 0;
 }
 
@@ -244,32 +256,25 @@
 		struct ethtool_stats *stats, uint64_t *data)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_drvr_stats *drvr_stats = &adapter->stats.drvr_stats;
-	struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va);
-	struct be_rxf_stats *rxf_stats = &hw_stats->rxf;
-	struct be_port_rxf_stats *port_stats =
-			&rxf_stats->port[adapter->port_num];
-	struct net_device_stats *net_stats = &netdev->stats;
+	struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats_cmd.va);
 	struct be_erx_stats *erx_stats = &hw_stats->erx;
+	struct be_rx_obj *rxo;
 	void *p = NULL;
-	int i;
+	int i, j;
 
 	for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
 		switch (et_stats[i].type) {
 		case NETSTAT:
-			p = net_stats;
+			p = &netdev->stats;
 			break;
-		case DRVSTAT:
-			p = drvr_stats;
+		case DRVSTAT_TX:
+			p = &adapter->tx_stats;
 			break;
 		case PORTSTAT:
-			p = port_stats;
+			p = &hw_stats->rxf.port[adapter->port_num];
 			break;
 		case MISCSTAT:
-			p = rxf_stats;
-			break;
-		case ERXSTAT: /* Currently only one ERX stat is provided */
-			p = (u32 *)erx_stats + adapter->rx_obj.q.id;
+			p = &hw_stats->rxf;
 			break;
 		}
 
@@ -277,19 +282,44 @@
 		data[i] = (et_stats[i].size == sizeof(u64)) ?
 				*(u64 *)p: *(u32 *)p;
 	}
+
+	for_all_rx_queues(adapter, rxo, j) {
+		for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) {
+			switch (et_rx_stats[i].type) {
+			case DRVSTAT_RX:
+				p = (u8 *)&rxo->stats + et_rx_stats[i].offset;
+				break;
+			case ERXSTAT:
+				p = (u32 *)erx_stats + rxo->q.id;
+				break;
+			}
+			data[ETHTOOL_STATS_NUM + j * ETHTOOL_RXSTATS_NUM + i] =
+				(et_rx_stats[i].size == sizeof(u64)) ?
+					*(u64 *)p: *(u32 *)p;
+		}
+	}
 }
 
 static void
 be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
 		uint8_t *data)
 {
-	int i;
+	struct be_adapter *adapter = netdev_priv(netdev);
+	int i, j;
+
 	switch (stringset) {
 	case ETH_SS_STATS:
 		for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
 			memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN);
 			data += ETH_GSTRING_LEN;
 		}
+		for (i = 0; i < adapter->num_rx_qs; i++) {
+			for (j = 0; j < ETHTOOL_RXSTATS_NUM; j++) {
+				sprintf(data, "rxq%d: %s", i,
+					et_rx_stats[j].desc);
+				data += ETH_GSTRING_LEN;
+			}
+		}
 		break;
 	case ETH_SS_TEST:
 		for (i = 0; i < ETHTOOL_TESTS_NUM; i++) {
@@ -302,11 +332,14 @@
 
 static int be_get_sset_count(struct net_device *netdev, int stringset)
 {
+	struct be_adapter *adapter = netdev_priv(netdev);
+
 	switch (stringset) {
 	case ETH_SS_TEST:
 		return ETHTOOL_TESTS_NUM;
 	case ETH_SS_STATS:
-		return ETHTOOL_STATS_NUM;
+		return ETHTOOL_STATS_NUM +
+			adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
 	default:
 		return -EINVAL;
 	}
@@ -421,10 +454,10 @@
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
 
-	ring->rx_max_pending = adapter->rx_obj.q.len;
+	ring->rx_max_pending = adapter->rx_obj[0].q.len;
 	ring->tx_max_pending = adapter->tx_obj.q.len;
 
-	ring->rx_pending = atomic_read(&adapter->rx_obj.q.used);
+	ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used);
 	ring->tx_pending = atomic_read(&adapter->tx_obj.q.used);
 }
 
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 6eda7a0..45b1f66 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -32,6 +32,10 @@
 MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
 MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize");
 
+static bool multi_rxq = true;
+module_param(multi_rxq, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(multi_rxq, "Multi Rx Queue support. Enabled by default");
+
 static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
@@ -111,6 +115,11 @@
 	"Unknown"
 };
 
+static inline bool be_multi_rxq(struct be_adapter *adapter)
+{
+	return (adapter->num_rx_qs > 1);
+}
+
 static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q)
 {
 	struct be_dma_mem *mem = &q->dma_mem;
@@ -236,18 +245,27 @@
 
 void netdev_stats_update(struct be_adapter *adapter)
 {
-	struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va);
+	struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats_cmd.va);
 	struct be_rxf_stats *rxf_stats = &hw_stats->rxf;
 	struct be_port_rxf_stats *port_stats =
 			&rxf_stats->port[adapter->port_num];
 	struct net_device_stats *dev_stats = &adapter->netdev->stats;
 	struct be_erx_stats *erx_stats = &hw_stats->erx;
+	struct be_rx_obj *rxo;
+	int i;
 
-	dev_stats->rx_packets = drvr_stats(adapter)->be_rx_pkts;
-	dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts;
-	dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes;
-	dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes;
-	dev_stats->multicast = drvr_stats(adapter)->be_rx_mcast_pkt;
+	memset(dev_stats, 0, sizeof(*dev_stats));
+	for_all_rx_queues(adapter, rxo, i) {
+		dev_stats->rx_packets += rx_stats(rxo)->rx_pkts;
+		dev_stats->rx_bytes += rx_stats(rxo)->rx_bytes;
+		dev_stats->multicast += rx_stats(rxo)->rx_mcast_pkts;
+		/*  no space in linux buffers: best possible approximation */
+		dev_stats->rx_dropped +=
+			erx_stats->rx_drops_no_fragments[rxo->q.id];
+	}
+
+	dev_stats->tx_packets = tx_stats(adapter)->be_tx_pkts;
+	dev_stats->tx_bytes = tx_stats(adapter)->be_tx_bytes;
 
 	/* bad pkts received */
 	dev_stats->rx_errors = port_stats->rx_crc_errors +
@@ -264,18 +282,11 @@
 		port_stats->rx_ip_checksum_errs +
 		port_stats->rx_udp_checksum_errs;
 
-	/*  no space in linux buffers: best possible approximation */
-	dev_stats->rx_dropped =
-		erx_stats->rx_drops_no_fragments[adapter->rx_obj.q.id];
-
 	/* detailed rx errors */
 	dev_stats->rx_length_errors = port_stats->rx_in_range_errors +
 		port_stats->rx_out_range_errors +
 		port_stats->rx_frame_too_long;
 
-	/* receive ring buffer overflow */
-	dev_stats->rx_over_errors = 0;
-
 	dev_stats->rx_crc_errors = port_stats->rx_crc_errors;
 
 	/* frame alignment errors */
@@ -286,23 +297,6 @@
 	dev_stats->rx_fifo_errors = port_stats->rx_fifo_overflow +
 					port_stats->rx_input_fifo_overflow +
 					rxf_stats->rx_drops_no_pbuf;
-	/* receiver missed packetd */
-	dev_stats->rx_missed_errors = 0;
-
-	/*  packet transmit problems */
-	dev_stats->tx_errors = 0;
-
-	/* no space available in linux */
-	dev_stats->tx_dropped = 0;
-
-	dev_stats->collisions = 0;
-
-	/* detailed tx_errors */
-	dev_stats->tx_aborted_errors = 0;
-	dev_stats->tx_carrier_errors = 0;
-	dev_stats->tx_fifo_errors = 0;
-	dev_stats->tx_heartbeat_errors = 0;
-	dev_stats->tx_window_errors = 0;
 }
 
 void be_link_status_update(struct be_adapter *adapter, bool link_up)
@@ -326,10 +320,10 @@
 }
 
 /* Update the EQ delay n BE based on the RX frags consumed / sec */
-static void be_rx_eqd_update(struct be_adapter *adapter)
+static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo)
 {
-	struct be_eq_obj *rx_eq = &adapter->rx_eq;
-	struct be_drvr_stats *stats = &adapter->stats.drvr_stats;
+	struct be_eq_obj *rx_eq = &rxo->rx_eq;
+	struct be_rx_stats *stats = &rxo->stats;
 	ulong now = jiffies;
 	u32 eqd;
 
@@ -346,12 +340,12 @@
 	if ((now - stats->rx_fps_jiffies) < HZ)
 		return;
 
-	stats->be_rx_fps = (stats->be_rx_frags - stats->be_prev_rx_frags) /
+	stats->rx_fps = (stats->rx_frags - stats->prev_rx_frags) /
 			((now - stats->rx_fps_jiffies) / HZ);
 
 	stats->rx_fps_jiffies = now;
-	stats->be_prev_rx_frags = stats->be_rx_frags;
-	eqd = stats->be_rx_fps / 110000;
+	stats->prev_rx_frags = stats->rx_frags;
+	eqd = stats->rx_fps / 110000;
 	eqd = eqd << 3;
 	if (eqd > rx_eq->max_eqd)
 		eqd = rx_eq->max_eqd;
@@ -365,11 +359,6 @@
 	rx_eq->cur_eqd = eqd;
 }
 
-static struct net_device_stats *be_get_stats(struct net_device *dev)
-{
-	return &dev->stats;
-}
-
 static u32 be_calc_rate(u64 bytes, unsigned long ticks)
 {
 	u64 rate = bytes;
@@ -383,7 +372,7 @@
 
 static void be_tx_rate_update(struct be_adapter *adapter)
 {
-	struct be_drvr_stats *stats = drvr_stats(adapter);
+	struct be_tx_stats *stats = tx_stats(adapter);
 	ulong now = jiffies;
 
 	/* Wrapped around? */
@@ -405,7 +394,7 @@
 static void be_tx_stats_update(struct be_adapter *adapter,
 			u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped)
 {
-	struct be_drvr_stats *stats = drvr_stats(adapter);
+	struct be_tx_stats *stats = tx_stats(adapter);
 	stats->be_tx_reqs++;
 	stats->be_tx_wrbs += wrb_cnt;
 	stats->be_tx_bytes += copied;
@@ -440,9 +429,12 @@
 	wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK;
 }
 
-static void wrb_fill_hdr(struct be_eth_hdr_wrb *hdr, struct sk_buff *skb,
-		bool vlan, u32 wrb_cnt, u32 len)
+static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
+		struct sk_buff *skb, u32 wrb_cnt, u32 len)
 {
+	u8 vlan_prio = 0;
+	u16 vlan_tag = 0;
+
 	memset(hdr, 0, sizeof(*hdr));
 
 	AMAP_SET_BITS(struct amap_eth_hdr_wrb, crc, hdr, 1);
@@ -460,10 +452,15 @@
 			AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1);
 	}
 
-	if (vlan && vlan_tx_tag_present(skb)) {
+	if (adapter->vlan_grp && vlan_tx_tag_present(skb)) {
 		AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1);
-		AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag,
-			hdr, vlan_tx_tag_get(skb));
+		vlan_tag = vlan_tx_tag_get(skb);
+		vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+		/* If vlan priority provided by OS is NOT in available bmap */
+		if (!(adapter->vlan_prio_bmap & (1 << vlan_prio)))
+			vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) |
+					adapter->recommended_prio;
+		AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, hdr, vlan_tag);
 	}
 
 	AMAP_SET_BITS(struct amap_eth_hdr_wrb, event, hdr, 1);
@@ -543,8 +540,7 @@
 		queue_head_inc(txq);
 	}
 
-	wrb_fill_hdr(hdr, first_skb, adapter->vlan_grp ? true : false,
-		wrb_cnt, copied);
+	wrb_fill_hdr(adapter, hdr, first_skb, wrb_cnt, copied);
 	be_dws_cpu_to_le(hdr, sizeof(*hdr));
 
 	return copied;
@@ -637,7 +633,7 @@
 
 	if (adapter->vlans_added <= adapter->max_vlans)  {
 		/* Construct VLAN Table to give to HW */
-		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		for (i = 0; i < VLAN_N_VID; i++) {
 			if (adapter->vlan_tag[i]) {
 				vtag[ntags] = cpu_to_le16(i);
 				ntags++;
@@ -656,14 +652,8 @@
 static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_eq_obj *rx_eq = &adapter->rx_eq;
-	struct be_eq_obj *tx_eq = &adapter->tx_eq;
 
-	be_eq_notify(adapter, rx_eq->q.id, false, false, 0);
-	be_eq_notify(adapter, tx_eq->q.id, false, false, 0);
 	adapter->vlan_grp = grp;
-	be_eq_notify(adapter, rx_eq->q.id, true, false, 0);
-	be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
 }
 
 static void be_vlan_add_vid(struct net_device *netdev, u16 vid)
@@ -825,40 +815,38 @@
 	return status;
 }
 
-static void be_rx_rate_update(struct be_adapter *adapter)
+static void be_rx_rate_update(struct be_rx_obj *rxo)
 {
-	struct be_drvr_stats *stats = drvr_stats(adapter);
+	struct be_rx_stats *stats = &rxo->stats;
 	ulong now = jiffies;
 
 	/* Wrapped around */
-	if (time_before(now, stats->be_rx_jiffies)) {
-		stats->be_rx_jiffies = now;
+	if (time_before(now, stats->rx_jiffies)) {
+		stats->rx_jiffies = now;
 		return;
 	}
 
 	/* Update the rate once in two seconds */
-	if ((now - stats->be_rx_jiffies) < 2 * HZ)
+	if ((now - stats->rx_jiffies) < 2 * HZ)
 		return;
 
-	stats->be_rx_rate = be_calc_rate(stats->be_rx_bytes
-					  - stats->be_rx_bytes_prev,
-					 now - stats->be_rx_jiffies);
-	stats->be_rx_jiffies = now;
-	stats->be_rx_bytes_prev = stats->be_rx_bytes;
+	stats->rx_rate = be_calc_rate(stats->rx_bytes - stats->rx_bytes_prev,
+				now - stats->rx_jiffies);
+	stats->rx_jiffies = now;
+	stats->rx_bytes_prev = stats->rx_bytes;
 }
 
-static void be_rx_stats_update(struct be_adapter *adapter,
+static void be_rx_stats_update(struct be_rx_obj *rxo,
 		u32 pktsize, u16 numfrags, u8 pkt_type)
 {
-	struct be_drvr_stats *stats = drvr_stats(adapter);
+	struct be_rx_stats *stats = &rxo->stats;
 
-	stats->be_rx_compl++;
-	stats->be_rx_frags += numfrags;
-	stats->be_rx_bytes += pktsize;
-	stats->be_rx_pkts++;
-
+	stats->rx_compl++;
+	stats->rx_frags += numfrags;
+	stats->rx_bytes += pktsize;
+	stats->rx_pkts++;
 	if (pkt_type == BE_MULTICAST_PACKET)
-		stats->be_rx_mcast_pkt++;
+		stats->rx_mcast_pkts++;
 }
 
 static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso)
@@ -878,12 +866,14 @@
 }
 
 static struct be_rx_page_info *
-get_rx_page_info(struct be_adapter *adapter, u16 frag_idx)
+get_rx_page_info(struct be_adapter *adapter,
+		struct be_rx_obj *rxo,
+		u16 frag_idx)
 {
 	struct be_rx_page_info *rx_page_info;
-	struct be_queue_info *rxq = &adapter->rx_obj.q;
+	struct be_queue_info *rxq = &rxo->q;
 
-	rx_page_info = &adapter->rx_obj.page_info_tbl[frag_idx];
+	rx_page_info = &rxo->page_info_tbl[frag_idx];
 	BUG_ON(!rx_page_info->page);
 
 	if (rx_page_info->last_page_user) {
@@ -898,9 +888,10 @@
 
 /* Throwaway the data in the Rx completion */
 static void be_rx_compl_discard(struct be_adapter *adapter,
-			struct be_eth_rx_compl *rxcp)
+		struct be_rx_obj *rxo,
+		struct be_eth_rx_compl *rxcp)
 {
-	struct be_queue_info *rxq = &adapter->rx_obj.q;
+	struct be_queue_info *rxq = &rxo->q;
 	struct be_rx_page_info *page_info;
 	u16 rxq_idx, i, num_rcvd;
 
@@ -908,7 +899,7 @@
 	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
 
 	for (i = 0; i < num_rcvd; i++) {
-		page_info = get_rx_page_info(adapter, rxq_idx);
+		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);
@@ -919,11 +910,11 @@
  * skb_fill_rx_data forms a complete skb for an ether frame
  * indicated by rxcp.
  */
-static void skb_fill_rx_data(struct be_adapter *adapter,
+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 be_queue_info *rxq = &adapter->rx_obj.q;
+	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;
@@ -934,7 +925,7 @@
 	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, rxq_idx);
+	page_info = get_rx_page_info(adapter, rxo, rxq_idx);
 
 	start = page_address(page_info->page) + page_info->page_offset;
 	prefetch(start);
@@ -972,7 +963,7 @@
 	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, rxq_idx);
+		page_info = get_rx_page_info(adapter, rxo, rxq_idx);
 
 		curr_frag_len = min(size, rx_frag_size);
 
@@ -998,11 +989,12 @@
 	BUG_ON(j > MAX_SKB_FRAGS);
 
 done:
-	be_rx_stats_update(adapter, pktsize, num_rcvd, pkt_type);
+	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 sk_buff *skb;
@@ -1019,14 +1011,14 @@
 	if (unlikely(!skb)) {
 		if (net_ratelimit())
 			dev_warn(&adapter->pdev->dev, "skb alloc failed\n");
-		be_rx_compl_discard(adapter, rxcp);
+		be_rx_compl_discard(adapter, rxo, rxcp);
 		return;
 	}
 
-	skb_fill_rx_data(adapter, skb, rxcp, num_rcvd);
+	skb_fill_rx_data(adapter, rxo, skb, rxcp, num_rcvd);
 
 	if (do_pkt_csum(rxcp, adapter->rx_csum))
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 	else
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
@@ -1056,12 +1048,13 @@
 
 /* Process the RX completion indicated by rxcp when GRO is enabled */
 static void be_rx_compl_process_gro(struct be_adapter *adapter,
-			struct be_eth_rx_compl *rxcp)
+		struct be_rx_obj *rxo,
+		struct be_eth_rx_compl *rxcp)
 {
 	struct be_rx_page_info *page_info;
 	struct sk_buff *skb = NULL;
-	struct be_queue_info *rxq = &adapter->rx_obj.q;
-	struct be_eq_obj *eq_obj =  &adapter->rx_eq;
+	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;
@@ -1085,13 +1078,13 @@
 
 	skb = napi_get_frags(&eq_obj->napi);
 	if (!skb) {
-		be_rx_compl_discard(adapter, rxcp);
+		be_rx_compl_discard(adapter, rxo, rxcp);
 		return;
 	}
 
 	remaining = pkt_size;
 	for (i = 0, j = -1; i < num_rcvd; i++) {
-		page_info = get_rx_page_info(adapter, rxq_idx);
+		page_info = get_rx_page_info(adapter, rxo, rxq_idx);
 
 		curr_frag_len = min(remaining, rx_frag_size);
 
@@ -1132,12 +1125,12 @@
 		vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid);
 	}
 
-	be_rx_stats_update(adapter, pkt_size, num_rcvd, pkt_type);
+	be_rx_stats_update(rxo, pkt_size, num_rcvd, pkt_type);
 }
 
-static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter)
+static struct be_eth_rx_compl *be_rx_compl_get(struct be_rx_obj *rxo)
 {
-	struct be_eth_rx_compl *rxcp = queue_tail_node(&adapter->rx_obj.cq);
+	struct be_eth_rx_compl *rxcp = queue_tail_node(&rxo->cq);
 
 	if (rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] == 0)
 		return NULL;
@@ -1145,7 +1138,7 @@
 	rmb();
 	be_dws_le_to_cpu(rxcp, sizeof(*rxcp));
 
-	queue_tail_inc(&adapter->rx_obj.cq);
+	queue_tail_inc(&rxo->cq);
 	return rxcp;
 }
 
@@ -1171,22 +1164,23 @@
  * 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_adapter *adapter)
+static void be_post_rx_frags(struct be_rx_obj *rxo)
 {
-	struct be_rx_page_info *page_info_tbl = adapter->rx_obj.page_info_tbl;
+	struct be_adapter *adapter = rxo->adapter;
+	struct be_rx_page_info *page_info_tbl = rxo->page_info_tbl;
 	struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL;
-	struct be_queue_info *rxq = &adapter->rx_obj.q;
+	struct be_queue_info *rxq = &rxo->q;
 	struct page *pagep = NULL;
 	struct be_eth_rx_d *rxd;
 	u64 page_dmaaddr = 0, frag_dmaaddr;
 	u32 posted, page_offset = 0;
 
-	page_info = &page_info_tbl[rxq->head];
+	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);
 			if (unlikely(!pagep)) {
-				drvr_stats(adapter)->be_ethrx_post_fail++;
+				rxo->stats.rx_post_fail++;
 				break;
 			}
 			page_dmaaddr = pci_map_page(adapter->pdev, pagep, 0,
@@ -1225,7 +1219,7 @@
 		be_rxq_notify(adapter, rxq->id, posted);
 	} else if (atomic_read(&rxq->used) == 0) {
 		/* Let be_worker replenish when memory is available */
-		adapter->rx_post_starved = true;
+		rxo->rx_post_starved = true;
 	}
 }
 
@@ -1328,17 +1322,17 @@
 		be_eq_notify(adapter, eq_obj->q.id, false, true, num);
 }
 
-static void be_rx_q_clean(struct be_adapter *adapter)
+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 = &adapter->rx_obj.q;
-	struct be_queue_info *rx_cq = &adapter->rx_obj.cq;
+	struct be_queue_info *rxq = &rxo->q;
+	struct be_queue_info *rx_cq = &rxo->cq;
 	struct be_eth_rx_compl *rxcp;
 	u16 tail;
 
 	/* First cleanup pending rx completions */
-	while ((rxcp = be_rx_compl_get(adapter)) != NULL) {
-		be_rx_compl_discard(adapter, rxcp);
+	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, true, 1);
 	}
@@ -1346,7 +1340,7 @@
 	/* Then free posted rx buffer that were not used */
 	tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len;
 	for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) {
-		page_info = get_rx_page_info(adapter, tail);
+		page_info = get_rx_page_info(adapter, rxo, tail);
 		put_page(page_info->page);
 		memset(page_info, 0, sizeof(*page_info));
 	}
@@ -1524,92 +1518,101 @@
 static void be_rx_queues_destroy(struct be_adapter *adapter)
 {
 	struct be_queue_info *q;
+	struct be_rx_obj *rxo;
+	int i;
 
-	q = &adapter->rx_obj.q;
-	if (q->created) {
-		be_cmd_q_destroy(adapter, q, QTYPE_RXQ);
+	for_all_rx_queues(adapter, rxo, i) {
+		q = &rxo->q;
+		if (q->created) {
+			be_cmd_q_destroy(adapter, q, QTYPE_RXQ);
+			/* After the rxq is invalidated, wait for a grace time
+			 * of 1ms for all dma to end and the flush compl to
+			 * arrive
+			 */
+			mdelay(1);
+			be_rx_q_clean(adapter, rxo);
+		}
+		be_queue_free(adapter, q);
 
-		/* After the rxq is invalidated, wait for a grace time
-		 * of 1ms for all dma to end and the flush compl to arrive
-		 */
-		mdelay(1);
-		be_rx_q_clean(adapter);
+		q = &rxo->cq;
+		if (q->created)
+			be_cmd_q_destroy(adapter, q, QTYPE_CQ);
+		be_queue_free(adapter, q);
+
+		/* Clear any residual events */
+		q = &rxo->rx_eq.q;
+		if (q->created) {
+			be_eq_clean(adapter, &rxo->rx_eq);
+			be_cmd_q_destroy(adapter, q, QTYPE_EQ);
+		}
+		be_queue_free(adapter, q);
 	}
-	be_queue_free(adapter, q);
-
-	q = &adapter->rx_obj.cq;
-	if (q->created)
-		be_cmd_q_destroy(adapter, q, QTYPE_CQ);
-	be_queue_free(adapter, q);
-
-	/* Clear any residual events */
-	be_eq_clean(adapter, &adapter->rx_eq);
-
-	q = &adapter->rx_eq.q;
-	if (q->created)
-		be_cmd_q_destroy(adapter, q, QTYPE_EQ);
-	be_queue_free(adapter, q);
 }
 
 static int be_rx_queues_create(struct be_adapter *adapter)
 {
 	struct be_queue_info *eq, *q, *cq;
-	int rc;
+	struct be_rx_obj *rxo;
+	int rc, i;
 
 	adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
-	adapter->rx_eq.max_eqd = BE_MAX_EQD;
-	adapter->rx_eq.min_eqd = 0;
-	adapter->rx_eq.cur_eqd = 0;
-	adapter->rx_eq.enable_aic = true;
+	for_all_rx_queues(adapter, rxo, i) {
+		rxo->adapter = adapter;
+		rxo->rx_eq.max_eqd = BE_MAX_EQD;
+		rxo->rx_eq.enable_aic = true;
 
-	/* Alloc Rx Event queue */
-	eq = &adapter->rx_eq.q;
-	rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN,
-				sizeof(struct be_eq_entry));
-	if (rc)
-		return rc;
+		/* EQ */
+		eq = &rxo->rx_eq.q;
+		rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN,
+					sizeof(struct be_eq_entry));
+		if (rc)
+			goto err;
 
-	/* Ask BE to create Rx Event queue */
-	rc = be_cmd_eq_create(adapter, eq, adapter->rx_eq.cur_eqd);
-	if (rc)
-		goto rx_eq_free;
+		rc = be_cmd_eq_create(adapter, eq, rxo->rx_eq.cur_eqd);
+		if (rc)
+			goto err;
 
-	/* Alloc RX eth compl queue */
-	cq = &adapter->rx_obj.cq;
-	rc = be_queue_alloc(adapter, cq, RX_CQ_LEN,
-			sizeof(struct be_eth_rx_compl));
-	if (rc)
-		goto rx_eq_destroy;
+		/* CQ */
+		cq = &rxo->cq;
+		rc = be_queue_alloc(adapter, cq, RX_CQ_LEN,
+				sizeof(struct be_eth_rx_compl));
+		if (rc)
+			goto err;
 
-	/* Ask BE to create Rx eth compl queue */
-	rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
-	if (rc)
-		goto rx_cq_free;
+		rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
+		if (rc)
+			goto err;
 
-	/* Alloc RX eth queue */
-	q = &adapter->rx_obj.q;
-	rc = be_queue_alloc(adapter, q, RX_Q_LEN, sizeof(struct be_eth_rx_d));
-	if (rc)
-		goto rx_cq_destroy;
+		/* Rx Q */
+		q = &rxo->q;
+		rc = be_queue_alloc(adapter, q, RX_Q_LEN,
+				sizeof(struct be_eth_rx_d));
+		if (rc)
+			goto err;
 
-	/* Ask BE to create Rx eth queue */
-	rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size,
-		BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle, false);
-	if (rc)
-		goto rx_q_free;
+		rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size,
+			BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle,
+			(i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id);
+		if (rc)
+			goto err;
+	}
+
+	if (be_multi_rxq(adapter)) {
+		u8 rsstable[MAX_RSS_QS];
+
+		for_all_rss_queues(adapter, rxo, i)
+			rsstable[i] = rxo->rss_id;
+
+		rc = be_cmd_rss_config(adapter, rsstable,
+			adapter->num_rx_qs - 1);
+		if (rc)
+			goto err;
+	}
 
 	return 0;
-rx_q_free:
-	be_queue_free(adapter, q);
-rx_cq_destroy:
-	be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
-rx_cq_free:
-	be_queue_free(adapter, cq);
-rx_eq_destroy:
-	be_cmd_q_destroy(adapter, eq, QTYPE_EQ);
-rx_eq_free:
-	be_queue_free(adapter, eq);
-	return rc;
+err:
+	be_rx_queues_destroy(adapter);
+	return -1;
 }
 
 /* There are 8 evt ids per func. Retruns the evt id's bit number */
@@ -1621,24 +1624,31 @@
 static irqreturn_t be_intx(int irq, void *dev)
 {
 	struct be_adapter *adapter = dev;
-	int isr;
+	struct be_rx_obj *rxo;
+	int isr, i;
 
 	isr = ioread32(adapter->csr + CEV_ISR0_OFFSET +
 		(adapter->tx_eq.q.id/ 8) * CEV_ISR_SIZE);
 	if (!isr)
 		return IRQ_NONE;
 
-	event_handle(adapter, &adapter->tx_eq);
-	event_handle(adapter, &adapter->rx_eq);
+	if ((1 << be_evt_bit_get(adapter, adapter->tx_eq.q.id) & isr))
+		event_handle(adapter, &adapter->tx_eq);
+
+	for_all_rx_queues(adapter, rxo, i) {
+		if ((1 << be_evt_bit_get(adapter, rxo->rx_eq.q.id) & isr))
+			event_handle(adapter, &rxo->rx_eq);
+	}
 
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t be_msix_rx(int irq, void *dev)
 {
-	struct be_adapter *adapter = dev;
+	struct be_rx_obj *rxo = dev;
+	struct be_adapter *adapter = rxo->adapter;
 
-	event_handle(adapter, &adapter->rx_eq);
+	event_handle(adapter, &rxo->rx_eq);
 
 	return IRQ_HANDLED;
 }
@@ -1652,14 +1662,14 @@
 	return IRQ_HANDLED;
 }
 
-static inline bool do_gro(struct be_adapter *adapter,
+static inline bool do_gro(struct be_adapter *adapter, struct be_rx_obj *rxo,
 			struct be_eth_rx_compl *rxcp)
 {
 	int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp);
 	int tcp_frame = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp);
 
 	if (err)
-		drvr_stats(adapter)->be_rxcp_err++;
+		rxo->stats.rxcp_err++;
 
 	return (tcp_frame && !err) ? true : false;
 }
@@ -1667,29 +1677,29 @@
 int be_poll_rx(struct napi_struct *napi, int budget)
 {
 	struct be_eq_obj *rx_eq = container_of(napi, struct be_eq_obj, napi);
-	struct be_adapter *adapter =
-		container_of(rx_eq, struct be_adapter, rx_eq);
-	struct be_queue_info *rx_cq = &adapter->rx_obj.cq;
+	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;
 	u32 work_done;
 
-	adapter->stats.drvr_stats.be_rx_polls++;
+	rxo->stats.rx_polls++;
 	for (work_done = 0; work_done < budget; work_done++) {
-		rxcp = be_rx_compl_get(adapter);
+		rxcp = be_rx_compl_get(rxo);
 		if (!rxcp)
 			break;
 
-		if (do_gro(adapter, rxcp))
-			be_rx_compl_process_gro(adapter, rxcp);
+		if (do_gro(adapter, rxo, rxcp))
+			be_rx_compl_process_gro(adapter, rxo, rxcp);
 		else
-			be_rx_compl_process(adapter, rxcp);
+			be_rx_compl_process(adapter, rxo, rxcp);
 
 		be_rx_compl_reset(rxcp);
 	}
 
 	/* Refill the queue */
-	if (atomic_read(&adapter->rx_obj.q.used) < RX_FRAGS_REFILL_WM)
-		be_post_rx_frags(adapter);
+	if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM)
+		be_post_rx_frags(rxo);
 
 	/* All consumed */
 	if (work_done < budget) {
@@ -1743,8 +1753,8 @@
 			netif_wake_queue(adapter->netdev);
 		}
 
-		drvr_stats(adapter)->be_tx_events++;
-		drvr_stats(adapter)->be_tx_compl += tx_compl;
+		tx_stats(adapter)->be_tx_events++;
+		tx_stats(adapter)->be_tx_compl += tx_compl;
 	}
 
 	return 1;
@@ -1793,20 +1803,24 @@
 {
 	struct be_adapter *adapter =
 		container_of(work, struct be_adapter, work.work);
+	struct be_rx_obj *rxo;
+	int i;
 
 	if (!adapter->stats_ioctl_sent)
-		be_cmd_get_stats(adapter, &adapter->stats.cmd);
-
-	/* Set EQ delay */
-	be_rx_eqd_update(adapter);
+		be_cmd_get_stats(adapter, &adapter->stats_cmd);
 
 	be_tx_rate_update(adapter);
-	be_rx_rate_update(adapter);
 
-	if (adapter->rx_post_starved) {
-		adapter->rx_post_starved = false;
-		be_post_rx_frags(adapter);
+	for_all_rx_queues(adapter, rxo, i) {
+		be_rx_rate_update(rxo);
+		be_rx_eqd_update(adapter, rxo);
+
+		if (rxo->rx_post_starved) {
+			rxo->rx_post_starved = false;
+			be_post_rx_frags(rxo);
+		}
 	}
+
 	if (!adapter->ue_detected)
 		be_detect_dump_ue(adapter);
 
@@ -1821,17 +1835,45 @@
 	}
 }
 
+static int be_num_rxqs_get(struct be_adapter *adapter)
+{
+	if (multi_rxq && (adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
+		!adapter->sriov_enabled && !(adapter->function_mode & 0x400)) {
+		return 1 + MAX_RSS_QS; /* one default non-RSS queue */
+	} else {
+		dev_warn(&adapter->pdev->dev,
+			"No support for multiple RX queues\n");
+		return 1;
+	}
+}
+
 static void be_msix_enable(struct be_adapter *adapter)
 {
+#define BE_MIN_MSIX_VECTORS	(1 + 1) /* Rx + Tx */
 	int i, status;
 
-	for (i = 0; i < BE_NUM_MSIX_VECTORS; i++)
+	adapter->num_rx_qs = be_num_rxqs_get(adapter);
+
+	for (i = 0; i < (adapter->num_rx_qs + 1); i++)
 		adapter->msix_entries[i].entry = i;
 
 	status = pci_enable_msix(adapter->pdev, adapter->msix_entries,
-		BE_NUM_MSIX_VECTORS);
-	if (status == 0)
-		adapter->msix_enabled = true;
+			adapter->num_rx_qs + 1);
+	if (status == 0) {
+		goto done;
+	} else if (status >= BE_MIN_MSIX_VECTORS) {
+		if (pci_enable_msix(adapter->pdev, adapter->msix_entries,
+				status) == 0) {
+			adapter->num_rx_qs = status - 1;
+			dev_warn(&adapter->pdev->dev,
+				"Could alloc only %d MSIx vectors. "
+				"Using %d RX Qs\n", status, adapter->num_rx_qs);
+			goto done;
+		}
+	}
+	return;
+done:
+	adapter->msix_enabled = true;
 }
 
 static void be_sriov_enable(struct be_adapter *adapter)
@@ -1865,38 +1907,50 @@
 
 static int be_request_irq(struct be_adapter *adapter,
 		struct be_eq_obj *eq_obj,
-		void *handler, char *desc)
+		void *handler, char *desc, void *context)
 {
 	struct net_device *netdev = adapter->netdev;
 	int vec;
 
 	sprintf(eq_obj->desc, "%s-%s", netdev->name, desc);
 	vec = be_msix_vec_get(adapter, eq_obj->q.id);
-	return request_irq(vec, handler, 0, eq_obj->desc, adapter);
+	return request_irq(vec, handler, 0, eq_obj->desc, context);
 }
 
-static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj)
+static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj,
+			void *context)
 {
 	int vec = be_msix_vec_get(adapter, eq_obj->q.id);
-	free_irq(vec, adapter);
+	free_irq(vec, context);
 }
 
 static int be_msix_register(struct be_adapter *adapter)
 {
-	int status;
+	struct be_rx_obj *rxo;
+	int status, i;
+	char qname[10];
 
-	status = be_request_irq(adapter, &adapter->tx_eq, be_msix_tx_mcc, "tx");
+	status = be_request_irq(adapter, &adapter->tx_eq, be_msix_tx_mcc, "tx",
+				adapter);
 	if (status)
 		goto err;
 
-	status = be_request_irq(adapter, &adapter->rx_eq, be_msix_rx, "rx");
-	if (status)
-		goto free_tx_irq;
+	for_all_rx_queues(adapter, rxo, i) {
+		sprintf(qname, "rxq%d", i);
+		status = be_request_irq(adapter, &rxo->rx_eq, be_msix_rx,
+				qname, rxo);
+		if (status)
+			goto err_msix;
+	}
 
 	return 0;
 
-free_tx_irq:
-	be_free_irq(adapter, &adapter->tx_eq);
+err_msix:
+	be_free_irq(adapter, &adapter->tx_eq, adapter);
+
+	for (i--, rxo = &adapter->rx_obj[i]; i >= 0; i--, rxo--)
+		be_free_irq(adapter, &rxo->rx_eq, rxo);
+
 err:
 	dev_warn(&adapter->pdev->dev,
 		"MSIX Request IRQ failed - err %d\n", status);
@@ -1936,6 +1990,8 @@
 static void be_irq_unregister(struct be_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
+	struct be_rx_obj *rxo;
+	int i;
 
 	if (!adapter->isr_registered)
 		return;
@@ -1947,8 +2003,11 @@
 	}
 
 	/* MSIx */
-	be_free_irq(adapter, &adapter->tx_eq);
-	be_free_irq(adapter, &adapter->rx_eq);
+	be_free_irq(adapter, &adapter->tx_eq, adapter);
+
+	for_all_rx_queues(adapter, rxo, i)
+		be_free_irq(adapter, &rxo->rx_eq, rxo);
+
 done:
 	adapter->isr_registered = false;
 }
@@ -1956,9 +2015,9 @@
 static int be_close(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_eq_obj *rx_eq = &adapter->rx_eq;
+	struct be_rx_obj *rxo;
 	struct be_eq_obj *tx_eq = &adapter->tx_eq;
-	int vec;
+	int vec, i;
 
 	cancel_delayed_work_sync(&adapter->work);
 
@@ -1973,14 +2032,19 @@
 	if (adapter->msix_enabled) {
 		vec = be_msix_vec_get(adapter, tx_eq->q.id);
 		synchronize_irq(vec);
-		vec = be_msix_vec_get(adapter, rx_eq->q.id);
-		synchronize_irq(vec);
+
+		for_all_rx_queues(adapter, rxo, i) {
+			vec = be_msix_vec_get(adapter, rxo->rx_eq.q.id);
+			synchronize_irq(vec);
+		}
 	} else {
 		synchronize_irq(netdev->irq);
 	}
 	be_irq_unregister(adapter);
 
-	napi_disable(&rx_eq->napi);
+	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
@@ -1994,17 +2058,17 @@
 static int be_open(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_eq_obj *rx_eq = &adapter->rx_eq;
 	struct be_eq_obj *tx_eq = &adapter->tx_eq;
+	struct be_rx_obj *rxo;
 	bool link_up;
-	int status;
+	int status, i;
 	u8 mac_speed;
 	u16 link_speed;
 
-	/* First time posting */
-	be_post_rx_frags(adapter);
-
-	napi_enable(&rx_eq->napi);
+	for_all_rx_queues(adapter, rxo, i) {
+		be_post_rx_frags(rxo);
+		napi_enable(&rxo->rx_eq.napi);
+	}
 	napi_enable(&tx_eq->napi);
 
 	be_irq_register(adapter);
@@ -2012,12 +2076,12 @@
 	be_intr_set(adapter, true);
 
 	/* The evt queues are created in unarmed state; arm them */
-	be_eq_notify(adapter, rx_eq->q.id, true, false, 0);
+	for_all_rx_queues(adapter, rxo, i) {
+		be_eq_notify(adapter, rxo->rx_eq.q.id, true, false, 0);
+		be_cq_notify(adapter, rxo->cq.id, true, 0);
+	}
 	be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
 
-	/* Rx compl queue may be in unarmed state; rearm it */
-	be_cq_notify(adapter, adapter->rx_obj.cq.id, true, 0);
-
 	/* Now that interrupts are on we can process async mcc */
 	be_async_mcc_enable(adapter);
 
@@ -2084,6 +2148,47 @@
 	return status;
 }
 
+/*
+ * Generate a seed MAC address from the PF MAC Address using jhash.
+ * MAC Address for VFs are assigned incrementally starting from the seed.
+ * These addresses are programmed in the ASIC by the PF and the VF driver
+ * queries for the MAC address during its probe.
+ */
+static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
+{
+	u32 vf = 0;
+	int status = 0;
+	u8 mac[ETH_ALEN];
+
+	be_vf_eth_addr_generate(adapter, mac);
+
+	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);
+		if (status)
+			dev_err(&adapter->pdev->dev,
+				"Mac address add failed for VF %d\n", vf);
+		else
+			memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN);
+
+		mac[5] += 1;
+	}
+	return status;
+}
+
+static inline void be_vf_eth_addr_rem(struct be_adapter *adapter)
+{
+	u32 vf;
+
+	for (vf = 0; vf < num_vfs; vf++) {
+		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);
+	}
+}
+
 static int be_setup(struct be_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -2098,6 +2203,11 @@
 				BE_IF_FLAGS_PROMISCUOUS |
 				BE_IF_FLAGS_PASS_L3L4_ERRORS;
 		en_flags |= BE_IF_FLAGS_PASS_L3L4_ERRORS;
+
+		if (be_multi_rxq(adapter)) {
+			cap_flags |= BE_IF_FLAGS_RSS;
+			en_flags |= BE_IF_FLAGS_RSS;
+		}
 	}
 
 	status = be_cmd_if_create(adapter, cap_flags, en_flags,
@@ -2143,10 +2253,20 @@
 	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:
@@ -2163,6 +2283,9 @@
 
 static int be_clear(struct be_adapter *adapter)
 {
+	if (be_physfn(adapter))
+		be_vf_eth_addr_rem(adapter);
+
 	be_mcc_queues_destroy(adapter);
 	be_rx_queues_destroy(adapter);
 	be_tx_queues_destroy(adapter);
@@ -2390,7 +2513,6 @@
 	.ndo_open		= be_open,
 	.ndo_stop		= be_close,
 	.ndo_start_xmit		= be_xmit,
-	.ndo_get_stats		= be_get_stats,
 	.ndo_set_rx_mode	= be_set_multicast_list,
 	.ndo_set_mac_address	= be_mac_addr_set,
 	.ndo_change_mtu		= be_change_mtu,
@@ -2407,6 +2529,8 @@
 static void be_netdev_init(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
+	struct be_rx_obj *rxo;
+	int i;
 
 	netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO |
 		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM |
@@ -2428,8 +2552,10 @@
 
 	SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
 
-	netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx,
-		BE_NAPI_WEIGHT);
+	for_all_rx_queues(adapter, rxo, i)
+		netif_napi_add(netdev, &rxo->rx_eq.napi, be_poll_rx,
+				BE_NAPI_WEIGHT);
+
 	netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc,
 		BE_NAPI_WEIGHT);
 
@@ -2563,8 +2689,7 @@
 
 static void be_stats_cleanup(struct be_adapter *adapter)
 {
-	struct be_stats_obj *stats = &adapter->stats;
-	struct be_dma_mem *cmd = &stats->cmd;
+	struct be_dma_mem *cmd = &adapter->stats_cmd;
 
 	if (cmd->va)
 		pci_free_consistent(adapter->pdev, cmd->size,
@@ -2573,8 +2698,7 @@
 
 static int be_stats_init(struct be_adapter *adapter)
 {
-	struct be_stats_obj *stats = &adapter->stats;
-	struct be_dma_mem *cmd = &stats->cmd;
+	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);
@@ -2619,8 +2743,8 @@
 	if (status)
 		return status;
 
-	status = be_cmd_query_fw_cfg(adapter,
-				&adapter->port_num, &adapter->function_mode);
+	status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
+			&adapter->function_mode, &adapter->function_caps);
 	if (status)
 		return status;
 
@@ -2655,7 +2779,6 @@
 	struct be_adapter *adapter;
 	struct net_device *netdev;
 
-
 	status = pci_enable_device(pdev);
 	if (status)
 		goto do_none;
@@ -2688,11 +2811,8 @@
 	adapter->pdev = pdev;
 	pci_set_drvdata(pdev, adapter);
 	adapter->netdev = netdev;
-	be_netdev_init(netdev);
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 
-	be_msix_enable(adapter);
-
 	status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
 	if (!status) {
 		netdev->features |= NETIF_F_HIGHDMA;
@@ -2736,12 +2856,15 @@
 	if (status)
 		goto stats_clean;
 
+	be_msix_enable(adapter);
+
 	INIT_DELAYED_WORK(&adapter->work, be_worker);
 
 	status = be_setup(adapter);
 	if (status)
-		goto stats_clean;
+		goto msix_disable;
 
+	be_netdev_init(netdev);
 	status = register_netdev(netdev);
 	if (status != 0)
 		goto unsetup;
@@ -2751,12 +2874,13 @@
 
 unsetup:
 	be_clear(adapter);
+msix_disable:
+	be_msix_disable(adapter);
 stats_clean:
 	be_stats_cleanup(adapter);
 ctrl_clean:
 	be_ctrl_cleanup(adapter);
 free_netdev:
-	be_msix_disable(adapter);
 	be_sriov_disable(adapter);
 	free_netdev(adapter->netdev);
 	pci_set_drvdata(pdev, NULL);
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 012613f..f723319 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -38,6 +38,7 @@
 #include <asm/blackfin.h>
 #include <asm/cacheflush.h>
 #include <asm/portmux.h>
+#include <mach/pll.h>
 
 #include "bfin_mac.h"
 
@@ -803,15 +804,14 @@
 static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
 {
 	struct bfin_mac_local *lp = netdev_priv(netdev);
-	union skb_shared_tx *shtx = skb_tx(skb);
 
-	if (shtx->hardware) {
+	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
 		int timeout_cnt = MAX_TIMEOUT_CNT;
 
 		/* When doing time stamping, keep the connection to the socket
 		 * a while longer
 		 */
-		shtx->in_progress = 1;
+		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 
 		/*
 		 * The timestamping is done at the EMAC module's MII/RMII interface
@@ -991,7 +991,6 @@
 	struct bfin_mac_local *lp = netdev_priv(dev);
 	u16 *data;
 	u32 data_align = (unsigned long)(skb->data) & 0x3;
-	union skb_shared_tx *shtx = skb_tx(skb);
 
 	current_tx_ptr->skb = skb;
 
@@ -1005,7 +1004,7 @@
 		 * of this field are the length of the packet payload in bytes and the higher
 		 * 4 bits are the timestamping enable field.
 		 */
-		if (shtx->hardware)
+		if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
 			*data |= 0x1000;
 
 		current_tx_ptr->desc_a.start_addr = (u32)data;
@@ -1015,7 +1014,7 @@
 	} else {
 		*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
 		/* enable timestamping for the sent packet */
-		if (shtx->hardware)
+		if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
 			*((u16 *)(current_tx_ptr->packet)) |= 0x1000;
 		memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
 			skb->len);
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 959add2..a1b8c8b 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -1233,15 +1233,8 @@
 	}
 	spin_unlock_irqrestore(&bp->lock, flags);
 }
-static void bmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct bmac_data *bp = netdev_priv(dev);
-	strcpy(info->driver, "bmac");
-	strcpy(info->bus_info, dev_name(&bp->mdev->ofdev.dev));
-}
 
 static const struct ethtool_ops bmac_ethtool_ops = {
-	.get_drvinfo		= bmac_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
 };
 
@@ -1588,7 +1581,7 @@
 	int i;
 
 	if (bmac_devs == NULL)
-		return (-ENOSYS);
+		return -ENOSYS;
 
 	len += sprintf(buffer, "BMAC counters & registers\n");
 
diff --git a/drivers/net/bna/Makefile b/drivers/net/bna/Makefile
new file mode 100644
index 0000000..a5d604de
--- /dev/null
+++ b/drivers/net/bna/Makefile
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+# All rights reserved.
+#
+
+obj-$(CONFIG_BNA) += bna.o
+
+bna-objs := bnad.o bnad_ethtool.o bna_ctrl.o bna_txrx.o
+bna-objs += bfa_ioc.o bfa_ioc_ct.o bfa_cee.o cna_fwimg.o
+
+EXTRA_CFLAGS := -Idrivers/net/bna
diff --git a/drivers/net/bna/bfa_cee.c b/drivers/net/bna/bfa_cee.c
new file mode 100644
index 0000000..f7b789a
--- /dev/null
+++ b/drivers/net/bna/bfa_cee.c
@@ -0,0 +1,291 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#include "bfa_defs_cna.h"
+#include "cna.h"
+#include "bfa_cee.h"
+#include "bfi_cna.h"
+#include "bfa_ioc.h"
+
+#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
+#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
+
+static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg);
+static void bfa_cee_format_cee_cfg(void *buffer);
+
+static void
+bfa_cee_format_cee_cfg(void *buffer)
+{
+	struct bfa_cee_attr *cee_cfg = buffer;
+	bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote);
+}
+
+static void
+bfa_cee_stats_swap(struct bfa_cee_stats *stats)
+{
+	u32 *buffer = (u32 *)stats;
+	int i;
+
+	for (i = 0; i < (sizeof(struct bfa_cee_stats) / sizeof(u32));
+		i++) {
+		buffer[i] = ntohl(buffer[i]);
+	}
+}
+
+static void
+bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg)
+{
+	lldp_cfg->time_to_live =
+			ntohs(lldp_cfg->time_to_live);
+	lldp_cfg->enabled_system_cap =
+			ntohs(lldp_cfg->enabled_system_cap);
+}
+
+/**
+ * bfa_cee_attr_meminfo()
+ *
+ * @brief Returns the size of the DMA memory needed by CEE attributes
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+static u32
+bfa_cee_attr_meminfo(void)
+{
+	return roundup(sizeof(struct bfa_cee_attr), BFA_DMA_ALIGN_SZ);
+}
+/**
+ * bfa_cee_stats_meminfo()
+ *
+ * @brief Returns the size of the DMA memory needed by CEE stats
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+static u32
+bfa_cee_stats_meminfo(void)
+{
+	return roundup(sizeof(struct bfa_cee_stats), BFA_DMA_ALIGN_SZ);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ * @brief CEE ISR for get-attributes responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_attr_isr(struct bfa_cee *cee, enum bfa_status status)
+{
+	cee->get_attr_status = status;
+	if (status == BFA_STATUS_OK) {
+		memcpy(cee->attr, cee->attr_dma.kva,
+		    sizeof(struct bfa_cee_attr));
+		bfa_cee_format_cee_cfg(cee->attr);
+	}
+	cee->get_attr_pending = false;
+	if (cee->cbfn.get_attr_cbfn)
+		cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ * @brief CEE ISR for get-stats responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_stats_isr(struct bfa_cee *cee, enum bfa_status status)
+{
+	cee->get_stats_status = status;
+	if (status == BFA_STATUS_OK) {
+		memcpy(cee->stats, cee->stats_dma.kva,
+			sizeof(struct bfa_cee_stats));
+		bfa_cee_stats_swap(cee->stats);
+	}
+	cee->get_stats_pending = false;
+	if (cee->cbfn.get_stats_cbfn)
+		cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ * @brief CEE ISR for reset-stats responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_reset_stats_isr(struct bfa_cee *cee, enum bfa_status status)
+{
+	cee->reset_stats_status = status;
+	cee->reset_stats_pending = false;
+	if (cee->cbfn.reset_stats_cbfn)
+		cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
+}
+/**
+ * bfa_nw_cee_meminfo()
+ *
+ * @brief Returns the size of the DMA memory needed by CEE module
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+u32
+bfa_nw_cee_meminfo(void)
+{
+	return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo();
+}
+
+/**
+ * bfa_nw_cee_mem_claim()
+ *
+ * @brief Initialized CEE DMA Memory
+ *
+ * @param[in] cee CEE module pointer
+ *	      dma_kva Kernel Virtual Address of CEE DMA Memory
+ *	      dma_pa  Physical Address of CEE DMA Memory
+ *
+ * @return void
+ */
+void
+bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa)
+{
+	cee->attr_dma.kva = dma_kva;
+	cee->attr_dma.pa = dma_pa;
+	cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo();
+	cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo();
+	cee->attr = (struct bfa_cee_attr *) dma_kva;
+	cee->stats = (struct bfa_cee_stats *)
+		(dma_kva + bfa_cee_attr_meminfo());
+}
+
+/**
+ * bfa_cee_isrs()
+ *
+ * @brief Handles Mail-box interrupts for CEE module.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return void
+ */
+
+static void
+bfa_cee_isr(void *cbarg, struct bfi_mbmsg *m)
+{
+	union bfi_cee_i2h_msg_u *msg;
+	struct bfi_cee_get_rsp *get_rsp;
+	struct bfa_cee *cee = (struct bfa_cee *) cbarg;
+	msg = (union bfi_cee_i2h_msg_u *) m;
+	get_rsp = (struct bfi_cee_get_rsp *) m;
+	switch (msg->mh.msg_id) {
+	case BFI_CEE_I2H_GET_CFG_RSP:
+		bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
+		break;
+	case BFI_CEE_I2H_GET_STATS_RSP:
+		bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
+		break;
+	case BFI_CEE_I2H_RESET_STATS_RSP:
+		bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
+		break;
+	default:
+		BUG_ON(1);
+	}
+}
+
+/**
+ * bfa_cee_hbfail()
+ *
+ * @brief CEE module heart-beat failure handler.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return void
+ */
+
+static void
+bfa_cee_hbfail(void *arg)
+{
+	struct bfa_cee *cee;
+	cee = (struct bfa_cee *) arg;
+
+	if (cee->get_attr_pending == true) {
+		cee->get_attr_status = BFA_STATUS_FAILED;
+		cee->get_attr_pending  = false;
+		if (cee->cbfn.get_attr_cbfn) {
+			cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg,
+			    BFA_STATUS_FAILED);
+		}
+	}
+	if (cee->get_stats_pending == true) {
+		cee->get_stats_status = BFA_STATUS_FAILED;
+		cee->get_stats_pending  = false;
+		if (cee->cbfn.get_stats_cbfn) {
+			cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg,
+			    BFA_STATUS_FAILED);
+		}
+	}
+	if (cee->reset_stats_pending == true) {
+		cee->reset_stats_status = BFA_STATUS_FAILED;
+		cee->reset_stats_pending  = false;
+		if (cee->cbfn.reset_stats_cbfn) {
+			cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg,
+			    BFA_STATUS_FAILED);
+		}
+	}
+}
+
+/**
+ * bfa_nw_cee_attach()
+ *
+ * @brief CEE module-attach API
+ *
+ * @param[in] cee - Pointer to the CEE module data structure
+ *            ioc - Pointer to the ioc module data structure
+ *            dev - Pointer to the device driver module data structure
+ *                  The device driver specific mbox ISR functions have
+ *                  this pointer as one of the parameters.
+ *
+ * @return void
+ */
+void
+bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc,
+		void *dev)
+{
+	BUG_ON(!(cee != NULL));
+	cee->dev = dev;
+	cee->ioc = ioc;
+
+	bfa_nw_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
+	bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee);
+	bfa_nw_ioc_hbfail_register(cee->ioc, &cee->hbfail);
+}
diff --git a/drivers/net/bna/bfa_cee.h b/drivers/net/bna/bfa_cee.h
new file mode 100644
index 0000000..20543d1
--- /dev/null
+++ b/drivers/net/bna/bfa_cee.h
@@ -0,0 +1,64 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFA_CEE_H__
+#define __BFA_CEE_H__
+
+#include "bfa_defs_cna.h"
+#include "bfa_ioc.h"
+
+typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, enum bfa_status status);
+typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, enum bfa_status status);
+typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, enum bfa_status status);
+typedef void (*bfa_cee_hbfail_cbfn_t) (void *dev, enum bfa_status status);
+
+struct bfa_cee_cbfn {
+	bfa_cee_get_attr_cbfn_t    get_attr_cbfn;
+	void *get_attr_cbarg;
+	bfa_cee_get_stats_cbfn_t   get_stats_cbfn;
+	void *get_stats_cbarg;
+	bfa_cee_reset_stats_cbfn_t reset_stats_cbfn;
+	void *reset_stats_cbarg;
+};
+
+struct bfa_cee {
+	void *dev;
+	bool get_attr_pending;
+	bool get_stats_pending;
+	bool reset_stats_pending;
+	enum bfa_status get_attr_status;
+	enum bfa_status get_stats_status;
+	enum bfa_status reset_stats_status;
+	struct bfa_cee_cbfn cbfn;
+	struct bfa_ioc_hbfail_notify hbfail;
+	struct bfa_cee_attr *attr;
+	struct bfa_cee_stats *stats;
+	struct bfa_dma attr_dma;
+	struct bfa_dma stats_dma;
+	struct bfa_ioc *ioc;
+	struct bfa_mbox_cmd get_cfg_mb;
+	struct bfa_mbox_cmd get_stats_mb;
+	struct bfa_mbox_cmd reset_stats_mb;
+};
+
+u32 bfa_nw_cee_meminfo(void);
+void bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva,
+	u64 dma_pa);
+void bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, void *dev);
+
+#endif /* __BFA_CEE_H__ */
diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
new file mode 100644
index 0000000..29c1b8de
--- /dev/null
+++ b/drivers/net/bna/bfa_defs.h
@@ -0,0 +1,243 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFA_DEFS_H__
+#define __BFA_DEFS_H__
+
+#include "cna.h"
+#include "bfa_defs_status.h"
+#include "bfa_defs_mfg_comm.h"
+
+#define BFA_STRING_32	32
+#define BFA_VERSION_LEN 64
+
+/**
+ * ---------------------- adapter definitions ------------
+ */
+
+/**
+ * BFA adapter level attributes.
+ */
+enum {
+	BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE),
+					/*
+					 *!< adapter serial num length
+					 */
+	BFA_ADAPTER_MODEL_NAME_LEN  = 16,  /*!< model name length */
+	BFA_ADAPTER_MODEL_DESCR_LEN = 128, /*!< model description length */
+	BFA_ADAPTER_MFG_NAME_LEN    = 8,   /*!< manufacturer name length */
+	BFA_ADAPTER_SYM_NAME_LEN    = 64,  /*!< adapter symbolic name length */
+	BFA_ADAPTER_OS_TYPE_LEN	    = 64,  /*!< adapter os type length */
+};
+
+struct bfa_adapter_attr {
+	char		manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
+	char		serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+	u32	card_type;
+	char		model[BFA_ADAPTER_MODEL_NAME_LEN];
+	char		model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
+	u64		pwwn;
+	char		node_symname[FC_SYMNAME_MAX];
+	char		hw_ver[BFA_VERSION_LEN];
+	char		fw_ver[BFA_VERSION_LEN];
+	char		optrom_ver[BFA_VERSION_LEN];
+	char		os_type[BFA_ADAPTER_OS_TYPE_LEN];
+	struct bfa_mfg_vpd vpd;
+	struct mac mac;
+
+	u8		nports;
+	u8		max_speed;
+	u8		prototype;
+	char	        asic_rev;
+
+	u8		pcie_gen;
+	u8		pcie_lanes_orig;
+	u8		pcie_lanes;
+	u8	        cna_capable;
+
+	u8		is_mezz;
+	u8		trunk_capable;
+};
+
+/**
+ * ---------------------- IOC definitions ------------
+ */
+
+enum {
+	BFA_IOC_DRIVER_LEN	= 16,
+	BFA_IOC_CHIP_REV_LEN 	= 8,
+};
+
+/**
+ * Driver and firmware versions.
+ */
+struct bfa_ioc_driver_attr {
+	char		driver[BFA_IOC_DRIVER_LEN];	/*!< driver name */
+	char		driver_ver[BFA_VERSION_LEN];	/*!< driver version */
+	char		fw_ver[BFA_VERSION_LEN];	/*!< firmware version */
+	char		bios_ver[BFA_VERSION_LEN];	/*!< bios version */
+	char		efi_ver[BFA_VERSION_LEN];	/*!< EFI version */
+	char		ob_ver[BFA_VERSION_LEN];	/*!< openboot version */
+};
+
+/**
+ * IOC PCI device attributes
+ */
+struct bfa_ioc_pci_attr {
+	u16	vendor_id;	/*!< PCI vendor ID */
+	u16	device_id;	/*!< PCI device ID */
+	u16	ssid;		/*!< subsystem ID */
+	u16	ssvid;		/*!< subsystem vendor ID */
+	u32	pcifn;		/*!< PCI device function */
+	u32	rsvd;		/* padding */
+	char		chip_rev[BFA_IOC_CHIP_REV_LEN];	 /*!< chip revision */
+};
+
+/**
+ * IOC states
+ */
+enum bfa_ioc_state {
+	BFA_IOC_RESET		= 1,	/*!< IOC is in reset state */
+	BFA_IOC_SEMWAIT		= 2,	/*!< Waiting for IOC h/w semaphore */
+	BFA_IOC_HWINIT		= 3,	/*!< IOC h/w is being initialized */
+	BFA_IOC_GETATTR		= 4,	/*!< IOC is being configured */
+	BFA_IOC_OPERATIONAL	= 5,	/*!< IOC is operational */
+	BFA_IOC_INITFAIL	= 6,	/*!< IOC hardware failure */
+	BFA_IOC_HBFAIL		= 7,	/*!< IOC heart-beat failure */
+	BFA_IOC_DISABLING	= 8,	/*!< IOC is being disabled */
+	BFA_IOC_DISABLED	= 9,	/*!< IOC is disabled */
+	BFA_IOC_FWMISMATCH	= 10,	/*!< IOC f/w different from drivers */
+};
+
+/**
+ * IOC firmware stats
+ */
+struct bfa_fw_ioc_stats {
+	u32	enable_reqs;
+	u32	disable_reqs;
+	u32	get_attr_reqs;
+	u32	dbg_sync;
+	u32	dbg_dump;
+	u32	unknown_reqs;
+};
+
+/**
+ * IOC driver stats
+ */
+struct bfa_ioc_drv_stats {
+	u32	ioc_isrs;
+	u32	ioc_enables;
+	u32	ioc_disables;
+	u32	ioc_hbfails;
+	u32	ioc_boots;
+	u32	stats_tmos;
+	u32	hb_count;
+	u32	disable_reqs;
+	u32	enable_reqs;
+	u32	disable_replies;
+	u32	enable_replies;
+};
+
+/**
+ * IOC statistics
+ */
+struct bfa_ioc_stats {
+	struct bfa_ioc_drv_stats drv_stats; /*!< driver IOC stats */
+	struct bfa_fw_ioc_stats fw_stats;  /*!< firmware IOC stats */
+};
+
+enum bfa_ioc_type {
+	BFA_IOC_TYPE_FC		= 1,
+	BFA_IOC_TYPE_FCoE	= 2,
+	BFA_IOC_TYPE_LL		= 3,
+};
+
+/**
+ * IOC attributes returned in queries
+ */
+struct bfa_ioc_attr {
+	enum bfa_ioc_type ioc_type;
+	enum bfa_ioc_state 		state;		/*!< IOC state      */
+	struct bfa_adapter_attr adapter_attr;	/*!< HBA attributes */
+	struct bfa_ioc_driver_attr driver_attr;	/*!< driver attr    */
+	struct bfa_ioc_pci_attr pci_attr;
+	u8				port_id;	/*!< port number    */
+	u8				rsvd[7];	/*!< 64bit align    */
+};
+
+/**
+ * ---------------------- mfg definitions ------------
+ */
+
+/**
+ * Checksum size
+ */
+#define BFA_MFG_CHKSUM_SIZE			16
+
+#define BFA_MFG_PARTNUM_SIZE			14
+#define BFA_MFG_SUPPLIER_ID_SIZE		10
+#define BFA_MFG_SUPPLIER_PARTNUM_SIZE		20
+#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE		20
+#define BFA_MFG_SUPPLIER_REVISION_SIZE		4
+
+#pragma pack(1)
+
+/**
+ * @brief BFA adapter manufacturing block definition.
+ *
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_block {
+	u8		version;	/*!< manufacturing block version */
+	u8		mfg_sig[3];	/*!< characters 'M', 'F', 'G' */
+	u16	mfgsize;	/*!< mfg block size */
+	u16	u16_chksum;	/*!< old u16 checksum */
+	char		brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+	char		brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
+	u8		mfg_day;	/*!< manufacturing day */
+	u8		mfg_month;	/*!< manufacturing month */
+	u16	mfg_year;	/*!< manufacturing year */
+	u64		mfg_wwn;	/*!< wwn base for this adapter */
+	u8		num_wwn;	/*!< number of wwns assigned */
+	u8		mfg_speeds;	/*!< speeds allowed for this adapter */
+	u8		rsv[2];
+	char		supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
+	char		supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
+	char
+		supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
+	char
+		supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
+	mac_t		mfg_mac;	/*!< mac address */
+	u8		num_mac;	/*!< number of mac addresses */
+	u8		rsv2;
+	u32	mfg_type;	/*!< card type */
+	u8		rsv3[108];
+	u8		md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */
+};
+
+#pragma pack()
+
+/**
+ * ---------------------- pci definitions ------------
+ */
+
+#define bfa_asic_id_ct(devid)			\
+	((devid) == PCI_DEVICE_ID_BROCADE_CT ||	\
+	(devid) == PCI_DEVICE_ID_BROCADE_CT_FC)
+
+#endif /* __BFA_DEFS_H__ */
diff --git a/drivers/net/bna/bfa_defs_cna.h b/drivers/net/bna/bfa_defs_cna.h
new file mode 100644
index 0000000..7e0a918
--- /dev/null
+++ b/drivers/net/bna/bfa_defs_cna.h
@@ -0,0 +1,223 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFA_DEFS_CNA_H__
+#define __BFA_DEFS_CNA_H__
+
+#include "bfa_defs.h"
+
+/**
+ * @brief
+ * FC physical port statistics.
+ */
+struct bfa_port_fc_stats {
+	u64	secs_reset;	/*!< Seconds since stats is reset */
+	u64	tx_frames;	/*!< Tx frames			*/
+	u64	tx_words;	/*!< Tx words			*/
+	u64	tx_lip;		/*!< Tx LIP			*/
+	u64	tx_nos;		/*!< Tx NOS			*/
+	u64	tx_ols;		/*!< Tx OLS			*/
+	u64	tx_lr;		/*!< Tx LR			*/
+	u64	tx_lrr;		/*!< Tx LRR			*/
+	u64	rx_frames;	/*!< Rx frames			*/
+	u64	rx_words;	/*!< Rx words			*/
+	u64	lip_count;	/*!< Rx LIP			*/
+	u64	nos_count;	/*!< Rx NOS			*/
+	u64	ols_count;	/*!< Rx OLS			*/
+	u64	lr_count;	/*!< Rx LR			*/
+	u64	lrr_count;	/*!< Rx LRR			*/
+	u64	invalid_crcs;	/*!< Rx CRC err frames		*/
+	u64	invalid_crc_gd_eof; /*!< Rx CRC err good EOF frames */
+	u64	undersized_frm; /*!< Rx undersized frames	*/
+	u64	oversized_frm;	/*!< Rx oversized frames	*/
+	u64	bad_eof_frm;	/*!< Rx frames with bad EOF	*/
+	u64	error_frames;	/*!< Errored frames		*/
+	u64	dropped_frames;	/*!< Dropped frames		*/
+	u64	link_failures;	/*!< Link Failure (LF) count	*/
+	u64	loss_of_syncs;	/*!< Loss of sync count		*/
+	u64	loss_of_signals; /*!< Loss of signal count	*/
+	u64	primseq_errs;	/*!< Primitive sequence protocol err. */
+	u64	bad_os_count;	/*!< Invalid ordered sets	*/
+	u64	err_enc_out;	/*!< Encoding err nonframe_8b10b */
+	u64	err_enc;	/*!< Encoding err frame_8b10b	*/
+};
+
+/**
+ * @brief
+ * Eth Physical Port statistics.
+ */
+struct bfa_port_eth_stats {
+	u64	secs_reset;	/*!< Seconds since stats is reset */
+	u64	frame_64;	/*!< Frames 64 bytes		*/
+	u64	frame_65_127;	/*!< Frames 65-127 bytes	*/
+	u64	frame_128_255;	/*!< Frames 128-255 bytes	*/
+	u64	frame_256_511;	/*!< Frames 256-511 bytes	*/
+	u64	frame_512_1023;	/*!< Frames 512-1023 bytes	*/
+	u64	frame_1024_1518; /*!< Frames 1024-1518 bytes	*/
+	u64	frame_1519_1522; /*!< Frames 1519-1522 bytes	*/
+	u64	tx_bytes;	/*!< Tx bytes			*/
+	u64	tx_packets;	 /*!< Tx packets		*/
+	u64	tx_mcast_packets; /*!< Tx multicast packets	*/
+	u64	tx_bcast_packets; /*!< Tx broadcast packets	*/
+	u64	tx_control_frame; /*!< Tx control frame		*/
+	u64	tx_drop;	/*!< Tx drops			*/
+	u64	tx_jabber;	/*!< Tx jabber			*/
+	u64	tx_fcs_error;	/*!< Tx FCS errors		*/
+	u64	tx_fragments;	/*!< Tx fragments		*/
+	u64	rx_bytes;	/*!< Rx bytes			*/
+	u64	rx_packets;	/*!< Rx packets			*/
+	u64	rx_mcast_packets; /*!< Rx multicast packets	*/
+	u64	rx_bcast_packets; /*!< Rx broadcast packets	*/
+	u64	rx_control_frames; /*!< Rx control frames	*/
+	u64	rx_unknown_opcode; /*!< Rx unknown opcode	*/
+	u64	rx_drop;	/*!< Rx drops			*/
+	u64	rx_jabber;	/*!< Rx jabber			*/
+	u64	rx_fcs_error;	/*!< Rx FCS errors		*/
+	u64	rx_alignment_error; /*!< Rx alignment errors	*/
+	u64	rx_frame_length_error; /*!< Rx frame len errors	*/
+	u64	rx_code_error;	/*!< Rx code errors		*/
+	u64	rx_fragments;	/*!< Rx fragments		*/
+	u64	rx_pause;	/*!< Rx pause			*/
+	u64	rx_zero_pause;	/*!< Rx zero pause		*/
+	u64	tx_pause;	/*!< Tx pause			*/
+	u64	tx_zero_pause;	/*!< Tx zero pause		*/
+	u64	rx_fcoe_pause;	/*!< Rx FCoE pause		*/
+	u64	rx_fcoe_zero_pause; /*!< Rx FCoE zero pause	*/
+	u64	tx_fcoe_pause;	/*!< Tx FCoE pause		*/
+	u64	tx_fcoe_zero_pause; /*!< Tx FCoE zero pause	*/
+};
+
+/**
+ * @brief
+ *		Port statistics.
+ */
+union bfa_port_stats_u {
+	struct bfa_port_fc_stats fc;
+	struct bfa_port_eth_stats eth;
+};
+
+#pragma pack(1)
+
+#define BFA_CEE_LLDP_MAX_STRING_LEN (128)
+#define BFA_CEE_DCBX_MAX_PRIORITY	(8)
+#define BFA_CEE_DCBX_MAX_PGID		(8)
+
+#define BFA_CEE_LLDP_SYS_CAP_OTHER	0x0001
+#define BFA_CEE_LLDP_SYS_CAP_REPEATER	0x0002
+#define BFA_CEE_LLDP_SYS_CAP_MAC_BRIDGE	0x0004
+#define BFA_CEE_LLDP_SYS_CAP_WLAN_AP	0x0008
+#define BFA_CEE_LLDP_SYS_CAP_ROUTER	0x0010
+#define BFA_CEE_LLDP_SYS_CAP_TELEPHONE	0x0020
+#define BFA_CEE_LLDP_SYS_CAP_DOCSIS_CD	0x0040
+#define BFA_CEE_LLDP_SYS_CAP_STATION	0x0080
+#define BFA_CEE_LLDP_SYS_CAP_CVLAN	0x0100
+#define BFA_CEE_LLDP_SYS_CAP_SVLAN	0x0200
+#define BFA_CEE_LLDP_SYS_CAP_TPMR	0x0400
+
+/* LLDP string type */
+struct bfa_cee_lldp_str {
+	u8 sub_type;
+	u8 len;
+	u8 rsvd[2];
+	u8 value[BFA_CEE_LLDP_MAX_STRING_LEN];
+};
+
+/* LLDP paramters */
+struct bfa_cee_lldp_cfg {
+	struct bfa_cee_lldp_str chassis_id;
+	struct bfa_cee_lldp_str port_id;
+	struct bfa_cee_lldp_str port_desc;
+	struct bfa_cee_lldp_str sys_name;
+	struct bfa_cee_lldp_str sys_desc;
+	struct bfa_cee_lldp_str mgmt_addr;
+	u16 time_to_live;
+	u16 enabled_system_cap;
+};
+
+enum bfa_cee_dcbx_version {
+	DCBX_PROTOCOL_PRECEE	= 1,
+	DCBX_PROTOCOL_CEE	= 2,
+};
+
+enum bfa_cee_lls {
+	/* LLS is down because the TLV not sent by the peer */
+	CEE_LLS_DOWN_NO_TLV = 0,
+	/* LLS is down as advertised by the peer */
+	CEE_LLS_DOWN	= 1,
+	CEE_LLS_UP	= 2,
+};
+
+/* CEE/DCBX parameters */
+struct bfa_cee_dcbx_cfg {
+	u8 pgid[BFA_CEE_DCBX_MAX_PRIORITY];
+	u8 pg_percentage[BFA_CEE_DCBX_MAX_PGID];
+	u8 pfc_primap; /* bitmap of priorties with PFC enabled */
+	u8 fcoe_primap; /* bitmap of priorities used for FcoE traffic */
+	u8 iscsi_primap; /* bitmap of priorities used for iSCSI traffic */
+	u8 dcbx_version; /* operating version:CEE or preCEE */
+	u8 lls_fcoe; /* FCoE Logical Link Status */
+	u8 lls_lan; /* LAN Logical Link Status */
+	u8 rsvd[2];
+};
+
+/* CEE status */
+/* Making this to tri-state for the benefit of port list command */
+enum bfa_cee_status {
+	CEE_UP = 0,
+	CEE_PHY_UP = 1,
+	CEE_LOOPBACK = 2,
+	CEE_PHY_DOWN = 3,
+};
+
+/* CEE Query */
+struct bfa_cee_attr {
+	u8	cee_status;
+	u8 error_reason;
+	struct bfa_cee_lldp_cfg lldp_remote;
+	struct bfa_cee_dcbx_cfg dcbx_remote;
+	mac_t src_mac;
+	u8 link_speed;
+	u8 nw_priority;
+	u8 filler[2];
+};
+
+/* LLDP/DCBX/CEE Statistics */
+struct bfa_cee_stats {
+	u32	lldp_tx_frames;		/*!< LLDP Tx Frames */
+	u32	lldp_rx_frames;		/*!< LLDP Rx Frames */
+	u32	lldp_rx_frames_invalid;	/*!< LLDP Rx Frames invalid */
+	u32	lldp_rx_frames_new;	/*!< LLDP Rx Frames new */
+	u32	lldp_tlvs_unrecognized;	/*!< LLDP Rx unrecognized TLVs */
+	u32	lldp_rx_shutdown_tlvs;	/*!< LLDP Rx shutdown TLVs */
+	u32	lldp_info_aged_out;	/*!< LLDP remote info aged out */
+	u32	dcbx_phylink_ups;	/*!< DCBX phy link ups */
+	u32	dcbx_phylink_downs;	/*!< DCBX phy link downs */
+	u32	dcbx_rx_tlvs;		/*!< DCBX Rx TLVs */
+	u32	dcbx_rx_tlvs_invalid;	/*!< DCBX Rx TLVs invalid */
+	u32	dcbx_control_tlv_error;	/*!< DCBX control TLV errors */
+	u32	dcbx_feature_tlv_error;	/*!< DCBX feature TLV errors */
+	u32	dcbx_cee_cfg_new;	/*!< DCBX new CEE cfg rcvd */
+	u32	cee_status_down;	/*!< CEE status down */
+	u32	cee_status_up;		/*!< CEE status up */
+	u32	cee_hw_cfg_changed;	/*!< CEE hw cfg changed */
+	u32	cee_rx_invalid_cfg;	/*!< CEE invalid cfg */
+};
+
+#pragma pack()
+
+#endif	/* __BFA_DEFS_CNA_H__ */
diff --git a/drivers/net/bna/bfa_defs_mfg_comm.h b/drivers/net/bna/bfa_defs_mfg_comm.h
new file mode 100644
index 0000000..987978f
--- /dev/null
+++ b/drivers/net/bna/bfa_defs_mfg_comm.h
@@ -0,0 +1,244 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BFA_DEFS_MFG_COMM_H__
+#define __BFA_DEFS_MFG_COMM_H__
+
+#include "cna.h"
+
+/**
+ * Manufacturing block version
+ */
+#define BFA_MFG_VERSION				2
+#define BFA_MFG_VERSION_UNINIT			0xFF
+
+/**
+ * Manufacturing block encrypted version
+ */
+#define BFA_MFG_ENC_VER				2
+
+/**
+ * Manufacturing block version 1 length
+ */
+#define BFA_MFG_VER1_LEN			128
+
+/**
+ * Manufacturing block header length
+ */
+#define BFA_MFG_HDR_LEN				4
+
+#define BFA_MFG_SERIALNUM_SIZE			11
+#define STRSZ(_n)				(((_n) + 4) & ~3)
+
+/**
+ * Manufacturing card type
+ */
+enum {
+	BFA_MFG_TYPE_CB_MAX  = 825,      /*!< Crossbow card type max	*/
+	BFA_MFG_TYPE_FC8P2   = 825,      /*!< 8G 2port FC card		*/
+	BFA_MFG_TYPE_FC8P1   = 815,      /*!< 8G 1port FC card		*/
+	BFA_MFG_TYPE_FC4P2   = 425,      /*!< 4G 2port FC card		*/
+	BFA_MFG_TYPE_FC4P1   = 415,      /*!< 4G 1port FC card		*/
+	BFA_MFG_TYPE_CNA10P2 = 1020,     /*!< 10G 2port CNA card	*/
+	BFA_MFG_TYPE_CNA10P1 = 1010,     /*!< 10G 1port CNA card	*/
+	BFA_MFG_TYPE_JAYHAWK = 804,	 /*!< Jayhawk mezz card		*/
+	BFA_MFG_TYPE_WANCHESE = 1007,	 /*!< Wanchese mezz card	*/
+	BFA_MFG_TYPE_ASTRA    = 807,	 /*!< Astra mezz card		*/
+	BFA_MFG_TYPE_LIGHTNING_P0 = 902, /*!< Lightning mezz card - old	*/
+	BFA_MFG_TYPE_LIGHTNING = 1741,	 /*!< Lightning mezz card	*/
+	BFA_MFG_TYPE_INVALID = 0,	 /*!< Invalid card type		*/
+};
+
+#pragma pack(1)
+
+/**
+ * Check if 1-port card
+ */
+#define bfa_mfg_is_1port(type) (( \
+	(type) == BFA_MFG_TYPE_FC8P1 || \
+	(type) == BFA_MFG_TYPE_FC4P1 || \
+	(type) == BFA_MFG_TYPE_CNA10P1))
+
+/**
+ * Check if Mezz card
+ */
+#define bfa_mfg_is_mezz(type) (( \
+	(type) == BFA_MFG_TYPE_JAYHAWK || \
+	(type) == BFA_MFG_TYPE_WANCHESE || \
+	(type) == BFA_MFG_TYPE_ASTRA || \
+	(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
+	(type) == BFA_MFG_TYPE_LIGHTNING))
+
+/**
+ * Check if card type valid
+ */
+#define bfa_mfg_is_card_type_valid(type) (( \
+	(type) == BFA_MFG_TYPE_FC8P2 || \
+	(type) == BFA_MFG_TYPE_FC8P1 || \
+	(type) == BFA_MFG_TYPE_FC4P2 || \
+	(type) == BFA_MFG_TYPE_FC4P1 || \
+	(type) == BFA_MFG_TYPE_CNA10P2 || \
+	(type) == BFA_MFG_TYPE_CNA10P1 || \
+	bfa_mfg_is_mezz(type)))
+
+/**
+ * Check if the card having old wwn/mac handling
+ */
+#define bfa_mfg_is_old_wwn_mac_model(type) (( \
+	(type) == BFA_MFG_TYPE_FC8P2 || \
+	(type) == BFA_MFG_TYPE_FC8P1 || \
+	(type) == BFA_MFG_TYPE_FC4P2 || \
+	(type) == BFA_MFG_TYPE_FC4P1 || \
+	(type) == BFA_MFG_TYPE_CNA10P2 || \
+	(type) == BFA_MFG_TYPE_CNA10P1 || \
+	(type) == BFA_MFG_TYPE_JAYHAWK || \
+	(type) == BFA_MFG_TYPE_WANCHESE))
+
+#define bfa_mfg_increment_wwn_mac(m, i)				\
+do {								\
+	u32 t = ((m)[0] << 16) | ((m)[1] << 8) | (m)[2];	\
+	t += (i);						\
+	(m)[0] = (t >> 16) & 0xFF;				\
+	(m)[1] = (t >> 8) & 0xFF;				\
+	(m)[2] = t & 0xFF;					\
+} while (0)
+
+#define bfa_mfg_adapter_prop_init_flash(card_type, prop)	\
+do {								\
+	switch ((card_type)) {					\
+	case BFA_MFG_TYPE_FC8P2:				\
+	case BFA_MFG_TYPE_JAYHAWK:				\
+	case BFA_MFG_TYPE_ASTRA:				\
+		(prop) = BFI_ADAPTER_SETP(NPORTS, 2) |		\
+			BFI_ADAPTER_SETP(SPEED, 8);		\
+		break;						\
+	case BFA_MFG_TYPE_FC8P1:				\
+		(prop) = BFI_ADAPTER_SETP(NPORTS, 1) |		\
+			BFI_ADAPTER_SETP(SPEED, 8);		\
+		break;						\
+	case BFA_MFG_TYPE_FC4P2:				\
+		(prop) = BFI_ADAPTER_SETP(NPORTS, 2) |		\
+			BFI_ADAPTER_SETP(SPEED, 4);		\
+		break;						\
+	case BFA_MFG_TYPE_FC4P1:				\
+		(prop) = BFI_ADAPTER_SETP(NPORTS, 1) |		\
+			BFI_ADAPTER_SETP(SPEED, 4);		\
+		break;						\
+	case BFA_MFG_TYPE_CNA10P2:				\
+	case BFA_MFG_TYPE_WANCHESE:				\
+	case BFA_MFG_TYPE_LIGHTNING_P0:				\
+	case BFA_MFG_TYPE_LIGHTNING:				\
+		(prop) = BFI_ADAPTER_SETP(NPORTS, 2);		\
+		(prop) |= BFI_ADAPTER_SETP(SPEED, 10);		\
+		break;						\
+	case BFA_MFG_TYPE_CNA10P1:				\
+		(prop) = BFI_ADAPTER_SETP(NPORTS, 1);		\
+		(prop) |= BFI_ADAPTER_SETP(SPEED, 10);		\
+		break;						\
+	default:						\
+		(prop) = BFI_ADAPTER_UNSUPP;			\
+	}							\
+} while (0)
+
+enum {
+	CB_GPIO_TTV	= (1),		/*!< TTV debug capable cards	*/
+	CB_GPIO_FC8P2   = (2),		/*!< 8G 2port FC card		*/
+	CB_GPIO_FC8P1   = (3),		/*!< 8G 1port FC card		*/
+	CB_GPIO_FC4P2   = (4),		/*!< 4G 2port FC card		*/
+	CB_GPIO_FC4P1   = (5),		/*!< 4G 1port FC card		*/
+	CB_GPIO_DFLY    = (6),		/*!< 8G 2port FC mezzanine card	*/
+	CB_GPIO_PROTO   = (1 << 7)	/*!< 8G 2port FC prototypes	*/
+};
+
+#define bfa_mfg_adapter_prop_init_gpio(gpio, card_type, prop)	\
+do {								\
+	if ((gpio) & CB_GPIO_PROTO) {				\
+		(prop) |= BFI_ADAPTER_PROTO;			\
+		(gpio) &= ~CB_GPIO_PROTO;			\
+	}							\
+	switch ((gpio)) {					\
+	case CB_GPIO_TTV:					\
+		(prop) |= BFI_ADAPTER_TTV;			\
+	case CB_GPIO_DFLY:					\
+	case CB_GPIO_FC8P2:					\
+		(prop) |= BFI_ADAPTER_SETP(NPORTS, 2);		\
+		(prop) |= BFI_ADAPTER_SETP(SPEED, 8);		\
+		(card_type) = BFA_MFG_TYPE_FC8P2;		\
+		break;						\
+	case CB_GPIO_FC8P1:					\
+		(prop) |= BFI_ADAPTER_SETP(NPORTS, 1);		\
+		(prop) |= BFI_ADAPTER_SETP(SPEED, 8);		\
+		(card_type) = BFA_MFG_TYPE_FC8P1;		\
+		break;						\
+	case CB_GPIO_FC4P2:					\
+		(prop) |= BFI_ADAPTER_SETP(NPORTS, 2);		\
+		(prop) |= BFI_ADAPTER_SETP(SPEED, 4);		\
+		(card_type) = BFA_MFG_TYPE_FC4P2;		\
+		break;						\
+	case CB_GPIO_FC4P1:					\
+		(prop) |= BFI_ADAPTER_SETP(NPORTS, 1);		\
+		(prop) |= BFI_ADAPTER_SETP(SPEED, 4);		\
+		(card_type) = BFA_MFG_TYPE_FC4P1;		\
+		break;						\
+	default:						\
+		(prop) |= BFI_ADAPTER_UNSUPP;			\
+		(card_type) = BFA_MFG_TYPE_INVALID;		\
+	}							\
+} while (0)
+
+/**
+ * VPD data length
+ */
+#define BFA_MFG_VPD_LEN			512
+#define BFA_MFG_VPD_LEN_INVALID		0
+
+#define BFA_MFG_VPD_PCI_HDR_OFF		137
+#define BFA_MFG_VPD_PCI_VER_MASK	0x07	/*!< version mask 3 bits */
+#define BFA_MFG_VPD_PCI_VDR_MASK	0xf8	/*!< vendor mask 5 bits */
+
+/**
+ * VPD vendor tag
+ */
+enum {
+	BFA_MFG_VPD_UNKNOWN	= 0,     /*!< vendor unknown 		*/
+	BFA_MFG_VPD_IBM 	= 1,     /*!< vendor IBM 		*/
+	BFA_MFG_VPD_HP  	= 2,     /*!< vendor HP  		*/
+	BFA_MFG_VPD_DELL  	= 3,     /*!< vendor DELL  		*/
+	BFA_MFG_VPD_PCI_IBM 	= 0x08,  /*!< PCI VPD IBM     		*/
+	BFA_MFG_VPD_PCI_HP  	= 0x10,  /*!< PCI VPD HP		*/
+	BFA_MFG_VPD_PCI_DELL  	= 0x20,  /*!< PCI VPD DELL		*/
+	BFA_MFG_VPD_PCI_BRCD 	= 0xf8,  /*!< PCI VPD Brocade 		*/
+};
+
+/**
+ * @brief BFA adapter flash vpd data definition.
+ *
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_vpd {
+	u8		version;	/*!< vpd data version */
+	u8		vpd_sig[3];	/*!< characters 'V', 'P', 'D' */
+	u8		chksum;		/*!< u8 checksum */
+	u8		vendor;		/*!< vendor */
+	u8 	len;		/*!< vpd data length excluding header */
+	u8 	rsv;
+	u8		data[BFA_MFG_VPD_LEN];	/*!< vpd data */
+};
+
+#pragma pack()
+
+#endif /* __BFA_DEFS_MFG_H__ */
diff --git a/drivers/net/bna/bfa_defs_status.h b/drivers/net/bna/bfa_defs_status.h
new file mode 100644
index 0000000..af95112
--- /dev/null
+++ b/drivers/net/bna/bfa_defs_status.h
@@ -0,0 +1,216 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BFA_DEFS_STATUS_H__
+#define __BFA_DEFS_STATUS_H__
+
+/**
+ * API status return values
+ *
+ * NOTE: The error msgs are auto generated from the comments. Only singe line
+ * comments are supported
+ */
+enum bfa_status {
+	BFA_STATUS_OK 		= 0,
+	BFA_STATUS_FAILED 	= 1,
+	BFA_STATUS_EINVAL 	= 2,
+	BFA_STATUS_ENOMEM 	= 3,
+	BFA_STATUS_ENOSYS 	= 4,
+	BFA_STATUS_ETIMER 	= 5,
+	BFA_STATUS_EPROTOCOL 	= 6,
+	BFA_STATUS_ENOFCPORTS 	= 7,
+	BFA_STATUS_NOFLASH 	= 8,
+	BFA_STATUS_BADFLASH 	= 9,
+	BFA_STATUS_SFP_UNSUPP 	= 10,
+	BFA_STATUS_UNKNOWN_VFID = 11,
+	BFA_STATUS_DATACORRUPTED = 12,
+	BFA_STATUS_DEVBUSY 	= 13,
+	BFA_STATUS_ABORTED 	= 14,
+	BFA_STATUS_NODEV 	= 15,
+	BFA_STATUS_HDMA_FAILED 	= 16,
+	BFA_STATUS_FLASH_BAD_LEN = 17,
+	BFA_STATUS_UNKNOWN_LWWN = 18,
+	BFA_STATUS_UNKNOWN_RWWN = 19,
+	BFA_STATUS_FCPT_LS_RJT 	= 20,
+	BFA_STATUS_VPORT_EXISTS = 21,
+	BFA_STATUS_VPORT_MAX 	= 22,
+	BFA_STATUS_UNSUPP_SPEED = 23,
+	BFA_STATUS_INVLD_DFSZ 	= 24,
+	BFA_STATUS_CNFG_FAILED 	= 25,
+	BFA_STATUS_CMD_NOTSUPP 	= 26,
+	BFA_STATUS_NO_ADAPTER 	= 27,
+	BFA_STATUS_LINKDOWN 	= 28,
+	BFA_STATUS_FABRIC_RJT 	= 29,
+	BFA_STATUS_UNKNOWN_VWWN = 30,
+	BFA_STATUS_NSLOGIN_FAILED = 31,
+	BFA_STATUS_NO_RPORTS 	= 32,
+	BFA_STATUS_NSQUERY_FAILED = 33,
+	BFA_STATUS_PORT_OFFLINE = 34,
+	BFA_STATUS_RPORT_OFFLINE = 35,
+	BFA_STATUS_TGTOPEN_FAILED = 36,
+	BFA_STATUS_BAD_LUNS 	= 37,
+	BFA_STATUS_IO_FAILURE 	= 38,
+	BFA_STATUS_NO_FABRIC 	= 39,
+	BFA_STATUS_EBADF 	= 40,
+	BFA_STATUS_EINTR 	= 41,
+	BFA_STATUS_EIO 		= 42,
+	BFA_STATUS_ENOTTY 	= 43,
+	BFA_STATUS_ENXIO 	= 44,
+	BFA_STATUS_EFOPEN 	= 45,
+	BFA_STATUS_VPORT_WWN_BP = 46,
+	BFA_STATUS_PORT_NOT_DISABLED = 47,
+	BFA_STATUS_BADFRMHDR 	= 48,
+	BFA_STATUS_BADFRMSZ 	= 49,
+	BFA_STATUS_MISSINGFRM 	= 50,
+	BFA_STATUS_LINKTIMEOUT 	= 51,
+	BFA_STATUS_NO_FCPIM_NEXUS = 52,
+	BFA_STATUS_CHECKSUM_FAIL = 53,
+	BFA_STATUS_GZME_FAILED 	= 54,
+	BFA_STATUS_SCSISTART_REQD = 55,
+	BFA_STATUS_IOC_FAILURE 	= 56,
+	BFA_STATUS_INVALID_WWN 	= 57,
+	BFA_STATUS_MISMATCH 	= 58,
+	BFA_STATUS_IOC_ENABLED 	= 59,
+	BFA_STATUS_ADAPTER_ENABLED = 60,
+	BFA_STATUS_IOC_NON_OP 	= 61,
+	BFA_STATUS_ADDR_MAP_FAILURE = 62,
+	BFA_STATUS_SAME_NAME 	= 63,
+	BFA_STATUS_PENDING      = 64,
+	BFA_STATUS_8G_SPD	= 65,
+	BFA_STATUS_4G_SPD	= 66,
+	BFA_STATUS_AD_IS_ENABLE = 67,
+	BFA_STATUS_EINVAL_TOV 	= 68,
+	BFA_STATUS_EINVAL_QDEPTH = 69,
+	BFA_STATUS_VERSION_FAIL = 70,
+	BFA_STATUS_DIAG_BUSY    = 71,
+	BFA_STATUS_BEACON_ON	= 72,
+	BFA_STATUS_BEACON_OFF	= 73,
+	BFA_STATUS_LBEACON_ON   = 74,
+	BFA_STATUS_LBEACON_OFF	= 75,
+	BFA_STATUS_PORT_NOT_INITED = 76,
+	BFA_STATUS_RPSC_ENABLED = 77,
+	BFA_STATUS_ENOFSAVE 	= 78,
+	BFA_STATUS_BAD_FILE		= 79,
+	BFA_STATUS_RLIM_EN		= 80,
+	BFA_STATUS_RLIM_DIS		= 81,
+	BFA_STATUS_IOC_DISABLED  = 82,
+	BFA_STATUS_ADAPTER_DISABLED  = 83,
+	BFA_STATUS_BIOS_DISABLED  = 84,
+	BFA_STATUS_AUTH_ENABLED  = 85,
+	BFA_STATUS_AUTH_DISABLED  = 86,
+	BFA_STATUS_ERROR_TRL_ENABLED  = 87,
+	BFA_STATUS_ERROR_QOS_ENABLED  = 88,
+	BFA_STATUS_NO_SFP_DEV = 89,
+	BFA_STATUS_MEMTEST_FAILED = 90,
+	BFA_STATUS_INVALID_DEVID = 91,
+	BFA_STATUS_QOS_ENABLED = 92,
+	BFA_STATUS_QOS_DISABLED = 93,
+	BFA_STATUS_INCORRECT_DRV_CONFIG = 94,
+	BFA_STATUS_REG_FAIL = 95,
+	BFA_STATUS_IM_INV_CODE = 96,
+	BFA_STATUS_IM_INV_VLAN = 97,
+	BFA_STATUS_IM_INV_ADAPT_NAME = 98,
+	BFA_STATUS_IM_LOW_RESOURCES = 99,
+	BFA_STATUS_IM_VLANID_IS_PVID = 100,
+	BFA_STATUS_IM_VLANID_EXISTS = 101,
+	BFA_STATUS_IM_FW_UPDATE_FAIL = 102,
+	BFA_STATUS_PORTLOG_ENABLED = 103,
+	BFA_STATUS_PORTLOG_DISABLED = 104,
+	BFA_STATUS_FILE_NOT_FOUND = 105,
+	BFA_STATUS_QOS_FC_ONLY = 106,
+	BFA_STATUS_RLIM_FC_ONLY = 107,
+	BFA_STATUS_CT_SPD = 108,
+	BFA_STATUS_LEDTEST_OP = 109,
+	BFA_STATUS_CEE_NOT_DN = 110,
+	BFA_STATUS_10G_SPD = 111,
+	BFA_STATUS_IM_INV_TEAM_NAME = 112,
+	BFA_STATUS_IM_DUP_TEAM_NAME = 113,
+	BFA_STATUS_IM_ADAPT_ALREADY_IN_TEAM = 114,
+	BFA_STATUS_IM_ADAPT_HAS_VLANS = 115,
+	BFA_STATUS_IM_PVID_MISMATCH = 116,
+	BFA_STATUS_IM_LINK_SPEED_MISMATCH = 117,
+	BFA_STATUS_IM_MTU_MISMATCH = 118,
+	BFA_STATUS_IM_RSS_MISMATCH = 119,
+	BFA_STATUS_IM_HDS_MISMATCH = 120,
+	BFA_STATUS_IM_OFFLOAD_MISMATCH = 121,
+	BFA_STATUS_IM_PORT_PARAMS = 122,
+	BFA_STATUS_IM_PORT_NOT_IN_TEAM = 123,
+	BFA_STATUS_IM_CANNOT_REM_PRI = 124,
+	BFA_STATUS_IM_MAX_PORTS_REACHED = 125,
+	BFA_STATUS_IM_LAST_PORT_DELETE = 126,
+	BFA_STATUS_IM_NO_DRIVER = 127,
+	BFA_STATUS_IM_MAX_VLANS_REACHED = 128,
+	BFA_STATUS_TOMCAT_SPD_NOT_ALLOWED = 129,
+	BFA_STATUS_NO_MINPORT_DRIVER = 130,
+	BFA_STATUS_CARD_TYPE_MISMATCH = 131,
+	BFA_STATUS_BAD_ASICBLK = 132,
+	BFA_STATUS_NO_DRIVER = 133,
+	BFA_STATUS_INVALID_MAC = 134,
+	BFA_STATUS_IM_NO_VLAN = 135,
+	BFA_STATUS_IM_ETH_LB_FAILED = 136,
+	BFA_STATUS_IM_PVID_REMOVE = 137,
+	BFA_STATUS_IM_PVID_EDIT = 138,
+	BFA_STATUS_CNA_NO_BOOT = 139,
+	BFA_STATUS_IM_PVID_NON_ZERO = 140,
+	BFA_STATUS_IM_INETCFG_LOCK_FAILED = 141,
+	BFA_STATUS_IM_GET_INETCFG_FAILED = 142,
+	BFA_STATUS_IM_NOT_BOUND = 143,
+	BFA_STATUS_INSUFFICIENT_PERMS = 144,
+	BFA_STATUS_IM_INV_VLAN_NAME = 145,
+	BFA_STATUS_CMD_NOTSUPP_CNA = 146,
+	BFA_STATUS_IM_PASSTHRU_EDIT = 147,
+	BFA_STATUS_IM_BIND_FAILED = 148,
+	BFA_STATUS_IM_UNBIND_FAILED = 149,
+	BFA_STATUS_IM_PORT_IN_TEAM = 150,
+	BFA_STATUS_IM_VLAN_NOT_FOUND = 151,
+	BFA_STATUS_IM_TEAM_NOT_FOUND = 152,
+	BFA_STATUS_IM_TEAM_CFG_NOT_ALLOWED = 153,
+	BFA_STATUS_PBC = 154,
+	BFA_STATUS_DEVID_MISSING = 155,
+	BFA_STATUS_BAD_FWCFG = 156,
+	BFA_STATUS_CREATE_FILE = 157,
+	BFA_STATUS_INVALID_VENDOR = 158,
+	BFA_STATUS_SFP_NOT_READY = 159,
+	BFA_STATUS_FLASH_UNINIT = 160,
+	BFA_STATUS_FLASH_EMPTY = 161,
+	BFA_STATUS_FLASH_CKFAIL = 162,
+	BFA_STATUS_TRUNK_UNSUPP = 163,
+	BFA_STATUS_TRUNK_ENABLED = 164,
+	BFA_STATUS_TRUNK_DISABLED  = 165,
+	BFA_STATUS_TRUNK_ERROR_TRL_ENABLED = 166,
+	BFA_STATUS_BOOT_CODE_UPDATED = 167,
+	BFA_STATUS_BOOT_VERSION = 168,
+	BFA_STATUS_CARDTYPE_MISSING = 169,
+	BFA_STATUS_INVALID_CARDTYPE = 170,
+	BFA_STATUS_NO_TOPOLOGY_FOR_CNA = 171,
+	BFA_STATUS_IM_VLAN_OVER_TEAM_DELETE_FAILED = 172,
+	BFA_STATUS_ETHBOOT_ENABLED  = 173,
+	BFA_STATUS_ETHBOOT_DISABLED  = 174,
+	BFA_STATUS_IOPROFILE_OFF = 175,
+	BFA_STATUS_NO_PORT_INSTANCE = 176,
+	BFA_STATUS_BOOT_CODE_TIMEDOUT = 177,
+	BFA_STATUS_NO_VPORT_LOCK = 178,
+	BFA_STATUS_VPORT_NO_CNFG = 179,
+	BFA_STATUS_MAX_VAL
+};
+
+enum bfa_eproto_status {
+	BFA_EPROTO_BAD_ACCEPT = 0,
+	BFA_EPROTO_UNKNOWN_RSP = 1
+};
+
+#endif /* __BFA_DEFS_STATUS_H__ */
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
new file mode 100644
index 0000000..e94e5aa9
--- /dev/null
+++ b/drivers/net/bna/bfa_ioc.c
@@ -0,0 +1,1732 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#include "bfa_ioc.h"
+#include "cna.h"
+#include "bfi.h"
+#include "bfi_ctreg.h"
+#include "bfa_defs.h"
+
+/**
+ * IOC local definitions
+ */
+
+#define bfa_ioc_timer_start(__ioc)					\
+	mod_timer(&(__ioc)->ioc_timer, jiffies +	\
+			msecs_to_jiffies(BFA_IOC_TOV))
+#define bfa_ioc_timer_stop(__ioc)   del_timer(&(__ioc)->ioc_timer)
+
+#define bfa_ioc_recovery_timer_start(__ioc)				\
+	mod_timer(&(__ioc)->ioc_timer, jiffies +	\
+			msecs_to_jiffies(BFA_IOC_TOV_RECOVER))
+
+#define bfa_sem_timer_start(__ioc)					\
+	mod_timer(&(__ioc)->sem_timer, jiffies +	\
+			msecs_to_jiffies(BFA_IOC_HWSEM_TOV))
+#define bfa_sem_timer_stop(__ioc)	del_timer(&(__ioc)->sem_timer)
+
+#define bfa_hb_timer_start(__ioc)					\
+	mod_timer(&(__ioc)->hb_timer, jiffies +		\
+			msecs_to_jiffies(BFA_IOC_HB_TOV))
+#define bfa_hb_timer_stop(__ioc)	del_timer(&(__ioc)->hb_timer)
+
+/**
+ * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
+ */
+
+#define bfa_ioc_firmware_lock(__ioc)			\
+			((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
+#define bfa_ioc_firmware_unlock(__ioc)			\
+			((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
+#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
+#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
+#define bfa_ioc_notify_hbfail(__ioc)			\
+			((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc))
+
+#define bfa_ioc_is_optrom(__ioc)	\
+	(bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
+
+#define bfa_ioc_mbox_cmd_pending(__ioc)		\
+			(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
+			readl((__ioc)->ioc_regs.hfn_mbox_cmd))
+
+static bool bfa_nw_auto_recover = true;
+
+/*
+ * forward declarations
+ */
+static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);
+static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);
+static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);
+static void bfa_ioc_send_enable(struct bfa_ioc *ioc);
+static void bfa_ioc_send_disable(struct bfa_ioc *ioc);
+static void bfa_ioc_send_getattr(struct bfa_ioc *ioc);
+static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc);
+static void bfa_ioc_hb_stop(struct bfa_ioc *ioc);
+static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force);
+static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc);
+static void bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc);
+static void bfa_ioc_recover(struct bfa_ioc *ioc);
+static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
+static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
+static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
+static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
+			 u32 boot_param);
+static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr);
+static u32 bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr);
+static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc,
+						char *serial_num);
+static void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc,
+						char *fw_ver);
+static void bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc,
+						char *chip_rev);
+static void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc,
+						char *optrom_ver);
+static void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc,
+						char *manufacturer);
+static void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model);
+static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc);
+static mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc);
+
+/**
+ * IOC state machine events
+ */
+enum ioc_event {
+	IOC_E_ENABLE		= 1,	/*!< IOC enable request		*/
+	IOC_E_DISABLE		= 2,	/*!< IOC disable request	*/
+	IOC_E_TIMEOUT		= 3,	/*!< f/w response timeout	*/
+	IOC_E_FWREADY		= 4,	/*!< f/w initialization done	*/
+	IOC_E_FWRSP_GETATTR	= 5,	/*!< IOC get attribute response	*/
+	IOC_E_FWRSP_ENABLE	= 6,	/*!< enable f/w response	*/
+	IOC_E_FWRSP_DISABLE	= 7,	/*!< disable f/w response	*/
+	IOC_E_HBFAIL		= 8,	/*!< heartbeat failure		*/
+	IOC_E_HWERROR		= 9,	/*!< hardware error interrupt	*/
+	IOC_E_SEMLOCKED		= 10,	/*!< h/w semaphore is locked	*/
+	IOC_E_DETACH		= 11,	/*!< driver detach cleanup	*/
+};
+
+bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
+
+static struct bfa_sm_table ioc_sm_table[] = {
+	{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
+	{BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH},
+	{BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH},
+	{BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT},
+	{BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT},
+	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT},
+	{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
+	{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
+	{BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
+	{BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL},
+	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
+	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
+};
+
+/**
+ * Reset entry actions -- initialize state machine
+ */
+static void
+bfa_ioc_sm_reset_entry(struct bfa_ioc *ioc)
+{
+	ioc->retry_count = 0;
+	ioc->auto_recover = bfa_nw_auto_recover;
+}
+
+/**
+ * Beginning state. IOC is in reset state.
+ */
+static void
+bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_ENABLE:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_disable_comp(ioc);
+		break;
+
+	case IOC_E_DETACH:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Semaphore should be acquired for version check.
+ */
+static void
+bfa_ioc_sm_fwcheck_entry(struct bfa_ioc *ioc)
+{
+	bfa_ioc_hw_sem_get(ioc);
+}
+
+/**
+ * Awaiting h/w semaphore to continue with version check.
+ */
+static void
+bfa_ioc_sm_fwcheck(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_SEMLOCKED:
+		if (bfa_ioc_firmware_lock(ioc)) {
+			ioc->retry_count = 0;
+			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+		} else {
+			bfa_nw_ioc_hw_sem_release(ioc);
+			bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch);
+		}
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_disable_comp(ioc);
+		/* fall through */
+
+	case IOC_E_DETACH:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		break;
+
+	case IOC_E_FWREADY:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Notify enable completion callback and generate mismatch AEN.
+ */
+static void
+bfa_ioc_sm_mismatch_entry(struct bfa_ioc *ioc)
+{
+	/**
+	 * Provide enable completion callback and AEN notification only once.
+	 */
+	if (ioc->retry_count == 0)
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+	ioc->retry_count++;
+	bfa_ioc_timer_start(ioc);
+}
+
+/**
+ * Awaiting firmware version match.
+ */
+static void
+bfa_ioc_sm_mismatch(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_TIMEOUT:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_disable_comp(ioc);
+		/* fall through */
+
+	case IOC_E_DETACH:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		break;
+
+	case IOC_E_FWREADY:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Request for semaphore.
+ */
+static void
+bfa_ioc_sm_semwait_entry(struct bfa_ioc *ioc)
+{
+	bfa_ioc_hw_sem_get(ioc);
+}
+
+/**
+ * Awaiting semaphore for h/w initialzation.
+ */
+static void
+bfa_ioc_sm_semwait(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_SEMLOCKED:
+		ioc->retry_count = 0;
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+static void
+bfa_ioc_sm_hwinit_entry(struct bfa_ioc *ioc)
+{
+	bfa_ioc_timer_start(ioc);
+	bfa_ioc_reset(ioc, false);
+}
+
+/**
+ * @brief
+ * Hardware is being initialized. Interrupts are enabled.
+ * Holding hardware semaphore lock.
+ */
+static void
+bfa_ioc_sm_hwinit(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_FWREADY:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
+		break;
+
+	case IOC_E_HWERROR:
+		bfa_ioc_timer_stop(ioc);
+		/* fall through */
+
+	case IOC_E_TIMEOUT:
+		ioc->retry_count++;
+		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
+			bfa_ioc_timer_start(ioc);
+			bfa_ioc_reset(ioc, true);
+			break;
+		}
+
+		bfa_nw_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_nw_ioc_hw_sem_release(ioc);
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+static void
+bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc)
+{
+	bfa_ioc_timer_start(ioc);
+	bfa_ioc_send_enable(ioc);
+}
+
+/**
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
+ */
+static void
+bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_FWRSP_ENABLE:
+		bfa_ioc_timer_stop(ioc);
+		bfa_nw_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+		break;
+
+	case IOC_E_HWERROR:
+		bfa_ioc_timer_stop(ioc);
+		/* fall through */
+
+	case IOC_E_TIMEOUT:
+		ioc->retry_count++;
+		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
+			writel(BFI_IOC_UNINIT,
+				      ioc->ioc_regs.ioc_fwstate);
+			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+			break;
+		}
+
+		bfa_nw_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_timer_stop(ioc);
+		bfa_nw_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	case IOC_E_FWREADY:
+		bfa_ioc_send_enable(ioc);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+static void
+bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc)
+{
+	bfa_ioc_timer_start(ioc);
+	bfa_ioc_send_getattr(ioc);
+}
+
+/**
+ * @brief
+ * IOC configuration in progress. Timer is active.
+ */
+static void
+bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_FWRSP_GETATTR:
+		bfa_ioc_timer_stop(ioc);
+		bfa_ioc_check_attr_wwns(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+		break;
+
+	case IOC_E_HWERROR:
+		bfa_ioc_timer_stop(ioc);
+		/* fall through */
+
+	case IOC_E_TIMEOUT:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+static void
+bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
+{
+	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
+	bfa_ioc_hb_monitor(ioc);
+}
+
+static void
+bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_ENABLE:
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_ioc_hb_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
+
+	case IOC_E_HWERROR:
+	case IOC_E_FWREADY:
+		/**
+		 * Hard error or IOC recovery by other function.
+		 * Treat it same as heartbeat failure.
+		 */
+		bfa_ioc_hb_stop(ioc);
+		/* !!! fall through !!! */
+
+	case IOC_E_HBFAIL:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+static void
+bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)
+{
+	bfa_ioc_timer_start(ioc);
+	bfa_ioc_send_disable(ioc);
+}
+
+/**
+ * IOC is being disabled
+ */
+static void
+bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_FWRSP_DISABLE:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	case IOC_E_HWERROR:
+		bfa_ioc_timer_stop(ioc);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case IOC_E_TIMEOUT:
+		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * IOC disable completion entry.
+ */
+static void
+bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)
+{
+	bfa_ioc_disable_comp(ioc);
+}
+
+static void
+bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_ENABLE:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+		break;
+
+	case IOC_E_DISABLE:
+		ioc->cbfn->disable_cbfn(ioc->bfa);
+		break;
+
+	case IOC_E_FWREADY:
+		break;
+
+	case IOC_E_DETACH:
+		bfa_ioc_firmware_unlock(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+static void
+bfa_ioc_sm_initfail_entry(struct bfa_ioc *ioc)
+{
+	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+	bfa_ioc_timer_start(ioc);
+}
+
+/**
+ * @brief
+ * Hardware initialization failed.
+ */
+static void
+bfa_ioc_sm_initfail(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+	case IOC_E_DISABLE:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	case IOC_E_DETACH:
+		bfa_ioc_timer_stop(ioc);
+		bfa_ioc_firmware_unlock(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		break;
+
+	case IOC_E_TIMEOUT:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+static void
+bfa_ioc_sm_hbfail_entry(struct bfa_ioc *ioc)
+{
+	struct list_head			*qe;
+	struct bfa_ioc_hbfail_notify *notify;
+
+	/**
+	 * Mark IOC as failed in hardware and stop firmware.
+	 */
+	bfa_ioc_lpu_stop(ioc);
+	writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+
+	/**
+	 * Notify other functions on HB failure.
+	 */
+	bfa_ioc_notify_hbfail(ioc);
+
+	/**
+	 * Notify driver and common modules registered for notification.
+	 */
+	ioc->cbfn->hbfail_cbfn(ioc->bfa);
+	list_for_each(qe, &ioc->hb_notify_q) {
+		notify = (struct bfa_ioc_hbfail_notify *) qe;
+		notify->cbfn(notify->cbarg);
+	}
+
+	/**
+	 * Flush any queued up mailbox requests.
+	 */
+	bfa_ioc_mbox_hbfail(ioc);
+
+	/**
+	 * Trigger auto-recovery after a delay.
+	 */
+	if (ioc->auto_recover)
+		mod_timer(&ioc->ioc_timer, jiffies +
+			msecs_to_jiffies(BFA_IOC_TOV_RECOVER));
+}
+
+/**
+ * @brief
+ * IOC heartbeat failure.
+ */
+static void
+bfa_ioc_sm_hbfail(struct bfa_ioc *ioc, enum ioc_event event)
+{
+	switch (event) {
+
+	case IOC_E_ENABLE:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		break;
+
+	case IOC_E_DISABLE:
+		if (ioc->auto_recover)
+			bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		break;
+
+	case IOC_E_TIMEOUT:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+		break;
+
+	case IOC_E_FWREADY:
+		/**
+		 * Recovery is already initiated by other function.
+		 */
+		break;
+
+	case IOC_E_HWERROR:
+		/*
+		 * HB failure notification, ignore.
+		 */
+		break;
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * BFA IOC private functions
+ */
+
+static void
+bfa_ioc_disable_comp(struct bfa_ioc *ioc)
+{
+	struct list_head			*qe;
+	struct bfa_ioc_hbfail_notify *notify;
+
+	ioc->cbfn->disable_cbfn(ioc->bfa);
+
+	/**
+	 * Notify common modules registered for notification.
+	 */
+	list_for_each(qe, &ioc->hb_notify_q) {
+		notify = (struct bfa_ioc_hbfail_notify *) qe;
+		notify->cbfn(notify->cbarg);
+	}
+}
+
+void
+bfa_nw_ioc_sem_timeout(void *ioc_arg)
+{
+	struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
+
+	bfa_ioc_hw_sem_get(ioc);
+}
+
+bool
+bfa_nw_ioc_sem_get(void __iomem *sem_reg)
+{
+	u32 r32;
+	int cnt = 0;
+#define BFA_SEM_SPINCNT	3000
+
+	r32 = readl(sem_reg);
+
+	while (r32 && (cnt < BFA_SEM_SPINCNT)) {
+		cnt++;
+		udelay(2);
+		r32 = readl(sem_reg);
+	}
+
+	if (r32 == 0)
+		return true;
+
+	BUG_ON(!(cnt < BFA_SEM_SPINCNT));
+	return false;
+}
+
+void
+bfa_nw_ioc_sem_release(void __iomem *sem_reg)
+{
+	writel(1, sem_reg);
+}
+
+static void
+bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
+{
+	u32	r32;
+
+	/**
+	 * First read to the semaphore register will return 0, subsequent reads
+	 * will return 1. Semaphore is released by writing 1 to the register
+	 */
+	r32 = readl(ioc->ioc_regs.ioc_sem_reg);
+	if (r32 == 0) {
+		bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED);
+		return;
+	}
+
+	mod_timer(&ioc->sem_timer, jiffies +
+		msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
+}
+
+void
+bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc)
+{
+	writel(1, ioc->ioc_regs.ioc_sem_reg);
+}
+
+static void
+bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc)
+{
+	del_timer(&ioc->sem_timer);
+}
+
+/**
+ * @brief
+ * Initialize LPU local memory (aka secondary memory / SRAM)
+ */
+static void
+bfa_ioc_lmem_init(struct bfa_ioc *ioc)
+{
+	u32	pss_ctl;
+	int		i;
+#define PSS_LMEM_INIT_TIME  10000
+
+	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
+	pss_ctl &= ~__PSS_LMEM_RESET;
+	pss_ctl |= __PSS_LMEM_INIT_EN;
+
+	/*
+	 * i2c workaround 12.5khz clock
+	 */
+	pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
+	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
+
+	/**
+	 * wait for memory initialization to be complete
+	 */
+	i = 0;
+	do {
+		pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
+		i++;
+	} while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
+
+	/**
+	 * If memory initialization is not successful, IOC timeout will catch
+	 * such failures.
+	 */
+	BUG_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));
+
+	pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
+	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
+}
+
+static void
+bfa_ioc_lpu_start(struct bfa_ioc *ioc)
+{
+	u32	pss_ctl;
+
+	/**
+	 * Take processor out of reset.
+	 */
+	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
+	pss_ctl &= ~__PSS_LPU0_RESET;
+
+	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
+}
+
+static void
+bfa_ioc_lpu_stop(struct bfa_ioc *ioc)
+{
+	u32	pss_ctl;
+
+	/**
+	 * Put processors in reset.
+	 */
+	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
+	pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
+
+	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
+}
+
+/**
+ * Get driver and firmware versions.
+ */
+void
+bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
+{
+	u32	pgnum, pgoff;
+	u32	loff = 0;
+	int		i;
+	u32	*fwsig = (u32 *) fwhdr;
+
+	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
+
+	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32));
+	     i++) {
+		fwsig[i] =
+			swab32(readl((loff) + (ioc->ioc_regs.smem_page_start)));
+		loff += sizeof(u32);
+	}
+}
+
+/**
+ * Returns TRUE if same.
+ */
+bool
+bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
+{
+	struct bfi_ioc_image_hdr *drv_fwhdr;
+	int i;
+
+	drv_fwhdr = (struct bfi_ioc_image_hdr *)
+		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+
+	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
+		if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i])
+			return false;
+	}
+
+	return true;
+}
+
+/**
+ * Return true if current running version is valid. Firmware signature and
+ * execution context (driver/bios) must match.
+ */
+static bool
+bfa_ioc_fwver_valid(struct bfa_ioc *ioc)
+{
+	struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr;
+
+	/**
+	 * If bios/efi boot (flash based) -- return true
+	 */
+	if (bfa_ioc_is_optrom(ioc))
+		return true;
+
+	bfa_nw_ioc_fwver_get(ioc, &fwhdr);
+	drv_fwhdr = (struct bfi_ioc_image_hdr *)
+		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+
+	if (fwhdr.signature != drv_fwhdr->signature)
+		return false;
+
+	if (fwhdr.exec != drv_fwhdr->exec)
+		return false;
+
+	return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr);
+}
+
+/**
+ * Conditionally flush any pending message from firmware at start.
+ */
+static void
+bfa_ioc_msgflush(struct bfa_ioc *ioc)
+{
+	u32	r32;
+
+	r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
+	if (r32)
+		writel(1, ioc->ioc_regs.lpu_mbox_cmd);
+}
+
+/**
+ * @img ioc_init_logic.jpg
+ */
+static void
+bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
+{
+	enum bfi_ioc_state ioc_fwstate;
+	bool fwvalid;
+
+	ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+	if (force)
+		ioc_fwstate = BFI_IOC_UNINIT;
+
+	/**
+	 * check if firmware is valid
+	 */
+	fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
+		false : bfa_ioc_fwver_valid(ioc);
+
+	if (!fwvalid) {
+		bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+		return;
+	}
+
+	/**
+	 * If hardware initialization is in progress (initialized by other IOC),
+	 * just wait for an initialization completion interrupt.
+	 */
+	if (ioc_fwstate == BFI_IOC_INITING) {
+		ioc->cbfn->reset_cbfn(ioc->bfa);
+		return;
+	}
+
+	/**
+	 * If IOC function is disabled and firmware version is same,
+	 * just re-enable IOC.
+	 *
+	 * If option rom, IOC must not be in operational state. With
+	 * convergence, IOC will be in operational state when 2nd driver
+	 * is loaded.
+	 */
+	if (ioc_fwstate == BFI_IOC_DISABLED ||
+	    (!bfa_ioc_is_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
+		/**
+		 * When using MSI-X any pending firmware ready event should
+		 * be flushed. Otherwise MSI-X interrupts are not delivered.
+		 */
+		bfa_ioc_msgflush(ioc);
+		ioc->cbfn->reset_cbfn(ioc->bfa);
+		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+		return;
+	}
+
+	/**
+	 * Initialize the h/w for any other states.
+	 */
+	bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+}
+
+void
+bfa_nw_ioc_timeout(void *ioc_arg)
+{
+	struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
+
+	bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
+}
+
+static void
+bfa_ioc_mbox_send(struct bfa_ioc *ioc, void *ioc_msg, int len)
+{
+	u32 *msgp = (u32 *) ioc_msg;
+	u32 i;
+
+	BUG_ON(!(len <= BFI_IOC_MSGLEN_MAX));
+
+	/*
+	 * first write msg to mailbox registers
+	 */
+	for (i = 0; i < len / sizeof(u32); i++)
+		writel(cpu_to_le32(msgp[i]),
+			      ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
+
+	for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
+		writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
+
+	/*
+	 * write 1 to mailbox CMD to trigger LPU event
+	 */
+	writel(1, ioc->ioc_regs.hfn_mbox_cmd);
+	(void) readl(ioc->ioc_regs.hfn_mbox_cmd);
+}
+
+static void
+bfa_ioc_send_enable(struct bfa_ioc *ioc)
+{
+	struct bfi_ioc_ctrl_req enable_req;
+	struct timeval tv;
+
+	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
+		    bfa_ioc_portid(ioc));
+	enable_req.ioc_class = ioc->ioc_mc;
+	do_gettimeofday(&tv);
+	enable_req.tv_sec = ntohl(tv.tv_sec);
+	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req));
+}
+
+static void
+bfa_ioc_send_disable(struct bfa_ioc *ioc)
+{
+	struct bfi_ioc_ctrl_req disable_req;
+
+	bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
+		    bfa_ioc_portid(ioc));
+	bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req));
+}
+
+static void
+bfa_ioc_send_getattr(struct bfa_ioc *ioc)
+{
+	struct bfi_ioc_getattr_req attr_req;
+
+	bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
+		    bfa_ioc_portid(ioc));
+	bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
+	bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
+}
+
+void
+bfa_nw_ioc_hb_check(void *cbarg)
+{
+	struct bfa_ioc *ioc = cbarg;
+	u32	hb_count;
+
+	hb_count = readl(ioc->ioc_regs.heartbeat);
+	if (ioc->hb_count == hb_count) {
+		pr_crit("Firmware heartbeat failure at %d", hb_count);
+		bfa_ioc_recover(ioc);
+		return;
+	} else {
+		ioc->hb_count = hb_count;
+	}
+
+	bfa_ioc_mbox_poll(ioc);
+	mod_timer(&ioc->hb_timer, jiffies +
+		msecs_to_jiffies(BFA_IOC_HB_TOV));
+}
+
+static void
+bfa_ioc_hb_monitor(struct bfa_ioc *ioc)
+{
+	ioc->hb_count = readl(ioc->ioc_regs.heartbeat);
+	mod_timer(&ioc->hb_timer, jiffies +
+		msecs_to_jiffies(BFA_IOC_HB_TOV));
+}
+
+static void
+bfa_ioc_hb_stop(struct bfa_ioc *ioc)
+{
+	del_timer(&ioc->hb_timer);
+}
+
+/**
+ * @brief
+ *	Initiate a full firmware download.
+ */
+static void
+bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
+		    u32 boot_param)
+{
+	u32 *fwimg;
+	u32 pgnum, pgoff;
+	u32 loff = 0;
+	u32 chunkno = 0;
+	u32 i;
+
+	/**
+	 * Initialize LMEM first before code download
+	 */
+	bfa_ioc_lmem_init(ioc);
+
+	/**
+	 * Flash based firmware boot
+	 */
+	if (bfa_ioc_is_optrom(ioc))
+		boot_type = BFI_BOOT_TYPE_FLASH;
+	fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
+
+	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+
+	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
+
+	for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
+		if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
+			chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
+			fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
+					BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
+		}
+
+		/**
+		 * write smem
+		 */
+		writel((swab32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)])),
+			      ((ioc->ioc_regs.smem_page_start) + (loff)));
+
+		loff += sizeof(u32);
+
+		/**
+		 * handle page offset wrap around
+		 */
+		loff = PSS_SMEM_PGOFF(loff);
+		if (loff == 0) {
+			pgnum++;
+			writel(pgnum,
+				      ioc->ioc_regs.host_page_num_fn);
+		}
+	}
+
+	writel(bfa_ioc_smem_pgnum(ioc, 0),
+		      ioc->ioc_regs.host_page_num_fn);
+
+	/*
+	 * Set boot type and boot param at the end.
+	*/
+	writel((swab32(swab32(boot_type))), ((ioc->ioc_regs.smem_page_start)
+			+ (BFI_BOOT_TYPE_OFF)));
+	writel((swab32(swab32(boot_param))), ((ioc->ioc_regs.smem_page_start)
+			+ (BFI_BOOT_PARAM_OFF)));
+}
+
+static void
+bfa_ioc_reset(struct bfa_ioc *ioc, bool force)
+{
+	bfa_ioc_hwinit(ioc, force);
+}
+
+/**
+ * @brief
+ * Update BFA configuration from firmware configuration.
+ */
+static void
+bfa_ioc_getattr_reply(struct bfa_ioc *ioc)
+{
+	struct bfi_ioc_attr *attr = ioc->attr;
+
+	attr->adapter_prop  = ntohl(attr->adapter_prop);
+	attr->card_type     = ntohl(attr->card_type);
+	attr->maxfrsize	    = ntohs(attr->maxfrsize);
+
+	bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
+}
+
+/**
+ * Attach time initialization of mbox logic.
+ */
+static void
+bfa_ioc_mbox_attach(struct bfa_ioc *ioc)
+{
+	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+	int	mc;
+
+	INIT_LIST_HEAD(&mod->cmd_q);
+	for (mc = 0; mc < BFI_MC_MAX; mc++) {
+		mod->mbhdlr[mc].cbfn = NULL;
+		mod->mbhdlr[mc].cbarg = ioc->bfa;
+	}
+}
+
+/**
+ * Mbox poll timer -- restarts any pending mailbox requests.
+ */
+static void
+bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
+{
+	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+	struct bfa_mbox_cmd *cmd;
+	u32			stat;
+
+	/**
+	 * If no command pending, do nothing
+	 */
+	if (list_empty(&mod->cmd_q))
+		return;
+
+	/**
+	 * If previous command is not yet fetched by firmware, do nothing
+	 */
+	stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
+	if (stat)
+		return;
+
+	/**
+	 * Enqueue command to firmware.
+	 */
+	bfa_q_deq(&mod->cmd_q, &cmd);
+	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+}
+
+/**
+ * Cleanup any pending requests.
+ */
+static void
+bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc)
+{
+	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+	struct bfa_mbox_cmd *cmd;
+
+	while (!list_empty(&mod->cmd_q))
+		bfa_q_deq(&mod->cmd_q, &cmd);
+}
+
+/**
+ * IOC public
+ */
+static enum bfa_status
+bfa_ioc_pll_init(struct bfa_ioc *ioc)
+{
+	/*
+	 *  Hold semaphore so that nobody can access the chip during init.
+	 */
+	bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
+
+	bfa_ioc_pll_init_asic(ioc);
+
+	ioc->pllinit = true;
+	/*
+	 *  release semaphore.
+	 */
+	bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Interface used by diag module to do firmware boot with memory test
+ * as the entry vector.
+ */
+static void
+bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param)
+{
+	void __iomem *rb;
+
+	bfa_ioc_stats(ioc, ioc_boots);
+
+	if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
+		return;
+
+	/**
+	 * Initialize IOC state of all functions on a chip reset.
+	 */
+	rb = ioc->pcidev.pci_bar_kva;
+	if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
+		writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
+		writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
+	} else {
+		writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
+		writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
+	}
+
+	bfa_ioc_msgflush(ioc);
+	bfa_ioc_download_fw(ioc, boot_type, boot_param);
+
+	/**
+	 * Enable interrupts just before starting LPU
+	 */
+	ioc->cbfn->reset_cbfn(ioc->bfa);
+	bfa_ioc_lpu_start(ioc);
+}
+
+/**
+ * Enable/disable IOC failure auto recovery.
+ */
+void
+bfa_nw_ioc_auto_recover(bool auto_recover)
+{
+	bfa_nw_auto_recover = auto_recover;
+}
+
+static void
+bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)
+{
+	u32	*msgp = mbmsg;
+	u32	r32;
+	int		i;
+
+	/**
+	 * read the MBOX msg
+	 */
+	for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
+	     i++) {
+		r32 = readl(ioc->ioc_regs.lpu_mbox +
+				   i * sizeof(u32));
+		msgp[i] = htonl(r32);
+	}
+
+	/**
+	 * turn off mailbox interrupt by clearing mailbox status
+	 */
+	writel(1, ioc->ioc_regs.lpu_mbox_cmd);
+	readl(ioc->ioc_regs.lpu_mbox_cmd);
+}
+
+static void
+bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
+{
+	union bfi_ioc_i2h_msg_u	*msg;
+
+	msg = (union bfi_ioc_i2h_msg_u *) m;
+
+	bfa_ioc_stats(ioc, ioc_isrs);
+
+	switch (msg->mh.msg_id) {
+	case BFI_IOC_I2H_HBEAT:
+		break;
+
+	case BFI_IOC_I2H_READY_EVENT:
+		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+		break;
+
+	case BFI_IOC_I2H_ENABLE_REPLY:
+		bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE);
+		break;
+
+	case BFI_IOC_I2H_DISABLE_REPLY:
+		bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE);
+		break;
+
+	case BFI_IOC_I2H_GETATTR_REPLY:
+		bfa_ioc_getattr_reply(ioc);
+		break;
+
+	default:
+		BUG_ON(1);
+	}
+}
+
+/**
+ * IOC attach time initialization and setup.
+ *
+ * @param[in]	ioc	memory for IOC
+ * @param[in]	bfa	driver instance structure
+ */
+void
+bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn)
+{
+	ioc->bfa	= bfa;
+	ioc->cbfn	= cbfn;
+	ioc->fcmode	= false;
+	ioc->pllinit	= false;
+	ioc->dbg_fwsave_once = true;
+
+	bfa_ioc_mbox_attach(ioc);
+	INIT_LIST_HEAD(&ioc->hb_notify_q);
+
+	bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+}
+
+/**
+ * Driver detach time IOC cleanup.
+ */
+void
+bfa_nw_ioc_detach(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_DETACH);
+}
+
+/**
+ * Setup IOC PCI properties.
+ *
+ * @param[in]	pcidev	PCI device information for this IOC
+ */
+void
+bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
+		 enum bfi_mclass mc)
+{
+	ioc->ioc_mc	= mc;
+	ioc->pcidev	= *pcidev;
+	ioc->ctdev	= bfa_asic_id_ct(ioc->pcidev.device_id);
+	ioc->cna	= ioc->ctdev && !ioc->fcmode;
+
+	bfa_nw_ioc_set_ct_hwif(ioc);
+
+	bfa_ioc_map_port(ioc);
+	bfa_ioc_reg_init(ioc);
+}
+
+/**
+ * Initialize IOC dma memory
+ *
+ * @param[in]	dm_kva	kernel virtual address of IOC dma memory
+ * @param[in]	dm_pa	physical address of IOC dma memory
+ */
+void
+bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc,  u8 *dm_kva, u64 dm_pa)
+{
+	/**
+	 * dma memory for firmware attribute
+	 */
+	ioc->attr_dma.kva = dm_kva;
+	ioc->attr_dma.pa = dm_pa;
+	ioc->attr = (struct bfi_ioc_attr *) dm_kva;
+}
+
+/**
+ * Return size of dma memory required.
+ */
+u32
+bfa_nw_ioc_meminfo(void)
+{
+	return roundup(sizeof(struct bfi_ioc_attr), BFA_DMA_ALIGN_SZ);
+}
+
+void
+bfa_nw_ioc_enable(struct bfa_ioc *ioc)
+{
+	bfa_ioc_stats(ioc, ioc_enables);
+	ioc->dbg_fwsave_once = true;
+
+	bfa_fsm_send_event(ioc, IOC_E_ENABLE);
+}
+
+void
+bfa_nw_ioc_disable(struct bfa_ioc *ioc)
+{
+	bfa_ioc_stats(ioc, ioc_disables);
+	bfa_fsm_send_event(ioc, IOC_E_DISABLE);
+}
+
+static u32
+bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr)
+{
+	return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
+}
+
+static u32
+bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr)
+{
+	return PSS_SMEM_PGOFF(fmaddr);
+}
+
+/**
+ * Register mailbox message handler function, to be called by common modules
+ */
+void
+bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
+		    bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
+{
+	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+
+	mod->mbhdlr[mc].cbfn	= cbfn;
+	mod->mbhdlr[mc].cbarg = cbarg;
+}
+
+/**
+ * Queue a mailbox command request to firmware. Waits if mailbox is busy.
+ * Responsibility of caller to serialize
+ *
+ * @param[in]	ioc	IOC instance
+ * @param[i]	cmd	Mailbox command
+ */
+void
+bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
+{
+	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+	u32			stat;
+
+	/**
+	 * If a previous command is pending, queue new command
+	 */
+	if (!list_empty(&mod->cmd_q)) {
+		list_add_tail(&cmd->qe, &mod->cmd_q);
+		return;
+	}
+
+	/**
+	 * If mailbox is busy, queue command for poll timer
+	 */
+	stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
+	if (stat) {
+		list_add_tail(&cmd->qe, &mod->cmd_q);
+		return;
+	}
+
+	/**
+	 * mailbox is free -- queue command to firmware
+	 */
+	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+}
+
+/**
+ * Handle mailbox interrupts
+ */
+void
+bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
+{
+	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+	struct bfi_mbmsg m;
+	int				mc;
+
+	bfa_ioc_msgget(ioc, &m);
+
+	/**
+	 * Treat IOC message class as special.
+	 */
+	mc = m.mh.msg_class;
+	if (mc == BFI_MC_IOC) {
+		bfa_ioc_isr(ioc, &m);
+		return;
+	}
+
+	if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
+		return;
+
+	mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
+}
+
+void
+bfa_nw_ioc_error_isr(struct bfa_ioc *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_HWERROR);
+}
+
+/**
+ * Add to IOC heartbeat failure notification queue. To be used by common
+ * modules such as cee, port, diag.
+ */
+void
+bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc,
+			struct bfa_ioc_hbfail_notify *notify)
+{
+	list_add_tail(&notify->qe, &ioc->hb_notify_q);
+}
+
+#define BFA_MFG_NAME "Brocade"
+static void
+bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc,
+			 struct bfa_adapter_attr *ad_attr)
+{
+	struct bfi_ioc_attr *ioc_attr;
+
+	ioc_attr = ioc->attr;
+
+	bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);
+	bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);
+	bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);
+	bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);
+	memcpy(&ad_attr->vpd, &ioc_attr->vpd,
+		      sizeof(struct bfa_mfg_vpd));
+
+	ad_attr->nports = bfa_ioc_get_nports(ioc);
+	ad_attr->max_speed = bfa_ioc_speed_sup(ioc);
+
+	bfa_ioc_get_adapter_model(ioc, ad_attr->model);
+	/* For now, model descr uses same model string */
+	bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);
+
+	ad_attr->card_type = ioc_attr->card_type;
+	ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);
+
+	if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
+		ad_attr->prototype = 1;
+	else
+		ad_attr->prototype = 0;
+
+	ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
+	ad_attr->mac  = bfa_nw_ioc_get_mac(ioc);
+
+	ad_attr->pcie_gen = ioc_attr->pcie_gen;
+	ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
+	ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
+	ad_attr->asic_rev = ioc_attr->asic_rev;
+
+	bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
+
+	ad_attr->cna_capable = ioc->cna;
+	ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
+}
+
+static enum bfa_ioc_type
+bfa_ioc_get_type(struct bfa_ioc *ioc)
+{
+	if (!ioc->ctdev || ioc->fcmode)
+		return BFA_IOC_TYPE_FC;
+	else if (ioc->ioc_mc == BFI_MC_IOCFC)
+		return BFA_IOC_TYPE_FCoE;
+	else if (ioc->ioc_mc == BFI_MC_LL)
+		return BFA_IOC_TYPE_LL;
+	else {
+		BUG_ON(!(ioc->ioc_mc == BFI_MC_LL));
+		return BFA_IOC_TYPE_LL;
+	}
+}
+
+static void
+bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num)
+{
+	memset(serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
+	memcpy(serial_num,
+			(void *)ioc->attr->brcd_serialnum,
+			BFA_ADAPTER_SERIAL_NUM_LEN);
+}
+
+static void
+bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver)
+{
+	memset(fw_ver, 0, BFA_VERSION_LEN);
+	memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
+}
+
+static void
+bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev)
+{
+	BUG_ON(!(chip_rev));
+
+	memset(chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
+
+	chip_rev[0] = 'R';
+	chip_rev[1] = 'e';
+	chip_rev[2] = 'v';
+	chip_rev[3] = '-';
+	chip_rev[4] = ioc->attr->asic_rev;
+	chip_rev[5] = '\0';
+}
+
+static void
+bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)
+{
+	memset(optrom_ver, 0, BFA_VERSION_LEN);
+	memcpy(optrom_ver, ioc->attr->optrom_version,
+		      BFA_VERSION_LEN);
+}
+
+static void
+bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer)
+{
+	memset(manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
+	memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
+}
+
+static void
+bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model)
+{
+	struct bfi_ioc_attr *ioc_attr;
+
+	BUG_ON(!(model));
+	memset(model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
+
+	ioc_attr = ioc->attr;
+
+	/**
+	 * model name
+	 */
+	snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
+		BFA_MFG_NAME, ioc_attr->card_type);
+}
+
+static enum bfa_ioc_state
+bfa_ioc_get_state(struct bfa_ioc *ioc)
+{
+	return bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+}
+
+void
+bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr)
+{
+	memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr));
+
+	ioc_attr->state = bfa_ioc_get_state(ioc);
+	ioc_attr->port_id = ioc->port_id;
+
+	ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
+
+	bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
+
+	ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
+	ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
+	bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
+}
+
+/**
+ * WWN public
+ */
+static u64
+bfa_ioc_get_pwwn(struct bfa_ioc *ioc)
+{
+	return ioc->attr->pwwn;
+}
+
+mac_t
+bfa_nw_ioc_get_mac(struct bfa_ioc *ioc)
+{
+	/*
+	 * Currently mfg mac is used as FCoE enode mac (not configured by PBC)
+	 */
+	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
+		return bfa_ioc_get_mfg_mac(ioc);
+	else
+		return ioc->attr->mac;
+}
+
+static mac_t
+bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc)
+{
+	mac_t	m;
+
+	m = ioc->attr->mfg_mac;
+	if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
+		m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
+	else
+		bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
+			bfa_ioc_pcifn(ioc));
+
+	return m;
+}
+
+/**
+ * Firmware failure detected. Start recovery actions.
+ */
+static void
+bfa_ioc_recover(struct bfa_ioc *ioc)
+{
+	bfa_ioc_stats(ioc, ioc_hbfails);
+	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
+}
+
+static void
+bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc)
+{
+	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
+		return;
+
+}
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
new file mode 100644
index 0000000..a73d84e
--- /dev/null
+++ b/drivers/net/bna/bfa_ioc.h
@@ -0,0 +1,300 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFA_IOC_H__
+#define __BFA_IOC_H__
+
+#include "bfa_sm.h"
+#include "bfi.h"
+#include "cna.h"
+
+#define BFA_IOC_TOV		3000	/* msecs */
+#define BFA_IOC_HWSEM_TOV	500	/* msecs */
+#define BFA_IOC_HB_TOV		500	/* msecs */
+#define BFA_IOC_HWINIT_MAX	2
+#define BFA_IOC_TOV_RECOVER	BFA_IOC_HB_TOV
+
+/**
+ * Generic Scatter Gather Element used by driver
+ */
+struct bfa_sge {
+	u32	sg_len;
+	void	*sg_addr;
+};
+
+/**
+ * PCI device information required by IOC
+ */
+struct bfa_pcidev {
+	int	pci_slot;
+	u8	pci_func;
+	u16	device_id;
+	void	__iomem *pci_bar_kva;
+};
+
+/**
+ * Structure used to remember the DMA-able memory block's KVA and Physical
+ * Address
+ */
+struct bfa_dma {
+	void	*kva;	/* ! Kernel virtual address	*/
+	u64	pa;	/* ! Physical address		*/
+};
+
+#define BFA_DMA_ALIGN_SZ	256
+
+/**
+ * smem size for Crossbow and Catapult
+ */
+#define BFI_SMEM_CB_SIZE	0x200000U	/* ! 2MB for crossbow	*/
+#define BFI_SMEM_CT_SIZE	0x280000U	/* ! 2.5MB for catapult	*/
+
+/**
+ * @brief BFA dma address assignment macro
+ */
+#define bfa_dma_addr_set(dma_addr, pa)	\
+		__bfa_dma_addr_set(&dma_addr, (u64)pa)
+
+static inline void
+__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa)
+{
+	dma_addr->a32.addr_lo = (u32) pa;
+	dma_addr->a32.addr_hi = (u32) (upper_32_bits(pa));
+}
+
+/**
+ * @brief BFA dma address assignment macro. (big endian format)
+ */
+#define bfa_dma_be_addr_set(dma_addr, pa)	\
+		__bfa_dma_be_addr_set(&dma_addr, (u64)pa)
+static inline void
+__bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)
+{
+	dma_addr->a32.addr_lo = (u32) htonl(pa);
+	dma_addr->a32.addr_hi = (u32) htonl(upper_32_bits(pa));
+}
+
+struct bfa_ioc_regs {
+	void __iomem *hfn_mbox_cmd;
+	void __iomem *hfn_mbox;
+	void __iomem *lpu_mbox_cmd;
+	void __iomem *lpu_mbox;
+	void __iomem *pss_ctl_reg;
+	void __iomem *pss_err_status_reg;
+	void __iomem *app_pll_fast_ctl_reg;
+	void __iomem *app_pll_slow_ctl_reg;
+	void __iomem *ioc_sem_reg;
+	void __iomem *ioc_usage_sem_reg;
+	void __iomem *ioc_init_sem_reg;
+	void __iomem *ioc_usage_reg;
+	void __iomem *host_page_num_fn;
+	void __iomem *heartbeat;
+	void __iomem *ioc_fwstate;
+	void __iomem *ll_halt;
+	void __iomem *err_set;
+	void __iomem *shirq_isr_next;
+	void __iomem *shirq_msk_next;
+	void __iomem *smem_page_start;
+	u32	smem_pg0;
+};
+
+/**
+ * IOC Mailbox structures
+ */
+struct bfa_mbox_cmd {
+	struct list_head	qe;
+	u32			msg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * IOC mailbox module
+ */
+typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg *m);
+struct bfa_ioc_mbox_mod {
+	struct list_head	cmd_q;		/*!< pending mbox queue	*/
+	int			nmclass;	/*!< number of handlers */
+	struct {
+		bfa_ioc_mbox_mcfunc_t	cbfn;	/*!< message handlers	*/
+		void			*cbarg;
+	} mbhdlr[BFI_MC_MAX];
+};
+
+/**
+ * IOC callback function interfaces
+ */
+typedef void (*bfa_ioc_enable_cbfn_t)(void *bfa, enum bfa_status status);
+typedef void (*bfa_ioc_disable_cbfn_t)(void *bfa);
+typedef void (*bfa_ioc_hbfail_cbfn_t)(void *bfa);
+typedef void (*bfa_ioc_reset_cbfn_t)(void *bfa);
+struct bfa_ioc_cbfn {
+	bfa_ioc_enable_cbfn_t	enable_cbfn;
+	bfa_ioc_disable_cbfn_t	disable_cbfn;
+	bfa_ioc_hbfail_cbfn_t	hbfail_cbfn;
+	bfa_ioc_reset_cbfn_t	reset_cbfn;
+};
+
+/**
+ * Heartbeat failure notification queue element.
+ */
+struct bfa_ioc_hbfail_notify {
+	struct list_head	qe;
+	bfa_ioc_hbfail_cbfn_t	cbfn;
+	void			*cbarg;
+};
+
+/**
+ * Initialize a heartbeat failure notification structure
+ */
+#define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do {	\
+	(__notify)->cbfn = (__cbfn);				\
+	(__notify)->cbarg = (__cbarg);				\
+} while (0)
+
+struct bfa_ioc {
+	bfa_fsm_t		fsm;
+	struct bfa 		*bfa;
+	struct bfa_pcidev 	pcidev;
+	struct bfa_timer_mod	*timer_mod;
+	struct timer_list 	ioc_timer;
+	struct timer_list 	sem_timer;
+	struct timer_list	hb_timer;
+	u32			hb_count;
+	u32			retry_count;
+	struct list_head	hb_notify_q;
+	void			*dbg_fwsave;
+	int			dbg_fwsave_len;
+	bool			dbg_fwsave_once;
+	enum bfi_mclass		ioc_mc;
+	struct bfa_ioc_regs 	ioc_regs;
+	struct bfa_ioc_drv_stats stats;
+	bool			auto_recover;
+	bool			fcmode;
+	bool			ctdev;
+	bool			cna;
+	bool			pllinit;
+	bool   			stats_busy;	/*!< outstanding stats */
+	u8			port_id;
+
+	struct bfa_dma		attr_dma;
+	struct bfi_ioc_attr	*attr;
+	struct bfa_ioc_cbfn	*cbfn;
+	struct bfa_ioc_mbox_mod	mbox_mod;
+	struct bfa_ioc_hwif	*ioc_hwif;
+};
+
+struct bfa_ioc_hwif {
+	enum bfa_status (*ioc_pll_init) (void __iomem *rb, bool fcmode);
+	bool		(*ioc_firmware_lock)	(struct bfa_ioc *ioc);
+	void		(*ioc_firmware_unlock)	(struct bfa_ioc *ioc);
+	void		(*ioc_reg_init)	(struct bfa_ioc *ioc);
+	void		(*ioc_map_port)	(struct bfa_ioc *ioc);
+	void		(*ioc_isr_mode_set)	(struct bfa_ioc *ioc,
+					bool msix);
+	void		(*ioc_notify_hbfail)	(struct bfa_ioc *ioc);
+	void		(*ioc_ownership_reset)	(struct bfa_ioc *ioc);
+};
+
+#define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)
+#define bfa_ioc_devid(__ioc)		((__ioc)->pcidev.device_id)
+#define bfa_ioc_bar0(__ioc)		((__ioc)->pcidev.pci_bar_kva)
+#define bfa_ioc_portid(__ioc)		((__ioc)->port_id)
+#define bfa_ioc_fetch_stats(__ioc, __stats) \
+		(((__stats)->drv_stats) = (__ioc)->stats)
+#define bfa_ioc_clr_stats(__ioc)	\
+		memset(&(__ioc)->stats, 0, sizeof((__ioc)->stats))
+#define bfa_ioc_maxfrsize(__ioc)	((__ioc)->attr->maxfrsize)
+#define bfa_ioc_rx_bbcredit(__ioc)	((__ioc)->attr->rx_bbcredit)
+#define bfa_ioc_speed_sup(__ioc)	\
+	BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
+#define bfa_ioc_get_nports(__ioc)	\
+	BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)
+
+#define bfa_ioc_stats(_ioc, _stats)	((_ioc)->stats._stats++)
+#define BFA_IOC_FWIMG_MINSZ	(16 * 1024)
+#define BFA_IOC_FWIMG_TYPE(__ioc)					\
+	(((__ioc)->ctdev) ? 						\
+	 (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) :	\
+	 BFI_IMAGE_CB_FC)
+#define BFA_IOC_FW_SMEM_SIZE(__ioc)					\
+	(((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE)
+#define BFA_IOC_FLASH_CHUNK_NO(off)		(off / BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off)	(off % BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_IOC_FLASH_CHUNK_ADDR(chunkno)  (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
+
+/**
+ * IOC mailbox interface
+ */
+void bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd);
+void bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc);
+void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
+		bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg);
+
+/**
+ * IOC interfaces
+ */
+
+#define bfa_ioc_pll_init_asic(__ioc) \
+	((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \
+			   (__ioc)->fcmode))
+
+#define	bfa_ioc_isr_mode_set(__ioc, __msix)			\
+			((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix))
+#define	bfa_ioc_ownership_reset(__ioc)				\
+			((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
+
+void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc);
+
+void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa,
+		struct bfa_ioc_cbfn *cbfn);
+void bfa_nw_ioc_auto_recover(bool auto_recover);
+void bfa_nw_ioc_detach(struct bfa_ioc *ioc);
+void bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
+		enum bfi_mclass mc);
+u32 bfa_nw_ioc_meminfo(void);
+void bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc,  u8 *dm_kva, u64 dm_pa);
+void bfa_nw_ioc_enable(struct bfa_ioc *ioc);
+void bfa_nw_ioc_disable(struct bfa_ioc *ioc);
+
+void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc);
+
+void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr);
+void bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc,
+	struct bfa_ioc_hbfail_notify *notify);
+bool bfa_nw_ioc_sem_get(void __iomem *sem_reg);
+void bfa_nw_ioc_sem_release(void __iomem *sem_reg);
+void bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc);
+void bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc,
+			struct bfi_ioc_image_hdr *fwhdr);
+bool bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc,
+			struct bfi_ioc_image_hdr *fwhdr);
+mac_t bfa_nw_ioc_get_mac(struct bfa_ioc *ioc);
+
+/*
+ * Timeout APIs
+ */
+void bfa_nw_ioc_timeout(void *ioc);
+void bfa_nw_ioc_hb_check(void *ioc);
+void bfa_nw_ioc_sem_timeout(void *ioc);
+
+/*
+ * F/W Image Size & Chunk
+ */
+u32 *bfa_cb_image_get_chunk(int type, u32 off);
+u32 bfa_cb_image_get_size(int type);
+
+#endif /* __BFA_IOC_H__ */
diff --git a/drivers/net/bna/bfa_ioc_ct.c b/drivers/net/bna/bfa_ioc_ct.c
new file mode 100644
index 0000000..121cfd6
--- /dev/null
+++ b/drivers/net/bna/bfa_ioc_ct.c
@@ -0,0 +1,392 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#include "bfa_ioc.h"
+#include "cna.h"
+#include "bfi.h"
+#include "bfi_ctreg.h"
+#include "bfa_defs.h"
+
+/*
+ * forward declarations
+ */
+static bool bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_reg_init(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix);
+static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc);
+static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode);
+
+static struct bfa_ioc_hwif nw_hwif_ct;
+
+/**
+ * Called from bfa_ioc_attach() to map asic specific calls.
+ */
+void
+bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc)
+{
+	nw_hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
+	nw_hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
+	nw_hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
+	nw_hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
+	nw_hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
+	nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
+	nw_hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail;
+	nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+
+	ioc->ioc_hwif = &nw_hwif_ct;
+}
+
+/**
+ * Return true if firmware of current driver matches the running firmware.
+ */
+static bool
+bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc)
+{
+	enum bfi_ioc_state ioc_fwstate;
+	u32 usecnt;
+	struct bfi_ioc_image_hdr fwhdr;
+
+	/**
+	 * Firmware match check is relevant only for CNA.
+	 */
+	if (!ioc->cna)
+		return true;
+
+	/**
+	 * If bios boot (flash based) -- do not increment usage count
+	 */
+	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+						BFA_IOC_FWIMG_MINSZ)
+		return true;
+
+	bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+	usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
+
+	/**
+	 * If usage count is 0, always return TRUE.
+	 */
+	if (usecnt == 0) {
+		writel(1, ioc->ioc_regs.ioc_usage_reg);
+		bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+		return true;
+	}
+
+	ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+	/**
+	 * Use count cannot be non-zero and chip in uninitialized state.
+	 */
+	BUG_ON(!(ioc_fwstate != BFI_IOC_UNINIT));
+
+	/**
+	 * Check if another driver with a different firmware is active
+	 */
+	bfa_nw_ioc_fwver_get(ioc, &fwhdr);
+	if (!bfa_nw_ioc_fwver_cmp(ioc, &fwhdr)) {
+		bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+		return false;
+	}
+
+	/**
+	 * Same firmware version. Increment the reference count.
+	 */
+	usecnt++;
+	writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
+	bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+	return true;
+}
+
+static void
+bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc)
+{
+	u32 usecnt;
+
+	/**
+	 * Firmware lock is relevant only for CNA.
+	 */
+	if (!ioc->cna)
+		return;
+
+	/**
+	 * If bios boot (flash based) -- do not decrement usage count
+	 */
+	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+						BFA_IOC_FWIMG_MINSZ)
+		return;
+
+	/**
+	 * decrement usage count
+	 */
+	bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+	usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
+	BUG_ON(!(usecnt > 0));
+
+	usecnt--;
+	writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
+
+	bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+}
+
+/**
+ * Notify other functions on HB failure.
+ */
+static void
+bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc)
+{
+	if (ioc->cna) {
+		writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
+		/* Wait for halt to take effect */
+		readl(ioc->ioc_regs.ll_halt);
+	} else {
+		writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
+		readl(ioc->ioc_regs.err_set);
+	}
+}
+
+/**
+ * Host to LPU mailbox message addresses
+ */
+static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
+	{ HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
+	{ HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
+	{ HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 },
+	{ HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 }
+};
+
+/**
+ * Host <-> LPU mailbox command/status registers - port 0
+ */
+static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = {
+	{ HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT },
+	{ HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT },
+	{ HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT },
+	{ HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT }
+};
+
+/**
+ * Host <-> LPU mailbox command/status registers - port 1
+ */
+static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = {
+	{ HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT },
+	{ HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT },
+	{ HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT },
+	{ HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT }
+};
+
+static void
+bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
+{
+	void __iomem *rb;
+	int		pcifn = bfa_ioc_pcifn(ioc);
+
+	rb = bfa_ioc_bar0(ioc);
+
+	ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
+	ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
+	ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
+
+	if (ioc->port_id == 0) {
+		ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
+		ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
+		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
+		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
+		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
+	} else {
+		ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
+		ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
+		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
+		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
+		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
+	}
+
+	/*
+	 * PSS control registers
+	 */
+	ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
+	ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
+	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG);
+	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG);
+
+	/*
+	 * IOC semaphore registers and serialization
+	 */
+	ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
+	ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
+	ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
+	ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
+
+	/**
+	 * sram memory access
+	 */
+	ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
+	ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
+
+	/*
+	 * err set reg : for notification of hb failure in fcmode
+	 */
+	ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
+}
+
+/**
+ * Initialize IOC to port mapping.
+ */
+
+#define FNC_PERS_FN_SHIFT(__fn)	((__fn) * 8)
+static void
+bfa_ioc_ct_map_port(struct bfa_ioc *ioc)
+{
+	void __iomem *rb = ioc->pcidev.pci_bar_kva;
+	u32	r32;
+
+	/**
+	 * For catapult, base port id on personality register and IOC type
+	 */
+	r32 = readl(rb + FNC_PERS_REG);
+	r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
+	ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
+
+}
+
+/**
+ * Set interrupt mode for a function: INTX or MSIX
+ */
+static void
+bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix)
+{
+	void __iomem *rb = ioc->pcidev.pci_bar_kva;
+	u32	r32, mode;
+
+	r32 = readl(rb + FNC_PERS_REG);
+
+	mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
+		__F0_INTX_STATUS;
+
+	/**
+	 * If already in desired mode, do not change anything
+	 */
+	if (!msix && mode)
+		return;
+
+	if (msix)
+		mode = __F0_INTX_STATUS_MSIX;
+	else
+		mode = __F0_INTX_STATUS_INTA;
+
+	r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
+	r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
+
+	writel(r32, rb + FNC_PERS_REG);
+}
+
+/**
+ * Cleanup hw semaphore and usecnt registers
+ */
+static void
+bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc)
+{
+	if (ioc->cna) {
+		bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+		writel(0, ioc->ioc_regs.ioc_usage_reg);
+		bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+	}
+
+	/*
+	 * Read the hw sem reg to make sure that it is locked
+	 * before we clear it. If it is not locked, writing 1
+	 * will lock it instead of clearing it.
+	 */
+	readl(ioc->ioc_regs.ioc_sem_reg);
+	bfa_nw_ioc_hw_sem_release(ioc);
+}
+
+static enum bfa_status
+bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode)
+{
+	u32	pll_sclk, pll_fclk, r32;
+
+	pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
+		__APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
+		__APP_PLL_312_JITLMT0_1(3U) |
+		__APP_PLL_312_CNTLMT0_1(1U);
+	pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
+		__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
+		__APP_PLL_425_JITLMT0_1(3U) |
+		__APP_PLL_425_CNTLMT0_1(1U);
+	if (fcmode) {
+		writel(0, (rb + OP_MODE));
+		writel(__APP_EMS_CMLCKSEL |
+				__APP_EMS_REFCKBUFEN2 |
+				__APP_EMS_CHANNEL_SEL,
+				(rb + ETH_MAC_SER_REG));
+	} else {
+		writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE));
+		writel(__APP_EMS_REFCKBUFEN1,
+				(rb + ETH_MAC_SER_REG));
+	}
+	writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
+	writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
+	writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
+	writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
+	writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
+	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
+	writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
+	writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
+	writel(pll_sclk |
+		__APP_PLL_312_LOGIC_SOFT_RESET,
+		rb + APP_PLL_312_CTL_REG);
+	writel(pll_fclk |
+		__APP_PLL_425_LOGIC_SOFT_RESET,
+		rb + APP_PLL_425_CTL_REG);
+	writel(pll_sclk |
+		__APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE,
+		rb + APP_PLL_312_CTL_REG);
+	writel(pll_fclk |
+		__APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE,
+		rb + APP_PLL_425_CTL_REG);
+	readl(rb + HOSTFN0_INT_MSK);
+	udelay(2000);
+	writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
+	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
+	writel(pll_sclk |
+		__APP_PLL_312_ENABLE,
+		rb + APP_PLL_312_CTL_REG);
+	writel(pll_fclk |
+		__APP_PLL_425_ENABLE,
+		rb + APP_PLL_425_CTL_REG);
+	if (!fcmode) {
+		writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0));
+		writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1));
+	}
+	r32 = readl((rb + PSS_CTL_REG));
+	r32 &= ~__PSS_LMEM_RESET;
+	writel(r32, (rb + PSS_CTL_REG));
+	udelay(1000);
+	if (!fcmode) {
+		writel(0, (rb + PMM_1T_RESET_REG_P0));
+		writel(0, (rb + PMM_1T_RESET_REG_P1));
+	}
+
+	writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG));
+	udelay(1000);
+	r32 = readl((rb + MBIST_STAT_REG));
+	writel(0, (rb + MBIST_CTL_REG));
+	return BFA_STATUS_OK;
+}
diff --git a/drivers/net/bna/bfa_sm.h b/drivers/net/bna/bfa_sm.h
new file mode 100644
index 0000000..46462c4
--- /dev/null
+++ b/drivers/net/bna/bfa_sm.h
@@ -0,0 +1,88 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/**
+ * @file bfasm.h State machine defines
+ */
+
+#ifndef __BFA_SM_H__
+#define __BFA_SM_H__
+
+#include "cna.h"
+
+typedef void (*bfa_sm_t)(void *sm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_sm_state_decl(oc, st, otype, etype)		\
+	static void oc ## _sm_ ## st(otype * fsm, etype event)
+
+#define bfa_sm_set_state(_sm, _state)	((_sm)->sm = (bfa_sm_t)(_state))
+#define bfa_sm_send_event(_sm, _event)	((_sm)->sm((_sm), (_event)))
+#define bfa_sm_get_state(_sm)		((_sm)->sm)
+#define bfa_sm_cmp_state(_sm, _state)	((_sm)->sm == (bfa_sm_t)(_state))
+
+/**
+ * For converting from state machine function to state encoding.
+ */
+struct bfa_sm_table {
+	bfa_sm_t	sm;	/*!< state machine function	*/
+	int		state;	/*!< state machine encoding	*/
+	char		*name;	/*!< state name for display	*/
+};
+#define BFA_SM(_sm)	((bfa_sm_t)(_sm))
+
+/**
+ * State machine with entry actions.
+ */
+typedef void (*bfa_fsm_t)(void *fsm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_fsm_state_decl(oc, st, otype, etype)		\
+	static void oc ## _sm_ ## st(otype * fsm, etype event);	\
+	static void oc ## _sm_ ## st ## _entry(otype * fsm)
+
+#define bfa_fsm_set_state(_fsm, _state) do {	\
+	(_fsm)->fsm = (bfa_fsm_t)(_state);	\
+	_state ## _entry(_fsm);			\
+} while (0)
+
+#define bfa_fsm_send_event(_fsm, _event)	((_fsm)->fsm((_fsm), (_event)))
+#define bfa_fsm_get_state(_fsm)			((_fsm)->fsm)
+#define bfa_fsm_cmp_state(_fsm, _state)		\
+	((_fsm)->fsm == (bfa_fsm_t)(_state))
+
+static inline int
+bfa_sm_to_state(const struct bfa_sm_table *smt, bfa_sm_t sm)
+{
+	int	i = 0;
+
+	while (smt[i].sm && smt[i].sm != sm)
+		i++;
+	return smt[i].state;
+}
+#endif
diff --git a/drivers/net/bna/bfa_wc.h b/drivers/net/bna/bfa_wc.h
new file mode 100644
index 0000000..d0e4cae
--- /dev/null
+++ b/drivers/net/bna/bfa_wc.h
@@ -0,0 +1,69 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/**
+ * @file bfa_wc.h Generic wait counter.
+ */
+
+#ifndef __BFA_WC_H__
+#define __BFA_WC_H__
+
+typedef void (*bfa_wc_resume_t) (void *cbarg);
+
+struct bfa_wc {
+	bfa_wc_resume_t wc_resume;
+	void		*wc_cbarg;
+	int		wc_count;
+};
+
+static inline void
+bfa_wc_up(struct bfa_wc *wc)
+{
+	wc->wc_count++;
+}
+
+static inline void
+bfa_wc_down(struct bfa_wc *wc)
+{
+	wc->wc_count--;
+	if (wc->wc_count == 0)
+		wc->wc_resume(wc->wc_cbarg);
+}
+
+/**
+ * Initialize a waiting counter.
+ */
+static inline void
+bfa_wc_init(struct bfa_wc *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
+{
+	wc->wc_resume = wc_resume;
+	wc->wc_cbarg = wc_cbarg;
+	wc->wc_count = 0;
+	bfa_wc_up(wc);
+}
+
+/**
+ * Wait for counter to reach zero
+ */
+static inline void
+bfa_wc_wait(struct bfa_wc *wc)
+{
+	bfa_wc_down(wc);
+}
+
+#endif
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
new file mode 100644
index 0000000..a973968
--- /dev/null
+++ b/drivers/net/bna/bfi.h
@@ -0,0 +1,392 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFI_H__
+#define __BFI_H__
+
+#include "bfa_defs.h"
+
+#pragma pack(1)
+
+/**
+ * BFI FW image type
+ */
+#define	BFI_FLASH_CHUNK_SZ			256	/*!< Flash chunk size */
+#define	BFI_FLASH_CHUNK_SZ_WORDS	(BFI_FLASH_CHUNK_SZ/sizeof(u32))
+enum {
+	BFI_IMAGE_CB_FC,
+	BFI_IMAGE_CT_FC,
+	BFI_IMAGE_CT_CNA,
+	BFI_IMAGE_MAX,
+};
+
+/**
+ * Msg header common to all msgs
+ */
+struct bfi_mhdr {
+	u8		msg_class;	/*!< @ref enum bfi_mclass	    */
+	u8		msg_id;		/*!< msg opcode with in the class   */
+	union {
+		struct {
+			u8	rsvd;
+			u8	lpu_id;	/*!< msg destination		    */
+		} h2i;
+		u16	i2htok;	/*!< token in msgs to host	    */
+	} mtag;
+};
+
+#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {		\
+	(_mh).msg_class 		= (_mc);		\
+	(_mh).msg_id			= (_op);		\
+	(_mh).mtag.h2i.lpu_id	= (_lpuid);			\
+} while (0)
+
+#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {		\
+	(_mh).msg_class 		= (_mc);		\
+	(_mh).msg_id			= (_op);		\
+	(_mh).mtag.i2htok		= (_i2htok);		\
+} while (0)
+
+/*
+ * Message opcodes: 0-127 to firmware, 128-255 to host
+ */
+#define BFI_I2H_OPCODE_BASE	128
+#define BFA_I2HM(_x) 			((_x) + BFI_I2H_OPCODE_BASE)
+
+/**
+ ****************************************************************************
+ *
+ * Scatter Gather Element and Page definition
+ *
+ ****************************************************************************
+ */
+
+#define BFI_SGE_INLINE	1
+#define BFI_SGE_INLINE_MAX	(BFI_SGE_INLINE + 1)
+
+/**
+ * SG Flags
+ */
+enum {
+	BFI_SGE_DATA		= 0,	/*!< data address, not last	     */
+	BFI_SGE_DATA_CPL	= 1,	/*!< data addr, last in current page */
+	BFI_SGE_DATA_LAST	= 3,	/*!< data address, last		     */
+	BFI_SGE_LINK		= 2,	/*!< link address		     */
+	BFI_SGE_PGDLEN		= 2,	/*!< cumulative data length for page */
+};
+
+/**
+ * DMA addresses
+ */
+union bfi_addr_u {
+	struct {
+		u32	addr_lo;
+		u32	addr_hi;
+	} a32;
+};
+
+/**
+ * Scatter Gather Element
+ */
+struct bfi_sge {
+#ifdef __BIGENDIAN
+	u32	flags:2,
+			rsvd:2,
+			sg_len:28;
+#else
+	u32	sg_len:28,
+			rsvd:2,
+			flags:2;
+#endif
+	union bfi_addr_u sga;
+};
+
+/**
+ * Scatter Gather Page
+ */
+#define BFI_SGPG_DATA_SGES		7
+#define BFI_SGPG_SGES_MAX		(BFI_SGPG_DATA_SGES + 1)
+#define BFI_SGPG_RSVD_WD_LEN	8
+struct bfi_sgpg {
+	struct bfi_sge sges[BFI_SGPG_SGES_MAX];
+	u32	rsvd[BFI_SGPG_RSVD_WD_LEN];
+};
+
+/*
+ * Large Message structure - 128 Bytes size Msgs
+ */
+#define BFI_LMSG_SZ		128
+#define BFI_LMSG_PL_WSZ	\
+			((BFI_LMSG_SZ - sizeof(struct bfi_mhdr)) / 4)
+
+struct bfi_msg {
+	struct bfi_mhdr mhdr;
+	u32	pl[BFI_LMSG_PL_WSZ];
+};
+
+/**
+ * Mailbox message structure
+ */
+#define BFI_MBMSG_SZ		7
+struct bfi_mbmsg {
+	struct bfi_mhdr mh;
+	u32		pl[BFI_MBMSG_SZ];
+};
+
+/**
+ * Message Classes
+ */
+enum bfi_mclass {
+	BFI_MC_IOC		= 1,	/*!< IO Controller (IOC)	    */
+	BFI_MC_DIAG		= 2,	/*!< Diagnostic Msgs		    */
+	BFI_MC_FLASH		= 3,	/*!< Flash message class	    */
+	BFI_MC_CEE		= 4,	/*!< CEE			    */
+	BFI_MC_FCPORT		= 5,	/*!< FC port			    */
+	BFI_MC_IOCFC		= 6,	/*!< FC - IO Controller (IOC)	    */
+	BFI_MC_LL		= 7,	/*!< Link Layer			    */
+	BFI_MC_UF		= 8,	/*!< Unsolicited frame receive	    */
+	BFI_MC_FCXP		= 9,	/*!< FC Transport		    */
+	BFI_MC_LPS		= 10,	/*!< lport fc login services	    */
+	BFI_MC_RPORT		= 11,	/*!< Remote port		    */
+	BFI_MC_ITNIM		= 12,	/*!< I-T nexus (Initiator mode)	    */
+	BFI_MC_IOIM_READ	= 13,	/*!< read IO (Initiator mode)	    */
+	BFI_MC_IOIM_WRITE	= 14,	/*!< write IO (Initiator mode)	    */
+	BFI_MC_IOIM_IO		= 15,	/*!< IO (Initiator mode)	    */
+	BFI_MC_IOIM		= 16,	/*!< IO (Initiator mode)	    */
+	BFI_MC_IOIM_IOCOM	= 17,	/*!< good IO completion		    */
+	BFI_MC_TSKIM		= 18,	/*!< Initiator Task management	    */
+	BFI_MC_SBOOT		= 19,	/*!< SAN boot services		    */
+	BFI_MC_IPFC		= 20,	/*!< IP over FC Msgs		    */
+	BFI_MC_PORT		= 21,	/*!< Physical port		    */
+	BFI_MC_SFP		= 22,	/*!< SFP module			    */
+	BFI_MC_MSGQ		= 23,	/*!< MSGQ			    */
+	BFI_MC_ENET		= 24,	/*!< ENET commands/responses	    */
+	BFI_MC_MAX		= 32
+};
+
+#define BFI_IOC_MAX_CQS		4
+#define BFI_IOC_MAX_CQS_ASIC	8
+#define BFI_IOC_MSGLEN_MAX	32	/* 32 bytes */
+
+#define BFI_BOOT_TYPE_OFF		8
+#define BFI_BOOT_PARAM_OFF		12
+
+#define BFI_BOOT_TYPE_NORMAL 		0	/* param is device id */
+#define	BFI_BOOT_TYPE_FLASH		1
+#define	BFI_BOOT_TYPE_MEMTEST		2
+
+#define BFI_BOOT_MEMTEST_RES_ADDR   0x900
+#define BFI_BOOT_MEMTEST_RES_SIG    0xA0A1A2A3
+
+/**
+ *----------------------------------------------------------------------
+ *				IOC
+ *----------------------------------------------------------------------
+ */
+
+enum bfi_ioc_h2i_msgs {
+	BFI_IOC_H2I_ENABLE_REQ		= 1,
+	BFI_IOC_H2I_DISABLE_REQ		= 2,
+	BFI_IOC_H2I_GETATTR_REQ		= 3,
+	BFI_IOC_H2I_DBG_SYNC		= 4,
+	BFI_IOC_H2I_DBG_DUMP		= 5,
+};
+
+enum bfi_ioc_i2h_msgs {
+	BFI_IOC_I2H_ENABLE_REPLY	= BFA_I2HM(1),
+	BFI_IOC_I2H_DISABLE_REPLY 	= BFA_I2HM(2),
+	BFI_IOC_I2H_GETATTR_REPLY 	= BFA_I2HM(3),
+	BFI_IOC_I2H_READY_EVENT 	= BFA_I2HM(4),
+	BFI_IOC_I2H_HBEAT		= BFA_I2HM(5),
+};
+
+/**
+ * BFI_IOC_H2I_GETATTR_REQ message
+ */
+struct bfi_ioc_getattr_req {
+	struct bfi_mhdr mh;
+	union bfi_addr_u	attr_addr;
+};
+
+struct bfi_ioc_attr {
+	u64		mfg_pwwn;	/*!< Mfg port wwn	   */
+	u64		mfg_nwwn;	/*!< Mfg node wwn	   */
+	mac_t		mfg_mac;	/*!< Mfg mac		   */
+	u16	rsvd_a;
+	u64		pwwn;
+	u64		nwwn;
+	mac_t		mac;		/*!< PBC or Mfg mac	   */
+	u16	rsvd_b;
+	mac_t		fcoe_mac;
+	u16	rsvd_c;
+	char		brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+	u8		pcie_gen;
+	u8		pcie_lanes_orig;
+	u8		pcie_lanes;
+	u8		rx_bbcredit;	/*!< receive buffer credits */
+	u32	adapter_prop;	/*!< adapter properties     */
+	u16	maxfrsize;	/*!< max receive frame size */
+	char		asic_rev;
+	u8		rsvd_d;
+	char		fw_version[BFA_VERSION_LEN];
+	char		optrom_version[BFA_VERSION_LEN];
+	struct bfa_mfg_vpd vpd;
+	u32	card_type;	/*!< card type			*/
+};
+
+/**
+ * BFI_IOC_I2H_GETATTR_REPLY message
+ */
+struct bfi_ioc_getattr_reply {
+	struct bfi_mhdr mh;	/*!< Common msg header		*/
+	u8			status;	/*!< cfg reply status		*/
+	u8			rsvd[3];
+};
+
+/**
+ * Firmware memory page offsets
+ */
+#define BFI_IOC_SMEM_PG0_CB	(0x40)
+#define BFI_IOC_SMEM_PG0_CT	(0x180)
+
+/**
+ * Firmware statistic offset
+ */
+#define BFI_IOC_FWSTATS_OFF	(0x6B40)
+#define BFI_IOC_FWSTATS_SZ	(4096)
+
+/**
+ * Firmware trace offset
+ */
+#define BFI_IOC_TRC_OFF		(0x4b00)
+#define BFI_IOC_TRC_ENTS	256
+
+#define BFI_IOC_FW_SIGNATURE	(0xbfadbfad)
+#define BFI_IOC_MD5SUM_SZ	4
+struct bfi_ioc_image_hdr {
+	u32	signature;	/*!< constant signature */
+	u32	rsvd_a;
+	u32	exec;		/*!< exec vector	*/
+	u32	param;		/*!< parameters		*/
+	u32	rsvd_b[4];
+	u32	md5sum[BFI_IOC_MD5SUM_SZ];
+};
+
+/**
+ *  BFI_IOC_I2H_READY_EVENT message
+ */
+struct bfi_ioc_rdy_event {
+	struct bfi_mhdr mh;		/*!< common msg header */
+	u8			init_status;	/*!< init event status */
+	u8			rsvd[3];
+};
+
+struct bfi_ioc_hbeat {
+	struct bfi_mhdr mh;		/*!< common msg header		*/
+	u32	   hb_count;	/*!< current heart beat count	*/
+};
+
+/**
+ * IOC hardware/firmware state
+ */
+enum bfi_ioc_state {
+	BFI_IOC_UNINIT		= 0,	/*!< not initialized		     */
+	BFI_IOC_INITING		= 1,	/*!< h/w is being initialized	     */
+	BFI_IOC_HWINIT		= 2,	/*!< h/w is initialized		     */
+	BFI_IOC_CFG		= 3,	/*!< IOC configuration in progress   */
+	BFI_IOC_OP		= 4,	/*!< IOC is operational		     */
+	BFI_IOC_DISABLING	= 5,	/*!< IOC is being disabled	     */
+	BFI_IOC_DISABLED	= 6,	/*!< IOC is disabled		     */
+	BFI_IOC_CFG_DISABLED	= 7,	/*!< IOC is being disabled;transient */
+	BFI_IOC_FAIL		= 8,	/*!< IOC heart-beat failure	     */
+	BFI_IOC_MEMTEST		= 9,	/*!< IOC is doing memtest	     */
+};
+
+#define BFI_IOC_ENDIAN_SIG  0x12345678
+
+enum {
+	BFI_ADAPTER_TYPE_FC	= 0x01,		/*!< FC adapters	   */
+	BFI_ADAPTER_TYPE_MK	= 0x0f0000,	/*!< adapter type mask     */
+	BFI_ADAPTER_TYPE_SH	= 16,	        /*!< adapter type shift    */
+	BFI_ADAPTER_NPORTS_MK	= 0xff00,	/*!< number of ports mask  */
+	BFI_ADAPTER_NPORTS_SH	= 8,	        /*!< number of ports shift */
+	BFI_ADAPTER_SPEED_MK	= 0xff,		/*!< adapter speed mask    */
+	BFI_ADAPTER_SPEED_SH	= 0,	        /*!< adapter speed shift   */
+	BFI_ADAPTER_PROTO	= 0x100000,	/*!< prototype adapaters   */
+	BFI_ADAPTER_TTV		= 0x200000,	/*!< TTV debug capable     */
+	BFI_ADAPTER_UNSUPP	= 0x400000,	/*!< unknown adapter type  */
+};
+
+#define BFI_ADAPTER_GETP(__prop, __adap_prop)			\
+	(((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >>	\
+		BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_SETP(__prop, __val)				\
+	((__val) << BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_IS_PROTO(__adap_type)			\
+	((__adap_type) & BFI_ADAPTER_PROTO)
+#define BFI_ADAPTER_IS_TTV(__adap_type)				\
+	((__adap_type) & BFI_ADAPTER_TTV)
+#define BFI_ADAPTER_IS_UNSUPP(__adap_type)			\
+	((__adap_type) & BFI_ADAPTER_UNSUPP)
+#define BFI_ADAPTER_IS_SPECIAL(__adap_type)			\
+	((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO |	\
+			BFI_ADAPTER_UNSUPP))
+
+/**
+ * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages
+ */
+struct bfi_ioc_ctrl_req {
+	struct bfi_mhdr mh;
+	u8			ioc_class;
+	u8			rsvd[3];
+	u32		tv_sec;
+};
+
+/**
+ * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
+ */
+struct bfi_ioc_ctrl_reply {
+	struct bfi_mhdr mh;		/*!< Common msg header     */
+	u8			status;		/*!< enable/disable status */
+	u8			rsvd[3];
+};
+
+#define BFI_IOC_MSGSZ   8
+/**
+ * H2I Messages
+ */
+union bfi_ioc_h2i_msg_u {
+	struct bfi_mhdr mh;
+	struct bfi_ioc_ctrl_req enable_req;
+	struct bfi_ioc_ctrl_req disable_req;
+	struct bfi_ioc_getattr_req getattr_req;
+	u32			mboxmsg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * I2H Messages
+ */
+union bfi_ioc_i2h_msg_u {
+	struct bfi_mhdr mh;
+	struct bfi_ioc_rdy_event rdy_event;
+	u32			mboxmsg[BFI_IOC_MSGSZ];
+};
+
+#pragma pack()
+
+#endif /* __BFI_H__ */
diff --git a/drivers/net/bna/bfi_cna.h b/drivers/net/bna/bfi_cna.h
new file mode 100644
index 0000000..4eecabe
--- /dev/null
+++ b/drivers/net/bna/bfi_cna.h
@@ -0,0 +1,199 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BFI_CNA_H__
+#define __BFI_CNA_H__
+
+#include "bfi.h"
+#include "bfa_defs_cna.h"
+
+#pragma pack(1)
+
+enum bfi_port_h2i {
+	BFI_PORT_H2I_ENABLE_REQ		= (1),
+	BFI_PORT_H2I_DISABLE_REQ	= (2),
+	BFI_PORT_H2I_GET_STATS_REQ	= (3),
+	BFI_PORT_H2I_CLEAR_STATS_REQ	= (4),
+};
+
+enum bfi_port_i2h {
+	BFI_PORT_I2H_ENABLE_RSP		= BFA_I2HM(1),
+	BFI_PORT_I2H_DISABLE_RSP	= BFA_I2HM(2),
+	BFI_PORT_I2H_GET_STATS_RSP	= BFA_I2HM(3),
+	BFI_PORT_I2H_CLEAR_STATS_RSP	= BFA_I2HM(4),
+};
+
+/**
+ * Generic REQ type
+ */
+struct bfi_port_generic_req {
+	struct bfi_mhdr mh;		/*!< msg header			    */
+	u32	msgtag;		/*!< msgtag for reply		    */
+	u32	rsvd;
+};
+
+/**
+ * Generic RSP type
+ */
+struct bfi_port_generic_rsp {
+	struct bfi_mhdr mh;		/*!< common msg header		    */
+	u8		status;		/*!< port enable status		    */
+	u8		rsvd[3];
+	u32	msgtag;		/*!< msgtag for reply		    */
+};
+
+/**
+ * @todo
+ * BFI_PORT_H2I_ENABLE_REQ
+ */
+
+/**
+ * @todo
+ * BFI_PORT_I2H_ENABLE_RSP
+ */
+
+/**
+ * BFI_PORT_H2I_DISABLE_REQ
+ */
+
+/**
+ * BFI_PORT_I2H_DISABLE_RSP
+ */
+
+/**
+ * BFI_PORT_H2I_GET_STATS_REQ
+ */
+struct bfi_port_get_stats_req {
+	struct bfi_mhdr mh;		/*!< common msg header		    */
+	union bfi_addr_u   dma_addr;
+};
+
+/**
+ * BFI_PORT_I2H_GET_STATS_RSP
+ */
+
+/**
+ * BFI_PORT_H2I_CLEAR_STATS_REQ
+ */
+
+/**
+ * BFI_PORT_I2H_CLEAR_STATS_RSP
+ */
+
+union bfi_port_h2i_msg_u {
+	struct bfi_mhdr mh;
+	struct bfi_port_generic_req enable_req;
+	struct bfi_port_generic_req disable_req;
+	struct bfi_port_get_stats_req getstats_req;
+	struct bfi_port_generic_req clearstats_req;
+};
+
+union bfi_port_i2h_msg_u {
+	struct bfi_mhdr mh;
+	struct bfi_port_generic_rsp enable_rsp;
+	struct bfi_port_generic_rsp disable_rsp;
+	struct bfi_port_generic_rsp getstats_rsp;
+	struct bfi_port_generic_rsp clearstats_rsp;
+};
+
+/* @brief Mailbox commands from host to (DCBX/LLDP) firmware */
+enum bfi_cee_h2i_msgs {
+	BFI_CEE_H2I_GET_CFG_REQ = 1,
+	BFI_CEE_H2I_RESET_STATS = 2,
+	BFI_CEE_H2I_GET_STATS_REQ = 3,
+};
+
+/* @brief Mailbox reply and AEN messages from DCBX/LLDP firmware to host */
+enum bfi_cee_i2h_msgs {
+	BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1),
+	BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2),
+	BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3),
+};
+
+/* Data structures */
+
+/*
+ * @brief H2I command structure for resetting the stats.
+ * BFI_CEE_H2I_RESET_STATS
+ */
+struct bfi_lldp_reset_stats {
+	struct bfi_mhdr mh;
+};
+
+/*
+ * @brief H2I command structure for resetting the stats.
+ * BFI_CEE_H2I_RESET_STATS
+ */
+struct bfi_cee_reset_stats {
+	struct bfi_mhdr mh;
+};
+
+/*
+ * @brief  get configuration  command from host
+ * BFI_CEE_H2I_GET_CFG_REQ
+ */
+struct bfi_cee_get_req {
+	struct bfi_mhdr mh;
+	union bfi_addr_u   dma_addr;
+};
+
+/*
+ * @brief reply message from firmware
+ * BFI_CEE_I2H_GET_CFG_RSP
+ */
+struct bfi_cee_get_rsp {
+	struct bfi_mhdr mh;
+	u8			cmd_status;
+	u8			rsvd[3];
+};
+
+/*
+ * @brief  get configuration  command from host
+ * BFI_CEE_H2I_GET_STATS_REQ
+ */
+struct bfi_cee_stats_req {
+	struct bfi_mhdr mh;
+	union bfi_addr_u   dma_addr;
+};
+
+/*
+ * @brief reply message from firmware
+ * BFI_CEE_I2H_GET_STATS_RSP
+ */
+struct bfi_cee_stats_rsp {
+	struct bfi_mhdr mh;
+	u8			cmd_status;
+	u8			rsvd[3];
+};
+
+/* @brief mailbox command structures from host to firmware */
+union bfi_cee_h2i_msg_u {
+	struct bfi_mhdr mh;
+	struct bfi_cee_get_req get_req;
+	struct bfi_cee_stats_req stats_req;
+};
+
+/* @brief mailbox message structures from firmware to host	*/
+union bfi_cee_i2h_msg_u {
+	struct bfi_mhdr mh;
+	struct bfi_cee_get_rsp get_rsp;
+	struct bfi_cee_stats_rsp stats_rsp;
+};
+
+#pragma pack()
+
+#endif /* __BFI_CNA_H__ */
diff --git a/drivers/net/bna/bfi_ctreg.h b/drivers/net/bna/bfi_ctreg.h
new file mode 100644
index 0000000..404ea351
--- /dev/null
+++ b/drivers/net/bna/bfi_ctreg.h
@@ -0,0 +1,637 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/*
+ * bfi_ctreg.h catapult host block register definitions
+ *
+ * !!! Do not edit. Auto generated. !!!
+ */
+
+#ifndef __BFI_CTREG_H__
+#define __BFI_CTREG_H__
+
+#define HOSTFN0_LPU_MBOX0_0		0x00019200
+#define HOSTFN1_LPU_MBOX0_8		0x00019260
+#define LPU_HOSTFN0_MBOX0_0		0x00019280
+#define LPU_HOSTFN1_MBOX0_8		0x000192e0
+#define HOSTFN2_LPU_MBOX0_0		0x00019400
+#define HOSTFN3_LPU_MBOX0_8		0x00019460
+#define LPU_HOSTFN2_MBOX0_0		0x00019480
+#define LPU_HOSTFN3_MBOX0_8		0x000194e0
+#define HOSTFN0_INT_STATUS		0x00014000
+#define __HOSTFN0_HALT_OCCURRED		0x01000000
+#define __HOSTFN0_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN0_INT_STATUS_LVL_SH	20
+#define __HOSTFN0_INT_STATUS_LVL(_v)	((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
+#define __HOSTFN0_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN0_INT_STATUS_P_SH	16
+#define __HOSTFN0_INT_STATUS_P(_v)	((_v) << __HOSTFN0_INT_STATUS_P_SH)
+#define __HOSTFN0_INT_STATUS_F		0x0000ffff
+#define HOSTFN0_INT_MSK			0x00014004
+#define HOST_PAGE_NUM_FN0		0x00014008
+#define __HOST_PAGE_NUM_FN		0x000001ff
+#define HOST_MSIX_ERR_INDEX_FN0		0x0001400c
+#define __MSIX_ERR_INDEX_FN		0x000001ff
+#define HOSTFN1_INT_STATUS		0x00014100
+#define __HOSTFN1_HALT_OCCURRED		0x01000000
+#define __HOSTFN1_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN1_INT_STATUS_LVL_SH	20
+#define __HOSTFN1_INT_STATUS_LVL(_v)	((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
+#define __HOSTFN1_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN1_INT_STATUS_P_SH	16
+#define __HOSTFN1_INT_STATUS_P(_v)	((_v) << __HOSTFN1_INT_STATUS_P_SH)
+#define __HOSTFN1_INT_STATUS_F		0x0000ffff
+#define HOSTFN1_INT_MSK			0x00014104
+#define HOST_PAGE_NUM_FN1		0x00014108
+#define HOST_MSIX_ERR_INDEX_FN1		0x0001410c
+#define APP_PLL_425_CTL_REG		0x00014204
+#define __P_425_PLL_LOCK		0x80000000
+#define __APP_PLL_425_SRAM_USE_100MHZ	0x00100000
+#define __APP_PLL_425_RESET_TIMER_MK	0x000e0000
+#define __APP_PLL_425_RESET_TIMER_SH	17
+#define __APP_PLL_425_RESET_TIMER(_v)	((_v) << __APP_PLL_425_RESET_TIMER_SH)
+#define __APP_PLL_425_LOGIC_SOFT_RESET	0x00010000
+#define __APP_PLL_425_CNTLMT0_1_MK	0x0000c000
+#define __APP_PLL_425_CNTLMT0_1_SH	14
+#define __APP_PLL_425_CNTLMT0_1(_v)	((_v) << __APP_PLL_425_CNTLMT0_1_SH)
+#define __APP_PLL_425_JITLMT0_1_MK	0x00003000
+#define __APP_PLL_425_JITLMT0_1_SH	12
+#define __APP_PLL_425_JITLMT0_1(_v)	((_v) << __APP_PLL_425_JITLMT0_1_SH)
+#define __APP_PLL_425_HREF		0x00000800
+#define __APP_PLL_425_HDIV		0x00000400
+#define __APP_PLL_425_P0_1_MK		0x00000300
+#define __APP_PLL_425_P0_1_SH		8
+#define __APP_PLL_425_P0_1(_v)		((_v) << __APP_PLL_425_P0_1_SH)
+#define __APP_PLL_425_Z0_2_MK		0x000000e0
+#define __APP_PLL_425_Z0_2_SH		5
+#define __APP_PLL_425_Z0_2(_v)		((_v) << __APP_PLL_425_Z0_2_SH)
+#define __APP_PLL_425_RSEL200500	0x00000010
+#define __APP_PLL_425_ENARST		0x00000008
+#define __APP_PLL_425_BYPASS		0x00000004
+#define __APP_PLL_425_LRESETN		0x00000002
+#define __APP_PLL_425_ENABLE		0x00000001
+#define APP_PLL_312_CTL_REG		0x00014208
+#define __P_312_PLL_LOCK		0x80000000
+#define __ENABLE_MAC_AHB_1		0x00800000
+#define __ENABLE_MAC_AHB_0		0x00400000
+#define __ENABLE_MAC_1			0x00200000
+#define __ENABLE_MAC_0			0x00100000
+#define __APP_PLL_312_RESET_TIMER_MK	0x000e0000
+#define __APP_PLL_312_RESET_TIMER_SH	17
+#define __APP_PLL_312_RESET_TIMER(_v)	((_v) << __APP_PLL_312_RESET_TIMER_SH)
+#define __APP_PLL_312_LOGIC_SOFT_RESET	0x00010000
+#define __APP_PLL_312_CNTLMT0_1_MK	0x0000c000
+#define __APP_PLL_312_CNTLMT0_1_SH	14
+#define __APP_PLL_312_CNTLMT0_1(_v)	((_v) << __APP_PLL_312_CNTLMT0_1_SH)
+#define __APP_PLL_312_JITLMT0_1_MK	0x00003000
+#define __APP_PLL_312_JITLMT0_1_SH	12
+#define __APP_PLL_312_JITLMT0_1(_v)	((_v) << __APP_PLL_312_JITLMT0_1_SH)
+#define __APP_PLL_312_HREF		0x00000800
+#define __APP_PLL_312_HDIV		0x00000400
+#define __APP_PLL_312_P0_1_MK		0x00000300
+#define __APP_PLL_312_P0_1_SH		8
+#define __APP_PLL_312_P0_1(_v)		((_v) << __APP_PLL_312_P0_1_SH)
+#define __APP_PLL_312_Z0_2_MK		0x000000e0
+#define __APP_PLL_312_Z0_2_SH		5
+#define __APP_PLL_312_Z0_2(_v)		((_v) << __APP_PLL_312_Z0_2_SH)
+#define __APP_PLL_312_RSEL200500	0x00000010
+#define __APP_PLL_312_ENARST		0x00000008
+#define __APP_PLL_312_BYPASS		0x00000004
+#define __APP_PLL_312_LRESETN		0x00000002
+#define __APP_PLL_312_ENABLE		0x00000001
+#define MBIST_CTL_REG			0x00014220
+#define __EDRAM_BISTR_START		0x00000004
+#define __MBIST_RESET			0x00000002
+#define __MBIST_START			0x00000001
+#define MBIST_STAT_REG			0x00014224
+#define __EDRAM_BISTR_STATUS		0x00000008
+#define __EDRAM_BISTR_DONE		0x00000004
+#define __MEM_BIT_STATUS		0x00000002
+#define __MBIST_DONE			0x00000001
+#define HOST_SEM0_REG			0x00014230
+#define __HOST_SEMAPHORE		0x00000001
+#define HOST_SEM1_REG			0x00014234
+#define HOST_SEM2_REG			0x00014238
+#define HOST_SEM3_REG			0x0001423c
+#define HOST_SEM0_INFO_REG		0x00014240
+#define HOST_SEM1_INFO_REG		0x00014244
+#define HOST_SEM2_INFO_REG		0x00014248
+#define HOST_SEM3_INFO_REG		0x0001424c
+#define ETH_MAC_SER_REG			0x00014288
+#define __APP_EMS_CKBUFAMPIN		0x00000020
+#define __APP_EMS_REFCLKSEL		0x00000010
+#define __APP_EMS_CMLCKSEL		0x00000008
+#define __APP_EMS_REFCKBUFEN2		0x00000004
+#define __APP_EMS_REFCKBUFEN1		0x00000002
+#define __APP_EMS_CHANNEL_SEL		0x00000001
+#define HOSTFN2_INT_STATUS		0x00014300
+#define __HOSTFN2_HALT_OCCURRED		0x01000000
+#define __HOSTFN2_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN2_INT_STATUS_LVL_SH	20
+#define __HOSTFN2_INT_STATUS_LVL(_v)	((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
+#define __HOSTFN2_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN2_INT_STATUS_P_SH	16
+#define __HOSTFN2_INT_STATUS_P(_v)	((_v) << __HOSTFN2_INT_STATUS_P_SH)
+#define __HOSTFN2_INT_STATUS_F		0x0000ffff
+#define HOSTFN2_INT_MSK			0x00014304
+#define HOST_PAGE_NUM_FN2		0x00014308
+#define HOST_MSIX_ERR_INDEX_FN2		0x0001430c
+#define HOSTFN3_INT_STATUS		0x00014400
+#define __HALT_OCCURRED			0x01000000
+#define __HOSTFN3_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN3_INT_STATUS_LVL_SH	20
+#define __HOSTFN3_INT_STATUS_LVL(_v)	((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
+#define __HOSTFN3_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN3_INT_STATUS_P_SH	16
+#define __HOSTFN3_INT_STATUS_P(_v)	((_v) << __HOSTFN3_INT_STATUS_P_SH)
+#define __HOSTFN3_INT_STATUS_F		0x0000ffff
+#define HOSTFN3_INT_MSK			0x00014404
+#define HOST_PAGE_NUM_FN3		0x00014408
+#define HOST_MSIX_ERR_INDEX_FN3		0x0001440c
+#define FNC_ID_REG			0x00014600
+#define __FUNCTION_NUMBER		0x00000007
+#define FNC_PERS_REG			0x00014604
+#define __F3_FUNCTION_ACTIVE		0x80000000
+#define __F3_FUNCTION_MODE		0x40000000
+#define __F3_PORT_MAP_MK		0x30000000
+#define __F3_PORT_MAP_SH		28
+#define __F3_PORT_MAP(_v)		((_v) << __F3_PORT_MAP_SH)
+#define __F3_VM_MODE			0x08000000
+#define __F3_INTX_STATUS_MK		0x07000000
+#define __F3_INTX_STATUS_SH		24
+#define __F3_INTX_STATUS(_v)		((_v) << __F3_INTX_STATUS_SH)
+#define __F2_FUNCTION_ACTIVE		0x00800000
+#define __F2_FUNCTION_MODE		0x00400000
+#define __F2_PORT_MAP_MK		0x00300000
+#define __F2_PORT_MAP_SH		20
+#define __F2_PORT_MAP(_v)		((_v) << __F2_PORT_MAP_SH)
+#define __F2_VM_MODE			0x00080000
+#define __F2_INTX_STATUS_MK		0x00070000
+#define __F2_INTX_STATUS_SH		16
+#define __F2_INTX_STATUS(_v)		((_v) << __F2_INTX_STATUS_SH)
+#define __F1_FUNCTION_ACTIVE		0x00008000
+#define __F1_FUNCTION_MODE		0x00004000
+#define __F1_PORT_MAP_MK		0x00003000
+#define __F1_PORT_MAP_SH		12
+#define __F1_PORT_MAP(_v)		((_v) << __F1_PORT_MAP_SH)
+#define __F1_VM_MODE			0x00000800
+#define __F1_INTX_STATUS_MK		0x00000700
+#define __F1_INTX_STATUS_SH		8
+#define __F1_INTX_STATUS(_v)		((_v) << __F1_INTX_STATUS_SH)
+#define __F0_FUNCTION_ACTIVE		0x00000080
+#define __F0_FUNCTION_MODE		0x00000040
+#define __F0_PORT_MAP_MK		0x00000030
+#define __F0_PORT_MAP_SH		4
+#define __F0_PORT_MAP(_v)		((_v) << __F0_PORT_MAP_SH)
+#define __F0_VM_MODE		0x00000008
+#define __F0_INTX_STATUS		0x00000007
+enum {
+	__F0_INTX_STATUS_MSIX		= 0x0,
+	__F0_INTX_STATUS_INTA		= 0x1,
+	__F0_INTX_STATUS_INTB		= 0x2,
+	__F0_INTX_STATUS_INTC		= 0x3,
+	__F0_INTX_STATUS_INTD		= 0x4,
+};
+#define OP_MODE				0x0001460c
+#define __APP_ETH_CLK_LOWSPEED		0x00000004
+#define __GLOBAL_CORECLK_HALFSPEED	0x00000002
+#define __GLOBAL_FCOE_MODE		0x00000001
+#define HOST_SEM4_REG			0x00014610
+#define HOST_SEM5_REG			0x00014614
+#define HOST_SEM6_REG			0x00014618
+#define HOST_SEM7_REG			0x0001461c
+#define HOST_SEM4_INFO_REG		0x00014620
+#define HOST_SEM5_INFO_REG		0x00014624
+#define HOST_SEM6_INFO_REG		0x00014628
+#define HOST_SEM7_INFO_REG		0x0001462c
+#define HOSTFN0_LPU0_MBOX0_CMD_STAT	0x00019000
+#define __HOSTFN0_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN0_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN0_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN0_LPU1_MBOX0_CMD_STAT	0x00019004
+#define __HOSTFN0_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN0_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN0_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN0_MBOX0_CMD_STAT	0x00019008
+#define __LPU0_HOSTFN0_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN0_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN0_MBOX0_CMD_STAT	0x0001900c
+#define __LPU1_HOSTFN0_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN0_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN1_LPU0_MBOX0_CMD_STAT	0x00019010
+#define __HOSTFN1_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN1_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN1_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN1_LPU1_MBOX0_CMD_STAT	0x00019014
+#define __HOSTFN1_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN1_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN1_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN1_MBOX0_CMD_STAT	0x00019018
+#define __LPU0_HOSTFN1_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN1_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN1_MBOX0_CMD_STAT	0x0001901c
+#define __LPU1_HOSTFN1_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN1_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN2_LPU0_MBOX0_CMD_STAT	0x00019150
+#define __HOSTFN2_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN2_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN2_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN2_LPU1_MBOX0_CMD_STAT	0x00019154
+#define __HOSTFN2_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN2_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN2_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN2_MBOX0_CMD_STAT	0x00019158
+#define __LPU0_HOSTFN2_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN2_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN2_MBOX0_CMD_STAT	0x0001915c
+#define __LPU1_HOSTFN2_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN2_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN3_LPU0_MBOX0_CMD_STAT	0x00019160
+#define __HOSTFN3_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN3_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN3_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN3_LPU1_MBOX0_CMD_STAT	0x00019164
+#define __HOSTFN3_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN3_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN3_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN3_MBOX0_CMD_STAT	0x00019168
+#define __LPU0_HOSTFN3_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN3_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN3_MBOX0_CMD_STAT	0x0001916c
+#define __LPU1_HOSTFN3_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN3_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS	0x00000001
+#define FW_INIT_HALT_P0			0x000191ac
+#define __FW_INIT_HALT_P		0x00000001
+#define FW_INIT_HALT_P1			0x000191bc
+#define CPE_PI_PTR_Q0			0x00038000
+#define __CPE_PI_UNUSED_MK		0xffff0000
+#define __CPE_PI_UNUSED_SH		16
+#define __CPE_PI_UNUSED(_v)		((_v) << __CPE_PI_UNUSED_SH)
+#define __CPE_PI_PTR			0x0000ffff
+#define CPE_PI_PTR_Q1			0x00038040
+#define CPE_CI_PTR_Q0			0x00038004
+#define __CPE_CI_UNUSED_MK		0xffff0000
+#define __CPE_CI_UNUSED_SH		16
+#define __CPE_CI_UNUSED(_v)		((_v) << __CPE_CI_UNUSED_SH)
+#define __CPE_CI_PTR			0x0000ffff
+#define CPE_CI_PTR_Q1			0x00038044
+#define CPE_DEPTH_Q0			0x00038008
+#define __CPE_DEPTH_UNUSED_MK		0xf8000000
+#define __CPE_DEPTH_UNUSED_SH		27
+#define __CPE_DEPTH_UNUSED(_v)		((_v) << __CPE_DEPTH_UNUSED_SH)
+#define __CPE_MSIX_VEC_INDEX_MK		0x07ff0000
+#define __CPE_MSIX_VEC_INDEX_SH		16
+#define __CPE_MSIX_VEC_INDEX(_v)	((_v) << __CPE_MSIX_VEC_INDEX_SH)
+#define __CPE_DEPTH			0x0000ffff
+#define CPE_DEPTH_Q1			0x00038048
+#define CPE_QCTRL_Q0			0x0003800c
+#define __CPE_CTRL_UNUSED30_MK		0xfc000000
+#define __CPE_CTRL_UNUSED30_SH		26
+#define __CPE_CTRL_UNUSED30(_v)		((_v) << __CPE_CTRL_UNUSED30_SH)
+#define __CPE_FUNC_INT_CTRL_MK		0x03000000
+#define __CPE_FUNC_INT_CTRL_SH		24
+#define __CPE_FUNC_INT_CTRL(_v)		((_v) << __CPE_FUNC_INT_CTRL_SH)
+enum {
+	__CPE_FUNC_INT_CTRL_DISABLE		= 0x0,
+	__CPE_FUNC_INT_CTRL_F2NF		= 0x1,
+	__CPE_FUNC_INT_CTRL_3QUART		= 0x2,
+	__CPE_FUNC_INT_CTRL_HALF		= 0x3,
+};
+#define __CPE_CTRL_UNUSED20_MK		0x00f00000
+#define __CPE_CTRL_UNUSED20_SH		20
+#define __CPE_CTRL_UNUSED20(_v)		((_v) << __CPE_CTRL_UNUSED20_SH)
+#define __CPE_SCI_TH_MK			0x000f0000
+#define __CPE_SCI_TH_SH			16
+#define __CPE_SCI_TH(_v)		((_v) << __CPE_SCI_TH_SH)
+#define __CPE_CTRL_UNUSED10_MK		0x0000c000
+#define __CPE_CTRL_UNUSED10_SH		14
+#define __CPE_CTRL_UNUSED10(_v)		((_v) << __CPE_CTRL_UNUSED10_SH)
+#define __CPE_ACK_PENDING		0x00002000
+#define __CPE_CTRL_UNUSED40_MK		0x00001c00
+#define __CPE_CTRL_UNUSED40_SH		10
+#define __CPE_CTRL_UNUSED40(_v)		((_v) << __CPE_CTRL_UNUSED40_SH)
+#define __CPE_PCIEID_MK			0x00000300
+#define __CPE_PCIEID_SH			8
+#define __CPE_PCIEID(_v)		((_v) << __CPE_PCIEID_SH)
+#define __CPE_CTRL_UNUSED00_MK		0x000000fe
+#define __CPE_CTRL_UNUSED00_SH		1
+#define __CPE_CTRL_UNUSED00(_v)		((_v) << __CPE_CTRL_UNUSED00_SH)
+#define __CPE_ESIZE			0x00000001
+#define CPE_QCTRL_Q1			0x0003804c
+#define __CPE_CTRL_UNUSED31_MK		0xfc000000
+#define __CPE_CTRL_UNUSED31_SH		26
+#define __CPE_CTRL_UNUSED31(_v)		((_v) << __CPE_CTRL_UNUSED31_SH)
+#define __CPE_CTRL_UNUSED21_MK		0x00f00000
+#define __CPE_CTRL_UNUSED21_SH		20
+#define __CPE_CTRL_UNUSED21(_v)		((_v) << __CPE_CTRL_UNUSED21_SH)
+#define __CPE_CTRL_UNUSED11_MK		0x0000c000
+#define __CPE_CTRL_UNUSED11_SH		14
+#define __CPE_CTRL_UNUSED11(_v)		((_v) << __CPE_CTRL_UNUSED11_SH)
+#define __CPE_CTRL_UNUSED41_MK		0x00001c00
+#define __CPE_CTRL_UNUSED41_SH		10
+#define __CPE_CTRL_UNUSED41(_v)		((_v) << __CPE_CTRL_UNUSED41_SH)
+#define __CPE_CTRL_UNUSED01_MK		0x000000fe
+#define __CPE_CTRL_UNUSED01_SH		1
+#define __CPE_CTRL_UNUSED01(_v)		((_v) << __CPE_CTRL_UNUSED01_SH)
+#define RME_PI_PTR_Q0			0x00038020
+#define __LATENCY_TIME_STAMP_MK		0xffff0000
+#define __LATENCY_TIME_STAMP_SH		16
+#define __LATENCY_TIME_STAMP(_v)	((_v) << __LATENCY_TIME_STAMP_SH)
+#define __RME_PI_PTR			0x0000ffff
+#define RME_PI_PTR_Q1			0x00038060
+#define RME_CI_PTR_Q0			0x00038024
+#define __DELAY_TIME_STAMP_MK		0xffff0000
+#define __DELAY_TIME_STAMP_SH		16
+#define __DELAY_TIME_STAMP(_v)		((_v) << __DELAY_TIME_STAMP_SH)
+#define __RME_CI_PTR			0x0000ffff
+#define RME_CI_PTR_Q1			0x00038064
+#define RME_DEPTH_Q0			0x00038028
+#define __RME_DEPTH_UNUSED_MK		0xf8000000
+#define __RME_DEPTH_UNUSED_SH		27
+#define __RME_DEPTH_UNUSED(_v)		((_v) << __RME_DEPTH_UNUSED_SH)
+#define __RME_MSIX_VEC_INDEX_MK		0x07ff0000
+#define __RME_MSIX_VEC_INDEX_SH		16
+#define __RME_MSIX_VEC_INDEX(_v)	((_v) << __RME_MSIX_VEC_INDEX_SH)
+#define __RME_DEPTH			0x0000ffff
+#define RME_DEPTH_Q1			0x00038068
+#define RME_QCTRL_Q0			0x0003802c
+#define __RME_INT_LATENCY_TIMER_MK	0xff000000
+#define __RME_INT_LATENCY_TIMER_SH	24
+#define __RME_INT_LATENCY_TIMER(_v)	((_v) << __RME_INT_LATENCY_TIMER_SH)
+#define __RME_INT_DELAY_TIMER_MK	0x00ff0000
+#define __RME_INT_DELAY_TIMER_SH	16
+#define __RME_INT_DELAY_TIMER(_v)	((_v) << __RME_INT_DELAY_TIMER_SH)
+#define __RME_INT_DELAY_DISABLE		0x00008000
+#define __RME_DLY_DELAY_DISABLE		0x00004000
+#define __RME_ACK_PENDING		0x00002000
+#define __RME_FULL_INTERRUPT_DISABLE	0x00001000
+#define __RME_CTRL_UNUSED10_MK		0x00000c00
+#define __RME_CTRL_UNUSED10_SH		10
+#define __RME_CTRL_UNUSED10(_v)		((_v) << __RME_CTRL_UNUSED10_SH)
+#define __RME_PCIEID_MK			0x00000300
+#define __RME_PCIEID_SH			8
+#define __RME_PCIEID(_v)		((_v) << __RME_PCIEID_SH)
+#define __RME_CTRL_UNUSED00_MK		0x000000fe
+#define __RME_CTRL_UNUSED00_SH		1
+#define __RME_CTRL_UNUSED00(_v)		((_v) << __RME_CTRL_UNUSED00_SH)
+#define __RME_ESIZE			0x00000001
+#define RME_QCTRL_Q1			0x0003806c
+#define __RME_CTRL_UNUSED11_MK		0x00000c00
+#define __RME_CTRL_UNUSED11_SH		10
+#define __RME_CTRL_UNUSED11(_v)		((_v) << __RME_CTRL_UNUSED11_SH)
+#define __RME_CTRL_UNUSED01_MK		0x000000fe
+#define __RME_CTRL_UNUSED01_SH		1
+#define __RME_CTRL_UNUSED01(_v)		((_v) << __RME_CTRL_UNUSED01_SH)
+#define PSS_CTL_REG			0x00018800
+#define __PSS_I2C_CLK_DIV_MK		0x007f0000
+#define __PSS_I2C_CLK_DIV_SH		16
+#define __PSS_I2C_CLK_DIV(_v)		((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE		0x00001000
+#define __PSS_LMEM_RESET		0x00000200
+#define __PSS_LMEM_INIT_EN		0x00000100
+#define __PSS_LPU1_RESET		0x00000002
+#define __PSS_LPU0_RESET		0x00000001
+#define PSS_ERR_STATUS_REG		0x00018810
+#define __PSS_LPU1_TCM_READ_ERR		0x00200000
+#define __PSS_LPU0_TCM_READ_ERR		0x00100000
+#define __PSS_LMEM5_CORR_ERR		0x00080000
+#define __PSS_LMEM4_CORR_ERR		0x00040000
+#define __PSS_LMEM3_CORR_ERR		0x00020000
+#define __PSS_LMEM2_CORR_ERR		0x00010000
+#define __PSS_LMEM1_CORR_ERR		0x00008000
+#define __PSS_LMEM0_CORR_ERR		0x00004000
+#define __PSS_LMEM5_UNCORR_ERR		0x00002000
+#define __PSS_LMEM4_UNCORR_ERR		0x00001000
+#define __PSS_LMEM3_UNCORR_ERR		0x00000800
+#define __PSS_LMEM2_UNCORR_ERR		0x00000400
+#define __PSS_LMEM1_UNCORR_ERR		0x00000200
+#define __PSS_LMEM0_UNCORR_ERR		0x00000100
+#define __PSS_BAL_PERR			0x00000080
+#define __PSS_DIP_IF_ERR		0x00000040
+#define __PSS_IOH_IF_ERR		0x00000020
+#define __PSS_TDS_IF_ERR		0x00000010
+#define __PSS_RDS_IF_ERR		0x00000008
+#define __PSS_SGM_IF_ERR		0x00000004
+#define __PSS_LPU1_RAM_ERR		0x00000002
+#define __PSS_LPU0_RAM_ERR		0x00000001
+#define ERR_SET_REG			0x00018818
+#define __PSS_ERR_STATUS_SET		0x003fffff
+#define PMM_1T_RESET_REG_P0		0x0002381c
+#define __PMM_1T_RESET_P		0x00000001
+#define PMM_1T_RESET_REG_P1		0x00023c1c
+#define HQM_QSET0_RXQ_DRBL_P0		0x00038000
+#define __RXQ0_ADD_VECTORS_P		0x80000000
+#define __RXQ0_STOP_P			0x40000000
+#define __RXQ0_PRD_PTR_P		0x0000ffff
+#define HQM_QSET1_RXQ_DRBL_P0		0x00038080
+#define __RXQ1_ADD_VECTORS_P		0x80000000
+#define __RXQ1_STOP_P			0x40000000
+#define __RXQ1_PRD_PTR_P		0x0000ffff
+#define HQM_QSET0_RXQ_DRBL_P1		0x0003c000
+#define HQM_QSET1_RXQ_DRBL_P1		0x0003c080
+#define HQM_QSET0_TXQ_DRBL_P0		0x00038020
+#define __TXQ0_ADD_VECTORS_P		0x80000000
+#define __TXQ0_STOP_P			0x40000000
+#define __TXQ0_PRD_PTR_P		0x0000ffff
+#define HQM_QSET1_TXQ_DRBL_P0		0x000380a0
+#define __TXQ1_ADD_VECTORS_P		0x80000000
+#define __TXQ1_STOP_P			0x40000000
+#define __TXQ1_PRD_PTR_P		0x0000ffff
+#define HQM_QSET0_TXQ_DRBL_P1		0x0003c020
+#define HQM_QSET1_TXQ_DRBL_P1		0x0003c0a0
+#define HQM_QSET0_IB_DRBL_1_P0		0x00038040
+#define __IB1_0_ACK_P			0x80000000
+#define __IB1_0_DISABLE_P		0x40000000
+#define __IB1_0_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB1_0_COALESCING_CFG_P_SH	16
+#define __IB1_0_COALESCING_CFG_P(_v)	((_v) << __IB1_0_COALESCING_CFG_P_SH)
+#define __IB1_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET1_IB_DRBL_1_P0		0x000380c0
+#define __IB1_1_ACK_P			0x80000000
+#define __IB1_1_DISABLE_P		0x40000000
+#define __IB1_1_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB1_1_COALESCING_CFG_P_SH	16
+#define __IB1_1_COALESCING_CFG_P(_v)	((_v) << __IB1_1_COALESCING_CFG_P_SH)
+#define __IB1_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET0_IB_DRBL_1_P1		0x0003c040
+#define HQM_QSET1_IB_DRBL_1_P1		0x0003c0c0
+#define HQM_QSET0_IB_DRBL_2_P0		0x00038060
+#define __IB2_0_ACK_P			0x80000000
+#define __IB2_0_DISABLE_P		0x40000000
+#define __IB2_0_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB2_0_COALESCING_CFG_P_SH	16
+#define __IB2_0_COALESCING_CFG_P(_v)	((_v) << __IB2_0_COALESCING_CFG_P_SH)
+#define __IB2_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET1_IB_DRBL_2_P0		0x000380e0
+#define __IB2_1_ACK_P			0x80000000
+#define __IB2_1_DISABLE_P		0x40000000
+#define __IB2_1_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB2_1_COALESCING_CFG_P_SH	16
+#define __IB2_1_COALESCING_CFG_P(_v)	((_v) << __IB2_1_COALESCING_CFG_P_SH)
+#define __IB2_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET0_IB_DRBL_2_P1		0x0003c060
+#define HQM_QSET1_IB_DRBL_2_P1		0x0003c0e0
+
+/*
+ * These definitions are either in error/missing in spec. Its auto-generated
+ * from hard coded values in regparse.pl.
+ */
+#define __EMPHPOST_AT_4G_MK_FIX		0x0000001c
+#define __EMPHPOST_AT_4G_SH_FIX		0x00000002
+#define __EMPHPRE_AT_4G_FIX		0x00000003
+#define __SFP_TXRATE_EN_FIX		0x00000100
+#define __SFP_RXRATE_EN_FIX		0x00000080
+
+/*
+ * These register definitions are auto-generated from hard coded values
+ * in regparse.pl.
+ */
+
+/*
+ * These register mapping definitions are auto-generated from mapping tables
+ * in regparse.pl.
+ */
+#define BFA_IOC0_HBEAT_REG		HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG		HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG		HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG		HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT		 HOST_SEM4_INFO_REG
+
+#define CPE_DEPTH_Q(__n) \
+	(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
+#define CPE_QCTRL_Q(__n) \
+	(CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
+#define CPE_PI_PTR_Q(__n) \
+	(CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
+#define CPE_CI_PTR_Q(__n) \
+	(CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
+#define RME_DEPTH_Q(__n) \
+	(RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
+#define RME_QCTRL_Q(__n) \
+	(RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
+#define RME_PI_PTR_Q(__n) \
+	(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
+#define RME_CI_PTR_Q(__n) \
+	(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
+#define HQM_QSET_RXQ_DRBL_P0(__n) (HQM_QSET0_RXQ_DRBL_P0 + (__n) \
+	* (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
+#define HQM_QSET_TXQ_DRBL_P0(__n) (HQM_QSET0_TXQ_DRBL_P0 + (__n) \
+	* (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
+#define HQM_QSET_IB_DRBL_1_P0(__n) (HQM_QSET0_IB_DRBL_1_P0 + (__n) \
+	* (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
+#define HQM_QSET_IB_DRBL_2_P0(__n) (HQM_QSET0_IB_DRBL_2_P0 + (__n) \
+	* (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
+#define HQM_QSET_RXQ_DRBL_P1(__n) (HQM_QSET0_RXQ_DRBL_P1 + (__n) \
+	* (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
+#define HQM_QSET_TXQ_DRBL_P1(__n) (HQM_QSET0_TXQ_DRBL_P1 + (__n) \
+	* (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
+#define HQM_QSET_IB_DRBL_1_P1(__n) (HQM_QSET0_IB_DRBL_1_P1 + (__n) \
+	* (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
+#define HQM_QSET_IB_DRBL_2_P1(__n) (HQM_QSET0_IB_DRBL_2_P1 + (__n) \
+	* (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
+
+#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+#define CPE_Q_MASK(__q) ((__q) & 0x3)
+#define RME_Q_MASK(__q) ((__q) & 0x3)
+
+/*
+ * PCI MSI-X vector defines
+ */
+enum {
+	BFA_MSIX_CPE_Q0 = 0,
+	BFA_MSIX_CPE_Q1 = 1,
+	BFA_MSIX_CPE_Q2 = 2,
+	BFA_MSIX_CPE_Q3 = 3,
+	BFA_MSIX_RME_Q0 = 4,
+	BFA_MSIX_RME_Q1 = 5,
+	BFA_MSIX_RME_Q2 = 6,
+	BFA_MSIX_RME_Q3 = 7,
+	BFA_MSIX_LPU_ERR = 8,
+	BFA_MSIX_CT_MAX = 9,
+};
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0		0x00000001U
+#define __HFN_INT_CPE_Q1		0x00000002U
+#define __HFN_INT_CPE_Q2		0x00000004U
+#define __HFN_INT_CPE_Q3		0x00000008U
+#define __HFN_INT_CPE_Q4		0x00000010U
+#define __HFN_INT_CPE_Q5		0x00000020U
+#define __HFN_INT_CPE_Q6		0x00000040U
+#define __HFN_INT_CPE_Q7		0x00000080U
+#define __HFN_INT_RME_Q0		0x00000100U
+#define __HFN_INT_RME_Q1		0x00000200U
+#define __HFN_INT_RME_Q2		0x00000400U
+#define __HFN_INT_RME_Q3		0x00000800U
+#define __HFN_INT_RME_Q4		0x00001000U
+#define __HFN_INT_RME_Q5		0x00002000U
+#define __HFN_INT_RME_Q6		0x00004000U
+#define __HFN_INT_RME_Q7		0x00008000U
+#define __HFN_INT_ERR_EMC		0x00010000U
+#define __HFN_INT_ERR_LPU0		0x00020000U
+#define __HFN_INT_ERR_LPU1		0x00040000U
+#define __HFN_INT_ERR_PSS		0x00080000U
+#define __HFN_INT_MBOX_LPU0		0x00100000U
+#define __HFN_INT_MBOX_LPU1		0x00200000U
+#define __HFN_INT_MBOX1_LPU0		0x00400000U
+#define __HFN_INT_MBOX1_LPU1		0x00800000U
+#define __HFN_INT_LL_HALT		0x01000000U
+#define __HFN_INT_CPE_MASK		0x000000ffU
+#define __HFN_INT_RME_MASK		0x0000ff00U
+
+/*
+ * catapult memory map.
+ */
+#define LL_PGN_HQM0		0x0096
+#define LL_PGN_HQM1		0x0097
+#define PSS_SMEM_PAGE_START	0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff)
+
+/*
+ * End of catapult memory map
+ */
+
+#endif /* __BFI_CTREG_H__ */
diff --git a/drivers/net/bna/bfi_ll.h b/drivers/net/bna/bfi_ll.h
new file mode 100644
index 0000000..bee4d05
--- /dev/null
+++ b/drivers/net/bna/bfi_ll.h
@@ -0,0 +1,438 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BFI_LL_H__
+#define __BFI_LL_H__
+
+#include "bfi.h"
+
+#pragma pack(1)
+
+/**
+ * @brief
+ *	"enums" for all LL mailbox messages other than IOC
+ */
+enum {
+	BFI_LL_H2I_MAC_UCAST_SET_REQ = 1,
+	BFI_LL_H2I_MAC_UCAST_ADD_REQ = 2,
+	BFI_LL_H2I_MAC_UCAST_DEL_REQ = 3,
+
+	BFI_LL_H2I_MAC_MCAST_ADD_REQ = 4,
+	BFI_LL_H2I_MAC_MCAST_DEL_REQ = 5,
+	BFI_LL_H2I_MAC_MCAST_FILTER_REQ = 6,
+	BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ = 7,
+
+	BFI_LL_H2I_PORT_ADMIN_REQ = 8,
+	BFI_LL_H2I_STATS_GET_REQ = 9,
+	BFI_LL_H2I_STATS_CLEAR_REQ = 10,
+
+	BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ = 11,
+	BFI_LL_H2I_RXF_DEFAULT_SET_REQ = 12,
+
+	BFI_LL_H2I_TXQ_STOP_REQ = 13,
+	BFI_LL_H2I_RXQ_STOP_REQ = 14,
+
+	BFI_LL_H2I_DIAG_LOOPBACK_REQ = 15,
+
+	BFI_LL_H2I_SET_PAUSE_REQ = 16,
+	BFI_LL_H2I_MTU_INFO_REQ = 17,
+
+	BFI_LL_H2I_RX_REQ = 18,
+} ;
+
+enum {
+	BFI_LL_I2H_MAC_UCAST_SET_RSP = BFA_I2HM(1),
+	BFI_LL_I2H_MAC_UCAST_ADD_RSP = BFA_I2HM(2),
+	BFI_LL_I2H_MAC_UCAST_DEL_RSP = BFA_I2HM(3),
+
+	BFI_LL_I2H_MAC_MCAST_ADD_RSP = BFA_I2HM(4),
+	BFI_LL_I2H_MAC_MCAST_DEL_RSP = BFA_I2HM(5),
+	BFI_LL_I2H_MAC_MCAST_FILTER_RSP = BFA_I2HM(6),
+	BFI_LL_I2H_MAC_MCAST_DEL_ALL_RSP = BFA_I2HM(7),
+
+	BFI_LL_I2H_PORT_ADMIN_RSP = BFA_I2HM(8),
+	BFI_LL_I2H_STATS_GET_RSP = BFA_I2HM(9),
+	BFI_LL_I2H_STATS_CLEAR_RSP = BFA_I2HM(10),
+
+	BFI_LL_I2H_RXF_PROMISCUOUS_SET_RSP = BFA_I2HM(11),
+	BFI_LL_I2H_RXF_DEFAULT_SET_RSP = BFA_I2HM(12),
+
+	BFI_LL_I2H_TXQ_STOP_RSP = BFA_I2HM(13),
+	BFI_LL_I2H_RXQ_STOP_RSP = BFA_I2HM(14),
+
+	BFI_LL_I2H_DIAG_LOOPBACK_RSP = BFA_I2HM(15),
+
+	BFI_LL_I2H_SET_PAUSE_RSP = BFA_I2HM(16),
+
+	BFI_LL_I2H_MTU_INFO_RSP = BFA_I2HM(17),
+	BFI_LL_I2H_RX_RSP = BFA_I2HM(18),
+
+	BFI_LL_I2H_LINK_DOWN_AEN = BFA_I2HM(19),
+	BFI_LL_I2H_LINK_UP_AEN = BFA_I2HM(20),
+
+	BFI_LL_I2H_PORT_ENABLE_AEN = BFA_I2HM(21),
+	BFI_LL_I2H_PORT_DISABLE_AEN = BFA_I2HM(22),
+} ;
+
+/**
+ * @brief bfi_ll_mac_addr_req is used by:
+ *        BFI_LL_H2I_MAC_UCAST_SET_REQ
+ *        BFI_LL_H2I_MAC_UCAST_ADD_REQ
+ *        BFI_LL_H2I_MAC_UCAST_DEL_REQ
+ *        BFI_LL_H2I_MAC_MCAST_ADD_REQ
+ *        BFI_LL_H2I_MAC_MCAST_DEL_REQ
+ */
+struct bfi_ll_mac_addr_req {
+	struct bfi_mhdr mh;		/*!< common msg header */
+	u8		rxf_id;
+	u8		rsvd1[3];
+	mac_t		mac_addr;
+	u8		rsvd2[2];
+};
+
+/**
+ * @brief bfi_ll_mcast_filter_req is used by:
+ *	  BFI_LL_H2I_MAC_MCAST_FILTER_REQ
+ */
+struct bfi_ll_mcast_filter_req {
+	struct bfi_mhdr mh;		/*!< common msg header */
+	u8		rxf_id;
+	u8		enable;
+	u8		rsvd[2];
+};
+
+/**
+ * @brief bfi_ll_mcast_del_all is used by:
+ *	  BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ
+ */
+struct bfi_ll_mcast_del_all_req {
+	struct bfi_mhdr mh;		/*!< common msg header */
+	u8		   rxf_id;
+	u8		   rsvd[3];
+};
+
+/**
+ * @brief bfi_ll_q_stop_req is used by:
+ *	BFI_LL_H2I_TXQ_STOP_REQ
+ *	BFI_LL_H2I_RXQ_STOP_REQ
+ */
+struct bfi_ll_q_stop_req {
+	struct bfi_mhdr mh;		/*!< common msg header */
+	u32	q_id_mask[2];	/* !< bit-mask for queue ids */
+};
+
+/**
+ * @brief bfi_ll_stats_req is used by:
+ *    BFI_LL_I2H_STATS_GET_REQ
+ *    BFI_LL_I2H_STATS_CLEAR_REQ
+ */
+struct bfi_ll_stats_req {
+	struct bfi_mhdr mh;	/*!< common msg header */
+	u16 stats_mask;	/* !< bit-mask for non-function statistics */
+	u8	rsvd[2];
+	u32 rxf_id_mask[2];	/* !< bit-mask for RxF Statistics */
+	u32 txf_id_mask[2];	/* !< bit-mask for TxF Statistics */
+	union bfi_addr_u  host_buffer;	/* !< where statistics are returned */
+};
+
+/**
+ * @brief defines for "stats_mask" above.
+ */
+#define BFI_LL_STATS_MAC	(1 << 0)	/* !< MAC Statistics */
+#define BFI_LL_STATS_BPC	(1 << 1)	/* !< Pause Stats from BPC */
+#define BFI_LL_STATS_RAD	(1 << 2)	/* !< Rx Admission Statistics */
+#define BFI_LL_STATS_RX_FC	(1 << 3)	/* !< Rx FC Stats from RxA */
+#define BFI_LL_STATS_TX_FC	(1 << 4)	/* !< Tx FC Stats from TxA */
+
+#define BFI_LL_STATS_ALL	0x1f
+
+/**
+ * @brief bfi_ll_port_admin_req
+ */
+struct bfi_ll_port_admin_req {
+	struct bfi_mhdr mh;		/*!< common msg header */
+	u8		 up;
+	u8		 rsvd[3];
+};
+
+/**
+ * @brief bfi_ll_rxf_req is used by:
+ *      BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ
+ *      BFI_LL_H2I_RXF_DEFAULT_SET_REQ
+ */
+struct bfi_ll_rxf_req {
+	struct bfi_mhdr mh;		/*!< common msg header */
+	u8		rxf_id;
+	u8		enable;
+	u8		rsvd[2];
+};
+
+/**
+ * @brief bfi_ll_rxf_multi_req is used by:
+ *	BFI_LL_H2I_RX_REQ
+ */
+struct bfi_ll_rxf_multi_req {
+	struct bfi_mhdr mh;		/*!< common msg header */
+	u32	rxf_id_mask[2];
+	u8		enable;
+	u8		rsvd[3];
+};
+
+/**
+ * @brief enum for Loopback opmodes
+ */
+enum {
+	BFI_LL_DIAG_LB_OPMODE_EXT = 0,
+	BFI_LL_DIAG_LB_OPMODE_CBL = 1,
+};
+
+/**
+ * @brief bfi_ll_set_pause_req is used by:
+ *	BFI_LL_H2I_SET_PAUSE_REQ
+ */
+struct bfi_ll_set_pause_req {
+	struct bfi_mhdr mh;
+	u8		tx_pause; /* 1 = enable, 0 =  disable */
+	u8		rx_pause; /* 1 = enable, 0 =  disable */
+	u8		rsvd[2];
+};
+
+/**
+ * @brief bfi_ll_mtu_info_req is used by:
+ *	BFI_LL_H2I_MTU_INFO_REQ
+ */
+struct bfi_ll_mtu_info_req {
+	struct bfi_mhdr mh;
+	u16	mtu;
+	u8		rsvd[2];
+};
+
+/**
+ * @brief
+ *	  Response header format used by all responses
+ *	  For both responses and asynchronous notifications
+ */
+struct bfi_ll_rsp {
+	struct bfi_mhdr mh;		/*!< common msg header */
+	u8		error;
+	u8		rsvd[3];
+};
+
+/**
+ * @brief bfi_ll_cee_aen is used by:
+ *	BFI_LL_I2H_LINK_DOWN_AEN
+ *	BFI_LL_I2H_LINK_UP_AEN
+ */
+struct bfi_ll_aen {
+	struct bfi_mhdr mh;		/*!< common msg header */
+	u32	reason;
+	u8		cee_linkup;
+	u8		prio_map;    /*!< LL priority bit-map */
+	u8		rsvd[2];
+};
+
+/**
+ * @brief
+ * 	The following error codes can be returned
+ *	by the mbox commands
+ */
+enum {
+	BFI_LL_CMD_OK 		= 0,
+	BFI_LL_CMD_FAIL 	= 1,
+	BFI_LL_CMD_DUP_ENTRY	= 2,	/* !< Duplicate entry in CAM */
+	BFI_LL_CMD_CAM_FULL	= 3,	/* !< CAM is full */
+	BFI_LL_CMD_NOT_OWNER	= 4,   	/* !< Not permitted, b'cos not owner */
+	BFI_LL_CMD_NOT_EXEC	= 5,   	/* !< Was not sent to f/w at all */
+	BFI_LL_CMD_WAITING	= 6,	/* !< Waiting for completion (VMware) */
+	BFI_LL_CMD_PORT_DISABLED	= 7,	/* !< port in disabled state */
+} ;
+
+/* Statistics */
+#define BFI_LL_TXF_ID_MAX  	64
+#define BFI_LL_RXF_ID_MAX  	64
+
+/* TxF Frame Statistics */
+struct bfi_ll_stats_txf {
+	u64 ucast_octets;
+	u64 ucast;
+	u64 ucast_vlan;
+
+	u64 mcast_octets;
+	u64 mcast;
+	u64 mcast_vlan;
+
+	u64 bcast_octets;
+	u64 bcast;
+	u64 bcast_vlan;
+
+	u64 errors;
+	u64 filter_vlan;      /* frames filtered due to VLAN */
+	u64 filter_mac_sa;    /* frames filtered due to SA check */
+};
+
+/* RxF Frame Statistics */
+struct bfi_ll_stats_rxf {
+	u64 ucast_octets;
+	u64 ucast;
+	u64 ucast_vlan;
+
+	u64 mcast_octets;
+	u64 mcast;
+	u64 mcast_vlan;
+
+	u64 bcast_octets;
+	u64 bcast;
+	u64 bcast_vlan;
+	u64 frame_drops;
+};
+
+/* FC Tx Frame Statistics */
+struct bfi_ll_stats_fc_tx {
+	u64 txf_ucast_octets;
+	u64 txf_ucast;
+	u64 txf_ucast_vlan;
+
+	u64 txf_mcast_octets;
+	u64 txf_mcast;
+	u64 txf_mcast_vlan;
+
+	u64 txf_bcast_octets;
+	u64 txf_bcast;
+	u64 txf_bcast_vlan;
+
+	u64 txf_parity_errors;
+	u64 txf_timeout;
+	u64 txf_fid_parity_errors;
+};
+
+/* FC Rx Frame Statistics */
+struct bfi_ll_stats_fc_rx {
+	u64 rxf_ucast_octets;
+	u64 rxf_ucast;
+	u64 rxf_ucast_vlan;
+
+	u64 rxf_mcast_octets;
+	u64 rxf_mcast;
+	u64 rxf_mcast_vlan;
+
+	u64 rxf_bcast_octets;
+	u64 rxf_bcast;
+	u64 rxf_bcast_vlan;
+};
+
+/* RAD Frame Statistics */
+struct bfi_ll_stats_rad {
+	u64 rx_frames;
+	u64 rx_octets;
+	u64 rx_vlan_frames;
+
+	u64 rx_ucast;
+	u64 rx_ucast_octets;
+	u64 rx_ucast_vlan;
+
+	u64 rx_mcast;
+	u64 rx_mcast_octets;
+	u64 rx_mcast_vlan;
+
+	u64 rx_bcast;
+	u64 rx_bcast_octets;
+	u64 rx_bcast_vlan;
+
+	u64 rx_drops;
+};
+
+/* BPC Tx Registers */
+struct bfi_ll_stats_bpc {
+	/* transmit stats */
+	u64 tx_pause[8];
+	u64 tx_zero_pause[8];	/*!< Pause cancellation */
+	/*!<Pause initiation rather than retention */
+	u64 tx_first_pause[8];
+
+	/* receive stats */
+	u64 rx_pause[8];
+	u64 rx_zero_pause[8];	/*!< Pause cancellation */
+	/*!<Pause initiation rather than retention */
+	u64 rx_first_pause[8];
+};
+
+/* MAC Rx Statistics */
+struct bfi_ll_stats_mac {
+	u64 frame_64;		/* both rx and tx counter */
+	u64 frame_65_127;		/* both rx and tx counter */
+	u64 frame_128_255;		/* both rx and tx counter */
+	u64 frame_256_511;		/* both rx and tx counter */
+	u64 frame_512_1023;	/* both rx and tx counter */
+	u64 frame_1024_1518;	/* both rx and tx counter */
+	u64 frame_1519_1522;	/* both rx and tx counter */
+
+	/* receive stats */
+	u64 rx_bytes;
+	u64 rx_packets;
+	u64 rx_fcs_error;
+	u64 rx_multicast;
+	u64 rx_broadcast;
+	u64 rx_control_frames;
+	u64 rx_pause;
+	u64 rx_unknown_opcode;
+	u64 rx_alignment_error;
+	u64 rx_frame_length_error;
+	u64 rx_code_error;
+	u64 rx_carrier_sense_error;
+	u64 rx_undersize;
+	u64 rx_oversize;
+	u64 rx_fragments;
+	u64 rx_jabber;
+	u64 rx_drop;
+
+	/* transmit stats */
+	u64 tx_bytes;
+	u64 tx_packets;
+	u64 tx_multicast;
+	u64 tx_broadcast;
+	u64 tx_pause;
+	u64 tx_deferral;
+	u64 tx_excessive_deferral;
+	u64 tx_single_collision;
+	u64 tx_muliple_collision;
+	u64 tx_late_collision;
+	u64 tx_excessive_collision;
+	u64 tx_total_collision;
+	u64 tx_pause_honored;
+	u64 tx_drop;
+	u64 tx_jabber;
+	u64 tx_fcs_error;
+	u64 tx_control_frame;
+	u64 tx_oversize;
+	u64 tx_undersize;
+	u64 tx_fragments;
+};
+
+/* Complete statistics */
+struct bfi_ll_stats {
+	struct bfi_ll_stats_mac		mac_stats;
+	struct bfi_ll_stats_bpc		bpc_stats;
+	struct bfi_ll_stats_rad		rad_stats;
+	struct bfi_ll_stats_fc_rx	fc_rx_stats;
+	struct bfi_ll_stats_fc_tx	fc_tx_stats;
+	struct bfi_ll_stats_rxf	rxf_stats[BFI_LL_RXF_ID_MAX];
+	struct bfi_ll_stats_txf	txf_stats[BFI_LL_TXF_ID_MAX];
+};
+
+#pragma pack()
+
+#endif  /* __BFI_LL_H__ */
diff --git a/drivers/net/bna/bna.h b/drivers/net/bna/bna.h
new file mode 100644
index 0000000..df6676b
--- /dev/null
+++ b/drivers/net/bna/bna.h
@@ -0,0 +1,550 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BNA_H__
+#define __BNA_H__
+
+#include "bfa_wc.h"
+#include "bfa_ioc.h"
+#include "cna.h"
+#include "bfi_ll.h"
+#include "bna_types.h"
+
+extern const u32 bna_napi_dim_vector[][BNA_BIAS_T_MAX];
+
+/**
+ *
+ *  Macros and constants
+ *
+ */
+
+#define BNA_IOC_TIMER_FREQ		200
+
+/* Log string size */
+#define BNA_MESSAGE_SIZE		256
+
+#define bna_device_timer(_dev)		bfa_timer_beat(&((_dev)->timer_mod))
+
+/* MBOX API for PORT, TX, RX */
+#define bna_mbox_qe_fill(_qe, _cmd, _cmd_len, _cbfn, _cbarg)		\
+do {									\
+	memcpy(&((_qe)->cmd.msg[0]), (_cmd), (_cmd_len));	\
+	(_qe)->cbfn = (_cbfn);						\
+	(_qe)->cbarg = (_cbarg);					\
+} while (0)
+
+#define bna_is_small_rxq(rcb) ((rcb)->id == 1)
+
+#define BNA_MAC_IS_EQUAL(_mac1, _mac2)					\
+	(!memcmp((_mac1), (_mac2), sizeof(mac_t)))
+
+#define BNA_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
+
+#define BNA_TO_POWER_OF_2(x)						\
+do {									\
+	int _shift = 0;							\
+	while ((x) && (x) != 1) {					\
+		(x) >>= 1;						\
+		_shift++;						\
+	}								\
+	(x) <<= _shift;							\
+} while (0)
+
+#define BNA_TO_POWER_OF_2_HIGH(x)					\
+do {									\
+	int n = 1;							\
+	while (n < (x))							\
+		n <<= 1;						\
+	(x) = n;							\
+} while (0)
+
+/*
+ * input : _addr-> os dma addr in host endian format,
+ * output : _bna_dma_addr-> pointer to hw dma addr
+ */
+#define BNA_SET_DMA_ADDR(_addr, _bna_dma_addr)				\
+do {									\
+	u64 tmp_addr =						\
+	cpu_to_be64((u64)(_addr));				\
+	(_bna_dma_addr)->msb = ((struct bna_dma_addr *)&tmp_addr)->msb; \
+	(_bna_dma_addr)->lsb = ((struct bna_dma_addr *)&tmp_addr)->lsb; \
+} while (0)
+
+/*
+ * input : _bna_dma_addr-> pointer to hw dma addr
+ * output : _addr-> os dma addr in host endian format
+ */
+#define BNA_GET_DMA_ADDR(_bna_dma_addr, _addr)			\
+do {								\
+	(_addr) = ((((u64)ntohl((_bna_dma_addr)->msb))) << 32)		\
+	| ((ntohl((_bna_dma_addr)->lsb) & 0xffffffff));	\
+} while (0)
+
+#define	containing_rec(addr, type, field)				\
+	((type *)((unsigned char *)(addr) - 				\
+	(unsigned char *)(&((type *)0)->field)))
+
+#define BNA_TXQ_WI_NEEDED(_vectors)	(((_vectors) + 3) >> 2)
+
+/* TxQ element is 64 bytes */
+#define BNA_TXQ_PAGE_INDEX_MAX		(PAGE_SIZE >> 6)
+#define BNA_TXQ_PAGE_INDEX_MAX_SHIFT	(PAGE_SHIFT - 6)
+
+#define BNA_TXQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range) \
+{									\
+	unsigned int page_index;	/* index within a page */	\
+	void *page_addr;						\
+	page_index = (_qe_idx) & (BNA_TXQ_PAGE_INDEX_MAX - 1); 		\
+	(_qe_ptr_range) = (BNA_TXQ_PAGE_INDEX_MAX - page_index); 	\
+	page_addr = (_qpt_ptr)[((_qe_idx) >>  BNA_TXQ_PAGE_INDEX_MAX_SHIFT)];\
+	(_qe_ptr) = &((struct bna_txq_entry *)(page_addr))[page_index]; \
+}
+
+/* RxQ element is 8 bytes */
+#define BNA_RXQ_PAGE_INDEX_MAX		(PAGE_SIZE >> 3)
+#define BNA_RXQ_PAGE_INDEX_MAX_SHIFT	(PAGE_SHIFT - 3)
+
+#define BNA_RXQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range) \
+{									\
+	unsigned int page_index;	/* index within a page */	\
+	void *page_addr;						\
+	page_index = (_qe_idx) & (BNA_RXQ_PAGE_INDEX_MAX - 1);		\
+	(_qe_ptr_range) = (BNA_RXQ_PAGE_INDEX_MAX - page_index);	\
+	page_addr = (_qpt_ptr)[((_qe_idx) >>				\
+				BNA_RXQ_PAGE_INDEX_MAX_SHIFT)];		\
+	(_qe_ptr) = &((struct bna_rxq_entry *)(page_addr))[page_index]; \
+}
+
+/* CQ element is 16 bytes */
+#define BNA_CQ_PAGE_INDEX_MAX		(PAGE_SIZE >> 4)
+#define BNA_CQ_PAGE_INDEX_MAX_SHIFT	(PAGE_SHIFT - 4)
+
+#define BNA_CQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range)	\
+{									\
+	unsigned int page_index;	  /* index within a page */	\
+	void *page_addr;						\
+									\
+	page_index = (_qe_idx) & (BNA_CQ_PAGE_INDEX_MAX - 1);		\
+	(_qe_ptr_range) = (BNA_CQ_PAGE_INDEX_MAX - page_index);		\
+	page_addr = (_qpt_ptr)[((_qe_idx) >>				\
+				    BNA_CQ_PAGE_INDEX_MAX_SHIFT)];	\
+	(_qe_ptr) = &((struct bna_cq_entry *)(page_addr))[page_index];\
+}
+
+#define BNA_QE_INDX_2_PTR(_cast, _qe_idx, _q_base)			\
+	(&((_cast *)(_q_base))[(_qe_idx)])
+
+#define BNA_QE_INDX_RANGE(_qe_idx, _q_depth) ((_q_depth) - (_qe_idx))
+
+#define BNA_QE_INDX_ADD(_qe_idx, _qe_num, _q_depth)			\
+	((_qe_idx) = ((_qe_idx) + (_qe_num)) & ((_q_depth) - 1))
+
+#define BNA_Q_INDEX_CHANGE(_old_idx, _updated_idx, _q_depth)		\
+	(((_updated_idx) - (_old_idx)) & ((_q_depth) - 1))
+
+#define BNA_QE_FREE_CNT(_q_ptr, _q_depth)				\
+	(((_q_ptr)->consumer_index - (_q_ptr)->producer_index - 1) &	\
+	 ((_q_depth) - 1))
+
+#define BNA_QE_IN_USE_CNT(_q_ptr, _q_depth)				\
+	((((_q_ptr)->producer_index - (_q_ptr)->consumer_index)) &	\
+	 (_q_depth - 1))
+
+#define BNA_Q_GET_CI(_q_ptr)		((_q_ptr)->q.consumer_index)
+
+#define BNA_Q_GET_PI(_q_ptr)		((_q_ptr)->q.producer_index)
+
+#define BNA_Q_PI_ADD(_q_ptr, _num)					\
+	(_q_ptr)->q.producer_index =					\
+		(((_q_ptr)->q.producer_index + (_num)) &		\
+		((_q_ptr)->q.q_depth - 1))
+
+#define BNA_Q_CI_ADD(_q_ptr, _num) 					\
+	(_q_ptr)->q.consumer_index =					\
+		(((_q_ptr)->q.consumer_index + (_num))  		\
+		& ((_q_ptr)->q.q_depth - 1))
+
+#define BNA_Q_FREE_COUNT(_q_ptr)					\
+	(BNA_QE_FREE_CNT(&((_q_ptr)->q), (_q_ptr)->q.q_depth))
+
+#define BNA_Q_IN_USE_COUNT(_q_ptr)  					\
+	(BNA_QE_IN_USE_CNT(&(_q_ptr)->q, (_q_ptr)->q.q_depth))
+
+/* These macros build the data portion of the TxQ/RxQ doorbell */
+#define BNA_DOORBELL_Q_PRD_IDX(_pi) 	(0x80000000 | (_pi))
+#define BNA_DOORBELL_Q_STOP		(0x40000000)
+
+/* These macros build the data portion of the IB doorbell */
+#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
+	(0x80000000 | ((_timeout) << 16) | (_events))
+#define BNA_DOORBELL_IB_INT_DISABLE 	(0x40000000)
+
+/* Set the coalescing timer for the given ib */
+#define bna_ib_coalescing_timer_set(_i_dbell, _cls_timer)		\
+	((_i_dbell)->doorbell_ack = BNA_DOORBELL_IB_INT_ACK((_cls_timer), 0));
+
+/* Acks 'events' # of events for a given ib */
+#define bna_ib_ack(_i_dbell, _events)					\
+	(writel(((_i_dbell)->doorbell_ack | (_events)), \
+		(_i_dbell)->doorbell_addr));
+
+#define bna_txq_prod_indx_doorbell(_tcb)				\
+	(writel(BNA_DOORBELL_Q_PRD_IDX((_tcb)->producer_index), \
+		(_tcb)->q_dbell));
+
+#define bna_rxq_prod_indx_doorbell(_rcb)				\
+	(writel(BNA_DOORBELL_Q_PRD_IDX((_rcb)->producer_index), \
+		(_rcb)->q_dbell));
+
+#define BNA_LARGE_PKT_SIZE		1000
+
+#define BNA_UPDATE_PKT_CNT(_pkt, _len)					\
+do {									\
+	if ((_len) > BNA_LARGE_PKT_SIZE) {				\
+		(_pkt)->large_pkt_cnt++;				\
+	} else {							\
+		(_pkt)->small_pkt_cnt++;				\
+	}								\
+} while (0)
+
+#define	call_rxf_stop_cbfn(rxf, status)					\
+	if ((rxf)->stop_cbfn) {						\
+		(*(rxf)->stop_cbfn)((rxf)->stop_cbarg, (status));	\
+		(rxf)->stop_cbfn = NULL;				\
+		(rxf)->stop_cbarg = NULL;				\
+	}
+
+#define	call_rxf_start_cbfn(rxf, status)				\
+	if ((rxf)->start_cbfn) {					\
+		(*(rxf)->start_cbfn)((rxf)->start_cbarg, (status));	\
+		(rxf)->start_cbfn = NULL;				\
+		(rxf)->start_cbarg = NULL;				\
+	}
+
+#define	call_rxf_cam_fltr_cbfn(rxf, status)				\
+	if ((rxf)->cam_fltr_cbfn) {					\
+		(*(rxf)->cam_fltr_cbfn)((rxf)->cam_fltr_cbarg, rxf->rx,	\
+					(status));			\
+		(rxf)->cam_fltr_cbfn = NULL;				\
+		(rxf)->cam_fltr_cbarg = NULL;				\
+	}
+
+#define	call_rxf_pause_cbfn(rxf, status)				\
+	if ((rxf)->oper_state_cbfn) {					\
+		(*(rxf)->oper_state_cbfn)((rxf)->oper_state_cbarg, rxf->rx,\
+					(status));			\
+		(rxf)->rxf_flags &= ~BNA_RXF_FL_OPERSTATE_CHANGED;	\
+		(rxf)->oper_state_cbfn = NULL;				\
+		(rxf)->oper_state_cbarg = NULL;				\
+	}
+
+#define	call_rxf_resume_cbfn(rxf, status) call_rxf_pause_cbfn(rxf, status)
+
+#define is_xxx_enable(mode, bitmask, xxx) ((bitmask & xxx) && (mode & xxx))
+
+#define is_xxx_disable(mode, bitmask, xxx) ((bitmask & xxx) && !(mode & xxx))
+
+#define xxx_enable(mode, bitmask, xxx)					\
+do {									\
+	bitmask |= xxx;							\
+	mode |= xxx;							\
+} while (0)
+
+#define xxx_disable(mode, bitmask, xxx)					\
+do {									\
+	bitmask |= xxx;							\
+	mode &= ~xxx;							\
+} while (0)
+
+#define xxx_inactive(mode, bitmask, xxx)				\
+do {									\
+	bitmask &= ~xxx;						\
+	mode &= ~xxx;							\
+} while (0)
+
+#define is_promisc_enable(mode, bitmask)				\
+	is_xxx_enable(mode, bitmask, BNA_RXMODE_PROMISC)
+
+#define is_promisc_disable(mode, bitmask)				\
+	is_xxx_disable(mode, bitmask, BNA_RXMODE_PROMISC)
+
+#define promisc_enable(mode, bitmask)					\
+	xxx_enable(mode, bitmask, BNA_RXMODE_PROMISC)
+
+#define promisc_disable(mode, bitmask)					\
+	xxx_disable(mode, bitmask, BNA_RXMODE_PROMISC)
+
+#define promisc_inactive(mode, bitmask)					\
+	xxx_inactive(mode, bitmask, BNA_RXMODE_PROMISC)
+
+#define is_default_enable(mode, bitmask)				\
+	is_xxx_enable(mode, bitmask, BNA_RXMODE_DEFAULT)
+
+#define is_default_disable(mode, bitmask)				\
+	is_xxx_disable(mode, bitmask, BNA_RXMODE_DEFAULT)
+
+#define default_enable(mode, bitmask)					\
+	xxx_enable(mode, bitmask, BNA_RXMODE_DEFAULT)
+
+#define default_disable(mode, bitmask)					\
+	xxx_disable(mode, bitmask, BNA_RXMODE_DEFAULT)
+
+#define default_inactive(mode, bitmask)					\
+	xxx_inactive(mode, bitmask, BNA_RXMODE_DEFAULT)
+
+#define is_allmulti_enable(mode, bitmask)				\
+	is_xxx_enable(mode, bitmask, BNA_RXMODE_ALLMULTI)
+
+#define is_allmulti_disable(mode, bitmask)				\
+	is_xxx_disable(mode, bitmask, BNA_RXMODE_ALLMULTI)
+
+#define allmulti_enable(mode, bitmask)					\
+	xxx_enable(mode, bitmask, BNA_RXMODE_ALLMULTI)
+
+#define allmulti_disable(mode, bitmask)					\
+	xxx_disable(mode, bitmask, BNA_RXMODE_ALLMULTI)
+
+#define allmulti_inactive(mode, bitmask)				\
+	xxx_inactive(mode, bitmask, BNA_RXMODE_ALLMULTI)
+
+#define	GET_RXQS(rxp, q0, q1)	do {					\
+	switch ((rxp)->type) {						\
+	case BNA_RXP_SINGLE:						\
+		(q0) = rxp->rxq.single.only;				\
+		(q1) = NULL;						\
+		break;							\
+	case BNA_RXP_SLR:						\
+		(q0) = rxp->rxq.slr.large;				\
+		(q1) = rxp->rxq.slr.small;				\
+		break;							\
+	case BNA_RXP_HDS:						\
+		(q0) = rxp->rxq.hds.data;				\
+		(q1) = rxp->rxq.hds.hdr;				\
+		break;							\
+	}								\
+} while (0)
+
+/**
+ *
+ * Function prototypes
+ *
+ */
+
+/**
+ * BNA
+ */
+
+/* APIs for BNAD */
+void bna_res_req(struct bna_res_info *res_info);
+void bna_init(struct bna *bna, struct bnad *bnad,
+			struct bfa_pcidev *pcidev,
+			struct bna_res_info *res_info);
+void bna_uninit(struct bna *bna);
+void bna_stats_get(struct bna *bna);
+void bna_get_perm_mac(struct bna *bna, u8 *mac);
+
+/* APIs for Rx */
+int bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size);
+
+/* APIs for RxF */
+struct bna_mac *bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod);
+void bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod,
+			  struct bna_mac *mac);
+struct bna_mac *bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod);
+void bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod,
+			  struct bna_mac *mac);
+struct bna_rit_segment *
+bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size);
+void bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod,
+			struct bna_rit_segment *seg);
+
+/**
+ * DEVICE
+ */
+
+/* APIs for BNAD */
+void bna_device_enable(struct bna_device *device);
+void bna_device_disable(struct bna_device *device,
+			enum bna_cleanup_type type);
+
+/**
+ * MBOX
+ */
+
+/* APIs for PORT, TX, RX */
+void bna_mbox_handler(struct bna *bna, u32 intr_status);
+void bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe);
+
+/**
+ * PORT
+ */
+
+/* API for RX */
+int bna_port_mtu_get(struct bna_port *port);
+void bna_llport_admin_up(struct bna_llport *llport);
+void bna_llport_admin_down(struct bna_llport *llport);
+
+/* API for BNAD */
+void bna_port_enable(struct bna_port *port);
+void bna_port_disable(struct bna_port *port, enum bna_cleanup_type type,
+		      void (*cbfn)(void *, enum bna_cb_status));
+void bna_port_pause_config(struct bna_port *port,
+			   struct bna_pause_config *pause_config,
+			   void (*cbfn)(struct bnad *, enum bna_cb_status));
+void bna_port_mtu_set(struct bna_port *port, int mtu,
+		      void (*cbfn)(struct bnad *, enum bna_cb_status));
+void bna_port_mac_get(struct bna_port *port, mac_t *mac);
+
+/* Callbacks for TX, RX */
+void bna_port_cb_tx_stopped(struct bna_port *port,
+			    enum bna_cb_status status);
+void bna_port_cb_rx_stopped(struct bna_port *port,
+			    enum bna_cb_status status);
+
+/**
+ * IB
+ */
+
+/* APIs for BNA */
+void bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna,
+		     struct bna_res_info *res_info);
+void bna_ib_mod_uninit(struct bna_ib_mod *ib_mod);
+
+/**
+ * TX MODULE AND TX
+ */
+
+/* APIs for BNA */
+void bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
+		     struct bna_res_info *res_info);
+void bna_tx_mod_uninit(struct bna_tx_mod *tx_mod);
+int bna_tx_state_get(struct bna_tx *tx);
+
+/* APIs for PORT */
+void bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type);
+void bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type);
+void bna_tx_mod_fail(struct bna_tx_mod *tx_mod);
+void bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio);
+void bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link);
+
+/* APIs for BNAD */
+void bna_tx_res_req(int num_txq, int txq_depth,
+		    struct bna_res_info *res_info);
+struct bna_tx *bna_tx_create(struct bna *bna, struct bnad *bnad,
+			       struct bna_tx_config *tx_cfg,
+			       struct bna_tx_event_cbfn *tx_cbfn,
+			       struct bna_res_info *res_info, void *priv);
+void bna_tx_destroy(struct bna_tx *tx);
+void bna_tx_enable(struct bna_tx *tx);
+void bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
+		    void (*cbfn)(void *, struct bna_tx *,
+				 enum bna_cb_status));
+void bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo);
+
+/**
+ * RX MODULE, RX, RXF
+ */
+
+/* Internal APIs */
+void rxf_cb_cam_fltr_mbox_cmd(void *arg, int status);
+void rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd,
+		const struct bna_mac *mac_addr);
+void __rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status);
+void bna_rxf_adv_init(struct bna_rxf *rxf,
+		struct bna_rx *rx,
+		struct bna_rx_config *q_config);
+int rxf_process_packet_filter_ucast(struct bna_rxf *rxf);
+int rxf_process_packet_filter_promisc(struct bna_rxf *rxf);
+int rxf_process_packet_filter_default(struct bna_rxf *rxf);
+int rxf_process_packet_filter_allmulti(struct bna_rxf *rxf);
+int rxf_clear_packet_filter_ucast(struct bna_rxf *rxf);
+int rxf_clear_packet_filter_promisc(struct bna_rxf *rxf);
+int rxf_clear_packet_filter_default(struct bna_rxf *rxf);
+int rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf);
+void rxf_reset_packet_filter_ucast(struct bna_rxf *rxf);
+void rxf_reset_packet_filter_promisc(struct bna_rxf *rxf);
+void rxf_reset_packet_filter_default(struct bna_rxf *rxf);
+void rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf);
+
+/* APIs for BNA */
+void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
+		     struct bna_res_info *res_info);
+void bna_rx_mod_uninit(struct bna_rx_mod *rx_mod);
+int bna_rx_state_get(struct bna_rx *rx);
+int bna_rxf_state_get(struct bna_rxf *rxf);
+
+/* APIs for PORT */
+void bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type);
+void bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type);
+void bna_rx_mod_fail(struct bna_rx_mod *rx_mod);
+
+/* APIs for BNAD */
+void bna_rx_res_req(struct bna_rx_config *rx_config,
+		    struct bna_res_info *res_info);
+struct bna_rx *bna_rx_create(struct bna *bna, struct bnad *bnad,
+			       struct bna_rx_config *rx_cfg,
+			       struct bna_rx_event_cbfn *rx_cbfn,
+			       struct bna_res_info *res_info, void *priv);
+void bna_rx_destroy(struct bna_rx *rx);
+void bna_rx_enable(struct bna_rx *rx);
+void bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
+		    void (*cbfn)(void *, struct bna_rx *,
+				 enum bna_cb_status));
+void bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo);
+void bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX]);
+void bna_rx_dim_update(struct bna_ccb *ccb);
+enum bna_cb_status
+bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
+		 void (*cbfn)(struct bnad *, struct bna_rx *,
+			      enum bna_cb_status));
+enum bna_cb_status
+bna_rx_mcast_add(struct bna_rx *rx, u8 *mcmac,
+		 void (*cbfn)(struct bnad *, struct bna_rx *,
+			      enum bna_cb_status));
+enum bna_cb_status
+bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mcmac,
+		     void (*cbfn)(struct bnad *, struct bna_rx *,
+				  enum bna_cb_status));
+enum bna_cb_status
+bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode rxmode,
+		enum bna_rxmode bitmask,
+		void (*cbfn)(struct bnad *, struct bna_rx *,
+			     enum bna_cb_status));
+void bna_rx_vlan_add(struct bna_rx *rx, int vlan_id);
+void bna_rx_vlan_del(struct bna_rx *rx, int vlan_id);
+void bna_rx_vlanfilter_enable(struct bna_rx *rx);
+void bna_rx_hds_enable(struct bna_rx *rx, struct bna_rxf_hds *hds_config,
+		       void (*cbfn)(struct bnad *, struct bna_rx *,
+				    enum bna_cb_status));
+void bna_rx_hds_disable(struct bna_rx *rx,
+			void (*cbfn)(struct bnad *, struct bna_rx *,
+				     enum bna_cb_status));
+
+/**
+ * BNAD
+ */
+
+/* Callbacks for BNA */
+void bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status,
+		       struct bna_stats *stats);
+
+/* Callbacks for DEVICE */
+void bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status);
+void bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status);
+void bnad_cb_device_enable_mbox_intr(struct bnad *bnad);
+void bnad_cb_device_disable_mbox_intr(struct bnad *bnad);
+
+/* Callbacks for port */
+void bnad_cb_port_link_status(struct bnad *bnad,
+			      enum bna_link_status status);
+
+#endif  /* __BNA_H__ */
diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c
new file mode 100644
index 0000000..07b2659
--- /dev/null
+++ b/drivers/net/bna/bna_ctrl.c
@@ -0,0 +1,3261 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include "bna.h"
+#include "bfa_sm.h"
+#include "bfa_wc.h"
+
+static void bna_device_cb_port_stopped(void *arg, enum bna_cb_status status);
+
+static void
+bna_port_cb_link_up(struct bna_port *port, struct bfi_ll_aen *aen,
+			int status)
+{
+	int i;
+	u8 prio_map;
+
+	port->llport.link_status = BNA_LINK_UP;
+	if (aen->cee_linkup)
+		port->llport.link_status = BNA_CEE_UP;
+
+	/* Compute the priority */
+	prio_map = aen->prio_map;
+	if (prio_map) {
+		for (i = 0; i < 8; i++) {
+			if ((prio_map >> i) & 0x1)
+				break;
+		}
+		port->priority = i;
+	} else
+		port->priority = 0;
+
+	/* Dispatch events */
+	bna_tx_mod_cee_link_status(&port->bna->tx_mod, aen->cee_linkup);
+	bna_tx_mod_prio_changed(&port->bna->tx_mod, port->priority);
+	port->link_cbfn(port->bna->bnad, port->llport.link_status);
+}
+
+static void
+bna_port_cb_link_down(struct bna_port *port, int status)
+{
+	port->llport.link_status = BNA_LINK_DOWN;
+
+	/* Dispatch events */
+	bna_tx_mod_cee_link_status(&port->bna->tx_mod, BNA_LINK_DOWN);
+	port->link_cbfn(port->bna->bnad, BNA_LINK_DOWN);
+}
+
+/**
+ * MBOX
+ */
+static int
+bna_is_aen(u8 msg_id)
+{
+	return msg_id == BFI_LL_I2H_LINK_DOWN_AEN ||
+	       msg_id == BFI_LL_I2H_LINK_UP_AEN;
+}
+
+static void
+bna_mbox_aen_callback(struct bna *bna, struct bfi_mbmsg *msg)
+{
+	struct bfi_ll_aen *aen = (struct bfi_ll_aen *)(msg);
+
+	switch (aen->mh.msg_id) {
+	case BFI_LL_I2H_LINK_UP_AEN:
+		bna_port_cb_link_up(&bna->port, aen, aen->reason);
+		break;
+	case BFI_LL_I2H_LINK_DOWN_AEN:
+		bna_port_cb_link_down(&bna->port, aen->reason);
+		break;
+	default:
+		break;
+	}
+}
+
+static void
+bna_ll_isr(void *llarg, struct bfi_mbmsg *msg)
+{
+	struct bna *bna = (struct bna *)(llarg);
+	struct bfi_ll_rsp *mb_rsp = (struct bfi_ll_rsp *)(msg);
+	struct bfi_mhdr *cmd_h, *rsp_h;
+	struct bna_mbox_qe *mb_qe = NULL;
+	int to_post = 0;
+	u8 aen = 0;
+	char message[BNA_MESSAGE_SIZE];
+
+	aen = bna_is_aen(mb_rsp->mh.msg_id);
+
+	if (!aen) {
+		mb_qe = bfa_q_first(&bna->mbox_mod.posted_q);
+		cmd_h = (struct bfi_mhdr *)(&mb_qe->cmd.msg[0]);
+		rsp_h = (struct bfi_mhdr *)(&mb_rsp->mh);
+
+		if ((BFA_I2HM(cmd_h->msg_id) == rsp_h->msg_id) &&
+		    (cmd_h->mtag.i2htok == rsp_h->mtag.i2htok)) {
+			/* Remove the request from posted_q, update state  */
+			list_del(&mb_qe->qe);
+			bna->mbox_mod.msg_pending--;
+			if (list_empty(&bna->mbox_mod.posted_q))
+				bna->mbox_mod.state = BNA_MBOX_FREE;
+			else
+				to_post = 1;
+
+			/* Dispatch the cbfn */
+			if (mb_qe->cbfn)
+				mb_qe->cbfn(mb_qe->cbarg, mb_rsp->error);
+
+			/* Post the next entry, if needed */
+			if (to_post) {
+				mb_qe = bfa_q_first(&bna->mbox_mod.posted_q);
+				bfa_nw_ioc_mbox_queue(&bna->device.ioc,
+							&mb_qe->cmd);
+			}
+		} else {
+			snprintf(message, BNA_MESSAGE_SIZE,
+				       "No matching rsp for [%d:%d:%d]\n",
+				       mb_rsp->mh.msg_class, mb_rsp->mh.msg_id,
+				       mb_rsp->mh.mtag.i2htok);
+		pr_info("%s", message);
+		}
+
+	} else
+		bna_mbox_aen_callback(bna, msg);
+}
+
+static void
+bna_err_handler(struct bna *bna, u32 intr_status)
+{
+	u32 init_halt;
+
+	if (intr_status & __HALT_STATUS_BITS) {
+		init_halt = readl(bna->device.ioc.ioc_regs.ll_halt);
+		init_halt &= ~__FW_INIT_HALT_P;
+		writel(init_halt, bna->device.ioc.ioc_regs.ll_halt);
+	}
+
+	bfa_nw_ioc_error_isr(&bna->device.ioc);
+}
+
+void
+bna_mbox_handler(struct bna *bna, u32 intr_status)
+{
+	if (BNA_IS_ERR_INTR(intr_status)) {
+		bna_err_handler(bna, intr_status);
+		return;
+	}
+	if (BNA_IS_MBOX_INTR(intr_status))
+		bfa_nw_ioc_mbox_isr(&bna->device.ioc);
+}
+
+void
+bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe)
+{
+	struct bfi_mhdr *mh;
+
+	mh = (struct bfi_mhdr *)(&mbox_qe->cmd.msg[0]);
+
+	mh->mtag.i2htok = htons(bna->mbox_mod.msg_ctr);
+	bna->mbox_mod.msg_ctr++;
+	bna->mbox_mod.msg_pending++;
+	if (bna->mbox_mod.state == BNA_MBOX_FREE) {
+		list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);
+		bfa_nw_ioc_mbox_queue(&bna->device.ioc, &mbox_qe->cmd);
+		bna->mbox_mod.state = BNA_MBOX_POSTED;
+	} else {
+		list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);
+	}
+}
+
+static void
+bna_mbox_flush_q(struct bna *bna, struct list_head *q)
+{
+	struct bna_mbox_qe *mb_qe = NULL;
+	struct bfi_mhdr *cmd_h;
+	struct list_head			*mb_q;
+	void 			(*cbfn)(void *arg, int status);
+	void 			*cbarg;
+
+	mb_q = &bna->mbox_mod.posted_q;
+
+	while (!list_empty(mb_q)) {
+		bfa_q_deq(mb_q, &mb_qe);
+		cbfn = mb_qe->cbfn;
+		cbarg = mb_qe->cbarg;
+		bfa_q_qe_init(mb_qe);
+		bna->mbox_mod.msg_pending--;
+
+		cmd_h = (struct bfi_mhdr *)(&mb_qe->cmd.msg[0]);
+		if (cbfn)
+			cbfn(cbarg, BNA_CB_NOT_EXEC);
+	}
+
+	bna->mbox_mod.state = BNA_MBOX_FREE;
+}
+
+static void
+bna_mbox_mod_start(struct bna_mbox_mod *mbox_mod)
+{
+}
+
+static void
+bna_mbox_mod_stop(struct bna_mbox_mod *mbox_mod)
+{
+	bna_mbox_flush_q(mbox_mod->bna, &mbox_mod->posted_q);
+}
+
+static void
+bna_mbox_mod_init(struct bna_mbox_mod *mbox_mod, struct bna *bna)
+{
+	bfa_nw_ioc_mbox_regisr(&bna->device.ioc, BFI_MC_LL, bna_ll_isr, bna);
+	mbox_mod->state = BNA_MBOX_FREE;
+	mbox_mod->msg_ctr = mbox_mod->msg_pending = 0;
+	INIT_LIST_HEAD(&mbox_mod->posted_q);
+	mbox_mod->bna = bna;
+}
+
+static void
+bna_mbox_mod_uninit(struct bna_mbox_mod *mbox_mod)
+{
+	mbox_mod->bna = NULL;
+}
+
+/**
+ * LLPORT
+ */
+#define call_llport_stop_cbfn(llport, status)\
+do {\
+	if ((llport)->stop_cbfn)\
+		(llport)->stop_cbfn(&(llport)->bna->port, status);\
+	(llport)->stop_cbfn = NULL;\
+} while (0)
+
+static void bna_fw_llport_up(struct bna_llport *llport);
+static void bna_fw_cb_llport_up(void *arg, int status);
+static void bna_fw_llport_down(struct bna_llport *llport);
+static void bna_fw_cb_llport_down(void *arg, int status);
+static void bna_llport_start(struct bna_llport *llport);
+static void bna_llport_stop(struct bna_llport *llport);
+static void bna_llport_fail(struct bna_llport *llport);
+
+enum bna_llport_event {
+	LLPORT_E_START			= 1,
+	LLPORT_E_STOP			= 2,
+	LLPORT_E_FAIL			= 3,
+	LLPORT_E_UP			= 4,
+	LLPORT_E_DOWN			= 5,
+	LLPORT_E_FWRESP_UP		= 6,
+	LLPORT_E_FWRESP_DOWN		= 7
+};
+
+enum bna_llport_state {
+	BNA_LLPORT_STOPPED		= 1,
+	BNA_LLPORT_DOWN			= 2,
+	BNA_LLPORT_UP_RESP_WAIT		= 3,
+	BNA_LLPORT_DOWN_RESP_WAIT	= 4,
+	BNA_LLPORT_UP			= 5,
+	BNA_LLPORT_LAST_RESP_WAIT 	= 6
+};
+
+bfa_fsm_state_decl(bna_llport, stopped, struct bna_llport,
+			enum bna_llport_event);
+bfa_fsm_state_decl(bna_llport, down, struct bna_llport,
+			enum bna_llport_event);
+bfa_fsm_state_decl(bna_llport, up_resp_wait, struct bna_llport,
+			enum bna_llport_event);
+bfa_fsm_state_decl(bna_llport, down_resp_wait, struct bna_llport,
+			enum bna_llport_event);
+bfa_fsm_state_decl(bna_llport, up, struct bna_llport,
+			enum bna_llport_event);
+bfa_fsm_state_decl(bna_llport, last_resp_wait, struct bna_llport,
+			enum bna_llport_event);
+
+static struct bfa_sm_table llport_sm_table[] = {
+	{BFA_SM(bna_llport_sm_stopped), BNA_LLPORT_STOPPED},
+	{BFA_SM(bna_llport_sm_down), BNA_LLPORT_DOWN},
+	{BFA_SM(bna_llport_sm_up_resp_wait), BNA_LLPORT_UP_RESP_WAIT},
+	{BFA_SM(bna_llport_sm_down_resp_wait), BNA_LLPORT_DOWN_RESP_WAIT},
+	{BFA_SM(bna_llport_sm_up), BNA_LLPORT_UP},
+	{BFA_SM(bna_llport_sm_last_resp_wait), BNA_LLPORT_LAST_RESP_WAIT}
+};
+
+static void
+bna_llport_sm_stopped_entry(struct bna_llport *llport)
+{
+	llport->bna->port.link_cbfn((llport)->bna->bnad, BNA_LINK_DOWN);
+	call_llport_stop_cbfn(llport, BNA_CB_SUCCESS);
+}
+
+static void
+bna_llport_sm_stopped(struct bna_llport *llport,
+			enum bna_llport_event event)
+{
+	switch (event) {
+	case LLPORT_E_START:
+		bfa_fsm_set_state(llport, bna_llport_sm_down);
+		break;
+
+	case LLPORT_E_STOP:
+		call_llport_stop_cbfn(llport, BNA_CB_SUCCESS);
+		break;
+
+	case LLPORT_E_FAIL:
+		break;
+
+	case LLPORT_E_DOWN:
+		/* This event is received due to Rx objects failing */
+		/* No-op */
+		break;
+
+	case LLPORT_E_FWRESP_UP:
+	case LLPORT_E_FWRESP_DOWN:
+		/**
+		 * These events are received due to flushing of mbox when
+		 * device fails
+		 */
+		/* No-op */
+		break;
+
+	default:
+		bfa_sm_fault(llport->bna, event);
+	}
+}
+
+static void
+bna_llport_sm_down_entry(struct bna_llport *llport)
+{
+	bnad_cb_port_link_status((llport)->bna->bnad, BNA_LINK_DOWN);
+}
+
+static void
+bna_llport_sm_down(struct bna_llport *llport,
+			enum bna_llport_event event)
+{
+	switch (event) {
+	case LLPORT_E_STOP:
+		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+		break;
+
+	case LLPORT_E_FAIL:
+		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+		break;
+
+	case LLPORT_E_UP:
+		bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
+		bna_fw_llport_up(llport);
+		break;
+
+	default:
+		bfa_sm_fault(llport->bna, event);
+	}
+}
+
+static void
+bna_llport_sm_up_resp_wait_entry(struct bna_llport *llport)
+{
+	/**
+	 * NOTE: Do not call bna_fw_llport_up() here. That will over step
+	 * mbox due to down_resp_wait -> up_resp_wait transition on event
+	 * LLPORT_E_UP
+	 */
+}
+
+static void
+bna_llport_sm_up_resp_wait(struct bna_llport *llport,
+			enum bna_llport_event event)
+{
+	switch (event) {
+	case LLPORT_E_STOP:
+		bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
+		break;
+
+	case LLPORT_E_FAIL:
+		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+		break;
+
+	case LLPORT_E_DOWN:
+		bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
+		break;
+
+	case LLPORT_E_FWRESP_UP:
+		bfa_fsm_set_state(llport, bna_llport_sm_up);
+		break;
+
+	case LLPORT_E_FWRESP_DOWN:
+		/* down_resp_wait -> up_resp_wait transition on LLPORT_E_UP */
+		bna_fw_llport_up(llport);
+		break;
+
+	default:
+		bfa_sm_fault(llport->bna, event);
+	}
+}
+
+static void
+bna_llport_sm_down_resp_wait_entry(struct bna_llport *llport)
+{
+	/**
+	 * NOTE: Do not call bna_fw_llport_down() here. That will over step
+	 * mbox due to up_resp_wait -> down_resp_wait transition on event
+	 * LLPORT_E_DOWN
+	 */
+}
+
+static void
+bna_llport_sm_down_resp_wait(struct bna_llport *llport,
+			enum bna_llport_event event)
+{
+	switch (event) {
+	case LLPORT_E_STOP:
+		bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
+		break;
+
+	case LLPORT_E_FAIL:
+		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+		break;
+
+	case LLPORT_E_UP:
+		bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
+		break;
+
+	case LLPORT_E_FWRESP_UP:
+		/* up_resp_wait->down_resp_wait transition on LLPORT_E_DOWN */
+		bna_fw_llport_down(llport);
+		break;
+
+	case LLPORT_E_FWRESP_DOWN:
+		bfa_fsm_set_state(llport, bna_llport_sm_down);
+		break;
+
+	default:
+		bfa_sm_fault(llport->bna, event);
+	}
+}
+
+static void
+bna_llport_sm_up_entry(struct bna_llport *llport)
+{
+}
+
+static void
+bna_llport_sm_up(struct bna_llport *llport,
+			enum bna_llport_event event)
+{
+	switch (event) {
+	case LLPORT_E_STOP:
+		bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
+		bna_fw_llport_down(llport);
+		break;
+
+	case LLPORT_E_FAIL:
+		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+		break;
+
+	case LLPORT_E_DOWN:
+		bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
+		bna_fw_llport_down(llport);
+		break;
+
+	default:
+		bfa_sm_fault(llport->bna, event);
+	}
+}
+
+static void
+bna_llport_sm_last_resp_wait_entry(struct bna_llport *llport)
+{
+}
+
+static void
+bna_llport_sm_last_resp_wait(struct bna_llport *llport,
+			enum bna_llport_event event)
+{
+	switch (event) {
+	case LLPORT_E_FAIL:
+		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+		break;
+
+	case LLPORT_E_DOWN:
+		/**
+		 * This event is received due to Rx objects stopping in
+		 * parallel to llport
+		 */
+		/* No-op */
+		break;
+
+	case LLPORT_E_FWRESP_UP:
+		/* up_resp_wait->last_resp_wait transition on LLPORT_T_STOP */
+		bna_fw_llport_down(llport);
+		break;
+
+	case LLPORT_E_FWRESP_DOWN:
+		bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+		break;
+
+	default:
+		bfa_sm_fault(llport->bna, event);
+	}
+}
+
+static void
+bna_fw_llport_admin_up(struct bna_llport *llport)
+{
+	struct bfi_ll_port_admin_req ll_req;
+
+	memset(&ll_req, 0, sizeof(ll_req));
+	ll_req.mh.msg_class = BFI_MC_LL;
+	ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ;
+	ll_req.mh.mtag.h2i.lpu_id = 0;
+
+	ll_req.up = BNA_STATUS_T_ENABLED;
+
+	bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req),
+			bna_fw_cb_llport_up, llport);
+
+	bna_mbox_send(llport->bna, &llport->mbox_qe);
+}
+
+static void
+bna_fw_llport_up(struct bna_llport *llport)
+{
+	if (llport->type == BNA_PORT_T_REGULAR)
+		bna_fw_llport_admin_up(llport);
+}
+
+static void
+bna_fw_cb_llport_up(void *arg, int status)
+{
+	struct bna_llport *llport = (struct bna_llport *)arg;
+
+	bfa_q_qe_init(&llport->mbox_qe.qe);
+	bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP);
+}
+
+static void
+bna_fw_llport_admin_down(struct bna_llport *llport)
+{
+	struct bfi_ll_port_admin_req ll_req;
+
+	memset(&ll_req, 0, sizeof(ll_req));
+	ll_req.mh.msg_class = BFI_MC_LL;
+	ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ;
+	ll_req.mh.mtag.h2i.lpu_id = 0;
+
+	ll_req.up = BNA_STATUS_T_DISABLED;
+
+	bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req),
+			bna_fw_cb_llport_down, llport);
+
+	bna_mbox_send(llport->bna, &llport->mbox_qe);
+}
+
+static void
+bna_fw_llport_down(struct bna_llport *llport)
+{
+	if (llport->type == BNA_PORT_T_REGULAR)
+		bna_fw_llport_admin_down(llport);
+}
+
+static void
+bna_fw_cb_llport_down(void *arg, int status)
+{
+	struct bna_llport *llport = (struct bna_llport *)arg;
+
+	bfa_q_qe_init(&llport->mbox_qe.qe);
+	bfa_fsm_send_event(llport, LLPORT_E_FWRESP_DOWN);
+}
+
+static void
+bna_port_cb_llport_stopped(struct bna_port *port,
+				enum bna_cb_status status)
+{
+	bfa_wc_down(&port->chld_stop_wc);
+}
+
+static void
+bna_llport_init(struct bna_llport *llport, struct bna *bna)
+{
+	llport->flags |= BNA_LLPORT_F_ENABLED;
+	llport->type = BNA_PORT_T_REGULAR;
+	llport->bna = bna;
+
+	llport->link_status = BNA_LINK_DOWN;
+
+	llport->admin_up_count = 0;
+
+	llport->stop_cbfn = NULL;
+
+	bfa_q_qe_init(&llport->mbox_qe.qe);
+
+	bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+}
+
+static void
+bna_llport_uninit(struct bna_llport *llport)
+{
+	llport->flags &= ~BNA_LLPORT_F_ENABLED;
+
+	llport->bna = NULL;
+}
+
+static void
+bna_llport_start(struct bna_llport *llport)
+{
+	bfa_fsm_send_event(llport, LLPORT_E_START);
+}
+
+static void
+bna_llport_stop(struct bna_llport *llport)
+{
+	llport->stop_cbfn = bna_port_cb_llport_stopped;
+
+	bfa_fsm_send_event(llport, LLPORT_E_STOP);
+}
+
+static void
+bna_llport_fail(struct bna_llport *llport)
+{
+	bfa_fsm_send_event(llport, LLPORT_E_FAIL);
+}
+
+static int
+bna_llport_state_get(struct bna_llport *llport)
+{
+	return bfa_sm_to_state(llport_sm_table, llport->fsm);
+}
+
+void
+bna_llport_admin_up(struct bna_llport *llport)
+{
+	llport->admin_up_count++;
+
+	if (llport->admin_up_count == 1) {
+		llport->flags |= BNA_LLPORT_F_RX_ENABLED;
+		if (llport->flags & BNA_LLPORT_F_ENABLED)
+			bfa_fsm_send_event(llport, LLPORT_E_UP);
+	}
+}
+
+void
+bna_llport_admin_down(struct bna_llport *llport)
+{
+	llport->admin_up_count--;
+
+	if (llport->admin_up_count == 0) {
+		llport->flags &= ~BNA_LLPORT_F_RX_ENABLED;
+		if (llport->flags & BNA_LLPORT_F_ENABLED)
+			bfa_fsm_send_event(llport, LLPORT_E_DOWN);
+	}
+}
+
+/**
+ * PORT
+ */
+#define bna_port_chld_start(port)\
+do {\
+	enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+					BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\
+	enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+					BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
+	bna_llport_start(&(port)->llport);\
+	bna_tx_mod_start(&(port)->bna->tx_mod, tx_type);\
+	bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\
+} while (0)
+
+#define bna_port_chld_stop(port)\
+do {\
+	enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+					BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\
+	enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+					BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
+	bfa_wc_up(&(port)->chld_stop_wc);\
+	bfa_wc_up(&(port)->chld_stop_wc);\
+	bfa_wc_up(&(port)->chld_stop_wc);\
+	bna_llport_stop(&(port)->llport);\
+	bna_tx_mod_stop(&(port)->bna->tx_mod, tx_type);\
+	bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\
+} while (0)
+
+#define bna_port_chld_fail(port)\
+do {\
+	bna_llport_fail(&(port)->llport);\
+	bna_tx_mod_fail(&(port)->bna->tx_mod);\
+	bna_rx_mod_fail(&(port)->bna->rx_mod);\
+} while (0)
+
+#define bna_port_rx_start(port)\
+do {\
+	enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+					BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
+	bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\
+} while (0)
+
+#define bna_port_rx_stop(port)\
+do {\
+	enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+					BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
+	bfa_wc_up(&(port)->chld_stop_wc);\
+	bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\
+} while (0)
+
+#define call_port_stop_cbfn(port, status)\
+do {\
+	if ((port)->stop_cbfn)\
+		(port)->stop_cbfn((port)->stop_cbarg, status);\
+	(port)->stop_cbfn = NULL;\
+	(port)->stop_cbarg = NULL;\
+} while (0)
+
+#define call_port_pause_cbfn(port, status)\
+do {\
+	if ((port)->pause_cbfn)\
+		(port)->pause_cbfn((port)->bna->bnad, status);\
+	(port)->pause_cbfn = NULL;\
+} while (0)
+
+#define call_port_mtu_cbfn(port, status)\
+do {\
+	if ((port)->mtu_cbfn)\
+		(port)->mtu_cbfn((port)->bna->bnad, status);\
+	(port)->mtu_cbfn = NULL;\
+} while (0)
+
+static void bna_fw_pause_set(struct bna_port *port);
+static void bna_fw_cb_pause_set(void *arg, int status);
+static void bna_fw_mtu_set(struct bna_port *port);
+static void bna_fw_cb_mtu_set(void *arg, int status);
+
+enum bna_port_event {
+	PORT_E_START			= 1,
+	PORT_E_STOP			= 2,
+	PORT_E_FAIL			= 3,
+	PORT_E_PAUSE_CFG		= 4,
+	PORT_E_MTU_CFG			= 5,
+	PORT_E_CHLD_STOPPED		= 6,
+	PORT_E_FWRESP_PAUSE		= 7,
+	PORT_E_FWRESP_MTU		= 8
+};
+
+enum bna_port_state {
+	BNA_PORT_STOPPED		= 1,
+	BNA_PORT_MTU_INIT_WAIT		= 2,
+	BNA_PORT_PAUSE_INIT_WAIT	= 3,
+	BNA_PORT_LAST_RESP_WAIT		= 4,
+	BNA_PORT_STARTED		= 5,
+	BNA_PORT_PAUSE_CFG_WAIT		= 6,
+	BNA_PORT_RX_STOP_WAIT		= 7,
+	BNA_PORT_MTU_CFG_WAIT 		= 8,
+	BNA_PORT_CHLD_STOP_WAIT		= 9
+};
+
+bfa_fsm_state_decl(bna_port, stopped, struct bna_port,
+			enum bna_port_event);
+bfa_fsm_state_decl(bna_port, mtu_init_wait, struct bna_port,
+			enum bna_port_event);
+bfa_fsm_state_decl(bna_port, pause_init_wait, struct bna_port,
+			enum bna_port_event);
+bfa_fsm_state_decl(bna_port, last_resp_wait, struct bna_port,
+			enum bna_port_event);
+bfa_fsm_state_decl(bna_port, started, struct bna_port,
+			enum bna_port_event);
+bfa_fsm_state_decl(bna_port, pause_cfg_wait, struct bna_port,
+			enum bna_port_event);
+bfa_fsm_state_decl(bna_port, rx_stop_wait, struct bna_port,
+			enum bna_port_event);
+bfa_fsm_state_decl(bna_port, mtu_cfg_wait, struct bna_port,
+			enum bna_port_event);
+bfa_fsm_state_decl(bna_port, chld_stop_wait, struct bna_port,
+			enum bna_port_event);
+
+static struct bfa_sm_table port_sm_table[] = {
+	{BFA_SM(bna_port_sm_stopped), BNA_PORT_STOPPED},
+	{BFA_SM(bna_port_sm_mtu_init_wait), BNA_PORT_MTU_INIT_WAIT},
+	{BFA_SM(bna_port_sm_pause_init_wait), BNA_PORT_PAUSE_INIT_WAIT},
+	{BFA_SM(bna_port_sm_last_resp_wait), BNA_PORT_LAST_RESP_WAIT},
+	{BFA_SM(bna_port_sm_started), BNA_PORT_STARTED},
+	{BFA_SM(bna_port_sm_pause_cfg_wait), BNA_PORT_PAUSE_CFG_WAIT},
+	{BFA_SM(bna_port_sm_rx_stop_wait), BNA_PORT_RX_STOP_WAIT},
+	{BFA_SM(bna_port_sm_mtu_cfg_wait), BNA_PORT_MTU_CFG_WAIT},
+	{BFA_SM(bna_port_sm_chld_stop_wait), BNA_PORT_CHLD_STOP_WAIT}
+};
+
+static void
+bna_port_sm_stopped_entry(struct bna_port *port)
+{
+	call_port_pause_cbfn(port, BNA_CB_SUCCESS);
+	call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
+	call_port_stop_cbfn(port, BNA_CB_SUCCESS);
+}
+
+static void
+bna_port_sm_stopped(struct bna_port *port, enum bna_port_event event)
+{
+	switch (event) {
+	case PORT_E_START:
+		bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait);
+		break;
+
+	case PORT_E_STOP:
+		call_port_stop_cbfn(port, BNA_CB_SUCCESS);
+		break;
+
+	case PORT_E_FAIL:
+		/* No-op */
+		break;
+
+	case PORT_E_PAUSE_CFG:
+		call_port_pause_cbfn(port, BNA_CB_SUCCESS);
+		break;
+
+	case PORT_E_MTU_CFG:
+		call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
+		break;
+
+	case PORT_E_CHLD_STOPPED:
+		/**
+		 * This event is received due to LLPort, Tx and Rx objects
+		 * failing
+		 */
+		/* No-op */
+		break;
+
+	case PORT_E_FWRESP_PAUSE:
+	case PORT_E_FWRESP_MTU:
+		/**
+		 * These events are received due to flushing of mbox when
+		 * device fails
+		 */
+		/* No-op */
+		break;
+
+	default:
+		bfa_sm_fault(port->bna, event);
+	}
+}
+
+static void
+bna_port_sm_mtu_init_wait_entry(struct bna_port *port)
+{
+	bna_fw_mtu_set(port);
+}
+
+static void
+bna_port_sm_mtu_init_wait(struct bna_port *port, enum bna_port_event event)
+{
+	switch (event) {
+	case PORT_E_STOP:
+		bfa_fsm_set_state(port, bna_port_sm_last_resp_wait);
+		break;
+
+	case PORT_E_FAIL:
+		bfa_fsm_set_state(port, bna_port_sm_stopped);
+		break;
+
+	case PORT_E_PAUSE_CFG:
+		/* No-op */
+		break;
+
+	case PORT_E_MTU_CFG:
+		port->flags |= BNA_PORT_F_MTU_CHANGED;
+		break;
+
+	case PORT_E_FWRESP_MTU:
+		if (port->flags & BNA_PORT_F_MTU_CHANGED) {
+			port->flags &= ~BNA_PORT_F_MTU_CHANGED;
+			bna_fw_mtu_set(port);
+		} else {
+			bfa_fsm_set_state(port, bna_port_sm_pause_init_wait);
+		}
+		break;
+
+	default:
+		bfa_sm_fault(port->bna, event);
+	}
+}
+
+static void
+bna_port_sm_pause_init_wait_entry(struct bna_port *port)
+{
+	bna_fw_pause_set(port);
+}
+
+static void
+bna_port_sm_pause_init_wait(struct bna_port *port,
+				enum bna_port_event event)
+{
+	switch (event) {
+	case PORT_E_STOP:
+		bfa_fsm_set_state(port, bna_port_sm_last_resp_wait);
+		break;
+
+	case PORT_E_FAIL:
+		bfa_fsm_set_state(port, bna_port_sm_stopped);
+		break;
+
+	case PORT_E_PAUSE_CFG:
+		port->flags |= BNA_PORT_F_PAUSE_CHANGED;
+		break;
+
+	case PORT_E_MTU_CFG:
+		port->flags |= BNA_PORT_F_MTU_CHANGED;
+		break;
+
+	case PORT_E_FWRESP_PAUSE:
+		if (port->flags & BNA_PORT_F_PAUSE_CHANGED) {
+			port->flags &= ~BNA_PORT_F_PAUSE_CHANGED;
+			bna_fw_pause_set(port);
+		} else if (port->flags & BNA_PORT_F_MTU_CHANGED) {
+			port->flags &= ~BNA_PORT_F_MTU_CHANGED;
+			bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait);
+		} else {
+			bfa_fsm_set_state(port, bna_port_sm_started);
+			bna_port_chld_start(port);
+		}
+		break;
+
+	default:
+		bfa_sm_fault(port->bna, event);
+	}
+}
+
+static void
+bna_port_sm_last_resp_wait_entry(struct bna_port *port)
+{
+}
+
+static void
+bna_port_sm_last_resp_wait(struct bna_port *port,
+				enum bna_port_event event)
+{
+	switch (event) {
+	case PORT_E_FAIL:
+	case PORT_E_FWRESP_PAUSE:
+	case PORT_E_FWRESP_MTU:
+		bfa_fsm_set_state(port, bna_port_sm_stopped);
+		break;
+
+	default:
+		bfa_sm_fault(port->bna, event);
+	}
+}
+
+static void
+bna_port_sm_started_entry(struct bna_port *port)
+{
+	/**
+	 * NOTE: Do not call bna_port_chld_start() here, since it will be
+	 * inadvertently called during pause_cfg_wait->started transition
+	 * as well
+	 */
+	call_port_pause_cbfn(port, BNA_CB_SUCCESS);
+	call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
+}
+
+static void
+bna_port_sm_started(struct bna_port *port,
+			enum bna_port_event event)
+{
+	switch (event) {
+	case PORT_E_STOP:
+		bfa_fsm_set_state(port, bna_port_sm_chld_stop_wait);
+		break;
+
+	case PORT_E_FAIL:
+		bfa_fsm_set_state(port, bna_port_sm_stopped);
+		bna_port_chld_fail(port);
+		break;
+
+	case PORT_E_PAUSE_CFG:
+		bfa_fsm_set_state(port, bna_port_sm_pause_cfg_wait);
+		break;
+
+	case PORT_E_MTU_CFG:
+		bfa_fsm_set_state(port, bna_port_sm_rx_stop_wait);
+		break;
+
+	default:
+		bfa_sm_fault(port->bna, event);
+	}
+}
+
+static void
+bna_port_sm_pause_cfg_wait_entry(struct bna_port *port)
+{
+	bna_fw_pause_set(port);
+}
+
+static void
+bna_port_sm_pause_cfg_wait(struct bna_port *port,
+				enum bna_port_event event)
+{
+	switch (event) {
+	case PORT_E_FAIL:
+		bfa_fsm_set_state(port, bna_port_sm_stopped);
+		bna_port_chld_fail(port);
+		break;
+
+	case PORT_E_FWRESP_PAUSE:
+		bfa_fsm_set_state(port, bna_port_sm_started);
+		break;
+
+	default:
+		bfa_sm_fault(port->bna, event);
+	}
+}
+
+static void
+bna_port_sm_rx_stop_wait_entry(struct bna_port *port)
+{
+	bna_port_rx_stop(port);
+}
+
+static void
+bna_port_sm_rx_stop_wait(struct bna_port *port,
+				enum bna_port_event event)
+{
+	switch (event) {
+	case PORT_E_FAIL:
+		bfa_fsm_set_state(port, bna_port_sm_stopped);
+		bna_port_chld_fail(port);
+		break;
+
+	case PORT_E_CHLD_STOPPED:
+		bfa_fsm_set_state(port, bna_port_sm_mtu_cfg_wait);
+		break;
+
+	default:
+		bfa_sm_fault(port->bna, event);
+	}
+}
+
+static void
+bna_port_sm_mtu_cfg_wait_entry(struct bna_port *port)
+{
+	bna_fw_mtu_set(port);
+}
+
+static void
+bna_port_sm_mtu_cfg_wait(struct bna_port *port, enum bna_port_event event)
+{
+	switch (event) {
+	case PORT_E_FAIL:
+		bfa_fsm_set_state(port, bna_port_sm_stopped);
+		bna_port_chld_fail(port);
+		break;
+
+	case PORT_E_FWRESP_MTU:
+		bfa_fsm_set_state(port, bna_port_sm_started);
+		bna_port_rx_start(port);
+		break;
+
+	default:
+		bfa_sm_fault(port->bna, event);
+	}
+}
+
+static void
+bna_port_sm_chld_stop_wait_entry(struct bna_port *port)
+{
+	bna_port_chld_stop(port);
+}
+
+static void
+bna_port_sm_chld_stop_wait(struct bna_port *port,
+				enum bna_port_event event)
+{
+	switch (event) {
+	case PORT_E_FAIL:
+		bfa_fsm_set_state(port, bna_port_sm_stopped);
+		bna_port_chld_fail(port);
+		break;
+
+	case PORT_E_CHLD_STOPPED:
+		bfa_fsm_set_state(port, bna_port_sm_stopped);
+		break;
+
+	default:
+		bfa_sm_fault(port->bna, event);
+	}
+}
+
+static void
+bna_fw_pause_set(struct bna_port *port)
+{
+	struct bfi_ll_set_pause_req ll_req;
+
+	memset(&ll_req, 0, sizeof(ll_req));
+	ll_req.mh.msg_class = BFI_MC_LL;
+	ll_req.mh.msg_id = BFI_LL_H2I_SET_PAUSE_REQ;
+	ll_req.mh.mtag.h2i.lpu_id = 0;
+
+	ll_req.tx_pause = port->pause_config.tx_pause;
+	ll_req.rx_pause = port->pause_config.rx_pause;
+
+	bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req),
+			bna_fw_cb_pause_set, port);
+
+	bna_mbox_send(port->bna, &port->mbox_qe);
+}
+
+static void
+bna_fw_cb_pause_set(void *arg, int status)
+{
+	struct bna_port *port = (struct bna_port *)arg;
+
+	bfa_q_qe_init(&port->mbox_qe.qe);
+	bfa_fsm_send_event(port, PORT_E_FWRESP_PAUSE);
+}
+
+void
+bna_fw_mtu_set(struct bna_port *port)
+{
+	struct bfi_ll_mtu_info_req ll_req;
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_MTU_INFO_REQ, 0);
+	ll_req.mtu = htons((u16)port->mtu);
+
+	bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req),
+				bna_fw_cb_mtu_set, port);
+	bna_mbox_send(port->bna, &port->mbox_qe);
+}
+
+void
+bna_fw_cb_mtu_set(void *arg, int status)
+{
+	struct bna_port *port = (struct bna_port *)arg;
+
+	bfa_q_qe_init(&port->mbox_qe.qe);
+	bfa_fsm_send_event(port, PORT_E_FWRESP_MTU);
+}
+
+static void
+bna_port_cb_chld_stopped(void *arg)
+{
+	struct bna_port *port = (struct bna_port *)arg;
+
+	bfa_fsm_send_event(port, PORT_E_CHLD_STOPPED);
+}
+
+static void
+bna_port_init(struct bna_port *port, struct bna *bna)
+{
+	port->bna = bna;
+	port->flags = 0;
+	port->mtu = 0;
+	port->type = BNA_PORT_T_REGULAR;
+
+	port->link_cbfn = bnad_cb_port_link_status;
+
+	port->chld_stop_wc.wc_resume = bna_port_cb_chld_stopped;
+	port->chld_stop_wc.wc_cbarg = port;
+	port->chld_stop_wc.wc_count = 0;
+
+	port->stop_cbfn = NULL;
+	port->stop_cbarg = NULL;
+
+	port->pause_cbfn = NULL;
+
+	port->mtu_cbfn = NULL;
+
+	bfa_q_qe_init(&port->mbox_qe.qe);
+
+	bfa_fsm_set_state(port, bna_port_sm_stopped);
+
+	bna_llport_init(&port->llport, bna);
+}
+
+static void
+bna_port_uninit(struct bna_port *port)
+{
+	bna_llport_uninit(&port->llport);
+
+	port->flags = 0;
+
+	port->bna = NULL;
+}
+
+static int
+bna_port_state_get(struct bna_port *port)
+{
+	return bfa_sm_to_state(port_sm_table, port->fsm);
+}
+
+static void
+bna_port_start(struct bna_port *port)
+{
+	port->flags |= BNA_PORT_F_DEVICE_READY;
+	if (port->flags & BNA_PORT_F_ENABLED)
+		bfa_fsm_send_event(port, PORT_E_START);
+}
+
+static void
+bna_port_stop(struct bna_port *port)
+{
+	port->stop_cbfn = bna_device_cb_port_stopped;
+	port->stop_cbarg = &port->bna->device;
+
+	port->flags &= ~BNA_PORT_F_DEVICE_READY;
+	bfa_fsm_send_event(port, PORT_E_STOP);
+}
+
+static void
+bna_port_fail(struct bna_port *port)
+{
+	port->flags &= ~BNA_PORT_F_DEVICE_READY;
+	bfa_fsm_send_event(port, PORT_E_FAIL);
+}
+
+void
+bna_port_cb_tx_stopped(struct bna_port *port, enum bna_cb_status status)
+{
+	bfa_wc_down(&port->chld_stop_wc);
+}
+
+void
+bna_port_cb_rx_stopped(struct bna_port *port, enum bna_cb_status status)
+{
+	bfa_wc_down(&port->chld_stop_wc);
+}
+
+int
+bna_port_mtu_get(struct bna_port *port)
+{
+	return port->mtu;
+}
+
+void
+bna_port_enable(struct bna_port *port)
+{
+	if (port->fsm != (bfa_sm_t)bna_port_sm_stopped)
+		return;
+
+	port->flags |= BNA_PORT_F_ENABLED;
+
+	if (port->flags & BNA_PORT_F_DEVICE_READY)
+		bfa_fsm_send_event(port, PORT_E_START);
+}
+
+void
+bna_port_disable(struct bna_port *port, enum bna_cleanup_type type,
+		 void (*cbfn)(void *, enum bna_cb_status))
+{
+	if (type == BNA_SOFT_CLEANUP) {
+		(*cbfn)(port->bna->bnad, BNA_CB_SUCCESS);
+		return;
+	}
+
+	port->stop_cbfn = cbfn;
+	port->stop_cbarg = port->bna->bnad;
+
+	port->flags &= ~BNA_PORT_F_ENABLED;
+
+	bfa_fsm_send_event(port, PORT_E_STOP);
+}
+
+void
+bna_port_pause_config(struct bna_port *port,
+		      struct bna_pause_config *pause_config,
+		      void (*cbfn)(struct bnad *, enum bna_cb_status))
+{
+	port->pause_config = *pause_config;
+
+	port->pause_cbfn = cbfn;
+
+	bfa_fsm_send_event(port, PORT_E_PAUSE_CFG);
+}
+
+void
+bna_port_mtu_set(struct bna_port *port, int mtu,
+		 void (*cbfn)(struct bnad *, enum bna_cb_status))
+{
+	port->mtu = mtu;
+
+	port->mtu_cbfn = cbfn;
+
+	bfa_fsm_send_event(port, PORT_E_MTU_CFG);
+}
+
+void
+bna_port_mac_get(struct bna_port *port, mac_t *mac)
+{
+	*mac = bfa_nw_ioc_get_mac(&port->bna->device.ioc);
+}
+
+/**
+ * DEVICE
+ */
+#define enable_mbox_intr(_device)\
+do {\
+	u32 intr_status;\
+	bna_intr_status_get((_device)->bna, intr_status);\
+	bnad_cb_device_enable_mbox_intr((_device)->bna->bnad);\
+	bna_mbox_intr_enable((_device)->bna);\
+} while (0)
+
+#define disable_mbox_intr(_device)\
+do {\
+	bna_mbox_intr_disable((_device)->bna);\
+	bnad_cb_device_disable_mbox_intr((_device)->bna->bnad);\
+} while (0)
+
+static const struct bna_chip_regs_offset reg_offset[] =
+{{HOST_PAGE_NUM_FN0, HOSTFN0_INT_STATUS,
+	HOSTFN0_INT_MASK, HOST_MSIX_ERR_INDEX_FN0},
+{HOST_PAGE_NUM_FN1, HOSTFN1_INT_STATUS,
+	HOSTFN1_INT_MASK, HOST_MSIX_ERR_INDEX_FN1},
+{HOST_PAGE_NUM_FN2, HOSTFN2_INT_STATUS,
+	HOSTFN2_INT_MASK, HOST_MSIX_ERR_INDEX_FN2},
+{HOST_PAGE_NUM_FN3, HOSTFN3_INT_STATUS,
+	HOSTFN3_INT_MASK, HOST_MSIX_ERR_INDEX_FN3},
+};
+
+enum bna_device_event {
+	DEVICE_E_ENABLE			= 1,
+	DEVICE_E_DISABLE		= 2,
+	DEVICE_E_IOC_READY		= 3,
+	DEVICE_E_IOC_FAILED		= 4,
+	DEVICE_E_IOC_DISABLED		= 5,
+	DEVICE_E_IOC_RESET		= 6,
+	DEVICE_E_PORT_STOPPED		= 7,
+};
+
+enum bna_device_state {
+	BNA_DEVICE_STOPPED		= 1,
+	BNA_DEVICE_IOC_READY_WAIT 	= 2,
+	BNA_DEVICE_READY		= 3,
+	BNA_DEVICE_PORT_STOP_WAIT 	= 4,
+	BNA_DEVICE_IOC_DISABLE_WAIT 	= 5,
+	BNA_DEVICE_FAILED		= 6
+};
+
+bfa_fsm_state_decl(bna_device, stopped, struct bna_device,
+			enum bna_device_event);
+bfa_fsm_state_decl(bna_device, ioc_ready_wait, struct bna_device,
+			enum bna_device_event);
+bfa_fsm_state_decl(bna_device, ready, struct bna_device,
+			enum bna_device_event);
+bfa_fsm_state_decl(bna_device, port_stop_wait, struct bna_device,
+			enum bna_device_event);
+bfa_fsm_state_decl(bna_device, ioc_disable_wait, struct bna_device,
+			enum bna_device_event);
+bfa_fsm_state_decl(bna_device, failed, struct bna_device,
+			enum bna_device_event);
+
+static struct bfa_sm_table device_sm_table[] = {
+	{BFA_SM(bna_device_sm_stopped), BNA_DEVICE_STOPPED},
+	{BFA_SM(bna_device_sm_ioc_ready_wait), BNA_DEVICE_IOC_READY_WAIT},
+	{BFA_SM(bna_device_sm_ready), BNA_DEVICE_READY},
+	{BFA_SM(bna_device_sm_port_stop_wait), BNA_DEVICE_PORT_STOP_WAIT},
+	{BFA_SM(bna_device_sm_ioc_disable_wait), BNA_DEVICE_IOC_DISABLE_WAIT},
+	{BFA_SM(bna_device_sm_failed), BNA_DEVICE_FAILED},
+};
+
+static void
+bna_device_sm_stopped_entry(struct bna_device *device)
+{
+	if (device->stop_cbfn)
+		device->stop_cbfn(device->stop_cbarg, BNA_CB_SUCCESS);
+
+	device->stop_cbfn = NULL;
+	device->stop_cbarg = NULL;
+}
+
+static void
+bna_device_sm_stopped(struct bna_device *device,
+			enum bna_device_event event)
+{
+	switch (event) {
+	case DEVICE_E_ENABLE:
+		if (device->intr_type == BNA_INTR_T_MSIX)
+			bna_mbox_msix_idx_set(device);
+		bfa_nw_ioc_enable(&device->ioc);
+		bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait);
+		break;
+
+	case DEVICE_E_DISABLE:
+		bfa_fsm_set_state(device, bna_device_sm_stopped);
+		break;
+
+	case DEVICE_E_IOC_RESET:
+		enable_mbox_intr(device);
+		break;
+
+	case DEVICE_E_IOC_FAILED:
+		bfa_fsm_set_state(device, bna_device_sm_failed);
+		break;
+
+	default:
+		bfa_sm_fault(device->bna, event);
+	}
+}
+
+static void
+bna_device_sm_ioc_ready_wait_entry(struct bna_device *device)
+{
+	/**
+	 * Do not call bfa_ioc_enable() here. It must be called in the
+	 * previous state due to failed -> ioc_ready_wait transition.
+	 */
+}
+
+static void
+bna_device_sm_ioc_ready_wait(struct bna_device *device,
+				enum bna_device_event event)
+{
+	switch (event) {
+	case DEVICE_E_DISABLE:
+		if (device->ready_cbfn)
+			device->ready_cbfn(device->ready_cbarg,
+						BNA_CB_INTERRUPT);
+		device->ready_cbfn = NULL;
+		device->ready_cbarg = NULL;
+		bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
+		break;
+
+	case DEVICE_E_IOC_READY:
+		bfa_fsm_set_state(device, bna_device_sm_ready);
+		break;
+
+	case DEVICE_E_IOC_FAILED:
+		bfa_fsm_set_state(device, bna_device_sm_failed);
+		break;
+
+	case DEVICE_E_IOC_RESET:
+		enable_mbox_intr(device);
+		break;
+
+	default:
+		bfa_sm_fault(device->bna, event);
+	}
+}
+
+static void
+bna_device_sm_ready_entry(struct bna_device *device)
+{
+	bna_mbox_mod_start(&device->bna->mbox_mod);
+	bna_port_start(&device->bna->port);
+
+	if (device->ready_cbfn)
+		device->ready_cbfn(device->ready_cbarg,
+					BNA_CB_SUCCESS);
+	device->ready_cbfn = NULL;
+	device->ready_cbarg = NULL;
+}
+
+static void
+bna_device_sm_ready(struct bna_device *device, enum bna_device_event event)
+{
+	switch (event) {
+	case DEVICE_E_DISABLE:
+		bfa_fsm_set_state(device, bna_device_sm_port_stop_wait);
+		break;
+
+	case DEVICE_E_IOC_FAILED:
+		bfa_fsm_set_state(device, bna_device_sm_failed);
+		break;
+
+	default:
+		bfa_sm_fault(device->bna, event);
+	}
+}
+
+static void
+bna_device_sm_port_stop_wait_entry(struct bna_device *device)
+{
+	bna_port_stop(&device->bna->port);
+}
+
+static void
+bna_device_sm_port_stop_wait(struct bna_device *device,
+				enum bna_device_event event)
+{
+	switch (event) {
+	case DEVICE_E_PORT_STOPPED:
+		bna_mbox_mod_stop(&device->bna->mbox_mod);
+		bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
+		break;
+
+	case DEVICE_E_IOC_FAILED:
+		disable_mbox_intr(device);
+		bna_port_fail(&device->bna->port);
+		break;
+
+	default:
+		bfa_sm_fault(device->bna, event);
+	}
+}
+
+static void
+bna_device_sm_ioc_disable_wait_entry(struct bna_device *device)
+{
+	bfa_nw_ioc_disable(&device->ioc);
+}
+
+static void
+bna_device_sm_ioc_disable_wait(struct bna_device *device,
+				enum bna_device_event event)
+{
+	switch (event) {
+	case DEVICE_E_IOC_DISABLED:
+		disable_mbox_intr(device);
+		bfa_fsm_set_state(device, bna_device_sm_stopped);
+		break;
+
+	default:
+		bfa_sm_fault(device->bna, event);
+	}
+}
+
+static void
+bna_device_sm_failed_entry(struct bna_device *device)
+{
+	disable_mbox_intr(device);
+	bna_port_fail(&device->bna->port);
+	bna_mbox_mod_stop(&device->bna->mbox_mod);
+
+	if (device->ready_cbfn)
+		device->ready_cbfn(device->ready_cbarg,
+					BNA_CB_FAIL);
+	device->ready_cbfn = NULL;
+	device->ready_cbarg = NULL;
+}
+
+static void
+bna_device_sm_failed(struct bna_device *device,
+			enum bna_device_event event)
+{
+	switch (event) {
+	case DEVICE_E_DISABLE:
+		bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
+		break;
+
+	case DEVICE_E_IOC_RESET:
+		enable_mbox_intr(device);
+		bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait);
+		break;
+
+	default:
+		bfa_sm_fault(device->bna, event);
+	}
+}
+
+/* IOC callback functions */
+
+static void
+bna_device_cb_iocll_ready(void *dev, enum bfa_status error)
+{
+	struct bna_device *device = (struct bna_device *)dev;
+
+	if (error)
+		bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED);
+	else
+		bfa_fsm_send_event(device, DEVICE_E_IOC_READY);
+}
+
+static void
+bna_device_cb_iocll_disabled(void *dev)
+{
+	struct bna_device *device = (struct bna_device *)dev;
+
+	bfa_fsm_send_event(device, DEVICE_E_IOC_DISABLED);
+}
+
+static void
+bna_device_cb_iocll_failed(void *dev)
+{
+	struct bna_device *device = (struct bna_device *)dev;
+
+	bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED);
+}
+
+static void
+bna_device_cb_iocll_reset(void *dev)
+{
+	struct bna_device *device = (struct bna_device *)dev;
+
+	bfa_fsm_send_event(device, DEVICE_E_IOC_RESET);
+}
+
+static struct bfa_ioc_cbfn bfa_iocll_cbfn = {
+	bna_device_cb_iocll_ready,
+	bna_device_cb_iocll_disabled,
+	bna_device_cb_iocll_failed,
+	bna_device_cb_iocll_reset
+};
+
+/* device */
+static void
+bna_adv_device_init(struct bna_device *device, struct bna *bna,
+		struct bna_res_info *res_info)
+{
+	u8 *kva;
+	u64 dma;
+
+	device->bna = bna;
+
+	kva = res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mdl[0].kva;
+
+	/**
+	 * Attach common modules (Diag, SFP, CEE, Port) and claim respective
+	 * DMA memory.
+	 */
+	BNA_GET_DMA_ADDR(
+		&res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].dma, dma);
+	kva = res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].kva;
+
+	bfa_nw_cee_attach(&bna->cee, &device->ioc, bna);
+	bfa_nw_cee_mem_claim(&bna->cee, kva, dma);
+	kva += bfa_nw_cee_meminfo();
+	dma += bfa_nw_cee_meminfo();
+
+}
+
+static void
+bna_device_init(struct bna_device *device, struct bna *bna,
+		struct bna_res_info *res_info)
+{
+	u64 dma;
+
+	device->bna = bna;
+
+	/**
+	 * Attach IOC and claim:
+	 *	1. DMA memory for IOC attributes
+	 *	2. Kernel memory for FW trace
+	 */
+	bfa_nw_ioc_attach(&device->ioc, device, &bfa_iocll_cbfn);
+	bfa_nw_ioc_pci_init(&device->ioc, &bna->pcidev, BFI_MC_LL);
+
+	BNA_GET_DMA_ADDR(
+		&res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].dma, dma);
+	bfa_nw_ioc_mem_claim(&device->ioc,
+		res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].kva,
+			  dma);
+
+	bna_adv_device_init(device, bna, res_info);
+	/*
+	 * Initialize mbox_mod only after IOC, so that mbox handler
+	 * registration goes through
+	 */
+	device->intr_type =
+		res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type;
+	device->vector =
+		res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.idl[0].vector;
+	bna_mbox_mod_init(&bna->mbox_mod, bna);
+
+	device->ready_cbfn = device->stop_cbfn = NULL;
+	device->ready_cbarg = device->stop_cbarg = NULL;
+
+	bfa_fsm_set_state(device, bna_device_sm_stopped);
+}
+
+static void
+bna_device_uninit(struct bna_device *device)
+{
+	bna_mbox_mod_uninit(&device->bna->mbox_mod);
+
+	bfa_nw_ioc_detach(&device->ioc);
+
+	device->bna = NULL;
+}
+
+static void
+bna_device_cb_port_stopped(void *arg, enum bna_cb_status status)
+{
+	struct bna_device *device = (struct bna_device *)arg;
+
+	bfa_fsm_send_event(device, DEVICE_E_PORT_STOPPED);
+}
+
+static int
+bna_device_status_get(struct bna_device *device)
+{
+	return device->fsm == (bfa_fsm_t)bna_device_sm_ready;
+}
+
+void
+bna_device_enable(struct bna_device *device)
+{
+	if (device->fsm != (bfa_fsm_t)bna_device_sm_stopped) {
+		bnad_cb_device_enabled(device->bna->bnad, BNA_CB_BUSY);
+		return;
+	}
+
+	device->ready_cbfn = bnad_cb_device_enabled;
+	device->ready_cbarg = device->bna->bnad;
+
+	bfa_fsm_send_event(device, DEVICE_E_ENABLE);
+}
+
+void
+bna_device_disable(struct bna_device *device, enum bna_cleanup_type type)
+{
+	if (type == BNA_SOFT_CLEANUP) {
+		bnad_cb_device_disabled(device->bna->bnad, BNA_CB_SUCCESS);
+		return;
+	}
+
+	device->stop_cbfn = bnad_cb_device_disabled;
+	device->stop_cbarg = device->bna->bnad;
+
+	bfa_fsm_send_event(device, DEVICE_E_DISABLE);
+}
+
+static int
+bna_device_state_get(struct bna_device *device)
+{
+	return bfa_sm_to_state(device_sm_table, device->fsm);
+}
+
+const u32 bna_napi_dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX] = {
+	{12, 12},
+	{6, 10},
+	{5, 10},
+	{4, 8},
+	{3, 6},
+	{3, 6},
+	{2, 4},
+	{1, 2},
+};
+
+/* utils */
+
+static void
+bna_adv_res_req(struct bna_res_info *res_info)
+{
+	/* DMA memory for COMMON_MODULE */
+	res_info[BNA_RES_MEM_T_COM].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+	res_info[BNA_RES_MEM_T_COM].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_COM].res_u.mem_info.len = ALIGN(
+				bfa_nw_cee_meminfo(), PAGE_SIZE);
+
+	/* Virtual memory for retreiving fw_trc */
+	res_info[BNA_RES_MEM_T_FWTRC].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.num = 0;
+	res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.len = 0;
+
+	/* DMA memory for retreiving stats */
+	res_info[BNA_RES_MEM_T_STATS].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+	res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.len =
+				ALIGN(BFI_HW_STATS_SIZE, PAGE_SIZE);
+
+	/* Virtual memory for soft stats */
+	res_info[BNA_RES_MEM_T_SWSTATS].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.len =
+				sizeof(struct bna_sw_stats);
+}
+
+static void
+bna_sw_stats_get(struct bna *bna, struct bna_sw_stats *sw_stats)
+{
+	struct bna_tx *tx;
+	struct bna_txq *txq;
+	struct bna_rx *rx;
+	struct bna_rxp *rxp;
+	struct list_head *qe;
+	struct list_head *txq_qe;
+	struct list_head *rxp_qe;
+	struct list_head *mac_qe;
+	int i;
+
+	sw_stats->device_state = bna_device_state_get(&bna->device);
+	sw_stats->port_state = bna_port_state_get(&bna->port);
+	sw_stats->port_flags = bna->port.flags;
+	sw_stats->llport_state = bna_llport_state_get(&bna->port.llport);
+	sw_stats->priority = bna->port.priority;
+
+	i = 0;
+	list_for_each(qe, &bna->tx_mod.tx_active_q) {
+		tx = (struct bna_tx *)qe;
+		sw_stats->tx_stats[i].tx_state = bna_tx_state_get(tx);
+		sw_stats->tx_stats[i].tx_flags = tx->flags;
+
+		sw_stats->tx_stats[i].num_txqs = 0;
+		sw_stats->tx_stats[i].txq_bmap[0] = 0;
+		sw_stats->tx_stats[i].txq_bmap[1] = 0;
+		list_for_each(txq_qe, &tx->txq_q) {
+			txq = (struct bna_txq *)txq_qe;
+			if (txq->txq_id < 32)
+				sw_stats->tx_stats[i].txq_bmap[0] |=
+						((u32)1 << txq->txq_id);
+			else
+				sw_stats->tx_stats[i].txq_bmap[1] |=
+						((u32)
+						 1 << (txq->txq_id - 32));
+			sw_stats->tx_stats[i].num_txqs++;
+		}
+
+		sw_stats->tx_stats[i].txf_id = tx->txf.txf_id;
+
+		i++;
+	}
+	sw_stats->num_active_tx = i;
+
+	i = 0;
+	list_for_each(qe, &bna->rx_mod.rx_active_q) {
+		rx = (struct bna_rx *)qe;
+		sw_stats->rx_stats[i].rx_state = bna_rx_state_get(rx);
+		sw_stats->rx_stats[i].rx_flags = rx->rx_flags;
+
+		sw_stats->rx_stats[i].num_rxps = 0;
+		sw_stats->rx_stats[i].num_rxqs = 0;
+		sw_stats->rx_stats[i].rxq_bmap[0] = 0;
+		sw_stats->rx_stats[i].rxq_bmap[1] = 0;
+		sw_stats->rx_stats[i].cq_bmap[0] = 0;
+		sw_stats->rx_stats[i].cq_bmap[1] = 0;
+		list_for_each(rxp_qe, &rx->rxp_q) {
+			rxp = (struct bna_rxp *)rxp_qe;
+
+			sw_stats->rx_stats[i].num_rxqs += 1;
+
+			if (rxp->type == BNA_RXP_SINGLE) {
+				if (rxp->rxq.single.only->rxq_id < 32) {
+					sw_stats->rx_stats[i].rxq_bmap[0] |=
+					((u32)1 <<
+					rxp->rxq.single.only->rxq_id);
+				} else {
+					sw_stats->rx_stats[i].rxq_bmap[1] |=
+					((u32)1 <<
+					(rxp->rxq.single.only->rxq_id - 32));
+				}
+			} else {
+				if (rxp->rxq.slr.large->rxq_id < 32) {
+					sw_stats->rx_stats[i].rxq_bmap[0] |=
+					((u32)1 <<
+					rxp->rxq.slr.large->rxq_id);
+				} else {
+					sw_stats->rx_stats[i].rxq_bmap[1] |=
+					((u32)1 <<
+					(rxp->rxq.slr.large->rxq_id - 32));
+				}
+
+				if (rxp->rxq.slr.small->rxq_id < 32) {
+					sw_stats->rx_stats[i].rxq_bmap[0] |=
+					((u32)1 <<
+					rxp->rxq.slr.small->rxq_id);
+				} else {
+					sw_stats->rx_stats[i].rxq_bmap[1] |=
+				((u32)1 <<
+				 (rxp->rxq.slr.small->rxq_id - 32));
+				}
+				sw_stats->rx_stats[i].num_rxqs += 1;
+			}
+
+			if (rxp->cq.cq_id < 32)
+				sw_stats->rx_stats[i].cq_bmap[0] |=
+					(1 << rxp->cq.cq_id);
+			else
+				sw_stats->rx_stats[i].cq_bmap[1] |=
+					(1 << (rxp->cq.cq_id - 32));
+
+			sw_stats->rx_stats[i].num_rxps++;
+		}
+
+		sw_stats->rx_stats[i].rxf_id = rx->rxf.rxf_id;
+		sw_stats->rx_stats[i].rxf_state = bna_rxf_state_get(&rx->rxf);
+		sw_stats->rx_stats[i].rxf_oper_state = rx->rxf.rxf_oper_state;
+
+		sw_stats->rx_stats[i].num_active_ucast = 0;
+		if (rx->rxf.ucast_active_mac)
+			sw_stats->rx_stats[i].num_active_ucast++;
+		list_for_each(mac_qe, &rx->rxf.ucast_active_q)
+			sw_stats->rx_stats[i].num_active_ucast++;
+
+		sw_stats->rx_stats[i].num_active_mcast = 0;
+		list_for_each(mac_qe, &rx->rxf.mcast_active_q)
+			sw_stats->rx_stats[i].num_active_mcast++;
+
+		sw_stats->rx_stats[i].rxmode_active = rx->rxf.rxmode_active;
+		sw_stats->rx_stats[i].vlan_filter_status =
+						rx->rxf.vlan_filter_status;
+		memcpy(sw_stats->rx_stats[i].vlan_filter_table,
+				rx->rxf.vlan_filter_table,
+				sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32));
+
+		sw_stats->rx_stats[i].rss_status = rx->rxf.rss_status;
+		sw_stats->rx_stats[i].hds_status = rx->rxf.hds_status;
+
+		i++;
+	}
+	sw_stats->num_active_rx = i;
+}
+
+static void
+bna_fw_cb_stats_get(void *arg, int status)
+{
+	struct bna *bna = (struct bna *)arg;
+	u64 *p_stats;
+	int i, count;
+	int rxf_count, txf_count;
+	u64 rxf_bmap, txf_bmap;
+
+	bfa_q_qe_init(&bna->mbox_qe.qe);
+
+	if (status == 0) {
+		p_stats = (u64 *)bna->stats.hw_stats;
+		count = sizeof(struct bfi_ll_stats) / sizeof(u64);
+		for (i = 0; i < count; i++)
+			p_stats[i] = cpu_to_be64(p_stats[i]);
+
+		rxf_count = 0;
+		rxf_bmap = (u64)bna->stats.rxf_bmap[0] |
+			((u64)bna->stats.rxf_bmap[1] << 32);
+		for (i = 0; i < BFI_LL_RXF_ID_MAX; i++)
+			if (rxf_bmap & ((u64)1 << i))
+				rxf_count++;
+
+		txf_count = 0;
+		txf_bmap = (u64)bna->stats.txf_bmap[0] |
+			((u64)bna->stats.txf_bmap[1] << 32);
+		for (i = 0; i < BFI_LL_TXF_ID_MAX; i++)
+			if (txf_bmap & ((u64)1 << i))
+				txf_count++;
+
+		p_stats = (u64 *)&bna->stats.hw_stats->rxf_stats[0] +
+				((rxf_count * sizeof(struct bfi_ll_stats_rxf) +
+				txf_count * sizeof(struct bfi_ll_stats_txf))/
+				sizeof(u64));
+
+		/* Populate the TXF stats from the firmware DMAed copy */
+		for (i = (BFI_LL_TXF_ID_MAX - 1); i >= 0; i--)
+			if (txf_bmap & ((u64)1 << i)) {
+				p_stats -= sizeof(struct bfi_ll_stats_txf)/
+						sizeof(u64);
+				memcpy(&bna->stats.hw_stats->txf_stats[i],
+					p_stats,
+					sizeof(struct bfi_ll_stats_txf));
+			}
+
+		/* Populate the RXF stats from the firmware DMAed copy */
+		for (i = (BFI_LL_RXF_ID_MAX - 1); i >= 0; i--)
+			if (rxf_bmap & ((u64)1 << i)) {
+				p_stats -= sizeof(struct bfi_ll_stats_rxf)/
+						sizeof(u64);
+				memcpy(&bna->stats.hw_stats->rxf_stats[i],
+					p_stats,
+					sizeof(struct bfi_ll_stats_rxf));
+			}
+
+		bna_sw_stats_get(bna, bna->stats.sw_stats);
+		bnad_cb_stats_get(bna->bnad, BNA_CB_SUCCESS, &bna->stats);
+	} else
+		bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
+}
+
+static void
+bna_fw_stats_get(struct bna *bna)
+{
+	struct bfi_ll_stats_req ll_req;
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_GET_REQ, 0);
+	ll_req.stats_mask = htons(BFI_LL_STATS_ALL);
+
+	ll_req.rxf_id_mask[0] = htonl(bna->rx_mod.rxf_bmap[0]);
+	ll_req.rxf_id_mask[1] =	htonl(bna->rx_mod.rxf_bmap[1]);
+	ll_req.txf_id_mask[0] =	htonl(bna->tx_mod.txf_bmap[0]);
+	ll_req.txf_id_mask[1] =	htonl(bna->tx_mod.txf_bmap[1]);
+
+	ll_req.host_buffer.a32.addr_hi = bna->hw_stats_dma.msb;
+	ll_req.host_buffer.a32.addr_lo = bna->hw_stats_dma.lsb;
+
+	bna_mbox_qe_fill(&bna->mbox_qe, &ll_req, sizeof(ll_req),
+				bna_fw_cb_stats_get, bna);
+	bna_mbox_send(bna, &bna->mbox_qe);
+
+	bna->stats.rxf_bmap[0] = bna->rx_mod.rxf_bmap[0];
+	bna->stats.rxf_bmap[1] = bna->rx_mod.rxf_bmap[1];
+	bna->stats.txf_bmap[0] = bna->tx_mod.txf_bmap[0];
+	bna->stats.txf_bmap[1] = bna->tx_mod.txf_bmap[1];
+}
+
+void
+bna_stats_get(struct bna *bna)
+{
+	if (bna_device_status_get(&bna->device))
+		bna_fw_stats_get(bna);
+	else
+		bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
+}
+
+/* IB */
+static void
+bna_ib_coalescing_timeo_set(struct bna_ib *ib, u8 coalescing_timeo)
+{
+	ib->ib_config.coalescing_timeo = coalescing_timeo;
+
+	if (ib->start_count)
+		ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
+				(u32)ib->ib_config.coalescing_timeo, 0);
+}
+
+/* RxF */
+void
+bna_rxf_adv_init(struct bna_rxf *rxf,
+		struct bna_rx *rx,
+		struct bna_rx_config *q_config)
+{
+	switch (q_config->rxp_type) {
+	case BNA_RXP_SINGLE:
+		/* No-op */
+		break;
+	case BNA_RXP_SLR:
+		rxf->ctrl_flags |= BNA_RXF_CF_SM_LG_RXQ;
+		break;
+	case BNA_RXP_HDS:
+		rxf->hds_cfg.hdr_type = q_config->hds_config.hdr_type;
+		rxf->hds_cfg.header_size =
+				q_config->hds_config.header_size;
+		rxf->forced_offset = 0;
+		break;
+	default:
+		break;
+	}
+
+	if (q_config->rss_status == BNA_STATUS_T_ENABLED) {
+		rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE;
+		rxf->rss_cfg.hash_type = q_config->rss_config.hash_type;
+		rxf->rss_cfg.hash_mask = q_config->rss_config.hash_mask;
+		memcpy(&rxf->rss_cfg.toeplitz_hash_key[0],
+			&q_config->rss_config.toeplitz_hash_key[0],
+			sizeof(rxf->rss_cfg.toeplitz_hash_key));
+	}
+}
+
+static void
+rxf_fltr_mbox_cmd(struct bna_rxf *rxf, u8 cmd, enum bna_status status)
+{
+	struct bfi_ll_rxf_req req;
+
+	bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0);
+
+	req.rxf_id = rxf->rxf_id;
+	req.enable = status;
+
+	bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req),
+			rxf_cb_cam_fltr_mbox_cmd, rxf);
+
+	bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
+}
+
+static void
+__rxf_default_function_config(struct bna_rxf *rxf, enum bna_status status)
+{
+	struct bna_rx_fndb_ram *rx_fndb_ram;
+	u32 ctrl_flags;
+	int i;
+
+	rx_fndb_ram = (struct bna_rx_fndb_ram *)
+			BNA_GET_MEM_BASE_ADDR(rxf->rx->bna->pcidev.pci_bar_kva,
+			RX_FNDB_RAM_BASE_OFFSET);
+
+	for (i = 0; i < BFI_MAX_RXF; i++) {
+		if (status == BNA_STATUS_T_ENABLED) {
+			if (i == rxf->rxf_id)
+				continue;
+
+			ctrl_flags =
+				readl(&rx_fndb_ram[i].control_flags);
+			ctrl_flags |= BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE;
+			writel(ctrl_flags,
+						&rx_fndb_ram[i].control_flags);
+		} else {
+			ctrl_flags =
+				readl(&rx_fndb_ram[i].control_flags);
+			ctrl_flags &= ~BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE;
+			writel(ctrl_flags,
+						&rx_fndb_ram[i].control_flags);
+		}
+	}
+}
+
+int
+rxf_process_packet_filter_ucast(struct bna_rxf *rxf)
+{
+	struct bna_mac *mac = NULL;
+	struct list_head *qe;
+
+	/* Add additional MAC entries */
+	if (!list_empty(&rxf->ucast_pending_add_q)) {
+		bfa_q_deq(&rxf->ucast_pending_add_q, &qe);
+		bfa_q_qe_init(qe);
+		mac = (struct bna_mac *)qe;
+		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_ADD_REQ, mac);
+		list_add_tail(&mac->qe, &rxf->ucast_active_q);
+		return 1;
+	}
+
+	/* Delete MAC addresses previousely added */
+	if (!list_empty(&rxf->ucast_pending_del_q)) {
+		bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
+		bfa_q_qe_init(qe);
+		mac = (struct bna_mac *)qe;
+		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
+		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+rxf_process_packet_filter_promisc(struct bna_rxf *rxf)
+{
+	struct bna *bna = rxf->rx->bna;
+
+	/* Enable/disable promiscuous mode */
+	if (is_promisc_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* move promisc configuration from pending -> active */
+		promisc_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active |= BNA_RXMODE_PROMISC;
+
+		/* Disable VLAN filter to allow all VLANs */
+		__rxf_vlan_filter_set(rxf, BNA_STATUS_T_DISABLED);
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
+				BNA_STATUS_T_ENABLED);
+		return 1;
+	} else if (is_promisc_disable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* move promisc configuration from pending -> active */
+		promisc_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+		bna->rxf_promisc_id = BFI_MAX_RXF;
+
+		/* Revert VLAN filter */
+		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
+				BNA_STATUS_T_DISABLED);
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+rxf_process_packet_filter_default(struct bna_rxf *rxf)
+{
+	struct bna *bna = rxf->rx->bna;
+
+	/* Enable/disable default mode */
+	if (is_default_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* move default configuration from pending -> active */
+		default_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active |= BNA_RXMODE_DEFAULT;
+
+		/* Disable VLAN filter to allow all VLANs */
+		__rxf_vlan_filter_set(rxf, BNA_STATUS_T_DISABLED);
+		/* Redirect all other RxF vlan filtering to this one */
+		__rxf_default_function_config(rxf, BNA_STATUS_T_ENABLED);
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
+				BNA_STATUS_T_ENABLED);
+		return 1;
+	} else if (is_default_disable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* move default configuration from pending -> active */
+		default_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
+		bna->rxf_default_id = BFI_MAX_RXF;
+
+		/* Revert VLAN filter */
+		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+		/* Stop RxF vlan filter table redirection */
+		__rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
+				BNA_STATUS_T_DISABLED);
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+rxf_process_packet_filter_allmulti(struct bna_rxf *rxf)
+{
+	/* Enable/disable allmulti mode */
+	if (is_allmulti_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* move allmulti configuration from pending -> active */
+		allmulti_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active |= BNA_RXMODE_ALLMULTI;
+
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
+				BNA_STATUS_T_ENABLED);
+		return 1;
+	} else if (is_allmulti_disable(rxf->rxmode_pending,
+					rxf->rxmode_pending_bitmask)) {
+		/* move allmulti configuration from pending -> active */
+		allmulti_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
+				BNA_STATUS_T_DISABLED);
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+rxf_clear_packet_filter_ucast(struct bna_rxf *rxf)
+{
+	struct bna_mac *mac = NULL;
+	struct list_head *qe;
+
+	/* 1. delete pending ucast entries */
+	if (!list_empty(&rxf->ucast_pending_del_q)) {
+		bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
+		bfa_q_qe_init(qe);
+		mac = (struct bna_mac *)qe;
+		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
+		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+		return 1;
+	}
+
+	/* 2. clear active ucast entries; move them to pending_add_q */
+	if (!list_empty(&rxf->ucast_active_q)) {
+		bfa_q_deq(&rxf->ucast_active_q, &qe);
+		bfa_q_qe_init(qe);
+		mac = (struct bna_mac *)qe;
+		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
+		list_add_tail(&mac->qe, &rxf->ucast_pending_add_q);
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+rxf_clear_packet_filter_promisc(struct bna_rxf *rxf)
+{
+	struct bna *bna = rxf->rx->bna;
+
+	/* 6. Execute pending promisc mode disable command */
+	if (is_promisc_disable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* move promisc configuration from pending -> active */
+		promisc_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+		bna->rxf_promisc_id = BFI_MAX_RXF;
+
+		/* Revert VLAN filter */
+		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
+				BNA_STATUS_T_DISABLED);
+		return 1;
+	}
+
+	/* 7. Clear active promisc mode; move it to pending enable */
+	if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
+		/* move promisc configuration from active -> pending */
+		promisc_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+
+		/* Revert VLAN filter */
+		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
+				BNA_STATUS_T_DISABLED);
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+rxf_clear_packet_filter_default(struct bna_rxf *rxf)
+{
+	struct bna *bna = rxf->rx->bna;
+
+	/* 8. Execute pending default mode disable command */
+	if (is_default_disable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* move default configuration from pending -> active */
+		default_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
+		bna->rxf_default_id = BFI_MAX_RXF;
+
+		/* Revert VLAN filter */
+		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+		/* Stop RxF vlan filter table redirection */
+		__rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
+				BNA_STATUS_T_DISABLED);
+		return 1;
+	}
+
+	/* 9. Clear active default mode; move it to pending enable */
+	if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
+		/* move default configuration from active -> pending */
+		default_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
+
+		/* Revert VLAN filter */
+		__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+		/* Stop RxF vlan filter table redirection */
+		__rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
+				BNA_STATUS_T_DISABLED);
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf)
+{
+	/* 10. Execute pending allmulti mode disable command */
+	if (is_allmulti_disable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* move allmulti configuration from pending -> active */
+		allmulti_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
+				BNA_STATUS_T_DISABLED);
+		return 1;
+	}
+
+	/* 11. Clear active allmulti mode; move it to pending enable */
+	if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
+		/* move allmulti configuration from active -> pending */
+		allmulti_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+		rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
+				BNA_STATUS_T_DISABLED);
+		return 1;
+	}
+
+	return 0;
+}
+
+void
+rxf_reset_packet_filter_ucast(struct bna_rxf *rxf)
+{
+	struct list_head *qe;
+	struct bna_mac *mac;
+
+	/* 1. Move active ucast entries to pending_add_q */
+	while (!list_empty(&rxf->ucast_active_q)) {
+		bfa_q_deq(&rxf->ucast_active_q, &qe);
+		bfa_q_qe_init(qe);
+		list_add_tail(qe, &rxf->ucast_pending_add_q);
+	}
+
+	/* 2. Throw away delete pending ucast entries */
+	while (!list_empty(&rxf->ucast_pending_del_q)) {
+		bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
+		bfa_q_qe_init(qe);
+		mac = (struct bna_mac *)qe;
+		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+	}
+}
+
+void
+rxf_reset_packet_filter_promisc(struct bna_rxf *rxf)
+{
+	struct bna *bna = rxf->rx->bna;
+
+	/* 6. Clear pending promisc mode disable */
+	if (is_promisc_disable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		promisc_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+		bna->rxf_promisc_id = BFI_MAX_RXF;
+	}
+
+	/* 7. Move promisc mode config from active -> pending */
+	if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
+		promisc_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+	}
+
+}
+
+void
+rxf_reset_packet_filter_default(struct bna_rxf *rxf)
+{
+	struct bna *bna = rxf->rx->bna;
+
+	/* 8. Clear pending default mode disable */
+	if (is_default_disable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		default_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
+		bna->rxf_default_id = BFI_MAX_RXF;
+	}
+
+	/* 9. Move default mode config from active -> pending */
+	if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
+		default_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
+	}
+}
+
+void
+rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf)
+{
+	/* 10. Clear pending allmulti mode disable */
+	if (is_allmulti_disable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		allmulti_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+	}
+
+	/* 11. Move allmulti mode config from active -> pending */
+	if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
+		allmulti_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+	}
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ *  Returns:
+ *	0 = no h/w change
+ *	1 = need h/w change
+ */
+static int
+rxf_promisc_enable(struct bna_rxf *rxf)
+{
+	struct bna *bna = rxf->rx->bna;
+	int ret = 0;
+
+	/* There can not be any pending disable command */
+
+	/* Do nothing if pending enable or already enabled */
+	if (is_promisc_enable(rxf->rxmode_pending,
+			rxf->rxmode_pending_bitmask) ||
+			(rxf->rxmode_active & BNA_RXMODE_PROMISC)) {
+		/* Schedule enable */
+	} else {
+		/* Promisc mode should not be active in the system */
+		promisc_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		bna->rxf_promisc_id = rxf->rxf_id;
+		ret = 1;
+	}
+
+	return ret;
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ *  Returns:
+ *	0 = no h/w change
+ *	1 = need h/w change
+ */
+static int
+rxf_promisc_disable(struct bna_rxf *rxf)
+{
+	struct bna *bna = rxf->rx->bna;
+	int ret = 0;
+
+	/* There can not be any pending disable */
+
+	/* Turn off pending enable command , if any */
+	if (is_promisc_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* Promisc mode should not be active */
+		/* system promisc state should be pending */
+		promisc_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		/* Remove the promisc state from the system */
+		bna->rxf_promisc_id = BFI_MAX_RXF;
+
+		/* Schedule disable */
+	} else if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
+		/* Promisc mode should be active in the system */
+		promisc_disable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		ret = 1;
+
+	/* Do nothing if already disabled */
+	} else {
+	}
+
+	return ret;
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ *  Returns:
+ *	0 = no h/w change
+ *	1 = need h/w change
+ */
+static int
+rxf_default_enable(struct bna_rxf *rxf)
+{
+	struct bna *bna = rxf->rx->bna;
+	int ret = 0;
+
+	/* There can not be any pending disable command */
+
+	/* Do nothing if pending enable or already enabled */
+	if (is_default_enable(rxf->rxmode_pending,
+		rxf->rxmode_pending_bitmask) ||
+		(rxf->rxmode_active & BNA_RXMODE_DEFAULT)) {
+		/* Schedule enable */
+	} else {
+		/* Default mode should not be active in the system */
+		default_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		bna->rxf_default_id = rxf->rxf_id;
+		ret = 1;
+	}
+
+	return ret;
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ *  Returns:
+ *	0 = no h/w change
+ *	1 = need h/w change
+ */
+static int
+rxf_default_disable(struct bna_rxf *rxf)
+{
+	struct bna *bna = rxf->rx->bna;
+	int ret = 0;
+
+	/* There can not be any pending disable */
+
+	/* Turn off pending enable command , if any */
+	if (is_default_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* Promisc mode should not be active */
+		/* system default state should be pending */
+		default_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		/* Remove the default state from the system */
+		bna->rxf_default_id = BFI_MAX_RXF;
+
+	/* Schedule disable */
+	} else if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
+		/* Default mode should be active in the system */
+		default_disable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		ret = 1;
+
+	/* Do nothing if already disabled */
+	} else {
+	}
+
+	return ret;
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ *  Returns:
+ *	0 = no h/w change
+ *	1 = need h/w change
+ */
+static int
+rxf_allmulti_enable(struct bna_rxf *rxf)
+{
+	int ret = 0;
+
+	/* There can not be any pending disable command */
+
+	/* Do nothing if pending enable or already enabled */
+	if (is_allmulti_enable(rxf->rxmode_pending,
+			rxf->rxmode_pending_bitmask) ||
+			(rxf->rxmode_active & BNA_RXMODE_ALLMULTI)) {
+		/* Schedule enable */
+	} else {
+		allmulti_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ *  Returns:
+ *	0 = no h/w change
+ *	1 = need h/w change
+ */
+static int
+rxf_allmulti_disable(struct bna_rxf *rxf)
+{
+	int ret = 0;
+
+	/* There can not be any pending disable */
+
+	/* Turn off pending enable command , if any */
+	if (is_allmulti_enable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask)) {
+		/* Allmulti mode should not be active */
+		allmulti_inactive(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+
+	/* Schedule disable */
+	} else if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
+		allmulti_disable(rxf->rxmode_pending,
+				rxf->rxmode_pending_bitmask);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+/* RxF <- bnad */
+enum bna_cb_status
+bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode new_mode,
+		enum bna_rxmode bitmask,
+		void (*cbfn)(struct bnad *, struct bna_rx *,
+			     enum bna_cb_status))
+{
+	struct bna_rxf *rxf = &rx->rxf;
+	int need_hw_config = 0;
+
+	/* Error checks */
+
+	if (is_promisc_enable(new_mode, bitmask)) {
+		/* If promisc mode is already enabled elsewhere in the system */
+		if ((rx->bna->rxf_promisc_id != BFI_MAX_RXF) &&
+			(rx->bna->rxf_promisc_id != rxf->rxf_id))
+			goto err_return;
+
+		/* If default mode is already enabled in the system */
+		if (rx->bna->rxf_default_id != BFI_MAX_RXF)
+			goto err_return;
+
+		/* Trying to enable promiscuous and default mode together */
+		if (is_default_enable(new_mode, bitmask))
+			goto err_return;
+	}
+
+	if (is_default_enable(new_mode, bitmask)) {
+		/* If default mode is already enabled elsewhere in the system */
+		if ((rx->bna->rxf_default_id != BFI_MAX_RXF) &&
+			(rx->bna->rxf_default_id != rxf->rxf_id)) {
+				goto err_return;
+		}
+
+		/* If promiscuous mode is already enabled in the system */
+		if (rx->bna->rxf_promisc_id != BFI_MAX_RXF)
+			goto err_return;
+	}
+
+	/* Process the commands */
+
+	if (is_promisc_enable(new_mode, bitmask)) {
+		if (rxf_promisc_enable(rxf))
+			need_hw_config = 1;
+	} else if (is_promisc_disable(new_mode, bitmask)) {
+		if (rxf_promisc_disable(rxf))
+			need_hw_config = 1;
+	}
+
+	if (is_default_enable(new_mode, bitmask)) {
+		if (rxf_default_enable(rxf))
+			need_hw_config = 1;
+	} else if (is_default_disable(new_mode, bitmask)) {
+		if (rxf_default_disable(rxf))
+			need_hw_config = 1;
+	}
+
+	if (is_allmulti_enable(new_mode, bitmask)) {
+		if (rxf_allmulti_enable(rxf))
+			need_hw_config = 1;
+	} else if (is_allmulti_disable(new_mode, bitmask)) {
+		if (rxf_allmulti_disable(rxf))
+			need_hw_config = 1;
+	}
+
+	/* Trigger h/w if needed */
+
+	if (need_hw_config) {
+		rxf->cam_fltr_cbfn = cbfn;
+		rxf->cam_fltr_cbarg = rx->bna->bnad;
+		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+	} else if (cbfn)
+		(*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
+
+	return BNA_CB_SUCCESS;
+
+err_return:
+	return BNA_CB_FAIL;
+}
+
+void
+/* RxF <- bnad */
+bna_rx_vlanfilter_enable(struct bna_rx *rx)
+{
+	struct bna_rxf *rxf = &rx->rxf;
+
+	if (rxf->vlan_filter_status == BNA_STATUS_T_DISABLED) {
+		rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
+		rxf->vlan_filter_status = BNA_STATUS_T_ENABLED;
+		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+	}
+}
+
+/* Rx */
+
+/* Rx <- bnad */
+void
+bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo)
+{
+	struct bna_rxp *rxp;
+	struct list_head *qe;
+
+	list_for_each(qe, &rx->rxp_q) {
+		rxp = (struct bna_rxp *)qe;
+		rxp->cq.ccb->rx_coalescing_timeo = coalescing_timeo;
+		bna_ib_coalescing_timeo_set(rxp->cq.ib, coalescing_timeo);
+	}
+}
+
+/* Rx <- bnad */
+void
+bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX])
+{
+	int i, j;
+
+	for (i = 0; i < BNA_LOAD_T_MAX; i++)
+		for (j = 0; j < BNA_BIAS_T_MAX; j++)
+			bna->rx_mod.dim_vector[i][j] = vector[i][j];
+}
+
+/* Rx <- bnad */
+void
+bna_rx_dim_update(struct bna_ccb *ccb)
+{
+	struct bna *bna = ccb->cq->rx->bna;
+	u32 load, bias;
+	u32 pkt_rt, small_rt, large_rt;
+	u8 coalescing_timeo;
+
+	if ((ccb->pkt_rate.small_pkt_cnt == 0) &&
+		(ccb->pkt_rate.large_pkt_cnt == 0))
+		return;
+
+	/* Arrive at preconfigured coalescing timeo value based on pkt rate */
+
+	small_rt = ccb->pkt_rate.small_pkt_cnt;
+	large_rt = ccb->pkt_rate.large_pkt_cnt;
+
+	pkt_rt = small_rt + large_rt;
+
+	if (pkt_rt < BNA_PKT_RATE_10K)
+		load = BNA_LOAD_T_LOW_4;
+	else if (pkt_rt < BNA_PKT_RATE_20K)
+		load = BNA_LOAD_T_LOW_3;
+	else if (pkt_rt < BNA_PKT_RATE_30K)
+		load = BNA_LOAD_T_LOW_2;
+	else if (pkt_rt < BNA_PKT_RATE_40K)
+		load = BNA_LOAD_T_LOW_1;
+	else if (pkt_rt < BNA_PKT_RATE_50K)
+		load = BNA_LOAD_T_HIGH_1;
+	else if (pkt_rt < BNA_PKT_RATE_60K)
+		load = BNA_LOAD_T_HIGH_2;
+	else if (pkt_rt < BNA_PKT_RATE_80K)
+		load = BNA_LOAD_T_HIGH_3;
+	else
+		load = BNA_LOAD_T_HIGH_4;
+
+	if (small_rt > (large_rt << 1))
+		bias = 0;
+	else
+		bias = 1;
+
+	ccb->pkt_rate.small_pkt_cnt = 0;
+	ccb->pkt_rate.large_pkt_cnt = 0;
+
+	coalescing_timeo = bna->rx_mod.dim_vector[load][bias];
+	ccb->rx_coalescing_timeo = coalescing_timeo;
+
+	/* Set it to IB */
+	bna_ib_coalescing_timeo_set(ccb->cq->ib, coalescing_timeo);
+}
+
+/* Tx */
+/* TX <- bnad */
+void
+bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo)
+{
+	struct bna_txq *txq;
+	struct list_head *qe;
+
+	list_for_each(qe, &tx->txq_q) {
+		txq = (struct bna_txq *)qe;
+		bna_ib_coalescing_timeo_set(txq->ib, coalescing_timeo);
+	}
+}
+
+/*
+ * Private data
+ */
+
+struct bna_ritseg_pool_cfg {
+	u32	pool_size;
+	u32	pool_entry_size;
+};
+init_ritseg_pool(ritseg_pool_cfg);
+
+/*
+ * Private functions
+ */
+static void
+bna_ucam_mod_init(struct bna_ucam_mod *ucam_mod, struct bna *bna,
+		  struct bna_res_info *res_info)
+{
+	int i;
+
+	ucam_mod->ucmac = (struct bna_mac *)
+		res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
+
+	INIT_LIST_HEAD(&ucam_mod->free_q);
+	for (i = 0; i < BFI_MAX_UCMAC; i++) {
+		bfa_q_qe_init(&ucam_mod->ucmac[i].qe);
+		list_add_tail(&ucam_mod->ucmac[i].qe, &ucam_mod->free_q);
+	}
+
+	ucam_mod->bna = bna;
+}
+
+static void
+bna_ucam_mod_uninit(struct bna_ucam_mod *ucam_mod)
+{
+	struct list_head *qe;
+	int i = 0;
+
+	list_for_each(qe, &ucam_mod->free_q)
+		i++;
+
+	ucam_mod->bna = NULL;
+}
+
+static void
+bna_mcam_mod_init(struct bna_mcam_mod *mcam_mod, struct bna *bna,
+		  struct bna_res_info *res_info)
+{
+	int i;
+
+	mcam_mod->mcmac = (struct bna_mac *)
+		res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
+
+	INIT_LIST_HEAD(&mcam_mod->free_q);
+	for (i = 0; i < BFI_MAX_MCMAC; i++) {
+		bfa_q_qe_init(&mcam_mod->mcmac[i].qe);
+		list_add_tail(&mcam_mod->mcmac[i].qe, &mcam_mod->free_q);
+	}
+
+	mcam_mod->bna = bna;
+}
+
+static void
+bna_mcam_mod_uninit(struct bna_mcam_mod *mcam_mod)
+{
+	struct list_head *qe;
+	int i = 0;
+
+	list_for_each(qe, &mcam_mod->free_q)
+		i++;
+
+	mcam_mod->bna = NULL;
+}
+
+static void
+bna_rit_mod_init(struct bna_rit_mod *rit_mod,
+		struct bna_res_info *res_info)
+{
+	int i;
+	int j;
+	int count;
+	int offset;
+
+	rit_mod->rit = (struct bna_rit_entry *)
+		res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mdl[0].kva;
+	rit_mod->rit_segment = (struct bna_rit_segment *)
+		res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mdl[0].kva;
+
+	count = 0;
+	offset = 0;
+	for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
+		INIT_LIST_HEAD(&rit_mod->rit_seg_pool[i]);
+		for (j = 0; j < ritseg_pool_cfg[i].pool_size; j++) {
+			bfa_q_qe_init(&rit_mod->rit_segment[count].qe);
+			rit_mod->rit_segment[count].max_rit_size =
+					ritseg_pool_cfg[i].pool_entry_size;
+			rit_mod->rit_segment[count].rit_offset = offset;
+			rit_mod->rit_segment[count].rit =
+					&rit_mod->rit[offset];
+			list_add_tail(&rit_mod->rit_segment[count].qe,
+				&rit_mod->rit_seg_pool[i]);
+			count++;
+			offset += ritseg_pool_cfg[i].pool_entry_size;
+		}
+	}
+}
+
+static void
+bna_rit_mod_uninit(struct bna_rit_mod *rit_mod)
+{
+	struct bna_rit_segment *rit_segment;
+	struct list_head *qe;
+	int i;
+	int j;
+
+	for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
+		j = 0;
+		list_for_each(qe, &rit_mod->rit_seg_pool[i]) {
+			rit_segment = (struct bna_rit_segment *)qe;
+			j++;
+		}
+	}
+}
+
+/*
+ * Public functions
+ */
+
+/* Called during probe(), before calling bna_init() */
+void
+bna_res_req(struct bna_res_info *res_info)
+{
+	bna_adv_res_req(res_info);
+
+	/* DMA memory for retrieving IOC attributes */
+	res_info[BNA_RES_MEM_T_ATTR].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+	res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.len =
+				ALIGN(bfa_nw_ioc_meminfo(), PAGE_SIZE);
+
+	/* DMA memory for index segment of an IB */
+	res_info[BNA_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+	res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.len =
+				BFI_IBIDX_SIZE * BFI_IBIDX_MAX_SEGSIZE;
+	res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.num = BFI_MAX_IB;
+
+	/* Virtual memory for IB objects - stored by IB module */
+	res_info[BNA_RES_MEM_T_IB_ARRAY].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.len =
+				BFI_MAX_IB * sizeof(struct bna_ib);
+
+	/* Virtual memory for intr objects - stored by IB module */
+	res_info[BNA_RES_MEM_T_INTR_ARRAY].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.len =
+				BFI_MAX_IB * sizeof(struct bna_intr);
+
+	/* Virtual memory for idx_seg objects - stored by IB module */
+	res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.len =
+			BFI_IBIDX_TOTAL_SEGS * sizeof(struct bna_ibidx_seg);
+
+	/* Virtual memory for Tx objects - stored by Tx module */
+	res_info[BNA_RES_MEM_T_TX_ARRAY].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.len =
+			BFI_MAX_TXQ * sizeof(struct bna_tx);
+
+	/* Virtual memory for TxQ - stored by Tx module */
+	res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.len =
+			BFI_MAX_TXQ * sizeof(struct bna_txq);
+
+	/* Virtual memory for Rx objects - stored by Rx module */
+	res_info[BNA_RES_MEM_T_RX_ARRAY].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.len =
+			BFI_MAX_RXQ * sizeof(struct bna_rx);
+
+	/* Virtual memory for RxPath - stored by Rx module */
+	res_info[BNA_RES_MEM_T_RXP_ARRAY].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.len =
+			BFI_MAX_RXQ * sizeof(struct bna_rxp);
+
+	/* Virtual memory for RxQ - stored by Rx module */
+	res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.len =
+			BFI_MAX_RXQ * sizeof(struct bna_rxq);
+
+	/* Virtual memory for Unicast MAC address - stored by ucam module */
+	res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.len =
+			BFI_MAX_UCMAC * sizeof(struct bna_mac);
+
+	/* Virtual memory for Multicast MAC address - stored by mcam module */
+	res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.len =
+			BFI_MAX_MCMAC * sizeof(struct bna_mac);
+
+	/* Virtual memory for RIT entries */
+	res_info[BNA_RES_MEM_T_RIT_ENTRY].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.len =
+			BFI_MAX_RIT_SIZE * sizeof(struct bna_rit_entry);
+
+	/* Virtual memory for RIT segment table */
+	res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_type = BNA_RES_T_MEM;
+	res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mem_type =
+								BNA_MEM_T_KVA;
+	res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.num = 1;
+	res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.len =
+			BFI_RIT_TOTAL_SEGS * sizeof(struct bna_rit_segment);
+
+	/* Interrupt resource for mailbox interrupt */
+	res_info[BNA_RES_INTR_T_MBOX].res_type = BNA_RES_T_INTR;
+	res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type =
+							BNA_INTR_T_MSIX;
+	res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.num = 1;
+}
+
+/* Called during probe() */
+void
+bna_init(struct bna *bna, struct bnad *bnad, struct bfa_pcidev *pcidev,
+		struct bna_res_info *res_info)
+{
+	bna->bnad = bnad;
+	bna->pcidev = *pcidev;
+
+	bna->stats.hw_stats = (struct bfi_ll_stats *)
+		res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].kva;
+	bna->hw_stats_dma.msb =
+		res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.msb;
+	bna->hw_stats_dma.lsb =
+		res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.lsb;
+	bna->stats.sw_stats = (struct bna_sw_stats *)
+		res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mdl[0].kva;
+
+	bna->regs.page_addr = bna->pcidev.pci_bar_kva +
+				reg_offset[bna->pcidev.pci_func].page_addr;
+	bna->regs.fn_int_status = bna->pcidev.pci_bar_kva +
+				reg_offset[bna->pcidev.pci_func].fn_int_status;
+	bna->regs.fn_int_mask = bna->pcidev.pci_bar_kva +
+				reg_offset[bna->pcidev.pci_func].fn_int_mask;
+
+	if (bna->pcidev.pci_func < 3)
+		bna->port_num = 0;
+	else
+		bna->port_num = 1;
+
+	/* Also initializes diag, cee, sfp, phy_port and mbox_mod */
+	bna_device_init(&bna->device, bna, res_info);
+
+	bna_port_init(&bna->port, bna);
+
+	bna_tx_mod_init(&bna->tx_mod, bna, res_info);
+
+	bna_rx_mod_init(&bna->rx_mod, bna, res_info);
+
+	bna_ib_mod_init(&bna->ib_mod, bna, res_info);
+
+	bna_rit_mod_init(&bna->rit_mod, res_info);
+
+	bna_ucam_mod_init(&bna->ucam_mod, bna, res_info);
+
+	bna_mcam_mod_init(&bna->mcam_mod, bna, res_info);
+
+	bna->rxf_default_id = BFI_MAX_RXF;
+	bna->rxf_promisc_id = BFI_MAX_RXF;
+
+	/* Mbox q element for posting stat request to f/w */
+	bfa_q_qe_init(&bna->mbox_qe.qe);
+}
+
+void
+bna_uninit(struct bna *bna)
+{
+	bna_mcam_mod_uninit(&bna->mcam_mod);
+
+	bna_ucam_mod_uninit(&bna->ucam_mod);
+
+	bna_rit_mod_uninit(&bna->rit_mod);
+
+	bna_ib_mod_uninit(&bna->ib_mod);
+
+	bna_rx_mod_uninit(&bna->rx_mod);
+
+	bna_tx_mod_uninit(&bna->tx_mod);
+
+	bna_port_uninit(&bna->port);
+
+	bna_device_uninit(&bna->device);
+
+	bna->bnad = NULL;
+}
+
+struct bna_mac *
+bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod)
+{
+	struct list_head *qe;
+
+	if (list_empty(&ucam_mod->free_q))
+		return NULL;
+
+	bfa_q_deq(&ucam_mod->free_q, &qe);
+
+	return (struct bna_mac *)qe;
+}
+
+void
+bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod, struct bna_mac *mac)
+{
+	list_add_tail(&mac->qe, &ucam_mod->free_q);
+}
+
+struct bna_mac *
+bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod)
+{
+	struct list_head *qe;
+
+	if (list_empty(&mcam_mod->free_q))
+		return NULL;
+
+	bfa_q_deq(&mcam_mod->free_q, &qe);
+
+	return (struct bna_mac *)qe;
+}
+
+void
+bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod, struct bna_mac *mac)
+{
+	list_add_tail(&mac->qe, &mcam_mod->free_q);
+}
+
+/**
+ * Note: This should be called in the same locking context as the call to
+ * bna_rit_mod_seg_get()
+ */
+int
+bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size)
+{
+	int i;
+
+	/* Select the pool for seg_size */
+	for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
+		if (seg_size <= ritseg_pool_cfg[i].pool_entry_size)
+			break;
+	}
+
+	if (i == BFI_RIT_SEG_TOTAL_POOLS)
+		return 0;
+
+	if (list_empty(&rit_mod->rit_seg_pool[i]))
+		return 0;
+
+	return 1;
+}
+
+struct bna_rit_segment *
+bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size)
+{
+	struct bna_rit_segment *seg;
+	struct list_head *qe;
+	int i;
+
+	/* Select the pool for seg_size */
+	for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
+		if (seg_size <= ritseg_pool_cfg[i].pool_entry_size)
+			break;
+	}
+
+	if (i == BFI_RIT_SEG_TOTAL_POOLS)
+		return NULL;
+
+	if (list_empty(&rit_mod->rit_seg_pool[i]))
+		return NULL;
+
+	bfa_q_deq(&rit_mod->rit_seg_pool[i], &qe);
+	seg = (struct bna_rit_segment *)qe;
+	bfa_q_qe_init(&seg->qe);
+	seg->rit_size = seg_size;
+
+	return seg;
+}
+
+void
+bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod,
+			struct bna_rit_segment *seg)
+{
+	int i;
+
+	/* Select the pool for seg->max_rit_size */
+	for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
+		if (seg->max_rit_size == ritseg_pool_cfg[i].pool_entry_size)
+			break;
+	}
+
+	seg->rit_size = 0;
+	list_add_tail(&seg->qe, &rit_mod->rit_seg_pool[i]);
+}
diff --git a/drivers/net/bna/bna_hw.h b/drivers/net/bna/bna_hw.h
new file mode 100644
index 0000000..806b224
--- /dev/null
+++ b/drivers/net/bna/bna_hw.h
@@ -0,0 +1,1490 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * File for interrupt macros and functions
+ */
+
+#ifndef __BNA_HW_H__
+#define __BNA_HW_H__
+
+#include "bfi_ctreg.h"
+
+/**
+ *
+ * SW imposed limits
+ *
+ */
+
+#ifndef BNA_BIOS_BUILD
+
+#define BFI_MAX_TXQ			64
+#define BFI_MAX_RXQ			64
+#define	BFI_MAX_RXF			64
+#define BFI_MAX_IB			128
+#define	BFI_MAX_RIT_SIZE		256
+#define	BFI_RSS_RIT_SIZE		64
+#define	BFI_NONRSS_RIT_SIZE		1
+#define BFI_MAX_UCMAC			256
+#define BFI_MAX_MCMAC			512
+#define BFI_IBIDX_SIZE			4
+#define BFI_MAX_VLAN			4095
+
+/**
+ * There are 2 free IB index pools:
+ *	pool1: 120 segments of 1 index each
+ *	pool8: 1 segment of 8 indexes
+ */
+#define BFI_IBIDX_POOL1_SIZE		116
+#define	BFI_IBIDX_POOL1_ENTRY_SIZE	1
+#define BFI_IBIDX_POOL2_SIZE		2
+#define	BFI_IBIDX_POOL2_ENTRY_SIZE	2
+#define	BFI_IBIDX_POOL8_SIZE		1
+#define	BFI_IBIDX_POOL8_ENTRY_SIZE	8
+#define	BFI_IBIDX_TOTAL_POOLS		3
+#define	BFI_IBIDX_TOTAL_SEGS		119 /* (POOL1 + POOL2 + POOL8)_SIZE */
+#define	BFI_IBIDX_MAX_SEGSIZE		8
+#define init_ibidx_pool(name)						\
+static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] =		\
+{									\
+	{ BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE },		\
+	{ BFI_IBIDX_POOL2_SIZE, BFI_IBIDX_POOL2_ENTRY_SIZE },		\
+	{ BFI_IBIDX_POOL8_SIZE, BFI_IBIDX_POOL8_ENTRY_SIZE }		\
+}
+
+/**
+ * There are 2 free RIT segment pools:
+ * 	Pool1: 192 segments of 1 RIT entry each
+ *	Pool2: 1 segment of 64 RIT entry
+ */
+#define BFI_RIT_SEG_POOL1_SIZE		192
+#define BFI_RIT_SEG_POOL1_ENTRY_SIZE	1
+#define BFI_RIT_SEG_POOLRSS_SIZE	1
+#define BFI_RIT_SEG_POOLRSS_ENTRY_SIZE	64
+#define BFI_RIT_SEG_TOTAL_POOLS		2
+#define BFI_RIT_TOTAL_SEGS		193 /* POOL1_SIZE + POOLRSS_SIZE */
+#define init_ritseg_pool(name)						\
+static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] =	\
+{									\
+	{ BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE },	\
+	{ BFI_RIT_SEG_POOLRSS_SIZE, BFI_RIT_SEG_POOLRSS_ENTRY_SIZE }	\
+}
+
+#else /* BNA_BIOS_BUILD */
+
+#define BFI_MAX_TXQ			1
+#define BFI_MAX_RXQ			1
+#define	BFI_MAX_RXF			1
+#define BFI_MAX_IB			2
+#define	BFI_MAX_RIT_SIZE		2
+#define	BFI_RSS_RIT_SIZE		64
+#define	BFI_NONRSS_RIT_SIZE		1
+#define BFI_MAX_UCMAC			1
+#define BFI_MAX_MCMAC			8
+#define BFI_IBIDX_SIZE			4
+#define BFI_MAX_VLAN			4095
+/* There is one free pool: 2 segments of 1 index each */
+#define BFI_IBIDX_POOL1_SIZE		2
+#define	BFI_IBIDX_POOL1_ENTRY_SIZE	1
+#define	BFI_IBIDX_TOTAL_POOLS		1
+#define	BFI_IBIDX_TOTAL_SEGS		2 /* POOL1_SIZE */
+#define	BFI_IBIDX_MAX_SEGSIZE		1
+#define init_ibidx_pool(name)						\
+static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] =		\
+{									\
+	{ BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE }		\
+}
+
+#define BFI_RIT_SEG_POOL1_SIZE		1
+#define BFI_RIT_SEG_POOL1_ENTRY_SIZE	1
+#define BFI_RIT_SEG_TOTAL_POOLS		1
+#define BFI_RIT_TOTAL_SEGS		1 /* POOL1_SIZE */
+#define init_ritseg_pool(name)						\
+static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] =	\
+{									\
+	{ BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE }	\
+}
+
+#endif /* BNA_BIOS_BUILD */
+
+#define BFI_RSS_HASH_KEY_LEN		10
+
+#define BFI_COALESCING_TIMER_UNIT	5	/* 5us */
+#define BFI_MAX_COALESCING_TIMEO	0xFF	/* in 5us units */
+#define BFI_MAX_INTERPKT_COUNT		0xFF
+#define BFI_MAX_INTERPKT_TIMEO		0xF	/* in 0.5us units */
+#define BFI_TX_COALESCING_TIMEO		20	/* 20 * 5 = 100us */
+#define BFI_TX_INTERPKT_COUNT		32
+#define	BFI_RX_COALESCING_TIMEO		12	/* 12 * 5 = 60us */
+#define	BFI_RX_INTERPKT_COUNT		6	/* Pkt Cnt = 6 */
+#define	BFI_RX_INTERPKT_TIMEO		3	/* 3 * 0.5 = 1.5us */
+
+#define BFI_TXQ_WI_SIZE			64	/* bytes */
+#define BFI_RXQ_WI_SIZE			8	/* bytes */
+#define BFI_CQ_WI_SIZE			16	/* bytes */
+#define BFI_TX_MAX_WRR_QUOTA		0xFFF
+
+#define BFI_TX_MAX_VECTORS_PER_WI	4
+#define BFI_TX_MAX_VECTORS_PER_PKT	0xFF
+#define BFI_TX_MAX_DATA_PER_VECTOR	0xFFFF
+#define BFI_TX_MAX_DATA_PER_PKT		0xFFFFFF
+
+/* Small Q buffer size */
+#define BFI_SMALL_RXBUF_SIZE		128
+
+/* Defined separately since BFA_FLASH_DMA_BUF_SZ is in bfa_flash.c */
+#define BFI_FLASH_DMA_BUF_SZ		0x010000 /* 64K DMA */
+#define BFI_HW_STATS_SIZE		0x4000 /* 16K DMA */
+
+/**
+ *
+ * HW register offsets, macros
+ *
+ */
+
+/* DMA Block Register Host Window Start Address */
+#define DMA_BLK_REG_ADDR		0x00013000
+
+/* DMA Block Internal Registers */
+#define DMA_CTRL_REG0			(DMA_BLK_REG_ADDR + 0x000)
+#define DMA_CTRL_REG1			(DMA_BLK_REG_ADDR + 0x004)
+#define DMA_ERR_INT_STATUS		(DMA_BLK_REG_ADDR + 0x008)
+#define DMA_ERR_INT_ENABLE		(DMA_BLK_REG_ADDR + 0x00c)
+#define DMA_ERR_INT_STATUS_SET		(DMA_BLK_REG_ADDR + 0x010)
+
+/* APP Block Register Address Offset from BAR0 */
+#define APP_BLK_REG_ADDR		0x00014000
+
+/* Host Function Interrupt Mask Registers */
+#define HOSTFN0_INT_MASK		(APP_BLK_REG_ADDR + 0x004)
+#define HOSTFN1_INT_MASK		(APP_BLK_REG_ADDR + 0x104)
+#define HOSTFN2_INT_MASK		(APP_BLK_REG_ADDR + 0x304)
+#define HOSTFN3_INT_MASK		(APP_BLK_REG_ADDR + 0x404)
+
+/**
+ * Host Function PCIe Error Registers
+ * Duplicates "Correctable" & "Uncorrectable"
+ * registers in PCIe Config space.
+ */
+#define FN0_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x014)
+#define FN1_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x114)
+#define FN2_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x314)
+#define FN3_PCIE_ERR_REG		(APP_BLK_REG_ADDR + 0x414)
+
+/* Host Function Error Type Status Registers */
+#define FN0_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x018)
+#define FN1_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x118)
+#define FN2_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x318)
+#define FN3_ERR_TYPE_STATUS_REG		(APP_BLK_REG_ADDR + 0x418)
+
+/* Host Function Error Type Mask Registers */
+#define FN0_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x01c)
+#define FN1_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x11c)
+#define FN2_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x31c)
+#define FN3_ERR_TYPE_MSK_STATUS_REG	(APP_BLK_REG_ADDR + 0x41c)
+
+/* Catapult Host Semaphore Status Registers (App block) */
+#define HOST_SEM_STS0_REG		(APP_BLK_REG_ADDR + 0x630)
+#define HOST_SEM_STS1_REG		(APP_BLK_REG_ADDR + 0x634)
+#define HOST_SEM_STS2_REG		(APP_BLK_REG_ADDR + 0x638)
+#define HOST_SEM_STS3_REG		(APP_BLK_REG_ADDR + 0x63c)
+#define HOST_SEM_STS4_REG		(APP_BLK_REG_ADDR + 0x640)
+#define HOST_SEM_STS5_REG		(APP_BLK_REG_ADDR + 0x644)
+#define HOST_SEM_STS6_REG		(APP_BLK_REG_ADDR + 0x648)
+#define HOST_SEM_STS7_REG		(APP_BLK_REG_ADDR + 0x64c)
+
+/* PCIe Misc Register */
+#define PCIE_MISC_REG			(APP_BLK_REG_ADDR + 0x200)
+
+/* Temp Sensor Control Registers */
+#define TEMPSENSE_CNTL_REG		(APP_BLK_REG_ADDR + 0x250)
+#define TEMPSENSE_STAT_REG		(APP_BLK_REG_ADDR + 0x254)
+
+/* APP Block local error registers */
+#define APP_LOCAL_ERR_STAT		(APP_BLK_REG_ADDR + 0x258)
+#define APP_LOCAL_ERR_MSK		(APP_BLK_REG_ADDR + 0x25c)
+
+/* PCIe Link Error registers */
+#define PCIE_LNK_ERR_STAT		(APP_BLK_REG_ADDR + 0x260)
+#define PCIE_LNK_ERR_MSK		(APP_BLK_REG_ADDR + 0x264)
+
+/**
+ * FCoE/FIP Ethertype Register
+ * 31:16 -- Chip wide value for FIP type
+ * 15:0  -- Chip wide value for FCoE type
+ */
+#define FCOE_FIP_ETH_TYPE		(APP_BLK_REG_ADDR + 0x280)
+
+/**
+ * Reserved Ethertype Register
+ * 31:16 -- Reserved
+ * 15:0  -- Other ethertype
+ */
+#define RESV_ETH_TYPE			(APP_BLK_REG_ADDR + 0x284)
+
+/**
+ * Host Command Status Registers
+ * Each set consists of 3 registers :
+ * clear, set, cmd
+ * 16 such register sets in all
+ * See catapult_spec.pdf for detailed functionality
+ * Put each type in a single macro accessed by _num ?
+ */
+#define HOST_CMDSTS0_CLR_REG		(APP_BLK_REG_ADDR + 0x500)
+#define HOST_CMDSTS0_SET_REG		(APP_BLK_REG_ADDR + 0x504)
+#define HOST_CMDSTS0_REG		(APP_BLK_REG_ADDR + 0x508)
+#define HOST_CMDSTS1_CLR_REG		(APP_BLK_REG_ADDR + 0x510)
+#define HOST_CMDSTS1_SET_REG		(APP_BLK_REG_ADDR + 0x514)
+#define HOST_CMDSTS1_REG		(APP_BLK_REG_ADDR + 0x518)
+#define HOST_CMDSTS2_CLR_REG		(APP_BLK_REG_ADDR + 0x520)
+#define HOST_CMDSTS2_SET_REG		(APP_BLK_REG_ADDR + 0x524)
+#define HOST_CMDSTS2_REG		(APP_BLK_REG_ADDR + 0x528)
+#define HOST_CMDSTS3_CLR_REG		(APP_BLK_REG_ADDR + 0x530)
+#define HOST_CMDSTS3_SET_REG		(APP_BLK_REG_ADDR + 0x534)
+#define HOST_CMDSTS3_REG		(APP_BLK_REG_ADDR + 0x538)
+#define HOST_CMDSTS4_CLR_REG		(APP_BLK_REG_ADDR + 0x540)
+#define HOST_CMDSTS4_SET_REG		(APP_BLK_REG_ADDR + 0x544)
+#define HOST_CMDSTS4_REG		(APP_BLK_REG_ADDR + 0x548)
+#define HOST_CMDSTS5_CLR_REG		(APP_BLK_REG_ADDR + 0x550)
+#define HOST_CMDSTS5_SET_REG		(APP_BLK_REG_ADDR + 0x554)
+#define HOST_CMDSTS5_REG		(APP_BLK_REG_ADDR + 0x558)
+#define HOST_CMDSTS6_CLR_REG		(APP_BLK_REG_ADDR + 0x560)
+#define HOST_CMDSTS6_SET_REG		(APP_BLK_REG_ADDR + 0x564)
+#define HOST_CMDSTS6_REG		(APP_BLK_REG_ADDR + 0x568)
+#define HOST_CMDSTS7_CLR_REG		(APP_BLK_REG_ADDR + 0x570)
+#define HOST_CMDSTS7_SET_REG		(APP_BLK_REG_ADDR + 0x574)
+#define HOST_CMDSTS7_REG		(APP_BLK_REG_ADDR + 0x578)
+#define HOST_CMDSTS8_CLR_REG		(APP_BLK_REG_ADDR + 0x580)
+#define HOST_CMDSTS8_SET_REG		(APP_BLK_REG_ADDR + 0x584)
+#define HOST_CMDSTS8_REG		(APP_BLK_REG_ADDR + 0x588)
+#define HOST_CMDSTS9_CLR_REG		(APP_BLK_REG_ADDR + 0x590)
+#define HOST_CMDSTS9_SET_REG		(APP_BLK_REG_ADDR + 0x594)
+#define HOST_CMDSTS9_REG		(APP_BLK_REG_ADDR + 0x598)
+#define HOST_CMDSTS10_CLR_REG		(APP_BLK_REG_ADDR + 0x5A0)
+#define HOST_CMDSTS10_SET_REG		(APP_BLK_REG_ADDR + 0x5A4)
+#define HOST_CMDSTS10_REG		(APP_BLK_REG_ADDR + 0x5A8)
+#define HOST_CMDSTS11_CLR_REG		(APP_BLK_REG_ADDR + 0x5B0)
+#define HOST_CMDSTS11_SET_REG		(APP_BLK_REG_ADDR + 0x5B4)
+#define HOST_CMDSTS11_REG		(APP_BLK_REG_ADDR + 0x5B8)
+#define HOST_CMDSTS12_CLR_REG		(APP_BLK_REG_ADDR + 0x5C0)
+#define HOST_CMDSTS12_SET_REG		(APP_BLK_REG_ADDR + 0x5C4)
+#define HOST_CMDSTS12_REG		(APP_BLK_REG_ADDR + 0x5C8)
+#define HOST_CMDSTS13_CLR_REG		(APP_BLK_REG_ADDR + 0x5D0)
+#define HOST_CMDSTS13_SET_REG		(APP_BLK_REG_ADDR + 0x5D4)
+#define HOST_CMDSTS13_REG		(APP_BLK_REG_ADDR + 0x5D8)
+#define HOST_CMDSTS14_CLR_REG		(APP_BLK_REG_ADDR + 0x5E0)
+#define HOST_CMDSTS14_SET_REG		(APP_BLK_REG_ADDR + 0x5E4)
+#define HOST_CMDSTS14_REG		(APP_BLK_REG_ADDR + 0x5E8)
+#define HOST_CMDSTS15_CLR_REG		(APP_BLK_REG_ADDR + 0x5F0)
+#define HOST_CMDSTS15_SET_REG		(APP_BLK_REG_ADDR + 0x5F4)
+#define HOST_CMDSTS15_REG		(APP_BLK_REG_ADDR + 0x5F8)
+
+/**
+ * LPU0 Block Register Address Offset from BAR0
+ * Range 0x18000 - 0x18033
+ */
+#define LPU0_BLK_REG_ADDR		0x00018000
+
+/**
+ * LPU0 Registers
+ * Should they be directly used from host,
+ * except for diagnostics ?
+ * CTL_REG : Control register
+ * CMD_REG : Triggers exec. of cmd. in
+ *           Mailbox memory
+ */
+#define LPU0_MBOX_CTL_REG		(LPU0_BLK_REG_ADDR + 0x000)
+#define LPU0_MBOX_CMD_REG		(LPU0_BLK_REG_ADDR + 0x004)
+#define LPU0_MBOX_LINK_0REG		(LPU0_BLK_REG_ADDR + 0x008)
+#define LPU1_MBOX_LINK_0REG		(LPU0_BLK_REG_ADDR + 0x00c)
+#define LPU0_MBOX_STATUS_0REG		(LPU0_BLK_REG_ADDR + 0x010)
+#define LPU1_MBOX_STATUS_0REG		(LPU0_BLK_REG_ADDR + 0x014)
+#define LPU0_ERR_STATUS_REG		(LPU0_BLK_REG_ADDR + 0x018)
+#define LPU0_ERR_SET_REG		(LPU0_BLK_REG_ADDR + 0x020)
+
+/**
+ * LPU1 Block Register Address Offset from BAR0
+ * Range 0x18400 - 0x18433
+ */
+#define LPU1_BLK_REG_ADDR		0x00018400
+
+/**
+ * LPU1 Registers
+ * Same as LPU0 registers above
+ */
+#define LPU1_MBOX_CTL_REG		(LPU1_BLK_REG_ADDR + 0x000)
+#define LPU1_MBOX_CMD_REG		(LPU1_BLK_REG_ADDR + 0x004)
+#define LPU0_MBOX_LINK_1REG		(LPU1_BLK_REG_ADDR + 0x008)
+#define LPU1_MBOX_LINK_1REG		(LPU1_BLK_REG_ADDR + 0x00c)
+#define LPU0_MBOX_STATUS_1REG		(LPU1_BLK_REG_ADDR + 0x010)
+#define LPU1_MBOX_STATUS_1REG		(LPU1_BLK_REG_ADDR + 0x014)
+#define LPU1_ERR_STATUS_REG		(LPU1_BLK_REG_ADDR + 0x018)
+#define LPU1_ERR_SET_REG		(LPU1_BLK_REG_ADDR + 0x020)
+
+/**
+ * PSS Block Register Address Offset from BAR0
+ * Range 0x18800 - 0x188DB
+ */
+#define PSS_BLK_REG_ADDR		0x00018800
+
+/**
+ * PSS Registers
+ * For details, see catapult_spec.pdf
+ * ERR_STATUS_REG : Indicates error in PSS module
+ * RAM_ERR_STATUS_REG : Indicates RAM module that detected error
+ */
+#define ERR_STATUS_SET			(PSS_BLK_REG_ADDR + 0x018)
+#define PSS_RAM_ERR_STATUS_REG		(PSS_BLK_REG_ADDR + 0x01C)
+
+/**
+ * PSS Semaphore Lock Registers, total 16
+ * First read when unlocked returns 0,
+ * and is set to 1, atomically.
+ * Subsequent reads returns 1.
+ * To clear set the value to 0.
+ * Range : 0x20 to 0x5c
+ */
+#define PSS_SEM_LOCK_REG(_num) 		\
+	(PSS_BLK_REG_ADDR + 0x020 + ((_num) << 2))
+
+/**
+ * PSS Semaphore Status Registers,
+ * corresponding to the lock registers above
+ */
+#define PSS_SEM_STATUS_REG(_num) 		\
+	(PSS_BLK_REG_ADDR + 0x060 + ((_num) << 2))
+
+/**
+ * Catapult CPQ Registers
+ * Defines for Mailbox Registers
+ * Used to send mailbox commands to firmware from
+ * host. The data part is written to the MBox
+ * memory, registers are used to indicate that
+ * a commnad is resident in memory.
+ *
+ * Note : LPU0<->LPU1 mailboxes are not listed here
+ */
+#define CPQ_BLK_REG_ADDR		0x00019000
+
+#define HOSTFN0_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x130)
+#define HOSTFN0_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x134)
+#define LPU0_HOSTFN0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x138)
+#define LPU1_HOSTFN0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x13C)
+
+#define HOSTFN1_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x140)
+#define HOSTFN1_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x144)
+#define LPU0_HOSTFN1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x148)
+#define LPU1_HOSTFN1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x14C)
+
+#define HOSTFN2_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x170)
+#define HOSTFN2_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x174)
+#define LPU0_HOSTFN2_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x178)
+#define LPU1_HOSTFN2_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x17C)
+
+#define HOSTFN3_LPU0_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x180)
+#define HOSTFN3_LPU1_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x184)
+#define LPU0_HOSTFN3_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x188)
+#define LPU1_HOSTFN3_MBOX1_CMD_STAT	(CPQ_BLK_REG_ADDR + 0x18C)
+
+/* Host Function Force Parity Error Registers */
+#define HOSTFN0_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x120)
+#define HOSTFN1_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x124)
+#define HOSTFN2_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x128)
+#define HOSTFN3_LPU_FORCE_PERR		(CPQ_BLK_REG_ADDR + 0x12C)
+
+/* LL Port[0|1] Halt Mask Registers */
+#define LL_HALT_MSK_P0			(CPQ_BLK_REG_ADDR + 0x1A0)
+#define LL_HALT_MSK_P1			(CPQ_BLK_REG_ADDR + 0x1B0)
+
+/* LL Port[0|1] Error Mask Registers */
+#define LL_ERR_MSK_P0			(CPQ_BLK_REG_ADDR + 0x1D0)
+#define LL_ERR_MSK_P1			(CPQ_BLK_REG_ADDR + 0x1D4)
+
+/* EMC FLI (Flash Controller) Block Register Address Offset from BAR0 */
+#define FLI_BLK_REG_ADDR		0x0001D000
+
+/* EMC FLI Registers */
+#define FLI_CMD_REG			(FLI_BLK_REG_ADDR + 0x000)
+#define FLI_ADDR_REG			(FLI_BLK_REG_ADDR + 0x004)
+#define FLI_CTL_REG			(FLI_BLK_REG_ADDR + 0x008)
+#define FLI_WRDATA_REG			(FLI_BLK_REG_ADDR + 0x00C)
+#define FLI_RDDATA_REG			(FLI_BLK_REG_ADDR + 0x010)
+#define FLI_DEV_STATUS_REG		(FLI_BLK_REG_ADDR + 0x014)
+#define FLI_SIG_WD_REG			(FLI_BLK_REG_ADDR + 0x018)
+
+/**
+ * RO register
+ * 31:16 -- Vendor Id
+ * 15:0  -- Device Id
+ */
+#define FLI_DEV_VENDOR_REG		(FLI_BLK_REG_ADDR + 0x01C)
+#define FLI_ERR_STATUS_REG		(FLI_BLK_REG_ADDR + 0x020)
+
+/**
+ * RAD (RxAdm) Block Register Address Offset from BAR0
+ * RAD0 Range : 0x20000 - 0x203FF
+ * RAD1 Range : 0x20400 - 0x207FF
+ */
+#define RAD0_BLK_REG_ADDR		0x00020000
+#define RAD1_BLK_REG_ADDR		0x00020400
+
+/* RAD0 Registers */
+#define RAD0_CTL_REG			(RAD0_BLK_REG_ADDR + 0x000)
+#define RAD0_PE_PARM_REG		(RAD0_BLK_REG_ADDR + 0x004)
+#define RAD0_BCN_REG			(RAD0_BLK_REG_ADDR + 0x008)
+
+/* Default function ID register */
+#define RAD0_DEFAULT_REG		(RAD0_BLK_REG_ADDR + 0x00C)
+
+/* Default promiscuous ID register */
+#define RAD0_PROMISC_REG		(RAD0_BLK_REG_ADDR + 0x010)
+
+#define RAD0_BCNQ_REG			(RAD0_BLK_REG_ADDR + 0x014)
+
+/*
+ * This register selects 1 of 8 PM Q's using
+ * VLAN pri, for non-BCN packets without a VLAN tag
+ */
+#define RAD0_DEFAULTQ_REG		(RAD0_BLK_REG_ADDR + 0x018)
+
+#define RAD0_ERR_STS			(RAD0_BLK_REG_ADDR + 0x01C)
+#define RAD0_SET_ERR_STS		(RAD0_BLK_REG_ADDR + 0x020)
+#define RAD0_ERR_INT_EN			(RAD0_BLK_REG_ADDR + 0x024)
+#define RAD0_FIRST_ERR			(RAD0_BLK_REG_ADDR + 0x028)
+#define RAD0_FORCE_ERR			(RAD0_BLK_REG_ADDR + 0x02C)
+
+#define RAD0_IF_RCVD			(RAD0_BLK_REG_ADDR + 0x030)
+#define RAD0_IF_RCVD_OCTETS_HIGH	(RAD0_BLK_REG_ADDR + 0x034)
+#define RAD0_IF_RCVD_OCTETS_LOW		(RAD0_BLK_REG_ADDR + 0x038)
+#define RAD0_IF_RCVD_VLAN		(RAD0_BLK_REG_ADDR + 0x03C)
+#define RAD0_IF_RCVD_UCAST		(RAD0_BLK_REG_ADDR + 0x040)
+#define RAD0_IF_RCVD_UCAST_OCTETS_HIGH	(RAD0_BLK_REG_ADDR + 0x044)
+#define RAD0_IF_RCVD_UCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x048)
+#define RAD0_IF_RCVD_UCAST_VLAN		(RAD0_BLK_REG_ADDR + 0x04C)
+#define RAD0_IF_RCVD_MCAST		(RAD0_BLK_REG_ADDR + 0x050)
+#define RAD0_IF_RCVD_MCAST_OCTETS_HIGH  (RAD0_BLK_REG_ADDR + 0x054)
+#define RAD0_IF_RCVD_MCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x058)
+#define RAD0_IF_RCVD_MCAST_VLAN		(RAD0_BLK_REG_ADDR + 0x05C)
+#define RAD0_IF_RCVD_BCAST		(RAD0_BLK_REG_ADDR + 0x060)
+#define RAD0_IF_RCVD_BCAST_OCTETS_HIGH  (RAD0_BLK_REG_ADDR + 0x064)
+#define RAD0_IF_RCVD_BCAST_OCTETS_LOW   (RAD0_BLK_REG_ADDR + 0x068)
+#define RAD0_IF_RCVD_BCAST_VLAN		(RAD0_BLK_REG_ADDR + 0x06C)
+#define RAD0_DROPPED_FRAMES		(RAD0_BLK_REG_ADDR + 0x070)
+
+#define RAD0_MAC_MAN_1H			(RAD0_BLK_REG_ADDR + 0x080)
+#define RAD0_MAC_MAN_1L			(RAD0_BLK_REG_ADDR + 0x084)
+#define RAD0_MAC_MAN_2H			(RAD0_BLK_REG_ADDR + 0x088)
+#define RAD0_MAC_MAN_2L			(RAD0_BLK_REG_ADDR + 0x08C)
+#define RAD0_MAC_MAN_3H			(RAD0_BLK_REG_ADDR + 0x090)
+#define RAD0_MAC_MAN_3L			(RAD0_BLK_REG_ADDR + 0x094)
+#define RAD0_MAC_MAN_4H			(RAD0_BLK_REG_ADDR + 0x098)
+#define RAD0_MAC_MAN_4L			(RAD0_BLK_REG_ADDR + 0x09C)
+
+#define RAD0_LAST4_IP			(RAD0_BLK_REG_ADDR + 0x100)
+
+/* RAD1 Registers */
+#define RAD1_CTL_REG			(RAD1_BLK_REG_ADDR + 0x000)
+#define RAD1_PE_PARM_REG		(RAD1_BLK_REG_ADDR + 0x004)
+#define RAD1_BCN_REG			(RAD1_BLK_REG_ADDR + 0x008)
+
+/* Default function ID register */
+#define RAD1_DEFAULT_REG		(RAD1_BLK_REG_ADDR + 0x00C)
+
+/* Promiscuous function ID register */
+#define RAD1_PROMISC_REG		(RAD1_BLK_REG_ADDR + 0x010)
+
+#define RAD1_BCNQ_REG			(RAD1_BLK_REG_ADDR + 0x014)
+
+/*
+ * This register selects 1 of 8 PM Q's using
+ * VLAN pri, for non-BCN packets without a VLAN tag
+ */
+#define RAD1_DEFAULTQ_REG		(RAD1_BLK_REG_ADDR + 0x018)
+
+#define RAD1_ERR_STS			(RAD1_BLK_REG_ADDR + 0x01C)
+#define RAD1_SET_ERR_STS		(RAD1_BLK_REG_ADDR + 0x020)
+#define RAD1_ERR_INT_EN			(RAD1_BLK_REG_ADDR + 0x024)
+
+/**
+ * TXA Block Register Address Offset from BAR0
+ * TXA0 Range : 0x21000 - 0x213FF
+ * TXA1 Range : 0x21400 - 0x217FF
+ */
+#define TXA0_BLK_REG_ADDR		0x00021000
+#define TXA1_BLK_REG_ADDR		0x00021400
+
+/* TXA Registers */
+#define TXA0_CTRL_REG			(TXA0_BLK_REG_ADDR + 0x000)
+#define TXA1_CTRL_REG			(TXA1_BLK_REG_ADDR + 0x000)
+
+/**
+ * TSO Sequence # Registers (RO)
+ * Total 8 (for 8 queues)
+ * Holds the last seq.# for TSO frames
+ * See catapult_spec.pdf for more details
+ */
+#define TXA0_TSO_TCP_SEQ_REG(_num)		\
+	(TXA0_BLK_REG_ADDR + 0x020 + ((_num) << 2))
+
+#define TXA1_TSO_TCP_SEQ_REG(_num)		\
+	(TXA1_BLK_REG_ADDR + 0x020 + ((_num) << 2))
+
+/**
+ * TSO IP ID # Registers (RO)
+ * Total 8 (for 8 queues)
+ * Holds the last IP ID for TSO frames
+ * See catapult_spec.pdf for more details
+ */
+#define TXA0_TSO_IP_INFO_REG(_num)		\
+	(TXA0_BLK_REG_ADDR + 0x040 + ((_num) << 2))
+
+#define TXA1_TSO_IP_INFO_REG(_num)		\
+	(TXA1_BLK_REG_ADDR + 0x040 + ((_num) << 2))
+
+/**
+ * RXA Block Register Address Offset from BAR0
+ * RXA0 Range : 0x21800 - 0x21BFF
+ * RXA1 Range : 0x21C00 - 0x21FFF
+ */
+#define RXA0_BLK_REG_ADDR		0x00021800
+#define RXA1_BLK_REG_ADDR		0x00021C00
+
+/* RXA Registers */
+#define RXA0_CTL_REG			(RXA0_BLK_REG_ADDR + 0x040)
+#define RXA1_CTL_REG			(RXA1_BLK_REG_ADDR + 0x040)
+
+/**
+ * PPLB Block Register Address Offset from BAR0
+ * PPLB0 Range : 0x22000 - 0x223FF
+ * PPLB1 Range : 0x22400 - 0x227FF
+ */
+#define PLB0_BLK_REG_ADDR		0x00022000
+#define PLB1_BLK_REG_ADDR		0x00022400
+
+/**
+ * PLB Registers
+ * Holds RL timer used time stamps in RLT tagged frames
+ */
+#define PLB0_ECM_TIMER_REG		(PLB0_BLK_REG_ADDR + 0x05C)
+#define PLB1_ECM_TIMER_REG		(PLB1_BLK_REG_ADDR + 0x05C)
+
+/* Controls the rate-limiter on each of the priority class */
+#define PLB0_RL_CTL			(PLB0_BLK_REG_ADDR + 0x060)
+#define PLB1_RL_CTL			(PLB1_BLK_REG_ADDR + 0x060)
+
+/**
+ * Max byte register, total 8, 0-7
+ * see catapult_spec.pdf for details
+ */
+#define PLB0_RL_MAX_BC(_num)			\
+	(PLB0_BLK_REG_ADDR + 0x064 + ((_num) << 2))
+#define PLB1_RL_MAX_BC(_num)			\
+	(PLB1_BLK_REG_ADDR + 0x064 + ((_num) << 2))
+
+/**
+ * RL Time Unit Register for priority 0-7
+ * 4 bits per priority
+ * (2^rl_unit)*1us is the actual time period
+ */
+#define PLB0_RL_TU_PRIO			(PLB0_BLK_REG_ADDR + 0x084)
+#define PLB1_RL_TU_PRIO			(PLB1_BLK_REG_ADDR + 0x084)
+
+/**
+ * RL byte count register,
+ * bytes transmitted in (rl_unit*1)us time period
+ * 1 per priority, 8 in all, 0-7.
+ */
+#define PLB0_RL_BYTE_CNT(_num)			\
+	(PLB0_BLK_REG_ADDR + 0x088 + ((_num) << 2))
+#define PLB1_RL_BYTE_CNT(_num)			\
+	(PLB1_BLK_REG_ADDR + 0x088 + ((_num) << 2))
+
+/**
+ * RL Min factor register
+ * 2 bits per priority,
+ * 4 factors possible: 1, 0.5, 0.25, 0
+ * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
+ */
+#define PLB0_RL_MIN_REG			(PLB0_BLK_REG_ADDR + 0x0A8)
+#define PLB1_RL_MIN_REG			(PLB1_BLK_REG_ADDR + 0x0A8)
+
+/**
+ * RL Max factor register
+ * 2 bits per priority,
+ * 4 factors possible: 1, 0.5, 0.25, 0
+ * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
+ */
+#define PLB0_RL_MAX_REG			(PLB0_BLK_REG_ADDR + 0x0AC)
+#define PLB1_RL_MAX_REG			(PLB1_BLK_REG_ADDR + 0x0AC)
+
+/* MAC SERDES Address Paging register */
+#define PLB0_EMS_ADD_REG		(PLB0_BLK_REG_ADDR + 0xD0)
+#define PLB1_EMS_ADD_REG		(PLB1_BLK_REG_ADDR + 0xD0)
+
+/* LL EMS Registers */
+#define LL_EMS0_BLK_REG_ADDR		0x00026800
+#define LL_EMS1_BLK_REG_ADDR		0x00026C00
+
+/**
+ * BPC Block Register Address Offset from BAR0
+ * BPC0 Range : 0x23000 - 0x233FF
+ * BPC1 Range : 0x23400 - 0x237FF
+ */
+#define BPC0_BLK_REG_ADDR		0x00023000
+#define BPC1_BLK_REG_ADDR		0x00023400
+
+/**
+ * PMM Block Register Address Offset from BAR0
+ * PMM0 Range : 0x23800 - 0x23BFF
+ * PMM1 Range : 0x23C00 - 0x23FFF
+ */
+#define PMM0_BLK_REG_ADDR		0x00023800
+#define PMM1_BLK_REG_ADDR		0x00023C00
+
+/**
+ * HQM Block Register Address Offset from BAR0
+ * HQM0 Range : 0x24000 - 0x243FF
+ * HQM1 Range : 0x24400 - 0x247FF
+ */
+#define HQM0_BLK_REG_ADDR		0x00024000
+#define HQM1_BLK_REG_ADDR		0x00024400
+
+/**
+ * HQM Control Register
+ * Controls some aspects of IB
+ * See catapult_spec.pdf for details
+ */
+#define HQM0_CTL_REG			(HQM0_BLK_REG_ADDR + 0x000)
+#define HQM1_CTL_REG			(HQM1_BLK_REG_ADDR + 0x000)
+
+/**
+ * HQM Stop Q Semaphore Registers.
+ * Only one Queue resource can be stopped at
+ * any given time. This register controls access
+ * to the single stop Q resource.
+ * See catapult_spec.pdf for details
+ */
+#define HQM0_RXQ_STOP_SEM		(HQM0_BLK_REG_ADDR + 0x028)
+#define HQM0_TXQ_STOP_SEM		(HQM0_BLK_REG_ADDR + 0x02C)
+#define HQM1_RXQ_STOP_SEM		(HQM1_BLK_REG_ADDR + 0x028)
+#define HQM1_TXQ_STOP_SEM		(HQM1_BLK_REG_ADDR + 0x02C)
+
+/**
+ * LUT Block Register Address Offset from BAR0
+ * LUT0 Range : 0x25800 - 0x25BFF
+ * LUT1 Range : 0x25C00 - 0x25FFF
+ */
+#define LUT0_BLK_REG_ADDR		0x00025800
+#define LUT1_BLK_REG_ADDR		0x00025C00
+
+/**
+ * LUT Registers
+ * See catapult_spec.pdf for details
+ */
+#define LUT0_ERR_STS			(LUT0_BLK_REG_ADDR + 0x000)
+#define LUT1_ERR_STS			(LUT1_BLK_REG_ADDR + 0x000)
+#define LUT0_SET_ERR_STS		(LUT0_BLK_REG_ADDR + 0x004)
+#define LUT1_SET_ERR_STS		(LUT1_BLK_REG_ADDR + 0x004)
+
+/**
+ * TRC (Debug/Trace) Register Offset from BAR0
+ * Range : 0x26000 -- 0x263FFF
+ */
+#define TRC_BLK_REG_ADDR		0x00026000
+
+/**
+ * TRC Registers
+ * See catapult_spec.pdf for details of each
+ */
+#define TRC_CTL_REG			(TRC_BLK_REG_ADDR + 0x000)
+#define TRC_MODS_REG			(TRC_BLK_REG_ADDR + 0x004)
+#define TRC_TRGC_REG			(TRC_BLK_REG_ADDR + 0x008)
+#define TRC_CNT1_REG			(TRC_BLK_REG_ADDR + 0x010)
+#define TRC_CNT2_REG			(TRC_BLK_REG_ADDR + 0x014)
+#define TRC_NXTS_REG			(TRC_BLK_REG_ADDR + 0x018)
+#define TRC_DIRR_REG			(TRC_BLK_REG_ADDR + 0x01C)
+
+/**
+ * TRC Trigger match filters, total 10
+ * Determines the trigger condition
+ */
+#define TRC_TRGM_REG(_num)		\
+	(TRC_BLK_REG_ADDR + 0x040 + ((_num) << 2))
+
+/**
+ * TRC Next State filters, total 10
+ * Determines the next state conditions
+ */
+#define TRC_NXTM_REG(_num)		\
+	(TRC_BLK_REG_ADDR + 0x080 + ((_num) << 2))
+
+/**
+ * TRC Store Match filters, total 10
+ * Determines the store conditions
+ */
+#define TRC_STRM_REG(_num)		\
+	(TRC_BLK_REG_ADDR + 0x0C0 + ((_num) << 2))
+
+/* DOORBELLS ACCESS */
+
+/**
+ * Catapult doorbells
+ * Each doorbell-queue set has
+ * 1 RxQ, 1 TxQ, 2 IBs in that order
+ * Size of each entry in 32 bytes, even though only 1 word
+ * is used. For Non-VM case each doorbell-q set is
+ * separated by 128 bytes, for VM case it is separated
+ * by 4K bytes
+ * Non VM case Range : 0x38000 - 0x39FFF
+ * VM case Range     : 0x100000 - 0x11FFFF
+ * The range applies to both HQMs
+ */
+#define HQM_DOORBELL_BLK_BASE_ADDR	0x00038000
+#define HQM_DOORBELL_VM_BLK_BASE_ADDR	0x00100000
+
+/* MEMORY ACCESS */
+
+/**
+ * Catapult H/W Block Memory Access Address
+ * To the host a memory space of 32K (page) is visible
+ * at a time. The address range is from 0x08000 to 0x0FFFF
+ */
+#define HW_BLK_HOST_MEM_ADDR		0x08000
+
+/**
+ * Catapult LUT Memory Access Page Numbers
+ * Range : LUT0 0xa0-0xa1
+ *         LUT1 0xa2-0xa3
+ */
+#define LUT0_MEM_BLK_BASE_PG_NUM	0x000000A0
+#define LUT1_MEM_BLK_BASE_PG_NUM	0x000000A2
+
+/**
+ * Catapult RxFn Database Memory Block Base Offset
+ *
+ * The Rx function database exists in LUT block.
+ * In PCIe space this is accessible as a 256x32
+ * bit block. Each entry in this database is 4
+ * (4 byte) words. Max. entries is 64.
+ * Address of an entry corresponding to a function
+ * = base_addr + (function_no. * 16)
+ */
+#define RX_FNDB_RAM_BASE_OFFSET		0x0000B400
+
+/**
+ * Catapult TxFn Database Memory Block Base Offset Address
+ *
+ * The Tx function database exists in LUT block.
+ * In PCIe space this is accessible as a 64x32
+ * bit block. Each entry in this database is 1
+ * (4 byte) word. Max. entries is 64.
+ * Address of an entry corresponding to a function
+ * = base_addr + (function_no. * 4)
+ */
+#define TX_FNDB_RAM_BASE_OFFSET		0x0000B800
+
+/**
+ * Catapult Unicast CAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Shared by both the LL & FCoE driver.
+ * Size is 256x48 bits; mapped to PCIe space
+ * 512x32 bit blocks. For each address, bits
+ * are written in the order : [47:32] and then
+ * [31:0].
+ */
+#define UCAST_CAM_BASE_OFFSET		0x0000A800
+
+/**
+ * Catapult Unicast RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Shared by both the LL & FCoE driver.
+ * Size is 256x9 bits.
+ */
+#define UCAST_RAM_BASE_OFFSET		0x0000B000
+
+/**
+ * Catapult Mulicast CAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Shared by both the LL & FCoE driver.
+ * Size is 256x48 bits; mapped to PCIe space
+ * 512x32 bit blocks. For each address, bits
+ * are written in the order : [47:32] and then
+ * [31:0].
+ */
+#define MCAST_CAM_BASE_OFFSET		0x0000A000
+
+/**
+ * Catapult VLAN RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Size is 4096x66 bits; mapped to PCIe space as
+ * 8192x32 bit blocks.
+ * All the 4K entries are within the address range
+ * 0x0000 to 0x8000, so in the first LUT page.
+ */
+#define VLAN_RAM_BASE_OFFSET		0x00000000
+
+/**
+ * Catapult Tx Stats RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Size is 1024x33 bits;
+ * Each Tx function has 64 bytes of space
+ */
+#define TX_STATS_RAM_BASE_OFFSET	0x00009000
+
+/**
+ * Catapult Rx Stats RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Size is 1024x33 bits;
+ * Each Rx function has 64 bytes of space
+ */
+#define RX_STATS_RAM_BASE_OFFSET	0x00008000
+
+/* Catapult RXA Memory Access Page Numbers */
+#define RXA0_MEM_BLK_BASE_PG_NUM	0x0000008C
+#define RXA1_MEM_BLK_BASE_PG_NUM	0x0000008D
+
+/**
+ * Catapult Multicast Vector Table Base Offset Address
+ *
+ * Exists in RxA memory space.
+ * Organized as 512x65 bit block.
+ * However for each entry 16 bytes allocated (power of 2)
+ * Total size 512*16 bytes.
+ * There are two logical divisions, 256 entries each :
+ * a) Entries 0x00 to 0xff (256) -- Approx. MVT
+ *    Offset 0x000 to 0xFFF
+ * b) Entries 0x100 to 0x1ff (256) -- Exact MVT
+ *    Offsets 0x1000 to 0x1FFF
+ */
+#define MCAST_APPROX_MVT_BASE_OFFSET	0x00000000
+#define MCAST_EXACT_MVT_BASE_OFFSET	0x00001000
+
+/**
+ * Catapult RxQ Translate Table (RIT) Base Offset Address
+ *
+ * Exists in RxA memory space
+ * Total no. of entries 64
+ * Each entry is 1 (4 byte) word.
+ * 31:12 -- Reserved
+ * 11:0  -- Two 6 bit RxQ Ids
+ */
+#define FUNCTION_TO_RXQ_TRANSLATE	0x00002000
+
+/* Catapult RxAdm (RAD) Memory Access Page Numbers */
+#define RAD0_MEM_BLK_BASE_PG_NUM	0x00000086
+#define RAD1_MEM_BLK_BASE_PG_NUM	0x00000087
+
+/**
+ * Catapult RSS Table Base Offset Address
+ *
+ * Exists in RAD memory space.
+ * Each entry is 352 bits, but alligned on
+ * 64 byte (512 bit) boundary. Accessed
+ * 4 byte words, the whole entry can be
+ * broken into 11 word accesses.
+ */
+#define RSS_TABLE_BASE_OFFSET		0x00000800
+
+/**
+ * Catapult CPQ Block Page Number
+ * This value is written to the page number registers
+ * to access the memory associated with the mailboxes.
+ */
+#define CPQ_BLK_PG_NUM			0x00000005
+
+/**
+ * Clarification :
+ * LL functions are 2 & 3; can HostFn0/HostFn1
+ * <-> LPU0/LPU1 memories be used ?
+ */
+/**
+ * Catapult HostFn0/HostFn1 to LPU0/LPU1 Mbox memory
+ * Per catapult_spec.pdf, the offset of the mbox
+ * memory is in the register space at an offset of 0x200
+ */
+#define CPQ_BLK_REG_MBOX_ADDR		(CPQ_BLK_REG_ADDR + 0x200)
+
+#define HOSTFN_LPU_MBOX			(CPQ_BLK_REG_MBOX_ADDR + 0x000)
+
+/* Catapult LPU0/LPU1 to HostFn0/HostFn1 Mbox memory */
+#define LPU_HOSTFN_MBOX			(CPQ_BLK_REG_MBOX_ADDR + 0x080)
+
+/**
+ * Catapult HQM Block Page Number
+ * This is written to the page number register for
+ * the appropriate function to access the memory
+ * associated with HQM
+ */
+#define HQM0_BLK_PG_NUM			0x00000096
+#define HQM1_BLK_PG_NUM			0x00000097
+
+/**
+ * Note that TxQ and RxQ entries are interlaced
+ * the HQM memory, i.e RXQ0, TXQ0, RXQ1, TXQ1.. etc.
+ */
+
+#define HQM_RXTX_Q_RAM_BASE_OFFSET	0x00004000
+
+/**
+ * CQ Memory
+ * Exists in HQM Memory space
+ * Each entry is 16 (4 byte) words of which
+ * only 12 words are used for configuration
+ * Total 64 entries per HQM memory space
+ */
+#define HQM_CQ_RAM_BASE_OFFSET		0x00006000
+
+/**
+ * Interrupt Block (IB) Memory
+ * Exists in HQM Memory space
+ * Each entry is 8 (4 byte) words of which
+ * only 5 words are used for configuration
+ * Total 128 entries per HQM memory space
+ */
+#define HQM_IB_RAM_BASE_OFFSET		0x00001000
+
+/**
+ * Index Table (IT) Memory
+ * Exists in HQM Memory space
+ * Each entry is 1 (4 byte) word which
+ * is used for configuration
+ * Total 128 entries per HQM memory space
+ */
+#define HQM_INDX_TBL_RAM_BASE_OFFSET	0x00002000
+
+/**
+ * PSS Block Memory Page Number
+ * This is written to the appropriate page number
+ * register to access the CPU memory.
+ * Also known as the PSS secondary memory (SMEM).
+ * Range : 0x180 to 0x1CF
+ * See catapult_spec.pdf for details
+ */
+#define PSS_BLK_PG_NUM			0x00000180
+
+/**
+ * Offsets of different instances of PSS SMEM
+ * 2.5M of continuous 1T memory space : 2 blocks
+ * of 1M each (32 pages each, page=32KB) and 4 smaller
+ * blocks of 128K each (4 pages each, page=32KB)
+ * PSS_LMEM_INST0 is used for firmware download
+ */
+#define PSS_LMEM_INST0			0x00000000
+#define PSS_LMEM_INST1			0x00100000
+#define PSS_LMEM_INST2			0x00200000
+#define PSS_LMEM_INST3			0x00220000
+#define PSS_LMEM_INST4			0x00240000
+#define PSS_LMEM_INST5			0x00260000
+
+#define BNA_PCI_REG_CT_ADDRSZ		(0x40000)
+
+#define BNA_GET_PAGE_NUM(_base_page, _offset)   \
+	((_base_page) + ((_offset) >> 15))
+
+#define BNA_GET_PAGE_OFFSET(_offset)    \
+	((_offset) & 0x7fff)
+
+#define BNA_GET_MEM_BASE_ADDR(_bar0, _base_offset)	\
+	((_bar0) + HW_BLK_HOST_MEM_ADDR		\
+	  + BNA_GET_PAGE_OFFSET((_base_offset)))
+
+#define BNA_GET_VLAN_MEM_ENTRY_ADDR(_bar0, _fn_id, _vlan_id)\
+	(_bar0 + (HW_BLK_HOST_MEM_ADDR)  \
+	+ (BNA_GET_PAGE_OFFSET(VLAN_RAM_BASE_OFFSET))	\
+	+ (((_fn_id) & 0x3f) << 9)	  \
+	+ (((_vlan_id) & 0xfe0) >> 3))
+
+/**
+ *
+ *  Interrupt related bits, flags and macros
+ *
+ */
+
+#define __LPU02HOST_MBOX0_STATUS_BITS 0x00100000
+#define __LPU12HOST_MBOX0_STATUS_BITS 0x00200000
+#define __LPU02HOST_MBOX1_STATUS_BITS 0x00400000
+#define __LPU12HOST_MBOX1_STATUS_BITS 0x00800000
+
+#define __LPU02HOST_MBOX0_MASK_BITS	0x00100000
+#define __LPU12HOST_MBOX0_MASK_BITS	0x00200000
+#define __LPU02HOST_MBOX1_MASK_BITS	0x00400000
+#define __LPU12HOST_MBOX1_MASK_BITS	0x00800000
+
+#define __LPU2HOST_MBOX_MASK_BITS			 \
+	(__LPU02HOST_MBOX0_MASK_BITS | __LPU02HOST_MBOX1_MASK_BITS |	\
+	  __LPU12HOST_MBOX0_MASK_BITS | __LPU12HOST_MBOX1_MASK_BITS)
+
+#define __LPU2HOST_IB_STATUS_BITS	0x0000ffff
+
+#define BNA_IS_LPU0_MBOX_INTR(_intr_status) \
+	((_intr_status) & (__LPU02HOST_MBOX0_STATUS_BITS | \
+			__LPU02HOST_MBOX1_STATUS_BITS))
+
+#define BNA_IS_LPU1_MBOX_INTR(_intr_status) \
+	((_intr_status) & (__LPU12HOST_MBOX0_STATUS_BITS | \
+		__LPU12HOST_MBOX1_STATUS_BITS))
+
+#define BNA_IS_MBOX_INTR(_intr_status)		\
+	((_intr_status) &  			\
+	(__LPU02HOST_MBOX0_STATUS_BITS |	\
+	 __LPU02HOST_MBOX1_STATUS_BITS |	\
+	 __LPU12HOST_MBOX0_STATUS_BITS |	\
+	 __LPU12HOST_MBOX1_STATUS_BITS))
+
+#define __EMC_ERROR_STATUS_BITS		0x00010000
+#define __LPU0_ERROR_STATUS_BITS	0x00020000
+#define __LPU1_ERROR_STATUS_BITS	0x00040000
+#define __PSS_ERROR_STATUS_BITS		0x00080000
+
+#define __HALT_STATUS_BITS		0x01000000
+
+#define __EMC_ERROR_MASK_BITS		0x00010000
+#define __LPU0_ERROR_MASK_BITS		0x00020000
+#define __LPU1_ERROR_MASK_BITS		0x00040000
+#define __PSS_ERROR_MASK_BITS		0x00080000
+
+#define __HALT_MASK_BITS		0x01000000
+
+#define __ERROR_MASK_BITS		\
+	(__EMC_ERROR_MASK_BITS | __LPU0_ERROR_MASK_BITS | \
+	  __LPU1_ERROR_MASK_BITS | __PSS_ERROR_MASK_BITS | \
+	  __HALT_MASK_BITS)
+
+#define BNA_IS_ERR_INTR(_intr_status)	\
+	((_intr_status) &  		\
+	(__EMC_ERROR_STATUS_BITS |  	\
+	 __LPU0_ERROR_STATUS_BITS | 	\
+	 __LPU1_ERROR_STATUS_BITS | 	\
+	 __PSS_ERROR_STATUS_BITS  | 	\
+	 __HALT_STATUS_BITS))
+
+#define BNA_IS_MBOX_ERR_INTR(_intr_status)	\
+	(BNA_IS_MBOX_INTR((_intr_status)) |	\
+	 BNA_IS_ERR_INTR((_intr_status)))
+
+#define BNA_IS_INTX_DATA_INTR(_intr_status)	\
+	((_intr_status) & __LPU2HOST_IB_STATUS_BITS)
+
+#define BNA_INTR_STATUS_MBOX_CLR(_intr_status)			\
+do {								\
+	(_intr_status) &= ~(__LPU02HOST_MBOX0_STATUS_BITS |	\
+			__LPU02HOST_MBOX1_STATUS_BITS | 	\
+			__LPU12HOST_MBOX0_STATUS_BITS | 	\
+			__LPU12HOST_MBOX1_STATUS_BITS); 	\
+} while (0)
+
+#define BNA_INTR_STATUS_ERR_CLR(_intr_status)		\
+do {							\
+	(_intr_status) &= ~(__EMC_ERROR_STATUS_BITS |	\
+		__LPU0_ERROR_STATUS_BITS |		\
+		__LPU1_ERROR_STATUS_BITS |		\
+		__PSS_ERROR_STATUS_BITS  |		\
+		__HALT_STATUS_BITS);			\
+} while (0)
+
+#define bna_intx_disable(_bna, _cur_mask)		\
+{							\
+	(_cur_mask) = readl((_bna)->regs.fn_int_mask);\
+	writel(0xffffffff, (_bna)->regs.fn_int_mask);\
+}
+
+#define bna_intx_enable(bna, new_mask) 			\
+	writel((new_mask), (bna)->regs.fn_int_mask)
+
+#define bna_mbox_intr_disable(bna)		\
+	writel((readl((bna)->regs.fn_int_mask) | \
+	     (__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \
+	     (bna)->regs.fn_int_mask)
+
+#define bna_mbox_intr_enable(bna)		\
+	writel((readl((bna)->regs.fn_int_mask) & \
+	     ~(__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \
+	     (bna)->regs.fn_int_mask)
+
+#define bna_intr_status_get(_bna, _status)				\
+{									\
+	(_status) = readl((_bna)->regs.fn_int_status);		\
+	if ((_status)) {						\
+		writel((_status) & ~(__LPU02HOST_MBOX0_STATUS_BITS |\
+					  __LPU02HOST_MBOX1_STATUS_BITS |\
+					  __LPU12HOST_MBOX0_STATUS_BITS |\
+					  __LPU12HOST_MBOX1_STATUS_BITS), \
+			      (_bna)->regs.fn_int_status);\
+	}								\
+}
+
+#define bna_intr_status_get_no_clr(_bna, _status)		\
+	(_status) = readl((_bna)->regs.fn_int_status)
+
+#define bna_intr_mask_get(bna, mask)		\
+	(*mask) = readl((bna)->regs.fn_int_mask)
+
+#define bna_intr_ack(bna, intr_bmap)		\
+	writel((intr_bmap), (bna)->regs.fn_int_status)
+
+#define bna_ib_intx_disable(bna, ib_id)		\
+	writel(readl((bna)->regs.fn_int_mask) | \
+	    (1 << (ib_id)), \
+	    (bna)->regs.fn_int_mask)
+
+#define bna_ib_intx_enable(bna, ib_id)		\
+	writel(readl((bna)->regs.fn_int_mask) & \
+	    ~(1 << (ib_id)), \
+	    (bna)->regs.fn_int_mask)
+
+#define bna_mbox_msix_idx_set(_device) \
+do {\
+	writel(((_device)->vector & 0x000001FF), \
+		(_device)->bna->pcidev.pci_bar_kva + \
+		reg_offset[(_device)->bna->pcidev.pci_func].msix_idx);\
+} while (0)
+
+/**
+ *
+ * TxQ, RxQ, CQ related bits, offsets, macros
+ *
+ */
+
+#define	BNA_Q_IDLE_STATE	0x00008001
+
+#define BNA_GET_DOORBELL_BASE_ADDR(_bar0)	\
+	((_bar0) + HQM_DOORBELL_BLK_BASE_ADDR)
+
+#define BNA_GET_DOORBELL_ENTRY_OFFSET(_entry)		\
+	((HQM_DOORBELL_BLK_BASE_ADDR)		\
+	+ (_entry << 7))
+
+#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
+		(0x80000000 | ((_timeout) << 16) | (_events))
+
+#define BNA_DOORBELL_IB_INT_DISABLE		(0x40000000)
+
+/* TxQ Entry Opcodes */
+#define BNA_TXQ_WI_SEND 		(0x402)	/* Single Frame Transmission */
+#define BNA_TXQ_WI_SEND_LSO 		(0x403)	/* Multi-Frame Transmission */
+#define BNA_TXQ_WI_EXTENSION		(0x104)	/* Extension WI */
+
+/* TxQ Entry Control Flags */
+#define BNA_TXQ_WI_CF_FCOE_CRC  	(1 << 8)
+#define BNA_TXQ_WI_CF_IPID_MODE 	(1 << 5)
+#define BNA_TXQ_WI_CF_INS_PRIO  	(1 << 4)
+#define BNA_TXQ_WI_CF_INS_VLAN  	(1 << 3)
+#define BNA_TXQ_WI_CF_UDP_CKSUM 	(1 << 2)
+#define BNA_TXQ_WI_CF_TCP_CKSUM 	(1 << 1)
+#define BNA_TXQ_WI_CF_IP_CKSUM  	(1 << 0)
+
+#define BNA_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \
+		(((_hdr_size) << 10) | ((_offset) & 0x3FF))
+
+/*
+ * Completion Q defines
+ */
+/* CQ Entry Flags */
+#define	BNA_CQ_EF_MAC_ERROR 	(1 <<  0)
+#define	BNA_CQ_EF_FCS_ERROR 	(1 <<  1)
+#define	BNA_CQ_EF_TOO_LONG  	(1 <<  2)
+#define	BNA_CQ_EF_FC_CRC_OK 	(1 <<  3)
+
+#define	BNA_CQ_EF_RSVD1 	(1 <<  4)
+#define	BNA_CQ_EF_L4_CKSUM_OK	(1 <<  5)
+#define	BNA_CQ_EF_L3_CKSUM_OK	(1 <<  6)
+#define	BNA_CQ_EF_HDS_HEADER	(1 <<  7)
+
+#define	BNA_CQ_EF_UDP   	(1 <<  8)
+#define	BNA_CQ_EF_TCP   	(1 <<  9)
+#define	BNA_CQ_EF_IP_OPTIONS	(1 << 10)
+#define	BNA_CQ_EF_IPV6  	(1 << 11)
+
+#define	BNA_CQ_EF_IPV4  	(1 << 12)
+#define	BNA_CQ_EF_VLAN  	(1 << 13)
+#define	BNA_CQ_EF_RSS   	(1 << 14)
+#define	BNA_CQ_EF_RSVD2 	(1 << 15)
+
+#define	BNA_CQ_EF_MCAST_MATCH   (1 << 16)
+#define	BNA_CQ_EF_MCAST 	(1 << 17)
+#define BNA_CQ_EF_BCAST 	(1 << 18)
+#define	BNA_CQ_EF_REMOTE 	(1 << 19)
+
+#define	BNA_CQ_EF_LOCAL		(1 << 20)
+
+/**
+ *
+ * Data structures
+ *
+ */
+
+enum txf_flags {
+	BFI_TXF_CF_ENABLE		= 1 << 0,
+	BFI_TXF_CF_VLAN_FILTER		= 1 << 8,
+	BFI_TXF_CF_VLAN_ADMIT		= 1 << 9,
+	BFI_TXF_CF_VLAN_INSERT		= 1 << 10,
+	BFI_TXF_CF_RSVD1		= 1 << 11,
+	BFI_TXF_CF_MAC_SA_CHECK		= 1 << 12,
+	BFI_TXF_CF_VLAN_WI_BASED	= 1 << 13,
+	BFI_TXF_CF_VSWITCH_MCAST	= 1 << 14,
+	BFI_TXF_CF_VSWITCH_UCAST	= 1 << 15,
+	BFI_TXF_CF_RSVD2		= 0x7F << 1
+};
+
+enum ib_flags {
+	BFI_IB_CF_MASTER_ENABLE		= (1 << 0),
+	BFI_IB_CF_MSIX_MODE		= (1 << 1),
+	BFI_IB_CF_COALESCING_MODE	= (1 << 2),
+	BFI_IB_CF_INTER_PKT_ENABLE	= (1 << 3),
+	BFI_IB_CF_INT_ENABLE		= (1 << 4),
+	BFI_IB_CF_INTER_PKT_DMA		= (1 << 5),
+	BFI_IB_CF_ACK_PENDING		= (1 << 6),
+	BFI_IB_CF_RESERVED1		= (1 << 7)
+};
+
+enum rss_hash_type {
+	BFI_RSS_T_V4_TCP    		= (1 << 11),
+	BFI_RSS_T_V4_IP     		= (1 << 10),
+	BFI_RSS_T_V6_TCP    		= (1 <<  9),
+	BFI_RSS_T_V6_IP     		= (1 <<  8)
+};
+enum hds_header_type {
+	BNA_HDS_T_V4_TCP	= (1 << 11),
+	BNA_HDS_T_V4_UDP	= (1 << 10),
+	BNA_HDS_T_V6_TCP	= (1 << 9),
+	BNA_HDS_T_V6_UDP	= (1 << 8),
+	BNA_HDS_FORCED		= (1 << 7),
+};
+enum rxf_flags {
+	BNA_RXF_CF_SM_LG_RXQ			= (1 << 15),
+	BNA_RXF_CF_DEFAULT_VLAN			= (1 << 14),
+	BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE	= (1 << 13),
+	BNA_RXF_CF_VLAN_STRIP			= (1 << 12),
+	BNA_RXF_CF_RSS_ENABLE			= (1 <<  8)
+};
+struct bna_chip_regs_offset {
+	u32 page_addr;
+	u32 fn_int_status;
+	u32 fn_int_mask;
+	u32 msix_idx;
+};
+
+struct bna_chip_regs {
+	void __iomem *page_addr;
+	void __iomem *fn_int_status;
+	void __iomem *fn_int_mask;
+};
+
+struct bna_txq_mem {
+	u32 pg_tbl_addr_lo;
+	u32 pg_tbl_addr_hi;
+	u32 cur_q_entry_lo;
+	u32 cur_q_entry_hi;
+	u32 reserved1;
+	u32 reserved2;
+	u32 pg_cnt_n_prd_ptr;	/* 31:16->total page count */
+					/* 15:0 ->producer pointer (index?) */
+	u32 entry_n_pg_size; 	/* 31:16->entry size */
+					/* 15:0 ->page size */
+	u32 int_blk_n_cns_ptr;	/* 31:24->Int Blk Id;  */
+					/* 23:16->Int Blk Offset */
+					/* 15:0 ->consumer pointer(index?) */
+	u32 cns_ptr2_n_q_state;	/* 31:16->cons. ptr 2; 15:0-> Q state */
+	u32 nxt_qid_n_fid_n_pri;	/* 17:10->next */
+					/* QId;9:3->FID;2:0->Priority */
+	u32 wvc_n_cquota_n_rquota; /* 31:24->WI Vector Count; */
+					/* 23:12->Cfg Quota; */
+					/* 11:0 ->Run Quota */
+	u32 reserved3[4];
+};
+
+struct bna_rxq_mem {
+	u32 pg_tbl_addr_lo;
+	u32 pg_tbl_addr_hi;
+	u32 cur_q_entry_lo;
+	u32 cur_q_entry_hi;
+	u32 reserved1;
+	u32 reserved2;
+	u32 pg_cnt_n_prd_ptr;	/* 31:16->total page count */
+					/* 15:0 ->producer pointer (index?) */
+	u32 entry_n_pg_size;	/* 31:16->entry size */
+					/* 15:0 ->page size */
+	u32 sg_n_cq_n_cns_ptr;	/* 31:28->reserved; 27:24->sg count */
+					/* 23:16->CQ; */
+					/* 15:0->consumer pointer(index?) */
+	u32 buf_sz_n_q_state; 	/* 31:16->buffer size; 15:0-> Q state */
+	u32 next_qid;		/* 17:10->next QId */
+	u32 reserved3;
+	u32 reserved4[4];
+};
+
+struct bna_rxtx_q_mem {
+	struct bna_rxq_mem rxq;
+	struct bna_txq_mem txq;
+};
+
+struct bna_cq_mem {
+	u32 pg_tbl_addr_lo;
+	u32 pg_tbl_addr_hi;
+	u32 cur_q_entry_lo;
+	u32 cur_q_entry_hi;
+
+	u32 reserved1;
+	u32 reserved2;
+	u32 pg_cnt_n_prd_ptr;	/* 31:16->total page count */
+					/* 15:0 ->producer pointer (index?) */
+	u32 entry_n_pg_size;	/* 31:16->entry size */
+					/* 15:0 ->page size */
+	u32 int_blk_n_cns_ptr;	/* 31:24->Int Blk Id; */
+					/* 23:16->Int Blk Offset */
+					/* 15:0 ->consumer pointer(index?) */
+	u32 q_state;		/* 31:16->reserved; 15:0-> Q state */
+	u32 reserved3[2];
+	u32 reserved4[4];
+};
+
+struct bna_ib_blk_mem {
+	u32 host_addr_lo;
+	u32 host_addr_hi;
+	u32 clsc_n_ctrl_n_msix;	/* 31:24->coalescing; */
+					/* 23:16->coalescing cfg; */
+					/* 15:8 ->control; */
+					/* 7:0 ->msix; */
+	u32 ipkt_n_ent_n_idxof;
+	u32 ipkt_cnt_cfg_n_unacked;
+
+	u32 reserved[3];
+};
+
+struct bna_idx_tbl_mem {
+	u32 idx;	  /* !< 31:16->res;15:0->idx; */
+};
+
+struct bna_doorbell_qset {
+	u32 rxq[0x20 >> 2];
+	u32 txq[0x20 >> 2];
+	u32 ib0[0x20 >> 2];
+	u32 ib1[0x20 >> 2];
+};
+
+struct bna_rx_fndb_ram {
+	u32 rss_prop;
+	u32 size_routing_props;
+	u32 rit_hds_mcastq;
+	u32 control_flags;
+};
+
+struct bna_tx_fndb_ram {
+	u32 vlan_n_ctrl_flags;
+};
+
+/**
+ * @brief
+ *  Structure which maps to RxFn Indirection Table (RIT)
+ *  Size : 1 word
+ *  See catapult_spec.pdf, RxA for details
+ */
+struct bna_rit_mem {
+	u32 rxq_ids;	/* !< 31:12->res;11:0->two 6 bit RxQ Ids */
+};
+
+/**
+ * @brief
+ *  Structure which maps to RSS Table entry
+ *  Size : 16 words
+ *  See catapult_spec.pdf, RAD for details
+ */
+struct bna_rss_mem {
+	/*
+	 * 31:12-> res
+	 * 11:8 -> protocol type
+	 *  7:0 -> hash index
+	 */
+	u32 type_n_hash;
+	u32 hash_key[10];  /* !< 40 byte Toeplitz hash key */
+	u32 reserved[5];
+};
+
+/* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */
+struct bna_dma_addr {
+	u32		msb;
+	u32		lsb;
+};
+
+struct bna_txq_wi_vector {
+	u16 		reserved;
+	u16 		length;		/* Only 14 LSB are valid */
+	struct bna_dma_addr host_addr; /* Tx-Buf DMA addr */
+};
+
+typedef u16 bna_txq_wi_opcode_t;
+
+typedef u16 bna_txq_wi_ctrl_flag_t;
+
+/**
+ *  TxQ Entry Structure
+ *
+ *  BEWARE:  Load values into this structure with correct endianess.
+ */
+struct bna_txq_entry {
+	union {
+		struct {
+			u8 reserved;
+			u8 num_vectors;	/* number of vectors present */
+			bna_txq_wi_opcode_t opcode; /* Either */
+						    /* BNA_TXQ_WI_SEND or */
+						    /* BNA_TXQ_WI_SEND_LSO */
+			bna_txq_wi_ctrl_flag_t flags; /* OR of all the flags */
+			u16 l4_hdr_size_n_offset;
+			u16 vlan_tag;
+			u16 lso_mss;	/* Only 14 LSB are valid */
+			u32 frame_length;	/* Only 24 LSB are valid */
+		} wi;
+
+		struct {
+			u16 reserved;
+			bna_txq_wi_opcode_t opcode; /* Must be */
+						    /* BNA_TXQ_WI_EXTENSION */
+			u32 reserved2[3];	/* Place holder for */
+						/* removed vector (12 bytes) */
+		} wi_ext;
+	} hdr;
+	struct bna_txq_wi_vector vector[4];
+};
+#define wi_hdr  	hdr.wi
+#define wi_ext_hdr  hdr.wi_ext
+
+/* RxQ Entry Structure */
+struct bna_rxq_entry {		/* Rx-Buffer */
+	struct bna_dma_addr host_addr; /* Rx-Buffer DMA address */
+};
+
+typedef u32 bna_cq_e_flag_t;
+
+/* CQ Entry Structure */
+struct bna_cq_entry {
+	bna_cq_e_flag_t flags;
+	u16 vlan_tag;
+	u16 length;
+	u32 rss_hash;
+	u8 valid;
+	u8 reserved1;
+	u8 reserved2;
+	u8 rxq_id;
+};
+
+#endif /* __BNA_HW_H__ */
diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c
new file mode 100644
index 0000000..ad93fdb
--- /dev/null
+++ b/drivers/net/bna/bna_txrx.c
@@ -0,0 +1,4172 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+  */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include "bna.h"
+#include "bfa_sm.h"
+#include "bfi.h"
+
+/**
+ * IB
+ */
+#define bna_ib_find_free_ibidx(_mask, _pos)\
+do {\
+	(_pos) = 0;\
+	while (((_pos) < (BFI_IBIDX_MAX_SEGSIZE)) &&\
+		((1 << (_pos)) & (_mask)))\
+		(_pos)++;\
+} while (0)
+
+#define bna_ib_count_ibidx(_mask, _count)\
+do {\
+	int pos = 0;\
+	(_count) = 0;\
+	while (pos < (BFI_IBIDX_MAX_SEGSIZE)) {\
+		if ((1 << pos) & (_mask))\
+			(_count) = pos + 1;\
+		pos++;\
+	} \
+} while (0)
+
+#define bna_ib_select_segpool(_count, _q_idx)\
+do {\
+	int i;\
+	(_q_idx) = -1;\
+	for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {\
+		if ((_count <= ibidx_pool[i].pool_entry_size)) {\
+			(_q_idx) = i;\
+			break;\
+		} \
+	} \
+} while (0)
+
+struct bna_ibidx_pool {
+	int	pool_size;
+	int	pool_entry_size;
+};
+init_ibidx_pool(ibidx_pool);
+
+static struct bna_intr *
+bna_intr_get(struct bna_ib_mod *ib_mod, enum bna_intr_type intr_type,
+		int vector)
+{
+	struct bna_intr *intr;
+	struct list_head *qe;
+
+	list_for_each(qe, &ib_mod->intr_active_q) {
+		intr = (struct bna_intr *)qe;
+
+		if ((intr->intr_type == intr_type) &&
+			(intr->vector == vector)) {
+			intr->ref_count++;
+			return intr;
+		}
+	}
+
+	if (list_empty(&ib_mod->intr_free_q))
+		return NULL;
+
+	bfa_q_deq(&ib_mod->intr_free_q, &intr);
+	bfa_q_qe_init(&intr->qe);
+
+	intr->ref_count = 1;
+	intr->intr_type = intr_type;
+	intr->vector = vector;
+
+	list_add_tail(&intr->qe, &ib_mod->intr_active_q);
+
+	return intr;
+}
+
+static void
+bna_intr_put(struct bna_ib_mod *ib_mod,
+		struct bna_intr *intr)
+{
+	intr->ref_count--;
+
+	if (intr->ref_count == 0) {
+		intr->ib = NULL;
+		list_del(&intr->qe);
+		bfa_q_qe_init(&intr->qe);
+		list_add_tail(&intr->qe, &ib_mod->intr_free_q);
+	}
+}
+
+void
+bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna,
+		struct bna_res_info *res_info)
+{
+	int i;
+	int j;
+	int count;
+	u8 offset;
+	struct bna_doorbell_qset *qset;
+	unsigned long off;
+
+	ib_mod->bna = bna;
+
+	ib_mod->ib = (struct bna_ib *)
+		res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mdl[0].kva;
+	ib_mod->intr = (struct bna_intr *)
+		res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mdl[0].kva;
+	ib_mod->idx_seg = (struct bna_ibidx_seg *)
+		res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mdl[0].kva;
+
+	INIT_LIST_HEAD(&ib_mod->ib_free_q);
+	INIT_LIST_HEAD(&ib_mod->intr_free_q);
+	INIT_LIST_HEAD(&ib_mod->intr_active_q);
+
+	for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++)
+		INIT_LIST_HEAD(&ib_mod->ibidx_seg_pool[i]);
+
+	for (i = 0; i < BFI_MAX_IB; i++) {
+		ib_mod->ib[i].ib_id = i;
+
+		ib_mod->ib[i].ib_seg_host_addr_kva =
+		res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].kva;
+		ib_mod->ib[i].ib_seg_host_addr.lsb =
+		res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.lsb;
+		ib_mod->ib[i].ib_seg_host_addr.msb =
+		res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.msb;
+
+		qset = (struct bna_doorbell_qset *)0;
+		off = (unsigned long)(&qset[i >> 1].ib0[(i & 0x1)
+					* (0x20 >> 2)]);
+		ib_mod->ib[i].door_bell.doorbell_addr = off +
+			BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva);
+
+		bfa_q_qe_init(&ib_mod->ib[i].qe);
+		list_add_tail(&ib_mod->ib[i].qe, &ib_mod->ib_free_q);
+
+		bfa_q_qe_init(&ib_mod->intr[i].qe);
+		list_add_tail(&ib_mod->intr[i].qe, &ib_mod->intr_free_q);
+	}
+
+	count = 0;
+	offset = 0;
+	for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {
+		for (j = 0; j < ibidx_pool[i].pool_size; j++) {
+			bfa_q_qe_init(&ib_mod->idx_seg[count]);
+			ib_mod->idx_seg[count].ib_seg_size =
+					ibidx_pool[i].pool_entry_size;
+			ib_mod->idx_seg[count].ib_idx_tbl_offset = offset;
+			list_add_tail(&ib_mod->idx_seg[count].qe,
+				&ib_mod->ibidx_seg_pool[i]);
+			count++;
+			offset += ibidx_pool[i].pool_entry_size;
+		}
+	}
+}
+
+void
+bna_ib_mod_uninit(struct bna_ib_mod *ib_mod)
+{
+	int i;
+	int j;
+	struct list_head *qe;
+
+	i = 0;
+	list_for_each(qe, &ib_mod->ib_free_q)
+		i++;
+
+	i = 0;
+	list_for_each(qe, &ib_mod->intr_free_q)
+		i++;
+
+	for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {
+		j = 0;
+		list_for_each(qe, &ib_mod->ibidx_seg_pool[i])
+			j++;
+	}
+
+	ib_mod->bna = NULL;
+}
+
+static struct bna_ib *
+bna_ib_get(struct bna_ib_mod *ib_mod,
+		enum bna_intr_type intr_type,
+		int vector)
+{
+	struct bna_ib *ib;
+	struct bna_intr *intr;
+
+	if (intr_type == BNA_INTR_T_INTX)
+		vector = (1 << vector);
+
+	intr = bna_intr_get(ib_mod, intr_type, vector);
+	if (intr == NULL)
+		return NULL;
+
+	if (intr->ib) {
+		if (intr->ib->ref_count == BFI_IBIDX_MAX_SEGSIZE) {
+			bna_intr_put(ib_mod, intr);
+			return NULL;
+		}
+		intr->ib->ref_count++;
+		return intr->ib;
+	}
+
+	if (list_empty(&ib_mod->ib_free_q)) {
+		bna_intr_put(ib_mod, intr);
+		return NULL;
+	}
+
+	bfa_q_deq(&ib_mod->ib_free_q, &ib);
+	bfa_q_qe_init(&ib->qe);
+
+	ib->ref_count = 1;
+	ib->start_count = 0;
+	ib->idx_mask = 0;
+
+	ib->intr = intr;
+	ib->idx_seg = NULL;
+	intr->ib = ib;
+
+	ib->bna = ib_mod->bna;
+
+	return ib;
+}
+
+static void
+bna_ib_put(struct bna_ib_mod *ib_mod, struct bna_ib *ib)
+{
+	bna_intr_put(ib_mod, ib->intr);
+
+	ib->ref_count--;
+
+	if (ib->ref_count == 0) {
+		ib->intr = NULL;
+		ib->bna = NULL;
+		list_add_tail(&ib->qe, &ib_mod->ib_free_q);
+	}
+}
+
+/* Returns index offset - starting from 0 */
+static int
+bna_ib_reserve_idx(struct bna_ib *ib)
+{
+	struct bna_ib_mod *ib_mod = &ib->bna->ib_mod;
+	struct bna_ibidx_seg *idx_seg;
+	int idx;
+	int num_idx;
+	int q_idx;
+
+	/* Find the first free index position */
+	bna_ib_find_free_ibidx(ib->idx_mask, idx);
+	if (idx == BFI_IBIDX_MAX_SEGSIZE)
+		return -1;
+
+	/*
+	 * Calculate the total number of indexes held by this IB,
+	 * including the index newly reserved above.
+	 */
+	bna_ib_count_ibidx((ib->idx_mask | (1 << idx)), num_idx);
+
+	/* See if there is a free space in the index segment held by this IB */
+	if (ib->idx_seg && (num_idx <= ib->idx_seg->ib_seg_size)) {
+		ib->idx_mask |= (1 << idx);
+		return idx;
+	}
+
+	if (ib->start_count)
+		return -1;
+
+	/* Allocate a new segment */
+	bna_ib_select_segpool(num_idx, q_idx);
+	while (1) {
+		if (q_idx == BFI_IBIDX_TOTAL_POOLS)
+			return -1;
+		if (!list_empty(&ib_mod->ibidx_seg_pool[q_idx]))
+			break;
+		q_idx++;
+	}
+	bfa_q_deq(&ib_mod->ibidx_seg_pool[q_idx], &idx_seg);
+	bfa_q_qe_init(&idx_seg->qe);
+
+	/* Free the old segment */
+	if (ib->idx_seg) {
+		bna_ib_select_segpool(ib->idx_seg->ib_seg_size, q_idx);
+		list_add_tail(&ib->idx_seg->qe, &ib_mod->ibidx_seg_pool[q_idx]);
+	}
+
+	ib->idx_seg = idx_seg;
+
+	ib->idx_mask |= (1 << idx);
+
+	return idx;
+}
+
+static void
+bna_ib_release_idx(struct bna_ib *ib, int idx)
+{
+	struct bna_ib_mod *ib_mod = &ib->bna->ib_mod;
+	struct bna_ibidx_seg *idx_seg;
+	int num_idx;
+	int cur_q_idx;
+	int new_q_idx;
+
+	ib->idx_mask &= ~(1 << idx);
+
+	if (ib->start_count)
+		return;
+
+	bna_ib_count_ibidx(ib->idx_mask, num_idx);
+
+	/*
+	 * Free the segment, if there are no more indexes in the segment
+	 * held by this IB
+	 */
+	if (!num_idx) {
+		bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx);
+		list_add_tail(&ib->idx_seg->qe,
+			&ib_mod->ibidx_seg_pool[cur_q_idx]);
+		ib->idx_seg = NULL;
+		return;
+	}
+
+	/* See if we can move to a smaller segment */
+	bna_ib_select_segpool(num_idx, new_q_idx);
+	bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx);
+	while (new_q_idx < cur_q_idx) {
+		if (!list_empty(&ib_mod->ibidx_seg_pool[new_q_idx]))
+			break;
+		new_q_idx++;
+	}
+	if (new_q_idx < cur_q_idx) {
+		/* Select the new smaller segment */
+		bfa_q_deq(&ib_mod->ibidx_seg_pool[new_q_idx], &idx_seg);
+		bfa_q_qe_init(&idx_seg->qe);
+		/* Free the old segment */
+		list_add_tail(&ib->idx_seg->qe,
+			&ib_mod->ibidx_seg_pool[cur_q_idx]);
+		ib->idx_seg = idx_seg;
+	}
+}
+
+static int
+bna_ib_config(struct bna_ib *ib, struct bna_ib_config *ib_config)
+{
+	if (ib->start_count)
+		return -1;
+
+	ib->ib_config.coalescing_timeo = ib_config->coalescing_timeo;
+	ib->ib_config.interpkt_timeo = ib_config->interpkt_timeo;
+	ib->ib_config.interpkt_count = ib_config->interpkt_count;
+	ib->ib_config.ctrl_flags = ib_config->ctrl_flags;
+
+	ib->ib_config.ctrl_flags |= BFI_IB_CF_MASTER_ENABLE;
+	if (ib->intr->intr_type == BNA_INTR_T_MSIX)
+		ib->ib_config.ctrl_flags |= BFI_IB_CF_MSIX_MODE;
+
+	return 0;
+}
+
+static void
+bna_ib_start(struct bna_ib *ib)
+{
+	struct bna_ib_blk_mem ib_cfg;
+	struct bna_ib_blk_mem *ib_mem;
+	u32 pg_num;
+	u32 intx_mask;
+	int i;
+	void __iomem *base_addr;
+	unsigned long off;
+
+	ib->start_count++;
+
+	if (ib->start_count > 1)
+		return;
+
+	ib_cfg.host_addr_lo = (u32)(ib->ib_seg_host_addr.lsb);
+	ib_cfg.host_addr_hi = (u32)(ib->ib_seg_host_addr.msb);
+
+	ib_cfg.clsc_n_ctrl_n_msix = (((u32)
+				     ib->ib_config.coalescing_timeo << 16) |
+				((u32)ib->ib_config.ctrl_flags << 8) |
+				(ib->intr->vector));
+	ib_cfg.ipkt_n_ent_n_idxof =
+				((u32)
+				 (ib->ib_config.interpkt_timeo & 0xf) << 16) |
+				((u32)ib->idx_seg->ib_seg_size << 8) |
+				(ib->idx_seg->ib_idx_tbl_offset);
+	ib_cfg.ipkt_cnt_cfg_n_unacked = ((u32)
+					 ib->ib_config.interpkt_count << 24);
+
+	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num,
+				HQM_IB_RAM_BASE_OFFSET);
+	writel(pg_num, ib->bna->regs.page_addr);
+
+	base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva,
+					HQM_IB_RAM_BASE_OFFSET);
+
+	ib_mem = (struct bna_ib_blk_mem *)0;
+	off = (unsigned long)&ib_mem[ib->ib_id].host_addr_lo;
+	writel(htonl(ib_cfg.host_addr_lo), base_addr + off);
+
+	off = (unsigned long)&ib_mem[ib->ib_id].host_addr_hi;
+	writel(htonl(ib_cfg.host_addr_hi), base_addr + off);
+
+	off = (unsigned long)&ib_mem[ib->ib_id].clsc_n_ctrl_n_msix;
+	writel(ib_cfg.clsc_n_ctrl_n_msix, base_addr + off);
+
+	off = (unsigned long)&ib_mem[ib->ib_id].ipkt_n_ent_n_idxof;
+	writel(ib_cfg.ipkt_n_ent_n_idxof, base_addr + off);
+
+	off = (unsigned long)&ib_mem[ib->ib_id].ipkt_cnt_cfg_n_unacked;
+	writel(ib_cfg.ipkt_cnt_cfg_n_unacked, base_addr + off);
+
+	ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
+				(u32)ib->ib_config.coalescing_timeo, 0);
+
+	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num,
+				HQM_INDX_TBL_RAM_BASE_OFFSET);
+	writel(pg_num, ib->bna->regs.page_addr);
+
+	base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva,
+					HQM_INDX_TBL_RAM_BASE_OFFSET);
+	for (i = 0; i < ib->idx_seg->ib_seg_size; i++) {
+		off = (unsigned long)
+		((ib->idx_seg->ib_idx_tbl_offset + i) * BFI_IBIDX_SIZE);
+		writel(0, base_addr + off);
+	}
+
+	if (ib->intr->intr_type == BNA_INTR_T_INTX) {
+		bna_intx_disable(ib->bna, intx_mask);
+		intx_mask &= ~(ib->intr->vector);
+		bna_intx_enable(ib->bna, intx_mask);
+	}
+}
+
+static void
+bna_ib_stop(struct bna_ib *ib)
+{
+	u32 intx_mask;
+
+	ib->start_count--;
+
+	if (ib->start_count == 0) {
+		writel(BNA_DOORBELL_IB_INT_DISABLE,
+				ib->door_bell.doorbell_addr);
+		if (ib->intr->intr_type == BNA_INTR_T_INTX) {
+			bna_intx_disable(ib->bna, intx_mask);
+			intx_mask |= (ib->intr->vector);
+			bna_intx_enable(ib->bna, intx_mask);
+		}
+	}
+}
+
+static void
+bna_ib_fail(struct bna_ib *ib)
+{
+	ib->start_count = 0;
+}
+
+/**
+ * RXF
+ */
+static void rxf_enable(struct bna_rxf *rxf);
+static void rxf_disable(struct bna_rxf *rxf);
+static void __rxf_config_set(struct bna_rxf *rxf);
+static void __rxf_rit_set(struct bna_rxf *rxf);
+static void __bna_rxf_stat_clr(struct bna_rxf *rxf);
+static int rxf_process_packet_filter(struct bna_rxf *rxf);
+static int rxf_clear_packet_filter(struct bna_rxf *rxf);
+static void rxf_reset_packet_filter(struct bna_rxf *rxf);
+static void rxf_cb_enabled(void *arg, int status);
+static void rxf_cb_disabled(void *arg, int status);
+static void bna_rxf_cb_stats_cleared(void *arg, int status);
+static void __rxf_enable(struct bna_rxf *rxf);
+static void __rxf_disable(struct bna_rxf *rxf);
+
+bfa_fsm_state_decl(bna_rxf, stopped, struct bna_rxf,
+			enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, start_wait, struct bna_rxf,
+			enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, cam_fltr_mod_wait, struct bna_rxf,
+			enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, started, struct bna_rxf,
+			enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, cam_fltr_clr_wait, struct bna_rxf,
+			enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, stop_wait, struct bna_rxf,
+			enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, pause_wait, struct bna_rxf,
+			enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, resume_wait, struct bna_rxf,
+			enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, stat_clr_wait, struct bna_rxf,
+			enum bna_rxf_event);
+
+static struct bfa_sm_table rxf_sm_table[] = {
+	{BFA_SM(bna_rxf_sm_stopped), BNA_RXF_STOPPED},
+	{BFA_SM(bna_rxf_sm_start_wait), BNA_RXF_START_WAIT},
+	{BFA_SM(bna_rxf_sm_cam_fltr_mod_wait), BNA_RXF_CAM_FLTR_MOD_WAIT},
+	{BFA_SM(bna_rxf_sm_started), BNA_RXF_STARTED},
+	{BFA_SM(bna_rxf_sm_cam_fltr_clr_wait), BNA_RXF_CAM_FLTR_CLR_WAIT},
+	{BFA_SM(bna_rxf_sm_stop_wait), BNA_RXF_STOP_WAIT},
+	{BFA_SM(bna_rxf_sm_pause_wait), BNA_RXF_PAUSE_WAIT},
+	{BFA_SM(bna_rxf_sm_resume_wait), BNA_RXF_RESUME_WAIT},
+	{BFA_SM(bna_rxf_sm_stat_clr_wait), BNA_RXF_STAT_CLR_WAIT}
+};
+
+static void
+bna_rxf_sm_stopped_entry(struct bna_rxf *rxf)
+{
+	call_rxf_stop_cbfn(rxf, BNA_CB_SUCCESS);
+}
+
+static void
+bna_rxf_sm_stopped(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+	switch (event) {
+	case RXF_E_START:
+		bfa_fsm_set_state(rxf, bna_rxf_sm_start_wait);
+		break;
+
+	case RXF_E_STOP:
+		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+		break;
+
+	case RXF_E_FAIL:
+		/* No-op */
+		break;
+
+	case RXF_E_CAM_FLTR_MOD:
+		call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
+		break;
+
+	case RXF_E_STARTED:
+	case RXF_E_STOPPED:
+	case RXF_E_CAM_FLTR_RESP:
+		/**
+		 * These events are received due to flushing of mbox
+		 * when device fails
+		 */
+		/* No-op */
+		break;
+
+	case RXF_E_PAUSE:
+		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
+		call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS);
+		break;
+
+	case RXF_E_RESUME:
+		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
+		call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS);
+		break;
+
+	default:
+		bfa_sm_fault(rxf->rx->bna, event);
+	}
+}
+
+static void
+bna_rxf_sm_start_wait_entry(struct bna_rxf *rxf)
+{
+	__rxf_config_set(rxf);
+	__rxf_rit_set(rxf);
+	rxf_enable(rxf);
+}
+
+static void
+bna_rxf_sm_start_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+	switch (event) {
+	case RXF_E_STOP:
+		/**
+		 * STOP is originated from bnad. When this happens,
+		 * it can not be waiting for filter update
+		 */
+		call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT);
+		bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait);
+		break;
+
+	case RXF_E_FAIL:
+		call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
+		call_rxf_start_cbfn(rxf, BNA_CB_FAIL);
+		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+		break;
+
+	case RXF_E_CAM_FLTR_MOD:
+		/* No-op */
+		break;
+
+	case RXF_E_STARTED:
+		/**
+		 * Force rxf_process_filter() to go through initial
+		 * config
+		 */
+		if ((rxf->ucast_active_mac != NULL) &&
+			(rxf->ucast_pending_set == 0))
+			rxf->ucast_pending_set = 1;
+
+		if (rxf->rss_status == BNA_STATUS_T_ENABLED)
+			rxf->rxf_flags |= BNA_RXF_FL_RSS_CONFIG_PENDING;
+
+		rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
+
+		bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait);
+		break;
+
+	case RXF_E_PAUSE:
+	case RXF_E_RESUME:
+		rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED;
+		break;
+
+	default:
+		bfa_sm_fault(rxf->rx->bna, event);
+	}
+}
+
+static void
+bna_rxf_sm_cam_fltr_mod_wait_entry(struct bna_rxf *rxf)
+{
+	if (!rxf_process_packet_filter(rxf)) {
+		/* No more pending CAM entries to update */
+		bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+	}
+}
+
+static void
+bna_rxf_sm_cam_fltr_mod_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+	switch (event) {
+	case RXF_E_STOP:
+		/**
+		 * STOP is originated from bnad. When this happens,
+		 * it can not be waiting for filter update
+		 */
+		call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT);
+		bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait);
+		break;
+
+	case RXF_E_FAIL:
+		rxf_reset_packet_filter(rxf);
+		call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
+		call_rxf_start_cbfn(rxf, BNA_CB_FAIL);
+		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+		break;
+
+	case RXF_E_CAM_FLTR_MOD:
+		/* No-op */
+		break;
+
+	case RXF_E_CAM_FLTR_RESP:
+		if (!rxf_process_packet_filter(rxf)) {
+			/* No more pending CAM entries to update */
+			call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
+			bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+		}
+		break;
+
+	case RXF_E_PAUSE:
+	case RXF_E_RESUME:
+		rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED;
+		break;
+
+	default:
+		bfa_sm_fault(rxf->rx->bna, event);
+	}
+}
+
+static void
+bna_rxf_sm_started_entry(struct bna_rxf *rxf)
+{
+	call_rxf_start_cbfn(rxf, BNA_CB_SUCCESS);
+
+	if (rxf->rxf_flags & BNA_RXF_FL_OPERSTATE_CHANGED) {
+		if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
+			bfa_fsm_send_event(rxf, RXF_E_PAUSE);
+		else
+			bfa_fsm_send_event(rxf, RXF_E_RESUME);
+	}
+
+}
+
+static void
+bna_rxf_sm_started(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+	switch (event) {
+	case RXF_E_STOP:
+		bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait);
+		/* Hack to get FSM start clearing CAM entries */
+		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP);
+		break;
+
+	case RXF_E_FAIL:
+		rxf_reset_packet_filter(rxf);
+		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+		break;
+
+	case RXF_E_CAM_FLTR_MOD:
+		bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait);
+		break;
+
+	case RXF_E_PAUSE:
+		bfa_fsm_set_state(rxf, bna_rxf_sm_pause_wait);
+		break;
+
+	case RXF_E_RESUME:
+		bfa_fsm_set_state(rxf, bna_rxf_sm_resume_wait);
+		break;
+
+	default:
+		bfa_sm_fault(rxf->rx->bna, event);
+	}
+}
+
+static void
+bna_rxf_sm_cam_fltr_clr_wait_entry(struct bna_rxf *rxf)
+{
+	/**
+	 *  Note: Do not add rxf_clear_packet_filter here.
+	 * It will overstep mbox when this transition happens:
+	 * 	cam_fltr_mod_wait -> cam_fltr_clr_wait on RXF_E_STOP event
+	 */
+}
+
+static void
+bna_rxf_sm_cam_fltr_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+	switch (event) {
+	case RXF_E_FAIL:
+		/**
+		 * FSM was in the process of stopping, initiated by
+		 * bnad. When this happens, no one can be waiting for
+		 * start or filter update
+		 */
+		rxf_reset_packet_filter(rxf);
+		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+		break;
+
+	case RXF_E_CAM_FLTR_RESP:
+		if (!rxf_clear_packet_filter(rxf)) {
+			/* No more pending CAM entries to clear */
+			bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait);
+			rxf_disable(rxf);
+		}
+		break;
+
+	default:
+		bfa_sm_fault(rxf->rx->bna, event);
+	}
+}
+
+static void
+bna_rxf_sm_stop_wait_entry(struct bna_rxf *rxf)
+{
+	/**
+	 * NOTE: Do not add  rxf_disable here.
+	 * It will overstep mbox when this transition happens:
+	 * 	start_wait -> stop_wait on RXF_E_STOP event
+	 */
+}
+
+static void
+bna_rxf_sm_stop_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+	switch (event) {
+	case RXF_E_FAIL:
+		/**
+		 * FSM was in the process of stopping, initiated by
+		 * bnad. When this happens, no one can be waiting for
+		 * start or filter update
+		 */
+		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+		break;
+
+	case RXF_E_STARTED:
+		/**
+		 * This event is received due to abrupt transition from
+		 * bna_rxf_sm_start_wait state on receiving
+		 * RXF_E_STOP event
+		 */
+		rxf_disable(rxf);
+		break;
+
+	case RXF_E_STOPPED:
+		/**
+		 * FSM was in the process of stopping, initiated by
+		 * bnad. When this happens, no one can be waiting for
+		 * start or filter update
+		 */
+		bfa_fsm_set_state(rxf, bna_rxf_sm_stat_clr_wait);
+		break;
+
+	case RXF_E_PAUSE:
+		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
+		break;
+
+	case RXF_E_RESUME:
+		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
+		break;
+
+	default:
+		bfa_sm_fault(rxf->rx->bna, event);
+	}
+}
+
+static void
+bna_rxf_sm_pause_wait_entry(struct bna_rxf *rxf)
+{
+	rxf->rxf_flags &=
+		~(BNA_RXF_FL_OPERSTATE_CHANGED | BNA_RXF_FL_RXF_ENABLED);
+	__rxf_disable(rxf);
+}
+
+static void
+bna_rxf_sm_pause_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+	switch (event) {
+	case RXF_E_FAIL:
+		/**
+		 * FSM was in the process of disabling rxf, initiated by
+		 * bnad.
+		 */
+		call_rxf_pause_cbfn(rxf, BNA_CB_FAIL);
+		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+		break;
+
+	case RXF_E_STOPPED:
+		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
+		call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS);
+		bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+		break;
+
+	/*
+	 * Since PAUSE/RESUME can only be sent by bnad, we don't expect
+	 * any other event during these states
+	 */
+	default:
+		bfa_sm_fault(rxf->rx->bna, event);
+	}
+}
+
+static void
+bna_rxf_sm_resume_wait_entry(struct bna_rxf *rxf)
+{
+	rxf->rxf_flags &= ~(BNA_RXF_FL_OPERSTATE_CHANGED);
+	rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED;
+	__rxf_enable(rxf);
+}
+
+static void
+bna_rxf_sm_resume_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+	switch (event) {
+	case RXF_E_FAIL:
+		/**
+		 * FSM was in the process of disabling rxf, initiated by
+		 * bnad.
+		 */
+		call_rxf_resume_cbfn(rxf, BNA_CB_FAIL);
+		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+		break;
+
+	case RXF_E_STARTED:
+		rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
+		call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS);
+		bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+		break;
+
+	/*
+	 * Since PAUSE/RESUME can only be sent by bnad, we don't expect
+	 * any other event during these states
+	 */
+	default:
+		bfa_sm_fault(rxf->rx->bna, event);
+	}
+}
+
+static void
+bna_rxf_sm_stat_clr_wait_entry(struct bna_rxf *rxf)
+{
+	__bna_rxf_stat_clr(rxf);
+}
+
+static void
+bna_rxf_sm_stat_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+	switch (event) {
+	case RXF_E_FAIL:
+	case RXF_E_STAT_CLEARED:
+		bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+		break;
+
+	default:
+		bfa_sm_fault(rxf->rx->bna, event);
+	}
+}
+
+static void
+__rxf_enable(struct bna_rxf *rxf)
+{
+	struct bfi_ll_rxf_multi_req ll_req;
+	u32 bm[2] = {0, 0};
+
+	if (rxf->rxf_id < 32)
+		bm[0] = 1 << rxf->rxf_id;
+	else
+		bm[1] = 1 << (rxf->rxf_id - 32);
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
+	ll_req.rxf_id_mask[0] = htonl(bm[0]);
+	ll_req.rxf_id_mask[1] = htonl(bm[1]);
+	ll_req.enable = 1;
+
+	bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
+			rxf_cb_enabled, rxf);
+
+	bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
+}
+
+static void
+__rxf_disable(struct bna_rxf *rxf)
+{
+	struct bfi_ll_rxf_multi_req ll_req;
+	u32 bm[2] = {0, 0};
+
+	if (rxf->rxf_id < 32)
+		bm[0] = 1 << rxf->rxf_id;
+	else
+		bm[1] = 1 << (rxf->rxf_id - 32);
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
+	ll_req.rxf_id_mask[0] = htonl(bm[0]);
+	ll_req.rxf_id_mask[1] = htonl(bm[1]);
+	ll_req.enable = 0;
+
+	bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
+			rxf_cb_disabled, rxf);
+
+	bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
+}
+
+static void
+__rxf_config_set(struct bna_rxf *rxf)
+{
+	u32 i;
+	struct bna_rss_mem *rss_mem;
+	struct bna_rx_fndb_ram *rx_fndb_ram;
+	struct bna *bna = rxf->rx->bna;
+	void __iomem *base_addr;
+	unsigned long off;
+
+	base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
+			RSS_TABLE_BASE_OFFSET);
+
+	rss_mem = (struct bna_rss_mem *)0;
+
+	/* Configure RSS if required */
+	if (rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE) {
+		/* configure RSS Table */
+		writel(BNA_GET_PAGE_NUM(RAD0_MEM_BLK_BASE_PG_NUM +
+			bna->port_num, RSS_TABLE_BASE_OFFSET),
+					bna->regs.page_addr);
+
+		/* temporarily disable RSS, while hash value is written */
+		off = (unsigned long)&rss_mem[0].type_n_hash;
+		writel(0, base_addr + off);
+
+		for (i = 0; i < BFI_RSS_HASH_KEY_LEN; i++) {
+			off = (unsigned long)
+			&rss_mem[0].hash_key[(BFI_RSS_HASH_KEY_LEN - 1) - i];
+			writel(htonl(rxf->rss_cfg.toeplitz_hash_key[i]),
+			base_addr + off);
+		}
+
+		off = (unsigned long)&rss_mem[0].type_n_hash;
+		writel(rxf->rss_cfg.hash_type | rxf->rss_cfg.hash_mask,
+			base_addr + off);
+	}
+
+	/* Configure RxF */
+	writel(BNA_GET_PAGE_NUM(
+		LUT0_MEM_BLK_BASE_PG_NUM + (bna->port_num * 2),
+		RX_FNDB_RAM_BASE_OFFSET),
+		bna->regs.page_addr);
+
+	base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
+		RX_FNDB_RAM_BASE_OFFSET);
+
+	rx_fndb_ram = (struct bna_rx_fndb_ram *)0;
+
+	/* We always use RSS table 0 */
+	off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rss_prop;
+	writel(rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE,
+		base_addr + off);
+
+	/* small large buffer enable/disable */
+	off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].size_routing_props;
+	writel((rxf->ctrl_flags & BNA_RXF_CF_SM_LG_RXQ) | 0x80,
+		base_addr + off);
+
+	/* RIT offset,  HDS forced offset, multicast RxQ Id */
+	off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rit_hds_mcastq;
+	writel((rxf->rit_segment->rit_offset << 16) |
+		(rxf->forced_offset << 8) |
+		(rxf->hds_cfg.hdr_type & BNA_HDS_FORCED) | rxf->mcast_rxq_id,
+		base_addr + off);
+
+	/*
+	 * default vlan tag, default function enable, strip vlan bytes,
+	 * HDS type, header size
+	 */
+
+	off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].control_flags;
+	 writel(((u32)rxf->default_vlan_tag << 16) |
+		(rxf->ctrl_flags &
+			(BNA_RXF_CF_DEFAULT_VLAN |
+			BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE |
+			BNA_RXF_CF_VLAN_STRIP)) |
+		(rxf->hds_cfg.hdr_type & ~BNA_HDS_FORCED) |
+		rxf->hds_cfg.header_size,
+		base_addr + off);
+}
+
+void
+__rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status)
+{
+	struct bna *bna = rxf->rx->bna;
+	int i;
+
+	writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+			(bna->port_num * 2), VLAN_RAM_BASE_OFFSET),
+			bna->regs.page_addr);
+
+	if (status == BNA_STATUS_T_ENABLED) {
+		/* enable VLAN filtering on this function */
+		for (i = 0; i <= BFI_MAX_VLAN / 32; i++) {
+			writel(rxf->vlan_filter_table[i],
+					BNA_GET_VLAN_MEM_ENTRY_ADDR
+					(bna->pcidev.pci_bar_kva, rxf->rxf_id,
+						i * 32));
+		}
+	} else {
+		/* disable VLAN filtering on this function */
+		for (i = 0; i <= BFI_MAX_VLAN / 32; i++) {
+			writel(0xffffffff,
+					BNA_GET_VLAN_MEM_ENTRY_ADDR
+					(bna->pcidev.pci_bar_kva, rxf->rxf_id,
+						i * 32));
+		}
+	}
+}
+
+static void
+__rxf_rit_set(struct bna_rxf *rxf)
+{
+	struct bna *bna = rxf->rx->bna;
+	struct bna_rit_mem *rit_mem;
+	int i;
+	void __iomem *base_addr;
+	unsigned long off;
+
+	base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
+			FUNCTION_TO_RXQ_TRANSLATE);
+
+	rit_mem = (struct bna_rit_mem *)0;
+
+	writel(BNA_GET_PAGE_NUM(RXA0_MEM_BLK_BASE_PG_NUM + bna->port_num,
+		FUNCTION_TO_RXQ_TRANSLATE),
+		bna->regs.page_addr);
+
+	for (i = 0; i < rxf->rit_segment->rit_size; i++) {
+		off = (unsigned long)&rit_mem[i + rxf->rit_segment->rit_offset];
+		writel(rxf->rit_segment->rit[i].large_rxq_id << 6 |
+			rxf->rit_segment->rit[i].small_rxq_id,
+			base_addr + off);
+	}
+}
+
+static void
+__bna_rxf_stat_clr(struct bna_rxf *rxf)
+{
+	struct bfi_ll_stats_req ll_req;
+	u32 bm[2] = {0, 0};
+
+	if (rxf->rxf_id < 32)
+		bm[0] = 1 << rxf->rxf_id;
+	else
+		bm[1] = 1 << (rxf->rxf_id - 32);
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
+	ll_req.stats_mask = 0;
+	ll_req.txf_id_mask[0] = 0;
+	ll_req.txf_id_mask[1] =	0;
+
+	ll_req.rxf_id_mask[0] = htonl(bm[0]);
+	ll_req.rxf_id_mask[1] = htonl(bm[1]);
+
+	bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
+			bna_rxf_cb_stats_cleared, rxf);
+	bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
+}
+
+static void
+rxf_enable(struct bna_rxf *rxf)
+{
+	if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
+		bfa_fsm_send_event(rxf, RXF_E_STARTED);
+	else {
+		rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED;
+		__rxf_enable(rxf);
+	}
+}
+
+static void
+rxf_cb_enabled(void *arg, int status)
+{
+	struct bna_rxf *rxf = (struct bna_rxf *)arg;
+
+	bfa_q_qe_init(&rxf->mbox_qe.qe);
+	bfa_fsm_send_event(rxf, RXF_E_STARTED);
+}
+
+static void
+rxf_disable(struct bna_rxf *rxf)
+{
+	if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
+		bfa_fsm_send_event(rxf, RXF_E_STOPPED);
+	else
+		rxf->rxf_flags &= ~BNA_RXF_FL_RXF_ENABLED;
+		__rxf_disable(rxf);
+}
+
+static void
+rxf_cb_disabled(void *arg, int status)
+{
+	struct bna_rxf *rxf = (struct bna_rxf *)arg;
+
+	bfa_q_qe_init(&rxf->mbox_qe.qe);
+	bfa_fsm_send_event(rxf, RXF_E_STOPPED);
+}
+
+void
+rxf_cb_cam_fltr_mbox_cmd(void *arg, int status)
+{
+	struct bna_rxf *rxf = (struct bna_rxf *)arg;
+
+	bfa_q_qe_init(&rxf->mbox_qe.qe);
+
+	bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP);
+}
+
+static void
+bna_rxf_cb_stats_cleared(void *arg, int status)
+{
+	struct bna_rxf *rxf = (struct bna_rxf *)arg;
+
+	bfa_q_qe_init(&rxf->mbox_qe.qe);
+	bfa_fsm_send_event(rxf, RXF_E_STAT_CLEARED);
+}
+
+void
+rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd,
+		const struct bna_mac *mac_addr)
+{
+	struct bfi_ll_mac_addr_req req;
+
+	bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0);
+
+	req.rxf_id = rxf->rxf_id;
+	memcpy(&req.mac_addr, (void *)&mac_addr->addr, ETH_ALEN);
+
+	bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req),
+				rxf_cb_cam_fltr_mbox_cmd, rxf);
+
+	bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
+}
+
+static int
+rxf_process_packet_filter_mcast(struct bna_rxf *rxf)
+{
+	struct bna_mac *mac = NULL;
+	struct list_head *qe;
+
+	/* Add multicast entries */
+	if (!list_empty(&rxf->mcast_pending_add_q)) {
+		bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
+		bfa_q_qe_init(qe);
+		mac = (struct bna_mac *)qe;
+		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_ADD_REQ, mac);
+		list_add_tail(&mac->qe, &rxf->mcast_active_q);
+		return 1;
+	}
+
+	/* Delete multicast entries previousely added */
+	if (!list_empty(&rxf->mcast_pending_del_q)) {
+		bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
+		bfa_q_qe_init(qe);
+		mac = (struct bna_mac *)qe;
+		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
+		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int
+rxf_process_packet_filter_vlan(struct bna_rxf *rxf)
+{
+	/* Apply the VLAN filter */
+	if (rxf->rxf_flags & BNA_RXF_FL_VLAN_CONFIG_PENDING) {
+		rxf->rxf_flags &= ~BNA_RXF_FL_VLAN_CONFIG_PENDING;
+		if (!(rxf->rxmode_active & BNA_RXMODE_PROMISC) &&
+			!(rxf->rxmode_active & BNA_RXMODE_DEFAULT))
+			__rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+	}
+
+	/* Apply RSS configuration */
+	if (rxf->rxf_flags & BNA_RXF_FL_RSS_CONFIG_PENDING) {
+		rxf->rxf_flags &= ~BNA_RXF_FL_RSS_CONFIG_PENDING;
+		if (rxf->rss_status == BNA_STATUS_T_DISABLED) {
+			/* RSS is being disabled */
+			rxf->ctrl_flags &= ~BNA_RXF_CF_RSS_ENABLE;
+			__rxf_rit_set(rxf);
+			__rxf_config_set(rxf);
+		} else {
+			/* RSS is being enabled or reconfigured */
+			rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE;
+			__rxf_rit_set(rxf);
+			__rxf_config_set(rxf);
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Processes pending ucast, mcast entry addition/deletion and issues mailbox
+ * command. Also processes pending filter configuration - promiscuous mode,
+ * default mode, allmutli mode and issues mailbox command or directly applies
+ * to h/w
+ */
+static int
+rxf_process_packet_filter(struct bna_rxf *rxf)
+{
+	/* Set the default MAC first */
+	if (rxf->ucast_pending_set > 0) {
+		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_SET_REQ,
+				rxf->ucast_active_mac);
+		rxf->ucast_pending_set--;
+		return 1;
+	}
+
+	if (rxf_process_packet_filter_ucast(rxf))
+		return 1;
+
+	if (rxf_process_packet_filter_mcast(rxf))
+		return 1;
+
+	if (rxf_process_packet_filter_promisc(rxf))
+		return 1;
+
+	if (rxf_process_packet_filter_default(rxf))
+		return 1;
+
+	if (rxf_process_packet_filter_allmulti(rxf))
+		return 1;
+
+	if (rxf_process_packet_filter_vlan(rxf))
+		return 1;
+
+	return 0;
+}
+
+static int
+rxf_clear_packet_filter_mcast(struct bna_rxf *rxf)
+{
+	struct bna_mac *mac = NULL;
+	struct list_head *qe;
+
+	/* 3. delete pending mcast entries */
+	if (!list_empty(&rxf->mcast_pending_del_q)) {
+		bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
+		bfa_q_qe_init(qe);
+		mac = (struct bna_mac *)qe;
+		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
+		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+		return 1;
+	}
+
+	/* 4. clear active mcast entries; move them to pending_add_q */
+	if (!list_empty(&rxf->mcast_active_q)) {
+		bfa_q_deq(&rxf->mcast_active_q, &qe);
+		bfa_q_qe_init(qe);
+		mac = (struct bna_mac *)qe;
+		rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
+		list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * In the rxf stop path, processes pending ucast/mcast delete queue and issues
+ * the mailbox command. Moves the active ucast/mcast entries to pending add q,
+ * so that they are added to CAM again in the rxf start path. Moves the current
+ * filter settings - promiscuous, default, allmutli - to pending filter
+ * configuration
+ */
+static int
+rxf_clear_packet_filter(struct bna_rxf *rxf)
+{
+	if (rxf_clear_packet_filter_ucast(rxf))
+		return 1;
+
+	if (rxf_clear_packet_filter_mcast(rxf))
+		return 1;
+
+	/* 5. clear active default MAC in the CAM */
+	if (rxf->ucast_pending_set > 0)
+		rxf->ucast_pending_set = 0;
+
+	if (rxf_clear_packet_filter_promisc(rxf))
+		return 1;
+
+	if (rxf_clear_packet_filter_default(rxf))
+		return 1;
+
+	if (rxf_clear_packet_filter_allmulti(rxf))
+		return 1;
+
+	return 0;
+}
+
+static void
+rxf_reset_packet_filter_mcast(struct bna_rxf *rxf)
+{
+	struct list_head *qe;
+	struct bna_mac *mac;
+
+	/* 3. Move active mcast entries to pending_add_q */
+	while (!list_empty(&rxf->mcast_active_q)) {
+		bfa_q_deq(&rxf->mcast_active_q, &qe);
+		bfa_q_qe_init(qe);
+		list_add_tail(qe, &rxf->mcast_pending_add_q);
+	}
+
+	/* 4. Throw away delete pending mcast entries */
+	while (!list_empty(&rxf->mcast_pending_del_q)) {
+		bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
+		bfa_q_qe_init(qe);
+		mac = (struct bna_mac *)qe;
+		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+	}
+}
+
+/**
+ * In the rxf fail path, throws away the ucast/mcast entries pending for
+ * deletion, moves all active ucast/mcast entries to pending queue so that
+ * they are added back to CAM in the rxf start path. Also moves the current
+ * filter configuration to pending filter configuration.
+ */
+static void
+rxf_reset_packet_filter(struct bna_rxf *rxf)
+{
+	rxf_reset_packet_filter_ucast(rxf);
+
+	rxf_reset_packet_filter_mcast(rxf);
+
+	/* 5. Turn off ucast set flag */
+	rxf->ucast_pending_set = 0;
+
+	rxf_reset_packet_filter_promisc(rxf);
+
+	rxf_reset_packet_filter_default(rxf);
+
+	rxf_reset_packet_filter_allmulti(rxf);
+}
+
+static void
+bna_rxf_init(struct bna_rxf *rxf,
+		struct bna_rx *rx,
+		struct bna_rx_config *q_config)
+{
+	struct list_head *qe;
+	struct bna_rxp *rxp;
+
+	/* rxf_id is initialized during rx_mod init */
+	rxf->rx = rx;
+
+	INIT_LIST_HEAD(&rxf->ucast_pending_add_q);
+	INIT_LIST_HEAD(&rxf->ucast_pending_del_q);
+	rxf->ucast_pending_set = 0;
+	INIT_LIST_HEAD(&rxf->ucast_active_q);
+	rxf->ucast_active_mac = NULL;
+
+	INIT_LIST_HEAD(&rxf->mcast_pending_add_q);
+	INIT_LIST_HEAD(&rxf->mcast_pending_del_q);
+	INIT_LIST_HEAD(&rxf->mcast_active_q);
+
+	bfa_q_qe_init(&rxf->mbox_qe.qe);
+
+	if (q_config->vlan_strip_status == BNA_STATUS_T_ENABLED)
+		rxf->ctrl_flags |= BNA_RXF_CF_VLAN_STRIP;
+
+	rxf->rxf_oper_state = (q_config->paused) ?
+		BNA_RXF_OPER_STATE_PAUSED : BNA_RXF_OPER_STATE_RUNNING;
+
+	bna_rxf_adv_init(rxf, rx, q_config);
+
+	rxf->rit_segment = bna_rit_mod_seg_get(&rxf->rx->bna->rit_mod,
+					q_config->num_paths);
+
+	list_for_each(qe, &rx->rxp_q) {
+		rxp = (struct bna_rxp *)qe;
+		if (q_config->rxp_type == BNA_RXP_SINGLE)
+			rxf->mcast_rxq_id = rxp->rxq.single.only->rxq_id;
+		else
+			rxf->mcast_rxq_id = rxp->rxq.slr.large->rxq_id;
+		break;
+	}
+
+	rxf->vlan_filter_status = BNA_STATUS_T_DISABLED;
+	memset(rxf->vlan_filter_table, 0,
+			(sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32)));
+
+	bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+}
+
+static void
+bna_rxf_uninit(struct bna_rxf *rxf)
+{
+	struct bna_mac *mac;
+
+	bna_rit_mod_seg_put(&rxf->rx->bna->rit_mod, rxf->rit_segment);
+	rxf->rit_segment = NULL;
+
+	rxf->ucast_pending_set = 0;
+
+	while (!list_empty(&rxf->ucast_pending_add_q)) {
+		bfa_q_deq(&rxf->ucast_pending_add_q, &mac);
+		bfa_q_qe_init(&mac->qe);
+		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+	}
+
+	if (rxf->ucast_active_mac) {
+		bfa_q_qe_init(&rxf->ucast_active_mac->qe);
+		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod,
+			rxf->ucast_active_mac);
+		rxf->ucast_active_mac = NULL;
+	}
+
+	while (!list_empty(&rxf->mcast_pending_add_q)) {
+		bfa_q_deq(&rxf->mcast_pending_add_q, &mac);
+		bfa_q_qe_init(&mac->qe);
+		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+	}
+
+	rxf->rx = NULL;
+}
+
+static void
+bna_rx_cb_rxf_started(struct bna_rx *rx, enum bna_cb_status status)
+{
+	bfa_fsm_send_event(rx, RX_E_RXF_STARTED);
+	if (rx->rxf.rxf_id < 32)
+		rx->bna->rx_mod.rxf_bmap[0] |= ((u32)1 << rx->rxf.rxf_id);
+	else
+		rx->bna->rx_mod.rxf_bmap[1] |= ((u32)
+				1 << (rx->rxf.rxf_id - 32));
+}
+
+static void
+bna_rxf_start(struct bna_rxf *rxf)
+{
+	rxf->start_cbfn = bna_rx_cb_rxf_started;
+	rxf->start_cbarg = rxf->rx;
+	rxf->rxf_flags &= ~BNA_RXF_FL_FAILED;
+	bfa_fsm_send_event(rxf, RXF_E_START);
+}
+
+static void
+bna_rx_cb_rxf_stopped(struct bna_rx *rx, enum bna_cb_status status)
+{
+	bfa_fsm_send_event(rx, RX_E_RXF_STOPPED);
+	if (rx->rxf.rxf_id < 32)
+		rx->bna->rx_mod.rxf_bmap[0] &= ~(u32)1 << rx->rxf.rxf_id;
+	else
+		rx->bna->rx_mod.rxf_bmap[1] &= ~(u32)
+				1 << (rx->rxf.rxf_id - 32);
+}
+
+static void
+bna_rxf_stop(struct bna_rxf *rxf)
+{
+	rxf->stop_cbfn = bna_rx_cb_rxf_stopped;
+	rxf->stop_cbarg = rxf->rx;
+	bfa_fsm_send_event(rxf, RXF_E_STOP);
+}
+
+static void
+bna_rxf_fail(struct bna_rxf *rxf)
+{
+	rxf->rxf_flags |= BNA_RXF_FL_FAILED;
+	bfa_fsm_send_event(rxf, RXF_E_FAIL);
+}
+
+int
+bna_rxf_state_get(struct bna_rxf *rxf)
+{
+	return bfa_sm_to_state(rxf_sm_table, rxf->fsm);
+}
+
+enum bna_cb_status
+bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
+		 void (*cbfn)(struct bnad *, struct bna_rx *,
+			      enum bna_cb_status))
+{
+	struct bna_rxf *rxf = &rx->rxf;
+
+	if (rxf->ucast_active_mac == NULL) {
+		rxf->ucast_active_mac =
+				bna_ucam_mod_mac_get(&rxf->rx->bna->ucam_mod);
+		if (rxf->ucast_active_mac == NULL)
+			return BNA_CB_UCAST_CAM_FULL;
+		bfa_q_qe_init(&rxf->ucast_active_mac->qe);
+	}
+
+	memcpy(rxf->ucast_active_mac->addr, ucmac, ETH_ALEN);
+	rxf->ucast_pending_set++;
+	rxf->cam_fltr_cbfn = cbfn;
+	rxf->cam_fltr_cbarg = rx->bna->bnad;
+
+	bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+
+	return BNA_CB_SUCCESS;
+}
+
+enum bna_cb_status
+bna_rx_mcast_add(struct bna_rx *rx, u8 *addr,
+		 void (*cbfn)(struct bnad *, struct bna_rx *,
+			      enum bna_cb_status))
+{
+	struct bna_rxf *rxf = &rx->rxf;
+	struct list_head	*qe;
+	struct bna_mac *mac;
+
+	/* Check if already added */
+	list_for_each(qe, &rxf->mcast_active_q) {
+		mac = (struct bna_mac *)qe;
+		if (BNA_MAC_IS_EQUAL(mac->addr, addr)) {
+			if (cbfn)
+				(*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
+			return BNA_CB_SUCCESS;
+		}
+	}
+
+	/* Check if pending addition */
+	list_for_each(qe, &rxf->mcast_pending_add_q) {
+		mac = (struct bna_mac *)qe;
+		if (BNA_MAC_IS_EQUAL(mac->addr, addr)) {
+			if (cbfn)
+				(*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
+			return BNA_CB_SUCCESS;
+		}
+	}
+
+	mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
+	if (mac == NULL)
+		return BNA_CB_MCAST_LIST_FULL;
+	bfa_q_qe_init(&mac->qe);
+	memcpy(mac->addr, addr, ETH_ALEN);
+	list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+
+	rxf->cam_fltr_cbfn = cbfn;
+	rxf->cam_fltr_cbarg = rx->bna->bnad;
+
+	bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+
+	return BNA_CB_SUCCESS;
+}
+
+enum bna_cb_status
+bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist,
+		     void (*cbfn)(struct bnad *, struct bna_rx *,
+				  enum bna_cb_status))
+{
+	struct bna_rxf *rxf = &rx->rxf;
+	struct list_head list_head;
+	struct list_head *qe;
+	u8 *mcaddr;
+	struct bna_mac *mac;
+	struct bna_mac *mac1;
+	int skip;
+	int delete;
+	int need_hw_config = 0;
+	int i;
+
+	/* Allocate nodes */
+	INIT_LIST_HEAD(&list_head);
+	for (i = 0, mcaddr = mclist; i < count; i++) {
+		mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
+		if (mac == NULL)
+			goto err_return;
+		bfa_q_qe_init(&mac->qe);
+		memcpy(mac->addr, mcaddr, ETH_ALEN);
+		list_add_tail(&mac->qe, &list_head);
+
+		mcaddr += ETH_ALEN;
+	}
+
+	/* Schedule for addition */
+	while (!list_empty(&list_head)) {
+		bfa_q_deq(&list_head, &qe);
+		mac = (struct bna_mac *)qe;
+		bfa_q_qe_init(&mac->qe);
+
+		skip = 0;
+
+		/* Skip if already added */
+		list_for_each(qe, &rxf->mcast_active_q) {
+			mac1 = (struct bna_mac *)qe;
+			if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) {
+				bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod,
+							mac);
+				skip = 1;
+				break;
+			}
+		}
+
+		if (skip)
+			continue;
+
+		/* Skip if pending addition */
+		list_for_each(qe, &rxf->mcast_pending_add_q) {
+			mac1 = (struct bna_mac *)qe;
+			if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) {
+				bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod,
+							mac);
+				skip = 1;
+				break;
+			}
+		}
+
+		if (skip)
+			continue;
+
+		need_hw_config = 1;
+		list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+	}
+
+	/**
+	 * Delete the entries that are in the pending_add_q but not
+	 * in the new list
+	 */
+	while (!list_empty(&rxf->mcast_pending_add_q)) {
+		bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
+		mac = (struct bna_mac *)qe;
+		bfa_q_qe_init(&mac->qe);
+		for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) {
+			if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) {
+				delete = 0;
+				break;
+			}
+			mcaddr += ETH_ALEN;
+		}
+		if (delete)
+			bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+		else
+			list_add_tail(&mac->qe, &list_head);
+	}
+	while (!list_empty(&list_head)) {
+		bfa_q_deq(&list_head, &qe);
+		mac = (struct bna_mac *)qe;
+		bfa_q_qe_init(&mac->qe);
+		list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+	}
+
+	/**
+	 * Schedule entries for deletion that are in the active_q but not
+	 * in the new list
+	 */
+	while (!list_empty(&rxf->mcast_active_q)) {
+		bfa_q_deq(&rxf->mcast_active_q, &qe);
+		mac = (struct bna_mac *)qe;
+		bfa_q_qe_init(&mac->qe);
+		for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) {
+			if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) {
+				delete = 0;
+				break;
+			}
+			mcaddr += ETH_ALEN;
+		}
+		if (delete) {
+			list_add_tail(&mac->qe, &rxf->mcast_pending_del_q);
+			need_hw_config = 1;
+		} else {
+			list_add_tail(&mac->qe, &list_head);
+		}
+	}
+	while (!list_empty(&list_head)) {
+		bfa_q_deq(&list_head, &qe);
+		mac = (struct bna_mac *)qe;
+		bfa_q_qe_init(&mac->qe);
+		list_add_tail(&mac->qe, &rxf->mcast_active_q);
+	}
+
+	if (need_hw_config) {
+		rxf->cam_fltr_cbfn = cbfn;
+		rxf->cam_fltr_cbarg = rx->bna->bnad;
+		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+	} else if (cbfn)
+		(*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
+
+	return BNA_CB_SUCCESS;
+
+err_return:
+	while (!list_empty(&list_head)) {
+		bfa_q_deq(&list_head, &qe);
+		mac = (struct bna_mac *)qe;
+		bfa_q_qe_init(&mac->qe);
+		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+	}
+
+	return BNA_CB_MCAST_LIST_FULL;
+}
+
+void
+bna_rx_vlan_add(struct bna_rx *rx, int vlan_id)
+{
+	struct bna_rxf *rxf = &rx->rxf;
+	int index = (vlan_id >> 5);
+	int bit = (1 << (vlan_id & 0x1F));
+
+	rxf->vlan_filter_table[index] |= bit;
+	if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
+		rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
+		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+	}
+}
+
+void
+bna_rx_vlan_del(struct bna_rx *rx, int vlan_id)
+{
+	struct bna_rxf *rxf = &rx->rxf;
+	int index = (vlan_id >> 5);
+	int bit = (1 << (vlan_id & 0x1F));
+
+	rxf->vlan_filter_table[index] &= ~bit;
+	if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
+		rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
+		bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+	}
+}
+
+/**
+ * RX
+ */
+#define	RXQ_RCB_INIT(q, rxp, qdepth, bna, _id, unmapq_mem)	do {	\
+	struct bna_doorbell_qset *_qset;				\
+	unsigned long off;						\
+	(q)->rcb->producer_index = (q)->rcb->consumer_index = 0;	\
+	(q)->rcb->q_depth = (qdepth);					\
+	(q)->rcb->unmap_q = unmapq_mem;					\
+	(q)->rcb->rxq = (q);						\
+	(q)->rcb->cq = &(rxp)->cq;					\
+	(q)->rcb->bnad = (bna)->bnad;					\
+	_qset = (struct bna_doorbell_qset *)0;			\
+	off = (unsigned long)&_qset[(q)->rxq_id].rxq[0];		\
+	(q)->rcb->q_dbell = off +					\
+		BNA_GET_DOORBELL_BASE_ADDR((bna)->pcidev.pci_bar_kva);	\
+	(q)->rcb->id = _id;						\
+} while (0)
+
+#define	BNA_GET_RXQS(qcfg)	(((qcfg)->rxp_type == BNA_RXP_SINGLE) ?	\
+	(qcfg)->num_paths : ((qcfg)->num_paths * 2))
+
+#define	SIZE_TO_PAGES(size)	(((size) >> PAGE_SHIFT) + ((((size) &\
+	(PAGE_SIZE - 1)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
+
+#define	call_rx_stop_callback(rx, status)				\
+	if ((rx)->stop_cbfn) {						\
+		(*(rx)->stop_cbfn)((rx)->stop_cbarg, rx, (status));	\
+		(rx)->stop_cbfn = NULL;					\
+		(rx)->stop_cbarg = NULL;				\
+	}
+
+/*
+ * Since rx_enable is synchronous callback, there is no start_cbfn required.
+ * Instead, we'll call bnad_rx_post(rxp) so that bnad can post the buffers
+ * for each rxpath.
+ */
+
+#define	call_rx_disable_cbfn(rx, status)				\
+		if ((rx)->disable_cbfn)	{				\
+			(*(rx)->disable_cbfn)((rx)->disable_cbarg,	\
+					status);			\
+			(rx)->disable_cbfn = NULL;			\
+			(rx)->disable_cbarg = NULL;			\
+		}							\
+
+#define	rxqs_reqd(type, num_rxqs)					\
+	(((type) == BNA_RXP_SINGLE) ? (num_rxqs) : ((num_rxqs) * 2))
+
+#define rx_ib_fail(rx)						\
+do {								\
+	struct bna_rxp *rxp;					\
+	struct list_head *qe;						\
+	list_for_each(qe, &(rx)->rxp_q) {				\
+		rxp = (struct bna_rxp *)qe;			\
+		bna_ib_fail(rxp->cq.ib);			\
+	}							\
+} while (0)
+
+static void __bna_multi_rxq_stop(struct bna_rxp *, u32 *);
+static void __bna_rxq_start(struct bna_rxq *rxq);
+static void __bna_cq_start(struct bna_cq *cq);
+static void bna_rit_create(struct bna_rx *rx);
+static void bna_rx_cb_multi_rxq_stopped(void *arg, int status);
+static void bna_rx_cb_rxq_stopped_all(void *arg);
+
+bfa_fsm_state_decl(bna_rx, stopped,
+	struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, rxf_start_wait,
+	struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, started,
+	struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, rxf_stop_wait,
+	struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, rxq_stop_wait,
+	struct bna_rx, enum bna_rx_event);
+
+static const struct bfa_sm_table rx_sm_table[] = {
+	{BFA_SM(bna_rx_sm_stopped), BNA_RX_STOPPED},
+	{BFA_SM(bna_rx_sm_rxf_start_wait), BNA_RX_RXF_START_WAIT},
+	{BFA_SM(bna_rx_sm_started), BNA_RX_STARTED},
+	{BFA_SM(bna_rx_sm_rxf_stop_wait), BNA_RX_RXF_STOP_WAIT},
+	{BFA_SM(bna_rx_sm_rxq_stop_wait), BNA_RX_RXQ_STOP_WAIT},
+};
+
+static void bna_rx_sm_stopped_entry(struct bna_rx *rx)
+{
+	struct bna_rxp *rxp;
+	struct list_head *qe_rxp;
+
+	list_for_each(qe_rxp, &rx->rxp_q) {
+		rxp = (struct bna_rxp *)qe_rxp;
+		rx->rx_cleanup_cbfn(rx->bna->bnad, rxp->cq.ccb);
+	}
+
+	call_rx_stop_callback(rx, BNA_CB_SUCCESS);
+}
+
+static void bna_rx_sm_stopped(struct bna_rx *rx,
+				enum bna_rx_event event)
+{
+	switch (event) {
+	case RX_E_START:
+		bfa_fsm_set_state(rx, bna_rx_sm_rxf_start_wait);
+		break;
+	case RX_E_STOP:
+		call_rx_stop_callback(rx, BNA_CB_SUCCESS);
+		break;
+	case RX_E_FAIL:
+		/* no-op */
+		break;
+	default:
+		bfa_sm_fault(rx->bna, event);
+		break;
+	}
+
+}
+
+static void bna_rx_sm_rxf_start_wait_entry(struct bna_rx *rx)
+{
+	struct bna_rxp *rxp;
+	struct list_head *qe_rxp;
+	struct bna_rxq *q0 = NULL, *q1 = NULL;
+
+	/* Setup the RIT */
+	bna_rit_create(rx);
+
+	list_for_each(qe_rxp, &rx->rxp_q) {
+		rxp = (struct bna_rxp *)qe_rxp;
+		bna_ib_start(rxp->cq.ib);
+		GET_RXQS(rxp, q0, q1);
+		q0->buffer_size = bna_port_mtu_get(&rx->bna->port);
+		__bna_rxq_start(q0);
+		rx->rx_post_cbfn(rx->bna->bnad, q0->rcb);
+		if (q1)  {
+			__bna_rxq_start(q1);
+			rx->rx_post_cbfn(rx->bna->bnad, q1->rcb);
+		}
+		__bna_cq_start(&rxp->cq);
+	}
+
+	bna_rxf_start(&rx->rxf);
+}
+
+static void bna_rx_sm_rxf_start_wait(struct bna_rx *rx,
+				enum bna_rx_event event)
+{
+	switch (event) {
+	case RX_E_STOP:
+		bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
+		break;
+	case RX_E_FAIL:
+		bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+		rx_ib_fail(rx);
+		bna_rxf_fail(&rx->rxf);
+		break;
+	case RX_E_RXF_STARTED:
+		bfa_fsm_set_state(rx, bna_rx_sm_started);
+		break;
+	default:
+		bfa_sm_fault(rx->bna, event);
+		break;
+	}
+}
+
+void
+bna_rx_sm_started_entry(struct bna_rx *rx)
+{
+	struct bna_rxp *rxp;
+	struct list_head *qe_rxp;
+
+	/* Start IB */
+	list_for_each(qe_rxp, &rx->rxp_q) {
+		rxp = (struct bna_rxp *)qe_rxp;
+		bna_ib_ack(&rxp->cq.ib->door_bell, 0);
+	}
+
+	bna_llport_admin_up(&rx->bna->port.llport);
+}
+
+void
+bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event)
+{
+	switch (event) {
+	case RX_E_FAIL:
+		bna_llport_admin_down(&rx->bna->port.llport);
+		bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+		rx_ib_fail(rx);
+		bna_rxf_fail(&rx->rxf);
+		break;
+	case RX_E_STOP:
+		bna_llport_admin_down(&rx->bna->port.llport);
+		bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
+		break;
+	default:
+		bfa_sm_fault(rx->bna, event);
+		break;
+	}
+}
+
+void
+bna_rx_sm_rxf_stop_wait_entry(struct bna_rx *rx)
+{
+	bna_rxf_stop(&rx->rxf);
+}
+
+void
+bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+	switch (event) {
+	case RX_E_RXF_STOPPED:
+		bfa_fsm_set_state(rx, bna_rx_sm_rxq_stop_wait);
+		break;
+	case RX_E_RXF_STARTED:
+		/**
+		 * RxF was in the process of starting up when
+		 * RXF_E_STOP was issued. Ignore this event
+		 */
+		break;
+	case RX_E_FAIL:
+		bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+		rx_ib_fail(rx);
+		bna_rxf_fail(&rx->rxf);
+		break;
+	default:
+		bfa_sm_fault(rx->bna, event);
+		break;
+	}
+
+}
+
+void
+bna_rx_sm_rxq_stop_wait_entry(struct bna_rx *rx)
+{
+	struct bna_rxp *rxp = NULL;
+	struct bna_rxq *q0 = NULL;
+	struct bna_rxq *q1 = NULL;
+	struct list_head	*qe;
+	u32 rxq_mask[2] = {0, 0};
+
+	/* Only one call to multi-rxq-stop for all RXPs in this RX */
+	bfa_wc_up(&rx->rxq_stop_wc);
+	list_for_each(qe, &rx->rxp_q) {
+		rxp = (struct bna_rxp *)qe;
+		GET_RXQS(rxp, q0, q1);
+		if (q0->rxq_id < 32)
+			rxq_mask[0] |= ((u32)1 << q0->rxq_id);
+		else
+			rxq_mask[1] |= ((u32)1 << (q0->rxq_id - 32));
+		if (q1) {
+			if (q1->rxq_id < 32)
+				rxq_mask[0] |= ((u32)1 << q1->rxq_id);
+			else
+				rxq_mask[1] |= ((u32)
+						1 << (q1->rxq_id - 32));
+		}
+	}
+
+	__bna_multi_rxq_stop(rxp, rxq_mask);
+}
+
+void
+bna_rx_sm_rxq_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+	struct bna_rxp *rxp = NULL;
+	struct list_head	*qe;
+
+	switch (event) {
+	case RX_E_RXQ_STOPPED:
+		list_for_each(qe, &rx->rxp_q) {
+			rxp = (struct bna_rxp *)qe;
+			bna_ib_stop(rxp->cq.ib);
+		}
+		/* Fall through */
+	case RX_E_FAIL:
+		bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+		break;
+	default:
+		bfa_sm_fault(rx->bna, event);
+		break;
+	}
+}
+
+void
+__bna_multi_rxq_stop(struct bna_rxp *rxp, u32 * rxq_id_mask)
+{
+	struct bfi_ll_q_stop_req ll_req;
+
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RXQ_STOP_REQ, 0);
+	ll_req.q_id_mask[0] = htonl(rxq_id_mask[0]);
+	ll_req.q_id_mask[1] = htonl(rxq_id_mask[1]);
+	bna_mbox_qe_fill(&rxp->mbox_qe, &ll_req, sizeof(ll_req),
+		bna_rx_cb_multi_rxq_stopped, rxp);
+	bna_mbox_send(rxp->rx->bna, &rxp->mbox_qe);
+}
+
+void
+__bna_rxq_start(struct bna_rxq *rxq)
+{
+	struct bna_rxtx_q_mem *q_mem;
+	struct bna_rxq_mem rxq_cfg, *rxq_mem;
+	struct bna_dma_addr cur_q_addr;
+	/* struct bna_doorbell_qset *qset; */
+	struct bna_qpt *qpt;
+	u32 pg_num;
+	struct bna *bna = rxq->rx->bna;
+	void __iomem *base_addr;
+	unsigned long off;
+
+	qpt = &rxq->qpt;
+	cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
+
+	rxq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
+	rxq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
+	rxq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
+	rxq_cfg.cur_q_entry_hi = cur_q_addr.msb;
+
+	rxq_cfg.pg_cnt_n_prd_ptr = ((u32)qpt->page_count << 16) | 0x0;
+	rxq_cfg.entry_n_pg_size = ((u32)(BFI_RXQ_WI_SIZE >> 2) << 16) |
+		(qpt->page_size >> 2);
+	rxq_cfg.sg_n_cq_n_cns_ptr =
+		((u32)(rxq->rxp->cq.cq_id & 0xff) << 16) | 0x0;
+	rxq_cfg.buf_sz_n_q_state = ((u32)rxq->buffer_size << 16) |
+		BNA_Q_IDLE_STATE;
+	rxq_cfg.next_qid = 0x0 | (0x3 << 8);
+
+	/* Write the page number register */
+	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num,
+			HQM_RXTX_Q_RAM_BASE_OFFSET);
+	writel(pg_num, bna->regs.page_addr);
+
+	/* Write to h/w */
+	base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
+					HQM_RXTX_Q_RAM_BASE_OFFSET);
+
+	q_mem = (struct bna_rxtx_q_mem *)0;
+	rxq_mem = &q_mem[rxq->rxq_id].rxq;
+
+	off = (unsigned long)&rxq_mem->pg_tbl_addr_lo;
+	writel(htonl(rxq_cfg.pg_tbl_addr_lo), base_addr + off);
+
+	off = (unsigned long)&rxq_mem->pg_tbl_addr_hi;
+	writel(htonl(rxq_cfg.pg_tbl_addr_hi), base_addr + off);
+
+	off = (unsigned long)&rxq_mem->cur_q_entry_lo;
+	writel(htonl(rxq_cfg.cur_q_entry_lo), base_addr + off);
+
+	off = (unsigned long)&rxq_mem->cur_q_entry_hi;
+	writel(htonl(rxq_cfg.cur_q_entry_hi), base_addr + off);
+
+	off = (unsigned long)&rxq_mem->pg_cnt_n_prd_ptr;
+	writel(rxq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
+
+	off = (unsigned long)&rxq_mem->entry_n_pg_size;
+	writel(rxq_cfg.entry_n_pg_size, base_addr + off);
+
+	off = (unsigned long)&rxq_mem->sg_n_cq_n_cns_ptr;
+	writel(rxq_cfg.sg_n_cq_n_cns_ptr, base_addr + off);
+
+	off = (unsigned long)&rxq_mem->buf_sz_n_q_state;
+	writel(rxq_cfg.buf_sz_n_q_state, base_addr + off);
+
+	off = (unsigned long)&rxq_mem->next_qid;
+	writel(rxq_cfg.next_qid, base_addr + off);
+
+	rxq->rcb->producer_index = 0;
+	rxq->rcb->consumer_index = 0;
+}
+
+void
+__bna_cq_start(struct bna_cq *cq)
+{
+	struct bna_cq_mem cq_cfg, *cq_mem;
+	const struct bna_qpt *qpt;
+	struct bna_dma_addr cur_q_addr;
+	u32 pg_num;
+	struct bna *bna = cq->rx->bna;
+	void __iomem *base_addr;
+	unsigned long off;
+
+	qpt = &cq->qpt;
+	cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
+
+	/*
+	 * Fill out structure, to be subsequently written
+	 * to hardware
+	 */
+	cq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
+	cq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
+	cq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
+	cq_cfg.cur_q_entry_hi = cur_q_addr.msb;
+
+	cq_cfg.pg_cnt_n_prd_ptr = (qpt->page_count << 16) | 0x0;
+	cq_cfg.entry_n_pg_size =
+		((u32)(BFI_CQ_WI_SIZE >> 2) << 16) | (qpt->page_size >> 2);
+	cq_cfg.int_blk_n_cns_ptr = ((((u32)cq->ib_seg_offset) << 24) |
+			((u32)(cq->ib->ib_id & 0xff)  << 16) | 0x0);
+	cq_cfg.q_state = BNA_Q_IDLE_STATE;
+
+	/* Write the page number register */
+	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num,
+				  HQM_CQ_RAM_BASE_OFFSET);
+
+	writel(pg_num, bna->regs.page_addr);
+
+	/* H/W write */
+	base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
+					HQM_CQ_RAM_BASE_OFFSET);
+
+	cq_mem = (struct bna_cq_mem *)0;
+
+	off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_lo;
+	writel(htonl(cq_cfg.pg_tbl_addr_lo), base_addr + off);
+
+	off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_hi;
+	writel(htonl(cq_cfg.pg_tbl_addr_hi), base_addr + off);
+
+	off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_lo;
+	writel(htonl(cq_cfg.cur_q_entry_lo), base_addr + off);
+
+	off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_hi;
+	writel(htonl(cq_cfg.cur_q_entry_hi), base_addr + off);
+
+	off = (unsigned long)&cq_mem[cq->cq_id].pg_cnt_n_prd_ptr;
+	writel(cq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
+
+	off = (unsigned long)&cq_mem[cq->cq_id].entry_n_pg_size;
+	writel(cq_cfg.entry_n_pg_size, base_addr + off);
+
+	off = (unsigned long)&cq_mem[cq->cq_id].int_blk_n_cns_ptr;
+	writel(cq_cfg.int_blk_n_cns_ptr, base_addr + off);
+
+	off = (unsigned long)&cq_mem[cq->cq_id].q_state;
+	writel(cq_cfg.q_state, base_addr + off);
+
+	cq->ccb->producer_index = 0;
+	*(cq->ccb->hw_producer_index) = 0;
+}
+
+void
+bna_rit_create(struct bna_rx *rx)
+{
+	struct list_head	*qe_rxp;
+	struct bna *bna;
+	struct bna_rxp *rxp;
+	struct bna_rxq *q0 = NULL;
+	struct bna_rxq *q1 = NULL;
+	int offset;
+
+	bna = rx->bna;
+
+	offset = 0;
+	list_for_each(qe_rxp, &rx->rxp_q) {
+		rxp = (struct bna_rxp *)qe_rxp;
+		GET_RXQS(rxp, q0, q1);
+		rx->rxf.rit_segment->rit[offset].large_rxq_id = q0->rxq_id;
+		rx->rxf.rit_segment->rit[offset].small_rxq_id =
+						(q1 ? q1->rxq_id : 0);
+		offset++;
+	}
+}
+
+static int
+_rx_can_satisfy(struct bna_rx_mod *rx_mod,
+		struct bna_rx_config *rx_cfg)
+{
+	if ((rx_mod->rx_free_count == 0) ||
+		(rx_mod->rxp_free_count == 0) ||
+		(rx_mod->rxq_free_count == 0))
+		return 0;
+
+	if (rx_cfg->rxp_type == BNA_RXP_SINGLE) {
+		if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
+			(rx_mod->rxq_free_count < rx_cfg->num_paths))
+				return 0;
+	} else {
+		if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
+			(rx_mod->rxq_free_count < (2 * rx_cfg->num_paths)))
+			return 0;
+	}
+
+	if (!bna_rit_mod_can_satisfy(&rx_mod->bna->rit_mod, rx_cfg->num_paths))
+		return 0;
+
+	return 1;
+}
+
+static struct bna_rxq *
+_get_free_rxq(struct bna_rx_mod *rx_mod)
+{
+	struct bna_rxq *rxq = NULL;
+	struct list_head	*qe = NULL;
+
+	bfa_q_deq(&rx_mod->rxq_free_q, &qe);
+	if (qe) {
+		rx_mod->rxq_free_count--;
+		rxq = (struct bna_rxq *)qe;
+	}
+	return rxq;
+}
+
+static void
+_put_free_rxq(struct bna_rx_mod *rx_mod, struct bna_rxq *rxq)
+{
+	bfa_q_qe_init(&rxq->qe);
+	list_add_tail(&rxq->qe, &rx_mod->rxq_free_q);
+	rx_mod->rxq_free_count++;
+}
+
+static struct bna_rxp *
+_get_free_rxp(struct bna_rx_mod *rx_mod)
+{
+	struct list_head	*qe = NULL;
+	struct bna_rxp *rxp = NULL;
+
+	bfa_q_deq(&rx_mod->rxp_free_q, &qe);
+	if (qe) {
+		rx_mod->rxp_free_count--;
+
+		rxp = (struct bna_rxp *)qe;
+	}
+
+	return rxp;
+}
+
+static void
+_put_free_rxp(struct bna_rx_mod *rx_mod, struct bna_rxp *rxp)
+{
+	bfa_q_qe_init(&rxp->qe);
+	list_add_tail(&rxp->qe, &rx_mod->rxp_free_q);
+	rx_mod->rxp_free_count++;
+}
+
+static struct bna_rx *
+_get_free_rx(struct bna_rx_mod *rx_mod)
+{
+	struct list_head	*qe = NULL;
+	struct bna_rx *rx = NULL;
+
+	bfa_q_deq(&rx_mod->rx_free_q, &qe);
+	if (qe) {
+		rx_mod->rx_free_count--;
+
+		rx = (struct bna_rx *)qe;
+		bfa_q_qe_init(qe);
+		list_add_tail(&rx->qe, &rx_mod->rx_active_q);
+	}
+
+	return rx;
+}
+
+static void
+_put_free_rx(struct bna_rx_mod *rx_mod, struct bna_rx *rx)
+{
+	bfa_q_qe_init(&rx->qe);
+	list_add_tail(&rx->qe, &rx_mod->rx_free_q);
+	rx_mod->rx_free_count++;
+}
+
+static void
+_rx_init(struct bna_rx *rx, struct bna *bna)
+{
+	rx->bna = bna;
+	rx->rx_flags = 0;
+
+	INIT_LIST_HEAD(&rx->rxp_q);
+
+	rx->rxq_stop_wc.wc_resume = bna_rx_cb_rxq_stopped_all;
+	rx->rxq_stop_wc.wc_cbarg = rx;
+	rx->rxq_stop_wc.wc_count = 0;
+
+	rx->stop_cbfn = NULL;
+	rx->stop_cbarg = NULL;
+}
+
+static void
+_rxp_add_rxqs(struct bna_rxp *rxp,
+		struct bna_rxq *q0,
+		struct bna_rxq *q1)
+{
+	switch (rxp->type) {
+	case BNA_RXP_SINGLE:
+		rxp->rxq.single.only = q0;
+		rxp->rxq.single.reserved = NULL;
+		break;
+	case BNA_RXP_SLR:
+		rxp->rxq.slr.large = q0;
+		rxp->rxq.slr.small = q1;
+		break;
+	case BNA_RXP_HDS:
+		rxp->rxq.hds.data = q0;
+		rxp->rxq.hds.hdr = q1;
+		break;
+	default:
+		break;
+	}
+}
+
+static void
+_rxq_qpt_init(struct bna_rxq *rxq,
+		struct bna_rxp *rxp,
+		u32 page_count,
+		u32 page_size,
+		struct bna_mem_descr *qpt_mem,
+		struct bna_mem_descr *swqpt_mem,
+		struct bna_mem_descr *page_mem)
+{
+	int	i;
+
+	rxq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+	rxq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+	rxq->qpt.kv_qpt_ptr = qpt_mem->kva;
+	rxq->qpt.page_count = page_count;
+	rxq->qpt.page_size = page_size;
+
+	rxq->rcb->sw_qpt = (void **) swqpt_mem->kva;
+
+	for (i = 0; i < rxq->qpt.page_count; i++) {
+		rxq->rcb->sw_qpt[i] = page_mem[i].kva;
+		((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].lsb =
+			page_mem[i].dma.lsb;
+		((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].msb =
+			page_mem[i].dma.msb;
+
+	}
+}
+
+static void
+_rxp_cqpt_setup(struct bna_rxp *rxp,
+		u32 page_count,
+		u32 page_size,
+		struct bna_mem_descr *qpt_mem,
+		struct bna_mem_descr *swqpt_mem,
+		struct bna_mem_descr *page_mem)
+{
+	int	i;
+
+	rxp->cq.qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+	rxp->cq.qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+	rxp->cq.qpt.kv_qpt_ptr = qpt_mem->kva;
+	rxp->cq.qpt.page_count = page_count;
+	rxp->cq.qpt.page_size = page_size;
+
+	rxp->cq.ccb->sw_qpt = (void **) swqpt_mem->kva;
+
+	for (i = 0; i < rxp->cq.qpt.page_count; i++) {
+		rxp->cq.ccb->sw_qpt[i] = page_mem[i].kva;
+
+		((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].lsb =
+			page_mem[i].dma.lsb;
+		((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].msb =
+			page_mem[i].dma.msb;
+
+	}
+}
+
+static void
+_rx_add_rxp(struct bna_rx *rx, struct bna_rxp *rxp)
+{
+	list_add_tail(&rxp->qe, &rx->rxp_q);
+}
+
+static void
+_init_rxmod_queues(struct bna_rx_mod *rx_mod)
+{
+	INIT_LIST_HEAD(&rx_mod->rx_free_q);
+	INIT_LIST_HEAD(&rx_mod->rxq_free_q);
+	INIT_LIST_HEAD(&rx_mod->rxp_free_q);
+	INIT_LIST_HEAD(&rx_mod->rx_active_q);
+
+	rx_mod->rx_free_count = 0;
+	rx_mod->rxq_free_count = 0;
+	rx_mod->rxp_free_count = 0;
+}
+
+static void
+_rx_ctor(struct bna_rx *rx, int id)
+{
+	bfa_q_qe_init(&rx->qe);
+	INIT_LIST_HEAD(&rx->rxp_q);
+	rx->bna = NULL;
+
+	rx->rxf.rxf_id = id;
+
+	/* FIXME: mbox_qe ctor()?? */
+	bfa_q_qe_init(&rx->mbox_qe.qe);
+
+	rx->stop_cbfn = NULL;
+	rx->stop_cbarg = NULL;
+}
+
+void
+bna_rx_cb_multi_rxq_stopped(void *arg, int status)
+{
+	struct bna_rxp *rxp = (struct bna_rxp *)arg;
+
+	bfa_wc_down(&rxp->rx->rxq_stop_wc);
+}
+
+void
+bna_rx_cb_rxq_stopped_all(void *arg)
+{
+	struct bna_rx *rx = (struct bna_rx *)arg;
+
+	bfa_fsm_send_event(rx, RX_E_RXQ_STOPPED);
+}
+
+static void
+bna_rx_mod_cb_rx_stopped(void *arg, struct bna_rx *rx,
+			 enum bna_cb_status status)
+{
+	struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
+
+	bfa_wc_down(&rx_mod->rx_stop_wc);
+}
+
+static void
+bna_rx_mod_cb_rx_stopped_all(void *arg)
+{
+	struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
+
+	if (rx_mod->stop_cbfn)
+		rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS);
+	rx_mod->stop_cbfn = NULL;
+}
+
+static void
+bna_rx_start(struct bna_rx *rx)
+{
+	rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
+	if (rx->rx_flags & BNA_RX_F_ENABLE)
+		bfa_fsm_send_event(rx, RX_E_START);
+}
+
+static void
+bna_rx_stop(struct bna_rx *rx)
+{
+	rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED;
+	if (rx->fsm == (bfa_fsm_t) bna_rx_sm_stopped)
+		bna_rx_mod_cb_rx_stopped(&rx->bna->rx_mod, rx, BNA_CB_SUCCESS);
+	else {
+		rx->stop_cbfn = bna_rx_mod_cb_rx_stopped;
+		rx->stop_cbarg = &rx->bna->rx_mod;
+		bfa_fsm_send_event(rx, RX_E_STOP);
+	}
+}
+
+static void
+bna_rx_fail(struct bna_rx *rx)
+{
+	/* Indicate port is not enabled, and failed */
+	rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED;
+	rx->rx_flags |= BNA_RX_F_PORT_FAILED;
+	bfa_fsm_send_event(rx, RX_E_FAIL);
+}
+
+void
+bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
+{
+	struct bna_rx *rx;
+	struct list_head *qe;
+
+	rx_mod->flags |= BNA_RX_MOD_F_PORT_STARTED;
+	if (type == BNA_RX_T_LOOPBACK)
+		rx_mod->flags |= BNA_RX_MOD_F_PORT_LOOPBACK;
+
+	list_for_each(qe, &rx_mod->rx_active_q) {
+		rx = (struct bna_rx *)qe;
+		if (rx->type == type)
+			bna_rx_start(rx);
+	}
+}
+
+void
+bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
+{
+	struct bna_rx *rx;
+	struct list_head *qe;
+
+	rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED;
+	rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK;
+
+	rx_mod->stop_cbfn = bna_port_cb_rx_stopped;
+
+	/**
+	 * Before calling bna_rx_stop(), increment rx_stop_wc as many times
+	 * as we are going to call bna_rx_stop
+	 */
+	list_for_each(qe, &rx_mod->rx_active_q) {
+		rx = (struct bna_rx *)qe;
+		if (rx->type == type)
+			bfa_wc_up(&rx_mod->rx_stop_wc);
+	}
+
+	if (rx_mod->rx_stop_wc.wc_count == 0) {
+		rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS);
+		rx_mod->stop_cbfn = NULL;
+		return;
+	}
+
+	list_for_each(qe, &rx_mod->rx_active_q) {
+		rx = (struct bna_rx *)qe;
+		if (rx->type == type)
+			bna_rx_stop(rx);
+	}
+}
+
+void
+bna_rx_mod_fail(struct bna_rx_mod *rx_mod)
+{
+	struct bna_rx *rx;
+	struct list_head *qe;
+
+	rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED;
+	rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK;
+
+	list_for_each(qe, &rx_mod->rx_active_q) {
+		rx = (struct bna_rx *)qe;
+		bna_rx_fail(rx);
+	}
+}
+
+void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
+			struct bna_res_info *res_info)
+{
+	int	index;
+	struct bna_rx *rx_ptr;
+	struct bna_rxp *rxp_ptr;
+	struct bna_rxq *rxq_ptr;
+
+	rx_mod->bna = bna;
+	rx_mod->flags = 0;
+
+	rx_mod->rx = (struct bna_rx *)
+		res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mdl[0].kva;
+	rx_mod->rxp = (struct bna_rxp *)
+		res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mdl[0].kva;
+	rx_mod->rxq = (struct bna_rxq *)
+		res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mdl[0].kva;
+
+	/* Initialize the queues */
+	_init_rxmod_queues(rx_mod);
+
+	/* Build RX queues */
+	for (index = 0; index < BFI_MAX_RXQ; index++) {
+		rx_ptr = &rx_mod->rx[index];
+		_rx_ctor(rx_ptr, index);
+		list_add_tail(&rx_ptr->qe, &rx_mod->rx_free_q);
+		rx_mod->rx_free_count++;
+	}
+
+	/* build RX-path queue */
+	for (index = 0; index < BFI_MAX_RXQ; index++) {
+		rxp_ptr = &rx_mod->rxp[index];
+		rxp_ptr->cq.cq_id = index;
+		bfa_q_qe_init(&rxp_ptr->qe);
+		list_add_tail(&rxp_ptr->qe, &rx_mod->rxp_free_q);
+		rx_mod->rxp_free_count++;
+	}
+
+	/* build RXQ queue */
+	for (index = 0; index < BFI_MAX_RXQ; index++) {
+		rxq_ptr = &rx_mod->rxq[index];
+		rxq_ptr->rxq_id = index;
+
+		bfa_q_qe_init(&rxq_ptr->qe);
+		list_add_tail(&rxq_ptr->qe, &rx_mod->rxq_free_q);
+		rx_mod->rxq_free_count++;
+	}
+
+	rx_mod->rx_stop_wc.wc_resume = bna_rx_mod_cb_rx_stopped_all;
+	rx_mod->rx_stop_wc.wc_cbarg = rx_mod;
+	rx_mod->rx_stop_wc.wc_count = 0;
+}
+
+void
+bna_rx_mod_uninit(struct bna_rx_mod *rx_mod)
+{
+	struct list_head		*qe;
+	int i;
+
+	i = 0;
+	list_for_each(qe, &rx_mod->rx_free_q)
+		i++;
+
+	i = 0;
+	list_for_each(qe, &rx_mod->rxp_free_q)
+		i++;
+
+	i = 0;
+	list_for_each(qe, &rx_mod->rxq_free_q)
+		i++;
+
+	rx_mod->bna = NULL;
+}
+
+int
+bna_rx_state_get(struct bna_rx *rx)
+{
+	return bfa_sm_to_state(rx_sm_table, rx->fsm);
+}
+
+void
+bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info)
+{
+	u32 cq_size, hq_size, dq_size;
+	u32 cpage_count, hpage_count, dpage_count;
+	struct bna_mem_info *mem_info;
+	u32 cq_depth;
+	u32 hq_depth;
+	u32 dq_depth;
+
+	dq_depth = q_cfg->q_depth;
+	hq_depth = ((q_cfg->rxp_type == BNA_RXP_SINGLE) ? 0 : q_cfg->q_depth);
+	cq_depth = dq_depth + hq_depth;
+
+	BNA_TO_POWER_OF_2_HIGH(cq_depth);
+	cq_size = cq_depth * BFI_CQ_WI_SIZE;
+	cq_size = ALIGN(cq_size, PAGE_SIZE);
+	cpage_count = SIZE_TO_PAGES(cq_size);
+
+	BNA_TO_POWER_OF_2_HIGH(dq_depth);
+	dq_size = dq_depth * BFI_RXQ_WI_SIZE;
+	dq_size = ALIGN(dq_size, PAGE_SIZE);
+	dpage_count = SIZE_TO_PAGES(dq_size);
+
+	if (BNA_RXP_SINGLE != q_cfg->rxp_type) {
+		BNA_TO_POWER_OF_2_HIGH(hq_depth);
+		hq_size = hq_depth * BFI_RXQ_WI_SIZE;
+		hq_size = ALIGN(hq_size, PAGE_SIZE);
+		hpage_count = SIZE_TO_PAGES(hq_size);
+	} else {
+		hpage_count = 0;
+	}
+
+	/* CCB structures */
+	res_info[BNA_RX_RES_MEM_T_CCB].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_KVA;
+	mem_info->len = sizeof(struct bna_ccb);
+	mem_info->num = q_cfg->num_paths;
+
+	/* RCB structures */
+	res_info[BNA_RX_RES_MEM_T_RCB].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_KVA;
+	mem_info->len = sizeof(struct bna_rcb);
+	mem_info->num = BNA_GET_RXQS(q_cfg);
+
+	/* Completion QPT */
+	res_info[BNA_RX_RES_MEM_T_CQPT].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_DMA;
+	mem_info->len = cpage_count * sizeof(struct bna_dma_addr);
+	mem_info->num = q_cfg->num_paths;
+
+	/* Completion s/w QPT */
+	res_info[BNA_RX_RES_MEM_T_CSWQPT].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_KVA;
+	mem_info->len = cpage_count * sizeof(void *);
+	mem_info->num = q_cfg->num_paths;
+
+	/* Completion QPT pages */
+	res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_DMA;
+	mem_info->len = PAGE_SIZE;
+	mem_info->num = cpage_count * q_cfg->num_paths;
+
+	/* Data QPTs */
+	res_info[BNA_RX_RES_MEM_T_DQPT].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_DMA;
+	mem_info->len = dpage_count * sizeof(struct bna_dma_addr);
+	mem_info->num = q_cfg->num_paths;
+
+	/* Data s/w QPTs */
+	res_info[BNA_RX_RES_MEM_T_DSWQPT].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_KVA;
+	mem_info->len = dpage_count * sizeof(void *);
+	mem_info->num = q_cfg->num_paths;
+
+	/* Data QPT pages */
+	res_info[BNA_RX_RES_MEM_T_DPAGE].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_DMA;
+	mem_info->len = PAGE_SIZE;
+	mem_info->num = dpage_count * q_cfg->num_paths;
+
+	/* Hdr QPTs */
+	res_info[BNA_RX_RES_MEM_T_HQPT].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_DMA;
+	mem_info->len = hpage_count * sizeof(struct bna_dma_addr);
+	mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
+
+	/* Hdr s/w QPTs */
+	res_info[BNA_RX_RES_MEM_T_HSWQPT].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_KVA;
+	mem_info->len = hpage_count * sizeof(void *);
+	mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
+
+	/* Hdr QPT pages */
+	res_info[BNA_RX_RES_MEM_T_HPAGE].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_DMA;
+	mem_info->len = (hpage_count ? PAGE_SIZE : 0);
+	mem_info->num = (hpage_count ? (hpage_count * q_cfg->num_paths) : 0);
+
+	/* RX Interrupts */
+	res_info[BNA_RX_RES_T_INTR].res_type = BNA_RES_T_INTR;
+	res_info[BNA_RX_RES_T_INTR].res_u.intr_info.intr_type = BNA_INTR_T_MSIX;
+	res_info[BNA_RX_RES_T_INTR].res_u.intr_info.num = q_cfg->num_paths;
+}
+
+struct bna_rx *
+bna_rx_create(struct bna *bna, struct bnad *bnad,
+		struct bna_rx_config *rx_cfg,
+		struct bna_rx_event_cbfn *rx_cbfn,
+		struct bna_res_info *res_info,
+		void *priv)
+{
+	struct bna_rx_mod *rx_mod = &bna->rx_mod;
+	struct bna_rx *rx;
+	struct bna_rxp *rxp;
+	struct bna_rxq *q0;
+	struct bna_rxq *q1;
+	struct bna_intr_info *intr_info;
+	u32 page_count;
+	struct bna_mem_descr *ccb_mem;
+	struct bna_mem_descr *rcb_mem;
+	struct bna_mem_descr *unmapq_mem;
+	struct bna_mem_descr *cqpt_mem;
+	struct bna_mem_descr *cswqpt_mem;
+	struct bna_mem_descr *cpage_mem;
+	struct bna_mem_descr *hqpt_mem;	/* Header/Small Q qpt */
+	struct bna_mem_descr *dqpt_mem;	/* Data/Large Q qpt */
+	struct bna_mem_descr *hsqpt_mem;	/* s/w qpt for hdr */
+	struct bna_mem_descr *dsqpt_mem;	/* s/w qpt for data */
+	struct bna_mem_descr *hpage_mem;	/* hdr page mem */
+	struct bna_mem_descr *dpage_mem;	/* data page mem */
+	int i, cpage_idx = 0, dpage_idx = 0, hpage_idx = 0, ret;
+	int dpage_count, hpage_count, rcb_idx;
+	struct bna_ib_config ibcfg;
+	/* Fail if we don't have enough RXPs, RXQs */
+	if (!_rx_can_satisfy(rx_mod, rx_cfg))
+		return NULL;
+
+	/* Initialize resource pointers */
+	intr_info = &res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
+	ccb_mem = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info.mdl[0];
+	rcb_mem = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info.mdl[0];
+	unmapq_mem = &res_info[BNA_RX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[0];
+	cqpt_mem = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info.mdl[0];
+	cswqpt_mem = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info.mdl[0];
+	cpage_mem = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.mdl[0];
+	hqpt_mem = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info.mdl[0];
+	dqpt_mem = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info.mdl[0];
+	hsqpt_mem = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info.mdl[0];
+	dsqpt_mem = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info.mdl[0];
+	hpage_mem = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.mdl[0];
+	dpage_mem = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.mdl[0];
+
+	/* Compute q depth & page count */
+	page_count = res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.num /
+			rx_cfg->num_paths;
+
+	dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.num /
+			rx_cfg->num_paths;
+
+	hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.num /
+			rx_cfg->num_paths;
+	/* Get RX pointer */
+	rx = _get_free_rx(rx_mod);
+	_rx_init(rx, bna);
+	rx->priv = priv;
+	rx->type = rx_cfg->rx_type;
+
+	rx->rcb_setup_cbfn = rx_cbfn->rcb_setup_cbfn;
+	rx->rcb_destroy_cbfn = rx_cbfn->rcb_destroy_cbfn;
+	rx->ccb_setup_cbfn = rx_cbfn->ccb_setup_cbfn;
+	rx->ccb_destroy_cbfn = rx_cbfn->ccb_destroy_cbfn;
+	/* Following callbacks are mandatory */
+	rx->rx_cleanup_cbfn = rx_cbfn->rx_cleanup_cbfn;
+	rx->rx_post_cbfn = rx_cbfn->rx_post_cbfn;
+
+	if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_STARTED) {
+		switch (rx->type) {
+		case BNA_RX_T_REGULAR:
+			if (!(rx->bna->rx_mod.flags &
+				BNA_RX_MOD_F_PORT_LOOPBACK))
+				rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
+			break;
+		case BNA_RX_T_LOOPBACK:
+			if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_LOOPBACK)
+				rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
+			break;
+		}
+	}
+
+	for (i = 0, rcb_idx = 0; i < rx_cfg->num_paths; i++) {
+		rxp = _get_free_rxp(rx_mod);
+		rxp->type = rx_cfg->rxp_type;
+		rxp->rx = rx;
+		rxp->cq.rx = rx;
+
+		/* Get required RXQs, and queue them to rx-path */
+		q0 = _get_free_rxq(rx_mod);
+		if (BNA_RXP_SINGLE == rx_cfg->rxp_type)
+			q1 = NULL;
+		else
+			q1 = _get_free_rxq(rx_mod);
+
+		/* Initialize IB */
+		if (1 == intr_info->num) {
+			rxp->cq.ib = bna_ib_get(&bna->ib_mod,
+					intr_info->intr_type,
+					intr_info->idl[0].vector);
+			rxp->vector = intr_info->idl[0].vector;
+		} else {
+			rxp->cq.ib = bna_ib_get(&bna->ib_mod,
+					intr_info->intr_type,
+					intr_info->idl[i].vector);
+
+			/* Map the MSI-x vector used for this RXP */
+			rxp->vector = intr_info->idl[i].vector;
+		}
+
+		rxp->cq.ib_seg_offset = bna_ib_reserve_idx(rxp->cq.ib);
+
+		ibcfg.coalescing_timeo = BFI_RX_COALESCING_TIMEO;
+		ibcfg.interpkt_count = BFI_RX_INTERPKT_COUNT;
+		ibcfg.interpkt_timeo = BFI_RX_INTERPKT_TIMEO;
+		ibcfg.ctrl_flags = BFI_IB_CF_INT_ENABLE;
+
+		ret = bna_ib_config(rxp->cq.ib, &ibcfg);
+
+		/* Link rxqs to rxp */
+		_rxp_add_rxqs(rxp, q0, q1);
+
+		/* Link rxp to rx */
+		_rx_add_rxp(rx, rxp);
+
+		q0->rx = rx;
+		q0->rxp = rxp;
+
+		/* Initialize RCB for the large / data q */
+		q0->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
+		RXQ_RCB_INIT(q0, rxp, rx_cfg->q_depth, bna, 0,
+			(void *)unmapq_mem[rcb_idx].kva);
+		rcb_idx++;
+		(q0)->rx_packets = (q0)->rx_bytes = 0;
+		(q0)->rx_packets_with_error = (q0)->rxbuf_alloc_failed = 0;
+
+		/* Initialize RXQs */
+		_rxq_qpt_init(q0, rxp, dpage_count, PAGE_SIZE,
+			&dqpt_mem[i], &dsqpt_mem[i], &dpage_mem[dpage_idx]);
+		q0->rcb->page_idx = dpage_idx;
+		q0->rcb->page_count = dpage_count;
+		dpage_idx += dpage_count;
+
+		/* Call bnad to complete rcb setup */
+		if (rx->rcb_setup_cbfn)
+			rx->rcb_setup_cbfn(bnad, q0->rcb);
+
+		if (q1) {
+			q1->rx = rx;
+			q1->rxp = rxp;
+
+			q1->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
+			RXQ_RCB_INIT(q1, rxp, rx_cfg->q_depth, bna, 1,
+				(void *)unmapq_mem[rcb_idx].kva);
+			rcb_idx++;
+			(q1)->buffer_size = (rx_cfg)->small_buff_size;
+			(q1)->rx_packets = (q1)->rx_bytes = 0;
+			(q1)->rx_packets_with_error =
+				(q1)->rxbuf_alloc_failed = 0;
+
+			_rxq_qpt_init(q1, rxp, hpage_count, PAGE_SIZE,
+				&hqpt_mem[i], &hsqpt_mem[i],
+				&hpage_mem[hpage_idx]);
+			q1->rcb->page_idx = hpage_idx;
+			q1->rcb->page_count = hpage_count;
+			hpage_idx += hpage_count;
+
+			/* Call bnad to complete rcb setup */
+			if (rx->rcb_setup_cbfn)
+				rx->rcb_setup_cbfn(bnad, q1->rcb);
+		}
+		/* Setup RXP::CQ */
+		rxp->cq.ccb = (struct bna_ccb *) ccb_mem[i].kva;
+		_rxp_cqpt_setup(rxp, page_count, PAGE_SIZE,
+			&cqpt_mem[i], &cswqpt_mem[i], &cpage_mem[cpage_idx]);
+		rxp->cq.ccb->page_idx = cpage_idx;
+		rxp->cq.ccb->page_count = page_count;
+		cpage_idx += page_count;
+
+		rxp->cq.ccb->pkt_rate.small_pkt_cnt = 0;
+		rxp->cq.ccb->pkt_rate.large_pkt_cnt = 0;
+
+		rxp->cq.ccb->producer_index = 0;
+		rxp->cq.ccb->q_depth =	rx_cfg->q_depth +
+					((rx_cfg->rxp_type == BNA_RXP_SINGLE) ?
+					0 : rx_cfg->q_depth);
+		rxp->cq.ccb->i_dbell = &rxp->cq.ib->door_bell;
+		rxp->cq.ccb->rcb[0] = q0->rcb;
+		if (q1)
+			rxp->cq.ccb->rcb[1] = q1->rcb;
+		rxp->cq.ccb->cq = &rxp->cq;
+		rxp->cq.ccb->bnad = bna->bnad;
+		rxp->cq.ccb->hw_producer_index =
+			((volatile u32 *)rxp->cq.ib->ib_seg_host_addr_kva +
+				      (rxp->cq.ib_seg_offset * BFI_IBIDX_SIZE));
+		*(rxp->cq.ccb->hw_producer_index) = 0;
+		rxp->cq.ccb->intr_type = intr_info->intr_type;
+		rxp->cq.ccb->intr_vector = (intr_info->num == 1) ?
+						intr_info->idl[0].vector :
+						intr_info->idl[i].vector;
+		rxp->cq.ccb->rx_coalescing_timeo =
+					rxp->cq.ib->ib_config.coalescing_timeo;
+		rxp->cq.ccb->id = i;
+
+		/* Call bnad to complete CCB setup */
+		if (rx->ccb_setup_cbfn)
+			rx->ccb_setup_cbfn(bnad, rxp->cq.ccb);
+
+	} /* for each rx-path */
+
+	bna_rxf_init(&rx->rxf, rx, rx_cfg);
+
+	bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+
+	return rx;
+}
+
+void
+bna_rx_destroy(struct bna_rx *rx)
+{
+	struct bna_rx_mod *rx_mod = &rx->bna->rx_mod;
+	struct bna_ib_mod *ib_mod = &rx->bna->ib_mod;
+	struct bna_rxq *q0 = NULL;
+	struct bna_rxq *q1 = NULL;
+	struct bna_rxp *rxp;
+	struct list_head *qe;
+
+	bna_rxf_uninit(&rx->rxf);
+
+	while (!list_empty(&rx->rxp_q)) {
+		bfa_q_deq(&rx->rxp_q, &rxp);
+		GET_RXQS(rxp, q0, q1);
+		/* Callback to bnad for destroying RCB */
+		if (rx->rcb_destroy_cbfn)
+			rx->rcb_destroy_cbfn(rx->bna->bnad, q0->rcb);
+		q0->rcb = NULL;
+		q0->rxp = NULL;
+		q0->rx = NULL;
+		_put_free_rxq(rx_mod, q0);
+		if (q1) {
+			/* Callback to bnad for destroying RCB */
+			if (rx->rcb_destroy_cbfn)
+				rx->rcb_destroy_cbfn(rx->bna->bnad, q1->rcb);
+			q1->rcb = NULL;
+			q1->rxp = NULL;
+			q1->rx = NULL;
+			_put_free_rxq(rx_mod, q1);
+		}
+		rxp->rxq.slr.large = NULL;
+		rxp->rxq.slr.small = NULL;
+		if (rxp->cq.ib) {
+			if (rxp->cq.ib_seg_offset != 0xff)
+				bna_ib_release_idx(rxp->cq.ib,
+						rxp->cq.ib_seg_offset);
+			bna_ib_put(ib_mod, rxp->cq.ib);
+			rxp->cq.ib = NULL;
+		}
+		/* Callback to bnad for destroying CCB */
+		if (rx->ccb_destroy_cbfn)
+			rx->ccb_destroy_cbfn(rx->bna->bnad, rxp->cq.ccb);
+		rxp->cq.ccb = NULL;
+		rxp->rx = NULL;
+		_put_free_rxp(rx_mod, rxp);
+	}
+
+	list_for_each(qe, &rx_mod->rx_active_q) {
+		if (qe == &rx->qe) {
+			list_del(&rx->qe);
+			bfa_q_qe_init(&rx->qe);
+			break;
+		}
+	}
+
+	rx->bna = NULL;
+	rx->priv = NULL;
+	_put_free_rx(rx_mod, rx);
+}
+
+void
+bna_rx_enable(struct bna_rx *rx)
+{
+	if (rx->fsm != (bfa_sm_t)bna_rx_sm_stopped)
+		return;
+
+	rx->rx_flags |= BNA_RX_F_ENABLE;
+	if (rx->rx_flags & BNA_RX_F_PORT_ENABLED)
+		bfa_fsm_send_event(rx, RX_E_START);
+}
+
+void
+bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
+		void (*cbfn)(void *, struct bna_rx *,
+				enum bna_cb_status))
+{
+	if (type == BNA_SOFT_CLEANUP) {
+		/* h/w should not be accessed. Treat we're stopped */
+		(*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
+	} else {
+		rx->stop_cbfn = cbfn;
+		rx->stop_cbarg = rx->bna->bnad;
+
+		rx->rx_flags &= ~BNA_RX_F_ENABLE;
+
+		bfa_fsm_send_event(rx, RX_E_STOP);
+	}
+}
+
+/**
+ * TX
+ */
+#define call_tx_stop_cbfn(tx, status)\
+do {\
+	if ((tx)->stop_cbfn)\
+		(tx)->stop_cbfn((tx)->stop_cbarg, (tx), status);\
+	(tx)->stop_cbfn = NULL;\
+	(tx)->stop_cbarg = NULL;\
+} while (0)
+
+#define call_tx_prio_change_cbfn(tx, status)\
+do {\
+	if ((tx)->prio_change_cbfn)\
+		(tx)->prio_change_cbfn((tx)->bna->bnad, (tx), status);\
+	(tx)->prio_change_cbfn = NULL;\
+} while (0)
+
+static void bna_tx_mod_cb_tx_stopped(void *tx_mod, struct bna_tx *tx,
+					enum bna_cb_status status);
+static void bna_tx_cb_txq_stopped(void *arg, int status);
+static void bna_tx_cb_stats_cleared(void *arg, int status);
+static void __bna_tx_stop(struct bna_tx *tx);
+static void __bna_tx_start(struct bna_tx *tx);
+static void __bna_txf_stat_clr(struct bna_tx *tx);
+
+enum bna_tx_event {
+	TX_E_START			= 1,
+	TX_E_STOP			= 2,
+	TX_E_FAIL			= 3,
+	TX_E_TXQ_STOPPED		= 4,
+	TX_E_PRIO_CHANGE		= 5,
+	TX_E_STAT_CLEARED		= 6,
+};
+
+enum bna_tx_state {
+	BNA_TX_STOPPED			= 1,
+	BNA_TX_STARTED			= 2,
+	BNA_TX_TXQ_STOP_WAIT		= 3,
+	BNA_TX_PRIO_STOP_WAIT		= 4,
+	BNA_TX_STAT_CLR_WAIT		= 5,
+};
+
+bfa_fsm_state_decl(bna_tx, stopped, struct bna_tx,
+			enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, started, struct bna_tx,
+			enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, txq_stop_wait, struct bna_tx,
+			enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, prio_stop_wait, struct bna_tx,
+			enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, stat_clr_wait, struct bna_tx,
+			enum bna_tx_event);
+
+static struct bfa_sm_table tx_sm_table[] = {
+	{BFA_SM(bna_tx_sm_stopped), BNA_TX_STOPPED},
+	{BFA_SM(bna_tx_sm_started), BNA_TX_STARTED},
+	{BFA_SM(bna_tx_sm_txq_stop_wait), BNA_TX_TXQ_STOP_WAIT},
+	{BFA_SM(bna_tx_sm_prio_stop_wait), BNA_TX_PRIO_STOP_WAIT},
+	{BFA_SM(bna_tx_sm_stat_clr_wait), BNA_TX_STAT_CLR_WAIT},
+};
+
+static void
+bna_tx_sm_stopped_entry(struct bna_tx *tx)
+{
+	struct bna_txq *txq;
+	struct list_head		 *qe;
+
+	list_for_each(qe, &tx->txq_q) {
+		txq = (struct bna_txq *)qe;
+		(tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb);
+	}
+
+	call_tx_stop_cbfn(tx, BNA_CB_SUCCESS);
+}
+
+static void
+bna_tx_sm_stopped(struct bna_tx *tx, enum bna_tx_event event)
+{
+	switch (event) {
+	case TX_E_START:
+		bfa_fsm_set_state(tx, bna_tx_sm_started);
+		break;
+
+	case TX_E_STOP:
+		bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+		break;
+
+	case TX_E_FAIL:
+		/* No-op */
+		break;
+
+	case TX_E_PRIO_CHANGE:
+		call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS);
+		break;
+
+	case TX_E_TXQ_STOPPED:
+		/**
+		 * This event is received due to flushing of mbox when
+		 * device fails
+		 */
+		/* No-op */
+		break;
+
+	default:
+		bfa_sm_fault(tx->bna, event);
+	}
+}
+
+static void
+bna_tx_sm_started_entry(struct bna_tx *tx)
+{
+	struct bna_txq *txq;
+	struct list_head		 *qe;
+
+	__bna_tx_start(tx);
+
+	/* Start IB */
+	list_for_each(qe, &tx->txq_q) {
+		txq = (struct bna_txq *)qe;
+		bna_ib_ack(&txq->ib->door_bell, 0);
+	}
+}
+
+static void
+bna_tx_sm_started(struct bna_tx *tx, enum bna_tx_event event)
+{
+	struct bna_txq *txq;
+	struct list_head		 *qe;
+
+	switch (event) {
+	case TX_E_STOP:
+		bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait);
+		__bna_tx_stop(tx);
+		break;
+
+	case TX_E_FAIL:
+		list_for_each(qe, &tx->txq_q) {
+			txq = (struct bna_txq *)qe;
+			bna_ib_fail(txq->ib);
+			(tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb);
+		}
+		bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+		break;
+
+	case TX_E_PRIO_CHANGE:
+		bfa_fsm_set_state(tx, bna_tx_sm_prio_stop_wait);
+		break;
+
+	default:
+		bfa_sm_fault(tx->bna, event);
+	}
+}
+
+static void
+bna_tx_sm_txq_stop_wait_entry(struct bna_tx *tx)
+{
+}
+
+static void
+bna_tx_sm_txq_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+	struct bna_txq *txq;
+	struct list_head		 *qe;
+
+	switch (event) {
+	case TX_E_FAIL:
+		bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+		break;
+
+	case TX_E_TXQ_STOPPED:
+		list_for_each(qe, &tx->txq_q) {
+			txq = (struct bna_txq *)qe;
+			bna_ib_stop(txq->ib);
+		}
+		bfa_fsm_set_state(tx, bna_tx_sm_stat_clr_wait);
+		break;
+
+	case TX_E_PRIO_CHANGE:
+		/* No-op */
+		break;
+
+	default:
+		bfa_sm_fault(tx->bna, event);
+	}
+}
+
+static void
+bna_tx_sm_prio_stop_wait_entry(struct bna_tx *tx)
+{
+	__bna_tx_stop(tx);
+}
+
+static void
+bna_tx_sm_prio_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+	struct bna_txq *txq;
+	struct list_head		 *qe;
+
+	switch (event) {
+	case TX_E_STOP:
+		bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait);
+		break;
+
+	case TX_E_FAIL:
+		call_tx_prio_change_cbfn(tx, BNA_CB_FAIL);
+		bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+		break;
+
+	case TX_E_TXQ_STOPPED:
+		list_for_each(qe, &tx->txq_q) {
+			txq = (struct bna_txq *)qe;
+			bna_ib_stop(txq->ib);
+			(tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb);
+		}
+		call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS);
+		bfa_fsm_set_state(tx, bna_tx_sm_started);
+		break;
+
+	case TX_E_PRIO_CHANGE:
+		/* No-op */
+		break;
+
+	default:
+		bfa_sm_fault(tx->bna, event);
+	}
+}
+
+static void
+bna_tx_sm_stat_clr_wait_entry(struct bna_tx *tx)
+{
+	__bna_txf_stat_clr(tx);
+}
+
+static void
+bna_tx_sm_stat_clr_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+	switch (event) {
+	case TX_E_FAIL:
+	case TX_E_STAT_CLEARED:
+		bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+		break;
+
+	default:
+		bfa_sm_fault(tx->bna, event);
+	}
+}
+
+static void
+__bna_txq_start(struct bna_tx *tx, struct bna_txq *txq)
+{
+	struct bna_rxtx_q_mem *q_mem;
+	struct bna_txq_mem txq_cfg;
+	struct bna_txq_mem *txq_mem;
+	struct bna_dma_addr cur_q_addr;
+	u32 pg_num;
+	void __iomem *base_addr;
+	unsigned long off;
+
+	/* Fill out structure, to be subsequently written to hardware */
+	txq_cfg.pg_tbl_addr_lo = txq->qpt.hw_qpt_ptr.lsb;
+	txq_cfg.pg_tbl_addr_hi = txq->qpt.hw_qpt_ptr.msb;
+	cur_q_addr = *((struct bna_dma_addr *)(txq->qpt.kv_qpt_ptr));
+	txq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
+	txq_cfg.cur_q_entry_hi = cur_q_addr.msb;
+
+	txq_cfg.pg_cnt_n_prd_ptr = (txq->qpt.page_count << 16) | 0x0;
+
+	txq_cfg.entry_n_pg_size = ((u32)(BFI_TXQ_WI_SIZE >> 2) << 16) |
+			(txq->qpt.page_size >> 2);
+	txq_cfg.int_blk_n_cns_ptr = ((((u32)txq->ib_seg_offset) << 24) |
+			((u32)(txq->ib->ib_id & 0xff) << 16) | 0x0);
+
+	txq_cfg.cns_ptr2_n_q_state = BNA_Q_IDLE_STATE;
+	txq_cfg.nxt_qid_n_fid_n_pri = (((tx->txf.txf_id & 0x3f) << 3) |
+			(txq->priority & 0x3));
+	txq_cfg.wvc_n_cquota_n_rquota =
+			((((u32)BFI_TX_MAX_WRR_QUOTA & 0xfff) << 12) |
+			(BFI_TX_MAX_WRR_QUOTA & 0xfff));
+
+	/* Setup the page and write to H/W */
+
+	pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + tx->bna->port_num,
+			HQM_RXTX_Q_RAM_BASE_OFFSET);
+	writel(pg_num, tx->bna->regs.page_addr);
+
+	base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
+					HQM_RXTX_Q_RAM_BASE_OFFSET);
+	q_mem = (struct bna_rxtx_q_mem *)0;
+	txq_mem = &q_mem[txq->txq_id].txq;
+
+	/*
+	 * The following 4 lines, is a hack b'cos the H/W needs to read
+	 * these DMA addresses as little endian
+	 */
+
+	off = (unsigned long)&txq_mem->pg_tbl_addr_lo;
+	writel(htonl(txq_cfg.pg_tbl_addr_lo), base_addr + off);
+
+	off = (unsigned long)&txq_mem->pg_tbl_addr_hi;
+	writel(htonl(txq_cfg.pg_tbl_addr_hi), base_addr + off);
+
+	off = (unsigned long)&txq_mem->cur_q_entry_lo;
+	writel(htonl(txq_cfg.cur_q_entry_lo), base_addr + off);
+
+	off = (unsigned long)&txq_mem->cur_q_entry_hi;
+	writel(htonl(txq_cfg.cur_q_entry_hi), base_addr + off);
+
+	off = (unsigned long)&txq_mem->pg_cnt_n_prd_ptr;
+	writel(txq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
+
+	off = (unsigned long)&txq_mem->entry_n_pg_size;
+	writel(txq_cfg.entry_n_pg_size, base_addr + off);
+
+	off = (unsigned long)&txq_mem->int_blk_n_cns_ptr;
+	writel(txq_cfg.int_blk_n_cns_ptr, base_addr + off);
+
+	off = (unsigned long)&txq_mem->cns_ptr2_n_q_state;
+	writel(txq_cfg.cns_ptr2_n_q_state, base_addr + off);
+
+	off = (unsigned long)&txq_mem->nxt_qid_n_fid_n_pri;
+	writel(txq_cfg.nxt_qid_n_fid_n_pri, base_addr + off);
+
+	off = (unsigned long)&txq_mem->wvc_n_cquota_n_rquota;
+	writel(txq_cfg.wvc_n_cquota_n_rquota, base_addr + off);
+
+	txq->tcb->producer_index = 0;
+	txq->tcb->consumer_index = 0;
+	*(txq->tcb->hw_consumer_index) = 0;
+
+}
+
+static void
+__bna_txq_stop(struct bna_tx *tx, struct bna_txq *txq)
+{
+	struct bfi_ll_q_stop_req ll_req;
+	u32 bit_mask[2] = {0, 0};
+	if (txq->txq_id < 32)
+		bit_mask[0] = (u32)1 << txq->txq_id;
+	else
+		bit_mask[1] = (u32)1 << (txq->txq_id - 32);
+
+	memset(&ll_req, 0, sizeof(ll_req));
+	ll_req.mh.msg_class = BFI_MC_LL;
+	ll_req.mh.msg_id = BFI_LL_H2I_TXQ_STOP_REQ;
+	ll_req.mh.mtag.h2i.lpu_id = 0;
+	ll_req.q_id_mask[0] = htonl(bit_mask[0]);
+	ll_req.q_id_mask[1] = htonl(bit_mask[1]);
+
+	bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req),
+			bna_tx_cb_txq_stopped, tx);
+
+	bna_mbox_send(tx->bna, &tx->mbox_qe);
+}
+
+static void
+__bna_txf_start(struct bna_tx *tx)
+{
+	struct bna_tx_fndb_ram *tx_fndb;
+	struct bna_txf *txf = &tx->txf;
+	void __iomem *base_addr;
+	unsigned long off;
+
+	writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+			(tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET),
+			tx->bna->regs.page_addr);
+
+	base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
+					TX_FNDB_RAM_BASE_OFFSET);
+
+	tx_fndb = (struct bna_tx_fndb_ram *)0;
+	off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags;
+
+	writel(((u32)txf->vlan << 16) | txf->ctrl_flags,
+			base_addr + off);
+
+	if (tx->txf.txf_id < 32)
+		tx->bna->tx_mod.txf_bmap[0] |= ((u32)1 << tx->txf.txf_id);
+	else
+		tx->bna->tx_mod.txf_bmap[1] |= ((u32)
+						 1 << (tx->txf.txf_id - 32));
+}
+
+static void
+__bna_txf_stop(struct bna_tx *tx)
+{
+	struct bna_tx_fndb_ram *tx_fndb;
+	u32 page_num;
+	u32 ctl_flags;
+	struct bna_txf *txf = &tx->txf;
+	void __iomem *base_addr;
+	unsigned long off;
+
+	/* retrieve the running txf_flags & turn off enable bit */
+	page_num = BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+			(tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET);
+	writel(page_num, tx->bna->regs.page_addr);
+
+	base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
+					TX_FNDB_RAM_BASE_OFFSET);
+	tx_fndb = (struct bna_tx_fndb_ram *)0;
+	off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags;
+
+	ctl_flags = readl(base_addr + off);
+	ctl_flags &= ~BFI_TXF_CF_ENABLE;
+
+	writel(ctl_flags, base_addr + off);
+
+	if (tx->txf.txf_id < 32)
+		tx->bna->tx_mod.txf_bmap[0] &= ~((u32)1 << tx->txf.txf_id);
+	else
+		tx->bna->tx_mod.txf_bmap[0] &= ~((u32)
+						 1 << (tx->txf.txf_id - 32));
+}
+
+static void
+__bna_txf_stat_clr(struct bna_tx *tx)
+{
+	struct bfi_ll_stats_req ll_req;
+	u32 txf_bmap[2] = {0, 0};
+	if (tx->txf.txf_id < 32)
+		txf_bmap[0] = ((u32)1 << tx->txf.txf_id);
+	else
+		txf_bmap[1] = ((u32)1 << (tx->txf.txf_id - 32));
+	bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
+	ll_req.stats_mask = 0;
+	ll_req.rxf_id_mask[0] = 0;
+	ll_req.rxf_id_mask[1] =	0;
+	ll_req.txf_id_mask[0] =	htonl(txf_bmap[0]);
+	ll_req.txf_id_mask[1] =	htonl(txf_bmap[1]);
+
+	bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req),
+			bna_tx_cb_stats_cleared, tx);
+	bna_mbox_send(tx->bna, &tx->mbox_qe);
+}
+
+static void
+__bna_tx_start(struct bna_tx *tx)
+{
+	struct bna_txq *txq;
+	struct list_head		 *qe;
+
+	list_for_each(qe, &tx->txq_q) {
+		txq = (struct bna_txq *)qe;
+		bna_ib_start(txq->ib);
+		__bna_txq_start(tx, txq);
+	}
+
+	__bna_txf_start(tx);
+
+	list_for_each(qe, &tx->txq_q) {
+		txq = (struct bna_txq *)qe;
+		txq->tcb->priority = txq->priority;
+		(tx->tx_resume_cbfn)(tx->bna->bnad, txq->tcb);
+	}
+}
+
+static void
+__bna_tx_stop(struct bna_tx *tx)
+{
+	struct bna_txq *txq;
+	struct list_head		 *qe;
+
+	list_for_each(qe, &tx->txq_q) {
+		txq = (struct bna_txq *)qe;
+		(tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb);
+	}
+
+	__bna_txf_stop(tx);
+
+	list_for_each(qe, &tx->txq_q) {
+		txq = (struct bna_txq *)qe;
+		bfa_wc_up(&tx->txq_stop_wc);
+	}
+
+	list_for_each(qe, &tx->txq_q) {
+		txq = (struct bna_txq *)qe;
+		__bna_txq_stop(tx, txq);
+	}
+}
+
+static void
+bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size,
+		struct bna_mem_descr *qpt_mem,
+		struct bna_mem_descr *swqpt_mem,
+		struct bna_mem_descr *page_mem)
+{
+	int i;
+
+	txq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+	txq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+	txq->qpt.kv_qpt_ptr = qpt_mem->kva;
+	txq->qpt.page_count = page_count;
+	txq->qpt.page_size = page_size;
+
+	txq->tcb->sw_qpt = (void **) swqpt_mem->kva;
+
+	for (i = 0; i < page_count; i++) {
+		txq->tcb->sw_qpt[i] = page_mem[i].kva;
+
+		((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].lsb =
+			page_mem[i].dma.lsb;
+		((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].msb =
+			page_mem[i].dma.msb;
+
+	}
+}
+
+static void
+bna_tx_free(struct bna_tx *tx)
+{
+	struct bna_tx_mod *tx_mod = &tx->bna->tx_mod;
+	struct bna_txq *txq;
+	struct bna_ib_mod *ib_mod = &tx->bna->ib_mod;
+	struct list_head *qe;
+
+	while (!list_empty(&tx->txq_q)) {
+		bfa_q_deq(&tx->txq_q, &txq);
+		bfa_q_qe_init(&txq->qe);
+		if (txq->ib) {
+			if (txq->ib_seg_offset != -1)
+				bna_ib_release_idx(txq->ib,
+						txq->ib_seg_offset);
+			bna_ib_put(ib_mod, txq->ib);
+			txq->ib = NULL;
+		}
+		txq->tcb = NULL;
+		txq->tx = NULL;
+		list_add_tail(&txq->qe, &tx_mod->txq_free_q);
+	}
+
+	list_for_each(qe, &tx_mod->tx_active_q) {
+		if (qe == &tx->qe) {
+			list_del(&tx->qe);
+			bfa_q_qe_init(&tx->qe);
+			break;
+		}
+	}
+
+	tx->bna = NULL;
+	tx->priv = NULL;
+	list_add_tail(&tx->qe, &tx_mod->tx_free_q);
+}
+
+static void
+bna_tx_cb_txq_stopped(void *arg, int status)
+{
+	struct bna_tx *tx = (struct bna_tx *)arg;
+
+	bfa_q_qe_init(&tx->mbox_qe.qe);
+	bfa_wc_down(&tx->txq_stop_wc);
+}
+
+static void
+bna_tx_cb_txq_stopped_all(void *arg)
+{
+	struct bna_tx *tx = (struct bna_tx *)arg;
+
+	bfa_fsm_send_event(tx, TX_E_TXQ_STOPPED);
+}
+
+static void
+bna_tx_cb_stats_cleared(void *arg, int status)
+{
+	struct bna_tx *tx = (struct bna_tx *)arg;
+
+	bfa_q_qe_init(&tx->mbox_qe.qe);
+
+	bfa_fsm_send_event(tx, TX_E_STAT_CLEARED);
+}
+
+static void
+bna_tx_start(struct bna_tx *tx)
+{
+	tx->flags |= BNA_TX_F_PORT_STARTED;
+	if (tx->flags & BNA_TX_F_ENABLED)
+		bfa_fsm_send_event(tx, TX_E_START);
+}
+
+static void
+bna_tx_stop(struct bna_tx *tx)
+{
+	tx->stop_cbfn = bna_tx_mod_cb_tx_stopped;
+	tx->stop_cbarg = &tx->bna->tx_mod;
+
+	tx->flags &= ~BNA_TX_F_PORT_STARTED;
+	bfa_fsm_send_event(tx, TX_E_STOP);
+}
+
+static void
+bna_tx_fail(struct bna_tx *tx)
+{
+	tx->flags &= ~BNA_TX_F_PORT_STARTED;
+	bfa_fsm_send_event(tx, TX_E_FAIL);
+}
+
+static void
+bna_tx_prio_changed(struct bna_tx *tx, int prio)
+{
+	struct bna_txq *txq;
+	struct list_head		 *qe;
+
+	list_for_each(qe, &tx->txq_q) {
+		txq = (struct bna_txq *)qe;
+		txq->priority = prio;
+	}
+
+	bfa_fsm_send_event(tx, TX_E_PRIO_CHANGE);
+}
+
+static void
+bna_tx_cee_link_status(struct bna_tx *tx, int cee_link)
+{
+	if (cee_link)
+		tx->flags |= BNA_TX_F_PRIO_LOCK;
+	else
+		tx->flags &= ~BNA_TX_F_PRIO_LOCK;
+}
+
+static void
+bna_tx_mod_cb_tx_stopped(void *arg, struct bna_tx *tx,
+			enum bna_cb_status status)
+{
+	struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
+
+	bfa_wc_down(&tx_mod->tx_stop_wc);
+}
+
+static void
+bna_tx_mod_cb_tx_stopped_all(void *arg)
+{
+	struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
+
+	if (tx_mod->stop_cbfn)
+		tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS);
+	tx_mod->stop_cbfn = NULL;
+}
+
+void
+bna_tx_res_req(int num_txq, int txq_depth, struct bna_res_info *res_info)
+{
+	u32 q_size;
+	u32 page_count;
+	struct bna_mem_info *mem_info;
+
+	res_info[BNA_TX_RES_MEM_T_TCB].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_KVA;
+	mem_info->len = sizeof(struct bna_tcb);
+	mem_info->num = num_txq;
+
+	q_size = txq_depth * BFI_TXQ_WI_SIZE;
+	q_size = ALIGN(q_size, PAGE_SIZE);
+	page_count = q_size >> PAGE_SHIFT;
+
+	res_info[BNA_TX_RES_MEM_T_QPT].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_DMA;
+	mem_info->len = page_count * sizeof(struct bna_dma_addr);
+	mem_info->num = num_txq;
+
+	res_info[BNA_TX_RES_MEM_T_SWQPT].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_KVA;
+	mem_info->len = page_count * sizeof(void *);
+	mem_info->num = num_txq;
+
+	res_info[BNA_TX_RES_MEM_T_PAGE].res_type = BNA_RES_T_MEM;
+	mem_info = &res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info;
+	mem_info->mem_type = BNA_MEM_T_DMA;
+	mem_info->len = PAGE_SIZE;
+	mem_info->num = num_txq * page_count;
+
+	res_info[BNA_TX_RES_INTR_T_TXCMPL].res_type = BNA_RES_T_INTR;
+	res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.intr_type =
+			BNA_INTR_T_MSIX;
+	res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.num = num_txq;
+}
+
+struct bna_tx *
+bna_tx_create(struct bna *bna, struct bnad *bnad,
+		struct bna_tx_config *tx_cfg,
+		struct bna_tx_event_cbfn *tx_cbfn,
+		struct bna_res_info *res_info, void *priv)
+{
+	struct bna_intr_info *intr_info;
+	struct bna_tx_mod *tx_mod = &bna->tx_mod;
+	struct bna_tx *tx;
+	struct bna_txq *txq;
+	struct list_head *qe;
+	struct bna_ib_mod *ib_mod = &bna->ib_mod;
+	struct bna_doorbell_qset *qset;
+	struct bna_ib_config ib_config;
+	int page_count;
+	int page_size;
+	int page_idx;
+	int i;
+	unsigned long off;
+
+	intr_info = &res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info;
+	page_count = (res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.num) /
+			tx_cfg->num_txq;
+	page_size = res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.len;
+
+	/**
+	 * Get resources
+	 */
+
+	if ((intr_info->num != 1) && (intr_info->num != tx_cfg->num_txq))
+		return NULL;
+
+	/* Tx */
+
+	if (list_empty(&tx_mod->tx_free_q))
+		return NULL;
+	bfa_q_deq(&tx_mod->tx_free_q, &tx);
+	bfa_q_qe_init(&tx->qe);
+
+	/* TxQs */
+
+	INIT_LIST_HEAD(&tx->txq_q);
+	for (i = 0; i < tx_cfg->num_txq; i++) {
+		if (list_empty(&tx_mod->txq_free_q))
+			goto err_return;
+
+		bfa_q_deq(&tx_mod->txq_free_q, &txq);
+		bfa_q_qe_init(&txq->qe);
+		list_add_tail(&txq->qe, &tx->txq_q);
+		txq->ib = NULL;
+		txq->ib_seg_offset = -1;
+		txq->tx = tx;
+	}
+
+	/* IBs */
+	i = 0;
+	list_for_each(qe, &tx->txq_q) {
+		txq = (struct bna_txq *)qe;
+
+		if (intr_info->num == 1)
+			txq->ib = bna_ib_get(ib_mod, intr_info->intr_type,
+						intr_info->idl[0].vector);
+		else
+			txq->ib = bna_ib_get(ib_mod, intr_info->intr_type,
+						intr_info->idl[i].vector);
+
+		if (txq->ib == NULL)
+			goto err_return;
+
+		txq->ib_seg_offset = bna_ib_reserve_idx(txq->ib);
+		if (txq->ib_seg_offset == -1)
+			goto err_return;
+
+		i++;
+	}
+
+	/*
+	 * Initialize
+	 */
+
+	/* Tx */
+
+	tx->tcb_setup_cbfn = tx_cbfn->tcb_setup_cbfn;
+	tx->tcb_destroy_cbfn = tx_cbfn->tcb_destroy_cbfn;
+	/* Following callbacks are mandatory */
+	tx->tx_stall_cbfn = tx_cbfn->tx_stall_cbfn;
+	tx->tx_resume_cbfn = tx_cbfn->tx_resume_cbfn;
+	tx->tx_cleanup_cbfn = tx_cbfn->tx_cleanup_cbfn;
+
+	list_add_tail(&tx->qe, &tx_mod->tx_active_q);
+	tx->bna = bna;
+	tx->priv = priv;
+	tx->txq_stop_wc.wc_resume = bna_tx_cb_txq_stopped_all;
+	tx->txq_stop_wc.wc_cbarg = tx;
+	tx->txq_stop_wc.wc_count = 0;
+
+	tx->type = tx_cfg->tx_type;
+
+	tx->flags = 0;
+	if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_STARTED) {
+		switch (tx->type) {
+		case BNA_TX_T_REGULAR:
+			if (!(tx->bna->tx_mod.flags &
+				BNA_TX_MOD_F_PORT_LOOPBACK))
+				tx->flags |= BNA_TX_F_PORT_STARTED;
+			break;
+		case BNA_TX_T_LOOPBACK:
+			if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_LOOPBACK)
+				tx->flags |= BNA_TX_F_PORT_STARTED;
+			break;
+		}
+	}
+	if (tx->bna->tx_mod.cee_link)
+		tx->flags |= BNA_TX_F_PRIO_LOCK;
+
+	/* TxQ */
+
+	i = 0;
+	page_idx = 0;
+	list_for_each(qe, &tx->txq_q) {
+		txq = (struct bna_txq *)qe;
+		txq->priority = tx_mod->priority;
+		txq->tcb = (struct bna_tcb *)
+		  res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info.mdl[i].kva;
+		txq->tx_packets = 0;
+		txq->tx_bytes = 0;
+
+		/* IB */
+
+		ib_config.coalescing_timeo = BFI_TX_COALESCING_TIMEO;
+		ib_config.interpkt_timeo = 0; /* Not used */
+		ib_config.interpkt_count = BFI_TX_INTERPKT_COUNT;
+		ib_config.ctrl_flags = (BFI_IB_CF_INTER_PKT_DMA |
+					BFI_IB_CF_INT_ENABLE |
+					BFI_IB_CF_COALESCING_MODE);
+		bna_ib_config(txq->ib, &ib_config);
+
+		/* TCB */
+
+		txq->tcb->producer_index = 0;
+		txq->tcb->consumer_index = 0;
+		txq->tcb->hw_consumer_index = (volatile u32 *)
+			((volatile u8 *)txq->ib->ib_seg_host_addr_kva +
+			 (txq->ib_seg_offset * BFI_IBIDX_SIZE));
+		*(txq->tcb->hw_consumer_index) = 0;
+		txq->tcb->q_depth = tx_cfg->txq_depth;
+		txq->tcb->unmap_q = (void *)
+		res_info[BNA_TX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[i].kva;
+		qset = (struct bna_doorbell_qset *)0;
+		off = (unsigned long)&qset[txq->txq_id].txq[0];
+		txq->tcb->q_dbell = off +
+			BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva);
+		txq->tcb->i_dbell = &txq->ib->door_bell;
+		txq->tcb->intr_type = intr_info->intr_type;
+		txq->tcb->intr_vector = (intr_info->num == 1) ?
+					intr_info->idl[0].vector :
+					intr_info->idl[i].vector;
+		txq->tcb->txq = txq;
+		txq->tcb->bnad = bnad;
+		txq->tcb->id = i;
+
+		/* QPT, SWQPT, Pages */
+		bna_txq_qpt_setup(txq, page_count, page_size,
+			&res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info.mdl[i],
+			&res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info.mdl[i],
+			&res_info[BNA_TX_RES_MEM_T_PAGE].
+				  res_u.mem_info.mdl[page_idx]);
+		txq->tcb->page_idx = page_idx;
+		txq->tcb->page_count = page_count;
+		page_idx += page_count;
+
+		/* Callback to bnad for setting up TCB */
+		if (tx->tcb_setup_cbfn)
+			(tx->tcb_setup_cbfn)(bna->bnad, txq->tcb);
+
+		i++;
+	}
+
+	/* TxF */
+
+	tx->txf.ctrl_flags = BFI_TXF_CF_ENABLE | BFI_TXF_CF_VLAN_WI_BASED;
+	tx->txf.vlan = 0;
+
+	/* Mbox element */
+	bfa_q_qe_init(&tx->mbox_qe.qe);
+
+	bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+
+	return tx;
+
+err_return:
+	bna_tx_free(tx);
+	return NULL;
+}
+
+void
+bna_tx_destroy(struct bna_tx *tx)
+{
+	/* Callback to bnad for destroying TCB */
+	if (tx->tcb_destroy_cbfn) {
+		struct bna_txq *txq;
+		struct list_head *qe;
+
+		list_for_each(qe, &tx->txq_q) {
+			txq = (struct bna_txq *)qe;
+			(tx->tcb_destroy_cbfn)(tx->bna->bnad, txq->tcb);
+		}
+	}
+
+	bna_tx_free(tx);
+}
+
+void
+bna_tx_enable(struct bna_tx *tx)
+{
+	if (tx->fsm != (bfa_sm_t)bna_tx_sm_stopped)
+		return;
+
+	tx->flags |= BNA_TX_F_ENABLED;
+
+	if (tx->flags & BNA_TX_F_PORT_STARTED)
+		bfa_fsm_send_event(tx, TX_E_START);
+}
+
+void
+bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
+		void (*cbfn)(void *, struct bna_tx *, enum bna_cb_status))
+{
+	if (type == BNA_SOFT_CLEANUP) {
+		(*cbfn)(tx->bna->bnad, tx, BNA_CB_SUCCESS);
+		return;
+	}
+
+	tx->stop_cbfn = cbfn;
+	tx->stop_cbarg = tx->bna->bnad;
+
+	tx->flags &= ~BNA_TX_F_ENABLED;
+
+	bfa_fsm_send_event(tx, TX_E_STOP);
+}
+
+int
+bna_tx_state_get(struct bna_tx *tx)
+{
+	return bfa_sm_to_state(tx_sm_table, tx->fsm);
+}
+
+void
+bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
+		struct bna_res_info *res_info)
+{
+	int i;
+
+	tx_mod->bna = bna;
+	tx_mod->flags = 0;
+
+	tx_mod->tx = (struct bna_tx *)
+		res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mdl[0].kva;
+	tx_mod->txq = (struct bna_txq *)
+		res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mdl[0].kva;
+
+	INIT_LIST_HEAD(&tx_mod->tx_free_q);
+	INIT_LIST_HEAD(&tx_mod->tx_active_q);
+
+	INIT_LIST_HEAD(&tx_mod->txq_free_q);
+
+	for (i = 0; i < BFI_MAX_TXQ; i++) {
+		tx_mod->tx[i].txf.txf_id = i;
+		bfa_q_qe_init(&tx_mod->tx[i].qe);
+		list_add_tail(&tx_mod->tx[i].qe, &tx_mod->tx_free_q);
+
+		tx_mod->txq[i].txq_id = i;
+		bfa_q_qe_init(&tx_mod->txq[i].qe);
+		list_add_tail(&tx_mod->txq[i].qe, &tx_mod->txq_free_q);
+	}
+
+	tx_mod->tx_stop_wc.wc_resume = bna_tx_mod_cb_tx_stopped_all;
+	tx_mod->tx_stop_wc.wc_cbarg = tx_mod;
+	tx_mod->tx_stop_wc.wc_count = 0;
+}
+
+void
+bna_tx_mod_uninit(struct bna_tx_mod *tx_mod)
+{
+	struct list_head		*qe;
+	int i;
+
+	i = 0;
+	list_for_each(qe, &tx_mod->tx_free_q)
+		i++;
+
+	i = 0;
+	list_for_each(qe, &tx_mod->txq_free_q)
+		i++;
+
+	tx_mod->bna = NULL;
+}
+
+void
+bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
+{
+	struct bna_tx *tx;
+	struct list_head		*qe;
+
+	tx_mod->flags |= BNA_TX_MOD_F_PORT_STARTED;
+	if (type == BNA_TX_T_LOOPBACK)
+		tx_mod->flags |= BNA_TX_MOD_F_PORT_LOOPBACK;
+
+	list_for_each(qe, &tx_mod->tx_active_q) {
+		tx = (struct bna_tx *)qe;
+		if (tx->type == type)
+			bna_tx_start(tx);
+	}
+}
+
+void
+bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
+{
+	struct bna_tx *tx;
+	struct list_head		*qe;
+
+	tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED;
+	tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK;
+
+	tx_mod->stop_cbfn = bna_port_cb_tx_stopped;
+
+	/**
+	 * Before calling bna_tx_stop(), increment tx_stop_wc as many times
+	 * as we are going to call bna_tx_stop
+	 */
+	list_for_each(qe, &tx_mod->tx_active_q) {
+		tx = (struct bna_tx *)qe;
+		if (tx->type == type)
+			bfa_wc_up(&tx_mod->tx_stop_wc);
+	}
+
+	if (tx_mod->tx_stop_wc.wc_count == 0) {
+		tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS);
+		tx_mod->stop_cbfn = NULL;
+		return;
+	}
+
+	list_for_each(qe, &tx_mod->tx_active_q) {
+		tx = (struct bna_tx *)qe;
+		if (tx->type == type)
+			bna_tx_stop(tx);
+	}
+}
+
+void
+bna_tx_mod_fail(struct bna_tx_mod *tx_mod)
+{
+	struct bna_tx *tx;
+	struct list_head		*qe;
+
+	tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED;
+	tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK;
+
+	list_for_each(qe, &tx_mod->tx_active_q) {
+		tx = (struct bna_tx *)qe;
+		bna_tx_fail(tx);
+	}
+}
+
+void
+bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio)
+{
+	struct bna_tx *tx;
+	struct list_head		*qe;
+
+	if (prio != tx_mod->priority) {
+		tx_mod->priority = prio;
+
+		list_for_each(qe, &tx_mod->tx_active_q) {
+			tx = (struct bna_tx *)qe;
+			bna_tx_prio_changed(tx, prio);
+		}
+	}
+}
+
+void
+bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link)
+{
+	struct bna_tx *tx;
+	struct list_head		*qe;
+
+	tx_mod->cee_link = cee_link;
+
+	list_for_each(qe, &tx_mod->tx_active_q) {
+		tx = (struct bna_tx *)qe;
+		bna_tx_cee_link_status(tx, cee_link);
+	}
+}
diff --git a/drivers/net/bna/bna_types.h b/drivers/net/bna/bna_types.h
new file mode 100644
index 0000000..6877310
--- /dev/null
+++ b/drivers/net/bna/bna_types.h
@@ -0,0 +1,1128 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BNA_TYPES_H__
+#define __BNA_TYPES_H__
+
+#include "cna.h"
+#include "bna_hw.h"
+#include "bfa_cee.h"
+
+/**
+ *
+ * Forward declarations
+ *
+ */
+
+struct bna_txq;
+struct bna_tx;
+struct bna_rxq;
+struct bna_cq;
+struct bna_rx;
+struct bna_rxf;
+struct bna_port;
+struct bna;
+struct bnad;
+
+/**
+ *
+ * Enums, primitive data types
+ *
+ */
+
+enum bna_status {
+	BNA_STATUS_T_DISABLED	= 0,
+	BNA_STATUS_T_ENABLED	= 1
+};
+
+enum bna_cleanup_type {
+	BNA_HARD_CLEANUP 	= 0,
+	BNA_SOFT_CLEANUP 	= 1
+};
+
+enum bna_cb_status {
+	BNA_CB_SUCCESS 		= 0,
+	BNA_CB_FAIL		= 1,
+	BNA_CB_INTERRUPT	= 2,
+	BNA_CB_BUSY		= 3,
+	BNA_CB_INVALID_MAC	= 4,
+	BNA_CB_MCAST_LIST_FULL	= 5,
+	BNA_CB_UCAST_CAM_FULL	= 6,
+	BNA_CB_WAITING		= 7,
+	BNA_CB_NOT_EXEC		= 8
+};
+
+enum bna_res_type {
+	BNA_RES_T_MEM		= 1,
+	BNA_RES_T_INTR		= 2
+};
+
+enum bna_mem_type {
+	BNA_MEM_T_KVA 		= 1,
+	BNA_MEM_T_DMA 		= 2
+};
+
+enum bna_intr_type {
+	BNA_INTR_T_INTX		= 1,
+	BNA_INTR_T_MSIX		= 2
+};
+
+enum bna_res_req_type {
+	BNA_RES_MEM_T_COM 		= 0,
+	BNA_RES_MEM_T_ATTR 		= 1,
+	BNA_RES_MEM_T_FWTRC 		= 2,
+	BNA_RES_MEM_T_STATS 		= 3,
+	BNA_RES_MEM_T_SWSTATS		= 4,
+	BNA_RES_MEM_T_IBIDX		= 5,
+	BNA_RES_MEM_T_IB_ARRAY		= 6,
+	BNA_RES_MEM_T_INTR_ARRAY	= 7,
+	BNA_RES_MEM_T_IDXSEG_ARRAY	= 8,
+	BNA_RES_MEM_T_TX_ARRAY		= 9,
+	BNA_RES_MEM_T_TXQ_ARRAY		= 10,
+	BNA_RES_MEM_T_RX_ARRAY		= 11,
+	BNA_RES_MEM_T_RXP_ARRAY		= 12,
+	BNA_RES_MEM_T_RXQ_ARRAY		= 13,
+	BNA_RES_MEM_T_UCMAC_ARRAY	= 14,
+	BNA_RES_MEM_T_MCMAC_ARRAY	= 15,
+	BNA_RES_MEM_T_RIT_ENTRY		= 16,
+	BNA_RES_MEM_T_RIT_SEGMENT	= 17,
+	BNA_RES_INTR_T_MBOX		= 18,
+	BNA_RES_T_MAX
+};
+
+enum bna_tx_res_req_type {
+	BNA_TX_RES_MEM_T_TCB	= 0,
+	BNA_TX_RES_MEM_T_UNMAPQ	= 1,
+	BNA_TX_RES_MEM_T_QPT 	= 2,
+	BNA_TX_RES_MEM_T_SWQPT	= 3,
+	BNA_TX_RES_MEM_T_PAGE 	= 4,
+	BNA_TX_RES_INTR_T_TXCMPL = 5,
+	BNA_TX_RES_T_MAX,
+};
+
+enum bna_rx_mem_type {
+	BNA_RX_RES_MEM_T_CCB		= 0,	/* CQ context */
+	BNA_RX_RES_MEM_T_RCB		= 1,	/* CQ context */
+	BNA_RX_RES_MEM_T_UNMAPQ		= 2,	/* UnmapQ for RxQs */
+	BNA_RX_RES_MEM_T_CQPT		= 3,	/* CQ QPT */
+	BNA_RX_RES_MEM_T_CSWQPT		= 4,	/* S/W QPT */
+	BNA_RX_RES_MEM_T_CQPT_PAGE	= 5,	/* CQPT page */
+	BNA_RX_RES_MEM_T_HQPT		= 6,	/* RX QPT */
+	BNA_RX_RES_MEM_T_DQPT		= 7,	/* RX QPT */
+	BNA_RX_RES_MEM_T_HSWQPT		= 8,	/* RX s/w QPT */
+	BNA_RX_RES_MEM_T_DSWQPT		= 9,	/* RX s/w QPT */
+	BNA_RX_RES_MEM_T_DPAGE		= 10,	/* RX s/w QPT */
+	BNA_RX_RES_MEM_T_HPAGE		= 11,	/* RX s/w QPT */
+	BNA_RX_RES_T_INTR		= 12,	/* Rx interrupts */
+	BNA_RX_RES_T_MAX		= 13
+};
+
+enum bna_mbox_state {
+	BNA_MBOX_FREE		= 0,
+	BNA_MBOX_POSTED		= 1
+};
+
+enum bna_tx_type {
+	BNA_TX_T_REGULAR	= 0,
+	BNA_TX_T_LOOPBACK	= 1,
+};
+
+enum bna_tx_flags {
+	BNA_TX_F_PORT_STARTED	= 1,
+	BNA_TX_F_ENABLED	= 2,
+	BNA_TX_F_PRIO_LOCK	= 4,
+};
+
+enum bna_tx_mod_flags {
+	BNA_TX_MOD_F_PORT_STARTED	= 1,
+	BNA_TX_MOD_F_PORT_LOOPBACK	= 2,
+};
+
+enum bna_rx_type {
+	BNA_RX_T_REGULAR	= 0,
+	BNA_RX_T_LOOPBACK	= 1,
+};
+
+enum bna_rxp_type {
+	BNA_RXP_SINGLE 		= 1,
+	BNA_RXP_SLR 		= 2,
+	BNA_RXP_HDS 		= 3
+};
+
+enum bna_rxmode {
+	BNA_RXMODE_PROMISC 	= 1,
+	BNA_RXMODE_DEFAULT 	= 2,
+	BNA_RXMODE_ALLMULTI 	= 4
+};
+
+enum bna_rx_event {
+	RX_E_START			= 1,
+	RX_E_STOP			= 2,
+	RX_E_FAIL			= 3,
+	RX_E_RXF_STARTED		= 4,
+	RX_E_RXF_STOPPED		= 5,
+	RX_E_RXQ_STOPPED		= 6,
+};
+
+enum bna_rx_state {
+	BNA_RX_STOPPED			= 1,
+	BNA_RX_RXF_START_WAIT		= 2,
+	BNA_RX_STARTED			= 3,
+	BNA_RX_RXF_STOP_WAIT		= 4,
+	BNA_RX_RXQ_STOP_WAIT		= 5,
+};
+
+enum bna_rx_flags {
+	BNA_RX_F_ENABLE		= 0x01,		/* bnad enabled rxf */
+	BNA_RX_F_PORT_ENABLED	= 0x02,		/* Port object is enabled */
+	BNA_RX_F_PORT_FAILED	= 0x04,		/* Port in failed state */
+};
+
+enum bna_rx_mod_flags {
+	BNA_RX_MOD_F_PORT_STARTED	= 1,
+	BNA_RX_MOD_F_PORT_LOOPBACK	= 2,
+};
+
+enum bna_rxf_oper_state {
+	BNA_RXF_OPER_STATE_RUNNING	= 0x01, /* rxf operational */
+	BNA_RXF_OPER_STATE_PAUSED	= 0x02,	/* rxf in PAUSED state */
+};
+
+enum bna_rxf_flags {
+	BNA_RXF_FL_STOP_PENDING 	= 0x01,
+	BNA_RXF_FL_FAILED		= 0x02,
+	BNA_RXF_FL_RSS_CONFIG_PENDING	= 0x04,
+	BNA_RXF_FL_OPERSTATE_CHANGED	= 0x08,
+	BNA_RXF_FL_RXF_ENABLED		= 0x10,
+	BNA_RXF_FL_VLAN_CONFIG_PENDING	= 0x20,
+};
+
+enum bna_rxf_event {
+	RXF_E_START			= 1,
+	RXF_E_STOP			= 2,
+	RXF_E_FAIL			= 3,
+	RXF_E_CAM_FLTR_MOD		= 4,
+	RXF_E_STARTED			= 5,
+	RXF_E_STOPPED			= 6,
+	RXF_E_CAM_FLTR_RESP		= 7,
+	RXF_E_PAUSE			= 8,
+	RXF_E_RESUME			= 9,
+	RXF_E_STAT_CLEARED		= 10,
+};
+
+enum bna_rxf_state {
+	BNA_RXF_STOPPED			= 1,
+	BNA_RXF_START_WAIT		= 2,
+	BNA_RXF_CAM_FLTR_MOD_WAIT	= 3,
+	BNA_RXF_STARTED			= 4,
+	BNA_RXF_CAM_FLTR_CLR_WAIT	= 5,
+	BNA_RXF_STOP_WAIT		= 6,
+	BNA_RXF_PAUSE_WAIT		= 7,
+	BNA_RXF_RESUME_WAIT		= 8,
+	BNA_RXF_STAT_CLR_WAIT		= 9,
+};
+
+enum bna_port_type {
+	BNA_PORT_T_REGULAR		= 0,
+	BNA_PORT_T_LOOPBACK_INTERNAL	= 1,
+	BNA_PORT_T_LOOPBACK_EXTERNAL	= 2,
+};
+
+enum bna_link_status {
+	BNA_LINK_DOWN		= 0,
+	BNA_LINK_UP		= 1,
+	BNA_CEE_UP 		= 2
+};
+
+enum bna_llport_flags {
+	BNA_LLPORT_F_ENABLED 	= 1,
+	BNA_LLPORT_F_RX_ENABLED	= 2
+};
+
+enum bna_port_flags {
+	BNA_PORT_F_DEVICE_READY	= 1,
+	BNA_PORT_F_ENABLED	= 2,
+	BNA_PORT_F_PAUSE_CHANGED = 4,
+	BNA_PORT_F_MTU_CHANGED	= 8
+};
+
+enum bna_pkt_rates {
+	BNA_PKT_RATE_10K		= 10000,
+	BNA_PKT_RATE_20K		= 20000,
+	BNA_PKT_RATE_30K		= 30000,
+	BNA_PKT_RATE_40K		= 40000,
+	BNA_PKT_RATE_50K		= 50000,
+	BNA_PKT_RATE_60K		= 60000,
+	BNA_PKT_RATE_70K		= 70000,
+	BNA_PKT_RATE_80K		= 80000,
+};
+
+enum bna_dim_load_types {
+	BNA_LOAD_T_HIGH_4		= 0, /* 80K <= r */
+	BNA_LOAD_T_HIGH_3		= 1, /* 60K <= r < 80K */
+	BNA_LOAD_T_HIGH_2		= 2, /* 50K <= r < 60K */
+	BNA_LOAD_T_HIGH_1		= 3, /* 40K <= r < 50K */
+	BNA_LOAD_T_LOW_1		= 4, /* 30K <= r < 40K */
+	BNA_LOAD_T_LOW_2		= 5, /* 20K <= r < 30K */
+	BNA_LOAD_T_LOW_3		= 6, /* 10K <= r < 20K */
+	BNA_LOAD_T_LOW_4		= 7, /* r < 10K */
+	BNA_LOAD_T_MAX			= 8
+};
+
+enum bna_dim_bias_types {
+	BNA_BIAS_T_SMALL		= 0, /* small pkts > (large pkts * 2) */
+	BNA_BIAS_T_LARGE		= 1, /* Not BNA_BIAS_T_SMALL */
+	BNA_BIAS_T_MAX			= 2
+};
+
+struct bna_mac {
+	/* This should be the first one */
+	struct list_head			qe;
+	u8			addr[ETH_ALEN];
+};
+
+struct bna_mem_descr {
+	u32		len;
+	void		*kva;
+	struct bna_dma_addr dma;
+};
+
+struct bna_mem_info {
+	enum bna_mem_type mem_type;
+	u32		len;
+	u32 		num;
+	u32		align_sz; /* 0/1 = no alignment */
+	struct bna_mem_descr *mdl;
+	void			*cookie; /* For bnad to unmap dma later */
+};
+
+struct bna_intr_descr {
+	int			vector;
+};
+
+struct bna_intr_info {
+	enum bna_intr_type intr_type;
+	int			num;
+	struct bna_intr_descr *idl;
+};
+
+union bna_res_u {
+	struct bna_mem_info mem_info;
+	struct bna_intr_info intr_info;
+};
+
+struct bna_res_info {
+	enum bna_res_type res_type;
+	union bna_res_u		res_u;
+};
+
+/* HW QPT */
+struct bna_qpt {
+	struct bna_dma_addr hw_qpt_ptr;
+	void		*kv_qpt_ptr;
+	u32		page_count;
+	u32		page_size;
+};
+
+/**
+ *
+ * Device
+ *
+ */
+
+struct bna_device {
+	bfa_fsm_t		fsm;
+	struct bfa_ioc ioc;
+
+	enum bna_intr_type intr_type;
+	int			vector;
+
+	void (*ready_cbfn)(struct bnad *bnad, enum bna_cb_status status);
+	struct bnad *ready_cbarg;
+
+	void (*stop_cbfn)(struct bnad *bnad, enum bna_cb_status status);
+	struct bnad *stop_cbarg;
+
+	struct bna *bna;
+};
+
+/**
+ *
+ * Mail box
+ *
+ */
+
+struct bna_mbox_qe {
+	/* This should be the first one */
+	struct list_head			qe;
+
+	struct bfa_mbox_cmd cmd;
+	u32 		cmd_len;
+	/* Callback for port, tx, rx, rxf */
+	void (*cbfn)(void *arg, int status);
+	void 			*cbarg;
+};
+
+struct bna_mbox_mod {
+	enum bna_mbox_state state;
+	struct list_head			posted_q;
+	u32		msg_pending;
+	u32		msg_ctr;
+	struct bna *bna;
+};
+
+/**
+ *
+ * Port
+ *
+ */
+
+/* Pause configuration */
+struct bna_pause_config {
+	enum bna_status tx_pause;
+	enum bna_status rx_pause;
+};
+
+struct bna_llport {
+	bfa_fsm_t		fsm;
+	enum bna_llport_flags flags;
+
+	enum bna_port_type type;
+
+	enum bna_link_status link_status;
+
+	int			admin_up_count;
+
+	void (*stop_cbfn)(struct bna_port *, enum bna_cb_status);
+
+	struct bna_mbox_qe mbox_qe;
+
+	struct bna *bna;
+};
+
+struct bna_port {
+	bfa_fsm_t		fsm;
+	enum bna_port_flags flags;
+
+	enum bna_port_type type;
+
+	struct bna_llport llport;
+
+	struct bna_pause_config pause_config;
+	u8			priority;
+	int			mtu;
+
+	/* Callback for bna_port_disable(), port_stop() */
+	void (*stop_cbfn)(void *, enum bna_cb_status);
+	void			*stop_cbarg;
+
+	/* Callback for bna_port_pause_config() */
+	void (*pause_cbfn)(struct bnad *, enum bna_cb_status);
+
+	/* Callback for bna_port_mtu_set() */
+	void (*mtu_cbfn)(struct bnad *, enum bna_cb_status);
+
+	void (*link_cbfn)(struct bnad *, enum bna_link_status);
+
+	struct bfa_wc		chld_stop_wc;
+
+	struct bna_mbox_qe mbox_qe;
+
+	struct bna *bna;
+};
+
+/**
+ *
+ * Interrupt Block
+ *
+ */
+
+/* IB index segment structure */
+struct bna_ibidx_seg {
+	/* This should be the first one */
+	struct list_head			qe;
+
+	u8			ib_seg_size;
+	u8			ib_idx_tbl_offset;
+};
+
+/* Interrupt structure */
+struct bna_intr {
+	/* This should be the first one */
+	struct list_head			qe;
+	int			ref_count;
+
+	enum bna_intr_type intr_type;
+	int			vector;
+
+	struct bna_ib *ib;
+};
+
+/* Doorbell structure */
+struct bna_ib_dbell {
+	void *__iomem doorbell_addr;
+	u32		doorbell_ack;
+};
+
+/* Interrupt timer configuration */
+struct bna_ib_config {
+	u8 		coalescing_timeo;    /* Unit is 5usec. */
+
+	int			interpkt_count;
+	int			interpkt_timeo;
+
+	enum ib_flags ctrl_flags;
+};
+
+/* IB structure */
+struct bna_ib {
+	/* This should be the first one */
+	struct list_head			qe;
+
+	int			ib_id;
+
+	int			ref_count;
+	int			start_count;
+
+	struct bna_dma_addr ib_seg_host_addr;
+	void		*ib_seg_host_addr_kva;
+	u32		idx_mask; /* Size >= BNA_IBIDX_MAX_SEGSIZE */
+
+	struct bna_ibidx_seg *idx_seg;
+
+	struct bna_ib_dbell door_bell;
+
+	struct bna_intr *intr;
+
+	struct bna_ib_config ib_config;
+
+	struct bna *bna;
+};
+
+/* IB module - keeps track of IBs and interrupts */
+struct bna_ib_mod {
+	struct bna_ib *ib;		/* BFI_MAX_IB entries */
+	struct bna_intr *intr;		/* BFI_MAX_IB entries */
+	struct bna_ibidx_seg *idx_seg;	/* BNA_IBIDX_TOTAL_SEGS */
+
+	struct list_head			ib_free_q;
+
+	struct list_head		ibidx_seg_pool[BFI_IBIDX_TOTAL_POOLS];
+
+	struct list_head			intr_free_q;
+	struct list_head			intr_active_q;
+
+	struct bna *bna;
+};
+
+/**
+ *
+ * Tx object
+ *
+ */
+
+/* Tx datapath control structure */
+#define BNA_Q_NAME_SIZE		16
+struct bna_tcb {
+	/* Fast path */
+	void			**sw_qpt;
+	void			*unmap_q;
+	u32		producer_index;
+	u32		consumer_index;
+	volatile u32	*hw_consumer_index;
+	u32		q_depth;
+	void *__iomem q_dbell;
+	struct bna_ib_dbell *i_dbell;
+	int			page_idx;
+	int			page_count;
+	/* Control path */
+	struct bna_txq *txq;
+	struct bnad *bnad;
+	enum bna_intr_type intr_type;
+	int			intr_vector;
+	u8			priority; /* Current priority */
+	unsigned long		flags; /* Used by bnad as required */
+	int			id;
+	char			name[BNA_Q_NAME_SIZE];
+};
+
+/* TxQ QPT and configuration */
+struct bna_txq {
+	/* This should be the first one */
+	struct list_head			qe;
+
+	int			txq_id;
+
+	u8			priority;
+
+	struct bna_qpt qpt;
+	struct bna_tcb *tcb;
+	struct bna_ib *ib;
+	int			ib_seg_offset;
+
+	struct bna_tx *tx;
+
+	u64 		tx_packets;
+	u64 		tx_bytes;
+};
+
+/* TxF structure (hardware Tx Function) */
+struct bna_txf {
+	int			txf_id;
+	enum txf_flags ctrl_flags;
+	u16		vlan;
+};
+
+/* Tx object */
+struct bna_tx {
+	/* This should be the first one */
+	struct list_head			qe;
+
+	bfa_fsm_t		fsm;
+	enum bna_tx_flags flags;
+
+	enum bna_tx_type type;
+
+	struct list_head			txq_q;
+	struct bna_txf txf;
+
+	/* Tx event handlers */
+	void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *);
+	void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *);
+	void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *);
+	void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *);
+	void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *);
+
+	/* callback for bna_tx_disable(), bna_tx_stop() */
+	void (*stop_cbfn)(void *arg, struct bna_tx *tx,
+				enum bna_cb_status status);
+	void			*stop_cbarg;
+
+	/* callback for bna_tx_prio_set() */
+	void (*prio_change_cbfn)(struct bnad *bnad, struct bna_tx *tx,
+				enum bna_cb_status status);
+
+	struct bfa_wc		txq_stop_wc;
+
+	struct bna_mbox_qe mbox_qe;
+
+	struct bna *bna;
+	void			*priv;	/* bnad's cookie */
+};
+
+struct bna_tx_config {
+	int			num_txq;
+	int			txq_depth;
+	enum bna_tx_type tx_type;
+};
+
+struct bna_tx_event_cbfn {
+	/* Optional */
+	void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *);
+	void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *);
+	/* Mandatory */
+	void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *);
+	void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *);
+	void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *);
+};
+
+/* Tx module - keeps track of free, active tx objects */
+struct bna_tx_mod {
+	struct bna_tx *tx;		/* BFI_MAX_TXQ entries */
+	struct bna_txq *txq;		/* BFI_MAX_TXQ entries */
+
+	struct list_head			tx_free_q;
+	struct list_head			tx_active_q;
+
+	struct list_head			txq_free_q;
+
+	/* callback for bna_tx_mod_stop() */
+	void (*stop_cbfn)(struct bna_port *port,
+				enum bna_cb_status status);
+
+	struct bfa_wc		tx_stop_wc;
+
+	enum bna_tx_mod_flags flags;
+
+	int			priority;
+	int			cee_link;
+
+	u32		txf_bmap[2];
+
+	struct bna *bna;
+};
+
+/**
+ *
+ * Receive Indirection Table
+ *
+ */
+
+/* One row of RIT table */
+struct bna_rit_entry {
+	u8 large_rxq_id;	/* used for either large or data buffers */
+	u8 small_rxq_id;	/* used for either small or header buffers */
+};
+
+/* RIT segment */
+struct bna_rit_segment {
+	struct list_head			qe;
+
+	u32		rit_offset;
+	u32		rit_size;
+	/**
+	 * max_rit_size: Varies per RIT segment depending on how RIT is
+	 * partitioned
+	 */
+	u32		max_rit_size;
+
+	struct bna_rit_entry *rit;
+};
+
+struct bna_rit_mod {
+	struct bna_rit_entry *rit;
+	struct bna_rit_segment *rit_segment;
+
+	struct list_head		rit_seg_pool[BFI_RIT_SEG_TOTAL_POOLS];
+};
+
+/**
+ *
+ * Rx object
+ *
+ */
+
+/* Rx datapath control structure */
+struct bna_rcb {
+	/* Fast path */
+	void			**sw_qpt;
+	void			*unmap_q;
+	u32		producer_index;
+	u32		consumer_index;
+	u32		q_depth;
+	void *__iomem q_dbell;
+	int			page_idx;
+	int			page_count;
+	/* Control path */
+	struct bna_rxq *rxq;
+	struct bna_cq *cq;
+	struct bnad *bnad;
+	unsigned long		flags;
+	int			id;
+};
+
+/* RxQ structure - QPT, configuration */
+struct bna_rxq {
+	struct list_head			qe;
+	int			rxq_id;
+
+	int			buffer_size;
+	int			q_depth;
+
+	struct bna_qpt qpt;
+	struct bna_rcb *rcb;
+
+	struct bna_rxp *rxp;
+	struct bna_rx *rx;
+
+	u64 		rx_packets;
+	u64		rx_bytes;
+	u64 		rx_packets_with_error;
+	u64 		rxbuf_alloc_failed;
+};
+
+/* RxQ pair */
+union bna_rxq_u {
+	struct {
+		struct bna_rxq *hdr;
+		struct bna_rxq *data;
+	} hds;
+	struct {
+		struct bna_rxq *small;
+		struct bna_rxq *large;
+	} slr;
+	struct {
+		struct bna_rxq *only;
+		struct bna_rxq *reserved;
+	} single;
+};
+
+/* Packet rate for Dynamic Interrupt Moderation */
+struct bna_pkt_rate {
+	u32		small_pkt_cnt;
+	u32		large_pkt_cnt;
+};
+
+/* Completion control structure */
+struct bna_ccb {
+	/* Fast path */
+	void			**sw_qpt;
+	u32		producer_index;
+	volatile u32	*hw_producer_index;
+	u32		q_depth;
+	struct bna_ib_dbell *i_dbell;
+	struct bna_rcb *rcb[2];
+	void			*ctrl; /* For bnad */
+	struct bna_pkt_rate pkt_rate;
+	int			page_idx;
+	int			page_count;
+
+	/* Control path */
+	struct bna_cq *cq;
+	struct bnad *bnad;
+	enum bna_intr_type intr_type;
+	int			intr_vector;
+	u8			rx_coalescing_timeo; /* For NAPI */
+	int			id;
+	char			name[BNA_Q_NAME_SIZE];
+};
+
+/* CQ QPT, configuration  */
+struct bna_cq {
+	int			cq_id;
+
+	struct bna_qpt qpt;
+	struct bna_ccb *ccb;
+
+	struct bna_ib *ib;
+	u8			ib_seg_offset;
+
+	struct bna_rx *rx;
+};
+
+struct bna_rss_config {
+	enum rss_hash_type hash_type;
+	u8			hash_mask;
+	u32		toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN];
+};
+
+struct bna_hds_config {
+	enum hds_header_type hdr_type;
+	int			header_size;
+};
+
+/* This structure is used during RX creation */
+struct bna_rx_config {
+	enum bna_rx_type rx_type;
+	int			num_paths;
+	enum bna_rxp_type rxp_type;
+	int			paused;
+	int			q_depth;
+	/*
+	 * Small/Large (or Header/Data) buffer size to be configured
+	 * for SLR and HDS queue type. Large buffer size comes from
+	 * port->mtu.
+	 */
+	int			small_buff_size;
+
+	enum bna_status rss_status;
+	struct bna_rss_config rss_config;
+
+	enum bna_status hds_status;
+	struct bna_hds_config hds_config;
+
+	enum bna_status vlan_strip_status;
+};
+
+/* Rx Path structure - one per MSIX vector/CPU */
+struct bna_rxp {
+	/* This should be the first one */
+	struct list_head			qe;
+
+	enum bna_rxp_type type;
+	union	bna_rxq_u	rxq;
+	struct bna_cq cq;
+
+	struct bna_rx *rx;
+
+	/* MSI-x vector number for configuring RSS */
+	int			vector;
+
+	struct bna_mbox_qe mbox_qe;
+};
+
+/* HDS configuration structure */
+struct bna_rxf_hds {
+	enum hds_header_type hdr_type;
+	int			header_size;
+};
+
+/* RSS configuration structure */
+struct bna_rxf_rss {
+	enum rss_hash_type hash_type;
+	u8			hash_mask;
+	u32		toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN];
+};
+
+/* RxF structure (hardware Rx Function) */
+struct bna_rxf {
+	bfa_fsm_t		fsm;
+	int			rxf_id;
+	enum rxf_flags ctrl_flags;
+	u16		default_vlan_tag;
+	enum bna_rxf_oper_state rxf_oper_state;
+	enum bna_status hds_status;
+	struct bna_rxf_hds hds_cfg;
+	enum bna_status rss_status;
+	struct bna_rxf_rss rss_cfg;
+	struct bna_rit_segment *rit_segment;
+	struct bna_rx *rx;
+	u32		forced_offset;
+	struct bna_mbox_qe mbox_qe;
+	int			mcast_rxq_id;
+
+	/* callback for bna_rxf_start() */
+	void (*start_cbfn) (struct bna_rx *rx, enum bna_cb_status status);
+	struct bna_rx *start_cbarg;
+
+	/* callback for bna_rxf_stop() */
+	void (*stop_cbfn) (struct bna_rx *rx, enum bna_cb_status status);
+	struct bna_rx *stop_cbarg;
+
+	/* callback for bna_rxf_receive_enable() / bna_rxf_receive_disable() */
+	void (*oper_state_cbfn) (struct bnad *bnad, struct bna_rx *rx,
+			enum bna_cb_status status);
+	struct bnad *oper_state_cbarg;
+
+	/**
+	 * callback for:
+	 *	bna_rxf_ucast_set()
+	 *	bna_rxf_{ucast/mcast}_add(),
+	 * 	bna_rxf_{ucast/mcast}_del(),
+	 *	bna_rxf_mode_set()
+	 */
+	void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx,
+				enum bna_cb_status status);
+	struct bnad *cam_fltr_cbarg;
+
+	enum bna_rxf_flags rxf_flags;
+
+	/* List of unicast addresses yet to be applied to h/w */
+	struct list_head			ucast_pending_add_q;
+	struct list_head			ucast_pending_del_q;
+	int			ucast_pending_set;
+	/* ucast addresses applied to the h/w */
+	struct list_head			ucast_active_q;
+	struct bna_mac *ucast_active_mac;
+
+	/* List of multicast addresses yet to be applied to h/w */
+	struct list_head			mcast_pending_add_q;
+	struct list_head			mcast_pending_del_q;
+	/* multicast addresses applied to the h/w */
+	struct list_head			mcast_active_q;
+
+	/* Rx modes yet to be applied to h/w */
+	enum bna_rxmode rxmode_pending;
+	enum bna_rxmode rxmode_pending_bitmask;
+	/* Rx modes applied to h/w */
+	enum bna_rxmode rxmode_active;
+
+	enum bna_status vlan_filter_status;
+	u32		vlan_filter_table[(BFI_MAX_VLAN + 1) / 32];
+};
+
+/* Rx object */
+struct bna_rx {
+	/* This should be the first one */
+	struct list_head			qe;
+
+	bfa_fsm_t		fsm;
+
+	enum bna_rx_type type;
+
+	/* list-head for RX path objects */
+	struct list_head			rxp_q;
+
+	struct bna_rxf rxf;
+
+	enum bna_rx_flags rx_flags;
+
+	struct bna_mbox_qe mbox_qe;
+
+	struct bfa_wc		rxq_stop_wc;
+
+	/* Rx event handlers */
+	void (*rcb_setup_cbfn)(struct bnad *, struct bna_rcb *);
+	void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *);
+	void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *);
+	void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *);
+	void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *);
+	void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *);
+
+	/* callback for bna_rx_disable(), bna_rx_stop() */
+	void (*stop_cbfn)(void *arg, struct bna_rx *rx,
+				enum bna_cb_status status);
+	void			*stop_cbarg;
+
+	struct bna *bna;
+	void			*priv; /* bnad's cookie */
+};
+
+struct bna_rx_event_cbfn {
+	/* Optional */
+	void (*rcb_setup_cbfn)(struct bnad *, struct bna_rcb *);
+	void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *);
+	void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *);
+	void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *);
+	/* Mandatory */
+	void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *);
+	void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *);
+};
+
+/* Rx module - keeps track of free, active rx objects */
+struct bna_rx_mod {
+	struct bna *bna;		/* back pointer to parent */
+	struct bna_rx *rx;		/* BFI_MAX_RXQ entries */
+	struct bna_rxp *rxp;		/* BFI_MAX_RXQ entries */
+	struct bna_rxq *rxq;		/* BFI_MAX_RXQ entries */
+
+	struct list_head			rx_free_q;
+	struct list_head			rx_active_q;
+	int			rx_free_count;
+
+	struct list_head			rxp_free_q;
+	int			rxp_free_count;
+
+	struct list_head			rxq_free_q;
+	int			rxq_free_count;
+
+	enum bna_rx_mod_flags flags;
+
+	/* callback for bna_rx_mod_stop() */
+	void (*stop_cbfn)(struct bna_port *port,
+				enum bna_cb_status status);
+
+	struct bfa_wc		rx_stop_wc;
+	u32		dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX];
+	u32		rxf_bmap[2];
+};
+
+/**
+ *
+ * CAM
+ *
+ */
+
+struct bna_ucam_mod {
+	struct bna_mac *ucmac;		/* BFI_MAX_UCMAC entries */
+	struct list_head			free_q;
+
+	struct bna *bna;
+};
+
+struct bna_mcam_mod {
+	struct bna_mac *mcmac;		/* BFI_MAX_MCMAC entries */
+	struct list_head			free_q;
+
+	struct bna *bna;
+};
+
+/**
+ *
+ * Statistics
+ *
+ */
+
+struct bna_tx_stats {
+	int			tx_state;
+	int			tx_flags;
+	int			num_txqs;
+	u32		txq_bmap[2];
+	int			txf_id;
+};
+
+struct bna_rx_stats {
+	int			rx_state;
+	int			rx_flags;
+	int			num_rxps;
+	int			num_rxqs;
+	u32		rxq_bmap[2];
+	u32		cq_bmap[2];
+	int			rxf_id;
+	int			rxf_state;
+	int			rxf_oper_state;
+	int			num_active_ucast;
+	int			num_active_mcast;
+	int			rxmode_active;
+	int			vlan_filter_status;
+	u32		vlan_filter_table[(BFI_MAX_VLAN + 1) / 32];
+	int			rss_status;
+	int			hds_status;
+};
+
+struct bna_sw_stats {
+	int			device_state;
+	int			port_state;
+	int			port_flags;
+	int			llport_state;
+	int			priority;
+	int			num_active_tx;
+	int			num_active_rx;
+	struct bna_tx_stats tx_stats[BFI_MAX_TXQ];
+	struct bna_rx_stats rx_stats[BFI_MAX_RXQ];
+};
+
+struct bna_stats {
+	u32		txf_bmap[2];
+	u32		rxf_bmap[2];
+	struct bfi_ll_stats	*hw_stats;
+	struct bna_sw_stats *sw_stats;
+};
+
+/**
+ *
+ * BNA
+ *
+ */
+
+struct bna {
+	struct bfa_pcidev pcidev;
+
+	int			port_num;
+
+	struct bna_chip_regs regs;
+
+	struct bna_dma_addr hw_stats_dma;
+	struct bna_stats stats;
+
+	struct bna_device device;
+	struct bfa_cee cee;
+
+	struct bna_mbox_mod mbox_mod;
+
+	struct bna_port port;
+
+	struct bna_tx_mod tx_mod;
+
+	struct bna_rx_mod rx_mod;
+
+	struct bna_ib_mod ib_mod;
+
+	struct bna_ucam_mod ucam_mod;
+	struct bna_mcam_mod mcam_mod;
+
+	struct bna_rit_mod rit_mod;
+
+	int			rxf_default_id;
+	int			rxf_promisc_id;
+
+	struct bna_mbox_qe mbox_qe;
+
+	struct bnad *bnad;
+};
+
+#endif	/* __BNA_TYPES_H__ */
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
new file mode 100644
index 0000000..7e839b9
--- /dev/null
+++ b/drivers/net/bna/bnad.c
@@ -0,0 +1,3264 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/in.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/if_ether.h>
+#include <linux/ip.h>
+
+#include "bnad.h"
+#include "bna.h"
+#include "cna.h"
+
+static DEFINE_MUTEX(bnad_fwimg_mutex);
+
+/*
+ * Module params
+ */
+static uint bnad_msix_disable;
+module_param(bnad_msix_disable, uint, 0444);
+MODULE_PARM_DESC(bnad_msix_disable, "Disable MSIX mode");
+
+static uint bnad_ioc_auto_recover = 1;
+module_param(bnad_ioc_auto_recover, uint, 0444);
+MODULE_PARM_DESC(bnad_ioc_auto_recover, "Enable / Disable auto recovery");
+
+/*
+ * Global variables
+ */
+u32 bnad_rxqs_per_cq = 2;
+
+static const u8 bnad_bcast_addr[] =  {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+/*
+ * Local MACROS
+ */
+#define BNAD_TX_UNMAPQ_DEPTH (bnad->txq_depth * 2)
+
+#define BNAD_RX_UNMAPQ_DEPTH (bnad->rxq_depth)
+
+#define BNAD_GET_MBOX_IRQ(_bnad)				\
+	(((_bnad)->cfg_flags & BNAD_CF_MSIX) ?			\
+	 ((_bnad)->msix_table[(_bnad)->msix_num - 1].vector) : 	\
+	 ((_bnad)->pcidev->irq))
+
+#define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _depth)	\
+do {								\
+	(_res_info)->res_type = BNA_RES_T_MEM;			\
+	(_res_info)->res_u.mem_info.mem_type = BNA_MEM_T_KVA;	\
+	(_res_info)->res_u.mem_info.num = (_num);		\
+	(_res_info)->res_u.mem_info.len =			\
+	sizeof(struct bnad_unmap_q) +				\
+	(sizeof(struct bnad_skb_unmap) * ((_depth) - 1));	\
+} while (0)
+
+/*
+ * Reinitialize completions in CQ, once Rx is taken down
+ */
+static void
+bnad_cq_cmpl_init(struct bnad *bnad, struct bna_ccb *ccb)
+{
+	struct bna_cq_entry *cmpl, *next_cmpl;
+	unsigned int wi_range, wis = 0, ccb_prod = 0;
+	int i;
+
+	BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt, cmpl,
+			    wi_range);
+
+	for (i = 0; i < ccb->q_depth; i++) {
+		wis++;
+		if (likely(--wi_range))
+			next_cmpl = cmpl + 1;
+		else {
+			BNA_QE_INDX_ADD(ccb_prod, wis, ccb->q_depth);
+			wis = 0;
+			BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt,
+						next_cmpl, wi_range);
+		}
+		cmpl->valid = 0;
+		cmpl = next_cmpl;
+	}
+}
+
+/*
+ * Frees all pending Tx Bufs
+ * At this point no activity is expected on the Q,
+ * so DMA unmap & freeing is fine.
+ */
+static void
+bnad_free_all_txbufs(struct bnad *bnad,
+		 struct bna_tcb *tcb)
+{
+	u16 		unmap_cons;
+	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+	struct bnad_skb_unmap *unmap_array;
+	struct sk_buff 		*skb = NULL;
+	int			i;
+
+	unmap_array = unmap_q->unmap_array;
+
+	unmap_cons = 0;
+	while (unmap_cons < unmap_q->q_depth) {
+		skb = unmap_array[unmap_cons].skb;
+		if (!skb) {
+			unmap_cons++;
+			continue;
+		}
+		unmap_array[unmap_cons].skb = NULL;
+
+		pci_unmap_single(bnad->pcidev,
+				 pci_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);
+		unmap_cons++;
+		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+			pci_unmap_page(bnad->pcidev,
+				       pci_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,
+					   0);
+			unmap_cons++;
+		}
+		dev_kfree_skb_any(skb);
+	}
+}
+
+/* Data Path Handlers */
+
+/*
+ * bnad_free_txbufs : Frees the Tx bufs on Tx completion
+ * Can be called in a) Interrupt context
+ *		    b) Sending context
+ *		    c) Tasklet context
+ */
+static u32
+bnad_free_txbufs(struct bnad *bnad,
+		 struct bna_tcb *tcb)
+{
+	u32 		sent_packets = 0, sent_bytes = 0;
+	u16 		wis, unmap_cons, updated_hw_cons;
+	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+	struct bnad_skb_unmap *unmap_array;
+	struct sk_buff 		*skb;
+	int i;
+
+	/*
+	 * Just return if TX is stopped. This check is useful
+	 * when bnad_free_txbufs() runs out of a tasklet scheduled
+	 * before bnad_cb_tx_cleanup() cleared BNAD_RF_TX_STARTED bit
+	 * but this routine runs actually after the cleanup has been
+	 * executed.
+	 */
+	if (!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))
+		return 0;
+
+	updated_hw_cons = *(tcb->hw_consumer_index);
+
+	wis = BNA_Q_INDEX_CHANGE(tcb->consumer_index,
+				  updated_hw_cons, tcb->q_depth);
+
+	BUG_ON(!(wis <= BNA_QE_IN_USE_CNT(tcb, tcb->q_depth)));
+
+	unmap_array = unmap_q->unmap_array;
+	unmap_cons = unmap_q->consumer_index;
+
+	prefetch(&unmap_array[unmap_cons + 1]);
+	while (wis) {
+		skb = unmap_array[unmap_cons].skb;
+
+		unmap_array[unmap_cons].skb = NULL;
+
+		sent_packets++;
+		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_addr), skb_headlen(skb),
+				 PCI_DMA_TODEVICE);
+		pci_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_addr),
+				       skb_shinfo(skb)->frags[i].size,
+				       PCI_DMA_TODEVICE);
+			pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
+					   0);
+			BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth);
+		}
+		dev_kfree_skb_any(skb);
+	}
+
+	/* Update consumer pointers. */
+	tcb->consumer_index = updated_hw_cons;
+	unmap_q->consumer_index = unmap_cons;
+
+	tcb->txq->tx_packets += sent_packets;
+	tcb->txq->tx_bytes += sent_bytes;
+
+	return sent_packets;
+}
+
+/* Tx Free Tasklet function */
+/* Frees for all the tcb's in all the Tx's */
+/*
+ * Scheduled from sending context, so that
+ * the fat Tx lock is not held for too long
+ * in the sending context.
+ */
+static void
+bnad_tx_free_tasklet(unsigned long bnad_ptr)
+{
+	struct bnad *bnad = (struct bnad *)bnad_ptr;
+	struct bna_tcb *tcb;
+	u32 		acked;
+	int			i, j;
+
+	for (i = 0; i < bnad->num_tx; i++) {
+		for (j = 0; j < bnad->num_txq_per_tx; j++) {
+			tcb = bnad->tx_info[i].tcb[j];
+			if (!tcb)
+				continue;
+			if (((u16) (*tcb->hw_consumer_index) !=
+				tcb->consumer_index) &&
+				(!test_and_set_bit(BNAD_TXQ_FREE_SENT,
+						  &tcb->flags))) {
+				acked = bnad_free_txbufs(bnad, tcb);
+				bna_ib_ack(tcb->i_dbell, acked);
+				smp_mb__before_clear_bit();
+				clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+			}
+		}
+	}
+}
+
+static u32
+bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
+{
+	struct net_device *netdev = bnad->netdev;
+	u32 sent;
+
+	if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+		return 0;
+
+	sent = bnad_free_txbufs(bnad, tcb);
+	if (sent) {
+		if (netif_queue_stopped(netdev) &&
+		    netif_carrier_ok(netdev) &&
+		    BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
+				    BNAD_NETIF_WAKE_THRESHOLD) {
+			netif_wake_queue(netdev);
+			BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+		}
+		bna_ib_ack(tcb->i_dbell, sent);
+	} else
+		bna_ib_ack(tcb->i_dbell, 0);
+
+	smp_mb__before_clear_bit();
+	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+
+	return sent;
+}
+
+/* MSIX Tx Completion Handler */
+static irqreturn_t
+bnad_msix_tx(int irq, void *data)
+{
+	struct bna_tcb *tcb = (struct bna_tcb *)data;
+	struct bnad *bnad = tcb->bnad;
+
+	bnad_tx(bnad, tcb);
+
+	return IRQ_HANDLED;
+}
+
+static void
+bnad_reset_rcb(struct bnad *bnad, struct bna_rcb *rcb)
+{
+	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+
+	rcb->producer_index = 0;
+	rcb->consumer_index = 0;
+
+	unmap_q->producer_index = 0;
+	unmap_q->consumer_index = 0;
+}
+
+static void
+bnad_free_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
+{
+	struct bnad_unmap_q *unmap_q;
+	struct sk_buff *skb;
+
+	unmap_q = rcb->unmap_q;
+	while (BNA_QE_IN_USE_CNT(unmap_q, unmap_q->q_depth)) {
+		skb = unmap_q->unmap_array[unmap_q->consumer_index].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],
+					dma_addr), rcb->rxq->buffer_size +
+					NET_IP_ALIGN, PCI_DMA_FROMDEVICE);
+		dev_kfree_skb(skb);
+		BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
+		BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth);
+	}
+
+	bnad_reset_rcb(bnad, rcb);
+}
+
+static void
+bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
+{
+	u16 to_alloc, alloced, unmap_prod, wi_range;
+	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+	struct bnad_skb_unmap *unmap_array;
+	struct bna_rxq_entry *rxent;
+	struct sk_buff *skb;
+	dma_addr_t dma_addr;
+
+	alloced = 0;
+	to_alloc =
+		BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth);
+
+	unmap_array = unmap_q->unmap_array;
+	unmap_prod = unmap_q->producer_index;
+
+	BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent, wi_range);
+
+	while (to_alloc--) {
+		if (!wi_range) {
+			BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent,
+					     wi_range);
+		}
+		skb = alloc_skb(rcb->rxq->buffer_size + NET_IP_ALIGN,
+				     GFP_ATOMIC);
+		if (unlikely(!skb)) {
+			BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed);
+			goto finishing;
+		}
+		skb->dev = bnad->netdev;
+		skb_reserve(skb, NET_IP_ALIGN);
+		unmap_array[unmap_prod].skb = skb;
+		dma_addr = 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);
+		BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr);
+		BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+
+		rxent++;
+		wi_range--;
+		alloced++;
+	}
+
+finishing:
+	if (likely(alloced)) {
+		unmap_q->producer_index = unmap_prod;
+		rcb->producer_index = unmap_prod;
+		smp_mb();
+		bna_rxq_prod_indx_doorbell(rcb);
+	}
+}
+
+/*
+ * Locking is required in the enable path
+ * because it is called from a napi poll
+ * context, where the bna_lock is not held
+ * unlike the IRQ context.
+ */
+static void
+bnad_enable_txrx_irqs(struct bnad *bnad)
+{
+	struct bna_tcb *tcb;
+	struct bna_ccb *ccb;
+	int i, j;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	for (i = 0; i < bnad->num_tx; i++) {
+		for (j = 0; j < bnad->num_txq_per_tx; j++) {
+			tcb = bnad->tx_info[i].tcb[j];
+			bna_ib_coalescing_timer_set(tcb->i_dbell,
+				tcb->txq->ib->ib_config.coalescing_timeo);
+			bna_ib_ack(tcb->i_dbell, 0);
+		}
+	}
+
+	for (i = 0; i < bnad->num_rx; i++) {
+		for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+			ccb = bnad->rx_info[i].rx_ctrl[j].ccb;
+			bnad_enable_rx_irq_unsafe(ccb);
+		}
+	}
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static inline void
+bnad_refill_rxq(struct bnad *bnad, struct bna_rcb *rcb)
+{
+	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+
+	if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
+		if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
+			 >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
+			bnad_alloc_n_post_rxbufs(bnad, rcb);
+		smp_mb__before_clear_bit();
+		clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
+	}
+}
+
+static u32
+bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
+{
+	struct bna_cq_entry *cmpl, *next_cmpl;
+	struct bna_rcb *rcb = NULL;
+	unsigned int wi_range, packets = 0, wis = 0;
+	struct bnad_unmap_q *unmap_q;
+	struct sk_buff *skb;
+	u32 flags;
+	u32 qid0 = ccb->rcb[0]->rxq->rxq_id;
+	struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
+
+	prefetch(bnad->netdev);
+	BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
+			    wi_range);
+	BUG_ON(!(wi_range <= ccb->q_depth));
+	while (cmpl->valid && packets < budget) {
+		packets++;
+		BNA_UPDATE_PKT_CNT(pkt_rt, ntohs(cmpl->length));
+
+		if (qid0 == cmpl->rxq_id)
+			rcb = ccb->rcb[0];
+		else
+			rcb = ccb->rcb[1];
+
+		unmap_q = rcb->unmap_q;
+
+		skb = unmap_q->unmap_array[unmap_q->consumer_index].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],
+						dma_addr),
+						rcb->rxq->buffer_size,
+						PCI_DMA_FROMDEVICE);
+		BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
+
+		/* Should be more efficient ? Performance ? */
+		BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth);
+
+		wis++;
+		if (likely(--wi_range))
+			next_cmpl = cmpl + 1;
+		else {
+			BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
+			wis = 0;
+			BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt,
+						next_cmpl, wi_range);
+			BUG_ON(!(wi_range <= ccb->q_depth));
+		}
+		prefetch(next_cmpl);
+
+		flags = ntohl(cmpl->flags);
+		if (unlikely
+		    (flags &
+		     (BNA_CQ_EF_MAC_ERROR | BNA_CQ_EF_FCS_ERROR |
+		      BNA_CQ_EF_TOO_LONG))) {
+			dev_kfree_skb_any(skb);
+			rcb->rxq->rx_packets_with_error++;
+			goto next;
+		}
+
+		skb_put(skb, ntohs(cmpl->length));
+		if (likely
+		    (bnad->rx_csum &&
+		     (((flags & BNA_CQ_EF_IPV4) &&
+		      (flags & BNA_CQ_EF_L3_CKSUM_OK)) ||
+		      (flags & BNA_CQ_EF_IPV6)) &&
+		      (flags & (BNA_CQ_EF_TCP | BNA_CQ_EF_UDP)) &&
+		      (flags & BNA_CQ_EF_L4_CKSUM_OK)))
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+		else
+			skb_checksum_none_assert(skb);
+
+		rcb->rxq->rx_packets++;
+		rcb->rxq->rx_bytes += skb->len;
+		skb->protocol = eth_type_trans(skb, bnad->netdev);
+
+		if (bnad->vlan_grp && (flags & BNA_CQ_EF_VLAN)) {
+			struct bnad_rx_ctrl *rx_ctrl =
+				(struct bnad_rx_ctrl *)ccb->ctrl;
+			if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+				vlan_gro_receive(&rx_ctrl->napi, bnad->vlan_grp,
+						ntohs(cmpl->vlan_tag), skb);
+			else
+				vlan_hwaccel_receive_skb(skb,
+							 bnad->vlan_grp,
+							 ntohs(cmpl->vlan_tag));
+
+		} else { /* Not VLAN tagged/stripped */
+			struct bnad_rx_ctrl *rx_ctrl =
+				(struct bnad_rx_ctrl *)ccb->ctrl;
+			if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+				napi_gro_receive(&rx_ctrl->napi, skb);
+			else
+				netif_receive_skb(skb);
+		}
+
+next:
+		cmpl->valid = 0;
+		cmpl = next_cmpl;
+	}
+
+	BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
+
+	if (likely(ccb)) {
+		bna_ib_ack(ccb->i_dbell, packets);
+		bnad_refill_rxq(bnad, ccb->rcb[0]);
+		if (ccb->rcb[1])
+			bnad_refill_rxq(bnad, ccb->rcb[1]);
+	} else
+		bna_ib_ack(ccb->i_dbell, 0);
+
+	return packets;
+}
+
+static void
+bnad_disable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
+{
+	bna_ib_coalescing_timer_set(ccb->i_dbell, 0);
+	bna_ib_ack(ccb->i_dbell, 0);
+}
+
+static void
+bnad_enable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags); /* Because of polling context */
+	bnad_enable_rx_irq_unsafe(ccb);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static void
+bnad_netif_rx_schedule_poll(struct bnad *bnad, struct bna_ccb *ccb)
+{
+	struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
+	if (likely(napi_schedule_prep((&rx_ctrl->napi)))) {
+		bnad_disable_rx_irq(bnad, ccb);
+		__napi_schedule((&rx_ctrl->napi));
+	}
+	BNAD_UPDATE_CTR(bnad, netif_rx_schedule);
+}
+
+/* MSIX Rx Path Handler */
+static irqreturn_t
+bnad_msix_rx(int irq, void *data)
+{
+	struct bna_ccb *ccb = (struct bna_ccb *)data;
+	struct bnad *bnad = ccb->bnad;
+
+	bnad_netif_rx_schedule_poll(bnad, ccb);
+
+	return IRQ_HANDLED;
+}
+
+/* Interrupt handlers */
+
+/* Mbox Interrupt Handlers */
+static irqreturn_t
+bnad_msix_mbox_handler(int irq, void *data)
+{
+	u32 intr_status;
+	unsigned long flags;
+	struct net_device *netdev = data;
+	struct bnad *bnad;
+
+	bnad = netdev_priv(netdev);
+
+	/* BNA_ISR_GET(bnad); Inc Ref count */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+
+	bna_intr_status_get(&bnad->bna, intr_status);
+
+	if (BNA_IS_MBOX_ERR_INTR(intr_status))
+		bna_mbox_handler(&bnad->bna, intr_status);
+
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	/* BNAD_ISR_PUT(bnad); Dec Ref count */
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+bnad_isr(int irq, void *data)
+{
+	int i, j;
+	u32 intr_status;
+	unsigned long flags;
+	struct net_device *netdev = data;
+	struct bnad *bnad = netdev_priv(netdev);
+	struct bnad_rx_info *rx_info;
+	struct bnad_rx_ctrl *rx_ctrl;
+
+	if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
+		return IRQ_NONE;
+
+	bna_intr_status_get(&bnad->bna, intr_status);
+
+	if (unlikely(!intr_status))
+		return IRQ_NONE;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+
+	if (BNA_IS_MBOX_ERR_INTR(intr_status)) {
+		bna_mbox_handler(&bnad->bna, intr_status);
+		if (!BNA_IS_INTX_DATA_INTR(intr_status)) {
+			spin_unlock_irqrestore(&bnad->bna_lock, flags);
+			goto done;
+		}
+	}
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	/* Process data interrupts */
+	for (i = 0; i < bnad->num_rx; i++) {
+		rx_info = &bnad->rx_info[i];
+		if (!rx_info->rx)
+			continue;
+		for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+			rx_ctrl = &rx_info->rx_ctrl[j];
+			if (rx_ctrl->ccb)
+				bnad_netif_rx_schedule_poll(bnad,
+							    rx_ctrl->ccb);
+		}
+	}
+done:
+	return IRQ_HANDLED;
+}
+
+/*
+ * Called in interrupt / callback context
+ * with bna_lock held, so cfg_flags access is OK
+ */
+static void
+bnad_enable_mbox_irq(struct bnad *bnad)
+{
+	int irq = BNAD_GET_MBOX_IRQ(bnad);
+
+	if (test_and_clear_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
+		if (bnad->cfg_flags & BNAD_CF_MSIX)
+			enable_irq(irq);
+
+	BNAD_UPDATE_CTR(bnad, mbox_intr_enabled);
+}
+
+/*
+ * Called with bnad->bna_lock held b'cos of
+ * bnad->cfg_flags access.
+ */
+static void
+bnad_disable_mbox_irq(struct bnad *bnad)
+{
+	int irq = BNAD_GET_MBOX_IRQ(bnad);
+
+
+	if (!test_and_set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
+		if (bnad->cfg_flags & BNAD_CF_MSIX)
+			disable_irq_nosync(irq);
+
+	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
+}
+
+/* Control Path Handlers */
+
+/* Callbacks */
+void
+bnad_cb_device_enable_mbox_intr(struct bnad *bnad)
+{
+	bnad_enable_mbox_irq(bnad);
+}
+
+void
+bnad_cb_device_disable_mbox_intr(struct bnad *bnad)
+{
+	bnad_disable_mbox_irq(bnad);
+}
+
+void
+bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status)
+{
+	complete(&bnad->bnad_completions.ioc_comp);
+	bnad->bnad_completions.ioc_comp_status = status;
+}
+
+void
+bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status)
+{
+	complete(&bnad->bnad_completions.ioc_comp);
+	bnad->bnad_completions.ioc_comp_status = status;
+}
+
+static void
+bnad_cb_port_disabled(void *arg, enum bna_cb_status status)
+{
+	struct bnad *bnad = (struct bnad *)arg;
+
+	complete(&bnad->bnad_completions.port_comp);
+
+	netif_carrier_off(bnad->netdev);
+}
+
+void
+bnad_cb_port_link_status(struct bnad *bnad,
+			enum bna_link_status link_status)
+{
+	bool link_up = 0;
+
+	link_up = (link_status == BNA_LINK_UP) || (link_status == BNA_CEE_UP);
+
+	if (link_status == BNA_CEE_UP) {
+		set_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags);
+		BNAD_UPDATE_CTR(bnad, cee_up);
+	} else
+		clear_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags);
+
+	if (link_up) {
+		if (!netif_carrier_ok(bnad->netdev)) {
+			pr_warn("bna: %s link up\n",
+				bnad->netdev->name);
+			netif_carrier_on(bnad->netdev);
+			BNAD_UPDATE_CTR(bnad, link_toggle);
+			if (test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags)) {
+				/* Force an immediate Transmit Schedule */
+				pr_info("bna: %s TX_STARTED\n",
+					bnad->netdev->name);
+				netif_wake_queue(bnad->netdev);
+				BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+			} else {
+				netif_stop_queue(bnad->netdev);
+				BNAD_UPDATE_CTR(bnad, netif_queue_stop);
+			}
+		}
+	} else {
+		if (netif_carrier_ok(bnad->netdev)) {
+			pr_warn("bna: %s link down\n",
+				bnad->netdev->name);
+			netif_carrier_off(bnad->netdev);
+			BNAD_UPDATE_CTR(bnad, link_toggle);
+		}
+	}
+}
+
+static void
+bnad_cb_tx_disabled(void *arg, struct bna_tx *tx,
+			enum bna_cb_status status)
+{
+	struct bnad *bnad = (struct bnad *)arg;
+
+	complete(&bnad->bnad_completions.tx_comp);
+}
+
+static void
+bnad_cb_tcb_setup(struct bnad *bnad, struct bna_tcb *tcb)
+{
+	struct bnad_tx_info *tx_info =
+			(struct bnad_tx_info *)tcb->txq->tx->priv;
+	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+
+	tx_info->tcb[tcb->id] = tcb;
+	unmap_q->producer_index = 0;
+	unmap_q->consumer_index = 0;
+	unmap_q->q_depth = BNAD_TX_UNMAPQ_DEPTH;
+}
+
+static void
+bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb)
+{
+	struct bnad_tx_info *tx_info =
+			(struct bnad_tx_info *)tcb->txq->tx->priv;
+
+	tx_info->tcb[tcb->id] = NULL;
+}
+
+static void
+bnad_cb_rcb_setup(struct bnad *bnad, struct bna_rcb *rcb)
+{
+	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+
+	unmap_q->producer_index = 0;
+	unmap_q->consumer_index = 0;
+	unmap_q->q_depth = BNAD_RX_UNMAPQ_DEPTH;
+}
+
+static void
+bnad_cb_ccb_setup(struct bnad *bnad, struct bna_ccb *ccb)
+{
+	struct bnad_rx_info *rx_info =
+			(struct bnad_rx_info *)ccb->cq->rx->priv;
+
+	rx_info->rx_ctrl[ccb->id].ccb = ccb;
+	ccb->ctrl = &rx_info->rx_ctrl[ccb->id];
+}
+
+static void
+bnad_cb_ccb_destroy(struct bnad *bnad, struct bna_ccb *ccb)
+{
+	struct bnad_rx_info *rx_info =
+			(struct bnad_rx_info *)ccb->cq->rx->priv;
+
+	rx_info->rx_ctrl[ccb->id].ccb = NULL;
+}
+
+static void
+bnad_cb_tx_stall(struct bnad *bnad, struct bna_tcb *tcb)
+{
+	struct bnad_tx_info *tx_info =
+			(struct bnad_tx_info *)tcb->txq->tx->priv;
+
+	if (tx_info != &bnad->tx_info[0])
+		return;
+
+	clear_bit(BNAD_RF_TX_STARTED, &bnad->run_flags);
+	netif_stop_queue(bnad->netdev);
+	pr_info("bna: %s TX_STOPPED\n", bnad->netdev->name);
+}
+
+static void
+bnad_cb_tx_resume(struct bnad *bnad, struct bna_tcb *tcb)
+{
+	if (test_and_set_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))
+		return;
+
+	if (netif_carrier_ok(bnad->netdev)) {
+		pr_info("bna: %s TX_STARTED\n", bnad->netdev->name);
+		netif_wake_queue(bnad->netdev);
+		BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+	}
+}
+
+static void
+bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
+{
+	struct bnad_unmap_q *unmap_q;
+
+	if (!tcb || (!tcb->unmap_q))
+		return;
+
+	unmap_q = tcb->unmap_q;
+	if (!unmap_q->unmap_array)
+		return;
+
+	if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+		return;
+
+	bnad_free_all_txbufs(bnad, tcb);
+
+	unmap_q->producer_index = 0;
+	unmap_q->consumer_index = 0;
+
+	smp_mb__before_clear_bit();
+	clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+}
+
+static void
+bnad_cb_rx_cleanup(struct bnad *bnad,
+			struct bna_ccb *ccb)
+{
+	bnad_cq_cmpl_init(bnad, ccb);
+
+	bnad_free_rxbufs(bnad, ccb->rcb[0]);
+	clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags);
+
+	if (ccb->rcb[1]) {
+		bnad_free_rxbufs(bnad, ccb->rcb[1]);
+		clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
+	}
+}
+
+static void
+bnad_cb_rx_post(struct bnad *bnad, struct bna_rcb *rcb)
+{
+	struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+
+	set_bit(BNAD_RXQ_STARTED, &rcb->flags);
+
+	/* Now allocate & post buffers for this RCB */
+	/* !!Allocation in callback context */
+	if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
+		if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
+			 >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
+			bnad_alloc_n_post_rxbufs(bnad, rcb);
+		smp_mb__before_clear_bit();
+		clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
+	}
+}
+
+static void
+bnad_cb_rx_disabled(void *arg, struct bna_rx *rx,
+			enum bna_cb_status status)
+{
+	struct bnad *bnad = (struct bnad *)arg;
+
+	complete(&bnad->bnad_completions.rx_comp);
+}
+
+static void
+bnad_cb_rx_mcast_add(struct bnad *bnad, struct bna_rx *rx,
+				enum bna_cb_status status)
+{
+	bnad->bnad_completions.mcast_comp_status = status;
+	complete(&bnad->bnad_completions.mcast_comp);
+}
+
+void
+bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status,
+		       struct bna_stats *stats)
+{
+	if (status == BNA_CB_SUCCESS)
+		BNAD_UPDATE_CTR(bnad, hw_stats_updates);
+
+	if (!netif_running(bnad->netdev) ||
+		!test_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags))
+		return;
+
+	mod_timer(&bnad->stats_timer,
+		  jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ));
+}
+
+/* Resource allocation, free functions */
+
+static void
+bnad_mem_free(struct bnad *bnad,
+	      struct bna_mem_info *mem_info)
+{
+	int i;
+	dma_addr_t dma_pa;
+
+	if (mem_info->mdl == NULL)
+		return;
+
+	for (i = 0; i < mem_info->num; i++) {
+		if (mem_info->mdl[i].kva != NULL) {
+			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);
+			} else
+				kfree(mem_info->mdl[i].kva);
+		}
+	}
+	kfree(mem_info->mdl);
+	mem_info->mdl = NULL;
+}
+
+static int
+bnad_mem_alloc(struct bnad *bnad,
+	       struct bna_mem_info *mem_info)
+{
+	int i;
+	dma_addr_t dma_pa;
+
+	if ((mem_info->num == 0) || (mem_info->len == 0)) {
+		mem_info->mdl = NULL;
+		return 0;
+	}
+
+	mem_info->mdl = kcalloc(mem_info->num, sizeof(struct bna_mem_descr),
+				GFP_KERNEL);
+	if (mem_info->mdl == NULL)
+		return -ENOMEM;
+
+	if (mem_info->mem_type == BNA_MEM_T_DMA) {
+		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);
+
+			if (mem_info->mdl[i].kva == NULL)
+				goto err_return;
+
+			BNA_SET_DMA_ADDR(dma_pa,
+					 &(mem_info->mdl[i].dma));
+		}
+	} else {
+		for (i = 0; i < mem_info->num; i++) {
+			mem_info->mdl[i].len = mem_info->len;
+			mem_info->mdl[i].kva = kzalloc(mem_info->len,
+							GFP_KERNEL);
+			if (mem_info->mdl[i].kva == NULL)
+				goto err_return;
+		}
+	}
+
+	return 0;
+
+err_return:
+	bnad_mem_free(bnad, mem_info);
+	return -ENOMEM;
+}
+
+/* Free IRQ for Mailbox */
+static void
+bnad_mbox_irq_free(struct bnad *bnad,
+		   struct bna_intr_info *intr_info)
+{
+	int irq;
+	unsigned long flags;
+
+	if (intr_info->idl == NULL)
+		return;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bnad_disable_mbox_irq(bnad);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	irq = BNAD_GET_MBOX_IRQ(bnad);
+	free_irq(irq, bnad->netdev);
+
+	kfree(intr_info->idl);
+}
+
+/*
+ * Allocates IRQ for Mailbox, but keep it disabled
+ * This will be enabled once we get the mbox enable callback
+ * from bna
+ */
+static int
+bnad_mbox_irq_alloc(struct bnad *bnad,
+		    struct bna_intr_info *intr_info)
+{
+	int 		err;
+	unsigned long 	flags;
+	u32	irq;
+	irq_handler_t 	irq_handler;
+
+	/* Mbox should use only 1 vector */
+
+	intr_info->idl = kzalloc(sizeof(*(intr_info->idl)), GFP_KERNEL);
+	if (!intr_info->idl)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	if (bnad->cfg_flags & BNAD_CF_MSIX) {
+		irq_handler = (irq_handler_t)bnad_msix_mbox_handler;
+		irq = bnad->msix_table[bnad->msix_num - 1].vector;
+		flags = 0;
+		intr_info->intr_type = BNA_INTR_T_MSIX;
+		intr_info->idl[0].vector = bnad->msix_num - 1;
+	} else {
+		irq_handler = (irq_handler_t)bnad_isr;
+		irq = bnad->pcidev->irq;
+		flags = IRQF_SHARED;
+		intr_info->intr_type = BNA_INTR_T_INTX;
+		/* intr_info->idl.vector = 0 ? */
+	}
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	sprintf(bnad->mbox_irq_name, "%s", BNAD_NAME);
+
+	/*
+	 * Set the Mbox IRQ disable flag, so that the IRQ handler
+	 * called from request_irq() for SHARED IRQs do not execute
+	 */
+	set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
+
+	err = request_irq(irq, irq_handler, flags,
+			  bnad->mbox_irq_name, bnad->netdev);
+
+	if (err) {
+		kfree(intr_info->idl);
+		intr_info->idl = NULL;
+		return err;
+	}
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+
+	if (bnad->cfg_flags & BNAD_CF_MSIX)
+		disable_irq_nosync(irq);
+
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+	return 0;
+}
+
+static void
+bnad_txrx_irq_free(struct bnad *bnad, struct bna_intr_info *intr_info)
+{
+	kfree(intr_info->idl);
+	intr_info->idl = NULL;
+}
+
+/* Allocates Interrupt Descriptor List for MSIX/INT-X vectors */
+static int
+bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
+		    uint txrx_id, struct bna_intr_info *intr_info)
+{
+	int i, vector_start = 0;
+	u32 cfg_flags;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	cfg_flags = bnad->cfg_flags;
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	if (cfg_flags & BNAD_CF_MSIX) {
+		intr_info->intr_type = BNA_INTR_T_MSIX;
+		intr_info->idl = kcalloc(intr_info->num,
+					sizeof(struct bna_intr_descr),
+					GFP_KERNEL);
+		if (!intr_info->idl)
+			return -ENOMEM;
+
+		switch (src) {
+		case BNAD_INTR_TX:
+			vector_start = txrx_id;
+			break;
+
+		case BNAD_INTR_RX:
+			vector_start = bnad->num_tx * bnad->num_txq_per_tx +
+					txrx_id;
+			break;
+
+		default:
+			BUG();
+		}
+
+		for (i = 0; i < intr_info->num; i++)
+			intr_info->idl[i].vector = vector_start + i;
+	} else {
+		intr_info->intr_type = BNA_INTR_T_INTX;
+		intr_info->num = 1;
+		intr_info->idl = kcalloc(intr_info->num,
+					sizeof(struct bna_intr_descr),
+					GFP_KERNEL);
+		if (!intr_info->idl)
+			return -ENOMEM;
+
+		switch (src) {
+		case BNAD_INTR_TX:
+			intr_info->idl[0].vector = 0x1; /* Bit mask : Tx IB */
+			break;
+
+		case BNAD_INTR_RX:
+			intr_info->idl[0].vector = 0x2; /* Bit mask : Rx IB */
+			break;
+		}
+	}
+	return 0;
+}
+
+/**
+ * NOTE: Should be called for MSIX only
+ * Unregisters Tx MSIX vector(s) from the kernel
+ */
+static void
+bnad_tx_msix_unregister(struct bnad *bnad, struct bnad_tx_info *tx_info,
+			int num_txqs)
+{
+	int i;
+	int vector_num;
+
+	for (i = 0; i < num_txqs; i++) {
+		if (tx_info->tcb[i] == NULL)
+			continue;
+
+		vector_num = tx_info->tcb[i]->intr_vector;
+		free_irq(bnad->msix_table[vector_num].vector, tx_info->tcb[i]);
+	}
+}
+
+/**
+ * NOTE: Should be called for MSIX only
+ * Registers Tx MSIX vector(s) and ISR(s), cookie with the kernel
+ */
+static int
+bnad_tx_msix_register(struct bnad *bnad, struct bnad_tx_info *tx_info,
+			uint tx_id, int num_txqs)
+{
+	int i;
+	int err;
+	int vector_num;
+
+	for (i = 0; i < num_txqs; i++) {
+		vector_num = tx_info->tcb[i]->intr_vector;
+		sprintf(tx_info->tcb[i]->name, "%s TXQ %d", bnad->netdev->name,
+				tx_id + tx_info->tcb[i]->id);
+		err = request_irq(bnad->msix_table[vector_num].vector,
+				  (irq_handler_t)bnad_msix_tx, 0,
+				  tx_info->tcb[i]->name,
+				  tx_info->tcb[i]);
+		if (err)
+			goto err_return;
+	}
+
+	return 0;
+
+err_return:
+	if (i > 0)
+		bnad_tx_msix_unregister(bnad, tx_info, (i - 1));
+	return -1;
+}
+
+/**
+ * NOTE: Should be called for MSIX only
+ * Unregisters Rx MSIX vector(s) from the kernel
+ */
+static void
+bnad_rx_msix_unregister(struct bnad *bnad, struct bnad_rx_info *rx_info,
+			int num_rxps)
+{
+	int i;
+	int vector_num;
+
+	for (i = 0; i < num_rxps; i++) {
+		if (rx_info->rx_ctrl[i].ccb == NULL)
+			continue;
+
+		vector_num = rx_info->rx_ctrl[i].ccb->intr_vector;
+		free_irq(bnad->msix_table[vector_num].vector,
+			 rx_info->rx_ctrl[i].ccb);
+	}
+}
+
+/**
+ * NOTE: Should be called for MSIX only
+ * Registers Tx MSIX vector(s) and ISR(s), cookie with the kernel
+ */
+static int
+bnad_rx_msix_register(struct bnad *bnad, struct bnad_rx_info *rx_info,
+			uint rx_id, int num_rxps)
+{
+	int i;
+	int err;
+	int vector_num;
+
+	for (i = 0; i < num_rxps; i++) {
+		vector_num = rx_info->rx_ctrl[i].ccb->intr_vector;
+		sprintf(rx_info->rx_ctrl[i].ccb->name, "%s CQ %d",
+			bnad->netdev->name,
+			rx_id + rx_info->rx_ctrl[i].ccb->id);
+		err = request_irq(bnad->msix_table[vector_num].vector,
+				  (irq_handler_t)bnad_msix_rx, 0,
+				  rx_info->rx_ctrl[i].ccb->name,
+				  rx_info->rx_ctrl[i].ccb);
+		if (err)
+			goto err_return;
+	}
+
+	return 0;
+
+err_return:
+	if (i > 0)
+		bnad_rx_msix_unregister(bnad, rx_info, (i - 1));
+	return -1;
+}
+
+/* Free Tx object Resources */
+static void
+bnad_tx_res_free(struct bnad *bnad, struct bna_res_info *res_info)
+{
+	int i;
+
+	for (i = 0; i < BNA_TX_RES_T_MAX; i++) {
+		if (res_info[i].res_type == BNA_RES_T_MEM)
+			bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
+		else if (res_info[i].res_type == BNA_RES_T_INTR)
+			bnad_txrx_irq_free(bnad, &res_info[i].res_u.intr_info);
+	}
+}
+
+/* Allocates memory and interrupt resources for Tx object */
+static int
+bnad_tx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
+		  uint tx_id)
+{
+	int i, err = 0;
+
+	for (i = 0; i < BNA_TX_RES_T_MAX; i++) {
+		if (res_info[i].res_type == BNA_RES_T_MEM)
+			err = bnad_mem_alloc(bnad,
+					&res_info[i].res_u.mem_info);
+		else if (res_info[i].res_type == BNA_RES_T_INTR)
+			err = bnad_txrx_irq_alloc(bnad, BNAD_INTR_TX, tx_id,
+					&res_info[i].res_u.intr_info);
+		if (err)
+			goto err_return;
+	}
+	return 0;
+
+err_return:
+	bnad_tx_res_free(bnad, res_info);
+	return err;
+}
+
+/* Free Rx object Resources */
+static void
+bnad_rx_res_free(struct bnad *bnad, struct bna_res_info *res_info)
+{
+	int i;
+
+	for (i = 0; i < BNA_RX_RES_T_MAX; i++) {
+		if (res_info[i].res_type == BNA_RES_T_MEM)
+			bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
+		else if (res_info[i].res_type == BNA_RES_T_INTR)
+			bnad_txrx_irq_free(bnad, &res_info[i].res_u.intr_info);
+	}
+}
+
+/* Allocates memory and interrupt resources for Rx object */
+static int
+bnad_rx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
+		  uint rx_id)
+{
+	int i, err = 0;
+
+	/* All memory needs to be allocated before setup_ccbs */
+	for (i = 0; i < BNA_RX_RES_T_MAX; i++) {
+		if (res_info[i].res_type == BNA_RES_T_MEM)
+			err = bnad_mem_alloc(bnad,
+					&res_info[i].res_u.mem_info);
+		else if (res_info[i].res_type == BNA_RES_T_INTR)
+			err = bnad_txrx_irq_alloc(bnad, BNAD_INTR_RX, rx_id,
+					&res_info[i].res_u.intr_info);
+		if (err)
+			goto err_return;
+	}
+	return 0;
+
+err_return:
+	bnad_rx_res_free(bnad, res_info);
+	return err;
+}
+
+/* Timer callbacks */
+/* a) IOC timer */
+static void
+bnad_ioc_timeout(unsigned long data)
+{
+	struct bnad *bnad = (struct bnad *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bfa_nw_ioc_timeout((void *) &bnad->bna.device.ioc);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static void
+bnad_ioc_hb_check(unsigned long data)
+{
+	struct bnad *bnad = (struct bnad *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bfa_nw_ioc_hb_check((void *) &bnad->bna.device.ioc);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static void
+bnad_ioc_sem_timeout(unsigned long data)
+{
+	struct bnad *bnad = (struct bnad *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bfa_nw_ioc_sem_timeout((void *) &bnad->bna.device.ioc);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+/*
+ * All timer routines use bnad->bna_lock to protect against
+ * the following race, which may occur in case of no locking:
+ * 	Time	CPU m  		CPU n
+ *	0       1 = test_bit
+ *	1			clear_bit
+ *	2			del_timer_sync
+ *	3	mod_timer
+ */
+
+/* b) Dynamic Interrupt Moderation Timer */
+static void
+bnad_dim_timeout(unsigned long data)
+{
+	struct bnad *bnad = (struct bnad *)data;
+	struct bnad_rx_info *rx_info;
+	struct bnad_rx_ctrl *rx_ctrl;
+	int i, j;
+	unsigned long flags;
+
+	if (!netif_carrier_ok(bnad->netdev))
+		return;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	for (i = 0; i < bnad->num_rx; i++) {
+		rx_info = &bnad->rx_info[i];
+		if (!rx_info->rx)
+			continue;
+		for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+			rx_ctrl = &rx_info->rx_ctrl[j];
+			if (!rx_ctrl->ccb)
+				continue;
+			bna_rx_dim_update(rx_ctrl->ccb);
+		}
+	}
+
+	/* Check for BNAD_CF_DIM_ENABLED, does not eleminate a race */
+	if (test_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags))
+		mod_timer(&bnad->dim_timer,
+			  jiffies + msecs_to_jiffies(BNAD_DIM_TIMER_FREQ));
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+/* c)  Statistics Timer */
+static void
+bnad_stats_timeout(unsigned long data)
+{
+	struct bnad *bnad = (struct bnad *)data;
+	unsigned long flags;
+
+	if (!netif_running(bnad->netdev) ||
+		!test_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags))
+		return;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_stats_get(&bnad->bna);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+/*
+ * Set up timer for DIM
+ * Called with bnad->bna_lock held
+ */
+void
+bnad_dim_timer_start(struct bnad *bnad)
+{
+	if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED &&
+	    !test_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags)) {
+		setup_timer(&bnad->dim_timer, bnad_dim_timeout,
+			    (unsigned long)bnad);
+		set_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags);
+		mod_timer(&bnad->dim_timer,
+			  jiffies + msecs_to_jiffies(BNAD_DIM_TIMER_FREQ));
+	}
+}
+
+/*
+ * Set up timer for statistics
+ * Called with mutex_lock(&bnad->conf_mutex) held
+ */
+static void
+bnad_stats_timer_start(struct bnad *bnad)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	if (!test_and_set_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags)) {
+		setup_timer(&bnad->stats_timer, bnad_stats_timeout,
+			    (unsigned long)bnad);
+		mod_timer(&bnad->stats_timer,
+			  jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ));
+	}
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+/*
+ * Stops the stats timer
+ * Called with mutex_lock(&bnad->conf_mutex) held
+ */
+static void
+bnad_stats_timer_stop(struct bnad *bnad)
+{
+	int to_del = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	if (test_and_clear_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags))
+		to_del = 1;
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+	if (to_del)
+		del_timer_sync(&bnad->stats_timer);
+}
+
+/* Utilities */
+
+static void
+bnad_netdev_mc_list_get(struct net_device *netdev, u8 *mc_list)
+{
+	int i = 1; /* Index 0 has broadcast address */
+	struct netdev_hw_addr *mc_addr;
+
+	netdev_for_each_mc_addr(mc_addr, netdev) {
+		memcpy(&mc_list[i * ETH_ALEN], &mc_addr->addr[0],
+							ETH_ALEN);
+		i++;
+	}
+}
+
+static int
+bnad_napi_poll_rx(struct napi_struct *napi, int budget)
+{
+	struct bnad_rx_ctrl *rx_ctrl =
+		container_of(napi, struct bnad_rx_ctrl, napi);
+	struct bna_ccb *ccb;
+	struct bnad *bnad;
+	int rcvd = 0;
+
+	ccb = rx_ctrl->ccb;
+
+	bnad = ccb->bnad;
+
+	if (!netif_carrier_ok(bnad->netdev))
+		goto poll_exit;
+
+	rcvd = bnad_poll_cq(bnad, ccb, budget);
+	if (rcvd == budget)
+		return rcvd;
+
+poll_exit:
+	napi_complete((napi));
+
+	BNAD_UPDATE_CTR(bnad, netif_rx_complete);
+
+	bnad_enable_rx_irq(bnad, ccb);
+	return rcvd;
+}
+
+static int
+bnad_napi_poll_txrx(struct napi_struct *napi, int budget)
+{
+	struct bnad_rx_ctrl *rx_ctrl =
+		container_of(napi, struct bnad_rx_ctrl, napi);
+	struct bna_ccb *ccb;
+	struct bnad *bnad;
+	int 			rcvd = 0;
+	int			i, j;
+
+	ccb = rx_ctrl->ccb;
+
+	bnad = ccb->bnad;
+
+	if (!netif_carrier_ok(bnad->netdev))
+		goto poll_exit;
+
+	/* Handle Tx Completions, if any */
+	for (i = 0; i < bnad->num_tx; i++) {
+		for (j = 0; j < bnad->num_txq_per_tx; j++)
+			bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+	}
+
+	/* Handle Rx Completions */
+	rcvd = bnad_poll_cq(bnad, ccb, budget);
+	if (rcvd == budget)
+		return rcvd;
+poll_exit:
+	napi_complete((napi));
+
+	BNAD_UPDATE_CTR(bnad, netif_rx_complete);
+
+	bnad_enable_txrx_irqs(bnad);
+	return rcvd;
+}
+
+static void
+bnad_napi_enable(struct bnad *bnad, u32 rx_id)
+{
+	int (*napi_poll) (struct napi_struct *, int);
+	struct bnad_rx_ctrl *rx_ctrl;
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	if (bnad->cfg_flags & BNAD_CF_MSIX)
+		napi_poll = bnad_napi_poll_rx;
+	else
+		napi_poll = bnad_napi_poll_txrx;
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	/* Initialize & enable NAPI */
+	for (i = 0; i <	bnad->num_rxp_per_rx; i++) {
+		rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i];
+		netif_napi_add(bnad->netdev, &rx_ctrl->napi,
+			       napi_poll, 64);
+		napi_enable(&rx_ctrl->napi);
+	}
+}
+
+static void
+bnad_napi_disable(struct bnad *bnad, u32 rx_id)
+{
+	int i;
+
+	/* First disable and then clean up */
+	for (i = 0; i < bnad->num_rxp_per_rx; i++) {
+		napi_disable(&bnad->rx_info[rx_id].rx_ctrl[i].napi);
+		netif_napi_del(&bnad->rx_info[rx_id].rx_ctrl[i].napi);
+	}
+}
+
+/* Should be held with conf_lock held */
+void
+bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
+{
+	struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
+	struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0];
+	unsigned long flags;
+
+	if (!tx_info->tx)
+		return;
+
+	init_completion(&bnad->bnad_completions.tx_comp);
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_tx_disable(tx_info->tx, BNA_HARD_CLEANUP, bnad_cb_tx_disabled);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+	wait_for_completion(&bnad->bnad_completions.tx_comp);
+
+	if (tx_info->tcb[0]->intr_type == BNA_INTR_T_MSIX)
+		bnad_tx_msix_unregister(bnad, tx_info,
+			bnad->num_txq_per_tx);
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_tx_destroy(tx_info->tx);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	tx_info->tx = NULL;
+
+	if (0 == tx_id)
+		tasklet_kill(&bnad->tx_free_tasklet);
+
+	bnad_tx_res_free(bnad, res_info);
+}
+
+/* Should be held with conf_lock held */
+int
+bnad_setup_tx(struct bnad *bnad, uint tx_id)
+{
+	int err;
+	struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
+	struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0];
+	struct bna_intr_info *intr_info =
+			&res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info;
+	struct bna_tx_config *tx_config = &bnad->tx_config[tx_id];
+	struct bna_tx_event_cbfn tx_cbfn;
+	struct bna_tx *tx;
+	unsigned long flags;
+
+	/* Initialize the Tx object configuration */
+	tx_config->num_txq = bnad->num_txq_per_tx;
+	tx_config->txq_depth = bnad->txq_depth;
+	tx_config->tx_type = BNA_TX_T_REGULAR;
+
+	/* Initialize the tx event handlers */
+	tx_cbfn.tcb_setup_cbfn = bnad_cb_tcb_setup;
+	tx_cbfn.tcb_destroy_cbfn = bnad_cb_tcb_destroy;
+	tx_cbfn.tx_stall_cbfn = bnad_cb_tx_stall;
+	tx_cbfn.tx_resume_cbfn = bnad_cb_tx_resume;
+	tx_cbfn.tx_cleanup_cbfn = bnad_cb_tx_cleanup;
+
+	/* Get BNA's resource requirement for one tx object */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_tx_res_req(bnad->num_txq_per_tx,
+		bnad->txq_depth, res_info);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	/* Fill Unmap Q memory requirements */
+	BNAD_FILL_UNMAPQ_MEM_REQ(
+			&res_info[BNA_TX_RES_MEM_T_UNMAPQ],
+			bnad->num_txq_per_tx,
+			BNAD_TX_UNMAPQ_DEPTH);
+
+	/* Allocate resources */
+	err = bnad_tx_res_alloc(bnad, res_info, tx_id);
+	if (err)
+		return err;
+
+	/* Ask BNA to create one Tx object, supplying required resources */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	tx = bna_tx_create(&bnad->bna, bnad, tx_config, &tx_cbfn, res_info,
+			tx_info);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+	if (!tx)
+		goto err_return;
+	tx_info->tx = tx;
+
+	/* Register ISR for the Tx object */
+	if (intr_info->intr_type == BNA_INTR_T_MSIX) {
+		err = bnad_tx_msix_register(bnad, tx_info,
+			tx_id, bnad->num_txq_per_tx);
+		if (err)
+			goto err_return;
+	}
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_tx_enable(tx);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	return 0;
+
+err_return:
+	bnad_tx_res_free(bnad, res_info);
+	return err;
+}
+
+/* Setup the rx config for bna_rx_create */
+/* bnad decides the configuration */
+static void
+bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
+{
+	rx_config->rx_type = BNA_RX_T_REGULAR;
+	rx_config->num_paths = bnad->num_rxp_per_rx;
+
+	if (bnad->num_rxp_per_rx > 1) {
+		rx_config->rss_status = BNA_STATUS_T_ENABLED;
+		rx_config->rss_config.hash_type =
+				(BFI_RSS_T_V4_TCP |
+				 BFI_RSS_T_V6_TCP |
+				 BFI_RSS_T_V4_IP  |
+				 BFI_RSS_T_V6_IP);
+		rx_config->rss_config.hash_mask =
+				bnad->num_rxp_per_rx - 1;
+		get_random_bytes(rx_config->rss_config.toeplitz_hash_key,
+			sizeof(rx_config->rss_config.toeplitz_hash_key));
+	} else {
+		rx_config->rss_status = BNA_STATUS_T_DISABLED;
+		memset(&rx_config->rss_config, 0,
+		       sizeof(rx_config->rss_config));
+	}
+	rx_config->rxp_type = BNA_RXP_SLR;
+	rx_config->q_depth = bnad->rxq_depth;
+
+	rx_config->small_buff_size = BFI_SMALL_RXBUF_SIZE;
+
+	rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED;
+}
+
+/* Called with mutex_lock(&bnad->conf_mutex) held */
+void
+bnad_cleanup_rx(struct bnad *bnad, uint rx_id)
+{
+	struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
+	struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
+	struct bna_res_info *res_info = &bnad->rx_res_info[rx_id].res_info[0];
+	unsigned long flags;
+	int dim_timer_del = 0;
+
+	if (!rx_info->rx)
+		return;
+
+	if (0 == rx_id) {
+		spin_lock_irqsave(&bnad->bna_lock, flags);
+		dim_timer_del = bnad_dim_timer_running(bnad);
+		if (dim_timer_del)
+			clear_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags);
+		spin_unlock_irqrestore(&bnad->bna_lock, flags);
+		if (dim_timer_del)
+			del_timer_sync(&bnad->dim_timer);
+	}
+
+	bnad_napi_disable(bnad, rx_id);
+
+	init_completion(&bnad->bnad_completions.rx_comp);
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_rx_disable(rx_info->rx, BNA_HARD_CLEANUP, bnad_cb_rx_disabled);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+	wait_for_completion(&bnad->bnad_completions.rx_comp);
+
+	if (rx_info->rx_ctrl[0].ccb->intr_type == BNA_INTR_T_MSIX)
+		bnad_rx_msix_unregister(bnad, rx_info, rx_config->num_paths);
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_rx_destroy(rx_info->rx);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	rx_info->rx = NULL;
+
+	bnad_rx_res_free(bnad, res_info);
+}
+
+/* Called with mutex_lock(&bnad->conf_mutex) held */
+int
+bnad_setup_rx(struct bnad *bnad, uint rx_id)
+{
+	int err;
+	struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
+	struct bna_res_info *res_info = &bnad->rx_res_info[rx_id].res_info[0];
+	struct bna_intr_info *intr_info =
+			&res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
+	struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
+	struct bna_rx_event_cbfn rx_cbfn;
+	struct bna_rx *rx;
+	unsigned long flags;
+
+	/* Initialize the Rx object configuration */
+	bnad_init_rx_config(bnad, rx_config);
+
+	/* Initialize the Rx event handlers */
+	rx_cbfn.rcb_setup_cbfn = bnad_cb_rcb_setup;
+	rx_cbfn.rcb_destroy_cbfn = NULL;
+	rx_cbfn.ccb_setup_cbfn = bnad_cb_ccb_setup;
+	rx_cbfn.ccb_destroy_cbfn = bnad_cb_ccb_destroy;
+	rx_cbfn.rx_cleanup_cbfn = bnad_cb_rx_cleanup;
+	rx_cbfn.rx_post_cbfn = bnad_cb_rx_post;
+
+	/* Get BNA's resource requirement for one Rx object */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_rx_res_req(rx_config, res_info);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	/* Fill Unmap Q memory requirements */
+	BNAD_FILL_UNMAPQ_MEM_REQ(
+			&res_info[BNA_RX_RES_MEM_T_UNMAPQ],
+			rx_config->num_paths +
+			((rx_config->rxp_type == BNA_RXP_SINGLE) ? 0 :
+				rx_config->num_paths), BNAD_RX_UNMAPQ_DEPTH);
+
+	/* Allocate resource */
+	err = bnad_rx_res_alloc(bnad, res_info, rx_id);
+	if (err)
+		return err;
+
+	/* Ask BNA to create one Rx object, supplying required resources */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	rx = bna_rx_create(&bnad->bna, bnad, rx_config, &rx_cbfn, res_info,
+			rx_info);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+	if (!rx)
+		goto err_return;
+	rx_info->rx = rx;
+
+	/* Register ISR for the Rx object */
+	if (intr_info->intr_type == BNA_INTR_T_MSIX) {
+		err = bnad_rx_msix_register(bnad, rx_info, rx_id,
+						rx_config->num_paths);
+		if (err)
+			goto err_return;
+	}
+
+	/* Enable NAPI */
+	bnad_napi_enable(bnad, rx_id);
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	if (0 == rx_id) {
+		/* Set up Dynamic Interrupt Moderation Vector */
+		if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED)
+			bna_rx_dim_reconfig(&bnad->bna, bna_napi_dim_vector);
+
+		/* Enable VLAN filtering only on the default Rx */
+		bna_rx_vlanfilter_enable(rx);
+
+		/* Start the DIM timer */
+		bnad_dim_timer_start(bnad);
+	}
+
+	bna_rx_enable(rx);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	return 0;
+
+err_return:
+	bnad_cleanup_rx(bnad, rx_id);
+	return err;
+}
+
+/* Called with conf_lock & bnad->bna_lock held */
+void
+bnad_tx_coalescing_timeo_set(struct bnad *bnad)
+{
+	struct bnad_tx_info *tx_info;
+
+	tx_info = &bnad->tx_info[0];
+	if (!tx_info->tx)
+		return;
+
+	bna_tx_coalescing_timeo_set(tx_info->tx, bnad->tx_coalescing_timeo);
+}
+
+/* Called with conf_lock & bnad->bna_lock held */
+void
+bnad_rx_coalescing_timeo_set(struct bnad *bnad)
+{
+	struct bnad_rx_info *rx_info;
+	int 	i;
+
+	for (i = 0; i < bnad->num_rx; i++) {
+		rx_info = &bnad->rx_info[i];
+		if (!rx_info->rx)
+			continue;
+		bna_rx_coalescing_timeo_set(rx_info->rx,
+				bnad->rx_coalescing_timeo);
+	}
+}
+
+/*
+ * Called with bnad->bna_lock held
+ */
+static int
+bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr)
+{
+	int ret;
+
+	if (!is_valid_ether_addr(mac_addr))
+		return -EADDRNOTAVAIL;
+
+	/* If datapath is down, pretend everything went through */
+	if (!bnad->rx_info[0].rx)
+		return 0;
+
+	ret = bna_rx_ucast_set(bnad->rx_info[0].rx, mac_addr, NULL);
+	if (ret != BNA_CB_SUCCESS)
+		return -EADDRNOTAVAIL;
+
+	return 0;
+}
+
+/* Should be called with conf_lock held */
+static int
+bnad_enable_default_bcast(struct bnad *bnad)
+{
+	struct bnad_rx_info *rx_info = &bnad->rx_info[0];
+	int ret;
+	unsigned long flags;
+
+	init_completion(&bnad->bnad_completions.mcast_comp);
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	ret = bna_rx_mcast_add(rx_info->rx, (u8 *)bnad_bcast_addr,
+				bnad_cb_rx_mcast_add);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	if (ret == BNA_CB_SUCCESS)
+		wait_for_completion(&bnad->bnad_completions.mcast_comp);
+	else
+		return -ENODEV;
+
+	if (bnad->bnad_completions.mcast_comp_status != BNA_CB_SUCCESS)
+		return -ENODEV;
+
+	return 0;
+}
+
+/* Statistics utilities */
+void
+bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
+{
+	int i, j;
+
+	for (i = 0; i < bnad->num_rx; i++) {
+		for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+			if (bnad->rx_info[i].rx_ctrl[j].ccb) {
+				stats->rx_packets += bnad->rx_info[i].
+				rx_ctrl[j].ccb->rcb[0]->rxq->rx_packets;
+				stats->rx_bytes += bnad->rx_info[i].
+					rx_ctrl[j].ccb->rcb[0]->rxq->rx_bytes;
+				if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&
+					bnad->rx_info[i].rx_ctrl[j].ccb->
+					rcb[1]->rxq) {
+					stats->rx_packets +=
+						bnad->rx_info[i].rx_ctrl[j].
+						ccb->rcb[1]->rxq->rx_packets;
+					stats->rx_bytes +=
+						bnad->rx_info[i].rx_ctrl[j].
+						ccb->rcb[1]->rxq->rx_bytes;
+				}
+			}
+		}
+	}
+	for (i = 0; i < bnad->num_tx; i++) {
+		for (j = 0; j < bnad->num_txq_per_tx; j++) {
+			if (bnad->tx_info[i].tcb[j]) {
+				stats->tx_packets +=
+				bnad->tx_info[i].tcb[j]->txq->tx_packets;
+				stats->tx_bytes +=
+					bnad->tx_info[i].tcb[j]->txq->tx_bytes;
+			}
+		}
+	}
+}
+
+/*
+ * Must be called with the bna_lock held.
+ */
+void
+bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
+{
+	struct bfi_ll_stats_mac *mac_stats;
+	u64 bmap;
+	int i;
+
+	mac_stats = &bnad->stats.bna_stats->hw_stats->mac_stats;
+	stats->rx_errors =
+		mac_stats->rx_fcs_error + mac_stats->rx_alignment_error +
+		mac_stats->rx_frame_length_error + mac_stats->rx_code_error +
+		mac_stats->rx_undersize;
+	stats->tx_errors = mac_stats->tx_fcs_error +
+					mac_stats->tx_undersize;
+	stats->rx_dropped = mac_stats->rx_drop;
+	stats->tx_dropped = mac_stats->tx_drop;
+	stats->multicast = mac_stats->rx_multicast;
+	stats->collisions = mac_stats->tx_total_collision;
+
+	stats->rx_length_errors = mac_stats->rx_frame_length_error;
+
+	/* receive ring buffer overflow  ?? */
+
+	stats->rx_crc_errors = mac_stats->rx_fcs_error;
+	stats->rx_frame_errors = mac_stats->rx_alignment_error;
+	/* recv'r fifo overrun */
+	bmap = (u64)bnad->stats.bna_stats->rxf_bmap[0] |
+		((u64)bnad->stats.bna_stats->rxf_bmap[1] << 32);
+	for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+		if (bmap & 1) {
+			stats->rx_fifo_errors +=
+				bnad->stats.bna_stats->
+					hw_stats->rxf_stats[i].frame_drops;
+			break;
+		}
+		bmap >>= 1;
+	}
+}
+
+static void
+bnad_mbox_irq_sync(struct bnad *bnad)
+{
+	u32 irq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	if (bnad->cfg_flags & BNAD_CF_MSIX)
+		irq = bnad->msix_table[bnad->msix_num - 1].vector;
+	else
+		irq = bnad->pcidev->irq;
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	synchronize_irq(irq);
+}
+
+/* Utility used by bnad_start_xmit, for doing TSO */
+static int
+bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
+{
+	int err;
+
+	/* SKB_GSO_TCPV4 and SKB_GSO_TCPV6 is defined since 2.6.18. */
+	BUG_ON(!(skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4 ||
+		   skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6));
+	if (skb_header_cloned(skb)) {
+		err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+		if (err) {
+			BNAD_UPDATE_CTR(bnad, tso_err);
+			return err;
+		}
+	}
+
+	/*
+	 * For TSO, the TCP checksum field is seeded with pseudo-header sum
+	 * excluding the length field.
+	 */
+	if (skb->protocol == htons(ETH_P_IP)) {
+		struct iphdr *iph = ip_hdr(skb);
+
+		/* Do we really need these? */
+		iph->tot_len = 0;
+		iph->check = 0;
+
+		tcp_hdr(skb)->check =
+			~csum_tcpudp_magic(iph->saddr, iph->daddr, 0,
+					   IPPROTO_TCP, 0);
+		BNAD_UPDATE_CTR(bnad, tso4);
+	} else {
+		struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+
+		BUG_ON(!(skb->protocol == htons(ETH_P_IPV6)));
+		ipv6h->payload_len = 0;
+		tcp_hdr(skb)->check =
+			~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 0,
+					 IPPROTO_TCP, 0);
+		BNAD_UPDATE_CTR(bnad, tso6);
+	}
+
+	return 0;
+}
+
+/*
+ * Initialize Q numbers depending on Rx Paths
+ * Called with bnad->bna_lock held, because of cfg_flags
+ * access.
+ */
+static void
+bnad_q_num_init(struct bnad *bnad)
+{
+	int rxps;
+
+	rxps = min((uint)num_online_cpus(),
+			(uint)(BNAD_MAX_RXS * BNAD_MAX_RXPS_PER_RX));
+
+	if (!(bnad->cfg_flags & BNAD_CF_MSIX))
+		rxps = 1;	/* INTx */
+
+	bnad->num_rx = 1;
+	bnad->num_tx = 1;
+	bnad->num_rxp_per_rx = rxps;
+	bnad->num_txq_per_tx = BNAD_TXQ_NUM;
+}
+
+/*
+ * Adjusts the Q numbers, given a number of msix vectors
+ * Give preference to RSS as opposed to Tx priority Queues,
+ * in such a case, just use 1 Tx Q
+ * Called with bnad->bna_lock held b'cos of cfg_flags access
+ */
+static void
+bnad_q_num_adjust(struct bnad *bnad, int msix_vectors)
+{
+	bnad->num_txq_per_tx = 1;
+	if ((msix_vectors >= (bnad->num_tx * bnad->num_txq_per_tx)  +
+	     bnad_rxqs_per_cq + BNAD_MAILBOX_MSIX_VECTORS) &&
+	    (bnad->cfg_flags & BNAD_CF_MSIX)) {
+		bnad->num_rxp_per_rx = msix_vectors -
+			(bnad->num_tx * bnad->num_txq_per_tx) -
+			BNAD_MAILBOX_MSIX_VECTORS;
+	} else
+		bnad->num_rxp_per_rx = 1;
+}
+
+static void
+bnad_set_netdev_perm_addr(struct bnad *bnad)
+{
+	struct net_device *netdev = bnad->netdev;
+
+	memcpy(netdev->perm_addr, &bnad->perm_addr, netdev->addr_len);
+	if (is_zero_ether_addr(netdev->dev_addr))
+		memcpy(netdev->dev_addr, &bnad->perm_addr, netdev->addr_len);
+}
+
+/* Enable / disable device */
+static void
+bnad_device_disable(struct bnad *bnad)
+{
+	unsigned long flags;
+
+	init_completion(&bnad->bnad_completions.ioc_comp);
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_device_disable(&bnad->bna.device, BNA_HARD_CLEANUP);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	wait_for_completion(&bnad->bnad_completions.ioc_comp);
+}
+
+static int
+bnad_device_enable(struct bnad *bnad)
+{
+	int err = 0;
+	unsigned long flags;
+
+	init_completion(&bnad->bnad_completions.ioc_comp);
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_device_enable(&bnad->bna.device);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	wait_for_completion(&bnad->bnad_completions.ioc_comp);
+
+	if (bnad->bnad_completions.ioc_comp_status)
+		err = bnad->bnad_completions.ioc_comp_status;
+
+	return err;
+}
+
+/* Free BNA resources */
+static void
+bnad_res_free(struct bnad *bnad)
+{
+	int i;
+	struct bna_res_info *res_info = &bnad->res_info[0];
+
+	for (i = 0; i < BNA_RES_T_MAX; i++) {
+		if (res_info[i].res_type == BNA_RES_T_MEM)
+			bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
+		else
+			bnad_mbox_irq_free(bnad, &res_info[i].res_u.intr_info);
+	}
+}
+
+/* Allocates memory and interrupt resources for BNA */
+static int
+bnad_res_alloc(struct bnad *bnad)
+{
+	int i, err;
+	struct bna_res_info *res_info = &bnad->res_info[0];
+
+	for (i = 0; i < BNA_RES_T_MAX; i++) {
+		if (res_info[i].res_type == BNA_RES_T_MEM)
+			err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info);
+		else
+			err = bnad_mbox_irq_alloc(bnad,
+						  &res_info[i].res_u.intr_info);
+		if (err)
+			goto err_return;
+	}
+	return 0;
+
+err_return:
+	bnad_res_free(bnad);
+	return err;
+}
+
+/* Interrupt enable / disable */
+static void
+bnad_enable_msix(struct bnad *bnad)
+{
+	int i, ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	if (!(bnad->cfg_flags & BNAD_CF_MSIX)) {
+		spin_unlock_irqrestore(&bnad->bna_lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	if (bnad->msix_table)
+		return;
+
+	bnad->msix_table =
+		kcalloc(bnad->msix_num, sizeof(struct msix_entry), GFP_KERNEL);
+
+	if (!bnad->msix_table)
+		goto intx_mode;
+
+	for (i = 0; i < bnad->msix_num; i++)
+		bnad->msix_table[i].entry = i;
+
+	ret = pci_enable_msix(bnad->pcidev, bnad->msix_table, bnad->msix_num);
+	if (ret > 0) {
+		/* Not enough MSI-X vectors. */
+
+		spin_lock_irqsave(&bnad->bna_lock, flags);
+		/* ret = #of vectors that we got */
+		bnad_q_num_adjust(bnad, ret);
+		spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+		bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx)
+			+ (bnad->num_rx
+			* bnad->num_rxp_per_rx) +
+			 BNAD_MAILBOX_MSIX_VECTORS;
+
+		/* Try once more with adjusted numbers */
+		/* If this fails, fall back to INTx */
+		ret = pci_enable_msix(bnad->pcidev, bnad->msix_table,
+				      bnad->msix_num);
+		if (ret)
+			goto intx_mode;
+
+	} else if (ret < 0)
+		goto intx_mode;
+	return;
+
+intx_mode:
+
+	kfree(bnad->msix_table);
+	bnad->msix_table = NULL;
+	bnad->msix_num = 0;
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bnad->cfg_flags &= ~BNAD_CF_MSIX;
+	bnad_q_num_init(bnad);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static void
+bnad_disable_msix(struct bnad *bnad)
+{
+	u32 cfg_flags;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	cfg_flags = bnad->cfg_flags;
+	if (bnad->cfg_flags & BNAD_CF_MSIX)
+		bnad->cfg_flags &= ~BNAD_CF_MSIX;
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	if (cfg_flags & BNAD_CF_MSIX) {
+		pci_disable_msix(bnad->pcidev);
+		kfree(bnad->msix_table);
+		bnad->msix_table = NULL;
+	}
+}
+
+/* Netdev entry points */
+static int
+bnad_open(struct net_device *netdev)
+{
+	int err;
+	struct bnad *bnad = netdev_priv(netdev);
+	struct bna_pause_config pause_config;
+	int mtu;
+	unsigned long flags;
+
+	mutex_lock(&bnad->conf_mutex);
+
+	/* Tx */
+	err = bnad_setup_tx(bnad, 0);
+	if (err)
+		goto err_return;
+
+	/* Rx */
+	err = bnad_setup_rx(bnad, 0);
+	if (err)
+		goto cleanup_tx;
+
+	/* Port */
+	pause_config.tx_pause = 0;
+	pause_config.rx_pause = 0;
+
+	mtu = ETH_HLEN + bnad->netdev->mtu + ETH_FCS_LEN;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_port_mtu_set(&bnad->bna.port, mtu, NULL);
+	bna_port_pause_config(&bnad->bna.port, &pause_config, NULL);
+	bna_port_enable(&bnad->bna.port);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	/* Enable broadcast */
+	bnad_enable_default_bcast(bnad);
+
+	/* Set the UCAST address */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bnad_mac_addr_set_locked(bnad, netdev->dev_addr);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	/* Start the stats timer */
+	bnad_stats_timer_start(bnad);
+
+	mutex_unlock(&bnad->conf_mutex);
+
+	return 0;
+
+cleanup_tx:
+	bnad_cleanup_tx(bnad, 0);
+
+err_return:
+	mutex_unlock(&bnad->conf_mutex);
+	return err;
+}
+
+static int
+bnad_stop(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	unsigned long flags;
+
+	mutex_lock(&bnad->conf_mutex);
+
+	/* Stop the stats timer */
+	bnad_stats_timer_stop(bnad);
+
+	init_completion(&bnad->bnad_completions.port_comp);
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_port_disable(&bnad->bna.port, BNA_HARD_CLEANUP,
+			bnad_cb_port_disabled);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	wait_for_completion(&bnad->bnad_completions.port_comp);
+
+	bnad_cleanup_tx(bnad, 0);
+	bnad_cleanup_rx(bnad, 0);
+
+	/* Synchronize mailbox IRQ */
+	bnad_mbox_irq_sync(bnad);
+
+	mutex_unlock(&bnad->conf_mutex);
+
+	return 0;
+}
+
+/* TX */
+/*
+ * bnad_start_xmit : Netdev entry point for Transmit
+ *		     Called under lock held by net_device
+ */
+static netdev_tx_t
+bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	u16 		txq_prod, vlan_tag = 0;
+	u32 		unmap_prod, wis, wis_used, wi_range;
+	u32 		vectors, vect_id, i, acked;
+	u32		tx_id;
+	int 			err;
+
+	struct bnad_tx_info *tx_info;
+	struct bna_tcb *tcb;
+	struct bnad_unmap_q *unmap_q;
+	dma_addr_t 		dma_addr;
+	struct bna_txq_entry *txqent;
+	bna_txq_wi_ctrl_flag_t 	flags;
+
+	if (unlikely
+	    (skb->len <= ETH_HLEN || skb->len > BFI_TX_MAX_DATA_PER_PKT)) {
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	/*
+	 * Takes care of the Tx that is scheduled between clearing the flag
+	 * and the netif_stop_queue() call.
+	 */
+	if (unlikely(!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))) {
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	tx_id = 0;
+
+	tx_info = &bnad->tx_info[tx_id];
+	tcb = tx_info->tcb[tx_id];
+	unmap_q = tcb->unmap_q;
+
+	vectors = 1 + skb_shinfo(skb)->nr_frags;
+	if (vectors > BFI_TX_MAX_VECTORS_PER_PKT) {
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+	wis = BNA_TXQ_WI_NEEDED(vectors);	/* 4 vectors per work item */
+	acked = 0;
+	if (unlikely
+	    (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
+	     vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
+		if ((u16) (*tcb->hw_consumer_index) !=
+		    tcb->consumer_index &&
+		    !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
+			acked = bnad_free_txbufs(bnad, tcb);
+			bna_ib_ack(tcb->i_dbell, acked);
+			smp_mb__before_clear_bit();
+			clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+		} else {
+			netif_stop_queue(netdev);
+			BNAD_UPDATE_CTR(bnad, netif_queue_stop);
+		}
+
+		smp_mb();
+		/*
+		 * Check again to deal with race condition between
+		 * netif_stop_queue here, and netif_wake_queue in
+		 * interrupt handler which is not inside netif tx lock.
+		 */
+		if (likely
+		    (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
+		     vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
+			BNAD_UPDATE_CTR(bnad, netif_queue_stop);
+			return NETDEV_TX_BUSY;
+		} else {
+			netif_wake_queue(netdev);
+			BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+		}
+	}
+
+	unmap_prod = unmap_q->producer_index;
+	wis_used = 1;
+	vect_id = 0;
+	flags = 0;
+
+	txq_prod = tcb->producer_index;
+	BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt, txqent, wi_range);
+	BUG_ON(!(wi_range <= tcb->q_depth));
+	txqent->hdr.wi.reserved = 0;
+	txqent->hdr.wi.num_vectors = vectors;
+	txqent->hdr.wi.opcode =
+		htons((skb_is_gso(skb) ? BNA_TXQ_WI_SEND_LSO :
+		       BNA_TXQ_WI_SEND));
+
+	if (vlan_tx_tag_present(skb)) {
+		vlan_tag = (u16) vlan_tx_tag_get(skb);
+		flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN);
+	}
+	if (test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags)) {
+		vlan_tag =
+			(tcb->priority & 0x7) << 13 | (vlan_tag & 0x1fff);
+		flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN);
+	}
+
+	txqent->hdr.wi.vlan_tag = htons(vlan_tag);
+
+	if (skb_is_gso(skb)) {
+		err = bnad_tso_prepare(bnad, skb);
+		if (err) {
+			dev_kfree_skb(skb);
+			return NETDEV_TX_OK;
+		}
+		txqent->hdr.wi.lso_mss = htons(skb_is_gso(skb));
+		flags |= (BNA_TXQ_WI_CF_IP_CKSUM | BNA_TXQ_WI_CF_TCP_CKSUM);
+		txqent->hdr.wi.l4_hdr_size_n_offset =
+			htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
+			      (tcp_hdrlen(skb) >> 2,
+			       skb_transport_offset(skb)));
+	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		u8 proto = 0;
+
+		txqent->hdr.wi.lso_mss = 0;
+
+		if (skb->protocol == htons(ETH_P_IP))
+			proto = ip_hdr(skb)->protocol;
+		else if (skb->protocol == htons(ETH_P_IPV6)) {
+			/* nexthdr may not be TCP immediately. */
+			proto = ipv6_hdr(skb)->nexthdr;
+		}
+		if (proto == IPPROTO_TCP) {
+			flags |= BNA_TXQ_WI_CF_TCP_CKSUM;
+			txqent->hdr.wi.l4_hdr_size_n_offset =
+				htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
+				      (0, skb_transport_offset(skb)));
+
+			BNAD_UPDATE_CTR(bnad, tcpcsum_offload);
+
+			BUG_ON(!(skb_headlen(skb) >=
+				skb_transport_offset(skb) + tcp_hdrlen(skb)));
+
+		} else if (proto == IPPROTO_UDP) {
+			flags |= BNA_TXQ_WI_CF_UDP_CKSUM;
+			txqent->hdr.wi.l4_hdr_size_n_offset =
+				htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
+				      (0, skb_transport_offset(skb)));
+
+			BNAD_UPDATE_CTR(bnad, udpcsum_offload);
+
+			BUG_ON(!(skb_headlen(skb) >=
+				   skb_transport_offset(skb) +
+				   sizeof(struct udphdr)));
+		} else {
+			err = skb_checksum_help(skb);
+			BNAD_UPDATE_CTR(bnad, csum_help);
+			if (err) {
+				dev_kfree_skb(skb);
+				BNAD_UPDATE_CTR(bnad, csum_help_err);
+				return NETDEV_TX_OK;
+			}
+		}
+	} else {
+		txqent->hdr.wi.lso_mss = 0;
+		txqent->hdr.wi.l4_hdr_size_n_offset = 0;
+	}
+
+	txqent->hdr.wi.flags = htons(flags);
+
+	txqent->hdr.wi.frame_length = htonl(skb->len);
+
+	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);
+
+	BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
+	BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+		u32		size = frag->size;
+
+		if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) {
+			vect_id = 0;
+			if (--wi_range)
+				txqent++;
+			else {
+				BNA_QE_INDX_ADD(txq_prod, wis_used,
+						tcb->q_depth);
+				wis_used = 0;
+				BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt,
+						     txqent, wi_range);
+				BUG_ON(!(wi_range <= tcb->q_depth));
+			}
+			wis_used++;
+			txqent->hdr.wi_ext.opcode = htons(BNA_TXQ_WI_EXTENSION);
+		}
+
+		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);
+		BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
+		BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+	}
+
+	unmap_q->producer_index = unmap_prod;
+	BNA_QE_INDX_ADD(txq_prod, wis_used, tcb->q_depth);
+	tcb->producer_index = txq_prod;
+
+	smp_mb();
+	bna_txq_prod_indx_doorbell(tcb);
+
+	if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index)
+		tasklet_schedule(&bnad->tx_free_tasklet);
+
+	return NETDEV_TX_OK;
+}
+
+/*
+ * Used spin_lock to synchronize reading of stats structures, which
+ * is written by BNA under the same lock.
+ */
+static struct rtnl_link_stats64 *
+bnad_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+
+	bnad_netdev_qstats_fill(bnad, stats);
+	bnad_netdev_hwstats_fill(bnad, stats);
+
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	return stats;
+}
+
+static void
+bnad_set_rx_mode(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	u32	new_mask, valid_mask;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+
+	new_mask = valid_mask = 0;
+
+	if (netdev->flags & IFF_PROMISC) {
+		if (!(bnad->cfg_flags & BNAD_CF_PROMISC)) {
+			new_mask = BNAD_RXMODE_PROMISC_DEFAULT;
+			valid_mask = BNAD_RXMODE_PROMISC_DEFAULT;
+			bnad->cfg_flags |= BNAD_CF_PROMISC;
+		}
+	} else {
+		if (bnad->cfg_flags & BNAD_CF_PROMISC) {
+			new_mask = ~BNAD_RXMODE_PROMISC_DEFAULT;
+			valid_mask = BNAD_RXMODE_PROMISC_DEFAULT;
+			bnad->cfg_flags &= ~BNAD_CF_PROMISC;
+		}
+	}
+
+	if (netdev->flags & IFF_ALLMULTI) {
+		if (!(bnad->cfg_flags & BNAD_CF_ALLMULTI)) {
+			new_mask |= BNA_RXMODE_ALLMULTI;
+			valid_mask |= BNA_RXMODE_ALLMULTI;
+			bnad->cfg_flags |= BNAD_CF_ALLMULTI;
+		}
+	} else {
+		if (bnad->cfg_flags & BNAD_CF_ALLMULTI) {
+			new_mask &= ~BNA_RXMODE_ALLMULTI;
+			valid_mask |= BNA_RXMODE_ALLMULTI;
+			bnad->cfg_flags &= ~BNAD_CF_ALLMULTI;
+		}
+	}
+
+	bna_rx_mode_set(bnad->rx_info[0].rx, new_mask, valid_mask, NULL);
+
+	if (!netdev_mc_empty(netdev)) {
+		u8 *mcaddr_list;
+		int mc_count = netdev_mc_count(netdev);
+
+		/* Index 0 holds the broadcast address */
+		mcaddr_list =
+			kzalloc((mc_count + 1) * ETH_ALEN,
+				GFP_ATOMIC);
+		if (!mcaddr_list)
+			goto unlock;
+
+		memcpy(&mcaddr_list[0], &bnad_bcast_addr[0], ETH_ALEN);
+
+		/* Copy rest of the MC addresses */
+		bnad_netdev_mc_list_get(netdev, mcaddr_list);
+
+		bna_rx_mcast_listset(bnad->rx_info[0].rx, mc_count + 1,
+					mcaddr_list, NULL);
+
+		/* Should we enable BNAD_CF_ALLMULTI for err != 0 ? */
+		kfree(mcaddr_list);
+	}
+unlock:
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+/*
+ * bna_lock is used to sync writes to netdev->addr
+ * conf_lock cannot be used since this call may be made
+ * in a non-blocking context.
+ */
+static int
+bnad_set_mac_address(struct net_device *netdev, void *mac_addr)
+{
+	int err;
+	struct bnad *bnad = netdev_priv(netdev);
+	struct sockaddr *sa = (struct sockaddr *)mac_addr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+
+	err = bnad_mac_addr_set_locked(bnad, sa->sa_data);
+
+	if (!err)
+		memcpy(netdev->dev_addr, sa->sa_data, netdev->addr_len);
+
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	return err;
+}
+
+static int
+bnad_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	int mtu, err = 0;
+	unsigned long flags;
+
+	struct bnad *bnad = netdev_priv(netdev);
+
+	if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU)
+		return -EINVAL;
+
+	mutex_lock(&bnad->conf_mutex);
+
+	netdev->mtu = new_mtu;
+
+	mtu = ETH_HLEN + new_mtu + ETH_FCS_LEN;
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_port_mtu_set(&bnad->bna.port, mtu, NULL);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	mutex_unlock(&bnad->conf_mutex);
+	return err;
+}
+
+static void
+bnad_vlan_rx_register(struct net_device *netdev,
+				  struct vlan_group *vlan_grp)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	mutex_lock(&bnad->conf_mutex);
+	bnad->vlan_grp = vlan_grp;
+	mutex_unlock(&bnad->conf_mutex);
+}
+
+static void
+bnad_vlan_rx_add_vid(struct net_device *netdev,
+				 unsigned short vid)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	unsigned long flags;
+
+	if (!bnad->rx_info[0].rx)
+		return;
+
+	mutex_lock(&bnad->conf_mutex);
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_rx_vlan_add(bnad->rx_info[0].rx, vid);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	mutex_unlock(&bnad->conf_mutex);
+}
+
+static void
+bnad_vlan_rx_kill_vid(struct net_device *netdev,
+				  unsigned short vid)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	unsigned long flags;
+
+	if (!bnad->rx_info[0].rx)
+		return;
+
+	mutex_lock(&bnad->conf_mutex);
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_rx_vlan_del(bnad->rx_info[0].rx, vid);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	mutex_unlock(&bnad->conf_mutex);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void
+bnad_netpoll(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	struct bnad_rx_info *rx_info;
+	struct bnad_rx_ctrl *rx_ctrl;
+	u32 curr_mask;
+	int i, j;
+
+	if (!(bnad->cfg_flags & BNAD_CF_MSIX)) {
+		bna_intx_disable(&bnad->bna, curr_mask);
+		bnad_isr(bnad->pcidev->irq, netdev);
+		bna_intx_enable(&bnad->bna, curr_mask);
+	} else {
+		for (i = 0; i < bnad->num_rx; i++) {
+			rx_info = &bnad->rx_info[i];
+			if (!rx_info->rx)
+				continue;
+			for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+				rx_ctrl = &rx_info->rx_ctrl[j];
+				if (rx_ctrl->ccb) {
+					bnad_disable_rx_irq(bnad,
+							    rx_ctrl->ccb);
+					bnad_netif_rx_schedule_poll(bnad,
+							    rx_ctrl->ccb);
+				}
+			}
+		}
+	}
+}
+#endif
+
+static const struct net_device_ops bnad_netdev_ops = {
+	.ndo_open		= bnad_open,
+	.ndo_stop		= bnad_stop,
+	.ndo_start_xmit		= bnad_start_xmit,
+	.ndo_get_stats64		= bnad_get_stats64,
+	.ndo_set_rx_mode	= bnad_set_rx_mode,
+	.ndo_set_multicast_list = bnad_set_rx_mode,
+	.ndo_validate_addr      = eth_validate_addr,
+	.ndo_set_mac_address    = bnad_set_mac_address,
+	.ndo_change_mtu		= bnad_change_mtu,
+	.ndo_vlan_rx_register   = bnad_vlan_rx_register,
+	.ndo_vlan_rx_add_vid    = bnad_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid   = bnad_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller    = bnad_netpoll
+#endif
+};
+
+static void
+bnad_netdev_init(struct bnad *bnad, bool using_dac)
+{
+	struct net_device *netdev = bnad->netdev;
+
+	netdev->features |= NETIF_F_IPV6_CSUM;
+	netdev->features |= NETIF_F_TSO;
+	netdev->features |= NETIF_F_TSO6;
+
+	netdev->features |= NETIF_F_GRO;
+	pr_warn("bna: GRO enabled, using kernel stack GRO\n");
+
+	netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+
+	if (using_dac)
+		netdev->features |= NETIF_F_HIGHDMA;
+
+	netdev->features |=
+		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
+		NETIF_F_HW_VLAN_FILTER;
+
+	netdev->vlan_features = netdev->features;
+	netdev->mem_start = bnad->mmio_start;
+	netdev->mem_end = bnad->mmio_start + bnad->mmio_len - 1;
+
+	netdev->netdev_ops = &bnad_netdev_ops;
+	bnad_set_ethtool_ops(netdev);
+}
+
+/*
+ * 1. Initialize the bnad structure
+ * 2. Setup netdev pointer in pci_dev
+ * 3. Initialze Tx free tasklet
+ * 4. Initialize no. of TxQ & CQs & MSIX vectors
+ */
+static int
+bnad_init(struct bnad *bnad,
+	  struct pci_dev *pdev, struct net_device *netdev)
+{
+	unsigned long flags;
+
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+	pci_set_drvdata(pdev, netdev);
+
+	bnad->netdev = netdev;
+	bnad->pcidev = pdev;
+	bnad->mmio_start = pci_resource_start(pdev, 0);
+	bnad->mmio_len = pci_resource_len(pdev, 0);
+	bnad->bar0 = ioremap_nocache(bnad->mmio_start, bnad->mmio_len);
+	if (!bnad->bar0) {
+		dev_err(&pdev->dev, "ioremap for bar0 failed\n");
+		pci_set_drvdata(pdev, NULL);
+		return -ENOMEM;
+	}
+	pr_info("bar0 mapped to %p, len %llu\n", bnad->bar0,
+	       (unsigned long long) bnad->mmio_len);
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	if (!bnad_msix_disable)
+		bnad->cfg_flags = BNAD_CF_MSIX;
+
+	bnad->cfg_flags |= BNAD_CF_DIM_ENABLED;
+
+	bnad_q_num_init(bnad);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx) +
+		(bnad->num_rx * bnad->num_rxp_per_rx) +
+			 BNAD_MAILBOX_MSIX_VECTORS;
+
+	bnad->txq_depth = BNAD_TXQ_DEPTH;
+	bnad->rxq_depth = BNAD_RXQ_DEPTH;
+	bnad->rx_csum = true;
+
+	bnad->tx_coalescing_timeo = BFI_TX_COALESCING_TIMEO;
+	bnad->rx_coalescing_timeo = BFI_RX_COALESCING_TIMEO;
+
+	tasklet_init(&bnad->tx_free_tasklet, bnad_tx_free_tasklet,
+		     (unsigned long)bnad);
+
+	return 0;
+}
+
+/*
+ * Must be called after bnad_pci_uninit()
+ * so that iounmap() and pci_set_drvdata(NULL)
+ * happens only after PCI uninitialization.
+ */
+static void
+bnad_uninit(struct bnad *bnad)
+{
+	if (bnad->bar0)
+		iounmap(bnad->bar0);
+	pci_set_drvdata(bnad->pcidev, NULL);
+}
+
+/*
+ * Initialize locks
+	a) Per device mutes used for serializing configuration
+	   changes from OS interface
+	b) spin lock used to protect bna state machine
+ */
+static void
+bnad_lock_init(struct bnad *bnad)
+{
+	spin_lock_init(&bnad->bna_lock);
+	mutex_init(&bnad->conf_mutex);
+}
+
+static void
+bnad_lock_uninit(struct bnad *bnad)
+{
+	mutex_destroy(&bnad->conf_mutex);
+}
+
+/* PCI Initialization */
+static int
+bnad_pci_init(struct bnad *bnad,
+	      struct pci_dev *pdev, bool *using_dac)
+{
+	int err;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+	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))) {
+		*using_dac = 1;
+	} else {
+		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)
+				goto release_regions;
+		}
+		*using_dac = 0;
+	}
+	pci_set_master(pdev);
+	return 0;
+
+release_regions:
+	pci_release_regions(pdev);
+disable_device:
+	pci_disable_device(pdev);
+
+	return err;
+}
+
+static void
+bnad_pci_uninit(struct pci_dev *pdev)
+{
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+static int __devinit
+bnad_pci_probe(struct pci_dev *pdev,
+		const struct pci_device_id *pcidev_id)
+{
+	bool 	using_dac;
+	int 	err;
+	struct bnad *bnad;
+	struct bna *bna;
+	struct net_device *netdev;
+	struct bfa_pcidev pcidev_info;
+	unsigned long flags;
+
+	pr_info("bnad_pci_probe : (0x%p, 0x%p) PCI Func : (%d)\n",
+	       pdev, pcidev_id, PCI_FUNC(pdev->devfn));
+
+	mutex_lock(&bnad_fwimg_mutex);
+	if (!cna_get_firmware_buf(pdev)) {
+		mutex_unlock(&bnad_fwimg_mutex);
+		pr_warn("Failed to load Firmware Image!\n");
+		return -ENODEV;
+	}
+	mutex_unlock(&bnad_fwimg_mutex);
+
+	/*
+	 * Allocates sizeof(struct net_device + struct bnad)
+	 * bnad = netdev->priv
+	 */
+	netdev = alloc_etherdev(sizeof(struct bnad));
+	if (!netdev) {
+		dev_err(&pdev->dev, "alloc_etherdev failed\n");
+		err = -ENOMEM;
+		return err;
+	}
+	bnad = netdev_priv(netdev);
+
+	/*
+	 * PCI initialization
+	 * 	Output : using_dac = 1 for 64 bit DMA
+	 *		           = 0 for 32 bit DMA
+	 */
+	err = bnad_pci_init(bnad, pdev, &using_dac);
+	if (err)
+		goto free_netdev;
+
+	bnad_lock_init(bnad);
+	/*
+	 * Initialize bnad structure
+	 * Setup relation between pci_dev & netdev
+	 * Init Tx free tasklet
+	 */
+	err = bnad_init(bnad, pdev, netdev);
+	if (err)
+		goto pci_uninit;
+	/* Initialize netdev structure, set up ethtool ops */
+	bnad_netdev_init(bnad, using_dac);
+
+	bnad_enable_msix(bnad);
+
+	/* Get resource requirement form bna */
+	bna_res_req(&bnad->res_info[0]);
+
+	/* Allocate resources from bna */
+	err = bnad_res_alloc(bnad);
+	if (err)
+		goto free_netdev;
+
+	bna = &bnad->bna;
+
+	/* Setup pcidev_info for bna_init() */
+	pcidev_info.pci_slot = PCI_SLOT(bnad->pcidev->devfn);
+	pcidev_info.pci_func = PCI_FUNC(bnad->pcidev->devfn);
+	pcidev_info.device_id = bnad->pcidev->device;
+	pcidev_info.pci_bar_kva = bnad->bar0;
+
+	mutex_lock(&bnad->conf_mutex);
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_init(bna, bnad, &pcidev_info, &bnad->res_info[0]);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	bnad->stats.bna_stats = &bna->stats;
+
+	/* Set up timers */
+	setup_timer(&bnad->bna.device.ioc.ioc_timer, bnad_ioc_timeout,
+				((unsigned long)bnad));
+	setup_timer(&bnad->bna.device.ioc.hb_timer, bnad_ioc_hb_check,
+				((unsigned long)bnad));
+	setup_timer(&bnad->bna.device.ioc.sem_timer, bnad_ioc_sem_timeout,
+				((unsigned long)bnad));
+
+	/* Now start the timer before calling IOC */
+	mod_timer(&bnad->bna.device.ioc.ioc_timer,
+		  jiffies + msecs_to_jiffies(BNA_IOC_TIMER_FREQ));
+
+	/*
+	 * Start the chip
+	 * Don't care even if err != 0, bna state machine will
+	 * deal with it
+	 */
+	err = bnad_device_enable(bnad);
+
+	/* Get the burnt-in mac */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_port_mac_get(&bna->port, &bnad->perm_addr);
+	bnad_set_netdev_perm_addr(bnad);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	mutex_unlock(&bnad->conf_mutex);
+
+	/*
+	 * Make sure the link appears down to the stack
+	 */
+	netif_carrier_off(netdev);
+
+	/* Finally, reguister with net_device layer */
+	err = register_netdev(netdev);
+	if (err) {
+		pr_err("BNA : Registering with netdev failed\n");
+		goto disable_device;
+	}
+
+	return 0;
+
+disable_device:
+	mutex_lock(&bnad->conf_mutex);
+	bnad_device_disable(bnad);
+	del_timer_sync(&bnad->bna.device.ioc.ioc_timer);
+	del_timer_sync(&bnad->bna.device.ioc.sem_timer);
+	del_timer_sync(&bnad->bna.device.ioc.hb_timer);
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_uninit(bna);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+	mutex_unlock(&bnad->conf_mutex);
+
+	bnad_res_free(bnad);
+	bnad_disable_msix(bnad);
+pci_uninit:
+	bnad_pci_uninit(pdev);
+	bnad_lock_uninit(bnad);
+	bnad_uninit(bnad);
+free_netdev:
+	free_netdev(netdev);
+	return err;
+}
+
+static void __devexit
+bnad_pci_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct bnad *bnad;
+	struct bna *bna;
+	unsigned long flags;
+
+	if (!netdev)
+		return;
+
+	pr_info("%s bnad_pci_remove\n", netdev->name);
+	bnad = netdev_priv(netdev);
+	bna = &bnad->bna;
+
+	unregister_netdev(netdev);
+
+	mutex_lock(&bnad->conf_mutex);
+	bnad_device_disable(bnad);
+	del_timer_sync(&bnad->bna.device.ioc.ioc_timer);
+	del_timer_sync(&bnad->bna.device.ioc.sem_timer);
+	del_timer_sync(&bnad->bna.device.ioc.hb_timer);
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bna_uninit(bna);
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+	mutex_unlock(&bnad->conf_mutex);
+
+	bnad_res_free(bnad);
+	bnad_disable_msix(bnad);
+	bnad_pci_uninit(pdev);
+	bnad_lock_uninit(bnad);
+	bnad_uninit(bnad);
+	free_netdev(netdev);
+}
+
+static const struct pci_device_id bnad_pci_id_table[] = {
+	{
+		PCI_DEVICE(PCI_VENDOR_ID_BROCADE,
+			PCI_DEVICE_ID_BROCADE_CT),
+		.class = PCI_CLASS_NETWORK_ETHERNET << 8,
+		.class_mask =  0xffff00
+	}, {0,  }
+};
+
+MODULE_DEVICE_TABLE(pci, bnad_pci_id_table);
+
+static struct pci_driver bnad_pci_driver = {
+	.name = BNAD_NAME,
+	.id_table = bnad_pci_id_table,
+	.probe = bnad_pci_probe,
+	.remove = __devexit_p(bnad_pci_remove),
+};
+
+static int __init
+bnad_module_init(void)
+{
+	int err;
+
+	pr_info("Brocade 10G Ethernet driver\n");
+
+	bfa_nw_ioc_auto_recover(bnad_ioc_auto_recover);
+
+	err = pci_register_driver(&bnad_pci_driver);
+	if (err < 0) {
+		pr_err("bna : PCI registration failed in module init "
+		       "(%d)\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void __exit
+bnad_module_exit(void)
+{
+	pci_unregister_driver(&bnad_pci_driver);
+
+	if (bfi_fw)
+		release_firmware(bfi_fw);
+}
+
+module_init(bnad_module_init);
+module_exit(bnad_module_exit);
+
+MODULE_AUTHOR("Brocade");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Brocade 10G PCIe Ethernet driver");
+MODULE_VERSION(BNAD_VERSION);
+MODULE_FIRMWARE(CNA_FW_FILE_CT);
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
new file mode 100644
index 0000000..ebc3a907
--- /dev/null
+++ b/drivers/net/bna/bnad.h
@@ -0,0 +1,332 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BNAD_H__
+#define __BNAD_H__
+
+#include <linux/rtnetlink.h>
+#include <linux/workqueue.h>
+#include <linux/ipv6.h>
+#include <linux/etherdevice.h>
+#include <linux/mutex.h>
+#include <linux/firmware.h>
+
+/* Fix for IA64 */
+#include <asm/checksum.h>
+#include <net/ip6_checksum.h>
+
+#include <net/ip.h>
+#include <net/tcp.h>
+
+#include "bna.h"
+
+#define BNAD_TXQ_DEPTH		2048
+#define BNAD_RXQ_DEPTH		2048
+
+#define BNAD_MAX_TXS		1
+#define BNAD_MAX_TXQ_PER_TX	8	/* 8 priority queues */
+#define BNAD_TXQ_NUM		1
+
+#define BNAD_MAX_RXS		1
+#define BNAD_MAX_RXPS_PER_RX	16
+
+/*
+ * Control structure pointed to ccb->ctrl, which
+ * determines the NAPI / LRO behavior CCB
+ * There is 1:1 corres. between ccb & ctrl
+ */
+struct bnad_rx_ctrl {
+	struct bna_ccb *ccb;
+	struct napi_struct	napi;
+};
+
+#define BNAD_RXMODE_PROMISC_DEFAULT	BNA_RXMODE_PROMISC
+
+#define BNAD_GET_TX_ID(_skb)	(0)
+
+/*
+ * GLOBAL #defines (CONSTANTS)
+ */
+#define BNAD_NAME			"bna"
+#define BNAD_NAME_LEN			64
+
+#define BNAD_VERSION			"2.3.2.0"
+
+#define BNAD_MAILBOX_MSIX_VECTORS	1
+
+#define BNAD_STATS_TIMER_FREQ		1000 	/* in msecs */
+#define BNAD_DIM_TIMER_FREQ		1000 	/* in msecs */
+
+#define BNAD_MAX_Q_DEPTH		0x10000
+#define BNAD_MIN_Q_DEPTH		0x200
+
+#define BNAD_JUMBO_MTU			9000
+
+#define BNAD_NETIF_WAKE_THRESHOLD	8
+
+#define BNAD_RXQ_REFILL_THRESHOLD_SHIFT	3
+
+/* Bit positions for tcb->flags */
+#define BNAD_TXQ_FREE_SENT		0
+
+/* Bit positions for rcb->flags */
+#define BNAD_RXQ_REFILL			0
+#define BNAD_RXQ_STARTED		1
+
+/*
+ * DATA STRUCTURES
+ */
+
+/* enums */
+enum bnad_intr_source {
+	BNAD_INTR_TX		= 1,
+	BNAD_INTR_RX		= 2
+};
+
+enum bnad_link_state {
+	BNAD_LS_DOWN		= 0,
+	BNAD_LS_UP 		= 1
+};
+
+struct bnad_completion {
+	struct completion 	ioc_comp;
+	struct completion 	ucast_comp;
+	struct completion	mcast_comp;
+	struct completion	tx_comp;
+	struct completion	rx_comp;
+	struct completion	stats_comp;
+	struct completion	port_comp;
+
+	u8			ioc_comp_status;
+	u8			ucast_comp_status;
+	u8			mcast_comp_status;
+	u8			tx_comp_status;
+	u8			rx_comp_status;
+	u8			stats_comp_status;
+	u8			port_comp_status;
+};
+
+/* Tx Rx Control Stats */
+struct bnad_drv_stats {
+	u64 		netif_queue_stop;
+	u64		netif_queue_wakeup;
+	u64		tso4;
+	u64		tso6;
+	u64		tso_err;
+	u64		tcpcsum_offload;
+	u64		udpcsum_offload;
+	u64		csum_help;
+	u64		csum_help_err;
+
+	u64		hw_stats_updates;
+	u64		netif_rx_schedule;
+	u64		netif_rx_complete;
+	u64		netif_rx_dropped;
+
+	u64		link_toggle;
+	u64		cee_up;
+
+	u64		rxp_info_alloc_failed;
+	u64		mbox_intr_disabled;
+	u64		mbox_intr_enabled;
+	u64		tx_unmap_q_alloc_failed;
+	u64		rx_unmap_q_alloc_failed;
+
+	u64		rxbuf_alloc_failed;
+};
+
+/* Complete driver stats */
+struct bnad_stats {
+	struct bnad_drv_stats drv_stats;
+	struct bna_stats *bna_stats;
+};
+
+/* Tx / Rx Resources */
+struct bnad_tx_res_info {
+	struct bna_res_info res_info[BNA_TX_RES_T_MAX];
+};
+
+struct bnad_rx_res_info {
+	struct bna_res_info res_info[BNA_RX_RES_T_MAX];
+};
+
+struct bnad_tx_info {
+	struct bna_tx *tx; /* 1:1 between tx_info & tx */
+	struct bna_tcb *tcb[BNAD_MAX_TXQ_PER_TX];
+} ____cacheline_aligned;
+
+struct bnad_rx_info {
+	struct bna_rx *rx; /* 1:1 between rx_info & rx */
+
+	struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXPS_PER_RX];
+} ____cacheline_aligned;
+
+/* Unmap queues for Tx / Rx cleanup */
+struct bnad_skb_unmap {
+	struct sk_buff		*skb;
+	DECLARE_PCI_UNMAP_ADDR(dma_addr)
+};
+
+struct bnad_unmap_q {
+	u32		producer_index;
+	u32		consumer_index;
+	u32 		q_depth;
+	/* This should be the last one */
+	struct bnad_skb_unmap unmap_array[1];
+};
+
+/* Bit mask values for bnad->cfg_flags */
+#define	BNAD_CF_DIM_ENABLED		0x01	/* DIM */
+#define	BNAD_CF_PROMISC			0x02
+#define BNAD_CF_ALLMULTI		0x04
+#define	BNAD_CF_MSIX			0x08	/* If in MSIx mode */
+
+/* Defines for run_flags bit-mask */
+/* Set, tested & cleared using xxx_bit() functions */
+/* Values indicated bit positions */
+#define	BNAD_RF_CEE_RUNNING		1
+#define BNAD_RF_HW_ERROR 		2
+#define BNAD_RF_MBOX_IRQ_DISABLED	3
+#define BNAD_RF_TX_STARTED		4
+#define BNAD_RF_RX_STARTED		5
+#define BNAD_RF_DIM_TIMER_RUNNING	6
+#define BNAD_RF_STATS_TIMER_RUNNING	7
+
+struct bnad {
+	struct net_device 	*netdev;
+
+	/* Data path */
+	struct bnad_tx_info tx_info[BNAD_MAX_TXS];
+	struct bnad_rx_info rx_info[BNAD_MAX_RXS];
+
+	struct vlan_group	*vlan_grp;
+	/*
+	 * These q numbers are global only because
+	 * they are used to calculate MSIx vectors.
+	 * Actually the exact # of queues are per Tx/Rx
+	 * object.
+	 */
+	u32		num_tx;
+	u32		num_rx;
+	u32		num_txq_per_tx;
+	u32		num_rxp_per_rx;
+
+	u32		txq_depth;
+	u32		rxq_depth;
+
+	u8			tx_coalescing_timeo;
+	u8			rx_coalescing_timeo;
+
+	struct bna_rx_config rx_config[BNAD_MAX_RXS];
+	struct bna_tx_config tx_config[BNAD_MAX_TXS];
+
+	u32		rx_csum;
+
+	void __iomem		*bar0;	/* BAR0 address */
+
+	struct bna bna;
+
+	u32		cfg_flags;
+	unsigned long		run_flags;
+
+	struct pci_dev 		*pcidev;
+	u64		mmio_start;
+	u64		mmio_len;
+
+	u32		msix_num;
+	struct msix_entry	*msix_table;
+
+	struct mutex		conf_mutex;
+	spinlock_t		bna_lock ____cacheline_aligned;
+
+	/* Timers */
+	struct timer_list	ioc_timer;
+	struct timer_list	dim_timer;
+	struct timer_list	stats_timer;
+
+	/* Control path resources, memory & irq */
+	struct bna_res_info res_info[BNA_RES_T_MAX];
+	struct bnad_tx_res_info tx_res_info[BNAD_MAX_TXS];
+	struct bnad_rx_res_info rx_res_info[BNAD_MAX_RXS];
+
+	struct bnad_completion bnad_completions;
+
+	/* Burnt in MAC address */
+	mac_t			perm_addr;
+
+	struct tasklet_struct	tx_free_tasklet;
+
+	/* Statistics */
+	struct bnad_stats stats;
+
+	struct bnad_diag *diag;
+
+	char			adapter_name[BNAD_NAME_LEN];
+	char 			port_name[BNAD_NAME_LEN];
+	char			mbox_irq_name[BNAD_NAME_LEN];
+};
+
+/*
+ * EXTERN VARIABLES
+ */
+extern struct firmware *bfi_fw;
+extern u32 		bnad_rxqs_per_cq;
+
+/*
+ * EXTERN PROTOTYPES
+ */
+extern u32 *cna_get_firmware_buf(struct pci_dev *pdev);
+/* Netdev entry point prototypes */
+extern void bnad_set_ethtool_ops(struct net_device *netdev);
+
+/* Configuration & setup */
+extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad);
+extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad);
+
+extern int bnad_setup_rx(struct bnad *bnad, uint rx_id);
+extern int bnad_setup_tx(struct bnad *bnad, uint tx_id);
+extern void bnad_cleanup_tx(struct bnad *bnad, uint tx_id);
+extern void bnad_cleanup_rx(struct bnad *bnad, uint rx_id);
+
+/* Timer start/stop protos */
+extern void bnad_dim_timer_start(struct bnad *bnad);
+
+/* Statistics */
+extern void bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats);
+extern void bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats);
+
+/**
+ * MACROS
+ */
+/* To set & get the stats counters */
+#define BNAD_UPDATE_CTR(_bnad, _ctr)				\
+				(((_bnad)->stats.drv_stats._ctr)++)
+
+#define BNAD_GET_CTR(_bnad, _ctr) ((_bnad)->stats.drv_stats._ctr)
+
+#define bnad_enable_rx_irq_unsafe(_ccb)			\
+{							\
+	bna_ib_coalescing_timer_set((_ccb)->i_dbell,	\
+		(_ccb)->rx_coalescing_timeo);		\
+	bna_ib_ack((_ccb)->i_dbell, 0);			\
+}
+
+#define bnad_dim_timer_running(_bnad)				\
+	(((_bnad)->cfg_flags & BNAD_CF_DIM_ENABLED) && 		\
+	(test_bit(BNAD_RF_DIM_TIMER_RUNNING, &((_bnad)->run_flags))))
+
+#endif /* __BNAD_H__ */
diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c
new file mode 100644
index 0000000..11fa2ea
--- /dev/null
+++ b/drivers/net/bna/bnad_ethtool.c
@@ -0,0 +1,1277 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#include "cna.h"
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/rtnetlink.h>
+
+#include "bna.h"
+
+#include "bnad.h"
+
+#define BNAD_NUM_TXF_COUNTERS 12
+#define BNAD_NUM_RXF_COUNTERS 10
+#define BNAD_NUM_CQ_COUNTERS 3
+#define BNAD_NUM_RXQ_COUNTERS 6
+#define BNAD_NUM_TXQ_COUNTERS 5
+
+#define BNAD_ETHTOOL_STATS_NUM						\
+	(sizeof(struct rtnl_link_stats64) / sizeof(u64) +	\
+	sizeof(struct bnad_drv_stats) / sizeof(u64) +		\
+	offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64))
+
+static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
+	"rx_packets",
+	"tx_packets",
+	"rx_bytes",
+	"tx_bytes",
+	"rx_errors",
+	"tx_errors",
+	"rx_dropped",
+	"tx_dropped",
+	"multicast",
+	"collisions",
+
+	"rx_length_errors",
+	"rx_over_errors",
+	"rx_crc_errors",
+	"rx_frame_errors",
+	"rx_fifo_errors",
+	"rx_missed_errors",
+
+	"tx_aborted_errors",
+	"tx_carrier_errors",
+	"tx_fifo_errors",
+	"tx_heartbeat_errors",
+	"tx_window_errors",
+
+	"rx_compressed",
+	"tx_compressed",
+
+	"netif_queue_stop",
+	"netif_queue_wakeup",
+	"tso4",
+	"tso6",
+	"tso_err",
+	"tcpcsum_offload",
+	"udpcsum_offload",
+	"csum_help",
+	"csum_help_err",
+	"hw_stats_updates",
+	"netif_rx_schedule",
+	"netif_rx_complete",
+	"netif_rx_dropped",
+
+	"link_toggle",
+	"cee_up",
+
+	"rxp_info_alloc_failed",
+	"mbox_intr_disabled",
+	"mbox_intr_enabled",
+	"tx_unmap_q_alloc_failed",
+	"rx_unmap_q_alloc_failed",
+	"rxbuf_alloc_failed",
+
+	"mac_frame_64",
+	"mac_frame_65_127",
+	"mac_frame_128_255",
+	"mac_frame_256_511",
+	"mac_frame_512_1023",
+	"mac_frame_1024_1518",
+	"mac_frame_1518_1522",
+	"mac_rx_bytes",
+	"mac_rx_packets",
+	"mac_rx_fcs_error",
+	"mac_rx_multicast",
+	"mac_rx_broadcast",
+	"mac_rx_control_frames",
+	"mac_rx_pause",
+	"mac_rx_unknown_opcode",
+	"mac_rx_alignment_error",
+	"mac_rx_frame_length_error",
+	"mac_rx_code_error",
+	"mac_rx_carrier_sense_error",
+	"mac_rx_undersize",
+	"mac_rx_oversize",
+	"mac_rx_fragments",
+	"mac_rx_jabber",
+	"mac_rx_drop",
+
+	"mac_tx_bytes",
+	"mac_tx_packets",
+	"mac_tx_multicast",
+	"mac_tx_broadcast",
+	"mac_tx_pause",
+	"mac_tx_deferral",
+	"mac_tx_excessive_deferral",
+	"mac_tx_single_collision",
+	"mac_tx_muliple_collision",
+	"mac_tx_late_collision",
+	"mac_tx_excessive_collision",
+	"mac_tx_total_collision",
+	"mac_tx_pause_honored",
+	"mac_tx_drop",
+	"mac_tx_jabber",
+	"mac_tx_fcs_error",
+	"mac_tx_control_frame",
+	"mac_tx_oversize",
+	"mac_tx_undersize",
+	"mac_tx_fragments",
+
+	"bpc_tx_pause_0",
+	"bpc_tx_pause_1",
+	"bpc_tx_pause_2",
+	"bpc_tx_pause_3",
+	"bpc_tx_pause_4",
+	"bpc_tx_pause_5",
+	"bpc_tx_pause_6",
+	"bpc_tx_pause_7",
+	"bpc_tx_zero_pause_0",
+	"bpc_tx_zero_pause_1",
+	"bpc_tx_zero_pause_2",
+	"bpc_tx_zero_pause_3",
+	"bpc_tx_zero_pause_4",
+	"bpc_tx_zero_pause_5",
+	"bpc_tx_zero_pause_6",
+	"bpc_tx_zero_pause_7",
+	"bpc_tx_first_pause_0",
+	"bpc_tx_first_pause_1",
+	"bpc_tx_first_pause_2",
+	"bpc_tx_first_pause_3",
+	"bpc_tx_first_pause_4",
+	"bpc_tx_first_pause_5",
+	"bpc_tx_first_pause_6",
+	"bpc_tx_first_pause_7",
+
+	"bpc_rx_pause_0",
+	"bpc_rx_pause_1",
+	"bpc_rx_pause_2",
+	"bpc_rx_pause_3",
+	"bpc_rx_pause_4",
+	"bpc_rx_pause_5",
+	"bpc_rx_pause_6",
+	"bpc_rx_pause_7",
+	"bpc_rx_zero_pause_0",
+	"bpc_rx_zero_pause_1",
+	"bpc_rx_zero_pause_2",
+	"bpc_rx_zero_pause_3",
+	"bpc_rx_zero_pause_4",
+	"bpc_rx_zero_pause_5",
+	"bpc_rx_zero_pause_6",
+	"bpc_rx_zero_pause_7",
+	"bpc_rx_first_pause_0",
+	"bpc_rx_first_pause_1",
+	"bpc_rx_first_pause_2",
+	"bpc_rx_first_pause_3",
+	"bpc_rx_first_pause_4",
+	"bpc_rx_first_pause_5",
+	"bpc_rx_first_pause_6",
+	"bpc_rx_first_pause_7",
+
+	"rad_rx_frames",
+	"rad_rx_octets",
+	"rad_rx_vlan_frames",
+	"rad_rx_ucast",
+	"rad_rx_ucast_octets",
+	"rad_rx_ucast_vlan",
+	"rad_rx_mcast",
+	"rad_rx_mcast_octets",
+	"rad_rx_mcast_vlan",
+	"rad_rx_bcast",
+	"rad_rx_bcast_octets",
+	"rad_rx_bcast_vlan",
+	"rad_rx_drops",
+
+	"fc_rx_ucast_octets",
+	"fc_rx_ucast",
+	"fc_rx_ucast_vlan",
+	"fc_rx_mcast_octets",
+	"fc_rx_mcast",
+	"fc_rx_mcast_vlan",
+	"fc_rx_bcast_octets",
+	"fc_rx_bcast",
+	"fc_rx_bcast_vlan",
+
+	"fc_tx_ucast_octets",
+	"fc_tx_ucast",
+	"fc_tx_ucast_vlan",
+	"fc_tx_mcast_octets",
+	"fc_tx_mcast",
+	"fc_tx_mcast_vlan",
+	"fc_tx_bcast_octets",
+	"fc_tx_bcast",
+	"fc_tx_bcast_vlan",
+	"fc_tx_parity_errors",
+	"fc_tx_timeout",
+	"fc_tx_fid_parity_errors",
+};
+
+static int
+bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	cmd->supported = SUPPORTED_10000baseT_Full;
+	cmd->advertising = ADVERTISED_10000baseT_Full;
+	cmd->autoneg = AUTONEG_DISABLE;
+	cmd->supported |= SUPPORTED_FIBRE;
+	cmd->advertising |= ADVERTISED_FIBRE;
+	cmd->port = PORT_FIBRE;
+	cmd->phy_address = 0;
+
+	if (netif_carrier_ok(netdev)) {
+		cmd->speed = SPEED_10000;
+		cmd->duplex = DUPLEX_FULL;
+	} else {
+		cmd->speed = -1;
+		cmd->duplex = -1;
+	}
+	cmd->transceiver = XCVR_EXTERNAL;
+	cmd->maxtxpkt = 0;
+	cmd->maxrxpkt = 0;
+
+	return 0;
+}
+
+static int
+bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	/* 10G full duplex setting supported only */
+	if (cmd->autoneg == AUTONEG_ENABLE)
+		return -EOPNOTSUPP; else {
+		if ((cmd->speed == SPEED_10000) && (cmd->duplex == DUPLEX_FULL))
+			return 0;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static void
+bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	struct bfa_ioc_attr *ioc_attr;
+	unsigned long flags;
+
+	strcpy(drvinfo->driver, BNAD_NAME);
+	strcpy(drvinfo->version, BNAD_VERSION);
+
+	ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL);
+	if (ioc_attr) {
+		memset(ioc_attr, 0, sizeof(*ioc_attr));
+		spin_lock_irqsave(&bnad->bna_lock, flags);
+		bfa_nw_ioc_get_attr(&bnad->bna.device.ioc, ioc_attr);
+		spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+		strncpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver,
+			sizeof(drvinfo->fw_version) - 1);
+		kfree(ioc_attr);
+	}
+
+	strncpy(drvinfo->bus_info, pci_name(bnad->pcidev), ETHTOOL_BUSINFO_LEN);
+}
+
+static int
+get_regs(struct bnad *bnad, u32 * regs)
+{
+	int num = 0, i;
+	u32 reg_addr;
+	unsigned long flags;
+
+#define BNAD_GET_REG(addr) 					\
+do {								\
+	if (regs)						\
+		regs[num++] = readl(bnad->bar0 + (addr));	\
+	else							\
+		num++;						\
+} while (0)
+
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+
+	/* DMA Block Internal Registers */
+	BNAD_GET_REG(DMA_CTRL_REG0);
+	BNAD_GET_REG(DMA_CTRL_REG1);
+	BNAD_GET_REG(DMA_ERR_INT_STATUS);
+	BNAD_GET_REG(DMA_ERR_INT_ENABLE);
+	BNAD_GET_REG(DMA_ERR_INT_STATUS_SET);
+
+	/* APP Block Register Address Offset from BAR0 */
+	BNAD_GET_REG(HOSTFN0_INT_STATUS);
+	BNAD_GET_REG(HOSTFN0_INT_MASK);
+	BNAD_GET_REG(HOST_PAGE_NUM_FN0);
+	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN0);
+	BNAD_GET_REG(FN0_PCIE_ERR_REG);
+	BNAD_GET_REG(FN0_ERR_TYPE_STATUS_REG);
+	BNAD_GET_REG(FN0_ERR_TYPE_MSK_STATUS_REG);
+
+	BNAD_GET_REG(HOSTFN1_INT_STATUS);
+	BNAD_GET_REG(HOSTFN1_INT_MASK);
+	BNAD_GET_REG(HOST_PAGE_NUM_FN1);
+	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN1);
+	BNAD_GET_REG(FN1_PCIE_ERR_REG);
+	BNAD_GET_REG(FN1_ERR_TYPE_STATUS_REG);
+	BNAD_GET_REG(FN1_ERR_TYPE_MSK_STATUS_REG);
+
+	BNAD_GET_REG(PCIE_MISC_REG);
+
+	BNAD_GET_REG(HOST_SEM0_REG);
+	BNAD_GET_REG(HOST_SEM1_REG);
+	BNAD_GET_REG(HOST_SEM2_REG);
+	BNAD_GET_REG(HOST_SEM3_REG);
+	BNAD_GET_REG(HOST_SEM0_INFO_REG);
+	BNAD_GET_REG(HOST_SEM1_INFO_REG);
+	BNAD_GET_REG(HOST_SEM2_INFO_REG);
+	BNAD_GET_REG(HOST_SEM3_INFO_REG);
+
+	BNAD_GET_REG(TEMPSENSE_CNTL_REG);
+	BNAD_GET_REG(TEMPSENSE_STAT_REG);
+
+	BNAD_GET_REG(APP_LOCAL_ERR_STAT);
+	BNAD_GET_REG(APP_LOCAL_ERR_MSK);
+
+	BNAD_GET_REG(PCIE_LNK_ERR_STAT);
+	BNAD_GET_REG(PCIE_LNK_ERR_MSK);
+
+	BNAD_GET_REG(FCOE_FIP_ETH_TYPE);
+	BNAD_GET_REG(RESV_ETH_TYPE);
+
+	BNAD_GET_REG(HOSTFN2_INT_STATUS);
+	BNAD_GET_REG(HOSTFN2_INT_MASK);
+	BNAD_GET_REG(HOST_PAGE_NUM_FN2);
+	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN2);
+	BNAD_GET_REG(FN2_PCIE_ERR_REG);
+	BNAD_GET_REG(FN2_ERR_TYPE_STATUS_REG);
+	BNAD_GET_REG(FN2_ERR_TYPE_MSK_STATUS_REG);
+
+	BNAD_GET_REG(HOSTFN3_INT_STATUS);
+	BNAD_GET_REG(HOSTFN3_INT_MASK);
+	BNAD_GET_REG(HOST_PAGE_NUM_FN3);
+	BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN3);
+	BNAD_GET_REG(FN3_PCIE_ERR_REG);
+	BNAD_GET_REG(FN3_ERR_TYPE_STATUS_REG);
+	BNAD_GET_REG(FN3_ERR_TYPE_MSK_STATUS_REG);
+
+	/* Host Command Status Registers */
+	reg_addr = HOST_CMDSTS0_CLR_REG;
+	for (i = 0; i < 16; i++) {
+		BNAD_GET_REG(reg_addr);
+		BNAD_GET_REG(reg_addr + 4);
+		BNAD_GET_REG(reg_addr + 8);
+		reg_addr += 0x10;
+	}
+
+	/* Function ID register */
+	BNAD_GET_REG(FNC_ID_REG);
+
+	/* Function personality register */
+	BNAD_GET_REG(FNC_PERS_REG);
+
+	/* Operation mode register */
+	BNAD_GET_REG(OP_MODE);
+
+	/* LPU0 Registers */
+	BNAD_GET_REG(LPU0_MBOX_CTL_REG);
+	BNAD_GET_REG(LPU0_MBOX_CMD_REG);
+	BNAD_GET_REG(LPU0_MBOX_LINK_0REG);
+	BNAD_GET_REG(LPU1_MBOX_LINK_0REG);
+	BNAD_GET_REG(LPU0_MBOX_STATUS_0REG);
+	BNAD_GET_REG(LPU1_MBOX_STATUS_0REG);
+	BNAD_GET_REG(LPU0_ERR_STATUS_REG);
+	BNAD_GET_REG(LPU0_ERR_SET_REG);
+
+	/* LPU1 Registers */
+	BNAD_GET_REG(LPU1_MBOX_CTL_REG);
+	BNAD_GET_REG(LPU1_MBOX_CMD_REG);
+	BNAD_GET_REG(LPU0_MBOX_LINK_1REG);
+	BNAD_GET_REG(LPU1_MBOX_LINK_1REG);
+	BNAD_GET_REG(LPU0_MBOX_STATUS_1REG);
+	BNAD_GET_REG(LPU1_MBOX_STATUS_1REG);
+	BNAD_GET_REG(LPU1_ERR_STATUS_REG);
+	BNAD_GET_REG(LPU1_ERR_SET_REG);
+
+	/* PSS Registers */
+	BNAD_GET_REG(PSS_CTL_REG);
+	BNAD_GET_REG(PSS_ERR_STATUS_REG);
+	BNAD_GET_REG(ERR_STATUS_SET);
+	BNAD_GET_REG(PSS_RAM_ERR_STATUS_REG);
+
+	/* Catapult CPQ Registers */
+	BNAD_GET_REG(HOSTFN0_LPU0_MBOX0_CMD_STAT);
+	BNAD_GET_REG(HOSTFN0_LPU1_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN0_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN0_MBOX0_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN0_LPU0_MBOX1_CMD_STAT);
+	BNAD_GET_REG(HOSTFN0_LPU1_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN0_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN0_MBOX1_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN1_LPU0_MBOX0_CMD_STAT);
+	BNAD_GET_REG(HOSTFN1_LPU1_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN1_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN1_MBOX0_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN1_LPU0_MBOX1_CMD_STAT);
+	BNAD_GET_REG(HOSTFN1_LPU1_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN1_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN1_MBOX1_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN2_LPU0_MBOX0_CMD_STAT);
+	BNAD_GET_REG(HOSTFN2_LPU1_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN2_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN2_MBOX0_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN2_LPU0_MBOX1_CMD_STAT);
+	BNAD_GET_REG(HOSTFN2_LPU1_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN2_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN2_MBOX1_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN3_LPU0_MBOX0_CMD_STAT);
+	BNAD_GET_REG(HOSTFN3_LPU1_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN3_MBOX0_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN3_MBOX0_CMD_STAT);
+
+	BNAD_GET_REG(HOSTFN3_LPU0_MBOX1_CMD_STAT);
+	BNAD_GET_REG(HOSTFN3_LPU1_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU0_HOSTFN3_MBOX1_CMD_STAT);
+	BNAD_GET_REG(LPU1_HOSTFN3_MBOX1_CMD_STAT);
+
+	/* Host Function Force Parity Error Registers */
+	BNAD_GET_REG(HOSTFN0_LPU_FORCE_PERR);
+	BNAD_GET_REG(HOSTFN1_LPU_FORCE_PERR);
+	BNAD_GET_REG(HOSTFN2_LPU_FORCE_PERR);
+	BNAD_GET_REG(HOSTFN3_LPU_FORCE_PERR);
+
+	/* LL Port[0|1] Halt Mask Registers */
+	BNAD_GET_REG(LL_HALT_MSK_P0);
+	BNAD_GET_REG(LL_HALT_MSK_P1);
+
+	/* LL Port[0|1] Error Mask Registers */
+	BNAD_GET_REG(LL_ERR_MSK_P0);
+	BNAD_GET_REG(LL_ERR_MSK_P1);
+
+	/* EMC FLI Registers */
+	BNAD_GET_REG(FLI_CMD_REG);
+	BNAD_GET_REG(FLI_ADDR_REG);
+	BNAD_GET_REG(FLI_CTL_REG);
+	BNAD_GET_REG(FLI_WRDATA_REG);
+	BNAD_GET_REG(FLI_RDDATA_REG);
+	BNAD_GET_REG(FLI_DEV_STATUS_REG);
+	BNAD_GET_REG(FLI_SIG_WD_REG);
+
+	BNAD_GET_REG(FLI_DEV_VENDOR_REG);
+	BNAD_GET_REG(FLI_ERR_STATUS_REG);
+
+	/* RxAdm 0 Registers */
+	BNAD_GET_REG(RAD0_CTL_REG);
+	BNAD_GET_REG(RAD0_PE_PARM_REG);
+	BNAD_GET_REG(RAD0_BCN_REG);
+	BNAD_GET_REG(RAD0_DEFAULT_REG);
+	BNAD_GET_REG(RAD0_PROMISC_REG);
+	BNAD_GET_REG(RAD0_BCNQ_REG);
+	BNAD_GET_REG(RAD0_DEFAULTQ_REG);
+
+	BNAD_GET_REG(RAD0_ERR_STS);
+	BNAD_GET_REG(RAD0_SET_ERR_STS);
+	BNAD_GET_REG(RAD0_ERR_INT_EN);
+	BNAD_GET_REG(RAD0_FIRST_ERR);
+	BNAD_GET_REG(RAD0_FORCE_ERR);
+
+	BNAD_GET_REG(RAD0_MAC_MAN_1H);
+	BNAD_GET_REG(RAD0_MAC_MAN_1L);
+	BNAD_GET_REG(RAD0_MAC_MAN_2H);
+	BNAD_GET_REG(RAD0_MAC_MAN_2L);
+	BNAD_GET_REG(RAD0_MAC_MAN_3H);
+	BNAD_GET_REG(RAD0_MAC_MAN_3L);
+	BNAD_GET_REG(RAD0_MAC_MAN_4H);
+	BNAD_GET_REG(RAD0_MAC_MAN_4L);
+
+	BNAD_GET_REG(RAD0_LAST4_IP);
+
+	/* RxAdm 1 Registers */
+	BNAD_GET_REG(RAD1_CTL_REG);
+	BNAD_GET_REG(RAD1_PE_PARM_REG);
+	BNAD_GET_REG(RAD1_BCN_REG);
+	BNAD_GET_REG(RAD1_DEFAULT_REG);
+	BNAD_GET_REG(RAD1_PROMISC_REG);
+	BNAD_GET_REG(RAD1_BCNQ_REG);
+	BNAD_GET_REG(RAD1_DEFAULTQ_REG);
+
+	BNAD_GET_REG(RAD1_ERR_STS);
+	BNAD_GET_REG(RAD1_SET_ERR_STS);
+	BNAD_GET_REG(RAD1_ERR_INT_EN);
+
+	/* TxA0 Registers */
+	BNAD_GET_REG(TXA0_CTRL_REG);
+	/* TxA0 TSO Sequence # Registers (RO) */
+	for (i = 0; i < 8; i++) {
+		BNAD_GET_REG(TXA0_TSO_TCP_SEQ_REG(i));
+		BNAD_GET_REG(TXA0_TSO_IP_INFO_REG(i));
+	}
+
+	/* TxA1 Registers */
+	BNAD_GET_REG(TXA1_CTRL_REG);
+	/* TxA1 TSO Sequence # Registers (RO) */
+	for (i = 0; i < 8; i++) {
+		BNAD_GET_REG(TXA1_TSO_TCP_SEQ_REG(i));
+		BNAD_GET_REG(TXA1_TSO_IP_INFO_REG(i));
+	}
+
+	/* RxA Registers */
+	BNAD_GET_REG(RXA0_CTL_REG);
+	BNAD_GET_REG(RXA1_CTL_REG);
+
+	/* PLB0 Registers */
+	BNAD_GET_REG(PLB0_ECM_TIMER_REG);
+	BNAD_GET_REG(PLB0_RL_CTL);
+	for (i = 0; i < 8; i++)
+		BNAD_GET_REG(PLB0_RL_MAX_BC(i));
+	BNAD_GET_REG(PLB0_RL_TU_PRIO);
+	for (i = 0; i < 8; i++)
+		BNAD_GET_REG(PLB0_RL_BYTE_CNT(i));
+	BNAD_GET_REG(PLB0_RL_MIN_REG);
+	BNAD_GET_REG(PLB0_RL_MAX_REG);
+	BNAD_GET_REG(PLB0_EMS_ADD_REG);
+
+	/* PLB1 Registers */
+	BNAD_GET_REG(PLB1_ECM_TIMER_REG);
+	BNAD_GET_REG(PLB1_RL_CTL);
+	for (i = 0; i < 8; i++)
+		BNAD_GET_REG(PLB1_RL_MAX_BC(i));
+	BNAD_GET_REG(PLB1_RL_TU_PRIO);
+	for (i = 0; i < 8; i++)
+		BNAD_GET_REG(PLB1_RL_BYTE_CNT(i));
+	BNAD_GET_REG(PLB1_RL_MIN_REG);
+	BNAD_GET_REG(PLB1_RL_MAX_REG);
+	BNAD_GET_REG(PLB1_EMS_ADD_REG);
+
+	/* HQM Control Register */
+	BNAD_GET_REG(HQM0_CTL_REG);
+	BNAD_GET_REG(HQM0_RXQ_STOP_SEM);
+	BNAD_GET_REG(HQM0_TXQ_STOP_SEM);
+	BNAD_GET_REG(HQM1_CTL_REG);
+	BNAD_GET_REG(HQM1_RXQ_STOP_SEM);
+	BNAD_GET_REG(HQM1_TXQ_STOP_SEM);
+
+	/* LUT Registers */
+	BNAD_GET_REG(LUT0_ERR_STS);
+	BNAD_GET_REG(LUT0_SET_ERR_STS);
+	BNAD_GET_REG(LUT1_ERR_STS);
+	BNAD_GET_REG(LUT1_SET_ERR_STS);
+
+	/* TRC Registers */
+	BNAD_GET_REG(TRC_CTL_REG);
+	BNAD_GET_REG(TRC_MODS_REG);
+	BNAD_GET_REG(TRC_TRGC_REG);
+	BNAD_GET_REG(TRC_CNT1_REG);
+	BNAD_GET_REG(TRC_CNT2_REG);
+	BNAD_GET_REG(TRC_NXTS_REG);
+	BNAD_GET_REG(TRC_DIRR_REG);
+	for (i = 0; i < 10; i++)
+		BNAD_GET_REG(TRC_TRGM_REG(i));
+	for (i = 0; i < 10; i++)
+		BNAD_GET_REG(TRC_NXTM_REG(i));
+	for (i = 0; i < 10; i++)
+		BNAD_GET_REG(TRC_STRM_REG(i));
+
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+#undef BNAD_GET_REG
+	return num;
+}
+static int
+bnad_get_regs_len(struct net_device *netdev)
+{
+	int ret = get_regs(netdev_priv(netdev), NULL) * sizeof(u32);
+	return ret;
+}
+
+static void
+bnad_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
+{
+	memset(buf, 0, bnad_get_regs_len(netdev));
+	get_regs(netdev_priv(netdev), buf);
+}
+
+static void
+bnad_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo)
+{
+	wolinfo->supported = 0;
+	wolinfo->wolopts = 0;
+}
+
+static int
+bnad_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	unsigned long flags;
+
+	/* Lock rqd. to access bnad->bna_lock */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	coalesce->use_adaptive_rx_coalesce =
+		(bnad->cfg_flags & BNAD_CF_DIM_ENABLED) ? true : false;
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	coalesce->rx_coalesce_usecs = bnad->rx_coalescing_timeo *
+					BFI_COALESCING_TIMER_UNIT;
+	coalesce->tx_coalesce_usecs = bnad->tx_coalescing_timeo *
+					BFI_COALESCING_TIMER_UNIT;
+	coalesce->tx_max_coalesced_frames = BFI_TX_INTERPKT_COUNT;
+
+	return 0;
+}
+
+static int
+bnad_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	unsigned long flags;
+	int dim_timer_del = 0;
+
+	if (coalesce->rx_coalesce_usecs == 0 ||
+	    coalesce->rx_coalesce_usecs >
+	    BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT)
+		return -EINVAL;
+
+	if (coalesce->tx_coalesce_usecs == 0 ||
+	    coalesce->tx_coalesce_usecs >
+	    BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT)
+		return -EINVAL;
+
+	mutex_lock(&bnad->conf_mutex);
+	/*
+	 * Do not need to store rx_coalesce_usecs here
+	 * Every time DIM is disabled, we can get it from the
+	 * stack.
+	 */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	if (coalesce->use_adaptive_rx_coalesce) {
+		if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED)) {
+			bnad->cfg_flags |= BNAD_CF_DIM_ENABLED;
+			bnad_dim_timer_start(bnad);
+		}
+	} else {
+		if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) {
+			bnad->cfg_flags &= ~BNAD_CF_DIM_ENABLED;
+			dim_timer_del = bnad_dim_timer_running(bnad);
+			if (dim_timer_del) {
+				clear_bit(BNAD_RF_DIM_TIMER_RUNNING,
+							&bnad->run_flags);
+				spin_unlock_irqrestore(&bnad->bna_lock, flags);
+				del_timer_sync(&bnad->dim_timer);
+				spin_lock_irqsave(&bnad->bna_lock, flags);
+			}
+			bnad_rx_coalescing_timeo_set(bnad);
+		}
+	}
+	if (bnad->tx_coalescing_timeo != coalesce->tx_coalesce_usecs /
+					BFI_COALESCING_TIMER_UNIT) {
+		bnad->tx_coalescing_timeo = coalesce->tx_coalesce_usecs /
+						BFI_COALESCING_TIMER_UNIT;
+		bnad_tx_coalescing_timeo_set(bnad);
+	}
+
+	if (bnad->rx_coalescing_timeo != coalesce->rx_coalesce_usecs /
+					BFI_COALESCING_TIMER_UNIT) {
+		bnad->rx_coalescing_timeo = coalesce->rx_coalesce_usecs /
+						BFI_COALESCING_TIMER_UNIT;
+
+		if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED))
+			bnad_rx_coalescing_timeo_set(bnad);
+
+	}
+
+	/* Add Tx Inter-pkt DMA count?  */
+
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	mutex_unlock(&bnad->conf_mutex);
+	return 0;
+}
+
+static void
+bnad_get_ringparam(struct net_device *netdev,
+		   struct ethtool_ringparam *ringparam)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	ringparam->rx_max_pending = BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq;
+	ringparam->rx_mini_max_pending = 0;
+	ringparam->rx_jumbo_max_pending = 0;
+	ringparam->tx_max_pending = BNAD_MAX_Q_DEPTH;
+
+	ringparam->rx_pending = bnad->rxq_depth;
+	ringparam->rx_mini_max_pending = 0;
+	ringparam->rx_jumbo_max_pending = 0;
+	ringparam->tx_pending = bnad->txq_depth;
+}
+
+static int
+bnad_set_ringparam(struct net_device *netdev,
+		   struct ethtool_ringparam *ringparam)
+{
+	int i, current_err, err = 0;
+	struct bnad *bnad = netdev_priv(netdev);
+
+	mutex_lock(&bnad->conf_mutex);
+	if (ringparam->rx_pending == bnad->rxq_depth &&
+	    ringparam->tx_pending == bnad->txq_depth) {
+		mutex_unlock(&bnad->conf_mutex);
+		return 0;
+	}
+
+	if (ringparam->rx_pending < BNAD_MIN_Q_DEPTH ||
+	    ringparam->rx_pending > BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq ||
+	    !BNA_POWER_OF_2(ringparam->rx_pending)) {
+		mutex_unlock(&bnad->conf_mutex);
+		return -EINVAL;
+	}
+	if (ringparam->tx_pending < BNAD_MIN_Q_DEPTH ||
+	    ringparam->tx_pending > BNAD_MAX_Q_DEPTH ||
+	    !BNA_POWER_OF_2(ringparam->tx_pending)) {
+		mutex_unlock(&bnad->conf_mutex);
+		return -EINVAL;
+	}
+
+	if (ringparam->rx_pending != bnad->rxq_depth) {
+		bnad->rxq_depth = ringparam->rx_pending;
+		for (i = 0; i < bnad->num_rx; i++) {
+			if (!bnad->rx_info[i].rx)
+				continue;
+			bnad_cleanup_rx(bnad, i);
+			current_err = bnad_setup_rx(bnad, i);
+			if (current_err && !err)
+				err = current_err;
+		}
+	}
+	if (ringparam->tx_pending != bnad->txq_depth) {
+		bnad->txq_depth = ringparam->tx_pending;
+		for (i = 0; i < bnad->num_tx; i++) {
+			if (!bnad->tx_info[i].tx)
+				continue;
+			bnad_cleanup_tx(bnad, i);
+			current_err = bnad_setup_tx(bnad, i);
+			if (current_err && !err)
+				err = current_err;
+		}
+	}
+
+	mutex_unlock(&bnad->conf_mutex);
+	return err;
+}
+
+static void
+bnad_get_pauseparam(struct net_device *netdev,
+		    struct ethtool_pauseparam *pauseparam)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	pauseparam->autoneg = 0;
+	pauseparam->rx_pause = bnad->bna.port.pause_config.rx_pause;
+	pauseparam->tx_pause = bnad->bna.port.pause_config.tx_pause;
+}
+
+static int
+bnad_set_pauseparam(struct net_device *netdev,
+		    struct ethtool_pauseparam *pauseparam)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	struct bna_pause_config pause_config;
+	unsigned long flags;
+
+	if (pauseparam->autoneg == AUTONEG_ENABLE)
+		return -EINVAL;
+
+	mutex_lock(&bnad->conf_mutex);
+	if (pauseparam->rx_pause != bnad->bna.port.pause_config.rx_pause ||
+	    pauseparam->tx_pause != bnad->bna.port.pause_config.tx_pause) {
+		pause_config.rx_pause = pauseparam->rx_pause;
+		pause_config.tx_pause = pauseparam->tx_pause;
+		spin_lock_irqsave(&bnad->bna_lock, flags);
+		bna_port_pause_config(&bnad->bna.port, &pause_config, NULL);
+		spin_unlock_irqrestore(&bnad->bna_lock, flags);
+	}
+	mutex_unlock(&bnad->conf_mutex);
+	return 0;
+}
+
+static u32
+bnad_get_rx_csum(struct net_device *netdev)
+{
+	u32 rx_csum;
+	struct bnad *bnad = netdev_priv(netdev);
+
+	rx_csum = bnad->rx_csum;
+	return rx_csum;
+}
+
+static int
+bnad_set_rx_csum(struct net_device *netdev, u32 rx_csum)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	mutex_lock(&bnad->conf_mutex);
+	bnad->rx_csum = rx_csum;
+	mutex_unlock(&bnad->conf_mutex);
+	return 0;
+}
+
+static int
+bnad_set_tx_csum(struct net_device *netdev, u32 tx_csum)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	mutex_lock(&bnad->conf_mutex);
+	if (tx_csum) {
+		netdev->features |= NETIF_F_IP_CSUM;
+		netdev->features |= NETIF_F_IPV6_CSUM;
+	} else {
+		netdev->features &= ~NETIF_F_IP_CSUM;
+		netdev->features &= ~NETIF_F_IPV6_CSUM;
+	}
+	mutex_unlock(&bnad->conf_mutex);
+	return 0;
+}
+
+static int
+bnad_set_tso(struct net_device *netdev, u32 tso)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+
+	mutex_lock(&bnad->conf_mutex);
+	if (tso) {
+		netdev->features |= NETIF_F_TSO;
+		netdev->features |= NETIF_F_TSO6;
+	} else {
+		netdev->features &= ~NETIF_F_TSO;
+		netdev->features &= ~NETIF_F_TSO6;
+	}
+	mutex_unlock(&bnad->conf_mutex);
+	return 0;
+}
+
+static void
+bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	int i, j, q_num;
+	u64 bmap;
+
+	mutex_lock(&bnad->conf_mutex);
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < BNAD_ETHTOOL_STATS_NUM; i++) {
+			BUG_ON(!(strlen(bnad_net_stats_strings[i]) <
+				   ETH_GSTRING_LEN));
+			memcpy(string, bnad_net_stats_strings[i],
+			       ETH_GSTRING_LEN);
+			string += ETH_GSTRING_LEN;
+		}
+		bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
+			((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
+		for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+			if (bmap & 1) {
+				sprintf(string, "txf%d_ucast_octets", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txf%d_ucast", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txf%d_ucast_vlan", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txf%d_mcast_octets", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txf%d_mcast", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txf%d_mcast_vlan", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txf%d_bcast_octets", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txf%d_bcast", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txf%d_bcast_vlan", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txf%d_errors", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txf%d_filter_vlan", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txf%d_filter_mac_sa", i);
+				string += ETH_GSTRING_LEN;
+			}
+			bmap >>= 1;
+		}
+
+		bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
+			((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
+		for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+			if (bmap & 1) {
+				sprintf(string, "rxf%d_ucast_octets", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxf%d_ucast", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxf%d_ucast_vlan", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxf%d_mcast_octets", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxf%d_mcast", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxf%d_mcast_vlan", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxf%d_bcast_octets", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxf%d_bcast", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxf%d_bcast_vlan", i);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxf%d_frame_drops", i);
+				string += ETH_GSTRING_LEN;
+			}
+			bmap >>= 1;
+		}
+
+		q_num = 0;
+		for (i = 0; i < bnad->num_rx; i++) {
+			if (!bnad->rx_info[i].rx)
+				continue;
+			for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+				sprintf(string, "cq%d_producer_index", q_num);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "cq%d_consumer_index", q_num);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "cq%d_hw_producer_index",
+					q_num);
+				string += ETH_GSTRING_LEN;
+				q_num++;
+			}
+		}
+
+		q_num = 0;
+		for (i = 0; i < bnad->num_rx; i++) {
+			if (!bnad->rx_info[i].rx)
+				continue;
+			for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+				sprintf(string, "rxq%d_packets", q_num);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxq%d_bytes", q_num);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxq%d_packets_with_error",
+								q_num);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxq%d_allocbuf_failed", q_num);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxq%d_producer_index", q_num);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "rxq%d_consumer_index", q_num);
+				string += ETH_GSTRING_LEN;
+				q_num++;
+				if (bnad->rx_info[i].rx_ctrl[j].ccb &&
+					bnad->rx_info[i].rx_ctrl[j].ccb->
+					rcb[1] &&
+					bnad->rx_info[i].rx_ctrl[j].ccb->
+					rcb[1]->rxq) {
+					sprintf(string, "rxq%d_packets", q_num);
+					string += ETH_GSTRING_LEN;
+					sprintf(string, "rxq%d_bytes", q_num);
+					string += ETH_GSTRING_LEN;
+					sprintf(string,
+					"rxq%d_packets_with_error", q_num);
+					string += ETH_GSTRING_LEN;
+					sprintf(string, "rxq%d_allocbuf_failed",
+								q_num);
+					string += ETH_GSTRING_LEN;
+					sprintf(string, "rxq%d_producer_index",
+								q_num);
+					string += ETH_GSTRING_LEN;
+					sprintf(string, "rxq%d_consumer_index",
+								q_num);
+					string += ETH_GSTRING_LEN;
+					q_num++;
+				}
+			}
+		}
+
+		q_num = 0;
+		for (i = 0; i < bnad->num_tx; i++) {
+			if (!bnad->tx_info[i].tx)
+				continue;
+			for (j = 0; j < bnad->num_txq_per_tx; j++) {
+				sprintf(string, "txq%d_packets", q_num);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txq%d_bytes", q_num);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txq%d_producer_index", q_num);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txq%d_consumer_index", q_num);
+				string += ETH_GSTRING_LEN;
+				sprintf(string, "txq%d_hw_consumer_index",
+									q_num);
+				string += ETH_GSTRING_LEN;
+				q_num++;
+			}
+		}
+
+		break;
+
+	default:
+		break;
+	}
+
+	mutex_unlock(&bnad->conf_mutex);
+}
+
+static int
+bnad_get_stats_count_locked(struct net_device *netdev)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	int i, j, count, rxf_active_num = 0, txf_active_num = 0;
+	u64 bmap;
+
+	bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
+			((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
+	for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+		if (bmap & 1)
+			txf_active_num++;
+		bmap >>= 1;
+	}
+	bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
+			((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
+	for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+		if (bmap & 1)
+			rxf_active_num++;
+		bmap >>= 1;
+	}
+	count = BNAD_ETHTOOL_STATS_NUM +
+		txf_active_num * BNAD_NUM_TXF_COUNTERS +
+		rxf_active_num * BNAD_NUM_RXF_COUNTERS;
+
+	for (i = 0; i < bnad->num_rx; i++) {
+		if (!bnad->rx_info[i].rx)
+			continue;
+		count += bnad->num_rxp_per_rx * BNAD_NUM_CQ_COUNTERS;
+		count += bnad->num_rxp_per_rx * BNAD_NUM_RXQ_COUNTERS;
+		for (j = 0; j < bnad->num_rxp_per_rx; j++)
+			if (bnad->rx_info[i].rx_ctrl[j].ccb &&
+				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&
+				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1]->rxq)
+				count +=  BNAD_NUM_RXQ_COUNTERS;
+	}
+
+	for (i = 0; i < bnad->num_tx; i++) {
+		if (!bnad->tx_info[i].tx)
+			continue;
+		count += bnad->num_txq_per_tx * BNAD_NUM_TXQ_COUNTERS;
+	}
+	return count;
+}
+
+static int
+bnad_per_q_stats_fill(struct bnad *bnad, u64 *buf, int bi)
+{
+	int i, j;
+	struct bna_rcb *rcb = NULL;
+	struct bna_tcb *tcb = NULL;
+
+	for (i = 0; i < bnad->num_rx; i++) {
+		if (!bnad->rx_info[i].rx)
+			continue;
+		for (j = 0; j < bnad->num_rxp_per_rx; j++)
+			if (bnad->rx_info[i].rx_ctrl[j].ccb &&
+				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] &&
+				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0]->rxq) {
+				buf[bi++] = bnad->rx_info[i].rx_ctrl[j].
+						ccb->producer_index;
+				buf[bi++] = 0; /* ccb->consumer_index */
+				buf[bi++] = *(bnad->rx_info[i].rx_ctrl[j].
+						ccb->hw_producer_index);
+			}
+	}
+	for (i = 0; i < bnad->num_rx; i++) {
+		if (!bnad->rx_info[i].rx)
+			continue;
+		for (j = 0; j < bnad->num_rxp_per_rx; j++)
+			if (bnad->rx_info[i].rx_ctrl[j].ccb) {
+				if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] &&
+					bnad->rx_info[i].rx_ctrl[j].ccb->
+					rcb[0]->rxq) {
+					rcb = bnad->rx_info[i].rx_ctrl[j].
+							ccb->rcb[0];
+					buf[bi++] = rcb->rxq->rx_packets;
+					buf[bi++] = rcb->rxq->rx_bytes;
+					buf[bi++] = rcb->rxq->
+							rx_packets_with_error;
+					buf[bi++] = rcb->rxq->
+							rxbuf_alloc_failed;
+					buf[bi++] = rcb->producer_index;
+					buf[bi++] = rcb->consumer_index;
+				}
+				if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&
+					bnad->rx_info[i].rx_ctrl[j].ccb->
+					rcb[1]->rxq) {
+					rcb = bnad->rx_info[i].rx_ctrl[j].
+								ccb->rcb[1];
+					buf[bi++] = rcb->rxq->rx_packets;
+					buf[bi++] = rcb->rxq->rx_bytes;
+					buf[bi++] = rcb->rxq->
+							rx_packets_with_error;
+					buf[bi++] = rcb->rxq->
+							rxbuf_alloc_failed;
+					buf[bi++] = rcb->producer_index;
+					buf[bi++] = rcb->consumer_index;
+				}
+			}
+	}
+
+	for (i = 0; i < bnad->num_tx; i++) {
+		if (!bnad->tx_info[i].tx)
+			continue;
+		for (j = 0; j < bnad->num_txq_per_tx; j++)
+			if (bnad->tx_info[i].tcb[j] &&
+				bnad->tx_info[i].tcb[j]->txq) {
+				tcb = bnad->tx_info[i].tcb[j];
+				buf[bi++] = tcb->txq->tx_packets;
+				buf[bi++] = tcb->txq->tx_bytes;
+				buf[bi++] = tcb->producer_index;
+				buf[bi++] = tcb->consumer_index;
+				buf[bi++] = *(tcb->hw_consumer_index);
+			}
+	}
+
+	return bi;
+}
+
+static void
+bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
+		       u64 *buf)
+{
+	struct bnad *bnad = netdev_priv(netdev);
+	int i, j, bi;
+	unsigned long flags;
+	struct rtnl_link_stats64 *net_stats64;
+	u64 *stats64;
+	u64 bmap;
+
+	mutex_lock(&bnad->conf_mutex);
+	if (bnad_get_stats_count_locked(netdev) != stats->n_stats) {
+		mutex_unlock(&bnad->conf_mutex);
+		return;
+	}
+
+	/*
+	 * Used bna_lock to sync reads from bna_stats, which is written
+	 * under the same lock
+	 */
+	spin_lock_irqsave(&bnad->bna_lock, flags);
+	bi = 0;
+	memset(buf, 0, stats->n_stats * sizeof(u64));
+
+	net_stats64 = (struct rtnl_link_stats64 *)buf;
+	bnad_netdev_qstats_fill(bnad, net_stats64);
+	bnad_netdev_hwstats_fill(bnad, net_stats64);
+
+	bi = sizeof(*net_stats64) / sizeof(u64);
+
+	/* Fill driver stats into ethtool buffers */
+	stats64 = (u64 *)&bnad->stats.drv_stats;
+	for (i = 0; i < sizeof(struct bnad_drv_stats) / sizeof(u64); i++)
+		buf[bi++] = stats64[i];
+
+	/* Fill hardware stats excluding the rxf/txf into ethtool bufs */
+	stats64 = (u64 *) bnad->stats.bna_stats->hw_stats;
+	for (i = 0;
+	     i < offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64);
+	     i++)
+		buf[bi++] = stats64[i];
+
+	/* Fill txf stats into ethtool buffers */
+	bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
+			((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
+	for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+		if (bmap & 1) {
+			stats64 = (u64 *)&bnad->stats.bna_stats->
+						hw_stats->txf_stats[i];
+			for (j = 0; j < sizeof(struct bfi_ll_stats_txf) /
+					sizeof(u64); j++)
+				buf[bi++] = stats64[j];
+		}
+		bmap >>= 1;
+	}
+
+	/*  Fill rxf stats into ethtool buffers */
+	bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
+			((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
+	for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+		if (bmap & 1) {
+			stats64 = (u64 *)&bnad->stats.bna_stats->
+						hw_stats->rxf_stats[i];
+			for (j = 0; j < sizeof(struct bfi_ll_stats_rxf) /
+					sizeof(u64); j++)
+				buf[bi++] = stats64[j];
+		}
+		bmap >>= 1;
+	}
+
+	/* Fill per Q stats into ethtool buffers */
+	bi = bnad_per_q_stats_fill(bnad, buf, bi);
+
+	spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+	mutex_unlock(&bnad->conf_mutex);
+}
+
+static int
+bnad_get_sset_count(struct net_device *netdev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return bnad_get_stats_count_locked(netdev);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static struct ethtool_ops bnad_ethtool_ops = {
+	.get_settings = bnad_get_settings,
+	.set_settings = bnad_set_settings,
+	.get_drvinfo = bnad_get_drvinfo,
+	.get_regs_len = bnad_get_regs_len,
+	.get_regs = bnad_get_regs,
+	.get_wol = bnad_get_wol,
+	.get_link = ethtool_op_get_link,
+	.get_coalesce = bnad_get_coalesce,
+	.set_coalesce = bnad_set_coalesce,
+	.get_ringparam = bnad_get_ringparam,
+	.set_ringparam = bnad_set_ringparam,
+	.get_pauseparam = bnad_get_pauseparam,
+	.set_pauseparam = bnad_set_pauseparam,
+	.get_rx_csum = bnad_get_rx_csum,
+	.set_rx_csum = bnad_set_rx_csum,
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = bnad_set_tx_csum,
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = ethtool_op_set_sg,
+	.get_tso = ethtool_op_get_tso,
+	.set_tso = bnad_set_tso,
+	.get_strings = bnad_get_strings,
+	.get_ethtool_stats = bnad_get_ethtool_stats,
+	.get_sset_count = bnad_get_sset_count
+};
+
+void
+bnad_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &bnad_ethtool_ops);
+}
diff --git a/drivers/net/bna/cna.h b/drivers/net/bna/cna.h
new file mode 100644
index 0000000..bbd39dc
--- /dev/null
+++ b/drivers/net/bna/cna.h
@@ -0,0 +1,81 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2006-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __CNA_H__
+#define __CNA_H__
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/string.h>
+
+#include <linux/list.h>
+
+#define bfa_sm_fault(__mod, __event)    do {                            \
+	pr_err("SM Assertion failure: %s: %d: event = %d", __FILE__, __LINE__, \
+		__event); \
+} while (0)
+
+extern char bfa_version[];
+
+#define	CNA_FW_FILE_CT	"ctfw_cna.bin"
+#define FC_SYMNAME_MAX	256	/*!< max name server symbolic name size */
+
+#pragma pack(1)
+
+#define MAC_ADDRLEN	(6)
+typedef struct mac { u8 mac[MAC_ADDRLEN]; } mac_t;
+
+#pragma pack()
+
+#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
+#define bfa_q_next(_qe)	(((struct list_head *) (_qe))->next)
+#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev)
+
+/*
+ * bfa_q_qe_init - to initialize a queue element
+ */
+#define bfa_q_qe_init(_qe) {						\
+	bfa_q_next(_qe) = (struct list_head *) NULL;			\
+	bfa_q_prev(_qe) = (struct list_head *) NULL;			\
+}
+
+/*
+ * bfa_q_deq - dequeue an element from head of the queue
+ */
+#define bfa_q_deq(_q, _qe) {						\
+	if (!list_empty(_q)) {						\
+		(*((struct list_head **) (_qe))) = bfa_q_next(_q);	\
+		bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) =	\
+						(struct list_head *) (_q); \
+		bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \
+		bfa_q_qe_init(*((struct list_head **) _qe));		\
+	} else {							\
+		*((struct list_head **) (_qe)) = (struct list_head *) NULL; \
+	}								\
+}
+
+#endif /* __CNA_H__ */
diff --git a/drivers/net/bna/cna_fwimg.c b/drivers/net/bna/cna_fwimg.c
new file mode 100644
index 0000000..e8f4ecd
--- /dev/null
+++ b/drivers/net/bna/cna_fwimg.c
@@ -0,0 +1,64 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include <linux/firmware.h>
+#include "cna.h"
+
+const struct firmware *bfi_fw;
+static u32 *bfi_image_ct_cna;
+static u32 bfi_image_ct_cna_size;
+
+static u32 *
+cna_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
+			u32 *bfi_image_size, char *fw_name)
+{
+	const struct firmware *fw;
+
+	if (request_firmware(&fw, fw_name, &pdev->dev)) {
+		pr_alert("Can't locate firmware %s\n", fw_name);
+		goto error;
+	}
+
+	*bfi_image = (u32 *)fw->data;
+	*bfi_image_size = fw->size/sizeof(u32);
+	bfi_fw = fw;
+
+	return *bfi_image;
+error:
+	return NULL;
+}
+
+u32 *
+cna_get_firmware_buf(struct pci_dev *pdev)
+{
+	if (bfi_image_ct_cna_size == 0)
+		cna_read_firmware(pdev, &bfi_image_ct_cna,
+			&bfi_image_ct_cna_size, CNA_FW_FILE_CT);
+	return bfi_image_ct_cna;
+}
+
+u32 *
+bfa_cb_image_get_chunk(int type, u32 off)
+{
+	return (u32 *)(bfi_image_ct_cna + off);
+}
+
+u32
+bfa_cb_image_get_size(int type)
+{
+	return bfi_image_ct_cna_size;
+}
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index e6a803f..062600b 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -37,9 +37,6 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/if_vlan.h>
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define BCM_VLAN 1
-#endif
 #include <net/ip.h>
 #include <net/tcp.h>
 #include <net/checksum.h>
@@ -49,6 +46,7 @@
 #include <linux/cache.h>
 #include <linux/firmware.h>
 #include <linux/log2.h>
+#include <linux/aer.h>
 
 #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
 #define BCM_CNIC 1
@@ -58,13 +56,13 @@
 #include "bnx2_fw.h"
 
 #define DRV_MODULE_NAME		"bnx2"
-#define DRV_MODULE_VERSION	"2.0.17"
-#define DRV_MODULE_RELDATE	"July 18, 2010"
-#define FW_MIPS_FILE_06		"bnx2/bnx2-mips-06-5.0.0.j6.fw"
-#define FW_RV2P_FILE_06		"bnx2/bnx2-rv2p-06-5.0.0.j3.fw"
-#define FW_MIPS_FILE_09		"bnx2/bnx2-mips-09-5.0.0.j15.fw"
-#define FW_RV2P_FILE_09_Ax	"bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw"
-#define FW_RV2P_FILE_09		"bnx2/bnx2-rv2p-09-5.0.0.j10.fw"
+#define DRV_MODULE_VERSION	"2.0.18"
+#define DRV_MODULE_RELDATE	"Oct 7, 2010"
+#define FW_MIPS_FILE_06		"bnx2/bnx2-mips-06-6.0.15.fw"
+#define FW_RV2P_FILE_06		"bnx2/bnx2-rv2p-06-6.0.15.fw"
+#define FW_MIPS_FILE_09		"bnx2/bnx2-mips-09-6.0.17.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"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -265,7 +263,7 @@
 		if (diff == TX_DESC_CNT)
 			diff = MAX_TX_DESC_CNT;
 	}
-	return (bp->tx_ring_size - diff);
+	return bp->tx_ring_size - diff;
 }
 
 static u32
@@ -298,7 +296,7 @@
 static u32
 bnx2_shmem_rd(struct bnx2 *bp, u32 offset)
 {
-	return (bnx2_reg_rd_ind(bp, bp->shmem_base + offset));
+	return bnx2_reg_rd_ind(bp, bp->shmem_base + offset);
 }
 
 static void
@@ -976,9 +974,9 @@
 static char *
 bnx2_xceiver_str(struct bnx2 *bp)
 {
-	return ((bp->phy_port == PORT_FIBRE) ? "SerDes" :
+	return (bp->phy_port == PORT_FIBRE) ? "SerDes" :
 		((bp->phy_flags & BNX2_PHY_FLAG_SERDES) ? "Remote Copper" :
-		 "Copper"));
+		 "Copper");
 }
 
 static void
@@ -1268,30 +1266,9 @@
 	val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
 	val |= 0x02 << 8;
 
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		u32 lo_water, hi_water;
+	if (bp->flow_ctrl & FLOW_CTRL_TX)
+		val |= BNX2_L2CTX_FLOW_CTRL_ENABLE;
 
-		if (bp->flow_ctrl & FLOW_CTRL_TX)
-			lo_water = BNX2_L2CTX_LO_WATER_MARK_DEFAULT;
-		else
-			lo_water = BNX2_L2CTX_LO_WATER_MARK_DIS;
-		if (lo_water >= bp->rx_ring_size)
-			lo_water = 0;
-
-		hi_water = min_t(int, bp->rx_ring_size / 4, lo_water + 16);
-
-		if (hi_water <= lo_water)
-			lo_water = 0;
-
-		hi_water /= BNX2_L2CTX_HI_WATER_MARK_SCALE;
-		lo_water /= BNX2_L2CTX_LO_WATER_MARK_SCALE;
-
-		if (hi_water > 0xf)
-			hi_water = 0xf;
-		else if (hi_water == 0)
-			lo_water = 0;
-		val |= lo_water | (hi_water << BNX2_L2CTX_HI_WATER_MARK_SHIFT);
-	}
 	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_CTX_TYPE, val);
 }
 
@@ -1372,8 +1349,7 @@
 	/* Acknowledge the interrupt. */
 	REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
 
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		bnx2_init_all_rx_contexts(bp);
+	bnx2_init_all_rx_contexts(bp);
 }
 
 static void
@@ -1757,7 +1733,7 @@
 	u32 new_adv = 0;
 
 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
-		return (bnx2_setup_remote_phy(bp, port));
+		return bnx2_setup_remote_phy(bp, port);
 
 	if (!(bp->autoneg & AUTONEG_SPEED)) {
 		u32 new_bmcr;
@@ -2170,10 +2146,10 @@
 		return 0;
 
 	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-		return (bnx2_setup_serdes_phy(bp, port));
+		return bnx2_setup_serdes_phy(bp, port);
 	}
 	else {
-		return (bnx2_setup_copper_phy(bp));
+		return bnx2_setup_copper_phy(bp);
 	}
 }
 
@@ -3108,8 +3084,6 @@
 		struct sw_bd *rx_buf, *next_rx_buf;
 		struct sk_buff *skb;
 		dma_addr_t dma_addr;
-		u16 vtag = 0;
-		int hw_vlan __maybe_unused = 0;
 
 		sw_ring_cons = RX_RING_IDX(sw_cons);
 		sw_ring_prod = RX_RING_IDX(sw_prod);
@@ -3189,23 +3163,8 @@
 			goto next_rx;
 
 		if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) &&
-		    !(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) {
-			vtag = rx_hdr->l2_fhdr_vlan_tag;
-#ifdef BCM_VLAN
-			if (bp->vlgrp)
-				hw_vlan = 1;
-			else
-#endif
-			{
-				struct vlan_ethhdr *ve = (struct vlan_ethhdr *)
-					__skb_push(skb, 4);
-
-				memmove(ve, skb->data + 4, ETH_ALEN * 2);
-				ve->h_vlan_proto = htons(ETH_P_8021Q);
-				ve->h_vlan_TCI = htons(vtag);
-				len += 4;
-			}
-		}
+		    !(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG))
+			__vlan_hwaccel_put_tag(skb, rx_hdr->l2_fhdr_vlan_tag);
 
 		skb->protocol = eth_type_trans(skb, bp->dev);
 
@@ -3217,7 +3176,7 @@
 
 		}
 
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 		if (bp->rx_csum &&
 			(status & (L2_FHDR_STATUS_TCP_SEGMENT |
 			L2_FHDR_STATUS_UDP_DATAGRAM))) {
@@ -3232,14 +3191,7 @@
 			skb->rxhash = rx_hdr->l2_fhdr_hash;
 
 		skb_record_rx_queue(skb, bnapi - &bp->bnx2_napi[0]);
-
-#ifdef BCM_VLAN
-		if (hw_vlan)
-			vlan_gro_receive(&bnapi->napi, bp->vlgrp, vtag, skb);
-		else
-#endif
-			napi_gro_receive(&bnapi->napi, skb);
-
+		napi_gro_receive(&bnapi->napi, skb);
 		rx_pkt++;
 
 next_rx:
@@ -3554,13 +3506,9 @@
 	rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
 				  BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
 	sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
-#ifdef BCM_VLAN
-	if (!bp->vlgrp && (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
+	if (!(dev->features & NETIF_F_HW_VLAN_RX) &&
+	     (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
 		rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
-#else
-	if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)
-		rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
-#endif
 	if (dev->flags & IFF_PROMISC) {
 		/* Promiscuous mode. */
 		rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
@@ -4973,6 +4921,11 @@
 
 	REG_WR(bp, BNX2_HC_CONFIG, val);
 
+	if (bp->rx_ticks < 25)
+		bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 1);
+	else
+		bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 0);
+
 	for (i = 1; i < bp->irq_nvecs; i++) {
 		u32 base = ((i - 1) * BNX2_HC_SB_CONFIG_SIZE) +
 			   BNX2_HC_SB_CONFIG_1;
@@ -5241,18 +5194,20 @@
 		bnx2_init_rx_ring(bp, i);
 
 	if (bp->num_rx_rings > 1) {
-		u32 tbl_32;
-		u8 *tbl = (u8 *) &tbl_32;
-
-		bnx2_reg_wr_ind(bp, BNX2_RXP_SCRATCH_RSS_TBL_SZ,
-				BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES);
+		u32 tbl_32 = 0;
 
 		for (i = 0; i < BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES; i++) {
-			tbl[i % 4] = i % (bp->num_rx_rings - 1);
-			if ((i % 4) == 3)
-				bnx2_reg_wr_ind(bp,
-						BNX2_RXP_SCRATCH_RSS_TBL + i,
-						cpu_to_be32(tbl_32));
+			int shift = (i % 8) << 2;
+
+			tbl_32 |= (i % (bp->num_rx_rings - 1)) << shift;
+			if ((i % 8) == 7) {
+				REG_WR(bp, BNX2_RLUP_RSS_DATA, tbl_32);
+				REG_WR(bp, BNX2_RLUP_RSS_COMMAND, (i >> 3) |
+					BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK |
+					BNX2_RLUP_RSS_COMMAND_WRITE |
+					BNX2_RLUP_RSS_COMMAND_HASH_MASK);
+				tbl_32 = 0;
+			}
 		}
 
 		val = BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI |
@@ -6201,7 +6156,7 @@
 	}
 }
 
-static void
+static int
 bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
 {
 	int cpus = num_online_cpus();
@@ -6230,9 +6185,10 @@
 	}
 
 	bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
-	bp->dev->real_num_tx_queues = bp->num_tx_rings;
+	netif_set_real_num_tx_queues(bp->dev, bp->num_tx_rings);
 
 	bp->num_rx_rings = bp->irq_nvecs;
+	return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings);
 }
 
 /* Called with rtnl_lock */
@@ -6247,7 +6203,9 @@
 	bnx2_set_power_state(bp, PCI_D0);
 	bnx2_disable_int(bp);
 
-	bnx2_setup_int_mode(bp, disable_msi);
+	rc = bnx2_setup_int_mode(bp, disable_msi);
+	if (rc)
+		goto open_err;
 	bnx2_init_napi(bp);
 	bnx2_napi_enable(bp);
 	rc = bnx2_alloc_mem(bp);
@@ -6376,29 +6334,6 @@
 	schedule_work(&bp->reset_task);
 }
 
-#ifdef BCM_VLAN
-/* Called with rtnl_lock */
-static void
-bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	if (netif_running(dev))
-		bnx2_netif_stop(bp, false);
-
-	bp->vlgrp = vlgrp;
-
-	if (!netif_running(dev))
-		return;
-
-	bnx2_set_rx_mode(dev);
-	if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)
-		bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
-
-	bnx2_netif_start(bp, false);
-}
-#endif
-
 /* Called with netif_tx_lock.
  * bnx2_tx_int() runs without netif_tx_lock unless it needs to call
  * netif_wake_queue().
@@ -6439,12 +6374,11 @@
 		vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
 	}
 
-#ifdef BCM_VLAN
-	if (bp->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		vlan_tag_flags |=
 			(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
 	}
-#endif
+
 	if ((mss = skb_shinfo(skb)->gso_size)) {
 		u32 tcp_opt_len;
 		struct iphdr *iph;
@@ -7581,15 +7515,36 @@
 	struct bnx2 *bp = netdev_priv(dev);
 
 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		return (ethtool_op_set_tx_ipv6_csum(dev, data));
+		return ethtool_op_set_tx_ipv6_csum(dev, data);
 	else
-		return (ethtool_op_set_tx_csum(dev, data));
+		return ethtool_op_set_tx_csum(dev, data);
 }
 
 static int
 bnx2_set_flags(struct net_device *dev, u32 data)
 {
-	return ethtool_op_set_flags(dev, data, ETH_FLAG_RXHASH);
+	struct bnx2 *bp = netdev_priv(dev);
+	int rc;
+
+	if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN) &&
+	    !(data & ETH_FLAG_RXVLAN))
+		return -EINVAL;
+
+	rc = ethtool_op_set_flags(dev, data, ETH_FLAG_RXHASH | ETH_FLAG_RXVLAN |
+				  ETH_FLAG_TXVLAN);
+	if (rc)
+		return rc;
+
+	if ((!!(data & ETH_FLAG_RXVLAN) !=
+	    !!(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) &&
+	    netif_running(dev)) {
+		bnx2_netif_stop(bp, false);
+		bnx2_set_rx_mode(dev);
+		bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
+		bnx2_netif_start(bp, false);
+	}
+
+	return 0;
 }
 
 static const struct ethtool_ops bnx2_ethtool_ops = {
@@ -7704,7 +7659,7 @@
 		return -EINVAL;
 
 	dev->mtu = new_mtu;
-	return (bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size));
+	return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -7890,6 +7845,7 @@
 	int rc, i, j;
 	u32 reg;
 	u64 dma_mask, persist_dma_mask;
+	int err;
 
 	SET_NETDEV_DEV(dev, &pdev->dev);
 	bp = netdev_priv(dev);
@@ -7926,7 +7882,6 @@
 	}
 
 	pci_set_master(pdev);
-	pci_save_state(pdev);
 
 	bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
 	if (bp->pm_cap == 0) {
@@ -7981,6 +7936,15 @@
 		bp->flags |= BNX2_FLAG_PCIE;
 		if (CHIP_REV(bp) == CHIP_REV_Ax)
 			bp->flags |= BNX2_FLAG_JUMBO_BROKEN;
+
+		/* AER (Advanced Error Reporting) hooks */
+		err = pci_enable_pcie_error_reporting(pdev);
+		if (err) {
+			dev_err(&pdev->dev, "pci_enable_pcie_error_reporting "
+					    "failed 0x%x\n", err);
+			/* non-fatal, continue */
+		}
+
 	} else {
 		bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
 		if (bp->pcix_cap == 0) {
@@ -8237,9 +8201,14 @@
 	bp->timer.data = (unsigned long) bp;
 	bp->timer.function = bnx2_timer;
 
+	pci_save_state(pdev);
+
 	return 0;
 
 err_out_unmap:
+	if (bp->flags & BNX2_FLAG_PCIE)
+		pci_disable_pcie_error_reporting(pdev);
+
 	if (bp->regview) {
 		iounmap(bp->regview);
 		bp->regview = NULL;
@@ -8315,9 +8284,6 @@
 	.ndo_set_mac_address	= bnx2_change_mac_addr,
 	.ndo_change_mtu		= bnx2_change_mtu,
 	.ndo_tx_timeout		= bnx2_tx_timeout,
-#ifdef BCM_VLAN
-	.ndo_vlan_rx_register	= bnx2_vlan_rx_register,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= poll_bnx2,
 #endif
@@ -8325,9 +8291,7 @@
 
 static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
 {
-#ifdef BCM_VLAN
 	dev->vlan_features |= flags;
-#endif
 }
 
 static int __devinit
@@ -8376,9 +8340,7 @@
 		dev->features |= NETIF_F_IPV6_CSUM;
 		vlan_features_add(dev, NETIF_F_IPV6_CSUM);
 	}
-#ifdef BCM_VLAN
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
 	dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
 	vlan_features_add(dev, NETIF_F_TSO | NETIF_F_TSO_ECN);
 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
@@ -8435,7 +8397,11 @@
 
 	kfree(bp->temp_stats_blk);
 
+	if (bp->flags & BNX2_FLAG_PCIE)
+		pci_disable_pcie_error_reporting(pdev);
+
 	free_netdev(dev);
+
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
@@ -8527,25 +8493,38 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct bnx2 *bp = netdev_priv(dev);
+	pci_ers_result_t result;
+	int err;
 
 	rtnl_lock();
 	if (pci_enable_device(pdev)) {
 		dev_err(&pdev->dev,
 			"Cannot re-enable PCI device after reset\n");
-		rtnl_unlock();
-		return PCI_ERS_RESULT_DISCONNECT;
-	}
-	pci_set_master(pdev);
-	pci_restore_state(pdev);
-	pci_save_state(pdev);
+		result = PCI_ERS_RESULT_DISCONNECT;
+	} else {
+		pci_set_master(pdev);
+		pci_restore_state(pdev);
+		pci_save_state(pdev);
 
-	if (netif_running(dev)) {
-		bnx2_set_power_state(bp, PCI_D0);
-		bnx2_init_nic(bp, 1);
+		if (netif_running(dev)) {
+			bnx2_set_power_state(bp, PCI_D0);
+			bnx2_init_nic(bp, 1);
+		}
+		result = PCI_ERS_RESULT_RECOVERED;
 	}
-
 	rtnl_unlock();
-	return PCI_ERS_RESULT_RECOVERED;
+
+	if (!(bp->flags & BNX2_FLAG_PCIE))
+		return result;
+
+	err = pci_cleanup_aer_uncorrect_error_status(pdev);
+	if (err) {
+		dev_err(&pdev->dev,
+			"pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n",
+			 err); /* non-fatal, continue */
+	}
+
+	return result;
 }
 
 /**
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 2104c10..bf4c342 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -352,12 +352,7 @@
 #define BNX2_L2CTX_BD_PRE_READ				0x00000000
 #define BNX2_L2CTX_CTX_SIZE				0x00000000
 #define BNX2_L2CTX_CTX_TYPE				0x00000000
-#define BNX2_L2CTX_LO_WATER_MARK_DEFAULT		 4
-#define BNX2_L2CTX_LO_WATER_MARK_SCALE			 4
-#define BNX2_L2CTX_LO_WATER_MARK_DIS			 0
-#define BNX2_L2CTX_HI_WATER_MARK_SHIFT			 4
-#define BNX2_L2CTX_HI_WATER_MARK_SCALE			 16
-#define BNX2_L2CTX_WATER_MARKS_MSK			 0x000000ff
+#define BNX2_L2CTX_FLOW_CTRL_ENABLE			 0x000000ff
 #define BNX2_L2CTX_CTX_TYPE_SIZE_L2			 ((0x20/20)<<16)
 #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE		 (0xf<<28)
 #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_UNDEFINED	 (0<<28)
@@ -4185,6 +4180,15 @@
 #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_IP_ONLY_XI	 (2L<<2)
 #define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_RES_XI	 (3L<<2)
 
+#define BNX2_RLUP_RSS_COMMAND				0x00002048
+#define BNX2_RLUP_RSS_COMMAND_RSS_IND_TABLE_ADDR	 (0xfUL<<0)
+#define BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK		 (0xffUL<<4)
+#define BNX2_RLUP_RSS_COMMAND_WRITE			 (1UL<<12)
+#define BNX2_RLUP_RSS_COMMAND_READ			 (1UL<<13)
+#define BNX2_RLUP_RSS_COMMAND_HASH_MASK			 (0x7UL<<14)
+
+#define BNX2_RLUP_RSS_DATA				0x0000204c
+
 
 /*
  *  rbuf_reg definition
@@ -6077,6 +6081,7 @@
 
 #define BNX2_COM_SCRATCH				0x00120000
 
+#define BNX2_FW_RX_LOW_LATENCY				 0x00120058
 #define BNX2_FW_RX_DROP_COUNT				 0x00120084
 
 
@@ -6497,8 +6502,8 @@
 #define TX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct tx_bd))
 #define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
 
-#define MAX_RX_RINGS	4
-#define MAX_RX_PG_RINGS	16
+#define MAX_RX_RINGS	8
+#define MAX_RX_PG_RINGS	32
 #define RX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct rx_bd))
 #define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
 #define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
@@ -6737,10 +6742,6 @@
 
 	struct bnx2_napi	bnx2_napi[BNX2_MAX_MSIX_VEC];
 
-#ifdef BCM_VLAN
-	struct			vlan_group *vlgrp;
-#endif
-
 	u32			rx_buf_use_size;	/* useable size */
 	u32			rx_buf_size;		/* with alignment */
 	u32			rx_copy_thresh;
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 0c2d96e..9571ecf 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -20,26 +20,20 @@
  * (you will need to reboot afterwards) */
 /* #define BNX2X_STOP_ON_ERROR */
 
-#define DRV_MODULE_VERSION      "1.52.53-4"
-#define DRV_MODULE_RELDATE      "2010/16/08"
+#define DRV_MODULE_VERSION      "1.60.00-3"
+#define DRV_MODULE_RELDATE      "2010/10/19"
 #define BNX2X_BC_VER            0x040200
 
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define BCM_VLAN			1
-#endif
-
 #define BNX2X_MULTI_QUEUE
 
 #define BNX2X_NEW_NAPI
 
 
-
 #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
 #define BCM_CNIC 1
 #include "../cnic_if.h"
 #endif
 
-
 #ifdef BCM_CNIC
 #define BNX2X_MIN_MSIX_VEC_CNT 3
 #define BNX2X_MSIX_VEC_FP_START 2
@@ -129,16 +123,18 @@
 	} while (0)
 #endif
 
+#define bnx2x_mc_addr(ha)      ((ha)->addr)
 
 #define U64_LO(x)			(u32)(((u64)(x)) & 0xffffffff)
 #define U64_HI(x)			(u32)(((u64)(x)) >> 32)
 #define HILO_U64(hi, lo)		((((u64)(hi)) << 32) + (lo))
 
 
-#define REG_ADDR(bp, offset)		(bp->regview + offset)
+#define REG_ADDR(bp, offset)		((bp->regview) + (offset))
 
 #define REG_RD(bp, offset)		readl(REG_ADDR(bp, offset))
 #define REG_RD8(bp, offset)		readb(REG_ADDR(bp, offset))
+#define REG_RD16(bp, offset)		readw(REG_ADDR(bp, offset))
 
 #define REG_WR(bp, offset, val)		writel((u32)val, REG_ADDR(bp, offset))
 #define REG_WR8(bp, offset, val)	writeb((u8)val, REG_ADDR(bp, offset))
@@ -160,6 +156,9 @@
 				 offset, len32); \
 	} while (0)
 
+#define REG_WR_DMAE_LEN(bp, offset, valp, len32) \
+	REG_WR_DMAE(bp, offset, valp, len32)
+
 #define VIRT_WR_DMAE_LEN(bp, data, addr, len32, le32_swap) \
 	do { \
 		memcpy(GUNZIP_BUF(bp), data, (len32) * 4); \
@@ -175,16 +174,59 @@
 					 offsetof(struct shmem2_region, field))
 #define SHMEM2_RD(bp, field)		REG_RD(bp, SHMEM2_ADDR(bp, field))
 #define SHMEM2_WR(bp, field, val)	REG_WR(bp, SHMEM2_ADDR(bp, field), val)
+#define MF_CFG_ADDR(bp, field)		(bp->common.mf_cfg_base + \
+					 offsetof(struct mf_cfg, field))
+#define MF2_CFG_ADDR(bp, field)		(bp->common.mf2_cfg_base + \
+					 offsetof(struct mf2_cfg, field))
 
-#define MF_CFG_RD(bp, field)		SHMEM_RD(bp, mf_cfg.field)
-#define MF_CFG_WR(bp, field, val)	SHMEM_WR(bp, mf_cfg.field, val)
+#define MF_CFG_RD(bp, field)		REG_RD(bp, MF_CFG_ADDR(bp, field))
+#define MF_CFG_WR(bp, field, val)	REG_WR(bp,\
+					       MF_CFG_ADDR(bp, field), (val))
+#define MF2_CFG_RD(bp, field)		REG_RD(bp, MF2_CFG_ADDR(bp, field))
+
+#define SHMEM2_HAS(bp, field)		((bp)->common.shmem2_base &&	\
+					 (SHMEM2_RD((bp), size) >	\
+					 offsetof(struct shmem2_region, field)))
 
 #define EMAC_RD(bp, reg)		REG_RD(bp, emac_base + reg)
 #define EMAC_WR(bp, reg, val)		REG_WR(bp, emac_base + reg, val)
 
+/* SP SB indices */
+
+/* General SP events - stats query, cfc delete, etc  */
+#define HC_SP_INDEX_ETH_DEF_CONS		3
+
+/* EQ completions */
+#define HC_SP_INDEX_EQ_CONS			7
+
+/* iSCSI L2 */
+#define HC_SP_INDEX_ETH_ISCSI_CQ_CONS		5
+#define HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS	1
+
+/**
+ *  CIDs and CLIDs:
+ *  CLIDs below is a CLID for func 0, then the CLID for other
+ *  functions will be calculated by the formula:
+ *
+ *  FUNC_N_CLID_X = N * NUM_SPECIAL_CLIENTS + FUNC_0_CLID_X
+ *
+ */
+/* iSCSI L2 */
+#define BNX2X_ISCSI_ETH_CL_ID		17
+#define BNX2X_ISCSI_ETH_CID		17
+
+/** Additional rings budgeting */
+#ifdef BCM_CNIC
+#define CNIC_CONTEXT_USE		1
+#else
+#define CNIC_CONTEXT_USE		0
+#endif /* BCM_CNIC */
+
 #define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \
 	AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR
 
+#define SM_RX_ID			0
+#define SM_TX_ID			1
 
 /* fast path */
 
@@ -254,11 +296,24 @@
 #define RX_SGE_MASK_LEN_MASK		(RX_SGE_MASK_LEN - 1)
 #define NEXT_SGE_MASK_ELEM(el)		(((el) + 1) & RX_SGE_MASK_LEN_MASK)
 
+union host_hc_status_block {
+	/* pointer to fp status block e1x */
+	struct host_hc_status_block_e1x *e1x_sb;
+	/* pointer to fp status block e2 */
+	struct host_hc_status_block_e2  *e2_sb;
+};
 
 struct bnx2x_fastpath {
 
+#define BNX2X_NAPI_WEIGHT       128
 	struct napi_struct	napi;
-	struct host_status_block *status_blk;
+	union host_hc_status_block	status_blk;
+	/* chip independed shortcuts into sb structure */
+	__le16			*sb_index_values;
+	__le16			*sb_running_index;
+	/* chip independed shortcut into rx_prods_offset memory */
+	u32			ustorm_rx_prods_offset;
+
 	dma_addr_t		status_blk_mapping;
 
 	struct sw_tx_bd		*tx_buf_ring;
@@ -288,10 +343,15 @@
 #define BNX2X_FP_STATE_OPEN		0xa0000
 #define BNX2X_FP_STATE_HALTING		0xb0000
 #define BNX2X_FP_STATE_HALTED		0xc0000
+#define BNX2X_FP_STATE_TERMINATING	0xd0000
+#define BNX2X_FP_STATE_TERMINATED	0xe0000
 
-	u8			index;	/* number in fp array */
-	u8			cl_id;	/* eth client id */
-	u8			sb_id;	/* status block number in HW */
+	u8			index;		/* number in fp array */
+	u8			cl_id;		/* eth client id */
+	u8			cl_qzone_id;
+	u8			fw_sb_id;	/* status block number in FW */
+	u8			igu_sb_id;	/* status block number in HW */
+	u32			cid;
 
 	union db_prod		tx_db;
 
@@ -301,8 +361,7 @@
 	u16			tx_bd_cons;
 	__le16			*tx_cons_sb;
 
-	__le16			fp_c_idx;
-	__le16			fp_u_idx;
+	__le16			fp_hc_idx;
 
 	u16			rx_bd_prod;
 	u16			rx_bd_cons;
@@ -312,8 +371,6 @@
 	/* The last maximal completed SGE */
 	u16			last_max_sge;
 	__le16			*rx_cons_sb;
-	__le16			*rx_bd_cons_sb;
-
 
 	unsigned long		tx_pkt,
 				rx_pkt,
@@ -356,6 +413,8 @@
 #define NUM_TX_BD			(TX_DESC_CNT * NUM_TX_RINGS)
 #define MAX_TX_BD			(NUM_TX_BD - 1)
 #define MAX_TX_AVAIL			(MAX_TX_DESC_CNT * NUM_TX_RINGS - 2)
+#define INIT_JUMBO_TX_RING_SIZE		MAX_TX_AVAIL
+#define INIT_TX_RING_SIZE		MAX_TX_AVAIL
 #define NEXT_TX_IDX(x)		((((x) & MAX_TX_DESC_CNT) == \
 				  (MAX_TX_DESC_CNT - 1)) ? (x) + 2 : (x) + 1)
 #define TX_BD(x)			((x) & MAX_TX_BD)
@@ -369,6 +428,9 @@
 #define NUM_RX_BD			(RX_DESC_CNT * NUM_RX_RINGS)
 #define MAX_RX_BD			(NUM_RX_BD - 1)
 #define MAX_RX_AVAIL			(MAX_RX_DESC_CNT * NUM_RX_RINGS - 2)
+#define MIN_RX_AVAIL			128
+#define INIT_JUMBO_RX_RING_SIZE		MAX_RX_AVAIL
+#define INIT_RX_RING_SIZE		MAX_RX_AVAIL
 #define NEXT_RX_IDX(x)		((((x) & RX_DESC_MASK) == \
 				  (MAX_RX_DESC_CNT - 1)) ? (x) + 3 : (x) + 1)
 #define RX_BD(x)			((x) & MAX_RX_BD)
@@ -419,11 +481,12 @@
 						 le32_to_cpu((bd)->addr_lo))
 #define BD_UNMAP_LEN(bd)		(le16_to_cpu((bd)->nbytes))
 
-
+#define BNX2X_DB_MIN_SHIFT		3	/* 8 bytes */
+#define BNX2X_DB_SHIFT			7	/* 128 bytes*/
 #define DPM_TRIGER_TYPE			0x40
 #define DOORBELL(bp, cid, val) \
 	do { \
-		writel((u32)(val), bp->doorbells + (BCM_PAGE_SIZE * (cid)) + \
+		writel((u32)(val), bp->doorbells + (bp->db_size * (cid)) + \
 		       DPM_TRIGER_TYPE); \
 	} while (0)
 
@@ -481,31 +544,15 @@
 #define BNX2X_RX_SUM_FIX(cqe) \
 	BNX2X_PRS_FLAG_OVERETH_IPV4(cqe->fast_path_cqe.pars_flags.flags)
 
-
-#define FP_USB_FUNC_OFF			(2 + 2*HC_USTORM_SB_NUM_INDICES)
-#define FP_CSB_FUNC_OFF			(2 + 2*HC_CSTORM_SB_NUM_INDICES)
-
-#define U_SB_ETH_RX_CQ_INDEX		HC_INDEX_U_ETH_RX_CQ_CONS
-#define U_SB_ETH_RX_BD_INDEX		HC_INDEX_U_ETH_RX_BD_CONS
-#define C_SB_ETH_TX_CQ_INDEX		HC_INDEX_C_ETH_TX_CQ_CONS
+#define U_SB_ETH_RX_CQ_INDEX		1
+#define U_SB_ETH_RX_BD_INDEX		2
+#define C_SB_ETH_TX_CQ_INDEX		5
 
 #define BNX2X_RX_SB_INDEX \
-	(&fp->status_blk->u_status_block.index_values[U_SB_ETH_RX_CQ_INDEX])
-
-#define BNX2X_RX_SB_BD_INDEX \
-	(&fp->status_blk->u_status_block.index_values[U_SB_ETH_RX_BD_INDEX])
-
-#define BNX2X_RX_SB_INDEX_NUM \
-		(((U_SB_ETH_RX_CQ_INDEX << \
-		   USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER_SHIFT) & \
-		  USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER) | \
-		 ((U_SB_ETH_RX_BD_INDEX << \
-		   USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER_SHIFT) & \
-		  USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER))
+	(&fp->sb_index_values[U_SB_ETH_RX_CQ_INDEX])
 
 #define BNX2X_TX_SB_INDEX \
-	(&fp->status_blk->c_status_block.index_values[C_SB_ETH_TX_CQ_INDEX])
-
+	(&fp->sb_index_values[C_SB_ETH_TX_CQ_INDEX])
 
 /* end of fast path */
 
@@ -521,12 +568,19 @@
 #define CHIP_NUM_57710			0x164e
 #define CHIP_NUM_57711			0x164f
 #define CHIP_NUM_57711E			0x1650
+#define CHIP_NUM_57712			0x1662
+#define CHIP_NUM_57712E			0x1663
 #define CHIP_IS_E1(bp)			(CHIP_NUM(bp) == CHIP_NUM_57710)
 #define CHIP_IS_57711(bp)		(CHIP_NUM(bp) == CHIP_NUM_57711)
 #define CHIP_IS_57711E(bp)		(CHIP_NUM(bp) == CHIP_NUM_57711E)
+#define CHIP_IS_57712(bp)		(CHIP_NUM(bp) == CHIP_NUM_57712)
+#define CHIP_IS_57712E(bp)		(CHIP_NUM(bp) == CHIP_NUM_57712E)
 #define CHIP_IS_E1H(bp)			(CHIP_IS_57711(bp) || \
 					 CHIP_IS_57711E(bp))
-#define IS_E1H_OFFSET			CHIP_IS_E1H(bp)
+#define CHIP_IS_E2(bp)			(CHIP_IS_57712(bp) || \
+					 CHIP_IS_57712E(bp))
+#define CHIP_IS_E1x(bp)			(CHIP_IS_E1((bp)) || CHIP_IS_E1H((bp)))
+#define IS_E1H_OFFSET			(CHIP_IS_E1H(bp) || CHIP_IS_E2(bp))
 
 #define CHIP_REV(bp)			(bp->common.chip_id & 0x0000f000)
 #define CHIP_REV_Ax			0x00000000
@@ -552,12 +606,34 @@
 
 	u32			shmem_base;
 	u32			shmem2_base;
+	u32			mf_cfg_base;
+	u32			mf2_cfg_base;
 
 	u32			hw_config;
 
 	u32			bc_ver;
+
+	u8			int_block;
+#define INT_BLOCK_HC			0
+#define INT_BLOCK_IGU			1
+#define INT_BLOCK_MODE_NORMAL		0
+#define INT_BLOCK_MODE_BW_COMP		2
+#define CHIP_INT_MODE_IS_NBC(bp)		\
+			(CHIP_IS_E2(bp) &&	\
+			!((bp)->common.int_block & INT_BLOCK_MODE_BW_COMP))
+#define CHIP_INT_MODE_IS_BC(bp) (!CHIP_INT_MODE_IS_NBC(bp))
+
+	u8			chip_port_mode;
+#define CHIP_4_PORT_MODE			0x0
+#define CHIP_2_PORT_MODE			0x1
+#define CHIP_PORT_MODE_NONE			0x2
+#define CHIP_MODE(bp)			(bp->common.chip_port_mode)
+#define CHIP_MODE_IS_4_PORT(bp) (CHIP_MODE(bp) == CHIP_4_PORT_MODE)
 };
 
+/* IGU MSIX STATISTICS on 57712: 64 for VFs; 4 for PFs; 4 for Attentions */
+#define BNX2X_IGU_STAS_MSG_VF_CNT 64
+#define BNX2X_IGU_STAS_MSG_PF_CNT 4
 
 /* end of common */
 
@@ -566,13 +642,13 @@
 struct bnx2x_port {
 	u32			pmf;
 
-	u32			link_config;
+	u32			link_config[LINK_CONFIG_SIZE];
 
-	u32			supported;
+	u32			supported[LINK_CONFIG_SIZE];
 /* link settings - missing defines */
 #define SUPPORTED_2500baseX_Full	(1 << 15)
 
-	u32			advertising;
+	u32			advertising[LINK_CONFIG_SIZE];
 /* link settings - missing defines */
 #define ADVERTISED_2500baseX_Full	(1 << 15)
 
@@ -589,27 +665,98 @@
 
 /* end of port */
 
+/* e1h Classification CAM line allocations */
+enum {
+	CAM_ETH_LINE = 0,
+	CAM_ISCSI_ETH_LINE,
+	CAM_MAX_PF_LINE = CAM_ISCSI_ETH_LINE
+};
 
+#define BNX2X_VF_ID_INVALID	0xFF
 
-#ifdef BCM_CNIC
-#define MAX_CONTEXT			15
-#else
-#define MAX_CONTEXT			16
-#endif
+/*
+ * The total number of L2 queues, MSIX vectors and HW contexts (CIDs) is
+ * control by the number of fast-path status blocks supported by the
+ * device (HW/FW). Each fast-path status block (FP-SB) aka non-default
+ * status block represents an independent interrupts context that can
+ * serve a regular L2 networking queue. However special L2 queues such
+ * as the FCoE queue do not require a FP-SB and other components like
+ * the CNIC may consume FP-SB reducing the number of possible L2 queues
+ *
+ * If the maximum number of FP-SB available is X then:
+ * a. If CNIC is supported it consumes 1 FP-SB thus the max number of
+ *    regular L2 queues is Y=X-1
+ * b. in MF mode the actual number of L2 queues is Y= (X-1/MF_factor)
+ * c. If the FCoE L2 queue is supported the actual number of L2 queues
+ *    is Y+1
+ * d. The number of irqs (MSIX vectors) is either Y+1 (one extra for
+ *    slow-path interrupts) or Y+2 if CNIC is supported (one additional
+ *    FP interrupt context for the CNIC).
+ * e. The number of HW context (CID count) is always X or X+1 if FCoE
+ *    L2 queue is supported. the cid for the FCoE L2 queue is always X.
+ */
+
+#define FP_SB_MAX_E1x		16	/* fast-path interrupt contexts E1x */
+#define FP_SB_MAX_E2		16	/* fast-path interrupt contexts E2 */
+
+/*
+ * cid_cnt paramter below refers to the value returned by
+ * 'bnx2x_get_l2_cid_count()' routine
+ */
+
+/*
+ * The number of FP context allocated by the driver == max number of regular
+ * L2 queues + 1 for the FCoE L2 queue
+ */
+#define L2_FP_COUNT(cid_cnt)	((cid_cnt) - CNIC_CONTEXT_USE)
 
 union cdu_context {
 	struct eth_context eth;
 	char pad[1024];
 };
 
+/* CDU host DB constants */
+#define CDU_ILT_PAGE_SZ_HW	3
+#define CDU_ILT_PAGE_SZ		(4096 << CDU_ILT_PAGE_SZ_HW) /* 32K */
+#define ILT_PAGE_CIDS		(CDU_ILT_PAGE_SZ / sizeof(union cdu_context))
+
+#ifdef BCM_CNIC
+#define CNIC_ISCSI_CID_MAX	256
+#define CNIC_CID_MAX		(CNIC_ISCSI_CID_MAX)
+#define CNIC_ILT_LINES		DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
+#endif
+
+#define QM_ILT_PAGE_SZ_HW	3
+#define QM_ILT_PAGE_SZ		(4096 << QM_ILT_PAGE_SZ_HW) /* 32K */
+#define QM_CID_ROUND		1024
+
+#ifdef BCM_CNIC
+/* TM (timers) host DB constants */
+#define TM_ILT_PAGE_SZ_HW	2
+#define TM_ILT_PAGE_SZ		(4096 << TM_ILT_PAGE_SZ_HW) /* 16K */
+/* #define TM_CONN_NUM		(CNIC_STARTING_CID+CNIC_ISCSI_CXT_MAX) */
+#define TM_CONN_NUM		1024
+#define TM_ILT_SZ		(8 * TM_CONN_NUM)
+#define TM_ILT_LINES		DIV_ROUND_UP(TM_ILT_SZ, TM_ILT_PAGE_SZ)
+
+/* SRC (Searcher) host DB constants */
+#define SRC_ILT_PAGE_SZ_HW	3
+#define SRC_ILT_PAGE_SZ		(4096 << SRC_ILT_PAGE_SZ_HW) /* 32K */
+#define SRC_HASH_BITS		10
+#define SRC_CONN_NUM		(1 << SRC_HASH_BITS) /* 1024 */
+#define SRC_ILT_SZ		(sizeof(struct src_ent) * SRC_CONN_NUM)
+#define SRC_T2_SZ		SRC_ILT_SZ
+#define SRC_ILT_LINES		DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ)
+#endif
+
 #define MAX_DMAE_C			8
 
 /* DMA memory not used in fastpath */
 struct bnx2x_slowpath {
-	union cdu_context		context[MAX_CONTEXT];
 	struct eth_stats_query		fw_stats;
 	struct mac_configuration_cmd	mac_config;
 	struct mac_configuration_cmd	mcast_config;
+	struct client_init_ramrod_data	client_init_data;
 
 	/* used by dmae command executer */
 	struct dmae_command		dmae[MAX_DMAE_C];
@@ -634,52 +781,83 @@
 #define MAX_DYNAMIC_ATTN_GRPS		8
 
 struct attn_route {
-	u32	sig[4];
+	u32	sig[5];
 };
 
+struct iro {
+	u32 base;
+	u16 m1;
+	u16 m2;
+	u16 m3;
+	u16 size;
+};
+
+struct hw_context {
+	union cdu_context *vcxt;
+	dma_addr_t cxt_mapping;
+	size_t size;
+};
+
+/* forward */
+struct bnx2x_ilt;
+
 typedef enum {
 	BNX2X_RECOVERY_DONE,
 	BNX2X_RECOVERY_INIT,
 	BNX2X_RECOVERY_WAIT,
 } bnx2x_recovery_state_t;
 
+/**
+ * Event queue (EQ or event ring) MC hsi
+ * NUM_EQ_PAGES and EQ_DESC_CNT_PAGE must be power of 2
+ */
+#define NUM_EQ_PAGES		1
+#define EQ_DESC_CNT_PAGE	(BCM_PAGE_SIZE / sizeof(union event_ring_elem))
+#define EQ_DESC_MAX_PAGE	(EQ_DESC_CNT_PAGE - 1)
+#define NUM_EQ_DESC		(EQ_DESC_CNT_PAGE * NUM_EQ_PAGES)
+#define EQ_DESC_MASK		(NUM_EQ_DESC - 1)
+#define MAX_EQ_AVAIL		(EQ_DESC_MAX_PAGE * NUM_EQ_PAGES - 2)
+
+/* depends on EQ_DESC_CNT_PAGE being a power of 2 */
+#define NEXT_EQ_IDX(x)		((((x) & EQ_DESC_MAX_PAGE) == \
+				  (EQ_DESC_MAX_PAGE - 1)) ? (x) + 2 : (x) + 1)
+
+/* depends on the above and on NUM_EQ_PAGES being a power of 2 */
+#define EQ_DESC(x)		((x) & EQ_DESC_MASK)
+
+#define BNX2X_EQ_INDEX \
+	(&bp->def_status_blk->sp_sb.\
+	index_values[HC_SP_INDEX_EQ_CONS])
+
 struct bnx2x {
 	/* Fields used in the tx and intr/napi performance paths
 	 * are grouped together in the beginning of the structure
 	 */
-	struct bnx2x_fastpath	fp[MAX_CONTEXT];
+	struct bnx2x_fastpath	*fp;
 	void __iomem		*regview;
 	void __iomem		*doorbells;
-#ifdef BCM_CNIC
-#define BNX2X_DB_SIZE		(18*BCM_PAGE_SIZE)
-#else
-#define BNX2X_DB_SIZE		(16*BCM_PAGE_SIZE)
-#endif
+	u16			db_size;
 
 	struct net_device	*dev;
 	struct pci_dev		*pdev;
 
+	struct iro		*iro_arr;
+#define IRO (bp->iro_arr)
+
 	atomic_t		intr_sem;
 
 	bnx2x_recovery_state_t	recovery_state;
 	int			is_leader;
-#ifdef BCM_CNIC
-	struct msix_entry	msix_table[MAX_CONTEXT+2];
-#else
-	struct msix_entry	msix_table[MAX_CONTEXT+1];
-#endif
+	struct msix_entry	*msix_table;
 #define INT_MODE_INTx			1
 #define INT_MODE_MSI			2
 
 	int			tx_ring_size;
 
-#ifdef BCM_VLAN
-	struct vlan_group	*vlgrp;
-#endif
-
 	u32			rx_csum;
 	u32			rx_buf_size;
-#define ETH_OVREHEAD			(ETH_HLEN + 8)	/* 8 for CRC + VLAN */
+/* 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
@@ -688,13 +866,12 @@
 #define BNX2X_RX_ALIGN_SHIFT		((L1_CACHE_SHIFT < 8) ? \
 					 L1_CACHE_SHIFT : 8)
 #define BNX2X_RX_ALIGN			(1 << BNX2X_RX_ALIGN_SHIFT)
+#define BNX2X_PXP_DRAM_ALIGN		(BNX2X_RX_ALIGN_SHIFT - 5)
 
-	struct host_def_status_block *def_status_blk;
-#define DEF_SB_ID			16
-	__le16			def_c_idx;
-	__le16			def_u_idx;
-	__le16			def_x_idx;
-	__le16			def_t_idx;
+	struct host_sp_status_block *def_status_blk;
+#define DEF_SB_IGU_ID			16
+#define DEF_SB_ID			HC_SP_SB_ID
+	__le16			def_idx;
 	__le16			def_att_idx;
 	u32			attn_state;
 	struct attn_route	attn_group[MAX_DYNAMIC_ATTN_GRPS];
@@ -706,10 +883,17 @@
 	struct eth_spe		*spq_prod_bd;
 	struct eth_spe		*spq_last_bd;
 	__le16			*dsb_sp_prod;
-	u16			spq_left; /* serialize spq */
+	atomic_t		spq_left; /* serialize spq */
 	/* used to synchronize spq accesses */
 	spinlock_t		spq_lock;
 
+	/* event queue */
+	union event_ring_elem	*eq_ring;
+	dma_addr_t		eq_mapping;
+	u16			eq_prod;
+	u16			eq_cons;
+	__le16			*eq_cons_sb;
+
 	/* Flags for marking that there is a STAT_QUERY or
 	   SET_MAC ramrod pending */
 	int			stats_pending;
@@ -728,18 +912,27 @@
 #define USING_DAC_FLAG			0x10
 #define USING_MSIX_FLAG			0x20
 #define USING_MSI_FLAG			0x40
+
 #define TPA_ENABLE_FLAG			0x80
 #define NO_MCP_FLAG			0x100
+#define DISABLE_MSI_FLAG		0x200
 #define BP_NOMCP(bp)			(bp->flags & NO_MCP_FLAG)
-#define HW_VLAN_TX_FLAG			0x400
-#define HW_VLAN_RX_FLAG			0x800
 #define MF_FUNC_DIS			0x1000
 
-	int			func;
-#define BP_PORT(bp)			(bp->func % PORT_MAX)
-#define BP_FUNC(bp)			(bp->func)
-#define BP_E1HVN(bp)			(bp->func >> 1)
+	int			pf_num;	/* absolute PF number */
+	int			pfid;	/* per-path PF number */
+	int			base_fw_ndsb;
+#define BP_PATH(bp)			(!CHIP_IS_E2(bp) ? \
+						0 : (bp->pf_num & 1))
+#define BP_PORT(bp)			(bp->pfid & 1)
+#define BP_FUNC(bp)			(bp->pfid)
+#define BP_ABS_FUNC(bp)			(bp->pf_num)
+#define BP_E1HVN(bp)			(bp->pfid >> 1)
+#define BP_VN(bp)			(CHIP_MODE_IS_4_PORT(bp) ? \
+						0 : BP_E1HVN(bp))
 #define BP_L_ID(bp)			(BP_E1HVN(bp) << 2)
+#define BP_FW_MB_IDX(bp)		(BP_PORT(bp) +\
+					 BP_VN(bp) * (CHIP_IS_E1x(bp) ? 2  : 1))
 
 #ifdef BCM_CNIC
 #define BCM_CNIC_CID_START		16
@@ -769,10 +962,11 @@
 	struct cmng_struct_per_port cmng;
 	u32			vn_weight_sum;
 
-	u32			mf_config;
-	u16			e1hov;
-	u8			e1hmf;
-#define IS_E1HMF(bp)			(bp->e1hmf != 0)
+	u32			mf_config[E1HVN_MAX];
+	u32			mf2_config[E2_FUNC_MAX];
+	u16			mf_ov;
+	u8			mf_mode;
+#define IS_MF(bp)		(bp->mf_mode != 0)
 
 	u8			wol;
 
@@ -800,6 +994,7 @@
 #define BNX2X_STATE_CLOSING_WAIT4_HALT	0x4000
 #define BNX2X_STATE_CLOSING_WAIT4_DELETE 0x5000
 #define BNX2X_STATE_CLOSING_WAIT4_UNLOAD 0x6000
+#define BNX2X_STATE_FUNC_STARTED	0x7000
 #define BNX2X_STATE_DIAG		0xe000
 #define BNX2X_STATE_ERROR		0xf000
 
@@ -808,6 +1003,15 @@
 	int			disable_tpa;
 	int			int_mode;
 
+	struct tstorm_eth_mac_filter_config	mac_filters;
+#define BNX2X_ACCEPT_NONE		0x0000
+#define BNX2X_ACCEPT_UNICAST		0x0001
+#define BNX2X_ACCEPT_MULTICAST		0x0002
+#define BNX2X_ACCEPT_ALL_UNICAST	0x0004
+#define BNX2X_ACCEPT_ALL_MULTICAST	0x0008
+#define BNX2X_ACCEPT_BROADCAST		0x0010
+#define BNX2X_PROMISCUOUS_MODE		0x10000
+
 	u32			rx_mode;
 #define BNX2X_RX_MODE_NONE		0
 #define BNX2X_RX_MODE_NORMAL		1
@@ -816,34 +1020,41 @@
 #define BNX2X_MAX_MULTICAST		64
 #define BNX2X_MAX_EMUL_MULTI		16
 
-	u32 			rx_mode_cl_mask;
-
+	u8			igu_dsb_id;
+	u8			igu_base_sb;
+	u8			igu_sb_cnt;
 	dma_addr_t		def_status_blk_mapping;
 
 	struct bnx2x_slowpath	*slowpath;
 	dma_addr_t		slowpath_mapping;
+	struct hw_context	context;
+
+	struct bnx2x_ilt	*ilt;
+#define BP_ILT(bp)		((bp)->ilt)
+#define ILT_MAX_LINES		128
+
+	int			l2_cid_count;
+#define L2_ILT_LINES(bp)	(DIV_ROUND_UP((bp)->l2_cid_count, \
+				 ILT_PAGE_CIDS))
+#define BNX2X_DB_SIZE(bp)	((bp)->l2_cid_count * (1 << BNX2X_DB_SHIFT))
+
+	int			qm_cid_count;
 
 	int			dropless_fc;
 
 #ifdef BCM_CNIC
 	u32			cnic_flags;
 #define BNX2X_CNIC_FLAG_MAC_SET		1
-
-	void			*t1;
-	dma_addr_t		t1_mapping;
 	void			*t2;
 	dma_addr_t		t2_mapping;
-	void			*timers;
-	dma_addr_t		timers_mapping;
-	void			*qm;
-	dma_addr_t		qm_mapping;
 	struct cnic_ops		*cnic_ops;
 	void			*cnic_data;
 	u32			cnic_tag;
 	struct cnic_eth_dev	cnic_eth_dev;
-	struct host_status_block *cnic_sb;
+	union host_hc_status_block cnic_sb;
 	dma_addr_t		cnic_sb_mapping;
-#define CNIC_SB_ID(bp)			BP_L_ID(bp)
+#define CNIC_SB_ID(bp)		((bp)->base_fw_ndsb + BP_L_ID(bp))
+#define CNIC_IGU_SB_ID(bp)	((bp)->igu_base_sb)
 	struct eth_spe		*cnic_kwq;
 	struct eth_spe		*cnic_kwq_prod;
 	struct eth_spe		*cnic_kwq_cons;
@@ -913,32 +1124,196 @@
 	const struct firmware	*firmware;
 };
 
+/**
+ *	Init queue/func interface
+ */
+/* queue init flags */
+#define QUEUE_FLG_TPA		0x0001
+#define QUEUE_FLG_CACHE_ALIGN	0x0002
+#define QUEUE_FLG_STATS		0x0004
+#define QUEUE_FLG_OV		0x0008
+#define QUEUE_FLG_VLAN		0x0010
+#define QUEUE_FLG_COS		0x0020
+#define QUEUE_FLG_HC		0x0040
+#define QUEUE_FLG_DHC		0x0080
+#define QUEUE_FLG_OOO		0x0100
 
-#define BNX2X_MAX_QUEUES(bp)	(IS_E1HMF(bp) ? (MAX_CONTEXT/E1HVN_MAX) \
-					      : MAX_CONTEXT)
+#define QUEUE_DROP_IP_CS_ERR	TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR
+#define QUEUE_DROP_TCP_CS_ERR	TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR
+#define QUEUE_DROP_TTL0		TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0
+#define QUEUE_DROP_UDP_CS_ERR	TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR
+
+
+
+/* rss capabilities */
+#define RSS_IPV4_CAP		0x0001
+#define RSS_IPV4_TCP_CAP	0x0002
+#define RSS_IPV6_CAP		0x0004
+#define RSS_IPV6_TCP_CAP	0x0008
+
 #define BNX2X_NUM_QUEUES(bp)	(bp->num_queues)
 #define is_multi(bp)		(BNX2X_NUM_QUEUES(bp) > 1)
 
+#define BNX2X_MAX_QUEUES(bp)	(bp->igu_sb_cnt - CNIC_CONTEXT_USE)
+#define is_eth_multi(bp)	(BNX2X_NUM_ETH_QUEUES(bp) > 1)
+
+#define RSS_IPV4_CAP_MASK						\
+	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY
+
+#define RSS_IPV4_TCP_CAP_MASK						\
+	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY
+
+#define RSS_IPV6_CAP_MASK						\
+	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY
+
+#define RSS_IPV6_TCP_CAP_MASK						\
+	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY
+
+/* func init flags */
+#define FUNC_FLG_STATS		0x0001
+#define FUNC_FLG_TPA		0x0002
+#define FUNC_FLG_SPQ		0x0004
+#define FUNC_FLG_LEADING	0x0008	/* PF only */
+
+struct rxq_pause_params {
+	u16		bd_th_lo;
+	u16		bd_th_hi;
+	u16		rcq_th_lo;
+	u16		rcq_th_hi;
+	u16		sge_th_lo; /* valid iff QUEUE_FLG_TPA */
+	u16		sge_th_hi; /* valid iff QUEUE_FLG_TPA */
+	u16		pri_map;
+};
+
+struct bnx2x_rxq_init_params {
+	/* cxt*/
+	struct eth_context *cxt;
+
+	/* dma */
+	dma_addr_t	dscr_map;
+	dma_addr_t	sge_map;
+	dma_addr_t	rcq_map;
+	dma_addr_t	rcq_np_map;
+
+	u16		flags;
+	u16		drop_flags;
+	u16		mtu;
+	u16		buf_sz;
+	u16		fw_sb_id;
+	u16		cl_id;
+	u16		spcl_id;
+	u16		cl_qzone_id;
+
+	/* valid iff QUEUE_FLG_STATS */
+	u16		stat_id;
+
+	/* valid iff QUEUE_FLG_TPA */
+	u16		tpa_agg_sz;
+	u16		sge_buf_sz;
+	u16		max_sges_pkt;
+
+	/* valid iff QUEUE_FLG_CACHE_ALIGN */
+	u8		cache_line_log;
+
+	u8		sb_cq_index;
+	u32		cid;
+
+	/* desired interrupts per sec. valid iff QUEUE_FLG_HC */
+	u32		hc_rate;
+};
+
+struct bnx2x_txq_init_params {
+	/* cxt*/
+	struct eth_context *cxt;
+
+	/* dma */
+	dma_addr_t	dscr_map;
+
+	u16		flags;
+	u16		fw_sb_id;
+	u8		sb_cq_index;
+	u8		cos;		/* valid iff QUEUE_FLG_COS */
+	u16		stat_id;	/* valid iff QUEUE_FLG_STATS */
+	u16		traffic_type;
+	u32		cid;
+	u16		hc_rate;	/* desired interrupts per sec.*/
+					/* valid iff QUEUE_FLG_HC */
+
+};
+
+struct bnx2x_client_ramrod_params {
+	int *pstate;
+	int state;
+	u16 index;
+	u16 cl_id;
+	u32 cid;
+	u8 poll;
+#define CLIENT_IS_LEADING_RSS		0x02
+	u8 flags;
+};
+
+struct bnx2x_client_init_params {
+	struct rxq_pause_params pause;
+	struct bnx2x_rxq_init_params rxq_params;
+	struct bnx2x_txq_init_params txq_params;
+	struct bnx2x_client_ramrod_params ramrod_params;
+};
+
+struct bnx2x_rss_params {
+	int	mode;
+	u16	cap;
+	u16	result_mask;
+};
+
+struct bnx2x_func_init_params {
+
+	/* rss */
+	struct bnx2x_rss_params *rss;	/* valid iff FUNC_FLG_RSS */
+
+	/* dma */
+	dma_addr_t	fw_stat_map;	/* valid iff FUNC_FLG_STATS */
+	dma_addr_t	spq_map;	/* valid iff FUNC_FLG_SPQ */
+
+	u16		func_flgs;
+	u16		func_id;	/* abs fid */
+	u16		pf_id;
+	u16		spq_prod;	/* valid iff FUNC_FLG_SPQ */
+};
+
 #define for_each_queue(bp, var) \
 			for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++)
 #define for_each_nondefault_queue(bp, var) \
 			for (var = 1; var < BNX2X_NUM_QUEUES(bp); var++)
 
 
+#define WAIT_RAMROD_POLL	0x01
+#define WAIT_RAMROD_COMMON	0x02
+int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
+			     int *state_p, int flags);
+
+/* dmae */
 void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32);
 void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
 		      u32 len32);
+void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
+			       u32 addr, u32 len);
+void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx);
+u32 bnx2x_dmae_opcode_add_comp(u32 opcode, u8 comp_type);
+u32 bnx2x_dmae_opcode_clr_src_reset(u32 opcode);
+u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
+		      bool with_comp, u8 comp_type);
+
 int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
 int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
 int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
-u32 bnx2x_fw_command(struct bnx2x *bp, u32 command);
+u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
 void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
-void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
-			       u32 addr, u32 len);
+
 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);
 void bnx2x_update_coalesce(struct bnx2x *bp);
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
 
 static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 			   int wait)
@@ -957,6 +1332,40 @@
 	return val;
 }
 
+#define BNX2X_ILT_ZALLOC(x, y, size) \
+	do { \
+		x = pci_alloc_consistent(bp->pdev, size, y); \
+		if (x) \
+			memset(x, 0, size); \
+	} while (0)
+
+#define BNX2X_ILT_FREE(x, y, size) \
+	do { \
+		if (x) { \
+			pci_free_consistent(bp->pdev, size, x, y); \
+			x = NULL; \
+			y = 0; \
+		} \
+	} while (0)
+
+#define ILOG2(x)	(ilog2((x)))
+
+#define ILT_NUM_PAGE_ENTRIES	(3072)
+/* In 57710/11 we use whole table since we have 8 func
+ * In 57712 we have only 4 func, but use same size per func, then only half of
+ * the table in use
+ */
+#define ILT_PER_FUNC		(ILT_NUM_PAGE_ENTRIES/8)
+
+#define FUNC_ILT_BASE(func)	(func * ILT_PER_FUNC)
+/*
+ * the phys address is shifted right 12 bits and has an added
+ * 1=valid bit added to the 53rd bit
+ * then since this is a wide register(TM)
+ * we split it into two 32 bit writes
+ */
+#define ONCHIP_ADDR1(x)		((u32)(((u64)x >> 12) & 0xFFFFFFFF))
+#define ONCHIP_ADDR2(x)		((u32)((1 << 20) | ((u64)x >> 44)))
 
 /* load/unload mode */
 #define LOAD_NORMAL			0
@@ -964,18 +1373,44 @@
 #define LOAD_DIAG			2
 #define UNLOAD_NORMAL			0
 #define UNLOAD_CLOSE			1
-#define UNLOAD_RECOVERY                 2
+#define UNLOAD_RECOVERY			2
 
 
 /* DMAE command defines */
-#define DMAE_CMD_SRC_PCI		0
-#define DMAE_CMD_SRC_GRC		DMAE_COMMAND_SRC
+#define DMAE_TIMEOUT			-1
+#define DMAE_PCI_ERROR			-2	/* E2 and onward */
+#define DMAE_NOT_RDY			-3
+#define DMAE_PCI_ERR_FLAG		0x80000000
 
-#define DMAE_CMD_DST_PCI		(1 << DMAE_COMMAND_DST_SHIFT)
-#define DMAE_CMD_DST_GRC		(2 << DMAE_COMMAND_DST_SHIFT)
+#define DMAE_SRC_PCI			0
+#define DMAE_SRC_GRC			1
 
-#define DMAE_CMD_C_DST_PCI		0
-#define DMAE_CMD_C_DST_GRC		(1 << DMAE_COMMAND_C_DST_SHIFT)
+#define DMAE_DST_NONE			0
+#define DMAE_DST_PCI			1
+#define DMAE_DST_GRC			2
+
+#define DMAE_COMP_PCI			0
+#define DMAE_COMP_GRC			1
+
+/* E2 and onward - PCI error handling in the completion */
+
+#define DMAE_COMP_REGULAR		0
+#define DMAE_COM_SET_ERR		1
+
+#define DMAE_CMD_SRC_PCI		(DMAE_SRC_PCI << \
+						DMAE_COMMAND_SRC_SHIFT)
+#define DMAE_CMD_SRC_GRC		(DMAE_SRC_GRC << \
+						DMAE_COMMAND_SRC_SHIFT)
+
+#define DMAE_CMD_DST_PCI		(DMAE_DST_PCI << \
+						DMAE_COMMAND_DST_SHIFT)
+#define DMAE_CMD_DST_GRC		(DMAE_DST_GRC << \
+						DMAE_COMMAND_DST_SHIFT)
+
+#define DMAE_CMD_C_DST_PCI		(DMAE_COMP_PCI << \
+						DMAE_COMMAND_C_DST_SHIFT)
+#define DMAE_CMD_C_DST_GRC		(DMAE_COMP_GRC << \
+						DMAE_COMMAND_C_DST_SHIFT)
 
 #define DMAE_CMD_C_ENABLE		DMAE_COMMAND_C_TYPE_ENABLE
 
@@ -991,10 +1426,20 @@
 #define DMAE_CMD_DST_RESET		DMAE_COMMAND_DST_RESET
 #define DMAE_CMD_E1HVN_SHIFT		DMAE_COMMAND_E1HVN_SHIFT
 
+#define DMAE_SRC_PF			0
+#define DMAE_SRC_VF			1
+
+#define DMAE_DST_PF			0
+#define DMAE_DST_VF			1
+
+#define DMAE_C_SRC			0
+#define DMAE_C_DST			1
+
 #define DMAE_LEN32_RD_MAX		0x80
 #define DMAE_LEN32_WR_MAX(bp)		(CHIP_IS_E1(bp) ? 0x400 : 0x2000)
 
-#define DMAE_COMP_VAL			0xe0d0d0ae
+#define DMAE_COMP_VAL			0x60d0d0ae /* E2 and on - upper bit
+							indicates eror */
 
 #define MAX_DMAE_C_PER_PORT		8
 #define INIT_DMAE_C(bp)			(BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
@@ -1002,7 +1447,6 @@
 #define PMF_DMAE_C(bp)			(BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
 					 E1HVN_MAX)
 
-
 /* PCIE link and speed */
 #define PCICFG_LINK_WIDTH		0x1f00000
 #define PCICFG_LINK_WIDTH_SHIFT		20
@@ -1031,7 +1475,7 @@
 #define MAX_SP_DESC_CNT			(SP_DESC_CNT - 1)
 
 
-#define BNX2X_BTR			1
+#define BNX2X_BTR			4
 #define MAX_SPQ_PENDING			8
 
 
@@ -1148,20 +1592,26 @@
 		  TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT))
 #define MULTI_MASK			0x7f
 
-
-#define DEF_USB_FUNC_OFF		(2 + 2*HC_USTORM_DEF_SB_NUM_INDICES)
-#define DEF_CSB_FUNC_OFF		(2 + 2*HC_CSTORM_DEF_SB_NUM_INDICES)
-#define DEF_XSB_FUNC_OFF		(2 + 2*HC_XSTORM_DEF_SB_NUM_INDICES)
-#define DEF_TSB_FUNC_OFF		(2 + 2*HC_TSTORM_DEF_SB_NUM_INDICES)
-
-#define C_DEF_SB_SP_INDEX		HC_INDEX_DEF_C_ETH_SLOW_PATH
-
 #define BNX2X_SP_DSB_INDEX \
-(&bp->def_status_blk->c_def_status_block.index_values[C_DEF_SB_SP_INDEX])
+		(&bp->def_status_blk->sp_sb.\
+					index_values[HC_SP_INDEX_ETH_DEF_CONS])
 
+#define SET_FLAG(value, mask, flag) \
+	do {\
+		(value) &= ~(mask);\
+		(value) |= ((flag) << (mask##_SHIFT));\
+	} while (0)
+
+#define GET_FLAG(value, mask) \
+	(((value) &= (mask)) >> (mask##_SHIFT))
+
+#define GET_FIELD(value, fname) \
+	(((value) & (fname##_MASK)) >> (fname##_SHIFT))
 
 #define CAM_IS_INVALID(x) \
-(x.target_table_entry.flags == TSTORM_CAM_TARGET_TABLE_ENTRY_ACTION_TYPE)
+	(GET_FLAG(x.flags, \
+	MAC_CONFIGURATION_ENTRY_ACTION_TYPE) == \
+	(T_ETH_MAC_COMMAND_INVALIDATE))
 
 #define CAM_INVALIDATE(x) \
 	(x.target_table_entry.flags = TSTORM_CAM_TARGET_TABLE_ENTRY_ACTION_TYPE)
@@ -1177,21 +1627,29 @@
 #define PXP2_REG_PXP2_INT_STS		PXP2_REG_PXP2_INT_STS_0
 #endif
 
+#ifndef ETH_MAX_RX_CLIENTS_E2
+#define ETH_MAX_RX_CLIENTS_E2		ETH_MAX_RX_CLIENTS_E1H
+#endif
+
 #define BNX2X_VPD_LEN			128
 #define VENDOR_ID_LEN			4
 
+/* Congestion management fairness mode */
+#define CMNG_FNS_NONE		0
+#define CMNG_FNS_MINMAX		1
+
+#define HC_SEG_ACCESS_DEF		0   /*Driver decision 0-3*/
+#define HC_SEG_ACCESS_ATTN		4
+#define HC_SEG_ACCESS_NORM		0   /*Driver decision 0-1*/
+
 #ifdef BNX2X_MAIN
 #define BNX2X_EXTERN
 #else
 #define BNX2X_EXTERN extern
 #endif
 
-BNX2X_EXTERN int load_count[3]; /* 0-common, 1-port0, 2-port1 */
-
-/* MISC_REG_RESET_REG - this is here for the hsi to work don't touch */
+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_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx);
-
 #endif /* bnx2x.h */
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index 02bf710..bc58375 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -15,18 +15,16 @@
  *
  */
 
-
 #include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
 #include <linux/ip.h>
-#include <linux/ipv6.h>
+#include <net/ipv6.h>
 #include <net/ip6_checksum.h>
+#include <linux/firmware.h>
 #include "bnx2x_cmn.h"
 
-#ifdef BCM_VLAN
-#include <linux/if_vlan.h>
-#endif
+#include "bnx2x_init.h"
 
-static int bnx2x_poll(struct napi_struct *napi, int budget);
 
 /* free skb in the packet ring at pos idx
  * return idx of last bd freed
@@ -51,7 +49,7 @@
 	DP(BNX2X_MSG_OFF, "free bd_idx %d\n", bd_idx);
 	tx_start_bd = &fp->tx_desc_ring[bd_idx].start_bd;
 	dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
-			 BD_UNMAP_LEN(tx_start_bd), PCI_DMA_TODEVICE);
+			 BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
 
 	nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
 #ifdef BNX2X_STOP_ON_ERROR
@@ -115,16 +113,10 @@
 
 		pkt_cons = TX_BD(sw_cons);
 
-		/* prefetch(bp->tx_buf_ring[pkt_cons].skb); */
+		DP(NETIF_MSG_TX_DONE, "queue[%d]: hw_cons %u  sw_cons %u "
+				      " pkt_cons %u\n",
+		   fp->index, hw_cons, sw_cons, pkt_cons);
 
-		DP(NETIF_MSG_TX_DONE, "hw_cons %u  sw_cons %u  pkt_cons %u\n",
-		   hw_cons, sw_cons, pkt_cons);
-
-/*		if (NEXT_TX_IDX(sw_cons) != hw_cons) {
-			rmb();
-			prefetch(fp->tx_buf_ring[NEXT_TX_IDX(sw_cons)].skb);
-		}
-*/
 		bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons);
 		sw_cons++;
 	}
@@ -140,7 +132,6 @@
 	 */
 	smp_mb();
 
-	/* TBD need a thresh? */
 	if (unlikely(netif_tx_queue_stopped(txq))) {
 		/* Taking tx_lock() is needed to prevent reenabling the queue
 		 * while it's empty. This could have happen if rx_action() gets
@@ -189,14 +180,16 @@
 
 	/* First mark all used pages */
 	for (i = 0; i < sge_len; i++)
-		SGE_MASK_CLEAR_BIT(fp, RX_SGE(le16_to_cpu(fp_cqe->sgl[i])));
+		SGE_MASK_CLEAR_BIT(fp,
+			RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[i])));
 
 	DP(NETIF_MSG_RX_STATUS, "fp_cqe->sgl[%d] = %d\n",
-	   sge_len - 1, le16_to_cpu(fp_cqe->sgl[sge_len - 1]));
+	   sge_len - 1, le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1]));
 
 	/* Here we assume that the last SGE index is the biggest */
 	prefetch((void *)(fp->sge_mask));
-	bnx2x_update_last_max_sge(fp, le16_to_cpu(fp_cqe->sgl[sge_len - 1]));
+	bnx2x_update_last_max_sge(fp,
+		le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1]));
 
 	last_max = RX_SGE(fp->last_max_sge);
 	last_elem = last_max >> RX_SGE_MASK_ELEM_SHIFT;
@@ -297,7 +290,8 @@
 
 	/* Run through the SGL and compose the fragmented skb */
 	for (i = 0, j = 0; i < pages; i += PAGES_PER_SGE, j++) {
-		u16 sge_idx = RX_SGE(le16_to_cpu(fp_cqe->sgl[j]));
+		u16 sge_idx =
+			RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[j]));
 
 		/* FW gives the indices of the SGE as if the ring is an array
 		   (meaning that "next" element will consume 2 indices) */
@@ -349,16 +343,9 @@
 	if (likely(new_skb)) {
 		/* fix ip xsum and give it to the stack */
 		/* (no need to map the new skb) */
-#ifdef BCM_VLAN
-		int is_vlan_cqe =
-			(le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
-			 PARSING_FLAGS_VLAN);
-		int is_not_hwaccel_vlan_cqe =
-			(is_vlan_cqe && (!(bp->flags & HW_VLAN_RX_FLAG)));
-#endif
 
 		prefetch(skb);
-		prefetch(((char *)(skb)) + 128);
+		prefetch(((char *)(skb)) + L1_CACHE_BYTES);
 
 #ifdef BNX2X_STOP_ON_ERROR
 		if (pad + len > bp->rx_buf_size) {
@@ -380,27 +367,18 @@
 			struct iphdr *iph;
 
 			iph = (struct iphdr *)skb->data;
-#ifdef BCM_VLAN
-			/* If there is no Rx VLAN offloading -
-			   take VLAN tag into an account */
-			if (unlikely(is_not_hwaccel_vlan_cqe))
-				iph = (struct iphdr *)((u8 *)iph + VLAN_HLEN);
-#endif
 			iph->check = 0;
 			iph->check = ip_fast_csum((u8 *)iph, iph->ihl);
 		}
 
 		if (!bnx2x_fill_frag_skb(bp, fp, skb,
 					 &cqe->fast_path_cqe, cqe_idx)) {
-#ifdef BCM_VLAN
-			if ((bp->vlgrp != NULL) && is_vlan_cqe &&
-			    (!is_not_hwaccel_vlan_cqe))
-				vlan_gro_receive(&fp->napi, bp->vlgrp,
+			if ((le16_to_cpu(cqe->fast_path_cqe.
+			    pars_flags.flags) & PARSING_FLAGS_VLAN))
+				__vlan_hwaccel_put_tag(skb,
 						 le16_to_cpu(cqe->fast_path_cqe.
-							     vlan_tag), skb);
-			else
-#endif
-				napi_gro_receive(&fp->napi, skb);
+							     vlan_tag));
+			napi_gro_receive(&fp->napi, skb);
 		} else {
 			DP(NETIF_MSG_RX_STATUS, "Failed to allocate new pages"
 			   " - dropping packet!\n");
@@ -509,8 +487,11 @@
 			len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
 			pad = cqe->fast_path_cqe.placement_offset;
 
-			/* If CQE is marked both TPA_START and TPA_END
-			   it is a non-TPA CQE */
+			/* - If CQE is marked both TPA_START and TPA_END it is
+			 *   a non-TPA CQE.
+			 * - FP CQE will always have either TPA_START or/and
+			 *   TPA_STOP flags set.
+			 */
 			if ((!fp->disable_tpa) &&
 			    (TPA_TYPE(cqe_fp_flags) !=
 					(TPA_TYPE_START | TPA_TYPE_END))) {
@@ -528,9 +509,7 @@
 					bnx2x_set_skb_rxhash(bp, cqe, skb);
 
 					goto next_rx;
-				}
-
-				if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_END) {
+				} else { /* TPA_STOP */
 					DP(NETIF_MSG_RX_STATUS,
 					   "calling tpa_stop on queue %d\n",
 					   queue);
@@ -560,7 +539,7 @@
 					dma_unmap_addr(rx_buf, mapping),
 						   pad + RX_COPY_THRESH,
 						   DMA_FROM_DEVICE);
-			prefetch(((char *)(skb)) + 128);
+			prefetch(((char *)(skb)) + L1_CACHE_BYTES);
 
 			/* is this an error packet? */
 			if (unlikely(cqe_fp_flags & ETH_RX_ERROR_FALGS)) {
@@ -594,7 +573,7 @@
 				skb_reserve(new_skb, pad);
 				skb_put(new_skb, len);
 
-				bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod);
+				bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod);
 
 				skb = new_skb;
 
@@ -613,7 +592,7 @@
 				   "of alloc failure\n");
 				fp->eth_q_stats.rx_skb_alloc_failed++;
 reuse_rx:
-				bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod);
+				bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod);
 				goto next_rx;
 			}
 
@@ -622,7 +601,8 @@
 			/* Set Toeplitz hash for a none-LRO skb */
 			bnx2x_set_skb_rxhash(bp, cqe, skb);
 
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
+
 			if (bp->rx_csum) {
 				if (likely(BNX2X_RX_CSUM_OK(cqe)))
 					skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -633,15 +613,11 @@
 
 		skb_record_rx_queue(skb, fp->index);
 
-#ifdef BCM_VLAN
-		if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) &&
-		    (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
-		     PARSING_FLAGS_VLAN))
-			vlan_gro_receive(&fp->napi, bp->vlgrp,
-				le16_to_cpu(cqe->fast_path_cqe.vlan_tag), skb);
-		else
-#endif
-			napi_gro_receive(&fp->napi, skb);
+		if (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
+		     PARSING_FLAGS_VLAN)
+			__vlan_hwaccel_put_tag(skb,
+				le16_to_cpu(cqe->fast_path_cqe.vlan_tag));
+		napi_gro_receive(&fp->napi, skb);
 
 
 next_rx:
@@ -685,9 +661,10 @@
 		return IRQ_HANDLED;
 	}
 
-	DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB [%d:%d]\n",
-	   fp->index, fp->sb_id);
-	bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0);
+	DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB "
+			 "[fp %d fw_sd %d igusb %d]\n",
+	   fp->index, fp->fw_sb_id, fp->igu_sb_id);
+	bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0);
 
 #ifdef BNX2X_STOP_ON_ERROR
 	if (unlikely(bp->panic))
@@ -697,14 +674,12 @@
 	/* Handle Rx and Tx according to MSI-X vector */
 	prefetch(fp->rx_cons_sb);
 	prefetch(fp->tx_cons_sb);
-	prefetch(&fp->status_blk->u_status_block.status_block_index);
-	prefetch(&fp->status_blk->c_status_block.status_block_index);
+	prefetch(&fp->sb_running_index[SM_RX_ID]);
 	napi_schedule(&bnx2x_fp(bp, fp->index, napi));
 
 	return IRQ_HANDLED;
 }
 
-
 /* HW Lock for shared dual port PHYs */
 void bnx2x_acquire_phy_lock(struct bnx2x *bp)
 {
@@ -738,12 +713,13 @@
 		netdev_info(bp->dev, "NIC Link is Up, ");
 
 		line_speed = bp->link_vars.line_speed;
-		if (IS_E1HMF(bp)) {
+		if (IS_MF(bp)) {
 			u16 vn_max_rate;
 
 			vn_max_rate =
-				((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >>
-				 FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
+				((bp->mf_config[BP_VN(bp)] &
+				  FUNC_MF_CFG_MAX_BW_MASK) >>
+						FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
 			if (vn_max_rate < line_speed)
 				line_speed = vn_max_rate;
 		}
@@ -773,23 +749,73 @@
 	}
 }
 
+/* Returns the number of actually allocated BDs */
+static inline int bnx2x_alloc_rx_bds(struct bnx2x_fastpath *fp,
+				      int rx_ring_size)
+{
+	struct bnx2x *bp = fp->bp;
+	u16 ring_prod, cqe_ring_prod;
+	int i;
+
+	fp->rx_comp_cons = 0;
+	cqe_ring_prod = ring_prod = 0;
+	for (i = 0; i < rx_ring_size; i++) {
+		if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) {
+			BNX2X_ERR("was only able to allocate "
+				  "%d rx skbs on queue[%d]\n", i, fp->index);
+			fp->eth_q_stats.rx_skb_alloc_failed++;
+			break;
+		}
+		ring_prod = NEXT_RX_IDX(ring_prod);
+		cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod);
+		WARN_ON(ring_prod <= i);
+	}
+
+	fp->rx_bd_prod = ring_prod;
+	/* Limit the CQE producer by the CQE ring size */
+	fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT,
+			       cqe_ring_prod);
+	fp->rx_pkt = fp->rx_calls = 0;
+
+	return i;
+}
+
+static inline void bnx2x_alloc_rx_bd_ring(struct bnx2x_fastpath *fp)
+{
+	struct bnx2x *bp = fp->bp;
+	int rx_ring_size = bp->rx_ring_size ? bp->rx_ring_size :
+					      MAX_RX_AVAIL/bp->num_queues;
+
+	rx_ring_size = max_t(int, MIN_RX_AVAIL, rx_ring_size);
+
+	bnx2x_alloc_rx_bds(fp, rx_ring_size);
+
+	/* Warning!
+	 * this will generate an interrupt (to the TSTORM)
+	 * must only be done after chip is initialized
+	 */
+	bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod,
+			     fp->rx_sge_prod);
+}
+
 void bnx2x_init_rx_rings(struct bnx2x *bp)
 {
 	int func = BP_FUNC(bp);
 	int max_agg_queues = CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 :
 					      ETH_MAX_AGGREGATION_QUEUES_E1H;
-	u16 ring_prod, cqe_ring_prod;
+	u16 ring_prod;
 	int i, j;
 
-	bp->rx_buf_size = bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN;
+	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);
 
-	if (bp->flags & TPA_ENABLE_FLAG) {
+	for_each_queue(bp, j) {
+		struct bnx2x_fastpath *fp = &bp->fp[j];
 
-		for_each_queue(bp, j) {
-			struct bnx2x_fastpath *fp = &bp->fp[j];
-
+		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);
@@ -807,6 +833,35 @@
 						   mapping, 0);
 				fp->tpa_state[i] = BNX2X_TPA_STOP;
 			}
+
+			/* "next page" elements initialization */
+			bnx2x_set_next_page_sgl(fp);
+
+			/* set SGEs bit mask */
+			bnx2x_init_sge_ring_bit_mask(fp);
+
+			/* Allocate SGEs and initialize the ring elements */
+			for (i = 0, ring_prod = 0;
+			     i < MAX_RX_SGE_CNT*NUM_RX_SGE_PAGES; i++) {
+
+				if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) {
+					BNX2X_ERR("was only able to allocate "
+						  "%d rx sges\n", i);
+					BNX2X_ERR("disabling TPA for"
+						  " queue[%d]\n", j);
+					/* Cleanup already allocated elements */
+					bnx2x_free_rx_sge_range(bp,
+								fp, ring_prod);
+					bnx2x_free_tpa_pool(bp,
+							    fp, max_agg_queues);
+					fp->disable_tpa = 1;
+					ring_prod = 0;
+					break;
+				}
+				ring_prod = NEXT_SGE_IDX(ring_prod);
+			}
+
+			fp->rx_sge_prod = ring_prod;
 		}
 	}
 
@@ -814,109 +869,29 @@
 		struct bnx2x_fastpath *fp = &bp->fp[j];
 
 		fp->rx_bd_cons = 0;
-		fp->rx_cons_sb = BNX2X_RX_SB_INDEX;
-		fp->rx_bd_cons_sb = BNX2X_RX_SB_BD_INDEX;
 
-		/* "next page" elements initialization */
-		/* SGE ring */
-		for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
-			struct eth_rx_sge *sge;
-
-			sge = &fp->rx_sge_ring[RX_SGE_CNT * i - 2];
-			sge->addr_hi =
-				cpu_to_le32(U64_HI(fp->rx_sge_mapping +
-					BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
-			sge->addr_lo =
-				cpu_to_le32(U64_LO(fp->rx_sge_mapping +
-					BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
-		}
-
-		bnx2x_init_sge_ring_bit_mask(fp);
-
-		/* RX BD ring */
-		for (i = 1; i <= NUM_RX_RINGS; i++) {
-			struct eth_rx_bd *rx_bd;
-
-			rx_bd = &fp->rx_desc_ring[RX_DESC_CNT * i - 2];
-			rx_bd->addr_hi =
-				cpu_to_le32(U64_HI(fp->rx_desc_mapping +
-					    BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
-			rx_bd->addr_lo =
-				cpu_to_le32(U64_LO(fp->rx_desc_mapping +
-					    BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
-		}
+		bnx2x_set_next_page_rx_bd(fp);
 
 		/* CQ ring */
-		for (i = 1; i <= NUM_RCQ_RINGS; i++) {
-			struct eth_rx_cqe_next_page *nextpg;
-
-			nextpg = (struct eth_rx_cqe_next_page *)
-				&fp->rx_comp_ring[RCQ_DESC_CNT * i - 1];
-			nextpg->addr_hi =
-				cpu_to_le32(U64_HI(fp->rx_comp_mapping +
-					   BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
-			nextpg->addr_lo =
-				cpu_to_le32(U64_LO(fp->rx_comp_mapping +
-					   BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
-		}
-
-		/* Allocate SGEs and initialize the ring elements */
-		for (i = 0, ring_prod = 0;
-		     i < MAX_RX_SGE_CNT*NUM_RX_SGE_PAGES; i++) {
-
-			if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) {
-				BNX2X_ERR("was only able to allocate "
-					  "%d rx sges\n", i);
-				BNX2X_ERR("disabling TPA for queue[%d]\n", j);
-				/* Cleanup already allocated elements */
-				bnx2x_free_rx_sge_range(bp, fp, ring_prod);
-				bnx2x_free_tpa_pool(bp, fp, max_agg_queues);
-				fp->disable_tpa = 1;
-				ring_prod = 0;
-				break;
-			}
-			ring_prod = NEXT_SGE_IDX(ring_prod);
-		}
-		fp->rx_sge_prod = ring_prod;
+		bnx2x_set_next_page_rx_cq(fp);
 
 		/* Allocate BDs and initialize BD ring */
-		fp->rx_comp_cons = 0;
-		cqe_ring_prod = ring_prod = 0;
-		for (i = 0; i < bp->rx_ring_size; i++) {
-			if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) {
-				BNX2X_ERR("was only able to allocate "
-					  "%d rx skbs on queue[%d]\n", i, j);
-				fp->eth_q_stats.rx_skb_alloc_failed++;
-				break;
-			}
-			ring_prod = NEXT_RX_IDX(ring_prod);
-			cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod);
-			WARN_ON(ring_prod <= i);
-		}
+		bnx2x_alloc_rx_bd_ring(fp);
 
-		fp->rx_bd_prod = ring_prod;
-		/* must not have more available CQEs than BDs */
-		fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT,
-					 cqe_ring_prod);
-		fp->rx_pkt = fp->rx_calls = 0;
-
-		/* Warning!
-		 * this will generate an interrupt (to the TSTORM)
-		 * must only be done after chip is initialized
-		 */
-		bnx2x_update_rx_prod(bp, fp, ring_prod, fp->rx_comp_prod,
-				     fp->rx_sge_prod);
 		if (j != 0)
 			continue;
 
-		REG_WR(bp, BAR_USTRORM_INTMEM +
-		       USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func),
-		       U64_LO(fp->rx_comp_mapping));
-		REG_WR(bp, BAR_USTRORM_INTMEM +
-		       USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func) + 4,
-		       U64_HI(fp->rx_comp_mapping));
+		if (!CHIP_IS_E2(bp)) {
+			REG_WR(bp, BAR_USTRORM_INTMEM +
+			       USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func),
+			       U64_LO(fp->rx_comp_mapping));
+			REG_WR(bp, BAR_USTRORM_INTMEM +
+			       USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func) + 4,
+			       U64_HI(fp->rx_comp_mapping));
+		}
 	}
 }
+
 static void bnx2x_free_tx_skbs(struct bnx2x *bp)
 {
 	int i;
@@ -989,55 +964,49 @@
 	}
 }
 
-void bnx2x_free_irq(struct bnx2x *bp, bool disable_only)
+void bnx2x_free_irq(struct bnx2x *bp)
 {
-	if (bp->flags & USING_MSIX_FLAG) {
-		if (!disable_only)
-			bnx2x_free_msix_irqs(bp);
-		pci_disable_msix(bp->pdev);
-		bp->flags &= ~USING_MSIX_FLAG;
-
-	} else if (bp->flags & USING_MSI_FLAG) {
-		if (!disable_only)
-			free_irq(bp->pdev->irq, bp->dev);
-		pci_disable_msi(bp->pdev);
-		bp->flags &= ~USING_MSI_FLAG;
-
-	} else if (!disable_only)
+	if (bp->flags & USING_MSIX_FLAG)
+		bnx2x_free_msix_irqs(bp);
+	else if (bp->flags & USING_MSI_FLAG)
+		free_irq(bp->pdev->irq, bp->dev);
+	else
 		free_irq(bp->pdev->irq, bp->dev);
 }
 
-static int bnx2x_enable_msix(struct bnx2x *bp)
+int bnx2x_enable_msix(struct bnx2x *bp)
 {
-	int i, rc, offset = 1;
-	int igu_vec = 0;
+	int msix_vec = 0, i, rc, req_cnt;
 
-	bp->msix_table[0].entry = igu_vec;
-	DP(NETIF_MSG_IFUP, "msix_table[0].entry = %d (slowpath)\n", igu_vec);
+	bp->msix_table[msix_vec].entry = msix_vec;
+	DP(NETIF_MSG_IFUP, "msix_table[0].entry = %d (slowpath)\n",
+	   bp->msix_table[0].entry);
+	msix_vec++;
 
 #ifdef BCM_CNIC
-	igu_vec = BP_L_ID(bp) + offset;
-	bp->msix_table[1].entry = igu_vec;
-	DP(NETIF_MSG_IFUP, "msix_table[1].entry = %d (CNIC)\n", igu_vec);
-	offset++;
+	bp->msix_table[msix_vec].entry = msix_vec;
+	DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d (CNIC)\n",
+	   bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry);
+	msix_vec++;
 #endif
 	for_each_queue(bp, i) {
-		igu_vec = BP_L_ID(bp) + offset + i;
-		bp->msix_table[i + offset].entry = igu_vec;
+		bp->msix_table[msix_vec].entry = msix_vec;
 		DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d "
-		   "(fastpath #%u)\n", i + offset, igu_vec, i);
+		   "(fastpath #%u)\n", msix_vec, msix_vec, i);
+		msix_vec++;
 	}
 
-	rc = pci_enable_msix(bp->pdev, &bp->msix_table[0],
-			     BNX2X_NUM_QUEUES(bp) + offset);
+	req_cnt = BNX2X_NUM_QUEUES(bp) + CNIC_CONTEXT_USE + 1;
+
+	rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt);
 
 	/*
 	 * reconfigure number of tx/rx queues according to available
 	 * MSI-X vectors
 	 */
 	if (rc >= BNX2X_MIN_MSIX_VEC_CNT) {
-		/* vectors available for FP */
-		int fp_vec = rc - BNX2X_MSIX_VEC_FP_START;
+		/* how less vectors we will have? */
+		int diff = req_cnt - rc;
 
 		DP(NETIF_MSG_IFUP,
 		   "Trying to use less MSI-X vectors: %d\n", rc);
@@ -1049,12 +1018,17 @@
 			   "MSI-X is not attainable  rc %d\n", rc);
 			return rc;
 		}
-
-		bp->num_queues = min(bp->num_queues, fp_vec);
+		/*
+		 * decrease number of queues by number of unallocated entries
+		 */
+		bp->num_queues -= diff;
 
 		DP(NETIF_MSG_IFUP, "New queue configuration set: %d\n",
 				  bp->num_queues);
 	} else if (rc) {
+		/* fall to INTx if not enough memory */
+		if (rc == -ENOMEM)
+			bp->flags |= DISABLE_MSI_FLAG;
 		DP(NETIF_MSG_IFUP, "MSI-X is not attainable  rc %d\n", rc);
 		return rc;
 	}
@@ -1083,7 +1057,7 @@
 		snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
 			 bp->dev->name, i);
 
-		rc = request_irq(bp->msix_table[i + offset].vector,
+		rc = request_irq(bp->msix_table[offset].vector,
 				 bnx2x_msix_fp_int, 0, fp->name, fp);
 		if (rc) {
 			BNX2X_ERR("request fp #%d irq failed  rc %d\n", i, rc);
@@ -1091,10 +1065,12 @@
 			return -EBUSY;
 		}
 
+		offset++;
 		fp->state = BNX2X_FP_STATE_IRQ;
 	}
 
 	i = BNX2X_NUM_QUEUES(bp);
+	offset = 1 + CNIC_CONTEXT_USE;
 	netdev_info(bp->dev, "using MSI-X  IRQs: sp %d  fp[%d] %d"
 	       " ... fp[%d] %d\n",
 	       bp->msix_table[0].vector,
@@ -1104,7 +1080,7 @@
 	return 0;
 }
 
-static int bnx2x_enable_msi(struct bnx2x *bp)
+int bnx2x_enable_msi(struct bnx2x *bp)
 {
 	int rc;
 
@@ -1175,35 +1151,29 @@
 	bnx2x_napi_disable(bp);
 	netif_tx_disable(bp->dev);
 }
-static int bnx2x_set_num_queues(struct bnx2x *bp)
+
+void bnx2x_set_num_queues(struct bnx2x *bp)
 {
-	int rc = 0;
-
-	switch (bp->int_mode) {
-	case INT_MODE_INTx:
-	case INT_MODE_MSI:
+	switch (bp->multi_mode) {
+	case ETH_RSS_MODE_DISABLED:
 		bp->num_queues = 1;
-		DP(NETIF_MSG_IFUP, "set number of queues to 1\n");
 		break;
+	case ETH_RSS_MODE_REGULAR:
+		bp->num_queues = bnx2x_calc_num_queues(bp);
+		break;
+
 	default:
-		/* Set number of queues according to bp->multi_mode value */
-		bnx2x_set_num_queues_msix(bp);
-
-		DP(NETIF_MSG_IFUP, "set number of queues to %d\n",
-		   bp->num_queues);
-
-		/* if we can't use MSI-X we only need one fp,
-		 * so try to enable MSI-X with the requested number of fp's
-		 * and fallback to MSI or legacy INTx with one fp
-		 */
-		rc = bnx2x_enable_msix(bp);
-		if (rc)
-			/* failed to enable MSI-X */
-			bp->num_queues = 1;
+		bp->num_queues = 1;
 		break;
 	}
-	bp->dev->real_num_tx_queues = bp->num_queues;
-	return rc;
+}
+
+static void bnx2x_release_firmware(struct bnx2x *bp)
+{
+	kfree(bp->init_ops_offsets);
+	kfree(bp->init_ops);
+	kfree(bp->init_data);
+	release_firmware(bp->firmware);
 }
 
 /* must be called with rtnl_lock */
@@ -1212,6 +1182,13 @@
 	u32 load_code;
 	int i, rc;
 
+	/* Set init arrays */
+	rc = bnx2x_init_firmware(bp);
+	if (rc) {
+		BNX2X_ERR("Error loading firmware\n");
+		return rc;
+	}
+
 #ifdef BNX2X_STOP_ON_ERROR
 	if (unlikely(bp->panic))
 		return -EPERM;
@@ -1219,83 +1196,64 @@
 
 	bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
 
-	rc = bnx2x_set_num_queues(bp);
+	/* must be called before memory allocation and HW init */
+	bnx2x_ilt_set_info(bp);
 
-	if (bnx2x_alloc_mem(bp)) {
-		bnx2x_free_irq(bp, true);
+	if (bnx2x_alloc_mem(bp))
 		return -ENOMEM;
+
+	netif_set_real_num_tx_queues(bp->dev, bp->num_queues);
+	rc = netif_set_real_num_rx_queues(bp->dev, bp->num_queues);
+	if (rc) {
+		BNX2X_ERR("Unable to update real_num_rx_queues\n");
+		goto load_error0;
 	}
 
 	for_each_queue(bp, i)
 		bnx2x_fp(bp, i, disable_tpa) =
 					((bp->flags & TPA_ENABLE_FLAG) == 0);
 
-	for_each_queue(bp, i)
-		netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
-			       bnx2x_poll, 128);
-
 	bnx2x_napi_enable(bp);
 
-	if (bp->flags & USING_MSIX_FLAG) {
-		rc = bnx2x_req_msix_irqs(bp);
-		if (rc) {
-			bnx2x_free_irq(bp, true);
-			goto load_error1;
-		}
-	} else {
-		/* Fall to INTx if failed to enable MSI-X due to lack of
-		   memory (in bnx2x_set_num_queues()) */
-		if ((rc != -ENOMEM) && (bp->int_mode != INT_MODE_INTx))
-			bnx2x_enable_msi(bp);
-		bnx2x_ack_int(bp);
-		rc = bnx2x_req_irq(bp);
-		if (rc) {
-			BNX2X_ERR("IRQ request failed  rc %d, aborting\n", rc);
-			bnx2x_free_irq(bp, true);
-			goto load_error1;
-		}
-		if (bp->flags & USING_MSI_FLAG) {
-			bp->dev->irq = bp->pdev->irq;
-			netdev_info(bp->dev, "using MSI  IRQ %d\n",
-				    bp->pdev->irq);
-		}
-	}
-
 	/* Send LOAD_REQUEST command to MCP
 	   Returns the type of LOAD command:
 	   if it is the first port to be initialized
 	   common blocks should be initialized, otherwise - not
 	*/
 	if (!BP_NOMCP(bp)) {
-		load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ);
+		load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
 		if (!load_code) {
 			BNX2X_ERR("MCP response failure, aborting\n");
 			rc = -EBUSY;
-			goto load_error2;
+			goto load_error1;
 		}
 		if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) {
 			rc = -EBUSY; /* other port in diagnostic mode */
-			goto load_error2;
+			goto load_error1;
 		}
 
 	} else {
+		int path = BP_PATH(bp);
 		int port = BP_PORT(bp);
 
-		DP(NETIF_MSG_IFUP, "NO MCP - load counts      %d, %d, %d\n",
-		   load_count[0], load_count[1], load_count[2]);
-		load_count[0]++;
-		load_count[1 + port]++;
-		DP(NETIF_MSG_IFUP, "NO MCP - new load counts  %d, %d, %d\n",
-		   load_count[0], load_count[1], load_count[2]);
-		if (load_count[0] == 1)
+		DP(NETIF_MSG_IFUP, "NO MCP - load counts[%d]      %d, %d, %d\n",
+		   path, load_count[path][0], load_count[path][1],
+		   load_count[path][2]);
+		load_count[path][0]++;
+		load_count[path][1 + port]++;
+		DP(NETIF_MSG_IFUP, "NO MCP - new load counts[%d]  %d, %d, %d\n",
+		   path, load_count[path][0], load_count[path][1],
+		   load_count[path][2]);
+		if (load_count[path][0] == 1)
 			load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
-		else if (load_count[1 + port] == 1)
+		else if (load_count[path][1 + port] == 1)
 			load_code = FW_MSG_CODE_DRV_LOAD_PORT;
 		else
 			load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION;
 	}
 
 	if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
+	    (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
 	    (load_code == FW_MSG_CODE_DRV_LOAD_PORT))
 		bp->port.pmf = 1;
 	else
@@ -1306,16 +1264,22 @@
 	rc = bnx2x_init_hw(bp, load_code);
 	if (rc) {
 		BNX2X_ERR("HW init failed, aborting\n");
-		bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
-		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP);
-		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+		bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
+		goto load_error2;
+	}
+
+	/* Connect to IRQs */
+	rc = bnx2x_setup_irqs(bp);
+	if (rc) {
+		bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
 		goto load_error2;
 	}
 
 	/* Setup NIC internals and enable interrupts */
 	bnx2x_nic_init(bp, load_code);
 
-	if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) &&
+	if (((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
+	    (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP)) &&
 	    (bp->common.shmem2_base))
 		SHMEM2_WR(bp, dcc_support,
 			  (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
@@ -1323,7 +1287,7 @@
 
 	/* Send LOAD_DONE command to MCP */
 	if (!BP_NOMCP(bp)) {
-		load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
+		load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
 		if (!load_code) {
 			BNX2X_ERR("MCP response failure, aborting\n");
 			rc = -EBUSY;
@@ -1333,7 +1297,18 @@
 
 	bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
 
-	rc = bnx2x_setup_leading(bp);
+	rc = bnx2x_func_start(bp);
+	if (rc) {
+		BNX2X_ERR("Function start failed!\n");
+#ifndef BNX2X_STOP_ON_ERROR
+		goto load_error3;
+#else
+		bp->panic = 1;
+		return -EBUSY;
+#endif
+	}
+
+	rc = bnx2x_setup_client(bp, &bp->fp[0], 1 /* Leading */);
 	if (rc) {
 		BNX2X_ERR("Setup leading failed!\n");
 #ifndef BNX2X_STOP_ON_ERROR
@@ -1344,62 +1319,47 @@
 #endif
 	}
 
-	if (CHIP_IS_E1H(bp))
-		if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) {
-			DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n");
-			bp->flags |= MF_FUNC_DIS;
-		}
+	if (!CHIP_IS_E1(bp) &&
+	    (bp->mf_config[BP_VN(bp)] & FUNC_MF_CFG_FUNC_DISABLED)) {
+		DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n");
+		bp->flags |= MF_FUNC_DIS;
+	}
 
-	if (bp->state == BNX2X_STATE_OPEN) {
 #ifdef BCM_CNIC
-		/* Enable Timer scan */
-		REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1);
+	/* Enable Timer scan */
+	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1);
 #endif
-		for_each_nondefault_queue(bp, i) {
-			rc = bnx2x_setup_multi(bp, i);
-			if (rc)
+
+	for_each_nondefault_queue(bp, i) {
+		rc = bnx2x_setup_client(bp, &bp->fp[i], 0);
+		if (rc)
 #ifdef BCM_CNIC
-				goto load_error4;
+			goto load_error4;
 #else
-				goto load_error3;
-#endif
-		}
-
-		if (CHIP_IS_E1(bp))
-			bnx2x_set_eth_mac_addr_e1(bp, 1);
-		else
-			bnx2x_set_eth_mac_addr_e1h(bp, 1);
-#ifdef BCM_CNIC
-		/* Set iSCSI L2 MAC */
-		mutex_lock(&bp->cnic_mutex);
-		if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD) {
-			bnx2x_set_iscsi_eth_mac_addr(bp, 1);
-			bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET;
-			bnx2x_init_sb(bp, bp->cnic_sb, bp->cnic_sb_mapping,
-				      CNIC_SB_ID(bp));
-		}
-		mutex_unlock(&bp->cnic_mutex);
+			goto load_error3;
 #endif
 	}
 
+	/* Now when Clients are configured we are ready to work */
+	bp->state = BNX2X_STATE_OPEN;
+
+	bnx2x_set_eth_mac(bp, 1);
+
 	if (bp->port.pmf)
 		bnx2x_initial_phy_init(bp, load_mode);
 
 	/* Start fast path */
 	switch (load_mode) {
 	case LOAD_NORMAL:
-		if (bp->state == BNX2X_STATE_OPEN) {
-			/* Tx queue should be only reenabled */
-			netif_tx_wake_all_queues(bp->dev);
-		}
+		/* 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);
-		if (bp->state != BNX2X_STATE_OPEN)
-			netif_tx_disable(bp->dev);
+		smp_mb__after_clear_bit();
 		/* Initialize the receive filter. */
 		bnx2x_set_rx_mode(bp->dev);
 		break;
@@ -1427,6 +1387,8 @@
 #endif
 	bnx2x_inc_load_cnt(bp);
 
+	bnx2x_release_firmware(bp);
+
 	return 0;
 
 #ifdef BCM_CNIC
@@ -1436,24 +1398,28 @@
 #endif
 load_error3:
 	bnx2x_int_disable_sync(bp, 1);
-	if (!BP_NOMCP(bp)) {
-		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP);
-		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
-	}
-	bp->port.pmf = 0;
+
 	/* Free SKBs, SGEs, TPA pool and driver internals */
 	bnx2x_free_skbs(bp);
 	for_each_queue(bp, i)
 		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
-load_error2:
+
 	/* Release IRQs */
-	bnx2x_free_irq(bp, false);
+	bnx2x_free_irq(bp);
+load_error2:
+	if (!BP_NOMCP(bp)) {
+		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0);
+		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+	}
+
+	bp->port.pmf = 0;
 load_error1:
 	bnx2x_napi_disable(bp);
-	for_each_queue(bp, i)
-		netif_napi_del(&bnx2x_fp(bp, i, napi));
+load_error0:
 	bnx2x_free_mem(bp);
 
+	bnx2x_release_firmware(bp);
+
 	return rc;
 }
 
@@ -1481,21 +1447,26 @@
 	bp->rx_mode = BNX2X_RX_MODE_NONE;
 	bnx2x_set_storm_rx_mode(bp);
 
-	/* Disable HW interrupts, NAPI and Tx */
-	bnx2x_netif_stop(bp, 1);
-	netif_carrier_off(bp->dev);
+	/* Stop Tx */
+	bnx2x_tx_disable(bp);
 
 	del_timer_sync(&bp->timer);
-	SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb,
-		 (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
-	bnx2x_stats_handle(bp, STATS_EVENT_STOP);
 
-	/* Release IRQs */
-	bnx2x_free_irq(bp, false);
+	SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb,
+		 (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
+
+	bnx2x_stats_handle(bp, STATS_EVENT_STOP);
 
 	/* Cleanup the chip if needed */
 	if (unload_mode != UNLOAD_RECOVERY)
 		bnx2x_chip_cleanup(bp, unload_mode);
+	else {
+		/* Disable HW interrupts, NAPI and Tx */
+		bnx2x_netif_stop(bp, 1);
+
+		/* Release IRQs */
+		bnx2x_free_irq(bp);
+	}
 
 	bp->port.pmf = 0;
 
@@ -1503,8 +1474,7 @@
 	bnx2x_free_skbs(bp);
 	for_each_queue(bp, i)
 		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
-	for_each_queue(bp, i)
-		netif_napi_del(&bnx2x_fp(bp, i, napi));
+
 	bnx2x_free_mem(bp);
 
 	bp->state = BNX2X_STATE_CLOSED;
@@ -1522,10 +1492,17 @@
 
 	return 0;
 }
+
 int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
 {
 	u16 pmcsr;
 
+	/* If there is no power capability, silently succeed */
+	if (!bp->pm_cap) {
+		DP(NETIF_MSG_HW, "No power capability. Breaking.\n");
+		return 0;
+	}
+
 	pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
 
 	switch (state) {
@@ -1568,13 +1545,10 @@
 	return 0;
 }
 
-
-
 /*
  * net_device service functions
  */
-
-static int bnx2x_poll(struct napi_struct *napi, int budget)
+int bnx2x_poll(struct napi_struct *napi, int budget)
 {
 	int work_done = 0;
 	struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath,
@@ -1603,27 +1577,28 @@
 		/* Fall out from the NAPI loop if needed */
 		if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
 			bnx2x_update_fpsb_idx(fp);
-		/* bnx2x_has_rx_work() reads the status block, thus we need
-		 * to ensure that status block indices have been actually read
-		 * (bnx2x_update_fpsb_idx) prior to this check
-		 * (bnx2x_has_rx_work) so that we won't write the "newer"
-		 * value of the status block to IGU (if there was a DMA right
-		 * after bnx2x_has_rx_work and if there is no rmb, the memory
-		 * reading (bnx2x_update_fpsb_idx) may be postponed to right
-		 * before bnx2x_ack_sb). In this case there will never be
-		 * another interrupt until there is another update of the
-		 * status block, while there is still unhandled work.
-		 */
+			/* bnx2x_has_rx_work() reads the status block,
+			 * thus we need to ensure that status block indices
+			 * have been actually read (bnx2x_update_fpsb_idx)
+			 * prior to this check (bnx2x_has_rx_work) so that
+			 * we won't write the "newer" value of the status block
+			 * to IGU (if there was a DMA right after
+			 * bnx2x_has_rx_work and if there is no rmb, the memory
+			 * reading (bnx2x_update_fpsb_idx) may be postponed
+			 * to right before bnx2x_ack_sb). In this case there
+			 * will never be another interrupt until there is
+			 * another update of the status block, while there
+			 * is still unhandled work.
+			 */
 			rmb();
 
 			if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
 				napi_complete(napi);
 				/* Re-enable interrupts */
-				bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID,
-					     le16_to_cpu(fp->fp_c_idx),
-					     IGU_INT_NOP, 1);
-				bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID,
-					     le16_to_cpu(fp->fp_u_idx),
+				DP(NETIF_MSG_HW,
+				   "Update index to %d\n", fp->fp_hc_idx);
+				bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID,
+					     le16_to_cpu(fp->fp_hc_idx),
 					     IGU_INT_ENABLE, 1);
 				break;
 			}
@@ -1633,7 +1608,6 @@
 	return work_done;
 }
 
-
 /* we split the first BD into headers and data BDs
  * to ease the pain of our fellow microcode engineers
  * we use one mapping for both BDs
@@ -1807,6 +1781,122 @@
 }
 #endif
 
+static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb,
+				     struct eth_tx_parse_bd_e2 *pbd,
+				     u32 xmit_type)
+{
+	pbd->parsing_data |= cpu_to_le16(skb_shinfo(skb)->gso_size) <<
+		ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT;
+	if ((xmit_type & XMIT_GSO_V6) &&
+	    (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
+		pbd->parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
+}
+
+/**
+ * Update PBD in GSO case.
+ *
+ * @param skb
+ * @param tx_start_bd
+ * @param pbd
+ * @param xmit_type
+ */
+static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
+				     struct eth_tx_parse_bd_e1x *pbd,
+				     u32 xmit_type)
+{
+	pbd->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+	pbd->tcp_send_seq = swab32(tcp_hdr(skb)->seq);
+	pbd->tcp_flags = pbd_tcp_flags(skb);
+
+	if (xmit_type & XMIT_GSO_V4) {
+		pbd->ip_id = swab16(ip_hdr(skb)->id);
+		pbd->tcp_pseudo_csum =
+			swab16(~csum_tcpudp_magic(ip_hdr(skb)->saddr,
+						  ip_hdr(skb)->daddr,
+						  0, IPPROTO_TCP, 0));
+
+	} else
+		pbd->tcp_pseudo_csum =
+			swab16(~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+						&ipv6_hdr(skb)->daddr,
+						0, IPPROTO_TCP, 0));
+
+	pbd->global_data |= ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN;
+}
+
+/**
+ *
+ * @param skb
+ * @param tx_start_bd
+ * @param pbd_e2
+ * @param xmit_type
+ *
+ * @return header len
+ */
+static inline  u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
+	struct eth_tx_parse_bd_e2 *pbd,
+	u32 xmit_type)
+{
+	pbd->parsing_data |= cpu_to_le16(tcp_hdrlen(skb)/4) <<
+		ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT;
+
+	pbd->parsing_data |= cpu_to_le16(((unsigned char *)tcp_hdr(skb) -
+					  skb->data) / 2) <<
+		ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT;
+
+	return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
+}
+
+/**
+ *
+ * @param skb
+ * @param tx_start_bd
+ * @param pbd
+ * @param xmit_type
+ *
+ * @return Header length
+ */
+static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
+	struct eth_tx_parse_bd_e1x *pbd,
+	u32 xmit_type)
+{
+	u8 hlen = (skb_network_header(skb) - skb->data) / 2;
+
+	/* for now NS flag is not used in Linux */
+	pbd->global_data =
+		(hlen | ((skb->protocol == cpu_to_be16(ETH_P_8021Q)) <<
+			 ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT));
+
+	pbd->ip_hlen_w = (skb_transport_header(skb) -
+			skb_network_header(skb)) / 2;
+
+	hlen += pbd->ip_hlen_w + tcp_hdrlen(skb) / 2;
+
+	pbd->total_hlen_w = cpu_to_le16(hlen);
+	hlen = hlen*2;
+
+	if (xmit_type & XMIT_CSUM_TCP) {
+		pbd->tcp_pseudo_csum = swab16(tcp_hdr(skb)->check);
+
+	} else {
+		s8 fix = SKB_CS_OFF(skb); /* signed! */
+
+		DP(NETIF_MSG_TX_QUEUED,
+		   "hlen %d  fix %d  csum before fix %x\n",
+		   le16_to_cpu(pbd->total_hlen_w), fix, SKB_CS(skb));
+
+		/* HW bug: fixup the CSUM */
+		pbd->tcp_pseudo_csum =
+			bnx2x_csum_fix(skb_transport_header(skb),
+				       SKB_CS(skb), fix);
+
+		DP(NETIF_MSG_TX_QUEUED, "csum after fix %x\n",
+		   pbd->tcp_pseudo_csum);
+	}
+
+	return hlen;
+}
+
 /* called with netif_tx_lock
  * bnx2x_tx_int() runs without netif_tx_lock unless it needs to call
  * netif_wake_queue()
@@ -1819,7 +1909,8 @@
 	struct sw_tx_bd *tx_buf;
 	struct eth_tx_start_bd *tx_start_bd;
 	struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
-	struct eth_tx_parse_bd *pbd = NULL;
+	struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
+	struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
 	u16 pkt_prod, bd_prod;
 	int nbd, fp_index;
 	dma_addr_t mapping;
@@ -1847,9 +1938,9 @@
 		return NETDEV_TX_BUSY;
 	}
 
-	DP(NETIF_MSG_TX_QUEUED, "SKB: summed %x  protocol %x  protocol(%x,%x)"
-	   "  gso type %x  xmit_type %x\n",
-	   skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
+	DP(NETIF_MSG_TX_QUEUED, "queue[%d]: SKB: summed %x  protocol %x  "
+				"protocol(%x,%x) gso type %x  xmit_type %x\n",
+	   fp_index, skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
 	   ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type);
 
 	eth = (struct ethhdr *)skb->data;
@@ -1895,10 +1986,11 @@
 	tx_start_bd = &fp->tx_desc_ring[bd_prod].start_bd;
 
 	tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
-	tx_start_bd->general_data =  (mac_type <<
-					ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT);
+	SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_ETH_ADDR_TYPE,
+		 mac_type);
+
 	/* header nbd */
-	tx_start_bd->general_data |= (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT);
+	SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_HDR_NBDS, 1);
 
 	/* remember the first BD of the packet */
 	tx_buf->first_bd = fp->tx_bd_prod;
@@ -1909,37 +2001,18 @@
 	   "sending pkt %u @%p  next_idx %u  bd %u @%p\n",
 	   pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_start_bd);
 
-#ifdef BCM_VLAN
-	if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) &&
-	    (bp->flags & HW_VLAN_TX_FLAG)) {
-		tx_start_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb));
-		tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG;
+	if (vlan_tx_tag_present(skb)) {
+		tx_start_bd->vlan_or_ethertype =
+		    cpu_to_le16(vlan_tx_tag_get(skb));
+		tx_start_bd->bd_flags.as_bitfield |=
+		    (X_ETH_OUTBAND_VLAN << ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT);
 	} else
-#endif
-		tx_start_bd->vlan = cpu_to_le16(pkt_prod);
+		tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
 
 	/* turn on parsing and get a BD */
 	bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
-	pbd = &fp->tx_desc_ring[bd_prod].parse_bd;
-
-	memset(pbd, 0, sizeof(struct eth_tx_parse_bd));
 
 	if (xmit_type & XMIT_CSUM) {
-		hlen = (skb_network_header(skb) - skb->data) / 2;
-
-		/* for now NS flag is not used in Linux */
-		pbd->global_data =
-			(hlen | ((skb->protocol == cpu_to_be16(ETH_P_8021Q)) <<
-				 ETH_TX_PARSE_BD_LLC_SNAP_EN_SHIFT));
-
-		pbd->ip_hlen = (skb_transport_header(skb) -
-				skb_network_header(skb)) / 2;
-
-		hlen += pbd->ip_hlen + tcp_hdrlen(skb) / 2;
-
-		pbd->total_hlen = cpu_to_le16(hlen);
-		hlen = hlen*2;
-
 		tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
 
 		if (xmit_type & XMIT_CSUM_V4)
@@ -1949,31 +2022,32 @@
 			tx_start_bd->bd_flags.as_bitfield |=
 						ETH_TX_BD_FLAGS_IPV6;
 
-		if (xmit_type & XMIT_CSUM_TCP) {
-			pbd->tcp_pseudo_csum = swab16(tcp_hdr(skb)->check);
-
-		} else {
-			s8 fix = SKB_CS_OFF(skb); /* signed! */
-
-			pbd->global_data |= ETH_TX_PARSE_BD_UDP_CS_FLG;
-
-			DP(NETIF_MSG_TX_QUEUED,
-			   "hlen %d  fix %d  csum before fix %x\n",
-			   le16_to_cpu(pbd->total_hlen), fix, SKB_CS(skb));
-
-			/* HW bug: fixup the CSUM */
-			pbd->tcp_pseudo_csum =
-				bnx2x_csum_fix(skb_transport_header(skb),
-					       SKB_CS(skb), fix);
-
-			DP(NETIF_MSG_TX_QUEUED, "csum after fix %x\n",
-			   pbd->tcp_pseudo_csum);
-		}
+		if (!(xmit_type & XMIT_CSUM_TCP))
+			tx_start_bd->bd_flags.as_bitfield |=
+						ETH_TX_BD_FLAGS_IS_UDP;
 	}
 
+	if (CHIP_IS_E2(bp)) {
+		pbd_e2 = &fp->tx_desc_ring[bd_prod].parse_bd_e2;
+		memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
+		/* Set PBD in checksum offload case */
+		if (xmit_type & XMIT_CSUM)
+			hlen = bnx2x_set_pbd_csum_e2(bp,
+						     skb, pbd_e2, xmit_type);
+	} else {
+		pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x;
+		memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
+		/* Set PBD in checksum offload case */
+		if (xmit_type & XMIT_CSUM)
+			hlen = bnx2x_set_pbd_csum(bp, skb, pbd_e1x, xmit_type);
+
+	}
+
+	/* Map skb linear data for DMA */
 	mapping = dma_map_single(&bp->pdev->dev, skb->data,
 				 skb_headlen(skb), DMA_TO_DEVICE);
 
+	/* Setup the data pointer of the first BD of the packet */
 	tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
 	tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
 	nbd = skb_shinfo(skb)->nr_frags + 2; /* start_bd + pbd + frags */
@@ -1985,7 +2059,8 @@
 	   "  nbytes %d  flags %x  vlan %x\n",
 	   tx_start_bd, tx_start_bd->addr_hi, tx_start_bd->addr_lo,
 	   le16_to_cpu(tx_start_bd->nbd), le16_to_cpu(tx_start_bd->nbytes),
-	   tx_start_bd->bd_flags.as_bitfield, le16_to_cpu(tx_start_bd->vlan));
+	   tx_start_bd->bd_flags.as_bitfield,
+	   le16_to_cpu(tx_start_bd->vlan_or_ethertype));
 
 	if (xmit_type & XMIT_GSO) {
 
@@ -1999,28 +2074,14 @@
 		if (unlikely(skb_headlen(skb) > hlen))
 			bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd,
 						 hlen, bd_prod, ++nbd);
-
-		pbd->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
-		pbd->tcp_send_seq = swab32(tcp_hdr(skb)->seq);
-		pbd->tcp_flags = pbd_tcp_flags(skb);
-
-		if (xmit_type & XMIT_GSO_V4) {
-			pbd->ip_id = swab16(ip_hdr(skb)->id);
-			pbd->tcp_pseudo_csum =
-				swab16(~csum_tcpudp_magic(ip_hdr(skb)->saddr,
-							  ip_hdr(skb)->daddr,
-							  0, IPPROTO_TCP, 0));
-
-		} else
-			pbd->tcp_pseudo_csum =
-				swab16(~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
-							&ipv6_hdr(skb)->daddr,
-							0, IPPROTO_TCP, 0));
-
-		pbd->global_data |= ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN;
+		if (CHIP_IS_E2(bp))
+			bnx2x_set_pbd_gso_e2(skb, pbd_e2, xmit_type);
+		else
+			bnx2x_set_pbd_gso(skb, pbd_e1x, xmit_type);
 	}
 	tx_data_bd = (struct eth_tx_bd *)tx_start_bd;
 
+	/* Handle fragmented skb */
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
@@ -2057,14 +2118,21 @@
 	if (total_pkt_bd != NULL)
 		total_pkt_bd->total_pkt_bytes = pkt_size;
 
-	if (pbd)
+	if (pbd_e1x)
 		DP(NETIF_MSG_TX_QUEUED,
-		   "PBD @%p  ip_data %x  ip_hlen %u  ip_id %u  lso_mss %u"
+		   "PBD (E1X) @%p  ip_data %x  ip_hlen %u  ip_id %u  lso_mss %u"
 		   "  tcp_flags %x  xsum %x  seq %u  hlen %u\n",
-		   pbd, pbd->global_data, pbd->ip_hlen, pbd->ip_id,
-		   pbd->lso_mss, pbd->tcp_flags, pbd->tcp_pseudo_csum,
-		   pbd->tcp_send_seq, le16_to_cpu(pbd->total_hlen));
-
+		   pbd_e1x, pbd_e1x->global_data, pbd_e1x->ip_hlen_w,
+		   pbd_e1x->ip_id, pbd_e1x->lso_mss, pbd_e1x->tcp_flags,
+		   pbd_e1x->tcp_pseudo_csum, pbd_e1x->tcp_send_seq,
+		    le16_to_cpu(pbd_e1x->total_hlen_w));
+	if (pbd_e2)
+		DP(NETIF_MSG_TX_QUEUED,
+		   "PBD (E2) @%p  dst %x %x %x src %x %x %x parsing_data %x\n",
+		   pbd_e2, pbd_e2->dst_mac_addr_hi, pbd_e2->dst_mac_addr_mid,
+		   pbd_e2->dst_mac_addr_lo, pbd_e2->src_mac_addr_hi,
+		   pbd_e2->src_mac_addr_mid, pbd_e2->src_mac_addr_lo,
+		   pbd_e2->parsing_data);
 	DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d  bd %u\n", nbd, bd_prod);
 
 	/*
@@ -2078,7 +2146,8 @@
 
 	fp->tx_db.data.prod += nbd;
 	barrier();
-	DOORBELL(bp, fp->index, fp->tx_db.raw);
+
+	DOORBELL(bp, fp->cid, fp->tx_db.raw);
 
 	mmiowb();
 
@@ -2100,6 +2169,7 @@
 
 	return NETDEV_TX_OK;
 }
+
 /* called with rtnl_lock */
 int bnx2x_change_mac_addr(struct net_device *dev, void *p)
 {
@@ -2110,16 +2180,76 @@
 		return -EINVAL;
 
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	if (netif_running(dev)) {
-		if (CHIP_IS_E1(bp))
-			bnx2x_set_eth_mac_addr_e1(bp, 1);
-		else
-			bnx2x_set_eth_mac_addr_e1h(bp, 1);
+	if (netif_running(dev))
+		bnx2x_set_eth_mac(bp, 1);
+
+	return 0;
+}
+
+
+int bnx2x_setup_irqs(struct bnx2x *bp)
+{
+	int rc = 0;
+	if (bp->flags & USING_MSIX_FLAG) {
+		rc = bnx2x_req_msix_irqs(bp);
+		if (rc)
+			return rc;
+	} else {
+		bnx2x_ack_int(bp);
+		rc = bnx2x_req_irq(bp);
+		if (rc) {
+			BNX2X_ERR("IRQ request failed  rc %d, aborting\n", rc);
+			return rc;
+		}
+		if (bp->flags & USING_MSI_FLAG) {
+			bp->dev->irq = bp->pdev->irq;
+			netdev_info(bp->dev, "using MSI  IRQ %d\n",
+			       bp->pdev->irq);
+		}
 	}
 
 	return 0;
 }
 
+void bnx2x_free_mem_bp(struct bnx2x *bp)
+{
+	kfree(bp->fp);
+	kfree(bp->msix_table);
+	kfree(bp->ilt);
+}
+
+int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
+{
+	struct bnx2x_fastpath *fp;
+	struct msix_entry *tbl;
+	struct bnx2x_ilt *ilt;
+
+	/* fp array */
+	fp = kzalloc(L2_FP_COUNT(bp->l2_cid_count)*sizeof(*fp), GFP_KERNEL);
+	if (!fp)
+		goto alloc_err;
+	bp->fp = fp;
+
+	/* msix table */
+	tbl = kzalloc((bp->l2_cid_count + 1) * sizeof(*tbl),
+				  GFP_KERNEL);
+	if (!tbl)
+		goto alloc_err;
+	bp->msix_table = tbl;
+
+	/* ilt */
+	ilt = kzalloc(sizeof(*ilt), GFP_KERNEL);
+	if (!ilt)
+		goto alloc_err;
+	bp->ilt = ilt;
+
+	return 0;
+alloc_err:
+	bnx2x_free_mem_bp(bp);
+	return -ENOMEM;
+
+}
+
 /* called with rtnl_lock */
 int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
 {
@@ -2161,29 +2291,6 @@
 	schedule_delayed_work(&bp->reset_task, 0);
 }
 
-#ifdef BCM_VLAN
-/* called with rtnl_lock */
-void bnx2x_vlan_rx_register(struct net_device *dev,
-				   struct vlan_group *vlgrp)
-{
-	struct bnx2x *bp = netdev_priv(dev);
-
-	bp->vlgrp = vlgrp;
-
-	/* Set flags according to the required capabilities */
-	bp->flags &= ~(HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
-
-	if (dev->features & NETIF_F_HW_VLAN_TX)
-		bp->flags |= HW_VLAN_TX_FLAG;
-
-	if (dev->features & NETIF_F_HW_VLAN_RX)
-		bp->flags |= HW_VLAN_RX_FLAG;
-
-	if (netif_running(dev))
-		bnx2x_set_client_config(bp);
-}
-
-#endif
 int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
@@ -2244,6 +2351,8 @@
 	bnx2x_set_power_state(bp, PCI_D0);
 	netif_device_attach(dev);
 
+	/* Since the chip was reset, clear the FW sequence number */
+	bp->fw_seq = 0;
 	rc = bnx2x_nic_load(bp, LOAD_OPEN);
 
 	rtnl_unlock();
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h
index d1979b1..5bfe0ab 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/bnx2x/bnx2x_cmn.h
@@ -23,6 +23,7 @@
 
 #include "bnx2x.h"
 
+extern int num_queues;
 
 /*********************** Interfaces ****************************
  *  Functions that need to be implemented by each driver version
@@ -49,10 +50,11 @@
  * Query link status
  *
  * @param bp
+ * @param is_serdes
  *
  * @return 0 - link is UP
  */
-u8 bnx2x_link_test(struct bnx2x *bp);
+u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes);
 
 /**
  * Handles link status change
@@ -62,6 +64,15 @@
 void bnx2x__link_status_update(struct bnx2x *bp);
 
 /**
+ * Report link status to upper layer
+ *
+ * @param bp
+ *
+ * @return int
+ */
+void bnx2x_link_report(struct bnx2x *bp);
+
+/**
  * MSI-X slowpath interrupt handler
  *
  * @param irq
@@ -106,6 +117,13 @@
 void bnx2x_int_enable(struct bnx2x *bp);
 
 /**
+ * Disable HW interrupts.
+ *
+ * @param bp
+ */
+void bnx2x_int_disable(struct bnx2x *bp);
+
+/**
  * Disable interrupts. This function ensures that there are no
  * ISRs or SP DPCs (sp_task) are running after it returns.
  *
@@ -115,6 +133,15 @@
 void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
 
 /**
+ * Loads device firmware
+ *
+ * @param bp
+ *
+ * @return int
+ */
+int bnx2x_init_firmware(struct bnx2x *bp);
+
+/**
  * Init HW blocks according to current initialization stage:
  * COMMON, PORT or FUNCTION.
  *
@@ -153,32 +180,35 @@
 void bnx2x_free_mem(struct bnx2x *bp);
 
 /**
- * Bring up a leading (the first) eth Client.
- *
- * @param bp
- *
- * @return int
- */
-int bnx2x_setup_leading(struct bnx2x *bp);
-
-/**
- * Setup non-leading eth Client.
+ * Setup eth Client.
  *
  * @param bp
  * @param fp
+ * @param is_leading
  *
  * @return int
  */
-int bnx2x_setup_multi(struct bnx2x *bp, int index);
+int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+		       int is_leading);
 
 /**
- * Set number of quueus according to mode and number of available
- * msi-x vectors
+ * Bring down an eth client.
+ *
+ * @param bp
+ * @param p
+ *
+ * @return int
+ */
+int bnx2x_stop_fw_client(struct bnx2x *bp,
+			 struct bnx2x_client_ramrod_params *p);
+
+/**
+ * Set number of queues according to mode
  *
  * @param bp
  *
  */
-void bnx2x_set_num_queues_msix(struct bnx2x *bp);
+void bnx2x_set_num_queues(struct bnx2x *bp);
 
 /**
  * Cleanup chip internals:
@@ -213,21 +243,12 @@
 
 /**
  * Configure eth MAC address in the HW according to the value in
- * netdev->dev_addr for 57711
+ * netdev->dev_addr.
  *
  * @param bp driver handle
  * @param set
  */
-void bnx2x_set_eth_mac_addr_e1h(struct bnx2x *bp, int set);
-
-/**
- * Configure eth MAC address in the HW according to the value in
- * netdev->dev_addr for 57710
- *
- * @param bp driver handle
- * @param set
- */
-void bnx2x_set_eth_mac_addr_e1(struct bnx2x *bp, int set);
+void bnx2x_set_eth_mac(struct bnx2x *bp, int set);
 
 #ifdef BCM_CNIC
 /**
@@ -247,18 +268,22 @@
  * Initialize status block in FW and HW
  *
  * @param bp driver handle
- * @param sb host_status_block
  * @param dma_addr_t mapping
  * @param int sb_id
+ * @param int vfid
+ * @param u8 vf_valid
+ * @param int fw_sb_id
+ * @param int igu_sb_id
  */
-void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb,
-			  dma_addr_t mapping, int sb_id);
+void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
+			  u8 vf_valid, int fw_sb_id, int igu_sb_id);
 
 /**
- * Reconfigure FW/HW according to dev->flags rx mode
+ * Set MAC filtering configurations.
+ *
+ * @remarks called with netif_tx_lock from dev_mcast.c
  *
  * @param dev net_device
- *
  */
 void bnx2x_set_rx_mode(struct net_device *dev);
 
@@ -280,34 +305,162 @@
  * Perform statistics handling according to event
  *
  * @param bp driver handle
- * @param even tbnx2x_stats_event
+ * @param event bnx2x_stats_event
  */
 void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
 
 /**
- * Configures FW with client paramteres (like HW VLAN removal)
- * for each active client.
- *
- * @param bp
- */
-void bnx2x_set_client_config(struct bnx2x *bp);
-
-/**
- * Handle sp events
+ * Handle ramrods completion
  *
  * @param fp fastpath handle for the event
  * @param rr_cqe eth_rx_cqe
  */
-void bnx2x_sp_event(struct bnx2x_fastpath *fp,  union eth_rx_cqe *rr_cqe);
+void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
 
+/**
+ * Init/halt function before/after sending
+ * CLIENT_SETUP/CFC_DEL for the first/last client.
+ *
+ * @param bp
+ *
+ * @return int
+ */
+int bnx2x_func_start(struct bnx2x *bp);
+int bnx2x_func_stop(struct bnx2x *bp);
+
+/**
+ * Prepare ILT configurations according to current driver
+ * parameters.
+ *
+ * @param bp
+ */
+void bnx2x_ilt_set_info(struct bnx2x *bp);
+
+/**
+ * Set power state to the requested value. Currently only D0 and
+ * D3hot are supported.
+ *
+ * @param bp
+ * @param state D0 or D3hot
+ *
+ * @return int
+ */
+int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state);
+
+/* dev_close main block */
+int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
+
+/* dev_open main block */
+int bnx2x_nic_load(struct bnx2x *bp, int load_mode);
+
+/* hard_xmit callback */
+netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
+
+int bnx2x_change_mac_addr(struct net_device *dev, void *p);
+
+/* NAPI poll Rx part */
+int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget);
+
+/* NAPI poll Tx part */
+int bnx2x_tx_int(struct bnx2x_fastpath *fp);
+
+/* suspend/resume callbacks */
+int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state);
+int bnx2x_resume(struct pci_dev *pdev);
+
+/* Release IRQ vectors */
+void bnx2x_free_irq(struct bnx2x *bp);
+
+void bnx2x_init_rx_rings(struct bnx2x *bp);
+void bnx2x_free_skbs(struct bnx2x *bp);
+void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
+void bnx2x_netif_start(struct bnx2x *bp);
+
+/**
+ * Fill msix_table, request vectors, update num_queues according
+ * to number of available vectors
+ *
+ * @param bp
+ *
+ * @return int
+ */
+int bnx2x_enable_msix(struct bnx2x *bp);
+
+/**
+ * Request msi mode from OS, updated internals accordingly
+ *
+ * @param bp
+ *
+ * @return int
+ */
+int bnx2x_enable_msi(struct bnx2x *bp);
+
+/**
+ * Request IRQ vectors from OS.
+ *
+ * @param bp
+ *
+ * @return int
+ */
+int bnx2x_setup_irqs(struct bnx2x *bp);
+/**
+ * NAPI callback
+ *
+ * @param napi
+ * @param budget
+ *
+ * @return int
+ */
+int bnx2x_poll(struct napi_struct *napi, int budget);
+
+/**
+ * Allocate/release memories outsize main driver structure
+ *
+ * @param bp
+ *
+ * @return int
+ */
+int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp);
+void bnx2x_free_mem_bp(struct bnx2x *bp);
+
+/**
+ * Change mtu netdev callback
+ *
+ * @param dev
+ * @param new_mtu
+ *
+ * @return int
+ */
+int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
+
+/**
+ * tx timeout netdev callback
+ *
+ * @param dev
+ * @param new_mtu
+ *
+ * @return int
+ */
+void bnx2x_tx_timeout(struct net_device *dev);
+
+#ifdef BCM_VLAN
+/**
+ * vlan rx register netdev callback
+ *
+ * @param dev
+ * @param new_mtu
+ *
+ * @return int
+ */
+void bnx2x_vlan_rx_register(struct net_device *dev,
+				   struct vlan_group *vlgrp);
+
+#endif
 
 static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
 {
-	struct host_status_block *fpsb = fp->status_blk;
-
 	barrier(); /* status block is written to by the chip */
-	fp->fp_c_idx = fpsb->c_status_block.status_block_index;
-	fp->fp_u_idx = fpsb->u_status_block.status_block_index;
+	fp->fp_hc_idx = fp->sb_running_index[SM_RX_ID];
 }
 
 static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
@@ -334,8 +487,8 @@
 	wmb();
 
 	for (i = 0; i < sizeof(struct ustorm_eth_rx_producers)/4; i++)
-		REG_WR(bp, BAR_USTRORM_INTMEM +
-		       USTORM_RX_PRODS_OFFSET(BP_PORT(bp), fp->cl_id) + i*4,
+		REG_WR(bp,
+		       BAR_USTRORM_INTMEM + fp->ustorm_rx_prods_offset + i*4,
 		       ((u32 *)&rx_prods)[i]);
 
 	mmiowb(); /* keep prod updates ordered */
@@ -345,10 +498,77 @@
 	   fp->index, bd_prod, rx_comp_prod, rx_sge_prod);
 }
 
+static inline void bnx2x_igu_ack_sb_gen(struct bnx2x *bp, u8 igu_sb_id,
+					u8 segment, u16 index, u8 op,
+					u8 update, u32 igu_addr)
+{
+	struct igu_regular cmd_data = {0};
+
+	cmd_data.sb_id_and_flags =
+			((index << IGU_REGULAR_SB_INDEX_SHIFT) |
+			 (segment << IGU_REGULAR_SEGMENT_ACCESS_SHIFT) |
+			 (update << IGU_REGULAR_BUPDATE_SHIFT) |
+			 (op << IGU_REGULAR_ENABLE_INT_SHIFT));
+
+	DP(NETIF_MSG_HW, "write 0x%08x to IGU addr 0x%x\n",
+	   cmd_data.sb_id_and_flags, igu_addr);
+	REG_WR(bp, igu_addr, cmd_data.sb_id_and_flags);
+
+	/* Make sure that ACK is written */
+	mmiowb();
+	barrier();
+}
+
+static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp,
+					  u8 idu_sb_id, bool is_Pf)
+{
+	u32 data, ctl, cnt = 100;
+	u32 igu_addr_data = IGU_REG_COMMAND_REG_32LSB_DATA;
+	u32 igu_addr_ctl = IGU_REG_COMMAND_REG_CTRL;
+	u32 igu_addr_ack = IGU_REG_CSTORM_TYPE_0_SB_CLEANUP + (idu_sb_id/32)*4;
+	u32 sb_bit =  1 << (idu_sb_id%32);
+	u32 func_encode = BP_FUNC(bp) |
+			((is_Pf == true ? 1 : 0) << IGU_FID_ENCODE_IS_PF_SHIFT);
+	u32 addr_encode = IGU_CMD_E2_PROD_UPD_BASE + idu_sb_id;
+
+	/* Not supported in BC mode */
+	if (CHIP_INT_MODE_IS_BC(bp))
+		return;
+
+	data = (IGU_USE_REGISTER_cstorm_type_0_sb_cleanup
+			<< IGU_REGULAR_CLEANUP_TYPE_SHIFT)	|
+		IGU_REGULAR_CLEANUP_SET				|
+		IGU_REGULAR_BCLEANUP;
+
+	ctl = addr_encode << IGU_CTRL_REG_ADDRESS_SHIFT		|
+	      func_encode << IGU_CTRL_REG_FID_SHIFT		|
+	      IGU_CTRL_CMD_TYPE_WR << IGU_CTRL_REG_TYPE_SHIFT;
+
+	DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
+			 data, igu_addr_data);
+	REG_WR(bp, igu_addr_data, data);
+	mmiowb();
+	barrier();
+	DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
+			  ctl, igu_addr_ctl);
+	REG_WR(bp, igu_addr_ctl, ctl);
+	mmiowb();
+	barrier();
+
+	/* wait for clean up to finish */
+	while (!(REG_RD(bp, igu_addr_ack) & sb_bit) && --cnt)
+		msleep(20);
 
 
-static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
-				u8 storm, u16 index, u8 op, u8 update)
+	if (!(REG_RD(bp, igu_addr_ack) & sb_bit)) {
+		DP(NETIF_MSG_HW, "Unable to finish IGU cleanup: "
+			  "idu_sb_id %d offset %d bit %d (cnt %d)\n",
+			  idu_sb_id, idu_sb_id/32, idu_sb_id%32, cnt);
+	}
+}
+
+static inline void bnx2x_hc_ack_sb(struct bnx2x *bp, u8 sb_id,
+				   u8 storm, u16 index, u8 op, u8 update)
 {
 	u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
 		       COMMAND_REG_INT_ACK);
@@ -369,7 +589,37 @@
 	mmiowb();
 	barrier();
 }
-static inline u16 bnx2x_ack_int(struct bnx2x *bp)
+
+static inline void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
+		      u16 index, u8 op, u8 update)
+{
+	u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id)*8;
+
+	bnx2x_igu_ack_sb_gen(bp, igu_sb_id, segment, index, op, update,
+			     igu_addr);
+}
+
+static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 storm,
+				u16 index, u8 op, u8 update)
+{
+	if (bp->common.int_block == INT_BLOCK_HC)
+		bnx2x_hc_ack_sb(bp, igu_sb_id, storm, index, op, update);
+	else {
+		u8 segment;
+
+		if (CHIP_INT_MODE_IS_BC(bp))
+			segment = storm;
+		else if (igu_sb_id != bp->igu_dsb_id)
+			segment = IGU_SEG_ACCESS_DEF;
+		else if (storm == ATTENTION_ID)
+			segment = IGU_SEG_ACCESS_ATTN;
+		else
+			segment = IGU_SEG_ACCESS_DEF;
+		bnx2x_igu_ack_sb(bp, igu_sb_id, segment, index, op, update);
+	}
+}
+
+static inline u16 bnx2x_hc_ack_int(struct bnx2x *bp)
 {
 	u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
 		       COMMAND_REG_SIMD_MASK);
@@ -378,18 +628,36 @@
 	DP(BNX2X_MSG_OFF, "read 0x%08x from HC addr 0x%x\n",
 	   result, hc_addr);
 
+	barrier();
 	return result;
 }
 
-/*
- * fast path service functions
- */
+static inline u16 bnx2x_igu_ack_int(struct bnx2x *bp)
+{
+	u32 igu_addr = (BAR_IGU_INTMEM + IGU_REG_SISR_MDPC_WMASK_LSB_UPPER*8);
+	u32 result = REG_RD(bp, igu_addr);
+
+	DP(NETIF_MSG_HW, "read 0x%08x from IGU addr 0x%x\n",
+	   result, igu_addr);
+
+	barrier();
+	return result;
+}
+
+static inline u16 bnx2x_ack_int(struct bnx2x *bp)
+{
+	barrier();
+	if (bp->common.int_block == INT_BLOCK_HC)
+		return bnx2x_hc_ack_int(bp);
+	else
+		return bnx2x_igu_ack_int(bp);
+}
 
 static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp)
 {
 	/* Tell compiler that consumer and producer can change */
 	barrier();
-	return (fp->tx_pkt_prod != fp->tx_pkt_cons);
+	return fp->tx_pkt_prod != fp->tx_pkt_cons;
 }
 
 static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
@@ -424,6 +692,29 @@
 	return hw_cons != fp->tx_pkt_cons;
 }
 
+static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
+{
+	u16 rx_cons_sb;
+
+	/* Tell compiler that status block fields can change */
+	barrier();
+	rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
+	if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
+		rx_cons_sb++;
+	return (fp->rx_comp_cons != rx_cons_sb);
+}
+
+/**
+ * disables tx from stack point of view
+ *
+ * @param bp
+ */
+static inline void bnx2x_tx_disable(struct bnx2x *bp)
+{
+	netif_tx_disable(bp->dev);
+	netif_carrier_off(bp->dev);
+}
+
 static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
 				     struct bnx2x_fastpath *fp, u16 index)
 {
@@ -436,7 +727,7 @@
 		return;
 
 	dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(sw_buf, mapping),
-		       SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE);
+		       SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE);
 	__free_pages(page, PAGES_PER_SGE_SHIFT);
 
 	sw_buf->page = NULL;
@@ -444,13 +735,67 @@
 	sge->addr_lo = 0;
 }
 
-static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
-					   struct bnx2x_fastpath *fp, int last)
+static inline void bnx2x_add_all_napi(struct bnx2x *bp)
 {
 	int i;
 
-	for (i = 0; i < last; i++)
-		bnx2x_free_rx_sge(bp, fp, i);
+	/* Add NAPI objects */
+	for_each_queue(bp, i)
+		netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
+			       bnx2x_poll, BNX2X_NAPI_WEIGHT);
+}
+
+static inline void bnx2x_del_all_napi(struct bnx2x *bp)
+{
+	int i;
+
+	for_each_queue(bp, i)
+		netif_napi_del(&bnx2x_fp(bp, i, napi));
+}
+
+static inline void bnx2x_disable_msi(struct bnx2x *bp)
+{
+	if (bp->flags & USING_MSIX_FLAG) {
+		pci_disable_msix(bp->pdev);
+		bp->flags &= ~USING_MSIX_FLAG;
+	} else if (bp->flags & USING_MSI_FLAG) {
+		pci_disable_msi(bp->pdev);
+		bp->flags &= ~USING_MSI_FLAG;
+	}
+}
+
+static inline int bnx2x_calc_num_queues(struct bnx2x *bp)
+{
+	return  num_queues ?
+		 min_t(int, num_queues, BNX2X_MAX_QUEUES(bp)) :
+		 min_t(int, num_online_cpus(), BNX2X_MAX_QUEUES(bp));
+}
+
+static inline void bnx2x_clear_sge_mask_next_elems(struct bnx2x_fastpath *fp)
+{
+	int i, j;
+
+	for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
+		int idx = RX_SGE_CNT * i - 1;
+
+		for (j = 0; j < 2; j++) {
+			SGE_MASK_CLEAR_BIT(fp, idx);
+			idx--;
+		}
+	}
+}
+
+static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp)
+{
+	/* Set the mask to all 1-s: it's faster to compare to 0 than to 0xf-s */
+	memset(fp->sge_mask, 0xff,
+	       (NUM_RX_SGE >> RX_SGE_MASK_ELEM_SHIFT)*sizeof(u64));
+
+	/* Clear the two last indices in the page to 1:
+	   these are the indices that correspond to the "next" element,
+	   hence will never be indicated and should be removed from
+	   the calculations. */
+	bnx2x_clear_sge_mask_next_elems(fp);
 }
 
 static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp,
@@ -479,6 +824,7 @@
 
 	return 0;
 }
+
 static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
 				     struct bnx2x_fastpath *fp, u16 index)
 {
@@ -513,7 +859,7 @@
  * so there is no need to check for dma_mapping_error().
  */
 static inline void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp,
-			       struct sk_buff *skb, u16 cons, u16 prod)
+				      u16 cons, u16 prod)
 {
 	struct bnx2x *bp = fp->bp;
 	struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons];
@@ -531,32 +877,15 @@
 	*prod_bd = *cons_bd;
 }
 
-static inline void bnx2x_clear_sge_mask_next_elems(struct bnx2x_fastpath *fp)
+static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
+					   struct bnx2x_fastpath *fp, int last)
 {
-	int i, j;
+	int i;
 
-	for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
-		int idx = RX_SGE_CNT * i - 1;
-
-		for (j = 0; j < 2; j++) {
-			SGE_MASK_CLEAR_BIT(fp, idx);
-			idx--;
-		}
-	}
+	for (i = 0; i < last; i++)
+		bnx2x_free_rx_sge(bp, fp, i);
 }
 
-static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp)
-{
-	/* Set the mask to all 1-s: it's faster to compare to 0 than to 0xf-s */
-	memset(fp->sge_mask, 0xff,
-	       (NUM_RX_SGE >> RX_SGE_MASK_ELEM_SHIFT)*sizeof(u64));
-
-	/* Clear the two last indices in the page to 1:
-	   these are the indices that correspond to the "next" element,
-	   hence will never be indicated and should be removed from
-	   the calculations. */
-	bnx2x_clear_sge_mask_next_elems(fp);
-}
 static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
 				       struct bnx2x_fastpath *fp, int last)
 {
@@ -582,7 +911,7 @@
 }
 
 
-static inline void bnx2x_init_tx_ring(struct bnx2x *bp)
+static inline void bnx2x_init_tx_rings(struct bnx2x *bp)
 {
 	int i, j;
 
@@ -601,7 +930,7 @@
 					    BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
 		}
 
-		fp->tx_db.data.header.header = DOORBELL_HDR_DB_TYPE;
+		SET_FLAG(fp->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
 		fp->tx_db.data.zero_fill1 = 0;
 		fp->tx_db.data.prod = 0;
 
@@ -609,44 +938,98 @@
 		fp->tx_pkt_cons = 0;
 		fp->tx_bd_prod = 0;
 		fp->tx_bd_cons = 0;
-		fp->tx_cons_sb = BNX2X_TX_SB_INDEX;
 		fp->tx_pkt = 0;
 	}
 }
-static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
-{
-	u16 rx_cons_sb;
 
-	/* Tell compiler that status block fields can change */
-	barrier();
-	rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
-	if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
-		rx_cons_sb++;
-	return (fp->rx_comp_cons != rx_cons_sb);
+static inline void bnx2x_set_next_page_rx_bd(struct bnx2x_fastpath *fp)
+{
+	int i;
+
+	for (i = 1; i <= NUM_RX_RINGS; i++) {
+		struct eth_rx_bd *rx_bd;
+
+		rx_bd = &fp->rx_desc_ring[RX_DESC_CNT * i - 2];
+		rx_bd->addr_hi =
+			cpu_to_le32(U64_HI(fp->rx_desc_mapping +
+				    BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
+		rx_bd->addr_lo =
+			cpu_to_le32(U64_LO(fp->rx_desc_mapping +
+				    BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
+	}
+}
+
+static inline void bnx2x_set_next_page_sgl(struct bnx2x_fastpath *fp)
+{
+	int i;
+
+	for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
+		struct eth_rx_sge *sge;
+
+		sge = &fp->rx_sge_ring[RX_SGE_CNT * i - 2];
+		sge->addr_hi =
+			cpu_to_le32(U64_HI(fp->rx_sge_mapping +
+			BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
+
+		sge->addr_lo =
+			cpu_to_le32(U64_LO(fp->rx_sge_mapping +
+			BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
+	}
+}
+
+static inline void bnx2x_set_next_page_rx_cq(struct bnx2x_fastpath *fp)
+{
+	int i;
+	for (i = 1; i <= NUM_RCQ_RINGS; i++) {
+		struct eth_rx_cqe_next_page *nextpg;
+
+		nextpg = (struct eth_rx_cqe_next_page *)
+			&fp->rx_comp_ring[RCQ_DESC_CNT * i - 1];
+		nextpg->addr_hi =
+			cpu_to_le32(U64_HI(fp->rx_comp_mapping +
+				   BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
+		nextpg->addr_lo =
+			cpu_to_le32(U64_LO(fp->rx_comp_mapping +
+				   BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
+	}
+}
+
+
+
+static inline void __storm_memset_struct(struct bnx2x *bp,
+					 u32 addr, size_t size, u32 *data)
+{
+	int i;
+	for (i = 0; i < size/4; i++)
+		REG_WR(bp, addr + (i * 4), data[i]);
+}
+
+static inline void storm_memset_mac_filters(struct bnx2x *bp,
+			struct tstorm_eth_mac_filter_config *mac_filters,
+			u16 abs_fid)
+{
+	size_t size = sizeof(struct tstorm_eth_mac_filter_config);
+
+	u32 addr = BAR_TSTRORM_INTMEM +
+			TSTORM_MAC_FILTER_CONFIG_OFFSET(abs_fid);
+
+	__storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
+}
+
+static inline void storm_memset_cmng(struct bnx2x *bp,
+				struct cmng_struct_per_port *cmng,
+				u8 port)
+{
+	size_t size = sizeof(struct cmng_struct_per_port);
+
+	u32 addr = BAR_XSTRORM_INTMEM +
+			XSTORM_CMNG_PER_PORT_VARS_OFFSET(port);
+
+	__storm_memset_struct(bp, addr, size, (u32 *)cmng);
 }
 
 /* HW Lock for shared dual port PHYs */
 void bnx2x_acquire_phy_lock(struct bnx2x *bp);
 void bnx2x_release_phy_lock(struct bnx2x *bp);
 
-void bnx2x_link_report(struct bnx2x *bp);
-int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget);
-int bnx2x_tx_int(struct bnx2x_fastpath *fp);
-void bnx2x_init_rx_rings(struct bnx2x *bp);
-netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
-
-int bnx2x_change_mac_addr(struct net_device *dev, void *p);
-void bnx2x_tx_timeout(struct net_device *dev);
-void bnx2x_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp);
-void bnx2x_netif_start(struct bnx2x *bp);
-void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
-void bnx2x_free_irq(struct bnx2x *bp, bool disable_only);
-int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state);
-int bnx2x_resume(struct pci_dev *pdev);
-void bnx2x_free_skbs(struct bnx2x *bp);
-int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
-int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
-int bnx2x_nic_load(struct bnx2x *bp, int load_mode);
-int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state);
-
 #endif /* BNX2X_CMN_H */
diff --git a/drivers/net/bnx2x/bnx2x_dump.h b/drivers/net/bnx2x/bnx2x_dump.h
index 3bb9a91..dc18c25 100644
--- a/drivers/net/bnx2x/bnx2x_dump.h
+++ b/drivers/net/bnx2x/bnx2x_dump.h
@@ -31,14 +31,24 @@
 
 #define RI_E1				0x1
 #define RI_E1H				0x2
+#define RI_E2			0x4
 #define RI_ONLINE			0x100
-
+#define RI_PATH0_DUMP		0x200
+#define RI_PATH1_DUMP		0x400
 #define RI_E1_OFFLINE			(RI_E1)
 #define RI_E1_ONLINE			(RI_E1 | RI_ONLINE)
 #define RI_E1H_OFFLINE			(RI_E1H)
 #define RI_E1H_ONLINE			(RI_E1H | RI_ONLINE)
-#define RI_ALL_OFFLINE			(RI_E1 | RI_E1H)
-#define RI_ALL_ONLINE			(RI_E1 | RI_E1H | RI_ONLINE)
+#define RI_E2_OFFLINE			(RI_E2)
+#define RI_E2_ONLINE			(RI_E2 | RI_ONLINE)
+#define RI_E1E1H_OFFLINE		(RI_E1 | RI_E1H)
+#define RI_E1E1H_ONLINE			(RI_E1 | RI_E1H | RI_ONLINE)
+#define RI_E1HE2_OFFLINE		(RI_E2 | RI_E1H)
+#define RI_E1HE2_ONLINE			(RI_E2 | RI_E1H | RI_ONLINE)
+#define RI_E1E2_OFFLINE			(RI_E2 | RI_E1)
+#define RI_E1E2_ONLINE			(RI_E2 | RI_E1 | RI_ONLINE)
+#define RI_ALL_OFFLINE			(RI_E1 | RI_E1H | RI_E2)
+#define RI_ALL_ONLINE			(RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
 
 #define MAX_TIMER_PENDING		200
 #define TIMER_SCAN_DONT_CARE		0xFF
@@ -513,6 +523,12 @@
 	{ 0x1b0c00, 256, 2, read_reg_e1h_0, RI_E1H_OFFLINE }
 };
 
+#define WREGS_COUNT_E2			1
+static const u32 read_reg_e2_0[] = { 0x1b1040, 0x1b1000 };
+
+static const struct wreg_addr wreg_addrs_e2[WREGS_COUNT_E2] = {
+	{ 0x1b0c00, 128, 2, read_reg_e2_0, RI_E2_OFFLINE }
+};
 
 static const struct dump_sign dump_sign_all = { 0x49aa93ee, 0x40835, 0x22 };
 
@@ -531,4 +547,17 @@
 	{ 0x1640d0, 0x1640d4 };
 
 
+#define PAGE_MODE_VALUES_E2 2
+
+#define PAGE_READ_REGS_E2 1
+
+#define PAGE_WRITE_REGS_E2 1
+
+static const u32 page_vals_e2[PAGE_MODE_VALUES_E2] = { 0, 128 };
+
+static const u32 page_write_regs_e2[PAGE_WRITE_REGS_E2] = { 328476 };
+
+static const struct reg_addr page_read_regs_e2[PAGE_READ_REGS_E2] = {
+	{ 0x58000, 4608, RI_E2_ONLINE } };
+
 #endif /* BNX2X_DUMP_H */
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index 8b75b05..d02ffbd 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -25,70 +25,46 @@
 #include "bnx2x_cmn.h"
 #include "bnx2x_dump.h"
 
-
 static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-
-	cmd->supported = bp->port.supported;
-	cmd->advertising = bp->port.advertising;
+	int cfg_idx = bnx2x_get_link_cfg_idx(bp);
+	/* Dual Media boards present all available port types */
+	cmd->supported = bp->port.supported[cfg_idx] |
+		(bp->port.supported[cfg_idx ^ 1] &
+		 (SUPPORTED_TP | SUPPORTED_FIBRE));
+	cmd->advertising = bp->port.advertising[cfg_idx];
 
 	if ((bp->state == BNX2X_STATE_OPEN) &&
 	    !(bp->flags & MF_FUNC_DIS) &&
 	    (bp->link_vars.link_up)) {
 		cmd->speed = bp->link_vars.line_speed;
 		cmd->duplex = bp->link_vars.duplex;
-		if (IS_E1HMF(bp)) {
-			u16 vn_max_rate;
-
-			vn_max_rate =
-				((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >>
-				FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
-			if (vn_max_rate < cmd->speed)
-				cmd->speed = vn_max_rate;
-		}
 	} else {
-		cmd->speed = -1;
-		cmd->duplex = -1;
+
+		cmd->speed = bp->link_params.req_line_speed[cfg_idx];
+		cmd->duplex = bp->link_params.req_duplex[cfg_idx];
+	}
+	if (IS_MF(bp)) {
+		u16 vn_max_rate = ((bp->mf_config[BP_VN(bp)] &
+			FUNC_MF_CFG_MAX_BW_MASK) >> FUNC_MF_CFG_MAX_BW_SHIFT) *
+			100;
+
+		if (vn_max_rate < cmd->speed)
+			cmd->speed = vn_max_rate;
 	}
 
-	if (bp->link_params.switch_cfg == SWITCH_CFG_10G) {
-		u32 ext_phy_type =
-			XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
-
-		switch (ext_phy_type) {
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-			cmd->port = PORT_FIBRE;
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-			cmd->port = PORT_TP;
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
-			BNX2X_ERR("XGXS PHY Failure detected 0x%x\n",
-				  bp->link_params.ext_phy_config);
-			break;
-
-		default:
-			DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
-			   bp->link_params.ext_phy_config);
-			break;
-		}
-	} else
+	if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
 		cmd->port = PORT_TP;
+	else if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE)
+		cmd->port = PORT_FIBRE;
+	else
+		BNX2X_ERR("XGXS PHY Failure detected\n");
 
 	cmd->phy_address = bp->mdio.prtad;
 	cmd->transceiver = XCVR_INTERNAL;
 
-	if (bp->link_params.req_line_speed == SPEED_AUTO_NEG)
+	if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG)
 		cmd->autoneg = AUTONEG_ENABLE;
 	else
 		cmd->autoneg = AUTONEG_DISABLE;
@@ -110,9 +86,9 @@
 static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-	u32 advertising;
+	u32 advertising, cfg_idx, old_multi_phy_config, new_multi_phy_config;
 
-	if (IS_E1HMF(bp))
+	if (IS_MF(bp))
 		return 0;
 
 	DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n"
@@ -123,26 +99,81 @@
 	   cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
 	   cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
 
+	cfg_idx = bnx2x_get_link_cfg_idx(bp);
+	old_multi_phy_config = bp->link_params.multi_phy_config;
+	switch (cmd->port) {
+	case PORT_TP:
+		if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
+			break; /* no port change */
+
+		if (!(bp->port.supported[0] & SUPPORTED_TP ||
+		      bp->port.supported[1] & SUPPORTED_TP)) {
+			DP(NETIF_MSG_LINK, "Unsupported port type\n");
+			return -EINVAL;
+		}
+		bp->link_params.multi_phy_config &=
+			~PORT_HW_CFG_PHY_SELECTION_MASK;
+		if (bp->link_params.multi_phy_config &
+		    PORT_HW_CFG_PHY_SWAPPED_ENABLED)
+			bp->link_params.multi_phy_config |=
+			PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
+		else
+			bp->link_params.multi_phy_config |=
+			PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
+		break;
+	case PORT_FIBRE:
+		if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE)
+			break; /* no port change */
+
+		if (!(bp->port.supported[0] & SUPPORTED_FIBRE ||
+		      bp->port.supported[1] & SUPPORTED_FIBRE)) {
+			DP(NETIF_MSG_LINK, "Unsupported port type\n");
+			return -EINVAL;
+		}
+		bp->link_params.multi_phy_config &=
+			~PORT_HW_CFG_PHY_SELECTION_MASK;
+		if (bp->link_params.multi_phy_config &
+		    PORT_HW_CFG_PHY_SWAPPED_ENABLED)
+			bp->link_params.multi_phy_config |=
+			PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
+		else
+			bp->link_params.multi_phy_config |=
+			PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
+		break;
+	default:
+		DP(NETIF_MSG_LINK, "Unsupported port type\n");
+		return -EINVAL;
+	}
+	/* Save new config in case command complete successuly */
+	new_multi_phy_config = bp->link_params.multi_phy_config;
+	/* Get the new cfg_idx */
+	cfg_idx = bnx2x_get_link_cfg_idx(bp);
+	/* Restore old config in case command failed */
+	bp->link_params.multi_phy_config = old_multi_phy_config;
+	DP(NETIF_MSG_LINK, "cfg_idx = %x\n", cfg_idx);
+
 	if (cmd->autoneg == AUTONEG_ENABLE) {
-		if (!(bp->port.supported & SUPPORTED_Autoneg)) {
+		if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) {
 			DP(NETIF_MSG_LINK, "Autoneg not supported\n");
 			return -EINVAL;
 		}
 
 		/* advertise the requested speed and duplex if supported */
-		cmd->advertising &= bp->port.supported;
+		cmd->advertising &= bp->port.supported[cfg_idx];
 
-		bp->link_params.req_line_speed = SPEED_AUTO_NEG;
-		bp->link_params.req_duplex = DUPLEX_FULL;
-		bp->port.advertising |= (ADVERTISED_Autoneg |
+		bp->link_params.req_line_speed[cfg_idx] = SPEED_AUTO_NEG;
+		bp->link_params.req_duplex[cfg_idx] = DUPLEX_FULL;
+		bp->port.advertising[cfg_idx] |= (ADVERTISED_Autoneg |
 					 cmd->advertising);
 
 	} else { /* forced speed */
 		/* advertise the requested speed and duplex if supported */
-		switch (cmd->speed) {
+		u32 speed = cmd->speed;
+		speed |= (cmd->speed_hi << 16);
+		switch (speed) {
 		case SPEED_10:
 			if (cmd->duplex == DUPLEX_FULL) {
-				if (!(bp->port.supported &
+				if (!(bp->port.supported[cfg_idx] &
 				      SUPPORTED_10baseT_Full)) {
 					DP(NETIF_MSG_LINK,
 					   "10M full not supported\n");
@@ -152,7 +183,7 @@
 				advertising = (ADVERTISED_10baseT_Full |
 					       ADVERTISED_TP);
 			} else {
-				if (!(bp->port.supported &
+				if (!(bp->port.supported[cfg_idx] &
 				      SUPPORTED_10baseT_Half)) {
 					DP(NETIF_MSG_LINK,
 					   "10M half not supported\n");
@@ -166,7 +197,7 @@
 
 		case SPEED_100:
 			if (cmd->duplex == DUPLEX_FULL) {
-				if (!(bp->port.supported &
+				if (!(bp->port.supported[cfg_idx] &
 						SUPPORTED_100baseT_Full)) {
 					DP(NETIF_MSG_LINK,
 					   "100M full not supported\n");
@@ -176,7 +207,7 @@
 				advertising = (ADVERTISED_100baseT_Full |
 					       ADVERTISED_TP);
 			} else {
-				if (!(bp->port.supported &
+				if (!(bp->port.supported[cfg_idx] &
 						SUPPORTED_100baseT_Half)) {
 					DP(NETIF_MSG_LINK,
 					   "100M half not supported\n");
@@ -194,7 +225,8 @@
 				return -EINVAL;
 			}
 
-			if (!(bp->port.supported & SUPPORTED_1000baseT_Full)) {
+			if (!(bp->port.supported[cfg_idx] &
+			      SUPPORTED_1000baseT_Full)) {
 				DP(NETIF_MSG_LINK, "1G full not supported\n");
 				return -EINVAL;
 			}
@@ -210,7 +242,8 @@
 				return -EINVAL;
 			}
 
-			if (!(bp->port.supported & SUPPORTED_2500baseX_Full)) {
+			if (!(bp->port.supported[cfg_idx]
+			      & SUPPORTED_2500baseX_Full)) {
 				DP(NETIF_MSG_LINK,
 				   "2.5G full not supported\n");
 				return -EINVAL;
@@ -226,7 +259,8 @@
 				return -EINVAL;
 			}
 
-			if (!(bp->port.supported & SUPPORTED_10000baseT_Full)) {
+			if (!(bp->port.supported[cfg_idx]
+			      & SUPPORTED_10000baseT_Full)) {
 				DP(NETIF_MSG_LINK, "10G full not supported\n");
 				return -EINVAL;
 			}
@@ -236,20 +270,23 @@
 			break;
 
 		default:
-			DP(NETIF_MSG_LINK, "Unsupported speed\n");
+			DP(NETIF_MSG_LINK, "Unsupported speed %d\n", speed);
 			return -EINVAL;
 		}
 
-		bp->link_params.req_line_speed = cmd->speed;
-		bp->link_params.req_duplex = cmd->duplex;
-		bp->port.advertising = advertising;
+		bp->link_params.req_line_speed[cfg_idx] = speed;
+		bp->link_params.req_duplex[cfg_idx] = cmd->duplex;
+		bp->port.advertising[cfg_idx] = advertising;
 	}
 
 	DP(NETIF_MSG_LINK, "req_line_speed %d\n"
 	   DP_LEVEL "  req_duplex %d  advertising 0x%x\n",
-	   bp->link_params.req_line_speed, bp->link_params.req_duplex,
-	   bp->port.advertising);
+	   bp->link_params.req_line_speed[cfg_idx],
+	   bp->link_params.req_duplex[cfg_idx],
+	   bp->port.advertising[cfg_idx]);
 
+	/* Set new config */
+	bp->link_params.multi_phy_config = new_multi_phy_config;
 	if (netif_running(dev)) {
 		bnx2x_stats_handle(bp, STATS_EVENT_STOP);
 		bnx2x_link_set(bp);
@@ -260,6 +297,7 @@
 
 #define IS_E1_ONLINE(info)	(((info) & RI_E1_ONLINE) == RI_E1_ONLINE)
 #define IS_E1H_ONLINE(info)	(((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE)
+#define IS_E2_ONLINE(info)	(((info) & RI_E2_ONLINE) == RI_E2_ONLINE)
 
 static int bnx2x_get_regs_len(struct net_device *dev)
 {
@@ -277,7 +315,7 @@
 				regdump_len += wreg_addrs_e1[i].size *
 					(1 + wreg_addrs_e1[i].read_regs_count);
 
-	} else { /* E1H */
+	} else if (CHIP_IS_E1H(bp)) {
 		for (i = 0; i < REGS_COUNT; i++)
 			if (IS_E1H_ONLINE(reg_addrs[i].info))
 				regdump_len += reg_addrs[i].size;
@@ -286,6 +324,15 @@
 			if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info))
 				regdump_len += wreg_addrs_e1h[i].size *
 					(1 + wreg_addrs_e1h[i].read_regs_count);
+	} else if (CHIP_IS_E2(bp)) {
+		for (i = 0; i < REGS_COUNT; i++)
+			if (IS_E2_ONLINE(reg_addrs[i].info))
+				regdump_len += reg_addrs[i].size;
+
+		for (i = 0; i < WREGS_COUNT_E2; i++)
+			if (IS_E2_ONLINE(wreg_addrs_e2[i].info))
+				regdump_len += wreg_addrs_e2[i].size *
+					(1 + wreg_addrs_e2[i].read_regs_count);
 	}
 	regdump_len *= 4;
 	regdump_len += sizeof(struct dump_hdr);
@@ -293,6 +340,23 @@
 	return regdump_len;
 }
 
+static inline void bnx2x_read_pages_regs_e2(struct bnx2x *bp, u32 *p)
+{
+	u32 i, j, k, n;
+
+	for (i = 0; i < PAGE_MODE_VALUES_E2; i++) {
+		for (j = 0; j < PAGE_WRITE_REGS_E2; j++) {
+			REG_WR(bp, page_write_regs_e2[j], page_vals_e2[i]);
+			for (k = 0; k < PAGE_READ_REGS_E2; k++)
+				if (IS_E2_ONLINE(page_read_regs_e2[k].info))
+					for (n = 0; n <
+					      page_read_regs_e2[k].size; n++)
+						*p++ = REG_RD(bp,
+					page_read_regs_e2[k].addr + n*4);
+		}
+	}
+}
+
 static void bnx2x_get_regs(struct net_device *dev,
 			   struct ethtool_regs *regs, void *_p)
 {
@@ -312,7 +376,14 @@
 	dump_hdr.tstorm_waitp = REG_RD(bp, TSTORM_WAITP_ADDR);
 	dump_hdr.ustorm_waitp = REG_RD(bp, USTORM_WAITP_ADDR);
 	dump_hdr.cstorm_waitp = REG_RD(bp, CSTORM_WAITP_ADDR);
-	dump_hdr.info = CHIP_IS_E1(bp) ? RI_E1_ONLINE : RI_E1H_ONLINE;
+
+	if (CHIP_IS_E1(bp))
+		dump_hdr.info = RI_E1_ONLINE;
+	else if (CHIP_IS_E1H(bp))
+		dump_hdr.info = RI_E1H_ONLINE;
+	else if (CHIP_IS_E2(bp))
+		dump_hdr.info = RI_E2_ONLINE |
+		(BP_PATH(bp) ? RI_PATH1_DUMP : RI_PATH0_DUMP);
 
 	memcpy(p, &dump_hdr, sizeof(struct dump_hdr));
 	p += dump_hdr.hdr_size + 1;
@@ -324,16 +395,25 @@
 					*p++ = REG_RD(bp,
 						      reg_addrs[i].addr + j*4);
 
-	} else { /* E1H */
+	} else if (CHIP_IS_E1H(bp)) {
 		for (i = 0; i < REGS_COUNT; i++)
 			if (IS_E1H_ONLINE(reg_addrs[i].info))
 				for (j = 0; j < reg_addrs[i].size; j++)
 					*p++ = REG_RD(bp,
 						      reg_addrs[i].addr + j*4);
+
+	} else if (CHIP_IS_E2(bp)) {
+		for (i = 0; i < REGS_COUNT; i++)
+			if (IS_E2_ONLINE(reg_addrs[i].info))
+				for (j = 0; j < reg_addrs[i].size; j++)
+					*p++ = REG_RD(bp,
+					      reg_addrs[i].addr + j*4);
+
+		bnx2x_read_pages_regs_e2(bp, p);
 	}
 }
 
-#define PHY_FW_VER_LEN			10
+#define PHY_FW_VER_LEN			20
 
 static void bnx2x_get_drvinfo(struct net_device *dev,
 			      struct ethtool_drvinfo *info)
@@ -436,7 +516,7 @@
 {
 	struct bnx2x *bp = netdev_priv(dev);
 
-	if (bp->flags & MF_FUNC_DIS)
+	if (bp->flags & MF_FUNC_DIS || (bp->state != BNX2X_STATE_OPEN))
 		return 0;
 
 	return bp->link_vars.link_up;
@@ -811,7 +891,7 @@
 	struct bnx2x *bp = netdev_priv(dev);
 	int port = BP_PORT(bp);
 	int rc = 0;
-
+	u32 ext_phy_config;
 	if (!netif_running(dev))
 		return -EAGAIN;
 
@@ -827,6 +907,10 @@
 	    !bp->port.pmf)
 		return -EINVAL;
 
+	ext_phy_config =
+		SHMEM_RD(bp,
+			 dev_info.port_hw_config[port].external_phy_config);
+
 	if (eeprom->magic == 0x50485950) {
 		/* 'PHYP' (0x50485950): prepare phy for FW upgrade */
 		bnx2x_stats_handle(bp, STATS_EVENT_STOP);
@@ -834,7 +918,7 @@
 		bnx2x_acquire_phy_lock(bp);
 		rc |= bnx2x_link_reset(&bp->link_params,
 				       &bp->link_vars, 0);
-		if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) ==
+		if (XGXS_EXT_PHY_TYPE(ext_phy_config) ==
 					PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101)
 			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
 				       MISC_REGISTERS_GPIO_HIGH, port);
@@ -855,10 +939,8 @@
 		}
 	} else if (eeprom->magic == 0x53985943) {
 		/* 'PHYC' (0x53985943): PHY FW upgrade completed */
-		if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) ==
+		if (XGXS_EXT_PHY_TYPE(ext_phy_config) ==
 				       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) {
-			u8 ext_phy_addr =
-			     XGXS_EXT_PHY_ADDR(bp->link_params.ext_phy_config);
 
 			/* DSP Remove Download Mode */
 			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
@@ -866,7 +948,8 @@
 
 			bnx2x_acquire_phy_lock(bp);
 
-			bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
+			bnx2x_sfx7101_sp_sw_reset(bp,
+						&bp->link_params.phy[EXT_PHY1]);
 
 			/* wait 0.5 sec to allow it to run */
 			msleep(500);
@@ -879,6 +962,7 @@
 
 	return rc;
 }
+
 static int bnx2x_get_coalesce(struct net_device *dev,
 			      struct ethtool_coalesce *coal)
 {
@@ -920,7 +1004,14 @@
 	ering->rx_mini_max_pending = 0;
 	ering->rx_jumbo_max_pending = 0;
 
-	ering->rx_pending = bp->rx_ring_size;
+	if (bp->rx_ring_size)
+		ering->rx_pending = bp->rx_ring_size;
+	else
+		if (bp->state == BNX2X_STATE_OPEN && bp->num_queues)
+			ering->rx_pending = MAX_RX_AVAIL/bp->num_queues;
+		else
+			ering->rx_pending = MAX_RX_AVAIL;
+
 	ering->rx_mini_pending = 0;
 	ering->rx_jumbo_pending = 0;
 
@@ -940,6 +1031,7 @@
 	}
 
 	if ((ering->rx_pending > MAX_RX_AVAIL) ||
+	    (ering->rx_pending < MIN_RX_AVAIL) ||
 	    (ering->tx_pending > MAX_TX_AVAIL) ||
 	    (ering->tx_pending <= MAX_SKB_FRAGS + 4))
 		return -EINVAL;
@@ -959,10 +1051,9 @@
 				 struct ethtool_pauseparam *epause)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-
-	epause->autoneg = (bp->link_params.req_flow_ctrl ==
-			   BNX2X_FLOW_CTRL_AUTO) &&
-			  (bp->link_params.req_line_speed == SPEED_AUTO_NEG);
+	int cfg_idx = bnx2x_get_link_cfg_idx(bp);
+	epause->autoneg = (bp->link_params.req_flow_ctrl[cfg_idx] ==
+			   BNX2X_FLOW_CTRL_AUTO);
 
 	epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) ==
 			    BNX2X_FLOW_CTRL_RX);
@@ -978,37 +1069,39 @@
 				struct ethtool_pauseparam *epause)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-
-	if (IS_E1HMF(bp))
+	u32 cfg_idx = bnx2x_get_link_cfg_idx(bp);
+	if (IS_MF(bp))
 		return 0;
 
 	DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
 	   DP_LEVEL "  autoneg %d  rx_pause %d  tx_pause %d\n",
 	   epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
 
-	bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
+	bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_AUTO;
 
 	if (epause->rx_pause)
-		bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_RX;
+		bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_RX;
 
 	if (epause->tx_pause)
-		bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_TX;
+		bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_TX;
 
-	if (bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
-		bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+	if (bp->link_params.req_flow_ctrl[cfg_idx] == BNX2X_FLOW_CTRL_AUTO)
+		bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_NONE;
 
 	if (epause->autoneg) {
-		if (!(bp->port.supported & SUPPORTED_Autoneg)) {
+		if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) {
 			DP(NETIF_MSG_LINK, "autoneg not supported\n");
 			return -EINVAL;
 		}
 
-		if (bp->link_params.req_line_speed == SPEED_AUTO_NEG)
-			bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
+		if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG) {
+			bp->link_params.req_flow_ctrl[cfg_idx] =
+				BNX2X_FLOW_CTRL_AUTO;
+		}
 	}
 
 	DP(NETIF_MSG_LINK,
-	   "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl);
+	   "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl[cfg_idx]);
 
 	if (netif_running(dev)) {
 		bnx2x_stats_handle(bp, STATS_EVENT_STOP);
@@ -1024,35 +1117,34 @@
 	int changed = 0;
 	int rc = 0;
 
-	if (data & ~(ETH_FLAG_LRO | ETH_FLAG_RXHASH))
-		return -EINVAL;
-
 	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
 		printk(KERN_ERR "Handling parity error recovery. Try again later\n");
 		return -EAGAIN;
 	}
 
+	if (!(data & ETH_FLAG_RXVLAN))
+		return -EINVAL;
+
+	if ((data & ETH_FLAG_LRO) && bp->rx_csum && bp->disable_tpa)
+		return -EINVAL;
+
+	rc = ethtool_op_set_flags(dev, data, ETH_FLAG_LRO | ETH_FLAG_RXVLAN |
+					ETH_FLAG_TXVLAN | ETH_FLAG_RXHASH);
+	if (rc)
+		return rc;
+
 	/* TPA requires Rx CSUM offloading */
 	if ((data & ETH_FLAG_LRO) && bp->rx_csum) {
-		if (!bp->disable_tpa) {
-			if (!(dev->features & NETIF_F_LRO)) {
-				dev->features |= NETIF_F_LRO;
-				bp->flags |= TPA_ENABLE_FLAG;
-				changed = 1;
-			}
-		} else
-			rc = -EINVAL;
-	} else if (dev->features & NETIF_F_LRO) {
+		if (!(bp->flags & TPA_ENABLE_FLAG)) {
+			bp->flags |= TPA_ENABLE_FLAG;
+			changed = 1;
+		}
+	} else if (bp->flags & TPA_ENABLE_FLAG) {
 		dev->features &= ~NETIF_F_LRO;
 		bp->flags &= ~TPA_ENABLE_FLAG;
 		changed = 1;
 	}
 
-	if (data & ETH_FLAG_RXHASH)
-		dev->features |= NETIF_F_RXHASH;
-	else
-		dev->features &= ~NETIF_F_RXHASH;
-
 	if (changed && netif_running(dev)) {
 		bnx2x_nic_unload(bp, UNLOAD_NORMAL);
 		rc = bnx2x_nic_load(bp, LOAD_NORMAL);
@@ -1185,6 +1277,9 @@
 
 		for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) {
 			u32 offset, mask, save_val, val;
+			if (CHIP_IS_E2(bp) &&
+			    reg_tbl[i].offset0 == HC_REG_AGG_INT_0)
+				continue;
 
 			offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1;
 			mask = reg_tbl[i].mask;
@@ -1192,6 +1287,7 @@
 			save_val = REG_RD(bp, offset);
 
 			REG_WR(bp, offset, (wr_val & mask));
+
 			val = REG_RD(bp, offset);
 
 			/* Restore the original register's value */
@@ -1236,20 +1332,33 @@
 		u32 offset;
 		u32 e1_mask;
 		u32 e1h_mask;
+		u32 e2_mask;
 	} prty_tbl[] = {
-		{ "CCM_PRTY_STS",  CCM_REG_CCM_PRTY_STS,   0x3ffc0, 0 },
-		{ "CFC_PRTY_STS",  CFC_REG_CFC_PRTY_STS,   0x2,     0x2 },
-		{ "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0,       0 },
-		{ "TCM_PRTY_STS",  TCM_REG_TCM_PRTY_STS,   0x3ffc0, 0 },
-		{ "UCM_PRTY_STS",  UCM_REG_UCM_PRTY_STS,   0x3ffc0, 0 },
-		{ "XCM_PRTY_STS",  XCM_REG_XCM_PRTY_STS,   0x3ffc1, 0 },
+		{ "CCM_PRTY_STS",  CCM_REG_CCM_PRTY_STS,   0x3ffc0, 0,   0 },
+		{ "CFC_PRTY_STS",  CFC_REG_CFC_PRTY_STS,   0x2,     0x2, 0 },
+		{ "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0,       0,   0 },
+		{ "TCM_PRTY_STS",  TCM_REG_TCM_PRTY_STS,   0x3ffc0, 0,   0 },
+		{ "UCM_PRTY_STS",  UCM_REG_UCM_PRTY_STS,   0x3ffc0, 0,   0 },
+		{ "XCM_PRTY_STS",  XCM_REG_XCM_PRTY_STS,   0x3ffc1, 0,   0 },
 
-		{ NULL, 0xffffffff, 0, 0 }
+		{ NULL, 0xffffffff, 0, 0, 0 }
 	};
 
 	if (!netif_running(bp->dev))
 		return rc;
 
+	/* pre-Check the parity status */
+	for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
+		val = REG_RD(bp, prty_tbl[i].offset);
+		if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
+		    (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
+		    (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
+			DP(NETIF_MSG_HW,
+			   "%s is 0x%x\n", prty_tbl[i].name, val);
+			goto test_mem_exit;
+		}
+	}
+
 	/* Go through all the memories */
 	for (i = 0; mem_tbl[i].offset != 0xffffffff; i++)
 		for (j = 0; j < mem_tbl[i].size; j++)
@@ -1259,7 +1368,8 @@
 	for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
 		val = REG_RD(bp, prty_tbl[i].offset);
 		if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
-		    (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask)))) {
+		    (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
+		    (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
 			DP(NETIF_MSG_HW,
 			   "%s is 0x%x\n", prty_tbl[i].name, val);
 			goto test_mem_exit;
@@ -1272,12 +1382,12 @@
 	return rc;
 }
 
-static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up)
+static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up, u8 is_serdes)
 {
-	int cnt = 1000;
+	int cnt = 1400;
 
 	if (link_up)
-		while (bnx2x_link_test(bp) && cnt--)
+		while (bnx2x_link_test(bp, is_serdes) && cnt--)
 			msleep(10);
 }
 
@@ -1293,7 +1403,8 @@
 	u16 pkt_prod, bd_prod;
 	struct sw_tx_bd *tx_buf;
 	struct eth_tx_start_bd *tx_start_bd;
-	struct eth_tx_parse_bd *pbd = NULL;
+	struct eth_tx_parse_bd_e1x  *pbd_e1x = NULL;
+	struct eth_tx_parse_bd_e2  *pbd_e2 = NULL;
 	dma_addr_t mapping;
 	union eth_rx_cqe *cqe;
 	u8 cqe_fp_flags;
@@ -1304,7 +1415,7 @@
 	/* check the loopback mode */
 	switch (loopback_mode) {
 	case BNX2X_PHY_LOOPBACK:
-		if (bp->link_params.loopback_mode != LOOPBACK_XGXS_10)
+		if (bp->link_params.loopback_mode != LOOPBACK_XGXS)
 			return -EINVAL;
 		break;
 	case BNX2X_MAC_LOOPBACK:
@@ -1349,16 +1460,23 @@
 	tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
 	tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */
 	tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb));
-	tx_start_bd->vlan = cpu_to_le16(pkt_prod);
+	tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
 	tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
-	tx_start_bd->general_data = ((UNICAST_ADDRESS <<
-				ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT) | 1);
+	SET_FLAG(tx_start_bd->general_data,
+		 ETH_TX_START_BD_ETH_ADDR_TYPE,
+		 UNICAST_ADDRESS);
+	SET_FLAG(tx_start_bd->general_data,
+		 ETH_TX_START_BD_HDR_NBDS,
+		 1);
 
 	/* turn on parsing and get a BD */
 	bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
-	pbd = &fp_tx->tx_desc_ring[bd_prod].parse_bd;
 
-	memset(pbd, 0, sizeof(struct eth_tx_parse_bd));
+	pbd_e1x = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e1x;
+	pbd_e2 = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e2;
+
+	memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
+	memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
 
 	wmb();
 
@@ -1377,6 +1495,13 @@
 	if (tx_idx != tx_start_idx + num_pkts)
 		goto test_loopback_exit;
 
+	/* Unlike HC IGU won't generate an interrupt for status block
+	 * updates that have been performed while interrupts were
+	 * disabled.
+	 */
+	if (bp->common.int_block == INT_BLOCK_IGU)
+		bnx2x_tx_int(fp_tx);
+
 	rx_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
 	if (rx_idx != rx_start_idx + num_pkts)
 		goto test_loopback_exit;
@@ -1519,8 +1644,7 @@
 
 	config->hdr.length = 0;
 	if (CHIP_IS_E1(bp))
-		/* use last unicast entries */
-		config->hdr.offset = (BP_PORT(bp) ? 63 : 31);
+		config->hdr.offset = (BP_PORT(bp) ? 32 : 0);
 	else
 		config->hdr.offset = BP_FUNC(bp);
 	config->hdr.client_id = bp->fp->cl_id;
@@ -1528,9 +1652,9 @@
 
 	bp->set_mac_pending++;
 	smp_wmb();
-	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
+	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
 			   U64_HI(bnx2x_sp_mapping(bp, mac_config)),
-			   U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0);
+			   U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
 	if (rc == 0) {
 		for (i = 0; i < 10; i++) {
 			if (!bp->set_mac_pending)
@@ -1549,7 +1673,7 @@
 			    struct ethtool_test *etest, u64 *buf)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-
+	u8 is_serdes;
 	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
 		printk(KERN_ERR "Handling parity error recovery. Try again later\n");
 		etest->flags |= ETH_TEST_FL_FAILED;
@@ -1562,8 +1686,9 @@
 		return;
 
 	/* offline tests are not supported in MF mode */
-	if (IS_E1HMF(bp))
+	if (IS_MF(bp))
 		etest->flags &= ~ETH_TEST_FL_OFFLINE;
+	is_serdes = (bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) > 0;
 
 	if (etest->flags & ETH_TEST_FL_OFFLINE) {
 		int port = BP_PORT(bp);
@@ -1575,11 +1700,12 @@
 		/* disable input for TX port IF */
 		REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0);
 
-		link_up = (bnx2x_link_test(bp) == 0);
+		link_up = bp->link_vars.link_up;
+
 		bnx2x_nic_unload(bp, UNLOAD_NORMAL);
 		bnx2x_nic_load(bp, LOAD_DIAG);
 		/* wait until link state is restored */
-		bnx2x_wait_for_link(bp, link_up);
+		bnx2x_wait_for_link(bp, link_up, is_serdes);
 
 		if (bnx2x_test_registers(bp) != 0) {
 			buf[0] = 1;
@@ -1589,6 +1715,7 @@
 			buf[1] = 1;
 			etest->flags |= ETH_TEST_FL_FAILED;
 		}
+
 		buf[2] = bnx2x_test_loopback(bp, link_up);
 		if (buf[2] != 0)
 			etest->flags |= ETH_TEST_FL_FAILED;
@@ -1600,7 +1727,7 @@
 
 		bnx2x_nic_load(bp, LOAD_NORMAL);
 		/* wait until link state is restored */
-		bnx2x_wait_for_link(bp, link_up);
+		bnx2x_wait_for_link(bp, link_up, is_serdes);
 	}
 	if (bnx2x_test_nvram(bp) != 0) {
 		buf[3] = 1;
@@ -1611,7 +1738,7 @@
 		etest->flags |= ETH_TEST_FL_FAILED;
 	}
 	if (bp->port.pmf)
-		if (bnx2x_link_test(bp) != 0) {
+		if (bnx2x_link_test(bp, is_serdes) != 0) {
 			buf[5] = 1;
 			etest->flags |= ETH_TEST_FL_FAILED;
 		}
@@ -1752,8 +1879,8 @@
 #define IS_PORT_STAT(i) \
 	((bnx2x_stats_arr[i].flags & STATS_FLAGS_BOTH) == STATS_FLAGS_PORT)
 #define IS_FUNC_STAT(i)		(bnx2x_stats_arr[i].flags & STATS_FLAGS_FUNC)
-#define IS_E1HMF_MODE_STAT(bp) \
-			(IS_E1HMF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS))
+#define IS_MF_MODE_STAT(bp) \
+			(IS_MF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS))
 
 static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
 {
@@ -1764,10 +1891,10 @@
 	case ETH_SS_STATS:
 		if (is_multi(bp)) {
 			num_stats = BNX2X_NUM_Q_STATS * bp->num_queues;
-			if (!IS_E1HMF_MODE_STAT(bp))
+			if (!IS_MF_MODE_STAT(bp))
 				num_stats += BNX2X_NUM_STATS;
 		} else {
-			if (IS_E1HMF_MODE_STAT(bp)) {
+			if (IS_MF_MODE_STAT(bp)) {
 				num_stats = 0;
 				for (i = 0; i < BNX2X_NUM_STATS; i++)
 					if (IS_FUNC_STAT(i))
@@ -1800,14 +1927,14 @@
 						bnx2x_q_stats_arr[j].string, i);
 				k += BNX2X_NUM_Q_STATS;
 			}
-			if (IS_E1HMF_MODE_STAT(bp))
+			if (IS_MF_MODE_STAT(bp))
 				break;
 			for (j = 0; j < BNX2X_NUM_STATS; j++)
 				strcpy(buf + (k + j)*ETH_GSTRING_LEN,
 				       bnx2x_stats_arr[j].string);
 		} else {
 			for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
-				if (IS_E1HMF_MODE_STAT(bp) && IS_PORT_STAT(i))
+				if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
 					continue;
 				strcpy(buf + j*ETH_GSTRING_LEN,
 				       bnx2x_stats_arr[i].string);
@@ -1851,7 +1978,7 @@
 			}
 			k += BNX2X_NUM_Q_STATS;
 		}
-		if (IS_E1HMF_MODE_STAT(bp))
+		if (IS_MF_MODE_STAT(bp))
 			return;
 		hw_stats = (u32 *)&bp->eth_stats;
 		for (j = 0; j < BNX2X_NUM_STATS; j++) {
@@ -1872,7 +1999,7 @@
 	} else {
 		hw_stats = (u32 *)&bp->eth_stats;
 		for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
-			if (IS_E1HMF_MODE_STAT(bp) && IS_PORT_STAT(i))
+			if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
 				continue;
 			if (bnx2x_stats_arr[i].size == 0) {
 				/* skip this counter */
@@ -1910,10 +2037,11 @@
 
 	for (i = 0; i < (data * 2); i++) {
 		if ((i % 2) == 0)
-			bnx2x_set_led(&bp->link_params, LED_MODE_OPER,
-				      SPEED_1000);
+			bnx2x_set_led(&bp->link_params, &bp->link_vars,
+				      LED_MODE_OPER, SPEED_1000);
 		else
-			bnx2x_set_led(&bp->link_params, LED_MODE_OFF, 0);
+			bnx2x_set_led(&bp->link_params, &bp->link_vars,
+				      LED_MODE_OFF, 0);
 
 		msleep_interruptible(500);
 		if (signal_pending(current))
@@ -1921,7 +2049,7 @@
 	}
 
 	if (bp->link_vars.link_up)
-		bnx2x_set_led(&bp->link_params, LED_MODE_OPER,
+		bnx2x_set_led(&bp->link_params, &bp->link_vars, LED_MODE_OPER,
 			      bp->link_vars.line_speed);
 
 	return 0;
diff --git a/drivers/net/bnx2x/bnx2x_fw_defs.h b/drivers/net/bnx2x/bnx2x_fw_defs.h
index 08d71bf..f4e5b1c 100644
--- a/drivers/net/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/bnx2x/bnx2x_fw_defs.h
@@ -7,369 +7,272 @@
  * the Free Software Foundation.
  */
 
+#ifndef BNX2X_FW_DEFS_H
+#define BNX2X_FW_DEFS_H
 
-#define CSTORM_ASSERT_LIST_INDEX_OFFSET \
-	(IS_E1H_OFFSET ? 0x7000 : 0x1000)
-#define CSTORM_ASSERT_LIST_OFFSET(idx) \
-	(IS_E1H_OFFSET ? (0x7020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
-#define CSTORM_DEF_SB_HC_DISABLE_C_OFFSET(function, index) \
-	(IS_E1H_OFFSET ? (0x8622 + ((function>>1) * 0x40) + \
-	((function&1) * 0x100) + (index * 0x4)) : (0x3562 + (function * \
-	0x40) + (index * 0x4)))
-#define CSTORM_DEF_SB_HC_DISABLE_U_OFFSET(function, index) \
-	(IS_E1H_OFFSET ? (0x8822 + ((function>>1) * 0x80) + \
-	((function&1) * 0x200) + (index * 0x4)) : (0x35e2 + (function * \
-	0x80) + (index * 0x4)))
-#define CSTORM_DEF_SB_HOST_SB_ADDR_C_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8600 + ((function>>1) * 0x40) + \
-	((function&1) * 0x100)) : (0x3540 + (function * 0x40)))
-#define CSTORM_DEF_SB_HOST_SB_ADDR_U_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8800 + ((function>>1) * 0x80) + \
-	((function&1) * 0x200)) : (0x35c0 + (function * 0x80)))
-#define CSTORM_DEF_SB_HOST_STATUS_BLOCK_C_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8608 + ((function>>1) * 0x40) + \
-	((function&1) * 0x100)) : (0x3548 + (function * 0x40)))
-#define CSTORM_DEF_SB_HOST_STATUS_BLOCK_U_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8808 + ((function>>1) * 0x80) + \
-	((function&1) * 0x200)) : (0x35c8 + (function * 0x80)))
-#define CSTORM_FUNCTION_MODE_OFFSET \
-	(IS_E1H_OFFSET ? 0x11e8 : 0xffffffff)
-#define CSTORM_HC_BTR_C_OFFSET(port) \
-	(IS_E1H_OFFSET ? (0x8c04 + (port * 0xf0)) : (0x36c4 + (port * 0xc0)))
-#define CSTORM_HC_BTR_U_OFFSET(port) \
-	(IS_E1H_OFFSET ? (0x8de4 + (port * 0xf0)) : (0x3844 + (port * 0xc0)))
-#define CSTORM_ISCSI_CQ_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6680 + (function * 0x8)) : (0x25a0 + \
-	(function * 0x8)))
-#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x66c0 + (function * 0x8)) : (0x25b0 + \
-	(function * 0x8)))
-#define CSTORM_ISCSI_EQ_CONS_OFFSET(function, eqIdx) \
-	(IS_E1H_OFFSET ? (0x6040 + (function * 0xc0) + (eqIdx * 0x18)) : \
-	(0x2410 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(function, eqIdx) \
-	(IS_E1H_OFFSET ? (0x6044 + (function * 0xc0) + (eqIdx * 0x18)) : \
-	(0x2414 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(function, eqIdx) \
-	(IS_E1H_OFFSET ? (0x604c + (function * 0xc0) + (eqIdx * 0x18)) : \
-	(0x241c + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(function, eqIdx) \
-	(IS_E1H_OFFSET ? (0x6057 + (function * 0xc0) + (eqIdx * 0x18)) : \
-	(0x2427 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_PROD_OFFSET(function, eqIdx) \
-	(IS_E1H_OFFSET ? (0x6042 + (function * 0xc0) + (eqIdx * 0x18)) : \
-	(0x2412 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(function, eqIdx) \
-	(IS_E1H_OFFSET ? (0x6056 + (function * 0xc0) + (eqIdx * 0x18)) : \
-	(0x2426 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(function, eqIdx) \
-	(IS_E1H_OFFSET ? (0x6054 + (function * 0xc0) + (eqIdx * 0x18)) : \
-	(0x2424 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_HQ_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6640 + (function * 0x8)) : (0x2590 + \
-	(function * 0x8)))
-#define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6004 + (function * 0x8)) : (0x2404 + \
-	(function * 0x8)))
-#define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6002 + (function * 0x8)) : (0x2402 + \
-	(function * 0x8)))
-#define CSTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6000 + (function * 0x8)) : (0x2400 + \
-	(function * 0x8)))
-#define CSTORM_SB_HC_DISABLE_C_OFFSET(port, cpu_id, index) \
-	(IS_E1H_OFFSET ? (0x811a + (port * 0x280) + (cpu_id * 0x28) + \
-	(index * 0x4)) : (0x305a + (port * 0x280) + (cpu_id * 0x28) + \
-	(index * 0x4)))
-#define CSTORM_SB_HC_DISABLE_U_OFFSET(port, cpu_id, index) \
-	(IS_E1H_OFFSET ? (0xb01a + (port * 0x800) + (cpu_id * 0x80) + \
-	(index * 0x4)) : (0x401a + (port * 0x800) + (cpu_id * 0x80) + \
-	(index * 0x4)))
-#define CSTORM_SB_HC_TIMEOUT_C_OFFSET(port, cpu_id, index) \
-	(IS_E1H_OFFSET ? (0x8118 + (port * 0x280) + (cpu_id * 0x28) + \
-	(index * 0x4)) : (0x3058 + (port * 0x280) + (cpu_id * 0x28) + \
-	(index * 0x4)))
-#define CSTORM_SB_HC_TIMEOUT_U_OFFSET(port, cpu_id, index) \
-	(IS_E1H_OFFSET ? (0xb018 + (port * 0x800) + (cpu_id * 0x80) + \
-	(index * 0x4)) : (0x4018 + (port * 0x800) + (cpu_id * 0x80) + \
-	(index * 0x4)))
-#define CSTORM_SB_HOST_SB_ADDR_C_OFFSET(port, cpu_id) \
-	(IS_E1H_OFFSET ? (0x8100 + (port * 0x280) + (cpu_id * 0x28)) : \
-	(0x3040 + (port * 0x280) + (cpu_id * 0x28)))
-#define CSTORM_SB_HOST_SB_ADDR_U_OFFSET(port, cpu_id) \
-	(IS_E1H_OFFSET ? (0xb000 + (port * 0x800) + (cpu_id * 0x80)) : \
-	(0x4000 + (port * 0x800) + (cpu_id * 0x80)))
-#define CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, cpu_id) \
-	(IS_E1H_OFFSET ? (0x8108 + (port * 0x280) + (cpu_id * 0x28)) : \
-	(0x3048 + (port * 0x280) + (cpu_id * 0x28)))
-#define CSTORM_SB_HOST_STATUS_BLOCK_U_OFFSET(port, cpu_id) \
-	(IS_E1H_OFFSET ? (0xb008 + (port * 0x800) + (cpu_id * 0x80)) : \
-	(0x4008 + (port * 0x800) + (cpu_id * 0x80)))
-#define CSTORM_SB_STATUS_BLOCK_C_SIZE 0x10
-#define CSTORM_SB_STATUS_BLOCK_U_SIZE 0x60
-#define CSTORM_STATS_FLAGS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x1108 + (function * 0x8)) : (0x5108 + \
-	(function * 0x8)))
-#define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x3200 + (function * 0x20)) : 0xffffffff)
-#define TSTORM_ASSERT_LIST_INDEX_OFFSET \
-	(IS_E1H_OFFSET ? 0xa000 : 0x1000)
-#define TSTORM_ASSERT_LIST_OFFSET(idx) \
-	(IS_E1H_OFFSET ? (0xa020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
-#define TSTORM_CLIENT_CONFIG_OFFSET(port, client_id) \
-	(IS_E1H_OFFSET ? (0x33a0 + (port * 0x1a0) + (client_id * 0x10)) \
-	: (0x9c0 + (port * 0x120) + (client_id * 0x10)))
-#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET \
-	(IS_E1H_OFFSET ? 0x1ed8 : 0xffffffff)
+#define CSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[142].base)
+#define CSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
+	(IRO[141].base + ((assertListEntry) * IRO[141].m1))
+#define CSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
+	(IRO[144].base + ((pfId) * IRO[144].m1))
+#define CSTORM_EVENT_RING_DATA_OFFSET(pfId) \
+	(IRO[149].base + (((pfId)>>1) * IRO[149].m1) + (((pfId)&1) * \
+	IRO[149].m2))
+#define CSTORM_EVENT_RING_PROD_OFFSET(pfId) \
+	(IRO[150].base + (((pfId)>>1) * IRO[150].m1) + (((pfId)&1) * \
+	IRO[150].m2))
+#define CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(funcId) \
+	(IRO[156].base + ((funcId) * IRO[156].m1))
+#define CSTORM_FUNC_EN_OFFSET(funcId) \
+	(IRO[146].base + ((funcId) * IRO[146].m1))
+#define CSTORM_FUNCTION_MODE_OFFSET (IRO[153].base)
+#define CSTORM_IGU_MODE_OFFSET (IRO[154].base)
+#define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
+	(IRO[311].base + ((pfId) * IRO[311].m1))
+#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
+	(IRO[312].base + ((pfId) * IRO[312].m1))
+	#define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
+	(IRO[304].base + ((pfId) * IRO[304].m1) + ((iscsiEqId) * \
+	IRO[304].m2))
+	#define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
+	(IRO[306].base + ((pfId) * IRO[306].m1) + ((iscsiEqId) * \
+	IRO[306].m2))
+	#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
+	(IRO[305].base + ((pfId) * IRO[305].m1) + ((iscsiEqId) * \
+	IRO[305].m2))
+	#define \
+	CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
+	(IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * \
+	IRO[307].m2))
+	#define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
+	(IRO[303].base + ((pfId) * IRO[303].m1) + ((iscsiEqId) * \
+	IRO[303].m2))
+	#define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
+	(IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * \
+	IRO[309].m2))
+	#define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
+	(IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * \
+	IRO[308].m2))
+#define CSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
+	(IRO[310].base + ((pfId) * IRO[310].m1))
+#define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+	(IRO[302].base + ((pfId) * IRO[302].m1))
+#define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+	(IRO[301].base + ((pfId) * IRO[301].m1))
+#define CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+	(IRO[300].base + ((pfId) * IRO[300].m1))
+#define CSTORM_PATH_ID_OFFSET (IRO[159].base)
+#define CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(pfId) \
+	(IRO[137].base + ((pfId) * IRO[137].m1))
+#define CSTORM_SP_STATUS_BLOCK_OFFSET(pfId) \
+	(IRO[136].base + ((pfId) * IRO[136].m1))
+#define CSTORM_SP_STATUS_BLOCK_SIZE (IRO[136].size)
+#define CSTORM_SP_SYNC_BLOCK_OFFSET(pfId) \
+	(IRO[138].base + ((pfId) * IRO[138].m1))
+#define CSTORM_SP_SYNC_BLOCK_SIZE (IRO[138].size)
+#define CSTORM_STATS_FLAGS_OFFSET(pfId) \
+	(IRO[143].base + ((pfId) * IRO[143].m1))
+#define CSTORM_STATUS_BLOCK_DATA_OFFSET(sbId) \
+	(IRO[129].base + ((sbId) * IRO[129].m1))
+#define CSTORM_STATUS_BLOCK_OFFSET(sbId) \
+	(IRO[128].base + ((sbId) * IRO[128].m1))
+#define CSTORM_STATUS_BLOCK_SIZE (IRO[128].size)
+#define CSTORM_SYNC_BLOCK_OFFSET(sbId) \
+	(IRO[132].base + ((sbId) * IRO[132].m1))
+#define CSTORM_SYNC_BLOCK_SIZE (IRO[132].size)
+#define CSTORM_VF_PF_CHANNEL_STATE_OFFSET(vfId) \
+	(IRO[151].base + ((vfId) * IRO[151].m1))
+#define CSTORM_VF_PF_CHANNEL_VALID_OFFSET(vfId) \
+	(IRO[152].base + ((vfId) * IRO[152].m1))
+#define CSTORM_VF_TO_PF_OFFSET(funcId) \
+	(IRO[147].base + ((funcId) * IRO[147].m1))
+#define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[199].base)
+#define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(pfId) \
+	(IRO[198].base + ((pfId) * IRO[198].m1))
+#define TSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[99].base)
+#define TSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
+	(IRO[98].base + ((assertListEntry) * IRO[98].m1))
+	#define TSTORM_CLIENT_CONFIG_OFFSET(portId, clientId) \
+	(IRO[197].base + ((portId) * IRO[197].m1) + ((clientId) * \
+	IRO[197].m2))
+#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET (IRO[104].base)
 #define TSTORM_COMMON_SAFC_WORKAROUND_TIMEOUT_10USEC_OFFSET \
-	(IS_E1H_OFFSET ? 0x1eda : 0xffffffff)
-#define TSTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
-	(IS_E1H_OFFSET ? (0xb01a + ((function>>1) * 0x28) + \
-	((function&1) * 0xa0) + (index * 0x4)) : (0x141a + (function * \
-	0x28) + (index * 0x4)))
-#define TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0xb000 + ((function>>1) * 0x28) + \
-	((function&1) * 0xa0)) : (0x1400 + (function * 0x28)))
-#define TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0xb008 + ((function>>1) * 0x28) + \
-	((function&1) * 0xa0)) : (0x1408 + (function * 0x28)))
-#define TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x2940 + (function * 0x8)) : (0x4928 + \
-	(function * 0x8)))
-#define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x3000 + (function * 0x40)) : (0x1500 + \
-	(function * 0x40)))
-#define TSTORM_FUNCTION_MODE_OFFSET \
-	(IS_E1H_OFFSET ? 0x1ed0 : 0xffffffff)
-#define TSTORM_HC_BTR_OFFSET(port) \
-	(IS_E1H_OFFSET ? (0xb144 + (port * 0x30)) : (0x1454 + (port * 0x18)))
-#define TSTORM_INDIRECTION_TABLE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x12c8 + (function * 0x80)) : (0x22c8 + \
-	(function * 0x80)))
-#define TSTORM_INDIRECTION_TABLE_SIZE 0x80
-#define TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(function, pblEntry) \
-	(IS_E1H_OFFSET ? (0x60c0 + (function * 0x40) + (pblEntry * 0x8)) \
-	: (0x4c30 + (function * 0x40) + (pblEntry * 0x8)))
-#define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6340 + (function * 0x8)) : (0x4cd0 + \
-	(function * 0x8)))
-#define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6004 + (function * 0x8)) : (0x4c04 + \
-	(function * 0x8)))
-#define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6002 + (function * 0x8)) : (0x4c02 + \
-	(function * 0x8)))
-#define TSTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6000 + (function * 0x8)) : (0x4c00 + \
-	(function * 0x8)))
-#define TSTORM_ISCSI_RQ_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6080 + (function * 0x8)) : (0x4c20 + \
-	(function * 0x8)))
-#define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6040 + (function * 0x8)) : (0x4c10 + \
-	(function * 0x8)))
-#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6042 + (function * 0x8)) : (0x4c12 + \
-	(function * 0x8)))
-#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x6044 + (function * 0x8)) : (0x4c14 + \
-	(function * 0x8)))
-#define TSTORM_MAC_FILTER_CONFIG_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x3008 + (function * 0x40)) : (0x1508 + \
-	(function * 0x40)))
-#define TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \
-	(IS_E1H_OFFSET ? (0x2010 + (port * 0x490) + (stats_counter_id * \
-	0x40)) : (0x4010 + (port * 0x490) + (stats_counter_id * 0x40)))
-#define TSTORM_STATS_FLAGS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x29c0 + (function * 0x8)) : (0x4948 + \
-	(function * 0x8)))
-#define TSTORM_TCP_MAX_CWND_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x4004 + (function * 0x8)) : (0x1fb4 + \
-	(function * 0x8)))
-#define USTORM_AGG_DATA_OFFSET (IS_E1H_OFFSET ? 0xa000 : 0x3000)
-#define USTORM_AGG_DATA_SIZE (IS_E1H_OFFSET ? 0x2000 : 0x1000)
-#define USTORM_ASSERT_LIST_INDEX_OFFSET \
-	(IS_E1H_OFFSET ? 0x8000 : 0x1000)
-#define USTORM_ASSERT_LIST_OFFSET(idx) \
-	(IS_E1H_OFFSET ? (0x8020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
-#define USTORM_CQE_PAGE_BASE_OFFSET(port, clientId) \
-	(IS_E1H_OFFSET ? (0x1010 + (port * 0x680) + (clientId * 0x40)) : \
-	(0x4010 + (port * 0x360) + (clientId * 0x30)))
-#define USTORM_CQE_PAGE_NEXT_OFFSET(port, clientId) \
-	(IS_E1H_OFFSET ? (0x1028 + (port * 0x680) + (clientId * 0x40)) : \
-	(0x4028 + (port * 0x360) + (clientId * 0x30)))
-#define USTORM_ETH_PAUSE_ENABLED_OFFSET(port) \
-	(IS_E1H_OFFSET ? (0x2ad4 + (port * 0x8)) : 0xffffffff)
-#define USTORM_ETH_RING_PAUSE_DATA_OFFSET(port, clientId) \
-	(IS_E1H_OFFSET ? (0x1030 + (port * 0x680) + (clientId * 0x40)) : \
-	0xffffffff)
-#define USTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x2a50 + (function * 0x8)) : (0x1dd0 + \
-	(function * 0x8)))
-#define USTORM_FUNCTION_MODE_OFFSET \
-	(IS_E1H_OFFSET ? 0x2448 : 0xffffffff)
-#define USTORM_ISCSI_CQ_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x7044 + (function * 0x8)) : (0x2414 + \
-	(function * 0x8)))
-#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x7046 + (function * 0x8)) : (0x2416 + \
-	(function * 0x8)))
-#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x7688 + (function * 0x8)) : (0x29c8 + \
-	(function * 0x8)))
-#define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x7648 + (function * 0x8)) : (0x29b8 + \
-	(function * 0x8)))
-#define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x7004 + (function * 0x8)) : (0x2404 + \
-	(function * 0x8)))
-#define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x7002 + (function * 0x8)) : (0x2402 + \
-	(function * 0x8)))
-#define USTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x7000 + (function * 0x8)) : (0x2400 + \
-	(function * 0x8)))
-#define USTORM_ISCSI_R2TQ_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x7040 + (function * 0x8)) : (0x2410 + \
-	(function * 0x8)))
-#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x7080 + (function * 0x8)) : (0x2420 + \
-	(function * 0x8)))
-#define USTORM_ISCSI_RQ_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x7084 + (function * 0x8)) : (0x2424 + \
-	(function * 0x8)))
-#define USTORM_MAX_AGG_SIZE_OFFSET(port, clientId) \
-	(IS_E1H_OFFSET ? (0x1018 + (port * 0x680) + (clientId * 0x40)) : \
-	(0x4018 + (port * 0x360) + (clientId * 0x30)))
-#define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x2408 + (function * 0x8)) : (0x1da8 + \
-	(function * 0x8)))
-#define USTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \
-	(IS_E1H_OFFSET ? (0x2450 + (port * 0x2d0) + (stats_counter_id * \
-	0x28)) : (0x1500 + (port * 0x2d0) + (stats_counter_id * 0x28)))
-#define USTORM_RX_PRODS_OFFSET(port, client_id) \
-	(IS_E1H_OFFSET ? (0x1000 + (port * 0x680) + (client_id * 0x40)) \
-	: (0x4000 + (port * 0x360) + (client_id * 0x30)))
-#define USTORM_STATS_FLAGS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x29f0 + (function * 0x8)) : (0x1db8 + \
-	(function * 0x8)))
-#define USTORM_TPA_BTR_OFFSET (IS_E1H_OFFSET ? 0x3da5 : 0x5095)
-#define USTORM_TPA_BTR_SIZE 0x1
-#define XSTORM_ASSERT_LIST_INDEX_OFFSET \
-	(IS_E1H_OFFSET ? 0x9000 : 0x1000)
-#define XSTORM_ASSERT_LIST_OFFSET(idx) \
-	(IS_E1H_OFFSET ? (0x9020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
-#define XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) \
-	(IS_E1H_OFFSET ? (0x24a8 + (port * 0x50)) : (0x3a80 + (port * 0x50)))
-#define XSTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
-	(IS_E1H_OFFSET ? (0xa01a + ((function>>1) * 0x28) + \
-	((function&1) * 0xa0) + (index * 0x4)) : (0x141a + (function * \
-	0x28) + (index * 0x4)))
-#define XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0xa000 + ((function>>1) * 0x28) + \
-	((function&1) * 0xa0)) : (0x1400 + (function * 0x28)))
-#define XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0xa008 + ((function>>1) * 0x28) + \
-	((function&1) * 0xa0)) : (0x1408 + (function * 0x28)))
-#define XSTORM_E1HOV_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x2c10 + (function * 0x8)) : 0xffffffff)
-#define XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x2418 + (function * 0x8)) : (0x3a50 + \
-	(function * 0x8)))
-#define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x2588 + (function * 0x90)) : (0x3b60 + \
-	(function * 0x90)))
-#define XSTORM_FUNCTION_MODE_OFFSET \
-	(IS_E1H_OFFSET ? 0x2c50 : 0xffffffff)
-#define XSTORM_HC_BTR_OFFSET(port) \
-	(IS_E1H_OFFSET ? (0xa144 + (port * 0x30)) : (0x1454 + (port * 0x18)))
-#define XSTORM_ISCSI_HQ_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x80c0 + (function * 0x8)) : (0x1c30 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8080 + (function * 0x8)) : (0x1c20 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8081 + (function * 0x8)) : (0x1c21 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8082 + (function * 0x8)) : (0x1c22 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8083 + (function * 0x8)) : (0x1c23 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8084 + (function * 0x8)) : (0x1c24 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8085 + (function * 0x8)) : (0x1c25 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8086 + (function * 0x8)) : (0x1c26 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8004 + (function * 0x8)) : (0x1c04 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8002 + (function * 0x8)) : (0x1c02 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8000 + (function * 0x8)) : (0x1c00 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x80c4 + (function * 0x8)) : (0x1c34 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_SQ_SIZE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x80c2 + (function * 0x8)) : (0x1c32 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8043 + (function * 0x8)) : (0x1c13 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8042 + (function * 0x8)) : (0x1c12 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8041 + (function * 0x8)) : (0x1c11 + \
-	(function * 0x8)))
-#define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x8040 + (function * 0x8)) : (0x1c10 + \
-	(function * 0x8)))
-#define XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \
-	(IS_E1H_OFFSET ? (0xc000 + (port * 0x360) + (stats_counter_id * \
-	0x30)) : (0x3378 + (port * 0x360) + (stats_counter_id * 0x30)))
-#define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x2548 + (function * 0x90)) : (0x3b20 + \
-	(function * 0x90)))
-#define XSTORM_SPQ_PAGE_BASE_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x2000 + (function * 0x10)) : (0x3328 + \
-	(function * 0x10)))
-#define XSTORM_SPQ_PROD_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x2008 + (function * 0x10)) : (0x3330 + \
-	(function * 0x10)))
-#define XSTORM_STATS_FLAGS_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x23d8 + (function * 0x8)) : (0x3a40 + \
-	(function * 0x8)))
-#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(port) \
-	(IS_E1H_OFFSET ? (0x4000 + (port * 0x8)) : (0x1960 + (port * 0x8)))
-#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(port) \
-	(IS_E1H_OFFSET ? (0x4001 + (port * 0x8)) : (0x1961 + (port * 0x8)))
-#define XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(function) \
-	(IS_E1H_OFFSET ? (0x4060 + ((function>>1) * 0x8) + ((function&1) \
-	* 0x4)) : (0x1978 + (function * 0x4)))
+	(IRO[105].base)
+#define TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
+	(IRO[96].base + ((pfId) * IRO[96].m1))
+#define TSTORM_FUNC_EN_OFFSET(funcId) \
+	(IRO[101].base + ((funcId) * IRO[101].m1))
+#define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(pfId) \
+	(IRO[195].base + ((pfId) * IRO[195].m1))
+#define TSTORM_FUNCTION_MODE_OFFSET (IRO[103].base)
+#define TSTORM_INDIRECTION_TABLE_OFFSET(pfId) \
+	(IRO[91].base + ((pfId) * IRO[91].m1))
+#define TSTORM_INDIRECTION_TABLE_SIZE (IRO[91].size)
+	#define \
+	TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfId, iscsiConBufPblEntry) \
+	(IRO[260].base + ((pfId) * IRO[260].m1) + ((iscsiConBufPblEntry) \
+	* IRO[260].m2))
+#define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
+	(IRO[264].base + ((pfId) * IRO[264].m1))
+#define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \
+	(IRO[265].base + ((pfId) * IRO[265].m1))
+#define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \
+	(IRO[266].base + ((pfId) * IRO[266].m1))
+#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \
+	(IRO[267].base + ((pfId) * IRO[267].m1))
+#define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+	(IRO[263].base + ((pfId) * IRO[263].m1))
+#define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+	(IRO[262].base + ((pfId) * IRO[262].m1))
+#define TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+	(IRO[261].base + ((pfId) * IRO[261].m1))
+#define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
+	(IRO[259].base + ((pfId) * IRO[259].m1))
+#define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \
+	(IRO[269].base + ((pfId) * IRO[269].m1))
+#define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
+	(IRO[256].base + ((pfId) * IRO[256].m1))
+#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
+	(IRO[257].base + ((pfId) * IRO[257].m1))
+#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
+	(IRO[258].base + ((pfId) * IRO[258].m1))
+#define TSTORM_MAC_FILTER_CONFIG_OFFSET(pfId) \
+	(IRO[196].base + ((pfId) * IRO[196].m1))
+	#define TSTORM_PER_COUNTER_ID_STATS_OFFSET(portId, tStatCntId) \
+	(IRO[100].base + ((portId) * IRO[100].m1) + ((tStatCntId) * \
+	IRO[100].m2))
+#define TSTORM_STATS_FLAGS_OFFSET(pfId) \
+	(IRO[95].base + ((pfId) * IRO[95].m1))
+#define TSTORM_TCP_MAX_CWND_OFFSET(pfId) \
+	(IRO[211].base + ((pfId) * IRO[211].m1))
+#define TSTORM_VF_TO_PF_OFFSET(funcId) \
+	(IRO[102].base + ((funcId) * IRO[102].m1))
+#define USTORM_AGG_DATA_OFFSET (IRO[201].base)
+#define USTORM_AGG_DATA_SIZE (IRO[201].size)
+#define USTORM_ASSERT_LIST_INDEX_OFFSET (IRO[170].base)
+#define USTORM_ASSERT_LIST_OFFSET(assertListEntry) \
+	(IRO[169].base + ((assertListEntry) * IRO[169].m1))
+#define USTORM_ETH_PAUSE_ENABLED_OFFSET(portId) \
+	(IRO[178].base + ((portId) * IRO[178].m1))
+#define USTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
+	(IRO[172].base + ((pfId) * IRO[172].m1))
+#define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \
+	(IRO[313].base + ((pfId) * IRO[313].m1))
+#define USTORM_FUNC_EN_OFFSET(funcId) \
+	(IRO[174].base + ((funcId) * IRO[174].m1))
+#define USTORM_FUNCTION_MODE_OFFSET (IRO[177].base)
+#define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
+	(IRO[277].base + ((pfId) * IRO[277].m1))
+#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
+	(IRO[278].base + ((pfId) * IRO[278].m1))
+#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
+	(IRO[282].base + ((pfId) * IRO[282].m1))
+#define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \
+	(IRO[279].base + ((pfId) * IRO[279].m1))
+#define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+	(IRO[275].base + ((pfId) * IRO[275].m1))
+#define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+	(IRO[274].base + ((pfId) * IRO[274].m1))
+#define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+	(IRO[273].base + ((pfId) * IRO[273].m1))
+#define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
+	(IRO[276].base + ((pfId) * IRO[276].m1))
+#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
+	(IRO[280].base + ((pfId) * IRO[280].m1))
+#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
+	(IRO[281].base + ((pfId) * IRO[281].m1))
+#define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \
+	(IRO[176].base + ((pfId) * IRO[176].m1))
+	#define USTORM_PER_COUNTER_ID_STATS_OFFSET(portId, uStatCntId) \
+	(IRO[173].base + ((portId) * IRO[173].m1) + ((uStatCntId) * \
+	IRO[173].m2))
+	#define USTORM_RX_PRODS_E1X_OFFSET(portId, clientId) \
+	(IRO[204].base + ((portId) * IRO[204].m1) + ((clientId) * \
+	IRO[204].m2))
+#define USTORM_RX_PRODS_E2_OFFSET(qzoneId) \
+	(IRO[205].base + ((qzoneId) * IRO[205].m1))
+#define USTORM_STATS_FLAGS_OFFSET(pfId) \
+	(IRO[171].base + ((pfId) * IRO[171].m1))
+#define USTORM_TPA_BTR_OFFSET (IRO[202].base)
+#define USTORM_TPA_BTR_SIZE (IRO[202].size)
+#define USTORM_VF_TO_PF_OFFSET(funcId) \
+	(IRO[175].base + ((funcId) * IRO[175].m1))
+#define XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE (IRO[59].base)
+#define XSTORM_AGG_INT_FINAL_CLEANUP_INDEX (IRO[58].base)
+#define XSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[54].base)
+#define XSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
+	(IRO[53].base + ((assertListEntry) * IRO[53].m1))
+#define XSTORM_CMNG_PER_PORT_VARS_OFFSET(portId) \
+	(IRO[47].base + ((portId) * IRO[47].m1))
+#define XSTORM_E1HOV_OFFSET(pfId) \
+	(IRO[55].base + ((pfId) * IRO[55].m1))
+#define XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
+	(IRO[45].base + ((pfId) * IRO[45].m1))
+#define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(pfId) \
+	(IRO[49].base + ((pfId) * IRO[49].m1))
+#define XSTORM_FUNC_EN_OFFSET(funcId) \
+	(IRO[51].base + ((funcId) * IRO[51].m1))
+#define XSTORM_FUNCTION_MODE_OFFSET (IRO[56].base)
+#define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
+	(IRO[290].base + ((pfId) * IRO[290].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \
+	(IRO[293].base + ((pfId) * IRO[293].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
+	(IRO[294].base + ((pfId) * IRO[294].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
+	(IRO[295].base + ((pfId) * IRO[295].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
+	(IRO[296].base + ((pfId) * IRO[296].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
+	(IRO[297].base + ((pfId) * IRO[297].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
+	(IRO[298].base + ((pfId) * IRO[298].m1))
+#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
+	(IRO[299].base + ((pfId) * IRO[299].m1))
+#define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+	(IRO[289].base + ((pfId) * IRO[289].m1))
+#define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+	(IRO[288].base + ((pfId) * IRO[288].m1))
+#define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+	(IRO[287].base + ((pfId) * IRO[287].m1))
+#define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
+	(IRO[292].base + ((pfId) * IRO[292].m1))
+#define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \
+	(IRO[291].base + ((pfId) * IRO[291].m1))
+#define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \
+	(IRO[286].base + ((pfId) * IRO[286].m1))
+#define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
+	(IRO[285].base + ((pfId) * IRO[285].m1))
+#define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \
+	(IRO[284].base + ((pfId) * IRO[284].m1))
+#define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \
+	(IRO[283].base + ((pfId) * IRO[283].m1))
+#define XSTORM_PATH_ID_OFFSET (IRO[65].base)
+	#define XSTORM_PER_COUNTER_ID_STATS_OFFSET(portId, xStatCntId) \
+	(IRO[50].base + ((portId) * IRO[50].m1) + ((xStatCntId) * \
+	IRO[50].m2))
+#define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(pfId) \
+	(IRO[48].base + ((pfId) * IRO[48].m1))
+#define XSTORM_SPQ_DATA_OFFSET(funcId) \
+	(IRO[32].base + ((funcId) * IRO[32].m1))
+#define XSTORM_SPQ_DATA_SIZE (IRO[32].size)
+#define XSTORM_SPQ_PAGE_BASE_OFFSET(funcId) \
+	(IRO[30].base + ((funcId) * IRO[30].m1))
+#define XSTORM_SPQ_PROD_OFFSET(funcId) \
+	(IRO[31].base + ((funcId) * IRO[31].m1))
+#define XSTORM_STATS_FLAGS_OFFSET(pfId) \
+	(IRO[43].base + ((pfId) * IRO[43].m1))
+#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(portId) \
+	(IRO[206].base + ((portId) * IRO[206].m1))
+#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(portId) \
+	(IRO[207].base + ((portId) * IRO[207].m1))
+#define XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(pfId) \
+	(IRO[209].base + (((pfId)>>1) * IRO[209].m1) + (((pfId)&1) * \
+	IRO[209].m2))
+#define XSTORM_VF_TO_PF_OFFSET(funcId) \
+	(IRO[52].base + ((funcId) * IRO[52].m1))
 #define COMMON_ASM_INVALID_ASSERT_OPCODE 0x0
 
-/**
-* This file defines HSI constants for the ETH flow
-*/
-#ifdef _EVEREST_MICROCODE
-#include "microcode_constants.h"
-#include "eth_rx_bd.h"
-#include "eth_tx_bd.h"
-#include "eth_rx_cqe.h"
-#include "eth_rx_sge.h"
-#include "eth_rx_cqe_next_page.h"
-#endif
-
 /* RSS hash types */
 #define DEFAULT_HASH_TYPE 0
 #define IPV4_HASH_TYPE 1
@@ -389,11 +292,17 @@
 #define U_ETH_NUM_OF_SGES_TO_FETCH 8
 #define U_ETH_MAX_SGES_FOR_PACKET 3
 
+/*Tx params*/
+#define X_ETH_NO_VLAN 0
+#define X_ETH_OUTBAND_VLAN 1
+#define X_ETH_INBAND_VLAN 2
 /* Rx ring params */
 #define U_ETH_LOCAL_BD_RING_SIZE 8
 #define U_ETH_LOCAL_SGE_RING_SIZE 10
 #define U_ETH_SGL_SIZE 8
-
+	/* The fw will padd the buffer with this value, so the IP header \
+	will be align to 4 Byte */
+#define IP_HEADER_ALIGNMENT_PADDING 2
 
 #define U_ETH_SGES_PER_PAGE_INVERSE_MASK \
 	(0xFFFF - ((PAGE_SIZE/((STRUCT_SIZE(eth_rx_sge))/8))-1))
@@ -409,16 +318,15 @@
 #define U_ETH_UNDEFINED_Q 0xFF
 
 /* values of command IDs in the ramrod message */
-#define RAMROD_CMD_ID_ETH_PORT_SETUP 80
-#define RAMROD_CMD_ID_ETH_CLIENT_SETUP 85
-#define RAMROD_CMD_ID_ETH_STAT_QUERY 90
-#define RAMROD_CMD_ID_ETH_UPDATE 100
-#define RAMROD_CMD_ID_ETH_HALT 105
-#define RAMROD_CMD_ID_ETH_SET_MAC 110
-#define RAMROD_CMD_ID_ETH_CFC_DEL 115
-#define RAMROD_CMD_ID_ETH_PORT_DEL 120
-#define RAMROD_CMD_ID_ETH_FORWARD_SETUP 125
-
+#define RAMROD_CMD_ID_ETH_UNUSED 0
+#define RAMROD_CMD_ID_ETH_CLIENT_SETUP 1
+#define RAMROD_CMD_ID_ETH_UPDATE 2
+#define RAMROD_CMD_ID_ETH_HALT 3
+#define RAMROD_CMD_ID_ETH_FORWARD_SETUP 4
+#define RAMROD_CMD_ID_ETH_ACTIVATE 5
+#define RAMROD_CMD_ID_ETH_DEACTIVATE 6
+#define RAMROD_CMD_ID_ETH_EMPTY 7
+#define RAMROD_CMD_ID_ETH_TERMINATE 8
 
 /* command values for set mac command */
 #define T_ETH_MAC_COMMAND_SET 0
@@ -431,7 +339,9 @@
 
 /* Maximal L2 clients supported */
 #define ETH_MAX_RX_CLIENTS_E1 18
-#define ETH_MAX_RX_CLIENTS_E1H 26
+#define ETH_MAX_RX_CLIENTS_E1H 28
+
+#define MAX_STAT_COUNTER_ID ETH_MAX_RX_CLIENTS_E1H
 
 /* Maximal aggregation queues supported */
 #define ETH_MAX_AGGREGATION_QUEUES_E1 32
@@ -443,6 +353,20 @@
 #define ETH_RSS_MODE_VLAN_PRI 2
 #define ETH_RSS_MODE_E1HOV_PRI 3
 #define ETH_RSS_MODE_IP_DSCP 4
+#define ETH_RSS_MODE_E2_INTEG 5
+
+
+/* ETH vlan filtering modes */
+#define ETH_VLAN_FILTER_ANY_VLAN 0 /* Don't filter by vlan */
+#define ETH_VLAN_FILTER_SPECIFIC_VLAN \
+	1 /* Only the vlan_id is allowed */
+#define ETH_VLAN_FILTER_CLASSIFY \
+	2 /* vlan will be added to CAM for classification */
+
+/* Fast path CQE selection */
+#define ETH_FP_CQE_REGULAR 0
+#define ETH_FP_CQE_SGL 1
+#define ETH_FP_CQE_RAW 2
 
 
 /**
@@ -458,6 +382,7 @@
 #define RESERVED_CONNECTION_TYPE_0 5
 #define RESERVED_CONNECTION_TYPE_1 6
 #define RESERVED_CONNECTION_TYPE_2 7
+#define NONE_CONNECTION_TYPE 8
 
 
 #define PROTOCOL_STATE_BIT_OFFSET 6
@@ -466,6 +391,16 @@
 #define TOE_STATE (TOE_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
 #define RDMA_STATE (RDMA_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
 
+/* values of command IDs in the ramrod message */
+#define RAMROD_CMD_ID_COMMON_FUNCTION_START 1
+#define RAMROD_CMD_ID_COMMON_FUNCTION_STOP 2
+#define RAMROD_CMD_ID_COMMON_CFC_DEL 3
+#define RAMROD_CMD_ID_COMMON_CFC_DEL_WB 4
+#define RAMROD_CMD_ID_COMMON_SET_MAC 5
+#define RAMROD_CMD_ID_COMMON_STAT_QUERY 6
+#define RAMROD_CMD_ID_COMMON_STOP_TRAFFIC 7
+#define RAMROD_CMD_ID_COMMON_START_TRAFFIC 8
+
 /* microcode fixed page page size 4K (chains and ring segments) */
 #define MC_PAGE_SIZE 4096
 
@@ -473,46 +408,26 @@
 /* Host coalescing constants */
 #define HC_IGU_BC_MODE 0
 #define HC_IGU_NBC_MODE 1
+/* Host coalescing constants. E1 includes E1H as well */
+
+/* Number of indices per slow-path SB */
+#define HC_SP_SB_MAX_INDICES 16
+
+/* Number of indices per SB */
+#define HC_SB_MAX_INDICES_E1X 8
+#define HC_SB_MAX_INDICES_E2 8
+
+#define HC_SB_MAX_SB_E1X 32
+#define HC_SB_MAX_SB_E2 136
+
+#define HC_SP_SB_ID 0xde
 
 #define HC_REGULAR_SEGMENT 0
 #define HC_DEFAULT_SEGMENT 1
+#define HC_SB_MAX_SM 2
 
-/* index numbers */
-#define HC_USTORM_DEF_SB_NUM_INDICES 8
-#define HC_CSTORM_DEF_SB_NUM_INDICES 8
-#define HC_XSTORM_DEF_SB_NUM_INDICES 4
-#define HC_TSTORM_DEF_SB_NUM_INDICES 4
-#define HC_USTORM_SB_NUM_INDICES 4
-#define HC_CSTORM_SB_NUM_INDICES 4
-
-/* index values - which counter to update */
-
-#define HC_INDEX_U_TOE_RX_CQ_CONS 0
-#define HC_INDEX_U_ETH_RX_CQ_CONS 1
-#define HC_INDEX_U_ETH_RX_BD_CONS 2
-#define HC_INDEX_U_FCOE_EQ_CONS 3
-
-#define HC_INDEX_C_TOE_TX_CQ_CONS 0
-#define HC_INDEX_C_ETH_TX_CQ_CONS 1
-#define HC_INDEX_C_ISCSI_EQ_CONS 2
-
-#define HC_INDEX_DEF_X_SPQ_CONS 0
-
-#define HC_INDEX_DEF_C_RDMA_EQ_CONS 0
-#define HC_INDEX_DEF_C_RDMA_NAL_PROD 1
-#define HC_INDEX_DEF_C_ETH_FW_TX_CQ_CONS 2
-#define HC_INDEX_DEF_C_ETH_SLOW_PATH 3
-#define HC_INDEX_DEF_C_ETH_RDMA_CQ_CONS 4
-#define HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS 5
-#define HC_INDEX_DEF_C_ETH_FCOE_CQ_CONS 6
-
-#define HC_INDEX_DEF_U_ETH_RDMA_RX_CQ_CONS 0
-#define HC_INDEX_DEF_U_ETH_ISCSI_RX_CQ_CONS 1
-#define HC_INDEX_DEF_U_ETH_RDMA_RX_BD_CONS 2
-#define HC_INDEX_DEF_U_ETH_ISCSI_RX_BD_CONS 3
-#define HC_INDEX_DEF_U_ETH_FCOE_RX_CQ_CONS 4
-#define HC_INDEX_DEF_U_ETH_FCOE_RX_BD_CONS 5
-
+#define HC_SB_MAX_DYNAMIC_INDICES 4
+#define HC_FUNCTION_DISABLED 0xff
 /* used by the driver to get the SB offset */
 #define USTORM_ID 0
 #define CSTORM_ID 1
@@ -529,45 +444,17 @@
 
 
 /**** DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
-#define EMULATION_FREQUENCY_FACTOR 1600
-#define FPGA_FREQUENCY_FACTOR 100
 
 #define TIMERS_TICK_SIZE_CHIP (1e-3)
-#define TIMERS_TICK_SIZE_EMUL \
- ((TIMERS_TICK_SIZE_CHIP)/((EMULATION_FREQUENCY_FACTOR)))
-#define TIMERS_TICK_SIZE_FPGA \
- ((TIMERS_TICK_SIZE_CHIP)/((FPGA_FREQUENCY_FACTOR)))
 
 #define TSEMI_CLK1_RESUL_CHIP (1e-3)
-#define TSEMI_CLK1_RESUL_EMUL \
- ((TSEMI_CLK1_RESUL_CHIP)/(EMULATION_FREQUENCY_FACTOR))
-#define TSEMI_CLK1_RESUL_FPGA \
- ((TSEMI_CLK1_RESUL_CHIP)/(FPGA_FREQUENCY_FACTOR))
-
-#define USEMI_CLK1_RESUL_CHIP (TIMERS_TICK_SIZE_CHIP)
-#define USEMI_CLK1_RESUL_EMUL (TIMERS_TICK_SIZE_EMUL)
-#define USEMI_CLK1_RESUL_FPGA (TIMERS_TICK_SIZE_FPGA)
 
 #define XSEMI_CLK1_RESUL_CHIP (1e-3)
-#define XSEMI_CLK1_RESUL_EMUL \
- ((XSEMI_CLK1_RESUL_CHIP)/(EMULATION_FREQUENCY_FACTOR))
-#define XSEMI_CLK1_RESUL_FPGA \
- ((XSEMI_CLK1_RESUL_CHIP)/(FPGA_FREQUENCY_FACTOR))
-
-#define XSEMI_CLK2_RESUL_CHIP (1e-6)
-#define XSEMI_CLK2_RESUL_EMUL \
- ((XSEMI_CLK2_RESUL_CHIP)/(EMULATION_FREQUENCY_FACTOR))
-#define XSEMI_CLK2_RESUL_FPGA \
- ((XSEMI_CLK2_RESUL_CHIP)/(FPGA_FREQUENCY_FACTOR))
 
 #define SDM_TIMER_TICK_RESUL_CHIP (4*(1e-6))
-#define SDM_TIMER_TICK_RESUL_EMUL \
- ((SDM_TIMER_TICK_RESUL_CHIP)/(EMULATION_FREQUENCY_FACTOR))
-#define SDM_TIMER_TICK_RESUL_FPGA \
- ((SDM_TIMER_TICK_RESUL_CHIP)/(FPGA_FREQUENCY_FACTOR))
-
 
 /**** END DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
+
 #define XSTORM_IP_ID_ROLL_HALF 0x8000
 #define XSTORM_IP_ID_ROLL_ALL 0
 
@@ -576,10 +463,36 @@
 #define NUM_OF_PROTOCOLS 4
 #define NUM_OF_SAFC_BITS 16
 #define MAX_COS_NUMBER 4
-#define MAX_T_STAT_COUNTER_ID 18
-#define MAX_X_STAT_COUNTER_ID 18
-#define MAX_U_STAT_COUNTER_ID 18
 
+#define FAIRNESS_COS_WRR_MODE 0
+#define FAIRNESS_COS_ETS_MODE 1
+
+
+/* Priority Flow Control (PFC) */
+#define MAX_PFC_PRIORITIES 8
+#define MAX_PFC_TRAFFIC_TYPES 8
+
+/* Available Traffic Types for Link Layer Flow Control */
+#define LLFC_TRAFFIC_TYPE_NW 0
+#define LLFC_TRAFFIC_TYPE_FCOE 1
+#define LLFC_TRAFFIC_TYPE_ISCSI 2
+	/***************** START OF E2 INTEGRATION \
+	CODE***************************************/
+#define LLFC_TRAFFIC_TYPE_NW_COS1_E2INTEG 3
+	/***************** END OF E2 INTEGRATION \
+	CODE***************************************/
+#define LLFC_TRAFFIC_TYPE_MAX 4
+
+	/* used by array traffic_type_to_priority[] to mark traffic type \
+	that is not mapped to priority*/
+#define LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED 0xFF
+
+#define LLFC_MODE_NONE 0
+#define LLFC_MODE_PFC 1
+#define LLFC_MODE_SAFC 2
+
+#define DCB_DISABLED 0
+#define DCB_ENABLED 1
 
 #define UNKNOWN_ADDRESS 0
 #define UNICAST_ADDRESS 1
@@ -587,8 +500,32 @@
 #define BROADCAST_ADDRESS 3
 
 #define SINGLE_FUNCTION 0
-#define MULTI_FUNCTION 1
+#define MULTI_FUNCTION_SD 1
+#define MULTI_FUNCTION_SI 2
 
 #define IP_V4 0
 #define IP_V6 1
 
+
+#define C_ERES_PER_PAGE \
+	(PAGE_SIZE / BITS_TO_BYTES(STRUCT_SIZE(event_ring_elem)))
+#define C_ERE_PER_PAGE_MASK (C_ERES_PER_PAGE - 1)
+
+#define EVENT_RING_OPCODE_VF_PF_CHANNEL 0
+#define EVENT_RING_OPCODE_FUNCTION_START 1
+#define EVENT_RING_OPCODE_FUNCTION_STOP 2
+#define EVENT_RING_OPCODE_CFC_DEL 3
+#define EVENT_RING_OPCODE_CFC_DEL_WB 4
+#define EVENT_RING_OPCODE_SET_MAC 5
+#define EVENT_RING_OPCODE_STAT_QUERY 6
+#define EVENT_RING_OPCODE_STOP_TRAFFIC 7
+#define EVENT_RING_OPCODE_START_TRAFFIC 8
+#define EVENT_RING_OPCODE_FORWARD_SETUP 9
+
+#define VF_PF_CHANNEL_STATE_READY 0
+#define VF_PF_CHANNEL_STATE_WAITING_FOR_ACK 1
+
+#define VF_PF_CHANNEL_STATE_MAX_NUMBER 2
+
+
+#endif /* BNX2X_FW_DEFS_H */
diff --git a/drivers/net/bnx2x/bnx2x_fw_file_hdr.h b/drivers/net/bnx2x/bnx2x_fw_file_hdr.h
index 3f5ee5d7..f807262 100644
--- a/drivers/net/bnx2x/bnx2x_fw_file_hdr.h
+++ b/drivers/net/bnx2x/bnx2x_fw_file_hdr.h
@@ -31,6 +31,7 @@
 	struct bnx2x_fw_file_section csem_pram_data;
 	struct bnx2x_fw_file_section xsem_int_table_data;
 	struct bnx2x_fw_file_section xsem_pram_data;
+	struct bnx2x_fw_file_section iro_arr;
 	struct bnx2x_fw_file_section fw_version;
 };
 
diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h
index fd1f29e..18c8e23 100644
--- a/drivers/net/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/bnx2x/bnx2x_hsi.h
@@ -6,6 +6,10 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
  */
+#ifndef BNX2X_HSI_H
+#define BNX2X_HSI_H
+
+#include "bnx2x_fw_defs.h"
 
 struct license_key {
 	u32 reserved[6];
@@ -78,6 +82,8 @@
 #define SHARED_HW_CFG_LED_PHY11 		    0x000b0000
 #define SHARED_HW_CFG_LED_MAC4			    0x000c0000
 #define SHARED_HW_CFG_LED_PHY8			    0x000d0000
+#define SHARED_HW_CFG_LED_EXTPHY1		    0x000e0000
+
 
 #define SHARED_HW_CFG_AN_ENABLE_MASK		    0x3f000000
 #define SHARED_HW_CFG_AN_ENABLE_SHIFT		    24
@@ -120,6 +126,23 @@
 #define SHARED_HW_CFG_FAN_FAILURE_DISABLED		      0x00080000
 #define SHARED_HW_CFG_FAN_FAILURE_ENABLED		      0x00100000
 
+	/* Set the MDC/MDIO access for the first external phy */
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK	    0x1C000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT	    26
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE     0x00000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0	    0x04000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1	    0x08000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH	    0x0c000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED	    0x10000000
+
+	/* Set the MDC/MDIO access for the second external phy */
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK	    0xE0000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT	    29
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_PHY_TYPE     0x00000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC0	    0x20000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC1	    0x40000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_BOTH	    0x60000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SWAPPED	    0x80000000
 	u32 power_dissipated;					/* 0x11c */
 #define SHARED_HW_CFG_POWER_DIS_CMN_MASK	    0xff000000
 #define SHARED_HW_CFG_POWER_DIS_CMN_SHIFT	    24
@@ -221,11 +244,93 @@
 
 	u16 xgxs_config_tx[4];				    /* 0x1A0 */
 
-	u32 Reserved1[64];				    /* 0x1A8 */
+	u32 Reserved1[57];				    /* 0x1A8 */
+	u32 speed_capability_mask2;			    /* 0x28C */
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK		      0x0000FFFF
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT		      0
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL	      0x00000001
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3__		      0x00000002
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3___		      0x00000004
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL	      0x00000008
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G		      0x00000010
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_DOT_5G	      0x00000020
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G		      0x00000040
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12G		      0x00000080
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12_DOT_5G	      0x00000100
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_13G		      0x00000200
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_15G		      0x00000400
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_16G		      0x00000800
+
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK		      0xFFFF0000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT		      16
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL	      0x00010000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0__		      0x00020000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0___		      0x00040000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL	      0x00080000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G		      0x00100000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_DOT_5G	      0x00200000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G		      0x00400000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12G		      0x00800000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12_DOT_5G	      0x01000000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_13G		      0x02000000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_15G		      0x04000000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_16G		      0x08000000
+
+	/* In the case where two media types (e.g. copper and fiber) are
+	  present and electrically active at the same time, PHY Selection
+	  will determine which of the two PHYs will be designated as the
+	  Active PHY and used for a connection to the network.	*/
+	u32 multi_phy_config;				/* 0x290 */
+#define PORT_HW_CFG_PHY_SELECTION_MASK		     0x00000007
+#define PORT_HW_CFG_PHY_SELECTION_SHIFT		     0
+#define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT   0x00000000
+#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY	     0x00000001
+#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY	     0x00000002
+#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003
+#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004
+
+	/* When enabled, all second phy nvram parameters will be swapped
+	  with the first phy parameters */
+#define PORT_HW_CFG_PHY_SWAPPED_MASK		     0x00000008
+#define PORT_HW_CFG_PHY_SWAPPED_SHIFT		     3
+#define PORT_HW_CFG_PHY_SWAPPED_DISABLED	     0x00000000
+#define PORT_HW_CFG_PHY_SWAPPED_ENABLED		     0x00000008
+
+
+	/* Address of the second external phy */
+	u32 external_phy_config2;				/* 0x294 */
+#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK	    0x000000FF
+#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT	    0
+
+	/* The second XGXS external PHY type */
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK	    0x0000FF00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT	    8
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT	    0x00000000
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8071	    0x00000100
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8072	    0x00000200
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8073	    0x00000300
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8705	    0x00000400
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8706	    0x00000500
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8726	    0x00000600
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8481	    0x00000700
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101	    0x00000800
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727	    0x00000900
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727_NOC  0x00000a00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823     0x00000b00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640     0x00000c00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833     0x00000d00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE	    0x0000fd00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN     0x0000ff00
+
+	/* 4 times 16 bits for all 4 lanes. For some external PHYs (such as
+	  8706, 8726 and 8727) not all 4 values are needed. */
+	u16 xgxs_config2_rx[4];				/* 0x296 */
+	u16 xgxs_config2_tx[4];				/* 0x2A0 */
 
 	u32 lane_config;
 #define PORT_HW_CFG_LANE_SWAP_CFG_MASK		    0x0000ffff
 #define PORT_HW_CFG_LANE_SWAP_CFG_SHIFT 	    0
+
 #define PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK	    0x000000ff
 #define PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT	    0
 #define PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK	    0x0000ff00
@@ -515,10 +620,17 @@
 #define PORT_FEATURE_FLOW_CONTROL_NONE		    0x00000400
 
 	/* The default for MCP link configuration,
-	   uses the same defines as link_config */
+	uses the same defines as link_config */
 	u32 mfw_wol_link_cfg;
+	/* The default for the driver of the second external phy,
+	uses the same defines as link_config */
+	u32 link_config2;					/* 0x47C */
 
-	u32 reserved[19];
+	/* The default for MCP of the second external phy,
+	uses the same defines as link_config */
+	u32 mfw_wol_link_cfg2;				/* 0x480 */
+
+	u32 Reserved2[17];					/* 0x484 */
 
 };
 
@@ -551,6 +663,7 @@
 #define FUNC_7				7
 #define E1_FUNC_MAX			2
 #define E1H_FUNC_MAX			8
+#define E2_FUNC_MAX	    4	/* per path */
 
 #define VN_0				0
 #define VN_1				1
@@ -686,8 +799,14 @@
 	 * The optic module verification commands require bootcode
 	 * v5.0.6 or later
 	 */
-#define DRV_MSG_CODE_VRFY_OPT_MDL			0xa0000000
-#define REQ_BC_VER_4_VRFY_OPT_MDL			0x00050006
+#define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL	0xa0000000
+#define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL	0x00050006
+	/*
+	 * The specific optic module verification command requires bootcode
+	 * v5.2.12 or later
+	 */
+#define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL	    0xa1000000
+#define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL	    0x00050234
 
 #define BIOS_MSG_CODE_LIC_CHALLENGE			0xff010000
 #define BIOS_MSG_CODE_LIC_RESPONSE			0xff020000
@@ -703,6 +822,9 @@
 #define FW_MSG_CODE_DRV_LOAD_COMMON			0x10100000
 #define FW_MSG_CODE_DRV_LOAD_PORT			0x10110000
 #define FW_MSG_CODE_DRV_LOAD_FUNCTION			0x10120000
+	/* Load common chip is supported from bc 6.0.0	*/
+#define REQ_BC_VER_4_DRV_LOAD_COMMON_CHIP	0x00060000
+#define FW_MSG_CODE_DRV_LOAD_COMMON_CHIP	0x10130000
 #define FW_MSG_CODE_DRV_LOAD_REFUSED			0x10200000
 #define FW_MSG_CODE_DRV_LOAD_DONE			0x11100000
 #define FW_MSG_CODE_DRV_UNLOAD_COMMON			0x20100000
@@ -903,11 +1025,22 @@
 	struct mgmtfw_state	mgmtfw_state;	       /* 0x4ac     (0x1b8) */
 
 	struct drv_port_mb	port_mb[PORT_MAX];     /* 0x664 (16*2=0x20) */
-	struct drv_func_mb	func_mb[E1H_FUNC_MAX];
+	struct drv_func_mb	func_mb[];	       /* 0x684
+					     (44*2/4/8=0x58/0xb0/0x160) */
 
-	struct mf_cfg		mf_cfg;
+}; /* 57710 = 0x6dc | 57711 = 0x7E4 | 57712 = 0x734 */
 
-};						       /* 0x6dc */
+struct fw_flr_ack {
+	u32	pf_ack;
+	u32	vf_ack[1];
+	u32	iov_dis_ack;
+};
+
+struct fw_flr_mb {
+	u32	aggint;
+	u32	opgen_addr;
+	struct	fw_flr_ack ack;
+};
 
 
 struct shmem2_region {
@@ -922,7 +1055,25 @@
 #define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV	    0x00000040
 #define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV	    0x00000080
 #define SHMEM_DCC_SUPPORT_DEFAULT		    SHMEM_DCC_SUPPORT_NONE
+	u32 ext_phy_fw_version2[PORT_MAX];
+	/*
+	 * For backwards compatibility, if the mf_cfg_addr does not exist
+	 * (the size filed is smaller than 0xc) the mf_cfg resides at the
+	 * end of struct shmem_region
+     */
+	u32	mf_cfg_addr;
+#define SHMEM_MF_CFG_ADDR_NONE			    0x00000000
 
+	struct fw_flr_mb flr_mb;
+	u32	reserved[3];
+	/*
+	 * The other shmemX_base_addr holds the other path's shmem address
+	 * required for example in case of common phy init, or for path1 to know
+	 * the address of mcp debug trace which is located in offset from shmem
+	 * of path0
+	 */
+	u32 other_shmem_base_addr;
+	u32 other_shmem2_base_addr;
 };
 
 
@@ -978,7 +1129,7 @@
 };
 
 
-struct bmac_stats {
+struct bmac1_stats {
     u32     tx_stat_gtpkt_lo;
     u32     tx_stat_gtpkt_hi;
     u32     tx_stat_gtxpf_lo;
@@ -1082,10 +1233,126 @@
     u32     rx_stat_gripj_hi;
 };
 
+struct bmac2_stats {
+	u32	tx_stat_gtpk_lo; /* gtpok */
+	u32	tx_stat_gtpk_hi; /* gtpok */
+	u32	tx_stat_gtxpf_lo; /* gtpf */
+	u32	tx_stat_gtxpf_hi; /* gtpf */
+	u32	tx_stat_gtpp_lo; /* NEW BMAC2 */
+	u32	tx_stat_gtpp_hi; /* NEW BMAC2 */
+	u32	tx_stat_gtfcs_lo;
+	u32	tx_stat_gtfcs_hi;
+	u32	tx_stat_gtuca_lo; /* NEW BMAC2 */
+	u32	tx_stat_gtuca_hi; /* NEW BMAC2 */
+	u32	tx_stat_gtmca_lo;
+	u32	tx_stat_gtmca_hi;
+	u32	tx_stat_gtbca_lo;
+	u32	tx_stat_gtbca_hi;
+	u32	tx_stat_gtovr_lo;
+	u32	tx_stat_gtovr_hi;
+	u32	tx_stat_gtfrg_lo;
+	u32	tx_stat_gtfrg_hi;
+	u32	tx_stat_gtpkt1_lo; /* gtpkt */
+	u32	tx_stat_gtpkt1_hi; /* gtpkt */
+	u32	tx_stat_gt64_lo;
+	u32	tx_stat_gt64_hi;
+	u32	tx_stat_gt127_lo;
+	u32	tx_stat_gt127_hi;
+	u32	tx_stat_gt255_lo;
+	u32	tx_stat_gt255_hi;
+	u32	tx_stat_gt511_lo;
+	u32	tx_stat_gt511_hi;
+	u32	tx_stat_gt1023_lo;
+	u32	tx_stat_gt1023_hi;
+	u32	tx_stat_gt1518_lo;
+	u32	tx_stat_gt1518_hi;
+	u32	tx_stat_gt2047_lo;
+	u32	tx_stat_gt2047_hi;
+	u32	tx_stat_gt4095_lo;
+	u32	tx_stat_gt4095_hi;
+	u32	tx_stat_gt9216_lo;
+	u32	tx_stat_gt9216_hi;
+	u32	tx_stat_gt16383_lo;
+	u32	tx_stat_gt16383_hi;
+	u32	tx_stat_gtmax_lo;
+	u32	tx_stat_gtmax_hi;
+	u32	tx_stat_gtufl_lo;
+	u32	tx_stat_gtufl_hi;
+	u32	tx_stat_gterr_lo;
+	u32	tx_stat_gterr_hi;
+	u32	tx_stat_gtbyt_lo;
+	u32	tx_stat_gtbyt_hi;
+
+	u32	rx_stat_gr64_lo;
+	u32	rx_stat_gr64_hi;
+	u32	rx_stat_gr127_lo;
+	u32	rx_stat_gr127_hi;
+	u32	rx_stat_gr255_lo;
+	u32	rx_stat_gr255_hi;
+	u32	rx_stat_gr511_lo;
+	u32	rx_stat_gr511_hi;
+	u32	rx_stat_gr1023_lo;
+	u32	rx_stat_gr1023_hi;
+	u32	rx_stat_gr1518_lo;
+	u32	rx_stat_gr1518_hi;
+	u32	rx_stat_gr2047_lo;
+	u32	rx_stat_gr2047_hi;
+	u32	rx_stat_gr4095_lo;
+	u32	rx_stat_gr4095_hi;
+	u32	rx_stat_gr9216_lo;
+	u32	rx_stat_gr9216_hi;
+	u32	rx_stat_gr16383_lo;
+	u32	rx_stat_gr16383_hi;
+	u32	rx_stat_grmax_lo;
+	u32	rx_stat_grmax_hi;
+	u32	rx_stat_grpkt_lo;
+	u32	rx_stat_grpkt_hi;
+	u32	rx_stat_grfcs_lo;
+	u32	rx_stat_grfcs_hi;
+	u32	rx_stat_gruca_lo;
+	u32	rx_stat_gruca_hi;
+	u32	rx_stat_grmca_lo;
+	u32	rx_stat_grmca_hi;
+	u32	rx_stat_grbca_lo;
+	u32	rx_stat_grbca_hi;
+	u32	rx_stat_grxpf_lo; /* grpf */
+	u32	rx_stat_grxpf_hi; /* grpf */
+	u32	rx_stat_grpp_lo;
+	u32	rx_stat_grpp_hi;
+	u32	rx_stat_grxuo_lo; /* gruo */
+	u32	rx_stat_grxuo_hi; /* gruo */
+	u32	rx_stat_grjbr_lo;
+	u32	rx_stat_grjbr_hi;
+	u32	rx_stat_grovr_lo;
+	u32	rx_stat_grovr_hi;
+	u32	rx_stat_grxcf_lo; /* grcf */
+	u32	rx_stat_grxcf_hi; /* grcf */
+	u32	rx_stat_grflr_lo;
+	u32	rx_stat_grflr_hi;
+	u32	rx_stat_grpok_lo;
+	u32	rx_stat_grpok_hi;
+	u32	rx_stat_grmeg_lo;
+	u32	rx_stat_grmeg_hi;
+	u32	rx_stat_grmeb_lo;
+	u32	rx_stat_grmeb_hi;
+	u32	rx_stat_grbyt_lo;
+	u32	rx_stat_grbyt_hi;
+	u32	rx_stat_grund_lo;
+	u32	rx_stat_grund_hi;
+	u32	rx_stat_grfrg_lo;
+	u32	rx_stat_grfrg_hi;
+	u32	rx_stat_grerb_lo; /* grerrbyt */
+	u32	rx_stat_grerb_hi; /* grerrbyt */
+	u32	rx_stat_grfre_lo; /* grfrerr */
+	u32	rx_stat_grfre_hi; /* grfrerr */
+	u32	rx_stat_gripj_lo;
+	u32	rx_stat_gripj_hi;
+};
 
 union mac_stats {
-    struct emac_stats	emac_stats;
-    struct bmac_stats	bmac_stats;
+	struct emac_stats	 emac_stats;
+	struct bmac1_stats	 bmac1_stats;
+	struct bmac2_stats	 bmac2_stats;
 };
 
 
@@ -1259,17 +1526,17 @@
 };
 
 
-#define BCM_5710_FW_MAJOR_VERSION			5
-#define BCM_5710_FW_MINOR_VERSION			2
-#define BCM_5710_FW_REVISION_VERSION			13
-#define BCM_5710_FW_ENGINEERING_VERSION 		0
+#define BCM_5710_FW_MAJOR_VERSION			6
+#define BCM_5710_FW_MINOR_VERSION			0
+#define BCM_5710_FW_REVISION_VERSION			34
+#define BCM_5710_FW_ENGINEERING_VERSION			0
 #define BCM_5710_FW_COMPILE_FLAGS			1
 
 
 /*
  * attention bits
  */
-struct atten_def_status_block {
+struct atten_sp_status_block {
 	__le32 attn_bits;
 	__le32 attn_bits_ack;
 	u8 status_block_id;
@@ -1327,7 +1594,60 @@
 
 
 /*
- * IGU driver acknowledgement register
+ * 3 lines. status block
+ */
+struct hc_status_block_e1x {
+	__le16 index_values[HC_SB_MAX_INDICES_E1X];
+	__le16 running_index[HC_SB_MAX_SM];
+	u32 rsrv;
+};
+
+/*
+ * host status block
+ */
+struct host_hc_status_block_e1x {
+	struct hc_status_block_e1x sb;
+};
+
+
+/*
+ * 3 lines. status block
+ */
+struct hc_status_block_e2 {
+	__le16 index_values[HC_SB_MAX_INDICES_E2];
+	__le16 running_index[HC_SB_MAX_SM];
+	u32 reserved;
+};
+
+/*
+ * host status block
+ */
+struct host_hc_status_block_e2 {
+	struct hc_status_block_e2 sb;
+};
+
+
+/*
+ * 5 lines. slow-path status block
+ */
+struct hc_sp_status_block {
+	__le16 index_values[HC_SP_SB_MAX_INDICES];
+	__le16 running_index;
+	__le16 rsrv;
+	u32 rsrv1;
+};
+
+/*
+ * host status block
+ */
+struct host_sp_status_block {
+	struct atten_sp_status_block atten_status_block;
+	struct hc_sp_status_block sp_sb;
+};
+
+
+/*
+ * IGU driver acknowledgment register
  */
 struct igu_ack_register {
 #if defined(__BIG_ENDIAN)
@@ -1417,6 +1737,24 @@
 
 
 /*
+ * Control register for the IGU command register
+ */
+struct igu_ctrl_reg {
+	u32 ctrl_data;
+#define IGU_CTRL_REG_ADDRESS (0xFFF<<0)
+#define IGU_CTRL_REG_ADDRESS_SHIFT 0
+#define IGU_CTRL_REG_FID (0x7F<<12)
+#define IGU_CTRL_REG_FID_SHIFT 12
+#define IGU_CTRL_REG_RESERVED (0x1<<19)
+#define IGU_CTRL_REG_RESERVED_SHIFT 19
+#define IGU_CTRL_REG_TYPE (0x1<<20)
+#define IGU_CTRL_REG_TYPE_SHIFT 20
+#define IGU_CTRL_REG_UNUSED (0x7FF<<21)
+#define IGU_CTRL_REG_UNUSED_SHIFT 21
+};
+
+
+/*
  * Parser parsing flags field
  */
 struct parsing_flags {
@@ -1485,8 +1823,14 @@
 #define DMAE_COMMAND_DST_RESET_SHIFT 14
 #define DMAE_COMMAND_E1HVN (0x3<<15)
 #define DMAE_COMMAND_E1HVN_SHIFT 15
-#define DMAE_COMMAND_RESERVED0 (0x7FFF<<17)
-#define DMAE_COMMAND_RESERVED0_SHIFT 17
+#define DMAE_COMMAND_DST_VN (0x3<<17)
+#define DMAE_COMMAND_DST_VN_SHIFT 17
+#define DMAE_COMMAND_C_FUNC (0x1<<19)
+#define DMAE_COMMAND_C_FUNC_SHIFT 19
+#define DMAE_COMMAND_ERR_POLICY (0x3<<20)
+#define DMAE_COMMAND_ERR_POLICY_SHIFT 20
+#define DMAE_COMMAND_RESERVED0 (0x3FF<<22)
+#define DMAE_COMMAND_RESERVED0_SHIFT 22
 	u32 src_addr_lo;
 	u32 src_addr_hi;
 	u32 dst_addr_lo;
@@ -1511,11 +1855,11 @@
 	u16 crc16_c;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 reserved2;
+	u16 reserved3;
 	u16 crc_t10;
 #elif defined(__LITTLE_ENDIAN)
 	u16 crc_t10;
-	u16 reserved2;
+	u16 reserved3;
 #endif
 #if defined(__BIG_ENDIAN)
 	u16 xsum8;
@@ -1536,96 +1880,20 @@
 
 
 /*
- * The eth storm context of Ustorm (configuration part)
+ * SDM operation gen command (generate aggregative interrupt)
  */
-struct ustorm_eth_st_context_config {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT (0x1<<0)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT_SHIFT 0
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_DYNAMIC_HC (0x1<<1)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_DYNAMIC_HC_SHIFT 1
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA (0x1<<2)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA_SHIFT 2
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS (0x1<<3)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS_SHIFT 3
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0 (0xF<<4)
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0_SHIFT 4
-	u8 status_block_id;
-	u8 clientId;
-	u8 sb_index_numbers;
-#define USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER (0xF<<0)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER_SHIFT 0
-#define USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER (0xF<<4)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER_SHIFT 4
-#elif defined(__LITTLE_ENDIAN)
-	u8 sb_index_numbers;
-#define USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER (0xF<<0)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER_SHIFT 0
-#define USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER (0xF<<4)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER_SHIFT 4
-	u8 clientId;
-	u8 status_block_id;
-	u8 flags;
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT (0x1<<0)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT_SHIFT 0
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_DYNAMIC_HC (0x1<<1)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_DYNAMIC_HC_SHIFT 1
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA (0x1<<2)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA_SHIFT 2
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS (0x1<<3)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS_SHIFT 3
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0 (0xF<<4)
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0_SHIFT 4
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 bd_buff_size;
-	u8 statistics_counter_id;
-	u8 mc_alignment_log_size;
-#elif defined(__LITTLE_ENDIAN)
-	u8 mc_alignment_log_size;
-	u8 statistics_counter_id;
-	u16 bd_buff_size;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __local_sge_prod;
-	u8 __local_bd_prod;
-	u16 sge_buff_size;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sge_buff_size;
-	u8 __local_bd_prod;
-	u8 __local_sge_prod;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __sdm_bd_expected_counter;
-	u8 cstorm_agg_int;
-	u8 __expected_bds_on_ram;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __expected_bds_on_ram;
-	u8 cstorm_agg_int;
-	u16 __sdm_bd_expected_counter;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __ring_data_ram_addr;
-	u16 __hc_cstorm_ram_addr;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __hc_cstorm_ram_addr;
-	u16 __ring_data_ram_addr;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 reserved1;
-	u8 max_sges_for_packet;
-	u16 __bd_ring_ram_addr;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __bd_ring_ram_addr;
-	u8 max_sges_for_packet;
-	u8 reserved1;
-#endif
-	u32 bd_page_base_lo;
-	u32 bd_page_base_hi;
-	u32 sge_page_base_lo;
-	u32 sge_page_base_hi;
-	struct regpair reserved2;
+struct sdm_op_gen {
+	__le32 command;
+#define SDM_OP_GEN_COMP_PARAM (0x1F<<0)
+#define SDM_OP_GEN_COMP_PARAM_SHIFT 0
+#define SDM_OP_GEN_COMP_TYPE (0x7<<5)
+#define SDM_OP_GEN_COMP_TYPE_SHIFT 5
+#define SDM_OP_GEN_AGG_VECT_IDX (0xFF<<8)
+#define SDM_OP_GEN_AGG_VECT_IDX_SHIFT 8
+#define SDM_OP_GEN_AGG_VECT_IDX_VALID (0x1<<16)
+#define SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT 16
+#define SDM_OP_GEN_RESERVED (0x7FFF<<17)
+#define SDM_OP_GEN_RESERVED_SHIFT 17
 };
 
 /*
@@ -1644,20 +1912,13 @@
 	__le32 addr_hi;
 };
 
-/*
- * Local BDs and SGEs rings (in ETH)
- */
-struct eth_local_rx_rings {
-	struct eth_rx_bd __local_bd_ring[8];
-	struct eth_rx_sge __local_sge_ring[10];
-};
+
 
 /*
  * The eth storm context of Ustorm
  */
 struct ustorm_eth_st_context {
-	struct ustorm_eth_st_context_config common;
-	struct eth_local_rx_rings __rings;
+	u32 reserved0[48];
 };
 
 /*
@@ -1668,337 +1929,53 @@
 };
 
 /*
- * The eth aggregative context section of Xstorm
- */
-struct xstorm_eth_extra_ag_context_section {
-#if defined(__BIG_ENDIAN)
-	u8 __tcp_agg_vars1;
-	u8 __reserved50;
-	u16 __mss;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __mss;
-	u8 __reserved50;
-	u8 __tcp_agg_vars1;
-#endif
-	u32 __snd_nxt;
-	u32 __tx_wnd;
-	u32 __snd_una;
-	u32 __reserved53;
-#if defined(__BIG_ENDIAN)
-	u8 __agg_val8_th;
-	u8 __agg_val8;
-	u16 __tcp_agg_vars2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __tcp_agg_vars2;
-	u8 __agg_val8;
-	u8 __agg_val8_th;
-#endif
-	u32 __reserved58;
-	u32 __reserved59;
-	u32 __reserved60;
-	u32 __reserved61;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val7_th;
-	u16 __agg_val7;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val7;
-	u16 __agg_val7_th;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __tcp_agg_vars5;
-	u8 __tcp_agg_vars4;
-	u8 __tcp_agg_vars3;
-	u8 __reserved62;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __reserved62;
-	u8 __tcp_agg_vars3;
-	u8 __tcp_agg_vars4;
-	u8 __tcp_agg_vars5;
-#endif
-	u32 __tcp_agg_vars6;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_misc6;
-	u16 __tcp_agg_vars7;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __tcp_agg_vars7;
-	u16 __agg_misc6;
-#endif
-	u32 __agg_val10;
-	u32 __agg_val10_th;
-#if defined(__BIG_ENDIAN)
-	u16 __reserved3;
-	u8 __reserved2;
-	u8 __da_only_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __da_only_cnt;
-	u8 __reserved2;
-	u16 __reserved3;
-#endif
-};
-
-/*
  * The eth aggregative context of Xstorm
  */
 struct xstorm_eth_ag_context {
-#if defined(__BIG_ENDIAN)
-	u16 agg_val1;
-	u8 __agg_vars1;
-	u8 __state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __state;
-	u8 __agg_vars1;
-	u16 agg_val1;
-#endif
+	u32 reserved0;
 #if defined(__BIG_ENDIAN)
 	u8 cdu_reserved;
-	u8 __agg_vars4;
-	u8 __agg_vars3;
-	u8 __agg_vars2;
+	u8 reserved2;
+	u16 reserved1;
 #elif defined(__LITTLE_ENDIAN)
-	u8 __agg_vars2;
-	u8 __agg_vars3;
-	u8 __agg_vars4;
+	u16 reserved1;
+	u8 reserved2;
 	u8 cdu_reserved;
 #endif
-	u32 __bd_prod;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_vars5;
-	u16 __agg_val4_th;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val4_th;
-	u16 __agg_vars5;
-#endif
-	struct xstorm_eth_extra_ag_context_section __extra_section;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_vars7;
-	u8 __agg_val3_th;
-	u8 __agg_vars6;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __agg_vars6;
-	u8 __agg_val3_th;
-	u16 __agg_vars7;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val11_th;
-	u16 __agg_val11;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val11;
-	u16 __agg_val11_th;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __reserved1;
-	u8 __agg_val6_th;
-	u16 __agg_val9;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val9;
-	u8 __agg_val6_th;
-	u8 __reserved1;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val2_th;
-	u16 __agg_val2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val2;
-	u16 __agg_val2_th;
-#endif
-	u32 __agg_vars8;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_misc0;
-	u16 __agg_val4;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val4;
-	u16 __agg_misc0;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __agg_val3;
-	u8 __agg_val6;
-	u8 __agg_val5_th;
-	u8 __agg_val5;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __agg_val5;
-	u8 __agg_val5_th;
-	u8 __agg_val6;
-	u8 __agg_val3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_misc1;
-	u16 __bd_ind_max_val;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __bd_ind_max_val;
-	u16 __agg_misc1;
-#endif
-	u32 __reserved57;
-	u32 __agg_misc4;
-	u32 __agg_misc5;
-};
-
-/*
- * The eth extra aggregative context section of Tstorm
- */
-struct tstorm_eth_extra_ag_context_section {
-	u32 __agg_val1;
-#if defined(__BIG_ENDIAN)
-	u8 __tcp_agg_vars2;
-	u8 __agg_val3;
-	u16 __agg_val2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val2;
-	u8 __agg_val3;
-	u8 __tcp_agg_vars2;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val5;
-	u8 __agg_val6;
-	u8 __tcp_agg_vars3;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __tcp_agg_vars3;
-	u8 __agg_val6;
-	u16 __agg_val5;
-#endif
-	u32 __reserved63;
-	u32 __reserved64;
-	u32 __reserved65;
-	u32 __reserved66;
-	u32 __reserved67;
-	u32 __tcp_agg_vars1;
-	u32 __reserved61;
-	u32 __reserved62;
-	u32 __reserved2;
+	u32 reserved3[30];
 };
 
 /*
  * The eth aggregative context of Tstorm
  */
 struct tstorm_eth_ag_context {
-#if defined(__BIG_ENDIAN)
-	u16 __reserved54;
-	u8 __agg_vars1;
-	u8 __state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __state;
-	u8 __agg_vars1;
-	u16 __reserved54;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val4;
-	u16 __agg_vars2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_vars2;
-	u16 __agg_val4;
-#endif
-	struct tstorm_eth_extra_ag_context_section __extra_section;
+	u32 __reserved0[14];
 };
 
+
 /*
  * The eth aggregative context of Cstorm
  */
 struct cstorm_eth_ag_context {
-	u32 __agg_vars1;
-#if defined(__BIG_ENDIAN)
-	u8 __aux1_th;
-	u8 __aux1_val;
-	u16 __agg_vars2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_vars2;
-	u8 __aux1_val;
-	u8 __aux1_th;
-#endif
-	u32 __num_of_treated_packet;
-	u32 __last_packet_treated;
-#if defined(__BIG_ENDIAN)
-	u16 __reserved58;
-	u16 __reserved57;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __reserved57;
-	u16 __reserved58;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __reserved62;
-	u8 __reserved61;
-	u8 __reserved60;
-	u8 __reserved59;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __reserved59;
-	u8 __reserved60;
-	u8 __reserved61;
-	u8 __reserved62;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __reserved64;
-	u16 __reserved63;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __reserved63;
-	u16 __reserved64;
-#endif
-	u32 __reserved65;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_vars3;
-	u16 __rq_inv_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __rq_inv_cnt;
-	u16 __agg_vars3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __packet_index_th;
-	u16 __packet_index;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __packet_index;
-	u16 __packet_index_th;
-#endif
+	u32 __reserved0[10];
 };
 
+
 /*
  * The eth aggregative context of Ustorm
  */
 struct ustorm_eth_ag_context {
-#if defined(__BIG_ENDIAN)
-	u8 __aux_counter_flags;
-	u8 __agg_vars2;
-	u8 __agg_vars1;
-	u8 __state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __state;
-	u8 __agg_vars1;
-	u8 __agg_vars2;
-	u8 __aux_counter_flags;
-#endif
+	u32 __reserved0;
 #if defined(__BIG_ENDIAN)
 	u8 cdu_usage;
-	u8 __agg_misc2;
-	u16 __agg_misc1;
+	u8 __reserved2;
+	u16 __reserved1;
 #elif defined(__LITTLE_ENDIAN)
-	u16 __agg_misc1;
-	u8 __agg_misc2;
+	u16 __reserved1;
+	u8 __reserved2;
 	u8 cdu_usage;
 #endif
-	u32 __agg_misc4;
-#if defined(__BIG_ENDIAN)
-	u8 __agg_val3_th;
-	u8 __agg_val3;
-	u16 __agg_misc3;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_misc3;
-	u8 __agg_val3;
-	u8 __agg_val3_th;
-#endif
-	u32 __agg_val1;
-	u32 __agg_misc4_th;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val2_th;
-	u16 __agg_val2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val2;
-	u16 __agg_val2_th;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __reserved2;
-	u8 __decision_rules;
-	u8 __decision_rule_enable_bits;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __decision_rule_enable_bits;
-	u8 __decision_rules;
-	u16 __reserved2;
-#endif
+	u32 __reserved3[6];
 };
 
 /*
@@ -2022,18 +1999,16 @@
  */
 struct eth_tx_bd_flags {
 	u8 as_bitfield;
-#define ETH_TX_BD_FLAGS_VLAN_TAG (0x1<<0)
-#define ETH_TX_BD_FLAGS_VLAN_TAG_SHIFT 0
-#define ETH_TX_BD_FLAGS_IP_CSUM (0x1<<1)
-#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT 1
-#define ETH_TX_BD_FLAGS_L4_CSUM (0x1<<2)
-#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT 2
-#define ETH_TX_BD_FLAGS_END_BD (0x1<<3)
-#define ETH_TX_BD_FLAGS_END_BD_SHIFT 3
+#define ETH_TX_BD_FLAGS_IP_CSUM (0x1<<0)
+#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT 0
+#define ETH_TX_BD_FLAGS_L4_CSUM (0x1<<1)
+#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT 1
+#define ETH_TX_BD_FLAGS_VLAN_MODE (0x3<<2)
+#define ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT 2
 #define ETH_TX_BD_FLAGS_START_BD (0x1<<4)
 #define ETH_TX_BD_FLAGS_START_BD_SHIFT 4
-#define ETH_TX_BD_FLAGS_HDR_POOL (0x1<<5)
-#define ETH_TX_BD_FLAGS_HDR_POOL_SHIFT 5
+#define ETH_TX_BD_FLAGS_IS_UDP (0x1<<5)
+#define ETH_TX_BD_FLAGS_IS_UDP_SHIFT 5
 #define ETH_TX_BD_FLAGS_SW_LSO (0x1<<6)
 #define ETH_TX_BD_FLAGS_SW_LSO_SHIFT 6
 #define ETH_TX_BD_FLAGS_IPV6 (0x1<<7)
@@ -2048,7 +2023,7 @@
 	__le32 addr_hi;
 	__le16 nbd;
 	__le16 nbytes;
-	__le16 vlan;
+	__le16 vlan_or_ethertype;
 	struct eth_tx_bd_flags bd_flags;
 	u8 general_data;
 #define ETH_TX_START_BD_HDR_NBDS (0x3F<<0)
@@ -2061,48 +2036,48 @@
  * Tx regular BD structure
  */
 struct eth_tx_bd {
-	u32 addr_lo;
-	u32 addr_hi;
-	u16 total_pkt_bytes;
-	u16 nbytes;
+	__le32 addr_lo;
+	__le32 addr_hi;
+	__le16 total_pkt_bytes;
+	__le16 nbytes;
 	u8 reserved[4];
 };
 
 /*
- * Tx parsing BD structure for ETH,Relevant in START
+ * Tx parsing BD structure for ETH E1/E1h
  */
-struct eth_tx_parse_bd {
+struct eth_tx_parse_bd_e1x {
 	u8 global_data;
-#define ETH_TX_PARSE_BD_IP_HDR_START_OFFSET (0xF<<0)
-#define ETH_TX_PARSE_BD_IP_HDR_START_OFFSET_SHIFT 0
-#define ETH_TX_PARSE_BD_UDP_CS_FLG (0x1<<4)
-#define ETH_TX_PARSE_BD_UDP_CS_FLG_SHIFT 4
-#define ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN (0x1<<5)
-#define ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN_SHIFT 5
-#define ETH_TX_PARSE_BD_LLC_SNAP_EN (0x1<<6)
-#define ETH_TX_PARSE_BD_LLC_SNAP_EN_SHIFT 6
-#define ETH_TX_PARSE_BD_NS_FLG (0x1<<7)
-#define ETH_TX_PARSE_BD_NS_FLG_SHIFT 7
+#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W (0xF<<0)
+#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W_SHIFT 0
+#define ETH_TX_PARSE_BD_E1X_RESERVED0 (0x1<<4)
+#define ETH_TX_PARSE_BD_E1X_RESERVED0_SHIFT 4
+#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN (0x1<<5)
+#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN_SHIFT 5
+#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN (0x1<<6)
+#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT 6
+#define ETH_TX_PARSE_BD_E1X_NS_FLG (0x1<<7)
+#define ETH_TX_PARSE_BD_E1X_NS_FLG_SHIFT 7
 	u8 tcp_flags;
-#define ETH_TX_PARSE_BD_FIN_FLG (0x1<<0)
-#define ETH_TX_PARSE_BD_FIN_FLG_SHIFT 0
-#define ETH_TX_PARSE_BD_SYN_FLG (0x1<<1)
-#define ETH_TX_PARSE_BD_SYN_FLG_SHIFT 1
-#define ETH_TX_PARSE_BD_RST_FLG (0x1<<2)
-#define ETH_TX_PARSE_BD_RST_FLG_SHIFT 2
-#define ETH_TX_PARSE_BD_PSH_FLG (0x1<<3)
-#define ETH_TX_PARSE_BD_PSH_FLG_SHIFT 3
-#define ETH_TX_PARSE_BD_ACK_FLG (0x1<<4)
-#define ETH_TX_PARSE_BD_ACK_FLG_SHIFT 4
-#define ETH_TX_PARSE_BD_URG_FLG (0x1<<5)
-#define ETH_TX_PARSE_BD_URG_FLG_SHIFT 5
-#define ETH_TX_PARSE_BD_ECE_FLG (0x1<<6)
-#define ETH_TX_PARSE_BD_ECE_FLG_SHIFT 6
-#define ETH_TX_PARSE_BD_CWR_FLG (0x1<<7)
-#define ETH_TX_PARSE_BD_CWR_FLG_SHIFT 7
-	u8 ip_hlen;
+#define ETH_TX_PARSE_BD_E1X_FIN_FLG (0x1<<0)
+#define ETH_TX_PARSE_BD_E1X_FIN_FLG_SHIFT 0
+#define ETH_TX_PARSE_BD_E1X_SYN_FLG (0x1<<1)
+#define ETH_TX_PARSE_BD_E1X_SYN_FLG_SHIFT 1
+#define ETH_TX_PARSE_BD_E1X_RST_FLG (0x1<<2)
+#define ETH_TX_PARSE_BD_E1X_RST_FLG_SHIFT 2
+#define ETH_TX_PARSE_BD_E1X_PSH_FLG (0x1<<3)
+#define ETH_TX_PARSE_BD_E1X_PSH_FLG_SHIFT 3
+#define ETH_TX_PARSE_BD_E1X_ACK_FLG (0x1<<4)
+#define ETH_TX_PARSE_BD_E1X_ACK_FLG_SHIFT 4
+#define ETH_TX_PARSE_BD_E1X_URG_FLG (0x1<<5)
+#define ETH_TX_PARSE_BD_E1X_URG_FLG_SHIFT 5
+#define ETH_TX_PARSE_BD_E1X_ECE_FLG (0x1<<6)
+#define ETH_TX_PARSE_BD_E1X_ECE_FLG_SHIFT 6
+#define ETH_TX_PARSE_BD_E1X_CWR_FLG (0x1<<7)
+#define ETH_TX_PARSE_BD_E1X_CWR_FLG_SHIFT 7
+	u8 ip_hlen_w;
 	s8 reserved;
-	__le16 total_hlen;
+	__le16 total_hlen_w;
 	__le16 tcp_pseudo_csum;
 	__le16 lso_mss;
 	__le16 ip_id;
@@ -2110,6 +2085,27 @@
 };
 
 /*
+ * Tx parsing BD structure for ETH E2
+ */
+struct eth_tx_parse_bd_e2 {
+	__le16 dst_mac_addr_lo;
+	__le16 dst_mac_addr_mid;
+	__le16 dst_mac_addr_hi;
+	__le16 src_mac_addr_lo;
+	__le16 src_mac_addr_mid;
+	__le16 src_mac_addr_hi;
+	__le32 parsing_data;
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W (0x1FFF<<0)
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT 0
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<13)
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 13
+#define ETH_TX_PARSE_BD_E2_LSO_MSS (0x3FFF<<17)
+#define ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT 17
+#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<31)
+#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR_SHIFT 31
+};
+
+/*
  * The last BD in the BD memory will hold a pointer to the next BD memory
  */
 struct eth_tx_next_bd {
@@ -2124,79 +2120,24 @@
 union eth_tx_bd_types {
 	struct eth_tx_start_bd start_bd;
 	struct eth_tx_bd reg_bd;
-	struct eth_tx_parse_bd parse_bd;
+	struct eth_tx_parse_bd_e1x parse_bd_e1x;
+	struct eth_tx_parse_bd_e2 parse_bd_e2;
 	struct eth_tx_next_bd next_bd;
 };
 
+
 /*
  * The eth storm context of Xstorm
  */
 struct xstorm_eth_st_context {
-	u32 tx_bd_page_base_lo;
-	u32 tx_bd_page_base_hi;
-#if defined(__BIG_ENDIAN)
-	u16 tx_bd_cons;
-	u8 statistics_data;
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_COUNTER_ID (0x7F<<0)
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_COUNTER_ID_SHIFT 0
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE (0x1<<7)
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE_SHIFT 7
-	u8 __local_tx_bd_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __local_tx_bd_prod;
-	u8 statistics_data;
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_COUNTER_ID (0x7F<<0)
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_COUNTER_ID_SHIFT 0
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE (0x1<<7)
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE_SHIFT 7
-	u16 tx_bd_cons;
-#endif
-	u32 __reserved1;
-	u32 __reserved2;
-#if defined(__BIG_ENDIAN)
-	u8 __ram_cache_index;
-	u8 __double_buffer_client;
-	u16 __pkt_cons;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __pkt_cons;
-	u8 __double_buffer_client;
-	u8 __ram_cache_index;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __statistics_address;
-	u16 __gso_next;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __gso_next;
-	u16 __statistics_address;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __local_tx_bd_cons;
-	u8 safc_group_num;
-	u8 safc_group_en;
-	u8 __is_eth_conn;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __is_eth_conn;
-	u8 safc_group_en;
-	u8 safc_group_num;
-	u8 __local_tx_bd_cons;
-#endif
-	union eth_tx_bd_types __bds[13];
+	u32 reserved0[60];
 };
 
 /*
  * The eth storm context of Cstorm
  */
 struct cstorm_eth_st_context {
-#if defined(__BIG_ENDIAN)
-	u16 __reserved0;
-	u8 sb_index_number;
-	u8 status_block_id;
-#elif defined(__LITTLE_ENDIAN)
-	u8 status_block_id;
-	u8 sb_index_number;
-	u16 __reserved0;
-#endif
-	u32 __reserved1[3];
+	u32 __reserved0[4];
 };
 
 /*
@@ -2244,104 +2185,115 @@
 
 
 /*
- * cstorm default status block, generated by ustorm
+ * client init fc data
  */
-struct cstorm_def_status_block_u {
-	__le16 index_values[HC_USTORM_DEF_SB_NUM_INDICES];
-	__le16 status_block_index;
-	u8 func;
+struct client_init_fc_data {
+	__le16 cqe_pause_thr_low;
+	__le16 cqe_pause_thr_high;
+	__le16 bd_pause_thr_low;
+	__le16 bd_pause_thr_high;
+	__le16 sge_pause_thr_low;
+	__le16 sge_pause_thr_high;
+	__le16 rx_cos_mask;
+	u8 safc_group_num;
+	u8 safc_group_en_flg;
+	u8 traffic_type;
+	u8 reserved0;
+	__le16 reserved1;
+	__le32 reserved2;
+};
+
+
+/*
+ * client init ramrod data
+ */
+struct client_init_general_data {
+	u8 client_id;
+	u8 statistics_counter_id;
+	u8 statistics_en_flg;
+	u8 is_fcoe_flg;
+	u8 activate_flg;
+	u8 sp_client_id;
+	__le16 reserved0;
+	__le32 reserved1[2];
+};
+
+
+/*
+ * client init rx data
+ */
+struct client_init_rx_data {
+	u8 tpa_en_flg;
+	u8 vmqueue_mode_en_flg;
+	u8 extra_data_over_sgl_en_flg;
+	u8 cache_line_alignment_log_size;
+	u8 enable_dynamic_hc;
+	u8 max_sges_for_packet;
+	u8 client_qzone_id;
+	u8 drop_ip_cs_err_flg;
+	u8 drop_tcp_cs_err_flg;
+	u8 drop_ttl0_flg;
+	u8 drop_udp_cs_err_flg;
+	u8 inner_vlan_removal_enable_flg;
+	u8 outer_vlan_removal_enable_flg;
 	u8 status_block_id;
-	__le32 __flags;
+	u8 rx_sb_index_number;
+	u8 reserved0[3];
+	__le16 bd_buff_size;
+	__le16 sge_buff_size;
+	__le16 mtu;
+	struct regpair bd_page_base;
+	struct regpair sge_page_base;
+	struct regpair cqe_page_base;
+	u8 is_leading_rss;
+	u8 is_approx_mcast;
+	__le16 max_agg_size;
+	__le32 reserved2[3];
 };
 
 /*
- * cstorm default status block, generated by cstorm
+ * client init tx data
  */
-struct cstorm_def_status_block_c {
-	__le16 index_values[HC_CSTORM_DEF_SB_NUM_INDICES];
-	__le16 status_block_index;
-	u8 func;
-	u8 status_block_id;
-	__le32 __flags;
+struct client_init_tx_data {
+	u8 enforce_security_flg;
+	u8 tx_status_block_id;
+	u8 tx_sb_index_number;
+	u8 reserved0;
+	__le16 mtu;
+	__le16 reserved1;
+	struct regpair tx_bd_page_base;
+	__le32 reserved2[2];
 };
 
 /*
- * xstorm status block
+ * client init ramrod data
  */
-struct xstorm_def_status_block {
-	__le16 index_values[HC_XSTORM_DEF_SB_NUM_INDICES];
-	__le16 status_block_index;
-	u8 func;
-	u8 status_block_id;
-	__le32 __flags;
-};
-
-/*
- * tstorm status block
- */
-struct tstorm_def_status_block {
-	__le16 index_values[HC_TSTORM_DEF_SB_NUM_INDICES];
-	__le16 status_block_index;
-	u8 func;
-	u8 status_block_id;
-	__le32 __flags;
-};
-
-/*
- * host status block
- */
-struct host_def_status_block {
-	struct atten_def_status_block atten_status_block;
-	struct cstorm_def_status_block_u u_def_status_block;
-	struct cstorm_def_status_block_c c_def_status_block;
-	struct xstorm_def_status_block x_def_status_block;
-	struct tstorm_def_status_block t_def_status_block;
+struct client_init_ramrod_data {
+	struct client_init_general_data general;
+	struct client_init_rx_data rx;
+	struct client_init_tx_data tx;
+	struct client_init_fc_data fc;
 };
 
 
 /*
- * cstorm status block, generated by ustorm
+ * The data contain client ID need to the ramrod
  */
-struct cstorm_status_block_u {
-	__le16 index_values[HC_USTORM_SB_NUM_INDICES];
-	__le16 status_block_index;
-	u8 func;
-	u8 status_block_id;
-	__le32 __flags;
-};
-
-/*
- * cstorm status block, generated by cstorm
- */
-struct cstorm_status_block_c {
-	__le16 index_values[HC_CSTORM_SB_NUM_INDICES];
-	__le16 status_block_index;
-	u8 func;
-	u8 status_block_id;
-	__le32 __flags;
-};
-
-/*
- * host status block
- */
-struct host_status_block {
-	struct cstorm_status_block_u u_status_block;
-	struct cstorm_status_block_c c_status_block;
-};
-
-
-/*
- * The data for RSS setup ramrod
- */
-struct eth_client_setup_ramrod_data {
+struct eth_common_ramrod_data {
 	u32 client_id;
-	u8 is_rdma;
-	u8 is_fcoe;
-	u16 reserved1;
+	u32 reserved1;
 };
 
 
 /*
+ * union for sgl and raw data.
+ */
+union eth_sgl_or_raw_data {
+	__le16 sgl[8];
+	u32 raw_data[4];
+};
+
+/*
  * regular eth FP CQE parameters struct
  */
 struct eth_fast_path_rx_cqe {
@@ -2358,8 +2310,8 @@
 #define ETH_FAST_PATH_RX_CQE_START_FLG_SHIFT 4
 #define ETH_FAST_PATH_RX_CQE_END_FLG (0x1<<5)
 #define ETH_FAST_PATH_RX_CQE_END_FLG_SHIFT 5
-#define ETH_FAST_PATH_RX_CQE_RESERVED0 (0x3<<6)
-#define ETH_FAST_PATH_RX_CQE_RESERVED0_SHIFT 6
+#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL (0x3<<6)
+#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL_SHIFT 6
 	u8 status_flags;
 #define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE (0x7<<0)
 #define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE_SHIFT 0
@@ -2380,7 +2332,7 @@
 	__le16 pkt_len;
 	__le16 len_on_bd;
 	struct parsing_flags pars_flags;
-	__le16 sgl[8];
+	union eth_sgl_or_raw_data sgl_or_raw_data;
 };
 
 
@@ -2392,11 +2344,10 @@
 	u32 reserved0;
 };
 
-
 /*
  * The data for statistics query ramrod
  */
-struct eth_query_ramrod_data {
+struct common_query_ramrod_data {
 #if defined(__BIG_ENDIAN)
 	u8 reserved0;
 	u8 collect_port;
@@ -2479,9 +2430,9 @@
 	__le16 type;
 #define SPE_HDR_CONN_TYPE (0xFF<<0)
 #define SPE_HDR_CONN_TYPE_SHIFT 0
-#define SPE_HDR_COMMON_RAMROD (0xFF<<8)
-#define SPE_HDR_COMMON_RAMROD_SHIFT 8
-	__le16 reserved;
+#define SPE_HDR_FUNCTION_ID (0xFF<<8)
+#define SPE_HDR_FUNCTION_ID_SHIFT 8
+	__le16 reserved1;
 };
 
 /*
@@ -2489,12 +2440,10 @@
  */
 union eth_specific_data {
 	u8 protocol_data[8];
-	struct regpair mac_config_addr;
-	struct eth_client_setup_ramrod_data client_setup_ramrod_data;
+	struct regpair client_init_ramrod_init_data;
 	struct eth_halt_ramrod_data halt_ramrod_data;
-	struct regpair leading_cqe_addr;
 	struct regpair update_data_addr;
-	struct eth_query_ramrod_data query_ramrod_data;
+	struct eth_common_ramrod_data common_ramrod_data;
 };
 
 /*
@@ -2519,7 +2468,7 @@
  */
 struct tstorm_eth_function_common_config {
 #if defined(__BIG_ENDIAN)
-	u8 leading_client_id;
+	u8 reserved1;
 	u8 rss_result_mask;
 	u16 config_flags;
 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
@@ -2532,16 +2481,12 @@
 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_DEFAULT_ENABLE (0x1<<7)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_DEFAULT_ENABLE_SHIFT 7
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_IN_CAM (0x1<<8)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_IN_CAM_SHIFT 8
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM (0x1<<9)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM_SHIFT 9
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<10)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 10
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x1F<<11)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 11
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<7)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 7
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<8)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 8
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x7F<<9)
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 9
 #elif defined(__LITTLE_ENDIAN)
 	u16 config_flags;
 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
@@ -2554,18 +2499,14 @@
 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_DEFAULT_ENABLE (0x1<<7)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_DEFAULT_ENABLE_SHIFT 7
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_IN_CAM (0x1<<8)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_IN_CAM_SHIFT 8
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM (0x1<<9)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM_SHIFT 9
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<10)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 10
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x1F<<11)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 11
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<7)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 7
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<8)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 8
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x7F<<9)
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 9
 	u8 rss_result_mask;
-	u8 leading_client_id;
+	u8 reserved1;
 #endif
 	u16 vlan_id[2];
 };
@@ -2613,51 +2554,34 @@
 	u8 length;
 	u8 offset;
 	u16 client_id;
-	u32 reserved1;
-};
-
-/*
- * MAC address in list for ramrod
- */
-struct tstorm_cam_entry {
-	__le16 lsb_mac_addr;
-	__le16 middle_mac_addr;
-	__le16 msb_mac_addr;
-	__le16 flags;
-#define TSTORM_CAM_ENTRY_PORT_ID (0x1<<0)
-#define TSTORM_CAM_ENTRY_PORT_ID_SHIFT 0
-#define TSTORM_CAM_ENTRY_RSRVVAL0 (0x7<<1)
-#define TSTORM_CAM_ENTRY_RSRVVAL0_SHIFT 1
-#define TSTORM_CAM_ENTRY_RESERVED0 (0xFFF<<4)
-#define TSTORM_CAM_ENTRY_RESERVED0_SHIFT 4
-};
-
-/*
- * MAC filtering: CAM target table entry
- */
-struct tstorm_cam_target_table_entry {
-	u8 flags;
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST (0x1<<0)
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST_SHIFT 0
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_OVERRIDE_VLAN_REMOVAL (0x1<<1)
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_OVERRIDE_VLAN_REMOVAL_SHIFT 1
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_ACTION_TYPE (0x1<<2)
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_ACTION_TYPE_SHIFT 2
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_RDMA_MAC (0x1<<3)
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_RDMA_MAC_SHIFT 3
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_RESERVED0 (0xF<<4)
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_RESERVED0_SHIFT 4
-	u8 reserved1;
-	u16 vlan_id;
-	u32 clients_bit_vector;
+	u16 echo;
+	u16 reserved1;
 };
 
 /*
  * MAC address in list for ramrod
  */
 struct mac_configuration_entry {
-	struct tstorm_cam_entry cam_entry;
-	struct tstorm_cam_target_table_entry target_table_entry;
+	__le16 lsb_mac_addr;
+	__le16 middle_mac_addr;
+	__le16 msb_mac_addr;
+	__le16 vlan_id;
+	u8 pf_id;
+	u8 flags;
+#define MAC_CONFIGURATION_ENTRY_ACTION_TYPE (0x1<<0)
+#define MAC_CONFIGURATION_ENTRY_ACTION_TYPE_SHIFT 0
+#define MAC_CONFIGURATION_ENTRY_RDMA_MAC (0x1<<1)
+#define MAC_CONFIGURATION_ENTRY_RDMA_MAC_SHIFT 1
+#define MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE (0x3<<2)
+#define MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE_SHIFT 2
+#define MAC_CONFIGURATION_ENTRY_OVERRIDE_VLAN_REMOVAL (0x1<<4)
+#define MAC_CONFIGURATION_ENTRY_OVERRIDE_VLAN_REMOVAL_SHIFT 4
+#define MAC_CONFIGURATION_ENTRY_BROADCAST (0x1<<5)
+#define MAC_CONFIGURATION_ENTRY_BROADCAST_SHIFT 5
+#define MAC_CONFIGURATION_ENTRY_RESERVED1 (0x3<<6)
+#define MAC_CONFIGURATION_ENTRY_RESERVED1_SHIFT 6
+	u16 reserved0;
+	u32 clients_bit_vector;
 };
 
 /*
@@ -2670,37 +2594,6 @@
 
 
 /*
- * MAC address in list for ramrod
- */
-struct mac_configuration_entry_e1h {
-	__le16 lsb_mac_addr;
-	__le16 middle_mac_addr;
-	__le16 msb_mac_addr;
-	__le16 vlan_id;
-	__le16 e1hov_id;
-	u8 reserved0;
-	u8 flags;
-#define MAC_CONFIGURATION_ENTRY_E1H_PORT (0x1<<0)
-#define MAC_CONFIGURATION_ENTRY_E1H_PORT_SHIFT 0
-#define MAC_CONFIGURATION_ENTRY_E1H_ACTION_TYPE (0x1<<1)
-#define MAC_CONFIGURATION_ENTRY_E1H_ACTION_TYPE_SHIFT 1
-#define MAC_CONFIGURATION_ENTRY_E1H_RDMA_MAC (0x1<<2)
-#define MAC_CONFIGURATION_ENTRY_E1H_RDMA_MAC_SHIFT 2
-#define MAC_CONFIGURATION_ENTRY_E1H_RESERVED1 (0x1F<<3)
-#define MAC_CONFIGURATION_ENTRY_E1H_RESERVED1_SHIFT 3
-	u32 clients_bit_vector;
-};
-
-/*
- * MAC filtering configuration command
- */
-struct mac_configuration_cmd_e1h {
-	struct mac_configuration_hdr hdr;
-	struct mac_configuration_entry_e1h config_table[32];
-};
-
-
-/*
  * approximate-match multicast filtering for E1H per function in Tstorm
  */
 struct tstorm_eth_approximate_match_multicast_filtering {
@@ -2709,65 +2602,6 @@
 
 
 /*
- * Configuration parameters per client in Tstorm
- */
-struct tstorm_eth_client_config {
-#if defined(__BIG_ENDIAN)
-	u8 reserved0;
-	u8 statistics_counter_id;
-	u16 mtu;
-#elif defined(__LITTLE_ENDIAN)
-	u16 mtu;
-	u8 statistics_counter_id;
-	u8 reserved0;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 drop_flags;
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR (0x1<<0)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR_SHIFT 0
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR (0x1<<1)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR_SHIFT 1
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0 (0x1<<2)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0_SHIFT 2
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR (0x1<<3)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR_SHIFT 3
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2 (0xFFF<<4)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2_SHIFT 4
-	u16 config_flags;
-#define TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE (0x1<<0)
-#define TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE_SHIFT 0
-#define TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE (0x1<<1)
-#define TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE_SHIFT 1
-#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE (0x1<<2)
-#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE_SHIFT 2
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1 (0x1FFF<<3)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1_SHIFT 3
-#elif defined(__LITTLE_ENDIAN)
-	u16 config_flags;
-#define TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE (0x1<<0)
-#define TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE_SHIFT 0
-#define TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE (0x1<<1)
-#define TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE_SHIFT 1
-#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE (0x1<<2)
-#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE_SHIFT 2
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1 (0x1FFF<<3)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1_SHIFT 3
-	u16 drop_flags;
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR (0x1<<0)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR_SHIFT 0
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR (0x1<<1)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR_SHIFT 1
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0 (0x1<<2)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0_SHIFT 2
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR (0x1<<3)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR_SHIFT 3
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2 (0xFFF<<4)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2_SHIFT 4
-#endif
-};
-
-
-/*
  * MAC filtering configuration parameters per port in Tstorm
  */
 struct tstorm_eth_mac_filter_config {
@@ -2777,8 +2611,8 @@
 	u32 mcast_accept_all;
 	u32 bcast_drop_all;
 	u32 bcast_accept_all;
-	u32 strict_vlan;
 	u32 vlan_filter[2];
+	u32 unmatched_unicast;
 	u32 reserved;
 };
 
@@ -2801,41 +2635,6 @@
 
 
 /*
- * rx rings pause data for E1h only
- */
-struct ustorm_eth_rx_pause_data_e1h {
-#if defined(__BIG_ENDIAN)
-	u16 bd_thr_low;
-	u16 cqe_thr_low;
-#elif defined(__LITTLE_ENDIAN)
-	u16 cqe_thr_low;
-	u16 bd_thr_low;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 cos;
-	u16 sge_thr_low;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sge_thr_low;
-	u16 cos;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 bd_thr_high;
-	u16 cqe_thr_high;
-#elif defined(__LITTLE_ENDIAN)
-	u16 cqe_thr_high;
-	u16 bd_thr_high;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 reserved0;
-	u16 sge_thr_high;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sge_thr_high;
-	u16 reserved0;
-#endif
-};
-
-
-/*
  * Three RX producers for ETH
  */
 struct ustorm_eth_rx_producers {
@@ -2857,6 +2656,18 @@
 
 
 /*
+ * cfc delete event data
+ */
+struct cfc_del_event_data {
+	u32 cid;
+	u8 error;
+	u8 reserved0;
+	u16 reserved1;
+	u32 reserved2;
+};
+
+
+/*
  * per-port SAFC demo variables
  */
 struct cmng_flags_per_port {
@@ -2872,8 +2683,10 @@
 #define CMNG_FLAGS_PER_PORT_RATE_SHAPING_PROTOCOL_SHIFT 3
 #define CMNG_FLAGS_PER_PORT_FAIRNESS_COS (0x1<<4)
 #define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_SHIFT 4
-#define __CMNG_FLAGS_PER_PORT_RESERVED0 (0x7FFFFFF<<5)
-#define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 5
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE (0x1<<5)
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE_SHIFT 5
+#define __CMNG_FLAGS_PER_PORT_RESERVED0 (0x3FFFFFF<<6)
+#define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 6
 };
 
 
@@ -2907,30 +2720,92 @@
 	u8 __reserved0;
 	u16 __reserved1;
 #endif
+	u8 cos_to_traffic_types[MAX_COS_NUMBER];
+	u32 __reserved2;
 	u16 cos_to_pause_mask[NUM_OF_SAFC_BITS];
 };
 
 /*
+ * per-port PFC variables
+ */
+struct pfc_struct_per_port {
+	u8 priority_to_traffic_types[MAX_PFC_PRIORITIES];
+#if defined(__BIG_ENDIAN)
+	u16 pfc_pause_quanta_in_nanosec;
+	u8 __reserved0;
+	u8 priority_non_pausable_mask;
+#elif defined(__LITTLE_ENDIAN)
+	u8 priority_non_pausable_mask;
+	u8 __reserved0;
+	u16 pfc_pause_quanta_in_nanosec;
+#endif
+};
+
+/*
+ * Priority and cos
+ */
+struct priority_cos {
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u8 cos;
+	u8 priority;
+#elif defined(__LITTLE_ENDIAN)
+	u8 priority;
+	u8 cos;
+	u16 reserved1;
+#endif
+	u32 reserved2;
+};
+
+/*
  * Per-port congestion management variables
  */
 struct cmng_struct_per_port {
 	struct rate_shaping_vars_per_port rs_vars;
 	struct fairness_vars_per_port fair_vars;
 	struct safc_struct_per_port safc_vars;
+	struct pfc_struct_per_port pfc_vars;
+#if defined(__BIG_ENDIAN)
+	u16 __reserved1;
+	u8 dcb_enabled;
+	u8 llfc_mode;
+#elif defined(__LITTLE_ENDIAN)
+	u8 llfc_mode;
+	u8 dcb_enabled;
+	u16 __reserved1;
+#endif
+	struct priority_cos
+		traffic_type_to_priority_cos[MAX_PFC_TRAFFIC_TYPES];
 	struct cmng_flags_per_port flags;
 };
 
 
+
+/*
+ * Dynamic HC counters set by the driver
+ */
+struct hc_dynamic_drv_counter {
+	u32 val[HC_SB_MAX_DYNAMIC_INDICES];
+};
+
+/*
+ * zone A per-queue data
+ */
+struct cstorm_queue_zone_data {
+	struct hc_dynamic_drv_counter hc_dyn_drv_cnt;
+	struct regpair reserved[2];
+};
+
 /*
  * Dynamic host coalescing init parameters
  */
 struct dynamic_hc_config {
 	u32 threshold[3];
-	u8 shift_per_protocol[HC_USTORM_SB_NUM_INDICES];
-	u8 hc_timeout0[HC_USTORM_SB_NUM_INDICES];
-	u8 hc_timeout1[HC_USTORM_SB_NUM_INDICES];
-	u8 hc_timeout2[HC_USTORM_SB_NUM_INDICES];
-	u8 hc_timeout3[HC_USTORM_SB_NUM_INDICES];
+	u8 shift_per_protocol[HC_SB_MAX_DYNAMIC_INDICES];
+	u8 hc_timeout0[HC_SB_MAX_DYNAMIC_INDICES];
+	u8 hc_timeout1[HC_SB_MAX_DYNAMIC_INDICES];
+	u8 hc_timeout2[HC_SB_MAX_DYNAMIC_INDICES];
+	u8 hc_timeout3[HC_SB_MAX_DYNAMIC_INDICES];
 };
 
 
@@ -2954,7 +2829,7 @@
  * Common statistics collected by the Xstorm (per port)
  */
 struct xstorm_common_stats {
- struct xstorm_per_client_stats client_statistics[MAX_X_STAT_COUNTER_ID];
+	struct xstorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
 };
 
 /*
@@ -2991,7 +2866,7 @@
  */
 struct tstorm_common_stats {
 	struct tstorm_per_port_stats port_statistics;
- struct tstorm_per_client_stats client_statistics[MAX_T_STAT_COUNTER_ID];
+	struct tstorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
 };
 
 /*
@@ -3012,7 +2887,7 @@
  * Protocol-common statistics collected by the Ustorm
  */
 struct ustorm_common_stats {
- struct ustorm_per_client_stats client_statistics[MAX_U_STAT_COUNTER_ID];
+	struct ustorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
 };
 
 /*
@@ -3026,6 +2901,70 @@
 
 
 /*
+ * set mac event data
+ */
+struct set_mac_event_data {
+	u16 echo;
+	u16 reserved0;
+	u32 reserved1;
+	u32 reserved2;
+};
+
+/*
+ * union for all event ring message types
+ */
+union event_data {
+	struct set_mac_event_data set_mac_event;
+	struct cfc_del_event_data cfc_del_event;
+};
+
+
+/*
+ * per PF event ring data
+ */
+struct event_ring_data {
+	struct regpair base_addr;
+#if defined(__BIG_ENDIAN)
+	u8 index_id;
+	u8 sb_id;
+	u16 producer;
+#elif defined(__LITTLE_ENDIAN)
+	u16 producer;
+	u8 sb_id;
+	u8 index_id;
+#endif
+	u32 reserved0;
+};
+
+
+/*
+ * event ring message element (each element is 128 bits)
+ */
+struct event_ring_msg {
+	u8 opcode;
+	u8 reserved0;
+	u16 reserved1;
+	union event_data data;
+};
+
+/*
+ * event ring next page element (128 bits)
+ */
+struct event_ring_next {
+	struct regpair addr;
+	u32 reserved[2];
+};
+
+/*
+ * union for event ring element types (each element is 128 bits)
+ */
+union event_ring_elem {
+	struct event_ring_msg message;
+	struct event_ring_next next_page;
+};
+
+
+/*
  * per-vnic fairness variables
  */
 struct fairness_vars_per_vn {
@@ -3064,6 +3003,137 @@
 
 
 /*
+ * Dynamic Host-Coalescing - Driver(host) counters
+ */
+struct hc_dynamic_sb_drv_counters {
+	u32 dynamic_hc_drv_counter[HC_SB_MAX_DYNAMIC_INDICES];
+};
+
+
+/*
+ * 2 bytes. configuration/state parameters for a single protocol index
+ */
+struct hc_index_data {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define HC_INDEX_DATA_SM_ID (0x1<<0)
+#define HC_INDEX_DATA_SM_ID_SHIFT 0
+#define HC_INDEX_DATA_HC_ENABLED (0x1<<1)
+#define HC_INDEX_DATA_HC_ENABLED_SHIFT 1
+#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED (0x1<<2)
+#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED_SHIFT 2
+#define HC_INDEX_DATA_RESERVE (0x1F<<3)
+#define HC_INDEX_DATA_RESERVE_SHIFT 3
+	u8 timeout;
+#elif defined(__LITTLE_ENDIAN)
+	u8 timeout;
+	u8 flags;
+#define HC_INDEX_DATA_SM_ID (0x1<<0)
+#define HC_INDEX_DATA_SM_ID_SHIFT 0
+#define HC_INDEX_DATA_HC_ENABLED (0x1<<1)
+#define HC_INDEX_DATA_HC_ENABLED_SHIFT 1
+#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED (0x1<<2)
+#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED_SHIFT 2
+#define HC_INDEX_DATA_RESERVE (0x1F<<3)
+#define HC_INDEX_DATA_RESERVE_SHIFT 3
+#endif
+};
+
+
+/*
+ * HC state-machine
+ */
+struct hc_status_block_sm {
+#if defined(__BIG_ENDIAN)
+	u8 igu_seg_id;
+	u8 igu_sb_id;
+	u8 timer_value;
+	u8 __flags;
+#elif defined(__LITTLE_ENDIAN)
+	u8 __flags;
+	u8 timer_value;
+	u8 igu_sb_id;
+	u8 igu_seg_id;
+#endif
+	u32 time_to_expire;
+};
+
+/*
+ * hold PCI identification variables- used in various places in firmware
+ */
+struct pci_entity {
+#if defined(__BIG_ENDIAN)
+	u8 vf_valid;
+	u8 vf_id;
+	u8 vnic_id;
+	u8 pf_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 pf_id;
+	u8 vnic_id;
+	u8 vf_id;
+	u8 vf_valid;
+#endif
+};
+
+/*
+ * The fast-path status block meta-data, common to all chips
+ */
+struct hc_sb_data {
+	struct regpair host_sb_addr;
+	struct hc_status_block_sm state_machine[HC_SB_MAX_SM];
+	struct pci_entity p_func;
+#if defined(__BIG_ENDIAN)
+	u8 rsrv0;
+	u8 dhc_qzone_id;
+	u8 __dynamic_hc_level;
+	u8 same_igu_sb_1b;
+#elif defined(__LITTLE_ENDIAN)
+	u8 same_igu_sb_1b;
+	u8 __dynamic_hc_level;
+	u8 dhc_qzone_id;
+	u8 rsrv0;
+#endif
+	struct regpair rsrv1[2];
+};
+
+
+/*
+ * The fast-path status block meta-data
+ */
+struct hc_sp_status_block_data {
+	struct regpair host_sb_addr;
+#if defined(__BIG_ENDIAN)
+	u16 rsrv;
+	u8 igu_seg_id;
+	u8 igu_sb_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 igu_sb_id;
+	u8 igu_seg_id;
+	u16 rsrv;
+#endif
+	struct pci_entity p_func;
+};
+
+
+/*
+ * The fast-path status block meta-data
+ */
+struct hc_status_block_data_e1x {
+	struct hc_index_data index_data[HC_SB_MAX_INDICES_E1X];
+	struct hc_sb_data common;
+};
+
+
+/*
+ * The fast-path status block meta-data
+ */
+struct hc_status_block_data_e2 {
+	struct hc_index_data index_data[HC_SB_MAX_INDICES_E2];
+	struct hc_sb_data common;
+};
+
+
+/*
  * FW version stored in first line of pram
  */
 struct pram_fw_version {
@@ -3086,11 +3156,21 @@
 
 
 /*
+ * Ethernet slow path element
+ */
+union protocol_common_specific_data {
+	u8 protocol_data[8];
+	struct regpair phy_address;
+	struct regpair mac_config_addr;
+	struct common_query_ramrod_data query_ramrod_data;
+};
+
+/*
  * The send queue element
  */
 struct protocol_common_spe {
 	struct spe_hdr hdr;
-	struct regpair phy_address;
+	union protocol_common_specific_data data;
 };
 
 
@@ -3123,7 +3203,7 @@
  */
 struct slow_path_element {
 	struct spe_hdr hdr;
-	u8 protocol_data[8];
+	struct regpair protocol_data;
 };
 
 
@@ -3136,3 +3216,97 @@
 };
 
 
+/*
+ * per-port PFC variables
+ */
+struct storm_pfc_struct_per_port {
+#if defined(__BIG_ENDIAN)
+	u16 mid_mac_addr;
+	u16 msb_mac_addr;
+#elif defined(__LITTLE_ENDIAN)
+	u16 msb_mac_addr;
+	u16 mid_mac_addr;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 pfc_pause_quanta_in_nanosec;
+	u16 lsb_mac_addr;
+#elif defined(__LITTLE_ENDIAN)
+	u16 lsb_mac_addr;
+	u16 pfc_pause_quanta_in_nanosec;
+#endif
+};
+
+/*
+ * Per-port congestion management variables
+ */
+struct storm_cmng_struct_per_port {
+	struct storm_pfc_struct_per_port pfc_vars;
+};
+
+
+/*
+ * zone A per-queue data
+ */
+struct tstorm_queue_zone_data {
+	struct regpair reserved[4];
+};
+
+
+/*
+ * zone B per-VF data
+ */
+struct tstorm_vf_zone_data {
+	struct regpair reserved;
+};
+
+
+/*
+ * zone A per-queue data
+ */
+struct ustorm_queue_zone_data {
+	struct ustorm_eth_rx_producers eth_rx_producers;
+	struct regpair reserved[3];
+};
+
+
+/*
+ * zone B per-VF data
+ */
+struct ustorm_vf_zone_data {
+	struct regpair reserved;
+};
+
+
+/*
+ * data per VF-PF channel
+ */
+struct vf_pf_channel_data {
+#if defined(__BIG_ENDIAN)
+	u16 reserved0;
+	u8 valid;
+	u8 state;
+#elif defined(__LITTLE_ENDIAN)
+	u8 state;
+	u8 valid;
+	u16 reserved0;
+#endif
+	u32 reserved1;
+};
+
+
+/*
+ * zone A per-queue data
+ */
+struct xstorm_queue_zone_data {
+	struct regpair reserved[4];
+};
+
+
+/*
+ * zone B per-VF data
+ */
+struct xstorm_vf_zone_data {
+	struct regpair reserved;
+};
+
+#endif /* BNX2X_HSI_H */
diff --git a/drivers/net/bnx2x/bnx2x_init.h b/drivers/net/bnx2x/bnx2x_init.h
index 65b26cb..a9d5487 100644
--- a/drivers/net/bnx2x/bnx2x_init.h
+++ b/drivers/net/bnx2x/bnx2x_init.h
@@ -97,6 +97,9 @@
 #define MISC_AEU_BLOCK		35
 #define PGLUE_B_BLOCK		36
 #define IGU_BLOCK		37
+#define ATC_BLOCK		38
+#define QM_4PORT_BLOCK		39
+#define XSEM_4PORT_BLOCK		40
 
 
 /* Returns the index of start or end of a specific block stage in ops array*/
@@ -148,5 +151,46 @@
 	struct raw_op		raw;
 };
 
+#define INITOP_SET		0	/* set the HW directly */
+#define INITOP_CLEAR		1	/* clear the HW directly */
+#define INITOP_INIT		2	/* set the init-value array */
+
+/****************************************************************************
+* ILT management
+****************************************************************************/
+struct ilt_line {
+	dma_addr_t page_mapping;
+	void *page;
+	u32 size;
+};
+
+struct ilt_client_info {
+	u32 page_size;
+	u16 start;
+	u16 end;
+	u16 client_num;
+	u16 flags;
+#define ILT_CLIENT_SKIP_INIT	0x1
+#define ILT_CLIENT_SKIP_MEM	0x2
+};
+
+struct bnx2x_ilt {
+	u32 start_line;
+	struct ilt_line		*lines;
+	struct ilt_client_info	clients[4];
+#define ILT_CLIENT_CDU	0
+#define ILT_CLIENT_QM	1
+#define ILT_CLIENT_SRC	2
+#define ILT_CLIENT_TM	3
+};
+
+/****************************************************************************
+* SRC configuration
+****************************************************************************/
+struct src_ent {
+	u8 opaque[56];
+	u64 next;
+};
+
 #endif /* BNX2X_INIT_H */
 
diff --git a/drivers/net/bnx2x/bnx2x_init_ops.h b/drivers/net/bnx2x/bnx2x_init_ops.h
index 2b1363a..e65de78 100644
--- a/drivers/net/bnx2x/bnx2x_init_ops.h
+++ b/drivers/net/bnx2x/bnx2x_init_ops.h
@@ -151,6 +151,15 @@
 		bnx2x_init_ind_wr(bp, addr, data, len);
 }
 
+static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo, u32 val_hi)
+{
+	u32 wb_write[2];
+
+	wb_write[0] = val_lo;
+	wb_write[1] = val_hi;
+	REG_WR_DMAE_LEN(bp, reg, wb_write, 2);
+}
+
 static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len, u32 blob_off)
 {
 	const u8 *data = NULL;
@@ -477,18 +486,30 @@
 	REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order);
 	REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order);
 
-	if (r_order == MAX_RD_ORD)
+	if ((CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) && (r_order == MAX_RD_ORD))
 		REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
 
-	REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
+	if (CHIP_IS_E2(bp))
+		REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x8 << w_order));
+	else
+		REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
 
-	if (CHIP_IS_E1H(bp)) {
+	if (CHIP_IS_E1H(bp) || CHIP_IS_E2(bp)) {
 		/*    MPS      w_order     optimal TH      presently TH
 		 *    128         0             0               2
 		 *    256         1             1               3
 		 *    >=512       2             2               3
 		 */
-		val = ((w_order == 0) ? 2 : 3);
+		/* DMAE is special */
+		if (CHIP_IS_E2(bp)) {
+			/* E2 can use optimal TH */
+			val = w_order;
+			REG_WR(bp, PXP2_REG_WR_DMAE_MPS, val);
+		} else {
+			val = ((w_order == 0) ? 2 : 3);
+			REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2);
+		}
+
 		REG_WR(bp, PXP2_REG_WR_HC_MPS, val);
 		REG_WR(bp, PXP2_REG_WR_USDM_MPS, val);
 		REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val);
@@ -498,9 +519,344 @@
 		REG_WR(bp, PXP2_REG_WR_TM_MPS, val);
 		REG_WR(bp, PXP2_REG_WR_SRC_MPS, val);
 		REG_WR(bp, PXP2_REG_WR_DBG_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */
 		REG_WR(bp, PXP2_REG_WR_CDU_MPS, val);
 	}
+
+	/* Validate number of tags suppoted by device */
+#define PCIE_REG_PCIER_TL_HDR_FC_ST		0x2980
+	val = REG_RD(bp, PCIE_REG_PCIER_TL_HDR_FC_ST);
+	val &= 0xFF;
+	if (val <= 0x20)
+		REG_WR(bp, PXP2_REG_PGL_TAGS_LIMIT, 0x20);
+}
+
+/****************************************************************************
+* ILT management
+****************************************************************************/
+/*
+ * This codes hides the low level HW interaction for ILT management and
+ * configuration. The API consists of a shadow ILT table which is set by the
+ * driver and a set of routines to use it to configure the HW.
+ *
+ */
+
+/* ILT HW init operations */
+
+/* ILT memory management operations */
+#define ILT_MEMOP_ALLOC		0
+#define ILT_MEMOP_FREE		1
+
+/* the phys address is shifted right 12 bits and has an added
+ * 1=valid bit added to the 53rd bit
+ * then since this is a wide register(TM)
+ * we split it into two 32 bit writes
+ */
+#define ILT_ADDR1(x)		((u32)(((u64)x >> 12) & 0xFFFFFFFF))
+#define ILT_ADDR2(x)		((u32)((1 << 20) | ((u64)x >> 44)))
+#define ILT_RANGE(f, l)		(((l) << 10) | f)
+
+static int bnx2x_ilt_line_mem_op(struct bnx2x *bp, struct ilt_line *line,
+				 u32 size, u8 memop)
+{
+	if (memop == ILT_MEMOP_FREE) {
+		BNX2X_ILT_FREE(line->page, line->page_mapping, line->size);
+		return 0;
+	}
+	BNX2X_ILT_ZALLOC(line->page, &line->page_mapping, size);
+	if (!line->page)
+		return -1;
+	line->size = size;
+	return 0;
+}
+
+
+static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num, u8 memop)
+{
+	int i, rc;
+	struct bnx2x_ilt *ilt = BP_ILT(bp);
+	struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
+
+	if (!ilt || !ilt->lines)
+		return -1;
+
+	if (ilt_cli->flags & (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM))
+		return 0;
+
+	for (rc = 0, i = ilt_cli->start; i <= ilt_cli->end && !rc; i++) {
+		rc = bnx2x_ilt_line_mem_op(bp, &ilt->lines[i],
+					   ilt_cli->page_size, memop);
+	}
+	return rc;
+}
+
+int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop)
+{
+	int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop);
+	if (!rc)
+		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_QM, memop);
+	if (!rc)
+		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);
+	if (!rc)
+		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);
+
+	return rc;
+}
+
+static void bnx2x_ilt_line_wr(struct bnx2x *bp, int abs_idx,
+			      dma_addr_t page_mapping)
+{
+	u32 reg;
+
+	if (CHIP_IS_E1(bp))
+		reg = PXP2_REG_RQ_ONCHIP_AT + abs_idx*8;
+	else
+		reg = PXP2_REG_RQ_ONCHIP_AT_B0 + abs_idx*8;
+
+	bnx2x_wr_64(bp, reg, ILT_ADDR1(page_mapping), ILT_ADDR2(page_mapping));
+}
+
+static void bnx2x_ilt_line_init_op(struct bnx2x *bp, struct bnx2x_ilt *ilt,
+				   int idx, u8 initop)
+{
+	dma_addr_t	null_mapping;
+	int abs_idx = ilt->start_line + idx;
+
+
+	switch (initop) {
+	case INITOP_INIT:
+		/* set in the init-value array */
+	case INITOP_SET:
+		bnx2x_ilt_line_wr(bp, abs_idx, ilt->lines[idx].page_mapping);
+		break;
+	case INITOP_CLEAR:
+		null_mapping = 0;
+		bnx2x_ilt_line_wr(bp, abs_idx, null_mapping);
+		break;
+	}
+}
+
+void bnx2x_ilt_boundry_init_op(struct bnx2x *bp,
+				      struct ilt_client_info *ilt_cli,
+				      u32 ilt_start, u8 initop)
+{
+	u32 start_reg = 0;
+	u32 end_reg = 0;
+
+	/* The boundary is either SET or INIT,
+	   CLEAR => SET and for now SET ~~ INIT */
+
+	/* find the appropriate regs */
+	if (CHIP_IS_E1(bp)) {
+		switch (ilt_cli->client_num) {
+		case ILT_CLIENT_CDU:
+			start_reg = PXP2_REG_PSWRQ_CDU0_L2P;
+			break;
+		case ILT_CLIENT_QM:
+			start_reg = PXP2_REG_PSWRQ_QM0_L2P;
+			break;
+		case ILT_CLIENT_SRC:
+			start_reg = PXP2_REG_PSWRQ_SRC0_L2P;
+			break;
+		case ILT_CLIENT_TM:
+			start_reg = PXP2_REG_PSWRQ_TM0_L2P;
+			break;
+		}
+		REG_WR(bp, start_reg + BP_FUNC(bp)*4,
+		       ILT_RANGE((ilt_start + ilt_cli->start),
+				 (ilt_start + ilt_cli->end)));
+	} else {
+		switch (ilt_cli->client_num) {
+		case ILT_CLIENT_CDU:
+			start_reg = PXP2_REG_RQ_CDU_FIRST_ILT;
+			end_reg = PXP2_REG_RQ_CDU_LAST_ILT;
+			break;
+		case ILT_CLIENT_QM:
+			start_reg = PXP2_REG_RQ_QM_FIRST_ILT;
+			end_reg = PXP2_REG_RQ_QM_LAST_ILT;
+			break;
+		case ILT_CLIENT_SRC:
+			start_reg = PXP2_REG_RQ_SRC_FIRST_ILT;
+			end_reg = PXP2_REG_RQ_SRC_LAST_ILT;
+			break;
+		case ILT_CLIENT_TM:
+			start_reg = PXP2_REG_RQ_TM_FIRST_ILT;
+			end_reg = PXP2_REG_RQ_TM_LAST_ILT;
+			break;
+		}
+		REG_WR(bp, start_reg, (ilt_start + ilt_cli->start));
+		REG_WR(bp, end_reg, (ilt_start + ilt_cli->end));
+	}
+}
+
+void bnx2x_ilt_client_init_op_ilt(struct bnx2x *bp, struct bnx2x_ilt *ilt,
+				  struct ilt_client_info *ilt_cli, u8 initop)
+{
+	int i;
+
+	if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT)
+		return;
+
+	for (i = ilt_cli->start; i <= ilt_cli->end; i++)
+		bnx2x_ilt_line_init_op(bp, ilt, i, initop);
+
+	/* init/clear the ILT boundries */
+	bnx2x_ilt_boundry_init_op(bp, ilt_cli, ilt->start_line, initop);
+}
+
+void bnx2x_ilt_client_init_op(struct bnx2x *bp,
+			      struct ilt_client_info *ilt_cli, u8 initop)
+{
+	struct bnx2x_ilt *ilt = BP_ILT(bp);
+
+	bnx2x_ilt_client_init_op_ilt(bp, ilt, ilt_cli, initop);
+}
+
+static void bnx2x_ilt_client_id_init_op(struct bnx2x *bp,
+					int cli_num, u8 initop)
+{
+	struct bnx2x_ilt *ilt = BP_ILT(bp);
+	struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
+
+	bnx2x_ilt_client_init_op(bp, ilt_cli, initop);
+}
+
+void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop)
+{
+	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop);
+	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop);
+	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
+	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop);
+}
+
+static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num,
+					    u32 psz_reg, u8 initop)
+{
+	struct bnx2x_ilt *ilt = BP_ILT(bp);
+	struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
+
+	if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT)
+		return;
+
+	switch (initop) {
+	case INITOP_INIT:
+		/* set in the init-value array */
+	case INITOP_SET:
+		REG_WR(bp, psz_reg, ILOG2(ilt_cli->page_size >> 12));
+		break;
+	case INITOP_CLEAR:
+		break;
+	}
+}
+
+/*
+ * called during init common stage, ilt clients should be initialized
+ * prioir to calling this function
+ */
+void bnx2x_ilt_init_page_size(struct bnx2x *bp, u8 initop)
+{
+	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_CDU,
+				  PXP2_REG_RQ_CDU_P_SIZE, initop);
+	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_QM,
+				  PXP2_REG_RQ_QM_P_SIZE, initop);
+	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_SRC,
+				  PXP2_REG_RQ_SRC_P_SIZE, initop);
+	bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_TM,
+				  PXP2_REG_RQ_TM_P_SIZE, initop);
+}
+
+/****************************************************************************
+* QM initializations
+****************************************************************************/
+#define QM_QUEUES_PER_FUNC	16 /* E1 has 32, but only 16 are used */
+#define QM_INIT_MIN_CID_COUNT	31
+#define QM_INIT(cid_cnt)	(cid_cnt > QM_INIT_MIN_CID_COUNT)
+
+/* called during init port stage */
+void bnx2x_qm_init_cid_count(struct bnx2x *bp, int qm_cid_count,
+			     u8 initop)
+{
+	int port = BP_PORT(bp);
+
+	if (QM_INIT(qm_cid_count)) {
+		switch (initop) {
+		case INITOP_INIT:
+			/* set in the init-value array */
+		case INITOP_SET:
+			REG_WR(bp, QM_REG_CONNNUM_0 + port*4,
+			       qm_cid_count/16 - 1);
+			break;
+		case INITOP_CLEAR:
+			break;
+		}
+	}
+}
+
+static void bnx2x_qm_set_ptr_table(struct bnx2x *bp, int qm_cid_count)
+{
+	int i;
+	u32 wb_data[2];
+
+	wb_data[0] = wb_data[1] = 0;
+
+	for (i = 0; i < 4 * QM_QUEUES_PER_FUNC; i++) {
+		REG_WR(bp, QM_REG_BASEADDR + i*4,
+		       qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC));
+		bnx2x_init_ind_wr(bp, QM_REG_PTRTBL + i*8,
+				  wb_data, 2);
+
+		if (CHIP_IS_E1H(bp)) {
+			REG_WR(bp, QM_REG_BASEADDR_EXT_A + i*4,
+			       qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC));
+			bnx2x_init_ind_wr(bp, QM_REG_PTRTBL_EXT_A + i*8,
+					  wb_data, 2);
+		}
+	}
+}
+
+/* called during init common stage */
+void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
+			     u8 initop)
+{
+	if (!QM_INIT(qm_cid_count))
+		return;
+
+	switch (initop) {
+	case INITOP_INIT:
+		/* set in the init-value array */
+	case INITOP_SET:
+		bnx2x_qm_set_ptr_table(bp, qm_cid_count);
+		break;
+	case INITOP_CLEAR:
+		break;
+	}
+}
+
+/****************************************************************************
+* SRC initializations
+****************************************************************************/
+
+/* called during init func stage */
+void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
+		       dma_addr_t t2_mapping, int src_cid_count)
+{
+	int i;
+	int port = BP_PORT(bp);
+
+	/* Initialize T2 */
+	for (i = 0; i < src_cid_count-1; i++)
+		t2[i].next = (u64)(t2_mapping + (i+1)*sizeof(struct src_ent));
+
+	/* tell the searcher where the T2 table is */
+	REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, src_cid_count);
+
+	bnx2x_wr_64(bp, SRC_REG_FIRSTFREE0 + port*16,
+		    U64_LO(t2_mapping), U64_HI(t2_mapping));
+
+	bnx2x_wr_64(bp, SRC_REG_LASTFREE0 + port*16,
+		    U64_LO((u64)t2_mapping +
+			   (src_cid_count-1) * sizeof(struct src_ent)),
+		    U64_HI((u64)t2_mapping +
+			   (src_cid_count-1) * sizeof(struct src_ent)));
 }
 
 #endif /* BNX2X_INIT_OPS_H */
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c
index 0383e30..3e99bf9 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/bnx2x/bnx2x_link.c
@@ -28,7 +28,7 @@
 
 /********************************************************/
 #define ETH_HLEN			14
-#define ETH_OVREHEAD		(ETH_HLEN + 8)/* 8 for CRC + VLAN*/
+#define ETH_OVREHEAD		(ETH_HLEN + 8 + 8)/* 16 for CRC + VLAN + LLC */
 #define ETH_MIN_PACKET_SIZE		60
 #define ETH_MAX_PACKET_SIZE		1500
 #define ETH_MAX_JUMBO_PACKET_SIZE	9600
@@ -168,50 +168,19 @@
 /**********************************************************/
 /*                     INTERFACE                          */
 /**********************************************************/
-#define CL45_WR_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
-	bnx2x_cl45_write(_bp, _port, 0, _phy_addr, \
-		DEFAULT_PHY_DEV_ADDR, \
+
+#define CL45_WR_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
+	bnx2x_cl45_write(_bp, _phy, \
+		(_phy)->def_md_devad, \
 		(_bank + (_addr & 0xf)), \
 		_val)
 
-#define CL45_RD_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
-	bnx2x_cl45_read(_bp, _port, 0, _phy_addr, \
-		DEFAULT_PHY_DEV_ADDR, \
+#define CL45_RD_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
+	bnx2x_cl45_read(_bp, _phy, \
+		(_phy)->def_md_devad, \
 		(_bank + (_addr & 0xf)), \
 		_val)
 
-static void bnx2x_set_serdes_access(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u32 emac_base = (params->port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-
-	/* Set Clause 22 */
-	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + params->port*0x10, 1);
-	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
-	udelay(500);
-	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
-	udelay(500);
-	 /* Set Clause 45 */
-	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + params->port*0x10, 0);
-}
-static void bnx2x_set_phy_mdio(struct link_params *params, u8 phy_flags)
-{
-	struct bnx2x *bp = params->bp;
-
-	if (phy_flags & PHY_XGXS_FLAG) {
-		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
-			   params->port*0x18, 0);
-		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
-			   DEFAULT_PHY_DEV_ADDR);
-	} else {
-		bnx2x_set_serdes_access(params);
-
-		REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD +
-			   params->port*0x10,
-			   DEFAULT_PHY_DEV_ADDR);
-	}
-}
-
 static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
 {
 	u32 val = REG_RD(bp, reg);
@@ -408,9 +377,60 @@
 	return 0;
 }
 
+static void bnx2x_update_bmac2(struct link_params *params,
+			       struct link_vars *vars,
+			       u8 is_lb)
+{
+	/*
+	 * Set rx control: Strip CRC and enable BigMAC to relay
+	 * control packets to the system as well
+	 */
+	u32 wb_data[2];
+	struct bnx2x *bp = params->bp;
+	u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
+		NIG_REG_INGRESS_BMAC0_MEM;
+	u32 val = 0x14;
+
+	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
+		/* Enable BigMAC to react on received Pause packets */
+		val |= (1<<5);
+	wb_data[0] = val;
+	wb_data[1] = 0;
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_CONTROL,
+			wb_data, 2);
+	udelay(30);
+
+	/* Tx control */
+	val = 0xc0;
+	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+		val |= 0x800000;
+	wb_data[0] = val;
+	wb_data[1] = 0;
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_CONTROL,
+			wb_data, 2);
+
+	val = 0x8000;
+	wb_data[0] = val;
+	wb_data[1] = 0;
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_PAUSE_CONTROL,
+			wb_data, 2);
+
+	/* mac control */
+	val = 0x3; /* Enable RX and TX */
+	if (is_lb) {
+		val |= 0x4; /* Local loopback */
+		DP(NETIF_MSG_LINK, "enable bmac loopback\n");
+	}
+
+	wb_data[0] = val;
+	wb_data[1] = 0;
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL,
+			wb_data, 2);
+}
 
 
-static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
+static u8 bnx2x_bmac1_enable(struct link_params *params,
+			     struct link_vars *vars,
 			  u8 is_lb)
 {
 	struct bnx2x *bp = params->bp;
@@ -420,17 +440,7 @@
 	u32 wb_data[2];
 	u32 val;
 
-	DP(NETIF_MSG_LINK, "Enabling BigMAC\n");
-	/* reset and unreset the BigMac */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-	       (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));
-
-	/* enable access for bmac registers */
-	REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
+	DP(NETIF_MSG_LINK, "Enabling BigMAC1\n");
 
 	/* XGXS control */
 	wb_data[0] = 0x3c;
@@ -510,6 +520,103 @@
 			    wb_data, 2);
 	}
 
+
+	return 0;
+}
+
+static u8 bnx2x_bmac2_enable(struct link_params *params,
+			     struct link_vars *vars,
+			     u8 is_lb)
+{
+	struct bnx2x *bp = params->bp;
+	u8 port = params->port;
+	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
+			       NIG_REG_INGRESS_BMAC0_MEM;
+	u32 wb_data[2];
+
+	DP(NETIF_MSG_LINK, "Enabling BigMAC2\n");
+
+	wb_data[0] = 0;
+	wb_data[1] = 0;
+	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);
+
+	udelay(30);
+
+	/* tx MAC SA */
+	wb_data[0] = ((params->mac_addr[2] << 24) |
+		       (params->mac_addr[3] << 16) |
+		       (params->mac_addr[4] << 8) |
+			params->mac_addr[5]);
+	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);
+
+	udelay(30);
+
+	/* Configure SAFC */
+	wb_data[0] = 0x1000200;
+	wb_data[1] = 0;
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS,
+			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);
+	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);
+	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);
+	udelay(30);
+	bnx2x_update_bmac2(params, vars, is_lb);
+
+	return 0;
+}
+
+u8 bnx2x_bmac_enable(struct link_params *params,
+			    struct link_vars *vars,
+			    u8 is_lb)
+{
+	u8 rc, port = params->port;
+	struct bnx2x *bp = params->bp;
+	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));
+	udelay(10);
+
+	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);
+
+	/* Enable BMAC according to BMAC type*/
+	if (CHIP_IS_E2(bp))
+		rc = bnx2x_bmac2_enable(params, vars, is_lb);
+	else
+		rc = bnx2x_bmac1_enable(params, vars, is_lb);
 	REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
 	REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
 	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
@@ -524,165 +631,9 @@
 	REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
 
 	vars->mac_type = MAC_TYPE_BMAC;
-	return 0;
+	return rc;
 }
 
-static void bnx2x_phy_deassert(struct link_params *params, u8 phy_flags)
-{
-	struct bnx2x *bp = params->bp;
-	u32 val;
-
-	if (phy_flags & PHY_XGXS_FLAG) {
-		DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:XGXS\n");
-		val = XGXS_RESET_BITS;
-
-	} else { /* SerDes */
-		DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:SerDes\n");
-		val = SERDES_RESET_BITS;
-	}
-
-	val = val << (params->port*16);
-
-	/* reset and unreset the SerDes/XGXS */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
-		    val);
-	udelay(500);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET,
-		    val);
-	bnx2x_set_phy_mdio(params, phy_flags);
-}
-
-void bnx2x_link_status_update(struct link_params *params,
-			    struct link_vars   *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 link_10g;
-	u8 port = params->port;
-
-	if (params->switch_cfg ==  SWITCH_CFG_1G)
-		vars->phy_flags = PHY_SERDES_FLAG;
-	else
-		vars->phy_flags = PHY_XGXS_FLAG;
-	vars->link_status = REG_RD(bp, params->shmem_base +
-					  offsetof(struct shmem_region,
-					   port_mb[port].link_status));
-
-	vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
-
-	if (vars->link_up) {
-		DP(NETIF_MSG_LINK, "phy link up\n");
-
-		vars->phy_link_up = 1;
-		vars->duplex = DUPLEX_FULL;
-		switch (vars->link_status &
-					LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
-			case LINK_10THD:
-				vars->duplex = DUPLEX_HALF;
-				/* fall thru */
-			case LINK_10TFD:
-				vars->line_speed = SPEED_10;
-				break;
-
-			case LINK_100TXHD:
-				vars->duplex = DUPLEX_HALF;
-				/* fall thru */
-			case LINK_100T4:
-			case LINK_100TXFD:
-				vars->line_speed = SPEED_100;
-				break;
-
-			case LINK_1000THD:
-				vars->duplex = DUPLEX_HALF;
-				/* fall thru */
-			case LINK_1000TFD:
-				vars->line_speed = SPEED_1000;
-				break;
-
-			case LINK_2500THD:
-				vars->duplex = DUPLEX_HALF;
-				/* fall thru */
-			case LINK_2500TFD:
-				vars->line_speed = SPEED_2500;
-				break;
-
-			case LINK_10GTFD:
-				vars->line_speed = SPEED_10000;
-				break;
-
-			case LINK_12GTFD:
-				vars->line_speed = SPEED_12000;
-				break;
-
-			case LINK_12_5GTFD:
-				vars->line_speed = SPEED_12500;
-				break;
-
-			case LINK_13GTFD:
-				vars->line_speed = SPEED_13000;
-				break;
-
-			case LINK_15GTFD:
-				vars->line_speed = SPEED_15000;
-				break;
-
-			case LINK_16GTFD:
-				vars->line_speed = SPEED_16000;
-				break;
-
-			default:
-				break;
-		}
-
-		if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
-			vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
-		else
-			vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_TX;
-
-		if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
-			vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
-		else
-			vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_RX;
-
-		if (vars->phy_flags & PHY_XGXS_FLAG) {
-			if (vars->line_speed &&
-			    ((vars->line_speed == SPEED_10) ||
-			     (vars->line_speed == SPEED_100))) {
-				vars->phy_flags |= PHY_SGMII_FLAG;
-			} else {
-				vars->phy_flags &= ~PHY_SGMII_FLAG;
-			}
-		}
-
-		/* anything 10 and over uses the bmac */
-		link_10g = ((vars->line_speed == SPEED_10000) ||
-			    (vars->line_speed == SPEED_12000) ||
-			    (vars->line_speed == SPEED_12500) ||
-			    (vars->line_speed == SPEED_13000) ||
-			    (vars->line_speed == SPEED_15000) ||
-			    (vars->line_speed == SPEED_16000));
-		if (link_10g)
-			vars->mac_type = MAC_TYPE_BMAC;
-		else
-			vars->mac_type = MAC_TYPE_EMAC;
-
-	} else { /* link down */
-		DP(NETIF_MSG_LINK, "phy link down\n");
-
-		vars->phy_link_up = 0;
-
-		vars->line_speed = 0;
-		vars->duplex = DUPLEX_FULL;
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-
-		/* indicate no mac active */
-		vars->mac_type = MAC_TYPE_NONE;
-	}
-
-	DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x\n",
-		 vars->link_status, vars->phy_link_up);
-	DP(NETIF_MSG_LINK, "line_speed %x  duplex %x  flow_ctrl 0x%x\n",
-		 vars->line_speed, vars->duplex, vars->flow_ctrl);
-}
 
 static void bnx2x_update_mng(struct link_params *params, u32 link_status)
 {
@@ -706,13 +657,25 @@
 			(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
 	    nig_bmac_enable) {
 
-		/* Clear Rx Enable bit in BMAC_CONTROL register */
-		REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
-			    wb_data, 2);
-		wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
-		REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
-			    wb_data, 2);
-
+		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);
+			wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
+			REG_WR_DMAE(bp, bmac_addr +
+					BIGMAC2_REGISTER_BMAC_CONTROL,
+					wb_data, 2);
+		} else {
+			/* Clear Rx Enable bit in BMAC_CONTROL register */
+			REG_RD_DMAE(bp, bmac_addr +
+					BIGMAC_REGISTER_BMAC_CONTROL,
+					wb_data, 2);
+			wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
+			REG_WR_DMAE(bp, bmac_addr +
+					BIGMAC_REGISTER_BMAC_CONTROL,
+					wb_data, 2);
+		}
 		msleep(1);
 	}
 }
@@ -800,62 +763,69 @@
 	return 0;
 }
 
-static u32 bnx2x_get_emac_base(struct bnx2x *bp, u32 ext_phy_type, u8 port)
+static u32 bnx2x_get_emac_base(struct bnx2x *bp,
+			       u32 mdc_mdio_access, u8 port)
 {
-	u32 emac_base;
-
-	switch (ext_phy_type) {
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-		/* All MDC/MDIO is directed through single EMAC */
+	u32 emac_base = 0;
+	switch (mdc_mdio_access) {
+	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE:
+		break;
+	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0:
+		if (REG_RD(bp, NIG_REG_PORT_SWAP))
+			emac_base = GRCBASE_EMAC1;
+		else
+			emac_base = GRCBASE_EMAC0;
+		break;
+	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1:
 		if (REG_RD(bp, NIG_REG_PORT_SWAP))
 			emac_base = GRCBASE_EMAC0;
 		else
 			emac_base = GRCBASE_EMAC1;
 		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
+	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH:
+		emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+		break;
+	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED:
 		emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
 		break;
 	default:
-		emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
 		break;
 	}
 	return emac_base;
 
 }
 
-u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
-		  u8 phy_addr, u8 devad, u16 reg, u16 val)
+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;
-	u32 mdio_ctrl = bnx2x_get_emac_base(bp, ext_phy_type, port);
 
 	/* 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, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
 	tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
 			     EMAC_MDIO_MODE_CLOCK_CNT);
 	tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
 		(49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
-	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
-	REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
+	REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
 	udelay(40);
 
 	/* address */
 
-	tmp = ((phy_addr << 21) | (devad << 16) | reg |
+	tmp = ((phy->addr << 21) | (devad << 16) | reg |
 	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
 	       EMAC_MDIO_COMM_START_BUSY);
-	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
 
 	for (i = 0; i < 50; i++) {
 		udelay(10);
 
-		tmp = REG_RD(bp, 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;
@@ -866,15 +836,15 @@
 		rc = -EFAULT;
 	} else {
 		/* data */
-		tmp = ((phy_addr << 21) | (devad << 16) | val |
+		tmp = ((phy->addr << 21) | (devad << 16) | val |
 		       EMAC_MDIO_COMM_COMMAND_WRITE_45 |
 		       EMAC_MDIO_COMM_START_BUSY);
-		REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
+		REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
 
 		for (i = 0; i < 50; i++) {
 			udelay(10);
 
-			tmp = REG_RD(bp, mdio_ctrl +
+			tmp = REG_RD(bp, phy->mdio_ctrl +
 					 EMAC_REG_EMAC_MDIO_COMM);
 			if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
 				udelay(5);
@@ -888,42 +858,41 @@
 	}
 
 	/* Restore the saved mode */
-	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
 
 	return rc;
 }
 
-u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
-		 u8 phy_addr, u8 devad, u16 reg, u16 *ret_val)
+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;
 
-	u32 mdio_ctrl = bnx2x_get_emac_base(bp, ext_phy_type, port);
 	/* 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, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
-	val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL |
+	saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	val = saved_mode & ~((EMAC_MDIO_MODE_AUTO_POLL |
 			     EMAC_MDIO_MODE_CLOCK_CNT));
 	val |= (EMAC_MDIO_MODE_CLAUSE_45 |
 		(49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
-	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
-	REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
+	REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
 	udelay(40);
 
 	/* address */
-	val = ((phy_addr << 21) | (devad << 16) | reg |
+	val = ((phy->addr << 21) | (devad << 16) | reg |
 	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
 	       EMAC_MDIO_COMM_START_BUSY);
-	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
 
 	for (i = 0; i < 50; i++) {
 		udelay(10);
 
-		val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
+		val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
 		if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
 			udelay(5);
 			break;
@@ -937,15 +906,15 @@
 
 	} else {
 		/* data */
-		val = ((phy_addr << 21) | (devad << 16) |
+		val = ((phy->addr << 21) | (devad << 16) |
 		       EMAC_MDIO_COMM_COMMAND_READ_45 |
 		       EMAC_MDIO_COMM_START_BUSY);
-		REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
+		REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
 
 		for (i = 0; i < 50; i++) {
 			udelay(10);
 
-			val = REG_RD(bp, mdio_ctrl +
+			val = REG_RD(bp, phy->mdio_ctrl +
 					  EMAC_REG_EMAC_MDIO_COMM);
 			if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
 				*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
@@ -961,32 +930,262 @@
 	}
 
 	/* Restore the saved mode */
-	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
 
 	return rc;
 }
 
-static void bnx2x_set_aer_mmd(struct link_params *params,
-			    struct link_vars   *vars)
+u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
+		  u8 devad, u16 reg, u16 *ret_val)
 {
-	struct bnx2x *bp = params->bp;
-	u32 ser_lane;
-	u16 offset;
+	u8 phy_index;
+	/**
+	 * Probe for the phy according to the given phy_addr, and execute
+	 * the read request on it
+	 */
+	for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
+		if (params->phy[phy_index].addr == phy_addr) {
+			return bnx2x_cl45_read(params->bp,
+					       &params->phy[phy_index], devad,
+					       reg, ret_val);
+		}
+	}
+	return -EINVAL;
+}
 
+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
+	 */
+	for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
+		if (params->phy[phy_index].addr == phy_addr) {
+			return bnx2x_cl45_write(params->bp,
+						&params->phy[phy_index], devad,
+						reg, val);
+		}
+	}
+	return -EINVAL;
+}
+
+static void bnx2x_set_aer_mmd_xgxs(struct link_params *params,
+				   struct bnx2x_phy *phy)
+{
+	u32 ser_lane;
+	u16 offset, aer_val;
+	struct bnx2x *bp = params->bp;
 	ser_lane = ((params->lane_config &
 		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
 		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
 
-	offset = (vars->phy_flags & PHY_XGXS_FLAG) ?
-		(params->phy_addr + ser_lane) : 0;
-
-	CL45_WR_OVER_CL22(bp, params->port,
-			      params->phy_addr,
-			      MDIO_REG_BANK_AER_BLOCK,
-			      MDIO_AER_BLOCK_AER_REG, 0x3800 + offset);
+	offset = phy->addr + ser_lane;
+	if (CHIP_IS_E2(bp))
+		aer_val = 0x2800 + 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);
+}
+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);
 }
 
-static void bnx2x_set_master_ln(struct link_params *params)
+/******************************************************************/
+/*			Internal phy section			  */
+/******************************************************************/
+
+static void bnx2x_set_serdes_access(struct bnx2x *bp, u8 port)
+{
+	u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+
+	/* Set Clause 22 */
+	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 1);
+	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
+	udelay(500);
+	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
+	udelay(500);
+	 /* Set Clause 45 */
+	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0);
+}
+
+static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
+{
+	u32 val;
+
+	DP(NETIF_MSG_LINK, "bnx2x_serdes_deassert\n");
+
+	val = SERDES_RESET_BITS << (port*16);
+
+	/* reset and unreset the SerDes/XGXS */
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
+	udelay(500);
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
+
+	bnx2x_set_serdes_access(bp, port);
+
+	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD +
+		     port*0x10,
+		     DEFAULT_PHY_DEV_ADDR);
+}
+
+static void bnx2x_xgxs_deassert(struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u8 port;
+	u32 val;
+	DP(NETIF_MSG_LINK, "bnx2x_xgxs_deassert\n");
+	port = params->port;
+
+	val = XGXS_RESET_BITS << (port*16);
+
+	/* reset and unreset the SerDes/XGXS */
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
+	udelay(500);
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
+
+	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
+		     port*0x18, 0);
+	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
+		     params->phy[INT_PHY].def_md_devad);
+}
+
+
+void bnx2x_link_status_update(struct link_params *params,
+			    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));
+
+	vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
+
+	if (vars->link_up) {
+		DP(NETIF_MSG_LINK, "phy link up\n");
+
+		vars->phy_link_up = 1;
+		vars->duplex = DUPLEX_FULL;
+		switch (vars->link_status &
+					LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
+			case LINK_10THD:
+				vars->duplex = DUPLEX_HALF;
+				/* fall thru */
+			case LINK_10TFD:
+				vars->line_speed = SPEED_10;
+				break;
+
+			case LINK_100TXHD:
+				vars->duplex = DUPLEX_HALF;
+				/* fall thru */
+			case LINK_100T4:
+			case LINK_100TXFD:
+				vars->line_speed = SPEED_100;
+				break;
+
+			case LINK_1000THD:
+				vars->duplex = DUPLEX_HALF;
+				/* fall thru */
+			case LINK_1000TFD:
+				vars->line_speed = SPEED_1000;
+				break;
+
+			case LINK_2500THD:
+				vars->duplex = DUPLEX_HALF;
+				/* fall thru */
+			case LINK_2500TFD:
+				vars->line_speed = SPEED_2500;
+				break;
+
+			case LINK_10GTFD:
+				vars->line_speed = SPEED_10000;
+				break;
+
+			case LINK_12GTFD:
+				vars->line_speed = SPEED_12000;
+				break;
+
+			case LINK_12_5GTFD:
+				vars->line_speed = SPEED_12500;
+				break;
+
+			case LINK_13GTFD:
+				vars->line_speed = SPEED_13000;
+				break;
+
+			case LINK_15GTFD:
+				vars->line_speed = SPEED_15000;
+				break;
+
+			case LINK_16GTFD:
+				vars->line_speed = SPEED_16000;
+				break;
+
+			default:
+				break;
+		}
+		vars->flow_ctrl = 0;
+		if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
+			vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
+
+		if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
+			vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
+
+		if (!vars->flow_ctrl)
+			vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+
+		if (vars->line_speed &&
+		    ((vars->line_speed == SPEED_10) ||
+		     (vars->line_speed == SPEED_100))) {
+			vars->phy_flags |= PHY_SGMII_FLAG;
+		} else {
+			vars->phy_flags &= ~PHY_SGMII_FLAG;
+		}
+
+		/* anything 10 and over uses the bmac */
+		link_10g = ((vars->line_speed == SPEED_10000) ||
+			    (vars->line_speed == SPEED_12000) ||
+			    (vars->line_speed == SPEED_12500) ||
+			    (vars->line_speed == SPEED_13000) ||
+			    (vars->line_speed == SPEED_15000) ||
+			    (vars->line_speed == SPEED_16000));
+		if (link_10g)
+			vars->mac_type = MAC_TYPE_BMAC;
+		else
+			vars->mac_type = MAC_TYPE_EMAC;
+
+	} else { /* link down */
+		DP(NETIF_MSG_LINK, "phy link down\n");
+
+		vars->phy_link_up = 0;
+
+		vars->line_speed = 0;
+		vars->duplex = DUPLEX_FULL;
+		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+
+		/* indicate no mac active */
+		vars->mac_type = MAC_TYPE_NONE;
+	}
+
+	DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x\n",
+		 vars->link_status, vars->phy_link_up);
+	DP(NETIF_MSG_LINK, "line_speed %x  duplex %x  flow_ctrl 0x%x\n",
+		 vars->line_speed, vars->duplex, vars->flow_ctrl);
+}
+
+
+static void bnx2x_set_master_ln(struct link_params *params,
+				struct bnx2x_phy *phy)
 {
 	struct bnx2x *bp = params->bp;
 	u16 new_master_ln, ser_lane;
@@ -995,47 +1194,44 @@
 		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
 
 	/* set the master_ln for AN */
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_XGXS_BLOCK2,
 			      MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
 			      &new_master_ln);
 
-	CL45_WR_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(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)
+static u8 bnx2x_reset_unicore(struct link_params *params,
+			      struct bnx2x_phy *phy,
+			      u8 set_serdes)
 {
 	struct bnx2x *bp = params->bp;
 	u16 mii_control;
 	u16 i;
 
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_COMBO_IEEE0,
 			      MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
 
 	/* reset the unicore */
-	CL45_WR_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_COMBO_IEEE0,
 			      MDIO_COMBO_IEEE0_MII_CONTROL,
 			      (mii_control |
 			       MDIO_COMBO_IEEO_MII_CONTROL_RESET));
-	if (params->switch_cfg == SWITCH_CFG_1G)
-		bnx2x_set_serdes_access(params);
+	if (set_serdes)
+		bnx2x_set_serdes_access(bp, params->port);
 
 	/* wait for the reset to self clear */
 	for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
 		udelay(5);
 
 		/* the reset erased the previous bank value */
-		CL45_RD_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+		CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_COMBO_IEEE0,
 			      MDIO_COMBO_IEEE0_MII_CONTROL,
 			      &mii_control);
@@ -1051,7 +1247,8 @@
 
 }
 
-static void bnx2x_set_swap_lanes(struct link_params *params)
+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:
@@ -1069,71 +1266,62 @@
 			    PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
 
 	if (rx_lane_swap != 0x1b) {
-		CL45_WR_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+		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));
 	} else {
-		CL45_WR_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+		CL45_WR_OVER_CL22(bp, phy,
 				      MDIO_REG_BANK_XGXS_BLOCK2,
 				      MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
 	}
 
 	if (tx_lane_swap != 0x1b) {
-		CL45_WR_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+		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));
 	} else {
-		CL45_WR_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+		CL45_WR_OVER_CL22(bp, phy,
 				      MDIO_REG_BANK_XGXS_BLOCK2,
 				      MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
 	}
 }
 
-static void bnx2x_set_parallel_detection(struct link_params *params,
-				       u8       	 phy_flags)
+static void bnx2x_set_parallel_detection(struct bnx2x_phy *phy,
+					 struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
 	u16 control2;
-
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_SERDES_DIGITAL,
 			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
 			      &control2);
-	if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
+	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, "params->speed_cap_mask = 0x%x, control2 = 0x%x\n",
-		params->speed_cap_mask, control2);
-	CL45_WR_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	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);
 
-	if ((phy_flags & PHY_XGXS_FLAG) &&
-	     (params->speed_cap_mask &
+	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, params->port,
-				      params->phy_addr,
+		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);
 
-		CL45_RD_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+		CL45_RD_OVER_CL22(bp, phy,
 				MDIO_REG_BANK_10G_PARALLEL_DETECT,
 				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
 				&control2);
@@ -1142,15 +1330,13 @@
 		control2 |=
 		    MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
 
-		CL45_WR_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+		CL45_WR_OVER_CL22(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, params->port,
-				      params->phy_addr,
+		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 |
@@ -1158,7 +1344,8 @@
 	}
 }
 
-static void bnx2x_set_autoneg(struct link_params *params,
+static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
+			      struct link_params *params,
 			    struct link_vars *vars,
 			    u8 enable_cl73)
 {
@@ -1166,9 +1353,7 @@
 	u16 reg_val;
 
 	/* CL37 Autoneg */
-
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_COMBO_IEEE0,
 			      MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
 
@@ -1179,15 +1364,13 @@
 		reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
 			     MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
 
-	CL45_WR_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_COMBO_IEEE0,
 			      MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
 
 	/* Enable/Disable Autodetection */
 
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(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 |
@@ -1198,14 +1381,12 @@
 	else
 		reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
 
-	CL45_WR_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(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, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_BAM_NEXT_PAGE,
 			      MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
 			  &reg_val);
@@ -1218,23 +1399,20 @@
 		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, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(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, params->port,
-				      params->phy_addr,
+		CL45_WR_OVER_CL22(bp, phy,
 				      MDIO_REG_BANK_CL73_USERB0,
 				    MDIO_CL73_USERB0_CL73_UCTRL,
 				      0xe);
 
 		/* Enable BAM Station Manager*/
-		CL45_WR_OVER_CL22(bp, params->port,
-			params->phy_addr,
+		CL45_WR_OVER_CL22(bp, phy,
 			MDIO_REG_BANK_CL73_USERB0,
 			MDIO_CL73_USERB0_CL73_BAM_CTRL1,
 			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
@@ -1242,20 +1420,18 @@
 			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);
 
 		/* Advertise CL73 link speeds */
-			CL45_RD_OVER_CL22(bp, params->port,
-					      params->phy_addr,
+		CL45_RD_OVER_CL22(bp, phy,
 					      MDIO_REG_BANK_CL73_IEEEB1,
 					      MDIO_CL73_IEEEB1_AN_ADV2,
 					      &reg_val);
-		if (params->speed_cap_mask &
+		if (phy->speed_cap_mask &
 		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
 			reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
-		if (params->speed_cap_mask &
+		if (phy->speed_cap_mask &
 		    PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
 			reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
 
-			CL45_WR_OVER_CL22(bp, params->port,
-					      params->phy_addr,
+		CL45_WR_OVER_CL22(bp, phy,
 					      MDIO_REG_BANK_CL73_IEEEB1,
 					      MDIO_CL73_IEEEB1_AN_ADV2,
 				      reg_val);
@@ -1266,38 +1442,35 @@
 	} else /* CL73 Autoneg Disabled */
 		reg_val = 0;
 
-	CL45_WR_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(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 link_params *params,
+static void bnx2x_program_serdes(struct bnx2x_phy *phy,
+				 struct link_params *params,
 			       struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u16 reg_val;
 
 	/* program duplex, disable autoneg and sgmii*/
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(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 (params->req_duplex == DUPLEX_FULL)
+	if (phy->req_duplex == DUPLEX_FULL)
 		reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
-	CL45_WR_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	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, params->port,
-				      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 				      MDIO_REG_BANK_SERDES_DIGITAL,
 				      MDIO_SERDES_DIGITAL_MISC1, &reg_val);
 	/* clearing the speed value before setting the right speed */
@@ -1320,14 +1493,14 @@
 				MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
 	}
 
-	CL45_WR_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+	CL45_WR_OVER_CL22(bp, phy,
 				      MDIO_REG_BANK_SERDES_DIGITAL,
 				      MDIO_SERDES_DIGITAL_MISC1, reg_val);
 
 }
 
-static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
+static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy,
+					     struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val = 0;
@@ -1335,29 +1508,28 @@
 	/* configure the 48 bits for BAM AN */
 
 	/* set extended capabilities */
-	if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
+	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
 		val |= MDIO_OVER_1G_UP1_2_5G;
-	if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
+	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
 		val |= MDIO_OVER_1G_UP1_10G;
-	CL45_WR_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_OVER_1G,
 			      MDIO_OVER_1G_UP1, val);
 
-	CL45_WR_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_OVER_1G,
 			      MDIO_OVER_1G_UP3, 0x400);
 }
 
-static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u16 *ieee_fc)
+static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
+				     struct link_params *params, u16 *ieee_fc)
 {
 	struct bnx2x *bp = params->bp;
 	*ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
 	/* resolve pause mode and advertisement
 	 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
 
-	switch (params->req_flow_ctrl) {
+	switch (phy->req_flow_ctrl) {
 	case BNX2X_FLOW_CTRL_AUTO:
 		if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
 			*ieee_fc |=
@@ -1385,30 +1557,30 @@
 	DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
 }
 
-static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
+static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x_phy *phy,
+					     struct link_params *params,
 					   u16 ieee_fc)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val;
 	/* for AN, we are always publishing full duplex */
 
-	CL45_WR_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_COMBO_IEEE0,
 			      MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(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, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_CL73_IEEEB1,
 			      MDIO_CL73_IEEEB1_AN_ADV1, val);
 }
 
-static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73)
+static void bnx2x_restart_autoneg(struct bnx2x_phy *phy,
+				  struct link_params *params,
+				  u8 enable_cl73)
 {
 	struct bnx2x *bp = params->bp;
 	u16 mii_control;
@@ -1417,14 +1589,12 @@
 	/* Enable and restart BAM/CL37 aneg */
 
 	if (enable_cl73) {
-		CL45_RD_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+		CL45_RD_OVER_CL22(bp, phy,
 				      MDIO_REG_BANK_CL73_IEEEB0,
 				      MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
 				      &mii_control);
 
-		CL45_WR_OVER_CL22(bp, params->port,
-				params->phy_addr,
+		CL45_WR_OVER_CL22(bp, phy,
 				MDIO_REG_BANK_CL73_IEEEB0,
 				MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
 				(mii_control |
@@ -1432,16 +1602,14 @@
 				MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
 	} else {
 
-		CL45_RD_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+		CL45_RD_OVER_CL22(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, params->port,
-				      params->phy_addr,
+		CL45_WR_OVER_CL22(bp, phy,
 				      MDIO_REG_BANK_COMBO_IEEE0,
 				      MDIO_COMBO_IEEE0_MII_CONTROL,
 				      (mii_control |
@@ -1450,7 +1618,8 @@
 	}
 }
 
-static void bnx2x_initialize_sgmii_process(struct link_params *params,
+static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
+					   struct link_params *params,
 					 struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
@@ -1458,8 +1627,7 @@
 
 	/* in SGMII mode, the unicore is always slave */
 
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_SERDES_DIGITAL,
 			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
 		      &control1);
@@ -1468,8 +1636,7 @@
 	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, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_SERDES_DIGITAL,
 			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
 			      control1);
@@ -1479,8 +1646,7 @@
 		/* set speed, disable autoneg */
 		u16 mii_control;
 
-		CL45_RD_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+		CL45_RD_OVER_CL22(bp, phy,
 				      MDIO_REG_BANK_COMBO_IEEE0,
 				      MDIO_COMBO_IEEE0_MII_CONTROL,
 				      &mii_control);
@@ -1508,18 +1674,17 @@
 		}
 
 		/* setting the full duplex */
-		if (params->req_duplex == DUPLEX_FULL)
+		if (phy->req_duplex == DUPLEX_FULL)
 			mii_control |=
 				MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
-		CL45_WR_OVER_CL22(bp, params->port,
-				      params->phy_addr,
+		CL45_WR_OVER_CL22(bp, phy,
 				      MDIO_REG_BANK_COMBO_IEEE0,
 				      MDIO_COMBO_IEEE0_MII_CONTROL,
 				      mii_control);
 
 	} else { /* AN mode */
 		/* enable and restart AN */
-		bnx2x_restart_autoneg(params, 0);
+		bnx2x_restart_autoneg(phy, params, 0);
 	}
 }
 
@@ -1549,91 +1714,24 @@
 	default:
 		break;
 	}
+	if (pause_result & (1<<0))
+		vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
+	if (pause_result & (1<<1))
+		vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
 }
 
-static u8 bnx2x_ext_phy_resolve_fc(struct link_params *params,
-				  struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 ext_phy_addr;
-	u16 ld_pause;		/* local */
-	u16 lp_pause;		/* link partner */
-	u16 an_complete;	/* AN complete */
-	u16 pause_result;
-	u8 ret = 0;
-	u32 ext_phy_type;
-	u8 port = params->port;
-	ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-	/* read twice */
-
-	bnx2x_cl45_read(bp, port,
-		      ext_phy_type,
-		      ext_phy_addr,
-		      MDIO_AN_DEVAD,
-		      MDIO_AN_REG_STATUS, &an_complete);
-	bnx2x_cl45_read(bp, port,
-		      ext_phy_type,
-		      ext_phy_addr,
-		      MDIO_AN_DEVAD,
-		      MDIO_AN_REG_STATUS, &an_complete);
-
-	if (an_complete & MDIO_AN_REG_STATUS_AN_COMPLETE) {
-		ret = 1;
-		bnx2x_cl45_read(bp, port,
-			      ext_phy_type,
-			      ext_phy_addr,
-			      MDIO_AN_DEVAD,
-			      MDIO_AN_REG_ADV_PAUSE, &ld_pause);
-		bnx2x_cl45_read(bp, port,
-			      ext_phy_type,
-			      ext_phy_addr,
-			      MDIO_AN_DEVAD,
-			      MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
-		pause_result = (ld_pause &
-				MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
-		pause_result |= (lp_pause &
-				 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
-		DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
-		   pause_result);
-		bnx2x_pause_resolve(vars, pause_result);
-		if (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE &&
-		     ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-			bnx2x_cl45_read(bp, port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_AN_DEVAD,
-				      MDIO_AN_REG_CL37_FC_LD, &ld_pause);
-
-			bnx2x_cl45_read(bp, port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_AN_DEVAD,
-				      MDIO_AN_REG_CL37_FC_LP, &lp_pause);
-			pause_result = (ld_pause &
-				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
-			pause_result |= (lp_pause &
-				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
-
-			bnx2x_pause_resolve(vars, pause_result);
-			DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
-				 pause_result);
-		}
-	}
-	return ret;
-}
-
-static u8 bnx2x_direct_parallel_detect_used(struct link_params *params)
+static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
+					    struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
 	u16 pd_10g, status2_1000x;
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	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, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_SERDES_DIGITAL,
 			      MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
 			      &status2_1000x);
@@ -1643,8 +1741,7 @@
 		return 1;
 	}
 
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_10G_PARALLEL_DETECT,
 			      MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS,
 			      &pd_10g);
@@ -1657,9 +1754,10 @@
 	return 0;
 }
 
-static void bnx2x_flow_ctrl_resolve(struct link_params *params,
-				  struct link_vars *vars,
-				  u32 gp_status)
+static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
+				    struct link_params *params,
+				    struct link_vars *vars,
+				    u32 gp_status)
 {
 	struct bnx2x *bp = params->bp;
 	u16 ld_pause;   /* local driver */
@@ -1669,12 +1767,13 @@
 	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
 
 	/* resolve from gp_status in case of AN complete and not sgmii */
-	if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
-	    (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
-	    (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
-	    (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
-	     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) {
-		if (bnx2x_direct_parallel_detect_used(params)) {
+	if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+		vars->flow_ctrl = phy->req_flow_ctrl;
+	else if (phy->req_line_speed != SPEED_AUTO_NEG)
+		vars->flow_ctrl = params->req_fc_auto_adv;
+	else if ((gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
+		 (!(vars->phy_flags & PHY_SGMII_FLAG))) {
+		if (bnx2x_direct_parallel_detect_used(phy, params)) {
 			vars->flow_ctrl = params->req_fc_auto_adv;
 			return;
 		}
@@ -1684,13 +1783,11 @@
 		    (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, params->port,
-					      params->phy_addr,
+			CL45_RD_OVER_CL22(bp, phy,
 					      MDIO_REG_BANK_CL73_IEEEB1,
 					      MDIO_CL73_IEEEB1_AN_ADV1,
 					      &ld_pause);
-			CL45_RD_OVER_CL22(bp, params->port,
-					     params->phy_addr,
+			CL45_RD_OVER_CL22(bp, phy,
 					     MDIO_REG_BANK_CL73_IEEEB1,
 					     MDIO_CL73_IEEEB1_AN_LP_ADV1,
 					     &lp_pause);
@@ -1703,14 +1800,11 @@
 			DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n",
 				 pause_result);
 		} else {
-
-			CL45_RD_OVER_CL22(bp, params->port,
-					      params->phy_addr,
+			CL45_RD_OVER_CL22(bp, phy,
 					      MDIO_REG_BANK_COMBO_IEEE0,
 					      MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
 					      &ld_pause);
-			CL45_RD_OVER_CL22(bp, params->port,
-			       params->phy_addr,
+			CL45_RD_OVER_CL22(bp, phy,
 			       MDIO_REG_BANK_COMBO_IEEE0,
 			       MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
 			       &lp_pause);
@@ -1722,26 +1816,18 @@
 				 pause_result);
 		}
 		bnx2x_pause_resolve(vars, pause_result);
-	} else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
-		   (bnx2x_ext_phy_resolve_fc(params, vars))) {
-		return;
-	} else {
-		if (params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
-			vars->flow_ctrl = params->req_fc_auto_adv;
-		else
-			vars->flow_ctrl = params->req_flow_ctrl;
 	}
 	DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
 }
 
-static void bnx2x_check_fallback_to_cl37(struct link_params *params)
+static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
+					 struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
 	u16 rx_status, ustat_val, cl37_fsm_recieved;
 	DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
 	/* Step 1: Make sure signal is detected */
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_RX0,
 			      MDIO_RX0_RX_STATUS,
 			      &rx_status);
@@ -1749,16 +1835,14 @@
 	    (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, params->port,
-				      params->phy_addr,
+		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);
 		return;
 	}
 	/* Step 2: Check CL73 state machine */
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_CL73_USERB0,
 			      MDIO_CL73_USERB0_CL73_USTAT1,
 			      &ustat_val);
@@ -1773,8 +1857,7 @@
 	}
 	/* Step 3: Check CL37 Message Pages received to indicate LP
 	supports only CL37 */
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_REMOTE_PHY,
 			      MDIO_REMOTE_PHY_MISC_RX_STATUS,
 			      &cl37_fsm_recieved);
@@ -1792,25 +1875,45 @@
 	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, params->port,
-			      params->phy_addr,
+	CL45_WR_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_CL73_IEEEB0,
 			      MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
 			      0);
 	/* Restart CL37 autoneg */
-	bnx2x_restart_autoneg(params, 0);
+	bnx2x_restart_autoneg(phy, params, 0);
 	DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
 }
-static u8 bnx2x_link_settings_status(struct link_params *params,
-				   struct link_vars *vars,
-				   u32 gp_status,
-				   u8 ext_phy_link_up)
+
+static void bnx2x_xgxs_an_resolve(struct bnx2x_phy *phy,
+				  struct link_params *params,
+				  struct link_vars *vars,
+				  u32 gp_status)
+{
+	if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE)
+		vars->link_status |=
+			LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+
+	if (bnx2x_direct_parallel_detect_used(phy, params))
+		vars->link_status |=
+			LINK_STATUS_PARALLEL_DETECTION_USED;
+}
+
+static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
+				     struct link_params *params,
+				     struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-	u16 new_line_speed;
+	u16 new_line_speed , gp_status;
 	u8 rc = 0;
-	vars->link_status = 0;
 
+	/* Read gp_status */
+	CL45_RD_OVER_CL22(bp, phy,
+				MDIO_REG_BANK_GP_STATUS,
+				MDIO_GP_STATUS_TOP_AN_STATUS1,
+				&gp_status);
+
+	if (phy->req_line_speed == SPEED_AUTO_NEG)
+		vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
 	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
 		DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
 			 gp_status);
@@ -1823,7 +1926,12 @@
 		else
 			vars->duplex = DUPLEX_HALF;
 
-		bnx2x_flow_ctrl_resolve(params, vars, gp_status);
+		if (SINGLE_MEDIA_DIRECT(params)) {
+			bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
+			if (phy->req_line_speed == SPEED_AUTO_NEG)
+				bnx2x_xgxs_an_resolve(phy, params, vars,
+						      gp_status);
+		}
 
 		switch (gp_status & GP_STATUS_SPEED_MASK) {
 		case GP_STATUS_10M:
@@ -1905,56 +2013,7 @@
 			return -EINVAL;
 		}
 
-		/* 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 */
-		if (new_line_speed != vars->line_speed) {
-			if (XGXS_EXT_PHY_TYPE(params->ext_phy_config) !=
-			     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT &&
-			    ext_phy_link_up) {
-				DP(NETIF_MSG_LINK, "Internal link speed %d is"
-					    " different than the external"
-					    " link speed %d\n", new_line_speed,
-					  vars->line_speed);
-				vars->phy_link_up = 0;
-				return 0;
-			}
-			REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
-				    + params->port*4, 0);
-			msleep(1);
-		}
 		vars->line_speed = new_line_speed;
-		vars->link_status |= LINK_STATUS_SERDES_LINK;
-
-		if ((params->req_line_speed == SPEED_AUTO_NEG) &&
-		    ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
-		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
-		    (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
-		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
-		    (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
-		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) ||
-		    (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
-		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726))) {
-			vars->autoneg = AUTO_NEG_ENABLED;
-
-			if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
-				vars->autoneg |= AUTO_NEG_COMPLETE;
-				vars->link_status |=
-					LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
-			}
-
-			vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
-			vars->link_status |=
-				LINK_STATUS_PARALLEL_DETECTION_USED;
-
-		}
-		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
-			vars->link_status |=
-				LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
-
-		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
-			vars->link_status |=
-				LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
 
 	} else { /* link_down */
 		DP(NETIF_MSG_LINK, "phy link down\n");
@@ -1963,38 +2022,32 @@
 
 		vars->duplex = DUPLEX_FULL;
 		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-		vars->autoneg = AUTO_NEG_DISABLED;
 		vars->mac_type = MAC_TYPE_NONE;
 
-		if ((params->req_line_speed == SPEED_AUTO_NEG) &&
-		    ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
-		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT))) {
+		if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
+		    SINGLE_MEDIA_DIRECT(params)) {
 			/* Check signal is detected */
-			bnx2x_check_fallback_to_cl37(params);
+			bnx2x_check_fallback_to_cl37(phy, params);
 		}
 	}
 
 	DP(NETIF_MSG_LINK, "gp_status 0x%x  phy_link_up %x line_speed %x\n",
 		 gp_status, vars->phy_link_up, vars->line_speed);
-	DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x"
-		 " autoneg 0x%x\n",
-		 vars->duplex,
-		 vars->flow_ctrl, vars->autoneg);
-	DP(NETIF_MSG_LINK, "link_status 0x%x\n", vars->link_status);
-
+	DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x link_status 0x%x\n",
+		   vars->duplex, vars->flow_ctrl, vars->link_status);
 	return rc;
 }
 
 static void bnx2x_set_gmii_tx_driver(struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
+	struct bnx2x_phy *phy = &params->phy[INT_PHY];
 	u16 lp_up2;
 	u16 tx_driver;
 	u16 bank;
 
 	/* read precomp */
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(bp, phy,
 			      MDIO_REG_BANK_OVER_1G,
 			      MDIO_OVER_1G_LP_UP2, &lp_up2);
 
@@ -2008,8 +2061,7 @@
 
 	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, params->port,
-				      params->phy_addr,
+		CL45_RD_OVER_CL22(bp, phy,
 				      bank,
 				      MDIO_TX0_TX_DRIVER, &tx_driver);
 
@@ -2018,8 +2070,7 @@
 		    (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, params->port,
-					      params->phy_addr,
+			CL45_WR_OVER_CL22(bp, phy,
 					      bank,
 					      MDIO_TX0_TX_DRIVER, tx_driver);
 		}
@@ -2027,7 +2078,7 @@
 }
 
 static u8 bnx2x_emac_program(struct link_params *params,
-			   u32 line_speed, u32 duplex)
+			     struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -2039,7 +2090,7 @@
 		     (EMAC_MODE_25G_MODE |
 		     EMAC_MODE_PORT_MII_10M |
 		     EMAC_MODE_HALF_DUPLEX));
-	switch (line_speed) {
+	switch (vars->line_speed) {
 	case SPEED_10:
 		mode |= EMAC_MODE_PORT_MII_10M;
 		break;
@@ -2058,3267 +2109,167 @@
 
 	default:
 		/* 10G not valid for EMAC */
-		DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", line_speed);
+		DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
+			   vars->line_speed);
 		return -EINVAL;
 	}
 
-	if (duplex == DUPLEX_HALF)
+	if (vars->duplex == DUPLEX_HALF)
 		mode |= EMAC_MODE_HALF_DUPLEX;
 	bnx2x_bits_en(bp,
 		    GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
 		    mode);
 
-	bnx2x_set_led(params, LED_MODE_OPER, line_speed);
+	bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
 	return 0;
 }
 
-/*****************************************************************************/
-/*      		     External Phy section       		     */
-/*****************************************************************************/
-void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
+static void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
+				  struct link_params *params)
 {
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-		       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
-	msleep(1);
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-		      MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
-}
-
-static void bnx2x_ext_phy_reset(struct link_params *params,
-			      struct link_vars   *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u32 ext_phy_type;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-
-	DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
-	ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-	/* The PHY reset is controled by GPIO 1
-	 * Give it 1ms of reset pulse
-	 */
-	if (vars->phy_flags & PHY_XGXS_FLAG) {
-
-		switch (ext_phy_type) {
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-			DP(NETIF_MSG_LINK, "XGXS Direct\n");
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-			DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");
-
-			/* Restore normal power mode*/
-			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-				      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-					  params->port);
-
-			/* HW reset */
-			bnx2x_ext_phy_hw_reset(bp, params->port);
-
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_CTRL, 0xa040);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-
-			/* 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, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_CTRL,
-				       1<<15);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-			DP(NETIF_MSG_LINK, "XGXS 8072\n");
-
-			/* Unset Low Power Mode and SW reset */
-			/* Restore normal power mode*/
-			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-				      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-					  params->port);
-
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_CTRL,
-				       1<<15);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-			DP(NETIF_MSG_LINK, "XGXS 8073\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);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-			DP(NETIF_MSG_LINK, "XGXS SFX7101\n");
-
-			/* Restore normal power mode*/
-			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-				      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-					  params->port);
-
-			/* HW reset */
-			bnx2x_ext_phy_hw_reset(bp, params->port);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-			/* Restore normal power mode*/
-			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-				      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-					  params->port);
-
-			/* HW reset */
-			bnx2x_ext_phy_hw_reset(bp, params->port);
-
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_CTRL,
-				       1<<15);
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
-			DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n");
-			break;
-
-		default:
-			DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
-			   params->ext_phy_config);
-			break;
-		}
-
-	} else { /* SerDes */
-		ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
-		switch (ext_phy_type) {
-		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
-			DP(NETIF_MSG_LINK, "SerDes Direct\n");
-			break;
-
-		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
-			DP(NETIF_MSG_LINK, "SerDes 5482\n");
-			bnx2x_ext_phy_hw_reset(bp, params->port);
-			break;
-
-		default:
-			DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
-				 params->ext_phy_config);
-			break;
-		}
-	}
-}
-
-static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
-				    u32 shmem_base, u32 spirom_ver)
-{
-	DP(NETIF_MSG_LINK, "FW version 0x%x:0x%x for port %d\n",
-		 (u16)(spirom_ver>>16), (u16)spirom_ver, port);
-	REG_WR(bp, shmem_base +
-		   offsetof(struct shmem_region,
-			    port_mb[port].ext_phy_fw_version),
-			spirom_ver);
-}
-
-static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp, u8 port,
-				    u32 ext_phy_type, u8 ext_phy_addr,
-				    u32 shmem_base)
-{
-	u16 fw_ver1, fw_ver2;
-
-	bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER1, &fw_ver1);
-	bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER2, &fw_ver2);
-	bnx2x_save_spirom_version(bp, port, shmem_base,
-				(u32)(fw_ver1<<16 | fw_ver2));
-}
-
-
-static void bnx2x_save_8481_spirom_version(struct bnx2x *bp, u8 port,
-					 u8 ext_phy_addr, u32 shmem_base)
-{
-	u16 val, fw_ver1, fw_ver2, cnt;
-	/* For the 32 bits registers in 8481, access via MDIO2ARM interface.*/
-	/* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-		       ext_phy_addr, MDIO_PMA_DEVAD,
-		       0xA819, 0x0014);
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       0xA81A,
-		       0xc200);
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       0xA81B,
-		       0x0000);
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       0xA81C,
-		       0x0300);
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       0xA817,
-		       0x0009);
-
-	for (cnt = 0; cnt < 100; cnt++) {
-		bnx2x_cl45_read(bp, port,
-			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-			      ext_phy_addr,
-			      MDIO_PMA_DEVAD,
-			      0xA818,
-			      &val);
-		if (val & 1)
-			break;
-		udelay(5);
-	}
-	if (cnt == 100) {
-		DP(NETIF_MSG_LINK, "Unable to read 8481 phy fw version(1)\n");
-		bnx2x_save_spirom_version(bp, port,
-					shmem_base, 0);
-		return;
-	}
-
-
-	/* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-		       ext_phy_addr, MDIO_PMA_DEVAD,
-		       0xA819, 0x0000);
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-		       ext_phy_addr, MDIO_PMA_DEVAD,
-		       0xA81A, 0xc200);
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-		       ext_phy_addr, MDIO_PMA_DEVAD,
-		       0xA817, 0x000A);
-	for (cnt = 0; cnt < 100; cnt++) {
-		bnx2x_cl45_read(bp, port,
-			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-			      ext_phy_addr,
-			      MDIO_PMA_DEVAD,
-			      0xA818,
-			      &val);
-		if (val & 1)
-			break;
-		udelay(5);
-	}
-	if (cnt == 100) {
-		DP(NETIF_MSG_LINK, "Unable to read 8481 phy fw version(2)\n");
-		bnx2x_save_spirom_version(bp, port,
-					shmem_base, 0);
-		return;
-	}
-
-	/* lower 16 bits of the register SPI_FW_STATUS */
-	bnx2x_cl45_read(bp, port,
-		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-		      ext_phy_addr,
-		      MDIO_PMA_DEVAD,
-		      0xA81B,
-		      &fw_ver1);
-	/* upper 16 bits of register SPI_FW_STATUS */
-	bnx2x_cl45_read(bp, port,
-		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-		      ext_phy_addr,
-		      MDIO_PMA_DEVAD,
-		      0xA81C,
-		      &fw_ver2);
-
-	bnx2x_save_spirom_version(bp, port,
-				shmem_base, (fw_ver2<<16) | fw_ver1);
-}
-
-static void bnx2x_bcm8072_external_rom_boot(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
-	/* Need to wait 200ms after reset */
-	msleep(200);
-	/* Boot port from external ROM
-	 * Set ser_boot_ctl bit in the MISC_CTRL1 register
-	 */
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-			    MDIO_PMA_DEVAD,
-			    MDIO_PMA_REG_MISC_CTRL1, 0x0001);
-
-	/* Reset internal microprocessor */
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-			  MDIO_PMA_DEVAD,
-			  MDIO_PMA_REG_GEN_CTRL,
-			  MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
-	/* set micro reset = 0 */
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-			    MDIO_PMA_DEVAD,
-			    MDIO_PMA_REG_GEN_CTRL,
-			    MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
-	/* Reset internal microprocessor */
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-			  MDIO_PMA_DEVAD,
-			  MDIO_PMA_REG_GEN_CTRL,
-			  MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
-	/* wait for 100ms for code download via SPI port */
-	msleep(100);
-
-	/* Clear ser_boot_ctl bit */
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-			    MDIO_PMA_DEVAD,
-			    MDIO_PMA_REG_MISC_CTRL1, 0x0000);
-	/* Wait 100ms */
-	msleep(100);
-
-	bnx2x_save_bcm_spirom_ver(bp, port,
-				ext_phy_type,
-				ext_phy_addr,
-				params->shmem_base);
-}
-
-static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
-{
-	/* This is only required for 8073A1, version 102 only */
-
-	struct bnx2x *bp = params->bp;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u16 val;
-
-	/* Read 8073 HW revision*/
-	bnx2x_cl45_read(bp, params->port,
-		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-		      ext_phy_addr,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_8073_CHIP_REV, &val);
-
-	if (val != 1) {
-		/* No need to workaround in 8073 A1 */
-		return 0;
-	}
-
-	bnx2x_cl45_read(bp, params->port,
-		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-		      ext_phy_addr,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER2, &val);
-
-	/* SNR should be applied only for version 0x102 */
-	if (val != 0x102)
-		return 0;
-
-	return 1;
-}
-
-static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u16 val, cnt, cnt1 ;
-
-	bnx2x_cl45_read(bp, params->port,
-		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-		      ext_phy_addr,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_8073_CHIP_REV, &val);
-
-	if (val > 0) {
-		/* No need to workaround in 8073 A1 */
-		return 0;
-	}
-	/* XAUI workaround in 8073 A0: */
-
-	/* After loading the boot ROM and restarting Autoneg,
-	poll Dev1, Reg $C820: */
-
-	for (cnt = 0; cnt < 1000; cnt++) {
-		bnx2x_cl45_read(bp, params->port,
-			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-			      ext_phy_addr,
-			      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.*/
-			for (cnt1 = 0; cnt1 < 1000; cnt1++) {
-				bnx2x_cl45_read(bp, params->port,
-					PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-					ext_phy_addr,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8073_XAUI_WA, &val);
-				if (val & (1<<15)) {
-					DP(NETIF_MSG_LINK,
-					  "XAUI workaround has completed\n");
-					return 0;
-				 }
-				 msleep(3);
-			}
-			break;
-		}
-		msleep(3);
-	}
-	DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
-	return -EINVAL;
-}
-
-static void bnx2x_bcm8073_bcm8727_external_rom_boot(struct bnx2x *bp, u8 port,
-						  u8 ext_phy_addr,
-						  u32 ext_phy_type,
-						  u32 shmem_base)
-{
-	/* Boot port from external ROM  */
-	/* EDC grst */
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       0x0001);
-
-	/* ucode reboot and rst */
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       0x008c);
-
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0001);
-
-	/* Reset internal microprocessor */
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
-
-	/* Release srst bit */
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
-
-	/* wait for 100ms for code download via SPI port */
-	msleep(100);
-
-	/* Clear ser_boot_ctl bit */
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0000);
-
-	bnx2x_save_bcm_spirom_ver(bp, port,
-				ext_phy_type,
-				ext_phy_addr,
-				shmem_base);
-}
-
-static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
-					  u8 ext_phy_addr,
-					  u32 shmem_base)
-{
-	bnx2x_bcm8073_bcm8727_external_rom_boot(bp, port, ext_phy_addr,
-					 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-					 shmem_base);
-}
-
-static void bnx2x_bcm8727_external_rom_boot(struct bnx2x *bp, u8 port,
-					  u8 ext_phy_addr,
-					  u32 shmem_base)
-{
-	bnx2x_bcm8073_bcm8727_external_rom_boot(bp, port, ext_phy_addr,
-					 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-					 shmem_base);
-
-}
-
-static void bnx2x_bcm8726_external_rom_boot(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
-	/* Need to wait 100ms after reset */
-	msleep(100);
-
-	/* Micro controller re-boot */
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       0x018B);
-
-	/* Set soft reset */
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
-
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0001);
-
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       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, port, ext_phy_type, ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0000);
-
-	msleep(200);
-	bnx2x_save_bcm_spirom_ver(bp, port,
-				ext_phy_type,
-				ext_phy_addr,
-				params->shmem_base);
-}
-
-static void bnx2x_sfp_set_transmitter(struct bnx2x *bp, u8 port,
-				    u32 ext_phy_type, u8 ext_phy_addr,
-				    u8 tx_en)
-{
-	u16 val;
-
-	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, port,
-		      ext_phy_type,
-		      ext_phy_addr,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_PHY_IDENTIFIER,
-		      &val);
-
-	if (tx_en)
-		val &= ~(1<<15);
-	else
-		val |= (1<<15);
-
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       val);
-}
-
-static u8 bnx2x_8726_read_sfp_module_eeprom(struct link_params *params,
-					  u16 addr, u8 byte_cnt, u8 *o_buf)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val = 0;
-	u16 i;
-	u8 port = params->port;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
-	if (byte_cnt > 16) {
-		DP(NETIF_MSG_LINK, "Reading from eeprom is"
-			    " is limited to 0xf\n");
-		return -EINVAL;
-	}
-	/* Set the read command byte count */
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
-		       (byte_cnt | 0xa000));
-
-	/* Set the read command address */
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
-		       addr);
-
-	/* Activate read command */
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
-		       0x2c0f);
-
-	/* Wait up to 500us for command complete status */
-	for (i = 0; i < 100; i++) {
-		bnx2x_cl45_read(bp, port,
-			      ext_phy_type,
-			      ext_phy_addr,
-			      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;
-		udelay(5);
-	}
-
-	if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
-		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
-		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;
-	}
-
-	/* Read the buffer */
-	for (i = 0; i < byte_cnt; i++) {
-		bnx2x_cl45_read(bp, port,
-			      ext_phy_type,
-			      ext_phy_addr,
-			      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, port,
-			      ext_phy_type,
-			      ext_phy_addr,
-			      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;;
-		msleep(1);
-	}
-	return -EINVAL;
-}
-
-static u8 bnx2x_8727_read_sfp_module_eeprom(struct link_params *params,
-					  u16 addr, u8 byte_cnt, u8 *o_buf)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val, i;
-	u8 port = params->port;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
-	if (byte_cnt > 16) {
-		DP(NETIF_MSG_LINK, "Reading from eeprom is"
-			    " is limited to 0xf\n");
-		return -EINVAL;
-	}
-
-	/* Need to read from 1.8000 to clear it */
-	bnx2x_cl45_read(bp, port,
-		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-		      ext_phy_addr,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
-		      &val);
-
-	/* Set the read command byte count */
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       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, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
-		       addr);
-	/* Set the destination address */
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       0x8004,
-		       MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF);
-
-	/* Activate read command */
-	bnx2x_cl45_write(bp, port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       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, port,
-			      ext_phy_type,
-			      ext_phy_addr,
-			      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;
-		udelay(5);
-	}
-
-	if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
-		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
-		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;
-	}
-
-	/* Read the buffer */
-	for (i = 0; i < byte_cnt; i++) {
-		bnx2x_cl45_read(bp, port,
-			      ext_phy_type,
-			      ext_phy_addr,
-			      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, port,
-			      ext_phy_type,
-			      ext_phy_addr,
-			      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;;
-		msleep(1);
-	}
-
-	return -EINVAL;
-}
-
-u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
-				     u8 byte_cnt, u8 *o_buf)
-{
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
-	if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
-		return bnx2x_8726_read_sfp_module_eeprom(params, addr,
-						       byte_cnt, o_buf);
-	else if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
-		return bnx2x_8727_read_sfp_module_eeprom(params, addr,
-						       byte_cnt, o_buf);
-	return -EINVAL;
-}
-
-static u8 bnx2x_get_edc_mode(struct link_params *params,
-				  u16 *edc_mode)
-{
-	struct bnx2x *bp = params->bp;
-	u8 val, check_limiting_mode = 0;
-	*edc_mode = EDC_MODE_LIMITING;
-
-	/* First check for copper cable */
-	if (bnx2x_read_sfp_module_eeprom(params,
-				       SFP_EEPROM_CON_TYPE_ADDR,
-				       1,
-				       &val) != 0) {
-		DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM\n");
-		return -EINVAL;
-	}
-
-	switch (val) {
-	case SFP_EEPROM_CON_TYPE_VAL_COPPER:
-	{
-		u8 copper_module_type;
-
-		/* Check if its active cable( includes SFP+ module)
-		of passive cable*/
-		if (bnx2x_read_sfp_module_eeprom(params,
-					       SFP_EEPROM_FC_TX_TECH_ADDR,
-					       1,
-					       &copper_module_type) !=
-		    0) {
-			DP(NETIF_MSG_LINK,
-				"Failed to read copper-cable-type"
-				" from SFP+ EEPROM\n");
-			return -EINVAL;
-		}
-
-		if (copper_module_type &
-		    SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
-			DP(NETIF_MSG_LINK, "Active Copper cable detected\n");
-			check_limiting_mode = 1;
-		} else if (copper_module_type &
-			SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
-				DP(NETIF_MSG_LINK, "Passive Copper"
-					    " cable detected\n");
-				*edc_mode =
-				      EDC_MODE_PASSIVE_DAC;
-		} else {
-			DP(NETIF_MSG_LINK, "Unknown copper-cable-"
-				     "type 0x%x !!!\n", copper_module_type);
-			return -EINVAL;
-		}
-		break;
-	}
-	case SFP_EEPROM_CON_TYPE_VAL_LC:
-		DP(NETIF_MSG_LINK, "Optic module detected\n");
-		check_limiting_mode = 1;
-		break;
-	default:
-		DP(NETIF_MSG_LINK, "Unable to determine module type 0x%x !!!\n",
-			 val);
-		return -EINVAL;
-	}
-
-	if (check_limiting_mode) {
-		u8 options[SFP_EEPROM_OPTIONS_SIZE];
-		if (bnx2x_read_sfp_module_eeprom(params,
-					       SFP_EEPROM_OPTIONS_ADDR,
-					       SFP_EEPROM_OPTIONS_SIZE,
-					       options) != 0) {
-			DP(NETIF_MSG_LINK, "Failed to read Option"
-				" field from module EEPROM\n");
-			return -EINVAL;
-		}
-		if ((options[0] & SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK))
-			*edc_mode = EDC_MODE_LINEAR;
-		else
-			*edc_mode = EDC_MODE_LIMITING;
-	}
-	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 */
-static u8 bnx2x_verify_sfp_module(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u32 val;
-	u32 fw_resp;
-	char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE+1];
-	char vendor_pn[SFP_EEPROM_PART_NO_SIZE+1];
-
-	val = REG_RD(bp, params->shmem_base +
-			 offsetof(struct shmem_region, dev_info.
-				  port_feature_config[params->port].config));
-	if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-	    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT) {
-		DP(NETIF_MSG_LINK, "NOT enforcing module verification\n");
-		return 0;
-	}
-
-	/* Ask the FW to validate the module */
-	if (!(params->feature_config_flags &
-	      FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY)) {
-		DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
-			    "verification\n");
-		return -EINVAL;
-	}
-
-	fw_resp = bnx2x_fw_command(bp, DRV_MSG_CODE_VRFY_OPT_MDL);
-	if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) {
-		DP(NETIF_MSG_LINK, "Approved module\n");
-		return 0;
-	}
-
-	/* format the warning message */
-	if (bnx2x_read_sfp_module_eeprom(params,
-				       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(params,
-				       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);
-	return -EINVAL;
-}
-
-static u8 bnx2x_bcm8726_set_limiting_mode(struct link_params *params,
-					u16 edc_mode)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u16 cur_limiting_mode;
-
-	bnx2x_cl45_read(bp, port,
-		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
-		      ext_phy_addr,
-		      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");
-		bnx2x_cl45_write(bp, port,
-			       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
-			       ext_phy_addr,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_ROM_VER2,
-			       EDC_MODE_LIMITING);
-	} else { /* LRM mode ( default )*/
-
-		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 )*/
-		if (cur_limiting_mode != EDC_MODE_LIMITING)
-			return 0;
-
-		bnx2x_cl45_write(bp, port,
-			       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
-			       ext_phy_addr,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_LRM_MODE,
-			       0);
-		bnx2x_cl45_write(bp, port,
-			       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
-			       ext_phy_addr,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_ROM_VER2,
-			       0x128);
-		bnx2x_cl45_write(bp, port,
-			       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
-			       ext_phy_addr,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_MISC_CTRL0,
-			       0x4008);
-		bnx2x_cl45_write(bp, port,
-			       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
-			       ext_phy_addr,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_LRM_MODE,
-			       0xaaaa);
-	}
-	return 0;
-}
-
-static u8 bnx2x_bcm8727_set_limiting_mode(struct link_params *params,
-					u16 edc_mode)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u16 phy_identifier;
-	u16 rom_ver2_val;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-
-	bnx2x_cl45_read(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       &phy_identifier);
-
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       (phy_identifier & ~(1<<9)));
-
-	bnx2x_cl45_read(bp, port,
-		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-		      ext_phy_addr,
-		      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, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_ROM_VER2,
-		       (rom_ver2_val & 0xff00) | (edc_mode & 0x00ff));
-
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       (phy_identifier | (1<<9)));
-
-	return 0;
-}
-
-
-static u8 bnx2x_wait_for_sfp_module_initialized(struct link_params *params)
-{
-	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 ) */
-	for (timeout = 0; timeout < 60; timeout++) {
-		if (bnx2x_read_sfp_module_eeprom(params, 1, 1, &val)
-		    == 0) {
-			DP(NETIF_MSG_LINK, "SFP+ module initialization "
-				     "took %d ms\n", timeout * 5);
-			return 0;
-		}
-		msleep(5);
-	}
-	return -EINVAL;
-}
-
-static void bnx2x_8727_power_module(struct bnx2x *bp,
-				  struct link_params *params,
-				  u8 ext_phy_addr, u8 is_power_up) {
-	/* Make sure GPIOs are not using for LED mode */
-	u16 val;
-	u8 port = params->port;
-	/*
-	 * In the GPIO register, bit 4 is use to detemine 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
-	 */
-
-	if (!(params->feature_config_flags &
-	      FEATURE_CONFIG_BCM8727_NOC) && is_power_up)
-		val = (1<<4);
-	else
-		/*
-		 * Set GPIO control to OUTPUT, and set the power bit
-		 * to according to the is_power_up
-		 */
-		val = ((!(is_power_up)) << 1);
-
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_8727_GPIO_CTRL,
-		       val);
-}
-
-static u8 bnx2x_sfp_module_detection(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u16 edc_mode;
-	u8 rc = 0;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-	u32 val = REG_RD(bp, params->shmem_base +
-			     offsetof(struct shmem_region, dev_info.
-				     port_feature_config[params->port].config));
-
-	DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
-		 params->port);
-
-	if (bnx2x_get_edc_mode(params, &edc_mode) != 0) {
-		DP(NETIF_MSG_LINK, "Failed to get valid module type\n");
-		return -EINVAL;
-	} else if (bnx2x_verify_sfp_module(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);
-		if ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
-		    ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-		     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) {
-			/* Shutdown SFP+ module */
-			DP(NETIF_MSG_LINK, "Shutdown SFP+ module!!\n");
-			bnx2x_8727_power_module(bp, params,
-					      ext_phy_addr, 0);
-			return rc;
-		}
-	} 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);
-	}
-
-	/* power up the SFP module */
-	if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
-		bnx2x_8727_power_module(bp, params, ext_phy_addr, 1);
-
-	/* Check and set limiting mode / LRM mode on 8726.
-	On 8727 it is done automatically */
-	if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
-		bnx2x_bcm8726_set_limiting_mode(params, edc_mode);
-	else
-		bnx2x_bcm8727_set_limiting_mode(params, edc_mode);
-	/*
-	 * Enable transmit for this module if the module is approved, or
-	 * if unapproved modules should also enable the Tx laser
-	 */
-	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, params->port,
-					ext_phy_type, ext_phy_addr, 1);
-	else
-		bnx2x_sfp_set_transmitter(bp, params->port,
-					ext_phy_type, ext_phy_addr, 0);
-
-	return rc;
-}
-
-void bnx2x_handle_module_detect_int(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u32 gpio_val;
-	u8 port = params->port;
-
-	/* Set valid module led off */
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-			  MISC_REGISTERS_GPIO_HIGH,
-			  params->port);
-
-	/* Get current gpio val refelecting module plugged in / out*/
-	gpio_val = bnx2x_get_gpio(bp,  MISC_REGISTERS_GPIO_3, port);
-
-	/* Call the handling function in case module is detected */
-	if (gpio_val == 0) {
-
-		bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
-				      MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
-				      port);
-
-		if (bnx2x_wait_for_sfp_module_initialized(params) ==
-		    0)
-			bnx2x_sfp_module_detection(params);
-		else
-			DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
-	} else {
-		u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-
-		u32 ext_phy_type =
-			XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-		u32 val = REG_RD(bp, params->shmem_base +
-				     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 */
-		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-		    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-			bnx2x_sfp_set_transmitter(bp, params->port,
-						ext_phy_type, ext_phy_addr, 0);
-	}
-}
-
-static void bnx2x_bcm807x_force_10G(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
-	/* Force KR or KX */
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_CTRL,
-		       0x2040);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_10G_CTRL2,
-		       0x000b);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_BCM_CTRL,
-		       0x0000);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_AN_DEVAD,
-		       MDIO_AN_REG_CTRL,
-		       0x0000);
-}
-
-static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u16 val;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
-	bnx2x_cl45_read(bp, params->port,
-		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-		      ext_phy_addr,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_8073_CHIP_REV, &val);
-
-	if (val == 0) {
-		/* Mustn't set low power mode in 8073 A0 */
-		return;
-	}
-
-	/* Disable PLL sequencer (use read-modify-write to clear bit 13) */
-	bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD,
-		       MDIO_XS_PLL_SEQUENCER, &val);
-	val &= ~(1<<13);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
-
-	/* PLL controls */
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, 0x805E, 0x1077);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, 0x805D, 0x0000);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, 0x805C, 0x030B);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, 0x805B, 0x1240);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, 0x805A, 0x2490);
-
-	/* Tx Controls */
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, 0x80A7, 0x0C74);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, 0x80A6, 0x9041);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, 0x80A5, 0x4640);
-
-	/* Rx Controls */
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, 0x80FE, 0x01C4);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, 0x80FD, 0x9249);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, 0x80FC, 0x2015);
-
-	/* Enable PLL sequencer  (use read-modify-write to set bit 13) */
-	bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD,
-		       MDIO_XS_PLL_SEQUENCER, &val);
-	val |= (1<<13);
-	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
-		       MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
-}
-
-static void bnx2x_8073_set_pause_cl37(struct link_params *params,
-				  struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u16 cl37_val;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
-	bnx2x_cl45_read(bp, params->port,
-		      ext_phy_type,
-		      ext_phy_addr,
-		      MDIO_AN_DEVAD,
-		      MDIO_AN_REG_CL37_FC_LD, &cl37_val);
-
-	cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
-	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
-
-	if ((vars->ieee_fc &
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
-		cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
-	}
-	if ((vars->ieee_fc &
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
-		cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
-	}
-	if ((vars->ieee_fc &
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
-		cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
-	}
-	DP(NETIF_MSG_LINK,
-		 "Ext phy AN advertize cl37 0x%x\n", cl37_val);
-
-	bnx2x_cl45_write(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_AN_DEVAD,
-		       MDIO_AN_REG_CL37_FC_LD, cl37_val);
-	msleep(500);
-}
-
-static void bnx2x_ext_phy_set_pause(struct link_params *params,
-				  struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
-	/* read modify write pause advertizing */
-	bnx2x_cl45_read(bp, params->port,
-		      ext_phy_type,
-		      ext_phy_addr,
-		      MDIO_AN_DEVAD,
-		      MDIO_AN_REG_ADV_PAUSE, &val);
-
-	val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
-
-	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
 
-	if ((vars->ieee_fc &
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
-		val |=  MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
-	}
-	if ((vars->ieee_fc &
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
-		val |=
-		 MDIO_AN_REG_ADV_PAUSE_PAUSE;
-	}
-	DP(NETIF_MSG_LINK,
-		 "Ext phy AN advertize 0x%x\n", val);
-	bnx2x_cl45_write(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_AN_DEVAD,
-		       MDIO_AN_REG_ADV_PAUSE, val);
-}
-static void bnx2x_set_preemphasis(struct link_params *params)
-{
 	u16 bank, i = 0;
 	struct bnx2x *bp = params->bp;
 
 	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, params->port,
-					      params->phy_addr,
-					      bank,
-					      MDIO_RX0_RX_EQ_BOOST,
-					      params->xgxs_config_rx[i]);
+			CL45_WR_OVER_CL22(bp, phy,
+					  bank,
+					  MDIO_RX0_RX_EQ_BOOST,
+					  phy->rx_preemphasis[i]);
 	}
 
 	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, params->port,
-					      params->phy_addr,
-					      bank,
-					      MDIO_TX0_TX_DRIVER,
-					      params->xgxs_config_tx[i]);
+			CL45_WR_OVER_CL22(bp, phy,
+					  bank,
+					  MDIO_TX0_TX_DRIVER,
+					  phy->tx_preemphasis[i]);
 	}
 }
 
-
-static void bnx2x_8481_set_led4(struct link_params *params,
-			      u32 ext_phy_type, u8 ext_phy_addr)
+static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
+				    struct link_params *params,
+				    struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-
-	/* PHYC_CTL_LED_CTL */
-	bnx2x_cl45_write(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_8481_LINK_SIGNAL, 0xa482);
-
-	/* Unmask LED4 for 10G link */
-	bnx2x_cl45_write(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_8481_SIGNAL_MASK, (1<<6));
-	/* 'Interrupt Mask' */
-	bnx2x_cl45_write(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_AN_DEVAD,
-		       0xFFFB, 0xFFFD);
-}
-static void bnx2x_8481_set_legacy_led_mode(struct link_params *params,
-					 u32 ext_phy_type, u8 ext_phy_addr)
-{
-	struct bnx2x *bp = params->bp;
-
-	/* LED1 (10G Link): Disable LED1 when 10/100/1000 link */
-	/* LED2 (1G/100/10 Link): Enable LED2 when 10/100/1000 link) */
-	bnx2x_cl45_write(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_AN_DEVAD,
-		       MDIO_AN_REG_8481_LEGACY_SHADOW,
-		       (1<<15) | (0xd << 10) | (0xc<<4) | 0xe);
-}
-
-static void bnx2x_8481_set_10G_led_mode(struct link_params *params,
-				      u32 ext_phy_type, u8 ext_phy_addr)
-{
-	struct bnx2x *bp = params->bp;
-	u16 val1;
-
-	/* LED1 (10G Link) */
-	/* Enable continuse based on source 7(10G-link) */
-	bnx2x_cl45_read(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_8481_LINK_SIGNAL,
-		       &val1);
-	/* Set bit 2 to 0, and bits [1:0] to 10 */
-	val1 &= ~((1<<0) | (1<<2) | (1<<7)); /* Clear bits 0,2,7*/
-	val1 |= ((1<<1) | (1<<6)); /* Set bit 1, 6 */
-
-	bnx2x_cl45_write(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_8481_LINK_SIGNAL,
-		       val1);
-
-	/* Unmask LED1 for 10G link */
-	bnx2x_cl45_read(bp, params->port,
-		      ext_phy_type,
-		      ext_phy_addr,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_8481_LED1_MASK,
-		      &val1);
-	/* Set bit 2 to 0, and bits [1:0] to 10 */
-	val1 |= (1<<7);
-	bnx2x_cl45_write(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_8481_LED1_MASK,
-		       val1);
-
-	/* LED2 (1G/100/10G Link) */
-	/* Mask LED2 for 10G link */
-	bnx2x_cl45_write(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_8481_LED2_MASK,
-		       0);
-
-	/* Unmask LED3 for 10G link */
-	bnx2x_cl45_write(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_8481_LED3_MASK,
-		       0x6);
-	bnx2x_cl45_write(bp, params->port,
-		       ext_phy_type,
-		       ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_8481_LED3_BLINK,
-		       0);
-}
-
-
-static void bnx2x_init_internal_phy(struct link_params *params,
-				  struct link_vars *vars,
-				  u8 enable_cl73)
-{
-	struct bnx2x *bp = params->bp;
-
+	u8 enable_cl73 = (SINGLE_MEDIA_DIRECT(params) ||
+			  (params->loopback_mode == LOOPBACK_XGXS));
 	if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
-		if ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
-		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
+		if (SINGLE_MEDIA_DIRECT(params) &&
 		    (params->feature_config_flags &
 		     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED))
-			bnx2x_set_preemphasis(params);
+			bnx2x_set_preemphasis(phy, params);
 
 		/* forced speed requested? */
 		if (vars->line_speed != SPEED_AUTO_NEG ||
-		    ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
-		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
+		    (SINGLE_MEDIA_DIRECT(params) &&
 			  params->loopback_mode == LOOPBACK_EXT)) {
 			DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
 
 			/* disable autoneg */
-			bnx2x_set_autoneg(params, vars, 0);
+			bnx2x_set_autoneg(phy, params, vars, 0);
 
 			/* program speed and duplex */
-			bnx2x_program_serdes(params, vars);
+			bnx2x_program_serdes(phy, params, vars);
 
 		} else { /* AN_mode */
 			DP(NETIF_MSG_LINK, "not SGMII, AN\n");
 
 			/* AN enabled */
-			bnx2x_set_brcm_cl37_advertisment(params);
+			bnx2x_set_brcm_cl37_advertisment(phy, params);
 
 			/* program duplex & pause advertisement (for aneg) */
-			bnx2x_set_ieee_aneg_advertisment(params,
+			bnx2x_set_ieee_aneg_advertisment(phy, params,
 						       vars->ieee_fc);
 
 			/* enable autoneg */
-			bnx2x_set_autoneg(params, vars, enable_cl73);
+			bnx2x_set_autoneg(phy, params, vars, enable_cl73);
 
 			/* enable and restart AN */
-			bnx2x_restart_autoneg(params, enable_cl73);
+			bnx2x_restart_autoneg(phy, params, enable_cl73);
 		}
 
 	} else { /* SGMII mode */
 		DP(NETIF_MSG_LINK, "SGMII\n");
 
-		bnx2x_initialize_sgmii_process(params, vars);
+		bnx2x_initialize_sgmii_process(phy, params, vars);
 	}
 }
 
-static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
+static u8 bnx2x_init_serdes(struct bnx2x_phy *phy,
+			    struct link_params *params,
+			    struct link_vars *vars)
 {
-	struct bnx2x *bp = params->bp;
-	u32 ext_phy_type;
-	u8 ext_phy_addr;
-	u16 cnt;
-	u16 ctrl = 0;
-	u16 val = 0;
-	u8 rc = 0;
-
-	if (vars->phy_flags & PHY_XGXS_FLAG) {
-		ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-
-		ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-		/* Make sure that the soft reset is off (expect for the 8072:
-		 * due to the lock, it will be done inside the specific
-		 * handling)
-		 */
-		if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
-		    (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
-		   (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
-		    (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
-		    (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
-			/* Wait for soft reset to get cleared upto 1 sec */
-			for (cnt = 0; cnt < 1000; cnt++) {
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_PMA_DEVAD,
-					      MDIO_PMA_REG_CTRL, &ctrl);
-				if (!(ctrl & (1<<15)))
-					break;
-				msleep(1);
-			}
-			DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n",
-				 ctrl, cnt);
-		}
-
-		switch (ext_phy_type) {
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
-			DP(NETIF_MSG_LINK, "XGXS 8705\n");
-
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_MISC_CTRL,
-				       0x8288);
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_PHY_IDENTIFIER,
-				       0x7fbf);
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_CMU_PLL_BYPASS,
-				       0x0100);
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_WIS_DEVAD,
-				       MDIO_WIS_REG_LASI_CNTL, 0x1);
-
-			/* BCM8705 doesn't have microcode, hence the 0 */
-			bnx2x_save_spirom_version(bp, params->port,
-						params->shmem_base, 0);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-			/* Wait until fw is loaded */
-			for (cnt = 0; cnt < 100; cnt++) {
-				bnx2x_cl45_read(bp, params->port, ext_phy_type,
-					      ext_phy_addr, MDIO_PMA_DEVAD,
-					      MDIO_PMA_REG_ROM_VER1, &val);
-				if (val)
-					break;
-				msleep(10);
-			}
-			DP(NETIF_MSG_LINK, "XGXS 8706 is initialized "
-				"after %d ms\n", cnt);
-			if ((params->feature_config_flags &
-			     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
-				u8 i;
-				u16 reg;
-				for (i = 0; i < 4; i++) {
-					reg = MDIO_XS_8706_REG_BANK_RX0 +
-						i*(MDIO_XS_8706_REG_BANK_RX1 -
-						   MDIO_XS_8706_REG_BANK_RX0);
-					bnx2x_cl45_read(bp, params->port,
-						      ext_phy_type,
-						      ext_phy_addr,
-						      MDIO_XS_DEVAD,
-						      reg, &val);
-					/* Clear first 3 bits of the control */
-					val &= ~0x7;
-					/* Set control bits according to
-					configuation */
-					val |= (params->xgxs_config_rx[i] &
-						0x7);
-					DP(NETIF_MSG_LINK, "Setting RX"
-						 "Equalizer to BCM8706 reg 0x%x"
-						 " <-- val 0x%x\n", reg, val);
-					bnx2x_cl45_write(bp, params->port,
-						       ext_phy_type,
-						       ext_phy_addr,
-						       MDIO_XS_DEVAD,
-						       reg, val);
-				}
-			}
-			/* Force speed */
-			if (params->req_line_speed == SPEED_10000) {
-				DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
-
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_DIGITAL_CTRL,
-					       0x400);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_LASI_CTRL, 1);
-			} else {
-				/* Force 1Gbps using autoneg with 1G
-				advertisment */
-
-				/* Allow CL37 through CL73 */
-				DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_AN_DEVAD,
-					       MDIO_AN_REG_CL37_CL73,
-					       0x040c);
-
-				/* Enable Full-Duplex advertisment on CL37 */
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_AN_DEVAD,
-					       MDIO_AN_REG_CL37_FC_LP,
-					       0x0020);
-				/* Enable CL37 AN */
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_AN_DEVAD,
-					       MDIO_AN_REG_CL37_AN,
-					       0x1000);
-				/* 1G support */
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_AN_DEVAD,
-					       MDIO_AN_REG_ADV, (1<<5));
-
-				/* Enable clause 73 AN */
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_AN_DEVAD,
-					       MDIO_AN_REG_CTRL,
-					       0x1200);
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_RX_ALARM_CTRL,
-					       0x0400);
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_LASI_CTRL, 0x0004);
-
-			}
-			bnx2x_save_bcm_spirom_ver(bp, params->port,
-						ext_phy_type,
-						ext_phy_addr,
-						params->shmem_base);
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-			DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
-			bnx2x_bcm8726_external_rom_boot(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 */
-			bnx2x_sfp_module_detection(params);
-
-			/* Set Flow control */
-			bnx2x_ext_phy_set_pause(params, vars);
-			if (params->req_line_speed == SPEED_1000) {
-				DP(NETIF_MSG_LINK, "Setting 1G force\n");
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_CTRL, 0x40);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_10G_CTRL2, 0xD);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_LASI_CTRL, 0x5);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_RX_ALARM_CTRL,
-					       0x400);
-			} else if ((params->req_line_speed ==
-				    SPEED_AUTO_NEG) &&
-				   ((params->speed_cap_mask &
-				     PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))) {
-				DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_AN_DEVAD,
-					       MDIO_AN_REG_ADV, 0x20);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_AN_DEVAD,
-					       MDIO_AN_REG_CL37_CL73, 0x040c);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_AN_DEVAD,
-					       MDIO_AN_REG_CL37_FC_LD, 0x0020);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_AN_DEVAD,
-					       MDIO_AN_REG_CL37_AN, 0x1000);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_AN_DEVAD,
-					       MDIO_AN_REG_CTRL, 0x1200);
-
-				/* Enable RX-ALARM control to receive
-				interrupt for 1G speed change */
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_LASI_CTRL, 0x4);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_RX_ALARM_CTRL,
-					       0x400);
-
-			} else { /* Default 10G. Set only LASI control */
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_LASI_CTRL, 1);
-			}
-
-			/* Set TX PreEmphasis if needed */
-			if ((params->feature_config_flags &
-			     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
-				DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
-					 "TX_CTRL2 0x%x\n",
-					 params->xgxs_config_tx[0],
-					 params->xgxs_config_tx[1]);
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_8726_TX_CTRL1,
-					       params->xgxs_config_tx[0]);
-
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_8726_TX_CTRL2,
-					       params->xgxs_config_tx[1]);
-			}
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-		{
-			u16 tmp1;
-			u16 rx_alarm_ctrl_val;
-			u16 lasi_ctrl_val;
-			if (ext_phy_type ==
-			    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
-				rx_alarm_ctrl_val = 0x400;
-				lasi_ctrl_val = 0x0004;
-			} else {
-				rx_alarm_ctrl_val = (1<<2);
-				lasi_ctrl_val = 0x0004;
-			}
-
-			/* enable LASI */
-			bnx2x_cl45_write(bp, params->port,
-				   ext_phy_type,
-				   ext_phy_addr,
-				   MDIO_PMA_DEVAD,
-				   MDIO_PMA_REG_RX_ALARM_CTRL,
-				   rx_alarm_ctrl_val);
-
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_LASI_CTRL,
-				       lasi_ctrl_val);
-
-			bnx2x_8073_set_pause_cl37(params, vars);
-
-			if (ext_phy_type ==
-			    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072)
-				bnx2x_bcm8072_external_rom_boot(params);
-			else
-				/* In case of 8073 with long xaui lines,
-				don't set the 8073 xaui low power*/
-				bnx2x_bcm8073_set_xaui_low_power_mode(params);
-
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_M8051_MSGOUT_REG,
-				      &tmp1);
-
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_RX_ALARM, &tmp1);
-
-			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)
-			 */
-			if (params->loopback_mode == LOOPBACK_EXT) {
-				bnx2x_bcm807x_force_10G(params);
-				DP(NETIF_MSG_LINK,
-					"Forced speed 10G on 807X\n");
-				break;
-			} else {
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type, ext_phy_addr,
-					       MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_BCM_CTRL,
-					       0x0002);
-			}
-			if (params->req_line_speed != SPEED_AUTO_NEG) {
-				if (params->req_line_speed == SPEED_10000) {
-					val = (1<<7);
-				} else if (params->req_line_speed ==
-					   SPEED_2500) {
-					val = (1<<5);
-					/* Note that 2.5G works only
-					when used with 1G advertisment */
-				} else
-					val = (1<<5);
-			} else {
-
-				val = 0;
-				if (params->speed_cap_mask &
-					PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
-					val |= (1<<7);
-
-				/* Note that 2.5G works only when
-				used with 1G advertisment */
-				if (params->speed_cap_mask &
-					(PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
-					 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
-					val |= (1<<5);
-				DP(NETIF_MSG_LINK,
-					 "807x autoneg val = 0x%x\n", val);
-			}
-
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_AN_DEVAD,
-				       MDIO_AN_REG_ADV, val);
-			if (ext_phy_type ==
-			    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_AN_DEVAD,
-					      MDIO_AN_REG_8073_2_5G, &tmp1);
-
-				if (((params->speed_cap_mask &
-				      PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
-				     (params->req_line_speed ==
-				      SPEED_AUTO_NEG)) ||
-				    (params->req_line_speed ==
-				     SPEED_2500)) {
-					u16 phy_ver;
-					/* Allow 2.5G for A1 and above */
-					bnx2x_cl45_read(bp, params->port,
-					 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-					 ext_phy_addr,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_8073_CHIP_REV, &phy_ver);
-					DP(NETIF_MSG_LINK, "Add 2.5G\n");
-					if (phy_ver > 0)
-						tmp1 |= 1;
-					else
-						tmp1 &= 0xfffe;
-				} else {
-					DP(NETIF_MSG_LINK, "Disable 2.5G\n");
-					tmp1 &= 0xfffe;
-				}
-
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_AN_DEVAD,
-					       MDIO_AN_REG_8073_2_5G, tmp1);
-			}
-
-			/* Add support for CL37 (passive mode) II */
-
-			bnx2x_cl45_read(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_AN_DEVAD,
-				       MDIO_AN_REG_CL37_FC_LD,
-				       &tmp1);
-
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_AN_DEVAD,
-				       MDIO_AN_REG_CL37_FC_LD, (tmp1 |
-				       ((params->req_duplex == DUPLEX_FULL) ?
-				       0x20 : 0x40)));
-
-			/* Add support for CL37 (passive mode) III */
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_AN_DEVAD,
-				       MDIO_AN_REG_CL37_AN, 0x1000);
-
-			if (ext_phy_type ==
-			    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-				/* 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(params))
-					bnx2x_cl45_write(bp, params->port,
-						    ext_phy_type,
-						    ext_phy_addr,
-						    MDIO_PMA_DEVAD,
-						    MDIO_PMA_REG_EDC_FFE_MAIN,
-						    0xFB0C);
-
-				/* Enable FEC (Forware Error Correction)
-				Request in the AN */
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_AN_DEVAD,
-					      MDIO_AN_REG_ADV2, &tmp1);
-
-				tmp1 |= (1<<15);
-
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_AN_DEVAD,
-					       MDIO_AN_REG_ADV2, tmp1);
-
-			}
-
-			bnx2x_ext_phy_set_pause(params, vars);
-
-			/* Restart autoneg */
-			msleep(500);
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_AN_DEVAD,
-				       MDIO_AN_REG_CTRL, 0x1200);
-			DP(NETIF_MSG_LINK, "807x Autoneg Restart: "
-			   "Advertise 1G=%x, 10G=%x\n",
-			   ((val & (1<<5)) > 0),
-			   ((val & (1<<7)) > 0));
-			break;
-		}
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-		{
-			u16 tmp1;
-			u16 rx_alarm_ctrl_val;
-			u16 lasi_ctrl_val;
-
-			/* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
-
-			u16 mod_abs;
-			rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
-			lasi_ctrl_val = 0x0004;
-
-			DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
-			/* enable LASI */
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_RX_ALARM_CTRL,
-				       rx_alarm_ctrl_val);
-
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_LASI_CTRL,
-				       lasi_ctrl_val);
-
-			/* Initially configure  MOD_ABS to interrupt when
-			module is presence( bit 8) */
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      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'.*/
-			mod_abs &= ~((1<<8) | (1<<9));
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
-
-			/* Make MOD_ABS give interrupt on change */
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_8727_PCS_OPT_CTRL,
-				      &val);
-			val |= (1<<12);
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_8727_PCS_OPT_CTRL,
-				       val);
-
-			/* Set 8727 GPIOs to input to allow reading from the
-			8727 GPIO0 status which reflect SFP+ module
-			over-current */
-
-			bnx2x_cl45_read(bp, params->port,
-				       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_8727_PCS_OPT_CTRL,
-				       &val);
-			val &= 0xff8f; /* Reset bits 4-6 */
-			bnx2x_cl45_write(bp, params->port,
-				       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_8727_PCS_OPT_CTRL,
-				       val);
-
-			bnx2x_8727_power_module(bp, params, ext_phy_addr, 1);
-			bnx2x_bcm8073_set_xaui_low_power_mode(params);
-
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_M8051_MSGOUT_REG,
-				      &tmp1);
-
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_RX_ALARM, &tmp1);
-
-			/* Set option 1G speed */
-			if (params->req_line_speed == SPEED_1000) {
-
-				DP(NETIF_MSG_LINK, "Setting 1G force\n");
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_CTRL, 0x40);
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_10G_CTRL2, 0xD);
-				bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_10G_CTRL2, &tmp1);
-				DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1);
-
-			} else if ((params->req_line_speed ==
-				    SPEED_AUTO_NEG) &&
-				   ((params->speed_cap_mask &
-				     PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))) {
-
-				DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_AN_DEVAD,
-					       MDIO_PMA_REG_8727_MISC_CTRL, 0);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, 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 */
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_AN_DEVAD,
-					       MDIO_AN_REG_CTRL, 0x0020);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_AN_DEVAD,
-					       0x7, 0x0100);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_CTRL, 0x2040);
-				bnx2x_cl45_write(bp, params->port, ext_phy_type,
-					       ext_phy_addr, MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_10G_CTRL2, 0x0008);
-			}
-
-			/* Set 2-wire transfer rate of SFP+ module EEPROM
-			 * to 100Khz since some DACs(direct attached cables) do
-			 * not work at 400Khz.
-			 */
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
-				       0xa001);
-
-			/* Set TX PreEmphasis if needed */
-			if ((params->feature_config_flags &
-			     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
-				DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
-					 "TX_CTRL2 0x%x\n",
-					 params->xgxs_config_tx[0],
-					 params->xgxs_config_tx[1]);
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_8727_TX_CTRL1,
-					       params->xgxs_config_tx[0]);
-
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_8727_TX_CTRL2,
-					       params->xgxs_config_tx[1]);
-			}
-
-			break;
-		}
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-		{
-			u16 fw_ver1, fw_ver2;
-			DP(NETIF_MSG_LINK,
-				"Setting the SFX7101 LASI indication\n");
-
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_LASI_CTRL, 0x1);
-			DP(NETIF_MSG_LINK,
-			  "Setting the SFX7101 LED to blink on traffic\n");
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
-
-			bnx2x_ext_phy_set_pause(params, vars);
-			/* Restart autoneg */
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_AN_DEVAD,
-				      MDIO_AN_REG_CTRL, &val);
-			val |= 0x200;
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_AN_DEVAD,
-				       MDIO_AN_REG_CTRL, val);
-
-			/* Save spirom version */
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr, MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_7101_VER1, &fw_ver1);
-
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr, MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_7101_VER2, &fw_ver2);
-
-			bnx2x_save_spirom_version(params->bp, params->port,
-						params->shmem_base,
-						(u32)(fw_ver1<<16 | fw_ver2));
-			break;
-		}
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
-			/* 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);
-
-			bnx2x_cl45_write(bp, params->port,
-				       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_CTRL, 0x0000);
-
-			bnx2x_8481_set_led4(params, ext_phy_type, ext_phy_addr);
-			if (params->req_line_speed == SPEED_AUTO_NEG) {
-
-				u16 autoneg_val, an_1000_val, an_10_100_val;
-				/* set 1000 speed advertisement */
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_AN_DEVAD,
-					      MDIO_AN_REG_8481_1000T_CTRL,
-					      &an_1000_val);
-
-				if (params->speed_cap_mask &
-				    PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) {
-					an_1000_val |= (1<<8);
-					if (params->req_duplex == DUPLEX_FULL)
-						an_1000_val |= (1<<9);
-					DP(NETIF_MSG_LINK, "Advertising 1G\n");
-				} else
-					an_1000_val &= ~((1<<8) | (1<<9));
-
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_AN_DEVAD,
-					       MDIO_AN_REG_8481_1000T_CTRL,
-					       an_1000_val);
-
-				/* set 100 speed advertisement */
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_AN_DEVAD,
-					      MDIO_AN_REG_8481_LEGACY_AN_ADV,
-					      &an_10_100_val);
-
-				if (params->speed_cap_mask &
-				 (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
-				  PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) {
-					an_10_100_val |= (1<<7);
-					if (params->req_duplex == DUPLEX_FULL)
-						an_10_100_val |= (1<<8);
-					DP(NETIF_MSG_LINK,
-						"Advertising 100M\n");
-				} else
-					an_10_100_val &= ~((1<<7) | (1<<8));
-
-				/* set 10 speed advertisement */
-				if (params->speed_cap_mask &
-				  (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
-				   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) {
-					an_10_100_val |= (1<<5);
-					if (params->req_duplex == DUPLEX_FULL)
-						an_10_100_val |= (1<<6);
-					DP(NETIF_MSG_LINK, "Advertising 10M\n");
-				     }
-				else
-					an_10_100_val &= ~((1<<5) | (1<<6));
-
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_AN_DEVAD,
-					       MDIO_AN_REG_8481_LEGACY_AN_ADV,
-					       an_10_100_val);
-
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_AN_DEVAD,
-					      MDIO_AN_REG_8481_LEGACY_MII_CTRL,
-					      &autoneg_val);
-
-				/* Disable forced speed */
-				autoneg_val &= ~(1<<6|1<<13);
-
-				/* Enable autoneg and restart autoneg
-				for legacy speeds */
-				autoneg_val |= (1<<9|1<<12);
-
-				if (params->req_duplex == DUPLEX_FULL)
-					autoneg_val |= (1<<8);
-				else
-					autoneg_val &= ~(1<<8);
-
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_AN_DEVAD,
-					       MDIO_AN_REG_8481_LEGACY_MII_CTRL,
-					       autoneg_val);
-
-				if (params->speed_cap_mask &
-				    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) {
-					DP(NETIF_MSG_LINK, "Advertising 10G\n");
-					/* Restart autoneg for 10G*/
-
-			bnx2x_cl45_write(bp, params->port,
-				       ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_AN_DEVAD,
-				       MDIO_AN_REG_CTRL, 0x3200);
-				}
-			} else {
-				/* Force speed */
-				u16 autoneg_ctrl, pma_ctrl;
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_AN_DEVAD,
-					      MDIO_AN_REG_8481_LEGACY_MII_CTRL,
-					      &autoneg_ctrl);
-
-				/* Disable autoneg */
-				autoneg_ctrl &= ~(1<<12);
-
-				/* Set 1000 force */
-				switch (params->req_line_speed) {
-				case SPEED_10000:
-					DP(NETIF_MSG_LINK,
-						"Unable to set 10G force !\n");
-					break;
-				case SPEED_1000:
-					bnx2x_cl45_read(bp, params->port,
-						      ext_phy_type,
-						      ext_phy_addr,
-						      MDIO_PMA_DEVAD,
-						      MDIO_PMA_REG_CTRL,
-						      &pma_ctrl);
-					autoneg_ctrl &= ~(1<<13);
-					autoneg_ctrl |= (1<<6);
-					pma_ctrl &= ~(1<<13);
-					pma_ctrl |= (1<<6);
-					DP(NETIF_MSG_LINK,
-						"Setting 1000M force\n");
-					bnx2x_cl45_write(bp, params->port,
-						       ext_phy_type,
-						       ext_phy_addr,
-						       MDIO_PMA_DEVAD,
-						       MDIO_PMA_REG_CTRL,
-						       pma_ctrl);
-					break;
-				case SPEED_100:
-					autoneg_ctrl |= (1<<13);
-					autoneg_ctrl &= ~(1<<6);
-					DP(NETIF_MSG_LINK,
-						"Setting 100M force\n");
-					break;
-				case SPEED_10:
-					autoneg_ctrl &= ~(1<<13);
-					autoneg_ctrl &= ~(1<<6);
-					DP(NETIF_MSG_LINK,
-						"Setting 10M force\n");
-					break;
-				}
-
-				/* Duplex mode */
-				if (params->req_duplex == DUPLEX_FULL) {
-					autoneg_ctrl |= (1<<8);
-					DP(NETIF_MSG_LINK,
-						"Setting full duplex\n");
-				} else
-					autoneg_ctrl &= ~(1<<8);
-
-				/* Update autoneg ctrl and pma ctrl */
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_AN_DEVAD,
-					       MDIO_AN_REG_8481_LEGACY_MII_CTRL,
-					       autoneg_ctrl);
-			}
-
-			/* Save spirom version */
-			bnx2x_save_8481_spirom_version(bp, params->port,
-						     ext_phy_addr,
-						     params->shmem_base);
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
-			DP(NETIF_MSG_LINK,
-				 "XGXS PHY Failure detected 0x%x\n",
-				 params->ext_phy_config);
-			rc = -EINVAL;
-			break;
-		default:
-			DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
-				  params->ext_phy_config);
-			rc = -EINVAL;
-			break;
-		}
-
-	} else { /* SerDes */
-
-		ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
-		switch (ext_phy_type) {
-		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
-			DP(NETIF_MSG_LINK, "SerDes Direct\n");
-			break;
-
-		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
-			DP(NETIF_MSG_LINK, "SerDes 5482\n");
-			break;
+	u8 rc;
+	vars->phy_flags |= PHY_SGMII_FLAG;
+	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+	bnx2x_set_aer_mmd_serdes(params->bp, phy);
+	rc = bnx2x_reset_unicore(params, phy, 1);
+	/* reset the SerDes and wait for reset bit return low */
+	if (rc != 0)
+		return rc;
+	bnx2x_set_aer_mmd_serdes(params->bp, phy);
 
-		default:
-			DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
-			   params->ext_phy_config);
-			break;
-		}
-	}
 	return rc;
 }
 
-static void bnx2x_8727_handle_mod_abs(struct link_params *params)
+static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
+			  struct link_params *params,
+			  struct link_vars *vars)
 {
-	struct bnx2x *bp = params->bp;
-	u16 mod_abs, rx_alarm_status;
-	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-	u32 val = REG_RD(bp, params->shmem_base +
-			     offsetof(struct shmem_region, dev_info.
-				      port_feature_config[params->port].
-				      config));
-	bnx2x_cl45_read(bp, params->port,
-		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-		      ext_phy_addr,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
-	if (mod_abs & (1<<8)) {
+	u8 rc;
+	vars->phy_flags = PHY_XGXS_FLAG;
+	if ((phy->req_line_speed &&
+	     ((phy->req_line_speed == SPEED_100) ||
+	      (phy->req_line_speed == SPEED_10))) ||
+	    (!phy->req_line_speed &&
+	     (phy->speed_cap_mask >=
+	      PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
+	     (phy->speed_cap_mask <
+	      PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
+	     ))
+		vars->phy_flags |= PHY_SGMII_FLAG;
+	else
+		vars->phy_flags &= ~PHY_SGMII_FLAG;
 
-		/* Module is absent */
-		DP(NETIF_MSG_LINK, "MOD_ABS indication "
-			    "show module is absent\n");
+	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+	bnx2x_set_aer_mmd_xgxs(params, phy);
+	bnx2x_set_master_ln(params, phy);
 
-		/* 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)|(1<<9));
-		bnx2x_cl45_write(bp, params->port,
-			       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-			       ext_phy_addr,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
+	rc = bnx2x_reset_unicore(params, phy, 0);
+	/* reset the SerDes and wait for reset bit return low */
+	if (rc != 0)
+		return rc;
 
-		/* Clear RX alarm since it stays up as long as
-		the mod_abs wasn't changed */
-		bnx2x_cl45_read(bp, params->port,
-			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-			      ext_phy_addr,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+	bnx2x_set_aer_mmd_xgxs(params, phy);
 
-	} 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*/
+	/* setting the masterLn_def again after the reset */
+	bnx2x_set_master_ln(params, phy);
+	bnx2x_set_swap_lanes(params, phy);
 
-		/* 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)|(1<<9));
-		bnx2x_cl45_write(bp, params->port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-		       ext_phy_addr,
-		       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 */
-		bnx2x_cl45_read(bp, params->port,
-			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-			      ext_phy_addr,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
-
-
-		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-		    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-			bnx2x_sfp_set_transmitter(bp, params->port,
-					PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-					ext_phy_addr, 0);
-
-		if (bnx2x_wait_for_sfp_module_initialized(params)
-		    == 0)
-			bnx2x_sfp_module_detection(params);
-		else
-			DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
-	}
-
-	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 */
+	return rc;
 }
 
-
-static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
-				 struct link_vars *vars,
-				 u8 is_mi_int)
+static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
+				     struct bnx2x_phy *phy)
 {
-	struct bnx2x *bp = params->bp;
-	u32 ext_phy_type;
-	u8 ext_phy_addr;
-	u16 val1 = 0, val2;
-	u16 rx_sd, pcs_status;
-	u8 ext_phy_link_up = 0;
-	u8 port = params->port;
-
-	if (vars->phy_flags & PHY_XGXS_FLAG) {
-		ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-		ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-		switch (ext_phy_type) {
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-			DP(NETIF_MSG_LINK, "XGXS Direct\n");
-			ext_phy_link_up = 1;
+	u16 cnt, ctrl;
+	/* Wait for soft reset to get cleared upto 1 sec */
+	for (cnt = 0; cnt < 1000; cnt++) {
+		bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, &ctrl);
+		if (!(ctrl & (1<<15)))
 			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
-			DP(NETIF_MSG_LINK, "XGXS 8705\n");
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_WIS_DEVAD,
-				      MDIO_WIS_REG_LASI_STATUS, &val1);
-			DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
-
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_WIS_DEVAD,
-				      MDIO_WIS_REG_LASI_STATUS, &val1);
-			DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
-
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_RX_SD, &rx_sd);
-
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      1,
-				      0xc809, &val1);
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      1,
-				      0xc809, &val1);
-
-			DP(NETIF_MSG_LINK, "8705 1.c809 val=0x%x\n", val1);
-			ext_phy_link_up = ((rx_sd & 0x1) && (val1 & (1<<9)) &&
-					   ((val1 & (1<<8)) == 0));
-			if (ext_phy_link_up)
-				vars->line_speed = SPEED_10000;
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-			DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
-			/* Clear RX Alarm*/
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM,
-				      &val2);
-			/* clear LASI indication*/
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS,
-				      &val1);
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS,
-				      &val2);
-			DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x-->"
-				     "0x%x\n", val1, val2);
-
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD,
-				      &rx_sd);
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS,
-				      &pcs_status);
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS,
-				      &val2);
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS,
-				      &val2);
-
-			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
-			 */
-			ext_phy_link_up = ((rx_sd & pcs_status & 0x1) ||
-					   (val2 & (1<<1)));
-			if (ext_phy_link_up) {
-				if (ext_phy_type ==
-				     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
-					/* If transmitter is disabled,
-					ignore false link up indication */
-					bnx2x_cl45_read(bp, params->port,
-						   ext_phy_type,
-						   ext_phy_addr,
-						   MDIO_PMA_DEVAD,
-						   MDIO_PMA_REG_PHY_IDENTIFIER,
-						   &val1);
-					if (val1 & (1<<15)) {
-						DP(NETIF_MSG_LINK, "Tx is "
-							    "disabled\n");
-						ext_phy_link_up = 0;
-						break;
-					}
-				}
-				if (val2 & (1<<1))
-					vars->line_speed = SPEED_1000;
-				else
-					vars->line_speed = SPEED_10000;
-			}
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-		{
-			u16 link_status = 0;
-			u16 rx_alarm_status;
-			/* Check the LASI */
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
-
-			DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n",
-				 rx_alarm_status);
-
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_LASI_STATUS, &val1);
-
-			DP(NETIF_MSG_LINK,
-				 "8727 LASI status 0x%x\n",
-				 val1);
-
-			/* Clear MSG-OUT */
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_M8051_MSGOUT_REG,
-				      &val1);
-
-			/*
-			 * If a module is present and there is need to check
-			 * for over current
-			 */
-			if (!(params->feature_config_flags &
-			      FEATURE_CONFIG_BCM8727_NOC) &&
-			    !(rx_alarm_status & (1<<5))) {
-				/* Check over-current using 8727 GPIO0 input*/
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_PMA_DEVAD,
-					      MDIO_PMA_REG_8727_GPIO_CTRL,
-					      &val1);
-
-				if ((val1 & (1<<8)) == 0) {
-					DP(NETIF_MSG_LINK, "8727 Power fault"
-						     " has been detected on "
-						     "port %d\n",
-						 params->port);
-					netdev_err(bp->dev, "Error:  Power fault on Port %d has been detected and the power to that SFP+ module has been removed to prevent failure of the card. Please remove the SFP+ module and restart the system to clear this error.\n",
-						   params->port);
-					/*
-					 * Disable all RX_ALARMs except for
-					 * mod_abs
-					 */
-					bnx2x_cl45_write(bp, params->port,
-						     ext_phy_type,
-						     ext_phy_addr,
-						     MDIO_PMA_DEVAD,
-						     MDIO_PMA_REG_RX_ALARM_CTRL,
-						     (1<<5));
-
-					bnx2x_cl45_read(bp, params->port,
-						    ext_phy_type,
-						    ext_phy_addr,
-						    MDIO_PMA_DEVAD,
-						    MDIO_PMA_REG_PHY_IDENTIFIER,
-						    &val1);
-					/* Wait for module_absent_event */
-					val1 |= (1<<8);
-					bnx2x_cl45_write(bp, params->port,
-						    ext_phy_type,
-						    ext_phy_addr,
-						    MDIO_PMA_DEVAD,
-						    MDIO_PMA_REG_PHY_IDENTIFIER,
-						    val1);
-					/* Clear RX alarm */
-					bnx2x_cl45_read(bp, params->port,
-						      ext_phy_type,
-						      ext_phy_addr,
-						      MDIO_PMA_DEVAD,
-						      MDIO_PMA_REG_RX_ALARM,
-						      &rx_alarm_status);
-					break;
-				}
-			} /* Over current check */
-
-			/* When module absent bit is set, check module */
-			if (rx_alarm_status & (1<<5)) {
-				bnx2x_8727_handle_mod_abs(params);
-				/* Enable all mod_abs and link detection bits */
-				bnx2x_cl45_write(bp, params->port,
-					       ext_phy_type,
-					       ext_phy_addr,
-					       MDIO_PMA_DEVAD,
-					       MDIO_PMA_REG_RX_ALARM_CTRL,
-					       ((1<<5) | (1<<2)));
-			}
-
-			/* If transmitter is disabled,
-			ignore false link up indication */
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_PHY_IDENTIFIER,
-				      &val1);
-			if (val1 & (1<<15)) {
-				DP(NETIF_MSG_LINK, "Tx is disabled\n");
-				ext_phy_link_up = 0;
-				break;
-			}
-
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
-				      &link_status);
-
-			/* Bits 0..2 --> speed detected,
-			   bits 13..15--> link is down */
-			if ((link_status & (1<<2)) &&
-			    (!(link_status & (1<<15)))) {
-				ext_phy_link_up = 1;
-				vars->line_speed = SPEED_10000;
-			} else if ((link_status & (1<<0)) &&
-				   (!(link_status & (1<<13)))) {
-				ext_phy_link_up = 1;
-				vars->line_speed = SPEED_1000;
-				DP(NETIF_MSG_LINK,
-					 "port %x: External link"
-					 " up in 1G\n", params->port);
-			} else {
-				ext_phy_link_up = 0;
-				DP(NETIF_MSG_LINK,
-					 "port %x: External link"
-					 " is down\n", params->port);
-			}
-			break;
-		}
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-		{
-			u16 link_status = 0;
-			u16 an1000_status = 0;
-
-			if (ext_phy_type ==
-			     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
-				bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PCS_DEVAD,
-				      MDIO_PCS_REG_LASI_STATUS, &val1);
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PCS_DEVAD,
-				      MDIO_PCS_REG_LASI_STATUS, &val2);
-			DP(NETIF_MSG_LINK,
-				 "870x LASI status 0x%x->0x%x\n",
-				  val1, val2);
-			} else {
-				/* In 8073, port1 is directed through emac0 and
-				 * port0 is directed through emac1
-				 */
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_PMA_DEVAD,
-					      MDIO_PMA_REG_LASI_STATUS, &val1);
-
-				DP(NETIF_MSG_LINK,
-					 "8703 LASI status 0x%x\n",
-					  val1);
-			}
-
-			/* clear the interrupt LASI status register */
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PCS_DEVAD,
-				      MDIO_PCS_REG_STATUS, &val2);
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PCS_DEVAD,
-				      MDIO_PCS_REG_STATUS, &val1);
-			DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n",
-			   val2, val1);
-			/* Clear MSG-OUT */
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_M8051_MSGOUT_REG,
-				      &val1);
-
-			/* Check the LASI */
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_RX_ALARM, &val2);
-
-			DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
-
-			/* Check the link status */
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PCS_DEVAD,
-				      MDIO_PCS_REG_STATUS, &val2);
-			DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
-
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_STATUS, &val2);
-			bnx2x_cl45_read(bp, params->port,
-				      ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_STATUS, &val1);
-			ext_phy_link_up = ((val1 & 4) == 4);
-			DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
-			if (ext_phy_type ==
-			    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-
-				if (ext_phy_link_up &&
-				    ((params->req_line_speed !=
-					SPEED_10000))) {
-					if (bnx2x_bcm8073_xaui_wa(params)
-					     != 0) {
-						ext_phy_link_up = 0;
-						break;
-					}
-				}
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_AN_DEVAD,
-					      MDIO_AN_REG_LINK_STATUS,
-					      &an1000_status);
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_AN_DEVAD,
-					      MDIO_AN_REG_LINK_STATUS,
-					      &an1000_status);
-
-				/* Check the link status on 1.1.2 */
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_PMA_DEVAD,
-					      MDIO_PMA_REG_STATUS, &val2);
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_PMA_DEVAD,
-					      MDIO_PMA_REG_STATUS, &val1);
-				DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
-					     "an_link_status=0x%x\n",
-					  val2, val1, an1000_status);
-
-				ext_phy_link_up = (((val1 & 4) == 4) ||
-						(an1000_status & (1<<1)));
-				if (ext_phy_link_up &&
-				    bnx2x_8073_is_snr_needed(params)) {
-					/* 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, port, ext_phy_type,
-						    ext_phy_addr,
-						    MDIO_PMA_DEVAD,
-						    MDIO_PMA_REG_PLL_BANDWIDTH,
-						    0x26BC);
-
-					/* Change CDR Bandwidth in EDC
-					register */
-					bnx2x_cl45_write(bp, port, ext_phy_type,
-						    ext_phy_addr,
-						    MDIO_PMA_DEVAD,
-						    MDIO_PMA_REG_CDR_BANDWIDTH,
-						    0x0333);
-				}
-				bnx2x_cl45_read(bp, params->port,
-					   ext_phy_type,
-					   ext_phy_addr,
-					   MDIO_PMA_DEVAD,
-					   MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
-					   &link_status);
-
-				/* Bits 0..2 --> speed detected,
-				   bits 13..15--> link is down */
-				if ((link_status & (1<<2)) &&
-				    (!(link_status & (1<<15)))) {
-					ext_phy_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<<1)) &&
-					   (!(link_status & (1<<14)))) {
-					ext_phy_link_up = 1;
-					vars->line_speed = SPEED_2500;
-					DP(NETIF_MSG_LINK,
-						 "port %x: External link"
-						 " up in 2.5G\n", params->port);
-				} else if ((link_status & (1<<0)) &&
-					   (!(link_status & (1<<13)))) {
-					ext_phy_link_up = 1;
-					vars->line_speed = SPEED_1000;
-					DP(NETIF_MSG_LINK,
-						 "port %x: External link"
-						 " up in 1G\n", params->port);
-				} else {
-					ext_phy_link_up = 0;
-					DP(NETIF_MSG_LINK,
-						 "port %x: External link"
-						 " is down\n", params->port);
-				}
-			} else {
-				/* See if 1G link is up for the 8072 */
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_AN_DEVAD,
-					      MDIO_AN_REG_LINK_STATUS,
-					      &an1000_status);
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_AN_DEVAD,
-					      MDIO_AN_REG_LINK_STATUS,
-					      &an1000_status);
-				if (an1000_status & (1<<1)) {
-					ext_phy_link_up = 1;
-					vars->line_speed = SPEED_1000;
-					DP(NETIF_MSG_LINK,
-						 "port %x: External link"
-						 " up in 1G\n", params->port);
-				} else if (ext_phy_link_up) {
-					ext_phy_link_up = 1;
-					vars->line_speed = SPEED_10000;
-					DP(NETIF_MSG_LINK,
-						 "port %x: External link"
-						 " up in 10G\n", params->port);
-				}
-			}
-
-
-			break;
-		}
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_LASI_STATUS, &val2);
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_LASI_STATUS, &val1);
-			DP(NETIF_MSG_LINK,
-				 "10G-base-T LASI status 0x%x->0x%x\n",
-				  val2, val1);
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_STATUS, &val2);
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_STATUS, &val1);
-			DP(NETIF_MSG_LINK,
-				 "10G-base-T PMA status 0x%x->0x%x\n",
-				 val2, val1);
-			ext_phy_link_up = ((val1 & 4) == 4);
-			/* if link is up
-			 * print the AN outcome of the SFX7101 PHY
-			 */
-			if (ext_phy_link_up) {
-				bnx2x_cl45_read(bp, params->port,
-					      ext_phy_type,
-					      ext_phy_addr,
-					      MDIO_AN_DEVAD,
-					      MDIO_AN_REG_MASTER_STATUS,
-					      &val2);
-				vars->line_speed = SPEED_10000;
-				DP(NETIF_MSG_LINK,
-					 "SFX7101 AN status 0x%x->Master=%x\n",
-					  val2,
-					 (val2 & (1<<14)));
-			}
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
-			/* Check 10G-BaseT link status */
-			/* Check PMD signal ok */
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-						      ext_phy_addr,
-						      MDIO_AN_DEVAD,
-						      0xFFFA,
-						      &val1);
-			bnx2x_cl45_read(bp, params->port, ext_phy_type,
-				      ext_phy_addr,
-				      MDIO_PMA_DEVAD,
-				      MDIO_PMA_REG_8481_PMD_SIGNAL,
-				      &val2);
-			DP(NETIF_MSG_LINK, "PMD_SIGNAL 1.a811 = 0x%x\n", val2);
-
-			/* Check link 10G */
-			if (val2 & (1<<11)) {
-				vars->line_speed = SPEED_10000;
-				ext_phy_link_up = 1;
-				bnx2x_8481_set_10G_led_mode(params,
-							  ext_phy_type,
-							  ext_phy_addr);
-			} else { /* Check Legacy speed link */
-				u16 legacy_status, legacy_speed;
-
-				/* Enable expansion register 0x42
-				(Operation mode status) */
-				bnx2x_cl45_write(bp, params->port,
-					 ext_phy_type,
-					 ext_phy_addr,
-					 MDIO_AN_DEVAD,
-					 MDIO_AN_REG_8481_EXPANSION_REG_ACCESS,
-					 0xf42);
-
-				/* Get legacy speed operation status */
-				bnx2x_cl45_read(bp, params->port,
-					  ext_phy_type,
-					  ext_phy_addr,
-					  MDIO_AN_DEVAD,
-					  MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
-					  &legacy_status);
-
-				DP(NETIF_MSG_LINK, "Legacy speed status"
-					     " = 0x%x\n", legacy_status);
-				ext_phy_link_up = ((legacy_status & (1<<11))
-						   == (1<<11));
-				if (ext_phy_link_up) {
-					legacy_speed = (legacy_status & (3<<9));
-					if (legacy_speed == (0<<9))
-						vars->line_speed = SPEED_10;
-					else if (legacy_speed == (1<<9))
-						vars->line_speed =
-							SPEED_100;
-					else if (legacy_speed == (2<<9))
-						vars->line_speed =
-							SPEED_1000;
-					else /* Should not happen */
-						vars->line_speed = 0;
-
-					if (legacy_status & (1<<8))
-						vars->duplex = DUPLEX_FULL;
-					else
-						vars->duplex = DUPLEX_HALF;
-
-					DP(NETIF_MSG_LINK, "Link is up "
-						     "in %dMbps, is_duplex_full"
-						     "= %d\n",
-						vars->line_speed,
-						(vars->duplex == DUPLEX_FULL));
-					bnx2x_8481_set_legacy_led_mode(params,
-								 ext_phy_type,
-								 ext_phy_addr);
-				}
-			}
-			break;
-		default:
-			DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
-			   params->ext_phy_config);
-			ext_phy_link_up = 0;
-			break;
-		}
-		/* Set SGMII mode for external phy */
-		if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
-			if (vars->line_speed < SPEED_1000)
-				vars->phy_flags |= PHY_SGMII_FLAG;
-			else
-				vars->phy_flags &= ~PHY_SGMII_FLAG;
-		}
-
-	} else { /* SerDes */
-		ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
-		switch (ext_phy_type) {
-		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
-			DP(NETIF_MSG_LINK, "SerDes Direct\n");
-			ext_phy_link_up = 1;
-			break;
-
-		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
-			DP(NETIF_MSG_LINK, "SerDes 5482\n");
-			ext_phy_link_up = 1;
-			break;
-
-		default:
-			DP(NETIF_MSG_LINK,
-				 "BAD SerDes ext_phy_config 0x%x\n",
-				 params->ext_phy_config);
-			ext_phy_link_up = 0;
-			break;
-		}
+		msleep(1);
 	}
-
-	return ext_phy_link_up;
+	DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n", ctrl, cnt);
+	return cnt;
 }
 
 static void bnx2x_link_int_enable(struct link_params *params)
 {
 	u8 port = params->port;
-	u32 ext_phy_type;
 	u32 mask;
 	struct bnx2x *bp = params->bp;
 
@@ -5329,11 +2280,9 @@
 		mask = (NIG_MASK_XGXS0_LINK10G |
 			NIG_MASK_XGXS0_LINK_STATUS);
 		DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
-		ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-		if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
-		    (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
-		    (ext_phy_type !=
-				PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) {
+		if (!(SINGLE_MEDIA_DIRECT(params)) &&
+			params->phy[INT_PHY].type !=
+				PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) {
 			mask |= NIG_MASK_MI_INT;
 			DP(NETIF_MSG_LINK, "enabled external phy int\n");
 		}
@@ -5341,11 +2290,9 @@
 	} else { /* SerDes */
 		mask = NIG_MASK_SERDES0_LINK_STATUS;
 		DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
-		ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
-		if ((ext_phy_type !=
-				PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
-		    (ext_phy_type !=
-				PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) {
+		if (!(SINGLE_MEDIA_DIRECT(params)) &&
+			params->phy[INT_PHY].type !=
+				PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN) {
 			mask |= NIG_MASK_MI_INT;
 			DP(NETIF_MSG_LINK, "enabled external phy int\n");
 		}
@@ -5366,47 +2313,43 @@
 	   REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
 }
 
-static void bnx2x_8481_rearm_latch_signal(struct bnx2x *bp, u8 port,
-					u8 is_mi_int)
+static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port,
+				     u8 exp_mi_int)
 {
-	u32 latch_status = 0, is_mi_int_status;
-	/* 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
+	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
 	 */
 	/* Read Latched signals */
 	latch_status = REG_RD(bp,
-				  NIG_REG_LATCH_STATUS_0 + port*8);
-	is_mi_int_status = REG_RD(bp,
-				  NIG_REG_STATUS_INTERRUPT_PORT0 + port*4);
-	DP(NETIF_MSG_LINK, "original_signal = 0x%x, nig_status = 0x%x,"
-		     "latch_status = 0x%x\n",
-		 is_mi_int, is_mi_int_status, latch_status);
+				    NIG_REG_LATCH_STATUS_0 + port*8);
+	DP(NETIF_MSG_LINK, "latch_status = 0x%x\n", latch_status);
 	/* Handle only those with latched-signal=up.*/
+	if (exp_mi_int)
+		bnx2x_bits_en(bp,
+			      NIG_REG_STATUS_INTERRUPT_PORT0
+			      + port*4,
+			      NIG_STATUS_EMAC0_MI_INT);
+	else
+		bnx2x_bits_dis(bp,
+			       NIG_REG_STATUS_INTERRUPT_PORT0
+			       + port*4,
+			       NIG_STATUS_EMAC0_MI_INT);
+
 	if (latch_status & 1) {
-		/* For all latched-signal=up,Write original_signal to status */
-		if (is_mi_int)
-			bnx2x_bits_en(bp,
-				    NIG_REG_STATUS_INTERRUPT_PORT0
-				    + port*4,
-				    NIG_STATUS_EMAC0_MI_INT);
-		else
-			bnx2x_bits_dis(bp,
-				     NIG_REG_STATUS_INTERRUPT_PORT0
-				     + port*4,
-				     NIG_STATUS_EMAC0_MI_INT);
+
 		/* 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 */
 }
-/*
- * link management
- */
+
 static void bnx2x_link_int_ack(struct link_params *params,
-			     struct link_vars *vars, u8 is_10g,
-			     u8 is_mi_int)
+			     struct link_vars *vars, u8 is_10g)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -5417,12 +2360,6 @@
 		     (NIG_STATUS_XGXS0_LINK10G |
 		      NIG_STATUS_XGXS0_LINK_STATUS |
 		      NIG_STATUS_SERDES0_LINK_STATUS));
-	if ((XGXS_EXT_PHY_TYPE(params->ext_phy_config)
-		== PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) ||
-	(XGXS_EXT_PHY_TYPE(params->ext_phy_config)
-		== PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823)) {
-		bnx2x_8481_rearm_latch_signal(bp, port, is_mi_int);
-	}
 	if (vars->phy_link_up) {
 		if (is_10g) {
 			/* Disable the 10G link interrupt
@@ -5459,37 +2396,52 @@
 				      NIG_STATUS_SERDES0_LINK_STATUS);
 		}
 
-	} else { /* link_down */
 	}
 }
 
-static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
+static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len)
 {
 	u8 *str_ptr = str;
 	u32 mask = 0xf0000000;
 	u8 shift = 8*4;
 	u8 digit;
-	if (len < 10) {
+	u8 remove_leading_zeros = 1;
+	if (*len < 10) {
 		/* Need more than 10chars for this format */
 		*str_ptr = '\0';
+		(*len)--;
 		return -EINVAL;
 	}
 	while (shift > 0) {
 
 		shift -= 4;
 		digit = ((num & mask) >> shift);
-		if (digit < 0xa)
+		if (digit == 0 && remove_leading_zeros) {
+			mask = mask >> 4;
+			continue;
+		} else if (digit < 0xa)
 			*str_ptr = digit + '0';
 		else
 			*str_ptr = digit - 0xa + 'a';
+		remove_leading_zeros = 0;
 		str_ptr++;
+		(*len)--;
 		mask = mask >> 4;
 		if (shift == 4*4) {
-			*str_ptr = ':';
+			*str_ptr = '.';
 			str_ptr++;
+			(*len)--;
+			remove_leading_zeros = 1;
 		}
 	}
-	*str_ptr = '\0';
+	return 0;
+}
+
+
+static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+{
+	str[0] = '\0';
+	(*len)--;
 	return 0;
 }
 
@@ -5497,72 +2449,50 @@
 			      u8 *version, u16 len)
 {
 	struct bnx2x *bp;
-	u32 ext_phy_type = 0;
 	u32 spirom_ver = 0;
-	u8 status;
-
+	u8 status = 0;
+	u8 *ver_p = version;
+	u16 remain_len = len;
 	if (version == NULL || params == NULL)
 		return -EINVAL;
 	bp = params->bp;
 
-	spirom_ver = REG_RD(bp, params->shmem_base +
-		   offsetof(struct shmem_region,
-			    port_mb[params->port].ext_phy_fw_version));
+	/* Extract first external phy*/
+	version[0] = '\0';
+	spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr);
 
-	status = 0;
-	/* reset the returned value to zero */
-	ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-	switch (ext_phy_type) {
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-
-		if (len < 5)
-			return -EINVAL;
-
-		version[0] = (spirom_ver & 0xFF);
-		version[1] = (spirom_ver & 0xFF00) >> 8;
-		version[2] = (spirom_ver & 0xFF0000) >> 16;
-		version[3] = (spirom_ver & 0xFF000000) >> 24;
-		version[4] = '\0';
-
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-		status = bnx2x_format_ver(spirom_ver, version, len);
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
-		spirom_ver = ((spirom_ver & 0xF80) >> 7) << 16 |
-			(spirom_ver & 0x7F);
-		status = bnx2x_format_ver(spirom_ver, version, len);
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
-		version[0] = '\0';
-		break;
-
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
-		DP(NETIF_MSG_LINK, "bnx2x_get_ext_phy_fw_version:"
-				    " type is FAILURE!\n");
-		status = -EINVAL;
-		break;
-
-	default:
-		break;
+	if (params->phy[EXT_PHY1].format_fw_ver) {
+		status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver,
+							      ver_p,
+							      &remain_len);
+		ver_p += (len - remain_len);
 	}
+	if ((params->num_phys == MAX_PHYS) &&
+	    (params->phy[EXT_PHY2].ver_addr != 0)) {
+		spirom_ver = REG_RD(bp,
+					  params->phy[EXT_PHY2].ver_addr);
+		if (params->phy[EXT_PHY2].format_fw_ver) {
+			*ver_p = '/';
+			ver_p++;
+			remain_len--;
+			status |= params->phy[EXT_PHY2].format_fw_ver(
+				spirom_ver,
+				ver_p,
+				&remain_len);
+			ver_p = version + (len - remain_len);
+		}
+	}
+	*ver_p = '\0';
 	return status;
 }
 
-static void bnx2x_set_xgxs_loopback(struct link_params *params,
-				  struct link_vars *vars,
-				  u8 is_10g)
+static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
+				    struct link_params *params)
 {
 	u8 port = params->port;
 	struct bnx2x *bp = params->bp;
 
-	if (is_10g) {
+	if (phy->req_line_speed != SPEED_1000) {
 		u32 md_devad;
 
 		DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
@@ -5573,107 +2503,45 @@
 
 		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
 
-		bnx2x_cl45_write(bp, port, 0,
-			       params->phy_addr,
+		bnx2x_cl45_write(bp, phy,
 			       5,
 			       (MDIO_REG_BANK_AER_BLOCK +
 				(MDIO_AER_BLOCK_AER_REG & 0xf)),
 			       0x2800);
 
-		bnx2x_cl45_write(bp, port, 0,
-			       params->phy_addr,
+		bnx2x_cl45_write(bp, phy,
 			       5,
 			       (MDIO_REG_BANK_CL73_IEEEB0 +
 				(MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
 			       0x6041);
 		msleep(200);
 		/* set aer mmd back */
-		bnx2x_set_aer_mmd(params, vars);
+		bnx2x_set_aer_mmd_xgxs(params, phy);
 
 		/* and md_devad */
 		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
 			    md_devad);
 
 	} else {
-		u16 mii_control;
-
+		u16 mii_ctrl;
 		DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
-
-		CL45_RD_OVER_CL22(bp, port,
-				      params->phy_addr,
-				      MDIO_REG_BANK_COMBO_IEEE0,
-				      MDIO_COMBO_IEEE0_MII_CONTROL,
-				      &mii_control);
-
-		CL45_WR_OVER_CL22(bp, port,
-				      params->phy_addr,
-				      MDIO_REG_BANK_COMBO_IEEE0,
-				      MDIO_COMBO_IEEE0_MII_CONTROL,
-				      (mii_control |
-				       MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK));
+		bnx2x_cl45_read(bp, phy, 5,
+				(MDIO_REG_BANK_COMBO_IEEE0 +
+				(MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
+				&mii_ctrl);
+		bnx2x_cl45_write(bp, phy, 5,
+				 (MDIO_REG_BANK_COMBO_IEEE0 +
+				 (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
+				 mii_ctrl |
+				 MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK);
 	}
 }
 
-
-static void bnx2x_ext_phy_loopback(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 ext_phy_addr;
-	u32 ext_phy_type;
-
-	if (params->switch_cfg == SWITCH_CFG_10G) {
-		ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-		ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-		/* CL37 Autoneg Enabled */
-		switch (ext_phy_type) {
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
-			DP(NETIF_MSG_LINK,
-				"ext_phy_loopback: We should not get here\n");
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
-			DP(NETIF_MSG_LINK, "ext_phy_loopback: 8705\n");
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-			DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n");
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-			DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n");
-			bnx2x_cl45_write(bp, params->port, ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_CTRL,
-				       0x0001);
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-			/* SFX7101_XGXS_TEST1 */
-			bnx2x_cl45_write(bp, params->port, ext_phy_type,
-				       ext_phy_addr,
-				       MDIO_XS_DEVAD,
-				       MDIO_XS_SFX7101_XGXS_TEST1,
-				       0x100);
-			DP(NETIF_MSG_LINK,
-				"ext_phy_loopback: set ext phy loopback\n");
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-
-			break;
-		} /* switch external PHY type */
-	} else {
-		/* serdes */
-		ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
-		ext_phy_addr = (params->ext_phy_config  &
-		PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK)
-		>> PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT;
-	}
-}
-
-
 /*
  *------------------------------------------------------------------------
  * bnx2x_override_led_value -
  *
- * Override the led value of the requsted led
+ * Override the led value of the requested led
  *
  *------------------------------------------------------------------------
  */
@@ -5785,19 +2653,28 @@
 }
 
 
-u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed)
+u8 bnx2x_set_led(struct link_params *params,
+		 struct link_vars *vars, u8 mode, u32 speed)
 {
 	u8 port = params->port;
 	u16 hw_led_mode = params->hw_led_mode;
-	u8 rc = 0;
+	u8 rc = 0, phy_idx;
 	u32 tmp;
 	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
 	struct bnx2x *bp = params->bp;
 	DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
 	DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
 		 speed, hw_led_mode);
+	/* In case */
+	for (phy_idx = EXT_PHY1; phy_idx < MAX_PHYS; phy_idx++) {
+		if (params->phy[phy_idx].set_link_led) {
+			params->phy[phy_idx].set_link_led(
+				&params->phy[phy_idx], params, mode);
+		}
+	}
+
 	switch (mode) {
+	case LED_MODE_FRONT_PANEL_OFF:
 	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,
@@ -5808,7 +2685,18 @@
 		break;
 
 	case LED_MODE_OPER:
-		if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
+		/**
+		 * 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 (SINGLE_MEDIA_DIRECT(params)) {
+			/**
+			* 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 {
@@ -5853,112 +2741,4135 @@
 
 }
 
-u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
+/**
+ * This function comes to reflect the actual link state read DIRECTLY from the
+ * HW
+ */
+u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
+		   u8 is_serdes)
 {
 	struct bnx2x *bp = params->bp;
-	u16 gp_status = 0;
+	u16 gp_status = 0, phy_index = 0;
+	u8 ext_phy_link_up = 0, serdes_phy_type;
+	struct link_vars temp_vars;
 
-	CL45_RD_OVER_CL22(bp, params->port,
-			      params->phy_addr,
+	CL45_RD_OVER_CL22(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) &&
-	    bnx2x_ext_phy_is_link_up(params, vars, 1))
-		return 0;
+	if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
+		return -ESRCH;
 
+	switch (params->num_phys) {
+	case 1:
+		/* No external PHY */
+		return 0;
+	case 2:
+		ext_phy_link_up = params->phy[EXT_PHY1].read_status(
+			&params->phy[EXT_PHY1],
+			params, &temp_vars);
+		break;
+	case 3: /* Dual Media */
+		for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+		      phy_index++) {
+			serdes_phy_type = ((params->phy[phy_index].media_type ==
+					    ETH_PHY_SFP_FIBER) ||
+					   (params->phy[phy_index].media_type ==
+					    ETH_PHY_XFP_FIBER));
+
+			if (is_serdes != serdes_phy_type)
+				continue;
+			if (params->phy[phy_index].read_status) {
+				ext_phy_link_up |=
+					params->phy[phy_index].read_status(
+						&params->phy[phy_index],
+						params, &temp_vars);
+			}
+		}
+		break;
+	}
+	if (ext_phy_link_up)
+		return 0;
 	return -ESRCH;
 }
 
 static u8 bnx2x_link_initialize(struct link_params *params,
-			      struct link_vars *vars)
+				struct link_vars *vars)
+{
+	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
+	*/
+	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.
+	 */
+
+	if (params->phy[INT_PHY].config_init)
+		params->phy[INT_PHY].config_init(
+			&params->phy[INT_PHY],
+			params, vars);
+
+	/* init ext phy and enable link state int */
+	non_ext_phy = (SINGLE_MEDIA_DIRECT(params) ||
+		       (params->loopback_mode == LOOPBACK_XGXS));
+
+	if (non_ext_phy ||
+	    (params->phy[EXT_PHY1].flags & FLAGS_INIT_XGXS_FIRST) ||
+	    (params->loopback_mode == LOOPBACK_EXT_PHY)) {
+		struct bnx2x_phy *phy = &params->phy[INT_PHY];
+		if (vars->line_speed == SPEED_AUTO_NEG)
+			bnx2x_set_parallel_detection(phy, params);
+		bnx2x_init_internal_phy(phy, params, vars);
+	}
+
+	/* Init external phy*/
+	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");
+				continue;
+			}
+			params->phy[phy_index].config_init(
+				&params->phy[phy_index],
+				params, vars);
+		}
+
+	/* Reset the interrupt indication after phy was initialized */
+	bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 +
+		       params->port*4,
+		       (NIG_STATUS_XGXS0_LINK10G |
+			NIG_STATUS_XGXS0_LINK_STATUS |
+			NIG_STATUS_SERDES0_LINK_STATUS |
+			NIG_MASK_MI_INT));
+	return rc;
+}
+
+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)));
+}
+
+static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
+					struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u8 gpio_port;
+	/* HW reset */
+	if (CHIP_IS_E2(bp))
+		gpio_port = BP_PATH(bp);
+	else
+		gpio_port = params->port;
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+			    MISC_REGISTERS_GPIO_OUTPUT_LOW,
+			    gpio_port);
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+			    MISC_REGISTERS_GPIO_OUTPUT_LOW,
+			    gpio_port);
+	DP(NETIF_MSG_LINK, "reset external PHY\n");
+}
+
+static u8 bnx2x_update_link_down(struct link_params *params,
+			       struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u8 port = params->port;
+
+	DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
+	bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
+
+	/* indicate no mac active */
+	vars->mac_type = MAC_TYPE_NONE;
+
+	/* update shared memory */
+	vars->link_status = 0;
+	vars->line_speed = 0;
+	bnx2x_update_mng(params, vars->link_status);
+
+	/* activate nig drain */
+	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
+
+	/* disable emac */
+	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+
+	msleep(10);
+
+	/* reset BigMac */
+	bnx2x_bmac_rx_disable(bp, params->port);
+	REG_WR(bp, GRCBASE_MISC +
+		   MISC_REGISTERS_RESET_REG_2_CLEAR,
+		   (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+	return 0;
+}
+
+static u8 bnx2x_update_link_up(struct link_params *params,
+			     struct link_vars *vars,
+			     u8 link_10g)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
 	u8 rc = 0;
-	u8 non_ext_phy;
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
 
-	/* Activate the external PHY */
-	bnx2x_ext_phy_reset(params, vars);
+	vars->link_status |= LINK_STATUS_LINK_UP;
 
-	bnx2x_set_aer_mmd(params, vars);
+	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+		vars->link_status |=
+			LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
 
-	if (vars->phy_flags & PHY_XGXS_FLAG)
-		bnx2x_set_master_ln(params);
+	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
+		vars->link_status |=
+			LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
 
-	rc = bnx2x_reset_unicore(params);
-	/* reset the SerDes and wait for reset bit return low */
-	if (rc != 0)
-		return rc;
+	if (link_10g) {
+		bnx2x_bmac_enable(params, vars, 0);
+		bnx2x_set_led(params, vars,
+			      LED_MODE_OPER, SPEED_10000);
+	} else {
+		rc = bnx2x_emac_program(params, vars);
 
-	bnx2x_set_aer_mmd(params, vars);
+		bnx2x_emac_enable(params, vars, 0);
 
-	/* setting the masterLn_def again after the reset */
-	if (vars->phy_flags & PHY_XGXS_FLAG) {
-		bnx2x_set_master_ln(params);
-		bnx2x_set_swap_lanes(params);
+		/* AN complete? */
+		if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
+		    && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
+		    SINGLE_MEDIA_DIRECT(params))
+			bnx2x_set_gmii_tx_driver(params);
 	}
 
-	if (vars->phy_flags & PHY_XGXS_FLAG) {
-		if ((params->req_line_speed &&
-		    ((params->req_line_speed == SPEED_100) ||
-		     (params->req_line_speed == SPEED_10))) ||
-		    (!params->req_line_speed &&
-		     (params->speed_cap_mask >=
-		       PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
-		     (params->speed_cap_mask <
-		       PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
-		     ))  {
-			vars->phy_flags |= PHY_SGMII_FLAG;
+	/* PBF - link up */
+	if (!(CHIP_IS_E2(bp)))
+		rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
+				       vars->line_speed);
+
+	/* disable drain */
+	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
+
+	/* update shared memory */
+	bnx2x_update_mng(params, vars->link_status);
+	msleep(20);
+	return rc;
+}
+/**
+ * The bnx2x_link_update function should be called upon link
+ * interrupt.
+ * Link is considered up as follows:
+ * - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs
+ *   to be up
+ * - SINGLE_MEDIA - The link between the 577xx and the external
+ *   phy (XGXS) need to up as well as the external link of the
+ *   phy (PHY_EXT1)
+ * - DUAL_MEDIA - The link between the 577xx and the first
+ *   external phy needs to be up, and at least one of the 2
+ *   external phy link must be up.
+ */
+u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	struct link_vars phy_vars[MAX_PHYS];
+	u8 port = params->port;
+	u8 link_10g, phy_index;
+	u8 ext_phy_link_up = 0, cur_link_up, rc = 0;
+	u8 is_mi_int = 0;
+	u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
+	u8 active_external_phy = INT_PHY;
+	vars->link_status = 0;
+	for (phy_index = INT_PHY; phy_index < params->num_phys;
+	      phy_index++) {
+		phy_vars[phy_index].flow_ctrl = 0;
+		phy_vars[phy_index].link_status = 0;
+		phy_vars[phy_index].line_speed = 0;
+		phy_vars[phy_index].duplex = DUPLEX_FULL;
+		phy_vars[phy_index].phy_link_up = 0;
+		phy_vars[phy_index].link_up = 0;
+	}
+
+	DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
+		 port, (vars->phy_flags & PHY_XGXS_FLAG),
+		 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
+
+	is_mi_int = (u8)(REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT +
+				    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));
+
+	DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
+	  REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
+	  REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
+
+	/* 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
+	*/
+	for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+	      phy_index++) {
+		struct bnx2x_phy *phy = &params->phy[phy_index];
+		if (!phy->read_status)
+			continue;
+		/* Read link status and params of this ext phy */
+		cur_link_up = phy->read_status(phy, params,
+					       &phy_vars[phy_index]);
+		if (cur_link_up) {
+			DP(NETIF_MSG_LINK, "phy in index %d link is up\n",
+				   phy_index);
 		} else {
-			vars->phy_flags &= ~PHY_SGMII_FLAG;
+			DP(NETIF_MSG_LINK, "phy in index %d link is down\n",
+				   phy_index);
+			continue;
+		}
+
+		if (!ext_phy_link_up) {
+			ext_phy_link_up = 1;
+			active_external_phy = phy_index;
+		} else {
+			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,
+			 * hence its link is expected to be down
+			 * - 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);
+				ext_phy_link_up = 0;
+				break;
+			}
 		}
 	}
-	/* In case of external phy existance, 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->req_line_speed;
+	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
+	*/
+	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
+	 * to the vars. The ext_phy_line_speed is needed to check if the
+	 * speed is different between the internal phy and external phy.
+	 * This case may be result of intermediate link speed change.
+	 */
+	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;
 
-	bnx2x_calc_ieee_aneg_adv(params, &vars->ieee_fc);
+		/**
+		 * if active_external_phy is first PHY and link is up - disable
+		 * disable TX on second external PHY
+		 */
+		if (active_external_phy == EXT_PHY1) {
+			if (params->phy[EXT_PHY2].phy_specific_func) {
+				DP(NETIF_MSG_LINK, "Disabling TX on"
+						   " EXT_PHY2\n");
+				params->phy[EXT_PHY2].phy_specific_func(
+					&params->phy[EXT_PHY2],
+					params, DISABLE_TX);
+			}
+		}
 
-	/* init ext phy and enable link state int */
-	non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
-		       (params->loopback_mode == LOOPBACK_XGXS_10));
-
-	if (non_ext_phy ||
-	    (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
-	    (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) ||
-	    (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) ||
-	    (params->loopback_mode == LOOPBACK_EXT_PHY)) {
-		if (params->req_line_speed == SPEED_AUTO_NEG)
-			bnx2x_set_parallel_detection(params, vars->phy_flags);
-		bnx2x_init_internal_phy(params, vars, non_ext_phy);
+		ext_phy_line_speed = phy_vars[active_external_phy].line_speed;
+		vars->duplex = phy_vars[active_external_phy].duplex;
+		if (params->phy[active_external_phy].supported &
+		    SUPPORTED_FIBRE)
+			vars->link_status |= LINK_STATUS_SERDES_LINK;
+		DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
+			   active_external_phy);
 	}
 
-	if (!non_ext_phy)
-		rc |= bnx2x_ext_phy_init(params, vars);
+	for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+	      phy_index++) {
+		if (params->phy[phy_index].flags &
+		    FLAGS_REARM_LATCH_SIGNAL) {
+			bnx2x_rearm_latch_signal(bp, port,
+						 phy_index ==
+						 active_external_phy);
+			break;
+		}
+	}
+	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
+	 */
 
-	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));
+	if (vars->phy_link_up) {
+		if (!(SINGLE_MEDIA_DIRECT(params)) && ext_phy_link_up &&
+		    (ext_phy_line_speed != vars->line_speed)) {
+			DP(NETIF_MSG_LINK, "Internal link speed %d is"
+				   " different than the external"
+				   " link speed %d\n", vars->line_speed,
+				   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);
+			msleep(1);
+		}
+	}
+
+	/* anything 10 and over uses the bmac */
+	link_10g = ((vars->line_speed == SPEED_10000) ||
+		    (vars->line_speed == SPEED_12000) ||
+		    (vars->line_speed == SPEED_12500) ||
+		    (vars->line_speed == SPEED_13000) ||
+		    (vars->line_speed == SPEED_15000) ||
+		    (vars->line_speed == SPEED_16000));
+
+	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
+	*/
+	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,
+			   vars->phy_link_up,
+			   params->phy[EXT_PHY1].flags &
+			   FLAGS_INIT_XGXS_FIRST);
+		if (!(params->phy[EXT_PHY1].flags &
+		      FLAGS_INIT_XGXS_FIRST)
+		    && ext_phy_link_up && !vars->phy_link_up) {
+			vars->line_speed = ext_phy_line_speed;
+			if (vars->line_speed < SPEED_1000)
+				vars->phy_flags |= PHY_SGMII_FLAG;
+			else
+				vars->phy_flags &= ~PHY_SGMII_FLAG;
+			bnx2x_init_internal_phy(&params->phy[INT_PHY],
+						params,
+						vars);
+		}
+	}
+	/**
+	 *  Link is up only if both local phy and external phy (in case of
+	 *  non-direct board) are up
+	 */
+	vars->link_up = (vars->phy_link_up &&
+			 (ext_phy_link_up ||
+			  SINGLE_MEDIA_DIRECT(params)));
+
+	if (vars->link_up)
+		rc = bnx2x_update_link_up(params, vars, link_10g);
+	else
+		rc = bnx2x_update_link_down(params, vars);
 
 	return rc;
+}
+
+
+/*****************************************************************************/
+/*			    External Phy section			     */
+/*****************************************************************************/
+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);
+	msleep(1);
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
+}
+
+static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
+				      u32 spirom_ver, u32 ver_addr)
+{
+	DP(NETIF_MSG_LINK, "FW version 0x%x:0x%x for port %d\n",
+		 (u16)(spirom_ver>>16), (u16)spirom_ver, port);
+
+	if (ver_addr)
+		REG_WR(bp, ver_addr, spirom_ver);
+}
+
+static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp,
+				      struct bnx2x_phy *phy,
+				      u8 port)
+{
+	u16 fw_ver1, fw_ver2;
+
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+		      MDIO_PMA_REG_ROM_VER1, &fw_ver1);
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+		      MDIO_PMA_REG_ROM_VER2, &fw_ver2);
+	bnx2x_save_spirom_version(bp, port, (u32)(fw_ver1<<16 | fw_ver2),
+				  phy->ver_addr);
+}
+
+static void bnx2x_ext_phy_set_pause(struct link_params *params,
+				    struct bnx2x_phy *phy,
+				    struct link_vars *vars)
+{
+	u16 val;
+	struct bnx2x *bp = params->bp;
+	/* read modify write pause advertizing */
+	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
+
+	val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
+
+	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+	if ((vars->ieee_fc &
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
+		val |=  MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
+	}
+	if ((vars->ieee_fc &
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
+		val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
+	}
+	DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val);
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
+}
+
+static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
+				   struct link_params *params,
+				   struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u16 ld_pause;		/* local */
+	u16 lp_pause;		/* link partner */
+	u16 pause_result;
+	u8 ret = 0;
+	/* read twice */
+
+	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+
+	if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+		vars->flow_ctrl = phy->req_flow_ctrl;
+	else if (phy->req_line_speed != SPEED_AUTO_NEG)
+		vars->flow_ctrl = params->req_fc_auto_adv;
+	else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
+		ret = 1;
+		bnx2x_cl45_read(bp, phy,
+			      MDIO_AN_DEVAD,
+			      MDIO_AN_REG_ADV_PAUSE, &ld_pause);
+		bnx2x_cl45_read(bp, phy,
+			      MDIO_AN_DEVAD,
+			      MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
+		pause_result = (ld_pause &
+				MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
+		pause_result |= (lp_pause &
+				 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
+		DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
+		   pause_result);
+		bnx2x_pause_resolve(vars, pause_result);
+	}
+	return ret;
+}
+
+static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp,
+				       struct bnx2x_phy *phy,
+				       struct link_vars *vars)
+{
+	u16 val;
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD,
+			MDIO_AN_REG_STATUS, &val);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD,
+			MDIO_AN_REG_STATUS, &val);
+	if (val & (1<<5))
+		vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+	if ((val & (1<<0)) == 0)
+		vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED;
+}
+
+/******************************************************************/
+/*		common BCM8073/BCM8727 PHY SECTION		  */
+/******************************************************************/
+static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy,
+				  struct link_params *params,
+				  struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	if (phy->req_line_speed == SPEED_10 ||
+	    phy->req_line_speed == SPEED_100) {
+		vars->flow_ctrl = phy->req_flow_ctrl;
+		return;
+	}
+
+	if (bnx2x_ext_phy_resolve_fc(phy, params, vars) &&
+	    (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE)) {
+		u16 pause_result;
+		u16 ld_pause;		/* local */
+		u16 lp_pause;		/* link partner */
+		bnx2x_cl45_read(bp, phy,
+				MDIO_AN_DEVAD,
+				MDIO_AN_REG_CL37_FC_LD, &ld_pause);
+
+		bnx2x_cl45_read(bp, phy,
+				MDIO_AN_DEVAD,
+				MDIO_AN_REG_CL37_FC_LP, &lp_pause);
+		pause_result = (ld_pause &
+				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
+		pause_result |= (lp_pause &
+				 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
+
+		bnx2x_pause_resolve(vars, pause_result);
+		DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
+			   pause_result);
+	}
+}
+
+static void bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
+					      struct bnx2x_phy *phy,
+					      u8 port)
+{
+	/* Boot port from external ROM  */
+	/* EDC grst */
+	bnx2x_cl45_write(bp, phy,
+		       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);
+
+	bnx2x_cl45_write(bp, phy,
+		       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);
+
+	/* 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);
+
+	/* wait for 120ms for code download via SPI port */
+	msleep(120);
+
+	/* Clear ser_boot_ctl bit */
+	bnx2x_cl45_write(bp, phy,
+		       MDIO_PMA_DEVAD,
+		       MDIO_PMA_REG_MISC_CTRL1, 0x0000);
+	bnx2x_save_bcm_spirom_ver(bp, phy, port);
+}
+
+static void bnx2x_8073_set_xaui_low_power_mode(struct bnx2x *bp,
+					       struct bnx2x_phy *phy)
+{
+	u16 val;
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val);
+
+	if (val == 0) {
+		/* Mustn't set low power mode in 8073 A0 */
+		return;
+	}
+
+	/* Disable PLL sequencer (use read-modify-write to clear bit 13) */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val);
+	val &= ~(1<<13);
+	bnx2x_cl45_write(bp, phy,
+		       MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
+
+	/* PLL controls */
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805E, 0x1077);
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805D, 0x0000);
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805C, 0x030B);
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805B, 0x1240);
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805A, 0x2490);
+
+	/* Tx Controls */
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A7, 0x0C74);
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A6, 0x9041);
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A5, 0x4640);
+
+	/* Rx Controls */
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FE, 0x01C4);
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FD, 0x9249);
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FC, 0x2015);
+
+	/* Enable PLL sequencer  (use read-modify-write to set bit 13) */
+	bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val);
+	val |= (1<<13);
+	bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
+}
+
+/******************************************************************/
+/*			BCM8073 PHY SECTION			  */
+/******************************************************************/
+static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
+{
+	/* This is only required for 8073A1, version 102 only */
+	u16 val;
+
+	/* Read 8073 HW revision*/
+	bnx2x_cl45_read(bp, phy,
+		      MDIO_PMA_DEVAD,
+		      MDIO_PMA_REG_8073_CHIP_REV, &val);
+
+	if (val != 1) {
+		/* No need to workaround in 8073 A1 */
+		return 0;
+	}
+
+	bnx2x_cl45_read(bp, phy,
+		      MDIO_PMA_DEVAD,
+		      MDIO_PMA_REG_ROM_VER2, &val);
+
+	/* SNR should be applied only for version 0x102 */
+	if (val != 0x102)
+		return 0;
+
+	return 1;
+}
+
+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);
+
+	if (val > 0) {
+		/* No need to workaround in 8073 A1 */
+		return 0;
+	}
+	/* XAUI workaround in 8073 A0: */
+
+	/* 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). */
+		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.*/
+			for (cnt1 = 0; cnt1 < 1000; cnt1++) {
+				bnx2x_cl45_read(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8073_XAUI_WA, &val);
+				if (val & (1<<15)) {
+					DP(NETIF_MSG_LINK,
+					  "XAUI workaround has completed\n");
+					return 0;
+				 }
+				 msleep(3);
+			}
+			break;
+		}
+		msleep(3);
+	}
+	DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
+	return -EINVAL;
+}
+
+static void bnx2x_807x_force_10G(struct bnx2x *bp, struct bnx2x_phy *phy)
+{
+	/* Force KR or KX */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0x000b);
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0000);
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
+}
+
+static void bnx2x_8073_set_pause_cl37(struct link_params *params,
+				      struct bnx2x_phy *phy,
+				      struct link_vars *vars)
+{
+	u16 cl37_val;
+	struct bnx2x *bp = params->bp;
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &cl37_val);
+
+	cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+	if ((vars->ieee_fc &
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
+		cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
+	}
+	if ((vars->ieee_fc &
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
+		cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+	}
+	if ((vars->ieee_fc &
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
+		cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+	}
+	DP(NETIF_MSG_LINK,
+		 "Ext phy AN advertize cl37 0x%x\n", cl37_val);
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, cl37_val);
+	msleep(500);
+}
+
+static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val = 0, tmp1;
+	u8 gpio_port;
+	DP(NETIF_MSG_LINK, "Init 8073\n");
+
+	if (CHIP_IS_E2(bp))
+		gpio_port = BP_PATH(bp);
+	else
+		gpio_port = params->port;
+	/* Restore normal power mode*/
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
+
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
+
+	/* enable LASI */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL, (1<<2));
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,  0x0004);
+
+	bnx2x_8073_set_pause_cl37(params, phy, vars);
+
+	bnx2x_8073_set_xaui_low_power_mode(bp, phy);
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
+
+	DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
+
+	/* Enable CL37 BAM */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD,
+			MDIO_AN_REG_8073_BAM, &val);
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_AN_DEVAD,
+			 MDIO_AN_REG_8073_BAM, val | 1);
+
+	if (params->loopback_mode == LOOPBACK_EXT) {
+		bnx2x_807x_force_10G(bp, phy);
+		DP(NETIF_MSG_LINK, "Forced speed 10G on 807X\n");
+		return 0;
+	} else {
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0002);
+	}
+	if (phy->req_line_speed != SPEED_AUTO_NEG) {
+		if (phy->req_line_speed == SPEED_10000) {
+			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 */
+		} else
+			val = (1<<5);
+	} else {
+		val = 0;
+		if (phy->speed_cap_mask &
+			PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
+			val |= (1<<7);
+
+		/* 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))
+			val |= (1<<5);
+		DP(NETIF_MSG_LINK, "807x autoneg val = 0x%x\n", val);
+	}
+
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, val);
+	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, &tmp1);
+
+	if (((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
+	     (phy->req_line_speed == SPEED_AUTO_NEG)) ||
+	    (phy->req_line_speed == SPEED_2500)) {
+		u16 phy_ver;
+		/* Allow 2.5G for A1 and above */
+		bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV,
+				&phy_ver);
+		DP(NETIF_MSG_LINK, "Add 2.5G\n");
+		if (phy_ver > 0)
+			tmp1 |= 1;
+		else
+			tmp1 &= 0xfffe;
+	} else {
+		DP(NETIF_MSG_LINK, "Disable 2.5G\n");
+		tmp1 &= 0xfffe;
+	}
+
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, tmp1);
+	/* Add support for CL37 (passive mode) II */
+
+	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &tmp1);
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD,
+			 (tmp1 | ((phy->req_duplex == DUPLEX_FULL) ?
+				  0x20 : 0x40)));
+
+	/* 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*/
+	if (bnx2x_8073_is_snr_needed(bp, phy))
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN,
+				 0xFB0C);
+
+	/* Enable FEC (Forware Error Correction) Request in the AN */
+	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, &tmp1);
+	tmp1 |= (1<<15);
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, tmp1);
+
+	bnx2x_ext_phy_set_pause(params, phy, vars);
+
+	/* Restart autoneg */
+	msleep(500);
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
+	DP(NETIF_MSG_LINK, "807x Autoneg Restart: Advertise 1G=%x, 10G=%x\n",
+		   ((val & (1<<5)) > 0), ((val & (1<<7)) > 0));
+	return 0;
+}
+
+static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u8 link_up = 0;
+	u16 val1, val2;
+	u16 link_status = 0;
+	u16 an1000_status = 0;
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+
+	DP(NETIF_MSG_LINK, "8703 LASI status 0x%x\n", val1);
+
+	/* clear the interrupt LASI status register */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val1);
+	DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n", val2, val1);
+	/* Clear MSG-OUT */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
+
+	/* Check the LASI */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
+
+	DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
+
+	/* Check the link status */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
+	DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
+	link_up = ((val1 & 4) == 4);
+	DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
+
+	if (link_up &&
+	     ((phy->req_line_speed != SPEED_10000))) {
+		if (bnx2x_8073_xaui_wa(bp, phy) != 0)
+			return 0;
+	}
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
+
+	/* Check the link status on 1.1.2 */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
+	DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
+		   "an_link_status=0x%x\n", val2, val1, an1000_status);
+
+	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 */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_PLL_BANDWIDTH,
+				 0x26BC);
+
+		/* Change CDR Bandwidth in EDC register */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CDR_BANDWIDTH,
+				 0x0333);
+	}
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
+			&link_status);
+
+	/* 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<<1)) && (!(link_status & (1<<14)))) {
+		link_up = 1;
+		vars->line_speed = SPEED_2500;
+		DP(NETIF_MSG_LINK, "port %x: External link up in 2.5G\n",
+			   params->port);
+	} else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
+		link_up = 1;
+		vars->line_speed = SPEED_1000;
+		DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n",
+			   params->port);
+	} else {
+		link_up = 0;
+		DP(NETIF_MSG_LINK, "port %x: External link is down\n",
+			   params->port);
+	}
+
+	if (link_up) {
+		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
+		bnx2x_8073_resolve_fc(phy, params, vars);
+	}
+	return link_up;
+}
+
+static void bnx2x_8073_link_reset(struct bnx2x_phy *phy,
+				  struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u8 gpio_port;
+	if (CHIP_IS_E2(bp))
+		gpio_port = BP_PATH(bp);
+	else
+		gpio_port = params->port;
+	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);
+}
+
+/******************************************************************/
+/*			BCM8705 PHY SECTION			  */
+/******************************************************************/
+static u8 bnx2x_8705_config_init(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "init 8705\n");
+	/* Restore normal power mode*/
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+	/* HW reset */
+	bnx2x_ext_phy_hw_reset(bp, params->port);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
+	bnx2x_wait_reset_complete(bp, phy);
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL, 0x8288);
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, 0x7fbf);
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CMU_PLL_BYPASS, 0x0100);
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_CNTL, 0x1);
+	/* BCM8705 doesn't have microcode, hence the 0 */
+	bnx2x_save_spirom_version(bp, params->port, params->shmem_base, 0);
+	return 0;
+}
+
+static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	u8 link_up = 0;
+	u16 val1, rx_sd;
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "read status 8705\n");
+	bnx2x_cl45_read(bp, phy,
+		      MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
+	DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
+
+	bnx2x_cl45_read(bp, phy,
+		      MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
+	DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
+
+	bnx2x_cl45_read(bp, phy,
+		      MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
+
+	bnx2x_cl45_read(bp, phy,
+		      MDIO_PMA_DEVAD, 0xc809, &val1);
+	bnx2x_cl45_read(bp, phy,
+		      MDIO_PMA_DEVAD, 0xc809, &val1);
+
+	DP(NETIF_MSG_LINK, "8705 1.c809 val=0x%x\n", val1);
+	link_up = ((rx_sd & 0x1) && (val1 & (1<<9)) && ((val1 & (1<<8)) == 0));
+	if (link_up) {
+		vars->line_speed = SPEED_10000;
+		bnx2x_ext_phy_resolve_fc(phy, params, vars);
+	}
+	return link_up;
+}
+
+/******************************************************************/
+/*			SFP+ module Section			  */
+/******************************************************************/
+static void bnx2x_sfp_set_transmitter(struct bnx2x *bp,
+				      struct bnx2x_phy *phy,
+				      u8 port,
+				      u8 tx_en)
+{
+	u16 val;
+
+	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);
+
+	if (tx_en)
+		val &= ~(1<<15);
+	else
+		val |= (1<<15);
+
+	bnx2x_cl45_write(bp, phy,
+		       MDIO_PMA_DEVAD,
+		       MDIO_PMA_REG_PHY_IDENTIFIER,
+		       val);
+}
+
+static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+					    struct link_params *params,
+					  u16 addr, u8 byte_cnt, u8 *o_buf)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val = 0;
+	u16 i;
+	if (byte_cnt > 16) {
+		DP(NETIF_MSG_LINK, "Reading from eeprom is"
+			    " is limited to 0xf\n");
+		return -EINVAL;
+	}
+	/* 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));
+
+	/* Set the read command address */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
+		       addr);
+
+	/* Activate read command */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
+		       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);
+		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
+		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
+			break;
+		udelay(5);
+	}
+
+	if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
+		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
+		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;
+	}
+
+	/* 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);
+		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);
+		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
+		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
+			return 0;;
+		msleep(1);
+	}
+	return -EINVAL;
+}
+
+static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+					    struct link_params *params,
+					  u16 addr, u8 byte_cnt, u8 *o_buf)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val, i;
+
+	if (byte_cnt > 16) {
+		DP(NETIF_MSG_LINK, "Reading from eeprom is"
+			    " is limited to 0xf\n");
+		return -EINVAL;
+	}
+
+	/* 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);
+
+	/* 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));
+
+	/* Set the read command address */
+	bnx2x_cl45_write(bp, phy,
+		       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);
+
+	/* 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 */
+	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);
+		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
+		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
+			break;
+		udelay(5);
+	}
+
+	if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
+		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
+		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;
+	}
+
+	/* 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);
+		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);
+		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
+		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
+			return 0;;
+		msleep(1);
+	}
+
+	return -EINVAL;
+}
+
+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);
+	else if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
+		return bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
+						       byte_cnt, o_buf);
+	return -EINVAL;
+}
+
+static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
+			     struct link_params *params,
+				  u16 *edc_mode)
+{
+	struct bnx2x *bp = params->bp;
+	u8 val, check_limiting_mode = 0;
+	*edc_mode = EDC_MODE_LIMITING;
+
+	/* First check for copper cable */
+	if (bnx2x_read_sfp_module_eeprom(phy,
+					 params,
+					 SFP_EEPROM_CON_TYPE_ADDR,
+					 1,
+					 &val) != 0) {
+		DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM\n");
+		return -EINVAL;
+	}
+
+	switch (val) {
+	case SFP_EEPROM_CON_TYPE_VAL_COPPER:
+	{
+		u8 copper_module_type;
+
+		/* 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,
+					       1,
+					       &copper_module_type) !=
+		    0) {
+			DP(NETIF_MSG_LINK,
+				"Failed to read copper-cable-type"
+				" from SFP+ EEPROM\n");
+			return -EINVAL;
+		}
+
+		if (copper_module_type &
+		    SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
+			DP(NETIF_MSG_LINK, "Active Copper cable detected\n");
+			check_limiting_mode = 1;
+		} else if (copper_module_type &
+			SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
+				DP(NETIF_MSG_LINK, "Passive Copper"
+					    " cable detected\n");
+				*edc_mode =
+				      EDC_MODE_PASSIVE_DAC;
+		} else {
+			DP(NETIF_MSG_LINK, "Unknown copper-cable-"
+				     "type 0x%x !!!\n", copper_module_type);
+			return -EINVAL;
+		}
+		break;
+	}
+	case SFP_EEPROM_CON_TYPE_VAL_LC:
+		DP(NETIF_MSG_LINK, "Optic module detected\n");
+		check_limiting_mode = 1;
+		break;
+	default:
+		DP(NETIF_MSG_LINK, "Unable to determine module type 0x%x !!!\n",
+			 val);
+		return -EINVAL;
+	}
+
+	if (check_limiting_mode) {
+		u8 options[SFP_EEPROM_OPTIONS_SIZE];
+		if (bnx2x_read_sfp_module_eeprom(phy,
+						 params,
+						 SFP_EEPROM_OPTIONS_ADDR,
+						 SFP_EEPROM_OPTIONS_SIZE,
+						 options) != 0) {
+			DP(NETIF_MSG_LINK, "Failed to read Option"
+				" field from module EEPROM\n");
+			return -EINVAL;
+		}
+		if ((options[0] & SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK))
+			*edc_mode = EDC_MODE_LINEAR;
+		else
+			*edc_mode = EDC_MODE_LIMITING;
+	}
+	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 */
+static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
+				  struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u32 val, cmd;
+	u32 fw_resp, fw_cmd_param;
+	char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE+1];
+	char vendor_pn[SFP_EEPROM_PART_NO_SIZE+1];
+	phy->flags &= ~FLAGS_SFP_NOT_APPROVED;
+	val = REG_RD(bp, params->shmem_base +
+			 offsetof(struct shmem_region, dev_info.
+				  port_feature_config[params->port].config));
+	if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+	    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT) {
+		DP(NETIF_MSG_LINK, "NOT enforcing module verification\n");
+		return 0;
+	}
+
+	if (params->feature_config_flags &
+	    FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY) {
+		/* Use specific phy request */
+		cmd = DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL;
+	} else if (params->feature_config_flags &
+		   FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY) {
+		/* Use first phy request only in case of non-dual media*/
+		if (DUAL_MEDIA(params)) {
+			DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
+			   "verification\n");
+			return -EINVAL;
+		}
+		cmd = DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL;
+	} else {
+		/* No support in OPT MDL detection */
+		DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
+			  "verification\n");
+		return -EINVAL;
+	}
+
+	fw_cmd_param = FW_PARAM_SET(phy->addr, phy->type, phy->mdio_ctrl);
+	fw_resp = bnx2x_fw_command(bp, cmd, fw_cmd_param);
+	if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) {
+		DP(NETIF_MSG_LINK, "Approved module\n");
+		return 0;
+	}
+
+	/* 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))
+		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))
+		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);
+	phy->flags |= FLAGS_SFP_NOT_APPROVED;
+	return -EINVAL;
+}
+
+static u8 bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
+						struct link_params *params)
+
+{
+	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 ) */
+	for (timeout = 0; timeout < 60; timeout++) {
+		if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
+		    == 0) {
+			DP(NETIF_MSG_LINK, "SFP+ module initialization "
+				     "took %d ms\n", timeout * 5);
+			return 0;
+		}
+		msleep(5);
+	}
+	return -EINVAL;
+}
+
+static void bnx2x_8727_power_module(struct bnx2x *bp,
+				    struct bnx2x_phy *phy,
+				    u8 is_power_up) {
+	/* 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
+	 * 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
+	 */
+	if (phy->flags & FLAGS_NOC)
+		return;
+	if (!(phy->flags &
+	      FLAGS_NOC) && is_power_up)
+		val = (1<<4);
+	else
+		/*
+		 * Set GPIO control to OUTPUT, and set the power bit
+		 * to according to the is_power_up
+		 */
+		val = ((!(is_power_up)) << 1);
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_8727_GPIO_CTRL,
+			 val);
+}
+
+static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
+				       struct bnx2x_phy *phy,
+				       u16 edc_mode)
+{
+	u16 cur_limiting_mode;
+
+	bnx2x_cl45_read(bp, phy,
+		      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");
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_ROM_VER2,
+				 EDC_MODE_LIMITING);
+	} else { /* LRM mode ( default )*/
+
+		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 )*/
+		if (cur_limiting_mode != EDC_MODE_LIMITING)
+			return 0;
+
+		bnx2x_cl45_write(bp, phy,
+			       MDIO_PMA_DEVAD,
+			       MDIO_PMA_REG_LRM_MODE,
+			       0);
+		bnx2x_cl45_write(bp, phy,
+			       MDIO_PMA_DEVAD,
+			       MDIO_PMA_REG_ROM_VER2,
+			       0x128);
+		bnx2x_cl45_write(bp, phy,
+			       MDIO_PMA_DEVAD,
+			       MDIO_PMA_REG_MISC_CTRL0,
+			       0x4008);
+		bnx2x_cl45_write(bp, phy,
+			       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 phy_identifier;
+	u16 rom_ver2_val;
+	bnx2x_cl45_read(bp, phy,
+		       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)));
+
+	bnx2x_cl45_read(bp, phy,
+		      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));
+
+	bnx2x_cl45_write(bp, phy,
+		       MDIO_PMA_DEVAD,
+		       MDIO_PMA_REG_PHY_IDENTIFIER,
+		       (phy_identifier | (1<<9)));
+
+	return 0;
+}
+
+static void bnx2x_8727_specific_func(struct bnx2x_phy *phy,
+				     struct link_params *params,
+				     u32 action)
+{
+	struct bnx2x *bp = params->bp;
+
+	switch (action) {
+	case DISABLE_TX:
+		bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+		break;
+	case ENABLE_TX:
+		if (!(phy->flags & FLAGS_SFP_NOT_APPROVED))
+			bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
+		break;
+	default:
+		DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n",
+		   action);
+		return;
+	}
+}
+
+static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
+				     struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u16 edc_mode;
+	u8 rc = 0;
+
+	u32 val = REG_RD(bp, params->shmem_base +
+			     offsetof(struct shmem_region, dev_info.
+				     port_feature_config[params->port].config));
+
+	DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
+		 params->port);
+
+	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) {
+		/* 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);
+		if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
+		    ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+		     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) {
+			/* Shutdown SFP+ module */
+			DP(NETIF_MSG_LINK, "Shutdown SFP+ module!!\n");
+			bnx2x_8727_power_module(bp, phy, 0);
+			return rc;
+		}
+	} 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);
+	}
+
+	/* power up the SFP module */
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
+		bnx2x_8727_power_module(bp, phy, 1);
+
+	/* Check and set limiting mode / LRM mode on 8726.
+	On 8727 it is done automatically */
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
+		bnx2x_8726_set_limiting_mode(bp, phy, edc_mode);
+	else
+		bnx2x_8727_set_limiting_mode(bp, phy, edc_mode);
+	/*
+	 * Enable transmit for this module if the module is approved, or
+	 * if unapproved modules should also enable the Tx laser
+	 */
+	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);
+	else
+		bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+
+	return rc;
+}
+
+void bnx2x_handle_module_detect_int(struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	struct bnx2x_phy *phy = &params->phy[EXT_PHY1];
+	u32 gpio_val;
+	u8 port = params->port;
+
+	/* Set valid module led off */
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
+			  MISC_REGISTERS_GPIO_HIGH,
+			  params->port);
+
+	/* Get current gpio val refelecting module plugged in / out*/
+	gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port);
+
+	/* Call the handling function in case module is detected */
+	if (gpio_val == 0) {
+
+		bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
+				   MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
+				   port);
+
+		if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
+			bnx2x_sfp_module_detection(phy, params);
+		else
+			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));
+
+		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 */
+		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);
+	}
+}
+
+/******************************************************************/
+/*		common BCM8706/BCM8726 PHY SECTION		  */
+/******************************************************************/
+static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
+				      struct link_params *params,
+				      struct link_vars *vars)
+{
+	u8 link_up = 0;
+	u16 val1, val2, rx_sd, pcs_status;
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
+	/* Clear RX Alarm*/
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
+	/* clear LASI indication*/
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
+	DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x--> 0x%x\n", val1, val2);
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &pcs_status);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
+
+	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_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1)));
+	if (link_up) {
+		if (val2 & (1<<1))
+			vars->line_speed = SPEED_1000;
+		else
+			vars->line_speed = SPEED_10000;
+		bnx2x_ext_phy_resolve_fc(phy, params, vars);
+	}
+	return link_up;
+}
+
+/******************************************************************/
+/*			BCM8706 PHY SECTION			  */
+/******************************************************************/
+static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	u16 cnt, val;
+	struct bnx2x *bp = params->bp;
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+	/* HW reset */
+	bnx2x_ext_phy_hw_reset(bp, params->port);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
+	bnx2x_wait_reset_complete(bp, phy);
+
+	/* Wait until fw is loaded */
+	for (cnt = 0; cnt < 100; cnt++) {
+		bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &val);
+		if (val)
+			break;
+		msleep(10);
+	}
+	DP(NETIF_MSG_LINK, "XGXS 8706 is initialized after %d ms\n", cnt);
+	if ((params->feature_config_flags &
+	     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
+		u8 i;
+		u16 reg;
+		for (i = 0; i < 4; i++) {
+			reg = MDIO_XS_8706_REG_BANK_RX0 +
+				i*(MDIO_XS_8706_REG_BANK_RX1 -
+				   MDIO_XS_8706_REG_BANK_RX0);
+			bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, reg, &val);
+			/* Clear first 3 bits of the control */
+			val &= ~0x7;
+			/* Set control bits according to configuration */
+			val |= (phy->rx_preemphasis[i] & 0x7);
+			DP(NETIF_MSG_LINK, "Setting RX Equalizer to BCM8706"
+				   " reg 0x%x <-- val 0x%x\n", reg, val);
+			bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, reg, val);
+		}
+	}
+	/* Force speed */
+	if (phy->req_line_speed == SPEED_10000) {
+		DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
+
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_DIGITAL_CTRL, 0x400);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
+	} else {
+		/* Force 1Gbps using autoneg with 1G advertisment */
+
+		/* Allow CL37 through CL73 */
+		DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
+
+		/* Enable Full-Duplex advertisment on CL37 */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, 0x0020);
+		/* Enable CL37 AN */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
+		/* 1G support */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_ADV, (1<<5));
+
+		/* Enable clause 73 AN */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+				 0x0400);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
+				 0x0004);
+	}
+	bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
+	return 0;
+}
+
+static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	return bnx2x_8706_8726_read_status(phy, params, vars);
+}
+
+/******************************************************************/
+/*			BCM8726 PHY SECTION			  */
+/******************************************************************/
+static void bnx2x_8726_config_loopback(struct bnx2x_phy *phy,
+				       struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n");
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0001);
+}
+
+static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy,
+					 struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	/* Need to wait 100ms after reset */
+	msleep(100);
+
+	/* Micro controller re-boot */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x018B);
+
+	/* Set soft reset */
+	bnx2x_cl45_write(bp, phy,
+		       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);
+
+	bnx2x_cl45_write(bp, phy,
+		       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);
+
+	msleep(200);
+	bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
+}
+
+static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val1;
+	u8 link_up = bnx2x_8706_8726_read_status(phy, params, vars);
+	if (link_up) {
+		bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
+				&val1);
+		if (val1 & (1<<15)) {
+			DP(NETIF_MSG_LINK, "Tx is disabled\n");
+			link_up = 0;
+			vars->line_speed = 0;
+		}
+	}
+	return link_up;
+}
+
+
+static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u32 val;
+	u32 swap_val, swap_override, aeu_gpio_mask, offset;
+	DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
+	/* 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_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 */
+	bnx2x_sfp_module_detection(phy, params);
+
+	if (phy->req_line_speed == SPEED_1000) {
+		DP(NETIF_MSG_LINK, "Setting 1G force\n");
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x5);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+				 0x400);
+	} else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
+		   (phy->speed_cap_mask &
+		      PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) &&
+		   ((phy->speed_cap_mask &
+		      PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
+		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
+		DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
+		/* Set Flow control */
+		bnx2x_ext_phy_set_pause(params, phy, vars);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_ADV, 0x20);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, 0x0020);
+		bnx2x_cl45_write(bp, 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 */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x4);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+				 0x400);
+
+	} else { /* Default 10G. Set only LASI control */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
+	}
+
+	/* Set TX PreEmphasis if needed */
+	if ((params->feature_config_flags &
+	     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
+		DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
+			 "TX_CTRL2 0x%x\n",
+			 phy->tx_preemphasis[0],
+			 phy->tx_preemphasis[1]);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_8726_TX_CTRL1,
+				 phy->tx_preemphasis[0]);
+
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_8726_TX_CTRL2,
+				 phy->tx_preemphasis[1]);
+	}
+
+	/* Set GPIO3 to trigger SFP+ module insertion/removal */
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+			    MISC_REGISTERS_GPIO_INPUT_HI_Z, params->port);
+
+	/* The GPIO should be swapped if the swap register is set and active */
+	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+
+	/* Select function upon port-swap configuration */
+	if (params->port == 0) {
+		offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
+		aeu_gpio_mask = (swap_val && swap_override) ?
+			AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 :
+			AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0;
+	} else {
+		offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
+		aeu_gpio_mask = (swap_val && swap_override) ?
+			AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 :
+			AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1;
+	}
+	val = REG_RD(bp, offset);
+	/* add GPIO3 to group */
+	val |= aeu_gpio_mask;
+	REG_WR(bp, offset, val);
+	return 0;
 
 }
 
+static void bnx2x_8726_link_reset(struct bnx2x_phy *phy,
+				  struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "bnx2x_8726_link_reset port %d\n", params->port);
+	/* Set serial boot control for external load */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL, 0x0001);
+}
+
+/******************************************************************/
+/*			BCM8727 PHY SECTION			  */
+/******************************************************************/
+
+static void bnx2x_8727_set_link_led(struct bnx2x_phy *phy,
+				    struct link_params *params, u8 mode)
+{
+	struct bnx2x *bp = params->bp;
+	u16 led_mode_bitmask = 0;
+	u16 gpio_pins_bitmask = 0;
+	u16 val;
+	/* Only NOC flavor requires to set the LED specifically */
+	if (!(phy->flags & FLAGS_NOC))
+		return;
+	switch (mode) {
+	case LED_MODE_FRONT_PANEL_OFF:
+	case LED_MODE_OFF:
+		led_mode_bitmask = 0;
+		gpio_pins_bitmask = 0x03;
+		break;
+	case LED_MODE_ON:
+		led_mode_bitmask = 0;
+		gpio_pins_bitmask = 0x02;
+		break;
+	case LED_MODE_OPER:
+		led_mode_bitmask = 0x60;
+		gpio_pins_bitmask = 0x11;
+		break;
+	}
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_8727_PCS_OPT_CTRL,
+			&val);
+	val &= 0xff8f;
+	val |= led_mode_bitmask;
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_8727_PCS_OPT_CTRL,
+			 val);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_8727_GPIO_CTRL,
+			&val);
+	val &= 0xffe0;
+	val |= gpio_pins_bitmask;
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_8727_GPIO_CTRL,
+			 val);
+}
+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()
+	 */
+	struct bnx2x *bp = params->bp;
+	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+	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);
+}
+
+static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	u16 tmp1, val, mod_abs;
+	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);
+	rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
+	lasi_ctrl_val = 0x0004;
+
+	DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
+	/* enable LASI */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+			 rx_alarm_ctrl_val);
+
+	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) */
+	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'.*/
+	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);
+
+
+	/* Make MOD_ABS give interrupt on change */
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
+			&val);
+	val |= (1<<12);
+	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
+	 */
+	if (!(phy->flags & FLAGS_NOC))
+		val &= 0xff8f; /* Reset bits 4-6 */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL, val);
+
+	bnx2x_8727_power_module(bp, phy, 1);
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
+
+	/* Set option 1G speed */
+	if (phy->req_line_speed == SPEED_1000) {
+		DP(NETIF_MSG_LINK, "Setting 1G force\n");
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
+		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
+		 */
+		if (DUAL_MEDIA(params)) {
+			bnx2x_cl45_read(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8727_PCS_GP, &val);
+			val |= (3<<10);
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8727_PCS_GP, val);
+		}
+	} else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
+		   ((phy->speed_cap_mask &
+		     PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) &&
+		   ((phy->speed_cap_mask &
+		      PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
+		   PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
+
+		DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL, 0);
+		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
+		 */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL,
+				 0x0020);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x0100);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2,
+				 0x0008);
+	}
+
+	/* Set 2-wire transfer rate of SFP+ module EEPROM
+	 * to 100Khz since some DACs(direct attached cables) do
+	 * not work at 400Khz.
+	 */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
+			 0xa001);
+
+	/* Set TX PreEmphasis if needed */
+	if ((params->feature_config_flags &
+	     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
+		DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
+			   phy->tx_preemphasis[0],
+			   phy->tx_preemphasis[1]);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL1,
+				 phy->tx_preemphasis[0]);
+
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL2,
+				 phy->tx_preemphasis[1]);
+	}
+
+	return 0;
+}
+
+static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
+				      struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u16 mod_abs, rx_alarm_status;
+	u32 val = REG_RD(bp, params->shmem_base +
+			     offsetof(struct shmem_region, dev_info.
+				      port_feature_config[params->port].
+				      config));
+	bnx2x_cl45_read(bp, phy,
+		      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'.*/
+		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);
+
+		/* 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);
+
+	} 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) */
+		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);
+
+		/* 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);
+
+
+		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);
+
+		if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
+			bnx2x_sfp_module_detection(phy, params);
+		else
+			DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
+	}
+
+	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 */
+}
+
+static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+
+{
+	struct bnx2x *bp = params->bp;
+	u8 link_up = 0;
+	u16 link_status = 0;
+	u16 rx_alarm_status, lasi_ctrl, val1;
+
+	/* If PHY is not initialized, do not check link status */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
+			&lasi_ctrl);
+	if (!lasi_ctrl)
+		return 0;
+
+	/* Check the LASI */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM,
+			&rx_alarm_status);
+	vars->line_speed = 0;
+	DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS  0x%x\n", rx_alarm_status);
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+
+	DP(NETIF_MSG_LINK, "8727 LASI status 0x%x\n", val1);
+
+	/* Clear MSG-OUT */
+	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
+	 */
+	if (!(phy->flags & FLAGS_NOC) && !(rx_alarm_status & (1<<5))) {
+		/* Check over-current using 8727 GPIO0 input*/
+		bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_GPIO_CTRL,
+				&val1);
+
+		if ((val1 & (1<<8)) == 0) {
+			DP(NETIF_MSG_LINK, "8727 Power fault has been detected"
+				       " on port %d\n", params->port);
+			netdev_err(bp->dev, "Error:  Power fault on Port %d has"
+					    " been detected and the power to "
+					    "that SFP+ module has been removed"
+					    " to prevent failure of the card."
+					    " Please remove the SFP+ module and"
+					    " restart the system to clear this"
+					    " error.\n",
+				   params->port);
+
+			/*
+			 * Disable all RX_ALARMs except for
+			 * mod_abs
+			 */
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_RX_ALARM_CTRL, (1<<5));
+
+			bnx2x_cl45_read(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
+			/* Wait for module_absent_event */
+			val1 |= (1<<8);
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_PHY_IDENTIFIER, val1);
+			/* Clear RX alarm */
+			bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+			return 0;
+		}
+	} /* Over current check */
+
+	/* When module absent bit is set, check module */
+	if (rx_alarm_status & (1<<5)) {
+		bnx2x_8727_handle_mod_abs(phy, params);
+		/* Enable all mod_abs and link detection bits */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+				 ((1<<5) | (1<<2)));
+	}
+	DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n");
+	bnx2x_8727_specific_func(phy, params, ENABLE_TX);
+	/* If transmitter is disabled, ignore false link up indication */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
+	if (val1 & (1<<15)) {
+		DP(NETIF_MSG_LINK, "Tx is disabled\n");
+		return 0;
+	}
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status);
+
+	/* 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;
+	} else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
+		link_up = 1;
+		vars->line_speed = SPEED_1000;
+		DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n",
+			   params->port);
+	} else {
+		link_up = 0;
+		DP(NETIF_MSG_LINK, "port %x: External link is down\n",
+			   params->port);
+	}
+	if (link_up)
+		bnx2x_ext_phy_resolve_fc(phy, params, vars);
+
+	if ((DUAL_MEDIA(params)) &&
+	    (phy->req_line_speed == SPEED_1000)) {
+		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
+		 */
+		if (link_up)
+			val1 &= ~(3<<10);
+		else
+			val1 |= (3<<10);
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_8727_PCS_GP, val1);
+	}
+	return link_up;
+}
+
+static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
+				  struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	/* Disable Transmitter */
+	bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+	/* Clear LASI */
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0);
+
+}
+
+/******************************************************************/
+/*		BCM8481/BCM84823/BCM84833 PHY SECTION	          */
+/******************************************************************/
+static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
+					   struct link_params *params)
+{
+	u16 val, fw_ver1, fw_ver2, cnt;
+	struct bnx2x *bp = params->bp;
+
+	/* 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);
+
+	for (cnt = 0; cnt < 100; cnt++) {
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+		if (val & 1)
+			break;
+		udelay(5);
+	}
+	if (cnt == 100) {
+		DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n");
+		bnx2x_save_spirom_version(bp, params->port, 0,
+					  phy->ver_addr);
+		return;
+	}
+
+
+	/* 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);
+	for (cnt = 0; cnt < 100; cnt++) {
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+		if (val & 1)
+			break;
+		udelay(5);
+	}
+	if (cnt == 100) {
+		DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n");
+		bnx2x_save_spirom_version(bp, params->port, 0,
+					  phy->ver_addr);
+		return;
+	}
+
+	/* lower 16 bits of the register SPI_FW_STATUS */
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
+	/* upper 16 bits of register SPI_FW_STATUS */
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
+
+	bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1,
+				  phy->ver_addr);
+}
+
+static void bnx2x_848xx_set_led(struct bnx2x *bp,
+				struct bnx2x_phy *phy)
+{
+	u16 val;
+
+	/* PHYC_CTL_LED_CTL */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_8481_LINK_SIGNAL, &val);
+	val &= 0xFE00;
+	val |= 0x0092;
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_8481_LINK_SIGNAL, val);
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_8481_LED1_MASK,
+			 0x80);
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_8481_LED2_MASK,
+			 0x18);
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_8481_LED3_MASK,
+			 0x0040);
+
+	/* 'Interrupt Mask' */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_AN_DEVAD,
+			 0xFFFB, 0xFFFD);
+}
+
+static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
+				      struct link_params *params,
+				      struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u16 autoneg_val, an_1000_val, an_10_100_val;
+	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4,
+		      1 << NIG_LATCH_BC_ENABLE_MI_INT);
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000);
+
+	bnx2x_848xx_set_led(bp, phy);
+
+	/* set 1000 speed advertisement */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
+			&an_1000_val);
+
+	bnx2x_ext_phy_set_pause(params, phy, vars);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD,
+			MDIO_AN_REG_8481_LEGACY_AN_ADV,
+			&an_10_100_val);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL,
+			&autoneg_val);
+	/* Disable forced speed */
+	autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
+	an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8));
+
+	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+	     (phy->speed_cap_mask &
+	     PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+	    (phy->req_line_speed == SPEED_1000)) {
+		an_1000_val |= (1<<8);
+		autoneg_val |= (1<<9 | 1<<12);
+		if (phy->req_duplex == DUPLEX_FULL)
+			an_1000_val |= (1<<9);
+		DP(NETIF_MSG_LINK, "Advertising 1G\n");
+	} else
+		an_1000_val &= ~((1<<8) | (1<<9));
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
+			 an_1000_val);
+
+	/* set 10 speed advertisement */
+	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+	     (phy->speed_cap_mask &
+	     (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
+	      PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
+		an_10_100_val |= (1<<7);
+		/* Enable autoneg and restart autoneg for legacy speeds */
+		autoneg_val |= (1<<9 | 1<<12);
+
+		if (phy->req_duplex == DUPLEX_FULL)
+			an_10_100_val |= (1<<8);
+		DP(NETIF_MSG_LINK, "Advertising 100M\n");
+	}
+	/* set 10 speed advertisement */
+	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+	    (phy->speed_cap_mask &
+	  (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
+	   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
+		an_10_100_val |= (1<<5);
+		autoneg_val |= (1<<9 | 1<<12);
+		if (phy->req_duplex == DUPLEX_FULL)
+			an_10_100_val |= (1<<6);
+		DP(NETIF_MSG_LINK, "Advertising 10M\n");
+	}
+
+	/* Only 10/100 are allowed to work in FORCE mode */
+	if (phy->req_line_speed == SPEED_100) {
+		autoneg_val |= (1<<13);
+		/* Enabled AUTO-MDIX when autoneg is disabled */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
+				 (1<<15 | 1<<9 | 7<<0));
+		DP(NETIF_MSG_LINK, "Setting 100M force\n");
+	}
+	if (phy->req_line_speed == SPEED_10) {
+		/* Enabled AUTO-MDIX when autoneg is disabled */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
+				 (1<<15 | 1<<9 | 7<<0));
+		DP(NETIF_MSG_LINK, "Setting 10M force\n");
+	}
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_AN_ADV,
+			 an_10_100_val);
+
+	if (phy->req_duplex == DUPLEX_FULL)
+		autoneg_val |= (1<<8);
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_AN_DEVAD,
+			 MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val);
+
+	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+	    (phy->speed_cap_mask &
+	     PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
+		(phy->req_line_speed == SPEED_10000)) {
+		DP(NETIF_MSG_LINK, "Advertising 10G\n");
+		/* Restart autoneg for 10G*/
+
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
+				 0x3200);
+	} else if (phy->req_line_speed != SPEED_10 &&
+		   phy->req_line_speed != SPEED_100) {
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD,
+				 MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
+				 1);
+	}
+	/* Save spirom version */
+	bnx2x_save_848xx_spirom_version(phy, params);
+
+	return 0;
+}
+
+static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	/* Restore normal power mode*/
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+
+	/* HW reset */
+	bnx2x_ext_phy_hw_reset(bp, params->port);
+
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
+	return bnx2x_848xx_cmn_config_init(phy, params, vars);
+}
+
+static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
+				  struct link_params *params,
+				  struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u8 port = params->port, initialize = 1;
+	u16 val;
+	u16 temp;
+	u32 actual_phy_selection;
+	u8 rc = 0;
+
+	/* This is just for MDIO_CTL_REG_84823_MEDIA register. */
+
+	msleep(1);
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+		       port);
+	msleep(200); /* 100 is not enough */
+
+	/* 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);
+	bnx2x_program_serdes(&params->phy[INT_PHY], params, vars);
+	vars->line_speed = temp;
+
+	/* Set dual-media configuration according to configuration */
+
+	bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+			MDIO_CTL_REG_84823_MEDIA, &val);
+	val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
+		 MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
+		 MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
+		 MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK |
+		 MDIO_CTL_REG_84823_MEDIA_FIBER_1G);
+	val |= MDIO_CTL_REG_84823_CTRL_MAC_XFI |
+		MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L;
+
+	actual_phy_selection = bnx2x_phy_selection(params);
+
+	switch (actual_phy_selection) {
+	case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
+		/* Do nothing. Essentialy this is like the priority copper */
+		break;
+	case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
+		val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER;
+		break;
+	case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
+		val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER;
+		break;
+	case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
+		/* Do nothing here. The first PHY won't be initialized at all */
+		break;
+	case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
+		val |= MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN;
+		initialize = 0;
+		break;
+	}
+	if (params->phy[EXT_PHY2].req_line_speed == SPEED_1000)
+		val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
+
+	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+			 MDIO_CTL_REG_84823_MEDIA, val);
+	DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
+		   params->multi_phy_config, val);
+
+	if (initialize)
+		rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
+	else
+		bnx2x_save_848xx_spirom_version(phy, params);
+	return rc;
+}
+
+static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
+				       struct link_params *params,
+				       struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val, val1, val2;
+	u8 link_up = 0;
+
+	/* 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,
+			&val2);
+	DP(NETIF_MSG_LINK, "BCM848xx: PMD_SIGNAL 1.a811 = 0x%x\n", val2);
+
+	/* Check link 10G */
+	if (val2 & (1<<11)) {
+		vars->line_speed = SPEED_10000;
+		link_up = 1;
+		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
+	} else { /* Check Legacy speed link */
+		u16 legacy_status, legacy_speed;
+
+		/* Enable expansion register 0x42 (Operation mode status) */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_AN_DEVAD,
+				 MDIO_AN_REG_8481_EXPANSION_REG_ACCESS, 0xf42);
+
+		/* Get legacy speed operation status */
+		bnx2x_cl45_read(bp, phy,
+				MDIO_AN_DEVAD,
+				MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
+				&legacy_status);
+
+		DP(NETIF_MSG_LINK, "Legacy speed status"
+			     " = 0x%x\n", legacy_status);
+		link_up = ((legacy_status & (1<<11)) == (1<<11));
+		if (link_up) {
+			legacy_speed = (legacy_status & (3<<9));
+			if (legacy_speed == (0<<9))
+				vars->line_speed = SPEED_10;
+			else if (legacy_speed == (1<<9))
+				vars->line_speed = SPEED_100;
+			else if (legacy_speed == (2<<9))
+				vars->line_speed = SPEED_1000;
+			else /* Should not happen */
+				vars->line_speed = 0;
+
+			if (legacy_status & (1<<8))
+				vars->duplex = DUPLEX_FULL;
+			else
+				vars->duplex = DUPLEX_HALF;
+
+			DP(NETIF_MSG_LINK, "Link is up in %dMbps,"
+				   " is_duplex_full= %d\n", vars->line_speed,
+				   (vars->duplex == DUPLEX_FULL));
+			/* Check legacy speed AN resolution */
+			bnx2x_cl45_read(bp, phy,
+					MDIO_AN_DEVAD,
+					MDIO_AN_REG_8481_LEGACY_MII_STATUS,
+					&val);
+			if (val & (1<<5))
+				vars->link_status |=
+					LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+			bnx2x_cl45_read(bp, phy,
+					MDIO_AN_DEVAD,
+					MDIO_AN_REG_8481_LEGACY_AN_EXPANSION,
+					&val);
+			if ((val & (1<<0)) == 0)
+				vars->link_status |=
+					LINK_STATUS_PARALLEL_DETECTION_USED;
+		}
+	}
+	if (link_up) {
+		DP(NETIF_MSG_LINK, "BCM84823: link speed is %d\n",
+			   vars->line_speed);
+		bnx2x_ext_phy_resolve_fc(phy, params, vars);
+	}
+
+	return link_up;
+}
+
+static u8 bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
+{
+	u8 status = 0;
+	u32 spirom_ver;
+	spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
+	status = bnx2x_format_ver(spirom_ver, str, len);
+	return status;
+}
+
+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);
+	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
+			    MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
+}
+
+static void bnx2x_8481_link_reset(struct bnx2x_phy *phy,
+					struct link_params *params)
+{
+	bnx2x_cl45_write(params->bp, phy,
+			 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
+	bnx2x_cl45_write(params->bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1);
+}
+
+static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
+				   struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u8 port = params->port;
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+			    MISC_REGISTERS_GPIO_OUTPUT_LOW,
+			    port);
+}
+
+static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
+				     struct link_params *params, u8 mode)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val;
+
+	switch (mode) {
+	case LED_MODE_OFF:
+
+		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OFF\n", params->port);
+
+		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
+		    SHARED_HW_CFG_LED_EXTPHY1) {
+
+			/* Set LED masks */
+			bnx2x_cl45_write(bp, phy,
+					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);
+
+			bnx2x_cl45_write(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8481_LED3_MASK,
+					0x0);
+
+			bnx2x_cl45_write(bp, phy,
+					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,
+					 0x0);
+		}
+		break;
+	case LED_MODE_FRONT_PANEL_OFF:
+
+		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE FRONT PANEL OFF\n",
+		   params->port);
+
+		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
+		    SHARED_HW_CFG_LED_EXTPHY1) {
+
+			/* Set LED masks */
+			bnx2x_cl45_write(bp, phy,
+					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);
+
+			bnx2x_cl45_write(bp, phy,
+					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);
+
+		} else {
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x0);
+		}
+		break;
+	case LED_MODE_ON:
+
+		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE ON\n", params->port);
+
+		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
+		    SHARED_HW_CFG_LED_EXTPHY1) {
+			/* Set control reg */
+			bnx2x_cl45_read(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8481_LINK_SIGNAL,
+					&val);
+			val &= 0x8000;
+			val |= 0x2492;
+
+			bnx2x_cl45_write(bp, phy,
+					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);
+
+			bnx2x_cl45_write(bp, phy,
+					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);
+
+			bnx2x_cl45_write(bp, phy,
+					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);
+		}
+		break;
+
+	case LED_MODE_OPER:
+
+		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OPER\n", params->port);
+
+		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
+		    SHARED_HW_CFG_LED_EXTPHY1) {
+
+			/* Set control reg */
+			bnx2x_cl45_read(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8481_LINK_SIGNAL,
+					&val);
+
+			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");
+				bnx2x_cl45_write(bp, phy,
+						 MDIO_PMA_DEVAD,
+						 MDIO_PMA_REG_8481_LINK_SIGNAL,
+						 0xa492);
+			}
+
+			/* Set LED masks */
+			bnx2x_cl45_write(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8481_LED1_MASK,
+					0x10);
+
+			bnx2x_cl45_write(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8481_LED2_MASK,
+					0x80);
+
+			bnx2x_cl45_write(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8481_LED3_MASK,
+					0x98);
+
+			bnx2x_cl45_write(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8481_LED5_MASK,
+					0x40);
+
+		} else {
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x80);
+		}
+		break;
+	}
+}
+/******************************************************************/
+/*			SFX7101 PHY SECTION			  */
+/******************************************************************/
+static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy,
+				       struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	/* SFX7101_XGXS_TEST1 */
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
+}
+
+static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	u16 fw_ver1, fw_ver2, val;
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "Setting the SFX7101 LASI indication\n");
+
+	/* Restore normal power mode*/
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+	/* HW reset */
+	bnx2x_ext_phy_hw_reset(bp, params->port);
+	bnx2x_wait_reset_complete(bp, phy);
+
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x1);
+	DP(NETIF_MSG_LINK, "Setting the SFX7101 LED to blink on traffic\n");
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
+
+	bnx2x_ext_phy_set_pause(params, phy, vars);
+	/* Restart autoneg */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, &val);
+	val |= 0x200;
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, val);
+
+	/* Save spirom version */
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER1, &fw_ver1);
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2, &fw_ver2);
+	bnx2x_save_spirom_version(bp, params->port,
+				  (u32)(fw_ver1<<16 | fw_ver2), phy->ver_addr);
+	return 0;
+}
+
+static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
+				 struct link_params *params,
+				 struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u8 link_up;
+	u16 val1, val2;
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+	DP(NETIF_MSG_LINK, "10G-base-T LASI status 0x%x->0x%x\n",
+		   val2, val1);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
+	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_up) {
+		bnx2x_cl45_read(bp, phy,
+				MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS,
+				&val2);
+		vars->line_speed = SPEED_10000;
+		DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n",
+			   val2, (val2 & (1<<14)));
+		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
+		bnx2x_ext_phy_resolve_fc(phy, params, vars);
+	}
+	return link_up;
+}
+
+
+static u8 bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+{
+	if (*len < 5)
+		return -EINVAL;
+	str[0] = (spirom_ver & 0xFF);
+	str[1] = (spirom_ver & 0xFF00) >> 8;
+	str[2] = (spirom_ver & 0xFF0000) >> 16;
+	str[3] = (spirom_ver & 0xFF000000) >> 24;
+	str[4] = '\0';
+	*len -= 5;
+	return 0;
+}
+
+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);
+
+	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)));
+		/* Wait for clear */
+		bnx2x_cl45_read(bp, phy,
+			      MDIO_PMA_DEVAD,
+			      MDIO_PMA_REG_7101_RESET, &val);
+
+		if ((val & (1<<15)) == 0)
+			break;
+	}
+}
+
+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);
+	/* The PHY reset is controlled by GPIO 1 */
+	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
+			    MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
+}
+
+static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
+				    struct link_params *params, u8 mode)
+{
+	u16 val = 0;
+	struct bnx2x *bp = params->bp;
+	switch (mode) {
+	case LED_MODE_FRONT_PANEL_OFF:
+	case LED_MODE_OFF:
+		val = 2;
+		break;
+	case LED_MODE_ON:
+		val = 1;
+		break;
+	case LED_MODE_OPER:
+		val = 0;
+		break;
+	}
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_7107_LINK_LED_CNTL,
+			 val);
+}
+
+/******************************************************************/
+/*			STATIC PHY DECLARATION			  */
+/******************************************************************/
+
+static struct bnx2x_phy phy_null = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
+	.addr		= 0,
+	.flags		= FLAGS_INIT_XGXS_FIRST,
+	.def_md_devad	= 0,
+	.reserved	= 0,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= 0,
+	.media_type	= ETH_PHY_NOT_PRESENT,
+	.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)NULL,
+	.read_status	= (read_status_t)NULL,
+	.link_reset	= (link_reset_t)NULL,
+	.config_loopback = (config_loopback_t)NULL,
+	.format_fw_ver	= (format_fw_ver_t)NULL,
+	.hw_reset	= (hw_reset_t)NULL,
+	.set_link_led	= (set_link_led_t)NULL,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_serdes = {
+	.type		= PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
+	.addr		= 0xff,
+	.flags		= 0,
+	.def_md_devad	= 0,
+	.reserved	= 0,
+	.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_2500baseX_Full |
+			   SUPPORTED_TP |
+			   SUPPORTED_Autoneg |
+			   SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_UNSPECIFIED,
+	.ver_addr	= 0,
+	.req_flow_ctrl	= 0,
+	.req_line_speed = 0,
+	.speed_cap_mask = 0,
+	.req_duplex	= 0,
+	.rsrv		= 0,
+	.config_init	= (config_init_t)bnx2x_init_serdes,
+	.read_status	= (read_status_t)bnx2x_link_settings_status,
+	.link_reset	= (link_reset_t)bnx2x_int_link_reset,
+	.config_loopback = (config_loopback_t)NULL,
+	.format_fw_ver	= (format_fw_ver_t)NULL,
+	.hw_reset	= (hw_reset_t)NULL,
+	.set_link_led	= (set_link_led_t)NULL,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_xgxs = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
+	.addr		= 0xff,
+	.flags		= 0,
+	.def_md_devad	= 0,
+	.reserved	= 0,
+	.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_2500baseX_Full |
+			   SUPPORTED_10000baseT_Full |
+			   SUPPORTED_FIBRE |
+			   SUPPORTED_Autoneg |
+			   SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_UNSPECIFIED,
+	.ver_addr	= 0,
+	.req_flow_ctrl	= 0,
+	.req_line_speed = 0,
+	.speed_cap_mask = 0,
+	.req_duplex	= 0,
+	.rsrv		= 0,
+	.config_init	= (config_init_t)bnx2x_init_xgxs,
+	.read_status	= (read_status_t)bnx2x_link_settings_status,
+	.link_reset	= (link_reset_t)bnx2x_int_link_reset,
+	.config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback,
+	.format_fw_ver	= (format_fw_ver_t)NULL,
+	.hw_reset	= (hw_reset_t)NULL,
+	.set_link_led	= (set_link_led_t)NULL,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_7101 = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
+	.addr		= 0xff,
+	.flags		= FLAGS_FAN_FAILURE_DET_REQ,
+	.def_md_devad	= 0,
+	.reserved	= 0,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= (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_7101_config_init,
+	.read_status	= (read_status_t)bnx2x_7101_read_status,
+	.link_reset	= (link_reset_t)bnx2x_common_ext_link_reset,
+	.config_loopback = (config_loopback_t)bnx2x_7101_config_loopback,
+	.format_fw_ver	= (format_fw_ver_t)bnx2x_7101_format_ver,
+	.hw_reset	= (hw_reset_t)bnx2x_7101_hw_reset,
+	.set_link_led	= (set_link_led_t)bnx2x_7101_set_link_led,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+static struct bnx2x_phy phy_8073 = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+	.addr		= 0xff,
+	.flags		= FLAGS_HW_LOCK_REQUIRED,
+	.def_md_devad	= 0,
+	.reserved	= 0,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= (SUPPORTED_10000baseT_Full |
+			   SUPPORTED_2500baseX_Full |
+			   SUPPORTED_1000baseT_Full |
+			   SUPPORTED_FIBRE |
+			   SUPPORTED_Autoneg |
+			   SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_UNSPECIFIED,
+	.ver_addr	= 0,
+	.req_flow_ctrl  = 0,
+	.req_line_speed = 0,
+	.speed_cap_mask = 0,
+	.req_duplex	= 0,
+	.rsrv		= 0,
+	.config_init	= (config_init_t)bnx2x_8073_config_init,
+	.read_status	= (read_status_t)bnx2x_8073_read_status,
+	.link_reset	= (link_reset_t)bnx2x_8073_link_reset,
+	.config_loopback = (config_loopback_t)NULL,
+	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
+	.hw_reset	= (hw_reset_t)NULL,
+	.set_link_led	= (set_link_led_t)NULL,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+static struct bnx2x_phy phy_8705 = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
+	.addr		= 0xff,
+	.flags		= FLAGS_INIT_XGXS_FIRST,
+	.def_md_devad	= 0,
+	.reserved	= 0,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= (SUPPORTED_10000baseT_Full |
+			   SUPPORTED_FIBRE |
+			   SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_XFP_FIBER,
+	.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_8705_config_init,
+	.read_status	= (read_status_t)bnx2x_8705_read_status,
+	.link_reset	= (link_reset_t)bnx2x_common_ext_link_reset,
+	.config_loopback = (config_loopback_t)NULL,
+	.format_fw_ver	= (format_fw_ver_t)bnx2x_null_format_ver,
+	.hw_reset	= (hw_reset_t)NULL,
+	.set_link_led	= (set_link_led_t)NULL,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+static struct bnx2x_phy phy_8706 = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
+	.addr		= 0xff,
+	.flags		= FLAGS_INIT_XGXS_FIRST,
+	.def_md_devad	= 0,
+	.reserved	= 0,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= (SUPPORTED_10000baseT_Full |
+			   SUPPORTED_1000baseT_Full |
+			   SUPPORTED_FIBRE |
+			   SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_SFP_FIBER,
+	.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_8706_config_init,
+	.read_status	= (read_status_t)bnx2x_8706_read_status,
+	.link_reset	= (link_reset_t)bnx2x_common_ext_link_reset,
+	.config_loopback = (config_loopback_t)NULL,
+	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
+	.hw_reset	= (hw_reset_t)NULL,
+	.set_link_led	= (set_link_led_t)NULL,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_8726 = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
+	.addr		= 0xff,
+	.flags		= (FLAGS_HW_LOCK_REQUIRED |
+			   FLAGS_INIT_XGXS_FIRST),
+	.def_md_devad	= 0,
+	.reserved	= 0,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= (SUPPORTED_10000baseT_Full |
+			   SUPPORTED_1000baseT_Full |
+			   SUPPORTED_Autoneg |
+			   SUPPORTED_FIBRE |
+			   SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_SFP_FIBER,
+	.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_8726_config_init,
+	.read_status	= (read_status_t)bnx2x_8726_read_status,
+	.link_reset	= (link_reset_t)bnx2x_8726_link_reset,
+	.config_loopback = (config_loopback_t)bnx2x_8726_config_loopback,
+	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
+	.hw_reset	= (hw_reset_t)NULL,
+	.set_link_led	= (set_link_led_t)NULL,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_8727 = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+	.addr		= 0xff,
+	.flags		= FLAGS_FAN_FAILURE_DET_REQ,
+	.def_md_devad	= 0,
+	.reserved	= 0,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= (SUPPORTED_10000baseT_Full |
+			   SUPPORTED_1000baseT_Full |
+			   SUPPORTED_FIBRE |
+			   SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_SFP_FIBER,
+	.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_8727_config_init,
+	.read_status	= (read_status_t)bnx2x_8727_read_status,
+	.link_reset	= (link_reset_t)bnx2x_8727_link_reset,
+	.config_loopback = (config_loopback_t)NULL,
+	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
+	.hw_reset	= (hw_reset_t)bnx2x_8727_hw_reset,
+	.set_link_led	= (set_link_led_t)bnx2x_8727_set_link_led,
+	.phy_specific_func = (phy_specific_func_t)bnx2x_8727_specific_func
+};
+static struct bnx2x_phy phy_8481 = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+	.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_8481_config_init,
+	.read_status	= (read_status_t)bnx2x_848xx_read_status,
+	.link_reset	= (link_reset_t)bnx2x_8481_link_reset,
+	.config_loopback = (config_loopback_t)NULL,
+	.format_fw_ver	= (format_fw_ver_t)bnx2x_848xx_format_ver,
+	.hw_reset	= (hw_reset_t)bnx2x_8481_hw_reset,
+	.set_link_led	= (set_link_led_t)bnx2x_848xx_set_link_led,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_84823 = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
+	.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   */
+/*                                                               */
+/*****************************************************************/
+
+static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base,
+				     struct bnx2x_phy *phy, u8 port,
+				     u8 phy_index)
+{
+	/* 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
+		 */
+		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]));
+
+			tx = REG_RD(bp, shmem_base +
+				    offsetof(struct shmem_region,
+			   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]));
+
+			tx = REG_RD(bp, shmem_base +
+				    offsetof(struct shmem_region,
+			  dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
+		}
+
+		phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff);
+		phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff);
+
+		phy->tx_preemphasis[i << 1] = ((tx>>16) & 0xffff);
+		phy->tx_preemphasis[(i << 1) + 1] = (tx & 0xffff);
+	}
+}
+
+static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base,
+				    u8 phy_index, u8 port)
+{
+	u32 ext_phy_config = 0;
+	switch (phy_index) {
+	case EXT_PHY1:
+		ext_phy_config = REG_RD(bp, shmem_base +
+					      offsetof(struct shmem_region,
+			dev_info.port_hw_config[port].external_phy_config));
+		break;
+	case EXT_PHY2:
+		ext_phy_config = REG_RD(bp, shmem_base +
+					      offsetof(struct shmem_region,
+			dev_info.port_hw_config[port].external_phy_config2));
+		break;
+	default:
+		DP(NETIF_MSG_LINK, "Invalid phy_index %d\n", phy_index);
+		return -EINVAL;
+	}
+
+	return ext_phy_config;
+}
+static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
+				 struct bnx2x_phy *phy)
+{
+	u32 phy_addr;
+	u32 chip_id;
+	u32 switch_cfg = (REG_RD(bp, shmem_base +
+				       offsetof(struct shmem_region,
+			dev_info.port_feature_config[port].link_config)) &
+			  PORT_FEATURE_CONNECTED_SWITCH_MASK);
+	chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
+	switch (switch_cfg) {
+	case SWITCH_CFG_1G:
+		phy_addr = REG_RD(bp,
+					NIG_REG_SERDES0_CTRL_PHY_ADDR +
+					port * 0x10);
+		*phy = phy_serdes;
+		break;
+	case SWITCH_CFG_10G:
+		phy_addr = REG_RD(bp,
+					NIG_REG_XGXS0_CTRL_PHY_ADDR +
+					port * 0x18);
+		*phy = phy_xgxs;
+		break;
+	default:
+		DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
+		return -EINVAL;
+	}
+	phy->addr = (u8)phy_addr;
+	phy->mdio_ctrl = bnx2x_get_emac_base(bp,
+					    SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH,
+					    port);
+	if (CHIP_IS_E2(bp))
+		phy->def_md_devad = E2_DEFAULT_PHY_DEV_ADDR;
+	else
+		phy->def_md_devad = DEFAULT_PHY_DEV_ADDR;
+
+	DP(NETIF_MSG_LINK, "Internal phy port=%d, addr=0x%x, mdio_ctl=0x%x\n",
+		   port, phy->addr, phy->mdio_ctrl);
+
+	bnx2x_populate_preemphasis(bp, shmem_base, phy, port, INT_PHY);
+	return 0;
+}
+
+static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
+				 u8 phy_index,
+				 u32 shmem_base,
+				 u32 shmem2_base,
+				 u8 port,
+				 struct bnx2x_phy *phy)
+{
+	u32 ext_phy_config, phy_type, config2;
+	u32 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH;
+	ext_phy_config = bnx2x_get_ext_phy_config(bp, shmem_base,
+						  phy_index, port);
+	phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
+	/* Select the phy type */
+	switch (phy_type) {
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
+		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED;
+		*phy = phy_8073;
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
+		*phy = phy_8705;
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
+		*phy = phy_8706;
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
+		*phy = phy_8726;
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
+		/* BCM8727_NOC => BCM8727 no over current */
+		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
+		*phy = phy_8727;
+		phy->flags |= FLAGS_NOC;
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
+		*phy = phy_8727;
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
+		*phy = phy_8481;
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
+		*phy = phy_84823;
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
+		*phy = phy_7101;
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
+		*phy = phy_null;
+		return -EINVAL;
+	default:
+		*phy = phy_null;
+		return 0;
+	}
+
+	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
+	*/
+	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;
+	} else {
+		u32 size = REG_RD(bp, shmem2_base);
+
+		if (size >
+		    offsetof(struct shmem2_region, ext_phy_fw_version2)) {
+			phy->ver_addr = shmem2_base +
+			    offsetof(struct shmem2_region,
+				     ext_phy_fw_version2[port]);
+		}
+		/* Check specific mdc mdio settings */
+		if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK)
+			mdc_mdio_access = (config2 &
+			SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK) >>
+			(SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT -
+			 SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT);
+	}
+	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.
+	 */
+	if (mdc_mdio_access != SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH)
+		phy->flags |= FLAGS_HW_LOCK_REQUIRED;
+	DP(NETIF_MSG_LINK, "phy_type 0x%x port %d found in index %d\n",
+		   phy_type, port, phy_index);
+	DP(NETIF_MSG_LINK, "             addr=0x%x, mdio_ctl=0x%x\n",
+		   phy->addr, phy->mdio_ctrl);
+	return 0;
+}
+
+static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
+			     u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
+{
+	u8 status = 0;
+	phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
+	if (phy_index == INT_PHY)
+		return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
+	status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base, shmem2_base,
+					port, phy);
+	return status;
+}
+
+static void bnx2x_phy_def_cfg(struct link_params *params,
+			      struct bnx2x_phy *phy,
+			      u8 phy_index)
+{
+	struct bnx2x *bp = params->bp;
+	u32 link_config;
+	/* 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.
+			port_feature_config[params->port].link_config2));
+		phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
+					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.
+				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));
+	}
+	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);
+
+	phy->req_duplex = DUPLEX_FULL;
+	switch (link_config  & PORT_FEATURE_LINK_SPEED_MASK) {
+	case PORT_FEATURE_LINK_SPEED_10M_HALF:
+		phy->req_duplex = DUPLEX_HALF;
+	case PORT_FEATURE_LINK_SPEED_10M_FULL:
+		phy->req_line_speed = SPEED_10;
+		break;
+	case PORT_FEATURE_LINK_SPEED_100M_HALF:
+		phy->req_duplex = DUPLEX_HALF;
+	case PORT_FEATURE_LINK_SPEED_100M_FULL:
+		phy->req_line_speed = SPEED_100;
+		break;
+	case PORT_FEATURE_LINK_SPEED_1G:
+		phy->req_line_speed = SPEED_1000;
+		break;
+	case PORT_FEATURE_LINK_SPEED_2_5G:
+		phy->req_line_speed = SPEED_2500;
+		break;
+	case PORT_FEATURE_LINK_SPEED_10G_CX4:
+		phy->req_line_speed = SPEED_10000;
+		break;
+	default:
+		phy->req_line_speed = SPEED_AUTO_NEG;
+		break;
+	}
+
+	switch (link_config  & PORT_FEATURE_FLOW_CONTROL_MASK) {
+	case PORT_FEATURE_FLOW_CONTROL_AUTO:
+		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
+		break;
+	case PORT_FEATURE_FLOW_CONTROL_TX:
+		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_TX;
+		break;
+	case PORT_FEATURE_FLOW_CONTROL_RX:
+		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_RX;
+		break;
+	case PORT_FEATURE_FLOW_CONTROL_BOTH:
+		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
+		break;
+	default:
+		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+		break;
+	}
+}
+
+u32 bnx2x_phy_selection(struct link_params *params)
+{
+	u32 phy_config_swapped, prio_cfg;
+	u32 return_cfg = PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT;
+
+	phy_config_swapped = params->multi_phy_config &
+		PORT_HW_CFG_PHY_SWAPPED_ENABLED;
+
+	prio_cfg = params->multi_phy_config &
+			PORT_HW_CFG_PHY_SELECTION_MASK;
+
+	if (phy_config_swapped) {
+		switch (prio_cfg) {
+		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
+		     return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY;
+		     break;
+		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
+		     return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY;
+		     break;
+		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
+		     return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
+		     break;
+		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
+		     return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
+		     break;
+		}
+	} else
+		return_cfg = prio_cfg;
+
+	return return_cfg;
+}
+
+
+u8 bnx2x_phy_probe(struct link_params *params)
+{
+	u8 phy_index, actual_phy_idx, link_cfg_idx;
+	u32 phy_config_swapped;
+	struct bnx2x *bp = params->bp;
+	struct bnx2x_phy *phy;
+	params->num_phys = 0;
+	DP(NETIF_MSG_LINK, "Begin phy probe\n");
+	phy_config_swapped = params->multi_phy_config &
+		PORT_HW_CFG_PHY_SWAPPED_ENABLED;
+
+	for (phy_index = INT_PHY; phy_index < MAX_PHYS;
+	      phy_index++) {
+		link_cfg_idx = LINK_CONFIG_IDX(phy_index);
+		actual_phy_idx = phy_index;
+		if (phy_config_swapped) {
+			if (phy_index == EXT_PHY1)
+				actual_phy_idx = EXT_PHY2;
+			else if (phy_index == EXT_PHY2)
+				actual_phy_idx = EXT_PHY1;
+		}
+		DP(NETIF_MSG_LINK, "phy_config_swapped %x, phy_index %x,"
+			       " actual_phy_idx %x\n", phy_config_swapped,
+			   phy_index, actual_phy_idx);
+		phy = &params->phy[actual_phy_idx];
+		if (bnx2x_populate_phy(bp, phy_index, params->shmem_base,
+				       params->shmem2_base, params->port,
+				       phy) != 0) {
+			params->num_phys = 0;
+			DP(NETIF_MSG_LINK, "phy probe failed in phy index %d\n",
+				   phy_index);
+			for (phy_index = INT_PHY;
+			      phy_index < MAX_PHYS;
+			      phy_index++)
+				*phy = phy_null;
+			return -EINVAL;
+		}
+		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
+			break;
+
+		bnx2x_phy_def_cfg(params, phy, phy_index);
+		params->num_phys++;
+	}
+
+	DP(NETIF_MSG_LINK, "End phy probe. #phys found %x\n", params->num_phys);
+	return 0;
+}
+
+u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx)
+{
+	if (phy_idx < params->num_phys)
+		return params->phy[phy_idx].supported;
+	return 0;
+}
+
+static void set_phy_vars(struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u8 actual_phy_idx, phy_index, link_cfg_idx;
+	u8 phy_config_swapped = params->multi_phy_config &
+			PORT_HW_CFG_PHY_SWAPPED_ENABLED;
+	for (phy_index = INT_PHY; phy_index < params->num_phys;
+	      phy_index++) {
+		link_cfg_idx = LINK_CONFIG_IDX(phy_index);
+		actual_phy_idx = phy_index;
+		if (phy_config_swapped) {
+			if (phy_index == EXT_PHY1)
+				actual_phy_idx = EXT_PHY2;
+			else if (phy_index == EXT_PHY2)
+				actual_phy_idx = EXT_PHY1;
+		}
+		params->phy[actual_phy_idx].req_flow_ctrl  =
+			params->req_flow_ctrl[link_cfg_idx];
+
+		params->phy[actual_phy_idx].req_line_speed =
+			params->req_line_speed[link_cfg_idx];
+
+		params->phy[actual_phy_idx].speed_cap_mask =
+			params->speed_cap_mask[link_cfg_idx];
+
+		params->phy[actual_phy_idx].req_duplex =
+			params->req_duplex[link_cfg_idx];
+
+		DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
+			   " speed_cap_mask %x\n",
+			   params->phy[actual_phy_idx].req_flow_ctrl,
+			   params->phy[actual_phy_idx].req_line_speed,
+			   params->phy[actual_phy_idx].speed_cap_mask);
+	}
+}
 
 u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-	u32 val;
-
 	DP(NETIF_MSG_LINK, "Phy Initialization started\n");
-	DP(NETIF_MSG_LINK, "req_speed %d, req_flowctrl %d\n",
-		 params->req_line_speed, params->req_flow_ctrl);
+	DP(NETIF_MSG_LINK, "(1) req_speed %d, req_flowctrl %d\n",
+		   params->req_line_speed[0], params->req_flow_ctrl[0]);
+	DP(NETIF_MSG_LINK, "(2) req_speed %d, req_flowctrl %d\n",
+		   params->req_line_speed[1], params->req_flow_ctrl[1]);
 	vars->link_status = 0;
 	vars->phy_link_up = 0;
 	vars->link_up = 0;
@@ -5966,11 +6877,7 @@
 	vars->duplex = DUPLEX_FULL;
 	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
 	vars->mac_type = MAC_TYPE_NONE;
-
-	if (params->switch_cfg ==  SWITCH_CFG_1G)
-		vars->phy_flags = PHY_SERDES_FLAG;
-	else
-		vars->phy_flags = PHY_XGXS_FLAG;
+	vars->phy_flags = 0;
 
 	/* disable attentions */
 	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
@@ -5981,6 +6888,13 @@
 
 	bnx2x_emac_init(params, vars);
 
+	if (params->num_phys == 0) {
+		DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
+		return -EINVAL;
+	}
+	set_phy_vars(params);
+
+	DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
 	if (CHIP_REV_IS_FPGA(bp)) {
 
 		vars->link_up = 1;
@@ -5999,7 +6913,9 @@
 		}
 
 		bnx2x_emac_enable(params, vars, 0);
-		bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
+		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);
 
@@ -6040,7 +6956,8 @@
 
 		vars->phy_flags = PHY_XGXS_FLAG;
 
-		bnx2x_phy_deassert(params, vars->phy_flags);
+		bnx2x_xgxs_deassert(params);
+
 		/* set bmac loopback */
 		bnx2x_bmac_enable(params, vars, 1);
 
@@ -6057,80 +6974,66 @@
 
 		vars->phy_flags = PHY_XGXS_FLAG;
 
-		bnx2x_phy_deassert(params, vars->phy_flags);
+		bnx2x_xgxs_deassert(params);
 		/* set bmac loopback */
 		bnx2x_emac_enable(params, vars, 1);
-		bnx2x_emac_program(params, vars->line_speed,
-					      vars->duplex);
+		bnx2x_emac_program(params, vars);
 		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
 		    params->port*4, 0);
 
-	} else if ((params->loopback_mode == LOOPBACK_XGXS_10) ||
+	} else if ((params->loopback_mode == LOOPBACK_XGXS) ||
 		   (params->loopback_mode == LOOPBACK_EXT_PHY)) {
 
 		vars->link_up = 1;
-		vars->line_speed = SPEED_10000;
-		vars->duplex = DUPLEX_FULL;
 		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+		vars->duplex = DUPLEX_FULL;
+		if (params->req_line_speed[0] == SPEED_1000) {
+			vars->line_speed = SPEED_1000;
+			vars->mac_type = MAC_TYPE_EMAC;
+		} else {
+			vars->line_speed = SPEED_10000;
+			vars->mac_type = MAC_TYPE_BMAC;
+		}
 
-		vars->phy_flags = PHY_XGXS_FLAG;
-
-		val = REG_RD(bp,
-				 NIG_REG_XGXS0_CTRL_PHY_ADDR+
-				 params->port*0x18);
-		params->phy_addr = (u8)val;
-
-		bnx2x_phy_deassert(params, vars->phy_flags);
+		bnx2x_xgxs_deassert(params);
 		bnx2x_link_initialize(params, vars);
 
-		vars->mac_type = MAC_TYPE_BMAC;
-
+		if (params->req_line_speed[0] == SPEED_1000) {
+			bnx2x_emac_program(params, vars);
+			bnx2x_emac_enable(params, vars, 0);
+		} else
 		bnx2x_bmac_enable(params, vars, 0);
 
-		if (params->loopback_mode == LOOPBACK_XGXS_10) {
+		if (params->loopback_mode == LOOPBACK_XGXS) {
 			/* set 10G XGXS loopback */
-			bnx2x_set_xgxs_loopback(params, vars, 1);
+			params->phy[INT_PHY].config_loopback(
+				&params->phy[INT_PHY],
+				params);
+
 		} else {
 			/* set external phy loopback */
-			bnx2x_ext_phy_loopback(params);
+			u8 phy_index;
+			for (phy_index = EXT_PHY1;
+			      phy_index < params->num_phys; phy_index++) {
+				if (params->phy[phy_index].config_loopback)
+					params->phy[phy_index].config_loopback(
+						&params->phy[phy_index],
+						params);
+			}
 		}
+
 		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
 			    params->port*4, 0);
 
-		bnx2x_set_led(params, LED_MODE_OPER, vars->line_speed);
+		bnx2x_set_led(params, vars,
+			      LED_MODE_OPER, vars->line_speed);
 	} else
 	/* No loopback */
 	{
-		bnx2x_phy_deassert(params, vars->phy_flags);
-		switch (params->switch_cfg) {
-		case SWITCH_CFG_1G:
-			vars->phy_flags |= PHY_SERDES_FLAG;
-			if ((params->ext_phy_config &
-			     PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
-			     PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
-				vars->phy_flags |= PHY_SGMII_FLAG;
-			}
-
-			val = REG_RD(bp,
-					 NIG_REG_SERDES0_CTRL_PHY_ADDR+
-					 params->port*0x10);
-
-			params->phy_addr = (u8)val;
-
-			break;
-		case SWITCH_CFG_10G:
-			vars->phy_flags |= PHY_XGXS_FLAG;
-			val = REG_RD(bp,
-				 NIG_REG_XGXS0_CTRL_PHY_ADDR+
-				 params->port*0x18);
-			params->phy_addr = (u8)val;
-
-			break;
-		default:
-			DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
-			return -EINVAL;
-		}
-		DP(NETIF_MSG_LINK, "Phy address = 0x%x\n", params->phy_addr);
+		if (params->switch_cfg == SWITCH_CFG_10G)
+			bnx2x_xgxs_deassert(params);
+		else
+			bnx2x_serdes_deassert(bp, params->port);
 
 		bnx2x_link_initialize(params, vars);
 		msleep(30);
@@ -6138,29 +7041,11 @@
 	}
 	return 0;
 }
-
-static void bnx2x_8726_reset_phy(struct bnx2x *bp, u8 port, u8 ext_phy_addr)
-{
-	DP(NETIF_MSG_LINK, "bnx2x_8726_reset_phy port %d\n", port);
-
-	/* Set serial boot control for external load */
-	bnx2x_cl45_write(bp, port,
-		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, ext_phy_addr,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL, 0x0001);
-}
-
 u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
 		  u8 reset_ext_phy)
 {
 	struct bnx2x *bp = params->bp;
-	u32 ext_phy_config = params->ext_phy_config;
-	u8 port = params->port;
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
-	u32 val = REG_RD(bp, params->shmem_base +
-			     offsetof(struct shmem_region, dev_info.
-				      port_feature_config[params->port].
-				      config));
+	u8 phy_index, port = params->port;
 	DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port);
 	/* disable attentions */
 	vars->link_status = 0;
@@ -6189,73 +7074,21 @@
 	 * Hold it as vars low
 	 */
 	 /* clear link led */
-	bnx2x_set_led(params, LED_MODE_OFF, 0);
+	bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
+
 	if (reset_ext_phy) {
-		switch (ext_phy_type) {
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-		{
-
-			/* Disable Transmitter */
-			u8 ext_phy_addr =
-				XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-			if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-			    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-				bnx2x_sfp_set_transmitter(bp, port,
-					PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-					ext_phy_addr, 0);
-			break;
-		}
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-			DP(NETIF_MSG_LINK, "Setting 8073 port %d into "
-				 "low power mode\n",
-				 port);
-			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-					  MISC_REGISTERS_GPIO_OUTPUT_LOW,
-					  port);
-			break;
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-		{
-			u8 ext_phy_addr =
-				XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-			/* Set soft reset */
-			bnx2x_8726_reset_phy(bp, params->port, ext_phy_addr);
-			break;
-		}
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
-		{
-			u8 ext_phy_addr =
-				XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-			bnx2x_cl45_write(bp, port,
-				       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-				       ext_phy_addr,
-				       MDIO_AN_DEVAD,
-				       MDIO_AN_REG_CTRL, 0x0000);
-			bnx2x_cl45_write(bp, port,
-				       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
-				       ext_phy_addr,
-				       MDIO_PMA_DEVAD,
-				       MDIO_PMA_REG_CTRL, 1);
-			break;
-		}
-		default:
-			/* HW reset */
-			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-					  MISC_REGISTERS_GPIO_OUTPUT_LOW,
-					  port);
-			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-					  MISC_REGISTERS_GPIO_OUTPUT_LOW,
-					  port);
-			DP(NETIF_MSG_LINK, "reset external PHY\n");
+		for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+		      phy_index++) {
+			if (params->phy[phy_index].link_reset)
+				params->phy[phy_index].link_reset(
+					&params->phy[phy_index],
+					params);
 		}
 	}
-	/* reset the SerDes/XGXS */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
-	       (0x1ff << (port*16)));
 
+	if (params->phy[INT_PHY].link_reset)
+		params->phy[INT_PHY].link_reset(
+			&params->phy[INT_PHY], params);
 	/* reset BigMac */
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
 	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
@@ -6269,183 +7102,41 @@
 	return 0;
 }
 
-static u8 bnx2x_update_link_down(struct link_params *params,
-			       struct link_vars *vars)
+/****************************************************************************/
+/*				Common function				    */
+/****************************************************************************/
+static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
+				     u32 shmem_base_path[],
+				     u32 shmem2_base_path[], u8 phy_index,
+				     u32 chip_id)
 {
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-
-	DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
-	bnx2x_set_led(params, LED_MODE_OFF, 0);
-
-	/* indicate no mac active */
-	vars->mac_type = MAC_TYPE_NONE;
-
-	/* update shared memory */
-	vars->link_status = 0;
-	vars->line_speed = 0;
-	bnx2x_update_mng(params, vars->link_status);
-
-	/* activate nig drain */
-	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
-
-	/* disable emac */
-	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
-
-	msleep(10);
-
-	/* reset BigMac */
-	bnx2x_bmac_rx_disable(bp, params->port);
-	REG_WR(bp, GRCBASE_MISC +
-		   MISC_REGISTERS_RESET_REG_2_CLEAR,
-		   (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
-	return 0;
-}
-
-static u8 bnx2x_update_link_up(struct link_params *params,
-			     struct link_vars *vars,
-			     u8 link_10g, u32 gp_status)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u8 rc = 0;
-
-	vars->link_status |= LINK_STATUS_LINK_UP;
-	if (link_10g) {
-		bnx2x_bmac_enable(params, vars, 0);
-		bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000);
-	} else {
-		rc = bnx2x_emac_program(params, vars->line_speed,
-				      vars->duplex);
-
-		bnx2x_emac_enable(params, vars, 0);
-
-		/* AN complete? */
-		if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
-			if (!(vars->phy_flags &
-			      PHY_SGMII_FLAG))
-				bnx2x_set_gmii_tx_driver(params);
-		}
-	}
-
-	/* PBF - link up */
-	rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
-			      vars->line_speed);
-
-	/* disable drain */
-	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
-
-	/* update shared memory */
-	bnx2x_update_mng(params, vars->link_status);
-	msleep(20);
-	return rc;
-}
-/* This function should called upon link interrupt */
-/* In case vars->link_up, driver needs to
-	1. Update the pbf
-	2. Disable drain
-	3. Update the shared memory
-	4. Indicate link up
-	5. Set LEDs
-   Otherwise,
-	1. Update shared memory
-	2. Reset BigMac
-	3. Report link down
-	4. Unset LEDs
-*/
-u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u8 port = params->port;
-	u16 gp_status;
-	u8 link_10g;
-	u8 ext_phy_link_up, rc = 0;
-	u32 ext_phy_type;
-	u8 is_mi_int = 0;
-
-	DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
-		 port, (vars->phy_flags & PHY_XGXS_FLAG),
-		 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
-
-	is_mi_int = (u8)(REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT +
-				    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));
-
-	DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
-	  REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
-	  REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
-
-	/* disable emac */
-	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
-
-	ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
-	/* Check external link change only for non-direct */
-	ext_phy_link_up = bnx2x_ext_phy_is_link_up(params, vars, is_mi_int);
-
-	/* Read gp_status */
-	CL45_RD_OVER_CL22(bp, port, params->phy_addr,
-			      MDIO_REG_BANK_GP_STATUS,
-			      MDIO_GP_STATUS_TOP_AN_STATUS1,
-			      &gp_status);
-
-	rc = bnx2x_link_settings_status(params, vars, gp_status,
-				      ext_phy_link_up);
-	if (rc != 0)
-		return rc;
-
-	/* anything 10 and over uses the bmac */
-	link_10g = ((vars->line_speed == SPEED_10000) ||
-		    (vars->line_speed == SPEED_12000) ||
-		    (vars->line_speed == SPEED_12500) ||
-		    (vars->line_speed == SPEED_13000) ||
-		    (vars->line_speed == SPEED_15000) ||
-		    (vars->line_speed == SPEED_16000));
-
-	bnx2x_link_int_ack(params, vars, link_10g, is_mi_int);
-
-	/* 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 to
-	initialize it*/
-
-	if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
-	    (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) &&
-	    (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) &&
-	    (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) &&
-	    (ext_phy_link_up && !vars->phy_link_up))
-		bnx2x_init_internal_phy(params, vars, 0);
-
-	/* link is up only if both local phy and external phy are up */
-	vars->link_up = (ext_phy_link_up && vars->phy_link_up);
-
-	if (vars->link_up)
-		rc = bnx2x_update_link_up(params, vars, link_10g, gp_status);
-	else
-		rc = bnx2x_update_link_down(params, vars);
-
-	return rc;
-}
-
-static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
-{
-	u8 ext_phy_addr[PORT_MAX];
+	struct bnx2x_phy phy[PORT_MAX];
+	struct bnx2x_phy *phy_blk[PORT_MAX];
 	u16 val;
 	s8 port;
+	s8 port_of_path = 0;
 
 	/* PART1 - Reset both phys */
 	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		/* Extract the ext phy address for the port */
-		u32 ext_phy_config = REG_RD(bp, shmem_base +
-					offsetof(struct shmem_region,
-		   dev_info.port_hw_config[port].external_phy_config));
+		u32 shmem_base, shmem2_base;
+		/* In E2, same phy is using for port0 of the two paths */
+		if (CHIP_IS_E2(bp)) {
+			shmem_base = shmem_base_path[port];
+			shmem2_base = shmem2_base_path[port];
+			port_of_path = 0;
+		} else {
+			shmem_base = shmem_base_path[0];
+			shmem2_base = shmem2_base_path[0];
+			port_of_path = port;
+		}
 
+		/* Extract the ext phy address for the port */
+		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+				       port_of_path, &phy[port]) !=
+		    0) {
+			DP(NETIF_MSG_LINK, "populate_phy failed\n");
+			return -EINVAL;
+		}
 		/* disable attentions */
 		bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
 			     (NIG_MASK_XGXS0_LINK_STATUS |
@@ -6453,17 +7144,13 @@
 			      NIG_MASK_SERDES0_LINK_STATUS |
 			      NIG_MASK_MI_INT));
 
-		ext_phy_addr[port] = XGXS_EXT_PHY_ADDR(ext_phy_config);
-
 		/* 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);
 
 		/* Reset the phy */
-		bnx2x_cl45_write(bp, port,
-			       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-			       ext_phy_addr[port],
+		bnx2x_cl45_write(bp, &phy[port],
 			       MDIO_PMA_DEVAD,
 			       MDIO_PMA_REG_CTRL,
 			       1<<15);
@@ -6472,15 +7159,28 @@
 	/* Add delay of 150ms after reset */
 	msleep(150);
 
+	if (phy[PORT_0].addr & 0x1) {
+		phy_blk[PORT_0] = &(phy[PORT_1]);
+		phy_blk[PORT_1] = &(phy[PORT_0]);
+	} else {
+		phy_blk[PORT_0] = &(phy[PORT_0]);
+		phy_blk[PORT_1] = &(phy[PORT_1]);
+	}
+
 	/* PART2 - Download firmware to both phys */
 	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
 		u16 fw_ver1;
+		if (CHIP_IS_E2(bp))
+			port_of_path = 0;
+		else
+			port_of_path = port;
 
-		bnx2x_bcm8073_external_rom_boot(bp, port,
-					      ext_phy_addr[port], shmem_base);
+		DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
+			   phy_blk[port]->addr);
+		bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
+						  port_of_path);
 
-		bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-			      ext_phy_addr[port],
+		bnx2x_cl45_read(bp, phy_blk[port],
 			      MDIO_PMA_DEVAD,
 			      MDIO_PMA_REG_ROM_VER1, &fw_ver1);
 		if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
@@ -6492,16 +7192,12 @@
 		}
 
 		/* Only set bit 10 = 1 (Tx power down) */
-		bnx2x_cl45_read(bp, port,
-			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-			      ext_phy_addr[port],
+		bnx2x_cl45_read(bp, phy_blk[port],
 			      MDIO_PMA_DEVAD,
 			      MDIO_PMA_REG_TX_POWER_DOWN, &val);
 
 		/* Phase1 of TX_POWER_DOWN reset */
-		bnx2x_cl45_write(bp, port,
-			       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-			       ext_phy_addr[port],
+		bnx2x_cl45_write(bp, phy_blk[port],
 			       MDIO_PMA_DEVAD,
 			       MDIO_PMA_REG_TX_POWER_DOWN,
 			       (val | 1<<10));
@@ -6515,28 +7211,20 @@
 	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
 		/* Phase2 of POWER_DOWN_RESET */
 		/* Release bit 10 (Release Tx power down) */
-		bnx2x_cl45_read(bp, port,
-			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-			      ext_phy_addr[port],
+		bnx2x_cl45_read(bp, phy_blk[port],
 			      MDIO_PMA_DEVAD,
 			      MDIO_PMA_REG_TX_POWER_DOWN, &val);
 
-		bnx2x_cl45_write(bp, port,
-			       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-			       ext_phy_addr[port],
+		bnx2x_cl45_write(bp, phy_blk[port],
 			       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, port,
-			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-			      ext_phy_addr[port],
+		bnx2x_cl45_read(bp, phy_blk[port],
 			      MDIO_PMA_DEVAD,
 			      MDIO_PMA_REG_EDC_FFE_MAIN, &val);
-		bnx2x_cl45_write(bp, port,
-			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
-			      ext_phy_addr[port],
+		bnx2x_cl45_write(bp, phy_blk[port],
 			      MDIO_PMA_DEVAD,
 			      MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
 
@@ -6545,46 +7233,111 @@
 				  MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
 	}
 	return 0;
-
 }
-
-static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base)
+static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp,
+				     u32 shmem_base_path[],
+				     u32 shmem2_base_path[], u8 phy_index,
+				     u32 chip_id)
 {
-	u8 ext_phy_addr[PORT_MAX];
-	s8 port, first_port, i;
+	u32 val;
+	s8 port;
+	struct bnx2x_phy phy;
+	/* Use port1 because of the static port-swap */
+	/* Enable the module detection interrupt */
+	val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
+	val |= ((1<<MISC_REGISTERS_GPIO_3)|
+		(1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT)));
+	REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
+
+	bnx2x_ext_phy_hw_reset(bp, 1);
+	msleep(5);
+	for (port = 0; port < PORT_MAX; port++) {
+		u32 shmem_base, shmem2_base;
+
+		/* In E2, same phy is using for port0 of the two paths */
+		if (CHIP_IS_E2(bp)) {
+			shmem_base = shmem_base_path[port];
+			shmem2_base = shmem2_base_path[port];
+		} else {
+			shmem_base = shmem_base_path[0];
+			shmem2_base = shmem2_base_path[0];
+		}
+		/* Extract the ext phy address for the port */
+		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+				       port, &phy) !=
+		    0) {
+			DP(NETIF_MSG_LINK, "populate phy failed\n");
+			return -EINVAL;
+		}
+
+		/* Reset phy*/
+		bnx2x_cl45_write(bp, &phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001);
+
+
+		/* Set fault module detected LED on */
+		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
+				  MISC_REGISTERS_GPIO_HIGH,
+				  port);
+	}
+
+	return 0;
+}
+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;
 	u32 swap_val, swap_override;
-	DP(NETIF_MSG_LINK, "Executing BCM8727 common init\n");
+	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);
 
-	bnx2x_ext_phy_hw_reset(bp, 1 ^ (swap_val && swap_override));
+	port = 1;
+
+	bnx2x_ext_phy_hw_reset(bp, port ^ (swap_val && swap_override));
+
+	/* Calculate the port based on port swap */
+	port ^= (swap_val && swap_override);
+
 	msleep(5);
 
-	if (swap_val && swap_override)
-		first_port = PORT_0;
-	else
-		first_port = PORT_1;
-
 	/* PART1 - Reset both phys */
-	for (i = 0, port = first_port; i < PORT_MAX; i++, port = !port) {
+	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
+		u32 shmem_base, shmem2_base;
+
+		/* In E2, same phy is using for port0 of the two paths */
+		if (CHIP_IS_E2(bp)) {
+			shmem_base = shmem_base_path[port];
+			shmem2_base = shmem2_base_path[port];
+			port_of_path = 0;
+		} else {
+			shmem_base = shmem_base_path[0];
+			shmem2_base = shmem2_base_path[0];
+			port_of_path = port;
+		}
+
 		/* Extract the ext phy address for the port */
-		u32 ext_phy_config = REG_RD(bp, shmem_base +
-					offsetof(struct shmem_region,
-		   dev_info.port_hw_config[port].external_phy_config));
-
+		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+				       port_of_path, &phy[port]) !=
+				       0) {
+			DP(NETIF_MSG_LINK, "populate phy failed\n");
+			return -EINVAL;
+		}
 		/* disable attentions */
-		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));
+		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));
 
-		ext_phy_addr[port] = XGXS_EXT_PHY_ADDR(ext_phy_config);
 
 		/* Reset the phy */
-		bnx2x_cl45_write(bp, port,
-			       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-			       ext_phy_addr[port],
+		bnx2x_cl45_write(bp, &phy[port],
 			       MDIO_PMA_DEVAD,
 			       MDIO_PMA_REG_CTRL,
 			       1<<15);
@@ -6592,16 +7345,25 @@
 
 	/* Add delay of 150ms after reset */
 	msleep(150);
-
+	if (phy[PORT_0].addr & 0x1) {
+		phy_blk[PORT_0] = &(phy[PORT_1]);
+		phy_blk[PORT_1] = &(phy[PORT_0]);
+	} else {
+		phy_blk[PORT_0] = &(phy[PORT_0]);
+		phy_blk[PORT_1] = &(phy[PORT_1]);
+	}
 	/* PART2 - Download firmware to both phys */
-	for (i = 0, port = first_port; i < PORT_MAX; i++, port = !port) {
+	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
 		u16 fw_ver1;
-
-		bnx2x_bcm8727_external_rom_boot(bp, port,
-					      ext_phy_addr[port], shmem_base);
-
-		bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
-			      ext_phy_addr[port],
+		 if (CHIP_IS_E2(bp))
+			port_of_path = 0;
+		else
+			port_of_path = port;
+		DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
+			   phy_blk[port]->addr);
+		bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
+						  port_of_path);
+		bnx2x_cl45_read(bp, phy_blk[port],
 			      MDIO_PMA_DEVAD,
 			      MDIO_PMA_REG_ROM_VER1, &fw_ver1);
 		if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
@@ -6616,82 +7378,35 @@
 	return 0;
 }
 
-
-static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base)
-{
-	u8 ext_phy_addr;
-	u32 val;
-	s8 port;
-
-	/* Use port1 because of the static port-swap */
-	/* Enable the module detection interrupt */
-	val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
-	val |= ((1<<MISC_REGISTERS_GPIO_3)|
-		(1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT)));
-	REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
-
-	bnx2x_ext_phy_hw_reset(bp, 1);
-	msleep(5);
-	for (port = 0; port < PORT_MAX; port++) {
-		/* Extract the ext phy address for the port */
-		u32 ext_phy_config = REG_RD(bp, shmem_base +
-					offsetof(struct shmem_region,
-			dev_info.port_hw_config[port].external_phy_config));
-
-		ext_phy_addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
-		DP(NETIF_MSG_LINK, "8726_common_init : ext_phy_addr = 0x%x\n",
-			 ext_phy_addr);
-
-		bnx2x_8726_reset_phy(bp, port, ext_phy_addr);
-
-		/* Set fault module detected LED on */
-		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-				  MISC_REGISTERS_GPIO_HIGH,
-				  port);
-	}
-
-	return 0;
-}
-
-
-static u8 bnx2x_84823_common_init_phy(struct bnx2x *bp, u32 shmem_base)
-{
-	/* HW reset */
-	bnx2x_ext_phy_hw_reset(bp, 1);
-	return 0;
-}
-u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
+static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
+				    u32 shmem2_base_path[], u8 phy_index,
+				    u32 ext_phy_type, u32 chip_id)
 {
 	u8 rc = 0;
-	u32 ext_phy_type;
-
-	DP(NETIF_MSG_LINK, "Begin common phy init\n");
-
-	/* Read the ext_phy_type for arbitrary port(0) */
-	ext_phy_type = XGXS_EXT_PHY_TYPE(
-			REG_RD(bp, shmem_base +
-			   offsetof(struct shmem_region,
-			     dev_info.port_hw_config[0].external_phy_config)));
 
 	switch (ext_phy_type) {
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-	{
-		rc = bnx2x_8073_common_init_phy(bp, shmem_base);
+		rc = bnx2x_8073_common_init_phy(bp, shmem_base_path,
+						shmem2_base_path,
+						phy_index, chip_id);
 		break;
-	}
 
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
-		rc = bnx2x_8727_common_init_phy(bp, shmem_base);
+		rc = bnx2x_8727_common_init_phy(bp, shmem_base_path,
+						shmem2_base_path,
+						phy_index, chip_id);
 		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 */
-		rc = bnx2x_8726_common_init_phy(bp, shmem_base);
+		rc = bnx2x_8726_common_init_phy(bp, shmem_base_path,
+						shmem2_base_path,
+						phy_index, chip_id);
 		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
-		rc = bnx2x_84823_common_init_phy(bp, shmem_base);
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
+		rc = -EINVAL;
 		break;
 	default:
 		DP(NETIF_MSG_LINK,
@@ -6703,33 +7418,81 @@
 	return rc;
 }
 
-void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
+u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
+			 u32 shmem2_base_path[], u32 chip_id)
 {
-	u16 val, cnt;
+	u8 rc = 0;
+	u8 phy_index;
+	u32 ext_phy_type, ext_phy_config;
+	DP(NETIF_MSG_LINK, "Begin common phy init\n");
 
-	bnx2x_cl45_read(bp, port,
-		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
-		      phy_addr,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_7101_RESET, &val);
+	if (CHIP_REV_IS_EMUL(bp))
+		return 0;
 
-	for (cnt = 0; cnt < 10; cnt++) {
-		msleep(50);
-		/* Writes a self-clearing reset */
-		bnx2x_cl45_write(bp, port,
-			       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
-			       phy_addr,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_7101_RESET,
-			       (val | (1<<15)));
-		/* Wait for clear */
-		bnx2x_cl45_read(bp, port,
-			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
-			      phy_addr,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_7101_RESET, &val);
+	/* Read the ext_phy_type for arbitrary port(0) */
+	for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+	      phy_index++) {
+		ext_phy_config = bnx2x_get_ext_phy_config(bp,
+							  shmem_base_path[0],
+							  phy_index, 0);
+		ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
+		rc |= bnx2x_ext_phy_common_init(bp, shmem_base_path,
+						shmem2_base_path,
+						phy_index, ext_phy_type,
+						chip_id);
+	}
+	return rc;
+}
 
-		if ((val & (1<<15)) == 0)
-			break;
+u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
+{
+	u8 phy_index;
+	struct bnx2x_phy phy;
+	for (phy_index = INT_PHY; phy_index < MAX_PHYS;
+	      phy_index++) {
+		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+				       0, &phy) != 0) {
+			DP(NETIF_MSG_LINK, "populate phy failed\n");
+			return 0;
+		}
+
+		if (phy.flags & FLAGS_HW_LOCK_REQUIRED)
+			return 1;
+	}
+	return 0;
+}
+
+u8 bnx2x_fan_failure_det_req(struct bnx2x *bp,
+			     u32 shmem_base,
+			     u32 shmem2_base,
+			     u8 port)
+{
+	u8 phy_index, fan_failure_det_req = 0;
+	struct bnx2x_phy phy;
+	for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+	      phy_index++) {
+		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+				       port, &phy)
+		    != 0) {
+			DP(NETIF_MSG_LINK, "populate phy failed\n");
+			return 0;
+		}
+		fan_failure_det_req |= (phy.flags &
+					FLAGS_FAN_FAILURE_DET_REQ);
+	}
+	return fan_failure_det_req;
+}
+
+void bnx2x_hw_reset_phy(struct link_params *params)
+{
+	u8 phy_index;
+	for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+	      phy_index++) {
+		if (params->phy[phy_index].hw_reset) {
+			params->phy[phy_index].hw_reset(
+				&params->phy[phy_index],
+				params);
+			params->phy[phy_index] = phy_null;
+		}
 	}
 }
diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h
index 40c2981..58a4c71 100644
--- a/drivers/net/bnx2x/bnx2x_link.h
+++ b/drivers/net/bnx2x/bnx2x_link.h
@@ -1,4 +1,4 @@
-/* Copyright 2008-2009 Broadcom Corporation
+/* Copyright 2008-2010 Broadcom Corporation
  *
  * Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -22,7 +22,8 @@
 /***********************************************************/
 /*                         Defines                         */
 /***********************************************************/
-#define DEFAULT_PHY_DEV_ADDR 3
+#define DEFAULT_PHY_DEV_ADDR	3
+#define E2_DEFAULT_PHY_DEV_ADDR	5
 
 
 
@@ -46,9 +47,137 @@
 #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) \
+		((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK)
+#define XGXS_EXT_PHY_ADDR(ext_phy_config) \
+		(((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> \
+		 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT)
+#define SERDES_EXT_PHY_TYPE(ext_phy_config) \
+		((ext_phy_config) & PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK)
+
+/* Single Media Direct board is the plain 577xx board with CX4/RJ45 jacks */
+#define SINGLE_MEDIA_DIRECT(params)	(params->num_phys == 1)
+/* Single Media board contains single external phy */
+#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_SET(phy_addr, phy_type, mdio_access) \
+	(phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET)
 /***********************************************************/
 /*                         Structs                         */
 /***********************************************************/
+#define INT_PHY		0
+#define EXT_PHY1	1
+#define EXT_PHY2	2
+#define MAX_PHYS	3
+
+/* Same configuration is shared between the XGXS and the first external phy */
+#define LINK_CONFIG_SIZE (MAX_PHYS - 1)
+#define LINK_CONFIG_IDX(_phy_idx) ((_phy_idx == INT_PHY) ? \
+					 0 : (_phy_idx - 1))
+/***********************************************************/
+/*                      bnx2x_phy struct                     */
+/*  Defines the required arguments and function per phy    */
+/***********************************************************/
+struct link_vars;
+struct link_params;
+struct bnx2x_phy;
+
+typedef u8 (*config_init_t)(struct bnx2x_phy *phy, struct link_params *params,
+			    struct link_vars *vars);
+typedef u8 (*read_status_t)(struct bnx2x_phy *phy, struct link_params *params,
+			    struct link_vars *vars);
+typedef void (*link_reset_t)(struct bnx2x_phy *phy,
+			     struct link_params *params);
+typedef void (*config_loopback_t)(struct bnx2x_phy *phy,
+				  struct link_params *params);
+typedef u8 (*format_fw_ver_t)(u32 raw, u8 *str, u16 *len);
+typedef void (*hw_reset_t)(struct bnx2x_phy *phy, struct link_params *params);
+typedef void (*set_link_led_t)(struct bnx2x_phy *phy,
+			       struct link_params *params, u8 mode);
+typedef void (*phy_specific_func_t)(struct bnx2x_phy *phy,
+				    struct link_params *params, u32 action);
+
+struct bnx2x_phy {
+	u32 type;
+
+	/* Loaded during init */
+	u8 addr;
+
+	u8 flags;
+	/* Require HW lock */
+#define FLAGS_HW_LOCK_REQUIRED		(1<<0)
+	/* No Over-Current detection */
+#define FLAGS_NOC			(1<<1)
+	/* Fan failure detection required */
+#define FLAGS_FAN_FAILURE_DET_REQ	(1<<2)
+	/* Initialize first the XGXS and only then the phy itself */
+#define FLAGS_INIT_XGXS_FIRST		(1<<3)
+#define FLAGS_REARM_LATCH_SIGNAL	(1<<6)
+#define FLAGS_SFP_NOT_APPROVED		(1<<7)
+
+	u8 def_md_devad;
+	u8 reserved;
+	/* preemphasis values for the rx side */
+	u16 rx_preemphasis[4];
+
+	/* preemphasis values for the tx side */
+	u16 tx_preemphasis[4];
+
+	/* EMAC address for access MDIO */
+	u32 mdio_ctrl;
+
+	u32 supported;
+
+	u32 media_type;
+#define	ETH_PHY_UNSPECIFIED 0x0
+#define	ETH_PHY_SFP_FIBER   0x1
+#define	ETH_PHY_XFP_FIBER   0x2
+#define	ETH_PHY_DA_TWINAX   0x3
+#define	ETH_PHY_BASE_T      0x4
+#define	ETH_PHY_NOT_PRESENT 0xff
+
+	/* The address in which version is located*/
+	u32 ver_addr;
+
+	u16 req_flow_ctrl;
+
+	u16 req_line_speed;
+
+	u32 speed_cap_mask;
+
+	u16 req_duplex;
+	u16 rsrv;
+	/* Called per phy/port init, and it configures LASI, speed, autoneg,
+	 duplex, flow control negotiation, etc. */
+	config_init_t config_init;
+
+	/* Called due to interrupt. It determines the link, speed */
+	read_status_t read_status;
+
+	/* Called when driver is unloading. Should reset the phy */
+	link_reset_t link_reset;
+
+	/* Set the loopback configuration for the phy */
+	config_loopback_t config_loopback;
+
+	/* Format the given raw number into str up to len */
+	format_fw_ver_t format_fw_ver;
+
+	/* Reset the phy (both ports) */
+	hw_reset_t hw_reset;
+
+	/* Set link led mode (on/off/oper)*/
+	set_link_led_t set_link_led;
+
+	/* PHY Specific tasks */
+	phy_specific_func_t phy_specific_func;
+#define DISABLE_TX	1
+#define ENABLE_TX	2
+};
+
 /* Inputs parameters to the CLC */
 struct link_params {
 
@@ -59,56 +188,50 @@
 #define LOOPBACK_NONE	0
 #define LOOPBACK_EMAC	1
 #define LOOPBACK_BMAC	2
-#define LOOPBACK_XGXS_10	3
+#define LOOPBACK_XGXS		3
 #define LOOPBACK_EXT_PHY	4
 #define LOOPBACK_EXT 	5
 
-	u16 req_duplex;
-	u16 req_flow_ctrl;
-	u16 req_fc_auto_adv; /* Should be set to TX / BOTH when
-	req_flow_ctrl is set to AUTO */
-	u16 req_line_speed; /* Also determine AutoNeg */
-
 	/* Device parameters */
 	u8 mac_addr[6];
 
+	u16 req_duplex[LINK_CONFIG_SIZE];
+	u16 req_flow_ctrl[LINK_CONFIG_SIZE];
+
+	u16 req_line_speed[LINK_CONFIG_SIZE]; /* Also determine AutoNeg */
+
 	/* shmem parameters */
 	u32 shmem_base;
-	u32 speed_cap_mask;
+	u32 shmem2_base;
+	u32 speed_cap_mask[LINK_CONFIG_SIZE];
 	u32 switch_cfg;
 #define SWITCH_CFG_1G		PORT_FEATURE_CON_SWITCH_1G_SWITCH
 #define SWITCH_CFG_10G		PORT_FEATURE_CON_SWITCH_10G_SWITCH
 #define SWITCH_CFG_AUTO_DETECT	PORT_FEATURE_CON_SWITCH_AUTO_DETECT
 
-	u16 hw_led_mode; /* part of the hw_config read from the shmem */
-
-	/* phy_addr populated by the phy_init function */
-	u8 phy_addr;
-	/*u8 reserved1;*/
-
 	u32 lane_config;
-	u32 ext_phy_config;
-#define XGXS_EXT_PHY_TYPE(ext_phy_config) \
-		((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK)
-#define XGXS_EXT_PHY_ADDR(ext_phy_config) \
-		(((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> \
-		 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT)
-#define SERDES_EXT_PHY_TYPE(ext_phy_config) \
-		((ext_phy_config) & PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK)
 
 	/* Phy register parameter */
 	u32 chip_id;
 
-	u16 xgxs_config_rx[4]; /* preemphasis values for the rx side */
-	u16 xgxs_config_tx[4]; /* preemphasis values for the tx side */
-
 	u32 feature_config_flags;
 #define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0)
 #define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY	(1<<2)
-#define FEATURE_CONFIG_BCM8727_NOC			(1<<3)
+#define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY	(1<<3)
+	/* Will be populated during common init */
+	struct bnx2x_phy phy[MAX_PHYS];
+
+	/* Will be populated during common init */
+	u8 num_phys;
+
+	u8 rsrv;
+	u16 hw_led_mode; /* part of the hw_config read from the shmem */
+	u32 multi_phy_config;
 
 	/* Device pointer passed to all callback functions */
 	struct bnx2x *bp;
+	u16 req_fc_auto_adv; /* Should be set to TX / BOTH when
+				req_flow_ctrl is set to AUTO */
 };
 
 /* Output parameters */
@@ -129,12 +252,6 @@
 	u16 flow_ctrl;
 	u16 ieee_fc;
 
-	u32 autoneg;
-#define AUTO_NEG_DISABLED			0x0
-#define AUTO_NEG_ENABLED			0x1
-#define AUTO_NEG_COMPLETE			0x2
-#define AUTO_NEG_PARALLEL_DETECTION_USED	0x3
-
 	/* The same definitions as the shmem parameter */
 	u32 link_status;
 };
@@ -142,8 +259,6 @@
 /***********************************************************/
 /*                         Functions                       */
 /***********************************************************/
-
-/* Initialize the phy */
 u8 bnx2x_phy_init(struct link_params *input, struct link_vars *output);
 
 /* Reset the link. Should be called when driver or interface goes down
@@ -155,17 +270,21 @@
 /* bnx2x_link_update should be called upon link interrupt */
 u8 bnx2x_link_update(struct link_params *input, struct link_vars *output);
 
-/* use the following cl45 functions to read/write from external_phy
+/* use the following phy functions to read/write from external_phy
   In order to use it to read/write internal phy registers, use
   DEFAULT_PHY_DEV_ADDR as devad, and (_bank + (_addr & 0xf)) as
-  Use ext_phy_type of 0 in case of cl22 over cl45
   the register */
-u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
-		 u8 phy_addr, u8 devad, u16 reg, u16 *ret_val);
+u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
+		  u8 devad, u16 reg, u16 *ret_val);
 
-u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
-		  u8 phy_addr, u8 devad, u16 reg, u16 val);
+u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
+		   u8 devad, u16 reg, u16 val);
 
+u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
+		   u8 devad, u16 reg, u16 *ret_val);
+
+u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
+		    u8 devad, u16 reg, u16 val);
 /* Reads the link_status from the shmem,
    and update the link vars accordingly */
 void bnx2x_link_status_update(struct link_params *input,
@@ -178,9 +297,12 @@
    Basically, the CLC takes care of the led for the link, but in case one needs
    to set/unset the led unnaturally, set the "mode" to LED_MODE_OPER to
    blink the led, and LED_MODE_OFF to set the led off.*/
-u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed);
-#define LED_MODE_OFF	0
-#define LED_MODE_OPER 	2
+u8 bnx2x_set_led(struct link_params *params, struct link_vars *vars,
+		 u8 mode, u32 speed);
+#define LED_MODE_OFF			0
+#define LED_MODE_ON			1
+#define LED_MODE_OPER			2
+#define LED_MODE_FRONT_PANEL_OFF	3
 
 u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port, u32 led_idx, u32 value);
 
@@ -190,17 +312,39 @@
 
 /* Get the actual link status. In case it returns 0, link is up,
 	otherwise link is down*/
-u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars);
+u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars,
+		   u8 is_serdes);
 
 /* One-time initialization for external phy after power up */
-u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base);
+u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
+			 u32 shmem2_base_path[], u32 chip_id);
 
 /* Reset the external PHY using GPIO */
 void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
 
-void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr);
+/* Reset the external of SFX7101 */
+void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy);
 
-u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
+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 */
+u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base,
+			  u32 shmem2_base);
+
+/* Returns the aggregative supported attributes of the phys on board */
+u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx);
+
+/* Check swap bit and adjust PHY order */
+u32 bnx2x_phy_selection(struct link_params *params);
+
+/* Probe the phys on board, and populate them in "params" */
+u8 bnx2x_phy_probe(struct link_params *params);
+/* Checks if fan failure detection is required on one of the phys on board */
+u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
+			     u32 shmem2_base, u8 port);
+
 #endif /* BNX2X_LINK_H */
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index f8c3f08..ff99a2f 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -23,7 +23,6 @@
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
-#include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
@@ -57,7 +56,6 @@
 #include "bnx2x_init_ops.h"
 #include "bnx2x_cmn.h"
 
-
 #include <linux/firmware.h>
 #include "bnx2x_fw_file_hdr.h"
 /* FW files */
@@ -66,8 +64,9 @@
 	__stringify(BCM_5710_FW_MINOR_VERSION) "."	\
 	__stringify(BCM_5710_FW_REVISION_VERSION) "."	\
 	__stringify(BCM_5710_FW_ENGINEERING_VERSION)
-#define FW_FILE_NAME_E1		"bnx2x-e1-" FW_FILE_VERSION ".fw"
-#define FW_FILE_NAME_E1H	"bnx2x-e1h-" FW_FILE_VERSION ".fw"
+#define FW_FILE_NAME_E1		"bnx2x/bnx2x-e1-" FW_FILE_VERSION ".fw"
+#define FW_FILE_NAME_E1H	"bnx2x/bnx2x-e1h-" FW_FILE_VERSION ".fw"
+#define FW_FILE_NAME_E2		"bnx2x/bnx2x-e2-" FW_FILE_VERSION ".fw"
 
 /* Time in jiffies before concluding the transmitter is hung */
 #define TX_TIMEOUT		(5*HZ)
@@ -77,18 +76,20 @@
 	DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("Eliezer Tamir");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710/57711/57711E Driver");
+MODULE_DESCRIPTION("Broadcom NetXtreme II "
+		   "BCM57710/57711/57711E/57712/57712E Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 MODULE_FIRMWARE(FW_FILE_NAME_E1);
 MODULE_FIRMWARE(FW_FILE_NAME_E1H);
+MODULE_FIRMWARE(FW_FILE_NAME_E2);
 
 static int multi_mode = 1;
 module_param(multi_mode, int, 0);
 MODULE_PARM_DESC(multi_mode, " Multi queue mode "
 			     "(0 Disable; 1 Enable (default))");
 
-static int num_queues;
+int num_queues;
 module_param(num_queues, int, 0);
 MODULE_PARM_DESC(num_queues, " Number of queues for multi_mode=1"
 				" (default is as a number of CPUs)");
@@ -124,6 +125,8 @@
 	BCM57710 = 0,
 	BCM57711 = 1,
 	BCM57711E = 2,
+	BCM57712 = 3,
+	BCM57712E = 4
 };
 
 /* indexed by board_type, above */
@@ -132,14 +135,24 @@
 } board_info[] __devinitdata = {
 	{ "Broadcom NetXtreme II BCM57710 XGb" },
 	{ "Broadcom NetXtreme II BCM57711 XGb" },
-	{ "Broadcom NetXtreme II BCM57711E XGb" }
+	{ "Broadcom NetXtreme II BCM57711E XGb" },
+	{ "Broadcom NetXtreme II BCM57712 XGb" },
+	{ "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 },
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E },
+	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712), BCM57712 },
+	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712E), BCM57712E },
 	{ 0 }
 };
 
@@ -149,6 +162,244 @@
 * General service functions
 ****************************************************************************/
 
+static inline void __storm_memset_dma_mapping(struct bnx2x *bp,
+				       u32 addr, dma_addr_t mapping)
+{
+	REG_WR(bp,  addr, U64_LO(mapping));
+	REG_WR(bp,  addr + 4, U64_HI(mapping));
+}
+
+static inline void __storm_memset_fill(struct bnx2x *bp,
+				       u32 addr, size_t size, u32 val)
+{
+	int i;
+	for (i = 0; i < size/4; i++)
+		REG_WR(bp,  addr + (i * 4), val);
+}
+
+static inline void storm_memset_ustats_zero(struct bnx2x *bp,
+					    u8 port, u16 stat_id)
+{
+	size_t size = sizeof(struct ustorm_per_client_stats);
+
+	u32 addr = BAR_USTRORM_INTMEM +
+			USTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
+
+	__storm_memset_fill(bp, addr, size, 0);
+}
+
+static inline void storm_memset_tstats_zero(struct bnx2x *bp,
+					    u8 port, u16 stat_id)
+{
+	size_t size = sizeof(struct tstorm_per_client_stats);
+
+	u32 addr = BAR_TSTRORM_INTMEM +
+			TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
+
+	__storm_memset_fill(bp, addr, size, 0);
+}
+
+static inline void storm_memset_xstats_zero(struct bnx2x *bp,
+					    u8 port, u16 stat_id)
+{
+	size_t size = sizeof(struct xstorm_per_client_stats);
+
+	u32 addr = BAR_XSTRORM_INTMEM +
+			XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
+
+	__storm_memset_fill(bp, addr, size, 0);
+}
+
+
+static inline void storm_memset_spq_addr(struct bnx2x *bp,
+					 dma_addr_t mapping, u16 abs_fid)
+{
+	u32 addr = XSEM_REG_FAST_MEMORY +
+			XSTORM_SPQ_PAGE_BASE_OFFSET(abs_fid);
+
+	__storm_memset_dma_mapping(bp, addr, mapping);
+}
+
+static inline void storm_memset_ov(struct bnx2x *bp, u16 ov, u16 abs_fid)
+{
+	REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_E1HOV_OFFSET(abs_fid), ov);
+}
+
+static inline void storm_memset_func_cfg(struct bnx2x *bp,
+				struct tstorm_eth_function_common_config *tcfg,
+				u16 abs_fid)
+{
+	size_t size = sizeof(struct tstorm_eth_function_common_config);
+
+	u32 addr = BAR_TSTRORM_INTMEM +
+			TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
+
+	__storm_memset_struct(bp, addr, size, (u32 *)tcfg);
+}
+
+static inline void storm_memset_xstats_flags(struct bnx2x *bp,
+				struct stats_indication_flags *flags,
+				u16 abs_fid)
+{
+	size_t size = sizeof(struct stats_indication_flags);
+
+	u32 addr = BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(abs_fid);
+
+	__storm_memset_struct(bp, addr, size, (u32 *)flags);
+}
+
+static inline void storm_memset_tstats_flags(struct bnx2x *bp,
+				struct stats_indication_flags *flags,
+				u16 abs_fid)
+{
+	size_t size = sizeof(struct stats_indication_flags);
+
+	u32 addr = BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(abs_fid);
+
+	__storm_memset_struct(bp, addr, size, (u32 *)flags);
+}
+
+static inline void storm_memset_ustats_flags(struct bnx2x *bp,
+				struct stats_indication_flags *flags,
+				u16 abs_fid)
+{
+	size_t size = sizeof(struct stats_indication_flags);
+
+	u32 addr = BAR_USTRORM_INTMEM + USTORM_STATS_FLAGS_OFFSET(abs_fid);
+
+	__storm_memset_struct(bp, addr, size, (u32 *)flags);
+}
+
+static inline void storm_memset_cstats_flags(struct bnx2x *bp,
+				struct stats_indication_flags *flags,
+				u16 abs_fid)
+{
+	size_t size = sizeof(struct stats_indication_flags);
+
+	u32 addr = BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(abs_fid);
+
+	__storm_memset_struct(bp, addr, size, (u32 *)flags);
+}
+
+static inline void storm_memset_xstats_addr(struct bnx2x *bp,
+					   dma_addr_t mapping, u16 abs_fid)
+{
+	u32 addr = BAR_XSTRORM_INTMEM +
+		XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
+
+	__storm_memset_dma_mapping(bp, addr, mapping);
+}
+
+static inline void storm_memset_tstats_addr(struct bnx2x *bp,
+					   dma_addr_t mapping, u16 abs_fid)
+{
+	u32 addr = BAR_TSTRORM_INTMEM +
+		TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
+
+	__storm_memset_dma_mapping(bp, addr, mapping);
+}
+
+static inline void storm_memset_ustats_addr(struct bnx2x *bp,
+					   dma_addr_t mapping, u16 abs_fid)
+{
+	u32 addr = BAR_USTRORM_INTMEM +
+		USTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
+
+	__storm_memset_dma_mapping(bp, addr, mapping);
+}
+
+static inline void storm_memset_cstats_addr(struct bnx2x *bp,
+					   dma_addr_t mapping, u16 abs_fid)
+{
+	u32 addr = BAR_CSTRORM_INTMEM +
+		CSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
+
+	__storm_memset_dma_mapping(bp, addr, mapping);
+}
+
+static inline void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
+					 u16 pf_id)
+{
+	REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_VF_TO_PF_OFFSET(abs_fid),
+		pf_id);
+	REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_VF_TO_PF_OFFSET(abs_fid),
+		pf_id);
+	REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_VF_TO_PF_OFFSET(abs_fid),
+		pf_id);
+	REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_VF_TO_PF_OFFSET(abs_fid),
+		pf_id);
+}
+
+static inline void storm_memset_func_en(struct bnx2x *bp, u16 abs_fid,
+					u8 enable)
+{
+	REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(abs_fid),
+		enable);
+	REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNC_EN_OFFSET(abs_fid),
+		enable);
+	REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNC_EN_OFFSET(abs_fid),
+		enable);
+	REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNC_EN_OFFSET(abs_fid),
+		enable);
+}
+
+static inline void storm_memset_eq_data(struct bnx2x *bp,
+				struct event_ring_data *eq_data,
+				u16 pfid)
+{
+	size_t size = sizeof(struct event_ring_data);
+
+	u32 addr = BAR_CSTRORM_INTMEM + CSTORM_EVENT_RING_DATA_OFFSET(pfid);
+
+	__storm_memset_struct(bp, addr, size, (u32 *)eq_data);
+}
+
+static inline void storm_memset_eq_prod(struct bnx2x *bp, u16 eq_prod,
+					u16 pfid)
+{
+	u32 addr = BAR_CSTRORM_INTMEM + CSTORM_EVENT_RING_PROD_OFFSET(pfid);
+	REG_WR16(bp, addr, eq_prod);
+}
+
+static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
+					     u16 fw_sb_id, u8 sb_index,
+					     u8 ticks)
+{
+
+	int index_offset = CHIP_IS_E2(bp) ?
+		offsetof(struct hc_status_block_data_e2, index_data) :
+		offsetof(struct hc_status_block_data_e1x, index_data);
+	u32 addr = BAR_CSTRORM_INTMEM +
+			CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
+			index_offset +
+			sizeof(struct hc_index_data)*sb_index +
+			offsetof(struct hc_index_data, timeout);
+	REG_WR8(bp, addr, ticks);
+	DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d ticks %d\n",
+			  port, fw_sb_id, sb_index, ticks);
+}
+static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
+					     u16 fw_sb_id, u8 sb_index,
+					     u8 disable)
+{
+	u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
+	int index_offset = CHIP_IS_E2(bp) ?
+		offsetof(struct hc_status_block_data_e2, index_data) :
+		offsetof(struct hc_status_block_data_e1x, index_data);
+	u32 addr = BAR_CSTRORM_INTMEM +
+			CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
+			index_offset +
+			sizeof(struct hc_index_data)*sb_index +
+			offsetof(struct hc_index_data, flags);
+	u16 flags = REG_RD16(bp, addr);
+	/* clear and set */
+	flags &= ~HC_INDEX_DATA_HC_ENABLED;
+	flags |= enable_flag;
+	REG_WR16(bp, addr, flags);
+	DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d disable %d\n",
+			  port, fw_sb_id, sb_index, disable);
+}
+
 /* used only at init
  * locking is done by mcp
  */
@@ -172,6 +423,75 @@
 	return val;
 }
 
+#define DMAE_DP_SRC_GRC		"grc src_addr [%08x]"
+#define DMAE_DP_SRC_PCI		"pci src_addr [%x:%08x]"
+#define DMAE_DP_DST_GRC		"grc dst_addr [%08x]"
+#define DMAE_DP_DST_PCI		"pci dst_addr [%x:%08x]"
+#define DMAE_DP_DST_NONE	"dst_addr [none]"
+
+void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae, int msglvl)
+{
+	u32 src_type = dmae->opcode & DMAE_COMMAND_SRC;
+
+	switch (dmae->opcode & DMAE_COMMAND_DST) {
+	case DMAE_CMD_DST_PCI:
+		if (src_type == DMAE_CMD_SRC_PCI)
+			DP(msglvl, "DMAE: opcode 0x%08x\n"
+			   "src [%x:%08x], len [%d*4], dst [%x:%08x]\n"
+			   "comp_addr [%x:%08x], comp_val 0x%08x\n",
+			   dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
+			   dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo,
+			   dmae->comp_addr_hi, dmae->comp_addr_lo,
+			   dmae->comp_val);
+		else
+			DP(msglvl, "DMAE: opcode 0x%08x\n"
+			   "src [%08x], len [%d*4], dst [%x:%08x]\n"
+			   "comp_addr [%x:%08x], comp_val 0x%08x\n",
+			   dmae->opcode, dmae->src_addr_lo >> 2,
+			   dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo,
+			   dmae->comp_addr_hi, dmae->comp_addr_lo,
+			   dmae->comp_val);
+		break;
+	case DMAE_CMD_DST_GRC:
+		if (src_type == DMAE_CMD_SRC_PCI)
+			DP(msglvl, "DMAE: opcode 0x%08x\n"
+			   "src [%x:%08x], len [%d*4], dst_addr [%08x]\n"
+			   "comp_addr [%x:%08x], comp_val 0x%08x\n",
+			   dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
+			   dmae->len, dmae->dst_addr_lo >> 2,
+			   dmae->comp_addr_hi, dmae->comp_addr_lo,
+			   dmae->comp_val);
+		else
+			DP(msglvl, "DMAE: opcode 0x%08x\n"
+			   "src [%08x], len [%d*4], dst [%08x]\n"
+			   "comp_addr [%x:%08x], comp_val 0x%08x\n",
+			   dmae->opcode, dmae->src_addr_lo >> 2,
+			   dmae->len, dmae->dst_addr_lo >> 2,
+			   dmae->comp_addr_hi, dmae->comp_addr_lo,
+			   dmae->comp_val);
+		break;
+	default:
+		if (src_type == DMAE_CMD_SRC_PCI)
+			DP(msglvl, "DMAE: opcode 0x%08x\n"
+			   DP_LEVEL "src_addr [%x:%08x]  len [%d * 4]  "
+				    "dst_addr [none]\n"
+			   DP_LEVEL "comp_addr [%x:%08x]  comp_val 0x%08x\n",
+			   dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
+			   dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
+			   dmae->comp_val);
+		else
+			DP(msglvl, "DMAE: opcode 0x%08x\n"
+			   DP_LEVEL "src_addr [%08x]  len [%d * 4]  "
+				    "dst_addr [none]\n"
+			   DP_LEVEL "comp_addr [%x:%08x]  comp_val 0x%08x\n",
+			   dmae->opcode, dmae->src_addr_lo >> 2,
+			   dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
+			   dmae->comp_val);
+		break;
+	}
+
+}
+
 const u32 dmae_reg_go_c[] = {
 	DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3,
 	DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7,
@@ -195,12 +515,108 @@
 	REG_WR(bp, dmae_reg_go_c[idx], 1);
 }
 
+u32 bnx2x_dmae_opcode_add_comp(u32 opcode, u8 comp_type)
+{
+	return opcode | ((comp_type << DMAE_COMMAND_C_DST_SHIFT) |
+			   DMAE_CMD_C_ENABLE);
+}
+
+u32 bnx2x_dmae_opcode_clr_src_reset(u32 opcode)
+{
+	return opcode & ~DMAE_CMD_SRC_RESET;
+}
+
+u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
+			     bool with_comp, u8 comp_type)
+{
+	u32 opcode = 0;
+
+	opcode |= ((src_type << DMAE_COMMAND_SRC_SHIFT) |
+		   (dst_type << DMAE_COMMAND_DST_SHIFT));
+
+	opcode |= (DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET);
+
+	opcode |= (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0);
+	opcode |= ((BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT) |
+		   (BP_E1HVN(bp) << DMAE_COMMAND_DST_VN_SHIFT));
+	opcode |= (DMAE_COM_SET_ERR << DMAE_COMMAND_ERR_POLICY_SHIFT);
+
+#ifdef __BIG_ENDIAN
+	opcode |= DMAE_CMD_ENDIANITY_B_DW_SWAP;
+#else
+	opcode |= DMAE_CMD_ENDIANITY_DW_SWAP;
+#endif
+	if (with_comp)
+		opcode = bnx2x_dmae_opcode_add_comp(opcode, comp_type);
+	return opcode;
+}
+
+void bnx2x_prep_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae,
+			       u8 src_type, u8 dst_type)
+{
+	memset(dmae, 0, sizeof(struct dmae_command));
+
+	/* set the opcode */
+	dmae->opcode = bnx2x_dmae_opcode(bp, src_type, dst_type,
+					 true, DMAE_COMP_PCI);
+
+	/* fill in the completion parameters */
+	dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp));
+	dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp));
+	dmae->comp_val = DMAE_COMP_VAL;
+}
+
+/* issue a dmae command over the init-channel and wailt for completion */
+int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae)
+{
+	u32 *wb_comp = bnx2x_sp(bp, wb_comp);
+	int cnt = CHIP_REV_IS_SLOW(bp) ? (400000) : 40;
+	int rc = 0;
+
+	DP(BNX2X_MSG_OFF, "data before [0x%08x 0x%08x 0x%08x 0x%08x]\n",
+	   bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
+	   bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
+
+	/* lock the dmae channel */
+	mutex_lock(&bp->dmae_mutex);
+
+	/* reset completion */
+	*wb_comp = 0;
+
+	/* post the command on the channel used for initializations */
+	bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
+
+	/* wait for completion */
+	udelay(5);
+	while ((*wb_comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) {
+		DP(BNX2X_MSG_OFF, "wb_comp 0x%08x\n", *wb_comp);
+
+		if (!cnt) {
+			BNX2X_ERR("DMAE timeout!\n");
+			rc = DMAE_TIMEOUT;
+			goto unlock;
+		}
+		cnt--;
+		udelay(50);
+	}
+	if (*wb_comp & DMAE_PCI_ERR_FLAG) {
+		BNX2X_ERR("DMAE PCI error!\n");
+		rc = DMAE_PCI_ERROR;
+	}
+
+	DP(BNX2X_MSG_OFF, "data after [0x%08x 0x%08x 0x%08x 0x%08x]\n",
+	   bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
+	   bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
+
+unlock:
+	mutex_unlock(&bp->dmae_mutex);
+	return rc;
+}
+
 void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
 		      u32 len32)
 {
 	struct dmae_command dmae;
-	u32 *wb_comp = bnx2x_sp(bp, wb_comp);
-	int cnt = 200;
 
 	if (!bp->dmae_ready) {
 		u32 *data = bnx2x_sp(bp, wb_data[0]);
@@ -211,69 +627,25 @@
 		return;
 	}
 
-	memset(&dmae, 0, sizeof(struct dmae_command));
+	/* set opcode and fixed command fields */
+	bnx2x_prep_dmae_with_comp(bp, &dmae, DMAE_SRC_PCI, DMAE_DST_GRC);
 
-	dmae.opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
-		       DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
-		       DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
-		       DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
-		       DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
-		       (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
-		       (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+	/* fill in addresses and len */
 	dmae.src_addr_lo = U64_LO(dma_addr);
 	dmae.src_addr_hi = U64_HI(dma_addr);
 	dmae.dst_addr_lo = dst_addr >> 2;
 	dmae.dst_addr_hi = 0;
 	dmae.len = len32;
-	dmae.comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp));
-	dmae.comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp));
-	dmae.comp_val = DMAE_COMP_VAL;
 
-	DP(BNX2X_MSG_OFF, "DMAE: opcode 0x%08x\n"
-	   DP_LEVEL "src_addr  [%x:%08x]  len [%d *4]  "
-		    "dst_addr [%x:%08x (%08x)]\n"
-	   DP_LEVEL "comp_addr [%x:%08x]  comp_val 0x%08x\n",
-	   dmae.opcode, dmae.src_addr_hi, dmae.src_addr_lo,
-	   dmae.len, dmae.dst_addr_hi, dmae.dst_addr_lo, dst_addr,
-	   dmae.comp_addr_hi, dmae.comp_addr_lo, dmae.comp_val);
-	DP(BNX2X_MSG_OFF, "data [0x%08x 0x%08x 0x%08x 0x%08x]\n",
-	   bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
-	   bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
+	bnx2x_dp_dmae(bp, &dmae, BNX2X_MSG_OFF);
 
-	mutex_lock(&bp->dmae_mutex);
-
-	*wb_comp = 0;
-
-	bnx2x_post_dmae(bp, &dmae, INIT_DMAE_C(bp));
-
-	udelay(5);
-
-	while (*wb_comp != DMAE_COMP_VAL) {
-		DP(BNX2X_MSG_OFF, "wb_comp 0x%08x\n", *wb_comp);
-
-		if (!cnt) {
-			BNX2X_ERR("DMAE timeout!\n");
-			break;
-		}
-		cnt--;
-		/* adjust delay for emulation/FPGA */
-		if (CHIP_REV_IS_SLOW(bp))
-			msleep(100);
-		else
-			udelay(5);
-	}
-
-	mutex_unlock(&bp->dmae_mutex);
+	/* issue the command and wait for completion */
+	bnx2x_issue_dmae_with_comp(bp, &dmae);
 }
 
 void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
 {
 	struct dmae_command dmae;
-	u32 *wb_comp = bnx2x_sp(bp, wb_comp);
-	int cnt = 200;
 
 	if (!bp->dmae_ready) {
 		u32 *data = bnx2x_sp(bp, wb_data[0]);
@@ -286,62 +658,20 @@
 		return;
 	}
 
-	memset(&dmae, 0, sizeof(struct dmae_command));
+	/* set opcode and fixed command fields */
+	bnx2x_prep_dmae_with_comp(bp, &dmae, DMAE_SRC_GRC, DMAE_DST_PCI);
 
-	dmae.opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
-		       DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
-		       DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
-		       DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
-		       DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
-		       (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
-		       (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+	/* fill in addresses and len */
 	dmae.src_addr_lo = src_addr >> 2;
 	dmae.src_addr_hi = 0;
 	dmae.dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_data));
 	dmae.dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_data));
 	dmae.len = len32;
-	dmae.comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp));
-	dmae.comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp));
-	dmae.comp_val = DMAE_COMP_VAL;
 
-	DP(BNX2X_MSG_OFF, "DMAE: opcode 0x%08x\n"
-	   DP_LEVEL "src_addr  [%x:%08x]  len [%d *4]  "
-		    "dst_addr [%x:%08x (%08x)]\n"
-	   DP_LEVEL "comp_addr [%x:%08x]  comp_val 0x%08x\n",
-	   dmae.opcode, dmae.src_addr_hi, dmae.src_addr_lo,
-	   dmae.len, dmae.dst_addr_hi, dmae.dst_addr_lo, src_addr,
-	   dmae.comp_addr_hi, dmae.comp_addr_lo, dmae.comp_val);
+	bnx2x_dp_dmae(bp, &dmae, BNX2X_MSG_OFF);
 
-	mutex_lock(&bp->dmae_mutex);
-
-	memset(bnx2x_sp(bp, wb_data[0]), 0, sizeof(u32) * 4);
-	*wb_comp = 0;
-
-	bnx2x_post_dmae(bp, &dmae, INIT_DMAE_C(bp));
-
-	udelay(5);
-
-	while (*wb_comp != DMAE_COMP_VAL) {
-
-		if (!cnt) {
-			BNX2X_ERR("DMAE timeout!\n");
-			break;
-		}
-		cnt--;
-		/* adjust delay for emulation/FPGA */
-		if (CHIP_REV_IS_SLOW(bp))
-			msleep(100);
-		else
-			udelay(5);
-	}
-	DP(BNX2X_MSG_OFF, "data [0x%08x 0x%08x 0x%08x 0x%08x]\n",
-	   bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
-	   bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
-
-	mutex_unlock(&bp->dmae_mutex);
+	/* issue the command and wait for completion */
+	bnx2x_issue_dmae_with_comp(bp, &dmae);
 }
 
 void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
@@ -508,19 +838,24 @@
 	u32 mark, offset;
 	__be32 data[9];
 	int word;
-
+	u32 trace_shmem_base;
 	if (BP_NOMCP(bp)) {
 		BNX2X_ERR("NO MCP - can not dump\n");
 		return;
 	}
 
-	addr = bp->common.shmem_base - 0x0800 + 4;
+	if (BP_PATH(bp) == 0)
+		trace_shmem_base = bp->common.shmem_base;
+	else
+		trace_shmem_base = SHMEM2_RD(bp, other_shmem_base_addr);
+	addr = trace_shmem_base - 0x0800 + 4;
 	mark = REG_RD(bp, addr);
-	mark = MCP_REG_MCPR_SCRATCH + ((mark + 0x3) & ~0x3) - 0x08000000;
+	mark = (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
+			+ ((mark + 0x3) & ~0x3) - 0x08000000;
 	pr_err("begin fw dump (mark 0x%x)\n", mark);
 
 	pr_err("");
-	for (offset = mark; offset <= bp->common.shmem_base; offset += 0x8*4) {
+	for (offset = mark; offset <= trace_shmem_base; offset += 0x8*4) {
 		for (word = 0; word < 8; word++)
 			data[word] = htonl(REG_RD(bp, offset + 4*word));
 		data[8] = 0x0;
@@ -538,7 +873,12 @@
 void bnx2x_panic_dump(struct bnx2x *bp)
 {
 	int i;
-	u16 j, start, end;
+	u16 j;
+	struct hc_sp_status_block_data sp_sb_data;
+	int func = BP_FUNC(bp);
+#ifdef BNX2X_STOP_ON_ERROR
+	u16 start = 0, end = 0;
+#endif
 
 	bp->stats_state = STATS_STATE_DISABLED;
 	DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
@@ -547,44 +887,143 @@
 
 	/* Indices */
 	/* Common */
-	BNX2X_ERR("def_c_idx(0x%x)  def_u_idx(0x%x)  def_x_idx(0x%x)"
-		  "  def_t_idx(0x%x)  def_att_idx(0x%x)  attn_state(0x%x)"
+	BNX2X_ERR("def_idx(0x%x)  def_att_idx(0x%x)  attn_state(0x%x)"
 		  "  spq_prod_idx(0x%x)\n",
-		  bp->def_c_idx, bp->def_u_idx, bp->def_x_idx, bp->def_t_idx,
-		  bp->def_att_idx, bp->attn_state, bp->spq_prod_idx);
+		  bp->def_idx, bp->def_att_idx,
+		  bp->attn_state, bp->spq_prod_idx);
+	BNX2X_ERR("DSB: attn bits(0x%x)  ack(0x%x)  id(0x%x)  idx(0x%x)\n",
+		  bp->def_status_blk->atten_status_block.attn_bits,
+		  bp->def_status_blk->atten_status_block.attn_bits_ack,
+		  bp->def_status_blk->atten_status_block.status_block_id,
+		  bp->def_status_blk->atten_status_block.attn_bits_index);
+	BNX2X_ERR("     def (");
+	for (i = 0; i < HC_SP_SB_MAX_INDICES; i++)
+		pr_cont("0x%x%s",
+		       bp->def_status_blk->sp_sb.index_values[i],
+		       (i == HC_SP_SB_MAX_INDICES - 1) ? ")  " : " ");
 
-	/* Rx */
+	for (i = 0; i < sizeof(struct hc_sp_status_block_data)/sizeof(u32); i++)
+		*((u32 *)&sp_sb_data + i) = REG_RD(bp, BAR_CSTRORM_INTMEM +
+			CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
+			i*sizeof(u32));
+
+	pr_cont("igu_sb_id(0x%x)  igu_seg_id (0x%x) "
+			 "pf_id(0x%x)  vnic_id(0x%x)  "
+			 "vf_id(0x%x)  vf_valid (0x%x)\n",
+	       sp_sb_data.igu_sb_id,
+	       sp_sb_data.igu_seg_id,
+	       sp_sb_data.p_func.pf_id,
+	       sp_sb_data.p_func.vnic_id,
+	       sp_sb_data.p_func.vf_id,
+	       sp_sb_data.p_func.vf_valid);
+
+
 	for_each_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
+		int loop;
+		struct hc_status_block_data_e2 sb_data_e2;
+		struct hc_status_block_data_e1x sb_data_e1x;
+		struct hc_status_block_sm  *hc_sm_p =
+			CHIP_IS_E2(bp) ?
+			sb_data_e2.common.state_machine :
+			sb_data_e1x.common.state_machine;
+		struct hc_index_data *hc_index_p =
+			CHIP_IS_E2(bp) ?
+			sb_data_e2.index_data :
+			sb_data_e1x.index_data;
+		int data_size;
+		u32 *sb_data_p;
 
+		/* Rx */
 		BNX2X_ERR("fp%d: rx_bd_prod(0x%x)  rx_bd_cons(0x%x)"
-			  "  *rx_bd_cons_sb(0x%x)  rx_comp_prod(0x%x)"
+			  "  rx_comp_prod(0x%x)"
 			  "  rx_comp_cons(0x%x)  *rx_cons_sb(0x%x)\n",
 			  i, fp->rx_bd_prod, fp->rx_bd_cons,
-			  le16_to_cpu(*fp->rx_bd_cons_sb), fp->rx_comp_prod,
+			  fp->rx_comp_prod,
 			  fp->rx_comp_cons, le16_to_cpu(*fp->rx_cons_sb));
 		BNX2X_ERR("     rx_sge_prod(0x%x)  last_max_sge(0x%x)"
-			  "  fp_u_idx(0x%x) *sb_u_idx(0x%x)\n",
+			  "  fp_hc_idx(0x%x)\n",
 			  fp->rx_sge_prod, fp->last_max_sge,
-			  le16_to_cpu(fp->fp_u_idx),
-			  fp->status_blk->u_status_block.status_block_index);
-	}
+			  le16_to_cpu(fp->fp_hc_idx));
 
-	/* Tx */
-	for_each_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-
+		/* Tx */
 		BNX2X_ERR("fp%d: tx_pkt_prod(0x%x)  tx_pkt_cons(0x%x)"
 			  "  tx_bd_prod(0x%x)  tx_bd_cons(0x%x)"
 			  "  *tx_cons_sb(0x%x)\n",
 			  i, fp->tx_pkt_prod, fp->tx_pkt_cons, fp->tx_bd_prod,
 			  fp->tx_bd_cons, le16_to_cpu(*fp->tx_cons_sb));
-		BNX2X_ERR("     fp_c_idx(0x%x)  *sb_c_idx(0x%x)"
-			  "  tx_db_prod(0x%x)\n", le16_to_cpu(fp->fp_c_idx),
-			  fp->status_blk->c_status_block.status_block_index,
-			  fp->tx_db.data.prod);
+
+		loop = CHIP_IS_E2(bp) ?
+			HC_SB_MAX_INDICES_E2 : HC_SB_MAX_INDICES_E1X;
+
+		/* host sb data */
+
+		BNX2X_ERR("     run indexes (");
+		for (j = 0; j < HC_SB_MAX_SM; j++)
+			pr_cont("0x%x%s",
+			       fp->sb_running_index[j],
+			       (j == HC_SB_MAX_SM - 1) ? ")" : " ");
+
+		BNX2X_ERR("     indexes (");
+		for (j = 0; j < loop; j++)
+			pr_cont("0x%x%s",
+			       fp->sb_index_values[j],
+			       (j == loop - 1) ? ")" : " ");
+		/* fw sb data */
+		data_size = CHIP_IS_E2(bp) ?
+			sizeof(struct hc_status_block_data_e2) :
+			sizeof(struct hc_status_block_data_e1x);
+		data_size /= sizeof(u32);
+		sb_data_p = CHIP_IS_E2(bp) ?
+			(u32 *)&sb_data_e2 :
+			(u32 *)&sb_data_e1x;
+		/* copy sb data in here */
+		for (j = 0; j < data_size; j++)
+			*(sb_data_p + j) = REG_RD(bp, BAR_CSTRORM_INTMEM +
+				CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id) +
+				j * sizeof(u32));
+
+		if (CHIP_IS_E2(bp)) {
+			pr_cont("pf_id(0x%x)  vf_id (0x%x)  vf_valid(0x%x) "
+				"vnic_id(0x%x)  same_igu_sb_1b(0x%x)\n",
+				sb_data_e2.common.p_func.pf_id,
+				sb_data_e2.common.p_func.vf_id,
+				sb_data_e2.common.p_func.vf_valid,
+				sb_data_e2.common.p_func.vnic_id,
+				sb_data_e2.common.same_igu_sb_1b);
+		} else {
+			pr_cont("pf_id(0x%x)  vf_id (0x%x)  vf_valid(0x%x) "
+				"vnic_id(0x%x)  same_igu_sb_1b(0x%x)\n",
+				sb_data_e1x.common.p_func.pf_id,
+				sb_data_e1x.common.p_func.vf_id,
+				sb_data_e1x.common.p_func.vf_valid,
+				sb_data_e1x.common.p_func.vnic_id,
+				sb_data_e1x.common.same_igu_sb_1b);
+		}
+
+		/* SB_SMs data */
+		for (j = 0; j < HC_SB_MAX_SM; j++) {
+			pr_cont("SM[%d] __flags (0x%x) "
+			       "igu_sb_id (0x%x)  igu_seg_id(0x%x) "
+			       "time_to_expire (0x%x) "
+			       "timer_value(0x%x)\n", j,
+			       hc_sm_p[j].__flags,
+			       hc_sm_p[j].igu_sb_id,
+			       hc_sm_p[j].igu_seg_id,
+			       hc_sm_p[j].time_to_expire,
+			       hc_sm_p[j].timer_value);
+		}
+
+		/* Indecies data */
+		for (j = 0; j < loop; j++) {
+			pr_cont("INDEX[%d] flags (0x%x) "
+					 "timeout (0x%x)\n", j,
+			       hc_index_p[j].flags,
+			       hc_index_p[j].timeout);
+		}
 	}
 
+#ifdef BNX2X_STOP_ON_ERROR
 	/* Rings */
 	/* Rx */
 	for_each_queue(bp, i) {
@@ -642,13 +1081,13 @@
 				  i, j, tx_bd[0], tx_bd[1], tx_bd[2], tx_bd[3]);
 		}
 	}
-
+#endif
 	bnx2x_fw_dump(bp);
 	bnx2x_mc_assert(bp);
 	BNX2X_ERR("end crash dump -----------------\n");
 }
 
-void bnx2x_int_enable(struct bnx2x *bp)
+static void bnx2x_hc_int_enable(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
 	u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
@@ -672,14 +1111,19 @@
 			HC_CONFIG_0_REG_INT_LINE_EN_0 |
 			HC_CONFIG_0_REG_ATTN_BIT_EN_0);
 
-		DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)\n",
-		   val, port, addr);
+		if (!CHIP_IS_E1(bp)) {
+			DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)\n",
+			   val, port, addr);
 
-		REG_WR(bp, addr, val);
+			REG_WR(bp, addr, val);
 
-		val &= ~HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0;
+			val &= ~HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0;
+		}
 	}
 
+	if (CHIP_IS_E1(bp))
+		REG_WR(bp, HC_REG_INT_MASK + port*4, 0x1FFFF);
+
 	DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)  mode %s\n",
 	   val, port, addr, (msix ? "MSI-X" : (msi ? "MSI" : "INTx")));
 
@@ -690,9 +1134,9 @@
 	mmiowb();
 	barrier();
 
-	if (CHIP_IS_E1H(bp)) {
+	if (!CHIP_IS_E1(bp)) {
 		/* init leading/trailing edge */
-		if (IS_E1HMF(bp)) {
+		if (IS_MF(bp)) {
 			val = (0xee0f | (1 << (BP_E1HVN(bp) + 4)));
 			if (bp->port.pmf)
 				/* enable nig and gpio3 attention */
@@ -708,16 +1152,91 @@
 	mmiowb();
 }
 
-static void bnx2x_int_disable(struct bnx2x *bp)
+static void bnx2x_igu_int_enable(struct bnx2x *bp)
+{
+	u32 val;
+	int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
+	int msi = (bp->flags & USING_MSI_FLAG) ? 1 : 0;
+
+	val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
+
+	if (msix) {
+		val &= ~(IGU_PF_CONF_INT_LINE_EN |
+			 IGU_PF_CONF_SINGLE_ISR_EN);
+		val |= (IGU_PF_CONF_FUNC_EN |
+			IGU_PF_CONF_MSI_MSIX_EN |
+			IGU_PF_CONF_ATTN_BIT_EN);
+	} else if (msi) {
+		val &= ~IGU_PF_CONF_INT_LINE_EN;
+		val |= (IGU_PF_CONF_FUNC_EN |
+			IGU_PF_CONF_MSI_MSIX_EN |
+			IGU_PF_CONF_ATTN_BIT_EN |
+			IGU_PF_CONF_SINGLE_ISR_EN);
+	} else {
+		val &= ~IGU_PF_CONF_MSI_MSIX_EN;
+		val |= (IGU_PF_CONF_FUNC_EN |
+			IGU_PF_CONF_INT_LINE_EN |
+			IGU_PF_CONF_ATTN_BIT_EN |
+			IGU_PF_CONF_SINGLE_ISR_EN);
+	}
+
+	DP(NETIF_MSG_INTR, "write 0x%x to IGU  mode %s\n",
+	   val, (msix ? "MSI-X" : (msi ? "MSI" : "INTx")));
+
+	REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
+
+	barrier();
+
+	/* init leading/trailing edge */
+	if (IS_MF(bp)) {
+		val = (0xee0f | (1 << (BP_E1HVN(bp) + 4)));
+		if (bp->port.pmf)
+			/* enable nig and gpio3 attention */
+			val |= 0x1100;
+	} else
+		val = 0xffff;
+
+	REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, val);
+	REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, val);
+
+	/* Make sure that interrupts are indeed enabled from here on */
+	mmiowb();
+}
+
+void bnx2x_int_enable(struct bnx2x *bp)
+{
+	if (bp->common.int_block == INT_BLOCK_HC)
+		bnx2x_hc_int_enable(bp);
+	else
+		bnx2x_igu_int_enable(bp);
+}
+
+static void bnx2x_hc_int_disable(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
 	u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
 	u32 val = REG_RD(bp, addr);
 
-	val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
-		 HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
-		 HC_CONFIG_0_REG_INT_LINE_EN_0 |
-		 HC_CONFIG_0_REG_ATTN_BIT_EN_0);
+	/*
+	 * in E1 we must use only PCI configuration space to disable
+	 * MSI/MSIX capablility
+	 * It's forbitten to disable IGU_PF_CONF_MSI_MSIX_EN in HC block
+	 */
+	if (CHIP_IS_E1(bp)) {
+		/*  Since IGU_PF_CONF_MSI_MSIX_EN still always on
+		 *  Use mask register to prevent from HC sending interrupts
+		 *  after we exit the function
+		 */
+		REG_WR(bp, HC_REG_INT_MASK + port*4, 0);
+
+		val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
+			 HC_CONFIG_0_REG_INT_LINE_EN_0 |
+			 HC_CONFIG_0_REG_ATTN_BIT_EN_0);
+	} else
+		val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
+			 HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
+			 HC_CONFIG_0_REG_INT_LINE_EN_0 |
+			 HC_CONFIG_0_REG_ATTN_BIT_EN_0);
 
 	DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)\n",
 	   val, port, addr);
@@ -730,6 +1249,32 @@
 		BNX2X_ERR("BUG! proper val not read from IGU!\n");
 }
 
+static void bnx2x_igu_int_disable(struct bnx2x *bp)
+{
+	u32 val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
+
+	val &= ~(IGU_PF_CONF_MSI_MSIX_EN |
+		 IGU_PF_CONF_INT_LINE_EN |
+		 IGU_PF_CONF_ATTN_BIT_EN);
+
+	DP(NETIF_MSG_INTR, "write %x to IGU\n", val);
+
+	/* flush all outstanding writes */
+	mmiowb();
+
+	REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
+	if (REG_RD(bp, IGU_REG_PF_CONFIGURATION) != val)
+		BNX2X_ERR("BUG! proper val not read from IGU!\n");
+}
+
+void bnx2x_int_disable(struct bnx2x *bp)
+{
+	if (bp->common.int_block == INT_BLOCK_HC)
+		bnx2x_hc_int_disable(bp);
+	else
+		bnx2x_igu_int_disable(bp);
+}
+
 void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
 {
 	int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
@@ -781,7 +1326,7 @@
 		DP(NETIF_MSG_HW,
 		   "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n",
 		   resource, HW_LOCK_MAX_RESOURCE_VALUE);
-		return -EINVAL;
+		return false;
 	}
 
 	if (func <= 5)
@@ -800,7 +1345,6 @@
 	return false;
 }
 
-
 #ifdef BCM_CNIC
 static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid);
 #endif
@@ -817,76 +1361,35 @@
 	   fp->index, cid, command, bp->state,
 	   rr_cqe->ramrod_cqe.ramrod_type);
 
-	bp->spq_left++;
-
-	if (fp->index) {
-		switch (command | fp->state) {
-		case (RAMROD_CMD_ID_ETH_CLIENT_SETUP |
-						BNX2X_FP_STATE_OPENING):
-			DP(NETIF_MSG_IFUP, "got MULTI[%d] setup ramrod\n",
-			   cid);
-			fp->state = BNX2X_FP_STATE_OPEN;
-			break;
-
-		case (RAMROD_CMD_ID_ETH_HALT | BNX2X_FP_STATE_HALTING):
-			DP(NETIF_MSG_IFDOWN, "got MULTI[%d] halt ramrod\n",
-			   cid);
-			fp->state = BNX2X_FP_STATE_HALTED;
-			break;
-
-		default:
-			BNX2X_ERR("unexpected MC reply (%d)  "
-				  "fp[%d] state is %x\n",
-				  command, fp->index, fp->state);
-			break;
-		}
-		mb(); /* force bnx2x_wait_ramrod() to see the change */
-		return;
-	}
-
-	switch (command | bp->state) {
-	case (RAMROD_CMD_ID_ETH_PORT_SETUP | BNX2X_STATE_OPENING_WAIT4_PORT):
-		DP(NETIF_MSG_IFUP, "got setup ramrod\n");
-		bp->state = BNX2X_STATE_OPEN;
+	switch (command | fp->state) {
+	case (RAMROD_CMD_ID_ETH_CLIENT_SETUP | BNX2X_FP_STATE_OPENING):
+		DP(NETIF_MSG_IFUP, "got MULTI[%d] setup ramrod\n", cid);
+		fp->state = BNX2X_FP_STATE_OPEN;
 		break;
 
-	case (RAMROD_CMD_ID_ETH_HALT | BNX2X_STATE_CLOSING_WAIT4_HALT):
-		DP(NETIF_MSG_IFDOWN, "got halt ramrod\n");
-		bp->state = BNX2X_STATE_CLOSING_WAIT4_DELETE;
+	case (RAMROD_CMD_ID_ETH_HALT | BNX2X_FP_STATE_HALTING):
+		DP(NETIF_MSG_IFDOWN, "got MULTI[%d] halt ramrod\n", cid);
 		fp->state = BNX2X_FP_STATE_HALTED;
 		break;
 
-	case (RAMROD_CMD_ID_ETH_CFC_DEL | BNX2X_STATE_CLOSING_WAIT4_HALT):
-		DP(NETIF_MSG_IFDOWN, "got delete ramrod for MULTI[%d]\n", cid);
-		bnx2x_fp(bp, cid, state) = BNX2X_FP_STATE_CLOSED;
-		break;
-
-#ifdef BCM_CNIC
-	case (RAMROD_CMD_ID_ETH_CFC_DEL | BNX2X_STATE_OPEN):
-		DP(NETIF_MSG_IFDOWN, "got delete ramrod for CID %d\n", cid);
-		bnx2x_cnic_cfc_comp(bp, cid);
-		break;
-#endif
-
-	case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_OPEN):
-	case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_DIAG):
-		DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
-		bp->set_mac_pending--;
-		smp_wmb();
-		break;
-
-	case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_CLOSING_WAIT4_HALT):
-		DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
-		bp->set_mac_pending--;
-		smp_wmb();
+	case (RAMROD_CMD_ID_ETH_TERMINATE | BNX2X_FP_STATE_TERMINATING):
+		DP(NETIF_MSG_IFDOWN, "got MULTI[%d] teminate ramrod\n", cid);
+		fp->state = BNX2X_FP_STATE_TERMINATED;
 		break;
 
 	default:
-		BNX2X_ERR("unexpected MC reply (%d)  bp->state is %x\n",
-			  command, bp->state);
+		BNX2X_ERR("unexpected MC reply (%d)  "
+			  "fp[%d] state is %x\n",
+			  command, fp->index, fp->state);
 		break;
 	}
-	mb(); /* force bnx2x_wait_ramrod() to see the change */
+
+	smp_mb__before_atomic_inc();
+	atomic_inc(&bp->spq_left);
+	/* push the change in fp->state and towards the memory */
+	smp_wmb();
+
+	return;
 }
 
 irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
@@ -914,25 +1417,22 @@
 		return IRQ_HANDLED;
 #endif
 
-	for (i = 0; i < BNX2X_NUM_QUEUES(bp); i++) {
+	for_each_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 
-		mask = 0x2 << fp->sb_id;
+		mask = 0x2 << (fp->index + CNIC_CONTEXT_USE);
 		if (status & mask) {
 			/* Handle Rx and Tx according to SB id */
 			prefetch(fp->rx_cons_sb);
-			prefetch(&fp->status_blk->u_status_block.
-						status_block_index);
 			prefetch(fp->tx_cons_sb);
-			prefetch(&fp->status_blk->c_status_block.
-						status_block_index);
+			prefetch(&fp->sb_running_index[SM_RX_ID]);
 			napi_schedule(&bnx2x_fp(bp, fp->index, napi));
 			status &= ~mask;
 		}
 	}
 
 #ifdef BCM_CNIC
-	mask = 0x2 << CNIC_SB_ID(bp);
+	mask = 0x2;
 	if (status & (mask | 0x1)) {
 		struct cnic_ops *c_ops = NULL;
 
@@ -1227,49 +1727,91 @@
 	return 0;
 }
 
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
+{
+	u32 sel_phy_idx = 0;
+	if (bp->link_vars.link_up) {
+		sel_phy_idx = EXT_PHY1;
+		/* In case link is SERDES, check if the EXT_PHY2 is the one */
+		if ((bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) &&
+		    (bp->link_params.phy[EXT_PHY2].supported & SUPPORTED_FIBRE))
+			sel_phy_idx = EXT_PHY2;
+	} else {
+
+		switch (bnx2x_phy_selection(&bp->link_params)) {
+		case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
+		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
+		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
+		       sel_phy_idx = EXT_PHY1;
+		       break;
+		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
+		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
+		       sel_phy_idx = EXT_PHY2;
+		       break;
+		}
+	}
+	/*
+	* The selected actived PHY is always after swapping (in case PHY
+	* swapping is enabled). So when swapping is enabled, we need to reverse
+	* the configuration
+	*/
+
+	if (bp->link_params.multi_phy_config &
+	    PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
+		if (sel_phy_idx == EXT_PHY1)
+			sel_phy_idx = EXT_PHY2;
+		else if (sel_phy_idx == EXT_PHY2)
+			sel_phy_idx = EXT_PHY1;
+	}
+	return LINK_CONFIG_IDX(sel_phy_idx);
+}
+
 void bnx2x_calc_fc_adv(struct bnx2x *bp)
 {
+	u8 cfg_idx = bnx2x_get_link_cfg_idx(bp);
 	switch (bp->link_vars.ieee_fc &
 		MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) {
 	case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE:
-		bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
-					  ADVERTISED_Pause);
+		bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause |
+						   ADVERTISED_Pause);
 		break;
 
 	case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH:
-		bp->port.advertising |= (ADVERTISED_Asym_Pause |
-					 ADVERTISED_Pause);
+		bp->port.advertising[cfg_idx] |= (ADVERTISED_Asym_Pause |
+						  ADVERTISED_Pause);
 		break;
 
 	case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC:
-		bp->port.advertising |= ADVERTISED_Asym_Pause;
+		bp->port.advertising[cfg_idx] |= ADVERTISED_Asym_Pause;
 		break;
 
 	default:
-		bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
-					  ADVERTISED_Pause);
+		bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause |
+						   ADVERTISED_Pause);
 		break;
 	}
 }
 
-
 u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 {
 	if (!BP_NOMCP(bp)) {
 		u8 rc;
-
+		int cfx_idx = bnx2x_get_link_cfg_idx(bp);
+		u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx];
 		/* Initialize link parameters structure variables */
 		/* It is recommended to turn off RX FC for jumbo frames
 		   for better performance */
-		if (bp->dev->mtu > 5000)
+		if ((CHIP_IS_E1x(bp)) && (bp->dev->mtu > 5000))
 			bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX;
 		else
 			bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
 
 		bnx2x_acquire_phy_lock(bp);
 
-		if (load_mode == LOAD_DIAG)
-			bp->link_params.loopback_mode = LOOPBACK_XGXS_10;
+		if (load_mode == LOAD_DIAG) {
+			bp->link_params.loopback_mode = LOOPBACK_XGXS;
+			bp->link_params.req_line_speed[cfx_idx] = SPEED_10000;
+		}
 
 		rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
 
@@ -1281,7 +1823,7 @@
 			bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
 			bnx2x_link_report(bp);
 		}
-
+		bp->link_params.req_line_speed[cfx_idx] = req_line_speed;
 		return rc;
 	}
 	BNX2X_ERR("Bootcode is missing - can not initialize link\n");
@@ -1292,6 +1834,7 @@
 {
 	if (!BP_NOMCP(bp)) {
 		bnx2x_acquire_phy_lock(bp);
+		bnx2x_link_reset(&bp->link_params, &bp->link_vars, 1);
 		bnx2x_phy_init(&bp->link_params, &bp->link_vars);
 		bnx2x_release_phy_lock(bp);
 
@@ -1310,13 +1853,14 @@
 		BNX2X_ERR("Bootcode is missing - can not reset link\n");
 }
 
-u8 bnx2x_link_test(struct bnx2x *bp)
+u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes)
 {
 	u8 rc = 0;
 
 	if (!BP_NOMCP(bp)) {
 		bnx2x_acquire_phy_lock(bp);
-		rc = bnx2x_test_link(&bp->link_params, &bp->link_vars);
+		rc = bnx2x_test_link(&bp->link_params, &bp->link_vars,
+				     is_serdes);
 		bnx2x_release_phy_lock(bp);
 	} else
 		BNX2X_ERR("Bootcode is missing - can not test link\n");
@@ -1371,13 +1915,11 @@
 static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
 {
 	int all_zero = 1;
-	int port = BP_PORT(bp);
 	int vn;
 
 	bp->vn_weight_sum = 0;
 	for (vn = VN_0; vn < E1HVN_MAX; vn++) {
-		int func = 2*vn + port;
-		u32 vn_cfg = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
+		u32 vn_cfg = bp->mf_config[vn];
 		u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
 				   FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
 
@@ -1405,11 +1947,12 @@
 					CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
 }
 
-static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func)
+static void bnx2x_init_vn_minmax(struct bnx2x *bp, int vn)
 {
 	struct rate_shaping_vars_per_vn m_rs_vn;
 	struct fairness_vars_per_vn m_fair_vn;
-	u32 vn_cfg = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
+	u32 vn_cfg = bp->mf_config[vn];
+	int func = 2*vn + BP_PORT(bp);
 	u16 vn_min_rate, vn_max_rate;
 	int i;
 
@@ -1422,11 +1965,12 @@
 		vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
 				FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
 		/* If min rate is zero - set it to 1 */
-		if (!vn_min_rate)
+		if (bp->vn_weight_sum && (vn_min_rate == 0))
 			vn_min_rate = DEF_MIN_RATE;
 		vn_max_rate = ((vn_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
 				FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
 	}
+
 	DP(NETIF_MSG_IFUP,
 	   "func %d: vn_min_rate %d  vn_max_rate %d  vn_weight_sum %d\n",
 	   func, vn_min_rate, vn_max_rate, bp->vn_weight_sum);
@@ -1467,6 +2011,83 @@
 		       ((u32 *)(&m_fair_vn))[i]);
 }
 
+static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp)
+{
+	if (CHIP_REV_IS_SLOW(bp))
+		return CMNG_FNS_NONE;
+	if (IS_MF(bp))
+		return CMNG_FNS_MINMAX;
+
+	return CMNG_FNS_NONE;
+}
+
+static void bnx2x_read_mf_cfg(struct bnx2x *bp)
+{
+	int vn;
+
+	if (BP_NOMCP(bp))
+		return; /* what should be the default bvalue in this case */
+
+	for (vn = VN_0; vn < E1HVN_MAX; vn++) {
+		int /*abs*/func = 2*vn + BP_PORT(bp);
+		bp->mf_config[vn] =
+			MF_CFG_RD(bp, func_mf_config[func].config);
+	}
+}
+
+static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type)
+{
+
+	if (cmng_type == CMNG_FNS_MINMAX) {
+		int vn;
+
+		/* clear cmng_enables */
+		bp->cmng.flags.cmng_enables = 0;
+
+		/* read mf conf from shmem */
+		if (read_cfg)
+			bnx2x_read_mf_cfg(bp);
+
+		/* Init rate shaping and fairness contexts */
+		bnx2x_init_port_minmax(bp);
+
+		/* vn_weight_sum and enable fairness if not 0 */
+		bnx2x_calc_vn_weight_sum(bp);
+
+		/* calculate and set min-max rate for each vn */
+		for (vn = VN_0; vn < E1HVN_MAX; vn++)
+			bnx2x_init_vn_minmax(bp, vn);
+
+		/* always enable rate shaping and fairness */
+		bp->cmng.flags.cmng_enables |=
+					CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN;
+		if (!bp->vn_weight_sum)
+			DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
+				   "  fairness will be disabled\n");
+		return;
+	}
+
+	/* rate shaping and fairness are disabled */
+	DP(NETIF_MSG_IFUP,
+	   "rate shaping and fairness are disabled\n");
+}
+
+static inline void bnx2x_link_sync_notify(struct bnx2x *bp)
+{
+	int port = BP_PORT(bp);
+	int func;
+	int vn;
+
+	/* Set the attention towards other drivers on the same port */
+	for (vn = VN_0; vn < E1HVN_MAX; vn++) {
+		if (vn == BP_E1HVN(bp))
+			continue;
+
+		func = ((vn << 1) | port);
+		REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
+		       (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
+	}
+}
 
 /* This function is called upon link interrupt */
 static void bnx2x_link_attn(struct bnx2x *bp)
@@ -1480,7 +2101,7 @@
 	if (bp->link_vars.link_up) {
 
 		/* dropless flow control */
-		if (CHIP_IS_E1H(bp) && bp->dropless_fc) {
+		if (!CHIP_IS_E1(bp) && bp->dropless_fc) {
 			int port = BP_PORT(bp);
 			u32 pause_enabled = 0;
 
@@ -1508,37 +2129,19 @@
 	if (prev_link_status != bp->link_vars.link_status)
 		bnx2x_link_report(bp);
 
-	if (IS_E1HMF(bp)) {
-		int port = BP_PORT(bp);
-		int func;
-		int vn;
+	if (IS_MF(bp))
+		bnx2x_link_sync_notify(bp);
 
-		/* Set the attention towards other drivers on the same port */
-		for (vn = VN_0; vn < E1HVN_MAX; vn++) {
-			if (vn == BP_E1HVN(bp))
-				continue;
+	if (bp->link_vars.link_up && bp->link_vars.line_speed) {
+		int cmng_fns = bnx2x_get_cmng_fns_mode(bp);
 
-			func = ((vn << 1) | port);
-			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
-			       (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
-		}
-
-		if (bp->link_vars.link_up) {
-			int i;
-
-			/* Init rate shaping and fairness contexts */
-			bnx2x_init_port_minmax(bp);
-
-			for (vn = VN_0; vn < E1HVN_MAX; vn++)
-				bnx2x_init_vn_minmax(bp, 2*vn + port);
-
-			/* Store it to internal memory */
-			for (i = 0;
-			     i < sizeof(struct cmng_struct_per_port) / 4; i++)
-				REG_WR(bp, BAR_XSTRORM_INTMEM +
-				  XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) + i*4,
-				       ((u32 *)(&bp->cmng))[i]);
-		}
+		if (cmng_fns != CMNG_FNS_NONE) {
+			bnx2x_cmng_fns_init(bp, false, cmng_fns);
+			storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
+		} else
+			/* rate shaping and fairness are disabled */
+			DP(NETIF_MSG_IFUP,
+			   "single function mode without fairness\n");
 	}
 }
 
@@ -1554,7 +2157,9 @@
 	else
 		bnx2x_stats_handle(bp, STATS_EVENT_STOP);
 
-	bnx2x_calc_vn_weight_sum(bp);
+	/* the link status update could be the result of a DCC event
+	   hence re-read the shmem mf configuration */
+	bnx2x_read_mf_cfg(bp);
 
 	/* indicate link status */
 	bnx2x_link_report(bp);
@@ -1570,8 +2175,13 @@
 
 	/* enable nig attention */
 	val = (0xff0f | (1 << (BP_E1HVN(bp) + 4)));
-	REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
-	REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
+	if (bp->common.int_block == INT_BLOCK_HC) {
+		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
+		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
+	} else if (CHIP_IS_E2(bp)) {
+		REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, val);
+		REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, val);
+	}
 
 	bnx2x_stats_handle(bp, STATS_EVENT_PMF);
 }
@@ -1585,23 +2195,25 @@
  */
 
 /* send the MCP a request, block until there is a reply */
-u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
+u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param)
 {
-	int func = BP_FUNC(bp);
+	int mb_idx = BP_FW_MB_IDX(bp);
 	u32 seq = ++bp->fw_seq;
 	u32 rc = 0;
 	u32 cnt = 1;
 	u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10;
 
 	mutex_lock(&bp->fw_mb_mutex);
-	SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq));
+	SHMEM_WR(bp, func_mb[mb_idx].drv_mb_param, param);
+	SHMEM_WR(bp, func_mb[mb_idx].drv_mb_header, (command | seq));
+
 	DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
 
 	do {
 		/* let the FW do it's magic ... */
 		msleep(delay);
 
-		rc = SHMEM_RD(bp, func_mb[func].fw_mb_header);
+		rc = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_header);
 
 		/* Give the FW up to 5 second (500*10ms) */
 	} while ((seq != (rc & FW_MSG_SEQ_NUMBER_MASK)) && (cnt++ < 500));
@@ -1623,6 +2235,315 @@
 	return rc;
 }
 
+/* must be called under rtnl_lock */
+void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters)
+{
+	u32 mask = (1 << cl_id);
+
+	/* initial seeting is BNX2X_ACCEPT_NONE */
+	u8 drop_all_ucast = 1, drop_all_bcast = 1, drop_all_mcast = 1;
+	u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
+	u8 unmatched_unicast = 0;
+
+	if (filters & BNX2X_PROMISCUOUS_MODE) {
+		/* promiscious - accept all, drop none */
+		drop_all_ucast = drop_all_bcast = drop_all_mcast = 0;
+		accp_all_ucast = accp_all_bcast = accp_all_mcast = 1;
+	}
+	if (filters & BNX2X_ACCEPT_UNICAST) {
+		/* accept matched ucast */
+		drop_all_ucast = 0;
+	}
+	if (filters & BNX2X_ACCEPT_MULTICAST) {
+		/* accept matched mcast */
+		drop_all_mcast = 0;
+	}
+	if (filters & BNX2X_ACCEPT_ALL_UNICAST) {
+		/* accept all mcast */
+		drop_all_ucast = 0;
+		accp_all_ucast = 1;
+	}
+	if (filters & BNX2X_ACCEPT_ALL_MULTICAST) {
+		/* accept all mcast */
+		drop_all_mcast = 0;
+		accp_all_mcast = 1;
+	}
+	if (filters & BNX2X_ACCEPT_BROADCAST) {
+		/* accept (all) bcast */
+		drop_all_bcast = 0;
+		accp_all_bcast = 1;
+	}
+
+	bp->mac_filters.ucast_drop_all = drop_all_ucast ?
+		bp->mac_filters.ucast_drop_all | mask :
+		bp->mac_filters.ucast_drop_all & ~mask;
+
+	bp->mac_filters.mcast_drop_all = drop_all_mcast ?
+		bp->mac_filters.mcast_drop_all | mask :
+		bp->mac_filters.mcast_drop_all & ~mask;
+
+	bp->mac_filters.bcast_drop_all = drop_all_bcast ?
+		bp->mac_filters.bcast_drop_all | mask :
+		bp->mac_filters.bcast_drop_all & ~mask;
+
+	bp->mac_filters.ucast_accept_all = accp_all_ucast ?
+		bp->mac_filters.ucast_accept_all | mask :
+		bp->mac_filters.ucast_accept_all & ~mask;
+
+	bp->mac_filters.mcast_accept_all = accp_all_mcast ?
+		bp->mac_filters.mcast_accept_all | mask :
+		bp->mac_filters.mcast_accept_all & ~mask;
+
+	bp->mac_filters.bcast_accept_all = accp_all_bcast ?
+		bp->mac_filters.bcast_accept_all | mask :
+		bp->mac_filters.bcast_accept_all & ~mask;
+
+	bp->mac_filters.unmatched_unicast = unmatched_unicast ?
+		bp->mac_filters.unmatched_unicast | mask :
+		bp->mac_filters.unmatched_unicast & ~mask;
+}
+
+void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
+{
+	struct tstorm_eth_function_common_config tcfg = {0};
+	u16 rss_flgs;
+
+	/* tpa */
+	if (p->func_flgs & FUNC_FLG_TPA)
+		tcfg.config_flags |=
+		TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA;
+
+	/* set rss flags */
+	rss_flgs = (p->rss->mode <<
+		TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT);
+
+	if (p->rss->cap & RSS_IPV4_CAP)
+		rss_flgs |= RSS_IPV4_CAP_MASK;
+	if (p->rss->cap & RSS_IPV4_TCP_CAP)
+		rss_flgs |= RSS_IPV4_TCP_CAP_MASK;
+	if (p->rss->cap & RSS_IPV6_CAP)
+		rss_flgs |= RSS_IPV6_CAP_MASK;
+	if (p->rss->cap & RSS_IPV6_TCP_CAP)
+		rss_flgs |= RSS_IPV6_TCP_CAP_MASK;
+
+	tcfg.config_flags |= rss_flgs;
+	tcfg.rss_result_mask = p->rss->result_mask;
+
+	storm_memset_func_cfg(bp, &tcfg, p->func_id);
+
+	/* Enable the function in the FW */
+	storm_memset_vf_to_pf(bp, p->func_id, p->pf_id);
+	storm_memset_func_en(bp, p->func_id, 1);
+
+	/* statistics */
+	if (p->func_flgs & FUNC_FLG_STATS) {
+		struct stats_indication_flags stats_flags = {0};
+		stats_flags.collect_eth = 1;
+
+		storm_memset_xstats_flags(bp, &stats_flags, p->func_id);
+		storm_memset_xstats_addr(bp, p->fw_stat_map, p->func_id);
+
+		storm_memset_tstats_flags(bp, &stats_flags, p->func_id);
+		storm_memset_tstats_addr(bp, p->fw_stat_map, p->func_id);
+
+		storm_memset_ustats_flags(bp, &stats_flags, p->func_id);
+		storm_memset_ustats_addr(bp, p->fw_stat_map, p->func_id);
+
+		storm_memset_cstats_flags(bp, &stats_flags, p->func_id);
+		storm_memset_cstats_addr(bp, p->fw_stat_map, p->func_id);
+	}
+
+	/* spq */
+	if (p->func_flgs & FUNC_FLG_SPQ) {
+		storm_memset_spq_addr(bp, p->spq_map, p->func_id);
+		REG_WR(bp, XSEM_REG_FAST_MEMORY +
+		       XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod);
+	}
+}
+
+static inline u16 bnx2x_get_cl_flags(struct bnx2x *bp,
+				     struct bnx2x_fastpath *fp)
+{
+	u16 flags = 0;
+
+	/* calculate queue flags */
+	flags |= QUEUE_FLG_CACHE_ALIGN;
+	flags |= QUEUE_FLG_HC;
+	flags |= IS_MF(bp) ? QUEUE_FLG_OV : 0;
+
+	flags |= QUEUE_FLG_VLAN;
+	DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
+
+	if (!fp->disable_tpa)
+		flags |= QUEUE_FLG_TPA;
+
+	flags |= QUEUE_FLG_STATS;
+
+	return flags;
+}
+
+static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp,
+	struct bnx2x_fastpath *fp, struct rxq_pause_params *pause,
+	struct bnx2x_rxq_init_params *rxq_init)
+{
+	u16 max_sge = 0;
+	u16 sge_sz = 0;
+	u16 tpa_agg_size = 0;
+
+	/* calculate queue flags */
+	u16 flags = bnx2x_get_cl_flags(bp, fp);
+
+	if (!fp->disable_tpa) {
+		pause->sge_th_hi = 250;
+		pause->sge_th_lo = 150;
+		tpa_agg_size = min_t(u32,
+			(min_t(u32, 8, MAX_SKB_FRAGS) *
+			SGE_PAGE_SIZE * PAGES_PER_SGE), 0xffff);
+		max_sge = SGE_PAGE_ALIGN(bp->dev->mtu) >>
+			SGE_PAGE_SHIFT;
+		max_sge = ((max_sge + PAGES_PER_SGE - 1) &
+			  (~(PAGES_PER_SGE-1))) >> PAGES_PER_SGE_SHIFT;
+		sge_sz = (u16)min_t(u32, SGE_PAGE_SIZE * PAGES_PER_SGE,
+				    0xffff);
+	}
+
+	/* pause - not for e1 */
+	if (!CHIP_IS_E1(bp)) {
+		pause->bd_th_hi = 350;
+		pause->bd_th_lo = 250;
+		pause->rcq_th_hi = 350;
+		pause->rcq_th_lo = 250;
+		pause->sge_th_hi = 0;
+		pause->sge_th_lo = 0;
+		pause->pri_map = 1;
+	}
+
+	/* rxq setup */
+	rxq_init->flags = flags;
+	rxq_init->cxt = &bp->context.vcxt[fp->cid].eth;
+	rxq_init->dscr_map = fp->rx_desc_mapping;
+	rxq_init->sge_map = fp->rx_sge_mapping;
+	rxq_init->rcq_map = fp->rx_comp_mapping;
+	rxq_init->rcq_np_map = fp->rx_comp_mapping + BCM_PAGE_SIZE;
+	rxq_init->mtu = bp->dev->mtu;
+	rxq_init->buf_sz = bp->rx_buf_size;
+	rxq_init->cl_qzone_id = fp->cl_qzone_id;
+	rxq_init->cl_id = fp->cl_id;
+	rxq_init->spcl_id = fp->cl_id;
+	rxq_init->stat_id = fp->cl_id;
+	rxq_init->tpa_agg_sz = tpa_agg_size;
+	rxq_init->sge_buf_sz = sge_sz;
+	rxq_init->max_sges_pkt = max_sge;
+	rxq_init->cache_line_log = BNX2X_RX_ALIGN_SHIFT;
+	rxq_init->fw_sb_id = fp->fw_sb_id;
+
+	rxq_init->sb_cq_index = U_SB_ETH_RX_CQ_INDEX;
+
+	rxq_init->cid = HW_CID(bp, fp->cid);
+
+	rxq_init->hc_rate = bp->rx_ticks ? (1000000 / bp->rx_ticks) : 0;
+}
+
+static void bnx2x_pf_tx_cl_prep(struct bnx2x *bp,
+	struct bnx2x_fastpath *fp, struct bnx2x_txq_init_params *txq_init)
+{
+	u16 flags = bnx2x_get_cl_flags(bp, fp);
+
+	txq_init->flags = flags;
+	txq_init->cxt = &bp->context.vcxt[fp->cid].eth;
+	txq_init->dscr_map = fp->tx_desc_mapping;
+	txq_init->stat_id = fp->cl_id;
+	txq_init->cid = HW_CID(bp, fp->cid);
+	txq_init->sb_cq_index = C_SB_ETH_TX_CQ_INDEX;
+	txq_init->traffic_type = LLFC_TRAFFIC_TYPE_NW;
+	txq_init->fw_sb_id = fp->fw_sb_id;
+	txq_init->hc_rate = bp->tx_ticks ? (1000000 / bp->tx_ticks) : 0;
+}
+
+void bnx2x_pf_init(struct bnx2x *bp)
+{
+	struct bnx2x_func_init_params func_init = {0};
+	struct bnx2x_rss_params rss = {0};
+	struct event_ring_data eq_data = { {0} };
+	u16 flags;
+
+	/* pf specific setups */
+	if (!CHIP_IS_E1(bp))
+		storm_memset_ov(bp, bp->mf_ov, BP_FUNC(bp));
+
+	if (CHIP_IS_E2(bp)) {
+		/* reset IGU PF statistics: MSIX + ATTN */
+		/* PF */
+		REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT +
+			   BNX2X_IGU_STAS_MSG_VF_CNT*4 +
+			   (CHIP_MODE_IS_4_PORT(bp) ?
+				BP_FUNC(bp) : BP_VN(bp))*4, 0);
+		/* ATTN */
+		REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT +
+			   BNX2X_IGU_STAS_MSG_VF_CNT*4 +
+			   BNX2X_IGU_STAS_MSG_PF_CNT*4 +
+			   (CHIP_MODE_IS_4_PORT(bp) ?
+				BP_FUNC(bp) : BP_VN(bp))*4, 0);
+	}
+
+	/* function setup flags */
+	flags = (FUNC_FLG_STATS | FUNC_FLG_LEADING | FUNC_FLG_SPQ);
+
+	if (CHIP_IS_E1x(bp))
+		flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
+	else
+		flags |= FUNC_FLG_TPA;
+
+	/* function setup */
+
+	/**
+	 * Although RSS is meaningless when there is a single HW queue we
+	 * still need it enabled in order to have HW Rx hash generated.
+	 */
+	rss.cap = (RSS_IPV4_CAP | RSS_IPV4_TCP_CAP |
+		   RSS_IPV6_CAP | RSS_IPV6_TCP_CAP);
+	rss.mode = bp->multi_mode;
+	rss.result_mask = MULTI_MASK;
+	func_init.rss = &rss;
+
+	func_init.func_flgs = flags;
+	func_init.pf_id = BP_FUNC(bp);
+	func_init.func_id = BP_FUNC(bp);
+	func_init.fw_stat_map = bnx2x_sp_mapping(bp, fw_stats);
+	func_init.spq_map = bp->spq_mapping;
+	func_init.spq_prod = bp->spq_prod_idx;
+
+	bnx2x_func_init(bp, &func_init);
+
+	memset(&(bp->cmng), 0, sizeof(struct cmng_struct_per_port));
+
+	/*
+	Congestion management values depend on the link rate
+	There is no active link so initial link rate is set to 10 Gbps.
+	When the link comes up The congestion management values are
+	re-calculated according to the actual link rate.
+	*/
+	bp->link_vars.line_speed = SPEED_10000;
+	bnx2x_cmng_fns_init(bp, true, bnx2x_get_cmng_fns_mode(bp));
+
+	/* Only the PMF sets the HW */
+	if (bp->port.pmf)
+		storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
+
+	/* no rx until link is up */
+	bp->rx_mode = BNX2X_RX_MODE_NONE;
+	bnx2x_set_storm_rx_mode(bp);
+
+	/* init Event Queue */
+	eq_data.base_addr.hi = U64_HI(bp->eq_mapping);
+	eq_data.base_addr.lo = U64_LO(bp->eq_mapping);
+	eq_data.producer = bp->eq_prod;
+	eq_data.index_id = HC_SP_INDEX_EQ_CONS;
+	eq_data.sb_id = DEF_SB_ID;
+	storm_memset_eq_data(bp, &eq_data, BP_FUNC(bp));
+}
+
+
 static void bnx2x_e1h_disable(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
@@ -1649,40 +2570,6 @@
 	 */
 }
 
-static void bnx2x_update_min_max(struct bnx2x *bp)
-{
-	int port = BP_PORT(bp);
-	int vn, i;
-
-	/* Init rate shaping and fairness contexts */
-	bnx2x_init_port_minmax(bp);
-
-	bnx2x_calc_vn_weight_sum(bp);
-
-	for (vn = VN_0; vn < E1HVN_MAX; vn++)
-		bnx2x_init_vn_minmax(bp, 2*vn + port);
-
-	if (bp->port.pmf) {
-		int func;
-
-		/* Set the attention towards other drivers on the same port */
-		for (vn = VN_0; vn < E1HVN_MAX; vn++) {
-			if (vn == BP_E1HVN(bp))
-				continue;
-
-			func = ((vn << 1) | port);
-			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
-			       (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
-		}
-
-		/* Store it to internal memory */
-		for (i = 0; i < sizeof(struct cmng_struct_per_port) / 4; i++)
-			REG_WR(bp, BAR_XSTRORM_INTMEM +
-			       XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) + i*4,
-			       ((u32 *)(&bp->cmng))[i]);
-	}
-}
-
 static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event)
 {
 	DP(BNX2X_MSG_MCP, "dcc_event 0x%x\n", dcc_event);
@@ -1694,7 +2581,7 @@
 		 * where the bp->flags can change so it is done without any
 		 * locks
 		 */
-		if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) {
+		if (bp->mf_config[BP_VN(bp)] & FUNC_MF_CFG_FUNC_DISABLED) {
 			DP(NETIF_MSG_IFDOWN, "mf_cfg function disabled\n");
 			bp->flags |= MF_FUNC_DIS;
 
@@ -1709,15 +2596,17 @@
 	}
 	if (dcc_event & DRV_STATUS_DCC_BANDWIDTH_ALLOCATION) {
 
-		bnx2x_update_min_max(bp);
+		bnx2x_cmng_fns_init(bp, true, CMNG_FNS_MINMAX);
+		bnx2x_link_sync_notify(bp);
+		storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
 		dcc_event &= ~DRV_STATUS_DCC_BANDWIDTH_ALLOCATION;
 	}
 
 	/* Report results to MCP */
 	if (dcc_event)
-		bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_FAILURE);
+		bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_FAILURE, 0);
 	else
-		bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK);
+		bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK, 0);
 }
 
 /* must be called under the spq lock */
@@ -1744,16 +2633,17 @@
 	/* Make sure that BD data is updated before writing the producer */
 	wmb();
 
-	REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
-	       bp->spq_prod_idx);
+	REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
+		 bp->spq_prod_idx);
 	mmiowb();
 }
 
 /* the slow path queue is odd since completions arrive on the fastpath ring */
 int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
-			 u32 data_hi, u32 data_lo, int common)
+		  u32 data_hi, u32 data_lo, int common)
 {
 	struct eth_spe *spe;
+	u16 type;
 
 #ifdef BNX2X_STOP_ON_ERROR
 	if (unlikely(bp->panic))
@@ -1762,7 +2652,7 @@
 
 	spin_lock_bh(&bp->spq_lock);
 
-	if (!bp->spq_left) {
+	if (!atomic_read(&bp->spq_left)) {
 		BNX2X_ERR("BUG! SPQ ring full!\n");
 		spin_unlock_bh(&bp->spq_lock);
 		bnx2x_panic();
@@ -1775,22 +2665,42 @@
 	spe->hdr.conn_and_cmd_data =
 			cpu_to_le32((command << SPE_HDR_CMD_ID_SHIFT) |
 				    HW_CID(bp, cid));
-	spe->hdr.type = cpu_to_le16(ETH_CONNECTION_TYPE);
+
 	if (common)
-		spe->hdr.type |=
-			cpu_to_le16((1 << SPE_HDR_COMMON_RAMROD_SHIFT));
+		/* Common ramrods:
+		 *	FUNC_START, FUNC_STOP, CFC_DEL, STATS, SET_MAC
+		 *	TRAFFIC_STOP, TRAFFIC_START
+		 */
+		type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
+			& SPE_HDR_CONN_TYPE;
+	else
+		/* ETH ramrods: SETUP, HALT */
+		type = (ETH_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
+			& SPE_HDR_CONN_TYPE;
 
-	spe->data.mac_config_addr.hi = cpu_to_le32(data_hi);
-	spe->data.mac_config_addr.lo = cpu_to_le32(data_lo);
+	type |= ((BP_FUNC(bp) << SPE_HDR_FUNCTION_ID_SHIFT) &
+		 SPE_HDR_FUNCTION_ID);
 
-	bp->spq_left--;
+	spe->hdr.type = cpu_to_le16(type);
+
+	spe->data.update_data_addr.hi = cpu_to_le32(data_hi);
+	spe->data.update_data_addr.lo = cpu_to_le32(data_lo);
+
+	/* stats ramrod has it's own slot on the spq */
+	if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY)
+		/* It's ok if the actual decrement is issued towards the memory
+		 * somewhere between the spin_lock and spin_unlock. Thus no
+		 * more explict memory barrier is needed.
+		 */
+		atomic_dec(&bp->spq_left);
 
 	DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/,
-	   "SPQE[%x] (%x:%x)  command %d  hw_cid %x  data (%x:%x)  left %x\n",
+	   "SPQE[%x] (%x:%x)  command %d  hw_cid %x  data (%x:%x) "
+	   "type(0x%x) left %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, bp->spq_left);
+	   HW_CID(bp, cid), data_hi, data_lo, type, atomic_read(&bp->spq_left));
 
 	bnx2x_sp_prod_update(bp);
 	spin_unlock_bh(&bp->spq_lock);
@@ -1827,32 +2737,27 @@
 	REG_WR(bp, GRCBASE_MCP + 0x9c, 0);
 }
 
+#define BNX2X_DEF_SB_ATT_IDX	0x0001
+#define BNX2X_DEF_SB_IDX	0x0002
+
 static inline u16 bnx2x_update_dsb_idx(struct bnx2x *bp)
 {
-	struct host_def_status_block *def_sb = bp->def_status_blk;
+	struct host_sp_status_block *def_sb = bp->def_status_blk;
 	u16 rc = 0;
 
 	barrier(); /* status block is written to by the chip */
 	if (bp->def_att_idx != def_sb->atten_status_block.attn_bits_index) {
 		bp->def_att_idx = def_sb->atten_status_block.attn_bits_index;
-		rc |= 1;
+		rc |= BNX2X_DEF_SB_ATT_IDX;
 	}
-	if (bp->def_c_idx != def_sb->c_def_status_block.status_block_index) {
-		bp->def_c_idx = def_sb->c_def_status_block.status_block_index;
-		rc |= 2;
+
+	if (bp->def_idx != def_sb->sp_sb.running_index) {
+		bp->def_idx = def_sb->sp_sb.running_index;
+		rc |= BNX2X_DEF_SB_IDX;
 	}
-	if (bp->def_u_idx != def_sb->u_def_status_block.status_block_index) {
-		bp->def_u_idx = def_sb->u_def_status_block.status_block_index;
-		rc |= 4;
-	}
-	if (bp->def_x_idx != def_sb->x_def_status_block.status_block_index) {
-		bp->def_x_idx = def_sb->x_def_status_block.status_block_index;
-		rc |= 8;
-	}
-	if (bp->def_t_idx != def_sb->t_def_status_block.status_block_index) {
-		bp->def_t_idx = def_sb->t_def_status_block.status_block_index;
-		rc |= 16;
-	}
+
+	/* Do not reorder: indecies reading should complete before handling */
+	barrier();
 	return rc;
 }
 
@@ -1863,14 +2768,13 @@
 static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
 {
 	int port = BP_PORT(bp);
-	u32 hc_addr = (HC_REG_COMMAND_REG + port*32 +
-		       COMMAND_REG_ATTN_BITS_SET);
 	u32 aeu_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
 			      MISC_REG_AEU_MASK_ATTN_FUNC_0;
 	u32 nig_int_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 :
 				       NIG_REG_MASK_INTERRUPT_PORT0;
 	u32 aeu_mask;
 	u32 nig_mask = 0;
+	u32 reg_addr;
 
 	if (bp->attn_state & asserted)
 		BNX2X_ERR("IGU ERROR\n");
@@ -1945,9 +2849,15 @@
 
 	} /* if hardwired */
 
-	DP(NETIF_MSG_HW, "about to mask 0x%08x at HC addr 0x%x\n",
-	   asserted, hc_addr);
-	REG_WR(bp, hc_addr, asserted);
+	if (bp->common.int_block == INT_BLOCK_HC)
+		reg_addr = (HC_REG_COMMAND_REG + port*32 +
+			    COMMAND_REG_ATTN_BITS_SET);
+	else
+		reg_addr = (BAR_IGU_INTMEM + IGU_CMD_ATTN_BIT_SET_UPPER*8);
+
+	DP(NETIF_MSG_HW, "about to mask 0x%08x at %s addr 0x%x\n", asserted,
+	   (bp->common.int_block == INT_BLOCK_HC) ? "HC" : "IGU", reg_addr);
+	REG_WR(bp, reg_addr, asserted);
 
 	/* now set back the mask */
 	if (asserted & ATTN_NIG_FOR_FUNC) {
@@ -1959,12 +2869,16 @@
 static inline void bnx2x_fan_failure(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
-
+	u32 ext_phy_config;
 	/* mark the failure */
-	bp->link_params.ext_phy_config &= ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
-	bp->link_params.ext_phy_config |= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
+	ext_phy_config =
+		SHMEM_RD(bp,
+			 dev_info.port_hw_config[port].external_phy_config);
+
+	ext_phy_config &= ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
+	ext_phy_config |= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
 	SHMEM_WR(bp, dev_info.port_hw_config[port].external_phy_config,
-		 bp->link_params.ext_phy_config);
+		 ext_phy_config);
 
 	/* log the failure */
 	netdev_err(bp->dev, "Fan Failure on Network Controller has caused"
@@ -1976,7 +2890,7 @@
 {
 	int port = BP_PORT(bp);
 	int reg_offset;
-	u32 val, swap_val, swap_override;
+	u32 val;
 
 	reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
 			     MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
@@ -1990,30 +2904,7 @@
 		BNX2X_ERR("SPIO5 hw attention\n");
 
 		/* Fan failure attention */
-		switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) {
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-			/* Low power mode is controlled by GPIO 2 */
-			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-				       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
-			/* The PHY reset is controlled by GPIO 1 */
-			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-				       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-			/* The PHY reset is controlled by GPIO 1 */
-			/* fake the port number to cancel the swap done in
-			   set_gpio() */
-			swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
-			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);
-			break;
-
-		default:
-			break;
-		}
+		bnx2x_hw_reset_phy(&bp->link_params);
 		bnx2x_fan_failure(bp);
 	}
 
@@ -2087,6 +2978,10 @@
 		/* RQ_USDMDP_FIFO_OVERFLOW */
 		if (val & 0x18000)
 			BNX2X_ERR("FATAL error from PXP\n");
+		if (CHIP_IS_E2(bp)) {
+			val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_1);
+			BNX2X_ERR("PXP hw attention-1 0x%x\n", val);
+		}
 	}
 
 	if (attn & HW_INTERRUT_ASSERT_SET_2) {
@@ -2117,9 +3012,10 @@
 			int func = BP_FUNC(bp);
 
 			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
-			bp->mf_config = SHMEM_RD(bp,
-					   mf_cfg.func_mf_config[func].config);
-			val = SHMEM_RD(bp, func_mb[func].drv_status);
+			bp->mf_config[BP_VN(bp)] = MF_CFG_RD(bp,
+					func_mf_config[BP_ABS_FUNC(bp)].config);
+			val = SHMEM_RD(bp,
+				       func_mb[BP_FW_MB_IDX(bp)].drv_status);
 			if (val & DRV_STATUS_DCC_EVENT_MASK)
 				bnx2x_dcc_event(bp,
 					    (val & DRV_STATUS_DCC_EVENT_MASK));
@@ -2149,13 +3045,13 @@
 	if (attn & EVEREST_LATCHED_ATTN_IN_USE_MASK) {
 		BNX2X_ERR("LATCHED attention 0x%08x (masked)\n", attn);
 		if (attn & BNX2X_GRC_TIMEOUT) {
-			val = CHIP_IS_E1H(bp) ?
-				REG_RD(bp, MISC_REG_GRC_TIMEOUT_ATTN) : 0;
+			val = CHIP_IS_E1(bp) ? 0 :
+					REG_RD(bp, MISC_REG_GRC_TIMEOUT_ATTN);
 			BNX2X_ERR("GRC time-out 0x%08x\n", val);
 		}
 		if (attn & BNX2X_GRC_RSV) {
-			val = CHIP_IS_E1H(bp) ?
-				REG_RD(bp, MISC_REG_GRC_RSV_ATTN) : 0;
+			val = CHIP_IS_E1(bp) ? 0 :
+					REG_RD(bp, MISC_REG_GRC_RSV_ATTN);
 			BNX2X_ERR("GRC reserved 0x%08x\n", val);
 		}
 		REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x7ff);
@@ -2168,6 +3064,7 @@
 #define RESET_DONE_FLAG_MASK	(~LOAD_COUNTER_MASK)
 #define RESET_DONE_FLAG_SHIFT	LOAD_COUNTER_BITS
 #define CHIP_PARITY_SUPPORTED(bp)   (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp))
+
 /*
  * should be run under rtnl lock
  */
@@ -2460,6 +3357,74 @@
 					attn.sig[3]);
 }
 
+
+static inline void bnx2x_attn_int_deasserted4(struct bnx2x *bp, u32 attn)
+{
+	u32 val;
+	if (attn & AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT) {
+
+		val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS_CLR);
+		BNX2X_ERR("PGLUE hw attention 0x%x\n", val);
+		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_ADDRESS_ERROR)
+			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+				  "ADDRESS_ERROR\n");
+		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_INCORRECT_RCV_BEHAVIOR)
+			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+				  "INCORRECT_RCV_BEHAVIOR\n");
+		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN)
+			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+				  "WAS_ERROR_ATTN\n");
+		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_VF_LENGTH_VIOLATION_ATTN)
+			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+				  "VF_LENGTH_VIOLATION_ATTN\n");
+		if (val &
+		    PGLUE_B_PGLUE_B_INT_STS_REG_VF_GRC_SPACE_VIOLATION_ATTN)
+			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+				  "VF_GRC_SPACE_VIOLATION_ATTN\n");
+		if (val &
+		    PGLUE_B_PGLUE_B_INT_STS_REG_VF_MSIX_BAR_VIOLATION_ATTN)
+			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+				  "VF_MSIX_BAR_VIOLATION_ATTN\n");
+		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_ERROR_ATTN)
+			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+				  "TCPL_ERROR_ATTN\n");
+		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_IN_TWO_RCBS_ATTN)
+			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+				  "TCPL_IN_TWO_RCBS_ATTN\n");
+		if (val & PGLUE_B_PGLUE_B_INT_STS_REG_CSSNOOP_FIFO_OVERFLOW)
+			BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+				  "CSSNOOP_FIFO_OVERFLOW\n");
+	}
+	if (attn & AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT) {
+		val = REG_RD(bp, ATC_REG_ATC_INT_STS_CLR);
+		BNX2X_ERR("ATC hw attention 0x%x\n", val);
+		if (val & ATC_ATC_INT_STS_REG_ADDRESS_ERROR)
+			BNX2X_ERR("ATC_ATC_INT_STS_REG_ADDRESS_ERROR\n");
+		if (val & ATC_ATC_INT_STS_REG_ATC_TCPL_TO_NOT_PEND)
+			BNX2X_ERR("ATC_ATC_INT_STS_REG"
+				  "_ATC_TCPL_TO_NOT_PEND\n");
+		if (val & ATC_ATC_INT_STS_REG_ATC_GPA_MULTIPLE_HITS)
+			BNX2X_ERR("ATC_ATC_INT_STS_REG_"
+				  "ATC_GPA_MULTIPLE_HITS\n");
+		if (val & ATC_ATC_INT_STS_REG_ATC_RCPL_TO_EMPTY_CNT)
+			BNX2X_ERR("ATC_ATC_INT_STS_REG_"
+				  "ATC_RCPL_TO_EMPTY_CNT\n");
+		if (val & ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR)
+			BNX2X_ERR("ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR\n");
+		if (val & ATC_ATC_INT_STS_REG_ATC_IREQ_LESS_THAN_STU)
+			BNX2X_ERR("ATC_ATC_INT_STS_REG_"
+				  "ATC_IREQ_LESS_THAN_STU\n");
+	}
+
+	if (attn & (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR |
+		    AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)) {
+		BNX2X_ERR("FATAL parity attention set4 0x%x\n",
+		(u32)(attn & (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR |
+		    AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)));
+	}
+
+}
+
 static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
 {
 	struct attn_route attn, *group_mask;
@@ -2490,17 +3455,28 @@
 	attn.sig[1] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 + port*4);
 	attn.sig[2] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 + port*4);
 	attn.sig[3] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 + port*4);
-	DP(NETIF_MSG_HW, "attn: %08x %08x %08x %08x\n",
-	   attn.sig[0], attn.sig[1], attn.sig[2], attn.sig[3]);
+	if (CHIP_IS_E2(bp))
+		attn.sig[4] =
+		      REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 + port*4);
+	else
+		attn.sig[4] = 0;
+
+	DP(NETIF_MSG_HW, "attn: %08x %08x %08x %08x %08x\n",
+	   attn.sig[0], attn.sig[1], attn.sig[2], attn.sig[3], attn.sig[4]);
 
 	for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) {
 		if (deasserted & (1 << index)) {
 			group_mask = &bp->attn_group[index];
 
-			DP(NETIF_MSG_HW, "group[%d]: %08x %08x %08x %08x\n",
-			   index, group_mask->sig[0], group_mask->sig[1],
-			   group_mask->sig[2], group_mask->sig[3]);
+			DP(NETIF_MSG_HW, "group[%d]: %08x %08x "
+					 "%08x %08x %08x\n",
+			   index,
+			   group_mask->sig[0], group_mask->sig[1],
+			   group_mask->sig[2], group_mask->sig[3],
+			   group_mask->sig[4]);
 
+			bnx2x_attn_int_deasserted4(bp,
+					attn.sig[4] & group_mask->sig[4]);
 			bnx2x_attn_int_deasserted3(bp,
 					attn.sig[3] & group_mask->sig[3]);
 			bnx2x_attn_int_deasserted1(bp,
@@ -2514,11 +3490,15 @@
 
 	bnx2x_release_alr(bp);
 
-	reg_addr = (HC_REG_COMMAND_REG + port*32 + COMMAND_REG_ATTN_BITS_CLR);
+	if (bp->common.int_block == INT_BLOCK_HC)
+		reg_addr = (HC_REG_COMMAND_REG + port*32 +
+			    COMMAND_REG_ATTN_BITS_CLR);
+	else
+		reg_addr = (BAR_IGU_INTMEM + IGU_CMD_ATTN_BIT_CLR_UPPER*8);
 
 	val = ~deasserted;
-	DP(NETIF_MSG_HW, "about to mask 0x%08x at HC addr 0x%x\n",
-	   val, reg_addr);
+	DP(NETIF_MSG_HW, "about to mask 0x%08x at %s addr 0x%x\n", val,
+	   (bp->common.int_block == INT_BLOCK_HC) ? "HC" : "IGU", reg_addr);
 	REG_WR(bp, reg_addr, val);
 
 	if (~bp->attn_state & deasserted)
@@ -2571,6 +3551,141 @@
 		bnx2x_attn_int_deasserted(bp, deasserted);
 }
 
+static inline void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
+{
+	/* No memory barriers */
+	storm_memset_eq_prod(bp, prod, BP_FUNC(bp));
+	mmiowb(); /* keep prod updates ordered */
+}
+
+#ifdef BCM_CNIC
+static int  bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
+				      union event_ring_elem *elem)
+{
+	if (!bp->cnic_eth_dev.starting_cid  ||
+	    cid < bp->cnic_eth_dev.starting_cid)
+		return 1;
+
+	DP(BNX2X_MSG_SP, "got delete ramrod for CNIC CID %d\n", cid);
+
+	if (unlikely(elem->message.data.cfc_del_event.error)) {
+		BNX2X_ERR("got delete ramrod for CNIC CID %d with error!\n",
+			  cid);
+		bnx2x_panic_dump(bp);
+	}
+	bnx2x_cnic_cfc_comp(bp, cid);
+	return 0;
+}
+#endif
+
+static void bnx2x_eq_int(struct bnx2x *bp)
+{
+	u16 hw_cons, sw_cons, sw_prod;
+	union event_ring_elem *elem;
+	u32 cid;
+	u8 opcode;
+	int spqe_cnt = 0;
+
+	hw_cons = le16_to_cpu(*bp->eq_cons_sb);
+
+	/* The hw_cos range is 1-255, 257 - the sw_cons range is 0-254, 256.
+	 * when we get the the next-page we nned to adjust so the loop
+	 * condition below will be met. The next element is the size of a
+	 * regular element and hence incrementing by 1
+	 */
+	if ((hw_cons & EQ_DESC_MAX_PAGE) == EQ_DESC_MAX_PAGE)
+		hw_cons++;
+
+	/* This function may never run in parralel with itself for a
+	 * specific bp, thus there is no need in "paired" read memory
+	 * barrier here.
+	 */
+	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));
+
+	for (; sw_cons != hw_cons;
+	      sw_prod = NEXT_EQ_IDX(sw_prod), sw_cons = NEXT_EQ_IDX(sw_cons)) {
+
+
+		elem = &bp->eq_ring[EQ_DESC(sw_cons)];
+
+		cid = SW_CID(elem->message.data.cfc_del_event.cid);
+		opcode = elem->message.opcode;
+
+
+		/* handle eq element */
+		switch (opcode) {
+		case EVENT_RING_OPCODE_STAT_QUERY:
+			DP(NETIF_MSG_TIMER, "got statistics comp event\n");
+			/* nothing to do with stats comp */
+			continue;
+
+		case EVENT_RING_OPCODE_CFC_DEL:
+			/* handle according to cid range */
+			/*
+			 * we may want to verify here that the bp state is
+			 * HALTING
+			 */
+			DP(NETIF_MSG_IFDOWN,
+			   "got delete ramrod for MULTI[%d]\n", cid);
+#ifdef BCM_CNIC
+			if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem))
+				goto next_spqe;
+#endif
+			bnx2x_fp(bp, cid, state) =
+						BNX2X_FP_STATE_CLOSED;
+
+			goto next_spqe;
+		}
+
+		switch (opcode | bp->state) {
+		case (EVENT_RING_OPCODE_FUNCTION_START |
+		      BNX2X_STATE_OPENING_WAIT4_PORT):
+			DP(NETIF_MSG_IFUP, "got setup ramrod\n");
+			bp->state = BNX2X_STATE_FUNC_STARTED;
+			break;
+
+		case (EVENT_RING_OPCODE_FUNCTION_STOP |
+		      BNX2X_STATE_CLOSING_WAIT4_HALT):
+			DP(NETIF_MSG_IFDOWN, "got halt ramrod\n");
+			bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
+			break;
+
+		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
+		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
+			DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
+			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;
+			break;
+		default:
+			/* unknown event log error and continue */
+			BNX2X_ERR("Unknown EQ event %d\n",
+				  elem->message.opcode);
+		}
+next_spqe:
+		spqe_cnt++;
+	} /* for */
+
+	smp_mb__before_atomic_inc();
+	atomic_add(spqe_cnt, &bp->spq_left);
+
+	bp->eq_cons = sw_cons;
+	bp->eq_prod = sw_prod;
+	/* Make sure that above mem writes were issued towards the memory */
+	smp_wmb();
+
+	/* update producer */
+	bnx2x_update_eq_prod(bp, bp->eq_prod);
+}
+
 static void bnx2x_sp_task(struct work_struct *work)
 {
 	struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work);
@@ -2589,31 +3704,29 @@
 	DP(NETIF_MSG_INTR, "got a slowpath interrupt (status 0x%x)\n", status);
 
 	/* HW attentions */
-	if (status & 0x1) {
+	if (status & BNX2X_DEF_SB_ATT_IDX) {
 		bnx2x_attn_int(bp);
-		status &= ~0x1;
+		status &= ~BNX2X_DEF_SB_ATT_IDX;
 	}
 
-	/* CStorm events: STAT_QUERY */
-	if (status & 0x2) {
-		DP(BNX2X_MSG_SP, "CStorm events: STAT_QUERY\n");
-		status &= ~0x2;
+	/* SP events: STAT_QUERY and others */
+	if (status & BNX2X_DEF_SB_IDX) {
+
+		/* Handle EQ completions */
+		bnx2x_eq_int(bp);
+
+		bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID,
+			le16_to_cpu(bp->def_idx), IGU_INT_NOP, 1);
+
+		status &= ~BNX2X_DEF_SB_IDX;
 	}
 
 	if (unlikely(status))
 		DP(NETIF_MSG_INTR, "got an unknown interrupt! (status 0x%x)\n",
 		   status);
 
-	bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, le16_to_cpu(bp->def_att_idx),
-		     IGU_INT_NOP, 1);
-	bnx2x_ack_sb(bp, DEF_SB_ID, USTORM_ID, le16_to_cpu(bp->def_u_idx),
-		     IGU_INT_NOP, 1);
-	bnx2x_ack_sb(bp, DEF_SB_ID, CSTORM_ID, le16_to_cpu(bp->def_c_idx),
-		     IGU_INT_NOP, 1);
-	bnx2x_ack_sb(bp, DEF_SB_ID, XSTORM_ID, le16_to_cpu(bp->def_x_idx),
-		     IGU_INT_NOP, 1);
-	bnx2x_ack_sb(bp, DEF_SB_ID, TSTORM_ID, le16_to_cpu(bp->def_t_idx),
-		     IGU_INT_ENABLE, 1);
+	bnx2x_ack_sb(bp, bp->igu_dsb_id, ATTENTION_ID,
+	     le16_to_cpu(bp->def_att_idx), IGU_INT_ENABLE, 1);
 }
 
 irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
@@ -2627,7 +3740,8 @@
 		return IRQ_HANDLED;
 	}
 
-	bnx2x_ack_sb(bp, DEF_SB_ID, TSTORM_ID, 0, IGU_INT_DISABLE, 0);
+	bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0,
+		     IGU_INT_DISABLE, 0);
 
 #ifdef BNX2X_STOP_ON_ERROR
 	if (unlikely(bp->panic))
@@ -2671,7 +3785,7 @@
 	}
 
 	if (!BP_NOMCP(bp)) {
-		int func = BP_FUNC(bp);
+		int mb_idx = BP_FW_MB_IDX(bp);
 		u32 drv_pulse;
 		u32 mcp_pulse;
 
@@ -2679,9 +3793,9 @@
 		bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK;
 		/* TBD - add SYSTEM_TIME */
 		drv_pulse = bp->fw_drv_pulse_wr_seq;
-		SHMEM_WR(bp, func_mb[func].drv_pulse_mb, drv_pulse);
+		SHMEM_WR(bp, func_mb[mb_idx].drv_pulse_mb, drv_pulse);
 
-		mcp_pulse = (SHMEM_RD(bp, func_mb[func].mcp_pulse_mb) &
+		mcp_pulse = (SHMEM_RD(bp, func_mb[mb_idx].mcp_pulse_mb) &
 			     MCP_PULSE_SEQ_MASK);
 		/* The delta between driver pulse and mcp response
 		 * should be 1 (before mcp response) or 0 (after mcp response)
@@ -2709,324 +3823,310 @@
  * nic init service functions
  */
 
-static void bnx2x_zero_sb(struct bnx2x *bp, int sb_id)
+static inline void bnx2x_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
 {
-	int port = BP_PORT(bp);
+	u32 i;
+	if (!(len%4) && !(addr%4))
+		for (i = 0; i < len; i += 4)
+			REG_WR(bp, addr + i, fill);
+	else
+		for (i = 0; i < len; i++)
+			REG_WR8(bp, addr + i, fill);
 
-	/* "CSTORM" */
-	bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
-			CSTORM_SB_HOST_STATUS_BLOCK_U_OFFSET(port, sb_id), 0,
-			CSTORM_SB_STATUS_BLOCK_U_SIZE / 4);
-	bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
-			CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, sb_id), 0,
-			CSTORM_SB_STATUS_BLOCK_C_SIZE / 4);
 }
 
-void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb,
-			  dma_addr_t mapping, int sb_id)
+/* helper: writes FP SP data to FW - data_size in dwords */
+static inline void bnx2x_wr_fp_sb_data(struct bnx2x *bp,
+				       int fw_sb_id,
+				       u32 *sb_data_p,
+				       u32 data_size)
 {
-	int port = BP_PORT(bp);
-	int func = BP_FUNC(bp);
 	int index;
-	u64 section;
-
-	/* USTORM */
-	section = ((u64)mapping) + offsetof(struct host_status_block,
-					    u_status_block);
-	sb->u_status_block.status_block_id = sb_id;
-
-	REG_WR(bp, BAR_CSTRORM_INTMEM +
-	       CSTORM_SB_HOST_SB_ADDR_U_OFFSET(port, sb_id), U64_LO(section));
-	REG_WR(bp, BAR_CSTRORM_INTMEM +
-	       ((CSTORM_SB_HOST_SB_ADDR_U_OFFSET(port, sb_id)) + 4),
-	       U64_HI(section));
-	REG_WR8(bp, BAR_CSTRORM_INTMEM + FP_USB_FUNC_OFF +
-		CSTORM_SB_HOST_STATUS_BLOCK_U_OFFSET(port, sb_id), func);
-
-	for (index = 0; index < HC_USTORM_SB_NUM_INDICES; index++)
-		REG_WR16(bp, BAR_CSTRORM_INTMEM +
-			 CSTORM_SB_HC_DISABLE_U_OFFSET(port, sb_id, index), 1);
-
-	/* CSTORM */
-	section = ((u64)mapping) + offsetof(struct host_status_block,
-					    c_status_block);
-	sb->c_status_block.status_block_id = sb_id;
-
-	REG_WR(bp, BAR_CSTRORM_INTMEM +
-	       CSTORM_SB_HOST_SB_ADDR_C_OFFSET(port, sb_id), U64_LO(section));
-	REG_WR(bp, BAR_CSTRORM_INTMEM +
-	       ((CSTORM_SB_HOST_SB_ADDR_C_OFFSET(port, sb_id)) + 4),
-	       U64_HI(section));
-	REG_WR8(bp, BAR_CSTRORM_INTMEM + FP_CSB_FUNC_OFF +
-		CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, sb_id), func);
-
-	for (index = 0; index < HC_CSTORM_SB_NUM_INDICES; index++)
-		REG_WR16(bp, BAR_CSTRORM_INTMEM +
-			 CSTORM_SB_HC_DISABLE_C_OFFSET(port, sb_id, index), 1);
-
-	bnx2x_ack_sb(bp, sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+	for (index = 0; index < data_size; index++)
+		REG_WR(bp, BAR_CSTRORM_INTMEM +
+			CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
+			sizeof(u32)*index,
+			*(sb_data_p + index));
 }
 
-static void bnx2x_zero_def_sb(struct bnx2x *bp)
+static inline void bnx2x_zero_fp_sb(struct bnx2x *bp, int fw_sb_id)
+{
+	u32 *sb_data_p;
+	u32 data_size = 0;
+	struct hc_status_block_data_e2 sb_data_e2;
+	struct hc_status_block_data_e1x sb_data_e1x;
+
+	/* disable the function first */
+	if (CHIP_IS_E2(bp)) {
+		memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
+		sb_data_e2.common.p_func.pf_id = HC_FUNCTION_DISABLED;
+		sb_data_e2.common.p_func.vf_id = HC_FUNCTION_DISABLED;
+		sb_data_e2.common.p_func.vf_valid = false;
+		sb_data_p = (u32 *)&sb_data_e2;
+		data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32);
+	} else {
+		memset(&sb_data_e1x, 0,
+		       sizeof(struct hc_status_block_data_e1x));
+		sb_data_e1x.common.p_func.pf_id = HC_FUNCTION_DISABLED;
+		sb_data_e1x.common.p_func.vf_id = HC_FUNCTION_DISABLED;
+		sb_data_e1x.common.p_func.vf_valid = false;
+		sb_data_p = (u32 *)&sb_data_e1x;
+		data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32);
+	}
+	bnx2x_wr_fp_sb_data(bp, fw_sb_id, sb_data_p, data_size);
+
+	bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
+			CSTORM_STATUS_BLOCK_OFFSET(fw_sb_id), 0,
+			CSTORM_STATUS_BLOCK_SIZE);
+	bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
+			CSTORM_SYNC_BLOCK_OFFSET(fw_sb_id), 0,
+			CSTORM_SYNC_BLOCK_SIZE);
+}
+
+/* helper:  writes SP SB data to FW */
+static inline void bnx2x_wr_sp_sb_data(struct bnx2x *bp,
+		struct hc_sp_status_block_data *sp_sb_data)
 {
 	int func = BP_FUNC(bp);
-
-	bnx2x_init_fill(bp, TSEM_REG_FAST_MEMORY +
-			TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
-			sizeof(struct tstorm_def_status_block)/4);
-	bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
-			CSTORM_DEF_SB_HOST_STATUS_BLOCK_U_OFFSET(func), 0,
-			sizeof(struct cstorm_def_status_block_u)/4);
-	bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
-			CSTORM_DEF_SB_HOST_STATUS_BLOCK_C_OFFSET(func), 0,
-			sizeof(struct cstorm_def_status_block_c)/4);
-	bnx2x_init_fill(bp, XSEM_REG_FAST_MEMORY +
-			XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
-			sizeof(struct xstorm_def_status_block)/4);
+	int i;
+	for (i = 0; i < sizeof(struct hc_sp_status_block_data)/sizeof(u32); i++)
+		REG_WR(bp, BAR_CSTRORM_INTMEM +
+			CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
+			i*sizeof(u32),
+			*((u32 *)sp_sb_data + i));
 }
 
-static void bnx2x_init_def_sb(struct bnx2x *bp,
-			      struct host_def_status_block *def_sb,
-			      dma_addr_t mapping, int sb_id)
+static inline void bnx2x_zero_sp_sb(struct bnx2x *bp)
+{
+	int func = BP_FUNC(bp);
+	struct hc_sp_status_block_data sp_sb_data;
+	memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data));
+
+	sp_sb_data.p_func.pf_id = HC_FUNCTION_DISABLED;
+	sp_sb_data.p_func.vf_id = HC_FUNCTION_DISABLED;
+	sp_sb_data.p_func.vf_valid = false;
+
+	bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
+
+	bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
+			CSTORM_SP_STATUS_BLOCK_OFFSET(func), 0,
+			CSTORM_SP_STATUS_BLOCK_SIZE);
+	bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
+			CSTORM_SP_SYNC_BLOCK_OFFSET(func), 0,
+			CSTORM_SP_SYNC_BLOCK_SIZE);
+
+}
+
+
+static inline
+void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm,
+					   int igu_sb_id, int igu_seg_id)
+{
+	hc_sm->igu_sb_id = igu_sb_id;
+	hc_sm->igu_seg_id = igu_seg_id;
+	hc_sm->timer_value = 0xFF;
+	hc_sm->time_to_expire = 0xFFFFFFFF;
+}
+
+void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
+			  u8 vf_valid, int fw_sb_id, int igu_sb_id)
+{
+	int igu_seg_id;
+
+	struct hc_status_block_data_e2 sb_data_e2;
+	struct hc_status_block_data_e1x sb_data_e1x;
+	struct hc_status_block_sm  *hc_sm_p;
+	struct hc_index_data *hc_index_p;
+	int data_size;
+	u32 *sb_data_p;
+
+	if (CHIP_INT_MODE_IS_BC(bp))
+		igu_seg_id = HC_SEG_ACCESS_NORM;
+	else
+		igu_seg_id = IGU_SEG_ACCESS_NORM;
+
+	bnx2x_zero_fp_sb(bp, fw_sb_id);
+
+	if (CHIP_IS_E2(bp)) {
+		memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
+		sb_data_e2.common.p_func.pf_id = BP_FUNC(bp);
+		sb_data_e2.common.p_func.vf_id = vfid;
+		sb_data_e2.common.p_func.vf_valid = vf_valid;
+		sb_data_e2.common.p_func.vnic_id = BP_VN(bp);
+		sb_data_e2.common.same_igu_sb_1b = true;
+		sb_data_e2.common.host_sb_addr.hi = U64_HI(mapping);
+		sb_data_e2.common.host_sb_addr.lo = U64_LO(mapping);
+		hc_sm_p = sb_data_e2.common.state_machine;
+		hc_index_p = sb_data_e2.index_data;
+		sb_data_p = (u32 *)&sb_data_e2;
+		data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32);
+	} else {
+		memset(&sb_data_e1x, 0,
+		       sizeof(struct hc_status_block_data_e1x));
+		sb_data_e1x.common.p_func.pf_id = BP_FUNC(bp);
+		sb_data_e1x.common.p_func.vf_id = 0xff;
+		sb_data_e1x.common.p_func.vf_valid = false;
+		sb_data_e1x.common.p_func.vnic_id = BP_VN(bp);
+		sb_data_e1x.common.same_igu_sb_1b = true;
+		sb_data_e1x.common.host_sb_addr.hi = U64_HI(mapping);
+		sb_data_e1x.common.host_sb_addr.lo = U64_LO(mapping);
+		hc_sm_p = sb_data_e1x.common.state_machine;
+		hc_index_p = sb_data_e1x.index_data;
+		sb_data_p = (u32 *)&sb_data_e1x;
+		data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32);
+	}
+
+	bnx2x_setup_ndsb_state_machine(&hc_sm_p[SM_RX_ID],
+				       igu_sb_id, igu_seg_id);
+	bnx2x_setup_ndsb_state_machine(&hc_sm_p[SM_TX_ID],
+				       igu_sb_id, igu_seg_id);
+
+	DP(NETIF_MSG_HW, "Init FW SB %d\n", fw_sb_id);
+
+	/* write indecies to HW */
+	bnx2x_wr_fp_sb_data(bp, fw_sb_id, sb_data_p, data_size);
+}
+
+static void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u16 fw_sb_id,
+					u8 sb_index, u8 disable, u16 usec)
 {
 	int port = BP_PORT(bp);
+	u8 ticks = usec / BNX2X_BTR;
+
+	storm_memset_hc_timeout(bp, port, fw_sb_id, sb_index, ticks);
+
+	disable = disable ? 1 : (usec ? 0 : 1);
+	storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable);
+}
+
+static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u16 fw_sb_id,
+				     u16 tx_usec, u16 rx_usec)
+{
+	bnx2x_update_coalesce_sb_index(bp, fw_sb_id, U_SB_ETH_RX_CQ_INDEX,
+				    false, rx_usec);
+	bnx2x_update_coalesce_sb_index(bp, fw_sb_id, C_SB_ETH_TX_CQ_INDEX,
+				    false, tx_usec);
+}
+
+static void bnx2x_init_def_sb(struct bnx2x *bp)
+{
+	struct host_sp_status_block *def_sb = bp->def_status_blk;
+	dma_addr_t mapping = bp->def_status_blk_mapping;
+	int igu_sp_sb_index;
+	int igu_seg_id;
+	int port = BP_PORT(bp);
 	int func = BP_FUNC(bp);
-	int index, val, reg_offset;
+	int reg_offset;
 	u64 section;
+	int index;
+	struct hc_sp_status_block_data sp_sb_data;
+	memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data));
+
+	if (CHIP_INT_MODE_IS_BC(bp)) {
+		igu_sp_sb_index = DEF_SB_IGU_ID;
+		igu_seg_id = HC_SEG_ACCESS_DEF;
+	} else {
+		igu_sp_sb_index = bp->igu_dsb_id;
+		igu_seg_id = IGU_SEG_ACCESS_DEF;
+	}
 
 	/* ATTN */
-	section = ((u64)mapping) + offsetof(struct host_def_status_block,
+	section = ((u64)mapping) + offsetof(struct host_sp_status_block,
 					    atten_status_block);
-	def_sb->atten_status_block.status_block_id = sb_id;
+	def_sb->atten_status_block.status_block_id = igu_sp_sb_index;
 
 	bp->attn_state = 0;
 
 	reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
 			     MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
-
 	for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) {
-		bp->attn_group[index].sig[0] = REG_RD(bp,
-						     reg_offset + 0x10*index);
-		bp->attn_group[index].sig[1] = REG_RD(bp,
-					       reg_offset + 0x4 + 0x10*index);
-		bp->attn_group[index].sig[2] = REG_RD(bp,
-					       reg_offset + 0x8 + 0x10*index);
-		bp->attn_group[index].sig[3] = REG_RD(bp,
-					       reg_offset + 0xc + 0x10*index);
+		int sindex;
+		/* take care of sig[0]..sig[4] */
+		for (sindex = 0; sindex < 4; sindex++)
+			bp->attn_group[index].sig[sindex] =
+			   REG_RD(bp, reg_offset + sindex*0x4 + 0x10*index);
+
+		if (CHIP_IS_E2(bp))
+			/*
+			 * enable5 is separate from the rest of the registers,
+			 * and therefore the address skip is 4
+			 * and not 16 between the different groups
+			 */
+			bp->attn_group[index].sig[4] = REG_RD(bp,
+					reg_offset + 0x10 + 0x4*index);
+		else
+			bp->attn_group[index].sig[4] = 0;
 	}
 
-	reg_offset = (port ? HC_REG_ATTN_MSG1_ADDR_L :
-			     HC_REG_ATTN_MSG0_ADDR_L);
+	if (bp->common.int_block == INT_BLOCK_HC) {
+		reg_offset = (port ? HC_REG_ATTN_MSG1_ADDR_L :
+				     HC_REG_ATTN_MSG0_ADDR_L);
 
-	REG_WR(bp, reg_offset, U64_LO(section));
-	REG_WR(bp, reg_offset + 4, U64_HI(section));
+		REG_WR(bp, reg_offset, U64_LO(section));
+		REG_WR(bp, reg_offset + 4, U64_HI(section));
+	} else if (CHIP_IS_E2(bp)) {
+		REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_L, U64_LO(section));
+		REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_H, U64_HI(section));
+	}
 
-	reg_offset = (port ? HC_REG_ATTN_NUM_P1 : HC_REG_ATTN_NUM_P0);
+	section = ((u64)mapping) + offsetof(struct host_sp_status_block,
+					    sp_sb);
 
-	val = REG_RD(bp, reg_offset);
-	val |= sb_id;
-	REG_WR(bp, reg_offset, val);
+	bnx2x_zero_sp_sb(bp);
 
-	/* USTORM */
-	section = ((u64)mapping) + offsetof(struct host_def_status_block,
-					    u_def_status_block);
-	def_sb->u_def_status_block.status_block_id = sb_id;
+	sp_sb_data.host_sb_addr.lo	= U64_LO(section);
+	sp_sb_data.host_sb_addr.hi	= U64_HI(section);
+	sp_sb_data.igu_sb_id		= igu_sp_sb_index;
+	sp_sb_data.igu_seg_id		= igu_seg_id;
+	sp_sb_data.p_func.pf_id		= func;
+	sp_sb_data.p_func.vnic_id	= BP_VN(bp);
+	sp_sb_data.p_func.vf_id		= 0xff;
 
-	REG_WR(bp, BAR_CSTRORM_INTMEM +
-	       CSTORM_DEF_SB_HOST_SB_ADDR_U_OFFSET(func), U64_LO(section));
-	REG_WR(bp, BAR_CSTRORM_INTMEM +
-	       ((CSTORM_DEF_SB_HOST_SB_ADDR_U_OFFSET(func)) + 4),
-	       U64_HI(section));
-	REG_WR8(bp, BAR_CSTRORM_INTMEM + DEF_USB_FUNC_OFF +
-		CSTORM_DEF_SB_HOST_STATUS_BLOCK_U_OFFSET(func), func);
-
-	for (index = 0; index < HC_USTORM_DEF_SB_NUM_INDICES; index++)
-		REG_WR16(bp, BAR_CSTRORM_INTMEM +
-			 CSTORM_DEF_SB_HC_DISABLE_U_OFFSET(func, index), 1);
-
-	/* CSTORM */
-	section = ((u64)mapping) + offsetof(struct host_def_status_block,
-					    c_def_status_block);
-	def_sb->c_def_status_block.status_block_id = sb_id;
-
-	REG_WR(bp, BAR_CSTRORM_INTMEM +
-	       CSTORM_DEF_SB_HOST_SB_ADDR_C_OFFSET(func), U64_LO(section));
-	REG_WR(bp, BAR_CSTRORM_INTMEM +
-	       ((CSTORM_DEF_SB_HOST_SB_ADDR_C_OFFSET(func)) + 4),
-	       U64_HI(section));
-	REG_WR8(bp, BAR_CSTRORM_INTMEM + DEF_CSB_FUNC_OFF +
-		CSTORM_DEF_SB_HOST_STATUS_BLOCK_C_OFFSET(func), func);
-
-	for (index = 0; index < HC_CSTORM_DEF_SB_NUM_INDICES; index++)
-		REG_WR16(bp, BAR_CSTRORM_INTMEM +
-			 CSTORM_DEF_SB_HC_DISABLE_C_OFFSET(func, index), 1);
-
-	/* TSTORM */
-	section = ((u64)mapping) + offsetof(struct host_def_status_block,
-					    t_def_status_block);
-	def_sb->t_def_status_block.status_block_id = sb_id;
-
-	REG_WR(bp, BAR_TSTRORM_INTMEM +
-	       TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
-	REG_WR(bp, BAR_TSTRORM_INTMEM +
-	       ((TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
-	       U64_HI(section));
-	REG_WR8(bp, BAR_TSTRORM_INTMEM + DEF_TSB_FUNC_OFF +
-		TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
-
-	for (index = 0; index < HC_TSTORM_DEF_SB_NUM_INDICES; index++)
-		REG_WR16(bp, BAR_TSTRORM_INTMEM +
-			 TSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
-
-	/* XSTORM */
-	section = ((u64)mapping) + offsetof(struct host_def_status_block,
-					    x_def_status_block);
-	def_sb->x_def_status_block.status_block_id = sb_id;
-
-	REG_WR(bp, BAR_XSTRORM_INTMEM +
-	       XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
-	REG_WR(bp, BAR_XSTRORM_INTMEM +
-	       ((XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
-	       U64_HI(section));
-	REG_WR8(bp, BAR_XSTRORM_INTMEM + DEF_XSB_FUNC_OFF +
-		XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
-
-	for (index = 0; index < HC_XSTORM_DEF_SB_NUM_INDICES; index++)
-		REG_WR16(bp, BAR_XSTRORM_INTMEM +
-			 XSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
+	bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
 
 	bp->stats_pending = 0;
 	bp->set_mac_pending = 0;
 
-	bnx2x_ack_sb(bp, sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+	bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0, IGU_INT_ENABLE, 0);
 }
 
 void bnx2x_update_coalesce(struct bnx2x *bp)
 {
-	int port = BP_PORT(bp);
 	int i;
 
-	for_each_queue(bp, i) {
-		int sb_id = bp->fp[i].sb_id;
-
-		/* HC_INDEX_U_ETH_RX_CQ_CONS */
-		REG_WR8(bp, BAR_CSTRORM_INTMEM +
-			CSTORM_SB_HC_TIMEOUT_U_OFFSET(port, sb_id,
-						      U_SB_ETH_RX_CQ_INDEX),
-			bp->rx_ticks/(4 * BNX2X_BTR));
-		REG_WR16(bp, BAR_CSTRORM_INTMEM +
-			 CSTORM_SB_HC_DISABLE_U_OFFSET(port, sb_id,
-						       U_SB_ETH_RX_CQ_INDEX),
-			 (bp->rx_ticks/(4 * BNX2X_BTR)) ? 0 : 1);
-
-		/* HC_INDEX_C_ETH_TX_CQ_CONS */
-		REG_WR8(bp, BAR_CSTRORM_INTMEM +
-			CSTORM_SB_HC_TIMEOUT_C_OFFSET(port, sb_id,
-						      C_SB_ETH_TX_CQ_INDEX),
-			bp->tx_ticks/(4 * BNX2X_BTR));
-		REG_WR16(bp, BAR_CSTRORM_INTMEM +
-			 CSTORM_SB_HC_DISABLE_C_OFFSET(port, sb_id,
-						       C_SB_ETH_TX_CQ_INDEX),
-			 (bp->tx_ticks/(4 * BNX2X_BTR)) ? 0 : 1);
-	}
+	for_each_queue(bp, i)
+		bnx2x_update_coalesce_sb(bp, bp->fp[i].fw_sb_id,
+					 bp->rx_ticks, bp->tx_ticks);
 }
 
 static void bnx2x_init_sp_ring(struct bnx2x *bp)
 {
-	int func = BP_FUNC(bp);
-
 	spin_lock_init(&bp->spq_lock);
+	atomic_set(&bp->spq_left, MAX_SPQ_PENDING);
 
-	bp->spq_left = MAX_SPQ_PENDING;
 	bp->spq_prod_idx = 0;
 	bp->dsb_sp_prod = BNX2X_SP_DSB_INDEX;
 	bp->spq_prod_bd = bp->spq;
 	bp->spq_last_bd = bp->spq_prod_bd + MAX_SP_DESC_CNT;
-
-	REG_WR(bp, XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PAGE_BASE_OFFSET(func),
-	       U64_LO(bp->spq_mapping));
-	REG_WR(bp,
-	       XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PAGE_BASE_OFFSET(func) + 4,
-	       U64_HI(bp->spq_mapping));
-
-	REG_WR(bp, XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PROD_OFFSET(func),
-	       bp->spq_prod_idx);
 }
 
-static void bnx2x_init_context(struct bnx2x *bp)
+static void bnx2x_init_eq_ring(struct bnx2x *bp)
 {
 	int i;
+	for (i = 1; i <= NUM_EQ_PAGES; i++) {
+		union event_ring_elem *elem =
+			&bp->eq_ring[EQ_DESC_CNT_PAGE * i - 1];
 
-	/* Rx */
-	for_each_queue(bp, i) {
-		struct eth_context *context = bnx2x_sp(bp, context[i].eth);
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-		u8 cl_id = fp->cl_id;
-
-		context->ustorm_st_context.common.sb_index_numbers =
-						BNX2X_RX_SB_INDEX_NUM;
-		context->ustorm_st_context.common.clientId = cl_id;
-		context->ustorm_st_context.common.status_block_id = fp->sb_id;
-		context->ustorm_st_context.common.flags =
-			(USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT |
-			 USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS);
-		context->ustorm_st_context.common.statistics_counter_id =
-						cl_id;
-		context->ustorm_st_context.common.mc_alignment_log_size =
-						BNX2X_RX_ALIGN_SHIFT;
-		context->ustorm_st_context.common.bd_buff_size =
-						bp->rx_buf_size;
-		context->ustorm_st_context.common.bd_page_base_hi =
-						U64_HI(fp->rx_desc_mapping);
-		context->ustorm_st_context.common.bd_page_base_lo =
-						U64_LO(fp->rx_desc_mapping);
-		if (!fp->disable_tpa) {
-			context->ustorm_st_context.common.flags |=
-				USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA;
-			context->ustorm_st_context.common.sge_buff_size =
-				(u16)min_t(u32, SGE_PAGE_SIZE*PAGES_PER_SGE,
-					   0xffff);
-			context->ustorm_st_context.common.sge_page_base_hi =
-						U64_HI(fp->rx_sge_mapping);
-			context->ustorm_st_context.common.sge_page_base_lo =
-						U64_LO(fp->rx_sge_mapping);
-
-			context->ustorm_st_context.common.max_sges_for_packet =
-				SGE_PAGE_ALIGN(bp->dev->mtu) >> SGE_PAGE_SHIFT;
-			context->ustorm_st_context.common.max_sges_for_packet =
-				((context->ustorm_st_context.common.
-				  max_sges_for_packet + PAGES_PER_SGE - 1) &
-				 (~(PAGES_PER_SGE - 1))) >> PAGES_PER_SGE_SHIFT;
-		}
-
-		context->ustorm_ag_context.cdu_usage =
-			CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, i),
-					       CDU_REGION_NUMBER_UCM_AG,
-					       ETH_CONNECTION_TYPE);
-
-		context->xstorm_ag_context.cdu_reserved =
-			CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, i),
-					       CDU_REGION_NUMBER_XCM_AG,
-					       ETH_CONNECTION_TYPE);
+		elem->next_page.addr.hi =
+			cpu_to_le32(U64_HI(bp->eq_mapping +
+				   BCM_PAGE_SIZE * (i % NUM_EQ_PAGES)));
+		elem->next_page.addr.lo =
+			cpu_to_le32(U64_LO(bp->eq_mapping +
+				   BCM_PAGE_SIZE*(i % NUM_EQ_PAGES)));
 	}
-
-	/* Tx */
-	for_each_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-		struct eth_context *context =
-			bnx2x_sp(bp, context[i].eth);
-
-		context->cstorm_st_context.sb_index_number =
-						C_SB_ETH_TX_CQ_INDEX;
-		context->cstorm_st_context.status_block_id = fp->sb_id;
-
-		context->xstorm_st_context.tx_bd_page_base_hi =
-						U64_HI(fp->tx_desc_mapping);
-		context->xstorm_st_context.tx_bd_page_base_lo =
-						U64_LO(fp->tx_desc_mapping);
-		context->xstorm_st_context.statistics_data = (fp->cl_id |
-				XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE);
-	}
+	bp->eq_cons = 0;
+	bp->eq_prod = NUM_EQ_DESC;
+	bp->eq_cons_sb = BNX2X_EQ_INDEX;
 }
 
 static void bnx2x_init_ind_table(struct bnx2x *bp)
@@ -3045,47 +4145,11 @@
 			bp->fp->cl_id + (i % bp->num_queues));
 }
 
-void bnx2x_set_client_config(struct bnx2x *bp)
-{
-	struct tstorm_eth_client_config tstorm_client = {0};
-	int port = BP_PORT(bp);
-	int i;
-
-	tstorm_client.mtu = bp->dev->mtu;
-	tstorm_client.config_flags =
-				(TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE |
-				 TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE);
-#ifdef BCM_VLAN
-	if (bp->rx_mode && bp->vlgrp && (bp->flags & HW_VLAN_RX_FLAG)) {
-		tstorm_client.config_flags |=
-				TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE;
-		DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
-	}
-#endif
-
-	for_each_queue(bp, i) {
-		tstorm_client.statistics_counter_id = bp->fp[i].cl_id;
-
-		REG_WR(bp, BAR_TSTRORM_INTMEM +
-		       TSTORM_CLIENT_CONFIG_OFFSET(port, bp->fp[i].cl_id),
-		       ((u32 *)&tstorm_client)[0]);
-		REG_WR(bp, BAR_TSTRORM_INTMEM +
-		       TSTORM_CLIENT_CONFIG_OFFSET(port, bp->fp[i].cl_id) + 4,
-		       ((u32 *)&tstorm_client)[1]);
-	}
-
-	DP(BNX2X_MSG_OFF, "tstorm_client: 0x%08x 0x%08x\n",
-	   ((u32 *)&tstorm_client)[0], ((u32 *)&tstorm_client)[1]);
-}
-
 void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
 {
-	struct tstorm_eth_mac_filter_config tstorm_mac_filter = {0};
 	int mode = bp->rx_mode;
-	int mask = bp->rx_mode_cl_mask;
-	int func = BP_FUNC(bp);
-	int port = BP_PORT(bp);
-	int i;
+	u16 cl_id;
+
 	/* All but management unicast packets should pass to the host as well */
 	u32 llh_mask =
 		NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST |
@@ -3093,28 +4157,32 @@
 		NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN |
 		NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN;
 
-	DP(NETIF_MSG_IFUP, "rx mode %d  mask 0x%x\n", mode, mask);
-
 	switch (mode) {
 	case BNX2X_RX_MODE_NONE: /* no Rx */
-		tstorm_mac_filter.ucast_drop_all = mask;
-		tstorm_mac_filter.mcast_drop_all = mask;
-		tstorm_mac_filter.bcast_drop_all = mask;
+		cl_id = BP_L_ID(bp);
+		bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
 		break;
 
 	case BNX2X_RX_MODE_NORMAL:
-		tstorm_mac_filter.bcast_accept_all = mask;
+		cl_id = BP_L_ID(bp);
+		bnx2x_rxq_set_mac_filters(bp, cl_id,
+			BNX2X_ACCEPT_UNICAST |
+			BNX2X_ACCEPT_BROADCAST |
+			BNX2X_ACCEPT_MULTICAST);
 		break;
 
 	case BNX2X_RX_MODE_ALLMULTI:
-		tstorm_mac_filter.mcast_accept_all = mask;
-		tstorm_mac_filter.bcast_accept_all = mask;
+		cl_id = BP_L_ID(bp);
+		bnx2x_rxq_set_mac_filters(bp, cl_id,
+			BNX2X_ACCEPT_UNICAST |
+			BNX2X_ACCEPT_BROADCAST |
+			BNX2X_ACCEPT_ALL_MULTICAST);
 		break;
 
 	case BNX2X_RX_MODE_PROMISC:
-		tstorm_mac_filter.ucast_accept_all = mask;
-		tstorm_mac_filter.mcast_accept_all = mask;
-		tstorm_mac_filter.bcast_accept_all = mask;
+		cl_id = BP_L_ID(bp);
+		bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_PROMISCUOUS_MODE);
+
 		/* pass management unicast packets as well */
 		llh_mask |= NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST;
 		break;
@@ -3125,262 +4193,64 @@
 	}
 
 	REG_WR(bp,
-	       (port ? NIG_REG_LLH1_BRB1_DRV_MASK : NIG_REG_LLH0_BRB1_DRV_MASK),
+	       BP_PORT(bp) ? NIG_REG_LLH1_BRB1_DRV_MASK :
+			     NIG_REG_LLH0_BRB1_DRV_MASK,
 	       llh_mask);
 
-	for (i = 0; i < sizeof(struct tstorm_eth_mac_filter_config)/4; i++) {
-		REG_WR(bp, BAR_TSTRORM_INTMEM +
-		       TSTORM_MAC_FILTER_CONFIG_OFFSET(func) + i * 4,
-		       ((u32 *)&tstorm_mac_filter)[i]);
+	DP(NETIF_MSG_IFUP, "rx mode %d\n"
+		"drop_ucast 0x%x\ndrop_mcast 0x%x\ndrop_bcast 0x%x\n"
+		"accp_ucast 0x%x\naccp_mcast 0x%x\naccp_bcast 0x%x\n", mode,
+		bp->mac_filters.ucast_drop_all,
+		bp->mac_filters.mcast_drop_all,
+		bp->mac_filters.bcast_drop_all,
+		bp->mac_filters.ucast_accept_all,
+		bp->mac_filters.mcast_accept_all,
+		bp->mac_filters.bcast_accept_all
+	);
 
-/*		DP(NETIF_MSG_IFUP, "tstorm_mac_filter[%d]: 0x%08x\n", i,
-		   ((u32 *)&tstorm_mac_filter)[i]); */
-	}
-
-	if (mode != BNX2X_RX_MODE_NONE)
-		bnx2x_set_client_config(bp);
+	storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
 }
 
 static void bnx2x_init_internal_common(struct bnx2x *bp)
 {
 	int i;
 
+	if (!CHIP_IS_E1(bp)) {
+
+		/* xstorm needs to know whether to add  ovlan to packets or not,
+		 * in switch-independent we'll write 0 to here... */
+		REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNCTION_MODE_OFFSET,
+			bp->mf_mode);
+		REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNCTION_MODE_OFFSET,
+			bp->mf_mode);
+		REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNCTION_MODE_OFFSET,
+			bp->mf_mode);
+		REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNCTION_MODE_OFFSET,
+			bp->mf_mode);
+	}
+
 	/* Zero this manually as its initialization is
 	   currently missing in the initTool */
 	for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
 		REG_WR(bp, BAR_USTRORM_INTMEM +
 		       USTORM_AGG_DATA_OFFSET + i * 4, 0);
+	if (CHIP_IS_E2(bp)) {
+		REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_IGU_MODE_OFFSET,
+			CHIP_INT_MODE_IS_BC(bp) ?
+			HC_IGU_BC_MODE : HC_IGU_NBC_MODE);
+	}
 }
 
 static void bnx2x_init_internal_port(struct bnx2x *bp)
 {
-	int port = BP_PORT(bp);
-
-	REG_WR(bp,
-	       BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_U_OFFSET(port), BNX2X_BTR);
-	REG_WR(bp,
-	       BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_C_OFFSET(port), BNX2X_BTR);
-	REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
-	REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
-}
-
-static void bnx2x_init_internal_func(struct bnx2x *bp)
-{
-	struct tstorm_eth_function_common_config tstorm_config = {0};
-	struct stats_indication_flags stats_flags = {0};
-	int port = BP_PORT(bp);
-	int func = BP_FUNC(bp);
-	int i, j;
-	u32 offset;
-	u16 max_agg_size;
-
-	tstorm_config.config_flags = RSS_FLAGS(bp);
-
-	if (is_multi(bp))
-		tstorm_config.rss_result_mask = MULTI_MASK;
-
-	/* Enable TPA if needed */
-	if (bp->flags & TPA_ENABLE_FLAG)
-		tstorm_config.config_flags |=
-			TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA;
-
-	if (IS_E1HMF(bp))
-		tstorm_config.config_flags |=
-				TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM;
-
-	tstorm_config.leading_client_id = BP_L_ID(bp);
-
-	REG_WR(bp, BAR_TSTRORM_INTMEM +
-	       TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(func),
-	       (*(u32 *)&tstorm_config));
-
-	bp->rx_mode = BNX2X_RX_MODE_NONE; /* no rx until link is up */
-	bp->rx_mode_cl_mask = (1 << BP_L_ID(bp));
-	bnx2x_set_storm_rx_mode(bp);
-
-	for_each_queue(bp, i) {
-		u8 cl_id = bp->fp[i].cl_id;
-
-		/* reset xstorm per client statistics */
-		offset = BAR_XSTRORM_INTMEM +
-			 XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cl_id);
-		for (j = 0;
-		     j < sizeof(struct xstorm_per_client_stats) / 4; j++)
-			REG_WR(bp, offset + j*4, 0);
-
-		/* reset tstorm per client statistics */
-		offset = BAR_TSTRORM_INTMEM +
-			 TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cl_id);
-		for (j = 0;
-		     j < sizeof(struct tstorm_per_client_stats) / 4; j++)
-			REG_WR(bp, offset + j*4, 0);
-
-		/* reset ustorm per client statistics */
-		offset = BAR_USTRORM_INTMEM +
-			 USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cl_id);
-		for (j = 0;
-		     j < sizeof(struct ustorm_per_client_stats) / 4; j++)
-			REG_WR(bp, offset + j*4, 0);
-	}
-
-	/* Init statistics related context */
-	stats_flags.collect_eth = 1;
-
-	REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(func),
-	       ((u32 *)&stats_flags)[0]);
-	REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(func) + 4,
-	       ((u32 *)&stats_flags)[1]);
-
-	REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(func),
-	       ((u32 *)&stats_flags)[0]);
-	REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(func) + 4,
-	       ((u32 *)&stats_flags)[1]);
-
-	REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_STATS_FLAGS_OFFSET(func),
-	       ((u32 *)&stats_flags)[0]);
-	REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_STATS_FLAGS_OFFSET(func) + 4,
-	       ((u32 *)&stats_flags)[1]);
-
-	REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(func),
-	       ((u32 *)&stats_flags)[0]);
-	REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(func) + 4,
-	       ((u32 *)&stats_flags)[1]);
-
-	REG_WR(bp, BAR_XSTRORM_INTMEM +
-	       XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func),
-	       U64_LO(bnx2x_sp_mapping(bp, fw_stats)));
-	REG_WR(bp, BAR_XSTRORM_INTMEM +
-	       XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func) + 4,
-	       U64_HI(bnx2x_sp_mapping(bp, fw_stats)));
-
-	REG_WR(bp, BAR_TSTRORM_INTMEM +
-	       TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func),
-	       U64_LO(bnx2x_sp_mapping(bp, fw_stats)));
-	REG_WR(bp, BAR_TSTRORM_INTMEM +
-	       TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func) + 4,
-	       U64_HI(bnx2x_sp_mapping(bp, fw_stats)));
-
-	REG_WR(bp, BAR_USTRORM_INTMEM +
-	       USTORM_ETH_STATS_QUERY_ADDR_OFFSET(func),
-	       U64_LO(bnx2x_sp_mapping(bp, fw_stats)));
-	REG_WR(bp, BAR_USTRORM_INTMEM +
-	       USTORM_ETH_STATS_QUERY_ADDR_OFFSET(func) + 4,
-	       U64_HI(bnx2x_sp_mapping(bp, fw_stats)));
-
-	if (CHIP_IS_E1H(bp)) {
-		REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNCTION_MODE_OFFSET,
-			IS_E1HMF(bp));
-		REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNCTION_MODE_OFFSET,
-			IS_E1HMF(bp));
-		REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNCTION_MODE_OFFSET,
-			IS_E1HMF(bp));
-		REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNCTION_MODE_OFFSET,
-			IS_E1HMF(bp));
-
-		REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_E1HOV_OFFSET(func),
-			 bp->e1hov);
-	}
-
-	/* Init CQ ring mapping and aggregation size, the FW limit is 8 frags */
-	max_agg_size = min_t(u32, (min_t(u32, 8, MAX_SKB_FRAGS) *
-				   SGE_PAGE_SIZE * PAGES_PER_SGE), 0xffff);
-	for_each_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-
-		REG_WR(bp, BAR_USTRORM_INTMEM +
-		       USTORM_CQE_PAGE_BASE_OFFSET(port, fp->cl_id),
-		       U64_LO(fp->rx_comp_mapping));
-		REG_WR(bp, BAR_USTRORM_INTMEM +
-		       USTORM_CQE_PAGE_BASE_OFFSET(port, fp->cl_id) + 4,
-		       U64_HI(fp->rx_comp_mapping));
-
-		/* Next page */
-		REG_WR(bp, BAR_USTRORM_INTMEM +
-		       USTORM_CQE_PAGE_NEXT_OFFSET(port, fp->cl_id),
-		       U64_LO(fp->rx_comp_mapping + BCM_PAGE_SIZE));
-		REG_WR(bp, BAR_USTRORM_INTMEM +
-		       USTORM_CQE_PAGE_NEXT_OFFSET(port, fp->cl_id) + 4,
-		       U64_HI(fp->rx_comp_mapping + BCM_PAGE_SIZE));
-
-		REG_WR16(bp, BAR_USTRORM_INTMEM +
-			 USTORM_MAX_AGG_SIZE_OFFSET(port, fp->cl_id),
-			 max_agg_size);
-	}
-
-	/* dropless flow control */
-	if (CHIP_IS_E1H(bp)) {
-		struct ustorm_eth_rx_pause_data_e1h rx_pause = {0};
-
-		rx_pause.bd_thr_low = 250;
-		rx_pause.cqe_thr_low = 250;
-		rx_pause.cos = 1;
-		rx_pause.sge_thr_low = 0;
-		rx_pause.bd_thr_high = 350;
-		rx_pause.cqe_thr_high = 350;
-		rx_pause.sge_thr_high = 0;
-
-		for_each_queue(bp, i) {
-			struct bnx2x_fastpath *fp = &bp->fp[i];
-
-			if (!fp->disable_tpa) {
-				rx_pause.sge_thr_low = 150;
-				rx_pause.sge_thr_high = 250;
-			}
-
-
-			offset = BAR_USTRORM_INTMEM +
-				 USTORM_ETH_RING_PAUSE_DATA_OFFSET(port,
-								   fp->cl_id);
-			for (j = 0;
-			     j < sizeof(struct ustorm_eth_rx_pause_data_e1h)/4;
-			     j++)
-				REG_WR(bp, offset + j*4,
-				       ((u32 *)&rx_pause)[j]);
-		}
-	}
-
-	memset(&(bp->cmng), 0, sizeof(struct cmng_struct_per_port));
-
-	/* Init rate shaping and fairness contexts */
-	if (IS_E1HMF(bp)) {
-		int vn;
-
-		/* During init there is no active link
-		   Until link is up, set link rate to 10Gbps */
-		bp->link_vars.line_speed = SPEED_10000;
-		bnx2x_init_port_minmax(bp);
-
-		if (!BP_NOMCP(bp))
-			bp->mf_config =
-			      SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
-		bnx2x_calc_vn_weight_sum(bp);
-
-		for (vn = VN_0; vn < E1HVN_MAX; vn++)
-			bnx2x_init_vn_minmax(bp, 2*vn + port);
-
-		/* Enable rate shaping and fairness */
-		bp->cmng.flags.cmng_enables |=
-					CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN;
-
-	} else {
-		/* rate shaping and fairness are disabled */
-		DP(NETIF_MSG_IFUP,
-		   "single function mode  minmax will be disabled\n");
-	}
-
-
-	/* Store cmng structures to internal memory */
-	if (bp->port.pmf)
-		for (i = 0; i < sizeof(struct cmng_struct_per_port) / 4; i++)
-			REG_WR(bp, BAR_XSTRORM_INTMEM +
-			       XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) + i * 4,
-			       ((u32 *)(&bp->cmng))[i]);
+	/* port */
 }
 
 static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
 {
 	switch (load_code) {
 	case FW_MSG_CODE_DRV_LOAD_COMMON:
+	case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
 		bnx2x_init_internal_common(bp);
 		/* no break */
 
@@ -3389,7 +4259,8 @@
 		/* no break */
 
 	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
-		bnx2x_init_internal_func(bp);
+		/* internal memory per function is
+		   initialized inside bnx2x_pf_init */
 		break;
 
 	default:
@@ -3398,43 +4269,63 @@
 	}
 }
 
+static void bnx2x_init_fp_sb(struct bnx2x *bp, int fp_idx)
+{
+	struct bnx2x_fastpath *fp = &bp->fp[fp_idx];
+
+	fp->state = BNX2X_FP_STATE_CLOSED;
+
+	fp->index = fp->cid = fp_idx;
+	fp->cl_id = BP_L_ID(bp) + fp_idx;
+	fp->fw_sb_id = bp->base_fw_ndsb + fp->cl_id + CNIC_CONTEXT_USE;
+	fp->igu_sb_id = bp->igu_base_sb + fp_idx + CNIC_CONTEXT_USE;
+	/* qZone id equals to FW (per path) client id */
+	fp->cl_qzone_id  = fp->cl_id +
+			   BP_PORT(bp)*(CHIP_IS_E2(bp) ? ETH_MAX_RX_CLIENTS_E2 :
+				ETH_MAX_RX_CLIENTS_E1H);
+	/* init shortcut */
+	fp->ustorm_rx_prods_offset = CHIP_IS_E2(bp) ?
+			    USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id) :
+			    USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id);
+	/* Setup SB indicies */
+	fp->rx_cons_sb = BNX2X_RX_SB_INDEX;
+	fp->tx_cons_sb = BNX2X_TX_SB_INDEX;
+
+	DP(NETIF_MSG_IFUP, "queue[%d]:  bnx2x_init_sb(%p,%p)  "
+				   "cl_id %d  fw_sb %d  igu_sb %d\n",
+		   fp_idx, bp, fp->status_blk.e1x_sb, fp->cl_id, fp->fw_sb_id,
+		   fp->igu_sb_id);
+	bnx2x_init_sb(bp, fp->status_blk_mapping, BNX2X_VF_ID_INVALID, false,
+		      fp->fw_sb_id, fp->igu_sb_id);
+
+	bnx2x_update_fpsb_idx(fp);
+}
+
 void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
 {
 	int i;
 
-	for_each_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-
-		fp->bp = bp;
-		fp->state = BNX2X_FP_STATE_CLOSED;
-		fp->index = i;
-		fp->cl_id = BP_L_ID(bp) + i;
+	for_each_queue(bp, i)
+		bnx2x_init_fp_sb(bp, i);
 #ifdef BCM_CNIC
-		fp->sb_id = fp->cl_id + 1;
-#else
-		fp->sb_id = fp->cl_id;
+
+	bnx2x_init_sb(bp, bp->cnic_sb_mapping,
+		      BNX2X_VF_ID_INVALID, false,
+		      CNIC_SB_ID(bp), CNIC_IGU_SB_ID(bp));
+
 #endif
-		DP(NETIF_MSG_IFUP,
-		   "queue[%d]:  bnx2x_init_sb(%p,%p)  cl_id %d  sb %d\n",
-		   i, bp, fp->status_blk, fp->cl_id, fp->sb_id);
-		bnx2x_init_sb(bp, fp->status_blk, fp->status_blk_mapping,
-			      fp->sb_id);
-		bnx2x_update_fpsb_idx(fp);
-	}
 
 	/* ensure status block indices were read */
 	rmb();
 
-
-	bnx2x_init_def_sb(bp, bp->def_status_blk, bp->def_status_blk_mapping,
-			  DEF_SB_ID);
+	bnx2x_init_def_sb(bp);
 	bnx2x_update_dsb_idx(bp);
-	bnx2x_update_coalesce(bp);
 	bnx2x_init_rx_rings(bp);
-	bnx2x_init_tx_ring(bp);
+	bnx2x_init_tx_rings(bp);
 	bnx2x_init_sp_ring(bp);
-	bnx2x_init_context(bp);
+	bnx2x_init_eq_ring(bp);
 	bnx2x_init_internal(bp, load_code);
+	bnx2x_pf_init(bp);
 	bnx2x_init_ind_table(bp);
 	bnx2x_stats_init(bp);
 
@@ -3495,7 +4386,6 @@
 static void bnx2x_gunzip_end(struct bnx2x *bp)
 {
 	kfree(bp->strm->workspace);
-
 	kfree(bp->strm);
 	bp->strm = NULL;
 
@@ -3593,8 +4483,6 @@
 	else
 		factor = 1;
 
-	DP(NETIF_MSG_HW, "start part1\n");
-
 	/* Disable inputs of parser neighbor blocks */
 	REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x0);
 	REG_WR(bp, TCM_REG_PRS_IFEN, 0x0);
@@ -3731,9 +4619,19 @@
 static void enable_blocks_attention(struct bnx2x *bp)
 {
 	REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
-	REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0);
+	if (CHIP_IS_E2(bp))
+		REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0x40);
+	else
+		REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0);
 	REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
 	REG_WR(bp, CFC_REG_CFC_INT_MASK, 0);
+	/*
+	 * mask read length error interrupts in brb for parser
+	 * (parsing unit and 'checksum and crc' unit)
+	 * these errors are legal (PU reads fixed length and CAC can cause
+	 * read length error on truncated packets)
+	 */
+	REG_WR(bp, BRB1_REG_BRB1_INT_MASK, 0xFC00);
 	REG_WR(bp, QM_REG_QM_INT_MASK, 0);
 	REG_WR(bp, TM_REG_TM_INT_MASK, 0);
 	REG_WR(bp, XSDM_REG_XSDM_INT_MASK_0, 0);
@@ -3752,8 +4650,16 @@
 	REG_WR(bp, CCM_REG_CCM_INT_MASK, 0);
 /*	REG_WR(bp, CSEM_REG_CSEM_INT_MASK_0, 0); */
 /*	REG_WR(bp, CSEM_REG_CSEM_INT_MASK_1, 0); */
+
 	if (CHIP_REV_IS_FPGA(bp))
 		REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000);
+	else if (CHIP_IS_E2(bp))
+		REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0,
+			   (PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF
+				| PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT
+				| PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN
+				| PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED
+				| PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED));
 	else
 		REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x480000);
 	REG_WR(bp, TSDM_REG_TSDM_INT_MASK_0, 0);
@@ -3771,42 +4677,41 @@
 	u32 addr;
 	u32 mask;
 } bnx2x_parity_mask[] = {
-	{PXP_REG_PXP_PRTY_MASK, 0xffffffff},
-	{PXP2_REG_PXP2_PRTY_MASK_0, 0xffffffff},
-	{PXP2_REG_PXP2_PRTY_MASK_1, 0xffffffff},
-	{HC_REG_HC_PRTY_MASK, 0xffffffff},
-	{MISC_REG_MISC_PRTY_MASK, 0xffffffff},
-	{QM_REG_QM_PRTY_MASK, 0x0},
-	{DORQ_REG_DORQ_PRTY_MASK, 0x0},
+	{PXP_REG_PXP_PRTY_MASK,		0x3ffffff},
+	{PXP2_REG_PXP2_PRTY_MASK_0,	0xffffffff},
+	{PXP2_REG_PXP2_PRTY_MASK_1,	0x7f},
+	{HC_REG_HC_PRTY_MASK,		0x7},
+	{MISC_REG_MISC_PRTY_MASK,	0x1},
+	{QM_REG_QM_PRTY_MASK,		0x0},
+	{DORQ_REG_DORQ_PRTY_MASK,	0x0},
 	{GRCBASE_UPB + PB_REG_PB_PRTY_MASK, 0x0},
 	{GRCBASE_XPB + PB_REG_PB_PRTY_MASK, 0x0},
-	{SRC_REG_SRC_PRTY_MASK, 0x4}, /* bit 2 */
-	{CDU_REG_CDU_PRTY_MASK, 0x0},
-	{CFC_REG_CFC_PRTY_MASK, 0x0},
-	{DBG_REG_DBG_PRTY_MASK, 0x0},
-	{DMAE_REG_DMAE_PRTY_MASK, 0x0},
-	{BRB1_REG_BRB1_PRTY_MASK, 0x0},
-	{PRS_REG_PRS_PRTY_MASK, (1<<6)},/* bit 6 */
-	{TSDM_REG_TSDM_PRTY_MASK, 0x18},/* bit 3,4 */
-	{CSDM_REG_CSDM_PRTY_MASK, 0x8},	/* bit 3 */
-	{USDM_REG_USDM_PRTY_MASK, 0x38},/* bit 3,4,5 */
-	{XSDM_REG_XSDM_PRTY_MASK, 0x8},	/* bit 3 */
-	{TSEM_REG_TSEM_PRTY_MASK_0, 0x0},
-	{TSEM_REG_TSEM_PRTY_MASK_1, 0x0},
-	{USEM_REG_USEM_PRTY_MASK_0, 0x0},
-	{USEM_REG_USEM_PRTY_MASK_1, 0x0},
-	{CSEM_REG_CSEM_PRTY_MASK_0, 0x0},
-	{CSEM_REG_CSEM_PRTY_MASK_1, 0x0},
-	{XSEM_REG_XSEM_PRTY_MASK_0, 0x0},
-	{XSEM_REG_XSEM_PRTY_MASK_1, 0x0}
+	{SRC_REG_SRC_PRTY_MASK,		0x4}, /* bit 2 */
+	{CDU_REG_CDU_PRTY_MASK,		0x0},
+	{CFC_REG_CFC_PRTY_MASK,		0x0},
+	{DBG_REG_DBG_PRTY_MASK,		0x0},
+	{DMAE_REG_DMAE_PRTY_MASK,	0x0},
+	{BRB1_REG_BRB1_PRTY_MASK,	0x0},
+	{PRS_REG_PRS_PRTY_MASK,		(1<<6)},/* bit 6 */
+	{TSDM_REG_TSDM_PRTY_MASK,	0x18},	/* bit 3,4 */
+	{CSDM_REG_CSDM_PRTY_MASK,	0x8},	/* bit 3 */
+	{USDM_REG_USDM_PRTY_MASK,	0x38},  /* bit 3,4,5 */
+	{XSDM_REG_XSDM_PRTY_MASK,	0x8},	/* bit 3 */
+	{TSEM_REG_TSEM_PRTY_MASK_0,	0x0},
+	{TSEM_REG_TSEM_PRTY_MASK_1,	0x0},
+	{USEM_REG_USEM_PRTY_MASK_0,	0x0},
+	{USEM_REG_USEM_PRTY_MASK_1,	0x0},
+	{CSEM_REG_CSEM_PRTY_MASK_0,	0x0},
+	{CSEM_REG_CSEM_PRTY_MASK_1,	0x0},
+	{XSEM_REG_XSEM_PRTY_MASK_0,	0x0},
+	{XSEM_REG_XSEM_PRTY_MASK_1,	0x0}
 };
 
 static void enable_blocks_parity(struct bnx2x *bp)
 {
-	int i, mask_arr_len =
-		sizeof(bnx2x_parity_mask)/(sizeof(bnx2x_parity_mask[0]));
+	int i;
 
-	for (i = 0; i < mask_arr_len; i++)
+	for (i = 0; i < ARRAY_SIZE(bnx2x_parity_mask); i++)
 		REG_WR(bp, bnx2x_parity_mask[i].addr,
 			bnx2x_parity_mask[i].mask);
 }
@@ -3862,17 +4767,12 @@
 	 */
 	else if (val == SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE)
 		for (port = PORT_0; port < PORT_MAX; port++) {
-			u32 phy_type =
-				SHMEM_RD(bp, dev_info.port_hw_config[port].
-					 external_phy_config) &
-				PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
 			is_required |=
-				((phy_type ==
-				  PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) ||
-				 (phy_type ==
-				  PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) ||
-				 (phy_type ==
-				  PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481));
+				bnx2x_fan_failure_det_req(
+					bp,
+					bp->common.shmem_base,
+					bp->common.shmem2_base,
+					port);
 		}
 
 	DP(NETIF_MSG_HW, "fan detection setting: %d\n", is_required);
@@ -3896,26 +4796,97 @@
 	REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
 }
 
-static int bnx2x_init_common(struct bnx2x *bp)
+static void bnx2x_pretend_func(struct bnx2x *bp, u8 pretend_func_num)
+{
+	u32 offset = 0;
+
+	if (CHIP_IS_E1(bp))
+		return;
+	if (CHIP_IS_E1H(bp) && (pretend_func_num >= E1H_FUNC_MAX))
+		return;
+
+	switch (BP_ABS_FUNC(bp)) {
+	case 0:
+		offset = PXP2_REG_PGL_PRETEND_FUNC_F0;
+		break;
+	case 1:
+		offset = PXP2_REG_PGL_PRETEND_FUNC_F1;
+		break;
+	case 2:
+		offset = PXP2_REG_PGL_PRETEND_FUNC_F2;
+		break;
+	case 3:
+		offset = PXP2_REG_PGL_PRETEND_FUNC_F3;
+		break;
+	case 4:
+		offset = PXP2_REG_PGL_PRETEND_FUNC_F4;
+		break;
+	case 5:
+		offset = PXP2_REG_PGL_PRETEND_FUNC_F5;
+		break;
+	case 6:
+		offset = PXP2_REG_PGL_PRETEND_FUNC_F6;
+		break;
+	case 7:
+		offset = PXP2_REG_PGL_PRETEND_FUNC_F7;
+		break;
+	default:
+		return;
+	}
+
+	REG_WR(bp, offset, pretend_func_num);
+	REG_RD(bp, offset);
+	DP(NETIF_MSG_HW, "Pretending to func %d\n", pretend_func_num);
+}
+
+static void bnx2x_pf_disable(struct bnx2x *bp)
+{
+	u32 val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
+	val &= ~IGU_PF_CONF_FUNC_EN;
+
+	REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
+	REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0);
+	REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 0);
+}
+
+static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 {
 	u32 val, i;
-#ifdef BCM_CNIC
-	u32 wb_write[2];
-#endif
 
-	DP(BNX2X_MSG_MCP, "starting common init  func %d\n", BP_FUNC(bp));
+	DP(BNX2X_MSG_MCP, "starting common init  func %d\n", BP_ABS_FUNC(bp));
 
 	bnx2x_reset_common(bp);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc);
 
 	bnx2x_init_block(bp, MISC_BLOCK, COMMON_STAGE);
-	if (CHIP_IS_E1H(bp))
-		REG_WR(bp, MISC_REG_E1HMF_MODE, IS_E1HMF(bp));
+	if (!CHIP_IS_E1(bp))
+		REG_WR(bp, MISC_REG_E1HMF_MODE, IS_MF(bp));
 
-	REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x100);
-	msleep(30);
-	REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x0);
+	if (CHIP_IS_E2(bp)) {
+		u8 fid;
+
+		/**
+		 * 4-port mode or 2-port mode we need to turn of master-enable
+		 * for everyone, after that, turn it back on for self.
+		 * so, we disregard multi-function or not, and always disable
+		 * for all functions on the given path, this means 0,2,4,6 for
+		 * path 0 and 1,3,5,7 for path 1
+		 */
+		for (fid = BP_PATH(bp); fid  < E2_FUNC_MAX*2; fid += 2) {
+			if (fid == BP_ABS_FUNC(bp)) {
+				REG_WR(bp,
+				    PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER,
+				    1);
+				continue;
+			}
+
+			bnx2x_pretend_func(bp, fid);
+			/* clear pf enable */
+			bnx2x_pf_disable(bp);
+			bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
+		}
+	}
 
 	bnx2x_init_block(bp, PXP_BLOCK, COMMON_STAGE);
 	if (CHIP_IS_E1(bp)) {
@@ -3943,12 +4914,7 @@
 	REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
 #endif
 
-	REG_WR(bp, PXP2_REG_RQ_CDU_P_SIZE, 2);
-#ifdef BCM_CNIC
-	REG_WR(bp, PXP2_REG_RQ_TM_P_SIZE, 5);
-	REG_WR(bp, PXP2_REG_RQ_QM_P_SIZE, 5);
-	REG_WR(bp, PXP2_REG_RQ_SRC_P_SIZE, 5);
-#endif
+	bnx2x_ilt_init_page_size(bp, INITOP_SET);
 
 	if (CHIP_REV_IS_FPGA(bp) && CHIP_IS_E1H(bp))
 		REG_WR(bp, PXP2_REG_PGL_TAGS_LIMIT, 0x1);
@@ -3967,9 +4933,65 @@
 		return -EBUSY;
 	}
 
+	/* Timers bug workaround E2 only. We need to set the entire ILT to
+	 * have entries with value "0" and valid bit on.
+	 * This needs to be done by the first PF that is loaded in a path
+	 * (i.e. common phase)
+	 */
+	if (CHIP_IS_E2(bp)) {
+		struct ilt_client_info ilt_cli;
+		struct bnx2x_ilt ilt;
+		memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
+		memset(&ilt, 0, sizeof(struct bnx2x_ilt));
+
+		/* initalize dummy TM client */
+		ilt_cli.start = 0;
+		ilt_cli.end = ILT_NUM_PAGE_ENTRIES - 1;
+		ilt_cli.client_num = ILT_CLIENT_TM;
+
+		/* Step 1: set zeroes to all ilt page entries with valid bit on
+		 * Step 2: set the timers first/last ilt entry to point
+		 * to the entire range to prevent ILT range error for 3rd/4th
+		 * vnic	(this code assumes existance of the vnic)
+		 *
+		 * both steps performed by call to bnx2x_ilt_client_init_op()
+		 * with dummy TM client
+		 *
+		 * we must use pretend since PXP2_REG_RQ_##blk##_FIRST_ILT
+		 * and his brother are split registers
+		 */
+		bnx2x_pretend_func(bp, (BP_PATH(bp) + 6));
+		bnx2x_ilt_client_init_op_ilt(bp, &ilt, &ilt_cli, INITOP_CLEAR);
+		bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
+
+		REG_WR(bp, PXP2_REG_RQ_DRAM_ALIGN, BNX2X_PXP_DRAM_ALIGN);
+		REG_WR(bp, PXP2_REG_RQ_DRAM_ALIGN_RD, BNX2X_PXP_DRAM_ALIGN);
+		REG_WR(bp, PXP2_REG_RQ_DRAM_ALIGN_SEL, 1);
+	}
+
+
 	REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
 	REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
 
+	if (CHIP_IS_E2(bp)) {
+		int factor = CHIP_REV_IS_EMUL(bp) ? 1000 :
+				(CHIP_REV_IS_FPGA(bp) ? 400 : 0);
+		bnx2x_init_block(bp, PGLUE_B_BLOCK, COMMON_STAGE);
+
+		bnx2x_init_block(bp, ATC_BLOCK, COMMON_STAGE);
+
+		/* let the HW do it's magic ... */
+		do {
+			msleep(200);
+			val = REG_RD(bp, ATC_REG_ATC_INIT_DONE);
+		} while (factor-- && (val != 1));
+
+		if (val != 1) {
+			BNX2X_ERR("ATC_INIT failed\n");
+			return -EBUSY;
+		}
+	}
+
 	bnx2x_init_block(bp, DMAE_BLOCK, COMMON_STAGE);
 
 	/* clean the DMAE memory */
@@ -3988,20 +5010,12 @@
 
 	bnx2x_init_block(bp, QM_BLOCK, COMMON_STAGE);
 
-#ifdef BCM_CNIC
-	wb_write[0] = 0;
-	wb_write[1] = 0;
-	for (i = 0; i < 64; i++) {
-		REG_WR(bp, QM_REG_BASEADDR + i*4, 1024 * 4 * (i%16));
-		bnx2x_init_ind_wr(bp, QM_REG_PTRTBL + i*8, wb_write, 2);
+	if (CHIP_MODE_IS_4_PORT(bp))
+		bnx2x_init_block(bp, QM_4PORT_BLOCK, COMMON_STAGE);
 
-		if (CHIP_IS_E1H(bp)) {
-			REG_WR(bp, QM_REG_BASEADDR_EXT_A + i*4, 1024*4*(i%16));
-			bnx2x_init_ind_wr(bp, QM_REG_PTRTBL_EXT_A + i*8,
-					  wb_write, 2);
-		}
-	}
-#endif
+	/* QM queues pointers table */
+	bnx2x_qm_init_ptr_table(bp, bp->qm_cid_count, INITOP_SET);
+
 	/* soft reset pulse */
 	REG_WR(bp, QM_REG_SOFT_RESET, 1);
 	REG_WR(bp, QM_REG_SOFT_RESET, 0);
@@ -4011,21 +5025,35 @@
 #endif
 
 	bnx2x_init_block(bp, DQ_BLOCK, COMMON_STAGE);
-	REG_WR(bp, DORQ_REG_DPM_CID_OFST, BCM_PAGE_SHIFT);
+	REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT);
+
 	if (!CHIP_REV_IS_SLOW(bp)) {
 		/* enable hw interrupt from doorbell Q */
 		REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
 	}
 
 	bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
+	if (CHIP_MODE_IS_4_PORT(bp)) {
+		REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD, 248);
+		REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD, 328);
+	}
+
 	bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
 	REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
 #ifndef BCM_CNIC
 	/* set NIC mode */
 	REG_WR(bp, PRS_REG_NIC_MODE, 1);
 #endif
-	if (CHIP_IS_E1H(bp))
-		REG_WR(bp, PRS_REG_E1HOV_MODE, IS_E1HMF(bp));
+	if (!CHIP_IS_E1(bp))
+		REG_WR(bp, PRS_REG_E1HOV_MODE, IS_MF(bp));
+
+	if (CHIP_IS_E2(bp)) {
+		/* Bit-map indicating which L2 hdrs may appear after the
+		   basic Ethernet header */
+		int has_ovlan = IS_MF(bp);
+		REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
+		REG_WR(bp, PRS_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
+	}
 
 	bnx2x_init_block(bp, TSDM_BLOCK, COMMON_STAGE);
 	bnx2x_init_block(bp, CSDM_BLOCK, COMMON_STAGE);
@@ -4042,6 +5070,9 @@
 	bnx2x_init_block(bp, CSEM_BLOCK, COMMON_STAGE);
 	bnx2x_init_block(bp, XSEM_BLOCK, COMMON_STAGE);
 
+	if (CHIP_MODE_IS_4_PORT(bp))
+		bnx2x_init_block(bp, XSEM_4PORT_BLOCK, COMMON_STAGE);
+
 	/* sync semi rtc */
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
 	       0x80000000);
@@ -4052,9 +5083,16 @@
 	bnx2x_init_block(bp, XPB_BLOCK, COMMON_STAGE);
 	bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE);
 
+	if (CHIP_IS_E2(bp)) {
+		int has_ovlan = IS_MF(bp);
+		REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
+		REG_WR(bp, PBF_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
+	}
+
 	REG_WR(bp, SRC_REG_SOFT_RST, 1);
 	for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4)
 		REG_WR(bp, i, random32());
+
 	bnx2x_init_block(bp, SRCH_BLOCK, COMMON_STAGE);
 #ifdef BCM_CNIC
 	REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
@@ -4089,6 +5127,11 @@
 	REG_WR(bp, CFC_REG_DEBUG0, 0x20020000);
 
 	bnx2x_init_block(bp, HC_BLOCK, COMMON_STAGE);
+
+	if (CHIP_IS_E2(bp) && BP_NOMCP(bp))
+		REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x36);
+
+	bnx2x_init_block(bp, IGU_BLOCK, COMMON_STAGE);
 	bnx2x_init_block(bp, MISC_AEU_BLOCK, COMMON_STAGE);
 
 	bnx2x_init_block(bp, PXPCS_BLOCK, COMMON_STAGE);
@@ -4096,15 +5139,34 @@
 	REG_WR(bp, 0x2814, 0xffffffff);
 	REG_WR(bp, 0x3820, 0xffffffff);
 
+	if (CHIP_IS_E2(bp)) {
+		REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_CONTROL_5,
+			   (PXPCS_TL_CONTROL_5_ERR_UNSPPORT1 |
+				PXPCS_TL_CONTROL_5_ERR_UNSPPORT));
+		REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_FUNC345_STAT,
+			   (PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT4 |
+				PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT3 |
+				PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT2));
+		REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_FUNC678_STAT,
+			   (PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT7 |
+				PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT6 |
+				PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5));
+	}
+
 	bnx2x_init_block(bp, EMAC0_BLOCK, COMMON_STAGE);
 	bnx2x_init_block(bp, EMAC1_BLOCK, COMMON_STAGE);
 	bnx2x_init_block(bp, DBU_BLOCK, COMMON_STAGE);
 	bnx2x_init_block(bp, DBG_BLOCK, COMMON_STAGE);
 
 	bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE);
-	if (CHIP_IS_E1H(bp)) {
-		REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_E1HMF(bp));
-		REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_E1HMF(bp));
+	if (!CHIP_IS_E1(bp)) {
+		REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp));
+		REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF(bp));
+	}
+	if (CHIP_IS_E2(bp)) {
+		/* Bit-map indicating which L2 hdrs may appear after the
+		   basic Ethernet header */
+		REG_WR(bp, NIG_REG_P0_HDRS_AFTER_BASIC, (IS_MF(bp) ? 7 : 6));
 	}
 
 	if (CHIP_REV_IS_SLOW(bp))
@@ -4128,28 +5190,22 @@
 	}
 	REG_WR(bp, CFC_REG_DEBUG0, 0);
 
-	/* read NIG statistic
-	   to see if this is our first up since powerup */
-	bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
-	val = *bnx2x_sp(bp, wb_data[0]);
+	if (CHIP_IS_E1(bp)) {
+		/* read NIG statistic
+		   to see if this is our first up since powerup */
+		bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
+		val = *bnx2x_sp(bp, wb_data[0]);
 
-	/* do internal memory self test */
-	if ((CHIP_IS_E1(bp)) && (val == 0) && bnx2x_int_mem_test(bp)) {
-		BNX2X_ERR("internal mem self test failed\n");
-		return -EBUSY;
+		/* do internal memory self test */
+		if ((val == 0) && bnx2x_int_mem_test(bp)) {
+			BNX2X_ERR("internal mem self test failed\n");
+			return -EBUSY;
+		}
 	}
 
-	switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) {
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-		bp->port.need_hw_lock = 1;
-		break;
-
-	default:
-		break;
-	}
+	bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
+						       bp->common.shmem_base,
+						       bp->common.shmem2_base);
 
 	bnx2x_setup_fan_failure_detection(bp);
 
@@ -4161,16 +5217,30 @@
 		enable_blocks_parity(bp);
 
 	if (!BP_NOMCP(bp)) {
-		bnx2x_acquire_phy_lock(bp);
-		bnx2x_common_init_phy(bp, bp->common.shmem_base);
-		bnx2x_release_phy_lock(bp);
+		/* In E2 2-PORT mode, same ext phy is used for the two paths */
+		if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
+		    CHIP_IS_E1x(bp)) {
+			u32 shmem_base[2], shmem2_base[2];
+			shmem_base[0] =  bp->common.shmem_base;
+			shmem2_base[0] = bp->common.shmem2_base;
+			if (CHIP_IS_E2(bp)) {
+				shmem_base[1] =
+					SHMEM2_RD(bp, other_shmem_base_addr);
+				shmem2_base[1] =
+					SHMEM2_RD(bp, other_shmem2_base_addr);
+			}
+			bnx2x_acquire_phy_lock(bp);
+			bnx2x_common_init_phy(bp, shmem_base, shmem2_base,
+					      bp->common.chip_id);
+			bnx2x_release_phy_lock(bp);
+		}
 	} else
 		BNX2X_ERR("Bootcode is missing - can not initialize link\n");
 
 	return 0;
 }
 
-static int bnx2x_init_port(struct bnx2x *bp)
+static int bnx2x_init_hw_port(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
 	int init_stage = port ? PORT1_STAGE : PORT0_STAGE;
@@ -4184,14 +5254,23 @@
 	bnx2x_init_block(bp, PXP_BLOCK, init_stage);
 	bnx2x_init_block(bp, PXP2_BLOCK, init_stage);
 
+	/* Timers bug workaround: disables the pf_master bit in pglue at
+	 * common phase, we need to enable it here before any dmae access are
+	 * attempted. Therefore we manually added the enable-master to the
+	 * port phase (it also happens in the function phase)
+	 */
+	if (CHIP_IS_E2(bp))
+		REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
+
 	bnx2x_init_block(bp, TCM_BLOCK, init_stage);
 	bnx2x_init_block(bp, UCM_BLOCK, init_stage);
 	bnx2x_init_block(bp, CCM_BLOCK, init_stage);
 	bnx2x_init_block(bp, XCM_BLOCK, init_stage);
 
-#ifdef BCM_CNIC
-	REG_WR(bp, QM_REG_CONNNUM_0 + port*4, 1024/16 - 1);
+	/* QM cid (connection) count */
+	bnx2x_qm_init_cid_count(bp, bp->qm_cid_count, INITOP_SET);
 
+#ifdef BCM_CNIC
 	bnx2x_init_block(bp, TIMERS_BLOCK, init_stage);
 	REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
 	REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
@@ -4199,29 +5278,41 @@
 
 	bnx2x_init_block(bp, DQ_BLOCK, init_stage);
 
-	bnx2x_init_block(bp, BRB1_BLOCK, init_stage);
-	if (CHIP_REV_IS_SLOW(bp) && !CHIP_IS_E1H(bp)) {
-		/* no pause for emulation and FPGA */
-		low = 0;
-		high = 513;
-	} else {
-		if (IS_E1HMF(bp))
-			low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
-		else if (bp->dev->mtu > 4096) {
-			if (bp->flags & ONE_PORT_FLAG)
-				low = 160;
-			else {
-				val = bp->dev->mtu;
-				/* (24*1024 + val*4)/256 */
-				low = 96 + (val/64) + ((val % 64) ? 1 : 0);
-			}
-		} else
-			low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160);
-		high = low + 56;	/* 14*1024/256 */
-	}
-	REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0 + port*4, low);
-	REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port*4, high);
+	if (CHIP_MODE_IS_4_PORT(bp))
+		bnx2x_init_block(bp, QM_4PORT_BLOCK, init_stage);
 
+	if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
+		bnx2x_init_block(bp, BRB1_BLOCK, init_stage);
+		if (CHIP_REV_IS_SLOW(bp) && CHIP_IS_E1(bp)) {
+			/* no pause for emulation and FPGA */
+			low = 0;
+			high = 513;
+		} else {
+			if (IS_MF(bp))
+				low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
+			else if (bp->dev->mtu > 4096) {
+				if (bp->flags & ONE_PORT_FLAG)
+					low = 160;
+				else {
+					val = bp->dev->mtu;
+					/* (24*1024 + val*4)/256 */
+					low = 96 + (val/64) +
+							((val % 64) ? 1 : 0);
+				}
+			} else
+				low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160);
+			high = low + 56;	/* 14*1024/256 */
+		}
+		REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0 + port*4, low);
+		REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port*4, high);
+	}
+
+	if (CHIP_MODE_IS_4_PORT(bp)) {
+		REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 + port*8, 248);
+		REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 + port*8, 328);
+		REG_WR(bp, (BP_PORT(bp) ? BRB1_REG_MAC_GUARANTIED_1 :
+					  BRB1_REG_MAC_GUARANTIED_0), 40);
+	}
 
 	bnx2x_init_block(bp, PRS_BLOCK, init_stage);
 
@@ -4234,24 +5325,28 @@
 	bnx2x_init_block(bp, USEM_BLOCK, init_stage);
 	bnx2x_init_block(bp, CSEM_BLOCK, init_stage);
 	bnx2x_init_block(bp, XSEM_BLOCK, init_stage);
+	if (CHIP_MODE_IS_4_PORT(bp))
+		bnx2x_init_block(bp, XSEM_4PORT_BLOCK, init_stage);
 
 	bnx2x_init_block(bp, UPB_BLOCK, init_stage);
 	bnx2x_init_block(bp, XPB_BLOCK, init_stage);
 
 	bnx2x_init_block(bp, PBF_BLOCK, init_stage);
 
-	/* configure PBF to work without PAUSE mtu 9000 */
-	REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
+	if (!CHIP_IS_E2(bp)) {
+		/* configure PBF to work without PAUSE mtu 9000 */
+		REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
 
-	/* update threshold */
-	REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, (9040/16));
-	/* update init credit */
-	REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, (9040/16) + 553 - 22);
+		/* update threshold */
+		REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, (9040/16));
+		/* update init credit */
+		REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, (9040/16) + 553 - 22);
 
-	/* probe changes */
-	REG_WR(bp, PBF_REG_INIT_P0 + port*4, 1);
-	msleep(5);
-	REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0);
+		/* probe changes */
+		REG_WR(bp, PBF_REG_INIT_P0 + port*4, 1);
+		udelay(50);
+		REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0);
+	}
 
 #ifdef BCM_CNIC
 	bnx2x_init_block(bp, SRCH_BLOCK, init_stage);
@@ -4265,13 +5360,15 @@
 	}
 	bnx2x_init_block(bp, HC_BLOCK, init_stage);
 
+	bnx2x_init_block(bp, IGU_BLOCK, init_stage);
+
 	bnx2x_init_block(bp, MISC_AEU_BLOCK, init_stage);
 	/* init aeu_mask_attn_func_0/1:
 	 *  - SF mode: bits 3-7 are masked. only bits 0-2 are in use
 	 *  - MF mode: bit 3 is masked. bits 0-2 are in use as in SF
 	 *             bits 4-7 are used for "per vn group attention" */
 	REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4,
-	       (IS_E1HMF(bp) ? 0xF7 : 0x7));
+	       (IS_MF(bp) ? 0xF7 : 0x7));
 
 	bnx2x_init_block(bp, PXPCS_BLOCK, init_stage);
 	bnx2x_init_block(bp, EMAC0_BLOCK, init_stage);
@@ -4283,11 +5380,25 @@
 
 	REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
 
-	if (CHIP_IS_E1H(bp)) {
-		/* 0x2 disable e1hov, 0x1 enable */
+	if (!CHIP_IS_E1(bp)) {
+		/* 0x2 disable mf_ov, 0x1 enable */
 		REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4,
-		       (IS_E1HMF(bp) ? 0x1 : 0x2));
+		       (IS_MF(bp) ? 0x1 : 0x2));
 
+		if (CHIP_IS_E2(bp)) {
+			val = 0;
+			switch (bp->mf_mode) {
+			case MULTI_FUNCTION_SD:
+				val = 1;
+				break;
+			case MULTI_FUNCTION_SI:
+				val = 2;
+				break;
+			}
+
+			REG_WR(bp, (BP_PORT(bp) ? NIG_REG_LLH1_CLS_TYPE :
+						  NIG_REG_LLH0_CLS_TYPE), val);
+		}
 		{
 			REG_WR(bp, NIG_REG_LLFC_ENABLE_0 + port*4, 0);
 			REG_WR(bp, NIG_REG_LLFC_OUT_EN_0 + port*4, 0);
@@ -4297,199 +5408,339 @@
 
 	bnx2x_init_block(bp, MCP_BLOCK, init_stage);
 	bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
-
-	switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) {
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-		{
-		u32 swap_val, swap_override, aeu_gpio_mask, offset;
-
-		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-			       MISC_REGISTERS_GPIO_INPUT_HI_Z, port);
-
-		/* The GPIO should be swapped if the swap register is
-		   set and active */
-		swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
-		swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
-
-		/* Select function upon port-swap configuration */
-		if (port == 0) {
-			offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
-			aeu_gpio_mask = (swap_val && swap_override) ?
-				AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 :
-				AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0;
-		} else {
-			offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
-			aeu_gpio_mask = (swap_val && swap_override) ?
-				AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 :
-				AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1;
-		}
-		val = REG_RD(bp, offset);
-		/* add GPIO3 to group */
-		val |= aeu_gpio_mask;
-		REG_WR(bp, offset, val);
-		}
-		bp->port.need_hw_lock = 1;
-		break;
-
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-		bp->port.need_hw_lock = 1;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-		/* add SPIO 5 to group 0 */
-		{
+	bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
+						       bp->common.shmem_base,
+						       bp->common.shmem2_base);
+	if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base,
+				      bp->common.shmem2_base, port)) {
 		u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
 				       MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
 		val = REG_RD(bp, reg_addr);
 		val |= AEU_INPUTS_ATTN_BITS_SPIO5;
 		REG_WR(bp, reg_addr, val);
-		}
-		break;
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-		bp->port.need_hw_lock = 1;
-		break;
-	default:
-		break;
 	}
-
 	bnx2x__link_reset(bp);
 
 	return 0;
 }
 
-#define ILT_PER_FUNC		(768/2)
-#define FUNC_ILT_BASE(func)	(func * ILT_PER_FUNC)
-/* the phys address is shifted right 12 bits and has an added
-   1=valid bit added to the 53rd bit
-   then since this is a wide register(TM)
-   we split it into two 32 bit writes
- */
-#define ONCHIP_ADDR1(x)		((u32)(((u64)x >> 12) & 0xFFFFFFFF))
-#define ONCHIP_ADDR2(x)		((u32)((1 << 20) | ((u64)x >> 44)))
-#define PXP_ONE_ILT(x)		(((x) << 10) | x)
-#define PXP_ILT_RANGE(f, l)	(((l) << 10) | f)
-
-#ifdef BCM_CNIC
-#define CNIC_ILT_LINES		127
-#define CNIC_CTX_PER_ILT	16
-#else
-#define CNIC_ILT_LINES		0
-#endif
-
 static void bnx2x_ilt_wr(struct bnx2x *bp, u32 index, dma_addr_t addr)
 {
 	int reg;
 
-	if (CHIP_IS_E1H(bp))
-		reg = PXP2_REG_RQ_ONCHIP_AT_B0 + index*8;
-	else /* E1 */
+	if (CHIP_IS_E1(bp))
 		reg = PXP2_REG_RQ_ONCHIP_AT + index*8;
+	else
+		reg = PXP2_REG_RQ_ONCHIP_AT_B0 + index*8;
 
 	bnx2x_wb_wr(bp, reg, ONCHIP_ADDR1(addr), ONCHIP_ADDR2(addr));
 }
 
-static int bnx2x_init_func(struct bnx2x *bp)
+static inline void bnx2x_igu_clear_sb(struct bnx2x *bp, u8 idu_sb_id)
+{
+	bnx2x_igu_clear_sb_gen(bp, idu_sb_id, true /*PF*/);
+}
+
+static inline void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
+{
+	u32 i, base = FUNC_ILT_BASE(func);
+	for (i = base; i < base + ILT_PER_FUNC; i++)
+		bnx2x_ilt_wr(bp, i, 0);
+}
+
+static int bnx2x_init_hw_func(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
 	int func = BP_FUNC(bp);
+	struct bnx2x_ilt *ilt = BP_ILT(bp);
+	u16 cdu_ilt_start;
 	u32 addr, val;
-	int i;
+	u32 main_mem_base, main_mem_size, main_mem_prty_clr;
+	int i, main_mem_width;
 
 	DP(BNX2X_MSG_MCP, "starting func init  func %d\n", func);
 
 	/* set MSI reconfigure capability */
-	addr = (port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0);
-	val = REG_RD(bp, addr);
-	val |= HC_CONFIG_0_REG_MSI_ATTN_EN_0;
-	REG_WR(bp, addr, val);
+	if (bp->common.int_block == INT_BLOCK_HC) {
+		addr = (port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0);
+		val = REG_RD(bp, addr);
+		val |= HC_CONFIG_0_REG_MSI_ATTN_EN_0;
+		REG_WR(bp, addr, val);
+	}
 
-	i = FUNC_ILT_BASE(func);
+	ilt = BP_ILT(bp);
+	cdu_ilt_start = ilt->clients[ILT_CLIENT_CDU].start;
 
-	bnx2x_ilt_wr(bp, i, bnx2x_sp_mapping(bp, context));
-	if (CHIP_IS_E1H(bp)) {
-		REG_WR(bp, PXP2_REG_RQ_CDU_FIRST_ILT, i);
-		REG_WR(bp, PXP2_REG_RQ_CDU_LAST_ILT, i + CNIC_ILT_LINES);
-	} else /* E1 */
-		REG_WR(bp, PXP2_REG_PSWRQ_CDU0_L2P + func*4,
-		       PXP_ILT_RANGE(i, i + CNIC_ILT_LINES));
+	for (i = 0; i < L2_ILT_LINES(bp); i++) {
+		ilt->lines[cdu_ilt_start + i].page =
+			bp->context.vcxt + (ILT_PAGE_CIDS * i);
+		ilt->lines[cdu_ilt_start + i].page_mapping =
+			bp->context.cxt_mapping + (CDU_ILT_PAGE_SZ * i);
+		/* cdu ilt pages are allocated manually so there's no need to
+		set the size */
+	}
+	bnx2x_ilt_init_op(bp, INITOP_SET);
 
 #ifdef BCM_CNIC
-	i += 1 + CNIC_ILT_LINES;
-	bnx2x_ilt_wr(bp, i, bp->timers_mapping);
-	if (CHIP_IS_E1(bp))
-		REG_WR(bp, PXP2_REG_PSWRQ_TM0_L2P + func*4, PXP_ONE_ILT(i));
-	else {
-		REG_WR(bp, PXP2_REG_RQ_TM_FIRST_ILT, i);
-		REG_WR(bp, PXP2_REG_RQ_TM_LAST_ILT, i);
-	}
+	bnx2x_src_init_t2(bp, bp->t2, bp->t2_mapping, SRC_CONN_NUM);
 
-	i++;
-	bnx2x_ilt_wr(bp, i, bp->qm_mapping);
-	if (CHIP_IS_E1(bp))
-		REG_WR(bp, PXP2_REG_PSWRQ_QM0_L2P + func*4, PXP_ONE_ILT(i));
-	else {
-		REG_WR(bp, PXP2_REG_RQ_QM_FIRST_ILT, i);
-		REG_WR(bp, PXP2_REG_RQ_QM_LAST_ILT, i);
-	}
-
-	i++;
-	bnx2x_ilt_wr(bp, i, bp->t1_mapping);
-	if (CHIP_IS_E1(bp))
-		REG_WR(bp, PXP2_REG_PSWRQ_SRC0_L2P + func*4, PXP_ONE_ILT(i));
-	else {
-		REG_WR(bp, PXP2_REG_RQ_SRC_FIRST_ILT, i);
-		REG_WR(bp, PXP2_REG_RQ_SRC_LAST_ILT, i);
-	}
-
-	/* tell the searcher where the T2 table is */
-	REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, 16*1024/64);
-
-	bnx2x_wb_wr(bp, SRC_REG_FIRSTFREE0 + port*16,
-		    U64_LO(bp->t2_mapping), U64_HI(bp->t2_mapping));
-
-	bnx2x_wb_wr(bp, SRC_REG_LASTFREE0 + port*16,
-		    U64_LO((u64)bp->t2_mapping + 16*1024 - 64),
-		    U64_HI((u64)bp->t2_mapping + 16*1024 - 64));
-
-	REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, 10);
+	/* T1 hash bits value determines the T1 number of entries */
+	REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, SRC_HASH_BITS);
 #endif
 
-	if (CHIP_IS_E1H(bp)) {
-		bnx2x_init_block(bp, MISC_BLOCK, FUNC0_STAGE + func);
-		bnx2x_init_block(bp, TCM_BLOCK, FUNC0_STAGE + func);
-		bnx2x_init_block(bp, UCM_BLOCK, FUNC0_STAGE + func);
-		bnx2x_init_block(bp, CCM_BLOCK, FUNC0_STAGE + func);
-		bnx2x_init_block(bp, XCM_BLOCK, FUNC0_STAGE + func);
-		bnx2x_init_block(bp, TSEM_BLOCK, FUNC0_STAGE + func);
-		bnx2x_init_block(bp, USEM_BLOCK, FUNC0_STAGE + func);
-		bnx2x_init_block(bp, CSEM_BLOCK, FUNC0_STAGE + func);
-		bnx2x_init_block(bp, XSEM_BLOCK, FUNC0_STAGE + func);
+#ifndef BCM_CNIC
+	/* set NIC mode */
+	REG_WR(bp, PRS_REG_NIC_MODE, 1);
+#endif  /* BCM_CNIC */
 
-		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
-		REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->e1hov);
+	if (CHIP_IS_E2(bp)) {
+		u32 pf_conf = IGU_PF_CONF_FUNC_EN;
+
+		/* Turn on a single ISR mode in IGU if driver is going to use
+		 * INT#x or MSI
+		 */
+		if (!(bp->flags & USING_MSIX_FLAG))
+			pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN;
+		/*
+		 * Timers workaround bug: function init part.
+		 * Need to wait 20msec after initializing ILT,
+		 * needed to make sure there are no requests in
+		 * one of the PXP internal queues with "old" ILT addresses
+		 */
+		msleep(20);
+		/*
+		 * Master enable - Due to WB DMAE writes performed before this
+		 * register is re-initialized as part of the regular function
+		 * init
+		 */
+		REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
+		/* Enable the function in IGU */
+		REG_WR(bp, IGU_REG_PF_CONFIGURATION, pf_conf);
 	}
 
+	bp->dmae_ready = 1;
+
+	bnx2x_init_block(bp, PGLUE_B_BLOCK, FUNC0_STAGE + func);
+
+	if (CHIP_IS_E2(bp))
+		REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, func);
+
+	bnx2x_init_block(bp, MISC_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, TCM_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, UCM_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, CCM_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, XCM_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, TSEM_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, USEM_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, CSEM_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, XSEM_BLOCK, FUNC0_STAGE + func);
+
+	if (CHIP_IS_E2(bp)) {
+		REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_PATH_ID_OFFSET,
+								BP_PATH(bp));
+		REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_PATH_ID_OFFSET,
+								BP_PATH(bp));
+	}
+
+	if (CHIP_MODE_IS_4_PORT(bp))
+		bnx2x_init_block(bp, XSEM_4PORT_BLOCK, FUNC0_STAGE + func);
+
+	if (CHIP_IS_E2(bp))
+		REG_WR(bp, QM_REG_PF_EN, 1);
+
+	bnx2x_init_block(bp, QM_BLOCK, FUNC0_STAGE + func);
+
+	if (CHIP_MODE_IS_4_PORT(bp))
+		bnx2x_init_block(bp, QM_4PORT_BLOCK, FUNC0_STAGE + func);
+
+	bnx2x_init_block(bp, TIMERS_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, DQ_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, BRB1_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, PRS_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, TSDM_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, CSDM_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, USDM_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, XSDM_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, UPB_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, XPB_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, PBF_BLOCK, FUNC0_STAGE + func);
+	if (CHIP_IS_E2(bp))
+		REG_WR(bp, PBF_REG_DISABLE_PF, 0);
+
+	bnx2x_init_block(bp, CDU_BLOCK, FUNC0_STAGE + func);
+
+	bnx2x_init_block(bp, CFC_BLOCK, FUNC0_STAGE + func);
+
+	if (CHIP_IS_E2(bp))
+		REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 1);
+
+	if (IS_MF(bp)) {
+		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
+		REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->mf_ov);
+	}
+
+	bnx2x_init_block(bp, MISC_AEU_BLOCK, FUNC0_STAGE + func);
+
 	/* HC init per function */
-	if (CHIP_IS_E1H(bp)) {
+	if (bp->common.int_block == INT_BLOCK_HC) {
+		if (CHIP_IS_E1H(bp)) {
+			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
+
+			REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
+			REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+		}
+		bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func);
+
+	} else {
+		int num_segs, sb_idx, prod_offset;
+
 		REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
 
-		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
-		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+		if (CHIP_IS_E2(bp)) {
+			REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, 0);
+			REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
+		}
+
+		bnx2x_init_block(bp, IGU_BLOCK, FUNC0_STAGE + func);
+
+		if (CHIP_IS_E2(bp)) {
+			int dsb_idx = 0;
+			/**
+			 * Producer memory:
+			 * E2 mode: address 0-135 match to the mapping memory;
+			 * 136 - PF0 default prod; 137 - PF1 default prod;
+			 * 138 - PF2 default prod; 139 - PF3 default prod;
+			 * 140 - PF0 attn prod;    141 - PF1 attn prod;
+			 * 142 - PF2 attn prod;    143 - PF3 attn prod;
+			 * 144-147 reserved.
+			 *
+			 * E1.5 mode - In backward compatible mode;
+			 * for non default SB; each even line in the memory
+			 * holds the U producer and each odd line hold
+			 * the C producer. The first 128 producers are for
+			 * NDSB (PF0 - 0-31; PF1 - 32-63 and so on). The last 20
+			 * producers are for the DSB for each PF.
+			 * Each PF has five segments: (the order inside each
+			 * segment is PF0; PF1; PF2; PF3) - 128-131 U prods;
+			 * 132-135 C prods; 136-139 X prods; 140-143 T prods;
+			 * 144-147 attn prods;
+			 */
+			/* non-default-status-blocks */
+			num_segs = CHIP_INT_MODE_IS_BC(bp) ?
+				IGU_BC_NDSB_NUM_SEGS : IGU_NORM_NDSB_NUM_SEGS;
+			for (sb_idx = 0; sb_idx < bp->igu_sb_cnt; sb_idx++) {
+				prod_offset = (bp->igu_base_sb + sb_idx) *
+					num_segs;
+
+				for (i = 0; i < num_segs; i++) {
+					addr = IGU_REG_PROD_CONS_MEMORY +
+							(prod_offset + i) * 4;
+					REG_WR(bp, addr, 0);
+				}
+				/* send consumer update with value 0 */
+				bnx2x_ack_sb(bp, bp->igu_base_sb + sb_idx,
+					     USTORM_ID, 0, IGU_INT_NOP, 1);
+				bnx2x_igu_clear_sb(bp,
+						   bp->igu_base_sb + sb_idx);
+			}
+
+			/* default-status-blocks */
+			num_segs = CHIP_INT_MODE_IS_BC(bp) ?
+				IGU_BC_DSB_NUM_SEGS : IGU_NORM_DSB_NUM_SEGS;
+
+			if (CHIP_MODE_IS_4_PORT(bp))
+				dsb_idx = BP_FUNC(bp);
+			else
+				dsb_idx = BP_E1HVN(bp);
+
+			prod_offset = (CHIP_INT_MODE_IS_BC(bp) ?
+				       IGU_BC_BASE_DSB_PROD + dsb_idx :
+				       IGU_NORM_BASE_DSB_PROD + dsb_idx);
+
+			for (i = 0; i < (num_segs * E1HVN_MAX);
+			     i += E1HVN_MAX) {
+				addr = IGU_REG_PROD_CONS_MEMORY +
+							(prod_offset + i)*4;
+				REG_WR(bp, addr, 0);
+			}
+			/* send consumer update with 0 */
+			if (CHIP_INT_MODE_IS_BC(bp)) {
+				bnx2x_ack_sb(bp, bp->igu_dsb_id,
+					     USTORM_ID, 0, IGU_INT_NOP, 1);
+				bnx2x_ack_sb(bp, bp->igu_dsb_id,
+					     CSTORM_ID, 0, IGU_INT_NOP, 1);
+				bnx2x_ack_sb(bp, bp->igu_dsb_id,
+					     XSTORM_ID, 0, IGU_INT_NOP, 1);
+				bnx2x_ack_sb(bp, bp->igu_dsb_id,
+					     TSTORM_ID, 0, IGU_INT_NOP, 1);
+				bnx2x_ack_sb(bp, bp->igu_dsb_id,
+					     ATTENTION_ID, 0, IGU_INT_NOP, 1);
+			} else {
+				bnx2x_ack_sb(bp, bp->igu_dsb_id,
+					     USTORM_ID, 0, IGU_INT_NOP, 1);
+				bnx2x_ack_sb(bp, bp->igu_dsb_id,
+					     ATTENTION_ID, 0, IGU_INT_NOP, 1);
+			}
+			bnx2x_igu_clear_sb(bp, bp->igu_dsb_id);
+
+			/* !!! these should become driver const once
+			   rf-tool supports split-68 const */
+			REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_LSB, 0);
+			REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_MSB, 0);
+			REG_WR(bp, IGU_REG_SB_MASK_LSB, 0);
+			REG_WR(bp, IGU_REG_SB_MASK_MSB, 0);
+			REG_WR(bp, IGU_REG_PBA_STATUS_LSB, 0);
+			REG_WR(bp, IGU_REG_PBA_STATUS_MSB, 0);
+		}
 	}
-	bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func);
 
 	/* Reset PCIE errors for debug */
 	REG_WR(bp, 0x2114, 0xffffffff);
 	REG_WR(bp, 0x2120, 0xffffffff);
 
+	bnx2x_init_block(bp, EMAC0_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, EMAC1_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, DBU_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, DBG_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, MCP_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, DMAE_BLOCK, FUNC0_STAGE + func);
+
+	if (CHIP_IS_E1x(bp)) {
+		main_mem_size = HC_REG_MAIN_MEMORY_SIZE / 2; /*dwords*/
+		main_mem_base = HC_REG_MAIN_MEMORY +
+				BP_PORT(bp) * (main_mem_size * 4);
+		main_mem_prty_clr = HC_REG_HC_PRTY_STS_CLR;
+		main_mem_width = 8;
+
+		val = REG_RD(bp, main_mem_prty_clr);
+		if (val)
+			DP(BNX2X_MSG_MCP, "Hmmm... Parity errors in HC "
+					  "block during "
+					  "function init (0x%x)!\n", val);
+
+		/* Clear "false" parity errors in MSI-X table */
+		for (i = main_mem_base;
+		     i < main_mem_base + main_mem_size * 4;
+		     i += main_mem_width) {
+			bnx2x_read_dmae(bp, i, main_mem_width / 4);
+			bnx2x_write_dmae(bp, bnx2x_sp_mapping(bp, wb_data),
+					 i, main_mem_width / 4);
+		}
+		/* Clear HC parity attention */
+		REG_RD(bp, main_mem_prty_clr);
+	}
+
+	bnx2x_phy_probe(&bp->link_params);
+
 	return 0;
 }
 
 int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
 {
-	int i, rc = 0;
+	int rc = 0;
 
 	DP(BNX2X_MSG_MCP, "function %d  load_code %x\n",
-	   BP_FUNC(bp), load_code);
+	   BP_ABS_FUNC(bp), load_code);
 
 	bp->dmae_ready = 0;
 	mutex_init(&bp->dmae_mutex);
@@ -4499,21 +5750,20 @@
 
 	switch (load_code) {
 	case FW_MSG_CODE_DRV_LOAD_COMMON:
-		rc = bnx2x_init_common(bp);
+	case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
+		rc = bnx2x_init_hw_common(bp, load_code);
 		if (rc)
 			goto init_hw_err;
 		/* no break */
 
 	case FW_MSG_CODE_DRV_LOAD_PORT:
-		bp->dmae_ready = 1;
-		rc = bnx2x_init_port(bp);
+		rc = bnx2x_init_hw_port(bp);
 		if (rc)
 			goto init_hw_err;
 		/* no break */
 
 	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
-		bp->dmae_ready = 1;
-		rc = bnx2x_init_func(bp);
+		rc = bnx2x_init_hw_func(bp);
 		if (rc)
 			goto init_hw_err;
 		break;
@@ -4524,22 +5774,14 @@
 	}
 
 	if (!BP_NOMCP(bp)) {
-		int func = BP_FUNC(bp);
+		int mb_idx = BP_FW_MB_IDX(bp);
 
 		bp->fw_drv_pulse_wr_seq =
-				(SHMEM_RD(bp, func_mb[func].drv_pulse_mb) &
+				(SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) &
 				 DRV_PULSE_SEQ_MASK);
 		DP(BNX2X_MSG_MCP, "drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
 	}
 
-	/* this needs to be done before gunzip end */
-	bnx2x_zero_def_sb(bp);
-	for_each_queue(bp, i)
-		bnx2x_zero_sb(bp, BP_L_ID(bp) + i);
-#ifdef BCM_CNIC
-	bnx2x_zero_sb(bp, BP_L_ID(bp) + i);
-#endif
-
 init_hw_err:
 	bnx2x_gunzip_end(bp);
 
@@ -4552,7 +5794,7 @@
 #define BNX2X_PCI_FREE(x, y, size) \
 	do { \
 		if (x) { \
-			dma_free_coherent(&bp->pdev->dev, size, x, y); \
+			dma_free_coherent(&bp->pdev->dev, size, (void *)x, y); \
 			x = NULL; \
 			y = 0; \
 		} \
@@ -4561,7 +5803,7 @@
 #define BNX2X_FREE(x) \
 	do { \
 		if (x) { \
-			vfree(x); \
+			kfree((void *)x); \
 			x = NULL; \
 		} \
 	} while (0)
@@ -4571,11 +5813,15 @@
 	/* fastpath */
 	/* Common */
 	for_each_queue(bp, i) {
-
 		/* status blocks */
-		BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk),
-			       bnx2x_fp(bp, i, status_blk_mapping),
-			       sizeof(struct host_status_block));
+		if (CHIP_IS_E2(bp))
+			BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk.e2_sb),
+				       bnx2x_fp(bp, i, status_blk_mapping),
+				       sizeof(struct host_hc_status_block_e2));
+		else
+			BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk.e1x_sb),
+				       bnx2x_fp(bp, i, status_blk_mapping),
+				       sizeof(struct host_hc_status_block_e1x));
 	}
 	/* Rx */
 	for_each_queue(bp, i) {
@@ -4609,28 +5855,56 @@
 	/* end of fastpath */
 
 	BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping,
-		       sizeof(struct host_def_status_block));
+		       sizeof(struct host_sp_status_block));
 
 	BNX2X_PCI_FREE(bp->slowpath, bp->slowpath_mapping,
 		       sizeof(struct bnx2x_slowpath));
 
+	BNX2X_PCI_FREE(bp->context.vcxt, bp->context.cxt_mapping,
+		       bp->context.size);
+
+	bnx2x_ilt_mem_op(bp, ILT_MEMOP_FREE);
+
+	BNX2X_FREE(bp->ilt->lines);
+
 #ifdef BCM_CNIC
-	BNX2X_PCI_FREE(bp->t1, bp->t1_mapping, 64*1024);
-	BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, 16*1024);
-	BNX2X_PCI_FREE(bp->timers, bp->timers_mapping, 8*1024);
-	BNX2X_PCI_FREE(bp->qm, bp->qm_mapping, 128*1024);
-	BNX2X_PCI_FREE(bp->cnic_sb, bp->cnic_sb_mapping,
-		       sizeof(struct host_status_block));
+	if (CHIP_IS_E2(bp))
+		BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
+			       sizeof(struct host_hc_status_block_e2));
+	else
+		BNX2X_PCI_FREE(bp->cnic_sb.e1x_sb, bp->cnic_sb_mapping,
+			       sizeof(struct host_hc_status_block_e1x));
+
+	BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, SRC_T2_SZ);
 #endif
+
 	BNX2X_PCI_FREE(bp->spq, bp->spq_mapping, BCM_PAGE_SIZE);
 
+	BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
+		       BCM_PAGE_SIZE * NUM_EQ_PAGES);
+
 #undef BNX2X_PCI_FREE
 #undef BNX2X_KFREE
 }
 
+static inline void set_sb_shortcuts(struct bnx2x *bp, int index)
+{
+	union host_hc_status_block status_blk = bnx2x_fp(bp, index, status_blk);
+	if (CHIP_IS_E2(bp)) {
+		bnx2x_fp(bp, index, sb_index_values) =
+			(__le16 *)status_blk.e2_sb->sb.index_values;
+		bnx2x_fp(bp, index, sb_running_index) =
+			(__le16 *)status_blk.e2_sb->sb.running_index;
+	} else {
+		bnx2x_fp(bp, index, sb_index_values) =
+			(__le16 *)status_blk.e1x_sb->sb.index_values;
+		bnx2x_fp(bp, index, sb_running_index) =
+			(__le16 *)status_blk.e1x_sb->sb.running_index;
+	}
+}
+
 int bnx2x_alloc_mem(struct bnx2x *bp)
 {
-
 #define BNX2X_PCI_ALLOC(x, y, size) \
 	do { \
 		x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
@@ -4641,10 +5915,9 @@
 
 #define BNX2X_ALLOC(x, size) \
 	do { \
-		x = vmalloc(size); \
+		x = kzalloc(size, GFP_KERNEL); \
 		if (x == NULL) \
 			goto alloc_mem_err; \
-		memset(x, 0, size); \
 	} while (0)
 
 	int i;
@@ -4652,12 +5925,19 @@
 	/* fastpath */
 	/* Common */
 	for_each_queue(bp, i) {
+		union host_hc_status_block *sb = &bnx2x_fp(bp, i, status_blk);
 		bnx2x_fp(bp, i, bp) = bp;
-
 		/* status blocks */
-		BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, status_blk),
+		if (CHIP_IS_E2(bp))
+			BNX2X_PCI_ALLOC(sb->e2_sb,
 				&bnx2x_fp(bp, i, status_blk_mapping),
-				sizeof(struct host_status_block));
+				sizeof(struct host_hc_status_block_e2));
+		else
+			BNX2X_PCI_ALLOC(sb->e1x_sb,
+				&bnx2x_fp(bp, i, status_blk_mapping),
+				sizeof(struct host_hc_status_block_e1x));
+
+		set_sb_shortcuts(bp, i);
 	}
 	/* Rx */
 	for_each_queue(bp, i) {
@@ -4693,37 +5973,41 @@
 	}
 	/* end of fastpath */
 
+#ifdef BCM_CNIC
+	if (CHIP_IS_E2(bp))
+		BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping,
+				sizeof(struct host_hc_status_block_e2));
+	else
+		BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb, &bp->cnic_sb_mapping,
+				sizeof(struct host_hc_status_block_e1x));
+
+	/* allocate searcher T2 table */
+	BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
+#endif
+
+
 	BNX2X_PCI_ALLOC(bp->def_status_blk, &bp->def_status_blk_mapping,
-			sizeof(struct host_def_status_block));
+			sizeof(struct host_sp_status_block));
 
 	BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping,
 			sizeof(struct bnx2x_slowpath));
 
-#ifdef BCM_CNIC
-	BNX2X_PCI_ALLOC(bp->t1, &bp->t1_mapping, 64*1024);
+	bp->context.size = sizeof(union cdu_context) * bp->l2_cid_count;
 
-	/* allocate searcher T2 table
-	   we allocate 1/4 of alloc num for T2
-	  (which is not entered into the ILT) */
-	BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, 16*1024);
+	BNX2X_PCI_ALLOC(bp->context.vcxt, &bp->context.cxt_mapping,
+			bp->context.size);
 
-	/* Initialize T2 (for 1024 connections) */
-	for (i = 0; i < 16*1024; i += 64)
-		*(u64 *)((char *)bp->t2 + i + 56) = bp->t2_mapping + i + 64;
+	BNX2X_ALLOC(bp->ilt->lines, sizeof(struct ilt_line) * ILT_MAX_LINES);
 
-	/* Timer block array (8*MAX_CONN) phys uncached for now 1024 conns */
-	BNX2X_PCI_ALLOC(bp->timers, &bp->timers_mapping, 8*1024);
-
-	/* QM queues (128*MAX_CONN) */
-	BNX2X_PCI_ALLOC(bp->qm, &bp->qm_mapping, 128*1024);
-
-	BNX2X_PCI_ALLOC(bp->cnic_sb, &bp->cnic_sb_mapping,
-			sizeof(struct host_status_block));
-#endif
+	if (bnx2x_ilt_mem_op(bp, ILT_MEMOP_ALLOC))
+		goto alloc_mem_err;
 
 	/* Slow path ring */
 	BNX2X_PCI_ALLOC(bp->spq, &bp->spq_mapping, BCM_PAGE_SIZE);
 
+	/* EQ */
+	BNX2X_PCI_ALLOC(bp->eq_ring, &bp->eq_mapping,
+			BCM_PAGE_SIZE * NUM_EQ_PAGES);
 	return 0;
 
 alloc_mem_err:
@@ -4734,97 +6018,47 @@
 #undef BNX2X_ALLOC
 }
 
-
 /*
  * Init service functions
  */
-
-/**
- * Sets a MAC in a CAM for a few L2 Clients for E1 chip
- *
- * @param bp driver descriptor
- * @param set set or clear an entry (1 or 0)
- * @param mac pointer to a buffer containing a MAC
- * @param cl_bit_vec bit vector of clients to register a MAC for
- * @param cam_offset offset in a CAM to use
- * @param with_bcast set broadcast MAC as well
- */
-static void bnx2x_set_mac_addr_e1_gen(struct bnx2x *bp, int set, u8 *mac,
-				      u32 cl_bit_vec, u8 cam_offset,
-				      u8 with_bcast)
+int bnx2x_func_start(struct bnx2x *bp)
 {
-	struct mac_configuration_cmd *config = bnx2x_sp(bp, mac_config);
-	int port = BP_PORT(bp);
+	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0, 0, 0, 1);
 
-	/* CAM allocation
-	 * unicasts 0-31:port0 32-63:port1
-	 * multicast 64-127:port0 128-191:port1
-	 */
-	config->hdr.length = 1 + (with_bcast ? 1 : 0);
-	config->hdr.offset = cam_offset;
-	config->hdr.client_id = 0xff;
-	config->hdr.reserved1 = 0;
+	/* Wait for completion */
+	return bnx2x_wait_ramrod(bp, BNX2X_STATE_FUNC_STARTED, 0, &(bp->state),
+				 WAIT_RAMROD_COMMON);
+}
 
-	/* primary MAC */
-	config->config_table[0].cam_entry.msb_mac_addr =
-					swab16(*(u16 *)&mac[0]);
-	config->config_table[0].cam_entry.middle_mac_addr =
-					swab16(*(u16 *)&mac[2]);
-	config->config_table[0].cam_entry.lsb_mac_addr =
-					swab16(*(u16 *)&mac[4]);
-	config->config_table[0].cam_entry.flags = cpu_to_le16(port);
-	if (set)
-		config->config_table[0].target_table_entry.flags = 0;
-	else
-		CAM_INVALIDATE(config->config_table[0]);
-	config->config_table[0].target_table_entry.clients_bit_vector =
-						cpu_to_le32(cl_bit_vec);
-	config->config_table[0].target_table_entry.vlan_id = 0;
+int bnx2x_func_stop(struct bnx2x *bp)
+{
+	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0, 1);
 
-	DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x)\n",
-	   (set ? "setting" : "clearing"),
-	   config->config_table[0].cam_entry.msb_mac_addr,
-	   config->config_table[0].cam_entry.middle_mac_addr,
-	   config->config_table[0].cam_entry.lsb_mac_addr);
-
-	/* broadcast */
-	if (with_bcast) {
-		config->config_table[1].cam_entry.msb_mac_addr =
-			cpu_to_le16(0xffff);
-		config->config_table[1].cam_entry.middle_mac_addr =
-			cpu_to_le16(0xffff);
-		config->config_table[1].cam_entry.lsb_mac_addr =
-			cpu_to_le16(0xffff);
-		config->config_table[1].cam_entry.flags = cpu_to_le16(port);
-		if (set)
-			config->config_table[1].target_table_entry.flags =
-					TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST;
-		else
-			CAM_INVALIDATE(config->config_table[1]);
-		config->config_table[1].target_table_entry.clients_bit_vector =
-							cpu_to_le32(cl_bit_vec);
-		config->config_table[1].target_table_entry.vlan_id = 0;
-	}
-
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
-		      U64_HI(bnx2x_sp_mapping(bp, mac_config)),
-		      U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0);
+	/* Wait for completion */
+	return bnx2x_wait_ramrod(bp, BNX2X_STATE_CLOSING_WAIT4_UNLOAD,
+				      0, &(bp->state), WAIT_RAMROD_COMMON);
 }
 
 /**
- * Sets a MAC in a CAM for a few L2 Clients for E1H chip
+ * Sets a MAC in a CAM for a few L2 Clients for E1x chips
  *
  * @param bp driver descriptor
  * @param set set or clear an entry (1 or 0)
  * @param mac pointer to a buffer containing a MAC
  * @param cl_bit_vec bit vector of clients to register a MAC for
  * @param cam_offset offset in a CAM to use
+ * @param is_bcast is the set MAC a broadcast address (for E1 only)
  */
-static void bnx2x_set_mac_addr_e1h_gen(struct bnx2x *bp, int set, u8 *mac,
-				       u32 cl_bit_vec, u8 cam_offset)
+static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, u8 *mac,
+				   u32 cl_bit_vec, u8 cam_offset,
+				   u8 is_bcast)
 {
-	struct mac_configuration_cmd_e1h *config =
-		(struct mac_configuration_cmd_e1h *)bnx2x_sp(bp, mac_config);
+	struct mac_configuration_cmd *config =
+		(struct mac_configuration_cmd *)bnx2x_sp(bp, mac_config);
+	int ramrod_flags = WAIT_RAMROD_COMMON;
+
+	bp->set_mac_pending = 1;
+	smp_wmb();
 
 	config->hdr.length = 1;
 	config->hdr.offset = cam_offset;
@@ -4841,29 +6075,41 @@
 	config->config_table[0].clients_bit_vector =
 					cpu_to_le32(cl_bit_vec);
 	config->config_table[0].vlan_id = 0;
-	config->config_table[0].e1hov_id = cpu_to_le16(bp->e1hov);
+	config->config_table[0].pf_id = BP_FUNC(bp);
 	if (set)
-		config->config_table[0].flags = BP_PORT(bp);
+		SET_FLAG(config->config_table[0].flags,
+			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			T_ETH_MAC_COMMAND_SET);
 	else
-		config->config_table[0].flags =
-				MAC_CONFIGURATION_ENTRY_E1H_ACTION_TYPE;
+		SET_FLAG(config->config_table[0].flags,
+			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			T_ETH_MAC_COMMAND_INVALIDATE);
 
-	DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x)  E1HOV %d  CLID mask %d\n",
+	if (is_bcast)
+		SET_FLAG(config->config_table[0].flags,
+			MAC_CONFIGURATION_ENTRY_BROADCAST, 1);
+
+	DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x)  PF_ID %d  CLID mask %d\n",
 	   (set ? "setting" : "clearing"),
 	   config->config_table[0].msb_mac_addr,
 	   config->config_table[0].middle_mac_addr,
-	   config->config_table[0].lsb_mac_addr, bp->e1hov, cl_bit_vec);
+	   config->config_table[0].lsb_mac_addr, BP_FUNC(bp), cl_bit_vec);
 
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
+	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)), 0);
+		      U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
+
+	/* Wait for a completion */
+	bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, ramrod_flags);
 }
 
-static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
-			     int *state_p, int poll)
+int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
+		      int *state_p, int flags)
 {
 	/* can take a while if any port is running */
 	int cnt = 5000;
+	u8 poll = flags & WAIT_RAMROD_POLL;
+	u8 common = flags & WAIT_RAMROD_COMMON;
 
 	DP(NETIF_MSG_IFUP, "%s for state to become %x on IDX [%d]\n",
 	   poll ? "polling" : "waiting", state, idx);
@@ -4871,13 +6117,17 @@
 	might_sleep();
 	while (cnt--) {
 		if (poll) {
-			bnx2x_rx_int(bp->fp, 10);
-			/* if index is different from 0
-			 * the reply for some commands will
-			 * be on the non default queue
-			 */
-			if (idx)
-				bnx2x_rx_int(&bp->fp[idx], 10);
+			if (common)
+				bnx2x_eq_int(bp);
+			else {
+				bnx2x_rx_int(bp->fp, 10);
+				/* if index is different from 0
+				 * the reply for some commands will
+				 * be on the non default queue
+				 */
+				if (idx)
+					bnx2x_rx_int(&bp->fp[idx], 10);
+			}
 		}
 
 		mb(); /* state is changed by bnx2x_sp_event() */
@@ -4904,29 +6154,112 @@
 	return -EBUSY;
 }
 
-void bnx2x_set_eth_mac_addr_e1h(struct bnx2x *bp, int set)
+u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset)
 {
-	bp->set_mac_pending++;
-	smp_wmb();
-
-	bnx2x_set_mac_addr_e1h_gen(bp, set, bp->dev->dev_addr,
-				   (1 << bp->fp->cl_id), BP_FUNC(bp));
-
-	/* Wait for a completion */
-	bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, set ? 0 : 1);
+	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;
+	else
+		return BP_VN(bp) * 32  + rel_offset;
 }
 
-void bnx2x_set_eth_mac_addr_e1(struct bnx2x *bp, int set)
+void bnx2x_set_eth_mac(struct bnx2x *bp, int set)
 {
-	bp->set_mac_pending++;
+	u8 cam_offset = (CHIP_IS_E1(bp) ? (BP_PORT(bp) ? 32 : 0) :
+			 bnx2x_e1h_cam_offset(bp, CAM_ETH_LINE));
+
+	/* networking  MAC */
+	bnx2x_set_mac_addr_gen(bp, set, bp->dev->dev_addr,
+			       (1 << bp->fp->cl_id), cam_offset , 0);
+
+	if (CHIP_IS_E1(bp)) {
+		/* broadcast MAC */
+		u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+		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)
+{
+	int i = 0, old;
+	struct net_device *dev = bp->dev;
+	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);
+
+	netdev_for_each_mc_addr(ha, dev) {
+		/* copy mac */
+		config_cmd->config_table[i].msb_mac_addr =
+			swab16(*(u16 *)&bnx2x_mc_addr(ha)[0]);
+		config_cmd->config_table[i].middle_mac_addr =
+			swab16(*(u16 *)&bnx2x_mc_addr(ha)[2]);
+		config_cmd->config_table[i].lsb_mac_addr =
+			swab16(*(u16 *)&bnx2x_mc_addr(ha)[4]);
+
+		config_cmd->config_table[i].vlan_id = 0;
+		config_cmd->config_table[i].pf_id = BP_FUNC(bp);
+		config_cmd->config_table[i].clients_bit_vector =
+			cpu_to_le32(1 << BP_L_ID(bp));
+
+		SET_FLAG(config_cmd->config_table[i].flags,
+			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			T_ETH_MAC_COMMAND_SET);
+
+		DP(NETIF_MSG_IFUP,
+		   "setting MCAST[%d] (%04x:%04x:%04x)\n", i,
+		   config_cmd->config_table[i].msb_mac_addr,
+		   config_cmd->config_table[i].middle_mac_addr,
+		   config_cmd->config_table[i].lsb_mac_addr);
+		i++;
+	}
+	old = config_cmd->hdr.length;
+	if (old > i) {
+		for (; i < old; i++) {
+			if (CAM_IS_INVALID(config_cmd->
+					   config_table[i])) {
+				/* already invalidated */
+				break;
+			}
+			/* invalidate */
+			SET_FLAG(config_cmd->config_table[i].flags,
+				MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+				T_ETH_MAC_COMMAND_INVALIDATE);
+		}
+	}
+
+	config_cmd->hdr.length = i;
+	config_cmd->hdr.offset = offset;
+	config_cmd->hdr.client_id = 0xff;
+	config_cmd->hdr.reserved1 = 0;
+
+	bp->set_mac_pending = 1;
 	smp_wmb();
 
-	bnx2x_set_mac_addr_e1_gen(bp, set, bp->dev->dev_addr,
-				  (1 << bp->fp->cl_id), (BP_PORT(bp) ? 32 : 0),
-				  1);
+	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)
+{
+	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;
+
+	bp->set_mac_pending = 1;
+	smp_wmb();
+
+	for (i = 0; i < config_cmd->hdr.length; i++)
+		SET_FLAG(config_cmd->config_table[i].flags,
+			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			T_ETH_MAC_COMMAND_INVALIDATE);
+
+	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, set ? 0 : 1);
+	bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
+				ramrod_flags);
+
 }
 
 #ifdef BCM_CNIC
@@ -4942,174 +6275,463 @@
  */
 int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set)
 {
-	u32 cl_bit_vec = (1 << BCM_ISCSI_ETH_CL_ID);
-
-	bp->set_mac_pending++;
-	smp_wmb();
+	u8 cam_offset = (CHIP_IS_E1(bp) ? ((BP_PORT(bp) ? 32 : 0) + 2) :
+			 bnx2x_e1h_cam_offset(bp, CAM_ISCSI_ETH_LINE));
+	u32 iscsi_l2_cl_id = BNX2X_ISCSI_ETH_CL_ID;
+	u32 cl_bit_vec = (1 << iscsi_l2_cl_id);
 
 	/* Send a SET_MAC ramrod */
-	if (CHIP_IS_E1(bp))
-		bnx2x_set_mac_addr_e1_gen(bp, set, bp->iscsi_mac,
-				  cl_bit_vec, (BP_PORT(bp) ? 32 : 0) + 2,
-				  1);
-	else
-		/* CAM allocation for E1H
-		* unicasts: by func number
-		* multicast: 20+FUNC*20, 20 each
-		*/
-		bnx2x_set_mac_addr_e1h_gen(bp, set, bp->iscsi_mac,
-				   cl_bit_vec, E1H_FUNC_MAX + BP_FUNC(bp));
-
-	/* Wait for a completion when setting */
-	bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, set ? 0 : 1);
-
+	bnx2x_set_mac_addr_gen(bp, set, bp->iscsi_mac, cl_bit_vec,
+			       cam_offset, 0);
 	return 0;
 }
 #endif
 
-int bnx2x_setup_leading(struct bnx2x *bp)
+static void bnx2x_fill_cl_init_data(struct bnx2x *bp,
+				    struct bnx2x_client_init_params *params,
+				    u8 activate,
+				    struct client_init_ramrod_data *data)
 {
-	int rc;
+	/* Clear the buffer */
+	memset(data, 0, sizeof(*data));
 
-	/* reset IGU state */
-	bnx2x_ack_sb(bp, bp->fp[0].sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+	/* general */
+	data->general.client_id = params->rxq_params.cl_id;
+	data->general.statistics_counter_id = params->rxq_params.stat_id;
+	data->general.statistics_en_flg =
+		(params->rxq_params.flags & QUEUE_FLG_STATS) ? 1 : 0;
+	data->general.activate_flg = activate;
+	data->general.sp_client_id = params->rxq_params.spcl_id;
 
-	/* SETUP ramrod */
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_PORT_SETUP, 0, 0, 0, 0);
+	/* Rx data */
+	data->rx.tpa_en_flg =
+		(params->rxq_params.flags & QUEUE_FLG_TPA) ? 1 : 0;
+	data->rx.vmqueue_mode_en_flg = 0;
+	data->rx.cache_line_alignment_log_size =
+		params->rxq_params.cache_line_log;
+	data->rx.enable_dynamic_hc =
+		(params->rxq_params.flags & QUEUE_FLG_DHC) ? 1 : 0;
+	data->rx.max_sges_for_packet = params->rxq_params.max_sges_pkt;
+	data->rx.client_qzone_id = params->rxq_params.cl_qzone_id;
+	data->rx.max_agg_size = params->rxq_params.tpa_agg_sz;
+
+	/* We don't set drop flags */
+	data->rx.drop_ip_cs_err_flg = 0;
+	data->rx.drop_tcp_cs_err_flg = 0;
+	data->rx.drop_ttl0_flg = 0;
+	data->rx.drop_udp_cs_err_flg = 0;
+
+	data->rx.inner_vlan_removal_enable_flg =
+		(params->rxq_params.flags & QUEUE_FLG_VLAN) ? 1 : 0;
+	data->rx.outer_vlan_removal_enable_flg =
+		(params->rxq_params.flags & QUEUE_FLG_OV) ? 1 : 0;
+	data->rx.status_block_id = params->rxq_params.fw_sb_id;
+	data->rx.rx_sb_index_number = params->rxq_params.sb_cq_index;
+	data->rx.bd_buff_size = cpu_to_le16(params->rxq_params.buf_sz);
+	data->rx.sge_buff_size = cpu_to_le16(params->rxq_params.sge_buf_sz);
+	data->rx.mtu = cpu_to_le16(params->rxq_params.mtu);
+	data->rx.bd_page_base.lo =
+		cpu_to_le32(U64_LO(params->rxq_params.dscr_map));
+	data->rx.bd_page_base.hi =
+		cpu_to_le32(U64_HI(params->rxq_params.dscr_map));
+	data->rx.sge_page_base.lo =
+		cpu_to_le32(U64_LO(params->rxq_params.sge_map));
+	data->rx.sge_page_base.hi =
+		cpu_to_le32(U64_HI(params->rxq_params.sge_map));
+	data->rx.cqe_page_base.lo =
+		cpu_to_le32(U64_LO(params->rxq_params.rcq_map));
+	data->rx.cqe_page_base.hi =
+		cpu_to_le32(U64_HI(params->rxq_params.rcq_map));
+	data->rx.is_leading_rss =
+		(params->ramrod_params.flags & CLIENT_IS_LEADING_RSS) ? 1 : 0;
+	data->rx.is_approx_mcast = data->rx.is_leading_rss;
+
+	/* Tx data */
+	data->tx.enforce_security_flg = 0; /* VF specific */
+	data->tx.tx_status_block_id = params->txq_params.fw_sb_id;
+	data->tx.tx_sb_index_number = params->txq_params.sb_cq_index;
+	data->tx.mtu = 0; /* VF specific */
+	data->tx.tx_bd_page_base.lo =
+		cpu_to_le32(U64_LO(params->txq_params.dscr_map));
+	data->tx.tx_bd_page_base.hi =
+		cpu_to_le32(U64_HI(params->txq_params.dscr_map));
+
+	/* flow control data */
+	data->fc.cqe_pause_thr_low = cpu_to_le16(params->pause.rcq_th_lo);
+	data->fc.cqe_pause_thr_high = cpu_to_le16(params->pause.rcq_th_hi);
+	data->fc.bd_pause_thr_low = cpu_to_le16(params->pause.bd_th_lo);
+	data->fc.bd_pause_thr_high = cpu_to_le16(params->pause.bd_th_hi);
+	data->fc.sge_pause_thr_low = cpu_to_le16(params->pause.sge_th_lo);
+	data->fc.sge_pause_thr_high = cpu_to_le16(params->pause.sge_th_hi);
+	data->fc.rx_cos_mask = cpu_to_le16(params->pause.pri_map);
+
+	data->fc.safc_group_num = params->txq_params.cos;
+	data->fc.safc_group_en_flg =
+		(params->txq_params.flags & QUEUE_FLG_COS) ? 1 : 0;
+	data->fc.traffic_type = LLFC_TRAFFIC_TYPE_NW;
+}
+
+static inline void bnx2x_set_ctx_validation(struct eth_context *cxt, u32 cid)
+{
+	/* ustorm cxt validation */
+	cxt->ustorm_ag_context.cdu_usage =
+		CDU_RSRVD_VALUE_TYPE_A(cid, CDU_REGION_NUMBER_UCM_AG,
+				       ETH_CONNECTION_TYPE);
+	/* xcontext validation */
+	cxt->xstorm_ag_context.cdu_reserved =
+		CDU_RSRVD_VALUE_TYPE_A(cid, CDU_REGION_NUMBER_XCM_AG,
+				       ETH_CONNECTION_TYPE);
+}
+
+int bnx2x_setup_fw_client(struct bnx2x *bp,
+			  struct bnx2x_client_init_params *params,
+			  u8 activate,
+			  struct client_init_ramrod_data *data,
+			  dma_addr_t data_mapping)
+{
+	u16 hc_usec;
+	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
+	int ramrod_flags = 0, rc;
+
+	/* HC and context validation values */
+	hc_usec = params->txq_params.hc_rate ?
+		1000000 / params->txq_params.hc_rate : 0;
+	bnx2x_update_coalesce_sb_index(bp,
+			params->txq_params.fw_sb_id,
+			params->txq_params.sb_cq_index,
+			!(params->txq_params.flags & QUEUE_FLG_HC),
+			hc_usec);
+
+	*(params->ramrod_params.pstate) = BNX2X_FP_STATE_OPENING;
+
+	hc_usec = params->rxq_params.hc_rate ?
+		1000000 / params->rxq_params.hc_rate : 0;
+	bnx2x_update_coalesce_sb_index(bp,
+			params->rxq_params.fw_sb_id,
+			params->rxq_params.sb_cq_index,
+			!(params->rxq_params.flags & QUEUE_FLG_HC),
+			hc_usec);
+
+	bnx2x_set_ctx_validation(params->rxq_params.cxt,
+				 params->rxq_params.cid);
+
+	/* zero stats */
+	if (params->txq_params.flags & QUEUE_FLG_STATS)
+		storm_memset_xstats_zero(bp, BP_PORT(bp),
+					 params->txq_params.stat_id);
+
+	if (params->rxq_params.flags & QUEUE_FLG_STATS) {
+		storm_memset_ustats_zero(bp, BP_PORT(bp),
+					 params->rxq_params.stat_id);
+		storm_memset_tstats_zero(bp, BP_PORT(bp),
+					 params->rxq_params.stat_id);
+	}
+
+	/* Fill the ramrod data */
+	bnx2x_fill_cl_init_data(bp, params, activate, data);
+
+	/* SETUP ramrod.
+	 *
+	 * bnx2x_sp_post() takes a spin_lock thus no other explict memory
+	 * barrier except from mmiowb() is needed to impose a
+	 * proper ordering of memory operations.
+	 */
+	mmiowb();
+
+
+	bnx2x_sp_post(bp, ramrod, params->ramrod_params.cid,
+		      U64_HI(data_mapping), U64_LO(data_mapping), 0);
 
 	/* Wait for completion */
-	rc = bnx2x_wait_ramrod(bp, BNX2X_STATE_OPEN, 0, &(bp->state), 0);
+	rc = bnx2x_wait_ramrod(bp, params->ramrod_params.state,
+				 params->ramrod_params.index,
+				 params->ramrod_params.pstate,
+				 ramrod_flags);
+	return rc;
+}
+
+/**
+ * Configure interrupt mode according to current configuration.
+ * In case of MSI-X it will also try to enable MSI-X.
+ *
+ * @param bp
+ *
+ * @return int
+ */
+static int __devinit bnx2x_set_int_mode(struct bnx2x *bp)
+{
+	int rc = 0;
+
+	switch (bp->int_mode) {
+	case INT_MODE_MSI:
+		bnx2x_enable_msi(bp);
+		/* falling through... */
+	case INT_MODE_INTx:
+		bp->num_queues = 1;
+		DP(NETIF_MSG_IFUP, "set number of queues to 1\n");
+		break;
+	default:
+		/* Set number of queues according to bp->multi_mode value */
+		bnx2x_set_num_queues(bp);
+
+		DP(NETIF_MSG_IFUP, "set number of queues to %d\n",
+		   bp->num_queues);
+
+		/* if we can't use MSI-X we only need one fp,
+		 * so try to enable MSI-X with the requested number of fp's
+		 * and fallback to MSI or legacy INTx with one fp
+		 */
+		rc = bnx2x_enable_msix(bp);
+		if (rc) {
+			/* failed to enable MSI-X */
+			if (bp->multi_mode)
+				DP(NETIF_MSG_IFUP,
+					  "Multi requested but failed to "
+					  "enable MSI-X (%d), "
+					  "set number of queues to %d\n",
+				   bp->num_queues,
+				   1);
+			bp->num_queues = 1;
+
+			if (!(bp->flags & DISABLE_MSI_FLAG))
+				bnx2x_enable_msi(bp);
+		}
+
+		break;
+	}
 
 	return rc;
 }
 
-int bnx2x_setup_multi(struct bnx2x *bp, int index)
+/* must be called prioir to any HW initializations */
+static inline u16 bnx2x_cid_ilt_lines(struct bnx2x *bp)
 {
-	struct bnx2x_fastpath *fp = &bp->fp[index];
-
-	/* reset IGU state */
-	bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
-
-	/* SETUP ramrod */
-	fp->state = BNX2X_FP_STATE_OPENING;
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_SETUP, index, 0,
-		      fp->cl_id, 0);
-
-	/* Wait for completion */
-	return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_OPEN, index,
-				 &(fp->state), 0);
+	return L2_ILT_LINES(bp);
 }
 
-
-void bnx2x_set_num_queues_msix(struct bnx2x *bp)
+void bnx2x_ilt_set_info(struct bnx2x *bp)
 {
+	struct ilt_client_info *ilt_client;
+	struct bnx2x_ilt *ilt = BP_ILT(bp);
+	u16 line = 0;
 
-	switch (bp->multi_mode) {
-	case ETH_RSS_MODE_DISABLED:
-		bp->num_queues = 1;
-		break;
+	ilt->start_line = FUNC_ILT_BASE(BP_FUNC(bp));
+	DP(BNX2X_MSG_SP, "ilt starts at line %d\n", ilt->start_line);
 
-	case ETH_RSS_MODE_REGULAR:
-		if (num_queues)
-			bp->num_queues = min_t(u32, num_queues,
-						  BNX2X_MAX_QUEUES(bp));
-		else
-			bp->num_queues = min_t(u32, num_online_cpus(),
-						  BNX2X_MAX_QUEUES(bp));
-		break;
+	/* CDU */
+	ilt_client = &ilt->clients[ILT_CLIENT_CDU];
+	ilt_client->client_num = ILT_CLIENT_CDU;
+	ilt_client->page_size = CDU_ILT_PAGE_SZ;
+	ilt_client->flags = ILT_CLIENT_SKIP_MEM;
+	ilt_client->start = line;
+	line += L2_ILT_LINES(bp);
+#ifdef BCM_CNIC
+	line += CNIC_ILT_LINES;
+#endif
+	ilt_client->end = line - 1;
 
+	DP(BNX2X_MSG_SP, "ilt client[CDU]: start %d, end %d, psz 0x%x, "
+					 "flags 0x%x, hw psz %d\n",
+	   ilt_client->start,
+	   ilt_client->end,
+	   ilt_client->page_size,
+	   ilt_client->flags,
+	   ilog2(ilt_client->page_size >> 12));
 
-	default:
-		bp->num_queues = 1;
-		break;
+	/* QM */
+	if (QM_INIT(bp->qm_cid_count)) {
+		ilt_client = &ilt->clients[ILT_CLIENT_QM];
+		ilt_client->client_num = ILT_CLIENT_QM;
+		ilt_client->page_size = QM_ILT_PAGE_SZ;
+		ilt_client->flags = 0;
+		ilt_client->start = line;
+
+		/* 4 bytes for each cid */
+		line += DIV_ROUND_UP(bp->qm_cid_count * QM_QUEUES_PER_FUNC * 4,
+							 QM_ILT_PAGE_SZ);
+
+		ilt_client->end = line - 1;
+
+		DP(BNX2X_MSG_SP, "ilt client[QM]: start %d, end %d, psz 0x%x, "
+						 "flags 0x%x, hw psz %d\n",
+		   ilt_client->start,
+		   ilt_client->end,
+		   ilt_client->page_size,
+		   ilt_client->flags,
+		   ilog2(ilt_client->page_size >> 12));
+
 	}
+	/* SRC */
+	ilt_client = &ilt->clients[ILT_CLIENT_SRC];
+#ifdef BCM_CNIC
+	ilt_client->client_num = ILT_CLIENT_SRC;
+	ilt_client->page_size = SRC_ILT_PAGE_SZ;
+	ilt_client->flags = 0;
+	ilt_client->start = line;
+	line += SRC_ILT_LINES;
+	ilt_client->end = line - 1;
+
+	DP(BNX2X_MSG_SP, "ilt client[SRC]: start %d, end %d, psz 0x%x, "
+					 "flags 0x%x, hw psz %d\n",
+	   ilt_client->start,
+	   ilt_client->end,
+	   ilt_client->page_size,
+	   ilt_client->flags,
+	   ilog2(ilt_client->page_size >> 12));
+
+#else
+	ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
+#endif
+
+	/* TM */
+	ilt_client = &ilt->clients[ILT_CLIENT_TM];
+#ifdef BCM_CNIC
+	ilt_client->client_num = ILT_CLIENT_TM;
+	ilt_client->page_size = TM_ILT_PAGE_SZ;
+	ilt_client->flags = 0;
+	ilt_client->start = line;
+	line += TM_ILT_LINES;
+	ilt_client->end = line - 1;
+
+	DP(BNX2X_MSG_SP, "ilt client[TM]: start %d, end %d, psz 0x%x, "
+					 "flags 0x%x, hw psz %d\n",
+	   ilt_client->start,
+	   ilt_client->end,
+	   ilt_client->page_size,
+	   ilt_client->flags,
+	   ilog2(ilt_client->page_size >> 12));
+
+#else
+	ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
+#endif
 }
 
-
-
-static int bnx2x_stop_multi(struct bnx2x *bp, int index)
+int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+		       int is_leading)
 {
-	struct bnx2x_fastpath *fp = &bp->fp[index];
+	struct bnx2x_client_init_params params = { {0} };
 	int rc;
 
+	bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0,
+			     IGU_INT_ENABLE, 0);
+
+	params.ramrod_params.pstate = &fp->state;
+	params.ramrod_params.state = BNX2X_FP_STATE_OPEN;
+	params.ramrod_params.index = fp->index;
+	params.ramrod_params.cid = fp->cid;
+
+	if (is_leading)
+		params.ramrod_params.flags |= CLIENT_IS_LEADING_RSS;
+
+	bnx2x_pf_rx_cl_prep(bp, fp, &params.pause, &params.rxq_params);
+
+	bnx2x_pf_tx_cl_prep(bp, fp, &params.txq_params);
+
+	rc = bnx2x_setup_fw_client(bp, &params, 1,
+				     bnx2x_sp(bp, client_init_data),
+				     bnx2x_sp_mapping(bp, client_init_data));
+	return rc;
+}
+
+int bnx2x_stop_fw_client(struct bnx2x *bp, struct bnx2x_client_ramrod_params *p)
+{
+	int rc;
+
+	int poll_flag = p->poll ? WAIT_RAMROD_POLL : 0;
+
 	/* halt the connection */
-	fp->state = BNX2X_FP_STATE_HALTING;
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, index, 0, fp->cl_id, 0);
+	*p->pstate = BNX2X_FP_STATE_HALTING;
+	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, p->cid, 0,
+						  p->cl_id, 0);
 
 	/* Wait for completion */
-	rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, index,
-			       &(fp->state), 1);
+	rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, p->index,
+			       p->pstate, poll_flag);
 	if (rc) /* timeout */
 		return rc;
 
+	*p->pstate = BNX2X_FP_STATE_TERMINATING;
+	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, p->cid, 0,
+						       p->cl_id, 0);
+	/* Wait for completion */
+	rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_TERMINATED, p->index,
+			       p->pstate, poll_flag);
+	if (rc) /* timeout */
+		return rc;
+
+
 	/* delete cfc entry */
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CFC_DEL, index, 0, 0, 1);
+	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, p->cid, 0, 0, 1);
 
 	/* Wait for completion */
-	rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, index,
-			       &(fp->state), 1);
+	rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, p->index,
+			       p->pstate, WAIT_RAMROD_COMMON);
 	return rc;
 }
 
-static int bnx2x_stop_leading(struct bnx2x *bp)
+static int bnx2x_stop_client(struct bnx2x *bp, int index)
 {
-	__le16 dsb_sp_prod_idx;
-	/* if the other port is handling traffic,
-	   this can take a lot of time */
-	int cnt = 500;
-	int rc;
+	struct bnx2x_client_ramrod_params client_stop = {0};
+	struct bnx2x_fastpath *fp = &bp->fp[index];
 
-	might_sleep();
+	client_stop.index = index;
+	client_stop.cid = fp->cid;
+	client_stop.cl_id = fp->cl_id;
+	client_stop.pstate = &(fp->state);
+	client_stop.poll = 0;
 
-	/* Send HALT ramrod */
-	bp->fp[0].state = BNX2X_FP_STATE_HALTING;
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, 0, 0, bp->fp->cl_id, 0);
-
-	/* Wait for completion */
-	rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, 0,
-			       &(bp->fp[0].state), 1);
-	if (rc) /* timeout */
-		return rc;
-
-	dsb_sp_prod_idx = *bp->dsb_sp_prod;
-
-	/* Send PORT_DELETE ramrod */
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_PORT_DEL, 0, 0, 0, 1);
-
-	/* Wait for completion to arrive on default status block
-	   we are going to reset the chip anyway
-	   so there is not much to do if this times out
-	 */
-	while (dsb_sp_prod_idx == *bp->dsb_sp_prod) {
-		if (!cnt) {
-			DP(NETIF_MSG_IFDOWN, "timeout waiting for port del "
-			   "dsb_sp_prod 0x%x != dsb_sp_prod_idx 0x%x\n",
-			   *bp->dsb_sp_prod, dsb_sp_prod_idx);
-#ifdef BNX2X_STOP_ON_ERROR
-			bnx2x_panic();
-#endif
-			rc = -EBUSY;
-			break;
-		}
-		cnt--;
-		msleep(1);
-		rmb(); /* Refresh the dsb_sp_prod */
-	}
-	bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
-	bp->fp[0].state = BNX2X_FP_STATE_CLOSED;
-
-	return rc;
+	return bnx2x_stop_fw_client(bp, &client_stop);
 }
 
+
 static void bnx2x_reset_func(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
 	int func = BP_FUNC(bp);
-	int base, i;
+	int i;
+	int pfunc_offset_fp = offsetof(struct hc_sb_data, p_func) +
+			(CHIP_IS_E2(bp) ?
+			 offsetof(struct hc_status_block_data_e2, common) :
+			 offsetof(struct hc_status_block_data_e1x, common));
+	int pfunc_offset_sp = offsetof(struct hc_sp_status_block_data, p_func);
+	int pfid_offset = offsetof(struct pci_entity, pf_id);
+
+	/* Disable the function in the FW */
+	REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(func), 0);
+	REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNC_EN_OFFSET(func), 0);
+	REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNC_EN_OFFSET(func), 0);
+	REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNC_EN_OFFSET(func), 0);
+
+	/* FP SBs */
+	for_each_queue(bp, i) {
+		struct bnx2x_fastpath *fp = &bp->fp[i];
+		REG_WR8(bp,
+			BAR_CSTRORM_INTMEM +
+			CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id)
+			+ pfunc_offset_fp + pfid_offset,
+			HC_FUNCTION_DISABLED);
+	}
+
+	/* SP SB */
+	REG_WR8(bp,
+		BAR_CSTRORM_INTMEM +
+		CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
+		pfunc_offset_sp + pfid_offset,
+		HC_FUNCTION_DISABLED);
+
+
+	for (i = 0; i < XSTORM_SPQ_DATA_SIZE / 4; i++)
+		REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_DATA_OFFSET(func),
+		       0);
 
 	/* Configure IGU */
-	REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
-	REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+	if (bp->common.int_block == INT_BLOCK_HC) {
+		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
+		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+	} else {
+		REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, 0);
+		REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
+	}
 
 #ifdef BCM_CNIC
 	/* Disable Timer scan */
@@ -5125,9 +6747,27 @@
 	}
 #endif
 	/* Clear ILT */
-	base = FUNC_ILT_BASE(func);
-	for (i = base; i < base + ILT_PER_FUNC; i++)
-		bnx2x_ilt_wr(bp, i, 0);
+	bnx2x_clear_func_ilt(bp, func);
+
+	/* Timers workaround bug for E2: if this is vnic-3,
+	 * we need to set the entire ilt range for this timers.
+	 */
+	if (CHIP_IS_E2(bp) && BP_VN(bp) == 3) {
+		struct ilt_client_info ilt_cli;
+		/* use dummy TM client */
+		memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
+		ilt_cli.start = 0;
+		ilt_cli.end = ILT_NUM_PAGE_ENTRIES - 1;
+		ilt_cli.client_num = ILT_CLIENT_TM;
+
+		bnx2x_ilt_boundry_init_op(bp, &ilt_cli, 0, INITOP_CLEAR);
+	}
+
+	/* this assumes that reset_port() called before reset_func()*/
+	if (CHIP_IS_E2(bp))
+		bnx2x_pf_disable(bp);
+
+	bp->dmae_ready = 0;
 }
 
 static void bnx2x_reset_port(struct bnx2x *bp)
@@ -5159,7 +6799,7 @@
 static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
 {
 	DP(BNX2X_MSG_MCP, "function %d  reset_code %x\n",
-	   BP_FUNC(bp), reset_code);
+	   BP_ABS_FUNC(bp), reset_code);
 
 	switch (reset_code) {
 	case FW_MSG_CODE_DRV_UNLOAD_COMMON:
@@ -5196,7 +6836,6 @@
 		cnt = 1000;
 		while (bnx2x_has_tx_work_unload(fp)) {
 
-			bnx2x_tx_int(fp);
 			if (!cnt) {
 				BNX2X_ERR("timeout waiting for queue[%d]\n",
 					  i);
@@ -5215,39 +6854,21 @@
 	msleep(1);
 
 	if (CHIP_IS_E1(bp)) {
-		struct mac_configuration_cmd *config =
-						bnx2x_sp(bp, mcast_config);
+		/* invalidate mc list,
+		 * wait and poll (interrupts are off)
+		 */
+		bnx2x_invlidate_e1_mc_list(bp);
+		bnx2x_set_eth_mac(bp, 0);
 
-		bnx2x_set_eth_mac_addr_e1(bp, 0);
-
-		for (i = 0; i < config->hdr.length; i++)
-			CAM_INVALIDATE(config->config_table[i]);
-
-		config->hdr.length = i;
-		if (CHIP_REV_IS_SLOW(bp))
-			config->hdr.offset = BNX2X_MAX_EMUL_MULTI*(1 + port);
-		else
-			config->hdr.offset = BNX2X_MAX_MULTICAST*(1 + port);
-		config->hdr.client_id = bp->fp->cl_id;
-		config->hdr.reserved1 = 0;
-
-		bp->set_mac_pending++;
-		smp_wmb();
-
-		bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
-			      U64_HI(bnx2x_sp_mapping(bp, mcast_config)),
-			      U64_LO(bnx2x_sp_mapping(bp, mcast_config)), 0);
-
-	} else { /* E1H */
+	} else {
 		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
 
-		bnx2x_set_eth_mac_addr_e1h(bp, 0);
+		bnx2x_set_eth_mac(bp, 0);
 
 		for (i = 0; i < MC_HASH_SIZE; i++)
 			REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
-
-		REG_WR(bp, MISC_REG_E1HMF_MODE, 0);
 	}
+
 #ifdef BCM_CNIC
 	/* Clear iSCSI L2 MAC */
 	mutex_lock(&bp->cnic_mutex);
@@ -5286,33 +6907,44 @@
 
 	/* Close multi and leading connections
 	   Completions for ramrods are collected in a synchronous way */
-	for_each_nondefault_queue(bp, i)
-		if (bnx2x_stop_multi(bp, i))
-			goto unload_error;
+	for_each_queue(bp, i)
 
-	rc = bnx2x_stop_leading(bp);
-	if (rc) {
-		BNX2X_ERR("Stop leading failed!\n");
+		if (bnx2x_stop_client(bp, i))
 #ifdef BNX2X_STOP_ON_ERROR
-		return -EBUSY;
+			return;
+#else
+			goto unload_error;
+#endif
+
+	rc = bnx2x_func_stop(bp);
+	if (rc) {
+		BNX2X_ERR("Function stop failed!\n");
+#ifdef BNX2X_STOP_ON_ERROR
+		return;
 #else
 		goto unload_error;
 #endif
 	}
-
+#ifndef BNX2X_STOP_ON_ERROR
 unload_error:
+#endif
 	if (!BP_NOMCP(bp))
-		reset_code = bnx2x_fw_command(bp, reset_code);
+		reset_code = bnx2x_fw_command(bp, reset_code, 0);
 	else {
-		DP(NETIF_MSG_IFDOWN, "NO MCP - load counts      %d, %d, %d\n",
-		   load_count[0], load_count[1], load_count[2]);
-		load_count[0]--;
-		load_count[1 + port]--;
-		DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts  %d, %d, %d\n",
-		   load_count[0], load_count[1], load_count[2]);
-		if (load_count[0] == 0)
+		DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d]      "
+				     "%d, %d, %d\n", BP_PATH(bp),
+		   load_count[BP_PATH(bp)][0],
+		   load_count[BP_PATH(bp)][1],
+		   load_count[BP_PATH(bp)][2]);
+		load_count[BP_PATH(bp)][0]--;
+		load_count[BP_PATH(bp)][1 + port]--;
+		DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d]  "
+				     "%d, %d, %d\n", BP_PATH(bp),
+		   load_count[BP_PATH(bp)][0], load_count[BP_PATH(bp)][1],
+		   load_count[BP_PATH(bp)][2]);
+		if (load_count[BP_PATH(bp)][0] == 0)
 			reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
-		else if (load_count[1 + port] == 0)
+		else if (load_count[BP_PATH(bp)][1 + port] == 0)
 			reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
 		else
 			reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
@@ -5322,12 +6954,18 @@
 	    (reset_code == FW_MSG_CODE_DRV_UNLOAD_PORT))
 		bnx2x__link_reset(bp);
 
+	/* Disable HW interrupts, NAPI */
+	bnx2x_netif_stop(bp, 1);
+
+	/* Release IRQs */
+	bnx2x_free_irq(bp);
+
 	/* Reset the chip */
 	bnx2x_reset_chip(bp, reset_code);
 
 	/* Report UNLOAD_DONE to MCP */
 	if (!BP_NOMCP(bp))
-		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
 
 }
 
@@ -5353,7 +6991,6 @@
 	}
 }
 
-
 /* Close gates #2, #3 and #4: */
 static void bnx2x_set_234_gates(struct bnx2x *bp, bool close)
 {
@@ -5399,15 +7036,13 @@
 static void bnx2x_clp_reset_done(struct bnx2x *bp, u32 magic_val)
 {
 	/* Restore the `magic' bit value... */
-	/* u32 val = SHMEM_RD(bp, mf_cfg.shared_mf_config.clp_mb);
-	SHMEM_WR(bp, mf_cfg.shared_mf_config.clp_mb,
-		(val & (~SHARED_MF_CLP_MAGIC)) | magic_val); */
 	u32 val = MF_CFG_RD(bp, shared_mf_config.clp_mb);
 	MF_CFG_WR(bp, shared_mf_config.clp_mb,
 		(val & (~SHARED_MF_CLP_MAGIC)) | magic_val);
 }
 
-/* Prepares for MCP reset: takes care of CLP configurations.
+/**
+ * Prepares for MCP reset: takes care of CLP configurations.
  *
  * @param bp
  * @param magic_val Old value of 'magic' bit.
@@ -5805,39 +7440,23 @@
  * Init service functions
  */
 
-static inline u32 bnx2x_get_pretend_reg(struct bnx2x *bp, int func)
+u32 bnx2x_get_pretend_reg(struct bnx2x *bp)
 {
-	switch (func) {
-	case 0: return PXP2_REG_PGL_PRETEND_FUNC_F0;
-	case 1:	return PXP2_REG_PGL_PRETEND_FUNC_F1;
-	case 2:	return PXP2_REG_PGL_PRETEND_FUNC_F2;
-	case 3:	return PXP2_REG_PGL_PRETEND_FUNC_F3;
-	case 4:	return PXP2_REG_PGL_PRETEND_FUNC_F4;
-	case 5:	return PXP2_REG_PGL_PRETEND_FUNC_F5;
-	case 6:	return PXP2_REG_PGL_PRETEND_FUNC_F6;
-	case 7:	return PXP2_REG_PGL_PRETEND_FUNC_F7;
-	default:
-		BNX2X_ERR("Unsupported function index: %d\n", func);
-		return (u32)(-1);
-	}
+	u32 base = PXP2_REG_PGL_PRETEND_FUNC_F0;
+	u32 stride = PXP2_REG_PGL_PRETEND_FUNC_F1 - base;
+	return base + (BP_ABS_FUNC(bp)) * stride;
 }
 
-static void bnx2x_undi_int_disable_e1h(struct bnx2x *bp, int orig_func)
+static void bnx2x_undi_int_disable_e1h(struct bnx2x *bp)
 {
-	u32 reg = bnx2x_get_pretend_reg(bp, orig_func), new_val;
+	u32 reg = bnx2x_get_pretend_reg(bp);
 
 	/* Flush all outstanding writes */
 	mmiowb();
 
 	/* Pretend to be function 0 */
 	REG_WR(bp, reg, 0);
-	/* Flush the GRC transaction (in the chip) */
-	new_val = REG_RD(bp, reg);
-	if (new_val != 0) {
-		BNX2X_ERR("Hmmm... Pretend register wasn't updated: (0,%d)!\n",
-			  new_val);
-		BUG();
-	}
+	REG_RD(bp, reg);	/* Flush the GRC transaction (in the chip) */
 
 	/* From now we are in the "like-E1" mode */
 	bnx2x_int_disable(bp);
@@ -5845,22 +7464,17 @@
 	/* Flush all outstanding writes */
 	mmiowb();
 
-	/* Restore the original funtion settings */
-	REG_WR(bp, reg, orig_func);
-	new_val = REG_RD(bp, reg);
-	if (new_val != orig_func) {
-		BNX2X_ERR("Hmmm... Pretend register wasn't updated: (%d,%d)!\n",
-			  orig_func, new_val);
-		BUG();
-	}
+	/* Restore the original function */
+	REG_WR(bp, reg, BP_ABS_FUNC(bp));
+	REG_RD(bp, reg);
 }
 
-static inline void bnx2x_undi_int_disable(struct bnx2x *bp, int func)
+static inline void bnx2x_undi_int_disable(struct bnx2x *bp)
 {
-	if (CHIP_IS_E1H(bp))
-		bnx2x_undi_int_disable_e1h(bp, func);
-	else
+	if (CHIP_IS_E1(bp))
 		bnx2x_int_disable(bp);
+	else
+		bnx2x_undi_int_disable_e1h(bp);
 }
 
 static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
@@ -5877,8 +7491,8 @@
 		val = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
 		if (val == 0x7) {
 			u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
-			/* save our func */
-			int func = BP_FUNC(bp);
+			/* save our pf_num */
+			int orig_pf_num = bp->pf_num;
 			u32 swap_en;
 			u32 swap_val;
 
@@ -5888,32 +7502,33 @@
 			BNX2X_DEV_INFO("UNDI is active! reset device\n");
 
 			/* try unload UNDI on port 0 */
-			bp->func = 0;
+			bp->pf_num = 0;
 			bp->fw_seq =
-			       (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
+			      (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
 				DRV_MSG_SEQ_NUMBER_MASK);
-			reset_code = bnx2x_fw_command(bp, reset_code);
+			reset_code = bnx2x_fw_command(bp, reset_code, 0);
 
 			/* if UNDI is loaded on the other port */
 			if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) {
 
 				/* send "DONE" for previous unload */
-				bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+				bnx2x_fw_command(bp,
+						 DRV_MSG_CODE_UNLOAD_DONE, 0);
 
 				/* unload UNDI on port 1 */
-				bp->func = 1;
+				bp->pf_num = 1;
 				bp->fw_seq =
-			       (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
+			      (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
 					DRV_MSG_SEQ_NUMBER_MASK);
 				reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
 
-				bnx2x_fw_command(bp, reset_code);
+				bnx2x_fw_command(bp, reset_code, 0);
 			}
 
 			/* now it's safe to release the lock */
 			bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
 
-			bnx2x_undi_int_disable(bp, func);
+			bnx2x_undi_int_disable(bp);
 
 			/* close input traffic and wait for it */
 			/* Do not rcv packets to BRB */
@@ -5949,14 +7564,13 @@
 			REG_WR(bp, NIG_REG_STRAP_OVERRIDE, swap_en);
 
 			/* send unload done to the MCP */
-			bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+			bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
 
 			/* restore our func and fw_seq */
-			bp->func = func;
+			bp->pf_num = orig_pf_num;
 			bp->fw_seq =
-			       (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
+			      (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
 				DRV_MSG_SEQ_NUMBER_MASK);
-
 		} else
 			bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
 	}
@@ -5978,6 +7592,40 @@
 	val = REG_RD(bp, MISC_REG_BOND_ID);
 	id |= (val & 0xf);
 	bp->common.chip_id = id;
+
+	/* Set doorbell size */
+	bp->db_size = (1 << BNX2X_DB_SHIFT);
+
+	if (CHIP_IS_E2(bp)) {
+		val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
+		if ((val & 1) == 0)
+			val = REG_RD(bp, MISC_REG_PORT4MODE_EN);
+		else
+			val = (val >> 1) & 1;
+		BNX2X_DEV_INFO("chip is in %s\n", val ? "4_PORT_MODE" :
+						       "2_PORT_MODE");
+		bp->common.chip_port_mode = val ? CHIP_4_PORT_MODE :
+						 CHIP_2_PORT_MODE;
+
+		if (CHIP_MODE_IS_4_PORT(bp))
+			bp->pfid = (bp->pf_num >> 1);	/* 0..3 */
+		else
+			bp->pfid = (bp->pf_num & 0x6);	/* 0, 2, 4, 6 */
+	} else {
+		bp->common.chip_port_mode = CHIP_PORT_MODE_NONE; /* N/A */
+		bp->pfid = bp->pf_num;			/* 0..7 */
+	}
+
+	/*
+	 * set base FW non-default (fast path) status block id, this value is
+	 * used to initialize the fw_sb_id saved on the fp/queue structure to
+	 * determine the id used by the FW.
+	 */
+	if (CHIP_IS_E1x(bp))
+		bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E1x;
+	else /* E2 */
+		bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E2;
+
 	bp->link_params.chip_id = bp->common.chip_id;
 	BNX2X_DEV_INFO("chip ID is 0x%x\n", id);
 
@@ -5995,14 +7643,15 @@
 		       bp->common.flash_size, bp->common.flash_size);
 
 	bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
-	bp->common.shmem2_base = REG_RD(bp, MISC_REG_GENERIC_CR_0);
+	bp->common.shmem2_base = REG_RD(bp, (BP_PATH(bp) ?
+					MISC_REG_GENERIC_CR_1 :
+					MISC_REG_GENERIC_CR_0));
 	bp->link_params.shmem_base = bp->common.shmem_base;
+	bp->link_params.shmem2_base = bp->common.shmem2_base;
 	BNX2X_DEV_INFO("shmem offset 0x%x  shmem2 offset 0x%x\n",
 		       bp->common.shmem_base, bp->common.shmem2_base);
 
-	if (!bp->common.shmem_base ||
-	    (bp->common.shmem_base < 0xA0000) ||
-	    (bp->common.shmem_base >= 0xC0000)) {
+	if (!bp->common.shmem_base) {
 		BNX2X_DEV_INFO("MCP not active\n");
 		bp->flags |= NO_MCP_FLAG;
 		return;
@@ -6011,7 +7660,7 @@
 	val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]);
 	if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
 		!= (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
-		BNX2X_ERROR("BAD MCP validity signature\n");
+		BNX2X_ERR("BAD MCP validity signature\n");
 
 	bp->common.hw_config = SHMEM_RD(bp, dev_info.shared_hw_config.config);
 	BNX2X_DEV_INFO("hw_config 0x%08x\n", bp->common.hw_config);
@@ -6035,12 +7684,16 @@
 	if (val < BNX2X_BC_VER) {
 		/* for now only warn
 		 * later we might need to enforce this */
-		BNX2X_ERROR("This driver needs bc_ver %X but found %X, "
-			    "please upgrade BC\n", BNX2X_BC_VER, val);
+		BNX2X_ERR("This driver needs bc_ver %X but found %X, "
+			  "please upgrade BC\n", BNX2X_BC_VER, val);
 	}
 	bp->link_params.feature_config_flags |=
-		(val >= REQ_BC_VER_4_VRFY_OPT_MDL) ?
-		FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY : 0;
+				(val >= REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL) ?
+				FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY : 0;
+
+	bp->link_params.feature_config_flags |=
+		(val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ?
+		FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0;
 
 	if (BP_E1HVN(bp) == 0) {
 		pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc);
@@ -6061,404 +7714,348 @@
 		 val, val2, val3, val4);
 }
 
+#define IGU_FID(val)	GET_FIELD((val), IGU_REG_MAPPING_MEMORY_FID)
+#define IGU_VEC(val)	GET_FIELD((val), IGU_REG_MAPPING_MEMORY_VECTOR)
+
+static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
+{
+	int pfid = BP_FUNC(bp);
+	int vn = BP_E1HVN(bp);
+	int igu_sb_id;
+	u32 val;
+	u8 fid;
+
+	bp->igu_base_sb = 0xff;
+	bp->igu_sb_cnt = 0;
+	if (CHIP_INT_MODE_IS_BC(bp)) {
+		bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x,
+				       bp->l2_cid_count);
+
+		bp->igu_base_sb = (CHIP_MODE_IS_4_PORT(bp) ? pfid : vn) *
+			FP_SB_MAX_E1x;
+
+		bp->igu_dsb_id =  E1HVN_MAX * FP_SB_MAX_E1x +
+			(CHIP_MODE_IS_4_PORT(bp) ? pfid : vn);
+
+		return;
+	}
+
+	/* IGU in normal mode - read CAM */
+	for (igu_sb_id = 0; igu_sb_id < IGU_REG_MAPPING_MEMORY_SIZE;
+	     igu_sb_id++) {
+		val = REG_RD(bp, IGU_REG_MAPPING_MEMORY + igu_sb_id * 4);
+		if (!(val & IGU_REG_MAPPING_MEMORY_VALID))
+			continue;
+		fid = IGU_FID(val);
+		if ((fid & IGU_FID_ENCODE_IS_PF)) {
+			if ((fid & IGU_FID_PF_NUM_MASK) != pfid)
+				continue;
+			if (IGU_VEC(val) == 0)
+				/* default status block */
+				bp->igu_dsb_id = igu_sb_id;
+			else {
+				if (bp->igu_base_sb == 0xff)
+					bp->igu_base_sb = igu_sb_id;
+				bp->igu_sb_cnt++;
+			}
+		}
+	}
+	bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt, bp->l2_cid_count);
+	if (bp->igu_sb_cnt == 0)
+		BNX2X_ERR("CAM configuration error\n");
+}
+
 static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
 						    u32 switch_cfg)
 {
-	int port = BP_PORT(bp);
-	u32 ext_phy_type;
+	int cfg_size = 0, idx, port = BP_PORT(bp);
+
+	/* Aggregation of supported attributes of all external phys */
+	bp->port.supported[0] = 0;
+	bp->port.supported[1] = 0;
+	switch (bp->link_params.num_phys) {
+	case 1:
+		bp->port.supported[0] = bp->link_params.phy[INT_PHY].supported;
+		cfg_size = 1;
+		break;
+	case 2:
+		bp->port.supported[0] = bp->link_params.phy[EXT_PHY1].supported;
+		cfg_size = 1;
+		break;
+	case 3:
+		if (bp->link_params.multi_phy_config &
+		    PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
+			bp->port.supported[1] =
+				bp->link_params.phy[EXT_PHY1].supported;
+			bp->port.supported[0] =
+				bp->link_params.phy[EXT_PHY2].supported;
+		} else {
+			bp->port.supported[0] =
+				bp->link_params.phy[EXT_PHY1].supported;
+			bp->port.supported[1] =
+				bp->link_params.phy[EXT_PHY2].supported;
+		}
+		cfg_size = 2;
+		break;
+	}
+
+	if (!(bp->port.supported[0] || bp->port.supported[1])) {
+		BNX2X_ERR("NVRAM config error. BAD phy config."
+			  "PHY1 config 0x%x, PHY2 config 0x%x\n",
+			   SHMEM_RD(bp,
+			   dev_info.port_hw_config[port].external_phy_config),
+			   SHMEM_RD(bp,
+			   dev_info.port_hw_config[port].external_phy_config2));
+			return;
+	}
 
 	switch (switch_cfg) {
 	case SWITCH_CFG_1G:
-		BNX2X_DEV_INFO("switch_cfg 0x%x (1G)\n", switch_cfg);
-
-		ext_phy_type =
-			SERDES_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
-		switch (ext_phy_type) {
-		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
-			BNX2X_DEV_INFO("ext_phy_type 0x%x (Direct)\n",
-				       ext_phy_type);
-
-			bp->port.supported |= (SUPPORTED_10baseT_Half |
-					       SUPPORTED_10baseT_Full |
-					       SUPPORTED_100baseT_Half |
-					       SUPPORTED_100baseT_Full |
-					       SUPPORTED_1000baseT_Full |
-					       SUPPORTED_2500baseX_Full |
-					       SUPPORTED_TP |
-					       SUPPORTED_FIBRE |
-					       SUPPORTED_Autoneg |
-					       SUPPORTED_Pause |
-					       SUPPORTED_Asym_Pause);
-			break;
-
-		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
-			BNX2X_DEV_INFO("ext_phy_type 0x%x (5482)\n",
-				       ext_phy_type);
-
-			bp->port.supported |= (SUPPORTED_10baseT_Half |
-					       SUPPORTED_10baseT_Full |
-					       SUPPORTED_100baseT_Half |
-					       SUPPORTED_100baseT_Full |
-					       SUPPORTED_1000baseT_Full |
-					       SUPPORTED_TP |
-					       SUPPORTED_FIBRE |
-					       SUPPORTED_Autoneg |
-					       SUPPORTED_Pause |
-					       SUPPORTED_Asym_Pause);
-			break;
-
-		default:
-			BNX2X_ERR("NVRAM config error. "
-				  "BAD SerDes ext_phy_config 0x%x\n",
-				  bp->link_params.ext_phy_config);
-			return;
-		}
-
 		bp->port.phy_addr = REG_RD(bp, NIG_REG_SERDES0_CTRL_PHY_ADDR +
 					   port*0x10);
 		BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
 		break;
 
 	case SWITCH_CFG_10G:
-		BNX2X_DEV_INFO("switch_cfg 0x%x (10G)\n", switch_cfg);
-
-		ext_phy_type =
-			XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
-		switch (ext_phy_type) {
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-			BNX2X_DEV_INFO("ext_phy_type 0x%x (Direct)\n",
-				       ext_phy_type);
-
-			bp->port.supported |= (SUPPORTED_10baseT_Half |
-					       SUPPORTED_10baseT_Full |
-					       SUPPORTED_100baseT_Half |
-					       SUPPORTED_100baseT_Full |
-					       SUPPORTED_1000baseT_Full |
-					       SUPPORTED_2500baseX_Full |
-					       SUPPORTED_10000baseT_Full |
-					       SUPPORTED_TP |
-					       SUPPORTED_FIBRE |
-					       SUPPORTED_Autoneg |
-					       SUPPORTED_Pause |
-					       SUPPORTED_Asym_Pause);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
-			BNX2X_DEV_INFO("ext_phy_type 0x%x (8072)\n",
-				       ext_phy_type);
-
-			bp->port.supported |= (SUPPORTED_10000baseT_Full |
-					       SUPPORTED_1000baseT_Full |
-					       SUPPORTED_FIBRE |
-					       SUPPORTED_Autoneg |
-					       SUPPORTED_Pause |
-					       SUPPORTED_Asym_Pause);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
-			BNX2X_DEV_INFO("ext_phy_type 0x%x (8073)\n",
-				       ext_phy_type);
-
-			bp->port.supported |= (SUPPORTED_10000baseT_Full |
-					       SUPPORTED_2500baseX_Full |
-					       SUPPORTED_1000baseT_Full |
-					       SUPPORTED_FIBRE |
-					       SUPPORTED_Autoneg |
-					       SUPPORTED_Pause |
-					       SUPPORTED_Asym_Pause);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
-			BNX2X_DEV_INFO("ext_phy_type 0x%x (8705)\n",
-				       ext_phy_type);
-
-			bp->port.supported |= (SUPPORTED_10000baseT_Full |
-					       SUPPORTED_FIBRE |
-					       SUPPORTED_Pause |
-					       SUPPORTED_Asym_Pause);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
-			BNX2X_DEV_INFO("ext_phy_type 0x%x (8706)\n",
-				       ext_phy_type);
-
-			bp->port.supported |= (SUPPORTED_10000baseT_Full |
-					       SUPPORTED_1000baseT_Full |
-					       SUPPORTED_FIBRE |
-					       SUPPORTED_Pause |
-					       SUPPORTED_Asym_Pause);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-			BNX2X_DEV_INFO("ext_phy_type 0x%x (8726)\n",
-				       ext_phy_type);
-
-			bp->port.supported |= (SUPPORTED_10000baseT_Full |
-					       SUPPORTED_1000baseT_Full |
-					       SUPPORTED_Autoneg |
-					       SUPPORTED_FIBRE |
-					       SUPPORTED_Pause |
-					       SUPPORTED_Asym_Pause);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
-			BNX2X_DEV_INFO("ext_phy_type 0x%x (8727)\n",
-				       ext_phy_type);
-
-			bp->port.supported |= (SUPPORTED_10000baseT_Full |
-					       SUPPORTED_1000baseT_Full |
-					       SUPPORTED_Autoneg |
-					       SUPPORTED_FIBRE |
-					       SUPPORTED_Pause |
-					       SUPPORTED_Asym_Pause);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
-			BNX2X_DEV_INFO("ext_phy_type 0x%x (SFX7101)\n",
-				       ext_phy_type);
-
-			bp->port.supported |= (SUPPORTED_10000baseT_Full |
-					       SUPPORTED_TP |
-					       SUPPORTED_Autoneg |
-					       SUPPORTED_Pause |
-					       SUPPORTED_Asym_Pause);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
-			BNX2X_DEV_INFO("ext_phy_type 0x%x (BCM8481)\n",
-				       ext_phy_type);
-
-			bp->port.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);
-			break;
-
-		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
-			BNX2X_ERR("XGXS PHY Failure detected 0x%x\n",
-				  bp->link_params.ext_phy_config);
-			break;
-
-		default:
-			BNX2X_ERR("NVRAM config error. "
-				  "BAD XGXS ext_phy_config 0x%x\n",
-				  bp->link_params.ext_phy_config);
-			return;
-		}
-
 		bp->port.phy_addr = REG_RD(bp, NIG_REG_XGXS0_CTRL_PHY_ADDR +
 					   port*0x18);
 		BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
-
 		break;
 
 	default:
 		BNX2X_ERR("BAD switch_cfg link_config 0x%x\n",
-			  bp->port.link_config);
+			  bp->port.link_config[0]);
 		return;
 	}
-	bp->link_params.phy_addr = bp->port.phy_addr;
-
-	/* mask what we support according to speed_cap_mask */
-	if (!(bp->link_params.speed_cap_mask &
+	/* mask what we support according to speed_cap_mask per configuration */
+	for (idx = 0; idx < cfg_size; idx++) {
+		if (!(bp->link_params.speed_cap_mask[idx] &
 				PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF))
-		bp->port.supported &= ~SUPPORTED_10baseT_Half;
+			bp->port.supported[idx] &= ~SUPPORTED_10baseT_Half;
 
-	if (!(bp->link_params.speed_cap_mask &
+		if (!(bp->link_params.speed_cap_mask[idx] &
 				PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL))
-		bp->port.supported &= ~SUPPORTED_10baseT_Full;
+			bp->port.supported[idx] &= ~SUPPORTED_10baseT_Full;
 
-	if (!(bp->link_params.speed_cap_mask &
+		if (!(bp->link_params.speed_cap_mask[idx] &
 				PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF))
-		bp->port.supported &= ~SUPPORTED_100baseT_Half;
+			bp->port.supported[idx] &= ~SUPPORTED_100baseT_Half;
 
-	if (!(bp->link_params.speed_cap_mask &
+		if (!(bp->link_params.speed_cap_mask[idx] &
 				PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL))
-		bp->port.supported &= ~SUPPORTED_100baseT_Full;
+			bp->port.supported[idx] &= ~SUPPORTED_100baseT_Full;
 
-	if (!(bp->link_params.speed_cap_mask &
+		if (!(bp->link_params.speed_cap_mask[idx] &
 					PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))
-		bp->port.supported &= ~(SUPPORTED_1000baseT_Half |
-					SUPPORTED_1000baseT_Full);
+			bp->port.supported[idx] &= ~(SUPPORTED_1000baseT_Half |
+						     SUPPORTED_1000baseT_Full);
 
-	if (!(bp->link_params.speed_cap_mask &
+		if (!(bp->link_params.speed_cap_mask[idx] &
 					PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
-		bp->port.supported &= ~SUPPORTED_2500baseX_Full;
+			bp->port.supported[idx] &= ~SUPPORTED_2500baseX_Full;
 
-	if (!(bp->link_params.speed_cap_mask &
+		if (!(bp->link_params.speed_cap_mask[idx] &
 					PORT_HW_CFG_SPEED_CAPABILITY_D0_10G))
-		bp->port.supported &= ~SUPPORTED_10000baseT_Full;
+			bp->port.supported[idx] &= ~SUPPORTED_10000baseT_Full;
 
-	BNX2X_DEV_INFO("supported 0x%x\n", bp->port.supported);
+	}
+
+	BNX2X_DEV_INFO("supported 0x%x 0x%x\n", bp->port.supported[0],
+		       bp->port.supported[1]);
 }
 
 static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 {
-	bp->link_params.req_duplex = DUPLEX_FULL;
-
-	switch (bp->port.link_config & PORT_FEATURE_LINK_SPEED_MASK) {
-	case PORT_FEATURE_LINK_SPEED_AUTO:
-		if (bp->port.supported & SUPPORTED_Autoneg) {
-			bp->link_params.req_line_speed = SPEED_AUTO_NEG;
-			bp->port.advertising = bp->port.supported;
-		} else {
-			u32 ext_phy_type =
-			    XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
-
-			if ((ext_phy_type ==
-			     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
-			    (ext_phy_type ==
-			     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706)) {
-				/* force 10G, no AN */
-				bp->link_params.req_line_speed = SPEED_10000;
-				bp->port.advertising =
-						(ADVERTISED_10000baseT_Full |
-						 ADVERTISED_FIBRE);
-				break;
-			}
-			BNX2X_ERR("NVRAM config error. "
-				  "Invalid link_config 0x%x"
-				  "  Autoneg not supported\n",
-				  bp->port.link_config);
-			return;
-		}
+	u32 link_config, idx, cfg_size = 0;
+	bp->port.advertising[0] = 0;
+	bp->port.advertising[1] = 0;
+	switch (bp->link_params.num_phys) {
+	case 1:
+	case 2:
+		cfg_size = 1;
 		break;
-
-	case PORT_FEATURE_LINK_SPEED_10M_FULL:
-		if (bp->port.supported & SUPPORTED_10baseT_Full) {
-			bp->link_params.req_line_speed = SPEED_10;
-			bp->port.advertising = (ADVERTISED_10baseT_Full |
-						ADVERTISED_TP);
-		} else {
-			BNX2X_ERROR("NVRAM config error. "
-				    "Invalid link_config 0x%x"
-				    "  speed_cap_mask 0x%x\n",
-				    bp->port.link_config,
-				    bp->link_params.speed_cap_mask);
-			return;
-		}
-		break;
-
-	case PORT_FEATURE_LINK_SPEED_10M_HALF:
-		if (bp->port.supported & SUPPORTED_10baseT_Half) {
-			bp->link_params.req_line_speed = SPEED_10;
-			bp->link_params.req_duplex = DUPLEX_HALF;
-			bp->port.advertising = (ADVERTISED_10baseT_Half |
-						ADVERTISED_TP);
-		} else {
-			BNX2X_ERROR("NVRAM config error. "
-				    "Invalid link_config 0x%x"
-				    "  speed_cap_mask 0x%x\n",
-				    bp->port.link_config,
-				    bp->link_params.speed_cap_mask);
-			return;
-		}
-		break;
-
-	case PORT_FEATURE_LINK_SPEED_100M_FULL:
-		if (bp->port.supported & SUPPORTED_100baseT_Full) {
-			bp->link_params.req_line_speed = SPEED_100;
-			bp->port.advertising = (ADVERTISED_100baseT_Full |
-						ADVERTISED_TP);
-		} else {
-			BNX2X_ERROR("NVRAM config error. "
-				    "Invalid link_config 0x%x"
-				    "  speed_cap_mask 0x%x\n",
-				    bp->port.link_config,
-				    bp->link_params.speed_cap_mask);
-			return;
-		}
-		break;
-
-	case PORT_FEATURE_LINK_SPEED_100M_HALF:
-		if (bp->port.supported & SUPPORTED_100baseT_Half) {
-			bp->link_params.req_line_speed = SPEED_100;
-			bp->link_params.req_duplex = DUPLEX_HALF;
-			bp->port.advertising = (ADVERTISED_100baseT_Half |
-						ADVERTISED_TP);
-		} else {
-			BNX2X_ERROR("NVRAM config error. "
-				    "Invalid link_config 0x%x"
-				    "  speed_cap_mask 0x%x\n",
-				    bp->port.link_config,
-				    bp->link_params.speed_cap_mask);
-			return;
-		}
-		break;
-
-	case PORT_FEATURE_LINK_SPEED_1G:
-		if (bp->port.supported & SUPPORTED_1000baseT_Full) {
-			bp->link_params.req_line_speed = SPEED_1000;
-			bp->port.advertising = (ADVERTISED_1000baseT_Full |
-						ADVERTISED_TP);
-		} else {
-			BNX2X_ERROR("NVRAM config error. "
-				    "Invalid link_config 0x%x"
-				    "  speed_cap_mask 0x%x\n",
-				    bp->port.link_config,
-				    bp->link_params.speed_cap_mask);
-			return;
-		}
-		break;
-
-	case PORT_FEATURE_LINK_SPEED_2_5G:
-		if (bp->port.supported & SUPPORTED_2500baseX_Full) {
-			bp->link_params.req_line_speed = SPEED_2500;
-			bp->port.advertising = (ADVERTISED_2500baseX_Full |
-						ADVERTISED_TP);
-		} else {
-			BNX2X_ERROR("NVRAM config error. "
-				    "Invalid link_config 0x%x"
-				    "  speed_cap_mask 0x%x\n",
-				    bp->port.link_config,
-				    bp->link_params.speed_cap_mask);
-			return;
-		}
-		break;
-
-	case PORT_FEATURE_LINK_SPEED_10G_CX4:
-	case PORT_FEATURE_LINK_SPEED_10G_KX4:
-	case PORT_FEATURE_LINK_SPEED_10G_KR:
-		if (bp->port.supported & SUPPORTED_10000baseT_Full) {
-			bp->link_params.req_line_speed = SPEED_10000;
-			bp->port.advertising = (ADVERTISED_10000baseT_Full |
-						ADVERTISED_FIBRE);
-		} else {
-			BNX2X_ERROR("NVRAM config error. "
-				    "Invalid link_config 0x%x"
-				    "  speed_cap_mask 0x%x\n",
-				    bp->port.link_config,
-				    bp->link_params.speed_cap_mask);
-			return;
-		}
-		break;
-
-	default:
-		BNX2X_ERROR("NVRAM config error. "
-			    "BAD link speed link_config 0x%x\n",
-			    bp->port.link_config);
-		bp->link_params.req_line_speed = SPEED_AUTO_NEG;
-		bp->port.advertising = bp->port.supported;
+	case 3:
+		cfg_size = 2;
 		break;
 	}
+	for (idx = 0; idx < cfg_size; idx++) {
+		bp->link_params.req_duplex[idx] = DUPLEX_FULL;
+		link_config = bp->port.link_config[idx];
+		switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) {
+		case PORT_FEATURE_LINK_SPEED_AUTO:
+			if (bp->port.supported[idx] & SUPPORTED_Autoneg) {
+				bp->link_params.req_line_speed[idx] =
+					SPEED_AUTO_NEG;
+				bp->port.advertising[idx] |=
+					bp->port.supported[idx];
+			} else {
+				/* force 10G, no AN */
+				bp->link_params.req_line_speed[idx] =
+					SPEED_10000;
+				bp->port.advertising[idx] |=
+					(ADVERTISED_10000baseT_Full |
+					 ADVERTISED_FIBRE);
+				continue;
+			}
+			break;
 
-	bp->link_params.req_flow_ctrl = (bp->port.link_config &
+		case PORT_FEATURE_LINK_SPEED_10M_FULL:
+			if (bp->port.supported[idx] & SUPPORTED_10baseT_Full) {
+				bp->link_params.req_line_speed[idx] =
+					SPEED_10;
+				bp->port.advertising[idx] |=
+					(ADVERTISED_10baseT_Full |
+					 ADVERTISED_TP);
+			} else {
+				BNX2X_ERROR("NVRAM config error. "
+					    "Invalid link_config 0x%x"
+					    "  speed_cap_mask 0x%x\n",
+					    link_config,
+				    bp->link_params.speed_cap_mask[idx]);
+				return;
+			}
+			break;
+
+		case PORT_FEATURE_LINK_SPEED_10M_HALF:
+			if (bp->port.supported[idx] & SUPPORTED_10baseT_Half) {
+				bp->link_params.req_line_speed[idx] =
+					SPEED_10;
+				bp->link_params.req_duplex[idx] =
+					DUPLEX_HALF;
+				bp->port.advertising[idx] |=
+					(ADVERTISED_10baseT_Half |
+					 ADVERTISED_TP);
+			} else {
+				BNX2X_ERROR("NVRAM config error. "
+					    "Invalid link_config 0x%x"
+					    "  speed_cap_mask 0x%x\n",
+					    link_config,
+					  bp->link_params.speed_cap_mask[idx]);
+				return;
+			}
+			break;
+
+		case PORT_FEATURE_LINK_SPEED_100M_FULL:
+			if (bp->port.supported[idx] &
+			    SUPPORTED_100baseT_Full) {
+				bp->link_params.req_line_speed[idx] =
+					SPEED_100;
+				bp->port.advertising[idx] |=
+					(ADVERTISED_100baseT_Full |
+					 ADVERTISED_TP);
+			} else {
+				BNX2X_ERROR("NVRAM config error. "
+					    "Invalid link_config 0x%x"
+					    "  speed_cap_mask 0x%x\n",
+					    link_config,
+					  bp->link_params.speed_cap_mask[idx]);
+				return;
+			}
+			break;
+
+		case PORT_FEATURE_LINK_SPEED_100M_HALF:
+			if (bp->port.supported[idx] &
+			    SUPPORTED_100baseT_Half) {
+				bp->link_params.req_line_speed[idx] =
+								SPEED_100;
+				bp->link_params.req_duplex[idx] =
+								DUPLEX_HALF;
+				bp->port.advertising[idx] |=
+					(ADVERTISED_100baseT_Half |
+					 ADVERTISED_TP);
+			} else {
+				BNX2X_ERROR("NVRAM config error. "
+				    "Invalid link_config 0x%x"
+				    "  speed_cap_mask 0x%x\n",
+				    link_config,
+				    bp->link_params.speed_cap_mask[idx]);
+				return;
+			}
+			break;
+
+		case PORT_FEATURE_LINK_SPEED_1G:
+			if (bp->port.supported[idx] &
+			    SUPPORTED_1000baseT_Full) {
+				bp->link_params.req_line_speed[idx] =
+					SPEED_1000;
+				bp->port.advertising[idx] |=
+					(ADVERTISED_1000baseT_Full |
+					 ADVERTISED_TP);
+			} else {
+				BNX2X_ERROR("NVRAM config error. "
+				    "Invalid link_config 0x%x"
+				    "  speed_cap_mask 0x%x\n",
+				    link_config,
+				    bp->link_params.speed_cap_mask[idx]);
+				return;
+			}
+			break;
+
+		case PORT_FEATURE_LINK_SPEED_2_5G:
+			if (bp->port.supported[idx] &
+			    SUPPORTED_2500baseX_Full) {
+				bp->link_params.req_line_speed[idx] =
+					SPEED_2500;
+				bp->port.advertising[idx] |=
+					(ADVERTISED_2500baseX_Full |
+						ADVERTISED_TP);
+			} else {
+				BNX2X_ERROR("NVRAM config error. "
+				    "Invalid link_config 0x%x"
+				    "  speed_cap_mask 0x%x\n",
+				    link_config,
+				    bp->link_params.speed_cap_mask[idx]);
+				return;
+			}
+			break;
+
+		case PORT_FEATURE_LINK_SPEED_10G_CX4:
+		case PORT_FEATURE_LINK_SPEED_10G_KX4:
+		case PORT_FEATURE_LINK_SPEED_10G_KR:
+			if (bp->port.supported[idx] &
+			    SUPPORTED_10000baseT_Full) {
+				bp->link_params.req_line_speed[idx] =
+					SPEED_10000;
+				bp->port.advertising[idx] |=
+					(ADVERTISED_10000baseT_Full |
+						ADVERTISED_FIBRE);
+			} else {
+				BNX2X_ERROR("NVRAM config error. "
+				    "Invalid link_config 0x%x"
+				    "  speed_cap_mask 0x%x\n",
+				    link_config,
+				    bp->link_params.speed_cap_mask[idx]);
+				return;
+			}
+			break;
+
+		default:
+			BNX2X_ERROR("NVRAM config error. "
+				    "BAD link speed link_config 0x%x\n",
+					  link_config);
+				bp->link_params.req_line_speed[idx] =
+							SPEED_AUTO_NEG;
+				bp->port.advertising[idx] =
+						bp->port.supported[idx];
+			break;
+		}
+
+		bp->link_params.req_flow_ctrl[idx] = (link_config &
 					 PORT_FEATURE_FLOW_CONTROL_MASK);
-	if ((bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
-	    !(bp->port.supported & SUPPORTED_Autoneg))
-		bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+		if ((bp->link_params.req_flow_ctrl[idx] ==
+		     BNX2X_FLOW_CTRL_AUTO) &&
+		    !(bp->port.supported[idx] & SUPPORTED_Autoneg)) {
+			bp->link_params.req_flow_ctrl[idx] =
+				BNX2X_FLOW_CTRL_NONE;
+		}
 
-	BNX2X_DEV_INFO("req_line_speed %d  req_duplex %d  req_flow_ctrl 0x%x"
-		       "  advertising 0x%x\n",
-		       bp->link_params.req_line_speed,
-		       bp->link_params.req_duplex,
-		       bp->link_params.req_flow_ctrl, bp->port.advertising);
+		BNX2X_DEV_INFO("req_line_speed %d  req_duplex %d req_flow_ctrl"
+			       " 0x%x advertising 0x%x\n",
+			       bp->link_params.req_line_speed[idx],
+			       bp->link_params.req_duplex[idx],
+			       bp->link_params.req_flow_ctrl[idx],
+			       bp->port.advertising[idx]);
+	}
 }
 
 static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
@@ -6474,48 +8071,28 @@
 	int port = BP_PORT(bp);
 	u32 val, val2;
 	u32 config;
-	u16 i;
-	u32 ext_phy_type;
+	u32 ext_phy_type, ext_phy_config;;
 
 	bp->link_params.bp = bp;
 	bp->link_params.port = port;
 
 	bp->link_params.lane_config =
 		SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config);
-	bp->link_params.ext_phy_config =
-		SHMEM_RD(bp,
-			 dev_info.port_hw_config[port].external_phy_config);
-	/* BCM8727_NOC => BCM8727 no over current */
-	if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) ==
-	    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC) {
-		bp->link_params.ext_phy_config &=
-			~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
-		bp->link_params.ext_phy_config |=
-			PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727;
-		bp->link_params.feature_config_flags |=
-			FEATURE_CONFIG_BCM8727_NOC;
-	}
 
-	bp->link_params.speed_cap_mask =
+	bp->link_params.speed_cap_mask[0] =
 		SHMEM_RD(bp,
 			 dev_info.port_hw_config[port].speed_capability_mask);
-
-	bp->port.link_config =
+	bp->link_params.speed_cap_mask[1] =
+		SHMEM_RD(bp,
+			 dev_info.port_hw_config[port].speed_capability_mask2);
+	bp->port.link_config[0] =
 		SHMEM_RD(bp, dev_info.port_feature_config[port].link_config);
 
-	/* Get the 4 lanes xgxs config rx and tx */
-	for (i = 0; i < 2; i++) {
-		val = SHMEM_RD(bp,
-			   dev_info.port_hw_config[port].xgxs_config_rx[i<<1]);
-		bp->link_params.xgxs_config_rx[i << 1] = ((val>>16) & 0xffff);
-		bp->link_params.xgxs_config_rx[(i << 1) + 1] = (val & 0xffff);
+	bp->port.link_config[1] =
+		SHMEM_RD(bp, dev_info.port_feature_config[port].link_config2);
 
-		val = SHMEM_RD(bp,
-			   dev_info.port_hw_config[port].xgxs_config_tx[i<<1]);
-		bp->link_params.xgxs_config_tx[i << 1] = ((val>>16) & 0xffff);
-		bp->link_params.xgxs_config_tx[(i << 1) + 1] = (val & 0xffff);
-	}
-
+	bp->link_params.multi_phy_config =
+		SHMEM_RD(bp, dev_info.port_hw_config[port].multi_phy_config);
 	/* If the device is capable of WoL, set the default state according
 	 * to the HW
 	 */
@@ -6523,14 +8100,15 @@
 	bp->wol = (!(bp->flags & NO_WOL_FLAG) &&
 		   (config & PORT_FEATURE_WOL_ENABLED));
 
-	BNX2X_DEV_INFO("lane_config 0x%08x  ext_phy_config 0x%08x"
-		       "  speed_cap_mask 0x%08x  link_config 0x%08x\n",
+	BNX2X_DEV_INFO("lane_config 0x%08x  "
+		       "speed_cap_mask0 0x%08x  link_config0 0x%08x\n",
 		       bp->link_params.lane_config,
-		       bp->link_params.ext_phy_config,
-		       bp->link_params.speed_cap_mask, bp->port.link_config);
+		       bp->link_params.speed_cap_mask[0],
+		       bp->port.link_config[0]);
 
-	bp->link_params.switch_cfg |= (bp->port.link_config &
-				       PORT_FEATURE_CONNECTED_SWITCH_MASK);
+	bp->link_params.switch_cfg = (bp->port.link_config[0] &
+				      PORT_FEATURE_CONNECTED_SWITCH_MASK);
+	bnx2x_phy_probe(&bp->link_params);
 	bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg);
 
 	bnx2x_link_settings_requested(bp);
@@ -6539,14 +8117,17 @@
 	 * If connected directly, work with the internal PHY, otherwise, work
 	 * with the external PHY
 	 */
-	ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
+	ext_phy_config =
+		SHMEM_RD(bp,
+			 dev_info.port_hw_config[port].external_phy_config);
+	ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
 	if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
-		bp->mdio.prtad = bp->link_params.phy_addr;
+		bp->mdio.prtad = bp->port.phy_addr;
 
 	else if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
 		 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
 		bp->mdio.prtad =
-			XGXS_EXT_PHY_ADDR(bp->link_params.ext_phy_config);
+			XGXS_EXT_PHY_ADDR(ext_phy_config);
 
 	val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
 	val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
@@ -6563,41 +8144,74 @@
 
 static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
 {
-	int func = BP_FUNC(bp);
+	int func = BP_ABS_FUNC(bp);
+	int vn;
 	u32 val, val2;
 	int rc = 0;
 
 	bnx2x_get_common_hwinfo(bp);
 
-	bp->e1hov = 0;
-	bp->e1hmf = 0;
-	if (CHIP_IS_E1H(bp) && !BP_NOMCP(bp)) {
-		bp->mf_config =
-			SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
+	if (CHIP_IS_E1x(bp)) {
+		bp->common.int_block = INT_BLOCK_HC;
 
-		val = (SHMEM_RD(bp, mf_cfg.func_mf_config[FUNC_0].e1hov_tag) &
+		bp->igu_dsb_id = DEF_SB_IGU_ID;
+		bp->igu_base_sb = 0;
+		bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x, bp->l2_cid_count);
+	} else {
+		bp->common.int_block = INT_BLOCK_IGU;
+		val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
+		if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) {
+			DP(NETIF_MSG_PROBE, "IGU Backward Compatible Mode\n");
+			bp->common.int_block |= INT_BLOCK_MODE_BW_COMP;
+		} else
+			DP(NETIF_MSG_PROBE, "IGU Normal Mode\n");
+
+		bnx2x_get_igu_cam_info(bp);
+
+	}
+	DP(NETIF_MSG_PROBE, "igu_dsb_id %d  igu_base_sb %d  igu_sb_cnt %d\n",
+			     bp->igu_dsb_id, bp->igu_base_sb, bp->igu_sb_cnt);
+
+	/*
+	 * Initialize MF configuration
+	 */
+
+	bp->mf_ov = 0;
+	bp->mf_mode = 0;
+	vn = BP_E1HVN(bp);
+	if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) {
+		if (SHMEM2_HAS(bp, mf_cfg_addr))
+			bp->common.mf_cfg_base = SHMEM2_RD(bp, mf_cfg_addr);
+		else
+			bp->common.mf_cfg_base = bp->common.shmem_base +
+				offsetof(struct shmem_region, func_mb) +
+				E1H_FUNC_MAX * sizeof(struct drv_func_mb);
+		bp->mf_config[vn] =
+			MF_CFG_RD(bp, func_mf_config[func].config);
+
+		val = (MF_CFG_RD(bp, func_mf_config[FUNC_0].e1hov_tag) &
 		       FUNC_MF_CFG_E1HOV_TAG_MASK);
 		if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT)
-			bp->e1hmf = 1;
+			bp->mf_mode = 1;
 		BNX2X_DEV_INFO("%s function mode\n",
-			       IS_E1HMF(bp) ? "multi" : "single");
+			       IS_MF(bp) ? "multi" : "single");
 
-		if (IS_E1HMF(bp)) {
-			val = (SHMEM_RD(bp, mf_cfg.func_mf_config[func].
+		if (IS_MF(bp)) {
+			val = (MF_CFG_RD(bp, func_mf_config[func].
 								e1hov_tag) &
 			       FUNC_MF_CFG_E1HOV_TAG_MASK);
 			if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
-				bp->e1hov = val;
-				BNX2X_DEV_INFO("E1HOV for func %d is %d "
+				bp->mf_ov = val;
+				BNX2X_DEV_INFO("MF OV for func %d is %d "
 					       "(0x%04x)\n",
-					       func, bp->e1hov, bp->e1hov);
+					       func, bp->mf_ov, bp->mf_ov);
 			} else {
-				BNX2X_ERROR("No valid E1HOV for func %d,"
+				BNX2X_ERROR("No valid MF OV for func %d,"
 					    "  aborting\n", func);
 				rc = -EPERM;
 			}
 		} else {
-			if (BP_E1HVN(bp)) {
+			if (BP_VN(bp)) {
 				BNX2X_ERROR("VN %d in single function mode,"
 					    "  aborting\n", BP_E1HVN(bp));
 				rc = -EPERM;
@@ -6605,17 +8219,31 @@
 		}
 	}
 
+	/* adjust igu_sb_cnt to MF for E1x */
+	if (CHIP_IS_E1x(bp) && IS_MF(bp))
+		bp->igu_sb_cnt /= E1HVN_MAX;
+
+	/*
+	 * adjust E2 sb count: to be removed when FW will support
+	 * more then 16 L2 clients
+	 */
+#define MAX_L2_CLIENTS				16
+	if (CHIP_IS_E2(bp))
+		bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt,
+				       MAX_L2_CLIENTS / (IS_MF(bp) ? 4 : 1));
+
 	if (!BP_NOMCP(bp)) {
 		bnx2x_get_port_hwinfo(bp);
 
-		bp->fw_seq = (SHMEM_RD(bp, func_mb[func].drv_mb_header) &
-			      DRV_MSG_SEQ_NUMBER_MASK);
+		bp->fw_seq =
+			(SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
+			 DRV_MSG_SEQ_NUMBER_MASK);
 		BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
 	}
 
-	if (IS_E1HMF(bp)) {
-		val2 = SHMEM_RD(bp, mf_cfg.func_mf_config[func].mac_upper);
-		val = SHMEM_RD(bp,  mf_cfg.func_mf_config[func].mac_lower);
+	if (IS_MF(bp)) {
+		val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
+		val = MF_CFG_RD(bp,  func_mf_config[func].mac_lower);
 		if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
 		    (val != FUNC_MF_CFG_LOWERMAC_DEFAULT)) {
 			bp->dev->dev_addr[0] = (u8)(val2 >> 8 & 0xff);
@@ -6709,7 +8337,7 @@
 
 static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 {
-	int func = BP_FUNC(bp);
+	int func;
 	int timer_interval;
 	int rc;
 
@@ -6729,7 +8357,13 @@
 
 	rc = bnx2x_get_hwinfo(bp);
 
+	if (!rc)
+		rc = bnx2x_alloc_mem_bp(bp);
+
 	bnx2x_read_fwinfo(bp);
+
+	func = BP_FUNC(bp);
+
 	/* need to reset chip if undi was active */
 	if (!BP_NOMCP(bp))
 		bnx2x_undi_unload(bp);
@@ -6771,13 +8405,12 @@
 	bp->mrrs = mrrs;
 
 	bp->tx_ring_size = MAX_TX_AVAIL;
-	bp->rx_ring_size = MAX_RX_AVAIL;
 
 	bp->rx_csum = 1;
 
 	/* make sure that the numbers are in the right granularity */
-	bp->tx_ticks = (50 / (4 * BNX2X_BTR)) * (4 * BNX2X_BTR);
-	bp->rx_ticks = (25 / (4 * BNX2X_BTR)) * (4 * BNX2X_BTR);
+	bp->tx_ticks = (50 / BNX2X_BTR) * BNX2X_BTR;
+	bp->rx_ticks = (25 / BNX2X_BTR) * BNX2X_BTR;
 
 	timer_interval = (CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ);
 	bp->current_interval = (poll ? poll : timer_interval);
@@ -6869,81 +8502,22 @@
 
 	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)))
 		rx_mode = BNX2X_RX_MODE_ALLMULTI;
-
 	else { /* some multicasts */
 		if (CHIP_IS_E1(bp)) {
-			int i, old, offset;
-			struct netdev_hw_addr *ha;
-			struct mac_configuration_cmd *config =
-						bnx2x_sp(bp, mcast_config);
+			/*
+			 * 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));
 
-			i = 0;
-			netdev_for_each_mc_addr(ha, dev) {
-				config->config_table[i].
-					cam_entry.msb_mac_addr =
-					swab16(*(u16 *)&ha->addr[0]);
-				config->config_table[i].
-					cam_entry.middle_mac_addr =
-					swab16(*(u16 *)&ha->addr[2]);
-				config->config_table[i].
-					cam_entry.lsb_mac_addr =
-					swab16(*(u16 *)&ha->addr[4]);
-				config->config_table[i].cam_entry.flags =
-							cpu_to_le16(port);
-				config->config_table[i].
-					target_table_entry.flags = 0;
-				config->config_table[i].target_table_entry.
-					clients_bit_vector =
-						cpu_to_le32(1 << BP_L_ID(bp));
-				config->config_table[i].
-					target_table_entry.vlan_id = 0;
-
-				DP(NETIF_MSG_IFUP,
-				   "setting MCAST[%d] (%04x:%04x:%04x)\n", i,
-				   config->config_table[i].
-						cam_entry.msb_mac_addr,
-				   config->config_table[i].
-						cam_entry.middle_mac_addr,
-				   config->config_table[i].
-						cam_entry.lsb_mac_addr);
-				i++;
-			}
-			old = config->hdr.length;
-			if (old > i) {
-				for (; i < old; i++) {
-					if (CAM_IS_INVALID(config->
-							   config_table[i])) {
-						/* already invalidated */
-						break;
-					}
-					/* invalidate */
-					CAM_INVALIDATE(config->
-						       config_table[i]);
-				}
-			}
-
-			if (CHIP_REV_IS_SLOW(bp))
-				offset = BNX2X_MAX_EMUL_MULTI*(1 + port);
-			else
-				offset = BNX2X_MAX_MULTICAST*(1 + port);
-
-			config->hdr.length = i;
-			config->hdr.offset = offset;
-			config->hdr.client_id = bp->fp->cl_id;
-			config->hdr.reserved1 = 0;
-
-			bp->set_mac_pending++;
-			smp_wmb();
-
-			bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
-				   U64_HI(bnx2x_sp_mapping(bp, mcast_config)),
-				   U64_LO(bnx2x_sp_mapping(bp, mcast_config)),
-				      0);
+			bnx2x_set_e1_mc_list(bp, offset);
 		} else { /* E1H */
 			/* Accept one or more multicasts */
 			struct netdev_hw_addr *ha;
@@ -6955,9 +8529,10 @@
 
 			netdev_for_each_mc_addr(ha, dev) {
 				DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
-				   ha->addr);
+				   bnx2x_mc_addr(ha));
 
-				crc = crc32c_le(0, ha->addr, ETH_ALEN);
+				crc = crc32c_le(0, bnx2x_mc_addr(ha),
+						ETH_ALEN);
 				bit = (crc >> 24) & 0xff;
 				regidx = bit >> 5;
 				bit &= 0x1f;
@@ -6974,7 +8549,6 @@
 	bnx2x_set_storm_rx_mode(bp);
 }
 
-
 /* called with rtnl_lock */
 static int bnx2x_mdio_read(struct net_device *netdev, int prtad,
 			   int devad, u16 addr)
@@ -6982,23 +8556,15 @@
 	struct bnx2x *bp = netdev_priv(netdev);
 	u16 value;
 	int rc;
-	u32 phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
 
 	DP(NETIF_MSG_LINK, "mdio_read: prtad 0x%x, devad 0x%x, addr 0x%x\n",
 	   prtad, devad, addr);
 
-	if (prtad != bp->mdio.prtad) {
-		DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
-		   prtad, bp->mdio.prtad);
-		return -EINVAL;
-	}
-
 	/* The HW expects different devad if CL22 is used */
 	devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
 
 	bnx2x_acquire_phy_lock(bp);
-	rc = bnx2x_cl45_read(bp, BP_PORT(bp), phy_type, prtad,
-			     devad, addr, &value);
+	rc = bnx2x_phy_read(&bp->link_params, prtad, devad, addr, &value);
 	bnx2x_release_phy_lock(bp);
 	DP(NETIF_MSG_LINK, "mdio_read_val 0x%x rc = 0x%x\n", value, rc);
 
@@ -7012,24 +8578,16 @@
 			    u16 addr, u16 value)
 {
 	struct bnx2x *bp = netdev_priv(netdev);
-	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
 	int rc;
 
 	DP(NETIF_MSG_LINK, "mdio_write: prtad 0x%x, devad 0x%x, addr 0x%x,"
 			   " value 0x%x\n", prtad, devad, addr, value);
 
-	if (prtad != bp->mdio.prtad) {
-		DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
-		   prtad, bp->mdio.prtad);
-		return -EINVAL;
-	}
-
 	/* The HW expects different devad if CL22 is used */
 	devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
 
 	bnx2x_acquire_phy_lock(bp);
-	rc = bnx2x_cl45_write(bp, BP_PORT(bp), ext_phy_type, prtad,
-			      devad, addr, value);
+	rc = bnx2x_phy_write(&bp->link_params, prtad, devad, addr, value);
 	bnx2x_release_phy_lock(bp);
 	return rc;
 }
@@ -7070,9 +8628,6 @@
 	.ndo_do_ioctl		= bnx2x_ioctl,
 	.ndo_change_mtu		= bnx2x_change_mtu,
 	.ndo_tx_timeout		= bnx2x_tx_timeout,
-#ifdef BCM_VLAN
-	.ndo_vlan_rx_register	= bnx2x_vlan_rx_register,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= poll_bnx2x,
 #endif
@@ -7090,7 +8645,7 @@
 	bp->dev = dev;
 	bp->pdev = pdev;
 	bp->flags = 0;
-	bp->func = PCI_FUNC(pdev->devfn);
+	bp->pf_num = PCI_FUNC(pdev->devfn);
 
 	rc = pci_enable_device(pdev);
 	if (rc) {
@@ -7172,7 +8727,7 @@
 	}
 
 	bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
-					min_t(u64, BNX2X_DB_SIZE,
+					min_t(u64, BNX2X_DB_SIZE(bp),
 					      pci_resource_len(pdev, 2)));
 	if (!bp->doorbells) {
 		dev_err(&bp->pdev->dev,
@@ -7204,9 +8759,7 @@
 		dev->features |= NETIF_F_HIGHDMA;
 	dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
 	dev->features |= NETIF_F_TSO6;
-#ifdef BCM_VLAN
 	dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
-	bp->flags |= (HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
 
 	dev->vlan_features |= NETIF_F_SG;
 	dev->vlan_features |= NETIF_F_HW_CSUM;
@@ -7214,7 +8767,6 @@
 		dev->vlan_features |= NETIF_F_HIGHDMA;
 	dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
 	dev->vlan_features |= NETIF_F_TSO6;
-#endif
 
 	/* get_port_hwinfo() will set prtad and mmds properly */
 	bp->mdio.prtad = MDIO_PRTAD_NONE;
@@ -7259,7 +8811,7 @@
 	*speed = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT;
 }
 
-static int __devinit bnx2x_check_firmware(struct bnx2x *bp)
+static int bnx2x_check_firmware(struct bnx2x *bp)
 {
 	const struct firmware *firmware = bp->firmware;
 	struct bnx2x_fw_file_hdr *fw_hdr;
@@ -7348,6 +8900,30 @@
 	}
 }
 
+/**
+ * IRO array is stored in the following format:
+ * {base(24bit), m1(16bit), m2(16bit), m3(16bit), size(16bit) }
+ */
+static inline void bnx2x_prep_iro(const u8 *_source, u8 *_target, u32 n)
+{
+	const __be32 *source = (const __be32 *)_source;
+	struct iro *target = (struct iro *)_target;
+	u32 i, j, tmp;
+
+	for (i = 0, j = 0; i < n/sizeof(struct iro); i++) {
+		target[i].base = be32_to_cpu(source[j]);
+		j++;
+		tmp = be32_to_cpu(source[j]);
+		target[i].m1 = (tmp >> 16) & 0xffff;
+		target[i].m2 = tmp & 0xffff;
+		j++;
+		tmp = be32_to_cpu(source[j]);
+		target[i].m3 = (tmp >> 16) & 0xffff;
+		target[i].size = tmp & 0xffff;
+		j++;
+	}
+}
+
 static inline void be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
 {
 	const __be16 *source = (const __be16 *)_source;
@@ -7370,7 +8946,7 @@
 	     (u8 *)bp->arr, len);					\
 } while (0)
 
-static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev)
+int bnx2x_init_firmware(struct bnx2x *bp)
 {
 	const char *fw_file_name;
 	struct bnx2x_fw_file_hdr *fw_hdr;
@@ -7380,22 +8956,24 @@
 		fw_file_name = FW_FILE_NAME_E1;
 	else if (CHIP_IS_E1H(bp))
 		fw_file_name = FW_FILE_NAME_E1H;
+	else if (CHIP_IS_E2(bp))
+		fw_file_name = FW_FILE_NAME_E2;
 	else {
-		dev_err(dev, "Unsupported chip revision\n");
+		BNX2X_ERR("Unsupported chip revision\n");
 		return -EINVAL;
 	}
 
-	dev_info(dev, "Loading %s\n", fw_file_name);
+	BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
 
-	rc = request_firmware(&bp->firmware, fw_file_name, dev);
+	rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev);
 	if (rc) {
-		dev_err(dev, "Can't load firmware file %s\n", fw_file_name);
+		BNX2X_ERR("Can't load firmware file %s\n", fw_file_name);
 		goto request_firmware_exit;
 	}
 
 	rc = bnx2x_check_firmware(bp);
 	if (rc) {
-		dev_err(dev, "Corrupt firmware file %s\n", fw_file_name);
+		BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
 		goto request_firmware_exit;
 	}
 
@@ -7429,9 +9007,13 @@
 			be32_to_cpu(fw_hdr->csem_int_table_data.offset);
 	INIT_CSEM_PRAM_DATA(bp)      = bp->firmware->data +
 			be32_to_cpu(fw_hdr->csem_pram_data.offset);
+	/* IRO */
+	BNX2X_ALLOC_AND_SET(iro_arr, iro_alloc_err, bnx2x_prep_iro);
 
 	return 0;
 
+iro_alloc_err:
+	kfree(bp->init_ops_offsets);
 init_offsets_alloc_err:
 	kfree(bp->init_ops);
 init_ops_alloc_err:
@@ -7442,6 +9024,15 @@
 	return rc;
 }
 
+static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp, int l2_cid_count)
+{
+	int cid_count = L2_FP_COUNT(l2_cid_count);
+
+#ifdef BCM_CNIC
+	cid_count += CNIC_CID_MAX;
+#endif
+	return roundup(cid_count, QM_CID_ROUND);
+}
 
 static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 				    const struct pci_device_id *ent)
@@ -7449,10 +9040,30 @@
 	struct net_device *dev = NULL;
 	struct bnx2x *bp;
 	int pcie_width, pcie_speed;
-	int rc;
+	int rc, cid_count;
+
+	switch (ent->driver_data) {
+	case BCM57710:
+	case BCM57711:
+	case BCM57711E:
+		cid_count = FP_SB_MAX_E1x;
+		break;
+
+	case BCM57712:
+	case BCM57712E:
+		cid_count = FP_SB_MAX_E2;
+		break;
+
+	default:
+		pr_err("Unknown board_type (%ld), aborting\n",
+			   ent->driver_data);
+		return ENODEV;
+	}
+
+	cid_count += CNIC_CONTEXT_USE;
 
 	/* dev zeroed in init_etherdev */
-	dev = alloc_etherdev_mq(sizeof(*bp), MAX_CONTEXT);
+	dev = alloc_etherdev_mq(sizeof(*bp), cid_count);
 	if (!dev) {
 		dev_err(&pdev->dev, "Cannot allocate net device\n");
 		return -ENOMEM;
@@ -7463,6 +9074,8 @@
 
 	pci_set_drvdata(pdev, dev);
 
+	bp->l2_cid_count = cid_count;
+
 	rc = bnx2x_init_dev(pdev, dev);
 	if (rc < 0) {
 		free_netdev(dev);
@@ -7473,12 +9086,8 @@
 	if (rc)
 		goto init_one_exit;
 
-	/* Set init arrays */
-	rc = bnx2x_init_firmware(bp, &pdev->dev);
-	if (rc) {
-		dev_err(&pdev->dev, "Error loading firmware\n");
-		goto init_one_exit;
-	}
+	/* calc qm_cid_count */
+	bp->qm_cid_count = bnx2x_set_qm_cid_count(bp, cid_count);
 
 	rc = register_netdev(dev);
 	if (rc) {
@@ -7486,11 +9095,23 @@
 		goto init_one_exit;
 	}
 
+	/* Configure interupt mode: try to enable MSI-X/MSI if
+	 * needed, set bp->num_queues appropriately.
+	 */
+	bnx2x_set_int_mode(bp);
+
+	/* Add all NAPI objects */
+	bnx2x_add_all_napi(bp);
+
 	bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
+
 	netdev_info(dev, "%s (%c%d) PCI-E x%d %s found at mem %lx,"
 	       " IRQ %d, ", board_info[ent->driver_data].name,
 	       (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
-	       pcie_width, (pcie_speed == 2) ? "5GHz (Gen2)" : "2.5GHz",
+	       pcie_width,
+	       ((!CHIP_IS_E2(bp) && pcie_speed == 2) ||
+		 (CHIP_IS_E2(bp) && pcie_speed == 1)) ?
+						"5GHz (Gen2)" : "2.5GHz",
 	       dev->base_addr, bp->pdev->irq);
 	pr_cont("node addr %pM\n", dev->dev_addr);
 
@@ -7527,20 +9148,23 @@
 
 	unregister_netdev(dev);
 
+	/* Delete all NAPI objects */
+	bnx2x_del_all_napi(bp);
+
+	/* Disable MSI/MSI-X */
+	bnx2x_disable_msi(bp);
+
 	/* Make sure RESET task is not scheduled before continuing */
 	cancel_delayed_work_sync(&bp->reset_task);
 
-	kfree(bp->init_ops_offsets);
-	kfree(bp->init_ops);
-	kfree(bp->init_data);
-	release_firmware(bp->firmware);
-
 	if (bp->regview)
 		iounmap(bp->regview);
 
 	if (bp->doorbells)
 		iounmap(bp->doorbells);
 
+	bnx2x_free_mem_bp(bp);
+
 	free_netdev(dev);
 
 	if (atomic_read(&pdev->enable_cnt) == 1)
@@ -7566,22 +9190,14 @@
 	DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
 
 	/* Release IRQs */
-	bnx2x_free_irq(bp, false);
-
-	if (CHIP_IS_E1(bp)) {
-		struct mac_configuration_cmd *config =
-						bnx2x_sp(bp, mcast_config);
-
-		for (i = 0; i < config->hdr.length; i++)
-			CAM_INVALIDATE(config->config_table[i]);
-	}
+	bnx2x_free_irq(bp);
 
 	/* Free SKBs, SGEs, TPA pool and driver internals */
 	bnx2x_free_skbs(bp);
+
 	for_each_queue(bp, i)
 		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
-	for_each_queue(bp, i)
-		netif_napi_del(&bnx2x_fp(bp, i, napi));
+
 	bnx2x_free_mem(bp);
 
 	bp->state = BNX2X_STATE_CLOSED;
@@ -7613,8 +9229,9 @@
 		BNX2X_ERR("BAD MCP validity signature\n");
 
 	if (!BP_NOMCP(bp)) {
-		bp->fw_seq = (SHMEM_RD(bp, func_mb[BP_FUNC(bp)].drv_mb_header)
-			      & DRV_MSG_SEQ_NUMBER_MASK);
+		bp->fw_seq =
+		    (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
+		    DRV_MSG_SEQ_NUMBER_MASK);
 		BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
 	}
 }
@@ -7697,7 +9314,8 @@
 	struct bnx2x *bp = netdev_priv(dev);
 
 	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-		printk(KERN_ERR "Handling parity error recovery. Try again later\n");
+		printk(KERN_ERR "Handling parity error recovery. "
+				"Try again later\n");
 		return;
 	}
 
@@ -7772,19 +9390,53 @@
 #endif
 
 	spin_lock_bh(&bp->spq_lock);
+	BUG_ON(bp->cnic_spq_pending < count);
 	bp->cnic_spq_pending -= count;
 
-	for (; bp->cnic_spq_pending < bp->cnic_eth_dev.max_kwqe_pending;
-	     bp->cnic_spq_pending++) {
 
-		if (!bp->cnic_kwq_pending)
+	for (; bp->cnic_kwq_pending; bp->cnic_kwq_pending--) {
+		u16 type =  (le16_to_cpu(bp->cnic_kwq_cons->hdr.type)
+				& SPE_HDR_CONN_TYPE) >>
+				SPE_HDR_CONN_TYPE_SHIFT;
+
+		/* Set validation for iSCSI L2 client before sending SETUP
+		 *  ramrod
+		 */
+		if (type == ETH_CONNECTION_TYPE) {
+			u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons->
+					     hdr.conn_and_cmd_data) >>
+				SPE_HDR_CMD_ID_SHIFT) & 0xff;
+
+			if (cmd == RAMROD_CMD_ID_ETH_CLIENT_SETUP)
+				bnx2x_set_ctx_validation(&bp->context.
+						vcxt[BNX2X_ISCSI_ETH_CID].eth,
+					HW_CID(bp, BNX2X_ISCSI_ETH_CID));
+		}
+
+		/* There may be not more than 8 L2 and COMMON SPEs and not more
+		 * than 8 L5 SPEs in the air.
+		 */
+		if ((type == NONE_CONNECTION_TYPE) ||
+		    (type == ETH_CONNECTION_TYPE)) {
+			if (!atomic_read(&bp->spq_left))
+				break;
+			else
+				atomic_dec(&bp->spq_left);
+		} else if (type == ISCSI_CONNECTION_TYPE) {
+			if (bp->cnic_spq_pending >=
+			    bp->cnic_eth_dev.max_kwqe_pending)
+				break;
+			else
+				bp->cnic_spq_pending++;
+		} else {
+			BNX2X_ERR("Unknown SPE type: %d\n", type);
+			bnx2x_panic();
 			break;
+		}
 
 		spe = bnx2x_sp_get_next(bp);
 		*spe = *bp->cnic_kwq_cons;
 
-		bp->cnic_kwq_pending--;
-
 		DP(NETIF_MSG_TIMER, "pending on SPQ %d, on KWQ %d count %d\n",
 		   bp->cnic_spq_pending, bp->cnic_kwq_pending, count);
 
@@ -7822,8 +9474,8 @@
 
 		DP(NETIF_MSG_TIMER, "L5 SPQE %x %x %x:%x pos %d\n",
 		   spe->hdr.conn_and_cmd_data, spe->hdr.type,
-		   spe->data.mac_config_addr.hi,
-		   spe->data.mac_config_addr.lo,
+		   spe->data.update_data_addr.hi,
+		   spe->data.update_data_addr.lo,
 		   bp->cnic_kwq_pending);
 
 		if (bp->cnic_kwq_prod == bp->cnic_kwq_last)
@@ -7889,7 +9541,7 @@
 	ctl.data.comp.cid = cid;
 
 	bnx2x_cnic_ctl_send_bh(bp, &ctl);
-	bnx2x_cnic_sp_post(bp, 1);
+	bnx2x_cnic_sp_post(bp, 0);
 }
 
 static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
@@ -7906,8 +9558,8 @@
 		break;
 	}
 
-	case DRV_CTL_COMPLETION_CMD: {
-		int count = ctl->data.comp.comp_count;
+	case DRV_CTL_RET_L5_SPQ_CREDIT_CMD: {
+		int count = ctl->data.credit.credit_count;
 
 		bnx2x_cnic_sp_post(bp, count);
 		break;
@@ -7917,8 +9569,24 @@
 	case DRV_CTL_START_L2_CMD: {
 		u32 cli = ctl->data.ring.client_id;
 
-		bp->rx_mode_cl_mask |= (1 << cli);
-		bnx2x_set_storm_rx_mode(bp);
+		/* Set iSCSI MAC address */
+		bnx2x_set_iscsi_eth_mac_addr(bp, 1);
+
+		mmiowb();
+		barrier();
+
+		/* Start accepting on iSCSI L2 ring. Accept all multicasts
+		 * because it's the only way for UIO Client to accept
+		 * multicasts (in non-promiscuous mode only one Client per
+		 * function will receive multicast packets (leading in our
+		 * case).
+		 */
+		bnx2x_rxq_set_mac_filters(bp, cli,
+			BNX2X_ACCEPT_UNICAST |
+			BNX2X_ACCEPT_BROADCAST |
+			BNX2X_ACCEPT_ALL_MULTICAST);
+		storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+
 		break;
 	}
 
@@ -7926,8 +9594,23 @@
 	case DRV_CTL_STOP_L2_CMD: {
 		u32 cli = ctl->data.ring.client_id;
 
-		bp->rx_mode_cl_mask &= ~(1 << cli);
-		bnx2x_set_storm_rx_mode(bp);
+		/* Stop accepting on iSCSI L2 ring */
+		bnx2x_rxq_set_mac_filters(bp, cli, BNX2X_ACCEPT_NONE);
+		storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+
+		mmiowb();
+		barrier();
+
+		/* Unset iSCSI L2 MAC */
+		bnx2x_set_iscsi_eth_mac_addr(bp, 0);
+		break;
+	}
+	case DRV_CTL_RET_L2_SPQ_CREDIT_CMD: {
+		int count = ctl->data.credit.credit_count;
+
+		smp_mb__before_atomic_inc();
+		atomic_add(count, &bp->spq_left);
+		smp_mb__after_atomic_inc();
 		break;
 	}
 
@@ -7951,10 +9634,16 @@
 		cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX;
 		cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX;
 	}
-	cp->irq_arr[0].status_blk = bp->cnic_sb;
+	if (CHIP_IS_E2(bp))
+		cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e2_sb;
+	else
+		cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e1x_sb;
+
 	cp->irq_arr[0].status_blk_num = CNIC_SB_ID(bp);
+	cp->irq_arr[0].status_blk_num2 = CNIC_IGU_SB_ID(bp);
 	cp->irq_arr[1].status_blk = bp->def_status_blk;
 	cp->irq_arr[1].status_blk_num = DEF_SB_ID;
+	cp->irq_arr[1].status_blk_num2 = DEF_SB_IGU_ID;
 
 	cp->num_irq = 2;
 }
@@ -7986,12 +9675,10 @@
 
 	cp->num_irq = 0;
 	cp->drv_state = CNIC_DRV_STATE_REGD;
-
-	bnx2x_init_sb(bp, bp->cnic_sb, bp->cnic_sb_mapping, CNIC_SB_ID(bp));
+	cp->iro_arr = bp->iro_arr;
 
 	bnx2x_setup_cnic_irq_info(bp);
-	bnx2x_set_iscsi_eth_mac_addr(bp, 1);
-	bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET;
+
 	rcu_assign_pointer(bp->cnic_ops, ops);
 
 	return 0;
@@ -8028,15 +9715,24 @@
 	cp->io_base = bp->regview;
 	cp->io_base2 = bp->doorbells;
 	cp->max_kwqe_pending = 8;
-	cp->ctx_blk_size = CNIC_CTX_PER_ILT * sizeof(union cdu_context);
-	cp->ctx_tbl_offset = FUNC_ILT_BASE(BP_FUNC(bp)) + 1;
+	cp->ctx_blk_size = CDU_ILT_PAGE_SZ;
+	cp->ctx_tbl_offset = FUNC_ILT_BASE(BP_FUNC(bp)) +
+			     bnx2x_cid_ilt_lines(bp);
 	cp->ctx_tbl_len = CNIC_ILT_LINES;
-	cp->starting_cid = BCM_CNIC_CID_START;
+	cp->starting_cid = bnx2x_cid_ilt_lines(bp) * ILT_PAGE_CIDS;
 	cp->drv_submit_kwqes_16 = bnx2x_cnic_sp_queue;
 	cp->drv_ctl = bnx2x_drv_ctl;
 	cp->drv_register_cnic = bnx2x_register_cnic;
 	cp->drv_unregister_cnic = bnx2x_unregister_cnic;
+	cp->iscsi_l2_client_id = BNX2X_ISCSI_ETH_CL_ID;
+	cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID;
 
+	DP(BNX2X_MSG_SP, "page_size %d, tbl_offset %d, tbl_lines %d, "
+			 "starting cid %d\n",
+	   cp->ctx_blk_size,
+	   cp->ctx_tbl_offset,
+	   cp->ctx_tbl_len,
+	   cp->starting_cid);
 	return cp;
 }
 EXPORT_SYMBOL(bnx2x_cnic_probe);
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h
index a1f3bf0..1cefe48 100644
--- a/drivers/net/bnx2x/bnx2x_reg.h
+++ b/drivers/net/bnx2x/bnx2x_reg.h
@@ -1,6 +1,6 @@
 /* bnx2x_reg.h: Broadcom Everest network driver.
  *
- * Copyright (c) 2007-2009 Broadcom Corporation
+ * Copyright (c) 2007-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
@@ -19,7 +19,20 @@
  *
  */
 
-
+#define ATC_ATC_INT_STS_REG_ADDRESS_ERROR			 (0x1<<0)
+#define ATC_ATC_INT_STS_REG_ATC_GPA_MULTIPLE_HITS		 (0x1<<2)
+#define ATC_ATC_INT_STS_REG_ATC_IREQ_LESS_THAN_STU		 (0x1<<5)
+#define ATC_ATC_INT_STS_REG_ATC_RCPL_TO_EMPTY_CNT		 (0x1<<3)
+#define ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR			 (0x1<<4)
+#define ATC_ATC_INT_STS_REG_ATC_TCPL_TO_NOT_PEND		 (0x1<<1)
+/* [RW 1] Initiate the ATC array - reset all the valid bits */
+#define ATC_REG_ATC_INIT_ARRAY					 0x1100b8
+/* [R 1] ATC initalization done */
+#define ATC_REG_ATC_INIT_DONE					 0x1100bc
+/* [RC 6] Interrupt register #0 read clear */
+#define ATC_REG_ATC_INT_STS_CLR				 0x1101c0
+/* [RW 19] Interrupt mask register #0 read/write */
+#define BRB1_REG_BRB1_INT_MASK					 0x60128
 /* [R 19] Interrupt register #0 read */
 #define BRB1_REG_BRB1_INT_STS					 0x6011c
 /* [RW 4] Parity mask register #0 read/write */
@@ -27,9 +40,31 @@
 /* [R 4] Parity register #0 read */
 #define BRB1_REG_BRB1_PRTY_STS					 0x6012c
 /* [RW 10] At address BRB1_IND_FREE_LIST_PRS_CRDT initialize free head. At
-   address BRB1_IND_FREE_LIST_PRS_CRDT+1 initialize free tail. At address
-   BRB1_IND_FREE_LIST_PRS_CRDT+2 initialize parser initial credit. */
+ * address BRB1_IND_FREE_LIST_PRS_CRDT+1 initialize free tail. At address
+ * BRB1_IND_FREE_LIST_PRS_CRDT+2 initialize parser initial credit. Warning -
+ * following reset the first rbc access to this reg must be write; there can
+ * be no more rbc writes after the first one; there can be any number of rbc
+ * read following the first write; rbc access not following these rules will
+ * result in hang condition. */
 #define BRB1_REG_FREE_LIST_PRS_CRDT				 0x60200
+/* [RW 10] The number of free blocks below which the full signal to class 0
+ * is asserted */
+#define BRB1_REG_FULL_0_XOFF_THRESHOLD_0			 0x601d0
+/* [RW 10] The number of free blocks above which the full signal to class 0
+ * is de-asserted */
+#define BRB1_REG_FULL_0_XON_THRESHOLD_0				 0x601d4
+/* [RW 10] The number of free blocks below which the full signal to class 1
+ * is asserted */
+#define BRB1_REG_FULL_1_XOFF_THRESHOLD_0			 0x601d8
+/* [RW 10] The number of free blocks above which the full signal to class 1
+ * is de-asserted */
+#define BRB1_REG_FULL_1_XON_THRESHOLD_0				 0x601dc
+/* [RW 10] The number of free blocks below which the full signal to the LB
+ * port is asserted */
+#define BRB1_REG_FULL_LB_XOFF_THRESHOLD				 0x601e0
+/* [RW 10] The number of free blocks above which the full signal to the LB
+ * port is de-asserted */
+#define BRB1_REG_FULL_LB_XON_THRESHOLD				 0x601e4
 /* [RW 10] The number of free blocks above which the High_llfc signal to
    interface #n is de-asserted. */
 #define BRB1_REG_HIGH_LLFC_HIGH_THRESHOLD_0			 0x6014c
@@ -44,6 +79,9 @@
 /* [RW 10] The number of free blocks below which the Low_llfc signal to
    interface #n is asserted. */
 #define BRB1_REG_LOW_LLFC_LOW_THRESHOLD_0			 0x6015c
+/* [RW 10] The number of blocks guarantied for the MAC port */
+#define BRB1_REG_MAC_GUARANTIED_0				 0x601e8
+#define BRB1_REG_MAC_GUARANTIED_1				 0x60240
 /* [R 24] The number of full blocks. */
 #define BRB1_REG_NUM_OF_FULL_BLOCKS				 0x60090
 /* [ST 32] The number of cycles that the write_full signal towards MAC #0
@@ -55,7 +93,19 @@
    asserted. */
 #define BRB1_REG_NUM_OF_PAUSE_CYCLES_0				 0x600b8
 #define BRB1_REG_NUM_OF_PAUSE_CYCLES_1				 0x600bc
-/* [RW 10] Write client 0: De-assert pause threshold. */
+/* [RW 10] The number of free blocks below which the pause signal to class 0
+ * is asserted */
+#define BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0			 0x601c0
+/* [RW 10] The number of free blocks above which the pause signal to class 0
+ * is de-asserted */
+#define BRB1_REG_PAUSE_0_XON_THRESHOLD_0			 0x601c4
+/* [RW 10] The number of free blocks below which the pause signal to class 1
+ * is asserted */
+#define BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0			 0x601c8
+/* [RW 10] The number of free blocks above which the pause signal to class 1
+ * is de-asserted */
+#define BRB1_REG_PAUSE_1_XON_THRESHOLD_0			 0x601cc
+/* [RW 10] Write client 0: De-assert pause threshold. Not Functional */
 #define BRB1_REG_PAUSE_HIGH_THRESHOLD_0 			 0x60078
 #define BRB1_REG_PAUSE_HIGH_THRESHOLD_1 			 0x6007c
 /* [RW 10] Write client 0: Assert pause threshold. */
@@ -362,6 +412,7 @@
 #define CFC_REG_NUM_LCIDS_ARRIVING				 0x104004
 /* [R 9] Number of Leaving LCIDs in Link List Block */
 #define CFC_REG_NUM_LCIDS_LEAVING				 0x104018
+#define CFC_REG_WEAK_ENABLE_PF					 0x104124
 /* [RW 8] The event id for aggregated interrupt 0 */
 #define CSDM_REG_AGG_INT_EVENT_0				 0xc2038
 #define CSDM_REG_AGG_INT_EVENT_10				 0xc2060
@@ -590,10 +641,17 @@
 #define CSEM_REG_TS_8_AS					 0x200058
 /* [RW 3] The arbitration scheme of time_slot 9 */
 #define CSEM_REG_TS_9_AS					 0x20005c
+/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
+ * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
+#define CSEM_REG_VFPF_ERR_NUM					 0x200380
 /* [RW 1] Parity mask register #0 read/write */
 #define DBG_REG_DBG_PRTY_MASK					 0xc0a8
 /* [R 1] Parity register #0 read */
 #define DBG_REG_DBG_PRTY_STS					 0xc09c
+/* [RW 1] When set the DMAE will process the commands as in E1.5. 1.The
+ * function that is used is always SRC-PCI; 2.VF_Valid = 0; 3.VFID=0;
+ * 4.Completion function=0; 5.Error handling=0 */
+#define DMAE_REG_BACKWARD_COMP_EN				 0x10207c
 /* [RW 32] Commands memory. The address to command X; row Y is to calculated
    as 14*X+Y. */
 #define DMAE_REG_CMD_MEM					 0x102400
@@ -742,9 +800,13 @@
 #define HC_REG_HC_PRTY_MASK					 0x1080a0
 /* [R 3] Parity register #0 read */
 #define HC_REG_HC_PRTY_STS					 0x108094
-#define HC_REG_INT_MASK 					 0x108108
+/* [RC 3] Parity register #0 read clear */
+#define HC_REG_HC_PRTY_STS_CLR					 0x108098
+#define HC_REG_INT_MASK						 0x108108
 #define HC_REG_LEADING_EDGE_0					 0x108040
 #define HC_REG_LEADING_EDGE_1					 0x108048
+#define HC_REG_MAIN_MEMORY					 0x108800
+#define HC_REG_MAIN_MEMORY_SIZE					 152
 #define HC_REG_P0_PROD_CONS					 0x108200
 #define HC_REG_P1_PROD_CONS					 0x108400
 #define HC_REG_PBA_COMMAND					 0x108140
@@ -758,6 +820,92 @@
 #define HC_REG_USTORM_ADDR_FOR_COALESCE 			 0x108068
 #define HC_REG_VQID_0						 0x108008
 #define HC_REG_VQID_1						 0x10800c
+#define IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN		 (0x1<<1)
+#define IGU_REG_ATTENTION_ACK_BITS				 0x130108
+/* [R 4] Debug: attn_fsm */
+#define IGU_REG_ATTN_FSM					 0x130054
+#define IGU_REG_ATTN_MSG_ADDR_H				 0x13011c
+#define IGU_REG_ATTN_MSG_ADDR_L				 0x130120
+/* [R 4] Debug: [3] - attention write done message is pending (0-no pending;
+ * 1-pending). [2:0] = PFID. Pending means attention message was sent; but
+ * write done didnt receive. */
+#define IGU_REG_ATTN_WRITE_DONE_PENDING			 0x130030
+#define IGU_REG_BLOCK_CONFIGURATION				 0x130000
+#define IGU_REG_COMMAND_REG_32LSB_DATA				 0x130124
+#define IGU_REG_COMMAND_REG_CTRL				 0x13012c
+/* [WB_R 32] Cleanup bit status per SB. 1 = cleanup is set. 0 = cleanup bit
+ * is clear. The bits in this registers are set and clear via the producer
+ * command. Data valid only in addresses 0-4. all the rest are zero. */
+#define IGU_REG_CSTORM_TYPE_0_SB_CLEANUP			 0x130200
+/* [R 5] Debug: ctrl_fsm */
+#define IGU_REG_CTRL_FSM					 0x130064
+/* [R 1] data availble for error memory. If this bit is clear do not red
+ * from error_handling_memory. */
+#define IGU_REG_ERROR_HANDLING_DATA_VALID			 0x130130
+/* [R 11] Parity register #0 read */
+#define IGU_REG_IGU_PRTY_STS					 0x13009c
+/* [R 4] Debug: int_handle_fsm */
+#define IGU_REG_INT_HANDLE_FSM					 0x130050
+#define IGU_REG_LEADING_EDGE_LATCH				 0x130134
+/* [RW 14] mapping CAM; relevant for E2 operating mode only. [0] - valid.
+ * [6:1] - vector number; [13:7] - FID (if VF - [13] = 0; [12:7] = VF
+ * number; if PF - [13] = 1; [12:10] = 0; [9:7] = PF number); */
+#define IGU_REG_MAPPING_MEMORY					 0x131000
+#define IGU_REG_MAPPING_MEMORY_SIZE				 136
+#define IGU_REG_PBA_STATUS_LSB					 0x130138
+#define IGU_REG_PBA_STATUS_MSB					 0x13013c
+#define IGU_REG_PCI_PF_MSI_EN					 0x130140
+#define IGU_REG_PCI_PF_MSIX_EN					 0x130144
+#define IGU_REG_PCI_PF_MSIX_FUNC_MASK				 0x130148
+/* [WB_R 32] Each bit represent the pending bits status for that SB. 0 = no
+ * pending; 1 = pending. Pendings means interrupt was asserted; and write
+ * done was not received. Data valid only in addresses 0-4. all the rest are
+ * zero. */
+#define IGU_REG_PENDING_BITS_STATUS				 0x130300
+#define IGU_REG_PF_CONFIGURATION				 0x130154
+/* [RW 20] producers only. E2 mode: address 0-135 match to the mapping
+ * memory; 136 - PF0 default prod; 137 PF1 default prod; 138 - PF2 default
+ * prod; 139 PF3 default prod; 140 - PF0 - ATTN prod; 141 - PF1 - ATTN prod;
+ * 142 - PF2 - ATTN prod; 143 - PF3 - ATTN prod; 144-147 reserved. E1.5 mode
+ * - In backward compatible mode; for non default SB; each even line in the
+ * memory holds the U producer and each odd line hold the C producer. The
+ * first 128 producer are for NDSB (PF0 - 0-31; PF1 - 32-63 and so on). The
+ * last 20 producers are for the DSB for each PF. each PF has five segments
+ * (the order inside each segment is PF0; PF1; PF2; PF3) - 128-131 U prods;
+ * 132-135 C prods; 136-139 X prods; 140-143 T prods; 144-147 ATTN prods; */
+#define IGU_REG_PROD_CONS_MEMORY				 0x132000
+/* [R 3] Debug: pxp_arb_fsm */
+#define IGU_REG_PXP_ARB_FSM					 0x130068
+/* [RW 6] Write one for each bit will reset the appropriate memory. When the
+ * memory reset finished the appropriate bit will be clear. Bit 0 - mapping
+ * memory; Bit 1 - SB memory; Bit 2 - SB interrupt and mask register; Bit 3
+ * - MSIX memory; Bit 4 - PBA memory; Bit 5 - statistics; */
+#define IGU_REG_RESET_MEMORIES					 0x130158
+/* [R 4] Debug: sb_ctrl_fsm */
+#define IGU_REG_SB_CTRL_FSM					 0x13004c
+#define IGU_REG_SB_INT_BEFORE_MASK_LSB				 0x13015c
+#define IGU_REG_SB_INT_BEFORE_MASK_MSB				 0x130160
+#define IGU_REG_SB_MASK_LSB					 0x130164
+#define IGU_REG_SB_MASK_MSB					 0x130168
+/* [RW 16] Number of command that were dropped without causing an interrupt
+ * due to: read access for WO BAR address; or write access for RO BAR
+ * address or any access for reserved address or PCI function error is set
+ * and address is not MSIX; PBA or cleanup */
+#define IGU_REG_SILENT_DROP					 0x13016c
+/* [RW 10] Number of MSI/MSIX/ATTN messages sent for the function: 0-63 -
+ * number of MSIX messages per VF; 64-67 - number of MSI/MSIX messages per
+ * PF; 68-71 number of ATTN messages per PF */
+#define IGU_REG_STATISTIC_NUM_MESSAGE_SENT			 0x130800
+/* [RW 32] Number of cycles the timer mask masking the IGU interrupt when a
+ * timer mask command arrives. Value must be bigger than 100. */
+#define IGU_REG_TIMER_MASKING_VALUE				 0x13003c
+#define IGU_REG_TRAILING_EDGE_LATCH				 0x130104
+#define IGU_REG_VF_CONFIGURATION				 0x130170
+/* [WB_R 32] Each bit represent write done pending bits status for that SB
+ * (MSI/MSIX message was sent and write done was not received yet). 0 =
+ * clear; 1 = set. Data valid only in addresses 0-4. all the rest are zero. */
+#define IGU_REG_WRITE_DONE_PENDING				 0x130480
+#define MCP_A_REG_MCPR_SCRATCH					 0x3a0000
 #define MCP_REG_MCPR_NVM_ACCESS_ENABLE				 0x86424
 #define MCP_REG_MCPR_NVM_ADDR					 0x8640c
 #define MCP_REG_MCPR_NVM_CFG4					 0x8642c
@@ -880,6 +1028,11 @@
    rom_parity; [29] MCP Latched ump_rx_parity; [30] MCP Latched
    ump_tx_parity; [31] MCP Latched scpad_parity; */
 #define MISC_REG_AEU_AFTER_INVERT_4_MCP 			 0xa458
+/* [R 32] Read fifth 32 bit after inversion of function 0. Mapped as
+ * follows: [0] PGLUE config_space; [1] PGLUE misc_flr; [2] PGLUE B RBC
+ * attention [3] PGLUE B RBC parity; [4] ATC attention; [5] ATC parity; [6]
+ * CNIG attention (reserved); [7] CNIG parity (reserved); [31-8] Reserved; */
+#define MISC_REG_AEU_AFTER_INVERT_5_FUNC_0			 0xa700
 /* [W 14] write to this register results with the clear of the latched
    signals; one in d0 clears RBCR latch; one in d1 clears RBCT latch; one in
    d2 clears RBCN latch; one in d3 clears RBCU latch; one in d4 clears RBCP
@@ -1251,6 +1404,7 @@
 #define MISC_REG_E1HMF_MODE					 0xa5f8
 /* [RW 32] Debug only: spare RW register reset by core reset */
 #define MISC_REG_GENERIC_CR_0					 0xa460
+#define MISC_REG_GENERIC_CR_1					 0xa464
 /* [RW 32] Debug only: spare RW register reset by por reset */
 #define MISC_REG_GENERIC_POR_1					 0xa474
 /* [RW 32] GPIO. [31-28] FLOAT port 0; [27-24] FLOAT port 0; When any of
@@ -1373,6 +1527,14 @@
 #define MISC_REG_PLL_STORM_CTRL_2				 0xa298
 #define MISC_REG_PLL_STORM_CTRL_3				 0xa29c
 #define MISC_REG_PLL_STORM_CTRL_4				 0xa2a0
+/* [R 1] Status of 4 port mode enable input pin. */
+#define MISC_REG_PORT4MODE_EN					 0xa750
+/* [RW 2] 4 port mode enable overwrite.[0] - Overwrite control; if it is 0 -
+ * the port4mode_en output is equal to 4 port mode input pin; if it is 1 -
+ * the port4mode_en output is equal to bit[1] of this register; [1] -
+ * Overwrite value. If bit[0] of this register is 1 this is the value that
+ * receives the port4mode_en output . */
+#define MISC_REG_PORT4MODE_EN_OVWR				 0xa720
 /* [RW 32] reset reg#2; rite/read one = the specific block is out of reset;
    write/read zero = the specific block is in reset; addr 0-wr- the write
    value will be written to the register; addr 1-set - one will be written
@@ -1656,8 +1818,91 @@
 /* [R 32] Interrupt register #0 read */
 #define NIG_REG_NIG_INT_STS_0					 0x103b0
 #define NIG_REG_NIG_INT_STS_1					 0x103c0
-/* [R 32] Parity register #0 read */
+/* [R 32] Legacy E1 and E1H location for parity error status register. */
 #define NIG_REG_NIG_PRTY_STS					 0x103d0
+/* [R 32] Parity register #0 read */
+#define NIG_REG_NIG_PRTY_STS_0					 0x183bc
+#define NIG_REG_NIG_PRTY_STS_1					 0x183cc
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header. */
+#define NIG_REG_P0_HDRS_AFTER_BASIC				 0x18038
+/* [RW 1] HW PFC enable bit. Set this bit to enable the PFC functionality in
+ * the NIG. Other flow control modes such as PAUSE and SAFC/LLFC should be
+ * disabled when this bit is set. */
+#define NIG_REG_P0_HWPFC_ENABLE				 0x18078
+#define NIG_REG_P0_LLH_FUNC_MEM2				 0x18480
+#define NIG_REG_P0_LLH_FUNC_MEM2_ENABLE			 0x18440
+/* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
+ * future expansion) each priorty is to be mapped to. Bits 3:0 specify the
+ * COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
+ * priority field is extracted from the outer-most VLAN in receive packet.
+ * Only COS 0 and COS 1 are supported in E2. */
+#define NIG_REG_P0_PKT_PRIORITY_TO_COS				 0x18054
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 0. A
+ * priority is mapped to COS 0 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS0_PRIORITY_MASK			 0x18058
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 1. A
+ * priority is mapped to COS 1 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS1_PRIORITY_MASK			 0x1805c
+/* [RW 15] Specify which of the credit registers the client is to be mapped
+ * to. Bits[2:0] are for client 0; bits [14:12] are for client 4. For
+ * clients that are not subject to WFQ credit blocking - their
+ * specifications here are not used. */
+#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP			 0x180f0
+/* [RW 5] Specify whether the client competes directly in the strict
+ * priority arbiter. The bits are mapped according to client ID (client IDs
+ * are defined in tx_arb_priority_client). Default value is set to enable
+ * strict priorities for clients 0-2 -- management and debug traffic. */
+#define NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT			 0x180e8
+/* [RW 5] Specify whether the client is subject to WFQ credit blocking. The
+ * bits are mapped according to client ID (client IDs are defined in
+ * tx_arb_priority_client). Default value is 0 for not using WFQ credit
+ * blocking. */
+#define NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ		 0x180ec
+/* [RW 32] Specify the upper bound that credit register 0 is allowed to
+ * reach. */
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0			 0x1810c
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1			 0x18110
+/* [RW 32] Specify the weight (in bytes) to be added to credit register 0
+ * when it is time to increment. */
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0			 0x180f8
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1			 0x180fc
+/* [RW 12] Specify the number of strict priority arbitration slots between
+ * two round-robin arbitration slots to avoid starvation. A value of 0 means
+ * no strict priority cycles - the strict priority with anti-starvation
+ * arbiter becomes a round-robin arbiter. */
+#define NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS			 0x180f4
+/* [RW 15] Specify the client number to be assigned to each priority of the
+ * strict priority arbiter. Priority 0 is the highest priority. Bits [2:0]
+ * are for priority 0 client; bits [14:12] are for priority 4 client. The
+ * clients are assigned the following IDs: 0-management; 1-debug traffic
+ * from this port; 2-debug traffic from other port; 3-COS0 traffic; 4-COS1
+ * traffic. The reset value[14:0] is set to 0x4688 (15'b100_011_010_001_000)
+ * for management at priority 0; debug traffic at priorities 1 and 2; COS0
+ * traffic at priority 3; and COS1 traffic at priority 4. */
+#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT			 0x180e4
+#define NIG_REG_P1_LLH_FUNC_MEM2				 0x184c0
+#define NIG_REG_P1_LLH_FUNC_MEM2_ENABLE			 0x18460
+/* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
+ * future expansion) each priorty is to be mapped to. Bits 3:0 specify the
+ * COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
+ * priority field is extracted from the outer-most VLAN in receive packet.
+ * Only COS 0 and COS 1 are supported in E2. */
+#define NIG_REG_P1_PKT_PRIORITY_TO_COS				 0x181a8
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 0. A
+ * priority is mapped to COS 0 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P1_RX_COS0_PRIORITY_MASK			 0x181ac
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 1. A
+ * priority is mapped to COS 1 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P1_RX_COS1_PRIORITY_MASK			 0x181b0
 /* [RW 1] Pause enable for port0. This register may get 1 only when
    ~safc_enable.safc_enable = 0 and ppp_enable.ppp_enable =0 for the same
    port */
@@ -1742,6 +1987,10 @@
 /* [RW 1] Disable processing further tasks from port 4 (after ending the
    current task in process). */
 #define PBF_REG_DISABLE_NEW_TASK_PROC_P4			 0x14006c
+#define PBF_REG_DISABLE_PF					 0x1402e8
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header. */
+#define PBF_REG_HDRS_AFTER_BASIC				 0x15c0a8
 #define PBF_REG_IF_ENABLE_REG					 0x140044
 /* [RW 1] Init bit. When set the initial credits are copied to the credit
    registers (except the port credits). Should be set and then reset after
@@ -1765,6 +2014,8 @@
 #define PBF_REG_MAC_IF1_ENABLE					 0x140034
 /* [RW 1] Enable for the loopback interface. */
 #define PBF_REG_MAC_LB_ENABLE					 0x140040
+/* [RW 6] Bit-map indicating which headers must appear in the packet */
+#define PBF_REG_MUST_HAVE_HDRS					 0x15c0c4
 /* [RW 10] Port 0 threshold used by arbiter in 16 byte lines used when pause
    not suppoterd. */
 #define PBF_REG_P0_ARB_THRSH					 0x1400e4
@@ -1804,6 +2055,259 @@
 #define PB_REG_PB_PRTY_MASK					 0x38
 /* [R 4] Parity register #0 read */
 #define PB_REG_PB_PRTY_STS					 0x2c
+#define PGLUE_B_PGLUE_B_INT_STS_REG_ADDRESS_ERROR		 (0x1<<0)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_CSSNOOP_FIFO_OVERFLOW	 (0x1<<8)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_INCORRECT_RCV_BEHAVIOR	 (0x1<<1)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_ERROR_ATTN		 (0x1<<6)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_IN_TWO_RCBS_ATTN	 (0x1<<7)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_VF_GRC_SPACE_VIOLATION_ATTN  (0x1<<4)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_VF_LENGTH_VIOLATION_ATTN	 (0x1<<3)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_VF_MSIX_BAR_VIOLATION_ATTN	 (0x1<<5)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN		 (0x1<<2)
+/* [R 8] Config space A attention dirty bits. Each bit indicates that the
+ * corresponding PF generates config space A attention. Set by PXP. Reset by
+ * MCP writing 1 to icfg_space_a_request_clr. Note: register contains bits
+ * from both paths. */
+#define PGLUE_B_REG_CFG_SPACE_A_REQUEST			 0x9010
+/* [R 8] Config space B attention dirty bits. Each bit indicates that the
+ * corresponding PF generates config space B attention. Set by PXP. Reset by
+ * MCP writing 1 to icfg_space_b_request_clr. Note: register contains bits
+ * from both paths. */
+#define PGLUE_B_REG_CFG_SPACE_B_REQUEST			 0x9014
+/* [RW 1] Type A PF enable inbound interrupt table for CSDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_CSDM_INB_INT_A_PF_ENABLE			 0x9194
+/* [RW 18] Type B VF inbound interrupt table for CSDM: bits[17:9]-mask;
+ * its[8:0]-address. Bits [1:0] must be zero (DW resolution address). */
+#define PGLUE_B_REG_CSDM_INB_INT_B_VF				 0x916c
+/* [RW 1] Type B VF enable inbound interrupt table for CSDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_CSDM_INB_INT_B_VF_ENABLE			 0x919c
+/* [RW 16] Start offset of CSDM zone A (queue zone) in the internal RAM */
+#define PGLUE_B_REG_CSDM_START_OFFSET_A			 0x9100
+/* [RW 16] Start offset of CSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_CSDM_START_OFFSET_B			 0x9108
+/* [RW 5] VF Shift of CSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_CSDM_VF_SHIFT_B				 0x9110
+/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
+#define PGLUE_B_REG_CSDM_ZONE_A_SIZE_PF			 0x91ac
+/* [R 8] FLR request attention dirty bits for PFs 0 to 7. Each bit indicates
+ * that the FLR register of the corresponding PF was set. Set by PXP. Reset
+ * by MCP writing 1 to flr_request_pf_7_0_clr. Note: register contains bits
+ * from both paths. */
+#define PGLUE_B_REG_FLR_REQUEST_PF_7_0				 0x9028
+/* [W 8] FLR request attention dirty bits clear for PFs 0 to 7. MCP writes 1
+ * to a bit in this register in order to clear the corresponding bit in
+ * flr_request_pf_7_0 register. Note: register contains bits from both
+ * paths. */
+#define PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR			 0x9418
+/* [R 32] FLR request attention dirty bits for VFs 96 to 127. Each bit
+ * indicates that the FLR register of the corresponding VF was set. Set by
+ * PXP. Reset by MCP writing 1 to flr_request_vf_127_96_clr. */
+#define PGLUE_B_REG_FLR_REQUEST_VF_127_96			 0x9024
+/* [R 32] FLR request attention dirty bits for VFs 0 to 31. Each bit
+ * indicates that the FLR register of the corresponding VF was set. Set by
+ * PXP. Reset by MCP writing 1 to flr_request_vf_31_0_clr. */
+#define PGLUE_B_REG_FLR_REQUEST_VF_31_0			 0x9018
+/* [R 32] FLR request attention dirty bits for VFs 32 to 63. Each bit
+ * indicates that the FLR register of the corresponding VF was set. Set by
+ * PXP. Reset by MCP writing 1 to flr_request_vf_63_32_clr. */
+#define PGLUE_B_REG_FLR_REQUEST_VF_63_32			 0x901c
+/* [R 32] FLR request attention dirty bits for VFs 64 to 95. Each bit
+ * indicates that the FLR register of the corresponding VF was set. Set by
+ * PXP. Reset by MCP writing 1 to flr_request_vf_95_64_clr. */
+#define PGLUE_B_REG_FLR_REQUEST_VF_95_64			 0x9020
+/* [R 8] Each bit indicates an incorrect behavior in user RX interface. Bit
+ * 0 - Target memory read arrived with a correctable error. Bit 1 - Target
+ * memory read arrived with an uncorrectable error. Bit 2 - Configuration RW
+ * arrived with a correctable error. Bit 3 - Configuration RW arrived with
+ * an uncorrectable error. Bit 4 - Completion with Configuration Request
+ * Retry Status. Bit 5 - Expansion ROM access received with a write request.
+ * Bit 6 - Completion with pcie_rx_err of 0000; CMPL_STATUS of non-zero; and
+ * pcie_rx_last not asserted. Bit 7 - Completion with pcie_rx_err of 1010;
+ * and pcie_rx_last not asserted. */
+#define PGLUE_B_REG_INCORRECT_RCV_DETAILS			 0x9068
+#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER		 0x942c
+#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ		 0x9430
+#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_WRITE		 0x9434
+#define PGLUE_B_REG_INTERNAL_VFID_ENABLE			 0x9438
+/* [R 9] Interrupt register #0 read */
+#define PGLUE_B_REG_PGLUE_B_INT_STS				 0x9298
+/* [RC 9] Interrupt register #0 read clear */
+#define PGLUE_B_REG_PGLUE_B_INT_STS_CLR			 0x929c
+/* [R 2] Parity register #0 read */
+#define PGLUE_B_REG_PGLUE_B_PRTY_STS				 0x92a8
+/* [R 13] Details of first request received with error. [2:0] - PFID. [3] -
+ * VF_VALID. [9:4] - VFID. [11:10] - Error Code - 0 - Indicates Completion
+ * Timeout of a User Tx non-posted request. 1 - unsupported request. 2 -
+ * completer abort. 3 - Illegal value for this field. [12] valid - indicates
+ * if there was a completion error since the last time this register was
+ * cleared. */
+#define PGLUE_B_REG_RX_ERR_DETAILS				 0x9080
+/* [R 18] Details of first ATS Translation Completion request received with
+ * error. [2:0] - PFID. [3] - VF_VALID. [9:4] - VFID. [11:10] - Error Code -
+ * 0 - Indicates Completion Timeout of a User Tx non-posted request. 1 -
+ * unsupported request. 2 - completer abort. 3 - Illegal value for this
+ * field. [16:12] - ATC OTB EntryID. [17] valid - indicates if there was a
+ * completion error since the last time this register was cleared. */
+#define PGLUE_B_REG_RX_TCPL_ERR_DETAILS			 0x9084
+/* [W 8] Debug only - Shadow BME bits clear for PFs 0 to 7. MCP writes 1 to
+ * a bit in this register in order to clear the corresponding bit in
+ * shadow_bme_pf_7_0 register. MCP should never use this unless a
+ * work-around is needed. Note: register contains bits from both paths. */
+#define PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR			 0x9458
+/* [R 8] SR IOV disabled attention dirty bits. Each bit indicates that the
+ * VF enable register of the corresponding PF is written to 0 and was
+ * previously 1. Set by PXP. Reset by MCP writing 1 to
+ * sr_iov_disabled_request_clr. Note: register contains bits from both
+ * paths. */
+#define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST			 0x9030
+/* [R 32] Indicates the status of tags 32-63. 0 - tags is used - read
+ * completion did not return yet. 1 - tag is unused. Same functionality as
+ * pxp2_registers_pgl_exp_rom_data2 for tags 0-31. */
+#define PGLUE_B_REG_TAGS_63_32					 0x9244
+/* [RW 1] Type A PF enable inbound interrupt table for TSDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_TSDM_INB_INT_A_PF_ENABLE			 0x9170
+/* [RW 16] Start offset of TSDM zone A (queue zone) in the internal RAM */
+#define PGLUE_B_REG_TSDM_START_OFFSET_A			 0x90c4
+/* [RW 16] Start offset of TSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_TSDM_START_OFFSET_B			 0x90cc
+/* [RW 5] VF Shift of TSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_TSDM_VF_SHIFT_B				 0x90d4
+/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
+#define PGLUE_B_REG_TSDM_ZONE_A_SIZE_PF			 0x91a0
+/* [R 32] Address [31:0] of first read request not submitted due to error */
+#define PGLUE_B_REG_TX_ERR_RD_ADD_31_0				 0x9098
+/* [R 32] Address [63:32] of first read request not submitted due to error */
+#define PGLUE_B_REG_TX_ERR_RD_ADD_63_32			 0x909c
+/* [R 31] Details of first read request not submitted due to error. [4:0]
+ * VQID. [5] TREQ. 1 - Indicates the request is a Translation Request.
+ * [20:8] - Length in bytes. [23:21] - PFID. [24] - VF_VALID. [30:25] -
+ * VFID. */
+#define PGLUE_B_REG_TX_ERR_RD_DETAILS				 0x90a0
+/* [R 26] Details of first read request not submitted due to error. [15:0]
+ * Request ID. [19:16] client ID. [20] - last SR. [24:21] - Error type -
+ * [21] - Indicates was_error was set; [22] - Indicates BME was cleared;
+ * [23] - Indicates FID_enable was cleared; [24] - Indicates VF with parent
+ * PF FLR_request or IOV_disable_request dirty bit is set. [25] valid -
+ * indicates if there was a request not submitted due to error since the
+ * last time this register was cleared. */
+#define PGLUE_B_REG_TX_ERR_RD_DETAILS2				 0x90a4
+/* [R 32] Address [31:0] of first write request not submitted due to error */
+#define PGLUE_B_REG_TX_ERR_WR_ADD_31_0				 0x9088
+/* [R 32] Address [63:32] of first write request not submitted due to error */
+#define PGLUE_B_REG_TX_ERR_WR_ADD_63_32			 0x908c
+/* [R 31] Details of first write request not submitted due to error. [4:0]
+ * VQID. [20:8] - Length in bytes. [23:21] - PFID. [24] - VF_VALID. [30:25]
+ * - VFID. */
+#define PGLUE_B_REG_TX_ERR_WR_DETAILS				 0x9090
+/* [R 26] Details of first write request not submitted due to error. [15:0]
+ * Request ID. [19:16] client ID. [20] - last SR. [24:21] - Error type -
+ * [21] - Indicates was_error was set; [22] - Indicates BME was cleared;
+ * [23] - Indicates FID_enable was cleared; [24] - Indicates VF with parent
+ * PF FLR_request or IOV_disable_request dirty bit is set. [25] valid -
+ * indicates if there was a request not submitted due to error since the
+ * last time this register was cleared. */
+#define PGLUE_B_REG_TX_ERR_WR_DETAILS2				 0x9094
+/* [RW 10] Type A PF/VF inbound interrupt table for USDM: bits[9:5]-mask;
+ * its[4:0]-address relative to start_offset_a. Bits [1:0] can have any
+ * value (Byte resolution address). */
+#define PGLUE_B_REG_USDM_INB_INT_A_0				 0x9128
+#define PGLUE_B_REG_USDM_INB_INT_A_1				 0x912c
+#define PGLUE_B_REG_USDM_INB_INT_A_2				 0x9130
+#define PGLUE_B_REG_USDM_INB_INT_A_3				 0x9134
+#define PGLUE_B_REG_USDM_INB_INT_A_4				 0x9138
+#define PGLUE_B_REG_USDM_INB_INT_A_5				 0x913c
+#define PGLUE_B_REG_USDM_INB_INT_A_6				 0x9140
+/* [RW 1] Type A PF enable inbound interrupt table for USDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_USDM_INB_INT_A_PF_ENABLE			 0x917c
+/* [RW 1] Type A VF enable inbound interrupt table for USDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_USDM_INB_INT_A_VF_ENABLE			 0x9180
+/* [RW 1] Type B VF enable inbound interrupt table for USDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_USDM_INB_INT_B_VF_ENABLE			 0x9184
+/* [RW 16] Start offset of USDM zone A (queue zone) in the internal RAM */
+#define PGLUE_B_REG_USDM_START_OFFSET_A			 0x90d8
+/* [RW 16] Start offset of USDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_USDM_START_OFFSET_B			 0x90e0
+/* [RW 5] VF Shift of USDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_USDM_VF_SHIFT_B				 0x90e8
+/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
+#define PGLUE_B_REG_USDM_ZONE_A_SIZE_PF			 0x91a4
+/* [R 26] Details of first target VF request accessing VF GRC space that
+ * failed permission check. [14:0] Address. [15] w_nr: 0 - Read; 1 - Write.
+ * [21:16] VFID. [24:22] - PFID. [25] valid - indicates if there was a
+ * request accessing VF GRC space that failed permission check since the
+ * last time this register was cleared. Permission checks are: function
+ * permission; R/W permission; address range permission. */
+#define PGLUE_B_REG_VF_GRC_SPACE_VIOLATION_DETAILS		 0x9234
+/* [R 31] Details of first target VF request with length violation (too many
+ * DWs) accessing BAR0. [12:0] Address in DWs (bits [14:2] of byte address).
+ * [14:13] BAR. [20:15] VFID. [23:21] - PFID. [29:24] - Length in DWs. [30]
+ * valid - indicates if there was a request with length violation since the
+ * last time this register was cleared. Length violations: length of more
+ * than 2DWs; length of 2DWs and address not QW aligned; window is GRC and
+ * length is more than 1 DW. */
+#define PGLUE_B_REG_VF_LENGTH_VIOLATION_DETAILS		 0x9230
+/* [R 8] Was_error indication dirty bits for PFs 0 to 7. Each bit indicates
+ * that there was a completion with uncorrectable error for the
+ * corresponding PF. Set by PXP. Reset by MCP writing 1 to
+ * was_error_pf_7_0_clr. */
+#define PGLUE_B_REG_WAS_ERROR_PF_7_0				 0x907c
+/* [W 8] Was_error indication dirty bits clear for PFs 0 to 7. MCP writes 1
+ * to a bit in this register in order to clear the corresponding bit in
+ * flr_request_pf_7_0 register. */
+#define PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR			 0x9470
+/* [R 32] Was_error indication dirty bits for VFs 96 to 127. Each bit
+ * indicates that there was a completion with uncorrectable error for the
+ * corresponding VF. Set by PXP. Reset by MCP writing 1 to
+ * was_error_vf_127_96_clr. */
+#define PGLUE_B_REG_WAS_ERROR_VF_127_96			 0x9078
+/* [W 32] Was_error indication dirty bits clear for VFs 96 to 127. MCP
+ * writes 1 to a bit in this register in order to clear the corresponding
+ * bit in was_error_vf_127_96 register. */
+#define PGLUE_B_REG_WAS_ERROR_VF_127_96_CLR			 0x9474
+/* [R 32] Was_error indication dirty bits for VFs 0 to 31. Each bit
+ * indicates that there was a completion with uncorrectable error for the
+ * corresponding VF. Set by PXP. Reset by MCP writing 1 to
+ * was_error_vf_31_0_clr. */
+#define PGLUE_B_REG_WAS_ERROR_VF_31_0				 0x906c
+/* [W 32] Was_error indication dirty bits clear for VFs 0 to 31. MCP writes
+ * 1 to a bit in this register in order to clear the corresponding bit in
+ * was_error_vf_31_0 register. */
+#define PGLUE_B_REG_WAS_ERROR_VF_31_0_CLR			 0x9478
+/* [R 32] Was_error indication dirty bits for VFs 32 to 63. Each bit
+ * indicates that there was a completion with uncorrectable error for the
+ * corresponding VF. Set by PXP. Reset by MCP writing 1 to
+ * was_error_vf_63_32_clr. */
+#define PGLUE_B_REG_WAS_ERROR_VF_63_32				 0x9070
+/* [W 32] Was_error indication dirty bits clear for VFs 32 to 63. MCP writes
+ * 1 to a bit in this register in order to clear the corresponding bit in
+ * was_error_vf_63_32 register. */
+#define PGLUE_B_REG_WAS_ERROR_VF_63_32_CLR			 0x947c
+/* [R 32] Was_error indication dirty bits for VFs 64 to 95. Each bit
+ * indicates that there was a completion with uncorrectable error for the
+ * corresponding VF. Set by PXP. Reset by MCP writing 1 to
+ * was_error_vf_95_64_clr. */
+#define PGLUE_B_REG_WAS_ERROR_VF_95_64				 0x9074
+/* [W 32] Was_error indication dirty bits clear for VFs 64 to 95. MCP writes
+ * 1 to a bit in this register in order to clear the corresponding bit in
+ * was_error_vf_95_64 register. */
+#define PGLUE_B_REG_WAS_ERROR_VF_95_64_CLR			 0x9480
+/* [RW 1] Type A PF enable inbound interrupt table for XSDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_XSDM_INB_INT_A_PF_ENABLE			 0x9188
+/* [RW 16] Start offset of XSDM zone A (queue zone) in the internal RAM */
+#define PGLUE_B_REG_XSDM_START_OFFSET_A			 0x90ec
+/* [RW 16] Start offset of XSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_XSDM_START_OFFSET_B			 0x90f4
+/* [RW 5] VF Shift of XSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_XSDM_VF_SHIFT_B				 0x90fc
+/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
+#define PGLUE_B_REG_XSDM_ZONE_A_SIZE_PF			 0x91a8
 #define PRS_REG_A_PRSU_20					 0x40134
 /* [R 8] debug only: CFC load request current credit. Transaction based. */
 #define PRS_REG_CFC_LD_CURRENT_CREDIT				 0x40164
@@ -1866,9 +2370,13 @@
 #define PRS_REG_FLUSH_REGIONS_TYPE_5				 0x40018
 #define PRS_REG_FLUSH_REGIONS_TYPE_6				 0x4001c
 #define PRS_REG_FLUSH_REGIONS_TYPE_7				 0x40020
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header. */
+#define PRS_REG_HDRS_AFTER_BASIC				 0x40238
 /* [RW 4] The increment value to send in the CFC load request message */
 #define PRS_REG_INC_VALUE					 0x40048
-/* [RW 1] If set indicates not to send messages to CFC on received packets */
+/* [RW 6] Bit-map indicating which headers must appear in the packet */
+#define PRS_REG_MUST_HAVE_HDRS					 0x40254
 #define PRS_REG_NIC_MODE					 0x40138
 /* [RW 8] The 8-bit event ID for cases where there is no match on the
    connection. Used in packet start message to TCM. */
@@ -1919,6 +2427,13 @@
 #define PRS_REG_TCM_CURRENT_CREDIT				 0x40160
 /* [R 8] debug only: TSDM current credit. Transaction based. */
 #define PRS_REG_TSDM_CURRENT_CREDIT				 0x4015c
+#define PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT			 (0x1<<19)
+#define PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF			 (0x1<<20)
+#define PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN			 (0x1<<22)
+#define PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED		 (0x1<<23)
+#define PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED		 (0x1<<24)
+#define PXP2_PXP2_INT_STS_0_REG_WR_PGLUE_EOP_ERROR		 (0x1<<7)
+#define PXP2_PXP2_INT_STS_CLR_0_REG_WR_PGLUE_EOP_ERROR		 (0x1<<7)
 /* [R 6] Debug only: Number of used entries in the data FIFO */
 #define PXP2_REG_HST_DATA_FIFO_STATUS				 0x12047c
 /* [R 7] Debug only: Number of used entries in the header FIFO */
@@ -2244,8 +2759,17 @@
 /* [RW 1] When '1'; requests will enter input buffers but wont get out
    towards the glue */
 #define PXP2_REG_RQ_DISABLE_INPUTS				 0x120330
-/* [RW 1] 1 - SR will be aligned by 64B; 0 - SR will be aligned by 8B */
+/* [RW 4] Determines alignment of write SRs when a request is split into
+ * several SRs. 0 - 8B aligned. 1 - 64B aligned. 2 - 128B aligned. 3 - 256B
+ * aligned. 4 - 512B aligned. */
 #define PXP2_REG_RQ_DRAM_ALIGN					 0x1205b0
+/* [RW 4] Determines alignment of read SRs when a request is split into
+ * several SRs. 0 - 8B aligned. 1 - 64B aligned. 2 - 128B aligned. 3 - 256B
+ * aligned. 4 - 512B aligned. */
+#define PXP2_REG_RQ_DRAM_ALIGN_RD				 0x12092c
+/* [RW 1] when set the new alignment method (E2) will be applied; when reset
+ * the original alignment method (E1 E1H) will be applied */
+#define PXP2_REG_RQ_DRAM_ALIGN_SEL				 0x120930
 /* [RW 1] If 1 ILT failiue will not result in ELT access; An interrupt will
    be asserted */
 #define PXP2_REG_RQ_ELT_DISABLE 				 0x12066c
@@ -2436,7 +2960,8 @@
 #define PXP_REG_PXP_INT_STS_1					 0x103078
 /* [RC 32] Interrupt register #0 read clear */
 #define PXP_REG_PXP_INT_STS_CLR_0				 0x10306c
-/* [RW 26] Parity mask register #0 read/write */
+#define PXP_REG_PXP_INT_STS_CLR_1				 0x10307c
+/* [RW 27] Parity mask register #0 read/write */
 #define PXP_REG_PXP_PRTY_MASK					 0x103094
 /* [R 26] Parity register #0 read */
 #define PXP_REG_PXP_PRTY_STS					 0x103088
@@ -2566,6 +3091,7 @@
 #define QM_REG_PAUSESTATE7					 0x16e698
 /* [RW 2] The PCI attributes field used in the PCI request. */
 #define QM_REG_PCIREQAT 					 0x168054
+#define QM_REG_PF_EN						 0x16e70c
 /* [R 16] The byte credit of port 0 */
 #define QM_REG_PORT0BYTECRD					 0x168300
 /* [R 16] The byte credit of port 1 */
@@ -3402,6 +3928,14 @@
 /* [R 32] Parity register #0 read */
 #define TSEM_REG_TSEM_PRTY_STS_0				 0x180114
 #define TSEM_REG_TSEM_PRTY_STS_1				 0x180124
+/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
+ * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
+#define TSEM_REG_VFPF_ERR_NUM					 0x180380
+/* [RW 32] Indirect access to AG context with 32-bits granularity. The bits
+ * [10:8] of the address should be the offset within the accessed LCID
+ * context; the bits [7:0] are the accessed LCID.Example: to write to REG10
+ * LCID100. The RBC address should be 12'ha64. */
+#define UCM_REG_AG_CTX						 0xe2000
 /* [R 5] Used to read the XX protection CAM occupancy counter. */
 #define UCM_REG_CAM_OCCUP					 0xe0170
 /* [RW 1] CDU AG read Interface enable. If 0 - the request input is
@@ -3851,6 +4385,17 @@
 /* [R 32] Parity register #0 read */
 #define USEM_REG_USEM_PRTY_STS_0				 0x300124
 #define USEM_REG_USEM_PRTY_STS_1				 0x300134
+/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
+ * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
+#define USEM_REG_VFPF_ERR_NUM					 0x300380
+#define VFC_MEMORIES_RST_REG_CAM_RST				 (0x1<<0)
+#define VFC_MEMORIES_RST_REG_RAM_RST				 (0x1<<1)
+#define VFC_REG_MEMORIES_RST					 0x1943c
+/* [RW 32] Indirect access to AG context with 32-bits granularity. The bits
+ * [12:8] of the address should be the offset within the accessed LCID
+ * context; the bits [7:0] are the accessed LCID.Example: to write to REG10
+ * LCID100. The RBC address should be 13'ha64. */
+#define XCM_REG_AG_CTX						 0x28000
 /* [RW 2] The queue index for registration on Aux1 counter flag. */
 #define XCM_REG_AUX1_Q						 0x20134
 /* [RW 2] Per each decision rule the queue index to register to. */
@@ -4333,6 +4878,9 @@
 #define XSEM_REG_TS_8_AS					 0x280058
 /* [RW 3] The arbitration scheme of time_slot 9 */
 #define XSEM_REG_TS_9_AS					 0x28005c
+/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
+ * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
+#define XSEM_REG_VFPF_ERR_NUM					 0x280380
 /* [RW 32] Interrupt mask register #0 read/write */
 #define XSEM_REG_XSEM_INT_MASK_0				 0x280110
 #define XSEM_REG_XSEM_INT_MASK_1				 0x280120
@@ -4371,6 +4919,23 @@
 #define BIGMAC_REGISTER_TX_SOURCE_ADDR				 (0x08<<3)
 #define BIGMAC_REGISTER_TX_STAT_GTBYT				 (0x20<<3)
 #define BIGMAC_REGISTER_TX_STAT_GTPKT				 (0x0C<<3)
+#define BIGMAC2_REGISTER_BMAC_CONTROL				 (0x00<<3)
+#define BIGMAC2_REGISTER_BMAC_XGXS_CONTROL			 (0x01<<3)
+#define BIGMAC2_REGISTER_CNT_MAX_SIZE				 (0x05<<3)
+#define BIGMAC2_REGISTER_PFC_CONTROL				 (0x06<<3)
+#define BIGMAC2_REGISTER_RX_CONTROL				 (0x3A<<3)
+#define BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS			 (0x62<<3)
+#define BIGMAC2_REGISTER_RX_MAX_SIZE				 (0x3C<<3)
+#define BIGMAC2_REGISTER_RX_STAT_GR64				 (0x40<<3)
+#define BIGMAC2_REGISTER_RX_STAT_GRIPJ				 (0x5f<<3)
+#define BIGMAC2_REGISTER_RX_STAT_GRPP				 (0x51<<3)
+#define BIGMAC2_REGISTER_TX_CONTROL				 (0x1C<<3)
+#define BIGMAC2_REGISTER_TX_MAX_SIZE				 (0x1E<<3)
+#define BIGMAC2_REGISTER_TX_PAUSE_CONTROL			 (0x20<<3)
+#define BIGMAC2_REGISTER_TX_SOURCE_ADDR			 (0x1D<<3)
+#define BIGMAC2_REGISTER_TX_STAT_GTBYT				 (0x39<<3)
+#define BIGMAC2_REGISTER_TX_STAT_GTPOK				 (0x22<<3)
+#define BIGMAC2_REGISTER_TX_STAT_GTPP				 (0x24<<3)
 #define EMAC_LED_1000MB_OVERRIDE				 (1L<<1)
 #define EMAC_LED_100MB_OVERRIDE 				 (1L<<2)
 #define EMAC_LED_10MB_OVERRIDE					 (1L<<3)
@@ -4478,6 +5043,8 @@
 #define HW_LOCK_RESOURCE_SPIO					 2
 #define HW_LOCK_RESOURCE_UNDI					 5
 #define PRS_FLAG_OVERETH_IPV4					 1
+#define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT		      (0x1<<4)
+#define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR		      (0x1<<5)
 #define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR		      (1<<18)
 #define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT		      (1<<31)
 #define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT		      (1<<9)
@@ -4504,6 +5071,8 @@
 #define AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR	      (1<<20)
 #define AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR	      (1<<0)
 #define AEU_INPUTS_ATTN_BITS_PBF_HW_INTERRUPT		      (1<<31)
+#define AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT	      (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR	      (0x1<<3)
 #define AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT		      (1<<3)
 #define AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR		      (1<<2)
 #define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT   (1<<5)
@@ -4796,6 +5365,253 @@
 #define PCI_ID_VAL1					0x434
 #define PCI_ID_VAL2					0x438
 
+#define PXPCS_TL_CONTROL_5		    0x814
+#define PXPCS_TL_CONTROL_5_UNKNOWNTYPE_ERR_ATTN    (1 << 29) /*WC*/
+#define PXPCS_TL_CONTROL_5_BOUNDARY4K_ERR_ATTN	   (1 << 28)   /*WC*/
+#define PXPCS_TL_CONTROL_5_MRRS_ERR_ATTN   (1 << 27)   /*WC*/
+#define PXPCS_TL_CONTROL_5_MPS_ERR_ATTN    (1 << 26)   /*WC*/
+#define PXPCS_TL_CONTROL_5_TTX_BRIDGE_FORWARD_ERR  (1 << 25)   /*WC*/
+#define PXPCS_TL_CONTROL_5_TTX_TXINTF_OVERFLOW	   (1 << 24)   /*WC*/
+#define PXPCS_TL_CONTROL_5_PHY_ERR_ATTN    (1 << 23)   /*RO*/
+#define PXPCS_TL_CONTROL_5_DL_ERR_ATTN	   (1 << 22)   /*RO*/
+#define PXPCS_TL_CONTROL_5_TTX_ERR_NP_TAG_IN_USE   (1 << 21)   /*WC*/
+#define PXPCS_TL_CONTROL_5_TRX_ERR_UNEXP_RTAG  (1 << 20)   /*WC*/
+#define PXPCS_TL_CONTROL_5_PRI_SIG_TARGET_ABORT1   (1 << 19)   /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_UNSPPORT1   (1 << 18)   /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_ECRC1   (1 << 17)   /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_MALF_TLP1   (1 << 16)   /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_RX_OFLOW1   (1 << 15)   /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_UNEXP_CPL1  (1 << 14)   /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_MASTER_ABRT1    (1 << 13)   /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_CPL_TIMEOUT1    (1 << 12)   /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_FC_PRTL1    (1 << 11)   /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_PSND_TLP1   (1 << 10)   /*WC*/
+#define PXPCS_TL_CONTROL_5_PRI_SIG_TARGET_ABORT    (1 << 9)    /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_UNSPPORT    (1 << 8)    /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_ECRC    (1 << 7)    /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_MALF_TLP    (1 << 6)    /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_RX_OFLOW    (1 << 5)    /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_UNEXP_CPL   (1 << 4)    /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_MASTER_ABRT     (1 << 3)    /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_CPL_TIMEOUT     (1 << 2)    /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_FC_PRTL	   (1 << 1)    /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_PSND_TLP    (1 << 0)    /*WC*/
+
+
+#define PXPCS_TL_FUNC345_STAT	   0x854
+#define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT4    (1 << 29)   /* WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT4\
+	(1 << 28) /* Unsupported Request Error Status in function4, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_ECRC4\
+	(1 << 27) /* ECRC Error TLP Status Status in function 4, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP4\
+	(1 << 26) /* Malformed TLP Status Status in function 4, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW4\
+	(1 << 25) /* Receiver Overflow Status Status in function 4, if \
+	set, generate pcie_err_attn output when this error is seen.. WC \
+	*/
+#define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL4\
+	(1 << 24) /* Unexpected Completion Status Status in function 4, \
+	if set, generate pcie_err_attn output when this error is seen. WC \
+	*/
+#define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT4\
+	(1 << 23) /* Receive UR Statusin function 4. If set, generate \
+	pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT4\
+	(1 << 22) /* Completer Timeout Status Status in function 4, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL4\
+	(1 << 21) /* Flow Control Protocol Error Status Status in \
+	function 4, if set, generate pcie_err_attn output when this error \
+	is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP4\
+	(1 << 20) /* Poisoned Error Status Status in function 4, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT3    (1 << 19)   /* WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT3\
+	(1 << 18) /* Unsupported Request Error Status in function3, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_ECRC3\
+	(1 << 17) /* ECRC Error TLP Status Status in function 3, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP3\
+	(1 << 16) /* Malformed TLP Status Status in function 3, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW3\
+	(1 << 15) /* Receiver Overflow Status Status in function 3, if \
+	set, generate pcie_err_attn output when this error is seen.. WC \
+	*/
+#define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL3\
+	(1 << 14) /* Unexpected Completion Status Status in function 3, \
+	if set, generate pcie_err_attn output when this error is seen. WC \
+	*/
+#define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT3\
+	(1 << 13) /* Receive UR Statusin function 3. If set, generate \
+	pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT3\
+	(1 << 12) /* Completer Timeout Status Status in function 3, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL3\
+	(1 << 11) /* Flow Control Protocol Error Status Status in \
+	function 3, if set, generate pcie_err_attn output when this error \
+	is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP3\
+	(1 << 10) /* Poisoned Error Status Status in function 3, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT2    (1 << 9)    /* WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT2\
+	(1 << 8) /* Unsupported Request Error Status for Function 2, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_ECRC2\
+	(1 << 7) /* ECRC Error TLP Status Status for Function 2, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP2\
+	(1 << 6) /* Malformed TLP Status Status for Function 2, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW2\
+	(1 << 5) /* Receiver Overflow Status Status for Function 2, if \
+	set, generate pcie_err_attn output when this error is seen.. WC \
+	*/
+#define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL2\
+	(1 << 4) /* Unexpected Completion Status Status for Function 2, \
+	if set, generate pcie_err_attn output when this error is seen. WC \
+	*/
+#define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT2\
+	(1 << 3) /* Receive UR Statusfor Function 2. If set, generate \
+	pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT2\
+	(1 << 2) /* Completer Timeout Status Status for Function 2, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL2\
+	(1 << 1) /* Flow Control Protocol Error Status Status for \
+	Function 2, if set, generate pcie_err_attn output when this error \
+	is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP2\
+	(1 << 0) /* Poisoned Error Status Status for Function 2, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+
+
+#define PXPCS_TL_FUNC678_STAT  0x85C
+#define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT7    (1 << 29)   /*	 WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT7\
+	(1 << 28) /* Unsupported Request Error Status in function7, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_ECRC7\
+	(1 << 27) /* ECRC Error TLP Status Status in function 7, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP7\
+	(1 << 26) /* Malformed TLP Status Status in function 7, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW7\
+	(1 << 25) /* Receiver Overflow Status Status in function 7, if \
+	set, generate pcie_err_attn output when this error is seen.. WC \
+	*/
+#define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL7\
+	(1 << 24) /* Unexpected Completion Status Status in function 7, \
+	if set, generate pcie_err_attn output when this error is seen. WC \
+	*/
+#define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT7\
+	(1 << 23) /* Receive UR Statusin function 7. If set, generate \
+	pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT7\
+	(1 << 22) /* Completer Timeout Status Status in function 7, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL7\
+	(1 << 21) /* Flow Control Protocol Error Status Status in \
+	function 7, if set, generate pcie_err_attn output when this error \
+	is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP7\
+	(1 << 20) /* Poisoned Error Status Status in function 7, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT6    (1 << 19)    /*	  WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT6\
+	(1 << 18) /* Unsupported Request Error Status in function6, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_ECRC6\
+	(1 << 17) /* ECRC Error TLP Status Status in function 6, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP6\
+	(1 << 16) /* Malformed TLP Status Status in function 6, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW6\
+	(1 << 15) /* Receiver Overflow Status Status in function 6, if \
+	set, generate pcie_err_attn output when this error is seen.. WC \
+	*/
+#define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL6\
+	(1 << 14) /* Unexpected Completion Status Status in function 6, \
+	if set, generate pcie_err_attn output when this error is seen. WC \
+	*/
+#define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT6\
+	(1 << 13) /* Receive UR Statusin function 6. If set, generate \
+	pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT6\
+	(1 << 12) /* Completer Timeout Status Status in function 6, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL6\
+	(1 << 11) /* Flow Control Protocol Error Status Status in \
+	function 6, if set, generate pcie_err_attn output when this error \
+	is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP6\
+	(1 << 10) /* Poisoned Error Status Status in function 6, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT5    (1 << 9) /*    WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5\
+	(1 << 8) /* Unsupported Request Error Status for Function 5, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_ECRC5\
+	(1 << 7) /* ECRC Error TLP Status Status for Function 5, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP5\
+	(1 << 6) /* Malformed TLP Status Status for Function 5, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW5\
+	(1 << 5) /* Receiver Overflow Status Status for Function 5, if \
+	set, generate pcie_err_attn output when this error is seen.. WC \
+	*/
+#define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL5\
+	(1 << 4) /* Unexpected Completion Status Status for Function 5, \
+	if set, generate pcie_err_attn output when this error is seen. WC \
+	*/
+#define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT5\
+	(1 << 3) /* Receive UR Statusfor Function 5. If set, generate \
+	pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT5\
+	(1 << 2) /* Completer Timeout Status Status for Function 5, if \
+	set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL5\
+	(1 << 1) /* Flow Control Protocol Error Status Status for \
+	Function 5, if set, generate pcie_err_attn output when this error \
+	is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP5\
+	(1 << 0) /* Poisoned Error Status Status for Function 5, if set, \
+	generate pcie_err_attn output when this error is seen.. WC */
+
+
+#define BAR_USTRORM_INTMEM				0x400000
+#define BAR_CSTRORM_INTMEM				0x410000
+#define BAR_XSTRORM_INTMEM				0x420000
+#define BAR_TSTRORM_INTMEM				0x430000
+
+/* for accessing the IGU in case of status block ACK */
+#define BAR_IGU_INTMEM					0x440000
+
+#define BAR_DOORBELL_OFFSET				0x800000
+
+#define BAR_ME_REGISTER				0x450000
+#define ME_REG_PF_NUM_SHIFT		0
+#define ME_REG_PF_NUM\
+	(7L<<ME_REG_PF_NUM_SHIFT) /* Relative PF Num */
+#define ME_REG_VF_VALID		(1<<8)
+#define ME_REG_VF_NUM_SHIFT		9
+#define ME_REG_VF_NUM_MASK		(0x3f<<ME_REG_VF_NUM_SHIFT)
+#define ME_REG_VF_ERR			(0x1<<3)
+#define ME_REG_ABS_PF_NUM_SHIFT	16
+#define ME_REG_ABS_PF_NUM\
+	(7L<<ME_REG_ABS_PF_NUM_SHIFT) /* Absolute PF Num */
+
 
 #define MDIO_REG_BANK_CL73_IEEEB0	0x0
 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL	0x0
@@ -4964,6 +5780,8 @@
 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN			0x0001
 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_AN_FST_TMR 		0x0040
 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1			0x14
+#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SGMII			0x0001
+#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_LINK			0x0002
 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_DUPLEX			0x0004
 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_MASK			0x0018
 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_SHIFT 		3
@@ -5135,28 +5953,35 @@
 #define MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR	0x8005
 #define MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF	0x8007
 #define MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK 0xff
-#define MDIO_PMA_REG_8727_MISC_CTRL		0x8309
 #define MDIO_PMA_REG_8727_TX_CTRL1		0xca02
 #define MDIO_PMA_REG_8727_TX_CTRL2		0xca05
 #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_AN_REG_8727_MISC_CTRL		0x8309
 
 #define MDIO_PMA_REG_8073_CHIP_REV			0xc801
 #define MDIO_PMA_REG_8073_SPEED_LINK_STATUS		0xc820
 #define MDIO_PMA_REG_8073_XAUI_WA			0xc841
+#define MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL		0xcd08
 
 #define MDIO_PMA_REG_7101_RESET 	0xc000
 #define MDIO_PMA_REG_7107_LED_CNTL	0xc007
+#define MDIO_PMA_REG_7107_LINK_LED_CNTL 0xc009
 #define MDIO_PMA_REG_7101_VER1		0xc026
 #define MDIO_PMA_REG_7101_VER2		0xc027
 
-#define MDIO_PMA_REG_8481_PMD_SIGNAL	0xa811
-#define MDIO_PMA_REG_8481_LED1_MASK	0xa82c
-#define MDIO_PMA_REG_8481_LED2_MASK	0xa82f
-#define MDIO_PMA_REG_8481_LED3_MASK	0xa832
-#define MDIO_PMA_REG_8481_LED3_BLINK	0xa834
-#define MDIO_PMA_REG_8481_SIGNAL_MASK	0xa835
-#define MDIO_PMA_REG_8481_LINK_SIGNAL	0xa83b
+#define MDIO_PMA_REG_8481_PMD_SIGNAL			0xa811
+#define MDIO_PMA_REG_8481_LED1_MASK			0xa82c
+#define MDIO_PMA_REG_8481_LED2_MASK			0xa82f
+#define MDIO_PMA_REG_8481_LED3_MASK			0xa832
+#define MDIO_PMA_REG_8481_LED3_BLINK			0xa834
+#define MDIO_PMA_REG_8481_LED5_MASK			0xa838
+#define MDIO_PMA_REG_8481_SIGNAL_MASK			0xa835
+#define MDIO_PMA_REG_8481_LINK_SIGNAL			0xa83b
+#define MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK	0x800
+#define MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT 11
 
 
 #define MDIO_WIS_DEVAD			0x2
@@ -5188,6 +6013,8 @@
 #define MDIO_XS_8706_REG_BANK_RX3	0x80ec
 #define MDIO_XS_8706_REG_BANK_RXA	0x80fc
 
+#define MDIO_XS_REG_8073_RX_CTRL_PCIE	0x80FA
+
 #define MDIO_AN_DEVAD			0x7
 /*ieee*/
 #define MDIO_AN_REG_CTRL		0x0000
@@ -5210,14 +6037,40 @@
 #define MDIO_AN_REG_CL37_FC_LP		0xffe5
 
 #define MDIO_AN_REG_8073_2_5G		0x8329
+#define MDIO_AN_REG_8073_BAM		0x8350
 
+#define MDIO_AN_REG_8481_10GBASE_T_AN_CTRL	0x0020
 #define MDIO_AN_REG_8481_LEGACY_MII_CTRL	0xffe0
+#define MDIO_AN_REG_8481_LEGACY_MII_STATUS	0xffe1
 #define MDIO_AN_REG_8481_LEGACY_AN_ADV		0xffe4
+#define MDIO_AN_REG_8481_LEGACY_AN_EXPANSION	0xffe6
 #define MDIO_AN_REG_8481_1000T_CTRL		0xffe9
 #define MDIO_AN_REG_8481_EXPANSION_REG_RD_RW	0xfff5
 #define MDIO_AN_REG_8481_EXPANSION_REG_ACCESS	0xfff7
+#define MDIO_AN_REG_8481_AUX_CTRL		0xfff8
 #define MDIO_AN_REG_8481_LEGACY_SHADOW		0xfffc
 
+/* BCM84823 only */
+#define MDIO_CTL_DEVAD			0x1e
+#define MDIO_CTL_REG_84823_MEDIA		0x401a
+#define MDIO_CTL_REG_84823_MEDIA_MAC_MASK		0x0018
+	/* These pins configure the BCM84823 interface to MAC after reset. */
+#define MDIO_CTL_REG_84823_CTRL_MAC_XFI			0x0008
+#define MDIO_CTL_REG_84823_MEDIA_MAC_XAUI_M		0x0010
+	/* These pins configure the BCM84823 interface to Line after reset. */
+#define MDIO_CTL_REG_84823_MEDIA_LINE_MASK		0x0060
+#define MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L		0x0020
+#define MDIO_CTL_REG_84823_MEDIA_LINE_XFI		0x0040
+	/* When this pin is active high during reset, 10GBASE-T core is power
+	 * down, When it is active low the 10GBASE-T is power up
+	 */
+#define MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN	0x0080
+#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK		0x0100
+#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER	0x0000
+#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER		0x0100
+#define MDIO_CTL_REG_84823_MEDIA_FIBER_1G			0x1000
+
+
 #define IGU_FUNC_BASE			0x0400
 
 #define IGU_ADDR_MSIX			0x0000
@@ -5239,6 +6092,11 @@
 #define IGU_INT_NOP				2
 #define IGU_INT_NOP2			3
 
+#define IGU_USE_REGISTER_ustorm_type_0_sb_cleanup  0
+#define IGU_USE_REGISTER_ustorm_type_1_sb_cleanup  1
+#define IGU_USE_REGISTER_cstorm_type_0_sb_cleanup  2
+#define IGU_USE_REGISTER_cstorm_type_1_sb_cleanup  3
+
 #define COMMAND_REG_INT_ACK	    0x0
 #define COMMAND_REG_PROD_UPD	    0x4
 #define COMMAND_REG_ATTN_BITS_UPD   0x8
@@ -5281,6 +6139,50 @@
 #define IGU_REG_SISR_MDPC_WOMASK_UPPER		0x05a6
 
 #define IGU_REG_RESERVED_UPPER				0x05ff
+/* Fields of IGU PF CONFIGRATION REGISTER */
+#define IGU_PF_CONF_FUNC_EN	  (0x1<<0)  /* function enable	      */
+#define IGU_PF_CONF_MSI_MSIX_EN   (0x1<<1)  /* MSI/MSIX enable	      */
+#define IGU_PF_CONF_INT_LINE_EN   (0x1<<2)  /* INT enable	      */
+#define IGU_PF_CONF_ATTN_BIT_EN   (0x1<<3)  /* attention enable       */
+#define IGU_PF_CONF_SINGLE_ISR_EN (0x1<<4)  /* single ISR mode enable */
+#define IGU_PF_CONF_SIMD_MODE	  (0x1<<5)  /* simd all ones mode     */
+
+/* Fields of IGU VF CONFIGRATION REGISTER */
+#define IGU_VF_CONF_FUNC_EN	   (0x1<<0)  /* function enable        */
+#define IGU_VF_CONF_MSI_MSIX_EN    (0x1<<1)  /* MSI/MSIX enable        */
+#define IGU_VF_CONF_PARENT_MASK    (0x3<<2)  /* Parent PF	       */
+#define IGU_VF_CONF_PARENT_SHIFT   2	     /* Parent PF	       */
+#define IGU_VF_CONF_SINGLE_ISR_EN  (0x1<<4)  /* single ISR mode enable */
+
+
+#define IGU_BC_DSB_NUM_SEGS    5
+#define IGU_BC_NDSB_NUM_SEGS   2
+#define IGU_NORM_DSB_NUM_SEGS  2
+#define IGU_NORM_NDSB_NUM_SEGS 1
+#define IGU_BC_BASE_DSB_PROD   128
+#define IGU_NORM_BASE_DSB_PROD 136
+
+#define IGU_CTRL_CMD_TYPE_WR\
+	1
+#define IGU_CTRL_CMD_TYPE_RD\
+	0
+
+#define IGU_SEG_ACCESS_NORM   0
+#define IGU_SEG_ACCESS_DEF    1
+#define IGU_SEG_ACCESS_ATTN   2
+
+	/* FID (if VF - [6] = 0; [5:0] = VF number; if PF - [6] = 1; \
+	[5:2] = 0; [1:0] = PF number) */
+#define IGU_FID_ENCODE_IS_PF	    (0x1<<6)
+#define IGU_FID_ENCODE_IS_PF_SHIFT  6
+#define IGU_FID_VF_NUM_MASK	    (0x3f)
+#define IGU_FID_PF_NUM_MASK	    (0x7)
+
+#define IGU_REG_MAPPING_MEMORY_VALID		(1<<0)
+#define IGU_REG_MAPPING_MEMORY_VECTOR_MASK	(0x3F<<1)
+#define IGU_REG_MAPPING_MEMORY_VECTOR_SHIFT	1
+#define IGU_REG_MAPPING_MEMORY_FID_MASK	(0x7F<<7)
+#define IGU_REG_MAPPING_MEMORY_FID_SHIFT	7
 
 
 #define CDU_REGION_NUMBER_XCM_AG 2
diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c
index c747244..4733c83 100644
--- a/drivers/net/bnx2x/bnx2x_stats.c
+++ b/drivers/net/bnx2x/bnx2x_stats.c
@@ -14,8 +14,8 @@
  * Statistics and Link management by Yitchak Gertner
  *
  */
- #include "bnx2x_cmn.h"
- #include "bnx2x_stats.h"
+#include "bnx2x_cmn.h"
+#include "bnx2x_stats.h"
 
 /* Statistics */
 
@@ -153,7 +153,7 @@
 static void bnx2x_storm_stats_post(struct bnx2x *bp)
 {
 	if (!bp->stats_pending) {
-		struct eth_query_ramrod_data ramrod_data = {0};
+		struct common_query_ramrod_data ramrod_data = {0};
 		int i, rc;
 
 		spin_lock_bh(&bp->stats_lock);
@@ -163,14 +163,11 @@
 		for_each_queue(bp, i)
 			ramrod_data.ctr_id_vector |= (1 << bp->fp[i].cl_id);
 
-		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_STAT_QUERY, 0,
+		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STAT_QUERY, 0,
 				   ((u32 *)&ramrod_data)[1],
-				   ((u32 *)&ramrod_data)[0], 0);
-		if (rc == 0) {
-			/* stats ramrod has it's own slot on the spq */
-			bp->spq_left++;
+				   ((u32 *)&ramrod_data)[0], 1);
+		if (rc == 0)
 			bp->stats_pending = 1;
-		}
 
 		spin_unlock_bh(&bp->stats_lock);
 	}
@@ -188,20 +185,12 @@
 	/* loader */
 	if (bp->executer_idx) {
 		int loader_idx = PMF_DMAE_C(bp);
+		u32 opcode =  bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
+						 true, DMAE_COMP_GRC);
+		opcode = bnx2x_dmae_opcode_clr_src_reset(opcode);
 
 		memset(dmae, 0, sizeof(struct dmae_command));
-
-		dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
-				DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE |
-				DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
-				DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
-				DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
-				(BP_PORT(bp) ? DMAE_CMD_PORT_1 :
-					       DMAE_CMD_PORT_0) |
-				(BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+		dmae->opcode = opcode;
 		dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, dmae[0]));
 		dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, dmae[0]));
 		dmae->dst_addr_lo = (DMAE_REG_CMD_MEM +
@@ -253,26 +242,17 @@
 	u32 *stats_comp = bnx2x_sp(bp, stats_comp);
 
 	/* sanity */
-	if (!IS_E1HMF(bp) || !bp->port.pmf || !bp->port.port_stx) {
+	if (!IS_MF(bp) || !bp->port.pmf || !bp->port.port_stx) {
 		BNX2X_ERR("BUG!\n");
 		return;
 	}
 
 	bp->executer_idx = 0;
 
-	opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
-		  DMAE_CMD_C_ENABLE |
-		  DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
-		  DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
-		  DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
-		  (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
-		  (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+	opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI, false, 0);
 
 	dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-	dmae->opcode = (opcode | DMAE_CMD_C_DST_GRC);
+	dmae->opcode = bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_GRC);
 	dmae->src_addr_lo = bp->port.port_stx >> 2;
 	dmae->src_addr_hi = 0;
 	dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
@@ -283,7 +263,7 @@
 	dmae->comp_val = 1;
 
 	dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-	dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI);
+	dmae->opcode = bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI);
 	dmae->src_addr_lo = (bp->port.port_stx >> 2) + DMAE_LEN32_RD_MAX;
 	dmae->src_addr_hi = 0;
 	dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats) +
@@ -304,7 +284,6 @@
 {
 	struct dmae_command *dmae;
 	int port = BP_PORT(bp);
-	int vn = BP_E1HVN(bp);
 	u32 opcode;
 	int loader_idx = PMF_DMAE_C(bp);
 	u32 mac_addr;
@@ -319,16 +298,8 @@
 	bp->executer_idx = 0;
 
 	/* MCP */
-	opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
-		  DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE |
-		  DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
-		  DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
-		  DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
-		  (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
-		  (vn << DMAE_CMD_E1HVN_SHIFT));
+	opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
+				    true, DMAE_COMP_GRC);
 
 	if (bp->port.port_stx) {
 
@@ -359,16 +330,8 @@
 	}
 
 	/* MAC */
-	opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
-		  DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE |
-		  DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
-		  DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
-		  DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
-		  (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
-		  (vn << DMAE_CMD_E1HVN_SHIFT));
+	opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
+				   true, DMAE_COMP_GRC);
 
 	if (bp->link_vars.mac_type == MAC_TYPE_BMAC) {
 
@@ -379,13 +342,21 @@
 		   BIGMAC_REGISTER_TX_STAT_GTBYT */
 		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
 		dmae->opcode = opcode;
-		dmae->src_addr_lo = (mac_addr +
+		if (CHIP_IS_E1x(bp)) {
+			dmae->src_addr_lo = (mac_addr +
 				     BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
+			dmae->len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
+				     BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
+		} else {
+			dmae->src_addr_lo = (mac_addr +
+				     BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
+			dmae->len = (8 + BIGMAC2_REGISTER_TX_STAT_GTBYT -
+				     BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
+		}
+
 		dmae->src_addr_hi = 0;
 		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats));
 		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats));
-		dmae->len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
-			     BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
 		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
 		dmae->comp_addr_hi = 0;
 		dmae->comp_val = 1;
@@ -394,15 +365,31 @@
 		   BIGMAC_REGISTER_RX_STAT_GRIPJ */
 		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
 		dmae->opcode = opcode;
-		dmae->src_addr_lo = (mac_addr +
-				     BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
 		dmae->src_addr_hi = 0;
-		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
-				offsetof(struct bmac_stats, rx_stat_gr64_lo));
-		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
-				offsetof(struct bmac_stats, rx_stat_gr64_lo));
-		dmae->len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
-			     BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+		if (CHIP_IS_E1x(bp)) {
+			dmae->src_addr_lo = (mac_addr +
+					     BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+			dmae->dst_addr_lo =
+				U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
+				offsetof(struct bmac1_stats, rx_stat_gr64_lo));
+			dmae->dst_addr_hi =
+				U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
+				offsetof(struct bmac1_stats, rx_stat_gr64_lo));
+			dmae->len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
+				     BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+		} else {
+			dmae->src_addr_lo =
+				(mac_addr + BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
+			dmae->dst_addr_lo =
+				U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
+				offsetof(struct bmac2_stats, rx_stat_gr64_lo));
+			dmae->dst_addr_hi =
+				U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
+				offsetof(struct bmac2_stats, rx_stat_gr64_lo));
+			dmae->len = (8 + BIGMAC2_REGISTER_RX_STAT_GRIPJ -
+				     BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
+		}
+
 		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
 		dmae->comp_addr_hi = 0;
 		dmae->comp_val = 1;
@@ -483,16 +470,8 @@
 	dmae->comp_val = 1;
 
 	dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-	dmae->opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
-			DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
-			DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
-			DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
-			DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
-			(port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
-			(vn << DMAE_CMD_E1HVN_SHIFT));
+	dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
+					 true, DMAE_COMP_PCI);
 	dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 :
 				    NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2;
 	dmae->src_addr_hi = 0;
@@ -522,16 +501,8 @@
 	bp->executer_idx = 0;
 	memset(dmae, 0, sizeof(struct dmae_command));
 
-	dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
-			DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
-			DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
-			DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
-			DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
-			(BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
-			(BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+	dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
+					 true, DMAE_COMP_PCI);
 	dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats));
 	dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats));
 	dmae->dst_addr_lo = bp->func_stx >> 2;
@@ -571,7 +542,6 @@
 
 static void bnx2x_bmac_stats_update(struct bnx2x *bp)
 {
-	struct bmac_stats *new = bnx2x_sp(bp, mac_stats.bmac_stats);
 	struct host_port_stats *pstats = bnx2x_sp(bp, port_stats);
 	struct bnx2x_eth_stats *estats = &bp->eth_stats;
 	struct {
@@ -579,35 +549,74 @@
 		u32 hi;
 	} diff;
 
-	UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets);
-	UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors);
-	UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts);
-	UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong);
-	UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments);
-	UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
-	UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
-	UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
-	UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
-	UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
-	UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
-	UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
-	UPDATE_STAT64(tx_stat_gt127,
+	if (CHIP_IS_E1x(bp)) {
+		struct bmac1_stats *new = bnx2x_sp(bp, mac_stats.bmac1_stats);
+
+		/* the macros below will use "bmac1_stats" type */
+		UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets);
+		UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors);
+		UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts);
+		UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong);
+		UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments);
+		UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
+		UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
+		UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
+		UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
+		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
+		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
+		UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
+		UPDATE_STAT64(tx_stat_gt127,
 				tx_stat_etherstatspkts65octetsto127octets);
-	UPDATE_STAT64(tx_stat_gt255,
+		UPDATE_STAT64(tx_stat_gt255,
 				tx_stat_etherstatspkts128octetsto255octets);
-	UPDATE_STAT64(tx_stat_gt511,
+		UPDATE_STAT64(tx_stat_gt511,
 				tx_stat_etherstatspkts256octetsto511octets);
-	UPDATE_STAT64(tx_stat_gt1023,
+		UPDATE_STAT64(tx_stat_gt1023,
 				tx_stat_etherstatspkts512octetsto1023octets);
-	UPDATE_STAT64(tx_stat_gt1518,
+		UPDATE_STAT64(tx_stat_gt1518,
 				tx_stat_etherstatspkts1024octetsto1522octets);
-	UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
-	UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
-	UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
-	UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
-	UPDATE_STAT64(tx_stat_gterr,
+		UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
+		UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
+		UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
+		UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
+		UPDATE_STAT64(tx_stat_gterr,
 				tx_stat_dot3statsinternalmactransmiterrors);
-	UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+		UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+
+	} else {
+		struct bmac2_stats *new = bnx2x_sp(bp, mac_stats.bmac2_stats);
+
+		/* the macros below will use "bmac2_stats" type */
+		UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets);
+		UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors);
+		UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts);
+		UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong);
+		UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments);
+		UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
+		UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
+		UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
+		UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
+		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
+		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
+		UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
+		UPDATE_STAT64(tx_stat_gt127,
+				tx_stat_etherstatspkts65octetsto127octets);
+		UPDATE_STAT64(tx_stat_gt255,
+				tx_stat_etherstatspkts128octetsto255octets);
+		UPDATE_STAT64(tx_stat_gt511,
+				tx_stat_etherstatspkts256octetsto511octets);
+		UPDATE_STAT64(tx_stat_gt1023,
+				tx_stat_etherstatspkts512octetsto1023octets);
+		UPDATE_STAT64(tx_stat_gt1518,
+				tx_stat_etherstatspkts1024octetsto1522octets);
+		UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
+		UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
+		UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
+		UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
+		UPDATE_STAT64(tx_stat_gterr,
+				tx_stat_dot3statsinternalmactransmiterrors);
+		UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+	}
 
 	estats->pause_frames_received_hi =
 				pstats->mac_stx[1].rx_stat_bmac_xpf_hi;
@@ -969,6 +978,7 @@
 {
 	struct bnx2x_eth_stats *estats = &bp->eth_stats;
 	struct net_device_stats *nstats = &bp->dev->stats;
+	unsigned long tmp;
 	int i;
 
 	nstats->rx_packets =
@@ -985,10 +995,10 @@
 
 	nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi);
 
-	nstats->rx_dropped = estats->mac_discard;
+	tmp = estats->mac_discard;
 	for_each_queue(bp, i)
-		nstats->rx_dropped +=
-			le32_to_cpu(bp->fp[i].old_tclient.checksum_discard);
+		tmp += le32_to_cpu(bp->fp[i].old_tclient.checksum_discard);
+	nstats->rx_dropped = tmp;
 
 	nstats->tx_dropped = 0;
 
@@ -1123,24 +1133,17 @@
 
 	bp->executer_idx = 0;
 
-	opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
-		  DMAE_CMD_C_ENABLE |
-		  DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
-		  DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
-		  DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
-		  (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
-		  (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+	opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC, false, 0);
 
 	if (bp->port.port_stx) {
 
 		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
 		if (bp->func_stx)
-			dmae->opcode = (opcode | DMAE_CMD_C_DST_GRC);
+			dmae->opcode = bnx2x_dmae_opcode_add_comp(
+						opcode, DMAE_COMP_GRC);
 		else
-			dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI);
+			dmae->opcode = bnx2x_dmae_opcode_add_comp(
+						opcode, DMAE_COMP_PCI);
 		dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
 		dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
 		dmae->dst_addr_lo = bp->port.port_stx >> 2;
@@ -1164,7 +1167,8 @@
 	if (bp->func_stx) {
 
 		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI);
+		dmae->opcode =
+			bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI);
 		dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats));
 		dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats));
 		dmae->dst_addr_lo = bp->func_stx >> 2;
@@ -1257,16 +1261,8 @@
 	bp->executer_idx = 0;
 
 	dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-	dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
-			DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
-			DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
-			DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
-			DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
-			(BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
-			(BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+	dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
+					 true, DMAE_COMP_PCI);
 	dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
 	dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
 	dmae->dst_addr_lo = bp->port.port_stx >> 2;
@@ -1283,9 +1279,7 @@
 
 static void bnx2x_func_stats_base_init(struct bnx2x *bp)
 {
-	int vn, vn_max = IS_E1HMF(bp) ? E1HVN_MAX : E1VN_MAX;
-	int port = BP_PORT(bp);
-	int func;
+	int vn, vn_max = IS_MF(bp) ? E1HVN_MAX : E1VN_MAX;
 	u32 func_stx;
 
 	/* sanity */
@@ -1298,9 +1292,9 @@
 	func_stx = bp->func_stx;
 
 	for (vn = VN_0; vn < vn_max; vn++) {
-		func = 2*vn + port;
+		int mb_idx = !CHIP_IS_E2(bp) ? 2*vn + BP_PORT(bp) : vn;
 
-		bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param);
+		bp->func_stx = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_param);
 		bnx2x_func_stats_init(bp);
 		bnx2x_hw_stats_post(bp);
 		bnx2x_stats_comp(bp);
@@ -1324,16 +1318,8 @@
 	bp->executer_idx = 0;
 	memset(dmae, 0, sizeof(struct dmae_command));
 
-	dmae->opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
-			DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
-			DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
-			DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
-			DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
-			(BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
-			(BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+	dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
+					 true, DMAE_COMP_PCI);
 	dmae->src_addr_lo = bp->func_stx >> 2;
 	dmae->src_addr_hi = 0;
 	dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats_base));
@@ -1351,8 +1337,9 @@
 void bnx2x_stats_init(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
-	int func = BP_FUNC(bp);
+	int mb_idx = BP_FW_MB_IDX(bp);
 	int i;
+	struct eth_stats_query *stats = bnx2x_sp(bp, fw_stats);
 
 	bp->stats_pending = 0;
 	bp->executer_idx = 0;
@@ -1361,7 +1348,7 @@
 	/* port and func stats for management */
 	if (!BP_NOMCP(bp)) {
 		bp->port.port_stx = SHMEM_RD(bp, port_mb[port].port_stx);
-		bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param);
+		bp->func_stx = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_param);
 
 	} else {
 		bp->port.port_stx = 0;
@@ -1394,6 +1381,18 @@
 		memset(&fp->eth_q_stats, 0, sizeof(struct bnx2x_eth_q_stats));
 	}
 
+	for_each_queue(bp, i) {
+		/* Set initial stats counter in the stats ramrod data to -1 */
+		int cl_id = bp->fp[i].cl_id;
+
+		stats->xstorm_common.client_statistics[cl_id].
+			stats_counter = 0xffff;
+		stats->ustorm_common.client_statistics[cl_id].
+			stats_counter = 0xffff;
+		stats->tstorm_common.client_statistics[cl_id].
+			stats_counter = 0xffff;
+	}
+
 	memset(&bp->dev->stats, 0, sizeof(struct net_device_stats));
 	memset(&bp->eth_stats, 0, sizeof(struct bnx2x_eth_stats));
 
diff --git a/drivers/net/bnx2x/bnx2x_stats.h b/drivers/net/bnx2x/bnx2x_stats.h
index 38a4e90..afd15ef 100644
--- a/drivers/net/bnx2x/bnx2x_stats.h
+++ b/drivers/net/bnx2x/bnx2x_stats.h
@@ -9,6 +9,10 @@
  * Maintained by: Eilon Greenstein <eilong@broadcom.com>
  * Written by: Eliezer Tamir
  * Based on code from Michael Chan's bnx2 driver
+ * UDP CSUM errata workaround by Arik Gendelman
+ * Slowpath and fastpath rework by Vladislav Zolotarov
+ * Statistics and Link management by Yitchak Gertner
+ *
  */
 
 #ifndef BNX2X_STATS_H
@@ -228,12 +232,8 @@
 /* Forward declaration */
 struct bnx2x;
 
-
 void bnx2x_stats_init(struct bnx2x *bp);
 
 extern const u32 dmae_reg_go_c[];
-extern int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
-			 u32 data_hi, u32 data_lo, int common);
-
 
 #endif /* BNX2X_STATS_H */
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 0ddf4c6..881914bc 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -93,7 +93,7 @@
 // compare MAC addresses
 #define MAC_ADDRESS_COMPARE(A, B) memcmp(A, B, ETH_ALEN)
 
-static struct mac_addr null_mac_addr = {{0, 0, 0, 0, 0, 0}};
+static struct mac_addr null_mac_addr = { { 0, 0, 0, 0, 0, 0 } };
 static u16 ad_ticks_per_sec;
 static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
 
@@ -129,9 +129,8 @@
  */
 static inline struct bonding *__get_bond_by_port(struct port *port)
 {
-	if (port->slave == NULL) {
+	if (port->slave == NULL)
 		return NULL;
-	}
 
 	return bond_get_bond_by_slave(port->slave);
 }
@@ -144,9 +143,8 @@
  */
 static inline struct port *__get_first_port(struct bonding *bond)
 {
-	if (bond->slave_cnt == 0) {
+	if (bond->slave_cnt == 0)
 		return NULL;
-	}
 
 	return &(SLAVE_AD_INFO(bond->first_slave).port);
 }
@@ -164,9 +162,8 @@
 	struct slave *slave = port->slave;
 
 	// If there's no bond for this port, or this is the last slave
-	if ((bond == NULL) || (slave->next == bond->first_slave)) {
+	if ((bond == NULL) || (slave->next == bond->first_slave))
 		return NULL;
-	}
 
 	return &(SLAVE_AD_INFO(slave->next).port);
 }
@@ -183,9 +180,8 @@
 	struct bonding *bond = __get_bond_by_port(port);
 
 	// If there's no bond for this port, or bond has no slaves
-	if ((bond == NULL) || (bond->slave_cnt == 0)) {
+	if ((bond == NULL) || (bond->slave_cnt == 0))
 		return NULL;
-	}
 
 	return &(SLAVE_AD_INFO(bond->first_slave).aggregator);
 }
@@ -203,9 +199,8 @@
 	struct bonding *bond = bond_get_bond_by_slave(slave);
 
 	// If there's no bond for this aggregator, or this is the last slave
-	if ((bond == NULL) || (slave->next == bond->first_slave)) {
+	if ((bond == NULL) || (slave->next == bond->first_slave))
 		return NULL;
-	}
 
 	return &(SLAVE_AD_INFO(slave->next).aggregator);
 }
@@ -240,9 +235,8 @@
 {
 	struct slave *slave = port->slave;
 
-	if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) {
+	if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev))
 		bond_set_slave_active_flags(slave);
-	}
 }
 
 /**
@@ -252,7 +246,7 @@
  */
 static inline int __port_is_enabled(struct port *port)
 {
-	return(port->slave->state == BOND_STATE_ACTIVE);
+	return port->slave->state == BOND_STATE_ACTIVE;
 }
 
 /**
@@ -265,9 +259,8 @@
 {
 	struct bonding *bond = __get_bond_by_port(port);
 
-	if (bond == NULL) {
+	if (bond == NULL)
 		return BOND_AD_STABLE;
-	}
 
 	return BOND_AD_INFO(bond).agg_select_mode;
 }
@@ -281,9 +274,8 @@
 {
 	struct bonding *bond = __get_bond_by_port(port);
 
-	if (bond == NULL) {
+	if (bond == NULL)
 		return 0;
-	}
 
 	return BOND_AD_INFO(bond).agg_select_timer ? 1 : 0;
 }
@@ -328,9 +320,9 @@
 	 * link down, it sets the speed to 0.
 	 * This is done in spite of the fact that the e100 driver reports 0 to be
 	 * compatible with MVT in the future.*/
-	if (slave->link != BOND_LINK_UP) {
-		speed=0;
-	} else {
+	if (slave->link != BOND_LINK_UP)
+		speed = 0;
+	else {
 		switch (slave->speed) {
 		case SPEED_10:
 			speed = AD_LINK_SPEED_BITMASK_10MBPS;
@@ -375,18 +367,18 @@
 
 	//  handling a special case: when the configuration starts with
 	// link down, it sets the duplex to 0.
-	if (slave->link != BOND_LINK_UP) {
-		retval=0x0;
-	} else {
+	if (slave->link != BOND_LINK_UP)
+		retval = 0x0;
+	else {
 		switch (slave->duplex) {
 		case DUPLEX_FULL:
-			retval=0x1;
+			retval = 0x1;
 			pr_debug("Port %d Received status full duplex update from adapter\n",
 				 port->actor_port_number);
 			break;
 		case DUPLEX_HALF:
 		default:
-			retval=0x0;
+			retval = 0x0;
 			pr_debug("Port %d Received status NOT full duplex update from adapter\n",
 				 port->actor_port_number);
 			break;
@@ -419,15 +411,14 @@
  */
 static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
 {
-	u16 retval=0;	 //to silence the compiler
+	u16 retval = 0; /* to silence the compiler */
 
 	switch (timer_type) {
 	case AD_CURRENT_WHILE_TIMER:   // for rx machine usage
-		if (par) {	      // for short or long timeout
+		if (par)
 			retval = (AD_SHORT_TIMEOUT_TIME*ad_ticks_per_sec); // short timeout
-		} else {
+		else
 			retval = (AD_LONG_TIMEOUT_TIME*ad_ticks_per_sec); // long timeout
-		}
 		break;
 	case AD_ACTOR_CHURN_TIMER:	    // for local churn machine
 		retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec);
@@ -519,11 +510,11 @@
 		port->actor_oper_port_state &= ~AD_STATE_DEFAULTED;
 
 		// set the partner sync. to on if the partner is sync. and the port is matched
-		if ((port->sm_vars & AD_PORT_MATCHED) && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) {
+		if ((port->sm_vars & AD_PORT_MATCHED)
+		    && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION))
 			partner->port_state |= AD_STATE_SYNCHRONIZATION;
-		} else {
+		else
 			partner->port_state &= ~AD_STATE_SYNCHRONIZATION;
-		}
 	}
 }
 
@@ -653,7 +644,7 @@
  */
 static void __attach_bond_to_agg(struct port *port)
 {
-	port=NULL; // just to satisfy the compiler
+	port = NULL; /* just to satisfy the compiler */
 	// This function does nothing since the parser/multiplexer of the receive
 	// and the parser/multiplexer of the aggregator are already combined
 }
@@ -668,7 +659,7 @@
  */
 static void __detach_bond_from_agg(struct port *port)
 {
-	port=NULL; // just to satisfy the compiler
+	port = NULL; /* just to satisfy the compiler */
 	// This function does nothing sience the parser/multiplexer of the receive
 	// and the parser/multiplexer of the aggregator are already combined
 }
@@ -685,7 +676,9 @@
 
 	if (aggregator) {
 		// scan all ports in this aggregator to verfy if they are all ready
-		for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
+		for (port = aggregator->lag_ports;
+		     port;
+		     port = port->next_port_in_aggregator) {
 			if (!(port->sm_vars & AD_PORT_READY_N)) {
 				retval = 0;
 				break;
@@ -706,12 +699,12 @@
 {
 	struct port *port;
 
-	for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
-		if (val) {
+	for (port = aggregator->lag_ports; port;
+	     port = port->next_port_in_aggregator) {
+		if (val)
 			port->sm_vars |= AD_PORT_READY;
-		} else {
+		else
 			port->sm_vars &= ~AD_PORT_READY;
-		}
 	}
 }
 
@@ -722,7 +715,7 @@
  */
 static u32 __get_agg_bandwidth(struct aggregator *aggregator)
 {
-	u32 bandwidth=0;
+	u32 bandwidth = 0;
 	u32 basic_speed;
 
 	if (aggregator->num_of_ports) {
@@ -744,7 +737,7 @@
 			bandwidth = aggregator->num_of_ports * 10000;
 			break;
 		default:
-			bandwidth=0; // to silent the compilor ....
+			bandwidth = 0; /*to silence the compiler ....*/
 		}
 	}
 	return bandwidth;
@@ -835,9 +828,8 @@
 	int length = sizeof(struct lacpdu_header);
 
 	skb = dev_alloc_skb(length);
-	if (!skb) {
+	if (!skb)
 		return -ENOMEM;
-	}
 
 	skb->dev = slave->dev;
 	skb_reset_mac_header(skb);
@@ -876,9 +868,8 @@
 	int length = sizeof(struct bond_marker_header);
 
 	skb = dev_alloc_skb(length + 16);
-	if (!skb) {
+	if (!skb)
 		return -ENOMEM;
-	}
 
 	skb_reserve(skb, 16);
 
@@ -919,9 +910,10 @@
 	} else {
 		switch (port->sm_mux_state) {
 		case AD_MUX_DETACHED:
-			if ((port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) { // if SELECTED or STANDBY
+			if ((port->sm_vars & AD_PORT_SELECTED)
+			    || (port->sm_vars & AD_PORT_STANDBY))
+				/* if SELECTED or STANDBY */
 				port->sm_mux_state = AD_MUX_WAITING; // next state
-			}
 			break;
 		case AD_MUX_WAITING:
 			// if SELECTED == FALSE return to DETACH state
@@ -935,18 +927,18 @@
 			}
 
 			// check if the wait_while_timer expired
-			if (port->sm_mux_timer_counter && !(--port->sm_mux_timer_counter)) {
+			if (port->sm_mux_timer_counter
+			    && !(--port->sm_mux_timer_counter))
 				port->sm_vars |= AD_PORT_READY_N;
-			}
 
 			// in order to withhold the selection logic to check all ports READY_N value
 			// every callback cycle to update ready variable, we check READY_N and update READY here
 			__set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
 
 			// if the wait_while_timer expired, and the port is in READY state, move to ATTACHED state
-			if ((port->sm_vars & AD_PORT_READY) && !port->sm_mux_timer_counter) {
+			if ((port->sm_vars & AD_PORT_READY)
+			    && !port->sm_mux_timer_counter)
 				port->sm_mux_state = AD_MUX_ATTACHED;	 // next state
-			}
 			break;
 		case AD_MUX_ATTACHED:
 			// check also if agg_select_timer expired(so the edable port will take place only after this timer)
@@ -1041,13 +1033,14 @@
 
 	// check if state machine should change state
 	// first, check if port was reinitialized
-	if (port->sm_vars & AD_PORT_BEGIN) {
-		port->sm_rx_state = AD_RX_INITIALIZE;		    // next state
-	}
+	if (port->sm_vars & AD_PORT_BEGIN)
+		/* next state */
+		port->sm_rx_state = AD_RX_INITIALIZE;
 	// check if port is not enabled
-	else if (!(port->sm_vars & AD_PORT_BEGIN) && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED)) {
-		port->sm_rx_state = AD_RX_PORT_DISABLED;	    // next state
-	}
+	else if (!(port->sm_vars & AD_PORT_BEGIN)
+		 && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED))
+		/* next state */
+		port->sm_rx_state = AD_RX_PORT_DISABLED;
 	// check if new lacpdu arrived
 	else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || (port->sm_rx_state == AD_RX_DEFAULTED) || (port->sm_rx_state == AD_RX_CURRENT))) {
 		port->sm_rx_timer_counter = 0; // zero timer
@@ -1069,13 +1062,16 @@
 			// if no lacpdu arrived and no timer is on
 			switch (port->sm_rx_state) {
 			case AD_RX_PORT_DISABLED:
-				if (port->sm_vars & AD_PORT_MOVED) {
+				if (port->sm_vars & AD_PORT_MOVED)
 					port->sm_rx_state = AD_RX_INITIALIZE;	    // next state
-				} else if (port->is_enabled && (port->sm_vars & AD_PORT_LACP_ENABLED)) {
+				else if (port->is_enabled
+					 && (port->sm_vars
+					     & AD_PORT_LACP_ENABLED))
 					port->sm_rx_state = AD_RX_EXPIRED;	// next state
-				} else if (port->is_enabled && ((port->sm_vars & AD_PORT_LACP_ENABLED) == 0)) {
+				else if (port->is_enabled
+					 && ((port->sm_vars
+					      & AD_PORT_LACP_ENABLED) == 0))
 					port->sm_rx_state = AD_RX_LACP_DISABLED;    // next state
-				}
 				break;
 			default:    //to silence the compiler
 				break;
@@ -1091,11 +1087,10 @@
 			 port->sm_rx_state);
 		switch (port->sm_rx_state) {
 		case AD_RX_INITIALIZE:
-			if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
+			if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS))
 				port->sm_vars &= ~AD_PORT_LACP_ENABLED;
-			} else {
+			else
 				port->sm_vars |= AD_PORT_LACP_ENABLED;
-			}
 			port->sm_vars &= ~AD_PORT_SELECTED;
 			__record_default(port);
 			port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
@@ -1149,9 +1144,10 @@
 			// verify that if the aggregator is enabled, the port is enabled too.
 			//(because if the link goes down for a short time, the 802.3ad will not
 			// catch it, and the port will continue to be disabled)
-			if (port->aggregator && port->aggregator->is_active && !__port_is_enabled(port)) {
+			if (port->aggregator
+			    && port->aggregator->is_active
+			    && !__port_is_enabled(port))
 				__enable_port(port);
-			}
 			break;
 		default:    //to silence the compiler
 			break;
@@ -1183,7 +1179,8 @@
 			}
 		}
 		// restart tx timer(to verify that we will not exceed AD_MAX_TX_IN_SECOND
-		port->sm_tx_timer_counter=ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
+		port->sm_tx_timer_counter =
+			ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
 	}
 }
 
@@ -1216,9 +1213,9 @@
 			// If not expired, check if there is some new timeout parameter from the partner state
 			switch (port->sm_periodic_state) {
 			case AD_FAST_PERIODIC:
-				if (!(port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
+				if (!(port->partner_oper.port_state
+				      & AD_STATE_LACP_TIMEOUT))
 					port->sm_periodic_state = AD_SLOW_PERIODIC;  // next state
-				}
 				break;
 			case AD_SLOW_PERIODIC:
 				if ((port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
@@ -1237,11 +1234,11 @@
 			port->sm_periodic_state = AD_FAST_PERIODIC;	 // next state
 			break;
 		case AD_PERIODIC_TX:
-			if (!(port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
+			if (!(port->partner_oper.port_state
+			      & AD_STATE_LACP_TIMEOUT))
 				port->sm_periodic_state = AD_SLOW_PERIODIC;  // next state
-			} else {
+			else
 				port->sm_periodic_state = AD_FAST_PERIODIC;  // next state
-			}
 			break;
 		default:    //to silence the compiler
 			break;
@@ -1287,35 +1284,37 @@
 	int found = 0;
 
 	// if the port is already Selected, do nothing
-	if (port->sm_vars & AD_PORT_SELECTED) {
+	if (port->sm_vars & AD_PORT_SELECTED)
 		return;
-	}
 
 	// if the port is connected to other aggregator, detach it
 	if (port->aggregator) {
 		// detach the port from its former aggregator
-		temp_aggregator=port->aggregator;
-		for (curr_port=temp_aggregator->lag_ports; curr_port; last_port=curr_port, curr_port=curr_port->next_port_in_aggregator) {
+		temp_aggregator = port->aggregator;
+		for (curr_port = temp_aggregator->lag_ports; curr_port;
+		     last_port = curr_port,
+			     curr_port = curr_port->next_port_in_aggregator) {
 			if (curr_port == port) {
 				temp_aggregator->num_of_ports--;
 				if (!last_port) {// if it is the first port attached to the aggregator
-					temp_aggregator->lag_ports=port->next_port_in_aggregator;
+					temp_aggregator->lag_ports =
+						port->next_port_in_aggregator;
 				} else {// not the first port attached to the aggregator
-					last_port->next_port_in_aggregator=port->next_port_in_aggregator;
+					last_port->next_port_in_aggregator =
+						port->next_port_in_aggregator;
 				}
 
 				// clear the port's relations to this aggregator
 				port->aggregator = NULL;
-				port->next_port_in_aggregator=NULL;
-				port->actor_port_aggregator_identifier=0;
+				port->next_port_in_aggregator = NULL;
+				port->actor_port_aggregator_identifier = 0;
 
 				pr_debug("Port %d left LAG %d\n",
 					 port->actor_port_number,
 					 temp_aggregator->aggregator_identifier);
 				// if the aggregator is empty, clear its parameters, and set it ready to be attached
-				if (!temp_aggregator->lag_ports) {
+				if (!temp_aggregator->lag_ports)
 					ad_clear_agg(temp_aggregator);
-				}
 				break;
 			}
 		}
@@ -1333,9 +1332,8 @@
 
 		// keep a free aggregator for later use(if needed)
 		if (!aggregator->lag_ports) {
-			if (!free_aggregator) {
-				free_aggregator=aggregator;
-			}
+			if (!free_aggregator)
+				free_aggregator = aggregator;
 			continue;
 		}
 		// check if current aggregator suits us
@@ -1350,10 +1348,11 @@
 		   ) {
 			// attach to the founded aggregator
 			port->aggregator = aggregator;
-			port->actor_port_aggregator_identifier=port->aggregator->aggregator_identifier;
-			port->next_port_in_aggregator=aggregator->lag_ports;
+			port->actor_port_aggregator_identifier =
+				port->aggregator->aggregator_identifier;
+			port->next_port_in_aggregator = aggregator->lag_ports;
 			port->aggregator->num_of_ports++;
-			aggregator->lag_ports=port;
+			aggregator->lag_ports = port;
 			pr_debug("Port %d joined LAG %d(existing LAG)\n",
 				 port->actor_port_number,
 				 port->aggregator->aggregator_identifier);
@@ -1370,20 +1369,23 @@
 		if (free_aggregator) {
 			// assign port a new aggregator
 			port->aggregator = free_aggregator;
-			port->actor_port_aggregator_identifier=port->aggregator->aggregator_identifier;
+			port->actor_port_aggregator_identifier =
+				port->aggregator->aggregator_identifier;
 
 			// update the new aggregator's parameters
 			// if port was responsed from the end-user
-			if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS) {// if port is full duplex
+			if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)
+				/* if port is full duplex */
 				port->aggregator->is_individual = false;
-			} else {
+			else
 				port->aggregator->is_individual = true;
-			}
 
 			port->aggregator->actor_admin_aggregator_key = port->actor_admin_port_key;
 			port->aggregator->actor_oper_aggregator_key = port->actor_oper_port_key;
-			port->aggregator->partner_system=port->partner_oper.system;
-			port->aggregator->partner_system_priority = port->partner_oper.system_priority;
+			port->aggregator->partner_system =
+				port->partner_oper.system;
+			port->aggregator->partner_system_priority =
+				port->partner_oper.system_priority;
 			port->aggregator->partner_oper_aggregator_key = port->partner_oper.key;
 			port->aggregator->receive_state = 1;
 			port->aggregator->transmit_state = 1;
@@ -1704,9 +1706,8 @@
 		port->actor_admin_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
 		port->actor_oper_port_state  = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
 
-		if (lacp_fast) {
+		if (lacp_fast)
 			port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
-		}
 
 		memcpy(&port->partner_admin, &tmpl, sizeof(tmpl));
 		memcpy(&port->partner_oper, &tmpl, sizeof(tmpl));
@@ -1785,13 +1786,16 @@
 	marker.requester_port = (((port->actor_port_number & 0xFF) << 8) |((u16)(port->actor_port_number & 0xFF00) >> 8));
 	marker.requester_system = port->actor_system;
 	// convert requester_port(u32) to Big Endian
-	marker.requester_transaction_id = (((++port->transaction_id & 0xFF) << 24) |((port->transaction_id & 0xFF00) << 8) |((port->transaction_id & 0xFF0000) >> 8) |((port->transaction_id & 0xFF000000) >> 24));
+	marker.requester_transaction_id =
+		(((++port->transaction_id & 0xFF) << 24)
+		 | ((port->transaction_id & 0xFF00) << 8)
+		 | ((port->transaction_id & 0xFF0000) >> 8)
+		 | ((port->transaction_id & 0xFF000000) >> 24));
 	marker.pad = 0;
 	marker.tlv_type_terminator = 0x00;
 	marker.terminator_length = 0x00;
-	for (index=0; index<90; index++) {
-		marker.reserved_90[index]=0;
-	}
+	for (index = 0; index < 90; index++)
+		marker.reserved_90[index] = 0;
 
 	// send the marker information
 	if (ad_marker_send(port, &marker) >= 0) {
@@ -1816,7 +1820,7 @@
 	//marker = *marker_info;
 	memcpy(&marker, marker_info, sizeof(struct bond_marker));
 	// change the marker subtype to marker response
-	marker.tlv_type=AD_MARKER_RESPONSE_SUBTYPE;
+	marker.tlv_type = AD_MARKER_RESPONSE_SUBTYPE;
 	// send the marker response
 
 	if (ad_marker_send(port, &marker) >= 0) {
@@ -1837,8 +1841,8 @@
 static void ad_marker_response_received(struct bond_marker *marker,
 	struct port *port)
 {
-	marker=NULL; // just to satisfy the compiler
-	port=NULL;  // just to satisfy the compiler
+	marker = NULL; /* just to satisfy the compiler */
+	port = NULL;  /* just to satisfy the compiler */
 	// DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW
 }
 
@@ -1932,9 +1936,8 @@
 		port->actor_admin_port_key |= (__get_link_speed(port) << 1);
 		port->actor_oper_port_key = port->actor_admin_port_key;
 		// if the port is not full duplex, then the port should be not lacp Enabled
-		if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
+		if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS))
 			port->sm_vars &= ~AD_PORT_LACP_ENABLED;
-		}
 		// actor system is the bond's system
 		port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr;
 		// tx timer(to verify that no more than MAX_TX_IN_SECOND lacpdu's are sent in one second)
@@ -2006,9 +2009,10 @@
 			new_aggregator = __get_first_agg(port);
 			for (; new_aggregator; new_aggregator = __get_next_agg(new_aggregator)) {
 				// if the new aggregator is empty, or it is connected to our port only
-				if (!new_aggregator->lag_ports || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator)) {
+				if (!new_aggregator->lag_ports
+				    || ((new_aggregator->lag_ports == port)
+					&& !new_aggregator->lag_ports->next_port_in_aggregator))
 					break;
-				}
 			}
 			// if new aggregator found, copy the aggregator's parameters
 			// and connect the related lag_ports to the new aggregator
@@ -2037,17 +2041,17 @@
 				new_aggregator->num_of_ports = aggregator->num_of_ports;
 
 				// update the information that is written on the ports about the aggregator
-				for (temp_port=aggregator->lag_ports; temp_port; temp_port=temp_port->next_port_in_aggregator) {
-					temp_port->aggregator=new_aggregator;
+				for (temp_port = aggregator->lag_ports; temp_port;
+				     temp_port = temp_port->next_port_in_aggregator) {
+					temp_port->aggregator = new_aggregator;
 					temp_port->actor_port_aggregator_identifier = new_aggregator->aggregator_identifier;
 				}
 
 				// clear the aggregator
 				ad_clear_agg(aggregator);
 
-				if (select_new_active_agg) {
+				if (select_new_active_agg)
 					ad_agg_selection_logic(__get_first_agg(port));
-				}
 			} else {
 				pr_warning("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n",
 					   slave->dev->master->name);
@@ -2071,15 +2075,16 @@
 	for (; temp_aggregator; temp_aggregator = __get_next_agg(temp_aggregator)) {
 		prev_port = NULL;
 		// search the port in the aggregator's related ports
-		for (temp_port=temp_aggregator->lag_ports; temp_port; prev_port=temp_port, temp_port=temp_port->next_port_in_aggregator) {
+		for (temp_port = temp_aggregator->lag_ports; temp_port;
+		     prev_port = temp_port,
+			     temp_port = temp_port->next_port_in_aggregator) {
 			if (temp_port == port) { // the aggregator found - detach the port from this aggregator
-				if (prev_port) {
+				if (prev_port)
 					prev_port->next_port_in_aggregator = temp_port->next_port_in_aggregator;
-				} else {
+				else
 					temp_aggregator->lag_ports = temp_port->next_port_in_aggregator;
-				}
 				temp_aggregator->num_of_ports--;
-				if (temp_aggregator->num_of_ports==0) {
+				if (temp_aggregator->num_of_ports == 0) {
 					select_new_active_agg = temp_aggregator->is_active;
 					// clear the aggregator
 					ad_clear_agg(temp_aggregator);
@@ -2094,7 +2099,7 @@
 			}
 		}
 	}
-	port->slave=NULL;
+	port->slave = NULL;
 }
 
 /**
@@ -2119,14 +2124,12 @@
 
 	read_lock(&bond->lock);
 
-	if (bond->kill_timers) {
+	if (bond->kill_timers)
 		goto out;
-	}
 
 	//check if there are any slaves
-	if (bond->slave_cnt == 0) {
+	if (bond->slave_cnt == 0)
 		goto re_arm;
-	}
 
 	// check if agg_select_timer timer after initialize is timed out
 	if (BOND_AD_INFO(bond).agg_select_timer && !(--BOND_AD_INFO(bond).agg_select_timer)) {
@@ -2159,9 +2162,8 @@
 		ad_tx_machine(port);
 
 		// turn off the BEGIN bit, since we already handled it
-		if (port->sm_vars & AD_PORT_BEGIN) {
+		if (port->sm_vars & AD_PORT_BEGIN)
 			port->sm_vars &= ~AD_PORT_BEGIN;
-		}
 	}
 
 re_arm:
@@ -2245,7 +2247,8 @@
 	}
 
 	port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
-	port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
+	port->actor_oper_port_key = port->actor_admin_port_key |=
+		(__get_link_speed(port) << 1);
 	pr_debug("Port %d changed speed\n", port->actor_port_number);
 	// there is no need to reselect a new aggregator, just signal the
 	// state machines to reinitialize
@@ -2262,7 +2265,7 @@
 {
 	struct port *port;
 
-	port=&(SLAVE_AD_INFO(slave).port);
+	port = &(SLAVE_AD_INFO(slave).port);
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
@@ -2272,7 +2275,8 @@
 	}
 
 	port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
-	port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
+	port->actor_oper_port_key = port->actor_admin_port_key |=
+		__get_duplex(port);
 	pr_debug("Port %d changed duplex\n", port->actor_port_number);
 	// there is no need to reselect a new aggregator, just signal the
 	// state machines to reinitialize
@@ -2304,14 +2308,17 @@
 	if (link == BOND_LINK_UP) {
 		port->is_enabled = true;
 		port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
-		port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
+		port->actor_oper_port_key = port->actor_admin_port_key |=
+			__get_duplex(port);
 		port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
-		port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
+		port->actor_oper_port_key = port->actor_admin_port_key |=
+			(__get_link_speed(port) << 1);
 	} else {
 		/* link has failed */
 		port->is_enabled = false;
 		port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
-		port->actor_oper_port_key= (port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS);
+		port->actor_oper_port_key = (port->actor_admin_port_key &=
+					     ~AD_SPEED_KEY_BITS);
 	}
 	//BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN")));
 	// there is no need to reselect a new aggregator, just signal the
@@ -2394,9 +2401,8 @@
 	 */
 	read_lock(&bond->lock);
 
-	if (!BOND_IS_OK(bond)) {
+	if (!BOND_IS_OK(bond))
 		goto out;
-	}
 
 	if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
 		pr_debug("%s: Error: bond_3ad_get_active_agg_info failed\n",
@@ -2420,9 +2426,8 @@
 
 		if (agg && (agg->aggregator_identifier == agg_id)) {
 			slave_agg_no--;
-			if (slave_agg_no < 0) {
+			if (slave_agg_no < 0)
 				break;
-			}
 		}
 	}
 
@@ -2438,9 +2443,8 @@
 		int slave_agg_id = 0;
 		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
 
-		if (agg) {
+		if (agg)
 			slave_agg_id = agg->aggregator_identifier;
-		}
 
 		if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
 			res = bond_dev_queue_xmit(bond, skb, slave->dev);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 3b16f62..beb3b7c 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -76,6 +76,7 @@
 #include <linux/if_vlan.h>
 #include <linux/if_bonding.h>
 #include <linux/jiffies.h>
+#include <linux/preempt.h>
 #include <net/route.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
@@ -109,6 +110,7 @@
 static char *fail_over_mac;
 static int all_slaves_active = 0;
 static struct bond_params bonding_defaults;
+static int resend_igmp = BOND_DEFAULT_RESEND_IGMP;
 
 module_param(max_bonds, int, 0);
 MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
@@ -163,9 +165,15 @@
 MODULE_PARM_DESC(all_slaves_active, "Keep all frames received on an interface"
 				     "by setting active flag for all slaves.  "
 				     "0 for never (default), 1 for always.");
+module_param(resend_igmp, int, 0);
+MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on link failure");
 
 /*----------------------------- Global variables ----------------------------*/
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+cpumask_var_t netpoll_block_tx;
+#endif
+
 static const char * const version =
 	DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
 
@@ -176,9 +184,6 @@
 static int bond_mode	= BOND_MODE_ROUNDROBIN;
 static int xmit_hashtype = BOND_XMIT_POLICY_LAYER2;
 static int lacp_fast;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static int disable_netpoll = 1;
-#endif
 
 const struct bond_parm_tbl bond_lacp_tbl[] = {
 {	"slow",		AD_LACP_SLOW},
@@ -307,6 +312,7 @@
 
 	pr_debug("bond: %s, vlan id %d\n", bond->dev->name, vlan_id);
 
+	block_netpoll_tx();
 	write_lock_bh(&bond->lock);
 
 	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
@@ -341,6 +347,7 @@
 
 out:
 	write_unlock_bh(&bond->lock);
+	unblock_netpoll_tx();
 	return res;
 }
 
@@ -446,11 +453,9 @@
 	if (unlikely(bond->dev->priv_flags & IFF_IN_NETPOLL)) {
 		struct netpoll *np = bond->dev->npinfo->netpoll;
 		slave_dev->npinfo = bond->dev->npinfo;
-		np->real_dev = np->dev = skb->dev;
 		slave_dev->priv_flags |= IFF_IN_NETPOLL;
-		netpoll_send_skb(np, skb);
+		netpoll_send_skb_on_dev(np, skb, slave_dev);
 		slave_dev->priv_flags &= ~IFF_IN_NETPOLL;
-		np->dev = bond->dev;
 	} else
 #endif
 		dev_queue_xmit(skb);
@@ -865,6 +870,21 @@
 }
 
 
+static void __bond_resend_igmp_join_requests(struct net_device *dev)
+{
+	struct in_device *in_dev;
+	struct ip_mc_list *im;
+
+	rcu_read_lock();
+	in_dev = __in_dev_get_rcu(dev);
+	if (in_dev) {
+		for (im = in_dev->mc_list; im; im = im->next)
+			ip_mc_rejoin_group(im);
+	}
+
+	rcu_read_unlock();
+}
+
 /*
  * Retrieve the list of registered multicast addresses for the bonding
  * device and retransmit an IGMP JOIN request to the current active
@@ -872,17 +892,35 @@
  */
 static void bond_resend_igmp_join_requests(struct bonding *bond)
 {
-	struct in_device *in_dev;
-	struct ip_mc_list *im;
+	struct net_device *vlan_dev;
+	struct vlan_entry *vlan;
 
-	rcu_read_lock();
-	in_dev = __in_dev_get_rcu(bond->dev);
-	if (in_dev) {
-		for (im = in_dev->mc_list; im; im = im->next)
-			ip_mc_rejoin_group(im);
+	read_lock(&bond->lock);
+
+	/* rejoin all groups on bond device */
+	__bond_resend_igmp_join_requests(bond->dev);
+
+	/* rejoin all groups on vlan devices */
+	if (bond->vlgrp) {
+		list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+			vlan_dev = vlan_group_get_device(bond->vlgrp,
+							 vlan->vlan_id);
+			if (vlan_dev)
+				__bond_resend_igmp_join_requests(vlan_dev);
+		}
 	}
 
-	rcu_read_unlock();
+	if (--bond->igmp_retrans > 0)
+		queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5);
+
+	read_unlock(&bond->lock);
+}
+
+static void bond_resend_igmp_join_requests_delayed(struct work_struct *work)
+{
+	struct bonding *bond = container_of(work, struct bonding,
+							mcast_work.work);
+	bond_resend_igmp_join_requests(bond);
 }
 
 /*
@@ -944,7 +982,6 @@
 
 		netdev_for_each_mc_addr(ha, bond->dev)
 			dev_mc_add(new_active->dev, ha->addr);
-		bond_resend_igmp_join_requests(bond);
 	}
 }
 
@@ -1180,9 +1217,12 @@
 		}
 	}
 
-	/* resend IGMP joins since all were sent on curr_active_slave */
-	if (bond->params.mode == BOND_MODE_ROUNDROBIN) {
-		bond_resend_igmp_join_requests(bond);
+	/* resend IGMP joins since active slave has changed or
+	 * all were sent on curr_active_slave */
+	if ((USES_PRIMARY(bond->params.mode) && new_active) ||
+	    bond->params.mode == BOND_MODE_ROUNDROBIN) {
+		bond->igmp_retrans = bond->params.resend_igmp;
+		queue_delayed_work(bond->wq, &bond->mcast_work, 0);
 	}
 }
 
@@ -1294,9 +1334,14 @@
 
 static void bond_poll_controller(struct net_device *bond_dev)
 {
-	struct net_device *dev = bond_dev->npinfo->netpoll->real_dev;
-	if (dev != bond_dev)
-		netpoll_poll_dev(dev);
+	struct bonding *bond = netdev_priv(bond_dev);
+	struct slave *slave;
+	int i;
+
+	bond_for_each_slave(bond, slave, i) {
+		if (slave->dev && IS_UP(slave->dev))
+			netpoll_poll_dev(slave->dev);
+	}
 }
 
 static void bond_netpoll_cleanup(struct net_device *bond_dev)
@@ -1763,23 +1808,15 @@
 	bond_set_carrier(bond);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	/*
-	 * Netpoll and bonding is broken, make sure it is not initialized
-	 * until it is fixed.
-	 */
-	if (disable_netpoll) {
+	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;
-	} else {
-		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);
-		}
+		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);
 	}
 #endif
 	read_unlock(&bond->lock);
@@ -1851,6 +1888,7 @@
 		return -EINVAL;
 	}
 
+	block_netpoll_tx();
 	netdev_bonding_change(bond_dev, NETDEV_BONDING_DESLAVE);
 	write_lock_bh(&bond->lock);
 
@@ -1860,6 +1898,7 @@
 		pr_info("%s: %s not enslaved\n",
 			bond_dev->name, slave_dev->name);
 		write_unlock_bh(&bond->lock);
+		unblock_netpoll_tx();
 		return -EINVAL;
 	}
 
@@ -1953,6 +1992,7 @@
 	}
 
 	write_unlock_bh(&bond->lock);
+	unblock_netpoll_tx();
 
 	/* must do this from outside any spinlocks */
 	bond_destroy_slave_symlinks(bond_dev, slave_dev);
@@ -1983,10 +2023,8 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	read_lock_bh(&bond->lock);
 
-	 /* Make sure netpoll over stays disabled until fixed. */
-	if (!disable_netpoll)
-		if (slaves_support_netpoll(bond_dev))
-				bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+	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);
@@ -2019,8 +2057,8 @@
 * First release a slave and than destroy the bond if no more slaves are left.
 * Must be under rtnl_lock when this function is called.
 */
-int  bond_release_and_destroy(struct net_device *bond_dev,
-			      struct net_device *slave_dev)
+static int  bond_release_and_destroy(struct net_device *bond_dev,
+				     struct net_device *slave_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	int ret;
@@ -2142,7 +2180,6 @@
 
 out:
 	write_unlock_bh(&bond->lock);
-
 	return 0;
 }
 
@@ -2191,9 +2228,11 @@
 	    (old_active) &&
 	    (new_active->link == BOND_LINK_UP) &&
 	    IS_UP(new_active->dev)) {
+		block_netpoll_tx();
 		write_lock_bh(&bond->curr_slave_lock);
 		bond_change_active_slave(bond, new_active);
 		write_unlock_bh(&bond->curr_slave_lock);
+		unblock_netpoll_tx();
 	} else
 		res = -EINVAL;
 
@@ -2368,8 +2407,11 @@
 				slave->state = BOND_STATE_BACKUP;
 			}
 
-			pr_info("%s: link status definitely up for interface %s.\n",
-				bond->dev->name, slave->dev->name);
+			bond_update_speed_duplex(slave);
+
+			pr_info("%s: link status definitely up for interface %s, %d Mbps %s duplex.\n",
+				bond->dev->name, slave->dev->name,
+				slave->speed, slave->duplex ? "full" : "half");
 
 			/* notify ad that the link status has changed */
 			if (bond->params.mode == BOND_MODE_8023AD)
@@ -2422,9 +2464,11 @@
 
 do_failover:
 		ASSERT_RTNL();
+		block_netpoll_tx();
 		write_lock_bh(&bond->curr_slave_lock);
 		bond_select_active_slave(bond);
 		write_unlock_bh(&bond->curr_slave_lock);
+		unblock_netpoll_tx();
 	}
 
 	bond_set_carrier(bond);
@@ -2867,11 +2911,13 @@
 	}
 
 	if (do_failover) {
+		block_netpoll_tx();
 		write_lock_bh(&bond->curr_slave_lock);
 
 		bond_select_active_slave(bond);
 
 		write_unlock_bh(&bond->curr_slave_lock);
+		unblock_netpoll_tx();
 	}
 
 re_arm:
@@ -3030,9 +3076,11 @@
 
 do_failover:
 		ASSERT_RTNL();
+		block_netpoll_tx();
 		write_lock_bh(&bond->curr_slave_lock);
 		bond_select_active_slave(bond);
 		write_unlock_bh(&bond->curr_slave_lock);
+		unblock_netpoll_tx();
 	}
 
 	bond_set_carrier(bond);
@@ -3312,6 +3360,8 @@
 	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);
 
@@ -3744,6 +3794,8 @@
 
 	bond->kill_timers = 0;
 
+	INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed);
+
 	if (bond_is_lb(bond)) {
 		/* bond_alb_initialize must be called before the timer
 		 * is started.
@@ -3828,6 +3880,8 @@
 		break;
 	}
 
+	if (delayed_work_pending(&bond->mcast_work))
+		cancel_delayed_work(&bond->mcast_work);
 
 	if (bond_is_lb(bond)) {
 		/* Must be called only after all
@@ -4514,6 +4568,13 @@
 {
 	struct bonding *bond = netdev_priv(dev);
 
+	/*
+	 * If we risk deadlock from transmitting this in the
+	 * netpoll path, tell netpoll to queue the frame for later tx
+	 */
+	if (is_netpoll_tx_blocked(dev))
+		return NETDEV_TX_BUSY;
+
 	if (TX_QUEUE_OVERRIDE(bond->params.mode)) {
 		if (!bond_slave_override(bond, skb))
 			return NETDEV_TX_OK;
@@ -4678,6 +4739,10 @@
 			       NETIF_F_HW_VLAN_RX |
 			       NETIF_F_HW_VLAN_FILTER);
 
+	/* By default, we enable GRO on bonding devices.
+	 * Actual support requires lowlevel drivers are GRO ready.
+	 */
+	bond_dev->features |= NETIF_F_GRO;
 }
 
 static void bond_work_cancel_all(struct bonding *bond)
@@ -4699,6 +4764,9 @@
 	if (bond->params.mode == BOND_MODE_8023AD &&
 	    delayed_work_pending(&bond->ad_work))
 		cancel_delayed_work(&bond->ad_work);
+
+	if (delayed_work_pending(&bond->mcast_work))
+		cancel_delayed_work(&bond->mcast_work);
 }
 
 /*
@@ -4891,6 +4959,13 @@
 		all_slaves_active = 0;
 	}
 
+	if (resend_igmp < 0 || resend_igmp > 255) {
+		pr_warning("Warning: resend_igmp (%d) should be between "
+			   "0 and 255, resetting to %d\n",
+			   resend_igmp, BOND_DEFAULT_RESEND_IGMP);
+		resend_igmp = BOND_DEFAULT_RESEND_IGMP;
+	}
+
 	/* reset values for TLB/ALB */
 	if ((bond_mode == BOND_MODE_TLB) ||
 	    (bond_mode == BOND_MODE_ALB)) {
@@ -5063,6 +5138,7 @@
 	params->fail_over_mac = fail_over_mac_value;
 	params->tx_queues = tx_queues;
 	params->all_slaves_active = all_slaves_active;
+	params->resend_igmp = resend_igmp;
 
 	if (primary) {
 		strncpy(params->primary, primary, IFNAMSIZ);
@@ -5164,6 +5240,15 @@
 		res = dev_alloc_name(bond_dev, "bond%d");
 		if (res < 0)
 			goto out;
+	} else {
+		/*
+		 * If we're given a name to register
+		 * we need to ensure that its not already
+		 * registered
+		 */
+		res = -EEXIST;
+		if (__dev_get_by_name(net, name) != NULL)
+			goto out;
 	}
 
 	res = register_netdevice(bond_dev);
@@ -5212,6 +5297,13 @@
 	if (res)
 		goto out;
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	if (!alloc_cpumask_var(&netpoll_block_tx, GFP_KERNEL)) {
+		res = -ENOMEM;
+		goto out;
+	}
+#endif
+
 	res = register_pernet_subsys(&bond_net_ops);
 	if (res)
 		goto out;
@@ -5230,6 +5322,7 @@
 	if (res)
 		goto err;
 
+
 	register_netdevice_notifier(&bond_netdev_notifier);
 	register_inetaddr_notifier(&bond_inetaddr_notifier);
 	bond_register_ipv6_notifier();
@@ -5239,6 +5332,9 @@
 	rtnl_link_unregister(&bond_link_ops);
 err_link:
 	unregister_pernet_subsys(&bond_net_ops);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	free_cpumask_var(netpoll_block_tx);
+#endif
 	goto out;
 
 }
@@ -5253,6 +5349,10 @@
 
 	rtnl_link_unregister(&bond_link_ops);
 	unregister_pernet_subsys(&bond_net_ops);
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	free_cpumask_var(netpoll_block_tx);
+#endif
 }
 
 module_init(bonding_init);
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index c311aed..8fd0174 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1066,6 +1066,7 @@
 
 	if (!rtnl_trylock())
 		return restart_syscall();
+	block_netpoll_tx();
 	read_lock(&bond->lock);
 	write_lock_bh(&bond->curr_slave_lock);
 
@@ -1101,6 +1102,7 @@
 out:
 	write_unlock_bh(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
+	unblock_netpoll_tx();
 	rtnl_unlock();
 
 	return count;
@@ -1146,11 +1148,13 @@
 		bond->dev->name, pri_reselect_tbl[new_value].modename,
 		new_value);
 
+	block_netpoll_tx();
 	read_lock(&bond->lock);
 	write_lock_bh(&bond->curr_slave_lock);
 	bond_select_active_slave(bond);
 	write_unlock_bh(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
+	unblock_netpoll_tx();
 out:
 	rtnl_unlock();
 	return ret;
@@ -1232,6 +1236,8 @@
 
 	if (!rtnl_trylock())
 		return restart_syscall();
+
+	block_netpoll_tx();
 	read_lock(&bond->lock);
 	write_lock_bh(&bond->curr_slave_lock);
 
@@ -1288,6 +1294,8 @@
  out:
 	write_unlock_bh(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
+	unblock_netpoll_tx();
+
 	rtnl_unlock();
 
 	return count;
@@ -1592,6 +1600,49 @@
 static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR,
 		   bonding_show_slaves_active, bonding_store_slaves_active);
 
+/*
+ * Show and set the number of IGMP membership reports to send on link failure
+ */
+static ssize_t bonding_show_resend_igmp(struct device *d,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct bonding *bond = to_bond(d);
+
+	return sprintf(buf, "%d\n", bond->params.resend_igmp);
+}
+
+static ssize_t bonding_store_resend_igmp(struct device *d,
+					  struct device_attribute *attr,
+					  const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(d);
+
+	if (sscanf(buf, "%d", &new_value) != 1) {
+		pr_err("%s: no resend_igmp value specified.\n",
+		       bond->dev->name);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (new_value < 0) {
+		pr_err("%s: Invalid resend_igmp value %d not in range 0-255; rejected.\n",
+		       bond->dev->name, new_value);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	pr_info("%s: Setting resend_igmp to %d.\n",
+		bond->dev->name, new_value);
+	bond->params.resend_igmp = new_value;
+out:
+	return ret;
+}
+
+static DEVICE_ATTR(resend_igmp, S_IRUGO | S_IWUSR,
+		   bonding_show_resend_igmp, bonding_store_resend_igmp);
+
 static struct attribute *per_bond_attrs[] = {
 	&dev_attr_slaves.attr,
 	&dev_attr_mode.attr,
@@ -1619,6 +1670,7 @@
 	&dev_attr_ad_partner_mac.attr,
 	&dev_attr_queue_id.attr,
 	&dev_attr_all_slaves_active.attr,
+	&dev_attr_resend_igmp.attr,
 	NULL,
 };
 
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index c6fdd85..4eedb12 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -19,6 +19,7 @@
 #include <linux/proc_fs.h>
 #include <linux/if_bonding.h>
 #include <linux/kobject.h>
+#include <linux/cpumask.h>
 #include <linux/in6.h>
 #include "bond_3ad.h"
 #include "bond_alb.h"
@@ -117,6 +118,35 @@
 		bond_for_each_slave_from(bond, pos, cnt, (bond)->first_slave)
 
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+extern cpumask_var_t netpoll_block_tx;
+
+static inline void block_netpoll_tx(void)
+{
+	preempt_disable();
+	BUG_ON(cpumask_test_and_set_cpu(smp_processor_id(),
+					netpoll_block_tx));
+}
+
+static inline void unblock_netpoll_tx(void)
+{
+	BUG_ON(!cpumask_test_and_clear_cpu(smp_processor_id(),
+					   netpoll_block_tx));
+	preempt_enable();
+}
+
+static inline int is_netpoll_tx_blocked(struct net_device *dev)
+{
+	if (unlikely(dev->priv_flags & IFF_IN_NETPOLL))
+		return cpumask_test_cpu(smp_processor_id(), netpoll_block_tx);
+	return 0;
+}
+#else
+#define block_netpoll_tx()
+#define unblock_netpoll_tx()
+#define is_netpoll_tx_blocked(dev) (0)
+#endif
+
 struct bond_params {
 	int mode;
 	int xmit_policy;
@@ -136,6 +166,7 @@
 	__be32 arp_targets[BOND_MAX_ARP_TARGETS];
 	int tx_queues;
 	int all_slaves_active;
+	int resend_igmp;
 };
 
 struct bond_parm_tbl {
@@ -202,6 +233,7 @@
 	s8	 send_grat_arp;
 	s8	 send_unsol_na;
 	s8	 setup_by_slave;
+	s8       igmp_retrans;
 #ifdef CONFIG_PROC_FS
 	struct   proc_dir_entry *proc_entry;
 	char     proc_file_name[IFNAMSIZ];
@@ -223,6 +255,7 @@
 	struct   delayed_work arp_work;
 	struct   delayed_work alb_work;
 	struct   delayed_work ad_work;
+	struct   delayed_work mcast_work;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	struct   in6_addr master_ipv6;
 #endif
@@ -331,7 +364,6 @@
 struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
 int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
 int bond_create(struct net *net, const char *name);
-int  bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev);
 int bond_create_sysfs(void);
 void bond_destroy_sysfs(void);
 void bond_prepare_sysfs_group(struct bonding *bond);
diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c
index 88edb98..6e99d80 100644
--- a/drivers/net/bsd_comp.c
+++ b/drivers/net/bsd_comp.c
@@ -429,7 +429,7 @@
 	if (!db->lens)
 	  {
 	    bsd_free (db);
-	    return (NULL);
+	    return NULL;
 	  }
       }
 /*
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index f5058ff..8427533 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -240,13 +240,15 @@
 static const struct file_operations dbgfs_state_fops = {
 	.open = dbgfs_open,
 	.read = dbgfs_state,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations dbgfs_frame_fops = {
 	.open = dbgfs_open,
 	.read = dbgfs_frame,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static inline void dev_debugfs_add(struct cfspi *cfspi)
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
index b11a0cb..6aadc3e 100644
--- a/drivers/net/can/mcp251x.c
+++ b/drivers/net/can/mcp251x.c
@@ -38,14 +38,14 @@
  * static struct mcp251x_platform_data mcp251x_info = {
  *         .oscillator_frequency = 8000000,
  *         .board_specific_setup = &mcp251x_setup,
- *         .model = CAN_MCP251X_MCP2510,
  *         .power_enable = mcp251x_power_enable,
  *         .transceiver_enable = NULL,
  * };
  *
  * static struct spi_board_info spi_board_info[] = {
  *         {
- *                 .modalias = "mcp251x",
+ *                 .modalias = "mcp2510",
+ *			// or "mcp2515" depending on your controller
  *                 .platform_data = &mcp251x_info,
  *                 .irq = IRQ_EINT13,
  *                 .max_speed_hz = 2*1000*1000,
@@ -125,6 +125,9 @@
 #  define CANINTF_TX0IF 0x04
 #  define CANINTF_RX1IF 0x02
 #  define CANINTF_RX0IF 0x01
+#  define CANINTF_RX (CANINTF_RX0IF | CANINTF_RX1IF)
+#  define CANINTF_TX (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)
+#  define CANINTF_ERR (CANINTF_ERRIF)
 #define EFLG	      0x2d
 #  define EFLG_EWARN	0x01
 #  define EFLG_RXWAR	0x02
@@ -222,10 +225,16 @@
 	.brp_inc = 1,
 };
 
+enum mcp251x_model {
+	CAN_MCP251X_MCP2510	= 0x2510,
+	CAN_MCP251X_MCP2515	= 0x2515,
+};
+
 struct mcp251x_priv {
 	struct can_priv	   can;
 	struct net_device *net;
 	struct spi_device *spi;
+	enum mcp251x_model model;
 
 	struct mutex mcp_lock; /* SPI device lock */
 
@@ -250,6 +259,16 @@
 	int restart_tx;
 };
 
+#define MCP251X_IS(_model) \
+static inline int mcp251x_is_##_model(struct spi_device *spi) \
+{ \
+	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); \
+	return priv->model == CAN_MCP251X_MCP##_model; \
+}
+
+MCP251X_IS(2510);
+MCP251X_IS(2515);
+
 static void mcp251x_clean(struct net_device *net)
 {
 	struct mcp251x_priv *priv = netdev_priv(net);
@@ -319,6 +338,20 @@
 	return val;
 }
 
+static void mcp251x_read_2regs(struct spi_device *spi, uint8_t reg,
+		uint8_t *v1, uint8_t *v2)
+{
+	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
+
+	priv->spi_tx_buf[0] = INSTRUCTION_READ;
+	priv->spi_tx_buf[1] = reg;
+
+	mcp251x_spi_trans(spi, 4);
+
+	*v1 = priv->spi_rx_buf[2];
+	*v2 = priv->spi_rx_buf[3];
+}
+
 static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val)
 {
 	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
@@ -346,10 +379,9 @@
 static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf,
 				int len, int tx_buf_idx)
 {
-	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
 	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
 
-	if (pdata->model == CAN_MCP251X_MCP2510) {
+	if (mcp251x_is_2510(spi)) {
 		int i;
 
 		for (i = 1; i < TXBDAT_OFF + len; i++)
@@ -392,9 +424,8 @@
 				int buf_idx)
 {
 	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
-	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
 
-	if (pdata->model == CAN_MCP251X_MCP2510) {
+	if (mcp251x_is_2510(spi)) {
 		int i, len;
 
 		for (i = 1; i < RXBDAT_OFF; i++)
@@ -451,7 +482,7 @@
 
 	priv->net->stats.rx_packets++;
 	priv->net->stats.rx_bytes += frame->can_dlc;
-	netif_rx(skb);
+	netif_rx_ni(skb);
 }
 
 static void mcp251x_hw_sleep(struct spi_device *spi)
@@ -674,9 +705,9 @@
 
 	skb = alloc_can_err_skb(net, &frame);
 	if (skb) {
-		frame->can_id = can_id;
+		frame->can_id |= can_id;
 		frame->data[1] = data1;
-		netif_rx(skb);
+		netif_rx_ni(skb);
 	} else {
 		dev_err(&net->dev,
 			"cannot allocate error skb\n");
@@ -754,24 +785,42 @@
 	mutex_lock(&priv->mcp_lock);
 	while (!priv->force_quit) {
 		enum can_state new_state;
-		u8 intf = mcp251x_read_reg(spi, CANINTF);
-		u8 eflag;
+		u8 intf, eflag;
+		u8 clear_intf = 0;
 		int can_id = 0, data1 = 0;
 
+		mcp251x_read_2regs(spi, CANINTF, &intf, &eflag);
+
+		/* mask out flags we don't care about */
+		intf &= CANINTF_RX | CANINTF_TX | CANINTF_ERR;
+
+		/* receive buffer 0 */
 		if (intf & CANINTF_RX0IF) {
 			mcp251x_hw_rx(spi, 0);
-			/* Free one buffer ASAP */
-			mcp251x_write_bits(spi, CANINTF, intf & CANINTF_RX0IF,
-					   0x00);
+			/*
+			 * Free one buffer ASAP
+			 * (The MCP2515 does this automatically.)
+			 */
+			if (mcp251x_is_2510(spi))
+				mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00);
 		}
 
-		if (intf & CANINTF_RX1IF)
+		/* receive buffer 1 */
+		if (intf & CANINTF_RX1IF) {
 			mcp251x_hw_rx(spi, 1);
+			/* the MCP2515 does this automatically */
+			if (mcp251x_is_2510(spi))
+				clear_intf |= CANINTF_RX1IF;
+		}
 
-		mcp251x_write_bits(spi, CANINTF, intf, 0x00);
+		/* any error or tx interrupt we need to clear? */
+		if (intf & (CANINTF_ERR | CANINTF_TX))
+			clear_intf |= intf & (CANINTF_ERR | CANINTF_TX);
+		if (clear_intf)
+			mcp251x_write_bits(spi, CANINTF, clear_intf, 0x00);
 
-		eflag = mcp251x_read_reg(spi, EFLG);
-		mcp251x_write_reg(spi, EFLG, 0x00);
+		if (eflag)
+			mcp251x_write_bits(spi, EFLG, eflag, 0x00);
 
 		/* Update can state */
 		if (eflag & EFLG_TXBO) {
@@ -816,10 +865,14 @@
 		if (intf & CANINTF_ERRIF) {
 			/* Handle overflow counters */
 			if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) {
-				if (eflag & EFLG_RX0OVR)
+				if (eflag & EFLG_RX0OVR) {
 					net->stats.rx_over_errors++;
-				if (eflag & EFLG_RX1OVR)
+					net->stats.rx_errors++;
+				}
+				if (eflag & EFLG_RX1OVR) {
 					net->stats.rx_over_errors++;
+					net->stats.rx_errors++;
+				}
 				can_id |= CAN_ERR_CRTL;
 				data1 |= CAN_ERR_CRTL_RX_OVERFLOW;
 			}
@@ -838,7 +891,7 @@
 		if (intf == 0)
 			break;
 
-		if (intf & (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)) {
+		if (intf & CANINTF_TX) {
 			net->stats.tx_packets++;
 			net->stats.tx_bytes += priv->tx_len - 1;
 			if (priv->tx_len) {
@@ -921,16 +974,12 @@
 	struct net_device *net;
 	struct mcp251x_priv *priv;
 	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
-	int model = spi_get_device_id(spi)->driver_data;
 	int ret = -ENODEV;
 
 	if (!pdata)
 		/* Platform data is required for osc freq */
 		goto error_out;
 
-	if (model)
-		pdata->model = model;
-
 	/* Allocate can/net device */
 	net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX);
 	if (!net) {
@@ -947,6 +996,7 @@
 	priv->can.clock.freq = pdata->oscillator_frequency / 2;
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
 		CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
+	priv->model = spi_get_device_id(spi)->driver_data;
 	priv->net = net;
 	dev_set_drvdata(&spi->dev, priv);
 
@@ -1120,8 +1170,7 @@
 #define mcp251x_can_resume NULL
 #endif
 
-static struct spi_device_id mcp251x_id_table[] = {
-	{ "mcp251x", 	0 /* Use pdata.model */ },
+static const struct spi_device_id mcp251x_id_table[] = {
 	{ "mcp2510",	CAN_MCP251X_MCP2510 },
 	{ "mcp2515",	CAN_MCP251X_MCP2515 },
 	{ },
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index b1bdc90..312b9c8 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -143,12 +143,12 @@
 	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
 	if (!np_clock) {
 		dev_err(&ofdev->dev, "couldn't find clock node\n");
-		return -ENODEV;
+		return 0;
 	}
 	clockctl = of_iomap(np_clock, 0);
 	if (!clockctl) {
 		dev_err(&ofdev->dev, "couldn't map clock registers\n");
-		return 0;
+		goto exit_put;
 	}
 
 	/* Determine the MSCAN device index from the physical address */
@@ -233,9 +233,9 @@
 		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
 
 exit_unmap:
-	of_node_put(np_clock);
 	iounmap(clockctl);
-
+exit_put:
+	of_node_put(np_clock);
 	return freq;
 }
 #else /* !CONFIG_PPC_MPC512x */
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 28c88ee..d6b6d6a 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -419,7 +419,7 @@
 		udelay(10);
 		cmd = readl(cp->regs + REG_MIF_FRAME);
 		if (cmd & MIF_FRAME_TURN_AROUND_LSB)
-			return (cmd & MIF_FRAME_DATA_MASK);
+			return cmd & MIF_FRAME_DATA_MASK;
 	}
 	return 0xFFFF; /* -1 */
 }
@@ -804,7 +804,7 @@
 			break;
 		udelay(10);
 	}
-	return (limit <= 0);
+	return limit <= 0;
 }
 
 static int cas_saturn_firmware_init(struct cas *cp)
@@ -2149,7 +2149,7 @@
 		skb->csum = csum_unfold(~csum);
 		skb->ip_summed = CHECKSUM_COMPLETE;
 	} else
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 	return len;
 }
 
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index f01cfdb..70221ca 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1388,7 +1388,7 @@
 		++st->rx_cso_good;
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	} else
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 
 	if (unlikely(adapter->vlan_grp && p->vlan_valid)) {
 		st->vlan_xtract++;
@@ -1551,7 +1551,7 @@
 	const struct respQ *Q = &adapter->sge->respQ;
 	const struct respQ_e *e = &Q->entries[Q->cidx];
 
-	return (e->GenerationBit == Q->genbit);
+	return e->GenerationBit == Q->genbit;
 }
 
 /*
@@ -1870,7 +1870,7 @@
 	cpl->iff = dev->if_port;
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-	if (adapter->vlan_grp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		cpl->vlan_valid = 1;
 		cpl->vlan = htons(vlan_tx_tag_get(skb));
 		st->vlan_insert++;
diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c
index 599d178..63ebf76 100644
--- a/drivers/net/chelsio/subr.c
+++ b/drivers/net/chelsio/subr.c
@@ -314,14 +314,12 @@
 	return 0;
 }
 
-#if defined(CONFIG_CHELSIO_T1_1G)
 static const struct mdio_ops mi1_mdio_ops = {
 	.init = mi1_mdio_init,
 	.read = mi1_mdio_read,
 	.write = mi1_mdio_write,
 	.mode_support = MDIO_SUPPORTS_C22
 };
-#endif
 
 #endif
 
diff --git a/drivers/net/chelsio/vsc7326.c b/drivers/net/chelsio/vsc7326.c
index c844111..106a590 100644
--- a/drivers/net/chelsio/vsc7326.c
+++ b/drivers/net/chelsio/vsc7326.c
@@ -255,7 +255,7 @@
 	else if ((result & (1 << 8)) != 0x0)
 		pr_err("bist read error: 0x%x\n", result);
 
-	return (result & 0xff);
+	return result & 0xff;
 }
 
 static int bist_wr(adapter_t *adapter, int moduleid, int address, int value)
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 0961032..92bac19 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -60,6 +60,7 @@
 MODULE_VERSION(CNIC_MODULE_VERSION);
 
 static LIST_HEAD(cnic_dev_list);
+static LIST_HEAD(cnic_udev_list);
 static DEFINE_RWLOCK(cnic_dev_lock);
 static DEFINE_MUTEX(cnic_lock);
 
@@ -81,29 +82,34 @@
 	.cnic_ctl	= cnic_ctl,
 };
 
+static struct workqueue_struct *cnic_wq;
+
 static void cnic_shutdown_rings(struct cnic_dev *);
 static void cnic_init_rings(struct cnic_dev *);
 static int cnic_cm_set_pg(struct cnic_sock *);
 
 static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode)
 {
-	struct cnic_dev *dev = uinfo->priv;
-	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_uio_dev *udev = uinfo->priv;
+	struct cnic_dev *dev;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	if (cp->uio_dev != -1)
+	if (udev->uio_dev != -1)
 		return -EBUSY;
 
 	rtnl_lock();
-	if (!test_bit(CNIC_F_CNIC_UP, &dev->flags)) {
+	dev = udev->dev;
+
+	if (!dev || !test_bit(CNIC_F_CNIC_UP, &dev->flags)) {
 		rtnl_unlock();
 		return -ENODEV;
 	}
 
-	cp->uio_dev = iminor(inode);
+	udev->uio_dev = iminor(inode);
 
+	cnic_shutdown_rings(dev);
 	cnic_init_rings(dev);
 	rtnl_unlock();
 
@@ -112,12 +118,9 @@
 
 static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode)
 {
-	struct cnic_dev *dev = uinfo->priv;
-	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_uio_dev *udev = uinfo->priv;
 
-	cnic_shutdown_rings(dev);
-
-	cp->uio_dev = -1;
+	udev->uio_dev = -1;
 	return 0;
 }
 
@@ -242,14 +245,14 @@
 	return test_bit(SK_F_INUSE, &csk->flags);
 }
 
-static void cnic_kwq_completion(struct cnic_dev *dev, u32 count)
+static void cnic_spq_completion(struct cnic_dev *dev, int cmd, u32 count)
 {
 	struct cnic_local *cp = dev->cnic_priv;
 	struct cnic_eth_dev *ethdev = cp->ethdev;
 	struct drv_ctl_info info;
 
-	info.cmd = DRV_CTL_COMPLETION_CMD;
-	info.data.comp.comp_count = count;
+	info.cmd = cmd;
+	info.data.credit.credit_count = count;
 	ethdev->drv_ctl(dev->netdev, &info);
 }
 
@@ -274,8 +277,9 @@
 	u16 len = 0;
 	u32 msg_type = ISCSI_KEVENT_IF_DOWN;
 	struct cnic_ulp_ops *ulp_ops;
+	struct cnic_uio_dev *udev = cp->udev;
 
-	if (cp->uio_dev == -1)
+	if (!udev || udev->uio_dev == -1)
 		return -ENODEV;
 
 	if (csk) {
@@ -406,8 +410,7 @@
 	list_for_each_entry(dev, &cnic_dev_list, list) {
 		struct cnic_local *cp = dev->cnic_priv;
 
-		if (cp->cnic_uinfo)
-			cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+		cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
 	}
 	read_unlock(&cnic_dev_lock);
 }
@@ -768,31 +771,45 @@
 	}
 }
 
+static void __cnic_free_uio(struct cnic_uio_dev *udev)
+{
+	uio_unregister_device(&udev->cnic_uinfo);
+
+	if (udev->l2_buf) {
+		dma_free_coherent(&udev->pdev->dev, udev->l2_buf_size,
+				  udev->l2_buf, udev->l2_buf_map);
+		udev->l2_buf = NULL;
+	}
+
+	if (udev->l2_ring) {
+		dma_free_coherent(&udev->pdev->dev, udev->l2_ring_size,
+				  udev->l2_ring, udev->l2_ring_map);
+		udev->l2_ring = NULL;
+	}
+
+	pci_dev_put(udev->pdev);
+	kfree(udev);
+}
+
+static void cnic_free_uio(struct cnic_uio_dev *udev)
+{
+	if (!udev)
+		return;
+
+	write_lock(&cnic_dev_lock);
+	list_del_init(&udev->list);
+	write_unlock(&cnic_dev_lock);
+	__cnic_free_uio(udev);
+}
+
 static void cnic_free_resc(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	int i = 0;
+	struct cnic_uio_dev *udev = cp->udev;
 
-	if (cp->cnic_uinfo) {
-		while (cp->uio_dev != -1 && i < 15) {
-			msleep(100);
-			i++;
-		}
-		uio_unregister_device(cp->cnic_uinfo);
-		kfree(cp->cnic_uinfo);
-		cp->cnic_uinfo = NULL;
-	}
-
-	if (cp->l2_buf) {
-		dma_free_coherent(&dev->pcidev->dev, cp->l2_buf_size,
-				  cp->l2_buf, cp->l2_buf_map);
-		cp->l2_buf = NULL;
-	}
-
-	if (cp->l2_ring) {
-		dma_free_coherent(&dev->pcidev->dev, cp->l2_ring_size,
-				  cp->l2_ring, cp->l2_ring_map);
-		cp->l2_ring = NULL;
+	if (udev) {
+		udev->dev = NULL;
+		cp->udev = NULL;
 	}
 
 	cnic_free_context(dev);
@@ -894,37 +911,68 @@
 	return 0;
 }
 
-static int cnic_alloc_l2_rings(struct cnic_dev *dev, int pages)
+static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
 {
 	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_uio_dev *udev;
 
-	cp->l2_ring_size = pages * BCM_PAGE_SIZE;
-	cp->l2_ring = dma_alloc_coherent(&dev->pcidev->dev, cp->l2_ring_size,
-					 &cp->l2_ring_map,
-					 GFP_KERNEL | __GFP_COMP);
-	if (!cp->l2_ring)
+	read_lock(&cnic_dev_lock);
+	list_for_each_entry(udev, &cnic_udev_list, list) {
+		if (udev->pdev == dev->pcidev) {
+			udev->dev = dev;
+			cp->udev = udev;
+			read_unlock(&cnic_dev_lock);
+			return 0;
+		}
+	}
+	read_unlock(&cnic_dev_lock);
+
+	udev = kzalloc(sizeof(struct cnic_uio_dev), GFP_ATOMIC);
+	if (!udev)
 		return -ENOMEM;
 
-	cp->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;
-	cp->l2_buf_size = PAGE_ALIGN(cp->l2_buf_size);
-	cp->l2_buf = dma_alloc_coherent(&dev->pcidev->dev, cp->l2_buf_size,
-					&cp->l2_buf_map,
-					GFP_KERNEL | __GFP_COMP);
-	if (!cp->l2_buf)
+	udev->uio_dev = -1;
+
+	udev->dev = dev;
+	udev->pdev = dev->pcidev;
+	udev->l2_ring_size = pages * BCM_PAGE_SIZE;
+	udev->l2_ring = dma_alloc_coherent(&udev->pdev->dev, udev->l2_ring_size,
+					   &udev->l2_ring_map,
+					   GFP_KERNEL | __GFP_COMP);
+	if (!udev->l2_ring)
 		return -ENOMEM;
 
+	udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;
+	udev->l2_buf_size = PAGE_ALIGN(udev->l2_buf_size);
+	udev->l2_buf = dma_alloc_coherent(&udev->pdev->dev, udev->l2_buf_size,
+					  &udev->l2_buf_map,
+					  GFP_KERNEL | __GFP_COMP);
+	if (!udev->l2_buf)
+		return -ENOMEM;
+
+	write_lock(&cnic_dev_lock);
+	list_add(&udev->list, &cnic_udev_list);
+	write_unlock(&cnic_dev_lock);
+
+	pci_dev_get(udev->pdev);
+
+	cp->udev = udev;
+
 	return 0;
 }
 
-static int cnic_alloc_uio(struct cnic_dev *dev) {
+static int cnic_init_uio(struct cnic_dev *dev)
+{
 	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_uio_dev *udev = cp->udev;
 	struct uio_info *uinfo;
-	int ret;
+	int ret = 0;
 
-	uinfo = kzalloc(sizeof(*uinfo), GFP_ATOMIC);
-	if (!uinfo)
+	if (!udev)
 		return -ENOMEM;
 
+	uinfo = &udev->cnic_uinfo;
+
 	uinfo->mem[0].addr = dev->netdev->base_addr;
 	uinfo->mem[0].internal_addr = dev->regview;
 	uinfo->mem[0].size = dev->netdev->mem_end - dev->netdev->mem_start;
@@ -932,7 +980,7 @@
 
 	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
 		uinfo->mem[1].addr = (unsigned long) cp->status_blk.gen &
-			PAGE_MASK;
+					PAGE_MASK;
 		if (cp->ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX)
 			uinfo->mem[1].size = BNX2_SBLK_MSIX_ALIGN_SIZE * 9;
 		else
@@ -942,19 +990,19 @@
 	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
 		uinfo->mem[1].addr = (unsigned long) cp->bnx2x_def_status_blk &
 			PAGE_MASK;
-		uinfo->mem[1].size = sizeof(struct host_def_status_block);
+		uinfo->mem[1].size = sizeof(*cp->bnx2x_def_status_blk);
 
 		uinfo->name = "bnx2x_cnic";
 	}
 
 	uinfo->mem[1].memtype = UIO_MEM_LOGICAL;
 
-	uinfo->mem[2].addr = (unsigned long) cp->l2_ring;
-	uinfo->mem[2].size = cp->l2_ring_size;
+	uinfo->mem[2].addr = (unsigned long) udev->l2_ring;
+	uinfo->mem[2].size = udev->l2_ring_size;
 	uinfo->mem[2].memtype = UIO_MEM_LOGICAL;
 
-	uinfo->mem[3].addr = (unsigned long) cp->l2_buf;
-	uinfo->mem[3].size = cp->l2_buf_size;
+	uinfo->mem[3].addr = (unsigned long) udev->l2_buf;
+	uinfo->mem[3].size = udev->l2_buf_size;
 	uinfo->mem[3].memtype = UIO_MEM_LOGICAL;
 
 	uinfo->version = CNIC_MODULE_VERSION;
@@ -963,16 +1011,17 @@
 	uinfo->open = cnic_uio_open;
 	uinfo->release = cnic_uio_close;
 
-	uinfo->priv = dev;
+	if (udev->uio_dev == -1) {
+		if (!uinfo->priv) {
+			uinfo->priv = udev;
 
-	ret = uio_register_device(&dev->pcidev->dev, uinfo);
-	if (ret) {
-		kfree(uinfo);
-		return ret;
+			ret = uio_register_device(&udev->pdev->dev, uinfo);
+		}
+	} else {
+		cnic_init_rings(dev);
 	}
 
-	cp->cnic_uinfo = uinfo;
-	return 0;
+	return ret;
 }
 
 static int cnic_alloc_bnx2_resc(struct cnic_dev *dev)
@@ -993,11 +1042,11 @@
 	if (ret)
 		goto error;
 
-	ret = cnic_alloc_l2_rings(dev, 2);
+	ret = cnic_alloc_uio_rings(dev, 2);
 	if (ret)
 		goto error;
 
-	ret = cnic_alloc_uio(dev);
+	ret = cnic_init_uio(dev);
 	if (ret)
 		goto error;
 
@@ -1022,13 +1071,13 @@
 	if (blks > cp->ethdev->ctx_tbl_len)
 		return -ENOMEM;
 
-	cp->ctx_arr = kzalloc(blks * sizeof(struct cnic_ctx), GFP_KERNEL);
+	cp->ctx_arr = kcalloc(blks, sizeof(struct cnic_ctx), GFP_KERNEL);
 	if (cp->ctx_arr == NULL)
 		return -ENOMEM;
 
 	cp->ctx_blks = blks;
 	cp->ctx_blk_size = ctx_blk_size;
-	if (BNX2X_CHIP_IS_E1H(cp->chip_id))
+	if (!BNX2X_CHIP_IS_57710(cp->chip_id))
 		cp->ctx_align = 0;
 	else
 		cp->ctx_align = ctx_blk_size;
@@ -1063,6 +1112,8 @@
 	int i, j, n, ret, pages;
 	struct cnic_dma *kwq_16_dma = &cp->kwq_16_data_info;
 
+	cp->iro_arr = ethdev->iro_arr;
+
 	cp->max_cid_space = MAX_ISCSI_TBL_SZ;
 	cp->iscsi_start_cid = start_cid;
 	if (start_cid < BNX2X_ISCSI_START_CID) {
@@ -1127,15 +1178,13 @@
 
 	cp->bnx2x_def_status_blk = cp->ethdev->irq_arr[1].status_blk;
 
-	memset(cp->status_blk.bnx2x, 0, sizeof(*cp->status_blk.bnx2x));
-
 	cp->l2_rx_ring_size = 15;
 
-	ret = cnic_alloc_l2_rings(dev, 4);
+	ret = cnic_alloc_uio_rings(dev, 4);
 	if (ret)
 		goto error;
 
-	ret = cnic_alloc_uio(dev);
+	ret = cnic_init_uio(dev);
 	if (ret)
 		goto error;
 
@@ -1209,9 +1258,9 @@
 
 	kwqe.hdr.conn_and_cmd_data =
 		cpu_to_le32(((cmd << SPE_HDR_CMD_ID_SHIFT) |
-			     BNX2X_HW_CID(cid, cp->func)));
+			     BNX2X_HW_CID(cp, cid)));
 	kwqe.hdr.type = cpu_to_le16(type);
-	kwqe.hdr.reserved = 0;
+	kwqe.hdr.reserved1 = 0;
 	kwqe.data.phy_address.lo = cpu_to_le32(l5_data->phy_address.lo);
 	kwqe.data.phy_address.hi = cpu_to_le32(l5_data->phy_address.hi);
 
@@ -1246,8 +1295,8 @@
 {
 	struct cnic_local *cp = dev->cnic_priv;
 	struct iscsi_kwqe_init1 *req1 = (struct iscsi_kwqe_init1 *) kwqe;
-	int func = cp->func, pages;
-	int hq_bds;
+	int hq_bds, pages;
+	u32 pfid = cp->pfid;
 
 	cp->num_iscsi_tasks = req1->num_tasks_per_conn;
 	cp->num_ccells = req1->num_ccells_per_conn;
@@ -1264,60 +1313,60 @@
 		return 0;
 
 	/* init Tstorm RAM */
-	CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_RQ_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_RQ_SIZE_OFFSET(pfid),
 		  req1->rq_num_wqes);
-	CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_PAGE_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
 		  PAGE_SIZE);
 	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(func), PAGE_SHIFT);
+		 TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
 	CNIC_WR16(dev, BAR_TSTRORM_INTMEM +
-		  TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(func),
+		  TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
 		  req1->num_tasks_per_conn);
 
 	/* init Ustorm RAM */
 	CNIC_WR16(dev, BAR_USTRORM_INTMEM +
-		  USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(func),
+		  USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfid),
 		  req1->rq_buffer_size);
-	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_PAGE_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
 		  PAGE_SIZE);
 	CNIC_WR8(dev, BAR_USTRORM_INTMEM +
-		 USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(func), PAGE_SHIFT);
+		 USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
 	CNIC_WR16(dev, BAR_USTRORM_INTMEM +
-		  USTORM_ISCSI_NUM_OF_TASKS_OFFSET(func),
+		  USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
 		  req1->num_tasks_per_conn);
-	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_RQ_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_RQ_SIZE_OFFSET(pfid),
 		  req1->rq_num_wqes);
-	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_CQ_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_CQ_SIZE_OFFSET(pfid),
 		  req1->cq_num_wqes);
-	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_R2TQ_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfid),
 		  cp->num_iscsi_tasks * BNX2X_ISCSI_MAX_PENDING_R2TS);
 
 	/* init Xstorm RAM */
-	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_PAGE_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
 		  PAGE_SIZE);
 	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(func), PAGE_SHIFT);
+		 XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
 	CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
-		  XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(func),
+		  XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
 		  req1->num_tasks_per_conn);
-	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_HQ_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_HQ_SIZE_OFFSET(pfid),
 		  hq_bds);
-	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_SQ_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_SQ_SIZE_OFFSET(pfid),
 		  req1->num_tasks_per_conn);
-	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_R2TQ_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfid),
 		  cp->num_iscsi_tasks * BNX2X_ISCSI_MAX_PENDING_R2TS);
 
 	/* init Cstorm RAM */
-	CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_PAGE_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
 		  PAGE_SIZE);
 	CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
-		 CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(func), PAGE_SHIFT);
+		 CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
 	CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
-		  CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(func),
+		  CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
 		  req1->num_tasks_per_conn);
-	CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_CQ_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_CQ_SIZE_OFFSET(pfid),
 		  req1->cq_num_wqes);
-	CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_HQ_SIZE_OFFSET(func),
+	CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_HQ_SIZE_OFFSET(pfid),
 		  hq_bds);
 
 	return 0;
@@ -1327,7 +1376,7 @@
 {
 	struct iscsi_kwqe_init2 *req2 = (struct iscsi_kwqe_init2 *) kwqe;
 	struct cnic_local *cp = dev->cnic_priv;
-	int func = cp->func;
+	u32 pfid = cp->pfid;
 	struct iscsi_kcqe kcqe;
 	struct kcqe *cqes[1];
 
@@ -1339,21 +1388,21 @@
 	}
 
 	CNIC_WR(dev, BAR_TSTRORM_INTMEM +
-		TSTORM_ISCSI_ERROR_BITMAP_OFFSET(func), req2->error_bit_map[0]);
+		TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid), req2->error_bit_map[0]);
 	CNIC_WR(dev, BAR_TSTRORM_INTMEM +
-		TSTORM_ISCSI_ERROR_BITMAP_OFFSET(func) + 4,
+		TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid) + 4,
 		req2->error_bit_map[1]);
 
 	CNIC_WR16(dev, BAR_USTRORM_INTMEM +
-		  USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(func), req2->max_cq_sqn);
+		  USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfid), req2->max_cq_sqn);
 	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_ISCSI_ERROR_BITMAP_OFFSET(func), req2->error_bit_map[0]);
+		USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid), req2->error_bit_map[0]);
 	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_ISCSI_ERROR_BITMAP_OFFSET(func) + 4,
+		USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid) + 4,
 		req2->error_bit_map[1]);
 
 	CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
-		  CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(func), req2->max_cq_sqn);
+		  CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfid), req2->max_cq_sqn);
 
 	kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_SUCCESS;
 
@@ -1461,7 +1510,7 @@
 	struct cnic_context *ctx = &cp->ctx_tbl[req1->iscsi_conn_id];
 	struct cnic_iscsi *iscsi = ctx->proto.iscsi;
 	u32 cid = ctx->cid;
-	u32 hw_cid = BNX2X_HW_CID(cid, cp->func);
+	u32 hw_cid = BNX2X_HW_CID(cp, cid);
 	struct iscsi_context *ictx;
 	struct regpair context_addr;
 	int i, j, n = 2, n_max;
@@ -1527,8 +1576,10 @@
 	ictx->tstorm_st_context.tcp.cwnd = 0x5A8;
 	ictx->tstorm_st_context.tcp.flags2 |=
 		TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN;
+	ictx->tstorm_st_context.tcp.ooo_support_mode =
+		TCP_TSTORM_OOO_DROP_AND_PROC_ACK;
 
-	ictx->timers_context.flags |= ISCSI_TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG;
+	ictx->timers_context.flags |= TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG;
 
 	ictx->ustorm_st_context.ring.rq.pbl_base.lo =
 		req2->rq_page_table_addr_lo;
@@ -1627,10 +1678,11 @@
 	struct iscsi_kwqe_conn_offload1 *req1;
 	struct iscsi_kwqe_conn_offload2 *req2;
 	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_context *ctx;
 	struct iscsi_kcqe kcqe;
 	struct kcqe *cqes[1];
 	u32 l5_cid;
-	int ret;
+	int ret = 0;
 
 	if (num < 2) {
 		*work = num;
@@ -1654,9 +1706,15 @@
 	kcqe.iscsi_conn_id = l5_cid;
 	kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE;
 
+	ctx = &cp->ctx_tbl[l5_cid];
+	if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags)) {
+		kcqe.completion_status =
+			ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY;
+		goto done;
+	}
+
 	if (atomic_inc_return(&cp->iscsi_conn) > dev->max_iscsi_conn) {
 		atomic_dec(&cp->iscsi_conn);
-		ret = 0;
 		goto done;
 	}
 	ret = cnic_alloc_bnx2x_conn_resc(dev, l5_cid);
@@ -1673,8 +1731,7 @@
 	}
 
 	kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_SUCCESS;
-	kcqe.iscsi_conn_context_id = BNX2X_HW_CID(cp->ctx_tbl[l5_cid].cid,
-						  cp->func);
+	kcqe.iscsi_conn_context_id = BNX2X_HW_CID(cp, cp->ctx_tbl[l5_cid].cid);
 
 done:
 	cqes[0] = (struct kcqe *) &kcqe;
@@ -1707,40 +1764,66 @@
 	return ret;
 }
 
+static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
+	union l5cm_specific_data l5_data;
+	int ret;
+	u32 hw_cid, type;
+
+	init_waitqueue_head(&ctx->waitq);
+	ctx->wait_cond = 0;
+	memset(&l5_data, 0, sizeof(l5_data));
+	hw_cid = BNX2X_HW_CID(cp, ctx->cid);
+	type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
+		& SPE_HDR_CONN_TYPE;
+	type |= ((cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
+		 SPE_HDR_FUNCTION_ID);
+
+	ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
+				  hw_cid, type, &l5_data);
+
+	if (ret == 0)
+		wait_event(ctx->waitq, ctx->wait_cond);
+
+	return ret;
+}
+
 static int cnic_bnx2x_iscsi_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
 {
 	struct cnic_local *cp = dev->cnic_priv;
 	struct iscsi_kwqe_conn_destroy *req =
 		(struct iscsi_kwqe_conn_destroy *) kwqe;
-	union l5cm_specific_data l5_data;
 	u32 l5_cid = req->reserved0;
 	struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
 	int ret = 0;
 	struct iscsi_kcqe kcqe;
 	struct kcqe *cqes[1];
 
-	if (!(ctx->ctx_flags & CTX_FL_OFFLD_START))
+	if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
 		goto skip_cfc_delete;
 
-	while (!time_after(jiffies, ctx->timestamp + (2 * HZ)))
-		msleep(250);
+	if (!time_after(jiffies, ctx->timestamp + (2 * HZ))) {
+		unsigned long delta = ctx->timestamp + (2 * HZ) - jiffies;
 
-	init_waitqueue_head(&ctx->waitq);
-	ctx->wait_cond = 0;
-	memset(&l5_data, 0, sizeof(l5_data));
-	ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CFC_DEL,
-				  req->context_id,
-				  ETH_CONNECTION_TYPE |
-				  (1 << SPE_HDR_COMMON_RAMROD_SHIFT),
-				  &l5_data);
-	if (ret == 0)
-		wait_event(ctx->waitq, ctx->wait_cond);
+		if (delta > (2 * HZ))
+			delta = 0;
+
+		set_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags);
+		queue_delayed_work(cnic_wq, &cp->delete_task, delta);
+		goto destroy_reply;
+	}
+
+	ret = cnic_bnx2x_destroy_ramrod(dev, l5_cid);
 
 skip_cfc_delete:
 	cnic_free_bnx2x_conn_resc(dev, l5_cid);
 
 	atomic_dec(&cp->iscsi_conn);
+	clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
 
+destroy_reply:
 	memset(&kcqe, 0, sizeof(kcqe));
 	kcqe.op_code = ISCSI_KCQE_OPCODE_DESTROY_CONN;
 	kcqe.iscsi_conn_id = l5_cid;
@@ -1805,37 +1888,37 @@
 static void cnic_init_bnx2x_mac(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	int func = CNIC_FUNC(cp);
+	u32 pfid = cp->pfid;
 	u8 *mac = dev->mac_addr;
 
 	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(func), mac[0]);
+		 XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfid), mac[0]);
 	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(func), mac[1]);
+		 XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfid), mac[1]);
 	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(func), mac[2]);
+		 XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfid), mac[2]);
 	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(func), mac[3]);
+		 XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfid), mac[3]);
 	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(func), mac[4]);
+		 XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfid), mac[4]);
 	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(func), mac[5]);
+		 XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfid), mac[5]);
 
 	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(func), mac[5]);
+		 TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[5]);
 	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(func) + 1,
+		 TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
 		 mac[4]);
 	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(func), mac[3]);
+		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[3]);
 	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(func) + 1,
+		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
 		 mac[2]);
 	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(func) + 2,
+		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 2,
 		 mac[1]);
 	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(func) + 3,
+		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 3,
 		 mac[0]);
 }
 
@@ -1851,10 +1934,10 @@
 	}
 
 	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->func), xstorm_flags);
+		 XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), xstorm_flags);
 
 	CNIC_WR16(dev, BAR_TSTRORM_INTMEM +
-		  TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->func), tstorm_flags);
+		  TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), tstorm_flags);
 }
 
 static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[],
@@ -1929,7 +2012,7 @@
 	cnic_init_storm_conn_bufs(dev, kwqe1, kwqe3, conn_buf);
 
 	CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
-		  XSTORM_ISCSI_LOCAL_VLAN_OFFSET(cp->func), csk->vlan_id);
+		  XSTORM_ISCSI_LOCAL_VLAN_OFFSET(cp->pfid), csk->vlan_id);
 
 	cnic_bnx2x_set_tcp_timestamp(dev,
 		kwqe1->tcp_flags & L4_KWQ_CONNECT_REQ1_TIME_STAMP);
@@ -1937,7 +2020,7 @@
 	ret = cnic_submit_kwqe_16(dev, L5CM_RAMROD_CMD_ID_TCP_CONNECT,
 			kwqe1->cid, ISCSI_CONNECTION_TYPE, &l5_data);
 	if (!ret)
-		ctx->ctx_flags |= CTX_FL_OFFLD_START;
+		set_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
 
 	return ret;
 }
@@ -2063,7 +2146,7 @@
 static void service_kcqes(struct cnic_dev *dev, int num_cqes)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	int i, j;
+	int i, j, comp = 0;
 
 	i = 0;
 	j = 1;
@@ -2074,7 +2157,7 @@
 		u32 kcqe_layer = kcqe_op_flag & KCQE_FLAGS_LAYER_MASK;
 
 		if (unlikely(kcqe_op_flag & KCQE_RAMROD_COMPLETION))
-			cnic_kwq_completion(dev, 1);
+			comp++;
 
 		while (j < num_cqes) {
 			u32 next_op = cp->completed_kcq[i + j]->kcqe_op_flag;
@@ -2083,7 +2166,7 @@
 				break;
 
 			if (unlikely(next_op & KCQE_RAMROD_COMPLETION))
-				cnic_kwq_completion(dev, 1);
+				comp++;
 			j++;
 		}
 
@@ -2113,6 +2196,8 @@
 		i += j;
 		j = 1;
 	}
+	if (unlikely(comp))
+		cnic_spq_completion(dev, DRV_CTL_RET_L5_SPQ_CREDIT_CMD, comp);
 }
 
 static u16 cnic_bnx2_next_idx(u16 idx)
@@ -2171,8 +2256,9 @@
 static int cnic_l2_completion(struct cnic_local *cp)
 {
 	u16 hw_cons, sw_cons;
+	struct cnic_uio_dev *udev = cp->udev;
 	union eth_rx_cqe *cqe, *cqe_ring = (union eth_rx_cqe *)
-					(cp->l2_ring + (2 * BCM_PAGE_SIZE));
+					(udev->l2_ring + (2 * BCM_PAGE_SIZE));
 	u32 cmd;
 	int comp = 0;
 
@@ -2203,13 +2289,14 @@
 
 static void cnic_chk_pkt_rings(struct cnic_local *cp)
 {
-	u16 rx_cons = *cp->rx_cons_ptr;
-	u16 tx_cons = *cp->tx_cons_ptr;
+	u16 rx_cons, tx_cons;
 	int comp = 0;
 
-	if (!test_bit(CNIC_F_CNIC_UP, &cp->dev->flags))
+	if (!test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
 		return;
 
+	rx_cons = *cp->rx_cons_ptr;
+	tx_cons = *cp->tx_cons_ptr;
 	if (cp->tx_cons != tx_cons || cp->rx_cons != rx_cons) {
 		if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
 			comp = cnic_l2_completion(cp);
@@ -2217,7 +2304,8 @@
 		cp->tx_cons = tx_cons;
 		cp->rx_cons = rx_cons;
 
-		uio_event_notify(cp->cnic_uinfo);
+		if (cp->udev)
+			uio_event_notify(&cp->udev->cnic_uinfo);
 	}
 	if (comp)
 		clear_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
@@ -2318,14 +2406,38 @@
 	CNIC_WR(dev, hc_addr, (*(u32 *)&igu_ack));
 }
 
+static void cnic_ack_igu_sb(struct cnic_dev *dev, u8 igu_sb_id, u8 segment,
+			    u16 index, u8 op, u8 update)
+{
+	struct igu_regular cmd_data;
+	u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id) * 8;
+
+	cmd_data.sb_id_and_flags =
+		(index << IGU_REGULAR_SB_INDEX_SHIFT) |
+		(segment << IGU_REGULAR_SEGMENT_ACCESS_SHIFT) |
+		(update << IGU_REGULAR_BUPDATE_SHIFT) |
+		(op << IGU_REGULAR_ENABLE_INT_SHIFT);
+
+
+	CNIC_WR(dev, igu_addr, cmd_data.sb_id_and_flags);
+}
+
 static void cnic_ack_bnx2x_msix(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
 
-	cnic_ack_bnx2x_int(dev, cp->status_blk_num, CSTORM_ID, 0,
+	cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, CSTORM_ID, 0,
 			   IGU_INT_DISABLE, 0);
 }
 
+static void cnic_ack_bnx2x_e2_msix(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+
+	cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF, 0,
+			IGU_INT_DISABLE, 0);
+}
+
 static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info)
 {
 	u32 last_status = *info->status_idx_ptr;
@@ -2357,8 +2469,12 @@
 	status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1);
 
 	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX);
-	cnic_ack_bnx2x_int(dev, cp->status_blk_num, CSTORM_ID,
-			   status_idx, IGU_INT_ENABLE, 1);
+	if (BNX2X_CHIP_IS_E2(cp->chip_id))
+		cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF,
+				status_idx, IGU_INT_ENABLE, 1);
+	else
+		cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID,
+				   status_idx, IGU_INT_ENABLE, 1);
 }
 
 static int cnic_service_bnx2x(void *data, void *status_blk)
@@ -2379,8 +2495,7 @@
 	struct cnic_local *cp = dev->cnic_priv;
 	int if_type;
 
-	if (cp->cnic_uinfo)
-		cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+	cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
 
 	for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
 		struct cnic_ulp_ops *ulp_ops;
@@ -2728,6 +2843,13 @@
 	if (l5_cid >= MAX_CM_SK_TBL_SZ)
 		return -EINVAL;
 
+	if (cp->ctx_tbl) {
+		struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
+
+		if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
+			return -EAGAIN;
+	}
+
 	csk1 = &cp->csk_tbl[l5_cid];
 	if (atomic_read(&csk1->ref_count))
 		return -EAGAIN;
@@ -3279,39 +3401,106 @@
 
 static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
 {
+	struct cnic_local *cp = dev->cnic_priv;
+	int i;
+
+	if (!cp->ctx_tbl)
+		return;
+
+	if (!netif_running(dev->netdev))
+		return;
+
+	for (i = 0; i < cp->max_cid_space; i++) {
+		struct cnic_context *ctx = &cp->ctx_tbl[i];
+
+		while (test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
+			msleep(10);
+
+		if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
+			netdev_warn(dev->netdev, "CID %x not deleted\n",
+				   ctx->cid);
+	}
+
+	cancel_delayed_work(&cp->delete_task);
+	flush_workqueue(cnic_wq);
+
+	if (atomic_read(&cp->iscsi_conn) != 0)
+		netdev_warn(dev->netdev, "%d iSCSI connections not destroyed\n",
+			    atomic_read(&cp->iscsi_conn));
 }
 
 static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	int func = CNIC_FUNC(cp);
+	u32 pfid = cp->pfid;
+	u32 port = CNIC_PORT(cp);
 
 	cnic_init_bnx2x_mac(dev);
 	cnic_bnx2x_set_tcp_timestamp(dev, 1);
 
 	CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
-		  XSTORM_ISCSI_LOCAL_VLAN_OFFSET(func), 0);
+		  XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfid), 0);
 
 	CNIC_WR(dev, BAR_XSTRORM_INTMEM +
-		XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(func), 1);
+		XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(port), 1);
 	CNIC_WR(dev, BAR_XSTRORM_INTMEM +
-		XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(func),
+		XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(port),
 		DEF_MAX_DA_COUNT);
 
 	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(func), DEF_TTL);
+		 XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfid), DEF_TTL);
 	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(func), DEF_TOS);
+		 XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfid), DEF_TOS);
 	CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-		 XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(func), 2);
+		 XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfid), 2);
 	CNIC_WR(dev, BAR_XSTRORM_INTMEM +
-		XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(func), DEF_SWS_TIMER);
+		XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(pfid), DEF_SWS_TIMER);
 
-	CNIC_WR(dev, BAR_TSTRORM_INTMEM + TSTORM_TCP_MAX_CWND_OFFSET(func),
+	CNIC_WR(dev, BAR_TSTRORM_INTMEM + TSTORM_TCP_MAX_CWND_OFFSET(pfid),
 		DEF_MAX_CWND);
 	return 0;
 }
 
+static void cnic_delete_task(struct work_struct *work)
+{
+	struct cnic_local *cp;
+	struct cnic_dev *dev;
+	u32 i;
+	int need_resched = 0;
+
+	cp = container_of(work, struct cnic_local, delete_task.work);
+	dev = cp->dev;
+
+	for (i = 0; i < cp->max_cid_space; i++) {
+		struct cnic_context *ctx = &cp->ctx_tbl[i];
+
+		if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags) ||
+		    !test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
+			continue;
+
+		if (!time_after(jiffies, ctx->timestamp + (2 * HZ))) {
+			need_resched = 1;
+			continue;
+		}
+
+		if (!test_and_clear_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
+			continue;
+
+		cnic_bnx2x_destroy_ramrod(dev, i);
+
+		cnic_free_bnx2x_conn_resc(dev, i);
+		if (ctx->ulp_proto_id == CNIC_ULP_ISCSI)
+			atomic_dec(&cp->iscsi_conn);
+
+		clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+	}
+
+	if (need_resched)
+		queue_delayed_work(cnic_wq, &cp->delete_task,
+				   msecs_to_jiffies(10));
+
+}
+
 static int cnic_cm_open(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -3326,6 +3515,8 @@
 	if (err)
 		goto err_out;
 
+	INIT_DELAYED_WORK(&cp->delete_task, cnic_delete_task);
+
 	dev->cm_create = cnic_cm_create;
 	dev->cm_destroy = cnic_cm_destroy;
 	dev->cm_connect = cnic_cm_connect;
@@ -3418,11 +3609,24 @@
 
 	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
 		cp->disable_int_sync(dev);
-		tasklet_disable(&cp->cnic_irq_task);
+		tasklet_kill(&cp->cnic_irq_task);
 		free_irq(ethdev->irq_arr[0].vector, dev);
 	}
 }
 
+static int cnic_request_irq(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	int err;
+
+	err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0, "cnic", dev);
+	if (err)
+		tasklet_disable(&cp->cnic_irq_task);
+
+	return err;
+}
+
 static int cnic_init_bnx2_irq(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -3443,12 +3647,10 @@
 		cp->last_status_idx = cp->status_blk.bnx2->status_idx;
 		tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2_msix,
 			     (unsigned long) dev);
-		err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0,
-				  "cnic", dev);
-		if (err) {
-			tasklet_disable(&cp->cnic_irq_task);
+		err = cnic_request_irq(dev);
+		if (err)
 			return err;
-		}
+
 		while (cp->status_blk.bnx2->status_completion_producer_index &&
 		       i < 10) {
 			CNIC_WR(dev, BNX2_HC_COALESCE_NOW,
@@ -3515,11 +3717,12 @@
 {
 	struct cnic_local *cp = dev->cnic_priv;
 	struct cnic_eth_dev *ethdev = cp->ethdev;
+	struct cnic_uio_dev *udev = cp->udev;
 	u32 cid_addr, tx_cid, sb_id;
 	u32 val, offset0, offset1, offset2, offset3;
 	int i;
 	struct tx_bd *txbd;
-	dma_addr_t buf_map;
+	dma_addr_t buf_map, ring_map = udev->l2_ring_map;
 	struct status_block *s_blk = cp->status_blk.gen;
 
 	sb_id = cp->status_blk_num;
@@ -3561,18 +3764,18 @@
 	val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
 	cnic_ctx_wr(dev, cid_addr, offset1, val);
 
-	txbd = (struct tx_bd *) cp->l2_ring;
+	txbd = (struct tx_bd *) udev->l2_ring;
 
-	buf_map = cp->l2_buf_map;
+	buf_map = udev->l2_buf_map;
 	for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) {
 		txbd->tx_bd_haddr_hi = (u64) buf_map >> 32;
 		txbd->tx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
 	}
-	val = (u64) cp->l2_ring_map >> 32;
+	val = (u64) ring_map >> 32;
 	cnic_ctx_wr(dev, cid_addr, offset2, val);
 	txbd->tx_bd_haddr_hi = val;
 
-	val = (u64) cp->l2_ring_map & 0xffffffff;
+	val = (u64) ring_map & 0xffffffff;
 	cnic_ctx_wr(dev, cid_addr, offset3, val);
 	txbd->tx_bd_haddr_lo = val;
 }
@@ -3581,10 +3784,12 @@
 {
 	struct cnic_local *cp = dev->cnic_priv;
 	struct cnic_eth_dev *ethdev = cp->ethdev;
+	struct cnic_uio_dev *udev = cp->udev;
 	u32 cid_addr, sb_id, val, coal_reg, coal_val;
 	int i;
 	struct rx_bd *rxbd;
 	struct status_block *s_blk = cp->status_blk.gen;
+	dma_addr_t ring_map = udev->l2_ring_map;
 
 	sb_id = cp->status_blk_num;
 	cnic_init_context(dev, 2);
@@ -3618,22 +3823,22 @@
 		val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id);
 	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
 
-	rxbd = (struct rx_bd *) (cp->l2_ring + BCM_PAGE_SIZE);
+	rxbd = (struct rx_bd *) (udev->l2_ring + BCM_PAGE_SIZE);
 	for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
 		dma_addr_t buf_map;
 		int n = (i % cp->l2_rx_ring_size) + 1;
 
-		buf_map = cp->l2_buf_map + (n * cp->l2_single_buf_size);
+		buf_map = udev->l2_buf_map + (n * cp->l2_single_buf_size);
 		rxbd->rx_bd_len = cp->l2_single_buf_size;
 		rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
 		rxbd->rx_bd_haddr_hi = (u64) buf_map >> 32;
 		rxbd->rx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
 	}
-	val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) >> 32;
+	val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32;
 	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
 	rxbd->rx_bd_haddr_hi = val;
 
-	val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) & 0xffffffff;
+	val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff;
 	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
 	rxbd->rx_bd_haddr_lo = val;
 
@@ -3850,42 +4055,55 @@
 
 	tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2x_bh,
 		     (unsigned long) dev);
-	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
-		err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0,
-				  "cnic", dev);
-		if (err)
-			tasklet_disable(&cp->cnic_irq_task);
-	}
+	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX)
+		err = cnic_request_irq(dev);
+
 	return err;
 }
 
+static inline void cnic_storm_memset_hc_disable(struct cnic_dev *dev,
+						u16 sb_id, u8 sb_index,
+						u8 disable)
+{
+
+	u32 addr = BAR_CSTRORM_INTMEM +
+			CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +
+			offsetof(struct hc_status_block_data_e1x, index_data) +
+			sizeof(struct hc_index_data)*sb_index +
+			offsetof(struct hc_index_data, flags);
+	u16 flags = CNIC_RD16(dev, addr);
+	/* clear and set */
+	flags &= ~HC_INDEX_DATA_HC_ENABLED;
+	flags |= (((~disable) << HC_INDEX_DATA_HC_ENABLED_SHIFT) &
+		  HC_INDEX_DATA_HC_ENABLED);
+	CNIC_WR16(dev, addr, flags);
+}
+
 static void cnic_enable_bnx2x_int(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
 	u8 sb_id = cp->status_blk_num;
-	int port = CNIC_PORT(cp);
 
 	CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
-		 CSTORM_SB_HC_TIMEOUT_C_OFFSET(port, sb_id,
-					       HC_INDEX_C_ISCSI_EQ_CONS),
-		 64 / 12);
-	CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
-		  CSTORM_SB_HC_DISABLE_C_OFFSET(port, sb_id,
-						HC_INDEX_C_ISCSI_EQ_CONS), 0);
+			CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +
+			offsetof(struct hc_status_block_data_e1x, index_data) +
+			sizeof(struct hc_index_data)*HC_INDEX_ISCSI_EQ_CONS +
+			offsetof(struct hc_index_data, timeout), 64 / 12);
+	cnic_storm_memset_hc_disable(dev, sb_id, HC_INDEX_ISCSI_EQ_CONS, 0);
 }
 
 static void cnic_disable_bnx2x_int_sync(struct cnic_dev *dev)
 {
 }
 
-static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
+static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
+				    struct client_init_ramrod_data *data)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) cp->l2_ring;
-	struct eth_context *context;
-	struct regpair context_addr;
-	dma_addr_t buf_map;
-	int func = CNIC_FUNC(cp);
+	struct cnic_uio_dev *udev = cp->udev;
+	union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) udev->l2_ring;
+	dma_addr_t buf_map, ring_map = udev->l2_ring_map;
+	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
 	int port = CNIC_PORT(cp);
 	int i;
 	int cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
@@ -3893,7 +4111,7 @@
 
 	memset(txbd, 0, BCM_PAGE_SIZE);
 
-	buf_map = cp->l2_buf_map;
+	buf_map = udev->l2_buf_map;
 	for (i = 0; i < MAX_TX_DESC_CNT; i += 3, txbd += 3) {
 		struct eth_tx_start_bd *start_bd = &txbd->start_bd;
 		struct eth_tx_bd *reg_bd = &((txbd + 2)->reg_bd);
@@ -3910,33 +4128,23 @@
 		start_bd->general_data |= (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT);
 
 	}
-	context = cnic_get_bnx2x_ctx(dev, BNX2X_ISCSI_L2_CID, 1, &context_addr);
 
-	val = (u64) cp->l2_ring_map >> 32;
+	val = (u64) ring_map >> 32;
 	txbd->next_bd.addr_hi = cpu_to_le32(val);
 
-	context->xstorm_st_context.tx_bd_page_base_hi = val;
+	data->tx.tx_bd_page_base.hi = cpu_to_le32(val);
 
-	val = (u64) cp->l2_ring_map & 0xffffffff;
+	val = (u64) ring_map & 0xffffffff;
 	txbd->next_bd.addr_lo = cpu_to_le32(val);
 
-	context->xstorm_st_context.tx_bd_page_base_lo = val;
+	data->tx.tx_bd_page_base.lo = cpu_to_le32(val);
 
-	context->cstorm_st_context.sb_index_number =
-		HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS;
-	context->cstorm_st_context.status_block_id = BNX2X_DEF_SB_ID;
-
-	if (cli < MAX_X_STAT_COUNTER_ID)
-		context->xstorm_st_context.statistics_data = cli |
-				XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE;
-
-	context->xstorm_ag_context.cdu_reserved =
-		CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func),
-					CDU_REGION_NUMBER_XCM_AG,
-					ETH_CONNECTION_TYPE);
+	/* Other ramrod params */
+	data->tx.tx_sb_index_number = HC_SP_INDEX_ETH_ISCSI_CQ_CONS;
+	data->tx.tx_status_block_id = BNX2X_DEF_SB_ID;
 
 	/* reset xstorm per client statistics */
-	if (cli < MAX_X_STAT_COUNTER_ID) {
+	if (cli < MAX_STAT_COUNTER_ID) {
 		val = BAR_XSTRORM_INTMEM +
 		      XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
 		for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
@@ -3944,111 +4152,77 @@
 	}
 
 	cp->tx_cons_ptr =
-		&cp->bnx2x_def_status_blk->c_def_status_block.index_values[
-			HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS];
+		&sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_CQ_CONS];
 }
 
-static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
+static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
+				    struct client_init_ramrod_data *data)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (cp->l2_ring +
+	struct cnic_uio_dev *udev = cp->udev;
+	struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (udev->l2_ring +
 				BCM_PAGE_SIZE);
 	struct eth_rx_cqe_next_page *rxcqe = (struct eth_rx_cqe_next_page *)
-				(cp->l2_ring + (2 * BCM_PAGE_SIZE));
-	struct eth_context *context;
-	struct regpair context_addr;
+				(udev->l2_ring + (2 * BCM_PAGE_SIZE));
+	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
 	int i;
 	int port = CNIC_PORT(cp);
-	int func = CNIC_FUNC(cp);
 	int cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+	int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
 	u32 val;
-	struct tstorm_eth_client_config tstorm_client = {0};
+	dma_addr_t ring_map = udev->l2_ring_map;
+
+	/* General data */
+	data->general.client_id = cli;
+	data->general.statistics_en_flg = 1;
+	data->general.statistics_counter_id = cli;
+	data->general.activate_flg = 1;
+	data->general.sp_client_id = cli;
 
 	for (i = 0; i < BNX2X_MAX_RX_DESC_CNT; i++, rxbd++) {
 		dma_addr_t buf_map;
 		int n = (i % cp->l2_rx_ring_size) + 1;
 
-		buf_map = cp->l2_buf_map + (n * cp->l2_single_buf_size);
+		buf_map = udev->l2_buf_map + (n * cp->l2_single_buf_size);
 		rxbd->addr_hi = cpu_to_le32((u64) buf_map >> 32);
 		rxbd->addr_lo = cpu_to_le32(buf_map & 0xffffffff);
 	}
-	context = cnic_get_bnx2x_ctx(dev, BNX2X_ISCSI_L2_CID, 0, &context_addr);
 
-	val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) >> 32;
+	val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32;
 	rxbd->addr_hi = cpu_to_le32(val);
+	data->rx.bd_page_base.hi = cpu_to_le32(val);
 
-	context->ustorm_st_context.common.bd_page_base_hi = val;
-
-	val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) & 0xffffffff;
+	val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff;
 	rxbd->addr_lo = cpu_to_le32(val);
-
-	context->ustorm_st_context.common.bd_page_base_lo = val;
-
-	context->ustorm_st_context.common.sb_index_numbers =
-						BNX2X_ISCSI_RX_SB_INDEX_NUM;
-	context->ustorm_st_context.common.clientId = cli;
-	context->ustorm_st_context.common.status_block_id = BNX2X_DEF_SB_ID;
-	if (cli < MAX_U_STAT_COUNTER_ID) {
-		context->ustorm_st_context.common.flags =
-			USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
-		context->ustorm_st_context.common.statistics_counter_id = cli;
-	}
-	context->ustorm_st_context.common.mc_alignment_log_size = 0;
-	context->ustorm_st_context.common.bd_buff_size =
-						cp->l2_single_buf_size;
-
-	context->ustorm_ag_context.cdu_usage =
-		CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func),
-					CDU_REGION_NUMBER_UCM_AG,
-					ETH_CONNECTION_TYPE);
+	data->rx.bd_page_base.lo = cpu_to_le32(val);
 
 	rxcqe += BNX2X_MAX_RCQ_DESC_CNT;
-	val = (u64) (cp->l2_ring_map + (2 * BCM_PAGE_SIZE)) >> 32;
+	val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) >> 32;
 	rxcqe->addr_hi = cpu_to_le32(val);
+	data->rx.cqe_page_base.hi = cpu_to_le32(val);
 
-	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_CQE_PAGE_BASE_OFFSET(port, cli) + 4, val);
-
-	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_CQE_PAGE_NEXT_OFFSET(port, cli) + 4, val);
-
-	val = (u64) (cp->l2_ring_map + (2 * BCM_PAGE_SIZE)) & 0xffffffff;
+	val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) & 0xffffffff;
 	rxcqe->addr_lo = cpu_to_le32(val);
+	data->rx.cqe_page_base.lo = cpu_to_le32(val);
 
-	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_CQE_PAGE_BASE_OFFSET(port, cli), val);
+	/* Other ramrod params */
+	data->rx.client_qzone_id = cl_qzone_id;
+	data->rx.rx_sb_index_number = HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS;
+	data->rx.status_block_id = BNX2X_DEF_SB_ID;
 
-	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_CQE_PAGE_NEXT_OFFSET(port, cli), val);
+	data->rx.cache_line_alignment_log_size = L1_CACHE_SHIFT;
+	data->rx.bd_buff_size =	cpu_to_le16(cp->l2_single_buf_size);
 
-	/* client tstorm info */
-	tstorm_client.mtu = cp->l2_single_buf_size - 14;
-	tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE;
+	data->rx.mtu = cpu_to_le16(cp->l2_single_buf_size - 14);
+	data->rx.outer_vlan_removal_enable_flg = 1;
 
-	if (cli < MAX_T_STAT_COUNTER_ID) {
-		tstorm_client.config_flags |=
-				TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
-		tstorm_client.statistics_counter_id = cli;
-	}
-
-	CNIC_WR(dev, BAR_TSTRORM_INTMEM +
-		   TSTORM_CLIENT_CONFIG_OFFSET(port, cli),
-		   ((u32 *)&tstorm_client)[0]);
-	CNIC_WR(dev, BAR_TSTRORM_INTMEM +
-		   TSTORM_CLIENT_CONFIG_OFFSET(port, cli) + 4,
-		   ((u32 *)&tstorm_client)[1]);
-
-	/* reset tstorm per client statistics */
-	if (cli < MAX_T_STAT_COUNTER_ID) {
-
+	/* reset tstorm and ustorm per client statistics */
+	if (cli < MAX_STAT_COUNTER_ID) {
 		val = BAR_TSTRORM_INTMEM +
 		      TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
 		for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
 			CNIC_WR(dev, val + i * 4, 0);
-	}
 
-	/* reset ustorm per client statistics */
-	if (cli < MAX_U_STAT_COUNTER_ID) {
 		val = BAR_USTRORM_INTMEM +
 		      USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
 		for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
@@ -4056,21 +4230,22 @@
 	}
 
 	cp->rx_cons_ptr =
-		&cp->bnx2x_def_status_blk->u_def_status_block.index_values[
-			HC_INDEX_DEF_U_ETH_ISCSI_RX_CQ_CONS];
+		&sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS];
 }
 
 static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	u32 base, addr, val;
+	u32 base, base2, addr, val;
 	int port = CNIC_PORT(cp);
 
 	dev->max_iscsi_conn = 0;
 	base = CNIC_RD(dev, MISC_REG_SHARED_MEM_ADDR);
-	if (base < 0xa0000 || base >= 0xc0000)
+	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);
 
@@ -4103,16 +4278,25 @@
 			val16 ^= 0x1e1e;
 		dev->max_iscsi_conn = val16;
 	}
-	if (BNX2X_CHIP_IS_E1H(cp->chip_id)) {
+	if (BNX2X_CHIP_IS_E1H(cp->chip_id) || BNX2X_CHIP_IS_E2(cp->chip_id)) {
 		int func = CNIC_FUNC(cp);
+		u32 mf_cfg_addr;
 
-		addr = BNX2X_SHMEM_ADDR(base,
-				mf_cfg.func_mf_config[func].e1hov_tag);
+		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;
+
+		addr = mf_cfg_addr +
+			offsetof(struct mf_cfg, 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) {
-			addr = BNX2X_SHMEM_ADDR(base,
-				mf_cfg.func_mf_config[func].config);
+			addr = mf_cfg_addr +
+				offsetof(struct mf_cfg,
+					 func_mf_config[func].config);
 			val = CNIC_RD(dev, addr);
 			val &= FUNC_MF_CFG_PROTOCOL_MASK;
 			if (val != FUNC_MF_CFG_PROTOCOL_ISCSI)
@@ -4124,10 +4308,26 @@
 static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
 	int func = CNIC_FUNC(cp), ret, i;
-	int port = CNIC_PORT(cp);
-	u16 eq_idx;
-	u8 sb_id = cp->status_blk_num;
+	u32 pfid;
+
+	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+		u32 val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN_OVWR);
+
+		if (!(val & 1))
+			val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN);
+		else
+			val = (val >> 1) & 1;
+
+		if (val)
+			cp->pfid = func >> 1;
+		else
+			cp->pfid = func & 0x6;
+	} else {
+		cp->pfid = func;
+	}
+	pfid = cp->pfid;
 
 	ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ,
 			       cp->iscsi_start_cid);
@@ -4135,86 +4335,98 @@
 	if (ret)
 		return -ENOMEM;
 
+	cp->bnx2x_igu_sb_id = ethdev->irq_arr[0].status_blk_num2;
+
 	cp->kcq1.io_addr = BAR_CSTRORM_INTMEM +
-			  CSTORM_ISCSI_EQ_PROD_OFFSET(func, 0);
+			  CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0);
 	cp->kcq1.sw_prod_idx = 0;
 
-	cp->kcq1.hw_prod_idx_ptr =
-		&cp->status_blk.bnx2x->c_status_block.index_values[
-			HC_INDEX_C_ISCSI_EQ_CONS];
-	cp->kcq1.status_idx_ptr =
-		&cp->status_blk.bnx2x->c_status_block.status_block_index;
+	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+		struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
+
+		cp->kcq1.hw_prod_idx_ptr =
+			&sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS];
+		cp->kcq1.status_idx_ptr =
+			&sb->sb.running_index[SM_RX_ID];
+	} else {
+		struct host_hc_status_block_e1x *sb = cp->status_blk.gen;
+
+		cp->kcq1.hw_prod_idx_ptr =
+			&sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS];
+		cp->kcq1.status_idx_ptr =
+			&sb->sb.running_index[SM_RX_ID];
+	}
 
 	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 +
-		CSTORM_ISCSI_EQ_CONS_OFFSET(func, 0), 0);
+		CSTORM_ISCSI_EQ_CONS_OFFSET(pfid, 0), 0);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(func, 0),
+		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfid, 0),
 		cp->kcq1.dma.pg_map_arr[1] & 0xffffffff);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(func, 0) + 4,
+		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfid, 0) + 4,
 		(u64) cp->kcq1.dma.pg_map_arr[1] >> 32);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(func, 0),
+		CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfid, 0),
 		cp->kcq1.dma.pg_map_arr[0] & 0xffffffff);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(func, 0) + 4,
+		CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfid, 0) + 4,
 		(u64) cp->kcq1.dma.pg_map_arr[0] >> 32);
 	CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(func, 0), 1);
+		CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfid, 0), 1);
 	CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_SB_NUM_OFFSET(func, 0), cp->status_blk_num);
+		CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfid, 0), cp->status_blk_num);
 	CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(func, 0),
-		HC_INDEX_C_ISCSI_EQ_CONS);
+		CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfid, 0),
+		HC_INDEX_ISCSI_EQ_CONS);
 
 	for (i = 0; i < cp->conn_buf_info.num_pages; i++) {
 		CNIC_WR(dev, BAR_TSTRORM_INTMEM +
-			TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(func, i),
+			TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i),
 			cp->conn_buf_info.pgtbl[2 * i]);
 		CNIC_WR(dev, BAR_TSTRORM_INTMEM +
-			TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(func, i) + 4,
+			TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i) + 4,
 			cp->conn_buf_info.pgtbl[(2 * i) + 1]);
 	}
 
 	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(func),
+		USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfid),
 		cp->gbl_buf_info.pg_map_arr[0] & 0xffffffff);
 	CNIC_WR(dev, BAR_USTRORM_INTMEM +
-		USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(func) + 4,
+		USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfid) + 4,
 		(u64) cp->gbl_buf_info.pg_map_arr[0] >> 32);
 
+	CNIC_WR(dev, BAR_TSTRORM_INTMEM +
+		TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfid), DEF_RCV_BUF);
+
 	cnic_setup_bnx2x_context(dev);
 
-	eq_idx = CNIC_RD16(dev, BAR_CSTRORM_INTMEM +
-			   CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, sb_id) +
-			   offsetof(struct cstorm_status_block_c,
-				    index_values[HC_INDEX_C_ISCSI_EQ_CONS]));
-	if (eq_idx != 0) {
-		netdev_err(dev->netdev, "EQ cons index %x != 0\n", eq_idx);
-		return -EBUSY;
-	}
 	ret = cnic_init_bnx2x_irq(dev);
 	if (ret)
 		return ret;
 
-	cnic_init_bnx2x_tx_ring(dev);
-	cnic_init_bnx2x_rx_ring(dev);
-
 	return 0;
 }
 
 static void cnic_init_rings(struct cnic_dev *dev)
 {
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_uio_dev *udev = cp->udev;
+
+	if (test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
+		return;
+
 	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
 		cnic_init_bnx2_tx_ring(dev);
 		cnic_init_bnx2_rx_ring(dev);
+		set_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
 	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
-		struct cnic_local *cp = dev->cnic_priv;
 		u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+		u32 cl_qzone_id, type;
+		struct client_init_ramrod_data *data;
 		union l5cm_specific_data l5_data;
 		struct ustorm_eth_rx_producers rx_prods = {0};
 		u32 off, i;
@@ -4223,21 +4435,38 @@
 		rx_prods.cqe_prod = BNX2X_MAX_RCQ_DESC_CNT;
 		barrier();
 
+		cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
+
 		off = BAR_USTRORM_INTMEM +
-			USTORM_RX_PRODS_OFFSET(CNIC_PORT(cp), cli);
+			(BNX2X_CHIP_IS_E2(cp->chip_id) ?
+			 USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) :
+			 USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli));
 
 		for (i = 0; i < sizeof(struct ustorm_eth_rx_producers) / 4; i++)
 			CNIC_WR(dev, off + i * 4, ((u32 *) &rx_prods)[i]);
 
 		set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
 
-		cnic_init_bnx2x_tx_ring(dev);
-		cnic_init_bnx2x_rx_ring(dev);
+		data = udev->l2_buf;
 
-		l5_data.phy_address.lo = cli;
-		l5_data.phy_address.hi = 0;
+		memset(data, 0, sizeof(*data));
+
+		cnic_init_bnx2x_tx_ring(dev, data);
+		cnic_init_bnx2x_rx_ring(dev, data);
+
+		l5_data.phy_address.lo = udev->l2_buf_map & 0xffffffff;
+		l5_data.phy_address.hi = (u64) udev->l2_buf_map >> 32;
+
+		type = (ETH_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
+			& SPE_HDR_CONN_TYPE;
+		type |= ((cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
+			SPE_HDR_FUNCTION_ID);
+
+		set_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
+
 		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CLIENT_SETUP,
-			BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE, &l5_data);
+			BNX2X_ISCSI_L2_CID, type, &l5_data);
+
 		i = 0;
 		while (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags) &&
 		       ++i < 10)
@@ -4246,13 +4475,18 @@
 		if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
 			netdev_err(dev->netdev,
 				"iSCSI CLIENT_SETUP did not complete\n");
-		cnic_kwq_completion(dev, 1);
+		cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
 		cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 1);
 	}
 }
 
 static void cnic_shutdown_rings(struct cnic_dev *dev)
 {
+	struct cnic_local *cp = dev->cnic_priv;
+
+	if (!test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
+		return;
+
 	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
 		cnic_shutdown_bnx2_rx_ring(dev);
 	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
@@ -4260,6 +4494,7 @@
 		u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
 		union l5cm_specific_data l5_data;
 		int i;
+		u32 type;
 
 		cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 0);
 
@@ -4277,14 +4512,18 @@
 		if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
 			netdev_err(dev->netdev,
 				"iSCSI CLIENT_HALT did not complete\n");
-		cnic_kwq_completion(dev, 1);
+		cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
 
 		memset(&l5_data, 0, sizeof(l5_data));
-		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CFC_DEL,
-			BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE |
-			(1 << SPE_HDR_COMMON_RAMROD_SHIFT), &l5_data);
+		type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
+			& SPE_HDR_CONN_TYPE;
+		type |= ((cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
+			 SPE_HDR_FUNCTION_ID);
+		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
+			BNX2X_ISCSI_L2_CID, type, &l5_data);
 		msleep(10);
 	}
+	clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
 }
 
 static int cnic_register_netdev(struct cnic_dev *dev)
@@ -4327,7 +4566,6 @@
 		return -EALREADY;
 
 	dev->regview = ethdev->io_base;
-	cp->chip_id = ethdev->chip_id;
 	pci_dev_get(dev->pcidev);
 	cp->func = PCI_FUNC(dev->pcidev->devfn);
 	cp->status_blk.gen = ethdev->irq_arr[0].status_blk;
@@ -4379,17 +4617,11 @@
 static void cnic_stop_bnx2x_hw(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	u8 sb_id = cp->status_blk_num;
-	int port = CNIC_PORT(cp);
 
 	cnic_free_irq(dev);
-	CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
-		  CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, sb_id) +
-		  offsetof(struct cstorm_status_block_c,
-			   index_values[HC_INDEX_C_ISCSI_EQ_CONS]),
-		  0);
+	*cp->kcq1.hw_prod_idx_ptr = 0;
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
-		CSTORM_ISCSI_EQ_CONS_OFFSET(cp->func, 0), 0);
+		CSTORM_ISCSI_EQ_CONS_OFFSET(cp->pfid, 0), 0);
 	CNIC_WR16(dev, cp->kcq1.io_addr, 0);
 	cnic_free_resc(dev);
 }
@@ -4403,10 +4635,11 @@
 		/* Need to wait for the ring shutdown event to complete
 		 * before clearing the CNIC_UP flag.
 		 */
-		while (cp->uio_dev != -1 && i < 15) {
+		while (cp->udev->uio_dev != -1 && i < 15) {
 			msleep(100);
 			i++;
 		}
+		cnic_shutdown_rings(dev);
 		clear_bit(CNIC_F_CNIC_UP, &dev->flags);
 		rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], NULL);
 		synchronize_rcu();
@@ -4455,7 +4688,6 @@
 
 	cp = cdev->cnic_priv;
 	cp->dev = cdev;
-	cp->uio_dev = -1;
 	cp->l2_single_buf_size = 0x400;
 	cp->l2_rx_ring_size = 3;
 
@@ -4510,6 +4742,7 @@
 	cp = cdev->cnic_priv;
 	cp->ethdev = ethdev;
 	cdev->pcidev = pdev;
+	cp->chip_id = ethdev->chip_id;
 
 	cp->cnic_ops = &cnic_bnx2_ops;
 	cp->start_hw = cnic_start_bnx2_hw;
@@ -4564,6 +4797,7 @@
 	cp = cdev->cnic_priv;
 	cp->ethdev = ethdev;
 	cdev->pcidev = pdev;
+	cp->chip_id = ethdev->chip_id;
 
 	cp->cnic_ops = &cnic_bnx2x_ops;
 	cp->start_hw = cnic_start_bnx2x_hw;
@@ -4575,7 +4809,10 @@
 	cp->stop_cm = cnic_cm_stop_bnx2x_hw;
 	cp->enable_int = cnic_enable_bnx2x_int;
 	cp->disable_int_sync = cnic_disable_bnx2x_int_sync;
-	cp->ack_int = cnic_ack_bnx2x_msix;
+	if (BNX2X_CHIP_IS_E2(cp->chip_id))
+		cp->ack_int = cnic_ack_bnx2x_e2_msix;
+	else
+		cp->ack_int = cnic_ack_bnx2x_msix;
 	cp->close_conn = cnic_close_bnx2x_conn;
 	cp->next_idx = cnic_bnx2x_next_idx;
 	cp->hw_idx = cnic_bnx2x_hw_idx;
@@ -4683,6 +4920,7 @@
 static void cnic_release(void)
 {
 	struct cnic_dev *dev;
+	struct cnic_uio_dev *udev;
 
 	while (!list_empty(&cnic_dev_list)) {
 		dev = list_entry(cnic_dev_list.next, struct cnic_dev, list);
@@ -4696,6 +4934,11 @@
 		list_del_init(&dev->list);
 		cnic_free_dev(dev);
 	}
+	while (!list_empty(&cnic_udev_list)) {
+		udev = list_entry(cnic_udev_list.next, struct cnic_uio_dev,
+				  list);
+		cnic_free_uio(udev);
+	}
 }
 
 static int __init cnic_init(void)
@@ -4710,6 +4953,13 @@
 		return rc;
 	}
 
+	cnic_wq = create_singlethread_workqueue("cnic_wq");
+	if (!cnic_wq) {
+		cnic_release();
+		unregister_netdevice_notifier(&cnic_netdev_notifier);
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 
@@ -4717,6 +4967,7 @@
 {
 	unregister_netdevice_notifier(&cnic_netdev_notifier);
 	cnic_release();
+	destroy_workqueue(cnic_wq);
 }
 
 module_init(cnic_init);
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index 275c361..6a4a0ae 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -12,6 +12,13 @@
 #ifndef CNIC_H
 #define CNIC_H
 
+#define HC_INDEX_ISCSI_EQ_CONS			6
+
+#define HC_INDEX_FCOE_EQ_CONS			3
+
+#define HC_SP_INDEX_ETH_ISCSI_CQ_CONS		5
+#define HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS	1
+
 #define KWQ_PAGE_CNT	4
 #define KCQ_PAGE_CNT	16
 
@@ -161,8 +168,9 @@
 	wait_queue_head_t	waitq;
 	int			wait_cond;
 	unsigned long		timestamp;
-	u32			ctx_flags;
-#define	CTX_FL_OFFLD_START	0x00000001
+	unsigned long		ctx_flags;
+#define	CTX_FL_OFFLD_START	0
+#define	CTX_FL_DELETE_WAIT	1
 	u8			ulp_proto_id;
 	union {
 		struct cnic_iscsi	*iscsi;
@@ -179,6 +187,31 @@
 	u32		io_addr;
 };
 
+struct iro {
+	u32 base;
+	u16 m1;
+	u16 m2;
+	u16 m3;
+	u16 size;
+};
+
+struct cnic_uio_dev {
+	struct uio_info		cnic_uinfo;
+	u32			uio_dev;
+
+	int			l2_ring_size;
+	void			*l2_ring;
+	dma_addr_t		l2_ring_map;
+
+	int			l2_buf_size;
+	void			*l2_buf;
+	dma_addr_t		l2_buf_map;
+
+	struct cnic_dev		*dev;
+	struct pci_dev		*pdev;
+	struct list_head	list;
+};
+
 struct cnic_local {
 
 	spinlock_t cnic_ulp_lock;
@@ -192,19 +225,15 @@
 	unsigned long cnic_local_flags;
 #define	CNIC_LCL_FL_KWQ_INIT		0x0
 #define	CNIC_LCL_FL_L2_WAIT		0x1
+#define	CNIC_LCL_FL_RINGS_INITED	0x2
 
 	struct cnic_dev *dev;
 
 	struct cnic_eth_dev *ethdev;
 
-	void		*l2_ring;
-	dma_addr_t	l2_ring_map;
-	int		l2_ring_size;
-	int		l2_rx_ring_size;
+	struct cnic_uio_dev *udev;
 
-	void		*l2_buf;
-	dma_addr_t	l2_buf_map;
-	int		l2_buf_size;
+	int		l2_rx_ring_size;
 	int		l2_single_buf_size;
 
 	u16		*rx_cons_ptr;
@@ -212,6 +241,9 @@
 	u16		rx_cons;
 	u16		tx_cons;
 
+	struct iro		*iro_arr;
+#define IRO (((struct cnic_local *) dev->cnic_priv)->iro_arr)
+
 	struct cnic_dma		kwq_info;
 	struct kwqe		**kwq;
 
@@ -230,12 +262,16 @@
 	union {
 		void				*gen;
 		struct status_block_msix	*bnx2;
-		struct host_status_block	*bnx2x;
+		struct host_hc_status_block_e1x	*bnx2x_e1x;
+		/* index values - which counter to update */
+		#define SM_RX_ID		0
+		#define SM_TX_ID		1
 	} status_blk;
 
-	struct host_def_status_block	*bnx2x_def_status_blk;
+	struct host_sp_status_block	*bnx2x_def_status_blk;
 
 	u32				status_blk_num;
+	u32				bnx2x_igu_sb_id;
 	u32				int_num;
 	u32				last_status_idx;
 	struct tasklet_struct		cnic_irq_task;
@@ -264,6 +300,8 @@
 	int			hq_size;
 	int			num_cqs;
 
+	struct delayed_work	delete_task;
+
 	struct cnic_ctx		*ctx_arr;
 	int			ctx_blks;
 	int			ctx_blk_size;
@@ -272,11 +310,9 @@
 
 	u32			chip_id;
 	int			func;
+	u32			pfid;
 	u32			shmem_base;
 
-	u32			uio_dev;
-	struct uio_info		*cnic_uinfo;
-
 	struct cnic_ops		*cnic_ops;
 	int			(*start_hw)(struct cnic_dev *);
 	void			(*stop_hw)(struct cnic_dev *);
@@ -335,18 +371,36 @@
 #define BNX2X_ISCSI_GLB_BUF_SIZE	64
 #define BNX2X_ISCSI_PBL_NOT_CACHED	0xff
 #define BNX2X_ISCSI_PDU_HEADER_NOT_CACHED	0xff
-#define BNX2X_HW_CID(x, func)		((x) | (((func) % PORT_MAX) << 23) | \
-					 (((func) >> 1) << 17))
-#define BNX2X_SW_CID(x)			(x & 0x1ffff)
+
+#define BNX2X_CHIP_NUM_57710		0x164e
 #define BNX2X_CHIP_NUM_57711		0x164f
 #define BNX2X_CHIP_NUM_57711E		0x1650
+#define BNX2X_CHIP_NUM_57712		0x1662
+#define BNX2X_CHIP_NUM_57712E		0x1663
+#define BNX2X_CHIP_NUM_57713		0x1651
+#define BNX2X_CHIP_NUM_57713E		0x1652
+
 #define BNX2X_CHIP_NUM(x)		(x >> 16)
+#define BNX2X_CHIP_IS_57710(x)		\
+	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57710)
 #define BNX2X_CHIP_IS_57711(x)		\
 	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57711)
 #define BNX2X_CHIP_IS_57711E(x)		\
 	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57711E)
 #define BNX2X_CHIP_IS_E1H(x)		\
 	(BNX2X_CHIP_IS_57711(x) || BNX2X_CHIP_IS_57711E(x))
+#define BNX2X_CHIP_IS_57712(x)		\
+	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57712)
+#define BNX2X_CHIP_IS_57712E(x)		\
+	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57712E)
+#define BNX2X_CHIP_IS_57713(x)		\
+	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713)
+#define BNX2X_CHIP_IS_57713E(x)		\
+	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713E)
+#define BNX2X_CHIP_IS_E2(x)		\
+	(BNX2X_CHIP_IS_57712(x) || BNX2X_CHIP_IS_57712E(x) || \
+	 BNX2X_CHIP_IS_57713(x) || BNX2X_CHIP_IS_57713E(x))
+
 #define IS_E1H_OFFSET       		BNX2X_CHIP_IS_E1H(cp->chip_id)
 
 #define BNX2X_RX_DESC_CNT		(BCM_PAGE_SIZE / sizeof(struct eth_rx_bd))
@@ -358,19 +412,35 @@
 		(BNX2X_MAX_RCQ_DESC_CNT - 1)) ?				\
 		((x) + 2) : ((x) + 1)
 
-#define BNX2X_DEF_SB_ID			16
+#define BNX2X_DEF_SB_ID			HC_SP_SB_ID
 
-#define BNX2X_ISCSI_RX_SB_INDEX_NUM					\
-		((HC_INDEX_DEF_U_ETH_ISCSI_RX_CQ_CONS << \
-		  USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER_SHIFT) & \
-		 USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER)
+#define BNX2X_SHMEM_MF_BLK_OFFSET	0x7e4
 
 #define BNX2X_SHMEM_ADDR(base, field)	(base + \
 					 offsetof(struct shmem_region, field))
 
-#define CNIC_PORT(cp)			((cp)->func % PORT_MAX)
-#define CNIC_FUNC(cp)			((cp)->func)
-#define CNIC_E1HVN(cp)			((cp)->func >> 1)
+#define BNX2X_SHMEM2_ADDR(base, field)	(base + \
+					 offsetof(struct shmem2_region, field))
 
+#define BNX2X_SHMEM2_HAS(base, field)				\
+		((base) &&					\
+		 (CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base, size)) >	\
+		  offsetof(struct shmem2_region, field)))
+
+#define CNIC_PORT(cp)			((cp)->pfid & 1)
+#define CNIC_FUNC(cp)			((cp)->func)
+#define CNIC_PATH(cp)			(!BNX2X_CHIP_IS_E2(cp->chip_id) ? 0 :\
+					 (CNIC_FUNC(cp) & 1))
+#define CNIC_E1HVN(cp)			((cp)->pfid >> 1)
+
+#define BNX2X_HW_CID(cp, x)		((CNIC_PORT(cp) << 23) | \
+					 (CNIC_E1HVN(cp) << 17) | (x))
+
+#define BNX2X_SW_CID(x)			(x & 0x1ffff)
+
+#define BNX2X_CL_QZONE_ID(cp, cli)					\
+		(cli + (CNIC_PORT(cp) * ETH_MAX_RX_CLIENTS_E1H))
+
+#define TCP_TSTORM_OOO_DROP_AND_PROC_ACK	(0<<4)
 #endif
 
diff --git a/drivers/net/cnic_defs.h b/drivers/net/cnic_defs.h
index 7ce694d..328e8b2 100644
--- a/drivers/net/cnic_defs.h
+++ b/drivers/net/cnic_defs.h
@@ -14,6 +14,7 @@
 
 /* KWQ (kernel work queue) request op codes */
 #define L2_KWQE_OPCODE_VALUE_FLUSH                  (4)
+#define L2_KWQE_OPCODE_VALUE_VM_FREE_RX_QUEUE       (8)
 
 #define L4_KWQE_OPCODE_VALUE_CONNECT1               (50)
 #define L4_KWQE_OPCODE_VALUE_CONNECT2               (51)
@@ -48,11 +49,14 @@
 #define L4_KCQE_OPCODE_VALUE_UPLOAD_PG              (14)
 
 /* KCQ (kernel completion queue) completion status */
-#define L4_KCQE_COMPLETION_STATUS_SUCCESS		    (0)
-#define L4_KCQE_COMPLETION_STATUS_TIMEOUT        (0x93)
+#define L4_KCQE_COMPLETION_STATUS_SUCCESS           (0)
+#define L4_KCQE_COMPLETION_STATUS_TIMEOUT           (0x93)
 
-#define L4_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAIL (0x83)
-#define L4_KCQE_COMPLETION_STATUS_OFFLOADED_PG   (0x89)
+#define L4_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAIL    (0x83)
+#define L4_KCQE_COMPLETION_STATUS_OFFLOADED_PG      (0x89)
+
+#define L4_KCQE_OPCODE_VALUE_OOO_EVENT_NOTIFICATION (0xa0)
+#define L4_KCQE_OPCODE_VALUE_OOO_FLUSH              (0xa1)
 
 #define L4_LAYER_CODE (4)
 #define L2_LAYER_CODE (2)
@@ -585,6 +589,100 @@
  */
 
 /*
+ * The iscsi aggregative context of Cstorm
+ */
+struct cstorm_iscsi_ag_context {
+	u32 agg_vars1;
+#define CSTORM_ISCSI_AG_CONTEXT_STATE (0xFF<<0)
+#define CSTORM_ISCSI_AG_CONTEXT_STATE_SHIFT 0
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<8)
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 8
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<9)
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 9
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<10)
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 10
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<11)
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 11
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN (0x1<<12)
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN_SHIFT 12
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN (0x1<<13)
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN_SHIFT 13
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF (0x3<<14)
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_SHIFT 14
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66 (0x3<<16)
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66_SHIFT 16
+#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN (0x1<<18)
+#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN_SHIFT 18
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN (0x1<<19)
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN_SHIFT 19
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN (0x1<<20)
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN_SHIFT 20
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN (0x1<<21)
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN_SHIFT 21
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN (0x1<<22)
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN_SHIFT 22
+#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE (0x7<<23)
+#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE_SHIFT 23
+#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE (0x3<<26)
+#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE_SHIFT 26
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED52 (0x3<<28)
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED52_SHIFT 28
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED53 (0x3<<30)
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED53_SHIFT 30
+#if defined(__BIG_ENDIAN)
+	u8 __aux1_th;
+	u8 __aux1_val;
+	u16 __agg_vars2;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __agg_vars2;
+	u8 __aux1_val;
+	u8 __aux1_th;
+#endif
+	u32 rel_seq;
+	u32 rel_seq_th;
+#if defined(__BIG_ENDIAN)
+	u16 hq_cons;
+	u16 hq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 hq_prod;
+	u16 hq_cons;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 __reserved62;
+	u8 __reserved61;
+	u8 __reserved60;
+	u8 __reserved59;
+#elif defined(__LITTLE_ENDIAN)
+	u8 __reserved59;
+	u8 __reserved60;
+	u8 __reserved61;
+	u8 __reserved62;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 __reserved64;
+	u16 __cq_u_prod0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __cq_u_prod0;
+	u16 __reserved64;
+#endif
+	u32 __cq_u_prod1;
+#if defined(__BIG_ENDIAN)
+	u16 __agg_vars3;
+	u16 __cq_u_prod2;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __cq_u_prod2;
+	u16 __agg_vars3;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 __aux2_th;
+	u16 __cq_u_prod3;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __cq_u_prod3;
+	u16 __aux2_th;
+#endif
+};
+
+/*
  * iSCSI context region, used only in iSCSI
  */
 struct ustorm_iscsi_rq_db {
@@ -696,7 +794,7 @@
 	struct regpair task_pbl_base;
 	struct regpair tce_phy_addr;
 	struct ustorm_iscsi_placement_db place_db;
-	u32 data_rcv_seq;
+	u32 reserved8;
 	u32 rem_rcv_len;
 #if defined(__BIG_ENDIAN)
 	u16 hdr_itt;
@@ -713,8 +811,10 @@
 #define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
 #define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
 #define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x3F<<2)
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
 	u8 task_pdu_cache_index;
 	u8 task_pbe_cache_index;
 #elif defined(__LITTLE_ENDIAN)
@@ -725,8 +825,10 @@
 #define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
 #define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
 #define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x3F<<2)
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
 	u8 hdr_second_byte_union;
 #endif
 #if defined(__BIG_ENDIAN)
@@ -777,14 +879,14 @@
  */
 struct tstorm_tcp_st_context_section {
 	u32 flags1;
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_20B (0xFFFFFF<<0)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_20B_SHIFT 0
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT (0xFFFFFF<<0)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_SHIFT 0
 #define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID (0x1<<24)
 #define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID_SHIFT 24
 #define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS (0x1<<25)
 #define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS_SHIFT 25
-#define TSTORM_TCP_ST_CONTEXT_SECTION_ISLE_EXISTS (0x1<<26)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_ISLE_EXISTS_SHIFT 26
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0 (0x1<<26)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0_SHIFT 26
 #define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD (0x1<<27)
 #define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD_SHIFT 27
 #define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED (0x1<<28)
@@ -793,11 +895,11 @@
 #define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE_SHIFT 29
 #define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN (0x1<<30)
 #define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN_SHIFT 30
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED3 (0x1<<31)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED3_SHIFT 31
+#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN (0x1<<31)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN_SHIFT 31
 	u32 flags2;
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_20B (0xFFFFFF<<0)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_20B_SHIFT 0
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION (0xFFFFFF<<0)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_SHIFT 0
 #define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN (0x1<<24)
 #define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN_SHIFT 24
 #define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN (0x1<<25)
@@ -810,18 +912,18 @@
 #define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 28
 #define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<29)
 #define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 29
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_SECOND_ISLE_DROPPED (0x1<<30)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_SECOND_ISLE_DROPPED_SHIFT 30
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_DONT_SUPPORT_OOO (0x1<<31)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_DONT_SUPPORT_OOO_SHIFT 31
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK (0x1<<30)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK_SHIFT 30
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK (0x1<<31)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK_SHIFT 31
 #if defined(__BIG_ENDIAN)
-	u16 reserved_slowpath;
-	u8 tcp_sm_state_3b;
-	u8 rto_exp_3b;
+	u16 mss;
+	u8 tcp_sm_state;
+	u8 rto_exp;
 #elif defined(__LITTLE_ENDIAN)
-	u8 rto_exp_3b;
-	u8 tcp_sm_state_3b;
-	u16 reserved_slowpath;
+	u8 rto_exp;
+	u8 tcp_sm_state;
+	u16 mss;
 #endif
 	u32 rcv_nxt;
 	u32 timestamp_recent;
@@ -846,11 +948,11 @@
 #if defined(__BIG_ENDIAN)
 	u8 statistics_counter_id;
 	u8 ooo_support_mode;
-	u8 snd_wnd_scale_4b;
+	u8 snd_wnd_scale;
 	u8 dup_ack_count;
 #elif defined(__LITTLE_ENDIAN)
 	u8 dup_ack_count;
-	u8 snd_wnd_scale_4b;
+	u8 snd_wnd_scale;
 	u8 ooo_support_mode;
 	u8 statistics_counter_id;
 #endif
@@ -860,13 +962,21 @@
 	u32 isle_start_seq;
 	u32 isle_end_seq;
 #if defined(__BIG_ENDIAN)
-	u16 mss;
+	u16 second_isle_address;
 	u16 recent_seg_wnd;
 #elif defined(__LITTLE_ENDIAN)
 	u16 recent_seg_wnd;
-	u16 mss;
+	u16 second_isle_address;
 #endif
-	u32 reserved4;
+#if defined(__BIG_ENDIAN)
+	u8 max_isles_ever_happened;
+	u8 isles_number;
+	u16 last_isle_address;
+#elif defined(__LITTLE_ENDIAN)
+	u16 last_isle_address;
+	u8 isles_number;
+	u8 max_isles_ever_happened;
+#endif
 	u32 max_rt_time;
 #if defined(__BIG_ENDIAN)
 	u16 lsb_mac_address;
@@ -876,7 +986,7 @@
 	u16 lsb_mac_address;
 #endif
 	u32 msb_mac_address;
-	u32 reserved2;
+	u32 rightmost_received_seq;
 };
 
 /*
@@ -951,7 +1061,7 @@
 	u8 scratchpad_idx;
 	struct iscsi_term_vars term_vars;
 #endif
-	u32 reserved2;
+	u32 process_nxt;
 };
 
 /*
@@ -1174,24 +1284,12 @@
 #endif
 #if defined(__BIG_ENDIAN)
 	u8 cdu_reserved;
-	u8 agg_vars4;
-#define XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF (0x3<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF (0x3<<2)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_SHIFT 2
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_EN (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_EN_SHIFT 4
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_EN (0x1<<5)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_EN_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_EN (0x1<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_EN_SHIFT 6
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_EN_SHIFT 7
+	u8 __agg_vars4;
 	u8 agg_vars3;
 #define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
 #define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF (0x3<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_SHIFT 6
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
 	u8 agg_vars2;
 #define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
 #define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
@@ -1222,21 +1320,9 @@
 	u8 agg_vars3;
 #define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
 #define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF (0x3<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_SHIFT 6
-	u8 agg_vars4;
-#define XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF (0x3<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF (0x3<<2)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_SHIFT 2
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_EN (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_EN_SHIFT 4
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_EN (0x1<<5)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_EN_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_EN (0x1<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_EN_SHIFT 6
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_EN_SHIFT 7
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
+	u8 __agg_vars4;
 	u8 cdu_reserved;
 #endif
 	u32 more_to_send;
@@ -1270,8 +1356,8 @@
 #define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
 #define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
 #define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define XSTORM_ISCSI_AG_CONTEXT_AUX18_CF (0x3<<4)
-#define XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_SHIFT 4
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
 #define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
 #define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
 #define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
@@ -1286,8 +1372,8 @@
 #define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
 #define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
 #define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX2_FLAG (0x1<<15)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX2_FLAG_SHIFT 15
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
 	u8 agg_val3_th;
 	u8 agg_vars6;
 #define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
@@ -1310,8 +1396,8 @@
 #define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
 #define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
 #define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define XSTORM_ISCSI_AG_CONTEXT_AUX18_CF (0x3<<4)
-#define XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_SHIFT 4
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
 #define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
 #define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
 #define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
@@ -1326,14 +1412,14 @@
 #define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
 #define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
 #define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX2_FLAG (0x1<<15)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX2_FLAG_SHIFT 15
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
 #endif
 #if defined(__BIG_ENDIAN)
 	u16 __agg_val11_th;
-	u16 __agg_val11;
+	u16 __gen_data;
 #elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val11;
+	u16 __gen_data;
 	u16 __agg_val11_th;
 #endif
 #if defined(__BIG_ENDIAN)
@@ -1384,7 +1470,7 @@
 #endif
 	u32 hq_cons_tcp_seq;
 	u32 exp_stat_sn;
-	u32 agg_misc5;
+	u32 rst_seq_num;
 };
 
 /*
@@ -1478,12 +1564,12 @@
 #define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
 #define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
 #define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
 	u8 state;
 #elif defined(__LITTLE_ENDIAN)
 	u8 state;
@@ -1496,63 +1582,63 @@
 #define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
 #define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
 #define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
 	u16 ulp_credit;
 #endif
 #if defined(__BIG_ENDIAN)
 	u16 __agg_val4;
 	u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<11)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 11
-#define TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
 #define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
 #define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
 #define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
 #define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
 #elif defined(__LITTLE_ENDIAN)
 	u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
 #define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<11)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 11
-#define TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
 #define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
 #define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
 #define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
@@ -1563,100 +1649,6 @@
 };
 
 /*
- * The iscsi aggregative context of Cstorm
- */
-struct cstorm_iscsi_ag_context {
-	u32 agg_vars1;
-#define CSTORM_ISCSI_AG_CONTEXT_STATE (0xFF<<0)
-#define CSTORM_ISCSI_AG_CONTEXT_STATE_SHIFT 0
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<8)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 8
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<9)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 9
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<10)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 10
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<11)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 11
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN (0x1<<12)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN_SHIFT 12
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN (0x1<<13)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN_SHIFT 13
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF (0x3<<14)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_SHIFT 14
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66 (0x3<<16)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66_SHIFT 16
-#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN (0x1<<18)
-#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN_SHIFT 18
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN (0x1<<19)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN_SHIFT 19
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN (0x1<<20)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN_SHIFT 20
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN (0x1<<21)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN_SHIFT 21
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN (0x1<<22)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN_SHIFT 22
-#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE (0x7<<23)
-#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE_SHIFT 23
-#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE (0x3<<26)
-#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE_SHIFT 26
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED52 (0x3<<28)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED52_SHIFT 28
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED53 (0x3<<30)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED53_SHIFT 30
-#if defined(__BIG_ENDIAN)
-	u8 __aux1_th;
-	u8 __aux1_val;
-	u16 __agg_vars2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_vars2;
-	u8 __aux1_val;
-	u8 __aux1_th;
-#endif
-	u32 rel_seq;
-	u32 rel_seq_th;
-#if defined(__BIG_ENDIAN)
-	u16 hq_cons;
-	u16 hq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 hq_prod;
-	u16 hq_cons;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __reserved62;
-	u8 __reserved61;
-	u8 __reserved60;
-	u8 __reserved59;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __reserved59;
-	u8 __reserved60;
-	u8 __reserved61;
-	u8 __reserved62;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __reserved64;
-	u16 __cq_u_prod0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __cq_u_prod0;
-	u16 __reserved64;
-#endif
-	u32 __cq_u_prod1;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_vars3;
-	u16 __cq_u_prod2;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __cq_u_prod2;
-	u16 __agg_vars3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __aux2_th;
-	u16 __cq_u_prod3;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __cq_u_prod3;
-	u16 __aux2_th;
-#endif
-};
-
-/*
  * The iscsi aggregative context of Ustorm
  */
 struct ustorm_iscsi_ag_context {
@@ -1746,8 +1738,8 @@
 #define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
 #define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
 #define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
 #define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
 #define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
 	u8 decision_rule_enable_bits;
@@ -1790,8 +1782,8 @@
 #define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
 #define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
 #define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
 #define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
 #define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
 	u16 __reserved2;
@@ -1799,22 +1791,6 @@
 };
 
 /*
- * Timers connection context
- */
-struct iscsi_timers_block_context {
-	u32 __reserved_0;
-	u32 __reserved_1;
-	u32 __reserved_2;
-	u32 flags;
-#define __ISCSI_TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS (0x3<<0)
-#define __ISCSI_TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS_SHIFT 0
-#define ISCSI_TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG (0x1<<2)
-#define ISCSI_TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG_SHIFT 2
-#define __ISCSI_TIMERS_BLOCK_CONTEXT_RESERVED0 (0x1FFFFFFF<<3)
-#define __ISCSI_TIMERS_BLOCK_CONTEXT_RESERVED0_SHIFT 3
-};
-
-/*
  * Ethernet context section, shared in TOE, RDMA and ISCSI
  */
 struct xstorm_eth_context_section {
@@ -1963,7 +1939,7 @@
 #endif
 #if defined(__BIG_ENDIAN)
 	u8 original_nagle_1b;
-	u8 ts_enabled_1b;
+	u8 ts_enabled;
 	u16 tcp_params;
 #define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE (0xFF<<0)
 #define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE_SHIFT 0
@@ -1973,8 +1949,8 @@
 #define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED_SHIFT 9
 #define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED (0x1<<10)
 #define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED_SHIFT 10
-#define XSTORM_TCP_CONTEXT_SECTION_KA_STATE (0x1<<11)
-#define XSTORM_TCP_CONTEXT_SECTION_KA_STATE_SHIFT 11
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV (0x1<<11)
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV_SHIFT 11
 #define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<12)
 #define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 12
 #define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED (0x1<<13)
@@ -1991,15 +1967,15 @@
 #define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED_SHIFT 9
 #define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED (0x1<<10)
 #define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED_SHIFT 10
-#define XSTORM_TCP_CONTEXT_SECTION_KA_STATE (0x1<<11)
-#define XSTORM_TCP_CONTEXT_SECTION_KA_STATE_SHIFT 11
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV (0x1<<11)
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV_SHIFT 11
 #define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<12)
 #define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 12
 #define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED (0x1<<13)
 #define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED_SHIFT 13
 #define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER (0x3<<14)
 #define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER_SHIFT 14
-	u8 ts_enabled_1b;
+	u8 ts_enabled;
 	u8 original_nagle_1b;
 #endif
 #if defined(__BIG_ENDIAN)
@@ -2030,8 +2006,8 @@
 #define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
 #define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID (0x1F<<2)
 #define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID_SHIFT 2
-#define XSTORM_COMMON_CONTEXT_SECTION_RESERVED0 (0x1<<7)
-#define XSTORM_COMMON_CONTEXT_SECTION_RESERVED0_SHIFT 7
+#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS (0x1<<7)
+#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS_SHIFT 7
 	u8 ip_version_1b;
 #elif defined(__LITTLE_ENDIAN)
 	u8 ip_version_1b;
@@ -2042,8 +2018,8 @@
 #define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
 #define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID (0x1F<<2)
 #define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID_SHIFT 2
-#define XSTORM_COMMON_CONTEXT_SECTION_RESERVED0 (0x1<<7)
-#define XSTORM_COMMON_CONTEXT_SECTION_RESERVED0_SHIFT 7
+#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS (0x1<<7)
+#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS_SHIFT 7
 	u16 reserved;
 #endif
 };
@@ -2284,7 +2260,7 @@
 	struct tstorm_iscsi_ag_context tstorm_ag_context;
 	struct cstorm_iscsi_ag_context cstorm_ag_context;
 	struct ustorm_iscsi_ag_context ustorm_ag_context;
-	struct iscsi_timers_block_context timers_context;
+	struct timers_block_context timers_context;
 	struct regpair upb_context;
 	struct xstorm_iscsi_st_context xstorm_st_context;
 	struct regpair xpb_context;
@@ -2434,16 +2410,16 @@
  * l5cm connection parameters
  */
 union l5cm_reduce_param_union {
-	u32 passive_side_scramble_key;
-	u32 pcs_id;
+	u32 opaque1;
+	u32 opaque2;
 };
 
 /*
  * l5cm connection parameters
  */
 struct l5cm_reduce_conn {
-	union l5cm_reduce_param_union param;
-	u32 isn;
+	union l5cm_reduce_param_union opaque1;
+	u32 opaque2;
 };
 
 /*
diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h
index 344c842..0dbeaec4 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.1.3"
-#define CNIC_MODULE_RELDATE	"June 24, 2010"
+#define CNIC_MODULE_VERSION	"2.2.6"
+#define CNIC_MODULE_RELDATE	"Oct 12, 2010"
 
 #define CNIC_ULP_RDMA		0
 #define CNIC_ULP_ISCSI		1
@@ -80,18 +80,15 @@
 #define DRV_CTL_IO_RD_CMD		0x102
 #define DRV_CTL_CTX_WR_CMD		0x103
 #define DRV_CTL_CTXTBL_WR_CMD		0x104
-#define DRV_CTL_COMPLETION_CMD		0x105
+#define DRV_CTL_RET_L5_SPQ_CREDIT_CMD	0x105
 #define DRV_CTL_START_L2_CMD		0x106
 #define DRV_CTL_STOP_L2_CMD		0x107
+#define DRV_CTL_RET_L2_SPQ_CREDIT_CMD	0x10c
 
 struct cnic_ctl_completion {
 	u32	cid;
 };
 
-struct drv_ctl_completion {
-	u32	comp_count;
-};
-
 struct cnic_ctl_info {
 	int	cmd;
 	union {
@@ -100,6 +97,10 @@
 	} data;
 };
 
+struct drv_ctl_spq_credit {
+	u32	credit_count;
+};
+
 struct drv_ctl_io {
 	u32		cid_addr;
 	u32		offset;
@@ -115,7 +116,7 @@
 struct drv_ctl_info {
 	int	cmd;
 	union {
-		struct drv_ctl_completion comp;
+		struct drv_ctl_spq_credit credit;
 		struct drv_ctl_io io;
 		struct drv_ctl_l2_ring ring;
 		char bytes[MAX_DRV_CTL_DATA];
@@ -138,6 +139,7 @@
 	unsigned int	vector;
 	void		*status_blk;
 	u32		status_blk_num;
+	u32		status_blk_num2;
 	u32		irq_flags;
 #define CNIC_IRQ_FL_MSIX		0x00000001
 };
@@ -152,6 +154,7 @@
 	struct pci_dev	*pdev;
 	void __iomem	*io_base;
 	void __iomem	*io_base2;
+	void		*iro_arr;
 
 	u32		ctx_tbl_offset;
 	u32		ctx_tbl_len;
@@ -160,7 +163,9 @@
 	u32		max_iscsi_conn;
 	u32		max_fcoe_conn;
 	u32		max_rdma_conn;
-	u32		reserved0[2];
+	u32		fcoe_init_cid;
+	u16		iscsi_l2_client_id;
+	u16		iscsi_l2_cid;
 
 	int		num_irq;
 	struct cnic_irq	irq_arr[MAX_CNIC_VEC];
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index e1f6156..fec939f 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -38,7 +38,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
-#include <asm/gpio.h>
+#include <linux/gpio.h>
 #include <asm/atomic.h>
 
 MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>");
@@ -108,7 +108,7 @@
 #define CPMAC_RX_INT_CLEAR		0x019c
 #define CPMAC_MAC_INT_ENABLE		0x01a8
 #define CPMAC_MAC_INT_CLEAR		0x01ac
-#define CPMAC_MAC_ADDR_LO(channel) 	(0x01b0 + (channel) * 4)
+#define CPMAC_MAC_ADDR_LO(channel)	(0x01b0 + (channel) * 4)
 #define CPMAC_MAC_ADDR_MID		0x01d0
 #define CPMAC_MAC_ADDR_HI		0x01d4
 #define CPMAC_MAC_HASH_LO		0x01d8
@@ -227,7 +227,7 @@
 	for (i = 0; i < CPMAC_REG_END; i += 4) {
 		if (i % 16 == 0) {
 			if (i)
-				printk("\n");
+				pr_cont("\n");
 			printk(KERN_DEBUG "%s: reg[%p]:", dev->name,
 			       priv->regs + i);
 		}
@@ -262,7 +262,7 @@
 	for (i = 0; i < skb->len; i++) {
 		if (i % 16 == 0) {
 			if (i)
-				printk("\n");
+				pr_cont("\n");
 			printk(KERN_DEBUG "%s: data[%p]:", dev->name,
 			       skb->data + i);
 		}
@@ -391,7 +391,7 @@
 	if (likely(skb)) {
 		skb_put(desc->skb, desc->datalen);
 		desc->skb->protocol = eth_type_trans(desc->skb, priv->dev);
-		desc->skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(desc->skb);
 		priv->dev->stats.rx_packets++;
 		priv->dev->stats.rx_bytes += desc->datalen;
 		result = desc->skb;
@@ -506,7 +506,7 @@
 					"restart rx from a descriptor that's "
 					"not free: %p\n",
 					priv->dev->name, restart);
-				goto fatal_error;
+			goto fatal_error;
 		}
 
 		cpmac_write(priv->regs, CPMAC_RX_PTR(0), restart->mapping);
@@ -873,7 +873,8 @@
 	return -EINVAL;
 }
 
-static void cpmac_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)
+static void cpmac_get_ringparam(struct net_device *dev,
+						struct ethtool_ringparam *ring)
 {
 	struct cpmac_priv *priv = netdev_priv(dev);
 
@@ -888,7 +889,8 @@
 	ring->tx_pending = 1;
 }
 
-static int cpmac_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)
+static int cpmac_set_ringparam(struct net_device *dev,
+						struct ethtool_ringparam *ring)
 {
 	struct cpmac_priv *priv = netdev_priv(dev);
 
@@ -1012,8 +1014,8 @@
 
 	priv->rx_head->prev->hw_next = (u32)0;
 
-	if ((res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED,
-			       dev->name, dev))) {
+	res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, dev->name, dev);
+	if (res) {
 		if (netif_msg_drv(priv))
 			printk(KERN_ERR "%s: failed to obtain irq\n",
 			       dev->name);
@@ -1133,7 +1135,8 @@
 	}
 
 	if (phy_id == PHY_MAX_ADDR) {
-		dev_err(&pdev->dev, "no PHY present, falling back to switch on MDIO bus 0\n");
+		dev_err(&pdev->dev, "no PHY present, falling back "
+					"to switch on MDIO bus 0\n");
 		strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
 		phy_id = pdev->id;
 	}
@@ -1169,9 +1172,10 @@
 	priv->msg_enable = netif_msg_init(debug_level, 0xff);
 	memcpy(dev->dev_addr, pdata->dev_addr, sizeof(pdata->dev_addr));
 
-	snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
+	snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT,
+						mdio_bus_id, phy_id);
 
-	priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
+	priv->phy = phy_connect(dev, priv->phy_name, cpmac_adjust_link, 0,
 						PHY_INTERFACE_MODE_MII);
 
 	if (IS_ERR(priv->phy)) {
@@ -1182,7 +1186,8 @@
 		goto fail;
 	}
 
-	if ((rc = register_netdev(dev))) {
+	rc = register_netdev(dev);
+	if (rc) {
 		printk(KERN_ERR "cpmac: error %i registering device %s\n", rc,
 		       dev->name);
 		goto fail;
@@ -1248,11 +1253,13 @@
 
 	cpmac_mii->reset(cpmac_mii);
 
-	for (i = 0; i < 300; i++)
-		if ((mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE)))
+	for (i = 0; i < 300; i++) {
+		mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE);
+		if (mask)
 			break;
 		else
 			msleep(10);
+	}
 
 	mask &= 0x7fffffff;
 	if (mask & (mask - 1)) {
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 4cd7f420..ef67be5 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -336,9 +336,6 @@
 		      int irq_vec_idx, const struct qset_params *p,
 		      int ntxq, struct net_device *dev,
 		      struct netdev_queue *netdevq);
-int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx,
-		unsigned char *data);
-irqreturn_t t3_sge_intr_msix(int irq, void *cookie);
 extern struct workqueue_struct *cxgb3_wq;
 
 int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size);
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index fe08a00..5ccb77d 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -673,7 +673,6 @@
 void t3_xgm_intr_disable(struct adapter *adapter, int idx);
 void t3_port_intr_enable(struct adapter *adapter, int idx);
 void t3_port_intr_disable(struct adapter *adapter, int idx);
-void t3_port_intr_clear(struct adapter *adapter, int idx);
 int t3_slow_intr_handler(struct adapter *adapter);
 int t3_phy_intr_handler(struct adapter *adapter);
 
@@ -689,14 +688,10 @@
 int t3_check_tpsram(struct adapter *adapter, const u8 *tp_ram,
 		    unsigned int size);
 int t3_set_proto_sram(struct adapter *adap, const u8 *data);
-int t3_read_flash(struct adapter *adapter, unsigned int addr,
-		  unsigned int nwords, u32 *data, int byte_oriented);
 int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size);
 int t3_get_fw_version(struct adapter *adapter, u32 *vers);
 int t3_check_fw_version(struct adapter *adapter);
 int t3_init_hw(struct adapter *adapter, u32 fw_params);
-void mac_prep(struct cmac *mac, struct adapter *adapter, int index);
-void early_hw_init(struct adapter *adapter, const struct adapter_info *ai);
 int t3_reset_adapter(struct adapter *adapter);
 int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
 		    int reset);
@@ -706,8 +701,6 @@
 void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on);
 void t3_config_rss(struct adapter *adapter, unsigned int rss_config,
 		   const u8 * cpus, const u16 *rspq);
-int t3_read_rss(struct adapter *adapter, u8 * lkup, u16 *map);
-int t3_mps_set_active_ports(struct adapter *adap, unsigned int port_mask);
 int t3_cim_ctl_blk_read(struct adapter *adap, unsigned int addr,
 			unsigned int n, unsigned int *valp);
 int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n,
@@ -731,19 +724,12 @@
 int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
 		unsigned int nroutes);
 void t3_mc5_intr_handler(struct mc5 *mc5);
-int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start, unsigned int n,
-		      u32 *buf);
 
-int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh);
-void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size);
 void t3_tp_set_offload_mode(struct adapter *adap, int enable);
 void t3_tp_get_mib_stats(struct adapter *adap, struct tp_mib_stats *tps);
 void t3_load_mtus(struct adapter *adap, unsigned short mtus[NMTUS],
 		  unsigned short alpha[NCCTRL_WIN],
 		  unsigned short beta[NCCTRL_WIN], unsigned short mtu_cap);
-void t3_read_hw_mtus(struct adapter *adap, unsigned short mtus[NMTUS]);
-void t3_get_cong_cntl_tab(struct adapter *adap,
-			  unsigned short incr[NMTUS][NCCTRL_WIN]);
 void t3_config_trace_filter(struct adapter *adapter,
 			    const struct trace_params *tp, int filter_index,
 			    int invert, int enable);
@@ -769,10 +755,6 @@
 int t3_sge_disable_fl(struct adapter *adapter, unsigned int id);
 int t3_sge_disable_rspcntxt(struct adapter *adapter, unsigned int id);
 int t3_sge_disable_cqcntxt(struct adapter *adapter, unsigned int id);
-int t3_sge_read_ecntxt(struct adapter *adapter, unsigned int id, u32 data[4]);
-int t3_sge_read_fl(struct adapter *adapter, unsigned int id, u32 data[4]);
-int t3_sge_read_cq(struct adapter *adapter, unsigned int id, u32 data[4]);
-int t3_sge_read_rspq(struct adapter *adapter, unsigned int id, u32 data[4]);
 int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op,
 		      unsigned int credits);
 
diff --git a/drivers/net/cxgb3/cxgb3_defs.h b/drivers/net/cxgb3/cxgb3_defs.h
index 47e5376..920d918 100644
--- a/drivers/net/cxgb3/cxgb3_defs.h
+++ b/drivers/net/cxgb3/cxgb3_defs.h
@@ -43,8 +43,6 @@
 
 void *cxgb_alloc_mem(unsigned long size);
 void cxgb_free_mem(void *addr);
-void cxgb_neigh_update(struct neighbour *neigh);
-void cxgb_redirect(struct dst_entry *old, struct dst_entry *new);
 
 /*
  * Map an ATID or STID to their entries in the corresponding TID tables.
@@ -111,7 +109,6 @@
 	return &e->t3c_tid;
 }
 
-int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n);
 int attach_t3cdev(struct t3cdev *dev);
 void detach_t3cdev(struct t3cdev *dev);
 #endif
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index f208712..a04ce6a 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -1286,7 +1286,7 @@
 /*
  * Release resources when all the ports and offloading have been stopped.
  */
-static void cxgb_down(struct adapter *adapter)
+static void cxgb_down(struct adapter *adapter, int on_wq)
 {
 	t3_sge_stop(adapter);
 	spin_lock_irq(&adapter->work_lock);	/* sync with PHY intr task */
@@ -1296,7 +1296,8 @@
 	free_irq_resources(adapter);
 	quiesce_rx(adapter);
 	t3_sge_stop(adapter);
-	flush_workqueue(cxgb3_wq);	/* wait for external IRQ handler */
+	if (!on_wq)
+		flush_workqueue(cxgb3_wq);/* wait for external IRQ handler */
 }
 
 static void schedule_chk_task(struct adapter *adap)
@@ -1374,7 +1375,7 @@
 	clear_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map);
 
 	if (!adapter->open_device_map)
-		cxgb_down(adapter);
+		cxgb_down(adapter, 0);
 
 	cxgb3_offload_deactivate(adapter);
 	return 0;
@@ -1398,7 +1399,10 @@
 			       "Could not initialize offload capabilities\n");
 	}
 
-	dev->real_num_tx_queues = pi->nqsets;
+	netif_set_real_num_tx_queues(dev, pi->nqsets);
+	err = netif_set_real_num_rx_queues(dev, pi->nqsets);
+	if (err)
+		return err;
 	link_start(dev);
 	t3_port_intr_enable(adapter, pi->port_id);
 	netif_tx_start_all_queues(dev);
@@ -1409,7 +1413,7 @@
 	return 0;
 }
 
-static int cxgb_close(struct net_device *dev)
+static int __cxgb_close(struct net_device *dev, int on_wq)
 {
 	struct port_info *pi = netdev_priv(dev);
 	struct adapter *adapter = pi->adapter;
@@ -1436,12 +1440,17 @@
 		cancel_delayed_work_sync(&adapter->adap_check_task);
 
 	if (!adapter->open_device_map)
-		cxgb_down(adapter);
+		cxgb_down(adapter, on_wq);
 
 	cxgb3_event_notify(&adapter->tdev, OFFLOAD_PORT_DOWN, pi->port_id);
 	return 0;
 }
 
+static int cxgb_close(struct net_device *dev)
+{
+	return __cxgb_close(dev, 0);
+}
+
 static struct net_device_stats *cxgb_get_stats(struct net_device *dev)
 {
 	struct port_info *pi = netdev_priv(dev);
@@ -2864,7 +2873,7 @@
 	spin_unlock(&adapter->work_lock);
 }
 
-static int t3_adapter_error(struct adapter *adapter, int reset)
+static int t3_adapter_error(struct adapter *adapter, int reset, int on_wq)
 {
 	int i, ret = 0;
 
@@ -2879,7 +2888,7 @@
 		struct net_device *netdev = adapter->port[i];
 
 		if (netif_running(netdev))
-			cxgb_close(netdev);
+			__cxgb_close(netdev, on_wq);
 	}
 
 	/* Stop SGE timers */
@@ -2950,7 +2959,7 @@
 	int err = 0;
 
 	rtnl_lock();
-	err = t3_adapter_error(adapter, 1);
+	err = t3_adapter_error(adapter, 1, 1);
 	if (!err)
 		err = t3_reenable_adapter(adapter);
 	if (!err)
@@ -3000,7 +3009,7 @@
 	if (state == pci_channel_io_perm_failure)
 		return PCI_ERS_RESULT_DISCONNECT;
 
-	ret = t3_adapter_error(adapter, 0);
+	ret = t3_adapter_error(adapter, 0, 0);
 
 	/* Request a slot reset. */
 	return PCI_ERS_RESULT_NEED_RESET;
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index c6485b3..bcf0753 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -60,11 +60,14 @@
 static const unsigned int MAX_ATIDS = 64 * 1024;
 static const unsigned int ATID_BASE = 0x10000;
 
+static void cxgb_neigh_update(struct neighbour *neigh);
+static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new);
+
 static inline int offload_activated(struct t3cdev *tdev)
 {
 	const struct adapter *adapter = tdev2adap(tdev);
 
-	return (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map));
+	return test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map);
 }
 
 /**
@@ -1015,7 +1018,7 @@
 /*
  * T3CDEV's receive method.
  */
-int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n)
+static int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n)
 {
 	while (n--) {
 		struct sk_buff *skb = *skbs++;
@@ -1070,7 +1073,7 @@
 	return 0;
 }
 
-void cxgb_neigh_update(struct neighbour *neigh)
+static void cxgb_neigh_update(struct neighbour *neigh)
 {
 	struct net_device *dev = neigh->dev;
 
@@ -1104,7 +1107,7 @@
 	tdev->send(tdev, skb);
 }
 
-void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
+static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
 {
 	struct net_device *olddev, *newdev;
 	struct tid_info *ti;
diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/cxgb3/mc5.c
index 3b5517b..a8766fb 100644
--- a/drivers/net/cxgb3/mc5.c
+++ b/drivers/net/cxgb3/mc5.c
@@ -374,44 +374,6 @@
 	return err;
 }
 
-/*
- *	read_mc5_range - dump a part of the memory managed by MC5
- *	@mc5: the MC5 handle
- *	@start: the start address for the dump
- *	@n: number of 72-bit words to read
- *	@buf: result buffer
- *
- *	Read n 72-bit words from MC5 memory from the given start location.
- */
-int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start,
-		      unsigned int n, u32 *buf)
-{
-	u32 read_cmd;
-	int err = 0;
-	struct adapter *adap = mc5->adapter;
-
-	if (mc5->part_type == IDT75P52100)
-		read_cmd = IDT_CMD_READ;
-	else if (mc5->part_type == IDT75N43102)
-		read_cmd = IDT4_CMD_READ;
-	else
-		return -EINVAL;
-
-	mc5_dbgi_mode_enable(mc5);
-
-	while (n--) {
-		t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR0, start++);
-		if (mc5_cmd_write(adap, read_cmd)) {
-			err = -EIO;
-			break;
-		}
-		dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf);
-		buf += 3;
-	}
-
-	mc5_dbgi_mode_disable(mc5);
-	return 0;
-}
 
 #define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
 
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index cb42353..6990f6c 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -1997,6 +1997,10 @@
 
 #define A_PL_RST 0x6f0
 
+#define S_FATALPERREN    4
+#define V_FATALPERREN(x) ((x) << S_FATALPERREN)
+#define F_FATALPERREN    V_FATALPERREN(1U)
+
 #define S_CRSTWRM    1
 #define V_CRSTWRM(x) ((x) << S_CRSTWRM)
 #define F_CRSTWRM    V_CRSTWRM(1U)
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 8ff96c6..5d72bda 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -1145,7 +1145,7 @@
 	cpl->len = htonl(skb->len);
 	cntrl = V_TXPKT_INTF(pi->port_id);
 
-	if (vlan_tx_tag_present(skb) && pi->vlan_grp)
+	if (vlan_tx_tag_present(skb))
 		cntrl |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN(vlan_tx_tag_get(skb));
 
 	tso_info = V_LSO_MSS(skb_shinfo(skb)->gso_size);
@@ -1279,7 +1279,7 @@
 		qs->port_stats[SGE_PSTAT_TX_CSUM]++;
 	if (skb_shinfo(skb)->gso_size)
 		qs->port_stats[SGE_PSTAT_TSO]++;
-	if (vlan_tx_tag_present(skb) && pi->vlan_grp)
+	if (vlan_tx_tag_present(skb))
 		qs->port_stats[SGE_PSTAT_VLANINS]++;
 
 	/*
@@ -2022,7 +2022,7 @@
 		qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	} else
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 	skb_record_rx_queue(skb, qs - &adap->sge.qs[0]);
 
 	if (unlikely(p->vlan_valid)) {
@@ -2554,7 +2554,7 @@
  * The MSI-X interrupt handler for an SGE response queue for the non-NAPI case
  * (i.e., response queue serviced in hard interrupt).
  */
-irqreturn_t t3_sge_intr_msix(int irq, void *cookie)
+static irqreturn_t t3_sge_intr_msix(int irq, void *cookie)
 {
 	struct sge_qset *qs = cookie;
 	struct adapter *adap = qs->adap;
@@ -3320,40 +3320,3 @@
 
 	spin_lock_init(&adap->sge.reg_lock);
 }
-
-/**
- *	t3_get_desc - dump an SGE descriptor for debugging purposes
- *	@qs: the queue set
- *	@qnum: identifies the specific queue (0..2: Tx, 3:response, 4..5: Rx)
- *	@idx: the descriptor index in the queue
- *	@data: where to dump the descriptor contents
- *
- *	Dumps the contents of a HW descriptor of an SGE queue.  Returns the
- *	size of the descriptor.
- */
-int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx,
-		unsigned char *data)
-{
-	if (qnum >= 6)
-		return -EINVAL;
-
-	if (qnum < 3) {
-		if (!qs->txq[qnum].desc || idx >= qs->txq[qnum].size)
-			return -EINVAL;
-		memcpy(data, &qs->txq[qnum].desc[idx], sizeof(struct tx_desc));
-		return sizeof(struct tx_desc);
-	}
-
-	if (qnum == 3) {
-		if (!qs->rspq.desc || idx >= qs->rspq.size)
-			return -EINVAL;
-		memcpy(data, &qs->rspq.desc[idx], sizeof(struct rsp_desc));
-		return sizeof(struct rsp_desc);
-	}
-
-	qnum -= 4;
-	if (!qs->fl[qnum].desc || idx >= qs->fl[qnum].size)
-		return -EINVAL;
-	memcpy(data, &qs->fl[qnum].desc[idx], sizeof(struct rx_desc));
-	return sizeof(struct rx_desc);
-}
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index 427c451..3a6adf0 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -34,6 +34,8 @@
 #include "sge_defs.h"
 #include "firmware_exports.h"
 
+static void t3_port_intr_clear(struct adapter *adapter, int idx);
+
 /**
  *	t3_wait_op_done_val - wait until an operation is completed
  *	@adapter: the adapter performing the operation
@@ -840,8 +842,8 @@
  *	(i.e., big-endian), otherwise as 32-bit words in the platform's
  *	natural endianess.
  */
-int t3_read_flash(struct adapter *adapter, unsigned int addr,
-		  unsigned int nwords, u32 *data, int byte_oriented)
+static int t3_read_flash(struct adapter *adapter, unsigned int addr,
+			 unsigned int nwords, u32 *data, int byte_oriented)
 {
 	int ret;
 
@@ -1408,6 +1410,7 @@
 			fatal++;
 			CH_ALERT(adapter, "%s (0x%x)\n",
 				 acts->msg, status & acts->mask);
+			status &= ~acts->mask;
 		} else if (acts->msg)
 			CH_WARN(adapter, "%s (0x%x)\n",
 				acts->msg, status & acts->mask);
@@ -1843,11 +1846,10 @@
 		t3_os_link_fault_handler(adap, idx);
 	}
 
-	t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause);
-
 	if (cause & XGM_INTR_FATAL)
 		t3_fatal_err(adap);
 
+	t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause);
 	return cause != 0;
 }
 
@@ -2111,7 +2113,7 @@
  *	Clear port-specific (i.e., MAC and PHY) interrupts for the given
  *	adapter port.
  */
-void t3_port_intr_clear(struct adapter *adapter, int idx)
+static void t3_port_intr_clear(struct adapter *adapter, int idx)
 {
 	struct cphy *phy = &adap2pinfo(adapter, idx)->phy;
 
@@ -2484,98 +2486,6 @@
 }
 
 /**
- * 	t3_sge_read_context - read an SGE context
- * 	@type: the context type
- * 	@adapter: the adapter
- * 	@id: the context id
- * 	@data: holds the retrieved context
- *
- * 	Read an SGE egress context.  The caller is responsible for ensuring
- * 	only one context operation occurs at a time.
- */
-static int t3_sge_read_context(unsigned int type, struct adapter *adapter,
-			       unsigned int id, u32 data[4])
-{
-	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
-		return -EBUSY;
-
-	t3_write_reg(adapter, A_SG_CONTEXT_CMD,
-		     V_CONTEXT_CMD_OPCODE(0) | type | V_CONTEXT(id));
-	if (t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 0,
-			    SG_CONTEXT_CMD_ATTEMPTS, 1))
-		return -EIO;
-	data[0] = t3_read_reg(adapter, A_SG_CONTEXT_DATA0);
-	data[1] = t3_read_reg(adapter, A_SG_CONTEXT_DATA1);
-	data[2] = t3_read_reg(adapter, A_SG_CONTEXT_DATA2);
-	data[3] = t3_read_reg(adapter, A_SG_CONTEXT_DATA3);
-	return 0;
-}
-
-/**
- * 	t3_sge_read_ecntxt - read an SGE egress context
- * 	@adapter: the adapter
- * 	@id: the context id
- * 	@data: holds the retrieved context
- *
- * 	Read an SGE egress context.  The caller is responsible for ensuring
- * 	only one context operation occurs at a time.
- */
-int t3_sge_read_ecntxt(struct adapter *adapter, unsigned int id, u32 data[4])
-{
-	if (id >= 65536)
-		return -EINVAL;
-	return t3_sge_read_context(F_EGRESS, adapter, id, data);
-}
-
-/**
- * 	t3_sge_read_cq - read an SGE CQ context
- * 	@adapter: the adapter
- * 	@id: the context id
- * 	@data: holds the retrieved context
- *
- * 	Read an SGE CQ context.  The caller is responsible for ensuring
- * 	only one context operation occurs at a time.
- */
-int t3_sge_read_cq(struct adapter *adapter, unsigned int id, u32 data[4])
-{
-	if (id >= 65536)
-		return -EINVAL;
-	return t3_sge_read_context(F_CQ, adapter, id, data);
-}
-
-/**
- * 	t3_sge_read_fl - read an SGE free-list context
- * 	@adapter: the adapter
- * 	@id: the context id
- * 	@data: holds the retrieved context
- *
- * 	Read an SGE free-list context.  The caller is responsible for ensuring
- * 	only one context operation occurs at a time.
- */
-int t3_sge_read_fl(struct adapter *adapter, unsigned int id, u32 data[4])
-{
-	if (id >= SGE_QSETS * 2)
-		return -EINVAL;
-	return t3_sge_read_context(F_FREELIST, adapter, id, data);
-}
-
-/**
- * 	t3_sge_read_rspq - read an SGE response queue context
- * 	@adapter: the adapter
- * 	@id: the context id
- * 	@data: holds the retrieved context
- *
- * 	Read an SGE response queue context.  The caller is responsible for
- * 	ensuring only one context operation occurs at a time.
- */
-int t3_sge_read_rspq(struct adapter *adapter, unsigned int id, u32 data[4])
-{
-	if (id >= SGE_QSETS)
-		return -EINVAL;
-	return t3_sge_read_context(F_RESPONSEQ, adapter, id, data);
-}
-
-/**
  *	t3_config_rss - configure Rx packet steering
  *	@adapter: the adapter
  *	@rss_config: RSS settings (written to TP_RSS_CONFIG)
@@ -2616,42 +2526,6 @@
 }
 
 /**
- *	t3_read_rss - read the contents of the RSS tables
- *	@adapter: the adapter
- *	@lkup: holds the contents of the RSS lookup table
- *	@map: holds the contents of the RSS map table
- *
- *	Reads the contents of the receive packet steering tables.
- */
-int t3_read_rss(struct adapter *adapter, u8 * lkup, u16 *map)
-{
-	int i;
-	u32 val;
-
-	if (lkup)
-		for (i = 0; i < RSS_TABLE_SIZE; ++i) {
-			t3_write_reg(adapter, A_TP_RSS_LKP_TABLE,
-				     0xffff0000 | i);
-			val = t3_read_reg(adapter, A_TP_RSS_LKP_TABLE);
-			if (!(val & 0x80000000))
-				return -EAGAIN;
-			*lkup++ = val;
-			*lkup++ = (val >> 8);
-		}
-
-	if (map)
-		for (i = 0; i < RSS_TABLE_SIZE; ++i) {
-			t3_write_reg(adapter, A_TP_RSS_MAP_TABLE,
-				     0xffff0000 | i);
-			val = t3_read_reg(adapter, A_TP_RSS_MAP_TABLE);
-			if (!(val & 0x80000000))
-				return -EAGAIN;
-			*map++ = val;
-		}
-	return 0;
-}
-
-/**
  *	t3_tp_set_offload_mode - put TP in NIC/offload mode
  *	@adap: the adapter
  *	@enable: 1 to select offload mode, 0 for regular NIC
@@ -2868,7 +2742,8 @@
  *
  *	Set the receive coalescing size and PSH bit handling.
  */
-int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh)
+static int t3_tp_set_coalescing_size(struct adapter *adap,
+				     unsigned int size, int psh)
 {
 	u32 val;
 
@@ -2898,7 +2773,7 @@
  *	Set TP's max receive size.  This is the limit that applies when
  *	receive coalescing is disabled.
  */
-void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size)
+static void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size)
 {
 	t3_write_reg(adap, A_TP_PARA_REG7,
 		     V_PMMAXXFERLEN0(size) | V_PMMAXXFERLEN1(size));
@@ -3018,48 +2893,6 @@
 }
 
 /**
- *	t3_read_hw_mtus - returns the values in the HW MTU table
- *	@adap: the adapter
- *	@mtus: where to store the HW MTU values
- *
- *	Reads the HW MTU table.
- */
-void t3_read_hw_mtus(struct adapter *adap, unsigned short mtus[NMTUS])
-{
-	int i;
-
-	for (i = 0; i < NMTUS; ++i) {
-		unsigned int val;
-
-		t3_write_reg(adap, A_TP_MTU_TABLE, 0xff000000 | i);
-		val = t3_read_reg(adap, A_TP_MTU_TABLE);
-		mtus[i] = val & 0x3fff;
-	}
-}
-
-/**
- *	t3_get_cong_cntl_tab - reads the congestion control table
- *	@adap: the adapter
- *	@incr: where to store the alpha values
- *
- *	Reads the additive increments programmed into the HW congestion
- *	control table.
- */
-void t3_get_cong_cntl_tab(struct adapter *adap,
-			  unsigned short incr[NMTUS][NCCTRL_WIN])
-{
-	unsigned int mtu, w;
-
-	for (mtu = 0; mtu < NMTUS; ++mtu)
-		for (w = 0; w < NCCTRL_WIN; ++w) {
-			t3_write_reg(adap, A_TP_CCTRL_TABLE,
-				     0xffff0000 | (mtu << 5) | w);
-			incr[mtu][w] = t3_read_reg(adap, A_TP_CCTRL_TABLE) &
-				       0x1fff;
-		}
-}
-
-/**
  *	t3_tp_get_mib_stats - read TP's MIB counters
  *	@adap: the adapter
  *	@tps: holds the returned counter values
@@ -3223,15 +3056,6 @@
 	return busy;
 }
 
-int t3_mps_set_active_ports(struct adapter *adap, unsigned int port_mask)
-{
-	if (port_mask & ~((1 << adap->params.nports) - 1))
-		return -EINVAL;
-	t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE | F_PORT0ACTIVE,
-			 port_mask << S_PORT0ACTIVE);
-	return 0;
-}
-
 /*
  * Perform the bits of HW initialization that are dependent on the Tx
  * channels being used.
@@ -3569,6 +3393,7 @@
 	t3_write_reg(adapter, A_PM1_TX_MODE, 0);
 	chan_init_hw(adapter, adapter->params.chan_map);
 	t3_sge_init(adapter, &adapter->params.sge);
+	t3_set_reg_field(adapter, A_PL_RST, 0, F_FATALPERREN);
 
 	t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, calc_gpio_intr(adapter));
 
@@ -3682,11 +3507,11 @@
 	mc7->name = name;
 	mc7->offset = base_addr - MC7_PMRX_BASE_ADDR;
 	cfg = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);
-	mc7->size = mc7->size = G_DEN(cfg) == M_DEN ? 0 : mc7_calc_size(cfg);
+	mc7->size = G_DEN(cfg) == M_DEN ? 0 : mc7_calc_size(cfg);
 	mc7->width = G_WIDTH(cfg);
 }
 
-void mac_prep(struct cmac *mac, struct adapter *adapter, int index)
+static void mac_prep(struct cmac *mac, struct adapter *adapter, int index)
 {
 	u16 devid;
 
@@ -3706,7 +3531,8 @@
 	}
 }
 
-void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
+static void early_hw_init(struct adapter *adapter,
+			  const struct adapter_info *ai)
 {
 	u32 val = V_PORTSPEED(is_10G(adapter) ? 3 : 2);
 
diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h
index 6e562c0..eaa49e4 100644
--- a/drivers/net/cxgb4/cxgb4.h
+++ b/drivers/net/cxgb4/cxgb4.h
@@ -463,6 +463,8 @@
 	u8 counter_val[SGE_NCOUNTERS];
 	unsigned int starve_thres;
 	u8 idma_state[2];
+	unsigned int egr_start;
+	unsigned int ingr_start;
 	void *egr_map[MAX_EGRQ];    /* qid->queue egress queue map */
 	struct sge_rspq *ingr_map[MAX_INGQ]; /* qid->queue ingress queue map */
 	DECLARE_BITMAP(starving_fl, MAX_EGRQ);
@@ -590,7 +592,6 @@
 void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat);
 
 void *t4_alloc_mem(size_t size);
-void t4_free_mem(void *addr);
 
 void t4_free_sge_resources(struct adapter *adap);
 irq_handler_t t4_intr_handler(struct adapter *adap);
@@ -649,7 +650,6 @@
 
 void t4_intr_enable(struct adapter *adapter);
 void t4_intr_disable(struct adapter *adapter);
-void t4_intr_clear(struct adapter *adapter);
 int t4_slow_intr_handler(struct adapter *adapter);
 
 int t4_wait_dev_ready(struct adapter *adap);
@@ -662,24 +662,16 @@
 int t4_prep_adapter(struct adapter *adapter);
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
 void t4_fatal_err(struct adapter *adapter);
-int t4_set_trace_filter(struct adapter *adapter, const struct trace_params *tp,
-			int filter_index, int enable);
-void t4_get_trace_filter(struct adapter *adapter, struct trace_params *tp,
-			 int filter_index, int *enabled);
 int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
 			int start, int n, const u16 *rspq, unsigned int nrspq);
 int t4_config_glbl_rss(struct adapter *adapter, int mbox, unsigned int mode,
 		       unsigned int flags);
-int t4_read_rss(struct adapter *adapter, u16 *entries);
 int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *parity);
 int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,
 		u64 *parity);
 
 void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p);
-void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p);
-
 void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log);
-void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st);
 void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
 			 struct tp_tcp_stats *v6);
 void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
@@ -709,8 +701,6 @@
 int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
 		unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac,
 		unsigned int *rss_size);
-int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
-	       unsigned int vf, unsigned int viid);
 int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
 		int mtu, int promisc, int all_multi, int bcast, int vlanex,
 		bool sleep_ok);
@@ -729,9 +719,6 @@
 	       unsigned int mmd, unsigned int reg, u16 *valp);
 int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
 	       unsigned int mmd, unsigned int reg, u16 val);
-int t4_iq_start_stop(struct adapter *adap, unsigned int mbox, bool start,
-		     unsigned int pf, unsigned int vf, unsigned int iqid,
-		     unsigned int fl0id, unsigned int fl1id);
 int t4_iq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
 	       unsigned int vf, unsigned int iqtype, unsigned int iqid,
 	       unsigned int fl0id, unsigned int fl1id);
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index c327527..87054e0 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -175,16 +175,26 @@
 
 static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
 	CH_DEVICE(0xa000, 0),  /* PE10K */
-	CH_DEVICE(0x4001, 0),
-	CH_DEVICE(0x4002, 0),
-	CH_DEVICE(0x4003, 0),
-	CH_DEVICE(0x4004, 0),
-	CH_DEVICE(0x4005, 0),
-	CH_DEVICE(0x4006, 0),
-	CH_DEVICE(0x4007, 0),
-	CH_DEVICE(0x4008, 0),
-	CH_DEVICE(0x4009, 0),
-	CH_DEVICE(0x400a, 0),
+	CH_DEVICE(0x4001, -1),
+	CH_DEVICE(0x4002, -1),
+	CH_DEVICE(0x4003, -1),
+	CH_DEVICE(0x4004, -1),
+	CH_DEVICE(0x4005, -1),
+	CH_DEVICE(0x4006, -1),
+	CH_DEVICE(0x4007, -1),
+	CH_DEVICE(0x4008, -1),
+	CH_DEVICE(0x4009, -1),
+	CH_DEVICE(0x400a, -1),
+	CH_DEVICE(0x4401, 4),
+	CH_DEVICE(0x4402, 4),
+	CH_DEVICE(0x4403, 4),
+	CH_DEVICE(0x4404, 4),
+	CH_DEVICE(0x4405, 4),
+	CH_DEVICE(0x4406, 4),
+	CH_DEVICE(0x4407, 4),
+	CH_DEVICE(0x4408, 4),
+	CH_DEVICE(0x4409, 4),
+	CH_DEVICE(0x440a, 4),
 	{ 0, }
 };
 
@@ -423,10 +433,11 @@
 	if (likely(opcode == CPL_SGE_EGR_UPDATE)) {
 		const struct cpl_sge_egr_update *p = (void *)rsp;
 		unsigned int qid = EGR_QID(ntohl(p->opcode_qid));
-		struct sge_txq *txq = q->adap->sge.egr_map[qid];
+		struct sge_txq *txq;
 
+		txq = q->adap->sge.egr_map[qid - q->adap->sge.egr_start];
 		txq->restarts++;
-		if ((u8 *)txq < (u8 *)q->adap->sge.ethrxq) {
+		if ((u8 *)txq < (u8 *)q->adap->sge.ofldtxq) {
 			struct sge_eth_txq *eq;
 
 			eq = container_of(txq, struct sge_eth_txq, q);
@@ -658,6 +669,15 @@
 }
 
 /*
+ * Return the channel of the ingress queue with the given qid.
+ */
+static unsigned int rxq_to_chan(const struct sge *p, unsigned int qid)
+{
+	qid -= p->ingr_start;
+	return netdev2pinfo(p->ingr_map[qid]->netdev)->tx_chan;
+}
+
+/*
  * Wait until all NAPI handlers are descheduled.
  */
 static void quiesce_rx(struct adapter *adap)
@@ -860,7 +880,7 @@
 /*
  * Free memory allocated through alloc_mem().
  */
-void t4_free_mem(void *addr)
+static void t4_free_mem(void *addr)
 {
 	if (is_vmalloc_addr(addr))
 		vfree(addr);
@@ -1671,27 +1691,41 @@
 	return 0;
 }
 
-/*
- * Translate a physical EEPROM address to virtual.  The first 1K is accessed
- * through virtual addresses starting at 31K, the rest is accessed through
- * virtual addresses starting at 0.  This mapping is correct only for PF0.
+/**
+ *	eeprom_ptov - translate a physical EEPROM address to virtual
+ *	@phys_addr: the physical EEPROM address
+ *	@fn: the PCI function number
+ *	@sz: size of function-specific area
+ *
+ *	Translate a physical EEPROM address to virtual.  The first 1K is
+ *	accessed through virtual addresses starting at 31K, the rest is
+ *	accessed through virtual addresses starting at 0.
+ *
+ *	The mapping is as follows:
+ *	[0..1K) -> [31K..32K)
+ *	[1K..1K+A) -> [31K-A..31K)
+ *	[1K+A..ES) -> [0..ES-A-1K)
+ *
+ *	where A = @fn * @sz, and ES = EEPROM size.
  */
-static int eeprom_ptov(unsigned int phys_addr)
+static int eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz)
 {
+	fn *= sz;
 	if (phys_addr < 1024)
 		return phys_addr + (31 << 10);
+	if (phys_addr < 1024 + fn)
+		return 31744 - fn + phys_addr - 1024;
 	if (phys_addr < EEPROMSIZE)
-		return phys_addr - 1024;
+		return phys_addr - 1024 - fn;
 	return -EINVAL;
 }
 
 /*
  * The next two routines implement eeprom read/write from physical addresses.
- * The physical->virtual translation is correct only for PF0.
  */
 static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v)
 {
-	int vaddr = eeprom_ptov(phys_addr);
+	int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE);
 
 	if (vaddr >= 0)
 		vaddr = pci_read_vpd(adap->pdev, vaddr, sizeof(u32), v);
@@ -1700,7 +1734,7 @@
 
 static int eeprom_wr_phys(struct adapter *adap, unsigned int phys_addr, u32 v)
 {
-	int vaddr = eeprom_ptov(phys_addr);
+	int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE);
 
 	if (vaddr >= 0)
 		vaddr = pci_write_vpd(adap->pdev, vaddr, sizeof(u32), &v);
@@ -1743,6 +1777,14 @@
 	aligned_offset = eeprom->offset & ~3;
 	aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3;
 
+	if (adapter->fn > 0) {
+		u32 start = 1024 + adapter->fn * EEPROMPFSIZE;
+
+		if (aligned_offset < start ||
+		    aligned_offset + aligned_len > start + EEPROMPFSIZE)
+			return -EPERM;
+	}
+
 	if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) {
 		/*
 		 * RMW possibly needed for first or last words.
@@ -2026,6 +2068,7 @@
 	.owner   = THIS_MODULE,
 	.open    = mem_open,
 	.read    = mem_read,
+	.llseek  = default_llseek,
 };
 
 static void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
@@ -2164,8 +2207,8 @@
  * Queue a TID release request and if necessary schedule a work queue to
  * process it.
  */
-void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
-			     unsigned int tid)
+static void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
+				    unsigned int tid)
 {
 	void **p = &t->tid_tab[tid];
 	struct adapter *adap = container_of(t, struct adapter, tids);
@@ -2180,7 +2223,6 @@
 	}
 	spin_unlock_bh(&adap->tid_release_lock);
 }
-EXPORT_SYMBOL(cxgb4_queue_tid_release);
 
 /*
  * Process the list of pending TID release requests.
@@ -2304,7 +2346,7 @@
 	req->peer_port = htons(0);
 	req->local_ip = sip;
 	req->peer_ip = htonl(0);
-	chan = netdev2pinfo(adap->sge.ingr_map[queue]->netdev)->tx_chan;
+	chan = rxq_to_chan(&adap->sge, queue);
 	req->opt0 = cpu_to_be64(TX_CHAN(chan));
 	req->opt1 = cpu_to_be64(CONN_POLICY_ASK |
 				SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue));
@@ -2313,48 +2355,6 @@
 EXPORT_SYMBOL(cxgb4_create_server);
 
 /**
- *	cxgb4_create_server6 - create an IPv6 server
- *	@dev: the device
- *	@stid: the server TID
- *	@sip: local IPv6 address to bind server to
- *	@sport: the server's TCP port
- *	@queue: queue to direct messages from this server to
- *
- *	Create an IPv6 server for the given port and address.
- *	Returns <0 on error and one of the %NET_XMIT_* values on success.
- */
-int cxgb4_create_server6(const struct net_device *dev, unsigned int stid,
-			 const struct in6_addr *sip, __be16 sport,
-			 unsigned int queue)
-{
-	unsigned int chan;
-	struct sk_buff *skb;
-	struct adapter *adap;
-	struct cpl_pass_open_req6 *req;
-
-	skb = alloc_skb(sizeof(*req), GFP_KERNEL);
-	if (!skb)
-		return -ENOMEM;
-
-	adap = netdev2adap(dev);
-	req = (struct cpl_pass_open_req6 *)__skb_put(skb, sizeof(*req));
-	INIT_TP_WR(req, 0);
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ6, stid));
-	req->local_port = sport;
-	req->peer_port = htons(0);
-	req->local_ip_hi = *(__be64 *)(sip->s6_addr);
-	req->local_ip_lo = *(__be64 *)(sip->s6_addr + 8);
-	req->peer_ip_hi = cpu_to_be64(0);
-	req->peer_ip_lo = cpu_to_be64(0);
-	chan = netdev2pinfo(adap->sge.ingr_map[queue]->netdev)->tx_chan;
-	req->opt0 = cpu_to_be64(TX_CHAN(chan));
-	req->opt1 = cpu_to_be64(CONN_POLICY_ASK |
-				SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue));
-	return t4_mgmt_tx(adap, skb);
-}
-EXPORT_SYMBOL(cxgb4_create_server6);
-
-/**
  *	cxgb4_best_mtu - find the entry in the MTU table closest to an MTU
  *	@mtus: the HW MTU table
  *	@mtu: the target MTU
@@ -2413,25 +2413,6 @@
 }
 EXPORT_SYMBOL(cxgb4_port_idx);
 
-/**
- *	cxgb4_netdev_by_hwid - return the net device of a HW port
- *	@pdev: identifies the adapter
- *	@id: the HW port id
- *
- *	Return the net device associated with the interface with the given HW
- *	id.
- */
-struct net_device *cxgb4_netdev_by_hwid(struct pci_dev *pdev, unsigned int id)
-{
-	const struct adapter *adap = pci_get_drvdata(pdev);
-
-	if (!adap || id >= NCHAN)
-		return NULL;
-	id = adap->chan_map[id];
-	return id < MAX_NPORTS ? adap->port[id] : NULL;
-}
-EXPORT_SYMBOL(cxgb4_netdev_by_hwid);
-
 void cxgb4_get_tcp_stats(struct pci_dev *pdev, struct tp_tcp_stats *v4,
 			 struct tp_tcp_stats *v6)
 {
@@ -2721,7 +2702,10 @@
 			return err;
 	}
 
-	dev->real_num_tx_queues = pi->nqsets;
+	netif_set_real_num_tx_queues(dev, pi->nqsets);
+	err = netif_set_real_num_rx_queues(dev, pi->nqsets);
+	if (err)
+		return err;
 	err = link_start(dev);
 	if (!err)
 		netif_tx_start_all_queues(dev);
@@ -3061,12 +3045,16 @@
 	params[2] = FW_PARAM_PFVF(L2T_END);
 	params[3] = FW_PARAM_PFVF(FILTER_START);
 	params[4] = FW_PARAM_PFVF(FILTER_END);
-	ret = t4_query_params(adap, adap->fn, adap->fn, 0, 5, params, val);
+	params[5] = FW_PARAM_PFVF(IQFLINT_START);
+	params[6] = FW_PARAM_PFVF(EQ_START);
+	ret = t4_query_params(adap, adap->fn, adap->fn, 0, 7, params, val);
 	if (ret < 0)
 		goto bye;
 	port_vec = val[0];
 	adap->tids.ftid_base = val[3];
 	adap->tids.nftids = val[4] - val[3] + 1;
+	adap->sge.ingr_start = val[5];
+	adap->sge.egr_start = val[6];
 
 	if (c.ofldcaps) {
 		/* query offload-related parameters */
@@ -3814,7 +3802,7 @@
 		pci_disable_device(pdev);
 		pci_release_regions(pdev);
 		pci_set_drvdata(pdev, NULL);
-	} else if (PCI_FUNC(pdev->devfn) > 0)
+	} else
 		pci_release_regions(pdev);
 }
 
diff --git a/drivers/net/cxgb4/cxgb4_uld.h b/drivers/net/cxgb4/cxgb4_uld.h
index 85d74e7..1b48c01 100644
--- a/drivers/net/cxgb4/cxgb4_uld.h
+++ b/drivers/net/cxgb4/cxgb4_uld.h
@@ -139,16 +139,11 @@
 void cxgb4_free_atid(struct tid_info *t, unsigned int atid);
 void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family);
 void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid);
-void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
-			     unsigned int tid);
 
 struct in6_addr;
 
 int cxgb4_create_server(const struct net_device *dev, unsigned int stid,
 			__be32 sip, __be16 sport, unsigned int queue);
-int cxgb4_create_server6(const struct net_device *dev, unsigned int stid,
-			 const struct in6_addr *sip, __be16 sport,
-			 unsigned int queue);
 
 static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
 {
@@ -233,7 +228,6 @@
 unsigned int cxgb4_port_chan(const struct net_device *dev);
 unsigned int cxgb4_port_viid(const struct net_device *dev);
 unsigned int cxgb4_port_idx(const struct net_device *dev);
-struct net_device *cxgb4_netdev_by_hwid(struct pci_dev *pdev, unsigned int id);
 unsigned int cxgb4_best_mtu(const unsigned short *mtus, unsigned short mtu,
 			    unsigned int *idx);
 void cxgb4_get_tcp_stats(struct pci_dev *pdev, struct tp_tcp_stats *v4,
diff --git a/drivers/net/cxgb4/l2t.c b/drivers/net/cxgb4/l2t.c
index e8f0f55..a2d323c 100644
--- a/drivers/net/cxgb4/l2t.c
+++ b/drivers/net/cxgb4/l2t.c
@@ -481,40 +481,6 @@
 		handle_failed_resolution(adap, arpq);
 }
 
-/*
- * Allocate an L2T entry for use by a switching rule.  Such entries need to be
- * explicitly freed and while busy they are not on any hash chain, so normal
- * address resolution updates do not see them.
- */
-struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d)
-{
-	struct l2t_entry *e;
-
-	write_lock_bh(&d->lock);
-	e = alloc_l2e(d);
-	if (e) {
-		spin_lock(&e->lock);          /* avoid race with t4_l2t_free */
-		e->state = L2T_STATE_SWITCHING;
-		atomic_set(&e->refcnt, 1);
-		spin_unlock(&e->lock);
-	}
-	write_unlock_bh(&d->lock);
-	return e;
-}
-
-/*
- * Sets/updates the contents of a switching L2T entry that has been allocated
- * with an earlier call to @t4_l2t_alloc_switching.
- */
-int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
-			 u8 port, u8 *eth_addr)
-{
-	e->vlan = vlan;
-	e->lport = port;
-	memcpy(e->dmac, eth_addr, ETH_ALEN);
-	return write_l2e(adap, e, 0);
-}
-
 struct l2t_data *t4_init_l2t(void)
 {
 	int i;
diff --git a/drivers/net/cxgb4/l2t.h b/drivers/net/cxgb4/l2t.h
index 643f27e..7bd8f42 100644
--- a/drivers/net/cxgb4/l2t.h
+++ b/drivers/net/cxgb4/l2t.h
@@ -100,9 +100,6 @@
 				unsigned int priority);
 
 void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
-struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d);
-int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
-			 u8 port, u8 *eth_addr);
 struct l2t_data *t4_init_l2t(void);
 void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl);
 
diff --git a/drivers/net/cxgb4/sge.c b/drivers/net/cxgb4/sge.c
index bf38cfc..9967f3d 100644
--- a/drivers/net/cxgb4/sge.c
+++ b/drivers/net/cxgb4/sge.c
@@ -557,7 +557,8 @@
 
 	if (unlikely(fl_starving(q))) {
 		smp_wmb();
-		set_bit(q->cntxt_id, adap->sge.starving_fl);
+		set_bit(q->cntxt_id - adap->sge.egr_start,
+			adap->sge.starving_fl);
 	}
 
 	return cred;
@@ -974,7 +975,7 @@
 	}
 
 	cpl->ctrl0 = htonl(TXPKT_OPCODE(CPL_TX_PKT_XT) |
-			   TXPKT_INTF(pi->tx_chan) | TXPKT_PF(0));
+			   TXPKT_INTF(pi->tx_chan) | TXPKT_PF(adap->fn));
 	cpl->pack = htons(0);
 	cpl->len = htons(skb->len);
 	cpl->ctrl1 = cpu_to_be64(cntrl);
@@ -1213,7 +1214,8 @@
 {
 	q->mapping_err++;
 	q->q.stops++;
-	set_bit(q->q.cntxt_id, q->adap->sge.txq_maperr);
+	set_bit(q->q.cntxt_id - q->adap->sge.egr_start,
+		q->adap->sge.txq_maperr);
 }
 
 /**
@@ -1603,7 +1605,7 @@
 			rxq->stats.rx_cso++;
 		}
 	} else
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 
 	if (unlikely(pkt->vlan_ex)) {
 		struct vlan_group *grp = pi->vlan_grp;
@@ -1835,6 +1837,7 @@
 		if (RSPD_TYPE(rc->type_gen) == RSP_TYPE_INTR) {
 			unsigned int qid = ntohl(rc->pldbuflen_qid);
 
+			qid -= adap->sge.ingr_start;
 			napi_schedule(&adap->sge.ingr_map[qid]->napi);
 		}
 
@@ -2050,14 +2053,14 @@
 	/* set offset to -1 to distinguish ingress queues without FL */
 	iq->offset = fl ? 0 : -1;
 
-	adap->sge.ingr_map[iq->cntxt_id] = iq;
+	adap->sge.ingr_map[iq->cntxt_id - adap->sge.ingr_start] = iq;
 
 	if (fl) {
 		fl->cntxt_id = ntohs(c.fl0id);
 		fl->avail = fl->pend_cred = 0;
 		fl->pidx = fl->cidx = 0;
 		fl->alloc_failed = fl->large_alloc_failed = fl->starving = 0;
-		adap->sge.egr_map[fl->cntxt_id] = fl;
+		adap->sge.egr_map[fl->cntxt_id - adap->sge.egr_start] = fl;
 		refill_fl(adap, fl, fl_cap(fl), GFP_KERNEL);
 	}
 	return 0;
@@ -2087,7 +2090,7 @@
 	q->stops = q->restarts = 0;
 	q->stat = (void *)&q->desc[q->size];
 	q->cntxt_id = id;
-	adap->sge.egr_map[id] = q;
+	adap->sge.egr_map[id - adap->sge.egr_start] = q;
 }
 
 int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
@@ -2259,7 +2262,7 @@
 {
 	unsigned int fl_id = fl ? fl->cntxt_id : 0xffff;
 
-	adap->sge.ingr_map[rq->cntxt_id] = NULL;
+	adap->sge.ingr_map[rq->cntxt_id - adap->sge.ingr_start] = NULL;
 	t4_iq_free(adap, adap->fn, adap->fn, 0, FW_IQ_TYPE_FL_INT_CAP,
 		   rq->cntxt_id, fl_id, 0xffff);
 	dma_free_coherent(adap->pdev_dev, (rq->size + 1) * rq->iqe_len,
diff --git a/drivers/net/cxgb4/t4_hw.c b/drivers/net/cxgb4/t4_hw.c
index 9e1a4b4..bb813d9 100644
--- a/drivers/net/cxgb4/t4_hw.c
+++ b/drivers/net/cxgb4/t4_hw.c
@@ -120,30 +120,6 @@
 	}
 }
 
-#if 0
-/**
- *	t4_write_indirect - write indirectly addressed registers
- *	@adap: the adapter
- *	@addr_reg: register holding the indirect addresses
- *	@data_reg: register holding the value for the indirect registers
- *	@vals: values to write
- *	@nregs: how many indirect registers to write
- *	@start_idx: address of first indirect register to write
- *
- *	Writes a sequential block of registers that are accessed indirectly
- *	through an address/data register pair.
- */
-static void t4_write_indirect(struct adapter *adap, unsigned int addr_reg,
-			      unsigned int data_reg, const u32 *vals,
-			      unsigned int nregs, unsigned int start_idx)
-{
-	while (nregs--) {
-		t4_write_reg(adap, addr_reg, start_idx++);
-		t4_write_reg(adap, data_reg, *vals++);
-	}
-}
-#endif
-
 /*
  * Get the reply to a mailbox command and store it in @rpl in big-endian order.
  */
@@ -1560,44 +1536,6 @@
 }
 
 /**
- *	t4_intr_clear - clear all interrupts
- *	@adapter: the adapter whose interrupts should be cleared
- *
- *	Clears all interrupts.  The caller must be a PCI function managing
- *	global interrupts.
- */
-void t4_intr_clear(struct adapter *adapter)
-{
-	static const unsigned int cause_reg[] = {
-		SGE_INT_CAUSE1, SGE_INT_CAUSE2, SGE_INT_CAUSE3,
-		PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
-		PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
-		PCIE_NONFAT_ERR, PCIE_INT_CAUSE,
-		MC_INT_CAUSE,
-		MA_INT_WRAP_STATUS, MA_PARITY_ERROR_STATUS, MA_INT_CAUSE,
-		EDC_INT_CAUSE, EDC_REG(EDC_INT_CAUSE, 1),
-		CIM_HOST_INT_CAUSE, CIM_HOST_UPACC_INT_CAUSE,
-		MYPF_REG(CIM_PF_HOST_INT_CAUSE),
-		TP_INT_CAUSE,
-		ULP_RX_INT_CAUSE, ULP_TX_INT_CAUSE,
-		PM_RX_INT_CAUSE, PM_TX_INT_CAUSE,
-		MPS_RX_PERR_INT_CAUSE,
-		CPL_INTR_CAUSE,
-		MYPF_REG(PL_PF_INT_CAUSE),
-		PL_PL_INT_CAUSE,
-		LE_DB_INT_CAUSE,
-	};
-
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(cause_reg); ++i)
-		t4_write_reg(adapter, cause_reg[i], 0xffffffff);
-
-	t4_write_reg(adapter, PL_INT_CAUSE, GLBL_INTR_MASK);
-	(void) t4_read_reg(adapter, PL_INT_CAUSE);          /* flush */
-}
-
-/**
  *	hash_mac_addr - return the hash value of a MAC address
  *	@addr: the 48-bit Ethernet MAC address
  *
@@ -1709,36 +1647,6 @@
 	return t4_wr_mbox(adapter, mbox, &c, sizeof(c), NULL);
 }
 
-/* Read an RSS table row */
-static int rd_rss_row(struct adapter *adap, int row, u32 *val)
-{
-	t4_write_reg(adap, TP_RSS_LKP_TABLE, 0xfff00000 | row);
-	return t4_wait_op_done_val(adap, TP_RSS_LKP_TABLE, LKPTBLROWVLD, 1,
-				   5, 0, val);
-}
-
-/**
- *	t4_read_rss - read the contents of the RSS mapping table
- *	@adapter: the adapter
- *	@map: holds the contents of the RSS mapping table
- *
- *	Reads the contents of the RSS hash->queue mapping table.
- */
-int t4_read_rss(struct adapter *adapter, u16 *map)
-{
-	u32 val;
-	int i, ret;
-
-	for (i = 0; i < RSS_NENTRIES / 2; ++i) {
-		ret = rd_rss_row(adapter, i, &val);
-		if (ret)
-			return ret;
-		*map++ = LKPTBLQUEUE0_GET(val);
-		*map++ = LKPTBLQUEUE1_GET(val);
-	}
-	return 0;
-}
-
 /**
  *	t4_tp_get_tcp_stats - read TP's TCP MIB counters
  *	@adap: the adapter
@@ -1779,29 +1687,6 @@
 }
 
 /**
- *	t4_tp_get_err_stats - read TP's error MIB counters
- *	@adap: the adapter
- *	@st: holds the counter values
- *
- *	Returns the values of TP's error counters.
- */
-void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st)
-{
-	t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, st->macInErrs,
-			 12, TP_MIB_MAC_IN_ERR_0);
-	t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, st->tnlCongDrops,
-			 8, TP_MIB_TNL_CNG_DROP_0);
-	t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, st->tnlTxDrops,
-			 4, TP_MIB_TNL_DROP_0);
-	t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, st->ofldVlanDrops,
-			 4, TP_MIB_OFD_VLN_DROP_0);
-	t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, st->tcp6InErrs,
-			 4, TP_MIB_TCP_V6IN_ERR_0);
-	t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, &st->ofldNoNeigh,
-			 2, TP_MIB_OFD_ARP_DROP);
-}
-
-/**
  *	t4_read_mtu_tbl - returns the values in the HW path MTU table
  *	@adap: the adapter
  *	@mtus: where to store the MTU values
@@ -1916,122 +1801,6 @@
 }
 
 /**
- *	t4_set_trace_filter - configure one of the tracing filters
- *	@adap: the adapter
- *	@tp: the desired trace filter parameters
- *	@idx: which filter to configure
- *	@enable: whether to enable or disable the filter
- *
- *	Configures one of the tracing filters available in HW.  If @enable is
- *	%0 @tp is not examined and may be %NULL.
- */
-int t4_set_trace_filter(struct adapter *adap, const struct trace_params *tp,
-			int idx, int enable)
-{
-	int i, ofst = idx * 4;
-	u32 data_reg, mask_reg, cfg;
-	u32 multitrc = TRCMULTIFILTER;
-
-	if (!enable) {
-		t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + ofst, 0);
-		goto out;
-	}
-
-	if (tp->port > 11 || tp->invert > 1 || tp->skip_len > 0x1f ||
-	    tp->skip_ofst > 0x1f || tp->min_len > 0x1ff ||
-	    tp->snap_len > 9600 || (idx && tp->snap_len > 256))
-		return -EINVAL;
-
-	if (tp->snap_len > 256) {            /* must be tracer 0 */
-		if ((t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + 4) |
-		     t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + 8) |
-		     t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + 12)) & TFEN)
-			return -EINVAL;  /* other tracers are enabled */
-		multitrc = 0;
-	} else if (idx) {
-		i = t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_B);
-		if (TFCAPTUREMAX_GET(i) > 256 &&
-		    (t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A) & TFEN))
-			return -EINVAL;
-	}
-
-	/* stop the tracer we'll be changing */
-	t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + ofst, 0);
-
-	/* disable tracing globally if running in the wrong single/multi mode */
-	cfg = t4_read_reg(adap, MPS_TRC_CFG);
-	if ((cfg & TRCEN) && multitrc != (cfg & TRCMULTIFILTER)) {
-		t4_write_reg(adap, MPS_TRC_CFG, cfg ^ TRCEN);
-		t4_read_reg(adap, MPS_TRC_CFG);                  /* flush */
-		msleep(1);
-		if (!(t4_read_reg(adap, MPS_TRC_CFG) & TRCFIFOEMPTY))
-			return -ETIMEDOUT;
-	}
-	/*
-	 * At this point either the tracing is enabled and in the right mode or
-	 * disabled.
-	 */
-
-	idx *= (MPS_TRC_FILTER1_MATCH - MPS_TRC_FILTER0_MATCH);
-	data_reg = MPS_TRC_FILTER0_MATCH + idx;
-	mask_reg = MPS_TRC_FILTER0_DONT_CARE + idx;
-
-	for (i = 0; i < TRACE_LEN / 4; i++, data_reg += 4, mask_reg += 4) {
-		t4_write_reg(adap, data_reg, tp->data[i]);
-		t4_write_reg(adap, mask_reg, ~tp->mask[i]);
-	}
-	t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_B + ofst,
-		     TFCAPTUREMAX(tp->snap_len) |
-		     TFMINPKTSIZE(tp->min_len));
-	t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + ofst,
-		     TFOFFSET(tp->skip_ofst) | TFLENGTH(tp->skip_len) |
-		     TFPORT(tp->port) | TFEN |
-		     (tp->invert ? TFINVERTMATCH : 0));
-
-	cfg &= ~TRCMULTIFILTER;
-	t4_write_reg(adap, MPS_TRC_CFG, cfg | TRCEN | multitrc);
-out:	t4_read_reg(adap, MPS_TRC_CFG);  /* flush */
-	return 0;
-}
-
-/**
- *	t4_get_trace_filter - query one of the tracing filters
- *	@adap: the adapter
- *	@tp: the current trace filter parameters
- *	@idx: which trace filter to query
- *	@enabled: non-zero if the filter is enabled
- *
- *	Returns the current settings of one of the HW tracing filters.
- */
-void t4_get_trace_filter(struct adapter *adap, struct trace_params *tp, int idx,
-			 int *enabled)
-{
-	u32 ctla, ctlb;
-	int i, ofst = idx * 4;
-	u32 data_reg, mask_reg;
-
-	ctla = t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + ofst);
-	ctlb = t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_B + ofst);
-
-	*enabled = !!(ctla & TFEN);
-	tp->snap_len = TFCAPTUREMAX_GET(ctlb);
-	tp->min_len = TFMINPKTSIZE_GET(ctlb);
-	tp->skip_ofst = TFOFFSET_GET(ctla);
-	tp->skip_len = TFLENGTH_GET(ctla);
-	tp->invert = !!(ctla & TFINVERTMATCH);
-	tp->port = TFPORT_GET(ctla);
-
-	ofst = (MPS_TRC_FILTER1_MATCH - MPS_TRC_FILTER0_MATCH) * idx;
-	data_reg = MPS_TRC_FILTER0_MATCH + ofst;
-	mask_reg = MPS_TRC_FILTER0_DONT_CARE + ofst;
-
-	for (i = 0; i < TRACE_LEN / 4; i++, data_reg += 4, mask_reg += 4) {
-		tp->mask[i] = ~t4_read_reg(adap, mask_reg);
-		tp->data[i] = t4_read_reg(adap, data_reg) & tp->mask[i];
-	}
-}
-
-/**
  *	get_mps_bg_map - return the buffer groups associated with a port
  *	@adap: the adapter
  *	@idx: the port index
@@ -2133,52 +1902,6 @@
 }
 
 /**
- *	t4_get_lb_stats - collect loopback port statistics
- *	@adap: the adapter
- *	@idx: the loopback port index
- *	@p: the stats structure to fill
- *
- *	Return HW statistics for the given loopback port.
- */
-void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p)
-{
-	u32 bgmap = get_mps_bg_map(adap, idx);
-
-#define GET_STAT(name) \
-	t4_read_reg64(adap, PORT_REG(idx, MPS_PORT_STAT_LB_PORT_##name##_L))
-#define GET_STAT_COM(name) t4_read_reg64(adap, MPS_STAT_##name##_L)
-
-	p->octets           = GET_STAT(BYTES);
-	p->frames           = GET_STAT(FRAMES);
-	p->bcast_frames     = GET_STAT(BCAST);
-	p->mcast_frames     = GET_STAT(MCAST);
-	p->ucast_frames     = GET_STAT(UCAST);
-	p->error_frames     = GET_STAT(ERROR);
-
-	p->frames_64        = GET_STAT(64B);
-	p->frames_65_127    = GET_STAT(65B_127B);
-	p->frames_128_255   = GET_STAT(128B_255B);
-	p->frames_256_511   = GET_STAT(256B_511B);
-	p->frames_512_1023  = GET_STAT(512B_1023B);
-	p->frames_1024_1518 = GET_STAT(1024B_1518B);
-	p->frames_1519_max  = GET_STAT(1519B_MAX);
-	p->drop             = t4_read_reg(adap, PORT_REG(idx,
-					  MPS_PORT_STAT_LB_PORT_DROP_FRAMES));
-
-	p->ovflow0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_LB_DROP_FRAME) : 0;
-	p->ovflow1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_LB_DROP_FRAME) : 0;
-	p->ovflow2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_LB_DROP_FRAME) : 0;
-	p->ovflow3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_LB_DROP_FRAME) : 0;
-	p->trunc0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_LB_TRUNC_FRAME) : 0;
-	p->trunc1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_LB_TRUNC_FRAME) : 0;
-	p->trunc2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_LB_TRUNC_FRAME) : 0;
-	p->trunc3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_LB_TRUNC_FRAME) : 0;
-
-#undef GET_STAT
-#undef GET_STAT_COM
-}
-
-/**
  *	t4_wol_magic_enable - enable/disable magic packet WoL
  *	@adap: the adapter
  *	@port: the physical port index
@@ -2584,30 +2307,6 @@
 }
 
 /**
- *	t4_free_vi - free a virtual interface
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@pf: the PF owning the VI
- *	@vf: the VF owning the VI
- *	@viid: virtual interface identifiler
- *
- *	Free a previously allocated virtual interface.
- */
-int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
-	       unsigned int vf, unsigned int viid)
-{
-	struct fw_vi_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_VI_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_EXEC | FW_VI_CMD_PFN(pf) |
-			    FW_VI_CMD_VFN(vf));
-	c.alloc_to_len16 = htonl(FW_VI_CMD_FREE | FW_LEN16(c));
-	c.type_viid = htons(FW_VI_CMD_VIID(viid));
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
-}
-
-/**
  *	t4_set_rxmode - set Rx properties of a virtual interface
  *	@adap: the adapter
  *	@mbox: mailbox to use for the FW command
@@ -2833,37 +2532,6 @@
 }
 
 /**
- *	t4_iq_start_stop - enable/disable an ingress queue and its FLs
- *	@adap: the adapter
- *	@mbox: mailbox to use for the FW command
- *	@start: %true to enable the queues, %false to disable them
- *	@pf: the PF owning the queues
- *	@vf: the VF owning the queues
- *	@iqid: ingress queue id
- *	@fl0id: FL0 queue id or 0xffff if no attached FL0
- *	@fl1id: FL1 queue id or 0xffff if no attached FL1
- *
- *	Starts or stops an ingress queue and its associated FLs, if any.
- */
-int t4_iq_start_stop(struct adapter *adap, unsigned int mbox, bool start,
-		     unsigned int pf, unsigned int vf, unsigned int iqid,
-		     unsigned int fl0id, unsigned int fl1id)
-{
-	struct fw_iq_cmd c;
-
-	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD) | FW_CMD_REQUEST |
-			    FW_CMD_EXEC | FW_IQ_CMD_PFN(pf) |
-			    FW_IQ_CMD_VFN(vf));
-	c.alloc_to_len16 = htonl(FW_IQ_CMD_IQSTART(start) |
-				 FW_IQ_CMD_IQSTOP(!start) | FW_LEN16(c));
-	c.iqid = htons(iqid);
-	c.fl0id = htons(fl0id);
-	c.fl1id = htons(fl1id);
-	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
  *	t4_iq_free - free an ingress queue and its FLs
  *	@adap: the adapter
  *	@mbox: mailbox to use for the FW command
diff --git a/drivers/net/cxgb4/t4_hw.h b/drivers/net/cxgb4/t4_hw.h
index 10a0555..c26b455 100644
--- a/drivers/net/cxgb4/t4_hw.h
+++ b/drivers/net/cxgb4/t4_hw.h
@@ -42,6 +42,7 @@
 	MAX_MTU        = 9600,  /* max MAC MTU, excluding header + FCS */
 	EEPROMSIZE     = 17408, /* Serial EEPROM physical size */
 	EEPROMVSIZE    = 32768, /* Serial EEPROM virtual address space size */
+	EEPROMPFSIZE   = 1024,  /* EEPROM writable area size for PFn, n>0 */
 	RSS_NENTRIES   = 2048,  /* # of entries in RSS mapping table */
 	TCB_SIZE       = 128,   /* TCB size */
 	NMTUS          = 16,    /* size of MTU table */
diff --git a/drivers/net/cxgb4/t4fw_api.h b/drivers/net/cxgb4/t4fw_api.h
index 0969f2f..940584a 100644
--- a/drivers/net/cxgb4/t4fw_api.h
+++ b/drivers/net/cxgb4/t4fw_api.h
@@ -487,6 +487,11 @@
 	FW_PARAMS_PARAM_PFVF_CPMASK     = 0x25,
 	FW_PARAMS_PARAM_PFVF_OCQ_START  = 0x26,
 	FW_PARAMS_PARAM_PFVF_OCQ_END    = 0x27,
+	FW_PARAMS_PARAM_PFVF_CONM_MAP   = 0x28,
+	FW_PARAMS_PARAM_PFVF_IQFLINT_START = 0x29,
+	FW_PARAMS_PARAM_PFVF_IQFLINT_END = 0x2A,
+	FW_PARAMS_PARAM_PFVF_EQ_START	= 0x2B,
+	FW_PARAMS_PARAM_PFVF_EQ_END	= 0x2C,
 };
 
 /*
diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c
index 7b6d07f..555ecc5 100644
--- a/drivers/net/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/cxgb4vf/cxgb4vf_main.c
@@ -748,7 +748,10 @@
 	/*
 	 * Note that this interface is up and start everything up ...
 	 */
-	dev->real_num_tx_queues = pi->nqsets;
+	netif_set_real_num_tx_queues(dev, pi->nqsets);
+	err = netif_set_real_num_rx_queues(dev, pi->nqsets);
+	if (err)
+		return err;
 	set_bit(pi->port_id, &adapter->open_device_map);
 	link_start(dev);
 	netif_tx_start_all_queues(dev);
diff --git a/drivers/net/cxgb4vf/sge.c b/drivers/net/cxgb4vf/sge.c
index eb5a1c9..f10864d 100644
--- a/drivers/net/cxgb4vf/sge.c
+++ b/drivers/net/cxgb4vf/sge.c
@@ -1520,7 +1520,6 @@
 	__skb_pull(skb, PKTSHIFT);
 	skb->protocol = eth_type_trans(skb, rspq->netdev);
 	skb_record_rx_queue(skb, rspq->idx);
-	skb->dev->last_rx = jiffies;                  /* XXX removed 2.6.29 */
 	pi = netdev_priv(skb->dev);
 	rxq->stats.pkts++;
 
@@ -1535,7 +1534,7 @@
 		}
 		rxq->stats.rx_cso++;
 	} else
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 
 	if (unlikely(pkt->vlan_ex)) {
 		struct vlan_group *grp = pi->vlan_grp;
diff --git a/drivers/net/cxgb4vf/t4vf_common.h b/drivers/net/cxgb4vf/t4vf_common.h
index 5c7bde7..873cb7d 100644
--- a/drivers/net/cxgb4vf/t4vf_common.h
+++ b/drivers/net/cxgb4vf/t4vf_common.h
@@ -132,15 +132,15 @@
 	unsigned int mode;		/* RSS mode */
 	union {
 	    struct {
-		int synmapen:1;		/* SYN Map Enable */
-		int syn4tupenipv6:1;	/* enable hashing 4-tuple IPv6 SYNs */
-		int syn2tupenipv6:1;	/* enable hashing 2-tuple IPv6 SYNs */
-		int syn4tupenipv4:1;	/* enable hashing 4-tuple IPv4 SYNs */
-		int syn2tupenipv4:1;	/* enable hashing 2-tuple IPv4 SYNs */
-		int ofdmapen:1;		/* Offload Map Enable */
-		int tnlmapen:1;		/* Tunnel Map Enable */
-		int tnlalllookup:1;	/* Tunnel All Lookup */
-		int hashtoeplitz:1;	/* use Toeplitz hash */
+		unsigned int synmapen:1;	/* SYN Map Enable */
+		unsigned int syn4tupenipv6:1;	/* enable hashing 4-tuple IPv6 SYNs */
+		unsigned int syn2tupenipv6:1;	/* enable hashing 2-tuple IPv6 SYNs */
+		unsigned int syn4tupenipv4:1;	/* enable hashing 4-tuple IPv4 SYNs */
+		unsigned int syn2tupenipv4:1;	/* enable hashing 2-tuple IPv4 SYNs */
+		unsigned int ofdmapen:1;	/* Offload Map Enable */
+		unsigned int tnlmapen:1;	/* Tunnel Map Enable */
+		unsigned int tnlalllookup:1;	/* Tunnel All Lookup */
+		unsigned int hashtoeplitz:1;	/* use Toeplitz hash */
 	    } basicvirtual;
 	} u;
 };
@@ -151,10 +151,10 @@
 union rss_vi_config {
     struct {
 	u16 defaultq;			/* Ingress Queue ID for !tnlalllookup */
-	int ip6fourtupen:1;		/* hash 4-tuple IPv6 ingress packets */
-	int ip6twotupen:1;		/* hash 2-tuple IPv6 ingress packets */
-	int ip4fourtupen:1;		/* hash 4-tuple IPv4 ingress packets */
-	int ip4twotupen:1;		/* hash 2-tuple IPv4 ingress packets */
+	unsigned int ip6fourtupen:1;	/* hash 4-tuple IPv6 ingress packets */
+	unsigned int ip6twotupen:1;	/* hash 2-tuple IPv6 ingress packets */
+	unsigned int ip4fourtupen:1;	/* hash 4-tuple IPv4 ingress packets */
+	unsigned int ip4twotupen:1;	/* hash 2-tuple IPv4 ingress packets */
 	int udpen;			/* hash 4-tuple UDP ingress packets */
     } basicvirtual;
 };
diff --git a/drivers/net/de620.c b/drivers/net/de620.c
index f3650fd..1c51a75 100644
--- a/drivers/net/de620.c
+++ b/drivers/net/de620.c
@@ -676,7 +676,7 @@
 	de620_set_register(dev, W_NPRF, next_rx_page);
 	pr_debug("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page);
 
-	return (next_rx_page != curr_page); /* That was slightly tricky... */
+	return next_rx_page != curr_page; /* That was slightly tricky... */
 }
 
 /*********************************************
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index d7de376..219eb5a 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -1255,7 +1255,7 @@
 	 */
 	init_timer(&lp->multicast_timer);
 	lp->multicast_timer.data = (unsigned long) dev;
-	lp->multicast_timer.function = &lance_set_multicast_retry;
+	lp->multicast_timer.function = lance_set_multicast_retry;
 
 	ret = register_netdev(dev);
 	if (ret) {
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index e5667c5..417e143 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -1024,7 +1024,7 @@
 				 &data) != DFX_K_SUCCESS) {
 		printk("%s: Could not read adapter factory MAC address!\n",
 		       print_name);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 	}
 	le32 = cpu_to_le32(data);
 	memcpy(&bp->factory_mac_addr[0], &le32, sizeof(u32));
@@ -1033,7 +1033,7 @@
 				 &data) != DFX_K_SUCCESS) {
 		printk("%s: Could not read adapter factory MAC address!\n",
 		       print_name);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 	}
 	le32 = cpu_to_le32(data);
 	memcpy(&bp->factory_mac_addr[4], &le32, sizeof(u16));
@@ -1075,7 +1075,7 @@
 	if (top_v == NULL) {
 		printk("%s: Could not allocate memory for host buffers "
 		       "and structures!\n", print_name);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 	}
 	memset(top_v, 0, alloc_size);	/* zero out memory before continuing */
 	top_p = bp->kmalloced_dma;	/* get physical address of buffer */
@@ -1145,7 +1145,7 @@
 	DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",
 		   print_name, (long)bp->cons_block_virt, bp->cons_block_phys);
 
-	return(DFX_K_SUCCESS);
+	return DFX_K_SUCCESS;
 }
 
 
@@ -1195,7 +1195,7 @@
 	if (dfx_hw_dma_uninit(bp, bp->reset_type) != DFX_K_SUCCESS)
 		{
 		printk("%s: Could not uninitialize/reset adapter!\n", bp->dev->name);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 		}
 
 	/*
@@ -1229,7 +1229,7 @@
 							NULL) != DFX_K_SUCCESS)
 		{
 		printk("%s: Could not set adapter burst size!\n", bp->dev->name);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 		}
 
 	/*
@@ -1246,7 +1246,7 @@
 							NULL) != DFX_K_SUCCESS)
 		{
 		printk("%s: Could not set consumer block address!\n", bp->dev->name);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 		}
 
 	/*
@@ -1278,7 +1278,7 @@
 	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
 		{
 		printk("%s: DMA command request failed!\n", bp->dev->name);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 		}
 
 	/* Set the initial values for eFDXEnable and MACTReq MIB objects */
@@ -1294,7 +1294,7 @@
 	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
 		{
 		printk("%s: DMA command request failed!\n", bp->dev->name);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 		}
 
 	/* Initialize adapter CAM */
@@ -1302,7 +1302,7 @@
 	if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
 		{
 		printk("%s: Adapter CAM update failed!\n", bp->dev->name);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 		}
 
 	/* Initialize adapter filters */
@@ -1310,7 +1310,7 @@
 	if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
 		{
 		printk("%s: Adapter filters update failed!\n", bp->dev->name);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 		}
 
 	/*
@@ -1328,7 +1328,7 @@
 		printk("%s: Receive buffer allocation failed\n", bp->dev->name);
 		if (get_buffers)
 			dfx_rcv_flush(bp);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 		}
 
 	/* Issue START command and bring adapter to LINK_(UN)AVAILABLE state */
@@ -1339,13 +1339,13 @@
 		printk("%s: Start command failed\n", bp->dev->name);
 		if (get_buffers)
 			dfx_rcv_flush(bp);
-		return(DFX_K_FAILURE);
+		return DFX_K_FAILURE;
 		}
 
 	/* Initialization succeeded, reenable PDQ interrupts */
 
 	dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_ENABLE_DEF_INTS);
-	return(DFX_K_SUCCESS);
+	return DFX_K_SUCCESS;
 	}
 
 
@@ -1434,7 +1434,7 @@
 
 	/* Set device structure info */
 	netif_start_queue(dev);
-	return(0);
+	return 0;
 }
 
 
@@ -1526,7 +1526,7 @@
 
 	free_irq(dev->irq, dev);
 
-	return(0);
+	return 0;
 }
 
 
@@ -2027,7 +2027,7 @@
 
 	bp->cmd_req_virt->cmd_type = PI_CMD_K_SMT_MIB_GET;
 	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-		return((struct net_device_stats *) &bp->stats);
+		return (struct net_device_stats *)&bp->stats;
 
 	/* Fill the bp->stats structure with the SMT MIB object values */
 
@@ -2128,7 +2128,7 @@
 
 	bp->cmd_req_virt->cmd_type = PI_CMD_K_CNTRS_GET;
 	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-		return((struct net_device_stats *) &bp->stats);
+		return (struct net_device_stats *)&bp->stats;
 
 	/* Fill the bp->stats structure with the FDDI counter values */
 
@@ -2144,7 +2144,7 @@
 	bp->stats.port_lem_cts[0]			= bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[0].ls;
 	bp->stats.port_lem_cts[1]			= bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
 
-	return((struct net_device_stats *) &bp->stats);
+	return (struct net_device_stats *)&bp->stats;
 	}
 
 
@@ -2354,7 +2354,7 @@
 		{
 		DBG_printk("%s: Adapter CAM updated with new MAC address\n", dev->name);
 		}
-	return(0);			/* always return zero */
+	return 0;			/* always return zero */
 	}
 
 
@@ -2438,8 +2438,8 @@
 	/* Issue command to update adapter CAM, then return */
 
 	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-		return(DFX_K_FAILURE);
-	return(DFX_K_SUCCESS);
+		return DFX_K_FAILURE;
+	return DFX_K_SUCCESS;
 	}
 
 
@@ -2504,8 +2504,8 @@
 	/* Issue command to update adapter filters, then return */
 
 	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-		return(DFX_K_FAILURE);
-	return(DFX_K_SUCCESS);
+		return DFX_K_FAILURE;
+	return DFX_K_SUCCESS;
 	}
 
 
@@ -2561,7 +2561,7 @@
 		(status == PI_STATE_K_HALTED)		||
 		(status == PI_STATE_K_DMA_UNAVAIL)	||
 		(status == PI_STATE_K_UPGRADE))
-		return(DFX_K_OUTSTATE);
+		return DFX_K_OUTSTATE;
 
 	/* Put response buffer on the command response queue */
 
@@ -2599,7 +2599,7 @@
 		udelay(100);			/* wait for 100 microseconds */
 		}
 	if (timeout_cnt == 0)
-		return(DFX_K_HW_TIMEOUT);
+		return DFX_K_HW_TIMEOUT;
 
 	/* Bump (and wrap) the completion index and write out to register */
 
@@ -2619,14 +2619,14 @@
 		udelay(100);			/* wait for 100 microseconds */
 		}
 	if (timeout_cnt == 0)
-		return(DFX_K_HW_TIMEOUT);
+		return DFX_K_HW_TIMEOUT;
 
 	/* Bump (and wrap) the completion index and write out to register */
 
 	bp->cmd_rsp_reg.index.comp += 1;
 	bp->cmd_rsp_reg.index.comp &= PI_CMD_RSP_K_NUM_ENTRIES-1;
 	dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_RSP_PROD, bp->cmd_rsp_reg.lword);
-	return(DFX_K_SUCCESS);
+	return DFX_K_SUCCESS;
 	}
 
 
@@ -2700,7 +2700,7 @@
 		udelay(100);			/* wait for 100 microseconds */
 		}
 	if (timeout_cnt == 0)
-		return(DFX_K_HW_TIMEOUT);
+		return DFX_K_HW_TIMEOUT;
 
 	/*
 	 * If the address of host_data is non-zero, assume caller has supplied a
@@ -2710,7 +2710,7 @@
 
 	if (host_data != NULL)
 		dfx_port_read_long(bp, PI_PDQ_K_REG_HOST_DATA, host_data);
-	return(DFX_K_SUCCESS);
+	return DFX_K_SUCCESS;
 	}
 
 
@@ -2800,7 +2800,7 @@
 	PI_UINT32 port_status;		/* Port Status register value */
 
 	dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
-	return((port_status & PI_PSTATUS_M_STATE) >> PI_PSTATUS_V_STATE);
+	return (port_status & PI_PSTATUS_M_STATE) >> PI_PSTATUS_V_STATE;
 	}
 
 
@@ -2852,8 +2852,8 @@
 		udelay(100);					/* wait for 100 microseconds */
 		}
 	if (timeout_cnt == 0)
-		return(DFX_K_HW_TIMEOUT);
-	return(DFX_K_SUCCESS);
+		return DFX_K_HW_TIMEOUT;
+	return DFX_K_SUCCESS;
 	}
 
 /*
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index a2f238d..e1a8216 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -465,7 +465,7 @@
 	init_timer (&np->timer);
 	np->timer.expires = jiffies + 1*HZ;
 	np->timer.data = (unsigned long) dev;
-	np->timer.function = &rio_timer;
+	np->timer.function = rio_timer;
 	add_timer (&np->timer);
 
 	/* Start Tx/Rx */
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 4fd6b2b..9f6aeef 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -1056,7 +1056,7 @@
 				if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)
 					skb->ip_summed = CHECKSUM_UNNECESSARY;
 				else
-					skb->ip_summed = CHECKSUM_NONE;
+					skb_checksum_none_assert(skb);
 			}
 			netif_rx(skb);
 			dev->stats.rx_packets++;
diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c
index 7c07575..9d8a20b 100644
--- a/drivers/net/dnet.c
+++ b/drivers/net/dnet.c
@@ -27,7 +27,7 @@
 #undef DEBUG
 
 /* function for reading internal MAC register */
-u16 dnet_readw_mac(struct dnet *bp, u16 reg)
+static u16 dnet_readw_mac(struct dnet *bp, u16 reg)
 {
 	u16 data_read;
 
@@ -46,7 +46,7 @@
 }
 
 /* function for writing internal MAC register */
-void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val)
+static void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val)
 {
 	/* load data to write */
 	dnet_writel(bp, val, MACREG_DATA);
@@ -63,11 +63,11 @@
 {
 	u16 tmp;
 
-	tmp = cpu_to_be16(*((u16 *) bp->dev->dev_addr));
+	tmp = be16_to_cpup((__be16 *)bp->dev->dev_addr);
 	dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG, tmp);
-	tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 2)));
+	tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 2));
 	dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG, tmp);
-	tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 4)));
+	tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 4));
 	dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp);
 }
 
@@ -89,11 +89,11 @@
 	 * Mac_addr[15:0]).
 	 */
 	tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG);
-	*((u16 *) addr) = be16_to_cpu(tmp);
+	*((__be16 *)addr) = cpu_to_be16(tmp);
 	tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG);
-	*((u16 *) (addr + 2)) = be16_to_cpu(tmp);
+	*((__be16 *)(addr + 2)) = cpu_to_be16(tmp);
 	tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG);
-	*((u16 *) (addr + 4)) = be16_to_cpu(tmp);
+	*((__be16 *)(addr + 4)) = cpu_to_be16(tmp);
 
 	if (is_valid_ether_addr(addr))
 		memcpy(bp->dev->dev_addr, addr, sizeof(addr));
@@ -361,7 +361,7 @@
 }
 
 /* For Neptune board: LINK1000 as Link LED and TX as activity LED */
-int dnet_phy_marvell_fixup(struct phy_device *phydev)
+static int dnet_phy_marvell_fixup(struct phy_device *phydev)
 {
 	return phy_write(phydev, 0x18, 0x4148);
 }
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 37dcfdc..ff2d29b 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -36,6 +36,7 @@
 #include <linux/moduleparam.h>
 #include <linux/rtnetlink.h>
 #include <net/rtnetlink.h>
+#include <linux/u64_stats_sync.h>
 
 static int numdummies = 1;
 
@@ -55,21 +56,69 @@
 {
 }
 
+struct pcpu_dstats {
+	u64			tx_packets;
+	u64			tx_bytes;
+	struct u64_stats_sync	syncp;
+};
+
+static struct rtnl_link_stats64 *dummy_get_stats64(struct net_device *dev,
+						   struct rtnl_link_stats64 *stats)
+{
+	int i;
+
+	for_each_possible_cpu(i) {
+		const struct pcpu_dstats *dstats;
+		u64 tbytes, tpackets;
+		unsigned int start;
+
+		dstats = per_cpu_ptr(dev->dstats, i);
+		do {
+			start = u64_stats_fetch_begin(&dstats->syncp);
+			tbytes = dstats->tx_bytes;
+			tpackets = dstats->tx_packets;
+		} while (u64_stats_fetch_retry(&dstats->syncp, start));
+		stats->tx_bytes += tbytes;
+		stats->tx_packets += tpackets;
+	}
+	return stats;
+}
 
 static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
+	struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
+
+	u64_stats_update_begin(&dstats->syncp);
+	dstats->tx_packets++;
+	dstats->tx_bytes += skb->len;
+	u64_stats_update_end(&dstats->syncp);
 
 	dev_kfree_skb(skb);
 	return NETDEV_TX_OK;
 }
 
+static int dummy_dev_init(struct net_device *dev)
+{
+	dev->dstats = alloc_percpu(struct pcpu_dstats);
+	if (!dev->dstats)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void dummy_dev_free(struct net_device *dev)
+{
+	free_percpu(dev->dstats);
+	free_netdev(dev);
+}
+
 static const struct net_device_ops dummy_netdev_ops = {
+	.ndo_init		= dummy_dev_init,
 	.ndo_start_xmit		= dummy_xmit,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_multicast_list = set_multicast_list,
 	.ndo_set_mac_address	= dummy_set_address,
+	.ndo_get_stats64	= dummy_get_stats64,
 };
 
 static void dummy_setup(struct net_device *dev)
@@ -78,14 +127,17 @@
 
 	/* Initialize the device structure. */
 	dev->netdev_ops = &dummy_netdev_ops;
-	dev->destructor = free_netdev;
+	dev->destructor = dummy_dev_free;
 
 	/* Fill in device structure with ethernet-generic values. */
 	dev->tx_queue_len = 0;
 	dev->flags |= IFF_NOARP;
 	dev->flags &= ~IFF_MULTICAST;
+	dev->features	|= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO;
+	dev->features	|= NETIF_F_NO_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
 	random_ether_addr(dev->dev_addr);
 }
+
 static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
 {
 	if (tb[IFLA_ADDRESS]) {
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 8e2eab4..b0aa9e6 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2215,10 +2215,10 @@
 static int e100_asf(struct nic *nic)
 {
 	/* ASF can be enabled from eeprom */
-	return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) &&
+	return (nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) &&
 	   (nic->eeprom[eeprom_config_asf] & eeprom_asf) &&
 	   !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
-	   ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE));
+	   ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE);
 }
 
 static int e100_up(struct nic *nic)
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 99288b9..a881dd0 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -310,6 +310,9 @@
 	int need_ioport;
 
 	bool discarding;
+
+	struct work_struct fifo_stall_task;
+	struct work_struct phy_info_task;
 };
 
 enum e1000_state_t {
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 5cc39ed..a117f2a 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -123,8 +123,10 @@
                                 struct e1000_rx_ring *rx_ring);
 static void e1000_set_rx_mode(struct net_device *netdev);
 static void e1000_update_phy_info(unsigned long data);
+static void e1000_update_phy_info_task(struct work_struct *work);
 static void e1000_watchdog(unsigned long data);
 static void e1000_82547_tx_fifo_stall(unsigned long data);
+static void e1000_82547_tx_fifo_stall_task(struct work_struct *work);
 static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
 				    struct net_device *netdev);
 static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
@@ -519,8 +521,21 @@
 	e1000_clean_all_rx_rings(adapter);
 }
 
+void e1000_reinit_safe(struct e1000_adapter *adapter)
+{
+	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
+		msleep(1);
+	rtnl_lock();
+	e1000_down(adapter);
+	e1000_up(adapter);
+	rtnl_unlock();
+	clear_bit(__E1000_RESETTING, &adapter->flags);
+}
+
 void e1000_reinit_locked(struct e1000_adapter *adapter)
 {
+	/* if rtnl_lock is not held the call path is bogus */
+	ASSERT_RTNL();
 	WARN_ON(in_interrupt());
 	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
 		msleep(1);
@@ -790,6 +805,70 @@
 };
 
 /**
+ * e1000_init_hw_struct - initialize members of hw struct
+ * @adapter: board private struct
+ * @hw: structure used by e1000_hw.c
+ *
+ * Factors out initialization of the e1000_hw struct to its own function
+ * that can be called very early at init (just after struct allocation).
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ * Returns negative error codes if MAC type setup fails.
+ */
+static int e1000_init_hw_struct(struct e1000_adapter *adapter,
+				struct e1000_hw *hw)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	/* PCI config space info */
+	hw->vendor_id = pdev->vendor;
+	hw->device_id = pdev->device;
+	hw->subsystem_vendor_id = pdev->subsystem_vendor;
+	hw->subsystem_id = pdev->subsystem_device;
+	hw->revision_id = pdev->revision;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
+
+	hw->max_frame_size = adapter->netdev->mtu +
+			     ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
+
+	/* identify the MAC */
+	if (e1000_set_mac_type(hw)) {
+		e_err(probe, "Unknown MAC Type\n");
+		return -EIO;
+	}
+
+	switch (hw->mac_type) {
+	default:
+		break;
+	case e1000_82541:
+	case e1000_82547:
+	case e1000_82541_rev_2:
+	case e1000_82547_rev_2:
+		hw->phy_init_script = 1;
+		break;
+	}
+
+	e1000_set_media_type(hw);
+	e1000_get_bus_info(hw);
+
+	hw->wait_autoneg_complete = false;
+	hw->tbi_compatibility_en = true;
+	hw->adaptive_ifs = true;
+
+	/* Copper options */
+
+	if (hw->media_type == e1000_media_type_copper) {
+		hw->mdix = AUTO_ALL_MODES;
+		hw->disable_polarity_correction = false;
+		hw->master_slave = E1000_MASTER_SLAVE;
+	}
+
+	return 0;
+}
+
+/**
  * e1000_probe - Device Initialization Routine
  * @pdev: PCI device information struct
  * @ent: entry in e1000_pci_tbl
@@ -826,22 +905,6 @@
 	if (err)
 		return err;
 
-	if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) &&
-	    !dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) {
-		pci_using_dac = 1;
-	} else {
-		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
-		if (err) {
-			err = dma_set_coherent_mask(&pdev->dev,
-						    DMA_BIT_MASK(32));
-			if (err) {
-				pr_err("No usable DMA config, aborting\n");
-				goto err_dma;
-			}
-		}
-		pci_using_dac = 0;
-	}
-
 	err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
 	if (err)
 		goto err_pci_reg;
@@ -885,6 +948,32 @@
 		}
 	}
 
+	/* make ready for any if (hw->...) below */
+	err = e1000_init_hw_struct(adapter, hw);
+	if (err)
+		goto err_sw_init;
+
+	/*
+	 * there is a workaround being applied below that limits
+	 * 64-bit DMA addresses to 64-bit hardware.  There are some
+	 * 32-bit adapters that Tx hang when given 64-bit DMA addresses
+	 */
+	pci_using_dac = 0;
+	if ((hw->bus_type == e1000_bus_type_pcix) &&
+	    !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+		/*
+		 * according to DMA-API-HOWTO, coherent calls will always
+		 * succeed if the set call did
+		 */
+		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+		pci_using_dac = 1;
+	} else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
+		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+	} else {
+		pr_err("No usable DMA config, aborting\n");
+		goto err_dma;
+	}
+
 	netdev->netdev_ops = &e1000_netdev_ops;
 	e1000_set_ethtool_ops(netdev);
 	netdev->watchdog_timeo = 5 * HZ;
@@ -914,8 +1003,10 @@
 	   (hw->mac_type != e1000_82547))
 		netdev->features |= NETIF_F_TSO;
 
-	if (pci_using_dac)
+	if (pci_using_dac) {
 		netdev->features |= NETIF_F_HIGHDMA;
+		netdev->vlan_features |= NETIF_F_HIGHDMA;
+	}
 
 	netdev->vlan_features |= NETIF_F_TSO;
 	netdev->vlan_features |= NETIF_F_HW_CSUM;
@@ -959,21 +1050,21 @@
 	if (!is_valid_ether_addr(netdev->perm_addr))
 		e_err(probe, "Invalid MAC Address\n");
 
-	e1000_get_bus_info(hw);
-
 	init_timer(&adapter->tx_fifo_stall_timer);
-	adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall;
+	adapter->tx_fifo_stall_timer.function = e1000_82547_tx_fifo_stall;
 	adapter->tx_fifo_stall_timer.data = (unsigned long)adapter;
 
 	init_timer(&adapter->watchdog_timer);
-	adapter->watchdog_timer.function = &e1000_watchdog;
+	adapter->watchdog_timer.function = e1000_watchdog;
 	adapter->watchdog_timer.data = (unsigned long) adapter;
 
 	init_timer(&adapter->phy_info_timer);
-	adapter->phy_info_timer.function = &e1000_update_phy_info;
+	adapter->phy_info_timer.function = e1000_update_phy_info;
 	adapter->phy_info_timer.data = (unsigned long)adapter;
 
+	INIT_WORK(&adapter->fifo_stall_task, e1000_82547_tx_fifo_stall_task);
 	INIT_WORK(&adapter->reset_task, e1000_reset_task);
+	INIT_WORK(&adapter->phy_info_task, e1000_update_phy_info_task);
 
 	e1000_check_options(adapter);
 
@@ -1072,6 +1163,7 @@
 		iounmap(hw->flash_address);
 	kfree(adapter->tx_ring);
 	kfree(adapter->rx_ring);
+err_dma:
 err_sw_init:
 	iounmap(hw->hw_addr);
 err_ioremap:
@@ -1079,7 +1171,6 @@
 err_alloc_etherdev:
 	pci_release_selected_regions(pdev, bars);
 err_pci_reg:
-err_dma:
 	pci_disable_device(pdev);
 	return err;
 }
@@ -1131,62 +1222,12 @@
  * @adapter: board private structure to initialize
  *
  * e1000_sw_init initializes the Adapter private data structure.
- * Fields are initialized based on PCI device information and
- * OS network device settings (MTU size).
+ * e1000_init_hw_struct MUST be called before this function
  **/
 
 static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
 {
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-
-	/* PCI config space info */
-
-	hw->vendor_id = pdev->vendor;
-	hw->device_id = pdev->device;
-	hw->subsystem_vendor_id = pdev->subsystem_vendor;
-	hw->subsystem_id = pdev->subsystem_device;
-	hw->revision_id = pdev->revision;
-
-	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
-
 	adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
-	hw->max_frame_size = netdev->mtu +
-			     ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
-	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
-
-	/* identify the MAC */
-
-	if (e1000_set_mac_type(hw)) {
-		e_err(probe, "Unknown MAC Type\n");
-		return -EIO;
-	}
-
-	switch (hw->mac_type) {
-	default:
-		break;
-	case e1000_82541:
-	case e1000_82547:
-	case e1000_82541_rev_2:
-	case e1000_82547_rev_2:
-		hw->phy_init_script = 1;
-		break;
-	}
-
-	e1000_set_media_type(hw);
-
-	hw->wait_autoneg_complete = false;
-	hw->tbi_compatibility_en = true;
-	hw->adaptive_ifs = true;
-
-	/* Copper options */
-
-	if (hw->media_type == e1000_media_type_copper) {
-		hw->mdix = AUTO_ALL_MODES;
-		hw->disable_polarity_correction = false;
-		hw->master_slave = E1000_MASTER_SLAVE;
-	}
 
 	adapter->num_tx_queues = 1;
 	adapter->num_rx_queues = 1;
@@ -2210,22 +2251,45 @@
 static void e1000_update_phy_info(unsigned long data)
 {
 	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+	schedule_work(&adapter->phy_info_task);
+}
+
+static void e1000_update_phy_info_task(struct work_struct *work)
+{
+	struct e1000_adapter *adapter = container_of(work,
+	                                             struct e1000_adapter,
+	                                             phy_info_task);
 	struct e1000_hw *hw = &adapter->hw;
+
+	rtnl_lock();
 	e1000_phy_get_info(hw, &adapter->phy_info);
+	rtnl_unlock();
 }
 
 /**
  * e1000_82547_tx_fifo_stall - Timer Call-back
  * @data: pointer to adapter cast into an unsigned long
  **/
-
 static void e1000_82547_tx_fifo_stall(unsigned long data)
 {
 	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+	schedule_work(&adapter->fifo_stall_task);
+}
+
+/**
+ * e1000_82547_tx_fifo_stall_task - task to complete work
+ * @work: work struct contained inside adapter struct
+ **/
+static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
+{
+	struct e1000_adapter *adapter = container_of(work,
+	                                             struct e1000_adapter,
+	                                             fifo_stall_task);
 	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	u32 tctl;
 
+	rtnl_lock();
 	if (atomic_read(&adapter->tx_fifo_stall)) {
 		if ((er32(TDT) == er32(TDH)) &&
 		   (er32(TDFT) == er32(TDFH)) &&
@@ -2246,6 +2310,7 @@
 			mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
 		}
 	}
+	rtnl_unlock();
 }
 
 bool e1000_has_link(struct e1000_adapter *adapter)
@@ -3054,7 +3119,7 @@
 		}
 	}
 
-	if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+	if (unlikely(vlan_tx_tag_present(skb))) {
 		tx_flags |= E1000_TX_FLAGS_VLAN;
 		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
 	}
@@ -3113,7 +3178,7 @@
 	struct e1000_adapter *adapter =
 		container_of(work, struct e1000_adapter, reset_task);
 
-	e1000_reinit_locked(adapter);
+	e1000_reinit_safe(adapter);
 }
 
 /**
@@ -3535,7 +3600,7 @@
 	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);
+	return count < tx_ring->count;
 }
 
 /**
@@ -3552,7 +3617,8 @@
 	struct e1000_hw *hw = &adapter->hw;
 	u16 status = (u16)status_err;
 	u8 errors = (u8)(status_err >> 24);
-	skb->ip_summed = CHECKSUM_NONE;
+
+	skb_checksum_none_assert(skb);
 
 	/* 82543 or newer only */
 	if (unlikely(hw->mac_type < e1000_82543)) return;
@@ -3598,13 +3664,14 @@
 static void e1000_receive_skb(struct e1000_adapter *adapter, u8 status,
 			      __le16 vlan, struct sk_buff *skb)
 {
-	if (unlikely(adapter->vlgrp && (status & E1000_RXD_STAT_VP))) {
-		vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-		                         le16_to_cpu(vlan) &
-		                         E1000_RXD_SPC_VLAN_MASK);
-	} else {
-		netif_receive_skb(skb);
-	}
+	skb->protocol = eth_type_trans(skb, adapter->netdev);
+
+	if ((unlikely(adapter->vlgrp && (status & E1000_RXD_STAT_VP))))
+		vlan_gro_receive(&adapter->napi, adapter->vlgrp,
+				 le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK,
+				 skb);
+	else
+		napi_gro_receive(&adapter->napi, skb);
 }
 
 /**
@@ -3762,8 +3829,6 @@
 			goto next_desc;
 		}
 
-		skb->protocol = eth_type_trans(skb, netdev);
-
 		e1000_receive_skb(adapter, status, rx_desc->special, skb);
 
 next_desc:
@@ -3926,8 +3991,6 @@
 				  ((u32)(rx_desc->errors) << 24),
 				  le16_to_cpu(rx_desc->csum), skb);
 
-		skb->protocol = eth_type_trans(skb, netdev);
-
 		e1000_receive_skb(adapter, status, rx_desc->special, skb);
 
 next_desc:
@@ -4478,7 +4541,7 @@
 
 	if (adapter->vlgrp) {
 		u16 vid;
-		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+		for (vid = 0; vid < VLAN_N_VID; vid++) {
 			if (!vlan_group_get_device(adapter->vlgrp, vid))
 				continue;
 			e1000_vlan_rx_add_vid(adapter->netdev, vid);
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index d3d4a57..ca663f1 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -1801,7 +1801,8 @@
 				  | FLAG_RESET_OVERWRITES_LAA /* errata */
 				  | FLAG_TARC_SPEED_MODE_BIT /* errata */
 				  | FLAG_APME_CHECK_PORT_B,
-	.flags2			= FLAG2_DISABLE_ASPM_L1, /* errata 13 */
+	.flags2			= FLAG2_DISABLE_ASPM_L1 /* errata 13 */
+				  | FLAG2_DMA_BURST,
 	.pba			= 38,
 	.max_hw_frame_size	= DEFAULT_JUMBO,
 	.get_variants		= e1000_get_variants_82571,
@@ -1819,7 +1820,8 @@
 				  | FLAG_RX_CSUM_ENABLED
 				  | FLAG_HAS_CTRLEXT_ON_LOAD
 				  | FLAG_TARC_SPEED_MODE_BIT, /* errata */
-	.flags2			= FLAG2_DISABLE_ASPM_L1, /* errata 13 */
+	.flags2			= FLAG2_DISABLE_ASPM_L1 /* errata 13 */
+				  | FLAG2_DMA_BURST,
 	.pba			= 38,
 	.max_hw_frame_size	= DEFAULT_JUMBO,
 	.get_variants		= e1000_get_variants_82571,
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index 93b3bed..d3f7a9c 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -446,7 +446,9 @@
 
 /* Transmit Descriptor Control */
 #define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
+#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
 #define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
+#define E1000_TXDCTL_GRAN    0x01000000 /* TXDCTL Granularity */
 #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
 #define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
 /* Enable the counting of desc. still to be processed. */
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index f9a31c8..cee882d 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -153,6 +153,33 @@
 /* Time to wait before putting the device into D3 if there's no link (in ms). */
 #define LINK_TIMEOUT		100
 
+#define DEFAULT_RDTR			0
+#define DEFAULT_RADV			8
+#define BURST_RDTR			0x20
+#define BURST_RADV			0x20
+
+/*
+ * in the case of WTHRESH, it appears at least the 82571/2 hardware
+ * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when
+ * WTHRESH=4, and since we want 64 bytes at a time written back, set
+ * it to 5
+ */
+#define E1000_TXDCTL_DMA_BURST_ENABLE                          \
+	(E1000_TXDCTL_GRAN | /* set descriptor granularity */  \
+	 E1000_TXDCTL_COUNT_DESC |                             \
+	 (5 << 16) | /* wthresh must be +1 more than desired */\
+	 (1 << 8)  | /* hthresh */                             \
+	 0x1f)       /* pthresh */
+
+#define E1000_RXDCTL_DMA_BURST_ENABLE                          \
+	(0x01000000 | /* set descriptor granularity */         \
+	 (4 << 16)  | /* set writeback threshold    */         \
+	 (4 << 8)   | /* set prefetch threshold     */         \
+	 0x20)        /* set hthresh                */
+
+#define E1000_TIDV_FPD (1 << 31)
+#define E1000_RDTR_FPD (1 << 31)
+
 enum e1000_boards {
 	board_82571,
 	board_82572,
@@ -425,6 +452,8 @@
 #define FLAG2_DISABLE_ASPM_L1             (1 << 3)
 #define FLAG2_HAS_PHY_STATS               (1 << 4)
 #define FLAG2_HAS_EEE                     (1 << 5)
+#define FLAG2_DMA_BURST                   (1 << 6)
+#define FLAG2_DISABLE_AIM                 (1 << 8)
 
 #define E1000_RX_DESC_PS(R, i)	    \
 	(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
index 45aebb4..24f8ac9 100644
--- a/drivers/net/e1000e/es2lan.c
+++ b/drivers/net/e1000e/es2lan.c
@@ -1494,6 +1494,7 @@
 				  | FLAG_APME_CHECK_PORT_B
 				  | FLAG_DISABLE_FC_PAUSE_TIME /* errata */
 				  | FLAG_TIPG_MEDIUM_FOR_80003ESLAN,
+	.flags2			= FLAG2_DMA_BURST,
 	.pba			= 38,
 	.max_hw_frame_size	= DEFAULT_JUMBO,
 	.get_variants		= e1000_get_variants_80003es2lan,
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 6355a1b..8984d16 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -368,7 +368,7 @@
 static u32 e1000_get_rx_csum(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	return (adapter->flags & FLAG_RX_CSUM_ENABLED);
+	return adapter->flags & FLAG_RX_CSUM_ENABLED;
 }
 
 static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
@@ -389,7 +389,7 @@
 
 static u32 e1000_get_tx_csum(struct net_device *netdev)
 {
-	return ((netdev->features & NETIF_F_HW_CSUM) != 0);
+	return (netdev->features & NETIF_F_HW_CSUM) != 0;
 }
 
 static int e1000_set_tx_csum(struct net_device *netdev, u32 data)
@@ -1717,13 +1717,6 @@
 
 		e_info("offline testing starting\n");
 
-		/*
-		 * Link test performed before hardware reset so autoneg doesn't
-		 * interfere with test result
-		 */
-		if (e1000_link_test(adapter, &data[4]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
 		if (if_running)
 			/* indicate we're in test mode */
 			dev_close(netdev);
@@ -1747,16 +1740,20 @@
 		if (e1000_loopback_test(adapter, &data[3]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
-		/* restore speed, duplex, autoneg settings */
-		adapter->hw.phy.autoneg_advertised = autoneg_advertised;
-		adapter->hw.mac.forced_speed_duplex = forced_speed_duplex;
-		adapter->hw.mac.autoneg = autoneg;
-
 		/* force this routine to wait until autoneg complete/timeout */
 		adapter->hw.phy.autoneg_wait_to_complete = 1;
 		e1000e_reset(adapter);
 		adapter->hw.phy.autoneg_wait_to_complete = 0;
 
+		if (e1000_link_test(adapter, &data[4]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		/* restore speed, duplex, autoneg settings */
+		adapter->hw.phy.autoneg_advertised = autoneg_advertised;
+		adapter->hw.mac.forced_speed_duplex = forced_speed_duplex;
+		adapter->hw.mac.autoneg = autoneg;
+		e1000e_reset(adapter);
+
 		clear_bit(__E1000_TESTING, &adapter->state);
 		if (if_running)
 			dev_open(netdev);
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index 66ed08f..ba302a5 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -57,6 +57,7 @@
 	E1000_SCTL     = 0x00024, /* SerDes Control - RW */
 	E1000_FCAL     = 0x00028, /* Flow Control Address Low - RW */
 	E1000_FCAH     = 0x0002C, /* Flow Control Address High -RW */
+	E1000_FEXTNVM4 = 0x00024, /* Future Extended NVM 4 - RW */
 	E1000_FEXTNVM  = 0x00028, /* Future Extended NVM - RW */
 	E1000_FCT      = 0x00030, /* Flow Control Type - RW */
 	E1000_VET      = 0x00038, /* VLAN Ether Type - RW */
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 63930d1..e3374d9 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -105,6 +105,10 @@
 #define E1000_FEXTNVM_SW_CONFIG		1
 #define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ */
 
+#define E1000_FEXTNVM4_BEACON_DURATION_MASK    0x7
+#define E1000_FEXTNVM4_BEACON_DURATION_8USEC   0x7
+#define E1000_FEXTNVM4_BEACON_DURATION_16USEC  0x3
+
 #define PCIE_ICH8_SNOOP_ALL		PCIE_NO_SNOOP_ALL
 
 #define E1000_ICH_RAR_ENTRIES		7
@@ -125,6 +129,7 @@
 
 /* SMBus Address Phy Register */
 #define HV_SMB_ADDR            PHY_REG(768, 26)
+#define HV_SMB_ADDR_MASK       0x007F
 #define HV_SMB_ADDR_PEC_EN     0x0200
 #define HV_SMB_ADDR_VALID      0x0080
 
@@ -237,6 +242,8 @@
 static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
 static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
 static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
+static s32 e1000_k1_workaround_lv(struct e1000_hw *hw);
+static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate);
 
 static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
 {
@@ -272,7 +279,7 @@
 static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 {
 	struct e1000_phy_info *phy = &hw->phy;
-	u32 ctrl;
+	u32 ctrl, fwsm;
 	s32 ret_val = 0;
 
 	phy->addr                     = 1;
@@ -294,7 +301,8 @@
 	 * disabled, then toggle the LANPHYPC Value bit to force
 	 * the interconnect to PCIe mode.
 	 */
-	if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
+	fwsm = er32(FWSM);
+	if (!(fwsm & E1000_ICH_FWSM_FW_VALID)) {
 		ctrl = er32(CTRL);
 		ctrl |=  E1000_CTRL_LANPHYPC_OVERRIDE;
 		ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
@@ -303,6 +311,13 @@
 		ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
 		ew32(CTRL, ctrl);
 		msleep(50);
+
+		/*
+		 * Gate automatic PHY configuration by hardware on
+		 * non-managed 82579
+		 */
+		if (hw->mac.type == e1000_pch2lan)
+			e1000_gate_hw_phy_config_ich8lan(hw, true);
 	}
 
 	/*
@@ -315,6 +330,13 @@
 	if (ret_val)
 		goto out;
 
+	/* Ungate automatic PHY configuration on non-managed 82579 */
+	if ((hw->mac.type == e1000_pch2lan)  &&
+	    !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
+		msleep(10);
+		e1000_gate_hw_phy_config_ich8lan(hw, false);
+	}
+
 	phy->id = e1000_phy_unknown;
 	ret_val = e1000e_get_phy_id(hw);
 	if (ret_val)
@@ -561,13 +583,10 @@
 	if (mac->type == e1000_ich8lan)
 		e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
 
-	/* Disable PHY configuration by hardware, config by software */
-	if (mac->type == e1000_pch2lan) {
-		u32 extcnf_ctrl = er32(EXTCNF_CTRL);
-
-		extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
-		ew32(EXTCNF_CTRL, extcnf_ctrl);
-	}
+	/* Gate automatic PHY configuration by hardware on managed 82579 */
+	if ((mac->type == e1000_pch2lan) &&
+	    (er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
+		e1000_gate_hw_phy_config_ich8lan(hw, true);
 
 	return 0;
 }
@@ -652,6 +671,12 @@
 			goto out;
 	}
 
+	if (hw->mac.type == e1000_pch2lan) {
+		ret_val = e1000_k1_workaround_lv(hw);
+		if (ret_val)
+			goto out;
+	}
+
 	/*
 	 * Check if there was DownShift, must be checked
 	 * immediately after link-up
@@ -895,6 +920,34 @@
 }
 
 /**
+ *  e1000_write_smbus_addr - Write SMBus address to PHY needed during Sx states
+ *  @hw: pointer to the HW structure
+ *
+ *  Assumes semaphore already acquired.
+ *
+ **/
+static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
+{
+	u16 phy_data;
+	u32 strap = er32(STRAP);
+	s32 ret_val = 0;
+
+	strap &= E1000_STRAP_SMBUS_ADDRESS_MASK;
+
+	ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data);
+	if (ret_val)
+		goto out;
+
+	phy_data &= ~HV_SMB_ADDR_MASK;
+	phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT);
+	phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
+	ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data);
+
+out:
+	return ret_val;
+}
+
+/**
  *  e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration
  *  @hw:   pointer to the HW structure
  *
@@ -903,7 +956,6 @@
  **/
 static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
 {
-	struct e1000_adapter *adapter = hw->adapter;
 	struct e1000_phy_info *phy = &hw->phy;
 	u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
 	s32 ret_val = 0;
@@ -921,7 +973,8 @@
 		if (phy->type != e1000_phy_igp_3)
 			return ret_val;
 
-		if (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) {
+		if ((hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) ||
+		    (hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_C)) {
 			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
 			break;
 		}
@@ -961,21 +1014,16 @@
 	cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
 	cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
 
-	if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
-	    ((hw->mac.type == e1000_pchlan) ||
-	     (hw->mac.type == e1000_pch2lan))) {
+	if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
+	    (hw->mac.type == e1000_pchlan)) ||
+	     (hw->mac.type == e1000_pch2lan)) {
 		/*
 		 * HW configures the SMBus address and LEDs when the
 		 * OEM and LCD Write Enable bits are set in the NVM.
 		 * When both NVM bits are cleared, SW will configure
 		 * them instead.
 		 */
-		data = er32(STRAP);
-		data &= E1000_STRAP_SMBUS_ADDRESS_MASK;
-		reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT;
-		reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
-		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR,
-							reg_data);
+		ret_val = e1000_write_smbus_addr(hw);
 		if (ret_val)
 			goto out;
 
@@ -1440,10 +1488,6 @@
 			goto out;
 
 		/* Enable jumbo frame workaround in the PHY */
-		e1e_rphy(hw, PHY_REG(769, 20), &data);
-		ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14));
-		if (ret_val)
-			goto out;
 		e1e_rphy(hw, PHY_REG(769, 23), &data);
 		data &= ~(0x7F << 5);
 		data |= (0x37 << 5);
@@ -1452,7 +1496,6 @@
 			goto out;
 		e1e_rphy(hw, PHY_REG(769, 16), &data);
 		data &= ~(1 << 13);
-		data |= (1 << 12);
 		ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
 		if (ret_val)
 			goto out;
@@ -1477,7 +1520,7 @@
 
 		mac_reg = er32(RCTL);
 		mac_reg &= ~E1000_RCTL_SECRC;
-		ew32(FFLT_DBG, mac_reg);
+		ew32(RCTL, mac_reg);
 
 		ret_val = e1000e_read_kmrn_reg(hw,
 						E1000_KMRNCTRLSTA_CTRL_OFFSET,
@@ -1503,17 +1546,12 @@
 			goto out;
 
 		/* Write PHY register values back to h/w defaults */
-		e1e_rphy(hw, PHY_REG(769, 20), &data);
-		ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14));
-		if (ret_val)
-			goto out;
 		e1e_rphy(hw, PHY_REG(769, 23), &data);
 		data &= ~(0x7F << 5);
 		ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
 		if (ret_val)
 			goto out;
 		e1e_rphy(hw, PHY_REG(769, 16), &data);
-		data &= ~(1 << 12);
 		data |= (1 << 13);
 		ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
 		if (ret_val)
@@ -1559,6 +1597,69 @@
 }
 
 /**
+ *  e1000_k1_gig_workaround_lv - K1 Si workaround
+ *  @hw:   pointer to the HW structure
+ *
+ *  Workaround to set the K1 beacon duration for 82579 parts
+ **/
+static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	u16 status_reg = 0;
+	u32 mac_reg;
+
+	if (hw->mac.type != e1000_pch2lan)
+		goto out;
+
+	/* Set K1 beacon duration based on 1Gbps speed or otherwise */
+	ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg);
+	if (ret_val)
+		goto out;
+
+	if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE))
+	    == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) {
+		mac_reg = er32(FEXTNVM4);
+		mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
+
+		if (status_reg & HV_M_STATUS_SPEED_1000)
+			mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
+		else
+			mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
+
+		ew32(FEXTNVM4, mac_reg);
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware
+ *  @hw:   pointer to the HW structure
+ *  @gate: boolean set to true to gate, false to ungate
+ *
+ *  Gate/ungate the automatic PHY configuration via hardware; perform
+ *  the configuration via software instead.
+ **/
+static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate)
+{
+	u32 extcnf_ctrl;
+
+	if (hw->mac.type != e1000_pch2lan)
+		return;
+
+	extcnf_ctrl = er32(EXTCNF_CTRL);
+
+	if (gate)
+		extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
+	else
+		extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG;
+
+	ew32(EXTCNF_CTRL, extcnf_ctrl);
+	return;
+}
+
+/**
  *  e1000_lan_init_done_ich8lan - Check for PHY config completion
  *  @hw: pointer to the HW structure
  *
@@ -1602,6 +1703,9 @@
 	if (e1000_check_reset_block(hw))
 		goto out;
 
+	/* Allow time for h/w to get to quiescent state after reset */
+	msleep(10);
+
 	/* Perform any necessary post-reset workarounds */
 	switch (hw->mac.type) {
 	case e1000_pchlan:
@@ -1630,6 +1734,13 @@
 	/* 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);
+	}
+
 out:
 	return ret_val;
 }
@@ -1646,6 +1757,11 @@
 {
 	s32 ret_val = 0;
 
+	/* Gate automatic PHY configuration by hardware on non-managed 82579 */
+	if ((hw->mac.type == e1000_pch2lan) &&
+	    !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
+		e1000_gate_hw_phy_config_ich8lan(hw, true);
+
 	ret_val = e1000e_phy_hw_reset_generic(hw);
 	if (ret_val)
 		goto out;
@@ -2910,6 +3026,14 @@
 		 * external PHY is reset.
 		 */
 		ctrl |= E1000_CTRL_PHY_RST;
+
+		/*
+		 * Gate automatic PHY configuration by hardware on
+		 * non-managed 82579
+		 */
+		if ((hw->mac.type == e1000_pch2lan) &&
+		    !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
+			e1000_gate_hw_phy_config_ich8lan(hw, true);
 	}
 	ret_val = e1000_acquire_swflag_ich8lan(hw);
 	e_dbg("Issuing a global reset to ich8lan\n");
@@ -3460,13 +3584,20 @@
 void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
 {
 	u32 phy_ctrl;
+	s32 ret_val;
 
 	phy_ctrl = er32(PHY_CTRL);
 	phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE;
 	ew32(PHY_CTRL, phy_ctrl);
 
-	if (hw->mac.type >= e1000_pchlan)
-		e1000_phy_hw_reset_ich8lan(hw);
+	if (hw->mac.type >= e1000_pchlan) {
+		e1000_oem_bits_config_ich8lan(hw, true);
+		ret_val = hw->phy.ops.acquire(hw);
+		if (ret_val)
+			return;
+		e1000_write_smbus_addr(hw);
+		hw->phy.ops.release(hw);
+	}
 }
 
 /**
@@ -3855,7 +3986,7 @@
 				  | FLAG_APME_IN_WUC,
 	.flags2			= FLAG2_HAS_PHY_STATS
 				  | FLAG2_HAS_EEE,
-	.pba			= 18,
+	.pba			= 26,
 	.max_hw_frame_size	= DEFAULT_JUMBO,
 	.get_variants		= e1000_get_variants_ich8lan,
 	.mac_ops		= &ich8_mac_ops,
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 2b8ef44..ec8cf3f 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -475,7 +475,8 @@
 {
 	u16 status = (u16)status_err;
 	u8 errors = (u8)(status_err >> 24);
-	skb->ip_summed = CHECKSUM_NONE;
+
+	skb_checksum_none_assert(skb);
 
 	/* Ignore Checksum bit is set */
 	if (status & E1000_RXD_STAT_IXSM)
@@ -1052,7 +1053,7 @@
 	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);
+	return count < tx_ring->count;
 }
 
 /**
@@ -2289,6 +2290,11 @@
 		goto set_itr_now;
 	}
 
+	if (adapter->flags2 & FLAG2_DISABLE_AIM) {
+		new_itr = 0;
+		goto set_itr_now;
+	}
+
 	adapter->tx_itr = e1000_update_itr(adapter,
 				    adapter->tx_itr,
 				    adapter->total_tx_packets,
@@ -2337,7 +2343,10 @@
 		if (adapter->msix_entries)
 			adapter->rx_ring->set_itr = 1;
 		else
-			ew32(ITR, 1000000000 / (new_itr * 256));
+			if (new_itr)
+				ew32(ITR, 1000000000 / (new_itr * 256));
+			else
+				ew32(ITR, 0);
 	}
 }
 
@@ -2536,7 +2545,7 @@
 	if (!adapter->vlgrp)
 		return;
 
-	for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+	for (vid = 0; vid < VLAN_N_VID; vid++) {
 		if (!vlan_group_get_device(adapter->vlgrp, vid))
 			continue;
 		e1000_vlan_rx_add_vid(adapter->netdev, vid);
@@ -2649,6 +2658,26 @@
 	/* Tx irq moderation */
 	ew32(TADV, adapter->tx_abs_int_delay);
 
+	if (adapter->flags2 & FLAG2_DMA_BURST) {
+		u32 txdctl = er32(TXDCTL(0));
+		txdctl &= ~(E1000_TXDCTL_PTHRESH | E1000_TXDCTL_HTHRESH |
+			    E1000_TXDCTL_WTHRESH);
+		/*
+		 * set up some performance related parameters to encourage the
+		 * hardware to use the bus more efficiently in bursts, depends
+		 * on the tx_int_delay to be enabled,
+		 * wthresh = 5 ==> burst write a cacheline (64 bytes) at a time
+		 * hthresh = 1 ==> prefetch when one or more available
+		 * pthresh = 0x1f ==> prefetch if internal cache 31 or less
+		 * BEWARE: this seems to work but should be considered first if
+		 * there are tx hangs or other tx related bugs
+		 */
+		txdctl |= E1000_TXDCTL_DMA_BURST_ENABLE;
+		ew32(TXDCTL(0), txdctl);
+		/* erratum work around: set txdctl the same for both queues */
+		ew32(TXDCTL(1), txdctl);
+	}
+
 	/* Program the Transmit Control Register */
 	tctl = er32(TCTL);
 	tctl &= ~E1000_TCTL_CT;
@@ -2704,6 +2733,16 @@
 	u32 psrctl = 0;
 	u32 pages = 0;
 
+	/* Workaround Si errata on 82579 - configure jumbo frame flow */
+	if (hw->mac.type == e1000_pch2lan) {
+		s32 ret_val;
+
+		if (adapter->netdev->mtu > ETH_DATA_LEN)
+			ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true);
+		else
+			ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false);
+	}
+
 	/* Program MC offset vector base */
 	rctl = er32(RCTL);
 	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
@@ -2744,16 +2783,6 @@
 		e1e_wphy(hw, 22, phy_data);
 	}
 
-	/* Workaround Si errata on 82579 - configure jumbo frame flow */
-	if (hw->mac.type == e1000_pch2lan) {
-		s32 ret_val;
-
-		if (rctl & E1000_RCTL_LPE)
-			ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true);
-		else
-			ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false);
-	}
-
 	/* Setup buffer sizes */
 	rctl &= ~E1000_RCTL_SZ_4096;
 	rctl |= E1000_RCTL_BSEX;
@@ -2871,12 +2900,35 @@
 	e1e_flush();
 	msleep(10);
 
+	if (adapter->flags2 & FLAG2_DMA_BURST) {
+		/*
+		 * set the writeback threshold (only takes effect if the RDTR
+		 * is set). set GRAN=1 and write back up to 0x4 worth, and
+		 * enable prefetching of 0x20 rx descriptors
+		 * granularity = 01
+		 * wthresh = 04,
+		 * hthresh = 04,
+		 * pthresh = 0x20
+		 */
+		ew32(RXDCTL(0), E1000_RXDCTL_DMA_BURST_ENABLE);
+		ew32(RXDCTL(1), E1000_RXDCTL_DMA_BURST_ENABLE);
+
+		/*
+		 * override the delay timers for enabling bursting, only if
+		 * the value was not set by the user via module options
+		 */
+		if (adapter->rx_int_delay == DEFAULT_RDTR)
+			adapter->rx_int_delay = BURST_RDTR;
+		if (adapter->rx_abs_int_delay == DEFAULT_RADV)
+			adapter->rx_abs_int_delay = BURST_RADV;
+	}
+
 	/* set the Receive Delay Timer Register */
 	ew32(RDTR, adapter->rx_int_delay);
 
 	/* irq moderation */
 	ew32(RADV, adapter->rx_abs_int_delay);
-	if (adapter->itr_setting != 0)
+	if ((adapter->itr_setting != 0) && (adapter->itr != 0))
 		ew32(ITR, 1000000000 / (adapter->itr * 256));
 
 	ctrl_ext = er32(CTRL_EXT);
@@ -2921,11 +2973,13 @@
 	 * packet size is equal or larger than the specified value (in 8 byte
 	 * units), e.g. using jumbo frames when setting to E1000_ERT_2048
 	 */
-	if (adapter->flags & FLAG_HAS_ERT) {
+	if ((adapter->flags & FLAG_HAS_ERT) ||
+	    (adapter->hw.mac.type == e1000_pch2lan)) {
 		if (adapter->netdev->mtu > ETH_DATA_LEN) {
 			u32 rxdctl = er32(RXDCTL(0));
 			ew32(RXDCTL(0), rxdctl | 0x3);
-			ew32(ERT, E1000_ERT_2048 | (1 << 13));
+			if (adapter->flags & FLAG_HAS_ERT)
+				ew32(ERT, E1000_ERT_2048 | (1 << 13));
 			/*
 			 * With jumbo frames and early-receive enabled,
 			 * excessive C-state transition latencies result in
@@ -3188,9 +3242,35 @@
 		fc->low_water = 0x05048;
 		fc->pause_time = 0x0650;
 		fc->refresh_time = 0x0400;
+		if (adapter->netdev->mtu > ETH_DATA_LEN) {
+			pba = 14;
+			ew32(PBA, pba);
+		}
 		break;
 	}
 
+	/*
+	 * Disable Adaptive Interrupt Moderation if 2 full packets cannot
+	 * fit in receive buffer and early-receive not supported.
+	 */
+	if (adapter->itr_setting & 0x3) {
+		if (((adapter->max_frame_size * 2) > (pba << 10)) &&
+		    !(adapter->flags & FLAG_HAS_ERT)) {
+			if (!(adapter->flags2 & FLAG2_DISABLE_AIM)) {
+				dev_info(&adapter->pdev->dev,
+					"Interrupt Throttle Rate turned off\n");
+				adapter->flags2 |= FLAG2_DISABLE_AIM;
+				ew32(ITR, 0);
+			}
+		} else if (adapter->flags2 & FLAG2_DISABLE_AIM) {
+			dev_info(&adapter->pdev->dev,
+				 "Interrupt Throttle Rate turned on\n");
+			adapter->flags2 &= ~FLAG2_DISABLE_AIM;
+			adapter->itr = 20000;
+			ew32(ITR, 1000000000 / (adapter->itr * 256));
+		}
+	}
+
 	/* Allow time for pending master requests to run */
 	mac->ops.reset_hw(hw);
 
@@ -3411,22 +3491,16 @@
 
 	if (adapter->flags & FLAG_MSI_TEST_FAILED) {
 		adapter->int_mode = E1000E_INT_MODE_LEGACY;
-		err = -EIO;
-		e_info("MSI interrupt test failed!\n");
-	}
+		e_info("MSI interrupt test failed, using legacy interrupt.\n");
+	} else
+		e_dbg("MSI interrupt test succeeded!\n");
 
 	free_irq(adapter->pdev->irq, netdev);
 	pci_disable_msi(adapter->pdev);
 
-	if (err == -EIO)
-		goto msi_test_failed;
-
-	/* okay so the test worked, restore settings */
-	e_dbg("MSI interrupt test succeeded!\n");
 msi_test_failed:
 	e1000e_set_interrupt_capability(adapter);
-	e1000_request_irq(adapter);
-	return err;
+	return e1000_request_irq(adapter);
 }
 
 /**
@@ -3458,21 +3532,6 @@
 		pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
 	}
 
-	/* success ! */
-	if (!err)
-		return 0;
-
-	/* EIO means MSI test failed */
-	if (err != -EIO)
-		return err;
-
-	/* back to INTx mode */
-	e_warn("MSI interrupt test failed, using legacy interrupt.\n");
-
-	e1000_free_irq(adapter);
-
-	err = e1000_request_irq(adapter);
-
 	return err;
 }
 
@@ -3530,7 +3589,8 @@
 		e1000_update_mng_vlan(adapter);
 
 	/* DMA latency requirement to workaround early-receive/jumbo issue */
-	if (adapter->flags & FLAG_HAS_ERT)
+	if ((adapter->flags & FLAG_HAS_ERT) ||
+	    (adapter->hw.mac.type == e1000_pch2lan))
 		pm_qos_add_request(&adapter->netdev->pm_qos_req,
 				   PM_QOS_CPU_DMA_LATENCY,
 				   PM_QOS_DEFAULT_VALUE);
@@ -3639,7 +3699,8 @@
 	if (adapter->flags & FLAG_HAS_AMT)
 		e1000_release_hw_control(adapter);
 
-	if (adapter->flags & FLAG_HAS_ERT)
+	if ((adapter->flags & FLAG_HAS_ERT) ||
+	    (adapter->hw.mac.type == e1000_pch2lan))
 		pm_qos_remove_request(&adapter->netdev->pm_qos_req);
 
 	pm_runtime_put_sync(&pdev->dev);
@@ -4255,6 +4316,16 @@
 	/* Force detection of hung controller every watchdog period */
 	adapter->detect_tx_hung = 1;
 
+	/* flush partial descriptors to memory before detecting tx hang */
+	if (adapter->flags2 & FLAG2_DMA_BURST) {
+		ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
+		ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD);
+		/*
+		 * no need to flush the writes because the timeout code does
+		 * an er32 first thing
+		 */
+	}
+
 	/*
 	 * With 82571 controllers, LAA may be overwritten due to controller
 	 * reset from the other port. Set the appropriate LAA in RAR[0]
@@ -4729,7 +4800,7 @@
 	if (e1000_maybe_stop_tx(netdev, count + 2))
 		return NETDEV_TX_BUSY;
 
-	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		tx_flags |= E1000_TX_FLAGS_VLAN;
 		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
 	}
@@ -4833,6 +4904,15 @@
 		return -EINVAL;
 	}
 
+	/* Jumbo frame workaround on 82579 requires CRC be stripped */
+	if ((adapter->hw.mac.type == e1000_pch2lan) &&
+	    !(adapter->flags2 & FLAG2_CRC_STRIPPING) &&
+	    (new_mtu > ETH_DATA_LEN)) {
+		e_err("Jumbo Frames not supported on 82579 when CRC "
+		      "stripping is disabled.\n");
+		return -EINVAL;
+	}
+
 	/* 82573 Errata 17 */
 	if (((adapter->hw.mac.type == e1000_82573) ||
 	     (adapter->hw.mac.type == e1000_82574)) &&
@@ -5703,8 +5783,10 @@
 	netdev->vlan_features |= NETIF_F_HW_CSUM;
 	netdev->vlan_features |= NETIF_F_SG;
 
-	if (pci_using_dac)
+	if (pci_using_dac) {
 		netdev->features |= NETIF_F_HIGHDMA;
+		netdev->vlan_features |= NETIF_F_HIGHDMA;
+	}
 
 	if (e1000e_enable_mng_pass_thru(&adapter->hw))
 		adapter->flags |= FLAG_MNG_PT_ENABLED;
@@ -5745,11 +5827,11 @@
 	}
 
 	init_timer(&adapter->watchdog_timer);
-	adapter->watchdog_timer.function = &e1000_watchdog;
+	adapter->watchdog_timer.function = e1000_watchdog;
 	adapter->watchdog_timer.data = (unsigned long) adapter;
 
 	init_timer(&adapter->phy_info_timer);
-	adapter->phy_info_timer.function = &e1000_update_phy_info;
+	adapter->phy_info_timer.function = e1000_update_phy_info;
 	adapter->phy_info_timer.data = (unsigned long) adapter;
 
 	INIT_WORK(&adapter->reset_task, e1000_reset_task);
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
index 34aeec1..3d36911 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -91,7 +91,6 @@
  * Valid Range: 0-65535
  */
 E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
-#define DEFAULT_RDTR 0
 #define MAX_RXDELAY 0xFFFF
 #define MIN_RXDELAY 0
 
@@ -101,7 +100,6 @@
  * Valid Range: 0-65535
  */
 E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
-#define DEFAULT_RADV 8
 #define MAX_RXABSDELAY 0xFFFF
 #define MIN_RXABSDELAY 0
 
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 8d97f16..7c82631 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -1457,11 +1457,11 @@
 	if (net_debug > 5)
 		printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);
 
-		/* determine how much of the transmit buffer space is available */
-		if (lp->tx_end > lp->tx_start)
+	/* determine how much of the transmit buffer space is available */
+	if (lp->tx_end > lp->tx_start)
 		tx_available = lp->xmt_ram - (lp->tx_end - lp->tx_start);
-		else if (lp->tx_end < lp->tx_start)
-			tx_available = lp->tx_start - lp->tx_end;
+	else if (lp->tx_end < lp->tx_start)
+		tx_available = lp->tx_start - lp->tx_end;
 	else tx_available = lp->xmt_ram;
 
 	if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) {
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 1846623..1321cb6 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -491,6 +491,8 @@
 	u8 full_duplex;
 	u8 autoneg;
 	u8 num_def_qps;
+	wait_queue_head_t swqe_avail_wq;
+	wait_queue_head_t restart_wq;
 };
 
 struct port_res_cfg {
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index a333b42..bb7d306 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -180,7 +180,7 @@
 			 num_portres * EHEA_NUM_PORTRES_FW_HANDLES;
 
 	if (num_fw_handles) {
-		arr = kzalloc(num_fw_handles * sizeof(*arr), GFP_KERNEL);
+		arr = kcalloc(num_fw_handles, sizeof(*arr), GFP_KERNEL);
 		if (!arr)
 			goto out;  /* Keep the existing array */
 	} else
@@ -265,7 +265,7 @@
 		}
 
 	if (num_registrations) {
-		arr = kzalloc(num_registrations * sizeof(*arr), GFP_ATOMIC);
+		arr = kcalloc(num_registrations, sizeof(*arr), GFP_ATOMIC);
 		if (!arr)
 			goto out;  /* Keep the existing array */
 	} else
@@ -533,8 +533,15 @@
 	int length = cqe->num_bytes_transfered - 4;	/*remove CRC */
 
 	skb_put(skb, length);
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
 	skb->protocol = eth_type_trans(skb, dev);
+
+	/* The packet was not an IPV4 packet so a complemented checksum was
+	   calculated. The value is found in the Internet Checksum field. */
+	if (cqe->status & EHEA_CQE_BLIND_CKSUM) {
+		skb->ip_summed = CHECKSUM_COMPLETE;
+		skb->csum = csum_unfold(~cqe->inet_checksum_value);
+	} else
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
 }
 
 static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
@@ -786,6 +793,7 @@
 		struct ehea_port_res *pr = &port->port_res[i];
 		pr->sq_restart_flag = 0;
 	}
+	wake_up(&port->restart_wq);
 }
 
 static void check_sqs(struct ehea_port *port)
@@ -796,6 +804,7 @@
 
 	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
 		struct ehea_port_res *pr = &port->port_res[i];
+		int ret;
 		k = 0;
 		swqe = ehea_get_swqe(pr->qp, &swqe_index);
 		memset(swqe, 0, SWQE_HEADER_SIZE);
@@ -809,17 +818,16 @@
 
 		ehea_post_swqe(pr->qp, swqe);
 
-		while (pr->sq_restart_flag == 0) {
-			msleep(5);
-			if (++k == 100) {
-				ehea_error("HW/SW queues out of sync");
-				ehea_schedule_port_reset(pr->port);
-				return;
-			}
+		ret = wait_event_timeout(port->restart_wq,
+					 pr->sq_restart_flag == 0,
+					 msecs_to_jiffies(100));
+
+		if (!ret) {
+			ehea_error("HW/SW queues out of sync");
+			ehea_schedule_port_reset(pr->port);
+			return;
 		}
 	}
-
-	return;
 }
 
 
@@ -890,6 +898,7 @@
 		pr->queue_stopped = 0;
 	}
 	spin_unlock_irqrestore(&pr->netif_queue, flags);
+	wake_up(&pr->port->swqe_avail_wq);
 
 	return cqe;
 }
@@ -1916,7 +1925,7 @@
 	struct hcp_ehea_port_cb7 *cb7;
 	u64 hret;
 
-	if ((enable && port->promisc) || (!enable && !port->promisc))
+	if (enable == port->promisc)
 		return;
 
 	cb7 = (void *)get_zeroed_page(GFP_ATOMIC);
@@ -2270,7 +2279,7 @@
 	}
 	pr->swqe_id_counter += 1;
 
-	if (port->vgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		swqe->tx_control |= EHEA_SWQE_VLAN_INSERT;
 		swqe->vlan_tag = vlan_tx_tag_get(skb);
 	}
@@ -2654,6 +2663,9 @@
 		netif_start_queue(dev);
 	}
 
+	init_waitqueue_head(&port->swqe_avail_wq);
+	init_waitqueue_head(&port->restart_wq);
+
 	mutex_unlock(&port->port_lock);
 
 	return ret;
@@ -2726,13 +2738,15 @@
 	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
 		struct ehea_port_res *pr = &port->port_res[i];
 		int swqe_max = pr->sq_skba_size - 2 - pr->swqe_ll_count;
-		int k = 0;
-		while (atomic_read(&pr->swqe_avail) < swqe_max) {
-			msleep(5);
-			if (++k == 20) {
-				ehea_error("WARNING: sq not flushed completely");
-				break;
-			}
+		int ret;
+
+		ret = wait_event_timeout(port->swqe_avail_wq,
+			 atomic_read(&pr->swqe_avail) >= swqe_max,
+			 msecs_to_jiffies(100));
+
+		if (!ret) {
+			ehea_error("WARNING: sq not flushed completely");
+			break;
 		}
 	}
 }
@@ -3721,7 +3735,7 @@
 	if (ret)
 		ehea_info("failed registering memory remove notifier");
 
-	ret = crash_shutdown_register(&ehea_crash_handler);
+	ret = crash_shutdown_register(ehea_crash_handler);
 	if (ret)
 		ehea_info("failed registering crash handler");
 
@@ -3746,7 +3760,7 @@
 out2:
 	unregister_memory_notifier(&ehea_mem_nb);
 	unregister_reboot_notifier(&ehea_reboot_nb);
-	crash_shutdown_unregister(&ehea_crash_handler);
+	crash_shutdown_unregister(ehea_crash_handler);
 out:
 	return ret;
 }
@@ -3759,7 +3773,7 @@
 	driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
 	ibmebus_unregister_driver(&ehea_driver);
 	unregister_reboot_notifier(&ehea_reboot_nb);
-	ret = crash_shutdown_unregister(&ehea_crash_handler);
+	ret = crash_shutdown_unregister(ehea_crash_handler);
 	if (ret)
 		ehea_info("failed unregistering crash handler");
 	unregister_memory_notifier(&ehea_mem_nb);
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h
index f608a6c..3810473 100644
--- a/drivers/net/ehea/ehea_qmr.h
+++ b/drivers/net/ehea/ehea_qmr.h
@@ -150,6 +150,7 @@
 #define EHEA_CQE_TYPE_RQ           0x60
 #define EHEA_CQE_STAT_ERR_MASK     0x700F
 #define EHEA_CQE_STAT_FAT_ERR_MASK 0xF
+#define EHEA_CQE_BLIND_CKSUM       0x8000
 #define EHEA_CQE_STAT_ERR_TCP      0x4000
 #define EHEA_CQE_STAT_ERR_IP       0x2000
 #define EHEA_CQE_STAT_ERR_CRC      0x1000
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index f239aa8..c91d364 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -32,7 +32,7 @@
 
 #define DRV_NAME		"enic"
 #define DRV_DESCRIPTION		"Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION		"1.4.1.1"
+#define DRV_VERSION		"1.4.1.6"
 #define DRV_COPYRIGHT		"Copyright 2008-2010 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX		6
@@ -42,25 +42,6 @@
 #define ENIC_CQ_MAX		(ENIC_WQ_MAX + ENIC_RQ_MAX)
 #define ENIC_INTR_MAX		(ENIC_CQ_MAX + 2)
 
-enum enic_cq_index {
-	ENIC_CQ_RQ,
-	ENIC_CQ_WQ,
-};
-
-enum enic_intx_intr_index {
-	ENIC_INTX_WQ_RQ,
-	ENIC_INTX_ERR,
-	ENIC_INTX_NOTIFY,
-};
-
-enum enic_msix_intr_index {
-	ENIC_MSIX_RQ,
-	ENIC_MSIX_WQ,
-	ENIC_MSIX_ERR,
-	ENIC_MSIX_NOTIFY,
-	ENIC_MSIX_MAX,
-};
-
 struct enic_msix_entry {
 	int requested;
 	char devname[IFNAMSIZ];
@@ -91,8 +72,8 @@
 	struct vnic_dev *vdev;
 	struct timer_list notify_timer;
 	struct work_struct reset;
-	struct msix_entry msix_entry[ENIC_MSIX_MAX];
-	struct enic_msix_entry msix[ENIC_MSIX_MAX];
+	struct msix_entry msix_entry[ENIC_INTR_MAX];
+	struct enic_msix_entry msix[ENIC_INTR_MAX];
 	u32 msg_enable;
 	spinlock_t devcmd_lock;
 	u8 mac_addr[ETH_ALEN];
@@ -119,7 +100,7 @@
 	int (*rq_alloc_buf)(struct vnic_rq *rq);
 	u64 rq_truncated_pkts;
 	u64 rq_bad_fcs;
-	struct napi_struct napi;
+	struct napi_struct napi[ENIC_RQ_MAX];
 
 	/* interrupt resource cache line section */
 	____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX];
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 9aab853..a466ef9 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -122,6 +122,51 @@
 	return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN;
 }
 
+static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq)
+{
+	return rq;
+}
+
+static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq)
+{
+	return enic->rq_count + wq;
+}
+
+static inline unsigned int enic_legacy_io_intr(void)
+{
+	return 0;
+}
+
+static inline unsigned int enic_legacy_err_intr(void)
+{
+	return 1;
+}
+
+static inline unsigned int enic_legacy_notify_intr(void)
+{
+	return 2;
+}
+
+static inline unsigned int enic_msix_rq_intr(struct enic *enic, unsigned int rq)
+{
+	return rq;
+}
+
+static inline unsigned int enic_msix_wq_intr(struct enic *enic, unsigned int wq)
+{
+	return enic->rq_count + wq;
+}
+
+static inline unsigned int enic_msix_err_intr(struct enic *enic)
+{
+	return enic->rq_count + enic->wq_count;
+}
+
+static inline unsigned int enic_msix_notify_intr(struct enic *enic)
+{
+	return enic->rq_count + enic->wq_count + 1;
+}
+
 static int enic_get_settings(struct net_device *netdev,
 	struct ethtool_cmd *ecmd)
 {
@@ -306,6 +351,7 @@
 	struct enic *enic = netdev_priv(netdev);
 	u32 tx_coalesce_usecs;
 	u32 rx_coalesce_usecs;
+	unsigned int i, intr;
 
 	tx_coalesce_usecs = min_t(u32,
 		INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
@@ -319,7 +365,8 @@
 		if (tx_coalesce_usecs != rx_coalesce_usecs)
 			return -EINVAL;
 
-		vnic_intr_coalescing_timer_set(&enic->intr[ENIC_INTX_WQ_RQ],
+		intr = enic_legacy_io_intr();
+		vnic_intr_coalescing_timer_set(&enic->intr[intr],
 			INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
 		break;
 	case VNIC_DEV_INTR_MODE_MSI:
@@ -330,10 +377,18 @@
 			INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
 		break;
 	case VNIC_DEV_INTR_MODE_MSIX:
-		vnic_intr_coalescing_timer_set(&enic->intr[ENIC_MSIX_WQ],
-			INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
-		vnic_intr_coalescing_timer_set(&enic->intr[ENIC_MSIX_RQ],
-			INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs));
+		for (i = 0; i < enic->wq_count; i++) {
+			intr = enic_msix_wq_intr(enic, i);
+			vnic_intr_coalescing_timer_set(&enic->intr[intr],
+				INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
+		}
+
+		for (i = 0; i < enic->rq_count; i++) {
+			intr = enic_msix_rq_intr(enic, i);
+			vnic_intr_coalescing_timer_set(&enic->intr[intr],
+				INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs));
+		}
+
 		break;
 	default:
 		break;
@@ -482,34 +537,37 @@
 {
 	struct net_device *netdev = data;
 	struct enic *enic = netdev_priv(netdev);
+	unsigned int io_intr = enic_legacy_io_intr();
+	unsigned int err_intr = enic_legacy_err_intr();
+	unsigned int notify_intr = enic_legacy_notify_intr();
 	u32 pba;
 
-	vnic_intr_mask(&enic->intr[ENIC_INTX_WQ_RQ]);
+	vnic_intr_mask(&enic->intr[io_intr]);
 
 	pba = vnic_intr_legacy_pba(enic->legacy_pba);
 	if (!pba) {
-		vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]);
+		vnic_intr_unmask(&enic->intr[io_intr]);
 		return IRQ_NONE;	/* not our interrupt */
 	}
 
-	if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY)) {
-		vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_NOTIFY]);
+	if (ENIC_TEST_INTR(pba, notify_intr)) {
+		vnic_intr_return_all_credits(&enic->intr[notify_intr]);
 		enic_notify_check(enic);
 	}
 
-	if (ENIC_TEST_INTR(pba, ENIC_INTX_ERR)) {
-		vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_ERR]);
+	if (ENIC_TEST_INTR(pba, err_intr)) {
+		vnic_intr_return_all_credits(&enic->intr[err_intr]);
 		enic_log_q_error(enic);
 		/* schedule recovery from WQ/RQ error */
 		schedule_work(&enic->reset);
 		return IRQ_HANDLED;
 	}
 
-	if (ENIC_TEST_INTR(pba, ENIC_INTX_WQ_RQ)) {
-		if (napi_schedule_prep(&enic->napi))
-			__napi_schedule(&enic->napi);
+	if (ENIC_TEST_INTR(pba, io_intr)) {
+		if (napi_schedule_prep(&enic->napi[0]))
+			__napi_schedule(&enic->napi[0]);
 	} else {
-		vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]);
+		vnic_intr_unmask(&enic->intr[io_intr]);
 	}
 
 	return IRQ_HANDLED;
@@ -535,17 +593,17 @@
 	 * writes).
 	 */
 
-	napi_schedule(&enic->napi);
+	napi_schedule(&enic->napi[0]);
 
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t enic_isr_msix_rq(int irq, void *data)
 {
-	struct enic *enic = data;
+	struct napi_struct *napi = data;
 
 	/* schedule NAPI polling for RQ cleanup */
-	napi_schedule(&enic->napi);
+	napi_schedule(napi);
 
 	return IRQ_HANDLED;
 }
@@ -553,13 +611,15 @@
 static irqreturn_t enic_isr_msix_wq(int irq, void *data)
 {
 	struct enic *enic = data;
+	unsigned int cq = enic_cq_wq(enic, 0);
+	unsigned int intr = enic_msix_wq_intr(enic, 0);
 	unsigned int wq_work_to_do = -1; /* no limit */
 	unsigned int wq_work_done;
 
-	wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ],
+	wq_work_done = vnic_cq_service(&enic->cq[cq],
 		wq_work_to_do, enic_wq_service, NULL);
 
-	vnic_intr_return_credits(&enic->intr[ENIC_MSIX_WQ],
+	vnic_intr_return_credits(&enic->intr[intr],
 		wq_work_done,
 		1 /* unmask intr */,
 		1 /* reset intr timer */);
@@ -570,8 +630,9 @@
 static irqreturn_t enic_isr_msix_err(int irq, void *data)
 {
 	struct enic *enic = data;
+	unsigned int intr = enic_msix_err_intr(enic);
 
-	vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_ERR]);
+	vnic_intr_return_all_credits(&enic->intr[intr]);
 
 	enic_log_q_error(enic);
 
@@ -584,8 +645,9 @@
 static irqreturn_t enic_isr_msix_notify(int irq, void *data)
 {
 	struct enic *enic = data;
+	unsigned int intr = enic_msix_notify_intr(enic);
 
-	vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_NOTIFY]);
+	vnic_intr_return_all_credits(&enic->intr[intr]);
 	enic_notify_check(enic);
 
 	return IRQ_HANDLED;
@@ -743,7 +805,7 @@
 	int vlan_tag_insert = 0;
 	int loopback = 0;
 
-	if (enic->vlan_group && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		/* VLAN tag from trunking driver */
 		vlan_tag_insert = 1;
 		vlan_tag = vlan_tx_tag_get(skb);
@@ -911,7 +973,20 @@
 
 static int enic_set_mac_address(struct net_device *netdev, void *p)
 {
-	return -EOPNOTSUPP;
+	struct sockaddr *saddr = p;
+	char *addr = saddr->sa_data;
+	struct enic *enic = netdev_priv(netdev);
+	int err;
+
+	err = enic_dev_del_station_addr(enic);
+	if (err)
+		return err;
+
+	err = enic_set_mac_addr(netdev, addr);
+	if (err)
+		return err;
+
+	return enic_dev_add_station_addr(enic);
 }
 
 static int enic_dev_packet_filter(struct enic *enic, int directed,
@@ -1407,8 +1482,8 @@
 			(vlan_tci & CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_MASK)) {
 
 			if (netdev->features & NETIF_F_GRO)
-				vlan_gro_receive(&enic->napi, enic->vlan_group,
-					vlan_tci, skb);
+				vlan_gro_receive(&enic->napi[q_number],
+					enic->vlan_group, vlan_tci, skb);
 			else
 				vlan_hwaccel_receive_skb(skb,
 					enic->vlan_group, vlan_tci);
@@ -1416,12 +1491,11 @@
 		} else {
 
 			if (netdev->features & NETIF_F_GRO)
-				napi_gro_receive(&enic->napi, skb);
+				napi_gro_receive(&enic->napi[q_number], skb);
 			else
 				netif_receive_skb(skb);
 
 		}
-
 	} else {
 
 		/* Buffer overflow
@@ -1445,7 +1519,11 @@
 
 static int enic_poll(struct napi_struct *napi, int budget)
 {
-	struct enic *enic = container_of(napi, struct enic, napi);
+	struct net_device *netdev = napi->dev;
+	struct enic *enic = netdev_priv(netdev);
+	unsigned int cq_rq = enic_cq_rq(enic, 0);
+	unsigned int cq_wq = enic_cq_wq(enic, 0);
+	unsigned int intr = enic_legacy_io_intr();
 	unsigned int rq_work_to_do = budget;
 	unsigned int wq_work_to_do = -1; /* no limit */
 	unsigned int  work_done, rq_work_done, wq_work_done;
@@ -1454,10 +1532,10 @@
 	/* Service RQ (first) and WQ
 	 */
 
-	rq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ],
+	rq_work_done = vnic_cq_service(&enic->cq[cq_rq],
 		rq_work_to_do, enic_rq_service, NULL);
 
-	wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ],
+	wq_work_done = vnic_cq_service(&enic->cq[cq_wq],
 		wq_work_to_do, enic_wq_service, NULL);
 
 	/* Accumulate intr event credits for this polling
@@ -1468,7 +1546,7 @@
 	work_done = rq_work_done + wq_work_done;
 
 	if (work_done > 0)
-		vnic_intr_return_credits(&enic->intr[ENIC_INTX_WQ_RQ],
+		vnic_intr_return_credits(&enic->intr[intr],
 			work_done,
 			0 /* don't unmask intr */,
 			0 /* don't reset intr timer */);
@@ -1489,7 +1567,7 @@
 		 */
 
 		napi_complete(napi);
-		vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]);
+		vnic_intr_unmask(&enic->intr[intr]);
 	}
 
 	return rq_work_done;
@@ -1497,7 +1575,11 @@
 
 static int enic_poll_msix(struct napi_struct *napi, int budget)
 {
-	struct enic *enic = container_of(napi, struct enic, napi);
+	struct net_device *netdev = napi->dev;
+	struct enic *enic = netdev_priv(netdev);
+	unsigned int rq = (napi - &enic->napi[0]);
+	unsigned int cq = enic_cq_rq(enic, rq);
+	unsigned int intr = enic_msix_rq_intr(enic, rq);
 	unsigned int work_to_do = budget;
 	unsigned int work_done;
 	int err;
@@ -1505,7 +1587,7 @@
 	/* Service RQ
 	 */
 
-	work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ],
+	work_done = vnic_cq_service(&enic->cq[cq],
 		work_to_do, enic_rq_service, NULL);
 
 	/* Return intr event credits for this polling
@@ -1514,12 +1596,12 @@
 	 */
 
 	if (work_done > 0)
-		vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ],
+		vnic_intr_return_credits(&enic->intr[intr],
 			work_done,
 			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[rq], enic->rq_alloc_buf);
 
 	/* Buffer allocation failed. Stay in polling mode
 	 * so we can try to fill the ring again.
@@ -1535,7 +1617,7 @@
 		 */
 
 		napi_complete(napi);
-		vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]);
+		vnic_intr_unmask(&enic->intr[intr]);
 	}
 
 	return work_done;
@@ -1577,7 +1659,7 @@
 static int enic_request_intr(struct enic *enic)
 {
 	struct net_device *netdev = enic->netdev;
-	unsigned int i;
+	unsigned int i, intr;
 	int err = 0;
 
 	switch (vnic_dev_get_intr_mode(enic->vdev)) {
@@ -1596,27 +1678,38 @@
 
 	case VNIC_DEV_INTR_MODE_MSIX:
 
-		sprintf(enic->msix[ENIC_MSIX_RQ].devname,
-			"%.11s-rx-0", netdev->name);
-		enic->msix[ENIC_MSIX_RQ].isr = enic_isr_msix_rq;
-		enic->msix[ENIC_MSIX_RQ].devid = enic;
+		for (i = 0; i < enic->rq_count; i++) {
+			intr = enic_msix_rq_intr(enic, i);
+			sprintf(enic->msix[intr].devname,
+				"%.11s-rx-%d", netdev->name, i);
+			enic->msix[intr].isr = enic_isr_msix_rq;
+			enic->msix[intr].devid = &enic->napi[i];
+		}
 
-		sprintf(enic->msix[ENIC_MSIX_WQ].devname,
-			"%.11s-tx-0", netdev->name);
-		enic->msix[ENIC_MSIX_WQ].isr = enic_isr_msix_wq;
-		enic->msix[ENIC_MSIX_WQ].devid = enic;
+		for (i = 0; i < enic->wq_count; i++) {
+			intr = enic_msix_wq_intr(enic, i);
+			sprintf(enic->msix[intr].devname,
+				"%.11s-tx-%d", netdev->name, i);
+			enic->msix[intr].isr = enic_isr_msix_wq;
+			enic->msix[intr].devid = enic;
+		}
 
-		sprintf(enic->msix[ENIC_MSIX_ERR].devname,
+		intr = enic_msix_err_intr(enic);
+		sprintf(enic->msix[intr].devname,
 			"%.11s-err", netdev->name);
-		enic->msix[ENIC_MSIX_ERR].isr = enic_isr_msix_err;
-		enic->msix[ENIC_MSIX_ERR].devid = enic;
+		enic->msix[intr].isr = enic_isr_msix_err;
+		enic->msix[intr].devid = enic;
 
-		sprintf(enic->msix[ENIC_MSIX_NOTIFY].devname,
+		intr = enic_msix_notify_intr(enic);
+		sprintf(enic->msix[intr].devname,
 			"%.11s-notify", netdev->name);
-		enic->msix[ENIC_MSIX_NOTIFY].isr = enic_isr_msix_notify;
-		enic->msix[ENIC_MSIX_NOTIFY].devid = enic;
+		enic->msix[intr].isr = enic_isr_msix_notify;
+		enic->msix[intr].devid = enic;
 
-		for (i = 0; i < ARRAY_SIZE(enic->msix); i++) {
+		for (i = 0; i < ARRAY_SIZE(enic->msix); i++)
+			enic->msix[i].requested = 0;
+
+		for (i = 0; i < enic->intr_count; i++) {
 			err = request_irq(enic->msix_entry[i].vector,
 				enic->msix[i].isr, 0,
 				enic->msix[i].devname,
@@ -1662,10 +1755,12 @@
 	spin_lock(&enic->devcmd_lock);
 	switch (vnic_dev_get_intr_mode(enic->vdev)) {
 	case VNIC_DEV_INTR_MODE_INTX:
-		err = vnic_dev_notify_set(enic->vdev, ENIC_INTX_NOTIFY);
+		err = vnic_dev_notify_set(enic->vdev,
+			enic_legacy_notify_intr());
 		break;
 	case VNIC_DEV_INTR_MODE_MSIX:
-		err = vnic_dev_notify_set(enic->vdev, ENIC_MSIX_NOTIFY);
+		err = vnic_dev_notify_set(enic->vdev,
+			enic_msix_notify_intr(enic));
 		break;
 	default:
 		err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */);
@@ -1692,7 +1787,7 @@
 	int err;
 
 	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_enable(enic->vdev);
+	err = vnic_dev_enable_wait(enic->vdev);
 	spin_unlock(&enic->devcmd_lock);
 
 	return err;
@@ -1760,7 +1855,10 @@
 	enic_set_multicast_list(netdev);
 
 	netif_wake_queue(netdev);
-	napi_enable(&enic->napi);
+
+	for (i = 0; i < enic->rq_count; i++)
+		napi_enable(&enic->napi[i]);
+
 	enic_dev_enable(enic);
 
 	for (i = 0; i < enic->intr_count; i++)
@@ -1795,7 +1893,10 @@
 	del_timer_sync(&enic->notify_timer);
 
 	enic_dev_disable(enic);
-	napi_disable(&enic->napi);
+
+	for (i = 0; i < enic->rq_count; i++)
+		napi_disable(&enic->napi[i]);
+
 	netif_carrier_off(netdev);
 	netif_tx_disable(netdev);
 	enic_dev_del_station_addr(enic);
@@ -1855,11 +1956,16 @@
 {
 	struct enic *enic = netdev_priv(netdev);
 	struct vnic_dev *vdev = enic->vdev;
+	unsigned int i, intr;
 
 	switch (vnic_dev_get_intr_mode(vdev)) {
 	case VNIC_DEV_INTR_MODE_MSIX:
-		enic_isr_msix_rq(enic->pdev->irq, enic);
-		enic_isr_msix_wq(enic->pdev->irq, enic);
+		for (i = 0; i < enic->rq_count; i++) {
+			intr = enic_msix_rq_intr(enic, i);
+			enic_isr_msix_rq(enic->msix_entry[intr].vector, enic);
+		}
+		intr = enic_msix_wq_intr(enic, i);
+		enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
 		break;
 	case VNIC_DEV_INTR_MODE_MSI:
 		enic_isr_msi(enic->pdev->irq, enic);
@@ -1934,19 +2040,73 @@
 	return err;
 }
 
-static int enic_set_niccfg(struct enic *enic)
+static int enic_set_rsskey(struct enic *enic)
 {
-	const u8 rss_default_cpu = 0;
-	const u8 rss_hash_type = 0;
-	const u8 rss_hash_bits = 0;
-	const u8 rss_base_cpu = 0;
-	const u8 rss_enable = 0;
+	u64 rss_key_buf_pa;
+	union vnic_rss_key *rss_key_buf_va = NULL;
+	union vnic_rss_key rss_key = {
+		.key[0].b = {85, 67, 83, 97, 119, 101, 115, 111, 109, 101},
+		.key[1].b = {80, 65, 76, 79, 117, 110, 105, 113, 117, 101},
+		.key[2].b = {76, 73, 78, 85, 88, 114, 111, 99, 107, 115},
+		.key[3].b = {69, 78, 73, 67, 105, 115, 99, 111, 111, 108},
+	};
+	int err;
+
+	rss_key_buf_va = pci_alloc_consistent(enic->pdev,
+		sizeof(union vnic_rss_key), &rss_key_buf_pa);
+	if (!rss_key_buf_va)
+		return -ENOMEM;
+
+	memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key));
+
+	spin_lock(&enic->devcmd_lock);
+	err = enic_set_rss_key(enic,
+		rss_key_buf_pa,
+		sizeof(union vnic_rss_key));
+	spin_unlock(&enic->devcmd_lock);
+
+	pci_free_consistent(enic->pdev, sizeof(union vnic_rss_key),
+		rss_key_buf_va, rss_key_buf_pa);
+
+	return err;
+}
+
+static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits)
+{
+	u64 rss_cpu_buf_pa;
+	union vnic_rss_cpu *rss_cpu_buf_va = NULL;
+	unsigned int i;
+	int err;
+
+	rss_cpu_buf_va = pci_alloc_consistent(enic->pdev,
+		sizeof(union vnic_rss_cpu), &rss_cpu_buf_pa);
+	if (!rss_cpu_buf_va)
+		return -ENOMEM;
+
+	for (i = 0; i < (1 << rss_hash_bits); i++)
+		(*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count;
+
+	spin_lock(&enic->devcmd_lock);
+	err = enic_set_rss_cpu(enic,
+		rss_cpu_buf_pa,
+		sizeof(union vnic_rss_cpu));
+	spin_unlock(&enic->devcmd_lock);
+
+	pci_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu),
+		rss_cpu_buf_va, rss_cpu_buf_pa);
+
+	return err;
+}
+
+static int enic_set_niccfg(struct enic *enic, u8 rss_default_cpu,
+	u8 rss_hash_type, u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable)
+{
 	const u8 tso_ipid_split_en = 0;
 	const u8 ig_vlan_strip_en = 1;
 	int err;
 
-	/* Enable VLAN tag stripping.  RSS not enabled (yet).
-	 */
+	/* Enable VLAN tag stripping.
+	*/
 
 	spin_lock(&enic->devcmd_lock);
 	err = enic_set_nic_cfg(enic,
@@ -1959,6 +2119,35 @@
 	return err;
 }
 
+static int enic_set_rss_nic_cfg(struct enic *enic)
+{
+	struct device *dev = enic_get_dev(enic);
+	const u8 rss_default_cpu = 0;
+	const u8 rss_hash_type = NIC_CFG_RSS_HASH_TYPE_IPV4 |
+		NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 |
+		NIC_CFG_RSS_HASH_TYPE_IPV6 |
+		NIC_CFG_RSS_HASH_TYPE_TCP_IPV6;
+	const u8 rss_hash_bits = 7;
+	const u8 rss_base_cpu = 0;
+	u8 rss_enable = ENIC_SETTING(enic, RSS) && (enic->rq_count > 1);
+
+	if (rss_enable) {
+		if (!enic_set_rsskey(enic)) {
+			if (enic_set_rsscpu(enic, rss_hash_bits)) {
+				rss_enable = 0;
+				dev_warn(dev, "RSS disabled, "
+					"Failed to set RSS cpu indirection table.");
+			}
+		} else {
+			rss_enable = 0;
+			dev_warn(dev, "RSS disabled, Failed to set RSS key.\n");
+		}
+	}
+
+	return enic_set_niccfg(enic, rss_default_cpu, rss_hash_type,
+		rss_hash_bits, rss_base_cpu, rss_enable);
+}
+
 static int enic_dev_hang_notify(struct enic *enic)
 {
 	int err;
@@ -1970,7 +2159,7 @@
 	return err;
 }
 
-int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic)
+static int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic)
 {
 	int err;
 
@@ -1996,7 +2185,7 @@
 	enic_dev_hang_reset(enic);
 	enic_reset_multicast_list(enic);
 	enic_init_vnic_resources(enic);
-	enic_set_niccfg(enic);
+	enic_set_rss_nic_cfg(enic);
 	enic_dev_set_ig_vlan_rewrite_mode(enic);
 	enic_open(enic->netdev);
 
@@ -2005,12 +2194,12 @@
 
 static int enic_set_intr_mode(struct enic *enic)
 {
-	unsigned int n = 1;
+	unsigned int n = min_t(unsigned int, enic->rq_count, ENIC_RQ_MAX);
 	unsigned int m = 1;
 	unsigned int i;
 
 	/* Set interrupt mode (INTx, MSI, MSI-X) depending
-	 * system capabilities.
+	 * on system capabilities.
 	 *
 	 * Try MSI-X first
 	 *
@@ -2023,21 +2212,47 @@
 	for (i = 0; i < n + m + 2; i++)
 		enic->msix_entry[i].entry = i;
 
-	if (enic->config.intr_mode < 1 &&
+	/* Use multiple RQs if RSS is enabled
+	 */
+
+	if (ENIC_SETTING(enic, RSS) &&
+	    enic->config.intr_mode < 1 &&
 	    enic->rq_count >= n &&
 	    enic->wq_count >= m &&
 	    enic->cq_count >= n + m &&
-	    enic->intr_count >= n + m + 2 &&
-	    !pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) {
+	    enic->intr_count >= n + m + 2) {
 
-		enic->rq_count = n;
-		enic->wq_count = m;
-		enic->cq_count = n + m;
-		enic->intr_count = n + m + 2;
+		if (!pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) {
 
-		vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSIX);
+			enic->rq_count = n;
+			enic->wq_count = m;
+			enic->cq_count = n + m;
+			enic->intr_count = n + m + 2;
 
-		return 0;
+			vnic_dev_set_intr_mode(enic->vdev,
+				VNIC_DEV_INTR_MODE_MSIX);
+
+			return 0;
+		}
+	}
+
+	if (enic->config.intr_mode < 1 &&
+	    enic->rq_count >= 1 &&
+	    enic->wq_count >= m &&
+	    enic->cq_count >= 1 + m &&
+	    enic->intr_count >= 1 + m + 2) {
+		if (!pci_enable_msix(enic->pdev, enic->msix_entry, 1 + m + 2)) {
+
+			enic->rq_count = 1;
+			enic->wq_count = m;
+			enic->cq_count = 1 + m;
+			enic->intr_count = 1 + m + 2;
+
+			vnic_dev_set_intr_mode(enic->vdev,
+				VNIC_DEV_INTR_MODE_MSIX);
+
+			return 0;
+		}
 	}
 
 	/* Next try MSI
@@ -2145,28 +2360,22 @@
 #endif
 };
 
-void enic_dev_deinit(struct enic *enic)
+static void enic_dev_deinit(struct enic *enic)
 {
-	netif_napi_del(&enic->napi);
+	unsigned int i;
+
+	for (i = 0; i < enic->rq_count; i++)
+		netif_napi_del(&enic->napi[i]);
+
 	enic_free_vnic_resources(enic);
 	enic_clear_intr_mode(enic);
 }
 
-static int enic_dev_stats_clear(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_stats_clear(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-int enic_dev_init(struct enic *enic)
+static int enic_dev_init(struct enic *enic)
 {
 	struct device *dev = enic_get_dev(enic);
 	struct net_device *netdev = enic->netdev;
+	unsigned int i;
 	int err;
 
 	/* Get vNIC configuration
@@ -2205,17 +2414,13 @@
 
 	enic_init_vnic_resources(enic);
 
-	/* Clear LIF stats
-	 */
-	enic_dev_stats_clear(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_niccfg(enic);
+	err = enic_set_rss_nic_cfg(enic);
 	if (err) {
 		dev_err(dev, "Failed to config nic, aborting\n");
 		goto err_out_free_vnic_resources;
@@ -2223,17 +2428,19 @@
 
 	err = enic_dev_set_ig_vlan_rewrite_mode(enic);
 	if (err) {
-		netdev_err(netdev,
+		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, enic_poll, 64);
+		netif_napi_add(netdev, &enic->napi[0], enic_poll, 64);
 		break;
 	case VNIC_DEV_INTR_MODE_MSIX:
-		netif_napi_add(netdev, &enic->napi, enic_poll_msix, 64);
+		for (i = 0; i < enic->rq_count; i++)
+			netif_napi_add(netdev, &enic->napi[i],
+				enic_poll_msix, 64);
 		break;
 	}
 
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c
index 29ede8a..f111a37 100644
--- a/drivers/net/enic/enic_res.c
+++ b/drivers/net/enic/enic_res.c
@@ -94,13 +94,14 @@
 		INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
 		c->intr_timer_usec);
 
-	dev_info(enic_get_dev(enic), "vNIC MAC addr %pM wq/rq %d/%d\n",
-		enic->mac_addr, c->wq_desc_count, c->rq_desc_count);
-	dev_info(enic_get_dev(enic), "vNIC mtu %d csum tx/rx %d/%d "
-		"tso/lro %d/%d intr timer %d usec\n",
-		c->mtu, ENIC_SETTING(enic, TXCSUM),
-		ENIC_SETTING(enic, RXCSUM), ENIC_SETTING(enic, TSO),
-		ENIC_SETTING(enic, LRO), c->intr_timer_usec);
+	dev_info(enic_get_dev(enic),
+		"vNIC MAC addr %pM wq/rq %d/%d mtu %d\n",
+		enic->mac_addr, c->wq_desc_count, c->rq_desc_count, c->mtu);
+	dev_info(enic_get_dev(enic), "vNIC csum tx/rx %d/%d "
+		"tso/lro %d/%d intr timer %d usec rss %d\n",
+		ENIC_SETTING(enic, TXCSUM), ENIC_SETTING(enic, RXCSUM),
+		ENIC_SETTING(enic, TSO), ENIC_SETTING(enic, LRO),
+		c->intr_timer_usec, ENIC_SETTING(enic, RSS));
 
 	return 0;
 }
@@ -181,18 +182,11 @@
 
 void enic_get_res_counts(struct enic *enic)
 {
-	enic->wq_count = min_t(int,
-		vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ),
-		ENIC_WQ_MAX);
-	enic->rq_count = min_t(int,
-		vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ),
-		ENIC_RQ_MAX);
-	enic->cq_count = min_t(int,
-		vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ),
-		ENIC_CQ_MAX);
-	enic->intr_count = min_t(int,
-		vnic_dev_get_res_count(enic->vdev, RES_TYPE_INTR_CTRL),
-		ENIC_INTR_MAX);
+	enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ);
+	enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ);
+	enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ);
+	enic->intr_count = vnic_dev_get_res_count(enic->vdev,
+		RES_TYPE_INTR_CTRL);
 
 	dev_info(enic_get_dev(enic),
 		"vNIC resources avail: wq %d rq %d cq %d intr %d\n",
diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h
index 83bd172..9a103d9 100644
--- a/drivers/net/enic/enic_res.h
+++ b/drivers/net/enic/enic_res.h
@@ -30,7 +30,7 @@
 #define ENIC_MIN_RQ_DESCS		64
 #define ENIC_MAX_RQ_DESCS		4096
 
-#define ENIC_MIN_MTU			576  /* minimum for IPv4 */
+#define ENIC_MIN_MTU			68
 #define ENIC_MAX_MTU			9000
 
 #define ENIC_MULTICAST_PERFECT_FILTERS	32
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 6a5b578..fb35d8b 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -74,6 +74,7 @@
 	struct vnic_dev_bar *bar, unsigned int num_bars)
 {
 	struct vnic_resource_header __iomem *rh;
+	struct mgmt_barmap_hdr __iomem *mrh;
 	struct vnic_resource __iomem *r;
 	u8 type;
 
@@ -85,22 +86,32 @@
 		return -EINVAL;
 	}
 
-	rh = bar->vaddr;
+	rh  = bar->vaddr;
+	mrh = bar->vaddr;
 	if (!rh) {
 		pr_err("vNIC BAR0 res hdr not mem-mapped\n");
 		return -EINVAL;
 	}
 
-	if (ioread32(&rh->magic) != VNIC_RES_MAGIC ||
-	    ioread32(&rh->version) != VNIC_RES_VERSION) {
-		pr_err("vNIC BAR0 res magic/version error "
-			"exp (%lx/%lx) curr (%x/%x)\n",
+	/* Check for mgmt vnic in addition to normal vnic */
+	if ((ioread32(&rh->magic) != VNIC_RES_MAGIC) ||
+		(ioread32(&rh->version) != VNIC_RES_VERSION)) {
+		if ((ioread32(&mrh->magic) != MGMTVNIC_MAGIC) ||
+			(ioread32(&mrh->version) != MGMTVNIC_VERSION)) {
+			pr_err("vNIC BAR0 res magic/version error "
+			"exp (%lx/%lx) or (%lx/%lx), curr (%x/%x)\n",
 			VNIC_RES_MAGIC, VNIC_RES_VERSION,
+			MGMTVNIC_MAGIC, MGMTVNIC_VERSION,
 			ioread32(&rh->magic), ioread32(&rh->version));
-		return -EINVAL;
+			return -EINVAL;
+		}
 	}
 
-	r = (struct vnic_resource __iomem *)(rh + 1);
+	if (ioread32(&mrh->magic) == MGMTVNIC_MAGIC)
+		r = (struct vnic_resource __iomem *)(mrh + 1);
+	else
+		r = (struct vnic_resource __iomem *)(rh + 1);
+
 
 	while ((type = ioread8(&r->type)) != RES_TYPE_EOL) {
 
@@ -175,22 +186,7 @@
 	}
 }
 
-dma_addr_t vnic_dev_get_res_bus_addr(struct vnic_dev *vdev,
-	enum vnic_res_type type, unsigned int index)
-{
-	switch (type) {
-	case RES_TYPE_WQ:
-	case RES_TYPE_RQ:
-	case RES_TYPE_CQ:
-	case RES_TYPE_INTR_CTRL:
-		return vdev->res[type].bus_addr +
-			index * VNIC_RES_STRIDE;
-	default:
-		return vdev->res[type].bus_addr;
-	}
-}
-
-unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
+static unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
 	unsigned int desc_count, unsigned int desc_size)
 {
 	/* The base address of the desc rings must be 512 byte aligned.
@@ -373,18 +369,6 @@
 	return err;
 }
 
-void vnic_dev_cmd_proxy_by_bdf_start(struct vnic_dev *vdev, u16 bdf)
-{
-	vdev->proxy = PROXY_BY_BDF;
-	vdev->proxy_index = bdf;
-}
-
-void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev)
-{
-	vdev->proxy = PROXY_NONE;
-	vdev->proxy_index = 0;
-}
-
 int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
 	u64 *a0, u64 *a1, int wait)
 {
@@ -477,13 +461,6 @@
 	return err;
 }
 
-int vnic_dev_stats_clear(struct vnic_dev *vdev)
-{
-	u64 a0 = 0, a1 = 0;
-	int wait = 1000;
-	return vnic_dev_cmd(vdev, CMD_STATS_CLEAR, &a0, &a1, wait);
-}
-
 int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats)
 {
 	u64 a0, a1;
@@ -510,13 +487,6 @@
 	return vnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait);
 }
 
-int vnic_dev_enable(struct vnic_dev *vdev)
-{
-	u64 a0 = 0, a1 = 0;
-	int wait = 1000;
-	return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
-}
-
 int vnic_dev_enable_wait(struct vnic_dev *vdev)
 {
 	u64 a0 = 0, a1 = 0;
@@ -561,14 +531,14 @@
 	return 0;
 }
 
-int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
+static int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
 {
 	u64 a0 = (u32)arg, a1 = 0;
 	int wait = 1000;
 	return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait);
 }
 
-int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
+static int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
 {
 	u64 a0 = 0, a1 = 0;
 	int wait = 1000;
@@ -669,26 +639,6 @@
 	return err;
 }
 
-int vnic_dev_packet_filter_all(struct vnic_dev *vdev, int directed,
-	int multicast, int broadcast, int promisc, int allmulti)
-{
-	u64 a0, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	a0 = (directed ? CMD_PFILTER_DIRECTED : 0) |
-	     (multicast ? CMD_PFILTER_MULTICAST : 0) |
-	     (broadcast ? CMD_PFILTER_BROADCAST : 0) |
-	     (promisc ? CMD_PFILTER_PROMISCUOUS : 0) |
-	     (allmulti ? CMD_PFILTER_ALL_MULTICAST : 0);
-
-	err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER_ALL, &a0, &a1, wait);
-	if (err)
-		pr_err("Can't set packet filter\n");
-
-	return err;
-}
-
 int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
 {
 	u64 a0 = 0, a1 = 0;
@@ -737,20 +687,7 @@
 	return err;
 }
 
-int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr)
-{
-	u64 a0 = intr, a1 = 0;
-	int wait = 1000;
-	int err;
-
-	err = vnic_dev_cmd(vdev, CMD_IAR, &a0, &a1, wait);
-	if (err)
-		pr_err("Failed to raise INTR[%d], err %d\n", intr, err);
-
-	return err;
-}
-
-int vnic_dev_notify_setcmd(struct vnic_dev *vdev,
+static int vnic_dev_notify_setcmd(struct vnic_dev *vdev,
 	void *notify_addr, dma_addr_t notify_pa, u16 intr)
 {
 	u64 a0, a1;
@@ -789,7 +726,7 @@
 	return vnic_dev_notify_setcmd(vdev, notify_addr, notify_pa, intr);
 }
 
-int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev)
+static int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev)
 {
 	u64 a0, a1;
 	int wait = 1000;
@@ -943,30 +880,6 @@
 	return vdev->notify_copy.mtu;
 }
 
-u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev)
-{
-	if (!vnic_dev_notify_ready(vdev))
-		return 0;
-
-	return vdev->notify_copy.link_down_cnt;
-}
-
-u32 vnic_dev_notify_status(struct vnic_dev *vdev)
-{
-	if (!vnic_dev_notify_ready(vdev))
-		return 0;
-
-	return vdev->notify_copy.status;
-}
-
-u32 vnic_dev_uif(struct vnic_dev *vdev)
-{
-	if (!vnic_dev_notify_ready(vdev))
-		return 0;
-
-	return vdev->notify_copy.uif;
-}
-
 void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
 	enum vnic_dev_intr_mode intr_mode)
 {
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h
index 3a61873..05f9a24 100644
--- a/drivers/net/enic/vnic_dev.h
+++ b/drivers/net/enic/vnic_dev.h
@@ -84,10 +84,6 @@
 	enum vnic_res_type type);
 void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
 	unsigned int index);
-dma_addr_t vnic_dev_get_res_bus_addr(struct vnic_dev *vdev,
-	enum vnic_res_type type, unsigned int index);
-unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
-	unsigned int desc_count, unsigned int desc_size);
 void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring);
 int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring,
 	unsigned int desc_count, unsigned int desc_size);
@@ -95,39 +91,26 @@
 	struct vnic_dev_ring *ring);
 int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
 	u64 *a0, u64 *a1, int wait);
-void vnic_dev_cmd_proxy_by_bdf_start(struct vnic_dev *vdev, u16 bdf);
-void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev);
 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_clear(struct vnic_dev *vdev);
 int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats);
 int vnic_dev_hang_notify(struct vnic_dev *vdev);
 int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
 	int broadcast, int promisc, int allmulti);
-int vnic_dev_packet_filter_all(struct vnic_dev *vdev, int directed,
-	int multicast, int broadcast, int promisc, int allmulti);
 int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr);
 int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr);
 int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
-int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr);
-int vnic_dev_notify_setcmd(struct vnic_dev *vdev,
-	void *notify_addr, dma_addr_t notify_pa, u16 intr);
 int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr);
-int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev);
 int vnic_dev_notify_unset(struct vnic_dev *vdev);
 int vnic_dev_link_status(struct vnic_dev *vdev);
 u32 vnic_dev_port_speed(struct vnic_dev *vdev);
 u32 vnic_dev_msg_lvl(struct vnic_dev *vdev);
 u32 vnic_dev_mtu(struct vnic_dev *vdev);
-u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev);
-u32 vnic_dev_notify_status(struct vnic_dev *vdev);
-u32 vnic_dev_uif(struct vnic_dev *vdev);
 int vnic_dev_close(struct vnic_dev *vdev);
-int vnic_dev_enable(struct vnic_dev *vdev);
 int vnic_dev_enable_wait(struct vnic_dev *vdev);
 int vnic_dev_disable(struct vnic_dev *vdev);
 int vnic_dev_open(struct vnic_dev *vdev, int arg);
@@ -136,8 +119,6 @@
 int vnic_dev_init_done(struct vnic_dev *vdev, int *done, int *err);
 int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len);
 int vnic_dev_deinit(struct vnic_dev *vdev);
-int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg);
-int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done);
 int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg);
 int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done);
 void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
index 2066175..9abb3d5 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -238,6 +238,18 @@
 	 * out: (u32)a0=status of proxied cmd
 	 *      a1-a15=out args of proxied cmd */
 	CMD_PROXY_BY_BDF =	_CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 42),
+
+	/*
+	 * As for BY_BDF except a0 is index of hvnlink subordinate vnic
+	 * or SR-IOV virtual vnic */
+	CMD_PROXY_BY_INDEX =    _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 43),
+
+	/*
+	 * in:  (u64)a0=paddr of buffer to put latest VIC VIF-CONFIG-INFO TLV in
+	 *      (u32)a1=length of buffer in a0
+	 * out: (u64)a0=paddr of buffer with latest VIC VIF-CONFIG-INFO TLV
+	 *      (u32)a1=actual length of latest VIC VIF-CONFIG-INFO TLV */
+	CMD_CONFIG_INFO_GET     = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44),
 };
 
 /* flags for CMD_OPEN */
diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/enic/vnic_enet.h
index 3b32912..e8740e3 100644
--- a/drivers/net/enic/vnic_enet.h
+++ b/drivers/net/enic/vnic_enet.h
@@ -30,7 +30,7 @@
 	u32 wq_desc_count;
 	u32 rq_desc_count;
 	u16 mtu;
-	u16 intr_timer;
+	u16 intr_timer_deprecated;
 	u8 intr_timer_type;
 	u8 intr_mode;
 	char devname[16];
diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/enic/vnic_intr.c
index 52ab61a..3873771 100644
--- a/drivers/net/enic/vnic_intr.c
+++ b/drivers/net/enic/vnic_intr.c
@@ -65,8 +65,3 @@
 {
 	iowrite32(0, &intr->ctrl->int_credits);
 }
-
-void vnic_intr_raise(struct vnic_intr *intr)
-{
-	vnic_dev_raise_intr(intr->vdev, (u16)intr->index);
-}
diff --git a/drivers/net/enic/vnic_resource.h b/drivers/net/enic/vnic_resource.h
index 810287b..e0a73f1 100644
--- a/drivers/net/enic/vnic_resource.h
+++ b/drivers/net/enic/vnic_resource.h
@@ -22,6 +22,11 @@
 
 #define VNIC_RES_MAGIC		0x766E6963L	/* 'vnic' */
 #define VNIC_RES_VERSION	0x00000000L
+#define MGMTVNIC_MAGIC		0x544d474dL	/* 'MGMT' */
+#define MGMTVNIC_VERSION	0x00000000L
+
+/* The MAC address assigned to the CFG vNIC is fixed. */
+#define MGMTVNIC_MAC		{ 0x02, 0x00, 0x54, 0x4d, 0x47, 0x4d }
 
 /* vNIC resource types */
 enum vnic_res_type {
@@ -52,6 +57,14 @@
 	u32 version;
 };
 
+struct mgmt_barmap_hdr {
+	u32 magic;			/* magic number */
+	u32 version;			/* header format version */
+	u16 lif;			/* loopback lif for mgmt frames */
+	u16 pci_slot;			/* installed pci slot */
+	char serial[16];		/* card serial number */
+};
+
 struct vnic_resource {
 	u8 type;
 	u8 bar;
diff --git a/drivers/net/enic/vnic_rq.c b/drivers/net/enic/vnic_rq.c
index dbb2aca..34105e0 100644
--- a/drivers/net/enic/vnic_rq.c
+++ b/drivers/net/enic/vnic_rq.c
@@ -77,8 +77,10 @@
 	vnic_dev_free_desc_ring(vdev, &rq->ring);
 
 	for (i = 0; i < VNIC_RQ_BUF_BLKS_MAX; i++) {
-		kfree(rq->bufs[i]);
-		rq->bufs[i] = NULL;
+		if (rq->bufs[i]) {
+			kfree(rq->bufs[i]);
+			rq->bufs[i] = NULL;
+		}
 	}
 
 	rq->ctrl = NULL;
@@ -113,7 +115,7 @@
 	return 0;
 }
 
-void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
+static void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
 	unsigned int fetch_index, unsigned int posted_index,
 	unsigned int error_interrupt_enable,
 	unsigned int error_interrupt_offset)
diff --git a/drivers/net/enic/vnic_rq.h b/drivers/net/enic/vnic_rq.h
index 2dc48f9..37f08de 100644
--- a/drivers/net/enic/vnic_rq.h
+++ b/drivers/net/enic/vnic_rq.h
@@ -143,7 +143,7 @@
 
 static inline int vnic_rq_posting_soon(struct vnic_rq *rq)
 {
-	return ((rq->to_use->index & VNIC_RQ_RETURN_RATE) == 0);
+	return (rq->to_use->index & VNIC_RQ_RETURN_RATE) == 0;
 }
 
 static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count)
@@ -202,10 +202,6 @@
 void vnic_rq_free(struct vnic_rq *rq);
 int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
 	unsigned int desc_count, unsigned int desc_size);
-void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
-	unsigned int fetch_index, unsigned int posted_index,
-	unsigned int error_interrupt_enable,
-	unsigned int error_interrupt_offset);
 void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
 	unsigned int error_interrupt_enable,
 	unsigned int error_interrupt_offset);
diff --git a/drivers/net/enic/vnic_rss.h b/drivers/net/enic/vnic_rss.h
index f62d187..fa421ba 100644
--- a/drivers/net/enic/vnic_rss.h
+++ b/drivers/net/enic/vnic_rss.h
@@ -37,9 +37,4 @@
 	u64 raw[32];
 };
 
-void vnic_set_rss_key(union vnic_rss_key *rss_key, u8 *key);
-void vnic_set_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu);
-void vnic_get_rss_key(union vnic_rss_key *rss_key, u8 *key);
-void vnic_get_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu);
-
 #endif /* _VNIC_RSS_H_ */
diff --git a/drivers/net/enic/vnic_vic.c b/drivers/net/enic/vnic_vic.c
index 197c9d2..4725b79 100644
--- a/drivers/net/enic/vnic_vic.c
+++ b/drivers/net/enic/vnic_vic.c
@@ -54,8 +54,8 @@
 	if (!vp || !value)
 		return -EINVAL;
 
-	if (ntohl(vp->length) + sizeof(*tlv) + length >
-		VIC_PROVINFO_MAX_TLV_DATA)
+	if (ntohl(vp->length) + offsetof(struct vic_provinfo_tlv, value) +
+		length > VIC_PROVINFO_MAX_TLV_DATA)
 		return -ENOMEM;
 
 	tlv = (struct vic_provinfo_tlv *)((u8 *)vp->tlv +
@@ -66,7 +66,8 @@
 	memcpy(tlv->value, value, length);
 
 	vp->num_tlvs = htonl(ntohl(vp->num_tlvs) + 1);
-	vp->length = htonl(ntohl(vp->length) + sizeof(*tlv) + length);
+	vp->length = htonl(ntohl(vp->length) +
+		offsetof(struct vic_provinfo_tlv, value) + length);
 
 	return 0;
 }
diff --git a/drivers/net/enic/vnic_wq.c b/drivers/net/enic/vnic_wq.c
index 122e33b..df61bd9 100644
--- a/drivers/net/enic/vnic_wq.c
+++ b/drivers/net/enic/vnic_wq.c
@@ -77,8 +77,10 @@
 	vnic_dev_free_desc_ring(vdev, &wq->ring);
 
 	for (i = 0; i < VNIC_WQ_BUF_BLKS_MAX; i++) {
-		kfree(wq->bufs[i]);
-		wq->bufs[i] = NULL;
+		if (wq->bufs[i]) {
+			kfree(wq->bufs[i]);
+			wq->bufs[i] = NULL;
+		}
 	}
 
 	wq->ctrl = NULL;
@@ -113,7 +115,7 @@
 	return 0;
 }
 
-void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
+static void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
 	unsigned int fetch_index, unsigned int posted_index,
 	unsigned int error_interrupt_enable,
 	unsigned int error_interrupt_offset)
diff --git a/drivers/net/enic/vnic_wq.h b/drivers/net/enic/vnic_wq.h
index 94ac462..7dd937a 100644
--- a/drivers/net/enic/vnic_wq.h
+++ b/drivers/net/enic/vnic_wq.h
@@ -153,10 +153,6 @@
 void vnic_wq_free(struct vnic_wq *wq);
 int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index,
 	unsigned int desc_count, unsigned int desc_size);
-void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
-	unsigned int fetch_index, unsigned int posted_index,
-	unsigned int error_interrupt_enable,
-	unsigned int error_interrupt_offset);
 void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
 	unsigned int error_interrupt_enable,
 	unsigned int error_interrupt_offset);
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 57c8ac0..32543a3 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -758,7 +758,7 @@
 	init_timer(&ep->timer);
 	ep->timer.expires = jiffies + 3*HZ;
 	ep->timer.data = (unsigned long)dev;
-	ep->timer.function = &epic_timer;				/* timer handler */
+	ep->timer.function = epic_timer;				/* timer handler */
 	add_timer(&ep->timer);
 
 	return 0;
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index 10e39f2..fb717be 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -637,7 +637,9 @@
 
 	/* Set interface port type */
 	if(boot) {
-		char *porttype[] = {"BNC", "DIX", "TP", "AUTO", "FROM_EPROM" };
+		static const char * const porttype[] = {
+			"BNC", "DIX", "TP", "AUTO", "FROM_EPROM"
+		};
 
 		switch(dev->if_port)
 		{
@@ -794,7 +796,7 @@
 
 			if(eth16i_debug > 1)
 				printk(KERN_DEBUG "RECEIVE_PACKET\n");
-			return(0); /* Found receive packet */
+			return 0; /* Found receive packet */
 		}
 	}
 
@@ -803,7 +805,7 @@
 		printk(KERN_DEBUG "RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
 	}
 
-	return(0); /* Return success */
+	return 0; /* Return success */
 }
 
 #if 0
@@ -839,7 +841,7 @@
 
 	if( ioaddr < 0x1000) {
 		cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
-		return( eth16i_irqmap[ ((cbyte & 0xC0) >> 6) ] );
+		return eth16i_irqmap[((cbyte & 0xC0) >> 6)];
 	} else {  /* Oh..the card is EISA so method getting IRQ different */
 		unsigned short index = 0;
 		cbyte = inb(ioaddr + EISA_IRQ_REG);
@@ -847,7 +849,7 @@
 			cbyte = cbyte >> 1;
 			index++;
 		}
-		return( eth32i_irqmap[ index ] );
+		return eth32i_irqmap[index];
 	}
 }
 
@@ -907,7 +909,7 @@
 	data = eth16i_read_eeprom_word(ioaddr);
 	outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
 
-	return(data);
+	return data;
 }
 
 static int eth16i_read_eeprom_word(int ioaddr)
@@ -926,7 +928,7 @@
 		eeprom_slow_io();
 	}
 
-	return(data);
+	return data;
 }
 
 static void eth16i_eeprom_cmd(int ioaddr, unsigned char command)
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 6d653c4..c5a2fe0 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -806,11 +806,6 @@
 		ethoc_interrupt(dev->irq, dev);
 }
 
-static struct net_device_stats *ethoc_stats(struct net_device *dev)
-{
-	return &dev->stats;
-}
-
 static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ethoc *priv = netdev_priv(dev);
@@ -863,7 +858,6 @@
 	.ndo_set_multicast_list = ethoc_set_multicast_list,
 	.ndo_change_mtu = ethoc_change_mtu,
 	.ndo_tx_timeout = ethoc_tx_timeout,
-	.ndo_get_stats = ethoc_stats,
 	.ndo_start_xmit = ethoc_start_xmit,
 };
 
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index d7e8f6b..dd54abe 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -915,14 +915,14 @@
 	init_timer(&np->timer);
 	np->timer.expires = RUN_AT(3 * HZ);
 	np->timer.data = (unsigned long) dev;
-	np->timer.function = &netdev_timer;
+	np->timer.function = netdev_timer;
 
 	/* timer handler */
 	add_timer(&np->timer);
 
 	init_timer(&np->reset_timer);
 	np->reset_timer.data = (unsigned long) dev;
-	np->reset_timer.function = &reset_timer;
+	np->reset_timer.function = reset_timer;
 	np->reset_timer_armed = 0;
 
 	return 0;
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 768b840..cce32d4 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -678,24 +678,37 @@
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	struct phy_device *phy_dev = NULL;
-	int ret;
+	char mdio_bus_id[MII_BUS_ID_SIZE];
+	char phy_name[MII_BUS_ID_SIZE + 3];
+	int phy_id;
 
 	fep->phy_dev = NULL;
 
-	/* find the first phy */
-	phy_dev = phy_find_first(fep->mii_bus);
-	if (!phy_dev) {
-		printk(KERN_ERR "%s: no PHY found\n", dev->name);
-		return -ENODEV;
+	/* check for attached phy */
+	for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
+		if ((fep->mii_bus->phy_mask & (1 << phy_id)))
+			continue;
+		if (fep->mii_bus->phy_map[phy_id] == NULL)
+			continue;
+		if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
+			continue;
+		strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
+		break;
 	}
 
-	/* attach the mac to the phy */
-	ret = phy_connect_direct(dev, phy_dev,
-			     &fec_enet_adjust_link, 0,
-			     PHY_INTERFACE_MODE_MII);
-	if (ret) {
-		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
-		return ret;
+	if (phy_id >= PHY_MAX_ADDR) {
+		printk(KERN_INFO "%s: no PHY, assuming direct connection "
+			"to switch\n", dev->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_INTERFACE_MODE_MII);
+	if (IS_ERR(phy_dev)) {
+		printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
+		return PTR_ERR(phy_dev);
 	}
 
 	/* mask with MAC supported features */
@@ -738,7 +751,7 @@
 	fep->mii_bus->read = fec_enet_mdio_read;
 	fep->mii_bus->write = fec_enet_mdio_write;
 	fep->mii_bus->reset = fec_enet_mdio_reset;
-	snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+	snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id + 1);
 	fep->mii_bus->priv = fep;
 	fep->mii_bus->parent = &pdev->dev;
 
@@ -1311,6 +1324,9 @@
 	if (ret)
 		goto failed_mii_init;
 
+	/* Carrier starts down, phylib will bring it up */
+	netif_carrier_off(ndev);
+
 	ret = register_netdev(ndev);
 	if (ret)
 		goto failed_register;
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index e3e10b4..e9f5d03 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -771,11 +771,6 @@
 
 
 /* ethtool interface */
-static void mpc52xx_fec_get_drvinfo(struct net_device *dev,
-		struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, DRIVER_NAME);
-}
 
 static int mpc52xx_fec_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
@@ -810,7 +805,6 @@
 }
 
 static const struct ethtool_ops mpc52xx_fec_ethtool_ops = {
-	.get_drvinfo = mpc52xx_fec_get_drvinfo,
 	.get_settings = mpc52xx_fec_get_settings,
 	.set_settings = mpc52xx_fec_set_settings,
 	.get_link = ethtool_op_get_link,
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 4da05b1..0fa1776 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -2321,14 +2321,11 @@
 			 NV_TX2_CHECKSUM_L3 | NV_TX2_CHECKSUM_L4 : 0;
 
 	/* vlan tag */
-	if (likely(!np->vlangrp)) {
+	if (vlan_tx_tag_present(skb))
+		start_tx->txvlan = cpu_to_le32(NV_TX3_VLAN_TAG_PRESENT |
+					vlan_tx_tag_get(skb));
+	else
 		start_tx->txvlan = 0;
-	} else {
-		if (vlan_tx_tag_present(skb))
-			start_tx->txvlan = cpu_to_le32(NV_TX3_VLAN_TAG_PRESENT | vlan_tx_tag_get(skb));
-		else
-			start_tx->txvlan = 0;
-	}
 
 	spin_lock_irqsave(&np->lock, flags);
 
@@ -4620,7 +4617,7 @@
 static u32 nv_get_rx_csum(struct net_device *dev)
 {
 	struct fe_priv *np = netdev_priv(dev);
-	return (np->rx_csum) != 0;
+	return np->rx_csum != 0;
 }
 
 static int nv_set_rx_csum(struct net_device *dev, u32 data)
@@ -5440,13 +5437,13 @@
 
 	init_timer(&np->oom_kick);
 	np->oom_kick.data = (unsigned long) dev;
-	np->oom_kick.function = &nv_do_rx_refill;	/* timer handler */
+	np->oom_kick.function = nv_do_rx_refill;	/* timer handler */
 	init_timer(&np->nic_poll);
 	np->nic_poll.data = (unsigned long) dev;
-	np->nic_poll.function = &nv_do_nic_poll;	/* timer handler */
+	np->nic_poll.function = nv_do_nic_poll;	/* timer handler */
 	init_timer(&np->stats_poll);
 	np->stats_poll.data = (unsigned long) dev;
-	np->stats_poll.function = &nv_do_stats_poll;	/* timer handler */
+	np->stats_poll.function = nv_do_stats_poll;	/* timer handler */
 
 	err = pci_enable_device(pci_dev);
 	if (err)
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index d6e3111..d684f18 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -1036,7 +1036,7 @@
 	ndev = alloc_etherdev(privsize);
 	if (!ndev) {
 		ret = -ENOMEM;
-		goto out_free_fpi;
+		goto out_put;
 	}
 
 	SET_NETDEV_DEV(ndev, &ofdev->dev);
@@ -1099,6 +1099,7 @@
 out_free_dev:
 	free_netdev(ndev);
 	dev_set_drvdata(&ofdev->dev, NULL);
+out_put:
 	of_node_put(fpi->phy_node);
 out_free_fpi:
 	kfree(fpi);
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c
index d4bf91a..8d3a2cc 100644
--- a/drivers/net/fsl_pq_mdio.c
+++ b/drivers/net/fsl_pq_mdio.c
@@ -125,7 +125,7 @@
 	struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus);
 
 	/* Write to the local MII regs */
-	return(fsl_pq_local_mdio_write(regs, mii_id, regnum, value));
+	return fsl_pq_local_mdio_write(regs, mii_id, regnum, value);
 }
 
 /*
@@ -137,7 +137,7 @@
 	struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus);
 
 	/* Read the local MII regs */
-	return(fsl_pq_local_mdio_read(regs, mii_id, regnum));
+	return fsl_pq_local_mdio_read(regs, mii_id, regnum);
 }
 
 /* Reset the MIIM registers, and wait for the bus to free */
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 4f7c3f3..4c4cc80 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -654,9 +654,8 @@
 	priv->node = ofdev->dev.of_node;
 	priv->ndev = dev;
 
-	dev->num_tx_queues = num_tx_qs;
-	dev->real_num_tx_queues = num_tx_qs;
 	priv->num_tx_queues = num_tx_qs;
+	netif_set_real_num_rx_queues(dev, num_rx_qs);
 	priv->num_rx_queues = num_rx_qs;
 	priv->num_grps = 0x0;
 
@@ -1859,7 +1858,7 @@
 				printk(KERN_ERR "%s: Can't get IRQ %d\n",
 					dev->name, grp->interruptError);
 
-				goto err_irq_fail;
+			goto err_irq_fail;
 		}
 
 		if ((err = request_irq(grp->interruptTransmit, gfar_transmit,
@@ -2048,7 +2047,6 @@
 	u32 bufaddr;
 	unsigned long flags;
 	unsigned int nr_frags, nr_txbds, length;
-	union skb_shared_tx *shtx;
 
 	/*
 	 * TOE=1 frames larger than 2500 bytes may see excess delays
@@ -2069,15 +2067,15 @@
 	txq = netdev_get_tx_queue(dev, rq);
 	base = tx_queue->tx_bd_base;
 	regs = tx_queue->grp->regs;
-	shtx = skb_tx(skb);
 
 	/* check if time stamp should be generated */
-	if (unlikely(shtx->hardware && priv->hwts_tx_en))
+	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+		     priv->hwts_tx_en))
 		do_tstamp = 1;
 
 	/* make space for additional header when fcb is needed */
 	if (((skb->ip_summed == CHECKSUM_PARTIAL) ||
-			(priv->vlgrp && vlan_tx_tag_present(skb)) ||
+			vlan_tx_tag_present(skb) ||
 			unlikely(do_tstamp)) &&
 			(skb_headroom(skb) < GMAC_FCB_LEN)) {
 		struct sk_buff *skb_new;
@@ -2163,7 +2161,7 @@
 		gfar_tx_checksum(skb, fcb);
 	}
 
-	if (priv->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		if (unlikely(NULL == fcb)) {
 			fcb = gfar_add_fcb(skb);
 			lstatus |= BD_LFLAG(TXBD_TOE);
@@ -2174,7 +2172,7 @@
 
 	/* Setup tx hardware time stamping if requested */
 	if (unlikely(do_tstamp)) {
-		shtx->in_progress = 1;
+		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 		if (fcb == NULL)
 			fcb = gfar_add_fcb(skb);
 		fcb->ptp = 1;
@@ -2446,7 +2444,6 @@
 	int howmany = 0;
 	u32 lstatus;
 	size_t buflen;
-	union skb_shared_tx *shtx;
 
 	rx_queue = priv->rx_queue[tx_queue->qindex];
 	bdp = tx_queue->dirty_tx;
@@ -2461,8 +2458,7 @@
 		 * When time stamping, one additional TxBD must be freed.
 		 * Also, we need to dma_unmap_single() the TxPAL.
 		 */
-		shtx = skb_tx(skb);
-		if (unlikely(shtx->in_progress))
+		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
 			nr_txbds = frags + 2;
 		else
 			nr_txbds = frags + 1;
@@ -2476,7 +2472,7 @@
 				(lstatus & BD_LENGTH_MASK))
 			break;
 
-		if (unlikely(shtx->in_progress)) {
+		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
 			next = next_txbd(bdp, base, tx_ring_size);
 			buflen = next->length + GMAC_FCB_LEN;
 		} else
@@ -2485,7 +2481,7 @@
 		dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
 				buflen, DMA_TO_DEVICE);
 
-		if (unlikely(shtx->in_progress)) {
+		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
 			struct skb_shared_hwtstamps shhwtstamps;
 			u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7);
 			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
@@ -2657,7 +2653,7 @@
 	if ((fcb->flags & RXFCB_CSUM_MASK) == (RXFCB_CIP | RXFCB_CTU))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	else
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 }
 
 
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 9bda023..5c566eb 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -254,7 +254,7 @@
 
 	/* Make sure we return a number greater than 0
 	 * if usecs > 0 */
-	return ((usecs * 1000 + count - 1) / count);
+	return (usecs * 1000 + count - 1) / count;
 }
 
 /* Convert ethernet clock ticks to microseconds */
@@ -278,7 +278,7 @@
 
 	/* Make sure we return a number greater than 0 */
 	/* if ticks is > 0 */
-	return ((ticks * count) / 1000);
+	return (ticks * count) / 1000;
 }
 
 /* Get the coalescing parameters, and put them in the cvals
@@ -538,7 +538,7 @@
 
 		unlock_tx_qs(priv);
 		unlock_rx_qs(priv);
-		local_irq_save(flags);
+		local_irq_restore(flags);
 
 		for (i = 0; i < priv->num_rx_queues; i++)
 			gfar_clean_rx_ring(priv->rx_queue[i],
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index f15c64f..27d6960 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -893,7 +893,7 @@
 				if (greth->flags & GRETH_FLAG_RX_CSUM && hw_checksummed(status))
 					skb->ip_summed = CHECKSUM_UNNECESSARY;
 				else
-					skb->ip_summed = CHECKSUM_NONE;
+					skb_checksum_none_assert(skb);
 
 				skb->protocol = eth_type_trans(skb, dev);
 				dev->stats.rx_packets++;
@@ -1547,10 +1547,10 @@
 	dev->netdev_ops = &greth_netdev_ops;
 	dev->ethtool_ops = &greth_ethtool_ops;
 
-	if (register_netdev(dev)) {
+	err = register_netdev(dev);
+	if (err) {
 		if (netif_msg_probe(greth))
 			dev_err(greth->dev, "netdevice registration failed.\n");
-		err = -ENOMEM;
 		goto error5;
 	}
 
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 49aac70..9a64858 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -1004,7 +1004,7 @@
 	init_timer(&hmp->timer);
 	hmp->timer.expires = RUN_AT((24*HZ)/10);			/* 2.4 sec. */
 	hmp->timer.data = (unsigned long)dev;
-	hmp->timer.function = &hamachi_timer;				/* timer handler */
+	hmp->timer.function = hamachi_timer;				/* timer handler */
 	add_timer(&hmp->timer);
 
 	return 0;
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 4b52c76..3e5d0b6 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -608,7 +608,7 @@
 
 	spin_lock_init(&sp->lock);
 	atomic_set(&sp->refcnt, 1);
-	init_MUTEX_LOCKED(&sp->dead_sem);
+	sema_init(&sp->dead_sem, 0);
 
 	/* !!! length of the buffers. MTU is IP MTU, not PACLEN!  */
 
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 14f01d1..ac1d323 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -168,7 +168,7 @@
 
 static inline int dev_is_ethdev(struct net_device *dev)
 {
-	return (dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5));
+	return dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5);
 }
 
 /* ------------------------------------------------------------------------ */
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index b8bdf9d..5b37579 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -110,7 +110,7 @@
 	for (; cnt > 0; cnt--)
 		crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff];
 	crc ^= 0xffff;
-	return (crc & 0xffff);
+	return crc & 0xffff;
 }
 #endif
 
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 66e88bd..4c62839 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -747,7 +747,7 @@
 
 	spin_lock_init(&ax->buflock);
 	atomic_set(&ax->refcnt, 1);
-	init_MUTEX_LOCKED(&ax->dead_sem);
+	sema_init(&ax->dead_sem, 0);
 
 	ax->tty = tty;
 	tty->disc_data = ax;
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 9f64c86..3365581 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1069,7 +1069,8 @@
 		case KISS_DUPLEX_LINK:
 			scc->stat.tx_state = TXS_IDLE2;
 			if (scc->kiss.idletime != TIMER_OFF)
-			scc_start_tx_timer(scc, t_idle, scc->kiss.idletime*100);
+				scc_start_tx_timer(scc, t_idle,
+						   scc->kiss.idletime*100);
 			break;
 		case KISS_DUPLEX_OPTIMA:
 			scc_notify(scc, HWEV_ALL_SENT);
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 86ececd..d15d2f2 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -204,10 +204,10 @@
 	ei_status.rx_start_page = HP_START_PG + TX_PAGES;
 	ei_status.stop_page = wordmode ? HP_16BSTOP_PG : HP_8BSTOP_PG;
 
-	ei_status.reset_8390 = &hp_reset_8390;
-	ei_status.get_8390_hdr = &hp_get_8390_hdr;
-	ei_status.block_input = &hp_block_input;
-	ei_status.block_output = &hp_block_output;
+	ei_status.reset_8390 = hp_reset_8390;
+	ei_status.get_8390_hdr = hp_get_8390_hdr;
+	ei_status.block_input = hp_block_input;
+	ei_status.block_output = hp_block_output;
 	hp_init_card(dev);
 
 	retval = register_netdev(dev);
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 095b17e..8e2c460 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -1312,7 +1312,7 @@
 		for (p = (ringptr->pdl); p < (ringptr->pdl + 5); p++)
 			printk("hp100: %s: Adr 0x%.8x = 0x%.8x\n", dev->name, (u_int) p, (u_int) * p);
 #endif
-		return (1);
+		return 1;
 	}
 	/* else: */
 	/* alloc_skb failed (no memory) -> still can receive the header
@@ -1325,7 +1325,7 @@
 
 	ringptr->pdl[0] = 0x00010000;	/* PDH: Count=1 Fragment */
 
-	return (0);
+	return 0;
 }
 
 /*
@@ -2752,7 +2752,7 @@
 		hp100_outw(HP100_MISC_ERROR, IRQ_STATUS);
 
 		if (val & HP100_LINK_UP_ST)
-			return (0);	/* login was ok */
+			return 0;	/* login was ok */
 		else {
 			printk("hp100: %s: Training failed.\n", dev->name);
 			hp100_down_vg_link(dev);
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index 07d8e5b..c5ef62c 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -155,10 +155,10 @@
 
     ei_status.rx_start_page = start_page + TX_PAGES;
 
-    ei_status.reset_8390 = &hydra_reset_8390;
-    ei_status.block_input = &hydra_block_input;
-    ei_status.block_output = &hydra_block_output;
-    ei_status.get_8390_hdr = &hydra_get_8390_hdr;
+    ei_status.reset_8390 = hydra_reset_8390;
+    ei_status.block_input = hydra_block_input;
+    ei_status.block_output = hydra_block_output;
+    ei_status.get_8390_hdr = hydra_get_8390_hdr;
     ei_status.reg_offset = hydra_offsets;
 
     dev->netdev_ops = &hydra_netdev_ops;
@@ -173,9 +173,8 @@
 
     zorro_set_drvdata(z, dev);
 
-    printk(KERN_INFO "%s: Hydra at 0x%08llx, address "
-	   "%pM (hydra.c " HYDRA_VERSION ")\n",
-	   dev->name, (unsigned long long)z->resource.start, dev->dev_addr);
+    pr_info("%s: Hydra at %pR, address %pM (hydra.c " HYDRA_VERSION ")\n",
+	    dev->name, &z->resource, dev->dev_addr);
 
     return 0;
 }
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 3506fd6..385dc32 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -2095,11 +2095,11 @@
 	if (emac_has_feature(dev, EMAC_FTR_EMAC4)) {
 		hdr->version = EMAC4_ETHTOOL_REGS_VER;
 		memcpy_fromio(hdr + 1, dev->emacp, EMAC4_ETHTOOL_REGS_SIZE(dev));
-		return ((void *)(hdr + 1) + EMAC4_ETHTOOL_REGS_SIZE(dev));
+		return (void *)(hdr + 1) + EMAC4_ETHTOOL_REGS_SIZE(dev);
 	} else {
 		hdr->version = EMAC_ETHTOOL_REGS_VER;
 		memcpy_fromio(hdr + 1, dev->emacp, EMAC_ETHTOOL_REGS_SIZE(dev));
-		return ((void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE(dev));
+		return (void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE(dev);
 	}
 }
 
@@ -2293,7 +2293,7 @@
 		if (deps[i].drvdata != NULL)
 			there++;
 	}
-	return (there == EMAC_DEP_COUNT);
+	return there == EMAC_DEP_COUNT;
 }
 
 static void emac_put_deps(struct emac_instance *dev)
@@ -2928,7 +2928,7 @@
 	if (dev->emac_irq != NO_IRQ)
 		irq_dispose_mapping(dev->emac_irq);
  err_free:
-	kfree(ndev);
+	free_netdev(ndev);
  err_gone:
 	/* if we were on the bootlist, remove us as we won't show up and
 	 * wake up all waiters to notify them in case they were waiting
@@ -2971,7 +2971,7 @@
 	if (dev->emac_irq != NO_IRQ)
 		irq_dispose_mapping(dev->emac_irq);
 
-	kfree(dev->ndev);
+	free_netdev(dev->ndev);
 
 	return 0;
 }
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h
index 9e37e3d..4fec084 100644
--- a/drivers/net/ibm_newemac/core.h
+++ b/drivers/net/ibm_newemac/core.h
@@ -410,7 +410,7 @@
 	else
 		offset = offsetof(struct emac_regs, u0.emac4.iaht1);
 
-	return ((u32 *)((ptrdiff_t)p + offset));
+	return (u32 *)((ptrdiff_t)p + offset);
 }
 
 static inline u32 *emac_gaht_base(struct emac_instance *dev)
@@ -418,7 +418,7 @@
 	/* GAHT registers always come after an identical number of
 	 * IAHT registers.
 	 */
-	return (emac_xaht_base(dev) + EMAC_XAHT_REGS(dev));
+	return emac_xaht_base(dev) + EMAC_XAHT_REGS(dev);
 }
 
 static inline u32 *emac_iaht_base(struct emac_instance *dev)
@@ -426,7 +426,7 @@
 	/* IAHT registers always come before an identical number of
 	 * GAHT registers.
 	 */
-	return (emac_xaht_base(dev));
+	return emac_xaht_base(dev);
 }
 
 /* Ethtool get_regs complex data.
diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
index 294ccfb..0037a69 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ibmlana.c
@@ -602,7 +602,7 @@
 				/* set up skb fields */
 
 				skb->protocol = eth_type_trans(skb, dev);
-				skb->ip_summed = CHECKSUM_NONE;
+				skb_checksum_none_assert(skb);
 
 				/* bookkeeping */
 				dev->stats.rx_packets++;
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 4734c93..c454b45 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -1,122 +1,84 @@
-/**************************************************************************/
-/*                                                                        */
-/* IBM eServer i/pSeries Virtual Ethernet Device Driver                   */
-/* Copyright (C) 2003 IBM Corp.                                           */
-/*  Originally written by Dave Larson (larson1@us.ibm.com)                */
-/*  Maintained by Santiago Leon (santil@us.ibm.com)                       */
-/*                                                                        */
-/*  This program is free software; you can redistribute it and/or modify  */
-/*  it under the terms of the GNU General Public License as published by  */
-/*  the Free Software Foundation; either version 2 of the License, or     */
-/*  (at your option) any later version.                                   */
-/*                                                                        */
-/*  This program is distributed in the hope that it will be useful,       */
-/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
-/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
-/*  GNU General Public License for more details.                          */
-/*                                                                        */
-/*  You should have received a copy of the GNU General Public 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 module contains the implementation of a virtual ethernet device   */
-/* for use with IBM i/pSeries LPAR Linux.  It utilizes the logical LAN    */
-/* option of the RS/6000 Platform Architechture to interface with virtual */
-/* ethernet NICs that are presented to the partition by the hypervisor.   */
-/*                                                                        */
-/**************************************************************************/
 /*
-  TODO:
-  - add support for sysfs
-  - possibly remove procfs support
-*/
+ * IBM Power Virtual Ethernet Device 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2003, 2010
+ *
+ * Authors: Dave Larson <larson1@us.ibm.com>
+ *	    Santiago Leon <santil@linux.vnet.ibm.com>
+ *	    Brian King <brking@linux.vnet.ibm.com>
+ *	    Robert Jennings <rcj@linux.vnet.ibm.com>
+ *	    Anton Blanchard <anton@au.ibm.com>
+ */
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/ioport.h>
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/pm.h>
 #include <linux/ethtool.h>
-#include <linux/proc_fs.h>
 #include <linux/in.h>
 #include <linux/ip.h>
+#include <linux/ipv6.h>
 #include <linux/slab.h>
-#include <net/net_namespace.h>
 #include <asm/hvcall.h>
 #include <asm/atomic.h>
 #include <asm/vio.h>
 #include <asm/iommu.h>
-#include <asm/uaccess.h>
 #include <asm/firmware.h>
-#include <linux/seq_file.h>
 
 #include "ibmveth.h"
 
-#undef DEBUG
-
-#define ibmveth_printk(fmt, args...) \
-  printk(KERN_DEBUG "%s: " fmt, __FILE__, ## args)
-
-#define ibmveth_error_printk(fmt, args...) \
-  printk(KERN_ERR "(%s:%3.3d ua:%x) ERROR: " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args)
-
-#ifdef DEBUG
-#define ibmveth_debug_printk_no_adapter(fmt, args...) \
-  printk(KERN_DEBUG "(%s:%3.3d): " fmt, __FILE__, __LINE__ , ## args)
-#define ibmveth_debug_printk(fmt, args...) \
-  printk(KERN_DEBUG "(%s:%3.3d ua:%x): " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args)
-#define ibmveth_assert(expr) \
-  if(!(expr)) {                                   \
-    printk(KERN_DEBUG "assertion failed (%s:%3.3d ua:%x): %s\n", __FILE__, __LINE__, adapter->vdev->unit_address, #expr); \
-    BUG(); \
-  }
-#else
-#define ibmveth_debug_printk_no_adapter(fmt, args...)
-#define ibmveth_debug_printk(fmt, args...)
-#define ibmveth_assert(expr)
-#endif
-
-static int ibmveth_open(struct net_device *dev);
-static int ibmveth_close(struct net_device *dev);
-static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-static int ibmveth_poll(struct napi_struct *napi, int budget);
-static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void ibmveth_set_multicast_list(struct net_device *dev);
-static int ibmveth_change_mtu(struct net_device *dev, int new_mtu);
-static void ibmveth_proc_register_driver(void);
-static void ibmveth_proc_unregister_driver(void);
-static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter);
-static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter);
 static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance);
 static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
 static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev);
+
 static struct kobj_type ktype_veth_pool;
 
 
-#ifdef CONFIG_PROC_FS
-#define IBMVETH_PROC_DIR "ibmveth"
-static struct proc_dir_entry *ibmveth_proc_dir;
-#endif
-
 static const char ibmveth_driver_name[] = "ibmveth";
-static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver";
-#define ibmveth_driver_version "1.03"
+static const char ibmveth_driver_string[] = "IBM Power Virtual Ethernet Driver";
+#define ibmveth_driver_version "1.04"
 
-MODULE_AUTHOR("Santiago Leon <santil@us.ibm.com>");
-MODULE_DESCRIPTION("IBM i/pSeries Virtual Ethernet Driver");
+MODULE_AUTHOR("Santiago Leon <santil@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("IBM Power Virtual Ethernet Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(ibmveth_driver_version);
 
+static unsigned int tx_copybreak __read_mostly = 128;
+module_param(tx_copybreak, uint, 0644);
+MODULE_PARM_DESC(tx_copybreak,
+	"Maximum size of packet that is copied to a new buffer on transmit");
+
+static unsigned int rx_copybreak __read_mostly = 128;
+module_param(rx_copybreak, uint, 0644);
+MODULE_PARM_DESC(rx_copybreak,
+	"Maximum size of packet that is copied to a new buffer on receive");
+
+static unsigned int rx_flush __read_mostly = 0;
+module_param(rx_flush, uint, 0644);
+MODULE_PARM_DESC(rx_flush, "Flush receive buffers before use");
+
 struct ibmveth_stat {
 	char name[ETH_GSTRING_LEN];
 	int offset;
@@ -128,12 +90,16 @@
 struct ibmveth_stat ibmveth_stats[] = {
 	{ "replenish_task_cycles", IBMVETH_STAT_OFF(replenish_task_cycles) },
 	{ "replenish_no_mem", IBMVETH_STAT_OFF(replenish_no_mem) },
-	{ "replenish_add_buff_failure", IBMVETH_STAT_OFF(replenish_add_buff_failure) },
-	{ "replenish_add_buff_success", IBMVETH_STAT_OFF(replenish_add_buff_success) },
+	{ "replenish_add_buff_failure",
+			IBMVETH_STAT_OFF(replenish_add_buff_failure) },
+	{ "replenish_add_buff_success",
+			IBMVETH_STAT_OFF(replenish_add_buff_success) },
 	{ "rx_invalid_buffer", IBMVETH_STAT_OFF(rx_invalid_buffer) },
 	{ "rx_no_buffer", IBMVETH_STAT_OFF(rx_no_buffer) },
 	{ "tx_map_failed", IBMVETH_STAT_OFF(tx_map_failed) },
 	{ "tx_send_failed", IBMVETH_STAT_OFF(tx_send_failed) },
+	{ "fw_enabled_ipv4_csum", IBMVETH_STAT_OFF(fw_ipv4_csum_support) },
+	{ "fw_enabled_ipv6_csum", IBMVETH_STAT_OFF(fw_ipv6_csum_support) },
 };
 
 /* simple methods of getting data from the current rxq entry */
@@ -144,41 +110,44 @@
 
 static inline int ibmveth_rxq_toggle(struct ibmveth_adapter *adapter)
 {
-	return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_TOGGLE) >> IBMVETH_RXQ_TOGGLE_SHIFT;
+	return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_TOGGLE) >>
+			IBMVETH_RXQ_TOGGLE_SHIFT;
 }
 
 static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter)
 {
-	return (ibmveth_rxq_toggle(adapter) == adapter->rx_queue.toggle);
+	return ibmveth_rxq_toggle(adapter) == adapter->rx_queue.toggle;
 }
 
 static inline int ibmveth_rxq_buffer_valid(struct ibmveth_adapter *adapter)
 {
-	return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_VALID);
+	return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_VALID;
 }
 
 static inline int ibmveth_rxq_frame_offset(struct ibmveth_adapter *adapter)
 {
-	return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_OFF_MASK);
+	return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_OFF_MASK;
 }
 
 static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter)
 {
-	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].length);
+	return adapter->rx_queue.queue_addr[adapter->rx_queue.index].length;
 }
 
 static inline int ibmveth_rxq_csum_good(struct ibmveth_adapter *adapter)
 {
-	return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_CSUM_GOOD);
+	return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_CSUM_GOOD;
 }
 
 /* setup the initial settings for a buffer pool */
-static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size, u32 pool_active)
+static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool,
+				     u32 pool_index, u32 pool_size,
+				     u32 buff_size, u32 pool_active)
 {
 	pool->size = pool_size;
 	pool->index = pool_index;
 	pool->buff_size = buff_size;
-	pool->threshold = pool_size / 2;
+	pool->threshold = pool_size * 7 / 8;
 	pool->active = pool_active;
 }
 
@@ -189,12 +158,11 @@
 
 	pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL);
 
-	if(!pool->free_map) {
+	if (!pool->free_map)
 		return -1;
-	}
 
 	pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL);
-	if(!pool->dma_addr) {
+	if (!pool->dma_addr) {
 		kfree(pool->free_map);
 		pool->free_map = NULL;
 		return -1;
@@ -202,7 +170,7 @@
 
 	pool->skbuff = kcalloc(pool->size, sizeof(void *), GFP_KERNEL);
 
-	if(!pool->skbuff) {
+	if (!pool->skbuff) {
 		kfree(pool->dma_addr);
 		pool->dma_addr = NULL;
 
@@ -213,9 +181,8 @@
 
 	memset(pool->dma_addr, 0, sizeof(dma_addr_t) * pool->size);
 
-	for(i = 0; i < pool->size; ++i) {
+	for (i = 0; i < pool->size; ++i)
 		pool->free_map[i] = i;
-	}
 
 	atomic_set(&pool->available, 0);
 	pool->producer_index = 0;
@@ -224,10 +191,19 @@
 	return 0;
 }
 
+static inline void ibmveth_flush_buffer(void *addr, unsigned long length)
+{
+	unsigned long offset;
+
+	for (offset = 0; offset < length; offset += SMP_CACHE_BYTES)
+		asm("dcbfl %0,%1" :: "b" (addr), "r" (offset));
+}
+
 /* replenish the buffers for a pool.  note that we don't need to
  * skb_reserve these since they are used for incoming...
  */
-static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool)
+static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter,
+					  struct ibmveth_buff_pool *pool)
 {
 	u32 i;
 	u32 count = pool->size - atomic_read(&pool->available);
@@ -240,23 +216,26 @@
 
 	mb();
 
-	for(i = 0; i < count; ++i) {
+	for (i = 0; i < count; ++i) {
 		union ibmveth_buf_desc desc;
 
-		skb = alloc_skb(pool->buff_size, GFP_ATOMIC);
+		skb = netdev_alloc_skb(adapter->netdev, pool->buff_size);
 
-		if(!skb) {
-			ibmveth_debug_printk("replenish: unable to allocate skb\n");
+		if (!skb) {
+			netdev_dbg(adapter->netdev,
+				   "replenish: unable to allocate skb\n");
 			adapter->replenish_no_mem++;
 			break;
 		}
 
 		free_index = pool->consumer_index;
-		pool->consumer_index = (pool->consumer_index + 1) % pool->size;
+		pool->consumer_index++;
+		if (pool->consumer_index >= pool->size)
+			pool->consumer_index = 0;
 		index = pool->free_map[free_index];
 
-		ibmveth_assert(index != IBM_VETH_INVALID_MAP);
-		ibmveth_assert(pool->skbuff[index] == NULL);
+		BUG_ON(index == IBM_VETH_INVALID_MAP);
+		BUG_ON(pool->skbuff[index] != NULL);
 
 		dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
 				pool->buff_size, DMA_FROM_DEVICE);
@@ -269,16 +248,23 @@
 		pool->skbuff[index] = skb;
 
 		correlator = ((u64)pool->index << 32) | index;
-		*(u64*)skb->data = correlator;
+		*(u64 *)skb->data = correlator;
 
 		desc.fields.flags_len = IBMVETH_BUF_VALID | pool->buff_size;
 		desc.fields.address = dma_addr;
 
-		lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
+		if (rx_flush) {
+			unsigned int len = min(pool->buff_size,
+						adapter->netdev->mtu +
+						IBMVETH_BUFF_OH);
+			ibmveth_flush_buffer(skb->data, len);
+		}
+		lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address,
+						   desc.desc);
 
-		if (lpar_rc != H_SUCCESS)
+		if (lpar_rc != H_SUCCESS) {
 			goto failure;
-		else {
+		} else {
 			buffers_added++;
 			adapter->replenish_add_buff_success++;
 		}
@@ -313,26 +299,31 @@
 
 	adapter->replenish_task_cycles++;
 
-	for (i = (IbmVethNumBufferPools - 1); i >= 0; i--)
-		if(adapter->rx_buff_pool[i].active)
-			ibmveth_replenish_buffer_pool(adapter,
-						     &adapter->rx_buff_pool[i]);
+	for (i = (IBMVETH_NUM_BUFF_POOLS - 1); i >= 0; i--) {
+		struct ibmveth_buff_pool *pool = &adapter->rx_buff_pool[i];
 
-	adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
+		if (pool->active &&
+		    (atomic_read(&pool->available) < pool->threshold))
+			ibmveth_replenish_buffer_pool(adapter, pool);
+	}
+
+	adapter->rx_no_buffer = *(u64 *)(((char*)adapter->buffer_list_addr) +
+						4096 - 8);
 }
 
 /* empty and free ana buffer pool - also used to do cleanup in error paths */
-static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool)
+static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter,
+				     struct ibmveth_buff_pool *pool)
 {
 	int i;
 
 	kfree(pool->free_map);
 	pool->free_map = NULL;
 
-	if(pool->skbuff && pool->dma_addr) {
-		for(i = 0; i < pool->size; ++i) {
+	if (pool->skbuff && pool->dma_addr) {
+		for (i = 0; i < pool->size; ++i) {
 			struct sk_buff *skb = pool->skbuff[i];
-			if(skb) {
+			if (skb) {
 				dma_unmap_single(&adapter->vdev->dev,
 						 pool->dma_addr[i],
 						 pool->buff_size,
@@ -343,31 +334,32 @@
 		}
 	}
 
-	if(pool->dma_addr) {
+	if (pool->dma_addr) {
 		kfree(pool->dma_addr);
 		pool->dma_addr = NULL;
 	}
 
-	if(pool->skbuff) {
+	if (pool->skbuff) {
 		kfree(pool->skbuff);
 		pool->skbuff = NULL;
 	}
 }
 
 /* remove a buffer from a pool */
-static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64 correlator)
+static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter,
+					    u64 correlator)
 {
 	unsigned int pool  = correlator >> 32;
 	unsigned int index = correlator & 0xffffffffUL;
 	unsigned int free_index;
 	struct sk_buff *skb;
 
-	ibmveth_assert(pool < IbmVethNumBufferPools);
-	ibmveth_assert(index < adapter->rx_buff_pool[pool].size);
+	BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS);
+	BUG_ON(index >= adapter->rx_buff_pool[pool].size);
 
 	skb = adapter->rx_buff_pool[pool].skbuff[index];
 
-	ibmveth_assert(skb != NULL);
+	BUG_ON(skb == NULL);
 
 	adapter->rx_buff_pool[pool].skbuff[index] = NULL;
 
@@ -377,9 +369,10 @@
 			 DMA_FROM_DEVICE);
 
 	free_index = adapter->rx_buff_pool[pool].producer_index;
-	adapter->rx_buff_pool[pool].producer_index
-		= (adapter->rx_buff_pool[pool].producer_index + 1)
-		% adapter->rx_buff_pool[pool].size;
+	adapter->rx_buff_pool[pool].producer_index++;
+	if (adapter->rx_buff_pool[pool].producer_index >=
+	    adapter->rx_buff_pool[pool].size)
+		adapter->rx_buff_pool[pool].producer_index = 0;
 	adapter->rx_buff_pool[pool].free_map[free_index] = index;
 
 	mb();
@@ -394,8 +387,8 @@
 	unsigned int pool = correlator >> 32;
 	unsigned int index = correlator & 0xffffffffUL;
 
-	ibmveth_assert(pool < IbmVethNumBufferPools);
-	ibmveth_assert(index < adapter->rx_buff_pool[pool].size);
+	BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS);
+	BUG_ON(index >= adapter->rx_buff_pool[pool].size);
 
 	return adapter->rx_buff_pool[pool].skbuff[index];
 }
@@ -410,10 +403,10 @@
 	union ibmveth_buf_desc desc;
 	unsigned long lpar_rc;
 
-	ibmveth_assert(pool < IbmVethNumBufferPools);
-	ibmveth_assert(index < adapter->rx_buff_pool[pool].size);
+	BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS);
+	BUG_ON(index >= adapter->rx_buff_pool[pool].size);
 
-	if(!adapter->rx_buff_pool[pool].active) {
+	if (!adapter->rx_buff_pool[pool].active) {
 		ibmveth_rxq_harvest_buffer(adapter);
 		ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]);
 		return;
@@ -425,12 +418,13 @@
 
 	lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
 
-	if(lpar_rc != H_SUCCESS) {
-		ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc);
+	if (lpar_rc != H_SUCCESS) {
+		netdev_dbg(adapter->netdev, "h_add_logical_lan_buffer failed "
+			   "during recycle rc=%ld", lpar_rc);
 		ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
 	}
 
-	if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
+	if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
 		adapter->rx_queue.index = 0;
 		adapter->rx_queue.toggle = !adapter->rx_queue.toggle;
 	}
@@ -440,7 +434,7 @@
 {
 	ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
 
-	if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
+	if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
 		adapter->rx_queue.index = 0;
 		adapter->rx_queue.toggle = !adapter->rx_queue.toggle;
 	}
@@ -451,7 +445,7 @@
 	int i;
 	struct device *dev = &adapter->vdev->dev;
 
-	if(adapter->buffer_list_addr != NULL) {
+	if (adapter->buffer_list_addr != NULL) {
 		if (!dma_mapping_error(dev, adapter->buffer_list_dma)) {
 			dma_unmap_single(dev, adapter->buffer_list_dma, 4096,
 					DMA_BIDIRECTIONAL);
@@ -461,7 +455,7 @@
 		adapter->buffer_list_addr = NULL;
 	}
 
-	if(adapter->filter_list_addr != NULL) {
+	if (adapter->filter_list_addr != NULL) {
 		if (!dma_mapping_error(dev, adapter->filter_list_dma)) {
 			dma_unmap_single(dev, adapter->filter_list_dma, 4096,
 					DMA_BIDIRECTIONAL);
@@ -471,7 +465,7 @@
 		adapter->filter_list_addr = NULL;
 	}
 
-	if(adapter->rx_queue.queue_addr != NULL) {
+	if (adapter->rx_queue.queue_addr != NULL) {
 		if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) {
 			dma_unmap_single(dev,
 					adapter->rx_queue.queue_dma,
@@ -483,7 +477,7 @@
 		adapter->rx_queue.queue_addr = NULL;
 	}
 
-	for(i = 0; i<IbmVethNumBufferPools; i++)
+	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
 		if (adapter->rx_buff_pool[i].active)
 			ibmveth_free_buffer_pool(adapter,
 						 &adapter->rx_buff_pool[i]);
@@ -506,9 +500,11 @@
 {
 	int rc, try_again = 1;
 
-	/* After a kexec the adapter will still be open, so our attempt to
-	* open it will fail. So if we get a failure we free the adapter and
-	* try again, but only once. */
+	/*
+	 * After a kexec the adapter will still be open, so our attempt to
+	 * open it will fail. So if we get a failure we free the adapter and
+	 * try again, but only once.
+	 */
 retry:
 	rc = h_register_logical_lan(adapter->vdev->unit_address,
 				    adapter->buffer_list_dma, rxq_desc.desc,
@@ -537,31 +533,32 @@
 	int i;
 	struct device *dev;
 
-	ibmveth_debug_printk("open starting\n");
+	netdev_dbg(netdev, "open starting\n");
 
 	napi_enable(&adapter->napi);
 
-	for(i = 0; i<IbmVethNumBufferPools; i++)
+	for(i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
 		rxq_entries += adapter->rx_buff_pool[i].size;
 
 	adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
 	adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
 
-	if(!adapter->buffer_list_addr || !adapter->filter_list_addr) {
-		ibmveth_error_printk("unable to allocate filter or buffer list pages\n");
-		ibmveth_cleanup(adapter);
-		napi_disable(&adapter->napi);
-		return -ENOMEM;
+	if (!adapter->buffer_list_addr || !adapter->filter_list_addr) {
+		netdev_err(netdev, "unable to allocate filter or buffer list "
+			   "pages\n");
+		rc = -ENOMEM;
+		goto err_out;
 	}
 
-	adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries;
-	adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, GFP_KERNEL);
+	adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) *
+						rxq_entries;
+	adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len,
+						GFP_KERNEL);
 
-	if(!adapter->rx_queue.queue_addr) {
-		ibmveth_error_printk("unable to allocate rx queue pages\n");
-		ibmveth_cleanup(adapter);
-		napi_disable(&adapter->napi);
-		return -ENOMEM;
+	if (!adapter->rx_queue.queue_addr) {
+		netdev_err(netdev, "unable to allocate rx queue pages\n");
+		rc = -ENOMEM;
+		goto err_out;
 	}
 
 	dev = &adapter->vdev->dev;
@@ -577,10 +574,10 @@
 	if ((dma_mapping_error(dev, adapter->buffer_list_dma)) ||
 	    (dma_mapping_error(dev, adapter->filter_list_dma)) ||
 	    (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) {
-		ibmveth_error_printk("unable to map filter or buffer list pages\n");
-		ibmveth_cleanup(adapter);
-		napi_disable(&adapter->napi);
-		return -ENOMEM;
+		netdev_err(netdev, "unable to map filter or buffer list "
+			   "pages\n");
+		rc = -ENOMEM;
+		goto err_out;
 	}
 
 	adapter->rx_queue.index = 0;
@@ -590,79 +587,86 @@
 	memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
 	mac_address = mac_address >> 16;
 
-	rxq_desc.fields.flags_len = IBMVETH_BUF_VALID | adapter->rx_queue.queue_len;
+	rxq_desc.fields.flags_len = IBMVETH_BUF_VALID |
+					adapter->rx_queue.queue_len;
 	rxq_desc.fields.address = adapter->rx_queue.queue_dma;
 
-	ibmveth_debug_printk("buffer list @ 0x%p\n", adapter->buffer_list_addr);
-	ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr);
-	ibmveth_debug_printk("receive q   @ 0x%p\n", adapter->rx_queue.queue_addr);
+	netdev_dbg(netdev, "buffer list @ 0x%p\n", adapter->buffer_list_addr);
+	netdev_dbg(netdev, "filter list @ 0x%p\n", adapter->filter_list_addr);
+	netdev_dbg(netdev, "receive q   @ 0x%p\n", adapter->rx_queue.queue_addr);
 
 	h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
 
 	lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address);
 
-	if(lpar_rc != H_SUCCESS) {
-		ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
-		ibmveth_error_printk("buffer TCE:0x%llx filter TCE:0x%llx rxq desc:0x%llx MAC:0x%llx\n",
+	if (lpar_rc != H_SUCCESS) {
+		netdev_err(netdev, "h_register_logical_lan failed with %ld\n",
+			   lpar_rc);
+		netdev_err(netdev, "buffer TCE:0x%llx filter TCE:0x%llx rxq "
+			   "desc:0x%llx MAC:0x%llx\n",
 				     adapter->buffer_list_dma,
 				     adapter->filter_list_dma,
 				     rxq_desc.desc,
 				     mac_address);
-		ibmveth_cleanup(adapter);
-		napi_disable(&adapter->napi);
-		return -ENONET;
+		rc = -ENONET;
+		goto err_out;
 	}
 
-	for(i = 0; i<IbmVethNumBufferPools; i++) {
-		if(!adapter->rx_buff_pool[i].active)
+	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
+		if (!adapter->rx_buff_pool[i].active)
 			continue;
 		if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[i])) {
-			ibmveth_error_printk("unable to alloc pool\n");
+			netdev_err(netdev, "unable to alloc pool\n");
 			adapter->rx_buff_pool[i].active = 0;
-			ibmveth_cleanup(adapter);
-			napi_disable(&adapter->napi);
-			return -ENOMEM ;
+			rc = -ENOMEM;
+			goto err_out;
 		}
 	}
 
-	ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq);
-	if((rc = request_irq(netdev->irq, ibmveth_interrupt, 0, netdev->name, netdev)) != 0) {
-		ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc);
+	netdev_dbg(netdev, "registering irq 0x%x\n", netdev->irq);
+	rc = request_irq(netdev->irq, ibmveth_interrupt, 0, netdev->name,
+			 netdev);
+	if (rc != 0) {
+		netdev_err(netdev, "unable to request irq 0x%x, rc %d\n",
+			   netdev->irq, rc);
 		do {
 			rc = h_free_logical_lan(adapter->vdev->unit_address);
 		} while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY));
 
-		ibmveth_cleanup(adapter);
-		napi_disable(&adapter->napi);
-		return rc;
+		goto err_out;
 	}
 
 	adapter->bounce_buffer =
 	    kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL);
 	if (!adapter->bounce_buffer) {
-		ibmveth_error_printk("unable to allocate bounce buffer\n");
-		ibmveth_cleanup(adapter);
-		napi_disable(&adapter->napi);
-		return -ENOMEM;
+		netdev_err(netdev, "unable to allocate bounce buffer\n");
+		rc = -ENOMEM;
+		goto err_out_free_irq;
 	}
 	adapter->bounce_buffer_dma =
 	    dma_map_single(&adapter->vdev->dev, adapter->bounce_buffer,
 			   netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL);
 	if (dma_mapping_error(dev, adapter->bounce_buffer_dma)) {
-		ibmveth_error_printk("unable to map bounce buffer\n");
-		ibmveth_cleanup(adapter);
-		napi_disable(&adapter->napi);
-		return -ENOMEM;
+		netdev_err(netdev, "unable to map bounce buffer\n");
+		rc = -ENOMEM;
+		goto err_out_free_irq;
 	}
 
-	ibmveth_debug_printk("initial replenish cycle\n");
+	netdev_dbg(netdev, "initial replenish cycle\n");
 	ibmveth_interrupt(netdev->irq, netdev);
 
 	netif_start_queue(netdev);
 
-	ibmveth_debug_printk("open complete\n");
+	netdev_dbg(netdev, "open complete\n");
 
 	return 0;
+
+err_out_free_irq:
+	free_irq(netdev->irq, netdev);
+err_out:
+	ibmveth_cleanup(adapter);
+	napi_disable(&adapter->napi);
+	return rc;
 }
 
 static int ibmveth_close(struct net_device *netdev)
@@ -670,7 +674,7 @@
 	struct ibmveth_adapter *adapter = netdev_priv(netdev);
 	long lpar_rc;
 
-	ibmveth_debug_printk("close starting\n");
+	netdev_dbg(netdev, "close starting\n");
 
 	napi_disable(&adapter->napi);
 
@@ -683,26 +687,29 @@
 		lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
 	} while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
 
-	if(lpar_rc != H_SUCCESS)
-	{
-		ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n",
-				     lpar_rc);
+	if (lpar_rc != H_SUCCESS) {
+		netdev_err(netdev, "h_free_logical_lan failed with %lx, "
+			   "continuing with close\n", lpar_rc);
 	}
 
 	free_irq(netdev->irq, netdev);
 
-	adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
+	adapter->rx_no_buffer = *(u64 *)(((char *)adapter->buffer_list_addr) +
+						4096 - 8);
 
 	ibmveth_cleanup(adapter);
 
-	ibmveth_debug_printk("close complete\n");
+	netdev_dbg(netdev, "close complete\n");
 
 	return 0;
 }
 
-static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) {
-	cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
-	cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ADVERTISED_FIBRE);
+static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
+				SUPPORTED_FIBRE);
+	cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg |
+				ADVERTISED_FIBRE);
 	cmd->speed = SPEED_1000;
 	cmd->duplex = DUPLEX_FULL;
 	cmd->port = PORT_FIBRE;
@@ -714,12 +721,16 @@
 	return 0;
 }
 
-static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) {
+static void netdev_get_drvinfo(struct net_device *dev,
+			       struct ethtool_drvinfo *info)
+{
 	strncpy(info->driver, ibmveth_driver_name, sizeof(info->driver) - 1);
-	strncpy(info->version, ibmveth_driver_version, sizeof(info->version) - 1);
+	strncpy(info->version, ibmveth_driver_version,
+		sizeof(info->version) - 1);
 }
 
-static u32 netdev_get_link(struct net_device *dev) {
+static u32 netdev_get_link(struct net_device *dev)
+{
 	return 1;
 }
 
@@ -727,18 +738,20 @@
 {
 	struct ibmveth_adapter *adapter = netdev_priv(dev);
 
-	if (data)
+	if (data) {
 		adapter->rx_csum = 1;
-	else {
+	} else {
 		/*
-		 * Since the ibmveth firmware interface does not have the concept of
-		 * separate tx/rx checksum offload enable, if rx checksum is disabled
-		 * we also have to disable tx checksum offload. Once we disable rx
-		 * checksum offload, we are no longer allowed to send tx buffers that
-		 * are not properly checksummed.
+		 * Since the ibmveth firmware interface does not have the
+		 * concept of separate tx/rx checksum offload enable, if rx
+		 * checksum is disabled we also have to disable tx checksum
+		 * offload. Once we disable rx checksum offload, we are no
+		 * longer allowed to send tx buffers that are not properly
+		 * checksummed.
 		 */
 		adapter->rx_csum = 0;
 		dev->features &= ~NETIF_F_IP_CSUM;
+		dev->features &= ~NETIF_F_IPV6_CSUM;
 	}
 }
 
@@ -747,10 +760,15 @@
 	struct ibmveth_adapter *adapter = netdev_priv(dev);
 
 	if (data) {
-		dev->features |= NETIF_F_IP_CSUM;
+		if (adapter->fw_ipv4_csum_support)
+			dev->features |= NETIF_F_IP_CSUM;
+		if (adapter->fw_ipv6_csum_support)
+			dev->features |= NETIF_F_IPV6_CSUM;
 		adapter->rx_csum = 1;
-	} else
+	} else {
 		dev->features &= ~NETIF_F_IP_CSUM;
+		dev->features &= ~NETIF_F_IPV6_CSUM;
+	}
 }
 
 static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
@@ -758,7 +776,8 @@
 {
 	struct ibmveth_adapter *adapter = netdev_priv(dev);
 	unsigned long set_attr, clr_attr, ret_attr;
-	long ret;
+	unsigned long set_attr6, clr_attr6;
+	long ret, ret6;
 	int rc1 = 0, rc2 = 0;
 	int restart = 0;
 
@@ -772,10 +791,13 @@
 	set_attr = 0;
 	clr_attr = 0;
 
-	if (data)
+	if (data) {
 		set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
-	else
+		set_attr6 = IBMVETH_ILLAN_IPV6_TCP_CSUM;
+	} else {
 		clr_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
+		clr_attr6 = IBMVETH_ILLAN_IPV6_TCP_CSUM;
+	}
 
 	ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr);
 
@@ -786,18 +808,39 @@
 					 set_attr, &ret_attr);
 
 		if (ret != H_SUCCESS) {
-			rc1 = -EIO;
-			ibmveth_error_printk("unable to change checksum offload settings."
-					     " %d rc=%ld\n", data, ret);
+			netdev_err(dev, "unable to change IPv4 checksum "
+					"offload settings. %d rc=%ld\n",
+					data, ret);
 
 			ret = h_illan_attributes(adapter->vdev->unit_address,
 						 set_attr, clr_attr, &ret_attr);
+		} else {
+			adapter->fw_ipv4_csum_support = data;
+		}
+
+		ret6 = h_illan_attributes(adapter->vdev->unit_address,
+					 clr_attr6, set_attr6, &ret_attr);
+
+		if (ret6 != H_SUCCESS) {
+			netdev_err(dev, "unable to change IPv6 checksum "
+					"offload settings. %d rc=%ld\n",
+					data, ret);
+
+			ret = h_illan_attributes(adapter->vdev->unit_address,
+						 set_attr6, clr_attr6,
+						 &ret_attr);
 		} else
+			adapter->fw_ipv6_csum_support = data;
+
+		if (ret == H_SUCCESS || ret6 == H_SUCCESS)
 			done(dev, data);
+		else
+			rc1 = -EIO;
 	} else {
 		rc1 = -EIO;
-		ibmveth_error_printk("unable to change checksum offload settings."
-				     " %d rc=%ld ret_attr=%lx\n", data, ret, ret_attr);
+		netdev_err(dev, "unable to change checksum offload settings."
+				     " %d rc=%ld ret_attr=%lx\n", data, ret,
+				     ret_attr);
 	}
 
 	if (restart)
@@ -821,13 +864,14 @@
 	struct ibmveth_adapter *adapter = netdev_priv(dev);
 	int rc = 0;
 
-	if (data && (dev->features & NETIF_F_IP_CSUM))
+	if (data && (dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))
 		return 0;
-	if (!data && !(dev->features & NETIF_F_IP_CSUM))
+	if (!data && !(dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))
 		return 0;
 
 	if (data && !adapter->rx_csum)
-		rc = ibmveth_set_csum_offload(dev, data, ibmveth_set_tx_csum_flags);
+		rc = ibmveth_set_csum_offload(dev, data,
+					      ibmveth_set_tx_csum_flags);
 	else
 		ibmveth_set_tx_csum_flags(dev, data);
 
@@ -881,6 +925,7 @@
 	.get_strings		= ibmveth_get_strings,
 	.get_sset_count		= ibmveth_get_sset_count,
 	.get_ethtool_stats	= ibmveth_get_ethtool_stats,
+	.set_sg			= ethtool_op_set_sg,
 };
 
 static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -890,129 +935,216 @@
 
 #define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1))
 
+static int ibmveth_send(struct ibmveth_adapter *adapter,
+			union ibmveth_buf_desc *descs)
+{
+	unsigned long correlator;
+	unsigned int retry_count;
+	unsigned long ret;
+
+	/*
+	 * The retry count sets a maximum for the number of broadcast and
+	 * multicast destinations within the system.
+	 */
+	retry_count = 1024;
+	correlator = 0;
+	do {
+		ret = h_send_logical_lan(adapter->vdev->unit_address,
+					     descs[0].desc, descs[1].desc,
+					     descs[2].desc, descs[3].desc,
+					     descs[4].desc, descs[5].desc,
+					     correlator, &correlator);
+	} while ((ret == H_BUSY) && (retry_count--));
+
+	if (ret != H_SUCCESS && ret != H_DROPPED) {
+		netdev_err(adapter->netdev, "tx: h_send_logical_lan failed "
+			   "with rc=%ld\n", ret);
+		return 1;
+	}
+
+	return 0;
+}
+
 static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,
 				      struct net_device *netdev)
 {
 	struct ibmveth_adapter *adapter = netdev_priv(netdev);
-	union ibmveth_buf_desc desc;
-	unsigned long lpar_rc;
-	unsigned long correlator;
-	unsigned long flags;
-	unsigned int retry_count;
-	unsigned int tx_dropped = 0;
-	unsigned int tx_bytes = 0;
-	unsigned int tx_packets = 0;
-	unsigned int tx_send_failed = 0;
-	unsigned int tx_map_failed = 0;
-	int used_bounce = 0;
-	unsigned long data_dma_addr;
+	unsigned int desc_flags;
+	union ibmveth_buf_desc descs[6];
+	int last, i;
+	int force_bounce = 0;
 
-	desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len;
-
-	if (skb->ip_summed == CHECKSUM_PARTIAL &&
-	    ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
-		ibmveth_error_printk("tx: failed to checksum packet\n");
-		tx_dropped++;
+	/*
+	 * veth handles a maximum of 6 segments including the header, so
+	 * we have to linearize the skb if there are more than this.
+	 */
+	if (skb_shinfo(skb)->nr_frags > 5 && __skb_linearize(skb)) {
+		netdev->stats.tx_dropped++;
 		goto out;
 	}
 
-	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		unsigned char *buf = skb_transport_header(skb) + skb->csum_offset;
+	/* veth can't checksum offload UDP */
+	if (skb->ip_summed == CHECKSUM_PARTIAL &&
+	    ((skb->protocol == htons(ETH_P_IP) &&
+	      ip_hdr(skb)->protocol != IPPROTO_TCP) ||
+	     (skb->protocol == htons(ETH_P_IPV6) &&
+	      ipv6_hdr(skb)->nexthdr != IPPROTO_TCP)) &&
+	    skb_checksum_help(skb)) {
 
-		desc.fields.flags_len |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD);
+		netdev_err(netdev, "tx: failed to checksum packet\n");
+		netdev->stats.tx_dropped++;
+		goto out;
+	}
+
+	desc_flags = IBMVETH_BUF_VALID;
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		unsigned char *buf = skb_transport_header(skb) +
+						skb->csum_offset;
+
+		desc_flags |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD);
 
 		/* Need to zero out the checksum */
 		buf[0] = 0;
 		buf[1] = 0;
 	}
 
-	data_dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
-				       skb->len, DMA_TO_DEVICE);
-	if (dma_mapping_error(&adapter->vdev->dev, data_dma_addr)) {
-		if (!firmware_has_feature(FW_FEATURE_CMO))
-			ibmveth_error_printk("tx: unable to map xmit buffer\n");
+retry_bounce:
+	memset(descs, 0, sizeof(descs));
+
+	/*
+	 * If a linear packet is below the rx threshold then
+	 * copy it into the static bounce buffer. This avoids the
+	 * cost of a TCE insert and remove.
+	 */
+	if (force_bounce || (!skb_is_nonlinear(skb) &&
+				(skb->len < tx_copybreak))) {
 		skb_copy_from_linear_data(skb, adapter->bounce_buffer,
 					  skb->len);
-		desc.fields.address = adapter->bounce_buffer_dma;
-		tx_map_failed++;
-		used_bounce = 1;
-		wmb();
-	} else
-		desc.fields.address = data_dma_addr;
 
-	/* send the frame. Arbitrarily set retrycount to 1024 */
-	correlator = 0;
-	retry_count = 1024;
-	do {
-		lpar_rc = h_send_logical_lan(adapter->vdev->unit_address,
-					     desc.desc, 0, 0, 0, 0, 0,
-					     correlator, &correlator);
-	} while ((lpar_rc == H_BUSY) && (retry_count--));
+		descs[0].fields.flags_len = desc_flags | skb->len;
+		descs[0].fields.address = adapter->bounce_buffer_dma;
 
-	if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
-		ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
-		ibmveth_error_printk("tx: valid=%d, len=%d, address=0x%08x\n",
-				     (desc.fields.flags_len & IBMVETH_BUF_VALID) ? 1 : 0,
-				     skb->len, desc.fields.address);
-		tx_send_failed++;
-		tx_dropped++;
-	} else {
-		tx_packets++;
-		tx_bytes += skb->len;
-		netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
+		if (ibmveth_send(adapter, descs)) {
+			adapter->tx_send_failed++;
+			netdev->stats.tx_dropped++;
+		} else {
+			netdev->stats.tx_packets++;
+			netdev->stats.tx_bytes += skb->len;
+		}
+
+		goto out;
 	}
 
-	if (!used_bounce)
-		dma_unmap_single(&adapter->vdev->dev, data_dma_addr,
-				 skb->len, DMA_TO_DEVICE);
+	/* Map the header */
+	descs[0].fields.address = dma_map_single(&adapter->vdev->dev, skb->data,
+						 skb_headlen(skb),
+						 DMA_TO_DEVICE);
+	if (dma_mapping_error(&adapter->vdev->dev, descs[0].fields.address))
+		goto map_failed;
 
-out:	spin_lock_irqsave(&adapter->stats_lock, flags);
-	netdev->stats.tx_dropped += tx_dropped;
-	netdev->stats.tx_bytes += tx_bytes;
-	netdev->stats.tx_packets += tx_packets;
-	adapter->tx_send_failed += tx_send_failed;
-	adapter->tx_map_failed += tx_map_failed;
-	spin_unlock_irqrestore(&adapter->stats_lock, flags);
+	descs[0].fields.flags_len = desc_flags | skb_headlen(skb);
 
+	/* Map the frags */
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		unsigned long dma_addr;
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+		dma_addr = dma_map_page(&adapter->vdev->dev, frag->page,
+					frag->page_offset, frag->size,
+					DMA_TO_DEVICE);
+
+		if (dma_mapping_error(&adapter->vdev->dev, dma_addr))
+			goto map_failed_frags;
+
+		descs[i+1].fields.flags_len = desc_flags | frag->size;
+		descs[i+1].fields.address = dma_addr;
+	}
+
+	if (ibmveth_send(adapter, descs)) {
+		adapter->tx_send_failed++;
+		netdev->stats.tx_dropped++;
+	} else {
+		netdev->stats.tx_packets++;
+		netdev->stats.tx_bytes += skb->len;
+	}
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags + 1; i++)
+		dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address,
+			       descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK,
+			       DMA_TO_DEVICE);
+
+out:
 	dev_kfree_skb(skb);
 	return NETDEV_TX_OK;
+
+map_failed_frags:
+	last = i+1;
+	for (i = 0; i < last; i++)
+		dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address,
+			       descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK,
+			       DMA_TO_DEVICE);
+
+map_failed:
+	if (!firmware_has_feature(FW_FEATURE_CMO))
+		netdev_err(netdev, "tx: unable to map xmit buffer\n");
+	adapter->tx_map_failed++;
+	skb_linearize(skb);
+	force_bounce = 1;
+	goto retry_bounce;
 }
 
 static int ibmveth_poll(struct napi_struct *napi, int budget)
 {
-	struct ibmveth_adapter *adapter = container_of(napi, struct ibmveth_adapter, napi);
+	struct ibmveth_adapter *adapter =
+			container_of(napi, struct ibmveth_adapter, napi);
 	struct net_device *netdev = adapter->netdev;
 	int frames_processed = 0;
 	unsigned long lpar_rc;
 
- restart_poll:
+restart_poll:
 	do {
-		struct sk_buff *skb;
-
 		if (!ibmveth_rxq_pending_buffer(adapter))
 			break;
 
-		rmb();
+		smp_rmb();
 		if (!ibmveth_rxq_buffer_valid(adapter)) {
 			wmb(); /* suggested by larson1 */
 			adapter->rx_invalid_buffer++;
-			ibmveth_debug_printk("recycling invalid buffer\n");
+			netdev_dbg(netdev, "recycling invalid buffer\n");
 			ibmveth_rxq_recycle_buffer(adapter);
 		} else {
+			struct sk_buff *skb, *new_skb;
 			int length = ibmveth_rxq_frame_length(adapter);
 			int offset = ibmveth_rxq_frame_offset(adapter);
 			int csum_good = ibmveth_rxq_csum_good(adapter);
 
 			skb = ibmveth_rxq_get_buffer(adapter);
-			if (csum_good)
-				skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-			ibmveth_rxq_harvest_buffer(adapter);
+			new_skb = NULL;
+			if (length < rx_copybreak)
+				new_skb = netdev_alloc_skb(netdev, length);
 
-			skb_reserve(skb, offset);
+			if (new_skb) {
+				skb_copy_to_linear_data(new_skb,
+							skb->data + offset,
+							length);
+				if (rx_flush)
+					ibmveth_flush_buffer(skb->data,
+						length + offset);
+				skb = new_skb;
+				ibmveth_rxq_recycle_buffer(adapter);
+			} else {
+				ibmveth_rxq_harvest_buffer(adapter);
+				skb_reserve(skb, offset);
+			}
+
 			skb_put(skb, length);
 			skb->protocol = eth_type_trans(skb, netdev);
 
+			if (csum_good)
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+
 			netif_receive_skb(skb);	/* send it up */
 
 			netdev->stats.rx_packets++;
@@ -1030,7 +1162,7 @@
 		lpar_rc = h_vio_signal(adapter->vdev->unit_address,
 				       VIO_IRQ_ENABLE);
 
-		ibmveth_assert(lpar_rc == H_SUCCESS);
+		BUG_ON(lpar_rc != H_SUCCESS);
 
 		napi_complete(napi);
 
@@ -1054,7 +1186,7 @@
 	if (napi_schedule_prep(&adapter->napi)) {
 		lpar_rc = h_vio_signal(adapter->vdev->unit_address,
 				       VIO_IRQ_DISABLE);
-		ibmveth_assert(lpar_rc == H_SUCCESS);
+		BUG_ON(lpar_rc != H_SUCCESS);
 		__napi_schedule(&adapter->napi);
 	}
 	return IRQ_HANDLED;
@@ -1071,8 +1203,9 @@
 					   IbmVethMcastEnableRecv |
 					   IbmVethMcastDisableFiltering,
 					   0);
-		if(lpar_rc != H_SUCCESS) {
-			ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc);
+		if (lpar_rc != H_SUCCESS) {
+			netdev_err(netdev, "h_multicast_ctrl rc=%ld when "
+				   "entering promisc mode\n", lpar_rc);
 		}
 	} else {
 		struct netdev_hw_addr *ha;
@@ -1082,19 +1215,23 @@
 					   IbmVethMcastDisableFiltering |
 					   IbmVethMcastClearFilterTable,
 					   0);
-		if(lpar_rc != H_SUCCESS) {
-			ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc);
+		if (lpar_rc != H_SUCCESS) {
+			netdev_err(netdev, "h_multicast_ctrl rc=%ld when "
+				   "attempting to clear filter table\n",
+				   lpar_rc);
 		}
 		/* add the addresses to the filter table */
 		netdev_for_each_mc_addr(ha, netdev) {
-			// add the multicast address to the filter table
+			/* add the multicast address to the filter table */
 			unsigned long mcast_addr = 0;
 			memcpy(((char *)&mcast_addr)+2, ha->addr, 6);
 			lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
 						   IbmVethMcastAddFilter,
 						   mcast_addr);
-			if(lpar_rc != H_SUCCESS) {
-				ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
+			if (lpar_rc != H_SUCCESS) {
+				netdev_err(netdev, "h_multicast_ctrl rc=%ld "
+					   "when adding an entry to the filter "
+					   "table\n", lpar_rc);
 			}
 		}
 
@@ -1102,8 +1239,9 @@
 		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
 					   IbmVethMcastEnableFiltering,
 					   0);
-		if(lpar_rc != H_SUCCESS) {
-			ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc);
+		if (lpar_rc != H_SUCCESS) {
+			netdev_err(netdev, "h_multicast_ctrl rc=%ld when "
+				   "enabling filtering\n", lpar_rc);
 		}
 	}
 }
@@ -1116,14 +1254,14 @@
 	int i, rc;
 	int need_restart = 0;
 
-	if (new_mtu < IBMVETH_MAX_MTU)
+	if (new_mtu < IBMVETH_MIN_MTU)
 		return -EINVAL;
 
-	for (i = 0; i < IbmVethNumBufferPools; i++)
+	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
 		if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size)
 			break;
 
-	if (i == IbmVethNumBufferPools)
+	if (i == IBMVETH_NUM_BUFF_POOLS)
 		return -EINVAL;
 
 	/* Deactivate all the buffer pools so that the next loop can activate
@@ -1136,7 +1274,7 @@
 	}
 
 	/* Look for an active buffer pool that can hold the new MTU */
-	for(i = 0; i<IbmVethNumBufferPools; i++) {
+	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
 		adapter->rx_buff_pool[i].active = 1;
 
 		if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
@@ -1190,7 +1328,7 @@
 	ret = IBMVETH_BUFF_LIST_SIZE + IBMVETH_FILT_LIST_SIZE;
 	ret += IOMMU_PAGE_ALIGN(netdev->mtu);
 
-	for (i = 0; i < IbmVethNumBufferPools; i++) {
+	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
 		/* add the size of the active receive buffers */
 		if (adapter->rx_buff_pool[i].active)
 			ret +=
@@ -1219,41 +1357,36 @@
 #endif
 };
 
-static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
+static int __devinit ibmveth_probe(struct vio_dev *dev,
+				   const struct vio_device_id *id)
 {
 	int rc, i;
-	long ret;
 	struct net_device *netdev;
 	struct ibmveth_adapter *adapter;
-	unsigned long set_attr, ret_attr;
-
 	unsigned char *mac_addr_p;
 	unsigned int *mcastFilterSize_p;
 
+	dev_dbg(&dev->dev, "entering ibmveth_probe for UA 0x%x\n",
+		dev->unit_address);
 
-	ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n",
-					dev->unit_address);
-
-	mac_addr_p = (unsigned char *) vio_get_attribute(dev,
-						VETH_MAC_ADDR, NULL);
-	if(!mac_addr_p) {
-		printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find VETH_MAC_ADDR "
-				"attribute\n", __FILE__, __LINE__);
-		return 0;
+	mac_addr_p = (unsigned char *)vio_get_attribute(dev, VETH_MAC_ADDR,
+							NULL);
+	if (!mac_addr_p) {
+		dev_err(&dev->dev, "Can't find VETH_MAC_ADDR attribute\n");
+		return -EINVAL;
 	}
 
-	mcastFilterSize_p = (unsigned int *) vio_get_attribute(dev,
+	mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev,
 						VETH_MCAST_FILTER_SIZE, NULL);
-	if(!mcastFilterSize_p) {
-		printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find "
-				"VETH_MCAST_FILTER_SIZE attribute\n",
-				__FILE__, __LINE__);
-		return 0;
+	if (!mcastFilterSize_p) {
+		dev_err(&dev->dev, "Can't find VETH_MCAST_FILTER_SIZE "
+			"attribute\n");
+		return -EINVAL;
 	}
 
 	netdev = alloc_etherdev(sizeof(struct ibmveth_adapter));
 
-	if(!netdev)
+	if (!netdev)
 		return -ENOMEM;
 
 	adapter = netdev_priv(netdev);
@@ -1261,19 +1394,19 @@
 
 	adapter->vdev = dev;
 	adapter->netdev = netdev;
-	adapter->mcastFilterSize= *mcastFilterSize_p;
+	adapter->mcastFilterSize = *mcastFilterSize_p;
 	adapter->pool_config = 0;
 
 	netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16);
 
-	/* 	Some older boxes running PHYP non-natively have an OF that
-		returns a 8-byte local-mac-address field (and the first
-		2 bytes have to be ignored) while newer boxes' OF return
-		a 6-byte field. Note that IEEE 1275 specifies that
-		local-mac-address must be a 6-byte field.
-		The RPA doc specifies that the first byte must be 10b, so
-		we'll just look for it to solve this 8 vs. 6 byte field issue */
-
+	/*
+	 * Some older boxes running PHYP non-natively have an OF that returns
+	 * a 8-byte local-mac-address field (and the first 2 bytes have to be
+	 * ignored) while newer boxes' OF return a 6-byte field. Note that
+	 * IEEE 1275 specifies that local-mac-address must be a 6-byte field.
+	 * The RPA doc specifies that the first byte must be 10b, so we'll
+	 * just look for it to solve this 8 vs. 6 byte field issue
+	 */
 	if ((*mac_addr_p & 0x3) != 0x02)
 		mac_addr_p += 2;
 
@@ -1284,12 +1417,11 @@
 	netdev->netdev_ops = &ibmveth_netdev_ops;
 	netdev->ethtool_ops = &netdev_ethtool_ops;
 	SET_NETDEV_DEV(netdev, &dev->dev);
- 	netdev->features |= NETIF_F_LLTX;
-	spin_lock_init(&adapter->stats_lock);
+	netdev->features |= NETIF_F_SG;
 
 	memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
 
-	for(i = 0; i<IbmVethNumBufferPools; i++) {
+	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
 		struct kobject *kobj = &adapter->rx_buff_pool[i].kobj;
 		int error;
 
@@ -1302,41 +1434,25 @@
 			kobject_uevent(kobj, KOBJ_ADD);
 	}
 
-	ibmveth_debug_printk("adapter @ 0x%p\n", adapter);
+	netdev_dbg(netdev, "adapter @ 0x%p\n", adapter);
 
 	adapter->buffer_list_dma = DMA_ERROR_CODE;
 	adapter->filter_list_dma = DMA_ERROR_CODE;
 	adapter->rx_queue.queue_dma = DMA_ERROR_CODE;
 
-	ibmveth_debug_printk("registering netdev...\n");
+	netdev_dbg(netdev, "registering netdev...\n");
 
-	ret = h_illan_attributes(dev->unit_address, 0, 0, &ret_attr);
-
-	if (ret == H_SUCCESS && !(ret_attr & IBMVETH_ILLAN_ACTIVE_TRUNK) &&
-	    !(ret_attr & IBMVETH_ILLAN_TRUNK_PRI_MASK) &&
-	    (ret_attr & IBMVETH_ILLAN_PADDED_PKT_CSUM)) {
-		set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
-
-		ret = h_illan_attributes(dev->unit_address, 0, set_attr, &ret_attr);
-
-		if (ret == H_SUCCESS) {
-			adapter->rx_csum = 1;
-			netdev->features |= NETIF_F_IP_CSUM;
-		} else
-			ret = h_illan_attributes(dev->unit_address, set_attr, 0, &ret_attr);
-	}
+	ibmveth_set_csum_offload(netdev, 1, ibmveth_set_tx_csum_flags);
 
 	rc = register_netdev(netdev);
 
-	if(rc) {
-		ibmveth_debug_printk("failed to register netdev rc=%d\n", rc);
+	if (rc) {
+		netdev_dbg(netdev, "failed to register netdev rc=%d\n", rc);
 		free_netdev(netdev);
 		return rc;
 	}
 
-	ibmveth_debug_printk("registered\n");
-
-	ibmveth_proc_register_adapter(adapter);
+	netdev_dbg(netdev, "registered\n");
 
 	return 0;
 }
@@ -1347,114 +1463,23 @@
 	struct ibmveth_adapter *adapter = netdev_priv(netdev);
 	int i;
 
-	for(i = 0; i<IbmVethNumBufferPools; i++)
+	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
 		kobject_put(&adapter->rx_buff_pool[i].kobj);
 
 	unregister_netdev(netdev);
 
-	ibmveth_proc_unregister_adapter(adapter);
-
 	free_netdev(netdev);
 	dev_set_drvdata(&dev->dev, NULL);
 
 	return 0;
 }
 
-#ifdef CONFIG_PROC_FS
-static void ibmveth_proc_register_driver(void)
-{
-	ibmveth_proc_dir = proc_mkdir(IBMVETH_PROC_DIR, init_net.proc_net);
-	if (ibmveth_proc_dir) {
-	}
-}
-
-static void ibmveth_proc_unregister_driver(void)
-{
-	remove_proc_entry(IBMVETH_PROC_DIR, init_net.proc_net);
-}
-
-static int ibmveth_show(struct seq_file *seq, void *v)
-{
-	struct ibmveth_adapter *adapter = seq->private;
-	char *current_mac = (char *) adapter->netdev->dev_addr;
-	char *firmware_mac = (char *) &adapter->mac_addr;
-
-	seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version);
-
-	seq_printf(seq, "Unit Address:    0x%x\n", adapter->vdev->unit_address);
-	seq_printf(seq, "Current MAC:     %pM\n", current_mac);
-	seq_printf(seq, "Firmware MAC:    %pM\n", firmware_mac);
-
-	seq_printf(seq, "\nAdapter Statistics:\n");
-	seq_printf(seq, "  TX:  vio_map_single failres:      %lld\n", adapter->tx_map_failed);
-	seq_printf(seq, "       send failures:               %lld\n", adapter->tx_send_failed);
-	seq_printf(seq, "  RX:  replenish task cycles:       %lld\n", adapter->replenish_task_cycles);
-	seq_printf(seq, "       alloc_skb_failures:          %lld\n", adapter->replenish_no_mem);
-	seq_printf(seq, "       add buffer failures:         %lld\n", adapter->replenish_add_buff_failure);
-	seq_printf(seq, "       invalid buffers:             %lld\n", adapter->rx_invalid_buffer);
-	seq_printf(seq, "       no buffers:                  %lld\n", adapter->rx_no_buffer);
-
-	return 0;
-}
-
-static int ibmveth_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ibmveth_show, PDE(inode)->data);
-}
-
-static const struct file_operations ibmveth_proc_fops = {
-	.owner	 = THIS_MODULE,
-	.open    = ibmveth_proc_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = single_release,
-};
-
-static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
-{
-	struct proc_dir_entry *entry;
-	if (ibmveth_proc_dir) {
-		char u_addr[10];
-		sprintf(u_addr, "%x", adapter->vdev->unit_address);
-		entry = proc_create_data(u_addr, S_IFREG, ibmveth_proc_dir,
-					 &ibmveth_proc_fops, adapter);
-		if (!entry)
-			ibmveth_error_printk("Cannot create adapter proc entry");
-	}
-}
-
-static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter)
-{
-	if (ibmveth_proc_dir) {
-		char u_addr[10];
-		sprintf(u_addr, "%x", adapter->vdev->unit_address);
-		remove_proc_entry(u_addr, ibmveth_proc_dir);
-	}
-}
-
-#else /* CONFIG_PROC_FS */
-static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
-{
-}
-
-static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter)
-{
-}
-static void ibmveth_proc_register_driver(void)
-{
-}
-
-static void ibmveth_proc_unregister_driver(void)
-{
-}
-#endif /* CONFIG_PROC_FS */
-
 static struct attribute veth_active_attr;
 static struct attribute veth_num_attr;
 static struct attribute veth_size_attr;
 
-static ssize_t veth_pool_show(struct kobject * kobj,
-                              struct attribute * attr, char * buf)
+static ssize_t veth_pool_show(struct kobject *kobj,
+			      struct attribute *attr, char *buf)
 {
 	struct ibmveth_buff_pool *pool = container_of(kobj,
 						      struct ibmveth_buff_pool,
@@ -1469,8 +1494,8 @@
 	return 0;
 }
 
-static ssize_t veth_pool_store(struct kobject * kobj, struct attribute * attr,
-const char * buf, size_t count)
+static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr,
+			       const char *buf, size_t count)
 {
 	struct ibmveth_buff_pool *pool = container_of(kobj,
 						      struct ibmveth_buff_pool,
@@ -1484,8 +1509,9 @@
 	if (attr == &veth_active_attr) {
 		if (value && !pool->active) {
 			if (netif_running(netdev)) {
-				if(ibmveth_alloc_buffer_pool(pool)) {
-					ibmveth_error_printk("unable to alloc pool\n");
+				if (ibmveth_alloc_buffer_pool(pool)) {
+					netdev_err(netdev,
+						   "unable to alloc pool\n");
 					return -ENOMEM;
 				}
 				pool->active = 1;
@@ -1494,14 +1520,15 @@
 				adapter->pool_config = 0;
 				if ((rc = ibmveth_open(netdev)))
 					return rc;
-			} else
+			} else {
 				pool->active = 1;
+			}
 		} else if (!value && pool->active) {
 			int mtu = netdev->mtu + IBMVETH_BUFF_OH;
 			int i;
 			/* Make sure there is a buffer pool with buffers that
 			   can hold a packet of the size of the MTU */
-			for (i = 0; i < IbmVethNumBufferPools; i++) {
+			for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
 				if (pool == &adapter->rx_buff_pool[i])
 					continue;
 				if (!adapter->rx_buff_pool[i].active)
@@ -1510,8 +1537,8 @@
 					break;
 			}
 
-			if (i == IbmVethNumBufferPools) {
-				ibmveth_error_printk("no active pool >= MTU\n");
+			if (i == IBMVETH_NUM_BUFF_POOLS) {
+				netdev_err(netdev, "no active pool >= MTU\n");
 				return -EPERM;
 			}
 
@@ -1526,9 +1553,9 @@
 			pool->active = 0;
 		}
 	} else if (attr == &veth_num_attr) {
-		if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
+		if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) {
 			return -EINVAL;
-		else {
+		} else {
 			if (netif_running(netdev)) {
 				adapter->pool_config = 1;
 				ibmveth_close(netdev);
@@ -1536,13 +1563,14 @@
 				pool->size = value;
 				if ((rc = ibmveth_open(netdev)))
 					return rc;
-			} else
+			} else {
 				pool->size = value;
+			}
 		}
 	} else if (attr == &veth_size_attr) {
-		if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE)
+		if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE) {
 			return -EINVAL;
-		else {
+		} else {
 			if (netif_running(netdev)) {
 				adapter->pool_config = 1;
 				ibmveth_close(netdev);
@@ -1550,8 +1578,9 @@
 				pool->buff_size = value;
 				if ((rc = ibmveth_open(netdev)))
 					return rc;
-			} else
+			} else {
 				pool->buff_size = value;
+			}
 		}
 	}
 
@@ -1561,16 +1590,16 @@
 }
 
 
-#define ATTR(_name, _mode)      \
-        struct attribute veth_##_name##_attr = {               \
-        .name = __stringify(_name), .mode = _mode, \
-        };
+#define ATTR(_name, _mode)				\
+	struct attribute veth_##_name##_attr = {	\
+	.name = __stringify(_name), .mode = _mode,	\
+	};
 
 static ATTR(active, 0644);
 static ATTR(num, 0644);
 static ATTR(size, 0644);
 
-static struct attribute * veth_pool_attrs[] = {
+static struct attribute *veth_pool_attrs[] = {
 	&veth_active_attr,
 	&veth_num_attr,
 	&veth_size_attr,
@@ -1595,7 +1624,7 @@
 	return 0;
 }
 
-static struct vio_device_id ibmveth_device_table[] __devinitdata= {
+static struct vio_device_id ibmveth_device_table[] __devinitdata = {
 	{ "network", "IBM,l-lan"},
 	{ "", "" }
 };
@@ -1619,9 +1648,8 @@
 
 static int __init ibmveth_module_init(void)
 {
-	ibmveth_printk("%s: %s %s\n", ibmveth_driver_name, ibmveth_driver_string, ibmveth_driver_version);
-
-	ibmveth_proc_register_driver();
+	printk(KERN_DEBUG "%s: %s %s\n", ibmveth_driver_name,
+	       ibmveth_driver_string, ibmveth_driver_version);
 
 	return vio_register_driver(&ibmveth_driver);
 }
@@ -1629,7 +1657,6 @@
 static void __exit ibmveth_module_exit(void)
 {
 	vio_unregister_driver(&ibmveth_driver);
-	ibmveth_proc_unregister_driver();
 }
 
 module_init(ibmveth_module_init);
diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h
index ec76ace..43a794f 100644
--- a/drivers/net/ibmveth.h
+++ b/drivers/net/ibmveth.h
@@ -1,26 +1,28 @@
-/**************************************************************************/
-/*                                                                        */
-/* IBM eServer i/[Series Virtual Ethernet Device Driver                   */
-/* Copyright (C) 2003 IBM Corp.                                           */
-/*  Dave Larson (larson1@us.ibm.com)                                      */
-/*  Santiago Leon (santil@us.ibm.com)                                     */
-/*                                                                        */
-/*  This program is free software; you can redistribute it and/or modify  */
-/*  it under the terms of the GNU General Public License as published by  */
-/*  the Free Software Foundation; either version 2 of the License, or     */
-/*  (at your option) any later version.                                   */
-/*                                                                        */
-/*  This program is distributed in the hope that it will be useful,       */
-/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
-/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
-/*  GNU General Public License for more details.                          */
-/*                                                                        */
-/*  You should have received a copy of the GNU General Public License     */
-/*  along with this program; if not, write to the Free Software           */
-/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  */
-/*                                                                   USA  */
-/*                                                                        */
-/**************************************************************************/
+/*
+ * IBM Power Virtual Ethernet Device 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2003, 2010
+ *
+ * Authors: Dave Larson <larson1@us.ibm.com>
+ *	    Santiago Leon <santil@linux.vnet.ibm.com>
+ *	    Brian King <brking@linux.vnet.ibm.com>
+ *	    Robert Jennings <rcj@linux.vnet.ibm.com>
+ *	    Anton Blanchard <anton@au.ibm.com>
+ */
 
 #ifndef _IBMVETH_H
 #define _IBMVETH_H
@@ -92,17 +94,17 @@
 #define h_change_logical_lan_mac(ua, mac) \
   plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac)
 
-#define IbmVethNumBufferPools 5
+#define IBMVETH_NUM_BUFF_POOLS 5
 #define IBMVETH_IO_ENTITLEMENT_DEFAULT 4243456 /* MTU of 1500 needs 4.2Mb */
 #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */
-#define IBMVETH_MAX_MTU 68
+#define IBMVETH_MIN_MTU 68
 #define IBMVETH_MAX_POOL_COUNT 4096
 #define IBMVETH_BUFF_LIST_SIZE 4096
 #define IBMVETH_FILT_LIST_SIZE 4096
 #define IBMVETH_MAX_BUF_SIZE (1024 * 128)
 
 static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 };
-static int pool_count[] = { 256, 768, 256, 256, 256 };
+static int pool_count[] = { 256, 512, 256, 256, 256 };
 static int pool_active[] = { 1, 1, 0, 0, 0};
 
 #define IBM_VETH_INVALID_MAP ((u16)0xffff)
@@ -142,13 +144,15 @@
     void * filter_list_addr;
     dma_addr_t buffer_list_dma;
     dma_addr_t filter_list_dma;
-    struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools];
+    struct ibmveth_buff_pool rx_buff_pool[IBMVETH_NUM_BUFF_POOLS];
     struct ibmveth_rx_q rx_queue;
     int pool_config;
     int rx_csum;
     void *bounce_buffer;
     dma_addr_t bounce_buffer_dma;
 
+    u64 fw_ipv6_csum_support;
+    u64 fw_ipv4_csum_support;
     /* adapter specific stats */
     u64 replenish_task_cycles;
     u64 replenish_no_mem;
@@ -158,7 +162,6 @@
     u64 rx_no_buffer;
     u64 tx_map_failed;
     u64 tx_send_failed;
-    spinlock_t stats_lock;
 };
 
 struct ibmveth_buf_desc_fields {
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index 187622f..bc183f5 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -132,6 +132,8 @@
 	case E1000_DEV_ID_82580_SERDES:
 	case E1000_DEV_ID_82580_SGMII:
 	case E1000_DEV_ID_82580_COPPER_DUAL:
+	case E1000_DEV_ID_DH89XXCC_SGMII:
+	case E1000_DEV_ID_DH89XXCC_SERDES:
 		mac->type = e1000_82580;
 		break;
 	case E1000_DEV_ID_I350_COPPER:
@@ -282,10 +284,18 @@
 
 	/* Verify phy id and set remaining function pointers */
 	switch (phy->id) {
+	case I347AT4_E_PHY_ID:
+	case M88E1112_E_PHY_ID:
 	case M88E1111_I_PHY_ID:
 		phy->type                   = e1000_phy_m88;
 		phy->ops.get_phy_info       = igb_get_phy_info_m88;
-		phy->ops.get_cable_length   = igb_get_cable_length_m88;
+
+		if (phy->id == I347AT4_E_PHY_ID ||
+		    phy->id == M88E1112_E_PHY_ID)
+			phy->ops.get_cable_length = igb_get_cable_length_m88_gen2;
+		else
+			phy->ops.get_cable_length = igb_get_cable_length_m88;
+
 		phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
 		break;
 	case IGP03E1000_E_PHY_ID:
@@ -1058,7 +1068,11 @@
 	}
 	switch (hw->phy.type) {
 	case e1000_phy_m88:
-		ret_val = igb_copper_link_setup_m88(hw);
+		if (hw->phy.id == I347AT4_E_PHY_ID ||
+		    hw->phy.id == M88E1112_E_PHY_ID)
+			ret_val = igb_copper_link_setup_m88_gen2(hw);
+		else
+			ret_val = igb_copper_link_setup_m88(hw);
 		break;
 	case e1000_phy_igp_3:
 		ret_val = igb_copper_link_setup_igp(hw);
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index bbd2ec3..6222279 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -634,6 +634,8 @@
  * E = External
  */
 #define M88E1111_I_PHY_ID    0x01410CC0
+#define M88E1112_E_PHY_ID    0x01410C90
+#define I347AT4_E_PHY_ID     0x01410DC0
 #define IGP03E1000_E_PHY_ID  0x02A80390
 #define I82580_I_PHY_ID      0x015403A0
 #define I350_I_PHY_ID        0x015403B0
@@ -702,6 +704,35 @@
 #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X    0x0100
 #define M88E1000_EPSCR_TX_CLK_25      0x0070 /* 25  MHz TX_CLK */
 
+/* Intel i347-AT4 Registers */
+
+#define I347AT4_PCDL                   0x10 /* PHY Cable Diagnostics Length */
+#define I347AT4_PCDC                   0x15 /* PHY Cable Diagnostics Control */
+#define I347AT4_PAGE_SELECT            0x16
+
+/* i347-AT4 Extended PHY Specific Control Register */
+
+/*
+ *  Number of times we will attempt to autonegotiate before downshifting if we
+ *  are the master
+ */
+#define I347AT4_PSCR_DOWNSHIFT_ENABLE 0x0800
+#define I347AT4_PSCR_DOWNSHIFT_MASK   0x7000
+#define I347AT4_PSCR_DOWNSHIFT_1X     0x0000
+#define I347AT4_PSCR_DOWNSHIFT_2X     0x1000
+#define I347AT4_PSCR_DOWNSHIFT_3X     0x2000
+#define I347AT4_PSCR_DOWNSHIFT_4X     0x3000
+#define I347AT4_PSCR_DOWNSHIFT_5X     0x4000
+#define I347AT4_PSCR_DOWNSHIFT_6X     0x5000
+#define I347AT4_PSCR_DOWNSHIFT_7X     0x6000
+#define I347AT4_PSCR_DOWNSHIFT_8X     0x7000
+
+/* i347-AT4 PHY Cable Diagnostics Control */
+#define I347AT4_PCDC_CABLE_LENGTH_UNIT 0x0400 /* 0=cm 1=meters */
+
+/* Marvell 1112 only registers */
+#define M88E1112_VCT_DSP_DISTANCE       0x001A
+
 /* M88EC018 Rev 2 specific DownShift settings */
 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK  0x0E00
 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X    0x0800
diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h
index cb8db78..c0b017f 100644
--- a/drivers/net/igb/e1000_hw.h
+++ b/drivers/net/igb/e1000_hw.h
@@ -54,6 +54,8 @@
 #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_DH89XXCC_SGMII           0x0436
+#define E1000_DEV_ID_DH89XXCC_SERDES          0x0438
 #define E1000_DEV_ID_I350_COPPER              0x1521
 #define E1000_DEV_ID_I350_FIBER               0x1522
 #define E1000_DEV_ID_I350_SERDES              0x1523
diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c
index cf1f323..ddd036a 100644
--- a/drivers/net/igb/e1000_phy.c
+++ b/drivers/net/igb/e1000_phy.c
@@ -570,6 +570,89 @@
 }
 
 /**
+ *  igb_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's.
+ *  Also enables and sets the downshift parameters.
+ **/
+s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 phy_data;
+
+	if (phy->reset_disable) {
+		ret_val = 0;
+		goto out;
+	}
+
+	/* Enable CRS on Tx. This must be set for half-duplex operation. */
+	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+	if (ret_val)
+		goto out;
+
+	/*
+	 * Options:
+	 *   MDI/MDI-X = 0 (default)
+	 *   0 - Auto for all speeds
+	 *   1 - MDI mode
+	 *   2 - MDI-X mode
+	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+	 */
+	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+
+	switch (phy->mdix) {
+	case 1:
+		phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
+		break;
+	case 2:
+		phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
+		break;
+	case 3:
+		/* M88E1112 does not support this mode) */
+		if (phy->id != M88E1112_E_PHY_ID) {
+			phy_data |= M88E1000_PSCR_AUTO_X_1000T;
+			break;
+		}
+	case 0:
+	default:
+		phy_data |= M88E1000_PSCR_AUTO_X_MODE;
+		break;
+	}
+
+	/*
+	 * Options:
+	 *   disable_polarity_correction = 0 (default)
+	 *       Automatic Correction for Reversed Cable Polarity
+	 *   0 - Disabled
+	 *   1 - Enabled
+	 */
+	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+	if (phy->disable_polarity_correction == 1)
+		phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+
+	/* Enable downshift and setting it to X6 */
+	phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK;
+	phy_data |= I347AT4_PSCR_DOWNSHIFT_6X;
+	phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE;
+
+	ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+	if (ret_val)
+		goto out;
+
+	/* Commit the changes. */
+	ret_val = igb_phy_sw_reset(hw);
+	if (ret_val) {
+		hw_dbg("Error committing the PHY changes\n");
+		goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
  *  igb_copper_link_setup_igp - Setup igp PHY's for copper link
  *  @hw: pointer to the HW structure
  *
@@ -1124,18 +1207,25 @@
 			goto out;
 
 		if (!link) {
-			/*
-			 * We didn't get link.
-			 * Reset the DSP and cross our fingers.
-			 */
-			ret_val = phy->ops.write_reg(hw,
-						     M88E1000_PHY_PAGE_SELECT,
-						     0x001d);
-			if (ret_val)
-				goto out;
-			ret_val = igb_phy_reset_dsp(hw);
-			if (ret_val)
-				goto out;
+			if (hw->phy.type != e1000_phy_m88 ||
+			    hw->phy.id == I347AT4_E_PHY_ID ||
+			    hw->phy.id == M88E1112_E_PHY_ID) {
+				hw_dbg("Link taking longer than expected.\n");
+			} else {
+
+				/*
+				 * We didn't get link.
+				 * Reset the DSP and cross our fingers.
+				 */
+				ret_val = phy->ops.write_reg(hw,
+							     M88E1000_PHY_PAGE_SELECT,
+							     0x001d);
+				if (ret_val)
+					goto out;
+				ret_val = igb_phy_reset_dsp(hw);
+				if (ret_val)
+					goto out;
+			}
 		}
 
 		/* Try once more */
@@ -1145,6 +1235,11 @@
 			goto out;
 	}
 
+	if (hw->phy.type != e1000_phy_m88 ||
+	    hw->phy.id == I347AT4_E_PHY_ID ||
+	    hw->phy.id == M88E1112_E_PHY_ID)
+		goto out;
+
 	ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
 	if (ret_val)
 		goto out;
@@ -1557,6 +1652,93 @@
 	return ret_val;
 }
 
+s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 phy_data, phy_data2, index, default_page, is_cm;
+
+	switch (hw->phy.id) {
+	case I347AT4_E_PHY_ID:
+		/* Remember the original page select and set it to 7 */
+		ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
+					    &default_page);
+		if (ret_val)
+			goto out;
+
+		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07);
+		if (ret_val)
+			goto out;
+
+		/* Get cable length from PHY Cable Diagnostics Control Reg */
+		ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr),
+					    &phy_data);
+		if (ret_val)
+			goto out;
+
+		/* Check if the unit of cable length is meters or cm */
+		ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2);
+		if (ret_val)
+			goto out;
+
+		is_cm = !(phy_data & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+		/* Populate the phy structure with cable length in meters */
+		phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+		phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+		phy->cable_length = phy_data / (is_cm ? 100 : 1);
+
+		/* Reset the page selec to its original value */
+		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
+					     default_page);
+		if (ret_val)
+			goto out;
+		break;
+	case M88E1112_E_PHY_ID:
+		/* Remember the original page select and set it to 5 */
+		ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
+					    &default_page);
+		if (ret_val)
+			goto out;
+
+		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05);
+		if (ret_val)
+			goto out;
+
+		ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE,
+					    &phy_data);
+		if (ret_val)
+			goto out;
+
+		index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+			M88E1000_PSSR_CABLE_LENGTH_SHIFT;
+		if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
+			ret_val = -E1000_ERR_PHY;
+			goto out;
+		}
+
+		phy->min_cable_length = e1000_m88_cable_length_table[index];
+		phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
+
+		phy->cable_length = (phy->min_cable_length +
+				     phy->max_cable_length) / 2;
+
+		/* Reset the page select to its original value */
+		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
+					     default_page);
+		if (ret_val)
+			goto out;
+
+		break;
+	default:
+		ret_val = -E1000_ERR_PHY;
+		goto out;
+	}
+
+out:
+	return ret_val;
+}
+
 /**
  *  igb_get_cable_length_igp_2 - Determine cable length for igp2 PHY
  *  @hw: pointer to the HW structure
diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h
index 565a6db..2cc1177 100644
--- a/drivers/net/igb/e1000_phy.h
+++ b/drivers/net/igb/e1000_phy.h
@@ -45,9 +45,11 @@
 s32  igb_check_reset_block(struct e1000_hw *hw);
 s32  igb_copper_link_setup_igp(struct e1000_hw *hw);
 s32  igb_copper_link_setup_m88(struct e1000_hw *hw);
+s32  igb_copper_link_setup_m88_gen2(struct e1000_hw *hw);
 s32  igb_phy_force_speed_duplex_igp(struct e1000_hw *hw);
 s32  igb_phy_force_speed_duplex_m88(struct e1000_hw *hw);
 s32  igb_get_cable_length_m88(struct e1000_hw *hw);
+s32  igb_get_cable_length_m88_gen2(struct e1000_hw *hw);
 s32  igb_get_cable_length_igp_2(struct e1000_hw *hw);
 s32  igb_get_phy_id(struct e1000_hw *hw);
 s32  igb_get_phy_info_igp(struct e1000_hw *hw);
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 6e63d9a..edab9c4 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -143,7 +143,7 @@
 			u16 next_to_watch;
 			unsigned int bytecount;
 			u16 gso_segs;
-			union skb_shared_tx shtx;
+			u8 tx_flags;
 			u8 mapped_as_page;
 		};
 		/* RX */
@@ -159,6 +159,7 @@
 	u64 packets;
 	u64 bytes;
 	u64 restart_queue;
+	u64 restart_queue2;
 };
 
 struct igb_rx_queue_stats {
@@ -210,11 +211,14 @@
 		/* TX */
 		struct {
 			struct igb_tx_queue_stats tx_stats;
+			struct u64_stats_sync tx_syncp;
+			struct u64_stats_sync tx_syncp2;
 			bool detect_tx_hung;
 		};
 		/* RX */
 		struct {
 			struct igb_rx_queue_stats rx_stats;
+			struct u64_stats_sync rx_syncp;
 			u32 rx_buffer_len;
 		};
 	};
@@ -288,6 +292,9 @@
 	struct timecompare compare;
 	struct hwtstamp_config hwtstamp_config;
 
+	spinlock_t stats64_lock;
+	struct rtnl_link_stats64 stats64;
+
 	/* structs defined in e1000_hw.h */
 	struct e1000_hw hw;
 	struct e1000_hw_stats stats;
@@ -357,7 +364,7 @@
 extern void igb_unmap_and_free_tx_resource(struct igb_ring *,
 					   struct igb_buffer *);
 extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
-extern void igb_update_stats(struct igb_adapter *);
+extern void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *);
 extern bool igb_has_link(struct igb_adapter *adapter);
 extern void igb_set_ethtool_ops(struct net_device *);
 extern void igb_power_up_link(struct igb_adapter *);
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 26bf6a1..a70e16b 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -90,8 +90,8 @@
 
 #define IGB_NETDEV_STAT(_net_stat) { \
 	.stat_string = __stringify(_net_stat), \
-	.sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \
-	.stat_offset = offsetof(struct net_device_stats, _net_stat) \
+	.sizeof_stat = FIELD_SIZEOF(struct rtnl_link_stats64, _net_stat), \
+	.stat_offset = offsetof(struct rtnl_link_stats64, _net_stat) \
 }
 static const struct igb_stats igb_gstrings_net_stats[] = {
 	IGB_NETDEV_STAT(rx_errors),
@@ -111,8 +111,9 @@
 	(sizeof(igb_gstrings_net_stats) / sizeof(struct igb_stats))
 #define IGB_RX_QUEUE_STATS_LEN \
 	(sizeof(struct igb_rx_queue_stats) / sizeof(u64))
-#define IGB_TX_QUEUE_STATS_LEN \
-	(sizeof(struct igb_tx_queue_stats) / sizeof(u64))
+
+#define IGB_TX_QUEUE_STATS_LEN 3 /* packets, bytes, restart_queue */
+
 #define IGB_QUEUE_STATS_LEN \
 	((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues * \
 	  IGB_RX_QUEUE_STATS_LEN) + \
@@ -2070,12 +2071,14 @@
 				  struct ethtool_stats *stats, u64 *data)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
-	struct net_device_stats *net_stats = &netdev->stats;
-	u64 *queue_stat;
-	int i, j, k;
+	struct rtnl_link_stats64 *net_stats = &adapter->stats64;
+	unsigned int start;
+	struct igb_ring *ring;
+	int i, j;
 	char *p;
 
-	igb_update_stats(adapter);
+	spin_lock(&adapter->stats64_lock);
+	igb_update_stats(adapter, net_stats);
 
 	for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) {
 		p = (char *)adapter + igb_gstrings_stats[i].stat_offset;
@@ -2088,15 +2091,36 @@
 			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
 	}
 	for (j = 0; j < adapter->num_tx_queues; j++) {
-		queue_stat = (u64 *)&adapter->tx_ring[j]->tx_stats;
-		for (k = 0; k < IGB_TX_QUEUE_STATS_LEN; k++, i++)
-			data[i] = queue_stat[k];
+		u64	restart2;
+
+		ring = adapter->tx_ring[j];
+		do {
+			start = u64_stats_fetch_begin_bh(&ring->tx_syncp);
+			data[i]   = ring->tx_stats.packets;
+			data[i+1] = ring->tx_stats.bytes;
+			data[i+2] = ring->tx_stats.restart_queue;
+		} while (u64_stats_fetch_retry_bh(&ring->tx_syncp, start));
+		do {
+			start = u64_stats_fetch_begin_bh(&ring->tx_syncp2);
+			restart2  = ring->tx_stats.restart_queue2;
+		} while (u64_stats_fetch_retry_bh(&ring->tx_syncp2, start));
+		data[i+2] += restart2;
+
+		i += IGB_TX_QUEUE_STATS_LEN;
 	}
 	for (j = 0; j < adapter->num_rx_queues; j++) {
-		queue_stat = (u64 *)&adapter->rx_ring[j]->rx_stats;
-		for (k = 0; k < IGB_RX_QUEUE_STATS_LEN; k++, i++)
-			data[i] = queue_stat[k];
+		ring = adapter->rx_ring[j];
+		do {
+			start = u64_stats_fetch_begin_bh(&ring->rx_syncp);
+			data[i]   = ring->rx_stats.packets;
+			data[i+1] = ring->rx_stats.bytes;
+			data[i+2] = ring->rx_stats.drops;
+			data[i+3] = ring->rx_stats.csum_err;
+			data[i+4] = ring->rx_stats.alloc_failed;
+		} while (u64_stats_fetch_retry_bh(&ring->rx_syncp, start));
+		i += IGB_RX_QUEUE_STATS_LEN;
 	}
+	spin_unlock(&adapter->stats64_lock);
 }
 
 static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 9b4e589..75155a2 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -71,6 +71,8 @@
 	{ 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 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII), board_82575 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 },
@@ -94,7 +96,6 @@
 static void igb_free_all_tx_resources(struct igb_adapter *);
 static void igb_free_all_rx_resources(struct igb_adapter *);
 static void igb_setup_mrqc(struct igb_adapter *);
-void igb_update_stats(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 int igb_sw_init(struct igb_adapter *);
@@ -111,7 +112,8 @@
 static void igb_watchdog(unsigned long);
 static void igb_watchdog_task(struct work_struct *);
 static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *);
-static struct net_device_stats *igb_get_stats(struct net_device *);
+static struct rtnl_link_stats64 *igb_get_stats64(struct net_device *dev,
+						 struct rtnl_link_stats64 *stats);
 static int igb_change_mtu(struct net_device *, int);
 static int igb_set_mac(struct net_device *, void *);
 static void igb_set_uta(struct igb_adapter *adapter);
@@ -986,7 +988,7 @@
  * Attempt to configure interrupts using the best available
  * capabilities of the hardware and kernel.
  **/
-static void igb_set_interrupt_capability(struct igb_adapter *adapter)
+static int igb_set_interrupt_capability(struct igb_adapter *adapter)
 {
 	int err;
 	int numvecs, i;
@@ -1052,8 +1054,10 @@
 	if (!pci_enable_msi(adapter->pdev))
 		adapter->flags |= IGB_FLAG_HAS_MSI;
 out:
-	/* Notify the stack of the (possibly) reduced Tx Queue count. */
-	adapter->netdev->real_num_tx_queues = adapter->num_tx_queues;
+	/* Notify the stack of the (possibly) reduced queue counts. */
+	netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
+	return netif_set_real_num_rx_queues(adapter->netdev,
+					    adapter->num_rx_queues);
 }
 
 /**
@@ -1152,7 +1156,9 @@
 	struct pci_dev *pdev = adapter->pdev;
 	int err;
 
-	igb_set_interrupt_capability(adapter);
+	err = igb_set_interrupt_capability(adapter);
+	if (err)
+		return err;
 
 	err = igb_alloc_q_vectors(adapter);
 	if (err) {
@@ -1530,7 +1536,9 @@
 	netif_carrier_off(netdev);
 
 	/* record the stats before reset*/
-	igb_update_stats(adapter);
+	spin_lock(&adapter->stats64_lock);
+	igb_update_stats(adapter, &adapter->stats64);
+	spin_unlock(&adapter->stats64_lock);
 
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
@@ -1683,7 +1691,7 @@
 	.ndo_open		= igb_open,
 	.ndo_stop		= igb_close,
 	.ndo_start_xmit		= igb_xmit_frame_adv,
-	.ndo_get_stats		= igb_get_stats,
+	.ndo_get_stats64	= igb_get_stats64,
 	.ndo_set_rx_mode	= igb_set_rx_mode,
 	.ndo_set_multicast_list	= igb_set_rx_mode,
 	.ndo_set_mac_address	= igb_set_mac,
@@ -1856,8 +1864,10 @@
 	netdev->vlan_features |= NETIF_F_IPV6_CSUM;
 	netdev->vlan_features |= NETIF_F_SG;
 
-	if (pci_using_dac)
+	if (pci_using_dac) {
 		netdev->features |= NETIF_F_HIGHDMA;
+		netdev->vlan_features |= NETIF_F_HIGHDMA;
+	}
 
 	if (hw->mac.type >= e1000_82576)
 		netdev->features |= NETIF_F_SCTP_CSUM;
@@ -1888,9 +1898,9 @@
 		goto err_eeprom;
 	}
 
-	setup_timer(&adapter->watchdog_timer, &igb_watchdog,
+	setup_timer(&adapter->watchdog_timer, igb_watchdog,
 	            (unsigned long) adapter);
-	setup_timer(&adapter->phy_info_timer, &igb_update_phy_info,
+	setup_timer(&adapter->phy_info_timer, igb_update_phy_info,
 	            (unsigned long) adapter);
 
 	INIT_WORK(&adapter->reset_task, igb_reset_task);
@@ -2268,6 +2278,7 @@
 	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);
 #ifdef CONFIG_PCI_IOV
 	if (hw->mac.type == e1000_82576)
 		adapter->vfs_allocated_count = (max_vfs > 7) ? 7 : max_vfs;
@@ -3475,7 +3486,9 @@
 		}
 	}
 
-	igb_update_stats(adapter);
+	spin_lock(&adapter->stats64_lock);
+	igb_update_stats(adapter, &adapter->stats64);
+	spin_unlock(&adapter->stats64_lock);
 
 	for (i = 0; i < adapter->num_tx_queues; i++) {
 		struct igb_ring *tx_ring = adapter->tx_ring[i];
@@ -3542,6 +3555,8 @@
 	int new_val = q_vector->itr_val;
 	int avg_wire_size = 0;
 	struct igb_adapter *adapter = q_vector->adapter;
+	struct igb_ring *ring;
+	unsigned int packets;
 
 	/* For non-gigabit speeds, just fix the interrupt rate at 4000
 	 * ints/sec - ITR timer value of 120 ticks.
@@ -3551,16 +3566,21 @@
 		goto set_itr_val;
 	}
 
-	if (q_vector->rx_ring && q_vector->rx_ring->total_packets) {
-		struct igb_ring *ring = q_vector->rx_ring;
-		avg_wire_size = ring->total_bytes / ring->total_packets;
+	ring = q_vector->rx_ring;
+	if (ring) {
+		packets = ACCESS_ONCE(ring->total_packets);
+
+		if (packets)
+			avg_wire_size = ring->total_bytes / packets;
 	}
 
-	if (q_vector->tx_ring && q_vector->tx_ring->total_packets) {
-		struct igb_ring *ring = q_vector->tx_ring;
-		avg_wire_size = max_t(u32, avg_wire_size,
-		                      (ring->total_bytes /
-		                       ring->total_packets));
+	ring = q_vector->tx_ring;
+	if (ring) {
+		packets = ACCESS_ONCE(ring->total_packets);
+
+		if (packets)
+			avg_wire_size = max_t(u32, avg_wire_size,
+			                      ring->total_bytes / packets);
 	}
 
 	/* if avg_wire_size isn't set no work was done */
@@ -3954,7 +3974,7 @@
 	}
 
 	tx_ring->buffer_info[i].skb = skb;
-	tx_ring->buffer_info[i].shtx = skb_shinfo(skb)->tx_flags;
+	tx_ring->buffer_info[i].tx_flags = skb_shinfo(skb)->tx_flags;
 	/* multiply data chunks by size of headers */
 	tx_ring->buffer_info[i].bytecount = ((gso_segs - 1) * hlen) + skb->len;
 	tx_ring->buffer_info[i].gso_segs = gso_segs;
@@ -4069,7 +4089,11 @@
 
 	/* A reprieve! */
 	netif_wake_subqueue(netdev, tx_ring->queue_index);
-	tx_ring->tx_stats.restart_queue++;
+
+	u64_stats_update_begin(&tx_ring->tx_syncp2);
+	tx_ring->tx_stats.restart_queue2++;
+	u64_stats_update_end(&tx_ring->tx_syncp2);
+
 	return 0;
 }
 
@@ -4088,7 +4112,6 @@
 	u32 tx_flags = 0;
 	u16 first;
 	u8 hdr_len = 0;
-	union skb_shared_tx *shtx = skb_tx(skb);
 
 	/* need: 1 descriptor per page,
 	 *       + 2 desc gap to keep tail from touching head,
@@ -4100,12 +4123,12 @@
 		return NETDEV_TX_BUSY;
 	}
 
-	if (unlikely(shtx->hardware)) {
-		shtx->in_progress = 1;
+	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 		tx_flags |= IGB_TX_FLAGS_TSTAMP;
 	}
 
-	if (vlan_tx_tag_present(skb) && adapter->vlgrp) {
+	if (vlan_tx_tag_present(skb)) {
 		tx_flags |= IGB_TX_FLAGS_VLAN;
 		tx_flags |= (vlan_tx_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT);
 	}
@@ -4207,16 +4230,22 @@
 }
 
 /**
- * igb_get_stats - Get System Network Statistics
+ * igb_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 *igb_get_stats(struct net_device *netdev)
+static struct rtnl_link_stats64 *igb_get_stats64(struct net_device *netdev,
+						 struct rtnl_link_stats64 *stats)
 {
-	/* only return the current stats */
-	return &netdev->stats;
+	struct igb_adapter *adapter = netdev_priv(netdev);
+
+	spin_lock(&adapter->stats64_lock);
+	igb_update_stats(adapter, &adapter->stats64);
+	memcpy(stats, &adapter->stats64, sizeof(*stats));
+	spin_unlock(&adapter->stats64_lock);
+
+	return stats;
 }
 
 /**
@@ -4298,15 +4327,17 @@
  * @adapter: board private structure
  **/
 
-void igb_update_stats(struct igb_adapter *adapter)
+void igb_update_stats(struct igb_adapter *adapter,
+		      struct rtnl_link_stats64 *net_stats)
 {
-	struct net_device_stats *net_stats = igb_get_stats(adapter->netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
 	u32 reg, mpc;
 	u16 phy_tmp;
 	int i;
 	u64 bytes, packets;
+	unsigned int start;
+	u64 _bytes, _packets;
 
 #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
 
@@ -4324,10 +4355,17 @@
 	for (i = 0; i < adapter->num_rx_queues; i++) {
 		u32 rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0x0FFF;
 		struct igb_ring *ring = adapter->rx_ring[i];
+
 		ring->rx_stats.drops += rqdpc_tmp;
 		net_stats->rx_fifo_errors += rqdpc_tmp;
-		bytes += ring->rx_stats.bytes;
-		packets += ring->rx_stats.packets;
+
+		do {
+			start = u64_stats_fetch_begin_bh(&ring->rx_syncp);
+			_bytes = ring->rx_stats.bytes;
+			_packets = ring->rx_stats.packets;
+		} while (u64_stats_fetch_retry_bh(&ring->rx_syncp, start));
+		bytes += _bytes;
+		packets += _packets;
 	}
 
 	net_stats->rx_bytes = bytes;
@@ -4337,8 +4375,13 @@
 	packets = 0;
 	for (i = 0; i < adapter->num_tx_queues; i++) {
 		struct igb_ring *ring = adapter->tx_ring[i];
-		bytes += ring->tx_stats.bytes;
-		packets += ring->tx_stats.packets;
+		do {
+			start = u64_stats_fetch_begin_bh(&ring->tx_syncp);
+			_bytes = ring->tx_stats.bytes;
+			_packets = ring->tx_stats.packets;
+		} while (u64_stats_fetch_retry_bh(&ring->tx_syncp, start));
+		bytes += _bytes;
+		packets += _packets;
 	}
 	net_stats->tx_bytes = bytes;
 	net_stats->tx_packets = packets;
@@ -4660,12 +4703,13 @@
 	u32 vmolr = rd32(E1000_VMOLR(vf));
 	struct vf_data_storage *vf_data = &adapter->vf_data[vf];
 
-	vf_data->flags |= ~(IGB_VF_FLAG_UNI_PROMISC |
+	vf_data->flags &= ~(IGB_VF_FLAG_UNI_PROMISC |
 	                    IGB_VF_FLAG_MULTI_PROMISC);
 	vmolr &= ~(E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE | E1000_VMOLR_MPME);
 
 	if (*msgbuf & E1000_VF_SET_PROMISC_MULTICAST) {
 		vmolr |= E1000_VMOLR_MPME;
+		vf_data->flags |= IGB_VF_FLAG_MULTI_PROMISC;
 		*msgbuf &= ~E1000_VF_SET_PROMISC_MULTICAST;
 	} else {
 		/*
@@ -5319,7 +5363,7 @@
 	u64 regval;
 
 	/* if skb does not support hw timestamp or TX stamp not valid exit */
-	if (likely(!buffer_info->shtx.hardware) ||
+	if (likely(!(buffer_info->tx_flags & SKBTX_HW_TSTAMP)) ||
 	    !(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID))
 		return;
 
@@ -5389,7 +5433,10 @@
 		if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
 		    !(test_bit(__IGB_DOWN, &adapter->state))) {
 			netif_wake_subqueue(netdev, tx_ring->queue_index);
+
+			u64_stats_update_begin(&tx_ring->tx_syncp);
 			tx_ring->tx_stats.restart_queue++;
+			u64_stats_update_end(&tx_ring->tx_syncp);
 		}
 	}
 
@@ -5429,9 +5476,11 @@
 	}
 	tx_ring->total_bytes += total_bytes;
 	tx_ring->total_packets += total_packets;
+	u64_stats_update_begin(&tx_ring->tx_syncp);
 	tx_ring->tx_stats.bytes += total_bytes;
 	tx_ring->tx_stats.packets += total_packets;
-	return (count < tx_ring->count);
+	u64_stats_update_end(&tx_ring->tx_syncp);
+	return count < tx_ring->count;
 }
 
 /**
@@ -5456,7 +5505,7 @@
 static inline void igb_rx_checksum_adv(struct igb_ring *ring,
 				       u32 status_err, struct sk_buff *skb)
 {
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 
 	/* Ignore Checksum bit is set or checksum is disabled through ethtool */
 	if (!(ring->flags & IGB_RING_FLAG_RX_CSUM) ||
@@ -5472,9 +5521,11 @@
 		 * packets, (aka let the stack check the crc32c)
 		 */
 		if ((skb->len == 60) &&
-		    (ring->flags & IGB_RING_FLAG_RX_SCTP_CSUM))
+		    (ring->flags & IGB_RING_FLAG_RX_SCTP_CSUM)) {
+			u64_stats_update_begin(&ring->rx_syncp);
 			ring->rx_stats.csum_err++;
-
+			u64_stats_update_end(&ring->rx_syncp);
+		}
 		/* let the stack verify checksum errors */
 		return;
 	}
@@ -5500,7 +5551,7 @@
 	 * values must belong to this one here and therefore we don't need to
 	 * compare any of the additional attributes stored for it.
 	 *
-	 * If nothing went wrong, then it should have a skb_shared_tx that we
+	 * If nothing went wrong, then it should have a shared tx_flags that we
 	 * can turn into a skb_shared_hwtstamps.
 	 */
 	if (staterr & E1000_RXDADV_STAT_TSIP) {
@@ -5661,8 +5712,10 @@
 
 	rx_ring->total_packets += total_packets;
 	rx_ring->total_bytes += total_bytes;
+	u64_stats_update_begin(&rx_ring->rx_syncp);
 	rx_ring->rx_stats.packets += total_packets;
 	rx_ring->rx_stats.bytes += total_bytes;
+	u64_stats_update_end(&rx_ring->rx_syncp);
 	return cleaned;
 }
 
@@ -5690,8 +5743,10 @@
 		if ((bufsz < IGB_RXBUFFER_1024) && !buffer_info->page_dma) {
 			if (!buffer_info->page) {
 				buffer_info->page = netdev_alloc_page(netdev);
-				if (!buffer_info->page) {
+				if (unlikely(!buffer_info->page)) {
+					u64_stats_update_begin(&rx_ring->rx_syncp);
 					rx_ring->rx_stats.alloc_failed++;
+					u64_stats_update_end(&rx_ring->rx_syncp);
 					goto no_buffers;
 				}
 				buffer_info->page_offset = 0;
@@ -5706,7 +5761,9 @@
 			if (dma_mapping_error(rx_ring->dev,
 					      buffer_info->page_dma)) {
 				buffer_info->page_dma = 0;
+				u64_stats_update_begin(&rx_ring->rx_syncp);
 				rx_ring->rx_stats.alloc_failed++;
+				u64_stats_update_end(&rx_ring->rx_syncp);
 				goto no_buffers;
 			}
 		}
@@ -5714,8 +5771,10 @@
 		skb = buffer_info->skb;
 		if (!skb) {
 			skb = netdev_alloc_skb_ip_align(netdev, bufsz);
-			if (!skb) {
+			if (unlikely(!skb)) {
+				u64_stats_update_begin(&rx_ring->rx_syncp);
 				rx_ring->rx_stats.alloc_failed++;
+				u64_stats_update_end(&rx_ring->rx_syncp);
 				goto no_buffers;
 			}
 
@@ -5729,7 +5788,9 @@
 			if (dma_mapping_error(rx_ring->dev,
 					      buffer_info->dma)) {
 				buffer_info->dma = 0;
+				u64_stats_update_begin(&rx_ring->rx_syncp);
 				rx_ring->rx_stats.alloc_failed++;
+				u64_stats_update_end(&rx_ring->rx_syncp);
 				goto no_buffers;
 			}
 		}
@@ -6092,7 +6153,7 @@
 
 	if (adapter->vlgrp) {
 		u16 vid;
-		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+		for (vid = 0; vid < VLAN_N_VID; vid++) {
 			if (!vlan_group_get_device(adapter->vlgrp, vid))
 				continue;
 			igb_vlan_rx_add_vid(adapter->netdev, vid);
@@ -6107,6 +6168,13 @@
 
 	mac->autoneg = 0;
 
+	/* Fiber NIC's only allow 1000 Gbps Full duplex */
+	if ((adapter->hw.phy.media_type == e1000_media_type_internal_serdes) &&
+		spddplx != (SPEED_1000 + DUPLEX_FULL)) {
+		dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n");
+		return -EINVAL;
+	}
+
 	switch (spddplx) {
 	case SPEED_10 + DUPLEX_HALF:
 		mac->forced_speed_duplex = ADVERTISE_10_HALF;
diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c
index 103b3aa..33add70 100644
--- a/drivers/net/igbvf/ethtool.c
+++ b/drivers/net/igbvf/ethtool.c
@@ -153,7 +153,7 @@
 
 static u32 igbvf_get_tx_csum(struct net_device *netdev)
 {
-	return ((netdev->features & NETIF_F_IP_CSUM) != 0);
+	return (netdev->features & NETIF_F_IP_CSUM) != 0;
 }
 
 static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index c539f7c..ebfaa68 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -41,14 +41,12 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
-#include <linux/pm_qos_params.h>
 
 #include "igbvf.h"
 
 #define DRV_VERSION "1.0.0-k0"
 char igbvf_driver_name[] = "igbvf";
 const char igbvf_driver_version[] = DRV_VERSION;
-static struct pm_qos_request_list igbvf_driver_pm_qos_req;
 static const char igbvf_driver_string[] =
 				"Intel(R) Virtual Function Network Driver";
 static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
@@ -103,7 +101,7 @@
 static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
                                          u32 status_err, struct sk_buff *skb)
 {
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 
 	/* Ignore Checksum bit is set or checksum is disabled through ethtool */
 	if ((status_err & E1000_RXD_STAT_IXSM) ||
@@ -845,7 +843,7 @@
 	}
 	adapter->net_stats.tx_bytes += total_bytes;
 	adapter->net_stats.tx_packets += total_packets;
-	return (count < tx_ring->count);
+	return count < tx_ring->count;
 }
 
 static irqreturn_t igbvf_msix_other(int irq, void *data)
@@ -1256,7 +1254,7 @@
 	if (!adapter->vlgrp)
 		return;
 
-	for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+	for (vid = 0; vid < VLAN_N_VID; vid++) {
 		if (!vlan_group_get_device(adapter->vlgrp, vid))
 			continue;
 		igbvf_vlan_rx_add_vid(adapter->netdev, vid);
@@ -2904,8 +2902,6 @@
 	printk(KERN_INFO "%s\n", igbvf_copyright);
 
 	ret = pci_register_driver(&igbvf_driver);
-	pm_qos_add_request(&igbvf_driver_pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
-			   PM_QOS_DEFAULT_VALUE);
 
 	return ret;
 }
@@ -2920,7 +2916,6 @@
 static void __exit igbvf_exit_module(void)
 {
 	pci_unregister_driver(&igbvf_driver);
-	pm_qos_remove_request(&igbvf_driver_pm_qos_req);
 }
 module_exit(igbvf_exit_module);
 
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 0b3f6df..c8ee8d2 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -827,7 +827,7 @@
 {
 	ip->ioc3_timer.expires = jiffies + (12 * HZ)/10;  /* 1.2 sec. */
 	ip->ioc3_timer.data = (unsigned long) ip;
-	ip->ioc3_timer.function = &ioc3_timer;
+	ip->ioc3_timer.function = ioc3_timer;
 	add_timer(&ip->ioc3_timer);
 }
 
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 72e3d2d..dc01980 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -1213,7 +1213,7 @@
 
 	skb_put(skb, framelen);
 	skb->protocol = eth_type_trans(skb, dev);
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 	netif_rx(skb);
 	sp->rx_buff[entry] = NULL;
 }
@@ -1278,7 +1278,7 @@
 				jumbo->skb->protocol =
 				    eth_type_trans(jumbo->skb, dev);
 
-				jumbo->skb->ip_summed = CHECKSUM_NONE;
+				skb_checksum_none_assert(jumbo->skb);
 				netif_rx(jumbo->skb);
 			}
 		}
@@ -1476,7 +1476,7 @@
 			 * IP/TCP/UDP frame was received. Let the
 			 * upper layer decide.
 			 */
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
 
 			/* Hand off frame for higher layer processing.
 			 * The function netif_rx() releases the sk_buff
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 48bd5ec..b626ccc 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -217,7 +217,7 @@
   for (i = 0; i < len; ++i)
     fcs.value = irda_fcs (fcs.value, *(buf++));
 
-  return (fcs.value == GOOD_FCS);
+  return fcs.value == GOOD_FCS;
 }
 
 /***********************************************************************/
@@ -759,7 +759,7 @@
   if (fir)
     {
       memset (buf, 0, TT_LEN);
-      return (TT_LEN);
+      return TT_LEN;
     }
 
   fcs.value = INIT_FCS;
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 4441fa3..e4ea619 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1124,11 +1124,11 @@
                  * The actual image starts after the "STMP" keyword
                  * so forward to the firmware header tag
                  */
-                for (i = 0; (fw->data[i] != STIR421X_PATCH_END_OF_HDR_TAG) &&
-			     (i < fw->size); i++) ;
+                for (i = 0; i < fw->size && fw->data[i] !=
+			     STIR421X_PATCH_END_OF_HDR_TAG; i++) ;
                 /* here we check for the out of buffer case */
-                if ((STIR421X_PATCH_END_OF_HDR_TAG == fw->data[i]) &&
-                    (i < STIR421X_PATCH_CODE_OFFSET)) {
+                if (i < STIR421X_PATCH_CODE_OFFSET && i < fw->size &&
+				STIR421X_PATCH_END_OF_HDR_TAG == fw->data[i]) {
                         if (!memcmp(fw->data + i + 1, STIR421X_PATCH_STMP_TAG,
                                     sizeof(STIR421X_PATCH_STMP_TAG) - 1)) {
 
@@ -1514,7 +1514,7 @@
 	IRDA_DEBUG(0, "%s(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n",
 		__func__, self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, self->bulk_int_ep);
 
-	return((self->bulk_in_ep != 0) && (self->bulk_out_ep != 0));
+	return (self->bulk_in_ep != 0) && (self->bulk_out_ep != 0);
 }
 
 #ifdef IU_DUMP_CLASS_DESC
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
index 5b1036a..74b20f1 100644
--- a/drivers/net/irda/mcs7780.c
+++ b/drivers/net/irda/mcs7780.c
@@ -734,7 +734,7 @@
 	}
 
 	if (!mcs_setup_urbs(mcs))
-	goto error3;
+		goto error3;
 
 	ret = mcs_receive_start(mcs);
 	if (ret)
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index e30cdbb..559fe85 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -1348,7 +1348,7 @@
 	outb(bank, iobase+BSR);
 
 	/* Make sure interrupt handlers keep the proper interrupt mask */
-	return(ier);
+	return ier;
 }
 
 /*
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index 1b051da..efe05bb 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -336,7 +336,7 @@
 	if (!atomic_read(&dev->enable_rx))
 		return 0;
 
-	return (dev->rx_buff.state != OUTSIDE_FRAME);
+	return dev->rx_buff.state != OUTSIDE_FRAME;
 }
 
 int sirdev_set_dongle(struct sir_dev *dev, IRDA_DONGLE type)
@@ -909,7 +909,7 @@
 	dev->tx_skb = NULL;
 
 	spin_lock_init(&dev->tx_lock);
-	init_MUTEX(&dev->fsm.sem);
+	sema_init(&dev->fsm.sem, 1);
 
 	dev->drv = drv;
 	dev->netdev = ndev;
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 850ca1c..8c57bfb 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -2051,7 +2051,7 @@
  */
 static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self)
 {
-	return (self->rx_buff.state != OUTSIDE_FRAME);
+	return self->rx_buff.state != OUTSIDE_FRAME;
 }
 
 
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index e5698fa..41c96b3 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -219,7 +219,7 @@
 
 static inline int isfir(u32 speed)
 {
-	return (speed == 4000000);
+	return speed == 4000000;
 }
 
 /*
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index b0a6cd8..67c0ad4 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -1182,12 +1182,13 @@
 
 		skb = dev_alloc_skb(len + 1 - 4);
 		/*
-		 * if frame size,data ptr,or skb ptr are wrong ,the get next
+		 * if frame size, data ptr, or skb ptr are wrong, then get next
 		 * entry.
 		 */
 		if ((skb == NULL) || (skb->data == NULL) ||
 		    (self->rx_buff.data == NULL) || (len < 6)) {
 			self->netdev->stats.rx_dropped++;
+			kfree_skb(skb);
 			return TRUE;
 		}
 		skb_reserve(skb, 1);
diff --git a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h
index 5a84822..c6f5848 100644
--- a/drivers/net/irda/via-ircc.h
+++ b/drivers/net/irda/via-ircc.h
@@ -238,7 +238,7 @@
 
 static __u8 ReadReg(unsigned int BaseAddr, int iRegNum)
 {
-	return ((__u8) inb(BaseAddr + iRegNum));
+	return (__u8) inb(BaseAddr + iRegNum);
 }
 
 static void WriteReg(unsigned int BaseAddr, int iRegNum, unsigned char iVal)
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index 3f24a1f3..d66fab8 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -595,7 +595,7 @@
 
 static inline int rd_is_active(struct ring_descr *rd)
 {
-	return ((rd->hw->rd_status & RD_ACTIVE) != 0);
+	return (rd->hw->rd_status & RD_ACTIVE) != 0;
 }
 
 static inline void rd_activate(struct ring_descr *rd)
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index ba1de59..8df645e 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -1524,7 +1524,7 @@
 
 		skb_put(skb, length);
 		skb->protocol = eth_type_trans(skb, dev);
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 		netif_rx(skb);	/* send it up */
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += length;
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
index 813993f..c982ab9 100644
--- a/drivers/net/ixgb/ixgb_ee.c
+++ b/drivers/net/ixgb/ixgb_ee.c
@@ -296,12 +296,12 @@
 		eecd_reg = IXGB_READ_REG(hw, EECD);
 
 		if (eecd_reg & IXGB_EECD_DO)
-			return (true);
+			return true;
 
 		udelay(50);
 	}
 	ASSERT(0);
-	return (false);
+	return false;
 }
 
 /******************************************************************************
@@ -327,9 +327,9 @@
 		checksum += ixgb_read_eeprom(hw, i);
 
 	if (checksum == (u16) EEPROM_SUM)
-		return (true);
+		return true;
 	else
-		return (false);
+		return false;
 }
 
 /******************************************************************************
@@ -439,7 +439,7 @@
 	/*  End this read operation  */
 	ixgb_standby_eeprom(hw);
 
-	return (data);
+	return data;
 }
 
 /******************************************************************************
@@ -476,16 +476,16 @@
 		/* clear the init_ctrl_reg_1 to signify that the cache is
 		 * invalidated */
 		ee_map->init_ctrl_reg_1 = cpu_to_le16(EEPROM_ICW1_SIGNATURE_CLEAR);
-		return (false);
+		return false;
 	}
 
 	if ((ee_map->init_ctrl_reg_1 & cpu_to_le16(EEPROM_ICW1_SIGNATURE_MASK))
 		 != cpu_to_le16(EEPROM_ICW1_SIGNATURE_VALID)) {
 		pr_debug("Signature invalid\n");
-		return(false);
+		return false;
 	}
 
-	return(true);
+	return true;
 }
 
 /******************************************************************************
@@ -505,7 +505,7 @@
 
 	if ((ee_map->init_ctrl_reg_1 & cpu_to_le16(EEPROM_ICW1_SIGNATURE_MASK))
 	    == cpu_to_le16(EEPROM_ICW1_SIGNATURE_VALID)) {
-		return (true);
+		return true;
 	} else {
 		return ixgb_get_eeprom_data(hw);
 	}
@@ -526,10 +526,10 @@
 
 	if ((index < IXGB_EEPROM_SIZE) &&
 		(ixgb_check_and_get_eeprom_data(hw) == true)) {
-	   return(hw->eeprom[index]);
+	   return hw->eeprom[index];
 	}
 
-	return(0);
+	return 0;
 }
 
 /******************************************************************************
@@ -570,10 +570,10 @@
 ixgb_get_ee_pba_number(struct ixgb_hw *hw)
 {
 	if (ixgb_check_and_get_eeprom_data(hw) == true)
-		return (le16_to_cpu(hw->eeprom[EEPROM_PBA_1_2_REG])
-			| (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG])<<16));
+		return le16_to_cpu(hw->eeprom[EEPROM_PBA_1_2_REG])
+			| (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG])<<16);
 
-	return(0);
+	return 0;
 }
 
 
@@ -591,8 +591,8 @@
 	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
 
 	if (ixgb_check_and_get_eeprom_data(hw) == true)
-		return (le16_to_cpu(ee_map->device_id));
+		return le16_to_cpu(ee_map->device_id);
 
-	return (0);
+	return 0;
 }
 
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index a4ed96c..43994c1 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -410,7 +410,7 @@
 ixgb_get_eeprom_len(struct net_device *netdev)
 {
 	/* return size in bytes */
-	return (IXGB_EEPROM_SIZE << 1);
+	return IXGB_EEPROM_SIZE << 1;
 }
 
 static int
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
index 397acab..6cb2e42 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -167,7 +167,7 @@
 	/* Clear any pending interrupt events. */
 	icr_reg = IXGB_READ_REG(hw, ICR);
 
-	return (ctrl_reg & IXGB_CTRL0_RST);
+	return ctrl_reg & IXGB_CTRL0_RST;
 }
 
 
@@ -209,7 +209,7 @@
 		xpak_vendor = ixgb_xpak_vendor_infineon;
 	}
 
-	return (xpak_vendor);
+	return xpak_vendor;
 }
 
 /******************************************************************************
@@ -273,7 +273,7 @@
 	if (hw->subsystem_vendor_id == SUN_SUBVENDOR_ID)
 		phy_type = ixgb_phy_type_bcm;
 
-	return (phy_type);
+	return phy_type;
 }
 
 /******************************************************************************
@@ -366,7 +366,7 @@
 	/* 82597EX errata: Call check-for-link in case lane deskew is locked */
 	ixgb_check_for_link(hw);
 
-	return (status);
+	return status;
 }
 
 /******************************************************************************
@@ -531,7 +531,7 @@
 	}
 
 	hash_value &= 0xFFF;
-	return (hash_value);
+	return hash_value;
 }
 
 /******************************************************************************
@@ -715,7 +715,7 @@
 		}
 		IXGB_WRITE_REG(hw, FCRTH, hw->fc.high_water);
 	}
-	return (status);
+	return status;
 }
 
 /******************************************************************************
@@ -1140,7 +1140,7 @@
 		pr_debug("MAC address is all zeros\n");
 		is_valid = false;
 	}
-	return (is_valid);
+	return is_valid;
 }
 
 /******************************************************************************
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 45fc89b..666207a 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -446,8 +446,10 @@
 			   NETIF_F_HW_VLAN_FILTER;
 	netdev->features |= NETIF_F_TSO;
 
-	if (pci_using_dac)
+	if (pci_using_dac) {
 		netdev->features |= NETIF_F_HIGHDMA;
+		netdev->vlan_features |= NETIF_F_HIGHDMA;
+	}
 
 	/* make sure the EEPROM is good */
 
@@ -470,7 +472,7 @@
 	adapter->part_num = ixgb_get_ee_pba_number(&adapter->hw);
 
 	init_timer(&adapter->watchdog_timer);
-	adapter->watchdog_timer.function = &ixgb_watchdog;
+	adapter->watchdog_timer.function = ixgb_watchdog;
 	adapter->watchdog_timer.data = (unsigned long)adapter;
 
 	INIT_WORK(&adapter->tx_timeout_task, ixgb_tx_timeout_task);
@@ -1905,7 +1907,7 @@
 	 */
 	if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
 	   (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 		return;
 	}
 
@@ -1913,7 +1915,7 @@
 	/* now look at the TCP checksum error bit */
 	if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
 		/* let the stack verify checksum errors */
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 		adapter->hw_csum_rx_error++;
 	} else {
 		/* TCP checksum is good */
@@ -2221,7 +2223,7 @@
 
 	if (adapter->vlgrp) {
 		u16 vid;
-		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; 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);
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 9e15eb9..ed8703c 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -28,10 +28,13 @@
 #ifndef _IXGBE_H_
 #define _IXGBE_H_
 
+#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/cpumask.h>
 #include <linux/aer.h>
+#include <linux/if_vlan.h>
 
 #include "ixgbe_type.h"
 #include "ixgbe_common.h"
@@ -69,15 +72,20 @@
 #define IXGBE_MAX_FCPAUSE		 0xFFFF
 
 /* Supported Rx Buffer Sizes */
-#define IXGBE_RXBUFFER_64    64     /* Used for packet split */
-#define IXGBE_RXBUFFER_128   128    /* Used for packet split */
-#define IXGBE_RXBUFFER_256   256    /* Used for packet split */
+#define IXGBE_RXBUFFER_512   512    /* Used for packet split */
 #define IXGBE_RXBUFFER_2048  2048
 #define IXGBE_RXBUFFER_4096  4096
 #define IXGBE_RXBUFFER_8192  8192
 #define IXGBE_MAX_RXBUFFER   16384  /* largest size for a single descriptor */
 
-#define IXGBE_RX_HDR_SIZE IXGBE_RXBUFFER_256
+/*
+ * NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN mans we
+ * reserve 2 more, and skb_shared_info adds an additional 384 bytes more,
+ * this adds up to 512 bytes of extra data meaning the smallest allocation
+ * we could have is 1K.
+ * i.e. RXBUFFER_512 --> size-1024 slab
+ */
+#define IXGBE_RX_HDR_SIZE IXGBE_RXBUFFER_512
 
 #define MAXIMUM_ETHERNET_VLAN_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)
 
@@ -174,8 +182,9 @@
 					 */
 
 	struct ixgbe_queue_stats stats;
-	unsigned long reinit_state;
+	struct u64_stats_sync syncp;
 	int numa_node;
+	unsigned long reinit_state;
 	u64 rsc_count;			/* stat for coalesced packets */
 	u64 rsc_flush;			/* stats for flushed packets */
 	u32 restart_queue;		/* track tx queue restarts */
@@ -236,6 +245,7 @@
 	u8 tx_itr;
 	u8 rx_itr;
 	u32 eitr;
+	cpumask_var_t affinity_mask;
 };
 
 /* Helper macros to switch between ints/sec and what the register uses.
@@ -251,11 +261,11 @@
 	(R)->next_to_clean - (R)->next_to_use - 1)
 
 #define IXGBE_RX_DESC_ADV(R, i)	    \
-	(&(((union ixgbe_adv_rx_desc *)((R).desc))[i]))
+	(&(((union ixgbe_adv_rx_desc *)((R)->desc))[i]))
 #define IXGBE_TX_DESC_ADV(R, i)	    \
-	(&(((union ixgbe_adv_tx_desc *)((R).desc))[i]))
+	(&(((union ixgbe_adv_tx_desc *)((R)->desc))[i]))
 #define IXGBE_TX_CTXTDESC_ADV(R, i)	    \
-	(&(((struct ixgbe_adv_tx_context_desc *)((R).desc))[i]))
+	(&(((struct ixgbe_adv_tx_context_desc *)((R)->desc))[i]))
 
 #define IXGBE_MAX_JUMBO_FRAME_SIZE        16128
 #ifdef IXGBE_FCOE
@@ -280,7 +290,7 @@
 /* board specific private data structure */
 struct ixgbe_adapter {
 	struct timer_list watchdog_timer;
-	struct vlan_group *vlgrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	u16 bd_number;
 	struct work_struct reset_task;
 	struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
@@ -448,9 +458,20 @@
 extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
 extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
 extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
+extern void ixgbe_configure_rx_ring(struct ixgbe_adapter *,struct ixgbe_ring *);
+extern void ixgbe_configure_tx_ring(struct ixgbe_adapter *,struct ixgbe_ring *);
 extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
 extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
 extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
+extern netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *,
+					 struct net_device *,
+					 struct ixgbe_adapter *,
+					 struct ixgbe_ring *);
+extern void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *,
+                                             struct ixgbe_tx_buffer *);
+extern void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
+                                   struct ixgbe_ring *rx_ring,
+                                   int cleaned_count);
 extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
 extern int ethtool_ioctl(struct ifreq *ifr);
 extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index 3e06a61..0bd8fbb 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -39,20 +39,20 @@
 #define IXGBE_82599_MC_TBL_SIZE   128
 #define IXGBE_82599_VFT_TBL_SIZE  128
 
-void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
-void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
-void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
-s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
-                                          ixgbe_link_speed speed,
-                                          bool autoneg,
-                                          bool autoneg_wait_to_complete);
+static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
+static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
+static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
+static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
+						 ixgbe_link_speed speed,
+						 bool autoneg,
+						 bool autoneg_wait_to_complete);
 static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
                                            ixgbe_link_speed speed,
                                            bool autoneg,
                                            bool autoneg_wait_to_complete);
-s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
-                               bool autoneg_wait_to_complete);
-s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
+				      bool autoneg_wait_to_complete);
+static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
                                ixgbe_link_speed speed,
                                bool autoneg,
                                bool autoneg_wait_to_complete);
@@ -369,7 +369,7 @@
  *  Configures link settings based on values in the ixgbe_hw struct.
  *  Restarts the link.  Performs autonegotiation if needed.
  **/
-s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
                                bool autoneg_wait_to_complete)
 {
 	u32 autoc_reg;
@@ -418,7 +418,7 @@
   *  PHY states.  This includes selectively shutting down the Tx
   *  laser on the PHY, effectively halting physical link.
   **/
-void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
+static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
 
@@ -437,7 +437,7 @@
  *  PHY states.  This includes selectively turning on the Tx
  *  laser on the PHY, effectively starting physical link.
  **/
-void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
+static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
 
@@ -460,7 +460,7 @@
  *  end.  This is consistent with true clause 37 autoneg, which also
  *  involves a loss of signal.
  **/
-void ixgbe_flap_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");
 
@@ -729,7 +729,7 @@
  *
  *  Set the link speed in the AUTOC register and restarts link.
  **/
-s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
                                ixgbe_link_speed speed, bool autoneg,
                                bool autoneg_wait_to_complete)
 {
@@ -1415,92 +1415,6 @@
 }
 
 /**
- *  ixgbe_atr_set_src_ipv6_82599 - Sets the source IPv6 address
- *  @input: input stream to modify
- *  @src_addr_1: the first 4 bytes of the IP address to load
- *  @src_addr_2: the second 4 bytes of the IP address to load
- *  @src_addr_3: the third 4 bytes of the IP address to load
- *  @src_addr_4: the fourth 4 bytes of the IP address to load
- **/
-s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input,
-                                 u32 src_addr_1, u32 src_addr_2,
-                                 u32 src_addr_3, u32 src_addr_4)
-{
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] =
-	                                               (src_addr_4 >> 8) & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] =
-	                                              (src_addr_4 >> 16) & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] = src_addr_4 >> 24;
-
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4] = src_addr_3 & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] =
-	                                               (src_addr_3 >> 8) & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] =
-	                                              (src_addr_3 >> 16) & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] = src_addr_3 >> 24;
-
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8] = src_addr_2 & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] =
-	                                               (src_addr_2 >> 8) & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] =
-	                                              (src_addr_2 >> 16) & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] = src_addr_2 >> 24;
-
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12] = src_addr_1 & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] =
-	                                               (src_addr_1 >> 8) & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] =
-	                                              (src_addr_1 >> 16) & 0xff;
-	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] = src_addr_1 >> 24;
-
-	return 0;
-}
-
-/**
- *  ixgbe_atr_set_dst_ipv6_82599 - Sets the destination IPv6 address
- *  @input: input stream to modify
- *  @dst_addr_1: the first 4 bytes of the IP address to load
- *  @dst_addr_2: the second 4 bytes of the IP address to load
- *  @dst_addr_3: the third 4 bytes of the IP address to load
- *  @dst_addr_4: the fourth 4 bytes of the IP address to load
- **/
-s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input,
-                                 u32 dst_addr_1, u32 dst_addr_2,
-                                 u32 dst_addr_3, u32 dst_addr_4)
-{
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] =
-	                                               (dst_addr_4 >> 8) & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] =
-	                                              (dst_addr_4 >> 16) & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] = dst_addr_4 >> 24;
-
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4] = dst_addr_3 & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] =
-	                                               (dst_addr_3 >> 8) & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] =
-	                                              (dst_addr_3 >> 16) & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] = dst_addr_3 >> 24;
-
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8] = dst_addr_2 & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] =
-	                                               (dst_addr_2 >> 8) & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] =
-	                                              (dst_addr_2 >> 16) & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] = dst_addr_2 >> 24;
-
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12] = dst_addr_1 & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] =
-	                                               (dst_addr_1 >> 8) & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] =
-	                                              (dst_addr_1 >> 16) & 0xff;
-	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] = dst_addr_1 >> 24;
-
-	return 0;
-}
-
-/**
  *  ixgbe_atr_set_src_port_82599 - Sets the source port
  *  @input: input stream to modify
  *  @src_port: the source port to load
@@ -1540,19 +1454,6 @@
 }
 
 /**
- *  ixgbe_atr_set_vm_pool_82599 - Sets the Virtual Machine pool
- *  @input: input stream to modify
- *  @vm_pool: the Virtual Machine pool to load
- **/
-s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input,
-                                u8 vm_pool)
-{
-	input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool;
-
-	return 0;
-}
-
-/**
  *  ixgbe_atr_set_l4type_82599 - Sets the layer 4 packet type
  *  @input: input stream to modify
  *  @l4type: the layer 4 type value to load
@@ -1645,41 +1546,6 @@
 }
 
 /**
- *  ixgbe_atr_get_dst_ipv6_82599 - Gets the destination IPv6 address
- *  @input: input stream to search
- *  @dst_addr_1: the first 4 bytes of the IP address to load
- *  @dst_addr_2: the second 4 bytes of the IP address to load
- *  @dst_addr_3: the third 4 bytes of the IP address to load
- *  @dst_addr_4: the fourth 4 bytes of the IP address to load
- **/
-s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input,
-                                        u32 *dst_addr_1, u32 *dst_addr_2,
-                                        u32 *dst_addr_3, u32 *dst_addr_4)
-{
-	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12];
-	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] << 8;
-	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] << 16;
-	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] << 24;
-
-	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8];
-	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] << 8;
-	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] << 16;
-	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] << 24;
-
-	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4];
-	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] << 8;
-	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] << 16;
-	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] << 24;
-
-	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET];
-	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] << 8;
-	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] << 16;
-	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] << 24;
-
-	return 0;
-}
-
-/**
  *  ixgbe_atr_get_src_port_82599 - Gets the source port
  *  @input: input stream to modify
  *  @src_port: the source port to load
@@ -1732,19 +1598,6 @@
 }
 
 /**
- *  ixgbe_atr_get_vm_pool_82599 - Gets the Virtual Machine pool
- *  @input: input stream to modify
- *  @vm_pool: the Virtual Machine pool to load
- **/
-s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input,
-                                       u8 *vm_pool)
-{
-	*vm_pool = input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET];
-
-	return 0;
-}
-
-/**
  *  ixgbe_atr_get_l4type_82599 - Gets the layer 4 packet type
  *  @input: input stream to modify
  *  @l4type: the layer 4 type value to load
@@ -1910,56 +1763,27 @@
 	              (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT)));
 
 	/*
-	 * Program the relevant mask registers.  If src/dst_port or src/dst_addr
-	 * are zero, then assume a full mask for that field.  Also assume that
-	 * a VLAN of 0 is unspecified, so mask that out as well.  L4type
-	 * cannot be masked out in this implementation.
+	 * Program the relevant mask registers.  L4type cannot be
+	 * masked out in this implementation.
 	 *
 	 * This also assumes IPv4 only.  IPv6 masking isn't supported at this
 	 * point in time.
 	 */
-	if (src_ipv4 == 0)
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, 0xffffffff);
-	else
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask);
-
-	if (dst_ipv4 == 0)
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, 0xffffffff);
-	else
-		IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask);
 
 	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
 	case IXGBE_ATR_L4TYPE_TCP:
-		if (src_port == 0)
-			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xffff);
-		else
-			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
-			                input_masks->src_port_mask);
-
-		if (dst_port == 0)
-			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
-			               (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
-			                (0xffff << 16)));
-		else
-			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
-			               (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
-			                (input_masks->dst_port_mask << 16)));
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, input_masks->src_port_mask);
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
+				(IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
+				 (input_masks->dst_port_mask << 16)));
 		break;
 	case IXGBE_ATR_L4TYPE_UDP:
-		if (src_port == 0)
-			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xffff);
-		else
-			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
-			                input_masks->src_port_mask);
-
-		if (dst_port == 0)
-			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
-			               (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
-			                (0xffff << 16)));
-		else
-			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
-			               (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
-			                (input_masks->src_port_mask << 16)));
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, input_masks->src_port_mask);
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
+				(IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
+				 (input_masks->src_port_mask << 16)));
 		break;
 	default:
 		/* this already would have failed above */
@@ -1967,11 +1791,11 @@
 	}
 
 	/* Program the last mask register, FDIRM */
-	if (input_masks->vlan_id_mask || !vlan_id)
+	if (input_masks->vlan_id_mask)
 		/* Mask both VLAN and VLANP - bits 0 and 1 */
 		fdirm |= 0x3;
 
-	if (input_masks->data_mask || !flex_bytes)
+	if (input_masks->data_mask)
 		/* Flex bytes need masking, so mask the whole thing - bit 4 */
 		fdirm |= 0x10;
 
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index 9595b1b..e3eca13 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -52,6 +52,7 @@
 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_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
+static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
 
 /**
  *  ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
@@ -637,7 +638,7 @@
  *  Polls the status bit (bit 1) of the EERD or EEWR to determine when the
  *  read or write is done respectively.
  **/
-s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
+static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
 {
 	u32 i;
 	u32 reg;
@@ -2449,7 +2450,7 @@
  *  return the VLVF index where this VLAN id should be placed
  *
  **/
-s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
+static s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
 {
 	u32 bits = 0;
 	u32 first_empty_slot = 0;
@@ -2704,48 +2705,3 @@
 
 	return 0;
 }
-
-/**
- *  ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from
- *  the EEPROM
- *  @hw: pointer to hardware structure
- *  @wwnn_prefix: the alternative WWNN prefix
- *  @wwpn_prefix: the alternative WWPN prefix
- *
- *  This function will read the EEPROM from the alternative SAN MAC address
- *  block to check the support for the alternative WWNN/WWPN prefix support.
- **/
-s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
-                                 u16 *wwpn_prefix)
-{
-	u16 offset, caps;
-	u16 alt_san_mac_blk_offset;
-
-	/* clear output first */
-	*wwnn_prefix = 0xFFFF;
-	*wwpn_prefix = 0xFFFF;
-
-	/* check if alternative SAN MAC is supported */
-	hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR,
-	                    &alt_san_mac_blk_offset);
-
-	if ((alt_san_mac_blk_offset == 0) ||
-	    (alt_san_mac_blk_offset == 0xFFFF))
-		goto wwn_prefix_out;
-
-	/* check capability in alternative san mac address block */
-	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
-	hw->eeprom.ops.read(hw, offset, &caps);
-	if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
-		goto wwn_prefix_out;
-
-	/* get the corresponding prefix for WWNN/WWPN */
-	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
-	hw->eeprom.ops.read(hw, offset, wwnn_prefix);
-
-	offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET;
-	hw->eeprom.ops.read(hw, offset, wwpn_prefix);
-
-wwn_prefix_out:
-	return 0;
-}
diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h
index 5cf15aa..424c223 100644
--- a/drivers/net/ixgbe/ixgbe_common.h
+++ b/drivers/net/ixgbe/ixgbe_common.h
@@ -52,7 +52,6 @@
 s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
                                            u16 *checksum_val);
 s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw);
-s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
 
 s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
                           u32 enable_addr);
diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c
index 9aea4f0..8bb9ddb 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.c
+++ b/drivers/net/ixgbe/ixgbe_dcb.c
@@ -34,98 +34,6 @@
 #include "ixgbe_dcb_82599.h"
 
 /**
- * ixgbe_dcb_config - Struct containing DCB settings.
- * @dcb_config: Pointer to DCB config structure
- *
- * This function checks DCB rules for DCB settings.
- * The following rules are checked:
- * 1. The sum of bandwidth percentages of all Bandwidth Groups must total 100%.
- * 2. The sum of bandwidth percentages of all Traffic Classes within a Bandwidth
- *    Group must total 100.
- * 3. A Traffic Class should not be set to both Link Strict Priority
- *    and Group Strict Priority.
- * 4. Link strict Bandwidth Groups can only have link strict traffic classes
- *    with zero bandwidth.
- */
-s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *dcb_config)
-{
-	struct tc_bw_alloc *p;
-	s32 ret_val = 0;
-	u8 i, j, bw = 0, bw_id;
-	u8 bw_sum[2][MAX_BW_GROUP];
-	bool link_strict[2][MAX_BW_GROUP];
-
-	memset(bw_sum, 0, sizeof(bw_sum));
-	memset(link_strict, 0, sizeof(link_strict));
-
-	/* First Tx, then Rx */
-	for (i = 0; i < 2; i++) {
-		/* Check each traffic class for rule violation */
-		for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
-			p = &dcb_config->tc_config[j].path[i];
-
-			bw = p->bwg_percent;
-			bw_id = p->bwg_id;
-
-			if (bw_id >= MAX_BW_GROUP) {
-				ret_val = DCB_ERR_CONFIG;
-				goto err_config;
-			}
-			if (p->prio_type == prio_link) {
-				link_strict[i][bw_id] = true;
-				/* Link strict should have zero bandwidth */
-				if (bw) {
-					ret_val = DCB_ERR_LS_BW_NONZERO;
-					goto err_config;
-				}
-			} else if (!bw) {
-				/*
-				 * Traffic classes without link strict
-				 * should have non-zero bandwidth.
-				 */
-				ret_val = DCB_ERR_TC_BW_ZERO;
-				goto err_config;
-			}
-			bw_sum[i][bw_id] += bw;
-		}
-
-		bw = 0;
-
-		/* Check each bandwidth group for rule violation */
-		for (j = 0; j < MAX_BW_GROUP; j++) {
-			bw += dcb_config->bw_percentage[i][j];
-			/*
-			 * Sum of bandwidth percentages of all traffic classes
-			 * within a Bandwidth Group must total 100 except for
-			 * link strict group (zero bandwidth).
-			 */
-			if (link_strict[i][j]) {
-				if (bw_sum[i][j]) {
-					/*
-					 * Link strict group should have zero
-					 * bandwidth.
-					 */
-					ret_val = DCB_ERR_LS_BWG_NONZERO;
-					goto err_config;
-				}
-			} else if (bw_sum[i][j] != BW_PERCENT &&
-				   bw_sum[i][j] != 0) {
-				ret_val = DCB_ERR_TC_BW;
-				goto err_config;
-			}
-		}
-
-		if (bw != BW_PERCENT) {
-			ret_val = DCB_ERR_BW_GROUP;
-			goto err_config;
-		}
-	}
-
-err_config:
-	return ret_val;
-}
-
-/**
  * ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits
  * @ixgbe_dcb_config: Struct containing DCB settings.
  * @direction: Configuring either Tx or Rx.
@@ -203,133 +111,6 @@
 }
 
 /**
- * ixgbe_dcb_get_tc_stats - Returns status of each traffic class
- * @hw: pointer to hardware structure
- * @stats: pointer to statistics structure
- * @tc_count:  Number of elements in bwg_array.
- *
- * This function returns the status data for each of the Traffic Classes in use.
- */
-s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
-                           u8 tc_count)
-{
-	s32 ret = 0;
-	if (hw->mac.type == ixgbe_mac_82598EB)
-		ret = ixgbe_dcb_get_tc_stats_82598(hw, stats, tc_count);
-	else if (hw->mac.type == ixgbe_mac_82599EB)
-		ret = ixgbe_dcb_get_tc_stats_82599(hw, stats, tc_count);
-	return ret;
-}
-
-/**
- * ixgbe_dcb_get_pfc_stats - Returns CBFC status of each traffic class
- * hw - pointer to hardware structure
- * stats - pointer to statistics structure
- * tc_count -  Number of elements in bwg_array.
- *
- * This function returns the CBFC status data for each of the Traffic Classes.
- */
-s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
-                            u8 tc_count)
-{
-	s32 ret = 0;
-	if (hw->mac.type == ixgbe_mac_82598EB)
-		ret = ixgbe_dcb_get_pfc_stats_82598(hw, stats, tc_count);
-	else if (hw->mac.type == ixgbe_mac_82599EB)
-		ret = ixgbe_dcb_get_pfc_stats_82599(hw, stats, tc_count);
-	return ret;
-}
-
-/**
- * ixgbe_dcb_config_rx_arbiter - Config Rx arbiter
- * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
- *
- * Configure Rx Data Arbiter and credits for each traffic class.
- */
-s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *hw,
-                                struct ixgbe_dcb_config *dcb_config)
-{
-	s32 ret = 0;
-	if (hw->mac.type == ixgbe_mac_82598EB)
-		ret = ixgbe_dcb_config_rx_arbiter_82598(hw, dcb_config);
-	else if (hw->mac.type == ixgbe_mac_82599EB)
-		ret = ixgbe_dcb_config_rx_arbiter_82599(hw, dcb_config);
-	return ret;
-}
-
-/**
- * ixgbe_dcb_config_tx_desc_arbiter - Config Tx Desc arbiter
- * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
- *
- * Configure Tx Descriptor Arbiter and credits for each traffic class.
- */
-s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *hw,
-                                     struct ixgbe_dcb_config *dcb_config)
-{
-	s32 ret = 0;
-	if (hw->mac.type == ixgbe_mac_82598EB)
-		ret = ixgbe_dcb_config_tx_desc_arbiter_82598(hw, dcb_config);
-	else if (hw->mac.type == ixgbe_mac_82599EB)
-		ret = ixgbe_dcb_config_tx_desc_arbiter_82599(hw, dcb_config);
-	return ret;
-}
-
-/**
- * ixgbe_dcb_config_tx_data_arbiter - Config Tx data arbiter
- * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
- *
- * Configure Tx Data Arbiter and credits for each traffic class.
- */
-s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *hw,
-                                     struct ixgbe_dcb_config *dcb_config)
-{
-	s32 ret = 0;
-	if (hw->mac.type == ixgbe_mac_82598EB)
-		ret = ixgbe_dcb_config_tx_data_arbiter_82598(hw, dcb_config);
-	else if (hw->mac.type == ixgbe_mac_82599EB)
-		ret = ixgbe_dcb_config_tx_data_arbiter_82599(hw, dcb_config);
-	return ret;
-}
-
-/**
- * ixgbe_dcb_config_pfc - Config priority flow control
- * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
- *
- * Configure Priority Flow Control for each traffic class.
- */
-s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *hw,
-                         struct ixgbe_dcb_config *dcb_config)
-{
-	s32 ret = 0;
-	if (hw->mac.type == ixgbe_mac_82598EB)
-		ret = ixgbe_dcb_config_pfc_82598(hw, dcb_config);
-	else if (hw->mac.type == ixgbe_mac_82599EB)
-		ret = ixgbe_dcb_config_pfc_82599(hw, dcb_config);
-	return ret;
-}
-
-/**
- * ixgbe_dcb_config_tc_stats - Config traffic class statistics
- * @hw: pointer to hardware structure
- *
- * Configure queue statistics registers, all queues belonging to same traffic
- * class uses a single set of queue statistics counters.
- */
-s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *hw)
-{
-	s32 ret = 0;
-	if (hw->mac.type == ixgbe_mac_82598EB)
-		ret = ixgbe_dcb_config_tc_stats_82598(hw);
-	else if (hw->mac.type == ixgbe_mac_82599EB)
-		ret = ixgbe_dcb_config_tc_stats_82599(hw);
-	return ret;
-}
-
-/**
  * ixgbe_dcb_hw_config - Config and enable DCB
  * @hw: pointer to hardware structure
  * @dcb_config: pointer to ixgbe_dcb_config structure
diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h
index 5caafd4..eb1059f 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.h
+++ b/drivers/net/ixgbe/ixgbe_dcb.h
@@ -149,27 +149,9 @@
 
 /* DCB driver APIs */
 
-/* DCB rule checking function.*/
-s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *config);
-
 /* DCB credits calculation */
 s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *, u8);
 
-/* DCB PFC functions */
-s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *, struct ixgbe_dcb_config *g);
-s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8);
-
-/* DCB traffic class stats */
-s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *);
-s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8);
-
-/* DCB config arbiters */
-s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *,
-                                     struct ixgbe_dcb_config *);
-s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *,
-                                     struct ixgbe_dcb_config *);
-s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *, struct ixgbe_dcb_config *);
-
 /* DCB hw initialization */
 s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *);
 
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c
index f0e9279..50288bc 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c
@@ -32,65 +32,6 @@
 #include "ixgbe_dcb_82598.h"
 
 /**
- * ixgbe_dcb_get_tc_stats_82598 - Return status data for each traffic class
- * @hw: pointer to hardware structure
- * @stats: pointer to statistics structure
- * @tc_count:  Number of elements in bwg_array.
- *
- * This function returns the status data for each of the Traffic Classes in use.
- */
-s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *hw,
-                                 struct ixgbe_hw_stats *stats,
-                                 u8 tc_count)
-{
-	int tc;
-
-	if (tc_count > MAX_TRAFFIC_CLASS)
-		return DCB_ERR_PARAM;
-
-	/* Statistics pertaining to each traffic class */
-	for (tc = 0; tc < tc_count; tc++) {
-		/* Transmitted Packets */
-		stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc));
-		/* Transmitted Bytes */
-		stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc));
-		/* Received Packets */
-		stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc));
-		/* Received Bytes */
-		stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc));
-	}
-
-	return 0;
-}
-
-/**
- * ixgbe_dcb_get_pfc_stats_82598 - Returns CBFC status data
- * @hw: pointer to hardware structure
- * @stats: pointer to statistics structure
- * @tc_count:  Number of elements in bwg_array.
- *
- * This function returns the CBFC status data for each of the Traffic Classes.
- */
-s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *hw,
-                                  struct ixgbe_hw_stats *stats,
-                                  u8 tc_count)
-{
-	int tc;
-
-	if (tc_count > MAX_TRAFFIC_CLASS)
-		return DCB_ERR_PARAM;
-
-	for (tc = 0; tc < tc_count; tc++) {
-		/* Priority XOFF Transmitted */
-		stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc));
-		/* Priority XOFF Received */
-		stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(tc));
-	}
-
-	return 0;
-}
-
-/**
  * ixgbe_dcb_config_packet_buffers_82598 - Configure packet buffers
  * @hw: pointer to hardware structure
  * @dcb_config: pointer to ixgbe_dcb_config structure
@@ -137,7 +78,7 @@
  *
  * Configure Rx Data Arbiter and credits for each traffic class.
  */
-s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
                                       struct ixgbe_dcb_config *dcb_config)
 {
 	struct tc_bw_alloc    *p;
@@ -194,7 +135,7 @@
  *
  * Configure Tx Descriptor Arbiter and credits for each traffic class.
  */
-s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
                                            struct ixgbe_dcb_config *dcb_config)
 {
 	struct tc_bw_alloc *p;
@@ -242,7 +183,7 @@
  *
  * Configure Tx Data Arbiter and credits for each traffic class.
  */
-s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
                                            struct ixgbe_dcb_config *dcb_config)
 {
 	struct tc_bw_alloc *p;
@@ -355,7 +296,7 @@
  * Configure queue statistics registers, all queues belonging to same traffic
  * class uses a single set of queue statistics counters.
  */
-s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
+static s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
 {
 	u32 reg = 0;
 	u8  i   = 0;
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ixgbe/ixgbe_dcb_82598.h
index cc728fa..abc03cc 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h
@@ -72,21 +72,6 @@
 
 /* DCB PFC functions */
 s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *);
-s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *,
-                                  u8);
-
-/* DCB traffic class stats */
-s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *);
-s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *,
-                                 u8);
-
-/* DCB config arbiters */
-s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *,
-                                           struct ixgbe_dcb_config *);
-s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *,
-                                           struct ixgbe_dcb_config *);
-s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *,
-                                      struct ixgbe_dcb_config *);
 
 /* DCB hw initialization */
 s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *);
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c
index 25b02fb..67c219f 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c
@@ -31,70 +31,13 @@
 #include "ixgbe_dcb_82599.h"
 
 /**
- * ixgbe_dcb_get_tc_stats_82599 - Returns status for each traffic class
- * @hw: pointer to hardware structure
- * @stats: pointer to statistics structure
- * @tc_count:  Number of elements in bwg_array.
- *
- * This function returns the status data for each of the Traffic Classes in use.
- */
-s32 ixgbe_dcb_get_tc_stats_82599(struct ixgbe_hw *hw,
-                                 struct ixgbe_hw_stats *stats,
-                                 u8 tc_count)
-{
-	int tc;
-
-	if (tc_count > MAX_TRAFFIC_CLASS)
-		return DCB_ERR_PARAM;
-	/* Statistics pertaining to each traffic class */
-	for (tc = 0; tc < tc_count; tc++) {
-		/* Transmitted Packets */
-		stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc));
-		/* Transmitted Bytes */
-		stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc));
-		/* Received Packets */
-		stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc));
-		/* Received Bytes */
-		stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc));
-	}
-
-	return 0;
-}
-
-/**
- * ixgbe_dcb_get_pfc_stats_82599 - Return CBFC status data
- * @hw: pointer to hardware structure
- * @stats: pointer to statistics structure
- * @tc_count:  Number of elements in bwg_array.
- *
- * This function returns the CBFC status data for each of the Traffic Classes.
- */
-s32 ixgbe_dcb_get_pfc_stats_82599(struct ixgbe_hw *hw,
-                                  struct ixgbe_hw_stats *stats,
-                                  u8 tc_count)
-{
-	int tc;
-
-	if (tc_count > MAX_TRAFFIC_CLASS)
-		return DCB_ERR_PARAM;
-	for (tc = 0; tc < tc_count; tc++) {
-		/* Priority XOFF Transmitted */
-		stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc));
-		/* Priority XOFF Received */
-		stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(tc));
-	}
-
-	return 0;
-}
-
-/**
  * ixgbe_dcb_config_packet_buffers_82599 - Configure DCB packet buffers
  * @hw: pointer to hardware structure
  * @dcb_config: pointer to ixgbe_dcb_config structure
  *
  * Configure packet buffers for DCB mode.
  */
-s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw,
                                           struct ixgbe_dcb_config *dcb_config)
 {
 	s32 ret_val = 0;
@@ -136,7 +79,7 @@
  *
  * Configure Rx Packet Arbiter and credits for each traffic class.
  */
-s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
                                       struct ixgbe_dcb_config *dcb_config)
 {
 	struct tc_bw_alloc    *p;
@@ -191,7 +134,7 @@
  *
  * Configure Tx Descriptor Arbiter and credits for each traffic class.
  */
-s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
                                            struct ixgbe_dcb_config *dcb_config)
 {
 	struct tc_bw_alloc *p;
@@ -238,7 +181,7 @@
  *
  * Configure Tx Packet Arbiter and credits for each traffic class.
  */
-s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
                                            struct ixgbe_dcb_config *dcb_config)
 {
 	struct tc_bw_alloc *p;
@@ -359,7 +302,7 @@
  * Configure queue statistics registers, all queues belonging to same traffic
  * class uses a single set of queue statistics counters.
  */
-s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw)
+static s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw)
 {
 	u32 reg = 0;
 	u8  i   = 0;
@@ -412,7 +355,7 @@
  *
  * Configure general DCB parameters.
  */
-s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw)
+static s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw)
 {
 	u32 reg;
 	u32 q;
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ixgbe/ixgbe_dcb_82599.h
index 0f3f791..18d7fbf 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.h
@@ -101,24 +101,6 @@
 /* DCB PFC functions */
 s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw,
                                struct ixgbe_dcb_config *dcb_config);
-s32 ixgbe_dcb_get_pfc_stats_82599(struct ixgbe_hw *hw,
-                                  struct ixgbe_hw_stats *stats,
-                                  u8 tc_count);
-
-/* DCB traffic class stats */
-s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw);
-s32 ixgbe_dcb_get_tc_stats_82599(struct ixgbe_hw *hw,
-                                 struct ixgbe_hw_stats *stats,
-                                 u8 tc_count);
-
-/* DCB config arbiters */
-s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
-                                           struct ixgbe_dcb_config *dcb_config);
-s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
-                                           struct ixgbe_dcb_config *dcb_config);
-s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
-                                      struct ixgbe_dcb_config *dcb_config);
-
 
 /* DCB hw initialization */
 s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index dcebc82..3dc731c 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -401,7 +401,7 @@
 static u32 ixgbe_get_rx_csum(struct net_device *netdev)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	return (adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED);
+	return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED;
 }
 
 static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data)
@@ -820,16 +820,19 @@
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	char firmware_version[32];
 
-	strncpy(drvinfo->driver, ixgbe_driver_name, 32);
-	strncpy(drvinfo->version, ixgbe_driver_version, 32);
+	strncpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver));
+	strncpy(drvinfo->version, ixgbe_driver_version,
+	        sizeof(drvinfo->version));
 
-	sprintf(firmware_version, "%d.%d-%d",
-	        (adapter->eeprom_version & 0xF000) >> 12,
-	        (adapter->eeprom_version & 0x0FF0) >> 4,
-	        adapter->eeprom_version & 0x000F);
+	snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d",
+	         (adapter->eeprom_version & 0xF000) >> 12,
+	         (adapter->eeprom_version & 0x0FF0) >> 4,
+	         adapter->eeprom_version & 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));
+	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+	        sizeof(drvinfo->bus_info));
 	drvinfo->n_stats = IXGBE_STATS_LEN;
 	drvinfo->testinfo_len = IXGBE_TEST_LEN;
 	drvinfo->regdump_len = ixgbe_get_regs_len(netdev);
@@ -985,8 +988,8 @@
 	case ETH_SS_STATS:
 		return IXGBE_STATS_LEN;
 	case ETH_SS_NTUPLE_FILTERS:
-		return (ETHTOOL_MAX_NTUPLE_LIST_ENTRY *
-		        ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY);
+		return ETHTOOL_MAX_NTUPLE_LIST_ENTRY *
+		       ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -996,12 +999,11 @@
                                     struct ethtool_stats *stats, u64 *data)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	u64 *queue_stat;
-	int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64);
 	struct rtnl_link_stats64 temp;
 	const struct rtnl_link_stats64 *net_stats;
-	int j, k;
-	int i;
+	unsigned int start;
+	struct ixgbe_ring *ring;
+	int i, j;
 	char *p = NULL;
 
 	ixgbe_update_stats(adapter);
@@ -1022,16 +1024,22 @@
 		           sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
 	}
 	for (j = 0; j < adapter->num_tx_queues; j++) {
-		queue_stat = (u64 *)&adapter->tx_ring[j]->stats;
-		for (k = 0; k < stat_count; k++)
-			data[i + k] = queue_stat[k];
-		i += k;
+		ring = adapter->tx_ring[j];
+		do {
+			start = u64_stats_fetch_begin_bh(&ring->syncp);
+			data[i]   = ring->stats.packets;
+			data[i+1] = ring->stats.bytes;
+		} while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+		i += 2;
 	}
 	for (j = 0; j < adapter->num_rx_queues; j++) {
-		queue_stat = (u64 *)&adapter->rx_ring[j]->stats;
-		for (k = 0; k < stat_count; k++)
-			data[i + k] = queue_stat[k];
-		i += k;
+		ring = adapter->rx_ring[j];
+		do {
+			start = u64_stats_fetch_begin_bh(&ring->syncp);
+			data[i]   = ring->stats.packets;
+			data[i+1] = ring->stats.bytes;
+		} while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+		i += 2;
 	}
 	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
 		for (j = 0; j < MAX_TX_PACKET_BUFFERS; j++) {
@@ -1435,9 +1443,7 @@
 	struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
 	struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
 	struct ixgbe_hw *hw = &adapter->hw;
-	struct pci_dev *pdev = adapter->pdev;
 	u32 reg_ctl;
-	int i;
 
 	/* shut down the DMA engines now so they can be reinitialized later */
 
@@ -1445,14 +1451,15 @@
 	reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
 	reg_ctl &= ~IXGBE_RXCTRL_RXEN;
 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_ctl);
-	reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(0));
+	reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rx_ring->reg_idx));
 	reg_ctl &= ~IXGBE_RXDCTL_ENABLE;
-	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(0), reg_ctl);
+	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rx_ring->reg_idx), reg_ctl);
 
 	/* now Tx */
-	reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(0));
+	reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx));
 	reg_ctl &= ~IXGBE_TXDCTL_ENABLE;
-	IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(0), reg_ctl);
+	IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx), reg_ctl);
+
 	if (hw->mac.type == ixgbe_mac_82599EB) {
 		reg_ctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
 		reg_ctl &= ~IXGBE_DMATXCTL_TE;
@@ -1461,221 +1468,57 @@
 
 	ixgbe_reset(adapter);
 
-	if (tx_ring->desc && tx_ring->tx_buffer_info) {
-		for (i = 0; i < tx_ring->count; i++) {
-			struct ixgbe_tx_buffer *buf =
-					&(tx_ring->tx_buffer_info[i]);
-			if (buf->dma)
-				dma_unmap_single(&pdev->dev, buf->dma,
-						 buf->length, DMA_TO_DEVICE);
-			if (buf->skb)
-				dev_kfree_skb(buf->skb);
-		}
-	}
-
-	if (rx_ring->desc && rx_ring->rx_buffer_info) {
-		for (i = 0; i < rx_ring->count; i++) {
-			struct ixgbe_rx_buffer *buf =
-					&(rx_ring->rx_buffer_info[i]);
-			if (buf->dma)
-				dma_unmap_single(&pdev->dev, buf->dma,
-						 IXGBE_RXBUFFER_2048,
-						 DMA_FROM_DEVICE);
-			if (buf->skb)
-				dev_kfree_skb(buf->skb);
-		}
-	}
-
-	if (tx_ring->desc) {
-		dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
-				  tx_ring->dma);
-		tx_ring->desc = NULL;
-	}
-	if (rx_ring->desc) {
-		dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
-				  rx_ring->dma);
-		rx_ring->desc = NULL;
-	}
-
-	kfree(tx_ring->tx_buffer_info);
-	tx_ring->tx_buffer_info = NULL;
-	kfree(rx_ring->rx_buffer_info);
-	rx_ring->rx_buffer_info = NULL;
+	ixgbe_free_tx_resources(adapter, &adapter->test_tx_ring);
+	ixgbe_free_rx_resources(adapter, &adapter->test_rx_ring);
 }
 
 static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
 	struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
-	struct pci_dev *pdev = adapter->pdev;
 	u32 rctl, reg_data;
-	int i, ret_val;
+	int ret_val;
+	int err;
 
 	/* Setup Tx descriptor ring and Tx buffers */
+	tx_ring->count = IXGBE_DEFAULT_TXD;
+	tx_ring->queue_index = 0;
+	tx_ring->reg_idx = adapter->tx_ring[0]->reg_idx;
+	tx_ring->numa_node = adapter->node;
 
-	if (!tx_ring->count)
-		tx_ring->count = IXGBE_DEFAULT_TXD;
-
-	tx_ring->tx_buffer_info = kcalloc(tx_ring->count,
-	                                  sizeof(struct ixgbe_tx_buffer),
-	                                  GFP_KERNEL);
-	if (!(tx_ring->tx_buffer_info)) {
-		ret_val = 1;
-		goto err_nomem;
-	}
-
-	tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc);
-	tx_ring->size = ALIGN(tx_ring->size, 4096);
-	tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
-					   &tx_ring->dma, GFP_KERNEL);
-	if (!(tx_ring->desc)) {
-		ret_val = 2;
-		goto err_nomem;
-	}
-	tx_ring->next_to_use = tx_ring->next_to_clean = 0;
-
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAL(0),
-			((u64) tx_ring->dma & 0x00000000FFFFFFFF));
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAH(0),
-			((u64) tx_ring->dma >> 32));
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDLEN(0),
-			tx_ring->count * sizeof(union ixgbe_adv_tx_desc));
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDH(0), 0);
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), 0);
-
-	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
-	reg_data |= IXGBE_HLREG0_TXPADEN;
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
+	err = ixgbe_setup_tx_resources(adapter, tx_ring);
+	if (err)
+		return 1;
 
 	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
 		reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL);
 		reg_data |= IXGBE_DMATXCTL_TE;
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data);
 	}
-	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(0));
-	reg_data |= IXGBE_TXDCTL_ENABLE;
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(0), reg_data);
 
-	for (i = 0; i < tx_ring->count; i++) {
-		union ixgbe_adv_tx_desc *desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
-		struct sk_buff *skb;
-		unsigned int size = 1024;
-
-		skb = alloc_skb(size, GFP_KERNEL);
-		if (!skb) {
-			ret_val = 3;
-			goto err_nomem;
-		}
-		skb_put(skb, size);
-		tx_ring->tx_buffer_info[i].skb = skb;
-		tx_ring->tx_buffer_info[i].length = skb->len;
-		tx_ring->tx_buffer_info[i].dma =
-			dma_map_single(&pdev->dev, skb->data, skb->len,
-				       DMA_TO_DEVICE);
-		desc->read.buffer_addr =
-		                    cpu_to_le64(tx_ring->tx_buffer_info[i].dma);
-		desc->read.cmd_type_len = cpu_to_le32(skb->len);
-		desc->read.cmd_type_len |= cpu_to_le32(IXGBE_TXD_CMD_EOP |
-		                                       IXGBE_TXD_CMD_IFCS |
-		                                       IXGBE_TXD_CMD_RS);
-		desc->read.olinfo_status = 0;
-		if (adapter->hw.mac.type == ixgbe_mac_82599EB)
-			desc->read.olinfo_status |=
-			                (skb->len << IXGBE_ADVTXD_PAYLEN_SHIFT);
-
-	}
+	ixgbe_configure_tx_ring(adapter, tx_ring);
 
 	/* Setup Rx Descriptor ring and Rx buffers */
+	rx_ring->count = IXGBE_DEFAULT_RXD;
+	rx_ring->queue_index = 0;
+	rx_ring->reg_idx = adapter->rx_ring[0]->reg_idx;
+	rx_ring->rx_buf_len = IXGBE_RXBUFFER_2048;
+	rx_ring->numa_node = adapter->node;
 
-	if (!rx_ring->count)
-		rx_ring->count = IXGBE_DEFAULT_RXD;
-
-	rx_ring->rx_buffer_info = kcalloc(rx_ring->count,
-	                                  sizeof(struct ixgbe_rx_buffer),
-	                                  GFP_KERNEL);
-	if (!(rx_ring->rx_buffer_info)) {
+	err = ixgbe_setup_rx_resources(adapter, rx_ring);
+	if (err) {
 		ret_val = 4;
 		goto err_nomem;
 	}
 
-	rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
-	rx_ring->size = ALIGN(rx_ring->size, 4096);
-	rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
-					   &rx_ring->dma, GFP_KERNEL);
-	if (!(rx_ring->desc)) {
-		ret_val = 5;
-		goto err_nomem;
-	}
-	rx_ring->next_to_use = rx_ring->next_to_clean = 0;
-
 	rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXCTRL);
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl & ~IXGBE_RXCTRL_RXEN);
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAL(0),
-			((u64)rx_ring->dma & 0xFFFFFFFF));
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAH(0),
-			((u64) rx_ring->dma >> 32));
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDLEN(0), rx_ring->size);
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDH(0), 0);
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), 0);
 
-	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
-	reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE;
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data);
-
-	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
-	reg_data &= ~IXGBE_HLREG0_LPBK;
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
-
-	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RDRXCTL);
-#define IXGBE_RDRXCTL_RDMTS_MASK    0x00000003 /* Receive Descriptor Minimum
-                                                  Threshold Size mask */
-	reg_data &= ~IXGBE_RDRXCTL_RDMTS_MASK;
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDRXCTL, reg_data);
-
-	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_MCSTCTRL);
-#define IXGBE_MCSTCTRL_MO_MASK      0x00000003 /* Multicast Offset mask */
-	reg_data &= ~IXGBE_MCSTCTRL_MO_MASK;
-	reg_data |= adapter->hw.mac.mc_filter_type;
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_MCSTCTRL, reg_data);
-
-	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(0));
-	reg_data |= IXGBE_RXDCTL_ENABLE;
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(0), reg_data);
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-		int j = adapter->rx_ring[0]->reg_idx;
-		u32 k;
-		for (k = 0; k < 10; k++) {
-			if (IXGBE_READ_REG(&adapter->hw,
-			                   IXGBE_RXDCTL(j)) & IXGBE_RXDCTL_ENABLE)
-				break;
-			else
-				msleep(1);
-		}
-	}
+	ixgbe_configure_rx_ring(adapter, rx_ring);
 
 	rctl |= IXGBE_RXCTRL_RXEN | IXGBE_RXCTRL_DMBYPS;
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl);
 
-	for (i = 0; i < rx_ring->count; i++) {
-		union ixgbe_adv_rx_desc *rx_desc =
-		                                 IXGBE_RX_DESC_ADV(*rx_ring, i);
-		struct sk_buff *skb;
-
-		skb = alloc_skb(IXGBE_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
-		if (!skb) {
-			ret_val = 6;
-			goto err_nomem;
-		}
-		skb_reserve(skb, NET_IP_ALIGN);
-		rx_ring->rx_buffer_info[i].skb = skb;
-		rx_ring->rx_buffer_info[i].dma =
-			dma_map_single(&pdev->dev, skb->data,
-				       IXGBE_RXBUFFER_2048, DMA_FROM_DEVICE);
-		rx_desc->read.pkt_addr =
-				cpu_to_le64(rx_ring->rx_buffer_info[i].dma);
-		memset(skb->data, 0x00, skb->len);
-	}
-
 	return 0;
 
 err_nomem:
@@ -1689,16 +1532,21 @@
 	u32 reg_data;
 
 	/* right now we only support MAC loopback in the driver */
-
-	/* Setup MAC loopback */
 	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
+	/* Setup MAC loopback */
 	reg_data |= IXGBE_HLREG0_LPBK;
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
 
+	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
+	reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data);
+
 	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_AUTOC);
 	reg_data &= ~IXGBE_AUTOC_LMS_MASK;
 	reg_data |= IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU;
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_AUTOC, reg_data);
+	IXGBE_WRITE_FLUSH(&adapter->hw);
+	msleep(10);
 
 	/* Disable Atlas Tx lanes; re-enabled in reset path */
 	if (hw->mac.type == ixgbe_mac_82598EB) {
@@ -1756,15 +1604,81 @@
 	return 13;
 }
 
+static u16 ixgbe_clean_test_rings(struct ixgbe_adapter *adapter,
+                                  struct ixgbe_ring *rx_ring,
+                                  struct ixgbe_ring *tx_ring,
+                                  unsigned int size)
+{
+	union ixgbe_adv_rx_desc *rx_desc;
+	struct ixgbe_rx_buffer *rx_buffer_info;
+	struct ixgbe_tx_buffer *tx_buffer_info;
+	const int bufsz = rx_ring->rx_buf_len;
+	u32 staterr;
+	u16 rx_ntc, tx_ntc, count = 0;
+
+	/* initialize next to clean and descriptor values */
+	rx_ntc = rx_ring->next_to_clean;
+	tx_ntc = tx_ring->next_to_clean;
+	rx_desc = IXGBE_RX_DESC_ADV(rx_ring, rx_ntc);
+	staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+
+	while (staterr & IXGBE_RXD_STAT_DD) {
+		/* check Rx buffer */
+		rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc];
+
+		/* unmap Rx buffer, will be remapped by alloc_rx_buffers */
+		dma_unmap_single(&adapter->pdev->dev,
+		                 rx_buffer_info->dma,
+				 bufsz,
+				 DMA_FROM_DEVICE);
+		rx_buffer_info->dma = 0;
+
+		/* verify contents of skb */
+		if (!ixgbe_check_lbtest_frame(rx_buffer_info->skb, size))
+			count++;
+
+		/* unmap buffer on Tx side */
+		tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc];
+		ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info);
+
+		/* increment Rx/Tx next to clean counters */
+		rx_ntc++;
+		if (rx_ntc == rx_ring->count)
+			rx_ntc = 0;
+		tx_ntc++;
+		if (tx_ntc == tx_ring->count)
+			tx_ntc = 0;
+
+		/* fetch next descriptor */
+		rx_desc = IXGBE_RX_DESC_ADV(rx_ring, rx_ntc);
+		staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+	}
+
+	/* re-map buffers to ring, store next to clean values */
+	ixgbe_alloc_rx_buffers(adapter, rx_ring, count);
+	rx_ring->next_to_clean = rx_ntc;
+	tx_ring->next_to_clean = tx_ntc;
+
+	return count;
+}
+
 static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
 	struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	int i, j, k, l, lc, good_cnt, ret_val = 0;
-	unsigned long time;
+	int i, j, lc, good_cnt, ret_val = 0;
+	unsigned int size = 1024;
+	netdev_tx_t tx_ret_val;
+	struct sk_buff *skb;
 
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), rx_ring->count - 1);
+	/* allocate test skb */
+	skb = alloc_skb(size, GFP_KERNEL);
+	if (!skb)
+		return 11;
+
+	/* place data into test skb */
+	ixgbe_create_lbtest_frame(skb, size);
+	skb_put(skb, size);
 
 	/*
 	 * Calculate the loop count based on the largest descriptor ring
@@ -1777,54 +1691,40 @@
 	else
 		lc = ((rx_ring->count / 64) * 2) + 1;
 
-	k = l = 0;
 	for (j = 0; j <= lc; j++) {
-		for (i = 0; i < 64; i++) {
-			ixgbe_create_lbtest_frame(
-					tx_ring->tx_buffer_info[k].skb,
-					1024);
-			dma_sync_single_for_device(&pdev->dev,
-				tx_ring->tx_buffer_info[k].dma,
-				tx_ring->tx_buffer_info[k].length,
-				DMA_TO_DEVICE);
-			if (unlikely(++k == tx_ring->count))
-				k = 0;
-		}
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), k);
-		msleep(200);
-		/* set the start time for the receive */
-		time = jiffies;
+		/* reset count of good packets */
 		good_cnt = 0;
-		do {
-			/* receive the sent packets */
-			dma_sync_single_for_cpu(&pdev->dev,
-					rx_ring->rx_buffer_info[l].dma,
-					IXGBE_RXBUFFER_2048,
-					DMA_FROM_DEVICE);
-			ret_val = ixgbe_check_lbtest_frame(
-					rx_ring->rx_buffer_info[l].skb, 1024);
-			if (!ret_val)
+
+		/* place 64 packets on the transmit queue*/
+		for (i = 0; i < 64; i++) {
+			skb_get(skb);
+			tx_ret_val = ixgbe_xmit_frame_ring(skb,
+							   adapter->netdev,
+							   adapter,
+							   tx_ring);
+			if (tx_ret_val == NETDEV_TX_OK)
 				good_cnt++;
-			if (++l == rx_ring->count)
-				l = 0;
-			/*
-			 * time + 20 msecs (200 msecs on 2.4) is more than
-			 * enough time to complete the receives, if it's
-			 * exceeded, break and error off
-			 */
-		} while (good_cnt < 64 && jiffies < (time + 20));
+		}
+
 		if (good_cnt != 64) {
-			/* ret_val is the same as mis-compare */
+			ret_val = 12;
+			break;
+		}
+
+		/* allow 200 milliseconds for packets to go from Tx to Rx */
+		msleep(200);
+
+		good_cnt = ixgbe_clean_test_rings(adapter, rx_ring,
+						  tx_ring, size);
+		if (good_cnt != 64) {
 			ret_val = 13;
 			break;
 		}
-		if (jiffies >= (time + 20)) {
-			/* Error code for time out error */
-			ret_val = 14;
-			break;
-		}
 	}
 
+	/* free the original skb */
+	kfree_skb(skb);
+
 	return ret_val;
 }
 
@@ -2218,7 +2118,17 @@
 	bool need_reset = false;
 	int rc;
 
-	rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO | ETH_FLAG_NTUPLE);
+#ifdef CONFIG_IXGBE_DCB
+	if ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
+	    !(data & ETH_FLAG_RXVLAN))
+		return -EINVAL;
+#endif
+
+	need_reset = (data & ETH_FLAG_RXVLAN) !=
+		     (netdev->features & NETIF_F_HW_VLAN_RX);
+
+	rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO |
+					ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN);
 	if (rc)
 		return rc;
 
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c
index 072327c..05efa6a8 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ixgbe/ixgbe_fcoe.c
@@ -304,12 +304,13 @@
 	if (!ixgbe_rx_is_fcoe(rx_desc))
 		goto ddp_out;
 
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
 	sterr = le32_to_cpu(rx_desc->wb.upper.status_error);
 	fcerr = (sterr & IXGBE_RXDADV_ERR_FCERR);
 	fceofe = (sterr & IXGBE_RXDADV_ERR_FCEOFE);
 	if (fcerr == IXGBE_FCERR_BADCRC)
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
+	else
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 	if (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q))
 		fh = (struct fc_frame_header *)(skb->data +
@@ -471,7 +472,7 @@
 
 	/* write context desc */
 	i = tx_ring->next_to_use;
-	context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i);
+	context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
 	context_desc->vlan_macip_lens	= cpu_to_le32(vlan_macip_lens);
 	context_desc->seqnum_seed	= cpu_to_le32(fcoe_sof_eof);
 	context_desc->type_tucmd_mlhl	= cpu_to_le32(type_tucmd);
@@ -603,11 +604,13 @@
 {
 	int rc = -EINVAL;
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
 
 
 	if (!(adapter->flags & IXGBE_FLAG_FCOE_CAPABLE))
 		goto out_enable;
 
+	atomic_inc(&fcoe->refcnt);
 	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
 		goto out_enable;
 
@@ -647,6 +650,7 @@
 {
 	int rc = -EINVAL;
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
 
 	if (!(adapter->flags & IXGBE_FLAG_FCOE_CAPABLE))
 		goto out_disable;
@@ -654,6 +658,9 @@
 	if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
 		goto out_disable;
 
+	if (!atomic_dec_and_test(&fcoe->refcnt))
+		goto out_disable;
+
 	e_info(drv, "Disabling FCoE offload features.\n");
 	netdev->features &= ~NETIF_F_FCOE_CRC;
 	netdev->features &= ~NETIF_F_FSO;
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h
index abf4b2b..4bc2c55 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.h
+++ b/drivers/net/ixgbe/ixgbe_fcoe.h
@@ -66,6 +66,7 @@
 	u8 tc;
 	u8 up;
 #endif
+	atomic_t refcnt;
 	spinlock_t lock;
 	struct pci_pool *pool;
 	struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX];
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index e32af43..f856312 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -50,7 +50,7 @@
 
 char ixgbe_driver_name[] = "ixgbe";
 static const char ixgbe_driver_string[] =
-                              "Intel(R) 10 Gigabit PCI Express Network Driver";
+			      "Intel(R) 10 Gigabit PCI Express Network Driver";
 
 #define DRV_VERSION "2.0.84-k2"
 const char ixgbe_driver_version[] = DRV_VERSION;
@@ -120,7 +120,7 @@
 
 #ifdef CONFIG_IXGBE_DCA
 static int ixgbe_notify_dca(struct notifier_block *, unsigned long event,
-                            void *p);
+			    void *p);
 static struct notifier_block dca_notifier = {
 	.notifier_call = ixgbe_notify_dca,
 	.next          = NULL,
@@ -131,8 +131,8 @@
 #ifdef CONFIG_PCI_IOV
 static unsigned int max_vfs;
 module_param(max_vfs, uint, 0);
-MODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate "
-                 "per physical function");
+MODULE_PARM_DESC(max_vfs,
+		 "Maximum number of virtual functions to allocate per physical function");
 #endif /* CONFIG_PCI_IOV */
 
 MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
@@ -169,8 +169,8 @@
 
 	/* take a breather then clean up driver data */
 	msleep(100);
-	if (adapter->vfinfo)
-		kfree(adapter->vfinfo);
+
+	kfree(adapter->vfinfo);
 	adapter->vfinfo = NULL;
 
 	adapter->num_vfs = 0;
@@ -282,17 +282,17 @@
 			regs[i] = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
 		break;
 	default:
-		printk(KERN_INFO "%-15s %08x\n", reginfo->name,
+		pr_info("%-15s %08x\n", reginfo->name,
 			IXGBE_READ_REG(hw, reginfo->ofs));
 		return;
 	}
 
 	for (i = 0; i < 8; i++) {
 		snprintf(rname, 16, "%s[%d-%d]", reginfo->name, i*8, i*8+7);
-		printk(KERN_ERR "%-15s ", rname);
+		pr_err("%-15s", rname);
 		for (j = 0; j < 8; j++)
-			printk(KERN_CONT "%08x ", regs[i*8+j]);
-		printk(KERN_CONT "\n");
+			pr_cont(" %08x", regs[i*8+j]);
+		pr_cont("\n");
 	}
 
 }
@@ -322,18 +322,18 @@
 	/* Print netdevice Info */
 	if (netdev) {
 		dev_info(&adapter->pdev->dev, "Net device Info\n");
-		printk(KERN_INFO "Device Name     state            "
+		pr_info("Device Name     state            "
 			"trans_start      last_rx\n");
-		printk(KERN_INFO "%-15s %016lX %016lX %016lX\n",
-		netdev->name,
-		netdev->state,
-		netdev->trans_start,
-		netdev->last_rx);
+		pr_info("%-15s %016lX %016lX %016lX\n",
+			netdev->name,
+			netdev->state,
+			netdev->trans_start,
+			netdev->last_rx);
 	}
 
 	/* Print Registers */
 	dev_info(&adapter->pdev->dev, "Register Dump\n");
-	printk(KERN_INFO " Register Name   Value\n");
+	pr_info(" Register Name   Value\n");
 	for (reginfo = (struct ixgbe_reg_info *)ixgbe_reg_info_tbl;
 	     reginfo->name; reginfo++) {
 		ixgbe_regdump(hw, reginfo);
@@ -344,13 +344,12 @@
 		goto exit;
 
 	dev_info(&adapter->pdev->dev, "TX Rings Summary\n");
-	printk(KERN_INFO "Queue [NTU] [NTC] [bi(ntc)->dma  ] "
-		"leng ntw timestamp\n");
+	pr_info("Queue [NTU] [NTC] [bi(ntc)->dma  ] leng ntw timestamp\n");
 	for (n = 0; n < adapter->num_tx_queues; n++) {
 		tx_ring = adapter->tx_ring[n];
 		tx_buffer_info =
 			&tx_ring->tx_buffer_info[tx_ring->next_to_clean];
-		printk(KERN_INFO " %5d %5X %5X %016llX %04X %3X %016llX\n",
+		pr_info(" %5d %5X %5X %016llX %04X %3X %016llX\n",
 			   n, tx_ring->next_to_use, tx_ring->next_to_clean,
 			   (u64)tx_buffer_info->dma,
 			   tx_buffer_info->length,
@@ -377,18 +376,18 @@
 
 	for (n = 0; n < adapter->num_tx_queues; n++) {
 		tx_ring = adapter->tx_ring[n];
-		printk(KERN_INFO "------------------------------------\n");
-		printk(KERN_INFO "TX QUEUE INDEX = %d\n", tx_ring->queue_index);
-		printk(KERN_INFO "------------------------------------\n");
-		printk(KERN_INFO "T [desc]     [address 63:0  ] "
+		pr_info("------------------------------------\n");
+		pr_info("TX QUEUE INDEX = %d\n", tx_ring->queue_index);
+		pr_info("------------------------------------\n");
+		pr_info("T [desc]     [address 63:0  ] "
 			"[PlPOIdStDDt Ln] [bi->dma       ] "
 			"leng  ntw timestamp        bi->skb\n");
 
 		for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
-			tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
+			tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
 			tx_buffer_info = &tx_ring->tx_buffer_info[i];
 			u0 = (struct my_u0 *)tx_desc;
-			printk(KERN_INFO "T [0x%03X]    %016llX %016llX %016llX"
+			pr_info("T [0x%03X]    %016llX %016llX %016llX"
 				" %04X  %3X %016llX %p", i,
 				le64_to_cpu(u0->a),
 				le64_to_cpu(u0->b),
@@ -399,13 +398,13 @@
 				tx_buffer_info->skb);
 			if (i == tx_ring->next_to_use &&
 				i == tx_ring->next_to_clean)
-				printk(KERN_CONT " NTC/U\n");
+				pr_cont(" NTC/U\n");
 			else if (i == tx_ring->next_to_use)
-				printk(KERN_CONT " NTU\n");
+				pr_cont(" NTU\n");
 			else if (i == tx_ring->next_to_clean)
-				printk(KERN_CONT " NTC\n");
+				pr_cont(" NTC\n");
 			else
-				printk(KERN_CONT "\n");
+				pr_cont("\n");
 
 			if (netif_msg_pktdata(adapter) &&
 				tx_buffer_info->dma != 0)
@@ -419,11 +418,11 @@
 	/* Print RX Rings Summary */
 rx_ring_summary:
 	dev_info(&adapter->pdev->dev, "RX Rings Summary\n");
-	printk(KERN_INFO "Queue [NTU] [NTC]\n");
+	pr_info("Queue [NTU] [NTC]\n");
 	for (n = 0; n < adapter->num_rx_queues; n++) {
 		rx_ring = adapter->rx_ring[n];
-		printk(KERN_INFO "%5d %5X %5X\n", n,
-			   rx_ring->next_to_use, rx_ring->next_to_clean);
+		pr_info("%5d %5X %5X\n",
+			n, rx_ring->next_to_use, rx_ring->next_to_clean);
 	}
 
 	/* Print RX Rings */
@@ -454,30 +453,30 @@
 	 */
 	for (n = 0; n < adapter->num_rx_queues; n++) {
 		rx_ring = adapter->rx_ring[n];
-		printk(KERN_INFO "------------------------------------\n");
-		printk(KERN_INFO "RX QUEUE INDEX = %d\n", rx_ring->queue_index);
-		printk(KERN_INFO "------------------------------------\n");
-		printk(KERN_INFO "R  [desc]      [ PktBuf     A0] "
+		pr_info("------------------------------------\n");
+		pr_info("RX QUEUE INDEX = %d\n", rx_ring->queue_index);
+		pr_info("------------------------------------\n");
+		pr_info("R  [desc]      [ PktBuf     A0] "
 			"[  HeadBuf   DD] [bi->dma       ] [bi->skb] "
 			"<-- Adv Rx Read format\n");
-		printk(KERN_INFO "RWB[desc]      [PcsmIpSHl PtRs] "
+		pr_info("RWB[desc]      [PcsmIpSHl PtRs] "
 			"[vl er S cks ln] ---------------- [bi->skb] "
 			"<-- Adv Rx Write-Back format\n");
 
 		for (i = 0; i < rx_ring->count; i++) {
 			rx_buffer_info = &rx_ring->rx_buffer_info[i];
-			rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
+			rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
 			u0 = (struct my_u0 *)rx_desc;
 			staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
 			if (staterr & IXGBE_RXD_STAT_DD) {
 				/* Descriptor Done */
-				printk(KERN_INFO "RWB[0x%03X]     %016llX "
+				pr_info("RWB[0x%03X]     %016llX "
 					"%016llX ---------------- %p", i,
 					le64_to_cpu(u0->a),
 					le64_to_cpu(u0->b),
 					rx_buffer_info->skb);
 			} else {
-				printk(KERN_INFO "R  [0x%03X]     %016llX "
+				pr_info("R  [0x%03X]     %016llX "
 					"%016llX %016llX %p", i,
 					le64_to_cpu(u0->a),
 					le64_to_cpu(u0->b),
@@ -503,11 +502,11 @@
 			}
 
 			if (i == rx_ring->next_to_use)
-				printk(KERN_CONT " NTU\n");
+				pr_cont(" NTU\n");
 			else if (i == rx_ring->next_to_clean)
-				printk(KERN_CONT " NTC\n");
+				pr_cont(" NTC\n");
 			else
-				printk(KERN_CONT "\n");
+				pr_cont("\n");
 
 		}
 	}
@@ -523,7 +522,7 @@
 	/* Let firmware take over control of h/w */
 	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
-	                ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD);
+			ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD);
 }
 
 static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter)
@@ -533,7 +532,7 @@
 	/* Let firmware know the driver has taken over */
 	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
-	                ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD);
+			ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD);
 }
 
 /*
@@ -545,7 +544,7 @@
  *
  */
 static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction,
-	                   u8 queue, u8 msix_vector)
+			   u8 queue, u8 msix_vector)
 {
 	u32 ivar, index;
 	struct ixgbe_hw *hw = &adapter->hw;
@@ -586,7 +585,7 @@
 }
 
 static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter,
-                                          u64 qmask)
+					  u64 qmask)
 {
 	u32 mask;
 
@@ -601,9 +600,9 @@
 	}
 }
 
-static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
-                                             struct ixgbe_tx_buffer
-                                             *tx_buffer_info)
+void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
+				      struct ixgbe_tx_buffer
+				      *tx_buffer_info)
 {
 	if (tx_buffer_info->dma) {
 		if (tx_buffer_info->mapped_as_page)
@@ -637,7 +636,7 @@
  * Returns : true if in xon state (currently not paused)
  */
 static inline bool ixgbe_tx_xon_state(struct ixgbe_adapter *adapter,
-                                      struct ixgbe_ring *tx_ring)
+				      struct ixgbe_ring *tx_ring)
 {
 	u32 txoff = IXGBE_TFCS_TXOFF;
 
@@ -682,8 +681,8 @@
 }
 
 static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter,
-                                       struct ixgbe_ring *tx_ring,
-                                       unsigned int eop)
+				       struct ixgbe_ring *tx_ring,
+				       unsigned int eop)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 
@@ -695,7 +694,7 @@
 	    ixgbe_tx_xon_state(adapter, tx_ring)) {
 		/* detected Tx unit hang */
 		union ixgbe_adv_tx_desc *tx_desc;
-		tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
+		tx_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
 		e_err(drv, "Detected Tx Unit Hang\n"
 		      "  Tx Queue             <%d>\n"
 		      "  TDH, TDT             <%x>, <%x>\n"
@@ -732,7 +731,7 @@
  * @tx_ring: tx ring to clean
  **/
 static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
-                               struct ixgbe_ring *tx_ring)
+			       struct ixgbe_ring *tx_ring)
 {
 	struct ixgbe_adapter *adapter = q_vector->adapter;
 	struct net_device *netdev = adapter->netdev;
@@ -743,7 +742,7 @@
 
 	i = tx_ring->next_to_clean;
 	eop = tx_ring->tx_buffer_info[i].next_to_watch;
-	eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
+	eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
 
 	while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) &&
 	       (count < tx_ring->work_limit)) {
@@ -751,7 +750,7 @@
 		rmb(); /* read buffer_info after eop_desc */
 		for ( ; !cleaned; count++) {
 			struct sk_buff *skb;
-			tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
+			tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
 			tx_buffer_info = &tx_ring->tx_buffer_info[i];
 			cleaned = (i == eop);
 			skb = tx_buffer_info->skb;
@@ -781,7 +780,7 @@
 			}
 
 			ixgbe_unmap_and_free_tx_resource(adapter,
-			                                 tx_buffer_info);
+							 tx_buffer_info);
 
 			tx_desc->wb.status = 0;
 
@@ -791,14 +790,14 @@
 		}
 
 		eop = tx_ring->tx_buffer_info[i].next_to_watch;
-		eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
+		eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
 	}
 
 	tx_ring->next_to_clean = i;
 
 #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
 	if (unlikely(count && netif_carrier_ok(netdev) &&
-	             (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
+		     (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
 		/* Make sure that anybody stopping the queue after this
 		 * sees the new next_to_clean.
 		 */
@@ -825,14 +824,16 @@
 
 	tx_ring->total_bytes += total_bytes;
 	tx_ring->total_packets += total_packets;
+	u64_stats_update_begin(&tx_ring->syncp);
 	tx_ring->stats.packets += total_packets;
 	tx_ring->stats.bytes += total_bytes;
-	return (count < tx_ring->work_limit);
+	u64_stats_update_end(&tx_ring->syncp);
+	return count < tx_ring->work_limit;
 }
 
 #ifdef CONFIG_IXGBE_DCA
 static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
-                                struct ixgbe_ring *rx_ring)
+				struct ixgbe_ring *rx_ring)
 {
 	u32 rxctrl;
 	int cpu = get_cpu();
@@ -846,13 +847,13 @@
 		} else if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
 			rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK_82599;
 			rxctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) <<
-			           IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599);
+				   IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599);
 		}
 		rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN;
 		rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN;
 		rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_RRO_EN);
 		rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
-		            IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
+			    IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl);
 		rx_ring->cpu = cpu;
 	}
@@ -860,7 +861,7 @@
 }
 
 static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
-                                struct ixgbe_ring *tx_ring)
+				struct ixgbe_ring *tx_ring)
 {
 	u32 txctrl;
 	int cpu = get_cpu();
@@ -878,7 +879,7 @@
 			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(q));
 			txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599;
 			txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) <<
-			          IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599);
+				  IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599);
 			txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
 			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(q), txctrl);
 		}
@@ -946,27 +947,22 @@
  * @rx_desc: rx descriptor
  **/
 static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
-                              struct sk_buff *skb, u8 status,
-                              struct ixgbe_ring *ring,
-                              union ixgbe_adv_rx_desc *rx_desc)
+			      struct sk_buff *skb, u8 status,
+			      struct ixgbe_ring *ring,
+			      union ixgbe_adv_rx_desc *rx_desc)
 {
 	struct ixgbe_adapter *adapter = q_vector->adapter;
 	struct napi_struct *napi = &q_vector->napi;
 	bool is_vlan = (status & IXGBE_RXD_STAT_VP);
 	u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
 
-	skb_record_rx_queue(skb, ring->queue_index);
-	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
-		if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK))
-			vlan_gro_receive(napi, adapter->vlgrp, tag, skb);
-		else
-			napi_gro_receive(napi, skb);
-	} else {
-		if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK))
-			vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
-		else
-			netif_rx(skb);
-	}
+	if (is_vlan && (tag & VLAN_VID_MASK))
+		__vlan_hwaccel_put_tag(skb, tag);
+
+	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
+		napi_gro_receive(napi, skb);
+	else
+		netif_rx(skb);
 }
 
 /**
@@ -981,7 +977,7 @@
 {
 	u32 status_err = le32_to_cpu(rx_desc->wb.upper.status_error);
 
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 
 	/* Rx csum disabled */
 	if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
@@ -1017,7 +1013,7 @@
 }
 
 static inline void ixgbe_release_rx_desc(struct ixgbe_hw *hw,
-                                         struct ixgbe_ring *rx_ring, u32 val)
+					 struct ixgbe_ring *rx_ring, u32 val)
 {
 	/*
 	 * Force memory writes to complete before letting h/w
@@ -1033,25 +1029,27 @@
  * ixgbe_alloc_rx_buffers - Replace used receive buffers; packet split
  * @adapter: address of board private structure
  **/
-static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
-                                   struct ixgbe_ring *rx_ring,
-                                   int cleaned_count)
+void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
+			    struct ixgbe_ring *rx_ring,
+			    int cleaned_count)
 {
+	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 	union ixgbe_adv_rx_desc *rx_desc;
 	struct ixgbe_rx_buffer *bi;
 	unsigned int i;
+	unsigned int bufsz = rx_ring->rx_buf_len;
 
 	i = rx_ring->next_to_use;
 	bi = &rx_ring->rx_buffer_info[i];
 
 	while (cleaned_count--) {
-		rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
+		rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
 
 		if (!bi->page_dma &&
 		    (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)) {
 			if (!bi->page) {
-				bi->page = alloc_page(GFP_ATOMIC);
+				bi->page = netdev_alloc_page(netdev);
 				if (!bi->page) {
 					adapter->alloc_rx_page_failed++;
 					goto no_buffers;
@@ -1063,29 +1061,28 @@
 			}
 
 			bi->page_dma = dma_map_page(&pdev->dev, bi->page,
-			                            bi->page_offset,
-			                            (PAGE_SIZE / 2),
+						    bi->page_offset,
+						    (PAGE_SIZE / 2),
 						    DMA_FROM_DEVICE);
 		}
 
 		if (!bi->skb) {
-			struct sk_buff *skb;
-			/* netdev_alloc_skb reserves 32 bytes up front!! */
-			uint bufsz = rx_ring->rx_buf_len + SMP_CACHE_BYTES;
-			skb = netdev_alloc_skb(adapter->netdev, bufsz);
+			struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev,
+									bufsz);
+			bi->skb = skb;
 
 			if (!skb) {
 				adapter->alloc_rx_buff_failed++;
 				goto no_buffers;
 			}
+			/* initialize queue mapping */
+			skb_record_rx_queue(skb, rx_ring->queue_index);
+		}
 
-			/* advance the data pointer to the next cache line */
-			skb_reserve(skb, (PTR_ALIGN(skb->data, SMP_CACHE_BYTES)
-			                  - skb->data));
-
-			bi->skb = skb;
-			bi->dma = dma_map_single(&pdev->dev, skb->data,
-			                         rx_ring->rx_buf_len,
+		if (!bi->dma) {
+			bi->dma = dma_map_single(&pdev->dev,
+						 bi->skb->data,
+						 rx_ring->rx_buf_len,
 						 DMA_FROM_DEVICE);
 		}
 		/* Refresh the desc even if buffer_addrs didn't change because
@@ -1095,6 +1092,7 @@
 			rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
 		} else {
 			rx_desc->read.pkt_addr = cpu_to_le64(bi->dma);
+			rx_desc->read.hdr_addr = 0;
 		}
 
 		i++;
@@ -1126,8 +1124,8 @@
 static inline u32 ixgbe_get_rsc_count(union ixgbe_adv_rx_desc *rx_desc)
 {
 	return (le32_to_cpu(rx_desc->wb.lower.lo_dword.data) &
-	        IXGBE_RXDADV_RSCCNT_MASK) >>
-	        IXGBE_RXDADV_RSCCNT_SHIFT;
+		IXGBE_RXDADV_RSCCNT_MASK) >>
+		IXGBE_RXDADV_RSCCNT_SHIFT;
 }
 
 /**
@@ -1140,7 +1138,7 @@
  * turns it into the frag list owner.
  **/
 static inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb,
-                                                        u64 *count)
+							u64 *count)
 {
 	unsigned int frag_list_size = 0;
 
@@ -1168,11 +1166,10 @@
 #define IXGBE_RSC_CB(skb) ((struct ixgbe_rsc_cb *)(skb)->cb)
 
 static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
-                               struct ixgbe_ring *rx_ring,
-                               int *work_done, int work_to_do)
+			       struct ixgbe_ring *rx_ring,
+			       int *work_done, int work_to_do)
 {
 	struct ixgbe_adapter *adapter = q_vector->adapter;
-	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 	union ixgbe_adv_rx_desc *rx_desc, *next_rxd;
 	struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer;
@@ -1188,7 +1185,7 @@
 #endif /* IXGBE_FCOE */
 
 	i = rx_ring->next_to_clean;
-	rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
+	rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
 	staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
 	rx_buffer_info = &rx_ring->rx_buffer_info[i];
 
@@ -1231,9 +1228,9 @@
 				IXGBE_RSC_CB(skb)->dma = rx_buffer_info->dma;
 			} else {
 				dma_unmap_single(&pdev->dev,
-				                 rx_buffer_info->dma,
-				                 rx_ring->rx_buf_len,
-				                 DMA_FROM_DEVICE);
+						 rx_buffer_info->dma,
+						 rx_ring->rx_buf_len,
+						 DMA_FROM_DEVICE);
 			}
 			rx_buffer_info->dma = 0;
 			skb_put(skb, len);
@@ -1244,9 +1241,9 @@
 				       PAGE_SIZE / 2, DMA_FROM_DEVICE);
 			rx_buffer_info->page_dma = 0;
 			skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
-			                   rx_buffer_info->page,
-			                   rx_buffer_info->page_offset,
-			                   upper_len);
+					   rx_buffer_info->page,
+					   rx_buffer_info->page_offset,
+					   upper_len);
 
 			if ((rx_ring->rx_buf_len > (PAGE_SIZE / 2)) ||
 			    (page_count(rx_buffer_info->page) != 1))
@@ -1263,7 +1260,7 @@
 		if (i == rx_ring->count)
 			i = 0;
 
-		next_rxd = IXGBE_RX_DESC_ADV(*rx_ring, i);
+		next_rxd = IXGBE_RX_DESC_ADV(rx_ring, i);
 		prefetch(next_rxd);
 		cleaned_count++;
 
@@ -1280,24 +1277,28 @@
 
 		if (staterr & IXGBE_RXD_STAT_EOP) {
 			if (skb->prev)
-				skb = ixgbe_transform_rsc_queue(skb, &(rx_ring->rsc_count));
+				skb = ixgbe_transform_rsc_queue(skb,
+								&(rx_ring->rsc_count));
 			if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
 				if (IXGBE_RSC_CB(skb)->delay_unmap) {
 					dma_unmap_single(&pdev->dev,
 							 IXGBE_RSC_CB(skb)->dma,
-					                 rx_ring->rx_buf_len,
+							 rx_ring->rx_buf_len,
 							 DMA_FROM_DEVICE);
 					IXGBE_RSC_CB(skb)->dma = 0;
 					IXGBE_RSC_CB(skb)->delay_unmap = false;
 				}
 				if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)
-					rx_ring->rsc_count += skb_shinfo(skb)->nr_frags;
+					rx_ring->rsc_count +=
+						skb_shinfo(skb)->nr_frags;
 				else
 					rx_ring->rsc_count++;
 				rx_ring->rsc_flush++;
 			}
+			u64_stats_update_begin(&rx_ring->syncp);
 			rx_ring->stats.packets++;
 			rx_ring->stats.bytes += skb->len;
+			u64_stats_update_end(&rx_ring->syncp);
 		} else {
 			if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
 				rx_buffer_info->skb = next_buffer->skb;
@@ -1373,8 +1374,6 @@
 
 	rx_ring->total_packets += total_rx_packets;
 	rx_ring->total_bytes += total_rx_bytes;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
 
 	return cleaned;
 }
@@ -1403,24 +1402,24 @@
 		q_vector = adapter->q_vector[v_idx];
 		/* XXX for_each_set_bit(...) */
 		r_idx = find_first_bit(q_vector->rxr_idx,
-		                       adapter->num_rx_queues);
+				       adapter->num_rx_queues);
 
 		for (i = 0; i < q_vector->rxr_count; i++) {
 			j = adapter->rx_ring[r_idx]->reg_idx;
 			ixgbe_set_ivar(adapter, 0, j, v_idx);
 			r_idx = find_next_bit(q_vector->rxr_idx,
-			                      adapter->num_rx_queues,
-			                      r_idx + 1);
+					      adapter->num_rx_queues,
+					      r_idx + 1);
 		}
 		r_idx = find_first_bit(q_vector->txr_idx,
-		                       adapter->num_tx_queues);
+				       adapter->num_tx_queues);
 
 		for (i = 0; i < q_vector->txr_count; i++) {
 			j = adapter->tx_ring[r_idx]->reg_idx;
 			ixgbe_set_ivar(adapter, 1, j, v_idx);
 			r_idx = find_next_bit(q_vector->txr_idx,
-			                      adapter->num_tx_queues,
-			                      r_idx + 1);
+					      adapter->num_tx_queues,
+					      r_idx + 1);
 		}
 
 		if (q_vector->txr_count && !q_vector->rxr_count)
@@ -1431,11 +1430,26 @@
 			q_vector->eitr = adapter->rx_eitr_param;
 
 		ixgbe_write_eitr(q_vector);
+		/* If Flow Director is enabled, set interrupt affinity */
+		if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
+		    (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+			/*
+			 * Allocate the affinity_hint cpumask, assign the mask
+			 * for this vector, and set our affinity_hint for
+			 * this irq.
+			 */
+			if (!alloc_cpumask_var(&q_vector->affinity_mask,
+			                       GFP_KERNEL))
+				return;
+			cpumask_set_cpu(v_idx, q_vector->affinity_mask);
+			irq_set_affinity_hint(adapter->msix_entries[v_idx].vector,
+			                      q_vector->affinity_mask);
+		}
 	}
 
 	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
 		ixgbe_set_ivar(adapter, -1, IXGBE_IVAR_OTHER_CAUSES_INDEX,
-		               v_idx);
+			       v_idx);
 	else if (adapter->hw.mac.type == ixgbe_mac_82599EB)
 		ixgbe_set_ivar(adapter, -1, 1, v_idx);
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), 1950);
@@ -1477,8 +1491,8 @@
  *      parameter (see ixgbe_param.c)
  **/
 static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter,
-                           u32 eitr, u8 itr_setting,
-                           int packets, int bytes)
+			   u32 eitr, u8 itr_setting,
+			   int packets, int bytes)
 {
 	unsigned int retval = itr_setting;
 	u32 timepassed_us;
@@ -1567,30 +1581,30 @@
 	for (i = 0; i < q_vector->txr_count; i++) {
 		tx_ring = adapter->tx_ring[r_idx];
 		ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
-		                           q_vector->tx_itr,
-		                           tx_ring->total_packets,
-		                           tx_ring->total_bytes);
+					   q_vector->tx_itr,
+					   tx_ring->total_packets,
+					   tx_ring->total_bytes);
 		/* if the result for this queue would decrease interrupt
 		 * rate for this vector then use that result */
 		q_vector->tx_itr = ((q_vector->tx_itr > ret_itr) ?
-		                    q_vector->tx_itr - 1 : ret_itr);
+				    q_vector->tx_itr - 1 : ret_itr);
 		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
-		                      r_idx + 1);
+				      r_idx + 1);
 	}
 
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
 	for (i = 0; i < q_vector->rxr_count; i++) {
 		rx_ring = adapter->rx_ring[r_idx];
 		ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
-		                           q_vector->rx_itr,
-		                           rx_ring->total_packets,
-		                           rx_ring->total_bytes);
+					   q_vector->rx_itr,
+					   rx_ring->total_packets,
+					   rx_ring->total_bytes);
 		/* if the result for this queue would decrease interrupt
 		 * rate for this vector then use that result */
 		q_vector->rx_itr = ((q_vector->rx_itr > ret_itr) ?
-		                    q_vector->rx_itr - 1 : ret_itr);
+				    q_vector->rx_itr - 1 : ret_itr);
 		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
-		                      r_idx + 1);
+				      r_idx + 1);
 	}
 
 	current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
@@ -1627,39 +1641,40 @@
 static void ixgbe_check_overtemp_task(struct work_struct *work)
 {
 	struct ixgbe_adapter *adapter = container_of(work,
-	                                             struct ixgbe_adapter,
-	                                             check_overtemp_task);
+						     struct ixgbe_adapter,
+						     check_overtemp_task);
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 eicr = adapter->interrupt_event;
 
-	if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) {
-		switch (hw->device_id) {
-		case IXGBE_DEV_ID_82599_T3_LOM: {
-			u32 autoneg;
-			bool link_up = false;
+	if (!(adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE))
+		return;
 
-			if (hw->mac.ops.check_link)
-				hw->mac.ops.check_link(hw, &autoneg, &link_up, false);
+	switch (hw->device_id) {
+	case IXGBE_DEV_ID_82599_T3_LOM: {
+		u32 autoneg;
+		bool link_up = false;
 
-			if (((eicr & IXGBE_EICR_GPI_SDP0) && (!link_up)) ||
-			    (eicr & IXGBE_EICR_LSC))
-				/* Check if this is due to overtemp */
-				if (hw->phy.ops.check_overtemp(hw) == IXGBE_ERR_OVERTEMP)
-					break;
-			}
-			return;
-		default:
-			if (!(eicr & IXGBE_EICR_GPI_SDP0))
-				return;
-			break;
-		}
-		e_crit(drv, "Network adapter has been stopped because it has "
-		       "over heated. Restart the computer. If the problem "
-		       "persists, power off the system and replace the "
-		       "adapter\n");
-		/* write to clear the interrupt */
-		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0);
+		if (hw->mac.ops.check_link)
+			hw->mac.ops.check_link(hw, &autoneg, &link_up, false);
+
+		if (((eicr & IXGBE_EICR_GPI_SDP0) && (!link_up)) ||
+		    (eicr & IXGBE_EICR_LSC))
+			/* Check if this is due to overtemp */
+			if (hw->phy.ops.check_overtemp(hw) == IXGBE_ERR_OVERTEMP)
+				break;
+		return;
 	}
+	default:
+		if (!(eicr & IXGBE_EICR_GPI_SDP0))
+			return;
+		break;
+	}
+	e_crit(drv,
+	       "Network adapter has been stopped because it has over heated. "
+	       "Restart the computer. If the problem persists, "
+	       "power off the system and replace the adapter\n");
+	/* write to clear the interrupt */
+	IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0);
 }
 
 static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr)
@@ -1746,9 +1761,9 @@
 			netif_tx_stop_all_queues(netdev);
 			for (i = 0; i < adapter->num_tx_queues; i++) {
 				struct ixgbe_ring *tx_ring =
-				                            adapter->tx_ring[i];
+							    adapter->tx_ring[i];
 				if (test_and_clear_bit(__IXGBE_FDIR_INIT_DONE,
-				                       &tx_ring->reinit_state))
+						       &tx_ring->reinit_state))
 					schedule_work(&adapter->fdir_reinit_task);
 			}
 		}
@@ -1777,7 +1792,7 @@
 }
 
 static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
-                                            u64 qmask)
+					    u64 qmask)
 {
 	u32 mask;
 
@@ -1809,7 +1824,7 @@
 		tx_ring->total_bytes = 0;
 		tx_ring->total_packets = 0;
 		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
-		                      r_idx + 1);
+				      r_idx + 1);
 	}
 
 	/* EIAM disabled interrupts (on this vector) for us */
@@ -1837,7 +1852,7 @@
 		rx_ring->total_bytes = 0;
 		rx_ring->total_packets = 0;
 		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
-		                      r_idx + 1);
+				      r_idx + 1);
 	}
 
 	if (!q_vector->rxr_count)
@@ -1867,7 +1882,7 @@
 		ring->total_bytes = 0;
 		ring->total_packets = 0;
 		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
-		                      r_idx + 1);
+				      r_idx + 1);
 	}
 
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
@@ -1876,7 +1891,7 @@
 		ring->total_bytes = 0;
 		ring->total_packets = 0;
 		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
-		                      r_idx + 1);
+				      r_idx + 1);
 	}
 
 	/* EIAM disabled interrupts (on this vector) for us */
@@ -1896,7 +1911,7 @@
 static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
 {
 	struct ixgbe_q_vector *q_vector =
-	                       container_of(napi, struct ixgbe_q_vector, napi);
+			       container_of(napi, struct ixgbe_q_vector, napi);
 	struct ixgbe_adapter *adapter = q_vector->adapter;
 	struct ixgbe_ring *rx_ring = NULL;
 	int work_done = 0;
@@ -1918,7 +1933,7 @@
 			ixgbe_set_itr_msix(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			ixgbe_irq_enable_queues(adapter,
-			                        ((u64)1 << q_vector->v_idx));
+						((u64)1 << q_vector->v_idx));
 	}
 
 	return work_done;
@@ -1935,7 +1950,7 @@
 static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
 {
 	struct ixgbe_q_vector *q_vector =
-	                       container_of(napi, struct ixgbe_q_vector, napi);
+			       container_of(napi, struct ixgbe_q_vector, napi);
 	struct ixgbe_adapter *adapter = q_vector->adapter;
 	struct ixgbe_ring *ring = NULL;
 	int work_done = 0, i;
@@ -1951,7 +1966,7 @@
 #endif
 		tx_clean_complete &= ixgbe_clean_tx_irq(q_vector, ring);
 		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
-		                      r_idx + 1);
+				      r_idx + 1);
 	}
 
 	/* attempt to distribute budget to each queue fairly, but don't allow
@@ -1967,7 +1982,7 @@
 #endif
 		ixgbe_clean_rx_irq(q_vector, ring, &work_done, budget);
 		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
-		                      r_idx + 1);
+				      r_idx + 1);
 	}
 
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
@@ -1979,7 +1994,7 @@
 			ixgbe_set_itr_msix(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			ixgbe_irq_enable_queues(adapter,
-			                        ((u64)1 << q_vector->v_idx));
+						((u64)1 << q_vector->v_idx));
 		return 0;
 	}
 
@@ -1997,7 +2012,7 @@
 static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
 {
 	struct ixgbe_q_vector *q_vector =
-	                       container_of(napi, struct ixgbe_q_vector, napi);
+			       container_of(napi, struct ixgbe_q_vector, napi);
 	struct ixgbe_adapter *adapter = q_vector->adapter;
 	struct ixgbe_ring *tx_ring = NULL;
 	int work_done = 0;
@@ -2019,14 +2034,15 @@
 		if (adapter->tx_itr_setting & 1)
 			ixgbe_set_itr_msix(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
-			ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
+			ixgbe_irq_enable_queues(adapter,
+						((u64)1 << q_vector->v_idx));
 	}
 
 	return work_done;
 }
 
 static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
-                                     int r_idx)
+				     int r_idx)
 {
 	struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
 
@@ -2035,7 +2051,7 @@
 }
 
 static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
-                                     int t_idx)
+				     int t_idx)
 {
 	struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
 
@@ -2055,7 +2071,7 @@
  * mapping configurations in here.
  **/
 static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter,
-                                      int vectors)
+				      int vectors)
 {
 	int v_start = 0;
 	int rxr_idx = 0, txr_idx = 0;
@@ -2122,7 +2138,7 @@
 	struct net_device *netdev = adapter->netdev;
 	irqreturn_t (*handler)(int, void *);
 	int i, vector, q_vectors, err;
-	int ri=0, ti=0;
+	int ri = 0, ti = 0;
 
 	/* Decrement for Other and TCP Timer vectors */
 	q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
@@ -2133,26 +2149,24 @@
 		goto out;
 
 #define SET_HANDLER(_v) ((!(_v)->rxr_count) ? &ixgbe_msix_clean_tx : \
-                         (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
-                         &ixgbe_msix_clean_many)
+			 (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
+			 &ixgbe_msix_clean_many)
 	for (vector = 0; vector < q_vectors; vector++) {
 		handler = SET_HANDLER(adapter->q_vector[vector]);
 
-		if(handler == &ixgbe_msix_clean_rx) {
+		if (handler == &ixgbe_msix_clean_rx) {
 			sprintf(adapter->name[vector], "%s-%s-%d",
 				netdev->name, "rx", ri++);
-		}
-		else if(handler == &ixgbe_msix_clean_tx) {
+		} else if (handler == &ixgbe_msix_clean_tx) {
 			sprintf(adapter->name[vector], "%s-%s-%d",
 				netdev->name, "tx", ti++);
-		}
-		else
+		} else
 			sprintf(adapter->name[vector], "%s-%s-%d",
 				netdev->name, "TxRx", vector);
 
 		err = request_irq(adapter->msix_entries[vector].vector,
-		                  handler, 0, adapter->name[vector],
-		                  adapter->q_vector[vector]);
+				  handler, 0, adapter->name[vector],
+				  adapter->q_vector[vector]);
 		if (err) {
 			e_err(probe, "request_irq failed for MSIX interrupt "
 			      "Error: %d\n", err);
@@ -2162,7 +2176,7 @@
 
 	sprintf(adapter->name[vector], "%s:lsc", netdev->name);
 	err = request_irq(adapter->msix_entries[vector].vector,
-	                  ixgbe_msix_lsc, 0, adapter->name[vector], netdev);
+			  ixgbe_msix_lsc, 0, adapter->name[vector], netdev);
 	if (err) {
 		e_err(probe, "request_irq for msix_lsc failed: %d\n", err);
 		goto free_queue_irqs;
@@ -2173,7 +2187,7 @@
 free_queue_irqs:
 	for (i = vector - 1; i >= 0; i--)
 		free_irq(adapter->msix_entries[--vector].vector,
-		         adapter->q_vector[i]);
+			 adapter->q_vector[i]);
 	adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
 	pci_disable_msix(adapter->pdev);
 	kfree(adapter->msix_entries);
@@ -2191,13 +2205,13 @@
 	struct ixgbe_ring *tx_ring = adapter->tx_ring[0];
 
 	q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr,
-	                                    q_vector->tx_itr,
-	                                    tx_ring->total_packets,
-	                                    tx_ring->total_bytes);
+					    q_vector->tx_itr,
+					    tx_ring->total_packets,
+					    tx_ring->total_bytes);
 	q_vector->rx_itr = ixgbe_update_itr(adapter, new_itr,
-	                                    q_vector->rx_itr,
-	                                    rx_ring->total_packets,
-	                                    rx_ring->total_bytes);
+					    q_vector->rx_itr,
+					    rx_ring->total_packets,
+					    rx_ring->total_bytes);
 
 	current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
 
@@ -2231,7 +2245,8 @@
  * ixgbe_irq_enable - Enable default interrupt generation settings
  * @adapter: board private structure
  **/
-static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
+static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
+				    bool flush)
 {
 	u32 mask;
 
@@ -2252,8 +2267,10 @@
 		mask |= IXGBE_EIMS_FLOW_DIR;
 
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
-	ixgbe_irq_enable_queues(adapter, ~0);
-	IXGBE_WRITE_FLUSH(&adapter->hw);
+	if (queues)
+		ixgbe_irq_enable_queues(adapter, ~0);
+	if (flush)
+		IXGBE_WRITE_FLUSH(&adapter->hw);
 
 	if (adapter->num_vfs > 32) {
 		u32 eitrsel = (1 << (adapter->num_vfs - 32)) - 1;
@@ -2275,7 +2292,7 @@
 	u32 eicr;
 
 	/*
-	 * Workaround for silicon errata.  Mask the interrupts
+	 * Workaround for silicon errata on 82598.  Mask the interrupts
 	 * before the read of EICR.
 	 */
 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
@@ -2284,10 +2301,15 @@
 	 * therefore no explict interrupt disable is necessary */
 	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
 	if (!eicr) {
-		/* shared interrupt alert!
+		/*
+		 * shared interrupt alert!
 		 * make sure interrupts are enabled because the read will
-		 * have disabled interrupts due to EIAM */
-		ixgbe_irq_enable(adapter);
+		 * have disabled interrupts due to EIAM
+		 * finish the workaround of silicon errata on 82598.  Unmask
+		 * the interrupt that we masked before the EICR read.
+		 */
+		if (!test_bit(__IXGBE_DOWN, &adapter->state))
+			ixgbe_irq_enable(adapter, true, true);
 		return IRQ_NONE;	/* Not our interrupt */
 	}
 
@@ -2311,6 +2333,14 @@
 		__napi_schedule(&(q_vector->napi));
 	}
 
+	/*
+	 * re-enable link(maybe) and non-queue interrupts, no flush.
+	 * ixgbe_poll will re-enable the queue interrupts
+	 */
+
+	if (!test_bit(__IXGBE_DOWN, &adapter->state))
+		ixgbe_irq_enable(adapter, false, false);
+
 	return IRQ_HANDLED;
 }
 
@@ -2343,10 +2373,10 @@
 		err = ixgbe_request_msix_irqs(adapter);
 	} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
 		err = request_irq(adapter->pdev->irq, ixgbe_intr, 0,
-		                  netdev->name, netdev);
+				  netdev->name, netdev);
 	} else {
 		err = request_irq(adapter->pdev->irq, ixgbe_intr, IRQF_SHARED,
-		                  netdev->name, netdev);
+				  netdev->name, netdev);
 	}
 
 	if (err)
@@ -2370,7 +2400,7 @@
 		i--;
 		for (; i >= 0; i--) {
 			free_irq(adapter->msix_entries[i].vector,
-			         adapter->q_vector[i]);
+				 adapter->q_vector[i]);
 		}
 
 		ixgbe_reset_q_vectors(adapter);
@@ -2413,7 +2443,7 @@
 	struct ixgbe_hw *hw = &adapter->hw;
 
 	IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
-	                EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param));
+			EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param));
 
 	ixgbe_set_ivar(adapter, 0, 0, 0);
 	ixgbe_set_ivar(adapter, 1, 0, 0);
@@ -2425,6 +2455,111 @@
 }
 
 /**
+ * ixgbe_configure_tx_ring - Configure 8259x Tx ring after Reset
+ * @adapter: board private structure
+ * @ring: structure containing ring specific data
+ *
+ * Configure the Tx descriptor ring after a reset.
+ **/
+void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
+			     struct ixgbe_ring *ring)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u64 tdba = ring->dma;
+	int wait_loop = 10;
+	u32 txdctl;
+	u16 reg_idx = ring->reg_idx;
+
+	/* disable queue to avoid issues while updating state */
+	txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
+	IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx),
+			txdctl & ~IXGBE_TXDCTL_ENABLE);
+	IXGBE_WRITE_FLUSH(hw);
+
+	IXGBE_WRITE_REG(hw, IXGBE_TDBAL(reg_idx),
+			(tdba & DMA_BIT_MASK(32)));
+	IXGBE_WRITE_REG(hw, IXGBE_TDBAH(reg_idx), (tdba >> 32));
+	IXGBE_WRITE_REG(hw, IXGBE_TDLEN(reg_idx),
+			ring->count * sizeof(union ixgbe_adv_tx_desc));
+	IXGBE_WRITE_REG(hw, IXGBE_TDH(reg_idx), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_TDT(reg_idx), 0);
+	ring->head = IXGBE_TDH(reg_idx);
+	ring->tail = IXGBE_TDT(reg_idx);
+
+	/* configure fetching thresholds */
+	if (adapter->rx_itr_setting == 0) {
+		/* cannot set wthresh when itr==0 */
+		txdctl &= ~0x007F0000;
+	} else {
+		/* enable WTHRESH=8 descriptors, to encourage burst writeback */
+		txdctl |= (8 << 16);
+	}
+	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+		/* PThresh workaround for Tx hang with DFP enabled. */
+		txdctl |= 32;
+	}
+
+	/* reinitialize flowdirector state */
+	set_bit(__IXGBE_FDIR_INIT_DONE, &ring->reinit_state);
+
+	/* enable queue */
+	txdctl |= IXGBE_TXDCTL_ENABLE;
+	IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), txdctl);
+
+	/* TXDCTL.EN will return 0 on 82598 if link is down, so skip it */
+	if (hw->mac.type == ixgbe_mac_82598EB &&
+	    !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
+		return;
+
+	/* poll to verify queue is enabled */
+	do {
+		msleep(1);
+		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
+	} while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE));
+	if (!wait_loop)
+		e_err(drv, "Could not enable Tx Queue %d\n", reg_idx);
+}
+
+static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 rttdcs;
+	u32 mask;
+
+	if (hw->mac.type == ixgbe_mac_82598EB)
+		return;
+
+	/* disable the arbiter while setting MTQC */
+	rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
+	rttdcs |= IXGBE_RTTDCS_ARBDIS;
+	IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
+
+	/* set transmit pool layout */
+	mask = (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_DCB_ENABLED);
+	switch (adapter->flags & mask) {
+
+	case (IXGBE_FLAG_SRIOV_ENABLED):
+		IXGBE_WRITE_REG(hw, IXGBE_MTQC,
+				(IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF));
+		break;
+
+	case (IXGBE_FLAG_DCB_ENABLED):
+		/* We enable 8 traffic classes, DCB only */
+		IXGBE_WRITE_REG(hw, IXGBE_MTQC,
+			      (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ));
+		break;
+
+	default:
+		IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB);
+		break;
+	}
+
+	/* re-enable the arbiter */
+	rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
+	IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
+}
+
+/**
  * ixgbe_configure_tx - Configure 8259x Transmit Unit after Reset
  * @adapter: board private structure
  *
@@ -2432,88 +2567,28 @@
  **/
 static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
 {
-	u64 tdba;
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32 i, j, tdlen, txctrl;
+	u32 dmatxctl;
+	u32 i;
+
+	ixgbe_setup_mtqc(adapter);
+
+	if (hw->mac.type != ixgbe_mac_82598EB) {
+		/* DMATXCTL.EN must be before Tx queues are enabled */
+		dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
+		dmatxctl |= IXGBE_DMATXCTL_TE;
+		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
+	}
 
 	/* Setup the HW Tx Head and Tail descriptor pointers */
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		struct ixgbe_ring *ring = adapter->tx_ring[i];
-		j = ring->reg_idx;
-		tdba = ring->dma;
-		tdlen = ring->count * sizeof(union ixgbe_adv_tx_desc);
-		IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
-		                (tdba & DMA_BIT_MASK(32)));
-		IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
-		IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), tdlen);
-		IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
-		adapter->tx_ring[i]->head = IXGBE_TDH(j);
-		adapter->tx_ring[i]->tail = IXGBE_TDT(j);
-		/*
-		 * Disable Tx Head Writeback RO bit, since this hoses
-		 * bookkeeping if things aren't delivered in order.
-		 */
-		switch (hw->mac.type) {
-		case ixgbe_mac_82598EB:
-			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
-			break;
-		case ixgbe_mac_82599EB:
-		default:
-			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
-			break;
-		}
-		txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
-		switch (hw->mac.type) {
-		case ixgbe_mac_82598EB:
-			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
-			break;
-		case ixgbe_mac_82599EB:
-		default:
-			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
-			break;
-		}
-	}
-
-	if (hw->mac.type == ixgbe_mac_82599EB) {
-		u32 rttdcs;
-		u32 mask;
-
-		/* disable the arbiter while setting MTQC */
-		rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
-		rttdcs |= IXGBE_RTTDCS_ARBDIS;
-		IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
-
-		/* set transmit pool layout */
-		mask = (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_DCB_ENABLED);
-		switch (adapter->flags & mask) {
-
-		case (IXGBE_FLAG_SRIOV_ENABLED):
-			IXGBE_WRITE_REG(hw, IXGBE_MTQC,
-					(IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF));
-			break;
-
-		case (IXGBE_FLAG_DCB_ENABLED):
-			/* We enable 8 traffic classes, DCB only */
-			IXGBE_WRITE_REG(hw, IXGBE_MTQC,
-				      (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ));
-			break;
-
-		default:
-			IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB);
-			break;
-		}
-
-		/* re-eable the arbiter */
-		rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
-		IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
-	}
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		ixgbe_configure_tx_ring(adapter, adapter->tx_ring[i]);
 }
 
 #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
 
 static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter,
-                                   struct ixgbe_ring *rx_ring)
+				   struct ixgbe_ring *rx_ring)
 {
 	u32 srrctl;
 	int index;
@@ -2529,6 +2604,8 @@
 
 	srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
 	srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
+	if (adapter->num_vfs)
+		srrctl |= IXGBE_SRRCTL_DROP_EN;
 
 	srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
 		  IXGBE_SRRCTL_BSIZEHDR_MASK;
@@ -2549,20 +2626,46 @@
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl);
 }
 
-static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
+static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
 {
-	u32 mrqc = 0;
+	struct ixgbe_hw *hw = &adapter->hw;
+	static const u32 seed[10] = { 0xE291D73D, 0x1805EC6C, 0x2A94B30D,
+			  0xA54F2BEC, 0xEA49AF7C, 0xE214AD3D, 0xB855AABE,
+			  0x6A3E67EA, 0x14364D17, 0x3BED200D};
+	u32 mrqc = 0, reta = 0;
+	u32 rxcsum;
+	int i, j;
 	int mask;
 
-	if (!(adapter->hw.mac.type == ixgbe_mac_82599EB))
-		return mrqc;
+	/* Fill out hash function seeds */
+	for (i = 0; i < 10; i++)
+		IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]);
 
-	mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED
+	/* Fill out redirection table */
+	for (i = 0, j = 0; i < 128; i++, j++) {
+		if (j == adapter->ring_feature[RING_F_RSS].indices)
+			j = 0;
+		/* reta = 4-byte sliding window of
+		 * 0x00..(indices-1)(indices-1)00..etc. */
+		reta = (reta << 8) | (j * 0x11);
+		if ((i & 3) == 3)
+			IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
+	}
+
+	/* Disable indicating checksum in descriptor, enables RSS hash */
+	rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
+	rxcsum |= IXGBE_RXCSUM_PCSD;
+	IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
+
+	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+		mask = adapter->flags & IXGBE_FLAG_RSS_ENABLED;
+	else
+		mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED
 #ifdef CONFIG_IXGBE_DCB
-				 | IXGBE_FLAG_DCB_ENABLED
+					 | IXGBE_FLAG_DCB_ENABLED
 #endif
-				 | IXGBE_FLAG_SRIOV_ENABLED
-				);
+					 | IXGBE_FLAG_SRIOV_ENABLED
+					);
 
 	switch (mask) {
 	case (IXGBE_FLAG_RSS_ENABLED):
@@ -2580,7 +2683,13 @@
 		break;
 	}
 
-	return mrqc;
+	/* Perform hash on these packet types */
+	mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4
+	      | IXGBE_MRQC_RSS_FIELD_IPV4_TCP
+	      | IXGBE_MRQC_RSS_FIELD_IPV6
+	      | IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
+
+	IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
 }
 
 /**
@@ -2588,25 +2697,26 @@
  * @adapter:    address of board private structure
  * @index:      index of ring to set
  **/
-static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index)
+static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
+				   struct ixgbe_ring *ring)
 {
-	struct ixgbe_ring *rx_ring;
 	struct ixgbe_hw *hw = &adapter->hw;
-	int j;
 	u32 rscctrl;
 	int rx_buf_len;
+	u16 reg_idx = ring->reg_idx;
 
-	rx_ring = adapter->rx_ring[index];
-	j = rx_ring->reg_idx;
-	rx_buf_len = rx_ring->rx_buf_len;
-	rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
+	if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))
+		return;
+
+	rx_buf_len = ring->rx_buf_len;
+	rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(reg_idx));
 	rscctrl |= IXGBE_RSCCTL_RSCEN;
 	/*
 	 * we must limit the number of descriptors so that the
 	 * total size of max desc * buf_len is not greater
 	 * than 65535
 	 */
-	if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
+	if (ring->flags & IXGBE_RING_RX_PS_ENABLED) {
 #if (MAX_SKB_FRAGS > 16)
 		rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
 #elif (MAX_SKB_FRAGS > 8)
@@ -2624,31 +2734,181 @@
 		else
 			rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
 	}
-	IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl);
+	IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl);
 }
 
 /**
- * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
- * @adapter: board private structure
+ *  ixgbe_set_uta - Set unicast filter table address
+ *  @adapter: board private structure
  *
- * Configure the Rx unit of the MAC after a reset.
+ *  The unicast table address is a register array of 32-bit registers.
+ *  The table is meant to be used in a way similar to how the MTA is used
+ *  however due to certain limitations in the hardware it is necessary to
+ *  set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous
+ *  enable bit to allow vlan tag stripping when promiscuous mode is enabled
  **/
-static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
+static void ixgbe_set_uta(struct ixgbe_adapter *adapter)
 {
-	u64 rdba;
 	struct ixgbe_hw *hw = &adapter->hw;
-	struct ixgbe_ring *rx_ring;
+	int i;
+
+	/* The UTA table only exists on 82599 hardware and newer */
+	if (hw->mac.type < ixgbe_mac_82599EB)
+		return;
+
+	/* we only need to do this if VMDq is enabled */
+	if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+		return;
+
+	for (i = 0; i < 128; i++)
+		IXGBE_WRITE_REG(hw, IXGBE_UTA(i), ~0);
+}
+
+#define IXGBE_MAX_RX_DESC_POLL 10
+static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
+				       struct ixgbe_ring *ring)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	int reg_idx = ring->reg_idx;
+	int wait_loop = IXGBE_MAX_RX_DESC_POLL;
+	u32 rxdctl;
+
+	/* RXDCTL.EN will return 0 on 82598 if link is down, so skip it */
+	if (hw->mac.type == ixgbe_mac_82598EB &&
+	    !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
+		return;
+
+	do {
+		msleep(1);
+		rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
+	} while (--wait_loop && !(rxdctl & IXGBE_RXDCTL_ENABLE));
+
+	if (!wait_loop) {
+		e_err(drv, "RXDCTL.ENABLE on Rx queue %d not set within "
+		      "the polling period\n", reg_idx);
+	}
+}
+
+void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
+			     struct ixgbe_ring *ring)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u64 rdba = ring->dma;
+	u32 rxdctl;
+	u16 reg_idx = ring->reg_idx;
+
+	/* disable queue to avoid issues while updating state */
+	rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
+	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx),
+			rxdctl & ~IXGBE_RXDCTL_ENABLE);
+	IXGBE_WRITE_FLUSH(hw);
+
+	IXGBE_WRITE_REG(hw, IXGBE_RDBAL(reg_idx), (rdba & DMA_BIT_MASK(32)));
+	IXGBE_WRITE_REG(hw, IXGBE_RDBAH(reg_idx), (rdba >> 32));
+	IXGBE_WRITE_REG(hw, IXGBE_RDLEN(reg_idx),
+			ring->count * sizeof(union ixgbe_adv_rx_desc));
+	IXGBE_WRITE_REG(hw, IXGBE_RDH(reg_idx), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_RDT(reg_idx), 0);
+	ring->head = IXGBE_RDH(reg_idx);
+	ring->tail = IXGBE_RDT(reg_idx);
+
+	ixgbe_configure_srrctl(adapter, ring);
+	ixgbe_configure_rscctl(adapter, ring);
+
+	if (hw->mac.type == ixgbe_mac_82598EB) {
+		/*
+		 * enable cache line friendly hardware writes:
+		 * PTHRESH=32 descriptors (half the internal cache),
+		 * this also removes ugly rx_no_buffer_count increment
+		 * HTHRESH=4 descriptors (to minimize latency on fetch)
+		 * WTHRESH=8 burst writeback up to two cache lines
+		 */
+		rxdctl &= ~0x3FFFFF;
+		rxdctl |=  0x080420;
+	}
+
+	/* enable receive descriptor ring */
+	rxdctl |= IXGBE_RXDCTL_ENABLE;
+	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
+
+	ixgbe_rx_desc_queue_enable(adapter, ring);
+	ixgbe_alloc_rx_buffers(adapter, ring, IXGBE_DESC_UNUSED(ring));
+}
+
+static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	int p;
+
+	/* PSRTYPE must be initialized in non 82598 adapters */
+	u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
+		      IXGBE_PSRTYPE_UDPHDR |
+		      IXGBE_PSRTYPE_IPV4HDR |
+		      IXGBE_PSRTYPE_L2HDR |
+		      IXGBE_PSRTYPE_IPV6HDR;
+
+	if (hw->mac.type == ixgbe_mac_82598EB)
+		return;
+
+	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED)
+		psrtype |= (adapter->num_rx_queues_per_pool << 29);
+
+	for (p = 0; p < adapter->num_rx_pools; p++)
+		IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(adapter->num_vfs + p),
+				psrtype);
+}
+
+static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 gcr_ext;
+	u32 vt_reg_bits;
+	u32 reg_offset, vf_shift;
+	u32 vmdctl;
+
+	if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+		return;
+
+	vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+	vt_reg_bits = IXGBE_VMD_CTL_VMDQ_EN | IXGBE_VT_CTL_REPLEN;
+	vt_reg_bits |= (adapter->num_vfs << IXGBE_VT_CTL_POOL_SHIFT);
+	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl | vt_reg_bits);
+
+	vf_shift = adapter->num_vfs % 32;
+	reg_offset = (adapter->num_vfs > 32) ? 1 : 0;
+
+	/* Enable only the PF's pool for Tx/Rx */
+	IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift));
+	IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset ^ 1), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (1 << vf_shift));
+	IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset ^ 1), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+
+	/* Map PF MAC address in RAR Entry 0 to first pool following VFs */
+	hw->mac.ops.set_vmdq(hw, 0, adapter->num_vfs);
+
+	/*
+	 * Set up VF register offsets for selected VT Mode,
+	 * i.e. 32 or 64 VFs for SR-IOV
+	 */
+	gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
+	gcr_ext |= IXGBE_GCR_EXT_MSIX_EN;
+	gcr_ext |= IXGBE_GCR_EXT_VT_MODE_64;
+	IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
+
+	/* enable Tx loopback for VF/PF communication */
+	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+}
+
+static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
-	int i, j;
-	u32 rdlen, rxctrl, rxcsum;
-	static const u32 seed[10] = { 0xE291D73D, 0x1805EC6C, 0x2A94B30D,
-	                  0xA54F2BEC, 0xEA49AF7C, 0xE214AD3D, 0xB855AABE,
-	                  0x6A3E67EA, 0x14364D17, 0x3BED200D};
-	u32 fctrl, hlreg0;
-	u32 reta = 0, mrqc = 0;
-	u32 rdrxctl;
 	int rx_buf_len;
+	struct ixgbe_ring *rx_ring;
+	int i;
+	u32 mhadd, hlreg0;
 
 	/* Decide whether to use packet split mode or not */
 	/* Do not use packet split if we're in SR-IOV Mode */
@@ -2658,62 +2918,40 @@
 	/* Set the RX buffer length according to the mode */
 	if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
 		rx_buf_len = IXGBE_RX_HDR_SIZE;
-		if (hw->mac.type == ixgbe_mac_82599EB) {
-			/* PSRTYPE must be initialized in 82599 */
-			u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
-			              IXGBE_PSRTYPE_UDPHDR |
-			              IXGBE_PSRTYPE_IPV4HDR |
-			              IXGBE_PSRTYPE_IPV6HDR |
-			              IXGBE_PSRTYPE_L2HDR;
-			IXGBE_WRITE_REG(hw,
-					IXGBE_PSRTYPE(adapter->num_vfs),
-					psrtype);
-		}
 	} else {
 		if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) &&
 		    (netdev->mtu <= ETH_DATA_LEN))
 			rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;
 		else
-			rx_buf_len = ALIGN(max_frame, 1024);
+			rx_buf_len = ALIGN(max_frame + VLAN_HLEN, 1024);
 	}
 
-	fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
-	fctrl |= IXGBE_FCTRL_BAM;
-	fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */
-	fctrl |= IXGBE_FCTRL_PMCF;
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
+#ifdef IXGBE_FCOE
+	/* adjust max frame to be able to do baby jumbo for FCoE */
+	if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
+	    (max_frame < IXGBE_FCOE_JUMBO_FRAME_SIZE))
+		max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE;
+
+#endif /* IXGBE_FCOE */
+	mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
+	if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
+		mhadd &= ~IXGBE_MHADD_MFS_MASK;
+		mhadd |= max_frame << IXGBE_MHADD_MFS_SHIFT;
+
+		IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
+	}
 
 	hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
-	if (adapter->netdev->mtu <= ETH_DATA_LEN)
-		hlreg0 &= ~IXGBE_HLREG0_JUMBOEN;
-	else
-		hlreg0 |= IXGBE_HLREG0_JUMBOEN;
-#ifdef IXGBE_FCOE
-	if (netdev->features & NETIF_F_FCOE_MTU)
-		hlreg0 |= IXGBE_HLREG0_JUMBOEN;
-#endif
+	/* set jumbo enable since MHADD.MFS is keeping size locked at max_frame */
+	hlreg0 |= IXGBE_HLREG0_JUMBOEN;
 	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
 
-	rdlen = adapter->rx_ring[0]->count * sizeof(union ixgbe_adv_rx_desc);
-	/* disable receives while setting up the descriptors */
-	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
-	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
-
 	/*
 	 * Setup the HW Rx Head and Tail Descriptor Pointers and
 	 * the Base and Length of the Rx Descriptor Ring
 	 */
 	for (i = 0; i < adapter->num_rx_queues; i++) {
 		rx_ring = adapter->rx_ring[i];
-		rdba = rx_ring->dma;
-		j = rx_ring->reg_idx;
-		IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), (rdba & DMA_BIT_MASK(32)));
-		IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
-		IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), rdlen);
-		IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
-		rx_ring->head = IXGBE_RDH(j);
-		rx_ring->tail = IXGBE_RDT(j);
 		rx_ring->rx_buf_len = rx_buf_len;
 
 		if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)
@@ -2729,15 +2967,21 @@
 				rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED;
 				if (rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE)
 					rx_ring->rx_buf_len =
-					        IXGBE_FCOE_JUMBO_FRAME_SIZE;
+						IXGBE_FCOE_JUMBO_FRAME_SIZE;
 			}
 		}
-
 #endif /* IXGBE_FCOE */
-		ixgbe_configure_srrctl(adapter, rx_ring);
 	}
 
-	if (hw->mac.type == ixgbe_mac_82598EB) {
+}
+
+static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
+
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
 		/*
 		 * For VMDq support of different descriptor types or
 		 * buffer sizes through the use of multiple SRRCTL
@@ -2748,110 +2992,66 @@
 		 * effects of setting this bit are only that SRRCTL must be
 		 * fully programmed [0..15]
 		 */
-		rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
 		rdrxctl |= IXGBE_RDRXCTL_MVMEN;
-		IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
-	}
-
-	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
-		u32 vt_reg_bits;
-		u32 reg_offset, vf_shift;
-		u32 vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
-		vt_reg_bits = IXGBE_VMD_CTL_VMDQ_EN
-			| IXGBE_VT_CTL_REPLEN;
-		vt_reg_bits |= (adapter->num_vfs <<
-				IXGBE_VT_CTL_POOL_SHIFT);
-		IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl | vt_reg_bits);
-		IXGBE_WRITE_REG(hw, IXGBE_MRQC, 0);
-
-		vf_shift = adapter->num_vfs % 32;
-		reg_offset = adapter->num_vfs / 32;
-		IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_VFTE(1), 0);
-		/* Enable only the PF's pool for Tx/Rx */
-		IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift));
-		IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (1 << vf_shift));
-		IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
-		ixgbe_set_vmolr(hw, adapter->num_vfs, true);
-	}
-
-	/* Program MRQC for the distribution of queues */
-	mrqc = ixgbe_setup_mrqc(adapter);
-
-	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
-		/* Fill out redirection table */
-		for (i = 0, j = 0; i < 128; i++, j++) {
-			if (j == adapter->ring_feature[RING_F_RSS].indices)
-				j = 0;
-			/* reta = 4-byte sliding window of
-			 * 0x00..(indices-1)(indices-1)00..etc. */
-			reta = (reta << 8) | (j * 0x11);
-			if ((i & 3) == 3)
-				IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
-		}
-
-		/* Fill out hash function seeds */
-		for (i = 0; i < 10; i++)
-			IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]);
-
-		if (hw->mac.type == ixgbe_mac_82598EB)
-			mrqc |= IXGBE_MRQC_RSSEN;
-		    /* Perform hash on these packet types */
-		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4
-		      | IXGBE_MRQC_RSS_FIELD_IPV4_TCP
-		      | IXGBE_MRQC_RSS_FIELD_IPV6
-		      | IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
-	}
-	IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
-
-	if (adapter->num_vfs) {
-		u32 reg;
-
-		/* Map PF MAC address in RAR Entry 0 to first pool
-		 * following VFs */
-		hw->mac.ops.set_vmdq(hw, 0, adapter->num_vfs);
-
-		/* Set up VF register offsets for selected VT Mode, i.e.
-		 * 64 VFs for SR-IOV */
-		reg = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
-		reg |= IXGBE_GCR_EXT_SRIOV;
-		IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, reg);
-	}
-
-	rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
-
-	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED ||
-	    adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED) {
-		/* Disable indicating checksum in descriptor, enables
-		 * RSS hash */
-		rxcsum |= IXGBE_RXCSUM_PCSD;
-	}
-	if (!(rxcsum & IXGBE_RXCSUM_PCSD)) {
-		/* Enable IPv4 payload checksum for UDP fragments
-		 * if PCSD is not set */
-		rxcsum |= IXGBE_RXCSUM_IPPCSE;
-	}
-
-	IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
-
-	if (hw->mac.type == ixgbe_mac_82599EB) {
-		rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
-		rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP;
-		rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
-		IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
-	}
-
-	if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
-		/* Enable 82599 HW-RSC */
-		for (i = 0; i < adapter->num_rx_queues; i++)
-			ixgbe_configure_rscctl(adapter, i);
-
+		break;
+	case ixgbe_mac_82599EB:
 		/* Disable RSC for ACK packets */
 		IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
 		   (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
+		rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
+		/* hardware requires some bits to be set by default */
+		rdrxctl |= (IXGBE_RDRXCTL_RSCACKC | IXGBE_RDRXCTL_FCOE_WRFIX);
+		rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP;
+		break;
+	default:
+		/* We should do nothing since we don't know this hardware */
+		return;
 	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
+}
+
+/**
+ * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Rx unit of the MAC after a reset.
+ **/
+static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	int i;
+	u32 rxctrl;
+
+	/* disable receives while setting up the descriptors */
+	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
+
+	ixgbe_setup_psrtype(adapter);
+	ixgbe_setup_rdrxctl(adapter);
+
+	/* Program registers for the distribution of queues */
+	ixgbe_setup_mrqc(adapter);
+
+	ixgbe_set_uta(adapter);
+
+	/* set_rx_buffer_len must be called before ring initialization */
+	ixgbe_set_rx_buffer_len(adapter);
+
+	/*
+	 * Setup the HW Rx Head and Tail Descriptor Pointers and
+	 * the Base and Length of the Rx Descriptor Ring
+	 */
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		ixgbe_configure_rx_ring(adapter, adapter->rx_ring[i]);
+
+	/* disable drop enable for 82598 parts */
+	if (hw->mac.type == ixgbe_mac_82598EB)
+		rxctrl |= IXGBE_RXCTRL_DMBYPS;
+
+	/* enable all receives */
+	rxctrl |= IXGBE_RXCTRL_RXEN;
+	hw->mac.ops.enable_rx_dma(hw, rxctrl);
 }
 
 static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
@@ -2862,6 +3062,7 @@
 
 	/* add VID to filter table */
 	hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, true);
+	set_bit(vid, adapter->active_vlans);
 }
 
 static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -2870,16 +3071,9 @@
 	struct ixgbe_hw *hw = &adapter->hw;
 	int pool_ndx = adapter->num_vfs;
 
-	if (!test_bit(__IXGBE_DOWN, &adapter->state))
-		ixgbe_irq_disable(adapter);
-
-	vlan_group_set_device(adapter->vlgrp, vid, NULL);
-
-	if (!test_bit(__IXGBE_DOWN, &adapter->state))
-		ixgbe_irq_enable(adapter);
-
 	/* remove VID from filter table */
 	hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, false);
+	clear_bit(vid, adapter->active_vlans);
 }
 
 /**
@@ -2889,27 +3083,45 @@
 static void ixgbe_vlan_filter_disable(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32 vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+	u32 vlnctrl;
+
+	vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+	vlnctrl &= ~(IXGBE_VLNCTRL_VFE | IXGBE_VLNCTRL_CFIEN);
+	IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+}
+
+/**
+ * ixgbe_vlan_filter_enable - helper to enable hw vlan filtering
+ * @adapter: driver data
+ */
+static void ixgbe_vlan_filter_enable(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 vlnctrl;
+
+	vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+	vlnctrl |= IXGBE_VLNCTRL_VFE;
+	vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+	IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+}
+
+/**
+ * ixgbe_vlan_strip_disable - helper to disable hw vlan stripping
+ * @adapter: driver data
+ */
+static void ixgbe_vlan_strip_disable(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 vlnctrl;
 	int i, j;
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
-		vlnctrl &= ~IXGBE_VLNCTRL_VFE;
-#ifdef CONFIG_IXGBE_DCB
-		if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
-			vlnctrl &= ~IXGBE_VLNCTRL_VME;
-#endif
-		vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+		vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+		vlnctrl &= ~IXGBE_VLNCTRL_VME;
 		IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
 		break;
 	case ixgbe_mac_82599EB:
-		vlnctrl &= ~IXGBE_VLNCTRL_VFE;
-		vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
-		IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
-#ifdef CONFIG_IXGBE_DCB
-		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
-			break;
-#endif
 		for (i = 0; i < adapter->num_rx_queues; i++) {
 			j = adapter->rx_ring[i]->reg_idx;
 			vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
@@ -2923,25 +3135,22 @@
 }
 
 /**
- * ixgbe_vlan_filter_enable - helper to enable hw vlan filtering
+ * ixgbe_vlan_strip_enable - helper to enable hw vlan stripping
  * @adapter: driver data
  */
-static void ixgbe_vlan_filter_enable(struct ixgbe_adapter *adapter)
+static void ixgbe_vlan_strip_enable(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32 vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+	u32 vlnctrl;
 	int i, j;
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
-		vlnctrl |= IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE;
-		vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+		vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+		vlnctrl |= IXGBE_VLNCTRL_VME;
 		IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
 		break;
 	case ixgbe_mac_82599EB:
-		vlnctrl |= IXGBE_VLNCTRL_VFE;
-		vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
-		IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
 		for (i = 0; i < adapter->num_rx_queues; i++) {
 			j = adapter->rx_ring[i]->reg_idx;
 			vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
@@ -2954,40 +3163,14 @@
 	}
 }
 
-static void ixgbe_vlan_rx_register(struct net_device *netdev,
-                                   struct vlan_group *grp)
-{
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-
-	if (!test_bit(__IXGBE_DOWN, &adapter->state))
-		ixgbe_irq_disable(adapter);
-	adapter->vlgrp = grp;
-
-	/*
-	 * For a DCB driver, always enable VLAN tag stripping so we can
-	 * still receive traffic from a DCB-enabled host even if we're
-	 * not in DCB mode.
-	 */
-	ixgbe_vlan_filter_enable(adapter);
-
-	ixgbe_vlan_rx_add_vid(netdev, 0);
-
-	if (!test_bit(__IXGBE_DOWN, &adapter->state))
-		ixgbe_irq_enable(adapter);
-}
-
 static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter)
 {
-	ixgbe_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+	u16 vid;
 
-	if (adapter->vlgrp) {
-		u16 vid;
-		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
-			if (!vlan_group_get_device(adapter->vlgrp, vid))
-				continue;
-			ixgbe_vlan_rx_add_vid(adapter->netdev, vid);
-		}
-	}
+	ixgbe_vlan_rx_add_vid(adapter->netdev, 0);
+
+	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+		ixgbe_vlan_rx_add_vid(adapter->netdev, vid);
 }
 
 /**
@@ -3052,6 +3235,11 @@
 
 	fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
 
+	/* set all bits that we expect to always be set */
+	fctrl |= IXGBE_FCTRL_BAM;
+	fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */
+	fctrl |= IXGBE_FCTRL_PMCF;
+
 	/* clear the bits we are changing the status of */
 	fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
 
@@ -3097,6 +3285,11 @@
 	}
 
 	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
+
+	if (netdev->features & NETIF_F_HW_VLAN_RX)
+		ixgbe_vlan_strip_enable(adapter);
+	else
+		ixgbe_vlan_strip_disable(adapter);
 }
 
 static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
@@ -3157,7 +3350,15 @@
 	u32 txdctl;
 	int i, j;
 
-	ixgbe_dcb_check_config(&adapter->dcb_cfg);
+	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) {
+		if (hw->mac.type == ixgbe_mac_82598EB)
+			netif_set_gso_max_size(adapter->netdev, 65536);
+		return;
+	}
+
+	if (hw->mac.type == ixgbe_mac_82598EB)
+		netif_set_gso_max_size(adapter->netdev, 32768);
+
 	ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_TX_CONFIG);
 	ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_RX_CONFIG);
 
@@ -3172,7 +3373,7 @@
 		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
 	}
 	/* Enable VLAN tag insert/strip */
-	ixgbe_vlan_filter_enable(adapter);
+	adapter->netdev->features |= NETIF_F_HW_VLAN_RX;
 
 	hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
 }
@@ -3184,23 +3385,13 @@
 	struct ixgbe_hw *hw = &adapter->hw;
 	int i;
 
-	ixgbe_set_rx_mode(netdev);
-
-	ixgbe_restore_vlan(adapter);
 #ifdef CONFIG_IXGBE_DCB
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-		if (hw->mac.type == ixgbe_mac_82598EB)
-			netif_set_gso_max_size(netdev, 32768);
-		else
-			netif_set_gso_max_size(netdev, 65536);
-		ixgbe_configure_dcb(adapter);
-	} else {
-		netif_set_gso_max_size(netdev, 65536);
-	}
-#else
-	netif_set_gso_max_size(netdev, 65536);
+	ixgbe_configure_dcb(adapter);
 #endif
 
+	ixgbe_set_rx_mode(netdev);
+	ixgbe_restore_vlan(adapter);
+
 #ifdef IXGBE_FCOE
 	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
 		ixgbe_configure_fcoe(adapter);
@@ -3209,17 +3400,15 @@
 	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
 		for (i = 0; i < adapter->num_tx_queues; i++)
 			adapter->tx_ring[i]->atr_sample_rate =
-			                               adapter->atr_sample_rate;
+						       adapter->atr_sample_rate;
 		ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc);
 	} else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) {
 		ixgbe_init_fdir_perfect_82599(hw, adapter->fdir_pballoc);
 	}
+	ixgbe_configure_virtualization(adapter);
 
 	ixgbe_configure_tx(adapter);
 	ixgbe_configure_rx(adapter);
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		ixgbe_alloc_rx_buffers(adapter, adapter->rx_ring[i],
-		                       (adapter->rx_ring[i]->count - 1));
 }
 
 static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw)
@@ -3290,7 +3479,8 @@
 		goto link_cfg_out;
 
 	if (hw->mac.ops.get_link_capabilities)
-		ret = hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiation);
+		ret = hw->mac.ops.get_link_capabilities(hw, &autoneg,
+							&negotiation);
 	if (ret)
 		goto link_cfg_out;
 
@@ -3300,62 +3490,15 @@
 	return ret;
 }
 
-#define IXGBE_MAX_RX_DESC_POLL 10
-static inline void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
-	                                      int rxr)
+static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
 {
-	int j = adapter->rx_ring[rxr]->reg_idx;
-	int k;
-
-	for (k = 0; k < IXGBE_MAX_RX_DESC_POLL; k++) {
-		if (IXGBE_READ_REG(&adapter->hw,
-		                   IXGBE_RXDCTL(j)) & IXGBE_RXDCTL_ENABLE)
-			break;
-		else
-			msleep(1);
-	}
-	if (k >= IXGBE_MAX_RX_DESC_POLL) {
-		e_err(drv, "RXDCTL.ENABLE on Rx queue %d not set within "
-		      "the polling period\n", rxr);
-	}
-	ixgbe_release_rx_desc(&adapter->hw, adapter->rx_ring[rxr],
-	                      (adapter->rx_ring[rxr]->count - 1));
-}
-
-static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
 	struct ixgbe_hw *hw = &adapter->hw;
-	int i, j = 0;
-	int num_rx_rings = adapter->num_rx_queues;
-	int err;
-	int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
-	u32 txdctl, rxdctl, mhadd;
-	u32 dmatxctl;
-	u32 gpie;
-	u32 ctrl_ext;
-
-	ixgbe_get_hw_control(adapter);
-
-	if ((adapter->flags & IXGBE_FLAG_MSIX_ENABLED) ||
-	    (adapter->flags & IXGBE_FLAG_MSI_ENABLED)) {
-		if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
-			gpie = (IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_EIAME |
-			        IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD);
-		} else {
-			/* MSI only */
-			gpie = 0;
-		}
-		if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
-			gpie &= ~IXGBE_GPIE_VTMODE_MASK;
-			gpie |= IXGBE_GPIE_VTMODE_64;
-		}
-		/* XXX: to interrupt immediately for EICS writes, enable this */
-		/* gpie |= IXGBE_GPIE_EIMEN; */
-		IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
-	}
+	u32 gpie = 0;
 
 	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+		gpie = IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_PBA_SUPPORT |
+		       IXGBE_GPIE_OCD;
+		gpie |= IXGBE_GPIE_EIAME;
 		/*
 		 * use EIAM to auto-mask when MSI-X interrupt is asserted
 		 * this saves a register write for every interrupt
@@ -3376,98 +3519,33 @@
 		IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
 	}
 
-	/* Enable Thermal over heat sensor interrupt */
-	if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) {
-		gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
-		gpie |= IXGBE_SDP0_GPIEN;
-		IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+	/* XXX: to interrupt immediately for EICS writes, enable this */
+	/* gpie |= IXGBE_GPIE_EIMEN; */
+
+	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+		gpie &= ~IXGBE_GPIE_VTMODE_MASK;
+		gpie |= IXGBE_GPIE_VTMODE_64;
 	}
 
-	/* Enable fan failure interrupt if media type is copper */
-	if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) {
-		gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
+	/* Enable fan failure interrupt */
+	if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
 		gpie |= IXGBE_SDP1_GPIEN;
-		IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
-	}
 
-	if (hw->mac.type == ixgbe_mac_82599EB) {
-		gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
+	if (hw->mac.type == ixgbe_mac_82599EB)
 		gpie |= IXGBE_SDP1_GPIEN;
 		gpie |= IXGBE_SDP2_GPIEN;
-		IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
-	}
 
-#ifdef IXGBE_FCOE
-	/* adjust max frame to be able to do baby jumbo for FCoE */
-	if ((netdev->features & NETIF_F_FCOE_MTU) &&
-	    (max_frame < IXGBE_FCOE_JUMBO_FRAME_SIZE))
-		max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE;
+	IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+}
 
-#endif /* IXGBE_FCOE */
-	mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
-	if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
-		mhadd &= ~IXGBE_MHADD_MFS_MASK;
-		mhadd |= max_frame << IXGBE_MHADD_MFS_SHIFT;
+static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	int err;
+	u32 ctrl_ext;
 
-		IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
-	}
-
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		j = adapter->tx_ring[i]->reg_idx;
-		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
-		if (adapter->rx_itr_setting == 0) {
-			/* cannot set wthresh when itr==0 */
-			txdctl &= ~0x007F0000;
-		} else {
-			/* enable WTHRESH=8 descriptors, to encourage burst writeback */
-			txdctl |= (8 << 16);
-		}
-		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
-	}
-
-	if (hw->mac.type == ixgbe_mac_82599EB) {
-		/* DMATXCTL.EN must be set after all Tx queue config is done */
-		dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
-		dmatxctl |= IXGBE_DMATXCTL_TE;
-		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
-	}
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		j = adapter->tx_ring[i]->reg_idx;
-		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
-		txdctl |= IXGBE_TXDCTL_ENABLE;
-		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
-		if (hw->mac.type == ixgbe_mac_82599EB) {
-			int wait_loop = 10;
-			/* poll for Tx Enable ready */
-			do {
-				msleep(1);
-				txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
-			} while (--wait_loop &&
-			         !(txdctl & IXGBE_TXDCTL_ENABLE));
-			if (!wait_loop)
-				e_err(drv, "Could not enable Tx Queue %d\n", j);
-		}
-	}
-
-	for (i = 0; i < num_rx_rings; i++) {
-		j = adapter->rx_ring[i]->reg_idx;
-		rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
-		/* enable PTHRESH=32 descriptors (half the internal cache)
-		 * and HTHRESH=0 descriptors (to minimize latency on fetch),
-		 * this also removes a pesky rx_no_buffer_count increment */
-		rxdctl |= 0x0020;
-		rxdctl |= IXGBE_RXDCTL_ENABLE;
-		IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(j), rxdctl);
-		if (hw->mac.type == ixgbe_mac_82599EB)
-			ixgbe_rx_desc_queue_enable(adapter, i);
-	}
-	/* enable all receives */
-	rxdctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
-	if (hw->mac.type == ixgbe_mac_82598EB)
-		rxdctl |= (IXGBE_RXCTRL_DMBYPS | IXGBE_RXCTRL_RXEN);
-	else
-		rxdctl |= IXGBE_RXCTRL_RXEN;
-	hw->mac.ops.enable_rx_dma(hw, rxdctl);
+	ixgbe_get_hw_control(adapter);
+	ixgbe_setup_gpie(adapter);
 
 	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
 		ixgbe_configure_msix(adapter);
@@ -3483,8 +3561,7 @@
 
 	/* clear any pending interrupts, may auto mask */
 	IXGBE_READ_REG(hw, IXGBE_EICR);
-
-	ixgbe_irq_enable(adapter);
+	ixgbe_irq_enable(adapter, true, true);
 
 	/*
 	 * If this adapter has a fan, check to see if we had a failure
@@ -3525,12 +3602,8 @@
 			e_err(probe, "link_config FAILED %d\n", err);
 	}
 
-	for (i = 0; i < adapter->num_tx_queues; i++)
-		set_bit(__IXGBE_FDIR_INIT_DONE,
-		        &(adapter->tx_ring[i]->reinit_state));
-
 	/* enable transmits */
-	netif_tx_start_all_queues(netdev);
+	netif_tx_start_all_queues(adapter->netdev);
 
 	/* bring the link up in the watchdog, this could race with our first
 	 * link up interrupt but shouldn't be a problem */
@@ -3609,21 +3682,24 @@
  * @rx_ring: ring to free buffers from
  **/
 static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
-                                struct ixgbe_ring *rx_ring)
+				struct ixgbe_ring *rx_ring)
 {
 	struct pci_dev *pdev = adapter->pdev;
 	unsigned long size;
 	unsigned int i;
 
-	/* Free all the Rx ring sk_buffs */
+	/* ring already cleared, nothing to do */
+	if (!rx_ring->rx_buffer_info)
+		return;
 
+	/* Free all the Rx ring sk_buffs */
 	for (i = 0; i < rx_ring->count; i++) {
 		struct ixgbe_rx_buffer *rx_buffer_info;
 
 		rx_buffer_info = &rx_ring->rx_buffer_info[i];
 		if (rx_buffer_info->dma) {
 			dma_unmap_single(&pdev->dev, rx_buffer_info->dma,
-			                 rx_ring->rx_buf_len,
+					 rx_ring->rx_buf_len,
 					 DMA_FROM_DEVICE);
 			rx_buffer_info->dma = 0;
 		}
@@ -3635,7 +3711,7 @@
 				if (IXGBE_RSC_CB(this)->delay_unmap) {
 					dma_unmap_single(&pdev->dev,
 							 IXGBE_RSC_CB(this)->dma,
-					                 rx_ring->rx_buf_len,
+							 rx_ring->rx_buf_len,
 							 DMA_FROM_DEVICE);
 					IXGBE_RSC_CB(this)->dma = 0;
 					IXGBE_RSC_CB(skb)->delay_unmap = false;
@@ -3677,14 +3753,17 @@
  * @tx_ring: ring to be cleaned
  **/
 static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter,
-                                struct ixgbe_ring *tx_ring)
+				struct ixgbe_ring *tx_ring)
 {
 	struct ixgbe_tx_buffer *tx_buffer_info;
 	unsigned long size;
 	unsigned int i;
 
-	/* Free all the Tx ring sk_buffs */
+	/* ring already cleared, nothing to do */
+	if (!tx_ring->tx_buffer_info)
+		return;
 
+	/* Free all the Tx ring sk_buffs */
 	for (i = 0; i < tx_ring->count; i++) {
 		tx_buffer_info = &tx_ring->tx_buffer_info[i];
 		ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info);
@@ -3736,6 +3815,7 @@
 	u32 rxctrl;
 	u32 txdctl;
 	int i, j;
+	int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
 
 	/* signal that we are down to the interrupt handler */
 	set_bit(__IXGBE_DOWN, &adapter->state);
@@ -3774,6 +3854,15 @@
 
 	ixgbe_napi_disable_all(adapter);
 
+	/* Cleanup the affinity_hint CPU mask memory and callback */
+	for (i = 0; i < num_q_vectors; i++) {
+		struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
+		/* clear the affinity_mask in the IRQ descriptor */
+		irq_set_affinity_hint(adapter->msix_entries[i]. vector, NULL);
+		/* release the CPU mask memory */
+		free_cpumask_var(q_vector->affinity_mask);
+	}
+
 	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
 	    adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
 		cancel_work_sync(&adapter->fdir_reinit_task);
@@ -3786,13 +3875,13 @@
 		j = adapter->tx_ring[i]->reg_idx;
 		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
 		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j),
-		                (txdctl & ~IXGBE_TXDCTL_ENABLE));
+				(txdctl & ~IXGBE_TXDCTL_ENABLE));
 	}
 	/* Disable the Tx DMA engine on 82599 */
 	if (hw->mac.type == ixgbe_mac_82599EB)
 		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
-		                (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
-		                 ~IXGBE_DMATXCTL_TE));
+				(IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
+				 ~IXGBE_DMATXCTL_TE));
 
 	/* power down the optics */
 	if (hw->phy.multispeed_fiber)
@@ -3822,7 +3911,7 @@
 static int ixgbe_poll(struct napi_struct *napi, int budget)
 {
 	struct ixgbe_q_vector *q_vector =
-	                        container_of(napi, struct ixgbe_q_vector, napi);
+				container_of(napi, struct ixgbe_q_vector, napi);
 	struct ixgbe_adapter *adapter = q_vector->adapter;
 	int tx_clean_complete, work_done = 0;
 
@@ -3932,7 +4021,7 @@
  * Rx load across CPUs using RSS.
  *
  **/
-static bool inline ixgbe_set_fdir_queues(struct ixgbe_adapter *adapter)
+static inline bool ixgbe_set_fdir_queues(struct ixgbe_adapter *adapter)
 {
 	bool ret = false;
 	struct ixgbe_ring_feature *f_fdir = &adapter->ring_feature[RING_F_FDIR];
@@ -4024,7 +4113,7 @@
  * fallthrough conditions.
  *
  **/
-static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
+static int ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
 {
 	/* Start with base case */
 	adapter->num_rx_queues = 1;
@@ -4033,7 +4122,7 @@
 	adapter->num_rx_queues_per_pool = 1;
 
 	if (ixgbe_set_sriov_queues(adapter))
-		return;
+		goto done;
 
 #ifdef IXGBE_FCOE
 	if (ixgbe_set_fcoe_queues(adapter))
@@ -4056,12 +4145,14 @@
 	adapter->num_tx_queues = 1;
 
 done:
-	/* Notify the stack of the (possibly) reduced Tx Queue count. */
+	/* Notify the stack of the (possibly) reduced queue counts. */
 	netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
+	return netif_set_real_num_rx_queues(adapter->netdev,
+					    adapter->num_rx_queues);
 }
 
 static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
-                                       int vectors)
+				       int vectors)
 {
 	int err, vector_threshold;
 
@@ -4080,7 +4171,7 @@
 	 */
 	while (vectors >= vector_threshold) {
 		err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
-		                      vectors);
+				      vectors);
 		if (!err) /* Success in acquiring all requested vectors. */
 			break;
 		else if (err < 0)
@@ -4107,7 +4198,7 @@
 		 * vectors we were allocated.
 		 */
 		adapter->num_msix_vectors = min(vectors,
-		                   adapter->max_msix_q_vectors + NON_Q_VECTORS);
+				   adapter->max_msix_q_vectors + NON_Q_VECTORS);
 	}
 }
 
@@ -4178,12 +4269,12 @@
 				}
 				for ( ; i < 5; i++) {
 					adapter->tx_ring[i]->reg_idx =
-					                         ((i + 2) << 4);
+								 ((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);
+								 ((i + 8) << 3);
 					adapter->rx_ring[i]->reg_idx = i << 4;
 				}
 
@@ -4226,7 +4317,7 @@
  * Cache the descriptor ring offsets for Flow Director to the assigned rings.
  *
  **/
-static bool inline ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter)
+static inline bool ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter)
 {
 	int i;
 	bool ret = false;
@@ -4383,7 +4474,7 @@
 			adapter->node = cur_node;
 		}
 		ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL,
-		                    adapter->node);
+				    adapter->node);
 		if (!ring)
 			ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL);
 		if (!ring)
@@ -4407,7 +4498,7 @@
 			adapter->node = cur_node;
 		}
 		ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL,
-		                    adapter->node);
+				    adapter->node);
 		if (!ring)
 			ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL);
 		if (!ring)
@@ -4453,7 +4544,7 @@
 	 * (roughly) the same number of vectors as there are CPU's.
 	 */
 	v_budget = min(adapter->num_rx_queues + adapter->num_tx_queues,
-	               (int)num_online_cpus()) + NON_Q_VECTORS;
+		       (int)num_online_cpus()) + NON_Q_VECTORS;
 
 	/*
 	 * At the same time, hardware can only support a maximum of
@@ -4467,7 +4558,7 @@
 	/* A failure in MSI-X entry allocation isn't fatal, but it does
 	 * mean we disable MSI-X capabilities of the adapter. */
 	adapter->msix_entries = kcalloc(v_budget,
-	                                sizeof(struct msix_entry), GFP_KERNEL);
+					sizeof(struct msix_entry), GFP_KERNEL);
 	if (adapter->msix_entries) {
 		for (vector = 0; vector < v_budget; vector++)
 			adapter->msix_entries[vector].entry = vector;
@@ -4486,7 +4577,9 @@
 	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
 		ixgbe_disable_sriov(adapter);
 
-	ixgbe_set_num_queues(adapter);
+	err = ixgbe_set_num_queues(adapter);
+	if (err)
+		return err;
 
 	err = pci_enable_msi(adapter->pdev);
 	if (!err) {
@@ -4529,10 +4622,10 @@
 
 	for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
 		q_vector = kzalloc_node(sizeof(struct ixgbe_q_vector),
-		                        GFP_KERNEL, adapter->node);
+					GFP_KERNEL, adapter->node);
 		if (!q_vector)
 			q_vector = kzalloc(sizeof(struct ixgbe_q_vector),
-			                   GFP_KERNEL);
+					   GFP_KERNEL);
 		if (!q_vector)
 			goto err_out;
 		q_vector->adapter = adapter;
@@ -4611,7 +4704,9 @@
 	int err;
 
 	/* Number of supported queues */
-	ixgbe_set_num_queues(adapter);
+	err = ixgbe_set_num_queues(adapter);
+	if (err)
+		return err;
 
 	err = ixgbe_set_interrupt_capability(adapter);
 	if (err) {
@@ -4693,8 +4788,8 @@
 static void ixgbe_sfp_task(struct work_struct *work)
 {
 	struct ixgbe_adapter *adapter = container_of(work,
-	                                             struct ixgbe_adapter,
-	                                             sfp_task);
+						     struct ixgbe_adapter,
+						     sfp_task);
 	struct ixgbe_hw *hw = &adapter->hw;
 
 	if ((hw->phy.type == ixgbe_phy_nl) &&
@@ -4719,7 +4814,7 @@
 reschedule:
 	if (test_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state))
 		mod_timer(&adapter->sfp_timer,
-		          round_jiffies(jiffies + (2 * HZ)));
+			  round_jiffies(jiffies + (2 * HZ)));
 }
 
 /**
@@ -4775,7 +4870,7 @@
 			adapter->atr_sample_rate = 20;
 		}
 		adapter->ring_feature[RING_F_FDIR].indices =
-		                                         IXGBE_MAX_FDIR_INDICES;
+							 IXGBE_MAX_FDIR_INDICES;
 		adapter->fdir_pballoc = 0;
 #ifdef IXGBE_FCOE
 		adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
@@ -4806,7 +4901,7 @@
 	adapter->dcb_cfg.round_robin_enable = false;
 	adapter->dcb_set_bitmap = 0x00;
 	ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg,
-	                   adapter->ring_feature[RING_F_DCB].indices);
+			   adapter->ring_feature[RING_F_DCB].indices);
 
 #endif
 
@@ -4861,7 +4956,7 @@
  * Return 0 on success, negative on failure
  **/
 int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter,
-                             struct ixgbe_ring *tx_ring)
+			     struct ixgbe_ring *tx_ring)
 {
 	struct pci_dev *pdev = adapter->pdev;
 	int size;
@@ -4928,7 +5023,7 @@
  * Returns 0 on success, negative on failure
  **/
 int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
-                             struct ixgbe_ring *rx_ring)
+			     struct ixgbe_ring *rx_ring)
 {
 	struct pci_dev *pdev = adapter->pdev;
 	int size;
@@ -5001,7 +5096,7 @@
  * Free all transmit software resources
  **/
 void ixgbe_free_tx_resources(struct ixgbe_adapter *adapter,
-                             struct ixgbe_ring *tx_ring)
+			     struct ixgbe_ring *tx_ring)
 {
 	struct pci_dev *pdev = adapter->pdev;
 
@@ -5039,7 +5134,7 @@
  * Free all receive software resources
  **/
 void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter,
-                             struct ixgbe_ring *rx_ring)
+			     struct ixgbe_ring *rx_ring)
 {
 	struct pci_dev *pdev = adapter->pdev;
 
@@ -5333,6 +5428,7 @@
 	u64 total_mpc = 0;
 	u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
 	u64 non_eop_descs = 0, restart_queue = 0;
+	struct ixgbe_hw_stats *hwstats = &adapter->stats;
 
 	if (test_bit(__IXGBE_DOWN, &adapter->state) ||
 	    test_bit(__IXGBE_RESETTING, &adapter->state))
@@ -5343,7 +5439,7 @@
 		u64 rsc_flush = 0;
 		for (i = 0; i < 16; i++)
 			adapter->hw_rx_no_dma_resources +=
-			                     IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+				IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
 		for (i = 0; i < adapter->num_rx_queues; i++) {
 			rsc_count += adapter->rx_ring[i]->rsc_count;
 			rsc_flush += adapter->rx_ring[i]->rsc_flush;
@@ -5361,119 +5457,118 @@
 		non_eop_descs += adapter->rx_ring[i]->non_eop_descs;
 	adapter->non_eop_descs = non_eop_descs;
 
-	adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
+	hwstats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
 	for (i = 0; i < 8; i++) {
 		/* for packet buffers not used, the register should read 0 */
 		mpc = IXGBE_READ_REG(hw, IXGBE_MPC(i));
 		missed_rx += mpc;
-		adapter->stats.mpc[i] += mpc;
-		total_mpc += adapter->stats.mpc[i];
+		hwstats->mpc[i] += mpc;
+		total_mpc += hwstats->mpc[i];
 		if (hw->mac.type == ixgbe_mac_82598EB)
-			adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
-		adapter->stats.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
-		adapter->stats.qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i));
-		adapter->stats.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
-		adapter->stats.qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i));
+			hwstats->rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
+		hwstats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
+		hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+		hwstats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
+		hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i));
 		if (hw->mac.type == ixgbe_mac_82599EB) {
-			adapter->stats.pxonrxc[i] += IXGBE_READ_REG(hw,
-			                                    IXGBE_PXONRXCNT(i));
-			adapter->stats.pxoffrxc[i] += IXGBE_READ_REG(hw,
-			                                   IXGBE_PXOFFRXCNT(i));
-			adapter->stats.qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+			hwstats->pxonrxc[i] +=
+				IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
+			hwstats->pxoffrxc[i] +=
+				IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
+			hwstats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
 		} else {
-			adapter->stats.pxonrxc[i] += IXGBE_READ_REG(hw,
-			                                      IXGBE_PXONRXC(i));
-			adapter->stats.pxoffrxc[i] += IXGBE_READ_REG(hw,
-			                                     IXGBE_PXOFFRXC(i));
+			hwstats->pxonrxc[i] +=
+				IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
+			hwstats->pxoffrxc[i] +=
+				IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
 		}
-		adapter->stats.pxontxc[i] += IXGBE_READ_REG(hw,
-		                                            IXGBE_PXONTXC(i));
-		adapter->stats.pxofftxc[i] += IXGBE_READ_REG(hw,
-		                                             IXGBE_PXOFFTXC(i));
+		hwstats->pxontxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
+		hwstats->pxofftxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
 	}
-	adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
+	hwstats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
 	/* work around hardware counting issue */
-	adapter->stats.gprc -= missed_rx;
+	hwstats->gprc -= missed_rx;
 
 	/* 82598 hardware only has a 32 bit counter in the high register */
 	if (hw->mac.type == ixgbe_mac_82599EB) {
 		u64 tmp;
-		adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL);
-		tmp = IXGBE_READ_REG(hw, IXGBE_GORCH) & 0xF; /* 4 high bits of GORC */
-		adapter->stats.gorc += (tmp << 32);
-		adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL);
-		tmp = IXGBE_READ_REG(hw, IXGBE_GOTCH) & 0xF; /* 4 high bits of GOTC */
-		adapter->stats.gotc += (tmp << 32);
-		adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORL);
-		IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */
-		adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
-		adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
-		adapter->stats.fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
-		adapter->stats.fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
+		hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL);
+		tmp = IXGBE_READ_REG(hw, IXGBE_GORCH) & 0xF;
+						/* 4 high bits of GORC */
+		hwstats->gorc += (tmp << 32);
+		hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL);
+		tmp = IXGBE_READ_REG(hw, IXGBE_GOTCH) & 0xF;
+						/* 4 high bits of GOTC */
+		hwstats->gotc += (tmp << 32);
+		hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORL);
+		IXGBE_READ_REG(hw, IXGBE_TORH);	/* to clear */
+		hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
+		hwstats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+		hwstats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
+		hwstats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
 #ifdef IXGBE_FCOE
-		adapter->stats.fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
-		adapter->stats.fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
-		adapter->stats.fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
-		adapter->stats.fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
-		adapter->stats.fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
-		adapter->stats.fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
+		hwstats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
+		hwstats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
+		hwstats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
+		hwstats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
+		hwstats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
+		hwstats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
 #endif /* IXGBE_FCOE */
 	} else {
-		adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
-		adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
-		adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
-		adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
-		adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
+		hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
+		hwstats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+		hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
+		hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
+		hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORH);
 	}
 	bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
-	adapter->stats.bprc += bprc;
-	adapter->stats.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC);
+	hwstats->bprc += bprc;
+	hwstats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC);
 	if (hw->mac.type == ixgbe_mac_82598EB)
-		adapter->stats.mprc -= bprc;
-	adapter->stats.roc += IXGBE_READ_REG(hw, IXGBE_ROC);
-	adapter->stats.prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64);
-	adapter->stats.prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127);
-	adapter->stats.prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255);
-	adapter->stats.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511);
-	adapter->stats.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
-	adapter->stats.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
-	adapter->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
+		hwstats->mprc -= bprc;
+	hwstats->roc += IXGBE_READ_REG(hw, IXGBE_ROC);
+	hwstats->prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64);
+	hwstats->prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127);
+	hwstats->prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255);
+	hwstats->prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511);
+	hwstats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
+	hwstats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
+	hwstats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
 	lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
-	adapter->stats.lxontxc += lxon;
+	hwstats->lxontxc += lxon;
 	lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
-	adapter->stats.lxofftxc += lxoff;
-	adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
-	adapter->stats.gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
-	adapter->stats.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
+	hwstats->lxofftxc += lxoff;
+	hwstats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
+	hwstats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
+	hwstats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
 	/*
 	 * 82598 errata - tx of flow control packets is included in tx counters
 	 */
 	xon_off_tot = lxon + lxoff;
-	adapter->stats.gptc -= xon_off_tot;
-	adapter->stats.mptc -= xon_off_tot;
-	adapter->stats.gotc -= (xon_off_tot * (ETH_ZLEN + ETH_FCS_LEN));
-	adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
-	adapter->stats.rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
-	adapter->stats.rjc += IXGBE_READ_REG(hw, IXGBE_RJC);
-	adapter->stats.tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
-	adapter->stats.ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
-	adapter->stats.ptc64 -= xon_off_tot;
-	adapter->stats.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
-	adapter->stats.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
-	adapter->stats.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
-	adapter->stats.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023);
-	adapter->stats.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522);
-	adapter->stats.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC);
+	hwstats->gptc -= xon_off_tot;
+	hwstats->mptc -= xon_off_tot;
+	hwstats->gotc -= (xon_off_tot * (ETH_ZLEN + ETH_FCS_LEN));
+	hwstats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
+	hwstats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
+	hwstats->rjc += IXGBE_READ_REG(hw, IXGBE_RJC);
+	hwstats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
+	hwstats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
+	hwstats->ptc64 -= xon_off_tot;
+	hwstats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
+	hwstats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
+	hwstats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
+	hwstats->ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023);
+	hwstats->ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522);
+	hwstats->bptc += IXGBE_READ_REG(hw, IXGBE_BPTC);
 
 	/* Fill out the OS statistics structure */
-	netdev->stats.multicast = adapter->stats.mprc;
+	netdev->stats.multicast = hwstats->mprc;
 
 	/* Rx Errors */
-	netdev->stats.rx_errors = adapter->stats.crcerrs +
-	                               adapter->stats.rlec;
+	netdev->stats.rx_errors = hwstats->crcerrs + hwstats->rlec;
 	netdev->stats.rx_dropped = 0;
-	netdev->stats.rx_length_errors = adapter->stats.rlec;
-	netdev->stats.rx_crc_errors = adapter->stats.crcerrs;
+	netdev->stats.rx_length_errors = hwstats->rlec;
+	netdev->stats.rx_crc_errors = hwstats->crcerrs;
 	netdev->stats.rx_missed_errors = total_mpc;
 }
 
@@ -5532,8 +5627,8 @@
 static void ixgbe_multispeed_fiber_task(struct work_struct *work)
 {
 	struct ixgbe_adapter *adapter = container_of(work,
-	                                             struct ixgbe_adapter,
-	                                             multispeed_fiber_task);
+						     struct ixgbe_adapter,
+						     multispeed_fiber_task);
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 autoneg;
 	bool negotiation;
@@ -5556,8 +5651,8 @@
 static void ixgbe_sfp_config_module_task(struct work_struct *work)
 {
 	struct ixgbe_adapter *adapter = container_of(work,
-	                                             struct ixgbe_adapter,
-	                                             sfp_config_module_task);
+						     struct ixgbe_adapter,
+						     sfp_config_module_task);
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 err;
 
@@ -5590,15 +5685,15 @@
 static void ixgbe_fdir_reinit_task(struct work_struct *work)
 {
 	struct ixgbe_adapter *adapter = container_of(work,
-	                                             struct ixgbe_adapter,
-	                                             fdir_reinit_task);
+						     struct ixgbe_adapter,
+						     fdir_reinit_task);
 	struct ixgbe_hw *hw = &adapter->hw;
 	int i;
 
 	if (ixgbe_reinit_fdir_tables_82599(hw) == 0) {
 		for (i = 0; i < adapter->num_tx_queues; i++)
 			set_bit(__IXGBE_FDIR_INIT_DONE,
-			        &(adapter->tx_ring[i]->reinit_state));
+				&(adapter->tx_ring[i]->reinit_state));
 	} else {
 		e_err(probe, "failed to finish FDIR re-initialization, "
 		      "ignored adding FDIR ATR filters\n");
@@ -5616,8 +5711,8 @@
 static void ixgbe_watchdog_task(struct work_struct *work)
 {
 	struct ixgbe_adapter *adapter = container_of(work,
-	                                             struct ixgbe_adapter,
-	                                             watchdog_task);
+						     struct ixgbe_adapter,
+						     watchdog_task);
 	struct net_device *netdev = adapter->netdev;
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 link_speed;
@@ -5648,7 +5743,7 @@
 
 		if (link_up ||
 		    time_after(jiffies, (adapter->link_check_timeout +
-		                         IXGBE_TRY_LINK_TIMEOUT))) {
+					 IXGBE_TRY_LINK_TIMEOUT))) {
 			adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
 			IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC);
 		}
@@ -5719,8 +5814,8 @@
 }
 
 static int ixgbe_tso(struct ixgbe_adapter *adapter,
-                     struct ixgbe_ring *tx_ring, struct sk_buff *skb,
-                     u32 tx_flags, u8 *hdr_len)
+		     struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+		     u32 tx_flags, u8 *hdr_len)
 {
 	struct ixgbe_adv_tx_context_desc *context_desc;
 	unsigned int i;
@@ -5743,28 +5838,28 @@
 			iph->tot_len = 0;
 			iph->check = 0;
 			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-			                                         iph->daddr, 0,
-			                                         IPPROTO_TCP,
-			                                         0);
+								 iph->daddr, 0,
+								 IPPROTO_TCP,
+								 0);
 		} else if (skb_is_gso_v6(skb)) {
 			ipv6_hdr(skb)->payload_len = 0;
 			tcp_hdr(skb)->check =
 			    ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
-			                     &ipv6_hdr(skb)->daddr,
-			                     0, IPPROTO_TCP, 0);
+					     &ipv6_hdr(skb)->daddr,
+					     0, IPPROTO_TCP, 0);
 		}
 
 		i = tx_ring->next_to_use;
 
 		tx_buffer_info = &tx_ring->tx_buffer_info[i];
-		context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i);
+		context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
 
 		/* VLAN MACLEN IPLEN */
 		if (tx_flags & IXGBE_TX_FLAGS_VLAN)
 			vlan_macip_lens |=
 			    (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
 		vlan_macip_lens |= ((skb_network_offset(skb)) <<
-		                    IXGBE_ADVTXD_MACLEN_SHIFT);
+				    IXGBE_ADVTXD_MACLEN_SHIFT);
 		*hdr_len += skb_network_offset(skb);
 		vlan_macip_lens |=
 		    (skb_transport_header(skb) - skb_network_header(skb));
@@ -5775,7 +5870,7 @@
 
 		/* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
 		type_tucmd_mlhl = (IXGBE_TXD_CMD_DEXT |
-		                   IXGBE_ADVTXD_DTYP_CTXT);
+				   IXGBE_ADVTXD_DTYP_CTXT);
 
 		if (skb->protocol == htons(ETH_P_IP))
 			type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
@@ -5803,9 +5898,53 @@
 	return false;
 }
 
+static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb)
+{
+	u32 rtn = 0;
+	__be16 protocol;
+
+	if (skb->protocol == cpu_to_be16(ETH_P_8021Q))
+		protocol = ((const struct vlan_ethhdr *)skb->data)->
+					h_vlan_encapsulated_proto;
+	else
+		protocol = skb->protocol;
+
+	switch (protocol) {
+	case cpu_to_be16(ETH_P_IP):
+		rtn |= IXGBE_ADVTXD_TUCMD_IPV4;
+		switch (ip_hdr(skb)->protocol) {
+		case IPPROTO_TCP:
+			rtn |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+			break;
+		case IPPROTO_SCTP:
+			rtn |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+			break;
+		}
+		break;
+	case cpu_to_be16(ETH_P_IPV6):
+		/* XXX what about other V6 headers?? */
+		switch (ipv6_hdr(skb)->nexthdr) {
+		case IPPROTO_TCP:
+			rtn |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+			break;
+		case IPPROTO_SCTP:
+			rtn |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+			break;
+		}
+		break;
+	default:
+		if (unlikely(net_ratelimit()))
+			e_warn(probe, "partial checksum but proto=%x!\n",
+			       skb->protocol);
+		break;
+	}
+
+	return rtn;
+}
+
 static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
-                          struct ixgbe_ring *tx_ring,
-                          struct sk_buff *skb, u32 tx_flags)
+			  struct ixgbe_ring *tx_ring,
+			  struct sk_buff *skb, u32 tx_flags)
 {
 	struct ixgbe_adv_tx_context_desc *context_desc;
 	unsigned int i;
@@ -5816,63 +5955,25 @@
 	    (tx_flags & IXGBE_TX_FLAGS_VLAN)) {
 		i = tx_ring->next_to_use;
 		tx_buffer_info = &tx_ring->tx_buffer_info[i];
-		context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i);
+		context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
 
 		if (tx_flags & IXGBE_TX_FLAGS_VLAN)
 			vlan_macip_lens |=
 			    (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
 		vlan_macip_lens |= (skb_network_offset(skb) <<
-		                    IXGBE_ADVTXD_MACLEN_SHIFT);
+				    IXGBE_ADVTXD_MACLEN_SHIFT);
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			vlan_macip_lens |= (skb_transport_header(skb) -
-			                    skb_network_header(skb));
+					    skb_network_header(skb));
 
 		context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
 		context_desc->seqnum_seed = 0;
 
 		type_tucmd_mlhl |= (IXGBE_TXD_CMD_DEXT |
-		                    IXGBE_ADVTXD_DTYP_CTXT);
+				    IXGBE_ADVTXD_DTYP_CTXT);
 
-		if (skb->ip_summed == CHECKSUM_PARTIAL) {
-			__be16 protocol;
-
-			if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) {
-				const struct vlan_ethhdr *vhdr =
-					(const struct vlan_ethhdr *)skb->data;
-
-				protocol = vhdr->h_vlan_encapsulated_proto;
-			} else {
-				protocol = skb->protocol;
-			}
-
-			switch (protocol) {
-			case cpu_to_be16(ETH_P_IP):
-				type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
-				if (ip_hdr(skb)->protocol == IPPROTO_TCP)
-					type_tucmd_mlhl |=
-					        IXGBE_ADVTXD_TUCMD_L4T_TCP;
-				else if (ip_hdr(skb)->protocol == IPPROTO_SCTP)
-					type_tucmd_mlhl |=
-					        IXGBE_ADVTXD_TUCMD_L4T_SCTP;
-				break;
-			case cpu_to_be16(ETH_P_IPV6):
-				/* XXX what about other V6 headers?? */
-				if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
-					type_tucmd_mlhl |=
-					        IXGBE_ADVTXD_TUCMD_L4T_TCP;
-				else if (ipv6_hdr(skb)->nexthdr == IPPROTO_SCTP)
-					type_tucmd_mlhl |=
-					        IXGBE_ADVTXD_TUCMD_L4T_SCTP;
-				break;
-			default:
-				if (unlikely(net_ratelimit())) {
-					e_warn(probe, "partial checksum "
-					       "but proto=%x!\n",
-					       skb->protocol);
-				}
-				break;
-			}
-		}
+		if (skb->ip_summed == CHECKSUM_PARTIAL)
+			type_tucmd_mlhl |= ixgbe_psum(adapter, skb);
 
 		context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
 		/* use index zero for tx checksum offload */
@@ -5893,9 +5994,9 @@
 }
 
 static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
-                        struct ixgbe_ring *tx_ring,
-                        struct sk_buff *skb, u32 tx_flags,
-                        unsigned int first)
+			struct ixgbe_ring *tx_ring,
+			struct sk_buff *skb, u32 tx_flags,
+			unsigned int first)
 {
 	struct pci_dev *pdev = adapter->pdev;
 	struct ixgbe_tx_buffer *tx_buffer_info;
@@ -5990,7 +6091,7 @@
 
 	/* clear timestamp and dma mappings for remaining portion of packet */
 	while (count--) {
-		if (i==0)
+		if (i == 0)
 			i += tx_ring->count;
 		i--;
 		tx_buffer_info = &tx_ring->tx_buffer_info[i];
@@ -6001,8 +6102,8 @@
 }
 
 static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
-                           struct ixgbe_ring *tx_ring,
-                           int tx_flags, int count, u32 paylen, u8 hdr_len)
+			   struct ixgbe_ring *tx_ring,
+			   int tx_flags, int count, u32 paylen, u8 hdr_len)
 {
 	union ixgbe_adv_tx_desc *tx_desc = NULL;
 	struct ixgbe_tx_buffer *tx_buffer_info;
@@ -6021,17 +6122,17 @@
 		cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
 
 		olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
-		                 IXGBE_ADVTXD_POPTS_SHIFT;
+				 IXGBE_ADVTXD_POPTS_SHIFT;
 
 		/* use index 1 context for tso */
 		olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
 		if (tx_flags & IXGBE_TX_FLAGS_IPV4)
 			olinfo_status |= IXGBE_TXD_POPTS_IXSM <<
-			                 IXGBE_ADVTXD_POPTS_SHIFT;
+					 IXGBE_ADVTXD_POPTS_SHIFT;
 
 	} else if (tx_flags & IXGBE_TX_FLAGS_CSUM)
 		olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
-		                 IXGBE_ADVTXD_POPTS_SHIFT;
+				 IXGBE_ADVTXD_POPTS_SHIFT;
 
 	if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
 		olinfo_status |= IXGBE_ADVTXD_CC;
@@ -6045,10 +6146,10 @@
 	i = tx_ring->next_to_use;
 	while (count--) {
 		tx_buffer_info = &tx_ring->tx_buffer_info[i];
-		tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
+		tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
 		tx_desc->read.buffer_addr = cpu_to_le64(tx_buffer_info->dma);
 		tx_desc->read.cmd_type_len =
-		        cpu_to_le32(cmd_type_len | tx_buffer_info->length);
+			cpu_to_le32(cmd_type_len | tx_buffer_info->length);
 		tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
 		i++;
 		if (i == tx_ring->count)
@@ -6070,7 +6171,7 @@
 }
 
 static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
-	              int queue, u32 tx_flags)
+		      int queue, u32 tx_flags)
 {
 	struct ixgbe_atr_input atr_input;
 	struct tcphdr *th;
@@ -6098,7 +6199,7 @@
 	memset(&atr_input, 0, sizeof(struct ixgbe_atr_input));
 
 	vlan_id = (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK) >>
-	           IXGBE_TX_FLAGS_VLAN_SHIFT;
+		   IXGBE_TX_FLAGS_VLAN_SHIFT;
 	src_ipv4_addr = iph->saddr;
 	dst_ipv4_addr = iph->daddr;
 	flex_bytes = eth->h_proto;
@@ -6117,7 +6218,7 @@
 }
 
 static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
-                                 struct ixgbe_ring *tx_ring, int size)
+				 struct ixgbe_ring *tx_ring, int size)
 {
 	netif_stop_subqueue(netdev, tx_ring->queue_index);
 	/* Herbert's original patch had:
@@ -6137,7 +6238,7 @@
 }
 
 static int ixgbe_maybe_stop_tx(struct net_device *netdev,
-                              struct ixgbe_ring *tx_ring, int size)
+			      struct ixgbe_ring *tx_ring, int size)
 {
 	if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size))
 		return 0;
@@ -6183,11 +6284,10 @@
 	return skb_tx_hash(dev, skb);
 }
 
-static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
-				    struct net_device *netdev)
+netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev,
+			  struct ixgbe_adapter *adapter,
+			  struct ixgbe_ring *tx_ring)
 {
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	struct ixgbe_ring *tx_ring;
 	struct netdev_queue *txq;
 	unsigned int first;
 	unsigned int tx_flags = 0;
@@ -6196,7 +6296,7 @@
 	int count = 0;
 	unsigned int f;
 
-	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		tx_flags |= vlan_tx_tag_get(skb);
 		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
 			tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
@@ -6211,8 +6311,6 @@
 		tx_flags |= IXGBE_TX_FLAGS_VLAN;
 	}
 
-	tx_ring = adapter->tx_ring[skb->queue_mapping];
-
 #ifdef IXGBE_FCOE
 	/* for FCoE with DCB, we force the priority to what
 	 * was specified by the switch */
@@ -6283,10 +6381,10 @@
 		if (tx_ring->atr_sample_rate) {
 			++tx_ring->atr_count;
 			if ((tx_ring->atr_count >= tx_ring->atr_sample_rate) &&
-		             test_bit(__IXGBE_FDIR_INIT_DONE,
-                                      &tx_ring->reinit_state)) {
+			     test_bit(__IXGBE_FDIR_INIT_DONE,
+				      &tx_ring->reinit_state)) {
 				ixgbe_atr(adapter, skb, tx_ring->queue_index,
-				          tx_flags);
+					  tx_flags);
 				tx_ring->atr_count = 0;
 			}
 		}
@@ -6294,7 +6392,7 @@
 		txq->tx_bytes += skb->len;
 		txq->tx_packets++;
 		ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len,
-		               hdr_len);
+			       hdr_len);
 		ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED);
 
 	} else {
@@ -6306,6 +6404,15 @@
 	return NETDEV_TX_OK;
 }
 
+static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_ring *tx_ring;
+
+	tx_ring = adapter->tx_ring[skb->queue_mapping];
+	return ixgbe_xmit_frame_ring(skb, netdev, adapter, tx_ring);
+}
+
 /**
  * ixgbe_set_mac - Change the Ethernet Address of the NIC
  * @netdev: network interface device structure
@@ -6436,8 +6543,40 @@
 }
 #endif
 
+static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev,
+						   struct rtnl_link_stats64 *stats)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	int i;
+
+	/* accurate rx/tx bytes/packets stats */
+	dev_txq_stats_fold(netdev, stats);
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		struct ixgbe_ring *ring = adapter->rx_ring[i];
+		u64 bytes, packets;
+		unsigned int start;
+
+		do {
+			start = u64_stats_fetch_begin_bh(&ring->syncp);
+			packets = ring->stats.packets;
+			bytes   = ring->stats.bytes;
+		} while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+		stats->rx_packets += packets;
+		stats->rx_bytes   += bytes;
+	}
+
+	/* following stats updated by ixgbe_watchdog_task() */
+	stats->multicast	= netdev->stats.multicast;
+	stats->rx_errors	= netdev->stats.rx_errors;
+	stats->rx_length_errors	= netdev->stats.rx_length_errors;
+	stats->rx_crc_errors	= netdev->stats.rx_crc_errors;
+	stats->rx_missed_errors	= netdev->stats.rx_missed_errors;
+	return stats;
+}
+
+
 static const struct net_device_ops ixgbe_netdev_ops = {
-	.ndo_open 		= ixgbe_open,
+	.ndo_open		= ixgbe_open,
 	.ndo_stop		= ixgbe_close,
 	.ndo_start_xmit		= ixgbe_xmit_frame,
 	.ndo_select_queue	= ixgbe_select_queue,
@@ -6447,7 +6586,6 @@
 	.ndo_set_mac_address	= ixgbe_set_mac,
 	.ndo_change_mtu		= ixgbe_change_mtu,
 	.ndo_tx_timeout		= ixgbe_tx_timeout,
-	.ndo_vlan_rx_register	= ixgbe_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= ixgbe_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= ixgbe_vlan_rx_kill_vid,
 	.ndo_do_ioctl		= ixgbe_ioctl,
@@ -6455,6 +6593,7 @@
 	.ndo_set_vf_vlan	= ixgbe_ndo_set_vf_vlan,
 	.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_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= ixgbe_netpoll,
 #endif
@@ -6532,7 +6671,7 @@
  * and a hardware reset occur.
  **/
 static int __devinit ixgbe_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+				 const struct pci_device_id *ent)
 {
 	struct net_device *netdev;
 	struct ixgbe_adapter *adapter = NULL;
@@ -6577,7 +6716,7 @@
 	}
 
 	err = pci_request_selected_regions(pdev, pci_select_bars(pdev,
-	                                   IORESOURCE_MEM), ixgbe_driver_name);
+					   IORESOURCE_MEM), ixgbe_driver_name);
 	if (err) {
 		dev_err(&pdev->dev,
 			"pci_request_selected_regions failed 0x%x\n", err);
@@ -6617,7 +6756,7 @@
 	adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
 
 	hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
-	                      pci_resource_len(pdev, 0));
+			      pci_resource_len(pdev, 0));
 	if (!hw->hw_addr) {
 		err = -EIO;
 		goto err_ioremap;
@@ -6661,7 +6800,7 @@
 	 * which might start the timer
 	 */
 	init_timer(&adapter->sfp_timer);
-	adapter->sfp_timer.function = &ixgbe_sfp_timer;
+	adapter->sfp_timer.function = ixgbe_sfp_timer;
 	adapter->sfp_timer.data = (unsigned long) adapter;
 
 	INIT_WORK(&adapter->sfp_task, ixgbe_sfp_task);
@@ -6671,7 +6810,7 @@
 
 	/* a new SFP+ module arrival, called from GPI SDP2 context */
 	INIT_WORK(&adapter->sfp_config_module_task,
-	          ixgbe_sfp_config_module_task);
+		  ixgbe_sfp_config_module_task);
 
 	ii->get_invariants(hw);
 
@@ -6723,10 +6862,10 @@
 	ixgbe_probe_vf(adapter, ii);
 
 	netdev->features = NETIF_F_SG |
-	                   NETIF_F_IP_CSUM |
-	                   NETIF_F_HW_VLAN_TX |
-	                   NETIF_F_HW_VLAN_RX |
-	                   NETIF_F_HW_VLAN_FILTER;
+			   NETIF_F_IP_CSUM |
+			   NETIF_F_HW_VLAN_TX |
+			   NETIF_F_HW_VLAN_RX |
+			   NETIF_F_HW_VLAN_FILTER;
 
 	netdev->features |= NETIF_F_IPV6_CSUM;
 	netdev->features |= NETIF_F_TSO;
@@ -6766,8 +6905,10 @@
 		netdev->vlan_features |= NETIF_F_FCOE_MTU;
 	}
 #endif /* IXGBE_FCOE */
-	if (pci_using_dac)
+	if (pci_using_dac) {
 		netdev->features |= NETIF_F_HIGHDMA;
+		netdev->vlan_features |= NETIF_F_HIGHDMA;
+	}
 
 	if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
 		netdev->features |= NETIF_F_LRO;
@@ -6793,7 +6934,7 @@
 		hw->mac.ops.disable_tx_laser(hw);
 
 	init_timer(&adapter->watchdog_timer);
-	adapter->watchdog_timer.function = &ixgbe_watchdog;
+	adapter->watchdog_timer.function = ixgbe_watchdog;
 	adapter->watchdog_timer.data = (unsigned long)adapter;
 
 	INIT_WORK(&adapter->reset_task, ixgbe_reset_task);
@@ -6806,7 +6947,7 @@
 	switch (pdev->device) {
 	case IXGBE_DEV_ID_82599_KX4:
 		adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
-		                IXGBE_WUFC_MC | IXGBE_WUFC_BC);
+				IXGBE_WUFC_MC | IXGBE_WUFC_BC);
 		break;
 	default:
 		adapter->wol = 0;
@@ -6819,13 +6960,14 @@
 
 	/* print bus type/speed/width info */
 	e_dev_info("(PCI Express:%s:%s) %pM\n",
-	        ((hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0Gb/s":
-	         (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5Gb/s":"Unknown"),
-	        ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" :
-	         (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" :
-	         (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" :
-	         "Unknown"),
-	        netdev->dev_addr);
+		   (hw->bus.speed == ixgbe_bus_speed_5000 ? "5.0Gb/s" :
+		    hw->bus.speed == ixgbe_bus_speed_2500 ? "2.5Gb/s" :
+		    "Unknown"),
+		   (hw->bus.width == ixgbe_bus_width_pcie_x8 ? "Width x8" :
+		    hw->bus.width == ixgbe_bus_width_pcie_x4 ? "Width x4" :
+		    hw->bus.width == ixgbe_bus_width_pcie_x1 ? "Width x1" :
+		    "Unknown"),
+		   netdev->dev_addr);
 	ixgbe_read_pba_num_generic(hw, &part_num);
 	if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present)
 		e_dev_info("MAC: %d, PHY: %d, SFP+: %d, "
@@ -6872,7 +7014,8 @@
 		INIT_WORK(&adapter->fdir_reinit_task, ixgbe_fdir_reinit_task);
 
 	if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
-		INIT_WORK(&adapter->check_overtemp_task, ixgbe_check_overtemp_task);
+		INIT_WORK(&adapter->check_overtemp_task,
+			  ixgbe_check_overtemp_task);
 #ifdef CONFIG_IXGBE_DCA
 	if (dca_add_requester(&pdev->dev) == 0) {
 		adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
@@ -6908,8 +7051,8 @@
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
-	pci_release_selected_regions(pdev, pci_select_bars(pdev,
-	                             IORESOURCE_MEM));
+	pci_release_selected_regions(pdev,
+				     pci_select_bars(pdev, IORESOURCE_MEM));
 err_pci_reg:
 err_dma:
 	pci_disable_device(pdev);
@@ -6976,7 +7119,7 @@
 
 	iounmap(adapter->hw.hw_addr);
 	pci_release_selected_regions(pdev, pci_select_bars(pdev,
-	                             IORESOURCE_MEM));
+				     IORESOURCE_MEM));
 
 	e_dev_info("complete\n");
 
@@ -6996,7 +7139,7 @@
  * this device has been detected.
  */
 static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
-                                                pci_channel_state_t state)
+						pci_channel_state_t state)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
@@ -7102,8 +7245,7 @@
 static int __init ixgbe_init_module(void)
 {
 	int ret;
-	pr_info("%s - version %s\n", ixgbe_driver_string,
-		   ixgbe_driver_version);
+	pr_info("%s - version %s\n", ixgbe_driver_string, ixgbe_driver_version);
 	pr_info("%s\n", ixgbe_copyright);
 
 #ifdef CONFIG_IXGBE_DCA
@@ -7132,12 +7274,12 @@
 
 #ifdef CONFIG_IXGBE_DCA
 static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
-                            void *p)
+			    void *p)
 {
 	int ret_val;
 
 	ret_val = driver_for_each_device(&ixgbe_driver.driver, NULL, &event,
-	                                 __ixgbe_notify_dca);
+					 __ixgbe_notify_dca);
 
 	return ret_val ? NOTIFY_BAD : NOTIFY_DONE;
 }
diff --git a/drivers/net/ixgbe/ixgbe_mbx.c b/drivers/net/ixgbe/ixgbe_mbx.c
index d75f914..471f0f2 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 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 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,
@@ -200,7 +200,8 @@
  *  returns SUCCESS if it successfully received a message notification and
  *  copied it into the receive buffer.
  **/
-s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
+				 u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
 	s32 ret_val = IXGBE_ERR_MBX;
@@ -227,7 +228,7 @@
  *  returns SUCCESS if it successfully copied message into the buffer and
  *  received an ack to that message within delay * timeout period
  **/
-s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
+static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
                            u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
@@ -247,20 +248,6 @@
 	return ret_val;
 }
 
-/**
- *  ixgbe_init_mbx_ops_generic - Initialize MB function pointers
- *  @hw: pointer to the HW structure
- *
- *  Setup the mailbox read and write message function pointers
- **/
-void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw)
-{
-	struct ixgbe_mbx_info *mbx = &hw->mbx;
-
-	mbx->ops.read_posted = ixgbe_read_posted_mbx;
-	mbx->ops.write_posted = ixgbe_write_posted_mbx;
-}
-
 static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
 {
 	u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
diff --git a/drivers/net/ixgbe/ixgbe_mbx.h b/drivers/net/ixgbe/ixgbe_mbx.h
index be7ab33..7e0d08f 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 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 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,
@@ -83,12 +83,9 @@
 
 s32 ixgbe_read_mbx(struct ixgbe_hw *, u32 *, u16, u16);
 s32 ixgbe_write_mbx(struct ixgbe_hw *, u32 *, u16, u16);
-s32 ixgbe_read_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16);
-s32 ixgbe_write_posted_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);
-void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw);
 void ixgbe_init_mbx_params_pf(struct ixgbe_hw *);
 
 extern struct ixgbe_mbx_operations mbx_ops_82599;
diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c
index 49661a1..5428153 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 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 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,
@@ -43,8 +43,8 @@
 
 #include "ixgbe_sriov.h"
 
-int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
-			    int entries, u16 *hash_list, u32 vf)
+static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
+				   int entries, u16 *hash_list, u32 vf)
 {
 	struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
 	struct ixgbe_hw *hw = &adapter->hw;
@@ -104,13 +104,14 @@
 	}
 }
 
-int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf)
+static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
+			     u32 vf)
 {
 	return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);
 }
 
 
-void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
+static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
 {
 	u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
 	vmolr |= (IXGBE_VMOLR_ROMPE |
@@ -134,7 +135,7 @@
 		IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0);
 }
 
-inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
+static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	int rar_entry = hw->mac.num_rar_entries - (vf + 1);
@@ -162,8 +163,8 @@
 	hw->mac.ops.clear_rar(hw, rar_entry);
 }
 
-int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
-                          int vf, unsigned char *mac_addr)
+static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
+			    int vf, unsigned char *mac_addr)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	int rar_entry = hw->mac.num_rar_entries - (vf + 1);
@@ -197,7 +198,7 @@
 	return 0;
 }
 
-inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
+static inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 reg;
diff --git a/drivers/net/ixgbe/ixgbe_sriov.h b/drivers/net/ixgbe/ixgbe_sriov.h
index 184730e..49dc14d 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 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -28,16 +28,8 @@
 #ifndef _IXGBE_SRIOV_H_
 #define _IXGBE_SRIOV_H_
 
-int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
-                            int entries, u16 *hash_list, u32 vf);
 void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter);
-int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf);
-void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe);
-void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf);
-void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf);
 void ixgbe_msg_task(struct ixgbe_adapter *adapter);
-int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
-                     int vf, unsigned char *mac_addr);
 int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask);
 void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter);
 void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter);
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 9587d97..d3cc6ce 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -871,6 +871,8 @@
 #define IXGBE_RDRXCTL_MVMEN         0x00000020
 #define IXGBE_RDRXCTL_DMAIDONE      0x00000008 /* DMA init cycle done */
 #define IXGBE_RDRXCTL_AGGDIS        0x00010000 /* Aggregation disable */
+#define IXGBE_RDRXCTL_RSCACKC       0x02000000 /* must set 1 when RSC enabled */
+#define IXGBE_RDRXCTL_FCOE_WRFIX    0x04000000 /* must set 1 when RSC enabled */
 
 /* RQTC Bit Masks and Shifts */
 #define IXGBE_RQTC_SHIFT_TC(_i)     ((_i) * 4)
diff --git a/drivers/net/ixgbevf/ethtool.c b/drivers/net/ixgbevf/ethtool.c
index 4680b06..4cc817a 100644
--- a/drivers/net/ixgbevf/ethtool.c
+++ b/drivers/net/ixgbevf/ethtool.c
@@ -330,10 +330,8 @@
 {
 	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
 	struct ixgbevf_ring *tx_ring = NULL, *rx_ring = NULL;
-	int i, err;
+	int i, err = 0;
 	u32 new_rx_count, new_tx_count;
-	bool need_tx_update = false;
-	bool need_rx_update = false;
 
 	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 		return -EINVAL;
@@ -355,89 +353,96 @@
 	while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state))
 		msleep(1);
 
-	if (new_tx_count != adapter->tx_ring_count) {
-		tx_ring = kcalloc(adapter->num_tx_queues,
-				  sizeof(struct ixgbevf_ring), GFP_KERNEL);
-		if (!tx_ring) {
-			err = -ENOMEM;
-			goto err_setup;
-		}
-		memcpy(tx_ring, adapter->tx_ring,
-		       adapter->num_tx_queues * sizeof(struct ixgbevf_ring));
-		for (i = 0; i < adapter->num_tx_queues; i++) {
-			tx_ring[i].count = new_tx_count;
-			err = ixgbevf_setup_tx_resources(adapter,
-							 &tx_ring[i]);
-			if (err) {
-				while (i) {
-					i--;
-					ixgbevf_free_tx_resources(adapter,
-								  &tx_ring[i]);
-				}
-				kfree(tx_ring);
-				goto err_setup;
-			}
-			tx_ring[i].v_idx = adapter->tx_ring[i].v_idx;
-		}
-		need_tx_update = true;
-	}
-
-	if (new_rx_count != adapter->rx_ring_count) {
-		rx_ring = kcalloc(adapter->num_rx_queues,
-				  sizeof(struct ixgbevf_ring), GFP_KERNEL);
-		if ((!rx_ring) && (need_tx_update)) {
-			err = -ENOMEM;
-			goto err_rx_setup;
-		}
-		memcpy(rx_ring, adapter->rx_ring,
-		       adapter->num_rx_queues * sizeof(struct ixgbevf_ring));
-		for (i = 0; i < adapter->num_rx_queues; i++) {
-			rx_ring[i].count = new_rx_count;
-			err = ixgbevf_setup_rx_resources(adapter,
-							 &rx_ring[i]);
-			if (err) {
-				while (i) {
-					i--;
-					ixgbevf_free_rx_resources(adapter,
-								  &rx_ring[i]);
-				}
-				kfree(rx_ring);
-				goto err_rx_setup;
-			}
-			rx_ring[i].v_idx = adapter->rx_ring[i].v_idx;
-		}
-		need_rx_update = true;
-	}
-
-err_rx_setup:
-	/* if rings need to be updated, here's the place to do it in one shot */
-	if (need_tx_update || need_rx_update) {
-		if (netif_running(netdev))
-			ixgbevf_down(adapter);
-	}
-
-	/* tx */
-	if (need_tx_update) {
-		kfree(adapter->tx_ring);
-		adapter->tx_ring = tx_ring;
-		tx_ring = NULL;
+	/*
+	 * If the adapter isn't up and running then just set the
+	 * new parameters and scurry for the exits.
+	 */
+	if (!netif_running(adapter->netdev)) {
+		for (i = 0; i < adapter->num_tx_queues; i++)
+			adapter->tx_ring[i].count = new_tx_count;
+		for (i = 0; i < adapter->num_rx_queues; i++)
+			adapter->rx_ring[i].count = new_rx_count;
 		adapter->tx_ring_count = new_tx_count;
+		adapter->rx_ring_count = new_rx_count;
+		goto clear_reset;
 	}
 
-	/* rx */
-	if (need_rx_update) {
-		kfree(adapter->rx_ring);
-		adapter->rx_ring = rx_ring;
-		rx_ring = NULL;
-		adapter->rx_ring_count = new_rx_count;
+	tx_ring = kcalloc(adapter->num_tx_queues,
+			  sizeof(struct ixgbevf_ring), GFP_KERNEL);
+	if (!tx_ring) {
+		err = -ENOMEM;
+		goto clear_reset;
 	}
 
+	rx_ring = kcalloc(adapter->num_rx_queues,
+			  sizeof(struct ixgbevf_ring), GFP_KERNEL);
+	if (!rx_ring) {
+		err = -ENOMEM;
+		goto err_rx_setup;
+	}
+
+	ixgbevf_down(adapter);
+
+	memcpy(tx_ring, adapter->tx_ring,
+	       adapter->num_tx_queues * sizeof(struct ixgbevf_ring));
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		tx_ring[i].count = new_tx_count;
+		err = ixgbevf_setup_tx_resources(adapter, &tx_ring[i]);
+		if (err) {
+			while (i) {
+				i--;
+				ixgbevf_free_tx_resources(adapter,
+							  &tx_ring[i]);
+			}
+			goto err_tx_ring_setup;
+		}
+		tx_ring[i].v_idx = adapter->tx_ring[i].v_idx;
+	}
+
+	memcpy(rx_ring, adapter->rx_ring,
+	       adapter->num_rx_queues * sizeof(struct ixgbevf_ring));
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		rx_ring[i].count = new_rx_count;
+		err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]);
+		if (err) {
+			while (i) {
+				i--;
+				ixgbevf_free_rx_resources(adapter,
+							  &rx_ring[i]);
+			}
+				goto err_rx_ring_setup;
+		}
+		rx_ring[i].v_idx = adapter->rx_ring[i].v_idx;
+	}
+
+	/*
+	 * Only switch to new rings if all the prior allocations
+	 * and ring setups have succeeded.
+	 */
+	kfree(adapter->tx_ring);
+	adapter->tx_ring = tx_ring;
+	adapter->tx_ring_count = new_tx_count;
+
+	kfree(adapter->rx_ring);
+	adapter->rx_ring = rx_ring;
+	adapter->rx_ring_count = new_rx_count;
+
 	/* success! */
-	err = 0;
-	if (netif_running(netdev))
-		ixgbevf_up(adapter);
+	ixgbevf_up(adapter);
 
-err_setup:
+	goto clear_reset;
+
+err_rx_ring_setup:
+	for(i = 0; i < adapter->num_tx_queues; i++)
+		ixgbevf_free_tx_resources(adapter, &tx_ring[i]);
+
+err_tx_ring_setup:
+	kfree(rx_ring);
+
+err_rx_setup:
+	kfree(tx_ring);
+
+clear_reset:
 	clear_bit(__IXGBEVF_RESETTING, &adapter->state);
 	return err;
 }
diff --git a/drivers/net/ixgbevf/ixgbevf.h b/drivers/net/ixgbevf/ixgbevf.h
index f7015ef..da4033c 100644
--- a/drivers/net/ixgbevf/ixgbevf.h
+++ b/drivers/net/ixgbevf/ixgbevf.h
@@ -243,7 +243,6 @@
 	/* OS defined structs */
 	struct net_device *netdev;
 	struct pci_dev *pdev;
-	struct net_device_stats net_stats;
 
 	/* structs defined in ixgbe_vf.h */
 	struct ixgbe_hw hw;
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index 918c003..dc03c96 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -308,10 +308,10 @@
 	tx_ring->total_bytes += total_bytes;
 	tx_ring->total_packets += total_packets;
 
-	adapter->net_stats.tx_bytes += total_bytes;
-	adapter->net_stats.tx_packets += total_packets;
+	netdev->stats.tx_bytes += total_bytes;
+	netdev->stats.tx_packets += total_packets;
 
-	return (count < tx_ring->work_limit);
+	return count < tx_ring->work_limit;
 }
 
 /**
@@ -356,7 +356,7 @@
 static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter,
 				       u32 status_err, struct sk_buff *skb)
 {
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 
 	/* Rx csum disabled */
 	if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
@@ -639,8 +639,8 @@
 
 	rx_ring->total_packets += total_rx_packets;
 	rx_ring->total_bytes += total_rx_bytes;
-	adapter->net_stats.rx_bytes += total_rx_bytes;
-	adapter->net_stats.rx_packets += total_rx_packets;
+	adapter->netdev->stats.rx_bytes += total_rx_bytes;
+	adapter->netdev->stats.rx_packets += total_rx_packets;
 
 	return cleaned;
 }
@@ -1495,7 +1495,7 @@
 
 	if (adapter->vlgrp) {
 		u16 vid;
-		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+		for (vid = 0; vid < VLAN_N_VID; vid++) {
 			if (!vlan_group_get_device(adapter->vlgrp, vid))
 				continue;
 			ixgbevf_vlan_rx_add_vid(adapter->netdev, vid);
@@ -2297,7 +2297,7 @@
 				adapter->stats.vfmprc);
 
 	/* Fill out the OS statistics structure */
-	adapter->net_stats.multicast = adapter->stats.vfmprc -
+	adapter->netdev->stats.multicast = adapter->stats.vfmprc -
 		adapter->stats.base_vfmprc;
 }
 
@@ -3134,7 +3134,7 @@
 
 	tx_ring = &adapter->tx_ring[r_idx];
 
-	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		tx_flags |= vlan_tx_tag_get(skb);
 		tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
 		tx_flags |= IXGBE_TX_FLAGS_VLAN;
@@ -3181,21 +3181,6 @@
 }
 
 /**
- * ixgbevf_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
- **/
-static struct net_device_stats *ixgbevf_get_stats(struct net_device *netdev)
-{
-	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
-
-	/* only return the current stats */
-	return &adapter->net_stats;
-}
-
-/**
  * ixgbevf_set_mac - Change the Ethernet Address of the NIC
  * @netdev: network interface device structure
  * @p: pointer to an address structure
@@ -3272,7 +3257,6 @@
 	.ndo_open		= &ixgbevf_open,
 	.ndo_stop		= &ixgbevf_close,
 	.ndo_start_xmit		= &ixgbevf_xmit_frame,
-	.ndo_get_stats		= &ixgbevf_get_stats,
 	.ndo_set_rx_mode	= &ixgbevf_set_rx_mode,
 	.ndo_set_multicast_list	= &ixgbevf_set_rx_mode,
 	.ndo_validate_addr	= eth_validate_addr,
@@ -3426,7 +3410,7 @@
 	}
 
 	init_timer(&adapter->watchdog_timer);
-	adapter->watchdog_timer.function = &ixgbevf_watchdog;
+	adapter->watchdog_timer.function = ixgbevf_watchdog;
 	adapter->watchdog_timer.data = (unsigned long)adapter;
 
 	INIT_WORK(&adapter->reset_task, ixgbevf_reset_task);
diff --git a/drivers/net/ixgbevf/mbx.c b/drivers/net/ixgbevf/mbx.c
index b814350..84ac486 100644
--- a/drivers/net/ixgbevf/mbx.c
+++ b/drivers/net/ixgbevf/mbx.c
@@ -308,7 +308,7 @@
  *
  *  Initializes the hw->mbx struct to correct values for vf mailbox
  */
-s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw)
+static s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
 
diff --git a/drivers/net/ixgbevf/mbx.h b/drivers/net/ixgbevf/mbx.h
index 1b0e0bf..8c063be 100644
--- a/drivers/net/ixgbevf/mbx.h
+++ b/drivers/net/ixgbevf/mbx.h
@@ -95,6 +95,4 @@
 /* forward declaration of the HW struct */
 struct ixgbe_hw;
 
-s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *);
-
 #endif /* _IXGBE_MBX_H_ */
diff --git a/drivers/net/ixgbevf/vf.c b/drivers/net/ixgbevf/vf.c
index f6f9299..bfe42c1 100644
--- a/drivers/net/ixgbevf/vf.c
+++ b/drivers/net/ixgbevf/vf.c
@@ -368,7 +368,7 @@
 	return 0;
 }
 
-struct ixgbe_mac_operations ixgbevf_mac_ops = {
+static struct ixgbe_mac_operations ixgbevf_mac_ops = {
 	.init_hw             = ixgbevf_init_hw_vf,
 	.reset_hw            = ixgbevf_reset_hw_vf,
 	.start_hw            = ixgbevf_start_hw_vf,
diff --git a/drivers/net/ixgbevf/vf.h b/drivers/net/ixgbevf/vf.h
index 94b750b..61f9dc8 100644
--- a/drivers/net/ixgbevf/vf.h
+++ b/drivers/net/ixgbevf/vf.h
@@ -124,8 +124,6 @@
 	void *back;
 
 	u8 __iomem *hw_addr;
-	u8 *flash_address;
-	unsigned long io_base;
 
 	struct ixgbe_mac_info mac;
 	struct ixgbe_mbx_info mbx;
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 99f24f5..d7a975e 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -3,6 +3,7 @@
  *
  * Copyright 2008 JMicron Technology Corporation
  * http://www.jmicron.com/
+ * Copyright (c) 2009 - 2010 Guo-Fu Tseng <cooldavid@cooldavid.org>
  *
  * Author: Guo-Fu Tseng <cooldavid@cooldavid.org>
  *
@@ -21,6 +22,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -73,7 +76,7 @@
 	}
 
 	if (i == 0) {
-		jeprintk(jme->pdev, "phy(%d) read timeout : %d\n", phy, reg);
+		pr_err("phy(%d) read timeout : %d\n", phy, reg);
 		return 0;
 	}
 
@@ -102,7 +105,7 @@
 	}
 
 	if (i == 0)
-		jeprintk(jme->pdev, "phy(%d) write timeout : %d\n", phy, reg);
+		pr_err("phy(%d) write timeout : %d\n", phy, reg);
 }
 
 static inline void
@@ -227,7 +230,7 @@
 		}
 
 		if (i == 0) {
-			jeprintk(jme->pdev, "eeprom reload timeout\n");
+			pr_err("eeprom reload timeout\n");
 			return -EIO;
 		}
 	}
@@ -397,8 +400,7 @@
 					phylink = jread32(jme, JME_PHY_LINK);
 			}
 			if (!cnt)
-				jeprintk(jme->pdev,
-					"Waiting speed resolve timeout.\n");
+				pr_err("Waiting speed resolve timeout\n");
 
 			strcat(linkmsg, "ANed: ");
 		}
@@ -480,13 +482,13 @@
 		strcat(linkmsg, (phylink & PHY_LINK_MDI_STAT) ?
 					"MDI-X" :
 					"MDI");
-		netif_info(jme, link, jme->dev, "Link is up at %s.\n", linkmsg);
+		netif_info(jme, link, jme->dev, "Link is up at %s\n", linkmsg);
 		netif_carrier_on(netdev);
 	} else {
 		if (testonly)
 			goto out;
 
-		netif_info(jme, link, jme->dev, "Link is down.\n");
+		netif_info(jme, link, jme->dev, "Link is down\n");
 		jme->phylink = 0;
 		netif_carrier_off(netdev);
 	}
@@ -648,7 +650,7 @@
 	}
 
 	if (!i)
-		jeprintk(jme->pdev, "Disable TX engine timeout.\n");
+		pr_err("Disable TX engine timeout\n");
 }
 
 static void
@@ -867,7 +869,7 @@
 	}
 
 	if (!i)
-		jeprintk(jme->pdev, "Disable RX engine timeout.\n");
+		pr_err("Disable RX engine timeout\n");
 
 }
 
@@ -887,13 +889,13 @@
 	if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS))
 			== RXWBFLAG_UDPON)) {
 		if (flags & RXWBFLAG_IPV4)
-			netif_err(jme, rx_err, jme->dev, "UDP Checksum error.\n");
+			netif_err(jme, rx_err, jme->dev, "UDP Checksum error\n");
 		return false;
 	}
 
 	if (unlikely((flags & (RXWBFLAG_IPV4 | RXWBFLAG_IPCS))
 			== RXWBFLAG_IPV4)) {
-		netif_err(jme, rx_err, jme->dev, "IPv4 Checksum error.\n");
+		netif_err(jme, rx_err, jme->dev, "IPv4 Checksum error\n");
 		return false;
 	}
 
@@ -936,7 +938,7 @@
 		if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags)))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
 
 		if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) {
 			if (jme->vlgrp) {
@@ -988,6 +990,7 @@
 			goto out;
 		--limit;
 
+		rmb();
 		desccnt = rxdesc->descwb.desccnt & RXWBDCNT_DCNT;
 
 		if (unlikely(desccnt > 1 ||
@@ -1185,9 +1188,9 @@
 
 	while (!atomic_dec_and_test(&jme->link_changing)) {
 		atomic_inc(&jme->link_changing);
-		netif_info(jme, intr, jme->dev, "Get link change lock failed.\n");
+		netif_info(jme, intr, jme->dev, "Get link change lock failed\n");
 		while (atomic_read(&jme->link_changing) != 1)
-			netif_info(jme, intr, jme->dev, "Waiting link change lock.\n");
+			netif_info(jme, intr, jme->dev, "Waiting link change lock\n");
 	}
 
 	if (jme_check_link(netdev, 1) && jme->old_mtu == netdev->mtu)
@@ -1221,15 +1224,13 @@
 	if (netif_carrier_ok(netdev)) {
 		rc = jme_setup_rx_resources(jme);
 		if (rc) {
-			jeprintk(jme->pdev, "Allocating resources for RX error"
-				", Device STOPPED!\n");
+			pr_err("Allocating resources for RX error, Device STOPPED!\n");
 			goto out_enable_tasklet;
 		}
 
 		rc = jme_setup_tx_resources(jme);
 		if (rc) {
-			jeprintk(jme->pdev, "Allocating resources for TX error"
-				", Device STOPPED!\n");
+			pr_err("Allocating resources for TX error, Device STOPPED!\n");
 			goto err_out_free_rx_resources;
 		}
 
@@ -1324,7 +1325,7 @@
 	smp_wmb();
 	if (unlikely(netif_queue_stopped(jme->dev) &&
 	atomic_read(&txring->nr_free) >= (jme->tx_wake_threshold))) {
-		netif_info(jme, tx_done, jme->dev, "TX Queue Waked.\n");
+		netif_info(jme, tx_done, jme->dev, "TX Queue Waked\n");
 		netif_wake_queue(jme->dev);
 	}
 
@@ -1339,7 +1340,7 @@
 	struct jme_buffer_info *txbi = txring->bufinf, *ctxbi, *ttxbi;
 	int i, j, cnt = 0, max, err, mask;
 
-	tx_dbg(jme, "Into txclean.\n");
+	tx_dbg(jme, "Into txclean\n");
 
 	if (unlikely(!atomic_dec_and_test(&jme->tx_cleaning)))
 		goto out;
@@ -1361,7 +1362,7 @@
 		!(txdesc[i].descwb.flags & TXWBFLAG_OWN))) {
 
 			tx_dbg(jme, "txclean: %d+%d@%lu\n",
-					i, ctxbi->nr_desc, jiffies);
+			       i, ctxbi->nr_desc, jiffies);
 
 			err = txdesc[i].descwb.flags & TXWBFLAG_ALLERR;
 
@@ -1402,7 +1403,7 @@
 		ctxbi->nr_desc = 0;
 	}
 
-	tx_dbg(jme, "txclean: done %d@%lu.\n", i, jiffies);
+	tx_dbg(jme, "txclean: done %d@%lu\n", i, jiffies);
 	atomic_set(&txring->next_to_clean, i);
 	atomic_add(cnt, &txring->nr_free);
 
@@ -1548,10 +1549,10 @@
 	rc = request_irq(jme->pdev->irq, handler, irq_flags, netdev->name,
 			  netdev);
 	if (rc) {
-		jeprintk(jme->pdev,
-			"Unable to request %s interrupt (return: %d)\n",
-			test_bit(JME_FLAG_MSI, &jme->flags) ? "MSI" : "INTx",
-			rc);
+		netdev_err(netdev,
+			   "Unable to request %s interrupt (return: %d)\n",
+			   test_bit(JME_FLAG_MSI, &jme->flags) ? "MSI" : "INTx",
+			   rc);
 
 		if (test_bit(JME_FLAG_MSI, &jme->flags)) {
 			pci_disable_msi(jme->pdev);
@@ -1575,6 +1576,16 @@
 	}
 }
 
+static inline void
+jme_phy_on(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);
+}
+
 static int
 jme_open(struct net_device *netdev)
 {
@@ -1595,10 +1606,12 @@
 
 	jme_start_irq(jme);
 
-	if (test_bit(JME_FLAG_SSET, &jme->flags))
+	if (test_bit(JME_FLAG_SSET, &jme->flags)) {
+		jme_phy_on(jme);
 		jme_set_settings(netdev, &jme->old_ecmd);
-	else
+	} else {
 		jme_reset_phy_processor(jme);
+	}
 
 	jme_reset_link(jme);
 
@@ -1834,7 +1847,7 @@
 			*flags |= TXFLAG_UDPCS;
 			break;
 		default:
-			netif_err(jme, tx_err, jme->dev, "Error upper layer protocol.\n");
+			netif_err(jme, tx_err, jme->dev, "Error upper layer protocol\n");
 			break;
 		}
 	}
@@ -1909,12 +1922,12 @@
 	smp_wmb();
 	if (unlikely(atomic_read(&txring->nr_free) < (MAX_SKB_FRAGS+2))) {
 		netif_stop_queue(jme->dev);
-		netif_info(jme, tx_queued, jme->dev, "TX Queue Paused.\n");
+		netif_info(jme, tx_queued, jme->dev, "TX Queue Paused\n");
 		smp_wmb();
 		if (atomic_read(&txring->nr_free)
 			>= (jme->tx_wake_threshold)) {
 			netif_wake_queue(jme->dev);
-			netif_info(jme, tx_queued, jme->dev, "TX Queue Fast Waked.\n");
+			netif_info(jme, tx_queued, jme->dev, "TX Queue Fast Waked\n");
 		}
 	}
 
@@ -1922,7 +1935,8 @@
 			(jiffies - txbi->start_xmit) >= TX_TIMEOUT &&
 			txbi->skb)) {
 		netif_stop_queue(jme->dev);
-		netif_info(jme, tx_queued, jme->dev, "TX Queue Stopped %d@%lu.\n", idx, jiffies);
+		netif_info(jme, tx_queued, jme->dev,
+			   "TX Queue Stopped %d@%lu\n", idx, jiffies);
 	}
 }
 
@@ -1945,7 +1959,8 @@
 
 	if (unlikely(idx < 0)) {
 		netif_stop_queue(netdev);
-		netif_err(jme, tx_err, jme->dev, "BUG! Tx ring full when queue awake!\n");
+		netif_err(jme, tx_err, jme->dev,
+			  "BUG! Tx ring full when queue awake!\n");
 
 		return NETDEV_TX_BUSY;
 	}
@@ -1957,9 +1972,8 @@
 				TXCS_QUEUE0S |
 				TXCS_ENABLE);
 
-	tx_dbg(jme, "xmit: %d+%d@%lu\n", idx,
-			skb_shinfo(skb)->nr_frags + 2,
-			jiffies);
+	tx_dbg(jme, "xmit: %d+%d@%lu\n",
+	       idx, skb_shinfo(skb)->nr_frags + 2, jiffies);
 	jme_stop_queue_if_full(jme);
 
 	return NETDEV_TX_OK;
@@ -2382,6 +2396,10 @@
 	if (ecmd->speed == SPEED_1000 && ecmd->autoneg != AUTONEG_ENABLE)
 		return -EINVAL;
 
+	/*
+	 * Check If user changed duplex only while force_media.
+	 * Hardware would not generate link change interrupt.
+	 */
 	if (jme->mii_if.force_media &&
 	ecmd->autoneg != AUTONEG_ENABLE &&
 	(jme->mii_if.full_duplex != ecmd->duplex))
@@ -2391,12 +2409,40 @@
 	rc = mii_ethtool_sset(&(jme->mii_if), ecmd);
 	spin_unlock_bh(&jme->phy_lock);
 
-	if (!rc && fdc)
-		jme_reset_link(jme);
-
 	if (!rc) {
-		set_bit(JME_FLAG_SSET, &jme->flags);
+		if (fdc)
+			jme_reset_link(jme);
 		jme->old_ecmd = *ecmd;
+		set_bit(JME_FLAG_SSET, &jme->flags);
+	}
+
+	return rc;
+}
+
+static int
+jme_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+	int rc;
+	struct jme_adapter *jme = netdev_priv(netdev);
+	struct mii_ioctl_data *mii_data = if_mii(rq);
+	unsigned int duplex_chg;
+
+	if (cmd == SIOCSMIIREG) {
+		u16 val = mii_data->val_in;
+		if (!(val & (BMCR_RESET|BMCR_ANENABLE)) &&
+		    (val & BMCR_SPEED1000))
+			return -EINVAL;
+	}
+
+	spin_lock_bh(&jme->phy_lock);
+	rc = generic_mii_ioctl(&jme->mii_if, mii_data, cmd, &duplex_chg);
+	spin_unlock_bh(&jme->phy_lock);
+
+	if (!rc && (cmd == SIOCSMIIREG)) {
+		if (duplex_chg)
+			jme_reset_link(jme);
+		jme_get_settings(netdev, &jme->old_ecmd);
+		set_bit(JME_FLAG_SSET, &jme->flags);
 	}
 
 	return rc;
@@ -2501,7 +2547,7 @@
 		val = jread32(jme, JME_SMBCSR);
 	}
 	if (!to) {
-		netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n");
+		netif_err(jme, hw, jme->dev, "SMB Bus Busy\n");
 		return 0xFF;
 	}
 
@@ -2517,7 +2563,7 @@
 		val = jread32(jme, JME_SMBINTF);
 	}
 	if (!to) {
-		netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n");
+		netif_err(jme, hw, jme->dev, "SMB Bus Busy\n");
 		return 0xFF;
 	}
 
@@ -2537,7 +2583,7 @@
 		val = jread32(jme, JME_SMBCSR);
 	}
 	if (!to) {
-		netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n");
+		netif_err(jme, hw, jme->dev, "SMB Bus Busy\n");
 		return;
 	}
 
@@ -2554,7 +2600,7 @@
 		val = jread32(jme, JME_SMBINTF);
 	}
 	if (!to) {
-		netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n");
+		netif_err(jme, hw, jme->dev, "SMB Bus Busy\n");
 		return;
 	}
 
@@ -2676,6 +2722,7 @@
 	.ndo_open		= jme_open,
 	.ndo_stop		= jme_close,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_do_ioctl		= jme_ioctl,
 	.ndo_start_xmit		= jme_start_xmit,
 	.ndo_set_mac_address	= jme_set_macaddr,
 	.ndo_set_multicast_list	= jme_set_multi,
@@ -2699,26 +2746,26 @@
 	 */
 	rc = pci_enable_device(pdev);
 	if (rc) {
-		jeprintk(pdev, "Cannot enable PCI device.\n");
+		pr_err("Cannot enable PCI device\n");
 		goto err_out;
 	}
 
 	using_dac = jme_pci_dma64(pdev);
 	if (using_dac < 0) {
-		jeprintk(pdev, "Cannot set PCI DMA Mask.\n");
+		pr_err("Cannot set PCI DMA Mask\n");
 		rc = -EIO;
 		goto err_out_disable_pdev;
 	}
 
 	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-		jeprintk(pdev, "No PCI resource region found.\n");
+		pr_err("No PCI resource region found\n");
 		rc = -ENOMEM;
 		goto err_out_disable_pdev;
 	}
 
 	rc = pci_request_regions(pdev, DRV_NAME);
 	if (rc) {
-		jeprintk(pdev, "Cannot obtain PCI resource region.\n");
+		pr_err("Cannot obtain PCI resource region\n");
 		goto err_out_disable_pdev;
 	}
 
@@ -2729,7 +2776,7 @@
 	 */
 	netdev = alloc_etherdev(sizeof(*jme));
 	if (!netdev) {
-		jeprintk(pdev, "Cannot allocate netdev structure.\n");
+		pr_err("Cannot allocate netdev structure\n");
 		rc = -ENOMEM;
 		goto err_out_release_regions;
 	}
@@ -2767,7 +2814,7 @@
 	jme->regs = ioremap(pci_resource_start(pdev, 0),
 			     pci_resource_len(pdev, 0));
 	if (!(jme->regs)) {
-		jeprintk(pdev, "Mapping PCI resource region error.\n");
+		pr_err("Mapping PCI resource region error\n");
 		rc = -ENOMEM;
 		goto err_out_free_netdev;
 	}
@@ -2855,8 +2902,8 @@
 
 		if (!jme->mii_if.phy_id) {
 			rc = -EIO;
-			jeprintk(pdev, "Can not find phy_id.\n");
-			 goto err_out_unmap;
+			pr_err("Can not find phy_id\n");
+			goto err_out_unmap;
 		}
 
 		jme->reg_ghc |= GHC_LINK_POLL;
@@ -2867,6 +2914,8 @@
 		jme->mii_if.supports_gmii = true;
 	else
 		jme->mii_if.supports_gmii = false;
+	jme->mii_if.phy_id_mask = 0x1F;
+	jme->mii_if.reg_num_mask = 0x1F;
 	jme->mii_if.mdio_read = jme_mdio_read;
 	jme->mii_if.mdio_write = jme_mdio_write;
 
@@ -2883,8 +2932,7 @@
 	jme_reset_mac_processor(jme);
 	rc = jme_reload_eeprom(jme);
 	if (rc) {
-		jeprintk(pdev,
-			"Reload eeprom for reading MAC Address error.\n");
+		pr_err("Reload eeprom for reading MAC Address error\n");
 		goto err_out_unmap;
 	}
 	jme_load_macaddr(netdev);
@@ -2900,7 +2948,7 @@
 	 */
 	rc = register_netdev(netdev);
 	if (rc) {
-		jeprintk(pdev, "Cannot register net device.\n");
+		pr_err("Cannot register net device\n");
 		goto err_out_unmap;
 	}
 
@@ -3006,10 +3054,12 @@
 	jme_clear_pm(jme);
 	pci_restore_state(pdev);
 
-	if (test_bit(JME_FLAG_SSET, &jme->flags))
+	if (test_bit(JME_FLAG_SSET, &jme->flags)) {
+		jme_phy_on(jme);
 		jme_set_settings(netdev, &jme->old_ecmd);
-	else
+	} else {
 		jme_reset_phy_processor(jme);
+	}
 
 	jme_start_irq(jme);
 	netif_device_attach(netdev);
@@ -3042,8 +3092,7 @@
 static int __init
 jme_init_module(void)
 {
-	printk(KERN_INFO PFX "JMicron JMC2XX ethernet "
-	       "driver version %s\n", DRV_VERSION);
+	pr_info("JMicron JMC2XX ethernet driver version %s\n", DRV_VERSION);
 	return pci_register_driver(&jme_driver);
 }
 
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index 07ad3a4..eac0926 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -3,6 +3,7 @@
  *
  * Copyright 2008 JMicron Technology Corporation
  * http://www.jmicron.com/
+ * Copyright (c) 2009 - 2010 Guo-Fu Tseng <cooldavid@cooldavid.org>
  *
  * Author: Guo-Fu Tseng <cooldavid@cooldavid.org>
  *
@@ -25,7 +26,7 @@
 #define __JME_H_INCLUDED__
 
 #define DRV_NAME	"jme"
-#define DRV_VERSION	"1.0.6"
+#define DRV_VERSION	"1.0.7"
 #define PFX		DRV_NAME ": "
 
 #define PCI_DEVICE_ID_JMICRON_JMC250	0x0250
@@ -41,9 +42,6 @@
 	NETIF_MSG_TX_ERR | \
 	NETIF_MSG_HW)
 
-#define jeprintk(pdev, fmt, args...) \
-	printk(KERN_ERR PFX fmt, ## args)
-
 #ifdef TX_DEBUG
 #define tx_dbg(priv, fmt, args...)					\
 	printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ##args)
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index 87f0a93..9f8e702 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -495,7 +495,7 @@
 	lp->options |= options;
 	mutex_unlock(&lp->indirect_mutex);
 
-	return (0);
+	return 0;
 }
 
 /* Initialize temac */
@@ -761,7 +761,7 @@
 		skb_put(skb, length);
 		skb->dev = ndev;
 		skb->protocol = eth_type_trans(skb, ndev);
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 
 		/* if we're doing rx csum offload, set it up */
 		if (((lp->temac_features & TEMAC_FEATURE_RX_CSUM) != 0) &&
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 9a09967..2d9663a 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -64,7 +64,6 @@
 	u64			packets;
 	u64			bytes;
 	struct u64_stats_sync	syncp;
-	unsigned long		drops;
 };
 
 /*
@@ -74,7 +73,6 @@
 static netdev_tx_t loopback_xmit(struct sk_buff *skb,
 				 struct net_device *dev)
 {
-	struct pcpu_lstats __percpu *pcpu_lstats;
 	struct pcpu_lstats *lb_stats;
 	int len;
 
@@ -83,8 +81,7 @@
 	skb->protocol = eth_type_trans(skb, dev);
 
 	/* it's OK to use per_cpu_ptr() because BHs are off */
-	pcpu_lstats = (void __percpu __force *)dev->ml_priv;
-	lb_stats = this_cpu_ptr(pcpu_lstats);
+	lb_stats = this_cpu_ptr(dev->lstats);
 
 	len = skb->len;
 	if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
@@ -92,8 +89,7 @@
 		lb_stats->bytes += len;
 		lb_stats->packets++;
 		u64_stats_update_end(&lb_stats->syncp);
-	} else
-		lb_stats->drops++;
+	}
 
 	return NETDEV_TX_OK;
 }
@@ -101,32 +97,26 @@
 static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev,
 						      struct rtnl_link_stats64 *stats)
 {
-	const struct pcpu_lstats __percpu *pcpu_lstats;
 	u64 bytes = 0;
 	u64 packets = 0;
-	u64 drops = 0;
 	int i;
 
-	pcpu_lstats = (void __percpu __force *)dev->ml_priv;
 	for_each_possible_cpu(i) {
 		const struct pcpu_lstats *lb_stats;
 		u64 tbytes, tpackets;
 		unsigned int start;
 
-		lb_stats = per_cpu_ptr(pcpu_lstats, i);
+		lb_stats = per_cpu_ptr(dev->lstats, i);
 		do {
 			start = u64_stats_fetch_begin(&lb_stats->syncp);
 			tbytes = lb_stats->bytes;
 			tpackets = lb_stats->packets;
 		} while (u64_stats_fetch_retry(&lb_stats->syncp, start));
-		drops   += lb_stats->drops;
 		bytes   += tbytes;
 		packets += tpackets;
 	}
 	stats->rx_packets = packets;
 	stats->tx_packets = packets;
-	stats->rx_dropped = drops;
-	stats->rx_errors  = drops;
 	stats->rx_bytes   = bytes;
 	stats->tx_bytes   = bytes;
 	return stats;
@@ -147,22 +137,16 @@
 
 static int loopback_dev_init(struct net_device *dev)
 {
-	struct pcpu_lstats __percpu *lstats;
-
-	lstats = alloc_percpu(struct pcpu_lstats);
-	if (!lstats)
+	dev->lstats = alloc_percpu(struct pcpu_lstats);
+	if (!dev->lstats)
 		return -ENOMEM;
 
-	dev->ml_priv = (void __force *)lstats;
 	return 0;
 }
 
 static void loopback_dev_free(struct net_device *dev)
 {
-	struct pcpu_lstats __percpu *lstats =
-		(void __percpu __force *)dev->ml_priv;
-
-	free_percpu(lstats);
+	free_percpu(dev->lstats);
 	free_netdev(dev);
 }
 
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index 3df046a..3698824 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -460,7 +460,7 @@
 	}
 	lp->rbd_tail->next = rfd->rbd;
 #endif
-	return (i);
+	return i;
 }
 
 static inline void
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c
index 3832fa4..f84f5e6 100644
--- a/drivers/net/mac8390.c
+++ b/drivers/net/mac8390.c
@@ -562,19 +562,19 @@
 
 		case ACCESS_16:
 			/* 16 bit card, register map is reversed */
-			ei_status.reset_8390 = &mac8390_no_reset;
-			ei_status.block_input = &slow_sane_block_input;
-			ei_status.block_output = &slow_sane_block_output;
-			ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+			ei_status.reset_8390 = mac8390_no_reset;
+			ei_status.block_input = slow_sane_block_input;
+			ei_status.block_output = slow_sane_block_output;
+			ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
 			ei_status.reg_offset = back4_offsets;
 			break;
 
 		case ACCESS_32:
 			/* 32 bit card, register map is reversed */
-			ei_status.reset_8390 = &mac8390_no_reset;
-			ei_status.block_input = &sane_block_input;
-			ei_status.block_output = &sane_block_output;
-			ei_status.get_8390_hdr = &sane_get_8390_hdr;
+			ei_status.reset_8390 = mac8390_no_reset;
+			ei_status.block_input = sane_block_input;
+			ei_status.block_output = sane_block_output;
+			ei_status.get_8390_hdr = sane_get_8390_hdr;
 			ei_status.reg_offset = back4_offsets;
 			access_bitmode = 1;
 			break;
@@ -586,19 +586,19 @@
 		 * but overwrite system memory when run at 32 bit.
 		 * so we run them all at 16 bit.
 		 */
-		ei_status.reset_8390 = &mac8390_no_reset;
-		ei_status.block_input = &slow_sane_block_input;
-		ei_status.block_output = &slow_sane_block_output;
-		ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+		ei_status.reset_8390 = mac8390_no_reset;
+		ei_status.block_input = slow_sane_block_input;
+		ei_status.block_output = slow_sane_block_output;
+		ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
 		ei_status.reg_offset = back4_offsets;
 		break;
 
 	case MAC8390_CABLETRON:
 		/* 16 bit card, register map is short forward */
-		ei_status.reset_8390 = &mac8390_no_reset;
-		ei_status.block_input = &slow_sane_block_input;
-		ei_status.block_output = &slow_sane_block_output;
-		ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+		ei_status.reset_8390 = mac8390_no_reset;
+		ei_status.block_input = slow_sane_block_input;
+		ei_status.block_output = slow_sane_block_output;
+		ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
 		ei_status.reg_offset = fwrd2_offsets;
 		break;
 
@@ -606,19 +606,19 @@
 	case MAC8390_KINETICS:
 		/* 16 bit memory, register map is forward */
 		/* dayna and similar */
-		ei_status.reset_8390 = &mac8390_no_reset;
-		ei_status.block_input = &dayna_block_input;
-		ei_status.block_output = &dayna_block_output;
-		ei_status.get_8390_hdr = &dayna_get_8390_hdr;
+		ei_status.reset_8390 = mac8390_no_reset;
+		ei_status.block_input = dayna_block_input;
+		ei_status.block_output = dayna_block_output;
+		ei_status.get_8390_hdr = dayna_get_8390_hdr;
 		ei_status.reg_offset = fwrd4_offsets;
 		break;
 
 	case MAC8390_INTERLAN:
 		/* 16 bit memory, register map is forward */
-		ei_status.reset_8390 = &interlan_reset;
-		ei_status.block_input = &slow_sane_block_input;
-		ei_status.block_output = &slow_sane_block_output;
-		ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+		ei_status.reset_8390 = interlan_reset;
+		ei_status.block_input = slow_sane_block_input;
+		ei_status.block_output = slow_sane_block_output;
+		ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
 		ei_status.reg_offset = fwrd4_offsets;
 		break;
 
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index ff2f158..4297f6e 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -407,7 +407,7 @@
 	}
 
 	skb_reserve(skb, RX_OFFSET);
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 	skb_put(skb, len);
 
 	for (frag = first_frag; ; frag = NEXT_RX(frag)) {
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 0ef0eb0..0fc9dc7 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -788,6 +788,10 @@
 		}
 		break;
 	case NETDEV_UNREGISTER:
+		/* twiddle thumbs on netns device moves */
+		if (dev->reg_state != NETREG_UNREGISTERING)
+			break;
+
 		list_for_each_entry_safe(vlan, next, &port->vlans, list)
 			vlan->dev->rtnl_link_ops->dellink(vlan->dev, NULL);
 		break;
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 3b1c54a..4256727 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -84,26 +84,45 @@
 static DEFINE_SPINLOCK(macvtap_lock);
 
 /*
- * Choose the next free queue, for now there is only one
+ * get_slot: return a [unused/occupied] slot in vlan->taps[]:
+ *	- if 'q' is NULL, return the first empty slot;
+ *	- otherwise, return the slot this pointer occupies.
  */
+static int get_slot(struct macvlan_dev *vlan, struct macvtap_queue *q)
+{
+	int i;
+
+	for (i = 0; i < MAX_MACVTAP_QUEUES; i++) {
+		if (rcu_dereference(vlan->taps[i]) == q)
+			return i;
+	}
+
+	/* Should never happen */
+	BUG_ON(1);
+}
+
 static int macvtap_set_queue(struct net_device *dev, struct file *file,
 				struct macvtap_queue *q)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
+	int index;
 	int err = -EBUSY;
 
 	spin_lock(&macvtap_lock);
-	if (rcu_dereference(vlan->tap))
+	if (vlan->numvtaps == MAX_MACVTAP_QUEUES)
 		goto out;
 
 	err = 0;
+	index = get_slot(vlan, NULL);
 	rcu_assign_pointer(q->vlan, vlan);
-	rcu_assign_pointer(vlan->tap, q);
+	rcu_assign_pointer(vlan->taps[index], q);
 	sock_hold(&q->sk);
 
 	q->file = file;
 	file->private_data = q;
 
+	vlan->numvtaps++;
+
 out:
 	spin_unlock(&macvtap_lock);
 	return err;
@@ -124,9 +143,12 @@
 	spin_lock(&macvtap_lock);
 	vlan = rcu_dereference(q->vlan);
 	if (vlan) {
-		rcu_assign_pointer(vlan->tap, NULL);
+		int index = get_slot(vlan, q);
+
+		rcu_assign_pointer(vlan->taps[index], NULL);
 		rcu_assign_pointer(q->vlan, NULL);
 		sock_put(&q->sk);
+		--vlan->numvtaps;
 	}
 
 	spin_unlock(&macvtap_lock);
@@ -136,39 +158,82 @@
 }
 
 /*
- * Since we only support one queue, just dereference the pointer.
+ * Select a queue based on the rxq of the device on which this packet
+ * arrived. If the incoming device is not mq, calculate a flow hash
+ * to select a queue. If all fails, find the first available queue.
+ * Cache vlan->numvtaps since it can become zero during the execution
+ * of this function.
  */
 static struct macvtap_queue *macvtap_get_queue(struct net_device *dev,
 					       struct sk_buff *skb)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
+	struct macvtap_queue *tap = NULL;
+	int numvtaps = vlan->numvtaps;
+	__u32 rxq;
 
-	return rcu_dereference(vlan->tap);
+	if (!numvtaps)
+		goto out;
+
+	if (likely(skb_rx_queue_recorded(skb))) {
+		rxq = skb_get_rx_queue(skb);
+
+		while (unlikely(rxq >= numvtaps))
+			rxq -= numvtaps;
+
+		tap = rcu_dereference(vlan->taps[rxq]);
+		if (tap)
+			goto out;
+	}
+
+	/* Check if we can use flow to select a queue */
+	rxq = skb_get_rxhash(skb);
+	if (rxq) {
+		tap = rcu_dereference(vlan->taps[rxq % numvtaps]);
+		if (tap)
+			goto out;
+	}
+
+	/* Everything failed - find first available queue */
+	for (rxq = 0; rxq < MAX_MACVTAP_QUEUES; rxq++) {
+		tap = rcu_dereference(vlan->taps[rxq]);
+		if (tap)
+			break;
+	}
+
+out:
+	return tap;
 }
 
 /*
  * The net_device is going away, give up the reference
- * that it holds on the queue (all the queues one day)
- * and safely set the pointer from the queues to NULL.
+ * that it holds on all queues and safely set the pointer
+ * from the queues to NULL.
  */
 static void macvtap_del_queues(struct net_device *dev)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
-	struct macvtap_queue *q;
+	struct macvtap_queue *q, *qlist[MAX_MACVTAP_QUEUES];
+	int i, j = 0;
 
+	/* macvtap_put_queue can free some slots, so go through all slots */
 	spin_lock(&macvtap_lock);
-	q = rcu_dereference(vlan->tap);
-	if (!q) {
-		spin_unlock(&macvtap_lock);
-		return;
+	for (i = 0; i < MAX_MACVTAP_QUEUES && vlan->numvtaps; i++) {
+		q = rcu_dereference(vlan->taps[i]);
+		if (q) {
+			qlist[j++] = q;
+			rcu_assign_pointer(vlan->taps[i], NULL);
+			rcu_assign_pointer(q->vlan, NULL);
+			vlan->numvtaps--;
+		}
 	}
-
-	rcu_assign_pointer(vlan->tap, NULL);
-	rcu_assign_pointer(q->vlan, NULL);
+	BUG_ON(vlan->numvtaps != 0);
 	spin_unlock(&macvtap_lock);
 
 	synchronize_rcu();
-	sock_put(&q->sk);
+
+	for (--j; j >= 0; j--)
+		sock_put(&qlist[j]->sk);
 }
 
 /*
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index 42e3294..60135aa 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -461,7 +461,7 @@
 {
 	struct meth_private *priv = netdev_priv(dev);
 
-	return (priv->tx_count >= TX_RING_ENTRIES - 1);
+	return priv->tx_count >= TX_RING_ENTRIES - 1;
 }
 
 static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status)
diff --git a/drivers/net/mlx4/Makefile b/drivers/net/mlx4/Makefile
index 1fd068e..d1aa45a 100644
--- a/drivers/net/mlx4/Makefile
+++ b/drivers/net/mlx4/Makefile
@@ -6,4 +6,4 @@
 obj-$(CONFIG_MLX4_EN)               += mlx4_en.o
 
 mlx4_en-y := 	en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \
-		en_resources.o en_netdev.o
+		en_resources.o en_netdev.o en_selftest.o
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index 8c85156..8f4bf1f 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -74,7 +74,7 @@
 
 u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align)
 {
-	u32 obj, i;
+	u32 obj;
 
 	if (likely(cnt == 1 && align == 1))
 		return mlx4_bitmap_alloc(bitmap);
@@ -91,8 +91,7 @@
 	}
 
 	if (obj < bitmap->max) {
-		for (i = 0; i < cnt; i++)
-			set_bit(obj + i, bitmap->table);
+		bitmap_set(bitmap->table, obj, cnt);
 		if (obj == bitmap->last) {
 			bitmap->last = (obj + cnt);
 			if (bitmap->last >= bitmap->max)
@@ -109,13 +108,10 @@
 
 void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
 {
-	u32 i;
-
 	obj &= bitmap->max + bitmap->reserved_top - 1;
 
 	spin_lock(&bitmap->lock);
-	for (i = 0; i < cnt; i++)
-		clear_bit(obj + i, bitmap->table);
+	bitmap_clear(bitmap->table, obj, cnt);
 	bitmap->last = min(bitmap->last, obj);
 	bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
 			& bitmap->mask;
@@ -125,8 +121,6 @@
 int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
 		     u32 reserved_bot, u32 reserved_top)
 {
-	int i;
-
 	/* num must be a power of 2 */
 	if (num != roundup_pow_of_two(num))
 		return -EINVAL;
@@ -142,8 +136,7 @@
 	if (!bitmap->table)
 		return -ENOMEM;
 
-	for (i = 0; i < reserved_bot; ++i)
-		set_bit(i, bitmap->table);
+	bitmap_set(bitmap->table, 0, reserved_bot);
 
 	return 0;
 }
@@ -188,7 +181,7 @@
 		buf->nbufs       = (size + PAGE_SIZE - 1) / PAGE_SIZE;
 		buf->npages      = buf->nbufs;
 		buf->page_shift  = PAGE_SHIFT;
-		buf->page_list   = kzalloc(buf->nbufs * sizeof *buf->page_list,
+		buf->page_list   = kcalloc(buf->nbufs, sizeof(*buf->page_list),
 					   GFP_KERNEL);
 		if (!buf->page_list)
 			return -ENOMEM;
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index b275238..056152b 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -39,21 +39,6 @@
 #include "en_port.h"
 
 
-static void mlx4_en_update_lro_stats(struct mlx4_en_priv *priv)
-{
-	int i;
-
-	priv->port_stats.lro_aggregated = 0;
-	priv->port_stats.lro_flushed = 0;
-	priv->port_stats.lro_no_desc = 0;
-
-	for (i = 0; i < priv->rx_ring_num; i++) {
-		priv->port_stats.lro_aggregated += priv->rx_ring[i].lro.stats.aggregated;
-		priv->port_stats.lro_flushed += priv->rx_ring[i].lro.stats.flushed;
-		priv->port_stats.lro_no_desc += priv->rx_ring[i].lro.stats.no_desc;
-	}
-}
-
 static void
 mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
 {
@@ -112,7 +97,7 @@
 	"tx_heartbeat_errors", "tx_window_errors",
 
 	/* port statistics */
-	"lro_aggregated", "lro_flushed", "lro_no_desc", "tso_packets",
+	"tso_packets",
 	"queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed",
 	"rx_csum_good", "rx_csum_none", "tx_chksum_offload",
 
@@ -125,6 +110,14 @@
 #define NUM_MAIN_STATS	21
 #define NUM_ALL_STATS	(NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS)
 
+static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
+	"Interupt Test",
+	"Link Test",
+	"Speed Test",
+	"Register Test",
+	"Loopback Test",
+};
+
 static u32 mlx4_en_get_msglevel(struct net_device *dev)
 {
 	return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable;
@@ -146,10 +139,15 @@
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 
-	if (sset != ETH_SS_STATS)
+	switch (sset) {
+	case ETH_SS_STATS:
+		return NUM_ALL_STATS +
+			(priv->tx_ring_num + priv->rx_ring_num) * 2;
+	case ETH_SS_TEST:
+		return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.loopback_support) * 2;
+	default:
 		return -EOPNOTSUPP;
-
-	return NUM_ALL_STATS + (priv->tx_ring_num + priv->rx_ring_num) * 2;
+	}
 }
 
 static void mlx4_en_get_ethtool_stats(struct net_device *dev,
@@ -161,8 +159,6 @@
 
 	spin_lock_bh(&priv->stats_lock);
 
-	mlx4_en_update_lro_stats(priv);
-
 	for (i = 0; i < NUM_MAIN_STATS; i++)
 		data[index++] = ((unsigned long *) &priv->stats)[i];
 	for (i = 0; i < NUM_PORT_STATS; i++)
@@ -181,6 +177,12 @@
 
 }
 
+static void mlx4_en_self_test(struct net_device *dev,
+			      struct ethtool_test *etest, u64 *buf)
+{
+	mlx4_en_ex_selftest(dev, &etest->flags, buf);
+}
+
 static void mlx4_en_get_strings(struct net_device *dev,
 				uint32_t stringset, uint8_t *data)
 {
@@ -188,44 +190,76 @@
 	int index = 0;
 	int i;
 
-	if (stringset != ETH_SS_STATS)
-		return;
+	switch (stringset) {
+	case ETH_SS_TEST:
+		for (i = 0; i < MLX4_EN_NUM_SELF_TEST - 2; i++)
+			strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
+		if (priv->mdev->dev->caps.loopback_support)
+			for (; i < MLX4_EN_NUM_SELF_TEST; i++)
+				strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
+		break;
 
-	/* Add main counters */
-	for (i = 0; i < NUM_MAIN_STATS; i++)
-		strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
-	for (i = 0; i < NUM_PORT_STATS; i++)
-		strcpy(data + (index++) * ETH_GSTRING_LEN,
+	case ETH_SS_STATS:
+		/* Add main counters */
+		for (i = 0; i < NUM_MAIN_STATS; i++)
+			strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
+		for (i = 0; i< NUM_PORT_STATS; i++)
+			strcpy(data + (index++) * ETH_GSTRING_LEN,
 			main_strings[i + NUM_MAIN_STATS]);
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		sprintf(data + (index++) * ETH_GSTRING_LEN,
-			"tx%d_packets", i);
-		sprintf(data + (index++) * ETH_GSTRING_LEN,
-			"tx%d_bytes", i);
-	}
-	for (i = 0; i < priv->rx_ring_num; i++) {
-		sprintf(data + (index++) * ETH_GSTRING_LEN,
-			"rx%d_packets", i);
-		sprintf(data + (index++) * ETH_GSTRING_LEN,
-			"rx%d_bytes", i);
-	}
-	for (i = 0; i < NUM_PKT_STATS; i++)
-		strcpy(data + (index++) * ETH_GSTRING_LEN,
+		for (i = 0; i < priv->tx_ring_num; i++) {
+			sprintf(data + (index++) * ETH_GSTRING_LEN,
+				"tx%d_packets", i);
+			sprintf(data + (index++) * ETH_GSTRING_LEN,
+				"tx%d_bytes", i);
+		}
+		for (i = 0; i < priv->rx_ring_num; i++) {
+			sprintf(data + (index++) * ETH_GSTRING_LEN,
+				"rx%d_packets", i);
+			sprintf(data + (index++) * ETH_GSTRING_LEN,
+				"rx%d_bytes", i);
+		}
+		for (i = 0; i< NUM_PKT_STATS; i++)
+			strcpy(data + (index++) * ETH_GSTRING_LEN,
 			main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]);
+		break;
+	}
 }
 
 static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	int trans_type;
+
 	cmd->autoneg = AUTONEG_DISABLE;
 	cmd->supported = SUPPORTED_10000baseT_Full;
-	cmd->advertising = ADVERTISED_1000baseT_Full;
+	cmd->advertising = ADVERTISED_10000baseT_Full;
+
+	if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
+		return -ENOMEM;
+
+	trans_type = priv->port_state.transciver;
 	if (netif_carrier_ok(dev)) {
-		cmd->speed = SPEED_10000;
+		cmd->speed = priv->port_state.link_speed;
 		cmd->duplex = DUPLEX_FULL;
 	} else {
 		cmd->speed = -1;
 		cmd->duplex = -1;
 	}
+
+	if (trans_type > 0 && trans_type <= 0xC) {
+		cmd->port = PORT_FIBRE;
+		cmd->transceiver = XCVR_EXTERNAL;
+		cmd->supported |= SUPPORTED_FIBRE;
+		cmd->advertising |= ADVERTISED_FIBRE;
+	} else if (trans_type == 0x80 || trans_type == 0) {
+		cmd->port = PORT_TP;
+		cmd->transceiver = XCVR_INTERNAL;
+		cmd->supported |= SUPPORTED_TP;
+		cmd->advertising |= ADVERTISED_TP;
+	} else  {
+		cmd->port = -1;
+		cmd->transceiver = -1;
+	}
 	return 0;
 }
 
@@ -343,8 +377,9 @@
 	tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
 	tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
 
-	if (rx_size == priv->prof->rx_ring_size &&
-	    tx_size == priv->prof->tx_ring_size)
+	if (rx_size == (priv->port_up ? priv->rx_ring[0].actual_size :
+					priv->rx_ring[0].size) &&
+	    tx_size == priv->tx_ring[0].size)
 		return 0;
 
 	mutex_lock(&mdev->state_lock);
@@ -378,49 +413,13 @@
 				  struct ethtool_ringparam *param)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_en_dev *mdev = priv->mdev;
 
 	memset(param, 0, sizeof(*param));
 	param->rx_max_pending = MLX4_EN_MAX_RX_SIZE;
 	param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
-	param->rx_pending = mdev->profile.prof[priv->port].rx_ring_size;
-	param->tx_pending = mdev->profile.prof[priv->port].tx_ring_size;
-}
-
-static int mlx4_ethtool_op_set_flags(struct net_device *dev, u32 data)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_en_dev *mdev = priv->mdev;
-	int rc = 0;
-	int changed = 0;
-
-	if (data & ~ETH_FLAG_LRO)
-		return -EOPNOTSUPP;
-
-	if (data & ETH_FLAG_LRO) {
-		if (mdev->profile.num_lro == 0)
-			return -EOPNOTSUPP;
-		if (!(dev->features & NETIF_F_LRO))
-			changed = 1;
-	} else if (dev->features & NETIF_F_LRO) {
-		changed = 1;
-	}
-
-	if (changed) {
-		if (netif_running(dev)) {
-			mutex_lock(&mdev->state_lock);
-			mlx4_en_stop_port(dev);
-		}
-		dev->features ^= NETIF_F_LRO;
-		if (netif_running(dev)) {
-			rc = mlx4_en_start_port(dev);
-			if (rc)
-				en_err(priv, "Failed to restart port\n");
-			mutex_unlock(&mdev->state_lock);
-		}
-	}
-
-	return rc;
+	param->rx_pending = priv->port_up ?
+		priv->rx_ring[0].actual_size : priv->rx_ring[0].size;
+	param->tx_pending = priv->tx_ring[0].size;
 }
 
 const struct ethtool_ops mlx4_en_ethtool_ops = {
@@ -441,6 +440,7 @@
 	.get_strings = mlx4_en_get_strings,
 	.get_sset_count = mlx4_en_get_sset_count,
 	.get_ethtool_stats = mlx4_en_get_ethtool_stats,
+	.self_test = mlx4_en_self_test,
 	.get_wol = mlx4_en_get_wol,
 	.get_msglevel = mlx4_en_get_msglevel,
 	.set_msglevel = mlx4_en_set_msglevel,
@@ -451,7 +451,6 @@
 	.get_ringparam = mlx4_en_get_ringparam,
 	.set_ringparam = mlx4_en_set_ringparam,
 	.get_flags = ethtool_op_get_flags,
-	.set_flags = mlx4_ethtool_op_set_flags,
 };
 
 
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 97934f1..1439064 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -63,15 +63,12 @@
  */
 
 
-/* Use a XOR rathern than Toeplitz hash function for RSS */
-MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS");
-
-/* RSS hash type mask - default to <saddr, daddr, sport, dport> */
-MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask");
-
-/* Number of LRO sessions per Rx ring (rounded up to a power of two) */
-MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS,
-		 "Number of LRO sessions per ring or disabled (0)");
+/* Enable RSS TCP traffic */
+MLX4_EN_PARM_INT(tcp_rss, 1,
+		 "Enable RSS for incomming TCP traffic or disabled (0)");
+/* Enable RSS UDP traffic */
+MLX4_EN_PARM_INT(udp_rss, 1,
+		 "Enable RSS for incomming UDP traffic or disabled (0)");
 
 /* Priority pausing */
 MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
@@ -107,9 +104,12 @@
 	struct mlx4_en_profile *params = &mdev->profile;
 	int i;
 
-	params->rss_xor = (rss_xor != 0);
-	params->rss_mask = rss_mask & 0x1f;
-	params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
+	params->tcp_rss = tcp_rss;
+	params->udp_rss = udp_rss;
+	if (params->udp_rss && !mdev->dev->caps.udp_rss) {
+		mlx4_warn(mdev, "UDP RSS is not supported on this device.\n");
+		params->udp_rss = 0;
+	}
 	for (i = 1; i <= MLX4_MAX_PORTS; i++) {
 		params->prof[i].rx_pause = 1;
 		params->prof[i].rx_ppp = pfcrx;
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index a0d8a26..79478bd 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -109,7 +109,7 @@
 	mutex_unlock(&mdev->state_lock);
 }
 
-static u64 mlx4_en_mac_to_u64(u8 *addr)
+u64 mlx4_en_mac_to_u64(u8 *addr)
 {
 	u64 mac = 0;
 	int i;
@@ -513,6 +513,10 @@
 
 		queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
 	}
+	if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) {
+		queue_work(mdev->workqueue, &priv->mac_task);
+		mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0;
+	}
 	mutex_unlock(&mdev->state_lock);
 }
 
@@ -528,10 +532,10 @@
 	 * report to system log */
 	if (priv->last_link_state != linkstate) {
 		if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
-			en_dbg(LINK, priv, "Link Down\n");
+			en_info(priv, "Link Down\n");
 			netif_carrier_off(priv->dev);
 		} else {
-			en_dbg(LINK, priv, "Link Up\n");
+			en_info(priv, "Link Up\n");
 			netif_carrier_on(priv->dev);
 		}
 	}
@@ -653,6 +657,7 @@
 		en_err(priv, "Failed setting port mac\n");
 		goto tx_err;
 	}
+	mdev->mac_removed[priv->port] = 0;
 
 	/* Init port */
 	en_dbg(HW, priv, "Initializing port\n");
@@ -704,12 +709,12 @@
 	netif_tx_stop_all_queues(dev);
 	netif_tx_unlock_bh(dev);
 
-	/* close port*/
+	/* Set port as not active */
 	priv->port_up = false;
-	mlx4_CLOSE_PORT(mdev->dev, priv->port);
 
 	/* Unregister Mac address for the port */
 	mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
+	mdev->mac_removed[priv->port] = 1;
 
 	/* Free TX Rings */
 	for (i = 0; i < priv->tx_ring_num; i++) {
@@ -731,6 +736,9 @@
 			msleep(1);
 		mlx4_en_deactivate_cq(priv, &priv->rx_cq[i]);
 	}
+
+	/* close port*/
+	mlx4_CLOSE_PORT(mdev->dev, priv->port);
 }
 
 static void mlx4_en_restart(struct work_struct *work)
@@ -1017,15 +1025,17 @@
 	 */
 	dev->netdev_ops = &mlx4_netdev_ops;
 	dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
-	dev->real_num_tx_queues = MLX4_EN_NUM_TX_RINGS;
+	netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
+	netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
 
 	SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops);
 
 	/* Set defualt MAC */
 	dev->addr_len = ETH_ALEN;
-	for (i = 0; i < ETH_ALEN; i++)
-		dev->dev_addr[ETH_ALEN - 1 - i] =
-		(u8) (priv->mac >> (8 * i));
+	for (i = 0; i < ETH_ALEN; i++) {
+		dev->dev_addr[ETH_ALEN - 1 - i] = (u8) (priv->mac >> (8 * i));
+		dev->perm_addr[ETH_ALEN - 1 - i] = (u8) (priv->mac >> (8 * i));
+	}
 
 	/*
 	 * Set driver features
@@ -1038,8 +1048,7 @@
 	dev->features |= NETIF_F_HW_VLAN_TX |
 			 NETIF_F_HW_VLAN_RX |
 			 NETIF_F_HW_VLAN_FILTER;
-	if (mdev->profile.num_lro)
-		dev->features |= NETIF_F_LRO;
+	dev->features |= NETIF_F_GRO;
 	if (mdev->LSO_support) {
 		dev->features |= NETIF_F_TSO;
 		dev->features |= NETIF_F_TSO6;
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index a29abe8..aa3ef2a 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -142,6 +142,38 @@
 	return err;
 }
 
+int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
+{
+	struct mlx4_en_query_port_context *qport_context;
+	struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
+	struct mlx4_en_port_state *state = &priv->port_state;
+	struct mlx4_cmd_mailbox *mailbox;
+	int err;
+
+	mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
+	if (IS_ERR(mailbox))
+		return PTR_ERR(mailbox);
+	memset(mailbox->buf, 0, sizeof(*qport_context));
+	err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0,
+			   MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B);
+	if (err)
+		goto out;
+	qport_context = mailbox->buf;
+
+	/* This command is always accessed from Ethtool context
+	 * already synchronized, no need in locking */
+	state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK);
+	if ((qport_context->link_speed & MLX4_EN_SPEED_MASK) ==
+	    MLX4_EN_1G_SPEED)
+		state->link_speed = 1000;
+	else
+		state->link_speed = 10000;
+	state->transciver = qport_context->transceiver;
+
+out:
+	mlx4_free_cmd_mailbox(mdev->dev, mailbox);
+	return err;
+}
 
 int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
 {
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index e6477f1..f6511aa 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -84,6 +84,20 @@
 	MLX4_MCAST_ENABLE       = 2,
 };
 
+struct mlx4_en_query_port_context {
+	u8 link_up;
+#define MLX4_EN_LINK_UP_MASK	0x80
+	u8 reserved;
+	__be16 mtu;
+	u8 reserved2;
+	u8 link_speed;
+#define MLX4_EN_SPEED_MASK	0x3
+#define MLX4_EN_1G_SPEED	0x2
+	u16 reserved3[5];
+	__be64 mac;
+	u8 transceiver;
+};
+
 
 struct mlx4_en_stat_out_mbox {
 	/* Received frames with a length of 64 octets */
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 8e2fcb7..570f250 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -42,18 +42,6 @@
 #include "mlx4_en.h"
 
 
-static int mlx4_en_get_frag_header(struct skb_frag_struct *frags, void **mac_hdr,
-				   void **ip_hdr, void **tcpudp_hdr,
-				   u64 *hdr_flags, void *priv)
-{
-	*mac_hdr = page_address(frags->page) + frags->page_offset;
-	*ip_hdr = *mac_hdr + ETH_HLEN;
-	*tcpudp_hdr = (struct tcphdr *)(*ip_hdr + sizeof(struct iphdr));
-	*hdr_flags = LRO_IPV4 | LRO_TCP;
-
-	return 0;
-}
-
 static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
 			      struct mlx4_en_rx_desc *rx_desc,
 			      struct skb_frag_struct *skb_frags,
@@ -251,7 +239,6 @@
 			ring->prod--;
 			mlx4_en_free_rx_desc(priv, ring, ring->actual_size);
 		}
-		ring->size_mask = ring->actual_size - 1;
 	}
 
 	return 0;
@@ -313,28 +300,8 @@
 	}
 	ring->buf = ring->wqres.buf.direct.buf;
 
-	/* Configure lro mngr */
-	memset(&ring->lro, 0, sizeof(struct net_lro_mgr));
-	ring->lro.dev = priv->dev;
-	ring->lro.features = LRO_F_NAPI;
-	ring->lro.frag_align_pad = NET_IP_ALIGN;
-	ring->lro.ip_summed = CHECKSUM_UNNECESSARY;
-	ring->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY;
-	ring->lro.max_desc = mdev->profile.num_lro;
-	ring->lro.max_aggr = MAX_SKB_FRAGS;
-	ring->lro.lro_arr = kzalloc(mdev->profile.num_lro *
-				    sizeof(struct net_lro_desc),
-				    GFP_KERNEL);
-	if (!ring->lro.lro_arr) {
-		en_err(priv, "Failed to allocate lro array\n");
-		goto err_map;
-	}
-	ring->lro.get_frag_header = mlx4_en_get_frag_header;
-
 	return 0;
 
-err_map:
-	mlx4_en_unmap_buffer(&ring->wqres.buf);
 err_hwq:
 	mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
 err_ring:
@@ -389,6 +356,7 @@
 	for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
 		ring = &priv->rx_ring[ring_ind];
 
+		ring->size_mask = ring->actual_size - 1;
 		mlx4_en_update_rx_prod_db(ring);
 	}
 
@@ -412,7 +380,6 @@
 {
 	struct mlx4_en_dev *mdev = priv->mdev;
 
-	kfree(ring->lro.lro_arr);
 	mlx4_en_unmap_buffer(&ring->wqres.buf);
 	mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE);
 	vfree(ring->rx_info);
@@ -459,7 +426,7 @@
 			goto fail;
 
 		/* Unmap buffer */
-		pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size,
+		pci_unmap_single(mdev->pdev, dma, skb_frags_rx[nr].size,
 				 PCI_DMA_FROMDEVICE);
 	}
 	/* Adjust size of last fragment to match actual length */
@@ -541,6 +508,21 @@
 	return skb;
 }
 
+static void validate_loopback(struct mlx4_en_priv *priv, struct sk_buff *skb)
+{
+	int i;
+	int offset = ETH_HLEN;
+
+	for (i = 0; i < MLX4_LOOPBACK_TEST_PAYLOAD; i++, offset++) {
+		if (*(skb->data + offset) != (unsigned char) (i & 0xff))
+			goto out_loopback;
+	}
+	/* Loopback found */
+	priv->loopback_ok = 1;
+
+out_loopback:
+	dev_kfree_skb_any(skb);
+}
 
 int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
 {
@@ -548,7 +530,6 @@
 	struct mlx4_cqe *cqe;
 	struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
 	struct skb_frag_struct *skb_frags;
-	struct skb_frag_struct lro_frags[MLX4_EN_MAX_RX_FRAGS];
 	struct mlx4_en_rx_desc *rx_desc;
 	struct sk_buff *skb;
 	int index;
@@ -608,37 +589,35 @@
 				 * - TCP/IP (v4)
 				 * - without IP options
 				 * - not an IP fragment */
-				if (mlx4_en_can_lro(cqe->status) &&
-				    dev->features & NETIF_F_LRO) {
+				if (dev->features & NETIF_F_GRO) {
+					struct sk_buff *gro_skb = napi_get_frags(&cq->napi);
+					if (!gro_skb)
+						goto next;
 
 					nr = mlx4_en_complete_rx_desc(
 						priv, rx_desc,
-						skb_frags, lro_frags,
+						skb_frags, skb_shinfo(gro_skb)->frags,
 						ring->page_alloc, length);
 					if (!nr)
 						goto next;
 
+					skb_shinfo(gro_skb)->nr_frags = nr;
+					gro_skb->len = length;
+					gro_skb->data_len = length;
+					gro_skb->truesize += length;
+					gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
+
 					if (priv->vlgrp && (cqe->vlan_my_qpn &
-							    cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK))) {
-						lro_vlan_hwaccel_receive_frags(
-						       &ring->lro, lro_frags,
-						       length, length,
-						       priv->vlgrp,
-						       be16_to_cpu(cqe->sl_vid),
-						       NULL, 0);
-					} else
-						lro_receive_frags(&ring->lro,
-								  lro_frags,
-								  length,
-								  length,
-								  NULL, 0);
+							    cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)))
+						vlan_gro_frags(&cq->napi, priv->vlgrp, be16_to_cpu(cqe->sl_vid));
+					else
+						napi_gro_frags(&cq->napi);
 
 					goto next;
 				}
 
 				/* LRO not possible, complete processing here */
 				ip_summed = CHECKSUM_UNNECESSARY;
-				INC_PERF_COUNTER(priv->pstats.lro_misses);
 			} else {
 				ip_summed = CHECKSUM_NONE;
 				priv->port_stats.rx_chksum_none++;
@@ -655,6 +634,11 @@
 			goto next;
 		}
 
+                if (unlikely(priv->validate_loopback)) {
+			validate_loopback(priv, skb);
+			goto next;
+		}
+
 		skb->ip_summed = ip_summed;
 		skb->protocol = eth_type_trans(skb, dev);
 		skb_record_rx_queue(skb, cq->ring);
@@ -674,14 +658,10 @@
 		if (++polled == budget) {
 			/* We are here because we reached the NAPI budget -
 			 * flush only pending LRO sessions */
-			lro_flush_all(&ring->lro);
 			goto out;
 		}
 	}
 
-	/* If CQ is empty flush all LRO sessions unconditionally */
-	lro_flush_all(&ring->lro);
-
 out:
 	AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
 	mlx4_cq_set_ci(&cq->mcq);
@@ -816,7 +796,7 @@
 	qp->event = mlx4_en_sqp_event;
 
 	memset(context, 0, sizeof *context);
-	mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 0, 0,
+	mlx4_en_fill_qp_context(priv, ring->actual_size, ring->stride, 0, 0,
 				qpn, ring->cqn, context);
 	context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma);
 
@@ -839,8 +819,7 @@
 	struct mlx4_qp_context context;
 	struct mlx4_en_rss_context *rss_context;
 	void *ptr;
-	int rss_xor = mdev->profile.rss_xor;
-	u8 rss_mask = mdev->profile.rss_mask;
+	u8 rss_mask = 0x3f;
 	int i, qpn;
 	int err = 0;
 	int good_qps = 0;
@@ -886,9 +865,10 @@
 	rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
 					    (rss_map->base_qpn));
 	rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
-	rss_context->hash_fn = rss_xor & 0x3;
-	rss_context->flags = rss_mask << 2;
+	rss_context->flags = rss_mask;
 
+	if (priv->mdev->profile.udp_rss)
+		rss_context->base_qpn_udp = rss_context->default_qpn;
 	err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
 			       &rss_map->indir_qp, &rss_map->indir_state);
 	if (err)
diff --git a/drivers/net/mlx4/en_selftest.c b/drivers/net/mlx4/en_selftest.c
new file mode 100644
index 0000000..9c91a92
--- /dev/null
+++ b/drivers/net/mlx4/en_selftest.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/mlx4/driver.h>
+
+#include "mlx4_en.h"
+
+
+static int mlx4_en_test_registers(struct mlx4_en_priv *priv)
+{
+	return mlx4_cmd(priv->mdev->dev, 0, 0, 0, MLX4_CMD_HW_HEALTH_CHECK,
+			MLX4_CMD_TIME_CLASS_A);
+}
+
+static int mlx4_en_test_loopback_xmit(struct mlx4_en_priv *priv)
+{
+	struct sk_buff *skb;
+	struct ethhdr *ethh;
+	unsigned char *packet;
+	unsigned int packet_size = MLX4_LOOPBACK_TEST_PAYLOAD;
+	unsigned int i;
+	int err;
+
+
+	/* build the pkt before xmit */
+	skb = netdev_alloc_skb(priv->dev, MLX4_LOOPBACK_TEST_PAYLOAD + ETH_HLEN + NET_IP_ALIGN);
+	if (!skb) {
+		en_err(priv, "-LOOPBACK_TEST_XMIT- failed to create skb for xmit\n");
+		return -ENOMEM;
+	}
+	skb_reserve(skb, NET_IP_ALIGN);
+
+	ethh = (struct ethhdr *)skb_put(skb, sizeof(struct ethhdr));
+	packet	= (unsigned char *)skb_put(skb, packet_size);
+	memcpy(ethh->h_dest, priv->dev->dev_addr, ETH_ALEN);
+	memset(ethh->h_source, 0, ETH_ALEN);
+	ethh->h_proto = htons(ETH_P_ARP);
+	skb_set_mac_header(skb, 0);
+	for (i = 0; i < packet_size; ++i)	/* fill our packet */
+		packet[i] = (unsigned char)(i & 0xff);
+
+	/* xmit the pkt */
+	err = mlx4_en_xmit(skb, priv->dev);
+	return err;
+}
+
+static int mlx4_en_test_loopback(struct mlx4_en_priv *priv)
+{
+	u32 loopback_ok = 0;
+	int i;
+
+
+        priv->loopback_ok = 0;
+	priv->validate_loopback = 1;
+
+	/* xmit */
+	if (mlx4_en_test_loopback_xmit(priv)) {
+		en_err(priv, "Transmitting loopback packet failed\n");
+		goto mlx4_en_test_loopback_exit;
+	}
+
+	/* polling for result */
+	for (i = 0; i < MLX4_EN_LOOPBACK_RETRIES; ++i) {
+		msleep(MLX4_EN_LOOPBACK_TIMEOUT);
+		if (priv->loopback_ok) {
+			loopback_ok = 1;
+			break;
+		}
+	}
+	if (!loopback_ok)
+		en_err(priv, "Loopback packet didn't arrive\n");
+
+mlx4_en_test_loopback_exit:
+
+	priv->validate_loopback = 0;
+	return !loopback_ok;
+}
+
+
+static int mlx4_en_test_link(struct mlx4_en_priv *priv)
+{
+	if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
+		return -ENOMEM;
+	if (priv->port_state.link_state == 1)
+		return 0;
+	else
+		return 1;
+}
+
+static int mlx4_en_test_speed(struct mlx4_en_priv *priv)
+{
+
+	if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
+		return -ENOMEM;
+
+	/* The device currently only supports 10G speed */
+	if (priv->port_state.link_speed != SPEED_10000)
+		return priv->port_state.link_speed;
+	return 0;
+}
+
+
+void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	struct mlx4_en_dev *mdev = priv->mdev;
+	struct mlx4_en_tx_ring *tx_ring;
+	int i, carrier_ok;
+
+	memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST);
+
+	if (*flags & ETH_TEST_FL_OFFLINE) {
+		/* disable the interface */
+		carrier_ok = netif_carrier_ok(dev);
+
+		netif_carrier_off(dev);
+retry_tx:
+		/* Wait untill all tx queues are empty.
+		 * there should not be any additional incoming traffic
+		 * since we turned the carrier off */
+		msleep(200);
+		for (i = 0; i < priv->tx_ring_num && carrier_ok; i++) {
+			tx_ring = &priv->tx_ring[i];
+			if (tx_ring->prod != (tx_ring->cons + tx_ring->last_nr_txbb))
+				goto retry_tx;
+		}
+
+		if (priv->mdev->dev->caps.loopback_support){
+			buf[3] = mlx4_en_test_registers(priv);
+			buf[4] = mlx4_en_test_loopback(priv);
+		}
+
+		if (carrier_ok)
+			netif_carrier_on(dev);
+
+	}
+	buf[0] = mlx4_test_interrupts(mdev->dev);
+	buf[1] = mlx4_en_test_link(priv);
+	buf[2] = mlx4_en_test_speed(priv);
+
+	for (i = 0; i < MLX4_EN_NUM_SELF_TEST; i++) {
+		if (buf[i])
+			*flags |= ETH_TEST_FL_FAILED;
+	}
+}
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index 580968f..a680cd4 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -38,6 +38,7 @@
 #include <linux/skbuff.h>
 #include <linux/if_vlan.h>
 #include <linux/vmalloc.h>
+#include <linux/tcp.h>
 
 #include "mlx4_en.h"
 
@@ -582,7 +583,7 @@
 	/* If we support per priority flow control and the packet contains
 	 * a vlan tag, send the packet to the TX ring assigned to that priority
 	 */
-	if (priv->prof->rx_ppp && priv->vlgrp && vlan_tx_tag_present(skb)) {
+	if (priv->prof->rx_ppp && vlan_tx_tag_present(skb)) {
 		vlan_tag = vlan_tx_tag_get(skb);
 		return MLX4_EN_NUM_TX_RINGS + (vlan_tag >> 13);
 	}
@@ -600,6 +601,9 @@
 	struct mlx4_wqe_data_seg *data;
 	struct skb_frag_struct *frag;
 	struct mlx4_en_tx_info *tx_info;
+	struct ethhdr *ethh;
+	u64 mac;
+	u32 mac_l, mac_h;
 	int tx_ind = 0;
 	int nr_txbb;
 	int desc_size;
@@ -612,6 +616,9 @@
 	int lso_header_size;
 	void *fragptr;
 
+	if (!priv->port_up)
+		goto tx_drop;
+
 	real_size = get_real_size(skb, dev, &lso_header_size);
 	if (unlikely(!real_size))
 		goto tx_drop;
@@ -627,7 +634,7 @@
 
 	tx_ind = skb->queue_mapping;
 	ring = &priv->tx_ring[tx_ind];
-	if (priv->vlgrp && vlan_tx_tag_present(skb))
+	if (vlan_tx_tag_present(skb))
 		vlan_tag = vlan_tx_tag_get(skb);
 
 	/* Check available TXBBs And 2K spare for prefetch */
@@ -676,6 +683,19 @@
 		priv->port_stats.tx_chksum_offload++;
 	}
 
+	if (unlikely(priv->validate_loopback)) {
+		/* Copy dst mac address to wqe */
+		skb_reset_mac_header(skb);
+		ethh = eth_hdr(skb);
+		if (ethh && ethh->h_dest) {
+			mac = mlx4_en_mac_to_u64(ethh->h_dest);
+			mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16);
+			mac_l = (u32) (mac & 0xffffffff);
+			tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h);
+			tx_desc->ctrl.imm = cpu_to_be32(mac_l);
+		}
+	}
+
 	/* Handle LSO (TSO) packets */
 	if (lso_header_size) {
 		/* Mark opcode as LSO */
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 6d7b2bf..552d0fc 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -699,3 +699,47 @@
 
 	kfree(priv->eq_table.uar_map);
 }
+
+/* A test that verifies that we can accept interrupts on all
+ * the irq vectors of the device.
+ * Interrupts are checked using the NOP command.
+ */
+int mlx4_test_interrupts(struct mlx4_dev *dev)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	int i;
+	int err;
+
+	err = mlx4_NOP(dev);
+	/* When not in MSI_X, there is only one irq to check */
+	if (!(dev->flags & MLX4_FLAG_MSI_X))
+		return err;
+
+	/* A loop over all completion vectors, for each vector we will check
+	 * whether it works by mapping command completions to that vector
+	 * and performing a NOP command
+	 */
+	for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) {
+		/* Temporary use polling for command completions */
+		mlx4_cmd_use_polling(dev);
+
+		/* Map the new eq to handle all asyncronous events */
+		err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0,
+				  priv->eq_table.eq[i].eqn);
+		if (err) {
+			mlx4_warn(dev, "Failed mapping eq for interrupt test\n");
+			mlx4_cmd_use_events(dev);
+			break;
+		}
+
+		/* Go back to using events */
+		mlx4_cmd_use_events(dev);
+		err = mlx4_NOP(dev);
+	}
+
+	/* Return to default */
+	mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0,
+		    priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
+	return err;
+}
+EXPORT_SYMBOL(mlx4_test_interrupts);
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 04f42ae..b716e1a 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -141,6 +141,7 @@
 	struct mlx4_cmd_mailbox *mailbox;
 	u32 *outbox;
 	u8 field;
+	u32 field32;
 	u16 size;
 	u16 stat_rate;
 	int err;
@@ -178,6 +179,8 @@
 #define QUERY_DEV_CAP_MAX_GID_OFFSET		0x3b
 #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET	0x3c
 #define QUERY_DEV_CAP_MAX_PKEY_OFFSET		0x3f
+#define QUERY_DEV_CAP_UDP_RSS_OFFSET		0x42
+#define QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET	0x43
 #define QUERY_DEV_CAP_FLAGS_OFFSET		0x44
 #define QUERY_DEV_CAP_RSVD_UAR_OFFSET		0x48
 #define QUERY_DEV_CAP_UAR_SZ_OFFSET		0x49
@@ -268,6 +271,10 @@
 	dev_cap->max_msg_sz = 1 << (field & 0x1f);
 	MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
 	dev_cap->stat_rate_support = stat_rate;
+	MLX4_GET(field, outbox, QUERY_DEV_CAP_UDP_RSS_OFFSET);
+	dev_cap->udp_rss = field & 0x1;
+	MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
+	dev_cap->loopback_support = field & 0x1;
 	MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
 	dev_cap->reserved_uars = field >> 4;
@@ -365,6 +372,9 @@
 #define QUERY_PORT_MAX_MACVLAN_OFFSET		0x0a
 #define QUERY_PORT_MAX_VL_OFFSET		0x0b
 #define QUERY_PORT_MAC_OFFSET			0x10
+#define QUERY_PORT_TRANS_VENDOR_OFFSET		0x18
+#define QUERY_PORT_WAVELENGTH_OFFSET		0x1c
+#define QUERY_PORT_TRANS_CODE_OFFSET		0x20
 
 		for (i = 1; i <= dev_cap->num_ports; ++i) {
 			err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT,
@@ -388,6 +398,11 @@
 			dev_cap->log_max_vlans[i] = field >> 4;
 			MLX4_GET(dev_cap->eth_mtu[i], outbox, QUERY_PORT_ETH_MTU_OFFSET);
 			MLX4_GET(dev_cap->def_mac[i], outbox, QUERY_PORT_MAC_OFFSET);
+			MLX4_GET(field32, outbox, QUERY_PORT_TRANS_VENDOR_OFFSET);
+			dev_cap->trans_type[i] = field32 >> 24;
+			dev_cap->vendor_oui[i] = field32 & 0xffffff;
+			MLX4_GET(dev_cap->wavelength[i], outbox, QUERY_PORT_WAVELENGTH_OFFSET);
+			MLX4_GET(dev_cap->trans_code[i], outbox, QUERY_PORT_TRANS_CODE_OFFSET);
 		}
 	}
 
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 526d7f3..65cc72e 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -73,7 +73,13 @@
 	int max_pkeys[MLX4_MAX_PORTS + 1];
 	u64 def_mac[MLX4_MAX_PORTS + 1];
 	u16 eth_mtu[MLX4_MAX_PORTS + 1];
+	int trans_type[MLX4_MAX_PORTS + 1];
+	int vendor_oui[MLX4_MAX_PORTS + 1];
+	u16 wavelength[MLX4_MAX_PORTS + 1];
+	u64 trans_code[MLX4_MAX_PORTS + 1];
 	u16 stat_rate_support;
+	int udp_rss;
+	int loopback_support;
 	u32 flags;
 	int reserved_uars;
 	int uar_size;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 5102ab1..569fa3d 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -184,6 +184,10 @@
 		dev->caps.eth_mtu_cap[i]    = dev_cap->eth_mtu[i];
 		dev->caps.def_mac[i]        = dev_cap->def_mac[i];
 		dev->caps.supported_type[i] = dev_cap->supported_port_types[i];
+		dev->caps.trans_type[i]	    = dev_cap->trans_type[i];
+		dev->caps.vendor_oui[i]     = dev_cap->vendor_oui[i];
+		dev->caps.wavelength[i]     = dev_cap->wavelength[i];
+		dev->caps.trans_code[i]     = dev_cap->trans_code[i];
 	}
 
 	dev->caps.num_uars	     = dev_cap->uar_size / PAGE_SIZE;
@@ -221,6 +225,8 @@
 	dev->caps.bmme_flags	     = dev_cap->bmme_flags;
 	dev->caps.reserved_lkey	     = dev_cap->reserved_lkey;
 	dev->caps.stat_rate_support  = dev_cap->stat_rate_support;
+	dev->caps.udp_rss	     = dev_cap->udp_rss;
+	dev->caps.loopback_support   = dev_cap->loopback_support;
 	dev->caps.max_gso_sz	     = dev_cap->max_gso_sz;
 
 	dev->caps.log_num_macs  = log_num_mac;
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 4492109..1fc16ab 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -38,19 +38,19 @@
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/netdevice.h>
-#include <linux/inet_lro.h>
 
 #include <linux/mlx4/device.h>
 #include <linux/mlx4/qp.h>
 #include <linux/mlx4/cq.h>
 #include <linux/mlx4/srq.h>
 #include <linux/mlx4/doorbell.h>
+#include <linux/mlx4/cmd.h>
 
 #include "en_port.h"
 
 #define DRV_NAME	"mlx4_en"
-#define DRV_VERSION	"1.4.1.1"
-#define DRV_RELDATE	"June 2009"
+#define DRV_VERSION	"1.5.1.6"
+#define DRV_RELDATE	"August 2010"
 
 #define MLX4_EN_MSG_LEVEL	(NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
 
@@ -61,7 +61,6 @@
 
 #define MLX4_EN_PAGE_SHIFT	12
 #define MLX4_EN_PAGE_SIZE	(1 << MLX4_EN_PAGE_SHIFT)
-#define MAX_TX_RINGS		16
 #define MAX_RX_RINGS		16
 #define TXBB_SIZE		64
 #define HEADROOM		(2048 / TXBB_SIZE + 1)
@@ -107,6 +106,7 @@
 #define MLX4_EN_SMALL_PKT_SIZE		64
 #define MLX4_EN_NUM_TX_RINGS		8
 #define MLX4_EN_NUM_PPP_RINGS		8
+#define MAX_TX_RINGS			(MLX4_EN_NUM_TX_RINGS + MLX4_EN_NUM_PPP_RINGS)
 #define MLX4_EN_DEF_TX_RING_SIZE	512
 #define MLX4_EN_DEF_RX_RING_SIZE  	1024
 
@@ -139,10 +139,14 @@
 
 #define SMALL_PACKET_SIZE      (256 - NET_IP_ALIGN)
 #define HEADER_COPY_SIZE       (128 - NET_IP_ALIGN)
+#define MLX4_LOOPBACK_TEST_PAYLOAD (HEADER_COPY_SIZE - ETH_HLEN)
 
 #define MLX4_EN_MIN_MTU		46
 #define ETH_BCAST		0xffffffffffffULL
 
+#define MLX4_EN_LOOPBACK_RETRIES	5
+#define MLX4_EN_LOOPBACK_TIMEOUT	100
+
 #ifdef MLX4_EN_PERF_STAT
 /* Number of samples to 'average' */
 #define AVG_SIZE			128
@@ -249,7 +253,6 @@
 struct mlx4_en_rx_ring {
 	struct mlx4_hwq_resources wqres;
 	struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS];
-	struct net_lro_mgr lro;
 	u32 size ;	/* number of Rx descs*/
 	u32 actual_size;
 	u32 size_mask;
@@ -313,7 +316,8 @@
 
 struct mlx4_en_profile {
 	int rss_xor;
-	int num_lro;
+	int tcp_rss;
+	int udp_rss;
 	u8 rss_mask;
 	u32 active_ports;
 	u32 small_pkt_int;
@@ -337,6 +341,7 @@
 	struct mlx4_mr		mr;
 	u32                     priv_pdn;
 	spinlock_t              uar_lock;
+	u8			mac_removed[MLX4_MAX_PORTS + 1];
 };
 
 
@@ -355,6 +360,13 @@
 	u8 hash_fn;
 	u8 flags;
 	__be32 rss_key[10];
+	__be32 base_qpn_udp;
+};
+
+struct mlx4_en_port_state {
+	int link_state;
+	int link_speed;
+	int transciver;
 };
 
 struct mlx4_en_pkt_stats {
@@ -365,9 +377,6 @@
 };
 
 struct mlx4_en_port_stats {
-	unsigned long lro_aggregated;
-	unsigned long lro_flushed;
-	unsigned long lro_no_desc;
 	unsigned long tso_packets;
 	unsigned long queue_stopped;
 	unsigned long wake_queue;
@@ -376,7 +385,7 @@
 	unsigned long rx_chksum_good;
 	unsigned long rx_chksum_none;
 	unsigned long tx_chksum_offload;
-#define NUM_PORT_STATS		11
+#define NUM_PORT_STATS		8
 };
 
 struct mlx4_en_perf_stats {
@@ -405,6 +414,7 @@
 	struct vlan_group *vlgrp;
 	struct net_device_stats stats;
 	struct net_device_stats ret_stats;
+	struct mlx4_en_port_state port_state;
 	spinlock_t stats_lock;
 
 	unsigned long last_moder_packets;
@@ -423,6 +433,8 @@
 	u16 sample_interval;
 	u16 adaptive_rx_coal;
 	u32 msg_enable;
+	u32 loopback_ok;
+	u32 validate_loopback;
 
 	struct mlx4_hwq_resources res;
 	int link_state;
@@ -531,6 +543,11 @@
 			   u8 promisc);
 
 int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
+int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
+
+#define MLX4_EN_NUM_SELF_TEST	5
+void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf);
+u64 mlx4_en_mac_to_u64(u8 *addr);
 
 /*
  * Globals
@@ -555,6 +572,8 @@
 	en_print(KERN_WARNING, priv, format, ##arg)
 #define en_err(priv, format, arg...)			\
 	en_print(KERN_ERR, priv, format, ##arg)
+#define en_info(priv, format, arg...)			\
+	en_print(KERN_INFO, priv, format, ## arg)
 
 #define mlx4_err(mdev, format, arg...)			\
 	pr_err("%s %s: " format, DRV_NAME,		\
diff --git a/drivers/net/mlx4/profile.c b/drivers/net/mlx4/profile.c
index 5caf011..e749f82 100644
--- a/drivers/net/mlx4/profile.c
+++ b/drivers/net/mlx4/profile.c
@@ -85,7 +85,7 @@
 	struct mlx4_resource tmp;
 	int i, j;
 
-	profile = kzalloc(MLX4_RES_NUM * sizeof *profile, GFP_KERNEL);
+	profile = kcalloc(MLX4_RES_NUM, sizeof(*profile), GFP_KERNEL);
 	if (!profile)
 		return -ENOMEM;
 
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 2d488ab..dd2b6a7 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -2901,7 +2901,8 @@
 	mp->dev = dev;
 
 	set_params(mp, pd);
-	dev->real_num_tx_queues = mp->txq_count;
+	netif_set_real_num_tx_queues(dev, mp->txq_count);
+	netif_set_real_num_rx_queues(dev, mp->rxq_count);
 
 	if (pd->phy_addr != MV643XX_ETH_PHY_NONE)
 		mp->phy = phy_scan(mp, pd->phy_addr);
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index fb2c092..8524cc4 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -225,6 +225,7 @@
 	struct msix_entry *msix_vectors;
 #ifdef CONFIG_MYRI10GE_DCA
 	int dca_enabled;
+	int relaxed_order;
 #endif
 	u32 link_state;
 	unsigned int rdma_tags_available;
@@ -990,7 +991,7 @@
 		 * RX queues, so if we get an error, first retry using a
 		 * single TX queue before giving up */
 		if (status != 0 && mgp->dev->real_num_tx_queues > 1) {
-			mgp->dev->real_num_tx_queues = 1;
+			netif_set_real_num_tx_queues(mgp->dev, 1);
 			cmd.data0 = mgp->num_slices;
 			cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;
 			status = myri10ge_send_cmd(mgp,
@@ -1074,10 +1075,28 @@
 }
 
 #ifdef CONFIG_MYRI10GE_DCA
+static int myri10ge_toggle_relaxed(struct pci_dev *pdev, int on)
+{
+	int ret, cap, err;
+	u16 ctl;
+
+	cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	if (!cap)
+		return 0;
+
+	err = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
+	ret = (ctl & PCI_EXP_DEVCTL_RELAX_EN) >> 4;
+	if (ret != on) {
+		ctl &= ~PCI_EXP_DEVCTL_RELAX_EN;
+		ctl |= (on << 4);
+		pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
+	}
+	return ret;
+}
+
 static void
 myri10ge_write_dca(struct myri10ge_slice_state *ss, int cpu, int tag)
 {
-	ss->cpu = cpu;
 	ss->cached_dca_tag = tag;
 	put_be32(htonl(tag), ss->dca_tag);
 }
@@ -1088,9 +1107,10 @@
 	int tag;
 
 	if (cpu != ss->cpu) {
-		tag = dca_get_tag(cpu);
+		tag = dca3_get_tag(&ss->mgp->pdev->dev, cpu);
 		if (ss->cached_dca_tag != tag)
 			myri10ge_write_dca(ss, cpu, tag);
+		ss->cpu = cpu;
 	}
 	put_cpu();
 }
@@ -1113,9 +1133,13 @@
 				"dca_add_requester() failed, err=%d\n", err);
 		return;
 	}
+	mgp->relaxed_order = myri10ge_toggle_relaxed(pdev, 0);
 	mgp->dca_enabled = 1;
-	for (i = 0; i < mgp->num_slices; i++)
-		myri10ge_write_dca(&mgp->ss[i], -1, 0);
+	for (i = 0; i < mgp->num_slices; i++) {
+		mgp->ss[i].cpu = -1;
+		mgp->ss[i].cached_dca_tag = -1;
+		myri10ge_update_dca(&mgp->ss[i]);
+	 }
 }
 
 static void myri10ge_teardown_dca(struct myri10ge_priv *mgp)
@@ -1126,6 +1150,8 @@
 	if (!mgp->dca_enabled)
 		return;
 	mgp->dca_enabled = 0;
+	if (mgp->relaxed_order)
+		myri10ge_toggle_relaxed(pdev, 1);
 	err = dca_remove_requester(&pdev->dev);
 }
 
@@ -1555,12 +1581,12 @@
 	 * valid  since MSI-X irqs are not shared */
 	if ((mgp->dev->real_num_tx_queues == 1) && (ss != mgp->ss)) {
 		napi_schedule(&ss->napi);
-		return (IRQ_HANDLED);
+		return IRQ_HANDLED;
 	}
 
 	/* make sure it is our IRQ, and that the DMA has finished */
 	if (unlikely(!stats->valid))
-		return (IRQ_NONE);
+		return IRQ_NONE;
 
 	/* low bit indicates receives are present, so schedule
 	 * napi poll handler */
@@ -1599,7 +1625,7 @@
 		myri10ge_check_statblock(mgp);
 
 	put_be32(htonl(3), ss->irq_claim + 1);
-	return (IRQ_HANDLED);
+	return IRQ_HANDLED;
 }
 
 static int
@@ -3753,8 +3779,8 @@
 	 * slices. We give up on MSI-X if we can only get a single
 	 * vector. */
 
-	mgp->msix_vectors = kzalloc(mgp->num_slices *
-				    sizeof(*mgp->msix_vectors), GFP_KERNEL);
+	mgp->msix_vectors = kcalloc(mgp->num_slices, sizeof(*mgp->msix_vectors),
+				    GFP_KERNEL);
 	if (mgp->msix_vectors == NULL)
 		goto disable_msix;
 	for (i = 0; i < mgp->num_slices; i++) {
@@ -3923,7 +3949,8 @@
 		dev_err(&pdev->dev, "failed to alloc slice state\n");
 		goto abort_with_firmware;
 	}
-	netdev->real_num_tx_queues = mgp->num_slices;
+	netif_set_real_num_tx_queues(netdev, mgp->num_slices);
+	netif_set_real_num_rx_queues(netdev, mgp->num_slices);
 	status = myri10ge_reset(mgp);
 	if (status != 0) {
 		dev_err(&pdev->dev, "failed reset\n");
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 617f898..4846e13 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -735,7 +735,7 @@
 		int i;
 		for (i = 0; i < dev->addr_len; i++)
 			eth->h_dest[i] = 0;
-		return(dev->hard_header_len);
+		return dev->hard_header_len;
 	}
 
 	if (daddr) {
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index a6033d4..2fd3963 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -1570,7 +1570,7 @@
 	init_timer(&np->timer);
 	np->timer.expires = round_jiffies(jiffies + NATSEMI_TIMER_FREQ);
 	np->timer.data = (unsigned long)dev;
-	np->timer.function = &netdev_timer; /* timer handler */
+	np->timer.function = netdev_timer; /* timer handler */
 	add_timer(&np->timer);
 
 	return 0;
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index ca142c4..94255f0 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -678,7 +678,14 @@
 				strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
 				break;
 			case NETDEV_UNREGISTER:
-				netpoll_cleanup(&nt->np);
+				/*
+				 * rtnl_lock already held
+				 */
+				if (nt->np.dev) {
+					__netpoll_cleanup(&nt->np);
+					dev_put(nt->np.dev);
+					nt->np.dev = NULL;
+				}
 				/* Fall through */
 			case NETDEV_GOING_DOWN:
 			case NETDEV_BONDING_DESLAVE:
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 6dca357..8e8a978 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -175,7 +175,10 @@
 #define	MAX_NUM_CARDS		4
 
 #define MAX_BUFFERS_PER_CMD	32
-#define TX_STOP_THRESH		((MAX_SKB_FRAGS >> 2) + 4)
+#define MAX_TSO_HEADER_DESC	2
+#define MGMT_CMD_DESC_RESV	4
+#define TX_STOP_THRESH		((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
+							+ MGMT_CMD_DESC_RESV)
 #define NX_MAX_TX_TIMEOUTS	2
 
 /*
@@ -1253,19 +1256,9 @@
 	const struct firmware *fw;
 };
 
-int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port);
-int netxen_niu_disable_xg_port(struct netxen_adapter *adapter);
-
 int nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val);
 int nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val);
 
-/* Functions available from netxen_nic_hw.c */
-int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
-int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu);
-
-int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr);
-int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr);
-
 #define NXRD32(adapter, off) \
 	(adapter->crb_read(adapter, off))
 #define NXWR32(adapter, off, val) \
@@ -1345,11 +1338,8 @@
 		struct nx_host_rds_ring *rds_ring);
 int netxen_process_cmd_ring(struct netxen_adapter *adapter);
 int netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max);
-void netxen_p2_nic_set_multi(struct net_device *netdev);
-void netxen_p3_nic_set_multi(struct net_device *netdev);
+
 void netxen_p3_free_mac_list(struct netxen_adapter *adapter);
-int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode);
-int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32);
 int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
 int netxen_config_rss(struct netxen_adapter *adapter, int enable);
 int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd);
@@ -1364,9 +1354,6 @@
 int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable);
 int netxen_send_lro_cleanup(struct netxen_adapter *adapter);
 
-int netxen_nic_set_mac(struct net_device *netdev, void *p);
-struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
-
 void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
 		struct nx_host_tx_ring *tx_ring);
 
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 29d7b93d0..37d3ebd 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -319,6 +319,8 @@
 
 #define NETXEN_PCIE_SEM_TIMEOUT	10000
 
+static int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
+
 int
 netxen_pcie_sem_lock(struct netxen_adapter *adapter, int sem, u32 id_reg)
 {
@@ -345,7 +347,7 @@
 	NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_UNLOCK(sem)));
 }
 
-int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
+static int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
 {
 	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
 		NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
@@ -356,7 +358,7 @@
 }
 
 /* Disable an XG interface */
-int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
+static int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
 {
 	__u32 mac_cfg;
 	u32 port = adapter->physical_port;
@@ -383,7 +385,7 @@
 #define MAC_LO(addr) \
 	((addr[5] << 16) | (addr[4] << 8) | (addr[3]))
 
-int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
+static int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
 {
 	u32 mac_cfg;
 	u32 cnt = 0;
@@ -434,7 +436,7 @@
 	return 0;
 }
 
-int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
+static int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
 {
 	u32 mac_hi, mac_lo;
 	u32 reg_hi, reg_lo;
@@ -531,7 +533,7 @@
 	return 0;
 }
 
-void netxen_p2_nic_set_multi(struct net_device *netdev)
+static void netxen_p2_nic_set_multi(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
 	struct netdev_hw_addr *ha;
@@ -598,8 +600,14 @@
 
 	if (nr_desc >= netxen_tx_avail(tx_ring)) {
 		netif_tx_stop_queue(tx_ring->txq);
-		__netif_tx_unlock_bh(tx_ring->txq);
-		return -EBUSY;
+		smp_mb();
+		if (netxen_tx_avail(tx_ring) > nr_desc) {
+			if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
+				netif_tx_wake_queue(tx_ring->txq);
+		} else {
+			__netif_tx_unlock_bh(tx_ring->txq);
+			return -EBUSY;
+		}
 	}
 
 	do {
@@ -674,7 +682,7 @@
 				cur->mac_addr, NETXEN_MAC_ADD);
 }
 
-void netxen_p3_nic_set_multi(struct net_device *netdev)
+static void netxen_p3_nic_set_multi(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
 	struct netdev_hw_addr *ha;
@@ -721,7 +729,7 @@
 	}
 }
 
-int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
+static int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
 {
 	nx_nic_req_t req;
 	u64 word;
@@ -754,7 +762,7 @@
 	}
 }
 
-int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
+static int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
 {
 	/* assuming caller has already copied new addr to netdev */
 	netxen_p3_nic_set_multi(adapter->netdev);
@@ -1816,14 +1824,14 @@
 	if (netxen_rom_fast_read(adapter, offset, &board_type))
 		return -EIO;
 
-	adapter->ahw.board_type = board_type;
-
 	if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) {
 		u32 gpio = NXRD32(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I);
 		if ((gpio & 0x8000) == 0)
 			board_type = NETXEN_BRDTYPE_P3_10G_TP;
 	}
 
+	adapter->ahw.board_type = board_type;
+
 	switch (board_type) {
 	case NETXEN_BRDTYPE_P2_SB35_4G:
 		adapter->ahw.port_type = NETXEN_NIC_GBE;
@@ -1867,16 +1875,7 @@
 }
 
 /* NIU access sections */
-
-int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu)
-{
-	new_mtu += MTU_FUDGE_FACTOR;
-	NXWR32(adapter, NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port),
-		new_mtu);
-	return 0;
-}
-
-int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
+static int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
 {
 	new_mtu += MTU_FUDGE_FACTOR;
 	if (adapter->physical_port == 0)
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index cabae7b..95fe552 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -346,7 +346,7 @@
 	if (pci_base == NETXEN_ADDR_ERROR)
 		return pci_base;
 	else
-		return (pci_base + offset);
+		return pci_base + offset;
 }
 
 #define NETXEN_MAX_ROM_WAIT_USEC	100
@@ -1540,7 +1540,6 @@
 	if (pkt_offset)
 		skb_pull(skb, pkt_offset);
 
-	skb->truesize = skb->len + sizeof(struct sk_buff);
 	skb->protocol = eth_type_trans(skb, netdev);
 
 	napi_gro_receive(&sds_ring->napi, skb);
@@ -1602,8 +1601,6 @@
 
 	skb_put(skb, lro_length + data_offset);
 
-	skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb);
-
 	skb_pull(skb, l2_hdr_offset);
 	skb->protocol = eth_type_trans(skb, netdev);
 
@@ -1766,14 +1763,10 @@
 
 		smp_mb();
 
-		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
-			__netif_tx_lock(tx_ring->txq, smp_processor_id());
-			if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) {
+		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
+			if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
 				netif_wake_queue(netdev);
-				adapter->tx_timeo_cnt = 0;
-			}
-			__netif_tx_unlock(tx_ring->txq);
-		}
+		adapter->tx_timeo_cnt = 0;
 	}
 	/*
 	 * If everything is freed up to consumer then check if the ring is full
@@ -1792,7 +1785,7 @@
 	done = (sw_consumer == hw_consumer);
 	spin_unlock(&adapter->tx_clean_lock);
 
-	return (done);
+	return done;
 }
 
 void
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 73d3145..50820bea 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -95,6 +95,8 @@
 static irqreturn_t netxen_msix_intr(int irq, void *data);
 
 static void netxen_config_indev_addr(struct net_device *dev, unsigned long);
+static struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
+static int netxen_nic_set_mac(struct net_device *netdev, void *p);
 
 /*  PCI Device ID Table  */
 #define ENTRY(device) \
@@ -125,11 +127,6 @@
 		struct nx_host_tx_ring *tx_ring)
 {
 	NXWRIO(adapter, tx_ring->crb_cmd_producer, tx_ring->producer);
-
-	if (netxen_tx_avail(tx_ring) <= TX_STOP_THRESH) {
-		netif_stop_queue(adapter->netdev);
-		smp_mb();
-	}
 }
 
 static uint32_t crb_cmd_consumer[4] = {
@@ -177,7 +174,7 @@
 
 	recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL);
 
-	return (recv_ctx->sds_rings == NULL);
+	return recv_ctx->sds_rings == NULL;
 }
 
 static void
@@ -460,7 +457,7 @@
 	return 0;
 }
 
-int netxen_nic_set_mac(struct net_device *netdev, void *p)
+static int netxen_nic_set_mac(struct net_device *netdev, void *p)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
 	struct sockaddr *addr = p;
@@ -1209,7 +1206,7 @@
 		adapter->max_mc_count = 16;
 
 	netdev->netdev_ops	   = &netxen_netdev_ops;
-	netdev->watchdog_timeo     = 2*HZ;
+	netdev->watchdog_timeo     = 5*HZ;
 
 	netxen_nic_change_mtu(netdev, netdev->mtu);
 
@@ -1254,6 +1251,28 @@
 	return 0;
 }
 
+#ifdef CONFIG_PCIEAER
+static void netxen_mask_aer_correctable(struct netxen_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct pci_dev *root = pdev->bus->self;
+	u32 aer_pos;
+
+	if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM &&
+		adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP)
+		return;
+
+	if (root->pcie_type != PCI_EXP_TYPE_ROOT_PORT)
+		return;
+
+	aer_pos = pci_find_ext_capability(root, PCI_EXT_CAP_ID_ERR);
+	if (!aer_pos)
+		return;
+
+	pci_write_config_dword(root, aer_pos + PCI_ERR_COR_MASK, 0xffff);
+}
+#endif
+
 static int __devinit
 netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -1322,6 +1341,10 @@
 		goto err_out_iounmap;
 	}
 
+#ifdef CONFIG_PCIEAER
+	netxen_mask_aer_correctable(adapter);
+#endif
+
 	/* Mezz cards have PCI function 0,2,3 enabled */
 	switch (adapter->ahw.board_type) {
 	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
@@ -1825,9 +1848,13 @@
 	/* 4 fragments per cmd des */
 	no_of_desc = (frag_count + 3) >> 2;
 
-	if (unlikely(no_of_desc + 2 > netxen_tx_avail(tx_ring))) {
+	if (unlikely(netxen_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
 		netif_stop_queue(netdev);
-		return NETDEV_TX_BUSY;
+		smp_mb();
+		if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
+			netif_start_queue(netdev);
+		else
+			return NETDEV_TX_BUSY;
 	}
 
 	producer = tx_ring->producer;
@@ -2027,7 +2054,7 @@
 	clear_bit(__NX_RESETTING, &adapter->state);
 }
 
-struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+static struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
 	struct net_device_stats *stats = &netdev->stats;
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index fe6983a..781e368 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -283,7 +283,7 @@
 
 static u32 phy_encode(u32 type, int port)
 {
-	return (type << (port * 2));
+	return type << (port * 2);
 }
 
 static u32 phy_decode(u32 val, int port)
@@ -3043,8 +3043,7 @@
 
 static u64 hash_addr_regval(unsigned long index, unsigned long num_entries)
 {
-	return ((u64)index | (num_entries == 1 ?
-			      HASH_TBL_ADDR_AUTOINC : 0));
+	return (u64)index | (num_entries == 1 ? HASH_TBL_ADDR_AUTOINC : 0);
 }
 
 #if 0
@@ -3276,7 +3275,7 @@
 	/* One entry reserved for IP fragment rule */
 	if (idx >= (np->clas.tcam_sz - 1))
 		idx = 0;
-	return (np->clas.tcam_top + ((idx+1) * np->parent->num_ports));
+	return np->clas.tcam_top + ((idx+1) * np->parent->num_ports);
 }
 
 static u16 tcam_get_size(struct niu *np)
@@ -3313,7 +3312,7 @@
 	a >>= PAGE_SHIFT;
 	a ^= (a >> ilog2(MAX_RBR_RING_SIZE));
 
-	return (a & (MAX_RBR_RING_SIZE - 1));
+	return a & (MAX_RBR_RING_SIZE - 1);
 }
 
 static struct page *niu_find_rxpage(struct rx_ring_info *rp, u64 addr,
@@ -3484,7 +3483,7 @@
 				     RCR_ENTRY_ERROR)))
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
 			else
-				skb->ip_summed = CHECKSUM_NONE;
+				skb_checksum_none_assert(skb);
 		} else if (!(val & RCR_ENTRY_MULTI))
 			append_size = len - skb->len;
 
@@ -4502,9 +4501,10 @@
 	np->num_rx_rings = parent->rxchan_per_port[port];
 	np->num_tx_rings = parent->txchan_per_port[port];
 
-	np->dev->real_num_tx_queues = np->num_tx_rings;
+	netif_set_real_num_rx_queues(np->dev, np->num_rx_rings);
+	netif_set_real_num_tx_queues(np->dev, np->num_tx_rings);
 
-	np->rx_rings = kzalloc(np->num_rx_rings * sizeof(struct rx_ring_info),
+	np->rx_rings = kcalloc(np->num_rx_rings, sizeof(struct rx_ring_info),
 			       GFP_KERNEL);
 	err = -ENOMEM;
 	if (!np->rx_rings)
@@ -4538,7 +4538,7 @@
 			return err;
 	}
 
-	np->tx_rings = kzalloc(np->num_tx_rings * sizeof(struct tx_ring_info),
+	np->tx_rings = kcalloc(np->num_tx_rings, sizeof(struct tx_ring_info),
 			       GFP_KERNEL);
 	err = -ENOMEM;
 	if (!np->tx_rings)
@@ -7090,24 +7090,20 @@
 static void niu_get_ip4fs_from_tcam_key(struct niu_tcam_entry *tp,
 					struct ethtool_rx_flow_spec *fsp)
 {
+	u32 tmp;
+	u16 prt;
 
-	fsp->h_u.tcp_ip4_spec.ip4src = (tp->key[3] & TCAM_V4KEY3_SADDR) >>
-		TCAM_V4KEY3_SADDR_SHIFT;
-	fsp->h_u.tcp_ip4_spec.ip4dst = (tp->key[3] & TCAM_V4KEY3_DADDR) >>
-		TCAM_V4KEY3_DADDR_SHIFT;
-	fsp->m_u.tcp_ip4_spec.ip4src = (tp->key_mask[3] & TCAM_V4KEY3_SADDR) >>
-		TCAM_V4KEY3_SADDR_SHIFT;
-	fsp->m_u.tcp_ip4_spec.ip4dst = (tp->key_mask[3] & TCAM_V4KEY3_DADDR) >>
-		TCAM_V4KEY3_DADDR_SHIFT;
+	tmp = (tp->key[3] & TCAM_V4KEY3_SADDR) >> TCAM_V4KEY3_SADDR_SHIFT;
+	fsp->h_u.tcp_ip4_spec.ip4src = cpu_to_be32(tmp);
 
-	fsp->h_u.tcp_ip4_spec.ip4src =
-		cpu_to_be32(fsp->h_u.tcp_ip4_spec.ip4src);
-	fsp->m_u.tcp_ip4_spec.ip4src =
-		cpu_to_be32(fsp->m_u.tcp_ip4_spec.ip4src);
-	fsp->h_u.tcp_ip4_spec.ip4dst =
-		cpu_to_be32(fsp->h_u.tcp_ip4_spec.ip4dst);
-	fsp->m_u.tcp_ip4_spec.ip4dst =
-		cpu_to_be32(fsp->m_u.tcp_ip4_spec.ip4dst);
+	tmp = (tp->key[3] & TCAM_V4KEY3_DADDR) >> TCAM_V4KEY3_DADDR_SHIFT;
+	fsp->h_u.tcp_ip4_spec.ip4dst = cpu_to_be32(tmp);
+
+	tmp = (tp->key_mask[3] & TCAM_V4KEY3_SADDR) >> TCAM_V4KEY3_SADDR_SHIFT;
+	fsp->m_u.tcp_ip4_spec.ip4src = cpu_to_be32(tmp);
+
+	tmp = (tp->key_mask[3] & TCAM_V4KEY3_DADDR) >> TCAM_V4KEY3_DADDR_SHIFT;
+	fsp->m_u.tcp_ip4_spec.ip4dst = cpu_to_be32(tmp);
 
 	fsp->h_u.tcp_ip4_spec.tos = (tp->key[2] & TCAM_V4KEY2_TOS) >>
 		TCAM_V4KEY2_TOS_SHIFT;
@@ -7118,54 +7114,40 @@
 	case TCP_V4_FLOW:
 	case UDP_V4_FLOW:
 	case SCTP_V4_FLOW:
-		fsp->h_u.tcp_ip4_spec.psrc =
-			((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
-			 TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16;
-		fsp->h_u.tcp_ip4_spec.pdst =
-			((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
-			 TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff;
-		fsp->m_u.tcp_ip4_spec.psrc =
-			((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
-			 TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16;
-		fsp->m_u.tcp_ip4_spec.pdst =
-			((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
-			 TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff;
+		prt = ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
+			TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16;
+		fsp->h_u.tcp_ip4_spec.psrc = cpu_to_be16(prt);
 
-		fsp->h_u.tcp_ip4_spec.psrc =
-			cpu_to_be16(fsp->h_u.tcp_ip4_spec.psrc);
-		fsp->h_u.tcp_ip4_spec.pdst =
-			cpu_to_be16(fsp->h_u.tcp_ip4_spec.pdst);
-		fsp->m_u.tcp_ip4_spec.psrc =
-			cpu_to_be16(fsp->m_u.tcp_ip4_spec.psrc);
-		fsp->m_u.tcp_ip4_spec.pdst =
-			cpu_to_be16(fsp->m_u.tcp_ip4_spec.pdst);
+		prt = ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
+			TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff;
+		fsp->h_u.tcp_ip4_spec.pdst = cpu_to_be16(prt);
+
+		prt = ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+			TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16;
+		fsp->m_u.tcp_ip4_spec.psrc = cpu_to_be16(prt);
+
+		prt = ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+			 TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff;
+		fsp->m_u.tcp_ip4_spec.pdst = cpu_to_be16(prt);
 		break;
 	case AH_V4_FLOW:
 	case ESP_V4_FLOW:
-		fsp->h_u.ah_ip4_spec.spi =
-			(tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
+		tmp = (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
 			TCAM_V4KEY2_PORT_SPI_SHIFT;
-		fsp->m_u.ah_ip4_spec.spi =
-			(tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
-			TCAM_V4KEY2_PORT_SPI_SHIFT;
+		fsp->h_u.ah_ip4_spec.spi = cpu_to_be32(tmp);
 
-		fsp->h_u.ah_ip4_spec.spi =
-			cpu_to_be32(fsp->h_u.ah_ip4_spec.spi);
-		fsp->m_u.ah_ip4_spec.spi =
-			cpu_to_be32(fsp->m_u.ah_ip4_spec.spi);
+		tmp = (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+			TCAM_V4KEY2_PORT_SPI_SHIFT;
+		fsp->m_u.ah_ip4_spec.spi = cpu_to_be32(tmp);
 		break;
 	case IP_USER_FLOW:
-		fsp->h_u.usr_ip4_spec.l4_4_bytes =
-			(tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
+		tmp = (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
 			TCAM_V4KEY2_PORT_SPI_SHIFT;
-		fsp->m_u.usr_ip4_spec.l4_4_bytes =
-			(tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
-			TCAM_V4KEY2_PORT_SPI_SHIFT;
+		fsp->h_u.usr_ip4_spec.l4_4_bytes = cpu_to_be32(tmp);
 
-		fsp->h_u.usr_ip4_spec.l4_4_bytes =
-			cpu_to_be32(fsp->h_u.usr_ip4_spec.l4_4_bytes);
-		fsp->m_u.usr_ip4_spec.l4_4_bytes =
-			cpu_to_be32(fsp->m_u.usr_ip4_spec.l4_4_bytes);
+		tmp = (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+			TCAM_V4KEY2_PORT_SPI_SHIFT;
+		fsp->m_u.usr_ip4_spec.l4_4_bytes = cpu_to_be32(tmp);
 
 		fsp->h_u.usr_ip4_spec.proto =
 			(tp->key[2] & TCAM_V4KEY2_PROTO) >>
@@ -7462,10 +7444,12 @@
 	if (fsp->flow_type == IP_USER_FLOW) {
 		int i;
 		int add_usr_cls = 0;
-		int ipv6 = 0;
 		struct ethtool_usrip4_spec *uspec = &fsp->h_u.usr_ip4_spec;
 		struct ethtool_usrip4_spec *umask = &fsp->m_u.usr_ip4_spec;
 
+		if (uspec->ip_ver != ETH_RX_NFC_IP4)
+			return -EINVAL;
+
 		niu_lock_parent(np, flags);
 
 		for (i = 0; i < NIU_L3_PROG_CLS; i++) {
@@ -7494,9 +7478,7 @@
 				default:
 					break;
 				}
-				if (uspec->ip_ver == ETH_RX_NFC_IP6)
-					ipv6 = 1;
-				ret = tcam_user_ip_class_set(np, class, ipv6,
+				ret = tcam_user_ip_class_set(np, class, 0,
 							     uspec->proto,
 							     uspec->tos,
 							     umask->tos);
@@ -7553,16 +7535,7 @@
 		ret = -EINVAL;
 		goto out;
 	case IP_USER_FLOW:
-		if (fsp->h_u.usr_ip4_spec.ip_ver == ETH_RX_NFC_IP4) {
-			niu_get_tcamkey_from_ip4fs(fsp, tp, l2_rdc_table,
-						   class);
-		} else {
-			/* Not yet implemented */
-			netdev_info(np->dev, "niu%d: In %s(): usr flow for IPv6 not implemented\n",
-				    parent->index, __func__);
-			ret = -EINVAL;
-			goto out;
-		}
+		niu_get_tcamkey_from_ip4fs(fsp, tp, l2_rdc_table, class);
 		break;
 	default:
 		netdev_info(np->dev, "niu%d: In %s(): Unknown flow type %d\n",
@@ -7805,11 +7778,11 @@
 	if (stringset != ETH_SS_STATS)
 		return -EINVAL;
 
-	return ((np->flags & NIU_FLAGS_XMAC ?
+	return (np->flags & NIU_FLAGS_XMAC ?
 		 NUM_XMAC_STAT_KEYS :
 		 NUM_BMAC_STAT_KEYS) +
 		(np->num_rx_rings * NUM_RXCHAN_STAT_KEYS) +
-		(np->num_tx_rings * NUM_TXCHAN_STAT_KEYS));
+		(np->num_tx_rings * NUM_TXCHAN_STAT_KEYS);
 }
 
 static void niu_get_ethtool_stats(struct net_device *dev,
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 5a3488f..84134c7 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -772,7 +772,7 @@
 		phy_intr(ndev);
 
 		/* Okay, let it rip */
-		spin_lock_irq(&dev->misc_lock);
+		spin_lock(&dev->misc_lock);
 		dev->IMR_cache |= ISR_PHY;
 		dev->IMR_cache |= ISR_RXRCMP;
 		//dev->IMR_cache |= ISR_RXERR;
@@ -923,7 +923,7 @@
 			if ((extsts & 0x002a0000) && !(extsts & 0x00540000)) {
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
 			} else {
-				skb->ip_summed = CHECKSUM_NONE;
+				skb_checksum_none_assert(skb);
 			}
 			skb->protocol = eth_type_trans(skb, ndev);
 #ifdef NS83820_VLAN_ACCEL_SUPPORT
@@ -1246,7 +1246,6 @@
 {
 	struct ns83820 *dev = PRIV(ndev);
 	u32 cfg, tanar, tbicr;
-	int have_optical = 0;
 	int fullduplex   = 0;
 
 	/*
@@ -1267,25 +1266,25 @@
 	tanar = readl(dev->base + TANAR);
 	tbicr = readl(dev->base + TBICR);
 
-	if (dev->CFG_cache & CFG_TBI_EN) {
-		/* we have an optical interface */
-		have_optical = 1;
-		fullduplex = (cfg & CFG_DUPSTS) ? 1 : 0;
-
-	} else {
-		/* We have copper */
-		fullduplex = (cfg & CFG_DUPSTS) ? 1 : 0;
-        }
+	fullduplex = (cfg & CFG_DUPSTS) ? 1 : 0;
 
 	cmd->supported = SUPPORTED_Autoneg;
 
-	/* we have optical interface */
 	if (dev->CFG_cache & CFG_TBI_EN) {
+		/* we have optical interface */
 		cmd->supported |= SUPPORTED_1000baseT_Half |
 					SUPPORTED_1000baseT_Full |
 					SUPPORTED_FIBRE;
 		cmd->port       = PORT_FIBRE;
-	} /* TODO: else copper related  support */
+	} else {
+		/* we have copper */
+		cmd->supported |= SUPPORTED_10baseT_Half |
+			SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half |
+			SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half |
+			SUPPORTED_1000baseT_Full |
+			SUPPORTED_MII;
+		cmd->port = PORT_MII;
+	}
 
 	cmd->duplex = fullduplex ? DUPLEX_FULL : DUPLEX_HALF;
 	switch (cfg / CFG_SPDSTS0 & 3) {
@@ -1299,7 +1298,8 @@
 		cmd->speed = SPEED_10;
 		break;
 	}
-	cmd->autoneg = (tbicr & TBICR_MR_AN_ENABLE) ? 1: 0;
+	cmd->autoneg = (tbicr & TBICR_MR_AN_ENABLE)
+		? AUTONEG_ENABLE : AUTONEG_DISABLE;
 	return 0;
 }
 
@@ -1405,6 +1405,13 @@
 	.get_link        = ns83820_get_link
 };
 
+static inline void ns83820_disable_interrupts(struct ns83820 *dev)
+{
+	writel(0, dev->base + IMR);
+	writel(0, dev->base + IER);
+	readl(dev->base + IER);
+}
+
 /* this function is called in irq context from the ISR */
 static void ns83820_mib_isr(struct ns83820 *dev)
 {
@@ -1557,10 +1564,7 @@
 	/* FIXME: protect against interrupt handler? */
 	del_timer_sync(&dev->tx_watchdog);
 
-	/* disable interrupts */
-	writel(0, dev->base + IMR);
-	writel(0, dev->base + IER);
-	readl(dev->base + IER);
+	ns83820_disable_interrupts(dev);
 
 	dev->rx_info.up = 0;
 	synchronize_irq(dev->pci_dev->irq);
@@ -2023,10 +2027,7 @@
 		dev->tx_descs, (long)dev->tx_phy_descs,
 		dev->rx_info.descs, (long)dev->rx_info.phy_descs);
 
-	/* disable interrupts */
-	writel(0, dev->base + IMR);
-	writel(0, dev->base + IER);
-	readl(dev->base + IER);
+	ns83820_disable_interrupts(dev);
 
 	dev->IMR_cache = 0;
 
@@ -2250,9 +2251,7 @@
 	return 0;
 
 out_cleanup:
-	writel(0, dev->base + IMR);	/* paranoia */
-	writel(0, dev->base + IER);
-	readl(dev->base + IER);
+	ns83820_disable_interrupts(dev); /* paranoia */
 out_free_irq:
 	rtnl_unlock();
 	free_irq(pci_dev->irq, ndev);
@@ -2277,9 +2276,7 @@
 	if (!ndev)			/* paranoia */
 		return;
 
-	writel(0, dev->base + IMR);	/* paranoia */
-	writel(0, dev->base + IER);
-	readl(dev->base + IER);
+	ns83820_disable_interrupts(dev); /* paranoia */
 
 	unregister_netdev(ndev);
 	free_irq(dev->pci_dev->irq, ndev);
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 8ab6ae0..828e97c 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -808,7 +808,7 @@
 			skb->csum = (macrx & XCT_MACRX_CSUM_M) >>
 					   XCT_MACRX_CSUM_S;
 		} else
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
 
 		packets++;
 		tot_bytes += len;
diff --git a/drivers/net/pasemi_mac_ethtool.c b/drivers/net/pasemi_mac_ethtool.c
index fefa79e..4825959 100644
--- a/drivers/net/pasemi_mac_ethtool.c
+++ b/drivers/net/pasemi_mac_ethtool.c
@@ -90,21 +90,6 @@
 	return phy_ethtool_sset(phydev, cmd);
 }
 
-static void
-pasemi_mac_ethtool_get_drvinfo(struct net_device *netdev,
-			       struct ethtool_drvinfo *drvinfo)
-{
-	struct pasemi_mac *mac;
-	mac = netdev_priv(netdev);
-
-	/* clear and fill out info */
-	memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
-	strncpy(drvinfo->driver, "pasemi_mac", 12);
-	strcpy(drvinfo->version, "N/A");
-	strcpy(drvinfo->fw_version, "N/A");
-	strncpy(drvinfo->bus_info, pci_name(mac->pdev), 32);
-}
-
 static u32
 pasemi_mac_ethtool_get_msglevel(struct net_device *netdev)
 {
@@ -164,7 +149,6 @@
 const struct ethtool_ops pasemi_mac_ethtool_ops = {
 	.get_settings		= pasemi_mac_ethtool_get_settings,
 	.set_settings		= pasemi_mac_ethtool_set_settings,
-	.get_drvinfo		= pasemi_mac_ethtool_get_drvinfo,
 	.get_msglevel		= pasemi_mac_ethtool_get_msglevel,
 	.set_msglevel		= pasemi_mac_ethtool_set_msglevel,
 	.get_link		= ethtool_op_get_link,
diff --git a/drivers/net/pch_gbe/Makefile b/drivers/net/pch_gbe/Makefile
new file mode 100644
index 0000000..31288d4
--- /dev/null
+++ b/drivers/net/pch_gbe/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_PCH_GBE) += pch_gbe.o
+
+pch_gbe-y := pch_gbe_phy.o pch_gbe_ethtool.o pch_gbe_param.o
+pch_gbe-y += pch_gbe_api.o pch_gbe_main.o
diff --git a/drivers/net/pch_gbe/pch_gbe.h b/drivers/net/pch_gbe/pch_gbe.h
new file mode 100644
index 0000000..a0c26a9
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe.h
@@ -0,0 +1,659 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux 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; 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 _PCH_GBE_H_
+#define _PCH_GBE_H_
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/mii.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/vmalloc.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+
+/**
+ * pch_gbe_regs_mac_adr - Structure holding values of mac address registers
+ * @high	Denotes the 1st to 4th byte from the initial of MAC address
+ * @low		Denotes the 5th to 6th byte from the initial of MAC address
+ */
+struct pch_gbe_regs_mac_adr {
+	u32 high;
+	u32 low;
+};
+/**
+ * pch_udc_regs - Structure holding values of MAC registers
+ */
+struct pch_gbe_regs {
+	u32 INT_ST;
+	u32 INT_EN;
+	u32 MODE;
+	u32 RESET;
+	u32 TCPIP_ACC;
+	u32 EX_LIST;
+	u32 INT_ST_HOLD;
+	u32 PHY_INT_CTRL;
+	u32 MAC_RX_EN;
+	u32 RX_FCTRL;
+	u32 PAUSE_REQ;
+	u32 RX_MODE;
+	u32 TX_MODE;
+	u32 RX_FIFO_ST;
+	u32 TX_FIFO_ST;
+	u32 TX_FID;
+	u32 TX_RESULT;
+	u32 PAUSE_PKT1;
+	u32 PAUSE_PKT2;
+	u32 PAUSE_PKT3;
+	u32 PAUSE_PKT4;
+	u32 PAUSE_PKT5;
+	u32 reserve[2];
+	struct pch_gbe_regs_mac_adr mac_adr[16];
+	u32 ADDR_MASK;
+	u32 MIIM;
+	u32 reserve2;
+	u32 RGMII_ST;
+	u32 RGMII_CTRL;
+	u32 reserve3[3];
+	u32 DMA_CTRL;
+	u32 reserve4[3];
+	u32 RX_DSC_BASE;
+	u32 RX_DSC_SIZE;
+	u32 RX_DSC_HW_P;
+	u32 RX_DSC_HW_P_HLD;
+	u32 RX_DSC_SW_P;
+	u32 reserve5[3];
+	u32 TX_DSC_BASE;
+	u32 TX_DSC_SIZE;
+	u32 TX_DSC_HW_P;
+	u32 TX_DSC_HW_P_HLD;
+	u32 TX_DSC_SW_P;
+	u32 reserve6[3];
+	u32 RX_DMA_ST;
+	u32 TX_DMA_ST;
+	u32 reserve7[2];
+	u32 WOL_ST;
+	u32 WOL_CTRL;
+	u32 WOL_ADDR_MASK;
+};
+
+/* Interrupt Status */
+/* Interrupt Status Hold */
+/* Interrupt Enable */
+#define PCH_GBE_INT_RX_DMA_CMPLT  0x00000001 /* Receive DMA Transfer Complete */
+#define PCH_GBE_INT_RX_VALID      0x00000002 /* MAC Normal Receive Complete */
+#define PCH_GBE_INT_RX_FRAME_ERR  0x00000004 /* Receive frame error */
+#define PCH_GBE_INT_RX_FIFO_ERR   0x00000008 /* Receive FIFO Overflow */
+#define PCH_GBE_INT_RX_DMA_ERR    0x00000010 /* Receive DMA Transfer Error */
+#define PCH_GBE_INT_RX_DSC_EMP    0x00000020 /* Receive Descriptor Empty */
+#define PCH_GBE_INT_TX_CMPLT      0x00000100 /* MAC Transmission Complete */
+#define PCH_GBE_INT_TX_DMA_CMPLT  0x00000200 /* DMA Transfer Complete */
+#define PCH_GBE_INT_TX_FIFO_ERR   0x00000400 /* Transmission FIFO underflow. */
+#define PCH_GBE_INT_TX_DMA_ERR    0x00000800 /* Transmission DMA Error */
+#define PCH_GBE_INT_PAUSE_CMPLT   0x00001000 /* Pause Transmission complete */
+#define PCH_GBE_INT_MIIM_CMPLT    0x00010000 /* MIIM I/F Read completion */
+#define PCH_GBE_INT_PHY_INT       0x00100000 /* Interruption from PHY */
+#define PCH_GBE_INT_WOL_DET       0x01000000 /* Wake On LAN Event detection. */
+#define PCH_GBE_INT_TCPIP_ERR     0x10000000 /* TCP/IP Accelerator Error */
+
+/* Mode */
+#define PCH_GBE_MODE_MII_ETHER      0x00000000  /* GIGA Ethernet Mode [MII] */
+#define PCH_GBE_MODE_GMII_ETHER     0x80000000  /* GIGA Ethernet Mode [GMII] */
+#define PCH_GBE_MODE_HALF_DUPLEX    0x00000000  /* Duplex Mode [half duplex] */
+#define PCH_GBE_MODE_FULL_DUPLEX    0x40000000  /* Duplex Mode [full duplex] */
+#define PCH_GBE_MODE_FR_BST         0x04000000  /* Frame bursting is done */
+
+/* Reset */
+#define PCH_GBE_ALL_RST         0x80000000  /* All reset */
+#define PCH_GBE_TX_RST          0x40000000  /* TX MAC, TX FIFO, TX DMA reset */
+#define PCH_GBE_RX_RST          0x04000000  /* RX MAC, RX FIFO, RX DMA reset */
+
+/* TCP/IP Accelerator Control */
+#define PCH_GBE_EX_LIST_EN      0x00000008  /* External List Enable */
+#define PCH_GBE_RX_TCPIPACC_OFF 0x00000004  /* RX TCP/IP ACC Disabled */
+#define PCH_GBE_TX_TCPIPACC_EN  0x00000002  /* TX TCP/IP ACC Enable */
+#define PCH_GBE_RX_TCPIPACC_EN  0x00000001  /* RX TCP/IP ACC Enable */
+
+/* MAC RX Enable */
+#define PCH_GBE_MRE_MAC_RX_EN   0x00000001      /* MAC Receive Enable */
+
+/* RX Flow Control */
+#define PCH_GBE_FL_CTRL_EN      0x80000000  /* Pause packet is enabled */
+
+/* Pause Packet Request */
+#define PCH_GBE_PS_PKT_RQ       0x80000000  /* Pause packet Request */
+
+/* RX Mode */
+#define PCH_GBE_ADD_FIL_EN      0x80000000  /* Address Filtering Enable */
+/* Multicast Filtering Enable */
+#define PCH_GBE_MLT_FIL_EN      0x40000000
+/* Receive Almost Empty Threshold */
+#define PCH_GBE_RH_ALM_EMP_4    0x00000000      /* 4 words */
+#define PCH_GBE_RH_ALM_EMP_8    0x00004000      /* 8 words */
+#define PCH_GBE_RH_ALM_EMP_16   0x00008000      /* 16 words */
+#define PCH_GBE_RH_ALM_EMP_32   0x0000C000      /* 32 words */
+/* Receive Almost Full Threshold */
+#define PCH_GBE_RH_ALM_FULL_4   0x00000000      /* 4 words */
+#define PCH_GBE_RH_ALM_FULL_8   0x00001000      /* 8 words */
+#define PCH_GBE_RH_ALM_FULL_16  0x00002000      /* 16 words */
+#define PCH_GBE_RH_ALM_FULL_32  0x00003000      /* 32 words */
+/* RX FIFO Read Triger Threshold */
+#define PCH_GBE_RH_RD_TRG_4     0x00000000      /* 4 words */
+#define PCH_GBE_RH_RD_TRG_8     0x00000200      /* 8 words */
+#define PCH_GBE_RH_RD_TRG_16    0x00000400      /* 16 words */
+#define PCH_GBE_RH_RD_TRG_32    0x00000600      /* 32 words */
+#define PCH_GBE_RH_RD_TRG_64    0x00000800      /* 64 words */
+#define PCH_GBE_RH_RD_TRG_128   0x00000A00      /* 128 words */
+#define PCH_GBE_RH_RD_TRG_256   0x00000C00      /* 256 words */
+#define PCH_GBE_RH_RD_TRG_512   0x00000E00      /* 512 words */
+
+/* Receive Descriptor bit definitions */
+#define PCH_GBE_RXD_ACC_STAT_BCAST          0x00000400
+#define PCH_GBE_RXD_ACC_STAT_MCAST          0x00000200
+#define PCH_GBE_RXD_ACC_STAT_UCAST          0x00000100
+#define PCH_GBE_RXD_ACC_STAT_TCPIPOK        0x000000C0
+#define PCH_GBE_RXD_ACC_STAT_IPOK           0x00000080
+#define PCH_GBE_RXD_ACC_STAT_TCPOK          0x00000040
+#define PCH_GBE_RXD_ACC_STAT_IP6ERR         0x00000020
+#define PCH_GBE_RXD_ACC_STAT_OFLIST         0x00000010
+#define PCH_GBE_RXD_ACC_STAT_TYPEIP         0x00000008
+#define PCH_GBE_RXD_ACC_STAT_MACL           0x00000004
+#define PCH_GBE_RXD_ACC_STAT_PPPOE          0x00000002
+#define PCH_GBE_RXD_ACC_STAT_VTAGT          0x00000001
+#define PCH_GBE_RXD_GMAC_STAT_PAUSE         0x0200
+#define PCH_GBE_RXD_GMAC_STAT_MARBR         0x0100
+#define PCH_GBE_RXD_GMAC_STAT_MARMLT        0x0080
+#define PCH_GBE_RXD_GMAC_STAT_MARIND        0x0040
+#define PCH_GBE_RXD_GMAC_STAT_MARNOTMT      0x0020
+#define PCH_GBE_RXD_GMAC_STAT_TLONG         0x0010
+#define PCH_GBE_RXD_GMAC_STAT_TSHRT         0x0008
+#define PCH_GBE_RXD_GMAC_STAT_NOTOCTAL      0x0004
+#define PCH_GBE_RXD_GMAC_STAT_NBLERR        0x0002
+#define PCH_GBE_RXD_GMAC_STAT_CRCERR        0x0001
+
+/* Transmit Descriptor bit definitions */
+#define PCH_GBE_TXD_CTRL_TCPIP_ACC_OFF      0x0008
+#define PCH_GBE_TXD_CTRL_ITAG               0x0004
+#define PCH_GBE_TXD_CTRL_ICRC               0x0002
+#define PCH_GBE_TXD_CTRL_APAD               0x0001
+#define PCH_GBE_TXD_WORDS_SHIFT             2
+#define PCH_GBE_TXD_GMAC_STAT_CMPLT         0x2000
+#define PCH_GBE_TXD_GMAC_STAT_ABT           0x1000
+#define PCH_GBE_TXD_GMAC_STAT_EXCOL         0x0800
+#define PCH_GBE_TXD_GMAC_STAT_SNGCOL        0x0400
+#define PCH_GBE_TXD_GMAC_STAT_MLTCOL        0x0200
+#define PCH_GBE_TXD_GMAC_STAT_CRSER         0x0100
+#define PCH_GBE_TXD_GMAC_STAT_TLNG          0x0080
+#define PCH_GBE_TXD_GMAC_STAT_TSHRT         0x0040
+#define PCH_GBE_TXD_GMAC_STAT_LTCOL         0x0020
+#define PCH_GBE_TXD_GMAC_STAT_TFUNDFLW      0x0010
+#define PCH_GBE_TXD_GMAC_STAT_RTYCNT_MASK   0x000F
+
+/* TX Mode */
+#define PCH_GBE_TM_NO_RTRY     0x80000000 /* No Retransmission */
+#define PCH_GBE_TM_LONG_PKT    0x40000000 /* Long Packt TX Enable */
+#define PCH_GBE_TM_ST_AND_FD   0x20000000 /* Stare and Forward */
+#define PCH_GBE_TM_SHORT_PKT   0x10000000 /* Short Packet TX Enable */
+#define PCH_GBE_TM_LTCOL_RETX  0x08000000 /* Retransmission at Late Collision */
+/* Frame Start Threshold */
+#define PCH_GBE_TM_TH_TX_STRT_4    0x00000000    /* 4 words */
+#define PCH_GBE_TM_TH_TX_STRT_8    0x00004000    /* 8 words */
+#define PCH_GBE_TM_TH_TX_STRT_16   0x00008000    /* 16 words */
+#define PCH_GBE_TM_TH_TX_STRT_32   0x0000C000    /* 32 words */
+/* Transmit Almost Empty Threshold */
+#define PCH_GBE_TM_TH_ALM_EMP_4    0x00000000    /* 4 words */
+#define PCH_GBE_TM_TH_ALM_EMP_8    0x00000800    /* 8 words */
+#define PCH_GBE_TM_TH_ALM_EMP_16   0x00001000    /* 16 words */
+#define PCH_GBE_TM_TH_ALM_EMP_32   0x00001800    /* 32 words */
+#define PCH_GBE_TM_TH_ALM_EMP_64   0x00002000    /* 64 words */
+#define PCH_GBE_TM_TH_ALM_EMP_128  0x00002800    /* 128 words */
+#define PCH_GBE_TM_TH_ALM_EMP_256  0x00003000    /* 256 words */
+#define PCH_GBE_TM_TH_ALM_EMP_512  0x00003800    /* 512 words */
+/* Transmit Almost Full Threshold */
+#define PCH_GBE_TM_TH_ALM_FULL_4   0x00000000    /* 4 words */
+#define PCH_GBE_TM_TH_ALM_FULL_8   0x00000200    /* 8 words */
+#define PCH_GBE_TM_TH_ALM_FULL_16  0x00000400    /* 16 words */
+#define PCH_GBE_TM_TH_ALM_FULL_32  0x00000600    /* 32 words */
+
+/* RX FIFO Status */
+#define PCH_GBE_RF_ALM_FULL     0x80000000  /* RX FIFO is almost full. */
+#define PCH_GBE_RF_ALM_EMP      0x40000000  /* RX FIFO is almost empty. */
+#define PCH_GBE_RF_RD_TRG       0x20000000  /* Become more than RH_RD_TRG. */
+#define PCH_GBE_RF_STRWD        0x1FFE0000  /* The word count of RX FIFO. */
+#define PCH_GBE_RF_RCVING       0x00010000  /* Stored in RX FIFO. */
+
+/* MAC Address Mask */
+#define PCH_GBE_BUSY                0x80000000
+
+/* MIIM  */
+#define PCH_GBE_MIIM_OPER_WRITE     0x04000000
+#define PCH_GBE_MIIM_OPER_READ      0x00000000
+#define PCH_GBE_MIIM_OPER_READY     0x04000000
+#define PCH_GBE_MIIM_PHY_ADDR_SHIFT 21
+#define PCH_GBE_MIIM_REG_ADDR_SHIFT 16
+
+/* RGMII Status */
+#define PCH_GBE_LINK_UP             0x80000008
+#define PCH_GBE_RXC_SPEED_MSK       0x00000006
+#define PCH_GBE_RXC_SPEED_2_5M      0x00000000    /* 2.5MHz */
+#define PCH_GBE_RXC_SPEED_25M       0x00000002    /* 25MHz  */
+#define PCH_GBE_RXC_SPEED_125M      0x00000004    /* 100MHz */
+#define PCH_GBE_DUPLEX_FULL         0x00000001
+
+/* RGMII Control */
+#define PCH_GBE_CRS_SEL             0x00000010
+#define PCH_GBE_RGMII_RATE_125M     0x00000000
+#define PCH_GBE_RGMII_RATE_25M      0x00000008
+#define PCH_GBE_RGMII_RATE_2_5M     0x0000000C
+#define PCH_GBE_RGMII_MODE_GMII     0x00000000
+#define PCH_GBE_RGMII_MODE_RGMII    0x00000002
+#define PCH_GBE_CHIP_TYPE_EXTERNAL  0x00000000
+#define PCH_GBE_CHIP_TYPE_INTERNAL  0x00000001
+
+/* DMA Control */
+#define PCH_GBE_RX_DMA_EN       0x00000002   /* Enables Receive DMA */
+#define PCH_GBE_TX_DMA_EN       0x00000001   /* Enables Transmission DMA */
+
+/* Wake On LAN Status */
+#define PCH_GBE_WLS_BR          0x00000008 /* Broadcas Address */
+#define PCH_GBE_WLS_MLT         0x00000004 /* Multicast Address */
+
+/* The Frame registered in Address Recognizer */
+#define PCH_GBE_WLS_IND         0x00000002
+#define PCH_GBE_WLS_MP          0x00000001 /* Magic packet Address */
+
+/* Wake On LAN Control */
+#define PCH_GBE_WLC_WOL_MODE    0x00010000
+#define PCH_GBE_WLC_IGN_TLONG   0x00000100
+#define PCH_GBE_WLC_IGN_TSHRT   0x00000080
+#define PCH_GBE_WLC_IGN_OCTER   0x00000040
+#define PCH_GBE_WLC_IGN_NBLER   0x00000020
+#define PCH_GBE_WLC_IGN_CRCER   0x00000010
+#define PCH_GBE_WLC_BR          0x00000008
+#define PCH_GBE_WLC_MLT         0x00000004
+#define PCH_GBE_WLC_IND         0x00000002
+#define PCH_GBE_WLC_MP          0x00000001
+
+/* Wake On LAN Address Mask */
+#define PCH_GBE_WLA_BUSY        0x80000000
+
+
+
+/* TX/RX descriptor defines */
+#define PCH_GBE_MAX_TXD                     4096
+#define PCH_GBE_DEFAULT_TXD                  256
+#define PCH_GBE_MIN_TXD                        8
+#define PCH_GBE_MAX_RXD                     4096
+#define PCH_GBE_DEFAULT_RXD                  256
+#define PCH_GBE_MIN_RXD                        8
+
+/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
+#define PCH_GBE_TX_DESC_MULTIPLE               8
+#define PCH_GBE_RX_DESC_MULTIPLE               8
+
+/* Read/Write operation is done through MII Management IF */
+#define PCH_GBE_HAL_MIIM_READ          ((u32)0x00000000)
+#define PCH_GBE_HAL_MIIM_WRITE         ((u32)0x04000000)
+
+/* flow control values */
+#define PCH_GBE_FC_NONE			0
+#define PCH_GBE_FC_RX_PAUSE		1
+#define PCH_GBE_FC_TX_PAUSE		2
+#define PCH_GBE_FC_FULL			3
+#define PCH_GBE_FC_DEFAULT		PCH_GBE_FC_FULL
+
+
+struct pch_gbe_hw;
+/**
+ * struct  pch_gbe_functions - HAL APi function pointer
+ * @get_bus_info:	for pch_gbe_hal_get_bus_info
+ * @init_hw:		for pch_gbe_hal_init_hw
+ * @read_phy_reg:	for pch_gbe_hal_read_phy_reg
+ * @write_phy_reg:	for pch_gbe_hal_write_phy_reg
+ * @reset_phy:		for pch_gbe_hal_phy_hw_reset
+ * @sw_reset_phy:	for pch_gbe_hal_phy_sw_reset
+ * @power_up_phy:	for pch_gbe_hal_power_up_phy
+ * @power_down_phy:	for pch_gbe_hal_power_down_phy
+ * @read_mac_addr:	for pch_gbe_hal_read_mac_addr
+ */
+struct pch_gbe_functions {
+	void (*get_bus_info) (struct pch_gbe_hw *);
+	s32 (*init_hw) (struct pch_gbe_hw *);
+	s32 (*read_phy_reg) (struct pch_gbe_hw *, u32, u16 *);
+	s32 (*write_phy_reg) (struct pch_gbe_hw *, u32, u16);
+	void (*reset_phy) (struct pch_gbe_hw *);
+	void (*sw_reset_phy) (struct pch_gbe_hw *);
+	void (*power_up_phy) (struct pch_gbe_hw *hw);
+	void (*power_down_phy) (struct pch_gbe_hw *hw);
+	s32 (*read_mac_addr) (struct pch_gbe_hw *);
+};
+
+/**
+ * struct pch_gbe_mac_info - MAC infomation
+ * @addr[6]:		Store the MAC address
+ * @fc:			Mode of flow control
+ * @fc_autoneg:		Auto negotiation enable for flow control setting
+ * @tx_fc_enable:	Enable flag of Transmit flow control
+ * @max_frame_size:	Max transmit frame size
+ * @min_frame_size:	Min transmit frame size
+ * @autoneg:		Auto negotiation enable
+ * @link_speed:		Link speed
+ * @link_duplex:	Link duplex
+ */
+struct pch_gbe_mac_info {
+	u8 addr[6];
+	u8 fc;
+	u8 fc_autoneg;
+	u8 tx_fc_enable;
+	u32 max_frame_size;
+	u32 min_frame_size;
+	u8 autoneg;
+	u16 link_speed;
+	u16 link_duplex;
+};
+
+/**
+ * struct pch_gbe_phy_info - PHY infomation
+ * @addr:		PHY address
+ * @id:			PHY's identifier
+ * @revision:		PHY's revision
+ * @reset_delay_us:	HW reset delay time[us]
+ * @autoneg_advertised:	Autoneg advertised
+ */
+struct pch_gbe_phy_info {
+	u32 addr;
+	u32 id;
+	u32 revision;
+	u32 reset_delay_us;
+	u16 autoneg_advertised;
+};
+
+/*!
+ * @ingroup Gigabit Ether driver Layer
+ * @struct  pch_gbe_bus_info
+ * @brief   Bus infomation
+ */
+struct pch_gbe_bus_info {
+	u8 type;
+	u8 speed;
+	u8 width;
+};
+
+/*!
+ * @ingroup Gigabit Ether driver Layer
+ * @struct  pch_gbe_hw
+ * @brief   Hardware infomation
+ */
+struct pch_gbe_hw {
+	void *back;
+
+	struct pch_gbe_regs  __iomem *reg;
+	spinlock_t miim_lock;
+
+	const struct pch_gbe_functions *func;
+	struct pch_gbe_mac_info mac;
+	struct pch_gbe_phy_info phy;
+	struct pch_gbe_bus_info bus;
+};
+
+/**
+ * struct pch_gbe_rx_desc - Receive Descriptor
+ * @buffer_addr:	RX Frame Buffer Address
+ * @tcp_ip_status:	TCP/IP Accelerator Status
+ * @rx_words_eob:	RX word count and Byte position
+ * @gbec_status:	GMAC Status
+ * @dma_status:		DMA Status
+ * @reserved1:		Reserved
+ * @reserved2:		Reserved
+ */
+struct pch_gbe_rx_desc {
+	u32 buffer_addr;
+	u32 tcp_ip_status;
+	u16 rx_words_eob;
+	u16 gbec_status;
+	u8 dma_status;
+	u8 reserved1;
+	u16 reserved2;
+};
+
+/**
+ * struct pch_gbe_tx_desc - Transmit Descriptor
+ * @buffer_addr:	TX Frame Buffer Address
+ * @length:		Data buffer length
+ * @reserved1:		Reserved
+ * @tx_words_eob:	TX word count and Byte position
+ * @tx_frame_ctrl:	TX Frame Control
+ * @dma_status:		DMA Status
+ * @reserved2:		Reserved
+ * @gbec_status:	GMAC Status
+ */
+struct pch_gbe_tx_desc {
+	u32 buffer_addr;
+	u16 length;
+	u16 reserved1;
+	u16 tx_words_eob;
+	u16 tx_frame_ctrl;
+	u8 dma_status;
+	u8 reserved2;
+	u16 gbec_status;
+};
+
+
+/**
+ * struct pch_gbe_buffer - Buffer infomation
+ * @skb:	pointer to a socket buffer
+ * @dma:	DMA address
+ * @time_stamp:	time stamp
+ * @length:	data size
+ */
+struct pch_gbe_buffer {
+	struct sk_buff *skb;
+	dma_addr_t dma;
+	unsigned long time_stamp;
+	u16 length;
+	bool mapped;
+};
+
+/**
+ * struct pch_gbe_tx_ring - tx ring infomation
+ * @tx_lock:	spinlock structs
+ * @desc:	pointer to the descriptor ring memory
+ * @dma:	physical address of the descriptor ring
+ * @size:	length of descriptor ring in bytes
+ * @count:	number of descriptors in the ring
+ * @next_to_use:	next descriptor to associate a buffer with
+ * @next_to_clean:	next descriptor to check for DD status bit
+ * @buffer_info:	array of buffer information structs
+ */
+struct pch_gbe_tx_ring {
+	spinlock_t tx_lock;
+	struct pch_gbe_tx_desc *desc;
+	dma_addr_t dma;
+	unsigned int size;
+	unsigned int count;
+	unsigned int next_to_use;
+	unsigned int next_to_clean;
+	struct pch_gbe_buffer *buffer_info;
+};
+
+/**
+ * struct pch_gbe_rx_ring - rx ring infomation
+ * @desc:	pointer to the descriptor ring memory
+ * @dma:	physical address of the descriptor ring
+ * @size:	length of descriptor ring in bytes
+ * @count:	number of descriptors in the ring
+ * @next_to_use:	next descriptor to associate a buffer with
+ * @next_to_clean:	next descriptor to check for DD status bit
+ * @buffer_info:	array of buffer information structs
+ */
+struct pch_gbe_rx_ring {
+	struct pch_gbe_rx_desc *desc;
+	dma_addr_t dma;
+	unsigned int size;
+	unsigned int count;
+	unsigned int next_to_use;
+	unsigned int next_to_clean;
+	struct pch_gbe_buffer *buffer_info;
+};
+
+/**
+ * struct pch_gbe_hw_stats - Statistics counters collected by the MAC
+ * @rx_packets:		    total packets received
+ * @tx_packets:		    total packets transmitted
+ * @rx_bytes:		    total bytes received
+ * @tx_bytes:		    total bytes transmitted
+ * @rx_errors:		    bad packets received
+ * @tx_errors:		    packet transmit problems
+ * @rx_dropped:		    no space in Linux buffers
+ * @tx_dropped:		    no space available in Linux
+ * @multicast:		    multicast packets received
+ * @collisions:		    collisions
+ * @rx_crc_errors:	    received packet with crc error
+ * @rx_frame_errors:	    received frame alignment error
+ * @rx_alloc_buff_failed:   allocate failure of a receive buffer
+ * @tx_length_errors:	    transmit length error
+ * @tx_aborted_errors:	    transmit aborted error
+ * @tx_carrier_errors:	    transmit carrier error
+ * @tx_timeout_count:	    Number of transmit timeout
+ * @tx_restart_count:	    Number of transmit restert
+ * @intr_rx_dsc_empty_count:	Interrupt count of receive descriptor empty
+ * @intr_rx_frame_err_count:	Interrupt count of receive frame error
+ * @intr_rx_fifo_err_count:	Interrupt count of receive FIFO error
+ * @intr_rx_dma_err_count:	Interrupt count of receive DMA error
+ * @intr_tx_fifo_err_count:	Interrupt count of transmit FIFO error
+ * @intr_tx_dma_err_count:	Interrupt count of transmit DMA error
+ * @intr_tcpip_err_count:	Interrupt count of TCP/IP Accelerator
+ */
+struct pch_gbe_hw_stats {
+	u32 rx_packets;
+	u32 tx_packets;
+	u32 rx_bytes;
+	u32 tx_bytes;
+	u32 rx_errors;
+	u32 tx_errors;
+	u32 rx_dropped;
+	u32 tx_dropped;
+	u32 multicast;
+	u32 collisions;
+	u32 rx_crc_errors;
+	u32 rx_frame_errors;
+	u32 rx_alloc_buff_failed;
+	u32 tx_length_errors;
+	u32 tx_aborted_errors;
+	u32 tx_carrier_errors;
+	u32 tx_timeout_count;
+	u32 tx_restart_count;
+	u32 intr_rx_dsc_empty_count;
+	u32 intr_rx_frame_err_count;
+	u32 intr_rx_fifo_err_count;
+	u32 intr_rx_dma_err_count;
+	u32 intr_tx_fifo_err_count;
+	u32 intr_tx_dma_err_count;
+	u32 intr_tcpip_err_count;
+};
+
+/**
+ * struct pch_gbe_adapter - board specific private data structure
+ * @stats_lock:	Spinlock structure for status
+ * @tx_queue_lock:	Spinlock structure for transmit
+ * @ethtool_lock:	Spinlock structure for ethtool
+ * @irq_sem:		Semaphore for interrupt
+ * @netdev:		Pointer of network device structure
+ * @pdev:		Pointer of pci device structure
+ * @polling_netdev:	Pointer of polling network device structure
+ * @napi:		NAPI structure
+ * @hw:			Pointer of hardware structure
+ * @stats:		Hardware status
+ * @reset_task:		Reset task
+ * @mii:		MII information structure
+ * @watchdog_timer:	Watchdog timer list
+ * @wake_up_evt:	Wake up event
+ * @config_space:	Configuration space
+ * @msg_enable:		Driver message level
+ * @led_status:		LED status
+ * @tx_ring:		Pointer of Tx descriptor ring structure
+ * @rx_ring:		Pointer of Rx descriptor ring structure
+ * @rx_buffer_len:	Receive buffer length
+ * @tx_queue_len:	Transmit queue length
+ * @rx_csum:		Receive TCP/IP checksum enable/disable
+ * @tx_csum:		Transmit TCP/IP checksum enable/disable
+ * @have_msi:		PCI MSI mode flag
+ */
+
+struct pch_gbe_adapter {
+	spinlock_t stats_lock;
+	spinlock_t tx_queue_lock;
+	spinlock_t ethtool_lock;
+	atomic_t irq_sem;
+	struct net_device *netdev;
+	struct pci_dev *pdev;
+	struct net_device *polling_netdev;
+	struct napi_struct napi;
+	struct pch_gbe_hw hw;
+	struct pch_gbe_hw_stats stats;
+	struct work_struct reset_task;
+	struct mii_if_info mii;
+	struct timer_list watchdog_timer;
+	u32 wake_up_evt;
+	u32 *config_space;
+	unsigned long led_status;
+	struct pch_gbe_tx_ring *tx_ring;
+	struct pch_gbe_rx_ring *rx_ring;
+	unsigned long rx_buffer_len;
+	unsigned long tx_queue_len;
+	bool rx_csum;
+	bool tx_csum;
+	bool have_msi;
+};
+
+extern const char pch_driver_version[];
+
+/* pch_gbe_main.c */
+extern int pch_gbe_up(struct pch_gbe_adapter *adapter);
+extern void pch_gbe_down(struct pch_gbe_adapter *adapter);
+extern void pch_gbe_reinit_locked(struct pch_gbe_adapter *adapter);
+extern void pch_gbe_reset(struct pch_gbe_adapter *adapter);
+extern int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
+				       struct pch_gbe_tx_ring *txdr);
+extern int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
+				       struct pch_gbe_rx_ring *rxdr);
+extern void pch_gbe_free_tx_resources(struct pch_gbe_adapter *adapter,
+				       struct pch_gbe_tx_ring *tx_ring);
+extern void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter,
+				       struct pch_gbe_rx_ring *rx_ring);
+extern void pch_gbe_update_stats(struct pch_gbe_adapter *adapter);
+
+/* pch_gbe_param.c */
+extern void pch_gbe_check_options(struct pch_gbe_adapter *adapter);
+
+/* pch_gbe_ethtool.c */
+extern void pch_gbe_set_ethtool_ops(struct net_device *netdev);
+
+/* pch_gbe_mac.c */
+extern s32 pch_gbe_mac_force_mac_fc(struct pch_gbe_hw *hw);
+extern s32 pch_gbe_mac_read_mac_addr(struct pch_gbe_hw *hw);
+extern u16 pch_gbe_mac_ctrl_miim(struct pch_gbe_hw *hw,
+				  u32 addr, u32 dir, u32 reg, u16 data);
+#endif /* _PCH_GBE_H_ */
diff --git a/drivers/net/pch_gbe/pch_gbe_api.c b/drivers/net/pch_gbe/pch_gbe_api.c
new file mode 100644
index 0000000..e48f084
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_api.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include "pch_gbe.h"
+#include "pch_gbe_phy.h"
+
+/* bus type values */
+#define pch_gbe_bus_type_unknown	0
+#define pch_gbe_bus_type_pci		1
+#define pch_gbe_bus_type_pcix		2
+#define pch_gbe_bus_type_pci_express	3
+#define pch_gbe_bus_type_reserved	4
+
+/* bus speed values */
+#define pch_gbe_bus_speed_unknown	0
+#define pch_gbe_bus_speed_33		1
+#define pch_gbe_bus_speed_66		2
+#define pch_gbe_bus_speed_100		3
+#define pch_gbe_bus_speed_120		4
+#define pch_gbe_bus_speed_133		5
+#define pch_gbe_bus_speed_2500		6
+#define pch_gbe_bus_speed_reserved	7
+
+/* bus width values */
+#define pch_gbe_bus_width_unknown	0
+#define pch_gbe_bus_width_pcie_x1	1
+#define pch_gbe_bus_width_pcie_x2	2
+#define pch_gbe_bus_width_pcie_x4	4
+#define pch_gbe_bus_width_32		5
+#define pch_gbe_bus_width_64		6
+#define pch_gbe_bus_width_reserved	7
+
+/**
+ * pch_gbe_plat_get_bus_info - Obtain bus information for adapter
+ * @hw:	Pointer to the HW structure
+ */
+static void pch_gbe_plat_get_bus_info(struct pch_gbe_hw *hw)
+{
+	hw->bus.type  = pch_gbe_bus_type_pci_express;
+	hw->bus.speed = pch_gbe_bus_speed_2500;
+	hw->bus.width = pch_gbe_bus_width_pcie_x1;
+}
+
+/**
+ * pch_gbe_plat_init_hw - Initialize hardware
+ * @hw:	Pointer to the HW structure
+ * Returns
+ *	0:		Successfully
+ *	Negative value:	Failed-EBUSY
+ */
+static s32 pch_gbe_plat_init_hw(struct pch_gbe_hw *hw)
+{
+	s32 ret_val;
+
+	ret_val = pch_gbe_phy_get_id(hw);
+	if (ret_val) {
+		pr_err("pch_gbe_phy_get_id error\n");
+		return ret_val;
+	}
+	pch_gbe_phy_init_setting(hw);
+	/* Setup Mac interface option RGMII */
+#ifdef PCH_GBE_MAC_IFOP_RGMII
+	pch_gbe_phy_set_rgmii(hw);
+#endif
+	return ret_val;
+}
+
+static const struct pch_gbe_functions pch_gbe_ops = {
+	.get_bus_info      = pch_gbe_plat_get_bus_info,
+	.init_hw           = pch_gbe_plat_init_hw,
+	.read_phy_reg      = pch_gbe_phy_read_reg_miic,
+	.write_phy_reg     = pch_gbe_phy_write_reg_miic,
+	.reset_phy         = pch_gbe_phy_hw_reset,
+	.sw_reset_phy      = pch_gbe_phy_sw_reset,
+	.power_up_phy      = pch_gbe_phy_power_up,
+	.power_down_phy    = pch_gbe_phy_power_down,
+	.read_mac_addr     = pch_gbe_mac_read_mac_addr
+};
+
+/**
+ * pch_gbe_plat_init_function_pointers - Init func ptrs
+ * @hw:	Pointer to the HW structure
+ */
+static void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw)
+{
+	/* Set PHY parameter */
+	hw->phy.reset_delay_us     = PCH_GBE_PHY_RESET_DELAY_US;
+	/* Set function pointers */
+	hw->func = &pch_gbe_ops;
+}
+
+/**
+ * pch_gbe_hal_setup_init_funcs - Initializes function pointers
+ * @hw:	Pointer to the HW structure
+ * Returns
+ *	0:	Successfully
+ *	ENOSYS:	Function is not registered
+ */
+inline s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw)
+{
+	if (!hw->reg) {
+		pr_err("ERROR: Registers not mapped\n");
+		return -ENOSYS;
+	}
+	pch_gbe_plat_init_function_pointers(hw);
+	return 0;
+}
+
+/**
+ * pch_gbe_hal_get_bus_info - Obtain bus information for adapter
+ * @hw:	Pointer to the HW structure
+ */
+inline void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw)
+{
+	if (!hw->func->get_bus_info)
+		pr_err("ERROR: configuration\n");
+	else
+		hw->func->get_bus_info(hw);
+}
+
+/**
+ * pch_gbe_hal_init_hw - Initialize hardware
+ * @hw:	Pointer to the HW structure
+ * Returns
+ *	0:	Successfully
+ *	ENOSYS:	Function is not registered
+ */
+inline s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw)
+{
+	if (!hw->func->init_hw) {
+		pr_err("ERROR: configuration\n");
+		return -ENOSYS;
+	}
+	return hw->func->init_hw(hw);
+}
+
+/**
+ * pch_gbe_hal_read_phy_reg - Reads PHY register
+ * @hw:	    Pointer to the HW structure
+ * @offset: The register to read
+ * @data:   The buffer to store the 16-bit read.
+ * Returns
+ *	0:	Successfully
+ *	Negative value:	Failed
+ */
+inline s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset,
+					u16 *data)
+{
+	if (!hw->func->read_phy_reg)
+		return 0;
+	return hw->func->read_phy_reg(hw, offset, data);
+}
+
+/**
+ * pch_gbe_hal_write_phy_reg - Writes PHY register
+ * @hw:	    Pointer to the HW structure
+ * @offset: The register to read
+ * @data:   The value to write.
+ * Returns
+ *	0:	Successfully
+ *	Negative value:	Failed
+ */
+inline s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset,
+					u16 data)
+{
+	if (!hw->func->write_phy_reg)
+		return 0;
+	return hw->func->write_phy_reg(hw, offset, data);
+}
+
+/**
+ * pch_gbe_hal_phy_hw_reset - Hard PHY reset
+ * @hw:	    Pointer to the HW structure
+ */
+inline void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw)
+{
+	if (!hw->func->reset_phy)
+		pr_err("ERROR: configuration\n");
+	else
+		hw->func->reset_phy(hw);
+}
+
+/**
+ * pch_gbe_hal_phy_sw_reset - Soft PHY reset
+ * @hw:	    Pointer to the HW structure
+ */
+inline void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw)
+{
+	if (!hw->func->sw_reset_phy)
+		pr_err("ERROR: configuration\n");
+	else
+		hw->func->sw_reset_phy(hw);
+}
+
+/**
+ * pch_gbe_hal_read_mac_addr - Reads MAC address
+ * @hw:	Pointer to the HW structure
+ * Returns
+ *	0:	Successfully
+ *	ENOSYS:	Function is not registered
+ */
+inline s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw)
+{
+	if (!hw->func->read_mac_addr) {
+		pr_err("ERROR: configuration\n");
+		return -ENOSYS;
+	}
+	return hw->func->read_mac_addr(hw);
+}
+
+/**
+ * pch_gbe_hal_power_up_phy - Power up PHY
+ * @hw:	Pointer to the HW structure
+ */
+inline void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw)
+{
+	if (hw->func->power_up_phy)
+		hw->func->power_up_phy(hw);
+}
+
+/**
+ * pch_gbe_hal_power_down_phy - Power down PHY
+ * @hw:	Pointer to the HW structure
+ */
+inline void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw)
+{
+	if (hw->func->power_down_phy)
+		hw->func->power_down_phy(hw);
+}
diff --git a/drivers/net/pch_gbe/pch_gbe_api.h b/drivers/net/pch_gbe/pch_gbe_api.h
new file mode 100644
index 0000000..94aaac5
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_api.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux 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; 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 _PCH_GBE_API_H_
+#define _PCH_GBE_API_H_
+
+#include "pch_gbe_phy.h"
+
+s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw);
+void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw);
+s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw);
+s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 *data);
+s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 data);
+void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw);
+void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw);
+s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw);
+void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw);
+void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw);
+
+#endif
diff --git a/drivers/net/pch_gbe/pch_gbe_ethtool.c b/drivers/net/pch_gbe/pch_gbe_ethtool.c
new file mode 100644
index 0000000..c8cc32c
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_ethtool.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include "pch_gbe.h"
+#include "pch_gbe_api.h"
+
+/**
+ * pch_gbe_stats - Stats item infomation
+ */
+struct pch_gbe_stats {
+	char string[ETH_GSTRING_LEN];
+	size_t size;
+	size_t offset;
+};
+
+#define PCH_GBE_STAT(m)						\
+{								\
+	.string = #m,						\
+	.size = FIELD_SIZEOF(struct pch_gbe_hw_stats, m),	\
+	.offset = offsetof(struct pch_gbe_hw_stats, m),		\
+}
+
+/**
+ * pch_gbe_gstrings_stats - ethtool information status name list
+ */
+static const struct pch_gbe_stats pch_gbe_gstrings_stats[] = {
+	PCH_GBE_STAT(rx_packets),
+	PCH_GBE_STAT(tx_packets),
+	PCH_GBE_STAT(rx_bytes),
+	PCH_GBE_STAT(tx_bytes),
+	PCH_GBE_STAT(rx_errors),
+	PCH_GBE_STAT(tx_errors),
+	PCH_GBE_STAT(rx_dropped),
+	PCH_GBE_STAT(tx_dropped),
+	PCH_GBE_STAT(multicast),
+	PCH_GBE_STAT(collisions),
+	PCH_GBE_STAT(rx_crc_errors),
+	PCH_GBE_STAT(rx_frame_errors),
+	PCH_GBE_STAT(rx_alloc_buff_failed),
+	PCH_GBE_STAT(tx_length_errors),
+	PCH_GBE_STAT(tx_aborted_errors),
+	PCH_GBE_STAT(tx_carrier_errors),
+	PCH_GBE_STAT(tx_timeout_count),
+	PCH_GBE_STAT(tx_restart_count),
+	PCH_GBE_STAT(intr_rx_dsc_empty_count),
+	PCH_GBE_STAT(intr_rx_frame_err_count),
+	PCH_GBE_STAT(intr_rx_fifo_err_count),
+	PCH_GBE_STAT(intr_rx_dma_err_count),
+	PCH_GBE_STAT(intr_tx_fifo_err_count),
+	PCH_GBE_STAT(intr_tx_dma_err_count),
+	PCH_GBE_STAT(intr_tcpip_err_count)
+};
+
+#define PCH_GBE_QUEUE_STATS_LEN 0
+#define PCH_GBE_GLOBAL_STATS_LEN	ARRAY_SIZE(pch_gbe_gstrings_stats)
+#define PCH_GBE_STATS_LEN (PCH_GBE_GLOBAL_STATS_LEN + PCH_GBE_QUEUE_STATS_LEN)
+
+#define PCH_GBE_MAC_REGS_LEN    (sizeof(struct pch_gbe_regs) / 4)
+#define PCH_GBE_REGS_LEN        (PCH_GBE_MAC_REGS_LEN + PCH_GBE_PHY_REGS_LEN)
+/**
+ * pch_gbe_get_settings - Get device-specific settings
+ * @netdev: Network interface device structure
+ * @ecmd:   Ethtool command
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+static int pch_gbe_get_settings(struct net_device *netdev,
+				 struct ethtool_cmd *ecmd)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	int ret;
+
+	ret = mii_ethtool_gset(&adapter->mii, ecmd);
+	ecmd->supported &= ~(SUPPORTED_TP | SUPPORTED_1000baseT_Half);
+	ecmd->advertising &= ~(ADVERTISED_TP | ADVERTISED_1000baseT_Half);
+
+	if (!netif_carrier_ok(adapter->netdev))
+		ecmd->speed = -1;
+	return ret;
+}
+
+/**
+ * pch_gbe_set_settings - Set device-specific settings
+ * @netdev: Network interface device structure
+ * @ecmd:   Ethtool command
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+static int pch_gbe_set_settings(struct net_device *netdev,
+				 struct ethtool_cmd *ecmd)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+	int ret;
+
+	pch_gbe_hal_write_phy_reg(hw, MII_BMCR, BMCR_RESET);
+
+	if (ecmd->speed == USHRT_MAX) {
+		ecmd->speed = SPEED_1000;
+		ecmd->duplex = DUPLEX_FULL;
+	}
+	ret = mii_ethtool_sset(&adapter->mii, ecmd);
+	if (ret) {
+		pr_err("Error: mii_ethtool_sset\n");
+		return ret;
+	}
+	hw->mac.link_speed = ecmd->speed;
+	hw->mac.link_duplex = ecmd->duplex;
+	hw->phy.autoneg_advertised = ecmd->advertising;
+	hw->mac.autoneg = ecmd->autoneg;
+	pch_gbe_hal_phy_sw_reset(hw);
+
+	/* reset the link */
+	if (netif_running(adapter->netdev)) {
+		pch_gbe_down(adapter);
+		ret = pch_gbe_up(adapter);
+	} else {
+		pch_gbe_reset(adapter);
+	}
+	return ret;
+}
+
+/**
+ * pch_gbe_get_regs_len - Report the size of device registers
+ * @netdev: Network interface device structure
+ * Returns: the size of device registers.
+ */
+static int pch_gbe_get_regs_len(struct net_device *netdev)
+{
+	return PCH_GBE_REGS_LEN * (int)sizeof(u32);
+}
+
+/**
+ * pch_gbe_get_drvinfo - Report driver information
+ * @netdev:  Network interface device structure
+ * @drvinfo: Driver information structure
+ */
+static void pch_gbe_get_drvinfo(struct net_device *netdev,
+				 struct ethtool_drvinfo *drvinfo)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	strcpy(drvinfo->driver, KBUILD_MODNAME);
+	strcpy(drvinfo->version, pch_driver_version);
+	strcpy(drvinfo->fw_version, "N/A");
+	strcpy(drvinfo->bus_info, pci_name(adapter->pdev));
+	drvinfo->regdump_len = pch_gbe_get_regs_len(netdev);
+}
+
+/**
+ * pch_gbe_get_regs - Get device registers
+ * @netdev: Network interface device structure
+ * @regs:   Ethtool register structure
+ * @p:      Buffer pointer of read device register date
+ */
+static void pch_gbe_get_regs(struct net_device *netdev,
+				struct ethtool_regs *regs, void *p)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+	struct pci_dev *pdev = adapter->pdev;
+	u32 *regs_buff = p;
+	u16 i, tmp;
+
+	regs->version = 0x1000000 | (__u32)pdev->revision << 16 | pdev->device;
+	for (i = 0; i < PCH_GBE_MAC_REGS_LEN; i++)
+		*regs_buff++ = ioread32(&hw->reg->INT_ST + i);
+	/* PHY register */
+	for (i = 0; i < PCH_GBE_PHY_REGS_LEN; i++) {
+		pch_gbe_hal_read_phy_reg(&adapter->hw, i, &tmp);
+		*regs_buff++ = tmp;
+	}
+}
+
+/**
+ * pch_gbe_get_wol - Report whether Wake-on-Lan is enabled
+ * @netdev: Network interface device structure
+ * @wol:    Wake-on-Lan information
+ */
+static void pch_gbe_get_wol(struct net_device *netdev,
+				struct ethtool_wolinfo *wol)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+	wol->wolopts = 0;
+
+	if ((adapter->wake_up_evt & PCH_GBE_WLC_IND))
+		wol->wolopts |= WAKE_UCAST;
+	if ((adapter->wake_up_evt & PCH_GBE_WLC_MLT))
+		wol->wolopts |= WAKE_MCAST;
+	if ((adapter->wake_up_evt & PCH_GBE_WLC_BR))
+		wol->wolopts |= WAKE_BCAST;
+	if ((adapter->wake_up_evt & PCH_GBE_WLC_MP))
+		wol->wolopts |= WAKE_MAGIC;
+}
+
+/**
+ * pch_gbe_set_wol - Turn Wake-on-Lan on or off
+ * @netdev: Network interface device structure
+ * @wol:    Pointer of wake-on-Lan information straucture
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+static int pch_gbe_set_wol(struct net_device *netdev,
+				struct ethtool_wolinfo *wol)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	if ((wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)))
+		return -EOPNOTSUPP;
+	/* these settings will always override what we currently have */
+	adapter->wake_up_evt = 0;
+
+	if ((wol->wolopts & WAKE_UCAST))
+		adapter->wake_up_evt |= PCH_GBE_WLC_IND;
+	if ((wol->wolopts & WAKE_MCAST))
+		adapter->wake_up_evt |= PCH_GBE_WLC_MLT;
+	if ((wol->wolopts & WAKE_BCAST))
+		adapter->wake_up_evt |= PCH_GBE_WLC_BR;
+	if ((wol->wolopts & WAKE_MAGIC))
+		adapter->wake_up_evt |= PCH_GBE_WLC_MP;
+	return 0;
+}
+
+/**
+ * pch_gbe_nway_reset - Restart autonegotiation
+ * @netdev: Network interface device structure
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+static int pch_gbe_nway_reset(struct net_device *netdev)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	return mii_nway_restart(&adapter->mii);
+}
+
+/**
+ * pch_gbe_get_ringparam - Report ring sizes
+ * @netdev:  Network interface device structure
+ * @ring:    Ring param structure
+ */
+static void pch_gbe_get_ringparam(struct net_device *netdev,
+					struct ethtool_ringparam *ring)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_tx_ring *txdr = adapter->tx_ring;
+	struct pch_gbe_rx_ring *rxdr = adapter->rx_ring;
+
+	ring->rx_max_pending = PCH_GBE_MAX_RXD;
+	ring->tx_max_pending = PCH_GBE_MAX_TXD;
+	ring->rx_mini_max_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->rx_pending = rxdr->count;
+	ring->tx_pending = txdr->count;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_pending = 0;
+}
+
+/**
+ * pch_gbe_set_ringparam - Set ring sizes
+ * @netdev:  Network interface device structure
+ * @ring:    Ring param structure
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+static int pch_gbe_set_ringparam(struct net_device *netdev,
+					struct ethtool_ringparam *ring)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_tx_ring *txdr, *tx_old;
+	struct pch_gbe_rx_ring *rxdr, *rx_old;
+	int tx_ring_size, rx_ring_size;
+	int err = 0;
+
+	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+		return -EINVAL;
+	tx_ring_size = (int)sizeof(struct pch_gbe_tx_ring);
+	rx_ring_size = (int)sizeof(struct pch_gbe_rx_ring);
+
+	if ((netif_running(adapter->netdev)))
+		pch_gbe_down(adapter);
+	tx_old = adapter->tx_ring;
+	rx_old = adapter->rx_ring;
+
+	txdr = kzalloc(tx_ring_size, GFP_KERNEL);
+	if (!txdr) {
+		err = -ENOMEM;
+		goto err_alloc_tx;
+	}
+	rxdr = kzalloc(rx_ring_size, GFP_KERNEL);
+	if (!rxdr) {
+		err = -ENOMEM;
+		goto err_alloc_rx;
+	}
+	adapter->tx_ring = txdr;
+	adapter->rx_ring = rxdr;
+
+	rxdr->count =
+		clamp_val(ring->rx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
+	rxdr->count = roundup(rxdr->count, PCH_GBE_RX_DESC_MULTIPLE);
+
+	txdr->count =
+		clamp_val(ring->tx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
+	txdr->count = roundup(txdr->count, PCH_GBE_TX_DESC_MULTIPLE);
+
+	if ((netif_running(adapter->netdev))) {
+		/* Try to get new resources before deleting old */
+		err = pch_gbe_setup_rx_resources(adapter, adapter->rx_ring);
+		if (err)
+			goto err_setup_rx;
+		err = pch_gbe_setup_tx_resources(adapter, adapter->tx_ring);
+		if (err)
+			goto err_setup_tx;
+		/* save the new, restore the old in order to free it,
+		 * then restore the new back again */
+#ifdef RINGFREE
+		adapter->rx_ring = rx_old;
+		adapter->tx_ring = tx_old;
+		pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
+		pch_gbe_free_tx_resources(adapter, adapter->tx_ring);
+		kfree(tx_old);
+		kfree(rx_old);
+		adapter->rx_ring = rxdr;
+		adapter->tx_ring = txdr;
+#else
+		pch_gbe_free_rx_resources(adapter, rx_old);
+		pch_gbe_free_tx_resources(adapter, tx_old);
+		kfree(tx_old);
+		kfree(rx_old);
+		adapter->rx_ring = rxdr;
+		adapter->tx_ring = txdr;
+#endif
+		err = pch_gbe_up(adapter);
+	}
+	return err;
+
+err_setup_tx:
+	pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
+err_setup_rx:
+	adapter->rx_ring = rx_old;
+	adapter->tx_ring = tx_old;
+	kfree(rxdr);
+err_alloc_rx:
+	kfree(txdr);
+err_alloc_tx:
+	if (netif_running(adapter->netdev))
+		pch_gbe_up(adapter);
+	return err;
+}
+
+/**
+ * pch_gbe_get_pauseparam - Report pause parameters
+ * @netdev:  Network interface device structure
+ * @pause:   Pause parameters structure
+ */
+static void pch_gbe_get_pauseparam(struct net_device *netdev,
+				       struct ethtool_pauseparam *pause)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+
+	pause->autoneg =
+	    ((hw->mac.fc_autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+
+	if (hw->mac.fc == PCH_GBE_FC_RX_PAUSE) {
+		pause->rx_pause = 1;
+	} else if (hw->mac.fc == PCH_GBE_FC_TX_PAUSE) {
+		pause->tx_pause = 1;
+	} else if (hw->mac.fc == PCH_GBE_FC_FULL) {
+		pause->rx_pause = 1;
+		pause->tx_pause = 1;
+	}
+}
+
+/**
+ * pch_gbe_set_pauseparam - Set pause paramters
+ * @netdev:  Network interface device structure
+ * @pause:   Pause parameters structure
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+static int pch_gbe_set_pauseparam(struct net_device *netdev,
+				       struct ethtool_pauseparam *pause)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+	int ret = 0;
+
+	hw->mac.fc_autoneg = pause->autoneg;
+	if ((pause->rx_pause) && (pause->tx_pause))
+		hw->mac.fc = PCH_GBE_FC_FULL;
+	else if ((pause->rx_pause) && (!pause->tx_pause))
+		hw->mac.fc = PCH_GBE_FC_RX_PAUSE;
+	else if ((!pause->rx_pause) && (pause->tx_pause))
+		hw->mac.fc = PCH_GBE_FC_TX_PAUSE;
+	else if ((!pause->rx_pause) && (!pause->tx_pause))
+		hw->mac.fc = PCH_GBE_FC_NONE;
+
+	if (hw->mac.fc_autoneg == AUTONEG_ENABLE) {
+		if ((netif_running(adapter->netdev))) {
+			pch_gbe_down(adapter);
+			ret = pch_gbe_up(adapter);
+		} else {
+			pch_gbe_reset(adapter);
+		}
+	} else {
+		ret = pch_gbe_mac_force_mac_fc(hw);
+	}
+	return ret;
+}
+
+/**
+ * pch_gbe_get_rx_csum - Report whether receive checksums are turned on or off
+ * @netdev:  Network interface device structure
+ * Returns
+ *	true(1):  Checksum On
+ *	false(0): Checksum Off
+ */
+static u32 pch_gbe_get_rx_csum(struct net_device *netdev)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	return adapter->rx_csum;
+}
+
+/**
+ * pch_gbe_set_rx_csum - Turn receive checksum on or off
+ * @netdev:  Network interface device structure
+ * @data:    Checksum On[true] or Off[false]
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+static int pch_gbe_set_rx_csum(struct net_device *netdev, u32 data)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	adapter->rx_csum = data;
+	if ((netif_running(netdev)))
+		pch_gbe_reinit_locked(adapter);
+	else
+		pch_gbe_reset(adapter);
+
+	return 0;
+}
+
+/**
+ * pch_gbe_get_tx_csum - Report whether transmit checksums are turned on or off
+ * @netdev:  Network interface device structure
+ * Returns
+ *	true(1):  Checksum On
+ *	false(0): Checksum Off
+ */
+static u32 pch_gbe_get_tx_csum(struct net_device *netdev)
+{
+	return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+/**
+ * pch_gbe_set_tx_csum - Turn transmit checksums on or off
+ * @netdev: Network interface device structure
+ * @data:   Checksum on[true] or off[false]
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+static int pch_gbe_set_tx_csum(struct net_device *netdev, u32 data)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	adapter->tx_csum = data;
+	if (data)
+		netdev->features |= NETIF_F_HW_CSUM;
+	else
+		netdev->features &= ~NETIF_F_HW_CSUM;
+	return 0;
+}
+
+/**
+ * pch_gbe_get_strings - Return a set of strings that describe the requested
+ *			 objects
+ * @netdev:    Network interface device structure
+ * @stringset: Select the stringset. [ETH_SS_TEST] [ETH_SS_STATS]
+ * @data:      Pointer of read string data.
+ */
+static void pch_gbe_get_strings(struct net_device *netdev, u32 stringset,
+					u8 *data)
+{
+	u8 *p = data;
+	int i;
+
+	switch (stringset) {
+	case (u32) ETH_SS_STATS:
+		for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
+			memcpy(p, pch_gbe_gstrings_stats[i].string,
+			       ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
+		break;
+	}
+}
+
+/**
+ * pch_gbe_get_ethtool_stats - Return statistics about the device
+ * @netdev: Network interface device structure
+ * @stats:  Ethtool statue structure
+ * @data:   Pointer of read status area
+ */
+static void pch_gbe_get_ethtool_stats(struct net_device *netdev,
+				  struct ethtool_stats *stats, u64 *data)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	int i;
+	const struct pch_gbe_stats *gstats = pch_gbe_gstrings_stats;
+	char *hw_stats = (char *)&adapter->stats;
+
+	pch_gbe_update_stats(adapter);
+	for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
+		char *p = hw_stats + gstats->offset;
+		data[i] = gstats->size == sizeof(u64) ? *(u64 *)p:(*(u32 *)p);
+		gstats++;
+	}
+}
+
+static int pch_gbe_get_sset_count(struct net_device *netdev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return PCH_GBE_STATS_LEN;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static const struct ethtool_ops pch_gbe_ethtool_ops = {
+	.get_settings = pch_gbe_get_settings,
+	.set_settings = pch_gbe_set_settings,
+	.get_drvinfo = pch_gbe_get_drvinfo,
+	.get_regs_len = pch_gbe_get_regs_len,
+	.get_regs = pch_gbe_get_regs,
+	.get_wol = pch_gbe_get_wol,
+	.set_wol = pch_gbe_set_wol,
+	.nway_reset = pch_gbe_nway_reset,
+	.get_link = ethtool_op_get_link,
+	.get_ringparam = pch_gbe_get_ringparam,
+	.set_ringparam = pch_gbe_set_ringparam,
+	.get_pauseparam = pch_gbe_get_pauseparam,
+	.set_pauseparam = pch_gbe_set_pauseparam,
+	.get_rx_csum = pch_gbe_get_rx_csum,
+	.set_rx_csum = pch_gbe_set_rx_csum,
+	.get_tx_csum = pch_gbe_get_tx_csum,
+	.set_tx_csum = pch_gbe_set_tx_csum,
+	.get_strings = pch_gbe_get_strings,
+	.get_ethtool_stats = pch_gbe_get_ethtool_stats,
+	.get_sset_count = pch_gbe_get_sset_count,
+};
+
+void pch_gbe_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &pch_gbe_ethtool_ops);
+}
diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c
new file mode 100644
index 0000000..472056b
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_main.c
@@ -0,0 +1,2477 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "pch_gbe.h"
+#include "pch_gbe_api.h"
+
+#define DRV_VERSION     "1.00"
+const char pch_driver_version[] = DRV_VERSION;
+
+#define PCI_DEVICE_ID_INTEL_IOH1_GBE	0x8802		/* Pci device ID */
+#define PCH_GBE_MAR_ENTRIES		16
+#define PCH_GBE_SHORT_PKT		64
+#define DSC_INIT16			0xC000
+#define PCH_GBE_DMA_ALIGN		0
+#define PCH_GBE_WATCHDOG_PERIOD		(1 * HZ)	/* watchdog time */
+#define PCH_GBE_COPYBREAK_DEFAULT	256
+#define PCH_GBE_PCI_BAR			1
+
+#define PCH_GBE_TX_WEIGHT         64
+#define PCH_GBE_RX_WEIGHT         64
+#define PCH_GBE_RX_BUFFER_WRITE   16
+
+/* Initialize the wake-on-LAN settings */
+#define PCH_GBE_WL_INIT_SETTING    (PCH_GBE_WLC_MP)
+
+#define PCH_GBE_MAC_RGMII_CTRL_SETTING ( \
+	PCH_GBE_CHIP_TYPE_INTERNAL | \
+	PCH_GBE_RGMII_MODE_RGMII   | \
+	PCH_GBE_CRS_SEL              \
+	)
+
+/* Ethertype field values */
+#define PCH_GBE_MAX_JUMBO_FRAME_SIZE    10318
+#define PCH_GBE_FRAME_SIZE_2048         2048
+#define PCH_GBE_FRAME_SIZE_4096         4096
+#define PCH_GBE_FRAME_SIZE_8192         8192
+
+#define PCH_GBE_GET_DESC(R, i, type)    (&(((struct type *)((R).desc))[i]))
+#define PCH_GBE_RX_DESC(R, i)           PCH_GBE_GET_DESC(R, i, pch_gbe_rx_desc)
+#define PCH_GBE_TX_DESC(R, i)           PCH_GBE_GET_DESC(R, i, pch_gbe_tx_desc)
+#define PCH_GBE_DESC_UNUSED(R) \
+	((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
+	(R)->next_to_clean - (R)->next_to_use - 1)
+
+/* Pause packet value */
+#define	PCH_GBE_PAUSE_PKT1_VALUE    0x00C28001
+#define	PCH_GBE_PAUSE_PKT2_VALUE    0x00000100
+#define	PCH_GBE_PAUSE_PKT4_VALUE    0x01000888
+#define	PCH_GBE_PAUSE_PKT5_VALUE    0x0000FFFF
+
+#define PCH_GBE_ETH_ALEN            6
+
+/* This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register.  Each bit is documented below:
+ *   o RXT0   = Receiver Timer Interrupt (ring 0)
+ *   o TXDW   = Transmit Descriptor Written Back
+ *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
+ *   o RXSEQ  = Receive Sequence Error
+ *   o LSC    = Link Status Change
+ */
+#define PCH_GBE_INT_ENABLE_MASK ( \
+	PCH_GBE_INT_RX_DMA_CMPLT |    \
+	PCH_GBE_INT_RX_DSC_EMP   |    \
+	PCH_GBE_INT_WOL_DET      |    \
+	PCH_GBE_INT_TX_CMPLT          \
+	)
+
+
+static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT;
+
+static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg);
+static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg,
+			       int data);
+/**
+ * pch_gbe_mac_read_mac_addr - Read MAC address
+ * @hw:	            Pointer to the HW structure
+ * Returns
+ *	0:			Successful.
+ */
+s32 pch_gbe_mac_read_mac_addr(struct pch_gbe_hw *hw)
+{
+	u32  adr1a, adr1b;
+
+	adr1a = ioread32(&hw->reg->mac_adr[0].high);
+	adr1b = ioread32(&hw->reg->mac_adr[0].low);
+
+	hw->mac.addr[0] = (u8)(adr1a & 0xFF);
+	hw->mac.addr[1] = (u8)((adr1a >> 8) & 0xFF);
+	hw->mac.addr[2] = (u8)((adr1a >> 16) & 0xFF);
+	hw->mac.addr[3] = (u8)((adr1a >> 24) & 0xFF);
+	hw->mac.addr[4] = (u8)(adr1b & 0xFF);
+	hw->mac.addr[5] = (u8)((adr1b >> 8) & 0xFF);
+
+	pr_debug("hw->mac.addr : %pM\n", hw->mac.addr);
+	return 0;
+}
+
+/**
+ * pch_gbe_wait_clr_bit - Wait to clear a bit
+ * @reg:	Pointer of register
+ * @busy:	Busy bit
+ */
+static void pch_gbe_wait_clr_bit(void *reg, u32 bit)
+{
+	u32 tmp;
+	/* wait busy */
+	tmp = 1000;
+	while ((ioread32(reg) & bit) && --tmp)
+		cpu_relax();
+	if (!tmp)
+		pr_err("Error: busy bit is not cleared\n");
+}
+/**
+ * pch_gbe_mac_mar_set - Set MAC address register
+ * @hw:	    Pointer to the HW structure
+ * @addr:   Pointer to the MAC address
+ * @index:  MAC address array register
+ */
+static void pch_gbe_mac_mar_set(struct pch_gbe_hw *hw, u8 * addr, u32 index)
+{
+	u32 mar_low, mar_high, adrmask;
+
+	pr_debug("index : 0x%x\n", index);
+
+	/*
+	 * HW expects these in little endian so we reverse the byte order
+	 * from network order (big endian) to little endian
+	 */
+	mar_high = ((u32) addr[0] | ((u32) addr[1] << 8) |
+		   ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+	mar_low = ((u32) addr[4] | ((u32) addr[5] << 8));
+	/* Stop the MAC Address of index. */
+	adrmask = ioread32(&hw->reg->ADDR_MASK);
+	iowrite32((adrmask | (0x0001 << index)), &hw->reg->ADDR_MASK);
+	/* wait busy */
+	pch_gbe_wait_clr_bit(&hw->reg->ADDR_MASK, PCH_GBE_BUSY);
+	/* Set the MAC address to the MAC address 1A/1B register */
+	iowrite32(mar_high, &hw->reg->mac_adr[index].high);
+	iowrite32(mar_low, &hw->reg->mac_adr[index].low);
+	/* Start the MAC address of index */
+	iowrite32((adrmask & ~(0x0001 << index)), &hw->reg->ADDR_MASK);
+	/* wait busy */
+	pch_gbe_wait_clr_bit(&hw->reg->ADDR_MASK, PCH_GBE_BUSY);
+}
+
+/**
+ * pch_gbe_mac_reset_hw - Reset hardware
+ * @hw:	Pointer to the HW structure
+ */
+static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw)
+{
+	/* Read the MAC address. and store to the private data */
+	pch_gbe_mac_read_mac_addr(hw);
+	iowrite32(PCH_GBE_ALL_RST, &hw->reg->RESET);
+#ifdef PCH_GBE_MAC_IFOP_RGMII
+	iowrite32(PCH_GBE_MODE_GMII_ETHER, &hw->reg->MODE);
+#endif
+	pch_gbe_wait_clr_bit(&hw->reg->RESET, PCH_GBE_ALL_RST);
+	/* Setup the receive address */
+	pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
+	return;
+}
+
+/**
+ * pch_gbe_mac_init_rx_addrs - Initialize receive address's
+ * @hw:	Pointer to the HW structure
+ * @mar_count: Receive address registers
+ */
+static void pch_gbe_mac_init_rx_addrs(struct pch_gbe_hw *hw, u16 mar_count)
+{
+	u32 i;
+
+	/* Setup the receive address */
+	pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
+
+	/* Zero out the other receive addresses */
+	for (i = 1; i < mar_count; i++) {
+		iowrite32(0, &hw->reg->mac_adr[i].high);
+		iowrite32(0, &hw->reg->mac_adr[i].low);
+	}
+	iowrite32(0xFFFE, &hw->reg->ADDR_MASK);
+	/* wait busy */
+	pch_gbe_wait_clr_bit(&hw->reg->ADDR_MASK, PCH_GBE_BUSY);
+}
+
+
+/**
+ * pch_gbe_mac_mc_addr_list_update - Update Multicast addresses
+ * @hw:	            Pointer to the HW structure
+ * @mc_addr_list:   Array of multicast addresses to program
+ * @mc_addr_count:  Number of multicast addresses to program
+ * @mar_used_count: The first MAC Address register free to program
+ * @mar_total_num:  Total number of supported MAC Address Registers
+ */
+static void pch_gbe_mac_mc_addr_list_update(struct pch_gbe_hw *hw,
+					    u8 *mc_addr_list, u32 mc_addr_count,
+					    u32 mar_used_count, u32 mar_total_num)
+{
+	u32 i, adrmask;
+
+	/* Load the first set of multicast addresses into the exact
+	 * filters (RAR).  If there are not enough to fill the RAR
+	 * array, clear the filters.
+	 */
+	for (i = mar_used_count; i < mar_total_num; i++) {
+		if (mc_addr_count) {
+			pch_gbe_mac_mar_set(hw, mc_addr_list, i);
+			mc_addr_count--;
+			mc_addr_list += PCH_GBE_ETH_ALEN;
+		} else {
+			/* Clear MAC address mask */
+			adrmask = ioread32(&hw->reg->ADDR_MASK);
+			iowrite32((adrmask | (0x0001 << i)),
+					&hw->reg->ADDR_MASK);
+			/* wait busy */
+			pch_gbe_wait_clr_bit(&hw->reg->ADDR_MASK, PCH_GBE_BUSY);
+			/* Clear MAC address */
+			iowrite32(0, &hw->reg->mac_adr[i].high);
+			iowrite32(0, &hw->reg->mac_adr[i].low);
+		}
+	}
+}
+
+/**
+ * pch_gbe_mac_force_mac_fc - Force the MAC's flow control settings
+ * @hw:	            Pointer to the HW structure
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+s32 pch_gbe_mac_force_mac_fc(struct pch_gbe_hw *hw)
+{
+	struct pch_gbe_mac_info *mac = &hw->mac;
+	u32 rx_fctrl;
+
+	pr_debug("mac->fc = %u\n", mac->fc);
+
+	rx_fctrl = ioread32(&hw->reg->RX_FCTRL);
+
+	switch (mac->fc) {
+	case PCH_GBE_FC_NONE:
+		rx_fctrl &= ~PCH_GBE_FL_CTRL_EN;
+		mac->tx_fc_enable = false;
+		break;
+	case PCH_GBE_FC_RX_PAUSE:
+		rx_fctrl |= PCH_GBE_FL_CTRL_EN;
+		mac->tx_fc_enable = false;
+		break;
+	case PCH_GBE_FC_TX_PAUSE:
+		rx_fctrl &= ~PCH_GBE_FL_CTRL_EN;
+		mac->tx_fc_enable = true;
+		break;
+	case PCH_GBE_FC_FULL:
+		rx_fctrl |= PCH_GBE_FL_CTRL_EN;
+		mac->tx_fc_enable = true;
+		break;
+	default:
+		pr_err("Flow control param set incorrectly\n");
+		return -EINVAL;
+	}
+	if (mac->link_duplex == DUPLEX_HALF)
+		rx_fctrl &= ~PCH_GBE_FL_CTRL_EN;
+	iowrite32(rx_fctrl, &hw->reg->RX_FCTRL);
+	pr_debug("RX_FCTRL reg : 0x%08x  mac->tx_fc_enable : %d\n",
+		 ioread32(&hw->reg->RX_FCTRL), mac->tx_fc_enable);
+	return 0;
+}
+
+/**
+ * pch_gbe_mac_set_wol_event - Set wake-on-lan event
+ * @hw:     Pointer to the HW structure
+ * @wu_evt: Wake up event
+ */
+static void pch_gbe_mac_set_wol_event(struct pch_gbe_hw *hw, u32 wu_evt)
+{
+	u32 addr_mask;
+
+	pr_debug("wu_evt : 0x%08x  ADDR_MASK reg : 0x%08x\n",
+		 wu_evt, ioread32(&hw->reg->ADDR_MASK));
+
+	if (wu_evt) {
+		/* Set Wake-On-Lan address mask */
+		addr_mask = ioread32(&hw->reg->ADDR_MASK);
+		iowrite32(addr_mask, &hw->reg->WOL_ADDR_MASK);
+		/* wait busy */
+		pch_gbe_wait_clr_bit(&hw->reg->WOL_ADDR_MASK, PCH_GBE_WLA_BUSY);
+		iowrite32(0, &hw->reg->WOL_ST);
+		iowrite32((wu_evt | PCH_GBE_WLC_WOL_MODE), &hw->reg->WOL_CTRL);
+		iowrite32(0x02, &hw->reg->TCPIP_ACC);
+		iowrite32(PCH_GBE_INT_ENABLE_MASK, &hw->reg->INT_EN);
+	} else {
+		iowrite32(0, &hw->reg->WOL_CTRL);
+		iowrite32(0, &hw->reg->WOL_ST);
+	}
+	return;
+}
+
+/**
+ * pch_gbe_mac_ctrl_miim - Control MIIM interface
+ * @hw:   Pointer to the HW structure
+ * @addr: Address of PHY
+ * @dir:  Operetion. (Write or Read)
+ * @reg:  Access register of PHY
+ * @data: Write data.
+ *
+ * Returns: Read date.
+ */
+u16 pch_gbe_mac_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32 reg,
+			u16 data)
+{
+	u32 data_out = 0;
+	unsigned int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->miim_lock, flags);
+
+	for (i = 100; i; --i) {
+		if ((ioread32(&hw->reg->MIIM) & PCH_GBE_MIIM_OPER_READY))
+			break;
+		udelay(20);
+	}
+	if (i == 0) {
+		pr_err("pch-gbe.miim won't go Ready\n");
+		spin_unlock_irqrestore(&hw->miim_lock, flags);
+		return 0;	/* No way to indicate timeout error */
+	}
+	iowrite32(((reg << PCH_GBE_MIIM_REG_ADDR_SHIFT) |
+		  (addr << PCH_GBE_MIIM_PHY_ADDR_SHIFT) |
+		  dir | data), &hw->reg->MIIM);
+	for (i = 0; i < 100; i++) {
+		udelay(20);
+		data_out = ioread32(&hw->reg->MIIM);
+		if ((data_out & PCH_GBE_MIIM_OPER_READY))
+			break;
+	}
+	spin_unlock_irqrestore(&hw->miim_lock, flags);
+
+	pr_debug("PHY %s: reg=%d, data=0x%04X\n",
+		 dir == PCH_GBE_MIIM_OPER_READ ? "READ" : "WRITE", reg,
+		 dir == PCH_GBE_MIIM_OPER_READ ? data_out : data);
+	return (u16) data_out;
+}
+
+/**
+ * pch_gbe_mac_set_pause_packet - Set pause packet
+ * @hw:   Pointer to the HW structure
+ */
+static void pch_gbe_mac_set_pause_packet(struct pch_gbe_hw *hw)
+{
+	unsigned long tmp2, tmp3;
+
+	/* Set Pause packet */
+	tmp2 = hw->mac.addr[1];
+	tmp2 = (tmp2 << 8) | hw->mac.addr[0];
+	tmp2 = PCH_GBE_PAUSE_PKT2_VALUE | (tmp2 << 16);
+
+	tmp3 = hw->mac.addr[5];
+	tmp3 = (tmp3 << 8) | hw->mac.addr[4];
+	tmp3 = (tmp3 << 8) | hw->mac.addr[3];
+	tmp3 = (tmp3 << 8) | hw->mac.addr[2];
+
+	iowrite32(PCH_GBE_PAUSE_PKT1_VALUE, &hw->reg->PAUSE_PKT1);
+	iowrite32(tmp2, &hw->reg->PAUSE_PKT2);
+	iowrite32(tmp3, &hw->reg->PAUSE_PKT3);
+	iowrite32(PCH_GBE_PAUSE_PKT4_VALUE, &hw->reg->PAUSE_PKT4);
+	iowrite32(PCH_GBE_PAUSE_PKT5_VALUE, &hw->reg->PAUSE_PKT5);
+
+	/* Transmit Pause Packet */
+	iowrite32(PCH_GBE_PS_PKT_RQ, &hw->reg->PAUSE_REQ);
+
+	pr_debug("PAUSE_PKT1-5 reg : 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+		 ioread32(&hw->reg->PAUSE_PKT1), ioread32(&hw->reg->PAUSE_PKT2),
+		 ioread32(&hw->reg->PAUSE_PKT3), ioread32(&hw->reg->PAUSE_PKT4),
+		 ioread32(&hw->reg->PAUSE_PKT5));
+
+	return;
+}
+
+
+/**
+ * pch_gbe_alloc_queues - Allocate memory for all rings
+ * @adapter:  Board private structure to initialize
+ * Returns
+ *	0:	Successfully
+ *	Negative value:	Failed
+ */
+static int pch_gbe_alloc_queues(struct pch_gbe_adapter *adapter)
+{
+	int size;
+
+	size = (int)sizeof(struct pch_gbe_tx_ring);
+	adapter->tx_ring = kzalloc(size, GFP_KERNEL);
+	if (!adapter->tx_ring)
+		return -ENOMEM;
+	size = (int)sizeof(struct pch_gbe_rx_ring);
+	adapter->rx_ring = kzalloc(size, GFP_KERNEL);
+	if (!adapter->rx_ring) {
+		kfree(adapter->tx_ring);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+/**
+ * pch_gbe_init_stats - Initialize status
+ * @adapter:  Board private structure to initialize
+ */
+static void pch_gbe_init_stats(struct pch_gbe_adapter *adapter)
+{
+	memset(&adapter->stats, 0, sizeof(adapter->stats));
+	return;
+}
+
+/**
+ * pch_gbe_init_phy - Initialize PHY
+ * @adapter:  Board private structure to initialize
+ * Returns
+ *	0:	Successfully
+ *	Negative value:	Failed
+ */
+static int pch_gbe_init_phy(struct pch_gbe_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	u32 addr;
+	u16 bmcr, stat;
+
+	/* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
+	for (addr = 0; addr < PCH_GBE_PHY_REGS_LEN; addr++) {
+		adapter->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
+		bmcr = pch_gbe_mdio_read(netdev, adapter->mii.phy_id, MII_BMCR);
+		stat = pch_gbe_mdio_read(netdev, adapter->mii.phy_id, MII_BMSR);
+		stat = pch_gbe_mdio_read(netdev, adapter->mii.phy_id, MII_BMSR);
+		if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
+			break;
+	}
+	adapter->hw.phy.addr = adapter->mii.phy_id;
+	pr_debug("phy_addr = %d\n", adapter->mii.phy_id);
+	if (addr == 32)
+		return -EAGAIN;
+	/* Selected the phy and isolate the rest */
+	for (addr = 0; addr < PCH_GBE_PHY_REGS_LEN; addr++) {
+		if (addr != adapter->mii.phy_id) {
+			pch_gbe_mdio_write(netdev, addr, MII_BMCR,
+					   BMCR_ISOLATE);
+		} else {
+			bmcr = pch_gbe_mdio_read(netdev, addr, MII_BMCR);
+			pch_gbe_mdio_write(netdev, addr, MII_BMCR,
+					   bmcr & ~BMCR_ISOLATE);
+		}
+	}
+
+	/* MII setup */
+	adapter->mii.phy_id_mask = 0x1F;
+	adapter->mii.reg_num_mask = 0x1F;
+	adapter->mii.dev = adapter->netdev;
+	adapter->mii.mdio_read = pch_gbe_mdio_read;
+	adapter->mii.mdio_write = pch_gbe_mdio_write;
+	adapter->mii.supports_gmii = mii_check_gmii_support(&adapter->mii);
+	return 0;
+}
+
+/**
+ * pch_gbe_mdio_read - The read function for mii
+ * @netdev: Network interface device structure
+ * @addr:   Phy ID
+ * @reg:    Access location
+ * Returns
+ *	0:	Successfully
+ *	Negative value:	Failed
+ */
+static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+
+	return pch_gbe_mac_ctrl_miim(hw, addr, PCH_GBE_HAL_MIIM_READ, reg,
+				     (u16) 0);
+}
+
+/**
+ * pch_gbe_mdio_write - The write function for mii
+ * @netdev: Network interface device structure
+ * @addr:   Phy ID (not used)
+ * @reg:    Access location
+ * @data:   Write data
+ */
+static void pch_gbe_mdio_write(struct net_device *netdev,
+			       int addr, int reg, int data)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+
+	pch_gbe_mac_ctrl_miim(hw, addr, PCH_GBE_HAL_MIIM_WRITE, reg, data);
+}
+
+/**
+ * pch_gbe_reset_task - Reset processing at the time of transmission timeout
+ * @work:  Pointer of board private structure
+ */
+static void pch_gbe_reset_task(struct work_struct *work)
+{
+	struct pch_gbe_adapter *adapter;
+	adapter = container_of(work, struct pch_gbe_adapter, reset_task);
+
+	pch_gbe_reinit_locked(adapter);
+}
+
+/**
+ * pch_gbe_reinit_locked- Re-initialization
+ * @adapter:  Board private structure
+ */
+void pch_gbe_reinit_locked(struct pch_gbe_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	rtnl_lock();
+	if (netif_running(netdev)) {
+		pch_gbe_down(adapter);
+		pch_gbe_up(adapter);
+	}
+	rtnl_unlock();
+}
+
+/**
+ * pch_gbe_reset - Reset GbE
+ * @adapter:  Board private structure
+ */
+void pch_gbe_reset(struct pch_gbe_adapter *adapter)
+{
+	pch_gbe_mac_reset_hw(&adapter->hw);
+	/* Setup the receive address. */
+	pch_gbe_mac_init_rx_addrs(&adapter->hw, PCH_GBE_MAR_ENTRIES);
+	if (pch_gbe_hal_init_hw(&adapter->hw))
+		pr_err("Hardware Error\n");
+}
+
+/**
+ * pch_gbe_free_irq - Free an interrupt
+ * @adapter:  Board private structure
+ */
+static void pch_gbe_free_irq(struct pch_gbe_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	free_irq(adapter->pdev->irq, netdev);
+	if (adapter->have_msi) {
+		pci_disable_msi(adapter->pdev);
+		pr_debug("call pci_disable_msi\n");
+	}
+}
+
+/**
+ * pch_gbe_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter:  Board private structure
+ */
+static void pch_gbe_irq_disable(struct pch_gbe_adapter *adapter)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+
+	atomic_inc(&adapter->irq_sem);
+	iowrite32(0, &hw->reg->INT_EN);
+	ioread32(&hw->reg->INT_ST);
+	synchronize_irq(adapter->pdev->irq);
+
+	pr_debug("INT_EN reg : 0x%08x\n", ioread32(&hw->reg->INT_EN));
+}
+
+/**
+ * pch_gbe_irq_enable - Enable default interrupt generation settings
+ * @adapter:  Board private structure
+ */
+static void pch_gbe_irq_enable(struct pch_gbe_adapter *adapter)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+
+	if (likely(atomic_dec_and_test(&adapter->irq_sem)))
+		iowrite32(PCH_GBE_INT_ENABLE_MASK, &hw->reg->INT_EN);
+	ioread32(&hw->reg->INT_ST);
+	pr_debug("INT_EN reg : 0x%08x\n", ioread32(&hw->reg->INT_EN));
+}
+
+
+
+/**
+ * pch_gbe_setup_tctl - configure the Transmit control registers
+ * @adapter:  Board private structure
+ */
+static void pch_gbe_setup_tctl(struct pch_gbe_adapter *adapter)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+	u32 tx_mode, tcpip;
+
+	tx_mode = PCH_GBE_TM_LONG_PKT |
+		PCH_GBE_TM_ST_AND_FD |
+		PCH_GBE_TM_SHORT_PKT |
+		PCH_GBE_TM_TH_TX_STRT_8 |
+		PCH_GBE_TM_TH_ALM_EMP_4 | PCH_GBE_TM_TH_ALM_FULL_8;
+
+	iowrite32(tx_mode, &hw->reg->TX_MODE);
+
+	tcpip = ioread32(&hw->reg->TCPIP_ACC);
+	tcpip |= PCH_GBE_TX_TCPIPACC_EN;
+	iowrite32(tcpip, &hw->reg->TCPIP_ACC);
+	return;
+}
+
+/**
+ * pch_gbe_configure_tx - Configure Transmit Unit after Reset
+ * @adapter:  Board private structure
+ */
+static void pch_gbe_configure_tx(struct pch_gbe_adapter *adapter)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+	u32 tdba, tdlen, dctrl;
+
+	pr_debug("dma addr = 0x%08llx  size = 0x%08x\n",
+		 (unsigned long long)adapter->tx_ring->dma,
+		 adapter->tx_ring->size);
+
+	/* Setup the HW Tx Head and Tail descriptor pointers */
+	tdba = adapter->tx_ring->dma;
+	tdlen = adapter->tx_ring->size - 0x10;
+	iowrite32(tdba, &hw->reg->TX_DSC_BASE);
+	iowrite32(tdlen, &hw->reg->TX_DSC_SIZE);
+	iowrite32(tdba, &hw->reg->TX_DSC_SW_P);
+
+	/* Enables Transmission DMA */
+	dctrl = ioread32(&hw->reg->DMA_CTRL);
+	dctrl |= PCH_GBE_TX_DMA_EN;
+	iowrite32(dctrl, &hw->reg->DMA_CTRL);
+}
+
+/**
+ * pch_gbe_setup_rctl - Configure the receive control registers
+ * @adapter:  Board private structure
+ */
+static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+	u32 rx_mode, tcpip;
+
+	rx_mode = PCH_GBE_ADD_FIL_EN | PCH_GBE_MLT_FIL_EN |
+	PCH_GBE_RH_ALM_EMP_4 | PCH_GBE_RH_ALM_FULL_4 | PCH_GBE_RH_RD_TRG_8;
+
+	iowrite32(rx_mode, &hw->reg->RX_MODE);
+
+	tcpip = ioread32(&hw->reg->TCPIP_ACC);
+
+	if (adapter->rx_csum) {
+		tcpip &= ~PCH_GBE_RX_TCPIPACC_OFF;
+		tcpip |= PCH_GBE_RX_TCPIPACC_EN;
+	} else {
+		tcpip |= PCH_GBE_RX_TCPIPACC_OFF;
+		tcpip &= ~PCH_GBE_RX_TCPIPACC_EN;
+	}
+	iowrite32(tcpip, &hw->reg->TCPIP_ACC);
+	return;
+}
+
+/**
+ * pch_gbe_configure_rx - Configure Receive Unit after Reset
+ * @adapter:  Board private structure
+ */
+static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+	u32 rdba, rdlen, rctl, rxdma;
+
+	pr_debug("dma adr = 0x%08llx  size = 0x%08x\n",
+		 (unsigned long long)adapter->rx_ring->dma,
+		 adapter->rx_ring->size);
+
+	pch_gbe_mac_force_mac_fc(hw);
+
+	/* Disables Receive MAC */
+	rctl = ioread32(&hw->reg->MAC_RX_EN);
+	iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+
+	/* Disables Receive DMA */
+	rxdma = ioread32(&hw->reg->DMA_CTRL);
+	rxdma &= ~PCH_GBE_RX_DMA_EN;
+	iowrite32(rxdma, &hw->reg->DMA_CTRL);
+
+	pr_debug("MAC_RX_EN reg = 0x%08x  DMA_CTRL reg = 0x%08x\n",
+		 ioread32(&hw->reg->MAC_RX_EN),
+		 ioread32(&hw->reg->DMA_CTRL));
+
+	/* Setup the HW Rx Head and Tail Descriptor Pointers and
+	 * the Base and Length of the Rx Descriptor Ring */
+	rdba = adapter->rx_ring->dma;
+	rdlen = adapter->rx_ring->size - 0x10;
+	iowrite32(rdba, &hw->reg->RX_DSC_BASE);
+	iowrite32(rdlen, &hw->reg->RX_DSC_SIZE);
+	iowrite32((rdba + rdlen), &hw->reg->RX_DSC_SW_P);
+
+	/* Enables Receive DMA */
+	rxdma = ioread32(&hw->reg->DMA_CTRL);
+	rxdma |= PCH_GBE_RX_DMA_EN;
+	iowrite32(rxdma, &hw->reg->DMA_CTRL);
+	/* Enables Receive */
+	iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN);
+}
+
+/**
+ * pch_gbe_unmap_and_free_tx_resource - Unmap and free tx socket buffer
+ * @adapter:     Board private structure
+ * @buffer_info: Buffer information structure
+ */
+static void pch_gbe_unmap_and_free_tx_resource(
+	struct pch_gbe_adapter *adapter, struct pch_gbe_buffer *buffer_info)
+{
+	if (buffer_info->mapped) {
+		dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
+				 buffer_info->length, DMA_TO_DEVICE);
+		buffer_info->mapped = false;
+	}
+	if (buffer_info->skb) {
+		dev_kfree_skb_any(buffer_info->skb);
+		buffer_info->skb = NULL;
+	}
+}
+
+/**
+ * pch_gbe_unmap_and_free_rx_resource - Unmap and free rx socket buffer
+ * @adapter:      Board private structure
+ * @buffer_info:  Buffer information structure
+ */
+static void pch_gbe_unmap_and_free_rx_resource(
+					struct pch_gbe_adapter *adapter,
+					struct pch_gbe_buffer *buffer_info)
+{
+	if (buffer_info->mapped) {
+		dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
+				 buffer_info->length, DMA_FROM_DEVICE);
+		buffer_info->mapped = false;
+	}
+	if (buffer_info->skb) {
+		dev_kfree_skb_any(buffer_info->skb);
+		buffer_info->skb = NULL;
+	}
+}
+
+/**
+ * pch_gbe_clean_tx_ring - Free Tx Buffers
+ * @adapter:  Board private structure
+ * @tx_ring:  Ring to be cleaned
+ */
+static void pch_gbe_clean_tx_ring(struct pch_gbe_adapter *adapter,
+				   struct pch_gbe_tx_ring *tx_ring)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+	struct pch_gbe_buffer *buffer_info;
+	unsigned long size;
+	unsigned int i;
+
+	/* Free all the Tx ring sk_buffs */
+	for (i = 0; i < tx_ring->count; i++) {
+		buffer_info = &tx_ring->buffer_info[i];
+		pch_gbe_unmap_and_free_tx_resource(adapter, buffer_info);
+	}
+	pr_debug("call pch_gbe_unmap_and_free_tx_resource() %d count\n", i);
+
+	size = (unsigned long)sizeof(struct pch_gbe_buffer) * tx_ring->count;
+	memset(tx_ring->buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+	memset(tx_ring->desc, 0, tx_ring->size);
+	tx_ring->next_to_use = 0;
+	tx_ring->next_to_clean = 0;
+	iowrite32(tx_ring->dma, &hw->reg->TX_DSC_HW_P);
+	iowrite32((tx_ring->size - 0x10), &hw->reg->TX_DSC_SIZE);
+}
+
+/**
+ * pch_gbe_clean_rx_ring - Free Rx Buffers
+ * @adapter:  Board private structure
+ * @rx_ring:  Ring to free buffers from
+ */
+static void
+pch_gbe_clean_rx_ring(struct pch_gbe_adapter *adapter,
+		      struct pch_gbe_rx_ring *rx_ring)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+	struct pch_gbe_buffer *buffer_info;
+	unsigned long size;
+	unsigned int i;
+
+	/* Free all the Rx ring sk_buffs */
+	for (i = 0; i < rx_ring->count; i++) {
+		buffer_info = &rx_ring->buffer_info[i];
+		pch_gbe_unmap_and_free_rx_resource(adapter, buffer_info);
+	}
+	pr_debug("call pch_gbe_unmap_and_free_rx_resource() %d count\n", i);
+	size = (unsigned long)sizeof(struct pch_gbe_buffer) * rx_ring->count;
+	memset(rx_ring->buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+	memset(rx_ring->desc, 0, rx_ring->size);
+	rx_ring->next_to_clean = 0;
+	rx_ring->next_to_use = 0;
+	iowrite32(rx_ring->dma, &hw->reg->RX_DSC_HW_P);
+	iowrite32((rx_ring->size - 0x10), &hw->reg->RX_DSC_SIZE);
+}
+
+static void pch_gbe_set_rgmii_ctrl(struct pch_gbe_adapter *adapter, u16 speed,
+				    u16 duplex)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+	unsigned long rgmii = 0;
+
+	/* Set the RGMII control. */
+#ifdef PCH_GBE_MAC_IFOP_RGMII
+	switch (speed) {
+	case SPEED_10:
+		rgmii = (PCH_GBE_RGMII_RATE_2_5M |
+			 PCH_GBE_MAC_RGMII_CTRL_SETTING);
+		break;
+	case SPEED_100:
+		rgmii = (PCH_GBE_RGMII_RATE_25M |
+			 PCH_GBE_MAC_RGMII_CTRL_SETTING);
+		break;
+	case SPEED_1000:
+		rgmii = (PCH_GBE_RGMII_RATE_125M |
+			 PCH_GBE_MAC_RGMII_CTRL_SETTING);
+		break;
+	}
+	iowrite32(rgmii, &hw->reg->RGMII_CTRL);
+#else	/* GMII */
+	rgmii = 0;
+	iowrite32(rgmii, &hw->reg->RGMII_CTRL);
+#endif
+}
+static void pch_gbe_set_mode(struct pch_gbe_adapter *adapter, u16 speed,
+			      u16 duplex)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct pch_gbe_hw *hw = &adapter->hw;
+	unsigned long mode = 0;
+
+	/* Set the communication mode */
+	switch (speed) {
+	case SPEED_10:
+		mode = PCH_GBE_MODE_MII_ETHER;
+		netdev->tx_queue_len = 10;
+		break;
+	case SPEED_100:
+		mode = PCH_GBE_MODE_MII_ETHER;
+		netdev->tx_queue_len = 100;
+		break;
+	case SPEED_1000:
+		mode = PCH_GBE_MODE_GMII_ETHER;
+		break;
+	}
+	if (duplex == DUPLEX_FULL)
+		mode |= PCH_GBE_MODE_FULL_DUPLEX;
+	else
+		mode |= PCH_GBE_MODE_HALF_DUPLEX;
+	iowrite32(mode, &hw->reg->MODE);
+}
+
+/**
+ * pch_gbe_watchdog - Watchdog process
+ * @data:  Board private structure
+ */
+static void pch_gbe_watchdog(unsigned long data)
+{
+	struct pch_gbe_adapter *adapter = (struct pch_gbe_adapter *)data;
+	struct net_device *netdev = adapter->netdev;
+	struct pch_gbe_hw *hw = &adapter->hw;
+	struct ethtool_cmd cmd;
+
+	pr_debug("right now = %ld\n", jiffies);
+
+	pch_gbe_update_stats(adapter);
+	if ((mii_link_ok(&adapter->mii)) && (!netif_carrier_ok(netdev))) {
+		netdev->tx_queue_len = adapter->tx_queue_len;
+		/* mii library handles link maintenance tasks */
+		if (mii_ethtool_gset(&adapter->mii, &cmd)) {
+			pr_err("ethtool get setting Error\n");
+			mod_timer(&adapter->watchdog_timer,
+				  round_jiffies(jiffies +
+						PCH_GBE_WATCHDOG_PERIOD));
+			return;
+		}
+		hw->mac.link_speed = cmd.speed;
+		hw->mac.link_duplex = cmd.duplex;
+		/* Set the RGMII control. */
+		pch_gbe_set_rgmii_ctrl(adapter, hw->mac.link_speed,
+						hw->mac.link_duplex);
+		/* Set the communication mode */
+		pch_gbe_set_mode(adapter, hw->mac.link_speed,
+				 hw->mac.link_duplex);
+		netdev_dbg(netdev,
+			   "Link is Up %d Mbps %s-Duplex\n",
+			   cmd.speed,
+			   cmd.duplex == DUPLEX_FULL ? "Full" : "Half");
+		netif_carrier_on(netdev);
+		netif_wake_queue(netdev);
+	} else if ((!mii_link_ok(&adapter->mii)) &&
+		   (netif_carrier_ok(netdev))) {
+		netdev_dbg(netdev, "NIC Link is Down\n");
+		hw->mac.link_speed = SPEED_10;
+		hw->mac.link_duplex = DUPLEX_HALF;
+		netif_carrier_off(netdev);
+		netif_stop_queue(netdev);
+	}
+	mod_timer(&adapter->watchdog_timer,
+		  round_jiffies(jiffies + PCH_GBE_WATCHDOG_PERIOD));
+}
+
+/**
+ * pch_gbe_tx_queue - Carry out queuing of the transmission data
+ * @adapter:  Board private structure
+ * @tx_ring:  Tx descriptor ring structure
+ * @skb:      Sockt buffer structure
+ */
+static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
+			      struct pch_gbe_tx_ring *tx_ring,
+			      struct sk_buff *skb)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+	struct pch_gbe_tx_desc *tx_desc;
+	struct pch_gbe_buffer *buffer_info;
+	struct sk_buff *tmp_skb;
+	unsigned int frame_ctrl;
+	unsigned int ring_num;
+	unsigned long flags;
+
+	/*-- Set frame control --*/
+	frame_ctrl = 0;
+	if (unlikely(skb->len < PCH_GBE_SHORT_PKT))
+		frame_ctrl |= PCH_GBE_TXD_CTRL_APAD;
+	if (unlikely(!adapter->tx_csum))
+		frame_ctrl |= PCH_GBE_TXD_CTRL_TCPIP_ACC_OFF;
+
+	/* Performs checksum processing */
+	/*
+	 * It is because the hardware accelerator does not support a checksum,
+	 * when the received data size is less than 64 bytes.
+	 */
+	if ((skb->len < PCH_GBE_SHORT_PKT) && (adapter->tx_csum)) {
+		frame_ctrl |= PCH_GBE_TXD_CTRL_APAD |
+			      PCH_GBE_TXD_CTRL_TCPIP_ACC_OFF;
+		if (skb->protocol == htons(ETH_P_IP)) {
+			struct iphdr *iph = ip_hdr(skb);
+			unsigned int offset;
+			iph->check = 0;
+			iph->check = ip_fast_csum((u8 *) iph, iph->ihl);
+			offset = skb_transport_offset(skb);
+			if (iph->protocol == IPPROTO_TCP) {
+				skb->csum = 0;
+				tcp_hdr(skb)->check = 0;
+				skb->csum = skb_checksum(skb, offset,
+							 skb->len - offset, 0);
+				tcp_hdr(skb)->check =
+					csum_tcpudp_magic(iph->saddr,
+							  iph->daddr,
+							  skb->len - offset,
+							  IPPROTO_TCP,
+							  skb->csum);
+			} else if (iph->protocol == IPPROTO_UDP) {
+				skb->csum = 0;
+				udp_hdr(skb)->check = 0;
+				skb->csum =
+					skb_checksum(skb, offset,
+						     skb->len - offset, 0);
+				udp_hdr(skb)->check =
+					csum_tcpudp_magic(iph->saddr,
+							  iph->daddr,
+							  skb->len - offset,
+							  IPPROTO_UDP,
+							  skb->csum);
+			}
+		}
+	}
+	spin_lock_irqsave(&tx_ring->tx_lock, flags);
+	ring_num = tx_ring->next_to_use;
+	if (unlikely((ring_num + 1) == tx_ring->count))
+		tx_ring->next_to_use = 0;
+	else
+		tx_ring->next_to_use = ring_num + 1;
+
+	spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+	buffer_info = &tx_ring->buffer_info[ring_num];
+	tmp_skb = buffer_info->skb;
+
+	/* [Header:14][payload] ---> [Header:14][paddong:2][payload]    */
+	memcpy(tmp_skb->data, skb->data, ETH_HLEN);
+	tmp_skb->data[ETH_HLEN] = 0x00;
+	tmp_skb->data[ETH_HLEN + 1] = 0x00;
+	tmp_skb->len = skb->len;
+	memcpy(&tmp_skb->data[ETH_HLEN + 2], &skb->data[ETH_HLEN],
+	       (skb->len - ETH_HLEN));
+	/*-- Set Buffer infomation --*/
+	buffer_info->length = tmp_skb->len;
+	buffer_info->dma = dma_map_single(&adapter->pdev->dev, tmp_skb->data,
+					  buffer_info->length,
+					  DMA_TO_DEVICE);
+	if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) {
+		pr_err("TX DMA map failed\n");
+		buffer_info->dma = 0;
+		buffer_info->time_stamp = 0;
+		tx_ring->next_to_use = ring_num;
+		return;
+	}
+	buffer_info->mapped = true;
+	buffer_info->time_stamp = jiffies;
+
+	/*-- Set Tx descriptor --*/
+	tx_desc = PCH_GBE_TX_DESC(*tx_ring, ring_num);
+	tx_desc->buffer_addr = (buffer_info->dma);
+	tx_desc->length = (tmp_skb->len);
+	tx_desc->tx_words_eob = ((tmp_skb->len + 3));
+	tx_desc->tx_frame_ctrl = (frame_ctrl);
+	tx_desc->gbec_status = (DSC_INIT16);
+
+	if (unlikely(++ring_num == tx_ring->count))
+		ring_num = 0;
+
+	/* Update software pointer of TX descriptor */
+	iowrite32(tx_ring->dma +
+		  (int)sizeof(struct pch_gbe_tx_desc) * ring_num,
+		  &hw->reg->TX_DSC_SW_P);
+	dev_kfree_skb_any(skb);
+}
+
+/**
+ * pch_gbe_update_stats - Update the board statistics counters
+ * @adapter:  Board private structure
+ */
+void pch_gbe_update_stats(struct pch_gbe_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	struct pch_gbe_hw_stats *stats = &adapter->stats;
+	unsigned long flags;
+
+	/*
+	 * Prevent stats update while adapter is being reset, or if the pci
+	 * connection is down.
+	 */
+	if ((pdev->error_state) && (pdev->error_state != pci_channel_io_normal))
+		return;
+
+	spin_lock_irqsave(&adapter->stats_lock, flags);
+
+	/* Update device status "adapter->stats" */
+	stats->rx_errors = stats->rx_crc_errors + stats->rx_frame_errors;
+	stats->tx_errors = stats->tx_length_errors +
+	    stats->tx_aborted_errors +
+	    stats->tx_carrier_errors + stats->tx_timeout_count;
+
+	/* Update network device status "adapter->net_stats" */
+	netdev->stats.rx_packets = stats->rx_packets;
+	netdev->stats.rx_bytes = stats->rx_bytes;
+	netdev->stats.rx_dropped = stats->rx_dropped;
+	netdev->stats.tx_packets = stats->tx_packets;
+	netdev->stats.tx_bytes = stats->tx_bytes;
+	netdev->stats.tx_dropped = stats->tx_dropped;
+	/* Fill out the OS statistics structure */
+	netdev->stats.multicast = stats->multicast;
+	netdev->stats.collisions = stats->collisions;
+	/* Rx Errors */
+	netdev->stats.rx_errors = stats->rx_errors;
+	netdev->stats.rx_crc_errors = stats->rx_crc_errors;
+	netdev->stats.rx_frame_errors = stats->rx_frame_errors;
+	/* Tx Errors */
+	netdev->stats.tx_errors = stats->tx_errors;
+	netdev->stats.tx_aborted_errors = stats->tx_aborted_errors;
+	netdev->stats.tx_carrier_errors = stats->tx_carrier_errors;
+
+	spin_unlock_irqrestore(&adapter->stats_lock, flags);
+}
+
+/**
+ * pch_gbe_intr - Interrupt Handler
+ * @irq:   Interrupt number
+ * @data:  Pointer to a network interface device structure
+ * Returns
+ *	- IRQ_HANDLED:	Our interrupt
+ *	- IRQ_NONE:	Not our interrupt
+ */
+static irqreturn_t pch_gbe_intr(int irq, void *data)
+{
+	struct net_device *netdev = data;
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+	u32 int_st;
+	u32 int_en;
+
+	/* Check request status */
+	int_st = ioread32(&hw->reg->INT_ST);
+	int_st = int_st & ioread32(&hw->reg->INT_EN);
+	/* When request status is no interruption factor */
+	if (unlikely(!int_st))
+		return IRQ_NONE;	/* Not our interrupt. End processing. */
+	pr_debug("%s occur int_st = 0x%08x\n", __func__, int_st);
+	if (int_st & PCH_GBE_INT_RX_FRAME_ERR)
+		adapter->stats.intr_rx_frame_err_count++;
+	if (int_st & PCH_GBE_INT_RX_FIFO_ERR)
+		adapter->stats.intr_rx_fifo_err_count++;
+	if (int_st & PCH_GBE_INT_RX_DMA_ERR)
+		adapter->stats.intr_rx_dma_err_count++;
+	if (int_st & PCH_GBE_INT_TX_FIFO_ERR)
+		adapter->stats.intr_tx_fifo_err_count++;
+	if (int_st & PCH_GBE_INT_TX_DMA_ERR)
+		adapter->stats.intr_tx_dma_err_count++;
+	if (int_st & PCH_GBE_INT_TCPIP_ERR)
+		adapter->stats.intr_tcpip_err_count++;
+	/* When Rx descriptor is empty  */
+	if ((int_st & PCH_GBE_INT_RX_DSC_EMP)) {
+		adapter->stats.intr_rx_dsc_empty_count++;
+		pr_err("Rx descriptor is empty\n");
+		int_en = ioread32(&hw->reg->INT_EN);
+		iowrite32((int_en & ~PCH_GBE_INT_RX_DSC_EMP), &hw->reg->INT_EN);
+		if (hw->mac.tx_fc_enable) {
+			/* Set Pause packet */
+			pch_gbe_mac_set_pause_packet(hw);
+		}
+		if ((int_en & (PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT))
+		    == 0) {
+			return IRQ_HANDLED;
+		}
+	}
+
+	/* When request status is Receive interruption */
+	if ((int_st & (PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT))) {
+		if (likely(napi_schedule_prep(&adapter->napi))) {
+			/* Enable only Rx Descriptor empty */
+			atomic_inc(&adapter->irq_sem);
+			int_en = ioread32(&hw->reg->INT_EN);
+			int_en &=
+			    ~(PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT);
+			iowrite32(int_en, &hw->reg->INT_EN);
+			/* Start polling for NAPI */
+			__napi_schedule(&adapter->napi);
+		}
+	}
+	pr_debug("return = 0x%08x  INT_EN reg = 0x%08x\n",
+		 IRQ_HANDLED, ioread32(&hw->reg->INT_EN));
+	return IRQ_HANDLED;
+}
+
+/**
+ * pch_gbe_alloc_rx_buffers - Replace used receive buffers; legacy & extended
+ * @adapter:       Board private structure
+ * @rx_ring:       Rx descriptor ring
+ * @cleaned_count: Cleaned count
+ */
+static void
+pch_gbe_alloc_rx_buffers(struct pch_gbe_adapter *adapter,
+			 struct pch_gbe_rx_ring *rx_ring, int cleaned_count)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	struct pch_gbe_hw *hw = &adapter->hw;
+	struct pch_gbe_rx_desc *rx_desc;
+	struct pch_gbe_buffer *buffer_info;
+	struct sk_buff *skb;
+	unsigned int i;
+	unsigned int bufsz;
+
+	bufsz = adapter->rx_buffer_len + PCH_GBE_DMA_ALIGN;
+	i = rx_ring->next_to_use;
+
+	while ((cleaned_count--)) {
+		buffer_info = &rx_ring->buffer_info[i];
+		skb = buffer_info->skb;
+		if (skb) {
+			skb_trim(skb, 0);
+		} else {
+			skb = netdev_alloc_skb(netdev, bufsz);
+			if (unlikely(!skb)) {
+				/* Better luck next round */
+				adapter->stats.rx_alloc_buff_failed++;
+				break;
+			}
+			/* 64byte align */
+			skb_reserve(skb, PCH_GBE_DMA_ALIGN);
+
+			buffer_info->skb = skb;
+			buffer_info->length = adapter->rx_buffer_len;
+		}
+		buffer_info->dma = dma_map_single(&pdev->dev,
+						  skb->data,
+						  buffer_info->length,
+						  DMA_FROM_DEVICE);
+		if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) {
+			dev_kfree_skb(skb);
+			buffer_info->skb = NULL;
+			buffer_info->dma = 0;
+			adapter->stats.rx_alloc_buff_failed++;
+			break; /* while !buffer_info->skb */
+		}
+		buffer_info->mapped = true;
+		rx_desc = PCH_GBE_RX_DESC(*rx_ring, i);
+		rx_desc->buffer_addr = (buffer_info->dma);
+		rx_desc->gbec_status = DSC_INIT16;
+
+		pr_debug("i = %d  buffer_info->dma = 0x08%llx  buffer_info->length = 0x%x\n",
+			 i, (unsigned long long)buffer_info->dma,
+			 buffer_info->length);
+
+		if (unlikely(++i == rx_ring->count))
+			i = 0;
+	}
+	if (likely(rx_ring->next_to_use != i)) {
+		rx_ring->next_to_use = i;
+		if (unlikely(i-- == 0))
+			i = (rx_ring->count - 1);
+		iowrite32(rx_ring->dma +
+			  (int)sizeof(struct pch_gbe_rx_desc) * i,
+			  &hw->reg->RX_DSC_SW_P);
+	}
+	return;
+}
+
+/**
+ * pch_gbe_alloc_tx_buffers - Allocate transmit buffers
+ * @adapter:   Board private structure
+ * @tx_ring:   Tx descriptor ring
+ */
+static void pch_gbe_alloc_tx_buffers(struct pch_gbe_adapter *adapter,
+					struct pch_gbe_tx_ring *tx_ring)
+{
+	struct pch_gbe_buffer *buffer_info;
+	struct sk_buff *skb;
+	unsigned int i;
+	unsigned int bufsz;
+	struct pch_gbe_tx_desc *tx_desc;
+
+	bufsz =
+	    adapter->hw.mac.max_frame_size + PCH_GBE_DMA_ALIGN + NET_IP_ALIGN;
+
+	for (i = 0; i < tx_ring->count; i++) {
+		buffer_info = &tx_ring->buffer_info[i];
+		skb = netdev_alloc_skb(adapter->netdev, bufsz);
+		skb_reserve(skb, PCH_GBE_DMA_ALIGN);
+		buffer_info->skb = skb;
+		tx_desc = PCH_GBE_TX_DESC(*tx_ring, i);
+		tx_desc->gbec_status = (DSC_INIT16);
+	}
+	return;
+}
+
+/**
+ * pch_gbe_clean_tx - Reclaim resources after transmit completes
+ * @adapter:   Board private structure
+ * @tx_ring:   Tx descriptor ring
+ * Returns
+ *	true:  Cleaned the descriptor
+ *	false: Not cleaned the descriptor
+ */
+static bool
+pch_gbe_clean_tx(struct pch_gbe_adapter *adapter,
+		 struct pch_gbe_tx_ring *tx_ring)
+{
+	struct pch_gbe_tx_desc *tx_desc;
+	struct pch_gbe_buffer *buffer_info;
+	struct sk_buff *skb;
+	unsigned int i;
+	unsigned int cleaned_count = 0;
+	bool cleaned = false;
+
+	pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean);
+
+	i = tx_ring->next_to_clean;
+	tx_desc = PCH_GBE_TX_DESC(*tx_ring, i);
+	pr_debug("gbec_status:0x%04x  dma_status:0x%04x\n",
+		 tx_desc->gbec_status, tx_desc->dma_status);
+
+	while ((tx_desc->gbec_status & DSC_INIT16) == 0x0000) {
+		pr_debug("gbec_status:0x%04x\n", tx_desc->gbec_status);
+		cleaned = true;
+		buffer_info = &tx_ring->buffer_info[i];
+		skb = buffer_info->skb;
+
+		if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_ABT)) {
+			adapter->stats.tx_aborted_errors++;
+			pr_err("Transfer Abort Error\n");
+		} else if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_CRSER)
+			  ) {
+			adapter->stats.tx_carrier_errors++;
+			pr_err("Transfer Carrier Sense Error\n");
+		} else if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_EXCOL)
+			  ) {
+			adapter->stats.tx_aborted_errors++;
+			pr_err("Transfer Collision Abort Error\n");
+		} else if ((tx_desc->gbec_status &
+			    (PCH_GBE_TXD_GMAC_STAT_SNGCOL |
+			     PCH_GBE_TXD_GMAC_STAT_MLTCOL))) {
+			adapter->stats.collisions++;
+			adapter->stats.tx_packets++;
+			adapter->stats.tx_bytes += skb->len;
+			pr_debug("Transfer Collision\n");
+		} else if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_CMPLT)
+			  ) {
+			adapter->stats.tx_packets++;
+			adapter->stats.tx_bytes += skb->len;
+		}
+		if (buffer_info->mapped) {
+			pr_debug("unmap buffer_info->dma : %d\n", i);
+			dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
+					 buffer_info->length, DMA_TO_DEVICE);
+			buffer_info->mapped = false;
+		}
+		if (buffer_info->skb) {
+			pr_debug("trim buffer_info->skb : %d\n", i);
+			skb_trim(buffer_info->skb, 0);
+		}
+		tx_desc->gbec_status = DSC_INIT16;
+		if (unlikely(++i == tx_ring->count))
+			i = 0;
+		tx_desc = PCH_GBE_TX_DESC(*tx_ring, i);
+
+		/* weight of a sort for tx, to avoid endless transmit cleanup */
+		if (cleaned_count++ == PCH_GBE_TX_WEIGHT)
+			break;
+	}
+	pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n",
+		 cleaned_count);
+	/* Recover from running out of Tx resources in xmit_frame */
+	if (unlikely(cleaned && (netif_queue_stopped(adapter->netdev)))) {
+		netif_wake_queue(adapter->netdev);
+		adapter->stats.tx_restart_count++;
+		pr_debug("Tx wake queue\n");
+	}
+	spin_lock(&adapter->tx_queue_lock);
+	tx_ring->next_to_clean = i;
+	spin_unlock(&adapter->tx_queue_lock);
+	pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean);
+	return cleaned;
+}
+
+/**
+ * pch_gbe_clean_rx - Send received data up the network stack; legacy
+ * @adapter:     Board private structure
+ * @rx_ring:     Rx descriptor ring
+ * @work_done:   Completed count
+ * @work_to_do:  Request count
+ * Returns
+ *	true:  Cleaned the descriptor
+ *	false: Not cleaned the descriptor
+ */
+static bool
+pch_gbe_clean_rx(struct pch_gbe_adapter *adapter,
+		 struct pch_gbe_rx_ring *rx_ring,
+		 int *work_done, int work_to_do)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	struct pch_gbe_buffer *buffer_info;
+	struct pch_gbe_rx_desc *rx_desc;
+	u32 length;
+	unsigned char tmp_packet[ETH_HLEN];
+	unsigned int i;
+	unsigned int cleaned_count = 0;
+	bool cleaned = false;
+	struct sk_buff *skb;
+	u8 dma_status;
+	u16 gbec_status;
+	u32 tcp_ip_status;
+	u8 skb_copy_flag = 0;
+	u8 skb_padding_flag = 0;
+
+	i = rx_ring->next_to_clean;
+
+	while (*work_done < work_to_do) {
+		/* Check Rx descriptor status */
+		rx_desc = PCH_GBE_RX_DESC(*rx_ring, i);
+		if (rx_desc->gbec_status == DSC_INIT16)
+			break;
+		cleaned = true;
+		cleaned_count++;
+
+		dma_status = rx_desc->dma_status;
+		gbec_status = rx_desc->gbec_status;
+		tcp_ip_status = rx_desc->tcp_ip_status;
+		rx_desc->gbec_status = DSC_INIT16;
+		buffer_info = &rx_ring->buffer_info[i];
+		skb = buffer_info->skb;
+
+		/* unmap dma */
+		dma_unmap_single(&pdev->dev, buffer_info->dma,
+				   buffer_info->length, DMA_FROM_DEVICE);
+		buffer_info->mapped = false;
+		/* Prefetch the packet */
+		prefetch(skb->data);
+
+		pr_debug("RxDecNo = 0x%04x  Status[DMA:0x%02x GBE:0x%04x "
+			 "TCP:0x%08x]  BufInf = 0x%p\n",
+			 i, dma_status, gbec_status, tcp_ip_status,
+			 buffer_info);
+		/* Error check */
+		if (unlikely(gbec_status & PCH_GBE_RXD_GMAC_STAT_NOTOCTAL)) {
+			adapter->stats.rx_frame_errors++;
+			pr_err("Receive Not Octal Error\n");
+		} else if (unlikely(gbec_status &
+				PCH_GBE_RXD_GMAC_STAT_NBLERR)) {
+			adapter->stats.rx_frame_errors++;
+			pr_err("Receive Nibble Error\n");
+		} else if (unlikely(gbec_status &
+				PCH_GBE_RXD_GMAC_STAT_CRCERR)) {
+			adapter->stats.rx_crc_errors++;
+			pr_err("Receive CRC Error\n");
+		} else {
+			/* get receive length */
+			/* length convert[-3], padding[-2] */
+			length = (rx_desc->rx_words_eob) - 3 - 2;
+
+			/* Decide the data conversion method */
+			if (!adapter->rx_csum) {
+				/* [Header:14][payload] */
+				skb_padding_flag = 0;
+				skb_copy_flag = 1;
+			} else {
+				/* [Header:14][padding:2][payload] */
+				skb_padding_flag = 1;
+				if (length < copybreak)
+					skb_copy_flag = 1;
+				else
+					skb_copy_flag = 0;
+			}
+
+			/* Data conversion */
+			if (skb_copy_flag) {	/* recycle  skb */
+				struct sk_buff *new_skb;
+				new_skb =
+				    netdev_alloc_skb(netdev,
+						     length + NET_IP_ALIGN);
+				if (new_skb) {
+					if (!skb_padding_flag) {
+						skb_reserve(new_skb,
+								NET_IP_ALIGN);
+					}
+					memcpy(new_skb->data, skb->data,
+						length);
+					/* save the skb
+					 * in buffer_info as good */
+					skb = new_skb;
+				} else if (!skb_padding_flag) {
+					/* dorrop error */
+					pr_err("New skb allocation Error\n");
+					goto dorrop;
+				}
+			} else {
+				buffer_info->skb = NULL;
+			}
+			if (skb_padding_flag) {
+				memcpy(&tmp_packet[0], &skb->data[0], ETH_HLEN);
+				memcpy(&skb->data[NET_IP_ALIGN], &tmp_packet[0],
+					ETH_HLEN);
+				skb_reserve(skb, NET_IP_ALIGN);
+
+			}
+
+			/* update status of driver */
+			adapter->stats.rx_bytes += length;
+			adapter->stats.rx_packets++;
+			if ((gbec_status & PCH_GBE_RXD_GMAC_STAT_MARMLT))
+				adapter->stats.multicast++;
+			/* Write meta date of skb */
+			skb_put(skb, length);
+			skb->protocol = eth_type_trans(skb, netdev);
+			if ((tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK) ==
+			    PCH_GBE_RXD_ACC_STAT_TCPIPOK) {
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+			} else {
+				skb->ip_summed = CHECKSUM_NONE;
+			}
+			napi_gro_receive(&adapter->napi, skb);
+			(*work_done)++;
+			pr_debug("Receive skb->ip_summed: %d length: %d\n",
+				 skb->ip_summed, length);
+		}
+dorrop:
+		/* return some buffers to hardware, one at a time is too slow */
+		if (unlikely(cleaned_count >= PCH_GBE_RX_BUFFER_WRITE)) {
+			pch_gbe_alloc_rx_buffers(adapter, rx_ring,
+						 cleaned_count);
+			cleaned_count = 0;
+		}
+		if (++i == rx_ring->count)
+			i = 0;
+	}
+	rx_ring->next_to_clean = i;
+	if (cleaned_count)
+		pch_gbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count);
+	return cleaned;
+}
+
+/**
+ * pch_gbe_setup_tx_resources - Allocate Tx resources (Descriptors)
+ * @adapter:  Board private structure
+ * @tx_ring:  Tx descriptor ring (for a specific queue) to setup
+ * Returns
+ *	0:		Successfully
+ *	Negative value:	Failed
+ */
+int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
+				struct pch_gbe_tx_ring *tx_ring)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct pch_gbe_tx_desc *tx_desc;
+	int size;
+	int desNo;
+
+	size = (int)sizeof(struct pch_gbe_buffer) * tx_ring->count;
+	tx_ring->buffer_info = vmalloc(size);
+	if (!tx_ring->buffer_info) {
+		pr_err("Unable to allocate memory for the buffer infomation\n");
+		return -ENOMEM;
+	}
+	memset(tx_ring->buffer_info, 0, size);
+
+	tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc);
+
+	tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
+					   &tx_ring->dma, GFP_KERNEL);
+	if (!tx_ring->desc) {
+		vfree(tx_ring->buffer_info);
+		pr_err("Unable to allocate memory for the transmit descriptor ring\n");
+		return -ENOMEM;
+	}
+	memset(tx_ring->desc, 0, tx_ring->size);
+
+	tx_ring->next_to_use = 0;
+	tx_ring->next_to_clean = 0;
+	spin_lock_init(&tx_ring->tx_lock);
+
+	for (desNo = 0; desNo < tx_ring->count; desNo++) {
+		tx_desc = PCH_GBE_TX_DESC(*tx_ring, desNo);
+		tx_desc->gbec_status = DSC_INIT16;
+	}
+	pr_debug("tx_ring->desc = 0x%p  tx_ring->dma = 0x%08llx\n"
+		 "next_to_clean = 0x%08x  next_to_use = 0x%08x\n",
+		 tx_ring->desc, (unsigned long long)tx_ring->dma,
+		 tx_ring->next_to_clean, tx_ring->next_to_use);
+	return 0;
+}
+
+/**
+ * pch_gbe_setup_rx_resources - Allocate Rx resources (Descriptors)
+ * @adapter:  Board private structure
+ * @rx_ring:  Rx descriptor ring (for a specific queue) to setup
+ * Returns
+ *	0:		Successfully
+ *	Negative value:	Failed
+ */
+int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
+				struct pch_gbe_rx_ring *rx_ring)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct pch_gbe_rx_desc *rx_desc;
+	int size;
+	int desNo;
+
+	size = (int)sizeof(struct pch_gbe_buffer) * rx_ring->count;
+	rx_ring->buffer_info = vmalloc(size);
+	if (!rx_ring->buffer_info) {
+		pr_err("Unable to allocate memory for the receive descriptor ring\n");
+		return -ENOMEM;
+	}
+	memset(rx_ring->buffer_info, 0, size);
+	rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc);
+	rx_ring->desc =	dma_alloc_coherent(&pdev->dev, rx_ring->size,
+					   &rx_ring->dma, GFP_KERNEL);
+
+	if (!rx_ring->desc) {
+		pr_err("Unable to allocate memory for the receive descriptor ring\n");
+		vfree(rx_ring->buffer_info);
+		return -ENOMEM;
+	}
+	memset(rx_ring->desc, 0, rx_ring->size);
+	rx_ring->next_to_clean = 0;
+	rx_ring->next_to_use = 0;
+	for (desNo = 0; desNo < rx_ring->count; desNo++) {
+		rx_desc = PCH_GBE_RX_DESC(*rx_ring, desNo);
+		rx_desc->gbec_status = DSC_INIT16;
+	}
+	pr_debug("rx_ring->desc = 0x%p  rx_ring->dma = 0x%08llx "
+		 "next_to_clean = 0x%08x  next_to_use = 0x%08x\n",
+		 rx_ring->desc, (unsigned long long)rx_ring->dma,
+		 rx_ring->next_to_clean, rx_ring->next_to_use);
+	return 0;
+}
+
+/**
+ * pch_gbe_free_tx_resources - Free Tx Resources
+ * @adapter:  Board private structure
+ * @tx_ring:  Tx descriptor ring for a specific queue
+ */
+void pch_gbe_free_tx_resources(struct pch_gbe_adapter *adapter,
+				struct pch_gbe_tx_ring *tx_ring)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	pch_gbe_clean_tx_ring(adapter, tx_ring);
+	vfree(tx_ring->buffer_info);
+	tx_ring->buffer_info = NULL;
+	pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
+	tx_ring->desc = NULL;
+}
+
+/**
+ * pch_gbe_free_rx_resources - Free Rx Resources
+ * @adapter:  Board private structure
+ * @rx_ring:  Ring to clean the resources from
+ */
+void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter,
+				struct pch_gbe_rx_ring *rx_ring)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	pch_gbe_clean_rx_ring(adapter, rx_ring);
+	vfree(rx_ring->buffer_info);
+	rx_ring->buffer_info = NULL;
+	pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
+	rx_ring->desc = NULL;
+}
+
+/**
+ * pch_gbe_request_irq - Allocate an interrupt line
+ * @adapter:  Board private structure
+ * Returns
+ *	0:		Successfully
+ *	Negative value:	Failed
+ */
+static int pch_gbe_request_irq(struct pch_gbe_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	int err;
+	int flags;
+
+	flags = IRQF_SHARED;
+	adapter->have_msi = false;
+	err = pci_enable_msi(adapter->pdev);
+	pr_debug("call pci_enable_msi\n");
+	if (err) {
+		pr_debug("call pci_enable_msi - Error: %d\n", err);
+	} else {
+		flags = 0;
+		adapter->have_msi = true;
+	}
+	err = request_irq(adapter->pdev->irq, &pch_gbe_intr,
+			  flags, netdev->name, netdev);
+	if (err)
+		pr_err("Unable to allocate interrupt Error: %d\n", err);
+	pr_debug("adapter->have_msi : %d  flags : 0x%04x  return : 0x%04x\n",
+		 adapter->have_msi, flags, err);
+	return err;
+}
+
+
+static void pch_gbe_set_multi(struct net_device *netdev);
+/**
+ * pch_gbe_up - Up GbE network device
+ * @adapter:  Board private structure
+ * Returns
+ *	0:		Successfully
+ *	Negative value:	Failed
+ */
+int pch_gbe_up(struct pch_gbe_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
+	struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
+	int err;
+
+	/* hardware has been reset, we need to reload some things */
+	pch_gbe_set_multi(netdev);
+
+	pch_gbe_setup_tctl(adapter);
+	pch_gbe_configure_tx(adapter);
+	pch_gbe_setup_rctl(adapter);
+	pch_gbe_configure_rx(adapter);
+
+	err = pch_gbe_request_irq(adapter);
+	if (err) {
+		pr_err("Error: can't bring device up\n");
+		return err;
+	}
+	pch_gbe_alloc_tx_buffers(adapter, tx_ring);
+	pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count);
+	adapter->tx_queue_len = netdev->tx_queue_len;
+
+	mod_timer(&adapter->watchdog_timer, jiffies);
+
+	napi_enable(&adapter->napi);
+	pch_gbe_irq_enable(adapter);
+	netif_start_queue(adapter->netdev);
+
+	return 0;
+}
+
+/**
+ * pch_gbe_down - Down GbE network device
+ * @adapter:  Board private structure
+ */
+void pch_gbe_down(struct pch_gbe_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	/* signal that we're down so the interrupt handler does not
+	 * reschedule our watchdog timer */
+	napi_disable(&adapter->napi);
+	atomic_set(&adapter->irq_sem, 0);
+
+	pch_gbe_irq_disable(adapter);
+	pch_gbe_free_irq(adapter);
+
+	del_timer_sync(&adapter->watchdog_timer);
+
+	netdev->tx_queue_len = adapter->tx_queue_len;
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+
+	pch_gbe_reset(adapter);
+	pch_gbe_clean_tx_ring(adapter, adapter->tx_ring);
+	pch_gbe_clean_rx_ring(adapter, adapter->rx_ring);
+}
+
+/**
+ * pch_gbe_sw_init - Initialize general software structures (struct pch_gbe_adapter)
+ * @adapter:  Board private structure to initialize
+ * Returns
+ *	0:		Successfully
+ *	Negative value:	Failed
+ */
+static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+
+	adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_2048;
+	hw->mac.max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
+	hw->mac.min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+
+	/* Initialize the hardware-specific values */
+	if (pch_gbe_hal_setup_init_funcs(hw)) {
+		pr_err("Hardware Initialization Failure\n");
+		return -EIO;
+	}
+	if (pch_gbe_alloc_queues(adapter)) {
+		pr_err("Unable to allocate memory for queues\n");
+		return -ENOMEM;
+	}
+	spin_lock_init(&adapter->hw.miim_lock);
+	spin_lock_init(&adapter->tx_queue_lock);
+	spin_lock_init(&adapter->stats_lock);
+	spin_lock_init(&adapter->ethtool_lock);
+	atomic_set(&adapter->irq_sem, 0);
+	pch_gbe_irq_disable(adapter);
+
+	pch_gbe_init_stats(adapter);
+
+	pr_debug("rx_buffer_len : %d  mac.min_frame_size : %d  mac.max_frame_size : %d\n",
+		 (u32) adapter->rx_buffer_len,
+		 hw->mac.min_frame_size, hw->mac.max_frame_size);
+	return 0;
+}
+
+/**
+ * pch_gbe_open - Called when a network interface is made active
+ * @netdev:	Network interface device structure
+ * Returns
+ *	0:		Successfully
+ *	Negative value:	Failed
+ */
+static int pch_gbe_open(struct net_device *netdev)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+	int err;
+
+	/* allocate transmit descriptors */
+	err = pch_gbe_setup_tx_resources(adapter, adapter->tx_ring);
+	if (err)
+		goto err_setup_tx;
+	/* allocate receive descriptors */
+	err = pch_gbe_setup_rx_resources(adapter, adapter->rx_ring);
+	if (err)
+		goto err_setup_rx;
+	pch_gbe_hal_power_up_phy(hw);
+	err = pch_gbe_up(adapter);
+	if (err)
+		goto err_up;
+	pr_debug("Success End\n");
+	return 0;
+
+err_up:
+	if (!adapter->wake_up_evt)
+		pch_gbe_hal_power_down_phy(hw);
+	pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
+err_setup_rx:
+	pch_gbe_free_tx_resources(adapter, adapter->tx_ring);
+err_setup_tx:
+	pch_gbe_reset(adapter);
+	pr_err("Error End\n");
+	return err;
+}
+
+/**
+ * pch_gbe_stop - Disables a network interface
+ * @netdev:  Network interface device structure
+ * Returns
+ *	0: Successfully
+ */
+static int pch_gbe_stop(struct net_device *netdev)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+
+	pch_gbe_down(adapter);
+	if (!adapter->wake_up_evt)
+		pch_gbe_hal_power_down_phy(hw);
+	pch_gbe_free_tx_resources(adapter, adapter->tx_ring);
+	pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
+	return 0;
+}
+
+/**
+ * pch_gbe_xmit_frame - Packet transmitting start
+ * @skb:     Socket buffer structure
+ * @netdev:  Network interface device structure
+ * Returns
+ *	- NETDEV_TX_OK:   Normal end
+ *	- NETDEV_TX_BUSY: Error end
+ */
+static int pch_gbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
+	unsigned long flags;
+
+	if (unlikely(skb->len > (adapter->hw.mac.max_frame_size - 4))) {
+		pr_err("Transfer length Error: skb len: %d > max: %d\n",
+		       skb->len, adapter->hw.mac.max_frame_size);
+		dev_kfree_skb_any(skb);
+		adapter->stats.tx_length_errors++;
+		return NETDEV_TX_OK;
+	}
+	if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) {
+		/* Collision - tell upper layer to requeue */
+		return NETDEV_TX_LOCKED;
+	}
+	if (unlikely(!PCH_GBE_DESC_UNUSED(tx_ring))) {
+		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+		pr_debug("Return : BUSY  next_to use : 0x%08x  next_to clean : 0x%08x\n",
+			 tx_ring->next_to_use, tx_ring->next_to_clean);
+		return NETDEV_TX_BUSY;
+	}
+	spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+
+	/* CRC,ITAG no support */
+	pch_gbe_tx_queue(adapter, tx_ring, skb);
+	return NETDEV_TX_OK;
+}
+
+/**
+ * pch_gbe_get_stats - Get System Network Statistics
+ * @netdev:  Network interface device structure
+ * Returns:  The current stats
+ */
+static struct net_device_stats *pch_gbe_get_stats(struct net_device *netdev)
+{
+	/* only return the current stats */
+	return &netdev->stats;
+}
+
+/**
+ * pch_gbe_set_multi - Multicast and Promiscuous mode set
+ * @netdev:   Network interface device structure
+ */
+static void pch_gbe_set_multi(struct net_device *netdev)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+	struct netdev_hw_addr *ha;
+	u8 *mta_list;
+	u32 rctl;
+	int i;
+	int mc_count;
+
+	pr_debug("netdev->flags : 0x%08x\n", netdev->flags);
+
+	/* Check for Promiscuous and All Multicast modes */
+	rctl = ioread32(&hw->reg->RX_MODE);
+	mc_count = netdev_mc_count(netdev);
+	if ((netdev->flags & IFF_PROMISC)) {
+		rctl &= ~PCH_GBE_ADD_FIL_EN;
+		rctl &= ~PCH_GBE_MLT_FIL_EN;
+	} else if ((netdev->flags & IFF_ALLMULTI)) {
+		/* all the multicasting receive permissions */
+		rctl |= PCH_GBE_ADD_FIL_EN;
+		rctl &= ~PCH_GBE_MLT_FIL_EN;
+	} else {
+		if (mc_count >= PCH_GBE_MAR_ENTRIES) {
+			/* all the multicasting receive permissions */
+			rctl |= PCH_GBE_ADD_FIL_EN;
+			rctl &= ~PCH_GBE_MLT_FIL_EN;
+		} else {
+			rctl |= (PCH_GBE_ADD_FIL_EN | PCH_GBE_MLT_FIL_EN);
+		}
+	}
+	iowrite32(rctl, &hw->reg->RX_MODE);
+
+	if (mc_count >= PCH_GBE_MAR_ENTRIES)
+		return;
+	mta_list = kmalloc(mc_count * ETH_ALEN, GFP_ATOMIC);
+	if (!mta_list)
+		return;
+
+	/* The shared function expects a packed array of only addresses. */
+	i = 0;
+	netdev_for_each_mc_addr(ha, netdev) {
+		if (i == mc_count)
+			break;
+		memcpy(mta_list + (i++ * ETH_ALEN), &ha->addr, ETH_ALEN);
+	}
+	pch_gbe_mac_mc_addr_list_update(hw, mta_list, i, 1,
+					PCH_GBE_MAR_ENTRIES);
+	kfree(mta_list);
+
+	pr_debug("RX_MODE reg(check bit31,30 ADD,MLT) : 0x%08x  netdev->mc_count : 0x%08x\n",
+		 ioread32(&hw->reg->RX_MODE), mc_count);
+}
+
+/**
+ * pch_gbe_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: Network interface device structure
+ * @addr:   Pointer to an address structure
+ * Returns
+ *	0:		Successfully
+ *	-EADDRNOTAVAIL:	Failed
+ */
+static int pch_gbe_set_mac(struct net_device *netdev, void *addr)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct sockaddr *skaddr = addr;
+	int ret_val;
+
+	if (!is_valid_ether_addr(skaddr->sa_data)) {
+		ret_val = -EADDRNOTAVAIL;
+	} else {
+		memcpy(netdev->dev_addr, skaddr->sa_data, netdev->addr_len);
+		memcpy(adapter->hw.mac.addr, skaddr->sa_data, netdev->addr_len);
+		pch_gbe_mac_mar_set(&adapter->hw, adapter->hw.mac.addr, 0);
+		ret_val = 0;
+	}
+	pr_debug("ret_val : 0x%08x\n", ret_val);
+	pr_debug("dev_addr : %pM\n", netdev->dev_addr);
+	pr_debug("mac_addr : %pM\n", adapter->hw.mac.addr);
+	pr_debug("MAC_ADR1AB reg : 0x%08x 0x%08x\n",
+		 ioread32(&adapter->hw.reg->mac_adr[0].high),
+		 ioread32(&adapter->hw.reg->mac_adr[0].low));
+	return ret_val;
+}
+
+/**
+ * pch_gbe_change_mtu - Change the Maximum Transfer Unit
+ * @netdev:   Network interface device structure
+ * @new_mtu:  New value for maximum frame size
+ * Returns
+ *	0:		Successfully
+ *	-EINVAL:	Failed
+ */
+static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	int max_frame;
+
+	max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
+	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+		(max_frame > PCH_GBE_MAX_JUMBO_FRAME_SIZE)) {
+		pr_err("Invalid MTU setting\n");
+		return -EINVAL;
+	}
+	if (max_frame <= PCH_GBE_FRAME_SIZE_2048)
+		adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_2048;
+	else if (max_frame <= PCH_GBE_FRAME_SIZE_4096)
+		adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_4096;
+	else if (max_frame <= PCH_GBE_FRAME_SIZE_8192)
+		adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_8192;
+	else
+		adapter->rx_buffer_len = PCH_GBE_MAX_JUMBO_FRAME_SIZE;
+	netdev->mtu = new_mtu;
+	adapter->hw.mac.max_frame_size = max_frame;
+
+	if (netif_running(netdev))
+		pch_gbe_reinit_locked(adapter);
+	else
+		pch_gbe_reset(adapter);
+
+	pr_debug("max_frame : %d  rx_buffer_len : %d  mtu : %d  max_frame_size : %d\n",
+		 max_frame, (u32) adapter->rx_buffer_len, netdev->mtu,
+		 adapter->hw.mac.max_frame_size);
+	return 0;
+}
+
+/**
+ * pch_gbe_ioctl - Controls register through a MII interface
+ * @netdev:   Network interface device structure
+ * @ifr:      Pointer to ifr structure
+ * @cmd:      Control command
+ * Returns
+ *	0:	Successfully
+ *	Negative value:	Failed
+ */
+static int pch_gbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	pr_debug("cmd : 0x%04x\n", cmd);
+
+	return generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+}
+
+/**
+ * pch_gbe_tx_timeout - Respond to a Tx Hang
+ * @netdev:   Network interface device structure
+ */
+static void pch_gbe_tx_timeout(struct net_device *netdev)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	/* Do the reset outside of interrupt context */
+	adapter->stats.tx_timeout_count++;
+	schedule_work(&adapter->reset_task);
+}
+
+/**
+ * pch_gbe_napi_poll - NAPI receive and transfer polling callback
+ * @napi:    Pointer of polling device struct
+ * @budget:  The maximum number of a packet
+ * Returns
+ *	false:  Exit the polling mode
+ *	true:   Continue the polling mode
+ */
+static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
+{
+	struct pch_gbe_adapter *adapter =
+	    container_of(napi, struct pch_gbe_adapter, napi);
+	struct net_device *netdev = adapter->netdev;
+	int work_done = 0;
+	bool poll_end_flag = false;
+	bool cleaned = false;
+
+	pr_debug("budget : %d\n", budget);
+
+	/* Keep link state information with original netdev */
+	if (!netif_carrier_ok(netdev)) {
+		poll_end_flag = true;
+	} else {
+		cleaned = pch_gbe_clean_tx(adapter, adapter->tx_ring);
+		pch_gbe_clean_rx(adapter, adapter->rx_ring, &work_done, budget);
+
+		if (cleaned)
+			work_done = budget;
+		/* If no Tx and not enough Rx work done,
+		 * exit the polling mode
+		 */
+		if ((work_done < budget) || !netif_running(netdev))
+			poll_end_flag = true;
+	}
+
+	if (poll_end_flag) {
+		napi_complete(napi);
+		pch_gbe_irq_enable(adapter);
+	}
+
+	pr_debug("poll_end_flag : %d  work_done : %d  budget : %d\n",
+		 poll_end_flag, work_done, budget);
+
+	return work_done;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * pch_gbe_netpoll - Used by things like netconsole to send skbs
+ * @netdev:  Network interface device structure
+ */
+static void pch_gbe_netpoll(struct net_device *netdev)
+{
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	disable_irq(adapter->pdev->irq);
+	pch_gbe_intr(adapter->pdev->irq, netdev);
+	enable_irq(adapter->pdev->irq);
+}
+#endif
+
+static const struct net_device_ops pch_gbe_netdev_ops = {
+	.ndo_open = pch_gbe_open,
+	.ndo_stop = pch_gbe_stop,
+	.ndo_start_xmit = pch_gbe_xmit_frame,
+	.ndo_get_stats = pch_gbe_get_stats,
+	.ndo_set_mac_address = pch_gbe_set_mac,
+	.ndo_tx_timeout = pch_gbe_tx_timeout,
+	.ndo_change_mtu = pch_gbe_change_mtu,
+	.ndo_do_ioctl = pch_gbe_ioctl,
+	.ndo_set_multicast_list = &pch_gbe_set_multi,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller = pch_gbe_netpoll,
+#endif
+};
+
+static pci_ers_result_t pch_gbe_io_error_detected(struct pci_dev *pdev,
+						pci_channel_state_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	netif_device_detach(netdev);
+	if (netif_running(netdev))
+		pch_gbe_down(adapter);
+	pci_disable_device(pdev);
+	/* Request a slot slot reset. */
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t pch_gbe_io_slot_reset(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+
+	if (pci_enable_device(pdev)) {
+		pr_err("Cannot re-enable PCI device after reset\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+	pci_set_master(pdev);
+	pci_enable_wake(pdev, PCI_D0, 0);
+	pch_gbe_hal_power_up_phy(hw);
+	pch_gbe_reset(adapter);
+	/* Clear wake up status */
+	pch_gbe_mac_set_wol_event(hw, 0);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void pch_gbe_io_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	if (netif_running(netdev)) {
+		if (pch_gbe_up(adapter)) {
+			pr_debug("can't bring device back up after reset\n");
+			return;
+		}
+	}
+	netif_device_attach(netdev);
+}
+
+static int __pch_gbe_suspend(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+	u32 wufc = adapter->wake_up_evt;
+	int retval = 0;
+
+	netif_device_detach(netdev);
+	if (netif_running(netdev))
+		pch_gbe_down(adapter);
+	if (wufc) {
+		pch_gbe_set_multi(netdev);
+		pch_gbe_setup_rctl(adapter);
+		pch_gbe_configure_rx(adapter);
+		pch_gbe_set_rgmii_ctrl(adapter, hw->mac.link_speed,
+					hw->mac.link_duplex);
+		pch_gbe_set_mode(adapter, hw->mac.link_speed,
+					hw->mac.link_duplex);
+		pch_gbe_mac_set_wol_event(hw, wufc);
+		pci_disable_device(pdev);
+	} else {
+		pch_gbe_hal_power_down_phy(hw);
+		pch_gbe_mac_set_wol_event(hw, wufc);
+		pci_disable_device(pdev);
+	}
+	return retval;
+}
+
+#ifdef CONFIG_PM
+static int pch_gbe_suspend(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+
+	return __pch_gbe_suspend(pdev);
+}
+
+static int pch_gbe_resume(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+	struct pch_gbe_hw *hw = &adapter->hw;
+	u32 err;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		pr_err("Cannot enable PCI device from suspend\n");
+		return err;
+	}
+	pci_set_master(pdev);
+	pch_gbe_hal_power_up_phy(hw);
+	pch_gbe_reset(adapter);
+	/* Clear wake on lan control and status */
+	pch_gbe_mac_set_wol_event(hw, 0);
+
+	if (netif_running(netdev))
+		pch_gbe_up(adapter);
+	netif_device_attach(netdev);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static void pch_gbe_shutdown(struct pci_dev *pdev)
+{
+	__pch_gbe_suspend(pdev);
+	if (system_state == SYSTEM_POWER_OFF) {
+		pci_wake_from_d3(pdev, true);
+		pci_set_power_state(pdev, PCI_D3hot);
+	}
+}
+
+static void pch_gbe_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+	flush_scheduled_work();
+	unregister_netdev(netdev);
+
+	pch_gbe_hal_phy_hw_reset(&adapter->hw);
+
+	kfree(adapter->tx_ring);
+	kfree(adapter->rx_ring);
+
+	iounmap(adapter->hw.reg);
+	pci_release_regions(pdev);
+	free_netdev(netdev);
+	pci_disable_device(pdev);
+}
+
+static int pch_gbe_probe(struct pci_dev *pdev,
+			  const struct pci_device_id *pci_id)
+{
+	struct net_device *netdev;
+	struct pch_gbe_adapter *adapter;
+	int ret;
+
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
+
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
+		|| pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+		ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (ret) {
+			ret = pci_set_consistent_dma_mask(pdev,
+							  DMA_BIT_MASK(32));
+			if (ret) {
+				dev_err(&pdev->dev, "ERR: No usable DMA "
+					"configuration, aborting\n");
+				goto err_disable_device;
+			}
+		}
+	}
+
+	ret = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"ERR: Can't reserve PCI I/O and memory resources\n");
+		goto err_disable_device;
+	}
+	pci_set_master(pdev);
+
+	netdev = alloc_etherdev((int)sizeof(struct pch_gbe_adapter));
+	if (!netdev) {
+		ret = -ENOMEM;
+		dev_err(&pdev->dev,
+			"ERR: Can't allocate and set up an Ethernet device\n");
+		goto err_release_pci;
+	}
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+
+	pci_set_drvdata(pdev, netdev);
+	adapter = netdev_priv(netdev);
+	adapter->netdev = netdev;
+	adapter->pdev = pdev;
+	adapter->hw.back = adapter;
+	adapter->hw.reg = pci_iomap(pdev, PCH_GBE_PCI_BAR, 0);
+	if (!adapter->hw.reg) {
+		ret = -EIO;
+		dev_err(&pdev->dev, "Can't ioremap\n");
+		goto err_free_netdev;
+	}
+
+	netdev->netdev_ops = &pch_gbe_netdev_ops;
+	netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
+	netif_napi_add(netdev, &adapter->napi,
+		       pch_gbe_napi_poll, PCH_GBE_RX_WEIGHT);
+	netdev->features = NETIF_F_HW_CSUM | NETIF_F_GRO;
+	pch_gbe_set_ethtool_ops(netdev);
+
+	pch_gbe_mac_reset_hw(&adapter->hw);
+
+	/* setup the private structure */
+	ret = pch_gbe_sw_init(adapter);
+	if (ret)
+		goto err_iounmap;
+
+	/* Initialize PHY */
+	ret = pch_gbe_init_phy(adapter);
+	if (ret) {
+		dev_err(&pdev->dev, "PHY initialize error\n");
+		goto err_free_adapter;
+	}
+	pch_gbe_hal_get_bus_info(&adapter->hw);
+
+	/* Read the MAC address. and store to the private data */
+	ret = pch_gbe_hal_read_mac_addr(&adapter->hw);
+	if (ret) {
+		dev_err(&pdev->dev, "MAC address Read Error\n");
+		goto err_free_adapter;
+	}
+
+	memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
+	if (!is_valid_ether_addr(netdev->dev_addr)) {
+		dev_err(&pdev->dev, "Invalid MAC Address\n");
+		ret = -EIO;
+		goto err_free_adapter;
+	}
+	setup_timer(&adapter->watchdog_timer, pch_gbe_watchdog,
+		    (unsigned long)adapter);
+
+	INIT_WORK(&adapter->reset_task, pch_gbe_reset_task);
+
+	pch_gbe_check_options(adapter);
+
+	if (adapter->tx_csum)
+		netdev->features |= NETIF_F_HW_CSUM;
+	else
+		netdev->features &= ~NETIF_F_HW_CSUM;
+
+	/* initialize the wol settings based on the eeprom settings */
+	adapter->wake_up_evt = PCH_GBE_WL_INIT_SETTING;
+	dev_info(&pdev->dev, "MAC address : %pM\n", netdev->dev_addr);
+
+	/* reset the hardware with the new settings */
+	pch_gbe_reset(adapter);
+
+	ret = register_netdev(netdev);
+	if (ret)
+		goto err_free_adapter;
+	/* tell the stack to leave us alone until pch_gbe_open() is called */
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+
+	dev_dbg(&pdev->dev, "OKIsemi(R) PCH Network Connection\n");
+
+	device_set_wakeup_enable(&pdev->dev, 1);
+	return 0;
+
+err_free_adapter:
+	pch_gbe_hal_phy_hw_reset(&adapter->hw);
+	kfree(adapter->tx_ring);
+	kfree(adapter->rx_ring);
+err_iounmap:
+	iounmap(adapter->hw.reg);
+err_free_netdev:
+	free_netdev(netdev);
+err_release_pci:
+	pci_release_regions(pdev);
+err_disable_device:
+	pci_disable_device(pdev);
+	return ret;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = {
+	{.vendor = PCI_VENDOR_ID_INTEL,
+	 .device = PCI_DEVICE_ID_INTEL_IOH1_GBE,
+	 .subvendor = PCI_ANY_ID,
+	 .subdevice = PCI_ANY_ID,
+	 .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
+	 .class_mask = (0xFFFF00)
+	 },
+	/* required last entry */
+	{0}
+};
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops pch_gbe_pm_ops = {
+	.suspend = pch_gbe_suspend,
+	.resume = pch_gbe_resume,
+	.freeze = pch_gbe_suspend,
+	.thaw = pch_gbe_resume,
+	.poweroff = pch_gbe_suspend,
+	.restore = pch_gbe_resume,
+};
+#endif
+
+static struct pci_error_handlers pch_gbe_err_handler = {
+	.error_detected = pch_gbe_io_error_detected,
+	.slot_reset = pch_gbe_io_slot_reset,
+	.resume = pch_gbe_io_resume
+};
+
+static struct pci_driver pch_gbe_pcidev = {
+	.name = KBUILD_MODNAME,
+	.id_table = pch_gbe_pcidev_id,
+	.probe = pch_gbe_probe,
+	.remove = pch_gbe_remove,
+#ifdef CONFIG_PM_OPS
+	.driver.pm = &pch_gbe_pm_ops,
+#endif
+	.shutdown = pch_gbe_shutdown,
+	.err_handler = &pch_gbe_err_handler
+};
+
+
+static int __init pch_gbe_init_module(void)
+{
+	int ret;
+
+	ret = pci_register_driver(&pch_gbe_pcidev);
+	if (copybreak != PCH_GBE_COPYBREAK_DEFAULT) {
+		if (copybreak == 0) {
+			pr_info("copybreak disabled\n");
+		} else {
+			pr_info("copybreak enabled for packets <= %u bytes\n",
+				copybreak);
+		}
+	}
+	return ret;
+}
+
+static void __exit pch_gbe_exit_module(void)
+{
+	pci_unregister_driver(&pch_gbe_pcidev);
+}
+
+module_init(pch_gbe_init_module);
+module_exit(pch_gbe_exit_module);
+
+MODULE_DESCRIPTION("OKI semiconductor PCH Gigabit ethernet Driver");
+MODULE_AUTHOR("OKI semiconductor, <masa-korg@dsn.okisemi.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_DEVICE_TABLE(pci, pch_gbe_pcidev_id);
+
+module_param(copybreak, uint, 0644);
+MODULE_PARM_DESC(copybreak,
+	"Maximum size of packet that is copied to a new buffer on receive");
+
+/* pch_gbe_main.c */
diff --git a/drivers/net/pch_gbe/pch_gbe_param.c b/drivers/net/pch_gbe/pch_gbe_param.c
new file mode 100644
index 0000000..2510146
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_param.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "pch_gbe.h"
+
+#define OPTION_UNSET   -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED  1
+
+/**
+ * TxDescriptors - Transmit Descriptor Count
+ * @Valid Range:   PCH_GBE_MIN_TXD - PCH_GBE_MAX_TXD
+ * @Default Value: PCH_GBE_DEFAULT_TXD
+ */
+static int TxDescriptors = OPTION_UNSET;
+module_param(TxDescriptors, int, 0);
+MODULE_PARM_DESC(TxDescriptors, "Number of transmit descriptors");
+
+/**
+ * RxDescriptors -Receive Descriptor Count
+ * @Valid Range:   PCH_GBE_MIN_RXD - PCH_GBE_MAX_RXD
+ * @Default Value: PCH_GBE_DEFAULT_RXD
+ */
+static int RxDescriptors = OPTION_UNSET;
+module_param(RxDescriptors, int, 0);
+MODULE_PARM_DESC(RxDescriptors, "Number of receive descriptors");
+
+/**
+ * Speed - User Specified Speed Override
+ * @Valid Range: 0, 10, 100, 1000
+ *   - 0:    auto-negotiate at all supported speeds
+ *   - 10:   only link at 10 Mbps
+ *   - 100:  only link at 100 Mbps
+ *   - 1000: only link at 1000 Mbps
+ * @Default Value: 0
+ */
+static int Speed = OPTION_UNSET;
+module_param(Speed, int, 0);
+MODULE_PARM_DESC(Speed, "Speed setting");
+
+/**
+ * Duplex - User Specified Duplex Override
+ * @Valid Range: 0-2
+ *   - 0:  auto-negotiate for duplex
+ *   - 1:  only link at half duplex
+ *   - 2:  only link at full duplex
+ * @Default Value: 0
+ */
+static int Duplex = OPTION_UNSET;
+module_param(Duplex, int, 0);
+MODULE_PARM_DESC(Duplex, "Duplex setting");
+
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
+
+/**
+ * AutoNeg - Auto-negotiation Advertisement Override
+ * @Valid Range: 0x01-0x0F, 0x20-0x2F
+ *
+ *       The AutoNeg value is a bit mask describing which speed and duplex
+ *       combinations should be advertised during auto-negotiation.
+ *       The supported speed and duplex modes are listed below
+ *
+ *       Bit           7     6     5      4      3     2     1      0
+ *       Speed (Mbps)  N/A   N/A   1000   N/A    100   100   10     10
+ *       Duplex                    Full          Full  Half  Full   Half
+ *
+ * @Default Value: 0x2F (copper)
+ */
+static int AutoNeg = OPTION_UNSET;
+module_param(AutoNeg, int, 0);
+MODULE_PARM_DESC(AutoNeg, "Advertised auto-negotiation setting");
+
+#define PHY_ADVERTISE_10_HALF      0x0001
+#define PHY_ADVERTISE_10_FULL      0x0002
+#define PHY_ADVERTISE_100_HALF     0x0004
+#define PHY_ADVERTISE_100_FULL     0x0008
+#define PHY_ADVERTISE_1000_HALF    0x0010 /* Not used, just FYI */
+#define PHY_ADVERTISE_1000_FULL    0x0020
+#define PCH_AUTONEG_ADVERTISE_DEFAULT   0x2F
+
+/**
+ * FlowControl - User Specified Flow Control Override
+ * @Valid Range: 0-3
+ *    - 0:  No Flow Control
+ *    - 1:  Rx only, respond to PAUSE frames but do not generate them
+ *    - 2:  Tx only, generate PAUSE frames but ignore them on receive
+ *    - 3:  Full Flow Control Support
+ * @Default Value: Read flow control settings from the EEPROM
+ */
+static int FlowControl = OPTION_UNSET;
+module_param(FlowControl, int, 0);
+MODULE_PARM_DESC(FlowControl, "Flow Control setting");
+
+/*
+ * XsumRX - Receive Checksum Offload Enable/Disable
+ * @Valid Range: 0, 1
+ *    - 0:  disables all checksum offload
+ *    - 1:  enables receive IP/TCP/UDP checksum offload
+ * @Default Value: PCH_GBE_DEFAULT_RX_CSUM
+ */
+static int XsumRX = OPTION_UNSET;
+module_param(XsumRX, int, 0);
+MODULE_PARM_DESC(XsumRX, "Disable or enable Receive Checksum offload");
+
+#define PCH_GBE_DEFAULT_RX_CSUM             true	/* trueorfalse */
+
+/*
+ * XsumTX - Transmit Checksum Offload Enable/Disable
+ * @Valid Range: 0, 1
+ *    - 0:  disables all checksum offload
+ *    - 1:  enables transmit IP/TCP/UDP checksum offload
+ * @Default Value: PCH_GBE_DEFAULT_TX_CSUM
+ */
+static int XsumTX = OPTION_UNSET;
+module_param(XsumTX, int, 0);
+MODULE_PARM_DESC(XsumTX, "Disable or enable Transmit Checksum offload");
+
+#define PCH_GBE_DEFAULT_TX_CSUM             true	/* trueorfalse */
+
+/**
+ * pch_gbe_option - Force the MAC's flow control settings
+ * @hw:	            Pointer to the HW structure
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+struct pch_gbe_option {
+	enum { enable_option, range_option, list_option } type;
+	char *name;
+	char *err;
+	int  def;
+	union {
+		struct { /* range_option info */
+			int min;
+			int max;
+		} r;
+		struct { /* list_option info */
+			int nr;
+			const struct pch_gbe_opt_list { int i; char *str; } *p;
+		} l;
+	} arg;
+};
+
+static const struct pch_gbe_opt_list speed_list[] = {
+	{ 0, "" },
+	{ SPEED_10, "" },
+	{ SPEED_100, "" },
+	{ SPEED_1000, "" }
+};
+
+static const struct pch_gbe_opt_list dplx_list[] = {
+	{ 0, "" },
+	{ HALF_DUPLEX, "" },
+	{ FULL_DUPLEX, "" }
+};
+
+static const struct pch_gbe_opt_list an_list[] =
+	#define AA "AutoNeg advertising "
+	{{ 0x01, AA "10/HD" },
+	 { 0x02, AA "10/FD" },
+	 { 0x03, AA "10/FD, 10/HD" },
+	 { 0x04, AA "100/HD" },
+	 { 0x05, AA "100/HD, 10/HD" },
+	 { 0x06, AA "100/HD, 10/FD" },
+	 { 0x07, AA "100/HD, 10/FD, 10/HD" },
+	 { 0x08, AA "100/FD" },
+	 { 0x09, AA "100/FD, 10/HD" },
+	 { 0x0a, AA "100/FD, 10/FD" },
+	 { 0x0b, AA "100/FD, 10/FD, 10/HD" },
+	 { 0x0c, AA "100/FD, 100/HD" },
+	 { 0x0d, AA "100/FD, 100/HD, 10/HD" },
+	 { 0x0e, AA "100/FD, 100/HD, 10/FD" },
+	 { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
+	 { 0x20, AA "1000/FD" },
+	 { 0x21, AA "1000/FD, 10/HD" },
+	 { 0x22, AA "1000/FD, 10/FD" },
+	 { 0x23, AA "1000/FD, 10/FD, 10/HD" },
+	 { 0x24, AA "1000/FD, 100/HD" },
+	 { 0x25, AA "1000/FD, 100/HD, 10/HD" },
+	 { 0x26, AA "1000/FD, 100/HD, 10/FD" },
+	 { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
+	 { 0x28, AA "1000/FD, 100/FD" },
+	 { 0x29, AA "1000/FD, 100/FD, 10/HD" },
+	 { 0x2a, AA "1000/FD, 100/FD, 10/FD" },
+	 { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
+	 { 0x2c, AA "1000/FD, 100/FD, 100/HD" },
+	 { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
+	 { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
+	 { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }
+};
+
+static const struct pch_gbe_opt_list fc_list[] = {
+	{ PCH_GBE_FC_NONE, "Flow Control Disabled" },
+	{ PCH_GBE_FC_RX_PAUSE, "Flow Control Receive Only" },
+	{ PCH_GBE_FC_TX_PAUSE, "Flow Control Transmit Only" },
+	{ PCH_GBE_FC_FULL, "Flow Control Enabled" }
+};
+
+/**
+ * pch_gbe_validate_option - Validate option
+ * @value:    value
+ * @opt:      option
+ * @adapter:  Board private structure
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+static int pch_gbe_validate_option(int *value,
+				    const struct pch_gbe_option *opt,
+				    struct pch_gbe_adapter *adapter)
+{
+	if (*value == OPTION_UNSET) {
+		*value = opt->def;
+		return 0;
+	}
+
+	switch (opt->type) {
+	case enable_option:
+		switch (*value) {
+		case OPTION_ENABLED:
+			pr_debug("%s Enabled\n", opt->name);
+			return 0;
+		case OPTION_DISABLED:
+			pr_debug("%s Disabled\n", opt->name);
+			return 0;
+		}
+		break;
+	case range_option:
+		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+			pr_debug("%s set to %i\n", opt->name, *value);
+			return 0;
+		}
+		break;
+	case list_option: {
+		int i;
+		const struct pch_gbe_opt_list *ent;
+
+		for (i = 0; i < opt->arg.l.nr; i++) {
+			ent = &opt->arg.l.p[i];
+			if (*value == ent->i) {
+				if (ent->str[0] != '\0')
+					pr_debug("%s\n", ent->str);
+				return 0;
+			}
+		}
+	}
+		break;
+	default:
+		BUG();
+	}
+
+	pr_debug("Invalid %s value specified (%i) %s\n",
+		 opt->name, *value, opt->err);
+	*value = opt->def;
+	return -1;
+}
+
+/**
+ * pch_gbe_check_copper_options - Range Checking for Link Options, Copper Version
+ * @adapter:  Board private structure
+ */
+static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+	int speed, dplx;
+
+	{ /* Speed */
+		static const struct pch_gbe_option opt = {
+			.type = list_option,
+			.name = "Speed",
+			.err  = "parameter ignored",
+			.def  = 0,
+			.arg  = { .l = { .nr = (int)ARRAY_SIZE(speed_list),
+					 .p = speed_list } }
+		};
+		speed = Speed;
+		pch_gbe_validate_option(&speed, &opt, adapter);
+	}
+	{ /* Duplex */
+		static const struct pch_gbe_option opt = {
+			.type = list_option,
+			.name = "Duplex",
+			.err  = "parameter ignored",
+			.def  = 0,
+			.arg  = { .l = { .nr = (int)ARRAY_SIZE(dplx_list),
+					 .p = dplx_list } }
+		};
+		dplx = Duplex;
+		pch_gbe_validate_option(&dplx, &opt, adapter);
+	}
+
+	{ /* Autoneg */
+		static const struct pch_gbe_option opt = {
+			.type = list_option,
+			.name = "AutoNeg",
+			.err  = "parameter ignored",
+			.def  = PCH_AUTONEG_ADVERTISE_DEFAULT,
+			.arg  = { .l = { .nr = (int)ARRAY_SIZE(an_list),
+					 .p = an_list} }
+		};
+		if (speed || dplx) {
+			pr_debug("AutoNeg specified along with Speed or Duplex, AutoNeg parameter ignored\n");
+			hw->phy.autoneg_advertised = opt.def;
+		} else {
+			hw->phy.autoneg_advertised = AutoNeg;
+			pch_gbe_validate_option(
+				(int *)(&hw->phy.autoneg_advertised),
+				&opt, adapter);
+		}
+	}
+
+	switch (speed + dplx) {
+	case 0:
+		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+		if ((speed || dplx))
+			pr_debug("Speed and duplex autonegotiation enabled\n");
+		hw->mac.link_speed = SPEED_10;
+		hw->mac.link_duplex = DUPLEX_HALF;
+		break;
+	case HALF_DUPLEX:
+		pr_debug("Half Duplex specified without Speed\n");
+		pr_debug("Using Autonegotiation at Half Duplex only\n");
+		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+		hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
+						PHY_ADVERTISE_100_HALF;
+		hw->mac.link_speed = SPEED_10;
+		hw->mac.link_duplex = DUPLEX_HALF;
+		break;
+	case FULL_DUPLEX:
+		pr_debug("Full Duplex specified without Speed\n");
+		pr_debug("Using Autonegotiation at Full Duplex only\n");
+		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+		hw->phy.autoneg_advertised = PHY_ADVERTISE_10_FULL |
+						PHY_ADVERTISE_100_FULL |
+						PHY_ADVERTISE_1000_FULL;
+		hw->mac.link_speed = SPEED_10;
+		hw->mac.link_duplex = DUPLEX_FULL;
+		break;
+	case SPEED_10:
+		pr_debug("10 Mbps Speed specified without Duplex\n");
+		pr_debug("Using Autonegotiation at 10 Mbps only\n");
+		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+		hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
+						PHY_ADVERTISE_10_FULL;
+		hw->mac.link_speed = SPEED_10;
+		hw->mac.link_duplex = DUPLEX_HALF;
+		break;
+	case SPEED_10 + HALF_DUPLEX:
+		pr_debug("Forcing to 10 Mbps Half Duplex\n");
+		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+		hw->phy.autoneg_advertised = 0;
+		hw->mac.link_speed = SPEED_10;
+		hw->mac.link_duplex = DUPLEX_HALF;
+		break;
+	case SPEED_10 + FULL_DUPLEX:
+		pr_debug("Forcing to 10 Mbps Full Duplex\n");
+		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+		hw->phy.autoneg_advertised = 0;
+		hw->mac.link_speed = SPEED_10;
+		hw->mac.link_duplex = DUPLEX_FULL;
+		break;
+	case SPEED_100:
+		pr_debug("100 Mbps Speed specified without Duplex\n");
+		pr_debug("Using Autonegotiation at 100 Mbps only\n");
+		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+		hw->phy.autoneg_advertised = PHY_ADVERTISE_100_HALF |
+						PHY_ADVERTISE_100_FULL;
+		hw->mac.link_speed = SPEED_100;
+		hw->mac.link_duplex = DUPLEX_HALF;
+		break;
+	case SPEED_100 + HALF_DUPLEX:
+		pr_debug("Forcing to 100 Mbps Half Duplex\n");
+		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+		hw->phy.autoneg_advertised = 0;
+		hw->mac.link_speed = SPEED_100;
+		hw->mac.link_duplex = DUPLEX_HALF;
+		break;
+	case SPEED_100 + FULL_DUPLEX:
+		pr_debug("Forcing to 100 Mbps Full Duplex\n");
+		hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+		hw->phy.autoneg_advertised = 0;
+		hw->mac.link_speed = SPEED_100;
+		hw->mac.link_duplex = DUPLEX_FULL;
+		break;
+	case SPEED_1000:
+		pr_debug("1000 Mbps Speed specified without Duplex\n");
+		goto full_duplex_only;
+	case SPEED_1000 + HALF_DUPLEX:
+		pr_debug("Half Duplex is not supported at 1000 Mbps\n");
+		/* fall through */
+	case SPEED_1000 + FULL_DUPLEX:
+full_duplex_only:
+		pr_debug("Using Autonegotiation at 1000 Mbps Full Duplex only\n");
+		hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+		hw->phy.autoneg_advertised = PHY_ADVERTISE_1000_FULL;
+		hw->mac.link_speed = SPEED_1000;
+		hw->mac.link_duplex = DUPLEX_FULL;
+		break;
+	default:
+		BUG();
+	}
+}
+
+/**
+ * pch_gbe_check_options - Range Checking for Command Line Parameters
+ * @adapter:  Board private structure
+ */
+void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
+{
+	struct pch_gbe_hw *hw = &adapter->hw;
+
+	{ /* Transmit Descriptor Count */
+		static const struct pch_gbe_option opt = {
+			.type = range_option,
+			.name = "Transmit Descriptors",
+			.err  = "using default of "
+				__MODULE_STRING(PCH_GBE_DEFAULT_TXD),
+			.def  = PCH_GBE_DEFAULT_TXD,
+			.arg  = { .r = { .min = PCH_GBE_MIN_TXD } },
+			.arg  = { .r = { .max = PCH_GBE_MAX_TXD } }
+		};
+		struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
+		tx_ring->count = TxDescriptors;
+		pch_gbe_validate_option(&tx_ring->count, &opt, adapter);
+		tx_ring->count = roundup(tx_ring->count,
+					PCH_GBE_TX_DESC_MULTIPLE);
+	}
+	{ /* Receive Descriptor Count */
+		static const struct pch_gbe_option opt = {
+			.type = range_option,
+			.name = "Receive Descriptors",
+			.err  = "using default of "
+				__MODULE_STRING(PCH_GBE_DEFAULT_RXD),
+			.def  = PCH_GBE_DEFAULT_RXD,
+			.arg  = { .r = { .min = PCH_GBE_MIN_RXD } },
+			.arg  = { .r = { .max = PCH_GBE_MAX_RXD } }
+		};
+		struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
+		rx_ring->count = RxDescriptors;
+		pch_gbe_validate_option(&rx_ring->count, &opt, adapter);
+		rx_ring->count = roundup(rx_ring->count,
+				PCH_GBE_RX_DESC_MULTIPLE);
+	}
+	{ /* Checksum Offload Enable/Disable */
+		static const struct pch_gbe_option opt = {
+			.type = enable_option,
+			.name = "Checksum Offload",
+			.err  = "defaulting to Enabled",
+			.def  = PCH_GBE_DEFAULT_RX_CSUM
+		};
+		adapter->rx_csum = XsumRX;
+		pch_gbe_validate_option((int *)(&adapter->rx_csum),
+					&opt, adapter);
+	}
+	{ /* Checksum Offload Enable/Disable */
+		static const struct pch_gbe_option opt = {
+			.type = enable_option,
+			.name = "Checksum Offload",
+			.err  = "defaulting to Enabled",
+			.def  = PCH_GBE_DEFAULT_TX_CSUM
+		};
+		adapter->tx_csum = XsumTX;
+		pch_gbe_validate_option((int *)(&adapter->tx_csum),
+						&opt, adapter);
+	}
+	{ /* Flow Control */
+		static const struct pch_gbe_option opt = {
+			.type = list_option,
+			.name = "Flow Control",
+			.err  = "reading default settings from EEPROM",
+			.def  = PCH_GBE_FC_DEFAULT,
+			.arg  = { .l = { .nr = (int)ARRAY_SIZE(fc_list),
+					 .p = fc_list } }
+		};
+		hw->mac.fc = FlowControl;
+		pch_gbe_validate_option((int *)(&hw->mac.fc),
+						&opt, adapter);
+	}
+
+	pch_gbe_check_copper_options(adapter);
+}
diff --git a/drivers/net/pch_gbe/pch_gbe_phy.c b/drivers/net/pch_gbe/pch_gbe_phy.c
new file mode 100644
index 0000000..923a687
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_phy.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "pch_gbe.h"
+#include "pch_gbe_phy.h"
+
+#define PHY_MAX_REG_ADDRESS   0x1F	/* 5 bit address bus (0-0x1F) */
+
+/* PHY 1000 MII Register/Bit Definitions */
+/* PHY Registers defined by IEEE */
+#define PHY_CONTROL           0x00  /* Control Register */
+#define PHY_STATUS            0x01  /* Status Regiser */
+#define PHY_ID1               0x02  /* Phy Id Register (word 1) */
+#define PHY_ID2               0x03  /* Phy Id Register (word 2) */
+#define PHY_AUTONEG_ADV       0x04  /* Autoneg Advertisement */
+#define PHY_LP_ABILITY        0x05  /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP       0x06  /* Autoneg Expansion Register */
+#define PHY_NEXT_PAGE_TX      0x07  /* Next Page TX */
+#define PHY_LP_NEXT_PAGE      0x08  /* Link Partner Next Page */
+#define PHY_1000T_CTRL        0x09  /* 1000Base-T Control Register */
+#define PHY_1000T_STATUS      0x0A  /* 1000Base-T Status Register */
+#define PHY_EXT_STATUS        0x0F  /* Extended Status Register */
+#define PHY_PHYSP_CONTROL     0x10  /* PHY Specific Control Register */
+#define PHY_EXT_PHYSP_CONTROL 0x14  /* Extended PHY Specific Control Register */
+#define PHY_LED_CONTROL       0x18  /* LED Control Register */
+#define PHY_EXT_PHYSP_STATUS  0x1B  /* Extended PHY Specific Status Register */
+
+/* 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_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 */
+
+/* Phy Id Register (word 2) */
+#define PHY_REVISION_MASK        0x000F
+
+/* PHY Specific Control Register */
+#define PHYSP_CTRL_ASSERT_CRS_TX  0x0800
+
+
+/* Default value of PHY register */
+#define PHY_CONTROL_DEFAULT         0x1140 /* Control Register */
+#define PHY_AUTONEG_ADV_DEFAULT     0x01e0 /* Autoneg Advertisement */
+#define PHY_NEXT_PAGE_TX_DEFAULT    0x2001 /* Next Page TX */
+#define PHY_1000T_CTRL_DEFAULT      0x0300 /* 1000Base-T Control Register */
+#define PHY_PHYSP_CONTROL_DEFAULT   0x01EE /* PHY Specific Control Register */
+
+/**
+ * pch_gbe_phy_get_id - Retrieve the PHY ID and revision
+ * @hw:	       Pointer to the HW structure
+ * Returns
+ *	0:			Successful.
+ *	Negative value:		Failed.
+ */
+s32 pch_gbe_phy_get_id(struct pch_gbe_hw *hw)
+{
+	struct pch_gbe_phy_info *phy = &hw->phy;
+	s32 ret;
+	u16 phy_id1;
+	u16 phy_id2;
+
+	ret = pch_gbe_phy_read_reg_miic(hw, PHY_ID1, &phy_id1);
+	if (ret)
+		return ret;
+	ret = pch_gbe_phy_read_reg_miic(hw, PHY_ID2, &phy_id2);
+	if (ret)
+		return ret;
+	/*
+	 * PHY_ID1: [bit15-0:ID(21-6)]
+	 * PHY_ID2: [bit15-10:ID(5-0)][bit9-4:Model][bit3-0:revision]
+	 */
+	phy->id = (u32)phy_id1;
+	phy->id = ((phy->id << 6) | ((phy_id2 & 0xFC00) >> 10));
+	phy->revision = (u32) (phy_id2 & 0x000F);
+	pr_debug("phy->id : 0x%08x  phy->revision : 0x%08x\n",
+		 phy->id, phy->revision);
+	return 0;
+}
+
+/**
+ * pch_gbe_phy_read_reg_miic - Read MII control register
+ * @hw:	     Pointer to the HW structure
+ * @offset:  Register offset to be read
+ * @data:    Pointer to the read data
+ * Returns
+ *	0:		Successful.
+ *	-EINVAL:	Invalid argument.
+ */
+s32 pch_gbe_phy_read_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 *data)
+{
+	struct pch_gbe_phy_info *phy = &hw->phy;
+
+	if (offset > PHY_MAX_REG_ADDRESS) {
+		pr_err("PHY Address %d is out of range\n", offset);
+		return -EINVAL;
+	}
+	*data = pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_READ,
+				      offset, (u16)0);
+	return 0;
+}
+
+/**
+ * pch_gbe_phy_write_reg_miic - Write MII control register
+ * @hw:	     Pointer to the HW structure
+ * @offset:  Register offset to be read
+ * @data:    data to write to register at offset
+ * Returns
+ *	0:		Successful.
+ *	-EINVAL:	Invalid argument.
+ */
+s32 pch_gbe_phy_write_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 data)
+{
+	struct pch_gbe_phy_info *phy = &hw->phy;
+
+	if (offset > PHY_MAX_REG_ADDRESS) {
+		pr_err("PHY Address %d is out of range\n", offset);
+		return -EINVAL;
+	}
+	pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_WRITE,
+				 offset, data);
+	return 0;
+}
+
+/**
+ * pch_gbe_phy_sw_reset - PHY software reset
+ * @hw:	            Pointer to the HW structure
+ */
+void pch_gbe_phy_sw_reset(struct pch_gbe_hw *hw)
+{
+	u16 phy_ctrl;
+
+	pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &phy_ctrl);
+	phy_ctrl |= MII_CR_RESET;
+	pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, phy_ctrl);
+	udelay(1);
+}
+
+/**
+ * pch_gbe_phy_hw_reset - PHY hardware reset
+ * @hw:	   Pointer to the HW structure
+ */
+void pch_gbe_phy_hw_reset(struct pch_gbe_hw *hw)
+{
+	pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, PHY_CONTROL_DEFAULT);
+	pch_gbe_phy_write_reg_miic(hw, PHY_AUTONEG_ADV,
+					PHY_AUTONEG_ADV_DEFAULT);
+	pch_gbe_phy_write_reg_miic(hw, PHY_NEXT_PAGE_TX,
+					PHY_NEXT_PAGE_TX_DEFAULT);
+	pch_gbe_phy_write_reg_miic(hw, PHY_1000T_CTRL, PHY_1000T_CTRL_DEFAULT);
+	pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL,
+					PHY_PHYSP_CONTROL_DEFAULT);
+}
+
+/**
+ * pch_gbe_phy_power_up - restore link in case the phy was powered down
+ * @hw:	   Pointer to the HW structure
+ */
+void pch_gbe_phy_power_up(struct pch_gbe_hw *hw)
+{
+	u16 mii_reg;
+
+	mii_reg = 0;
+	/* Just clear the power down bit to wake the phy back up */
+	/* according to the manual, the phy will retain its
+	 * settings across a power-down/up cycle */
+	pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &mii_reg);
+	mii_reg &= ~MII_CR_POWER_DOWN;
+	pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, mii_reg);
+}
+
+/**
+ * pch_gbe_phy_power_down - Power down PHY
+ * @hw:	   Pointer to the HW structure
+ */
+void pch_gbe_phy_power_down(struct pch_gbe_hw *hw)
+{
+	u16 mii_reg;
+
+	mii_reg = 0;
+	/* Power down the PHY so no link is implied when interface is down *
+	 * The PHY cannot be powered down if any of the following is TRUE *
+	 * (a) WoL is enabled
+	 * (b) AMT is active
+	 */
+	pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &mii_reg);
+	mii_reg |= MII_CR_POWER_DOWN;
+	pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, mii_reg);
+	mdelay(1);
+}
+
+/**
+ * pch_gbe_phy_set_rgmii - RGMII interface setting
+ * @hw:	            Pointer to the HW structure
+ */
+inline void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw)
+{
+	pch_gbe_phy_sw_reset(hw);
+}
+
+/**
+ * pch_gbe_phy_init_setting - PHY initial setting
+ * @hw:	            Pointer to the HW structure
+ */
+void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw)
+{
+	struct pch_gbe_adapter *adapter;
+	struct ethtool_cmd     cmd;
+	int ret;
+	u16 mii_reg;
+
+	adapter = container_of(hw, struct pch_gbe_adapter, hw);
+	ret = mii_ethtool_gset(&adapter->mii, &cmd);
+	if (ret)
+		pr_err("Error: mii_ethtool_gset\n");
+
+	cmd.speed = hw->mac.link_speed;
+	cmd.duplex = hw->mac.link_duplex;
+	cmd.advertising = hw->phy.autoneg_advertised;
+	cmd.autoneg = hw->mac.autoneg;
+	pch_gbe_phy_write_reg_miic(hw, MII_BMCR, BMCR_RESET);
+	ret = mii_ethtool_sset(&adapter->mii, &cmd);
+	if (ret)
+		pr_err("Error: mii_ethtool_sset\n");
+
+	pch_gbe_phy_sw_reset(hw);
+
+	pch_gbe_phy_read_reg_miic(hw, PHY_PHYSP_CONTROL, &mii_reg);
+	mii_reg |= PHYSP_CTRL_ASSERT_CRS_TX;
+	pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL, mii_reg);
+
+}
diff --git a/drivers/net/pch_gbe/pch_gbe_phy.h b/drivers/net/pch_gbe/pch_gbe_phy.h
new file mode 100644
index 0000000..03264dc7
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_phy.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux 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; 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 _PCH_GBE_PHY_H_
+#define _PCH_GBE_PHY_H_
+
+#define PCH_GBE_PHY_REGS_LEN		32
+#define	PCH_GBE_PHY_RESET_DELAY_US	10
+#define PCH_GBE_MAC_IFOP_RGMII
+
+s32 pch_gbe_phy_get_id(struct pch_gbe_hw *hw);
+s32 pch_gbe_phy_read_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 *data);
+s32 pch_gbe_phy_write_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 data);
+void pch_gbe_phy_sw_reset(struct pch_gbe_hw *hw);
+void pch_gbe_phy_hw_reset(struct pch_gbe_hw *hw);
+void pch_gbe_phy_power_up(struct pch_gbe_hw *hw);
+void pch_gbe_phy_power_down(struct pch_gbe_hw *hw);
+void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw);
+void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw);
+
+#endif /* _PCH_GBE_PHY_H_ */
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index 56f3fc4..8dd0343 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -1125,7 +1125,7 @@
 	init_timer(&tp->timer);
 	tp->timer.expires = jiffies + 3 * HZ;
 	tp->timer.data = (unsigned long) dev;
-	tp->timer.function = &netdrv_timer;
+	tp->timer.function = netdrv_timer;
 	add_timer(&tp->timer);
 
 	DPRINTK("EXIT, returning 0\n");
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index c683f77..2807a0f 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -69,6 +69,8 @@
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -83,11 +85,9 @@
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/ioport.h>
-#include <linux/ethtool.h>
 #include <linux/bitops.h>
 #include <linux/mii.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -238,7 +238,6 @@
 static int el3_close(struct net_device *dev);
 static void el3_tx_timeout(struct net_device *dev);
 static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static const struct ethtool_ops netdev_ethtool_ops;
 static void set_rx_mode(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 
@@ -280,25 +279,14 @@
 	spin_lock_init(&lp->window_lock);
 	link->resource[0]->end = 32;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-	link->conf.ConfigIndex = 1;
+	link->config_flags |= CONF_ENABLE_IRQ;
+	link->config_index = 1;
 
 	dev->netdev_ops = &el3_netdev_ops;
-	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 	dev->watchdog_timeo = TX_TIMEOUT;
 
 	return tc574_config(link);
-} /* tc574_attach */
-
-/*
-
-	This deletes a driver "instance".  The device is de-registered
-	with Card Services.  If it has been released, all local data
-	structures are freed.  Otherwise, the structures will be freed
-	when the device is released.
-
-*/
+}
 
 static void tc574_detach(struct pcmcia_device *link)
 {
@@ -313,12 +301,6 @@
 	free_netdev(dev);
 } /* tc574_detach */
 
-/*
-	tc574_config() is scheduled to run after a CARD_INSERTION event
-	is received, to configure the PCMCIA socket, and to make the
-	ethernet device available to the system.
-*/
-
 static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
 
 static int tc574_config(struct pcmcia_device *link)
@@ -352,7 +334,7 @@
 	if (ret)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -376,8 +358,8 @@
 		for (i = 0; i < 3; i++)
 			phys_addr[i] = htons(read_eeprom(ioaddr, i + 10));
 		if (phys_addr[0] == htons(0x6060)) {
-			printk(KERN_NOTICE "3c574_cs: IO port conflict at 0x%03lx"
-				   "-0x%03lx\n", dev->base_addr, dev->base_addr+15);
+			pr_notice("IO port conflict at 0x%03lx-0x%03lx\n",
+				  dev->base_addr, dev->base_addr+15);
 			goto failed;
 		}
 	}
@@ -391,7 +373,7 @@
 		outw(2<<11, ioaddr + RunnerRdCtrl);
 		mcr = inb(ioaddr + 2);
 		outw(0<<11, ioaddr + RunnerRdCtrl);
-		printk(KERN_INFO "  ASIC rev %d,", mcr>>3);
+		pr_info("  ASIC rev %d,", mcr>>3);
 		EL3WINDOW(3);
 		config = inl(ioaddr + Wn3_Config);
 		lp->default_media = (config & Xcvr) >> Xcvr_shift;
@@ -428,7 +410,7 @@
 			}
 		}
 		if (phy > 32) {
-			printk(KERN_NOTICE "  No MII transceivers found!\n");
+			pr_notice("  No MII transceivers found!\n");
 			goto failed;
 		}
 		i = mdio_read(ioaddr, lp->phys, 16) | 0x40;
@@ -444,18 +426,16 @@
 	SET_NETDEV_DEV(dev, &link->dev);
 
 	if (register_netdev(dev) != 0) {
-		printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
+		pr_notice("register_netdev() failed\n");
 		goto failed;
 	}
 
-	printk(KERN_INFO "%s: %s at io %#3lx, irq %d, "
-	       "hw_addr %pM.\n",
-	       dev->name, cardname, dev->base_addr, dev->irq,
-	       dev->dev_addr);
-	printk(" %dK FIFO split %s Rx:Tx, %sMII interface.\n",
-		   8 << config & Ram_size,
-		   ram_split[(config & Ram_split) >> Ram_split_shift],
-		   config & Autoselect ? "autoselect " : "");
+	netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n",
+		    cardname, dev->base_addr, dev->irq, dev->dev_addr);
+	netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n",
+		    8 << config & Ram_size,
+		    ram_split[(config & Ram_split) >> Ram_split_shift],
+		    config & Autoselect ? "autoselect " : "");
 
 	return 0;
 
@@ -465,12 +445,6 @@
 
 } /* tc574_config */
 
-/*
-	After a card is removed, tc574_release() will unregister the net
-	device, and release the PCMCIA configuration.  If the device is
-	still open, this will be postponed until it is closed.
-*/
-
 static void tc574_release(struct pcmcia_device *link)
 {
 	pcmcia_disable_device(link);
@@ -502,14 +476,14 @@
 {
 	unsigned int ioaddr = dev->base_addr;
 	EL3WINDOW(1);
-	printk(KERN_INFO "  irq status %04x, rx status %04x, tx status "
-		   "%02x, tx free %04x\n", inw(ioaddr+EL3_STATUS),
-		   inw(ioaddr+RxStatus), inb(ioaddr+TxStatus),
-		   inw(ioaddr+TxFree));
+	netdev_info(dev, "  irq status %04x, rx status %04x, tx status %02x, tx free %04x\n",
+		    inw(ioaddr+EL3_STATUS),
+		    inw(ioaddr+RxStatus), inb(ioaddr+TxStatus),
+		    inw(ioaddr+TxFree));
 	EL3WINDOW(4);
-	printk(KERN_INFO "  diagnostics: fifo %04x net %04x ethernet %04x"
-		   " media %04x\n", inw(ioaddr+0x04), inw(ioaddr+0x06),
-		   inw(ioaddr+0x08), inw(ioaddr+0x0a));
+	netdev_info(dev, "  diagnostics: fifo %04x net %04x ethernet %04x media %04x\n",
+		    inw(ioaddr+0x04), inw(ioaddr+0x06),
+		    inw(ioaddr+0x08), inw(ioaddr+0x0a));
 	EL3WINDOW(1);
 }
 
@@ -523,7 +497,7 @@
 	while (--i > 0)
 		if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break;
 	if (i == 0)
-		printk(KERN_NOTICE "%s: command 0x%04x did not complete!\n", dev->name, cmd);
+		netdev_notice(dev, "command 0x%04x did not complete!\n", cmd);
 }
 
 /* Read a word from the EEPROM using the regular EEPROM access register.
@@ -710,7 +684,7 @@
 	netif_start_queue(dev);
 	
 	tc574_reset(dev);
-	lp->media.function = &media_check;
+	lp->media.function = media_check;
 	lp->media.data = (unsigned long) dev;
 	lp->media.expires = jiffies + HZ;
 	add_timer(&lp->media);
@@ -725,7 +699,7 @@
 {
 	unsigned int ioaddr = dev->base_addr;
 	
-	printk(KERN_NOTICE "%s: Transmit timed out!\n", dev->name);
+	netdev_notice(dev, "Transmit timed out!\n");
 	dump_status(dev);
 	dev->stats.tx_errors++;
 	dev->trans_start = jiffies; /* prevent tx timeout */
@@ -848,8 +822,8 @@
 				EL3WINDOW(4);
 				fifo_diag = inw(ioaddr + Wn4_FIFODiag);
 				EL3WINDOW(1);
-				printk(KERN_NOTICE "%s: adapter failure, FIFO diagnostic"
-					   " register %04x.\n", dev->name, fifo_diag);
+				netdev_notice(dev, "adapter failure, FIFO diagnostic register %04x\n",
+					      fifo_diag);
 				if (fifo_diag & 0x0400) {
 					/* Tx overrun */
 					tc574_wait_for_completion(dev, TxReset);
@@ -903,7 +877,7 @@
 	   this, we can limp along even if the interrupt is blocked */
 	if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) {
 		if (!lp->fast_poll)
-			printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
+			netdev_info(dev, "interrupt(s) dropped!\n");
 
 		local_irq_save(flags);
 		el3_interrupt(dev->irq, dev);
@@ -926,23 +900,21 @@
 	
 	if (media != lp->media_status) {
 		if ((media ^ lp->media_status) & 0x0004)
-			printk(KERN_INFO "%s: %s link beat\n", dev->name,
-				   (lp->media_status & 0x0004) ? "lost" : "found");
+			netdev_info(dev, "%s link beat\n",
+				    (lp->media_status & 0x0004) ? "lost" : "found");
 		if ((media ^ lp->media_status) & 0x0020) {
 			lp->partner = 0;
 			if (lp->media_status & 0x0020) {
-				printk(KERN_INFO "%s: autonegotiation restarted\n",
-					   dev->name);
+				netdev_info(dev, "autonegotiation restarted\n");
 			} else if (partner) {
 				partner &= lp->advertising;
 				lp->partner = partner;
-				printk(KERN_INFO "%s: autonegotiation complete: "
-					   "%sbaseT-%cD selected\n", dev->name,
-					   ((partner & 0x0180) ? "100" : "10"),
-					   ((partner & 0x0140) ? 'F' : 'H'));
+				netdev_info(dev, "autonegotiation complete: "
+					    "%dbaseT-%cD selected\n",
+					    (partner & 0x0180) ? 100 : 10,
+					    (partner & 0x0140) ? 'F' : 'H');
 			} else {
-				printk(KERN_INFO "%s: link partner did not autonegotiate\n",
-					   dev->name);
+				netdev_info(dev, "link partner did not autonegotiate\n");
 			}
 
 			EL3WINDOW(3);
@@ -952,10 +924,9 @@
 
 		}
 		if (media & 0x0010)
-			printk(KERN_INFO "%s: remote fault detected\n",
-				   dev->name);
+			netdev_info(dev, "remote fault detected\n");
 		if (media & 0x0002)
-			printk(KERN_INFO "%s: jabber detected\n", dev->name);
+			netdev_info(dev, "jabber detected\n");
 		lp->media_status = media;
 	}
 	spin_unlock_irqrestore(&lp->window_lock, flags);
@@ -1065,16 +1036,6 @@
 	return worklimit;
 }
 
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, "3c574_cs");
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-};
-
 /* Provide ioctl() calls to examine the MII xcvr state. */
 static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
@@ -1198,9 +1159,7 @@
 
 static struct pcmcia_driver tc574_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "3c574_cs",
-	},
+	.name		= "3c574_cs",
 	.probe		= tc574_probe,
 	.remove		= tc574_detach,
 	.id_table       = tc574_ids,
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 61f9cf2..79b9ca0 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -19,6 +19,8 @@
 
 ======================================================================*/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DRV_NAME	"3c589_cs"
 #define DRV_VERSION	"1.162-ac"
 
@@ -41,7 +43,6 @@
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -176,14 +177,6 @@
 
 static void tc589_detach(struct pcmcia_device *p_dev);
 
-/*======================================================================
-
-    tc589_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static const struct net_device_ops el3_netdev_ops = {
 	.ndo_open		= el3_open,
 	.ndo_stop		= el3_close,
@@ -216,9 +209,8 @@
     link->resource[0]->end = 16;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
+    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_index = 1;
 
     dev->netdev_ops = &el3_netdev_ops;
     dev->watchdog_timeo = TX_TIMEOUT;
@@ -226,16 +218,7 @@
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
     return tc589_config(link);
-} /* tc589_attach */
-
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
+}
 
 static void tc589_detach(struct pcmcia_device *link)
 {
@@ -250,21 +233,13 @@
     free_netdev(dev);
 } /* tc589_detach */
 
-/*======================================================================
-
-    tc589_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-
-======================================================================*/
-
 static int tc589_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     __be16 *phys_addr;
     int ret, i, j, multi = 0, fifo;
     unsigned int ioaddr;
-    char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+    static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
     u8 *buf;
     size_t len;
 
@@ -273,8 +248,7 @@
     phys_addr = (__be16 *)dev->dev_addr;
     /* Is this a 3c562? */
     if (link->manf_id != MANFID_3COM)
-	    printk(KERN_INFO "3c589_cs: hmmm, is this really a "
-		   "3Com card??\n");
+	    dev_info(&link->dev, "hmmm, is this really a 3Com card??\n");
     multi = (link->card_id == PRODID_3COM_3C562);
 
     link->io_lines = 16;
@@ -294,7 +268,7 @@
     if (ret)
 	    goto failed;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
@@ -315,8 +289,8 @@
 	for (i = 0; i < 3; i++)
 	    phys_addr[i] = htons(read_eeprom(ioaddr, i));
 	if (phys_addr[0] == htons(0x6060)) {
-	    printk(KERN_ERR "3c589_cs: IO port conflict at 0x%03lx"
-		   "-0x%03lx\n", dev->base_addr, dev->base_addr+15);
+	    dev_err(&link->dev, "IO port conflict at 0x%03lx-0x%03lx\n",
+		    dev->base_addr, dev->base_addr+15);
 	    goto failed;
 	}
     }
@@ -330,12 +304,12 @@
     if ((if_port >= 0) && (if_port <= 3))
 	dev->if_port = if_port;
     else
-	printk(KERN_ERR "3c589_cs: invalid if_port requested\n");
+	dev_err(&link->dev, "invalid if_port requested\n");
 
     SET_NETDEV_DEV(dev, &link->dev);
 
     if (register_netdev(dev) != 0) {
-	printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
+	    dev_err(&link->dev, "register_netdev() failed\n");
 	goto failed;
     }
 
@@ -352,14 +326,6 @@
     return -ENODEV;
 } /* tc589_config */
 
-/*======================================================================
-
-    After a card is removed, tc589_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void tc589_release(struct pcmcia_device *link)
 {
 	pcmcia_disable_device(link);
@@ -537,7 +503,7 @@
 
     tc589_reset(dev);
     init_timer(&lp->media);
-    lp->media.function = &media_check;
+    lp->media.function = media_check;
     lp->media.data = (unsigned long) dev;
     lp->media.expires = jiffies + HZ;
     add_timer(&lp->media);
@@ -955,9 +921,7 @@
 
 static struct pcmcia_driver tc589_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "3c589_cs",
-	},
+	.name		= "3c589_cs",
 	.probe		= tc589_probe,
 	.remove		= tc589_detach,
 	.id_table	= tc589_ids,
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 5f05ffb..d2e166e 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -24,6 +24,8 @@
 
 ======================================================================*/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -32,14 +34,12 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
-#include <linux/ethtool.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/crc32.h>
 #include <linux/mii.h>
 #include "../8390.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -86,7 +86,6 @@
 static struct net_device_stats *get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static void axnet_tx_timeout(struct net_device *dev);
-static const struct ethtool_ops netdev_ethtool_ops;
 static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
 static void ei_watchdog(u_long arg);
 static void axnet_reset_8390(struct net_device *dev);
@@ -140,14 +139,6 @@
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
-/*======================================================================
-
-    axnet_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int axnet_probe(struct pcmcia_device *link)
 {
     axnet_dev_t *info;
@@ -166,26 +157,15 @@
     info = PRIV(dev);
     info->p_dev = link;
     link->priv = dev;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ;
 
     dev->netdev_ops = &axnet_netdev_ops;
 
-    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
     dev->watchdog_timeo = TX_TIMEOUT;
 
     return axnet_config(link);
 } /* axnet_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void axnet_detach(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
@@ -231,7 +211,7 @@
     };
 
     /* Not much of a test, but the alternatives are messy */
-    if (link->conf.ConfigBase != 0x03c0)
+    if (link->config_base != 0x03c0)
 	return 0;
 
     axnet_reset_8390(dev);
@@ -248,14 +228,6 @@
     return 1;
 } /* get_prom */
 
-/*======================================================================
-
-    axnet_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-
-======================================================================*/
-
 static int try_io_port(struct pcmcia_device *link)
 {
     int j, ret;
@@ -286,35 +258,16 @@
     }
 }
 
-static int axnet_configcheck(struct pcmcia_device *p_dev,
-			     cistpl_cftable_entry_t *cfg,
-			     cistpl_cftable_entry_t *dflt,
-			     unsigned int vcc,
-			     void *priv_data)
+static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-	int i;
-	cistpl_io_t *io = &cfg->io;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	if (cfg->index == 0 || cfg->io.nwin == 0)
+	p_dev->config_index = 0x05;
+	if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
 		return -ENODEV;
 
-	p_dev->conf.ConfigIndex = 0x05;
-	/* For multifunction cards, by convention, we configure the
-	   network function with window 0, and serial with window 1 */
-	if (io->nwin > 1) {
-		i = (io->win[1].len > io->win[0].len);
-		p_dev->resource[1]->start = io->win[1-i].base;
-		p_dev->resource[1]->end = io->win[1-i].len;
-	} else {
-		i = p_dev->resource[1]->end = 0;
-	}
-	p_dev->resource[0]->start = io->win[i].base;
-	p_dev->resource[0]->end = io->win[i].len;
-	p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-	if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
-		return try_io_port(p_dev);
-
-	return -ENODEV;
+	return try_io_port(p_dev);
 }
 
 static int axnet_config(struct pcmcia_device *link)
@@ -326,20 +279,19 @@
     dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);
 
     /* don't trust the CIS on this; Linksys got it wrong */
-    link->conf.Present = 0x63;
+    link->config_regs = 0x63;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
     ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
     if (ret != 0)
 	goto failed;
 
     if (!link->irq)
 	    goto failed;
+
+    if (resource_size(link->resource[1]) == 8)
+	link->config_flags |= CONF_ENABLE_SPKR;
     
-    if (resource_size(link->resource[1]) == 8) {
-	link->conf.Attributes |= CONF_ENABLE_SPKR;
-	link->conf.Status = CCSR_AUDIO_ENA;
-    }
-    
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
@@ -347,8 +299,8 @@
     dev->base_addr = link->resource[0]->start;
 
     if (!get_prom(link)) {
-	printk(KERN_NOTICE "axnet_cs: this is not an AX88190 card!\n");
-	printk(KERN_NOTICE "axnet_cs: use pcnet_cs instead.\n");
+	pr_notice("this is not an AX88190 card!\n");
+	pr_notice("use pcnet_cs instead.\n");
 	goto failed;
     }
 
@@ -357,10 +309,10 @@
     ei_status.tx_start_page = AXNET_START_PG;
     ei_status.rx_start_page = AXNET_START_PG + TX_PAGES;
     ei_status.stop_page = AXNET_STOP_PG;
-    ei_status.reset_8390 = &axnet_reset_8390;
-    ei_status.get_8390_hdr = &get_8390_hdr;
-    ei_status.block_input = &block_input;
-    ei_status.block_output = &block_output;
+    ei_status.reset_8390 = axnet_reset_8390;
+    ei_status.get_8390_hdr = get_8390_hdr;
+    ei_status.block_input = block_input;
+    ei_status.block_output = block_output;
 
     if (inb(dev->base_addr + AXNET_TEST) != 0)
 	info->flags |= IS_AX88790;
@@ -393,19 +345,18 @@
     SET_NETDEV_DEV(dev, &link->dev);
 
     if (register_netdev(dev) != 0) {
-	printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
+	pr_notice("register_netdev() failed\n");
 	goto failed;
     }
 
-    printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, "
-	   "hw_addr %pM\n",
-	   dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
-	   dev->base_addr, dev->irq,
-	   dev->dev_addr);
+    netdev_info(dev, "Asix AX88%d90: io %#3lx, irq %d, hw_addr %pM\n",
+		((info->flags & IS_AX88790) ? 7 : 1),
+		dev->base_addr, dev->irq, dev->dev_addr);
     if (info->phy_id != -1) {
-	dev_dbg(&link->dev, "  MII transceiver at index %d, status %x.\n", info->phy_id, j);
+	netdev_dbg(dev, "  MII transceiver at index %d, status %x\n",
+		   info->phy_id, j);
     } else {
-	printk(KERN_NOTICE "  No MII transceivers found!\n");
+	netdev_notice(dev, "  No MII transceivers found!\n");
     }
     return 0;
 
@@ -414,14 +365,6 @@
     return -ENODEV;
 } /* axnet_config */
 
-/*======================================================================
-
-    After a card is removed, axnet_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void axnet_release(struct pcmcia_device *link)
 {
 	pcmcia_disable_device(link);
@@ -532,7 +475,7 @@
 
     info->link_status = 0x00;
     init_timer(&info->watchdog);
-    info->watchdog.function = &ei_watchdog;
+    info->watchdog.function = ei_watchdog;
     info->watchdog.data = (u_long)dev;
     info->watchdog.expires = jiffies + HZ;
     add_timer(&info->watchdog);
@@ -585,8 +528,7 @@
     outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
     
     if (i == 100)
-	printk(KERN_ERR "%s: axnet_reset_8390() did not complete.\n",
-	       dev->name);
+	netdev_err(dev, "axnet_reset_8390() did not complete\n");
     
 } /* axnet_reset_8390 */
 
@@ -613,7 +555,7 @@
        this, we can limp along even if the interrupt is blocked */
     if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
 	if (!info->fast_poll)
-	    printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
+	    netdev_info(dev, "interrupt(s) dropped!\n");
 	ei_irq_wrapper(dev->irq, dev);
 	info->fast_poll = HZ;
     }
@@ -628,7 +570,7 @@
 	goto reschedule;
     link = mdio_read(mii_addr, info->phy_id, 1);
     if (!link || (link == 0xffff)) {
-	printk(KERN_INFO "%s: MII is missing!\n", dev->name);
+	netdev_info(dev, "MII is missing!\n");
 	info->phy_id = -1;
 	goto reschedule;
     }
@@ -636,18 +578,14 @@
     link &= 0x0004;
     if (link != info->link_status) {
 	u_short p = mdio_read(mii_addr, info->phy_id, 5);
-	printk(KERN_INFO "%s: %s link beat\n", dev->name,
-	       (link) ? "found" : "lost");
+	netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
 	if (link) {
 	    info->duplex_flag = (p & 0x0140) ? 0x80 : 0x00;
 	    if (p)
-		printk(KERN_INFO "%s: autonegotiation complete: "
-		       "%sbaseT-%cD selected\n", dev->name,
-		       ((p & 0x0180) ? "100" : "10"),
-		       ((p & 0x0140) ? 'F' : 'H'));
+		netdev_info(dev, "autonegotiation complete: %dbaseT-%cD selected\n",
+			    (p & 0x0180) ? 100 : 10, (p & 0x0140) ? 'F' : 'H');
 	    else
-		printk(KERN_INFO "%s: link partner did not autonegotiate\n",
-		       dev->name);
+		netdev_info(dev, "link partner did not autonegotiate\n");
 	    AX88190_init(dev, 1);
 	}
 	info->link_status = link;
@@ -658,16 +596,6 @@
     add_timer(&info->watchdog);
 }
 
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, "axnet_cs");
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-};
-
 /*====================================================================*/
 
 static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -783,9 +711,7 @@
 
 static struct pcmcia_driver axnet_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "axnet_cs",
-	},
+	.name		= "axnet_cs",
 	.probe		= axnet_probe,
 	.remove		= axnet_detach,
 	.id_table       = axnet_ids,
@@ -855,9 +781,6 @@
 
   */
 
-static const char version_8390[] = KERN_INFO \
-    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@scyld.com)\n";
-
 #include <linux/bitops.h>
 #include <asm/irq.h>
 #include <linux/fcntl.h>
@@ -1004,9 +927,11 @@
 	isr = inb(e8390_base+EN0_ISR);
 	spin_unlock_irqrestore(&ei_local->page_lock, flags);
 
-	printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
-		dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
-		(isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
+	netdev_printk(KERN_DEBUG, dev,
+		      "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
+		      (txsr & ENTSR_ABT) ? "excess collisions." :
+		      (isr) ? "lost interrupt?" : "cable problem?",
+		      txsr, isr, tickssofar);
 
 	if (!isr && !dev->stats.tx_packets) 
 	{
@@ -1076,22 +1001,28 @@
 		output_page = ei_local->tx_start_page;
 		ei_local->tx1 = send_length;
 		if (ei_debug  &&  ei_local->tx2 > 0)
-			printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
-				dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
+			netdev_printk(KERN_DEBUG, dev,
+				      "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
+				      ei_local->tx2, ei_local->lasttx,
+				      ei_local->txing);
 	}
 	else if (ei_local->tx2 == 0) 
 	{
 		output_page = ei_local->tx_start_page + TX_PAGES/2;
 		ei_local->tx2 = send_length;
 		if (ei_debug  &&  ei_local->tx1 > 0)
-			printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
-				dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
+			netdev_printk(KERN_DEBUG, dev,
+				      "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
+				      ei_local->tx1, ei_local->lasttx,
+				      ei_local->txing);
 	}
 	else
 	{	/* We should never get here. */
 		if (ei_debug)
-			printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n",
-				dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+			netdev_printk(KERN_DEBUG, dev,
+				      "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+				      ei_local->tx1, ei_local->tx2,
+				      ei_local->lasttx);
 		ei_local->irqlock = 0;
 		netif_stop_queue(dev);
 		outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -1179,23 +1110,26 @@
 	 
 	spin_lock_irqsave(&ei_local->page_lock, flags);
 
-	if (ei_local->irqlock) 
-	{
+	if (ei_local->irqlock) {
 #if 1 /* This might just be an interrupt for a PCI device sharing this line */
+		const char *msg;
 		/* The "irqlock" check is only for testing. */
-		printk(ei_local->irqlock
-			   ? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n"
-			   : "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n",
-			   dev->name, inb_p(e8390_base + EN0_ISR),
-			   inb_p(e8390_base + EN0_IMR));
+		if (ei_local->irqlock)
+			msg = "Interrupted while interrupts are masked!";
+		else
+			msg = "Reentering the interrupt handler!";
+		netdev_info(dev, "%s, isr=%#2x imr=%#2x\n",
+			    msg,
+			    inb_p(e8390_base + EN0_ISR),
+			    inb_p(e8390_base + EN0_IMR));
 #endif
 		spin_unlock_irqrestore(&ei_local->page_lock, flags);
 		return IRQ_NONE;
 	}
     
 	if (ei_debug > 3)
-		printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name,
-			   inb_p(e8390_base + EN0_ISR));
+		netdev_printk(KERN_DEBUG, dev, "interrupt(isr=%#2.2x)\n",
+			      inb_p(e8390_base + EN0_ISR));
 
 	outb_p(0x00, e8390_base + EN0_ISR);
 	ei_local->irqlock = 1;
@@ -1206,7 +1140,8 @@
 	{
 		if (!netif_running(dev) || (interrupts == 0xff)) {
 			if (ei_debug > 1)
-				printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
+				netdev_warn(dev,
+					    "interrupt from stopped card\n");
 			outb_p(interrupts, e8390_base + EN0_ISR);
 			interrupts = 0;
 			break;
@@ -1249,11 +1184,12 @@
 		{
 			/* 0xFF is valid for a card removal */
 			if(interrupts!=0xFF)
-				printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n",
-				   dev->name, interrupts);
+				netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
+					    interrupts);
 			outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
 		} else {
-			printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts);
+			netdev_warn(dev, "unknown interrupt %#2x\n",
+				    interrupts);
 			outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
 		}
 	}
@@ -1287,18 +1223,19 @@
 	unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
 
 #ifdef VERBOSE_ERROR_DUMP
-	printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
+	netdev_printk(KERN_DEBUG, dev,
+		      "transmitter error (%#2x):", txsr);
 	if (txsr & ENTSR_ABT)
-		printk("excess-collisions ");
+		pr_cont(" excess-collisions");
 	if (txsr & ENTSR_ND)
-		printk("non-deferral ");
+		pr_cont(" non-deferral");
 	if (txsr & ENTSR_CRS)
-		printk("lost-carrier ");
+		pr_cont(" lost-carrier");
 	if (txsr & ENTSR_FU)
-		printk("FIFO-underrun ");
+		pr_cont(" FIFO-underrun");
 	if (txsr & ENTSR_CDH)
-		printk("lost-heartbeat ");
-	printk("\n");
+		pr_cont(" lost-heartbeat");
+	pr_cont("\n");
 #endif
 
 	if (tx_was_aborted)
@@ -1335,8 +1272,9 @@
 	if (ei_local->tx1 < 0) 
 	{
 		if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
-			printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n",
-				ei_local->name, ei_local->lasttx, ei_local->tx1);
+			netdev_err(dev, "%s: bogus last_tx_buffer %d, tx1=%d\n",
+				   ei_local->name, ei_local->lasttx,
+				   ei_local->tx1);
 		ei_local->tx1 = 0;
 		if (ei_local->tx2 > 0) 
 		{
@@ -1351,8 +1289,9 @@
 	else if (ei_local->tx2 < 0) 
 	{
 		if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
-			printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
-				ei_local->name, ei_local->lasttx, ei_local->tx2);
+			netdev_info(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n",
+				    ei_local->name, ei_local->lasttx,
+				    ei_local->tx2);
 		ei_local->tx2 = 0;
 		if (ei_local->tx1 > 0) 
 		{
@@ -1365,8 +1304,9 @@
 		else
 			ei_local->lasttx = 10, ei_local->txing = 0;
 	}
-//	else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
-//			dev->name, ei_local->lasttx);
+//	else
+//		netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
+//			    ei_local->lasttx);
 
 	/* Minimize Tx latency: update the statistics after we restart TXing. */
 	if (status & ENTSR_COL)
@@ -1429,8 +1369,8 @@
 		   is that some clones crash in roughly the same way.
 		 */
 		if (ei_debug > 0  &&  this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
-			printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n",
-				   dev->name, this_frame, ei_local->current_page);
+		    netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
+			       this_frame, ei_local->current_page);
 		
 		if (this_frame == rxing_page)	/* Read all the frames? */
 			break;				/* Done for now */
@@ -1446,9 +1386,10 @@
 		if (pkt_len < 60  ||  pkt_len > 1518) 
 		{
 			if (ei_debug)
-				printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
-					   dev->name, rx_frame.count, rx_frame.status,
-					   rx_frame.next);
+				netdev_printk(KERN_DEBUG, dev,
+					      "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
+					      rx_frame.count, rx_frame.status,
+					      rx_frame.next);
 			dev->stats.rx_errors++;
 			dev->stats.rx_length_errors++;
 		}
@@ -1460,8 +1401,9 @@
 			if (skb == NULL) 
 			{
 				if (ei_debug > 1)
-					printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n",
-						   dev->name, pkt_len);
+					netdev_printk(KERN_DEBUG, dev,
+						      "Couldn't allocate a sk_buff of size %d\n",
+						      pkt_len);
 				dev->stats.rx_dropped++;
 				break;
 			}
@@ -1481,9 +1423,10 @@
 		else 
 		{
 			if (ei_debug)
-				printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
-					   dev->name, rx_frame.status, rx_frame.next,
-					   rx_frame.count);
+				netdev_printk(KERN_DEBUG, dev,
+					      "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+					      rx_frame.status, rx_frame.next,
+					      rx_frame.count);
 			dev->stats.rx_errors++;
 			/* NB: The NIC counts CRC, frame and missed errors. */
 			if (pkt_stat & ENRSR_FO)
@@ -1493,8 +1436,8 @@
 		
 		/* This _should_ never happen: it's here for avoiding bad clones. */
 		if (next_frame >= ei_local->stop_page) {
-			printk("%s: next frame inconsistency, %#2x\n", dev->name,
-				   next_frame);
+			netdev_info(dev, "next frame inconsistency, %#2x\n",
+				    next_frame);
 			next_frame = ei_local->rx_start_page;
 		}
 		ei_local->current_page = next_frame;
@@ -1529,7 +1472,7 @@
 	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
     
 	if (ei_debug > 1)
-		printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name);
+		netdev_printk(KERN_DEBUG, dev, "Receiver overrun\n");
 	dev->stats.rx_over_errors++;
     
 	/* 
@@ -1726,7 +1669,7 @@
 	{
 		outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
 		if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
-			printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
+			netdev_err(dev, "Hw. address read/write mismap %d\n", i);
 	}
 
 	outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
@@ -1763,8 +1706,7 @@
     
 	if (inb_p(e8390_base) & E8390_TRANS) 
 	{
-		printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n",
-			dev->name);
+		netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
 		return;
 	}
 	outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 3c400cf..27bfad7 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -43,7 +43,6 @@
 #include <linux/arcdevice.h>
 #include <linux/com20020.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -52,23 +51,23 @@
 
 #define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
 
-#ifdef DEBUG
 
 static void regdump(struct net_device *dev)
 {
+#ifdef DEBUG
     int ioaddr = dev->base_addr;
     int count;
     
-    printk("com20020 register dump:\n");
+    netdev_dbg(dev, "register dump:\n");
     for (count = ioaddr; count < ioaddr + 16; count++)
     {
 	if (!(count % 16))
-	    printk("\n%04X: ", count);
-	printk("%02X ", inb(count));
+	    pr_cont("%04X:", count);
+	pr_cont(" %02X", inb(count));
     }
-    printk("\n");
+    pr_cont("\n");
     
-    printk("buffer0 dump:\n");
+    netdev_dbg(dev, "buffer0 dump:\n");
 	/* set up the address register */
         count = 0;
 	outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
@@ -77,19 +76,15 @@
     for (count = 0; count < 256+32; count++)
     {
 	if (!(count % 16))
-	    printk("\n%04X: ", count);
+	    pr_cont("%04X:", count);
 	
 	/* copy the data */
-	printk("%02X ", inb(_MEMDATA));
+	pr_cont(" %02X", inb(_MEMDATA));
     }
-    printk("\n");
+    pr_cont("\n");
+#endif
 }
 
-#else
-
-static inline void regdump(struct net_device *dev) { }
-
-#endif
 
 
 /*====================================================================*/
@@ -123,14 +118,6 @@
     struct net_device       *dev;
 } com20020_dev_t;
 
-/*======================================================================
-
-    com20020_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int com20020_probe(struct pcmcia_device *p_dev)
 {
     com20020_dev_t *info;
@@ -160,8 +147,7 @@
 
     p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
     p_dev->resource[0]->end = 16;
-    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-    p_dev->conf.IntType = INT_MEMORY_AND_IO;
+    p_dev->config_flags |= CONF_ENABLE_IRQ;
 
     info->dev = dev;
     p_dev->priv = info;
@@ -174,15 +160,6 @@
     return -ENOMEM;
 } /* com20020_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void com20020_detach(struct pcmcia_device *link)
 {
     struct com20020_dev_t *info = link->priv;
@@ -221,14 +198,6 @@
 
 } /* com20020_detach */
 
-/*======================================================================
-
-    com20020_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.
-
-======================================================================*/
-
 static int com20020_config(struct pcmcia_device *link)
 {
     struct arcnet_local *lp;
@@ -282,7 +251,7 @@
 
     dev->irq = link->irq;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
@@ -301,13 +270,13 @@
     i = com20020_found(dev, 0);	/* calls register_netdev */
     
     if (i != 0) {
-	dev_printk(KERN_NOTICE, &link->dev,
-		"com20020_cs: com20020_found() failed\n");
+	dev_notice(&link->dev,
+		   "com20020_found() failed\n");
 	goto failed;
     }
 
-    dev_dbg(&link->dev,KERN_INFO "%s: port %#3lx, irq %d\n",
-           dev->name, dev->base_addr, dev->irq);
+    netdev_dbg(dev, "port %#3lx, irq %d\n",
+	       dev->base_addr, dev->irq);
     return 0;
 
 failed:
@@ -316,14 +285,6 @@
     return -ENODEV;
 } /* com20020_config */
 
-/*======================================================================
-
-    After a card is removed, com20020_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void com20020_release(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "com20020_release\n");
@@ -366,9 +327,7 @@
 
 static struct pcmcia_driver com20020_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "com20020_cs",
-	},
+	.name		= "com20020_cs",
 	.probe		= com20020_probe,
 	.remove		= com20020_detach,
 	.id_table	= com20020_ids,
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 98fffb0..9226cda 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -28,6 +28,8 @@
    
 ======================================================================*/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DRV_NAME	"fmvj18x_cs"
 #define DRV_VERSION	"2.9"
 
@@ -49,7 +51,6 @@
 #include <linux/ioport.h>
 #include <linux/crc32.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -252,8 +253,7 @@
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ;
 
     dev->netdev_ops = &fjn_netdev_ops;
     dev->watchdog_timeo = TX_TIMEOUT;
@@ -291,7 +291,7 @@
 	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 	if (link->resource[1]->start == 0) {
 	    link->resource[1]->end = 0;
-	    printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
+	    pr_notice("out of resource for serial\n");
 	}
 	ret = pcmcia_request_io(link);
 	if (ret == 0)
@@ -313,7 +313,7 @@
 	ret = pcmcia_request_io(link);
 	if (ret == 0) {
 	    /* calculate ConfigIndex value */
-	    link->conf.ConfigIndex = 
+	    link->config_index =
 		((link->resource[0]->start & 0x0f0) >> 3) | 0x22;
 	    return ret;
 	}
@@ -321,11 +321,7 @@
     return ret;	/* RequestIO failed */
 }
 
-static int fmvj18x_ioprobe(struct pcmcia_device *p_dev,
-			   cistpl_cftable_entry_t *cfg,
-			   cistpl_cftable_entry_t *dflt,
-			   unsigned int vcc,
-			   void *priv_data)
+static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
 {
 	return 0; /* strange, but that's what the code did already before... */
 }
@@ -362,28 +358,28 @@
 		link->card_id == PRODID_TDK_NP9610 ||
 		link->card_id == PRODID_TDK_MN3200) {
 		/* MultiFunction Card */
-		link->conf.ConfigBase = 0x800;
-		link->conf.ConfigIndex = 0x47;
+		link->config_base = 0x800;
+		link->config_index = 0x47;
 		link->resource[1]->end = 8;
 	    }
 	    break;
 	case MANFID_NEC:
 	    cardtype = NEC; /* MultiFunction Card */
-	    link->conf.ConfigBase = 0x800;
-	    link->conf.ConfigIndex = 0x47;
+	    link->config_base = 0x800;
+	    link->config_index = 0x47;
 	    link->resource[1]->end = 8;
 	    break;
 	case MANFID_KME:
 	    cardtype = KME; /* MultiFunction Card */
-	    link->conf.ConfigBase = 0x800;
-	    link->conf.ConfigIndex = 0x47;
+	    link->config_base = 0x800;
+	    link->config_index = 0x47;
 	    link->resource[1]->end = 8;
 	    break;
 	case MANFID_CONTEC:
 	    cardtype = CONTEC;
 	    break;
 	case MANFID_FUJITSU:
-	    if (link->conf.ConfigBase == 0x0fe0)
+	    if (link->config_base == 0x0fe0)
 		cardtype = MBH10302;
 	    else if (link->card_id == PRODID_FUJITSU_MBH10302) 
                 /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
@@ -403,10 +399,10 @@
 	case MANFID_FUJITSU:
 	    if (link->card_id == PRODID_FUJITSU_MBH10304) {
 		cardtype = XXX10304;    /* MBH10304 with buggy CIS */
-	        link->conf.ConfigIndex = 0x20;
+		link->config_index = 0x20;
 	    } else {
 		cardtype = MBH10302;    /* NextCom NC5310, etc. */
-		link->conf.ConfigIndex = 1;
+		link->config_index = 1;
 	    }
 	    break;
 	case MANFID_UNGERMANN:
@@ -414,7 +410,7 @@
 	    break;
 	default:
 	    cardtype = MBH10302;
-	    link->conf.ConfigIndex = 1;
+	    link->config_index = 1;
 	}
     }
 
@@ -432,7 +428,7 @@
     ret = pcmcia_request_irq(link, fjn_interrupt);
     if (ret)
 	    goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
@@ -503,7 +499,7 @@
     case XXX10304:
 	/* Read MACID from Buggy CIS */
 	if (fmvj18x_get_hwinfo(link, buggybuf) == -1) {
-	    printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n");
+	    pr_notice("unable to read hardware net address\n");
 	    goto failed;
 	}
 	for (i = 0 ; i < 6; i++) {
@@ -524,15 +520,14 @@
     SET_NETDEV_DEV(dev, &link->dev);
 
     if (register_netdev(dev) != 0) {
-	printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
+	pr_notice("register_netdev() failed\n");
 	goto failed;
     }
 
     /* print current configuration */
-    printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, "
-	   "hw_addr %pM\n",
-	   dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2", 
-	   dev->base_addr, dev->irq, dev->dev_addr);
+    netdev_info(dev, "%s, sram %s, port %#3lx, irq %d, hw_addr %pM\n",
+		card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
+		dev->base_addr, dev->irq, dev->dev_addr);
 
     return 0;
     
@@ -544,20 +539,18 @@
 
 static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 {
-    win_req_t req;
     u_char __iomem *base;
     int i, j;
 
     /* Allocate a small memory window */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = 0; req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[2]->start = 0; link->resource[2]->end = 0;
+    i = pcmcia_request_window(link, link->resource[2], 0);
     if (i != 0)
 	return -1;
 
-    base = ioremap(req.Base, req.Size);
-    pcmcia_map_mem_page(link, link->win, 0);
+    base = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
+    pcmcia_map_mem_page(link, link->resource[2], 0);
 
     /*
      *  MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
@@ -582,7 +575,7 @@
     }
 
     iounmap(base);
-    j = pcmcia_release_window(link, link->win);
+    j = pcmcia_release_window(link, link->resource[2]);
     return (i != 0x200) ? 0 : -1;
 
 } /* fmvj18x_get_hwinfo */
@@ -590,27 +583,26 @@
 
 static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 {
-    win_req_t req;
     int i;
     struct net_device *dev = link->priv;
     unsigned int ioaddr;
     local_info_t *lp = netdev_priv(dev);
 
     /* Allocate a small memory window */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = 0; req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[3]->start = link->resource[3]->end = 0;
+    i = pcmcia_request_window(link, link->resource[3], 0);
     if (i != 0)
 	return -1;
 
-    lp->base = ioremap(req.Base, req.Size);
+    lp->base = ioremap(link->resource[3]->start,
+		       resource_size(link->resource[3]));
     if (lp->base == NULL) {
-	printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n");
+	netdev_notice(dev, "ioremap failed\n");
 	return -1;
     }
 
-    i = pcmcia_map_mem_page(link, link->win, 0);
+    i = pcmcia_map_mem_page(link, link->resource[3], 0);
     if (i != 0) {
 	iounmap(lp->base);
 	lp->base = NULL;
@@ -638,7 +630,6 @@
     struct net_device *dev = link->priv;
     local_info_t *lp = netdev_priv(dev);
     u_char __iomem *tmp;
-    int j;
 
     dev_dbg(&link->dev, "fmvj18x_release\n");
 
@@ -646,7 +637,6 @@
 	tmp = lp->base;
 	lp->base = NULL;    /* set NULL before iounmap */
 	iounmap(tmp);
-	j = pcmcia_release_window(link, link->win);
     }
 
     pcmcia_disable_device(link);
@@ -708,9 +698,7 @@
 
 static struct pcmcia_driver fmvj18x_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "fmvj18x_cs",
-	},
+	.name		= "fmvj18x_cs",
 	.probe		= fmvj18x_probe,
 	.remove		= fmvj18x_detach,
 	.id_table       = fmvj18x_ids,
@@ -800,17 +788,16 @@
     struct local_info_t *lp = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
 
-    printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
-	   dev->name, htons(inw(ioaddr + TX_STATUS)),
-	   inb(ioaddr + TX_STATUS) & F_TMT_RDY
-	   ? "IRQ conflict" : "network cable problem");
-    printk(KERN_NOTICE "%s: timeout registers: %04x %04x %04x "
-	   "%04x %04x %04x %04x %04x.\n",
-	   dev->name, htons(inw(ioaddr + 0)),
-	   htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
-	   htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
-	   htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
-	   htons(inw(ioaddr +14)));
+    netdev_notice(dev, "transmit timed out with status %04x, %s?\n",
+		  htons(inw(ioaddr + TX_STATUS)),
+		  inb(ioaddr + TX_STATUS) & F_TMT_RDY
+		  ? "IRQ conflict" : "network cable problem");
+    netdev_notice(dev, "timeout registers: %04x %04x %04x "
+		  "%04x %04x %04x %04x %04x.\n",
+		  htons(inw(ioaddr + 0)), htons(inw(ioaddr + 2)),
+		  htons(inw(ioaddr + 4)), htons(inw(ioaddr + 6)),
+		  htons(inw(ioaddr + 8)), htons(inw(ioaddr + 10)),
+		  htons(inw(ioaddr + 12)), htons(inw(ioaddr + 14)));
     dev->stats.tx_errors++;
     /* ToDo: We should try to restart the adaptor... */
     local_irq_disable();
@@ -845,13 +832,13 @@
 	unsigned char *buf = skb->data;
 
 	if (length > ETH_FRAME_LEN) {
-	    printk(KERN_NOTICE "%s: Attempting to send a large packet"
-		   " (%d bytes).\n", dev->name, length);
+	    netdev_notice(dev, "Attempting to send a large packet (%d bytes)\n",
+			  length);
 	    return NETDEV_TX_BUSY;
 	}
 
-	pr_debug("%s: Transmitting a packet of length %lu.\n",
-	      dev->name, (unsigned long)skb->len);
+	netdev_dbg(dev, "Transmitting a packet of length %lu\n",
+		   (unsigned long)skb->len);
 	dev->stats.tx_bytes += skb->len;
 
 	/* Disable both interrupts. */
@@ -904,7 +891,7 @@
     unsigned int ioaddr = dev->base_addr;
     int i;
 
-    pr_debug("fjn_reset(%s) called.\n",dev->name);
+    netdev_dbg(dev, "fjn_reset() called\n");
 
     /* Reset controller */
     if( sram_config == 0 ) 
@@ -988,8 +975,8 @@
     while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
 	u_short status = inw(ioaddr + DATAPORT);
 
-	pr_debug("%s: Rxing packet mode %02x status %04x.\n",
-	      dev->name, inb(ioaddr + RX_MODE), status);
+	netdev_dbg(dev, "Rxing packet mode %02x status %04x.\n",
+		   inb(ioaddr + RX_MODE), status);
 #ifndef final_version
 	if (status == 0) {
 	    outb(F_SKP_PKT, ioaddr + RX_SKIP);
@@ -1008,16 +995,16 @@
 	    struct sk_buff *skb;
 
 	    if (pkt_len > 1550) {
-		printk(KERN_NOTICE "%s: The FMV-18x claimed a very "
-		       "large packet, size %d.\n", dev->name, pkt_len);
+		netdev_notice(dev, "The FMV-18x claimed a very large packet, size %d\n",
+			      pkt_len);
 		outb(F_SKP_PKT, ioaddr + RX_SKIP);
 		dev->stats.rx_errors++;
 		break;
 	    }
 	    skb = dev_alloc_skb(pkt_len+2);
 	    if (skb == NULL) {
-		printk(KERN_NOTICE "%s: Memory squeeze, dropping "
-		       "packet (len %d).\n", dev->name, pkt_len);
+		netdev_notice(dev, "Memory squeeze, dropping packet (len %d)\n",
+			      pkt_len);
 		outb(F_SKP_PKT, ioaddr + RX_SKIP);
 		dev->stats.rx_dropped++;
 		break;
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index b0d06a3..15d57f5 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -45,6 +45,8 @@
 
 ======================================================================*/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/ptrace.h>
@@ -52,12 +54,10 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/module.h>
-#include <linux/ethtool.h>
 #include <linux/netdevice.h>
 #include <linux/trdevice.h>
 #include <linux/ibmtr.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -102,35 +102,16 @@
 
 typedef struct ibmtr_dev_t {
 	struct pcmcia_device	*p_dev;
-    struct net_device	*dev;
-    window_handle_t     sram_win_handle;
-    struct tok_info	*ti;
+	struct net_device	*dev;
+	struct tok_info		*ti;
 } ibmtr_dev_t;
 
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, "ibmtr_cs");
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-};
-
 static irqreturn_t ibmtr_interrupt(int irq, void *dev_id) {
 	ibmtr_dev_t *info = dev_id;
 	struct net_device *dev = info->dev;
 	return tok_interrupt(irq, dev);
 };
 
-/*======================================================================
-
-    ibmtr_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int __devinit ibmtr_attach(struct pcmcia_device *link)
 {
     ibmtr_dev_t *info;
@@ -153,26 +134,14 @@
 
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[0]->end = 4;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_regs = PRESENT_OPTION;
 
     info->dev = dev;
 
-    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
-
     return ibmtr_config(link);
 } /* ibmtr_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void ibmtr_detach(struct pcmcia_device *link)
 {
     struct ibmtr_dev_t *info = link->priv;
@@ -197,26 +166,17 @@
     kfree(info);
 } /* ibmtr_detach */
 
-/*======================================================================
-
-    ibmtr_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    token-ring device available to the system.
-
-======================================================================*/
-
 static int __devinit ibmtr_config(struct pcmcia_device *link)
 {
     ibmtr_dev_t *info = link->priv;
     struct net_device *dev = info->dev;
     struct tok_info *ti = netdev_priv(dev);
-    win_req_t req;
     int i, ret;
 
     dev_dbg(&link->dev, "ibmtr_config\n");
 
-    link->conf.ConfigIndex = 0x61;
     link->io_lines = 16;
+    link->config_index = 0x61;
 
     /* Determine if this is PRIMARY or ALTERNATE. */
 
@@ -240,39 +200,39 @@
     ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
 
     /* Allocate the MMIO memory window */
-    req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    req.Attributes |= WIN_USE_WAIT;
-    req.Base = 0; 
-    req.Size = 0x2000;
-    req.AccessSpeed = 250;
-    ret = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[2]->flags |= WIN_USE_WAIT;
+    link->resource[2]->start = 0;
+    link->resource[2]->end = 0x2000;
+    ret = pcmcia_request_window(link, link->resource[2], 250);
     if (ret)
 	    goto failed;
 
-    ret = pcmcia_map_mem_page(link, link->win, mmiobase);
+    ret = pcmcia_map_mem_page(link, link->resource[2], mmiobase);
     if (ret)
 	    goto failed;
-    ti->mmio = ioremap(req.Base, req.Size);
+    ti->mmio = ioremap(link->resource[2]->start,
+		    resource_size(link->resource[2]));
 
     /* Allocate the SRAM memory window */
-    req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    req.Attributes |= WIN_USE_WAIT;
-    req.Base = 0;
-    req.Size = sramsize * 1024;
-    req.AccessSpeed = 250;
-    ret = pcmcia_request_window(link, &req, &info->sram_win_handle);
+    link->resource[3]->flags = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[3]->flags |= WIN_USE_WAIT;
+    link->resource[3]->start = 0;
+    link->resource[3]->end = sramsize * 1024;
+    ret = pcmcia_request_window(link, link->resource[3], 250);
     if (ret)
 	    goto failed;
 
-    ret = pcmcia_map_mem_page(link, info->sram_win_handle, srambase);
+    ret = pcmcia_map_mem_page(link, link->resource[3], srambase);
     if (ret)
 	    goto failed;
 
     ti->sram_base = srambase >> 12;
-    ti->sram_virt = ioremap(req.Base, req.Size);
-    ti->sram_phys = req.Base;
+    ti->sram_virt = ioremap(link->resource[3]->start,
+		    resource_size(link->resource[3]));
+    ti->sram_phys = link->resource[3]->start;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
@@ -285,15 +245,14 @@
 
     i = ibmtr_probe_card(dev);
     if (i != 0) {
-	printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
+	pr_notice("register_netdev() failed\n");
 	goto failed;
     }
 
-    printk(KERN_INFO
-	   "%s: port %#3lx, irq %d,  mmio %#5lx, sram %#5lx, hwaddr=%pM\n",
-           dev->name, dev->base_addr, dev->irq,
-	   (u_long)ti->mmio, (u_long)(ti->sram_base << 12),
-	   dev->dev_addr);
+    netdev_info(dev, "port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n",
+		dev->base_addr, dev->irq,
+		(u_long)ti->mmio, (u_long)(ti->sram_base << 12),
+		dev->dev_addr);
     return 0;
 
 failed:
@@ -301,14 +260,6 @@
     return -ENODEV;
 } /* ibmtr_config */
 
-/*======================================================================
-
-    After a card is removed, ibmtr_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void ibmtr_release(struct pcmcia_device *link)
 {
 	ibmtr_dev_t *info = link->priv;
@@ -316,7 +267,7 @@
 
 	dev_dbg(&link->dev, "ibmtr_release\n");
 
-	if (link->win) {
+	if (link->resource[2]->end) {
 		struct tok_info *ti = netdev_priv(dev);
 		iounmap(ti->mmio);
 	}
@@ -398,9 +349,7 @@
 
 static struct pcmcia_driver ibmtr_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "ibmtr_cs",
-	},
+	.name		= "ibmtr_cs",
 	.probe		= ibmtr_attach,
 	.remove		= ibmtr_detach,
 	.id_table       = ibmtr_ids,
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 68f2dee..0a2b0f9 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -111,6 +111,8 @@
 
 ---------------------------------------------------------------------------- */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DRV_NAME	"nmclan_cs"
 #define DRV_VERSION	"0.16"
 
@@ -146,7 +148,6 @@
 #include <linux/ioport.h>
 #include <linux/bitops.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
@@ -435,13 +436,6 @@
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
-/* ----------------------------------------------------------------------------
-nmclan_attach
-	Creates an "instance" of the driver, allocating local data
-	structures for one device.  The device is registered with Card
-	Services.
----------------------------------------------------------------------------- */
-
 static int nmclan_probe(struct pcmcia_device *link)
 {
     mace_private *lp;
@@ -460,10 +454,9 @@
     spin_lock_init(&lp->bank_lock);
     link->resource[0]->end = 32;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_index = 1;
+    link->config_regs = PRESENT_OPTION;
 
     lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
 
@@ -474,14 +467,6 @@
     return nmclan_config(link);
 } /* nmclan_attach */
 
-/* ----------------------------------------------------------------------------
-nmclan_detach
-	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 nmclan_detach(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
@@ -519,7 +504,7 @@
       spin_unlock_irqrestore(&lp->bank_lock, flags);
       break;
   }
-  return (data & 0xFF);
+  return data & 0xFF;
 } /* mace_read */
 
 /* ----------------------------------------------------------------------------
@@ -563,7 +548,7 @@
     /* Wait for reset bit to be cleared automatically after <= 200ns */;
     if(++ct > 500)
     {
-    	printk(KERN_ERR "mace: reset failed, card removed ?\n");
+	pr_err("reset failed, card removed?\n");
     	return -1;
     }
     udelay(1);
@@ -610,7 +595,7 @@
   {
   	if(++ ct > 500)
   	{
-  		printk(KERN_ERR "mace: ADDRCHG timeout, card removed ?\n");
+		pr_err("ADDRCHG timeout, card removed?\n");
   		return -1;
   	}
   }
@@ -625,13 +610,6 @@
   return 0;
 } /* mace_init */
 
-/* ----------------------------------------------------------------------------
-nmclan_config
-	This routine is scheduled to run after a CARD_INSERTION event
-	is received, to configure the PCMCIA socket, and to make the
-	ethernet device available to the system.
----------------------------------------------------------------------------- */
-
 static int nmclan_config(struct pcmcia_device *link)
 {
   struct net_device *dev = link->priv;
@@ -650,7 +628,7 @@
   ret = pcmcia_request_exclusive_irq(link, mace_interrupt);
   if (ret)
 	  goto failed;
-  ret = pcmcia_request_configuration(link, &link->conf);
+  ret = pcmcia_enable_device(link);
   if (ret)
 	  goto failed;
 
@@ -678,8 +656,8 @@
       dev_dbg(&link->dev, "nmclan_cs configured: mace id=%x %x\n",
 	    sig[0], sig[1]);
     } else {
-      printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should"
-	     " be 0x40 0x?9\n", sig[0], sig[1]);
+      pr_notice("mace id not found: %x %x should be 0x40 0x?9\n",
+		sig[0], sig[1]);
       return -ENODEV;
     }
   }
@@ -691,20 +669,18 @@
   if (if_port <= 2)
     dev->if_port = if_port;
   else
-    printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");
+    pr_notice("invalid if_port requested\n");
 
   SET_NETDEV_DEV(dev, &link->dev);
 
   i = register_netdev(dev);
   if (i != 0) {
-    printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
+    pr_notice("register_netdev() failed\n");
     goto failed;
   }
 
-  printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port,"
-	 " hw_addr %pM\n",
-	 dev->name, dev->base_addr, dev->irq, if_names[dev->if_port],
-	 dev->dev_addr);
+  netdev_info(dev, "nmclan: port %#3lx, irq %d, %s port, hw_addr %pM\n",
+	      dev->base_addr, dev->irq, if_names[dev->if_port], dev->dev_addr);
   return 0;
 
 failed:
@@ -712,12 +688,6 @@
 	return -ENODEV;
 } /* nmclan_config */
 
-/* ----------------------------------------------------------------------------
-nmclan_release
-	After a card is removed, nmclan_release() will unregister the
-	net device, and release the PCMCIA configuration.  If the device
-	is still open, this will be postponed until it is closed.
----------------------------------------------------------------------------- */
 static void nmclan_release(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "nmclan_release\n");
@@ -798,8 +768,7 @@
   if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
     if (map->port <= 2) {
       dev->if_port = map->port;
-      printk(KERN_INFO "%s: switched to %s port\n", dev->name,
-	     if_names[dev->if_port]);
+      netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
     } else
       return -EINVAL;
   }
@@ -878,12 +847,12 @@
   mace_private *lp = netdev_priv(dev);
   struct pcmcia_device *link = lp->p_dev;
 
-  printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
+  netdev_notice(dev, "transmit timed out -- ");
 #if RESET_ON_TIMEOUT
-  printk("resetting card\n");
+  pr_cont("resetting card\n");
   pcmcia_reset_card(link->socket);
 #else /* #if RESET_ON_TIMEOUT */
-  printk("NOT resetting card\n");
+  pr_cont("NOT resetting card\n");
 #endif /* #if RESET_ON_TIMEOUT */
   dev->trans_start = jiffies; /* prevent tx timeout */
   netif_wake_queue(dev);
@@ -965,22 +934,21 @@
   ioaddr = dev->base_addr;
 
   if (lp->tx_irq_disabled) {
-    printk(
-      (lp->tx_irq_disabled?
-       KERN_NOTICE "%s: Interrupt with tx_irq_disabled "
-       "[isr=%02X, imr=%02X]\n": 
-       KERN_NOTICE "%s: Re-entering the interrupt handler "
-       "[isr=%02X, imr=%02X]\n"),
-      dev->name,
-      inb(ioaddr + AM2150_MACE_BASE + MACE_IR),
-      inb(ioaddr + AM2150_MACE_BASE + MACE_IMR)
-    );
+    const char *msg;
+    if (lp->tx_irq_disabled)
+      msg = "Interrupt with tx_irq_disabled";
+    else
+      msg = "Re-entering the interrupt handler";
+    netdev_notice(dev, "%s [isr=%02X, imr=%02X]\n",
+		  msg,
+		  inb(ioaddr + AM2150_MACE_BASE + MACE_IR),
+		  inb(ioaddr + AM2150_MACE_BASE + MACE_IMR));
     /* WARNING: MACE_IR has been read! */
     return IRQ_NONE;
   }
 
   if (!netif_device_present(dev)) {
-    pr_debug("%s: interrupt from dead card\n", dev->name);
+    netdev_dbg(dev, "interrupt from dead card\n");
     return IRQ_NONE;
   }
 
@@ -1378,8 +1346,8 @@
     printk(KERN_DEBUG "    adr =%pM\n", adr);
   printk(KERN_DEBUG "    hashcode = %d(decimal), ladrf[0:63] =", hashcode);
   for (i = 0; i < 8; i++)
-    printk(KERN_CONT " %02X", ladrf[i]);
-  printk(KERN_CONT "\n");
+    pr_cont(" %02X", ladrf[i]);
+  pr_cont("\n");
 #endif
 } /* BuildLAF */
 
@@ -1535,9 +1503,7 @@
 
 static struct pcmcia_driver nmclan_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "nmclan_cs",
-	},
+	.name		= "nmclan_cs",
 	.probe		= nmclan_probe,
 	.remove		= nmclan_detach,
 	.id_table       = nmclan_ids,
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index f9b509a..03096c8 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -28,6 +28,8 @@
 
 ======================================================================*/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -35,14 +37,12 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
-#include <linux/ethtool.h>
 #include <linux/netdevice.h>
 #include <linux/log2.h>
 #include <linux/etherdevice.h>
 #include <linux/mii.h>
 #include "../8390.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -100,7 +100,6 @@
 static int pcnet_open(struct net_device *dev);
 static int pcnet_close(struct net_device *dev);
 static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static const struct ethtool_ops netdev_ethtool_ops;
 static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
 static void ei_watchdog(u_long arg);
 static void pcnet_reset_8390(struct net_device *dev);
@@ -238,14 +237,6 @@
 #endif
 };
 
-/*======================================================================
-
-    pcnet_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int pcnet_probe(struct pcmcia_device *link)
 {
     pcnet_dev_t *info;
@@ -260,23 +251,13 @@
     info->p_dev = link;
     link->priv = dev;
 
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
     dev->netdev_ops = &pcnet_netdev_ops;
 
     return pcnet_config(link);
 } /* pcnet_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void pcnet_detach(struct pcmcia_device *link)
 {
 	struct net_device *dev = link->priv;
@@ -300,22 +281,22 @@
 static hw_info_t *get_hwinfo(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
-    win_req_t req;
     u_char __iomem *base, *virt;
     int i, j;
 
     /* Allocate a small memory window */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = 0; req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[2]->start = 0; link->resource[2]->end = 0;
+    i = pcmcia_request_window(link, link->resource[2], 0);
     if (i != 0)
 	return NULL;
 
-    virt = ioremap(req.Base, req.Size);
+    virt = ioremap(link->resource[2]->start,
+	    resource_size(link->resource[2]));
     for (i = 0; i < NR_INFO; i++) {
-	pcmcia_map_mem_page(link, link->win, hw_info[i].offset & ~(req.Size-1));
-	base = &virt[hw_info[i].offset & (req.Size-1)];
+	pcmcia_map_mem_page(link, link->resource[2],
+		hw_info[i].offset & ~(resource_size(link->resource[2])-1));
+	base = &virt[hw_info[i].offset & (resource_size(link->resource[2])-1)];
 	if ((readb(base+0) == hw_info[i].a0) &&
 	    (readb(base+2) == hw_info[i].a1) &&
 	    (readb(base+4) == hw_info[i].a2)) {
@@ -326,7 +307,7 @@
     }
 
     iounmap(virt);
-    j = pcmcia_release_window(link, link->win);
+    j = pcmcia_release_window(link, link->resource[2]);
     return (i < NR_INFO) ? hw_info+i : NULL;
 } /* get_hwinfo */
 
@@ -421,7 +402,7 @@
     int i, j;
 
     /* Not much of a test, but the alternatives are messy */
-    if (link->conf.ConfigBase != 0x03c0)
+    if (link->config_base != 0x03c0)
 	return NULL;
 
     outb_p(0x01, ioaddr + EN0_DCFG);	/* Set word-wide access. */
@@ -434,8 +415,6 @@
 	dev->dev_addr[i] = j & 0xff;
 	dev->dev_addr[i+1] = j >> 8;
     }
-    printk(KERN_NOTICE "pcnet_cs: this is an AX88190 card!\n");
-    printk(KERN_NOTICE "pcnet_cs: use axnet_cs instead.\n");
     return NULL;
 }
 
@@ -463,14 +442,6 @@
     return &default_info;
 } /* get_hwired */
 
-/*======================================================================
-
-    pcnet_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-
-======================================================================*/
-
 static int try_io_port(struct pcmcia_device *link)
 {
     int j, ret;
@@ -502,43 +473,22 @@
     }
 }
 
-static int pcnet_confcheck(struct pcmcia_device *p_dev,
-			   cistpl_cftable_entry_t *cfg,
-			   cistpl_cftable_entry_t *dflt,
-			   unsigned int vcc,
-			   void *priv_data)
+static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int *priv = priv_data;
 	int try = (*priv & 0x1);
-	int i;
-	cistpl_io_t *io = &cfg->io;
 
-	if (cfg->index == 0 || cfg->io.nwin == 0)
+	*priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10;
+
+	if (p_dev->config_index == 0)
 		return -EINVAL;
 
-	/* For multifunction cards, by convention, we configure the
-	   network function with window 0, and serial with window 1 */
-	if (io->nwin > 1) {
-		i = (io->win[1].len > io->win[0].len);
-		p_dev->resource[1]->start = io->win[1-i].base;
-		p_dev->resource[1]->end = io->win[1-i].len;
-	} else {
-		i = p_dev->resource[1]->end = 0;
-	}
+	if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
+		return -EINVAL;
 
-	*priv &= ((cfg->mem.nwin == 1) &&
-		  (cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10;
-
-	p_dev->resource[0]->start = io->win[i].base;
-	p_dev->resource[0]->end = io->win[i].len;
-	if (!try)
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-	else
+	if (try)
 		p_dev->io_lines = 16;
-	if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
-		return try_io_port(p_dev);
-
-	return -EINVAL;
+	return try_io_port(p_dev);
 }
 
 static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
@@ -560,15 +510,14 @@
 	if (!link->irq)
 		return NULL;
 
-	if (resource_size(link->resource[1]) == 8) {
-		link->conf.Attributes |= CONF_ENABLE_SPKR;
-		link->conf.Status = CCSR_AUDIO_ENA;
-	}
+	if (resource_size(link->resource[1]) == 8)
+		link->config_flags |= CONF_ENABLE_SPKR;
+
 	if ((link->manf_id == MANFID_IBM) &&
 	    (link->card_id == PRODID_IBM_HOME_AND_AWAY))
-		link->conf.ConfigIndex |= 0x10;
+		link->config_index |= 0x10;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		return NULL;
 
@@ -583,7 +532,7 @@
 	} else
 		dev->if_port = 0;
 
-	if ((link->conf.ConfigBase == 0x03c0) &&
+	if ((link->config_base == 0x03c0) &&
 	    (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
 		dev_info(&link->dev,
 			"this is an AX88190 card - use axnet_cs instead.\n");
@@ -653,9 +602,7 @@
 
     ei_status.name = "NE2000";
     ei_status.word16 = 1;
-    ei_status.reset_8390 = &pcnet_reset_8390;
-
-    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+    ei_status.reset_8390 = pcnet_reset_8390;
 
     if (info->flags & (IS_DL10019|IS_DL10022))
 	mii_phy_probe(dev);
@@ -663,25 +610,25 @@
     SET_NETDEV_DEV(dev, &link->dev);
 
     if (register_netdev(dev) != 0) {
-	printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n");
+	pr_notice("register_netdev() failed\n");
 	goto failed;
     }
 
     if (info->flags & (IS_DL10019|IS_DL10022)) {
 	u_char id = inb(dev->base_addr + 0x1a);
-	printk(KERN_INFO "%s: NE2000 (DL100%d rev %02x): ",
-	       dev->name, ((info->flags & IS_DL10022) ? 22 : 19), id);
+	netdev_info(dev, "NE2000 (DL100%d rev %02x): ",
+	       (info->flags & IS_DL10022) ? 22 : 19, id);
 	if (info->pna_phy)
-	    printk("PNA, ");
+	    pr_cont("PNA, ");
     } else {
-	printk(KERN_INFO "%s: NE2000 Compatible: ", dev->name);
+	netdev_info(dev, "NE2000 Compatible: ");
     }
-    printk("io %#3lx, irq %d,", dev->base_addr, dev->irq);
+    pr_cont("io %#3lx, irq %d,", dev->base_addr, dev->irq);
     if (info->flags & USE_SHMEM)
-	printk (" mem %#5lx,", dev->mem_start);
+	pr_cont(" mem %#5lx,", dev->mem_start);
     if (info->flags & HAS_MISC_REG)
-	printk(" %s xcvr,", if_names[dev->if_port]);
-    printk(" hw_addr %pM\n", dev->dev_addr);
+	pr_cont(" %s xcvr,", if_names[dev->if_port]);
+    pr_cont(" hw_addr %pM\n", dev->dev_addr);
     return 0;
 
 failed:
@@ -689,14 +636,6 @@
     return -ENODEV;
 } /* pcnet_config */
 
-/*======================================================================
-
-    After a card is removed, pcnet_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void pcnet_release(struct pcmcia_device *link)
 {
 	pcnet_dev_t *info = PRIV(link->priv);
@@ -709,15 +648,6 @@
 	pcmcia_disable_device(link);
 }
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
-
-======================================================================*/
-
 static int pcnet_suspend(struct pcmcia_device *link)
 {
 	struct net_device *dev = link->priv;
@@ -955,7 +885,7 @@
 	phyid = tmp << 16;
 	phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2);
 	phyid &= MII_PHYID_REV_MASK;
-	pr_debug("%s: MII at %d is 0x%08x\n", dev->name, i, phyid);
+	netdev_dbg(dev, "MII at %d is 0x%08x\n", i, phyid);
 	if (phyid == AM79C9XX_HOME_PHY) {
 	    info->pna_phy = i;
 	} else if (phyid != AM79C9XX_ETH_PHY) {
@@ -988,7 +918,7 @@
     info->phy_id = info->eth_phy;
     info->link_status = 0x00;
     init_timer(&info->watchdog);
-    info->watchdog.function = &ei_watchdog;
+    info->watchdog.function = ei_watchdog;
     info->watchdog.data = (u_long)dev;
     info->watchdog.expires = jiffies + HZ;
     add_timer(&info->watchdog);
@@ -1041,8 +971,8 @@
     outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
 
     if (i == 100)
-	printk(KERN_ERR "%s: pcnet_reset_8390() did not complete.\n",
-	       dev->name);
+	netdev_err(dev, "pcnet_reset_8390() did not complete.\n");
+
     set_misc_reg(dev);
 
 } /* pcnet_reset_8390 */
@@ -1058,8 +988,7 @@
 	else if ((map->port < 1) || (map->port > 2))
 	    return -EINVAL;
 	dev->if_port = map->port;
-	printk(KERN_INFO "%s: switched to %s port\n",
-	       dev->name, if_names[dev->if_port]);
+	netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
 	NS8390_init(dev, 1);
     }
     return 0;
@@ -1094,7 +1023,7 @@
        this, we can limp along even if the interrupt is blocked */
     if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
 	if (!info->fast_poll)
-	    printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
+	    netdev_info(dev, "interrupt(s) dropped!\n");
 	ei_irq_wrapper(dev->irq, dev);
 	info->fast_poll = HZ;
     }
@@ -1114,7 +1043,7 @@
 	if (info->eth_phy) {
 	    info->phy_id = info->eth_phy = 0;
 	} else {
-	    printk(KERN_INFO "%s: MII is missing!\n", dev->name);
+	    netdev_info(dev, "MII is missing!\n");
 	    info->flags &= ~HAS_MII;
 	}
 	goto reschedule;
@@ -1123,8 +1052,7 @@
     link &= 0x0004;
     if (link != info->link_status) {
 	u_short p = mdio_read(mii_addr, info->phy_id, 5);
-	printk(KERN_INFO "%s: %s link beat\n", dev->name,
-	       (link) ? "found" : "lost");
+	netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
 	if (link && (info->flags & IS_DL10022)) {
 	    /* Disable collision detection on full duplex links */
 	    outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG);
@@ -1135,13 +1063,12 @@
 	if (link) {
 	    if (info->phy_id == info->eth_phy) {
 		if (p)
-		    printk(KERN_INFO "%s: autonegotiation complete: "
-			   "%sbaseT-%cD selected\n", dev->name,
+		    netdev_info(dev, "autonegotiation complete: "
+			   "%sbaseT-%cD selected\n",
 			   ((p & 0x0180) ? "100" : "10"),
 			   ((p & 0x0140) ? 'F' : 'H'));
 		else
-		    printk(KERN_INFO "%s: link partner did not "
-			   "autonegotiate\n", dev->name);
+		    netdev_info(dev, "link partner did not autonegotiate\n");
 	    }
 	    NS8390_init(dev, 1);
 	}
@@ -1154,7 +1081,7 @@
 	    /* isolate this MII and try flipping to the other one */
 	    mdio_write(mii_addr, info->phy_id, 0, 0x0400);
 	    info->phy_id ^= info->pna_phy ^ info->eth_phy;
-	    printk(KERN_INFO "%s: switched to %s transceiver\n", dev->name,
+	    netdev_info(dev, "switched to %s transceiver\n",
 		   (info->phy_id == info->eth_phy) ? "ethernet" : "PNA");
 	    mdio_write(mii_addr, info->phy_id, 0,
 		       (info->phy_id == info->eth_phy) ? 0x1000 : 0);
@@ -1170,18 +1097,6 @@
 
 /*====================================================================*/
 
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, "pcnet_cs");
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-};
-
-/*====================================================================*/
-
 
 static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
@@ -1214,9 +1129,9 @@
     unsigned int nic_base = dev->base_addr;
 
     if (ei_status.dmaing) {
-	printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input."
+	netdev_notice(dev, "DMAing conflict in dma_block_input."
 	       "[DMAstat:%1x][irqlock:%1x]\n",
-	       dev->name, ei_status.dmaing, ei_status.irqlock);
+	       ei_status.dmaing, ei_status.irqlock);
 	return;
     }
 
@@ -1247,11 +1162,11 @@
     char *buf = skb->data;
 
     if ((ei_debug > 4) && (count != 4))
-	pr_debug("%s: [bi=%d]\n", dev->name, count+4);
+	netdev_dbg(dev, "[bi=%d]\n", count+4);
     if (ei_status.dmaing) {
-	printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input."
+	netdev_notice(dev, "DMAing conflict in dma_block_input."
 	       "[DMAstat:%1x][irqlock:%1x]\n",
-	       dev->name, ei_status.dmaing, ei_status.irqlock);
+	       ei_status.dmaing, ei_status.irqlock);
 	return;
     }
     ei_status.dmaing |= 0x01;
@@ -1281,9 +1196,9 @@
 		break;
 	} while (--tries > 0);
 	if (tries <= 0)
-	    printk(KERN_NOTICE "%s: RX transfer address mismatch,"
+	    netdev_notice(dev, "RX transfer address mismatch,"
 		   "%#4.4x (expected) vs. %#4.4x (actual).\n",
-		   dev->name, ring_offset + xfer_count, addr);
+		   ring_offset + xfer_count, addr);
     }
 #endif
     outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
@@ -1304,7 +1219,7 @@
 
 #ifdef PCMCIA_DEBUG
     if (ei_debug > 4)
-	printk(KERN_DEBUG "%s: [bo=%d]\n", dev->name, count);
+	netdev_dbg(dev, "[bo=%d]\n", count);
 #endif
 
     /* Round the count up for word writes.  Do we need to do this?
@@ -1313,9 +1228,9 @@
     if (count & 0x01)
 	count++;
     if (ei_status.dmaing) {
-	printk(KERN_NOTICE "%s: DMAing conflict in dma_block_output."
+	netdev_notice(dev, "DMAing conflict in dma_block_output."
 	       "[DMAstat:%1x][irqlock:%1x]\n",
-	       dev->name, ei_status.dmaing, ei_status.irqlock);
+	       ei_status.dmaing, ei_status.irqlock);
 	return;
     }
     ei_status.dmaing |= 0x01;
@@ -1352,9 +1267,9 @@
 		break;
 	} while (--tries > 0);
 	if (tries <= 0) {
-	    printk(KERN_NOTICE "%s: Tx packet transfer address mismatch,"
+	    netdev_notice(dev, "Tx packet transfer address mismatch,"
 		   "%#4.4x (expected) vs. %#4.4x (actual).\n",
-		   dev->name, (start_page << 8) + count, addr);
+		   (start_page << 8) + count, addr);
 	    if (retries++ == 0)
 		goto retry;
 	}
@@ -1363,8 +1278,7 @@
 
     while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
 	if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) {
-	    printk(KERN_NOTICE "%s: timeout waiting for Tx RDC.\n",
-		   dev->name);
+	    netdev_notice(dev, "timeout waiting for Tx RDC.\n");
 	    pcnet_reset_8390(dev);
 	    NS8390_init(dev, 1);
 	    break;
@@ -1388,9 +1302,9 @@
     ei_status.stop_page = stop_pg;
 
     /* set up block i/o functions */
-    ei_status.get_8390_hdr = &dma_get_8390_hdr;
-    ei_status.block_input = &dma_block_input;
-    ei_status.block_output = &dma_block_output;
+    ei_status.get_8390_hdr = dma_get_8390_hdr;
+    ei_status.block_input = dma_block_input;
+    ei_status.block_output = dma_block_output;
 
     return 0;
 }
@@ -1486,7 +1400,6 @@
 {
     struct net_device *dev = link->priv;
     pcnet_dev_t *info = PRIV(dev);
-    win_req_t req;
     int i, window_size, offset, ret;
 
     window_size = (stop_pg - start_pg) << 8;
@@ -1497,22 +1410,22 @@
     window_size = roundup_pow_of_two(window_size);
 
     /* Allocate a memory window */
-    req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    req.Attributes |= WIN_USE_WAIT;
-    req.Base = 0; req.Size = window_size;
-    req.AccessSpeed = mem_speed;
-    ret = pcmcia_request_window(link, &req, &link->win);
+    link->resource[3]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[3]->flags |= WIN_USE_WAIT;
+    link->resource[3]->start = 0; link->resource[3]->end = window_size;
+    ret = pcmcia_request_window(link, link->resource[3], mem_speed);
     if (ret)
 	    goto failed;
 
     offset = (start_pg << 8) + cm_offset;
     offset -= offset % window_size;
-    ret = pcmcia_map_mem_page(link, link->win, offset);
+    ret = pcmcia_map_mem_page(link, link->resource[3], offset);
     if (ret)
 	    goto failed;
 
     /* Try scribbling on the buffer */
-    info->base = ioremap(req.Base, window_size);
+    info->base = ioremap(link->resource[3]->start,
+			resource_size(link->resource[3]));
     for (i = 0; i < (TX_PAGES<<8); i += 2)
 	__raw_writew((i>>1), info->base+offset+i);
     udelay(100);
@@ -1521,24 +1434,25 @@
     pcnet_reset_8390(dev);
     if (i != (TX_PAGES<<8)) {
 	iounmap(info->base);
-	pcmcia_release_window(link, link->win);
-	info->base = NULL; link->win = 0;
+	pcmcia_release_window(link, link->resource[3]);
+	info->base = NULL;
 	goto failed;
     }
 
     ei_status.mem = info->base + offset;
-    ei_status.priv = req.Size;
+    ei_status.priv = resource_size(link->resource[3]);
     dev->mem_start = (u_long)ei_status.mem;
-    dev->mem_end = dev->mem_start + req.Size;
+    dev->mem_end = dev->mem_start + resource_size(link->resource[3]);
 
     ei_status.tx_start_page = start_pg;
     ei_status.rx_start_page = start_pg + TX_PAGES;
-    ei_status.stop_page = start_pg + ((req.Size - offset) >> 8);
+    ei_status.stop_page = start_pg + (
+	    (resource_size(link->resource[3]) - offset) >> 8);
 
     /* set up block i/o functions */
-    ei_status.get_8390_hdr = &shmem_get_8390_hdr;
-    ei_status.block_input = &shmem_block_input;
-    ei_status.block_output = &shmem_block_output;
+    ei_status.get_8390_hdr = shmem_get_8390_hdr;
+    ei_status.block_input = shmem_block_input;
+    ei_status.block_output = shmem_block_output;
 
     info->flags |= USE_SHMEM;
     return 0;
@@ -1772,9 +1686,7 @@
 MODULE_FIRMWARE("cis/tamarack.cis");
 
 static struct pcmcia_driver pcnet_driver = {
-	.drv		= {
-		.name	= "pcnet_cs",
-	},
+	.name		= "pcnet_cs",
 	.probe		= pcnet_probe,
 	.remove		= pcnet_detach,
 	.owner		= THIS_MODULE,
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 377367d..8a9ff53 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -25,6 +25,8 @@
 
 ======================================================================*/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -44,7 +46,6 @@
 #include <linux/jiffies.h>
 #include <linux/firmware.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -294,20 +295,12 @@
 	.ndo_tx_timeout 	= smc_tx_timeout,
 	.ndo_set_config 	= s9k_config,
 	.ndo_set_multicast_list = set_rx_mode,
-	.ndo_do_ioctl		= &smc_ioctl,
+	.ndo_do_ioctl		= smc_ioctl,
 	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
-/*======================================================================
-
-  smc91c92_attach() creates an "instance" of the driver, allocating
-  local data structures for one device.  The device is registered
-  with Card Services.
-
-======================================================================*/
-
 static int smc91c92_probe(struct pcmcia_device *link)
 {
     struct smc_private *smc;
@@ -324,10 +317,6 @@
     link->priv = dev;
 
     spin_lock_init(&smc->lock);
-    link->resource[0]->end = 16;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     /* The SMC91c92-specific entries in the device structure. */
     dev->netdev_ops = &smc_netdev_ops;
@@ -343,15 +332,6 @@
     return smc91c92_config(link);
 } /* smc91c92_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void smc91c92_detach(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
@@ -412,26 +392,28 @@
     mdelay(200);
 
     /* Now read and write the COR... */
-    tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR);
+    tmp = readb(smc->base + link->config_base + CISREG_COR);
     udelay(5);
-    writeb(tmp, smc->base + link->conf.ConfigBase + CISREG_COR);
+    writeb(tmp, smc->base + link->config_base + CISREG_COR);
 
     return 0;
 }
 
-static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cf,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
-				void *priv_data)
+static int mhz_mfc_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int k;
-	p_dev->resource[1]->start = cf->io.win[0].base;
+	p_dev->io_lines = 16;
+	p_dev->resource[1]->start = p_dev->resource[0]->start;
+	p_dev->resource[1]->end = 8;
+	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[0]->end = 16;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	for (k = 0; k < 0x400; k += 0x10) {
 		if (k & 0x80)
 			continue;
 		p_dev->resource[0]->start = k ^ 0x300;
-		p_dev->io_lines = 16;
 		if (!pcmcia_request_io(p_dev))
 			return 0;
 	}
@@ -442,14 +424,11 @@
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
-    win_req_t req;
     unsigned int offset;
     int i;
 
-    link->conf.Attributes |= CONF_ENABLE_SPKR;
-    link->conf.Status = CCSR_AUDIO_ENA;
-    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->resource[1]->end = 8;
+    link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ |
+	    CONF_AUTO_SET_IO;
 
     /* The Megahertz combo cards have modem-like CIS entries, so
        we have to explicitly try a bunch of port combinations. */
@@ -459,16 +438,16 @@
     dev->base_addr = link->resource[0]->start;
 
     /* Allocate a memory window, for accessing the ISR */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[2]->start = link->resource[2]->end = 0;
+    i = pcmcia_request_window(link, link->resource[2], 0);
     if (i != 0)
 	    return -ENODEV;
 
-    smc->base = ioremap(req.Base, req.Size);
-    offset = (smc->manfid == MANFID_MOTOROLA) ? link->conf.ConfigBase : 0;
-    i = pcmcia_map_mem_page(link, link->win, offset);
+    smc->base = ioremap(link->resource[2]->start,
+		    resource_size(link->resource[2]));
+    offset = (smc->manfid == MANFID_MOTOROLA) ? link->config_base : 0;
+    i = pcmcia_map_mem_page(link, link->resource[2], offset);
     if ((i == 0) &&
 	(smc->manfid == MANFID_MEGAHERTZ) &&
 	(smc->cardid == PRODID_MEGAHERTZ_EM3288))
@@ -591,14 +570,12 @@
 
 /*====================================================================*/
 
-static int smc_configcheck(struct pcmcia_device *p_dev,
-			   cistpl_cftable_entry_t *cf,
-			   cistpl_cftable_entry_t *dflt,
-			   unsigned int vcc,
-			   void *priv_data)
+static int smc_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-	p_dev->resource[0]->start = cf->io.win[0].base;
-	p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+	p_dev->resource[0]->end = 16;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+
 	return pcmcia_request_io(p_dev);
 }
 
@@ -607,7 +584,8 @@
     struct net_device *dev = link->priv;
     int i;
 
-    link->resource[0]->end = 16;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
     i = pcmcia_loop_config(link, smc_configcheck, NULL);
     if (!i)
 	    dev->base_addr = link->resource[0]->start;
@@ -640,15 +618,14 @@
     static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
     int i, j;
 
-    link->conf.Attributes |= CONF_ENABLE_SPKR;
-    link->conf.Status = CCSR_AUDIO_ENA;
+    link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ;
     link->resource[0]->end = 64;
     link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[1]->end = 8;
 
     /* Enable Hard Decode, LAN, Modem */
-    link->conf.ConfigIndex = 0x23;
     link->io_lines = 16;
+    link->config_index = 0x23;
 
     for (i = j = 0; j < 4; j++) {
 	link->resource[1]->start = com[j];
@@ -658,7 +635,7 @@
     }
     if (i != 0) {
 	/* Fallback: turn off hard decode */
-	link->conf.ConfigIndex = 0x03;
+	link->config_index = 0x03;
 	link->resource[1]->end = 0;
 	i = pcmcia_request_io(link);
     }
@@ -813,31 +790,20 @@
 	((s >> 8) != (s & 0xff))) {
 	SMC_SELECT_BANK(3);
 	s = inw(ioaddr + REVISION);
-	return (s & 0xff);
+	return s & 0xff;
     }
 
     if (width) {
-	    modconf_t mod = {
-		    .Attributes = CONF_IO_CHANGE_WIDTH,
-	    };
-	    printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
+	    pr_info("using 8-bit IO window\n");
 
 	    smc91c92_suspend(link);
-	    pcmcia_modify_configuration(link, &mod);
+	    pcmcia_fixup_iowidth(link);
 	    smc91c92_resume(link);
 	    return check_sig(link);
     }
     return -ENODEV;
 }
 
-/*======================================================================
-
-    smc91c92_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-
-======================================================================*/
-
 static int smc91c92_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
@@ -869,7 +835,7 @@
     i = pcmcia_request_irq(link, smc_interrupt);
     if (i)
 	    goto config_failed;
-    i = pcmcia_request_configuration(link, &link->conf);
+    i = pcmcia_enable_device(link);
     if (i)
 	    goto config_failed;
 
@@ -881,7 +847,7 @@
     if ((if_port >= 0) && (if_port <= 2))
 	dev->if_port = if_port;
     else
-	printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");
+	dev_notice(&link->dev, "invalid if_port requested\n");
 
     switch (smc->manfid) {
     case MANFID_OSITECH:
@@ -899,7 +865,7 @@
     }
 
     if (i != 0) {
-	printk(KERN_NOTICE "smc91c92_cs: Unable to find hardware address.\n");
+	dev_notice(&link->dev, "Unable to find hardware address.\n");
 	goto config_failed;
     }
 
@@ -952,30 +918,28 @@
     SET_NETDEV_DEV(dev, &link->dev);
 
     if (register_netdev(dev) != 0) {
-	printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
+	dev_err(&link->dev, "register_netdev() failed\n");
 	goto config_undo;
     }
 
-    printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
-	   "hw_addr %pM\n",
-	   dev->name, name, (rev & 0x0f), dev->base_addr, dev->irq,
-	   dev->dev_addr);
+    netdev_info(dev, "smc91c%s rev %d: io %#3lx, irq %d, hw_addr %pM\n",
+		name, (rev & 0x0f), dev->base_addr, dev->irq, dev->dev_addr);
 
     if (rev > 0) {
 	if (mir & 0x3ff)
-	    printk(KERN_INFO "  %lu byte", mir);
+	    netdev_info(dev, "  %lu byte", mir);
 	else
-	    printk(KERN_INFO "  %lu kb", mir>>10);
-	printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ?
-	       "MII" : if_names[dev->if_port]);
+	    netdev_info(dev, "  %lu kb", mir>>10);
+	pr_cont(" buffer, %s xcvr\n",
+		(smc->cfg & CFG_MII_SELECT) ? "MII" : if_names[dev->if_port]);
     }
 
     if (smc->cfg & CFG_MII_SELECT) {
 	if (smc->mii_if.phy_id != -1) {
-	    dev_dbg(&link->dev, "  MII transceiver at index %d, status %x.\n",
-		  smc->mii_if.phy_id, j);
+	    netdev_dbg(dev, "  MII transceiver at index %d, status %x\n",
+		       smc->mii_if.phy_id, j);
 	} else {
-    	    printk(KERN_NOTICE "  No MII transceivers found!\n");
+	    netdev_notice(dev, "  No MII transceivers found!\n");
 	}
     }
     return 0;
@@ -988,18 +952,10 @@
     return -ENODEV;
 } /* smc91c92_config */
 
-/*======================================================================
-
-    After a card is removed, smc91c92_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void smc91c92_release(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "smc91c92_release\n");
-	if (link->win) {
+	if (link->resource[2]->end) {
 		struct net_device *dev = link->priv;
 		struct smc_private *smc = netdev_priv(dev);
 		iounmap(smc->base);
@@ -1081,10 +1037,10 @@
     save = inw(ioaddr + BANK_SELECT);
     for (w = 0; w < 4; w++) {
 	SMC_SELECT_BANK(w);
-	printk(KERN_DEBUG "bank %d: ", w);
+	netdev_printk(KERN_DEBUG, dev, "bank %d: ", w);
 	for (i = 0; i < 14; i += 2)
-	    printk(" %04x", inw(ioaddr + i));
-	printk("\n");
+	    pr_cont(" %04x", inw(ioaddr + i));
+	pr_cont("\n");
     }
     outw(save, ioaddr + BANK_SELECT);
 }
@@ -1106,7 +1062,7 @@
 	return -ENODEV;
     /* Physical device present signature. */
     if (check_sig(link) < 0) {
-	printk("smc91c92_cs: Yikes!  Bad chip signature!\n");
+	netdev_info(dev, "Yikes!  Bad chip signature!\n");
 	return -ENODEV;
     }
     link->open++;
@@ -1117,7 +1073,7 @@
 
     smc_reset(dev);
     init_timer(&smc->media);
-    smc->media.function = &media_check;
+    smc->media.function = media_check;
     smc->media.data = (u_long) dev;
     smc->media.expires = jiffies + HZ;
     add_timer(&smc->media);
@@ -1172,7 +1128,7 @@
     u_char packet_no;
 
     if (!skb) {
-	printk(KERN_ERR "%s: In XMIT with no packet to send.\n", dev->name);
+	netdev_err(dev, "In XMIT with no packet to send\n");
 	return;
     }
 
@@ -1180,8 +1136,8 @@
     packet_no = inw(ioaddr + PNR_ARR) >> 8;
     if (packet_no & 0x80) {
 	/* If not, there is a hardware problem!  Likely an ejected card. */
-	printk(KERN_WARNING "%s: 91c92 hardware Tx buffer allocation"
-	       " failed, status %#2.2x.\n", dev->name, packet_no);
+	netdev_warn(dev, "hardware Tx buffer allocation failed, status %#2.2x\n",
+		    packet_no);
 	dev_kfree_skb_irq(skb);
 	smc->saved_skb = NULL;
 	netif_start_queue(dev);
@@ -1200,8 +1156,7 @@
 	u_char *buf = skb->data;
 	u_int length = skb->len; /* The chip will pad to ethernet min. */
 
-	pr_debug("%s: Trying to xmit packet of length %d.\n",
-	      dev->name, length);
+	netdev_dbg(dev, "Trying to xmit packet of length %d\n", length);
 	
 	/* send the packet length: +6 for status word, length, and ctl */
 	outw(0, ioaddr + DATA_1);
@@ -1233,9 +1188,8 @@
     struct smc_private *smc = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
 
-    printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, "
-	   "Tx_status %2.2x status %4.4x.\n",
-	   dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2));
+    netdev_notice(dev, "transmit timed out, Tx_status %2.2x status %4.4x.\n",
+		  inw(ioaddr)&0xff, inw(ioaddr + 2));
     dev->stats.tx_errors++;
     smc_reset(dev);
     dev->trans_start = jiffies; /* prevent tx timeout */
@@ -1254,14 +1208,14 @@
 
     netif_stop_queue(dev);
 
-    pr_debug("%s: smc_start_xmit(length = %d) called,"
-	  " status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2));
+    netdev_dbg(dev, "smc_start_xmit(length = %d) called, status %04x\n",
+	       skb->len, inw(ioaddr + 2));
 
     if (smc->saved_skb) {
 	/* THIS SHOULD NEVER HAPPEN. */
 	dev->stats.tx_aborted_errors++;
-	printk(KERN_DEBUG "%s: Internal error -- sent packet while busy.\n",
-	       dev->name);
+	netdev_printk(KERN_DEBUG, dev,
+		      "Internal error -- sent packet while busy\n");
 	return NETDEV_TX_BUSY;
     }
     smc->saved_skb = skb;
@@ -1269,7 +1223,7 @@
     num_pages = skb->len >> 8;
 
     if (num_pages > 7) {
-	printk(KERN_ERR "%s: Far too big packet error.\n", dev->name);
+	netdev_err(dev, "Far too big packet error: %d pages\n", num_pages);
 	dev_kfree_skb (skb);
 	smc->saved_skb = NULL;
 	dev->stats.tx_dropped++;
@@ -1339,8 +1293,7 @@
     }
 
     if (tx_status & TS_SUCCESS) {
-	printk(KERN_NOTICE "%s: Successful packet caused error "
-	       "interrupt?\n", dev->name);
+	netdev_notice(dev, "Successful packet caused error interrupt?\n");
     }
     /* re-enable transmit */
     SMC_SELECT_BANK(0);
@@ -1530,8 +1483,7 @@
     /* Assertion: we are in Window 2. */
 
     if (inw(ioaddr + FIFO_PORTS) & FP_RXEMPTY) {
-	printk(KERN_ERR "%s: smc_rx() with nothing on Rx FIFO.\n",
-	       dev->name);
+	netdev_err(dev, "smc_rx() with nothing on Rx FIFO\n");
 	return;
     }
 
@@ -1646,8 +1598,7 @@
 	else if (map->port > 2)
 	    return -EINVAL;
 	dev->if_port = map->port;
-	printk(KERN_INFO "%s: switched to %s port\n",
-	       dev->name, if_names[dev->if_port]);
+	netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
 	smc_reset(dev);
     }
     return 0;
@@ -1798,7 +1749,7 @@
        this, we can limp along even if the interrupt is blocked */
     if (smc->watchdog++ && ((i>>8) & i)) {
 	if (!smc->fast_poll)
-	    printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
+	    netdev_info(dev, "interrupt(s) dropped!\n");
 	local_irq_save(flags);
 	smc_interrupt(dev->irq, dev);
 	local_irq_restore(flags);
@@ -1822,7 +1773,7 @@
 	SMC_SELECT_BANK(3);
 	link = mdio_read(dev, smc->mii_if.phy_id, 1);
 	if (!link || (link == 0xffff)) {
-  	    printk(KERN_INFO "%s: MII is missing!\n", dev->name);
+	    netdev_info(dev, "MII is missing!\n");
 	    smc->mii_if.phy_id = -1;
 	    goto reschedule;
 	}
@@ -1830,15 +1781,13 @@
 	link &= 0x0004;
 	if (link != smc->link_status) {
 	    u_short p = mdio_read(dev, smc->mii_if.phy_id, 5);
-	    printk(KERN_INFO "%s: %s link beat\n", dev->name,
-		(link) ? "found" : "lost");
+	    netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
 	    smc->duplex = (((p & 0x0100) || ((p & 0x1c0) == 0x40))
 			   ? TCR_FDUPLX : 0);
 	    if (link) {
-	        printk(KERN_INFO "%s: autonegotiation complete: "
-		       "%sbaseT-%cD selected\n", dev->name,
-		       ((p & 0x0180) ? "100" : "10"),
-		       (smc->duplex ? 'F' : 'H'));
+		netdev_info(dev, "autonegotiation complete: "
+			    "%dbaseT-%cD selected\n",
+			    (p & 0x0180) ? 100 : 10, smc->duplex ? 'F' : 'H');
 	    }
 	    SMC_SELECT_BANK(0);
 	    outw(inw(ioaddr + TCR) | smc->duplex, ioaddr + TCR);
@@ -1857,25 +1806,23 @@
     if (media != smc->media_status) {
 	if ((media & smc->media_status & 1) &&
 	    ((smc->media_status ^ media) & EPH_LINK_OK))
-	    printk(KERN_INFO "%s: %s link beat\n", dev->name,
-		   (smc->media_status & EPH_LINK_OK ? "lost" : "found"));
+	    netdev_info(dev, "%s link beat\n",
+			smc->media_status & EPH_LINK_OK ? "lost" : "found");
 	else if ((media & smc->media_status & 2) &&
 		 ((smc->media_status ^ media) & EPH_16COL))
-	    printk(KERN_INFO "%s: coax cable %s\n", dev->name,
-		   (media & EPH_16COL ? "problem" : "ok"));
+	    netdev_info(dev, "coax cable %s\n",
+			media & EPH_16COL ? "problem" : "ok");
 	if (dev->if_port == 0) {
 	    if (media & 1) {
 		if (media & EPH_LINK_OK)
-		    printk(KERN_INFO "%s: flipped to 10baseT\n",
-			   dev->name);
+		    netdev_info(dev, "flipped to 10baseT\n");
 		else
 		    smc_set_xcvr(dev, 2);
 	    } else {
 		if (media & EPH_16COL)
 		    smc_set_xcvr(dev, 1);
 		else
-		    printk(KERN_INFO "%s: flipped to 10base2\n",
-			   dev->name);
+		    netdev_info(dev, "flipped to 10base2\n");
 	    }
 	}
 	smc->media_status = media;
@@ -2101,9 +2048,7 @@
 
 static struct pcmcia_driver smc91c92_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "smc91c92_cs",
-	},
+	.name		= "smc91c92_cs",
 	.probe		= smc91c92_probe,
 	.remove		= smc91c92_detach,
 	.id_table       = smc91c92_ids,
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index f5819526..a46b7fd 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -63,6 +63,8 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -82,7 +84,6 @@
 #include <linux/bitops.h>
 #include <linux/mii.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -210,13 +211,6 @@
 
 static const char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" };
 
-
-#define KDBG_XIRC KERN_DEBUG   "xirc2ps_cs: "
-#define KERR_XIRC KERN_ERR     "xirc2ps_cs: "
-#define KWRN_XIRC KERN_WARNING "xirc2ps_cs: "
-#define KNOT_XIRC KERN_NOTICE  "xirc2ps_cs: "
-#define KINF_XIRC KERN_INFO    "xirc2ps_cs: "
-
 /* card types */
 #define XIR_UNKNOWN  0	/* unknown: not supported */
 #define XIR_CE	     1	/* (prodid 1) different hardware: not supported */
@@ -267,33 +261,11 @@
 static void mii_wr(unsigned int ioaddr, u_char phyaddr, u_char phyreg,
 		   unsigned data, int len);
 
-/*
- * The event() function is this driver's Card Services event handler.
- * It will be called by Card Services when an appropriate card status
- * event is received.  The config() and release() entry points are
- * used to configure or release a socket, in response to card insertion
- * and ejection events.  They are invoked from the event handler.
- */
-
 static int has_ce2_string(struct pcmcia_device * link);
 static int xirc2ps_config(struct pcmcia_device * link);
 static void xirc2ps_release(struct pcmcia_device * link);
-
-/****************
- * The attach() and detach() entry points are used to create and destroy
- * "instances" of the driver, where each instance represents everything
- * needed to manage one actual PCMCIA card.
- */
-
 static void xirc2ps_detach(struct pcmcia_device *p_dev);
 
-/****************
- * You'll also need to prototype all the functions that will actually
- * be used to talk to your device.  See 'pcmem_cs' for a good example
- * of a fully self-sufficient driver; the other drivers rely more or
- * less on other parts of the kernel.
- */
-
 static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id);
 
 typedef struct local_info_t {
@@ -350,26 +322,26 @@
     if (pc_debug > 1) {
 	int i, page;
 
-	printk(KDBG_XIRC "Register  common: ");
+	printk(KERN_DEBUG pr_fmt("Register  common: "));
 	for (i = 0; i < 8; i++)
-	    printk(" %2.2x", GetByte(i));
-	printk("\n");
+	    pr_cont(" %2.2x", GetByte(i));
+	pr_cont("\n");
 	for (page = 0; page <= 8; page++) {
-	    printk(KDBG_XIRC "Register page %2x: ", page);
+	    printk(KERN_DEBUG pr_fmt("Register page %2x: "), page);
 	    SelectPage(page);
 	    for (i = 8; i < 16; i++)
-		printk(" %2.2x", GetByte(i));
-	    printk("\n");
+		pr_cont(" %2.2x", GetByte(i));
+	    pr_cont("\n");
 	}
 	for (page=0x40 ; page <= 0x5f; page++) {
 		if (page == 0x43 || (page >= 0x46 && page <= 0x4f) ||
 		    (page >= 0x51 && page <=0x5e))
 			continue;
-	    printk(KDBG_XIRC "Register page %2x: ", page);
+	    printk(KERN_DEBUG pr_fmt("Register page %2x: "), page);
 	    SelectPage(page);
 	    for (i = 8; i < 16; i++)
-		printk(" %2.2x", GetByte(i));
-	    printk("\n");
+		pr_cont(" %2.2x", GetByte(i));
+	    pr_cont("\n");
 	}
     }
 }
@@ -501,16 +473,6 @@
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
-/****************
- * xirc2ps_attach() creates an "instance" of the driver, allocating
- * local data structures for one device.  The device is registered
- * with Card Services.
- *
- * The dev_link 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
 xirc2ps_probe(struct pcmcia_device *link)
 {
@@ -529,9 +491,7 @@
     link->priv = dev;
 
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
+    link->config_index = 1;
 
     /* Fill in card specific entries */
     dev->netdev_ops = &netdev_ops;
@@ -542,13 +502,6 @@
     return xirc2ps_config(link);
 } /* xirc2ps_attach */
 
-/****************
- *  This deletes a driver "instance".  The device is de-registered
- *  with Card Services.  If it has been released, all local data
- *  structures are freed.  Otherwise, the structures will be freed
- *  when the device is released.
- */
-
 static void
 xirc2ps_detach(struct pcmcia_device *link)
 {
@@ -608,11 +561,11 @@
     local->modem = 0;
     local->card_type = XIR_UNKNOWN;
     if (!(prodid & 0x40)) {
-	printk(KNOT_XIRC "Ooops: Not a creditcard\n");
+	pr_notice("Oops: Not a creditcard\n");
 	return 0;
     }
     if (!(mediaid & 0x01)) {
-	printk(KNOT_XIRC "Not an Ethernet card\n");
+	pr_notice("Not an Ethernet card\n");
 	return 0;
     }
     if (mediaid & 0x10) {
@@ -643,12 +596,11 @@
 	}
     }
     if (local->card_type == XIR_CE || local->card_type == XIR_CEM) {
-	printk(KNOT_XIRC "Sorry, this is an old CE card\n");
+	pr_notice("Sorry, this is an old CE card\n");
 	return 0;
     }
     if (local->card_type == XIR_UNKNOWN)
-	printk(KNOT_XIRC "unknown card (mediaid=%02x prodid=%02x)\n",
-	       mediaid, prodid);
+	pr_notice("unknown card (mediaid=%02x prodid=%02x)\n", mediaid, prodid);
 
     return 1;
 }
@@ -667,44 +619,53 @@
 }
 
 static int
-xirc2ps_config_modem(struct pcmcia_device *p_dev,
-		     cistpl_cftable_entry_t *cf,
-		     cistpl_cftable_entry_t *dflt,
-		     unsigned int vcc,
-		     void *priv_data)
+xirc2ps_config_modem(struct pcmcia_device *p_dev, void *priv_data)
 {
 	unsigned int ioaddr;
 
-	if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8) {
-		for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
-			p_dev->resource[1]->start = cf->io.win[0].base;
-			p_dev->resource[0]->start = ioaddr;
-			if (!pcmcia_request_io(p_dev))
-				return 0;
-		}
+	if ((p_dev->resource[0]->start & 0xf) == 8)
+		return -ENODEV;
+
+	p_dev->resource[0]->end = 16;
+	p_dev->resource[1]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->io_lines = 10;
+
+	p_dev->resource[1]->start = p_dev->resource[0]->start;
+	for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
+		p_dev->resource[0]->start = ioaddr;
+		if (!pcmcia_request_io(p_dev))
+			return 0;
 	}
 	return -ENODEV;
 }
 
 static int
-xirc2ps_config_check(struct pcmcia_device *p_dev,
-		     cistpl_cftable_entry_t *cf,
-		     cistpl_cftable_entry_t *dflt,
-		     unsigned int vcc,
-		     void *priv_data)
+xirc2ps_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int *pass = priv_data;
+	resource_size_t tmp = p_dev->resource[1]->start;
 
-	if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
-		p_dev->resource[1]->start = cf->io.win[0].base;
-		p_dev->resource[0]->start = p_dev->resource[1]->start
-			+ (*pass ? (cf->index & 0x20 ? -24:8)
-			   : (cf->index & 0x20 ?   8:-24));
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -ENODEV;
+	tmp += (*pass ? (p_dev->config_index & 0x20 ? -24 : 8)
+		: (p_dev->config_index & 0x20 ?   8 : -24));
 
+	if ((p_dev->resource[0]->start & 0xf) == 8)
+		return -ENODEV;
+
+	p_dev->resource[0]->end = 18;
+	p_dev->resource[1]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->io_lines = 10;
+
+	p_dev->resource[1]->start = p_dev->resource[0]->start;
+	p_dev->resource[0]->start = tmp;
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -727,11 +688,6 @@
 };
 
 
-/****************
- * xirc2ps_config() is scheduled to run after a CARD_INSERTION event
- * is received, to configure the PCMCIA socket, and to make the
- * ethernet device available to the system.
- */
 static int
 xirc2ps_config(struct pcmcia_device * link)
 {
@@ -748,7 +704,7 @@
 
     /* Is this a valid	card */
     if (link->has_manf_id == 0) {
-	printk(KNOT_XIRC "manfid not found in CIS\n");
+	pr_notice("manfid not found in CIS\n");
 	goto failure;
     }
 
@@ -770,14 +726,14 @@
 	local->manf_str = "Toshiba";
 	break;
       default:
-	printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n",
-	       (unsigned)link->manf_id);
+	pr_notice("Unknown Card Manufacturer ID: 0x%04x\n",
+		  (unsigned)link->manf_id);
 	goto failure;
     }
     dev_dbg(&link->dev, "found %s card\n", local->manf_str);
 
     if (!set_card_type(link)) {
-	printk(KNOT_XIRC "this card is not supported\n");
+	pr_notice("this card is not supported\n");
 	goto failure;
     }
 
@@ -803,44 +759,38 @@
 	err = pcmcia_loop_tuple(link, CISTPL_FUNCE, pcmcia_get_mac_ce, dev);
 
     if (err) {
-	printk(KNOT_XIRC "node-id not found in CIS\n");
+	pr_notice("node-id not found in CIS\n");
 	goto failure;
     }
 
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
-    link->io_lines = 10;
     if (local->modem) {
 	int pass;
+	link->config_flags |= CONF_AUTO_SET_IO;
 
-	if (do_sound) {
-	    link->conf.Attributes |= CONF_ENABLE_SPKR;
-	    link->conf.Status |= CCSR_AUDIO_ENA;
-	}
-	link->resource[1]->end = 8;
-	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 	if (local->dingo) {
 	    /* Take the Modem IO port from the CIS and scan for a free
 	     * Ethernet port */
-	    link->resource[0]->end = 16; /* no Mako stuff anymore */
 	    if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL))
 		    goto port_found;
 	} else {
-	    link->resource[0]->end = 18;
 	    /* We do 2 passes here: The first one uses the regular mapping and
 	     * the second tries again, thereby considering that the 32 ports are
 	     * mirrored every 32 bytes. Actually we use a mirrored port for
 	     * the Mako if (on the first pass) the COR bit 5 is set.
 	     */
 	    for (pass=0; pass < 2; pass++)
-		    if (!pcmcia_loop_config(link, xirc2ps_config_check, &pass))
+		    if (!pcmcia_loop_config(link, xirc2ps_config_check,
+						    &pass))
 			    goto port_found;
 	    /* if special option:
 	     * try to configure as Ethernet only.
 	     * .... */
 	}
-	printk(KNOT_XIRC "no ports available\n");
+	pr_notice("no ports available\n");
     } else {
+	link->io_lines = 10;
 	link->resource[0]->end = 16;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 	for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
 	    link->resource[0]->start = ioaddr;
 	    if (!(err = pcmcia_request_io(link)))
@@ -861,16 +811,14 @@
     if ((err=pcmcia_request_irq(link, xirc2ps_interrupt)))
 	goto config_error;
 
-    /****************
-     * This actually configures the PCMCIA socket -- setting up
-     * the I/O windows and the interrupt mapping.
-     */
-    if ((err=pcmcia_request_configuration(link, &link->conf)))
+    link->config_flags |= CONF_ENABLE_IRQ;
+    if (do_sound)
+	    link->config_flags |= CONF_ENABLE_SPKR;
+
+    if ((err = pcmcia_enable_device(link)))
 	goto config_error;
 
     if (local->dingo) {
-	win_req_t req;
-
 	/* Reset the modem's BAR to the correct value
 	 * This is necessary because in the RequestConfiguration call,
 	 * the base address of the ethernet port (BasePort1) is written
@@ -890,14 +838,14 @@
 	 * is at 0x0800. So we allocate a window into the attribute
 	 * memory and write direct to the CIS registers
 	 */
-	req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-	req.Base = req.Size = 0;
-	req.AccessSpeed = 0;
-	if ((err = pcmcia_request_window(link, &req, &link->win)))
+	link->resource[2]->flags = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM |
+					WIN_ENABLE;
+	link->resource[2]->start = link->resource[2]->end = 0;
+	if ((err = pcmcia_request_window(link, link->resource[2], 0)))
 	    goto config_error;
 
-	local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;
-	if ((err = pcmcia_map_mem_page(link, link->win, 0)))
+	local->dingo_ccr = ioremap(link->resource[2]->start, 0x1000) + 0x0800;
+	if ((err = pcmcia_map_mem_page(link, link->resource[2], 0)))
 	    goto config_error;
 
 	/* Setup the CCRs; there are no infos in the CIS about the Ethernet
@@ -911,24 +859,24 @@
       #if 0
 	{
 	    u_char tmp;
-	    printk(KERN_INFO "ECOR:");
+	    pr_info("ECOR:");
 	    for (i=0; i < 7; i++) {
 		tmp = readb(local->dingo_ccr + i*2);
-		printk(" %02x", tmp);
+		pr_cont(" %02x", tmp);
 	    }
-	    printk("\n");
-	    printk(KERN_INFO "DCOR:");
+	    pr_cont("\n");
+	    pr_info("DCOR:");
 	    for (i=0; i < 4; i++) {
 		tmp = readb(local->dingo_ccr + 0x20 + i*2);
-		printk(" %02x", tmp);
+		pr_cont(" %02x", tmp);
 	    }
-	    printk("\n");
-	    printk(KERN_INFO "SCOR:");
+	    pr_cont("\n");
+	    pr_info("SCOR:");
 	    for (i=0; i < 10; i++) {
 		tmp = readb(local->dingo_ccr + 0x40 + i*2);
-		printk(" %02x", tmp);
+		pr_cont(" %02x", tmp);
 	    }
-	    printk("\n");
+	    pr_cont("\n");
 	}
       #endif
 
@@ -947,7 +895,7 @@
 	       (local->mohawk && if_port==4))
 	dev->if_port = if_port;
     else
-	printk(KNOT_XIRC "invalid if_port requested\n");
+	pr_notice("invalid if_port requested\n");
 
     /* we can now register the device with the net subsystem */
     dev->irq = link->irq;
@@ -959,14 +907,14 @@
     SET_NETDEV_DEV(dev, &link->dev);
 
     if ((err=register_netdev(dev))) {
-	printk(KNOT_XIRC "register_netdev() failed\n");
+	pr_notice("register_netdev() failed\n");
 	goto config_error;
     }
 
     /* give some infos about the hardware */
-    printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr %pM\n",
-	   dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq,
-	   dev->dev_addr);
+    netdev_info(dev, "%s: port %#3lx, irq %d, hwaddr %pM\n",
+		local->manf_str, (u_long)dev->base_addr, (int)dev->irq,
+		dev->dev_addr);
 
     return 0;
 
@@ -978,17 +926,12 @@
     return -ENODEV;
 } /* xirc2ps_config */
 
-/****************
- * After a card is removed, xirc2ps_release() will unregister the net
- * device, and release the PCMCIA configuration.  If the device is
- * still open, this will be postponed until it is closed.
- */
 static void
 xirc2ps_release(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "release\n");
 
-	if (link->win) {
+	if (link->resource[2]->end) {
 		struct net_device *dev = link->priv;
 		local_info_t *local = netdev_priv(dev);
 		if (local->dingo)
@@ -1098,8 +1041,7 @@
 
 	    skb = dev_alloc_skb(pktlen+3); /* 1 extra so we can use insw */
 	    if (!skb) {
-		printk(KNOT_XIRC "low memory, packet dropped (size=%u)\n",
-		       pktlen);
+		pr_notice("low memory, packet dropped (size=%u)\n", pktlen);
 		dev->stats.rx_dropped++;
 	    } else { /* okay get the packet */
 		skb_reserve(skb, 2);
@@ -1268,7 +1210,7 @@
 {
     local_info_t *lp = netdev_priv(dev);
     dev->stats.tx_errors++;
-    printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
+    netdev_notice(dev, "transmit timed out\n");
     schedule_work(&lp->tx_timeout_task);
 }
 
@@ -1435,8 +1377,7 @@
 	    local->probe_port = 0;
 	    dev->if_port = map->port;
 	}
-	printk(KERN_INFO "%s: switching to %s port\n",
-	       dev->name, if_names[dev->if_port]);
+	netdev_info(dev, "switching to %s port\n", if_names[dev->if_port]);
 	do_reset(dev,1);  /* not the fine way :-) */
     }
     return 0;
@@ -1576,7 +1517,7 @@
     {
 	SelectPage(0);
 	value = GetByte(XIRCREG_ESR);	 /* read the ESR */
-	printk(KERN_DEBUG "%s: ESR is: %#02x\n", dev->name, value);
+	pr_debug("%s: ESR is: %#02x\n", dev->name, value);
     }
   #endif
 
@@ -1626,13 +1567,12 @@
 
     if (full && local->mohawk && init_mii(dev)) {
 	if (dev->if_port == 4 || local->dingo || local->new_mii) {
-	    printk(KERN_INFO "%s: MII selected\n", dev->name);
+	    netdev_info(dev, "MII selected\n");
 	    SelectPage(2);
 	    PutByte(XIRCREG2_MSR, GetByte(XIRCREG2_MSR) | 0x08);
 	    msleep(20);
 	} else {
-	    printk(KERN_INFO "%s: MII detected; using 10mbs\n",
-		   dev->name);
+	    netdev_info(dev, "MII detected; using 10mbs\n");
 	    SelectPage(0x42);
 	    if (dev->if_port == 2) /* enable 10Base2 */
 		PutByte(XIRCREG42_SWC1, 0xC0);
@@ -1677,8 +1617,8 @@
     }
 
     if (full)
-	printk(KERN_INFO "%s: media %s, silicon revision %d\n",
-	       dev->name, if_names[dev->if_port], local->silicon);
+	netdev_info(dev, "media %s, silicon revision %d\n",
+		    if_names[dev->if_port], local->silicon);
     /* We should switch back to page 0 to avoid a bug in revision 0
      * where regs with offset below 8 can't be read after an access
      * to the MAC registers */
@@ -1720,8 +1660,7 @@
     control = mii_rd(ioaddr, 0, 0);
 
     if (control & 0x0400) {
-	printk(KERN_NOTICE "%s can't take PHY out of isolation mode\n",
-	       dev->name);
+	netdev_notice(dev, "can't take PHY out of isolation mode\n");
 	local->probe_port = 0;
 	return 0;
     }
@@ -1739,8 +1678,7 @@
 	}
 
 	if (!(status & 0x0020)) {
-	    printk(KERN_INFO "%s: autonegotiation failed;"
-		   " using 10mbs\n", dev->name);
+	    netdev_info(dev, "autonegotiation failed; using 10mbs\n");
 	    if (!local->new_mii) {
 		control = 0x0000;
 		mii_wr(ioaddr,  0, 0, control, 16);
@@ -1750,8 +1688,7 @@
 	    }
 	} else {
 	    linkpartner = mii_rd(ioaddr, 0, 5);
-	    printk(KERN_INFO "%s: MII link partner: %04x\n",
-		   dev->name, linkpartner);
+	    netdev_info(dev, "MII link partner: %04x\n", linkpartner);
 	    if (linkpartner & 0x0080) {
 		dev->if_port = 4;
 	    } else
@@ -1830,9 +1767,7 @@
 
 static struct pcmcia_driver xirc2ps_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "xirc2ps_cs",
-	},
+	.name		= "xirc2ps_cs",
 	.probe		= xirc2ps_probe,
 	.remove		= xirc2ps_detach,
 	.id_table       = xirc2ps_ids,
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index c200c282..aee3bb0 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -376,7 +376,7 @@
 static int pcnet32_wio_check(unsigned long addr)
 {
 	outw(88, addr + PCNET32_WIO_RAP);
-	return (inw(addr + PCNET32_WIO_RAP) == 88);
+	return inw(addr + PCNET32_WIO_RAP) == 88;
 }
 
 static struct pcnet32_access pcnet32_wio = {
@@ -431,7 +431,7 @@
 static int pcnet32_dwio_check(unsigned long addr)
 {
 	outl(88, addr + PCNET32_DWIO_RAP);
-	return ((inl(addr + PCNET32_DWIO_RAP) & 0xffff) == 88);
+	return (inl(addr + PCNET32_DWIO_RAP) & 0xffff) == 88;
 }
 
 static struct pcnet32_access pcnet32_dwio = {
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index eb799b3..cb3d13e 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -58,7 +58,6 @@
 
 config BCM63XX_PHY
 	tristate "Drivers for Broadcom 63xx SOCs internal PHY"
-	depends on BCM63XX
 	---help---
 	  Currently supports the 6348 and 6358 PHYs.
 
diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c
index c128156..e16f98c 100644
--- a/drivers/net/phy/bcm63xx.c
+++ b/drivers/net/phy/bcm63xx.c
@@ -131,7 +131,7 @@
 module_init(bcm63xx_phy_init);
 module_exit(bcm63xx_phy_exit);
 
-static struct mdio_device_id bcm63xx_tbl[] = {
+static struct mdio_device_id __maybe_unused bcm63xx_tbl[] = {
 	{ 0x00406000, 0xfffffc00 },
 	{ 0x002bdc00, 0xfffffc00 },
 	{ }
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 4accd83..d84c422 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -930,7 +930,7 @@
 module_init(broadcom_init);
 module_exit(broadcom_exit);
 
-static struct mdio_device_id broadcom_tbl[] = {
+static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
 	{ PHY_ID_BCM5411, 0xfffffff0 },
 	{ PHY_ID_BCM5421, 0xfffffff0 },
 	{ PHY_ID_BCM5461, 0xfffffff0 },
diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c
index 1a325d6..d281731 100644
--- a/drivers/net/phy/cicada.c
+++ b/drivers/net/phy/cicada.c
@@ -159,7 +159,7 @@
 module_init(cicada_init);
 module_exit(cicada_exit);
 
-static struct mdio_device_id cicada_tbl[] = {
+static struct mdio_device_id __maybe_unused cicada_tbl[] = {
 	{ 0x000fc410, 0x000ffff0 },
 	{ 0x000fc440, 0x000fffc0 },
 	{ }
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index 29c1761..2f774ac 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -219,7 +219,7 @@
 module_init(davicom_init);
 module_exit(davicom_exit);
 
-static struct mdio_device_id davicom_tbl[] = {
+static struct mdio_device_id __maybe_unused davicom_tbl[] = {
 	{ 0x0181b880, 0x0ffffff0 },
 	{ 0x0181b8a0, 0x0ffffff0 },
 	{ 0x00181b80, 0x0ffffff0 },
diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c
index 13995f5..a8eb19e 100644
--- a/drivers/net/phy/et1011c.c
+++ b/drivers/net/phy/et1011c.c
@@ -111,7 +111,7 @@
 module_init(et1011c_init);
 module_exit(et1011c_exit);
 
-static struct mdio_device_id et1011c_tbl[] = {
+static struct mdio_device_id __maybe_unused et1011c_tbl[] = {
 	{ 0x0282f014, 0xfffffff0 },
 	{ }
 };
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index 3f2583f..c1d2d25 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -134,7 +134,7 @@
 module_init(ip175c_init);
 module_exit(ip175c_exit);
 
-static struct mdio_device_id icplus_tbl[] = {
+static struct mdio_device_id __maybe_unused icplus_tbl[] = {
 	{ 0x02430d80, 0x0ffffff0 },
 	{ }
 };
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 29c39ff..6f6e8b6 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -223,7 +223,7 @@
 module_init(lxt_init);
 module_exit(lxt_exit);
 
-static struct mdio_device_id lxt_tbl[] = {
+static struct mdio_device_id __maybe_unused lxt_tbl[] = {
 	{ 0x78100000, 0xfffffff0 },
 	{ 0x001378e0, 0xfffffff0 },
 	{ 0x00137a10, 0xfffffff0 },
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 0101f2b..e2afdce 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -196,20 +196,27 @@
 			MII_88E1121_PHY_MSCR_PAGE);
 	if (err < 0)
 		return err;
-	mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
-		MII_88E1121_PHY_MSCR_DELAY_MASK;
 
-	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
-		mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
-			 MII_88E1121_PHY_MSCR_TX_DELAY);
-	else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
-		mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
-	else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
-		mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
+	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
 
-	err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
-	if (err < 0)
-		return err;
+		mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
+			MII_88E1121_PHY_MSCR_DELAY_MASK;
+
+		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+			mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
+				 MII_88E1121_PHY_MSCR_TX_DELAY);
+		else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+			mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
+		else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+			mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
+
+		err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
+		if (err < 0)
+			return err;
+	}
 
 	phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
 
@@ -721,7 +728,7 @@
 module_init(marvell_init);
 module_exit(marvell_exit);
 
-static struct mdio_device_id marvell_tbl[] = {
+static struct mdio_device_id __maybe_unused marvell_tbl[] = {
 	{ 0x01410c60, 0xfffffff0 },
 	{ 0x01410c90, 0xfffffff0 },
 	{ 0x01410cc0, 0xfffffff0 },
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 8bb7db6..0fd1678 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -231,7 +231,7 @@
 MODULE_AUTHOR("David J. Choi");
 MODULE_LICENSE("GPL");
 
-static struct mdio_device_id micrel_tbl[] = {
+static struct mdio_device_id __maybe_unused micrel_tbl[] = {
 	{ PHY_ID_KSZ9021, 0x000fff10 },
 	{ PHY_ID_KS8001, 0x00fffff0 },
 	{ PHY_ID_KS8737, 0x00fffff0 },
diff --git a/drivers/net/phy/national.c b/drivers/net/phy/national.c
index a73ba0b..0620ba9 100644
--- a/drivers/net/phy/national.c
+++ b/drivers/net/phy/national.c
@@ -151,7 +151,7 @@
 module_init(ns_init);
 module_exit(ns_exit);
 
-static struct mdio_device_id ns_tbl[] = {
+static struct mdio_device_id __maybe_unused ns_tbl[] = {
 	{ DP83865_PHY_ID, 0xfffffff0 },
 	{ }
 };
diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c
index 6736b23..fe0d0a1 100644
--- a/drivers/net/phy/qsemi.c
+++ b/drivers/net/phy/qsemi.c
@@ -138,7 +138,7 @@
 module_init(qs6612_init);
 module_exit(qs6612_exit);
 
-static struct mdio_device_id qs6612_tbl[] = {
+static struct mdio_device_id __maybe_unused qs6612_tbl[] = {
 	{ 0x00181440, 0xfffffff0 },
 	{ }
 };
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index f567c0e..a4eae75 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -79,7 +79,7 @@
 module_init(realtek_init);
 module_exit(realtek_exit);
 
-static struct mdio_device_id realtek_tbl[] = {
+static struct mdio_device_id __maybe_unused realtek_tbl[] = {
 	{ 0x001cc912, 0x001fffff },
 	{ }
 };
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 78fa988..342505c 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -254,7 +254,7 @@
 module_init(smsc_init);
 module_exit(smsc_exit);
 
-static struct mdio_device_id smsc_tbl[] = {
+static struct mdio_device_id __maybe_unused smsc_tbl[] = {
 	{ 0x0007c0a0, 0xfffffff0 },
 	{ 0x0007c0b0, 0xfffffff0 },
 	{ 0x0007c0c0, 0xfffffff0 },
diff --git a/drivers/net/phy/ste10Xp.c b/drivers/net/phy/ste10Xp.c
index 7229009..187a2fa 100644
--- a/drivers/net/phy/ste10Xp.c
+++ b/drivers/net/phy/ste10Xp.c
@@ -132,7 +132,7 @@
 module_init(ste10Xp_init);
 module_exit(ste10Xp_exit);
 
-static struct mdio_device_id ste10Xp_tbl[] = {
+static struct mdio_device_id __maybe_unused ste10Xp_tbl[] = {
 	{ STE101P_PHY_ID, 0xfffffff0 },
 	{ STE100P_PHY_ID, 0xffffffff },
 	{ }
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 45cce50..5d8f6e1 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -192,7 +192,7 @@
 module_init(vsc82xx_init);
 module_exit(vsc82xx_exit);
 
-static struct mdio_device_id vitesse_tbl[] = {
+static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
 	{ PHY_ID_VSC8244, 0x000fffc0 },
 	{ PHY_ID_VSC8221, 0x000ffff0 },
 	{ }
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index ec0349e..ca4df7f 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -995,8 +995,10 @@
 static void
 plip_rewrite_address(const struct net_device *dev, struct ethhdr *eth)
 {
-	const struct in_device *in_dev = dev->ip_ptr;
+	const struct in_device *in_dev;
 
+	rcu_read_lock();
+	in_dev = __in_dev_get_rcu(dev);
 	if (in_dev) {
 		/* Any address will do - we take the first */
 		const struct in_ifaddr *ifa = in_dev->ifa_list;
@@ -1006,6 +1008,7 @@
 			memcpy(eth->h_dest+2, &ifa->ifa_address, 4);
 		}
 	}
+	rcu_read_unlock();
 }
 
 static int
@@ -1088,7 +1091,8 @@
 	   when the device address isn't identical to the address of a
 	   received frame, the kernel incorrectly drops it).             */
 
-	if ((in_dev=dev->ip_ptr) != NULL) {
+	in_dev=__in_dev_get_rtnl(dev);
+	if (in_dev) {
 		/* Any address will do - we take the first. We already
 		   have the first two bytes filled with 0xfc, from
 		   plip_init_dev(). */
@@ -1279,7 +1283,6 @@
 		if (!nl->pardev) {
 			printk(KERN_ERR "%s: parport_register failed\n", name);
 			goto err_free_dev;
-			return;
 		}
 
 		plip_init_netdev(dev);
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index af50a53..78d70a6 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -184,7 +184,7 @@
 	tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap);
 
 	atomic_set(&ap->refcnt, 1);
-	init_MUTEX_LOCKED(&ap->dead_sem);
+	sema_init(&ap->dead_sem, 0);
 
 	ap->chan.private = ap;
 	ap->chan.ops = &async_ops;
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 736b917..09cf56d 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -856,7 +856,8 @@
 	.poll		= ppp_poll,
 	.unlocked_ioctl	= ppp_ioctl,
 	.open		= ppp_open,
-	.release	= ppp_release
+	.release	= ppp_release,
+	.llseek		= noop_llseek,
 };
 
 static __net_init int ppp_init_net(struct net *net)
@@ -1547,9 +1548,11 @@
  * Receive-side routines.
  */
 
-/* misuse a few fields of the skb for MP reconstruction */
-#define sequence	priority
-#define BEbits		cb[0]
+struct ppp_mp_skb_parm {
+	u32		sequence;
+	u8		BEbits;
+};
+#define PPP_MP_CB(skb)	((struct ppp_mp_skb_parm *)((skb)->cb))
 
 static inline void
 ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
@@ -1878,13 +1881,13 @@
 		seq = (skb->data[3] << 16) | (skb->data[4] << 8)| skb->data[5];
 		mask = 0xffffff;
 	}
-	skb->BEbits = skb->data[2];
+	PPP_MP_CB(skb)->BEbits = skb->data[2];
 	skb_pull(skb, mphdrlen);	/* pull off PPP and MP headers */
 
 	/*
 	 * Do protocol ID decompression on the first fragment of each packet.
 	 */
-	if ((skb->BEbits & B) && (skb->data[0] & 1))
+	if ((PPP_MP_CB(skb)->BEbits & B) && (skb->data[0] & 1))
 		*skb_push(skb, 1) = 0;
 
 	/*
@@ -1896,7 +1899,7 @@
 		seq += mask + 1;
 	else if ((int)(seq - ppp->minseq) > (int)(mask >> 1))
 		seq -= mask + 1;	/* should never happen */
-	skb->sequence = seq;
+	PPP_MP_CB(skb)->sequence = seq;
 	pch->lastseq = seq;
 
 	/*
@@ -1932,8 +1935,8 @@
 	   before the start of the queue. */
 	if (skb_queue_len(&ppp->mrq) >= PPP_MP_MAX_QLEN) {
 		struct sk_buff *mskb = skb_peek(&ppp->mrq);
-		if (seq_before(ppp->minseq, mskb->sequence))
-			ppp->minseq = mskb->sequence;
+		if (seq_before(ppp->minseq, PPP_MP_CB(mskb)->sequence))
+			ppp->minseq = PPP_MP_CB(mskb)->sequence;
 	}
 
 	/* Pull completed packets off the queue and receive them. */
@@ -1963,12 +1966,12 @@
 {
 	struct sk_buff *p;
 	struct sk_buff_head *list = &ppp->mrq;
-	u32 seq = skb->sequence;
+	u32 seq = PPP_MP_CB(skb)->sequence;
 
 	/* N.B. we don't need to lock the list lock because we have the
 	   ppp unit receive-side lock. */
 	skb_queue_walk(list, p) {
-		if (seq_before(seq, p->sequence))
+		if (seq_before(seq, PPP_MP_CB(p)->sequence))
 			break;
 	}
 	__skb_queue_before(list, p, skb);
@@ -1997,22 +2000,22 @@
 	tail = NULL;
 	for (p = head; p != (struct sk_buff *) list; p = next) {
 		next = p->next;
-		if (seq_before(p->sequence, seq)) {
+		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",
-			       p->sequence, seq);
+			       PPP_MP_CB(p)->sequence, seq);
 			head = next;
 			continue;
 		}
-		if (p->sequence != seq) {
+		if (PPP_MP_CB(p)->sequence != seq) {
 			/* Fragment `seq' is missing.  If it is after
 			   minseq, it might arrive later, so stop here. */
 			if (seq_after(seq, minseq))
 				break;
 			/* Fragment `seq' is lost, keep going. */
 			lost = 1;
-			seq = seq_before(minseq, p->sequence)?
-				minseq + 1: p->sequence;
+			seq = seq_before(minseq, PPP_MP_CB(p)->sequence)?
+				minseq + 1: PPP_MP_CB(p)->sequence;
 			next = p;
 			continue;
 		}
@@ -2026,7 +2029,7 @@
 		 */
 
 		/* B bit set indicates this fragment starts a packet */
-		if (p->BEbits & B) {
+		if (PPP_MP_CB(p)->BEbits & B) {
 			head = p;
 			lost = 0;
 			len = 0;
@@ -2035,7 +2038,8 @@
 		len += p->len;
 
 		/* Got a complete packet yet? */
-		if (lost == 0 && (p->BEbits & E) && (head->BEbits & B)) {
+		if (lost == 0 && (PPP_MP_CB(p)->BEbits & E) &&
+		    (PPP_MP_CB(head)->BEbits & B)) {
 			if (len > ppp->mrru + 2) {
 				++ppp->dev->stats.rx_length_errors;
 				printk(KERN_DEBUG "PPP: reconstructed packet"
@@ -2061,7 +2065,7 @@
 		 * and we haven't found a complete valid packet yet,
 		 * we can discard up to and including this fragment.
 		 */
-		if (p->BEbits & E)
+		if (PPP_MP_CB(p)->BEbits & E)
 			head = next;
 
 		++seq;
@@ -2071,10 +2075,11 @@
 	if (tail != NULL) {
 		/* If we have discarded any fragments,
 		   signal a receive error. */
-		if (head->sequence != ppp->nextseq) {
+		if (PPP_MP_CB(head)->sequence != ppp->nextseq) {
 			if (ppp->debug & 1)
 				printk(KERN_DEBUG "  missed pkts %u..%u\n",
-				       ppp->nextseq, head->sequence-1);
+				       ppp->nextseq,
+				       PPP_MP_CB(head)->sequence-1);
 			++ppp->dev->stats.rx_dropped;
 			ppp_receive_error(ppp);
 		}
@@ -2083,7 +2088,7 @@
 			/* 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 = tail->sequence + 1;
+		ppp->nextseq = PPP_MP_CB(tail)->sequence + 1;
 		head = tail->next;
 	}
 
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index c07de35..d72fb05 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -1124,7 +1124,7 @@
 	.ioctl		= pppox_ioctl,
 };
 
-static struct pppox_proto pppoe_proto = {
+static const struct pppox_proto pppoe_proto = {
 	.create	= pppoe_create,
 	.ioctl	= pppoe_ioctl,
 	.owner	= THIS_MODULE,
diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c
index d4191ef..8c0d170 100644
--- a/drivers/net/pppox.c
+++ b/drivers/net/pppox.c
@@ -36,9 +36,9 @@
 
 #include <asm/uaccess.h>
 
-static struct pppox_proto *pppox_protos[PX_MAX_PROTO + 1];
+static const struct pppox_proto *pppox_protos[PX_MAX_PROTO + 1];
 
-int register_pppox_proto(int proto_num, struct pppox_proto *pp)
+int register_pppox_proto(int proto_num, const struct pppox_proto *pp)
 {
 	if (proto_num < 0 || proto_num > PX_MAX_PROTO)
 		return -EINVAL;
diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
new file mode 100644
index 0000000..ccbc913
--- /dev/null
+++ b/drivers/net/pptp.c
@@ -0,0 +1,726 @@
+/*
+ *  Point-to-Point Tunneling Protocol for Linux
+ *
+ *	Authors: Dmitry Kozlov <xeb@mail.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 <linux/string.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_pppox.h>
+#include <linux/if_ppp.h>
+#include <linux/notifier.h>
+#include <linux/file.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/version.h>
+#include <linux/rcupdate.h>
+#include <linux/spinlock.h>
+
+#include <net/sock.h>
+#include <net/protocol.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <net/route.h>
+#include <net/gre.h>
+
+#include <linux/uaccess.h>
+
+#define PPTP_DRIVER_VERSION "0.8.5"
+
+#define MAX_CALLID 65535
+
+static DECLARE_BITMAP(callid_bitmap, MAX_CALLID + 1);
+static struct pppox_sock **callid_sock;
+
+static DEFINE_SPINLOCK(chan_lock);
+
+static struct proto pptp_sk_proto __read_mostly;
+static const struct ppp_channel_ops pptp_chan_ops;
+static const struct proto_ops pptp_ops;
+
+#define PPP_LCP_ECHOREQ 0x09
+#define PPP_LCP_ECHOREP 0x0A
+#define SC_RCV_BITS	(SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
+
+#define MISSING_WINDOW 20
+#define WRAPPED(curseq, lastseq)\
+	((((curseq) & 0xffffff00) == 0) &&\
+	(((lastseq) & 0xffffff00) == 0xffffff00))
+
+#define PPTP_GRE_PROTO  0x880B
+#define PPTP_GRE_VER    0x1
+
+#define PPTP_GRE_FLAG_C	0x80
+#define PPTP_GRE_FLAG_R	0x40
+#define PPTP_GRE_FLAG_K	0x20
+#define PPTP_GRE_FLAG_S	0x10
+#define PPTP_GRE_FLAG_A	0x80
+
+#define PPTP_GRE_IS_C(f) ((f)&PPTP_GRE_FLAG_C)
+#define PPTP_GRE_IS_R(f) ((f)&PPTP_GRE_FLAG_R)
+#define PPTP_GRE_IS_K(f) ((f)&PPTP_GRE_FLAG_K)
+#define PPTP_GRE_IS_S(f) ((f)&PPTP_GRE_FLAG_S)
+#define PPTP_GRE_IS_A(f) ((f)&PPTP_GRE_FLAG_A)
+
+#define PPTP_HEADER_OVERHEAD (2+sizeof(struct pptp_gre_header))
+struct pptp_gre_header {
+	u8  flags;
+	u8  ver;
+	u16 protocol;
+	u16 payload_len;
+	u16 call_id;
+	u32 seq;
+	u32 ack;
+} __packed;
+
+static struct pppox_sock *lookup_chan(u16 call_id, __be32 s_addr)
+{
+	struct pppox_sock *sock;
+	struct pptp_opt *opt;
+
+	rcu_read_lock();
+	sock = rcu_dereference(callid_sock[call_id]);
+	if (sock) {
+		opt = &sock->proto.pptp;
+		if (opt->dst_addr.sin_addr.s_addr != s_addr)
+			sock = NULL;
+		else
+			sock_hold(sk_pppox(sock));
+	}
+	rcu_read_unlock();
+
+	return sock;
+}
+
+static int lookup_chan_dst(u16 call_id, __be32 d_addr)
+{
+	struct pppox_sock *sock;
+	struct pptp_opt *opt;
+	int i;
+
+	rcu_read_lock();
+	for (i = find_next_bit(callid_bitmap, MAX_CALLID, 1); i < MAX_CALLID;
+	     i = find_next_bit(callid_bitmap, MAX_CALLID, i + 1)) {
+		sock = rcu_dereference(callid_sock[i]);
+		if (!sock)
+			continue;
+		opt = &sock->proto.pptp;
+		if (opt->dst_addr.call_id == call_id &&
+			  opt->dst_addr.sin_addr.s_addr == d_addr)
+			break;
+	}
+	rcu_read_unlock();
+
+	return i < MAX_CALLID;
+}
+
+static int add_chan(struct pppox_sock *sock)
+{
+	static int call_id;
+
+	spin_lock(&chan_lock);
+	if (!sock->proto.pptp.src_addr.call_id)	{
+		call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1);
+		if (call_id == MAX_CALLID) {
+			call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1);
+			if (call_id == MAX_CALLID)
+				goto out_err;
+		}
+		sock->proto.pptp.src_addr.call_id = call_id;
+	} else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap))
+		goto out_err;
+
+	set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
+	rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock);
+	spin_unlock(&chan_lock);
+
+	return 0;
+
+out_err:
+	spin_unlock(&chan_lock);
+	return -1;
+}
+
+static void del_chan(struct pppox_sock *sock)
+{
+	spin_lock(&chan_lock);
+	clear_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
+	rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], NULL);
+	spin_unlock(&chan_lock);
+	synchronize_rcu();
+}
+
+static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+{
+	struct sock *sk = (struct sock *) chan->private;
+	struct pppox_sock *po = pppox_sk(sk);
+	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;
+	__u32 seq_recv;
+
+
+	struct rtable *rt;
+	struct net_device *tdev;
+	struct iphdr  *iph;
+	int    max_headroom;
+
+	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;
+	}
+	tdev = rt->dst.dev;
+
+	max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(*iph) + sizeof(*hdr) + 2;
+
+	if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
+		if (!new_skb) {
+			ip_rt_put(rt);
+			goto tx_error;
+		}
+		if (skb->sk)
+			skb_set_owner_w(new_skb, skb->sk);
+		kfree_skb(skb);
+		skb = new_skb;
+	}
+
+	data = skb->data;
+	islcp = ((data[0] << 8) + data[1]) == PPP_LCP && 1 <= data[2] && data[2] <= 7;
+
+	/* compress protocol field */
+	if ((opt->ppp_flags & SC_COMP_PROT) && data[0] == 0 && !islcp)
+		skb_pull(skb, 1);
+
+	/* Put in the address/control bytes if necessary */
+	if ((opt->ppp_flags & SC_COMP_AC) == 0 || islcp) {
+		data = skb_push(skb, 2);
+		data[0] = PPP_ALLSTATIONS;
+		data[1] = PPP_UI;
+	}
+
+	len = skb->len;
+
+	seq_recv = opt->seq_recv;
+
+	if (opt->ack_sent == seq_recv)
+		header_len -= sizeof(hdr->ack);
+
+	/* Push down and install GRE header */
+	skb_push(skb, header_len);
+	hdr = (struct pptp_gre_header *)(skb->data);
+
+	hdr->flags       = PPTP_GRE_FLAG_K;
+	hdr->ver         = PPTP_GRE_VER;
+	hdr->protocol    = htons(PPTP_GRE_PROTO);
+	hdr->call_id     = htons(opt->dst_addr.call_id);
+
+	hdr->flags      |= PPTP_GRE_FLAG_S;
+	hdr->seq         = htonl(++opt->seq_sent);
+	if (opt->ack_sent != seq_recv)	{
+		/* send ack with this message */
+		hdr->ver |= PPTP_GRE_FLAG_A;
+		hdr->ack  = htonl(seq_recv);
+		opt->ack_sent = seq_recv;
+	}
+	hdr->payload_len = htons(len);
+
+	/*	Push down and install the IP header. */
+
+	skb_reset_transport_header(skb);
+	skb_push(skb, sizeof(*iph));
+	skb_reset_network_header(skb);
+	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
+
+	iph =	ip_hdr(skb);
+	iph->version =	4;
+	iph->ihl =	sizeof(struct iphdr) >> 2;
+	if (ip_dont_fragment(sk, &rt->dst))
+		iph->frag_off	=	htons(IP_DF);
+	else
+		iph->frag_off	=	0;
+	iph->protocol = IPPROTO_GRE;
+	iph->tos      = 0;
+	iph->daddr    = rt->rt_dst;
+	iph->saddr    = rt->rt_src;
+	iph->ttl      = dst_metric(&rt->dst, RTAX_HOPLIMIT);
+	iph->tot_len  = htons(skb->len);
+
+	skb_dst_drop(skb);
+	skb_dst_set(skb, &rt->dst);
+
+	nf_reset(skb);
+
+	skb->ip_summed = CHECKSUM_NONE;
+	ip_select_ident(iph, &rt->dst, NULL);
+	ip_send_check(iph);
+
+	ip_local_out(skb);
+
+tx_error:
+	return 1;
+}
+
+static int pptp_rcv_core(struct sock *sk, struct sk_buff *skb)
+{
+	struct pppox_sock *po = pppox_sk(sk);
+	struct pptp_opt *opt = &po->proto.pptp;
+	int headersize, payload_len, seq;
+	__u8 *payload;
+	struct pptp_gre_header *header;
+
+	if (!(sk->sk_state & PPPOX_CONNECTED)) {
+		if (sock_queue_rcv_skb(sk, skb))
+			goto drop;
+		return NET_RX_SUCCESS;
+	}
+
+	header = (struct pptp_gre_header *)(skb->data);
+
+	/* test if acknowledgement present */
+	if (PPTP_GRE_IS_A(header->ver)) {
+		__u32 ack = (PPTP_GRE_IS_S(header->flags)) ?
+				header->ack : header->seq; /* ack in different place if S = 0 */
+
+		ack = ntohl(ack);
+
+		if (ack > opt->ack_recv)
+			opt->ack_recv = ack;
+		/* also handle sequence number wrap-around  */
+		if (WRAPPED(ack, opt->ack_recv))
+			opt->ack_recv = ack;
+	}
+
+	/* test if payload present */
+	if (!PPTP_GRE_IS_S(header->flags))
+		goto drop;
+
+	headersize  = sizeof(*header);
+	payload_len = ntohs(header->payload_len);
+	seq         = ntohl(header->seq);
+
+	/* no ack present? */
+	if (!PPTP_GRE_IS_A(header->ver))
+		headersize -= sizeof(header->ack);
+	/* check for incomplete packet (length smaller than expected) */
+	if (skb->len - headersize < payload_len)
+		goto drop;
+
+	payload = skb->data + headersize;
+	/* check for expected sequence number */
+	if (seq < opt->seq_recv + 1 || WRAPPED(opt->seq_recv, seq)) {
+		if ((payload[0] == PPP_ALLSTATIONS) && (payload[1] == PPP_UI) &&
+				(PPP_PROTOCOL(payload) == PPP_LCP) &&
+				((payload[4] == PPP_LCP_ECHOREQ) || (payload[4] == PPP_LCP_ECHOREP)))
+			goto allow_packet;
+	} else {
+		opt->seq_recv = seq;
+allow_packet:
+		skb_pull(skb, headersize);
+
+		if (payload[0] == PPP_ALLSTATIONS && payload[1] == PPP_UI) {
+			/* chop off address/control */
+			if (skb->len < 3)
+				goto drop;
+			skb_pull(skb, 2);
+		}
+
+		if ((*skb->data) & 1) {
+			/* protocol is compressed */
+			skb_push(skb, 1)[0] = 0;
+		}
+
+		skb->ip_summed = CHECKSUM_NONE;
+		skb_set_network_header(skb, skb->head-skb->data);
+		ppp_input(&po->chan, skb);
+
+		return NET_RX_SUCCESS;
+	}
+drop:
+	kfree_skb(skb);
+	return NET_RX_DROP;
+}
+
+static int pptp_rcv(struct sk_buff *skb)
+{
+	struct pppox_sock *po;
+	struct pptp_gre_header *header;
+	struct iphdr *iph;
+
+	if (skb->pkt_type != PACKET_HOST)
+		goto drop;
+
+	if (!pskb_may_pull(skb, 12))
+		goto drop;
+
+	iph = ip_hdr(skb);
+
+	header = (struct pptp_gre_header *)skb->data;
+
+	if (ntohs(header->protocol) != PPTP_GRE_PROTO || /* PPTP-GRE protocol for PPTP */
+		PPTP_GRE_IS_C(header->flags) ||                /* flag C should be clear */
+		PPTP_GRE_IS_R(header->flags) ||                /* flag R should be clear */
+		!PPTP_GRE_IS_K(header->flags) ||               /* flag K should be set */
+		(header->flags&0xF) != 0)                      /* routing and recursion ctrl = 0 */
+		/* if invalid, discard this packet */
+		goto drop;
+
+	po = lookup_chan(htons(header->call_id), iph->saddr);
+	if (po) {
+		skb_dst_drop(skb);
+		nf_reset(skb);
+		return sk_receive_skb(sk_pppox(po), skb, 0);
+	}
+drop:
+	kfree_skb(skb);
+	return NET_RX_DROP;
+}
+
+static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr,
+	int sockaddr_len)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+	struct pppox_sock *po = pppox_sk(sk);
+	struct pptp_opt *opt = &po->proto.pptp;
+	int error = 0;
+
+	lock_sock(sk);
+
+	opt->src_addr = sp->sa_addr.pptp;
+	if (add_chan(po)) {
+		release_sock(sk);
+		error = -EBUSY;
+	}
+
+	release_sock(sk);
+	return error;
+}
+
+static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
+	int sockaddr_len, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+	struct pppox_sock *po = pppox_sk(sk);
+	struct pptp_opt *opt = &po->proto.pptp;
+	struct rtable *rt;
+	int error = 0;
+
+	if (sp->sa_protocol != PX_PROTO_PPTP)
+		return -EINVAL;
+
+	if (lookup_chan_dst(sp->sa_addr.pptp.call_id, sp->sa_addr.pptp.sin_addr.s_addr))
+		return -EALREADY;
+
+	lock_sock(sk);
+	/* Check for already bound sockets */
+	if (sk->sk_state & PPPOX_CONNECTED) {
+		error = -EBUSY;
+		goto end;
+	}
+
+	/* Check for already disconnected sockets, on attempts to disconnect */
+	if (sk->sk_state & PPPOX_DEAD) {
+		error = -EALREADY;
+		goto end;
+	}
+
+	if (!opt->src_addr.sin_addr.s_addr || !sp->sa_addr.pptp.sin_addr.s_addr) {
+		error = -EINVAL;
+		goto end;
+	}
+
+	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);
+	}
+	po->chan.mtu = dst_mtu(&rt->dst);
+	if (!po->chan.mtu)
+		po->chan.mtu = PPP_MTU;
+	ip_rt_put(rt);
+	po->chan.mtu -= PPTP_HEADER_OVERHEAD;
+
+	po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header);
+	error = ppp_register_channel(&po->chan);
+	if (error) {
+		pr_err("PPTP: failed to register PPP channel (%d)\n", error);
+		goto end;
+	}
+
+	opt->dst_addr = sp->sa_addr.pptp;
+	sk->sk_state = PPPOX_CONNECTED;
+
+ end:
+	release_sock(sk);
+	return error;
+}
+
+static int pptp_getname(struct socket *sock, struct sockaddr *uaddr,
+	int *usockaddr_len, int peer)
+{
+	int len = sizeof(struct sockaddr_pppox);
+	struct sockaddr_pppox sp;
+
+	sp.sa_family	  = AF_PPPOX;
+	sp.sa_protocol  = PX_PROTO_PPTP;
+	sp.sa_addr.pptp = pppox_sk(sock->sk)->proto.pptp.src_addr;
+
+	memcpy(uaddr, &sp, len);
+
+	*usockaddr_len = len;
+
+	return 0;
+}
+
+static int pptp_release(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+	struct pppox_sock *po;
+	struct pptp_opt *opt;
+	int error = 0;
+
+	if (!sk)
+		return 0;
+
+	lock_sock(sk);
+
+	if (sock_flag(sk, SOCK_DEAD)) {
+		release_sock(sk);
+		return -EBADF;
+	}
+
+	po = pppox_sk(sk);
+	opt = &po->proto.pptp;
+	del_chan(po);
+
+	pppox_unbind_sock(sk);
+	sk->sk_state = PPPOX_DEAD;
+
+	sock_orphan(sk);
+	sock->sk = NULL;
+
+	release_sock(sk);
+	sock_put(sk);
+
+	return error;
+}
+
+static void pptp_sock_destruct(struct sock *sk)
+{
+	if (!(sk->sk_state & PPPOX_DEAD)) {
+		del_chan(pppox_sk(sk));
+		pppox_unbind_sock(sk);
+	}
+	skb_queue_purge(&sk->sk_receive_queue);
+}
+
+static int pptp_create(struct net *net, struct socket *sock)
+{
+	int error = -ENOMEM;
+	struct sock *sk;
+	struct pppox_sock *po;
+	struct pptp_opt *opt;
+
+	sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pptp_sk_proto);
+	if (!sk)
+		goto out;
+
+	sock_init_data(sock, sk);
+
+	sock->state = SS_UNCONNECTED;
+	sock->ops   = &pptp_ops;
+
+	sk->sk_backlog_rcv = pptp_rcv_core;
+	sk->sk_state       = PPPOX_NONE;
+	sk->sk_type        = SOCK_STREAM;
+	sk->sk_family      = PF_PPPOX;
+	sk->sk_protocol    = PX_PROTO_PPTP;
+	sk->sk_destruct    = pptp_sock_destruct;
+
+	po = pppox_sk(sk);
+	opt = &po->proto.pptp;
+
+	opt->seq_sent = 0; opt->seq_recv = 0;
+	opt->ack_recv = 0; opt->ack_sent = 0;
+
+	error = 0;
+out:
+	return error;
+}
+
+static int pptp_ppp_ioctl(struct ppp_channel *chan, unsigned int cmd,
+	unsigned long arg)
+{
+	struct sock *sk = (struct sock *) chan->private;
+	struct pppox_sock *po = pppox_sk(sk);
+	struct pptp_opt *opt = &po->proto.pptp;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
+	int err, val;
+
+	err = -EFAULT;
+	switch (cmd) {
+	case PPPIOCGFLAGS:
+		val = opt->ppp_flags;
+		if (put_user(val, p))
+			break;
+		err = 0;
+		break;
+	case PPPIOCSFLAGS:
+		if (get_user(val, p))
+			break;
+		opt->ppp_flags = val & ~SC_RCV_BITS;
+		err = 0;
+		break;
+	default:
+		err = -ENOTTY;
+	}
+
+	return err;
+}
+
+static const struct ppp_channel_ops pptp_chan_ops = {
+	.start_xmit = pptp_xmit,
+	.ioctl      = pptp_ppp_ioctl,
+};
+
+static struct proto pptp_sk_proto __read_mostly = {
+	.name     = "PPTP",
+	.owner    = THIS_MODULE,
+	.obj_size = sizeof(struct pppox_sock),
+};
+
+static const struct proto_ops pptp_ops = {
+	.family     = AF_PPPOX,
+	.owner      = THIS_MODULE,
+	.release    = pptp_release,
+	.bind       = pptp_bind,
+	.connect    = pptp_connect,
+	.socketpair = sock_no_socketpair,
+	.accept     = sock_no_accept,
+	.getname    = pptp_getname,
+	.poll       = sock_no_poll,
+	.listen     = sock_no_listen,
+	.shutdown   = sock_no_shutdown,
+	.setsockopt = sock_no_setsockopt,
+	.getsockopt = sock_no_getsockopt,
+	.sendmsg    = sock_no_sendmsg,
+	.recvmsg    = sock_no_recvmsg,
+	.mmap       = sock_no_mmap,
+	.ioctl      = pppox_ioctl,
+};
+
+static const struct pppox_proto pppox_pptp_proto = {
+	.create = pptp_create,
+	.owner  = THIS_MODULE,
+};
+
+static const struct gre_protocol gre_pptp_protocol = {
+	.handler = pptp_rcv,
+};
+
+static int __init pptp_init_module(void)
+{
+	int err = 0;
+	pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n");
+
+	callid_sock = __vmalloc((MAX_CALLID + 1) * sizeof(void *),
+		GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+	if (!callid_sock) {
+		pr_err("PPTP: cann't allocate memory\n");
+		return -ENOMEM;
+	}
+
+	err = gre_add_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
+	if (err) {
+		pr_err("PPTP: can't add gre protocol\n");
+		goto out_mem_free;
+	}
+
+	err = proto_register(&pptp_sk_proto, 0);
+	if (err) {
+		pr_err("PPTP: can't register sk_proto\n");
+		goto out_gre_del_protocol;
+	}
+
+	err = register_pppox_proto(PX_PROTO_PPTP, &pppox_pptp_proto);
+	if (err) {
+		pr_err("PPTP: can't register pppox_proto\n");
+		goto out_unregister_sk_proto;
+	}
+
+	return 0;
+
+out_unregister_sk_proto:
+	proto_unregister(&pptp_sk_proto);
+out_gre_del_protocol:
+	gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
+out_mem_free:
+	vfree(callid_sock);
+
+	return err;
+}
+
+static void __exit pptp_exit_module(void)
+{
+	unregister_pppox_proto(PX_PROTO_PPTP);
+	proto_unregister(&pptp_sk_proto);
+	gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
+	vfree(callid_sock);
+}
+
+module_init(pptp_init_module);
+module_exit(pptp_exit_module);
+
+MODULE_DESCRIPTION("Point-to-Point Tunneling Protocol");
+MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
index 87d6b8f..5526ab4 100644
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ps3_gelic_net.c
@@ -956,9 +956,9 @@
 		    (!(data_error & GELIC_DESCR_DATA_ERROR_CHK_MASK)))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
 	} else
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 
 	/* update netdevice statistics */
 	netdev->stats.rx_packets++;
diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c
index 43b8d77..4a624a2 100644
--- a/drivers/net/ps3_gelic_wireless.c
+++ b/drivers/net/ps3_gelic_wireless.c
@@ -85,12 +85,12 @@
  */
 static inline int wpa2_capable(void)
 {
-	return (0 <= ps3_compare_firmware_version(2, 0, 0));
+	return 0 <= ps3_compare_firmware_version(2, 0, 0);
 }
 
 static inline int precise_ie(void)
 {
-	return (0 <= ps3_compare_firmware_version(2, 2, 0));
+	return 0 <= ps3_compare_firmware_version(2, 2, 0);
 }
 /*
  * post_eurus_cmd helpers
@@ -506,7 +506,7 @@
 	start[1] = (buf - start - 2);
 
 	pr_debug("%s: ->\n", __func__);
-	return (buf - start);
+	return buf - start;
 }
 
 struct ie_item {
diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c
index 85eddda..18c0297 100644
--- a/drivers/net/pxa168_eth.c
+++ b/drivers/net/pxa168_eth.c
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2010 Marvell International Ltd.
  *		Sachin Sanap <ssanap@marvell.com>
+ *		Zhangfei Gao <zgao6@marvell.com>
  *		Philip Rakity <prakity@marvell.com>
  *		Mark Brown <markb@marvell.com>
  *
@@ -42,8 +43,6 @@
 #include <linux/types.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
 #include <asm/cacheflush.h>
 #include <linux/pxa168_eth.h>
 
@@ -850,7 +849,6 @@
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_receive_skb(skb);
 		}
-		dev->last_rx = jiffies;
 	}
 	/* Fill RX ring with skb's */
 	rxq_refill(dev);
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 6168a13..7496ed2 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2029,7 +2029,7 @@
 			 dma_unmap_len(lrg_buf_cb2, maplen),
 			 PCI_DMA_FROMDEVICE);
 	prefetch(skb->data);
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 	skb->protocol = eth_type_trans(skb, qdev->ndev);
 
 	netif_receive_skb(skb);
@@ -2076,7 +2076,7 @@
 			 PCI_DMA_FROMDEVICE);
 	prefetch(skb2->data);
 
-	skb2->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb2);
 	if (qdev->device_id == QL3022_DEVICE_ID) {
 		/*
 		 * Copy the ethhdr from first buffer to second. This
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 9703893..26c37d3 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -51,9 +51,11 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 7
-#define QLCNIC_LINUX_VERSIONID  "5.0.7"
+#define _QLCNIC_LINUX_SUBVERSION 11
+#define QLCNIC_LINUX_VERSIONID  "5.0.11"
 #define QLCNIC_DRV_IDC_VER  0x01
+#define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
+		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
 
 #define QLCNIC_VERSION_CODE(a, b, c)	(((a) << 24) + ((b) << 16) + (c))
 #define _major(v)	(((v) >> 24) & 0xff)
@@ -92,11 +94,12 @@
 #define FIRST_PAGE_GROUP_START	0
 #define FIRST_PAGE_GROUP_END	0x100000
 
-#define P3_MAX_MTU                     (9600)
+#define P3P_MAX_MTU                     (9600)
+#define P3P_MIN_MTU                     (68)
 #define QLCNIC_MAX_ETHERHDR                32 /* This contains some padding */
 
-#define QLCNIC_P3_RX_BUF_MAX_LEN         (QLCNIC_MAX_ETHERHDR + ETH_DATA_LEN)
-#define QLCNIC_P3_RX_JUMBO_BUF_MAX_LEN   (QLCNIC_MAX_ETHERHDR + P3_MAX_MTU)
+#define QLCNIC_P3P_RX_BUF_MAX_LEN         (QLCNIC_MAX_ETHERHDR + ETH_DATA_LEN)
+#define QLCNIC_P3P_RX_JUMBO_BUF_MAX_LEN   (QLCNIC_MAX_ETHERHDR + P3P_MAX_MTU)
 #define QLCNIC_CT_DEFAULT_RX_BUF_LEN	2048
 #define QLCNIC_LRO_BUFFER_EXTRA		2048
 
@@ -148,6 +151,7 @@
 
 #define DEFAULT_RCV_DESCRIPTORS_1G	2048
 #define DEFAULT_RCV_DESCRIPTORS_10G	4096
+#define MAX_RDS_RINGS                   2
 
 #define get_next_index(index, length)	\
 	(((index) + 1) & ((length) - 1))
@@ -172,7 +176,7 @@
 	((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0))
 
 #define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \
-	((_desc)->flags_opcode = \
+	((_desc)->flags_opcode |= \
 	cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)))
 
 #define qlcnic_set_tx_frags_len(_desc, _frags, _len) \
@@ -221,7 +225,8 @@
 #define QLCNIC_LRO_DESC  	0x12
 
 /* for status field in status_desc */
-#define STATUS_CKSUM_OK		(2)
+#define STATUS_CKSUM_LOOP	0
+#define STATUS_CKSUM_OK		2
 
 /* owner bits of status_desc */
 #define STATUS_OWNER_HOST	(0x1ULL << 56)
@@ -302,20 +307,20 @@
 /* Magic number to let user know flash is programmed */
 #define	QLCNIC_BDINFO_MAGIC 0x12345678
 
-#define QLCNIC_BRDTYPE_P3_REF_QG	0x0021
-#define QLCNIC_BRDTYPE_P3_HMEZ		0x0022
-#define QLCNIC_BRDTYPE_P3_10G_CX4_LP	0x0023
-#define QLCNIC_BRDTYPE_P3_4_GB		0x0024
-#define QLCNIC_BRDTYPE_P3_IMEZ		0x0025
-#define QLCNIC_BRDTYPE_P3_10G_SFP_PLUS	0x0026
-#define QLCNIC_BRDTYPE_P3_10000_BASE_T	0x0027
-#define QLCNIC_BRDTYPE_P3_XG_LOM	0x0028
-#define QLCNIC_BRDTYPE_P3_4_GB_MM	0x0029
-#define QLCNIC_BRDTYPE_P3_10G_SFP_CT	0x002a
-#define QLCNIC_BRDTYPE_P3_10G_SFP_QT	0x002b
-#define QLCNIC_BRDTYPE_P3_10G_CX4	0x0031
-#define QLCNIC_BRDTYPE_P3_10G_XFP	0x0032
-#define QLCNIC_BRDTYPE_P3_10G_TP	0x0080
+#define QLCNIC_BRDTYPE_P3P_REF_QG	0x0021
+#define QLCNIC_BRDTYPE_P3P_HMEZ		0x0022
+#define QLCNIC_BRDTYPE_P3P_10G_CX4_LP	0x0023
+#define QLCNIC_BRDTYPE_P3P_4_GB		0x0024
+#define QLCNIC_BRDTYPE_P3P_IMEZ		0x0025
+#define QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS	0x0026
+#define QLCNIC_BRDTYPE_P3P_10000_BASE_T	0x0027
+#define QLCNIC_BRDTYPE_P3P_XG_LOM	0x0028
+#define QLCNIC_BRDTYPE_P3P_4_GB_MM	0x0029
+#define QLCNIC_BRDTYPE_P3P_10G_SFP_CT	0x002a
+#define QLCNIC_BRDTYPE_P3P_10G_SFP_QT	0x002b
+#define QLCNIC_BRDTYPE_P3P_10G_CX4	0x0031
+#define QLCNIC_BRDTYPE_P3P_10G_XFP	0x0032
+#define QLCNIC_BRDTYPE_P3P_10G_TP	0x0080
 
 #define QLCNIC_MSIX_TABLE_OFFSET	0x44
 
@@ -555,6 +560,8 @@
 #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS	0x00000026
 #define QLCNIC_CDRP_CMD_SET_PORTMIRRORING	0x00000027
 #define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH	0x00000028
+#define QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG	0x00000029
+#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS	0x0000002a
 
 #define QLCNIC_RCODE_SUCCESS		0
 #define QLCNIC_RCODE_TIMEOUT		17
@@ -712,11 +719,13 @@
 
 /* MAC */
 
-#define MC_COUNT_P3	38
+#define MC_COUNT_P3P	38
 
 #define QLCNIC_MAC_NOOP	0
 #define QLCNIC_MAC_ADD	1
 #define QLCNIC_MAC_DEL	2
+#define QLCNIC_MAC_VLAN_ADD	3
+#define QLCNIC_MAC_VLAN_DEL	4
 
 struct qlcnic_mac_list_s {
 	struct list_head list;
@@ -890,12 +899,28 @@
 	u8 mac_addr[6];
 };
 
+struct qlcnic_vlan_req {
+	__le16 vlan_id;
+	__le16 rsvd[3];
+};
+
+struct qlcnic_ipaddr {
+	__be32 ipv4;
+	__be32 ipv6[4];
+};
+
 #define QLCNIC_MSI_ENABLED		0x02
 #define QLCNIC_MSIX_ENABLED		0x04
 #define QLCNIC_LRO_ENABLED		0x08
+#define QLCNIC_LRO_DISABLED		0x00
 #define QLCNIC_BRIDGE_ENABLED       	0X10
 #define QLCNIC_DIAG_ENABLED		0x20
 #define QLCNIC_ESWITCH_ENABLED		0x40
+#define QLCNIC_ADAPTER_INITIALIZED	0x80
+#define QLCNIC_TAGGING_ENABLED		0x100
+#define QLCNIC_MACSPOOF			0x200
+#define QLCNIC_MAC_OVERRIDE_DISABLED	0x400
+#define QLCNIC_PROMISC_DISABLED		0x800
 #define QLCNIC_IS_MSI_FAMILY(adapter) \
 	((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
 
@@ -916,6 +941,22 @@
 #define QLCNIC_INTERRUPT_TEST		1
 #define QLCNIC_LOOPBACK_TEST		2
 
+#define QLCNIC_FILTER_AGE	80
+#define QLCNIC_LB_MAX_FILTERS	64
+
+struct qlcnic_filter {
+	struct hlist_node fnode;
+	u8 faddr[ETH_ALEN];
+	__le16 vlan_id;
+	unsigned long ftime;
+};
+
+struct qlcnic_filter_hash {
+	struct hlist_head *fhead;
+	u8 fnum;
+	u8 fmax;
+};
+
 struct qlcnic_adapter {
 	struct qlcnic_hardware_context ahw;
 
@@ -924,6 +965,7 @@
 	struct list_head mac_list;
 
 	spinlock_t tx_clean_lock;
+	spinlock_t mac_learn_lock;
 
 	u16 num_txd;
 	u16 num_rxd;
@@ -931,7 +973,6 @@
 
 	u8 max_rds_rings;
 	u8 max_sds_rings;
-	u8 driver_mismatch;
 	u8 msix_supported;
 	u8 rx_csum;
 	u8 portnum;
@@ -961,6 +1002,7 @@
 	u16 max_tx_ques;
 	u16 max_rx_ques;
 	u16 max_mtu;
+	u16 pvid;
 
 	u32 fw_hal_version;
 	u32 capabilities;
@@ -969,7 +1011,7 @@
 	u32 temp;
 
 	u32 int_vec_bit;
-	u32 heartbit;
+	u32 heartbeat;
 
 	u8 max_mac_filters;
 	u8 dev_state;
@@ -983,6 +1025,7 @@
 
 	u64 dev_rst_time;
 
+	struct vlan_group *vlgrp;
 	struct qlcnic_npar_info *npars;
 	struct qlcnic_eswitch *eswitch;
 	struct qlcnic_nic_template *nic_ops;
@@ -1003,6 +1046,8 @@
 
 	struct qlcnic_nic_intr_coalesce coal;
 
+	struct qlcnic_filter_hash fhash;
+
 	unsigned long state;
 	__le32 file_prd_off;	/*File fw product offset*/
 	u32 fw_version;
@@ -1042,7 +1087,7 @@
 };
 
 struct qlcnic_npar_info {
-	u16	vlan_id;
+	u16	pvid;
 	u16	min_bw;
 	u16	max_bw;
 	u8	phy_port;
@@ -1050,11 +1095,13 @@
 	u8	active;
 	u8	enable_pm;
 	u8	dest_npar;
-	u8	host_vlan_tag;
-	u8	promisc_mode;
 	u8	discard_tagged;
-	u8	mac_learning;
+	u8	mac_override;
+	u8	mac_anti_spoof;
+	u8	promisc_mode;
+	u8	offload_flags;
 };
+
 struct qlcnic_eswitch {
 	u8	port;
 	u8	active_vports;
@@ -1086,7 +1133,6 @@
 #define IS_VALID_BW(bw)		(bw >= MIN_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)
-#define IS_VALID_MODE(mode)	(mode == 0 || mode == 1)
 
 struct qlcnic_pci_func_cfg {
 	u16	func_type;
@@ -1118,12 +1164,53 @@
 
 struct qlcnic_esw_func_cfg {
 	u16	vlan_id;
+	u8	op_mode;
+	u8	op_type;
 	u8	pci_func;
 	u8	host_vlan_tag;
 	u8	promisc_mode;
 	u8	discard_tagged;
-	u8	mac_learning;
-	u8	reserved;
+	u8	mac_override;
+	u8	mac_anti_spoof;
+	u8	offload_flags;
+	u8	reserved[5];
+};
+
+#define QLCNIC_STATS_VERSION		1
+#define QLCNIC_STATS_PORT		1
+#define QLCNIC_STATS_ESWITCH		2
+#define QLCNIC_QUERY_RX_COUNTER		0
+#define QLCNIC_QUERY_TX_COUNTER		1
+#define QLCNIC_ESW_STATS_NOT_AVAIL	0xffffffffffffffffULL
+
+#define QLCNIC_ADD_ESW_STATS(VAL1, VAL2)\
+do {	\
+	if (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) && \
+	    ((VAL2) != QLCNIC_ESW_STATS_NOT_AVAIL)) \
+		(VAL1) = (VAL2); \
+	else if (((VAL1) != QLCNIC_ESW_STATS_NOT_AVAIL) && \
+		 ((VAL2) != QLCNIC_ESW_STATS_NOT_AVAIL)) \
+			(VAL1) += (VAL2); \
+} while (0)
+
+struct __qlcnic_esw_statistics {
+	__le16 context_id;
+	__le16 version;
+	__le16 size;
+	__le16 unused;
+	__le64 unicast_frames;
+	__le64 multicast_frames;
+	__le64 broadcast_frames;
+	__le64 dropped_frames;
+	__le64 errors;
+	__le64 local_frames;
+	__le64 numbytes;
+	__le64 rsvd[3];
+};
+
+struct qlcnic_esw_statistics {
+	struct __qlcnic_esw_statistics rx;
+	struct __qlcnic_esw_statistics tx;
 };
 
 int qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val);
@@ -1171,6 +1258,8 @@
 int qlcnic_get_board_info(struct qlcnic_adapter *adapter);
 int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
 int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate);
+void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter);
+void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter);
 
 /* Functions from qlcnic_init.c */
 int qlcnic_load_firmware(struct qlcnic_adapter *adapter);
@@ -1199,7 +1288,7 @@
 void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter);
 void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter);
 
-int qlcnic_init_firmware(struct qlcnic_adapter *adapter);
+int qlcnic_check_fw_status(struct qlcnic_adapter *adapter);
 void qlcnic_watchdog_task(struct work_struct *work);
 void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid,
 		struct qlcnic_host_rds_ring *rds_ring);
@@ -1209,7 +1298,7 @@
 int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32);
 int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter);
 int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable);
-int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, u32 ip, int cmd);
+int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd);
 int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable);
 void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup);
 
@@ -1220,12 +1309,13 @@
 int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
 void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
 		struct qlcnic_host_tx_ring *tx_ring);
-int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u8 *mac);
 void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter);
 int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter);
 void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
 
 /* Functions from qlcnic_main.c */
+int qlcnic_request_quiscent_mode(struct qlcnic_adapter *adapter);
+void qlcnic_clear_quiscent_mode(struct qlcnic_adapter *adapter);
 int qlcnic_reset_context(struct qlcnic_adapter *);
 u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
 	u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd);
@@ -1236,22 +1326,22 @@
 void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
 
 /* Management functions */
-int qlcnic_set_mac_address(struct qlcnic_adapter *, u8*);
 int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
 int qlcnic_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8);
 int qlcnic_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
 int qlcnic_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info*);
-int qlcnic_reset_partition(struct qlcnic_adapter *, u8);
 
 /*  eSwitch management functions */
-int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *, u8,
-				struct qlcnic_eswitch *);
-int qlcnic_get_eswitch_status(struct qlcnic_adapter *, u8,
-				struct qlcnic_eswitch *);
-int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8);
-int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8,
-			u8, u8, u16);
+int qlcnic_config_switch_port(struct qlcnic_adapter *,
+				struct qlcnic_esw_func_cfg *);
+int qlcnic_get_eswitch_port_config(struct qlcnic_adapter *,
+				struct qlcnic_esw_func_cfg *);
 int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8);
+int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8,
+					struct __qlcnic_esw_statistics *);
+int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8,
+					struct __qlcnic_esw_statistics *);
+int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
 extern int qlcnic_config_tso;
 
 /*
@@ -1280,6 +1370,8 @@
 		"3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"},
 	{0x1077, 0x8020, 0x1077, 0x20f,
 		"3200 Series Single Port 10Gb Intelligent Ethernet Adapter"},
+	{0x1077, 0x8020, 0x103c, 0x3733,
+		"NC523SFP 10Gb 2-port Server Adapter"},
 	{0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
 };
 
@@ -1298,7 +1390,6 @@
 extern const struct ethtool_ops qlcnic_ethtool_ops;
 
 struct qlcnic_nic_template {
-	int (*get_mac_addr) (struct qlcnic_adapter *, u8*);
 	int (*config_bridged_mode) (struct qlcnic_adapter *, u32);
 	int (*config_led) (struct qlcnic_adapter *, u32, u32);
 	int (*start_firmware) (struct qlcnic_adapter *);
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index cc5d861..1cdc05d 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -556,32 +556,6 @@
 	}
 }
 
-/* Set MAC address of a NIC partition */
-int qlcnic_set_mac_address(struct qlcnic_adapter *adapter, u8* mac)
-{
-	int err = 0;
-	u32 arg1, arg2, arg3;
-
-	arg1 = adapter->ahw.pci_func | BIT_9;
-	arg2 = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);
-	arg3 = mac[4] | (mac[5] << 16);
-
-	err = qlcnic_issue_cmd(adapter,
-			adapter->ahw.pci_func,
-			adapter->fw_hal_version,
-			arg1,
-			arg2,
-			arg3,
-			QLCNIC_CDRP_CMD_MAC_ADDRESS);
-
-	if (err != QLCNIC_RCODE_SUCCESS) {
-		dev_err(&adapter->pdev->dev,
-			"Failed to set mac address%d\n", err);
-		err = -EIO;
-	}
-
-	return err;
-}
 
 /* Get MAC address of a NIC partition */
 int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
@@ -742,15 +716,15 @@
 
 	if (err == QLCNIC_RCODE_SUCCESS) {
 		for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) {
-			pci_info->id = le32_to_cpu(npar->id);
-			pci_info->active = le32_to_cpu(npar->active);
-			pci_info->type = le32_to_cpu(npar->type);
+			pci_info->id = le16_to_cpu(npar->id);
+			pci_info->active = le16_to_cpu(npar->active);
+			pci_info->type = le16_to_cpu(npar->type);
 			pci_info->default_port =
-				le32_to_cpu(npar->default_port);
+				le16_to_cpu(npar->default_port);
 			pci_info->tx_min_bw =
-				le32_to_cpu(npar->tx_min_bw);
+				le16_to_cpu(npar->tx_min_bw);
 			pci_info->tx_max_bw =
-				le32_to_cpu(npar->tx_max_bw);
+				le16_to_cpu(npar->tx_max_bw);
 			memcpy(pci_info->mac, npar->mac, ETH_ALEN);
 		}
 	} else {
@@ -764,150 +738,6 @@
 	return err;
 }
 
-/* Reset a NIC partition */
-
-int qlcnic_reset_partition(struct qlcnic_adapter *adapter, u8 func_no)
-{
-	int err = -EIO;
-
-	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
-		return err;
-
-	err = qlcnic_issue_cmd(adapter,
-			adapter->ahw.pci_func,
-			adapter->fw_hal_version,
-			func_no,
-			0,
-			0,
-			QLCNIC_CDRP_CMD_RESET_NPAR);
-
-	if (err != QLCNIC_RCODE_SUCCESS) {
-		dev_err(&adapter->pdev->dev,
-			"Failed to issue reset partition%d\n", err);
-		err = -EIO;
-	}
-
-	return err;
-}
-
-/* Get eSwitch Capabilities */
-int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *adapter, u8 port,
-					struct qlcnic_eswitch *eswitch)
-{
-	int err = -EIO;
-	u32 arg1, arg2;
-
-	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
-		return err;
-
-	err = qlcnic_issue_cmd(adapter,
-			adapter->ahw.pci_func,
-			adapter->fw_hal_version,
-			port,
-			0,
-			0,
-			QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY);
-
-	if (err == QLCNIC_RCODE_SUCCESS) {
-		arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
-		arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
-
-		eswitch->port = arg1 & 0xf;
-		eswitch->active_vports = LSB(arg2);
-		eswitch->max_ucast_filters = MSB(arg2);
-		eswitch->max_active_vlans = LSB(MSW(arg2));
-		if (arg1 & BIT_6)
-			eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING;
-		if (arg1 & BIT_7)
-			eswitch->flags |= QLCNIC_SWITCH_PROMISC_MODE;
-		if (arg1 & BIT_8)
-			eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING;
-	} else {
-		dev_err(&adapter->pdev->dev,
-			"Failed to get eswitch capabilities%d\n", err);
-	}
-
-	return err;
-}
-
-/* Get current status of eswitch */
-int qlcnic_get_eswitch_status(struct qlcnic_adapter *adapter, u8 port,
-				struct qlcnic_eswitch *eswitch)
-{
-	int err = -EIO;
-	u32 arg1, arg2;
-
-	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
-		return err;
-
-	err = qlcnic_issue_cmd(adapter,
-			adapter->ahw.pci_func,
-			adapter->fw_hal_version,
-			port,
-			0,
-			0,
-			QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS);
-
-	if (err == QLCNIC_RCODE_SUCCESS) {
-		arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
-		arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
-
-		eswitch->port = arg1 & 0xf;
-		eswitch->active_vports = LSB(arg2);
-		eswitch->active_ucast_filters = MSB(arg2);
-		eswitch->active_vlans = LSB(MSW(arg2));
-		if (arg1 & BIT_6)
-			eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING;
-		if (arg1 & BIT_8)
-			eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING;
-
-	} else {
-		dev_err(&adapter->pdev->dev,
-			"Failed to get eswitch status%d\n", err);
-	}
-
-	return err;
-}
-
-/* Enable/Disable eSwitch */
-int qlcnic_toggle_eswitch(struct qlcnic_adapter *adapter, u8 id, u8 enable)
-{
-	int err = -EIO;
-	u32 arg1, arg2;
-	struct qlcnic_eswitch *eswitch;
-
-	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
-		return err;
-
-	eswitch = &adapter->eswitch[id];
-	if (!eswitch)
-		return err;
-
-	arg1 = eswitch->port | (enable ? BIT_4 : 0);
-	arg2 = eswitch->active_vports | (eswitch->max_ucast_filters << 8) |
-		(eswitch->max_active_vlans << 16);
-	err = qlcnic_issue_cmd(adapter,
-			adapter->ahw.pci_func,
-			adapter->fw_hal_version,
-			arg1,
-			arg2,
-			0,
-			QLCNIC_CDRP_CMD_TOGGLE_ESWITCH);
-
-	if (err != QLCNIC_RCODE_SUCCESS) {
-		dev_err(&adapter->pdev->dev,
-			"Failed to enable eswitch%d\n", eswitch->port);
-		eswitch->flags &= ~QLCNIC_SWITCH_ENABLE;
-		err = -EIO;
-	} else {
-		eswitch->flags |= QLCNIC_SWITCH_ENABLE;
-		dev_info(&adapter->pdev->dev,
-			"Enabled eSwitch for port %d\n", eswitch->port);
-	}
-
-	return err;
-}
-
 /* Configure eSwitch for port mirroring */
 int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
 				u8 enable_mirroring, u8 pci_func)
@@ -943,43 +773,284 @@
 	return err;
 }
 
-/* Configure eSwitch port */
-int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id,
-		int vlan_tagging, u8 discard_tagged, u8 promsc_mode,
-		u8 mac_learn, u8 pci_func, u16 vlan_id)
-{
-	int err = -EIO;
+int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
+		const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
+
+	size_t stats_size = sizeof(struct __qlcnic_esw_statistics);
+	struct __qlcnic_esw_statistics *stats;
+	dma_addr_t stats_dma_t;
+	void *stats_addr;
 	u32 arg1;
-	struct qlcnic_eswitch *eswitch;
+	int err;
 
-	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
-		return err;
+	if (esw_stats == NULL)
+		return -ENOMEM;
 
-	eswitch = &adapter->eswitch[id];
-	if (!(eswitch->flags & QLCNIC_SWITCH_ENABLE))
-		return err;
+	if (adapter->op_mode != QLCNIC_MGMT_FUNC &&
+	    func != adapter->ahw.pci_func) {
+		dev_err(&adapter->pdev->dev,
+			"Not privilege to query stats for func=%d", func);
+		return -EIO;
+	}
 
-	arg1 = eswitch->port | (discard_tagged ? BIT_4 : 0);
-	arg1 |= (promsc_mode ? BIT_6 : 0) | (mac_learn ? BIT_7 : 0);
-	arg1 |= pci_func << 8;
-	if (vlan_tagging)
-		arg1 |= BIT_5 | (vlan_id << 16);
+	stats_addr = pci_alloc_consistent(adapter->pdev, stats_size,
+			&stats_dma_t);
+	if (!stats_addr) {
+		dev_err(&adapter->pdev->dev, "Unable to allocate memory\n");
+		return -ENOMEM;
+	}
+	memset(stats_addr, 0, stats_size);
+
+	arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
+	arg1 |= rx_tx << 15 | stats_size << 16;
 
 	err = qlcnic_issue_cmd(adapter,
 			adapter->ahw.pci_func,
 			adapter->fw_hal_version,
 			arg1,
+			MSD(stats_dma_t),
+			LSD(stats_dma_t),
+			QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
+
+	if (!err) {
+		stats = (struct __qlcnic_esw_statistics *)stats_addr;
+		esw_stats->context_id = le16_to_cpu(stats->context_id);
+		esw_stats->version = le16_to_cpu(stats->version);
+		esw_stats->size = le16_to_cpu(stats->size);
+		esw_stats->multicast_frames =
+				le64_to_cpu(stats->multicast_frames);
+		esw_stats->broadcast_frames =
+				le64_to_cpu(stats->broadcast_frames);
+		esw_stats->unicast_frames = le64_to_cpu(stats->unicast_frames);
+		esw_stats->dropped_frames = le64_to_cpu(stats->dropped_frames);
+		esw_stats->local_frames = le64_to_cpu(stats->local_frames);
+		esw_stats->errors = le64_to_cpu(stats->errors);
+		esw_stats->numbytes = le64_to_cpu(stats->numbytes);
+	}
+
+	pci_free_consistent(adapter->pdev, stats_size, stats_addr,
+		stats_dma_t);
+	return err;
+}
+
+int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
+		const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
+
+	struct __qlcnic_esw_statistics port_stats;
+	u8 i;
+	int ret = -EIO;
+
+	if (esw_stats == NULL)
+		return -ENOMEM;
+	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+		return -EIO;
+	if (adapter->npars == NULL)
+		return -EIO;
+
+	memset(esw_stats, 0, sizeof(u64));
+	esw_stats->unicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+	esw_stats->multicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+	esw_stats->broadcast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+	esw_stats->dropped_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+	esw_stats->errors = QLCNIC_ESW_STATS_NOT_AVAIL;
+	esw_stats->local_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+	esw_stats->numbytes = QLCNIC_ESW_STATS_NOT_AVAIL;
+	esw_stats->context_id = eswitch;
+
+	for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+		if (adapter->npars[i].phy_port != eswitch)
+			continue;
+
+		memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
+		if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats))
+			continue;
+
+		esw_stats->size = port_stats.size;
+		esw_stats->version = port_stats.version;
+		QLCNIC_ADD_ESW_STATS(esw_stats->unicast_frames,
+						port_stats.unicast_frames);
+		QLCNIC_ADD_ESW_STATS(esw_stats->multicast_frames,
+						port_stats.multicast_frames);
+		QLCNIC_ADD_ESW_STATS(esw_stats->broadcast_frames,
+						port_stats.broadcast_frames);
+		QLCNIC_ADD_ESW_STATS(esw_stats->dropped_frames,
+						port_stats.dropped_frames);
+		QLCNIC_ADD_ESW_STATS(esw_stats->errors,
+						port_stats.errors);
+		QLCNIC_ADD_ESW_STATS(esw_stats->local_frames,
+						port_stats.local_frames);
+		QLCNIC_ADD_ESW_STATS(esw_stats->numbytes,
+						port_stats.numbytes);
+		ret = 0;
+	}
+	return ret;
+}
+
+int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
+		const u8 port, const u8 rx_tx)
+{
+
+	u32 arg1;
+
+	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+		return -EIO;
+
+	if (func_esw == QLCNIC_STATS_PORT) {
+		if (port >= QLCNIC_MAX_PCI_FUNC)
+			goto err_ret;
+	} else if (func_esw == QLCNIC_STATS_ESWITCH) {
+		if (port >= QLCNIC_NIU_MAX_XG_PORTS)
+			goto err_ret;
+	} else {
+		goto err_ret;
+	}
+
+	if (rx_tx > QLCNIC_QUERY_TX_COUNTER)
+		goto err_ret;
+
+	arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
+	arg1 |= BIT_14 | rx_tx << 15;
+
+	return qlcnic_issue_cmd(adapter,
+			adapter->ahw.pci_func,
+			adapter->fw_hal_version,
+			arg1,
 			0,
 			0,
+			QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
+
+err_ret:
+	dev_err(&adapter->pdev->dev, "Invalid argument func_esw=%d port=%d"
+		"rx_ctx=%d\n", func_esw, port, rx_tx);
+	return -EIO;
+}
+
+static int
+__qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
+					u32 *arg1, u32 *arg2)
+{
+	int err = -EIO;
+	u8 pci_func;
+	pci_func = (*arg1 >> 8);
+	err = qlcnic_issue_cmd(adapter,
+			adapter->ahw.pci_func,
+			adapter->fw_hal_version,
+			*arg1,
+			0,
+			0,
+			QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG);
+
+	if (err == QLCNIC_RCODE_SUCCESS) {
+		*arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
+		*arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
+		dev_info(&adapter->pdev->dev,
+			"eSwitch port config for pci func %d\n", pci_func);
+	} else {
+		dev_err(&adapter->pdev->dev,
+			"Failed to get eswitch port config for pci func %d\n",
+								pci_func);
+	}
+	return err;
+}
+/* Configure eSwitch port
+op_mode = 0 for setting default port behavior
+op_mode = 1 for setting  vlan id
+op_mode = 2 for deleting vlan id
+op_type = 0 for vlan_id
+op_type = 1 for port vlan_id
+*/
+int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
+		struct qlcnic_esw_func_cfg *esw_cfg)
+{
+	int err = -EIO;
+	u32 arg1, arg2 = 0;
+	u8 pci_func;
+
+	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+		return err;
+	pci_func = esw_cfg->pci_func;
+	arg1 = (adapter->npars[pci_func].phy_port & BIT_0);
+	arg1 |= (pci_func << 8);
+
+	if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
+		return err;
+	arg1 &= ~(0x0ff << 8);
+	arg1 |= (pci_func << 8);
+	arg1 &= ~(BIT_2 | BIT_3);
+	switch (esw_cfg->op_mode) {
+	case QLCNIC_PORT_DEFAULTS:
+		arg1 |= (BIT_4 | BIT_6 | BIT_7);
+		arg2 |= (BIT_0 | BIT_1);
+		if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+			arg2 |= (BIT_2 | BIT_3);
+		if (!(esw_cfg->discard_tagged))
+			arg1 &= ~BIT_4;
+		if (!(esw_cfg->promisc_mode))
+			arg1 &= ~BIT_6;
+		if (!(esw_cfg->mac_override))
+			arg1 &= ~BIT_7;
+		if (!(esw_cfg->mac_anti_spoof))
+			arg2 &= ~BIT_0;
+		if (!(esw_cfg->offload_flags & BIT_0))
+			arg2 &= ~(BIT_1 | BIT_2 | BIT_3);
+		if (!(esw_cfg->offload_flags & BIT_1))
+			arg2 &= ~BIT_2;
+		if (!(esw_cfg->offload_flags & BIT_2))
+			arg2 &= ~BIT_3;
+		break;
+	case QLCNIC_ADD_VLAN:
+			arg1 |= (BIT_2 | BIT_5);
+			arg1 |= (esw_cfg->vlan_id << 16);
+			break;
+	case QLCNIC_DEL_VLAN:
+			arg1 |= (BIT_3 | BIT_5);
+			arg1 &= ~(0x0ffff << 16);
+			break;
+	default:
+		return err;
+	}
+
+	err = qlcnic_issue_cmd(adapter,
+			adapter->ahw.pci_func,
+			adapter->fw_hal_version,
+			arg1,
+			arg2,
+			0,
 			QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH);
 
 	if (err != QLCNIC_RCODE_SUCCESS) {
 		dev_err(&adapter->pdev->dev,
-			"Failed to configure eswitch port%d\n", eswitch->port);
+			"Failed to configure eswitch pci func %d\n", pci_func);
 	} else {
 		dev_info(&adapter->pdev->dev,
-			"Configured eSwitch for port %d\n", eswitch->port);
+			"Configured eSwitch for pci func %d\n", pci_func);
 	}
 
 	return err;
 }
+
+int
+qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
+			struct qlcnic_esw_func_cfg *esw_cfg)
+{
+	u32 arg1, arg2;
+	u8 phy_port;
+	if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+		phy_port = adapter->npars[esw_cfg->pci_func].phy_port;
+	else
+		phy_port = adapter->physical_port;
+	arg1 = phy_port;
+	arg1 |= (esw_cfg->pci_func << 8);
+	if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
+		return -EIO;
+
+	esw_cfg->discard_tagged = !!(arg1 & BIT_4);
+	esw_cfg->host_vlan_tag = !!(arg1 & BIT_5);
+	esw_cfg->promisc_mode = !!(arg1 & BIT_6);
+	esw_cfg->mac_override = !!(arg1 & BIT_7);
+	esw_cfg->vlan_id = LSW(arg1 >> 16);
+	esw_cfg->mac_anti_spoof = (arg2 & 0x1);
+	esw_cfg->offload_flags = ((arg2 >> 1) & 0x7);
+
+	return 0;
+}
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 9328d59..25e93a5 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -78,7 +78,25 @@
 
 };
 
+static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
+	"rx unicast frames",
+	"rx multicast frames",
+	"rx broadcast frames",
+	"rx dropped frames",
+	"rx errors",
+	"rx local frames",
+	"rx numbytes",
+	"tx unicast frames",
+	"tx multicast frames",
+	"tx broadcast frames",
+	"tx dropped frames",
+	"tx errors",
+	"tx local frames",
+	"tx numbytes",
+};
+
 #define QLCNIC_STATS_LEN	ARRAY_SIZE(qlcnic_gstrings_stats)
+#define QLCNIC_DEVICE_STATS_LEN	ARRAY_SIZE(qlcnic_device_gstrings_stats)
 
 static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
 	"Register_Test_on_offline",
@@ -96,10 +114,10 @@
 static const u32 diag_registers[] = {
 	CRB_CMDPEG_STATE,
 	CRB_RCVPEG_STATE,
-	CRB_XG_STATE_P3,
+	CRB_XG_STATE_P3P,
 	CRB_FW_CAPABILITIES_1,
 	ISR_INT_STATE_REG,
-	QLCNIC_CRB_DEV_REF_COUNT,
+	QLCNIC_CRB_DRV_ACTIVE,
 	QLCNIC_CRB_DEV_STATE,
 	QLCNIC_CRB_DRV_STATE,
 	QLCNIC_CRB_DRV_SCRATCH,
@@ -115,9 +133,13 @@
 	-1
 };
 
+#define QLCNIC_MGMT_API_VERSION	2
+#define QLCNIC_DEV_INFO_SIZE	1
+#define QLCNIC_ETHTOOL_REGS_VER	2
 static int qlcnic_get_regs_len(struct net_device *dev)
 {
-	return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN;
+	return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
+				QLCNIC_DEV_INFO_SIZE + 1;
 }
 
 static int qlcnic_get_eeprom_len(struct net_device *dev)
@@ -185,9 +207,9 @@
 			goto skip;
 		}
 
-		val = QLCRD32(adapter, P3_LINK_SPEED_REG(pcifn));
-		ecmd->speed = P3_LINK_SPEED_MHZ *
-			P3_LINK_SPEED_VAL(pcifn, val);
+		val = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn));
+		ecmd->speed = P3P_LINK_SPEED_MHZ *
+			P3P_LINK_SPEED_VAL(pcifn, val);
 		ecmd->duplex = DUPLEX_FULL;
 		ecmd->autoneg = AUTONEG_DISABLE;
 	} else
@@ -198,42 +220,42 @@
 	ecmd->transceiver = XCVR_EXTERNAL;
 
 	switch (adapter->ahw.board_type) {
-	case QLCNIC_BRDTYPE_P3_REF_QG:
-	case QLCNIC_BRDTYPE_P3_4_GB:
-	case QLCNIC_BRDTYPE_P3_4_GB_MM:
+	case QLCNIC_BRDTYPE_P3P_REF_QG:
+	case QLCNIC_BRDTYPE_P3P_4_GB:
+	case QLCNIC_BRDTYPE_P3P_4_GB_MM:
 
 		ecmd->supported |= SUPPORTED_Autoneg;
 		ecmd->advertising |= ADVERTISED_Autoneg;
-	case QLCNIC_BRDTYPE_P3_10G_CX4:
-	case QLCNIC_BRDTYPE_P3_10G_CX4_LP:
-	case QLCNIC_BRDTYPE_P3_10000_BASE_T:
+	case QLCNIC_BRDTYPE_P3P_10G_CX4:
+	case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
+	case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
 		ecmd->supported |= SUPPORTED_TP;
 		ecmd->advertising |= ADVERTISED_TP;
 		ecmd->port = PORT_TP;
 		ecmd->autoneg =  adapter->link_autoneg;
 		break;
-	case QLCNIC_BRDTYPE_P3_IMEZ:
-	case QLCNIC_BRDTYPE_P3_XG_LOM:
-	case QLCNIC_BRDTYPE_P3_HMEZ:
+	case QLCNIC_BRDTYPE_P3P_IMEZ:
+	case QLCNIC_BRDTYPE_P3P_XG_LOM:
+	case QLCNIC_BRDTYPE_P3P_HMEZ:
 		ecmd->supported |= SUPPORTED_MII;
 		ecmd->advertising |= ADVERTISED_MII;
 		ecmd->port = PORT_MII;
 		ecmd->autoneg = AUTONEG_DISABLE;
 		break;
-	case QLCNIC_BRDTYPE_P3_10G_SFP_PLUS:
-	case QLCNIC_BRDTYPE_P3_10G_SFP_CT:
-	case QLCNIC_BRDTYPE_P3_10G_SFP_QT:
+	case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
+	case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
+	case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
 		ecmd->advertising |= ADVERTISED_TP;
 		ecmd->supported |= SUPPORTED_TP;
 		check_sfp_module = netif_running(dev) &&
 			adapter->has_link_events;
-	case QLCNIC_BRDTYPE_P3_10G_XFP:
+	case QLCNIC_BRDTYPE_P3P_10G_XFP:
 		ecmd->supported |= SUPPORTED_FIBRE;
 		ecmd->advertising |= ADVERTISED_FIBRE;
 		ecmd->port = PORT_FIBRE;
 		ecmd->autoneg = AUTONEG_DISABLE;
 		break;
-	case QLCNIC_BRDTYPE_P3_10G_TP:
+	case QLCNIC_BRDTYPE_P3P_10G_TP:
 		if (adapter->ahw.port_type == QLCNIC_XGBE) {
 			ecmd->autoneg = AUTONEG_DISABLE;
 			ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
@@ -339,14 +361,17 @@
 	struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
 	struct qlcnic_host_sds_ring *sds_ring;
 	u32 *regs_buff = p;
-	int ring, i = 0;
+	int ring, i = 0, j = 0;
 
 	memset(p, 0, qlcnic_get_regs_len(dev));
-	regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
-	    (adapter->pdev)->device;
+	regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
+		(adapter->ahw.revision_id << 16) | (adapter->pdev)->device;
 
-	for (i = 0; diag_registers[i] != -1; i++)
-		regs_buff[i] = QLCRD32(adapter, diag_registers[i]);
+	regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
+	regs_buff[1] = QLCNIC_MGMT_API_VERSION;
+
+	for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
+		regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
 
 	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
 		return;
@@ -374,9 +399,9 @@
 	struct qlcnic_adapter *adapter = netdev_priv(dev);
 	u32 val;
 
-	val = QLCRD32(adapter, CRB_XG_STATE_P3);
-	val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
-	return (val == XG_LINK_UP_P3) ? 0 : 1;
+	val = QLCRD32(adapter, CRB_XG_STATE_P3P);
+	val = XG_LINK_STATE_P3P(adapter->ahw.pci_func, val);
+	return (val == XG_LINK_UP_P3P) ? 0 : 1;
 }
 
 static int
@@ -618,10 +643,13 @@
 
 static int qlcnic_get_sset_count(struct net_device *dev, int sset)
 {
+	struct qlcnic_adapter *adapter = netdev_priv(dev);
 	switch (sset) {
 	case ETH_SS_TEST:
 		return QLCNIC_TEST_LEN;
 	case ETH_SS_STATS:
+		if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+			return QLCNIC_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
 		return QLCNIC_STATS_LEN;
 	default:
 		return -EOPNOTSUPP;
@@ -629,6 +657,8 @@
 }
 
 #define QLC_ILB_PKT_SIZE 64
+#define QLC_NUM_ILB_PKT	16
+#define QLC_ILB_MAX_RCV_LOOP 10
 
 static void qlcnic_create_loopback_buff(unsigned char *data)
 {
@@ -650,24 +680,34 @@
 	struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
 	struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
 	struct sk_buff *skb;
-	int i;
+	int i, loop, cnt = 0;
 
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < QLC_NUM_ILB_PKT; i++) {
 		skb = dev_alloc_skb(QLC_ILB_PKT_SIZE);
 		qlcnic_create_loopback_buff(skb->data);
 		skb_put(skb, QLC_ILB_PKT_SIZE);
 
 		adapter->diag_cnt = 0;
-
 		qlcnic_xmit_frame(skb, adapter->netdev);
 
-		msleep(5);
-
-		qlcnic_process_rcv_ring_diag(sds_ring);
+		loop = 0;
+		do {
+			msleep(1);
+			qlcnic_process_rcv_ring_diag(sds_ring);
+		} while (loop++ < QLC_ILB_MAX_RCV_LOOP &&
+			 !adapter->diag_cnt);
 
 		dev_kfree_skb_any(skb);
+
 		if (!adapter->diag_cnt)
-			return -1;
+			dev_warn(&adapter->pdev->dev, "ILB Test: %dth packet"
+				" not recevied\n", i + 1);
+		else
+			cnt++;
+	}
+	if (cnt != i) {
+		dev_warn(&adapter->pdev->dev, "ILB Test failed\n");
+		return -1;
 	}
 	return 0;
 }
@@ -687,6 +727,11 @@
 	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
 		return -EIO;
 
+	if (qlcnic_request_quiscent_mode(adapter)) {
+		clear_bit(__QLCNIC_RESETTING, &adapter->state);
+		return -EIO;
+	}
+
 	ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
 	if (ret)
 		goto clear_it;
@@ -703,6 +748,7 @@
 	qlcnic_diag_free_res(netdev, max_sds_rings);
 
 clear_it:
+	qlcnic_clear_quiscent_mode(adapter);
 	adapter->max_sds_rings = max_sds_rings;
 	clear_bit(__QLCNIC_RESETTING, &adapter->state);
 	return ret;
@@ -747,6 +793,14 @@
 {
 	memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
 
+	data[0] = qlcnic_reg_test(dev);
+	if (data[0])
+		eth_test->flags |= ETH_TEST_FL_FAILED;
+
+	data[1] = (u64) qlcnic_test_link(dev);
+	if (data[1])
+		eth_test->flags |= ETH_TEST_FL_FAILED;
+
 	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
 		data[2] = qlcnic_irq_test(dev);
 		if (data[2])
@@ -757,21 +811,13 @@
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 	}
-
-	data[0] = qlcnic_reg_test(dev);
-	if (data[0])
-		eth_test->flags |= ETH_TEST_FL_FAILED;
-
-	/* link test */
-	data[1] = (u64) qlcnic_test_link(dev);
-	if (data[1])
-		eth_test->flags |= ETH_TEST_FL_FAILED;
 }
 
 static void
 qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
 {
-	int index;
+	struct qlcnic_adapter *adapter = netdev_priv(dev);
+	int index, i;
 
 	switch (stringset) {
 	case ETH_SS_TEST:
@@ -784,16 +830,43 @@
 			       qlcnic_gstrings_stats[index].stat_string,
 			       ETH_GSTRING_LEN);
 		}
-		break;
+		if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+			return;
+		for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
+			memcpy(data + index * ETH_GSTRING_LEN,
+			       qlcnic_device_gstrings_stats[i],
+			       ETH_GSTRING_LEN);
+		}
 	}
 }
 
+#define QLCNIC_FILL_ESWITCH_STATS(VAL1) \
+	(((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) ? 0 : VAL1)
+
+static void
+qlcnic_fill_device_stats(int *index, u64 *data,
+		struct __qlcnic_esw_statistics *stats)
+{
+	int ind = *index;
+
+	data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->unicast_frames);
+	data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->multicast_frames);
+	data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->broadcast_frames);
+	data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->dropped_frames);
+	data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->errors);
+	data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->local_frames);
+	data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->numbytes);
+
+	*index = ind;
+}
+
 static void
 qlcnic_get_ethtool_stats(struct net_device *dev,
 			     struct ethtool_stats *stats, u64 * data)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(dev);
-	int index;
+	struct qlcnic_esw_statistics port_stats;
+	int index, ret;
 
 	for (index = 0; index < QLCNIC_STATS_LEN; index++) {
 		char *p =
@@ -803,8 +876,40 @@
 		    (qlcnic_gstrings_stats[index].sizeof_stat ==
 		     sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
 	}
+
+	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+		return;
+
+	memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
+	ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func,
+			QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
+	if (ret)
+		return;
+
+	qlcnic_fill_device_stats(&index, data, &port_stats.rx);
+
+	ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func,
+			QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
+	if (ret)
+		return;
+
+	qlcnic_fill_device_stats(&index, data, &port_stats.tx);
 }
 
+static int qlcnic_set_tx_csum(struct net_device *dev, u32 data)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(dev);
+
+	if ((adapter->flags & QLCNIC_ESWITCH_ENABLED))
+		return -EOPNOTSUPP;
+	if (data)
+		dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+	else
+		dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+
+	return 0;
+
+}
 static u32 qlcnic_get_tx_csum(struct net_device *dev)
 {
 	return dev->features & NETIF_F_IP_CSUM;
@@ -819,7 +924,23 @@
 static int qlcnic_set_rx_csum(struct net_device *dev, u32 data)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(dev);
+
+	if ((adapter->flags & QLCNIC_ESWITCH_ENABLED))
+		return -EOPNOTSUPP;
+	if (!!data) {
+		adapter->rx_csum = !!data;
+		return 0;
+	}
+
+	if (dev->features & NETIF_F_LRO) {
+		if (qlcnic_config_hw_lro(adapter, QLCNIC_LRO_DISABLED))
+			return -EIO;
+
+		dev->features &= ~NETIF_F_LRO;
+		qlcnic_send_lro_cleanup(adapter);
+	}
 	adapter->rx_csum = !!data;
+	dev_info(&adapter->pdev->dev, "disabling LRO as rx_csum is off\n");
 	return 0;
 }
 
@@ -1002,6 +1123,15 @@
 	if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
 		return -EINVAL;
 
+	if (!adapter->rx_csum) {
+		dev_info(&adapter->pdev->dev, "rx csum is off, "
+			"cannot toggle lro\n");
+		return -EINVAL;
+	}
+
+	if ((data & ETH_FLAG_LRO) && (netdev->features & NETIF_F_LRO))
+		return 0;
+
 	if (data & ETH_FLAG_LRO) {
 		hw_lro = QLCNIC_LRO_ENABLED;
 		netdev->features |= NETIF_F_LRO;
@@ -1048,7 +1178,7 @@
 	.get_pauseparam = qlcnic_get_pauseparam,
 	.set_pauseparam = qlcnic_set_pauseparam,
 	.get_tx_csum = qlcnic_get_tx_csum,
-	.set_tx_csum = ethtool_op_set_tx_csum,
+	.set_tx_csum = qlcnic_set_tx_csum,
 	.set_sg = ethtool_op_set_sg,
 	.get_tso = qlcnic_get_tso,
 	.set_tso = qlcnic_set_tso,
diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h
index 15fc320..4290b80 100644
--- a/drivers/net/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/qlcnic/qlcnic_hdr.h
@@ -556,18 +556,18 @@
 #define XG_LINK_UP	0x10
 #define XG_LINK_DOWN	0x20
 
-#define XG_LINK_UP_P3	0x01
-#define XG_LINK_DOWN_P3	0x02
-#define XG_LINK_STATE_P3_MASK 0xf
-#define XG_LINK_STATE_P3(pcifn, val) \
-	(((val) >> ((pcifn) * 4)) & XG_LINK_STATE_P3_MASK)
+#define XG_LINK_UP_P3P	0x01
+#define XG_LINK_DOWN_P3P	0x02
+#define XG_LINK_STATE_P3P_MASK 0xf
+#define XG_LINK_STATE_P3P(pcifn, val) \
+	(((val) >> ((pcifn) * 4)) & XG_LINK_STATE_P3P_MASK)
 
-#define P3_LINK_SPEED_MHZ	100
-#define P3_LINK_SPEED_MASK	0xff
-#define P3_LINK_SPEED_REG(pcifn)	\
+#define P3P_LINK_SPEED_MHZ	100
+#define P3P_LINK_SPEED_MASK	0xff
+#define P3P_LINK_SPEED_REG(pcifn)	\
 	(CRB_PF_LINK_SPEED_1 + (((pcifn) / 4) * 4))
-#define P3_LINK_SPEED_VAL(pcifn, reg)	\
-	(((reg) >> (8 * ((pcifn) & 0x3))) & P3_LINK_SPEED_MASK)
+#define P3P_LINK_SPEED_VAL(pcifn, reg)	\
+	(((reg) >> (8 * ((pcifn) & 0x3))) & P3P_LINK_SPEED_MASK)
 
 #define QLCNIC_CAM_RAM_BASE	(QLCNIC_CRB_CAM + 0x02000)
 #define QLCNIC_CAM_RAM(reg)	(QLCNIC_CAM_RAM_BASE + (reg))
@@ -592,7 +592,7 @@
 #define CRB_CMDPEG_STATE		(QLCNIC_REG(0x50))
 #define CRB_RCVPEG_STATE		(QLCNIC_REG(0x13c))
 
-#define CRB_XG_STATE_P3 		(QLCNIC_REG(0x98))
+#define CRB_XG_STATE_P3P		(QLCNIC_REG(0x98))
 #define CRB_PF_LINK_SPEED_1		(QLCNIC_REG(0xe8))
 #define CRB_PF_LINK_SPEED_2		(QLCNIC_REG(0xec))
 
@@ -698,7 +698,7 @@
 #define QLCNIC_PEG_ALIVE_COUNTER	(QLCNIC_CAM_RAM(0xb0))
 #define QLCNIC_PEG_HALT_STATUS1 	(QLCNIC_CAM_RAM(0xa8))
 #define QLCNIC_PEG_HALT_STATUS2 	(QLCNIC_CAM_RAM(0xac))
-#define QLCNIC_CRB_DEV_REF_COUNT	(QLCNIC_CAM_RAM(0x138))
+#define QLCNIC_CRB_DRV_ACTIVE	(QLCNIC_CAM_RAM(0x138))
 #define QLCNIC_CRB_DEV_STATE		(QLCNIC_CAM_RAM(0x140))
 
 #define QLCNIC_CRB_DRV_STATE		(QLCNIC_CAM_RAM(0x144))
@@ -718,8 +718,9 @@
 #define QLCNIC_DEV_FAILED		0x6
 #define QLCNIC_DEV_QUISCENT		0x7
 
-#define QLCNIC_DEV_NPAR_NOT_RDY	0
-#define QLCNIC_DEV_NPAR_RDY		1
+#define QLCNIC_DEV_NPAR_NON_OPER	0 /* NON Operational */
+#define QLCNIC_DEV_NPAR_OPER		1 /* NPAR Operational */
+#define QLCNIC_DEV_NPAR_OPER_TIMEO	30 /* Operational time out */
 
 #define QLC_DEV_CHECK_ACTIVE(VAL, FN)		((VAL) &= (1 << (FN * 4)))
 #define QLC_DEV_SET_REF_CNT(VAL, FN)		((VAL) |= (1 << (FN * 4)))
@@ -744,6 +745,15 @@
 #define FW_POLL_DELAY		(1 * HZ)
 #define FW_FAIL_THRESH		2
 
+#define QLCNIC_RESET_TIMEOUT_SECS	10
+#define QLCNIC_INIT_TIMEOUT_SECS	30
+#define QLCNIC_RCVPEG_CHECK_RETRY_COUNT	2000
+#define QLCNIC_RCVPEG_CHECK_DELAY	10
+#define QLCNIC_CMDPEG_CHECK_RETRY_COUNT	60
+#define QLCNIC_CMDPEG_CHECK_DELAY	500
+#define QLCNIC_HEARTBEAT_PERIOD_MSECS	200
+#define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT	45
+
 #define	ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
 #define ISR_LEGACY_INT_TRIGGERED(VAL)	(((VAL) & 0x300) == 0x200)
 
@@ -770,6 +780,7 @@
 #define QLCNIC_DRV_OP_MODE	0x1b2170
 #define QLCNIC_MSIX_BASE	0x132110
 #define QLCNIC_MAX_PCI_FUNC	8
+#define QLCNIC_MAX_VLAN_FILTERS	64
 
 /* PCI function operational mode */
 enum {
@@ -778,6 +789,12 @@
 	QLCNIC_NON_PRIV_FUNC	= 2
 };
 
+enum {
+	QLCNIC_PORT_DEFAULTS	= 0,
+	QLCNIC_ADD_VLAN	= 1,
+	QLCNIC_DEL_VLAN	= 2
+};
+
 #define QLC_DEV_DRV_DEFAULT 0x11111111
 
 #define LSB(x)	((uint8_t)(x))
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index e08c8b0..7a47a2a 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -297,8 +297,8 @@
 			break;
 		if (++timeout >= QLCNIC_PCIE_SEM_TIMEOUT) {
 			dev_err(&adapter->pdev->dev,
-				"Failed to acquire sem=%d lock;reg_id=%d\n",
-				sem, id_reg);
+				"Failed to acquire sem=%d lock; holdby=%d\n",
+				sem, id_reg ? QLCRD32(adapter, id_reg) : -1);
 			return -EIO;
 		}
 		msleep(1);
@@ -375,10 +375,11 @@
 
 static int
 qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
-				unsigned op)
+				__le16 vlan_id, unsigned op)
 {
 	struct qlcnic_nic_req req;
 	struct qlcnic_mac_req *mac_req;
+	struct qlcnic_vlan_req *vlan_req;
 	u64 word;
 
 	memset(&req, 0, sizeof(struct qlcnic_nic_req));
@@ -391,6 +392,9 @@
 	mac_req->op = op;
 	memcpy(mac_req->mac_addr, addr, 6);
 
+	vlan_req = (struct qlcnic_vlan_req *)&req.words[1];
+	vlan_req->vlan_id = vlan_id;
+
 	return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
 }
 
@@ -415,7 +419,7 @@
 	memcpy(cur->mac_addr, addr, ETH_ALEN);
 
 	if (qlcnic_sre_macaddr_change(adapter,
-				cur->mac_addr, QLCNIC_MAC_ADD)) {
+				cur->mac_addr, 0, QLCNIC_MAC_ADD)) {
 		kfree(cur);
 		return -EIO;
 	}
@@ -438,7 +442,8 @@
 	qlcnic_nic_add_mac(adapter, bcast_addr);
 
 	if (netdev->flags & IFF_PROMISC) {
-		mode = VPORT_MISS_MODE_ACCEPT_ALL;
+		if (!(adapter->flags & QLCNIC_PROMISC_DISABLED))
+			mode = VPORT_MISS_MODE_ACCEPT_ALL;
 		goto send_fw_cmd;
 	}
 
@@ -485,12 +490,63 @@
 	while (!list_empty(head)) {
 		cur = list_entry(head->next, struct qlcnic_mac_list_s, list);
 		qlcnic_sre_macaddr_change(adapter,
-				cur->mac_addr, QLCNIC_MAC_DEL);
+				cur->mac_addr, 0, QLCNIC_MAC_DEL);
 		list_del(&cur->list);
 		kfree(cur);
 	}
 }
 
+void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_filter *tmp_fil;
+	struct hlist_node *tmp_hnode, *n;
+	struct hlist_head *head;
+	int i;
+
+	for (i = 0; i < adapter->fhash.fmax; i++) {
+		head = &(adapter->fhash.fhead[i]);
+
+		hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode)
+		{
+			if (jiffies >
+				(QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) {
+				qlcnic_sre_macaddr_change(adapter,
+					tmp_fil->faddr, tmp_fil->vlan_id,
+					tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL :
+					QLCNIC_MAC_DEL);
+				spin_lock_bh(&adapter->mac_learn_lock);
+				adapter->fhash.fnum--;
+				hlist_del(&tmp_fil->fnode);
+				spin_unlock_bh(&adapter->mac_learn_lock);
+				kfree(tmp_fil);
+			}
+		}
+	}
+}
+
+void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_filter *tmp_fil;
+	struct hlist_node *tmp_hnode, *n;
+	struct hlist_head *head;
+	int i;
+
+	for (i = 0; i < adapter->fhash.fmax; i++) {
+		head = &(adapter->fhash.fhead[i]);
+
+		hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
+			qlcnic_sre_macaddr_change(adapter, tmp_fil->faddr,
+				tmp_fil->vlan_id, tmp_fil->vlan_id ?
+				QLCNIC_MAC_VLAN_DEL :  QLCNIC_MAC_DEL);
+			spin_lock_bh(&adapter->mac_learn_lock);
+			adapter->fhash.fnum--;
+			hlist_del(&tmp_fil->fnode);
+			spin_unlock_bh(&adapter->mac_learn_lock);
+			kfree(tmp_fil);
+		}
+	}
+}
+
 #define	QLCNIC_CONFIG_INTR_COALESCE	3
 
 /*
@@ -527,9 +583,6 @@
 	u64 word;
 	int rv;
 
-	if ((adapter->flags & QLCNIC_LRO_ENABLED) == enable)
-		return 0;
-
 	memset(&req, 0, sizeof(struct qlcnic_nic_req));
 
 	req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
@@ -544,8 +597,6 @@
 		dev_err(&adapter->netdev->dev,
 			"Could not send configure hw lro request\n");
 
-	adapter->flags ^= QLCNIC_LRO_ENABLED;
-
 	return rv;
 }
 
@@ -623,9 +674,10 @@
 	return rv;
 }
 
-int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, u32 ip, int cmd)
+int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd)
 {
 	struct qlcnic_nic_req req;
+	struct qlcnic_ipaddr *ipa;
 	u64 word;
 	int rv;
 
@@ -636,7 +688,8 @@
 	req.req_hdr = cpu_to_le64(word);
 
 	req.words[0] = cpu_to_le64(cmd);
-	req.words[1] = cpu_to_le64(ip);
+	ipa = (struct qlcnic_ipaddr *)&req.words[1];
+	ipa->ipv4 = ip;
 
 	rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
 	if (rv != 0)
@@ -701,9 +754,9 @@
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	int rc = 0;
 
-	if (mtu > P3_MAX_MTU) {
-		dev_err(&adapter->netdev->dev, "mtu > %d bytes unsupported\n",
-						P3_MAX_MTU);
+	if (mtu < P3P_MIN_MTU || mtu > P3P_MAX_MTU) {
+		dev_err(&adapter->netdev->dev, "%d bytes < mtu < %d bytes"
+			" not supported\n", P3P_MAX_MTU, P3P_MIN_MTU);
 		return -EINVAL;
 	}
 
@@ -715,19 +768,6 @@
 	return rc;
 }
 
-int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u8 *mac)
-{
-	u32 crbaddr;
-	int pci_func = adapter->ahw.pci_func;
-
-	crbaddr = CRB_MAC_BLOCK_START +
-		(4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1));
-
-	qlcnic_fetch_mac(adapter, crbaddr, crbaddr+4, pci_func & 1, mac);
-
-	return 0;
-}
-
 /*
  * Changes the CRB window to the specified window.
  */
@@ -1121,31 +1161,31 @@
 
 	adapter->ahw.board_type = board_type;
 
-	if (board_type == QLCNIC_BRDTYPE_P3_4_GB_MM) {
+	if (board_type == QLCNIC_BRDTYPE_P3P_4_GB_MM) {
 		u32 gpio = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_PAD_GPIO_I);
 		if ((gpio & 0x8000) == 0)
-			board_type = QLCNIC_BRDTYPE_P3_10G_TP;
+			board_type = QLCNIC_BRDTYPE_P3P_10G_TP;
 	}
 
 	switch (board_type) {
-	case QLCNIC_BRDTYPE_P3_HMEZ:
-	case QLCNIC_BRDTYPE_P3_XG_LOM:
-	case QLCNIC_BRDTYPE_P3_10G_CX4:
-	case QLCNIC_BRDTYPE_P3_10G_CX4_LP:
-	case QLCNIC_BRDTYPE_P3_IMEZ:
-	case QLCNIC_BRDTYPE_P3_10G_SFP_PLUS:
-	case QLCNIC_BRDTYPE_P3_10G_SFP_CT:
-	case QLCNIC_BRDTYPE_P3_10G_SFP_QT:
-	case QLCNIC_BRDTYPE_P3_10G_XFP:
-	case QLCNIC_BRDTYPE_P3_10000_BASE_T:
+	case QLCNIC_BRDTYPE_P3P_HMEZ:
+	case QLCNIC_BRDTYPE_P3P_XG_LOM:
+	case QLCNIC_BRDTYPE_P3P_10G_CX4:
+	case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
+	case QLCNIC_BRDTYPE_P3P_IMEZ:
+	case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
+	case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
+	case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
+	case QLCNIC_BRDTYPE_P3P_10G_XFP:
+	case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
 		adapter->ahw.port_type = QLCNIC_XGBE;
 		break;
-	case QLCNIC_BRDTYPE_P3_REF_QG:
-	case QLCNIC_BRDTYPE_P3_4_GB:
-	case QLCNIC_BRDTYPE_P3_4_GB_MM:
+	case QLCNIC_BRDTYPE_P3P_REF_QG:
+	case QLCNIC_BRDTYPE_P3P_4_GB:
+	case QLCNIC_BRDTYPE_P3P_4_GB_MM:
 		adapter->ahw.port_type = QLCNIC_GBE;
 		break;
-	case QLCNIC_BRDTYPE_P3_10G_TP:
+	case QLCNIC_BRDTYPE_P3P_10G_TP:
 		adapter->ahw.port_type = (adapter->portnum < 2) ?
 			QLCNIC_XGBE : QLCNIC_GBE;
 		break;
@@ -1245,4 +1285,5 @@
 		mode = VPORT_MISS_MODE_ACCEPT_MULTI;
 
 	qlcnic_nic_set_promisc(adapter, mode);
+	msleep(1000);
 }
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 75ba744..0d180c6 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -25,6 +25,7 @@
 #include <linux/netdevice.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/if_vlan.h>
 #include "qlcnic.h"
 
 struct crb_addr_pair {
@@ -45,6 +46,9 @@
 qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
 		struct qlcnic_host_rds_ring *rds_ring);
 
+static int
+qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter);
+
 static void crb_addr_transform_setup(void)
 {
 	crb_addr_transform(XDMA);
@@ -136,8 +140,6 @@
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 		rds_ring = &recv_ctx->rds_rings[ring];
 
-		spin_lock(&rds_ring->lock);
-
 		INIT_LIST_HEAD(&rds_ring->free_list);
 
 		rx_buf = rds_ring->rx_buf_arr;
@@ -146,8 +148,6 @@
 					&rds_ring->free_list);
 			rx_buf++;
 		}
-
-		spin_unlock(&rds_ring->lock);
 	}
 }
 
@@ -259,14 +259,14 @@
 		switch (ring) {
 		case RCV_RING_NORMAL:
 			rds_ring->num_desc = adapter->num_rxd;
-			rds_ring->dma_size = QLCNIC_P3_RX_BUF_MAX_LEN;
+			rds_ring->dma_size = QLCNIC_P3P_RX_BUF_MAX_LEN;
 			rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN;
 			break;
 
 		case RCV_RING_JUMBO:
 			rds_ring->num_desc = adapter->num_jumbo_rxd;
 			rds_ring->dma_size =
-				QLCNIC_P3_RX_JUMBO_BUF_MAX_LEN;
+				QLCNIC_P3P_RX_JUMBO_BUF_MAX_LEN;
 
 			if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
 				rds_ring->dma_size += QLCNIC_LRO_BUFFER_EXTRA;
@@ -439,11 +439,14 @@
 	u32 off;
 	struct pci_dev *pdev = adapter->pdev;
 
-	/* resetall */
+	QLCWR32(adapter, CRB_CMDPEG_STATE, 0);
+	QLCWR32(adapter, CRB_RCVPEG_STATE, 0);
+
 	qlcnic_rom_lock(adapter);
 	QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff);
 	qlcnic_rom_unlock(adapter);
 
+	/* Init HW CRB block */
 	if (qlcnic_rom_fast_read(adapter, 0, &n) != 0 || (n != 0xcafecafe) ||
 			qlcnic_rom_fast_read(adapter, 4, &n) != 0) {
 		dev_err(&pdev->dev, "ERROR Reading crb_init area: val:%x\n", n);
@@ -524,13 +527,10 @@
 	}
 	kfree(buf);
 
-	/* p2dn replyCount */
+	/* Initialize protocol process engine */
 	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0xec, 0x1e);
-	/* disable_peg_cache 0 & 1*/
 	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0x4c, 8);
 	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_I + 0x4c, 8);
-
-	/* peg_clr_all */
 	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x8, 0);
 	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0xc, 0);
 	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x8, 0);
@@ -539,9 +539,87 @@
 	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0xc, 0);
 	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x8, 0);
 	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0xc, 0);
+	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x8, 0);
+	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0xc, 0);
+	msleep(1);
+	QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0);
+	QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0);
 	return 0;
 }
 
+static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter)
+{
+	u32 val;
+	int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;
+
+	do {
+		val = QLCRD32(adapter, CRB_CMDPEG_STATE);
+
+		switch (val) {
+		case PHAN_INITIALIZE_COMPLETE:
+		case PHAN_INITIALIZE_ACK:
+			return 0;
+		case PHAN_INITIALIZE_FAILED:
+			goto out_err;
+		default:
+			break;
+		}
+
+		msleep(QLCNIC_CMDPEG_CHECK_DELAY);
+
+	} while (--retries);
+
+	QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
+
+out_err:
+	dev_err(&adapter->pdev->dev, "Command Peg initialization not "
+		      "complete, state: 0x%x.\n", val);
+	return -EIO;
+}
+
+static int
+qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter)
+{
+	u32 val;
+	int retries = QLCNIC_RCVPEG_CHECK_RETRY_COUNT;
+
+	do {
+		val = QLCRD32(adapter, CRB_RCVPEG_STATE);
+
+		if (val == PHAN_PEG_RCV_INITIALIZED)
+			return 0;
+
+		msleep(QLCNIC_RCVPEG_CHECK_DELAY);
+
+	} while (--retries);
+
+	if (!retries) {
+		dev_err(&adapter->pdev->dev, "Receive Peg initialization not "
+			      "complete, state: 0x%x.\n", val);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
+qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
+{
+	int err;
+
+	err = qlcnic_cmd_peg_ready(adapter);
+	if (err)
+		return err;
+
+	err = qlcnic_receive_peg_ready(adapter);
+	if (err)
+		return err;
+
+	QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
+
+	return err;
+}
+
 int
 qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
 
@@ -557,12 +635,12 @@
 	}
 	adapter->physical_port = (val >> 2);
 	if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo))
-		timeo = 30;
+		timeo = QLCNIC_INIT_TIMEOUT_SECS;
 
 	adapter->dev_init_timeo = timeo;
 
 	if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DRV_RESET_TIMEOUT, &timeo))
-		timeo = 10;
+		timeo = QLCNIC_RESET_TIMEOUT_SECS;
 
 	adapter->reset_ack_timeo = timeo;
 
@@ -906,55 +984,48 @@
 	return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24);
 }
 
+static void qlcnic_rom_lock_recovery(struct qlcnic_adapter *adapter)
+{
+	if (qlcnic_pcie_sem_lock(adapter, 2, QLCNIC_ROM_LOCK_ID))
+		dev_info(&adapter->pdev->dev, "Resetting rom_lock\n");
+
+	qlcnic_pcie_sem_unlock(adapter, 2);
+}
+
+static int
+qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter)
+{
+	u32 heartbeat, ret = -EIO;
+	int retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;
+
+	adapter->heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+
+	do {
+		msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
+		heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+		if (heartbeat != adapter->heartbeat) {
+			ret = QLCNIC_RCODE_SUCCESS;
+			break;
+		}
+	} while (--retries);
+
+	return ret;
+}
+
 int
 qlcnic_need_fw_reset(struct qlcnic_adapter *adapter)
 {
-	u32 count, old_count;
-	u32 val, version, major, minor, build;
-	int i, timeout;
+	if (qlcnic_check_fw_hearbeat(adapter)) {
+		qlcnic_rom_lock_recovery(adapter);
+		return 1;
+	}
 
 	if (adapter->need_fw_reset)
 		return 1;
 
-	/* last attempt had failed */
-	if (QLCRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED)
+	if (adapter->fw)
 		return 1;
 
-	old_count = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
-
-	for (i = 0; i < 10; i++) {
-
-		timeout = msleep_interruptible(200);
-		if (timeout) {
-			QLCWR32(adapter, CRB_CMDPEG_STATE,
-					PHAN_INITIALIZE_FAILED);
-			return -EINTR;
-		}
-
-		count = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
-		if (count != old_count)
-			break;
-	}
-
-	/* firmware is dead */
-	if (count == old_count)
-		return 1;
-
-	/* check if we have got newer or different file firmware */
-	if (adapter->fw) {
-
-		val = qlcnic_get_fw_version(adapter);
-
-		version = QLCNIC_DECODE_VERSION(val);
-
-		major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
-		minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
-		build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
-
-		if (version > QLCNIC_VERSION_CODE(major, minor, build))
-			return 1;
-	}
-
 	return 0;
 }
 
@@ -1089,18 +1160,6 @@
 		return -EINVAL;
 	}
 
-	/* check if flashed firmware is newer */
-	if (qlcnic_rom_fast_read(adapter,
-			QLCNIC_FW_VERSION_OFFSET, (int *)&val))
-		return -EIO;
-
-	val = QLCNIC_DECODE_VERSION(val);
-	if (val > ver) {
-		dev_info(&pdev->dev, "%s: firmware is older than flash\n",
-				fw_name[fw_type]);
-		return -EINVAL;
-	}
-
 	QLCWR32(adapter, QLCNIC_CAM_RAM(0x1fc), QLCNIC_BDINFO_MAGIC);
 	return 0;
 }
@@ -1162,78 +1221,6 @@
 	adapter->fw = NULL;
 }
 
-static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter)
-{
-	u32 val;
-	int retries = 60;
-
-	do {
-		val = QLCRD32(adapter, CRB_CMDPEG_STATE);
-
-		switch (val) {
-		case PHAN_INITIALIZE_COMPLETE:
-		case PHAN_INITIALIZE_ACK:
-			return 0;
-		case PHAN_INITIALIZE_FAILED:
-			goto out_err;
-		default:
-			break;
-		}
-
-		msleep(500);
-
-	} while (--retries);
-
-	QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
-
-out_err:
-	dev_err(&adapter->pdev->dev, "Command Peg initialization not "
-		      "complete, state: 0x%x.\n", val);
-	return -EIO;
-}
-
-static int
-qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter)
-{
-	u32 val;
-	int retries = 2000;
-
-	do {
-		val = QLCRD32(adapter, CRB_RCVPEG_STATE);
-
-		if (val == PHAN_PEG_RCV_INITIALIZED)
-			return 0;
-
-		msleep(10);
-
-	} while (--retries);
-
-	if (!retries) {
-		dev_err(&adapter->pdev->dev, "Receive Peg initialization not "
-			      "complete, state: 0x%x.\n", val);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-int qlcnic_init_firmware(struct qlcnic_adapter *adapter)
-{
-	int err;
-
-	err = qlcnic_cmd_peg_ready(adapter);
-	if (err)
-		return err;
-
-	err = qlcnic_receive_peg_ready(adapter);
-	if (err)
-		return err;
-
-	QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
-
-	return err;
-}
-
 static void
 qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
 				struct qlcnic_fw_msg *msg)
@@ -1316,7 +1303,7 @@
 		return -ENOMEM;
 	}
 
-	skb_reserve(skb, 2);
+	skb_reserve(skb, NET_IP_ALIGN);
 
 	dma = pci_map_single(pdev, skb->data,
 			rds_ring->dma_size, PCI_DMA_FROMDEVICE);
@@ -1351,11 +1338,12 @@
 
 	skb = buffer->skb;
 
-	if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) {
+	if (likely(adapter->rx_csum && (cksum == STATUS_CKSUM_OK ||
+						cksum == STATUS_CKSUM_LOOP))) {
 		adapter->stats.csummed++;
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	} else {
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 	}
 
 	skb->dev = adapter->netdev;
@@ -1365,6 +1353,31 @@
 	return skb;
 }
 
+static int
+qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb,
+			u16 *vlan_tag)
+{
+	struct ethhdr *eth_hdr;
+
+	if (!__vlan_get_tag(skb, vlan_tag)) {
+		eth_hdr = (struct ethhdr *) skb->data;
+		memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
+		skb_pull(skb, VLAN_HLEN);
+	}
+	if (!adapter->pvid)
+		return 0;
+
+	if (*vlan_tag == adapter->pvid) {
+		/* Outer vlan tag. Packet should follow non-vlan path */
+		*vlan_tag = 0xffff;
+		return 0;
+	}
+	if (adapter->flags & QLCNIC_TAGGING_ENABLED)
+		return 0;
+
+	return -EINVAL;
+}
+
 static struct qlcnic_rx_buffer *
 qlcnic_process_rcv(struct qlcnic_adapter *adapter,
 		struct qlcnic_host_sds_ring *sds_ring,
@@ -1376,6 +1389,7 @@
 	struct sk_buff *skb;
 	struct qlcnic_host_rds_ring *rds_ring;
 	int index, length, cksum, pkt_offset;
+	u16 vid = 0xffff;
 
 	if (unlikely(ring >= adapter->max_rds_rings))
 		return NULL;
@@ -1404,10 +1418,18 @@
 	if (pkt_offset)
 		skb_pull(skb, pkt_offset);
 
-	skb->truesize = skb->len + sizeof(struct sk_buff);
+	if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+		adapter->stats.rxdropped++;
+		dev_kfree_skb(skb);
+		return buffer;
+	}
+
 	skb->protocol = eth_type_trans(skb, netdev);
 
-	napi_gro_receive(&sds_ring->napi, skb);
+	if ((vid != 0xffff) && adapter->vlgrp)
+		vlan_gro_receive(&sds_ring->napi, adapter->vlgrp, vid, skb);
+	else
+		napi_gro_receive(&sds_ring->napi, skb);
 
 	adapter->stats.rx_pkts++;
 	adapter->stats.rxbytes += length;
@@ -1436,6 +1458,7 @@
 	int index;
 	u16 lro_length, length, data_offset;
 	u32 seq_number;
+	u16 vid = 0xffff;
 
 	if (unlikely(ring > adapter->max_rds_rings))
 		return NULL;
@@ -1466,9 +1489,14 @@
 
 	skb_put(skb, lro_length + data_offset);
 
-	skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb);
-
 	skb_pull(skb, l2_hdr_offset);
+
+	if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+		adapter->stats.rxdropped++;
+		dev_kfree_skb(skb);
+		return buffer;
+	}
+
 	skb->protocol = eth_type_trans(skb, netdev);
 
 	iph = (struct iphdr *)skb->data;
@@ -1483,7 +1511,10 @@
 
 	length = skb->len;
 
-	netif_receive_skb(skb);
+	if ((vid != 0xffff) && adapter->vlgrp)
+		vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vid);
+	else
+		netif_receive_skb(skb);
 
 	adapter->stats.lro_pkts++;
 	adapter->stats.lrobytes += length;
@@ -1587,8 +1618,6 @@
 	int producer, count = 0;
 	struct list_head *head;
 
-	spin_lock(&rds_ring->lock);
-
 	producer = rds_ring->producer;
 
 	head = &rds_ring->free_list;
@@ -1618,7 +1647,6 @@
 		writel((producer-1) & (rds_ring->num_desc-1),
 				rds_ring->crb_rcv_producer);
 	}
-	spin_unlock(&rds_ring->lock);
 }
 
 static void
@@ -1665,6 +1693,18 @@
 	spin_unlock(&rds_ring->lock);
 }
 
+static void dump_skb(struct sk_buff *skb)
+{
+	int i;
+	unsigned char *data = skb->data;
+
+	for (i = 0; i < skb->len; i++) {
+		printk("%02x ", data[i]);
+		if ((i & 0x0f) == 8)
+			printk("\n");
+	}
+}
+
 static struct qlcnic_rx_buffer *
 qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
 		struct qlcnic_host_sds_ring *sds_ring,
@@ -1695,15 +1735,18 @@
 	if (!skb)
 		return buffer;
 
-	skb_put(skb, rds_ring->skb_size);
+	if (length > rds_ring->skb_size)
+		skb_put(skb, rds_ring->skb_size);
+	else
+		skb_put(skb, length);
 
 	if (pkt_offset)
 		skb_pull(skb, pkt_offset);
 
-	skb->truesize = skb->len + sizeof(struct sk_buff);
-
 	if (!qlcnic_check_loopback_buff(skb->data))
 		adapter->diag_cnt++;
+	else
+		dump_skb(skb);
 
 	dev_kfree_skb_any(skb);
 	adapter->stats.rx_pkts++;
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 66eea59..f047c7c 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -28,6 +28,7 @@
 
 #include "qlcnic.h"
 
+#include <linux/swab.h>
 #include <linux/dma-mapping.h>
 #include <linux/if_vlan.h>
 #include <net/ip.h>
@@ -45,10 +46,10 @@
 static const char qlcnic_driver_string[] = "QLogic 1/10 GbE "
 	"Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID;
 
-static int port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
-
-/* Default to restricted 1G auto-neg mode */
-static int wol_port_mode = 5;
+static struct workqueue_struct *qlcnic_wq;
+static int qlcnic_mac_learn;
+module_param(qlcnic_mac_learn, int, 0644);
+MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
 
 static int use_msi = 1;
 module_param(use_msi, int, 0644);
@@ -94,7 +95,7 @@
 static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
 
 static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
-static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter);
+static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8);
 static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
 
 static irqreturn_t qlcnic_tmp_intr(int irq, void *data);
@@ -103,13 +104,17 @@
 static irqreturn_t qlcnic_msix_intr(int irq, void *data);
 
 static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
-static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long);
+static void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long);
 static int qlcnic_start_firmware(struct qlcnic_adapter *);
 
+static void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
+static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
 static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
 static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
 static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
 static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
+static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
+				struct qlcnic_esw_func_cfg *);
 /*  PCI Device ID Table  */
 #define ENTRY(device) \
 	{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
@@ -164,7 +169,7 @@
 
 	recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL);
 
-	return (recv_ctx->sds_rings == NULL);
+	return recv_ctx->sds_rings == NULL;
 }
 
 static void
@@ -255,40 +260,6 @@
 	memset(&adapter->stats, 0, sizeof(adapter->stats));
 }
 
-static void qlcnic_set_port_mode(struct qlcnic_adapter *adapter)
-{
-	u32 val, data;
-
-	val = adapter->ahw.board_type;
-	if ((val == QLCNIC_BRDTYPE_P3_HMEZ) ||
-		(val == QLCNIC_BRDTYPE_P3_XG_LOM)) {
-		if (port_mode == QLCNIC_PORT_MODE_802_3_AP) {
-			data = QLCNIC_PORT_MODE_802_3_AP;
-			QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
-		} else if (port_mode == QLCNIC_PORT_MODE_XG) {
-			data = QLCNIC_PORT_MODE_XG;
-			QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
-		} else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_1G) {
-			data = QLCNIC_PORT_MODE_AUTO_NEG_1G;
-			QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
-		} else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_XG) {
-			data = QLCNIC_PORT_MODE_AUTO_NEG_XG;
-			QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
-		} else {
-			data = QLCNIC_PORT_MODE_AUTO_NEG;
-			QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
-		}
-
-		if ((wol_port_mode != QLCNIC_PORT_MODE_802_3_AP) &&
-			(wol_port_mode != QLCNIC_PORT_MODE_XG) &&
-			(wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_1G) &&
-			(wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_XG)) {
-			wol_port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
-		}
-		QLCWR32(adapter, QLCNIC_WOL_PORT_MODE, wol_port_mode);
-	}
-}
-
 static void qlcnic_set_msix_bit(struct pci_dev *pdev, int enable)
 {
 	u32 control;
@@ -320,7 +291,7 @@
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 
-	if (adapter->nic_ops->get_mac_addr(adapter, mac_addr) != 0)
+	if (qlcnic_get_mac_address(adapter, mac_addr) != 0)
 		return -EIO;
 
 	memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
@@ -341,6 +312,9 @@
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	struct sockaddr *addr = p;
 
+	if ((adapter->flags & QLCNIC_MAC_OVERRIDE_DISABLED))
+		return -EOPNOTSUPP;
+
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EINVAL;
 
@@ -360,6 +334,13 @@
 	return 0;
 }
 
+static void qlcnic_vlan_rx_register(struct net_device *netdev,
+		struct vlan_group *grp)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	adapter->vlgrp = grp;
+}
+
 static const struct net_device_ops qlcnic_netdev_ops = {
 	.ndo_open	   = qlcnic_open,
 	.ndo_stop	   = qlcnic_close,
@@ -370,20 +351,19 @@
 	.ndo_set_mac_address    = qlcnic_set_mac,
 	.ndo_change_mtu	   = qlcnic_change_mtu,
 	.ndo_tx_timeout	   = qlcnic_tx_timeout,
+	.ndo_vlan_rx_register = qlcnic_vlan_rx_register,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = qlcnic_poll_controller,
 #endif
 };
 
 static struct qlcnic_nic_template qlcnic_ops = {
-	.get_mac_addr = qlcnic_get_mac_address,
 	.config_bridged_mode = qlcnic_config_bridged_mode,
 	.config_led = qlcnic_config_led,
 	.start_firmware = qlcnic_start_firmware
 };
 
 static struct qlcnic_nic_template qlcnic_vf_ops = {
-	.get_mac_addr = qlcnic_get_mac_address,
 	.config_bridged_mode = qlcnicvf_config_bridged_mode,
 	.config_led = qlcnicvf_config_led,
 	.start_firmware = qlcnicvf_start_firmware
@@ -474,7 +454,7 @@
 qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
 {
 	struct qlcnic_pci_info *pci_info;
-	int i, ret = 0, err;
+	int i, ret = 0;
 	u8 pfn;
 
 	pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
@@ -484,14 +464,14 @@
 	adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
 				QLCNIC_MAX_PCI_FUNC, GFP_KERNEL);
 	if (!adapter->npars) {
-		err = -ENOMEM;
+		ret = -ENOMEM;
 		goto err_pci_info;
 	}
 
 	adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) *
 				QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL);
 	if (!adapter->eswitch) {
-		err = -ENOMEM;
+		ret = -ENOMEM;
 		goto err_npars;
 	}
 
@@ -503,10 +483,9 @@
 		pfn = pci_info[i].id;
 		if (pfn > QLCNIC_MAX_PCI_FUNC)
 			return QL_STATUS_INVALID_PARAM;
-		adapter->npars[pfn].active = pci_info[i].active;
-		adapter->npars[pfn].type = pci_info[i].type;
-		adapter->npars[pfn].phy_port = pci_info[i].default_port;
-		adapter->npars[pfn].mac_learning = DEFAULT_MAC_LEARN;
+		adapter->npars[pfn].active = (u8)pci_info[i].active;
+		adapter->npars[pfn].type = (u8)pci_info[i].type;
+		adapter->npars[pfn].phy_port = (u8)pci_info[i].default_port;
 		adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
 		adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
 	}
@@ -539,12 +518,10 @@
 	void __iomem *priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
 
 	/* If other drivers are not in use set their privilege level */
-	ref_count = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
+	ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
 	ret = qlcnic_api_lock(adapter);
 	if (ret)
 		goto err_lock;
-	if (QLC_DEV_CLR_REF_CNT(ref_count, adapter->ahw.pci_func))
-		goto err_npar;
 
 	if (qlcnic_config_npars) {
 		for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
@@ -562,18 +539,16 @@
 			adapter->ahw.pci_func));
 	}
 	writel(data, priv_op);
-err_npar:
 	qlcnic_api_unlock(adapter);
 err_lock:
 	return ret;
 }
 
-static u32
-qlcnic_get_driver_mode(struct qlcnic_adapter *adapter)
+static void
+qlcnic_check_vf(struct qlcnic_adapter *adapter)
 {
 	void __iomem *msix_base_addr;
 	void __iomem *priv_op;
-	struct qlcnic_info nic_info;
 	u32 func;
 	u32 msix_base;
 	u32 op_mode, priv_level;
@@ -588,20 +563,6 @@
 	func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
 	adapter->ahw.pci_func = func;
 
-	if (!qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func)) {
-		adapter->capabilities = nic_info.capabilities;
-
-		if (adapter->capabilities & BIT_6)
-			adapter->flags |= QLCNIC_ESWITCH_ENABLED;
-		else
-			adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
-	}
-
-	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))	{
-		adapter->nic_ops = &qlcnic_ops;
-		return adapter->fw_hal_version;
-	}
-
 	/* Determine function privilege level */
 	priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
 	op_mode = readl(priv_op);
@@ -610,37 +571,14 @@
 	else
 		priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
 
-	switch (priv_level) {
-	case QLCNIC_MGMT_FUNC:
-		adapter->op_mode = QLCNIC_MGMT_FUNC;
-		adapter->nic_ops = &qlcnic_ops;
-		qlcnic_init_pci_info(adapter);
-		/* Set privilege level for other functions */
-		qlcnic_set_function_modes(adapter);
-		dev_info(&adapter->pdev->dev,
-			"HAL Version: %d, Management function\n",
-			adapter->fw_hal_version);
-		break;
-	case QLCNIC_PRIV_FUNC:
-		adapter->op_mode = QLCNIC_PRIV_FUNC;
-		dev_info(&adapter->pdev->dev,
-			"HAL Version: %d, Privileged function\n",
-			adapter->fw_hal_version);
-		adapter->nic_ops = &qlcnic_ops;
-		break;
-	case QLCNIC_NON_PRIV_FUNC:
+	if (priv_level == QLCNIC_NON_PRIV_FUNC) {
 		adapter->op_mode = QLCNIC_NON_PRIV_FUNC;
 		dev_info(&adapter->pdev->dev,
 			"HAL Version: %d Non Privileged function\n",
 			adapter->fw_hal_version);
 		adapter->nic_ops = &qlcnic_vf_ops;
-		break;
-	default:
-		dev_info(&adapter->pdev->dev, "Unknown function mode: %d\n",
-			priv_level);
-		return 0;
-	}
-	return adapter->fw_hal_version;
+	} else
+		adapter->nic_ops = &qlcnic_ops;
 }
 
 static int
@@ -673,10 +611,7 @@
 	adapter->ahw.pci_base0 = mem_ptr0;
 	adapter->ahw.pci_len0 = pci_len0;
 
-	if (!qlcnic_get_driver_mode(adapter)) {
-		iounmap(adapter->ahw.pci_base0);
-		return -EIO;
-	}
+	qlcnic_check_vf(adapter);
 
 	adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter,
 		QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(adapter->ahw.pci_func)));
@@ -711,25 +646,7 @@
 qlcnic_check_options(struct qlcnic_adapter *adapter)
 {
 	u32 fw_major, fw_minor, fw_build;
-	char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
-	char serial_num[32];
-	int i, offset, val;
-	int *ptr32;
 	struct pci_dev *pdev = adapter->pdev;
-	struct qlcnic_info nic_info;
-	adapter->driver_mismatch = 0;
-
-	ptr32 = (int *)&serial_num;
-	offset = QLCNIC_FW_SERIAL_NUM_OFFSET;
-	for (i = 0; i < 8; i++) {
-		if (qlcnic_rom_fast_read(adapter, offset, &val) == -1) {
-			dev_err(&pdev->dev, "error reading board info\n");
-			adapter->driver_mismatch = 1;
-			return;
-		}
-		ptr32[i] = cpu_to_le32(val);
-		offset += sizeof(u32);
-	}
 
 	fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
 	fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
@@ -737,19 +654,9 @@
 
 	adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
 
-	if (adapter->portnum == 0) {
-		get_brd_name(adapter, brd_name);
-
-		pr_info("%s: %s Board Chip rev 0x%x\n",
-				module_name(THIS_MODULE),
-				brd_name, adapter->ahw.revision_id);
-	}
-
 	dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
 			fw_major, fw_minor, fw_build);
 
-	adapter->flags &= ~QLCNIC_LRO_ENABLED;
-
 	if (adapter->ahw.port_type == QLCNIC_XGBE) {
 		adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
 		adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
@@ -758,136 +665,364 @@
 		adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
 	}
 
-	if (!qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func)) {
-		adapter->physical_port = nic_info.phys_port;
-		adapter->switch_mode = nic_info.switch_mode;
-		adapter->max_tx_ques = nic_info.max_tx_ques;
-		adapter->max_rx_ques = nic_info.max_rx_ques;
-		adapter->capabilities = nic_info.capabilities;
-		adapter->max_mac_filters = nic_info.max_mac_filters;
-		adapter->max_mtu = nic_info.max_mtu;
-	}
-
 	adapter->msix_supported = !!use_msi_x;
 	adapter->rss_supported = !!use_msi_x;
 
 	adapter->num_txd = MAX_CMD_DESCRIPTORS;
 
-	adapter->max_rds_rings = 2;
+	adapter->max_rds_rings = MAX_RDS_RINGS;
+}
+
+static int
+qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
+{
+	int err;
+	struct qlcnic_info nic_info;
+
+	err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func);
+	if (err)
+		return err;
+
+	adapter->physical_port = (u8)nic_info.phys_port;
+	adapter->switch_mode = nic_info.switch_mode;
+	adapter->max_tx_ques = nic_info.max_tx_ques;
+	adapter->max_rx_ques = nic_info.max_rx_ques;
+	adapter->capabilities = nic_info.capabilities;
+	adapter->max_mac_filters = nic_info.max_mac_filters;
+	adapter->max_mtu = nic_info.max_mtu;
+
+	if (adapter->capabilities & BIT_6)
+		adapter->flags |= QLCNIC_ESWITCH_ENABLED;
+	else
+		adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
+
+	return err;
+}
+
+static void
+qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
+		struct qlcnic_esw_func_cfg *esw_cfg)
+{
+	if (esw_cfg->discard_tagged)
+		adapter->flags &= ~QLCNIC_TAGGING_ENABLED;
+	else
+		adapter->flags |= QLCNIC_TAGGING_ENABLED;
+
+	if (esw_cfg->vlan_id)
+		adapter->pvid = esw_cfg->vlan_id;
+	else
+		adapter->pvid = 0;
+}
+
+static void
+qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
+		struct qlcnic_esw_func_cfg *esw_cfg)
+{
+	adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED |
+				QLCNIC_PROMISC_DISABLED);
+
+	if (esw_cfg->mac_anti_spoof)
+		adapter->flags |= QLCNIC_MACSPOOF;
+
+	if (!esw_cfg->mac_override)
+		adapter->flags |= QLCNIC_MAC_OVERRIDE_DISABLED;
+
+	if (!esw_cfg->promisc_mode)
+		adapter->flags |= QLCNIC_PROMISC_DISABLED;
+
+	qlcnic_set_netdev_features(adapter, esw_cfg);
+}
+
+static int
+qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_esw_func_cfg esw_cfg;
+
+	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+		return 0;
+
+	esw_cfg.pci_func = adapter->ahw.pci_func;
+	if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg))
+			return -EIO;
+	qlcnic_set_vlan_config(adapter, &esw_cfg);
+	qlcnic_set_eswitch_port_features(adapter, &esw_cfg);
+
+	return 0;
+}
+
+static void
+qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
+		struct qlcnic_esw_func_cfg *esw_cfg)
+{
+	struct net_device *netdev = adapter->netdev;
+	unsigned long features, vlan_features;
+
+	features = (NETIF_F_SG | NETIF_F_IP_CSUM |
+			NETIF_F_IPV6_CSUM | NETIF_F_GRO);
+	vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
+			NETIF_F_IPV6_CSUM);
+
+	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
+		features |= (NETIF_F_TSO | NETIF_F_TSO6);
+		vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
+	}
+	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+		features |= NETIF_F_LRO;
+
+	if (esw_cfg->offload_flags & BIT_0) {
+		netdev->features |= features;
+		adapter->rx_csum = 1;
+		if (!(esw_cfg->offload_flags & BIT_1))
+			netdev->features &= ~NETIF_F_TSO;
+		if (!(esw_cfg->offload_flags & BIT_2))
+			netdev->features &= ~NETIF_F_TSO6;
+	} else {
+		netdev->features &= ~features;
+		adapter->rx_csum = 0;
+	}
+
+	netdev->vlan_features = (features & vlan_features);
+}
+
+static int
+qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
+{
+	void __iomem *priv_op;
+	u32 op_mode, priv_level;
+	int err = 0;
+
+	err = qlcnic_initialize_nic(adapter);
+	if (err)
+		return err;
+
+	if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED)
+		return 0;
+
+	priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
+	op_mode = readl(priv_op);
+	priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
+
+	if (op_mode == QLC_DEV_DRV_DEFAULT)
+		priv_level = QLCNIC_MGMT_FUNC;
+	else
+		priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
+
+	if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
+		if (priv_level == QLCNIC_MGMT_FUNC) {
+			adapter->op_mode = QLCNIC_MGMT_FUNC;
+			err = qlcnic_init_pci_info(adapter);
+			if (err)
+				return err;
+			/* Set privilege level for other functions */
+			qlcnic_set_function_modes(adapter);
+			dev_info(&adapter->pdev->dev,
+				"HAL Version: %d, Management function\n",
+				adapter->fw_hal_version);
+		} else if (priv_level == QLCNIC_PRIV_FUNC) {
+			adapter->op_mode = QLCNIC_PRIV_FUNC;
+			dev_info(&adapter->pdev->dev,
+				"HAL Version: %d, Privileged function\n",
+				adapter->fw_hal_version);
+		}
+	}
+
+	adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
+
+	return err;
+}
+
+static int
+qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_esw_func_cfg esw_cfg;
+	struct qlcnic_npar_info *npar;
+	u8 i;
+
+	if (adapter->need_fw_reset)
+		return 0;
+
+	for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+		if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+			continue;
+		memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg));
+		esw_cfg.pci_func = i;
+		esw_cfg.offload_flags = BIT_0;
+		esw_cfg.mac_override = BIT_0;
+		esw_cfg.promisc_mode = BIT_0;
+		if (adapter->capabilities  & QLCNIC_FW_CAPABILITY_TSO)
+			esw_cfg.offload_flags |= (BIT_1 | BIT_2);
+		if (qlcnic_config_switch_port(adapter, &esw_cfg))
+			return -EIO;
+		npar = &adapter->npars[i];
+		npar->pvid = esw_cfg.vlan_id;
+		npar->mac_override = esw_cfg.mac_override;
+		npar->mac_anti_spoof = esw_cfg.mac_anti_spoof;
+		npar->discard_tagged = esw_cfg.discard_tagged;
+		npar->promisc_mode = esw_cfg.promisc_mode;
+		npar->offload_flags = esw_cfg.offload_flags;
+	}
+
+	return 0;
+}
+
+static int
+qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter,
+			struct qlcnic_npar_info *npar, int pci_func)
+{
+	struct qlcnic_esw_func_cfg esw_cfg;
+	esw_cfg.op_mode = QLCNIC_PORT_DEFAULTS;
+	esw_cfg.pci_func = pci_func;
+	esw_cfg.vlan_id = npar->pvid;
+	esw_cfg.mac_override = npar->mac_override;
+	esw_cfg.discard_tagged = npar->discard_tagged;
+	esw_cfg.mac_anti_spoof = npar->mac_anti_spoof;
+	esw_cfg.offload_flags = npar->offload_flags;
+	esw_cfg.promisc_mode = npar->promisc_mode;
+	if (qlcnic_config_switch_port(adapter, &esw_cfg))
+		return -EIO;
+
+	esw_cfg.op_mode = QLCNIC_ADD_VLAN;
+	if (qlcnic_config_switch_port(adapter, &esw_cfg))
+		return -EIO;
+
+	return 0;
 }
 
 static int
 qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
 {
-	int i, err = 0;
+	int i, err;
 	struct qlcnic_npar_info *npar;
 	struct qlcnic_info nic_info;
 
-	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
-	    !adapter->need_fw_reset)
+	if (!adapter->need_fw_reset)
 		return 0;
 
-	if (adapter->op_mode == QLCNIC_MGMT_FUNC) {
-		/* Set the NPAR config data after FW reset */
-		for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
-			npar = &adapter->npars[i];
-			if (npar->type != QLCNIC_TYPE_NIC)
-				continue;
-			err = qlcnic_get_nic_info(adapter, &nic_info, i);
-			if (err)
-				goto err_out;
-			nic_info.min_tx_bw = npar->min_bw;
-			nic_info.max_tx_bw = npar->max_bw;
-			err = qlcnic_set_nic_info(adapter, &nic_info);
-			if (err)
-				goto err_out;
+	/* Set the NPAR config data after FW reset */
+	for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+		npar = &adapter->npars[i];
+		if (npar->type != QLCNIC_TYPE_NIC)
+			continue;
+		err = qlcnic_get_nic_info(adapter, &nic_info, i);
+		if (err)
+			return err;
+		nic_info.min_tx_bw = npar->min_bw;
+		nic_info.max_tx_bw = npar->max_bw;
+		err = qlcnic_set_nic_info(adapter, &nic_info);
+		if (err)
+			return err;
 
-			if (npar->enable_pm) {
-				err = qlcnic_config_port_mirroring(adapter,
-						npar->dest_npar, 1, i);
-				if (err)
-					goto err_out;
-
-			}
-			npar->mac_learning = DEFAULT_MAC_LEARN;
-			npar->host_vlan_tag = 0;
-			npar->promisc_mode = 0;
-			npar->discard_tagged = 0;
-			npar->vlan_id = 0;
+		if (npar->enable_pm) {
+			err = qlcnic_config_port_mirroring(adapter,
+							npar->dest_npar, 1, i);
+			if (err)
+				return err;
 		}
+		err = qlcnic_reset_eswitch_config(adapter, npar, i);
+		if (err)
+			return err;
 	}
-err_out:
+	return 0;
+}
+
+static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter)
+{
+	u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO;
+	u32 npar_state;
+
+	if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+		return 0;
+
+	npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+	while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) {
+		msleep(1000);
+		npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+	}
+	if (!npar_opt_timeo) {
+		dev_err(&adapter->pdev->dev,
+			"Waiting for NPAR state to opertional timeout\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int
+qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
+{
+	int err;
+
+	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
+		    adapter->op_mode != QLCNIC_MGMT_FUNC)
+		return 0;
+
+	err = qlcnic_set_default_offload_settings(adapter);
+	if (err)
+		return err;
+
+	err = qlcnic_reset_npar_config(adapter);
+	if (err)
+		return err;
+
+	qlcnic_dev_set_npar_ready(adapter);
+
 	return err;
 }
 
 static int
 qlcnic_start_firmware(struct qlcnic_adapter *adapter)
 {
-	int val, err, first_boot;
+	int err;
 
 	err = qlcnic_can_start_firmware(adapter);
 	if (err < 0)
 		return err;
 	else if (!err)
-		goto wait_init;
-
-	first_boot = QLCRD32(adapter, QLCNIC_CAM_RAM(0x1fc));
-	if (first_boot == 0x55555555)
-		/* This is the first boot after power up */
-		QLCWR32(adapter, QLCNIC_CAM_RAM(0x1fc), QLCNIC_BDINFO_MAGIC);
+		goto check_fw_status;
 
 	if (load_fw_file)
 		qlcnic_request_firmware(adapter);
 	else {
-		if (qlcnic_check_flash_fw_ver(adapter))
+		err = qlcnic_check_flash_fw_ver(adapter);
+		if (err)
 			goto err_out;
 
 		adapter->fw_type = QLCNIC_FLASH_ROMIMAGE;
 	}
 
 	err = qlcnic_need_fw_reset(adapter);
-	if (err < 0)
-		goto err_out;
 	if (err == 0)
-		goto wait_init;
+		goto check_fw_status;
 
-	if (first_boot != 0x55555555) {
-		QLCWR32(adapter, CRB_CMDPEG_STATE, 0);
-		QLCWR32(adapter, CRB_RCVPEG_STATE, 0);
-		qlcnic_pinit_from_rom(adapter);
-		msleep(1);
-	}
-
-	QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0);
-	QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0);
-
-	qlcnic_set_port_mode(adapter);
+	err = qlcnic_pinit_from_rom(adapter);
+	if (err)
+		goto err_out;
 
 	err = qlcnic_load_firmware(adapter);
 	if (err)
 		goto err_out;
 
 	qlcnic_release_firmware(adapter);
+	QLCWR32(adapter, CRB_DRIVER_VERSION, QLCNIC_DRIVER_VERSION);
 
-	val = (_QLCNIC_LINUX_MAJOR << 16)
-		| ((_QLCNIC_LINUX_MINOR << 8))
-		| (_QLCNIC_LINUX_SUBVERSION);
-	QLCWR32(adapter, CRB_DRIVER_VERSION, val);
-
-wait_init:
-	/* Handshake with the card before we register the devices. */
-	err = qlcnic_init_firmware(adapter);
+check_fw_status:
+	err = qlcnic_check_fw_status(adapter);
 	if (err)
 		goto err_out;
 
 	QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
 	qlcnic_idc_debug_info(adapter, 1);
 
-	qlcnic_check_options(adapter);
-	if (qlcnic_reset_npar_config(adapter))
+	err = qlcnic_check_eswitch_mode(adapter);
+	if (err) {
+		dev_err(&adapter->pdev->dev,
+			"Memory allocation failed for eswitch\n");
 		goto err_out;
-	qlcnic_dev_set_npar_ready(adapter);
+	}
+	err = qlcnic_set_mgmt_operations(adapter);
+	if (err)
+		goto err_out;
 
+	qlcnic_check_options(adapter);
 	adapter->need_fw_reset = 0;
 
 	qlcnic_release_firmware(adapter);
@@ -896,6 +1031,7 @@
 err_out:
 	QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
 	dev_err(&adapter->pdev->dev, "Device state set to failed\n");
+
 	qlcnic_release_firmware(adapter);
 	return err;
 }
@@ -979,6 +1115,8 @@
 
 	if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
 		return 0;
+	if (qlcnic_set_eswitch_port_config(adapter))
+		return -EIO;
 
 	if (qlcnic_fw_create_ctx(adapter))
 		return -EIO;
@@ -998,7 +1136,7 @@
 
 	qlcnic_config_intr_coalesce(adapter);
 
-	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+	if (netdev->features & NETIF_F_LRO)
 		qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED);
 
 	qlcnic_napi_enable(adapter);
@@ -1041,6 +1179,9 @@
 
 	qlcnic_free_mac_list(adapter);
 
+	if (adapter->fhash.fnum)
+		qlcnic_delete_lb_filters(adapter);
+
 	qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);
 
 	qlcnic_napi_disable(adapter);
@@ -1277,7 +1418,7 @@
 	SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
 
 	netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
-		NETIF_F_IPV6_CSUM | NETIF_F_GRO);
+		NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_HW_VLAN_RX);
 	netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
 		NETIF_F_IPV6_CSUM);
 
@@ -1296,12 +1437,8 @@
 
 	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
 		netdev->features |= NETIF_F_LRO;
-
 	netdev->irq = adapter->msix_entries[0].vector;
 
-	if (qlcnic_read_mac_addr(adapter))
-		dev_warn(&pdev->dev, "failed to read mac addr\n");
-
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
 
@@ -1338,6 +1475,7 @@
 	int err;
 	uint8_t revision_id;
 	uint8_t pci_using_dac;
+	char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
 
 	err = pci_enable_device(pdev);
 	if (err)
@@ -1395,10 +1533,8 @@
 		goto err_out_iounmap;
 	}
 
-	if (qlcnic_read_mac_addr(adapter))
-		dev_warn(&pdev->dev, "failed to read mac addr\n");
-
-	if (qlcnic_setup_idc_param(adapter))
+	err = qlcnic_setup_idc_param(adapter);
+	if (err)
 		goto err_out_iounmap;
 
 	err = adapter->nic_ops->start_firmware(adapter);
@@ -1407,6 +1543,17 @@
 		goto err_out_decr_ref;
 	}
 
+	if (qlcnic_read_mac_addr(adapter))
+		dev_warn(&pdev->dev, "failed to read mac addr\n");
+
+	if (adapter->portnum == 0) {
+		get_brd_name(adapter, brd_name);
+
+		pr_info("%s: %s Board Chip rev 0x%x\n",
+				module_name(THIS_MODULE),
+				brd_name, adapter->ahw.revision_id);
+	}
+
 	qlcnic_clear_stats(adapter);
 
 	qlcnic_setup_intr(adapter);
@@ -1430,6 +1577,7 @@
 		break;
 	}
 
+	qlcnic_alloc_lb_filters_mem(adapter);
 	qlcnic_create_diag_entries(adapter);
 
 	return 0;
@@ -1438,7 +1586,7 @@
 	qlcnic_teardown_intr(adapter);
 
 err_out_decr_ref:
-	qlcnic_clr_all_drv_state(adapter);
+	qlcnic_clr_all_drv_state(adapter, 0);
 
 err_out_iounmap:
 	qlcnic_cleanup_pci_map(adapter);
@@ -1477,10 +1625,12 @@
 	if (adapter->eswitch != NULL)
 		kfree(adapter->eswitch);
 
-	qlcnic_clr_all_drv_state(adapter);
+	qlcnic_clr_all_drv_state(adapter, 0);
 
 	clear_bit(__QLCNIC_RESETTING, &adapter->state);
 
+	qlcnic_free_lb_filters_mem(adapter);
+
 	qlcnic_teardown_intr(adapter);
 
 	qlcnic_remove_diag_entries(adapter);
@@ -1509,7 +1659,7 @@
 	if (netif_running(netdev))
 		qlcnic_down(adapter, netdev);
 
-	qlcnic_clr_all_drv_state(adapter);
+	qlcnic_clr_all_drv_state(adapter, 0);
 
 	clear_bit(__QLCNIC_RESETTING, &adapter->state);
 
@@ -1573,7 +1723,7 @@
 		if (err)
 			goto done;
 
-		qlcnic_config_indev_addr(netdev, NETDEV_UP);
+		qlcnic_restore_indev_addr(netdev, NETDEV_UP);
 	}
 done:
 	netif_device_attach(netdev);
@@ -1587,9 +1737,6 @@
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	int err;
 
-	if (adapter->driver_mismatch)
-		return -EIO;
-
 	err = qlcnic_attach(adapter);
 	if (err)
 		return err;
@@ -1619,6 +1766,121 @@
 }
 
 static void
+qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
+{
+	void *head;
+	int i;
+
+	if (!qlcnic_mac_learn)
+		return;
+
+	spin_lock_init(&adapter->mac_learn_lock);
+
+	head = kcalloc(QLCNIC_LB_MAX_FILTERS, sizeof(struct hlist_head),
+								GFP_KERNEL);
+	if (!head)
+		return;
+
+	adapter->fhash.fmax = QLCNIC_LB_MAX_FILTERS;
+	adapter->fhash.fhead = (struct hlist_head *)head;
+
+	for (i = 0; i < adapter->fhash.fmax; i++)
+		INIT_HLIST_HEAD(&adapter->fhash.fhead[i]);
+}
+
+static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
+{
+	if (adapter->fhash.fmax && adapter->fhash.fhead)
+		kfree(adapter->fhash.fhead);
+
+	adapter->fhash.fhead = NULL;
+	adapter->fhash.fmax = 0;
+}
+
+static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
+		u64 uaddr, __le16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
+{
+	struct cmd_desc_type0 *hwdesc;
+	struct qlcnic_nic_req *req;
+	struct qlcnic_mac_req *mac_req;
+	struct qlcnic_vlan_req *vlan_req;
+	u32 producer;
+	u64 word;
+
+	producer = tx_ring->producer;
+	hwdesc = &tx_ring->desc_head[tx_ring->producer];
+
+	req = (struct qlcnic_nic_req *)hwdesc;
+	memset(req, 0, sizeof(struct qlcnic_nic_req));
+	req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
+
+	word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
+	req->req_hdr = cpu_to_le64(word);
+
+	mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
+	mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
+	memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
+
+	vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
+	vlan_req->vlan_id = vlan_id;
+
+	tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
+}
+
+#define QLCNIC_MAC_HASH(MAC)\
+	((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
+
+static void
+qlcnic_send_filter(struct qlcnic_adapter *adapter,
+		struct qlcnic_host_tx_ring *tx_ring,
+		struct cmd_desc_type0 *first_desc,
+		struct sk_buff *skb)
+{
+	struct ethhdr *phdr = (struct ethhdr *)(skb->data);
+	struct qlcnic_filter *fil, *tmp_fil;
+	struct hlist_node *tmp_hnode, *n;
+	struct hlist_head *head;
+	u64 src_addr = 0;
+	__le16 vlan_id = 0;
+	u8 hindex;
+
+	if (!compare_ether_addr(phdr->h_source, adapter->mac_addr))
+		return;
+
+	if (adapter->fhash.fnum >= adapter->fhash.fmax)
+		return;
+
+	/* Only NPAR capable devices support vlan based learning*/
+	if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+		vlan_id = first_desc->vlan_TCI;
+	memcpy(&src_addr, phdr->h_source, ETH_ALEN);
+	hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
+	head = &(adapter->fhash.fhead[hindex]);
+
+	hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
+		if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
+			    tmp_fil->vlan_id == vlan_id) {
+			tmp_fil->ftime = jiffies;
+			return;
+		}
+	}
+
+	fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
+	if (!fil)
+		return;
+
+	qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
+
+	fil->ftime = jiffies;
+	fil->vlan_id = vlan_id;
+	memcpy(fil->faddr, &src_addr, ETH_ALEN);
+	spin_lock(&adapter->mac_learn_lock);
+	hlist_add_head(&(fil->fnode), head);
+	adapter->fhash.fnum++;
+	spin_unlock(&adapter->mac_learn_lock);
+}
+
+static void
 qlcnic_tso_check(struct net_device *netdev,
 		struct qlcnic_host_tx_ring *tx_ring,
 		struct cmd_desc_type0 *first_desc,
@@ -1626,26 +1888,14 @@
 {
 	u8 opcode = TX_ETHER_PKT;
 	__be16 protocol = skb->protocol;
-	u16 flags = 0, vid = 0;
-	int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0;
+	u16 flags = 0;
+	int copied, offset, copy_len, hdr_len = 0, tso = 0;
 	struct cmd_desc_type0 *hwdesc;
 	struct vlan_ethhdr *vh;
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	u32 producer = tx_ring->producer;
-
-	if (protocol == cpu_to_be16(ETH_P_8021Q)) {
-
-		vh = (struct vlan_ethhdr *)skb->data;
-		protocol = vh->h_vlan_encapsulated_proto;
-		flags = FLAGS_VLAN_TAGGED;
-
-	} else if (vlan_tx_tag_present(skb)) {
-
-		flags = FLAGS_VLAN_OOB;
-		vid = vlan_tx_tag_get(skb);
-		qlcnic_set_tx_vlan_tci(first_desc, vid);
-		vlan_oob = 1;
-	}
+	__le16 vlan_oob = first_desc->flags_opcode &
+				cpu_to_le16(FLAGS_VLAN_OOB);
 
 	if (*(skb->data) & BIT_0) {
 		flags |= BIT_0;
@@ -1716,7 +1966,8 @@
 		vh = (struct vlan_ethhdr *)((char *)hwdesc + 2);
 		skb_copy_from_linear_data(skb, vh, 12);
 		vh->h_vlan_proto = htons(ETH_P_8021Q);
-		vh->h_vlan_TCI = htons(vid);
+		vh->h_vlan_TCI = (__be16)swab16((u16)first_desc->vlan_TCI);
+
 		skb_copy_from_linear_data_offset(skb, 12,
 				(char *)vh + 16, copy_len - 16);
 
@@ -1796,11 +2047,47 @@
 	return -ENOMEM;
 }
 
+static int
+qlcnic_check_tx_tagging(struct qlcnic_adapter *adapter,
+			struct sk_buff *skb,
+			struct cmd_desc_type0 *first_desc)
+{
+	u8 opcode = 0;
+	u16 flags = 0;
+	__be16 protocol = skb->protocol;
+	struct vlan_ethhdr *vh;
+
+	if (protocol == cpu_to_be16(ETH_P_8021Q)) {
+		vh = (struct vlan_ethhdr *)skb->data;
+		protocol = vh->h_vlan_encapsulated_proto;
+		flags = FLAGS_VLAN_TAGGED;
+		qlcnic_set_tx_vlan_tci(first_desc, ntohs(vh->h_vlan_TCI));
+	} else if (vlan_tx_tag_present(skb)) {
+		flags = FLAGS_VLAN_OOB;
+		qlcnic_set_tx_vlan_tci(first_desc, vlan_tx_tag_get(skb));
+	}
+	if (unlikely(adapter->pvid)) {
+		if (first_desc->vlan_TCI &&
+				!(adapter->flags & QLCNIC_TAGGING_ENABLED))
+			return -EIO;
+		if (first_desc->vlan_TCI &&
+				(adapter->flags & QLCNIC_TAGGING_ENABLED))
+			goto set_flags;
+
+		flags = FLAGS_VLAN_OOB;
+		qlcnic_set_tx_vlan_tci(first_desc, adapter->pvid);
+	}
+set_flags:
+	qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
+	return 0;
+}
+
 static inline void
 qlcnic_clear_cmddesc(u64 *desc)
 {
 	desc[0] = 0ULL;
 	desc[2] = 0ULL;
+	desc[7] = 0ULL;
 }
 
 netdev_tx_t
@@ -1812,6 +2099,7 @@
 	struct qlcnic_skb_frag *buffrag;
 	struct cmd_desc_type0 *hwdesc, *first_desc;
 	struct pci_dev *pdev;
+	struct ethhdr *phdr;
 	int i, k;
 
 	u32 producer;
@@ -1823,6 +2111,13 @@
 		return NETDEV_TX_BUSY;
 	}
 
+	if (adapter->flags & QLCNIC_MACSPOOF) {
+		phdr = (struct ethhdr *)skb->data;
+		if (compare_ether_addr(phdr->h_source,
+					adapter->mac_addr))
+			goto drop_packet;
+	}
+
 	frag_count = skb_shinfo(skb)->nr_frags + 1;
 
 	/* 4 fragments per cmd des */
@@ -1844,6 +2139,12 @@
 
 	pdev = adapter->pdev;
 
+	first_desc = hwdesc = &tx_ring->desc_head[producer];
+	qlcnic_clear_cmddesc((u64 *)hwdesc);
+
+	if (qlcnic_check_tx_tagging(adapter, skb, first_desc))
+		goto drop_packet;
+
 	if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
 		adapter->stats.tx_dma_map_error++;
 		goto drop_packet;
@@ -1852,9 +2153,6 @@
 	pbuf->skb = skb;
 	pbuf->frag_count = frag_count;
 
-	first_desc = hwdesc = &tx_ring->desc_head[producer];
-	qlcnic_clear_cmddesc((u64 *)hwdesc);
-
 	qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
 	qlcnic_set_tx_port(first_desc, adapter->portnum);
 
@@ -1893,6 +2191,9 @@
 
 	qlcnic_tso_check(netdev, tx_ring, first_desc, skb);
 
+	if (qlcnic_mac_learn)
+		qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
+
 	qlcnic_update_cmd_producer(adapter, tx_ring);
 
 	adapter->stats.txbytes += skb->len;
@@ -1947,14 +2248,14 @@
 	struct net_device *netdev = adapter->netdev;
 
 	if (adapter->ahw.linkup && !linkup) {
-		dev_info(&netdev->dev, "NIC Link is down\n");
+		netdev_info(netdev, "NIC Link is down\n");
 		adapter->ahw.linkup = 0;
 		if (netif_running(netdev)) {
 			netif_carrier_off(netdev);
 			netif_stop_queue(netdev);
 		}
 	} else if (!adapter->ahw.linkup && linkup) {
-		dev_info(&netdev->dev, "NIC Link is up\n");
+		netdev_info(netdev, "NIC Link is up\n");
 		adapter->ahw.linkup = 1;
 		if (netif_running(netdev)) {
 			netif_carrier_on(netdev);
@@ -2258,18 +2559,22 @@
 }
 
 static void
-qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter)
+qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
 {
 	u32  val;
 
 	if (qlcnic_api_lock(adapter))
 		goto err;
 
-	val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
+	val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
 	QLC_DEV_CLR_REF_CNT(val, adapter->portnum);
-	QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val);
+	QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
 
-	if (!(val & 0x11111111))
+	if (failed) {
+		QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
+		dev_info(&adapter->pdev->dev,
+				"Device state set to Failed. Please Reboot\n");
+	} else if (!(val & 0x11111111))
 		QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_COLD);
 
 	val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
@@ -2290,7 +2595,7 @@
 	int act, state;
 
 	state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
-	act = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
+	act = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
 
 	if (((state & 0x11111111) == (act & 0x11111111)) ||
 			((act & 0x11111111) == ((state >> 1) & 0x11111111)))
@@ -2325,10 +2630,10 @@
 	if (qlcnic_api_lock(adapter))
 		return -1;
 
-	val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
+	val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
 	if (!(val & (1 << (portnum * 4)))) {
 		QLC_DEV_SET_REF_CNT(val, portnum);
-		QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val);
+		QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
 	}
 
 	prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
@@ -2403,13 +2708,14 @@
 {
 	struct qlcnic_adapter *adapter = container_of(work,
 			struct qlcnic_adapter, fw_work.work);
-	u32 dev_state = 0xf, npar_state;
+	u32 dev_state = 0xf;
 
 	if (qlcnic_api_lock(adapter))
 		goto err_ret;
 
 	dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-	if (dev_state ==  QLCNIC_DEV_QUISCENT) {
+	if (dev_state == QLCNIC_DEV_QUISCENT ||
+	    dev_state == QLCNIC_DEV_NEED_QUISCENT) {
 		qlcnic_api_unlock(adapter);
 		qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
 						FW_POLL_DELAY * 2);
@@ -2417,16 +2723,8 @@
 	}
 
 	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
-		npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
-		if (npar_state == QLCNIC_DEV_NPAR_RDY) {
-			qlcnic_api_unlock(adapter);
-			goto wait_npar;
-		} else {
-			qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
-				FW_POLL_DELAY);
-			qlcnic_api_unlock(adapter);
-			return;
-		}
+		qlcnic_api_unlock(adapter);
+		goto wait_npar;
 	}
 
 	if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
@@ -2439,18 +2737,6 @@
 skip_ack_check:
 		dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
 
-		if (dev_state == QLCNIC_DEV_NEED_QUISCENT) {
-			QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
-						QLCNIC_DEV_QUISCENT);
-			qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
-						FW_POLL_DELAY * 2);
-			QLCDB(adapter, DRV, "Quiscing the driver\n");
-			qlcnic_idc_debug_info(adapter, 0);
-
-			qlcnic_api_unlock(adapter);
-			return;
-		}
-
 		if (dev_state == QLCNIC_DEV_NEED_RESET) {
 			QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
 						QLCNIC_DEV_INITIALIZING);
@@ -2463,6 +2749,7 @@
 
 		if (!adapter->nic_ops->start_firmware(adapter)) {
 			qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
+			adapter->fw_wait_cnt = 0;
 			return;
 		}
 		goto err_ret;
@@ -2475,27 +2762,25 @@
 	QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
 
 	switch (dev_state) {
-	case QLCNIC_DEV_QUISCENT:
-	case QLCNIC_DEV_NEED_QUISCENT:
-	case QLCNIC_DEV_NEED_RESET:
+	case QLCNIC_DEV_READY:
+		if (!adapter->nic_ops->start_firmware(adapter)) {
+			qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
+			adapter->fw_wait_cnt = 0;
+			return;
+		}
+	case QLCNIC_DEV_FAILED:
+		break;
+	default:
 		qlcnic_schedule_work(adapter,
 			qlcnic_fwinit_work, FW_POLL_DELAY);
 		return;
-	case QLCNIC_DEV_FAILED:
-		break;
-
-	default:
-		if (!adapter->nic_ops->start_firmware(adapter)) {
-			qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
-			return;
-		}
 	}
 
 err_ret:
 	dev_err(&adapter->pdev->dev, "Fwinit work failed state=%u "
 		"fw_wait_cnt=%u\n", dev_state, adapter->fw_wait_cnt);
 	netif_device_attach(adapter->netdev);
-	qlcnic_clr_all_drv_state(adapter);
+	qlcnic_clr_all_drv_state(adapter, 0);
 }
 
 static void
@@ -2508,7 +2793,12 @@
 
 	netif_device_detach(netdev);
 
-	qlcnic_down(adapter, netdev);
+	/* Dont grab rtnl lock during Quiscent mode */
+	if (adapter->dev_state == QLCNIC_DEV_NEED_QUISCENT) {
+		if (netif_running(netdev))
+			__qlcnic_down(adapter, netdev);
+	} else
+		qlcnic_down(adapter, netdev);
 
 	status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
 
@@ -2531,8 +2821,78 @@
 	dev_err(&adapter->pdev->dev, "detach failed; status=%d temp=%d\n",
 			status, adapter->temp);
 	netif_device_attach(netdev);
-	qlcnic_clr_all_drv_state(adapter);
+	qlcnic_clr_all_drv_state(adapter, 1);
+}
 
+/*Transit NPAR state to NON Operational */
+static void
+qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
+{
+	u32 state;
+
+	state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+	if (state == QLCNIC_DEV_NPAR_NON_OPER)
+		return;
+
+	if (qlcnic_api_lock(adapter))
+		return;
+	QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
+	qlcnic_api_unlock(adapter);
+}
+
+/* Caller should held RESETTING bit.
+ * This should be call in sync with qlcnic_request_quiscent_mode.
+ */
+void qlcnic_clear_quiscent_mode(struct qlcnic_adapter *adapter)
+{
+	qlcnic_clr_drv_state(adapter);
+	qlcnic_api_lock(adapter);
+	QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
+	qlcnic_api_unlock(adapter);
+}
+
+/* Caller should held RESETTING bit.
+ */
+int qlcnic_request_quiscent_mode(struct qlcnic_adapter *adapter)
+{
+	u8 timeo = adapter->dev_init_timeo / 2;
+	u32 state;
+
+	if (qlcnic_api_lock(adapter))
+		return -EIO;
+
+	state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+	if (state != QLCNIC_DEV_READY)
+		return -EIO;
+
+	QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_QUISCENT);
+	qlcnic_api_unlock(adapter);
+	QLCDB(adapter, DRV, "NEED QUISCENT state set\n");
+	qlcnic_idc_debug_info(adapter, 0);
+
+	qlcnic_set_drv_state(adapter, QLCNIC_DEV_NEED_QUISCENT);
+
+	do {
+		msleep(2000);
+		state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+		if (state == QLCNIC_DEV_QUISCENT)
+			return 0;
+		if (!qlcnic_check_drv_state(adapter)) {
+			if (qlcnic_api_lock(adapter))
+				return -EIO;
+			QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
+							QLCNIC_DEV_QUISCENT);
+			qlcnic_api_unlock(adapter);
+			QLCDB(adapter, DRV, "QUISCENT mode set\n");
+			return 0;
+		}
+	} while (--timeo);
+
+	dev_err(&adapter->pdev->dev, "Failed to quiesce device, DRV_STATE=%08x"
+		" DRV_ACTIVE=%08x\n", QLCRD32(adapter, QLCNIC_CRB_DRV_STATE),
+		QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE));
+	qlcnic_clear_quiscent_mode(adapter);
+	return -EIO;
 }
 
 /*Transit to RESET state from READY state only */
@@ -2553,6 +2913,7 @@
 		qlcnic_idc_debug_info(adapter, 0);
 	}
 
+	QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
 	qlcnic_api_unlock(adapter);
 }
 
@@ -2560,21 +2921,11 @@
 static void
 qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
 {
-	u32 state;
-
-	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
-		adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
-		return;
 	if (qlcnic_api_lock(adapter))
 		return;
 
-	state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
-
-	if (state != QLCNIC_DEV_NPAR_RDY) {
-		QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
-			QLCNIC_DEV_NPAR_RDY);
-		QLCDB(adapter, DRV, "NPAR READY state set\n");
-	}
+	QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_OPER);
+	QLCDB(adapter, DRV, "NPAR operational state set\n");
 
 	qlcnic_api_unlock(adapter);
 }
@@ -2587,7 +2938,8 @@
 		return;
 
 	INIT_DELAYED_WORK(&adapter->fw_work, func);
-	schedule_delayed_work(&adapter->fw_work, round_jiffies_relative(delay));
+	queue_delayed_work(qlcnic_wq, &adapter->fw_work,
+					round_jiffies_relative(delay));
 }
 
 static void
@@ -2605,12 +2957,26 @@
 	struct qlcnic_adapter *adapter = container_of(work,
 				struct qlcnic_adapter, fw_work.work);
 	struct net_device *netdev = adapter->netdev;
+	u32 npar_state;
 
+	if (adapter->op_mode != QLCNIC_MGMT_FUNC) {
+		npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+		if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO)
+			qlcnic_clr_all_drv_state(adapter, 0);
+		else if (npar_state != QLCNIC_DEV_NPAR_OPER)
+			qlcnic_schedule_work(adapter, qlcnic_attach_work,
+							FW_POLL_DELAY);
+		else
+			goto attach;
+		QLCDB(adapter, DRV, "Waiting for NPAR state to operational\n");
+		return;
+	}
+attach:
 	if (netif_running(netdev)) {
 		if (qlcnic_up(adapter, netdev))
 			goto done;
 
-		qlcnic_config_indev_addr(netdev, NETDEV_UP);
+		qlcnic_restore_indev_addr(netdev, NETDEV_UP);
 	}
 
 done:
@@ -2626,7 +2992,7 @@
 static int
 qlcnic_check_health(struct qlcnic_adapter *adapter)
 {
-	u32 state = 0, heartbit;
+	u32 state = 0, heartbeat;
 	struct net_device *netdev = adapter->netdev;
 
 	if (qlcnic_check_temp(adapter))
@@ -2636,12 +3002,15 @@
 		qlcnic_dev_request_reset(adapter);
 
 	state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-	if (state == QLCNIC_DEV_NEED_RESET || state == QLCNIC_DEV_NEED_QUISCENT)
+	if (state == QLCNIC_DEV_NEED_RESET) {
+		qlcnic_set_npar_non_operational(adapter);
 		adapter->need_fw_reset = 1;
+	} else if (state == QLCNIC_DEV_NEED_QUISCENT)
+		goto detach;
 
-	heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
-	if (heartbit != adapter->heartbit) {
-		adapter->heartbit = heartbit;
+	heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+	if (heartbeat != adapter->heartbeat) {
+		adapter->heartbeat = heartbeat;
 		adapter->fw_fail_cnt = 0;
 		if (adapter->need_fw_reset)
 			goto detach;
@@ -2692,6 +3061,9 @@
 	if (qlcnic_check_health(adapter))
 		return;
 
+	if (adapter->fhash.fnum)
+		qlcnic_prune_lb_filters(adapter);
+
 reschedule:
 	qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
 }
@@ -2738,7 +3110,7 @@
 	if (qlcnic_api_lock(adapter))
 		return -EINVAL;
 
-	if (first_func) {
+	if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
 		adapter->need_fw_reset = 1;
 		set_bit(__QLCNIC_START_FW, &adapter->state);
 		QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
@@ -2756,7 +3128,7 @@
 	if (netif_running(netdev)) {
 		err = qlcnic_attach(adapter);
 		if (err) {
-			qlcnic_clr_all_drv_state(adapter);
+			qlcnic_clr_all_drv_state(adapter, 1);
 			clear_bit(__QLCNIC_AER, &adapter->state);
 			netif_device_attach(netdev);
 			return err;
@@ -2766,7 +3138,7 @@
 		if (err)
 			goto done;
 
-		qlcnic_config_indev_addr(netdev, NETDEV_UP);
+		qlcnic_restore_indev_addr(netdev, NETDEV_UP);
 	}
  done:
 	netif_device_attach(netdev);
@@ -2822,7 +3194,6 @@
 						FW_POLL_DELAY);
 }
 
-
 static int
 qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
 {
@@ -2832,8 +3203,20 @@
 	if (err)
 		return err;
 
+	err = qlcnic_check_npar_opertional(adapter);
+	if (err)
+		return err;
+
+	err = qlcnic_initialize_nic(adapter);
+	if (err)
+		return err;
+
 	qlcnic_check_options(adapter);
 
+	err = qlcnic_set_eswitch_port_config(adapter);
+	if (err)
+		return err;
+
 	adapter->need_fw_reset = 0;
 
 	return err;
@@ -3093,9 +3476,6 @@
 		if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
 			return QL_STATUS_INVALID_PARAM;
 
-		if (!IS_VALID_MODE(pm_cfg[i].action))
-			return QL_STATUS_INVALID_PARAM;
-
 		s_esw_id = adapter->npars[src_pci_func].phy_port;
 		d_esw_id = adapter->npars[dest_pci_func].phy_port;
 
@@ -3129,7 +3509,7 @@
 		return ret;
 	for (i = 0; i < count; i++) {
 		pci_func = pm_cfg[i].pci_func;
-		action = pm_cfg[i].action;
+		action = !!pm_cfg[i].action;
 		id = adapter->npars[pci_func].phy_port;
 		ret = qlcnic_config_port_mirroring(adapter, id,
 						action, pci_func);
@@ -3140,7 +3520,7 @@
 	for (i = 0; i < count; i++) {
 		pci_func = pm_cfg[i].pci_func;
 		id = adapter->npars[pci_func].phy_port;
-		adapter->npars[pci_func].enable_pm = pm_cfg[i].action;
+		adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
 		adapter->npars[pci_func].dest_npar = id;
 	}
 	return size;
@@ -3172,30 +3552,46 @@
 
 static int
 validate_esw_config(struct qlcnic_adapter *adapter,
-			struct qlcnic_esw_func_cfg *esw_cfg, int count)
+	struct qlcnic_esw_func_cfg *esw_cfg, int count)
 {
+	u32 op_mode;
 	u8 pci_func;
 	int i;
 
+	op_mode = readl(adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE);
+
 	for (i = 0; i < count; i++) {
 		pci_func = esw_cfg[i].pci_func;
 		if (pci_func >= QLCNIC_MAX_PCI_FUNC)
 			return QL_STATUS_INVALID_PARAM;
 
-		if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
-			return QL_STATUS_INVALID_PARAM;
-
-		if (esw_cfg->host_vlan_tag == 1)
-			if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
+		if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+			if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
 				return QL_STATUS_INVALID_PARAM;
 
-		if (!IS_VALID_MODE(esw_cfg[i].promisc_mode)
-				|| !IS_VALID_MODE(esw_cfg[i].host_vlan_tag)
-				|| !IS_VALID_MODE(esw_cfg[i].mac_learning)
-				|| !IS_VALID_MODE(esw_cfg[i].discard_tagged))
+		switch (esw_cfg[i].op_mode) {
+		case QLCNIC_PORT_DEFAULTS:
+			if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
+						QLCNIC_NON_PRIV_FUNC) {
+				esw_cfg[i].mac_anti_spoof = 0;
+				esw_cfg[i].mac_override = 1;
+				esw_cfg[i].promisc_mode = 1;
+			}
+			break;
+		case QLCNIC_ADD_VLAN:
+			if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
+				return QL_STATUS_INVALID_PARAM;
+			if (!esw_cfg[i].op_type)
+				return QL_STATUS_INVALID_PARAM;
+			break;
+		case QLCNIC_DEL_VLAN:
+			if (!esw_cfg[i].op_type)
+				return QL_STATUS_INVALID_PARAM;
+			break;
+		default:
 			return QL_STATUS_INVALID_PARAM;
+		}
 	}
-
 	return 0;
 }
 
@@ -3206,8 +3602,9 @@
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
 	struct qlcnic_esw_func_cfg *esw_cfg;
+	struct qlcnic_npar_info *npar;
 	int count, rem, i, ret;
-	u8 id, pci_func;
+	u8 pci_func, op_mode = 0;
 
 	count	= size / sizeof(struct qlcnic_esw_func_cfg);
 	rem	= size % sizeof(struct qlcnic_esw_func_cfg);
@@ -3220,30 +3617,55 @@
 		return ret;
 
 	for (i = 0; i < count; i++) {
-		pci_func = esw_cfg[i].pci_func;
-		id = adapter->npars[pci_func].phy_port;
-		ret = qlcnic_config_switch_port(adapter, id,
-						esw_cfg[i].host_vlan_tag,
-						esw_cfg[i].discard_tagged,
-						esw_cfg[i].promisc_mode,
-						esw_cfg[i].mac_learning,
-						esw_cfg[i].pci_func,
-						esw_cfg[i].vlan_id);
-		if (ret)
-			return ret;
+		if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+			if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
+				return QL_STATUS_INVALID_PARAM;
+
+		if (adapter->ahw.pci_func != esw_cfg[i].pci_func)
+			continue;
+
+		op_mode = esw_cfg[i].op_mode;
+		qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
+		esw_cfg[i].op_mode = op_mode;
+		esw_cfg[i].pci_func = adapter->ahw.pci_func;
+
+		switch (esw_cfg[i].op_mode) {
+		case QLCNIC_PORT_DEFAULTS:
+			qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
+			break;
+		case QLCNIC_ADD_VLAN:
+			qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+			break;
+		case QLCNIC_DEL_VLAN:
+			esw_cfg[i].vlan_id = 0;
+			qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+			break;
+		}
 	}
 
+	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+		goto out;
+
 	for (i = 0; i < count; i++) {
 		pci_func = esw_cfg[i].pci_func;
-		adapter->npars[pci_func].promisc_mode = esw_cfg[i].promisc_mode;
-		adapter->npars[pci_func].mac_learning =	esw_cfg[i].mac_learning;
-		adapter->npars[pci_func].vlan_id = esw_cfg[i].vlan_id;
-		adapter->npars[pci_func].discard_tagged	=
-						esw_cfg[i].discard_tagged;
-		adapter->npars[pci_func].host_vlan_tag =
-						esw_cfg[i].host_vlan_tag;
+		npar = &adapter->npars[pci_func];
+		switch (esw_cfg[i].op_mode) {
+		case QLCNIC_PORT_DEFAULTS:
+			npar->promisc_mode = esw_cfg[i].promisc_mode;
+			npar->mac_override = esw_cfg[i].mac_override;
+			npar->offload_flags = esw_cfg[i].offload_flags;
+			npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
+			npar->discard_tagged = esw_cfg[i].discard_tagged;
+			break;
+		case QLCNIC_ADD_VLAN:
+			npar->pvid = esw_cfg[i].vlan_id;
+			break;
+		case QLCNIC_DEL_VLAN:
+			npar->pvid = 0;
+			break;
+		}
 	}
-
+out:
 	return size;
 }
 
@@ -3254,7 +3676,7 @@
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
 	struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
-	int i;
+	u8 i;
 
 	if (size != sizeof(esw_cfg))
 		return QL_STATUS_INVALID_PARAM;
@@ -3262,12 +3684,9 @@
 	for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
 		if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
 			continue;
-
-		esw_cfg[i].host_vlan_tag = adapter->npars[i].host_vlan_tag;
-		esw_cfg[i].promisc_mode = adapter->npars[i].promisc_mode;
-		esw_cfg[i].discard_tagged = adapter->npars[i].discard_tagged;
-		esw_cfg[i].vlan_id = adapter->npars[i].vlan_id;
-		esw_cfg[i].mac_learning = adapter->npars[i].mac_learning;
+		esw_cfg[i].pci_func = i;
+		if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
+			return QL_STATUS_INVALID_PARAM;
 	}
 	memcpy(buf, &esw_cfg, size);
 
@@ -3357,7 +3776,7 @@
 			return ret;
 
 		np_cfg[i].pci_func = i;
-		np_cfg[i].op_mode = nic_info.op_mode;
+		np_cfg[i].op_mode = (u8)nic_info.op_mode;
 		np_cfg[i].port_num = nic_info.phys_port;
 		np_cfg[i].fw_capab = nic_info.capabilities;
 		np_cfg[i].min_bw = nic_info.min_tx_bw ;
@@ -3370,6 +3789,115 @@
 }
 
 static ssize_t
+qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj,
+	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	struct qlcnic_esw_statistics port_stats;
+	int ret;
+
+	if (size != sizeof(struct qlcnic_esw_statistics))
+		return QL_STATUS_INVALID_PARAM;
+
+	if (offset >= QLCNIC_MAX_PCI_FUNC)
+		return QL_STATUS_INVALID_PARAM;
+
+	memset(&port_stats, 0, size);
+	ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+								&port_stats.rx);
+	if (ret)
+		return ret;
+
+	ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+								&port_stats.tx);
+	if (ret)
+		return ret;
+
+	memcpy(buf, &port_stats, size);
+	return size;
+}
+
+static ssize_t
+qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj,
+	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	struct qlcnic_esw_statistics esw_stats;
+	int ret;
+
+	if (size != sizeof(struct qlcnic_esw_statistics))
+		return QL_STATUS_INVALID_PARAM;
+
+	if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+		return QL_STATUS_INVALID_PARAM;
+
+	memset(&esw_stats, 0, size);
+	ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+								&esw_stats.rx);
+	if (ret)
+		return ret;
+
+	ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+								&esw_stats.tx);
+	if (ret)
+		return ret;
+
+	memcpy(buf, &esw_stats, size);
+	return size;
+}
+
+static ssize_t
+qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj,
+	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	int ret;
+
+	if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+		return QL_STATUS_INVALID_PARAM;
+
+	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+						QLCNIC_QUERY_RX_COUNTER);
+	if (ret)
+		return ret;
+
+	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+						QLCNIC_QUERY_TX_COUNTER);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t
+qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj,
+	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	int ret;
+
+	if (offset >= QLCNIC_MAX_PCI_FUNC)
+		return QL_STATUS_INVALID_PARAM;
+
+	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+						QLCNIC_QUERY_RX_COUNTER);
+	if (ret)
+		return ret;
+
+	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+						QLCNIC_QUERY_TX_COUNTER);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t
 qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
 	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
 {
@@ -3418,6 +3946,20 @@
 	.write = NULL,
 };
 
+static struct bin_attribute bin_attr_port_stats = {
+	.attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
+	.size = 0,
+	.read = qlcnic_sysfs_get_port_stats,
+	.write = qlcnic_sysfs_clear_port_stats,
+};
+
+static struct bin_attribute bin_attr_esw_stats = {
+	.attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
+	.size = 0,
+	.read = qlcnic_sysfs_get_esw_stats,
+	.write = qlcnic_sysfs_clear_esw_stats,
+};
+
 static struct bin_attribute bin_attr_esw_config = {
 	.attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
 	.size = 0,
@@ -3457,6 +3999,9 @@
 {
 	struct device *dev = &adapter->pdev->dev;
 
+	if (device_create_bin_file(dev, &bin_attr_port_stats))
+		dev_info(dev, "failed to create port stats sysfs entry");
+
 	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
 		return;
 	if (device_create_file(dev, &dev_attr_diag_mode))
@@ -3465,18 +4010,20 @@
 		dev_info(dev, "failed to create crb sysfs entry\n");
 	if (device_create_bin_file(dev, &bin_attr_mem))
 		dev_info(dev, "failed to create mem sysfs entry\n");
-	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
-			adapter->op_mode != QLCNIC_MGMT_FUNC)
+	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+		return;
+	if (device_create_bin_file(dev, &bin_attr_esw_config))
+		dev_info(dev, "failed to create esw config sysfs entry");
+	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
 		return;
 	if (device_create_bin_file(dev, &bin_attr_pci_config))
 		dev_info(dev, "failed to create pci config sysfs entry");
 	if (device_create_bin_file(dev, &bin_attr_npar_config))
 		dev_info(dev, "failed to create npar config sysfs entry");
-	if (device_create_bin_file(dev, &bin_attr_esw_config))
-		dev_info(dev, "failed to create esw config sysfs entry");
 	if (device_create_bin_file(dev, &bin_attr_pm_config))
 		dev_info(dev, "failed to create pm config sysfs entry");
-
+	if (device_create_bin_file(dev, &bin_attr_esw_stats))
+		dev_info(dev, "failed to create eswitch stats sysfs entry");
 }
 
 static void
@@ -3484,18 +4031,22 @@
 {
 	struct device *dev = &adapter->pdev->dev;
 
+	device_remove_bin_file(dev, &bin_attr_port_stats);
+
 	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
 		return;
 	device_remove_file(dev, &dev_attr_diag_mode);
 	device_remove_bin_file(dev, &bin_attr_crb);
 	device_remove_bin_file(dev, &bin_attr_mem);
-	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
-			adapter->op_mode != QLCNIC_MGMT_FUNC)
+	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+		return;
+	device_remove_bin_file(dev, &bin_attr_esw_config);
+	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
 		return;
 	device_remove_bin_file(dev, &bin_attr_pci_config);
 	device_remove_bin_file(dev, &bin_attr_npar_config);
-	device_remove_bin_file(dev, &bin_attr_esw_config);
 	device_remove_bin_file(dev, &bin_attr_pm_config);
+	device_remove_bin_file(dev, &bin_attr_esw_stats);
 }
 
 #ifdef CONFIG_INET
@@ -3503,10 +4054,10 @@
 #define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops)
 
 static void
-qlcnic_config_indev_addr(struct net_device *dev, unsigned long event)
+qlcnic_config_indev_addr(struct qlcnic_adapter *adapter,
+			struct net_device *dev, unsigned long event)
 {
 	struct in_device *indev;
-	struct qlcnic_adapter *adapter = netdev_priv(dev);
 
 	indev = in_dev_get(dev);
 	if (!indev)
@@ -3530,6 +4081,27 @@
 	in_dev_put(indev);
 }
 
+static void
+qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	struct net_device *dev;
+	u16 vid;
+
+	qlcnic_config_indev_addr(adapter, netdev, event);
+
+	if (!adapter->vlgrp)
+		return;
+
+	for (vid = 0; vid < VLAN_N_VID; vid++) {
+		dev = vlan_group_get_device(adapter->vlgrp, vid);
+		if (!dev)
+			continue;
+
+		qlcnic_config_indev_addr(adapter, dev, event);
+	}
+}
+
 static int qlcnic_netdev_event(struct notifier_block *this,
 				 unsigned long event, void *ptr)
 {
@@ -3556,7 +4128,7 @@
 	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
 		goto done;
 
-	qlcnic_config_indev_addr(dev, event);
+	qlcnic_config_indev_addr(adapter, dev, event);
 done:
 	return NOTIFY_DONE;
 }
@@ -3573,7 +4145,7 @@
 	dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
 
 recheck:
-	if (dev == NULL || !netif_running(dev))
+	if (dev == NULL)
 		goto done;
 
 	if (dev->priv_flags & IFF_802_1Q_VLAN) {
@@ -3616,7 +4188,7 @@
 };
 #else
 static void
-qlcnic_config_indev_addr(struct net_device *dev, unsigned long event)
+qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event)
 { }
 #endif
 static struct pci_error_handlers qlcnic_err_handler = {
@@ -3645,6 +4217,12 @@
 
 	printk(KERN_INFO "%s\n", qlcnic_driver_string);
 
+	qlcnic_wq = create_singlethread_workqueue("qlcnic");
+	if (qlcnic_wq == NULL) {
+		printk(KERN_ERR "qlcnic: cannot create workqueue\n");
+		return -ENOMEM;
+	}
+
 #ifdef CONFIG_INET
 	register_netdevice_notifier(&qlcnic_netdev_cb);
 	register_inetaddr_notifier(&qlcnic_inetaddr_cb);
@@ -3656,6 +4234,7 @@
 		unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
 		unregister_netdevice_notifier(&qlcnic_netdev_cb);
 #endif
+		destroy_workqueue(qlcnic_wq);
 	}
 
 	return ret;
@@ -3672,6 +4251,7 @@
 	unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
 	unregister_netdevice_notifier(&qlcnic_netdev_cb);
 #endif
+	destroy_workqueue(qlcnic_wq);
 }
 
 module_exit(qlcnic_exit_module);
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 5f89e83..ba0053d 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -1566,7 +1566,7 @@
 	rx_ring->rx_packets++;
 	rx_ring->rx_bytes += skb->len;
 	skb->protocol = eth_type_trans(skb, ndev);
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 
 	if (qdev->rx_csum &&
 		!(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) {
@@ -1676,7 +1676,7 @@
 	rx_ring->rx_packets++;
 	rx_ring->rx_bytes += skb->len;
 	skb->protocol = eth_type_trans(skb, ndev);
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 
 	/* If rx checksum is on, and there are no
 	 * csum or frame errors.
@@ -1996,7 +1996,7 @@
 	}
 
 	skb->protocol = eth_type_trans(skb, ndev);
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 
 	/* If rx checksum is on, and there are no
 	 * csum or frame errors.
@@ -2222,10 +2222,11 @@
 		ql_update_cq(rx_ring);
 		prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
 	}
+	if (!net_rsp)
+		return 0;
 	ql_write_cq_idx(rx_ring);
 	tx_ring = &qdev->tx_ring[net_rsp->txq_idx];
-	if (__netif_subqueue_stopped(qdev->ndev, tx_ring->wq_id) &&
-					net_rsp != NULL) {
+	if (__netif_subqueue_stopped(qdev->ndev, tx_ring->wq_id)) {
 		if (atomic_read(&tx_ring->queue_stopped) &&
 		    (atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4)))
 			/*
@@ -2571,7 +2572,7 @@
 
 	mac_iocb_ptr->frame_len = cpu_to_le16((u16) skb->len);
 
-	if (qdev->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		netif_printk(qdev, tx_queued, KERN_DEBUG, qdev->ndev,
 			     "Adding a vlan tag %d.\n", vlan_tx_tag_get(skb));
 		mac_iocb_ptr->flags3 |= OB_MAC_IOCB_V;
@@ -3888,11 +3889,8 @@
 	return status;
 }
 
-static int ql_adapter_down(struct ql_adapter *qdev)
+static void ql_cancel_all_work_sync(struct ql_adapter *qdev)
 {
-	int i, status = 0;
-
-	ql_link_off(qdev);
 
 	/* Don't kill the reset worker thread if we
 	 * are in the process of recovery.
@@ -3904,6 +3902,15 @@
 	cancel_delayed_work_sync(&qdev->mpi_idc_work);
 	cancel_delayed_work_sync(&qdev->mpi_core_to_log);
 	cancel_delayed_work_sync(&qdev->mpi_port_cfg_work);
+}
+
+static int ql_adapter_down(struct ql_adapter *qdev)
+{
+	int i, status = 0;
+
+	ql_link_off(qdev);
+
+	ql_cancel_all_work_sync(qdev);
 
 	for (i = 0; i < qdev->rss_ring_count; i++)
 		napi_disable(&qdev->rx_ring[i].napi);
@@ -4726,6 +4733,7 @@
 	struct net_device *ndev = pci_get_drvdata(pdev);
 	struct ql_adapter *qdev = netdev_priv(ndev);
 	del_timer_sync(&qdev->timer);
+	ql_cancel_all_work_sync(qdev);
 	unregister_netdev(ndev);
 	ql_release_all(pdev);
 	pci_disable_device(pdev);
@@ -4745,13 +4753,7 @@
 
 	/* Disabling the timer */
 	del_timer_sync(&qdev->timer);
-	if (test_bit(QL_ADAPTER_UP, &qdev->flags))
-		cancel_delayed_work_sync(&qdev->asic_reset_work);
-	cancel_delayed_work_sync(&qdev->mpi_reset_work);
-	cancel_delayed_work_sync(&qdev->mpi_work);
-	cancel_delayed_work_sync(&qdev->mpi_idc_work);
-	cancel_delayed_work_sync(&qdev->mpi_core_to_log);
-	cancel_delayed_work_sync(&qdev->mpi_port_cfg_work);
+	ql_cancel_all_work_sync(qdev);
 
 	for (i = 0; i < qdev->rss_ring_count; i++)
 		netif_napi_del(&qdev->rx_ring[i].napi);
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 142c381..0b014c89 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -200,7 +200,7 @@
 	int old_duplex;
 };
 
-static char version[] __devinitdata = KERN_INFO DRV_NAME
+static char version[] __devinitdata = DRV_NAME
 	": RDC R6040 NAPI net driver,"
 	"version "DRV_VERSION " (" DRV_RELDATE ")";
 
@@ -224,7 +224,8 @@
 }
 
 /* Write a word data from PHY Chip */
-static void r6040_phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val)
+static void r6040_phy_write(void __iomem *ioaddr,
+					int phy_addr, int reg, u16 val)
 {
 	int limit = 2048;
 	u16 cmd;
@@ -348,8 +349,8 @@
 		}
 		desc->skb_ptr = skb;
 		desc->buf = cpu_to_le32(pci_map_single(lp->pdev,
-						desc->skb_ptr->data,
-						MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+					desc->skb_ptr->data,
+					MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
 		desc->status = DSC_OWNER_MAC;
 		desc = desc->vndescp;
 	} while (desc != lp->rx_ring);
@@ -491,12 +492,14 @@
 
 	/* Free Descriptor memory */
 	if (lp->rx_ring) {
-		pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma);
+		pci_free_consistent(pdev,
+				RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma);
 		lp->rx_ring = NULL;
 	}
 
 	if (lp->tx_ring) {
-		pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma);
+		pci_free_consistent(pdev,
+				TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma);
 		lp->tx_ring = NULL;
 	}
 
@@ -547,7 +550,7 @@
 			}
 			goto next_descr;
 		}
-		
+
 		/* Packet successfully received */
 		new_skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
 		if (!new_skb) {
@@ -556,13 +559,13 @@
 		}
 		skb_ptr = descptr->skb_ptr;
 		skb_ptr->dev = priv->dev;
-		
+
 		/* Do not count the CRC */
 		skb_put(skb_ptr, descptr->len - 4);
 		pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
 					MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
 		skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev);
-		
+
 		/* Send to upper layer */
 		netif_receive_skb(skb_ptr);
 		dev->stats.rx_packets++;
@@ -710,8 +713,10 @@
 		return ret;
 
 	/* improve performance (by RDC guys) */
-	r6040_phy_write(ioaddr, 30, 17, (r6040_phy_read(ioaddr, 30, 17) | 0x4000));
-	r6040_phy_write(ioaddr, 30, 17, ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000));
+	r6040_phy_write(ioaddr, 30, 17,
+			(r6040_phy_read(ioaddr, 30, 17) | 0x4000));
+	r6040_phy_write(ioaddr, 30, 17,
+			~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000));
 	r6040_phy_write(ioaddr, 0, 19, 0x0000);
 	r6040_phy_write(ioaddr, 0, 30, 0x01F0);
 
@@ -740,6 +745,9 @@
 	iowrite16(adrp[0], ioaddr + MID_0L);
 	iowrite16(adrp[1], ioaddr + MID_0M);
 	iowrite16(adrp[2], ioaddr + MID_0H);
+
+	/* Store MAC Address in perm_addr */
+	memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
 }
 
 static int r6040_open(struct net_device *dev)
@@ -751,7 +759,7 @@
 	ret = request_irq(dev->irq, r6040_interrupt,
 		IRQF_SHARED, dev->name, dev);
 	if (ret)
-		return ret;
+		goto out;
 
 	/* Set MAC address */
 	r6040_mac_address(dev);
@@ -759,30 +767,37 @@
 	/* Allocate Descriptor memory */
 	lp->rx_ring =
 		pci_alloc_consistent(lp->pdev, RX_DESC_SIZE, &lp->rx_ring_dma);
-	if (!lp->rx_ring)
-		return -ENOMEM;
+	if (!lp->rx_ring) {
+		ret = -ENOMEM;
+		goto err_free_irq;
+	}
 
 	lp->tx_ring =
 		pci_alloc_consistent(lp->pdev, TX_DESC_SIZE, &lp->tx_ring_dma);
 	if (!lp->tx_ring) {
-		pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
-				     lp->rx_ring_dma);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_free_rx_ring;
 	}
 
 	ret = r6040_up(dev);
-	if (ret) {
-		pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring,
-							lp->tx_ring_dma);
-		pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
-							lp->rx_ring_dma);
-		return ret;
-	}
+	if (ret)
+		goto err_free_tx_ring;
 
 	napi_enable(&lp->napi);
 	netif_start_queue(dev);
 
 	return 0;
+
+err_free_tx_ring:
+	pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring,
+			lp->tx_ring_dma);
+err_free_rx_ring:
+	pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
+			lp->rx_ring_dma);
+err_free_irq:
+	free_irq(dev->irq, dev);
+out:
+	return ret;
 }
 
 static netdev_tx_t r6040_start_xmit(struct sk_buff *skb,
@@ -893,16 +908,18 @@
 	/* Multicast Address 1~4 case */
 	i = 0;
 	netdev_for_each_mc_addr(ha, dev) {
-		if (i < MCAST_MAX) {
-			adrp = (u16 *) ha->addr;
-			iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
-			iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
-			iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
-		} else {
-			iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
-			iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
-			iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
-		}
+		if (i >= MCAST_MAX)
+			break;
+		adrp = (u16 *) ha->addr;
+		iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
+		iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
+		iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
+		i++;
+	}
+	while (i < MCAST_MAX) {
+		iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
+		iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
+		iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
 		i++;
 	}
 }
@@ -946,7 +963,7 @@
 	.ndo_set_multicast_list = r6040_multicast_list,
 	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_do_ioctl		= r6040_ioctl,
 	.ndo_tx_timeout		= r6040_tx_timeout,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1039,7 +1056,7 @@
 	u16 *adrp;
 	int i;
 
-	printk("%s\n", version);
+	pr_info("%s\n", version);
 
 	err = pci_enable_device(pdev);
 	if (err)
@@ -1113,7 +1130,8 @@
 	/* Some bootloader/BIOSes do not initialize
 	 * MAC address, warn about that */
 	if (!(adrp[0] || adrp[1] || adrp[2])) {
-		netdev_warn(dev, "MAC address not initialized, generating random\n");
+		netdev_warn(dev, "MAC address not initialized, "
+					"generating random\n");
 		random_ether_addr(dev->dev_addr);
 	}
 
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index a0da4a1..d88ce9f 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -187,12 +187,7 @@
 
 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
-/*
- * we set our copybreak very high so that we don't have
- * to allocate 16k frames all the time (see note in
- * rtl8169_open()
- */
-static int rx_copybreak = 16383;
+static int rx_buf_sz = 16383;
 static int use_dac;
 static struct {
 	u32 msg_enable;
@@ -484,10 +479,8 @@
 	struct RxDesc *RxDescArray;	/* 256-aligned Rx descriptor ring */
 	dma_addr_t TxPhyAddr;
 	dma_addr_t RxPhyAddr;
-	struct sk_buff *Rx_skbuff[NUM_RX_DESC];	/* Rx data buffers */
+	void *Rx_databuff[NUM_RX_DESC];	/* Rx data buffers */
 	struct ring_info tx_skb[NUM_TX_DESC];	/* Tx data buffers */
-	unsigned align;
-	unsigned rx_buf_sz;
 	struct timer_list timer;
 	u16 cp_cmd;
 	u16 intr_event;
@@ -515,8 +508,6 @@
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
 MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
-module_param(rx_copybreak, int, 0);
-MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
 module_param(use_dac, int, 0);
 MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
 module_param_named(debug, debug.msg_enable, int, 0);
@@ -1043,7 +1034,7 @@
 static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
 				      struct sk_buff *skb)
 {
-	return (tp->vlgrp && vlan_tx_tag_present(skb)) ?
+	return (vlan_tx_tag_present(skb)) ?
 		TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
 }
 
@@ -1076,7 +1067,12 @@
 	int ret;
 
 	if (vlgrp && (opts2 & RxVlanTag)) {
-		__vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling);
+		u16 vtag = 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;
@@ -1204,6 +1200,7 @@
 	dma_addr_t paddr;
 	u32 cmd;
 	int wait = 1000;
+	struct device *d = &tp->pci_dev->dev;
 
 	/*
 	 * Some chips are unable to dump tally counters when the receiver
@@ -1212,7 +1209,7 @@
 	if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
 		return;
 
-	counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr);
+	counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL);
 	if (!counters)
 		return;
 
@@ -1233,7 +1230,7 @@
 	RTL_W32(CounterAddrLow, 0);
 	RTL_W32(CounterAddrHigh, 0);
 
-	pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr);
+	dma_free_coherent(d, sizeof(*counters), counters, paddr);
 }
 
 static void rtl8169_get_ethtool_stats(struct net_device *dev,
@@ -3186,9 +3183,9 @@
 #ifdef CONFIG_R8169_VLAN
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 #endif
+	dev->features |= NETIF_F_GRO;
 
 	tp->intr_mask = 0xffff;
-	tp->align = cfg->align;
 	tp->hw_start = cfg->hw_start;
 	tp->intr_event = cfg->intr_event;
 	tp->napi_event = cfg->napi_event;
@@ -3258,18 +3255,6 @@
 	pci_set_drvdata(pdev, NULL);
 }
 
-static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
-				  unsigned int mtu)
-{
-	unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
-
-	if (max_frame != 16383)
-		printk(KERN_WARNING PFX "WARNING! Changing of MTU on this "
-			"NIC may lead to frame reception errors!\n");
-
-	tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE;
-}
-
 static int rtl8169_open(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -3279,28 +3264,16 @@
 	pm_runtime_get_sync(&pdev->dev);
 
 	/*
-	 * Note that we use a magic value here, its wierd I know
-	 * its done because, some subset of rtl8169 hardware suffers from
-	 * a problem in which frames received that are longer than
-	 * the size set in RxMaxSize register return garbage sizes
-	 * when received.  To avoid this we need to turn off filtering,
-	 * which is done by setting a value of 16383 in the RxMaxSize register
-	 * and allocating 16k frames to handle the largest possible rx value
-	 * thats what the magic math below does.
-	 */
-	rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN);
-
-	/*
 	 * Rx and Tx desscriptors needs 256 bytes alignment.
-	 * pci_alloc_consistent provides more.
+	 * dma_alloc_coherent provides more.
 	 */
-	tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES,
-					       &tp->TxPhyAddr);
+	tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
+					     &tp->TxPhyAddr, GFP_KERNEL);
 	if (!tp->TxDescArray)
 		goto err_pm_runtime_put;
 
-	tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES,
-					       &tp->RxPhyAddr);
+	tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
+					     &tp->RxPhyAddr, GFP_KERNEL);
 	if (!tp->RxDescArray)
 		goto err_free_tx_0;
 
@@ -3334,12 +3307,12 @@
 err_release_ring_2:
 	rtl8169_rx_clear(tp);
 err_free_rx_1:
-	pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
-			    tp->RxPhyAddr);
+	dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
+			  tp->RxPhyAddr);
 	tp->RxDescArray = NULL;
 err_free_tx_0:
-	pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
-			    tp->TxPhyAddr);
+	dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
+			  tp->TxPhyAddr);
 	tp->TxDescArray = NULL;
 err_pm_runtime_put:
 	pm_runtime_put_noidle(&pdev->dev);
@@ -3466,7 +3439,7 @@
 
 	RTL_W8(EarlyTxThres, EarlyTxThld);
 
-	rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz);
+	rtl_set_rx_max_size(ioaddr, rx_buf_sz);
 
 	if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
 	    (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
@@ -3727,7 +3700,7 @@
 
 	RTL_W8(EarlyTxThres, EarlyTxThld);
 
-	rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz);
+	rtl_set_rx_max_size(ioaddr, rx_buf_sz);
 
 	tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
 
@@ -3907,7 +3880,7 @@
 
 	RTL_W8(EarlyTxThres, EarlyTxThld);
 
-	rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz);
+	rtl_set_rx_max_size(ioaddr, rx_buf_sz);
 
 	tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
 
@@ -3935,33 +3908,11 @@
 
 static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct rtl8169_private *tp = netdev_priv(dev);
-	int ret = 0;
-
 	if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu)
 		return -EINVAL;
 
 	dev->mtu = new_mtu;
-
-	if (!netif_running(dev))
-		goto out;
-
-	rtl8169_down(dev);
-
-	rtl8169_set_rxbufsize(tp, dev->mtu);
-
-	ret = rtl8169_init_ring(dev);
-	if (ret < 0)
-		goto out;
-
-	napi_enable(&tp->napi);
-
-	rtl_hw_start(dev);
-
-	rtl8169_request_timer(dev);
-
-out:
-	return ret;
+	return 0;
 }
 
 static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
@@ -3970,15 +3921,14 @@
 	desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
 }
 
-static void rtl8169_free_rx_skb(struct rtl8169_private *tp,
-				struct sk_buff **sk_buff, struct RxDesc *desc)
+static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
+				     void **data_buff, struct RxDesc *desc)
 {
-	struct pci_dev *pdev = tp->pci_dev;
+	dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz,
+			 DMA_FROM_DEVICE);
 
-	pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz,
-			 PCI_DMA_FROMDEVICE);
-	dev_kfree_skb(*sk_buff);
-	*sk_buff = NULL;
+	kfree(*data_buff);
+	*data_buff = NULL;
 	rtl8169_make_unusable_by_asic(desc);
 }
 
@@ -3997,33 +3947,45 @@
 	rtl8169_mark_to_asic(desc, rx_buf_sz);
 }
 
-static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
-					    struct net_device *dev,
-					    struct RxDesc *desc, int rx_buf_sz,
-					    unsigned int align)
+static inline void *rtl8169_align(void *data)
 {
-	struct sk_buff *skb;
+	return (void *)ALIGN((long)data, 16);
+}
+
+static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
+					     struct RxDesc *desc)
+{
+	void *data;
 	dma_addr_t mapping;
-	unsigned int pad;
+	struct device *d = &tp->pci_dev->dev;
+	struct net_device *dev = tp->dev;
+	int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
 
-	pad = align ? align : NET_IP_ALIGN;
+	data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
+	if (!data)
+		return NULL;
 
-	skb = netdev_alloc_skb(dev, rx_buf_sz + pad);
-	if (!skb)
+	if (rtl8169_align(data) != data) {
+		kfree(data);
+		data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node);
+		if (!data)
+			return NULL;
+	}
+
+	mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz,
+				 DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(d, mapping))) {
+		if (net_ratelimit())
+			netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
 		goto err_out;
-
-	skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad);
-
-	mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
-				 PCI_DMA_FROMDEVICE);
+	}
 
 	rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
-out:
-	return skb;
+	return data;
 
 err_out:
-	rtl8169_make_unusable_by_asic(desc);
-	goto out;
+	kfree(data);
+	return NULL;
 }
 
 static void rtl8169_rx_clear(struct rtl8169_private *tp)
@@ -4031,43 +3993,44 @@
 	unsigned int i;
 
 	for (i = 0; i < NUM_RX_DESC; i++) {
-		if (tp->Rx_skbuff[i]) {
-			rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i,
+		if (tp->Rx_databuff[i]) {
+			rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
 					    tp->RxDescArray + i);
 		}
 	}
 }
 
-static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
-			   u32 start, u32 end)
-{
-	u32 cur;
-
-	for (cur = start; end - cur != 0; cur++) {
-		struct sk_buff *skb;
-		unsigned int i = cur % NUM_RX_DESC;
-
-		WARN_ON((s32)(end - cur) < 0);
-
-		if (tp->Rx_skbuff[i])
-			continue;
-
-		skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev,
-					   tp->RxDescArray + i,
-					   tp->rx_buf_sz, tp->align);
-		if (!skb)
-			break;
-
-		tp->Rx_skbuff[i] = skb;
-	}
-	return cur - start;
-}
-
 static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
 {
 	desc->opts1 |= cpu_to_le32(RingEnd);
 }
 
+static int rtl8169_rx_fill(struct rtl8169_private *tp)
+{
+	unsigned int i;
+
+	for (i = 0; i < NUM_RX_DESC; i++) {
+		void *data;
+
+		if (tp->Rx_databuff[i])
+			continue;
+
+		data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
+		if (!data) {
+			rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
+			goto err_out;
+		}
+		tp->Rx_databuff[i] = data;
+	}
+
+	rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
+	return 0;
+
+err_out:
+	rtl8169_rx_clear(tp);
+	return -ENOMEM;
+}
+
 static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
 {
 	tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
@@ -4080,53 +4043,51 @@
 	rtl8169_init_ring_indexes(tp);
 
 	memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
-	memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
+	memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *));
 
-	if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
-		goto err_out;
-
-	rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
-
-	return 0;
-
-err_out:
-	rtl8169_rx_clear(tp);
-	return -ENOMEM;
+	return rtl8169_rx_fill(tp);
 }
 
-static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb,
+static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb,
 				 struct TxDesc *desc)
 {
 	unsigned int len = tx_skb->len;
 
-	pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE);
+	dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE);
+
 	desc->opts1 = 0x00;
 	desc->opts2 = 0x00;
 	desc->addr = 0x00;
 	tx_skb->len = 0;
 }
 
-static void rtl8169_tx_clear(struct rtl8169_private *tp)
+static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
+				   unsigned int n)
 {
 	unsigned int i;
 
-	for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) {
-		unsigned int entry = i % NUM_TX_DESC;
+	for (i = 0; i < n; i++) {
+		unsigned int entry = (start + i) % NUM_TX_DESC;
 		struct ring_info *tx_skb = tp->tx_skb + entry;
 		unsigned int len = tx_skb->len;
 
 		if (len) {
 			struct sk_buff *skb = tx_skb->skb;
 
-			rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb,
+			rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
 					     tp->TxDescArray + entry);
 			if (skb) {
+				tp->dev->stats.tx_dropped++;
 				dev_kfree_skb(skb);
 				tx_skb->skb = NULL;
 			}
-			tp->dev->stats.tx_dropped++;
 		}
 	}
+}
+
+static void rtl8169_tx_clear(struct rtl8169_private *tp)
+{
+	rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
 	tp->cur_tx = tp->dirty_tx = 0;
 }
 
@@ -4230,6 +4191,7 @@
 	struct skb_shared_info *info = skb_shinfo(skb);
 	unsigned int cur_frag, entry;
 	struct TxDesc * uninitialized_var(txd);
+	struct device *d = &tp->pci_dev->dev;
 
 	entry = tp->cur_tx;
 	for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
@@ -4243,7 +4205,13 @@
 		txd = tp->TxDescArray + entry;
 		len = frag->size;
 		addr = ((void *) page_address(frag->page)) + frag->page_offset;
-		mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE);
+		mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(d, mapping))) {
+			if (net_ratelimit())
+				netif_err(tp, drv, tp->dev,
+					  "Failed to map TX fragments DMA!\n");
+			goto err_out;
+		}
 
 		/* anti gcc 2.95.3 bugware (sic) */
 		status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
@@ -4260,6 +4228,10 @@
 	}
 
 	return cur_frag;
+
+err_out:
+	rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
+	return -EIO;
 }
 
 static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
@@ -4286,39 +4258,47 @@
 				      struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
-	unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC;
+	unsigned int entry = tp->cur_tx % NUM_TX_DESC;
 	struct TxDesc *txd = tp->TxDescArray + entry;
 	void __iomem *ioaddr = tp->mmio_addr;
+	struct device *d = &tp->pci_dev->dev;
 	dma_addr_t mapping;
 	u32 status, len;
 	u32 opts1;
+	int frags;
 
 	if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
 		netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
-		goto err_stop;
+		goto err_stop_0;
 	}
 
 	if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
-		goto err_stop;
+		goto err_stop_0;
 
-	opts1 = DescOwn | rtl8169_tso_csum(skb, dev);
-
-	frags = rtl8169_xmit_frags(tp, skb, opts1);
-	if (frags) {
-		len = skb_headlen(skb);
-		opts1 |= FirstFrag;
-	} else {
-		len = skb->len;
-		opts1 |= FirstFrag | LastFrag;
-		tp->tx_skb[entry].skb = skb;
+	len = skb_headlen(skb);
+	mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(d, mapping))) {
+		if (net_ratelimit())
+			netif_err(tp, drv, dev, "Failed to map TX DMA!\n");
+		goto err_dma_0;
 	}
 
-	mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE);
-
 	tp->tx_skb[entry].len = len;
 	txd->addr = cpu_to_le64(mapping);
 	txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb));
 
+	opts1 = DescOwn | rtl8169_tso_csum(skb, dev);
+
+	frags = rtl8169_xmit_frags(tp, skb, opts1);
+	if (frags < 0)
+		goto err_dma_1;
+	else if (frags)
+		opts1 |= FirstFrag;
+	else {
+		opts1 |= FirstFrag | LastFrag;
+		tp->tx_skb[entry].skb = skb;
+	}
+
 	wmb();
 
 	/* anti gcc 2.95.3 bugware (sic) */
@@ -4340,7 +4320,14 @@
 
 	return NETDEV_TX_OK;
 
-err_stop:
+err_dma_1:
+	rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
+err_dma_0:
+	dev_kfree_skb(skb);
+	dev->stats.tx_dropped++;
+	return NETDEV_TX_OK;
+
+err_stop_0:
 	netif_stop_queue(dev);
 	dev->stats.tx_dropped++;
 	return NETDEV_TX_BUSY;
@@ -4405,7 +4392,6 @@
 	while (tx_left > 0) {
 		unsigned int entry = dirty_tx % NUM_TX_DESC;
 		struct ring_info *tx_skb = tp->tx_skb + entry;
-		u32 len = tx_skb->len;
 		u32 status;
 
 		rmb();
@@ -4413,12 +4399,11 @@
 		if (status & DescOwn)
 			break;
 
-		dev->stats.tx_bytes += len;
-		dev->stats.tx_packets++;
-
-		rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry);
-
+		rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
+				     tp->TxDescArray + entry);
 		if (status & LastFrag) {
+			dev->stats.tx_packets++;
+			dev->stats.tx_bytes += tx_skb->skb->len;
 			dev_kfree_skb(tx_skb->skb);
 			tx_skb->skb = NULL;
 		}
@@ -4450,9 +4435,8 @@
 	return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
 }
 
-static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
+static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
 {
-	u32 opts1 = le32_to_cpu(desc->opts1);
 	u32 status = opts1 & RxProtoMask;
 
 	if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
@@ -4460,30 +4444,26 @@
 	    ((status == RxProtoIP) && !(opts1 & IPFail)))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	else
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 }
 
-static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff,
-				       struct rtl8169_private *tp, int pkt_size,
-				       dma_addr_t addr)
+static struct sk_buff *rtl8169_try_rx_copy(void *data,
+					   struct rtl8169_private *tp,
+					   int pkt_size,
+					   dma_addr_t addr)
 {
 	struct sk_buff *skb;
-	bool done = false;
+	struct device *d = &tp->pci_dev->dev;
 
-	if (pkt_size >= rx_copybreak)
-		goto out;
-
+	data = rtl8169_align(data);
+	dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
+	prefetch(data);
 	skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
-	if (!skb)
-		goto out;
+	if (skb)
+		memcpy(skb->data, data, pkt_size);
+	dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
 
-	pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size,
-				    PCI_DMA_FROMDEVICE);
-	skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size);
-	*sk_buff = skb;
-	done = true;
-out:
-	return done;
+	return skb;
 }
 
 /*
@@ -4498,7 +4478,7 @@
 				void __iomem *ioaddr, u32 budget)
 {
 	unsigned int cur_rx, rx_left;
-	unsigned int delta, count;
+	unsigned int count;
 	int polling = (budget != ~(u32)0) ? 1 : 0;
 
 	cur_rx = tp->cur_rx;
@@ -4527,12 +4507,11 @@
 				rtl8169_schedule_work(dev, rtl8169_reset_task);
 				dev->stats.rx_fifo_errors++;
 			}
-			rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+			rtl8169_mark_to_asic(desc, rx_buf_sz);
 		} else {
-			struct sk_buff *skb = tp->Rx_skbuff[entry];
+			struct sk_buff *skb;
 			dma_addr_t addr = le64_to_cpu(desc->addr);
 			int pkt_size = (status & 0x00001FFF) - 4;
-			struct pci_dev *pdev = tp->pci_dev;
 
 			/*
 			 * The driver does not support incoming fragmented
@@ -4542,28 +4521,25 @@
 			if (unlikely(rtl8169_fragmented_frame(status))) {
 				dev->stats.rx_dropped++;
 				dev->stats.rx_length_errors++;
-				rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+				rtl8169_mark_to_asic(desc, rx_buf_sz);
 				continue;
 			}
 
-			rtl8169_rx_csum(skb, desc);
-
-			if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) {
-				pci_dma_sync_single_for_device(pdev, addr,
-					pkt_size, PCI_DMA_FROMDEVICE);
-				rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
-			} else {
-				pci_unmap_single(pdev, addr, tp->rx_buf_sz,
-						 PCI_DMA_FROMDEVICE);
-				tp->Rx_skbuff[entry] = NULL;
+			skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
+						  tp, pkt_size, addr);
+			rtl8169_mark_to_asic(desc, rx_buf_sz);
+			if (!skb) {
+				dev->stats.rx_dropped++;
+				continue;
 			}
 
+			rtl8169_rx_csum(skb, status);
 			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))
-					netif_receive_skb(skb);
+					napi_gro_receive(&tp->napi, skb);
 				else
 					netif_rx(skb);
 			}
@@ -4583,20 +4559,7 @@
 	count = cur_rx - tp->cur_rx;
 	tp->cur_rx = cur_rx;
 
-	delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
-	if (!delta && count)
-		netif_info(tp, intr, dev, "no Rx buffer allocated\n");
-	tp->dirty_rx += delta;
-
-	/*
-	 * FIXME: until there is periodic timer to try and refill the ring,
-	 * a temporary shortage may definitely kill the Rx process.
-	 * - disable the asic to try and avoid an overflow and kick it again
-	 *   after refill ?
-	 * - how do others driver handle this condition (Uh oh...).
-	 */
-	if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
-		netif_emerg(tp, intr, dev, "Rx buffers exhausted\n");
+	tp->dirty_rx += count;
 
 	return count;
 }
@@ -4711,7 +4674,6 @@
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
-	unsigned int intrmask;
 
 	rtl8169_delete_timer(dev);
 
@@ -4719,11 +4681,14 @@
 
 	napi_disable(&tp->napi);
 
-core_down:
 	spin_lock_irq(&tp->lock);
 
 	rtl8169_asic_down(ioaddr);
-
+	/*
+	 * At this point device interrupts can not be enabled in any function,
+	 * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task,
+	 * rtl8169_reinit_task) and napi is disabled (rtl8169_poll).
+	 */
 	rtl8169_rx_missed(dev, ioaddr);
 
 	spin_unlock_irq(&tp->lock);
@@ -4733,23 +4698,6 @@
 	/* Give a racing hard_start_xmit a few cycles to complete. */
 	synchronize_sched();  /* FIXME: should this be synchronize_irq()? */
 
-	/*
-	 * And now for the 50k$ question: are IRQ disabled or not ?
-	 *
-	 * Two paths lead here:
-	 * 1) dev->close
-	 *    -> netif_running() is available to sync the current code and the
-	 *       IRQ handler. See rtl8169_interrupt for details.
-	 * 2) dev->change_mtu
-	 *    -> rtl8169_poll can not be issued again and re-enable the
-	 *       interruptions. Let's simply issue the IRQ down sequence again.
-	 *
-	 * No loop if hotpluged or major error (0xffff).
-	 */
-	intrmask = RTL_R16(IntrMask);
-	if (intrmask && (intrmask != 0xffff))
-		goto core_down;
-
 	rtl8169_tx_clear(tp);
 
 	rtl8169_rx_clear(tp);
@@ -4769,10 +4717,10 @@
 
 	free_irq(dev->irq, dev);
 
-	pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
-			    tp->RxPhyAddr);
-	pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
-			    tp->TxPhyAddr);
+	dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
+			  tp->RxPhyAddr);
+	dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
+			  tp->TxPhyAddr);
 	tp->TxDescArray = NULL;
 	tp->RxDescArray = NULL;
 
@@ -4886,6 +4834,9 @@
 {
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rtl8169_private *tp = netdev_priv(dev);
+
+	rtl8169_init_phy(dev, tp);
 
 	if (netif_running(dev))
 		__rtl8169_resume(dev);
@@ -4926,6 +4877,8 @@
 	tp->saved_wolopts = 0;
 	spin_unlock_irq(&tp->lock);
 
+	rtl8169_init_phy(dev, tp);
+
 	__rtl8169_resume(dev);
 
 	return 0;
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 07eb884..44150f2 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -384,7 +384,7 @@
 	free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
 					__ilog2(sizeof(void *)) + 4 : 0);
 	unregister_netdev(ndev);
-	kfree(ndev);
+	free_netdev(ndev);
 
 	list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
 		list_del(&peer->node);
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index e26e107..e68c941 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -1245,7 +1245,7 @@
 	init_timer(&rrpriv->timer);
 	rrpriv->timer.expires = RUN_AT(5*HZ);           /* 5 sec. watchdog */
 	rrpriv->timer.data = (unsigned long)dev;
-	rrpriv->timer.function = &rr_timer;               /* timer handler */
+	rrpriv->timer.function = rr_timer;               /* timer handler */
 	add_timer(&rrpriv->timer);
 
 	netif_start_queue(dev);
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 18bc5b7..ecc25aa 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -38,8 +38,6 @@
  * Tx descriptors that can be associated with each corresponding FIFO.
  * intr_type: This defines the type of interrupt. The values can be 0(INTA),
  *     2(MSI_X). Default value is '2(MSI_X)'
- * lro: Specifies whether to enable Large Receive Offload (LRO) or not.
- *     Possible values '1' for enable '0' for disable. Default is '0'
  * lro_max_pkts: This parameter defines maximum number of packets can be
  *     aggregated as a single large packet
  * napi: This parameter used to enable/disable NAPI (polling Rx)
@@ -90,7 +88,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.26.26"
+#define DRV_VERSION "2.0.26.27"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -496,8 +494,6 @@
 /* Interrupt type. Values can be 0(INTA), 2(MSI_X) */
 S2IO_PARM_INT(intr_type, 2);
 /* Large receive offload feature */
-static unsigned int lro_enable = 1;
-module_param_named(lro, lro_enable, uint, 0);
 
 /* Max pkts to be aggregated by LRO at one time. If not specified,
  * aggregation happens until we hit max IP pkt size(64K)
@@ -4105,7 +4101,7 @@
 	}
 
 	queue = 0;
-	if (sp->vlgrp && vlan_tx_tag_present(skb))
+	if (vlan_tx_tag_present(skb))
 		vlan_tag = vlan_tx_tag_get(skb);
 	if (sp->config.tx_steering_type == TX_DEFAULT_STEERING) {
 		if (skb->protocol == htons(ETH_P_IP)) {
@@ -5124,8 +5120,6 @@
 		/* Create the new Rx filter list and update the same in H/W. */
 		i = 0;
 		netdev_for_each_mc_addr(ha, dev) {
-			memcpy(sp->usr_addrs[i].addr, ha->addr,
-			       ETH_ALEN);
 			mac_addr = 0;
 			for (j = 0; j < ETH_ALEN; j++) {
 				mac_addr |= ha->addr[j];
@@ -6735,13 +6729,10 @@
 		return -EINVAL;
 
 	if (data & ETH_FLAG_LRO) {
-		if (lro_enable) {
-			if (!(dev->features & NETIF_F_LRO)) {
-				dev->features |= NETIF_F_LRO;
-				changed = 1;
-			}
-		} else
-			rc = -EINVAL;
+		if (!(dev->features & NETIF_F_LRO)) {
+			dev->features |= NETIF_F_LRO;
+			changed = 1;
+		}
 	} else if (dev->features & NETIF_F_LRO) {
 		dev->features &= ~NETIF_F_LRO;
 		changed = 1;
@@ -6750,7 +6741,6 @@
 	if (changed && netif_running(dev)) {
 		s2io_stop_all_tx_queue(sp);
 		s2io_card_down(sp);
-		sp->lro = !!(dev->features & NETIF_F_LRO);
 		rc = s2io_card_up(sp);
 		if (rc)
 			s2io_reset(sp);
@@ -7307,7 +7297,7 @@
 		struct ring_info *ring = &mac_control->rings[i];
 
 		ring->mtu = dev->mtu;
-		ring->lro = sp->lro;
+		ring->lro = !!(dev->features & NETIF_F_LRO);
 		ret = fill_rx_buffers(sp, ring, 1);
 		if (ret) {
 			DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n",
@@ -7341,7 +7331,7 @@
 	/* Setting its receive mode */
 	s2io_set_multicast(dev);
 
-	if (sp->lro) {
+	if (dev->features & NETIF_F_LRO) {
 		/* Initialize max aggregatable pkts per session based on MTU */
 		sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu;
 		/* Check if we can use (if specified) user provided value */
@@ -7613,10 +7603,10 @@
 			 * Packet with erroneous checksum, let the
 			 * upper layers deal with it.
 			 */
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
 		}
 	} else
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 
 	swstats->mem_freed += skb->truesize;
 send_up:
@@ -7911,7 +7901,6 @@
 	else
 		sp->device_type = XFRAME_I_DEVICE;
 
-	sp->lro = lro_enable;
 
 	/* Initialize some PCI/PCI-X fields of the NIC. */
 	s2io_init_pci(sp);
@@ -8047,8 +8036,7 @@
 	dev->netdev_ops = &s2io_netdev_ops;
 	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-	if (lro_enable)
-		dev->features |= NETIF_F_LRO;
+	dev->features |= NETIF_F_LRO;
 	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
 	if (sp->high_dma_flag == true)
 		dev->features |= NETIF_F_HIGHDMA;
@@ -8283,9 +8271,8 @@
 			  dev->name);
 	}
 
-	if (sp->lro)
-		DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
-			  dev->name);
+	DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
+		  dev->name);
 	if (ufo)
 		DBG_PRINT(ERR_DBG,
 			  "%s: UDP Fragmentation Offload(UFO) enabled\n",
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 0af0335..00b8614 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -816,12 +816,6 @@
 	struct stat_block *stats_info;	/* Logical address of the stat block */
 };
 
-/* structure representing the user defined MAC addresses */
-struct usr_addr {
-	char addr[ETH_ALEN];
-	int usage_cnt;
-};
-
 /* Default Tunable parameters of the NIC. */
 #define DEFAULT_FIFO_0_LEN 4096
 #define DEFAULT_FIFO_1_7_LEN 512
@@ -894,9 +888,7 @@
 #define ALL_MULTI   2
 
 #define MAX_ADDRS_SUPPORTED 64
-	u16 usr_addr_count;
 	u16 mc_addr_count;
-	struct usr_addr usr_addrs[256];
 
 	u16 m_cast_flg;
 	u16 all_multi_pos;
@@ -971,7 +963,6 @@
 
 	unsigned long	clubbed_frms_cnt;
 	unsigned long	sending_both;
-	u8		lro;
 	u16		lro_max_aggr_per_sess;
 	volatile unsigned long state;
 	u64		general_int_mask;
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 8e6bd45..d8249d7 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -1170,7 +1170,7 @@
 						sb->ip_summed = CHECKSUM_UNNECESSARY;
 						/* don't need to set sb->csum */
 					} else {
-						sb->ip_summed = CHECKSUM_NONE;
+						skb_checksum_none_assert(sb);
 					}
 				}
 				prefetch(sb->data);
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index 8c4067a..31b92f5 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -1251,16 +1251,6 @@
 	return 0;
 }
 
-static void sc92031_ethtool_get_drvinfo(struct net_device *dev,
-		struct ethtool_drvinfo *drvinfo)
-{
-	struct sc92031_priv *priv = netdev_priv(dev);
-	struct pci_dev *pdev = priv->pdev;
-
-	strcpy(drvinfo->driver, SC92031_NAME);
-	strcpy(drvinfo->bus_info, pci_name(pdev));
-}
-
 static void sc92031_ethtool_get_wol(struct net_device *dev,
 		struct ethtool_wolinfo *wolinfo)
 {
@@ -1382,7 +1372,6 @@
 static const struct ethtool_ops sc92031_ethtool_ops = {
 	.get_settings		= sc92031_ethtool_get_settings,
 	.set_settings		= sc92031_ethtool_set_settings,
-	.get_drvinfo		= sc92031_ethtool_get_drvinfo,
 	.get_wol		= sc92031_ethtool_get_wol,
 	.set_wol		= sc92031_ethtool_set_wol,
 	.nway_reset		= sc92031_ethtool_nway_reset,
diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile
index 1047b19..ab31c71 100644
--- a/drivers/net/sfc/Makefile
+++ b/drivers/net/sfc/Makefile
@@ -1,7 +1,8 @@
-sfc-y			+= efx.o nic.o falcon.o siena.o tx.o rx.o \
-			   falcon_gmac.o falcon_xmac.o mcdi_mac.o \
+sfc-y			+= efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \
+			   falcon_xmac.o mcdi_mac.o \
 			   selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
-			   tenxpress.o falcon_boards.o mcdi.o mcdi_phy.o
+			   tenxpress.o txc43128_phy.o falcon_boards.o \
+			   mcdi.o mcdi_phy.o
 sfc-$(CONFIG_SFC_MTD)	+= mtd.o
 
 obj-$(CONFIG_SFC)	+= sfc.o
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index ba674c5..05df20e 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -68,14 +68,6 @@
 	[LOOPBACK_PHYXS_WS]  	= "PHYXS_WS",
 };
 
-/* Interrupt mode names (see INT_MODE())) */
-const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX;
-const char *efx_interrupt_mode_names[] = {
-	[EFX_INT_MODE_MSIX]   = "MSI-X",
-	[EFX_INT_MODE_MSI]    = "MSI",
-	[EFX_INT_MODE_LEGACY] = "legacy",
-};
-
 const unsigned int efx_reset_type_max = RESET_TYPE_MAX;
 const char *efx_reset_type_names[] = {
 	[RESET_TYPE_INVISIBLE]     = "INVISIBLE",
@@ -114,7 +106,7 @@
  * This is only used in MSI-X interrupt mode
  */
 static unsigned int separate_tx_channels;
-module_param(separate_tx_channels, uint, 0644);
+module_param(separate_tx_channels, uint, 0444);
 MODULE_PARM_DESC(separate_tx_channels,
 		 "Use separate channels for TX and RX");
 
@@ -124,10 +116,11 @@
 static int napi_weight = 64;
 
 /* This is the time (in jiffies) between invocations of the hardware
- * monitor, which checks for known hardware bugs and resets the
- * hardware and driver as necessary.
+ * monitor.  On Falcon-based NICs, this will:
+ * - Check the on-board hardware monitor;
+ * - Poll the link state and reconfigure the hardware as necessary.
  */
-unsigned int efx_monitor_interval = 1 * HZ;
+static unsigned int efx_monitor_interval = 1 * HZ;
 
 /* This controls whether or not the driver will initialise devices
  * with invalid MAC addresses stored in the EEPROM or flash.  If true,
@@ -201,10 +194,13 @@
  * Utility functions and prototypes
  *
  *************************************************************************/
-static void efx_remove_channel(struct efx_channel *channel);
+
+static void efx_remove_channels(struct efx_nic *efx);
 static void efx_remove_port(struct efx_nic *efx);
 static void efx_fini_napi(struct efx_nic *efx);
-static void efx_fini_channels(struct efx_nic *efx);
+static void efx_fini_struct(struct efx_nic *efx);
+static void efx_start_all(struct efx_nic *efx);
+static void efx_stop_all(struct efx_nic *efx);
 
 #define EFX_ASSERT_RESET_SERIALISED(efx)		\
 	do {						\
@@ -248,7 +244,7 @@
 
 	efx_rx_strategy(channel);
 
-	efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
+	efx_fast_push_rx_descriptors(efx_channel_get_rx_queue(channel));
 
 	return spent;
 }
@@ -334,6 +330,7 @@
 {
 	struct efx_nic *efx = channel->efx;
 
+	BUG_ON(channel->channel >= efx->n_channels);
 	BUG_ON(!channel->enabled);
 
 	/* Disable interrupts and wait for ISRs to complete */
@@ -347,7 +344,7 @@
 	napi_disable(&channel->napi_str);
 
 	/* Poll the channel */
-	efx_process_channel(channel, EFX_EVQ_SIZE);
+	efx_process_channel(channel, channel->eventq_mask + 1);
 
 	/* Ack the eventq. This may cause an interrupt to be generated
 	 * when they are reenabled */
@@ -364,9 +361,18 @@
  */
 static int efx_probe_eventq(struct efx_channel *channel)
 {
+	struct efx_nic *efx = channel->efx;
+	unsigned long entries;
+
 	netif_dbg(channel->efx, probe, channel->efx->net_dev,
 		  "chan %d create event queue\n", channel->channel);
 
+	/* Build an event queue with room for one event per tx and rx buffer,
+	 * plus some extra for link state events and MCDI completions. */
+	entries = roundup_pow_of_two(efx->rxq_entries + efx->txq_entries + 128);
+	EFX_BUG_ON_PARANOID(entries > EFX_MAX_EVQ_SIZE);
+	channel->eventq_mask = max(entries, EFX_MIN_EVQ_SIZE) - 1;
+
 	return efx_nic_probe_eventq(channel);
 }
 
@@ -403,6 +409,63 @@
  *
  *************************************************************************/
 
+/* Allocate and initialise a channel structure, optionally copying
+ * parameters (but not resources) from an old channel structure. */
+static struct efx_channel *
+efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
+{
+	struct efx_channel *channel;
+	struct efx_rx_queue *rx_queue;
+	struct efx_tx_queue *tx_queue;
+	int j;
+
+	if (old_channel) {
+		channel = kmalloc(sizeof(*channel), GFP_KERNEL);
+		if (!channel)
+			return NULL;
+
+		*channel = *old_channel;
+
+		memset(&channel->eventq, 0, sizeof(channel->eventq));
+
+		rx_queue = &channel->rx_queue;
+		rx_queue->buffer = NULL;
+		memset(&rx_queue->rxd, 0, sizeof(rx_queue->rxd));
+
+		for (j = 0; j < EFX_TXQ_TYPES; j++) {
+			tx_queue = &channel->tx_queue[j];
+			if (tx_queue->channel)
+				tx_queue->channel = channel;
+			tx_queue->buffer = NULL;
+			memset(&tx_queue->txd, 0, sizeof(tx_queue->txd));
+		}
+	} else {
+		channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+		if (!channel)
+			return NULL;
+
+		channel->efx = efx;
+		channel->channel = i;
+
+		for (j = 0; j < EFX_TXQ_TYPES; j++) {
+			tx_queue = &channel->tx_queue[j];
+			tx_queue->efx = efx;
+			tx_queue->queue = i * EFX_TXQ_TYPES + j;
+			tx_queue->channel = channel;
+		}
+	}
+
+	spin_lock_init(&channel->tx_stop_lock);
+	atomic_set(&channel->tx_stop_count, 1);
+
+	rx_queue = &channel->rx_queue;
+	rx_queue->efx = efx;
+	setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
+		    (unsigned long)rx_queue);
+
+	return channel;
+}
+
 static int efx_probe_channel(struct efx_channel *channel)
 {
 	struct efx_tx_queue *tx_queue;
@@ -459,11 +522,38 @@
 				number -= efx->n_rx_channels;
 			}
 		}
-		snprintf(channel->name, sizeof(channel->name),
+		snprintf(efx->channel_name[channel->channel],
+			 sizeof(efx->channel_name[0]),
 			 "%s%s-%d", efx->name, type, number);
 	}
 }
 
+static int efx_probe_channels(struct efx_nic *efx)
+{
+	struct efx_channel *channel;
+	int rc;
+
+	/* Restart special buffer allocation */
+	efx->next_buffer_table = 0;
+
+	efx_for_each_channel(channel, efx) {
+		rc = efx_probe_channel(channel);
+		if (rc) {
+			netif_err(efx, probe, efx->net_dev,
+				  "failed to create channel %d\n",
+				  channel->channel);
+			goto fail;
+		}
+	}
+	efx_set_channel_names(efx);
+
+	return 0;
+
+fail:
+	efx_remove_channels(efx);
+	return rc;
+}
+
 /* Channels are shutdown and reinitialised whilst the NIC is running
  * to propagate configuration changes (mtu, checksum offload), or
  * to clear hardware error conditions
@@ -601,6 +691,75 @@
 	efx_remove_eventq(channel);
 }
 
+static void efx_remove_channels(struct efx_nic *efx)
+{
+	struct efx_channel *channel;
+
+	efx_for_each_channel(channel, efx)
+		efx_remove_channel(channel);
+}
+
+int
+efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
+{
+	struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel;
+	u32 old_rxq_entries, old_txq_entries;
+	unsigned i;
+	int rc;
+
+	efx_stop_all(efx);
+	efx_fini_channels(efx);
+
+	/* Clone channels */
+	memset(other_channel, 0, sizeof(other_channel));
+	for (i = 0; i < efx->n_channels; i++) {
+		channel = efx_alloc_channel(efx, i, efx->channel[i]);
+		if (!channel) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		other_channel[i] = channel;
+	}
+
+	/* Swap entry counts and channel pointers */
+	old_rxq_entries = efx->rxq_entries;
+	old_txq_entries = efx->txq_entries;
+	efx->rxq_entries = rxq_entries;
+	efx->txq_entries = txq_entries;
+	for (i = 0; i < efx->n_channels; i++) {
+		channel = efx->channel[i];
+		efx->channel[i] = other_channel[i];
+		other_channel[i] = channel;
+	}
+
+	rc = efx_probe_channels(efx);
+	if (rc)
+		goto rollback;
+
+	/* Destroy old channels */
+	for (i = 0; i < efx->n_channels; i++)
+		efx_remove_channel(other_channel[i]);
+out:
+	/* Free unused channel structures */
+	for (i = 0; i < efx->n_channels; i++)
+		kfree(other_channel[i]);
+
+	efx_init_channels(efx);
+	efx_start_all(efx);
+	return rc;
+
+rollback:
+	/* Swap back */
+	efx->rxq_entries = old_rxq_entries;
+	efx->txq_entries = old_txq_entries;
+	for (i = 0; i < efx->n_channels; i++) {
+		channel = efx->channel[i];
+		efx->channel[i] = other_channel[i];
+		other_channel[i] = channel;
+	}
+	goto out;
+}
+
 void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
 {
 	mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100));
@@ -761,7 +920,7 @@
 	/* Connect up MAC/PHY operations table */
 	rc = efx->type->probe_port(efx);
 	if (rc)
-		goto err;
+		return rc;
 
 	/* Sanity check MAC address */
 	if (is_valid_ether_addr(efx->mac_address)) {
@@ -782,7 +941,7 @@
 	return 0;
 
  err:
-	efx_remove_port(efx);
+	efx->type->remove_port(efx);
 	return rc;
 }
 
@@ -1050,7 +1209,8 @@
 				efx->n_rx_channels = efx->n_channels;
 			}
 			for (i = 0; i < n_channels; i++)
-				efx->channel[i].irq = xentries[i].vector;
+				efx_get_channel(efx, i)->irq =
+					xentries[i].vector;
 		} else {
 			/* Fall back to single channel MSI */
 			efx->interrupt_mode = EFX_INT_MODE_MSI;
@@ -1066,7 +1226,7 @@
 		efx->n_tx_channels = 1;
 		rc = pci_enable_msi(efx->pci_dev);
 		if (rc == 0) {
-			efx->channel[0].irq = efx->pci_dev->irq;
+			efx_get_channel(efx, 0)->irq = efx->pci_dev->irq;
 		} else {
 			netif_err(efx, drv, efx->net_dev,
 				  "could not enable MSI\n");
@@ -1097,26 +1257,32 @@
 	efx->legacy_irq = 0;
 }
 
+struct efx_tx_queue *
+efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
+{
+	unsigned tx_channel_offset =
+		separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
+	EFX_BUG_ON_PARANOID(index >= efx->n_tx_channels ||
+			    type >= EFX_TXQ_TYPES);
+	return &efx->channel[tx_channel_offset + index]->tx_queue[type];
+}
+
 static void efx_set_channels(struct efx_nic *efx)
 {
 	struct efx_channel *channel;
 	struct efx_tx_queue *tx_queue;
-	struct efx_rx_queue *rx_queue;
 	unsigned 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 - tx_channel_offset < efx->n_tx_channels) {
-			channel->tx_queue = &efx->tx_queue[
-				(channel->channel - tx_channel_offset) *
-				EFX_TXQ_TYPES];
+		if (channel->channel - tx_channel_offset >=
+		    efx->n_tx_channels) {
 			efx_for_each_channel_tx_queue(tx_queue, channel)
-				tx_queue->channel = channel;
+				tx_queue->channel = NULL;
 		}
 	}
-
-	efx_for_each_rx_queue(rx_queue, efx)
-		rx_queue->channel = &efx->channel[rx_queue->queue];
 }
 
 static int efx_probe_nic(struct efx_nic *efx)
@@ -1141,7 +1307,8 @@
 		efx->rx_indir_table[i] = i % efx->n_rx_channels;
 
 	efx_set_channels(efx);
-	efx->net_dev->real_num_tx_queues = efx->n_tx_channels;
+	netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
+	netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels);
 
 	/* Initialise the interrupt moderation settings */
 	efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true);
@@ -1165,40 +1332,37 @@
 
 static int efx_probe_all(struct efx_nic *efx)
 {
-	struct efx_channel *channel;
 	int rc;
 
-	/* Create NIC */
 	rc = efx_probe_nic(efx);
 	if (rc) {
 		netif_err(efx, probe, efx->net_dev, "failed to create NIC\n");
 		goto fail1;
 	}
 
-	/* Create port */
 	rc = efx_probe_port(efx);
 	if (rc) {
 		netif_err(efx, probe, efx->net_dev, "failed to create port\n");
 		goto fail2;
 	}
 
-	/* Create channels */
-	efx_for_each_channel(channel, efx) {
-		rc = efx_probe_channel(channel);
-		if (rc) {
-			netif_err(efx, probe, efx->net_dev,
-				  "failed to create channel %d\n",
-				  channel->channel);
-			goto fail3;
-		}
+	efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE;
+	rc = efx_probe_channels(efx);
+	if (rc)
+		goto fail3;
+
+	rc = efx_probe_filters(efx);
+	if (rc) {
+		netif_err(efx, probe, efx->net_dev,
+			  "failed to create filter tables\n");
+		goto fail4;
 	}
-	efx_set_channel_names(efx);
 
 	return 0;
 
+ fail4:
+	efx_remove_channels(efx);
  fail3:
-	efx_for_each_channel(channel, efx)
-		efx_remove_channel(channel);
 	efx_remove_port(efx);
  fail2:
 	efx_remove_nic(efx);
@@ -1328,10 +1492,8 @@
 
 static void efx_remove_all(struct efx_nic *efx)
 {
-	struct efx_channel *channel;
-
-	efx_for_each_channel(channel, efx)
-		efx_remove_channel(channel);
+	efx_remove_filters(efx);
+	efx_remove_channels(efx);
 	efx_remove_port(efx);
 	efx_remove_nic(efx);
 }
@@ -1355,20 +1517,20 @@
 void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
 			     bool rx_adaptive)
 {
-	struct efx_tx_queue *tx_queue;
-	struct efx_rx_queue *rx_queue;
+	struct efx_channel *channel;
 	unsigned tx_ticks = irq_mod_ticks(tx_usecs, EFX_IRQ_MOD_RESOLUTION);
 	unsigned rx_ticks = irq_mod_ticks(rx_usecs, EFX_IRQ_MOD_RESOLUTION);
 
 	EFX_ASSERT_RESET_SERIALISED(efx);
 
-	efx_for_each_tx_queue(tx_queue, efx)
-		tx_queue->channel->irq_moderation = tx_ticks;
-
 	efx->irq_rx_adaptive = rx_adaptive;
 	efx->irq_rx_moderation = rx_ticks;
-	efx_for_each_rx_queue(rx_queue, efx)
-		rx_queue->channel->irq_moderation = rx_ticks;
+	efx_for_each_channel(channel, efx) {
+		if (efx_channel_get_rx_queue(channel))
+			channel->irq_moderation = rx_ticks;
+		else if (efx_channel_get_tx_queue(channel, 0))
+			channel->irq_moderation = tx_ticks;
+	}
 }
 
 /**************************************************************************
@@ -1377,8 +1539,7 @@
  *
  **************************************************************************/
 
-/* Run periodically off the general workqueue. Serialised against
- * efx_reconfigure_port via the mac_lock */
+/* Run periodically off the general workqueue */
 static void efx_monitor(struct work_struct *data)
 {
 	struct efx_nic *efx = container_of(data, struct efx_nic,
@@ -1391,16 +1552,13 @@
 
 	/* If the mac_lock is already held then it is likely a port
 	 * reconfiguration is already in place, which will likely do
-	 * most of the work of check_hw() anyway. */
-	if (!mutex_trylock(&efx->mac_lock))
-		goto out_requeue;
-	if (!efx->port_enabled)
-		goto out_unlock;
-	efx->type->monitor(efx);
+	 * most of the work of monitor() anyway. */
+	if (mutex_trylock(&efx->mac_lock)) {
+		if (efx->port_enabled)
+			efx->type->monitor(efx);
+		mutex_unlock(&efx->mac_lock);
+	}
 
-out_unlock:
-	mutex_unlock(&efx->mac_lock);
-out_requeue:
 	queue_delayed_work(efx->workqueue, &efx->monitor_work,
 			   efx_monitor_interval);
 }
@@ -1546,11 +1704,11 @@
 	stats->tx_packets = mac_stats->tx_packets;
 	stats->rx_bytes = mac_stats->rx_bytes;
 	stats->tx_bytes = mac_stats->tx_bytes;
+	stats->rx_dropped = efx->n_rx_nodesc_drop_cnt;
 	stats->multicast = mac_stats->rx_multicast;
 	stats->collisions = mac_stats->tx_collision;
 	stats->rx_length_errors = (mac_stats->rx_gtjumbo +
 				   mac_stats->rx_length_error);
-	stats->rx_over_errors = efx->n_rx_nodesc_drop_cnt;
 	stats->rx_crc_errors = mac_stats->rx_bad;
 	stats->rx_frame_errors = mac_stats->rx_align_error;
 	stats->rx_fifo_errors = mac_stats->rx_overflow;
@@ -1767,6 +1925,7 @@
 
 static void efx_unregister_netdev(struct efx_nic *efx)
 {
+	struct efx_channel *channel;
 	struct efx_tx_queue *tx_queue;
 
 	if (!efx->net_dev)
@@ -1777,8 +1936,10 @@
 	/* Free up any skbs still remaining. This has to happen before
 	 * we try to unregister the netdev as running their destructors
 	 * may be needed to get the device ref. count to 0. */
-	efx_for_each_tx_queue(tx_queue, efx)
-		efx_release_tx_buffers(tx_queue);
+	efx_for_each_channel(channel, efx) {
+		efx_for_each_channel_tx_queue(tx_queue, channel)
+			efx_release_tx_buffers(tx_queue);
+	}
 
 	if (efx_dev_registered(efx)) {
 		strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
@@ -1841,6 +2002,7 @@
 	efx->mac_op->reconfigure(efx);
 
 	efx_init_channels(efx);
+	efx_restore_filters(efx);
 
 	mutex_unlock(&efx->spi_lock);
 	mutex_unlock(&efx->mac_lock);
@@ -2010,10 +2172,8 @@
 	return 0;
 }
 void efx_port_dummy_op_void(struct efx_nic *efx) {}
-void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
-{
-}
-bool efx_port_dummy_op_poll(struct efx_nic *efx)
+
+static bool efx_port_dummy_op_poll(struct efx_nic *efx)
 {
 	return false;
 }
@@ -2037,9 +2197,6 @@
 static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
 			   struct pci_dev *pci_dev, struct net_device *net_dev)
 {
-	struct efx_channel *channel;
-	struct efx_tx_queue *tx_queue;
-	struct efx_rx_queue *rx_queue;
 	int i;
 
 	/* Initialise common structures */
@@ -2068,36 +2225,13 @@
 	INIT_WORK(&efx->mac_work, efx_mac_work);
 
 	for (i = 0; i < EFX_MAX_CHANNELS; i++) {
-		channel = &efx->channel[i];
-		channel->efx = efx;
-		channel->channel = i;
-		channel->work_pending = false;
-		spin_lock_init(&channel->tx_stop_lock);
-		atomic_set(&channel->tx_stop_count, 1);
-	}
-	for (i = 0; i < EFX_MAX_TX_QUEUES; i++) {
-		tx_queue = &efx->tx_queue[i];
-		tx_queue->efx = efx;
-		tx_queue->queue = i;
-		tx_queue->buffer = NULL;
-		tx_queue->channel = &efx->channel[0]; /* for safety */
-		tx_queue->tso_headers_free = NULL;
-	}
-	for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
-		rx_queue = &efx->rx_queue[i];
-		rx_queue->efx = efx;
-		rx_queue->queue = i;
-		rx_queue->channel = &efx->channel[0]; /* for safety */
-		rx_queue->buffer = NULL;
-		setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
-			    (unsigned long)rx_queue);
+		efx->channel[i] = efx_alloc_channel(efx, i, NULL);
+		if (!efx->channel[i])
+			goto fail;
 	}
 
 	efx->type = type;
 
-	/* As close as we can get to guaranteeing that we don't overflow */
-	BUILD_BUG_ON(EFX_EVQ_SIZE < EFX_TXQ_SIZE + EFX_RXQ_SIZE);
-
 	EFX_BUG_ON_PARANOID(efx->type->phys_addr_channels > EFX_MAX_CHANNELS);
 
 	/* Higher numbered interrupt modes are less capable! */
@@ -2109,13 +2243,22 @@
 		 pci_name(pci_dev));
 	efx->workqueue = create_singlethread_workqueue(efx->workqueue_name);
 	if (!efx->workqueue)
-		return -ENOMEM;
+		goto fail;
 
 	return 0;
+
+fail:
+	efx_fini_struct(efx);
+	return -ENOMEM;
 }
 
 static void efx_fini_struct(struct efx_nic *efx)
 {
+	int i;
+
+	for (i = 0; i < EFX_MAX_CHANNELS; i++)
+		kfree(efx->channel[i]);
+
 	if (efx->workqueue) {
 		destroy_workqueue(efx->workqueue);
 		efx->workqueue = NULL;
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index 060dc95..10a1bf4 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -12,6 +12,7 @@
 #define EFX_EFX_H
 
 #include "net_driver.h"
+#include "filter.h"
 
 /* PCI IDs */
 #define EFX_VENDID_SFC	        0x1924
@@ -37,8 +38,6 @@
 extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
 extern void efx_stop_queue(struct efx_channel *channel);
 extern void efx_wake_queue(struct efx_channel *channel);
-#define EFX_TXQ_SIZE 1024
-#define EFX_TXQ_MASK (EFX_TXQ_SIZE - 1)
 
 /* RX */
 extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
@@ -53,23 +52,42 @@
 extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
 			  unsigned int len, bool checksummed, bool discard);
 extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
-#define EFX_RXQ_SIZE 1024
-#define EFX_RXQ_MASK (EFX_RXQ_SIZE - 1)
+
+#define EFX_MAX_DMAQ_SIZE 4096UL
+#define EFX_DEFAULT_DMAQ_SIZE 1024UL
+#define EFX_MIN_DMAQ_SIZE 512UL
+
+#define EFX_MAX_EVQ_SIZE 16384UL
+#define EFX_MIN_EVQ_SIZE 512UL
+
+/* The smallest [rt]xq_entries that the driver supports. Callers of
+ * efx_wake_queue() assume that they can subsequently send at least one
+ * skb. Falcon/A1 may require up to three descriptors per skb_frag. */
+#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS))
+
+/* Filters */
+extern int efx_probe_filters(struct efx_nic *efx);
+extern void efx_restore_filters(struct efx_nic *efx);
+extern void efx_remove_filters(struct efx_nic *efx);
+extern int efx_filter_insert_filter(struct efx_nic *efx,
+				    struct efx_filter_spec *spec,
+				    bool replace);
+extern int efx_filter_remove_filter(struct efx_nic *efx,
+				    struct efx_filter_spec *spec);
+extern void efx_filter_table_clear(struct efx_nic *efx,
+				   enum efx_filter_table_id table_id,
+				   enum efx_filter_priority priority);
 
 /* Channels */
 extern void efx_process_channel_now(struct efx_channel *channel);
-#define EFX_EVQ_SIZE 4096
-#define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1)
+extern int
+efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries);
 
 /* Ports */
 extern int efx_reconfigure_port(struct efx_nic *efx);
 extern int __efx_reconfigure_port(struct efx_nic *efx);
 
 /* Ethtool support */
-extern int efx_ethtool_get_settings(struct net_device *net_dev,
-				    struct ethtool_cmd *ecmd);
-extern int efx_ethtool_set_settings(struct net_device *net_dev,
-				    struct ethtool_cmd *ecmd);
 extern const struct ethtool_ops efx_ethtool_ops;
 
 /* Reset handling */
@@ -81,15 +99,11 @@
 extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
 extern void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs,
 				    int rx_usecs, bool rx_adaptive);
-extern int efx_request_power(struct efx_nic *efx, int mw, const char *name);
-extern void efx_hex_dump(const u8 *, unsigned int, const char *);
 
 /* Dummy PHY ops for PHY drivers */
 extern int efx_port_dummy_op_int(struct efx_nic *efx);
 extern void efx_port_dummy_op_void(struct efx_nic *efx);
-extern void
-efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
-extern bool efx_port_dummy_op_poll(struct efx_nic *efx);
+
 
 /* MTD */
 #ifdef CONFIG_SFC_MTD
@@ -102,8 +116,6 @@
 static inline void efx_mtd_remove(struct efx_nic *efx) {}
 #endif
 
-extern unsigned int efx_monitor_interval;
-
 static inline void efx_schedule_channel(struct efx_channel *channel)
 {
 	netif_vdbg(channel->efx, intr, channel->efx->net_dev,
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index fd19d6a..edb9d16 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -15,6 +15,7 @@
 #include "workarounds.h"
 #include "selftest.h"
 #include "efx.h"
+#include "filter.h"
 #include "nic.h"
 #include "spi.h"
 #include "mdio_10g.h"
@@ -186,8 +187,8 @@
 }
 
 /* This must be called with rtnl_lock held. */
-int efx_ethtool_get_settings(struct net_device *net_dev,
-			     struct ethtool_cmd *ecmd)
+static int efx_ethtool_get_settings(struct net_device *net_dev,
+				    struct ethtool_cmd *ecmd)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	struct efx_link_state *link_state = &efx->link_state;
@@ -210,8 +211,8 @@
 }
 
 /* This must be called with rtnl_lock held. */
-int efx_ethtool_set_settings(struct net_device *net_dev,
-			     struct ethtool_cmd *ecmd)
+static int efx_ethtool_set_settings(struct net_device *net_dev,
+				    struct ethtool_cmd *ecmd)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	int rc;
@@ -328,9 +329,10 @@
 				  unsigned int test_index,
 				  struct ethtool_string *strings, u64 *data)
 {
+	struct efx_channel *channel = efx_get_channel(efx, 0);
 	struct efx_tx_queue *tx_queue;
 
-	efx_for_each_channel_tx_queue(tx_queue, &efx->channel[0]) {
+	efx_for_each_channel_tx_queue(tx_queue, channel) {
 		efx_fill_test(test_index++, strings, data,
 			      &lb_tests->tx_sent[tx_queue->queue],
 			      EFX_TX_QUEUE_NAME(tx_queue),
@@ -550,9 +552,22 @@
 static int efx_ethtool_set_flags(struct net_device *net_dev, u32 data)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
-	u32 supported = efx->type->offload_features & ETH_FLAG_RXHASH;
+	u32 supported = (efx->type->offload_features &
+			 (ETH_FLAG_RXHASH | ETH_FLAG_NTUPLE));
+	int rc;
 
-	return ethtool_op_set_flags(net_dev, data, supported);
+	rc = ethtool_op_set_flags(net_dev, data, supported);
+	if (rc)
+		return rc;
+
+	if (!(data & ETH_FLAG_NTUPLE)) {
+		efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_IP,
+				       EFX_FILTER_PRI_MANUAL);
+		efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_MAC,
+				       EFX_FILTER_PRI_MANUAL);
+	}
+
+	return 0;
 }
 
 static void efx_ethtool_self_test(struct net_device *net_dev,
@@ -673,15 +688,15 @@
 				    struct ethtool_coalesce *coalesce)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
-	struct efx_tx_queue *tx_queue;
 	struct efx_channel *channel;
 
 	memset(coalesce, 0, sizeof(*coalesce));
 
 	/* Find lowest IRQ moderation across all used TX queues */
 	coalesce->tx_coalesce_usecs_irq = ~((u32) 0);
-	efx_for_each_tx_queue(tx_queue, efx) {
-		channel = tx_queue->channel;
+	efx_for_each_channel(channel, efx) {
+		if (!efx_channel_get_tx_queue(channel, 0))
+			continue;
 		if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) {
 			if (channel->channel < efx->n_rx_channels)
 				coalesce->tx_coalesce_usecs_irq =
@@ -708,7 +723,6 @@
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	struct efx_channel *channel;
-	struct efx_tx_queue *tx_queue;
 	unsigned tx_usecs, rx_usecs, adaptive;
 
 	if (coalesce->use_adaptive_tx_coalesce)
@@ -725,8 +739,9 @@
 	adaptive = coalesce->use_adaptive_rx_coalesce;
 
 	/* If the channel is shared only allow RX parameters to be set */
-	efx_for_each_tx_queue(tx_queue, efx) {
-		if ((tx_queue->channel->channel < efx->n_rx_channels) &&
+	efx_for_each_channel(channel, efx) {
+		if (efx_channel_get_rx_queue(channel) &&
+		    efx_channel_get_tx_queue(channel, 0) &&
 		    tx_usecs) {
 			netif_err(efx, drv, efx->net_dev, "Channel is shared. "
 				  "Only RX coalescing may be set\n");
@@ -741,6 +756,42 @@
 	return 0;
 }
 
+static void efx_ethtool_get_ringparam(struct net_device *net_dev,
+				      struct ethtool_ringparam *ring)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+
+	ring->rx_max_pending = EFX_MAX_DMAQ_SIZE;
+	ring->tx_max_pending = EFX_MAX_DMAQ_SIZE;
+	ring->rx_mini_max_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->rx_pending = efx->rxq_entries;
+	ring->tx_pending = efx->txq_entries;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_pending = 0;
+}
+
+static int efx_ethtool_set_ringparam(struct net_device *net_dev,
+				     struct ethtool_ringparam *ring)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+
+	if (ring->rx_mini_pending || ring->rx_jumbo_pending ||
+	    ring->rx_pending > EFX_MAX_DMAQ_SIZE ||
+	    ring->tx_pending > EFX_MAX_DMAQ_SIZE)
+		return -EINVAL;
+
+	if (ring->rx_pending < EFX_MIN_RING_SIZE ||
+	    ring->tx_pending < EFX_MIN_RING_SIZE) {
+		netif_err(efx, drv, efx->net_dev,
+			  "TX and RX queues cannot be smaller than %ld\n",
+			  EFX_MIN_RING_SIZE);
+		return -EINVAL;
+	}
+
+	return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending);
+}
+
 static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
 				      struct ethtool_pauseparam *pause)
 {
@@ -840,7 +891,7 @@
 	return efx->type->set_wol(efx, wol->wolopts);
 }
 
-extern int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
+static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	enum reset_type method;
@@ -918,6 +969,105 @@
 	}
 }
 
+static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
+				     struct ethtool_rx_ntuple *ntuple)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	struct ethtool_tcpip4_spec *ip_entry = &ntuple->fs.h_u.tcp_ip4_spec;
+	struct ethtool_tcpip4_spec *ip_mask = &ntuple->fs.m_u.tcp_ip4_spec;
+	struct ethhdr *mac_entry = &ntuple->fs.h_u.ether_spec;
+	struct ethhdr *mac_mask = &ntuple->fs.m_u.ether_spec;
+	struct efx_filter_spec filter;
+
+	/* Range-check action */
+	if (ntuple->fs.action < ETHTOOL_RXNTUPLE_ACTION_CLEAR ||
+	    ntuple->fs.action >= (s32)efx->n_rx_channels)
+		return -EINVAL;
+
+	if (~ntuple->fs.data_mask)
+		return -EINVAL;
+
+	switch (ntuple->fs.flow_type) {
+	case TCP_V4_FLOW:
+	case UDP_V4_FLOW:
+		/* Must match all of destination, */
+		if (ip_mask->ip4dst | ip_mask->pdst)
+			return -EINVAL;
+		/* all or none of source, */
+		if ((ip_mask->ip4src | ip_mask->psrc) &&
+		    ((__force u32)~ip_mask->ip4src |
+		     (__force u16)~ip_mask->psrc))
+			return -EINVAL;
+		/* and nothing else */
+		if ((u8)~ip_mask->tos | (u16)~ntuple->fs.vlan_tag_mask)
+			return -EINVAL;
+		break;
+	case ETHER_FLOW:
+		/* Must match all of destination, */
+		if (!is_zero_ether_addr(mac_mask->h_dest))
+			return -EINVAL;
+		/* all or none of VID, */
+		if (ntuple->fs.vlan_tag_mask != 0xf000 &&
+		    ntuple->fs.vlan_tag_mask != 0xffff)
+			return -EINVAL;
+		/* and nothing else */
+		if (!is_broadcast_ether_addr(mac_mask->h_source) ||
+		    mac_mask->h_proto != htons(0xffff))
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	filter.priority = EFX_FILTER_PRI_MANUAL;
+	filter.flags = 0;
+
+	switch (ntuple->fs.flow_type) {
+	case TCP_V4_FLOW:
+		if (!ip_mask->ip4src)
+			efx_filter_set_rx_tcp_full(&filter,
+						   htonl(ip_entry->ip4src),
+						   htons(ip_entry->psrc),
+						   htonl(ip_entry->ip4dst),
+						   htons(ip_entry->pdst));
+		else
+			efx_filter_set_rx_tcp_wild(&filter,
+						   htonl(ip_entry->ip4dst),
+						   htons(ip_entry->pdst));
+		break;
+	case UDP_V4_FLOW:
+		if (!ip_mask->ip4src)
+			efx_filter_set_rx_udp_full(&filter,
+						   htonl(ip_entry->ip4src),
+						   htons(ip_entry->psrc),
+						   htonl(ip_entry->ip4dst),
+						   htons(ip_entry->pdst));
+		else
+			efx_filter_set_rx_udp_wild(&filter,
+						   htonl(ip_entry->ip4dst),
+						   htons(ip_entry->pdst));
+		break;
+	case ETHER_FLOW:
+		if (ntuple->fs.vlan_tag_mask == 0xf000)
+			efx_filter_set_rx_mac_full(&filter,
+						   ntuple->fs.vlan_tag & 0xfff,
+						   mac_entry->h_dest);
+		else
+			efx_filter_set_rx_mac_wild(&filter, mac_entry->h_dest);
+		break;
+	}
+
+	if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_CLEAR) {
+		return efx_filter_remove_filter(efx, &filter);
+	} else {
+		if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
+			filter.dmaq_id = 0xfff;
+		else
+			filter.dmaq_id = ntuple->fs.action;
+		return efx_filter_insert_filter(efx, &filter, true);
+	}
+}
+
 static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev,
 				      struct ethtool_rxfh_indir *indir)
 {
@@ -971,6 +1121,8 @@
 	.set_eeprom		= efx_ethtool_set_eeprom,
 	.get_coalesce		= efx_ethtool_get_coalesce,
 	.set_coalesce		= efx_ethtool_set_coalesce,
+	.get_ringparam		= efx_ethtool_get_ringparam,
+	.set_ringparam		= efx_ethtool_set_ringparam,
 	.get_pauseparam         = efx_ethtool_get_pauseparam,
 	.set_pauseparam         = efx_ethtool_set_pauseparam,
 	.get_rx_csum		= efx_ethtool_get_rx_csum,
@@ -994,6 +1146,7 @@
 	.set_wol                = efx_ethtool_set_wol,
 	.reset			= efx_ethtool_reset,
 	.get_rxnfc		= efx_ethtool_get_rxnfc,
+	.set_rx_ntuple		= efx_ethtool_set_rx_ntuple,
 	.get_rxfh_indir		= efx_ethtool_get_rxfh_indir,
 	.set_rxfh_indir		= efx_ethtool_set_rxfh_indir,
 };
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 4f9d33f..267019b 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -159,7 +159,6 @@
 {
 	struct efx_nic *efx = dev_id;
 	efx_oword_t *int_ker = efx->irq_status.addr;
-	struct efx_channel *channel;
 	int syserr;
 	int queues;
 
@@ -194,15 +193,10 @@
 	wmb(); /* Ensure the vector is cleared before interrupt ack */
 	falcon_irq_ack_a1(efx);
 
-	/* Schedule processing of any interrupting queues */
-	channel = &efx->channel[0];
-	while (queues) {
-		if (queues & 0x01)
-			efx_schedule_channel(channel);
-		channel++;
-		queues >>= 1;
-	}
-
+	if (queues & 1)
+		efx_schedule_channel(efx_get_channel(efx, 0));
+	if (queues & 2)
+		efx_schedule_channel(efx_get_channel(efx, 1));
 	return IRQ_HANDLED;
 }
 /**************************************************************************
@@ -452,30 +446,19 @@
 		/* It's not safe to use GLB_CTL_REG to reset the
 		 * macs, so instead use the internal MAC resets
 		 */
-		if (!EFX_IS10G(efx)) {
-			EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 1);
-			efx_writeo(efx, &reg, FR_AB_GM_CFG1);
-			udelay(1000);
+		EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1);
+		efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
 
-			EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 0);
-			efx_writeo(efx, &reg, FR_AB_GM_CFG1);
-			udelay(1000);
-			return;
-		} else {
-			EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1);
-			efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
-
-			for (count = 0; count < 10000; count++) {
-				efx_reado(efx, &reg, FR_AB_XM_GLB_CFG);
-				if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) ==
-				    0)
-					return;
-				udelay(10);
-			}
-
-			netif_err(efx, hw, efx->net_dev,
-				  "timed out waiting for XMAC core reset\n");
+		for (count = 0; count < 10000; count++) {
+			efx_reado(efx, &reg, FR_AB_XM_GLB_CFG);
+			if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) ==
+			    0)
+				return;
+			udelay(10);
 		}
+
+		netif_err(efx, hw, efx->net_dev,
+			  "timed out waiting for XMAC core reset\n");
 	}
 
 	/* Mac stats will fail whist the TX fifo is draining */
@@ -514,7 +497,6 @@
 	 * are re-enabled by the caller */
 	efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL);
 
-	/* This can run even when the GMAC is selected */
 	falcon_setup_xaui(efx);
 }
 
@@ -652,8 +634,6 @@
 	spin_unlock(&efx->stats_lock);
 }
 
-static void falcon_switch_mac(struct efx_nic *efx);
-
 static bool falcon_loopback_link_poll(struct efx_nic *efx)
 {
 	struct efx_link_state old_state = efx->link_state;
@@ -664,11 +644,7 @@
 	efx->link_state.fd = true;
 	efx->link_state.fc = efx->wanted_fc;
 	efx->link_state.up = true;
-
-	if (efx->loopback_mode == LOOPBACK_GMAC)
-		efx->link_state.speed = 1000;
-	else
-		efx->link_state.speed = 10000;
+	efx->link_state.speed = 10000;
 
 	return !efx_link_state_equal(&efx->link_state, &old_state);
 }
@@ -691,7 +667,7 @@
 	falcon_stop_nic_stats(efx);
 	falcon_deconfigure_mac_wrapper(efx);
 
-	falcon_switch_mac(efx);
+	falcon_reset_macs(efx);
 
 	efx->phy_op->reconfigure(efx);
 	rc = efx->mac_op->reconfigure(efx);
@@ -841,73 +817,23 @@
 	return rc;
 }
 
-static void falcon_clock_mac(struct efx_nic *efx)
-{
-	unsigned strap_val;
-	efx_oword_t nic_stat;
-
-	/* Configure the NIC generated MAC clock correctly */
-	efx_reado(efx, &nic_stat, FR_AB_NIC_STAT);
-	strap_val = EFX_IS10G(efx) ? 5 : 3;
-	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
-		EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP_EN, 1);
-		EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP, strap_val);
-		efx_writeo(efx, &nic_stat, FR_AB_NIC_STAT);
-	} else {
-		/* Falcon A1 does not support 1G/10G speed switching
-		 * and must not be used with a PHY that does. */
-		BUG_ON(EFX_OWORD_FIELD(nic_stat, FRF_AB_STRAP_PINS) !=
-		       strap_val);
-	}
-}
-
-static void falcon_switch_mac(struct efx_nic *efx)
-{
-	struct efx_mac_operations *old_mac_op = efx->mac_op;
-	struct falcon_nic_data *nic_data = efx->nic_data;
-	unsigned int stats_done_offset;
-
-	WARN_ON(!mutex_is_locked(&efx->mac_lock));
-	WARN_ON(nic_data->stats_disable_count == 0);
-
-	efx->mac_op = (EFX_IS10G(efx) ?
-		       &falcon_xmac_operations : &falcon_gmac_operations);
-
-	if (EFX_IS10G(efx))
-		stats_done_offset = XgDmaDone_offset;
-	else
-		stats_done_offset = GDmaDone_offset;
-	nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset;
-
-	if (old_mac_op == efx->mac_op)
-		return;
-
-	falcon_clock_mac(efx);
-
-	netif_dbg(efx, hw, efx->net_dev, "selected %cMAC\n",
-		  EFX_IS10G(efx) ? 'X' : 'G');
-	/* Not all macs support a mac-level link state */
-	efx->xmac_poll_required = false;
-	falcon_reset_macs(efx);
-}
-
 /* This call is responsible for hooking in the MAC and PHY operations */
 static int falcon_probe_port(struct efx_nic *efx)
 {
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	int rc;
 
 	switch (efx->phy_type) {
 	case PHY_TYPE_SFX7101:
 		efx->phy_op = &falcon_sfx7101_phy_ops;
 		break;
-	case PHY_TYPE_SFT9001A:
-	case PHY_TYPE_SFT9001B:
-		efx->phy_op = &falcon_sft9001_phy_ops;
-		break;
 	case PHY_TYPE_QT2022C2:
 	case PHY_TYPE_QT2025C:
 		efx->phy_op = &falcon_qt202x_phy_ops;
 		break;
+	case PHY_TYPE_TXC43128:
+		efx->phy_op = &falcon_txc_phy_ops;
+		break;
 	default:
 		netif_err(efx, probe, efx->net_dev, "Unknown PHY type %d\n",
 			  efx->phy_type);
@@ -943,6 +869,7 @@
 		  (u64)efx->stats_buffer.dma_addr,
 		  efx->stats_buffer.addr,
 		  (u64)virt_to_phys(efx->stats_buffer.addr));
+	nic_data->stats_dma_done = efx->stats_buffer.addr + XgDmaDone_offset;
 
 	return 0;
 }
@@ -1207,7 +1134,7 @@
 		falcon_stop_nic_stats(efx);
 		falcon_deconfigure_mac_wrapper(efx);
 
-		falcon_switch_mac(efx);
+		falcon_reset_macs(efx);
 		rc = efx->mac_op->reconfigure(efx);
 		BUG_ON(rc);
 
@@ -1216,8 +1143,7 @@
 		efx_link_status_changed(efx);
 	}
 
-	if (EFX_IS10G(efx))
-		falcon_poll_xmac(efx);
+	falcon_poll_xmac(efx);
 }
 
 /* Zeroes out the SRAM contents.  This routine must be called in
@@ -1610,16 +1536,6 @@
 	EFX_SET_OWORD_FIELD(temp, FRF_AB_ONCHIP_SRAM, 1);
 	efx_writeo(efx, &temp, FR_AB_NIC_STAT);
 
-	/* Set the source of the GMAC clock */
-	if (efx_nic_rev(efx) == EFX_REV_FALCON_B0) {
-		efx_reado(efx, &temp, FR_AB_GPIO_CTL);
-		EFX_SET_OWORD_FIELD(temp, FRF_AB_USE_NIC_CLK, true);
-		efx_writeo(efx, &temp, FR_AB_GPIO_CTL);
-	}
-
-	/* Select the correct MAC */
-	falcon_clock_mac(efx);
-
 	rc = falcon_reset_sram(efx);
 	if (rc)
 		return rc;
@@ -1880,7 +1796,7 @@
 				   * channels */
 	.tx_dc_base = 0x130000,
 	.rx_dc_base = 0x100000,
-	.offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH,
+	.offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE,
 	.reset_world_flags = ETH_RESET_IRQ,
 };
 
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c
index 3d950c2..cfc6a5b 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/sfc/falcon_boards.c
@@ -26,7 +26,7 @@
 /* Board types */
 #define FALCON_BOARD_SFE4001 0x01
 #define FALCON_BOARD_SFE4002 0x02
-#define FALCON_BOARD_SFN4111T 0x51
+#define FALCON_BOARD_SFE4003 0x03
 #define FALCON_BOARD_SFN4112F 0x52
 
 /* Board temperature is about 15°C above ambient when air flow is
@@ -142,17 +142,17 @@
 #endif /* CONFIG_SENSORS_LM87 */
 
 /*****************************************************************************
- * Support for the SFE4001 and SFN4111T NICs.
+ * Support for the SFE4001 NIC.
  *
  * The SFE4001 does not power-up fully at reset due to its high power
  * consumption.  We control its power via a PCA9539 I/O expander.
- * Both boards have a MAX6647 temperature monitor which we expose to
+ * It also has a MAX6647 temperature monitor which we expose to
  * the lm90 driver.
  *
  * This also provides minimal support for reflashing the PHY, which is
  * initiated by resetting it with the FLASH_CFG_1 pin pulled down.
  * On SFE4001 rev A2 and later this is connected to the 3V3X output of
- * the IO-expander; on the SFN4111T it is connected to Falcon's GPIO3.
+ * the IO-expander.
  * We represent reflash mode as PHY_MODE_SPECIAL and make it mutually
  * exclusive with the network device being open.
  */
@@ -304,34 +304,6 @@
 	return rc;
 }
 
-static int sfn4111t_reset(struct efx_nic *efx)
-{
-	struct falcon_board *board = falcon_board(efx);
-	efx_oword_t reg;
-
-	/* GPIO 3 and the GPIO register are shared with I2C, so block that */
-	i2c_lock_adapter(&board->i2c_adap);
-
-	/* Pull RST_N (GPIO 2) low then let it up again, setting the
-	 * FLASH_CFG_1 strap (GPIO 3) appropriately.  Only change the
-	 * output enables; the output levels should always be 0 (low)
-	 * and we rely on external pull-ups. */
-	efx_reado(efx, &reg, FR_AB_GPIO_CTL);
-	EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO2_OEN, true);
-	efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
-	msleep(1000);
-	EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO2_OEN, false);
-	EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO3_OEN,
-			    !!(efx->phy_mode & PHY_MODE_SPECIAL));
-	efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
-	msleep(1);
-
-	i2c_unlock_adapter(&board->i2c_adap);
-
-	ssleep(1);
-	return 0;
-}
-
 static ssize_t show_phy_flash_cfg(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
@@ -363,10 +335,7 @@
 		efx->phy_mode = new_mode;
 		if (new_mode & PHY_MODE_SPECIAL)
 			falcon_stop_nic_stats(efx);
-		if (falcon_board(efx)->type->id == FALCON_BOARD_SFE4001)
-			err = sfe4001_poweron(efx);
-		else
-			err = sfn4111t_reset(efx);
+		err = sfe4001_poweron(efx);
 		if (!err)
 			err = efx_reconfigure_port(efx);
 		if (!(new_mode & PHY_MODE_SPECIAL))
@@ -479,83 +448,6 @@
 	return rc;
 }
 
-static int sfn4111t_check_hw(struct efx_nic *efx)
-{
-	s32 status;
-
-	/* If XAUI link is up then do not monitor */
-	if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
-		return 0;
-
-	/* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */
-	status = i2c_smbus_read_byte_data(falcon_board(efx)->hwmon_client,
-					  MAX664X_REG_RSL);
-	if (status < 0)
-		return -EIO;
-	if (status & 0x57)
-		return -ERANGE;
-	return 0;
-}
-
-static void sfn4111t_fini(struct efx_nic *efx)
-{
-	netif_info(efx, drv, efx->net_dev, "%s\n", __func__);
-
-	device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
-	i2c_unregister_device(falcon_board(efx)->hwmon_client);
-}
-
-static struct i2c_board_info sfn4111t_a0_hwmon_info = {
-	I2C_BOARD_INFO("max6647", 0x4e),
-};
-
-static struct i2c_board_info sfn4111t_r5_hwmon_info = {
-	I2C_BOARD_INFO("max6646", 0x4d),
-};
-
-static void sfn4111t_init_phy(struct efx_nic *efx)
-{
-	if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
-		if (sft9001_wait_boot(efx) != -EINVAL)
-			return;
-
-		efx->phy_mode = PHY_MODE_SPECIAL;
-		falcon_stop_nic_stats(efx);
-	}
-
-	sfn4111t_reset(efx);
-	sft9001_wait_boot(efx);
-}
-
-static int sfn4111t_init(struct efx_nic *efx)
-{
-	struct falcon_board *board = falcon_board(efx);
-	int rc;
-
-	board->hwmon_client =
-		i2c_new_device(&board->i2c_adap,
-			       (board->minor < 5) ?
-			       &sfn4111t_a0_hwmon_info :
-			       &sfn4111t_r5_hwmon_info);
-	if (!board->hwmon_client)
-		return -EIO;
-
-	rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
-	if (rc)
-		goto fail_hwmon;
-
-	if (efx->phy_mode & PHY_MODE_SPECIAL)
-		/* PHY may not generate a 156.25 MHz clock and MAC
-		 * stats fetch will fail. */
-		falcon_stop_nic_stats(efx);
-
-	return 0;
-
-fail_hwmon:
-	i2c_unregister_device(board->hwmon_client);
-	return rc;
-}
-
 /*****************************************************************************
  * Support for the SFE4002
  *
@@ -691,6 +583,75 @@
 	return efx_init_lm87(efx, &sfn4112f_hwmon_info, sfn4112f_lm87_regs);
 }
 
+/*****************************************************************************
+ * Support for the SFE4003
+ *
+ */
+static u8 sfe4003_lm87_channel = 0x03; /* use AIN not FAN inputs */
+
+static const u8 sfe4003_lm87_regs[] = {
+	LM87_IN_LIMITS(0, 0x67, 0x7f),		/* 2.5V:  1.5V +/- 10% */
+	LM87_IN_LIMITS(1, 0x4c, 0x5e),		/* Vccp1: 1.2V +/- 10% */
+	LM87_IN_LIMITS(2, 0xac, 0xd4),		/* 3.3V:  3.3V +/- 10% */
+	LM87_IN_LIMITS(4, 0xac, 0xe0),		/* 12V:   10.8-14V */
+	LM87_IN_LIMITS(5, 0x3f, 0x4f),		/* Vccp2: 1.0V +/- 10% */
+	LM87_TEMP_INT_LIMITS(0, 70 + FALCON_BOARD_TEMP_BIAS),
+	0
+};
+
+static struct i2c_board_info sfe4003_hwmon_info = {
+	I2C_BOARD_INFO("lm87", 0x2e),
+	.platform_data	= &sfe4003_lm87_channel,
+};
+
+/* Board-specific LED info. */
+#define SFE4003_RED_LED_GPIO	11
+#define SFE4003_LED_ON		1
+#define SFE4003_LED_OFF		0
+
+static void sfe4003_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+{
+	struct falcon_board *board = falcon_board(efx);
+
+	/* The LEDs were not wired to GPIOs before A3 */
+	if (board->minor < 3 && board->major == 0)
+		return;
+
+	falcon_txc_set_gpio_val(
+		efx, SFE4003_RED_LED_GPIO,
+		(mode == EFX_LED_ON) ? SFE4003_LED_ON : SFE4003_LED_OFF);
+}
+
+static void sfe4003_init_phy(struct efx_nic *efx)
+{
+	struct falcon_board *board = falcon_board(efx);
+
+	/* The LEDs were not wired to GPIOs before A3 */
+	if (board->minor < 3 && board->major == 0)
+		return;
+
+	falcon_txc_set_gpio_dir(efx, SFE4003_RED_LED_GPIO, TXC_GPIO_DIR_OUTPUT);
+	falcon_txc_set_gpio_val(efx, SFE4003_RED_LED_GPIO, SFE4003_LED_OFF);
+}
+
+static int sfe4003_check_hw(struct efx_nic *efx)
+{
+	struct falcon_board *board = falcon_board(efx);
+
+	/* A0/A1/A2 board rev. 4003s  report a temperature fault the whole time
+	 * (bad sensor) so we mask it out. */
+	unsigned alarm_mask =
+		(board->major == 0 && board->minor <= 2) ?
+		~LM87_ALARM_TEMP_EXT1 : ~0;
+
+	return efx_check_lm87(efx, alarm_mask);
+}
+
+static int sfe4003_init(struct efx_nic *efx)
+{
+	return efx_init_lm87(efx, &sfe4003_hwmon_info, sfe4003_lm87_regs);
+}
+
 static const struct falcon_board_type board_types[] = {
 	{
 		.id		= FALCON_BOARD_SFE4001,
@@ -713,14 +674,14 @@
 		.monitor	= sfe4002_check_hw,
 	},
 	{
-		.id		= FALCON_BOARD_SFN4111T,
-		.ref_model	= "SFN4111T",
-		.gen_type	= "100/1000/10GBASE-T adapter",
-		.init		= sfn4111t_init,
-		.init_phy	= sfn4111t_init_phy,
-		.fini		= sfn4111t_fini,
-		.set_id_led	= tenxpress_set_id_led,
-		.monitor	= sfn4111t_check_hw,
+		.id		= FALCON_BOARD_SFE4003,
+		.ref_model	= "SFE4003",
+		.gen_type	= "10GBASE-CX4 adapter",
+		.init		= sfe4003_init,
+		.init_phy	= sfe4003_init_phy,
+		.fini		= efx_fini_lm87,
+		.set_id_led	= sfe4003_set_id_led,
+		.monitor	= sfe4003_check_hw,
 	},
 	{
 		.id		= FALCON_BOARD_SFN4112F,
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c
deleted file mode 100644
index 7dadfcb..0000000
--- a/drivers/net/sfc/falcon_gmac.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/****************************************************************************
- * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 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/delay.h>
-#include "net_driver.h"
-#include "efx.h"
-#include "nic.h"
-#include "mac.h"
-#include "regs.h"
-#include "io.h"
-
-/**************************************************************************
- *
- * MAC operations
- *
- *************************************************************************/
-
-static int falcon_reconfigure_gmac(struct efx_nic *efx)
-{
-	struct efx_link_state *link_state = &efx->link_state;
-	bool loopback, tx_fc, rx_fc, bytemode;
-	int if_mode;
-	unsigned int max_frame_len;
-	efx_oword_t reg;
-
-	/* Configuration register 1 */
-	tx_fc = (link_state->fc & EFX_FC_TX) || !link_state->fd;
-	rx_fc = !!(link_state->fc & EFX_FC_RX);
-	loopback = (efx->loopback_mode == LOOPBACK_GMAC);
-	bytemode = (link_state->speed == 1000);
-
-	EFX_POPULATE_OWORD_5(reg,
-			     FRF_AB_GM_LOOP, loopback,
-			     FRF_AB_GM_TX_EN, 1,
-			     FRF_AB_GM_TX_FC_EN, tx_fc,
-			     FRF_AB_GM_RX_EN, 1,
-			     FRF_AB_GM_RX_FC_EN, rx_fc);
-	efx_writeo(efx, &reg, FR_AB_GM_CFG1);
-	udelay(10);
-
-	/* Configuration register 2 */
-	if_mode = (bytemode) ? 2 : 1;
-	EFX_POPULATE_OWORD_5(reg,
-			     FRF_AB_GM_IF_MODE, if_mode,
-			     FRF_AB_GM_PAD_CRC_EN, 1,
-			     FRF_AB_GM_LEN_CHK, 1,
-			     FRF_AB_GM_FD, link_state->fd,
-			     FRF_AB_GM_PAMBL_LEN, 0x7/*datasheet recommended */);
-
-	efx_writeo(efx, &reg, FR_AB_GM_CFG2);
-	udelay(10);
-
-	/* Max frame len register */
-	max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
-	EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_MAX_FLEN, max_frame_len);
-	efx_writeo(efx, &reg, FR_AB_GM_MAX_FLEN);
-	udelay(10);
-
-	/* FIFO configuration register 0 */
-	EFX_POPULATE_OWORD_5(reg,
-			     FRF_AB_GMF_FTFENREQ, 1,
-			     FRF_AB_GMF_STFENREQ, 1,
-			     FRF_AB_GMF_FRFENREQ, 1,
-			     FRF_AB_GMF_SRFENREQ, 1,
-			     FRF_AB_GMF_WTMENREQ, 1);
-	efx_writeo(efx, &reg, FR_AB_GMF_CFG0);
-	udelay(10);
-
-	/* FIFO configuration register 1 */
-	EFX_POPULATE_OWORD_2(reg,
-			     FRF_AB_GMF_CFGFRTH, 0x12,
-			     FRF_AB_GMF_CFGXOFFRTX, 0xffff);
-	efx_writeo(efx, &reg, FR_AB_GMF_CFG1);
-	udelay(10);
-
-	/* FIFO configuration register 2 */
-	EFX_POPULATE_OWORD_2(reg,
-			     FRF_AB_GMF_CFGHWM, 0x3f,
-			     FRF_AB_GMF_CFGLWM, 0xa);
-	efx_writeo(efx, &reg, FR_AB_GMF_CFG2);
-	udelay(10);
-
-	/* FIFO configuration register 3 */
-	EFX_POPULATE_OWORD_2(reg,
-			     FRF_AB_GMF_CFGHWMFT, 0x1c,
-			     FRF_AB_GMF_CFGFTTH, 0x08);
-	efx_writeo(efx, &reg, FR_AB_GMF_CFG3);
-	udelay(10);
-
-	/* FIFO configuration register 4 */
-	EFX_POPULATE_OWORD_1(reg, FRF_AB_GMF_HSTFLTRFRM_PAUSE, 1);
-	efx_writeo(efx, &reg, FR_AB_GMF_CFG4);
-	udelay(10);
-
-	/* FIFO configuration register 5 */
-	efx_reado(efx, &reg, FR_AB_GMF_CFG5);
-	EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_CFGBYTMODE, bytemode);
-	EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_CFGHDPLX, !link_state->fd);
-	EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_HSTDRPLT64, !link_state->fd);
-	EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_HSTFLTRFRMDC_PAUSE, 0);
-	efx_writeo(efx, &reg, FR_AB_GMF_CFG5);
-	udelay(10);
-
-	/* MAC address */
-	EFX_POPULATE_OWORD_4(reg,
-			     FRF_AB_GM_ADR_B0, efx->net_dev->dev_addr[5],
-			     FRF_AB_GM_ADR_B1, efx->net_dev->dev_addr[4],
-			     FRF_AB_GM_ADR_B2, efx->net_dev->dev_addr[3],
-			     FRF_AB_GM_ADR_B3, efx->net_dev->dev_addr[2]);
-	efx_writeo(efx, &reg, FR_AB_GM_ADR1);
-	udelay(10);
-	EFX_POPULATE_OWORD_2(reg,
-			     FRF_AB_GM_ADR_B4, efx->net_dev->dev_addr[1],
-			     FRF_AB_GM_ADR_B5, efx->net_dev->dev_addr[0]);
-	efx_writeo(efx, &reg, FR_AB_GM_ADR2);
-	udelay(10);
-
-	falcon_reconfigure_mac_wrapper(efx);
-
-	return 0;
-}
-
-static void falcon_update_stats_gmac(struct efx_nic *efx)
-{
-	struct efx_mac_stats *mac_stats = &efx->mac_stats;
-	unsigned long old_rx_pause, old_tx_pause;
-	unsigned long new_rx_pause, new_tx_pause;
-
-	/* Pause frames are erroneously counted as errors (SFC bug 3269) */
-	old_rx_pause = mac_stats->rx_pause;
-	old_tx_pause = mac_stats->tx_pause;
-
-	/* Update MAC stats from DMAed values */
-	FALCON_STAT(efx, GRxGoodOct, rx_good_bytes);
-	FALCON_STAT(efx, GRxBadOct, rx_bad_bytes);
-	FALCON_STAT(efx, GRxMissPkt, rx_missed);
-	FALCON_STAT(efx, GRxFalseCRS, rx_false_carrier);
-	FALCON_STAT(efx, GRxPausePkt, rx_pause);
-	FALCON_STAT(efx, GRxBadPkt, rx_bad);
-	FALCON_STAT(efx, GRxUcastPkt, rx_unicast);
-	FALCON_STAT(efx, GRxMcastPkt, rx_multicast);
-	FALCON_STAT(efx, GRxBcastPkt, rx_broadcast);
-	FALCON_STAT(efx, GRxGoodLt64Pkt, rx_good_lt64);
-	FALCON_STAT(efx, GRxBadLt64Pkt, rx_bad_lt64);
-	FALCON_STAT(efx, GRx64Pkt, rx_64);
-	FALCON_STAT(efx, GRx65to127Pkt, rx_65_to_127);
-	FALCON_STAT(efx, GRx128to255Pkt, rx_128_to_255);
-	FALCON_STAT(efx, GRx256to511Pkt, rx_256_to_511);
-	FALCON_STAT(efx, GRx512to1023Pkt, rx_512_to_1023);
-	FALCON_STAT(efx, GRx1024to15xxPkt, rx_1024_to_15xx);
-	FALCON_STAT(efx, GRx15xxtoJumboPkt, rx_15xx_to_jumbo);
-	FALCON_STAT(efx, GRxGtJumboPkt, rx_gtjumbo);
-	FALCON_STAT(efx, GRxFcsErr64to15xxPkt, rx_bad_64_to_15xx);
-	FALCON_STAT(efx, GRxFcsErr15xxtoJumboPkt, rx_bad_15xx_to_jumbo);
-	FALCON_STAT(efx, GRxFcsErrGtJumboPkt, rx_bad_gtjumbo);
-	FALCON_STAT(efx, GTxGoodBadOct, tx_bytes);
-	FALCON_STAT(efx, GTxGoodOct, tx_good_bytes);
-	FALCON_STAT(efx, GTxSglColPkt, tx_single_collision);
-	FALCON_STAT(efx, GTxMultColPkt, tx_multiple_collision);
-	FALCON_STAT(efx, GTxExColPkt, tx_excessive_collision);
-	FALCON_STAT(efx, GTxDefPkt, tx_deferred);
-	FALCON_STAT(efx, GTxLateCol, tx_late_collision);
-	FALCON_STAT(efx, GTxExDefPkt, tx_excessive_deferred);
-	FALCON_STAT(efx, GTxPausePkt, tx_pause);
-	FALCON_STAT(efx, GTxBadPkt, tx_bad);
-	FALCON_STAT(efx, GTxUcastPkt, tx_unicast);
-	FALCON_STAT(efx, GTxMcastPkt, tx_multicast);
-	FALCON_STAT(efx, GTxBcastPkt, tx_broadcast);
-	FALCON_STAT(efx, GTxLt64Pkt, tx_lt64);
-	FALCON_STAT(efx, GTx64Pkt, tx_64);
-	FALCON_STAT(efx, GTx65to127Pkt, tx_65_to_127);
-	FALCON_STAT(efx, GTx128to255Pkt, tx_128_to_255);
-	FALCON_STAT(efx, GTx256to511Pkt, tx_256_to_511);
-	FALCON_STAT(efx, GTx512to1023Pkt, tx_512_to_1023);
-	FALCON_STAT(efx, GTx1024to15xxPkt, tx_1024_to_15xx);
-	FALCON_STAT(efx, GTx15xxtoJumboPkt, tx_15xx_to_jumbo);
-	FALCON_STAT(efx, GTxGtJumboPkt, tx_gtjumbo);
-	FALCON_STAT(efx, GTxNonTcpUdpPkt, tx_non_tcpudp);
-	FALCON_STAT(efx, GTxMacSrcErrPkt, tx_mac_src_error);
-	FALCON_STAT(efx, GTxIpSrcErrPkt, tx_ip_src_error);
-
-	/* Pause frames are erroneously counted as errors (SFC bug 3269) */
-	new_rx_pause = mac_stats->rx_pause;
-	new_tx_pause = mac_stats->tx_pause;
-	mac_stats->rx_bad -= (new_rx_pause - old_rx_pause);
-	mac_stats->tx_bad -= (new_tx_pause - old_tx_pause);
-
-	/* Derive stats that the MAC doesn't provide directly */
-	mac_stats->tx_bad_bytes =
-		mac_stats->tx_bytes - mac_stats->tx_good_bytes;
-	mac_stats->tx_packets =
-		mac_stats->tx_lt64 + mac_stats->tx_64 +
-		mac_stats->tx_65_to_127 + mac_stats->tx_128_to_255 +
-		mac_stats->tx_256_to_511 + mac_stats->tx_512_to_1023 +
-		mac_stats->tx_1024_to_15xx + mac_stats->tx_15xx_to_jumbo +
-		mac_stats->tx_gtjumbo;
-	mac_stats->tx_collision =
-		mac_stats->tx_single_collision +
-		mac_stats->tx_multiple_collision +
-		mac_stats->tx_excessive_collision +
-		mac_stats->tx_late_collision;
-	mac_stats->rx_bytes =
-		mac_stats->rx_good_bytes + mac_stats->rx_bad_bytes;
-	mac_stats->rx_packets =
-		mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64 +
-		mac_stats->rx_64 + mac_stats->rx_65_to_127 +
-		mac_stats->rx_128_to_255 + mac_stats->rx_256_to_511 +
-		mac_stats->rx_512_to_1023 + mac_stats->rx_1024_to_15xx +
-		mac_stats->rx_15xx_to_jumbo + mac_stats->rx_gtjumbo;
-	mac_stats->rx_good = mac_stats->rx_packets - mac_stats->rx_bad;
-	mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
-}
-
-static bool falcon_gmac_check_fault(struct efx_nic *efx)
-{
-	return false;
-}
-
-struct efx_mac_operations falcon_gmac_operations = {
-	.reconfigure	= falcon_reconfigure_gmac,
-	.update_stats	= falcon_update_stats_gmac,
-	.check_fault 	= falcon_gmac_check_fault,
-};
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index bae656d..b31f595 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -143,7 +143,7 @@
 		 efx_mdio_phyxgxs_lane_sync(efx));
 }
 
-void falcon_reconfigure_xmac_core(struct efx_nic *efx)
+static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
 {
 	unsigned int max_frame_len;
 	efx_oword_t reg;
diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c
new file mode 100644
index 0000000..52cb608
--- /dev/null
+++ b/drivers/net/sfc/filter.c
@@ -0,0 +1,454 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * 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
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include "efx.h"
+#include "filter.h"
+#include "io.h"
+#include "nic.h"
+#include "regs.h"
+
+/* "Fudge factors" - difference between programmed value and actual depth.
+ * Due to pipelined implementation we need to program H/W with a value that
+ * is larger than the hop limit we want.
+ */
+#define FILTER_CTL_SRCH_FUDGE_WILD 3
+#define FILTER_CTL_SRCH_FUDGE_FULL 1
+
+/* Hard maximum hop limit.  Hardware will time-out beyond 200-something.
+ * We also need to avoid infinite loops in efx_filter_search() when the
+ * table is full.
+ */
+#define FILTER_CTL_SRCH_MAX 200
+
+struct efx_filter_table {
+	u32		offset;		/* address of table relative to BAR */
+	unsigned	size;		/* number of entries */
+	unsigned	step;		/* step between entries */
+	unsigned	used;		/* number currently used */
+	unsigned long	*used_bitmap;
+	struct efx_filter_spec *spec;
+};
+
+struct efx_filter_state {
+	spinlock_t	lock;
+	struct efx_filter_table table[EFX_FILTER_TABLE_COUNT];
+	unsigned	search_depth[EFX_FILTER_TYPE_COUNT];
+};
+
+/* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
+ * key derived from the n-tuple.  The initial LFSR state is 0xffff. */
+static u16 efx_filter_hash(u32 key)
+{
+	u16 tmp;
+
+	/* First 16 rounds */
+	tmp = 0x1fff ^ key >> 16;
+	tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
+	tmp = tmp ^ tmp >> 9;
+	/* Last 16 rounds */
+	tmp = tmp ^ tmp << 13 ^ key;
+	tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
+	return tmp ^ tmp >> 9;
+}
+
+/* To allow for hash collisions, filter search continues at these
+ * increments from the first possible entry selected by the hash. */
+static u16 efx_filter_increment(u32 key)
+{
+	return key * 2 - 1;
+}
+
+static enum efx_filter_table_id
+efx_filter_type_table_id(enum efx_filter_type type)
+{
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_FULL >> 2));
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_WILD >> 2));
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_FULL >> 2));
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_WILD >> 2));
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_FULL >> 2));
+	BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_WILD >> 2));
+	return type >> 2;
+}
+
+static void
+efx_filter_table_reset_search_depth(struct efx_filter_state *state,
+				    enum efx_filter_table_id table_id)
+{
+	memset(state->search_depth + (table_id << 2), 0,
+	       sizeof(state->search_depth[0]) << 2);
+}
+
+static void efx_filter_push_rx_limits(struct efx_nic *efx)
+{
+	struct efx_filter_state *state = efx->filter_state;
+	efx_oword_t filter_ctl;
+
+	efx_reado(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
+
+	EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_FULL_SRCH_LIMIT,
+			    state->search_depth[EFX_FILTER_RX_TCP_FULL] +
+			    FILTER_CTL_SRCH_FUDGE_FULL);
+	EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_WILD_SRCH_LIMIT,
+			    state->search_depth[EFX_FILTER_RX_TCP_WILD] +
+			    FILTER_CTL_SRCH_FUDGE_WILD);
+	EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_FULL_SRCH_LIMIT,
+			    state->search_depth[EFX_FILTER_RX_UDP_FULL] +
+			    FILTER_CTL_SRCH_FUDGE_FULL);
+	EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_WILD_SRCH_LIMIT,
+			    state->search_depth[EFX_FILTER_RX_UDP_WILD] +
+			    FILTER_CTL_SRCH_FUDGE_WILD);
+
+	if (state->table[EFX_FILTER_TABLE_RX_MAC].size) {
+		EFX_SET_OWORD_FIELD(
+			filter_ctl, FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
+			state->search_depth[EFX_FILTER_RX_MAC_FULL] +
+			FILTER_CTL_SRCH_FUDGE_FULL);
+		EFX_SET_OWORD_FIELD(
+			filter_ctl, FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
+			state->search_depth[EFX_FILTER_RX_MAC_WILD] +
+			FILTER_CTL_SRCH_FUDGE_WILD);
+	}
+
+	efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
+}
+
+/* Build a filter entry and return its n-tuple key. */
+static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
+{
+	u32 data3;
+
+	switch (efx_filter_type_table_id(spec->type)) {
+	case EFX_FILTER_TABLE_RX_IP: {
+		bool is_udp = (spec->type == EFX_FILTER_RX_UDP_FULL ||
+			       spec->type == EFX_FILTER_RX_UDP_WILD);
+		EFX_POPULATE_OWORD_7(
+			*filter,
+			FRF_BZ_RSS_EN,
+			!!(spec->flags & EFX_FILTER_FLAG_RX_RSS),
+			FRF_BZ_SCATTER_EN,
+			!!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER),
+			FRF_BZ_TCP_UDP, is_udp,
+			FRF_BZ_RXQ_ID, spec->dmaq_id,
+			EFX_DWORD_2, spec->data[2],
+			EFX_DWORD_1, spec->data[1],
+			EFX_DWORD_0, spec->data[0]);
+		data3 = is_udp;
+		break;
+	}
+
+	case EFX_FILTER_TABLE_RX_MAC: {
+		bool is_wild = spec->type == EFX_FILTER_RX_MAC_WILD;
+		EFX_POPULATE_OWORD_8(
+			*filter,
+			FRF_CZ_RMFT_RSS_EN,
+			!!(spec->flags & EFX_FILTER_FLAG_RX_RSS),
+			FRF_CZ_RMFT_SCATTER_EN,
+			!!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER),
+			FRF_CZ_RMFT_IP_OVERRIDE,
+			!!(spec->flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP),
+			FRF_CZ_RMFT_RXQ_ID, spec->dmaq_id,
+			FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
+			FRF_CZ_RMFT_DEST_MAC_HI, spec->data[2],
+			FRF_CZ_RMFT_DEST_MAC_LO, spec->data[1],
+			FRF_CZ_RMFT_VLAN_ID, spec->data[0]);
+		data3 = is_wild;
+		break;
+	}
+
+	default:
+		BUG();
+	}
+
+	return spec->data[0] ^ spec->data[1] ^ spec->data[2] ^ data3;
+}
+
+static bool efx_filter_equal(const struct efx_filter_spec *left,
+			     const struct efx_filter_spec *right)
+{
+	if (left->type != right->type ||
+	    memcmp(left->data, right->data, sizeof(left->data)))
+		return false;
+
+	return true;
+}
+
+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;
+	struct efx_filter_spec *cmp;
+
+	hash = efx_filter_hash(key);
+	incr = efx_filter_increment(key);
+
+	for (depth = 1, filter_idx = hash & (table->size - 1);
+	     depth <= FILTER_CTL_SRCH_MAX &&
+		     test_bit(filter_idx, table->used_bitmap);
+	     ++depth) {
+		cmp = &table->spec[filter_idx];
+		if (efx_filter_equal(spec, cmp))
+			goto found;
+		filter_idx = (filter_idx + incr) & (table->size - 1);
+	}
+	if (!for_insert)
+		return -ENOENT;
+	if (depth > FILTER_CTL_SRCH_MAX)
+		return -EBUSY;
+found:
+	*depth_required = depth;
+	return filter_idx;
+}
+
+/**
+ * efx_filter_insert_filter - add or replace a filter
+ * @efx: NIC in which to insert the filter
+ * @spec: Specification for the filter
+ * @replace: Flag for whether the specified filter may replace a filter
+ *	with an identical match expression and equal or lower priority
+ *
+ * On success, return the filter index within its table.
+ * On failure, return a negative error code.
+ */
+int efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
+			     bool replace)
+{
+	struct efx_filter_state *state = efx->filter_state;
+	enum efx_filter_table_id table_id =
+		efx_filter_type_table_id(spec->type);
+	struct efx_filter_table *table = &state->table[table_id];
+	struct efx_filter_spec *saved_spec;
+	efx_oword_t filter;
+	int filter_idx, depth;
+	u32 key;
+	int rc;
+
+	if (table->size == 0)
+		return -EINVAL;
+
+	key = efx_filter_build(&filter, spec);
+
+	netif_vdbg(efx, hw, efx->net_dev,
+		   "%s: type %d search_depth=%d", __func__, spec->type,
+		   state->search_depth[spec->type]);
+
+	spin_lock_bh(&state->lock);
+
+	rc = efx_filter_search(table, spec, key, true, &depth);
+	if (rc < 0)
+		goto out;
+	filter_idx = rc;
+	BUG_ON(filter_idx >= table->size);
+	saved_spec = &table->spec[filter_idx];
+
+	if (test_bit(filter_idx, table->used_bitmap)) {
+		/* Should we replace the existing filter? */
+		if (!replace) {
+			rc = -EEXIST;
+			goto out;
+		}
+		if (spec->priority < saved_spec->priority) {
+			rc = -EPERM;
+			goto out;
+		}
+	} else {
+		__set_bit(filter_idx, table->used_bitmap);
+		++table->used;
+	}
+	*saved_spec = *spec;
+
+	if (state->search_depth[spec->type] < depth) {
+		state->search_depth[spec->type] = depth;
+		efx_filter_push_rx_limits(efx);
+	}
+
+	efx_writeo(efx, &filter, table->offset + table->step * filter_idx);
+
+	netif_vdbg(efx, hw, efx->net_dev,
+		   "%s: filter type %d index %d rxq %u set",
+		   __func__, spec->type, filter_idx, spec->dmaq_id);
+
+out:
+	spin_unlock_bh(&state->lock);
+	return rc;
+}
+
+static void efx_filter_table_clear_entry(struct efx_nic *efx,
+					 struct efx_filter_table *table,
+					 int filter_idx)
+{
+	static efx_oword_t filter;
+
+	if (test_bit(filter_idx, table->used_bitmap)) {
+		__clear_bit(filter_idx, table->used_bitmap);
+		--table->used;
+		memset(&table->spec[filter_idx], 0, sizeof(table->spec[0]));
+
+		efx_writeo(efx, &filter,
+			   table->offset + table->step * filter_idx);
+	}
+}
+
+/**
+ * efx_filter_remove_filter - remove a filter by specification
+ * @efx: NIC from which to remove the filter
+ * @spec: Specification for the filter
+ *
+ * On success, return zero.
+ * On failure, return a negative error code.
+ */
+int efx_filter_remove_filter(struct efx_nic *efx, struct efx_filter_spec *spec)
+{
+	struct efx_filter_state *state = efx->filter_state;
+	enum efx_filter_table_id table_id =
+		efx_filter_type_table_id(spec->type);
+	struct efx_filter_table *table = &state->table[table_id];
+	struct efx_filter_spec *saved_spec;
+	efx_oword_t filter;
+	int filter_idx, depth;
+	u32 key;
+	int rc;
+
+	key = efx_filter_build(&filter, spec);
+
+	spin_lock_bh(&state->lock);
+
+	rc = efx_filter_search(table, spec, key, false, &depth);
+	if (rc < 0)
+		goto out;
+	filter_idx = rc;
+	saved_spec = &table->spec[filter_idx];
+
+	if (spec->priority < saved_spec->priority) {
+		rc = -EPERM;
+		goto out;
+	}
+
+	efx_filter_table_clear_entry(efx, table, filter_idx);
+	if (table->used == 0)
+		efx_filter_table_reset_search_depth(state, table_id);
+	rc = 0;
+
+out:
+	spin_unlock_bh(&state->lock);
+	return rc;
+}
+
+/**
+ * efx_filter_table_clear - remove filters from a table by priority
+ * @efx: NIC from which to remove the filters
+ * @table_id: Table from which to remove the filters
+ * @priority: Maximum priority to remove
+ */
+void efx_filter_table_clear(struct efx_nic *efx,
+			    enum efx_filter_table_id table_id,
+			    enum efx_filter_priority priority)
+{
+	struct efx_filter_state *state = efx->filter_state;
+	struct efx_filter_table *table = &state->table[table_id];
+	int filter_idx;
+
+	spin_lock_bh(&state->lock);
+
+	for (filter_idx = 0; filter_idx < table->size; ++filter_idx)
+		if (table->spec[filter_idx].priority <= priority)
+			efx_filter_table_clear_entry(efx, table, filter_idx);
+	if (table->used == 0)
+		efx_filter_table_reset_search_depth(state, table_id);
+
+	spin_unlock_bh(&state->lock);
+}
+
+/* Restore filter stater after reset */
+void efx_restore_filters(struct efx_nic *efx)
+{
+	struct efx_filter_state *state = efx->filter_state;
+	enum efx_filter_table_id table_id;
+	struct efx_filter_table *table;
+	efx_oword_t filter;
+	int filter_idx;
+
+	spin_lock_bh(&state->lock);
+
+	for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
+		table = &state->table[table_id];
+		for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
+			if (!test_bit(filter_idx, table->used_bitmap))
+				continue;
+			efx_filter_build(&filter, &table->spec[filter_idx]);
+			efx_writeo(efx, &filter,
+				   table->offset + table->step * filter_idx);
+		}
+	}
+
+	efx_filter_push_rx_limits(efx);
+
+	spin_unlock_bh(&state->lock);
+}
+
+int efx_probe_filters(struct efx_nic *efx)
+{
+	struct efx_filter_state *state;
+	struct efx_filter_table *table;
+	unsigned table_id;
+
+	state = kzalloc(sizeof(*efx->filter_state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+	efx->filter_state = state;
+
+	spin_lock_init(&state->lock);
+
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		table = &state->table[EFX_FILTER_TABLE_RX_IP];
+		table->offset = FR_BZ_RX_FILTER_TBL0;
+		table->size = FR_BZ_RX_FILTER_TBL0_ROWS;
+		table->step = FR_BZ_RX_FILTER_TBL0_STEP;
+	}
+
+	if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
+		table = &state->table[EFX_FILTER_TABLE_RX_MAC];
+		table->offset = FR_CZ_RX_MAC_FILTER_TBL0;
+		table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
+		table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP;
+	}
+
+	for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
+		table = &state->table[table_id];
+		if (table->size == 0)
+			continue;
+		table->used_bitmap = kcalloc(BITS_TO_LONGS(table->size),
+					     sizeof(unsigned long),
+					     GFP_KERNEL);
+		if (!table->used_bitmap)
+			goto fail;
+		table->spec = vmalloc(table->size * sizeof(*table->spec));
+		if (!table->spec)
+			goto fail;
+		memset(table->spec, 0, table->size * sizeof(*table->spec));
+	}
+
+	return 0;
+
+fail:
+	efx_remove_filters(efx);
+	return -ENOMEM;
+}
+
+void efx_remove_filters(struct efx_nic *efx)
+{
+	struct efx_filter_state *state = efx->filter_state;
+	enum efx_filter_table_id table_id;
+
+	for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
+		kfree(state->table[table_id].used_bitmap);
+		vfree(state->table[table_id].spec);
+	}
+	kfree(state);
+}
diff --git a/drivers/net/sfc/filter.h b/drivers/net/sfc/filter.h
new file mode 100644
index 0000000..a53319d
--- /dev/null
+++ b/drivers/net/sfc/filter.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * 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
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EFX_FILTER_H
+#define EFX_FILTER_H
+
+#include <linux/types.h>
+
+enum efx_filter_table_id {
+	EFX_FILTER_TABLE_RX_IP = 0,
+	EFX_FILTER_TABLE_RX_MAC,
+	EFX_FILTER_TABLE_COUNT,
+};
+
+/**
+ * enum efx_filter_type - type of hardware filter
+ * @EFX_FILTER_RX_TCP_FULL: RX, matching TCP/IPv4 4-tuple
+ * @EFX_FILTER_RX_TCP_WILD: RX, matching TCP/IPv4 destination (host, port)
+ * @EFX_FILTER_RX_UDP_FULL: RX, matching UDP/IPv4 4-tuple
+ * @EFX_FILTER_RX_UDP_WILD: RX, matching UDP/IPv4 destination (host, port)
+ * @EFX_FILTER_RX_MAC_FULL: RX, matching Ethernet destination MAC address, VID
+ * @EFX_FILTER_RX_MAC_WILD: RX, matching Ethernet destination MAC address
+ *
+ * Falcon NICs only support the RX TCP/IPv4 and UDP/IPv4 filter types.
+ */
+enum efx_filter_type {
+	EFX_FILTER_RX_TCP_FULL = 0,
+	EFX_FILTER_RX_TCP_WILD,
+	EFX_FILTER_RX_UDP_FULL,
+	EFX_FILTER_RX_UDP_WILD,
+	EFX_FILTER_RX_MAC_FULL = 4,
+	EFX_FILTER_RX_MAC_WILD,
+	EFX_FILTER_TYPE_COUNT,
+};
+
+/**
+ * enum efx_filter_priority - priority of a hardware filter specification
+ * @EFX_FILTER_PRI_HINT: Performance hint
+ * @EFX_FILTER_PRI_MANUAL: Manually configured filter
+ * @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour
+ */
+enum efx_filter_priority {
+	EFX_FILTER_PRI_HINT = 0,
+	EFX_FILTER_PRI_MANUAL,
+	EFX_FILTER_PRI_REQUIRED,
+};
+
+/**
+ * enum efx_filter_flags - flags for hardware filter specifications
+ * @EFX_FILTER_FLAG_RX_RSS: Use RSS to spread across multiple queues.
+ *	By default, matching packets will be delivered only to the
+ *	specified queue. If this flag is set, they will be delivered
+ *	to a range of queues offset from the specified queue number
+ *	according to the indirection table.
+ * @EFX_FILTER_FLAG_RX_SCATTER: Enable DMA scatter on the receiving
+ *	queue.
+ * @EFX_FILTER_FLAG_RX_OVERRIDE_IP: Enables a MAC filter to override
+ *	any IP filter that matches the same packet.  By default, IP
+ *	filters take precedence.
+ *
+ * Currently, no flags are defined for TX filters.
+ */
+enum efx_filter_flags {
+	EFX_FILTER_FLAG_RX_RSS = 0x01,
+	EFX_FILTER_FLAG_RX_SCATTER = 0x02,
+	EFX_FILTER_FLAG_RX_OVERRIDE_IP = 0x04,
+};
+
+/**
+ * struct efx_filter_spec - specification for a hardware filter
+ * @type: Type of match to be performed, from &enum efx_filter_type
+ * @priority: Priority of the filter, from &enum efx_filter_priority
+ * @flags: Miscellaneous flags, from &enum efx_filter_flags
+ * @dmaq_id: Source/target queue index
+ * @data: Match data (type-dependent)
+ *
+ * Use the efx_filter_set_*() functions to initialise the @type and
+ * @data fields.
+ */
+struct efx_filter_spec {
+	u8	type:4;
+	u8	priority:4;
+	u8	flags;
+	u16	dmaq_id;
+	u32	data[3];
+};
+
+/**
+ * efx_filter_set_rx_tcp_full - specify RX filter with TCP/IPv4 full match
+ * @spec: Specification to initialise
+ * @shost: Source host address (host byte order)
+ * @sport: Source port (host byte order)
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_tcp_full(struct efx_filter_spec *spec,
+			   u32 shost, u16 sport, u32 dhost, u16 dport)
+{
+	spec->type = EFX_FILTER_RX_TCP_FULL;
+	spec->data[0] = sport | shost << 16;
+	spec->data[1] = dport << 16 | shost >> 16;
+	spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_tcp_wild - specify RX filter with TCP/IPv4 wildcard match
+ * @spec: Specification to initialise
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_tcp_wild(struct efx_filter_spec *spec, u32 dhost, u16 dport)
+{
+	spec->type = EFX_FILTER_RX_TCP_WILD;
+	spec->data[0] = 0;
+	spec->data[1] = dport << 16;
+	spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_udp_full - specify RX filter with UDP/IPv4 full match
+ * @spec: Specification to initialise
+ * @shost: Source host address (host byte order)
+ * @sport: Source port (host byte order)
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_udp_full(struct efx_filter_spec *spec,
+			   u32 shost, u16 sport, u32 dhost, u16 dport)
+{
+	spec->type = EFX_FILTER_RX_UDP_FULL;
+	spec->data[0] = sport | shost << 16;
+	spec->data[1] = dport << 16 | shost >> 16;
+	spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_udp_wild - specify RX filter with UDP/IPv4 wildcard match
+ * @spec: Specification to initialise
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_udp_wild(struct efx_filter_spec *spec, u32 dhost, u16 dport)
+{
+	spec->type = EFX_FILTER_RX_UDP_WILD;
+	spec->data[0] = dport;
+	spec->data[1] = 0;
+	spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_mac_full - specify RX filter with MAC full match
+ * @spec: Specification to initialise
+ * @vid: VLAN ID
+ * @addr: Destination MAC address
+ */
+static inline void efx_filter_set_rx_mac_full(struct efx_filter_spec *spec,
+					      u16 vid, const u8 *addr)
+{
+	spec->type = EFX_FILTER_RX_MAC_FULL;
+	spec->data[0] = vid;
+	spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5];
+	spec->data[2] = addr[0] << 8 | addr[1];
+}
+
+/**
+ * efx_filter_set_rx_mac_full - specify RX filter with MAC wildcard match
+ * @spec: Specification to initialise
+ * @addr: Destination MAC address
+ */
+static inline void efx_filter_set_rx_mac_wild(struct efx_filter_spec *spec,
+					      const u8 *addr)
+{
+	spec->type = EFX_FILTER_RX_MAC_WILD;
+	spec->data[0] = 0;
+	spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5];
+	spec->data[2] = addr[0] << 8 | addr[1];
+}
+
+#endif /* EFX_FILTER_H */
diff --git a/drivers/net/sfc/mac.h b/drivers/net/sfc/mac.h
index f1aa5f3..6886cdf 100644
--- a/drivers/net/sfc/mac.h
+++ b/drivers/net/sfc/mac.h
@@ -13,10 +13,8 @@
 
 #include "net_driver.h"
 
-extern struct efx_mac_operations falcon_gmac_operations;
 extern struct efx_mac_operations falcon_xmac_operations;
 extern struct efx_mac_operations efx_mcdi_mac_operations;
-extern void falcon_reconfigure_xmac_core(struct efx_nic *efx);
 extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
 			      u32 dma_len, int enable, int clear);
 
diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c
index 3912b8f..12cf910 100644
--- a/drivers/net/sfc/mcdi.c
+++ b/drivers/net/sfc/mcdi.c
@@ -1093,8 +1093,8 @@
 	return rc;
 }
 
-int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
-			    const u8 *mac, int *id_out)
+static int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
+				   const u8 *mac, int *id_out)
 {
 	u8 inbuf[MC_CMD_WOL_FILTER_SET_IN_LEN];
 	u8 outbuf[MC_CMD_WOL_FILTER_SET_OUT_LEN];
diff --git a/drivers/net/sfc/mcdi.h b/drivers/net/sfc/mcdi.h
index f1f89ad..c792f1d 100644
--- a/drivers/net/sfc/mcdi.h
+++ b/drivers/net/sfc/mcdi.h
@@ -121,8 +121,6 @@
 extern void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
 extern int efx_mcdi_reset_port(struct efx_nic *efx);
 extern int efx_mcdi_reset_mc(struct efx_nic *efx);
-extern int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
-				   const u8 *mac, int *id_out);
 extern int efx_mcdi_wol_filter_set_magic(struct efx_nic *efx,
 					 const u8 *mac, int *id_out);
 extern int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out);
diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c
index 0121e71..c992742 100644
--- a/drivers/net/sfc/mcdi_phy.c
+++ b/drivers/net/sfc/mcdi_phy.c
@@ -713,7 +713,8 @@
 	return 0;
 }
 
-const char *efx_mcdi_phy_test_name(struct efx_nic *efx, unsigned int index)
+static const char *efx_mcdi_phy_test_name(struct efx_nic *efx,
+					  unsigned int index)
 {
 	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index eeaf0bd..98d9460 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -286,46 +286,24 @@
  */
 void efx_mdio_an_reconfigure(struct efx_nic *efx)
 {
-	bool xnp = (efx->link_advertising & ADVERTISED_10000baseT_Full
-		    || EFX_WORKAROUND_13204(efx));
 	int reg;
 
 	WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN));
 
 	/* Set up the base page */
-	reg = ADVERTISE_CSMA;
-	if (efx->link_advertising & ADVERTISED_10baseT_Half)
-		reg |= ADVERTISE_10HALF;
-	if (efx->link_advertising & ADVERTISED_10baseT_Full)
-		reg |= ADVERTISE_10FULL;
-	if (efx->link_advertising & ADVERTISED_100baseT_Half)
-		reg |= ADVERTISE_100HALF;
-	if (efx->link_advertising & ADVERTISED_100baseT_Full)
-		reg |= ADVERTISE_100FULL;
-	if (xnp)
-		reg |= ADVERTISE_RESV;
-	else if (efx->link_advertising & (ADVERTISED_1000baseT_Half |
-					  ADVERTISED_1000baseT_Full))
-		reg |= ADVERTISE_NPAGE;
+	reg = ADVERTISE_CSMA | ADVERTISE_RESV;
 	if (efx->link_advertising & ADVERTISED_Pause)
 		reg |= ADVERTISE_PAUSE_CAP;
 	if (efx->link_advertising & ADVERTISED_Asym_Pause)
 		reg |= ADVERTISE_PAUSE_ASYM;
 	efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
 
-	/* Set up the (extended) next page if necessary */
-	if (efx->phy_op->set_npage_adv)
-		efx->phy_op->set_npage_adv(efx, efx->link_advertising);
+	/* Set up the (extended) next page */
+	efx->phy_op->set_npage_adv(efx, efx->link_advertising);
 
 	/* Enable and restart AN */
 	reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1);
-	reg |= MDIO_AN_CTRL1_ENABLE;
-	if (!(EFX_WORKAROUND_15195(efx) && LOOPBACK_EXTERNAL(efx)))
-		reg |= MDIO_AN_CTRL1_RESTART;
-	if (xnp)
-		reg |= MDIO_AN_CTRL1_XNP;
-	else
-		reg &= ~MDIO_AN_CTRL1_XNP;
+	reg |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART | MDIO_AN_CTRL1_XNP;
 	efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg);
 }
 
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 64e7caa..0a7e26d 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -29,6 +29,7 @@
 #include <linux/device.h>
 #include <linux/highmem.h>
 #include <linux/workqueue.h>
+#include <linux/vmalloc.h>
 #include <linux/i2c.h>
 
 #include "enum.h"
@@ -137,6 +138,7 @@
  * @channel: The associated channel
  * @buffer: The software buffer ring
  * @txd: The hardware descriptor ring
+ * @ptr_mask: The size of the ring minus 1.
  * @flushed: Used when handling queue flushing
  * @read_count: Current read pointer.
  *	This is the number of buffers that have been removed from both rings.
@@ -170,6 +172,7 @@
 	struct efx_nic *nic;
 	struct efx_tx_buffer *buffer;
 	struct efx_special_buffer txd;
+	unsigned int ptr_mask;
 	enum efx_flush_state flushed;
 
 	/* Members used mainly on the completion path */
@@ -225,10 +228,9 @@
 /**
  * struct efx_rx_queue - An Efx RX queue
  * @efx: The associated Efx NIC
- * @queue: DMA queue number
- * @channel: The associated channel
  * @buffer: The software buffer ring
  * @rxd: The hardware descriptor ring
+ * @ptr_mask: The size of the ring minus 1.
  * @added_count: Number of buffers added to the receive queue.
  * @notified_count: Number of buffers given to NIC (<= @added_count).
  * @removed_count: Number of buffers removed from the receive queue.
@@ -240,9 +242,6 @@
  * @min_fill: RX descriptor minimum non-zero fill level.
  *	This records the minimum fill level observed when a ring
  *	refill was triggered.
- * @min_overfill: RX descriptor minimum overflow fill level.
- *	This records the minimum fill level at which RX queue
- *	overflow was observed.  It should never be set.
  * @alloc_page_count: RX allocation strategy counter.
  * @alloc_skb_count: RX allocation strategy counter.
  * @slow_fill: Timer used to defer efx_nic_generate_fill_event().
@@ -250,10 +249,9 @@
  */
 struct efx_rx_queue {
 	struct efx_nic *efx;
-	int queue;
-	struct efx_channel *channel;
 	struct efx_rx_buffer *buffer;
 	struct efx_special_buffer rxd;
+	unsigned int ptr_mask;
 
 	int added_count;
 	int notified_count;
@@ -302,7 +300,6 @@
  *
  * @efx: Associated Efx NIC
  * @channel: Channel instance number
- * @name: Name for channel and IRQ
  * @enabled: Channel enabled indicator
  * @irq: IRQ number (MSI and MSI-X only)
  * @irq_moderation: IRQ moderation value (in hardware ticks)
@@ -311,6 +308,7 @@
  * @reset_work: Scheduled reset work thread
  * @work_pending: Is work pending via NAPI?
  * @eventq: Event queue buffer
+ * @eventq_mask: Event queue pointer mask
  * @eventq_read_ptr: Event queue read pointer
  * @last_eventq_read_ptr: Last event queue read pointer value.
  * @magic_count: Event queue test event count
@@ -327,14 +325,14 @@
  * @n_rx_frm_trunc: Count of RX_FRM_TRUNC errors
  * @n_rx_overlength: Count of RX_OVERLENGTH errors
  * @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun
- * @tx_queue: Pointer to first TX queue, or %NULL if not used for TX
+ * @rx_queue: RX queue for this channel
  * @tx_stop_count: Core TX queue stop count
  * @tx_stop_lock: Core TX queue stop lock
+ * @tx_queue: TX queues for this channel
  */
 struct efx_channel {
 	struct efx_nic *efx;
 	int channel;
-	char name[IFNAMSIZ + 6];
 	bool enabled;
 	int irq;
 	unsigned int irq_moderation;
@@ -342,6 +340,7 @@
 	struct napi_struct napi_str;
 	bool work_pending;
 	struct efx_special_buffer eventq;
+	unsigned int eventq_mask;
 	unsigned int eventq_read_ptr;
 	unsigned int last_eventq_read_ptr;
 	unsigned int magic_count;
@@ -366,9 +365,12 @@
 	struct efx_rx_buffer *rx_pkt;
 	bool rx_pkt_csummed;
 
-	struct efx_tx_queue *tx_queue;
+	struct efx_rx_queue rx_queue;
+
 	atomic_t tx_stop_count;
 	spinlock_t tx_stop_lock;
+
+	struct efx_tx_queue tx_queue[2];
 };
 
 enum efx_led_mode {
@@ -385,11 +387,6 @@
 #define LOOPBACK_MODE(efx) \
 	STRING_TABLE_LOOKUP((efx)->loopback_mode, efx_loopback_mode)
 
-extern const char *efx_interrupt_mode_names[];
-extern const unsigned int efx_interrupt_mode_max;
-#define INT_MODE(efx) \
-	STRING_TABLE_LOOKUP(efx->interrupt_mode, efx_interrupt_mode)
-
 extern const char *efx_reset_type_names[];
 extern const unsigned int efx_reset_type_max;
 #define RESET_TYPE(type) \
@@ -404,8 +401,6 @@
 };
 #define EFX_INT_MODE_USE_MSI(x) (((x)->interrupt_mode) <= EFX_INT_MODE_MSI)
 
-#define EFX_IS10G(efx) ((efx)->link_state.speed == 10000)
-
 enum nic_state {
 	STATE_INIT = 0,
 	STATE_RUNNING = 1,
@@ -618,6 +613,8 @@
 	efx_oword_t oword[EFX_MCAST_HASH_ENTRIES / sizeof(efx_oword_t) / 8];
 };
 
+struct efx_filter_state;
+
 /**
  * struct efx_nic - an Efx NIC
  * @name: Device name (net device name or bus id before net device registered)
@@ -641,6 +638,9 @@
  * @tx_queue: TX DMA queues
  * @rx_queue: RX DMA queues
  * @channel: Channels
+ * @channel_name: Names for channels and their IRQs
+ * @rxq_entries: Size of receive queues requested by user.
+ * @txq_entries: Size of transmit queues requested by user.
  * @next_buffer_table: First available buffer table id
  * @n_channels: Number of channels in use
  * @n_rx_channels: Number of channels used for RX (= number of RX queues)
@@ -724,10 +724,11 @@
 	enum nic_state state;
 	enum reset_type reset_pending;
 
-	struct efx_tx_queue tx_queue[EFX_MAX_TX_QUEUES];
-	struct efx_rx_queue rx_queue[EFX_MAX_RX_QUEUES];
-	struct efx_channel channel[EFX_MAX_CHANNELS];
+	struct efx_channel *channel[EFX_MAX_CHANNELS];
+	char channel_name[EFX_MAX_CHANNELS][IFNAMSIZ + 6];
 
+	unsigned rxq_entries;
+	unsigned txq_entries;
 	unsigned next_buffer_table;
 	unsigned n_channels;
 	unsigned n_rx_channels;
@@ -794,6 +795,8 @@
 	u64 loopback_modes;
 
 	void *loopback_selftest;
+
+	struct efx_filter_state *filter_state;
 };
 
 static inline int efx_dev_registered(struct efx_nic *efx)
@@ -909,39 +912,67 @@
  *
  *************************************************************************/
 
+static inline struct efx_channel *
+efx_get_channel(struct efx_nic *efx, unsigned index)
+{
+	EFX_BUG_ON_PARANOID(index >= efx->n_channels);
+	return efx->channel[index];
+}
+
 /* Iterate over all used channels */
 #define efx_for_each_channel(_channel, _efx)				\
-	for (_channel = &((_efx)->channel[0]);				\
-	     _channel < &((_efx)->channel[(efx)->n_channels]);		\
-	     _channel++)
+	for (_channel = (_efx)->channel[0];				\
+	     _channel;							\
+	     _channel = (_channel->channel + 1 < (_efx)->n_channels) ?	\
+		     (_efx)->channel[_channel->channel + 1] : NULL)
 
-/* Iterate over all used TX queues */
-#define efx_for_each_tx_queue(_tx_queue, _efx)				\
-	for (_tx_queue = &((_efx)->tx_queue[0]);			\
-	     _tx_queue < &((_efx)->tx_queue[EFX_TXQ_TYPES *		\
-					    (_efx)->n_tx_channels]);	\
-	     _tx_queue++)
+extern struct efx_tx_queue *
+efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type);
+
+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;
+}
 
 /* Iterate over all TX queues belonging to a channel */
 #define efx_for_each_channel_tx_queue(_tx_queue, _channel)		\
-	for (_tx_queue = (_channel)->tx_queue;				\
+	for (_tx_queue = efx_channel_get_tx_queue(channel, 0);		\
 	     _tx_queue && _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
 	     _tx_queue++)
 
-/* Iterate over all used RX queues */
-#define efx_for_each_rx_queue(_rx_queue, _efx)				\
-	for (_rx_queue = &((_efx)->rx_queue[0]);			\
-	     _rx_queue < &((_efx)->rx_queue[(_efx)->n_rx_channels]);	\
-	     _rx_queue++)
+static inline struct efx_rx_queue *
+efx_get_rx_queue(struct efx_nic *efx, unsigned index)
+{
+	EFX_BUG_ON_PARANOID(index >= efx->n_rx_channels);
+	return &efx->channel[index]->rx_queue;
+}
+
+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;
+}
 
 /* Iterate over all RX queues belonging to a channel */
 #define efx_for_each_channel_rx_queue(_rx_queue, _channel)		\
-	for (_rx_queue = &((_channel)->efx->rx_queue[(_channel)->channel]); \
+	for (_rx_queue = efx_channel_get_rx_queue(channel);		\
 	     _rx_queue;							\
-	     _rx_queue = NULL)						\
-		if (_rx_queue->channel != (_channel))			\
-			continue;					\
-		else
+	     _rx_queue = NULL)
+
+static inline struct efx_channel *
+efx_rx_queue_channel(struct efx_rx_queue *rx_queue)
+{
+	return container_of(rx_queue, struct efx_channel, rx_queue);
+}
+
+static inline int efx_rx_queue_index(struct efx_rx_queue *rx_queue)
+{
+	return efx_rx_queue_channel(rx_queue)->channel;
+}
 
 /* Returns a pointer to the specified receive buffer in the RX
  * descriptor queue.
@@ -949,7 +980,7 @@
 static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue,
 						  unsigned int index)
 {
-	return (&rx_queue->buffer[index]);
+	return &rx_queue->buffer[index];
 }
 
 /* Set bit in a little-endian bitfield */
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index f595d92..41c36b9 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -104,7 +104,7 @@
 static inline efx_qword_t *efx_event(struct efx_channel *channel,
 				     unsigned int index)
 {
-	return (((efx_qword_t *) (channel->eventq.addr)) + index);
+	return ((efx_qword_t *) (channel->eventq.addr)) + index;
 }
 
 /* See if an event is present
@@ -119,8 +119,8 @@
  */
 static inline int efx_event_present(efx_qword_t *event)
 {
-	return (!(EFX_DWORD_IS_ALL_ONES(event->dword[0]) |
-		  EFX_DWORD_IS_ALL_ONES(event->dword[1])));
+	return !(EFX_DWORD_IS_ALL_ONES(event->dword[0]) |
+		  EFX_DWORD_IS_ALL_ONES(event->dword[1]));
 }
 
 static bool efx_masked_compare_oword(const efx_oword_t *a, const efx_oword_t *b,
@@ -263,8 +263,8 @@
 {
 	len = ALIGN(len, EFX_BUF_SIZE);
 
-	buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
-					    &buffer->dma_addr);
+	buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
+					  &buffer->dma_addr, GFP_KERNEL);
 	if (!buffer->addr)
 		return -ENOMEM;
 	buffer->len = len;
@@ -301,8 +301,8 @@
 		  (u64)buffer->dma_addr, buffer->len,
 		  buffer->addr, (u64)virt_to_phys(buffer->addr));
 
-	pci_free_consistent(efx->pci_dev, buffer->len, buffer->addr,
-			    buffer->dma_addr);
+	dma_free_coherent(&efx->pci_dev->dev, buffer->len, buffer->addr,
+			  buffer->dma_addr);
 	buffer->addr = NULL;
 	buffer->entries = 0;
 }
@@ -347,7 +347,7 @@
 static inline efx_qword_t *
 efx_tx_desc(struct efx_tx_queue *tx_queue, unsigned int index)
 {
-	return (((efx_qword_t *) (tx_queue->txd.addr)) + index);
+	return ((efx_qword_t *) (tx_queue->txd.addr)) + index;
 }
 
 /* This writes to the TX_DESC_WPTR; write pointer for TX descriptor ring */
@@ -356,7 +356,7 @@
 	unsigned write_ptr;
 	efx_dword_t reg;
 
-	write_ptr = tx_queue->write_count & EFX_TXQ_MASK;
+	write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
 	EFX_POPULATE_DWORD_1(reg, FRF_AZ_TX_DESC_WPTR_DWORD, write_ptr);
 	efx_writed_page(tx_queue->efx, &reg,
 			FR_AZ_TX_DESC_UPD_DWORD_P0, tx_queue->queue);
@@ -377,7 +377,7 @@
 	BUG_ON(tx_queue->write_count == tx_queue->insert_count);
 
 	do {
-		write_ptr = tx_queue->write_count & EFX_TXQ_MASK;
+		write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
 		buffer = &tx_queue->buffer[write_ptr];
 		txd = efx_tx_desc(tx_queue, write_ptr);
 		++tx_queue->write_count;
@@ -398,10 +398,11 @@
 int efx_nic_probe_tx(struct efx_tx_queue *tx_queue)
 {
 	struct efx_nic *efx = tx_queue->efx;
-	BUILD_BUG_ON(EFX_TXQ_SIZE < 512 || EFX_TXQ_SIZE > 4096 ||
-		     EFX_TXQ_SIZE & EFX_TXQ_MASK);
+	unsigned entries;
+
+	entries = tx_queue->ptr_mask + 1;
 	return efx_alloc_special_buffer(efx, &tx_queue->txd,
-					EFX_TXQ_SIZE * sizeof(efx_qword_t));
+					entries * sizeof(efx_qword_t));
 }
 
 void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
@@ -501,7 +502,7 @@
 static inline efx_qword_t *
 efx_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index)
 {
-	return (((efx_qword_t *) (rx_queue->rxd.addr)) + index);
+	return ((efx_qword_t *) (rx_queue->rxd.addr)) + index;
 }
 
 /* This creates an entry in the RX descriptor queue */
@@ -526,30 +527,32 @@
  */
 void efx_nic_notify_rx_desc(struct efx_rx_queue *rx_queue)
 {
+	struct efx_nic *efx = rx_queue->efx;
 	efx_dword_t reg;
 	unsigned write_ptr;
 
 	while (rx_queue->notified_count != rx_queue->added_count) {
-		efx_build_rx_desc(rx_queue,
-				  rx_queue->notified_count &
-				  EFX_RXQ_MASK);
+		efx_build_rx_desc(
+			rx_queue,
+			rx_queue->notified_count & rx_queue->ptr_mask);
 		++rx_queue->notified_count;
 	}
 
 	wmb();
-	write_ptr = rx_queue->added_count & EFX_RXQ_MASK;
+	write_ptr = rx_queue->added_count & rx_queue->ptr_mask;
 	EFX_POPULATE_DWORD_1(reg, FRF_AZ_RX_DESC_WPTR_DWORD, write_ptr);
-	efx_writed_page(rx_queue->efx, &reg,
-			FR_AZ_RX_DESC_UPD_DWORD_P0, rx_queue->queue);
+	efx_writed_page(efx, &reg, FR_AZ_RX_DESC_UPD_DWORD_P0,
+			efx_rx_queue_index(rx_queue));
 }
 
 int efx_nic_probe_rx(struct efx_rx_queue *rx_queue)
 {
 	struct efx_nic *efx = rx_queue->efx;
-	BUILD_BUG_ON(EFX_RXQ_SIZE < 512 || EFX_RXQ_SIZE > 4096 ||
-		     EFX_RXQ_SIZE & EFX_RXQ_MASK);
+	unsigned entries;
+
+	entries = rx_queue->ptr_mask + 1;
 	return efx_alloc_special_buffer(efx, &rx_queue->rxd,
-					EFX_RXQ_SIZE * sizeof(efx_qword_t));
+					entries * sizeof(efx_qword_t));
 }
 
 void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
@@ -561,7 +564,7 @@
 
 	netif_dbg(efx, hw, efx->net_dev,
 		  "RX queue %d ring in special buffers %d-%d\n",
-		  rx_queue->queue, rx_queue->rxd.index,
+		  efx_rx_queue_index(rx_queue), rx_queue->rxd.index,
 		  rx_queue->rxd.index + rx_queue->rxd.entries - 1);
 
 	rx_queue->flushed = FLUSH_NONE;
@@ -575,9 +578,10 @@
 			      FRF_AZ_RX_ISCSI_HDIG_EN, iscsi_digest_en,
 			      FRF_AZ_RX_DESCQ_BUF_BASE_ID, rx_queue->rxd.index,
 			      FRF_AZ_RX_DESCQ_EVQ_ID,
-			      rx_queue->channel->channel,
+			      efx_rx_queue_channel(rx_queue)->channel,
 			      FRF_AZ_RX_DESCQ_OWNER_ID, 0,
-			      FRF_AZ_RX_DESCQ_LABEL, rx_queue->queue,
+			      FRF_AZ_RX_DESCQ_LABEL,
+			      efx_rx_queue_index(rx_queue),
 			      FRF_AZ_RX_DESCQ_SIZE,
 			      __ffs(rx_queue->rxd.entries),
 			      FRF_AZ_RX_DESCQ_TYPE, 0 /* kernel queue */ ,
@@ -585,7 +589,7 @@
 			      FRF_AZ_RX_DESCQ_JUMBO, !is_b0,
 			      FRF_AZ_RX_DESCQ_EN, 1);
 	efx_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
-			 rx_queue->queue);
+			 efx_rx_queue_index(rx_queue));
 }
 
 static void efx_flush_rx_queue(struct efx_rx_queue *rx_queue)
@@ -598,7 +602,8 @@
 	/* Post a flush command */
 	EFX_POPULATE_OWORD_2(rx_flush_descq,
 			     FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
-			     FRF_AZ_RX_FLUSH_DESCQ, rx_queue->queue);
+			     FRF_AZ_RX_FLUSH_DESCQ,
+			     efx_rx_queue_index(rx_queue));
 	efx_writeo(efx, &rx_flush_descq, FR_AZ_RX_FLUSH_DESCQ);
 }
 
@@ -613,7 +618,7 @@
 	/* Remove RX descriptor ring from card */
 	EFX_ZERO_OWORD(rx_desc_ptr);
 	efx_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
-			 rx_queue->queue);
+			 efx_rx_queue_index(rx_queue));
 
 	/* Unpin RX descriptor ring */
 	efx_fini_special_buffer(efx, &rx_queue->rxd);
@@ -648,7 +653,7 @@
 }
 
 /* Use HW to insert a SW defined event */
-void efx_generate_event(struct efx_channel *channel, efx_qword_t *event)
+static void efx_generate_event(struct efx_channel *channel, efx_qword_t *event)
 {
 	efx_oword_t drv_ev_reg;
 
@@ -680,15 +685,17 @@
 		/* Transmit completion */
 		tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_DESC_PTR);
 		tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
-		tx_queue = &efx->tx_queue[tx_ev_q_label];
+		tx_queue = efx_channel_get_tx_queue(
+			channel, tx_ev_q_label % EFX_TXQ_TYPES);
 		tx_packets = ((tx_ev_desc_ptr - tx_queue->read_count) &
-			      EFX_TXQ_MASK);
+			      tx_queue->ptr_mask);
 		channel->irq_mod_score += tx_packets;
 		efx_xmit_done(tx_queue, tx_ev_desc_ptr);
 	} else if (EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_WQ_FF_FULL)) {
 		/* Rewrite the FIFO write pointer */
 		tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
-		tx_queue = &efx->tx_queue[tx_ev_q_label];
+		tx_queue = efx_channel_get_tx_queue(
+			channel, tx_ev_q_label % EFX_TXQ_TYPES);
 
 		if (efx_dev_registered(efx))
 			netif_tx_lock(efx->net_dev);
@@ -714,6 +721,7 @@
 				 bool *rx_ev_pkt_ok,
 				 bool *discard)
 {
+	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
 	struct efx_nic *efx = rx_queue->efx;
 	bool rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
 	bool rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
@@ -746,14 +754,14 @@
 	/* Count errors that are not in MAC stats.  Ignore expected
 	 * checksum errors during self-test. */
 	if (rx_ev_frm_trunc)
-		++rx_queue->channel->n_rx_frm_trunc;
+		++channel->n_rx_frm_trunc;
 	else if (rx_ev_tobe_disc)
-		++rx_queue->channel->n_rx_tobe_disc;
+		++channel->n_rx_tobe_disc;
 	else if (!efx->loopback_selftest) {
 		if (rx_ev_ip_hdr_chksum_err)
-			++rx_queue->channel->n_rx_ip_hdr_chksum_err;
+			++channel->n_rx_ip_hdr_chksum_err;
 		else if (rx_ev_tcp_udp_chksum_err)
-			++rx_queue->channel->n_rx_tcp_udp_chksum_err;
+			++channel->n_rx_tcp_udp_chksum_err;
 	}
 
 	/* The frame must be discarded if any of these are true. */
@@ -769,7 +777,7 @@
 		netif_dbg(efx, rx_err, efx->net_dev,
 			  " RX queue %d unexpected RX event "
 			  EFX_QWORD_FMT "%s%s%s%s%s%s%s%s\n",
-			  rx_queue->queue, EFX_QWORD_VAL(*event),
+			  efx_rx_queue_index(rx_queue), EFX_QWORD_VAL(*event),
 			  rx_ev_buf_owner_id_err ? " [OWNER_ID_ERR]" : "",
 			  rx_ev_ip_hdr_chksum_err ?
 			  " [IP_HDR_CHKSUM_ERR]" : "",
@@ -791,8 +799,8 @@
 	struct efx_nic *efx = rx_queue->efx;
 	unsigned expected, dropped;
 
-	expected = rx_queue->removed_count & EFX_RXQ_MASK;
-	dropped = (index - expected) & EFX_RXQ_MASK;
+	expected = rx_queue->removed_count & rx_queue->ptr_mask;
+	dropped = (index - expected) & rx_queue->ptr_mask;
 	netif_info(efx, rx_err, efx->net_dev,
 		   "dropped %d events (index=%d expected=%d)\n",
 		   dropped, index, expected);
@@ -827,10 +835,10 @@
 	WARN_ON(EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_Q_LABEL) !=
 		channel->channel);
 
-	rx_queue = &efx->rx_queue[channel->channel];
+	rx_queue = efx_channel_get_rx_queue(channel);
 
 	rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_DESC_PTR);
-	expected_ptr = rx_queue->removed_count & EFX_RXQ_MASK;
+	expected_ptr = rx_queue->removed_count & rx_queue->ptr_mask;
 	if (unlikely(rx_ev_desc_ptr != expected_ptr))
 		efx_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr);
 
@@ -879,7 +887,7 @@
 		/* The queue must be empty, so we won't receive any rx
 		 * events, so efx_process_channel() won't refill the
 		 * queue. Refill it here */
-		efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
+		efx_fast_push_rx_descriptors(efx_channel_get_rx_queue(channel));
 	else
 		netif_dbg(efx, hw, efx->net_dev, "channel %d received "
 			  "generated event "EFX_QWORD_FMT"\n",
@@ -997,6 +1005,7 @@
 
 int efx_nic_process_eventq(struct efx_channel *channel, int budget)
 {
+	struct efx_nic *efx = channel->efx;
 	unsigned int read_ptr;
 	efx_qword_t event, *p_event;
 	int ev_code;
@@ -1021,7 +1030,7 @@
 		EFX_SET_QWORD(*p_event);
 
 		/* Increment read pointer */
-		read_ptr = (read_ptr + 1) & EFX_EVQ_MASK;
+		read_ptr = (read_ptr + 1) & channel->eventq_mask;
 
 		ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE);
 
@@ -1033,7 +1042,7 @@
 			break;
 		case FSE_AZ_EV_CODE_TX_EV:
 			tx_packets += efx_handle_tx_event(channel, &event);
-			if (tx_packets >= EFX_TXQ_SIZE) {
+			if (tx_packets > efx->txq_entries) {
 				spent = budget;
 				goto out;
 			}
@@ -1068,10 +1077,11 @@
 int efx_nic_probe_eventq(struct efx_channel *channel)
 {
 	struct efx_nic *efx = channel->efx;
-	BUILD_BUG_ON(EFX_EVQ_SIZE < 512 || EFX_EVQ_SIZE > 32768 ||
-		     EFX_EVQ_SIZE & EFX_EVQ_MASK);
+	unsigned entries;
+
+	entries = channel->eventq_mask + 1;
 	return efx_alloc_special_buffer(efx, &channel->eventq,
-					EFX_EVQ_SIZE * sizeof(efx_qword_t));
+					entries * sizeof(efx_qword_t));
 }
 
 void efx_nic_init_eventq(struct efx_channel *channel)
@@ -1163,11 +1173,11 @@
 
 static void efx_poll_flush_events(struct efx_nic *efx)
 {
-	struct efx_channel *channel = &efx->channel[0];
+	struct efx_channel *channel = efx_get_channel(efx, 0);
 	struct efx_tx_queue *tx_queue;
 	struct efx_rx_queue *rx_queue;
 	unsigned int read_ptr = channel->eventq_read_ptr;
-	unsigned int end_ptr = (read_ptr - 1) & EFX_EVQ_MASK;
+	unsigned int end_ptr = (read_ptr - 1) & channel->eventq_mask;
 
 	do {
 		efx_qword_t *event = efx_event(channel, read_ptr);
@@ -1185,7 +1195,9 @@
 			ev_queue = EFX_QWORD_FIELD(*event,
 						   FSF_AZ_DRIVER_EV_SUBDATA);
 			if (ev_queue < EFX_TXQ_TYPES * efx->n_tx_channels) {
-				tx_queue = efx->tx_queue + ev_queue;
+				tx_queue = efx_get_tx_queue(
+					efx, ev_queue / EFX_TXQ_TYPES,
+					ev_queue % EFX_TXQ_TYPES);
 				tx_queue->flushed = FLUSH_DONE;
 			}
 		} else if (ev_code == FSE_AZ_EV_CODE_DRIVER_EV &&
@@ -1195,7 +1207,7 @@
 			ev_failed = EFX_QWORD_FIELD(
 				*event, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
 			if (ev_queue < efx->n_rx_channels) {
-				rx_queue = efx->rx_queue + ev_queue;
+				rx_queue = efx_get_rx_queue(efx, ev_queue);
 				rx_queue->flushed =
 					ev_failed ? FLUSH_FAILED : FLUSH_DONE;
 			}
@@ -1205,7 +1217,7 @@
 		 * it's ok to throw away every non-flush event */
 		EFX_SET_QWORD(*event);
 
-		read_ptr = (read_ptr + 1) & EFX_EVQ_MASK;
+		read_ptr = (read_ptr + 1) & channel->eventq_mask;
 	} while (read_ptr != end_ptr);
 
 	channel->eventq_read_ptr = read_ptr;
@@ -1216,6 +1228,7 @@
  * serialise them */
 int efx_nic_flush_queues(struct efx_nic *efx)
 {
+	struct efx_channel *channel;
 	struct efx_rx_queue *rx_queue;
 	struct efx_tx_queue *tx_queue;
 	int i, tx_pending, rx_pending;
@@ -1224,29 +1237,35 @@
 	efx->type->prepare_flush(efx);
 
 	/* Flush all tx queues in parallel */
-	efx_for_each_tx_queue(tx_queue, efx)
-		efx_flush_tx_queue(tx_queue);
+	efx_for_each_channel(channel, efx) {
+		efx_for_each_channel_tx_queue(tx_queue, channel)
+			efx_flush_tx_queue(tx_queue);
+	}
 
 	/* The hardware supports four concurrent rx flushes, each of which may
 	 * need to be retried if there is an outstanding descriptor fetch */
 	for (i = 0; i < EFX_FLUSH_POLL_COUNT; ++i) {
 		rx_pending = tx_pending = 0;
-		efx_for_each_rx_queue(rx_queue, efx) {
-			if (rx_queue->flushed == FLUSH_PENDING)
-				++rx_pending;
-		}
-		efx_for_each_rx_queue(rx_queue, efx) {
-			if (rx_pending == EFX_RX_FLUSH_COUNT)
-				break;
-			if (rx_queue->flushed == FLUSH_FAILED ||
-			    rx_queue->flushed == FLUSH_NONE) {
-				efx_flush_rx_queue(rx_queue);
-				++rx_pending;
+		efx_for_each_channel(channel, efx) {
+			efx_for_each_channel_rx_queue(rx_queue, channel) {
+				if (rx_queue->flushed == FLUSH_PENDING)
+					++rx_pending;
 			}
 		}
-		efx_for_each_tx_queue(tx_queue, efx) {
-			if (tx_queue->flushed != FLUSH_DONE)
-				++tx_pending;
+		efx_for_each_channel(channel, efx) {
+			efx_for_each_channel_rx_queue(rx_queue, channel) {
+				if (rx_pending == EFX_RX_FLUSH_COUNT)
+					break;
+				if (rx_queue->flushed == FLUSH_FAILED ||
+				    rx_queue->flushed == FLUSH_NONE) {
+					efx_flush_rx_queue(rx_queue);
+					++rx_pending;
+				}
+			}
+			efx_for_each_channel_tx_queue(tx_queue, channel) {
+				if (tx_queue->flushed != FLUSH_DONE)
+					++tx_pending;
+			}
 		}
 
 		if (rx_pending == 0 && tx_pending == 0)
@@ -1258,19 +1277,21 @@
 
 	/* Mark the queues as all flushed. We're going to return failure
 	 * leading to a reset, or fake up success anyway */
-	efx_for_each_tx_queue(tx_queue, efx) {
-		if (tx_queue->flushed != FLUSH_DONE)
-			netif_err(efx, hw, efx->net_dev,
-				  "tx queue %d flush command timed out\n",
-				  tx_queue->queue);
-		tx_queue->flushed = FLUSH_DONE;
-	}
-	efx_for_each_rx_queue(rx_queue, efx) {
-		if (rx_queue->flushed != FLUSH_DONE)
-			netif_err(efx, hw, efx->net_dev,
-				  "rx queue %d flush command timed out\n",
-				  rx_queue->queue);
-		rx_queue->flushed = FLUSH_DONE;
+	efx_for_each_channel(channel, efx) {
+		efx_for_each_channel_tx_queue(tx_queue, channel) {
+			if (tx_queue->flushed != FLUSH_DONE)
+				netif_err(efx, hw, efx->net_dev,
+					  "tx queue %d flush command timed out\n",
+					  tx_queue->queue);
+			tx_queue->flushed = FLUSH_DONE;
+		}
+		efx_for_each_channel_rx_queue(rx_queue, channel) {
+			if (rx_queue->flushed != FLUSH_DONE)
+				netif_err(efx, hw, efx->net_dev,
+					  "rx queue %d flush command timed out\n",
+					  efx_rx_queue_index(rx_queue));
+			rx_queue->flushed = FLUSH_DONE;
+		}
 	}
 
 	return -ETIMEDOUT;
@@ -1457,7 +1478,7 @@
  */
 static irqreturn_t efx_msi_interrupt(int irq, void *dev_id)
 {
-	struct efx_channel *channel = dev_id;
+	struct efx_channel *channel = *(struct efx_channel **)dev_id;
 	struct efx_nic *efx = channel->efx;
 	efx_oword_t *int_ker = efx->irq_status.addr;
 	int syserr;
@@ -1532,7 +1553,8 @@
 	efx_for_each_channel(channel, efx) {
 		rc = request_irq(channel->irq, efx_msi_interrupt,
 				 IRQF_PROBE_SHARED, /* Not shared */
-				 channel->name, channel);
+				 efx->channel_name[channel->channel],
+				 &efx->channel[channel->channel]);
 		if (rc) {
 			netif_err(efx, drv, efx->net_dev,
 				  "failed to hook IRQ %d\n", channel->irq);
@@ -1544,7 +1566,7 @@
 
  fail2:
 	efx_for_each_channel(channel, efx)
-		free_irq(channel->irq, channel);
+		free_irq(channel->irq, &efx->channel[channel->channel]);
  fail1:
 	return rc;
 }
@@ -1557,7 +1579,7 @@
 	/* Disable MSI/MSI-X interrupts */
 	efx_for_each_channel(channel, efx) {
 		if (channel->irq)
-			free_irq(channel->irq, channel);
+			free_irq(channel->irq, &efx->channel[channel->channel]);
 	}
 
 	/* ACK legacy interrupt */
@@ -1827,8 +1849,7 @@
 	REGISTER_TABLE_BB_CZ(TX_DESC_PTR_TBL),
 	REGISTER_TABLE_AA(EVQ_PTR_TBL_KER),
 	REGISTER_TABLE_BB_CZ(EVQ_PTR_TBL),
-	/* The register buffer is allocated with slab, so we can't
-	 * reasonably read all of the buffer table (up to 8MB!).
+	/* We can't reasonably read all of the buffer table (up to 8MB!).
 	 * However this driver will only use a few entries.  Reading
 	 * 1K entries allows for some expansion of queue count and
 	 * size before we need to change the version. */
@@ -1836,7 +1857,6 @@
 				  A, A, 8, 1024),
 	REGISTER_TABLE_DIMENSIONS(BUF_FULL_TBL, FR_BZ_BUF_FULL_TBL,
 				  B, Z, 8, 1024),
-	/* RX_FILTER_TBL{0,1} is huge and not used by this driver */
 	REGISTER_TABLE_CZ(RX_MAC_FILTER_TBL0),
 	REGISTER_TABLE_BB_CZ(TIMER_TBL),
 	REGISTER_TABLE_BB_CZ(TX_PACE_TBL),
@@ -1846,6 +1866,7 @@
 	REGISTER_TABLE_CZ(MC_TREG_SMEM),
 	/* MSIX_PBA_TABLE is not mapped */
 	/* SRM_DBG is not mapped (and is redundant with BUF_FLL_TBL) */
+	REGISTER_TABLE_BZ(RX_FILTER_TBL0),
 };
 
 size_t efx_nic_get_regs_len(struct efx_nic *efx)
diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h
index 5bc2613..1dab609 100644
--- a/drivers/net/sfc/phy.h
+++ b/drivers/net/sfc/phy.h
@@ -11,17 +11,12 @@
 #define EFX_PHY_H
 
 /****************************************************************************
- * 10Xpress (SFX7101 and SFT9001) PHYs
+ * 10Xpress (SFX7101) PHY
  */
 extern struct efx_phy_operations falcon_sfx7101_phy_ops;
-extern struct efx_phy_operations falcon_sft9001_phy_ops;
 
 extern void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
 
-/* Wait for the PHY to boot. Return 0 on success, -EINVAL if the PHY failed
- * to boot due to corrupt flash, or some other negative error code. */
-extern int sft9001_wait_boot(struct efx_nic *efx);
-
 /****************************************************************************
  * AMCC/Quake QT202x PHYs
  */
@@ -42,6 +37,17 @@
 extern void falcon_qt202x_set_led(struct efx_nic *p, int led, int state);
 
 /****************************************************************************
+* Transwitch CX4 retimer
+*/
+extern struct efx_phy_operations falcon_txc_phy_ops;
+
+#define TXC_GPIO_DIR_INPUT	0
+#define TXC_GPIO_DIR_OUTPUT	1
+
+extern void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir);
+extern void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int val);
+
+/****************************************************************************
  * Siena managed PHYs
  */
 extern struct efx_phy_operations efx_mcdi_phy_ops;
diff --git a/drivers/net/sfc/regs.h b/drivers/net/sfc/regs.h
index 18a3be4..96430ed 100644
--- a/drivers/net/sfc/regs.h
+++ b/drivers/net/sfc/regs.h
@@ -2893,6 +2893,20 @@
 #define	FRF_AB_XX_FORCE_SIG_WIDTH 8
 #define	FFE_AB_XX_FORCE_SIG_ALL_LANES 0xff
 
+/* RX_MAC_FILTER_TBL0 */
+/* RMFT_DEST_MAC is wider than 32 bits */
+#define FRF_CZ_RMFT_DEST_MAC_LO_LBN 12
+#define FRF_CZ_RMFT_DEST_MAC_LO_WIDTH 32
+#define FRF_CZ_RMFT_DEST_MAC_HI_LBN 44
+#define FRF_CZ_RMFT_DEST_MAC_HI_WIDTH 16
+
+/* TX_MAC_FILTER_TBL0 */
+/* TMFT_SRC_MAC is wider than 32 bits */
+#define FRF_CZ_TMFT_SRC_MAC_LO_LBN 12
+#define FRF_CZ_TMFT_SRC_MAC_LO_WIDTH 32
+#define FRF_CZ_TMFT_SRC_MAC_HI_LBN 44
+#define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH 16
+
 /* 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 799c461..6d0959b 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -133,7 +133,7 @@
 	unsigned index, count;
 
 	for (count = 0; count < EFX_RX_BATCH; ++count) {
-		index = rx_queue->added_count & EFX_RXQ_MASK;
+		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);
@@ -208,7 +208,7 @@
 		dma_addr += sizeof(struct efx_rx_page_state);
 
 	split:
-		index = rx_queue->added_count & EFX_RXQ_MASK;
+		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;
@@ -285,7 +285,7 @@
 	 * we'd like to insert an additional descriptor whilst leaving
 	 * EFX_RXD_HEAD_ROOM for the non-recycle path */
 	fill_level = (rx_queue->added_count - rx_queue->removed_count + 2);
-	if (unlikely(fill_level >= EFX_RXQ_SIZE - EFX_RXD_HEAD_ROOM)) {
+	if (unlikely(fill_level > rx_queue->max_fill)) {
 		/* We could place "state" on a list, and drain the list in
 		 * efx_fast_push_rx_descriptors(). For now, this will do. */
 		return;
@@ -294,7 +294,7 @@
 	++state->refcnt;
 	get_page(rx_buf->page);
 
-	index = rx_queue->added_count & EFX_RXQ_MASK;
+	index = rx_queue->added_count & rx_queue->ptr_mask;
 	new_buf = efx_rx_buffer(rx_queue, index);
 	new_buf->dma_addr = rx_buf->dma_addr ^ (PAGE_SIZE >> 1);
 	new_buf->skb = NULL;
@@ -311,7 +311,7 @@
 				  struct efx_rx_buffer *rx_buf)
 {
 	struct efx_nic *efx = channel->efx;
-	struct efx_rx_queue *rx_queue = &efx->rx_queue[channel->channel];
+	struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
 	struct efx_rx_buffer *new_buf;
 	unsigned index;
 
@@ -319,7 +319,7 @@
 	    page_count(rx_buf->page) == 1)
 		efx_resurrect_rx_buffer(rx_queue, rx_buf);
 
-	index = rx_queue->added_count & EFX_RXQ_MASK;
+	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));
@@ -341,13 +341,13 @@
  */
 void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
 {
-	struct efx_channel *channel = rx_queue->channel;
+	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
 	unsigned fill_level;
 	int space, rc = 0;
 
 	/* Calculate current fill level, and exit if we don't need to fill */
 	fill_level = (rx_queue->added_count - rx_queue->removed_count);
-	EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE);
+	EFX_BUG_ON_PARANOID(fill_level > rx_queue->efx->rxq_entries);
 	if (fill_level >= rx_queue->fast_fill_trigger)
 		goto out;
 
@@ -364,7 +364,8 @@
 	netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
 		   "RX queue %d fast-filling descriptor ring from"
 		   " level %d to level %d using %s allocation\n",
-		   rx_queue->queue, fill_level, rx_queue->fast_fill_limit,
+		   efx_rx_queue_index(rx_queue), fill_level,
+		   rx_queue->fast_fill_limit,
 		   channel->rx_alloc_push_pages ? "page" : "skb");
 
 	do {
@@ -382,7 +383,7 @@
 
 	netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
 		   "RX queue %d fast-filled descriptor ring "
-		   "to level %d\n", rx_queue->queue,
+		   "to level %d\n", efx_rx_queue_index(rx_queue),
 		   rx_queue->added_count - rx_queue->removed_count);
 
  out:
@@ -393,7 +394,7 @@
 void efx_rx_slow_fill(unsigned long context)
 {
 	struct efx_rx_queue *rx_queue = (struct efx_rx_queue *)context;
-	struct efx_channel *channel = rx_queue->channel;
+	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
 
 	/* Post an event to cause NAPI to run and refill the queue */
 	efx_nic_generate_fill_event(channel);
@@ -421,7 +422,7 @@
 			netif_err(efx, rx_err, efx->net_dev,
 				  " RX queue %d seriously overlength "
 				  "RX event (0x%x > 0x%x+0x%x). Leaking\n",
-				  rx_queue->queue, len, max_len,
+				  efx_rx_queue_index(rx_queue), len, max_len,
 				  efx->type->rx_buffer_padding);
 		/* If this buffer was skb-allocated, then the meta
 		 * data at the end of the skb will be trashed. So
@@ -434,10 +435,10 @@
 			netif_err(efx, rx_err, efx->net_dev,
 				  " RX queue %d overlength RX event "
 				  "(0x%x > 0x%x)\n",
-				  rx_queue->queue, len, max_len);
+				  efx_rx_queue_index(rx_queue), len, max_len);
 	}
 
-	rx_queue->channel->n_rx_overlength++;
+	efx_rx_queue_channel(rx_queue)->n_rx_overlength++;
 }
 
 /* Pass a received packet up through the generic LRO stack
@@ -507,7 +508,7 @@
 		   unsigned int len, bool checksummed, bool discard)
 {
 	struct efx_nic *efx = rx_queue->efx;
-	struct efx_channel *channel = rx_queue->channel;
+	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
 	struct efx_rx_buffer *rx_buf;
 	bool leak_packet = false;
 
@@ -528,7 +529,7 @@
 
 	netif_vdbg(efx, rx_status, efx->net_dev,
 		   "RX queue %d received id %x at %llx+%x %s%s\n",
-		   rx_queue->queue, index,
+		   efx_rx_queue_index(rx_queue), index,
 		   (unsigned long long)rx_buf->dma_addr, len,
 		   (checksummed ? " [SUMMED]" : ""),
 		   (discard ? " [DISCARD]" : ""));
@@ -560,12 +561,11 @@
 	 */
 	rx_buf->len = len;
 out:
-	if (rx_queue->channel->rx_pkt)
-		__efx_rx_packet(rx_queue->channel,
-				rx_queue->channel->rx_pkt,
-				rx_queue->channel->rx_pkt_csummed);
-	rx_queue->channel->rx_pkt = rx_buf;
-	rx_queue->channel->rx_pkt_csummed = checksummed;
+	if (channel->rx_pkt)
+		__efx_rx_packet(channel,
+				channel->rx_pkt, channel->rx_pkt_csummed);
+	channel->rx_pkt = rx_buf;
+	channel->rx_pkt_csummed = checksummed;
 }
 
 /* Handle a received packet.  Second half: Touches packet payload. */
@@ -615,7 +615,7 @@
 	EFX_BUG_ON_PARANOID(!skb);
 
 	/* Set the SKB flags */
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 
 	/* Pass the packet up */
 	netif_receive_skb(skb);
@@ -650,15 +650,22 @@
 int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
 {
 	struct efx_nic *efx = rx_queue->efx;
-	unsigned int rxq_size;
+	unsigned int entries;
 	int rc;
 
+	/* Create the smallest power-of-two aligned ring */
+	entries = max(roundup_pow_of_two(efx->rxq_entries), EFX_MIN_DMAQ_SIZE);
+	EFX_BUG_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE);
+	rx_queue->ptr_mask = entries - 1;
+
 	netif_dbg(efx, probe, efx->net_dev,
-		  "creating RX queue %d\n", rx_queue->queue);
+		  "creating RX queue %d size %#x mask %#x\n",
+		  efx_rx_queue_index(rx_queue), efx->rxq_entries,
+		  rx_queue->ptr_mask);
 
 	/* Allocate RX buffers */
-	rxq_size = EFX_RXQ_SIZE * sizeof(*rx_queue->buffer);
-	rx_queue->buffer = kzalloc(rxq_size, GFP_KERNEL);
+	rx_queue->buffer = kzalloc(entries * sizeof(*rx_queue->buffer),
+				   GFP_KERNEL);
 	if (!rx_queue->buffer)
 		return -ENOMEM;
 
@@ -672,20 +679,20 @@
 
 void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
 {
+	struct efx_nic *efx = rx_queue->efx;
 	unsigned int max_fill, trigger, limit;
 
 	netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
-		  "initialising RX queue %d\n", rx_queue->queue);
+		  "initialising RX queue %d\n", efx_rx_queue_index(rx_queue));
 
 	/* Initialise ptr fields */
 	rx_queue->added_count = 0;
 	rx_queue->notified_count = 0;
 	rx_queue->removed_count = 0;
 	rx_queue->min_fill = -1U;
-	rx_queue->min_overfill = -1U;
 
 	/* Initialise limit fields */
-	max_fill = EFX_RXQ_SIZE - EFX_RXD_HEAD_ROOM;
+	max_fill = efx->rxq_entries - EFX_RXD_HEAD_ROOM;
 	trigger = max_fill * min(rx_refill_threshold, 100U) / 100U;
 	limit = max_fill * min(rx_refill_limit, 100U) / 100U;
 
@@ -703,14 +710,14 @@
 	struct efx_rx_buffer *rx_buf;
 
 	netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
-		  "shutting down RX queue %d\n", rx_queue->queue);
+		  "shutting down RX queue %d\n", efx_rx_queue_index(rx_queue));
 
 	del_timer_sync(&rx_queue->slow_fill);
 	efx_nic_fini_rx(rx_queue);
 
 	/* Release RX buffers NB start at index 0 not current HW ptr */
 	if (rx_queue->buffer) {
-		for (i = 0; i <= EFX_RXQ_MASK; i++) {
+		for (i = 0; i <= rx_queue->ptr_mask; i++) {
 			rx_buf = efx_rx_buffer(rx_queue, i);
 			efx_fini_rx_buffer(rx_queue, rx_buf);
 		}
@@ -720,7 +727,7 @@
 void efx_remove_rx_queue(struct efx_rx_queue *rx_queue)
 {
 	netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
-		  "destroying RX queue %d\n", rx_queue->queue);
+		  "destroying RX queue %d\n", efx_rx_queue_index(rx_queue));
 
 	efx_nic_remove_rx(rx_queue);
 
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 85f015f..0ebfb99 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -48,6 +48,16 @@
 static const char payload_msg[] =
 	"Hello world! This is an Efx loopback test in progress!";
 
+/* Interrupt mode names */
+static const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX;
+static const char *efx_interrupt_mode_names[] = {
+	[EFX_INT_MODE_MSIX]   = "MSI-X",
+	[EFX_INT_MODE_MSI]    = "MSI",
+	[EFX_INT_MODE_LEGACY] = "legacy",
+};
+#define INT_MODE(efx) \
+	STRING_TABLE_LOOKUP(efx->interrupt_mode, efx_interrupt_mode)
+
 /**
  * efx_loopback_state - persistent state during a loopback selftest
  * @flush:		Drop all packets in efx_loopback_rx_packet
@@ -506,7 +516,7 @@
 
 	for (i = 0; i < 3; i++) {
 		/* Determine how many packets to send */
-		state->packet_count = EFX_TXQ_SIZE / 3;
+		state->packet_count = efx->txq_entries / 3;
 		state->packet_count = min(1 << (i << 2), state->packet_count);
 		state->skbs = kzalloc(sizeof(state->skbs[0]) *
 				      state->packet_count, GFP_KERNEL);
@@ -567,7 +577,7 @@
 			efx->type->monitor(efx);
 			mutex_unlock(&efx->mac_lock);
 		} else {
-			struct efx_channel *channel = &efx->channel[0];
+			struct efx_channel *channel = efx_get_channel(efx, 0);
 			if (channel->work_pending)
 				efx_process_channel_now(channel);
 		}
@@ -594,6 +604,7 @@
 {
 	enum efx_loopback_mode mode;
 	struct efx_loopback_state *state;
+	struct efx_channel *channel = efx_get_channel(efx, 0);
 	struct efx_tx_queue *tx_queue;
 	int rc = 0;
 
@@ -634,7 +645,7 @@
 		}
 
 		/* Test both types of TX queue */
-		efx_for_each_channel_tx_queue(tx_queue, &efx->channel[0]) {
+		efx_for_each_channel_tx_queue(tx_queue, channel) {
 			state->offload_csum = (tx_queue->queue &
 					       EFX_TXQ_TYPE_OFFLOAD);
 			rc = efx_test_loopback(tx_queue,
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c
index 3fab030..45236f5 100644
--- a/drivers/net/sfc/siena.c
+++ b/drivers/net/sfc/siena.c
@@ -129,7 +129,7 @@
 	return 0;
 }
 
-void siena_remove_port(struct efx_nic *efx)
+static void siena_remove_port(struct efx_nic *efx)
 {
 	efx->phy_op->remove(efx);
 	efx_nic_free_buffer(efx, &efx->stats_buffer);
@@ -450,7 +450,7 @@
 				    mac_stats->rx_bad_bytes);
 	MAC_STAT(rx_packets, RX_PKTS);
 	MAC_STAT(rx_good, RX_GOOD_PKTS);
-	mac_stats->rx_bad = mac_stats->rx_packets - mac_stats->rx_good;
+	MAC_STAT(rx_bad, RX_BAD_FCS_PKTS);
 	MAC_STAT(rx_pause, RX_PAUSE_PKTS);
 	MAC_STAT(rx_control, RX_CONTROL_PKTS);
 	MAC_STAT(rx_unicast, RX_UNICAST_PKTS);
@@ -651,6 +651,6 @@
 	.tx_dc_base = 0x88000,
 	.rx_dc_base = 0x68000,
 	.offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			     NETIF_F_RXHASH),
+			     NETIF_F_RXHASH | NETIF_F_NTUPLE),
 	.reset_world_flags = ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT,
 };
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index 6791be9..1bc6c48 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -19,10 +19,7 @@
 #include "workarounds.h"
 #include "selftest.h"
 
-/* We expect these MMDs to be in the package.  SFT9001 also has a
- * clause 22 extension MMD, but since it doesn't have all the generic
- * MMD registers it is pointless to include it here.
- */
+/* We expect these MMDs to be in the package. */
 #define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD	| \
 				 MDIO_DEVS_PCS		| \
 				 MDIO_DEVS_PHYXS	| \
@@ -33,12 +30,6 @@
 			   (1 << LOOPBACK_PMAPMD) |	\
 			   (1 << LOOPBACK_PHYXS_WS))
 
-#define SFT9001_LOOPBACKS ((1 << LOOPBACK_GPHY) |	\
-			   (1 << LOOPBACK_PHYXS) |	\
-			   (1 << LOOPBACK_PCS) |	\
-			   (1 << LOOPBACK_PMAPMD) |	\
-			   (1 << LOOPBACK_PHYXS_WS))
-
 /* We complain if we fail to see the link partner as 10G capable this many
  * times in a row (must be > 1 as sampling the autoneg. registers is racy)
  */
@@ -50,9 +41,8 @@
 #define PMA_PMD_EXT_GMII_EN_WIDTH 1
 #define PMA_PMD_EXT_CLK_OUT_LBN	2
 #define PMA_PMD_EXT_CLK_OUT_WIDTH 1
-#define PMA_PMD_LNPGA_POWERDOWN_LBN 8	/* SFX7101 only */
+#define PMA_PMD_LNPGA_POWERDOWN_LBN 8
 #define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1
-#define PMA_PMD_EXT_CLK312_LBN	8	/* SFT9001 only */
 #define PMA_PMD_EXT_CLK312_WIDTH 1
 #define PMA_PMD_EXT_LPOWER_LBN  12
 #define PMA_PMD_EXT_LPOWER_WIDTH 1
@@ -84,7 +74,6 @@
 #define PMA_PMD_LED_FLASH	(3)
 #define PMA_PMD_LED_MASK	3
 /* All LEDs under hardware control */
-#define SFT9001_PMA_PMD_LED_DEFAULT 0
 /* Green and Amber under hardware control, Red off */
 #define SFX7101_PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
 
@@ -98,31 +87,7 @@
 #define PMA_PMD_SPEED_LBN        4
 #define PMA_PMD_SPEED_WIDTH      4
 
-/* Cable diagnostics - SFT9001 only */
-#define PMA_PMD_CDIAG_CTRL_REG  49213
-#define CDIAG_CTRL_IMMED_LBN    15
-#define CDIAG_CTRL_BRK_LINK_LBN 12
-#define CDIAG_CTRL_IN_PROG_LBN  11
-#define CDIAG_CTRL_LEN_UNIT_LBN 10
-#define CDIAG_CTRL_LEN_METRES   1
-#define PMA_PMD_CDIAG_RES_REG   49174
-#define CDIAG_RES_A_LBN         12
-#define CDIAG_RES_B_LBN         8
-#define CDIAG_RES_C_LBN         4
-#define CDIAG_RES_D_LBN         0
-#define CDIAG_RES_WIDTH         4
-#define CDIAG_RES_OPEN          2
-#define CDIAG_RES_OK            1
-#define CDIAG_RES_INVALID       0
-/* Set of 4 registers for pairs A-D */
-#define PMA_PMD_CDIAG_LEN_REG   49175
-
-/* Serdes control registers - SFT9001 only */
-#define PMA_PMD_CSERDES_CTRL_REG 64258
-/* Set the 156.25 MHz output to 312.5 MHz to drive Falcon's XMAC */
-#define PMA_PMD_CSERDES_DEFAULT	0x000f
-
-/* Misc register defines - SFX7101 only */
+/* Misc register defines */
 #define PCS_CLOCK_CTRL_REG	55297
 #define PLL312_RST_N_LBN 2
 
@@ -185,121 +150,17 @@
 	int bad_lp_tries;
 };
 
-static ssize_t show_phy_short_reach(struct device *dev,
-				    struct device_attribute *attr, char *buf)
-{
-	struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
-	int reg;
-
-	reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR);
-	return sprintf(buf, "%d\n", !!(reg & MDIO_PMA_10GBT_TXPWR_SHORT));
-}
-
-static ssize_t set_phy_short_reach(struct device *dev,
-				   struct device_attribute *attr,
-				   const char *buf, size_t count)
-{
-	struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
-	int rc;
-
-	rtnl_lock();
-	if (efx->state != STATE_RUNNING) {
-		rc = -EBUSY;
-	} else {
-		efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR,
-				  MDIO_PMA_10GBT_TXPWR_SHORT,
-				  count != 0 && *buf != '0');
-		rc = efx_reconfigure_port(efx);
-	}
-	rtnl_unlock();
-
-	return rc < 0 ? rc : (ssize_t)count;
-}
-
-static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach,
-		   set_phy_short_reach);
-
-int sft9001_wait_boot(struct efx_nic *efx)
-{
-	unsigned long timeout = jiffies + HZ + 1;
-	int boot_stat;
-
-	for (;;) {
-		boot_stat = efx_mdio_read(efx, MDIO_MMD_PCS,
-					  PCS_BOOT_STATUS_REG);
-		if (boot_stat >= 0) {
-			netif_dbg(efx, hw, efx->net_dev,
-				  "PHY boot status = %#x\n", boot_stat);
-			switch (boot_stat &
-				((1 << PCS_BOOT_FATAL_ERROR_LBN) |
-				 (3 << PCS_BOOT_PROGRESS_LBN) |
-				 (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) |
-				 (1 << PCS_BOOT_CODE_STARTED_LBN))) {
-			case ((1 << PCS_BOOT_FATAL_ERROR_LBN) |
-			      (PCS_BOOT_PROGRESS_CHECKSUM <<
-			       PCS_BOOT_PROGRESS_LBN)):
-			case ((1 << PCS_BOOT_FATAL_ERROR_LBN) |
-			      (PCS_BOOT_PROGRESS_INIT <<
-			       PCS_BOOT_PROGRESS_LBN) |
-			      (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)):
-				return -EINVAL;
-			case ((PCS_BOOT_PROGRESS_WAIT_MDIO <<
-			       PCS_BOOT_PROGRESS_LBN) |
-			      (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)):
-				return (efx->phy_mode & PHY_MODE_SPECIAL) ?
-					0 : -EIO;
-			case ((PCS_BOOT_PROGRESS_JUMP <<
-			       PCS_BOOT_PROGRESS_LBN) |
-			      (1 << PCS_BOOT_CODE_STARTED_LBN)):
-			case ((PCS_BOOT_PROGRESS_JUMP <<
-			       PCS_BOOT_PROGRESS_LBN) |
-			      (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) |
-			      (1 << PCS_BOOT_CODE_STARTED_LBN)):
-				return (efx->phy_mode & PHY_MODE_SPECIAL) ?
-					-EIO : 0;
-			default:
-				if (boot_stat & (1 << PCS_BOOT_FATAL_ERROR_LBN))
-					return -EIO;
-				break;
-			}
-		}
-
-		if (time_after_eq(jiffies, timeout))
-			return -ETIMEDOUT;
-
-		msleep(50);
-	}
-}
-
 static int tenxpress_init(struct efx_nic *efx)
 {
-	int reg;
-
-	if (efx->phy_type == PHY_TYPE_SFX7101) {
-		/* Enable 312.5 MHz clock */
-		efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
-			       1 << CLK312_EN_LBN);
-	} else {
-		/* Enable 312.5 MHz clock and GMII */
-		reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
-		reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) |
-			(1 << PMA_PMD_EXT_CLK_OUT_LBN) |
-			(1 << PMA_PMD_EXT_CLK312_LBN) |
-			(1 << PMA_PMD_EXT_ROBUST_LBN));
-
-		efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
-		efx_mdio_set_flag(efx, MDIO_MMD_C22EXT,
-			      GPHY_XCONTROL_REG, 1 << GPHY_ISOLATE_LBN,
-			      false);
-	}
+	/* Enable 312.5 MHz clock */
+	efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
+		       1 << CLK312_EN_LBN);
 
 	/* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */
-	if (efx->phy_type == PHY_TYPE_SFX7101) {
-		efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
-				  1 << PMA_PMA_LED_ACTIVITY_LBN, true);
-		efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
-			       SFX7101_PMA_PMD_LED_DEFAULT);
-	}
+	efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
+			  1 << PMA_PMA_LED_ACTIVITY_LBN, true);
+	efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
+		       SFX7101_PMA_PMD_LED_DEFAULT);
 
 	return 0;
 }
@@ -307,7 +168,6 @@
 static int tenxpress_phy_probe(struct efx_nic *efx)
 {
 	struct tenxpress_phy_data *phy_data;
-	int rc;
 
 	/* Allocate phy private storage */
 	phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
@@ -316,42 +176,15 @@
 	efx->phy_data = phy_data;
 	phy_data->phy_mode = efx->phy_mode;
 
-	/* Create any special files */
-	if (efx->phy_type == PHY_TYPE_SFT9001B) {
-		rc = device_create_file(&efx->pci_dev->dev,
-					&dev_attr_phy_short_reach);
-		if (rc)
-			goto fail;
-	}
+	efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
+	efx->mdio.mode_support = MDIO_SUPPORTS_C45;
 
-	if (efx->phy_type == PHY_TYPE_SFX7101) {
-		efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
-		efx->mdio.mode_support = MDIO_SUPPORTS_C45;
+	efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
 
-		efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
-
-		efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
-					 ADVERTISED_10000baseT_Full);
-	} else {
-		efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
-		efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
-
-		efx->loopback_modes = (SFT9001_LOOPBACKS |
-				       FALCON_XMAC_LOOPBACKS | 
-				       FALCON_GMAC_LOOPBACKS);
-
-		efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
-					 ADVERTISED_10000baseT_Full |
-					 ADVERTISED_1000baseT_Full |
-					 ADVERTISED_100baseT_Full);
-	}
+	efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
+				 ADVERTISED_10000baseT_Full);
 
 	return 0;
-
-fail:
-	kfree(efx->phy_data);
-	efx->phy_data = NULL;
-	return rc;
 }
 
 static int tenxpress_phy_init(struct efx_nic *efx)
@@ -361,16 +194,6 @@
 	falcon_board(efx)->type->init_phy(efx);
 
 	if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
-		if (efx->phy_type == PHY_TYPE_SFT9001A) {
-			int reg;
-			reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
-					    PMA_PMD_XCONTROL_REG);
-			reg |= (1 << PMA_PMD_EXT_SSR_LBN);
-			efx_mdio_write(efx, MDIO_MMD_PMAPMD,
-				       PMA_PMD_XCONTROL_REG, reg);
-			mdelay(200);
-		}
-
 		rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
 		if (rc < 0)
 			return rc;
@@ -403,7 +226,7 @@
 {
 	int rc, reg;
 
-	/* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
+	/* The XGMAC clock is driven from the SFX7101 312MHz clock, so
 	 * a special software reset can glitch the XGMAC sufficiently for stats
 	 * requests to fail. */
 	falcon_stop_nic_stats(efx);
@@ -484,53 +307,18 @@
 				 MDIO_DEVS_PHYXS);
 }
 
-static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd)
-{
-	u32 reg;
-
-	if (efx_phy_mode_disabled(efx->phy_mode))
-		return false;
-	else if (efx->loopback_mode == LOOPBACK_GPHY)
-		return true;
-	else if (efx->loopback_mode)
-		return efx_mdio_links_ok(efx,
-					 MDIO_DEVS_PMAPMD |
-					 MDIO_DEVS_PHYXS);
-
-	/* We must use the same definition of link state as LASI,
-	 * otherwise we can miss a link state transition
-	 */
-	if (ecmd->speed == 10000) {
-		reg = efx_mdio_read(efx, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1);
-		return reg & MDIO_PCS_10GBRT_STAT1_BLKLK;
-	} else {
-		reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_STATUS_REG);
-		return reg & (1 << C22EXT_STATUS_LINK_LBN);
-	}
-}
-
 static void tenxpress_ext_loopback(struct efx_nic *efx)
 {
 	efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1,
 			  1 << LOOPBACK_NEAR_LBN,
 			  efx->loopback_mode == LOOPBACK_PHYXS);
-	if (efx->phy_type != PHY_TYPE_SFX7101)
-		efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, GPHY_XCONTROL_REG,
-				  1 << GPHY_LOOPBACK_NEAR_LBN,
-				  efx->loopback_mode == LOOPBACK_GPHY);
 }
 
 static void tenxpress_low_power(struct efx_nic *efx)
 {
-	if (efx->phy_type == PHY_TYPE_SFX7101)
-		efx_mdio_set_mmds_lpower(
-			efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER),
-			TENXPRESS_REQUIRED_DEVS);
-	else
-		efx_mdio_set_flag(
-			efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG,
-			1 << PMA_PMD_EXT_LPOWER_LBN,
-			!!(efx->phy_mode & PHY_MODE_LOW_POWER));
+	efx_mdio_set_mmds_lpower(
+		efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER),
+		TENXPRESS_REQUIRED_DEVS);
 }
 
 static int tenxpress_phy_reconfigure(struct efx_nic *efx)
@@ -550,12 +338,7 @@
 
 	if (loop_reset || phy_mode_change) {
 		tenxpress_special_reset(efx);
-
-		/* Reset XAUI if we were in 10G, and are staying
-		 * in 10G. If we're moving into and out of 10G
-		 * then xaui will be reset anyway */
-		if (EFX_IS10G(efx))
-			falcon_reset_xaui(efx);
+		falcon_reset_xaui(efx);
 	}
 
 	tenxpress_low_power(efx);
@@ -578,29 +361,12 @@
 {
 	struct efx_link_state old_state = efx->link_state;
 
-	if (efx->phy_type == PHY_TYPE_SFX7101) {
-		efx->link_state.up = sfx7101_link_ok(efx);
-		efx->link_state.speed = 10000;
-		efx->link_state.fd = true;
-		efx->link_state.fc = efx_mdio_get_pause(efx);
+	efx->link_state.up = sfx7101_link_ok(efx);
+	efx->link_state.speed = 10000;
+	efx->link_state.fd = true;
+	efx->link_state.fc = efx_mdio_get_pause(efx);
 
-		sfx7101_check_bad_lp(efx, efx->link_state.up);
-	} else {
-		struct ethtool_cmd ecmd;
-
-		/* Check the LASI alarm first */
-		if (efx->loopback_mode == LOOPBACK_NONE &&
-		    !(efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT) &
-		      MDIO_PMA_LASI_LSALARM))
-			return false;
-
-		tenxpress_get_settings(efx, &ecmd);
-
-		efx->link_state.up = sft9001_link_ok(efx, &ecmd);
-		efx->link_state.speed = ecmd.speed;
-		efx->link_state.fd = (ecmd.duplex == DUPLEX_FULL);
-		efx->link_state.fc = efx_mdio_get_pause(efx);
-	}
+	sfx7101_check_bad_lp(efx, efx->link_state.up);
 
 	return !efx_link_state_equal(&efx->link_state, &old_state);
 }
@@ -621,10 +387,6 @@
 
 static void tenxpress_phy_remove(struct efx_nic *efx)
 {
-	if (efx->phy_type == PHY_TYPE_SFT9001B)
-		device_remove_file(&efx->pci_dev->dev,
-				   &dev_attr_phy_short_reach);
-
 	kfree(efx->phy_data);
 	efx->phy_data = NULL;
 }
@@ -647,10 +409,7 @@
 			(PMA_PMD_LED_ON << PMA_PMD_LED_LINK_LBN);
 		break;
 	default:
-		if (efx->phy_type == PHY_TYPE_SFX7101)
-			reg = SFX7101_PMA_PMD_LED_DEFAULT;
-		else
-			reg = SFT9001_PMA_PMD_LED_DEFAULT;
+		reg = SFX7101_PMA_PMD_LED_DEFAULT;
 		break;
 	}
 
@@ -685,102 +444,12 @@
 	return rc;
 }
 
-static const char *const sft9001_test_names[] = {
-	"bist",
-	"cable.pairA.status",
-	"cable.pairB.status",
-	"cable.pairC.status",
-	"cable.pairD.status",
-	"cable.pairA.length",
-	"cable.pairB.length",
-	"cable.pairC.length",
-	"cable.pairD.length",
-};
-
-static const char *sft9001_test_name(struct efx_nic *efx, unsigned int index)
-{
-	if (index < ARRAY_SIZE(sft9001_test_names))
-		return sft9001_test_names[index];
-	return NULL;
-}
-
-static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags)
-{
-	int rc = 0, rc2, i, ctrl_reg, res_reg;
-
-	/* Initialise cable diagnostic results to unknown failure */
-	for (i = 1; i < 9; ++i)
-		results[i] = -1;
-
-	/* Run cable diagnostics; wait up to 5 seconds for them to complete.
-	 * A cable fault is not a self-test failure, but a timeout is. */
-	ctrl_reg = ((1 << CDIAG_CTRL_IMMED_LBN) |
-		    (CDIAG_CTRL_LEN_METRES << CDIAG_CTRL_LEN_UNIT_LBN));
-	if (flags & ETH_TEST_FL_OFFLINE) {
-		/* Break the link in order to run full diagnostics.  We
-		 * must reset the PHY to resume normal service. */
-		ctrl_reg |= (1 << CDIAG_CTRL_BRK_LINK_LBN);
-	}
-	efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG,
-		       ctrl_reg);
-	i = 0;
-	while (efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG) &
-	       (1 << CDIAG_CTRL_IN_PROG_LBN)) {
-		if (++i == 50) {
-			rc = -ETIMEDOUT;
-			goto out;
-		}
-		msleep(100);
-	}
-	res_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_RES_REG);
-	for (i = 0; i < 4; i++) {
-		int pair_res =
-			(res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH))
-			& ((1 << CDIAG_RES_WIDTH) - 1);
-		int len_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
-					    PMA_PMD_CDIAG_LEN_REG + i);
-		if (pair_res == CDIAG_RES_OK)
-			results[1 + i] = 1;
-		else if (pair_res == CDIAG_RES_INVALID)
-			results[1 + i] = -1;
-		else
-			results[1 + i] = -pair_res;
-		if (pair_res != CDIAG_RES_INVALID &&
-		    pair_res != CDIAG_RES_OPEN &&
-		    len_reg != 0xffff)
-			results[5 + i] = len_reg;
-	}
-
-out:
-	if (flags & ETH_TEST_FL_OFFLINE) {
-		/* Reset, running the BIST and then resuming normal service. */
-		rc2 = tenxpress_special_reset(efx);
-		results[0] = rc2 ? -1 : 1;
-		if (!rc)
-			rc = rc2;
-
-		efx_mdio_an_reconfigure(efx);
-	}
-
-	return rc;
-}
-
 static void
 tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 {
 	u32 adv = 0, lpa = 0;
 	int reg;
 
-	if (efx->phy_type != PHY_TYPE_SFX7101) {
-		reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL);
-		if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN))
-			adv |= ADVERTISED_1000baseT_Full;
-		reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_STATUS);
-		if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN))
-			lpa |= ADVERTISED_1000baseT_Half;
-		if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN))
-			lpa |= ADVERTISED_1000baseT_Full;
-	}
 	reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL);
 	if (reg & MDIO_AN_10GBT_CTRL_ADV10G)
 		adv |= ADVERTISED_10000baseT_Full;
@@ -790,23 +459,9 @@
 
 	mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa);
 
-	if (efx->phy_type != PHY_TYPE_SFX7101) {
-		ecmd->supported |= (SUPPORTED_100baseT_Full |
-				    SUPPORTED_1000baseT_Full);
-		if (ecmd->speed != SPEED_10000) {
-			ecmd->eth_tp_mdix =
-				(efx_mdio_read(efx, MDIO_MMD_PMAPMD,
-					       PMA_PMD_XSTATUS_REG) &
-				 (1 << PMA_PMD_XSTAT_MDIX_LBN))
-				? ETH_TP_MDI_X : ETH_TP_MDI;
-		}
-	}
-
 	/* In loopback, the PHY automatically brings up the correct interface,
 	 * but doesn't advertise the correct speed. So override it */
-	if (efx->loopback_mode == LOOPBACK_GPHY)
-		ecmd->speed = SPEED_1000;
-	else if (LOOPBACK_EXTERNAL(efx))
+	if (LOOPBACK_EXTERNAL(efx))
 		ecmd->speed = SPEED_10000;
 }
 
@@ -825,16 +480,6 @@
 			  advertising & ADVERTISED_10000baseT_Full);
 }
 
-static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising)
-{
-	efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL,
-			  1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN,
-			  advertising & ADVERTISED_1000baseT_Full);
-	efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
-			  MDIO_AN_10GBT_CTRL_ADV10G,
-			  advertising & ADVERTISED_10000baseT_Full);
-}
-
 struct efx_phy_operations falcon_sfx7101_phy_ops = {
 	.probe		  = tenxpress_phy_probe,
 	.init             = tenxpress_phy_init,
@@ -849,18 +494,3 @@
 	.test_name	  = sfx7101_test_name,
 	.run_tests	  = sfx7101_run_tests,
 };
-
-struct efx_phy_operations falcon_sft9001_phy_ops = {
-	.probe		  = tenxpress_phy_probe,
-	.init             = tenxpress_phy_init,
-	.reconfigure      = tenxpress_phy_reconfigure,
-	.poll             = tenxpress_phy_poll,
-	.fini             = efx_port_dummy_op_void,
-	.remove		  = tenxpress_phy_remove,
-	.get_settings	  = tenxpress_get_settings,
-	.set_settings	  = tenxpress_set_settings,
-	.set_npage_adv    = sft9001_set_npage_adv,
-	.test_alive	  = efx_mdio_test_alive,
-	.test_name	  = sft9001_test_name,
-	.run_tests	  = sft9001_run_tests,
-};
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
index c6942da..1172698 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/sfc/tx.c
@@ -28,7 +28,7 @@
  * The tx_queue descriptor ring fill-level must fall below this value
  * before we restart the netif queue
  */
-#define EFX_TXQ_THRESHOLD (EFX_TXQ_MASK / 2u)
+#define EFX_TXQ_THRESHOLD(_efx) ((_efx)->txq_entries / 2u)
 
 /* We need to be able to nest calls to netif_tx_stop_queue(), partly
  * because of the 2 hardware queues associated with each core queue,
@@ -37,8 +37,9 @@
 void efx_stop_queue(struct efx_channel *channel)
 {
 	struct efx_nic *efx = channel->efx;
+	struct efx_tx_queue *tx_queue = efx_channel_get_tx_queue(channel, 0);
 
-	if (!channel->tx_queue)
+	if (!tx_queue)
 		return;
 
 	spin_lock_bh(&channel->tx_stop_lock);
@@ -46,9 +47,8 @@
 
 	atomic_inc(&channel->tx_stop_count);
 	netif_tx_stop_queue(
-		netdev_get_tx_queue(
-			efx->net_dev,
-			channel->tx_queue->queue / EFX_TXQ_TYPES));
+		netdev_get_tx_queue(efx->net_dev,
+				    tx_queue->queue / EFX_TXQ_TYPES));
 
 	spin_unlock_bh(&channel->tx_stop_lock);
 }
@@ -57,8 +57,9 @@
 void efx_wake_queue(struct efx_channel *channel)
 {
 	struct efx_nic *efx = channel->efx;
+	struct efx_tx_queue *tx_queue = efx_channel_get_tx_queue(channel, 0);
 
-	if (!channel->tx_queue)
+	if (!tx_queue)
 		return;
 
 	local_bh_disable();
@@ -66,9 +67,8 @@
 				&channel->tx_stop_lock)) {
 		netif_vdbg(efx, tx_queued, efx->net_dev, "waking TX queue\n");
 		netif_tx_wake_queue(
-			netdev_get_tx_queue(
-				efx->net_dev,
-				channel->tx_queue->queue / EFX_TXQ_TYPES));
+			netdev_get_tx_queue(efx->net_dev,
+					    tx_queue->queue / EFX_TXQ_TYPES));
 		spin_unlock(&channel->tx_stop_lock);
 	}
 	local_bh_enable();
@@ -207,7 +207,7 @@
 	}
 
 	fill_level = tx_queue->insert_count - tx_queue->old_read_count;
-	q_space = EFX_TXQ_MASK - 1 - fill_level;
+	q_space = efx->txq_entries - 1 - fill_level;
 
 	/* Map for DMA.  Use pci_map_single rather than pci_map_page
 	 * since this is more efficient on machines with sparse
@@ -244,14 +244,14 @@
 					&tx_queue->read_count;
 				fill_level = (tx_queue->insert_count
 					      - tx_queue->old_read_count);
-				q_space = EFX_TXQ_MASK - 1 - fill_level;
+				q_space = efx->txq_entries - 1 - fill_level;
 				if (unlikely(q_space-- <= 0))
 					goto stop;
 				smp_mb();
 				--tx_queue->stopped;
 			}
 
-			insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
+			insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
 			buffer = &tx_queue->buffer[insert_ptr];
 			efx_tsoh_free(tx_queue, buffer);
 			EFX_BUG_ON_PARANOID(buffer->tsoh);
@@ -320,7 +320,7 @@
 	/* Work backwards until we hit the original insert pointer value */
 	while (tx_queue->insert_count != tx_queue->write_count) {
 		--tx_queue->insert_count;
-		insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
+		insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
 		buffer = &tx_queue->buffer[insert_ptr];
 		efx_dequeue_buffer(tx_queue, buffer);
 		buffer->len = 0;
@@ -350,8 +350,8 @@
 	struct efx_nic *efx = tx_queue->efx;
 	unsigned int stop_index, read_ptr;
 
-	stop_index = (index + 1) & EFX_TXQ_MASK;
-	read_ptr = tx_queue->read_count & EFX_TXQ_MASK;
+	stop_index = (index + 1) & tx_queue->ptr_mask;
+	read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
 
 	while (read_ptr != stop_index) {
 		struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr];
@@ -368,7 +368,7 @@
 		buffer->len = 0;
 
 		++tx_queue->read_count;
-		read_ptr = tx_queue->read_count & EFX_TXQ_MASK;
+		read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
 	}
 }
 
@@ -390,9 +390,9 @@
 	if (unlikely(efx->port_inhibited))
 		return NETDEV_TX_BUSY;
 
-	tx_queue = &efx->tx_queue[EFX_TXQ_TYPES * skb_get_queue_mapping(skb)];
-	if (likely(skb->ip_summed == CHECKSUM_PARTIAL))
-		tx_queue += EFX_TXQ_TYPE_OFFLOAD;
+	tx_queue = efx_get_tx_queue(efx, skb_get_queue_mapping(skb),
+				    skb->ip_summed == CHECKSUM_PARTIAL ?
+				    EFX_TXQ_TYPE_OFFLOAD : 0);
 
 	return efx_enqueue_skb(tx_queue, skb);
 }
@@ -402,7 +402,7 @@
 	unsigned fill_level;
 	struct efx_nic *efx = tx_queue->efx;
 
-	EFX_BUG_ON_PARANOID(index > EFX_TXQ_MASK);
+	EFX_BUG_ON_PARANOID(index > tx_queue->ptr_mask);
 
 	efx_dequeue_buffers(tx_queue, index);
 
@@ -412,7 +412,7 @@
 	smp_mb();
 	if (unlikely(tx_queue->stopped) && likely(efx->port_enabled)) {
 		fill_level = tx_queue->insert_count - tx_queue->read_count;
-		if (fill_level < EFX_TXQ_THRESHOLD) {
+		if (fill_level < EFX_TXQ_THRESHOLD(efx)) {
 			EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
 
 			/* Do this under netif_tx_lock(), to avoid racing
@@ -430,18 +430,24 @@
 int efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
 {
 	struct efx_nic *efx = tx_queue->efx;
-	unsigned int txq_size;
+	unsigned int entries;
 	int i, rc;
 
-	netif_dbg(efx, probe, efx->net_dev, "creating TX queue %d\n",
-		  tx_queue->queue);
+	/* Create the smallest power-of-two aligned ring */
+	entries = max(roundup_pow_of_two(efx->txq_entries), EFX_MIN_DMAQ_SIZE);
+	EFX_BUG_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE);
+	tx_queue->ptr_mask = entries - 1;
+
+	netif_dbg(efx, probe, efx->net_dev,
+		  "creating TX queue %d size %#x mask %#x\n",
+		  tx_queue->queue, efx->txq_entries, tx_queue->ptr_mask);
 
 	/* Allocate software ring */
-	txq_size = EFX_TXQ_SIZE * sizeof(*tx_queue->buffer);
-	tx_queue->buffer = kzalloc(txq_size, GFP_KERNEL);
+	tx_queue->buffer = kzalloc(entries * sizeof(*tx_queue->buffer),
+				   GFP_KERNEL);
 	if (!tx_queue->buffer)
 		return -ENOMEM;
-	for (i = 0; i <= EFX_TXQ_MASK; ++i)
+	for (i = 0; i <= tx_queue->ptr_mask; ++i)
 		tx_queue->buffer[i].continuation = true;
 
 	/* Allocate hardware ring */
@@ -481,7 +487,7 @@
 
 	/* Free any buffers left in the ring */
 	while (tx_queue->read_count != tx_queue->write_count) {
-		buffer = &tx_queue->buffer[tx_queue->read_count & EFX_TXQ_MASK];
+		buffer = &tx_queue->buffer[tx_queue->read_count & tx_queue->ptr_mask];
 		efx_dequeue_buffer(tx_queue, buffer);
 		buffer->continuation = true;
 		buffer->len = 0;
@@ -741,7 +747,7 @@
 
 	fill_level = tx_queue->insert_count - tx_queue->old_read_count;
 	/* -1 as there is no way to represent all descriptors used */
-	q_space = EFX_TXQ_MASK - 1 - fill_level;
+	q_space = efx->txq_entries - 1 - fill_level;
 
 	while (1) {
 		if (unlikely(q_space-- <= 0)) {
@@ -757,7 +763,7 @@
 				*(volatile unsigned *)&tx_queue->read_count;
 			fill_level = (tx_queue->insert_count
 				      - tx_queue->old_read_count);
-			q_space = EFX_TXQ_MASK - 1 - fill_level;
+			q_space = efx->txq_entries - 1 - fill_level;
 			if (unlikely(q_space-- <= 0)) {
 				*final_buffer = NULL;
 				return 1;
@@ -766,13 +772,13 @@
 			--tx_queue->stopped;
 		}
 
-		insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
+		insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
 		buffer = &tx_queue->buffer[insert_ptr];
 		++tx_queue->insert_count;
 
 		EFX_BUG_ON_PARANOID(tx_queue->insert_count -
-				    tx_queue->read_count >
-				    EFX_TXQ_MASK);
+				    tx_queue->read_count >=
+				    efx->txq_entries);
 
 		efx_tsoh_free(tx_queue, buffer);
 		EFX_BUG_ON_PARANOID(buffer->len);
@@ -813,7 +819,7 @@
 {
 	struct efx_tx_buffer *buffer;
 
-	buffer = &tx_queue->buffer[tx_queue->insert_count & EFX_TXQ_MASK];
+	buffer = &tx_queue->buffer[tx_queue->insert_count & tx_queue->ptr_mask];
 	efx_tsoh_free(tx_queue, buffer);
 	EFX_BUG_ON_PARANOID(buffer->len);
 	EFX_BUG_ON_PARANOID(buffer->unmap_len);
@@ -838,7 +844,7 @@
 	while (tx_queue->insert_count != tx_queue->write_count) {
 		--tx_queue->insert_count;
 		buffer = &tx_queue->buffer[tx_queue->insert_count &
-					   EFX_TXQ_MASK];
+					   tx_queue->ptr_mask];
 		efx_tsoh_free(tx_queue, buffer);
 		EFX_BUG_ON_PARANOID(buffer->skb);
 		if (buffer->unmap_len) {
@@ -1168,7 +1174,7 @@
 	unsigned i;
 
 	if (tx_queue->buffer) {
-		for (i = 0; i <= EFX_TXQ_MASK; ++i)
+		for (i = 0; i <= tx_queue->ptr_mask; ++i)
 			efx_tsoh_free(tx_queue, &tx_queue->buffer[i]);
 	}
 
diff --git a/drivers/net/sfc/txc43128_phy.c b/drivers/net/sfc/txc43128_phy.c
new file mode 100644
index 0000000..351794a
--- /dev/null
+++ b/drivers/net/sfc/txc43128_phy.c
@@ -0,0 +1,560 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * 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
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+/*
+ * Driver for Transwitch/Mysticom CX4 retimer
+ * see www.transwitch.com, part is TXC-43128
+ */
+
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include "efx.h"
+#include "mdio_10g.h"
+#include "phy.h"
+#include "nic.h"
+
+/* We expect these MMDs to be in the package */
+#define TXC_REQUIRED_DEVS (MDIO_DEVS_PCS |	\
+			   MDIO_DEVS_PMAPMD |	\
+			   MDIO_DEVS_PHYXS)
+
+#define TXC_LOOPBACKS ((1 << LOOPBACK_PCS) |	\
+		       (1 << LOOPBACK_PMAPMD) |	\
+		       (1 << LOOPBACK_PHYXS_WS))
+
+/**************************************************************************
+ *
+ * Compile-time config
+ *
+ **************************************************************************
+ */
+#define TXCNAME "TXC43128"
+/* Total length of time we'll wait for the PHY to come out of reset (ms) */
+#define TXC_MAX_RESET_TIME	500
+/* Interval between checks (ms) */
+#define TXC_RESET_WAIT		10
+/* How long to run BIST (us) */
+#define TXC_BIST_DURATION	50
+
+/**************************************************************************
+ *
+ * Register definitions
+ *
+ **************************************************************************
+ */
+
+/* Command register */
+#define TXC_GLRGS_GLCMD		0xc004
+/* Useful bits in command register */
+/* Lane power-down */
+#define TXC_GLCMD_L01PD_LBN	5
+#define TXC_GLCMD_L23PD_LBN	6
+/* Limited SW reset: preserves configuration but
+ * initiates a logic reset. Self-clearing */
+#define TXC_GLCMD_LMTSWRST_LBN	14
+
+/* Signal Quality Control */
+#define TXC_GLRGS_GSGQLCTL	0xc01a
+/* Enable bit */
+#define TXC_GSGQLCT_SGQLEN_LBN	15
+/* Lane selection */
+#define TXC_GSGQLCT_LNSL_LBN	13
+#define TXC_GSGQLCT_LNSL_WIDTH	2
+
+/* Analog TX control */
+#define TXC_ALRGS_ATXCTL	0xc040
+/* Lane power-down */
+#define TXC_ATXCTL_TXPD3_LBN	15
+#define TXC_ATXCTL_TXPD2_LBN	14
+#define TXC_ATXCTL_TXPD1_LBN	13
+#define TXC_ATXCTL_TXPD0_LBN	12
+
+/* Amplitude on lanes 0, 1 */
+#define TXC_ALRGS_ATXAMP0	0xc041
+/* Amplitude on lanes 2, 3 */
+#define TXC_ALRGS_ATXAMP1	0xc042
+/* Bit position of value for lane 0 (or 2) */
+#define TXC_ATXAMP_LANE02_LBN	3
+/* Bit position of value for lane 1 (or 3) */
+#define TXC_ATXAMP_LANE13_LBN	11
+
+#define TXC_ATXAMP_1280_mV	0
+#define TXC_ATXAMP_1200_mV	8
+#define TXC_ATXAMP_1120_mV	12
+#define TXC_ATXAMP_1060_mV	14
+#define TXC_ATXAMP_0820_mV	25
+#define TXC_ATXAMP_0720_mV	26
+#define TXC_ATXAMP_0580_mV	27
+#define TXC_ATXAMP_0440_mV	28
+
+#define TXC_ATXAMP_0820_BOTH					\
+	((TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE02_LBN)		\
+	 | (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE13_LBN))
+
+#define TXC_ATXAMP_DEFAULT	0x6060 /* From databook */
+
+/* Preemphasis on lanes 0, 1 */
+#define TXC_ALRGS_ATXPRE0	0xc043
+/* Preemphasis on lanes 2, 3 */
+#define TXC_ALRGS_ATXPRE1	0xc044
+
+#define TXC_ATXPRE_NONE 0
+#define TXC_ATXPRE_DEFAULT	0x1010 /* From databook */
+
+#define TXC_ALRGS_ARXCTL	0xc045
+/* Lane power-down */
+#define TXC_ARXCTL_RXPD3_LBN	15
+#define TXC_ARXCTL_RXPD2_LBN	14
+#define TXC_ARXCTL_RXPD1_LBN	13
+#define TXC_ARXCTL_RXPD0_LBN	12
+
+/* Main control */
+#define TXC_MRGS_CTL		0xc340
+/* Bits in main control */
+#define TXC_MCTL_RESET_LBN	15	/* Self clear */
+#define TXC_MCTL_TXLED_LBN	14	/* 1 to show align status */
+#define TXC_MCTL_RXLED_LBN	13	/* 1 to show align status */
+
+/* GPIO output */
+#define TXC_GPIO_OUTPUT		0xc346
+#define TXC_GPIO_DIR		0xc348
+
+/* Vendor-specific BIST registers */
+#define TXC_BIST_CTL		0xc280
+#define TXC_BIST_TXFRMCNT	0xc281
+#define TXC_BIST_RX0FRMCNT	0xc282
+#define TXC_BIST_RX1FRMCNT	0xc283
+#define TXC_BIST_RX2FRMCNT	0xc284
+#define TXC_BIST_RX3FRMCNT	0xc285
+#define TXC_BIST_RX0ERRCNT	0xc286
+#define TXC_BIST_RX1ERRCNT	0xc287
+#define TXC_BIST_RX2ERRCNT	0xc288
+#define TXC_BIST_RX3ERRCNT	0xc289
+
+/* BIST type (controls bit patter in test) */
+#define TXC_BIST_CTRL_TYPE_LBN	10
+#define TXC_BIST_CTRL_TYPE_TSD	0	/* TranSwitch Deterministic */
+#define TXC_BIST_CTRL_TYPE_CRP	1	/* CRPAT standard */
+#define TXC_BIST_CTRL_TYPE_CJP	2	/* CJPAT standard */
+#define TXC_BIST_CTRL_TYPE_TSR	3	/* TranSwitch pseudo-random */
+/* Set this to 1 for 10 bit and 0 for 8 bit */
+#define TXC_BIST_CTRL_B10EN_LBN	12
+/* Enable BIST (write 0 to disable) */
+#define TXC_BIST_CTRL_ENAB_LBN	13
+/* Stop BIST (self-clears when stop complete) */
+#define TXC_BIST_CTRL_STOP_LBN	14
+/* Start BIST (cleared by writing 1 to STOP) */
+#define TXC_BIST_CTRL_STRT_LBN	15
+
+/* Mt. Diablo test configuration */
+#define TXC_MTDIABLO_CTRL	0xc34f
+#define TXC_MTDIABLO_CTRL_PMA_LOOP_LBN	10
+
+struct txc43128_data {
+	unsigned long bug10934_timer;
+	enum efx_phy_mode phy_mode;
+	enum efx_loopback_mode loopback_mode;
+};
+
+/* The PHY sometimes needs a reset to bring the link back up.  So long as
+ * it reports link down, we reset it every 5 seconds.
+ */
+#define BUG10934_RESET_INTERVAL (5 * HZ)
+
+/* Perform a reset that doesn't clear configuration changes */
+static void txc_reset_logic(struct efx_nic *efx);
+
+/* Set the output value of a gpio */
+void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int on)
+{
+	efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT, 1 << pin, on);
+}
+
+/* Set up the GPIO direction register */
+void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir)
+{
+	efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_DIR, 1 << pin, dir);
+}
+
+/* Reset the PMA/PMD MMD. The documentation is explicit that this does a
+ * global reset (it's less clear what reset of other MMDs does).*/
+static int txc_reset_phy(struct efx_nic *efx)
+{
+	int rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PMAPMD,
+				    TXC_MAX_RESET_TIME / TXC_RESET_WAIT,
+				    TXC_RESET_WAIT);
+	if (rc < 0)
+		goto fail;
+
+	/* Check that all the MMDs we expect are present and responding. */
+	rc = efx_mdio_check_mmds(efx, TXC_REQUIRED_DEVS, 0);
+	if (rc < 0)
+		goto fail;
+
+	return 0;
+
+fail:
+	netif_err(efx, hw, efx->net_dev, TXCNAME ": reset timed out!\n");
+	return rc;
+}
+
+/* Run a single BIST on one MMD */
+static int txc_bist_one(struct efx_nic *efx, int mmd, int test)
+{
+	int ctrl, bctl;
+	int lane;
+	int rc = 0;
+
+	/* Set PMA to test into loopback using Mt Diablo reg as per app note */
+	ctrl = efx_mdio_read(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL);
+	ctrl |= (1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
+	efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);
+
+	/* The BIST app. note lists these  as 3 distinct steps. */
+	/* Set the BIST type */
+	bctl = (test << TXC_BIST_CTRL_TYPE_LBN);
+	efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+
+	/* Set the BSTEN bit in the BIST Control register to enable */
+	bctl |= (1 << TXC_BIST_CTRL_ENAB_LBN);
+	efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+
+	/* Set the BSTRT bit in the BIST Control register */
+	efx_mdio_write(efx, mmd, TXC_BIST_CTL,
+		       bctl | (1 << TXC_BIST_CTRL_STRT_LBN));
+
+	/* Wait. */
+	udelay(TXC_BIST_DURATION);
+
+	/* Set the BSTOP bit in the BIST Control register */
+	bctl |= (1 << TXC_BIST_CTRL_STOP_LBN);
+	efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+
+	/* The STOP bit should go off when things have stopped */
+	while (bctl & (1 << TXC_BIST_CTRL_STOP_LBN))
+		bctl = efx_mdio_read(efx, mmd, TXC_BIST_CTL);
+
+	/* Check all the error counts are 0 and all the frame counts are
+	   non-zero */
+	for (lane = 0; lane < 4; lane++) {
+		int count = efx_mdio_read(efx, mmd, TXC_BIST_RX0ERRCNT + lane);
+		if (count != 0) {
+			netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. "
+				  "Lane %d had %d errs\n", lane, count);
+			rc = -EIO;
+		}
+		count = efx_mdio_read(efx, mmd, TXC_BIST_RX0FRMCNT + lane);
+		if (count == 0) {
+			netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. "
+				  "Lane %d got 0 frames\n", lane);
+			rc = -EIO;
+		}
+	}
+
+	if (rc == 0)
+		netif_info(efx, hw, efx->net_dev, TXCNAME": BIST pass\n");
+
+	/* Disable BIST */
+	efx_mdio_write(efx, mmd, TXC_BIST_CTL, 0);
+
+	/* Turn off loopback */
+	ctrl &= ~(1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
+	efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);
+
+	return rc;
+}
+
+static int txc_bist(struct efx_nic *efx)
+{
+	return txc_bist_one(efx, MDIO_MMD_PCS, TXC_BIST_CTRL_TYPE_TSD);
+}
+
+/* Push the non-configurable defaults into the PHY. This must be
+ * done after every full reset */
+static void txc_apply_defaults(struct efx_nic *efx)
+{
+	int mctrl;
+
+	/* Turn amplitude down and preemphasis off on the host side
+	 * (PHY<->MAC) as this is believed less likely to upset Falcon
+	 * and no adverse effects have been noted. It probably also
+	 * saves a picowatt or two */
+
+	/* Turn off preemphasis */
+	efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE0, TXC_ATXPRE_NONE);
+	efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE1, TXC_ATXPRE_NONE);
+
+	/* Turn down the amplitude */
+	efx_mdio_write(efx, MDIO_MMD_PHYXS,
+		       TXC_ALRGS_ATXAMP0, TXC_ATXAMP_0820_BOTH);
+	efx_mdio_write(efx, MDIO_MMD_PHYXS,
+		       TXC_ALRGS_ATXAMP1, TXC_ATXAMP_0820_BOTH);
+
+	/* Set the line side amplitude and preemphasis to the databook
+	 * defaults as an erratum causes them to be 0 on at least some
+	 * PHY rev.s */
+	efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+		       TXC_ALRGS_ATXPRE0, TXC_ATXPRE_DEFAULT);
+	efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+		       TXC_ALRGS_ATXPRE1, TXC_ATXPRE_DEFAULT);
+	efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+		       TXC_ALRGS_ATXAMP0, TXC_ATXAMP_DEFAULT);
+	efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+		       TXC_ALRGS_ATXAMP1, TXC_ATXAMP_DEFAULT);
+
+	/* Set up the LEDs  */
+	mctrl = efx_mdio_read(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL);
+
+	/* Set the Green and Red LEDs to their default modes */
+	mctrl &= ~((1 << TXC_MCTL_TXLED_LBN) | (1 << TXC_MCTL_RXLED_LBN));
+	efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL, mctrl);
+
+	/* Databook recommends doing this after configuration changes */
+	txc_reset_logic(efx);
+
+	falcon_board(efx)->type->init_phy(efx);
+}
+
+static int txc43128_phy_probe(struct efx_nic *efx)
+{
+	struct txc43128_data *phy_data;
+
+	/* Allocate phy private storage */
+	phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
+	if (!phy_data)
+		return -ENOMEM;
+	efx->phy_data = phy_data;
+	phy_data->phy_mode = efx->phy_mode;
+
+	efx->mdio.mmds = TXC_REQUIRED_DEVS;
+	efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+
+	efx->loopback_modes = TXC_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
+
+	return 0;
+}
+
+/* Initialisation entry point for this PHY driver */
+static int txc43128_phy_init(struct efx_nic *efx)
+{
+	int rc;
+
+	rc = txc_reset_phy(efx);
+	if (rc < 0)
+		return rc;
+
+	rc = txc_bist(efx);
+	if (rc < 0)
+		return rc;
+
+	txc_apply_defaults(efx);
+
+	return 0;
+}
+
+/* Set the lane power down state in the global registers */
+static void txc_glrgs_lane_power(struct efx_nic *efx, int mmd)
+{
+	int pd = (1 << TXC_GLCMD_L01PD_LBN) | (1 << TXC_GLCMD_L23PD_LBN);
+	int ctl = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+
+	if (!(efx->phy_mode & PHY_MODE_LOW_POWER))
+		ctl &= ~pd;
+	else
+		ctl |= pd;
+
+	efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, ctl);
+}
+
+/* Set the lane power down state in the analog control registers */
+static void txc_analog_lane_power(struct efx_nic *efx, int mmd)
+{
+	int txpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN)
+		| (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN);
+	int rxpd = (1 << TXC_ARXCTL_RXPD3_LBN) | (1 << TXC_ARXCTL_RXPD2_LBN)
+		| (1 << TXC_ARXCTL_RXPD1_LBN) | (1 << TXC_ARXCTL_RXPD0_LBN);
+	int txctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ATXCTL);
+	int rxctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ARXCTL);
+
+	if (!(efx->phy_mode & PHY_MODE_LOW_POWER)) {
+		txctl &= ~txpd;
+		rxctl &= ~rxpd;
+	} else {
+		txctl |= txpd;
+		rxctl |= rxpd;
+	}
+
+	efx_mdio_write(efx, mmd, TXC_ALRGS_ATXCTL, txctl);
+	efx_mdio_write(efx, mmd, TXC_ALRGS_ARXCTL, rxctl);
+}
+
+static void txc_set_power(struct efx_nic *efx)
+{
+	/* According to the data book, all the MMDs can do low power */
+	efx_mdio_set_mmds_lpower(efx,
+				 !!(efx->phy_mode & PHY_MODE_LOW_POWER),
+				 TXC_REQUIRED_DEVS);
+
+	/* Global register bank is in PCS, PHY XS. These control the host
+	 * side and line side settings respectively. */
+	txc_glrgs_lane_power(efx, MDIO_MMD_PCS);
+	txc_glrgs_lane_power(efx, MDIO_MMD_PHYXS);
+
+	/* Analog register bank in PMA/PMD, PHY XS */
+	txc_analog_lane_power(efx, MDIO_MMD_PMAPMD);
+	txc_analog_lane_power(efx, MDIO_MMD_PHYXS);
+}
+
+static void txc_reset_logic_mmd(struct efx_nic *efx, int mmd)
+{
+	int val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+	int tries = 50;
+
+	val |= (1 << TXC_GLCMD_LMTSWRST_LBN);
+	efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, val);
+	while (tries--) {
+		val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+		if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN)))
+			break;
+		udelay(1);
+	}
+	if (!tries)
+		netif_info(efx, hw, efx->net_dev,
+			   TXCNAME " Logic reset timed out!\n");
+}
+
+/* Perform a logic reset. This preserves the configuration registers
+ * and is needed for some configuration changes to take effect */
+static void txc_reset_logic(struct efx_nic *efx)
+{
+	/* The data sheet claims we can do the logic reset on either the
+	 * PCS or the PHYXS and the result is a reset of both host- and
+	 * line-side logic. */
+	txc_reset_logic_mmd(efx, MDIO_MMD_PCS);
+}
+
+static bool txc43128_phy_read_link(struct efx_nic *efx)
+{
+	return efx_mdio_links_ok(efx, TXC_REQUIRED_DEVS);
+}
+
+static int txc43128_phy_reconfigure(struct efx_nic *efx)
+{
+	struct txc43128_data *phy_data = efx->phy_data;
+	enum efx_phy_mode mode_change = efx->phy_mode ^ phy_data->phy_mode;
+	bool loop_change = LOOPBACK_CHANGED(phy_data, efx, TXC_LOOPBACKS);
+
+	if (efx->phy_mode & mode_change & PHY_MODE_TX_DISABLED) {
+		txc_reset_phy(efx);
+		txc_apply_defaults(efx);
+		falcon_reset_xaui(efx);
+		mode_change &= ~PHY_MODE_TX_DISABLED;
+	}
+
+	efx_mdio_transmit_disable(efx);
+	efx_mdio_phy_reconfigure(efx);
+	if (mode_change & PHY_MODE_LOW_POWER)
+		txc_set_power(efx);
+
+	/* The data sheet claims this is required after every reconfiguration
+	 * (note at end of 7.1), but we mustn't do it when nothing changes as
+	 * it glitches the link, and reconfigure gets called on link change,
+	 * so we get an IRQ storm on link up. */
+	if (loop_change || mode_change)
+		txc_reset_logic(efx);
+
+	phy_data->phy_mode = efx->phy_mode;
+	phy_data->loopback_mode = efx->loopback_mode;
+
+	return 0;
+}
+
+static void txc43128_phy_fini(struct efx_nic *efx)
+{
+	/* Disable link events */
+	efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0);
+}
+
+static void txc43128_phy_remove(struct efx_nic *efx)
+{
+	kfree(efx->phy_data);
+	efx->phy_data = NULL;
+}
+
+/* Periodic callback: this exists mainly to poll link status as we
+ * don't use LASI interrupts */
+static bool txc43128_phy_poll(struct efx_nic *efx)
+{
+	struct txc43128_data *data = efx->phy_data;
+	bool was_up = efx->link_state.up;
+
+	efx->link_state.up = txc43128_phy_read_link(efx);
+	efx->link_state.speed = 10000;
+	efx->link_state.fd = true;
+	efx->link_state.fc = efx->wanted_fc;
+
+	if (efx->link_state.up || (efx->loopback_mode != LOOPBACK_NONE)) {
+		data->bug10934_timer = jiffies;
+	} else {
+		if (time_after_eq(jiffies, (data->bug10934_timer +
+					    BUG10934_RESET_INTERVAL))) {
+			data->bug10934_timer = jiffies;
+			txc_reset_logic(efx);
+		}
+	}
+
+	return efx->link_state.up != was_up;
+}
+
+static const char *txc43128_test_names[] = {
+	"bist"
+};
+
+static const char *txc43128_test_name(struct efx_nic *efx, unsigned int index)
+{
+	if (index < ARRAY_SIZE(txc43128_test_names))
+		return txc43128_test_names[index];
+	return NULL;
+}
+
+static int txc43128_run_tests(struct efx_nic *efx, int *results, unsigned flags)
+{
+	int rc;
+
+	if (!(flags & ETH_TEST_FL_OFFLINE))
+		return 0;
+
+	rc = txc_reset_phy(efx);
+	if (rc < 0)
+		return rc;
+
+	rc = txc_bist(efx);
+	txc_apply_defaults(efx);
+	results[0] = rc ? -1 : 1;
+	return rc;
+}
+
+static void txc43128_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+	mdio45_ethtool_gset(&efx->mdio, ecmd);
+}
+
+struct efx_phy_operations falcon_txc_phy_ops = {
+	.probe		= txc43128_phy_probe,
+	.init		= txc43128_phy_init,
+	.reconfigure	= txc43128_phy_reconfigure,
+	.poll		= txc43128_phy_poll,
+	.fini		= txc43128_phy_fini,
+	.remove		= txc43128_phy_remove,
+	.get_settings	= txc43128_get_settings,
+	.set_settings	= efx_mdio_set_settings,
+	.test_alive	= efx_mdio_test_alive,
+	.run_tests	= txc43128_run_tests,
+	.test_name	= txc43128_test_name,
+};
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
index 782e45a..e0d6308 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/sfc/workarounds.h
@@ -19,9 +19,7 @@
 #define EFX_WORKAROUND_FALCON_A(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_A1)
 #define EFX_WORKAROUND_FALCON_AB(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_B0)
 #define EFX_WORKAROUND_SIENA(efx) (efx_nic_rev(efx) == EFX_REV_SIENA_A0)
-#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx)
-#define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \
-				     (efx)->phy_type == PHY_TYPE_SFT9001B)
+#define EFX_WORKAROUND_10G(efx) 1
 
 /* XAUI resets if link not detected */
 #define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
@@ -58,9 +56,4 @@
 /* Leak overlength packets rather than free */
 #define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
 
-/* Need to send XNP pages for 100BaseT */
-#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001
-/* Don't restart AN in near-side loopback */
-#define EFX_WORKAROUND_15195 EFX_WORKAROUND_SFT9001
-
 #endif /* EFX_WORKAROUNDS_H */
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index cc4bd8c..9265315 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -804,7 +804,7 @@
 err_out_free_page:
 	free_page((unsigned long) sp->srings);
 err_out_free_dev:
-	kfree(dev);
+	free_netdev(dev);
 
 err_out:
 	return err;
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 79fd02b..50259df 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -798,7 +798,7 @@
 			skb->dev = ndev;
 			sh_eth_set_receive_align(skb);
 
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
 			rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
 		}
 		if (entry >= RX_RING_SIZE - 1)
@@ -1031,7 +1031,7 @@
 	mdp->duplex = -1;
 
 	/* Try connect to PHY */
-	phydev = phy_connect(ndev, phy_id, &sh_eth_adjust_link,
+	phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link,
 				0, PHY_INTERFACE_MODE_MII);
 	if (IS_ERR(phydev)) {
 		dev_err(&ndev->dev, "phy_connect failed\n");
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index bbbded7..5818368 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -832,7 +832,7 @@
 	outl(0, ee_addr);
 	eeprom_delay();
 
-	return (retval);
+	return retval;
 }
 
 /* Read and write the MII management registers using software-generated
@@ -1042,7 +1042,7 @@
 	init_timer(&sis_priv->timer);
 	sis_priv->timer.expires = jiffies + HZ;
 	sis_priv->timer.data = (unsigned long)net_dev;
-	sis_priv->timer.function = &sis900_timer;
+	sis_priv->timer.function = sis900_timer;
 	add_timer(&sis_priv->timer);
 
 	return 0;
@@ -2247,9 +2247,9 @@
 
 	/* leave 8 or 7 most siginifant bits */
 	if ((revision >= SIS635A_900_REV) || (revision == SIS900B_900_REV))
-		return ((int)(crc >> 24));
+		return (int)(crc >> 24);
 	else
-		return ((int)(crc >> 25));
+		return (int)(crc >> 25);
 }
 
 /**
diff --git a/drivers/net/skfp/cfm.c b/drivers/net/skfp/cfm.c
index 5310d39..e395ace 100644
--- a/drivers/net/skfp/cfm.c
+++ b/drivers/net/skfp/cfm.c
@@ -542,8 +542,8 @@
  */
 int cfm_get_mac_input(struct s_smc *smc)
 {
-	return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
-		smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA) ;
+	return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
+		smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA;
 }
 
 /*
@@ -553,8 +553,8 @@
  */
 int cfm_get_mac_output(struct s_smc *smc)
 {
-	return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
-		smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA) ;
+	return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
+		smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA;
 }
 
 static char path_iso[] = {
@@ -623,5 +623,5 @@
 
 	LINT_USE(path_index);
 
-	return(len) ;
+	return len;
 }
diff --git a/drivers/net/skfp/drvfbi.c b/drivers/net/skfp/drvfbi.c
index c77cc14..07da97c 100644
--- a/drivers/net/skfp/drvfbi.c
+++ b/drivers/net/skfp/drvfbi.c
@@ -267,7 +267,7 @@
 int pcm_get_s_port(struct s_smc *smc)
 {
 	SK_UNUSED(smc) ;
-	return(PS) ;
+	return PS;
 }
 
 /*
@@ -366,7 +366,7 @@
  */
 int sm_pm_bypass_present(struct s_smc *smc)
 {
-	return(	(inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE: FALSE) ;
+	return (inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE : FALSE;
 }
 
 void plc_clear_irq(struct s_smc *smc, int p)
@@ -483,9 +483,9 @@
 
 	for (i = 0 ; i < num ; i++) {
 		if (comp1[i] != comp2[i])
-			return (0) ;
+			return 0;
 	}
-		return (1) ;
+		return 1;
 }	/* is_equal_num */
 
 
@@ -522,18 +522,18 @@
 			i++ ;
 			break ;			/* entry ok */
 		default:
-			return (1) ;		/* invalid oi_status */
+			return 1;		/* invalid oi_status */
 		}
 	}
 
 	if (i == 0)
-		return (2) ;
+		return 2;
 	if (!act_entries)
-		return (3) ;
+		return 3;
 
 	/* ok, we have a valid OEM data base with an active entry */
 	smc->hw.oem_id = (struct s_oem_ids *)  &oem_ids[sel_id] ;
-	return (0) ;
+	return 0;
 }
 #endif	/* MULT_OEM */
 
diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c
index e8387d2..8639a08 100644
--- a/drivers/net/skfp/ess.c
+++ b/drivers/net/skfp/ess.c
@@ -135,7 +135,7 @@
 	 */
 	if (!(p = (void *) sm_to_para(smc,sm,SMT_P0015))) {
 		DB_ESS("ESS: RAF frame error, parameter type not found\n",0,0) ;
-		return(fs) ;
+		return fs;
 	}
 	msg_res_type = ((struct smt_p_0015 *)p)->res_type ;
 
@@ -147,7 +147,7 @@
 		 * error in frame: para ESS command was not found
 		 */
 		 DB_ESS("ESS: RAF frame error, parameter command not found\n",0,0);
-		 return(fs) ;
+		 return fs;
 	}
 
 	DB_ESSN(2,"fc %x	ft %x\n",sm->smt_class,sm->smt_type) ;
@@ -175,12 +175,12 @@
 			 * local and no static allocation is used
 			 */
 			if (!local || smc->mib.fddiESSPayload)
-				return(fs) ;
+				return fs;
 			
 			p = (void *) sm_to_para(smc,sm,SMT_P0019)  ;
 			for (i = 0; i < 5; i++) {
 				if (((struct smt_p_0019 *)p)->alloc_addr.a[i]) {
-					return(fs) ;
+					return fs;
 				}
 			}
 
@@ -199,10 +199,10 @@
 			sm->smt_dest = smt_sba_da ;
 
 			if (smc->ess.local_sba_active)
-				return(fs | I_INDICATOR) ;
+				return fs | I_INDICATOR;
 
 			if (!(db = smt_get_mbuf(smc)))
-				return(fs) ;
+				return fs;
 
 			db->sm_len = mb->sm_len ;
 			db->sm_off = mb->sm_off ;
@@ -212,7 +212,7 @@
 				(struct smt_header *)(db->sm_data+db->sm_off),
 				"RAF") ;
 			smt_send_frame(smc,db,FC_SMT_INFO,0) ;
-			return(fs) ;
+			return fs;
 		}
 
 		/*
@@ -221,7 +221,7 @@
 		 */
 		if (smt_check_para(smc,sm,plist_raf_alc_res)) {
 			DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
-			return(fs) ;
+			return fs;
 		}
 
 		/*
@@ -242,7 +242,7 @@
 			(sm->smt_tid != smc->ess.alloc_trans_id)) {
 
 			DB_ESS("ESS: Allocation Responce not accepted\n",0,0) ;
-			return(fs) ;
+			return fs;
 		}
 
 		/*
@@ -268,7 +268,7 @@
 		 */
 		(void)process_bw_alloc(smc,(long)payload,(long)overhead) ;
 
-		return(fs) ;
+		return fs;
 		/* end of Process Allocation Request */
 
 	/*
@@ -280,7 +280,7 @@
 		 */
 		if (sm->smt_type != SMT_REQUEST) {
 			DB_ESS("ESS: Do not process Change Responses\n",0,0) ;
-			return(fs) ;
+			return fs;
 		}
 
 		/*
@@ -288,7 +288,7 @@
 		 */
 		if (smt_check_para(smc,sm,plist_raf_chg_req)) {
 			DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
-			return(fs) ;
+			return fs;
 		}
 
 		/*
@@ -300,7 +300,7 @@
 		if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
 			!= PRIMARY_RING) || (msg_res_type != SYNC_BW)) {
 			DB_ESS("ESS: RAF frame with para problem, ignoring\n",0,0) ;
-			return(fs) ;
+			return fs;
 		}
 
 		/*
@@ -319,14 +319,14 @@
 		 * process the bandwidth allocation
 		 */
 		if(!process_bw_alloc(smc,(long)payload,(long)overhead))
-			return(fs) ;
+			return fs;
 
 		/*
 		 * send an RAF Change Reply
 		 */
 		ess_send_response(smc,sm,CHANGE_ALLOCATION) ;
 
-		return(fs) ;
+		return fs;
 		/* end of Process Change Request */
 
 	/*
@@ -338,7 +338,7 @@
 		 */
 		if (sm->smt_type != SMT_REQUEST) {
 			DB_ESS("ESS: Do not process a Report Reply\n",0,0) ;
-			return(fs) ;
+			return fs;
 		}
 
 		DB_ESSN(2,"ESS: Report Request from %s\n",
@@ -349,7 +349,7 @@
 		 */
 		if (msg_res_type != SYNC_BW) {
 			DB_ESS("ESS: ignoring RAF with para problem\n",0,0) ;
-			return(fs) ;
+			return fs;
 		}
 
 		/*
@@ -357,7 +357,7 @@
 		 */
 		ess_send_response(smc,sm,REPORT_ALLOCATION) ;
 
-		return(fs) ;
+		return fs;
 		/* end of Process Report Request */
 
 	default:
@@ -368,7 +368,7 @@
 		break ;
 	}
 
-	return(fs) ;
+	return fs;
 }
 
 /*
@@ -418,17 +418,17 @@
 	 */
 /*	if (smt_set_obj(smc,SMT_P320F,payload,S_SET)) {
 		DB_ESS("ESS: SMT does not accept the payload value\n",0,0) ;
-		return(FALSE) ;
+		return FALSE;
 	}
 	if (smt_set_obj(smc,SMT_P3210,overhead,S_SET)) {
 		DB_ESS("ESS: SMT does not accept the overhead value\n",0,0) ;
-		return(FALSE) ;
+		return FALSE;
 	} */
 
 	/* premliminary */
 	if (payload > MAX_PAYLOAD || overhead > 5000) {
 		DB_ESS("ESS: payload / overhead not accepted\n",0,0) ;
-		return(FALSE) ;
+		return FALSE;
 	}
 
 	/*
@@ -468,7 +468,7 @@
 
 	ess_config_fifo(smc) ;
 	set_formac_tsync(smc,smc->ess.sync_bw) ;
-	return(TRUE) ;
+	return TRUE;
 }
 
 static void ess_send_response(struct s_smc *smc, struct smt_header *sm,
diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c
index 9d8d1ac4..ca4e7bb 100644
--- a/drivers/net/skfp/fplustm.c
+++ b/drivers/net/skfp/fplustm.c
@@ -112,8 +112,8 @@
 	u_long	tneg ;
 
 	tneg = (u_long)((long)inpw(FM_A(FM_TNEG))<<5) ;
-	return((u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) |
-		0xffe00000L)) ;
+	return (u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) |
+		0xffe00000L) ;
 }
 
 void mac_update_counter(struct s_smc *smc)
@@ -163,7 +163,7 @@
 			/* is used */
 	p = (u_long)inpw(FM_A(FM_MDRU))<<16 ;
 	p += (u_long)inpw(FM_A(FM_MDRL)) ;
-	return(p) ;
+	return p;
 }
 #endif
 
@@ -887,7 +887,7 @@
 	/* make sure all PCI settings are correct */
 	mac_do_pci_fix(smc) ;
 
-	return(init_mac(smc,1)) ;
+	return init_mac(smc, 1);
 	/* enable_formac(smc) ; */
 }
 
@@ -989,7 +989,7 @@
 	}
 	smc->hw.hw_state = STARTED ;
 
-	return(0) ;
+	return 0;
 }
 
 
@@ -1049,7 +1049,7 @@
 
 int sm_mac_get_tx_state(struct s_smc *smc)
 {
-	return((inpw(FM_A(FM_STMCHN))>>4)&7) ;
+	return (inpw(FM_A(FM_STMCHN))>>4) & 7;
 }
 
 /*
@@ -1084,9 +1084,9 @@
 		}
 		if (memcmp((char *)&tb->a,(char *)own,6))
 			continue ;
-		return(tb) ;
+		return tb;
 	}
-	return(slot) ;			/* return first free or NULL */
+	return slot;			/* return first free or NULL */
 }
 
 /*
@@ -1152,12 +1152,12 @@
 	 */
 	if (can & 0x80) {
 		if (smc->hw.fp.smt_slots_used >= SMT_MAX_MULTI) {
-			return(1) ;
+			return 1;
 		}
 	}
 	else {
 		if (smc->hw.fp.os_slots_used >= FPMAX_MULTICAST-SMT_MAX_MULTI) {
-			return(1) ;
+			return 1;
 		}
 	}
 
@@ -1165,7 +1165,7 @@
 	 * find empty slot
 	 */
 	if (!(tb = mac_get_mc_table(smc,addr,&own,0,can & ~0x80)))
-		return(1) ;
+		return 1;
 	tb->n++ ;
 	tb->a = own ;
 	tb->perm = (can & 0x80) ? 1 : 0 ;
@@ -1175,7 +1175,7 @@
 	else
 		smc->hw.fp.os_slots_used++ ;
 
-	return(0) ;
+	return 0;
 }
 
 /*
diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c
index d322f1b..af5a755 100644
--- a/drivers/net/skfp/hwmtm.c
+++ b/drivers/net/skfp/hwmtm.c
@@ -232,16 +232,16 @@
 #ifdef	COMMON_MB_POOL
 	call_count++ ;
 	if (call_count == 1) {
-		return(EXT_VIRT_MEM) ;
+		return EXT_VIRT_MEM;
 	}
 	else {
-		return(EXT_VIRT_MEM_2) ;
+		return EXT_VIRT_MEM_2;
 	}
 #else
-	return (EXT_VIRT_MEM) ;
+	return EXT_VIRT_MEM;
 #endif
 #else
-	return (0) ;
+	return 0;
 #endif
 }
 
@@ -271,7 +271,7 @@
 	if (!(smc->os.hwm.descr_p = (union s_fp_descr volatile *)
 		mac_drv_get_desc_mem(smc,(u_int)
 		(RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)))) {
-		return(1) ;	/* no space the hwm modul can't work */
+		return 1;	/* no space the hwm modul can't work */
 	}
 
 	/*
@@ -283,18 +283,18 @@
 #ifndef	COMMON_MB_POOL
 	if (!(smc->os.hwm.mbuf_pool.mb_start = (SMbuf *) mac_drv_get_space(smc,
 		MAX_MBUF*sizeof(SMbuf)))) {
-		return(1) ;	/* no space the hwm modul can't work */
+		return 1;	/* no space the hwm modul can't work */
 	}
 #else
 	if (!mb_start) {
 		if (!(mb_start = (SMbuf *) mac_drv_get_space(smc,
 			MAX_MBUF*sizeof(SMbuf)))) {
-			return(1) ;	/* no space the hwm modul can't work */
+			return 1;	/* no space the hwm modul can't work */
 		}
 	}
 #endif
 #endif
-	return (0) ;
+	return 0;
 }
 
 /*
@@ -349,7 +349,7 @@
 		DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ;
 		d1++;
 	}
-	return(phys) ;
+	return phys;
 }
 
 static void init_txd_ring(struct s_smc *smc)
@@ -502,7 +502,7 @@
 		mb->sm_use_count = 1 ;
 	}
 	DB_GEN("get SMbuf: mb = %x",(void *)mb,0,3) ;
-	return (mb) ;	/* May be NULL */
+	return mb;	/* May be NULL */
 }
 
 void smt_free_mbuf(struct s_smc *smc, SMbuf *mb)
@@ -621,7 +621,7 @@
 		t = t->txd_next ;
 		tx_used-- ;
 	}
-	return(phys) ;
+	return phys;
 }
 
 /*
@@ -673,7 +673,7 @@
 		r = r->rxd_next ;
 		rx_used-- ;
 	}
-	return(phys) ;
+	return phys;
 }
 
 
@@ -1595,7 +1595,7 @@
 	}
 	DB_TX("frame_status = %x",frame_status,0,3) ;
 	NDD_TRACE("THiE",frame_status,smc->os.hwm.tx_p->tx_free,0) ;
-	return(frame_status) ;
+	return frame_status;
 }
 
 /*
@@ -1764,7 +1764,7 @@
 		smc->os.hwm.llc_rx_pipe = mb->sm_next ;
 	}
 	DB_GEN("get_llc_rx: mb = 0x%x",(void *)mb,0,4) ;
-	return(mb) ;
+	return mb;
 }
 
 /*
@@ -1797,7 +1797,7 @@
 		smc->os.hwm.txd_tx_pipe = mb->sm_next ;
 	}
 	DB_GEN("get_txd_mb: mb = 0x%x",(void *)mb,0,4) ;
-	return(mb) ;
+	return mb;
 }
 
 /*
diff --git a/drivers/net/skfp/hwt.c b/drivers/net/skfp/hwt.c
index 0531514..e6baa53 100644
--- a/drivers/net/skfp/hwt.c
+++ b/drivers/net/skfp/hwt.c
@@ -179,7 +179,7 @@
 		else
 			smc->hw.t_stop = smc->hw.t_start - tr ;
 	}
-	return (smc->hw.t_stop) ;
+	return smc->hw.t_stop;
 }
 
 #ifdef	PCI
@@ -208,7 +208,7 @@
 	outpw(ADDR(B2_TI_CRTL), TIM_START) ;
 	outpd(ADDR(B2_TI_INI),interval) ;
 
-	return(time) ;
+	return time;
 }
 
 /************************
diff --git a/drivers/net/skfp/pcmplc.c b/drivers/net/skfp/pcmplc.c
index ba45bc7..112d35b 100644
--- a/drivers/net/skfp/pcmplc.c
+++ b/drivers/net/skfp/pcmplc.c
@@ -504,7 +504,7 @@
 
 #ifdef	CONCENTRATOR
 	if (!plc_is_installed(smc,phy))
-		return(PC_QLS) ;
+		return PC_QLS;
 #endif
 
 	state = inpw(PLC(phy,PL_STATUS_A)) & PL_LINE_ST ;
@@ -528,7 +528,7 @@
 	default :
 		state = PC_LS_NONE ;
 	}
-	return(state) ;
+	return state;
 }
 
 static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len)
@@ -547,7 +547,7 @@
 #if	0
 		printf("PL_PCM_SIGNAL is set\n") ;
 #endif
-		return(1) ;
+		return 1;
 	}
 	/* write bit[n] & length = 1 to regs */
 	outpw(PLC(np,PL_VECTOR_LEN),len-1) ;	/* len=nr-1 */
@@ -562,7 +562,7 @@
 		printf("SIGNALING bit %d .. %d\n",phy->bitn,phy->bitn+len-1) ;
 #endif
 #endif
-	return(0) ;
+	return 0;
 }
 
 /*
@@ -1590,12 +1590,12 @@
 {
 	int	twist = 0 ;
 	if (smc->s.sas != SMT_DAS)
-		return(0) ;
+		return 0;
 	if (smc->y[PA].twisted && (smc->y[PA].mib->fddiPORTPCMState == PC8_ACTIVE))
 		twist |= 1 ;
 	if (smc->y[PB].twisted && (smc->y[PB].mib->fddiPORTPCMState == PC8_ACTIVE))
 		twist |= 2 ;
-	return(twist) ;
+	return twist;
 }
 
 /*
@@ -1636,9 +1636,9 @@
 	for (n = 0 ; n < NUMPHYS ; n++) {
 		if (smc->y[n].mib->fddiPORTPCMState == PC8_ACTIVE &&
 		    smc->y[n].mib->fddiPORTNeighborType == TM)
-			return(0) ;
+			return 0;
 	}
-	return(1) ;
+	return 1;
 }
 
 /*
@@ -1915,7 +1915,7 @@
 		case PL_PC9 :	pcs = PC_MAINT ;	break ;
 		default :	pcs = PC_DISABLE ; 	break ;
 	}
-	return(pcs) ;
+	return pcs;
 }
 
 char *get_linestate(struct s_smc *smc, int np)
@@ -1937,7 +1937,7 @@
 		default:	ls = "unknown" ; break ;
 #endif
 	}
-	return(ls) ;
+	return ls;
 }
 
 char *get_pcmstate(struct s_smc *smc, int np)
@@ -1959,7 +1959,7 @@
 		case PL_PC9 :	pcs = "MAINT" ;		break ;
 		default :	pcs = "UNKNOWN" ; 	break ;
 	}
-	return(pcs) ;
+	return pcs;
 }
 
 void list_phy(struct s_smc *smc)
diff --git a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c
index a320fdb..9ac4665 100644
--- a/drivers/net/skfp/pmf.c
+++ b/drivers/net/skfp/pmf.c
@@ -328,7 +328,7 @@
 	 * build SMT header
 	 */
 	if (!(mb = smt_get_mbuf(smc)))
-		return(mb) ;
+		return mb;
 
 	smt = smtod(mb, struct smt_header *) ;
 	smt->smt_dest = req->smt_source ;	/* DA == source of request */
@@ -493,7 +493,7 @@
 		smt_add_para(smc,&set_pcon,(u_short) SMT_P1035,0,0) ;
 		smt_add_para(smc,&set_pcon,(u_short) SMT_P1036,0,0) ;
 	}
-	return(mb) ;
+	return mb;
 }
 
 static int smt_authorize(struct s_smc *smc, struct smt_header *sm)
@@ -511,7 +511,7 @@
 	if (i != 8) {
 		if (memcmp((char *) &sm->smt_sid,
 			(char *) &smc->mib.fddiPRPMFStation,8))
-			return(1) ;
+			return 1;
 	}
 	/*
 	 * check authoriziation parameter if passwd not zero
@@ -522,13 +522,13 @@
 	if (i != 8) {
 		pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P_AUTHOR) ;
 		if (!pa)
-			return(1) ;
+			return 1;
 		if (pa->p_len != 8)
-			return(1) ;
+			return 1;
 		if (memcmp((char *)(pa+1),(char *)smc->mib.fddiPRPMFPasswd,8))
-			return(1) ;
+			return 1;
 	}
-	return(0) ;
+	return 0;
 }
 
 static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm)
@@ -542,9 +542,9 @@
 		if ((smc->mib.fddiSMTSetCount.count != sc->count) ||
 			memcmp((char *) smc->mib.fddiSMTSetCount.timestamp,
 			(char *)sc->timestamp,8))
-			return(1) ;
+			return 1;
 	}
-	return(0) ;
+	return 0;
 }
 
 void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
@@ -1109,7 +1109,7 @@
 		break ;
 	case 0x2000 :
 		if (mac < 0 || mac >= NUMMACS) {
-			return(SMT_RDF_NOPARAM) ;
+			return SMT_RDF_NOPARAM;
 		}
 		mib_m = &smc->mib.m[mac] ;
 		mib_addr = (char *) mib_m ;
@@ -1118,7 +1118,7 @@
 		break ;
 	case 0x3000 :
 		if (path < 0 || path >= NUMPATHS) {
-			return(SMT_RDF_NOPARAM) ;
+			return SMT_RDF_NOPARAM;
 		}
 		mib_a = &smc->mib.a[path] ;
 		mib_addr = (char *) mib_a ;
@@ -1127,7 +1127,7 @@
 		break ;
 	case 0x4000 :
 		if (port < 0 || port >= smt_mib_phys(smc)) {
-			return(SMT_RDF_NOPARAM) ;
+			return SMT_RDF_NOPARAM;
 		}
 		mib_p = &smc->mib.p[port_to_mib(smc,port)] ;
 		mib_addr = (char *) mib_p ;
@@ -1151,22 +1151,20 @@
 	case SMT_P10F9 :
 #endif
 	case SMT_P20F1 :
-		if (!local) {
-			return(SMT_RDF_NOPARAM) ;
-		}
+		if (!local)
+			return SMT_RDF_NOPARAM;
 		break ;
 	}
 	pt = smt_get_ptab(pa->p_type) ;
-	if (!pt) {
-		return( (pa->p_type & 0xff00) ? SMT_RDF_NOPARAM :
-						SMT_RDF_ILLEGAL ) ;
-	}
+	if (!pt)
+		return (pa->p_type & 0xff00) ? SMT_RDF_NOPARAM :
+					       SMT_RDF_ILLEGAL;
 	switch (pt->p_access) {
 	case AC_GR :
 	case AC_S :
 		break ;
 	default :
-		return(SMT_RDF_ILLEGAL) ;
+		return SMT_RDF_ILLEGAL;
 	}
 	to = mib_addr + pt->p_offset ;
 	swap = pt->p_swap ;		/* pointer to swap string */
@@ -1292,7 +1290,7 @@
 			break ;
 		default :
 			SMT_PANIC(smc,SMT_E0120, SMT_E0120_MSG) ;
-			return(SMT_RDF_ILLEGAL) ;
+			return SMT_RDF_ILLEGAL;
 		}
 	}
 	/*
@@ -1501,15 +1499,15 @@
 	default :
 		break ;
 	}
-	return(0) ;
+	return 0;
 
 val_error:
 	/* parameter value in frame is out of range */
-	return(SMT_RDF_RANGE) ;
+	return SMT_RDF_RANGE;
 
 len_error:
 	/* parameter value in frame is too short */
-	return(SMT_RDF_LENGTH) ;
+	return SMT_RDF_LENGTH;
 
 #if	0
 no_author_error:
@@ -1518,7 +1516,7 @@
 	 *  because SBA denied is not a valid return code in the
 	 * PMF protocol.
 	 */
-	return(SMT_RDF_AUTHOR) ;
+	return SMT_RDF_AUTHOR;
 #endif
 }
 
@@ -1527,7 +1525,7 @@
 	const struct s_p_tab	*pt ;
 	for (pt = p_tab ; pt->p_num && pt->p_num != para ; pt++)
 		;
-	return(pt->p_num ? pt : NULL) ;
+	return pt->p_num ? pt : NULL;
 }
 
 static int smt_mib_phys(struct s_smc *smc)
@@ -1535,11 +1533,11 @@
 #ifdef	CONCENTRATOR
 	SK_UNUSED(smc) ;
 
-	return(NUMPHYS) ;
+	return NUMPHYS;
 #else
 	if (smc->s.sas == SMT_SAS)
-		return(1) ;
-	return(NUMPHYS) ;
+		return 1;
+	return NUMPHYS;
 #endif
 }
 
@@ -1548,11 +1546,11 @@
 #ifdef	CONCENTRATOR
 	SK_UNUSED(smc) ;
 
-	return(p) ;
+	return p;
 #else
 	if (smc->s.sas == SMT_SAS)
-		return(PS) ;
-	return(p) ;
+		return PS;
+	return p;
 #endif
 }
 
diff --git a/drivers/net/skfp/queue.c b/drivers/net/skfp/queue.c
index 09adb3d..c1a0df4 100644
--- a/drivers/net/skfp/queue.c
+++ b/drivers/net/skfp/queue.c
@@ -128,7 +128,7 @@
 {
 	queue_event(smc,EVENT_ECM,on ? EC_CONNECT : EC_DISCONNECT) ;
 	ev_dispatcher(smc) ;
-	return(smc->mib.fddiSMTCF_State) ;
+	return smc->mib.fddiSMTCF_State;
 }
 
 /*
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index 31b2dab..ba2e833 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -209,7 +209,7 @@
 	void __iomem *mem;
 	int err;
 
-	pr_debug(KERN_INFO "entering skfp_init_one\n");
+	pr_debug("entering skfp_init_one\n");
 
 	if (num_boards == 0) 
 		printk("%s\n", boot_msg);
@@ -385,7 +385,7 @@
 	skfddi_priv *bp = &smc->os;
 	int err = -EIO;
 
-	pr_debug(KERN_INFO "entering skfp_driver_init\n");
+	pr_debug("entering skfp_driver_init\n");
 
 	// set the io address in private structures
 	bp->base_addr = dev->base_addr;
@@ -405,7 +405,7 @@
 
 	// Determine the required size of the 'shared' memory area.
 	bp->SharedMemSize = mac_drv_check_space();
-	pr_debug(KERN_INFO "Memory for HWM: %ld\n", bp->SharedMemSize);
+	pr_debug("Memory for HWM: %ld\n", bp->SharedMemSize);
 	if (bp->SharedMemSize > 0) {
 		bp->SharedMemSize += 16;	// for descriptor alignment
 
@@ -429,18 +429,18 @@
 
 	card_stop(smc);		// Reset adapter.
 
-	pr_debug(KERN_INFO "mac_drv_init()..\n");
+	pr_debug("mac_drv_init()..\n");
 	if (mac_drv_init(smc) != 0) {
-		pr_debug(KERN_INFO "mac_drv_init() failed.\n");
+		pr_debug("mac_drv_init() failed\n");
 		goto fail;
 	}
 	read_address(smc, NULL);
-	pr_debug(KERN_INFO "HW-Addr: %pMF\n", smc->hw.fddi_canon_addr.a);
+	pr_debug("HW-Addr: %pMF\n", smc->hw.fddi_canon_addr.a);
 	memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6);
 
 	smt_reset_defaults(smc, 0);
 
-	return (0);
+	return 0;
 
 fail:
 	if (bp->SharedMemAddr) {
@@ -485,7 +485,7 @@
 	struct s_smc *smc = netdev_priv(dev);
 	int err;
 
-	pr_debug(KERN_INFO "entering skfp_open\n");
+	pr_debug("entering skfp_open\n");
 	/* Register IRQ - support shared interrupts by passing device ptr */
 	err = request_irq(dev->irq, skfp_interrupt, IRQF_SHARED,
 			  dev->name, dev);
@@ -516,7 +516,7 @@
 	mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
 
 	netif_start_queue(dev);
-	return (0);
+	return 0;
 }				// skfp_open
 
 
@@ -565,7 +565,7 @@
 	skb_queue_purge(&bp->SendSkbQueue);
 	bp->QueueSkb = MAX_TX_QUEUE_LEN;
 
-	return (0);
+	return 0;
 }				// skfp_close
 
 
@@ -794,7 +794,7 @@
 	bp->stats.port_lem_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
 
 #endif
-	return ((struct net_device_stats *) &bp->os.MacStat);
+	return (struct net_device_stats *)&bp->os.MacStat;
 }				// ctl_get_stat
 
 
@@ -856,12 +856,12 @@
 	/* Enable promiscuous mode, if necessary */
 	if (dev->flags & IFF_PROMISC) {
 		mac_drv_rx_mode(smc, RX_ENABLE_PROMISC);
-		pr_debug(KERN_INFO "PROMISCUOUS MODE ENABLED\n");
+		pr_debug("PROMISCUOUS MODE ENABLED\n");
 	}
 	/* Else, update multicast address table */
 	else {
 		mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
-		pr_debug(KERN_INFO "PROMISCUOUS MODE DISABLED\n");
+		pr_debug("PROMISCUOUS MODE DISABLED\n");
 
 		// Reset all MC addresses
 		mac_clear_multicast(smc);
@@ -869,7 +869,7 @@
 
 		if (dev->flags & IFF_ALLMULTI) {
 			mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
-			pr_debug(KERN_INFO "ENABLE ALL MC ADDRESSES\n");
+			pr_debug("ENABLE ALL MC ADDRESSES\n");
 		} else if (!netdev_mc_empty(dev)) {
 			if (netdev_mc_count(dev) <= FPMAX_MULTICAST) {
 				/* use exact filtering */
@@ -880,18 +880,18 @@
 						(struct fddi_addr *)ha->addr,
 						1);
 
-					pr_debug(KERN_INFO "ENABLE MC ADDRESS: %pMF\n",
-						ha->addr);
+					pr_debug("ENABLE MC ADDRESS: %pMF\n",
+						 ha->addr);
 				}
 
 			} else {	// more MC addresses than HW supports
 
 				mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
-				pr_debug(KERN_INFO "ENABLE ALL MC ADDRESSES\n");
+				pr_debug("ENABLE ALL MC ADDRESSES\n");
 			}
 		} else {	// no MC addresses
 
-			pr_debug(KERN_INFO "DISABLE ALL MC ADDRESSES\n");
+			pr_debug("DISABLE ALL MC ADDRESSES\n");
 		}
 
 		/* Update adapter filters */
@@ -932,7 +932,7 @@
 	ResetAdapter(smc);
 	spin_unlock_irqrestore(&bp->DriverLock, Flags);
 
-	return (0);		/* always return zero */
+	return 0;		/* always return zero */
 }				// skfp_ctl_set_mac_address
 
 
@@ -1045,7 +1045,7 @@
 	struct s_smc *smc = netdev_priv(dev);
 	skfddi_priv *bp = &smc->os;
 
-	pr_debug(KERN_INFO "skfp_send_pkt\n");
+	pr_debug("skfp_send_pkt\n");
 
 	/*
 	 * Verify that incoming transmit request is OK
@@ -1114,13 +1114,13 @@
 
 	int frame_status;	// HWM tx frame status.
 
-	pr_debug(KERN_INFO "send queued packets\n");
+	pr_debug("send queued packets\n");
 	for (;;) {
 		// send first buffer from queue
 		skb = skb_dequeue(&bp->SendSkbQueue);
 
 		if (!skb) {
-			pr_debug(KERN_INFO "queue empty\n");
+			pr_debug("queue empty\n");
 			return;
 		}		// queue empty !
 
@@ -1232,7 +1232,7 @@
 static void ResetAdapter(struct s_smc *smc)
 {
 
-	pr_debug(KERN_INFO "[fddi: ResetAdapter]\n");
+	pr_debug("[fddi: ResetAdapter]\n");
 
 	// Stop the adapter.
 
@@ -1278,7 +1278,7 @@
 {
 	skfddi_priv *bp = &smc->os;
 
-	pr_debug(KERN_INFO "[llc_restart_tx]\n");
+	pr_debug("[llc_restart_tx]\n");
 
 	// Try to send queued packets
 	spin_unlock(&bp->DriverLock);
@@ -1308,21 +1308,21 @@
 {
 	void *virt;
 
-	pr_debug(KERN_INFO "mac_drv_get_space (%d bytes), ", size);
+	pr_debug("mac_drv_get_space (%d bytes), ", size);
 	virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap);
 
 	if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) {
 		printk("Unexpected SMT memory size requested: %d\n", size);
-		return (NULL);
+		return NULL;
 	}
 	smc->os.SharedMemHeap += size;	// Move heap pointer.
 
-	pr_debug(KERN_INFO "mac_drv_get_space end\n");
-	pr_debug(KERN_INFO "virt addr: %lx\n", (ulong) virt);
-	pr_debug(KERN_INFO "bus  addr: %lx\n", (ulong)
+	pr_debug("mac_drv_get_space end\n");
+	pr_debug("virt addr: %lx\n", (ulong) virt);
+	pr_debug("bus  addr: %lx\n", (ulong)
 	       (smc->os.SharedMemDMA +
 		((char *) virt - (char *)smc->os.SharedMemAddr)));
-	return (virt);
+	return virt;
 }				// mac_drv_get_space
 
 
@@ -1349,7 +1349,7 @@
 
 	char *virt;
 
-	pr_debug(KERN_INFO "mac_drv_get_desc_mem\n");
+	pr_debug("mac_drv_get_desc_mem\n");
 
 	// Descriptor memory must be aligned on 16-byte boundary.
 
@@ -1363,9 +1363,9 @@
 
 	if (!mac_drv_get_space(smc, size)) {
 		printk("fddi: Unable to align descriptor memory.\n");
-		return (NULL);
+		return NULL;
 	}
-	return (virt + size);
+	return virt + size;
 }				// mac_drv_get_desc_mem
 
 
@@ -1384,8 +1384,8 @@
  ************************/
 unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt)
 {
-	return (smc->os.SharedMemDMA +
-		((char *) virt - (char *)smc->os.SharedMemAddr));
+	return smc->os.SharedMemDMA +
+		((char *) virt - (char *)smc->os.SharedMemAddr);
 }				// mac_drv_virt2phys
 
 
@@ -1419,8 +1419,8 @@
  ************************/
 u_long dma_master(struct s_smc * smc, void *virt, int len, int flag)
 {
-	return (smc->os.SharedMemDMA +
-		((char *) virt - (char *)smc->os.SharedMemAddr));
+	return smc->os.SharedMemDMA +
+		((char *) virt - (char *)smc->os.SharedMemAddr);
 }				// dma_master
 
 
@@ -1493,7 +1493,7 @@
 {
 	struct sk_buff *skb;
 
-	pr_debug(KERN_INFO "entering mac_drv_tx_complete\n");
+	pr_debug("entering mac_drv_tx_complete\n");
 	// Check if this TxD points to a skb
 
 	if (!(skb = txd->txd_os.skb)) {
@@ -1513,7 +1513,7 @@
 	// free the skb
 	dev_kfree_skb_irq(skb);
 
-	pr_debug(KERN_INFO "leaving mac_drv_tx_complete\n");
+	pr_debug("leaving mac_drv_tx_complete\n");
 }				// mac_drv_tx_complete
 
 
@@ -1580,7 +1580,7 @@
 	unsigned short ri;
 	u_int RifLength;
 
-	pr_debug(KERN_INFO "entering mac_drv_rx_complete (len=%d)\n", len);
+	pr_debug("entering mac_drv_rx_complete (len=%d)\n", len);
 	if (frag_count != 1) {	// This is not allowed to happen.
 
 		printk("fddi: Multi-fragment receive!\n");
@@ -1589,7 +1589,7 @@
 	}
 	skb = rxd->rxd_os.skb;
 	if (!skb) {
-		pr_debug(KERN_INFO "No skb in rxd\n");
+		pr_debug("No skb in rxd\n");
 		smc->os.MacStat.gen.rx_errors++;
 		goto RequeueRxd;
 	}
@@ -1619,7 +1619,7 @@
 	else {
 		int n;
 // goos: RIF removal has still to be tested
-		pr_debug(KERN_INFO "RIF found\n");
+		pr_debug("RIF found\n");
 		// Get RIF length from Routing Control (RC) field.
 		cp = virt + FDDI_MAC_HDR_LEN;	// Point behind MAC header.
 
@@ -1664,7 +1664,7 @@
 	return;
 
       RequeueRxd:
-	pr_debug(KERN_INFO "Rx: re-queue RXD.\n");
+	pr_debug("Rx: re-queue RXD.\n");
 	mac_drv_requeue_rxd(smc, rxd, frag_count);
 	smc->os.MacStat.gen.rx_errors++;	// Count receive packets
 						// not indicated.
@@ -1775,7 +1775,7 @@
 	struct sk_buff *skb;
 	volatile struct s_smt_fp_rxd *rxd;
 
-	pr_debug(KERN_INFO "entering mac_drv_fill_rxd\n");
+	pr_debug("entering mac_drv_fill_rxd\n");
 
 	// Walk through the list of free receive buffers, passing receive
 	// buffers to the HWM as long as RXDs are available.
@@ -1783,7 +1783,7 @@
 	MaxFrameSize = smc->os.MaxFrameSize;
 	// Check if there is any RXD left.
 	while (HWM_GET_RX_FREE(smc) > 0) {
-		pr_debug(KERN_INFO ".\n");
+		pr_debug(".\n");
 
 		rxd = HWM_GET_CURR_RXD(smc);
 		skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC);
@@ -1814,7 +1814,7 @@
 		hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,
 			    FIRST_FRAG | LAST_FRAG);
 	}
-	pr_debug(KERN_INFO "leaving mac_drv_fill_rxd\n");
+	pr_debug("leaving mac_drv_fill_rxd\n");
 }				// mac_drv_fill_rxd
 
 
@@ -1904,12 +1904,12 @@
 		pr_debug("fddi: Discard invalid local SMT frame\n");
 		pr_debug("  len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n",
 		       len, la_len, (unsigned long) look_ahead);
-		return (0);
+		return 0;
 	}
 	skb = alloc_skb(len + 3, GFP_ATOMIC);
 	if (!skb) {
 		pr_debug("fddi: Local SMT: skb memory exhausted.\n");
-		return (0);
+		return 0;
 	}
 	skb_reserve(skb, 3);
 	skb_put(skb, len);
@@ -1919,7 +1919,7 @@
 	skb->protocol = fddi_type_trans(skb, smc->os.dev);
 	netif_rx(skb);
 
-	return (0);
+	return 0;
 }				// mac_drv_rx_init
 
 
@@ -2034,17 +2034,17 @@
 {
 //      BOOLEAN RingIsUp ;
 
-	pr_debug(KERN_INFO "smt_stat_counter\n");
+	pr_debug("smt_stat_counter\n");
 	switch (stat) {
 	case 0:
-		pr_debug(KERN_INFO "Ring operational change.\n");
+		pr_debug("Ring operational change.\n");
 		break;
 	case 1:
-		pr_debug(KERN_INFO "Receive fifo overflow.\n");
+		pr_debug("Receive fifo overflow.\n");
 		smc->os.MacStat.gen.rx_errors++;
 		break;
 	default:
-		pr_debug(KERN_INFO "Unknown status (%d).\n", stat);
+		pr_debug("Unknown status (%d).\n", stat);
 		break;
 	}
 }				// smt_stat_counter
@@ -2100,10 +2100,10 @@
 		s = "SC11_C_WRAP_S";
 		break;
 	default:
-		pr_debug(KERN_INFO "cfm_state_change: unknown %d\n", c_state);
+		pr_debug("cfm_state_change: unknown %d\n", c_state);
 		return;
 	}
-	pr_debug(KERN_INFO "cfm_state_change: %s\n", s);
+	pr_debug("cfm_state_change: %s\n", s);
 #endif				// DRIVERDEBUG
 }				// cfm_state_change
 
@@ -2158,7 +2158,7 @@
 		s = "unknown";
 		break;
 	}
-	pr_debug(KERN_INFO "ecm_state_change: %s\n", s);
+	pr_debug("ecm_state_change: %s\n", s);
 #endif				//DRIVERDEBUG
 }				// ecm_state_change
 
@@ -2213,7 +2213,7 @@
 		s = "unknown";
 		break;
 	}
-	pr_debug(KERN_INFO "[rmt_state_change: %s]\n", s);
+	pr_debug("[rmt_state_change: %s]\n", s);
 #endif				// DRIVERDEBUG
 }				// rmt_state_change
 
@@ -2233,7 +2233,7 @@
  ************************/
 void drv_reset_indication(struct s_smc *smc)
 {
-	pr_debug(KERN_INFO "entering drv_reset_indication\n");
+	pr_debug("entering drv_reset_indication\n");
 
 	smc->os.ResetRequested = TRUE;	// Set flag.
 
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c
index 6f35bb7..2d9941c 100644
--- a/drivers/net/skfp/smt.c
+++ b/drivers/net/skfp/smt.c
@@ -127,22 +127,22 @@
 
 static inline int is_broadcast(const struct fddi_addr *addr)
 {
-	return(*(u_short *)(&addr->a[0]) == 0xffff &&
+	return *(u_short *)(&addr->a[0]) == 0xffff &&
 	       *(u_short *)(&addr->a[2]) == 0xffff &&
-	       *(u_short *)(&addr->a[4]) == 0xffff ) ;
+	       *(u_short *)(&addr->a[4]) == 0xffff;
 }
 
 static inline int is_individual(const struct fddi_addr *addr)
 {
-	return(!(addr->a[0] & GROUP_ADDR)) ;
+	return !(addr->a[0] & GROUP_ADDR);
 }
 
 static inline int is_equal(const struct fddi_addr *addr1, 
 			   const struct fddi_addr *addr2)
 {
-	return(*(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&
+	return *(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&
 	       *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) &&
-	       *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]) ) ;
+	       *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]);
 }
 
 /*
@@ -457,8 +457,8 @@
 	else
 		upper <<= 16L ;
 	if (!lower)
-		return(0) ;
-	return((int)(upper/lower)) ;
+		return 0;
+	return (int)(upper/lower) ;
 }
 
 #ifndef	SLIM_SMT
@@ -1111,11 +1111,11 @@
 
 #if	0
 	if (!smc->r.sm_ma_avail) {
-		return(0) ;
+		return 0;
 	}
 #endif
 	if (!(mb = smt_get_mbuf(smc)))
-		return(mb) ;
+		return mb;
 
 	mb->sm_len = length ;
 	smt = smtod(mb, struct smt_header *) ;
@@ -1136,7 +1136,7 @@
 	smt->smt_tid = smt_get_tid(smc) ;	/* set transaction ID */
 	smt->smt_pad = 0 ;
 	smt->smt_len = length - sizeof(struct smt_header) ;
-	return(mb) ;
+	return mb;
 }
 
 static void smt_add_frame_len(SMbuf *mb, int len)
@@ -1375,7 +1375,7 @@
 	pd_mac = (struct smt_mac_rec *) phy ;
 	pd_mac->mac_addr = smc->mib.m[MAC0].fddiMACSMTAddress ;
 	pd_mac->mac_resource_idx = mac_con_resource_index(smc,1) ;
-	return(len) ;
+	return len;
 }
 
 /*
@@ -1563,7 +1563,7 @@
 	u_long	tid ;
 	while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0)
 		;
-	return(tid & 0x3fffffffL) ;
+	return tid & 0x3fffffffL;
 }
 
 
@@ -1654,11 +1654,11 @@
 	while (*p) {
 		if (!sm_to_para(smc,sm,(int) *p)) {
 			DB_SMT("SMT: smt_check_para - missing para %x\n",*p,0);
-			return(-1) ;
+			return -1;
 		}
 		p++ ;
 	}
-	return(0) ;
+	return 0;
 }
 
 void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para)
@@ -1687,7 +1687,7 @@
 			return NULL;
 		}
 		if (found)
-			return(found) ;
+			return found;
 	}
 	return NULL;
 }
@@ -1732,7 +1732,7 @@
 		string[i * 3 + 2] = ':';
 	}
 	string[5 * 3 + 2] = 0;
-	return(string);
+	return string;
 }
 #endif
 
@@ -1742,9 +1742,9 @@
 	if (argc >= 2 && !strcmp(argv[0],"opt_bypass") &&
 	    !strcmp(argv[1],"yes")) {
 		smc->mib.fddiSMTBypassPresent = 1 ;
-		return(0) ;
+		return 0;
 	}
-	return(amdfddi_config(0,argc,argv)) ;
+	return amdfddi_config(0, argc, argv);
 }
 #endif
 
@@ -1756,9 +1756,9 @@
 	SK_UNUSED(mac) ;
 #ifdef	CONCENTRATOR
 	SK_UNUSED(smc) ;
-	return(NUMPHYS+1) ;
+	return NUMPHYS + 1;
 #else
-	return((smc->s.sas == SMT_SAS) ? 2 : 3) ;
+	return (smc->s.sas == SMT_SAS) ? 2 : 3;
 #endif
 }
 
@@ -1768,7 +1768,7 @@
 static int phy_index(struct s_smc *smc, int phy)
 {
 	SK_UNUSED(smc) ;
-	return(phy+1);
+	return phy + 1;
 }
 
 /*
@@ -1779,19 +1779,19 @@
 #ifdef	CONCENTRATOR
 	SK_UNUSED(smc) ;
 	SK_UNUSED(mac) ;
-	return(entity_to_index(smc,cem_get_downstream(smc,ENTITY_MAC))) ;
+	return entity_to_index(smc, cem_get_downstream(smc, ENTITY_MAC));
 #else
 	SK_UNUSED(mac) ;
 	switch (smc->mib.fddiSMTCF_State) {
 	case SC9_C_WRAP_A :
 	case SC5_THRU_B :
 	case SC11_C_WRAP_S :
-		return(1) ;
+		return 1;
 	case SC10_C_WRAP_B :
 	case SC4_THRU_A :
-		return(2) ;
+		return 2;
 	}
-	return(smc->s.sas == SMT_SAS ? 2 : 3) ;
+	return smc->s.sas == SMT_SAS ? 2 : 3;
 #endif
 }
 
@@ -1801,21 +1801,21 @@
 static int phy_con_resource_index(struct s_smc *smc, int phy)
 {
 #ifdef	CONCENTRATOR
-	return(entity_to_index(smc,cem_get_downstream(smc,ENTITY_PHY(phy)))) ;
+	return entity_to_index(smc, cem_get_downstream(smc, ENTITY_PHY(phy))) ;
 #else
 	switch (smc->mib.fddiSMTCF_State) {
 	case SC9_C_WRAP_A :
-		return(phy == PA ? 3 : 2) ;
+		return phy == PA ? 3 : 2;
 	case SC10_C_WRAP_B :
-		return(phy == PA ? 1 : 3) ;
+		return phy == PA ? 1 : 3;
 	case SC4_THRU_A :
-		return(phy == PA ? 3 : 1) ;
+		return phy == PA ? 3 : 1;
 	case SC5_THRU_B :
-		return(phy == PA ? 2 : 3) ;
+		return phy == PA ? 2 : 3;
 	case SC11_C_WRAP_S :
-		return(2) ;
+		return 2;
 	}
-	return(phy) ;
+	return phy;
 #endif
 }
 
@@ -1823,16 +1823,16 @@
 static int entity_to_index(struct s_smc *smc, int e)
 {
 	if (e == ENTITY_MAC)
-		return(mac_index(smc,1)) ;
+		return mac_index(smc, 1);
 	else
-		return(phy_index(smc,e - ENTITY_PHY(0))) ;
+		return phy_index(smc, e - ENTITY_PHY(0));
 }
 #endif
 
 #ifdef	LITTLE_ENDIAN
 static int smt_swap_short(u_short s)
 {
-	return(((s>>8)&0xff)|((s&0xff)<<8)) ;
+	return ((s>>8)&0xff) | ((s&0xff)<<8);
 }
 
 void smt_swap_para(struct smt_header *sm, int len, int direction)
@@ -1996,7 +1996,7 @@
 			}
 			break ;
 		default :
-			return(1) ;
+			return 1;
 		}
 		break ;
 	case SMT_PORT_ACTION :
@@ -2017,14 +2017,14 @@
 			event = PC_STOP ;
 			break ;
 		default :
-			return(1) ;
+			return 1;
 		}
 		queue_event(smc,EVENT_PCM+index,event) ;
 		break ;
 	default :
-		return(1) ;
+		return 1;
 	}
-	return(0) ;
+	return 0;
 }
 
 /*
diff --git a/drivers/net/skfp/smtdef.c b/drivers/net/skfp/smtdef.c
index 4e07ff7..1acab0b 100644
--- a/drivers/net/skfp/smtdef.c
+++ b/drivers/net/skfp/smtdef.c
@@ -303,7 +303,7 @@
 			FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_T_REQ,
 			smt_get_event_word(smc));
 	}
-	return(st) ;
+	return st;
 }
 
 void smt_fixup_mib(struct s_smc *smc)
@@ -350,6 +350,6 @@
 		*oper = limit ;
 	else
 		*oper = mib ;
-	return(old != *oper) ;
+	return old != *oper;
 }
 
diff --git a/drivers/net/skfp/smtinit.c b/drivers/net/skfp/smtinit.c
index 3c8964c..e3a0c0b 100644
--- a/drivers/net/skfp/smtinit.c
+++ b/drivers/net/skfp/smtinit.c
@@ -120,6 +120,6 @@
 
         PNMI_INIT(smc) ;                /* PNMI initialization */
 
-	return(0) ;
+	return 0;
 }
 
diff --git a/drivers/net/skfp/srf.c b/drivers/net/skfp/srf.c
index 40882b3..f6f7baf 100644
--- a/drivers/net/skfp/srf.c
+++ b/drivers/net/skfp/srf.c
@@ -165,7 +165,7 @@
 
 	for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
 		if (evc->evc_code == code && evc->evc_index == index)
-			return(evc) ;
+			return evc;
 	}
 	return NULL;
 }
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 40e5c46..bfec2e0 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -43,6 +43,7 @@
 #include <linux/seq_file.h>
 #include <linux/mii.h>
 #include <linux/slab.h>
+#include <linux/dmi.h>
 #include <asm/irq.h>
 
 #include "skge.h"
@@ -3178,8 +3179,7 @@
 
 		skb = skge_rx_get(dev, e, control, rd->status, rd->csum2);
 		if (likely(skb)) {
-			netif_receive_skb(skb);
-
+			napi_gro_receive(napi, skb);
 			++work_done;
 		}
 	}
@@ -3192,6 +3192,7 @@
 	if (work_done < to_do) {
 		unsigned long flags;
 
+		napi_gro_flush(napi);
 		spin_lock_irqsave(&hw->hw_lock, flags);
 		__napi_complete(napi);
 		hw->intr_mask |= napimask[skge->port];
@@ -3849,6 +3850,7 @@
 		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 		skge->rx_csum = 1;
 	}
+	dev->features |= NETIF_F_GRO;
 
 	/* read the mac address */
 	memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
@@ -3868,6 +3870,8 @@
 	netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr);
 }
 
+static int only_32bit_dma;
+
 static int __devinit skge_probe(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
@@ -3889,7 +3893,7 @@
 
 	pci_set_master(pdev);
 
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+	if (!only_32bit_dma && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
 		using_dac = 1;
 		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
 	} else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
@@ -4147,8 +4151,21 @@
 	.shutdown =	skge_shutdown,
 };
 
+static struct dmi_system_id skge_32bit_dma_boards[] = {
+	{
+		.ident = "Gigabyte nForce boards",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co"),
+			DMI_MATCH(DMI_BOARD_NAME, "nForce"),
+		},
+	},
+	{}
+};
+
 static int __init skge_init_module(void)
 {
+	if (dmi_check_system(skge_32bit_dma_boards))
+		only_32bit_dma = 1;
 	skge_debug_init();
 	return pci_register_driver(&skge_driver);
 }
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 194e5cf..d657708 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1782,7 +1782,7 @@
 	ctrl = 0;
 #ifdef SKY2_VLAN_TAG_USED
 	/* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */
-	if (sky2->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		if (!le) {
 			le = get_tx_le(sky2, &slot);
 			le->addr = 0;
@@ -4581,7 +4581,8 @@
 
 	sky2->port = port;
 
-	dev->features |= NETIF_F_TSO | NETIF_F_IP_CSUM | NETIF_F_SG;
+	dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG
+		| NETIF_F_TSO  | NETIF_F_GRO;
 	if (highmem)
 		dev->features |= NETIF_F_HIGHDMA;
 
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index fa434fb..86cbb9e 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -271,7 +271,7 @@
 			memcpy(sl->xbuff, sl->xhead, sl->xleft);
 		} else  {
 			sl->xleft = 0;
-			sl->tx_dropped++;
+			dev->stats.tx_dropped++;
 		}
 	}
 	sl->xhead = sl->xbuff;
@@ -281,7 +281,7 @@
 			memcpy(sl->rbuff, rbuff, sl->rcount);
 		} else  {
 			sl->rcount = 0;
-			sl->rx_over_errors++;
+			dev->stats.rx_over_errors++;
 			set_bit(SLF_ERROR, &sl->flags);
 		}
 	}
@@ -319,6 +319,7 @@
 /* Send one completely decapsulated IP datagram to the IP layer. */
 static void sl_bump(struct slip *sl)
 {
+	struct net_device *dev = sl->dev;
 	struct sk_buff *skb;
 	int count;
 
@@ -329,13 +330,13 @@
 		if (c & SL_TYPE_COMPRESSED_TCP) {
 			/* ignore compressed packets when CSLIP is off */
 			if (!(sl->mode & SL_MODE_CSLIP)) {
-				printk(KERN_WARNING "%s: compressed packet ignored\n", sl->dev->name);
+				printk(KERN_WARNING "%s: compressed packet ignored\n", dev->name);
 				return;
 			}
 			/* make sure we've reserved enough space for uncompress
 			   to use */
 			if (count + 80 > sl->buffsize) {
-				sl->rx_over_errors++;
+				dev->stats.rx_over_errors++;
 				return;
 			}
 			count = slhc_uncompress(sl->slcomp, sl->rbuff, count);
@@ -346,7 +347,7 @@
 				/* turn on header compression */
 				sl->mode |= SL_MODE_CSLIP;
 				sl->mode &= ~SL_MODE_ADAPTIVE;
-				printk(KERN_INFO "%s: header compression turned on\n", sl->dev->name);
+				printk(KERN_INFO "%s: header compression turned on\n", dev->name);
 			}
 			sl->rbuff[0] &= 0x4f;
 			if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0)
@@ -355,20 +356,20 @@
 	}
 #endif  /* SL_INCLUDE_CSLIP */
 
-	sl->rx_bytes += count;
+	dev->stats.rx_bytes += count;
 
 	skb = dev_alloc_skb(count);
 	if (skb == NULL) {
-		printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", sl->dev->name);
-		sl->rx_dropped++;
+		printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name);
+		dev->stats.rx_dropped++;
 		return;
 	}
-	skb->dev = sl->dev;
+	skb->dev = dev;
 	memcpy(skb_put(skb, count), sl->rbuff, count);
 	skb_reset_mac_header(skb);
 	skb->protocol = htons(ETH_P_IP);
 	netif_rx(skb);
-	sl->rx_packets++;
+	dev->stats.rx_packets++;
 }
 
 /* Encapsulate one IP datagram and stuff into a TTY queue. */
@@ -379,7 +380,7 @@
 
 	if (len > sl->mtu) {		/* Sigh, shouldn't occur BUT ... */
 		printk(KERN_WARNING "%s: truncating oversized transmit packet!\n", sl->dev->name);
-		sl->tx_dropped++;
+		sl->dev->stats.tx_dropped++;
 		sl_unlock(sl);
 		return;
 	}
@@ -433,7 +434,7 @@
 	if (sl->xleft <= 0)  {
 		/* Now serial buffer is almost free & we can start
 		 * transmission of another packet */
-		sl->tx_packets++;
+		sl->dev->stats.tx_packets++;
 		clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 		sl_unlock(sl);
 		return;
@@ -496,7 +497,7 @@
 	}
 
 	sl_lock(sl);
-	sl->tx_bytes += skb->len;
+	dev->stats.tx_bytes += skb->len;
 	sl_encaps(sl, skb->data, skb->len);
 	spin_unlock(&sl->lock);
 
@@ -558,39 +559,39 @@
 
 /* Netdevice get statistics request */
 
-static struct net_device_stats *
-sl_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *
+sl_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
 {
-	static struct net_device_stats stats;
+	struct net_device_stats *devstats = &dev->stats;
+	unsigned long c_rx_dropped = 0;
+#ifdef SL_INCLUDE_CSLIP
+	unsigned long c_rx_fifo_errors = 0;
+	unsigned long c_tx_fifo_errors = 0;
+	unsigned long c_collisions = 0;
 	struct slip *sl = netdev_priv(dev);
-#ifdef SL_INCLUDE_CSLIP
-	struct slcompress *comp;
-#endif
+	struct slcompress *comp = sl->slcomp;
 
-	memset(&stats, 0, sizeof(struct net_device_stats));
-
-	stats.rx_packets     = sl->rx_packets;
-	stats.tx_packets     = sl->tx_packets;
-	stats.rx_bytes	     = sl->rx_bytes;
-	stats.tx_bytes	     = sl->tx_bytes;
-	stats.rx_dropped     = sl->rx_dropped;
-	stats.tx_dropped     = sl->tx_dropped;
-	stats.tx_errors      = sl->tx_errors;
-	stats.rx_errors      = sl->rx_errors;
-	stats.rx_over_errors = sl->rx_over_errors;
-#ifdef SL_INCLUDE_CSLIP
-	stats.rx_fifo_errors = sl->rx_compressed;
-	stats.tx_fifo_errors = sl->tx_compressed;
-	stats.collisions     = sl->tx_misses;
-	comp = sl->slcomp;
 	if (comp) {
-		stats.rx_fifo_errors += comp->sls_i_compressed;
-		stats.rx_dropped     += comp->sls_i_tossed;
-		stats.tx_fifo_errors += comp->sls_o_compressed;
-		stats.collisions     += comp->sls_o_misses;
+		c_rx_fifo_errors = comp->sls_i_compressed;
+		c_rx_dropped     = comp->sls_i_tossed;
+		c_tx_fifo_errors = comp->sls_o_compressed;
+		c_collisions     = comp->sls_o_misses;
 	}
-#endif /* CONFIG_INET */
-	return (&stats);
+	stats->rx_fifo_errors = sl->rx_compressed + c_rx_fifo_errors;
+	stats->tx_fifo_errors = sl->tx_compressed + c_tx_fifo_errors;
+	stats->collisions     = sl->tx_misses + c_collisions;
+#endif
+	stats->rx_packets     = devstats->rx_packets;
+	stats->tx_packets     = devstats->tx_packets;
+	stats->rx_bytes       = devstats->rx_bytes;
+	stats->tx_bytes       = devstats->tx_bytes;
+	stats->rx_dropped     = devstats->rx_dropped + c_rx_dropped;
+	stats->tx_dropped     = devstats->tx_dropped;
+	stats->tx_errors      = devstats->tx_errors;
+	stats->rx_errors      = devstats->rx_errors;
+	stats->rx_over_errors = devstats->rx_over_errors;
+
+	return stats;
 }
 
 /* Netdevice register callback */
@@ -633,7 +634,7 @@
 	.ndo_open		= sl_open,
 	.ndo_stop		= sl_close,
 	.ndo_start_xmit		= sl_xmit,
-	.ndo_get_stats	        = sl_get_stats,
+	.ndo_get_stats64        = sl_get_stats64,
 	.ndo_change_mtu		= sl_change_mtu,
 	.ndo_tx_timeout		= sl_tx_timeout,
 #ifdef CONFIG_SLIP_SMART
@@ -681,7 +682,7 @@
 	while (count--) {
 		if (fp && *fp++) {
 			if (!test_and_set_bit(SLF_ERROR, &sl->flags))
-				sl->rx_errors++;
+				sl->dev->stats.rx_errors++;
 			cp++;
 			continue;
 		}
@@ -943,7 +944,7 @@
 		}
 	}
 	*ptr++ = END;
-	return (ptr - d);
+	return ptr - d;
 }
 
 static void slip_unesc(struct slip *sl, unsigned char s)
@@ -981,7 +982,7 @@
 			sl->rbuff[sl->rcount++] = s;
 			return;
 		}
-		sl->rx_over_errors++;
+		sl->dev->stats.rx_over_errors++;
 		set_bit(SLF_ERROR, &sl->flags);
 	}
 }
@@ -1057,7 +1058,7 @@
 					sl->rbuff[sl->rcount++] = c;
 					return;
 				}
-				sl->rx_over_errors++;
+				sl->dev->stats.rx_over_errors++;
 				set_bit(SLF_ERROR, &sl->flags);
 			}
 		}
diff --git a/drivers/net/slip.h b/drivers/net/slip.h
index 9ea5c11..914e958 100644
--- a/drivers/net/slip.h
+++ b/drivers/net/slip.h
@@ -67,15 +67,6 @@
   int                   xleft;          /* bytes left in XMIT queue     */
 
   /* SLIP interface statistics. */
-  unsigned long		rx_packets;	/* inbound frames counter	*/
-  unsigned long         tx_packets;     /* outbound frames counter      */
-  unsigned long		rx_bytes;	/* inbound byte counte		*/
-  unsigned long         tx_bytes;       /* outbound byte counter	*/
-  unsigned long         rx_errors;      /* Parity, etc. errors          */
-  unsigned long         tx_errors;      /* Planned stuff                */
-  unsigned long         rx_dropped;     /* No memory for skb            */
-  unsigned long         tx_dropped;     /* When MTU change              */
-  unsigned long         rx_over_errors; /* Frame bigger than SLIP buf.  */
 #ifdef SL_INCLUDE_CSLIP
   unsigned long		tx_compressed;
   unsigned long		rx_compressed;
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 10cf0cb..726df61 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -72,6 +72,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/crc32.h>
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index 0909ae9..a8e5856 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -58,6 +58,7 @@
 
 MODULE_LICENSE("GPL");
 MODULE_VERSION(SMSC_DRV_VERSION);
+MODULE_ALIAS("platform:smsc911x");
 
 #if USE_DEBUG > 0
 static int debug = 16;
@@ -1048,7 +1049,7 @@
 		smsc911x_rx_readfifo(pdata, (unsigned int *)skb->head,
 				     pktwords);
 		skb->protocol = eth_type_trans(skb, dev);
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 		netif_receive_skb(skb);
 
 		/* Update counters */
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 1636a34..cb6bcca 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1000,9 +1000,9 @@
 		     !(data_error & SPIDER_NET_DATA_ERR_CKSUM_MASK))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
 	} else
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 
 	if (data_status & SPIDER_NET_VLAN_PACKET) {
 		/* further enhancements: HW-accel VLAN
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index a42b687..4adf124 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -148,7 +148,7 @@
  * This SUCKS.
  * We need a much better method to determine if dma_addr_t is 64-bit.
  */
-#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
+#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT))
 /* 64-bit dma_addr_t */
 #define ADDR_64BITS	/* This chip uses 64 bit addresses. */
 #define netdrv_addr_t __le64
@@ -302,7 +302,7 @@
 };
 
 static DEFINE_PCI_DEVICE_TABLE(starfire_pci_tbl) = {
-	{ 0x9004, 0x6915, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_6915 },
+	{ PCI_VDEVICE(ADAPTEC, 0x6915), CH_6915 },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
@@ -2078,11 +2078,7 @@
 	printk(KERN_INFO DRV_NAME ": polling (NAPI) enabled\n");
 #endif
 
-	/* we can do this test only at run-time... sigh */
-	if (sizeof(dma_addr_t) != sizeof(netdrv_addr_t)) {
-		printk("This driver has dma_addr_t issues, please send email to maintainer\n");
-		return -ENODEV;
-	}
+	BUILD_BUG_ON(sizeof(dma_addr_t) != sizeof(netdrv_addr_t));
 
 	return pci_register_driver(&starfire_driver);
 }
diff --git a/drivers/net/stmmac/Kconfig b/drivers/net/stmmac/Kconfig
index eb63d44..7df7df4 100644
--- a/drivers/net/stmmac/Kconfig
+++ b/drivers/net/stmmac/Kconfig
@@ -3,10 +3,10 @@
 	select MII
 	select PHYLIB
 	select CRC32
-	depends on NETDEVICES && CPU_SUBTYPE_ST40
+	depends on NETDEVICES && HAS_IOMEM
 	help
 	  This is the driver for the Ethernet IPs are built around a
-	  Synopsys IP Core and fully tested on the STMicroelectronics
+	  Synopsys IP Core and only tested on the STMicroelectronics
 	  platforms.
 
 if STMMAC_ETH
@@ -32,6 +32,7 @@
 config STMMAC_TIMER
 	bool "STMMAC Timer optimisation"
 	default n
+	depends on RTC_HCTOSYS_DEVICE
 	help
 	  Use an external timer for mitigating the number of network
 	  interrupts. Currently, for SH architectures, it is possible
diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h
index 66b9da0..375ea19 100644
--- a/drivers/net/stmmac/common.h
+++ b/drivers/net/stmmac/common.h
@@ -102,8 +102,6 @@
 
 #define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */
 
-#define HW_CSUM 1
-#define NO_HW_CSUM 0
 enum rx_frame_status { /* IPC status */
 	good_frame = 0,
 	discard_frame = 1,
@@ -167,7 +165,7 @@
 	int (*get_tx_ls) (struct dma_desc *p);
 	/* Return the transmit status looking at the TDES1 */
 	int (*tx_status) (void *data, struct stmmac_extra_stats *x,
-			  struct dma_desc *p, unsigned long ioaddr);
+			  struct dma_desc *p, void __iomem *ioaddr);
 	/* Get the buffer size from the descriptor */
 	int (*get_tx_len) (struct dma_desc *p);
 	/* Handle extra events on specific interrupts hw dependent */
@@ -182,44 +180,46 @@
 
 struct stmmac_dma_ops {
 	/* DMA core initialization */
-	int (*init) (unsigned long ioaddr, int pbl, u32 dma_tx, u32 dma_rx);
+	int (*init) (void __iomem *ioaddr, int pbl, u32 dma_tx, u32 dma_rx);
 	/* Dump DMA registers */
-	void (*dump_regs) (unsigned long ioaddr);
+	void (*dump_regs) (void __iomem *ioaddr);
 	/* Set tx/rx threshold in the csr6 register
 	 * An invalid value enables the store-and-forward mode */
-	void (*dma_mode) (unsigned long ioaddr, int txmode, int rxmode);
+	void (*dma_mode) (void __iomem *ioaddr, int txmode, int rxmode);
 	/* To track extra statistic (if supported) */
 	void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x,
-				   unsigned long ioaddr);
-	void (*enable_dma_transmission) (unsigned long ioaddr);
-	void (*enable_dma_irq) (unsigned long ioaddr);
-	void (*disable_dma_irq) (unsigned long ioaddr);
-	void (*start_tx) (unsigned long ioaddr);
-	void (*stop_tx) (unsigned long ioaddr);
-	void (*start_rx) (unsigned long ioaddr);
-	void (*stop_rx) (unsigned long ioaddr);
-	int (*dma_interrupt) (unsigned long ioaddr,
+				   void __iomem *ioaddr);
+	void (*enable_dma_transmission) (void __iomem *ioaddr);
+	void (*enable_dma_irq) (void __iomem *ioaddr);
+	void (*disable_dma_irq) (void __iomem *ioaddr);
+	void (*start_tx) (void __iomem *ioaddr);
+	void (*stop_tx) (void __iomem *ioaddr);
+	void (*start_rx) (void __iomem *ioaddr);
+	void (*stop_rx) (void __iomem *ioaddr);
+	int (*dma_interrupt) (void __iomem *ioaddr,
 			      struct stmmac_extra_stats *x);
 };
 
 struct stmmac_ops {
 	/* MAC core initialization */
-	void (*core_init) (unsigned long ioaddr) ____cacheline_aligned;
+	void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned;
+	/* Support checksum offload engine */
+	int  (*rx_coe) (void __iomem *ioaddr);
 	/* Dump MAC registers */
-	void (*dump_regs) (unsigned long ioaddr);
+	void (*dump_regs) (void __iomem *ioaddr);
 	/* Handle extra events on specific interrupts hw dependent */
-	void (*host_irq_status) (unsigned long ioaddr);
+	void (*host_irq_status) (void __iomem *ioaddr);
 	/* Multicast filter setting */
 	void (*set_filter) (struct net_device *dev);
 	/* Flow control setting */
-	void (*flow_ctrl) (unsigned long ioaddr, unsigned int duplex,
+	void (*flow_ctrl) (void __iomem *ioaddr, unsigned int duplex,
 			   unsigned int fc, unsigned int pause_time);
 	/* Set power management mode (e.g. magic frame) */
-	void (*pmt) (unsigned long ioaddr, unsigned long mode);
+	void (*pmt) (void __iomem *ioaddr, unsigned long mode);
 	/* Set/Get Unicast MAC addresses */
-	void (*set_umac_addr) (unsigned long ioaddr, unsigned char *addr,
+	void (*set_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
 			       unsigned int reg_n);
-	void (*get_umac_addr) (unsigned long ioaddr, unsigned char *addr,
+	void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
 			       unsigned int reg_n);
 };
 
@@ -235,19 +235,18 @@
 };
 
 struct mac_device_info {
-	struct stmmac_ops	*mac;
-	struct stmmac_desc_ops	*desc;
-	struct stmmac_dma_ops	*dma;
-	unsigned int pmt;	/* support Power-Down */
+	const struct stmmac_ops		*mac;
+	const struct stmmac_desc_ops	*desc;
+	const struct stmmac_dma_ops	*dma;
 	struct mii_regs mii;	/* MII register Addresses */
 	struct mac_link link;
 };
 
-struct mac_device_info *dwmac1000_setup(unsigned long addr);
-struct mac_device_info *dwmac100_setup(unsigned long addr);
+struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr);
+struct mac_device_info *dwmac100_setup(void __iomem *ioaddr);
 
-extern void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6],
+extern void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
 				unsigned int high, unsigned int low);
-extern void stmmac_get_mac_addr(unsigned long ioaddr, unsigned char *addr,
+extern void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
 				unsigned int high, unsigned int low);
-extern void dwmac_dma_flush_tx_fifo(unsigned long ioaddr);
+extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
diff --git a/drivers/net/stmmac/dwmac100.h b/drivers/net/stmmac/dwmac100.h
index 97956cbf1..7c6d857 100644
--- a/drivers/net/stmmac/dwmac100.h
+++ b/drivers/net/stmmac/dwmac100.h
@@ -118,4 +118,4 @@
 #define DMA_MISSED_FRAME_OVE_M	0x00010000	/* Missed Frame Overflow */
 #define DMA_MISSED_FRAME_M_CNTR	0x0000ffff	/* Missed Frame Couinter */
 
-extern struct stmmac_dma_ops dwmac100_dma_ops;
+extern const struct stmmac_dma_ops dwmac100_dma_ops;
diff --git a/drivers/net/stmmac/dwmac1000.h b/drivers/net/stmmac/dwmac1000.h
index 8b20b19..cfcef0e 100644
--- a/drivers/net/stmmac/dwmac1000.h
+++ b/drivers/net/stmmac/dwmac1000.h
@@ -99,7 +99,7 @@
 #define GMAC_CONTROL_RE		0x00000004 /* Receiver Enable */
 
 #define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \
-			GMAC_CONTROL_IPC | GMAC_CONTROL_JE | GMAC_CONTROL_BE)
+			GMAC_CONTROL_JE | GMAC_CONTROL_BE)
 
 /* GMAC Frame Filter defines */
 #define GMAC_FRAME_FILTER_PR	0x00000001	/* Promiscuous Mode */
@@ -205,4 +205,4 @@
 #define GMAC_MMC_TX_INTR   0x108
 #define GMAC_MMC_RX_CSUM_OFFLOAD   0x208
 
-extern struct stmmac_dma_ops dwmac1000_dma_ops;
+extern const struct stmmac_dma_ops dwmac1000_dma_ops;
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c
index 2b2f5c8..6ae4c3f 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/stmmac/dwmac1000_core.c
@@ -30,7 +30,7 @@
 #include <linux/slab.h>
 #include "dwmac1000.h"
 
-static void dwmac1000_core_init(unsigned long ioaddr)
+static void dwmac1000_core_init(void __iomem *ioaddr)
 {
 	u32 value = readl(ioaddr + GMAC_CONTROL);
 	value |= GMAC_CORE_INIT;
@@ -50,10 +50,22 @@
 #endif
 }
 
-static void dwmac1000_dump_regs(unsigned long ioaddr)
+static int dwmac1000_rx_coe_supported(void __iomem *ioaddr)
+{
+	u32 value = readl(ioaddr + GMAC_CONTROL);
+
+	value |= GMAC_CONTROL_IPC;
+	writel(value, ioaddr + GMAC_CONTROL);
+
+	value = readl(ioaddr + GMAC_CONTROL);
+
+	return !!(value & GMAC_CONTROL_IPC);
+}
+
+static void dwmac1000_dump_regs(void __iomem *ioaddr)
 {
 	int i;
-	pr_info("\tDWMAC1000 regs (base addr = 0x%8x)\n", (unsigned int)ioaddr);
+	pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr);
 
 	for (i = 0; i < 55; i++) {
 		int offset = i * 4;
@@ -62,14 +74,14 @@
 	}
 }
 
-static void dwmac1000_set_umac_addr(unsigned long ioaddr, unsigned char *addr,
+static void dwmac1000_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
 				unsigned int reg_n)
 {
 	stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
 				GMAC_ADDR_LOW(reg_n));
 }
 
-static void dwmac1000_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
+static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
 				unsigned int reg_n)
 {
 	stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
@@ -78,7 +90,7 @@
 
 static void dwmac1000_set_filter(struct net_device *dev)
 {
-	unsigned long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = (void __iomem *) dev->base_addr;
 	unsigned int value = 0;
 
 	CHIP_DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n",
@@ -139,7 +151,7 @@
 	    readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW));
 }
 
-static void dwmac1000_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
+static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
 			   unsigned int fc, unsigned int pause_time)
 {
 	unsigned int flow = 0;
@@ -162,7 +174,7 @@
 	writel(flow, ioaddr + GMAC_FLOW_CTRL);
 }
 
-static void dwmac1000_pmt(unsigned long ioaddr, unsigned long mode)
+static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
 {
 	unsigned int pmt = 0;
 
@@ -178,7 +190,7 @@
 }
 
 
-static void dwmac1000_irq_status(unsigned long ioaddr)
+static void dwmac1000_irq_status(void __iomem *ioaddr)
 {
 	u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
 
@@ -200,8 +212,9 @@
 	}
 }
 
-struct stmmac_ops dwmac1000_ops = {
+static const struct stmmac_ops dwmac1000_ops = {
 	.core_init = dwmac1000_core_init,
+	.rx_coe = dwmac1000_rx_coe_supported,
 	.dump_regs = dwmac1000_dump_regs,
 	.host_irq_status = dwmac1000_irq_status,
 	.set_filter = dwmac1000_set_filter,
@@ -211,7 +224,7 @@
 	.get_umac_addr = dwmac1000_get_umac_addr,
 };
 
-struct mac_device_info *dwmac1000_setup(unsigned long ioaddr)
+struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
 {
 	struct mac_device_info *mac;
 	u32 uid = readl(ioaddr + GMAC_VERSION);
@@ -226,7 +239,6 @@
 	mac->mac = &dwmac1000_ops;
 	mac->dma = &dwmac1000_dma_ops;
 
-	mac->pmt = PMT_SUPPORTED;
 	mac->link.port = GMAC_CONTROL_PS;
 	mac->link.duplex = GMAC_CONTROL_DM;
 	mac->link.speed = GMAC_CONTROL_FES;
diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/stmmac/dwmac1000_dma.c
index 4158050..2c47712 100644
--- a/drivers/net/stmmac/dwmac1000_dma.c
+++ b/drivers/net/stmmac/dwmac1000_dma.c
@@ -29,14 +29,22 @@
 #include "dwmac1000.h"
 #include "dwmac_dma.h"
 
-static int dwmac1000_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx,
+static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
 			      u32 dma_rx)
 {
 	u32 value = readl(ioaddr + DMA_BUS_MODE);
+	int limit;
+
 	/* DMA SW reset */
 	value |= DMA_BUS_MODE_SFT_RESET;
 	writel(value, ioaddr + DMA_BUS_MODE);
-	do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET));
+	limit = 15000;
+	while (limit--) {
+		if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
+			break;
+	}
+	if (limit < 0)
+		return -EBUSY;
 
 	value = /* DMA_BUS_MODE_FB | */ DMA_BUS_MODE_4PBL |
 	    ((pbl << DMA_BUS_MODE_PBL_SHIFT) |
@@ -58,7 +66,7 @@
 	return 0;
 }
 
-static void dwmac1000_dma_operation_mode(unsigned long ioaddr, int txmode,
+static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode,
 				    int rxmode)
 {
 	u32 csr6 = readl(ioaddr + DMA_CONTROL);
@@ -111,12 +119,12 @@
 
 /* Not yet implemented --- no RMON module */
 static void dwmac1000_dma_diagnostic_fr(void *data,
-		  struct stmmac_extra_stats *x, unsigned long ioaddr)
+		  struct stmmac_extra_stats *x, void __iomem *ioaddr)
 {
 	return;
 }
 
-static void dwmac1000_dump_dma_regs(unsigned long ioaddr)
+static void dwmac1000_dump_dma_regs(void __iomem *ioaddr)
 {
 	int i;
 	pr_info(" DMA registers\n");
@@ -130,7 +138,7 @@
 	}
 }
 
-struct stmmac_dma_ops dwmac1000_dma_ops = {
+const struct stmmac_dma_ops dwmac1000_dma_ops = {
 	.init = dwmac1000_dma_init,
 	.dump_regs = dwmac1000_dump_dma_regs,
 	.dma_mode = dwmac1000_dma_operation_mode,
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c
index 2fb165f..c724fc3 100644
--- a/drivers/net/stmmac/dwmac100_core.c
+++ b/drivers/net/stmmac/dwmac100_core.c
@@ -31,7 +31,7 @@
 #include <linux/crc32.h>
 #include "dwmac100.h"
 
-static void dwmac100_core_init(unsigned long ioaddr)
+static void dwmac100_core_init(void __iomem *ioaddr)
 {
 	u32 value = readl(ioaddr + MAC_CONTROL);
 
@@ -42,12 +42,17 @@
 #endif
 }
 
-static void dwmac100_dump_mac_regs(unsigned long ioaddr)
+static int dwmac100_rx_coe_supported(void __iomem *ioaddr)
+{
+	return 0;
+}
+
+static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
 {
 	pr_info("\t----------------------------------------------\n"
-		"\t  DWMAC 100 CSR (base addr = 0x%8x)\n"
+		"\t  DWMAC 100 CSR (base addr = 0x%p)\n"
 		"\t----------------------------------------------\n",
-		(unsigned int)ioaddr);
+		ioaddr);
 	pr_info("\tcontrol reg (offset 0x%x): 0x%08x\n", MAC_CONTROL,
 		readl(ioaddr + MAC_CONTROL));
 	pr_info("\taddr HI (offset 0x%x): 0x%08x\n ", MAC_ADDR_HIGH,
@@ -77,18 +82,18 @@
 		MMC_LOW_INTR_MASK, readl(ioaddr + MMC_LOW_INTR_MASK));
 }
 
-static void dwmac100_irq_status(unsigned long ioaddr)
+static void dwmac100_irq_status(void __iomem *ioaddr)
 {
 	return;
 }
 
-static void dwmac100_set_umac_addr(unsigned long ioaddr, unsigned char *addr,
+static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
 				   unsigned int reg_n)
 {
 	stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
 }
 
-static void dwmac100_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
+static void dwmac100_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
 				   unsigned int reg_n)
 {
 	stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
@@ -96,7 +101,7 @@
 
 static void dwmac100_set_filter(struct net_device *dev)
 {
-	unsigned long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = (void __iomem *) dev->base_addr;
 	u32 value = readl(ioaddr + MAC_CONTROL);
 
 	if (dev->flags & IFF_PROMISC) {
@@ -145,7 +150,7 @@
 	    readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW));
 }
 
-static void dwmac100_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
+static void dwmac100_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
 			       unsigned int fc, unsigned int pause_time)
 {
 	unsigned int flow = MAC_FLOW_CTRL_ENABLE;
@@ -158,13 +163,14 @@
 /* No PMT module supported for this Ethernet Controller.
  * Tested on ST platforms only.
  */
-static void dwmac100_pmt(unsigned long ioaddr, unsigned long mode)
+static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
 {
 	return;
 }
 
-struct stmmac_ops dwmac100_ops = {
+static const struct stmmac_ops dwmac100_ops = {
 	.core_init = dwmac100_core_init,
+	.rx_coe = dwmac100_rx_coe_supported,
 	.dump_regs = dwmac100_dump_mac_regs,
 	.host_irq_status = dwmac100_irq_status,
 	.set_filter = dwmac100_set_filter,
@@ -174,7 +180,7 @@
 	.get_umac_addr = dwmac100_get_umac_addr,
 };
 
-struct mac_device_info *dwmac100_setup(unsigned long ioaddr)
+struct mac_device_info *dwmac100_setup(void __iomem *ioaddr)
 {
 	struct mac_device_info *mac;
 
@@ -187,7 +193,6 @@
 	mac->mac = &dwmac100_ops;
 	mac->dma = &dwmac100_dma_ops;
 
-	mac->pmt = PMT_NOT_SUPPORTED;
 	mac->link.port = MAC_CONTROL_PS;
 	mac->link.duplex = MAC_CONTROL_F;
 	mac->link.speed = 0;
diff --git a/drivers/net/stmmac/dwmac100_dma.c b/drivers/net/stmmac/dwmac100_dma.c
index 2fece7b..e3e224b 100644
--- a/drivers/net/stmmac/dwmac100_dma.c
+++ b/drivers/net/stmmac/dwmac100_dma.c
@@ -31,14 +31,22 @@
 #include "dwmac100.h"
 #include "dwmac_dma.h"
 
-static int dwmac100_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx,
+static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
 			     u32 dma_rx)
 {
 	u32 value = readl(ioaddr + DMA_BUS_MODE);
+	int limit;
+
 	/* DMA SW reset */
 	value |= DMA_BUS_MODE_SFT_RESET;
 	writel(value, ioaddr + DMA_BUS_MODE);
-	do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET));
+	limit = 15000;
+	while (limit--) {
+		if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
+			break;
+	}
+	if (limit < 0)
+		return -EBUSY;
 
 	/* Enable Application Access by writing to DMA CSR0 */
 	writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT),
@@ -58,7 +66,7 @@
 /* Store and Forward capability is not used at all..
  * The transmit threshold can be programmed by
  * setting the TTC bits in the DMA control register.*/
-static void dwmac100_dma_operation_mode(unsigned long ioaddr, int txmode,
+static void dwmac100_dma_operation_mode(void __iomem *ioaddr, int txmode,
 					int rxmode)
 {
 	u32 csr6 = readl(ioaddr + DMA_CONTROL);
@@ -73,7 +81,7 @@
 	writel(csr6, ioaddr + DMA_CONTROL);
 }
 
-static void dwmac100_dump_dma_regs(unsigned long ioaddr)
+static void dwmac100_dump_dma_regs(void __iomem *ioaddr)
 {
 	int i;
 
@@ -91,7 +99,7 @@
 /* DMA controller has two counters to track the number of
  * the receive missed frames. */
 static void dwmac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x,
-				       unsigned long ioaddr)
+				       void __iomem *ioaddr)
 {
 	struct net_device_stats *stats = (struct net_device_stats *)data;
 	u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR);
@@ -118,7 +126,7 @@
 	}
 }
 
-struct stmmac_dma_ops dwmac100_dma_ops = {
+const struct stmmac_dma_ops dwmac100_dma_ops = {
 	.init = dwmac100_dma_init,
 	.dump_regs = dwmac100_dump_dma_regs,
 	.dma_mode = dwmac100_dma_operation_mode,
diff --git a/drivers/net/stmmac/dwmac_dma.h b/drivers/net/stmmac/dwmac_dma.h
index 7b815a1..da3f5cc 100644
--- a/drivers/net/stmmac/dwmac_dma.h
+++ b/drivers/net/stmmac/dwmac_dma.h
@@ -97,12 +97,12 @@
 #define DMA_STATUS_TI	0x00000001	/* Transmit Interrupt */
 #define DMA_CONTROL_FTF		0x00100000 /* Flush transmit FIFO */
 
-extern void dwmac_enable_dma_transmission(unsigned long ioaddr);
-extern void dwmac_enable_dma_irq(unsigned long ioaddr);
-extern void dwmac_disable_dma_irq(unsigned long ioaddr);
-extern void dwmac_dma_start_tx(unsigned long ioaddr);
-extern void dwmac_dma_stop_tx(unsigned long ioaddr);
-extern void dwmac_dma_start_rx(unsigned long ioaddr);
-extern void dwmac_dma_stop_rx(unsigned long ioaddr);
-extern int dwmac_dma_interrupt(unsigned long ioaddr,
+extern void dwmac_enable_dma_transmission(void __iomem *ioaddr);
+extern void dwmac_enable_dma_irq(void __iomem *ioaddr);
+extern void dwmac_disable_dma_irq(void __iomem *ioaddr);
+extern void dwmac_dma_start_tx(void __iomem *ioaddr);
+extern void dwmac_dma_stop_tx(void __iomem *ioaddr);
+extern void dwmac_dma_start_rx(void __iomem *ioaddr);
+extern void dwmac_dma_stop_rx(void __iomem *ioaddr);
+extern int dwmac_dma_interrupt(void __iomem *ioaddr,
 				struct stmmac_extra_stats *x);
diff --git a/drivers/net/stmmac/dwmac_lib.c b/drivers/net/stmmac/dwmac_lib.c
index a854152..d65fab1 100644
--- a/drivers/net/stmmac/dwmac_lib.c
+++ b/drivers/net/stmmac/dwmac_lib.c
@@ -32,43 +32,43 @@
 #endif
 
 /* CSR1 enables the transmit DMA to check for new descriptor */
-void dwmac_enable_dma_transmission(unsigned long ioaddr)
+void dwmac_enable_dma_transmission(void __iomem *ioaddr)
 {
 	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
 }
 
-void dwmac_enable_dma_irq(unsigned long ioaddr)
+void dwmac_enable_dma_irq(void __iomem *ioaddr)
 {
 	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
 }
 
-void dwmac_disable_dma_irq(unsigned long ioaddr)
+void dwmac_disable_dma_irq(void __iomem *ioaddr)
 {
 	writel(0, ioaddr + DMA_INTR_ENA);
 }
 
-void dwmac_dma_start_tx(unsigned long ioaddr)
+void dwmac_dma_start_tx(void __iomem *ioaddr)
 {
 	u32 value = readl(ioaddr + DMA_CONTROL);
 	value |= DMA_CONTROL_ST;
 	writel(value, ioaddr + DMA_CONTROL);
 }
 
-void dwmac_dma_stop_tx(unsigned long ioaddr)
+void dwmac_dma_stop_tx(void __iomem *ioaddr)
 {
 	u32 value = readl(ioaddr + DMA_CONTROL);
 	value &= ~DMA_CONTROL_ST;
 	writel(value, ioaddr + DMA_CONTROL);
 }
 
-void dwmac_dma_start_rx(unsigned long ioaddr)
+void dwmac_dma_start_rx(void __iomem *ioaddr)
 {
 	u32 value = readl(ioaddr + DMA_CONTROL);
 	value |= DMA_CONTROL_SR;
 	writel(value, ioaddr + DMA_CONTROL);
 }
 
-void dwmac_dma_stop_rx(unsigned long ioaddr)
+void dwmac_dma_stop_rx(void __iomem *ioaddr)
 {
 	u32 value = readl(ioaddr + DMA_CONTROL);
 	value &= ~DMA_CONTROL_SR;
@@ -145,7 +145,7 @@
 }
 #endif
 
-int dwmac_dma_interrupt(unsigned long ioaddr,
+int dwmac_dma_interrupt(void __iomem *ioaddr,
 			struct stmmac_extra_stats *x)
 {
 	int ret = 0;
@@ -219,7 +219,7 @@
 	return ret;
 }
 
-void dwmac_dma_flush_tx_fifo(unsigned long ioaddr)
+void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr)
 {
 	u32 csr6 = readl(ioaddr + DMA_CONTROL);
 	writel((csr6 | DMA_CONTROL_FTF), ioaddr + DMA_CONTROL);
@@ -227,7 +227,7 @@
 	do {} while ((readl(ioaddr + DMA_CONTROL) & DMA_CONTROL_FTF));
 }
 
-void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6],
+void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
 			 unsigned int high, unsigned int low)
 {
 	unsigned long data;
@@ -238,7 +238,7 @@
 	writel(data, ioaddr + low);
 }
 
-void stmmac_get_mac_addr(unsigned long ioaddr, unsigned char *addr,
+void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
 			 unsigned int high, unsigned int low)
 {
 	unsigned int hi_addr, lo_addr;
diff --git a/drivers/net/stmmac/enh_desc.c b/drivers/net/stmmac/enh_desc.c
index f612f98..e5dfb6a 100644
--- a/drivers/net/stmmac/enh_desc.c
+++ b/drivers/net/stmmac/enh_desc.c
@@ -25,7 +25,7 @@
 #include "common.h"
 
 static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
-				  struct dma_desc *p, unsigned long ioaddr)
+				  struct dma_desc *p, void __iomem *ioaddr)
 {
 	int ret = 0;
 	struct net_device_stats *stats = (struct net_device_stats *)data;
@@ -284,7 +284,7 @@
 {
 	int ter = p->des01.etx.end_ring;
 
-	memset(p, 0, sizeof(struct dma_desc));
+	memset(p, 0, offsetof(struct dma_desc, des2));
 	p->des01.etx.end_ring = ter;
 }
 
@@ -318,7 +318,7 @@
 	return p->des01.erx.frame_length;
 }
 
-struct stmmac_desc_ops enh_desc_ops = {
+const struct stmmac_desc_ops enh_desc_ops = {
 	.tx_status = enh_desc_get_tx_status,
 	.rx_status = enh_desc_get_rx_status,
 	.get_tx_len = enh_desc_get_tx_len,
diff --git a/drivers/net/stmmac/norm_desc.c b/drivers/net/stmmac/norm_desc.c
index 31ad536..cd0cc76 100644
--- a/drivers/net/stmmac/norm_desc.c
+++ b/drivers/net/stmmac/norm_desc.c
@@ -25,7 +25,7 @@
 #include "common.h"
 
 static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
-			       struct dma_desc *p, unsigned long ioaddr)
+			       struct dma_desc *p, void __iomem *ioaddr)
 {
 	int ret = 0;
 	struct net_device_stats *stats = (struct net_device_stats *)data;
@@ -174,22 +174,7 @@
 {
 	int ter = p->des01.tx.end_ring;
 
-	/* clean field used within the xmit */
-	p->des01.tx.first_segment = 0;
-	p->des01.tx.last_segment = 0;
-	p->des01.tx.buffer1_size = 0;
-
-	/* clean status reported */
-	p->des01.tx.error_summary = 0;
-	p->des01.tx.underflow_error = 0;
-	p->des01.tx.no_carrier = 0;
-	p->des01.tx.loss_carrier = 0;
-	p->des01.tx.excessive_deferral = 0;
-	p->des01.tx.excessive_collisions = 0;
-	p->des01.tx.late_collision = 0;
-	p->des01.tx.heartbeat_fail = 0;
-	p->des01.tx.deferred = 0;
-
+	memset(p, 0, offsetof(struct dma_desc, des2));
 	/* set termination field */
 	p->des01.tx.end_ring = ter;
 }
@@ -217,7 +202,7 @@
 	return p->des01.rx.frame_length;
 }
 
-struct stmmac_desc_ops ndesc_ops = {
+const struct stmmac_desc_ops ndesc_ops = {
 	.tx_status = ndesc_get_tx_status,
 	.rx_status = ndesc_get_rx_status,
 	.get_tx_len = ndesc_get_tx_len,
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index ebebc64..79bdc2e 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -21,6 +21,7 @@
 *******************************************************************************/
 
 #define DRV_MODULE_VERSION	"Apr_2010"
+#include <linux/platform_device.h>
 #include <linux/stmmac.h>
 
 #include "common.h"
@@ -50,10 +51,10 @@
 	int is_gmac;
 	dma_addr_t dma_rx_phy;
 	unsigned int dma_rx_size;
-	int rx_csum;
 	unsigned int dma_buf_sz;
 	struct device *device;
 	struct mac_device_info *hw;
+	void __iomem *ioaddr;
 
 	struct stmmac_extra_stats xstats;
 	struct napi_struct napi;
@@ -65,7 +66,7 @@
 	int phy_mask;
 	int (*phy_reset) (void *priv);
 	void (*fix_mac_speed) (void *priv, unsigned int speed);
-	void (*bus_setup)(unsigned long ioaddr);
+	void (*bus_setup)(void __iomem *ioaddr);
 	void *bsp_priv;
 
 	int phy_irq;
@@ -76,6 +77,7 @@
 	unsigned int flow_ctrl;
 	unsigned int pause;
 	struct mii_bus *mii;
+	int mii_clk_csr;
 
 	u32 msg_enable;
 	spinlock_t lock;
@@ -89,6 +91,9 @@
 	struct vlan_group *vlgrp;
 #endif
 	int enh_desc;
+	int rx_coe;
+	int bugged_jumbo;
+	int no_csum_insertion;
 };
 
 #ifdef CONFIG_STM_DRIVERS
@@ -116,5 +121,5 @@
 extern int stmmac_mdio_unregister(struct net_device *ndev);
 extern int stmmac_mdio_register(struct net_device *ndev);
 extern void stmmac_set_ethtool_ops(struct net_device *netdev);
-extern struct stmmac_desc_ops enh_desc_ops;
-extern struct stmmac_desc_ops ndesc_ops;
+extern const struct stmmac_desc_ops enh_desc_ops;
+extern const struct stmmac_desc_ops ndesc_ops;
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c
index f080509..6d65482 100644
--- a/drivers/net/stmmac/stmmac_ethtool.c
+++ b/drivers/net/stmmac/stmmac_ethtool.c
@@ -89,8 +89,8 @@
 };
 #define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
 
-void stmmac_ethtool_getdrvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
+static void stmmac_ethtool_getdrvinfo(struct net_device *dev,
+				      struct ethtool_drvinfo *info)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 
@@ -104,7 +104,8 @@
 	info->n_stats = STMMAC_STATS_LEN;
 }
 
-int stmmac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int stmmac_ethtool_getsettings(struct net_device *dev,
+				      struct ethtool_cmd *cmd)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	struct phy_device *phy = priv->phydev;
@@ -126,7 +127,8 @@
 	return rc;
 }
 
-int stmmac_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int stmmac_ethtool_setsettings(struct net_device *dev,
+				      struct ethtool_cmd *cmd)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	struct phy_device *phy = priv->phydev;
@@ -139,32 +141,32 @@
 	return rc;
 }
 
-u32 stmmac_ethtool_getmsglevel(struct net_device *dev)
+static u32 stmmac_ethtool_getmsglevel(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	return priv->msg_enable;
 }
 
-void stmmac_ethtool_setmsglevel(struct net_device *dev, u32 level)
+static void stmmac_ethtool_setmsglevel(struct net_device *dev, u32 level)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	priv->msg_enable = level;
 
 }
 
-int stmmac_check_if_running(struct net_device *dev)
+static int stmmac_check_if_running(struct net_device *dev)
 {
 	if (!netif_running(dev))
 		return -EBUSY;
 	return 0;
 }
 
-int stmmac_ethtool_get_regs_len(struct net_device *dev)
+static int stmmac_ethtool_get_regs_len(struct net_device *dev)
 {
 	return REG_SPACE_SIZE;
 }
 
-void stmmac_ethtool_gregs(struct net_device *dev,
+static void stmmac_ethtool_gregs(struct net_device *dev,
 			  struct ethtool_regs *regs, void *space)
 {
 	int i;
@@ -177,25 +179,25 @@
 	if (!priv->is_gmac) {
 		/* MAC registers */
 		for (i = 0; i < 12; i++)
-			reg_space[i] = readl(dev->base_addr + (i * 4));
+			reg_space[i] = readl(priv->ioaddr + (i * 4));
 		/* DMA registers */
 		for (i = 0; i < 9; i++)
 			reg_space[i + 12] =
-			    readl(dev->base_addr + (DMA_BUS_MODE + (i * 4)));
-		reg_space[22] = readl(dev->base_addr + DMA_CUR_TX_BUF_ADDR);
-		reg_space[23] = readl(dev->base_addr + DMA_CUR_RX_BUF_ADDR);
+			    readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4)));
+		reg_space[22] = readl(priv->ioaddr + DMA_CUR_TX_BUF_ADDR);
+		reg_space[23] = readl(priv->ioaddr + DMA_CUR_RX_BUF_ADDR);
 	} else {
 		/* MAC registers */
 		for (i = 0; i < 55; i++)
-			reg_space[i] = readl(dev->base_addr + (i * 4));
+			reg_space[i] = readl(priv->ioaddr + (i * 4));
 		/* DMA registers */
 		for (i = 0; i < 22; i++)
 			reg_space[i + 55] =
-			    readl(dev->base_addr + (DMA_BUS_MODE + (i * 4)));
+			    readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4)));
 	}
 }
 
-int stmmac_ethtool_set_tx_csum(struct net_device *netdev, u32 data)
+static int stmmac_ethtool_set_tx_csum(struct net_device *netdev, u32 data)
 {
 	if (data)
 		netdev->features |= NETIF_F_HW_CSUM;
@@ -205,11 +207,11 @@
 	return 0;
 }
 
-u32 stmmac_ethtool_get_rx_csum(struct net_device *dev)
+static u32 stmmac_ethtool_get_rx_csum(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 
-	return priv->rx_csum;
+	return priv->rx_coe;
 }
 
 static void
@@ -263,11 +265,9 @@
 			cmd.phy_address = phy->addr;
 			ret = phy_ethtool_sset(phy, &cmd);
 		}
-	} else {
-		unsigned long ioaddr = netdev->base_addr;
-		priv->hw->mac->flow_ctrl(ioaddr, phy->duplex,
+	} else
+		priv->hw->mac->flow_ctrl(priv->ioaddr, phy->duplex,
 					 priv->flow_ctrl, priv->pause);
-	}
 	spin_unlock(&priv->lock);
 	return ret;
 }
@@ -276,12 +276,11 @@
 				 struct ethtool_stats *dummy, u64 *data)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
 	int i;
 
 	/* Update HW stats if supported */
 	priv->hw->dma->dma_diagnostic_fr(&dev->stats, (void *) &priv->xstats,
-					 ioaddr);
+					 priv->ioaddr);
 
 	for (i = 0; i < STMMAC_STATS_LEN; i++) {
 		char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
@@ -325,7 +324,7 @@
 	struct stmmac_priv *priv = netdev_priv(dev);
 
 	spin_lock_irq(&priv->lock);
-	if (priv->wolenabled == PMT_SUPPORTED) {
+	if (device_can_wakeup(priv->device)) {
 		wol->supported = WAKE_MAGIC;
 		wol->wolopts = priv->wolopts;
 	}
@@ -337,16 +336,20 @@
 	struct stmmac_priv *priv = netdev_priv(dev);
 	u32 support = WAKE_MAGIC;
 
-	if (priv->wolenabled == PMT_NOT_SUPPORTED)
+	if (!device_can_wakeup(priv->device))
 		return -EINVAL;
 
 	if (wol->wolopts & ~support)
 		return -EINVAL;
 
-	if (wol->wolopts == 0)
-		device_set_wakeup_enable(priv->device, 0);
-	else
+	if (wol->wolopts) {
+		pr_info("stmmac: wakeup enable\n");
 		device_set_wakeup_enable(priv->device, 1);
+		enable_irq_wake(dev->irq);
+	} else {
+		device_set_wakeup_enable(priv->device, 0);
+		disable_irq_wake(dev->irq);
+	}
 
 	spin_lock_irq(&priv->lock);
 	priv->wolopts = wol->wolopts;
@@ -377,10 +380,8 @@
 	.get_wol = stmmac_get_wol,
 	.set_wol = stmmac_set_wol,
 	.get_sset_count	= stmmac_get_sset_count,
-#ifdef NETIF_F_TSO
 	.get_tso = ethtool_op_get_tso,
 	.set_tso = ethtool_op_set_tso,
-#endif
 };
 
 void stmmac_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index ea0461e..823b9e6 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -134,13 +134,6 @@
 module_param(buf_sz, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(buf_sz, "DMA buffer size");
 
-/* In case of Giga ETH, we can enable/disable the COE for the
- * transmit HW checksum computation.
- * Note that, if tx csum is off in HW, SG will be still supported. */
-static int tx_coe = HW_CSUM;
-module_param(tx_coe, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(tx_coe, "GMAC COE type 2 [on/off]");
-
 static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
 				      NETIF_MSG_LINK | NETIF_MSG_IFUP |
 				      NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
@@ -202,7 +195,6 @@
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	struct phy_device *phydev = priv->phydev;
-	unsigned long ioaddr = dev->base_addr;
 	unsigned long flags;
 	int new_state = 0;
 	unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
@@ -215,7 +207,7 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 	if (phydev->link) {
-		u32 ctrl = readl(ioaddr + MAC_CTRL_REG);
+		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
 
 		/* Now we make sure that we can be in full duplex mode.
 		 * If not, we operate in half-duplex mode. */
@@ -229,7 +221,7 @@
 		}
 		/* Flow Control operation */
 		if (phydev->pause)
-			priv->hw->mac->flow_ctrl(ioaddr, phydev->duplex,
+			priv->hw->mac->flow_ctrl(priv->ioaddr, phydev->duplex,
 						 fc, pause_time);
 
 		if (phydev->speed != priv->speed) {
@@ -238,6 +230,9 @@
 			case 1000:
 				if (likely(priv->is_gmac))
 					ctrl &= ~priv->hw->link.port;
+				if (likely(priv->fix_mac_speed))
+					priv->fix_mac_speed(priv->bsp_priv,
+							    phydev->speed);
 				break;
 			case 100:
 			case 10:
@@ -265,7 +260,7 @@
 			priv->speed = phydev->speed;
 		}
 
-		writel(ctrl, ioaddr + MAC_CTRL_REG);
+		writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
 
 		if (!priv->oldlink) {
 			new_state = 1;
@@ -342,7 +337,7 @@
 	return 0;
 }
 
-static inline void stmmac_mac_enable_rx(unsigned long ioaddr)
+static inline void stmmac_mac_enable_rx(void __iomem *ioaddr)
 {
 	u32 value = readl(ioaddr + MAC_CTRL_REG);
 	value |= MAC_RNABLE_RX;
@@ -350,7 +345,7 @@
 	writel(value, ioaddr + MAC_CTRL_REG);
 }
 
-static inline void stmmac_mac_enable_tx(unsigned long ioaddr)
+static inline void stmmac_mac_enable_tx(void __iomem *ioaddr)
 {
 	u32 value = readl(ioaddr + MAC_CTRL_REG);
 	value |= MAC_ENABLE_TX;
@@ -358,14 +353,14 @@
 	writel(value, ioaddr + MAC_CTRL_REG);
 }
 
-static inline void stmmac_mac_disable_rx(unsigned long ioaddr)
+static inline void stmmac_mac_disable_rx(void __iomem *ioaddr)
 {
 	u32 value = readl(ioaddr + MAC_CTRL_REG);
 	value &= ~MAC_RNABLE_RX;
 	writel(value, ioaddr + MAC_CTRL_REG);
 }
 
-static inline void stmmac_mac_disable_tx(unsigned long ioaddr)
+static inline void stmmac_mac_disable_tx(void __iomem *ioaddr)
 {
 	u32 value = readl(ioaddr + MAC_CTRL_REG);
 	value &= ~MAC_ENABLE_TX;
@@ -567,29 +562,22 @@
  *  stmmac_dma_operation_mode - HW DMA operation mode
  *  @priv : pointer to the private device structure.
  *  Description: it sets the DMA operation mode: tx/rx DMA thresholds
- *  or Store-And-Forward capability. It also verifies the COE for the
- *  transmission in case of Giga ETH.
+ *  or Store-And-Forward capability.
  */
 static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
 {
-	if (!priv->is_gmac) {
-		/* MAC 10/100 */
-		priv->hw->dma->dma_mode(priv->dev->base_addr, tc, 0);
-		priv->tx_coe = NO_HW_CSUM;
-	} else {
-		if ((priv->dev->mtu <= ETH_DATA_LEN) && (tx_coe)) {
-			priv->hw->dma->dma_mode(priv->dev->base_addr,
-						SF_DMA_MODE, SF_DMA_MODE);
-			tc = SF_DMA_MODE;
-			priv->tx_coe = HW_CSUM;
-		} else {
-			/* Checksum computation is performed in software. */
-			priv->hw->dma->dma_mode(priv->dev->base_addr, tc,
-						SF_DMA_MODE);
-			priv->tx_coe = NO_HW_CSUM;
-		}
-	}
-	tx_coe = priv->tx_coe;
+	if (likely((priv->tx_coe) && (!priv->no_csum_insertion))) {
+		/* In case of GMAC, SF mode has to be enabled
+		 * to perform the TX COE. This depends on:
+		 * 1) TX COE if actually supported
+		 * 2) There is no bugged Jumbo frame support
+		 *    that needs to not insert csum in the TDES.
+		 */
+		priv->hw->dma->dma_mode(priv->ioaddr,
+					SF_DMA_MODE, SF_DMA_MODE);
+		tc = SF_DMA_MODE;
+	} else
+		priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
 }
 
 /**
@@ -600,7 +588,6 @@
 static void stmmac_tx(struct stmmac_priv *priv)
 {
 	unsigned int txsize = priv->dma_tx_size;
-	unsigned long ioaddr = priv->dev->base_addr;
 
 	while (priv->dirty_tx != priv->cur_tx) {
 		int last;
@@ -618,7 +605,7 @@
 			int tx_error =
 				priv->hw->desc->tx_status(&priv->dev->stats,
 							  &priv->xstats, p,
-							  ioaddr);
+							  priv->ioaddr);
 			if (likely(tx_error == 0)) {
 				priv->dev->stats.tx_packets++;
 				priv->xstats.tx_pkt_n++;
@@ -674,7 +661,7 @@
 		priv->tm->timer_start(tmrate);
 	else
 #endif
-		priv->hw->dma->enable_dma_irq(priv->dev->base_addr);
+		priv->hw->dma->enable_dma_irq(priv->ioaddr);
 }
 
 static inline void stmmac_disable_irq(struct stmmac_priv *priv)
@@ -684,7 +671,7 @@
 		priv->tm->timer_stop();
 	else
 #endif
-		priv->hw->dma->disable_dma_irq(priv->dev->base_addr);
+		priv->hw->dma->disable_dma_irq(priv->ioaddr);
 }
 
 static int stmmac_has_work(struct stmmac_priv *priv)
@@ -739,14 +726,15 @@
  */
 static void stmmac_tx_err(struct stmmac_priv *priv)
 {
+
 	netif_stop_queue(priv->dev);
 
-	priv->hw->dma->stop_tx(priv->dev->base_addr);
+	priv->hw->dma->stop_tx(priv->ioaddr);
 	dma_free_tx_skbufs(priv);
 	priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size);
 	priv->dirty_tx = 0;
 	priv->cur_tx = 0;
-	priv->hw->dma->start_tx(priv->dev->base_addr);
+	priv->hw->dma->start_tx(priv->ioaddr);
 
 	priv->dev->stats.tx_errors++;
 	netif_wake_queue(priv->dev);
@@ -755,11 +743,9 @@
 
 static void stmmac_dma_interrupt(struct stmmac_priv *priv)
 {
-	unsigned long ioaddr = priv->dev->base_addr;
 	int status;
 
-	status = priv->hw->dma->dma_interrupt(priv->dev->base_addr,
-					      &priv->xstats);
+	status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
 	if (likely(status == handle_tx_rx))
 		_stmmac_schedule(priv);
 
@@ -767,7 +753,7 @@
 		/* Try to bump up the dma threshold on this failure */
 		if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
 			tc += 64;
-			priv->hw->dma->dma_mode(ioaddr, tc, SF_DMA_MODE);
+			priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
 			priv->xstats.threshold = tc;
 		}
 		stmmac_tx_err(priv);
@@ -787,7 +773,6 @@
 static int stmmac_open(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
 	int ret;
 
 	/* Check that the MAC address is valid.  If its not, refuse
@@ -843,7 +828,8 @@
 	init_dma_desc_rings(dev);
 
 	/* DMA initialization and SW reset */
-	if (unlikely(priv->hw->dma->init(ioaddr, priv->pbl, priv->dma_tx_phy,
+	if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->pbl,
+					 priv->dma_tx_phy,
 					 priv->dma_rx_phy) < 0)) {
 
 		pr_err("%s: DMA initialization failed\n", __func__);
@@ -851,22 +837,28 @@
 	}
 
 	/* Copy the MAC addr into the HW  */
-	priv->hw->mac->set_umac_addr(ioaddr, dev->dev_addr, 0);
+	priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
 	/* If required, perform hw setup of the bus. */
 	if (priv->bus_setup)
-		priv->bus_setup(ioaddr);
+		priv->bus_setup(priv->ioaddr);
 	/* Initialize the MAC Core */
-	priv->hw->mac->core_init(ioaddr);
+	priv->hw->mac->core_init(priv->ioaddr);
+
+	priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
+	if (priv->rx_coe)
+		pr_info("stmmac: Rx Checksum Offload Engine supported\n");
+	if (priv->tx_coe)
+		pr_info("\tTX Checksum insertion supported\n");
 
 	priv->shutdown = 0;
 
 	/* Initialise the MMC (if present) to disable all interrupts. */
-	writel(0xffffffff, ioaddr + MMC_HIGH_INTR_MASK);
-	writel(0xffffffff, ioaddr + MMC_LOW_INTR_MASK);
+	writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK);
+	writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK);
 
 	/* Enable the MAC Rx/Tx */
-	stmmac_mac_enable_rx(ioaddr);
-	stmmac_mac_enable_tx(ioaddr);
+	stmmac_mac_enable_rx(priv->ioaddr);
+	stmmac_mac_enable_tx(priv->ioaddr);
 
 	/* Set the HW DMA mode and the COE */
 	stmmac_dma_operation_mode(priv);
@@ -877,16 +869,16 @@
 
 	/* Start the ball rolling... */
 	DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
-	priv->hw->dma->start_tx(ioaddr);
-	priv->hw->dma->start_rx(ioaddr);
+	priv->hw->dma->start_tx(priv->ioaddr);
+	priv->hw->dma->start_rx(priv->ioaddr);
 
 #ifdef CONFIG_STMMAC_TIMER
 	priv->tm->timer_start(tmrate);
 #endif
 	/* Dump DMA/MAC registers */
 	if (netif_msg_hw(priv)) {
-		priv->hw->mac->dump_regs(ioaddr);
-		priv->hw->dma->dump_regs(ioaddr);
+		priv->hw->mac->dump_regs(priv->ioaddr);
+		priv->hw->dma->dump_regs(priv->ioaddr);
 	}
 
 	if (priv->phydev)
@@ -930,15 +922,15 @@
 	free_irq(dev->irq, dev);
 
 	/* Stop TX/RX DMA and clear the descriptors */
-	priv->hw->dma->stop_tx(dev->base_addr);
-	priv->hw->dma->stop_rx(dev->base_addr);
+	priv->hw->dma->stop_tx(priv->ioaddr);
+	priv->hw->dma->stop_rx(priv->ioaddr);
 
 	/* Release and free the Rx/Tx resources */
 	free_dma_desc_resources(priv);
 
 	/* Disable the MAC core */
-	stmmac_mac_disable_tx(dev->base_addr);
-	stmmac_mac_disable_rx(dev->base_addr);
+	stmmac_mac_disable_tx(priv->ioaddr);
+	stmmac_mac_disable_rx(priv->ioaddr);
 
 	netif_carrier_off(dev);
 
@@ -1066,7 +1058,7 @@
 		return stmmac_sw_tso(priv, skb);
 
 	if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) {
-		if (likely(priv->tx_coe == NO_HW_CSUM))
+		if (unlikely((!priv->tx_coe) || (priv->no_csum_insertion)))
 			skb_checksum_help(skb);
 		else
 			csum_insertion = 1;
@@ -1140,7 +1132,7 @@
 
 	dev->stats.tx_bytes += skb->len;
 
-	priv->hw->dma->enable_dma_transmission(dev->base_addr);
+	priv->hw->dma->enable_dma_transmission(priv->ioaddr);
 
 	return NETDEV_TX_OK;
 }
@@ -1256,7 +1248,7 @@
 
 			if (unlikely(status == csum_none)) {
 				/* always for the old mac 10/100 */
-				skb->ip_summed = CHECKSUM_NONE;
+				skb_checksum_none_assert(skb);
 				netif_receive_skb(skb);
 			} else {
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1390,6 +1382,15 @@
 		return -EINVAL;
 	}
 
+	/* Some GMAC devices have a bugged Jumbo frame support that
+	 * needs to have the Tx COE disabled for oversized frames
+	 * (due to limited buffer sizes). In this case we disable
+	 * the TX csum insertionin the TDES and not use SF. */
+	if ((priv->bugged_jumbo) && (priv->dev->mtu > ETH_DATA_LEN))
+		priv->no_csum_insertion = 1;
+	else
+		priv->no_csum_insertion = 0;
+
 	dev->mtu = new_mtu;
 
 	return 0;
@@ -1405,11 +1406,9 @@
 		return IRQ_NONE;
 	}
 
-	if (priv->is_gmac) {
-		unsigned long ioaddr = dev->base_addr;
+	if (priv->is_gmac)
 		/* To handle GMAC own interrupts */
-		priv->hw->mac->host_irq_status(ioaddr);
-	}
+		priv->hw->mac->host_irq_status((void __iomem *) dev->base_addr);
 
 	stmmac_dma_interrupt(priv);
 
@@ -1512,9 +1511,6 @@
 #endif
 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
 
-	if (priv->is_gmac)
-		priv->rx_csum = 1;
-
 	if (flow_ctrl)
 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
 
@@ -1522,7 +1518,8 @@
 	netif_napi_add(dev, &priv->napi, stmmac_poll, 64);
 
 	/* Get the MAC address */
-	priv->hw->mac->get_umac_addr(dev->base_addr, dev->dev_addr, 0);
+	priv->hw->mac->get_umac_addr((void __iomem *) dev->base_addr,
+				     dev->dev_addr, 0);
 
 	if (!is_valid_ether_addr(dev->dev_addr))
 		pr_warning("\tno valid MAC address;"
@@ -1552,14 +1549,13 @@
 static int stmmac_mac_device_setup(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
 
 	struct mac_device_info *device;
 
 	if (priv->is_gmac)
-		device = dwmac1000_setup(ioaddr);
+		device = dwmac1000_setup(priv->ioaddr);
 	else
-		device = dwmac100_setup(ioaddr);
+		device = dwmac100_setup(priv->ioaddr);
 
 	if (!device)
 		return -ENOMEM;
@@ -1572,9 +1568,8 @@
 
 	priv->hw = device;
 
-	priv->wolenabled = priv->hw->pmt;	/* PMT supported */
-	if (priv->wolenabled == PMT_SUPPORTED)
-		priv->wolopts = WAKE_MAGIC;		/* Magic Frame */
+	if (device_can_wakeup(priv->device))
+		priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
 
 	return 0;
 }
@@ -1653,7 +1648,7 @@
 {
 	int ret = 0;
 	struct resource *res;
-	unsigned int *addr = NULL;
+	void __iomem *addr = NULL;
 	struct net_device *ndev = NULL;
 	struct stmmac_priv *priv;
 	struct plat_stmmacenet_data *plat_dat;
@@ -1664,7 +1659,7 @@
 		ret = -ENODEV;
 		goto out;
 	}
-	pr_info("done!\n");
+	pr_info("\tdone!\n");
 
 	if (!request_mem_region(res->start, resource_size(res),
 				pdev->name)) {
@@ -1706,8 +1701,18 @@
 	plat_dat = pdev->dev.platform_data;
 	priv->bus_id = plat_dat->bus_id;
 	priv->pbl = plat_dat->pbl;	/* TLI */
+	priv->mii_clk_csr = plat_dat->clk_csr;
+	priv->tx_coe = plat_dat->tx_coe;
+	priv->bugged_jumbo = plat_dat->bugged_jumbo;
 	priv->is_gmac = plat_dat->has_gmac;	/* GMAC is on board */
 	priv->enh_desc = plat_dat->enh_desc;
+	priv->ioaddr = addr;
+
+	/* PMT module is not integrated in all the MAC devices. */
+	if (plat_dat->pmt) {
+		pr_info("\tPMT module supported\n");
+		device_set_wakeup_capable(&pdev->dev, 1);
+	}
 
 	platform_set_drvdata(pdev, ndev);
 
@@ -1743,8 +1748,8 @@
 	priv->bsp_priv = plat_dat->bsp_priv;
 
 	pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n"
-	       "\tIO base addr: 0x%08x)\n", ndev->name, pdev->name,
-	       pdev->id, ndev->irq, (unsigned int)addr);
+	       "\tIO base addr: 0x%p)\n", ndev->name, pdev->name,
+	       pdev->id, ndev->irq, addr);
 
 	/* MDIO bus Registration */
 	pr_debug("\tMDIO bus (id: %d)...", priv->bus_id);
@@ -1779,11 +1784,11 @@
 
 	pr_info("%s:\n\tremoving driver", __func__);
 
-	priv->hw->dma->stop_rx(ndev->base_addr);
-	priv->hw->dma->stop_tx(ndev->base_addr);
+	priv->hw->dma->stop_rx(priv->ioaddr);
+	priv->hw->dma->stop_tx(priv->ioaddr);
 
-	stmmac_mac_disable_rx(ndev->base_addr);
-	stmmac_mac_disable_tx(ndev->base_addr);
+	stmmac_mac_disable_rx(priv->ioaddr);
+	stmmac_mac_disable_tx(priv->ioaddr);
 
 	netif_carrier_off(ndev);
 
@@ -1792,7 +1797,7 @@
 	platform_set_drvdata(pdev, NULL);
 	unregister_netdev(ndev);
 
-	iounmap((void *)ndev->base_addr);
+	iounmap((void *)priv->ioaddr);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(res->start, resource_size(res));
 
@@ -1827,23 +1832,20 @@
 		napi_disable(&priv->napi);
 
 		/* Stop TX/RX DMA */
-		priv->hw->dma->stop_tx(dev->base_addr);
-		priv->hw->dma->stop_rx(dev->base_addr);
+		priv->hw->dma->stop_tx(priv->ioaddr);
+		priv->hw->dma->stop_rx(priv->ioaddr);
 		/* Clear the Rx/Tx descriptors */
 		priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size,
 					     dis_ic);
 		priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size);
 
-		stmmac_mac_disable_tx(dev->base_addr);
+		stmmac_mac_disable_tx(priv->ioaddr);
 
-		if (device_may_wakeup(&(pdev->dev))) {
-			/* Enable Power down mode by programming the PMT regs */
-			if (priv->wolenabled == PMT_SUPPORTED)
-				priv->hw->mac->pmt(dev->base_addr,
-						   priv->wolopts);
-		} else {
-			stmmac_mac_disable_rx(dev->base_addr);
-		}
+		/* Enable Power down mode by programming the PMT regs */
+		if (device_can_wakeup(priv->device))
+			priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
+		else
+			stmmac_mac_disable_rx(priv->ioaddr);
 	} else {
 		priv->shutdown = 1;
 		/* Although this can appear slightly redundant it actually
@@ -1860,7 +1862,6 @@
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
 	struct stmmac_priv *priv = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
 
 	if (!netif_running(dev))
 		return 0;
@@ -1879,17 +1880,16 @@
 	 * is received. Anyway, it's better to manually clear
 	 * this bit because it can generate problems while resuming
 	 * from another devices (e.g. serial console). */
-	if (device_may_wakeup(&(pdev->dev)))
-		if (priv->wolenabled == PMT_SUPPORTED)
-			priv->hw->mac->pmt(dev->base_addr, 0);
+	if (device_can_wakeup(priv->device))
+		priv->hw->mac->pmt(priv->ioaddr, 0);
 
 	netif_device_attach(dev);
 
 	/* Enable the MAC and DMA */
-	stmmac_mac_enable_rx(ioaddr);
-	stmmac_mac_enable_tx(ioaddr);
-	priv->hw->dma->start_tx(ioaddr);
-	priv->hw->dma->start_rx(ioaddr);
+	stmmac_mac_enable_rx(priv->ioaddr);
+	stmmac_mac_enable_tx(priv->ioaddr);
+	priv->hw->dma->start_tx(priv->ioaddr);
+	priv->hw->dma->start_rx(priv->ioaddr);
 
 #ifdef CONFIG_STMMAC_TIMER
 	priv->tm->timer_start(tmrate);
@@ -1968,8 +1968,6 @@
 			strict_strtoul(opt + 7, 0, (unsigned long *)&buf_sz);
 		else if (!strncmp(opt, "tc:", 3))
 			strict_strtoul(opt + 3, 0, (unsigned long *)&tc);
-		else if (!strncmp(opt, "tx_coe:", 7))
-			strict_strtoul(opt + 7, 0, (unsigned long *)&tx_coe);
 		else if (!strncmp(opt, "watchdog:", 9))
 			strict_strtoul(opt + 9, 0, (unsigned long *)&watchdog);
 		else if (!strncmp(opt, "flow_ctrl:", 10))
diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/stmmac/stmmac_mdio.c
index 40b2c79..d744161 100644
--- a/drivers/net/stmmac/stmmac_mdio.c
+++ b/drivers/net/stmmac/stmmac_mdio.c
@@ -47,21 +47,20 @@
 {
 	struct net_device *ndev = bus->priv;
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	unsigned long ioaddr = ndev->base_addr;
 	unsigned int mii_address = priv->hw->mii.addr;
 	unsigned int mii_data = priv->hw->mii.data;
 
 	int data;
 	u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
 			((phyreg << 6) & (0x000007C0)));
-	regValue |= MII_BUSY;	/* in case of GMAC */
+	regValue |= MII_BUSY | ((priv->mii_clk_csr & 7) << 2);
 
-	do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
-	writel(regValue, ioaddr + mii_address);
-	do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
+	do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
+	writel(regValue, priv->ioaddr + mii_address);
+	do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
 
 	/* Read the data from the MII data register */
-	data = (int)readl(ioaddr + mii_data);
+	data = (int)readl(priv->ioaddr + mii_data);
 
 	return data;
 }
@@ -79,7 +78,6 @@
 {
 	struct net_device *ndev = bus->priv;
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	unsigned long ioaddr = ndev->base_addr;
 	unsigned int mii_address = priv->hw->mii.addr;
 	unsigned int mii_data = priv->hw->mii.data;
 
@@ -87,17 +85,18 @@
 	    (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
 	    | MII_WRITE;
 
-	value |= MII_BUSY;
+	value |= MII_BUSY | ((priv->mii_clk_csr & 7) << 2);
+
 
 	/* Wait until any existing MII operation is complete */
-	do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
+	do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
 
 	/* Set the MII address register to write */
-	writel(phydata, ioaddr + mii_data);
-	writel(value, ioaddr + mii_address);
+	writel(phydata, priv->ioaddr + mii_data);
+	writel(value, priv->ioaddr + mii_address);
 
 	/* Wait until any existing MII operation is complete */
-	do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
+	do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
 
 	return 0;
 }
@@ -111,7 +110,6 @@
 {
 	struct net_device *ndev = bus->priv;
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	unsigned long ioaddr = ndev->base_addr;
 	unsigned int mii_address = priv->hw->mii.addr;
 
 	if (priv->phy_reset) {
@@ -123,7 +121,7 @@
 	 * It doesn't complete its reset until at least one clock cycle
 	 * on MDC, so perform a dummy mdio read.
 	 */
-	writel(0, ioaddr + mii_address);
+	writel(0, priv->ioaddr + mii_address);
 
 	return 0;
 }
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 358c22f..7d9ec23 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -436,7 +436,7 @@
 		DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",
 					  dev->name, i, DREG ));
 		DREG = CSR0_STOP;
-		return( -EIO );
+		return -EIO;
 	}
 
 	DREG = CSR0_IDON | CSR0_STRT | CSR0_INEA;
@@ -445,7 +445,7 @@
 
 	DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
 
-	return( 0 );
+	return 0;
 }
 
 
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 618643e..0a6a5ce 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -617,7 +617,7 @@
 	bp->timer_ticks = 0;
 	bp->bigmac_timer.expires = jiffies + (12 * HZ) / 10;
 	bp->bigmac_timer.data = (unsigned long) bp;
-	bp->bigmac_timer.function = &bigmac_timer;
+	bp->bigmac_timer.function = bigmac_timer;
 	add_timer(&bp->bigmac_timer);
 }
 
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 2678588..3ed2a67 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -96,16 +96,10 @@
 #include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
-#ifndef _COMPAT_WITH_OLD_KERNEL
+#include <linux/dma-mapping.h>
 #include <linux/crc32.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
-#else
-#include "crc32.h"
-#include "ethtool.h"
-#include "mii.h"
-#include "compat.h"
-#endif
 
 /* These identify the driver base version and may not be removed. */
 static const char version[] __devinitconst =
@@ -369,9 +363,21 @@
         dma_addr_t tx_ring_dma;
         dma_addr_t rx_ring_dma;
 	struct timer_list timer;		/* Media monitoring timer. */
+	/* ethtool extra stats */
+	struct {
+		u64 tx_multiple_collisions;
+		u64 tx_single_collisions;
+		u64 tx_late_collisions;
+		u64 tx_deferred;
+		u64 tx_deferred_excessive;
+		u64 tx_aborted;
+		u64 tx_bcasts;
+		u64 rx_bcasts;
+		u64 tx_mcasts;
+		u64 rx_mcasts;
+	} xstats;
 	/* Frequently used values: keep some adjacent for cache effect. */
 	spinlock_t lock;
-	spinlock_t rx_lock;			/* Group with Tx control cache line. */
 	int msg_enable;
 	int chip_id;
 	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */
@@ -396,6 +402,7 @@
 	unsigned char phys[MII_CNT];		/* MII device addresses, only first one used. */
 	struct pci_dev *pci_dev;
 	void __iomem *base;
+	spinlock_t statlock;
 };
 
 /* The station address location in the EEPROM. */
@@ -520,16 +527,19 @@
 	np->chip_id = chip_idx;
 	np->msg_enable = (1 << debug) - 1;
 	spin_lock_init(&np->lock);
+	spin_lock_init(&np->statlock);
 	tasklet_init(&np->rx_tasklet, rx_poll, (unsigned long)dev);
 	tasklet_init(&np->tx_tasklet, tx_poll, (unsigned long)dev);
 
-	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
+	ring_space = dma_alloc_coherent(&pdev->dev, TX_TOTAL_SIZE,
+			&ring_dma, GFP_KERNEL);
 	if (!ring_space)
 		goto err_out_cleardev;
 	np->tx_ring = (struct netdev_desc *)ring_space;
 	np->tx_ring_dma = ring_dma;
 
-	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
+	ring_space = dma_alloc_coherent(&pdev->dev, RX_TOTAL_SIZE,
+			&ring_dma, GFP_KERNEL);
 	if (!ring_space)
 		goto err_out_unmap_tx;
 	np->rx_ring = (struct netdev_desc *)ring_space;
@@ -663,9 +673,11 @@
 err_out_unregister:
 	unregister_netdev(dev);
 err_out_unmap_rx:
-        pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);
+	dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE,
+		np->rx_ring, np->rx_ring_dma);
 err_out_unmap_tx:
-        pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);
+	dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE,
+		np->tx_ring, np->tx_ring_dma);
 err_out_cleardev:
 	pci_set_drvdata(pdev, NULL);
 	pci_iounmap(pdev, ioaddr);
@@ -874,7 +886,7 @@
 	init_timer(&np->timer);
 	np->timer.expires = jiffies + 3*HZ;
 	np->timer.data = (unsigned long)dev;
-	np->timer.function = &netdev_timer;				/* timer handler */
+	np->timer.function = netdev_timer;				/* timer handler */
 	add_timer(&np->timer);
 
 	/* Enable interrupts by setting the interrupt mask. */
@@ -1011,8 +1023,14 @@
 		skb->dev = dev;		/* Mark as being used by this device. */
 		skb_reserve(skb, 2);	/* 16 byte align the IP header. */
 		np->rx_ring[i].frag[0].addr = cpu_to_le32(
-			pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz,
-				PCI_DMA_FROMDEVICE));
+			dma_map_single(&np->pci_dev->dev, skb->data,
+				np->rx_buf_sz, DMA_FROM_DEVICE));
+		if (dma_mapping_error(&np->pci_dev->dev,
+					np->rx_ring[i].frag[0].addr)) {
+			dev_kfree_skb(skb);
+			np->rx_skbuff[i] = NULL;
+			break;
+		}
 		np->rx_ring[i].frag[0].length = cpu_to_le32(np->rx_buf_sz | LastFrag);
 	}
 	np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
@@ -1063,9 +1081,11 @@
 
 	txdesc->next_desc = 0;
 	txdesc->status = cpu_to_le32 ((entry << 2) | DisableAlign);
-	txdesc->frag[0].addr = cpu_to_le32 (pci_map_single (np->pci_dev, skb->data,
-							skb->len,
-							PCI_DMA_TODEVICE));
+	txdesc->frag[0].addr = cpu_to_le32(dma_map_single(&np->pci_dev->dev,
+				skb->data, skb->len, DMA_TO_DEVICE));
+	if (dma_mapping_error(&np->pci_dev->dev,
+				txdesc->frag[0].addr))
+			goto drop_frame;
 	txdesc->frag[0].length = cpu_to_le32 (skb->len | LastFrag);
 
 	/* Increment cur_tx before tasklet_schedule() */
@@ -1087,6 +1107,12 @@
 			dev->name, np->cur_tx, entry);
 	}
 	return NETDEV_TX_OK;
+
+drop_frame:
+	dev_kfree_skb(skb);
+	np->tx_skbuff[entry] = NULL;
+	dev->stats.tx_dropped++;
+	return NETDEV_TX_OK;
 }
 
 /* Reset hardware tx and free all of tx buffers */
@@ -1097,7 +1123,6 @@
 	void __iomem *ioaddr = np->base;
 	struct sk_buff *skb;
 	int i;
-	int irq = in_interrupt();
 
 	/* Reset tx logic, TxListPtr will be cleaned */
 	iowrite16 (TxDisable, ioaddr + MACCtrl1);
@@ -1109,13 +1134,10 @@
 
 		skb = np->tx_skbuff[i];
 		if (skb) {
-			pci_unmap_single(np->pci_dev,
+			dma_unmap_single(&np->pci_dev->dev,
 				le32_to_cpu(np->tx_ring[i].frag[0].addr),
-				skb->len, PCI_DMA_TODEVICE);
-			if (irq)
-				dev_kfree_skb_irq (skb);
-			else
-				dev_kfree_skb (skb);
+				skb->len, DMA_TO_DEVICE);
+			dev_kfree_skb_any(skb);
 			np->tx_skbuff[i] = NULL;
 			dev->stats.tx_dropped++;
 		}
@@ -1233,9 +1255,9 @@
 						break;
 				skb = np->tx_skbuff[entry];
 				/* Free the original skb. */
-				pci_unmap_single(np->pci_dev,
+				dma_unmap_single(&np->pci_dev->dev,
 					le32_to_cpu(np->tx_ring[entry].frag[0].addr),
-					skb->len, PCI_DMA_TODEVICE);
+					skb->len, DMA_TO_DEVICE);
 				dev_kfree_skb_irq (np->tx_skbuff[entry]);
 				np->tx_skbuff[entry] = NULL;
 				np->tx_ring[entry].frag[0].addr = 0;
@@ -1252,9 +1274,9 @@
 					break;
 				skb = np->tx_skbuff[entry];
 				/* Free the original skb. */
-				pci_unmap_single(np->pci_dev,
+				dma_unmap_single(&np->pci_dev->dev,
 					le32_to_cpu(np->tx_ring[entry].frag[0].addr),
-					skb->len, PCI_DMA_TODEVICE);
+					skb->len, DMA_TO_DEVICE);
 				dev_kfree_skb_irq (np->tx_skbuff[entry]);
 				np->tx_skbuff[entry] = NULL;
 				np->tx_ring[entry].frag[0].addr = 0;
@@ -1334,22 +1356,18 @@
 			if (pkt_len < rx_copybreak &&
 			    (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
 				skb_reserve(skb, 2);	/* 16 byte align the IP header */
-				pci_dma_sync_single_for_cpu(np->pci_dev,
-							    le32_to_cpu(desc->frag[0].addr),
-							    np->rx_buf_sz,
-							    PCI_DMA_FROMDEVICE);
-
+				dma_sync_single_for_cpu(&np->pci_dev->dev,
+						le32_to_cpu(desc->frag[0].addr),
+						np->rx_buf_sz, DMA_FROM_DEVICE);
 				skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
-				pci_dma_sync_single_for_device(np->pci_dev,
-							       le32_to_cpu(desc->frag[0].addr),
-							       np->rx_buf_sz,
-							       PCI_DMA_FROMDEVICE);
+				dma_sync_single_for_device(&np->pci_dev->dev,
+						le32_to_cpu(desc->frag[0].addr),
+						np->rx_buf_sz, DMA_FROM_DEVICE);
 				skb_put(skb, pkt_len);
 			} else {
-				pci_unmap_single(np->pci_dev,
+				dma_unmap_single(&np->pci_dev->dev,
 					le32_to_cpu(desc->frag[0].addr),
-					np->rx_buf_sz,
-					PCI_DMA_FROMDEVICE);
+					np->rx_buf_sz, DMA_FROM_DEVICE);
 				skb_put(skb = np->rx_skbuff[entry], pkt_len);
 				np->rx_skbuff[entry] = NULL;
 			}
@@ -1396,8 +1414,14 @@
 			skb->dev = dev;		/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
 			np->rx_ring[entry].frag[0].addr = cpu_to_le32(
-				pci_map_single(np->pci_dev, skb->data,
-					np->rx_buf_sz, PCI_DMA_FROMDEVICE));
+				dma_map_single(&np->pci_dev->dev, skb->data,
+					np->rx_buf_sz, DMA_FROM_DEVICE));
+			if (dma_mapping_error(&np->pci_dev->dev,
+				    np->rx_ring[entry].frag[0].addr)) {
+			    dev_kfree_skb_irq(skb);
+			    np->rx_skbuff[entry] = NULL;
+			    break;
+			}
 		}
 		/* Perhaps we need not reset this field. */
 		np->rx_ring[entry].frag[0].length =
@@ -1475,27 +1499,41 @@
 {
 	struct netdev_private *np = netdev_priv(dev);
 	void __iomem *ioaddr = np->base;
-	int i;
+	unsigned long flags;
+	u8 late_coll, single_coll, mult_coll;
 
-	/* We should lock this segment of code for SMP eventually, although
-	   the vulnerability window is very small and statistics are
-	   non-critical. */
+	spin_lock_irqsave(&np->statlock, flags);
 	/* The chip only need report frame silently dropped. */
 	dev->stats.rx_missed_errors	+= ioread8(ioaddr + RxMissed);
 	dev->stats.tx_packets += ioread16(ioaddr + TxFramesOK);
 	dev->stats.rx_packets += ioread16(ioaddr + RxFramesOK);
-	dev->stats.collisions += ioread8(ioaddr + StatsLateColl);
-	dev->stats.collisions += ioread8(ioaddr + StatsMultiColl);
-	dev->stats.collisions += ioread8(ioaddr + StatsOneColl);
 	dev->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError);
-	ioread8(ioaddr + StatsTxDefer);
-	for (i = StatsTxDefer; i <= StatsMcastRx; i++)
-		ioread8(ioaddr + i);
+
+	mult_coll = ioread8(ioaddr + StatsMultiColl);
+	np->xstats.tx_multiple_collisions += mult_coll;
+	single_coll = ioread8(ioaddr + StatsOneColl);
+	np->xstats.tx_single_collisions += single_coll;
+	late_coll = ioread8(ioaddr + StatsLateColl);
+	np->xstats.tx_late_collisions += late_coll;
+	dev->stats.collisions += mult_coll
+		+ single_coll
+		+ late_coll;
+
+	np->xstats.tx_deferred += ioread8(ioaddr + StatsTxDefer);
+	np->xstats.tx_deferred_excessive += ioread8(ioaddr + StatsTxXSDefer);
+	np->xstats.tx_aborted += ioread8(ioaddr + StatsTxAbort);
+	np->xstats.tx_bcasts += ioread8(ioaddr + StatsBcastTx);
+	np->xstats.rx_bcasts += ioread8(ioaddr + StatsBcastRx);
+	np->xstats.tx_mcasts += ioread8(ioaddr + StatsMcastTx);
+	np->xstats.rx_mcasts += ioread8(ioaddr + StatsMcastRx);
+
 	dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow);
 	dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16;
 	dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow);
 	dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsHigh) << 16;
 
+	spin_unlock_irqrestore(&np->statlock, flags);
+
 	return &dev->stats;
 }
 
@@ -1554,6 +1592,21 @@
 	return 0;
 }
 
+static const struct {
+	const char name[ETH_GSTRING_LEN];
+} sundance_stats[] = {
+	{ "tx_multiple_collisions" },
+	{ "tx_single_collisions" },
+	{ "tx_late_collisions" },
+	{ "tx_deferred" },
+	{ "tx_deferred_excessive" },
+	{ "tx_aborted" },
+	{ "tx_bcasts" },
+	{ "rx_bcasts" },
+	{ "tx_mcasts" },
+	{ "rx_mcasts" },
+};
+
 static int check_if_running(struct net_device *dev)
 {
 	if (!netif_running(dev))
@@ -1612,6 +1665,42 @@
 	np->msg_enable = val;
 }
 
+static void get_strings(struct net_device *dev, u32 stringset,
+		u8 *data)
+{
+	if (stringset == ETH_SS_STATS)
+		memcpy(data, sundance_stats, sizeof(sundance_stats));
+}
+
+static int get_sset_count(struct net_device *dev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return ARRAY_SIZE(sundance_stats);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void get_ethtool_stats(struct net_device *dev,
+		struct ethtool_stats *stats, u64 *data)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	int i = 0;
+
+	get_stats(dev);
+	data[i++] = np->xstats.tx_multiple_collisions;
+	data[i++] = np->xstats.tx_single_collisions;
+	data[i++] = np->xstats.tx_late_collisions;
+	data[i++] = np->xstats.tx_deferred;
+	data[i++] = np->xstats.tx_deferred_excessive;
+	data[i++] = np->xstats.tx_aborted;
+	data[i++] = np->xstats.tx_bcasts;
+	data[i++] = np->xstats.rx_bcasts;
+	data[i++] = np->xstats.tx_mcasts;
+	data[i++] = np->xstats.rx_mcasts;
+}
+
 static const struct ethtool_ops ethtool_ops = {
 	.begin = check_if_running,
 	.get_drvinfo = get_drvinfo,
@@ -1621,6 +1710,9 @@
 	.get_link = get_link,
 	.get_msglevel = get_msglevel,
 	.set_msglevel = set_msglevel,
+	.get_strings = get_strings,
+	.get_sset_count = get_sset_count,
+	.get_ethtool_stats = get_ethtool_stats,
 };
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1715,9 +1807,9 @@
 		np->rx_ring[i].status = 0;
 		skb = np->rx_skbuff[i];
 		if (skb) {
-			pci_unmap_single(np->pci_dev,
+			dma_unmap_single(&np->pci_dev->dev,
 				le32_to_cpu(np->rx_ring[i].frag[0].addr),
-				np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+				np->rx_buf_sz, DMA_FROM_DEVICE);
 			dev_kfree_skb(skb);
 			np->rx_skbuff[i] = NULL;
 		}
@@ -1727,9 +1819,9 @@
 		np->tx_ring[i].next_desc = 0;
 		skb = np->tx_skbuff[i];
 		if (skb) {
-			pci_unmap_single(np->pci_dev,
+			dma_unmap_single(&np->pci_dev->dev,
 				le32_to_cpu(np->tx_ring[i].frag[0].addr),
-				skb->len, PCI_DMA_TODEVICE);
+				skb->len, DMA_TO_DEVICE);
 			dev_kfree_skb(skb);
 			np->tx_skbuff[i] = NULL;
 		}
@@ -1743,25 +1835,72 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 
 	if (dev) {
-		struct netdev_private *np = netdev_priv(dev);
-
-		unregister_netdev(dev);
-        	pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring,
-			np->rx_ring_dma);
-	        pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring,
-			np->tx_ring_dma);
-		pci_iounmap(pdev, np->base);
-		pci_release_regions(pdev);
-		free_netdev(dev);
-		pci_set_drvdata(pdev, NULL);
+	    struct netdev_private *np = netdev_priv(dev);
+	    unregister_netdev(dev);
+	    dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE,
+		    np->rx_ring, np->rx_ring_dma);
+	    dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE,
+		    np->tx_ring, np->tx_ring_dma);
+	    pci_iounmap(pdev, np->base);
+	    pci_release_regions(pdev);
+	    free_netdev(dev);
+	    pci_set_drvdata(pdev, NULL);
 	}
 }
 
+#ifdef CONFIG_PM
+
+static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state)
+{
+	struct net_device *dev = pci_get_drvdata(pci_dev);
+
+	if (!netif_running(dev))
+		return 0;
+
+	netdev_close(dev);
+	netif_device_detach(dev);
+
+	pci_save_state(pci_dev);
+	pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
+
+	return 0;
+}
+
+static int sundance_resume(struct pci_dev *pci_dev)
+{
+	struct net_device *dev = pci_get_drvdata(pci_dev);
+	int err = 0;
+
+	if (!netif_running(dev))
+		return 0;
+
+	pci_set_power_state(pci_dev, PCI_D0);
+	pci_restore_state(pci_dev);
+
+	err = netdev_open(dev);
+	if (err) {
+		printk(KERN_ERR "%s: Can't resume interface!\n",
+				dev->name);
+		goto out;
+	}
+
+	netif_device_attach(dev);
+
+out:
+	return err;
+}
+
+#endif /* CONFIG_PM */
+
 static struct pci_driver sundance_driver = {
 	.name		= DRV_NAME,
 	.id_table	= sundance_pci_tbl,
 	.probe		= sundance_probe1,
 	.remove		= __devexit_p(sundance_remove1),
+#ifdef CONFIG_PM
+	.suspend	= sundance_suspend,
+	.resume		= sundance_resume,
+#endif /* CONFIG_PM */
 };
 
 static int __init sundance_init(void)
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 434f9d7..4ceb3cf 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -31,6 +31,8 @@
  *    about when we can start taking interrupts or get xmit() called...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -105,7 +107,6 @@
 MODULE_LICENSE("GPL");
 
 #define GEM_MODULE_NAME	"gem"
-#define PFX GEM_MODULE_NAME ": "
 
 static DEFINE_PCI_DEVICE_TABLE(gem_pci_tbl) = {
 	{ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_GEM,
@@ -262,8 +263,7 @@
 			gp->dev->name, pcs_istat);
 
 	if (!(pcs_istat & PCS_ISTAT_LSC)) {
-		printk(KERN_ERR "%s: PCS irq but no link status change???\n",
-		       dev->name);
+		netdev_err(dev, "PCS irq but no link status change???\n");
 		return 0;
 	}
 
@@ -282,20 +282,16 @@
 		 * when autoneg has completed.
 		 */
 		if (pcs_miistat & PCS_MIISTAT_RF)
-			printk(KERN_INFO "%s: PCS AutoNEG complete, "
-			       "RemoteFault\n", dev->name);
+			netdev_info(dev, "PCS AutoNEG complete, RemoteFault\n");
 		else
-			printk(KERN_INFO "%s: PCS AutoNEG complete.\n",
-			       dev->name);
+			netdev_info(dev, "PCS AutoNEG complete\n");
 	}
 
 	if (pcs_miistat & PCS_MIISTAT_LS) {
-		printk(KERN_INFO "%s: PCS link is now up.\n",
-		       dev->name);
+		netdev_info(dev, "PCS link is now up\n");
 		netif_carrier_on(gp->dev);
 	} else {
-		printk(KERN_INFO "%s: PCS link is now down.\n",
-		       dev->name);
+		netdev_info(dev, "PCS link is now down\n");
 		netif_carrier_off(gp->dev);
 		/* If this happens and the link timer is not running,
 		 * reset so we re-negotiate.
@@ -323,14 +319,12 @@
 		return 0;
 
 	if (txmac_stat & MAC_TXSTAT_URUN) {
-		printk(KERN_ERR "%s: TX MAC xmit underrun.\n",
-		       dev->name);
+		netdev_err(dev, "TX MAC xmit underrun\n");
 		gp->net_stats.tx_fifo_errors++;
 	}
 
 	if (txmac_stat & MAC_TXSTAT_MPE) {
-		printk(KERN_ERR "%s: TX MAC max packet size error.\n",
-		       dev->name);
+		netdev_err(dev, "TX MAC max packet size error\n");
 		gp->net_stats.tx_errors++;
 	}
 
@@ -377,8 +371,7 @@
 		udelay(10);
 	}
 	if (limit == 5000) {
-		printk(KERN_ERR "%s: RX MAC will not reset, resetting whole "
-                       "chip.\n", dev->name);
+		netdev_err(dev, "RX MAC will not reset, resetting whole chip\n");
 		return 1;
 	}
 
@@ -390,8 +383,7 @@
 		udelay(10);
 	}
 	if (limit == 5000) {
-		printk(KERN_ERR "%s: RX MAC will not disable, resetting whole "
-		       "chip.\n", dev->name);
+		netdev_err(dev, "RX MAC will not disable, resetting whole chip\n");
 		return 1;
 	}
 
@@ -403,8 +395,7 @@
 		udelay(10);
 	}
 	if (limit == 5000) {
-		printk(KERN_ERR "%s: RX DMA will not disable, resetting whole "
-		       "chip.\n", dev->name);
+		netdev_err(dev, "RX DMA will not disable, resetting whole chip\n");
 		return 1;
 	}
 
@@ -419,8 +410,7 @@
 		udelay(10);
 	}
 	if (limit == 5000) {
-		printk(KERN_ERR "%s: RX reset command will not execute, resetting "
-		       "whole chip.\n", dev->name);
+		netdev_err(dev, "RX reset command will not execute, resetting whole chip\n");
 		return 1;
 	}
 
@@ -429,8 +419,7 @@
 		struct gem_rxd *rxd = &gp->init_block->rxd[i];
 
 		if (gp->rx_skbs[i] == NULL) {
-			printk(KERN_ERR "%s: Parts of RX ring empty, resetting "
-			       "whole chip.\n", dev->name);
+			netdev_err(dev, "Parts of RX ring empty, resetting whole chip\n");
 			return 1;
 		}
 
@@ -479,8 +468,7 @@
 	if (rxmac_stat & MAC_RXSTAT_OFLW) {
 		u32 smac = readl(gp->regs + MAC_SMACHINE);
 
-		printk(KERN_ERR "%s: RX MAC fifo overflow smac[%08x].\n",
-				dev->name, smac);
+		netdev_err(dev, "RX MAC fifo overflow smac[%08x]\n", smac);
 		gp->net_stats.rx_over_errors++;
 		gp->net_stats.rx_fifo_errors++;
 
@@ -542,19 +530,18 @@
 
 	if (gp->pdev->vendor == PCI_VENDOR_ID_SUN &&
 	    gp->pdev->device == PCI_DEVICE_ID_SUN_GEM) {
-		printk(KERN_ERR "%s: PCI error [%04x] ",
-		       dev->name, pci_estat);
+		netdev_err(dev, "PCI error [%04x]", pci_estat);
 
 		if (pci_estat & GREG_PCIESTAT_BADACK)
-			printk("<No ACK64# during ABS64 cycle> ");
+			pr_cont(" <No ACK64# during ABS64 cycle>");
 		if (pci_estat & GREG_PCIESTAT_DTRTO)
-			printk("<Delayed transaction timeout> ");
+			pr_cont(" <Delayed transaction timeout>");
 		if (pci_estat & GREG_PCIESTAT_OTHER)
-			printk("<other>");
-		printk("\n");
+			pr_cont(" <other>");
+		pr_cont("\n");
 	} else {
 		pci_estat |= GREG_PCIESTAT_OTHER;
-		printk(KERN_ERR "%s: PCI error\n", dev->name);
+		netdev_err(dev, "PCI error\n");
 	}
 
 	if (pci_estat & GREG_PCIESTAT_OTHER) {
@@ -565,26 +552,20 @@
 		 */
 		pci_read_config_word(gp->pdev, PCI_STATUS,
 				     &pci_cfg_stat);
-		printk(KERN_ERR "%s: Read PCI cfg space status [%04x]\n",
-		       dev->name, pci_cfg_stat);
+		netdev_err(dev, "Read PCI cfg space status [%04x]\n",
+			   pci_cfg_stat);
 		if (pci_cfg_stat & PCI_STATUS_PARITY)
-			printk(KERN_ERR "%s: PCI parity error detected.\n",
-			       dev->name);
+			netdev_err(dev, "PCI parity error detected\n");
 		if (pci_cfg_stat & PCI_STATUS_SIG_TARGET_ABORT)
-			printk(KERN_ERR "%s: PCI target abort.\n",
-			       dev->name);
+			netdev_err(dev, "PCI target abort\n");
 		if (pci_cfg_stat & PCI_STATUS_REC_TARGET_ABORT)
-			printk(KERN_ERR "%s: PCI master acks target abort.\n",
-			       dev->name);
+			netdev_err(dev, "PCI master acks target abort\n");
 		if (pci_cfg_stat & PCI_STATUS_REC_MASTER_ABORT)
-			printk(KERN_ERR "%s: PCI master abort.\n",
-			       dev->name);
+			netdev_err(dev, "PCI master abort\n");
 		if (pci_cfg_stat & PCI_STATUS_SIG_SYSTEM_ERROR)
-			printk(KERN_ERR "%s: PCI system error SERR#.\n",
-			       dev->name);
+			netdev_err(dev, "PCI system error SERR#\n");
 		if (pci_cfg_stat & PCI_STATUS_DETECTED_PARITY)
-			printk(KERN_ERR "%s: PCI parity error.\n",
-			       dev->name);
+			netdev_err(dev, "PCI parity error\n");
 
 		/* Write the error bits back to clear them. */
 		pci_cfg_stat &= (PCI_STATUS_PARITY |
@@ -874,8 +855,7 @@
 	gp->rx_new = entry;
 
 	if (drops)
-		printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
-		       gp->dev->name);
+		netdev_info(gp->dev, "Memory squeeze, deferring packet\n");
 
 	return work_done;
 }
@@ -981,21 +961,19 @@
 {
 	struct gem *gp = netdev_priv(dev);
 
-	printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
+	netdev_err(dev, "transmit timed out, resetting\n");
 	if (!gp->running) {
-		printk("%s: hrm.. hw not running !\n", dev->name);
+		netdev_err(dev, "hrm.. hw not running !\n");
 		return;
 	}
-	printk(KERN_ERR "%s: TX_STATE[%08x:%08x:%08x]\n",
-	       dev->name,
-	       readl(gp->regs + TXDMA_CFG),
-	       readl(gp->regs + MAC_TXSTAT),
-	       readl(gp->regs + MAC_TXCFG));
-	printk(KERN_ERR "%s: RX_STATE[%08x:%08x:%08x]\n",
-	       dev->name,
-	       readl(gp->regs + RXDMA_CFG),
-	       readl(gp->regs + MAC_RXSTAT),
-	       readl(gp->regs + MAC_RXCFG));
+	netdev_err(dev, "TX_STATE[%08x:%08x:%08x]\n",
+		   readl(gp->regs + TXDMA_CFG),
+		   readl(gp->regs + MAC_TXSTAT),
+		   readl(gp->regs + MAC_TXCFG));
+	netdev_err(dev, "RX_STATE[%08x:%08x:%08x]\n",
+		   readl(gp->regs + RXDMA_CFG),
+		   readl(gp->regs + MAC_RXSTAT),
+		   readl(gp->regs + MAC_RXCFG));
 
 	spin_lock_irq(&gp->lock);
 	spin_lock(&gp->tx_lock);
@@ -1048,8 +1026,7 @@
 	if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
 		netif_stop_queue(dev);
 		spin_unlock_irqrestore(&gp->tx_lock, flags);
-		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
-		       dev->name);
+		netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
 		return NETDEV_TX_BUSY;
 	}
 
@@ -1158,8 +1135,7 @@
 			break;
 	}
 	if (limit < 0)
-		printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
-		       gp->dev->name);
+		netdev_warn(gp->dev, "PCS reset bit would not clear\n");
 }
 
 static void gem_pcs_reinit_adv(struct gem *gp)
@@ -1230,7 +1206,7 @@
 	} while (val & (GREG_SWRST_TXRST | GREG_SWRST_RXRST));
 
 	if (limit < 0)
-		printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name);
+		netdev_err(gp->dev, "SW reset is ghetto\n");
 
 	if (gp->phy_type == phy_serialink || gp->phy_type == phy_serdes)
 		gem_pcs_reinit_adv(gp);
@@ -1395,9 +1371,8 @@
 		speed = SPEED_1000;
 	}
 
-	if (netif_msg_link(gp))
-		printk(KERN_INFO "%s: Link is up at %d Mbps, %s-duplex.\n",
-			gp->dev->name, speed, (full_duplex ? "full" : "half"));
+	netif_info(gp, link, gp->dev, "Link is up at %d Mbps, %s-duplex\n",
+		   speed, (full_duplex ? "full" : "half"));
 
 	if (!gp->running)
 		return 0;
@@ -1451,15 +1426,13 @@
 
 	if (netif_msg_link(gp)) {
 		if (pause) {
-			printk(KERN_INFO "%s: Pause is enabled "
-			       "(rxfifo: %d off: %d on: %d)\n",
-			       gp->dev->name,
-			       gp->rx_fifo_sz,
-			       gp->rx_pause_off,
-			       gp->rx_pause_on);
+			netdev_info(gp->dev,
+				    "Pause is enabled (rxfifo: %d off: %d on: %d)\n",
+				    gp->rx_fifo_sz,
+				    gp->rx_pause_off,
+				    gp->rx_pause_on);
 		} else {
-			printk(KERN_INFO "%s: Pause is disabled\n",
-			       gp->dev->name);
+			netdev_info(gp->dev, "Pause is disabled\n");
 		}
 	}
 
@@ -1484,9 +1457,8 @@
 {
 	switch (gp->lstate) {
 	case link_force_ret:
-		if (netif_msg_link(gp))
-			printk(KERN_INFO "%s: Autoneg failed again, keeping"
-				" forced mode\n", gp->dev->name);
+		netif_info(gp, link, gp->dev,
+			   "Autoneg failed again, keeping forced mode\n");
 		gp->phy_mii.def->ops->setup_forced(&gp->phy_mii,
 			gp->last_forced_speed, DUPLEX_HALF);
 		gp->timer_ticks = 5;
@@ -1499,9 +1471,7 @@
 		 */
 		if (gp->phy_mii.def->magic_aneg)
 			return 1;
-		if (netif_msg_link(gp))
-			printk(KERN_INFO "%s: switching to forced 100bt\n",
-				gp->dev->name);
+		netif_info(gp, link, gp->dev, "switching to forced 100bt\n");
 		/* Try forced modes. */
 		gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, SPEED_100,
 			DUPLEX_HALF);
@@ -1517,9 +1487,8 @@
 			gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, SPEED_10,
 				DUPLEX_HALF);
 			gp->timer_ticks = 5;
-			if (netif_msg_link(gp))
-				printk(KERN_INFO "%s: switching to forced 10bt\n",
-					gp->dev->name);
+			netif_info(gp, link, gp->dev,
+				   "switching to forced 10bt\n");
 			return 0;
 		} else
 			return 1;
@@ -1574,8 +1543,8 @@
 			gp->last_forced_speed = gp->phy_mii.speed;
 			gp->timer_ticks = 5;
 			if (netif_msg_link(gp))
-				printk(KERN_INFO "%s: Got link after fallback, retrying"
-					" autoneg once...\n", gp->dev->name);
+				netdev_info(gp->dev,
+					    "Got link after fallback, retrying autoneg once...\n");
 			gp->phy_mii.def->ops->setup_aneg(&gp->phy_mii, gp->phy_mii.advertising);
 		} else if (gp->lstate != link_up) {
 			gp->lstate = link_up;
@@ -1589,9 +1558,7 @@
 		 */
 		if (gp->lstate == link_up) {
 			gp->lstate = link_down;
-			if (netif_msg_link(gp))
-				printk(KERN_INFO "%s: Link down\n",
-					gp->dev->name);
+			netif_info(gp, link, gp->dev, "Link down\n");
 			netif_carrier_off(gp->dev);
 			gp->reset_task_pending = 1;
 			schedule_work(&gp->reset_task);
@@ -1746,8 +1713,7 @@
 			if (phy_read(gp, MII_BMCR) != 0xffff)
 				break;
 			if (i == 2)
-				printk(KERN_WARNING "%s: GMAC PHY not responding !\n",
-				       gp->dev->name);
+				netdev_warn(gp->dev, "GMAC PHY not responding !\n");
 		}
 	}
 
@@ -2038,7 +2004,7 @@
 		 * as this chip has no gigabit PHY.
 		 */
 		if ((mif_cfg & (MIF_CFG_MDI0 | MIF_CFG_MDI1)) == 0) {
-			printk(KERN_ERR PFX "RIO GEM lacks MII phy, mif_cfg[%08x]\n",
+			pr_err("RIO GEM lacks MII phy, mif_cfg[%08x]\n",
 			       mif_cfg);
 			return -1;
 		}
@@ -2078,7 +2044,7 @@
 		}
 		if (i == 32) {
 			if (pdev->device != PCI_DEVICE_ID_SUN_GEM) {
-				printk(KERN_ERR PFX "RIO MII phy will not respond.\n");
+				pr_err("RIO MII phy will not respond\n");
 				return -1;
 			}
 			gp->phy_type = phy_serdes;
@@ -2093,7 +2059,7 @@
 		if (pdev->device == PCI_DEVICE_ID_SUN_GEM) {
 			if (gp->tx_fifo_sz != (9 * 1024) ||
 			    gp->rx_fifo_sz != (20 * 1024)) {
-				printk(KERN_ERR PFX "GEM has bogus fifo sizes tx(%d) rx(%d)\n",
+				pr_err("GEM has bogus fifo sizes tx(%d) rx(%d)\n",
 				       gp->tx_fifo_sz, gp->rx_fifo_sz);
 				return -1;
 			}
@@ -2101,7 +2067,7 @@
 		} else {
 			if (gp->tx_fifo_sz != (2 * 1024) ||
 			    gp->rx_fifo_sz != (2 * 1024)) {
-				printk(KERN_ERR PFX "RIO GEM has bogus fifo sizes tx(%d) rx(%d)\n",
+				pr_err("RIO GEM has bogus fifo sizes tx(%d) rx(%d)\n",
 				       gp->tx_fifo_sz, gp->rx_fifo_sz);
 				return -1;
 			}
@@ -2239,7 +2205,7 @@
 
 	if (request_irq(gp->pdev->irq, gem_interrupt,
 				   IRQF_SHARED, dev->name, (void *)dev)) {
-		printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
+		netdev_err(dev, "failed to request irq !\n");
 
 		spin_lock_irqsave(&gp->lock, flags);
 		spin_lock(&gp->tx_lock);
@@ -2378,9 +2344,8 @@
 
 	mutex_lock(&gp->pm_mutex);
 
-	printk(KERN_INFO "%s: suspending, WakeOnLan %s\n",
-	       dev->name,
-	       (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
+	netdev_info(dev, "suspending, WakeOnLan %s\n",
+		    (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
 
 	/* Keep the cell enabled during the entire operation */
 	spin_lock_irqsave(&gp->lock, flags);
@@ -2440,7 +2405,7 @@
 	struct gem *gp = netdev_priv(dev);
 	unsigned long flags;
 
-	printk(KERN_INFO "%s: resuming\n", dev->name);
+	netdev_info(dev, "resuming\n");
 
 	mutex_lock(&gp->pm_mutex);
 
@@ -2452,8 +2417,7 @@
 
 	/* Make sure PCI access and bus master are enabled */
 	if (pci_enable_device(gp->pdev)) {
-		printk(KERN_ERR "%s: Can't re-enable chip !\n",
-		       dev->name);
+		netdev_err(dev, "Can't re-enable chip !\n");
 		/* Put cell and forget it for now, it will be considered as
 		 * still asleep, a new sleep cycle may bring it back
 		 */
@@ -2938,7 +2902,7 @@
 		addr = idprom->id_ethaddr;
 #else
 		printk("\n");
-		printk(KERN_ERR "%s: can't get mac-address\n", dev->name);
+		pr_err("%s: can't get mac-address\n", dev->name);
 		return -1;
 #endif
 	}
@@ -3009,14 +2973,12 @@
 static int __devinit gem_init_one(struct pci_dev *pdev,
 				  const struct pci_device_id *ent)
 {
-	static int gem_version_printed = 0;
 	unsigned long gemreg_base, gemreg_len;
 	struct net_device *dev;
 	struct gem *gp;
 	int err, pci_using_dac;
 
-	if (gem_version_printed++ == 0)
-		printk(KERN_INFO "%s", version);
+	printk_once(KERN_INFO "%s", version);
 
 	/* Apple gmac note: during probe, the chip is powered up by
 	 * the arch code to allow the code below to work (and to let
@@ -3026,8 +2988,7 @@
 	 */
 	err = pci_enable_device(pdev);
 	if (err) {
-		printk(KERN_ERR PFX "Cannot enable MMIO operation, "
-		       "aborting.\n");
+		pr_err("Cannot enable MMIO operation, aborting\n");
 		return err;
 	}
 	pci_set_master(pdev);
@@ -3048,8 +3009,7 @@
 	} else {
 		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (err) {
-			printk(KERN_ERR PFX "No usable DMA configuration, "
-			       "aborting.\n");
+			pr_err("No usable DMA configuration, aborting\n");
 			goto err_disable_device;
 		}
 		pci_using_dac = 0;
@@ -3059,15 +3019,14 @@
 	gemreg_len = pci_resource_len(pdev, 0);
 
 	if ((pci_resource_flags(pdev, 0) & IORESOURCE_IO) != 0) {
-		printk(KERN_ERR PFX "Cannot find proper PCI device "
-		       "base address, aborting.\n");
+		pr_err("Cannot find proper PCI device base address, aborting\n");
 		err = -ENODEV;
 		goto err_disable_device;
 	}
 
 	dev = alloc_etherdev(sizeof(*gp));
 	if (!dev) {
-		printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
+		pr_err("Etherdev alloc failed, aborting\n");
 		err = -ENOMEM;
 		goto err_disable_device;
 	}
@@ -3077,8 +3036,7 @@
 
 	err = pci_request_regions(pdev, DRV_NAME);
 	if (err) {
-		printk(KERN_ERR PFX "Cannot obtain PCI resources, "
-		       "aborting.\n");
+		pr_err("Cannot obtain PCI resources, aborting\n");
 		goto err_out_free_netdev;
 	}
 
@@ -3104,8 +3062,7 @@
 
 	gp->regs = ioremap(gemreg_base, gemreg_len);
 	if (!gp->regs) {
-		printk(KERN_ERR PFX "Cannot map device registers, "
-		       "aborting.\n");
+		pr_err("Cannot map device registers, aborting\n");
 		err = -EIO;
 		goto err_out_free_res;
 	}
@@ -3150,8 +3107,7 @@
 		pci_alloc_consistent(pdev, sizeof(struct gem_init_block),
 				     &gp->gblock_dvma);
 	if (!gp->init_block) {
-		printk(KERN_ERR PFX "Cannot allocate init block, "
-		       "aborting.\n");
+		pr_err("Cannot allocate init block, aborting\n");
 		err = -ENOMEM;
 		goto err_out_iounmap;
 	}
@@ -3180,19 +3136,18 @@
 
 	/* Register with kernel */
 	if (register_netdev(dev)) {
-		printk(KERN_ERR PFX "Cannot register net device, "
-		       "aborting.\n");
+		pr_err("Cannot register net device, aborting\n");
 		err = -ENOMEM;
 		goto err_out_free_consistent;
 	}
 
-	printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n",
-	       dev->name, dev->dev_addr);
+	netdev_info(dev, "Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n",
+		    dev->dev_addr);
 
 	if (gp->phy_type == phy_mii_mdio0 ||
      	    gp->phy_type == phy_mii_mdio1)
-		printk(KERN_INFO "%s: Found %s PHY\n", dev->name,
-			gp->phy_mii.def ? gp->phy_mii.def->name : "no");
+		netdev_info(dev, "Found %s PHY\n",
+			    gp->phy_mii.def ? gp->phy_mii.def->name : "no");
 
 	/* GEM can do it all... */
 	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_LLTX;
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index 78f8cee..d16880d 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -88,7 +88,7 @@
 	if ((val & BMCR_ISOLATE) && limit > 0)
 		__phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
 
-	return (limit <= 0);
+	return limit <= 0;
 }
 
 static int bcm5201_init(struct mii_phy* phy)
@@ -1175,7 +1175,8 @@
 
 	/* Read ID and find matching entry */
 	id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
-	printk(KERN_DEBUG "PHY ID: %x, addr: %x\n", id, mii_id);
+	printk(KERN_DEBUG KBUILD_MODNAME ": " "PHY ID: %x, addr: %x\n",
+	       id, mii_id);
 	for (i=0; (def = mii_phy_table[i]) != NULL; i++)
 		if ((id & def->phy_id_mask) == def->phy_id)
 			break;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index bd0df1c..5e28c41 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -1409,7 +1409,7 @@
 	hp->timer_ticks = 0;
 	hp->happy_timer.expires = jiffies + (12 * HZ)/10;  /* 1.2 sec. */
 	hp->happy_timer.data = (unsigned long) hp;
-	hp->happy_timer.function = &happy_meal_timer;
+	hp->happy_timer.function = happy_meal_timer;
 	add_timer(&hp->happy_timer);
 }
 
@@ -2497,7 +2497,7 @@
 	hp->sw_bmcr = happy_meal_tcvr_read(hp, hp->tcvregs, MII_BMCR);
 	spin_unlock_irq(&hp->happy_lock);
 
-	return (hp->sw_bmsr & BMSR_LSTATUS);
+	return hp->sw_bmsr & BMSR_LSTATUS;
 }
 
 static const struct ethtool_ops hme_ethtool_ops = {
@@ -2808,7 +2808,8 @@
 	happy_meal_set_initial_advertisement(hp);
 	spin_unlock_irq(&hp->happy_lock);
 
-	if (register_netdev(hp->dev)) {
+	err = register_netdev(hp->dev);
+	if (err) {
 		printk(KERN_ERR "happymeal: Cannot register net device, "
 		       "aborting.\n");
 		goto err_out_free_coherent;
@@ -3130,7 +3131,8 @@
 	happy_meal_set_initial_advertisement(hp);
 	spin_unlock_irq(&hp->happy_lock);
 
-	if (register_netdev(hp->dev)) {
+	err = register_netdev(hp->dev);
+	if (err) {
 		printk(KERN_ERR "happymeal(PCI): Cannot register net device, "
 		       "aborting.\n");
 		goto err_out_iounmap;
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 8dcb858..2cf84e5 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1483,7 +1483,7 @@
 	 */
 	init_timer(&lp->multicast_timer);
 	lp->multicast_timer.data = (unsigned long) dev;
-	lp->multicast_timer.function = &lance_set_multicast_retry;
+	lp->multicast_timer.function = lance_set_multicast_retry;
 
 	if (register_netdev(dev)) {
 		printk(KERN_ERR "SunLance: Cannot register device.\n");
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 72e65d4..9536b2f 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -711,7 +711,7 @@
 	phyconfig = sbus_readb(mregs + MREGS_PHYCONFIG);
 	spin_unlock_irq(&qep->lock);
 
-	return (phyconfig & MREGS_PHYCONFIG_LSTAT);
+	return phyconfig & MREGS_PHYCONFIG_LSTAT;
 }
 
 static const struct ethtool_ops qe_ethtool_ops = {
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
index d281a7b..bf3c762 100644
--- a/drivers/net/sunvnet.c
+++ b/drivers/net/sunvnet.c
@@ -3,6 +3,8 @@
  * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -20,7 +22,6 @@
 #include "sunvnet.h"
 
 #define DRV_MODULE_NAME		"sunvnet"
-#define PFX DRV_MODULE_NAME	": "
 #define DRV_MODULE_VERSION	"1.0"
 #define DRV_MODULE_RELDATE	"June 25, 2007"
 
@@ -45,9 +46,9 @@
 {
 	struct vio_msg_tag *pkt = arg;
 
-	printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n",
+	pr_err("Received unknown msg [%02x:%02x:%04x:%08x]\n",
 	       pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
-	printk(KERN_ERR PFX "Resetting connection.\n");
+	pr_err("Resetting connection\n");
 
 	ldc_disconnect(port->vio.lp);
 
@@ -400,8 +401,8 @@
 	if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
 		return 0;
 	if (unlikely(pkt->seq != dr->rcv_nxt)) {
-		printk(KERN_ERR PFX "RX out of sequence seq[0x%llx] "
-		       "rcv_nxt[0x%llx]\n", pkt->seq, dr->rcv_nxt);
+		pr_err("RX out of sequence seq[0x%llx] rcv_nxt[0x%llx]\n",
+		       pkt->seq, dr->rcv_nxt);
 		return 0;
 	}
 
@@ -464,8 +465,7 @@
 	struct vio_net_mcast_info *pkt = msgbuf;
 
 	if (pkt->tag.stype != VIO_SUBTYPE_ACK)
-		printk(KERN_ERR PFX "%s: Got unexpected MCAST reply "
-		       "[%02x:%02x:%04x:%08x]\n",
+		pr_err("%s: Got unexpected MCAST reply [%02x:%02x:%04x:%08x]\n",
 		       port->vp->dev->name,
 		       pkt->tag.type,
 		       pkt->tag.stype,
@@ -520,7 +520,7 @@
 	}
 
 	if (unlikely(event != LDC_EVENT_DATA_READY)) {
-		printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+		pr_warning("Unexpected LDC event %d\n", event);
 		spin_unlock_irqrestore(&vio->lock, flags);
 		return;
 	}
@@ -662,8 +662,7 @@
 			netif_stop_queue(dev);
 
 			/* This is a hard error, log it. */
-			printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
-			       "queue awake!\n", dev->name);
+			netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
 			dev->stats.tx_errors++;
 		}
 		spin_unlock_irqrestore(&port->vio.lock, flags);
@@ -696,8 +695,7 @@
 
 	err = __vnet_tx_trigger(port);
 	if (unlikely(err < 0)) {
-		printk(KERN_INFO PFX "%s: TX trigger error %d\n",
-		       dev->name, err);
+		netdev_info(dev, "TX trigger error %d\n", err);
 		d->hdr.state = VIO_DESC_FREE;
 		dev->stats.tx_carrier_errors++;
 		goto out_dropped_unlock;
@@ -952,12 +950,12 @@
 
 		err = -ENOMEM;
 		if (!buf) {
-			printk(KERN_ERR "TX buffer allocation failure\n");
+			pr_err("TX buffer allocation failure\n");
 			goto err_out;
 		}
 		err = -EFAULT;
 		if ((unsigned long)buf & (8UL - 1)) {
-			printk(KERN_ERR "TX buffer misaligned\n");
+			pr_err("TX buffer misaligned\n");
 			kfree(buf);
 			goto err_out;
 		}
@@ -1030,7 +1028,7 @@
 
 	dev = alloc_etherdev(sizeof(*vp));
 	if (!dev) {
-		printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
+		pr_err("Etherdev alloc failed, aborting\n");
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -1056,12 +1054,11 @@
 
 	err = register_netdev(dev);
 	if (err) {
-		printk(KERN_ERR PFX "Cannot register net device, "
-		       "aborting.\n");
+		pr_err("Cannot register net device, aborting\n");
 		goto err_out_free_dev;
 	}
 
-	printk(KERN_INFO "%s: Sun LDOM vnet %pM\n", dev->name, dev->dev_addr);
+	netdev_info(dev, "Sun LDOM vnet %pM\n", dev->dev_addr);
 
 	list_add(&vp->list, &vnet_list);
 
@@ -1133,10 +1130,7 @@
 
 static void __devinit print_version(void)
 {
-	static int version_printed;
-
-	if (version_printed++ == 0)
-		printk(KERN_INFO "%s", version);
+	printk_once(KERN_INFO "%s", version);
 }
 
 const char *remote_macaddr_prop = "remote-mac-address";
@@ -1157,7 +1151,7 @@
 
 	vp = vnet_find_parent(hp, vdev->mp);
 	if (IS_ERR(vp)) {
-		printk(KERN_ERR PFX "Cannot find port parent vnet.\n");
+		pr_err("Cannot find port parent vnet\n");
 		err = PTR_ERR(vp);
 		goto err_out_put_mdesc;
 	}
@@ -1165,15 +1159,14 @@
 	rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len);
 	err = -ENODEV;
 	if (!rmac) {
-		printk(KERN_ERR PFX "Port lacks %s property.\n",
-		       remote_macaddr_prop);
+		pr_err("Port lacks %s property\n", remote_macaddr_prop);
 		goto err_out_put_mdesc;
 	}
 
 	port = kzalloc(sizeof(*port), GFP_KERNEL);
 	err = -ENOMEM;
 	if (!port) {
-		printk(KERN_ERR PFX "Cannot allocate vnet_port.\n");
+		pr_err("Cannot allocate vnet_port\n");
 		goto err_out_put_mdesc;
 	}
 
@@ -1214,9 +1207,8 @@
 
 	dev_set_drvdata(&vdev->dev, port);
 
-	printk(KERN_INFO "%s: PORT ( remote-mac %pM%s )\n",
-	       vp->dev->name, port->raddr,
-	       switch_port ? " switch-port" : "");
+	pr_info("%s: PORT ( remote-mac %pM%s )\n",
+		vp->dev->name, port->raddr, switch_port ? " switch-port" : "");
 
 	vio_port_up(&port->vio);
 
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 99e423a..b6eec8c 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -1167,7 +1167,7 @@
 static int tc35815_tx_full(struct net_device *dev)
 {
 	struct tc35815_local *lp = netdev_priv(dev);
-	return ((lp->tfd_start + 1) % TX_FD_NUM == lp->tfd_end);
+	return (lp->tfd_start + 1) % TX_FD_NUM == lp->tfd_end;
 }
 
 static void tc35815_restart(struct net_device *dev)
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 737df60..8b3dc1e 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -92,7 +92,7 @@
 static void bdx_tx_free(struct bdx_priv *priv);
 
 /* Definitions needed by bdx_probe */
-static void bdx_ethtool_ops(struct net_device *netdev);
+static void bdx_set_ethtool_ops(struct net_device *netdev);
 
 /*************************************************************************
  *    Print Info                                                         *
@@ -927,13 +927,6 @@
 	BDX_ASSERT((sizeof(struct bdx_stats) / sizeof(u64)) != i);
 }
 
-static struct net_device_stats *bdx_get_stats(struct net_device *ndev)
-{
-	struct bdx_priv *priv = netdev_priv(ndev);
-	struct net_device_stats *net_stat = &priv->net_stats;
-	return net_stat;
-}
-
 static void print_rxdd(struct rxd_desc *rxdd, u32 rxd_val1, u16 len,
 		       u16 rxd_vlan);
 static void print_rxfd(struct rxf_desc *rxfd);
@@ -1220,6 +1213,7 @@
 
 static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget)
 {
+	struct net_device *ndev = priv->ndev;
 	struct sk_buff *skb, *skb2;
 	struct rxd_desc *rxdd;
 	struct rx_map *dm;
@@ -1273,7 +1267,7 @@
 
 		if (unlikely(GET_RXD_ERR(rxd_val1))) {
 			DBG("rxd_err = 0x%x\n", GET_RXD_ERR(rxd_val1));
-			priv->net_stats.rx_errors++;
+			ndev->stats.rx_errors++;
 			bdx_recycle_skb(priv, rxdd);
 			continue;
 		}
@@ -1300,15 +1294,16 @@
 			bdx_rxdb_free_elem(db, rxdd->va_lo);
 		}
 
-		priv->net_stats.rx_bytes += len;
+		ndev->stats.rx_bytes += len;
 
 		skb_put(skb, len);
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		skb->protocol = eth_type_trans(skb, priv->ndev);
+		skb->protocol = eth_type_trans(skb, ndev);
 
 		/* Non-IP packets aren't checksum-offloaded */
 		if (GET_RXD_PKT_ID(rxd_val1) == 0)
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
+		else
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 		NETIF_RX_MUX(priv, rxd_val1, rxd_vlan, skb);
 
@@ -1316,7 +1311,7 @@
 			break;
 	}
 
-	priv->net_stats.rx_packets += done;
+	ndev->stats.rx_packets += done;
 
 	/* FIXME: do smth to minimize pci accesses    */
 	WRITE_REG(priv, f->m.reg_RPTR, f->m.rptr & TXF_WPTR_WR_PTR);
@@ -1712,8 +1707,8 @@
 #ifdef BDX_LLTX
 	ndev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
 #endif
-	priv->net_stats.tx_packets++;
-	priv->net_stats.tx_bytes += skb->len;
+	ndev->stats.tx_packets++;
+	ndev->stats.tx_bytes += skb->len;
 
 	if (priv->tx_level < BDX_MIN_TX_LEVEL) {
 		DBG("%s: %s: TX Q STOP level %d\n",
@@ -1888,7 +1883,6 @@
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_do_ioctl		= bdx_ioctl,
 	.ndo_set_multicast_list = bdx_setmulti,
-	.ndo_get_stats		= bdx_get_stats,
 	.ndo_change_mtu		= bdx_change_mtu,
 	.ndo_set_mac_address	= bdx_set_mac,
 	.ndo_vlan_rx_register	= bdx_vlan_rx_register,
@@ -2012,7 +2006,7 @@
 		ndev->netdev_ops = &bdx_netdev_ops;
 		ndev->tx_queue_len = BDX_NDEV_TXQ_LEN;
 
-		bdx_ethtool_ops(ndev);	/* ethtool interface */
+		bdx_set_ethtool_ops(ndev);	/* ethtool interface */
 
 		/* these fields are used for info purposes only
 		 * so we can have them same for all ports of the board */
@@ -2417,10 +2411,10 @@
 }
 
 /*
- * bdx_ethtool_ops - ethtool interface implementation
+ * bdx_set_ethtool_ops - ethtool interface implementation
  * @netdev
  */
-static void bdx_ethtool_ops(struct net_device *netdev)
+static void bdx_set_ethtool_ops(struct net_device *netdev)
 {
 	static const struct ethtool_ops bdx_ethtool_ops = {
 		.get_settings = bdx_get_settings,
diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h
index 67e3b71..b6ba860 100644
--- a/drivers/net/tehuti.h
+++ b/drivers/net/tehuti.h
@@ -269,7 +269,6 @@
 	u32 msg_enable;
 	int stats_flag;
 	struct bdx_stats hw_stats;
-	struct net_device_stats net_stats;
 	struct pci_dev *pdev;
 
 	struct pci_nic *nic;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index bc3af78..852e917 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,10 +69,10 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define TG3_MAJ_NUM			3
-#define TG3_MIN_NUM			113
+#define TG3_MIN_NUM			115
 #define DRV_MODULE_VERSION	\
 	__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE	"August 2, 2010"
+#define DRV_MODULE_RELDATE	"October 14, 2010"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -101,9 +101,15 @@
  * You can't change the ring sizes, but you can change where you place
  * them in the NIC onboard memory.
  */
-#define TG3_RX_RING_SIZE		512
+#define TG3_RX_STD_RING_SIZE(tp) \
+	((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || \
+	  GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ? \
+	 RX_STD_MAX_SIZE_5717 : 512)
 #define TG3_DEF_RX_RING_PENDING		200
-#define TG3_RX_JUMBO_RING_SIZE		256
+#define TG3_RX_JMB_RING_SIZE(tp) \
+	((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || \
+	  GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ? \
+	 1024 : 256)
 #define TG3_DEF_RX_JUMBO_RING_PENDING	100
 #define TG3_RSS_INDIR_TBL_SIZE		128
 
@@ -113,19 +119,16 @@
  * hw multiply/modulo instructions.  Another solution would be to
  * replace things like '% foo' with '& (foo - 1)'.
  */
-#define TG3_RX_RCB_RING_SIZE(tp)	\
-	(((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && \
-	  !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) ? 1024 : 512)
 
 #define TG3_TX_RING_SIZE		512
 #define TG3_DEF_TX_RING_PENDING		(TG3_TX_RING_SIZE - 1)
 
-#define TG3_RX_RING_BYTES	(sizeof(struct tg3_rx_buffer_desc) * \
-				 TG3_RX_RING_SIZE)
-#define TG3_RX_JUMBO_RING_BYTES	(sizeof(struct tg3_ext_rx_buffer_desc) * \
-				 TG3_RX_JUMBO_RING_SIZE)
-#define TG3_RX_RCB_RING_BYTES(tp) (sizeof(struct tg3_rx_buffer_desc) * \
-				 TG3_RX_RCB_RING_SIZE(tp))
+#define TG3_RX_STD_RING_BYTES(tp) \
+	(sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_RING_SIZE(tp))
+#define TG3_RX_JMB_RING_BYTES(tp) \
+	(sizeof(struct tg3_ext_rx_buffer_desc) * TG3_RX_JMB_RING_SIZE(tp))
+#define TG3_RX_RCB_RING_BYTES(tp) \
+	(sizeof(struct tg3_rx_buffer_desc) * (tp->rx_ret_ring_mask + 1))
 #define TG3_TX_RING_BYTES	(sizeof(struct tg3_tx_buffer_desc) * \
 				 TG3_TX_RING_SIZE)
 #define NEXT_TX(N)		(((N) + 1) & (TG3_TX_RING_SIZE - 1))
@@ -143,11 +146,11 @@
 #define TG3_RX_STD_MAP_SZ		TG3_RX_DMA_TO_MAP_SZ(TG3_RX_STD_DMA_SZ)
 #define TG3_RX_JMB_MAP_SZ		TG3_RX_DMA_TO_MAP_SZ(TG3_RX_JMB_DMA_SZ)
 
-#define TG3_RX_STD_BUFF_RING_SIZE \
-	(sizeof(struct ring_info) * TG3_RX_RING_SIZE)
+#define TG3_RX_STD_BUFF_RING_SIZE(tp) \
+	(sizeof(struct ring_info) * TG3_RX_STD_RING_SIZE(tp))
 
-#define TG3_RX_JMB_BUFF_RING_SIZE \
-	(sizeof(struct ring_info) * TG3_RX_JUMBO_RING_SIZE)
+#define TG3_RX_JMB_BUFF_RING_SIZE(tp) \
+	(sizeof(struct ring_info) * TG3_RX_JMB_RING_SIZE(tp))
 
 /* Due to a hardware bug, the 5701 can only DMA to memory addresses
  * that are at least dword aligned when used in PCIX mode.  The driver
@@ -264,7 +267,6 @@
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5724)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
@@ -752,42 +754,6 @@
 		     HOSTCC_MODE_ENABLE | tnapi->coal_now);
 }
 
-static void tg3_napi_disable(struct tg3 *tp)
-{
-	int i;
-
-	for (i = tp->irq_cnt - 1; i >= 0; i--)
-		napi_disable(&tp->napi[i].napi);
-}
-
-static void tg3_napi_enable(struct tg3 *tp)
-{
-	int i;
-
-	for (i = 0; i < tp->irq_cnt; i++)
-		napi_enable(&tp->napi[i].napi);
-}
-
-static inline void tg3_netif_stop(struct tg3 *tp)
-{
-	tp->dev->trans_start = jiffies;	/* prevent tx timeout */
-	tg3_napi_disable(tp);
-	netif_tx_disable(tp->dev);
-}
-
-static inline void tg3_netif_start(struct tg3 *tp)
-{
-	/* NOTE: unconditional netif_tx_wake_all_queues is only
-	 * appropriate so long as all callers are assured to
-	 * have free tx slots (such as after tg3_init_hw)
-	 */
-	netif_tx_wake_all_queues(tp->dev);
-
-	tg3_napi_enable(tp);
-	tp->napi[0].hw_status->status |= SD_STATUS_UPDATED;
-	tg3_enable_ints(tp);
-}
-
 static void tg3_switch_clocks(struct tg3 *tp)
 {
 	u32 clock_ctrl;
@@ -1196,6 +1162,52 @@
 	}
 }
 
+static int tg3_phy_cl45_write(struct tg3 *tp, u32 devad, u32 addr, u32 val)
+{
+	int err;
+
+	err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad);
+	if (err)
+		goto done;
+
+	err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr);
+	if (err)
+		goto done;
+
+	err = tg3_writephy(tp, MII_TG3_MMD_CTRL,
+			   MII_TG3_MMD_CTRL_DATA_NOINC | devad);
+	if (err)
+		goto done;
+
+	err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, val);
+
+done:
+	return err;
+}
+
+static int tg3_phy_cl45_read(struct tg3 *tp, u32 devad, u32 addr, u32 *val)
+{
+	int err;
+
+	err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad);
+	if (err)
+		goto done;
+
+	err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr);
+	if (err)
+		goto done;
+
+	err = tg3_writephy(tp, MII_TG3_MMD_CTRL,
+			   MII_TG3_MMD_CTRL_DATA_NOINC | devad);
+	if (err)
+		goto done;
+
+	err = tg3_readphy(tp, MII_TG3_MMD_ADDRESS, val);
+
+done:
+	return err;
+}
+
 /* tp->lock is held. */
 static inline void tg3_generate_fw_event(struct tg3 *tp)
 {
@@ -1572,6 +1584,17 @@
 	}
 }
 
+static int tg3_phydsp_read(struct tg3 *tp, u32 reg, u32 *val)
+{
+	int err;
+
+	err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
+	if (!err)
+		err = tg3_readphy(tp, MII_TG3_DSP_RW_PORT, val);
+
+	return err;
+}
+
 static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
 {
 	int err;
@@ -1735,6 +1758,42 @@
 	tg3_writephy(tp, MII_TG3_AUX_CTRL, phy);
 }
 
+static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
+{
+	u32 val;
+
+	if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
+		return;
+
+	tp->setlpicnt = 0;
+
+	if (tp->link_config.autoneg == AUTONEG_ENABLE &&
+	    current_link_up == 1 &&
+	    (tp->link_config.active_speed == SPEED_1000 ||
+	     (tp->link_config.active_speed == SPEED_100 &&
+	      tp->link_config.active_duplex == DUPLEX_FULL))) {
+		u32 eeectl;
+
+		if (tp->link_config.active_speed == SPEED_1000)
+			eeectl = TG3_CPMU_EEE_CTRL_EXIT_16_5_US;
+		else
+			eeectl = TG3_CPMU_EEE_CTRL_EXIT_36_US;
+
+		tw32(TG3_CPMU_EEE_CTRL, eeectl);
+
+		tg3_phy_cl45_read(tp, 0x7, TG3_CL45_D7_EEERES_STAT, &val);
+
+		if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
+		    val == TG3_CL45_D7_EEERES_STAT_LP_100TX)
+			tp->setlpicnt = 2;
+	}
+
+	if (!tp->setlpicnt) {
+		val = tr32(TG3_CPMU_EEE_MODE);
+		tw32(TG3_CPMU_EEE_MODE, val & ~TG3_CPMU_EEEMD_LPI_ENABLE);
+	}
+}
+
 static int tg3_wait_macro_done(struct tg3 *tp)
 {
 	int limit = 100;
@@ -1917,19 +1976,16 @@
  */
 static int tg3_phy_reset(struct tg3 *tp)
 {
-	u32 cpmuctrl;
-	u32 phy_status;
+	u32 val, cpmuctrl;
 	int err;
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-		u32 val;
-
 		val = tr32(GRC_MISC_CFG);
 		tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
 		udelay(40);
 	}
-	err  = tg3_readphy(tp, MII_BMSR, &phy_status);
-	err |= tg3_readphy(tp, MII_BMSR, &phy_status);
+	err  = tg3_readphy(tp, MII_BMSR, &val);
+	err |= tg3_readphy(tp, MII_BMSR, &val);
 	if (err != 0)
 		return -EBUSY;
 
@@ -1961,18 +2017,14 @@
 		return err;
 
 	if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) {
-		u32 phy;
-
-		phy = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
-		tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, phy);
+		val = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
+		tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, val);
 
 		tw32(TG3_CPMU_CTRL, cpmuctrl);
 	}
 
 	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
 	    GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
-		u32 val;
-
 		val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
 		if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
 		    CPMU_LSPD_1000MB_MACCLK_12_5) {
@@ -2028,23 +2080,19 @@
 		/* Cannot do read-modify-write on 5401 */
 		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20);
 	} else if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
-		u32 phy_reg;
-
 		/* Set bit 14 with read-modify-write to preserve other bits */
 		if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007) &&
-		    !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg))
-			tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000);
+		    !tg3_readphy(tp, MII_TG3_AUX_CTRL, &val))
+			tg3_writephy(tp, MII_TG3_AUX_CTRL, val | 0x4000);
 	}
 
 	/* Set phy register 0x10 bit 0 to high fifo elasticity to support
 	 * jumbo frames transmission.
 	 */
 	if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
-		u32 phy_reg;
-
-		if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &phy_reg))
+		if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &val))
 			tg3_writephy(tp, MII_TG3_EXT_CTRL,
-				     phy_reg | MII_TG3_EXT_CTRL_FIFO_ELASTIC);
+				     val | MII_TG3_EXT_CTRL_FIFO_ELASTIC);
 	}
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
@@ -2920,6 +2968,44 @@
 		tg3_writephy(tp, MII_TG3_CTRL, new_adv);
 	}
 
+	if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
+		u32 val = 0;
+
+		tw32(TG3_CPMU_EEE_MODE,
+		     tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
+
+		/* 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);
+
+		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);
+
+		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+			/* Advertise 100-BaseTX EEE ability */
+			if (tp->link_config.advertising &
+			    (ADVERTISED_100baseT_Half |
+			     ADVERTISED_100baseT_Full))
+				val |= TG3_CL45_D7_EEEADV_CAP_100TX;
+			/* Advertise 1000-BaseT EEE ability */
+			if (tp->link_config.advertising &
+			    (ADVERTISED_1000baseT_Half |
+			     ADVERTISED_1000baseT_Full))
+				val |= TG3_CL45_D7_EEEADV_CAP_1000T;
+		}
+		tg3_phy_cl45_write(tp, 0x7, TG3_CL45_D7_EEEADV_CAP, val);
+
+		/* 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);
+	}
+
 	if (tp->link_config.autoneg == AUTONEG_DISABLE &&
 	    tp->link_config.speed != SPEED_INVALID) {
 		u32 bmcr, orig_bmcr;
@@ -3060,7 +3146,7 @@
 static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 {
 	int current_link_up;
-	u32 bmsr, dummy;
+	u32 bmsr, val;
 	u32 lcl_adv, rmt_adv;
 	u16 current_speed;
 	u8 current_duplex;
@@ -3140,8 +3226,8 @@
 	}
 
 	/* Clear pending interrupts... */
-	tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
-	tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
+	tg3_readphy(tp, MII_TG3_ISTAT, &val);
+	tg3_readphy(tp, MII_TG3_ISTAT, &val);
 
 	if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT)
 		tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
@@ -3162,8 +3248,6 @@
 	current_duplex = DUPLEX_INVALID;
 
 	if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
-		u32 val;
-
 		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007);
 		tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
 		if (!(val & (1 << 10))) {
@@ -3238,13 +3322,11 @@
 
 relink:
 	if (current_link_up == 0 || (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
-		u32 tmp;
-
 		tg3_phy_copper_begin(tp);
 
-		tg3_readphy(tp, MII_BMSR, &tmp);
-		if (!tg3_readphy(tp, MII_BMSR, &tmp) &&
-		    (tmp & BMSR_LSTATUS))
+		tg3_readphy(tp, MII_BMSR, &bmsr);
+		if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+		    (bmsr & BMSR_LSTATUS))
 			current_link_up = 1;
 	}
 
@@ -3285,6 +3367,8 @@
 	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
+	tg3_phy_eee_adjust(tp, current_link_up);
+
 	if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
 		/* Polled via timer. */
 		tw32_f(MAC_EVENT, 0);
@@ -4353,6 +4437,11 @@
 	return err;
 }
 
+static inline int tg3_irq_sync(struct tg3 *tp)
+{
+	return tp->irq_sync;
+}
+
 /* This is called whenever we suspect that the system chipset is re-
  * ordering the sequence of MMIO to the tx send mailbox. The symptom
  * is bogus tx completions. We try to recover by setting the
@@ -4484,22 +4573,21 @@
 			    u32 opaque_key, u32 dest_idx_unmasked)
 {
 	struct tg3_rx_buffer_desc *desc;
-	struct ring_info *map, *src_map;
+	struct ring_info *map;
 	struct sk_buff *skb;
 	dma_addr_t mapping;
 	int skb_size, dest_idx;
 
-	src_map = NULL;
 	switch (opaque_key) {
 	case RXD_OPAQUE_RING_STD:
-		dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE;
+		dest_idx = dest_idx_unmasked & tp->rx_std_ring_mask;
 		desc = &tpr->rx_std[dest_idx];
 		map = &tpr->rx_std_buffers[dest_idx];
 		skb_size = tp->rx_pkt_map_sz;
 		break;
 
 	case RXD_OPAQUE_RING_JUMBO:
-		dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE;
+		dest_idx = dest_idx_unmasked & tp->rx_jmb_ring_mask;
 		desc = &tpr->rx_jmb[dest_idx].std;
 		map = &tpr->rx_jmb_buffers[dest_idx];
 		skb_size = TG3_RX_JMB_MAP_SZ;
@@ -4549,12 +4637,12 @@
 	struct tg3 *tp = tnapi->tp;
 	struct tg3_rx_buffer_desc *src_desc, *dest_desc;
 	struct ring_info *src_map, *dest_map;
-	struct tg3_rx_prodring_set *spr = &tp->prodring[0];
+	struct tg3_rx_prodring_set *spr = &tp->napi[0].prodring;
 	int dest_idx;
 
 	switch (opaque_key) {
 	case RXD_OPAQUE_RING_STD:
-		dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE;
+		dest_idx = dest_idx_unmasked & tp->rx_std_ring_mask;
 		dest_desc = &dpr->rx_std[dest_idx];
 		dest_map = &dpr->rx_std_buffers[dest_idx];
 		src_desc = &spr->rx_std[src_idx];
@@ -4562,7 +4650,7 @@
 		break;
 
 	case RXD_OPAQUE_RING_JUMBO:
-		dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE;
+		dest_idx = dest_idx_unmasked & tp->rx_jmb_ring_mask;
 		dest_desc = &dpr->rx_jmb[dest_idx].std;
 		dest_map = &dpr->rx_jmb_buffers[dest_idx];
 		src_desc = &spr->rx_jmb[src_idx].std;
@@ -4619,7 +4707,7 @@
 	u32 sw_idx = tnapi->rx_rcb_ptr;
 	u16 hw_idx;
 	int received;
-	struct tg3_rx_prodring_set *tpr = tnapi->prodring;
+	struct tg3_rx_prodring_set *tpr = &tnapi->prodring;
 
 	hw_idx = *(tnapi->rx_rcb_prod_idx);
 	/*
@@ -4644,13 +4732,13 @@
 		desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
 		opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
 		if (opaque_key == RXD_OPAQUE_RING_STD) {
-			ri = &tp->prodring[0].rx_std_buffers[desc_idx];
+			ri = &tp->napi[0].prodring.rx_std_buffers[desc_idx];
 			dma_addr = dma_unmap_addr(ri, mapping);
 			skb = ri->skb;
 			post_ptr = &std_prod_idx;
 			rx_std_posted++;
 		} else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
-			ri = &tp->prodring[0].rx_jmb_buffers[desc_idx];
+			ri = &tp->napi[0].prodring.rx_jmb_buffers[desc_idx];
 			dma_addr = dma_unmap_addr(ri, mapping);
 			skb = ri->skb;
 			post_ptr = &jmb_prod_idx;
@@ -4666,7 +4754,7 @@
 				       desc_idx, *post_ptr);
 		drop_it_no_recycle:
 			/* Other statistics kept track of by card. */
-			tp->net_stats.rx_dropped++;
+			tp->rx_dropped++;
 			goto next_pkt;
 		}
 
@@ -4719,14 +4807,14 @@
 		      >> RXD_TCPCSUM_SHIFT) == 0xffff))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
 
 		skb->protocol = eth_type_trans(skb, tp->dev);
 
 		if (len > (tp->dev->mtu + ETH_HLEN) &&
 		    skb->protocol != htons(ETH_P_8021Q)) {
 			dev_kfree_skb(skb);
-			goto next_pkt;
+			goto drop_it_no_recycle;
 		}
 
 		if (desc->type_flags & RXD_FLAG_VLAN &&
@@ -4762,7 +4850,8 @@
 		(*post_ptr)++;
 
 		if (unlikely(rx_std_posted >= tp->rx_std_max_post)) {
-			tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
+			tpr->rx_std_prod_idx = std_prod_idx &
+					       tp->rx_std_ring_mask;
 			tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG,
 				     tpr->rx_std_prod_idx);
 			work_mask &= ~RXD_OPAQUE_RING_STD;
@@ -4770,7 +4859,7 @@
 		}
 next_pkt_nopost:
 		sw_idx++;
-		sw_idx &= (TG3_RX_RCB_RING_SIZE(tp) - 1);
+		sw_idx &= tp->rx_ret_ring_mask;
 
 		/* Refresh hw_idx to see if there is new work */
 		if (sw_idx == hw_idx) {
@@ -4786,13 +4875,14 @@
 	/* Refill RX ring(s). */
 	if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)) {
 		if (work_mask & RXD_OPAQUE_RING_STD) {
-			tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
+			tpr->rx_std_prod_idx = std_prod_idx &
+					       tp->rx_std_ring_mask;
 			tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG,
 				     tpr->rx_std_prod_idx);
 		}
 		if (work_mask & RXD_OPAQUE_RING_JUMBO) {
-			tpr->rx_jmb_prod_idx = jmb_prod_idx %
-					       TG3_RX_JUMBO_RING_SIZE;
+			tpr->rx_jmb_prod_idx = jmb_prod_idx &
+					       tp->rx_jmb_ring_mask;
 			tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG,
 				     tpr->rx_jmb_prod_idx);
 		}
@@ -4803,8 +4893,8 @@
 		 */
 		smp_wmb();
 
-		tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
-		tpr->rx_jmb_prod_idx = jmb_prod_idx % TG3_RX_JUMBO_RING_SIZE;
+		tpr->rx_std_prod_idx = std_prod_idx & tp->rx_std_ring_mask;
+		tpr->rx_jmb_prod_idx = jmb_prod_idx & tp->rx_jmb_ring_mask;
 
 		if (tnapi != &tp->napi[1])
 			napi_schedule(&tp->napi[1].napi);
@@ -4860,9 +4950,11 @@
 		if (spr->rx_std_cons_idx < src_prod_idx)
 			cpycnt = src_prod_idx - spr->rx_std_cons_idx;
 		else
-			cpycnt = TG3_RX_RING_SIZE - spr->rx_std_cons_idx;
+			cpycnt = tp->rx_std_ring_mask + 1 -
+				 spr->rx_std_cons_idx;
 
-		cpycnt = min(cpycnt, TG3_RX_RING_SIZE - dpr->rx_std_prod_idx);
+		cpycnt = min(cpycnt,
+			     tp->rx_std_ring_mask + 1 - dpr->rx_std_prod_idx);
 
 		si = spr->rx_std_cons_idx;
 		di = dpr->rx_std_prod_idx;
@@ -4896,10 +4988,10 @@
 			dbd->addr_lo = sbd->addr_lo;
 		}
 
-		spr->rx_std_cons_idx = (spr->rx_std_cons_idx + cpycnt) %
-				       TG3_RX_RING_SIZE;
-		dpr->rx_std_prod_idx = (dpr->rx_std_prod_idx + cpycnt) %
-				       TG3_RX_RING_SIZE;
+		spr->rx_std_cons_idx = (spr->rx_std_cons_idx + cpycnt) &
+				       tp->rx_std_ring_mask;
+		dpr->rx_std_prod_idx = (dpr->rx_std_prod_idx + cpycnt) &
+				       tp->rx_std_ring_mask;
 	}
 
 	while (1) {
@@ -4916,10 +5008,11 @@
 		if (spr->rx_jmb_cons_idx < src_prod_idx)
 			cpycnt = src_prod_idx - spr->rx_jmb_cons_idx;
 		else
-			cpycnt = TG3_RX_JUMBO_RING_SIZE - spr->rx_jmb_cons_idx;
+			cpycnt = tp->rx_jmb_ring_mask + 1 -
+				 spr->rx_jmb_cons_idx;
 
 		cpycnt = min(cpycnt,
-			     TG3_RX_JUMBO_RING_SIZE - dpr->rx_jmb_prod_idx);
+			     tp->rx_jmb_ring_mask + 1 - dpr->rx_jmb_prod_idx);
 
 		si = spr->rx_jmb_cons_idx;
 		di = dpr->rx_jmb_prod_idx;
@@ -4953,10 +5046,10 @@
 			dbd->addr_lo = sbd->addr_lo;
 		}
 
-		spr->rx_jmb_cons_idx = (spr->rx_jmb_cons_idx + cpycnt) %
-				       TG3_RX_JUMBO_RING_SIZE;
-		dpr->rx_jmb_prod_idx = (dpr->rx_jmb_prod_idx + cpycnt) %
-				       TG3_RX_JUMBO_RING_SIZE;
+		spr->rx_jmb_cons_idx = (spr->rx_jmb_cons_idx + cpycnt) &
+				       tp->rx_jmb_ring_mask;
+		dpr->rx_jmb_prod_idx = (dpr->rx_jmb_prod_idx + cpycnt) &
+				       tp->rx_jmb_ring_mask;
 	}
 
 	return err;
@@ -4981,14 +5074,14 @@
 		work_done += tg3_rx(tnapi, budget - work_done);
 
 	if ((tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) && tnapi == &tp->napi[1]) {
-		struct tg3_rx_prodring_set *dpr = &tp->prodring[0];
+		struct tg3_rx_prodring_set *dpr = &tp->napi[0].prodring;
 		int i, err = 0;
 		u32 std_prod_idx = dpr->rx_std_prod_idx;
 		u32 jmb_prod_idx = dpr->rx_jmb_prod_idx;
 
 		for (i = 1; i < tp->irq_cnt; i++)
 			err |= tg3_rx_prodring_xfer(tp, dpr,
-						    tp->napi[i].prodring);
+						    &tp->napi[i].prodring);
 
 		wmb();
 
@@ -5098,6 +5191,59 @@
 	return work_done;
 }
 
+static void tg3_napi_disable(struct tg3 *tp)
+{
+	int i;
+
+	for (i = tp->irq_cnt - 1; i >= 0; i--)
+		napi_disable(&tp->napi[i].napi);
+}
+
+static void tg3_napi_enable(struct tg3 *tp)
+{
+	int i;
+
+	for (i = 0; i < tp->irq_cnt; i++)
+		napi_enable(&tp->napi[i].napi);
+}
+
+static void tg3_napi_init(struct tg3 *tp)
+{
+	int i;
+
+	netif_napi_add(tp->dev, &tp->napi[0].napi, tg3_poll, 64);
+	for (i = 1; i < tp->irq_cnt; i++)
+		netif_napi_add(tp->dev, &tp->napi[i].napi, tg3_poll_msix, 64);
+}
+
+static void tg3_napi_fini(struct tg3 *tp)
+{
+	int i;
+
+	for (i = 0; i < tp->irq_cnt; i++)
+		netif_napi_del(&tp->napi[i].napi);
+}
+
+static inline void tg3_netif_stop(struct tg3 *tp)
+{
+	tp->dev->trans_start = jiffies;	/* prevent tx timeout */
+	tg3_napi_disable(tp);
+	netif_tx_disable(tp->dev);
+}
+
+static inline void tg3_netif_start(struct tg3 *tp)
+{
+	/* NOTE: unconditional netif_tx_wake_all_queues is only
+	 * appropriate so long as all callers are assured to
+	 * have free tx slots (such as after tg3_init_hw)
+	 */
+	netif_tx_wake_all_queues(tp->dev);
+
+	tg3_napi_enable(tp);
+	tp->napi[0].hw_status->status |= SD_STATUS_UPDATED;
+	tg3_enable_ints(tp);
+}
+
 static void tg3_irq_quiesce(struct tg3 *tp)
 {
 	int i;
@@ -5111,11 +5257,6 @@
 		synchronize_irq(tp->napi[i].irq_vec);
 }
 
-static inline int tg3_irq_sync(struct tg3 *tp)
-{
-	return tp->irq_sync;
-}
-
 /* Fully shutdown all tg3 driver activity elsewhere in the system.
  * If irq_sync is non-zero, then the IRQ handler must be synchronized
  * with as well.  Most of the time, this is not necessary except when
@@ -5404,8 +5545,7 @@
 {
 	u32 base = (u32) mapping & 0xffffffff;
 
-	return ((base > 0xffffdcc0) &&
-		(base + len + 8 < base));
+	return (base > 0xffffdcc0) && (base + len + 8 < base);
 }
 
 /* Test for DMA addresses > 40-bit */
@@ -5414,7 +5554,7 @@
 {
 #if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
 	if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG)
-		return (((u64) mapping + len) > DMA_BIT_MASK(40));
+		return ((u64) mapping + len) > DMA_BIT_MASK(40);
 	return 0;
 #else
 	return 0;
@@ -5574,9 +5714,9 @@
 			goto out_unlock;
 		}
 
-		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+		if (skb_is_gso_v6(skb)) {
 			hdrlen = skb_headlen(skb) - ETH_HLEN;
-		else {
+		} else {
 			struct iphdr *iph = ip_hdr(skb);
 
 			tcp_opt_len = tcp_optlen(skb);
@@ -5605,7 +5745,7 @@
 	}
 
 #if TG3_VLAN_TAG_USED
-	if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
+	if (vlan_tx_tag_present(skb))
 		base_flags |= (TXD_FLAG_VLAN |
 			       (vlan_tx_tag_get(skb) << 16));
 #endif
@@ -5798,7 +5938,7 @@
 		iph = ip_hdr(skb);
 		tcp_opt_len = tcp_optlen(skb);
 
-		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
+		if (skb_is_gso_v6(skb)) {
 			hdr_len = skb_headlen(skb) - ETH_HLEN;
 		} else {
 			u32 ip_tcp_len;
@@ -5851,7 +5991,7 @@
 		}
 	}
 #if TG3_VLAN_TAG_USED
-	if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
+	if (vlan_tx_tag_present(skb))
 		base_flags |= (TXD_FLAG_VLAN |
 			       (vlan_tx_tag_get(skb) << 16));
 #endif
@@ -6057,16 +6197,16 @@
 {
 	int i;
 
-	if (tpr != &tp->prodring[0]) {
+	if (tpr != &tp->napi[0].prodring) {
 		for (i = tpr->rx_std_cons_idx; i != tpr->rx_std_prod_idx;
-		     i = (i + 1) % TG3_RX_RING_SIZE)
+		     i = (i + 1) & tp->rx_std_ring_mask)
 			tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i],
 					tp->rx_pkt_map_sz);
 
 		if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
 			for (i = tpr->rx_jmb_cons_idx;
 			     i != tpr->rx_jmb_prod_idx;
-			     i = (i + 1) % TG3_RX_JUMBO_RING_SIZE) {
+			     i = (i + 1) & tp->rx_jmb_ring_mask) {
 				tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i],
 						TG3_RX_JMB_MAP_SZ);
 			}
@@ -6075,12 +6215,13 @@
 		return;
 	}
 
-	for (i = 0; i < TG3_RX_RING_SIZE; i++)
+	for (i = 0; i <= tp->rx_std_ring_mask; i++)
 		tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i],
 				tp->rx_pkt_map_sz);
 
-	if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
-		for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++)
+	if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
+	    !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+		for (i = 0; i <= tp->rx_jmb_ring_mask; i++)
 			tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i],
 					TG3_RX_JMB_MAP_SZ);
 	}
@@ -6103,16 +6244,17 @@
 	tpr->rx_jmb_cons_idx = 0;
 	tpr->rx_jmb_prod_idx = 0;
 
-	if (tpr != &tp->prodring[0]) {
-		memset(&tpr->rx_std_buffers[0], 0, TG3_RX_STD_BUFF_RING_SIZE);
-		if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE)
+	if (tpr != &tp->napi[0].prodring) {
+		memset(&tpr->rx_std_buffers[0], 0,
+		       TG3_RX_STD_BUFF_RING_SIZE(tp));
+		if (tpr->rx_jmb_buffers)
 			memset(&tpr->rx_jmb_buffers[0], 0,
-			       TG3_RX_JMB_BUFF_RING_SIZE);
+			       TG3_RX_JMB_BUFF_RING_SIZE(tp));
 		goto done;
 	}
 
 	/* Zero out all descriptors. */
-	memset(tpr->rx_std, 0, TG3_RX_RING_BYTES);
+	memset(tpr->rx_std, 0, TG3_RX_STD_RING_BYTES(tp));
 
 	rx_pkt_dma_sz = TG3_RX_STD_DMA_SZ;
 	if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) &&
@@ -6124,7 +6266,7 @@
 	 * stuff once.  This works because the card does not
 	 * write into the rx buffer posting rings.
 	 */
-	for (i = 0; i < TG3_RX_RING_SIZE; i++) {
+	for (i = 0; i <= tp->rx_std_ring_mask; i++) {
 		struct tg3_rx_buffer_desc *rxd;
 
 		rxd = &tpr->rx_std[i];
@@ -6148,15 +6290,16 @@
 		}
 	}
 
-	if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE))
+	if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) ||
+	    (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
 		goto done;
 
-	memset(tpr->rx_jmb, 0, TG3_RX_JUMBO_RING_BYTES);
+	memset(tpr->rx_jmb, 0, TG3_RX_JMB_RING_BYTES(tp));
 
 	if (!(tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE))
 		goto done;
 
-	for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) {
+	for (i = 0; i <= tp->rx_jmb_ring_mask; i++) {
 		struct tg3_rx_buffer_desc *rxd;
 
 		rxd = &tpr->rx_jmb[i].std;
@@ -6196,12 +6339,12 @@
 	kfree(tpr->rx_jmb_buffers);
 	tpr->rx_jmb_buffers = NULL;
 	if (tpr->rx_std) {
-		pci_free_consistent(tp->pdev, TG3_RX_RING_BYTES,
+		pci_free_consistent(tp->pdev, TG3_RX_STD_RING_BYTES(tp),
 				    tpr->rx_std, tpr->rx_std_mapping);
 		tpr->rx_std = NULL;
 	}
 	if (tpr->rx_jmb) {
-		pci_free_consistent(tp->pdev, TG3_RX_JUMBO_RING_BYTES,
+		pci_free_consistent(tp->pdev, TG3_RX_JMB_RING_BYTES(tp),
 				    tpr->rx_jmb, tpr->rx_jmb_mapping);
 		tpr->rx_jmb = NULL;
 	}
@@ -6210,23 +6353,25 @@
 static int tg3_rx_prodring_init(struct tg3 *tp,
 				struct tg3_rx_prodring_set *tpr)
 {
-	tpr->rx_std_buffers = kzalloc(TG3_RX_STD_BUFF_RING_SIZE, GFP_KERNEL);
+	tpr->rx_std_buffers = kzalloc(TG3_RX_STD_BUFF_RING_SIZE(tp),
+				      GFP_KERNEL);
 	if (!tpr->rx_std_buffers)
 		return -ENOMEM;
 
-	tpr->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_RING_BYTES,
+	tpr->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_STD_RING_BYTES(tp),
 					   &tpr->rx_std_mapping);
 	if (!tpr->rx_std)
 		goto err_out;
 
-	if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
-		tpr->rx_jmb_buffers = kzalloc(TG3_RX_JMB_BUFF_RING_SIZE,
+	if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
+	    !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+		tpr->rx_jmb_buffers = kzalloc(TG3_RX_JMB_BUFF_RING_SIZE(tp),
 					      GFP_KERNEL);
 		if (!tpr->rx_jmb_buffers)
 			goto err_out;
 
 		tpr->rx_jmb = pci_alloc_consistent(tp->pdev,
-						   TG3_RX_JUMBO_RING_BYTES,
+						   TG3_RX_JMB_RING_BYTES(tp),
 						   &tpr->rx_jmb_mapping);
 		if (!tpr->rx_jmb)
 			goto err_out;
@@ -6253,7 +6398,7 @@
 	for (j = 0; j < tp->irq_cnt; j++) {
 		struct tg3_napi *tnapi = &tp->napi[j];
 
-		tg3_rx_prodring_free(tp, &tp->prodring[j]);
+		tg3_rx_prodring_free(tp, &tnapi->prodring);
 
 		if (!tnapi->tx_buffers)
 			continue;
@@ -6325,7 +6470,7 @@
 		if (tnapi->rx_rcb)
 			memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
 
-		if (tg3_rx_prodring_alloc(tp, &tp->prodring[i])) {
+		if (tg3_rx_prodring_alloc(tp, &tnapi->prodring)) {
 			tg3_free_rings(tp);
 			return -ENOMEM;
 		}
@@ -6361,6 +6506,8 @@
 			tnapi->rx_rcb = NULL;
 		}
 
+		tg3_rx_prodring_fini(tp, &tnapi->prodring);
+
 		if (tnapi->hw_status) {
 			pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE,
 					    tnapi->hw_status,
@@ -6374,9 +6521,6 @@
 				    tp->hw_stats, tp->stats_mapping);
 		tp->hw_stats = NULL;
 	}
-
-	for (i = 0; i < tp->irq_cnt; i++)
-		tg3_rx_prodring_fini(tp, &tp->prodring[i]);
 }
 
 /*
@@ -6387,11 +6531,6 @@
 {
 	int i;
 
-	for (i = 0; i < tp->irq_cnt; i++) {
-		if (tg3_rx_prodring_init(tp, &tp->prodring[i]))
-			goto err_out;
-	}
-
 	tp->hw_stats = pci_alloc_consistent(tp->pdev,
 					    sizeof(struct tg3_hw_stats),
 					    &tp->stats_mapping);
@@ -6413,6 +6552,9 @@
 		memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
 		sblk = tnapi->hw_status;
 
+		if (tg3_rx_prodring_init(tp, &tnapi->prodring))
+			goto err_out;
+
 		/* If multivector TSS is enabled, vector 0 does not handle
 		 * tx interrupts.  Don't allocate any resources for it.
 		 */
@@ -6452,8 +6594,6 @@
 			break;
 		}
 
-		tnapi->prodring = &tp->prodring[i];
-
 		/*
 		 * If multivector RSS is enabled, vector 0 does not handle
 		 * rx or tx interrupts.  Don't allocate any resources for it.
@@ -6596,6 +6736,10 @@
 	int i;
 	u32 apedata;
 
+	/* NCSI does not support APE events */
+	if (tp->tg3_flags3 & TG3_FLG3_APE_HAS_NCSI)
+		return;
+
 	apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
 	if (apedata != APE_SEG_SIG_MAGIC)
 		return;
@@ -6647,6 +6791,8 @@
 			APE_HOST_DRIVER_ID_MAGIC(TG3_MAJ_NUM, TG3_MIN_NUM));
 		tg3_ape_write32(tp, TG3_APE_HOST_BEHAVIOR,
 				APE_HOST_BEHAV_NO_PHYLOCK);
+		tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE,
+				    TG3_APE_HOST_DRVR_STATE_START);
 
 		event = APE_EVENT_STATUS_STATE_START;
 		break;
@@ -6658,6 +6804,16 @@
 		 */
 		tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0);
 
+		if (device_may_wakeup(&tp->pdev->dev) &&
+		    (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) {
+			tg3_ape_write32(tp, TG3_APE_HOST_WOL_SPEED,
+					    TG3_APE_HOST_WOL_SPEED_AUTO);
+			apedata = TG3_APE_HOST_DRVR_STATE_WOL;
+		} else
+			apedata = TG3_APE_HOST_DRVR_STATE_UNLOAD;
+
+		tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE, apedata);
+
 		event = APE_EVENT_STATUS_STATE_UNLOAD;
 		break;
 	case RESET_KIND_SUSPEND:
@@ -7515,6 +7671,9 @@
 	/* Disable all transmit rings but the first. */
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
 		limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16;
+	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+		 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+		limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4;
 	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
 		limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2;
 	else
@@ -7548,7 +7707,7 @@
 
 	/* Zero mailbox registers. */
 	if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) {
-		for (i = 1; i < TG3_IRQ_MAX_VECS; i++) {
+		for (i = 1; i < tp->irq_max; i++) {
 			tp->napi[i].tx_prod = 0;
 			tp->napi[i].tx_cons = 0;
 			if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)
@@ -7594,8 +7753,8 @@
 
 	if (tnapi->rx_rcb) {
 		tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
-			       (TG3_RX_RCB_RING_SIZE(tp) <<
-				BDINFO_FLAGS_MAXLEN_SHIFT), 0);
+			       (tp->rx_ret_ring_mask + 1) <<
+				BDINFO_FLAGS_MAXLEN_SHIFT, 0);
 		rxrcb += TG3_BDINFO_SIZE;
 	}
 
@@ -7618,7 +7777,7 @@
 		}
 
 		tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
-			       (TG3_RX_RCB_RING_SIZE(tp) <<
+			       ((tp->rx_ret_ring_mask + 1) <<
 				BDINFO_FLAGS_MAXLEN_SHIFT), 0);
 
 		stblk += 8;
@@ -7631,7 +7790,7 @@
 {
 	u32 val, rdmac_mode;
 	int i, err, limit;
-	struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
+	struct tg3_rx_prodring_set *tpr = &tp->napi[0].prodring;
 
 	tg3_disable_ints(tp);
 
@@ -7720,6 +7879,22 @@
 		tw32(TG3_CPMU_LSPD_10MB_CLK, val);
 	}
 
+	/* Enable MAC control of LPI */
+	if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
+		tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL,
+		       TG3_CPMU_EEE_LNKIDL_PCIE_NL0 |
+		       TG3_CPMU_EEE_LNKIDL_UART_IDL);
+
+		tw32_f(TG3_CPMU_EEE_CTRL,
+		       TG3_CPMU_EEE_CTRL_EXIT_20_1_US);
+
+		tw32_f(TG3_CPMU_EEE_MODE,
+		       TG3_CPMU_EEEMD_ERLY_L1_XIT_DET |
+		       TG3_CPMU_EEEMD_LPI_IN_TX |
+		       TG3_CPMU_EEEMD_LPI_IN_RX |
+		       TG3_CPMU_EEEMD_EEE_ENABLE);
+	}
+
 	/* This works around an issue with Athlon chipsets on
 	 * B3 tigon3 silicon.  This bit has no effect on any
 	 * other revision.  But do not set this on PCI Express
@@ -7845,7 +8020,10 @@
 	tw32(BUFMGR_DMA_HIGH_WATER,
 	     tp->bufmgr_config.dma_high_water);
 
-	tw32(BUFMGR_MODE, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
+	val = BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE;
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+		val |= BUFMGR_MODE_NO_TX_UNDERRUN;
+	tw32(BUFMGR_MODE, val);
 	for (i = 0; i < 2000; i++) {
 		if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE)
 			break;
@@ -7928,10 +8106,14 @@
 			     BDINFO_FLAGS_DISABLED);
 		}
 
-		if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)
-			val = (RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT) |
-			      (TG3_RX_STD_DMA_SZ << 2);
-		else
+		if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) {
+			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+				val = RX_STD_MAX_SIZE_5705;
+			else
+				val = RX_STD_MAX_SIZE_5717;
+			val <<= BDINFO_FLAGS_MAXLEN_SHIFT;
+			val |= (TG3_RX_STD_DMA_SZ << 2);
+		} else
 			val = TG3_RX_STD_DMA_SZ << BDINFO_FLAGS_MAXLEN_SHIFT;
 	} else
 		val = RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT;
@@ -8015,6 +8197,23 @@
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
 		rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN;
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+	    (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) {
+		val = tr32(TG3_RDMA_RSRVCTRL_REG);
+		tw32(TG3_RDMA_RSRVCTRL_REG,
+		     val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
+	}
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
+		val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
+		tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val |
+		     TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K |
+		     TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K);
+	}
+
 	/* Receive/send statistics. */
 	if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
 		val = tr32(RCVLPC_STATS_ENABLE);
@@ -8197,7 +8396,11 @@
 
 	tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE);
 	tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB);
-	tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ);
+	val = RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ;
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+		val |= RCVDBDI_MODE_LRG_RING_SZ;
+	tw32(RCVDBDI_MODE, val);
 	tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
 	if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
 		tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8);
@@ -8500,6 +8703,12 @@
 		if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
 			tg3_periodic_fetch_stats(tp);
 
+		if (tp->setlpicnt && !--tp->setlpicnt) {
+			u32 val = tr32(TG3_CPMU_EEE_MODE);
+			tw32(TG3_CPMU_EEE_MODE,
+			     val | TG3_CPMU_EEEMD_LPI_ENABLE);
+		}
+
 		if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
 			u32 mac_stat;
 			int phy_event;
@@ -8816,16 +9025,14 @@
 	for (i = 0; i < tp->irq_max; i++)
 		tp->napi[i].irq_vec = msix_ent[i].vector;
 
-	tp->dev->real_num_tx_queues = 1;
-	if (tp->irq_cnt > 1) {
-		tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS;
-
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
-		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
-			tp->tg3_flags3 |= TG3_FLG3_ENABLE_TSS;
-			tp->dev->real_num_tx_queues = tp->irq_cnt - 1;
-		}
+	netif_set_real_num_tx_queues(tp->dev, 1);
+	rc = tp->irq_cnt > 1 ? tp->irq_cnt - 1 : 1;
+	if (netif_set_real_num_rx_queues(tp->dev, rc)) {
+		pci_disable_msix(tp->pdev);
+		return false;
 	}
+	if (tp->irq_cnt > 1)
+		tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS;
 
 	return true;
 }
@@ -8858,7 +9065,8 @@
 	if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) {
 		tp->irq_cnt = 1;
 		tp->napi[0].irq_vec = tp->pdev->irq;
-		tp->dev->real_num_tx_queues = 1;
+		netif_set_real_num_tx_queues(tp->dev, 1);
+		netif_set_real_num_rx_queues(tp->dev, 1);
 	}
 }
 
@@ -8917,6 +9125,8 @@
 	if (err)
 		goto err_out1;
 
+	tg3_napi_init(tp);
+
 	tg3_napi_enable(tp);
 
 	for (i = 0; i < tp->irq_cnt; i++) {
@@ -9004,6 +9214,7 @@
 
 err_out2:
 	tg3_napi_disable(tp);
+	tg3_napi_fini(tp);
 	tg3_free_consistent(tp);
 
 err_out1:
@@ -9051,6 +9262,8 @@
 	memcpy(&tp->estats_prev, tg3_get_estats(tp),
 	       sizeof(tp->estats_prev));
 
+	tg3_napi_fini(tp);
+
 	tg3_free_consistent(tp);
 
 	tg3_set_power_state(tp, PCI_D3hot);
@@ -9240,6 +9453,8 @@
 	stats->rx_missed_errors = old_stats->rx_missed_errors +
 		get_stat64(&hw_stats->rx_discards);
 
+	stats->rx_dropped = tp->rx_dropped;
+
 	return stats;
 }
 
@@ -9594,6 +9809,9 @@
 	if (netif_running(dev)) {
 		cmd->speed = tp->link_config.active_speed;
 		cmd->duplex = tp->link_config.active_duplex;
+	} else {
+		cmd->speed = SPEED_INVALID;
+		cmd->duplex = DUPLEX_INVALID;
 	}
 	cmd->phy_address = tp->phy_addr;
 	cmd->transceiver = XCVR_INTERNAL;
@@ -9820,10 +10038,10 @@
 {
 	struct tg3 *tp = netdev_priv(dev);
 
-	ering->rx_max_pending = TG3_RX_RING_SIZE - 1;
+	ering->rx_max_pending = tp->rx_std_ring_mask;
 	ering->rx_mini_max_pending = 0;
 	if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE)
-		ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1;
+		ering->rx_jumbo_max_pending = tp->rx_jmb_ring_mask;
 	else
 		ering->rx_jumbo_max_pending = 0;
 
@@ -9844,8 +10062,8 @@
 	struct tg3 *tp = netdev_priv(dev);
 	int i, irq_sync = 0, err = 0;
 
-	if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
-	    (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
+	if ((ering->rx_pending > tp->rx_std_ring_mask) ||
+	    (ering->rx_jumbo_pending > tp->rx_jmb_ring_mask) ||
 	    (ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
 	    (ering->tx_pending <= MAX_SKB_FRAGS) ||
 	    ((tp->tg3_flags2 & TG3_FLG2_TSO_BUG) &&
@@ -9867,7 +10085,7 @@
 		tp->rx_pending = 63;
 	tp->rx_jumbo_pending = ering->rx_jumbo_pending;
 
-	for (i = 0; i < TG3_IRQ_MAX_VECS; i++)
+	for (i = 0; i < tp->irq_max; i++)
 		tp->napi[i].tx_pending = ering->tx_pending;
 
 	if (netif_running(dev)) {
@@ -9915,8 +10133,7 @@
 
 		if (!(phydev->supported & SUPPORTED_Pause) ||
 		    (!(phydev->supported & SUPPORTED_Asym_Pause) &&
-		     ((epause->rx_pause && !epause->tx_pause) ||
-		      (!epause->rx_pause && epause->tx_pause))))
+		     (epause->rx_pause != epause->tx_pause)))
 			return -EINVAL;
 
 		tp->link_config.flowctrl = 0;
@@ -10608,12 +10825,13 @@
 	int num_pkts, tx_len, rx_len, i, err;
 	struct tg3_rx_buffer_desc *desc;
 	struct tg3_napi *tnapi, *rnapi;
-	struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
+	struct tg3_rx_prodring_set *tpr = &tp->napi[0].prodring;
 
 	tnapi = &tp->napi[0];
 	rnapi = &tp->napi[0];
 	if (tp->irq_cnt > 1) {
-		rnapi = &tp->napi[1];
+		if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)
+			rnapi = &tp->napi[1];
 		if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)
 			tnapi = &tp->napi[1];
 	}
@@ -12330,6 +12548,11 @@
 		}
 	}
 
+	if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
+	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
+	     tp->pci_chip_rev_id != CHIPREV_ID_57765_A0))
+		tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
+
 	if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
 	    !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) &&
 	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
@@ -12401,14 +12624,18 @@
 
 static void __devinit tg3_read_vpd(struct tg3 *tp)
 {
-	u8 vpd_data[TG3_NVM_VPD_LEN];
+	u8 *vpd_data;
 	unsigned int block_end, rosize, len;
 	int j, i = 0;
 	u32 magic;
 
 	if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
 	    tg3_nvram_read(tp, 0x0, &magic))
-		goto out_not_found;
+		goto out_no_vpd;
+
+	vpd_data = kmalloc(TG3_NVM_VPD_LEN, GFP_KERNEL);
+	if (!vpd_data)
+		goto out_no_vpd;
 
 	if (magic == TG3_EEPROM_MAGIC) {
 		for (i = 0; i < TG3_NVM_VPD_LEN; i += 4) {
@@ -12492,43 +12719,51 @@
 
 	memcpy(tp->board_part_number, &vpd_data[i], len);
 
-	return;
-
 out_not_found:
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+	kfree(vpd_data);
+	if (tp->board_part_number[0])
+		return;
+
+out_no_vpd:
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+		if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717)
+			strcpy(tp->board_part_number, "BCM5717");
+		else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718)
+			strcpy(tp->board_part_number, "BCM5718");
+		else
+			goto nomatch;
+	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
+		if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57780)
+			strcpy(tp->board_part_number, "BCM57780");
+		else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57760)
+			strcpy(tp->board_part_number, "BCM57760");
+		else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790)
+			strcpy(tp->board_part_number, "BCM57790");
+		else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57788)
+			strcpy(tp->board_part_number, "BCM57788");
+		else
+			goto nomatch;
+	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) {
+		if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761)
+			strcpy(tp->board_part_number, "BCM57761");
+		else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765)
+			strcpy(tp->board_part_number, "BCM57765");
+		else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781)
+			strcpy(tp->board_part_number, "BCM57781");
+		else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785)
+			strcpy(tp->board_part_number, "BCM57785");
+		else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791)
+			strcpy(tp->board_part_number, "BCM57791");
+		else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795)
+			strcpy(tp->board_part_number, "BCM57795");
+		else
+			goto nomatch;
+	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 		strcpy(tp->board_part_number, "BCM95906");
-	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
-		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57780)
-		strcpy(tp->board_part_number, "BCM57780");
-	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
-		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57760)
-		strcpy(tp->board_part_number, "BCM57760");
-	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
-		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790)
-		strcpy(tp->board_part_number, "BCM57790");
-	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
-		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57788)
-		strcpy(tp->board_part_number, "BCM57788");
-	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761)
-		strcpy(tp->board_part_number, "BCM57761");
-	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765)
-		strcpy(tp->board_part_number, "BCM57765");
-	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781)
-		strcpy(tp->board_part_number, "BCM57781");
-	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785)
-		strcpy(tp->board_part_number, "BCM57785");
-	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791)
-		strcpy(tp->board_part_number, "BCM57791");
-	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795)
-		strcpy(tp->board_part_number, "BCM57795");
-	else
+	} else {
+nomatch:
 		strcpy(tp->board_part_number, "none");
+	}
 }
 
 static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
@@ -12637,6 +12872,9 @@
 	case TG3_EEPROM_SB_REVISION_5:
 		offset = TG3_EEPROM_SB_F1R5_EDH_OFF;
 		break;
+	case TG3_EEPROM_SB_REVISION_6:
+		offset = TG3_EEPROM_SB_F1R6_EDH_OFF;
+		break;
 	default:
 		return;
 	}
@@ -12736,10 +12974,12 @@
 
 	apedata = tg3_ape_read32(tp, TG3_APE_FW_VERSION);
 
-	if (tg3_ape_read32(tp, TG3_APE_FW_FEATURES) & TG3_APE_FW_FEATURE_NCSI)
+	if (tg3_ape_read32(tp, TG3_APE_FW_FEATURES) & TG3_APE_FW_FEATURE_NCSI) {
+		tp->tg3_flags3 |= TG3_FLG3_APE_HAS_NCSI;
 		fwtype = "NCSI";
-	else
+	} else {
 		fwtype = "DASH";
+	}
 
 	vlen = strlen(tp->fw_ver);
 
@@ -12795,6 +13035,18 @@
 #endif
 }
 
+static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp)
+{
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+		return 4096;
+	else if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
+		 !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
+		return 1024;
+	else
+		return 512;
+}
+
 static int __devinit tg3_get_invariants(struct tg3 *tp)
 {
 	static struct pci_device_id write_reorder_chipsets[] = {
@@ -12839,7 +13091,6 @@
 
 		if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
 		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
-		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5724 ||
 		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719)
 			pci_read_config_dword(tp->pdev,
 					      TG3PCI_GEN2_PRODID_ASICREV,
@@ -13410,10 +13661,6 @@
 	if (err)
 		return err;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
-	    tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
-		return -ENOTSUPP;
-
 	/* Initialize data/descriptor byte/word swapping. */
 	val = tr32(GRC_MODE);
 	val &= GRC_MODE_HOST_STACKUP;
@@ -13553,7 +13800,11 @@
 #endif
 	}
 
-	tp->rx_std_max_post = TG3_RX_RING_SIZE;
+	tp->rx_std_ring_mask = TG3_RX_STD_RING_SIZE(tp) - 1;
+	tp->rx_jmb_ring_mask = TG3_RX_JMB_RING_SIZE(tp) - 1;
+	tp->rx_ret_ring_mask = tg3_rx_ret_ring_size(tp) - 1;
+
+	tp->rx_std_max_post = tp->rx_std_ring_mask + 1;
 
 	/* Increment the rx prod index on the rx std ring by at most
 	 * 8 for these chips to workaround hw errata.
@@ -14442,7 +14693,7 @@
 	}
 
 	if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) &&
-	    tp->pci_chip_rev_id != CHIPREV_ID_5717_A0 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
 	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719)
 		dev->netdev_ops = &tg3_netdev_ops;
 	else
@@ -14581,7 +14832,7 @@
 	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;
-	for (i = 0; i < TG3_IRQ_MAX_VECS; i++) {
+	for (i = 0; i < tp->irq_max; i++) {
 		struct tg3_napi *tnapi = &tp->napi[i];
 
 		tnapi->tp = tp;
@@ -14596,13 +14847,10 @@
 		tnapi->consmbox = rcvmbx;
 		tnapi->prodmbox = sndmbx;
 
-		if (i) {
+		if (i)
 			tnapi->coal_now = HOSTCC_MODE_COAL_VEC1_NOW << (i - 1);
-			netif_napi_add(dev, &tnapi->napi, tg3_poll_msix, 64);
-		} else {
+		else
 			tnapi->coal_now = HOSTCC_MODE_NOW;
-			netif_napi_add(dev, &tnapi->napi, tg3_poll, 64);
-		}
 
 		if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX))
 			break;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 4937bd1..4a19748 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -26,6 +26,7 @@
 #define TG3_RX_INTERNAL_RING_SZ_5906	32
 
 #define RX_STD_MAX_SIZE_5705		512
+#define RX_STD_MAX_SIZE_5717		2048
 #define RX_JUMBO_MAX_SIZE		0xdeadbeef /* XXX */
 
 /* First 256 bytes are a mirror of PCI config space. */
@@ -46,7 +47,6 @@
 #define  TG3PCI_DEVICE_TIGON3_5785_F	 0x16a0 /* 10/100 only */
 #define  TG3PCI_DEVICE_TIGON3_5717	 0x1655
 #define  TG3PCI_DEVICE_TIGON3_5718	 0x1656
-#define  TG3PCI_DEVICE_TIGON3_5724	 0x165c
 #define  TG3PCI_DEVICE_TIGON3_57781	 0x16b1
 #define  TG3PCI_DEVICE_TIGON3_57785	 0x16b5
 #define  TG3PCI_DEVICE_TIGON3_57761	 0x16b0
@@ -973,6 +973,7 @@
 #define  RCVDBDI_MODE_JUMBOBD_NEEDED	 0x00000004
 #define  RCVDBDI_MODE_FRM_TOO_BIG	 0x00000008
 #define  RCVDBDI_MODE_INV_RING_SZ	 0x00000010
+#define  RCVDBDI_MODE_LRG_RING_SZ	 0x00010000
 #define RCVDBDI_STATUS			0x00002404
 #define  RCVDBDI_STATUS_JUMBOBD_NEEDED	 0x00000004
 #define  RCVDBDI_STATUS_FRM_TOO_BIG	 0x00000008
@@ -1090,7 +1091,26 @@
 #define  CPMU_MUTEX_GNT_DRIVER		 0x00001000
 #define TG3_CPMU_PHY_STRAP		0x00003664
 #define TG3_CPMU_PHY_STRAP_IS_SERDES	 0x00000020
-/* 0x3664 --> 0x3800 unused */
+/* 0x3664 --> 0x36b0 unused */
+
+#define TG3_CPMU_EEE_MODE		0x000036b0
+#define TG3_CPMU_EEEMD_ERLY_L1_XIT_DET	 0x00000008
+#define TG3_CPMU_EEEMD_LPI_ENABLE	 0x00000080
+#define TG3_CPMU_EEEMD_LPI_IN_TX	 0x00000100
+#define TG3_CPMU_EEEMD_LPI_IN_RX	 0x00000200
+#define TG3_CPMU_EEEMD_EEE_ENABLE	 0x00100000
+/* 0x36b4 --> 0x36b8 unused */
+
+#define TG3_CPMU_EEE_LNKIDL_CTRL	0x000036bc
+#define  TG3_CPMU_EEE_LNKIDL_PCIE_NL0	 0x01000000
+#define  TG3_CPMU_EEE_LNKIDL_UART_IDL	 0x00000004
+/* 0x36c0 --> 0x36d0 unused */
+
+#define TG3_CPMU_EEE_CTRL		0x000036d0
+#define TG3_CPMU_EEE_CTRL_EXIT_16_5_US	 0x0000019d
+#define TG3_CPMU_EEE_CTRL_EXIT_36_US	 0x00000384
+#define TG3_CPMU_EEE_CTRL_EXIT_20_1_US	 0x000001f8
+/* 0x36d4 --> 0x3800 unused */
 
 /* Mbuf cluster free registers */
 #define MBFREE_MODE			0x00003800
@@ -1225,6 +1245,7 @@
 #define  BUFMGR_MODE_ATTN_ENABLE	 0x00000004
 #define  BUFMGR_MODE_BM_TEST		 0x00000008
 #define  BUFMGR_MODE_MBLOW_ATTN_ENAB	 0x00000010
+#define  BUFMGR_MODE_NO_TX_UNDERRUN	 0x80000000
 #define BUFMGR_STATUS			0x00004404
 #define  BUFMGR_STATUS_ERROR		 0x00000004
 #define  BUFMGR_STATUS_MBLOW		 0x00000010
@@ -1302,7 +1323,16 @@
 #define  RDMAC_STATUS_FIFOURUN		 0x00000080
 #define  RDMAC_STATUS_FIFOOREAD		 0x00000100
 #define  RDMAC_STATUS_LNGREAD		 0x00000200
-/* 0x4808 --> 0x4c00 unused */
+/* 0x4808 --> 0x4900 unused */
+
+#define TG3_RDMA_RSRVCTRL_REG		0x00004900
+#define TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX	 0x00000004
+/* 0x4904 --> 0x4910 unused */
+
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL	0x00004910
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K	 0x00030000
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K	 0x000c0000
+/* 0x4914 --> 0x4c00 unused */
 
 /* Write DMA control registers */
 #define WDMAC_MODE			0x00004c00
@@ -1904,6 +1934,7 @@
 #define TG3_EEPROM_SB_REVISION_3	0x00030000
 #define TG3_EEPROM_SB_REVISION_4	0x00040000
 #define TG3_EEPROM_SB_REVISION_5	0x00050000
+#define TG3_EEPROM_SB_REVISION_6	0x00060000
 #define TG3_EEPROM_MAGIC_HW		0xabcd
 #define TG3_EEPROM_MAGIC_HW_MSK		0xffff
 
@@ -1923,6 +1954,7 @@
 #define TG3_EEPROM_SB_F1R3_EDH_OFF	0x18
 #define TG3_EEPROM_SB_F1R4_EDH_OFF	0x1c
 #define TG3_EEPROM_SB_F1R5_EDH_OFF	0x20
+#define TG3_EEPROM_SB_F1R6_EDH_OFF	0x4c
 #define TG3_EEPROM_SB_EDH_MAJ_MASK	0x00000700
 #define TG3_EEPROM_SB_EDH_MAJ_SHFT	8
 #define TG3_EEPROM_SB_EDH_MIN_MASK	0x000000ff
@@ -2048,6 +2080,10 @@
 #define  MII_TG3_CTRL_AS_MASTER		0x0800
 #define  MII_TG3_CTRL_ENABLE_AS_MASTER	0x1000
 
+#define MII_TG3_MMD_CTRL		0x0d /* MMD Access Control register */
+#define MII_TG3_MMD_CTRL_DATA_NOINC	0x4000
+#define MII_TG3_MMD_ADDRESS		0x0e /* MMD Address Data register */
+
 #define MII_TG3_EXT_CTRL		0x10 /* Extended control register */
 #define  MII_TG3_EXT_CTRL_FIFO_ELASTIC	0x0001
 #define  MII_TG3_EXT_CTRL_LNK3_LED_MODE	0x0002
@@ -2065,6 +2101,8 @@
 #define MII_TG3_DSP_TAP1		0x0001
 #define  MII_TG3_DSP_TAP1_AGCTGT_DFLT	0x0007
 #define MII_TG3_DSP_AADJ1CH0		0x001f
+#define MII_TG3_DSP_CH34TP2		0x4022
+#define MII_TG3_DSP_CH34TP2_HIBW01	0x0010
 #define MII_TG3_DSP_AADJ1CH3		0x601f
 #define  MII_TG3_DSP_AADJ1CH3_ADCCKADJ	0x0002
 #define MII_TG3_DSP_EXP1_INT_STAT	0x0f01
@@ -2131,6 +2169,14 @@
 #define MII_TG3_TEST1_TRIM_EN		0x0010
 #define MII_TG3_TEST1_CRC_EN		0x8000
 
+/* Clause 45 expansion registers */
+#define TG3_CL45_D7_EEEADV_CAP		0x003c
+#define TG3_CL45_D7_EEEADV_CAP_100TX	0x0002
+#define TG3_CL45_D7_EEEADV_CAP_1000T	0x0004
+#define TG3_CL45_D7_EEERES_STAT		0x803e
+#define TG3_CL45_D7_EEERES_STAT_LP_100TX	0x0002
+#define TG3_CL45_D7_EEERES_STAT_LP_1000T	0x0004
+
 
 /* Fast Ethernet Tranceiver definitions */
 #define MII_TG3_FET_PTEST		0x17
@@ -2176,7 +2222,7 @@
 #define TG3_APE_HOST_SEG_SIG		0x4200
 #define  APE_HOST_SEG_SIG_MAGIC		 0x484f5354
 #define TG3_APE_HOST_SEG_LEN		0x4204
-#define  APE_HOST_SEG_LEN_MAGIC		 0x0000001c
+#define  APE_HOST_SEG_LEN_MAGIC		 0x00000020
 #define TG3_APE_HOST_INIT_COUNT		0x4208
 #define TG3_APE_HOST_DRIVER_ID		0x420c
 #define  APE_HOST_DRIVER_ID_LINUX	 0xf0000000
@@ -2188,6 +2234,12 @@
 #define  APE_HOST_HEARTBEAT_INT_DISABLE	 0
 #define  APE_HOST_HEARTBEAT_INT_5SEC	 5000
 #define TG3_APE_HOST_HEARTBEAT_COUNT	0x4218
+#define TG3_APE_HOST_DRVR_STATE		0x421c
+#define TG3_APE_HOST_DRVR_STATE_START	 0x00000001
+#define TG3_APE_HOST_DRVR_STATE_UNLOAD	 0x00000002
+#define TG3_APE_HOST_DRVR_STATE_WOL	 0x00000003
+#define TG3_APE_HOST_WOL_SPEED		0x4224
+#define TG3_APE_HOST_WOL_SPEED_AUTO	 0x00008000
 
 #define TG3_APE_EVENT_STATUS		0x4300
 
@@ -2649,7 +2701,8 @@
 	dma_addr_t			rx_jmb_mapping;
 };
 
-#define TG3_IRQ_MAX_VECS 5
+#define TG3_IRQ_MAX_VECS_RSS		5
+#define TG3_IRQ_MAX_VECS		TG3_IRQ_MAX_VECS_RSS
 
 struct tg3_napi {
 	struct napi_struct		napi	____cacheline_aligned;
@@ -2668,7 +2721,7 @@
 	u32				consmbox;
 	u32				rx_rcb_ptr;
 	u16				*rx_rcb_prod_idx;
-	struct tg3_rx_prodring_set	*prodring;
+	struct tg3_rx_prodring_set	prodring;
 
 	struct tg3_rx_buffer_desc	*rx_rcb;
 	struct tg3_tx_buffer_desc	*tx_ring;
@@ -2746,6 +2799,9 @@
 	void				(*write32_rx_mbox) (struct tg3 *, u32,
 							    u32);
 	u32				rx_copy_thresh;
+	u32				rx_std_ring_mask;
+	u32				rx_jmb_ring_mask;
+	u32				rx_ret_ring_mask;
 	u32				rx_pending;
 	u32				rx_jumbo_pending;
 	u32				rx_std_max_post;
@@ -2755,11 +2811,9 @@
 	struct vlan_group		*vlgrp;
 #endif
 
-	struct tg3_rx_prodring_set	prodring[TG3_IRQ_MAX_VECS];
-
 
 	/* begin "everything else" cacheline(s) section */
-	struct rtnl_link_stats64	net_stats;
+	unsigned long			rx_dropped;
 	struct rtnl_link_stats64	net_stats_prev;
 	struct tg3_ethtool_stats	estats;
 	struct tg3_ethtool_stats	estats_prev;
@@ -2850,6 +2904,7 @@
 #define TG3_FLG3_USE_JUMBO_BDFLAG	0x00400000
 #define TG3_FLG3_L1PLLPD_EN		0x00800000
 #define TG3_FLG3_5717_PLUS		0x01000000
+#define TG3_FLG3_APE_HAS_NCSI		0x02000000
 
 	struct timer_list		timer;
 	u16				timer_counter;
@@ -2966,9 +3021,11 @@
 #define TG3_PHYFLG_BER_BUG		0x00008000
 #define TG3_PHYFLG_SERDES_PREEMPHASIS	0x00010000
 #define TG3_PHYFLG_PARALLEL_DETECT	0x00020000
+#define TG3_PHYFLG_EEE_CAP		0x00040000
 
 	u32				led_ctrl;
 	u32				phy_otp;
+	u32				setlpicnt;
 
 #define TG3_BPN_SIZE			24
 	char				board_part_number[TG3_BPN_SIZE];
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index ccee3ed..ec8c804 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -393,7 +393,7 @@
 			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);
 
@@ -1453,7 +1453,7 @@
 		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.function = TLan_Timer;
 			 priv->timer.data = (unsigned long) dev;
 			 priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
 			 priv->timerSetAt = jiffies;
@@ -1601,7 +1601,7 @@
 		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.function = TLan_Timer;
 			priv->timer.data = (unsigned long) dev;
 			priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
 			priv->timerSetAt = jiffies;
@@ -1897,7 +1897,7 @@
 					TLan_DioWrite8( dev->base_addr,
 							TLAN_LED_REG, TLAN_LED_LINK );
 				} else  {
-					priv->timer.function = &TLan_Timer;
+					priv->timer.function = TLan_Timer;
 					priv->timer.expires = priv->timerSetAt
 						+ TLAN_TIMER_ACT_DELAY;
 					spin_unlock_irqrestore(&priv->lock, flags);
@@ -3187,7 +3187,7 @@
 		TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
 	}
 
-	return ( err );
+	return err;
 
 } /* TLan_EeSendByte */
 
diff --git a/drivers/net/tlan.h b/drivers/net/tlan.h
index d13ff12..3315ced 100644
--- a/drivers/net/tlan.h
+++ b/drivers/net/tlan.h
@@ -442,7 +442,7 @@
 static inline u8 TLan_DioRead8(u16 base_addr, u16 internal_addr)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
-	return (inb((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x3)));
+	return inb((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x3));
 
 } /* TLan_DioRead8 */
 
@@ -452,7 +452,7 @@
 static inline u16 TLan_DioRead16(u16 base_addr, u16 internal_addr)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
-	return (inw((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x2)));
+	return inw((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x2));
 
 } /* TLan_DioRead16 */
 
@@ -462,7 +462,7 @@
 static inline u32 TLan_DioRead32(u16 base_addr, u16 internal_addr)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
-	return (inl(base_addr + TLAN_DIO_DATA));
+	return inl(base_addr + TLAN_DIO_DATA);
 
 } /* TLan_DioRead32 */
 
@@ -537,6 +537,6 @@
         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/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
index 16e8783..8d362e6 100644
--- a/drivers/net/tokenring/proteon.c
+++ b/drivers/net/tokenring/proteon.c
@@ -110,7 +110,7 @@
 	}
 
 	dev->base_addr = ioaddr;
-	return (0);
+	return 0;
 nodev:
 	release_region(ioaddr, PROTEON_IO_EXTENT); 
 	return -ENODEV;
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index 0929fff..63db5a6 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -435,7 +435,7 @@
                 RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[NON_MAC_QUEUE]);
         tp->rx_buff_end[NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
 
-        return (0);
+        return 0;
 }
 
 /* Enter Bypass state. */
@@ -448,7 +448,7 @@
 
         err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE, JS_BYPASS_STATE);
 
-        return (err);
+        return err;
 }
 
 static int smctr_checksum_firmware(struct net_device *dev)
@@ -471,9 +471,9 @@
         smctr_disable_adapter_ctrl_store(dev);
 
         if(checksum)
-                return (checksum);
+                return checksum;
 
-        return (0);
+        return 0;
 }
 
 static int __init smctr_chk_mca(struct net_device *dev)
@@ -485,7 +485,7 @@
 
 	current_slot = mca_find_unused_adapter(smctr_posid, 0);
 	if(current_slot == MCA_NOTFOUND)
-		return (-ENODEV);
+		return -ENODEV;
 
 	mca_set_adapter_name(current_slot, smctr_name);
 	mca_mark_as_used(current_slot);
@@ -622,9 +622,9 @@
                         break;
         }
 
-	return (0);
+	return 0;
 #else
-	return (-1);
+	return -1;
 #endif /* CONFIG_MCA_LEGACY */
 }
 
@@ -677,18 +677,18 @@
         if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_0,
                 &tp->config_word0)))
         {
-                return (err);
+                return err;
         }
 
         if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_1,
                 &tp->config_word1)))
         {
-                return (err);
+                return err;
         }
 
         smctr_disable_16bit(dev);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_clear_int(struct net_device *dev)
@@ -697,7 +697,7 @@
 
         outb((tp->trc_mask | CSR_CLRTINT), dev->base_addr + CSR);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_clear_trc_reset(int ioaddr)
@@ -707,7 +707,7 @@
         r = inb(ioaddr + MSR);
         outb(~MSR_RST & r, ioaddr + MSR);
 
-        return (0);
+        return 0;
 }
 
 /*
@@ -725,7 +725,7 @@
 
         /* Check to see if adapter is already in a closed state. */
         if(tp->status != OPEN)
-                return (0);
+                return 0;
 
         smctr_enable_16bit(dev);
         smctr_set_page(dev, (__u8 *)tp->ram_access);
@@ -733,7 +733,7 @@
         if((err = smctr_issue_remove_cmd(dev)))
         {
                 smctr_disable_16bit(dev);
-                return (err);
+                return err;
         }
 
         for(;;)
@@ -746,7 +746,7 @@
         }
 
 
-        return (0);
+        return 0;
 }
 
 static int smctr_decode_firmware(struct net_device *dev,
@@ -807,12 +807,12 @@
         if(buff)
                 *(mem++) = SWAP_BYTES(buff);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_disable_16bit(struct net_device *dev)
 {
-        return (0);
+        return 0;
 }
 
 /*
@@ -832,7 +832,7 @@
         tp->trc_mask |= CSR_WCSS;
         outb(tp->trc_mask, ioaddr + CSR);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_disable_bic_int(struct net_device *dev)
@@ -844,7 +844,7 @@
 	        | CSR_MSKTINT | CSR_WCSS;
         outb(tp->trc_mask, ioaddr + CSR);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_enable_16bit(struct net_device *dev)
@@ -858,7 +858,7 @@
                 outb((r | LAAR_MEM16ENB), dev->base_addr + LAAR);
         }
 
-        return (0);
+        return 0;
 }
 
 /*
@@ -881,7 +881,7 @@
         tp->trc_mask &= ~CSR_WCSS;
         outb(tp->trc_mask, ioaddr + CSR);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_enable_adapter_ram(struct net_device *dev)
@@ -895,7 +895,7 @@
         r = inb(ioaddr + MSR);
         outb(MSR_MEMB | r, ioaddr + MSR);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_enable_bic_int(struct net_device *dev)
@@ -921,7 +921,7 @@
                         break;
         }
 
-        return (0);
+        return 0;
 }
 
 static int __init smctr_chk_isa(struct net_device *dev)
@@ -1145,7 +1145,7 @@
 		*/
         }
 
-        return (0);
+        return 0;
 
 out2:
 	release_region(ioaddr, SMCTR_IO_EXTENT);
@@ -1199,7 +1199,7 @@
          *      return;
          */
         if(IdByte & 0xF8)
-                return (-1);
+                return -1;
 
         r1 = inb(ioaddr + BID_REG_1);
         r1 &= BID_ICR_MASK;
@@ -1250,21 +1250,21 @@
         while(r1 & BID_RECALL_DONE_MASK)
                 r1 = inb(ioaddr + BID_REG_1);
 
-        return (BoardIdMask);
+        return BoardIdMask;
 }
 
 static int smctr_get_group_address(struct net_device *dev)
 {
         smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_GROUP_ADDR);
 
-        return(smctr_wait_cmd(dev));
+        return smctr_wait_cmd(dev);
 }
 
 static int smctr_get_functional_address(struct net_device *dev)
 {
         smctr_issue_read_word_cmd(dev, RW_FUNCTIONAL_ADDR);
 
-        return(smctr_wait_cmd(dev));
+        return smctr_wait_cmd(dev);
 }
 
 /* Calculate number of Non-MAC receive BDB's and data buffers.
@@ -1346,14 +1346,14 @@
          */
         mem_used += 0x100;
 
-        return((0xffff - mem_used) / (RX_DATA_BUFFER_SIZE + sizeof(BDBlock)));
+        return (0xffff - mem_used) / (RX_DATA_BUFFER_SIZE + sizeof(BDBlock));
 }
 
 static int smctr_get_physical_drop_number(struct net_device *dev)
 {
         smctr_issue_read_word_cmd(dev, RW_PHYSICAL_DROP_NUMBER);
 
-        return(smctr_wait_cmd(dev));
+        return smctr_wait_cmd(dev);
 }
 
 static __u8 * smctr_get_rx_pointer(struct net_device *dev, short queue)
@@ -1366,14 +1366,14 @@
 
         tp->rx_fcb_curr[queue]->bdb_ptr = bdb;
 
-        return ((__u8 *)bdb->data_block_ptr);
+        return (__u8 *)bdb->data_block_ptr;
 }
 
 static int smctr_get_station_id(struct net_device *dev)
 {
         smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_MAC_ADDRESS);
 
-        return(smctr_wait_cmd(dev));
+        return smctr_wait_cmd(dev);
 }
 
 /*
@@ -1384,7 +1384,7 @@
 {
         struct net_local *tp = netdev_priv(dev);
 
-        return ((struct net_device_stats *)&tp->MacStat);
+        return (struct net_device_stats *)&tp->MacStat;
 }
 
 static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
@@ -1401,14 +1401,14 @@
 
         /* check if there is enough FCB blocks */
         if(tp->num_tx_fcbs_used[queue] >= tp->num_tx_fcbs[queue])
-                return ((FCBlock *)(-1L));
+                return (FCBlock *)(-1L);
 
         /* round off the input pkt size to the nearest even number */
         alloc_size = (bytes_count + 1) & 0xfffe;
 
         /* check if enough mem */
         if((tp->tx_buff_used[queue] + alloc_size) > tp->tx_buff_size[queue])
-                return ((FCBlock *)(-1L));
+                return (FCBlock *)(-1L);
 
         /* check if past the end ;
          * if exactly enough mem to end of ring, alloc from front.
@@ -1425,7 +1425,7 @@
                 if((tp->tx_buff_used[queue] + alloc_size)
                         > tp->tx_buff_size[queue])
                 {
-                        return ((FCBlock *)(-1L));
+                        return (FCBlock *)(-1L);
                 }
 
                 /* ring wrap */
@@ -1448,14 +1448,14 @@
         pFCB = tp->tx_fcb_curr[queue];
         tp->tx_fcb_curr[queue] = tp->tx_fcb_curr[queue]->next_ptr;
 
-        return (pFCB);
+        return pFCB;
 }
 
 static int smctr_get_upstream_neighbor_addr(struct net_device *dev)
 {
         smctr_issue_read_word_cmd(dev, RW_UPSTREAM_NEIGHBOR_ADDRESS);
 
-        return(smctr_wait_cmd(dev));
+        return smctr_wait_cmd(dev);
 }
 
 static int smctr_hardware_send_packet(struct net_device *dev,
@@ -1469,21 +1469,22 @@
                 printk(KERN_DEBUG"%s: smctr_hardware_send_packet\n", dev->name);
 
         if(tp->status != OPEN)
-                return (-1);
+                return -1;
 
         if(tp->monitor_state_ready != 1)
-                return (-1);
+                return -1;
 
         for(;;)
         {
                 /* Send first buffer from queue */
                 skb = skb_dequeue(&tp->SendSkbQueue);
                 if(skb == NULL)
-                        return (-1);
+                        return -1;
 
                 tp->QueueSkb++;
 
-                if(skb->len < SMC_HEADER_SIZE || skb->len > tp->max_packet_size)                        return (-1);
+                if(skb->len < SMC_HEADER_SIZE || skb->len > tp->max_packet_size)
+			return -1;
 
                 smctr_enable_16bit(dev);
                 smctr_set_page(dev, (__u8 *)tp->ram_access);
@@ -1492,7 +1493,7 @@
                         == (FCBlock *)(-1L))
                 {
                         smctr_disable_16bit(dev);
-                        return (-1);
+                        return -1;
                 }
 
                 smctr_tx_move_frame(dev, skb,
@@ -1508,7 +1509,7 @@
                 smctr_disable_16bit(dev);
         }
 
-        return (0);
+        return 0;
 }
 
 static int smctr_init_acbs(struct net_device *dev)
@@ -1552,7 +1553,7 @@
         tp->acb_curr            = tp->acb_head->next_ptr;
         tp->num_acbs_used       = 0;
 
-        return (0);
+        return 0;
 }
 
 static int smctr_init_adapter(struct net_device *dev)
@@ -1590,13 +1591,14 @@
 
         if(smctr_checksum_firmware(dev))
 	{
-                printk(KERN_ERR "%s: Previously loaded firmware is missing\n",dev->name);                return (-ENOENT);
+                printk(KERN_ERR "%s: Previously loaded firmware is missing\n",dev->name);
+		return -ENOENT;
         }
 
         if((err = smctr_ram_memory_test(dev)))
 	{
                 printk(KERN_ERR "%s: RAM memory test failed.\n", dev->name);
-                return (-EIO);
+                return -EIO;
         }
 
 	smctr_set_rx_look_ahead(dev);
@@ -1608,7 +1610,7 @@
 	{
                 printk(KERN_ERR "%s: Initialization of card failed (%d)\n",
                         dev->name, err);
-                return (-EINVAL);
+                return -EINVAL;
         }
 
         /* This routine clobbers the TRC's internal registers. */
@@ -1616,7 +1618,7 @@
 	{
                 printk(KERN_ERR "%s: Card failed internal self test (%d)\n",
                         dev->name, err);
-                return (-EINVAL);
+                return -EINVAL;
         }
 
         /* Re-Initialize adapter's internal registers */
@@ -1625,17 +1627,17 @@
 	{
                 printk(KERN_ERR "%s: Initialization of card failed (%d)\n",
                         dev->name, err);
-                return (-EINVAL);
+                return -EINVAL;
         }
 
         smctr_enable_bic_int(dev);
 
         if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
-                return (err);
+                return err;
 
         smctr_disable_16bit(dev);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_init_card_real(struct net_device *dev)
@@ -1703,15 +1705,15 @@
         smctr_init_shared_memory(dev);
 
         if((err = smctr_issue_init_timers_cmd(dev)))
-                return (err);
+                return err;
 
         if((err = smctr_issue_init_txrx_cmd(dev)))
 	{
                 printk(KERN_ERR "%s: Hardware failure\n", dev->name);
-                return (err);
+                return err;
         }
 
-        return (0);
+        return 0;
 }
 
 static int smctr_init_rx_bdbs(struct net_device *dev)
@@ -1763,7 +1765,7 @@
                 tp->rx_bdb_curr[i]              = tp->rx_bdb_head[i]->next_ptr;
         }
 
-        return (0);
+        return 0;
 }
 
 static int smctr_init_rx_fcbs(struct net_device *dev)
@@ -1813,7 +1815,7 @@
                 tp->rx_fcb_curr[i]              = tp->rx_fcb_head[i]->next_ptr;
         }
 
-        return(0);
+        return 0;
 }
 
 static int smctr_init_shared_memory(struct net_device *dev)
@@ -1871,7 +1873,7 @@
         smctr_init_rx_bdbs(dev);
         smctr_init_rx_fcbs(dev);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_init_tx_bdbs(struct net_device *dev)
@@ -1901,7 +1903,7 @@
                 tp->tx_bdb_head[i]->back_ptr = bdb;
         }
 
-        return (0);
+        return 0;
 }
 
 static int smctr_init_tx_fcbs(struct net_device *dev)
@@ -1940,7 +1942,7 @@
                 tp->num_tx_fcbs_used[i]         = 0;
         }
 
-        return (0);
+        return 0;
 }
 
 static int smctr_internal_self_test(struct net_device *dev)
@@ -1949,33 +1951,33 @@
         int err;
 
         if((err = smctr_issue_test_internal_rom_cmd(dev)))
-                return (err);
+                return err;
 
         if((err = smctr_wait_cmd(dev)))
-                return (err);
+                return err;
 
         if(tp->acb_head->cmd_done_status & 0xff)
-                return (-1);
+                return -1;
 
         if((err = smctr_issue_test_hic_cmd(dev)))
-                return (err);
+                return err;
 
         if((err = smctr_wait_cmd(dev)))
-                return (err);
+                return err;
 
         if(tp->acb_head->cmd_done_status & 0xff)
-                return (-1);
+                return -1;
 
         if((err = smctr_issue_test_mac_reg_cmd(dev)))
-                return (err);
+                return err;
 
         if((err = smctr_wait_cmd(dev)))
-                return (err);
+                return err;
 
         if(tp->acb_head->cmd_done_status & 0xff)
-                return (-1);
+                return -1;
 
-        return (0);
+        return 0;
 }
 
 /*
@@ -2468,14 +2470,14 @@
         int err;
 
         if((err = smctr_wait_while_cbusy(dev)))
-                return (err);
+                return err;
 
         tp->sclb_ptr->int_mask_control  = interrupt_enable_mask;
         tp->sclb_ptr->valid_command     = SCLB_VALID | SCLB_CMD_CLEAR_INTERRUPT_MASK;
 
         smctr_set_ctrl_attention(dev);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code, __u16 ibits)
@@ -2483,7 +2485,7 @@
         struct net_local *tp = netdev_priv(dev);
 
         if(smctr_wait_while_cbusy(dev))
-                return (-1);
+                return -1;
 
         tp->sclb_ptr->int_mask_control = ibits;
         tp->sclb_ptr->iack_code = iack_code << 1; /* use the offset from base */        tp->sclb_ptr->resume_control = 0;
@@ -2491,7 +2493,7 @@
 
         smctr_set_ctrl_attention(dev);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_issue_init_timers_cmd(struct net_device *dev)
@@ -2502,10 +2504,10 @@
         __u16 *pTimer_Struc = (__u16 *)tp->misc_command_data;
 
         if((err = smctr_wait_while_cbusy(dev)))
-                return (err);
+                return err;
 
         if((err = smctr_wait_cmd(dev)))
-                return (err);
+                return err;
 
         tp->config_word0 = THDREN | DMA_TRIGGER | USETPT | NO_AUTOREMOVE;
         tp->config_word1 = 0;
@@ -2648,7 +2650,7 @@
 
         err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TRC_TIMERS, 0);
 
-        return (err);
+        return err;
 }
 
 static int smctr_issue_init_txrx_cmd(struct net_device *dev)
@@ -2659,12 +2661,12 @@
         void **txrx_ptrs = (void *)tp->misc_command_data;
 
         if((err = smctr_wait_while_cbusy(dev)))
-                return (err);
+                return err;
 
         if((err = smctr_wait_cmd(dev)))
 	{
                 printk(KERN_ERR "%s: Hardware failure\n", dev->name);
-                return (err);
+                return err;
         }
 
         /* Initialize Transmit Queue Pointers that are used, to point to
@@ -2695,7 +2697,7 @@
 
         err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TX_RX, 0);
 
-        return (err);
+        return err;
 }
 
 static int smctr_issue_insert_cmd(struct net_device *dev)
@@ -2704,7 +2706,7 @@
 
         err = smctr_setup_single_cmd(dev, ACB_CMD_INSERT, ACB_SUB_CMD_NOP);
 
-        return (err);
+        return err;
 }
 
 static int smctr_issue_read_ring_status_cmd(struct net_device *dev)
@@ -2712,15 +2714,15 @@
         int err;
 
         if((err = smctr_wait_while_cbusy(dev)))
-                return (err);
+                return err;
 
         if((err = smctr_wait_cmd(dev)))
-                return (err);
+                return err;
 
         err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_READ_TRC_STATUS,
                 RW_TRC_STATUS_BLOCK);
 
-        return (err);
+        return err;
 }
 
 static int smctr_issue_read_word_cmd(struct net_device *dev, __u16 aword_cnt)
@@ -2728,15 +2730,15 @@
         int err;
 
         if((err = smctr_wait_while_cbusy(dev)))
-                return (err);
+                return err;
 
         if((err = smctr_wait_cmd(dev)))
-                return (err);
+                return err;
 
         err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_READ_VALUE,
                 aword_cnt);
 
-        return (err);
+        return err;
 }
 
 static int smctr_issue_remove_cmd(struct net_device *dev)
@@ -2745,14 +2747,14 @@
         int err;
 
         if((err = smctr_wait_while_cbusy(dev)))
-                return (err);
+                return err;
 
         tp->sclb_ptr->resume_control    = 0;
         tp->sclb_ptr->valid_command     = SCLB_VALID | SCLB_CMD_REMOVE;
 
         smctr_set_ctrl_attention(dev);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_issue_resume_acb_cmd(struct net_device *dev)
@@ -2761,7 +2763,7 @@
         int err;
 
         if((err = smctr_wait_while_cbusy(dev)))
-                return (err);
+                return err;
 
         tp->sclb_ptr->resume_control = SCLB_RC_ACB;
         tp->sclb_ptr->valid_command  = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
@@ -2770,7 +2772,7 @@
 
         smctr_set_ctrl_attention(dev);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue)
@@ -2779,7 +2781,7 @@
         int err;
 
         if((err = smctr_wait_while_cbusy(dev)))
-                return (err);
+                return err;
 
         if(queue == MAC_QUEUE)
                 tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_BDB;
@@ -2790,7 +2792,7 @@
 
         smctr_set_ctrl_attention(dev);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue)
@@ -2801,7 +2803,7 @@
                 printk(KERN_DEBUG "%s: smctr_issue_resume_rx_fcb_cmd\n", dev->name);
 
         if(smctr_wait_while_cbusy(dev))
-                return (-1);
+                return -1;
 
         if(queue == MAC_QUEUE)
                 tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_FCB;
@@ -2812,7 +2814,7 @@
 
         smctr_set_ctrl_attention(dev);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_issue_resume_tx_fcb_cmd(struct net_device *dev, __u16 queue)
@@ -2823,14 +2825,14 @@
                 printk(KERN_DEBUG "%s: smctr_issue_resume_tx_fcb_cmd\n", dev->name);
 
         if(smctr_wait_while_cbusy(dev))
-                return (-1);
+                return -1;
 
         tp->sclb_ptr->resume_control = (SCLB_RC_TFCB0 << queue);
         tp->sclb_ptr->valid_command = SCLB_RESUME_CONTROL_VALID | SCLB_VALID;
 
         smctr_set_ctrl_attention(dev);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_issue_test_internal_rom_cmd(struct net_device *dev)
@@ -2840,7 +2842,7 @@
         err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
                 TRC_INTERNAL_ROM_TEST);
 
-        return (err);
+        return err;
 }
 
 static int smctr_issue_test_hic_cmd(struct net_device *dev)
@@ -2850,7 +2852,7 @@
         err = smctr_setup_single_cmd(dev, ACB_CMD_HIC_TEST,
                 TRC_HOST_INTERFACE_REG_TEST);
 
-        return (err);
+        return err;
 }
 
 static int smctr_issue_test_mac_reg_cmd(struct net_device *dev)
@@ -2860,7 +2862,7 @@
         err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
                 TRC_MAC_REGISTERS_TEST);
 
-        return (err);
+        return err;
 }
 
 static int smctr_issue_trc_loopback_cmd(struct net_device *dev)
@@ -2870,7 +2872,7 @@
         err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
                 TRC_INTERNAL_LOOPBACK);
 
-        return (err);
+        return err;
 }
 
 static int smctr_issue_tri_loopback_cmd(struct net_device *dev)
@@ -2880,7 +2882,7 @@
         err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
                 TRC_TRI_LOOPBACK);
 
-        return (err);
+        return err;
 }
 
 static int smctr_issue_write_byte_cmd(struct net_device *dev,
@@ -2891,10 +2893,10 @@
 	int err;
 
         if((err = smctr_wait_while_cbusy(dev)))
-                return (err);
+                return err;
 
         if((err = smctr_wait_cmd(dev)))
-                return (err);
+                return err;
 
         for(iword = 0, ibyte = 0; iword < (unsigned int)(aword_cnt & 0xff);
         	iword++, ibyte += 2)
@@ -2903,8 +2905,8 @@
 			| (*((__u8 *)byte + ibyte + 1));
         }
 
-        return (smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE, 
-		aword_cnt));
+        return smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
+		aword_cnt);
 }
 
 static int smctr_issue_write_word_cmd(struct net_device *dev,
@@ -2914,10 +2916,10 @@
         unsigned int i, err;
 
         if((err = smctr_wait_while_cbusy(dev)))
-                return (err);
+                return err;
 
         if((err = smctr_wait_cmd(dev)))
-                return (err);
+                return err;
 
         for(i = 0; i < (unsigned int)(aword_cnt & 0xff); i++)
                 tp->misc_command_data[i] = *((__u16 *)word + i);
@@ -2925,7 +2927,7 @@
         err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
                 aword_cnt);
 
-        return (err);
+        return err;
 }
 
 static int smctr_join_complete_state(struct net_device *dev)
@@ -2935,7 +2937,7 @@
         err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
                 JS_JOIN_COMPLETE_STATE);
 
-        return (err);
+        return err;
 }
 
 static int smctr_link_tx_fcbs_to_bdbs(struct net_device *dev)
@@ -2959,7 +2961,7 @@
                 }
         }
 
-        return (0);
+        return 0;
 }
 
 static int smctr_load_firmware(struct net_device *dev)
@@ -2974,7 +2976,7 @@
 
 	if (request_firmware(&fw, "tr_smctr.bin", &dev->dev)) {
 		printk(KERN_ERR "%s: firmware not found\n", dev->name);
-		return (UCODE_NOT_PRESENT);
+		return UCODE_NOT_PRESENT;
 	}
 
         tp->num_of_tx_buffs     = 4;
@@ -3036,7 +3038,7 @@
         smctr_disable_16bit(dev);
  out:
 	release_firmware(fw);
-        return (err);
+        return err;
 }
 
 static int smctr_load_node_addr(struct net_device *dev)
@@ -3052,7 +3054,7 @@
         }
         dev->addr_len = 6;
 
-        return (0);
+        return 0;
 }
 
 /* Lobe Media Test.
@@ -3146,14 +3148,14 @@
                 if(smctr_wait_cmd(dev))
                 {
                         printk(KERN_ERR "Lobe Failed test state\n");
-                        return (LOBE_MEDIA_TEST_FAILED);
+                        return LOBE_MEDIA_TEST_FAILED;
                 }
         }
 
         err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
                 TRC_LOBE_MEDIA_TEST);
 
-        return (err);
+        return err;
 }
 
 static int smctr_lobe_media_test_state(struct net_device *dev)
@@ -3163,7 +3165,7 @@
         err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
                 JS_LOBE_TEST_STATE);
 
-        return (err);
+        return err;
 }
 
 static int smctr_make_8025_hdr(struct net_device *dev,
@@ -3212,7 +3214,7 @@
                         break;
         }
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_access_pri(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3225,7 +3227,7 @@
         tsv->svv[0] = MSB(tp->authorized_access_priority);
         tsv->svv[1] = LSB(tp->authorized_access_priority);
 
-	return (0);
+	return 0;
 }
 
 static int smctr_make_addr_mod(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3236,7 +3238,7 @@
         tsv->svv[0] = 0;
         tsv->svv[1] = 0;
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_auth_funct_class(struct net_device *dev,
@@ -3250,7 +3252,7 @@
         tsv->svv[0] = MSB(tp->authorized_function_classes);
         tsv->svv[1] = LSB(tp->authorized_function_classes);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_corr(struct net_device *dev,
@@ -3262,7 +3264,7 @@
         tsv->svv[0] = MSB(correlator);
         tsv->svv[1] = LSB(correlator);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_funct_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3280,7 +3282,7 @@
         tsv->svv[2] = MSB(tp->misc_command_data[1]);
         tsv->svv[3] = LSB(tp->misc_command_data[1]);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_group_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3305,7 +3307,7 @@
 	   tsv->svv[2] == 0x00 && tsv->svv[3] == 0x00)
                 tsv->svv[0] = 0x00;
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_phy_drop_num(struct net_device *dev,
@@ -3324,7 +3326,7 @@
         tsv->svv[2] = MSB(tp->misc_command_data[1]);
         tsv->svv[3] = LSB(tp->misc_command_data[1]);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_product_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3337,7 +3339,7 @@
         for(i = 0; i < 18; i++)
                 tsv->svv[i] = 0xF0;
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_station_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3358,7 +3360,7 @@
         tsv->svv[4] = MSB(tp->misc_command_data[2]);
         tsv->svv[5] = LSB(tp->misc_command_data[2]);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_ring_station_status(struct net_device *dev,
@@ -3374,7 +3376,7 @@
         tsv->svv[4] = 0;
         tsv->svv[5] = 0;
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_ring_station_version(struct net_device *dev,
@@ -3400,7 +3402,7 @@
         else
                 tsv->svv[9] = 0xc4;    /* EBCDIC - D */
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_tx_status_code(struct net_device *dev,
@@ -3414,7 +3416,7 @@
         /* Stripped frame status of Transmitted Frame */
         tsv->svv[1] = tx_fstatus & 0xff;
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_upstream_neighbor_addr(struct net_device *dev,
@@ -3436,7 +3438,7 @@
         tsv->svv[4] = MSB(tp->misc_command_data[2]);
         tsv->svv[5] = LSB(tp->misc_command_data[2]);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_make_wrap_data(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3444,7 +3446,7 @@
         tsv->svi = WRAP_DATA;
         tsv->svl = S_WRAP_DATA;
 
-        return (0);
+        return 0;
 }
 
 /*
@@ -3464,9 +3466,9 @@
 
         err = smctr_init_adapter(dev);
         if(err < 0)
-                return (err);
+                return err;
 
-        return (err);
+        return err;
 }
 
 /* Interrupt driven open of Token card. */
@@ -3481,9 +3483,9 @@
 
         /* Now we can actually open the adapter. */
         if(tp->status == OPEN)
-                return (0);
+                return 0;
         if(tp->status != INITIALIZED)
-                return (-1);
+                return -1;
 
 	/* FIXME: it would work a lot better if we masked the irq sources
 	   on the card here, then we could skip the locking and poll nicely */
@@ -3560,7 +3562,7 @@
 out:
         spin_unlock_irqrestore(&tp->lock, flags);
 
-        return (err);
+        return err;
 }
 
 /* Check for a network adapter of this type, 
@@ -3675,7 +3677,7 @@
 
 	dev->netdev_ops = &smctr_netdev_ops;
         dev->watchdog_timeo	= HZ;
-        return (0);
+        return 0;
 
 out:
 	return err;
@@ -3699,13 +3701,13 @@
                         case INIT:
                                 if((rcode = smctr_rcv_init(dev, rmf, &correlator)) == HARDWARE_FAILED)
                                 {
-                                        return (rcode);
+                                        return rcode;
                                 }
 
                                 if((err = smctr_send_rsp(dev, rmf, rcode,
                                         correlator)))
                                 {
-                                        return (err);
+                                        return err;
                                 }
                                 break;
 
@@ -3713,13 +3715,13 @@
                                 if((rcode = smctr_rcv_chg_param(dev, rmf,
                                         &correlator)) ==HARDWARE_FAILED)
                                 {
-                                        return (rcode);
+                                        return rcode;
                                 }
 
                                 if((err = smctr_send_rsp(dev, rmf, rcode,
                                         correlator)))
                                 {
-                                        return (err);
+                                        return err;
                                 }
                                 break;
 
@@ -3728,16 +3730,16 @@
                                         rmf, &correlator)) != POSITIVE_ACK)
                                 {
                                         if(rcode == HARDWARE_FAILED)
-                                                return (rcode);
+                                                return rcode;
                                         else
-                                                return (smctr_send_rsp(dev, rmf,
-                                                        rcode, correlator));
+                                                return smctr_send_rsp(dev, rmf,
+                                                        rcode, correlator);
                                 }
 
                                 if((err = smctr_send_rpt_addr(dev, rmf,
                                         correlator)))
                                 {
-                                        return (err);
+                                        return err;
                                 }
                                 break;
 
@@ -3746,17 +3748,17 @@
                                         rmf, &correlator)) != POSITIVE_ACK)
                                 {
                                         if(rcode == HARDWARE_FAILED)
-                                                return (rcode);
+                                                return rcode;
                                         else
-                                                return (smctr_send_rsp(dev, rmf,
+                                                return smctr_send_rsp(dev, rmf,
                                                         rcode,
-                                                        correlator));
+                                                        correlator);
                                 }
 
                                 if((err = smctr_send_rpt_attch(dev, rmf,
                                         correlator)))
                                 {
-                                        return (err);
+                                        return err;
                                 }
                                 break;
 
@@ -3765,17 +3767,17 @@
                                         rmf, &correlator)) != POSITIVE_ACK)
                                 {
                                         if(rcode == HARDWARE_FAILED)
-                                                return (rcode);
+                                                return rcode;
                                         else
-                                                return (smctr_send_rsp(dev, rmf,
+                                                return smctr_send_rsp(dev, rmf,
                                                         rcode,
-                                                        correlator));
+                                                        correlator);
                                 }
 
                                 if((err = smctr_send_rpt_state(dev, rmf,
                                         correlator)))
                                 {
-                                        return (err);
+                                        return err;
                                 }
                                 break;
 
@@ -3786,17 +3788,17 @@
                                         != POSITIVE_ACK)
                                 {
                                         if(rcode == HARDWARE_FAILED)
-                                                return (rcode);
+                                                return rcode;
                                         else
-                                                return (smctr_send_rsp(dev, rmf,
+                                                return smctr_send_rsp(dev, rmf,
                                                         rcode,
-                                                        correlator));
+                                                        correlator);
                                 }
 
                                 if((err = smctr_send_tx_forward(dev, rmf,
                                         &tx_fstatus)) == HARDWARE_FAILED)
                                 {
-                                        return (err);
+                                        return err;
                                 }
 
                                 if(err == A_FRAME_WAS_FORWARDED)
@@ -3805,7 +3807,7 @@
 						rmf, tx_fstatus))
                                                 == HARDWARE_FAILED)
                                         {
-                                                return (err);
+                                                return err;
                                         }
                                 }
                                 break;
@@ -3834,7 +3836,7 @@
                                         if((err = smctr_send_rsp(dev, rmf,rcode,
                                                 correlator)))
                                         {
-                                                return (err);
+                                                return err;
                                         }
                                 }
 
@@ -3899,7 +3901,7 @@
                 err = 0;
         }
 
-        return (err);
+        return err;
 }
 
 /* Adapter RAM test. Incremental word ODD boundary data test. */
@@ -3942,7 +3944,7 @@
                                 err_offset      = j;
                                 err_word        = word_read;
                                 err_pattern     = word_pattern;
-                                return (RAM_TEST_FAILED);
+                                return RAM_TEST_FAILED;
                         }
                 }
         }
@@ -3966,14 +3968,14 @@
                                 err_offset      = j;
                                 err_word        = word_read;
                                 err_pattern     = word_pattern;
-                                return (RAM_TEST_FAILED);
+                                return RAM_TEST_FAILED;
                         }
                 }
         }
 
         smctr_set_page(dev, (__u8 *)tp->ram_access);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
@@ -3986,7 +3988,7 @@
 
         /* This Frame can only come from a CRS */
         if((rmf->dc_sc & SC_MASK) != SC_CRS)
-                return(E_INAPPROPRIATE_SOURCE_CLASS);
+                return E_INAPPROPRIATE_SOURCE_CLASS;
 
         /* Remove MVID Length from total length. */
         vlen = (signed short)rmf->vl - 4;
@@ -4058,7 +4060,7 @@
 		}
         }
 
-        return (rcode);
+        return rcode;
 }
 
 static int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
@@ -4071,7 +4073,7 @@
 
         /* This Frame can only come from a RPS */
         if((rmf->dc_sc & SC_MASK) != SC_RPS)
-                return (E_INAPPROPRIATE_SOURCE_CLASS);
+                return E_INAPPROPRIATE_SOURCE_CLASS;
 
         /* Remove MVID Length from total length. */
         vlen = (signed short)rmf->vl - 4;
@@ -4133,7 +4135,7 @@
 		}
         }
 
-        return (rcode);
+        return rcode;
 }
 
 static int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf)
@@ -4145,7 +4147,7 @@
 
         /* This Frame can only come from a CRS */
         if((rmf->dc_sc & SC_MASK) != SC_CRS)
-                return (E_INAPPROPRIATE_SOURCE_CLASS);
+                return E_INAPPROPRIATE_SOURCE_CLASS;
 
         /* Remove MVID Length from total length */
         vlen = (signed short)rmf->vl - 4;
@@ -4193,7 +4195,7 @@
 		}
         }
 
-        return (rcode);
+        return rcode;
 }
 
 static int smctr_rcv_rq_addr_state_attch(struct net_device *dev,
@@ -4250,7 +4252,7 @@
 			}
         }
 
-        return (rcode);
+        return rcode;
 }
 
 static int smctr_rcv_unknown(struct net_device *dev, MAC_HEADER *rmf,
@@ -4284,7 +4286,7 @@
                 rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
         }
 
-        return (E_UNRECOGNIZED_VECTOR_ID);
+        return E_UNRECOGNIZED_VECTOR_ID;
 }
 
 /*
@@ -4311,7 +4313,7 @@
          */
         outb(tp->trc_mask | CSR_CLRTINT | CSR_CLRCBUSY, ioaddr + CSR);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_restart_tx_chain(struct net_device *dev, short queue)
@@ -4329,7 +4331,7 @@
                 err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
         }
 
-        return (err);
+        return err;
 }
 
 static int smctr_ring_status_chg(struct net_device *dev)
@@ -4371,7 +4373,7 @@
         }
 
         if(!(tp->ring_status_flags & RING_STATUS_CHANGED))
-                return (0);
+                return 0;
 
         switch(tp->ring_status)
         {
@@ -4421,7 +4423,7 @@
                         break;
         }
 
-        return (0);
+        return 0;
 }
 
 static int smctr_rx_frame(struct net_device *dev)
@@ -4486,7 +4488,7 @@
                         break;
         }
 
-        return (err);
+        return err;
 }
 
 static int smctr_send_dat(struct net_device *dev)
@@ -4502,7 +4504,7 @@
         if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE,
                 sizeof(MAC_HEADER))) == (FCBlock *)(-1L))
         {
-                return (OUT_OF_RESOURCES);
+                return OUT_OF_RESOURCES;
         }
 
         /* Initialize DAT Data Fields. */
@@ -4524,7 +4526,7 @@
 
         /* Start Transmit. */
         if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
-                return (err);
+                return err;
 
         /* Wait for Transmit to Complete */
         for(i = 0; i < 10000; i++)
@@ -4538,7 +4540,7 @@
         if(!(fcb->frame_status &  FCB_COMMAND_DONE) ||
 	   fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
         {
-                return (INITIALIZE_FAILED);
+                return INITIALIZE_FAILED;
         }
 
         /* De-allocated Tx FCB and Frame Buffer
@@ -4549,7 +4551,7 @@
         tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
         smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
 
-        return (0);
+        return 0;
 }
 
 static void smctr_timeout(struct net_device *dev)
@@ -4610,7 +4612,7 @@
         if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(struct trh_hdr)
                 + S_WRAP_DATA + S_WRAP_DATA)) == (FCBlock *)(-1L))
         {
-                return (OUT_OF_RESOURCES);
+                return OUT_OF_RESOURCES;
         }
 
         /* Initialize DAT Data Fields. */
@@ -4639,7 +4641,7 @@
         /* Start Transmit. */
         tmf->vl = SWAP_BYTES(tmf->vl);
         if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
-                return (err);
+                return err;
 
         /* Wait for Transmit to Complete. (10 ms). */
         for(i=0; i < 10000; i++)
@@ -4653,7 +4655,7 @@
         if(!(fcb->frame_status & FCB_COMMAND_DONE) ||
 	   fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
         {
-                return (LOBE_MEDIA_TEST_FAILED);
+                return LOBE_MEDIA_TEST_FAILED;
         }
 
         /* De-allocated Tx FCB and Frame Buffer
@@ -4664,7 +4666,7 @@
         tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
         smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
@@ -4679,7 +4681,7 @@
 		+ S_ADDRESS_MODIFER + S_GROUP_ADDRESS + S_FUNCTIONAL_ADDRESS))
 		== (FCBlock *)(-1L))
         {
-                return (0);
+                return 0;
         }
 
         tmf 		= (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4722,7 +4724,7 @@
 */
         tmf->vl = SWAP_BYTES(tmf->vl);
 
-        return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+        return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
 }
 
 static int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
@@ -4737,7 +4739,7 @@
 		+ S_AUTHORIZED_FUNCTION_CLASS + S_AUTHORIZED_ACCESS_PRIORITY))
 		== (FCBlock *)(-1L))
         {
-                return (0);
+                return 0;
         }
 
         tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4776,7 +4778,7 @@
 */
         tmf->vl = SWAP_BYTES(tmf->vl);
 
-        return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+        return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
 }
 
 static int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
@@ -4791,7 +4793,7 @@
 		+ S_RING_STATION_STATUS + S_STATION_IDENTIFER))
 		== (FCBlock *)(-1L))
         {
-                return (0);
+                return 0;
         }
 
         tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4826,7 +4828,7 @@
 */
         tmf->vl = SWAP_BYTES(tmf->vl);
 
-        return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+        return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
 }
 
 static int smctr_send_rpt_tx_forward(struct net_device *dev,
@@ -4839,7 +4841,7 @@
         if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
 		+ S_TRANSMIT_STATUS_CODE)) == (FCBlock *)(-1L))
         {
-                return (0);
+                return 0;
         }
 
         tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4862,7 +4864,7 @@
 */
         tmf->vl = SWAP_BYTES(tmf->vl);
 
-        return(smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+        return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
 }
 
 static int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
@@ -4875,7 +4877,7 @@
         if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
 		+ S_CORRELATOR + S_RESPONSE_CODE)) == (FCBlock *)(-1L))
         {
-                return (0);
+                return 0;
         }
 
         tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4888,7 +4890,7 @@
         tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
         smctr_make_corr(dev, tsv, correlator);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_send_rq_init(struct net_device *dev)
@@ -4907,7 +4909,7 @@
 			+ S_RING_STATION_VERSION_NUMBER + S_ADDRESS_MODIFER))
 			== (FCBlock *)(-1L)))
                 {
-                        return (0);
+                        return 0;
                 }
 
                 tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4943,7 +4945,7 @@
                 tmf->vl = SWAP_BYTES(tmf->vl);
 
                 if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
-                        return (err);
+                        return err;
 
                 /* Wait for Transmit to Complete */
       		for(i = 0; i < 10000; i++) 
@@ -4957,7 +4959,7 @@
                 fstatus = fcb->frame_status;
 
                 if(!(fstatus & FCB_COMMAND_DONE))
-                        return (HARDWARE_FAILED);
+                        return HARDWARE_FAILED;
 
                 if(!(fstatus & FCB_TX_STATUS_E))
                         count++;
@@ -4971,7 +4973,7 @@
                 smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
         } while(count < 4 && ((fstatus & FCB_TX_AC_BITS) ^ FCB_TX_AC_BITS));
 
-	return (smctr_join_complete_state(dev));
+	return smctr_join_complete_state(dev);
 }
 
 static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
@@ -4984,13 +4986,13 @@
 
         /* Check if this is the END POINT of the Transmit Forward Chain. */
         if(rmf->vl <= 18)
-                return (0);
+                return 0;
 
         /* Allocate Transmit FCB only by requesting 0 bytes
          * of data buffer.
          */
         if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, 0)) == (FCBlock *)(-1L))
-                return (0);
+                return 0;
 
         /* Set pointer to Transmit Frame Buffer to the data
          * portion of the received TX Forward frame, making
@@ -5006,7 +5008,7 @@
         fcb->bdb_ptr->buffer_length      = rmf->vl - 4 - 2;
 
         if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
-                return (err);
+                return err;
 
         /* Wait for Transmit to Complete */
    	for(i = 0; i < 10000; i++) 
@@ -5020,7 +5022,7 @@
         if(!(fcb->frame_status & FCB_COMMAND_DONE))
         {
                 if((err = smctr_issue_resume_tx_fcb_cmd(dev, MAC_QUEUE)))
-                        return (err);
+                        return err;
 
       		for(i = 0; i < 10000; i++) 
 		{
@@ -5030,12 +5032,12 @@
       		}
 
                 if(!(fcb->frame_status & FCB_COMMAND_DONE))
-                        return (HARDWARE_FAILED);
+                        return HARDWARE_FAILED;
         }
 
         *tx_fstatus = fcb->frame_status;
 
-        return (A_FRAME_WAS_FORWARDED);
+        return A_FRAME_WAS_FORWARDED;
 }
 
 static int smctr_set_auth_access_pri(struct net_device *dev,
@@ -5044,11 +5046,11 @@
         struct net_local *tp = netdev_priv(dev);
 
         if(rsv->svl != S_AUTHORIZED_ACCESS_PRIORITY)
-                return (E_SUB_VECTOR_LENGTH_ERROR);
+                return E_SUB_VECTOR_LENGTH_ERROR;
 
         tp->authorized_access_priority = (rsv->svv[0] << 8 | rsv->svv[1]);
 
-        return (POSITIVE_ACK);
+        return POSITIVE_ACK;
 }
 
 static int smctr_set_auth_funct_class(struct net_device *dev,
@@ -5057,22 +5059,22 @@
         struct net_local *tp = netdev_priv(dev);
 
         if(rsv->svl != S_AUTHORIZED_FUNCTION_CLASS)
-                return (E_SUB_VECTOR_LENGTH_ERROR);
+                return E_SUB_VECTOR_LENGTH_ERROR;
 
         tp->authorized_function_classes = (rsv->svv[0] << 8 | rsv->svv[1]);
 
-        return (POSITIVE_ACK);
+        return POSITIVE_ACK;
 }
 
 static int smctr_set_corr(struct net_device *dev, MAC_SUB_VECTOR *rsv,
         __u16 *correlator)
 {
         if(rsv->svl != S_CORRELATOR)
-                return (E_SUB_VECTOR_LENGTH_ERROR);
+                return E_SUB_VECTOR_LENGTH_ERROR;
 
         *correlator = (rsv->svv[0] << 8 | rsv->svv[1]);
 
-        return (POSITIVE_ACK);
+        return POSITIVE_ACK;
 }
 
 static int smctr_set_error_timer_value(struct net_device *dev,
@@ -5082,34 +5084,34 @@
 	int err;
 
         if(rsv->svl != S_ERROR_TIMER_VALUE)
-                return (E_SUB_VECTOR_LENGTH_ERROR);
+                return E_SUB_VECTOR_LENGTH_ERROR;
 
         err_tval = (rsv->svv[0] << 8 | rsv->svv[1])*10;
 
         smctr_issue_write_word_cmd(dev, RW_TER_THRESHOLD, &err_tval);
 
         if((err = smctr_wait_cmd(dev)))
-                return (err);
+                return err;
 
-        return (POSITIVE_ACK);
+        return POSITIVE_ACK;
 }
 
 static int smctr_set_frame_forward(struct net_device *dev,
         MAC_SUB_VECTOR *rsv, __u8 dc_sc)
 {
         if((rsv->svl < 2) || (rsv->svl > S_FRAME_FORWARD))
-                return (E_SUB_VECTOR_LENGTH_ERROR);
+                return E_SUB_VECTOR_LENGTH_ERROR;
 
         if((dc_sc & DC_MASK) != DC_CRS)
         {
                 if(rsv->svl >= 2 && rsv->svl < 20)
-                	return (E_TRANSMIT_FORWARD_INVALID);
+			return E_TRANSMIT_FORWARD_INVALID;
 
                 if((rsv->svv[0] != 0) || (rsv->svv[1] != 0))
-                        return (E_TRANSMIT_FORWARD_INVALID);
+                        return E_TRANSMIT_FORWARD_INVALID;
         }
 
-        return (POSITIVE_ACK);
+        return POSITIVE_ACK;
 }
 
 static int smctr_set_local_ring_num(struct net_device *dev,
@@ -5118,13 +5120,13 @@
         struct net_local *tp = netdev_priv(dev);
 
         if(rsv->svl != S_LOCAL_RING_NUMBER)
-                return (E_SUB_VECTOR_LENGTH_ERROR);
+                return E_SUB_VECTOR_LENGTH_ERROR;
 
         if(tp->ptr_local_ring_num)
                 *(__u16 *)(tp->ptr_local_ring_num) 
 			= (rsv->svv[0] << 8 | rsv->svv[1]);
 
-        return (POSITIVE_ACK);
+        return POSITIVE_ACK;
 }
 
 static unsigned short smctr_set_ctrl_attention(struct net_device *dev)
@@ -5140,7 +5142,7 @@
                 outb(tp->trc_mask, ioaddr + CSR);
         }
 
-        return (0);
+        return 0;
 }
 
 static void smctr_set_multicast_list(struct net_device *dev)
@@ -5159,7 +5161,7 @@
         amask = (__u8)((tptr & PR_PAGE_MASK) >> 8);
         outb(amask, dev->base_addr + PR);
 
-        return (0);
+        return 0;
 }
 
 static int smctr_set_phy_drop(struct net_device *dev, MAC_SUB_VECTOR *rsv)
@@ -5167,13 +5169,13 @@
 	int err;
 
         if(rsv->svl != S_PHYSICAL_DROP)
-                return (E_SUB_VECTOR_LENGTH_ERROR);
+                return E_SUB_VECTOR_LENGTH_ERROR;
 
         smctr_issue_write_byte_cmd(dev, RW_PHYSICAL_DROP_NUMBER, &rsv->svv[0]);
         if((err = smctr_wait_cmd(dev)))
-                return (err);
+                return err;
 
-        return (POSITIVE_ACK);
+        return POSITIVE_ACK;
 }
 
 /* Reset the ring speed to the opposite of what it was. This auto-pilot
@@ -5195,16 +5197,16 @@
         smctr_reset_adapter(dev);
 
         if((err = smctr_init_card_real(dev)))
-                return (err);
+                return err;
 
         smctr_enable_bic_int(dev);
 
         if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
-                return (err);
+                return err;
 
         smctr_disable_16bit(dev);
 
-	return (0);
+	return 0;
 }
 
 static int smctr_set_rx_look_ahead(struct net_device *dev)
@@ -5233,7 +5235,7 @@
                 *((__u16 *)(tp->ram_access)) = sword;
         }
 
-        return (0);
+        return 0;
 }
 
 static int smctr_set_trc_reset(int ioaddr)
@@ -5243,7 +5245,7 @@
         r = inb(ioaddr + MSR);
         outb(MSR_RST | r, ioaddr + MSR);
 
-        return (0);
+        return 0;
 }
 
 /*
@@ -5259,10 +5261,10 @@
                 printk(KERN_DEBUG "%s: smctr_setup_single_cmd\n", dev->name);
 
         if((err = smctr_wait_while_cbusy(dev)))
-                return (err);
+                return err;
 
         if((err = (unsigned int)smctr_wait_cmd(dev)))
-                return (err);
+                return err;
 
         tp->acb_head->cmd_done_status   = 0;
         tp->acb_head->cmd               = command;
@@ -5270,7 +5272,7 @@
 
         err = smctr_issue_resume_acb_cmd(dev);
 
-        return (err);
+        return err;
 }
 
 /*
@@ -5287,7 +5289,7 @@
         tp->acb_head->data_offset_lo
                 = (__u16)TRC_POINTER(tp->misc_command_data);
 
-        return(smctr_issue_resume_acb_cmd(dev));
+        return smctr_issue_resume_acb_cmd(dev);
 }
 
 static char *smctr_malloc(struct net_device *dev, __u16 size)
@@ -5298,7 +5300,7 @@
         m = (char *)(tp->ram_access + tp->sh_mem_used);
         tp->sh_mem_used += (__u32)size;
 
-        return (m);
+        return m;
 }
 
 static int smctr_status_chg(struct net_device *dev)
@@ -5333,7 +5335,7 @@
                         break;
         }
 
-        return (0);
+        return 0;
 }
 
 static int smctr_trc_send_packet(struct net_device *dev, FCBlock *fcb,
@@ -5355,7 +5357,7 @@
                 err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
         }
 
-        return (err);
+        return err;
 }
 
 static __u16 smctr_tx_complete(struct net_device *dev, __u16 queue)
@@ -5409,7 +5411,7 @@
                         break;
         }
 
-        return (err);
+        return err;
 }
 
 static unsigned short smctr_tx_move_frame(struct net_device *dev,
@@ -5450,7 +5452,7 @@
                 pbuff += len;
         }
 
-        return (0);
+        return 0;
 }
 
 /* Update the error statistic counters for this adapter. */
@@ -5493,7 +5495,7 @@
         if(tstat->token_errors)
                 tstat->token_errors += *(tp->misc_command_data + 5) >> 8;
 
-        return (0);
+        return 0;
 }
 
 static int smctr_update_rx_chain(struct net_device *dev, __u16 queue)
@@ -5530,7 +5532,7 @@
         tp->rx_bdb_curr[queue]->back_ptr->info = BDB_NOT_CHAIN_END;
         tp->rx_bdb_curr[queue] = bdb;
 
-        return (0);
+        return 0;
 }
 
 static int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
@@ -5542,13 +5544,13 @@
                 printk(KERN_DEBUG "smctr_update_tx_chain\n");
 
         if(tp->num_tx_fcbs_used[queue] <= 0)
-                return (HARDWARE_FAILED);
+                return HARDWARE_FAILED;
         else
         {
                 if(tp->tx_buff_used[queue] < fcb->memory_alloc)
                 {
                         tp->tx_buff_used[queue] = 0;
-                        return (HARDWARE_FAILED);
+                        return HARDWARE_FAILED;
                 }
 
                 tp->tx_buff_used[queue] -= fcb->memory_alloc;
@@ -5566,7 +5568,7 @@
                 fcb->frame_status = 0;
                 tp->tx_fcb_end[queue] = fcb->next_ptr;
 		netif_wake_queue(dev);
-                return (0);
+                return 0;
         }
 }
 
@@ -5587,12 +5589,12 @@
         }
 
         if(loop_count == 0)
-                return(HARDWARE_FAILED);
+                return HARDWARE_FAILED;
 
         if(tp->acb_head->cmd_done_status & 0xff)
-                return(HARDWARE_FAILED);
+                return HARDWARE_FAILED;
 
-        return (0);
+        return 0;
 }
 
 static int smctr_wait_while_cbusy(struct net_device *dev)
@@ -5624,9 +5626,9 @@
         }
 
         if(timeout)
-                return (0);
+                return 0;
         else
-                return (HARDWARE_FAILED);
+                return HARDWARE_FAILED;
 }
 
 #ifdef MODULE
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index 435ef7d..c83f4f6 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -224,7 +224,7 @@
                 chk2 ^= 0x0FE;
 
                 if(chk1 != chk2)
-                        return (-1);    /* No adapter */
+                        return -1;    /* No adapter */
                 chk1 -= 2;
         } while(chk1 != 0);     /* Repeat 128 times (all byte values) */
 
@@ -232,7 +232,7 @@
         /* Restore the SIFADR value */
 	SIFWRITEB(old, SIFADR);
 
-        return (0);
+        return 0;
 }
 #endif
 
@@ -271,7 +271,7 @@
 	{
 		printk(KERN_INFO "%s: Chipset initialization error\n", 
 			dev->name);
-		return (-1);
+		return -1;
 	}
 
 	tp->timer.expires	= jiffies + 30*HZ;
@@ -298,7 +298,7 @@
 	if(tp->AdapterVirtOpenFlag == 0)
 	{
 		tms380tr_disable_interrupts(dev);
-		return (-1);
+		return -1;
 	}
 
 	tp->StartTime = jiffies;
@@ -309,7 +309,7 @@
 	tp->timer.data		= (unsigned long)dev;
 	add_timer(&tp->timer);
 
-	return (0);
+	return 0;
 }
 
 /*
@@ -343,23 +343,23 @@
 		printk(KERN_DEBUG "%s: Resetting adapter...\n", dev->name);
 	err = tms380tr_reset_adapter(dev);
 	if(err < 0)
-		return (-1);
+		return -1;
 
 	if(tms380tr_debug > 3)
 		printk(KERN_DEBUG "%s: Bringup diags...\n", dev->name);
 	err = tms380tr_bringup_diags(dev);
 	if(err < 0)
-		return (-1);
+		return -1;
 
 	if(tms380tr_debug > 3)
 		printk(KERN_DEBUG "%s: Init adapter...\n", dev->name);
 	err = tms380tr_init_adapter(dev);
 	if(err < 0)
-		return (-1);
+		return -1;
 
 	if(tms380tr_debug > 3)
 		printk(KERN_DEBUG "%s: Done!\n", dev->name);
-	return (0);
+	return 0;
 }
 
 /*
@@ -877,7 +877,7 @@
 	   IrqType != STS_IRQ_COMMAND_STATUS &&
 	   IrqType != STS_IRQ_RING_STATUS)
 	{
-		return (1);	/* SSB not involved. */
+		return 1;	/* SSB not involved. */
 	}
 
 	/* Note: All fields of the SSB have been set to all ones (-1) after it
@@ -887,21 +887,21 @@
 	 */
 
 	if(ssb->STS == (unsigned short) -1)
-		return (0);	/* Command field not yet available. */
+		return 0;	/* Command field not yet available. */
 	if(IrqType == STS_IRQ_COMMAND_STATUS)
-		return (1);	/* Status fields not always affected. */
+		return 1;	/* Status fields not always affected. */
 	if(ssb->Parm[0] == (unsigned short) -1)
-		return (0);	/* Status 1 field not yet available. */
+		return 0;	/* Status 1 field not yet available. */
 	if(IrqType == STS_IRQ_RING_STATUS)
-		return (1);	/* Status 2 & 3 fields not affected. */
+		return 1;	/* Status 2 & 3 fields not affected. */
 
 	/* Note: At this point, the interrupt is either TRANSMIT or RECEIVE. */
 	if(ssb->Parm[1] == (unsigned short) -1)
-		return (0);	/* Status 2 field not yet available. */
+		return 0;	/* Status 2 field not yet available. */
 	if(ssb->Parm[2] == (unsigned short) -1)
-		return (0);	/* Status 3 field not yet available. */
+		return 0;	/* Status 3 field not yet available. */
 
-	return (1);	/* All SSB fields have been written by the adapter. */
+	return 1;	/* All SSB fields have been written by the adapter. */
 }
 
 /*
@@ -1143,7 +1143,7 @@
 #endif
 	tms380tr_cancel_tx_queue(tp);
 
-	return (0);
+	return 0;
 }
 
 /*
@@ -1154,7 +1154,7 @@
 {
 	struct net_local *tp = netdev_priv(dev);
 
-	return ((struct net_device_stats *)&tp->MacStat);
+	return (struct net_device_stats *)&tp->MacStat;
 }
 
 /*
@@ -1256,7 +1256,7 @@
 	if (request_firmware(&fw_entry, "tms380tr.bin", tp->pdev) != 0) {
 		printk(KERN_ALERT "%s: firmware %s is missing, cannot start.\n",
 			dev->name, "tms380tr.bin");
-		return (-1);
+		return -1;
 	}
 
 	fw_ptr = (unsigned short *)fw_entry->data;
@@ -1321,16 +1321,14 @@
 
 			/* Clear CPHALT and start BUD */
 			SIFWRITEW(c, SIFACL);
-			if (fw_entry)
-				release_firmware(fw_entry);
-			return (1);
+			release_firmware(fw_entry);
+			return 1;
 		}
 	} while(count == 0);
 
-	if (fw_entry)
-		release_firmware(fw_entry);
+	release_firmware(fw_entry);
 	printk(KERN_INFO "%s: Adapter Download Failed\n", dev->name);
-	return (-1);
+	return -1;
 }
 
 MODULE_FIRMWARE("tms380tr.bin");
@@ -1365,7 +1363,7 @@
 				printk(KERN_DEBUG " %04X\n", Status);
 			/* BUD successfully completed */
 			if(Status == STS_INITIALIZE)
-				return (1);
+				return 1;
 		/* Unrecoverable hardware error, BUD not completed? */
 		} while((loop_cnt > 0) && ((Status & (STS_ERROR | STS_TEST))
 			!= (STS_ERROR | STS_TEST)));
@@ -1392,7 +1390,7 @@
 	else
 		printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n", dev->name, Status & 0x000f);
 
-	return (-1);
+	return -1;
 }
 
 /*
@@ -1466,7 +1464,7 @@
 				{
 					printk(KERN_INFO "%s: DMA failed\n", dev->name);
 					/* DMA data error: wrong data in SCB */
-					return (-1);
+					return -1;
 				}
 				i++;
 			} while(i < 6);
@@ -1475,11 +1473,11 @@
 			do {	/* Test if contents of SSB is valid */
 				if(SSB_Test[i] != *(sb_ptr + i))
 					/* DMA data error: wrong data in SSB */
-					return (-1);
+					return -1;
 				i++;
 			} while (i < 8);
 
-			return (1);	/* Adapter successfully initialized */
+			return 1;	/* Adapter successfully initialized */
 		}
 		else
 		{
@@ -1490,7 +1488,7 @@
 				Status &= STS_ERROR_MASK;
 				/* ShowInitialisationErrorCode(Status); */
 				printk(KERN_INFO "%s: Status error: %d\n", dev->name, Status);
-				return (-1); /* Unrecoverable error */
+				return -1; /* Unrecoverable error */
 			}
 			else
 			{
@@ -1505,7 +1503,7 @@
 	} while(retry_cnt > 0);
 
 	printk(KERN_INFO "%s: Retry exceeded\n", dev->name);
-	return (-1);
+	return -1;
 }
 
 /*
diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c
index d4c7c0c..d3e788a 100644
--- a/drivers/net/tokenring/tmspci.c
+++ b/drivers/net/tokenring/tmspci.c
@@ -125,18 +125,16 @@
 	dev->irq 	= pci_irq_line;
 	dev->dma	= 0;
 
-	printk("%s: %s\n", dev->name, cardinfo->name);
-	printk("%s:    IO: %#4lx  IRQ: %d\n",
-	       dev->name, dev->base_addr, dev->irq);
+	dev_info(&pdev->dev, "%s\n", cardinfo->name);
+	dev_info(&pdev->dev, "    IO: %#4lx  IRQ: %d\n", dev->base_addr, dev->irq);
 		
 	tms_pci_read_eeprom(dev);
 
-	printk("%s:    Ring Station Address: %pM\n",
-	       dev->name, dev->dev_addr);
+	dev_info(&pdev->dev, "    Ring Station Address: %pM\n", dev->dev_addr);
 		
 	ret = tmsdev_init(dev, &pdev->dev);
 	if (ret) {
-		printk("%s: unable to get memory for dev->priv.\n", dev->name);
+		dev_info(&pdev->dev, "unable to get memory for dev->priv.\n");
 		goto err_out_region;
 	}
 
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
index a03730b..5c633a32 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
@@ -219,7 +219,7 @@
 	if (i == 100)
 		return 0xffff;
 	else
-		return (TSI_READ_PHY(TSI108_MAC_MII_DATAIN));
+		return TSI_READ_PHY(TSI108_MAC_MII_DATAIN);
 }
 
 static void tsi108_write_mii(struct tsi108_prv_data *data,
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 516713f..f303595 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -11,8 +11,8 @@
 if NET_TULIP
 
 config DE2104X
-	tristate "Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
+	tristate "Early DECchip Tulip (dc2104x) PCI support"
+	depends on PCI
 	select CRC32
 	---help---
 	  This driver is developed for the SMC EtherPower series Ethernet
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index 5efa577..28e1ffb 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -243,6 +243,7 @@
 	NWayState		= (1 << 14) | (1 << 13) | (1 << 12),
 	NWayRestart		= (1 << 12),
 	NonselPortActive	= (1 << 9),
+	SelPortActive		= (1 << 8),
 	LinkFailStatus		= (1 << 2),
 	NetCxnErr		= (1 << 1),
 };
@@ -363,7 +364,9 @@
 
 /* 21041 transceiver register settings: TP AUTO, BNC, AUI, TP, TP FD*/
 static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
-static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, };
+static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
+/* If on-chip autonegotiation is broken, use half-duplex (FF3F) instead */
+static u16 t21041_csr14_brk[] = { 0xFF3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
 static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
 
 
@@ -945,8 +948,9 @@
 	else
 		macmode &= ~FullDuplex;
 
-	if (netif_msg_link(de)) {
+	if (netif_msg_link(de))
 		dev_info(&de->dev->dev, "set link %s\n", media_name[media]);
+	if (netif_msg_hw(de)) {
 		dev_info(&de->dev->dev, "mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n",
 			 dr32(MacMode), dr32(SIAStatus),
 			 dr32(CSR13), dr32(CSR14), dr32(CSR15));
@@ -1064,6 +1068,9 @@
 	unsigned int carrier;
 	unsigned long flags;
 
+	/* clear port active bits */
+	dw32(SIAStatus, NonselPortActive | SelPortActive);
+
 	carrier = (status & NetCxnErr) ? 0 : 1;
 
 	if (carrier) {
@@ -1158,14 +1165,29 @@
 static void de_media_interrupt (struct de_private *de, u32 status)
 {
 	if (status & LinkPass) {
+		/* Ignore if current media is AUI or BNC and we can't use TP */
+		if ((de->media_type == DE_MEDIA_AUI ||
+		     de->media_type == DE_MEDIA_BNC) &&
+		    (de->media_lock ||
+		     !de_ok_to_advertise(de, DE_MEDIA_TP_AUTO)))
+			return;
+		/* If current media is not TP, change it to TP */
+		if ((de->media_type == DE_MEDIA_AUI ||
+		     de->media_type == DE_MEDIA_BNC)) {
+			de->media_type = DE_MEDIA_TP_AUTO;
+			de_stop_rxtx(de);
+			de_set_media(de);
+			de_start_rxtx(de);
+		}
 		de_link_up(de);
 		mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK);
 		return;
 	}
 
 	BUG_ON(!(status & LinkFail));
-
-	if (netif_carrier_ok(de->dev)) {
+	/* Mark the link as down only if current media is TP */
+	if (netif_carrier_ok(de->dev) && de->media_type != DE_MEDIA_AUI &&
+	    de->media_type != DE_MEDIA_BNC) {
 		de_link_down(de);
 		mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK);
 	}
@@ -1229,6 +1251,7 @@
 	if (de->de21040)
 		return;
 
+	dw32(CSR13, 0); /* Reset phy */
 	pci_read_config_dword(de->pdev, PCIPM, &pmctl);
 	pmctl |= PM_Sleep;
 	pci_write_config_dword(de->pdev, PCIPM, pmctl);
@@ -1574,12 +1597,15 @@
 		return 0; /* nothing to change */
 
 	de_link_down(de);
+	mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK);
 	de_stop_rxtx(de);
 
 	de->media_type = new_media;
 	de->media_lock = media_lock;
 	de->media_advertise = ecmd->advertising;
 	de_set_media(de);
+	if (netif_running(de->dev))
+		de_start_rxtx(de);
 
 	return 0;
 }
@@ -1911,8 +1937,14 @@
 	for (i = 0; i < DE_MAX_MEDIA; i++) {
 		if (de->media[i].csr13 == 0xffff)
 			de->media[i].csr13 = t21041_csr13[i];
-		if (de->media[i].csr14 == 0xffff)
-			de->media[i].csr14 = t21041_csr14[i];
+		if (de->media[i].csr14 == 0xffff) {
+			/* autonegotiation is broken at least on some chip
+			   revisions - rev. 0x21 works, 0x11 does not */
+			if (de->pdev->revision < 0x20)
+				de->media[i].csr14 = t21041_csr14_brk[i];
+			else
+				de->media[i].csr14 = t21041_csr14[i];
+		}
 		if (de->media[i].csr15 == 0xffff)
 			de->media[i].csr15 = t21041_csr15[i];
 	}
@@ -2158,6 +2190,8 @@
 		dev_err(&dev->dev, "pci_enable_device failed in resume\n");
 		goto out;
 	}
+	pci_set_master(pdev);
+	de_init_rings(de);
 	de_init_hw(de);
 out_attach:
 	netif_device_attach(dev);
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 75a64c8..4dbd493 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -1448,7 +1448,7 @@
 	status = -EIO;
     }
 
-    lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+    lp->tx_new = (lp->tx_new + 1) % lp->txRingSize;
     lp->tx_old = lp->tx_new;
 
     return status;
@@ -1506,7 +1506,7 @@
  	    lp->stats.tx_bytes += skb->len;
 	    outl(POLL_DEMAND, DE4X5_TPD);/* Start the TX */
 
-	    lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+	    lp->tx_new = (lp->tx_new + 1) % lp->txRingSize;
 
 	    if (TX_BUFFS_AVAIL) {
 		netif_start_queue(dev);         /* Another pkt may be queued */
@@ -1657,7 +1657,7 @@
 	    }
 
 	    /* Change buffer ownership for this frame, back to the adapter */
-	    for (;lp->rx_old!=entry;lp->rx_old=(++lp->rx_old)%lp->rxRingSize) {
+	    for (;lp->rx_old!=entry;lp->rx_old=(lp->rx_old + 1)%lp->rxRingSize) {
 		lp->rx_ring[lp->rx_old].status = cpu_to_le32(R_OWN);
 		barrier();
 	    }
@@ -1668,7 +1668,7 @@
 	/*
 	** Update entry information
 	*/
-	lp->rx_new = (++lp->rx_new) % lp->rxRingSize;
+	lp->rx_new = (lp->rx_new + 1) % lp->rxRingSize;
     }
 
     return 0;
@@ -1726,7 +1726,7 @@
 	}
 
 	/* Update all the pointers */
-	lp->tx_old = (++lp->tx_old) % lp->txRingSize;
+	lp->tx_old = (lp->tx_old + 1) % lp->txRingSize;
     }
 
     /* Any resources available? */
@@ -1801,7 +1801,7 @@
 
     for (; (s32)le32_to_cpu(lp->rx_ring[lp->rx_new].status)>=0;) {
 	lp->rx_ring[lp->rx_new].status = cpu_to_le32(R_OWN);
-	lp->rx_new = (++lp->rx_new % lp->rxRingSize);
+	lp->rx_new = (lp->rx_new + 1) % lp->rxRingSize;
     }
 
     outl(omr, DE4X5_OMR);
@@ -1932,7 +1932,7 @@
 	    load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
 			                                SETUP_FRAME_LEN, (struct sk_buff *)1);
 
-	    lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+	    lp->tx_new = (lp->tx_new + 1) % lp->txRingSize;
 	    outl(POLL_DEMAND, DE4X5_TPD);       /* Start the TX */
 	    dev->trans_start = jiffies; /* prevent tx timeout */
 	}
@@ -3119,7 +3119,7 @@
 	  if (lp->media == _100Mb) {
 	      if ((slnk = test_for_100Mb(dev, 6500)) < 0) {
 		  lp->media = SPD_DET;
-		  return  (slnk & ~TIMER_CB);
+		  return slnk & ~TIMER_CB;
 	      }
 	  } else {
 	      if (wait_for_link(dev) < 0) {
@@ -3484,7 +3484,7 @@
 	spd = ((~gep_rd(dev)) & GEP_SLNK);
     } else {
 	if ((lp->ibn == 2) || !lp->asBitValid)
-	    return ((lp->chipset == DC21143)?(~inl(DE4X5_SISR)&SISR_LS100):0);
+	    return (lp->chipset == DC21143) ? (~inl(DE4X5_SISR)&SISR_LS100) : 0;
 
 	spd = (lp->asBitValid & (lp->asPolarity ^ (gep_rd(dev) & lp->asBit))) |
 	          (lp->linkOK & ~lp->asBitValid);
@@ -3502,15 +3502,15 @@
     if (lp->useMII) {
 	/* Double read for sticky bits & temporary drops */
 	mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
-	return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS);
+	return mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS;
     } else if (!lp->useSROM) {                       /* de500-xa */
-	return ((~gep_rd(dev)) & GEP_SLNK);
+	return (~gep_rd(dev)) & GEP_SLNK;
     } else {
 	if ((lp->ibn == 2) || !lp->asBitValid)
-	    return ((lp->chipset == DC21143)?(~inl(DE4X5_SISR)&SISR_LS100):0);
+	    return (lp->chipset == DC21143) ? (~inl(DE4X5_SISR)&SISR_LS100) : 0;
 
-        return ((lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
-		(lp->linkOK & ~lp->asBitValid));
+        return (lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
+		(lp->linkOK & ~lp->asBitValid);
     }
 }
 
@@ -3523,17 +3523,17 @@
     if (lp->useMII) {
 	/* Double read for sticky bits & temporary drops */
 	mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
-	return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS);
+	return mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS;
     } else if (!lp->useSROM) {                       /* de500-xa */
-	return ((~gep_rd(dev)) & GEP_LNP);
+	return (~gep_rd(dev)) & GEP_LNP;
     } else {
 	if ((lp->ibn == 2) || !lp->asBitValid)
-	    return (((lp->chipset & ~0x00ff) == DC2114x) ?
+	    return ((lp->chipset & ~0x00ff) == DC2114x) ?
 		    (~inl(DE4X5_SISR)&SISR_LS10):
-		    0);
+		    0;
 
-	return ((lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
-		(lp->linkOK & ~lp->asBitValid));
+	return	(lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
+		(lp->linkOK & ~lp->asBitValid);
     }
 }
 
@@ -3544,7 +3544,7 @@
     u_long iobase = dev->base_addr;
 
     if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) {
-	return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII));
+	return mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
     } else if ((lp->chipset & ~0x00ff) == DC2114x) {
 	return (inl(DE4X5_SISR) & SISR_LPN) >> 12;
     } else {
@@ -3568,7 +3568,7 @@
 
 	lp->tmp = lp->tx_new;                /* Remember the ring position */
 	load_packet(dev, lp->frame, TD_LS | TD_FS | sizeof(lp->frame), (struct sk_buff *)1);
-	lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+	lp->tx_new = (lp->tx_new + 1) % lp->txRingSize;
 	outl(POLL_DEMAND, DE4X5_TPD);
     }
 
@@ -4930,7 +4930,7 @@
     outl(command | MII_MDC, ioaddr);
     udelay(1);
 
-    return ((inl(ioaddr) >> 19) & 1);
+    return (inl(ioaddr) >> 19) & 1;
 }
 
 /*
@@ -4975,8 +4975,8 @@
     a.breg[0]=a.breg[1];
     a.breg[1]=i;
 
-    return ((a.reg<<8)|ret); */                 /* SEEQ and Cypress way */
-/*    return ((r2<<6)|(u_int)(r3>>10)); */      /* NATIONAL and BROADCOM way */
+    return (a.reg<<8)|ret; */                 /* SEEQ and Cypress way */
+/*    return (r2<<6)|(u_int)(r3>>10); */      /* NATIONAL and BROADCOM way */
     return r2;                                  /* (I did it) My way */
 }
 
@@ -5144,7 +5144,7 @@
     if (lp->chipset == DC21140) {
 	return inl(DE4X5_GEP);
     } else if ((lp->chipset & ~0x00ff) == DC2114x) {
-	return (inl(DE4X5_SIGR) & 0x000fffff);
+	return inl(DE4X5_SIGR) & 0x000fffff;
     }
 
     return 0;
@@ -5417,7 +5417,7 @@
 	/* Set up the descriptor and give ownership to the card */
 	load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
 		                                       SETUP_FRAME_LEN, (struct sk_buff *)1);
-	lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+	lp->tx_new = (lp->tx_new + 1) % lp->txRingSize;
 	outl(POLL_DEMAND, DE4X5_TPD);                /* Start the TX */
 	netif_wake_queue(dev);                      /* Unlock the TX ring */
 	break;
@@ -5474,7 +5474,8 @@
 	tmp.lval[6] = inl(DE4X5_STRR); j+=4;
 	tmp.lval[7] = inl(DE4X5_SIGR); j+=4;
 	ioc->len = j;
-	if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
+	if (copy_to_user(ioc->data, tmp.lval, ioc->len))
+		return -EFAULT;
 	break;
 
 #define DE4X5_DUMP              0x0f /* Dump the DE4X5 Status */
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 0bc4f30..a9f7d5d 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -599,7 +599,7 @@
 	init_timer(&db->timer);
 	db->timer.expires = DMFE_TIMER_WUT + HZ * 2;
 	db->timer.data = (unsigned long)dev;
-	db->timer.function = &dmfe_timer;
+	db->timer.function = dmfe_timer;
 	add_timer(&db->timer);
 
 	return 0;
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index 1faf7a4..0013642 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -180,21 +180,24 @@
                                                        dev_warn(&dev->dev,
 								"Oversized Ethernet frame spanned multiple buffers, status %08x!\n",
 								status);
-                                               tp->stats.rx_length_errors++;
-                                       }
+						dev->stats.rx_length_errors++;
+					}
 			       } else {
                                 /* There was a fatal error. */
                                        if (tulip_debug > 2)
                                                printk(KERN_DEBUG "%s: Receive error, Rx status %08x\n",
                                                       dev->name, status);
-                                       tp->stats.rx_errors++; /* end of a packet.*/
-				       if (pkt_len > 1518 ||
-					   (status & RxDescRunt))
-					       tp->stats.rx_length_errors++;
+					dev->stats.rx_errors++; /* end of a packet.*/
+					if (pkt_len > 1518 ||
+					    (status & RxDescRunt))
+						dev->stats.rx_length_errors++;
 
-                                       if (status & 0x0004) tp->stats.rx_frame_errors++;
-                                       if (status & 0x0002) tp->stats.rx_crc_errors++;
-                                       if (status & 0x0001) tp->stats.rx_fifo_errors++;
+					if (status & 0x0004)
+						dev->stats.rx_frame_errors++;
+					if (status & 0x0002)
+						dev->stats.rx_crc_errors++;
+					if (status & 0x0001)
+						dev->stats.rx_fifo_errors++;
                                }
                        } else {
                                struct sk_buff *skb;
@@ -244,8 +247,8 @@
 
                                netif_receive_skb(skb);
 
-                               tp->stats.rx_packets++;
-                               tp->stats.rx_bytes += pkt_len;
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += pkt_len;
                        }
 #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
 		       received++;
@@ -404,20 +407,23 @@
 						dev_warn(&dev->dev,
 							 "Oversized Ethernet frame spanned multiple buffers, status %08x!\n",
 							 status);
-					tp->stats.rx_length_errors++;
+					dev->stats.rx_length_errors++;
 				}
 			} else {
 				/* There was a fatal error. */
 				if (tulip_debug > 2)
 					printk(KERN_DEBUG "%s: Receive error, Rx status %08x\n",
 					       dev->name, status);
-				tp->stats.rx_errors++; /* end of a packet.*/
+				dev->stats.rx_errors++; /* end of a packet.*/
 				if (pkt_len > 1518 ||
 				    (status & RxDescRunt))
-					tp->stats.rx_length_errors++;
-				if (status & 0x0004) tp->stats.rx_frame_errors++;
-				if (status & 0x0002) tp->stats.rx_crc_errors++;
-				if (status & 0x0001) tp->stats.rx_fifo_errors++;
+					dev->stats.rx_length_errors++;
+				if (status & 0x0004)
+					dev->stats.rx_frame_errors++;
+				if (status & 0x0002)
+					dev->stats.rx_crc_errors++;
+				if (status & 0x0001)
+					dev->stats.rx_fifo_errors++;
 			}
 		} else {
 			struct sk_buff *skb;
@@ -467,8 +473,8 @@
 
 			netif_rx(skb);
 
-			tp->stats.rx_packets++;
-			tp->stats.rx_bytes += pkt_len;
+			dev->stats.rx_packets++;
+			dev->stats.rx_bytes += pkt_len;
 		}
 		received++;
 		entry = (++tp->cur_rx) % RX_RING_SIZE;
@@ -602,18 +608,22 @@
 						printk(KERN_DEBUG "%s: Transmit error, Tx status %08x\n",
 						       dev->name, status);
 #endif
-					tp->stats.tx_errors++;
-					if (status & 0x4104) tp->stats.tx_aborted_errors++;
-					if (status & 0x0C00) tp->stats.tx_carrier_errors++;
-					if (status & 0x0200) tp->stats.tx_window_errors++;
-					if (status & 0x0002) tp->stats.tx_fifo_errors++;
+					dev->stats.tx_errors++;
+					if (status & 0x4104)
+						dev->stats.tx_aborted_errors++;
+					if (status & 0x0C00)
+						dev->stats.tx_carrier_errors++;
+					if (status & 0x0200)
+						dev->stats.tx_window_errors++;
+					if (status & 0x0002)
+						dev->stats.tx_fifo_errors++;
 					if ((status & 0x0080) && tp->full_duplex == 0)
-						tp->stats.tx_heartbeat_errors++;
+						dev->stats.tx_heartbeat_errors++;
 				} else {
-					tp->stats.tx_bytes +=
+					dev->stats.tx_bytes +=
 						tp->tx_buffers[entry].skb->len;
-					tp->stats.collisions += (status >> 3) & 15;
-					tp->stats.tx_packets++;
+					dev->stats.collisions += (status >> 3) & 15;
+					dev->stats.tx_packets++;
 				}
 
 				pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping,
@@ -655,7 +665,8 @@
 		if (csr5 & AbnormalIntr) {	/* Abnormal error summary bit. */
 			if (csr5 == 0xffffffff)
 				break;
-			if (csr5 & TxJabber) tp->stats.tx_errors++;
+			if (csr5 & TxJabber)
+				dev->stats.tx_errors++;
 			if (csr5 & TxFIFOUnderflow) {
 				if ((tp->csr6 & 0xC000) != 0xC000)
 					tp->csr6 += 0x4000;	/* Bump up the Tx threshold */
@@ -672,8 +683,8 @@
 				}
 			}
 			if (csr5 & RxDied) {		/* Missed a Rx frame. */
-                                tp->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
-				tp->stats.rx_errors++;
+				dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
+				dev->stats.rx_errors++;
 				tulip_start_rxtx(tp);
 			}
 			/*
@@ -789,7 +800,7 @@
 #endif /* CONFIG_TULIP_NAPI */
 
 	if ((missed = ioread32(ioaddr + CSR8) & 0x1ffff)) {
-		tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
+		dev->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
 	}
 
 	if (tulip_debug > 4)
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index e525875..ed66a16 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -417,7 +417,6 @@
 	int revision;
 	int flags;
 	struct napi_struct napi;
-	struct net_device_stats stats;
 	struct timer_list timer;	/* Media selection timer. */
 	struct timer_list oom_timer;    /* Out of memory timer. */
 	u32 mc_filter[2];
@@ -570,7 +569,7 @@
 	/* Trigger an immediate transmit demand. */
 	iowrite32(0, ioaddr + CSR1);
 
-	tp->stats.tx_errors++;
+	tp->dev->stats.tx_errors++;
 }
 
 #endif /* __NET_TULIP_H__ */
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 3a8d7ef..2c39f259 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -725,7 +725,7 @@
 		int status = le32_to_cpu(tp->tx_ring[entry].status);
 
 		if (status < 0) {
-			tp->stats.tx_errors++;	/* It wasn't Txed */
+			tp->dev->stats.tx_errors++;	/* It wasn't Txed */
 			tp->tx_ring[entry].status = 0;
 		}
 
@@ -781,8 +781,8 @@
 	/* release any unconsumed transmit buffers */
 	tulip_clean_tx_ring(tp);
 
-	if (ioread32 (ioaddr + CSR6) != 0xffffffff)
-		tp->stats.rx_missed_errors += ioread32 (ioaddr + CSR8) & 0xffff;
+	if (ioread32(ioaddr + CSR6) != 0xffffffff)
+		dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
 
 	spin_unlock_irqrestore (&tp->lock, flags);
 
@@ -864,12 +864,12 @@
 
 		spin_lock_irqsave (&tp->lock, flags);
 
-		tp->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
+		dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
 
 		spin_unlock_irqrestore(&tp->lock, flags);
 	}
 
-	return &tp->stats;
+	return &dev->stats;
 }
 
 
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 96de582..74217db 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -480,7 +480,7 @@
 	init_timer(&db->timer);
 	db->timer.expires = ULI526X_TIMER_WUT + HZ * 2;
 	db->timer.data = (unsigned long)dev;
-	db->timer.function = &uli526x_timer;
+	db->timer.function = uli526x_timer;
 	add_timer(&db->timer);
 
 	return 0;
@@ -1747,7 +1747,7 @@
 		if(cr10_value&0x10000000)
 			break;
 	}
-	return (cr10_value&0x0ffff);
+	return cr10_value & 0x0ffff;
 }
 
 static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data)
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 66d41cf..f0b2310 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -662,7 +662,7 @@
 	init_timer(&np->timer);
 	np->timer.expires = jiffies + 1*HZ;
 	np->timer.data = (unsigned long)dev;
-	np->timer.function = &netdev_timer;				/* timer handler */
+	np->timer.function = netdev_timer;				/* timer handler */
 	add_timer(&np->timer);
 	return 0;
 out_err:
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index a439e93..5a73752 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -29,7 +29,6 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/ethtool.h>
 #include <linux/bitops.h>
 
 #include <asm/uaccess.h>
@@ -181,19 +180,6 @@
 }
 #endif
 
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	struct xircom_private *private = netdev_priv(dev);
-
-	strcpy(info->driver, "xircom_cb");
-	strcpy(info->bus_info, pci_name(private->pdev));
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-};
-
 static const struct net_device_ops netdev_ops = {
 	.ndo_open		= xircom_open,
 	.ndo_stop		= xircom_close,
@@ -279,7 +265,6 @@
 	setup_descriptors(private);
 
 	dev->netdev_ops = &netdev_ops;
-	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 	pci_set_drvdata(pdev, dev);
 
 	if (register_netdev(dev)) {
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 2e50077..1cc6713 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -541,7 +541,7 @@
 
 	indexes->respCleared = cpu_to_le32(cleared);
 	wmb();
-	return (resp_save == NULL);
+	return resp_save == NULL;
 }
 
 static inline int
@@ -962,36 +962,34 @@
 	 * The extra status reported would be a good candidate for
 	 * ethtool_ops->get_{strings,stats}()
 	 */
-	stats->tx_packets = le32_to_cpu(s->txPackets);
-	stats->tx_bytes = le64_to_cpu(s->txBytes);
-	stats->tx_errors = le32_to_cpu(s->txCarrierLost);
-	stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost);
-	stats->collisions = le32_to_cpu(s->txMultipleCollisions);
-	stats->rx_packets = le32_to_cpu(s->rxPacketsGood);
-	stats->rx_bytes = le64_to_cpu(s->rxBytesGood);
-	stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns);
+	stats->tx_packets = le32_to_cpu(s->txPackets) +
+			saved->tx_packets;
+	stats->tx_bytes = le64_to_cpu(s->txBytes) +
+			saved->tx_bytes;
+	stats->tx_errors = le32_to_cpu(s->txCarrierLost) +
+			saved->tx_errors;
+	stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost) +
+			saved->tx_carrier_errors;
+	stats->collisions = le32_to_cpu(s->txMultipleCollisions) +
+			saved->collisions;
+	stats->rx_packets = le32_to_cpu(s->rxPacketsGood) +
+			saved->rx_packets;
+	stats->rx_bytes = le64_to_cpu(s->rxBytesGood) +
+			saved->rx_bytes;
+	stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns) +
+			saved->rx_fifo_errors;
 	stats->rx_errors = le32_to_cpu(s->rxFifoOverruns) +
-			le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors);
-	stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors);
-	stats->rx_length_errors = le32_to_cpu(s->rxOversized);
+			le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors) +
+			saved->rx_errors;
+	stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors) +
+			saved->rx_crc_errors;
+	stats->rx_length_errors = le32_to_cpu(s->rxOversized) +
+			saved->rx_length_errors;
 	tp->speed = (s->linkStatus & TYPHOON_LINK_100MBPS) ?
 			SPEED_100 : SPEED_10;
 	tp->duplex = (s->linkStatus & TYPHOON_LINK_FULL_DUPLEX) ?
 			DUPLEX_FULL : DUPLEX_HALF;
 
-	/* add in the saved statistics
-	 */
-	stats->tx_packets += saved->tx_packets;
-	stats->tx_bytes += saved->tx_bytes;
-	stats->tx_errors += saved->tx_errors;
-	stats->collisions += saved->collisions;
-	stats->rx_packets += saved->rx_packets;
-	stats->rx_bytes += saved->rx_bytes;
-	stats->rx_fifo_errors += saved->rx_fifo_errors;
-	stats->rx_errors += saved->rx_errors;
-	stats->rx_crc_errors += saved->rx_crc_errors;
-	stats->rx_length_errors += saved->rx_length_errors;
-
 	return 0;
 }
 
@@ -1762,7 +1760,7 @@
 		   (TYPHOON_RX_IP_CHK_GOOD | TYPHOON_RX_UDP_CHK_GOOD)) {
 			new_skb->ip_summed = CHECKSUM_UNNECESSARY;
 		} else
-			new_skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(new_skb);
 
 		spin_lock(&tp->state_lock);
 		if(tp->vlgrp != NULL && rx->rxStatus & TYPHOON_RX_VLAN)
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index d7b7018..52ffabe6 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -358,6 +358,14 @@
 	  really need this non-conformant variant of CDC Ethernet (or in
 	  some cases CDC MDLM) protocol, not "g_ether".
 
+config USB_NET_CX82310_ETH
+	tristate "Conexant CX82310 USB ethernet port"
+	depends on USB_USBNET
+	help
+	  Choose this option if you're using a Conexant CX82310-based ADSL
+	  router with USB ethernet port. This driver is for routers only,
+	  it will not work with ADSL modems (use cxacru driver instead).
+
 config USB_HSO
 	tristate "Option USB High Speed Mobile Devices"
 	depends on USB && RFKILL
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
index b13a279..a19b025 100644
--- a/drivers/net/usb/Makefile
+++ b/drivers/net/usb/Makefile
@@ -25,4 +25,5 @@
 obj-$(CONFIG_USB_CDC_PHONET)	+= cdc-phonet.o
 obj-$(CONFIG_USB_IPHETH)	+= ipheth.o
 obj-$(CONFIG_USB_SIERRA_NET)	+= sierra_net.o
+obj-$(CONFIG_USB_NET_CX82310_ETH)	+= cx82310_eth.o
 
diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c
new file mode 100644
index 0000000..8969f12
--- /dev/null
+++ b/drivers/net/usb/cx82310_eth.c
@@ -0,0 +1,346 @@
+/*
+ * Driver for USB ethernet port of Conexant CX82310-based ADSL routers
+ * Copyright (C) 2010 by Ondrej Zary
+ * some parts inspired by the cxacru 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/usbnet.h>
+
+enum cx82310_cmd {
+	CMD_START		= 0x84,	/* no effect? */
+	CMD_STOP		= 0x85,	/* no effect? */
+	CMD_GET_STATUS		= 0x90,	/* returns nothing? */
+	CMD_GET_MAC_ADDR	= 0x91,	/* read MAC address */
+	CMD_GET_LINK_STATUS	= 0x92,	/* not useful, link is always up */
+	CMD_ETHERNET_MODE	= 0x99,	/* unknown, needed during init */
+};
+
+enum cx82310_status {
+	STATUS_UNDEFINED,
+	STATUS_SUCCESS,
+	STATUS_ERROR,
+	STATUS_UNSUPPORTED,
+	STATUS_UNIMPLEMENTED,
+	STATUS_PARAMETER_ERROR,
+	STATUS_DBG_LOOPBACK,
+};
+
+#define CMD_PACKET_SIZE	64
+/* first command after power on can take around 8 seconds */
+#define CMD_TIMEOUT	15000
+#define CMD_REPLY_RETRY 5
+
+#define CX82310_MTU	1514
+#define CMD_EP		0x01
+
+/*
+ * execute control command
+ *  - optionally send some data (command parameters)
+ *  - optionally wait for the reply
+ *  - optionally read some data from the reply
+ */
+static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
+		       u8 *wdata, int wlen, u8 *rdata, int rlen)
+{
+	int actual_len, retries, ret;
+	struct usb_device *udev = dev->udev;
+	u8 *buf = kzalloc(CMD_PACKET_SIZE, GFP_KERNEL);
+
+	if (!buf)
+		return -ENOMEM;
+
+	/* create command packet */
+	buf[0] = cmd;
+	if (wdata)
+		memcpy(buf + 4, wdata, min_t(int, wlen, CMD_PACKET_SIZE - 4));
+
+	/* send command packet */
+	ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, CMD_EP), buf,
+			   CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT);
+	if (ret < 0) {
+		dev_err(&dev->udev->dev, "send command %#x: error %d\n",
+			cmd, ret);
+		goto end;
+	}
+
+	if (reply) {
+		/* wait for reply, retry if it's empty */
+		for (retries = 0; retries < CMD_REPLY_RETRY; retries++) {
+			ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, CMD_EP),
+					   buf, CMD_PACKET_SIZE, &actual_len,
+					   CMD_TIMEOUT);
+			if (ret < 0) {
+				dev_err(&dev->udev->dev,
+					"reply receive error %d\n", ret);
+				goto end;
+			}
+			if (actual_len > 0)
+				break;
+		}
+		if (actual_len == 0) {
+			dev_err(&dev->udev->dev, "no reply to command %#x\n",
+				cmd);
+			ret = -EIO;
+			goto end;
+		}
+		if (buf[0] != cmd) {
+			dev_err(&dev->udev->dev,
+				"got reply to command %#x, expected: %#x\n",
+				buf[0], cmd);
+			ret = -EIO;
+			goto end;
+		}
+		if (buf[1] != STATUS_SUCCESS) {
+			dev_err(&dev->udev->dev, "command %#x failed: %#x\n",
+				cmd, buf[1]);
+			ret = -EIO;
+			goto end;
+		}
+		if (rdata)
+			memcpy(rdata, buf + 4,
+			       min_t(int, rlen, CMD_PACKET_SIZE - 4));
+	}
+end:
+	kfree(buf);
+	return ret;
+}
+
+#define partial_len	data[0]		/* length of partial packet data */
+#define partial_rem	data[1]		/* remaining (missing) data length */
+#define partial_data	data[2]		/* partial packet data */
+
+static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int ret;
+	char buf[15];
+	struct usb_device *udev = dev->udev;
+
+	/* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */
+	if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0
+	    && strcmp(buf, "USB NET CARD")) {
+		dev_info(&udev->dev, "ignoring: probably an ADSL modem\n");
+		return -ENODEV;
+	}
+
+	ret = usbnet_get_endpoints(dev, intf);
+	if (ret)
+		return ret;
+
+	/*
+	 * this must not include ethernet header as the device can send partial
+	 * packets with no header (and sometimes even empty URBs)
+	 */
+	dev->net->hard_header_len = 0;
+	/* we can send at most 1514 bytes of data (+ 2-byte header) per URB */
+	dev->hard_mtu = CX82310_MTU + 2;
+	/* we can receive URBs up to 4KB from the device */
+	dev->rx_urb_size = 4096;
+
+	dev->partial_data = (unsigned long) kmalloc(dev->hard_mtu, GFP_KERNEL);
+	if (!dev->partial_data)
+		return -ENOMEM;
+
+	/* enable ethernet mode (?) */
+	ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);
+	if (ret) {
+		dev_err(&udev->dev, "unable to enable ethernet mode: %d\n",
+			ret);
+		goto err;
+	}
+
+	/* get the MAC address */
+	ret = cx82310_cmd(dev, CMD_GET_MAC_ADDR, true, NULL, 0,
+			  dev->net->dev_addr, ETH_ALEN);
+	if (ret) {
+		dev_err(&udev->dev, "unable to read MAC address: %d\n", ret);
+		goto err;
+	}
+
+	/* start (does not seem to have any effect?) */
+	ret = cx82310_cmd(dev, CMD_START, false, NULL, 0, NULL, 0);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	kfree((void *)dev->partial_data);
+	return ret;
+}
+
+static void cx82310_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+	kfree((void *)dev->partial_data);
+}
+
+/*
+ * RX is NOT easy - we can receive multiple packets per skb, each having 2-byte
+ * packet length at the beginning.
+ * The last packet might be incomplete (when it crosses the 4KB URB size),
+ * continuing in the next skb (without any headers).
+ * If a packet has odd length, there is one extra byte at the end (before next
+ * packet or at the end of the URB).
+ */
+static int cx82310_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	int len;
+	struct sk_buff *skb2;
+
+	/*
+	 * If the last skb ended with an incomplete packet, this skb contains
+	 * end of that packet at the beginning.
+	 */
+	if (dev->partial_rem) {
+		len = dev->partial_len + dev->partial_rem;
+		skb2 = alloc_skb(len, GFP_ATOMIC);
+		if (!skb2)
+			return 0;
+		skb_put(skb2, len);
+		memcpy(skb2->data, (void *)dev->partial_data,
+		       dev->partial_len);
+		memcpy(skb2->data + dev->partial_len, skb->data,
+		       dev->partial_rem);
+		usbnet_skb_return(dev, skb2);
+		skb_pull(skb, (dev->partial_rem + 1) & ~1);
+		dev->partial_rem = 0;
+		if (skb->len < 2)
+			return 1;
+	}
+
+	/* a skb can contain multiple packets */
+	while (skb->len > 1) {
+		/* first two bytes are packet length */
+		len = skb->data[0] | (skb->data[1] << 8);
+		skb_pull(skb, 2);
+
+		/* if last packet in the skb, let usbnet to process it */
+		if (len == skb->len || len + 1 == skb->len) {
+			skb_trim(skb, len);
+			break;
+		}
+
+		if (len > CX82310_MTU) {
+			dev_err(&dev->udev->dev, "RX packet too long: %d B\n",
+				len);
+			return 0;
+		}
+
+		/* incomplete packet, save it for the next skb */
+		if (len > skb->len) {
+			dev->partial_len = skb->len;
+			dev->partial_rem = len - skb->len;
+			memcpy((void *)dev->partial_data, skb->data,
+			       dev->partial_len);
+			skb_pull(skb, skb->len);
+			break;
+		}
+
+		skb2 = alloc_skb(len, GFP_ATOMIC);
+		if (!skb2)
+			return 0;
+		skb_put(skb2, len);
+		memcpy(skb2->data, skb->data, len);
+		/* process the packet */
+		usbnet_skb_return(dev, skb2);
+
+		skb_pull(skb, (len + 1) & ~1);
+	}
+
+	/* let usbnet process the last packet */
+	return 1;
+}
+
+/* TX is easy, just add 2 bytes of length at the beginning */
+static struct sk_buff *cx82310_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+				       gfp_t flags)
+{
+	int len = skb->len;
+
+	if (skb_headroom(skb) < 2) {
+		struct sk_buff *skb2 = skb_copy_expand(skb, 2, 0, flags);
+		dev_kfree_skb_any(skb);
+		skb = skb2;
+		if (!skb)
+			return NULL;
+	}
+	skb_push(skb, 2);
+
+	skb->data[0] = len;
+	skb->data[1] = len >> 8;
+
+	return skb;
+}
+
+
+static const struct driver_info	cx82310_info = {
+	.description	= "Conexant CX82310 USB ethernet",
+	.flags		= FLAG_ETHER,
+	.bind		= cx82310_bind,
+	.unbind		= cx82310_unbind,
+	.rx_fixup	= cx82310_rx_fixup,
+	.tx_fixup	= cx82310_tx_fixup,
+};
+
+#define USB_DEVICE_CLASS(vend, prod, cl, sc, pr) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+		       USB_DEVICE_ID_MATCH_DEV_INFO, \
+	.idVendor = (vend), \
+	.idProduct = (prod), \
+	.bDeviceClass = (cl), \
+	.bDeviceSubClass = (sc), \
+	.bDeviceProtocol = (pr)
+
+static const struct usb_device_id products[] = {
+	{
+		USB_DEVICE_CLASS(0x0572, 0xcb01, 0xff, 0, 0),
+		.driver_info = (unsigned long) &cx82310_info
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver cx82310_driver = {
+	.name		= "cx82310_eth",
+	.id_table	= products,
+	.probe		= usbnet_probe,
+	.disconnect	= usbnet_disconnect,
+	.suspend	= usbnet_suspend,
+	.resume		= usbnet_resume,
+};
+
+static int __init cx82310_init(void)
+{
+	return usb_register(&cx82310_driver);
+}
+module_init(cx82310_init);
+
+static void __exit cx82310_exit(void)
+{
+	usb_deregister(&cx82310_driver);
+}
+module_exit(cx82310_exit);
+
+MODULE_AUTHOR("Ondrej Zary");
+MODULE_DESCRIPTION("Conexant CX82310-based ADSL router USB ethernet driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 1cd752f..b154a94 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -843,16 +843,7 @@
 	return NETDEV_TX_OK;
 }
 
-static void hso_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
-{
-	struct hso_net *odev = netdev_priv(net);
-
-	strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN);
-	usb_make_path(odev->parent->usb, info->bus_info, sizeof info->bus_info);
-}
-
 static const struct ethtool_ops ops = {
-	.get_drvinfo = hso_get_drvinfo,
 	.get_link = ethtool_op_get_link
 };
 
@@ -1645,11 +1636,11 @@
  * NB: both 1->0 and 0->1 transitions are counted except for
  *     RI where only 0->1 is counted.
  */
-static int hso_get_count(struct hso_serial *serial,
-			  struct serial_icounter_struct __user *icnt)
+static int hso_get_count(struct tty_struct *tty,
+		  struct serial_icounter_struct *icount)
 {
-	struct serial_icounter_struct icount;
 	struct uart_icount cnow;
+	struct hso_serial *serial = get_serial_by_tty(tty);
 	struct hso_tiocmget  *tiocmget = serial->tiocmget;
 
 	memset(&icount, 0, sizeof(struct serial_icounter_struct));
@@ -1660,19 +1651,19 @@
 	memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
 	spin_unlock_irq(&serial->serial_lock);
 
-	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;
+	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 copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+	return 0;
 }
 
 
@@ -1764,10 +1755,6 @@
 	case TIOCMIWAIT:
 		ret = hso_wait_modem_status(serial, arg);
 		break;
-
-	case TIOCGICOUNT:
-		ret = hso_get_count(serial, uarg);
-		break;
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
@@ -3300,6 +3287,7 @@
 	.chars_in_buffer = hso_serial_chars_in_buffer,
 	.tiocmget = hso_serial_tiocmget,
 	.tiocmset = hso_serial_tiocmset,
+	.get_icount = hso_get_count,
 	.unthrottle = hso_unthrottle
 };
 
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index 2b7b39c..5e98643 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -759,14 +759,6 @@
 	return 0;
 }
 
-static void kaweth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	struct kaweth_device *kaweth = netdev_priv(dev);
-
-	strlcpy(info->driver, driver_name, sizeof(info->driver));
-	usb_make_path(kaweth->dev, info->bus_info, sizeof (info->bus_info));
-}
-
 static u32 kaweth_get_link(struct net_device *dev)
 {
 	struct kaweth_device *kaweth = netdev_priv(dev);
@@ -775,7 +767,6 @@
 }
 
 static const struct ethtool_ops ops = {
-	.get_drvinfo	= kaweth_get_drvinfo,
 	.get_link	= kaweth_get_link
 };
 
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index ee85c8b..d1ac15c 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -203,7 +203,7 @@
 /* is packet IPv4 */
 static inline int is_ip(struct sk_buff *skb)
 {
-	return (skb->protocol == cpu_to_be16(ETH_P_IP));
+	return skb->protocol == cpu_to_be16(ETH_P_IP);
 }
 
 /*
@@ -354,7 +354,7 @@
 
 static inline int sierra_net_is_valid_addrlen(u8 len)
 {
-	return (len == sizeof(struct in_addr));
+	return len == sizeof(struct in_addr);
 }
 
 static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen)
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 12a3c88..65cb1ab 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -805,8 +805,6 @@
 		return ret;
 	}
 
-	smsc95xx_init_mac_address(dev);
-
 	ret = smsc95xx_set_mac_address(dev);
 	if (ret < 0)
 		return ret;
@@ -1047,6 +1045,8 @@
 	pdata->use_tx_csum = DEFAULT_TX_CSUM_ENABLE;
 	pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE;
 
+	smsc95xx_init_mac_address(dev);
+
 	/* Init all registers */
 	ret = smsc95xx_reset(dev);
 
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 5ec542d..0bbc0c3 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -250,7 +250,7 @@
 
 static int is_valid_veth_mtu(int new_mtu)
 {
-	return (new_mtu >= MIN_MTU && new_mtu <= MAX_MTU);
+	return new_mtu >= MIN_MTU && new_mtu <= MAX_MTU;
 }
 
 static int veth_change_mtu(struct net_device *dev, int new_mtu)
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index f534123..cab96ad 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -312,13 +312,14 @@
 
 #define MED_LNK_DEF 0
 #define MED_LNK_MIN 0
-#define MED_LNK_MAX 4
+#define MED_LNK_MAX 5
 /* speed_duplex[] is used for setting the speed and duplex mode of NIC.
    0: indicate autonegotiation for both speed and duplex mode
    1: indicate 100Mbps half duplex mode
    2: indicate 100Mbps full duplex mode
    3: indicate 10Mbps half duplex mode
    4: indicate 10Mbps full duplex mode
+   5: indicate 1000Mbps full duplex mode
 
    Note:
    if EEPROM have been set to the force mode, this option is ignored
@@ -617,6 +618,9 @@
 	case SPD_DPX_10_HALF:
 		status = VELOCITY_SPEED_10;
 		break;
+	case SPD_DPX_1000_FULL:
+		status = VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL;
+		break;
 	}
 	vptr->mii_status = status;
 	return status;
@@ -922,6 +926,7 @@
 		/* enable AUTO-NEGO mode */
 		mii_set_auto_on(vptr);
 	} else {
+		u16 CTRL1000;
 		u16 ANAR;
 		u8 CHIPGCR;
 
@@ -936,7 +941,11 @@
 		BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
 
 		CHIPGCR = readb(&regs->CHIPGCR);
-		CHIPGCR &= ~CHIPGCR_FCGMII;
+
+		if (mii_status & VELOCITY_SPEED_1000)
+			CHIPGCR |= CHIPGCR_FCGMII;
+		else
+			CHIPGCR &= ~CHIPGCR_FCGMII;
 
 		if (mii_status & VELOCITY_DUPLEX_FULL) {
 			CHIPGCR |= CHIPGCR_FCFDX;
@@ -952,7 +961,13 @@
 				BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
 		}
 
-		MII_REG_BITS_OFF(ADVERTISE_1000FULL | ADVERTISE_1000HALF, MII_CTRL1000, vptr->mac_regs);
+		velocity_mii_read(vptr->mac_regs, MII_CTRL1000, &CTRL1000);
+		CTRL1000 &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+		if ((mii_status & VELOCITY_SPEED_1000) &&
+		    (mii_status & VELOCITY_DUPLEX_FULL)) {
+			CTRL1000 |= ADVERTISE_1000FULL;
+		}
+		velocity_mii_write(vptr->mac_regs, MII_CTRL1000, CTRL1000);
 
 		if (!(mii_status & VELOCITY_DUPLEX_FULL) && (mii_status & VELOCITY_SPEED_10))
 			BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
@@ -967,7 +982,7 @@
 				ANAR |= ADVERTISE_100FULL;
 			else
 				ANAR |= ADVERTISE_100HALF;
-		} else {
+		} else if (mii_status & VELOCITY_SPEED_10) {
 			if (mii_status & VELOCITY_DUPLEX_FULL)
 				ANAR |= ADVERTISE_10FULL;
 			else
@@ -1013,6 +1028,9 @@
 	} else {
 		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name);
 		switch (vptr->options.spd_dpx) {
+		case SPD_DPX_1000_FULL:
+			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps full duplex\n");
+			break;
 		case SPD_DPX_100_HALF:
 			VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n");
 			break;
@@ -1954,7 +1972,7 @@
  */
 static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb)
 {
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 
 	if (rd->rdesc1.CSM & CSM_IPKT) {
 		if (rd->rdesc1.CSM & CSM_IPOK) {
@@ -2574,7 +2592,7 @@
 
 	td_ptr->tdesc1.cmd = TCPLS_NORMAL + (tdinfo->nskb_dma + 1) * 16;
 
-	if (vptr->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		td_ptr->tdesc1.vlan = cpu_to_le16(vlan_tx_tag_get(skb));
 		td_ptr->tdesc1.TCR |= TCR0_VETAG;
 	}
@@ -3170,6 +3188,37 @@
 			SUPPORTED_100baseT_Full |
 			SUPPORTED_1000baseT_Half |
 			SUPPORTED_1000baseT_Full;
+
+	cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
+	if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
+		cmd->advertising |=
+			ADVERTISED_10baseT_Half |
+			ADVERTISED_10baseT_Full |
+			ADVERTISED_100baseT_Half |
+			ADVERTISED_100baseT_Full |
+			ADVERTISED_1000baseT_Half |
+			ADVERTISED_1000baseT_Full;
+	} else {
+		switch (vptr->options.spd_dpx) {
+		case SPD_DPX_1000_FULL:
+			cmd->advertising |= ADVERTISED_1000baseT_Full;
+			break;
+		case SPD_DPX_100_HALF:
+			cmd->advertising |= ADVERTISED_100baseT_Half;
+			break;
+		case SPD_DPX_100_FULL:
+			cmd->advertising |= ADVERTISED_100baseT_Full;
+			break;
+		case SPD_DPX_10_HALF:
+			cmd->advertising |= ADVERTISED_10baseT_Half;
+			break;
+		case SPD_DPX_10_FULL:
+			cmd->advertising |= ADVERTISED_10baseT_Full;
+			break;
+		default:
+			break;
+		}
+	}
 	if (status & VELOCITY_SPEED_1000)
 		cmd->speed = SPEED_1000;
 	else if (status & VELOCITY_SPEED_100)
@@ -3200,14 +3249,35 @@
 	curr_status &= (~VELOCITY_LINK_FAIL);
 
 	new_status |= ((cmd->autoneg) ? VELOCITY_AUTONEG_ENABLE : 0);
+	new_status |= ((cmd->speed == SPEED_1000) ? VELOCITY_SPEED_1000 : 0);
 	new_status |= ((cmd->speed == SPEED_100) ? VELOCITY_SPEED_100 : 0);
 	new_status |= ((cmd->speed == SPEED_10) ? VELOCITY_SPEED_10 : 0);
 	new_status |= ((cmd->duplex == DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0);
 
-	if ((new_status & VELOCITY_AUTONEG_ENABLE) && (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE)))
+	if ((new_status & VELOCITY_AUTONEG_ENABLE) &&
+	    (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE))) {
 		ret = -EINVAL;
-	else
+	} else {
+		enum speed_opt spd_dpx;
+
+		if (new_status & VELOCITY_AUTONEG_ENABLE)
+			spd_dpx = SPD_DPX_AUTO;
+		else if ((new_status & VELOCITY_SPEED_1000) &&
+			 (new_status & VELOCITY_DUPLEX_FULL)) {
+			spd_dpx = SPD_DPX_1000_FULL;
+		} else if (new_status & VELOCITY_SPEED_100)
+			spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ?
+				SPD_DPX_100_FULL : SPD_DPX_100_HALF;
+		else if (new_status & VELOCITY_SPEED_10)
+			spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ?
+				SPD_DPX_10_FULL : SPD_DPX_10_HALF;
+		else
+			return -EOPNOTSUPP;
+
+		vptr->options.spd_dpx = spd_dpx;
+
 		velocity_set_media_mode(vptr, new_status);
+	}
 
 	return ret;
 }
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index f7b33ae..aa2e69b 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -848,7 +848,7 @@
  *	Bits in CHIPGCR register
  */
 
-#define CHIPGCR_FCGMII      0x80
+#define CHIPGCR_FCGMII      0x80	/* enable GMII mode */
 #define CHIPGCR_FCFDX       0x40
 #define CHIPGCR_FCRESV      0x20
 #define CHIPGCR_FCMODE      0x10
@@ -1390,7 +1390,8 @@
 	SPD_DPX_100_HALF = 1,
 	SPD_DPX_100_FULL = 2,
 	SPD_DPX_10_HALF = 3,
-	SPD_DPX_10_FULL = 4
+	SPD_DPX_10_FULL = 4,
+	SPD_DPX_1000_FULL = 5
 };
 
 enum velocity_init_type {
@@ -1504,22 +1505,25 @@
  *	addresses on this chain then we use the first - multi-IP WOL is not
  *	supported.
  *
- *	CHECK ME: locking
  */
 
 static inline int velocity_get_ip(struct velocity_info *vptr)
 {
-	struct in_device *in_dev = (struct in_device *) vptr->dev->ip_ptr;
+	struct in_device *in_dev;
 	struct in_ifaddr *ifa;
+	int res = -ENOENT;
 
+	rcu_read_lock();
+	in_dev = __in_dev_get_rcu(vptr->dev);
 	if (in_dev != NULL) {
 		ifa = (struct in_ifaddr *) in_dev->ifa_list;
 		if (ifa != NULL) {
 			memcpy(vptr->ip_addr, &ifa->ifa_address, 4);
-			return 0;
+			res = 0;
 		}
 	}
-	return -ENOENT;
+	rcu_read_unlock();
+	return res;
 }
 
 /**
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 4598e9d..bb6b67f 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -705,19 +705,6 @@
 	return 0;
 }
 
-static void virtnet_get_drvinfo(struct net_device *dev,
-				struct ethtool_drvinfo *drvinfo)
-{
-	struct virtnet_info *vi = netdev_priv(dev);
-	struct virtio_device *vdev = vi->vdev;
-
-	strncpy(drvinfo->driver, KBUILD_MODNAME, ARRAY_SIZE(drvinfo->driver));
-	strncpy(drvinfo->version, "N/A", ARRAY_SIZE(drvinfo->version));
-	strncpy(drvinfo->fw_version, "N/A", ARRAY_SIZE(drvinfo->fw_version));
-	strncpy(drvinfo->bus_info, dev_name(&vdev->dev),
-		ARRAY_SIZE(drvinfo->bus_info));
-}
-
 static int virtnet_set_tx_csum(struct net_device *dev, u32 data)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
@@ -830,7 +817,6 @@
 }
 
 static const struct ethtool_ops virtnet_ethtool_ops = {
-	.get_drvinfo = virtnet_get_drvinfo,
 	.set_tx_csum = virtnet_set_tx_csum,
 	.set_sg = ethtool_op_set_sg,
 	.set_tso = ethtool_op_set_tso,
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index abe0ff5..3f60e0e 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -1042,11 +1042,11 @@
 				skb->csum = htons(gdesc->rcd.csum);
 				skb->ip_summed = CHECKSUM_PARTIAL;
 			} else {
-				skb->ip_summed = CHECKSUM_NONE;
+				skb_checksum_none_assert(skb);
 			}
 		}
 	} else {
-		skb->ip_summed = CHECKSUM_NONE;
+		skb_checksum_none_assert(skb);
 	}
 }
 
@@ -1548,23 +1548,6 @@
 	}
 }
 
-
-inline void set_flag_le16(__le16 *data, u16 flag)
-{
-	*data = cpu_to_le16(le16_to_cpu(*data) | flag);
-}
-
-inline void set_flag_le64(__le64 *data, u64 flag)
-{
-	*data = cpu_to_le64(le64_to_cpu(*data) | flag);
-}
-
-inline void reset_flag_le64(__le64 *data, u64 flag)
-{
-	*data = cpu_to_le64(le64_to_cpu(*data) & ~flag);
-}
-
-
 static void
 vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
 {
@@ -1634,7 +1617,7 @@
 		u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
 		bool activeVlan = false;
 
-		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+		for (vid = 0; vid < VLAN_N_VID; vid++) {
 			if (vlan_group_get_device(adapter->vlan_grp, vid)) {
 				VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
 				activeVlan = true;
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 2121c73..c88ea5c 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -353,9 +353,20 @@
 #define VMXNET3_MAX_ETH_HDR_SIZE    22
 #define VMXNET3_MAX_SKB_BUF_SIZE    (3*1024)
 
-void set_flag_le16(__le16 *data, u16 flag);
-void set_flag_le64(__le64 *data, u64 flag);
-void reset_flag_le64(__le64 *data, u64 flag);
+static inline void set_flag_le16(__le16 *data, u16 flag)
+{
+	*data = cpu_to_le16(le16_to_cpu(*data) | flag);
+}
+
+static inline void set_flag_le64(__le64 *data, u64 flag)
+{
+	*data = cpu_to_le64(le64_to_cpu(*data) | flag);
+}
+
+static inline void reset_flag_le64(__le64 *data, u64 flag)
+{
+	*data = cpu_to_le64(le64_to_cpu(*data) & ~flag);
+}
 
 int
 vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter);
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index c7c5605..a69542e 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -501,7 +501,7 @@
 		    ext_info.l4_cksum == VXGE_HW_L4_CKSUM_OK)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
-			skb->ip_summed = CHECKSUM_NONE;
+			skb_checksum_none_assert(skb);
 
 		vxge_rx_complete(ring, skb, ext_info.vlan,
 			pkt_length, &ext_info);
@@ -822,7 +822,7 @@
 		dev->name, __func__, __LINE__,
 		fifo_hw, dtr, dtr_priv);
 
-	if (vdev->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		u16 vlan_tag = vlan_tx_tag_get(skb);
 		vxge_hw_fifo_txdl_vlan_set(dtr, vlan_tag);
 	}
@@ -1862,7 +1862,7 @@
 
 	if (vdev->vlgrp && vpath->is_open) {
 
-		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+		for (vid = 0; vid < VLAN_N_VID; vid++) {
 			if (!vlan_group_get_device(vdev->vlgrp, vid))
 				continue;
 			/* Add these vlan to the vid table */
@@ -2159,8 +2159,8 @@
 	/* Alarm MSIX Vectors count */
 	vdev->intr_cnt++;
 
-	vdev->entries = kzalloc(vdev->intr_cnt * sizeof(struct msix_entry),
-						GFP_KERNEL);
+	vdev->entries = kcalloc(vdev->intr_cnt, sizeof(struct msix_entry),
+				GFP_KERNEL);
 	if (!vdev->entries) {
 		vxge_debug_init(VXGE_ERR,
 			"%s: memory allocation failed",
@@ -2169,9 +2169,9 @@
 		goto alloc_entries_failed;
 	}
 
-	vdev->vxge_entries =
-		kzalloc(vdev->intr_cnt * sizeof(struct vxge_msix_entry),
-				GFP_KERNEL);
+	vdev->vxge_entries = kcalloc(vdev->intr_cnt,
+				     sizeof(struct vxge_msix_entry),
+				     GFP_KERNEL);
 	if (!vdev->vxge_entries) {
 		vxge_debug_init(VXGE_ERR, "%s: memory allocation failed",
 			VXGE_DRIVER_NAME);
@@ -2914,26 +2914,18 @@
 }
 
 /**
- * vxge_get_stats
+ * vxge_get_stats64
  * @dev: pointer to the device structure
+ * @stats: pointer to struct rtnl_link_stats64
  *
- * Updates the device statistics structure. This function updates the device
- * statistics structure in the net_device structure and returns a pointer
- * to the same.
  */
-static struct net_device_stats *
-vxge_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *
+vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
 {
-	struct vxgedev *vdev;
-	struct net_device_stats *net_stats;
+	struct vxgedev *vdev = netdev_priv(dev);
 	int k;
 
-	vdev = netdev_priv(dev);
-
-	net_stats = &vdev->stats.net_stats;
-
-	memset(net_stats, 0, sizeof(struct net_device_stats));
-
+	/* net_stats already zeroed by caller */
 	for (k = 0; k < vdev->no_of_vpath; k++) {
 		net_stats->rx_packets += vdev->vpaths[k].ring.stats.rx_frms;
 		net_stats->rx_bytes += vdev->vpaths[k].ring.stats.rx_bytes;
@@ -3102,7 +3094,7 @@
 static const struct net_device_ops vxge_netdev_ops = {
 	.ndo_open               = vxge_open,
 	.ndo_stop               = vxge_close,
-	.ndo_get_stats          = vxge_get_stats,
+	.ndo_get_stats64        = vxge_get_stats64,
 	.ndo_start_xmit         = vxge_xmit,
 	.ndo_validate_addr      = eth_validate_addr,
 	.ndo_set_multicast_list = vxge_set_multicast,
diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h
index 2e3b064..d4be07e 100644
--- a/drivers/net/vxge/vxge-main.h
+++ b/drivers/net/vxge/vxge-main.h
@@ -172,7 +172,6 @@
 
 struct vxge_sw_stats {
 	/* Network Stats (interface stats) */
-	struct net_device_stats net_stats;
 
 	/* Tx */
 	u64 tx_frms;
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index 0bd898c..4ac85a0 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -264,7 +264,7 @@
 		    new_line.clock_type != CLOCK_TXFROMRX &&
 		    new_line.clock_type != CLOCK_INT &&
 		    new_line.clock_type != CLOCK_TXINT)
-		return -EINVAL;	/* No such clock setting */
+			return -EINVAL;	/* No such clock setting */
 
 		if (new_line.loopback != 0 && new_line.loopback != 1)
 			return -EINVAL;
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 04c6cd4..10bafd5 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -575,7 +575,7 @@
 
 		/* Initialize the chardev data structures */
 		mutex_init(&chan->rlock);
-		init_MUTEX(&chan->wsem);
+		sema_init(&chan->wsem, 1);
 
 		/* Register the network interface */
 		if (!(chan->netdev = alloc_hdlcdev(chan))) {
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index a5ddc6c..164c362 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -73,7 +73,7 @@
 static int detect_cyc2x(void __iomem *addr);
 
 /* Miscellaneous functions */
-static int get_option_index(long *optlist, long optval);
+static int get_option_index(const long *optlist, long optval);
 static u16 checksum(u8 *buf, u32 len);
 
 #define wait_cyc(addr) cycx_exec(addr + CMD_OFFSET)
@@ -81,23 +81,23 @@
 /* Global Data */
 
 /* private data */
-static char modname[] = "cycx_drv";
-static char fullname[] = "Cyclom 2X Support Module";
-static char copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
+static const char modname[] = "cycx_drv";
+static const char fullname[] = "Cyclom 2X Support Module";
+static const char copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
 			  "<acme@conectiva.com.br>";
 
 /* Hardware configuration options.
  * These are arrays of configuration options used by verification routines.
  * The first element of each array is its size (i.e. number of options).
  */
-static long cyc2x_dpmbase_options[] = {
+static const long cyc2x_dpmbase_options[] = {
 	20,
 	0xA0000, 0xA4000, 0xA8000, 0xAC000, 0xB0000, 0xB4000, 0xB8000,
 	0xBC000, 0xC0000, 0xC4000, 0xC8000, 0xCC000, 0xD0000, 0xD4000,
 	0xD8000, 0xDC000, 0xE0000, 0xE4000, 0xE8000, 0xEC000
 };
 
-static long cycx_2x_irq_options[]  = { 7, 3, 5, 9, 10, 11, 12, 15 };
+static const long cycx_2x_irq_options[]  = { 7, 3, 5, 9, 10, 11, 12, 15 };
 
 /* Kernel Loadable Module Entry Points */
 /* Module 'insert' entry point.
@@ -529,7 +529,7 @@
 /* Miscellaneous */
 /* Get option's index into the options list.
  *	Return option's index (1 .. N) or zero if option is invalid. */
-static int get_option_index(long *optlist, long optval)
+static int get_option_index(const long *optlist, long optval)
 {
 	int i = 1;
 
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index a0e8611..859dba9 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -81,9 +81,9 @@
  */
 
 /* private data */
-static char cycx_drvname[] = "cyclomx";
-static char cycx_fullname[] = "CYCLOM 2X(tm) Sync Card Driver";
-static char cycx_copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
+static const char cycx_drvname[] = "cyclomx";
+static const char cycx_fullname[] = "CYCLOM 2X(tm) Sync Card Driver";
+static const char cycx_copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
 			  "<acme@conectiva.com.br>";
 static int cycx_ncards = CONFIG_CYCX_CARDS;
 static struct cycx_device *cycx_card_array;	/* adapter data space */
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 421d071..1481a44 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -97,11 +97,11 @@
 
 	dest = skb_push(skb, hlen);
 	if (!dest)
-		return(0);
+		return 0;
 
 	memcpy(dest, &hdr, hlen);
 
-	return(hlen);
+	return hlen;
 }
 
 static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
@@ -211,14 +211,14 @@
 		if (copy_from_user(&config, conf, sizeof(struct dlci_conf)))
 			return -EFAULT;
 		if (config.flags & ~DLCI_VALID_FLAGS)
-			return(-EINVAL);
+			return -EINVAL;
 		memcpy(&dlp->config, &config, sizeof(struct dlci_conf));
 		dlp->configured = 1;
 	}
 
 	err = (*flp->dlci_conf)(dlp->slave, dev, get);
 	if (err)
-		return(err);
+		return err;
 
 	if (get)
 	{
@@ -226,7 +226,7 @@
 			return -EFAULT;
 	}
 
-	return(0);
+	return 0;
 }
 
 static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -234,7 +234,7 @@
 	struct dlci_local *dlp;
 
 	if (!capable(CAP_NET_ADMIN))
-		return(-EPERM);
+		return -EPERM;
 
 	dlp = netdev_priv(dev);
 
@@ -242,7 +242,7 @@
 	{
 		case DLCI_GET_SLAVE:
 			if (!*(short *)(dev->dev_addr))
-				return(-EINVAL);
+				return -EINVAL;
 
 			strncpy(ifr->ifr_slave, dlp->slave->name, sizeof(ifr->ifr_slave));
 			break;
@@ -250,15 +250,15 @@
 		case DLCI_GET_CONF:
 		case DLCI_SET_CONF:
 			if (!*(short *)(dev->dev_addr))
-				return(-EINVAL);
+				return -EINVAL;
 
-			return(dlci_config(dev, ifr->ifr_data, cmd == DLCI_GET_CONF));
+			return dlci_config(dev, ifr->ifr_data, cmd == DLCI_GET_CONF);
 			break;
 
 		default: 
-			return(-EOPNOTSUPP);
+			return -EOPNOTSUPP;
 	}
-	return(0);
+	return 0;
 }
 
 static int dlci_change_mtu(struct net_device *dev, int new_mtu)
@@ -277,15 +277,15 @@
 	dlp = netdev_priv(dev);
 
 	if (!*(short *)(dev->dev_addr))
-		return(-EINVAL);
+		return -EINVAL;
 
 	if (!netif_running(dlp->slave))
-		return(-ENOTCONN);
+		return -ENOTCONN;
 
 	flp = netdev_priv(dlp->slave);
 	err = (*flp->activate)(dlp->slave, dev);
 	if (err)
-		return(err);
+		return err;
 
 	netif_start_queue(dev);
 
@@ -365,14 +365,14 @@
 	list_add(&dlp->list, &dlci_devs);
 	rtnl_unlock();
 
-	return(0);
+	return 0;
 
  err2:
 	rtnl_unlock();
 	free_netdev(master);
  err1:
 	dev_put(slave);
-	return(err);
+	return err;
 }
 
 static int dlci_del(struct dlci_add *dlci)
@@ -385,10 +385,10 @@
 	/* validate slave device */
 	master = __dev_get_by_name(&init_net, dlci->devname);
 	if (!master)
-		return(-ENODEV);
+		return -ENODEV;
 
 	if (netif_running(master)) {
-		return(-EBUSY);
+		return -EBUSY;
 	}
 
 	dlp = netdev_priv(master);
@@ -406,7 +406,7 @@
 	}
 	rtnl_unlock();
 
-	return(err);
+	return err;
 }
 
 static int dlci_ioctl(unsigned int cmd, void __user *arg)
@@ -415,7 +415,7 @@
 	int err;
 	
 	if (!capable(CAP_NET_ADMIN))
-		return(-EPERM);
+		return -EPERM;
 
 	if (copy_from_user(&add, arg, sizeof(struct dlci_add)))
 		return -EFAULT;
@@ -438,7 +438,7 @@
 			err = -EINVAL;
 	}
 
-	return(err);
+	return err;
 }
 
 static const struct header_ops dlci_header_ops = {
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index b38ffa1..b1e5e5b 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -191,7 +191,8 @@
 
 		switch (ntohl (cisco_data->type)) {
 		case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
-			in_dev = dev->ip_ptr;
+			rcu_read_lock();
+			in_dev = __in_dev_get_rcu(dev);
 			addr = 0;
 			mask = ~cpu_to_be32(0); /* is the mask correct? */
 
@@ -211,6 +212,7 @@
 				cisco_keepalive_send(dev, CISCO_ADDR_REPLY,
 						     addr, mask);
 			}
+			rcu_read_unlock();
 			dev_kfree_skb_any(skb);
 			return NET_RX_SUCCESS;
 
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index 4d4dc38..7f5bb91 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -46,7 +46,7 @@
 
 #include <net/x25device.h>
 
-static char bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+static const u8 bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 
 /* If this number is made larger, check that the temporary string buffer
  * in lapbeth_new_device is large enough to store the probe device name.*/
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index e2c6f7f..70feb84 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -1022,7 +1022,7 @@
 
     if (sc->lmc_ok){
         lmc_trace(dev, "lmc_open lmc_ok out");
-        return (0);
+        return 0;
     }
 
     lmc_softreset (sc);
@@ -1105,12 +1105,12 @@
     init_timer (&sc->timer);
     sc->timer.expires = jiffies + HZ;
     sc->timer.data = (unsigned long) dev;
-    sc->timer.function = &lmc_watchdog;
+    sc->timer.function = lmc_watchdog;
     add_timer (&sc->timer);
 
     lmc_trace(dev, "lmc_open out");
 
-    return (0);
+    return 0;
 }
 
 /* Total reset to compensate for the AdTran DSU doing bad things
diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
index 5394b51..17d408f 100644
--- a/drivers/net/wan/n2.c
+++ b/drivers/net/wan/n2.c
@@ -282,7 +282,7 @@
 		    new_line.clock_type != CLOCK_TXFROMRX &&
 		    new_line.clock_type != CLOCK_INT &&
 		    new_line.clock_type != CLOCK_TXINT)
-		return -EINVAL;	/* No such clock setting */
+			return -EINVAL;	/* No such clock setting */
 
 		if (new_line.loopback != 0 && new_line.loopback != 1)
 			return -EINVAL;
@@ -379,14 +379,14 @@
 	if (request_irq(irq, sca_intr, 0, devname, card)) {
 		printk(KERN_ERR "n2: could not allocate IRQ\n");
 		n2_destroy_card(card);
-		return(-EBUSY);
+		return -EBUSY;
 	}
 	card->irq = irq;
 
 	if (!request_mem_region(winbase, USE_WINDOWSIZE, devname)) {
 		printk(KERN_ERR "n2: could not request RAM window\n");
 		n2_destroy_card(card);
-		return(-EBUSY);
+		return -EBUSY;
 	}
 	card->phy_winbase = winbase;
 	card->winbase = ioremap(winbase, USE_WINDOWSIZE);
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index c6aa66e..f875cfa 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -1,5 +1,5 @@
 #define	USE_PCI_CLOCK
-static char rcsid[] = 
+static const char rcsid[] =
 "Revision: 3.4.5 Date: 2002/03/07 ";
 
 /*
@@ -451,11 +451,11 @@
 		if ((status & DST_EOM) || (first_bd == card->chan[ch].rx_last_bd)) {
 			/* Return the size of a good frame or incomplete bad frame 
 			* (dma_buf_read will clean the buffer descriptors in this case). */
-			return (rcvd);
+			return rcvd;
 		}
 		ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
 	}
-	return (-1);
+	return -1;
 }
 
 /*
@@ -557,7 +557,7 @@
 		cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch),
 			   RX_BD_ADDR(ch, chan->rx_last_bd));
 	}
-	return (rcvd);
+	return rcvd;
 }
 
 static void tx_dma_stop(pc300_t * card, int ch)
@@ -1733,7 +1733,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
 
-	return (pfalc->bec);
+	return pfalc->bec;
 }
 
 /**********************************/
@@ -2819,7 +2819,7 @@
 	*br_io = 0;
 
 	if (rate == 0)
-		return (0);
+		return 0;
 
 	for (br = 0, br_pwr = 1; br <= 9; br++, br_pwr <<= 1) {
 		if ((tc = clock / br_pwr / rate) <= 0xff) {
@@ -2832,11 +2832,11 @@
 		error = ((rate - (clock / br_pwr / rate)) / rate) * 1000;
 		/* Errors bigger than +/- 1% won't be tolerated */
 		if (error < -10 || error > 10)
-			return (-1);
+			return -1;
 		else
-			return (tc);
+			return tc;
 	} else {
-		return (-1);
+		return -1;
 	}
 }
 
@@ -3207,7 +3207,7 @@
 			break;
 		}
 	}
-	return (i);
+	return i;
 }
 
 static void plx_init(pc300_t * card)
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 4293889..515d9b8 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -540,7 +540,7 @@
 		return -ENODEV; 
 	}
    
-	return(0); 
+	return 0;
 } 
 
 static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index e2cff64..fd73759 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -220,7 +220,7 @@
 		    new_line.clock_type != CLOCK_TXFROMRX &&
 		    new_line.clock_type != CLOCK_INT &&
 		    new_line.clock_type != CLOCK_TXINT)
-		return -EINVAL;	/* No such clock setting */
+			return -EINVAL;	/* No such clock setting */
 
 		if (new_line.loopback != 0 && new_line.loopback != 1)
 			return -EINVAL;
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index f4125da..3f4e2b5 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -178,7 +178,7 @@
 	byte = *temp;
 	spin_unlock_irqrestore(&sdla_lock, flags);
 
-	return(byte);
+	return byte;
 }
 
 static void sdla_stop(struct net_device *dev)
@@ -267,7 +267,7 @@
 			resp = *temp;
 		}
 	}
-	return(time_before(jiffies, done) ? jiffies - start : -1);
+	return time_before(jiffies, done) ? jiffies - start : -1;
 }
 
 /* constants for Z80 CPU speed */
@@ -283,13 +283,13 @@
 
 	sdla_start(dev);
 	if (sdla_z80_poll(dev, 0, 3*HZ, Z80_READY, 0) < 0)
-		return(-EIO);
+		return -EIO;
 
 	data = LOADER_READY;
 	sdla_write(dev, 0, &data, 1);
 
 	if ((jiffs = sdla_z80_poll(dev, 0, 8*HZ, Z80_SCC_OK, Z80_SCC_BAD)) < 0)
-		return(-EIO);
+		return -EIO;
 
 	sdla_stop(dev);
 	sdla_read(dev, 0, &data, 1);
@@ -297,11 +297,11 @@
 	if (data == Z80_SCC_BAD)
 	{
 		printk("%s: SCC bad\n", dev->name);
-		return(-EIO);
+		return -EIO;
 	}
 
 	if (data != Z80_SCC_OK)
-		return(-EINVAL);
+		return -EINVAL;
 
 	if (jiffs < 165)
 		ifr->ifr_mtu = SDLA_CPU_16M;
@@ -316,7 +316,7 @@
 	else
 		ifr->ifr_mtu = SDLA_CPU_3M;
  
-	return(0);
+	return 0;
 }
 
 /************************************************
@@ -493,7 +493,7 @@
 	if (ret != SDLA_RET_OK)
 	   	sdla_errors(dev, cmd, dlci, ret, len, &status);
 
-	return(ret);
+	return ret;
 }
 
 /***********************************************
@@ -516,14 +516,14 @@
 			break;
 
 	if (i == CONFIG_DLCI_MAX)
-		return(-ENODEV);
+		return -ENODEV;
 
 	flp->dlci[i] = abs(flp->dlci[i]);
 
 	if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE))
 		sdla_cmd(slave, SDLA_ACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL);
 
-	return(0);
+	return 0;
 }
 
 static int sdla_deactivate(struct net_device *slave, struct net_device *master)
@@ -538,14 +538,14 @@
 			break;
 
 	if (i == CONFIG_DLCI_MAX)
-		return(-ENODEV);
+		return -ENODEV;
 
 	flp->dlci[i] = -abs(flp->dlci[i]);
 
 	if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE))
 		sdla_cmd(slave, SDLA_DEACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL);
 
-	return(0);
+	return 0;
 }
 
 static int sdla_assoc(struct net_device *slave, struct net_device *master)
@@ -554,7 +554,7 @@
 	int               i;
 
 	if (master->type != ARPHRD_DLCI)
-		return(-EINVAL);
+		return -EINVAL;
 
 	flp = netdev_priv(slave);
 
@@ -563,11 +563,11 @@
 		if (!flp->master[i])
 			break;
 		if (abs(flp->dlci[i]) == *(short *)(master->dev_addr))
-			return(-EADDRINUSE);
+			return -EADDRINUSE;
 	} 
 
 	if (i == CONFIG_DLCI_MAX)
-		return(-EMLINK);  /* #### Alan: Comments on this ?? */
+		return -EMLINK;  /* #### Alan: Comments on this ?? */
 
 
 	flp->master[i] = master;
@@ -581,7 +581,7 @@
 			sdla_cmd(slave, SDLA_ADD_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL);
 	}
 
-	return(0);
+	return 0;
 }
 
 static int sdla_deassoc(struct net_device *slave, struct net_device *master)
@@ -596,7 +596,7 @@
 			break;
 
 	if (i == CONFIG_DLCI_MAX)
-		return(-ENODEV);
+		return -ENODEV;
 
 	flp->master[i] = NULL;
 	flp->dlci[i] = 0;
@@ -609,7 +609,7 @@
 			sdla_cmd(slave, SDLA_DELETE_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL);
 	}
 
-	return(0);
+	return 0;
 }
 
 static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
@@ -626,7 +626,7 @@
 			break;
 
 	if (i == CONFIG_DLCI_MAX)
-		return(-ENODEV);
+		return -ENODEV;
 
 	dlp = netdev_priv(master);
 
@@ -641,7 +641,7 @@
 			            &dlp->config, sizeof(struct dlci_conf) - 4 * sizeof(short), NULL, NULL);
 	}
 
-	return(ret == SDLA_RET_OK ? 0 : -EIO);
+	return ret == SDLA_RET_OK ? 0 : -EIO;
 }
 
 /**************************
@@ -986,7 +986,7 @@
 
 	netif_stop_queue(dev);
 	
-	return(0);
+	return 0;
 }
 
 struct conf_data {
@@ -1006,10 +1006,10 @@
 	flp = netdev_priv(dev);
 
 	if (!flp->initialized)
-		return(-EPERM);
+		return -EPERM;
 
 	if (!flp->configured)
-		return(-EPERM);
+		return -EPERM;
 
 	/* time to send in the configuration */
 	len = 0;
@@ -1087,7 +1087,7 @@
 
 	netif_start_queue(dev);
 	
-	return(0);
+	return 0;
 }
 
 static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, int get)
@@ -1098,48 +1098,48 @@
 	short             size;
 
 	if (dev->type == 0xFFFF)
-		return(-EUNATCH);
+		return -EUNATCH;
 
 	flp = netdev_priv(dev);
 
 	if (!get)
 	{
 		if (netif_running(dev))
-			return(-EBUSY);
+			return -EBUSY;
 
 		if(copy_from_user(&data.config, conf, sizeof(struct frad_conf)))
 			return -EFAULT;
 
 		if (data.config.station & ~FRAD_STATION_NODE)
-			return(-EINVAL);
+			return -EINVAL;
 
 		if (data.config.flags & ~FRAD_VALID_FLAGS)
-			return(-EINVAL);
+			return -EINVAL;
 
 		if ((data.config.kbaud < 0) || 
 			 ((data.config.kbaud > 128) && (flp->type != SDLA_S508)))
-			return(-EINVAL);
+			return -EINVAL;
 
 		if (data.config.clocking & ~(FRAD_CLOCK_INT | SDLA_S508_PORT_RS232))
-			return(-EINVAL);
+			return -EINVAL;
 
 		if ((data.config.mtu < 0) || (data.config.mtu > SDLA_MAX_MTU))
-			return(-EINVAL);
+			return -EINVAL;
 
 		if ((data.config.T391 < 5) || (data.config.T391 > 30))
-			return(-EINVAL);
+			return -EINVAL;
 
 		if ((data.config.T392 < 5) || (data.config.T392 > 30))
-			return(-EINVAL);
+			return -EINVAL;
 
 		if ((data.config.N391 < 1) || (data.config.N391 > 255))
-			return(-EINVAL);
+			return -EINVAL;
 
 		if ((data.config.N392 < 1) || (data.config.N392 > 10))
-			return(-EINVAL);
+			return -EINVAL;
 
 		if ((data.config.N393 < 1) || (data.config.N393 > 10))
-			return(-EINVAL);
+			return -EINVAL;
 
 		memcpy(&flp->config, &data.config, sizeof(struct frad_conf));
 		flp->config.flags |= SDLA_DIRECT_RECV;
@@ -1171,7 +1171,7 @@
 		{
 			size = sizeof(data);
 			if (sdla_cmd(dev, SDLA_READ_DLCI_CONFIGURATION, 0, 0, NULL, 0, &data, &size) != SDLA_RET_OK)
-				return(-EIO);
+				return -EIO;
 		}
 		else
 			if (flp->configured)
@@ -1185,7 +1185,7 @@
 		return copy_to_user(conf, &data.config, sizeof(struct frad_conf))?-EFAULT:0;
 	}
 
-	return(0);
+	return 0;
 }
 
 static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int read)
@@ -1200,7 +1200,7 @@
 	{	
 		temp = kzalloc(mem.len, GFP_KERNEL);
 		if (!temp)
-			return(-ENOMEM);
+			return -ENOMEM;
 		sdla_read(dev, mem.addr, temp, mem.len);
 		if(copy_to_user(mem.data, temp, mem.len))
 		{
@@ -1217,7 +1217,7 @@
 		sdla_write(dev, mem.addr, temp, mem.len);
 		kfree(temp);
 	}
-	return(0);
+	return 0;
 }
 
 static int sdla_reconfig(struct net_device *dev)
@@ -1241,7 +1241,7 @@
 	sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, 0, 0, &data, len, NULL, NULL);
 	sdla_cmd(dev, SDLA_ENABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
 
-	return(0);
+	return 0;
 }
 
 static int sdla_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -1254,20 +1254,20 @@
 	flp = netdev_priv(dev);
 
 	if (!flp->initialized)
-		return(-EINVAL);
+		return -EINVAL;
 
 	switch (cmd)
 	{
 		case FRAD_GET_CONF:
 		case FRAD_SET_CONF:
-			return(sdla_config(dev, ifr->ifr_data, cmd == FRAD_GET_CONF));
+			return sdla_config(dev, ifr->ifr_data, cmd == FRAD_GET_CONF);
 
 		case SDLA_IDENTIFY:
 			ifr->ifr_flags = flp->type;
 			break;
 
 		case SDLA_CPUSPEED:
-			return(sdla_cpuspeed(dev, ifr)); 
+			return sdla_cpuspeed(dev, ifr);
 
 /* ==========================================================
 NOTE:  This is rather a useless action right now, as the
@@ -1277,7 +1277,7 @@
 ============================================================*/
 		case SDLA_PROTOCOL:
 			if (flp->configured)
-				return(-EALREADY);
+				return -EALREADY;
 
 			switch (ifr->ifr_flags)
 			{
@@ -1285,7 +1285,7 @@
 					dev->type = ifr->ifr_flags;
 					break;
 				default:
-					return(-ENOPROTOOPT);
+					return -ENOPROTOOPT;
 			}
 			break;
 
@@ -1297,7 +1297,7 @@
 		case SDLA_READMEM:
 			if(!capable(CAP_SYS_RAWIO))
 				return -EPERM;
-			return(sdla_xfer(dev, ifr->ifr_data, cmd == SDLA_READMEM));
+			return sdla_xfer(dev, ifr->ifr_data, cmd == SDLA_READMEM);
 
 		case SDLA_START:
 			sdla_start(dev);
@@ -1308,9 +1308,9 @@
 			break;
 
 		default:
-			return(-EOPNOTSUPP);
+			return -EOPNOTSUPP;
 	}
-	return(0);
+	return 0;
 }
 
 static int sdla_change_mtu(struct net_device *dev, int new_mtu)
@@ -1320,10 +1320,10 @@
 	flp = netdev_priv(dev);
 
 	if (netif_running(dev))
-		return(-EBUSY);
+		return -EBUSY;
 
 	/* for now, you can't change the MTU! */
-	return(-EOPNOTSUPP);
+	return -EOPNOTSUPP;
 }
 
 static int sdla_set_config(struct net_device *dev, struct ifmap *map)
@@ -1337,18 +1337,18 @@
 	flp = netdev_priv(dev);
 
 	if (flp->initialized)
-		return(-EINVAL);
+		return -EINVAL;
 
 	for(i=0; i < ARRAY_SIZE(valid_port); i++)
 		if (valid_port[i] == map->base_addr)
 			break;   
 
 	if (i == ARRAY_SIZE(valid_port))
-		return(-EINVAL);
+		return -EINVAL;
 
 	if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
 		printk(KERN_WARNING "SDLA: io-port 0x%04lx in use\n", dev->base_addr);
-		return(-EINVAL);
+		return -EINVAL;
 	}
 	base = map->base_addr;
 
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index e47f5a9..d81ad83 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -648,7 +648,7 @@
 		}
 	}
 	*ptr++ = X25_END;
-	return (ptr - d);
+	return ptr - d;
 }
 
 static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index fbf5e84..9395686 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -766,7 +766,7 @@
 
 EXPORT_SYMBOL(z8530_interrupt);
 
-static char reg_init[16]=
+static const u8 reg_init[16]=
 {
 	0,0,0,0,
 	0,0,0,0,
@@ -1206,7 +1206,7 @@
  *	it exists...
  */
  
-static char *z8530_type_name[]={
+static const char *z8530_type_name[]={
 	"Z8530",
 	"Z85C30",
 	"Z85230"
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index eb72c67..f1549ff 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -342,10 +342,10 @@
 	printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
 		   model_name, dev->irq, dev->mem_start, dev->mem_end-1);
 
-	ei_status.reset_8390 = &wd_reset_8390;
-	ei_status.block_input = &wd_block_input;
-	ei_status.block_output = &wd_block_output;
-	ei_status.get_8390_hdr = &wd_get_8390_hdr;
+	ei_status.reset_8390 = wd_reset_8390;
+	ei_status.block_input = wd_block_input;
+	ei_status.block_output = wd_block_output;
+	ei_status.get_8390_hdr = wd_get_8390_hdr;
 
 	dev->netdev_ops = &wd_netdev_ops;
 	NS8390_init(dev, 0);
diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c
index 9fb0308..12b84ed 100644
--- a/drivers/net/wimax/i2400m/control.c
+++ b/drivers/net/wimax/i2400m/control.c
@@ -98,7 +98,7 @@
 		 "False by default (so the device is told to do power "
 		 "saving).");
 
-int i2400m_passive_mode;	/* 0 (passive mode disabled) by default */
+static int i2400m_passive_mode;	/* 0 (passive mode disabled) by default */
 module_param_named(passive_mode, i2400m_passive_mode, int, 0644);
 MODULE_PARM_DESC(passive_mode,
 		 "If true, the driver will not do any device setup "
@@ -558,8 +558,9 @@
  * processing should be done in the function that calls the
  * command. This is here for some cases where it can't happen...
  */
-void i2400m_msg_ack_hook(struct i2400m *i2400m,
-			 const struct i2400m_l3l4_hdr *l3l4_hdr, size_t size)
+static void i2400m_msg_ack_hook(struct i2400m *i2400m,
+				 const struct i2400m_l3l4_hdr *l3l4_hdr,
+				 size_t size)
 {
 	int result;
 	struct device *dev = i2400m_dev(i2400m);
@@ -1135,7 +1136,7 @@
  * i2400m_report_state_hook() to parse the answer. This will set the
  * carrier state, as well as the RF Kill switches state.
  */
-int i2400m_cmd_get_state(struct i2400m *i2400m)
+static int i2400m_cmd_get_state(struct i2400m *i2400m)
 {
 	int result;
 	struct device *dev = i2400m_dev(i2400m);
@@ -1177,8 +1178,6 @@
 error_alloc:
 	return result;
 }
-EXPORT_SYMBOL_GPL(i2400m_cmd_get_state);
-
 
 /**
  * Set basic configuration settings
@@ -1190,8 +1189,9 @@
  *     right endianess (LE).
  * @arg_size: number of pointers in the @args array
  */
-int i2400m_set_init_config(struct i2400m *i2400m,
-			   const struct i2400m_tlv_hdr **arg, size_t args)
+static int i2400m_set_init_config(struct i2400m *i2400m,
+				  const struct i2400m_tlv_hdr **arg,
+				  size_t args)
 {
 	int result;
 	struct device *dev = i2400m_dev(i2400m);
@@ -1258,8 +1258,6 @@
 	return result;
 
 }
-EXPORT_SYMBOL_GPL(i2400m_set_init_config);
-
 
 /**
  * i2400m_set_idle_timeout - Set the device's idle mode timeout
diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c
index b1aec3e..9c70b5f 100644
--- a/drivers/net/wimax/i2400m/debugfs.c
+++ b/drivers/net/wimax/i2400m/debugfs.c
@@ -119,6 +119,7 @@
 	.open =		i2400m_stats_open,
 	.read =		i2400m_rx_stats_read,
 	.write =	i2400m_rx_stats_write,
+	.llseek =	default_llseek,
 };
 
 
@@ -171,6 +172,7 @@
 	.open =		i2400m_stats_open,
 	.read =		i2400m_tx_stats_read,
 	.write =	i2400m_tx_stats_write,
+	.llseek =	default_llseek,
 };
 
 
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c
index 9c8b78d..cdedab4 100644
--- a/drivers/net/wimax/i2400m/driver.c
+++ b/drivers/net/wimax/i2400m/driver.c
@@ -122,7 +122,7 @@
  * works struct was already queued, but we have just allocated it, so
  * it should not happen.
  */
-int i2400m_schedule_work(struct i2400m *i2400m,
+static int i2400m_schedule_work(struct i2400m *i2400m,
 			 void (*fn)(struct work_struct *), gfp_t gfp_flags,
 			 const void *pl, size_t pl_size)
 {
diff --git a/drivers/net/wimax/i2400m/i2400m-sdio.h b/drivers/net/wimax/i2400m/i2400m-sdio.h
index 360d4fb..1d63ffd 100644
--- a/drivers/net/wimax/i2400m/i2400m-sdio.h
+++ b/drivers/net/wimax/i2400m/i2400m-sdio.h
@@ -140,7 +140,6 @@
 
 extern int i2400ms_rx_setup(struct i2400ms *);
 extern void i2400ms_rx_release(struct i2400ms *);
-extern ssize_t __i2400ms_rx_get_size(struct i2400ms *);
 
 extern int i2400ms_tx_setup(struct i2400ms *);
 extern void i2400ms_tx_release(struct i2400ms *);
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index fa74777..59ac770 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -910,28 +910,19 @@
 	u8 pl[0];
 };
 
-extern int i2400m_schedule_work(struct i2400m *,
-				void (*)(struct work_struct *), gfp_t,
-				const void *, size_t);
-
 extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *,
 				   char *, size_t);
 extern int i2400m_msg_size_check(struct i2400m *,
 				 const struct i2400m_l3l4_hdr *, size_t);
 extern struct sk_buff *i2400m_msg_to_dev(struct i2400m *, const void *, size_t);
 extern void i2400m_msg_to_dev_cancel_wait(struct i2400m *, int);
-extern void i2400m_msg_ack_hook(struct i2400m *,
-				const struct i2400m_l3l4_hdr *, size_t);
 extern void i2400m_report_hook(struct i2400m *,
 			       const struct i2400m_l3l4_hdr *, size_t);
 extern void i2400m_report_hook_work(struct work_struct *);
 extern int i2400m_cmd_enter_powersave(struct i2400m *);
-extern int i2400m_cmd_get_state(struct i2400m *);
 extern int i2400m_cmd_exit_idle(struct i2400m *);
 extern struct sk_buff *i2400m_get_device_info(struct i2400m *);
 extern int i2400m_firmware_check(struct i2400m *);
-extern int i2400m_set_init_config(struct i2400m *,
-				  const struct i2400m_tlv_hdr **, size_t);
 extern int i2400m_set_idle_timeout(struct i2400m *, unsigned);
 
 static inline
diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c
index 8cc9e31..844133b 100644
--- a/drivers/net/wimax/i2400m/rx.c
+++ b/drivers/net/wimax/i2400m/rx.c
@@ -922,7 +922,7 @@
  * rx_roq_refcount becomes zero. This routine gets executed when
  * rx_roq_refcount becomes zero.
  */
-void i2400m_rx_roq_destroy(struct kref *ref)
+static void i2400m_rx_roq_destroy(struct kref *ref)
 {
 	unsigned itr;
 	struct i2400m *i2400m
@@ -1244,16 +1244,16 @@
 	int i, result;
 	struct device *dev = i2400m_dev(i2400m);
 	const struct i2400m_msg_hdr *msg_hdr;
-	size_t pl_itr, pl_size, skb_len;
+	size_t pl_itr, pl_size;
 	unsigned long flags;
-	unsigned num_pls, single_last;
+	unsigned num_pls, single_last, skb_len;
 
 	skb_len = skb->len;
-	d_fnstart(4, dev, "(i2400m %p skb %p [size %zu])\n",
+	d_fnstart(4, dev, "(i2400m %p skb %p [size %u])\n",
 		  i2400m, skb, skb_len);
 	result = -EIO;
 	msg_hdr = (void *) skb->data;
-	result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb->len);
+	result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb_len);
 	if (result < 0)
 		goto error_msg_hdr_check;
 	result = -EIO;
@@ -1261,10 +1261,10 @@
 	pl_itr = sizeof(*msg_hdr) +	/* Check payload descriptor(s) */
 		num_pls * sizeof(msg_hdr->pld[0]);
 	pl_itr = ALIGN(pl_itr, I2400M_PL_ALIGN);
-	if (pl_itr > skb->len) {	/* got all the payload descriptors? */
+	if (pl_itr > skb_len) {	/* got all the payload descriptors? */
 		dev_err(dev, "RX: HW BUG? message too short (%u bytes) for "
 			"%u payload descriptors (%zu each, total %zu)\n",
-			skb->len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr);
+			skb_len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr);
 		goto error_pl_descr_short;
 	}
 	/* Walk each payload payload--check we really got it */
@@ -1272,7 +1272,7 @@
 		/* work around old gcc warnings */
 		pl_size = i2400m_pld_size(&msg_hdr->pld[i]);
 		result = i2400m_rx_pl_descr_check(i2400m, &msg_hdr->pld[i],
-						  pl_itr, skb->len);
+						  pl_itr, skb_len);
 		if (result < 0)
 			goto error_pl_descr_check;
 		single_last = num_pls == 1 || i == num_pls - 1;
@@ -1290,16 +1290,16 @@
 	if (i < i2400m->rx_pl_min)
 		i2400m->rx_pl_min = i;
 	i2400m->rx_num++;
-	i2400m->rx_size_acc += skb->len;
-	if (skb->len < i2400m->rx_size_min)
-		i2400m->rx_size_min = skb->len;
-	if (skb->len > i2400m->rx_size_max)
-		i2400m->rx_size_max = skb->len;
+	i2400m->rx_size_acc += skb_len;
+	if (skb_len < i2400m->rx_size_min)
+		i2400m->rx_size_min = skb_len;
+	if (skb_len > i2400m->rx_size_max)
+		i2400m->rx_size_max = skb_len;
 	spin_unlock_irqrestore(&i2400m->rx_lock, flags);
 error_pl_descr_check:
 error_pl_descr_short:
 error_msg_hdr_check:
-	d_fnend(4, dev, "(i2400m %p skb %p [size %zu]) = %d\n",
+	d_fnend(4, dev, "(i2400m %p skb %p [size %u]) = %d\n",
 		i2400m, skb, skb_len, result);
 	return result;
 }
diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c
index 8b809c2..fb6396d 100644
--- a/drivers/net/wimax/i2400m/sdio-rx.c
+++ b/drivers/net/wimax/i2400m/sdio-rx.c
@@ -87,7 +87,7 @@
  *
  * sdio_readl() doesn't work.
  */
-ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms)
+static ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms)
 {
 	int ret, cnt, val;
 	ssize_t rx_size;
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 174e344..4de4410 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -279,6 +279,7 @@
 source "drivers/net/wireless/orinoco/Kconfig"
 source "drivers/net/wireless/p54/Kconfig"
 source "drivers/net/wireless/rt2x00/Kconfig"
+source "drivers/net/wireless/wl1251/Kconfig"
 source "drivers/net/wireless/wl12xx/Kconfig"
 source "drivers/net/wireless/zd1211rw/Kconfig"
 
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 5d4ce4d..06f8ca2 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -49,6 +49,8 @@
 
 obj-$(CONFIG_MAC80211_HWSIM)	+= mac80211_hwsim.o
 
+obj-$(CONFIG_WL1251)	+= wl1251/
 obj-$(CONFIG_WL12XX)	+= wl12xx/
+obj-$(CONFIG_WL12XX_PLATFORM_DATA)	+= wl12xx/
 
 obj-$(CONFIG_IWM)	+= iwmc3200wifi/
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 1d05445..a36e787 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -105,7 +105,7 @@
    of statistics in the /proc filesystem */
 
 #define IGNLABEL(comment) NULL
-static char *statsLabels[] = {
+static const char *statsLabels[] = {
 	"RxOverrun",
 	IGNLABEL("RxPlcpCrcErr"),
 	IGNLABEL("RxPlcpFormatErr"),
@@ -217,7 +217,6 @@
    (no spaces) list of rates (up to 8). */
 
 static int rates[8];
-static int basic_rate;
 static char *ssids[3];
 
 static int io[4];
@@ -250,7 +249,6 @@
 MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350");
 module_param_array(io, int, NULL, 0);
 module_param_array(irq, int, NULL, 0);
-module_param(basic_rate, int, 0);
 module_param_array(rates, int, NULL, 0);
 module_param_array(ssids, charp, NULL, 0);
 module_param(auto_wep, int, 0);
@@ -932,7 +930,7 @@
 	unsigned char __user *data;	// d-data
 } aironet_ioctl;
 
-static char swversion[] = "2.1";
+static const char swversion[] = "2.1";
 #endif /* CISCO_EXT */
 
 #define NUM_MODULES       2
@@ -1374,7 +1372,7 @@
 	return SUCCESS;
 }
 
-static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
+static const u8 micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
 
 /*===========================================================================
  * Description: Mic a packet
@@ -2723,9 +2721,8 @@
 	if (ai->networks)
 		return 0;
 
-	ai->networks =
-	    kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement),
-		    GFP_KERNEL);
+	ai->networks = kcalloc(AIRO_MAX_NETWORK_COUNT, sizeof(BSSListElement),
+			       GFP_KERNEL);
 	if (!ai->networks) {
 		airo_print_warn("", "Out of memory allocating beacons");
 		return -ENOMEM;
@@ -3884,15 +3881,6 @@
 				ai->config.rates[i] = rates[i];
 			}
 		}
-		if ( basic_rate > 0 ) {
-			for( i = 0; i < 8; i++ ) {
-				if ( ai->config.rates[i] == basic_rate ||
-				     !ai->config.rates ) {
-					ai->config.rates[i] = basic_rate | 0x80;
-					break;
-				}
-			}
-		}
 		set_bit (FLAG_COMMIT, &ai->flags);
 	}
 
@@ -4430,21 +4418,24 @@
 	.owner		= THIS_MODULE,
 	.read		= proc_read,
 	.open		= proc_statsdelta_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_stats_ops = {
 	.owner		= THIS_MODULE,
 	.read		= proc_read,
 	.open		= proc_stats_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_status_ops = {
 	.owner		= THIS_MODULE,
 	.read		= proc_read,
 	.open		= proc_status_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_SSID_ops = {
@@ -4452,7 +4443,8 @@
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_SSID_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_BSSList_ops = {
@@ -4460,7 +4452,8 @@
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_BSSList_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_APList_ops = {
@@ -4468,7 +4461,8 @@
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_APList_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_config_ops = {
@@ -4476,7 +4470,8 @@
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_config_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_wepkey_ops = {
@@ -4484,7 +4479,8 @@
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_wepkey_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static struct proc_dir_entry *airo_entry;
@@ -5024,7 +5020,7 @@
 	airo_config_commit(dev, NULL, NULL, NULL);
 }
 
-static char *get_rmode(__le16 mode)
+static const char *get_rmode(__le16 mode)
 {
         switch(mode & RXMODE_MASK) {
         case RXMODE_RFMON:  return "rfmon";
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 9a121a5..df2484d 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -32,7 +32,6 @@
 #include <linux/timer.h>
 #include <linux/netdevice.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -54,58 +53,21 @@
 
 /*====================================================================*/
 
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card
-   insertion and ejection events.  They are invoked from the airo_cs
-   event handler.
-*/
-
 static int airo_config(struct pcmcia_device *link);
 static void airo_release(struct pcmcia_device *link);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void airo_detach(struct pcmcia_device *p_dev);
 
 typedef struct local_info_t {
 	struct net_device *eth_dev;
 } local_info_t;
 
-/*======================================================================
-
-  airo_attach() creates an "instance" of the driver, allocating
-  local data structures for one device.  The device is registered
-  with Card Services.
-
-  The dev_link 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 airo_probe(struct pcmcia_device *p_dev)
 {
 	local_info_t *local;
 
 	dev_dbg(&p_dev->dev, "airo_attach()\n");
 
-	/*
-	  General socket configuration defaults can go here.  In this
-	  client, we assume very little, and rely on the CIS for almost
-	  everything.  In most clients, many details (i.e., number, sizes,
-	  and attributes of IO windows) are fixed by the nature of the
-	  device, and can be hard-wired here.
-	*/
-	p_dev->conf.Attributes = 0;
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
-
 	/* Allocate space for private device-specific data */
 	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
 	if (!local) {
@@ -117,15 +79,6 @@
 	return airo_config(p_dev);
 } /* airo_attach */
 
-/*======================================================================
-
-  This deletes a driver "instance".  The device is de-registered
-  with Card Services.  If it has been released, all local data
-  structures are freed.  Otherwise, the structures will be freed
-  when the device is released.
-
-  ======================================================================*/
-
 static void airo_detach(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "airo_detach\n");
@@ -140,60 +93,12 @@
 	kfree(link->priv);
 } /* airo_detach */
 
-/*======================================================================
-
-  airo_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.
-
-  ======================================================================*/
-
-static int airo_cs_config_check(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
-				void *priv_data)
+static int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-		p_dev->conf.Status = CCSR_AUDIO_ENA;
-	}
-
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-					pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-	}
-
-	/* This reserves IO space but doesn't actually enable it */
-	if (pcmcia_request_io(p_dev) != 0)
-		return -ENODEV;
-
-	/* If we got this far, we're cool! */
-	return 0;
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -206,20 +111,9 @@
 
 	dev_dbg(&link->dev, "airo_config\n");
 
-	/*
-	 * 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.
-	 */
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+		CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
+
 	ret = pcmcia_loop_config(link, airo_cs_config_check, NULL);
 	if (ret)
 		goto failed;
@@ -227,12 +121,7 @@
 	if (!link->irq)
 		goto failed;
 
-	/*
-	  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.
-	*/
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 	((local_info_t *)link->priv)->eth_dev =
@@ -241,17 +130,6 @@
 	if (!((local_info_t *)link->priv)->eth_dev)
 		goto failed;
 
-	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x: ",
-	       link->conf.ConfigIndex);
-	if (link->conf.Vpp)
-		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
-	printk(", irq %d", link->irq);
-	if (link->resource[0])
-		printk(" & %pR", link->resource[0]);
-	if (link->resource[1])
-		printk(" & %pR", link->resource[1]);
-	printk("\n");
 	return 0;
 
  failed:
@@ -259,14 +137,6 @@
 	return -ENODEV;
 } /* airo_config */
 
-/*======================================================================
-
-  After a card is removed, airo_release() will unregister the
-  device, and release the PCMCIA configuration.  If the device is
-  still open, this will be postponed until it is closed.
-
-  ======================================================================*/
-
 static void airo_release(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "airo_release\n");
@@ -305,9 +175,7 @@
 
 static struct pcmcia_driver airo_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "airo_cs",
-	},
+	.name		= "airo_cs",
 	.probe		= airo_probe,
 	.remove		= airo_detach,
 	.id_table       = airo_ids,
@@ -315,12 +183,12 @@
 	.resume		= airo_resume,
 };
 
-static int airo_cs_init(void)
+static int __init airo_cs_init(void)
 {
 	return pcmcia_register_driver(&airo_driver);
 }
 
-static void airo_cs_cleanup(void)
+static void __exit airo_cs_cleanup(void)
 {
 	pcmcia_unregister_driver(&airo_driver);
 }
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 1128fa8..1476314 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1525,8 +1525,7 @@
 
 	if (priv->device_unplugged) {
 		at76_dbg(DBG_DEVSTART, "device unplugged");
-		if (urb)
-			at76_dbg(DBG_DEVSTART, "urb status %d", urb->status);
+		at76_dbg(DBG_DEVSTART, "urb status %d", urb->status);
 		return;
 	}
 
@@ -2061,11 +2060,12 @@
 
 	int i;
 
-	at76_dbg(DBG_MAC80211, "%s(): cmd %d key->alg %d key->keyidx %d "
+	at76_dbg(DBG_MAC80211, "%s(): cmd %d key->cipher %d key->keyidx %d "
 		 "key->keylen %d",
-		 __func__, cmd, key->alg, key->keyidx, key->keylen);
+		 __func__, cmd, key->cipher, key->keyidx, key->keylen);
 
-	if (key->alg != ALG_WEP)
+	if ((key->cipher != WLAN_CIPHER_SUITE_WEP40) &&
+	    (key->cipher != WLAN_CIPHER_SUITE_WEP104))
 		return -EOPNOTSUPP;
 
 	key->hw_key_idx = key->keyidx;
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 0a75be0..92c2162 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -25,5 +25,6 @@
 source "drivers/net/wireless/ath/ath5k/Kconfig"
 source "drivers/net/wireless/ath/ath9k/Kconfig"
 source "drivers/net/wireless/ath/ar9170/Kconfig"
+source "drivers/net/wireless/ath/carl9170/Kconfig"
 
 endif
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
index 8113a50..6d711ec 100644
--- a/drivers/net/wireless/ath/Makefile
+++ b/drivers/net/wireless/ath/Makefile
@@ -1,11 +1,13 @@
 obj-$(CONFIG_ATH5K)		+= ath5k/
 obj-$(CONFIG_ATH9K_HW)		+= ath9k/
 obj-$(CONFIG_AR9170_USB)        += ar9170/
+obj-$(CONFIG_CARL9170)		+= carl9170/
 
 obj-$(CONFIG_ATH_COMMON)	+= ath.o
 
 ath-objs :=	main.o \
 		regd.o \
-		hw.o
+		hw.o \
+		key.o
 
 ath-$(CONFIG_ATH_DEBUG) += debug.o
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index debfb0f..32bf79e 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -1190,14 +1190,13 @@
 	if (info->control.hw_key) {
 		icv = info->control.hw_key->icv_len;
 
-		switch (info->control.hw_key->alg) {
-		case ALG_WEP:
+		switch (info->control.hw_key->cipher) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+		case WLAN_CIPHER_SUITE_TKIP:
 			keytype = AR9170_TX_MAC_ENCR_RC4;
 			break;
-		case ALG_TKIP:
-			keytype = AR9170_TX_MAC_ENCR_RC4;
-			break;
-		case ALG_CCMP:
+		case WLAN_CIPHER_SUITE_CCMP:
 			keytype = AR9170_TX_MAC_ENCR_AES;
 			break;
 		default:
@@ -1778,17 +1777,17 @@
 	if ((!ar->vif) || (ar->disable_offload))
 		return -EOPNOTSUPP;
 
-	switch (key->alg) {
-	case ALG_WEP:
-		if (key->keylen == WLAN_KEY_LEN_WEP40)
-			ktype = AR9170_ENC_ALG_WEP64;
-		else
-			ktype = AR9170_ENC_ALG_WEP128;
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+		ktype = AR9170_ENC_ALG_WEP64;
 		break;
-	case ALG_TKIP:
+	case WLAN_CIPHER_SUITE_WEP104:
+		ktype = AR9170_ENC_ALG_WEP128;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
 		ktype = AR9170_ENC_ALG_TKIP;
 		break;
-	case ALG_CCMP:
+	case WLAN_CIPHER_SUITE_CCMP:
 		ktype = AR9170_ENC_ALG_AESCCMP;
 		break;
 	default:
@@ -1827,7 +1826,7 @@
 		if (err)
 			goto out;
 
-		if (key->alg == ALG_TKIP) {
+		if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
 			err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL,
 						ktype, 1, key->key + 16, 16);
 			if (err)
@@ -1864,7 +1863,7 @@
 			if (err)
 				goto out;
 
-			if (key->alg == ALG_TKIP) {
+			if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
 				err = ar9170_upload_key(ar, key->hw_key_idx,
 							NULL,
 							AR9170_ENC_ALG_NONE, 1,
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index a93dc18..5dbb536 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -54,8 +54,6 @@
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless");
 MODULE_FIRMWARE("ar9170.fw");
-MODULE_FIRMWARE("ar9170-1.fw");
-MODULE_FIRMWARE("ar9170-2.fw");
 
 enum ar9170_requirements {
 	AR9170_REQ_FW1_ONLY = 1,
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index d32f282..501050c 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -19,6 +19,7 @@
 
 #include <linux/skbuff.h>
 #include <linux/if_ether.h>
+#include <linux/spinlock.h>
 #include <net/mac80211.h>
 
 /*
@@ -35,7 +36,6 @@
 
 struct ath_ani {
 	bool caldone;
-	int16_t noise_floor;
 	unsigned int longcal_timer;
 	unsigned int shortcal_timer;
 	unsigned int resetcal_timer;
@@ -43,6 +43,13 @@
 	struct timer_list timer;
 };
 
+struct ath_cycle_counters {
+	u32 cycles;
+	u32 rx_busy;
+	u32 rx_frame;
+	u32 tx_frame;
+};
+
 enum ath_device_state {
 	ATH_HW_UNAVAILABLE,
 	ATH_HW_INITIALIZED,
@@ -71,20 +78,44 @@
 	struct reg_dmn_pair_mapping *regpair;
 };
 
+enum ath_crypt_caps {
+	ATH_CRYPT_CAP_CIPHER_AESCCM		= BIT(0),
+	ATH_CRYPT_CAP_MIC_COMBINED		= BIT(1),
+};
+
+struct ath_keyval {
+	u8 kv_type;
+	u8 kv_pad;
+	u16 kv_len;
+	u8 kv_val[16]; /* TK */
+	u8 kv_mic[8]; /* Michael MIC key */
+	u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
+			 * supports both MIC keys in the same key cache entry;
+			 * in that case, kv_mic is the RX key) */
+};
+
+enum ath_cipher {
+	ATH_CIPHER_WEP = 0,
+	ATH_CIPHER_AES_OCB = 1,
+	ATH_CIPHER_AES_CCM = 2,
+	ATH_CIPHER_CKIP = 3,
+	ATH_CIPHER_TKIP = 4,
+	ATH_CIPHER_CLR = 5,
+	ATH_CIPHER_MIC = 127
+};
+
 /**
  * struct ath_ops - Register read/write operations
  *
  * @read: Register read
  * @write: Register write
  * @enable_write_buffer: Enable multiple register writes
- * @disable_write_buffer: Disable multiple register writes
- * @write_flush: Flush buffered register writes
+ * @write_flush: flush buffered register writes and disable buffering
  */
 struct ath_ops {
 	unsigned int (*read)(void *, u32 reg_offset);
 	void (*write)(void *, u32 val, u32 reg_offset);
 	void (*enable_write_buffer)(void *);
-	void (*disable_write_buffer)(void *);
 	void (*write_flush) (void *);
 };
 
@@ -119,7 +150,14 @@
 
 	u32 keymax;
 	DECLARE_BITMAP(keymap, ATH_KEYMAX);
-	u8 splitmic;
+	DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX);
+	enum ath_crypt_caps crypt_caps;
+
+	unsigned int clockrate;
+
+	spinlock_t cc_lock;
+	struct ath_cycle_counters cc_ani;
+	struct ath_cycle_counters cc_survey;
 
 	struct ath_regulatory regulatory;
 	const struct ath_ops *ops;
@@ -131,5 +169,13 @@
 				gfp_t gfp_mask);
 
 void ath_hw_setbssidmask(struct ath_common *common);
+void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key);
+int ath_key_config(struct ath_common *common,
+			  struct ieee80211_vif *vif,
+			  struct ieee80211_sta *sta,
+			  struct ieee80211_key_conf *key);
+bool ath_hw_keyreset(struct ath_common *common, u16 entry);
+void ath_hw_cycle_counters_update(struct ath_common *common);
+int32_t ath_hw_get_listen_time(struct ath_common *common);
 
 #endif /* ATH_H */
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c
index 26dbe65..f141919 100644
--- a/drivers/net/wireless/ath/ath5k/ani.c
+++ b/drivers/net/wireless/ath/ath5k/ani.c
@@ -355,41 +355,28 @@
 
 
 /**
- * ath5k_hw_ani_get_listen_time() - Calculate time spent listening
+ * ath5k_hw_ani_get_listen_time() - Update counters and return listening time
  *
  * Return an approximation of the time spent "listening" in milliseconds (ms)
- * since the last call of this function by deducting the cycles spent
- * transmitting and receiving from the total cycle count.
- * Save profile count values for debugging/statistics and because we might want
- * to use them later.
- *
- * We assume no one else clears these registers!
+ * since the last call of this function.
+ * Save a snapshot of the counter values for debugging/statistics.
  */
 static int
 ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as)
 {
+	struct ath_common *common = ath5k_hw_common(ah);
 	int listen;
 
-	/* freeze */
-	ath5k_hw_reg_write(ah, AR5K_MIBC_FMC, AR5K_MIBC);
-	/* read */
-	as->pfc_cycles = ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE);
-	as->pfc_busy = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR);
-	as->pfc_tx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX);
-	as->pfc_rx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX);
-	/* clear */
-	ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
-	ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
-	ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
-	ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
-	/* un-freeze */
-	ath5k_hw_reg_write(ah, 0, AR5K_MIBC);
+	spin_lock_bh(&common->cc_lock);
 
-	/* TODO: where does 44000 come from? (11g clock rate?) */
-	listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000;
+	ath_hw_cycle_counters_update(common);
+	memcpy(&as->last_cc, &common->cc_ani, sizeof(as->last_cc));
 
-	if (as->pfc_cycles == 0 || listen < 0)
-		return 0;
+	/* clears common->cc_ani */
+	listen = ath_hw_get_listen_time(common);
+
+	spin_unlock_bh(&common->cc_lock);
+
 	return listen;
 }
 
@@ -552,9 +539,9 @@
 	if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO)
 		return;
 
-	/* if one of the errors triggered, we can get a superfluous second
-	 * interrupt, even though we have already reset the register. the
-	 * function detects that so we can return early */
+	/* If one of the errors triggered, we can get a superfluous second
+	 * interrupt, even though we have already reset the register. The
+	 * function detects that so we can return early. */
 	if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0)
 		return;
 
diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h
index 55cf26d..d0a6640 100644
--- a/drivers/net/wireless/ath/ath5k/ani.h
+++ b/drivers/net/wireless/ath/ath5k/ani.h
@@ -75,10 +75,7 @@
 	unsigned int		cck_errors;
 
 	/* debug/statistics only: numbers from last ANI calibration */
-	unsigned int		pfc_tx;
-	unsigned int		pfc_rx;
-	unsigned int		pfc_busy;
-	unsigned int		pfc_cycles;
+	struct ath_cycle_counters last_cc;
 	unsigned int		last_listen;
 	unsigned int		last_ofdm_errors;
 	unsigned int		last_cck_errors;
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index ea6362a..4a367cd 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -175,7 +175,7 @@
 #define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF	0
 #define AR5K_TUNE_RADAR_ALERT			false
 #define AR5K_TUNE_MIN_TX_FIFO_THRES		1
-#define AR5K_TUNE_MAX_TX_FIFO_THRES		((IEEE80211_MAX_LEN / 64) + 1)
+#define AR5K_TUNE_MAX_TX_FIFO_THRES	((IEEE80211_MAX_FRAME_LEN / 64) + 1)
 #define AR5K_TUNE_REGISTER_TIMEOUT		20000
 /* Register for RSSI threshold has a mask of 0xff, so 255 seems to
  * be the max value. */
@@ -206,6 +206,8 @@
 #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI	1000	/* 1 sec */
 #define ATH5K_TUNE_CALIBRATION_INTERVAL_NF	60000	/* 60 sec */
 
+#define ATH5K_TX_COMPLETE_POLL_INT		3000	/* 3 sec */
+
 #define AR5K_INIT_CARR_SENSE_EN			1
 
 /*Swap RX/TX Descriptor for big endian archs*/
@@ -256,8 +258,6 @@
 	(AR5K_INIT_PROG_IFS_TURBO)					\
 )
 
-/* token to use for aifs, cwmin, cwmax in MadWiFi */
-#define	AR5K_TXQ_USEDEFAULT	((u32) -1)
 
 /* GENERIC CHIPSET DEFINITIONS */
 
@@ -343,9 +343,6 @@
 #define AR5K_SREV_PHY_5413	0x61
 #define AR5K_SREV_PHY_2425	0x70
 
-/* IEEE defs */
-#define IEEE80211_MAX_LEN       2500
-
 /* TODO add support to mac80211 for vendor-specific rates and modes */
 
 /*
@@ -531,9 +528,9 @@
 	enum ath5k_tx_queue tqi_type;
 	enum ath5k_tx_queue_subtype tqi_subtype;
 	u16	tqi_flags;	/* Tx queue flags (see above) */
-	u32	tqi_aifs;	/* Arbitrated Interframe Space */
-	s32	tqi_cw_min;	/* Minimum Contention Window */
-	s32	tqi_cw_max;	/* Maximum Contention Window */
+	u8	tqi_aifs;	/* Arbitrated Interframe Space */
+	u16	tqi_cw_min;	/* Minimum Contention Window */
+	u16	tqi_cw_max;	/* Maximum Contention Window */
 	u32	tqi_cbr_period; /* Constant bit rate period */
 	u32	tqi_cbr_overflow_limit;
 	u32	tqi_burst_time;
@@ -1031,8 +1028,6 @@
 	bool			ah_turbo;
 	bool			ah_calibration;
 	bool			ah_single_chip;
-	bool			ah_aes_support;
-	bool			ah_combined_mic;
 
 	enum ath5k_version	ah_version;
 	enum ath5k_radio	ah_radio;
@@ -1046,10 +1041,6 @@
 #define ah_modes		ah_capabilities.cap_mode
 #define ah_ee_version		ah_capabilities.cap_eeprom.ee_version
 
-	u32			ah_atim_window;
-	u32			ah_aifs;
-	u32			ah_cw_min;
-	u32			ah_cw_max;
 	u32			ah_limit_tx_retries;
 	u8			ah_coverage_class;
 
@@ -1190,7 +1181,7 @@
 void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
 /* BSSID Functions */
 int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
-void ath5k_hw_set_associd(struct ath5k_hw *ah);
+void ath5k_hw_set_bssid(struct ath5k_hw *ah);
 void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
 /* Receive start/stop functions */
 void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
@@ -1204,17 +1195,13 @@
 void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
 void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
 void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
+bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval);
 /* ACK bit rate */
 void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
 /* Clock rate related functions */
 unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
 unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
-unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah);
-/* Key table (WEP) functions */
-int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
-int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
-		     const struct ieee80211_key_conf *key, const u8 *mac);
-int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac);
+void ath5k_hw_set_clockrate(struct ath5k_hw *ah);
 
 /* Queue Control Unit, DFS Control Unit Functions */
 int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index b32e28c..cd0b14a 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -118,9 +118,6 @@
 	ah->ah_turbo = false;
 	ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
 	ah->ah_imr = 0;
-	ah->ah_atim_window = 0;
-	ah->ah_aifs = AR5K_TUNE_AIFS;
-	ah->ah_cw_min = AR5K_TUNE_CWMIN;
 	ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
 	ah->ah_software_retry = false;
 	ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
@@ -139,12 +136,12 @@
 	else
 		ah->ah_version = AR5K_AR5212;
 
-	/*Fill the ath5k_hw struct with the needed functions*/
+	/* Fill the ath5k_hw struct with the needed functions */
 	ret = ath5k_hw_init_desc_functions(ah);
 	if (ret)
 		goto err_free;
 
-	/* Bring device out of sleep and reset it's units */
+	/* Bring device out of sleep and reset its units */
 	ret = ath5k_hw_nic_wakeup(ah, 0, true);
 	if (ret)
 		goto err_free;
@@ -158,7 +155,7 @@
 			CHANNEL_5GHZ);
 	ah->ah_phy = AR5K_PHY(0);
 
-	/* Try to identify radio chip based on it's srev */
+	/* Try to identify radio chip based on its srev */
 	switch (ah->ah_radio_5ghz_revision & 0xf0) {
 	case AR5K_SREV_RAD_5111:
 		ah->ah_radio = AR5K_RF5111;
@@ -314,12 +311,16 @@
 	}
 
 	/* Crypto settings */
-	ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 &&
-		(ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
-		 !AR5K_EEPROM_AES_DIS(ee->ee_misc5));
+	common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
+			  AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
+
+	if (srev >= AR5K_SREV_AR5212_V4 &&
+	    (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
+	    !AR5K_EEPROM_AES_DIS(ee->ee_misc5)))
+		common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
 
 	if (srev >= AR5K_SREV_AR2414) {
-		ah->ah_combined_mic = true;
+		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
 		AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE,
 			AR5K_MISC_MODE_COMBINED_MIC);
 	}
@@ -329,7 +330,7 @@
 
 	/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
 	memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN);
-	ath5k_hw_set_associd(ah);
+	ath5k_hw_set_bssid(ah);
 	ath5k_hw_set_opmode(ah, sc->opmode);
 
 	ath5k_hw_rfgain_opt_init(ah);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index d77ce99..f1ae75d 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -52,6 +52,7 @@
 #include <linux/ethtool.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/etherdevice.h>
 
 #include <net/ieee80211_radiotap.h>
 
@@ -61,6 +62,7 @@
 #include "reg.h"
 #include "debug.h"
 #include "ani.h"
+#include "../debug.h"
 
 static int modparam_nohwcrypt;
 module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
@@ -70,11 +72,6 @@
 module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO);
 MODULE_PARM_DESC(all_channels, "Expose all channels the device can use.");
 
-
-/******************\
-* Internal defines *
-\******************/
-
 /* Module info */
 MODULE_AUTHOR("Jiri Slaby");
 MODULE_AUTHOR("Nick Kossifidis");
@@ -83,6 +80,10 @@
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION("0.6.0 (EXPERIMENTAL)");
 
+static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
+static int ath5k_beacon_update(struct ieee80211_hw *hw,
+		struct ieee80211_vif *vif);
+static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
 
 /* Known PCI ids */
 static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {
@@ -190,129 +191,6 @@
 	/* XR missing */
 };
 
-/*
- * Prototypes - PCI stack related functions
- */
-static int __devinit	ath5k_pci_probe(struct pci_dev *pdev,
-				const struct pci_device_id *id);
-static void __devexit	ath5k_pci_remove(struct pci_dev *pdev);
-#ifdef CONFIG_PM_SLEEP
-static int		ath5k_pci_suspend(struct device *dev);
-static int		ath5k_pci_resume(struct device *dev);
-
-static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
-#define ATH5K_PM_OPS	(&ath5k_pm_ops)
-#else
-#define ATH5K_PM_OPS	NULL
-#endif /* CONFIG_PM_SLEEP */
-
-static struct pci_driver ath5k_pci_driver = {
-	.name		= KBUILD_MODNAME,
-	.id_table	= ath5k_pci_id_table,
-	.probe		= ath5k_pci_probe,
-	.remove		= __devexit_p(ath5k_pci_remove),
-	.driver.pm	= ATH5K_PM_OPS,
-};
-
-
-
-/*
- * Prototypes - MAC 802.11 stack related functions
- */
-static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
-static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
-		struct ath5k_txq *txq);
-static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-static int ath5k_start(struct ieee80211_hw *hw);
-static void ath5k_stop(struct ieee80211_hw *hw);
-static int ath5k_add_interface(struct ieee80211_hw *hw,
-		struct ieee80211_vif *vif);
-static void ath5k_remove_interface(struct ieee80211_hw *hw,
-		struct ieee80211_vif *vif);
-static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
-static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
-				   struct netdev_hw_addr_list *mc_list);
-static void ath5k_configure_filter(struct ieee80211_hw *hw,
-		unsigned int changed_flags,
-		unsigned int *new_flags,
-		u64 multicast);
-static int ath5k_set_key(struct ieee80211_hw *hw,
-		enum set_key_cmd cmd,
-		struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-		struct ieee80211_key_conf *key);
-static int ath5k_get_stats(struct ieee80211_hw *hw,
-		struct ieee80211_low_level_stats *stats);
-static int ath5k_get_survey(struct ieee80211_hw *hw,
-		int idx, struct survey_info *survey);
-static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
-static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
-static void ath5k_reset_tsf(struct ieee80211_hw *hw);
-static int ath5k_beacon_update(struct ieee80211_hw *hw,
-		struct ieee80211_vif *vif);
-static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
-		struct ieee80211_vif *vif,
-		struct ieee80211_bss_conf *bss_conf,
-		u32 changes);
-static void ath5k_sw_scan_start(struct ieee80211_hw *hw);
-static void ath5k_sw_scan_complete(struct ieee80211_hw *hw);
-static void ath5k_set_coverage_class(struct ieee80211_hw *hw,
-		u8 coverage_class);
-
-static const struct ieee80211_ops ath5k_hw_ops = {
-	.tx 		= ath5k_tx,
-	.start 		= ath5k_start,
-	.stop 		= ath5k_stop,
-	.add_interface 	= ath5k_add_interface,
-	.remove_interface = ath5k_remove_interface,
-	.config 	= ath5k_config,
-	.prepare_multicast = ath5k_prepare_multicast,
-	.configure_filter = ath5k_configure_filter,
-	.set_key 	= ath5k_set_key,
-	.get_stats 	= ath5k_get_stats,
-	.get_survey	= ath5k_get_survey,
-	.conf_tx 	= NULL,
-	.get_tsf 	= ath5k_get_tsf,
-	.set_tsf 	= ath5k_set_tsf,
-	.reset_tsf 	= ath5k_reset_tsf,
-	.bss_info_changed = ath5k_bss_info_changed,
-	.sw_scan_start	= ath5k_sw_scan_start,
-	.sw_scan_complete = ath5k_sw_scan_complete,
-	.set_coverage_class = ath5k_set_coverage_class,
-};
-
-/*
- * Prototypes - Internal functions
- */
-/* Attach detach */
-static int 	ath5k_attach(struct pci_dev *pdev,
-			struct ieee80211_hw *hw);
-static void 	ath5k_detach(struct pci_dev *pdev,
-			struct ieee80211_hw *hw);
-/* Channel/mode setup */
-static inline short ath5k_ieee2mhz(short chan);
-static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
-				struct ieee80211_channel *channels,
-				unsigned int mode,
-				unsigned int max);
-static int 	ath5k_setup_bands(struct ieee80211_hw *hw);
-static int 	ath5k_chan_set(struct ath5k_softc *sc,
-				struct ieee80211_channel *chan);
-static void	ath5k_setcurmode(struct ath5k_softc *sc,
-				unsigned int mode);
-static void	ath5k_mode_setup(struct ath5k_softc *sc);
-
-/* Descriptor setup */
-static int	ath5k_desc_alloc(struct ath5k_softc *sc,
-				struct pci_dev *pdev);
-static void	ath5k_desc_free(struct ath5k_softc *sc,
-				struct pci_dev *pdev);
-/* Buffers setup */
-static int 	ath5k_rxbuf_setup(struct ath5k_softc *sc,
-				struct ath5k_buf *bf);
-static int 	ath5k_txbuf_setup(struct ath5k_softc *sc,
-				struct ath5k_buf *bf,
-				struct ath5k_txq *txq, int padsize);
-
 static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc,
 				struct ath5k_buf *bf)
 {
@@ -345,35 +223,6 @@
 }
 
 
-/* Queues setup */
-static struct 	ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc,
-				int qtype, int subtype);
-static int 	ath5k_beaconq_setup(struct ath5k_hw *ah);
-static int 	ath5k_beaconq_config(struct ath5k_softc *sc);
-static void 	ath5k_txq_drainq(struct ath5k_softc *sc,
-				struct ath5k_txq *txq);
-static void 	ath5k_txq_cleanup(struct ath5k_softc *sc);
-static void 	ath5k_txq_release(struct ath5k_softc *sc);
-/* Rx handling */
-static int 	ath5k_rx_start(struct ath5k_softc *sc);
-static void 	ath5k_rx_stop(struct ath5k_softc *sc);
-static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
-					struct sk_buff *skb,
-					struct ath5k_rx_status *rs);
-static void 	ath5k_tasklet_rx(unsigned long data);
-/* Tx handling */
-static void 	ath5k_tx_processq(struct ath5k_softc *sc,
-				struct ath5k_txq *txq);
-static void 	ath5k_tasklet_tx(unsigned long data);
-/* Beacon handling */
-static int 	ath5k_beacon_setup(struct ath5k_softc *sc,
-					struct ath5k_buf *bf);
-static void 	ath5k_beacon_send(struct ath5k_softc *sc);
-static void 	ath5k_beacon_config(struct ath5k_softc *sc);
-static void	ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
-static void	ath5k_tasklet_beacon(unsigned long data);
-static void	ath5k_tasklet_ani(unsigned long data);
-
 static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
 {
 	u64 tsf = ath5k_hw_get_tsf64(ah);
@@ -384,50 +233,6 @@
 	return (tsf & ~0x7fff) | rstamp;
 }
 
-/* Interrupt handling */
-static int 	ath5k_init(struct ath5k_softc *sc);
-static int 	ath5k_stop_locked(struct ath5k_softc *sc);
-static int 	ath5k_stop_hw(struct ath5k_softc *sc);
-static irqreturn_t ath5k_intr(int irq, void *dev_id);
-static void ath5k_reset_work(struct work_struct *work);
-
-static void 	ath5k_tasklet_calibrate(unsigned long data);
-
-/*
- * Module init/exit functions
- */
-static int __init
-init_ath5k_pci(void)
-{
-	int ret;
-
-	ath5k_debug_init();
-
-	ret = pci_register_driver(&ath5k_pci_driver);
-	if (ret) {
-		printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static void __exit
-exit_ath5k_pci(void)
-{
-	pci_unregister_driver(&ath5k_pci_driver);
-
-	ath5k_debug_finish();
-}
-
-module_init(init_ath5k_pci);
-module_exit(exit_ath5k_pci);
-
-
-/********************\
-* PCI Initialization *
-\********************/
-
 static const char *
 ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
 {
@@ -466,299 +271,6 @@
 	.write = ath5k_iowrite32,
 };
 
-static int __devinit
-ath5k_pci_probe(struct pci_dev *pdev,
-		const struct pci_device_id *id)
-{
-	void __iomem *mem;
-	struct ath5k_softc *sc;
-	struct ath_common *common;
-	struct ieee80211_hw *hw;
-	int ret;
-	u8 csz;
-
-	/*
-	 * L0s needs to be disabled on all ath5k cards.
-	 *
-	 * For distributions shipping with CONFIG_PCIEASPM (this will be enabled
-	 * by default in the future in 2.6.36) this will also mean both L1 and
-	 * L0s will be disabled when a pre 1.1 PCIe device is detected. We do
-	 * know L1 works correctly even for all ath5k pre 1.1 PCIe devices
-	 * though but cannot currently undue the effect of a blacklist, for
-	 * details you can read pcie_aspm_sanity_check() and see how it adjusts
-	 * the device link capability.
-	 *
-	 * It may be possible in the future to implement some PCI API to allow
-	 * drivers to override blacklists for pre 1.1 PCIe but for now it is
-	 * best to accept that both L0s and L1 will be disabled completely for
-	 * distributions shipping with CONFIG_PCIEASPM rather than having this
-	 * issue present. Motivation for adding this new API will be to help
-	 * with power consumption for some of these devices.
-	 */
-	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
-
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "can't enable device\n");
-		goto err;
-	}
-
-	/* XXX 32-bit addressing only */
-	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (ret) {
-		dev_err(&pdev->dev, "32-bit DMA not available\n");
-		goto err_dis;
-	}
-
-	/*
-	 * Cache line size is used to size and align various
-	 * structures used to communicate with the hardware.
-	 */
-	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
-	if (csz == 0) {
-		/*
-		 * Linux 2.4.18 (at least) writes the cache line size
-		 * register as a 16-bit wide register which is wrong.
-		 * We must have this setup properly for rx buffer
-		 * DMA to work so force a reasonable value here if it
-		 * comes up zero.
-		 */
-		csz = L1_CACHE_BYTES >> 2;
-		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
-	}
-	/*
-	 * The default setting of latency timer yields poor results,
-	 * set it to the value used by other systems.  It may be worth
-	 * tweaking this setting more.
-	 */
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
-
-	/* Enable bus mastering */
-	pci_set_master(pdev);
-
-	/*
-	 * Disable the RETRY_TIMEOUT register (0x41) to keep
-	 * PCI Tx retries from interfering with C3 CPU state.
-	 */
-	pci_write_config_byte(pdev, 0x41, 0);
-
-	ret = pci_request_region(pdev, 0, "ath5k");
-	if (ret) {
-		dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
-		goto err_dis;
-	}
-
-	mem = pci_iomap(pdev, 0, 0);
-	if (!mem) {
-		dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
-		ret = -EIO;
-		goto err_reg;
-	}
-
-	/*
-	 * Allocate hw (mac80211 main struct)
-	 * and hw->priv (driver private data)
-	 */
-	hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
-	if (hw == NULL) {
-		dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
-		ret = -ENOMEM;
-		goto err_map;
-	}
-
-	dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
-
-	/* Initialize driver private data */
-	SET_IEEE80211_DEV(hw, &pdev->dev);
-	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-		    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-		    IEEE80211_HW_SIGNAL_DBM;
-
-	hw->wiphy->interface_modes =
-		BIT(NL80211_IFTYPE_AP) |
-		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC) |
-		BIT(NL80211_IFTYPE_MESH_POINT);
-
-	hw->extra_tx_headroom = 2;
-	hw->channel_change_time = 5000;
-	sc = hw->priv;
-	sc->hw = hw;
-	sc->pdev = pdev;
-
-	ath5k_debug_init_device(sc);
-
-	/*
-	 * Mark the device as detached to avoid processing
-	 * interrupts until setup is complete.
-	 */
-	__set_bit(ATH_STAT_INVALID, sc->status);
-
-	sc->iobase = mem; /* So we can unmap it on detach */
-	sc->opmode = NL80211_IFTYPE_STATION;
-	sc->bintval = 1000;
-	mutex_init(&sc->lock);
-	spin_lock_init(&sc->rxbuflock);
-	spin_lock_init(&sc->txbuflock);
-	spin_lock_init(&sc->block);
-
-	/* Set private data */
-	pci_set_drvdata(pdev, sc);
-
-	/* Setup interrupt handler */
-	ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
-	if (ret) {
-		ATH5K_ERR(sc, "request_irq failed\n");
-		goto err_free;
-	}
-
-	/*If we passed the test malloc a ath5k_hw struct*/
-	sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
-	if (!sc->ah) {
-		ret = -ENOMEM;
-		ATH5K_ERR(sc, "out of memory\n");
-		goto err_irq;
-	}
-
-	sc->ah->ah_sc = sc;
-	sc->ah->ah_iobase = sc->iobase;
-	common = ath5k_hw_common(sc->ah);
-	common->ops = &ath5k_common_ops;
-	common->ah = sc->ah;
-	common->hw = hw;
-	common->cachelsz = csz << 2; /* convert to bytes */
-
-	/* Initialize device */
-	ret = ath5k_hw_attach(sc);
-	if (ret) {
-		goto err_free_ah;
-	}
-
-	/* set up multi-rate retry capabilities */
-	if (sc->ah->ah_version == AR5K_AR5212) {
-		hw->max_rates = 4;
-		hw->max_rate_tries = 11;
-	}
-
-	/* Finish private driver data initialization */
-	ret = ath5k_attach(pdev, hw);
-	if (ret)
-		goto err_ah;
-
-	ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
-			ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
-					sc->ah->ah_mac_srev,
-					sc->ah->ah_phy_revision);
-
-	if (!sc->ah->ah_single_chip) {
-		/* Single chip radio (!RF5111) */
-		if (sc->ah->ah_radio_5ghz_revision &&
-			!sc->ah->ah_radio_2ghz_revision) {
-			/* No 5GHz support -> report 2GHz radio */
-			if (!test_bit(AR5K_MODE_11A,
-				sc->ah->ah_capabilities.cap_mode)) {
-				ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
-					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
-			/* No 2GHz support (5110 and some
-			 * 5Ghz only cards) -> report 5Ghz radio */
-			} else if (!test_bit(AR5K_MODE_11B,
-				sc->ah->ah_capabilities.cap_mode)) {
-				ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
-					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
-			/* Multiband radio */
-			} else {
-				ATH5K_INFO(sc, "RF%s multiband radio found"
-					" (0x%x)\n",
-					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
-			}
-		}
-		/* Multi chip radio (RF5111 - RF2111) ->
-		 * report both 2GHz/5GHz radios */
-		else if (sc->ah->ah_radio_5ghz_revision &&
-				sc->ah->ah_radio_2ghz_revision){
-			ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
-				ath5k_chip_name(AR5K_VERSION_RAD,
-					sc->ah->ah_radio_5ghz_revision),
-					sc->ah->ah_radio_5ghz_revision);
-			ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
-				ath5k_chip_name(AR5K_VERSION_RAD,
-					sc->ah->ah_radio_2ghz_revision),
-					sc->ah->ah_radio_2ghz_revision);
-		}
-	}
-
-
-	/* ready to process interrupts */
-	__clear_bit(ATH_STAT_INVALID, sc->status);
-
-	return 0;
-err_ah:
-	ath5k_hw_detach(sc->ah);
-err_irq:
-	free_irq(pdev->irq, sc);
-err_free_ah:
-	kfree(sc->ah);
-err_free:
-	ieee80211_free_hw(hw);
-err_map:
-	pci_iounmap(pdev, mem);
-err_reg:
-	pci_release_region(pdev, 0);
-err_dis:
-	pci_disable_device(pdev);
-err:
-	return ret;
-}
-
-static void __devexit
-ath5k_pci_remove(struct pci_dev *pdev)
-{
-	struct ath5k_softc *sc = pci_get_drvdata(pdev);
-
-	ath5k_debug_finish_device(sc);
-	ath5k_detach(pdev, sc->hw);
-	ath5k_hw_detach(sc->ah);
-	kfree(sc->ah);
-	free_irq(pdev->irq, sc);
-	pci_iounmap(pdev, sc->iobase);
-	pci_release_region(pdev, 0);
-	pci_disable_device(pdev);
-	ieee80211_free_hw(sc->hw);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int ath5k_pci_suspend(struct device *dev)
-{
-	struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
-
-	ath5k_led_off(sc);
-	return 0;
-}
-
-static int ath5k_pci_resume(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct ath5k_softc *sc = pci_get_drvdata(pdev);
-
-	/*
-	 * Suspend/Resume resets the PCI configuration space, so we have to
-	 * re-disable the RETRY_TIMEOUT register (0x41) to keep
-	 * PCI Tx retries from interfering with C3 CPU state
-	 */
-	pci_write_config_byte(pdev, 0x41, 0);
-
-	ath5k_led_enable(sc);
-	return 0;
-}
-#endif /* CONFIG_PM_SLEEP */
-
-
 /***********************\
 * Driver Initialization *
 \***********************/
@@ -772,170 +284,6 @@
 	return ath_reg_notifier_apply(wiphy, request, regulatory);
 }
 
-static int
-ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-	struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
-	u8 mac[ETH_ALEN] = {};
-	int ret;
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
-
-	/*
-	 * Check if the MAC has multi-rate retry support.
-	 * We do this by trying to setup a fake extended
-	 * descriptor.  MAC's that don't have support will
-	 * return false w/o doing anything.  MAC's that do
-	 * support it will return true w/o doing anything.
-	 */
-	ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0);
-
-	if (ret < 0)
-		goto err;
-	if (ret > 0)
-		__set_bit(ATH_STAT_MRRETRY, sc->status);
-
-	/*
-	 * Collect the channel list.  The 802.11 layer
-	 * is resposible for filtering this list based
-	 * on settings like the phy mode and regulatory
-	 * domain restrictions.
-	 */
-	ret = ath5k_setup_bands(hw);
-	if (ret) {
-		ATH5K_ERR(sc, "can't get channels\n");
-		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.
-	 */
-	ret = ath5k_desc_alloc(sc, pdev);
-	if (ret) {
-		ATH5K_ERR(sc, "can't allocate descriptors\n");
-		goto err;
-	}
-
-	/*
-	 * Allocate hardware transmit queues: one queue for
-	 * beacon frames and one data queue for each QoS
-	 * priority.  Note that hw functions handle reseting
-	 * these queues at the needed time.
-	 */
-	ret = ath5k_beaconq_setup(ah);
-	if (ret < 0) {
-		ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
-		goto err_desc;
-	}
-	sc->bhalq = ret;
-	sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0);
-	if (IS_ERR(sc->cabq)) {
-		ATH5K_ERR(sc, "can't setup cab queue\n");
-		ret = PTR_ERR(sc->cabq);
-		goto err_bhal;
-	}
-
-	sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
-	if (IS_ERR(sc->txq)) {
-		ATH5K_ERR(sc, "can't setup xmit queue\n");
-		ret = PTR_ERR(sc->txq);
-		goto err_queues;
-	}
-
-	tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
-	tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
-	tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
-	tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
-	tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
-
-	INIT_WORK(&sc->reset_work, ath5k_reset_work);
-
-	ret = ath5k_eeprom_read_mac(ah, mac);
-	if (ret) {
-		ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
-			sc->pdev->device);
-		goto err_queues;
-	}
-
-	SET_IEEE80211_PERM_ADDR(hw, mac);
-	/* All MAC address bits matter for ACKs */
-	memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN);
-	ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
-
-	regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
-	ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
-	if (ret) {
-		ATH5K_ERR(sc, "can't initialize regulatory system\n");
-		goto err_queues;
-	}
-
-	ret = ieee80211_register_hw(hw);
-	if (ret) {
-		ATH5K_ERR(sc, "can't register ieee80211 hw\n");
-		goto err_queues;
-	}
-
-	if (!ath_is_world_regd(regulatory))
-		regulatory_hint(hw->wiphy, regulatory->alpha2);
-
-	ath5k_init_leds(sc);
-
-	ath5k_sysfs_register(sc);
-
-	return 0;
-err_queues:
-	ath5k_txq_release(sc);
-err_bhal:
-	ath5k_hw_release_tx_queue(ah, sc->bhalq);
-err_desc:
-	ath5k_desc_free(sc, pdev);
-err:
-	return ret;
-}
-
-static void
-ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
-{
-	struct ath5k_softc *sc = hw->priv;
-
-	/*
-	 * NB: the order of these is important:
-	 * o call the 802.11 layer before detaching ath5k_hw to
-	 *   insure callbacks into the driver to delete global
-	 *   key cache entries can be handled
-	 * o reclaim the tx queue data structures after calling
-	 *   the 802.11 layer as we'll get called back to reclaim
-	 *   node state and potentially want to use them
-	 * o to cleanup the tx queues the hal is called, so detach
-	 *   it last
-	 * XXX: ??? detach ath5k_hw ???
-	 * Other than that, it's straightforward...
-	 */
-	ieee80211_unregister_hw(hw);
-	ath5k_desc_free(sc, pdev);
-	ath5k_txq_release(sc);
-	ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
-	ath5k_unregister_leds(sc);
-
-	ath5k_sysfs_unregister(sc);
-	/*
-	 * NB: can't reclaim these until after ieee80211_ifdetach
-	 * returns because we'll get called back to reclaim node
-	 * state and potentially want to use them.
-	 */
-}
-
-
-
-
 /********************\
 * Channel/mode setup *
 \********************/
@@ -1163,8 +511,101 @@
 	}
 }
 
+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)
+{
+	struct ath_vif_iter_data *iter_data = data;
+	int i;
+	struct ath5k_vif *avf = (void *)vif->drv_priv;
+
+	if (iter_data->hw_macaddr)
+		for (i = 0; i < ETH_ALEN; i++)
+			iter_data->mask[i] &=
+				~(iter_data->hw_macaddr[i] ^ mac[i]);
+
+	if (!iter_data->found_active) {
+		iter_data->found_active = true;
+		memcpy(iter_data->active_mac, mac, ETH_ALEN);
+	}
+
+	if (iter_data->need_set_hw_addr && iter_data->hw_macaddr)
+		if (compare_ether_addr(iter_data->hw_macaddr, mac) == 0)
+			iter_data->need_set_hw_addr = false;
+
+	if (!iter_data->any_assoc) {
+		if (avf->assoc)
+			iter_data->any_assoc = true;
+	}
+
+	/* Calculate combined mode - when APs are active, operate in AP mode.
+	 * Otherwise use the mode of the new interface. This can currently
+	 * only deal with combinations of APs and STAs. Only one ad-hoc
+	 * interfaces is allowed above.
+	 */
+	if (avf->opmode == NL80211_IFTYPE_AP)
+		iter_data->opmode = NL80211_IFTYPE_AP;
+	else
+		if (iter_data->opmode == NL80211_IFTYPE_UNSPECIFIED)
+			iter_data->opmode = avf->opmode;
+}
+
+static void ath_do_set_opmode(struct ath5k_softc *sc)
+{
+	struct ath5k_hw *ah = sc->ah;
+	ath5k_hw_set_opmode(ah, sc->opmode);
+	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
+		  sc->opmode, ath_opmode_to_string(sc->opmode));
+}
+
+void 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;
+
+	/*
+	 * 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);
+	iter_data.found_active = false;
+	iter_data.need_set_hw_addr = true;
+	iter_data.opmode = NL80211_IFTYPE_UNSPECIFIED;
+
+	if (vif)
+		ath_vif_iter(&iter_data, vif->addr, vif);
+
+	/* Get list of all active MAC addresses */
+	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter,
+						   &iter_data);
+	memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN);
+
+	sc->opmode = iter_data.opmode;
+	if (sc->opmode == NL80211_IFTYPE_UNSPECIFIED)
+		/* Nothing active, default to station mode */
+		sc->opmode = NL80211_IFTYPE_STATION;
+
+	ath_do_set_opmode(sc);
+
+	if (iter_data.need_set_hw_addr && iter_data.found_active)
+		ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac);
+
+	if (ath5k_hw_hasbssidmask(sc->ah))
+		ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
+}
+
 static void
-ath5k_mode_setup(struct ath5k_softc *sc)
+ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif)
 {
 	struct ath5k_hw *ah = sc->ah;
 	u32 rfilt;
@@ -1172,15 +613,9 @@
 	/* configure rx filter */
 	rfilt = sc->filter_flags;
 	ath5k_hw_set_rx_filter(ah, rfilt);
-
-	if (ath5k_hw_hasbssidmask(ah))
-		ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
-
-	/* configure operational mode */
-	ath5k_hw_set_opmode(ah, sc->opmode);
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode);
 	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
+
+	ath5k_update_bssid_mask_and_opmode(sc, vif);
 }
 
 static inline int
@@ -1352,13 +787,13 @@
 		flags |= AR5K_TXDESC_RTSENA;
 		cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
 		duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
-			sc->vif, pktlen, info));
+			info->control.vif, pktlen, info));
 	}
 	if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
 		flags |= AR5K_TXDESC_CTSENA;
 		cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
 		duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
-			sc->vif, pktlen, info));
+			info->control.vif, pktlen, info));
 	}
 	ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
 		ieee80211_get_hdrlen_from_skb(skb), padsize,
@@ -1391,6 +826,7 @@
 
 	spin_lock_bh(&txq->lock);
 	list_add_tail(&bf->list, &txq->q);
+	txq->txq_len++;
 	if (txq->link == NULL) /* is this first packet? */
 		ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
 	else /* no, so only link it */
@@ -1459,10 +895,13 @@
 		list_add_tail(&bf->list, &sc->txbuf);
 	}
 
-	/* beacon buffer */
-	bf->desc = ds;
-	bf->daddr = da;
-	sc->bbuf = bf;
+	/* beacon buffers */
+	INIT_LIST_HEAD(&sc->bcbuf);
+	for (i = 0; i < ATH_BCBUF; i++, bf++, ds++, da += sizeof(*ds)) {
+		bf->desc = ds;
+		bf->daddr = da;
+		list_add_tail(&bf->list, &sc->bcbuf);
+	}
 
 	return 0;
 err_free:
@@ -1477,11 +916,12 @@
 {
 	struct ath5k_buf *bf;
 
-	ath5k_txbuf_free_skb(sc, sc->bbuf);
 	list_for_each_entry(bf, &sc->txbuf, list)
 		ath5k_txbuf_free_skb(sc, bf);
 	list_for_each_entry(bf, &sc->rxbuf, list)
 		ath5k_rxbuf_free_skb(sc, bf);
+	list_for_each_entry(bf, &sc->bcbuf, list)
+		ath5k_txbuf_free_skb(sc, bf);
 
 	/* Free memory associated with all descriptors */
 	pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
@@ -1490,13 +930,9 @@
 
 	kfree(sc->bufptr);
 	sc->bufptr = NULL;
-	sc->bbuf = NULL;
 }
 
 
-
-
-
 /**************\
 * Queues setup *
 \**************/
@@ -1509,16 +945,18 @@
 	struct ath5k_txq *txq;
 	struct ath5k_txq_info qi = {
 		.tqi_subtype = subtype,
-		.tqi_aifs = AR5K_TXQ_USEDEFAULT,
-		.tqi_cw_min = AR5K_TXQ_USEDEFAULT,
-		.tqi_cw_max = AR5K_TXQ_USEDEFAULT
+		/* XXX: default values not correct for B and XR channels,
+		 * but who cares? */
+		.tqi_aifs = AR5K_TUNE_AIFS,
+		.tqi_cw_min = AR5K_TUNE_CWMIN,
+		.tqi_cw_max = AR5K_TUNE_CWMAX
 	};
 	int qnum;
 
 	/*
 	 * Enable interrupts only for EOL and DESC conditions.
 	 * We mark tx descriptors to receive a DESC interrupt
-	 * when a tx queue gets deep; otherwise waiting for the
+	 * when a tx queue gets deep; otherwise we wait for the
 	 * EOL to reap descriptors.  Note that this is done to
 	 * reduce interrupt load and this only defers reaping
 	 * descriptors, never transmitting frames.  Aside from
@@ -1550,6 +988,9 @@
 		INIT_LIST_HEAD(&txq->q);
 		spin_lock_init(&txq->lock);
 		txq->setup = true;
+		txq->txq_len = 0;
+		txq->txq_poll_mark = false;
+		txq->txq_stuck = 0;
 	}
 	return &sc->txqs[qnum];
 }
@@ -1558,9 +999,11 @@
 ath5k_beaconq_setup(struct ath5k_hw *ah)
 {
 	struct ath5k_txq_info qi = {
-		.tqi_aifs = AR5K_TXQ_USEDEFAULT,
-		.tqi_cw_min = AR5K_TXQ_USEDEFAULT,
-		.tqi_cw_max = AR5K_TXQ_USEDEFAULT,
+		/* XXX: default values not correct for B and XR channels,
+		 * but who cares? */
+		.tqi_aifs = AR5K_TUNE_AIFS,
+		.tqi_cw_min = AR5K_TUNE_CWMIN,
+		.tqi_cw_max = AR5K_TUNE_CWMAX,
 		/* NB: for dynamic turbo, don't enable any other interrupts */
 		.tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE
 	};
@@ -1594,7 +1037,7 @@
 		 */
 		qi.tqi_aifs = 0;
 		qi.tqi_cw_min = 0;
-		qi.tqi_cw_max = 2 * ah->ah_cw_min;
+		qi.tqi_cw_max = 2 * AR5K_TUNE_CWMIN;
 	}
 
 	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
@@ -1644,9 +1087,11 @@
 		spin_lock_bh(&sc->txbuflock);
 		list_move_tail(&bf->list, &sc->txbuf);
 		sc->txbuf_len++;
+		txq->txq_len--;
 		spin_unlock_bh(&sc->txbuflock);
 	}
 	txq->link = NULL;
+	txq->txq_poll_mark = false;
 	spin_unlock_bh(&txq->lock);
 }
 
@@ -1696,8 +1141,6 @@
 }
 
 
-
-
 /*************\
 * RX Handling *
 \*************/
@@ -1713,7 +1156,7 @@
 	struct ath5k_buf *bf;
 	int ret;
 
-	common->rx_bufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz);
+	common->rx_bufsize = roundup(IEEE80211_MAX_FRAME_LEN, common->cachelsz);
 
 	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n",
 		  common->cachelsz, common->rx_bufsize);
@@ -1732,7 +1175,7 @@
 	spin_unlock_bh(&sc->rxbuflock);
 
 	ath5k_hw_start_rx_dma(ah);	/* enable recv descriptors */
-	ath5k_mode_setup(sc);		/* set filters, etc. */
+	ath5k_mode_setup(sc, NULL);		/* set filters, etc. */
 	ath5k_hw_start_rx_pcu(ah);	/* re-enable PCU/DMA engine */
 
 	return 0;
@@ -1840,6 +1283,15 @@
 		 */
 		if (hw_tu >= sc->nexttbtt)
 			ath5k_beacon_update_timers(sc, bc_tstamp);
+
+		/* Check if the beacon timers are still correct, because a TSF
+		 * update might have created a window between them - for a
+		 * longer description see the comment of this function: */
+		if (!ath5k_hw_check_beacon_timers(sc->ah, sc->bintval)) {
+			ath5k_beacon_update_timers(sc, bc_tstamp);
+			ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+				"fixed beacon timers after beacon receive\n");
+		}
 	}
 }
 
@@ -1863,7 +1315,7 @@
 }
 
 /*
- * Compute padding position. skb must contains an IEEE 802.11 frame
+ * Compute padding position. skb must contain an IEEE 802.11 frame
  */
 static int ath5k_common_padpos(struct sk_buff *skb)
 {
@@ -1882,10 +1334,9 @@
 }
 
 /*
- * This function expects a 802.11 frame and returns the number of
- * bytes added, or -1 if we don't have enought header room.
+ * This function expects an 802.11 frame and returns the number of
+ * bytes added, or -1 if we don't have enough header room.
  */
-
 static int ath5k_add_padding(struct sk_buff *skb)
 {
 	int padpos = ath5k_common_padpos(skb);
@@ -1905,10 +1356,18 @@
 }
 
 /*
- * This function expects a 802.11 frame and returns the number of
- * bytes removed
+ * The MAC header is padded to have 32-bit boundary if the
+ * packet payload is non-zero. The general calculation for
+ * padsize would take into account odd header lengths:
+ * padsize = 4 - (hdrlen & 3); however, since only
+ * even-length headers are used, padding can only be 0 or 2
+ * bytes and we can optimize this a bit.  We must not try to
+ * remove padding from short control frames that do not have a
+ * payload.
+ *
+ * This function expects an 802.11 frame and returns the number of
+ * bytes removed.
  */
-
 static int ath5k_remove_padding(struct sk_buff *skb)
 {
 	int padpos = ath5k_common_padpos(skb);
@@ -1929,14 +1388,6 @@
 {
 	struct ieee80211_rx_status *rxs;
 
-	/* The MAC header is padded to have 32-bit boundary if the
-	 * packet payload is non-zero. The general calculation for
-	 * padsize would take into account odd header lengths:
-	 * padsize = (4 - hdrlen % 4) % 4; However, since only
-	 * even-length headers are used, padding can only be 0 or 2
-	 * bytes and we can optimize this a bit. In addition, we must
-	 * not try to remove padding from short control frames that do
-	 * not have payload. */
 	ath5k_remove_padding(skb);
 
 	rxs = IEEE80211_SKB_RXCB(skb);
@@ -2007,6 +1458,7 @@
 ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
 {
 	sc->stats.rx_all_count++;
+	sc->stats.rx_bytes_count += rs->rs_datalen;
 
 	if (unlikely(rs->rs_status)) {
 		if (rs->rs_status & AR5K_RXERR_CRC)
@@ -2040,9 +1492,8 @@
 			return true;
 		}
 
-		/* let crypto-error packets fall through in MNTR */
-		if ((rs->rs_status & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
-		    sc->opmode != NL80211_IFTYPE_MONITOR)
+		/* reject any frames with non-crypto errors */
+		if (rs->rs_status & ~(AR5K_RXERR_DECRYPT))
 			return false;
 	}
 
@@ -2123,6 +1574,118 @@
 * TX Handling *
 \*************/
 
+static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
+			  struct ath5k_txq *txq)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_buf *bf;
+	unsigned long flags;
+	int padsize;
+
+	ath5k_debug_dump_skb(sc, skb, "TX  ", 1);
+
+	/*
+	 * The hardware expects the header padded to 4 byte boundaries.
+	 * If this is not the case, we add the padding after the header.
+	 */
+	padsize = ath5k_add_padding(skb);
+	if (padsize < 0) {
+		ATH5K_ERR(sc, "tx hdrlen not %%4: not enough"
+			  " headroom to pad");
+		goto drop_packet;
+	}
+
+	if (txq->txq_len >= ATH5K_TXQ_LEN_MAX)
+		ieee80211_stop_queue(hw, txq->qnum);
+
+	spin_lock_irqsave(&sc->txbuflock, flags);
+	if (list_empty(&sc->txbuf)) {
+		ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
+		spin_unlock_irqrestore(&sc->txbuflock, flags);
+		ieee80211_stop_queues(hw);
+		goto drop_packet;
+	}
+	bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
+	list_del(&bf->list);
+	sc->txbuf_len--;
+	if (list_empty(&sc->txbuf))
+		ieee80211_stop_queues(hw);
+	spin_unlock_irqrestore(&sc->txbuflock, flags);
+
+	bf->skb = skb;
+
+	if (ath5k_txbuf_setup(sc, bf, txq, padsize)) {
+		bf->skb = NULL;
+		spin_lock_irqsave(&sc->txbuflock, flags);
+		list_add_tail(&bf->list, &sc->txbuf);
+		sc->txbuf_len++;
+		spin_unlock_irqrestore(&sc->txbuflock, flags);
+		goto drop_packet;
+	}
+	return NETDEV_TX_OK;
+
+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 ieee80211_tx_info *info;
+	int i;
+
+	sc->stats.tx_all_count++;
+	sc->stats.tx_bytes_count += skb->len;
+	info = IEEE80211_SKB_CB(skb);
+
+	ieee80211_tx_info_clear_status(info);
+	for (i = 0; i < 4; i++) {
+		struct ieee80211_tx_rate *r =
+			&info->status.rates[i];
+
+		if (ts->ts_rate[i]) {
+			r->idx = ath5k_hw_to_driver_rix(sc, ts->ts_rate[i]);
+			r->count = ts->ts_retry[i];
+		} else {
+			r->idx = -1;
+			r->count = 0;
+		}
+	}
+
+	/* count the successful attempt as well */
+	info->status.rates[ts->ts_final_idx].count++;
+
+	if (unlikely(ts->ts_status)) {
+		sc->stats.ack_fail++;
+		if (ts->ts_status & AR5K_TXERR_FILT) {
+			info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+			sc->stats.txerr_filt++;
+		}
+		if (ts->ts_status & AR5K_TXERR_XRETRY)
+			sc->stats.txerr_retry++;
+		if (ts->ts_status & AR5K_TXERR_FIFO)
+			sc->stats.txerr_fifo++;
+	} else {
+		info->flags |= IEEE80211_TX_STAT_ACK;
+		info->status.ack_signal = ts->ts_rssi;
+	}
+
+	/*
+	* Remove MAC header padding before giving the frame
+	* back to mac80211.
+	*/
+	ath5k_remove_padding(skb);
+
+	if (ts->ts_antenna > 0 && ts->ts_antenna < 5)
+		sc->stats.antenna_tx[ts->ts_antenna]++;
+	else
+		sc->stats.antenna_tx[0]++; /* invalid */
+
+	ieee80211_tx_status(sc->hw, skb);
+}
+
 static void
 ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
 {
@@ -2130,96 +1693,51 @@
 	struct ath5k_buf *bf, *bf0;
 	struct ath5k_desc *ds;
 	struct sk_buff *skb;
-	struct ieee80211_tx_info *info;
-	int i, ret;
+	int ret;
 
 	spin_lock(&txq->lock);
 	list_for_each_entry_safe(bf, bf0, &txq->q, list) {
-		ds = bf->desc;
+
+		txq->txq_poll_mark = false;
+
+		/* skb might already have been processed last time. */
+		if (bf->skb != NULL) {
+			ds = bf->desc;
+
+			ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
+			if (unlikely(ret == -EINPROGRESS))
+				break;
+			else if (unlikely(ret)) {
+				ATH5K_ERR(sc,
+					"error %d while processing "
+					"queue %u\n", ret, txq->qnum);
+				break;
+			}
+
+			skb = bf->skb;
+			bf->skb = NULL;
+			pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
+					PCI_DMA_TODEVICE);
+			ath5k_tx_frame_completed(sc, skb, &ts);
+		}
 
 		/*
 		 * It's possible that the hardware can say the buffer is
 		 * completed when it hasn't yet loaded the ds_link from
-		 * host memory and moved on.  If there are more TX
-		 * descriptors in the queue, wait for TXDP to change
-		 * before processing this one.
+		 * host memory and moved on.
+		 * Always keep the last descriptor to avoid HW races...
 		 */
-		if (ath5k_hw_get_txdp(sc->ah, txq->qnum) == bf->daddr &&
-		    !list_is_last(&bf->list, &txq->q))
-			break;
-
-		ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
-		if (unlikely(ret == -EINPROGRESS))
-			break;
-		else if (unlikely(ret)) {
-			ATH5K_ERR(sc, "error %d while processing queue %u\n",
-				ret, txq->qnum);
-			break;
+		if (ath5k_hw_get_txdp(sc->ah, txq->qnum) != bf->daddr) {
+			spin_lock(&sc->txbuflock);
+			list_move_tail(&bf->list, &sc->txbuf);
+			sc->txbuf_len++;
+			txq->txq_len--;
+			spin_unlock(&sc->txbuflock);
 		}
-
-		sc->stats.tx_all_count++;
-		skb = bf->skb;
-		info = IEEE80211_SKB_CB(skb);
-		bf->skb = NULL;
-
-		pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
-				PCI_DMA_TODEVICE);
-
-		ieee80211_tx_info_clear_status(info);
-		for (i = 0; i < 4; i++) {
-			struct ieee80211_tx_rate *r =
-				&info->status.rates[i];
-
-			if (ts.ts_rate[i]) {
-				r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
-				r->count = ts.ts_retry[i];
-			} else {
-				r->idx = -1;
-				r->count = 0;
-			}
-		}
-
-		/* count the successful attempt as well */
-		info->status.rates[ts.ts_final_idx].count++;
-
-		if (unlikely(ts.ts_status)) {
-			sc->stats.ack_fail++;
-			if (ts.ts_status & AR5K_TXERR_FILT) {
-				info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
-				sc->stats.txerr_filt++;
-			}
-			if (ts.ts_status & AR5K_TXERR_XRETRY)
-				sc->stats.txerr_retry++;
-			if (ts.ts_status & AR5K_TXERR_FIFO)
-				sc->stats.txerr_fifo++;
-		} else {
-			info->flags |= IEEE80211_TX_STAT_ACK;
-			info->status.ack_signal = ts.ts_rssi;
-		}
-
-		/*
-		 * Remove MAC header padding before giving the frame
-		 * back to mac80211.
-		 */
-		ath5k_remove_padding(skb);
-
-		if (ts.ts_antenna > 0 && ts.ts_antenna < 5)
-			sc->stats.antenna_tx[ts.ts_antenna]++;
-		else
-			sc->stats.antenna_tx[0]++; /* invalid */
-
-		ieee80211_tx_status(sc->hw, skb);
-
-		spin_lock(&sc->txbuflock);
-		list_move_tail(&bf->list, &sc->txbuf);
-		sc->txbuf_len++;
-		spin_unlock(&sc->txbuflock);
 	}
-	if (likely(list_empty(&txq->q)))
-		txq->link = NULL;
 	spin_unlock(&txq->lock);
-	if (sc->txbuf_len > ATH_TXBUF / 5)
-		ieee80211_wake_queues(sc->hw);
+	if (txq->txq_len < ATH5K_TXQ_LEN_LOW && txq->qnum < 4)
+		ieee80211_wake_queue(sc->hw, txq->qnum);
 }
 
 static void
@@ -2285,10 +1803,11 @@
 	 * default antenna which is supposed to be an omni.
 	 *
 	 * Note2: On sectored scenarios it's possible to have
-	 * multiple antennas (1omni -the default- and 14 sectors)
-	 * so if we choose to actually support this mode we need
-	 * to allow user to set how many antennas we have and tweak
-	 * the code below to send beacons on all of them.
+	 * multiple antennas (1 omni -- the default -- and 14
+	 * sectors), so if we choose to actually support this
+	 * mode, we need to allow the user to set how many antennas
+	 * we have and tweak the code below to send beacons
+	 * on all of them.
 	 */
 	if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP)
 		antenna = sc->bsent & 4 ? 2 : 1;
@@ -2314,6 +1833,44 @@
 }
 
 /*
+ * Updates the beacon that is sent by ath5k_beacon_send.  For adhoc,
+ * this is called only once at config_bss time, for AP we do it every
+ * SWBA interrupt so that the TIM will reflect buffered frames.
+ *
+ * Called with the beacon lock.
+ */
+static int
+ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	int ret;
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_vif *avf = (void *)vif->drv_priv;
+	struct sk_buff *skb;
+
+	if (WARN_ON(!vif)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	skb = ieee80211_beacon_get(hw, vif);
+
+	if (!skb) {
+		ret = -ENOMEM;
+		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);
+	if (ret)
+		avf->bbuf->skb = NULL;
+out:
+	return ret;
+}
+
+/*
  * Transmit a beacon frame at SWBA.  Dynamic updates to the
  * frame contents are done as needed and the slot time is
  * also adjusted based on current state.
@@ -2324,20 +1881,17 @@
 static void
 ath5k_beacon_send(struct ath5k_softc *sc)
 {
-	struct ath5k_buf *bf = sc->bbuf;
 	struct ath5k_hw *ah = sc->ah;
+	struct ieee80211_vif *vif;
+	struct ath5k_vif *avf;
+	struct ath5k_buf *bf;
 	struct sk_buff *skb;
 
 	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
 
-	if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
-			sc->opmode == NL80211_IFTYPE_MONITOR)) {
-		ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
-		return;
-	}
 	/*
 	 * Check if the previous beacon has gone out.  If
-	 * not don't don't try to post another, skip this
+	 * not, don't don't try to post another: skip this
 	 * period and wait for the next.  Missed beacons
 	 * indicate a problem and should not occur.  If we
 	 * miss too many consecutive beacons reset the device.
@@ -2363,6 +1917,28 @@
 		sc->bmisscount = 0;
 	}
 
+	if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+		u64 tsf = ath5k_hw_get_tsf64(ah);
+		u32 tsftu = TSF_TO_TU(tsf);
+		int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval;
+		vif = sc->bslot[(slot + 1) % ATH_BCBUF];
+		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+			"tsf %llx tsftu %x intval %u slot %u vif %p\n",
+			(unsigned long long)tsf, tsftu, sc->bintval, slot, vif);
+	} else /* only one interface */
+		vif = sc->bslot[0];
+
+	if (!vif)
+		return;
+
+	avf = (void *)vif->drv_priv;
+	bf = avf->bbuf;
+	if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
+			sc->opmode == NL80211_IFTYPE_MONITOR)) {
+		ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
+		return;
+	}
+
 	/*
 	 * Stop any current dma and put the new frame on the queue.
 	 * This should never fail since we check above that no frames
@@ -2375,23 +1951,22 @@
 
 	/* refresh the beacon for AP mode */
 	if (sc->opmode == NL80211_IFTYPE_AP)
-		ath5k_beacon_update(sc->hw, sc->vif);
+		ath5k_beacon_update(sc->hw, vif);
 
 	ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
 	ath5k_hw_start_tx_dma(ah, sc->bhalq);
 	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
 		sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
 
-	skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
+	skb = ieee80211_get_buffered_bc(sc->hw, vif);
 	while (skb) {
 		ath5k_tx_queue(sc->hw, skb, sc->cabq);
-		skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
+		skb = ieee80211_get_buffered_bc(sc->hw, vif);
 	}
 
 	sc->bsent++;
 }
 
-
 /**
  * ath5k_beacon_update_timers - update beacon timers
  *
@@ -2416,6 +1991,12 @@
 	u64 hw_tsf;
 
 	intval = sc->bintval & AR5K_BEACON_PERIOD;
+	if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+		intval /= ATH_BCBUF;	/* staggered multi-bss beacons */
+		if (intval < 15)
+			ATH5K_WARN(sc, "intval %u is too low, min 15\n",
+				   intval);
+	}
 	if (WARN_ON(!intval))
 		return;
 
@@ -2426,8 +2007,11 @@
 	hw_tsf = ath5k_hw_get_tsf64(ah);
 	hw_tu = TSF_TO_TU(hw_tsf);
 
-#define FUDGE 3
-	/* we use FUDGE to make sure the next TBTT is ahead of the current TU */
+#define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3
+	/* We use FUDGE to make sure the next TBTT is ahead of the current TU.
+	 * Since we later substract AR5K_TUNE_SW_BEACON_RESP (10) in the timer
+	 * configuration we need to make sure it is bigger than that. */
+
 	if (bc_tsf == -1) {
 		/*
 		 * no beacons received, called internally.
@@ -2493,7 +2077,6 @@
 		intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : "");
 }
 
-
 /**
  * ath5k_beacon_config - Configure the beacon queues and interrupts
  *
@@ -2572,155 +2155,6 @@
 * Interrupt handling *
 \********************/
 
-static int
-ath5k_init(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-	int ret, i;
-
-	mutex_lock(&sc->lock);
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
-
-	/*
-	 * Stop anything previously setup.  This is safe
-	 * no matter this is the first time through or not.
-	 */
-	ath5k_stop_locked(sc);
-
-	/*
-	 * The basic interface to setting the hardware in a good
-	 * state is ``reset''.  On return the hardware is known to
-	 * be powered up and with interrupts disabled.  This must
-	 * be followed by initialization of the appropriate bits
-	 * 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;
-
-	ret = ath5k_reset(sc, NULL);
-	if (ret)
-		goto done;
-
-	ath5k_rfkill_hw_start(ah);
-
-	/*
-	 * Reset the key cache since some parts do not reset the
-	 * contents on initial power up or resume from suspend.
-	 */
-	for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
-		ath5k_hw_reset_key(ah, i);
-
-	ath5k_hw_set_ack_bitrate_high(ah, true);
-	ret = 0;
-done:
-	mmiowb();
-	mutex_unlock(&sc->lock);
-	return ret;
-}
-
-static int
-ath5k_stop_locked(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
-			test_bit(ATH_STAT_INVALID, sc->status));
-
-	/*
-	 * Shutdown the hardware and driver:
-	 *    stop output from above
-	 *    disable interrupts
-	 *    turn off timers
-	 *    turn off the radio
-	 *    clear transmit machinery
-	 *    clear receive machinery
-	 *    drain and release tx queues
-	 *    reclaim beacon resources
-	 *    power down hardware
-	 *
-	 * Note that some of this work is not possible if the
-	 * hardware is gone (invalid).
-	 */
-	ieee80211_stop_queues(sc->hw);
-
-	if (!test_bit(ATH_STAT_INVALID, sc->status)) {
-		ath5k_led_off(sc);
-		ath5k_hw_set_imr(ah, 0);
-		synchronize_irq(sc->pdev->irq);
-	}
-	ath5k_txq_cleanup(sc);
-	if (!test_bit(ATH_STAT_INVALID, sc->status)) {
-		ath5k_rx_stop(sc);
-		ath5k_hw_phy_disable(ah);
-	}
-
-	return 0;
-}
-
-static void stop_tasklets(struct ath5k_softc *sc)
-{
-	tasklet_kill(&sc->rxtq);
-	tasklet_kill(&sc->txtq);
-	tasklet_kill(&sc->calib);
-	tasklet_kill(&sc->beacontq);
-	tasklet_kill(&sc->ani_tasklet);
-}
-
-/*
- * Stop the device, grabbing the top-level lock to protect
- * against concurrent entry through ath5k_init (which can happen
- * if another thread does a system call and the thread doing the
- * stop is preempted).
- */
-static int
-ath5k_stop_hw(struct ath5k_softc *sc)
-{
-	int ret;
-
-	mutex_lock(&sc->lock);
-	ret = ath5k_stop_locked(sc);
-	if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
-		/*
-		 * Don't set the card in full sleep mode!
-		 *
-		 * a) When the device is in this state it must be carefully
-		 * woken up or references to registers in the PCI clock
-		 * domain may freeze the bus (and system).  This varies
-		 * by chip and is mostly an issue with newer parts
-		 * (madwifi sources mentioned srev >= 0x78) that go to
-		 * sleep more quickly.
-		 *
-		 * b) On older chips full sleep results a weird behaviour
-		 * during wakeup. I tested various cards with srev < 0x78
-		 * and they don't wake up after module reload, a second
-		 * module reload is needed to bring the card up again.
-		 *
-		 * Until we figure out what's going on don't enable
-		 * full chip reset on any chip (this is what Legacy HAL
-		 * and Sam's HAL do anyway). Instead Perform a full reset
-		 * on the device (same as initial state after attach) and
-		 * leave it idle (keep MAC/BB on warm reset) */
-		ret = ath5k_hw_on_hold(sc->ah);
-
-		ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
-				"putting device to sleep\n");
-	}
-	ath5k_txbuf_free_skb(sc, sc->bbuf);
-
-	mmiowb();
-	mutex_unlock(&sc->lock);
-
-	stop_tasklets(sc);
-
-	ath5k_rfkill_hw_stop(sc->ah);
-
-	return ret;
-}
-
 static void
 ath5k_intr_calibration_poll(struct ath5k_hw *ah)
 {
@@ -2857,14 +2291,13 @@
 				sc->curchan->center_freq));
 
 	/* Noise floor calibration interrupts rx/tx path while I/Q calibration
-	 * doesn't. We stop the queues so that calibration doesn't interfere
-	 * with TX and don't run it as often */
+	 * doesn't.
+	 * TODO: We should stop TX here, so that it doesn't interfere.
+	 * Note that stopping the queues is not enough to stop TX! */
 	if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) {
 		ah->ah_cal_next_nf = jiffies +
 			msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF);
-		ieee80211_stop_queues(sc->hw);
 		ath5k_hw_update_noise_floor(ah);
-		ieee80211_wake_queues(sc->hw);
 	}
 
 	ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL;
@@ -2883,71 +2316,208 @@
 }
 
 
-/********************\
-* Mac80211 functions *
-\********************/
-
-static int
-ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void
+ath5k_tx_complete_poll_work(struct work_struct *work)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_softc *sc = container_of(work, struct ath5k_softc,
+			tx_complete_work.work);
+	struct ath5k_txq *txq;
+	int i;
+	bool needreset = false;
 
-	return ath5k_tx_queue(hw, skb, sc->txq);
+	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
+		if (sc->txqs[i].setup) {
+			txq = &sc->txqs[i];
+			spin_lock_bh(&txq->lock);
+			if (txq->txq_len > 1) {
+				if (txq->txq_poll_mark) {
+					ATH5K_DBG(sc, ATH5K_DEBUG_XMIT,
+						  "TX queue stuck %d\n",
+						  txq->qnum);
+					needreset = true;
+					txq->txq_stuck++;
+					spin_unlock_bh(&txq->lock);
+					break;
+				} else {
+					txq->txq_poll_mark = true;
+				}
+			}
+			spin_unlock_bh(&txq->lock);
+		}
+	}
+
+	if (needreset) {
+		ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+			  "TX queues stuck, resetting\n");
+		ath5k_reset(sc, sc->curchan);
+	}
+
+	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+		msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
 }
 
-static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
-			  struct ath5k_txq *txq)
+
+/*************************\
+* Initialization routines *
+\*************************/
+
+static int
+ath5k_stop_locked(struct ath5k_softc *sc)
 {
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_buf *bf;
-	unsigned long flags;
-	int padsize;
+	struct ath5k_hw *ah = sc->ah;
 
-	ath5k_debug_dump_skb(sc, skb, "TX  ", 1);
-
-	if (sc->opmode == NL80211_IFTYPE_MONITOR)
-		ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n");
+	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
+			test_bit(ATH_STAT_INVALID, sc->status));
 
 	/*
-	 * the hardware expects the header padded to 4 byte boundaries
-	 * if this is not the case we add the padding after the header
+	 * Shutdown the hardware and driver:
+	 *    stop output from above
+	 *    disable interrupts
+	 *    turn off timers
+	 *    turn off the radio
+	 *    clear transmit machinery
+	 *    clear receive machinery
+	 *    drain and release tx queues
+	 *    reclaim beacon resources
+	 *    power down hardware
+	 *
+	 * Note that some of this work is not possible if the
+	 * hardware is gone (invalid).
 	 */
-	padsize = ath5k_add_padding(skb);
-	if (padsize < 0) {
-		ATH5K_ERR(sc, "tx hdrlen not %%4: not enough"
-			  " headroom to pad");
-		goto drop_packet;
+	ieee80211_stop_queues(sc->hw);
+
+	if (!test_bit(ATH_STAT_INVALID, sc->status)) {
+		ath5k_led_off(sc);
+		ath5k_hw_set_imr(ah, 0);
+		synchronize_irq(sc->pdev->irq);
+	}
+	ath5k_txq_cleanup(sc);
+	if (!test_bit(ATH_STAT_INVALID, sc->status)) {
+		ath5k_rx_stop(sc);
+		ath5k_hw_phy_disable(ah);
 	}
 
-	spin_lock_irqsave(&sc->txbuflock, flags);
-	if (list_empty(&sc->txbuf)) {
-		ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
-		spin_unlock_irqrestore(&sc->txbuflock, flags);
-		ieee80211_stop_queue(hw, skb_get_queue_mapping(skb));
-		goto drop_packet;
+	return 0;
+}
+
+static int
+ath5k_init(struct ath5k_softc *sc)
+{
+	struct ath5k_hw *ah = sc->ah;
+	struct ath_common *common = ath5k_hw_common(ah);
+	int ret, i;
+
+	mutex_lock(&sc->lock);
+
+	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
+
+	/*
+	 * Stop anything previously setup.  This is safe
+	 * no matter this is the first time through or not.
+	 */
+	ath5k_stop_locked(sc);
+
+	/*
+	 * The basic interface to setting the hardware in a good
+	 * state is ``reset''.  On return the hardware is known to
+	 * be powered up and with interrupts disabled.  This must
+	 * be followed by initialization of the appropriate bits
+	 * 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;
+
+	ret = ath5k_reset(sc, NULL);
+	if (ret)
+		goto done;
+
+	ath5k_rfkill_hw_start(ah);
+
+	/*
+	 * Reset the key cache since some parts do not reset the
+	 * contents on initial power up or resume from suspend.
+	 */
+	for (i = 0; i < common->keymax; i++)
+		ath_hw_keyreset(common, (u16) i);
+
+	ath5k_hw_set_ack_bitrate_high(ah, true);
+
+	for (i = 0; i < ARRAY_SIZE(sc->bslot); i++)
+		sc->bslot[i] = NULL;
+
+	ret = 0;
+done:
+	mmiowb();
+	mutex_unlock(&sc->lock);
+
+	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+			msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
+
+	return ret;
+}
+
+static void stop_tasklets(struct ath5k_softc *sc)
+{
+	tasklet_kill(&sc->rxtq);
+	tasklet_kill(&sc->txtq);
+	tasklet_kill(&sc->calib);
+	tasklet_kill(&sc->beacontq);
+	tasklet_kill(&sc->ani_tasklet);
+}
+
+/*
+ * Stop the device, grabbing the top-level lock to protect
+ * against concurrent entry through ath5k_init (which can happen
+ * if another thread does a system call and the thread doing the
+ * stop is preempted).
+ */
+static int
+ath5k_stop_hw(struct ath5k_softc *sc)
+{
+	int ret;
+
+	mutex_lock(&sc->lock);
+	ret = ath5k_stop_locked(sc);
+	if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
+		/*
+		 * Don't set the card in full sleep mode!
+		 *
+		 * a) When the device is in this state it must be carefully
+		 * woken up or references to registers in the PCI clock
+		 * domain may freeze the bus (and system).  This varies
+		 * by chip and is mostly an issue with newer parts
+		 * (madwifi sources mentioned srev >= 0x78) that go to
+		 * sleep more quickly.
+		 *
+		 * b) On older chips full sleep results a weird behaviour
+		 * during wakeup. I tested various cards with srev < 0x78
+		 * and they don't wake up after module reload, a second
+		 * module reload is needed to bring the card up again.
+		 *
+		 * Until we figure out what's going on don't enable
+		 * full chip reset on any chip (this is what Legacy HAL
+		 * and Sam's HAL do anyway). Instead Perform a full reset
+		 * on the device (same as initial state after attach) and
+		 * leave it idle (keep MAC/BB on warm reset) */
+		ret = ath5k_hw_on_hold(sc->ah);
+
+		ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+				"putting device to sleep\n");
 	}
-	bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
-	list_del(&bf->list);
-	sc->txbuf_len--;
-	if (list_empty(&sc->txbuf))
-		ieee80211_stop_queues(hw);
-	spin_unlock_irqrestore(&sc->txbuflock, flags);
 
-	bf->skb = skb;
+	mmiowb();
+	mutex_unlock(&sc->lock);
 
-	if (ath5k_txbuf_setup(sc, bf, txq, padsize)) {
-		bf->skb = NULL;
-		spin_lock_irqsave(&sc->txbuflock, flags);
-		list_add_tail(&bf->list, &sc->txbuf);
-		sc->txbuf_len++;
-		spin_unlock_irqrestore(&sc->txbuflock, flags);
-		goto drop_packet;
-	}
-	return NETDEV_TX_OK;
+	stop_tasklets(sc);
 
-drop_packet:
-	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
+	cancel_delayed_work_sync(&sc->tx_complete_work);
+
+	ath5k_rfkill_hw_stop(sc->ah);
+
+	return ret;
 }
 
 /*
@@ -3024,6 +2594,208 @@
 	mutex_unlock(&sc->lock);
 }
 
+static int
+ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
+	struct ath5k_txq *txq;
+	u8 mac[ETH_ALEN] = {};
+	int ret;
+
+	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
+
+	/*
+	 * Check if the MAC has multi-rate retry support.
+	 * We do this by trying to setup a fake extended
+	 * descriptor.  MACs that don't have support will
+	 * return false w/o doing anything.  MACs that do
+	 * support it will return true w/o doing anything.
+	 */
+	ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0);
+
+	if (ret < 0)
+		goto err;
+	if (ret > 0)
+		__set_bit(ATH_STAT_MRRETRY, sc->status);
+
+	/*
+	 * Collect the channel list.  The 802.11 layer
+	 * is resposible for filtering this list based
+	 * on settings like the phy mode and regulatory
+	 * domain restrictions.
+	 */
+	ret = ath5k_setup_bands(hw);
+	if (ret) {
+		ATH5K_ERR(sc, "can't get channels\n");
+		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.
+	 */
+	ret = ath5k_desc_alloc(sc, pdev);
+	if (ret) {
+		ATH5K_ERR(sc, "can't allocate descriptors\n");
+		goto err;
+	}
+
+	/*
+	 * Allocate hardware transmit queues: one queue for
+	 * beacon frames and one data queue for each QoS
+	 * priority.  Note that hw functions handle resetting
+	 * these queues at the needed time.
+	 */
+	ret = ath5k_beaconq_setup(ah);
+	if (ret < 0) {
+		ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
+		goto err_desc;
+	}
+	sc->bhalq = ret;
+	sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0);
+	if (IS_ERR(sc->cabq)) {
+		ATH5K_ERR(sc, "can't setup cab queue\n");
+		ret = PTR_ERR(sc->cabq);
+		goto err_bhal;
+	}
+
+	/* This order matches mac80211's queue priority, so we can
+	 * directly use the mac80211 queue number without any mapping */
+	txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO);
+	if (IS_ERR(txq)) {
+		ATH5K_ERR(sc, "can't setup xmit queue\n");
+		ret = PTR_ERR(txq);
+		goto err_queues;
+	}
+	txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI);
+	if (IS_ERR(txq)) {
+		ATH5K_ERR(sc, "can't setup xmit queue\n");
+		ret = PTR_ERR(txq);
+		goto err_queues;
+	}
+	txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+	if (IS_ERR(txq)) {
+		ATH5K_ERR(sc, "can't setup xmit queue\n");
+		ret = PTR_ERR(txq);
+		goto err_queues;
+	}
+	txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
+	if (IS_ERR(txq)) {
+		ATH5K_ERR(sc, "can't setup xmit queue\n");
+		ret = PTR_ERR(txq);
+		goto err_queues;
+	}
+	hw->queues = 4;
+
+	tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
+	tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
+	tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
+	tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
+	tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
+
+	INIT_WORK(&sc->reset_work, ath5k_reset_work);
+	INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work);
+
+	ret = ath5k_eeprom_read_mac(ah, mac);
+	if (ret) {
+		ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
+			sc->pdev->device);
+		goto err_queues;
+	}
+
+	SET_IEEE80211_PERM_ADDR(hw, mac);
+	memcpy(&sc->lladdr, mac, ETH_ALEN);
+	/* All MAC address bits matter for ACKs */
+	ath5k_update_bssid_mask_and_opmode(sc, NULL);
+
+	regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
+	ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
+	if (ret) {
+		ATH5K_ERR(sc, "can't initialize regulatory system\n");
+		goto err_queues;
+	}
+
+	ret = ieee80211_register_hw(hw);
+	if (ret) {
+		ATH5K_ERR(sc, "can't register ieee80211 hw\n");
+		goto err_queues;
+	}
+
+	if (!ath_is_world_regd(regulatory))
+		regulatory_hint(hw->wiphy, regulatory->alpha2);
+
+	ath5k_init_leds(sc);
+
+	ath5k_sysfs_register(sc);
+
+	return 0;
+err_queues:
+	ath5k_txq_release(sc);
+err_bhal:
+	ath5k_hw_release_tx_queue(ah, sc->bhalq);
+err_desc:
+	ath5k_desc_free(sc, pdev);
+err:
+	return ret;
+}
+
+static void
+ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	/*
+	 * NB: the order of these is important:
+	 * o call the 802.11 layer before detaching ath5k_hw to
+	 *   ensure callbacks into the driver to delete global
+	 *   key cache entries can be handled
+	 * o reclaim the tx queue data structures after calling
+	 *   the 802.11 layer as we'll get called back to reclaim
+	 *   node state and potentially want to use them
+	 * o to cleanup the tx queues the hal is called, so detach
+	 *   it last
+	 * XXX: ??? detach ath5k_hw ???
+	 * Other than that, it's straightforward...
+	 */
+	ieee80211_unregister_hw(hw);
+	ath5k_desc_free(sc, pdev);
+	ath5k_txq_release(sc);
+	ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
+	ath5k_unregister_leds(sc);
+
+	ath5k_sysfs_unregister(sc);
+	/*
+	 * NB: can't reclaim these until after ieee80211_ifdetach
+	 * returns because we'll get called back to reclaim node
+	 * state and potentially want to use them.
+	 */
+}
+
+/********************\
+* Mac80211 functions *
+\********************/
+
+static int
+ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct ath5k_softc *sc = hw->priv;
+	u16 qnum = skb_get_queue_mapping(skb);
+
+	if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
+		dev_kfree_skb_any(skb);
+		return 0;
+	}
+
+	return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
+}
+
 static int ath5k_start(struct ieee80211_hw *hw)
 {
 	return ath5k_init(hw->priv);
@@ -3039,32 +2811,78 @@
 {
 	struct ath5k_softc *sc = hw->priv;
 	int ret;
+	struct ath5k_vif *avf = (void *)vif->drv_priv;
 
 	mutex_lock(&sc->lock);
-	if (sc->vif) {
-		ret = 0;
+
+	if ((vif->type == NL80211_IFTYPE_AP ||
+	     vif->type == NL80211_IFTYPE_ADHOC)
+	    && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) {
+		ret = -ELNRNG;
 		goto end;
 	}
 
-	sc->vif = vif;
+	/* Don't allow other interfaces if one ad-hoc is configured.
+	 * TODO: Fix the problems with ad-hoc and multiple other interfaces.
+	 * We would need to operate the HW in ad-hoc mode to allow TSF updates
+	 * for the IBSS, but this breaks with additional AP or STA interfaces
+	 * at the moment. */
+	if (sc->num_adhoc_vifs ||
+	    (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+		ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
+		ret = -ELNRNG;
+		goto end;
+	}
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_ADHOC:
 	case NL80211_IFTYPE_MESH_POINT:
-	case NL80211_IFTYPE_MONITOR:
-		sc->opmode = vif->type;
+		avf->opmode = vif->type;
 		break;
 	default:
 		ret = -EOPNOTSUPP;
 		goto end;
 	}
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode);
+	sc->nvifs++;
+	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
 
+	/* Assign the vap/adhoc to a beacon xmit slot. */
+	if ((avf->opmode == NL80211_IFTYPE_AP) ||
+	    (avf->opmode == NL80211_IFTYPE_ADHOC)) {
+		int slot;
+
+		WARN_ON(list_empty(&sc->bcbuf));
+		avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf,
+					     list);
+		list_del(&avf->bbuf->list);
+
+		avf->bslot = 0;
+		for (slot = 0; slot < ATH_BCBUF; slot++) {
+			if (!sc->bslot[slot]) {
+				avf->bslot = slot;
+				break;
+			}
+		}
+		BUG_ON(sc->bslot[avf->bslot] != NULL);
+		sc->bslot[avf->bslot] = vif;
+		if (avf->opmode == NL80211_IFTYPE_AP)
+			sc->num_ap_vifs++;
+		else
+			sc->num_adhoc_vifs++;
+	}
+
+	/* Any MAC address is fine, all others are included through the
+	 * filter.
+	 */
+	memcpy(&sc->lladdr, vif->addr, ETH_ALEN);
 	ath5k_hw_set_lladdr(sc->ah, vif->addr);
-	ath5k_mode_setup(sc);
+
+	memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
+
+	ath5k_mode_setup(sc, vif);
 
 	ret = 0;
 end:
@@ -3077,15 +2895,29 @@
 			struct ieee80211_vif *vif)
 {
 	struct ath5k_softc *sc = hw->priv;
-	u8 mac[ETH_ALEN] = {};
+	struct ath5k_vif *avf = (void *)vif->drv_priv;
+	unsigned int i;
 
 	mutex_lock(&sc->lock);
-	if (sc->vif != vif)
-		goto end;
+	sc->nvifs--;
 
-	ath5k_hw_set_lladdr(sc->ah, mac);
-	sc->vif = NULL;
-end:
+	if (avf->bbuf) {
+		ath5k_txbuf_free_skb(sc, avf->bbuf);
+		list_add_tail(&avf->bbuf->list, &sc->bcbuf);
+		for (i = 0; i < ATH_BCBUF; i++) {
+			if (sc->bslot[i] == vif) {
+				sc->bslot[i] = NULL;
+				break;
+			}
+		}
+		avf->bbuf = NULL;
+	}
+	if (avf->opmode == NL80211_IFTYPE_AP)
+		sc->num_ap_vifs--;
+	else if (avf->opmode == NL80211_IFTYPE_ADHOC)
+		sc->num_adhoc_vifs--;
+
+	ath5k_update_bssid_mask_and_opmode(sc, NULL);
 	mutex_unlock(&sc->lock);
 }
 
@@ -3168,6 +3000,19 @@
 	return ((u64)(mfilt[1]) << 32) | mfilt[0];
 }
 
+static bool ath_any_vif_assoc(struct ath5k_softc *sc)
+{
+	struct ath_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,
+						   &iter_data);
+	return iter_data.any_assoc;
+}
+
 #define SUPPORTED_FIF_FLAGS \
 	FIF_PROMISC_IN_BSS |  FIF_ALLMULTI | FIF_FCSFAIL | \
 	FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
@@ -3237,9 +3082,9 @@
 		rfilt |= AR5K_RX_FILTER_PHYERR;
 
 	/* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
-	* and probes for any BSSID, this needs testing */
-	if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
-		rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ;
+	* and probes for any BSSID */
+	if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1))
+		rfilt |= AR5K_RX_FILTER_BEACON;
 
 	/* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
 	 * set we should only pass on control frames for this
@@ -3255,7 +3100,6 @@
 
 	switch (sc->opmode) {
 	case NL80211_IFTYPE_MESH_POINT:
-	case NL80211_IFTYPE_MONITOR:
 		rfilt |= AR5K_RX_FILTER_CONTROL |
 			 AR5K_RX_FILTER_BEACON |
 			 AR5K_RX_FILTER_PROBEREQ |
@@ -3278,7 +3122,7 @@
 
 	/* Set multicast bits */
 	ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
-	/* Set the cached hw filter flags, this will alter actually
+	/* Set the cached hw filter flags, this will later actually
 	 * be set in HW */
 	sc->filter_flags = rfilt;
 
@@ -3298,17 +3142,14 @@
 	if (modparam_nohwcrypt)
 		return -EOPNOTSUPP;
 
-	if (sc->opmode == NL80211_IFTYPE_AP)
-		return -EOPNOTSUPP;
-
-	switch (key->alg) {
-	case ALG_WEP:
-	case ALG_TKIP:
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+	case WLAN_CIPHER_SUITE_TKIP:
 		break;
-	case ALG_CCMP:
-		if (sc->ah->ah_aes_support)
+	case WLAN_CIPHER_SUITE_CCMP:
+		if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)
 			break;
-
 		return -EOPNOTSUPP;
 	default:
 		WARN_ON(1);
@@ -3319,27 +3160,25 @@
 
 	switch (cmd) {
 	case SET_KEY:
-		ret = ath5k_hw_set_key(sc->ah, key->keyidx, key,
-				       sta ? sta->addr : NULL);
-		if (ret) {
-			ATH5K_ERR(sc, "can't set the key\n");
-			goto unlock;
+		ret = ath_key_config(common, vif, sta, key);
+		if (ret >= 0) {
+			key->hw_key_idx = ret;
+			/* push IV and Michael MIC generation to stack */
+			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+			if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
+				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+			if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
+				key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
+			ret = 0;
 		}
-		__set_bit(key->keyidx, common->keymap);
-		key->hw_key_idx = key->keyidx;
-		key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV |
-			       IEEE80211_KEY_FLAG_GENERATE_MMIC);
 		break;
 	case DISABLE_KEY:
-		ath5k_hw_reset_key(sc->ah, key->keyidx);
-		__clear_bit(key->keyidx, common->keymap);
+		ath_key_delete(common, key);
 		break;
 	default:
 		ret = -EINVAL;
-		goto unlock;
 	}
 
-unlock:
 	mmiowb();
 	mutex_unlock(&sc->lock);
 	return ret;
@@ -3409,43 +3248,6 @@
 		ath5k_hw_reset_tsf(sc->ah);
 }
 
-/*
- * Updates the beacon that is sent by ath5k_beacon_send.  For adhoc,
- * this is called only once at config_bss time, for AP we do it every
- * SWBA interrupt so that the TIM will reflect buffered frames.
- *
- * Called with the beacon lock.
- */
-static int
-ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-	int ret;
-	struct ath5k_softc *sc = hw->priv;
-	struct sk_buff *skb;
-
-	if (WARN_ON(!vif)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	skb = ieee80211_beacon_get(hw, vif);
-
-	if (!skb) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	ath5k_debug_dump_skb(sc, skb, "BC  ", 1);
-
-	ath5k_txbuf_free_skb(sc, sc->bbuf);
-	sc->bbuf->skb = skb;
-	ret = ath5k_beacon_setup(sc, sc->bbuf);
-	if (ret)
-		sc->bbuf->skb = NULL;
-out:
-	return ret;
-}
-
 static void
 set_beacon_filter(struct ieee80211_hw *hw, bool enable)
 {
@@ -3466,20 +3268,19 @@
 				    struct ieee80211_bss_conf *bss_conf,
 				    u32 changes)
 {
+	struct ath5k_vif *avf = (void *)vif->drv_priv;
 	struct ath5k_softc *sc = hw->priv;
 	struct ath5k_hw *ah = sc->ah;
 	struct ath_common *common = ath5k_hw_common(ah);
 	unsigned long flags;
 
 	mutex_lock(&sc->lock);
-	if (WARN_ON(sc->vif != vif))
-		goto unlock;
 
 	if (changes & BSS_CHANGED_BSSID) {
 		/* Cache for later use during resets */
 		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
 		common->curaid = 0;
-		ath5k_hw_set_associd(ah);
+		ath5k_hw_set_bssid(ah);
 		mmiowb();
 	}
 
@@ -3487,7 +3288,12 @@
 		sc->bintval = bss_conf->beacon_int;
 
 	if (changes & BSS_CHANGED_ASSOC) {
-		sc->assoc = bss_conf->assoc;
+		avf->assoc = bss_conf->assoc;
+		if (bss_conf->assoc)
+			sc->assoc = bss_conf->assoc;
+		else
+			sc->assoc = ath_any_vif_assoc(sc);
+
 		if (sc->opmode == NL80211_IFTYPE_STATION)
 			set_beacon_filter(hw, sc->assoc);
 		ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
@@ -3497,7 +3303,7 @@
 				  "Bss Info ASSOC %d, bssid: %pM\n",
 				  bss_conf->aid, common->curbssid);
 			common->curaid = bss_conf->aid;
-			ath5k_hw_set_associd(ah);
+			ath5k_hw_set_bssid(ah);
 			/* Once ANI is available you would start it here */
 		}
 	}
@@ -3515,7 +3321,6 @@
 		       BSS_CHANGED_BEACON_INT))
 		ath5k_beacon_config(sc);
 
- unlock:
 	mutex_unlock(&sc->lock);
 }
 
@@ -3551,3 +3356,399 @@
 	ath5k_hw_set_coverage_class(sc->ah, coverage_class);
 	mutex_unlock(&sc->lock);
 }
+
+static int ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
+			 const struct ieee80211_tx_queue_params *params)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_txq_info qi;
+	int ret = 0;
+
+	if (queue >= ah->ah_capabilities.cap_queues.q_tx_num)
+		return 0;
+
+	mutex_lock(&sc->lock);
+
+	ath5k_hw_get_tx_queueprops(ah, queue, &qi);
+
+	qi.tqi_aifs = params->aifs;
+	qi.tqi_cw_min = params->cw_min;
+	qi.tqi_cw_max = params->cw_max;
+	qi.tqi_burst_time = params->txop;
+
+	ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
+		  "Configure tx [queue %d],  "
+		  "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
+		  queue, params->aifs, params->cw_min,
+		  params->cw_max, params->txop);
+
+	if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) {
+		ATH5K_ERR(sc,
+			  "Unable to update hardware queue %u!\n", queue);
+		ret = -EIO;
+	} else
+		ath5k_hw_reset_tx_queue(ah, queue);
+
+	mutex_unlock(&sc->lock);
+
+	return ret;
+}
+
+static const struct ieee80211_ops ath5k_hw_ops = {
+	.tx 		= ath5k_tx,
+	.start 		= ath5k_start,
+	.stop 		= ath5k_stop,
+	.add_interface 	= ath5k_add_interface,
+	.remove_interface = ath5k_remove_interface,
+	.config 	= ath5k_config,
+	.prepare_multicast = ath5k_prepare_multicast,
+	.configure_filter = ath5k_configure_filter,
+	.set_key 	= ath5k_set_key,
+	.get_stats 	= ath5k_get_stats,
+	.get_survey	= ath5k_get_survey,
+	.conf_tx	= ath5k_conf_tx,
+	.get_tsf 	= ath5k_get_tsf,
+	.set_tsf 	= ath5k_set_tsf,
+	.reset_tsf 	= ath5k_reset_tsf,
+	.bss_info_changed = ath5k_bss_info_changed,
+	.sw_scan_start	= ath5k_sw_scan_start,
+	.sw_scan_complete = ath5k_sw_scan_complete,
+	.set_coverage_class = ath5k_set_coverage_class,
+};
+
+/********************\
+* PCI Initialization *
+\********************/
+
+static int __devinit
+ath5k_pci_probe(struct pci_dev *pdev,
+		const struct pci_device_id *id)
+{
+	void __iomem *mem;
+	struct ath5k_softc *sc;
+	struct ath_common *common;
+	struct ieee80211_hw *hw;
+	int ret;
+	u8 csz;
+
+	/*
+	 * L0s needs to be disabled on all ath5k cards.
+	 *
+	 * For distributions shipping with CONFIG_PCIEASPM (this will be enabled
+	 * by default in the future in 2.6.36) this will also mean both L1 and
+	 * L0s will be disabled when a pre 1.1 PCIe device is detected. We do
+	 * know L1 works correctly even for all ath5k pre 1.1 PCIe devices
+	 * though but cannot currently undue the effect of a blacklist, for
+	 * details you can read pcie_aspm_sanity_check() and see how it adjusts
+	 * the device link capability.
+	 *
+	 * It may be possible in the future to implement some PCI API to allow
+	 * drivers to override blacklists for pre 1.1 PCIe but for now it is
+	 * best to accept that both L0s and L1 will be disabled completely for
+	 * distributions shipping with CONFIG_PCIEASPM rather than having this
+	 * issue present. Motivation for adding this new API will be to help
+	 * with power consumption for some of these devices.
+	 */
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "can't enable device\n");
+		goto err;
+	}
+
+	/* XXX 32-bit addressing only */
+	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(&pdev->dev, "32-bit DMA not available\n");
+		goto err_dis;
+	}
+
+	/*
+	 * Cache line size is used to size and align various
+	 * structures used to communicate with the hardware.
+	 */
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+	if (csz == 0) {
+		/*
+		 * Linux 2.4.18 (at least) writes the cache line size
+		 * register as a 16-bit wide register which is wrong.
+		 * We must have this setup properly for rx buffer
+		 * DMA to work so force a reasonable value here if it
+		 * comes up zero.
+		 */
+		csz = L1_CACHE_BYTES >> 2;
+		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
+	}
+	/*
+	 * The default setting of latency timer yields poor results,
+	 * set it to the value used by other systems.  It may be worth
+	 * tweaking this setting more.
+	 */
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+	/* Enable bus mastering */
+	pci_set_master(pdev);
+
+	/*
+	 * Disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state.
+	 */
+	pci_write_config_byte(pdev, 0x41, 0);
+
+	ret = pci_request_region(pdev, 0, "ath5k");
+	if (ret) {
+		dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
+		goto err_dis;
+	}
+
+	mem = pci_iomap(pdev, 0, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
+		ret = -EIO;
+		goto err_reg;
+	}
+
+	/*
+	 * Allocate hw (mac80211 main struct)
+	 * and hw->priv (driver private data)
+	 */
+	hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
+	if (hw == NULL) {
+		dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
+		ret = -ENOMEM;
+		goto err_map;
+	}
+
+	dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
+
+	/* Initialize driver private data */
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+		    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+		    IEEE80211_HW_SIGNAL_DBM;
+
+	hw->wiphy->interface_modes =
+		BIT(NL80211_IFTYPE_AP) |
+		BIT(NL80211_IFTYPE_STATION) |
+		BIT(NL80211_IFTYPE_ADHOC) |
+		BIT(NL80211_IFTYPE_MESH_POINT);
+
+	hw->extra_tx_headroom = 2;
+	hw->channel_change_time = 5000;
+	sc = hw->priv;
+	sc->hw = hw;
+	sc->pdev = pdev;
+
+	/*
+	 * Mark the device as detached to avoid processing
+	 * interrupts until setup is complete.
+	 */
+	__set_bit(ATH_STAT_INVALID, sc->status);
+
+	sc->iobase = mem; /* So we can unmap it on detach */
+	sc->opmode = NL80211_IFTYPE_STATION;
+	sc->bintval = 1000;
+	mutex_init(&sc->lock);
+	spin_lock_init(&sc->rxbuflock);
+	spin_lock_init(&sc->txbuflock);
+	spin_lock_init(&sc->block);
+
+	/* Set private data */
+	pci_set_drvdata(pdev, sc);
+
+	/* Setup interrupt handler */
+	ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
+	if (ret) {
+		ATH5K_ERR(sc, "request_irq failed\n");
+		goto err_free;
+	}
+
+	/* If we passed the test, malloc an ath5k_hw struct */
+	sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
+	if (!sc->ah) {
+		ret = -ENOMEM;
+		ATH5K_ERR(sc, "out of memory\n");
+		goto err_irq;
+	}
+
+	sc->ah->ah_sc = sc;
+	sc->ah->ah_iobase = sc->iobase;
+	common = ath5k_hw_common(sc->ah);
+	common->ops = &ath5k_common_ops;
+	common->ah = sc->ah;
+	common->hw = hw;
+	common->cachelsz = csz << 2; /* convert to bytes */
+
+	/* Initialize device */
+	ret = ath5k_hw_attach(sc);
+	if (ret) {
+		goto err_free_ah;
+	}
+
+	/* set up multi-rate retry capabilities */
+	if (sc->ah->ah_version == AR5K_AR5212) {
+		hw->max_rates = 4;
+		hw->max_rate_tries = 11;
+	}
+
+	hw->vif_data_size = sizeof(struct ath5k_vif);
+
+	/* Finish private driver data initialization */
+	ret = ath5k_attach(pdev, hw);
+	if (ret)
+		goto err_ah;
+
+	ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
+			ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
+					sc->ah->ah_mac_srev,
+					sc->ah->ah_phy_revision);
+
+	if (!sc->ah->ah_single_chip) {
+		/* Single chip radio (!RF5111) */
+		if (sc->ah->ah_radio_5ghz_revision &&
+			!sc->ah->ah_radio_2ghz_revision) {
+			/* No 5GHz support -> report 2GHz radio */
+			if (!test_bit(AR5K_MODE_11A,
+				sc->ah->ah_capabilities.cap_mode)) {
+				ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+					ath5k_chip_name(AR5K_VERSION_RAD,
+						sc->ah->ah_radio_5ghz_revision),
+						sc->ah->ah_radio_5ghz_revision);
+			/* No 2GHz support (5110 and some
+			 * 5Ghz only cards) -> report 5Ghz radio */
+			} else if (!test_bit(AR5K_MODE_11B,
+				sc->ah->ah_capabilities.cap_mode)) {
+				ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+					ath5k_chip_name(AR5K_VERSION_RAD,
+						sc->ah->ah_radio_5ghz_revision),
+						sc->ah->ah_radio_5ghz_revision);
+			/* Multiband radio */
+			} else {
+				ATH5K_INFO(sc, "RF%s multiband radio found"
+					" (0x%x)\n",
+					ath5k_chip_name(AR5K_VERSION_RAD,
+						sc->ah->ah_radio_5ghz_revision),
+						sc->ah->ah_radio_5ghz_revision);
+			}
+		}
+		/* Multi chip radio (RF5111 - RF2111) ->
+		 * report both 2GHz/5GHz radios */
+		else if (sc->ah->ah_radio_5ghz_revision &&
+				sc->ah->ah_radio_2ghz_revision){
+			ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+				ath5k_chip_name(AR5K_VERSION_RAD,
+					sc->ah->ah_radio_5ghz_revision),
+					sc->ah->ah_radio_5ghz_revision);
+			ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+				ath5k_chip_name(AR5K_VERSION_RAD,
+					sc->ah->ah_radio_2ghz_revision),
+					sc->ah->ah_radio_2ghz_revision);
+		}
+	}
+
+	ath5k_debug_init_device(sc);
+
+	/* ready to process interrupts */
+	__clear_bit(ATH_STAT_INVALID, sc->status);
+
+	return 0;
+err_ah:
+	ath5k_hw_detach(sc->ah);
+err_free_ah:
+	kfree(sc->ah);
+err_irq:
+	free_irq(pdev->irq, sc);
+err_free:
+	ieee80211_free_hw(hw);
+err_map:
+	pci_iounmap(pdev, mem);
+err_reg:
+	pci_release_region(pdev, 0);
+err_dis:
+	pci_disable_device(pdev);
+err:
+	return ret;
+}
+
+static void __devexit
+ath5k_pci_remove(struct pci_dev *pdev)
+{
+	struct ath5k_softc *sc = pci_get_drvdata(pdev);
+
+	ath5k_debug_finish_device(sc);
+	ath5k_detach(pdev, sc->hw);
+	ath5k_hw_detach(sc->ah);
+	kfree(sc->ah);
+	free_irq(pdev->irq, sc);
+	pci_iounmap(pdev, sc->iobase);
+	pci_release_region(pdev, 0);
+	pci_disable_device(pdev);
+	ieee80211_free_hw(sc->hw);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int ath5k_pci_suspend(struct device *dev)
+{
+	struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
+
+	ath5k_led_off(sc);
+	return 0;
+}
+
+static int ath5k_pci_resume(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct ath5k_softc *sc = pci_get_drvdata(pdev);
+
+	/*
+	 * Suspend/Resume resets the PCI configuration space, so we have to
+	 * re-disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state
+	 */
+	pci_write_config_byte(pdev, 0x41, 0);
+
+	ath5k_led_enable(sc);
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
+#define ATH5K_PM_OPS	(&ath5k_pm_ops)
+#else
+#define ATH5K_PM_OPS	NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static struct pci_driver ath5k_pci_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= ath5k_pci_id_table,
+	.probe		= ath5k_pci_probe,
+	.remove		= __devexit_p(ath5k_pci_remove),
+	.driver.pm	= ATH5K_PM_OPS,
+};
+
+/*
+ * Module init/exit functions
+ */
+static int __init
+init_ath5k_pci(void)
+{
+	int ret;
+
+	ret = pci_register_driver(&ath5k_pci_driver);
+	if (ret) {
+		printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit
+exit_ath5k_pci(void)
+{
+	pci_unregister_driver(&ath5k_pci_driver);
+}
+
+module_init(init_ath5k_pci);
+module_exit(exit_ath5k_pci);
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index dc1241f..9a79773 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -58,7 +58,9 @@
 
 #define	ATH_RXBUF	40		/* number of RX buffers */
 #define	ATH_TXBUF	200		/* number of TX buffers */
-#define ATH_BCBUF	1		/* number of beacon buffers */
+#define ATH_BCBUF	4		/* number of beacon buffers */
+#define ATH5K_TXQ_LEN_MAX	(ATH_TXBUF / 4)		/* bufs per queue */
+#define ATH5K_TXQ_LEN_LOW	(ATH5K_TXQ_LEN_MAX / 2)	/* low mark */
 
 struct ath5k_buf {
 	struct list_head	list;
@@ -83,6 +85,9 @@
 	struct list_head	q;	/* transmit queue */
 	spinlock_t		lock;	/* lock on q and link */
 	bool			setup;
+	int			txq_len; /* number of queued buffers */
+	bool			txq_poll_mark;
+	unsigned int		txq_stuck;	/* informational counter */
 };
 
 #define ATH5K_LED_MAX_NAME_LEN 31
@@ -116,6 +121,13 @@
 	/* frame errors */
 	unsigned int rx_all_count;	/* all RX frames, including errors */
 	unsigned int tx_all_count;	/* all TX frames, including errors */
+	unsigned int rx_bytes_count;	/* all RX bytes, including errored pks
+					 * and the MAC headers for each packet
+					 */
+	unsigned int tx_bytes_count;	/* all TX bytes, including errored pkts
+					 * and the MAC headers and padding for
+					 * each packet.
+					 */
 	unsigned int rxerr_crc;
 	unsigned int rxerr_phy;
 	unsigned int rxerr_phy_code[32];
@@ -146,6 +158,14 @@
 #define ATH_CHAN_MAX	(14+14+14+252+20)
 #endif
 
+struct ath5k_vif {
+	bool			assoc; /* are we associated or not */
+	enum nl80211_iftype	opmode;
+	int			bslot;
+	struct ath5k_buf	*bbuf; /* beacon buffer */
+	u8			lladdr[ETH_ALEN];
+};
+
 /* Software Carrier, keeps track of the driver state
  * associated with an instance of a device */
 struct ath5k_softc {
@@ -182,10 +202,11 @@
 	unsigned int		curmode;	/* current phy mode */
 	struct ieee80211_channel *curchan;	/* current h/w channel */
 
-	struct ieee80211_vif *vif;
+	u16			nvifs;
 
 	enum ath5k_int		imask;		/* interrupt mask copy */
 
+	u8			lladdr[ETH_ALEN];
 	u8			bssidmask[ETH_ALEN];
 
 	unsigned int		led_pin,	/* GPIO pin for driving LED */
@@ -204,7 +225,6 @@
 	spinlock_t		txbuflock;
 	unsigned int		txbuf_len;	/* buf count in txbuf list */
 	struct ath5k_txq	txqs[AR5K_NUM_TX_QUEUES];	/* tx queues */
-	struct ath5k_txq	*txq;		/* main tx queue */
 	struct tasklet_struct	txtq;		/* tx intr tasklet */
 	struct ath5k_led	tx_led;		/* tx led */
 
@@ -214,7 +234,10 @@
 
 	spinlock_t		block;		/* protects beacon */
 	struct tasklet_struct	beacontq;	/* beacon intr tasklet */
-	struct ath5k_buf	*bbuf;		/* beacon buffer */
+	struct list_head	bcbuf;		/* beacon buffer */
+	struct ieee80211_vif	*bslot[ATH_BCBUF];
+	u16			num_ap_vifs;
+	u16			num_adhoc_vifs;
 	unsigned int		bhalq,		/* SW q for outgoing beacons */
 				bmisscount,	/* missed beacon transmits */
 				bintval,	/* beacon interval in TU */
@@ -230,6 +253,8 @@
 
 	struct ath5k_ani_state	ani_state;
 	struct tasklet_struct	ani_tasklet;	/* ANI calibration */
+
+	struct delayed_work	tx_complete_work;
 };
 
 #define ath5k_hw_hasbssidmask(_ah) \
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 4cccc29..acda56e 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -60,6 +60,7 @@
 
 #include "base.h"
 #include "debug.h"
+#include "../debug.h"
 
 static unsigned int ath5k_debug;
 module_param_named(debug, ath5k_debug, uint, 0);
@@ -71,8 +72,6 @@
 #include "reg.h"
 #include "ani.h"
 
-static struct dentry *ath5k_global_debugfs;
-
 static int ath5k_debugfs_open(struct inode *inode, struct file *file)
 {
 	file->private_data = inode->i_private;
@@ -271,6 +270,7 @@
 	.write = write_file_beacon,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -290,6 +290,7 @@
 	.write = write_file_reset,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 
@@ -312,6 +313,7 @@
 	{ ATH5K_DEBUG_DUMP_TX,	"dumptx",	"print transmit skb content" },
 	{ ATH5K_DEBUG_DUMPBANDS, "dumpbands",	"dump bands" },
 	{ ATH5K_DEBUG_ANI,	"ani",		"adaptive noise immunity" },
+	{ ATH5K_DEBUG_DESC,	"desc",		"descriptor chains" },
 	{ ATH5K_DEBUG_ANY,	"all",		"show all debug levels" },
 };
 
@@ -369,6 +371,7 @@
 	.write = write_file_debug,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -480,6 +483,61 @@
 	.write = write_file_antenna,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+/* debugfs: misc */
+
+static ssize_t read_file_misc(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	char buf[700];
+	unsigned int len = 0;
+	u32 filt = ath5k_hw_get_rx_filter(sc->ah);
+
+	len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n",
+			sc->bssidmask);
+	len += snprintf(buf+len, sizeof(buf)-len, "filter-flags: 0x%x ",
+			filt);
+	if (filt & AR5K_RX_FILTER_UCAST)
+		len += snprintf(buf+len, sizeof(buf)-len, " UCAST");
+	if (filt & AR5K_RX_FILTER_MCAST)
+		len += snprintf(buf+len, sizeof(buf)-len, " MCAST");
+	if (filt & AR5K_RX_FILTER_BCAST)
+		len += snprintf(buf+len, sizeof(buf)-len, " BCAST");
+	if (filt & AR5K_RX_FILTER_CONTROL)
+		len += snprintf(buf+len, sizeof(buf)-len, " CONTROL");
+	if (filt & AR5K_RX_FILTER_BEACON)
+		len += snprintf(buf+len, sizeof(buf)-len, " BEACON");
+	if (filt & AR5K_RX_FILTER_PROM)
+		len += snprintf(buf+len, sizeof(buf)-len, " PROM");
+	if (filt & AR5K_RX_FILTER_XRPOLL)
+		len += snprintf(buf+len, sizeof(buf)-len, " XRPOLL");
+	if (filt & AR5K_RX_FILTER_PROBEREQ)
+		len += snprintf(buf+len, sizeof(buf)-len, " PROBEREQ");
+	if (filt & AR5K_RX_FILTER_PHYERR_5212)
+		len += snprintf(buf+len, sizeof(buf)-len, " PHYERR-5212");
+	if (filt & AR5K_RX_FILTER_RADARERR_5212)
+		len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5212");
+	if (filt & AR5K_RX_FILTER_PHYERR_5211)
+		snprintf(buf+len, sizeof(buf)-len, " PHYERR-5211");
+	if (filt & AR5K_RX_FILTER_RADARERR_5211)
+		len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211");
+
+	len += snprintf(buf+len, sizeof(buf)-len, "\nopmode: %s (%d)\n",
+			ath_opmode_to_string(sc->opmode), sc->opmode);
+
+	if (len > sizeof(buf))
+		len = sizeof(buf);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_misc = {
+	.read = read_file_misc,
+	.open = ath5k_debugfs_open,
+	.owner = THIS_MODULE,
 };
 
 
@@ -533,6 +591,8 @@
 				st->rxerr_jumbo*100/st->rx_all_count : 0);
 	len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n",
 			st->rx_all_count);
+	len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%d\n",
+			st->rx_bytes_count);
 
 	len += snprintf(buf+len, sizeof(buf)-len,
 			"\nTX\n---------------------\n");
@@ -550,6 +610,8 @@
 				st->txerr_filt*100/st->tx_all_count : 0);
 	len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n",
 			st->tx_all_count);
+	len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%d\n",
+			st->tx_bytes_count);
 
 	if (len > sizeof(buf))
 		len = sizeof(buf);
@@ -591,6 +653,7 @@
 	.write = write_file_frameerrors,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -657,20 +720,21 @@
 	len += snprintf(buf+len, sizeof(buf)-len,
 			"beacon RSSI average:\t%d\n",
 			sc->ah->ah_beacon_rssi_avg.avg);
+
+#define CC_PRINT(_struct, _field) \
+	_struct._field, \
+	_struct.cycles > 0 ? \
+	_struct._field*100/_struct.cycles : 0
+
 	len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n",
-			as->pfc_tx,
-			as->pfc_cycles > 0 ?
-			as->pfc_tx*100/as->pfc_cycles : 0);
+			CC_PRINT(as->last_cc, tx_frame));
 	len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n",
-			as->pfc_rx,
-			as->pfc_cycles > 0 ?
-			as->pfc_rx*100/as->pfc_cycles : 0);
+			CC_PRINT(as->last_cc, rx_frame));
 	len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n",
-			as->pfc_busy,
-			as->pfc_cycles > 0 ?
-			as->pfc_busy*100/as->pfc_cycles : 0);
+			CC_PRINT(as->last_cc, rx_busy));
+#undef CC_PRINT
 	len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n",
-			as->pfc_cycles);
+			as->last_cc.cycles);
 	len += snprintf(buf+len, sizeof(buf)-len,
 			"listen time\t\t%d\tlast: %d\n",
 			as->listen_time, as->last_listen);
@@ -748,6 +812,7 @@
 	.write = write_file_ani,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -762,7 +827,7 @@
 
 	struct ath5k_txq *txq;
 	struct ath5k_buf *bf, *bf0;
-	int i, n = 0;
+	int i, n;
 
 	len += snprintf(buf+len, sizeof(buf)-len,
 			"available txbuffers: %d\n", sc->txbuf_len);
@@ -776,9 +841,16 @@
 		if (!txq->setup)
 			continue;
 
+		n = 0;
+		spin_lock_bh(&txq->lock);
 		list_for_each_entry_safe(bf, bf0, &txq->q, list)
 			n++;
-		len += snprintf(buf+len, sizeof(buf)-len, "  len: %d\n", n);
+		spin_unlock_bh(&txq->lock);
+
+		len += snprintf(buf+len, sizeof(buf)-len,
+				"  len: %d bufs: %d\n", txq->txq_len, n);
+		len += snprintf(buf+len, sizeof(buf)-len,
+				"  stuck: %d\n", txq->txq_stuck);
 	}
 
 	if (len > sizeof(buf))
@@ -811,24 +883,17 @@
 	.write = write_file_queue,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
-/* init */
-
-void
-ath5k_debug_init(void)
-{
-	ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL);
-}
-
 void
 ath5k_debug_init_device(struct ath5k_softc *sc)
 {
 	sc->debug.level = ath5k_debug;
 
-	sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
-				ath5k_global_debugfs);
+	sc->debug.debugfs_phydir = debugfs_create_dir("ath5k",
+				sc->hw->wiphy->debugfsdir);
 
 	sc->debug.debugfs_debug = debugfs_create_file("debug",
 				S_IWUSR | S_IRUSR,
@@ -848,6 +913,10 @@
 				S_IWUSR | S_IRUSR,
 				sc->debug.debugfs_phydir, sc, &fops_antenna);
 
+	sc->debug.debugfs_misc = debugfs_create_file("misc",
+				S_IRUSR,
+				sc->debug.debugfs_phydir, sc, &fops_misc);
+
 	sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors",
 				S_IWUSR | S_IRUSR,
 				sc->debug.debugfs_phydir, sc,
@@ -865,12 +934,6 @@
 }
 
 void
-ath5k_debug_finish(void)
-{
-	debugfs_remove(ath5k_global_debugfs);
-}
-
-void
 ath5k_debug_finish_device(struct ath5k_softc *sc)
 {
 	debugfs_remove(sc->debug.debugfs_debug);
@@ -878,6 +941,7 @@
 	debugfs_remove(sc->debug.debugfs_beacon);
 	debugfs_remove(sc->debug.debugfs_reset);
 	debugfs_remove(sc->debug.debugfs_antenna);
+	debugfs_remove(sc->debug.debugfs_misc);
 	debugfs_remove(sc->debug.debugfs_frameerrors);
 	debugfs_remove(sc->debug.debugfs_ani);
 	debugfs_remove(sc->debug.debugfs_queue);
@@ -955,7 +1019,7 @@
 	struct ath5k_rx_status rs = {};
 	int status;
 
-	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
+	if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
 		return;
 
 	printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
@@ -997,7 +1061,7 @@
 	struct ath5k_tx_status ts = {};
 	int done;
 
-	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
+	if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
 		return;
 
 	done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index 606ae94..236edbd 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -75,6 +75,7 @@
 	struct dentry		*debugfs_beacon;
 	struct dentry		*debugfs_reset;
 	struct dentry		*debugfs_antenna;
+	struct dentry		*debugfs_misc;
 	struct dentry		*debugfs_frameerrors;
 	struct dentry		*debugfs_ani;
 	struct dentry		*debugfs_queue;
@@ -95,6 +96,7 @@
  * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
  * @ATH5K_DEBUG_DUMPBANDS: dump bands
  * @ATH5K_DEBUG_TRACE: trace function calls
+ * @ATH5K_DEBUG_DESC: descriptor setup
  * @ATH5K_DEBUG_ANY: show at any debug level
  *
  * The debug level is used to control the amount and type of debugging output
@@ -117,6 +119,7 @@
 	ATH5K_DEBUG_DUMP_TX	= 0x00000200,
 	ATH5K_DEBUG_DUMPBANDS	= 0x00000400,
 	ATH5K_DEBUG_ANI		= 0x00002000,
+	ATH5K_DEBUG_DESC	= 0x00004000,
 	ATH5K_DEBUG_ANY		= 0xffffffff
 };
 
@@ -135,15 +138,9 @@
 	} while (0)
 
 void
-ath5k_debug_init(void);
-
-void
 ath5k_debug_init_device(struct ath5k_softc *sc);
 
 void
-ath5k_debug_finish(void);
-
-void
 ath5k_debug_finish_device(struct ath5k_softc *sc);
 
 void
@@ -171,15 +168,9 @@
 {}
 
 static inline void
-ath5k_debug_init(void) {}
-
-static inline void
 ath5k_debug_init_device(struct ath5k_softc *sc) {}
 
 static inline void
-ath5k_debug_finish(void) {}
-
-static inline void
 ath5k_debug_finish_device(struct ath5k_softc *sc) {}
 
 static inline void
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
index 484f318..923c9ca 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -244,7 +244,7 @@
 
 			/* Force channel idle high */
 			AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
-					AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+					AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
 
 			/* Wait a while and disable mechanism */
 			udelay(200);
@@ -261,7 +261,7 @@
 			} while (--i && pending);
 
 			AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
-					AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+					AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
 		}
 
 		/* Clear register */
@@ -377,11 +377,11 @@
  *
  * This function increases/decreases the tx trigger level for the tx fifo
  * buffer (aka FIFO threshold) that is used to indicate when PCU flushes
- * the buffer and transmits it's data. Lowering this results sending small
+ * the buffer and transmits its data. Lowering this results sending small
  * frames more quickly but can lead to tx underruns, raising it a lot can
  * result other problems (i think bmiss is related). Right now we start with
  * the lowest possible (64Bytes) and if we get tx underrun we increase it using
- * the increase flag. Returns -EIO if we have have reached maximum/minimum.
+ * the increase flag. Returns -EIO if we have reached maximum/minimum.
  *
  * XXX: Link this with tx DMA size ?
  * XXX: Use it to save interrupts ?
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index ae316fe..39722dd 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -661,7 +661,7 @@
  * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
  * steps that match with the power values we read from eeprom. On
  * older eeprom versions (< 3.2) these steps are equaly spaced at
- * 10% of the pcdac curve -until the curve reaches it's maximum-
+ * 10% of the pcdac curve -until the curve reaches its maximum-
  * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
  * these 11 steps are spaced in a different way. This function returns
  * the pcdac steps based on eeprom version and curve min/max so that we
@@ -1113,7 +1113,7 @@
  */
 
 /* For RF2413 power calibration data doesn't start on a fixed location and
- * if a mode is not supported, it's section is missing -not zeroed-.
+ * if a mode is not supported, its section is missing -not zeroed-.
  * So we need to calculate the starting offset for each section by using
  * these two functions */
 
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 86fdb6d..074b4c6 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -137,11 +137,11 @@
  * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
  *
  * @ah: The &struct ath5k_hw
- * @high: Flag to determine if we want to use high transmition rate
+ * @high: Flag to determine if we want to use high transmission rate
  * for ACKs or not
  *
  * If high flag is set, we tell hw to use a set of control rates based on
- * the current transmition rate (check out control_rates array inside reset.c).
+ * the current transmission rate (check out control_rates array inside reset.c).
  * If not hw just uses the lowest rate available for the current modulation
  * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
  */
@@ -207,7 +207,8 @@
  */
 unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
 {
-	return usec * ath5k_hw_get_clockrate(ah);
+	struct ath_common *common = ath5k_hw_common(ah);
+	return usec * common->clockrate;
 }
 
 /**
@@ -216,17 +217,19 @@
  */
 unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
 {
-	return clock / ath5k_hw_get_clockrate(ah);
+	struct ath_common *common = ath5k_hw_common(ah);
+	return clock / common->clockrate;
 }
 
 /**
- * ath5k_hw_get_clockrate - Get the clock rate for current mode
+ * ath5k_hw_set_clockrate - Set common->clockrate for the current channel
  *
  * @ah: The &struct ath5k_hw
  */
-unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah)
+void ath5k_hw_set_clockrate(struct ath5k_hw *ah)
 {
 	struct ieee80211_channel *channel = ah->ah_current_channel;
+	struct ath_common *common = ath5k_hw_common(ah);
 	int clock;
 
 	if (channel->hw_value & CHANNEL_5GHZ)
@@ -240,7 +243,7 @@
 	if (channel->hw_value & CHANNEL_TURBO)
 		clock *= 2;
 
-	return clock;
+	common->clockrate = clock;
 }
 
 /**
@@ -308,27 +311,26 @@
 }
 
 /**
- * ath5k_hw_set_associd - Set BSSID for association
+ * ath5k_hw_set_bssid - Set current BSSID on hw
  *
  * @ah: The &struct ath5k_hw
- * @bssid: BSSID
- * @assoc_id: Assoc id
  *
- * Sets the BSSID which trigers the "SME Join" operation
+ * Sets the current BSSID and BSSID mask we have from the
+ * common struct into the hardware
  */
-void ath5k_hw_set_associd(struct ath5k_hw *ah)
+void ath5k_hw_set_bssid(struct ath5k_hw *ah)
 {
 	struct ath_common *common = ath5k_hw_common(ah);
 	u16 tim_offset = 0;
 
 	/*
-	 * Set simple BSSID mask on 5212
+	 * Set BSSID mask on 5212
 	 */
 	if (ah->ah_version == AR5K_AR5212)
 		ath_hw_setbssidmask(common);
 
 	/*
-	 * Set BSSID which triggers the "SME Join" operation
+	 * Set BSSID
 	 */
 	ath5k_hw_reg_write(ah,
 			   get_unaligned_le32(common->curbssid),
@@ -496,6 +498,10 @@
 {
 	u32 tsf_lower, tsf_upper1, tsf_upper2;
 	int i;
+	unsigned long flags;
+
+	/* This code is time critical - we don't want to be interrupted here */
+	local_irq_save(flags);
 
 	/*
 	 * While reading TSF upper and then lower part, the clock is still
@@ -518,6 +524,8 @@
 		tsf_upper1 = tsf_upper2;
 	}
 
+	local_irq_restore(flags);
+
 	WARN_ON( i == ATH5K_MAX_TSF_READ );
 
 	return (((u64)tsf_upper1 << 32) | tsf_lower);
@@ -601,7 +609,7 @@
 	/* Timer3 marks the end of our ATIM window
 	 * a zero length window is not allowed because
 	 * we 'll get no beacons */
-	timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
+	timer3 = next_beacon + 1;
 
 	/*
 	 * Set the beacon register and enable all timers.
@@ -641,198 +649,95 @@
 
 }
 
-
-/*********************\
-* Key table functions *
-\*********************/
-
-/*
- * Reset a key entry on the table
+/**
+ * ath5k_check_timer_win - Check if timer B is timer A + window
+ *
+ * @a: timer a (before b)
+ * @b: timer b (after a)
+ * @window: difference between a and b
+ * @intval: timers are increased by this interval
+ *
+ * This helper function checks if timer B is timer A + window and covers
+ * cases where timer A or B might have already been updated or wrapped
+ * around (Timers are 16 bit).
+ *
+ * Returns true if O.K.
  */
-int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
+static inline bool
+ath5k_check_timer_win(int a, int b, int window, int intval)
 {
-	unsigned int i, type;
-	u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
-
-	AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
-
-	type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
-
-	for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
-		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
-
-	/* Reset associated MIC entry if TKIP
-	 * is enabled located at offset (entry + 64) */
-	if (type == AR5K_KEYTABLE_TYPE_TKIP) {
-		AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE);
-		for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
-			ath5k_hw_reg_write(ah, 0,
-				AR5K_KEYTABLE_OFF(micentry, i));
-	}
-
 	/*
-	 * Set NULL encryption on AR5212+
-	 *
-	 * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
-	 *       AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
-	 *
-	 * Note2: Windows driver (ndiswrapper) sets this to
-	 *        0x00000714 instead of 0x00000007
+	 * 1.) usually B should be A + window
+	 * 2.) A already updated, B not updated yet
+	 * 3.) A already updated and has wrapped around
+	 * 4.) B has wrapped around
 	 */
-	if (ah->ah_version >= AR5K_AR5211) {
-		ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
-				AR5K_KEYTABLE_TYPE(entry));
-
-		if (type == AR5K_KEYTABLE_TYPE_TKIP) {
-			ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
-				AR5K_KEYTABLE_TYPE(micentry));
-		}
-	}
-
-	return 0;
+	if ((b - a == window) ||				/* 1.) */
+	    (a - b == intval - window) ||			/* 2.) */
+	    ((a | 0x10000) - b == intval - window) ||		/* 3.) */
+	    ((b | 0x10000) - a == window))			/* 4.) */
+		return true; /* O.K. */
+	return false;
 }
 
-static
-int ath5k_keycache_type(const struct ieee80211_key_conf *key)
-{
-	switch (key->alg) {
-	case ALG_TKIP:
-		return AR5K_KEYTABLE_TYPE_TKIP;
-	case ALG_CCMP:
-		return AR5K_KEYTABLE_TYPE_CCM;
-	case ALG_WEP:
-		if (key->keylen == WLAN_KEY_LEN_WEP40)
-			return AR5K_KEYTABLE_TYPE_40;
-		else if (key->keylen == WLAN_KEY_LEN_WEP104)
-			return AR5K_KEYTABLE_TYPE_104;
-		return -EINVAL;
-	default:
-		return -EINVAL;
-	}
-	return -EINVAL;
-}
-
-/*
- * Set a key entry on the table
+/**
+ * ath5k_hw_check_beacon_timers - Check if the beacon timers are correct
+ *
+ * @ah: The &struct ath5k_hw
+ * @intval: beacon interval
+ *
+ * This is a workaround for IBSS mode:
+ *
+ * The need for this function arises from the fact that we have 4 separate
+ * HW timer registers (TIMER0 - TIMER3), which are closely related to the
+ * next beacon target time (NBTT), and that the HW updates these timers
+ * seperately based on the current TSF value. The hardware increments each
+ * timer by the beacon interval, when the local TSF coverted to TU is equal
+ * to the value stored in the timer.
+ *
+ * The reception of a beacon with the same BSSID can update the local HW TSF
+ * at any time - this is something we can't avoid. If the TSF jumps to a
+ * time which is later than the time stored in a timer, this timer will not
+ * be updated until the TSF in TU wraps around at 16 bit (the size of the
+ * timers) and reaches the time which is stored in the timer.
+ *
+ * The problem is that these timers are closely related to TIMER0 (NBTT) and
+ * that they define a time "window". When the TSF jumps between two timers
+ * (e.g. ATIM and NBTT), the one in the past will be left behind (not
+ * updated), while the one in the future will be updated every beacon
+ * interval. This causes the window to get larger, until the TSF wraps
+ * around as described above and the timer which was left behind gets
+ * updated again. But - because the beacon interval is usually not an exact
+ * divisor of the size of the timers (16 bit), an unwanted "window" between
+ * these timers has developed!
+ *
+ * This is especially important with the ATIM window, because during
+ * the ATIM window only ATIM frames and no data frames are allowed to be
+ * sent, which creates transmission pauses after each beacon. This symptom
+ * has been described as "ramping ping" because ping times increase linearly
+ * for some time and then drop down again. A wrong window on the DMA beacon
+ * timer has the same effect, so we check for these two conditions.
+ *
+ * Returns true if O.K.
  */
-int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
-		const struct ieee80211_key_conf *key, const u8 *mac)
+bool
+ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
 {
-	unsigned int i;
-	int keylen;
-	__le32 key_v[5] = {};
-	__le32 key0 = 0, key1 = 0;
-	__le32 *rxmic, *txmic;
-	int keytype;
-	u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
-	bool is_tkip;
-	const u8 *key_ptr;
+	unsigned int nbtt, atim, dma;
 
-	is_tkip = (key->alg == ALG_TKIP);
+	nbtt = ath5k_hw_reg_read(ah, AR5K_TIMER0);
+	atim = ath5k_hw_reg_read(ah, AR5K_TIMER3);
+	dma = ath5k_hw_reg_read(ah, AR5K_TIMER1) >> 3;
 
-	/*
-	 * key->keylen comes in from mac80211 in bytes.
-	 * TKIP is 128 bit + 128 bit mic
-	 */
-	keylen = (is_tkip) ? (128 / 8) : key->keylen;
+	/* NOTE: SWBA is different. Having a wrong window there does not
+	 * stop us from sending data and this condition is catched thru
+	 * other means (SWBA interrupt) */
 
-	if (entry > AR5K_KEYTABLE_SIZE ||
-		(is_tkip && micentry > AR5K_KEYTABLE_SIZE))
-		return -EOPNOTSUPP;
-
-	if (unlikely(keylen > 16))
-		return -EOPNOTSUPP;
-
-	keytype = ath5k_keycache_type(key);
-	if (keytype < 0)
-		return keytype;
-
-	/*
-	 * each key block is 6 bytes wide, written as pairs of
-	 * alternating 32 and 16 bit le values.
-	 */
-	key_ptr = key->key;
-	for (i = 0; keylen >= 6; keylen -= 6) {
-		memcpy(&key_v[i], key_ptr, 6);
-		i += 2;
-		key_ptr += 6;
-	}
-	if (keylen)
-		memcpy(&key_v[i], key_ptr, keylen);
-
-	/* intentionally corrupt key until mic is installed */
-	if (is_tkip) {
-		key0 = key_v[0] = ~key_v[0];
-		key1 = key_v[1] = ~key_v[1];
-	}
-
-	for (i = 0; i < ARRAY_SIZE(key_v); i++)
-		ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
-				AR5K_KEYTABLE_OFF(entry, i));
-
-	ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
-
-	if (is_tkip) {
-		/* Install rx/tx MIC */
-		rxmic = (__le32 *) &key->key[16];
-		txmic = (__le32 *) &key->key[24];
-
-		if (ah->ah_combined_mic) {
-			key_v[0] = rxmic[0];
-			key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16);
-			key_v[2] = rxmic[1];
-			key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff);
-			key_v[4] = txmic[1];
-		} else {
-			key_v[0] = rxmic[0];
-			key_v[1] = 0;
-			key_v[2] = rxmic[1];
-			key_v[3] = 0;
-			key_v[4] = 0;
-		}
-		for (i = 0; i < ARRAY_SIZE(key_v); i++)
-			ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
-				AR5K_KEYTABLE_OFF(micentry, i));
-
-		ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
-			AR5K_KEYTABLE_TYPE(micentry));
-		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry));
-		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry));
-
-		/* restore first 2 words of key */
-		ath5k_hw_reg_write(ah, le32_to_cpu(~key0),
-			AR5K_KEYTABLE_OFF(entry, 0));
-		ath5k_hw_reg_write(ah, le32_to_cpu(~key1),
-			AR5K_KEYTABLE_OFF(entry, 1));
-	}
-
-	return ath5k_hw_set_key_lladdr(ah, entry, mac);
-}
-
-int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
-{
-	u32 low_id, high_id;
-
-	 /* Invalid entry (key table overflow) */
-	AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
-
-	/*
-	 * MAC may be NULL if it's a broadcast key. In this case no need to
-	 * to compute get_unaligned_le32 and get_unaligned_le16 as we
-	 * already know it.
-	 */
-	if (!mac) {
-		low_id = 0xffffffff;
-		high_id = 0xffff | AR5K_KEYTABLE_VALID;
-	} else {
-		low_id = get_unaligned_le32(mac);
-		high_id = get_unaligned_le16(mac + 4) | AR5K_KEYTABLE_VALID;
-	}
-
-	ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry));
-	ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry));
-
-	return 0;
+	if (ath5k_check_timer_win(nbtt, atim, 1, intval) &&
+	    ath5k_check_timer_win(dma, nbtt, AR5K_TUNE_DMA_BEACON_RESP,
+				  intval))
+		return true; /* O.K. */
+	return false;
 }
 
 /**
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 6284c38..2193678 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -115,7 +115,7 @@
 \**********************/
 
 /*
- * This code is used to optimize rf gain on different environments
+ * This code is used to optimize RF gain on different environments
  * (temperature mostly) based on feedback from a power detector.
  *
  * It's only used on RF5111 and RF5112, later RF chips seem to have
@@ -302,7 +302,7 @@
 }
 
 /* Perform gain_F adjustment by choosing the right set
- * of parameters from rf gain optimization ladder */
+ * of parameters from RF gain optimization ladder */
 static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
 {
 	const struct ath5k_gain_opt *go;
@@ -367,7 +367,7 @@
 	return ret;
 }
 
-/* Main callback for thermal rf gain calibration engine
+/* Main callback for thermal RF gain calibration engine
  * Check for a new gain reading and schedule an adjustment
  * if needed.
  *
@@ -433,7 +433,7 @@
 	return ah->ah_gain.g_state;
 }
 
-/* Write initial rf gain table to set the RF sensitivity
+/* Write initial RF gain table to set the RF sensitivity
  * this one works on all RF chips and has nothing to do
  * with gain_F calibration */
 int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
@@ -496,7 +496,7 @@
 
 
 /*
- * Setup RF registers by writing rf buffer on hw
+ * Setup RF registers by writing RF buffer on hw
  */
 int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
 		unsigned int mode)
@@ -571,7 +571,7 @@
 		return -EINVAL;
 	}
 
-	/* If it's the first time we set rf buffer, allocate
+	/* If it's the first time we set RF buffer, allocate
 	 * ah->ah_rf_banks based on ah->ah_rf_banks_size
 	 * we set above */
 	if (ah->ah_rf_banks == NULL) {
@@ -1093,6 +1093,7 @@
 
 	ah->ah_current_channel = channel;
 	ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
+	ath5k_hw_set_clockrate(ah);
 
 	return 0;
 }
@@ -1257,7 +1258,7 @@
 	 * Disable beacons and RX/TX queues, wait
 	 */
 	AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
-		AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+		AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210);
 	beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
 	ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
 
@@ -1336,7 +1337,7 @@
 	 * Re-enable RX/TX and beacons
 	 */
 	AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
-		AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+		AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210);
 	ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
 
 	return 0;
@@ -1377,7 +1378,7 @@
 
 	/* protect against divide by 0 and loss of sign bits */
 	if (i_coffd == 0 || q_coffd < 2)
-		return -1;
+		return 0;
 
 	i_coff = (-iq_corr) / i_coffd;
 	i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */
@@ -1582,7 +1583,7 @@
 			else if (curr_sym_off >= 31 && curr_sym_off <= 46)
 				mag_mask[2] |=
 					plt_mag_map << (curr_sym_off - 31) * 2;
-			else if (curr_sym_off >= 46 && curr_sym_off <= 53)
+			else if (curr_sym_off >= 47 && curr_sym_off <= 53)
 				mag_mask[3] |=
 					plt_mag_map << (curr_sym_off - 47) * 2;
 
@@ -2987,7 +2988,7 @@
 
 
 /*
- * Set transmition power
+ * Set transmission power
  */
 int
 ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
@@ -3035,9 +3036,6 @@
 	/* Limit max power if we have a CTL available */
 	ath5k_get_max_ctl_power(ah, channel);
 
-	/* FIXME: Tx power limit for this regdomain
-	 * XXX: Mac80211/CRDA will do that anyway ? */
-
 	/* FIXME: Antenna reduction stuff */
 
 	/* FIXME: Limit power on turbo modes */
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index 4186ff4..84c717d 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -36,24 +36,58 @@
 }
 
 /*
+ * Make sure cw is a power of 2 minus 1 and smaller than 1024
+ */
+static u16 ath5k_cw_validate(u16 cw_req)
+{
+	u32 cw = 1;
+	cw_req = min(cw_req, (u16)1023);
+
+	while (cw < cw_req)
+		cw = (cw << 1) | 1;
+
+	return cw;
+}
+
+/*
  * Set properties for a transmit queue
  */
 int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
-				const struct ath5k_txq_info *queue_info)
+				const struct ath5k_txq_info *qinfo)
 {
+	struct ath5k_txq_info *qi;
+
 	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 
-	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+	qi = &ah->ah_txq[queue];
+
+	if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE)
 		return -EIO;
 
-	memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info));
+	/* copy and validate values */
+	qi->tqi_type = qinfo->tqi_type;
+	qi->tqi_subtype = qinfo->tqi_subtype;
+	qi->tqi_flags = qinfo->tqi_flags;
+	/*
+	 * According to the docs: Although the AIFS field is 8 bit wide,
+	 * the maximum supported value is 0xFC. Setting it higher than that
+	 * will cause the DCU to hang.
+	 */
+	qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC);
+	qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min);
+	qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max);
+	qi->tqi_cbr_period = qinfo->tqi_cbr_period;
+	qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit;
+	qi->tqi_burst_time = qinfo->tqi_burst_time;
+	qi->tqi_ready_time = qinfo->tqi_ready_time;
 
 	/*XXX: Is this supported on 5210 ?*/
-	if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
-			((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
-			(queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
-			queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
-		ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
+	/*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/
+	if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA &&
+		((qinfo->tqi_subtype == AR5K_WME_AC_VI) ||
+		 (qinfo->tqi_subtype == AR5K_WME_AC_VO))) ||
+	     qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD)
+		qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
 
 	return 0;
 }
@@ -186,7 +220,7 @@
  */
 int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
 {
-	u32 cw_min, cw_max, retry_lg, retry_sh;
+	u32 retry_lg, retry_sh;
 	struct ath5k_txq_info *tq = &ah->ah_txq[queue];
 
 	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
@@ -217,14 +251,13 @@
 		/* Set IFS0 */
 		if (ah->ah_turbo) {
 			 ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
-				(ah->ah_aifs + tq->tqi_aifs) *
-				AR5K_INIT_SLOT_TIME_TURBO) <<
+				tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO) <<
 				AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
 				AR5K_IFS0);
 		} else {
 			ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
-				(ah->ah_aifs + tq->tqi_aifs) *
-				AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
+				tq->tqi_aifs * AR5K_INIT_SLOT_TIME) <<
+				AR5K_IFS0_DIFS_S) |
 				AR5K_INIT_SIFS, AR5K_IFS0);
 		}
 
@@ -248,35 +281,6 @@
 	}
 
 	/*
-	 * Calculate cwmin/max by channel mode
-	 */
-	cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
-	cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
-	ah->ah_aifs = AR5K_TUNE_AIFS;
-	/*XR is only supported on 5212*/
-	if (IS_CHAN_XR(ah->ah_current_channel) &&
-			ah->ah_version == AR5K_AR5212) {
-		cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
-		cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
-		ah->ah_aifs = AR5K_TUNE_AIFS_XR;
-	/*B mode is not supported on 5210*/
-	} else if (IS_CHAN_B(ah->ah_current_channel) &&
-			ah->ah_version != AR5K_AR5210) {
-		cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
-		cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
-		ah->ah_aifs = AR5K_TUNE_AIFS_11B;
-	}
-
-	cw_min = 1;
-	while (cw_min < ah->ah_cw_min)
-		cw_min = (cw_min << 1) | 1;
-
-	cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
-		((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
-	cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
-		((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
-
-	/*
 	 * Calculate and set retry limits
 	 */
 	if (ah->ah_software_retry) {
@@ -292,7 +296,7 @@
 	/*No QCU/DCU [5210]*/
 	if (ah->ah_version == AR5K_AR5210) {
 		ath5k_hw_reg_write(ah,
-			(cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
+			(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,
@@ -314,14 +318,13 @@
 	/*===Rest is also for QCU/DCU only [5211+]===*/
 
 		/*
-		 * Set initial content window (cw_min/cw_max)
+		 * Set contention window (cw_min/cw_max)
 		 * and arbitrated interframe space (aifs)...
 		 */
 		ath5k_hw_reg_write(ah,
-			AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
-			AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
-			AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
-				AR5K_DCU_LCL_IFS_AIFS),
+			AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
+			AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
+			AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
 			AR5K_QUEUE_DFS_LOCAL_IFS(queue));
 
 		/*
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
index 55b4ac6d..a34929f 100644
--- a/drivers/net/wireless/ath/ath5k/reg.h
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -1387,10 +1387,9 @@
 
 
 /*
- * PCU control register
+ * PCU Diagnostic register
  *
- * Only DIS_RX is used in the code, the rest i guess are
- * for tweaking/diagnostics.
+ * Used for tweaking/diagnostics.
  */
 #define AR5K_DIAG_SW_5210		0x8068			/* Register Address [5210] */
 #define AR5K_DIAG_SW_5211		0x8048			/* Register Address [5211+] */
@@ -1399,22 +1398,22 @@
 #define AR5K_DIAG_SW_DIS_WEP_ACK	0x00000001	/* Disable ACKs if WEP key is invalid */
 #define AR5K_DIAG_SW_DIS_ACK		0x00000002	/* Disable ACKs */
 #define AR5K_DIAG_SW_DIS_CTS		0x00000004	/* Disable CTSs */
-#define AR5K_DIAG_SW_DIS_ENC		0x00000008	/* Disable encryption */
-#define AR5K_DIAG_SW_DIS_DEC		0x00000010	/* Disable decryption */
-#define AR5K_DIAG_SW_DIS_TX		0x00000020	/* Disable transmit [5210] */
-#define AR5K_DIAG_SW_DIS_RX_5210	0x00000040	/* Disable recieve */
+#define AR5K_DIAG_SW_DIS_ENC		0x00000008	/* Disable HW encryption */
+#define AR5K_DIAG_SW_DIS_DEC		0x00000010	/* Disable HW decryption */
+#define AR5K_DIAG_SW_DIS_TX_5210	0x00000020	/* Disable transmit [5210] */
+#define AR5K_DIAG_SW_DIS_RX_5210	0x00000040	/* Disable receive */
 #define AR5K_DIAG_SW_DIS_RX_5211	0x00000020
 #define	AR5K_DIAG_SW_DIS_RX		(ah->ah_version == AR5K_AR5210 ? \
 					AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211)
-#define AR5K_DIAG_SW_LOOP_BACK_5210	0x00000080	/* Loopback (i guess it goes with DIS_TX) [5210] */
+#define AR5K_DIAG_SW_LOOP_BACK_5210	0x00000080	/* TX Data Loopback (i guess it goes with DIS_TX) [5210] */
 #define AR5K_DIAG_SW_LOOP_BACK_5211	0x00000040
 #define AR5K_DIAG_SW_LOOP_BACK		(ah->ah_version == AR5K_AR5210 ? \
 					AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211)
-#define AR5K_DIAG_SW_CORR_FCS_5210	0x00000100	/* Corrupted FCS */
+#define AR5K_DIAG_SW_CORR_FCS_5210	0x00000100	/* Generate invalid TX FCS */
 #define AR5K_DIAG_SW_CORR_FCS_5211	0x00000080
 #define AR5K_DIAG_SW_CORR_FCS		(ah->ah_version == AR5K_AR5210 ? \
 					AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211)
-#define AR5K_DIAG_SW_CHAN_INFO_5210	0x00000200	/* Dump channel info */
+#define AR5K_DIAG_SW_CHAN_INFO_5210	0x00000200	/* Add 56 bytes of channel info before the frame data in the RX buffer */
 #define AR5K_DIAG_SW_CHAN_INFO_5211	0x00000100
 #define AR5K_DIAG_SW_CHAN_INFO		(ah->ah_version == AR5K_AR5210 ? \
 					AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211)
@@ -1426,17 +1425,17 @@
 #define AR5K_DIAG_SW_SCVRAM_SEED	0x0003f800	/* [5210] */
 #define AR5K_DIAG_SW_SCRAM_SEED_M	0x0001fc00	/* Scrambler seed mask */
 #define AR5K_DIAG_SW_SCRAM_SEED_S	10
-#define AR5K_DIAG_SW_DIS_SEQ_INC	0x00040000	/* Disable seqnum increment (?)[5210] */
+#define AR5K_DIAG_SW_DIS_SEQ_INC_5210	0x00040000	/* Disable seqnum increment (?)[5210] */
 #define AR5K_DIAG_SW_FRAME_NV0_5210	0x00080000
 #define AR5K_DIAG_SW_FRAME_NV0_5211	0x00020000	/* Accept frames of non-zero protocol number */
 #define	AR5K_DIAG_SW_FRAME_NV0		(ah->ah_version == AR5K_AR5210 ? \
 					AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211)
 #define AR5K_DIAG_SW_OBSPT_M		0x000c0000	/* Observation point select (?) */
 #define AR5K_DIAG_SW_OBSPT_S		18
-#define AR5K_DIAG_SW_RX_CLEAR_HIGH	0x0010000	/* Force RX Clear high */
-#define AR5K_DIAG_SW_IGNORE_CARR_SENSE	0x0020000	/* Ignore virtual carrier sense */
-#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH	0x0040000	/* Force channel idle high */
-#define AR5K_DIAG_SW_PHEAR_ME		0x0080000	/* ??? */
+#define AR5K_DIAG_SW_RX_CLEAR_HIGH	0x00100000	/* Ignore carrier sense */
+#define AR5K_DIAG_SW_IGNORE_CARR_SENSE	0x00200000	/* Ignore virtual carrier sense */
+#define AR5K_DIAG_SW_CHANNEL_IDLE_HIGH	0x00400000	/* Force channel idle high */
+#define AR5K_DIAG_SW_PHEAR_ME		0x00800000	/* ??? */
 
 /*
  * TSF (clock) register (lower 32 bits)
@@ -1822,50 +1821,8 @@
 
 /*===5212 end===*/
 
-/*
- * Key table (WEP) register
- */
-#define AR5K_KEYTABLE_0_5210		0x9000
-#define AR5K_KEYTABLE_0_5211		0x8800
-#define AR5K_KEYTABLE_5210(_n)		(AR5K_KEYTABLE_0_5210 + ((_n) << 5))
-#define AR5K_KEYTABLE_5211(_n)		(AR5K_KEYTABLE_0_5211 + ((_n) << 5))
-#define	AR5K_KEYTABLE(_n)		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n))
-#define AR5K_KEYTABLE_OFF(_n, x)	(AR5K_KEYTABLE(_n) + (x << 2))
-#define AR5K_KEYTABLE_TYPE(_n)		AR5K_KEYTABLE_OFF(_n, 5)
-#define AR5K_KEYTABLE_TYPE_40		0x00000000
-#define AR5K_KEYTABLE_TYPE_104		0x00000001
-#define AR5K_KEYTABLE_TYPE_128		0x00000003
-#define AR5K_KEYTABLE_TYPE_TKIP		0x00000004	/* [5212+] */
-#define AR5K_KEYTABLE_TYPE_AES		0x00000005	/* [5211+] */
-#define AR5K_KEYTABLE_TYPE_CCM		0x00000006	/* [5212+] */
-#define AR5K_KEYTABLE_TYPE_NULL		0x00000007	/* [5211+] */
-#define AR5K_KEYTABLE_ANTENNA		0x00000008	/* [5212+] */
-#define AR5K_KEYTABLE_MAC0(_n)		AR5K_KEYTABLE_OFF(_n, 6)
-#define AR5K_KEYTABLE_MAC1(_n)		AR5K_KEYTABLE_OFF(_n, 7)
-#define AR5K_KEYTABLE_VALID		0x00008000
-
-/* If key type is TKIP and MIC is enabled
- * MIC key goes in offset entry + 64 */
-#define	AR5K_KEYTABLE_MIC_OFFSET	64
-
-/* WEP 40-bit	= 40-bit  entered key + 24 bit IV = 64-bit
- * WEP 104-bit	= 104-bit entered key + 24-bit IV = 128-bit
- * WEP 128-bit	= 128-bit entered key + 24 bit IV = 152-bit
- *
- * Some vendors have introduced bigger WEP keys to address
- * security vulnerabilities in WEP. This includes:
- *
- * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit
- *
- * We can expand this if we find ar5k Atheros cards with a larger
- * key table size.
- */
 #define AR5K_KEYTABLE_SIZE_5210		64
 #define AR5K_KEYTABLE_SIZE_5211		128
-#define	AR5K_KEYTABLE_SIZE		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211)
-
 
 /*===PHY REGISTERS===*/
 
@@ -1911,7 +1868,7 @@
 #define	AR5K_PHY_TURBO			0x9804			/* Register Address */
 #define	AR5K_PHY_TURBO_MODE		0x00000001	/* Enable turbo mode */
 #define	AR5K_PHY_TURBO_SHORT		0x00000002	/* Set short symbols to turbo mode */
-#define	AR5K_PHY_TURBO_MIMO		0x00000004	/* Set turbo for mimo mimo */
+#define	AR5K_PHY_TURBO_MIMO		0x00000004	/* Set turbo for mimo */
 
 /*
  * PHY agility command register
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 498aa28..5b179d0 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -167,7 +167,7 @@
 		 * ieee80211_duration() for a brief description of
 		 * what rate we should choose to TX ACKs. */
 		tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
-							sc->vif, 10, rate));
+							NULL, 10, rate));
 
 		ath5k_hw_reg_write(ah, tx_time, reg);
 
@@ -326,7 +326,7 @@
  * register). After this MAC and Baseband are
  * disabled and a full reset is needed to come
  * back. This way we save as much power as possible
- * without puting the card on full sleep.
+ * without putting the card on full sleep.
  */
 int ath5k_hw_on_hold(struct ath5k_hw *ah)
 {
@@ -344,7 +344,7 @@
 	/*
 	 * Put chipset on warm reset...
 	 *
-	 * Note: puting PCI core on warm reset on PCI-E cards
+	 * Note: putting PCI core on warm reset on PCI-E cards
 	 * results card to hang and always return 0xffff... so
 	 * we ingore that flag for PCI-E cards. On PCI cards
 	 * this flag gets cleared after 64 PCI clocks.
@@ -400,7 +400,7 @@
 	/*
 	 * Put chipset on warm reset...
 	 *
-	 * Note: puting PCI core on warm reset on PCI-E cards
+	 * Note: putting PCI core on warm reset on PCI-E cards
 	 * results card to hang and always return 0xffff... so
 	 * we ingore that flag for PCI-E cards. On PCI cards
 	 * this flag gets cleared after 64 PCI clocks.
@@ -959,7 +959,7 @@
 						AR5K_QUEUE_DCU_SEQNUM(0));
 			}
 
-			/* TSF accelerates on AR5211 durring reset
+			/* TSF accelerates on AR5211 during reset
 			 * As a workaround save it here and restore
 			 * it later so that it's back in time after
 			 * reset. This way it'll get re-synced on the
@@ -1060,7 +1060,7 @@
 		 * XXX: rethink this after new mode changes to
 		 * mac80211 are integrated */
 		if (ah->ah_version == AR5K_AR5212 &&
-			ah->ah_sc->vif != NULL)
+			ah->ah_sc->nvifs)
 			ath5k_hw_write_rate_duration(ah, mode);
 
 		/*
@@ -1080,7 +1080,7 @@
 				return ret;
 
 			/* Spur info is available only from EEPROM versions
-			 * bigger than 5.3 but but the EEPOM routines will use
+			 * greater than 5.3, but the EEPROM routines will use
 			 * static values for older versions */
 			if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
 				ath5k_hw_set_spur_mitigation_filter(ah,
@@ -1160,7 +1160,7 @@
 	 */
 
 	/* Restore bssid and bssid mask */
-	ath5k_hw_set_associd(ah);
+	ath5k_hw_set_bssid(ah);
 
 	/* Set PCU config */
 	ath5k_hw_set_opmode(ah, op_mode);
@@ -1173,11 +1173,11 @@
 	/* Set RSSI/BRSSI thresholds
 	 *
 	 * Note: If we decide to set this value
-	 * dynamicaly, have in mind that when AR5K_RSSI_THR
-	 * register is read it might return 0x40 if we haven't
-	 * wrote anything to it plus BMISS RSSI threshold is zeroed.
+	 * dynamically, keep in mind that when AR5K_RSSI_THR
+	 * register is read, it might return 0x40 if we haven't
+	 * written anything to it.  Also, BMISS RSSI threshold is zeroed.
 	 * So doing a save/restore procedure here isn't the right
-	 * choice. Instead store it on ath5k_hw */
+	 * choice. Instead, store it in ath5k_hw */
 	ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
 				AR5K_TUNE_BMISS_THRES <<
 				AR5K_RSSI_THR_BMISS_S),
@@ -1235,7 +1235,7 @@
 
 	/*
 	 * Perform ADC test to see if baseband is ready
-	 * Set tx hold and check adc test register
+	 * Set TX hold and check ADC test register
 	 */
 	phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
 	ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
@@ -1254,15 +1254,15 @@
 	 *
 	 * This method is used to calibrate some static offsets
 	 * used together with on-the fly I/Q calibration (the
-	 * one performed via ath5k_hw_phy_calibrate), that doesn't
+	 * one performed via ath5k_hw_phy_calibrate), which doesn't
 	 * interrupt rx path.
 	 *
 	 * While rx path is re-routed to the power detector we also
-	 * start a noise floor calibration, to measure the
+	 * start a noise floor calibration to measure the
 	 * card's noise floor (the noise we measure when we are not
-	 * transmiting or receiving anything).
+	 * transmitting or receiving anything).
 	 *
-	 * If we are in a noisy environment AGC calibration may time
+	 * If we are in a noisy environment, AGC calibration may time
 	 * out and/or noise floor calibration might timeout.
 	 */
 	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h
index e50baff..3ac4cff 100644
--- a/drivers/net/wireless/ath/ath5k/rfbuffer.h
+++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h
@@ -25,10 +25,10 @@
  *
  * We don't write on those registers directly but
  * we send a data packet on the chip, using a special register,
- * that holds all the settings we need. After we 've sent the
+ * that holds all the settings we need. After we've sent the
  * data packet, we write on another special register to notify hw
  * to apply the settings. This is done so that control registers
- * can be dynamicaly programmed during operation and the settings
+ * can be dynamically programmed during operation and the settings
  * are applied faster on the hw.
  *
  * We call each data packet an "RF Bank" and all the data we write
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 35f23bd..ad57a6d 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -32,6 +32,14 @@
 
 	  Also required for changing debug message flags at run time.
 
+config ATH9K_RATE_CONTROL
+	bool "Atheros ath9k rate control"
+	depends on ATH9K
+	default y
+	---help---
+	  Say Y, if you want to use the ath9k specific rate control
+	  module instead of minstrel_ht.
+
 config ATH9K_HTC
        tristate "Atheros HTC based wireless cards support"
        depends on USB && MAC80211
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 973ae4f..aca0162 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -5,8 +5,8 @@
 		recv.o \
 		xmit.o \
 		virtual.o \
-		rc.o
 
+ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
 ath9k-$(CONFIG_PCI) += pci.o
 ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
 ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
@@ -46,6 +46,7 @@
 		htc_drv_txrx.o \
 		htc_drv_main.o \
 		htc_drv_beacon.o \
-		htc_drv_init.o
+		htc_drv_init.o \
+		htc_drv_gpio.o
 
 obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index cc648b6..63ccb39 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <linux/kernel.h>
 #include "hw.h"
 #include "hw-ops.h"
 
@@ -48,7 +49,7 @@
 	{  7,  8,  0  }  /* lvl 9 */
 };
 #define ATH9K_ANI_OFDM_NUM_LEVEL \
-	(sizeof(ofdm_level_table)/sizeof(ofdm_level_table[0]))
+	ARRAY_SIZE(ofdm_level_table)
 #define ATH9K_ANI_OFDM_MAX_LEVEL \
 	(ATH9K_ANI_OFDM_NUM_LEVEL-1)
 #define ATH9K_ANI_OFDM_DEF_LEVEL \
@@ -94,7 +95,7 @@
 };
 
 #define ATH9K_ANI_CCK_NUM_LEVEL \
-	(sizeof(cck_level_table)/sizeof(cck_level_table[0]))
+	ARRAY_SIZE(cck_level_table)
 #define ATH9K_ANI_CCK_MAX_LEVEL \
 	(ATH9K_ANI_CCK_NUM_LEVEL-1)
 #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
@@ -102,31 +103,9 @@
 #define ATH9K_ANI_CCK_DEF_LEVEL \
 	2 /* default level - matches the INI settings */
 
-/* Private to ani.c */
-static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
+static bool use_new_ani(struct ath_hw *ah)
 {
-	ath9k_hw_private_ops(ah)->ani_lower_immunity(ah);
-}
-
-int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
-				 struct ath9k_channel *chan)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
-		if (ah->ani[i].c &&
-		    ah->ani[i].c->channel == chan->channel)
-			return i;
-		if (ah->ani[i].c == NULL) {
-			ah->ani[i].c = chan;
-			return i;
-		}
-	}
-
-	ath_print(ath9k_hw_common(ah), ATH_DBG_ANI,
-		  "No more channel states left. Using channel 0\n");
-
-	return 0;
+	return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani;
 }
 
 static void ath9k_hw_update_mibstats(struct ath_hw *ah,
@@ -139,82 +118,34 @@
 	stats->beacons += REG_READ(ah, AR_BEACON_CNT);
 }
 
-static void ath9k_ani_restart_old(struct ath_hw *ah)
+static void ath9k_ani_restart(struct ath_hw *ah)
 {
 	struct ar5416AniState *aniState;
 	struct ath_common *common = ath9k_hw_common(ah);
+	u32 ofdm_base = 0, cck_base = 0;
 
 	if (!DO_ANI(ah))
 		return;
 
-	aniState = ah->curani;
+	aniState = &ah->curchan->ani;
 	aniState->listenTime = 0;
 
-	if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
-		aniState->ofdmPhyErrBase = 0;
-		ath_print(common, ATH_DBG_ANI,
-			  "OFDM Trigger is too high for hw counters\n");
-	} else {
-		aniState->ofdmPhyErrBase =
-			AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
+	if (!use_new_ani(ah)) {
+		ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
+		cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
 	}
-	if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
-		aniState->cckPhyErrBase = 0;
-		ath_print(common, ATH_DBG_ANI,
-			  "CCK Trigger is too high for hw counters\n");
-	} else {
-		aniState->cckPhyErrBase =
-			AR_PHY_COUNTMAX - aniState->cckTrigHigh;
-	}
+
 	ath_print(common, ATH_DBG_ANI,
-		  "Writing ofdmbase=%u   cckbase=%u\n",
-		  aniState->ofdmPhyErrBase,
-		  aniState->cckPhyErrBase);
+		  "Writing ofdmbase=%u   cckbase=%u\n", ofdm_base, cck_base);
 
 	ENABLE_REGWRITE_BUFFER(ah);
 
-	REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
-	REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
+	REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
+	REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
 	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
 	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
-
-	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
-	aniState->ofdmPhyErrCount = 0;
-	aniState->cckPhyErrCount = 0;
-}
-
-static void ath9k_ani_restart_new(struct ath_hw *ah)
-{
-	struct ar5416AniState *aniState;
-	struct ath_common *common = ath9k_hw_common(ah);
-
-	if (!DO_ANI(ah))
-		return;
-
-	aniState = ah->curani;
-	aniState->listenTime = 0;
-
-	aniState->ofdmPhyErrBase = 0;
-	aniState->cckPhyErrBase = 0;
-
-	ath_print(common, ATH_DBG_ANI,
-		  "Writing ofdmbase=%08x   cckbase=%08x\n",
-		  aniState->ofdmPhyErrBase,
-		  aniState->cckPhyErrBase);
-
-	ENABLE_REGWRITE_BUFFER(ah);
-
-	REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
-	REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
-	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
-	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
-	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
 
@@ -228,10 +159,7 @@
 	struct ar5416AniState *aniState;
 	int32_t rssi;
 
-	if (!DO_ANI(ah))
-		return;
-
-	aniState = ah->curani;
+	aniState = &ah->curchan->ani;
 
 	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
 		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
@@ -300,10 +228,7 @@
 	struct ar5416AniState *aniState;
 	int32_t rssi;
 
-	if (!DO_ANI(ah))
-		return;
-
-	aniState = ah->curani;
+	aniState = &ah->curchan->ani;
 	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
 		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
 					 aniState->noiseImmunityLevel + 1)) {
@@ -335,7 +260,7 @@
 /* Adjust the OFDM Noise Immunity Level */
 static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
 {
-	struct ar5416AniState *aniState = ah->curani;
+	struct ar5416AniState *aniState = &ah->curchan->ani;
 	struct ath_common *common = ath9k_hw_common(ah);
 	const struct ani_ofdm_level_entry *entry_ofdm;
 	const struct ani_cck_level_entry *entry_cck;
@@ -380,14 +305,19 @@
 	}
 }
 
-static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah)
+static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
 {
 	struct ar5416AniState *aniState;
 
 	if (!DO_ANI(ah))
 		return;
 
-	aniState = ah->curani;
+	if (!use_new_ani(ah)) {
+		ath9k_hw_ani_ofdm_err_trigger_old(ah);
+		return;
+	}
+
+	aniState = &ah->curchan->ani;
 
 	if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
 		ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
@@ -398,7 +328,7 @@
  */
 static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
 {
-	struct ar5416AniState *aniState = ah->curani;
+	struct ar5416AniState *aniState = &ah->curchan->ani;
 	struct ath_common *common = ath9k_hw_common(ah);
 	const struct ani_ofdm_level_entry *entry_ofdm;
 	const struct ani_cck_level_entry *entry_cck;
@@ -437,14 +367,19 @@
 				     entry_cck->mrc_cck_on);
 }
 
-static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah)
+static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
 {
 	struct ar5416AniState *aniState;
 
 	if (!DO_ANI(ah))
 		return;
 
-	aniState = ah->curani;
+	if (!use_new_ani(ah)) {
+		ath9k_hw_ani_cck_err_trigger_old(ah);
+		return;
+	}
+
+	aniState = &ah->curchan->ani;
 
 	if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
 		ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
@@ -455,7 +390,7 @@
 	struct ar5416AniState *aniState;
 	int32_t rssi;
 
-	aniState = ah->curani;
+	aniState = &ah->curchan->ani;
 
 	if (ah->opmode == NL80211_IFTYPE_AP) {
 		if (aniState->firstepLevel > 0) {
@@ -507,11 +442,16 @@
  * only lower either OFDM or CCK errors per turn
  * we lower the other one next time
  */
-static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah)
+static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
 {
 	struct ar5416AniState *aniState;
 
-	aniState = ah->curani;
+	aniState = &ah->curchan->ani;
+
+	if (!use_new_ani(ah)) {
+		ath9k_hw_ani_lower_immunity_old(ah);
+		return;
+	}
 
 	/* lower OFDM noise immunity */
 	if (aniState->ofdmNoiseImmunityLevel > 0 &&
@@ -525,87 +465,18 @@
 		ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
 }
 
-static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
-{
-	struct ath9k_channel *chan = ah->curchan;
-	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
-	u8 clockrate; /* in MHz */
-
-	if (!ah->curchan) /* should really check for CCK instead */
-		clockrate = ATH9K_CLOCK_RATE_CCK;
-	else if (conf->channel->band == IEEE80211_BAND_2GHZ)
-		clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
-	else if (IS_CHAN_A_FAST_CLOCK(ah, chan))
-		clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
-	else
-		clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
-
-	if (conf_is_ht40(conf))
-		return clockrate * 2;
-
-	return clockrate * 2;
-}
-
-static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
-{
-	struct ar5416AniState *aniState;
-	struct ath_common *common = ath9k_hw_common(ah);
-	u32 txFrameCount, rxFrameCount, cycleCount;
-	int32_t listenTime;
-
-	txFrameCount = REG_READ(ah, AR_TFCNT);
-	rxFrameCount = REG_READ(ah, AR_RFCNT);
-	cycleCount = REG_READ(ah, AR_CCCNT);
-
-	aniState = ah->curani;
-	if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
-		listenTime = 0;
-		ah->stats.ast_ani_lzero++;
-		ath_print(common, ATH_DBG_ANI,
-			  "1st call: aniState->cycleCount=%d\n",
-			  aniState->cycleCount);
-	} else {
-		int32_t ccdelta = cycleCount - aniState->cycleCount;
-		int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
-		int32_t tfdelta = txFrameCount - aniState->txFrameCount;
-		int32_t clock_rate;
-
-		/*
-		 * convert HW counter values to ms using mode
-		 * specifix clock rate
-		 */
-		clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;;
-
-		listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate;
-
-		ath_print(common, ATH_DBG_ANI,
-			  "cyclecount=%d, rfcount=%d, "
-			  "tfcount=%d, listenTime=%d CLOCK_RATE=%d\n",
-			  ccdelta, rfdelta, tfdelta, listenTime, clock_rate);
-	}
-
-	aniState->cycleCount = cycleCount;
-	aniState->txFrameCount = txFrameCount;
-	aniState->rxFrameCount = rxFrameCount;
-
-	return listenTime;
-}
-
 static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
 {
 	struct ar5416AniState *aniState;
 	struct ath9k_channel *chan = ah->curchan;
 	struct ath_common *common = ath9k_hw_common(ah);
-	int index;
 
 	if (!DO_ANI(ah))
 		return;
 
-	index = ath9k_hw_get_ani_channel_idx(ah, chan);
-	aniState = &ah->ani[index];
-	ah->curani = aniState;
+	aniState = &ah->curchan->ani;
 
-	if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
+	if (ah->opmode != NL80211_IFTYPE_STATION
 	    && ah->opmode != NL80211_IFTYPE_ADHOC) {
 		ath_print(common, ATH_DBG_ANI,
 			  "Reset ANI state opmode %u\n", ah->opmode);
@@ -634,17 +505,7 @@
 		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
 				     ATH9K_RX_FILTER_PHYERR);
 
-		if (ah->opmode == NL80211_IFTYPE_AP) {
-			ah->curani->ofdmTrigHigh =
-				ah->config.ofdm_trig_high;
-			ah->curani->ofdmTrigLow =
-				ah->config.ofdm_trig_low;
-			ah->curani->cckTrigHigh =
-				ah->config.cck_trig_high;
-			ah->curani->cckTrigLow =
-				ah->config.cck_trig_low;
-		}
-		ath9k_ani_restart_old(ah);
+		ath9k_ani_restart(ah);
 		return;
 	}
 
@@ -666,7 +527,7 @@
 
 	ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
 			     ~ATH9K_RX_FILTER_PHYERR);
-	ath9k_ani_restart_old(ah);
+	ath9k_ani_restart(ah);
 
 	ENABLE_REGWRITE_BUFFER(ah);
 
@@ -674,7 +535,6 @@
 	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 
 /*
@@ -682,15 +542,18 @@
  * This routine should be called for every hardware reset and for
  * every channel change.
  */
-static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
+void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
 {
-	struct ar5416AniState *aniState = ah->curani;
+	struct ar5416AniState *aniState = &ah->curchan->ani;
 	struct ath9k_channel *chan = ah->curchan;
 	struct ath_common *common = ath9k_hw_common(ah);
 
 	if (!DO_ANI(ah))
 		return;
 
+	if (!use_new_ani(ah))
+		return ath9k_ani_reset_old(ah, is_scanning);
+
 	BUG_ON(aniState == NULL);
 	ah->stats.ast_ani_reset++;
 
@@ -760,7 +623,7 @@
 	 * enable phy counters if hw supports or if not, enable phy
 	 * interrupts (so we can count each one)
 	 */
-	ath9k_ani_restart_new(ah);
+	ath9k_ani_restart(ah);
 
 	ENABLE_REGWRITE_BUFFER(ah);
 
@@ -768,28 +631,30 @@
 	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 
-static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
-				     struct ath9k_channel *chan)
+static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
 {
-	struct ar5416AniState *aniState;
 	struct ath_common *common = ath9k_hw_common(ah);
-	int32_t listenTime;
-	u32 phyCnt1, phyCnt2;
+	struct ar5416AniState *aniState = &ah->curchan->ani;
+	u32 ofdm_base = 0;
+	u32 cck_base = 0;
 	u32 ofdmPhyErrCnt, cckPhyErrCnt;
+	u32 phyCnt1, phyCnt2;
+	int32_t listenTime;
 
-	if (!DO_ANI(ah))
-		return;
+	ath_hw_cycle_counters_update(common);
+	listenTime = ath_hw_get_listen_time(common);
 
-	aniState = ah->curani;
-
-	listenTime = ath9k_hw_ani_get_listen_time(ah);
-	if (listenTime < 0) {
+	if (listenTime <= 0) {
 		ah->stats.ast_ani_lneg++;
-		ath9k_ani_restart_old(ah);
-		return;
+		ath9k_ani_restart(ah);
+		return false;
+	}
+
+	if (!use_new_ani(ah)) {
+		ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
+		cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
 	}
 
 	aniState->listenTime += listenTime;
@@ -799,145 +664,55 @@
 	phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
 	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
 
-	if (phyCnt1 < aniState->ofdmPhyErrBase ||
-	    phyCnt2 < aniState->cckPhyErrBase) {
-		if (phyCnt1 < aniState->ofdmPhyErrBase) {
+	if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
+		if (phyCnt1 < ofdm_base) {
 			ath_print(common, ATH_DBG_ANI,
 				  "phyCnt1 0x%x, resetting "
 				  "counter value to 0x%x\n",
-				  phyCnt1,
-				  aniState->ofdmPhyErrBase);
-			REG_WRITE(ah, AR_PHY_ERR_1,
-				  aniState->ofdmPhyErrBase);
+				  phyCnt1, ofdm_base);
+			REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
 			REG_WRITE(ah, AR_PHY_ERR_MASK_1,
 				  AR_PHY_ERR_OFDM_TIMING);
 		}
-		if (phyCnt2 < aniState->cckPhyErrBase) {
+		if (phyCnt2 < cck_base) {
 			ath_print(common, ATH_DBG_ANI,
 				  "phyCnt2 0x%x, resetting "
 				  "counter value to 0x%x\n",
-				  phyCnt2,
-				  aniState->cckPhyErrBase);
-			REG_WRITE(ah, AR_PHY_ERR_2,
-				  aniState->cckPhyErrBase);
+				  phyCnt2, cck_base);
+			REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
 			REG_WRITE(ah, AR_PHY_ERR_MASK_2,
 				  AR_PHY_ERR_CCK_TIMING);
 		}
-		return;
+		return false;
 	}
 
-	ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+	ofdmPhyErrCnt = phyCnt1 - ofdm_base;
 	ah->stats.ast_ani_ofdmerrs +=
 		ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
 	aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
 
-	cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+	cckPhyErrCnt = phyCnt2 - cck_base;
 	ah->stats.ast_ani_cckerrs +=
 		cckPhyErrCnt - aniState->cckPhyErrCount;
 	aniState->cckPhyErrCount = cckPhyErrCnt;
-
-	if (aniState->listenTime > 5 * ah->aniperiod) {
-		if (aniState->ofdmPhyErrCount <= aniState->listenTime *
-		    aniState->ofdmTrigLow / 1000 &&
-		    aniState->cckPhyErrCount <= aniState->listenTime *
-		    aniState->cckTrigLow / 1000)
-			ath9k_hw_ani_lower_immunity(ah);
-		ath9k_ani_restart_old(ah);
-	} else if (aniState->listenTime > ah->aniperiod) {
-		if (aniState->ofdmPhyErrCount > aniState->listenTime *
-		    aniState->ofdmTrigHigh / 1000) {
-			ath9k_hw_ani_ofdm_err_trigger_old(ah);
-			ath9k_ani_restart_old(ah);
-		} else if (aniState->cckPhyErrCount >
-			   aniState->listenTime * aniState->cckTrigHigh /
-			   1000) {
-			ath9k_hw_ani_cck_err_trigger_old(ah);
-			ath9k_ani_restart_old(ah);
-		}
-	}
+	return true;
 }
 
-static void ath9k_hw_ani_monitor_new(struct ath_hw *ah,
-				     struct ath9k_channel *chan)
+void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
 {
 	struct ar5416AniState *aniState;
 	struct ath_common *common = ath9k_hw_common(ah);
-	int32_t listenTime;
-	u32 phyCnt1, phyCnt2;
-	u32 ofdmPhyErrCnt, cckPhyErrCnt;
 	u32 ofdmPhyErrRate, cckPhyErrRate;
 
 	if (!DO_ANI(ah))
 		return;
 
-	aniState = ah->curani;
+	aniState = &ah->curchan->ani;
 	if (WARN_ON(!aniState))
 		return;
 
-	listenTime = ath9k_hw_ani_get_listen_time(ah);
-	if (listenTime <= 0) {
-		ah->stats.ast_ani_lneg++;
-		/* restart ANI period if listenTime is invalid */
-		ath_print(common, ATH_DBG_ANI,
-			  "listenTime=%d - on new ani monitor\n",
-			  listenTime);
-		ath9k_ani_restart_new(ah);
+	if (!ath9k_hw_ani_read_counters(ah))
 		return;
-	}
-
-	aniState->listenTime += listenTime;
-
-	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
-	phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
-	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-
-	if (phyCnt1 < aniState->ofdmPhyErrBase ||
-	    phyCnt2 < aniState->cckPhyErrBase) {
-		if (phyCnt1 < aniState->ofdmPhyErrBase) {
-			ath_print(common, ATH_DBG_ANI,
-				  "phyCnt1 0x%x, resetting "
-				  "counter value to 0x%x\n",
-				  phyCnt1,
-				  aniState->ofdmPhyErrBase);
-			REG_WRITE(ah, AR_PHY_ERR_1,
-				  aniState->ofdmPhyErrBase);
-			REG_WRITE(ah, AR_PHY_ERR_MASK_1,
-				  AR_PHY_ERR_OFDM_TIMING);
-		}
-		if (phyCnt2 < aniState->cckPhyErrBase) {
-			ath_print(common, ATH_DBG_ANI,
-				  "phyCnt2 0x%x, resetting "
-				  "counter value to 0x%x\n",
-				  phyCnt2,
-				  aniState->cckPhyErrBase);
-			REG_WRITE(ah, AR_PHY_ERR_2,
-				  aniState->cckPhyErrBase);
-			REG_WRITE(ah, AR_PHY_ERR_MASK_2,
-				  AR_PHY_ERR_CCK_TIMING);
-		}
-		return;
-	}
-
-	ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
-	ah->stats.ast_ani_ofdmerrs +=
-		ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
-	aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
-
-	cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
-	ah->stats.ast_ani_cckerrs +=
-		cckPhyErrCnt - aniState->cckPhyErrCount;
-	aniState->cckPhyErrCount = cckPhyErrCnt;
-
-	ath_print(common, ATH_DBG_ANI,
-		  "Errors: OFDM=0x%08x-0x%08x=%d   "
-		  "CCK=0x%08x-0x%08x=%d\n",
-		  phyCnt1,
-		  aniState->ofdmPhyErrBase,
-		  ofdmPhyErrCnt,
-		  phyCnt2,
-		  aniState->cckPhyErrBase,
-		  cckPhyErrCnt);
 
 	ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
 			 aniState->listenTime;
@@ -947,61 +722,34 @@
 	ath_print(common, ATH_DBG_ANI,
 		  "listenTime=%d OFDM:%d errs=%d/s CCK:%d "
 		  "errs=%d/s ofdm_turn=%d\n",
-		  listenTime, aniState->ofdmNoiseImmunityLevel,
+		  aniState->listenTime,
+		  aniState->ofdmNoiseImmunityLevel,
 		  ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
 		  cckPhyErrRate, aniState->ofdmsTurn);
 
 	if (aniState->listenTime > 5 * ah->aniperiod) {
-		if (ofdmPhyErrRate <= aniState->ofdmTrigLow &&
-		    cckPhyErrRate <= aniState->cckTrigLow) {
-			ath_print(common, ATH_DBG_ANI,
-				  "1. listenTime=%d OFDM:%d errs=%d/s(<%d)  "
-				  "CCK:%d errs=%d/s(<%d) -> "
-				  "ath9k_hw_ani_lower_immunity()\n",
-				  aniState->listenTime,
-				  aniState->ofdmNoiseImmunityLevel,
-				  ofdmPhyErrRate,
-				  aniState->ofdmTrigLow,
-				  aniState->cckNoiseImmunityLevel,
-				  cckPhyErrRate,
-				  aniState->cckTrigLow);
+		if (ofdmPhyErrRate <= ah->config.ofdm_trig_low &&
+		    cckPhyErrRate <= ah->config.cck_trig_low) {
 			ath9k_hw_ani_lower_immunity(ah);
 			aniState->ofdmsTurn = !aniState->ofdmsTurn;
 		}
-		ath_print(common, ATH_DBG_ANI,
-			  "1 listenTime=%d ofdm=%d/s cck=%d/s - "
-			  "calling ath9k_ani_restart_new()\n",
-			  aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate);
-		ath9k_ani_restart_new(ah);
+		ath9k_ani_restart(ah);
 	} else if (aniState->listenTime > ah->aniperiod) {
 		/* check to see if need to raise immunity */
-		if (ofdmPhyErrRate > aniState->ofdmTrigHigh &&
-		    (cckPhyErrRate <= aniState->cckTrigHigh ||
+		if (ofdmPhyErrRate > ah->config.ofdm_trig_high &&
+		    (cckPhyErrRate <= ah->config.cck_trig_high ||
 		     aniState->ofdmsTurn)) {
-			ath_print(common, ATH_DBG_ANI,
-				  "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> "
-				  "ath9k_hw_ani_ofdm_err_trigger_new()\n",
-				  aniState->listenTime,
-				  aniState->ofdmNoiseImmunityLevel,
-				  ofdmPhyErrRate,
-				  aniState->ofdmTrigHigh);
-			ath9k_hw_ani_ofdm_err_trigger_new(ah);
-			ath9k_ani_restart_new(ah);
+			ath9k_hw_ani_ofdm_err_trigger(ah);
+			ath9k_ani_restart(ah);
 			aniState->ofdmsTurn = false;
-		} else if (cckPhyErrRate > aniState->cckTrigHigh) {
-			ath_print(common, ATH_DBG_ANI,
-				 "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> "
-				 "ath9k_hw_ani_cck_err_trigger_new()\n",
-				 aniState->listenTime,
-				 aniState->cckNoiseImmunityLevel,
-				 cckPhyErrRate,
-				 aniState->cckTrigHigh);
-			ath9k_hw_ani_cck_err_trigger_new(ah);
-			ath9k_ani_restart_new(ah);
+		} else if (cckPhyErrRate > ah->config.cck_trig_high) {
+			ath9k_hw_ani_cck_err_trigger(ah);
+			ath9k_ani_restart(ah);
 			aniState->ofdmsTurn = true;
 		}
 	}
 }
+EXPORT_SYMBOL(ath9k_hw_ani_monitor);
 
 void ath9k_enable_mib_counters(struct ath_hw *ah)
 {
@@ -1022,7 +770,6 @@
 	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 
 /* Freeze the MIB counters, get the stats and then clear them */
@@ -1040,53 +787,12 @@
 }
 EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
 
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
-				  u32 *rxc_pcnt,
-				  u32 *rxf_pcnt,
-				  u32 *txf_pcnt)
-{
-	struct ath_common *common = ath9k_hw_common(ah);
-	static u32 cycles, rx_clear, rx_frame, tx_frame;
-	u32 good = 1;
-
-	u32 rc = REG_READ(ah, AR_RCCNT);
-	u32 rf = REG_READ(ah, AR_RFCNT);
-	u32 tf = REG_READ(ah, AR_TFCNT);
-	u32 cc = REG_READ(ah, AR_CCCNT);
-
-	if (cycles == 0 || cycles > cc) {
-		ath_print(common, ATH_DBG_ANI,
-			  "cycle counter wrap. ExtBusy = 0\n");
-		good = 0;
-	} else {
-		u32 cc_d = cc - cycles;
-		u32 rc_d = rc - rx_clear;
-		u32 rf_d = rf - rx_frame;
-		u32 tf_d = tf - tx_frame;
-
-		if (cc_d != 0) {
-			*rxc_pcnt = rc_d * 100 / cc_d;
-			*rxf_pcnt = rf_d * 100 / cc_d;
-			*txf_pcnt = tf_d * 100 / cc_d;
-		} else {
-			good = 0;
-		}
-	}
-
-	cycles = cc;
-	rx_frame = rf;
-	rx_clear = rc;
-	tx_frame = tf;
-
-	return good;
-}
-
 /*
  * Process a MIB interrupt.  We may potentially be invoked because
  * any of the MIB counters overflow/trigger so don't assume we're
  * here because a PHY error counter triggered.
  */
-static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah)
+void ath9k_hw_proc_mib_event(struct ath_hw *ah)
 {
 	u32 phyCnt1, phyCnt2;
 
@@ -1114,72 +820,15 @@
 	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
 	if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
 	    ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
-		struct ar5416AniState *aniState = ah->curani;
-		u32 ofdmPhyErrCnt, cckPhyErrCnt;
 
-		/* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
-		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
-		ah->stats.ast_ani_ofdmerrs +=
-			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
-		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+		if (!use_new_ani(ah))
+			ath9k_hw_ani_read_counters(ah);
 
-		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
-		ah->stats.ast_ani_cckerrs +=
-			cckPhyErrCnt - aniState->cckPhyErrCount;
-		aniState->cckPhyErrCount = cckPhyErrCnt;
-
-		/*
-		 * NB: figure out which counter triggered.  If both
-		 * trigger we'll only deal with one as the processing
-		 * clobbers the error counter so the trigger threshold
-		 * check will never be true.
-		 */
-		if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
-			ath9k_hw_ani_ofdm_err_trigger_new(ah);
-		if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
-			ath9k_hw_ani_cck_err_trigger_old(ah);
 		/* NB: always restart to insure the h/w counters are reset */
-		ath9k_ani_restart_old(ah);
+		ath9k_ani_restart(ah);
 	}
 }
-
-/*
- * Process a MIB interrupt.  We may potentially be invoked because
- * any of the MIB counters overflow/trigger so don't assume we're
- * here because a PHY error counter triggered.
- */
-static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah)
-{
-	u32 phyCnt1, phyCnt2;
-
-	/* Reset these counters regardless */
-	REG_WRITE(ah, AR_FILT_OFDM, 0);
-	REG_WRITE(ah, AR_FILT_CCK, 0);
-	if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
-		REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
-
-	/* Clear the mib counters and save them in the stats */
-	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
-	if (!DO_ANI(ah)) {
-		/*
-		 * We must always clear the interrupt cause by
-		 * resetting the phy error regs.
-		 */
-		REG_WRITE(ah, AR_PHY_ERR_1, 0);
-		REG_WRITE(ah, AR_PHY_ERR_2, 0);
-		return;
-	}
-
-	/* NB: these are not reset-on-read */
-	phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
-	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-
-	/* NB: always restart to insure the h/w counters are reset */
-	if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
-	    ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK))
-		ath9k_ani_restart_new(ah);
-}
+EXPORT_SYMBOL(ath9k_hw_proc_mib_event);
 
 void ath9k_hw_ani_setup(struct ath_hw *ah)
 {
@@ -1205,61 +854,58 @@
 
 	ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
 
-	memset(ah->ani, 0, sizeof(ah->ani));
-	for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
-		if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
-			ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
-			ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
+	if (use_new_ani(ah)) {
+		ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
+		ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
 
-			ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
-			ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW;
+		ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
+		ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW;
+	} else {
+		ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
+		ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
 
-			ah->ani[i].spurImmunityLevel =
+		ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
+		ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
+		struct ath9k_channel *chan = &ah->channels[i];
+		struct ar5416AniState *ani = &chan->ani;
+
+		if (use_new_ani(ah)) {
+			ani->spurImmunityLevel =
 				ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
 
-			ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
-
-			ah->ani[i].ofdmPhyErrBase = 0;
-			ah->ani[i].cckPhyErrBase = 0;
+			ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
 
 			if (AR_SREV_9300_20_OR_LATER(ah))
-				ah->ani[i].mrcCCKOff =
+				ani->mrcCCKOff =
 					!ATH9K_ANI_ENABLE_MRC_CCK;
 			else
-				ah->ani[i].mrcCCKOff = true;
+				ani->mrcCCKOff = true;
 
-			ah->ani[i].ofdmsTurn = true;
+			ani->ofdmsTurn = true;
 		} else {
-			ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
-			ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
-
-			ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
-			ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD;
-
-			ah->ani[i].spurImmunityLevel =
+			ani->spurImmunityLevel =
 				ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
-			ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
+			ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
 
-			ah->ani[i].ofdmPhyErrBase =
-				AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
-			ah->ani[i].cckPhyErrBase =
-				AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD;
-			ah->ani[i].cckWeakSigThreshold =
+			ani->cckWeakSigThreshold =
 				ATH9K_ANI_CCK_WEAK_SIG_THR;
 		}
 
-		ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
-		ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
-		ah->ani[i].ofdmWeakSigDetectOff =
+		ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
+		ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
+		ani->ofdmWeakSigDetectOff =
 			!ATH9K_ANI_USE_OFDM_WEAK_SIG;
-		ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
+		ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
 	}
 
 	/*
 	 * since we expect some ongoing maintenance on the tables, let's sanity
 	 * check here default level should not modify INI setting.
 	 */
-	if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
+	if (use_new_ani(ah)) {
 		const struct ani_ofdm_level_entry *entry_ofdm;
 		const struct ani_cck_level_entry *entry_cck;
 
@@ -1273,50 +919,9 @@
 		ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
 	}
 
-	ath_print(common, ATH_DBG_ANI,
-		  "Setting OfdmErrBase = 0x%08x\n",
-		  ah->ani[0].ofdmPhyErrBase);
-	ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
-		  ah->ani[0].cckPhyErrBase);
-
-	ENABLE_REGWRITE_BUFFER(ah);
-
-	REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
-	REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
-
-	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
-
-	ath9k_enable_mib_counters(ah);
-
 	if (ah->config.enable_ani)
 		ah->proc_phyerr |= HAL_PROCESS_ANI;
-}
 
-void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah)
-{
-	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
-	struct ath_hw_ops *ops = ath9k_hw_ops(ah);
-
-	priv_ops->ani_reset = ath9k_ani_reset_old;
-	priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old;
-
-	ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old;
-	ops->ani_monitor = ath9k_hw_ani_monitor_old;
-
-	ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n");
-}
-
-void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah)
-{
-	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
-	struct ath_hw_ops *ops = ath9k_hw_ops(ah);
-
-	priv_ops->ani_reset = ath9k_ani_reset_new;
-	priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new;
-
-	ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new;
-	ops->ani_monitor = ath9k_hw_ani_monitor_new;
-
-	ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n");
+	ath9k_ani_restart(ah);
+	ath9k_enable_mib_counters(ah);
 }
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index f4d0a4d..0cd6783 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -19,7 +19,7 @@
 
 #define HAL_PROCESS_ANI           0x00000001
 
-#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI))
+#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI) && ah->curchan)
 
 #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
 
@@ -123,20 +123,11 @@
 	u8 ofdmWeakSigDetectOff;
 	u8 cckWeakSigThreshold;
 	u32 listenTime;
-	u32 ofdmTrigHigh;
-	u32 ofdmTrigLow;
-	int32_t cckTrigHigh;
-	int32_t cckTrigLow;
 	int32_t rssiThrLow;
 	int32_t rssiThrHigh;
 	u32 noiseFloor;
-	u32 txFrameCount;
-	u32 rxFrameCount;
-	u32 cycleCount;
 	u32 ofdmPhyErrCount;
 	u32 cckPhyErrCount;
-	u32 ofdmPhyErrBase;
-	u32 cckPhyErrBase;
 	int16_t pktRssi[2];
 	int16_t ofdmErrRssi[2];
 	int16_t cckErrRssi[2];
@@ -166,8 +157,6 @@
 
 void ath9k_enable_mib_counters(struct ath_hw *ah);
 void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
-				  u32 *rxf_pcnt, u32 *txf_pcnt);
 void ath9k_hw_ani_setup(struct ath_hw *ah);
 void ath9k_hw_ani_init(struct ath_hw *ah);
 int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 3d2c867..ea9f449 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -118,7 +118,7 @@
 	if (!AR_SREV_5416(ah) || synth_freq >= 3000)
 		return;
 
-	BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
+	BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
 
 	if (synth_freq < 2412)
 		new_bias = 0;
@@ -454,7 +454,7 @@
 
 	struct ath_common *common = ath9k_hw_common(ah);
 
-	BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
+	BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
 
 	ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
 	ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
@@ -484,7 +484,7 @@
 		bank = NULL; \
 	} while (0);
 
-	BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
+	BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
 
 	ATH_FREE_BANK(ah->analogBank0Data);
 	ATH_FREE_BANK(ah->analogBank1Data);
@@ -525,7 +525,7 @@
 	 * for single chip devices, that is AR9280 or anything
 	 * after that.
 	 */
-	if (AR_SREV_9280_10_OR_LATER(ah))
+	if (AR_SREV_9280_20_OR_LATER(ah))
 		return true;
 
 	/* Setup rf parameters */
@@ -613,14 +613,11 @@
 	rx_chainmask = ah->rxchainmask;
 	tx_chainmask = ah->txchainmask;
 
-	ENABLE_REGWRITE_BUFFER(ah);
 
 	switch (rx_chainmask) {
 	case 0x5:
-		DISABLE_REGWRITE_BUFFER(ah);
 		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
 			    AR_PHY_SWAP_ALT_CHAIN);
-		ENABLE_REGWRITE_BUFFER(ah);
 	case 0x3:
 		if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) {
 			REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
@@ -630,17 +627,18 @@
 	case 0x1:
 	case 0x2:
 	case 0x7:
+		ENABLE_REGWRITE_BUFFER(ah);
 		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
 		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
 		break;
 	default:
+		ENABLE_REGWRITE_BUFFER(ah);
 		break;
 	}
 
 	REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	if (tx_chainmask == 0x5) {
 		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
@@ -663,20 +661,20 @@
 	 */
 	REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
 
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		val = REG_READ(ah, AR_PCU_MISC_MODE2);
 
 		if (!AR_SREV_9271(ah))
 			val &= ~AR_PCU_MISC_MODE2_HWWAR1;
 
-		if (AR_SREV_9287_10_OR_LATER(ah))
+		if (AR_SREV_9287_11_OR_LATER(ah))
 			val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
 
 		REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
 	}
 
 	if (!AR_SREV_5416_20_OR_LATER(ah) ||
-	    AR_SREV_9280_10_OR_LATER(ah))
+	    AR_SREV_9280_20_OR_LATER(ah))
 		return;
 	/*
 	 * Disable BB clock gating
@@ -701,7 +699,7 @@
 	u32 phymode;
 	u32 enableDacFifo = 0;
 
-	if (AR_SREV_9285_10_OR_LATER(ah))
+	if (AR_SREV_9285_12_OR_LATER(ah))
 		enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
 					 AR_PHY_FC_ENABLE_DAC_FIFO);
 
@@ -726,7 +724,6 @@
 	REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 
 
@@ -818,13 +815,12 @@
 	}
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
-	if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah))
+	if (AR_SREV_9280(ah) || AR_SREV_9287_11_OR_LATER(ah))
 		REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
 
 	if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) ||
-	    AR_SREV_9287_10_OR_LATER(ah))
+	    AR_SREV_9287_11_OR_LATER(ah))
 		REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
 
 	if (AR_SREV_9271_10(ah))
@@ -849,7 +845,6 @@
 	}
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	if (AR_SREV_9271(ah)) {
 		if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1)
@@ -900,7 +895,7 @@
 	rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
 		? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
 
-	if (!AR_SREV_9280_10_OR_LATER(ah))
+	if (!AR_SREV_9280_20_OR_LATER(ah))
 		rfMode |= (IS_CHAN_5GHZ(chan)) ?
 			AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
 
@@ -1053,7 +1048,7 @@
 				      enum ath9k_ani_cmd cmd,
 				      int param)
 {
-	struct ar5416AniState *aniState = ah->curani;
+	struct ar5416AniState *aniState = &ah->curchan->ani;
 	struct ath_common *common = ath9k_hw_common(ah);
 
 	switch (cmd & ah->ani_function) {
@@ -1225,8 +1220,7 @@
 		  aniState->firstepLevel,
 		  aniState->listenTime);
 	ath_print(common, ATH_DBG_ANI,
-		"cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
-		aniState->cycleCount,
+		"ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
 		aniState->ofdmPhyErrCount,
 		aniState->cckPhyErrCount);
 
@@ -1237,9 +1231,9 @@
 				      enum ath9k_ani_cmd cmd,
 				      int param)
 {
-	struct ar5416AniState *aniState = ah->curani;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_channel *chan = ah->curchan;
+	struct ar5416AniState *aniState = &chan->ani;
 	s32 value, value2;
 
 	switch (cmd & ah->ani_function) {
@@ -1478,15 +1472,13 @@
 
 	ath_print(common, ATH_DBG_ANI,
 		  "ANI parameters: SI=%d, ofdmWS=%s FS=%d "
-		  "MRCcck=%s listenTime=%d CC=%d listen=%d "
+		  "MRCcck=%s listenTime=%d "
 		  "ofdmErrs=%d cckErrs=%d\n",
 		  aniState->spurImmunityLevel,
 		  !aniState->ofdmWeakSigDetectOff ? "on" : "off",
 		  aniState->firstepLevel,
 		  !aniState->mrcCCKOff ? "on" : "off",
 		  aniState->listenTime,
-		  aniState->cycleCount,
-		  aniState->listenTime,
 		  aniState->ofdmPhyErrCount,
 		  aniState->cckPhyErrCount);
 	return true;
@@ -1526,16 +1518,12 @@
  */
 static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
 {
-	struct ar5416AniState *aniState;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_channel *chan = ah->curchan;
+	struct ar5416AniState *aniState = &chan->ani;
 	struct ath9k_ani_default *iniDef;
-	int index;
 	u32 val;
 
-	index = ath9k_hw_get_ani_channel_idx(ah, chan);
-	aniState = &ah->ani[index];
-	ah->curani = aniState;
 	iniDef = &aniState->iniDef;
 
 	ath_print(common, ATH_DBG_ANI,
@@ -1579,8 +1567,6 @@
 	aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
 	aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
 	aniState->mrcCCKOff = true; /* not available on pre AR9003 */
-
-	aniState->cycleCount = 0;
 }
 
 static void ar5008_hw_set_nf_limits(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index fe7418a..15f62cd 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -20,6 +20,13 @@
 
 #define AR9285_CLCAL_REDO_THRESH    1
 
+enum ar9002_cal_types {
+	ADC_GAIN_CAL = BIT(0),
+	ADC_DC_CAL = BIT(1),
+	IQ_MISMATCH_CAL = BIT(2),
+};
+
+
 static void ar9002_hw_setup_calibration(struct ath_hw *ah,
 					struct ath9k_cal_list *currCal)
 {
@@ -45,13 +52,6 @@
 		ath_print(common, ATH_DBG_CALIBRATE,
 			  "starting ADC DC Calibration\n");
 		break;
-	case ADC_DC_INIT_CAL:
-		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
-		ath_print(common, ATH_DBG_CALIBRATE,
-			  "starting Init ADC DC Calibration\n");
-		break;
-	case TEMP_COMP_CAL:
-		break; /* Not supported */
 	}
 
 	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
@@ -96,25 +96,6 @@
 	return iscaldone;
 }
 
-/* Assumes you are talking about the currently configured channel */
-static bool ar9002_hw_iscal_supported(struct ath_hw *ah,
-				      enum ath9k_cal_types calType)
-{
-	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
-
-	switch (calType & ah->supp_cals) {
-	case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
-		return true;
-	case ADC_GAIN_CAL:
-	case ADC_DC_CAL:
-		if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
-		      conf_is_ht20(conf)))
-			return true;
-		break;
-	}
-	return false;
-}
-
 static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
 {
 	int i;
@@ -541,7 +522,6 @@
 		REG_WRITE(ah, regList[i][0], regList[i][1]);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 
 static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
@@ -567,11 +547,6 @@
 	    AR5416_EEP_TXGAIN_HIGH_POWER)
 		return;
 
-	if (AR_SREV_9285_11(ah)) {
-		REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
-		udelay(10);
-	}
-
 	for (i = 0; i < ARRAY_SIZE(regList); i++)
 		regList[i][1] = REG_READ(ah, regList[i][0]);
 
@@ -651,10 +626,6 @@
 		REG_WRITE(ah, regList[i][0], regList[i][1]);
 
 	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
-
-	if (AR_SREV_9285_11(ah))
-		REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
-
 }
 
 static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
@@ -664,7 +635,7 @@
 			ar9271_hw_pa_cal(ah, is_reset);
 		else
 			ah->pacal_info.skipcount--;
-	} else if (AR_SREV_9285_11_OR_LATER(ah)) {
+	} else if (AR_SREV_9285_12_OR_LATER(ah)) {
 		if (is_reset || !ah->pacal_info.skipcount)
 			ar9285_hw_pa_cal(ah, is_reset);
 		else
@@ -841,8 +812,8 @@
 		if (!ar9285_hw_clc(ah, chan))
 			return false;
 	} else {
-		if (AR_SREV_9280_10_OR_LATER(ah)) {
-			if (!AR_SREV_9287_10_OR_LATER(ah))
+		if (AR_SREV_9280_20_OR_LATER(ah)) {
+			if (!AR_SREV_9287_11_OR_LATER(ah))
 				REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
 					    AR_PHY_ADC_CTL_OFF_PWDADC);
 			REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
@@ -864,8 +835,8 @@
 			return false;
 		}
 
-		if (AR_SREV_9280_10_OR_LATER(ah)) {
-			if (!AR_SREV_9287_10_OR_LATER(ah))
+		if (AR_SREV_9280_20_OR_LATER(ah)) {
+			if (!AR_SREV_9287_11_OR_LATER(ah))
 				REG_SET_BIT(ah, AR_PHY_ADC_CTL,
 					    AR_PHY_ADC_CTL_OFF_PWDADC);
 			REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
@@ -886,24 +857,28 @@
 
 	/* Enable IQ, ADC Gain and ADC DC offset CALs */
 	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
-		if (ar9002_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
+		ah->supp_cals = IQ_MISMATCH_CAL;
+
+		if (AR_SREV_9160_10_OR_LATER(ah) &&
+		    !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) {
+			ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
+
+
 			INIT_CAL(&ah->adcgain_caldata);
 			INSERT_CAL(ah, &ah->adcgain_caldata);
 			ath_print(common, ATH_DBG_CALIBRATE,
 				  "enabling ADC Gain Calibration.\n");
-		}
-		if (ar9002_hw_iscal_supported(ah, ADC_DC_CAL)) {
+
 			INIT_CAL(&ah->adcdc_caldata);
 			INSERT_CAL(ah, &ah->adcdc_caldata);
 			ath_print(common, ATH_DBG_CALIBRATE,
 				  "enabling ADC DC Calibration.\n");
 		}
-		if (ar9002_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
-			INIT_CAL(&ah->iq_caldata);
-			INSERT_CAL(ah, &ah->iq_caldata);
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "enabling IQ Calibration.\n");
-		}
+
+		INIT_CAL(&ah->iq_caldata);
+		INSERT_CAL(ah, &ah->iq_caldata);
+		ath_print(common, ATH_DBG_CALIBRATE,
+			  "enabling IQ Calibration.\n");
 
 		ah->cal_list_curr = ah->cal_list;
 
@@ -959,13 +934,6 @@
 	ar9002_hw_adc_dccal_collect,
 	ar9002_hw_adc_dccal_calibrate
 };
-static const struct ath9k_percal_data adc_init_dc_cal = {
-	ADC_DC_INIT_CAL,
-	MIN_CAL_SAMPLES,
-	INIT_LOG_COUNT,
-	ar9002_hw_adc_dccal_collect,
-	ar9002_hw_adc_dccal_calibrate
-};
 
 static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
 {
@@ -976,22 +944,18 @@
 	}
 
 	if (AR_SREV_9160_10_OR_LATER(ah)) {
-		if (AR_SREV_9280_10_OR_LATER(ah)) {
+		if (AR_SREV_9280_20_OR_LATER(ah)) {
 			ah->iq_caldata.calData = &iq_cal_single_sample;
 			ah->adcgain_caldata.calData =
 				&adc_gain_cal_single_sample;
 			ah->adcdc_caldata.calData =
 				&adc_dc_cal_single_sample;
-			ah->adcdc_calinitdata.calData =
-				&adc_init_dc_cal;
 		} else {
 			ah->iq_caldata.calData = &iq_cal_multi_sample;
 			ah->adcgain_caldata.calData =
 				&adc_gain_cal_multi_sample;
 			ah->adcdc_caldata.calData =
 				&adc_dc_cal_multi_sample;
-			ah->adcdc_calinitdata.calData =
-				&adc_init_dc_cal;
 		}
 		ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
 	}
@@ -1005,7 +969,6 @@
 	priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
 	priv_ops->init_cal = ar9002_hw_init_cal;
 	priv_ops->setup_calibration = ar9002_hw_setup_calibration;
-	priv_ops->iscal_supported = ar9002_hw_iscal_supported;
 
 	ops->calibrate = ar9002_hw_calibrate;
 }
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index 303c63d..a0471f2 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -371,7 +371,6 @@
 			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
 
 			REGWRITE_BUFFER_FLUSH(ah);
-			DISABLE_REGWRITE_BUFFER(ah);
 		}
 
 		udelay(1000);
@@ -468,7 +467,6 @@
 		REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
 	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
@@ -569,14 +567,57 @@
 	ops->config_pci_powersave = ar9002_hw_configpcipowersave;
 
 	ar5008_hw_attach_phy_ops(ah);
-	if (AR_SREV_9280_10_OR_LATER(ah))
+	if (AR_SREV_9280_20_OR_LATER(ah))
 		ar9002_hw_attach_phy_ops(ah);
 
 	ar9002_hw_attach_calib_ops(ah);
 	ar9002_hw_attach_mac_ops(ah);
+}
 
-	if (modparam_force_new_ani)
-		ath9k_hw_attach_ani_ops_new(ah);
-	else
-		ath9k_hw_attach_ani_ops_old(ah);
+void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	u32 modesIndex;
+	int i;
+
+	switch (chan->chanmode) {
+	case CHANNEL_A:
+	case CHANNEL_A_HT20:
+		modesIndex = 1;
+		break;
+	case CHANNEL_A_HT40PLUS:
+	case CHANNEL_A_HT40MINUS:
+		modesIndex = 2;
+		break;
+	case CHANNEL_G:
+	case CHANNEL_G_HT20:
+	case CHANNEL_B:
+		modesIndex = 4;
+		break;
+	case CHANNEL_G_HT40PLUS:
+	case CHANNEL_G_HT40MINUS:
+		modesIndex = 3;
+		break;
+
+	default:
+		return;
+	}
+
+	ENABLE_REGWRITE_BUFFER(ah);
+
+	for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) {
+		u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0);
+		u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex);
+		u32 val_orig;
+
+		if (reg == AR_PHY_CCK_DETECT) {
+			val_orig = REG_READ(ah, reg);
+			val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
+			val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
+
+			REG_WRITE(ah, reg, val|val_orig);
+		} else
+			REG_WRITE(ah, reg, val);
+	}
+
+	REGWRITE_BUFFER_FLUSH(ah);
 }
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index adbf031..c00cdc6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -415,7 +415,6 @@
 	REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 
 static void ar9002_olc_init(struct ath_hw *ah)
@@ -530,3 +529,38 @@
 
 	ar9002_hw_set_nf_limits(ah);
 }
+
+void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+				   struct ath_hw_antcomb_conf *antconf)
+{
+	u32 regval;
+
+	regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+	antconf->main_lna_conf = (regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF) >>
+				  AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S;
+	antconf->alt_lna_conf = (regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF) >>
+				 AR_PHY_9285_ANT_DIV_ALT_LNACONF_S;
+	antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >>
+				  AR_PHY_9285_FAST_DIV_BIAS_S;
+}
+EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_get);
+
+void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah,
+				   struct ath_hw_antcomb_conf *antconf)
+{
+	u32 regval;
+
+	regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+	regval &= ~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF |
+		    AR_PHY_9285_ANT_DIV_ALT_LNACONF |
+		    AR_PHY_9285_FAST_DIV_BIAS);
+	regval |= ((antconf->main_lna_conf << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S)
+		   & AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
+	regval |= ((antconf->alt_lna_conf << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S)
+		   & AR_PHY_9285_ANT_DIV_ALT_LNACONF);
+	regval |= ((antconf->fast_div_bias << AR_PHY_9285_FAST_DIV_BIAS_S)
+		   & AR_PHY_9285_FAST_DIV_BIAS);
+
+	REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
+}
+EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_set);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
index c5151a4..37663db 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
@@ -302,6 +302,8 @@
 #define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
 
 #define AR_PHY_MULTICHAIN_GAIN_CTL          0x99ac
+#define AR_PHY_9285_FAST_DIV_BIAS	    0x00007E00
+#define AR_PHY_9285_FAST_DIV_BIAS_S	    9
 #define AR_PHY_9285_ANT_DIV_CTL_ALL         0x7f000000
 #define AR_PHY_9285_ANT_DIV_CTL             0x01000000
 #define AR_PHY_9285_ANT_DIV_CTL_S           24
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h
deleted file mode 100644
index d3375fc..0000000
--- a/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h
+++ /dev/null
@@ -1,1784 +0,0 @@
-/*
- * Copyright (c) 2010 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef INITVALS_9003_2P0_H
-#define INITVALS_9003_2P0_H
-
-/* AR9003 2.0 */
-
-static const u32 ar9300_2p0_radio_postamble[][5] = {
-	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31},
-	{0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800},
-	{0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20},
-	{0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
-	{0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
-	{0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
-};
-
-static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = {
-	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
-	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
-	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
-	{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
-	{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
-	{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
-	{0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
-	{0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
-	{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
-	{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
-	{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
-	{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
-	{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
-	{0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
-	{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
-	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
-	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
-	{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
-	{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
-	{0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
-	{0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
-	{0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
-	{0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
-	{0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
-	{0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
-	{0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
-	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
-	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
-	{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
-	{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
-	{0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
-	{0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402},
-	{0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404},
-	{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
-	{0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
-	{0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
-	{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
-	{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
-	{0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
-	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
-	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
-	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
-	{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
-	{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
-	{0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83},
-	{0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84},
-	{0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3},
-	{0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5},
-	{0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9},
-	{0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb},
-	{0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-	{0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
-	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-	{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-	{0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
-	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-	{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-	{0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
-	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-};
-
-static const u32 ar9300Modes_fast_clock_2p0[][3] = {
-	/* Addr      5G_HT20     5G_HT40   */
-	{0x00001030, 0x00000268, 0x000004d0},
-	{0x00001070, 0x0000018c, 0x00000318},
-	{0x000010b0, 0x00000fd0, 0x00001fa0},
-	{0x00008014, 0x044c044c, 0x08980898},
-	{0x0000801c, 0x148ec02b, 0x148ec057},
-	{0x00008318, 0x000044c0, 0x00008980},
-	{0x00009e00, 0x03721821, 0x03721821},
-	{0x0000a230, 0x0000000b, 0x00000016},
-	{0x0000a254, 0x00000898, 0x00001130},
-};
-
-static const u32 ar9300_2p0_radio_core[][2] = {
-	/* Addr      allmodes  */
-	{0x00016000, 0x36db6db6},
-	{0x00016004, 0x6db6db40},
-	{0x00016008, 0x73f00000},
-	{0x0001600c, 0x00000000},
-	{0x00016040, 0x7f80fff8},
-	{0x0001604c, 0x76d005b5},
-	{0x00016050, 0x556cf031},
-	{0x00016054, 0x13449440},
-	{0x00016058, 0x0c51c92c},
-	{0x0001605c, 0x3db7fffc},
-	{0x00016060, 0xfffffffc},
-	{0x00016064, 0x000f0278},
-	{0x0001606c, 0x6db60000},
-	{0x00016080, 0x00000000},
-	{0x00016084, 0x0e48048c},
-	{0x00016088, 0x54214514},
-	{0x0001608c, 0x119f481e},
-	{0x00016090, 0x24926490},
-	{0x00016098, 0xd2888888},
-	{0x000160a0, 0x0a108ffe},
-	{0x000160a4, 0x812fc370},
-	{0x000160a8, 0x423c8000},
-	{0x000160b4, 0x92480080},
-	{0x000160c0, 0x00adb6d0},
-	{0x000160c4, 0x6db6db60},
-	{0x000160c8, 0x6db6db6c},
-	{0x000160cc, 0x01e6c000},
-	{0x00016100, 0x3fffbe01},
-	{0x00016104, 0xfff80000},
-	{0x00016108, 0x00080010},
-	{0x00016144, 0x02084080},
-	{0x00016148, 0x00000000},
-	{0x00016280, 0x058a0001},
-	{0x00016284, 0x3d840208},
-	{0x00016288, 0x05a20408},
-	{0x0001628c, 0x00038c07},
-	{0x00016290, 0x40000004},
-	{0x00016294, 0x458aa14f},
-	{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},
-	{0x00016400, 0x36db6db6},
-	{0x00016404, 0x6db6db40},
-	{0x00016408, 0x73f00000},
-	{0x0001640c, 0x00000000},
-	{0x00016440, 0x7f80fff8},
-	{0x0001644c, 0x76d005b5},
-	{0x00016450, 0x556cf031},
-	{0x00016454, 0x13449440},
-	{0x00016458, 0x0c51c92c},
-	{0x0001645c, 0x3db7fffc},
-	{0x00016460, 0xfffffffc},
-	{0x00016464, 0x000f0278},
-	{0x0001646c, 0x6db60000},
-	{0x00016500, 0x3fffbe01},
-	{0x00016504, 0xfff80000},
-	{0x00016508, 0x00080010},
-	{0x00016544, 0x02084080},
-	{0x00016548, 0x00000000},
-	{0x00016780, 0x00000000},
-	{0x00016784, 0x00000000},
-	{0x00016788, 0x00800700},
-	{0x0001678c, 0x00800700},
-	{0x00016790, 0x00800700},
-	{0x00016794, 0x00000000},
-	{0x00016798, 0x00000000},
-	{0x0001679c, 0x00000000},
-	{0x000167a0, 0x00000001},
-	{0x000167a4, 0x00000001},
-	{0x000167a8, 0x00000000},
-	{0x000167ac, 0x00000000},
-	{0x000167b0, 0x00000000},
-	{0x000167b4, 0x00000000},
-	{0x000167b8, 0x00000000},
-	{0x000167bc, 0x00000000},
-	{0x000167c0, 0x000000a0},
-	{0x000167c4, 0x000c0000},
-	{0x000167c8, 0x14021402},
-	{0x000167cc, 0x00001402},
-	{0x000167d0, 0x00000000},
-	{0x000167d4, 0x00000000},
-	{0x00016800, 0x36db6db6},
-	{0x00016804, 0x6db6db40},
-	{0x00016808, 0x73f00000},
-	{0x0001680c, 0x00000000},
-	{0x00016840, 0x7f80fff8},
-	{0x0001684c, 0x76d005b5},
-	{0x00016850, 0x556cf031},
-	{0x00016854, 0x13449440},
-	{0x00016858, 0x0c51c92c},
-	{0x0001685c, 0x3db7fffc},
-	{0x00016860, 0xfffffffc},
-	{0x00016864, 0x000f0278},
-	{0x0001686c, 0x6db60000},
-	{0x00016900, 0x3fffbe01},
-	{0x00016904, 0xfff80000},
-	{0x00016908, 0x00080010},
-	{0x00016944, 0x02084080},
-	{0x00016948, 0x00000000},
-	{0x00016b80, 0x00000000},
-	{0x00016b84, 0x00000000},
-	{0x00016b88, 0x00800700},
-	{0x00016b8c, 0x00800700},
-	{0x00016b90, 0x00800700},
-	{0x00016b94, 0x00000000},
-	{0x00016b98, 0x00000000},
-	{0x00016b9c, 0x00000000},
-	{0x00016ba0, 0x00000001},
-	{0x00016ba4, 0x00000001},
-	{0x00016ba8, 0x00000000},
-	{0x00016bac, 0x00000000},
-	{0x00016bb0, 0x00000000},
-	{0x00016bb4, 0x00000000},
-	{0x00016bb8, 0x00000000},
-	{0x00016bbc, 0x00000000},
-	{0x00016bc0, 0x000000a0},
-	{0x00016bc4, 0x000c0000},
-	{0x00016bc8, 0x14021402},
-	{0x00016bcc, 0x00001402},
-	{0x00016bd0, 0x00000000},
-	{0x00016bd4, 0x00000000},
-};
-
-static const u32 ar9300Common_rx_gain_table_merlin_2p0[][2] = {
-	/* Addr      allmodes  */
-	{0x0000a000, 0x02000101},
-	{0x0000a004, 0x02000102},
-	{0x0000a008, 0x02000103},
-	{0x0000a00c, 0x02000104},
-	{0x0000a010, 0x02000200},
-	{0x0000a014, 0x02000201},
-	{0x0000a018, 0x02000202},
-	{0x0000a01c, 0x02000203},
-	{0x0000a020, 0x02000204},
-	{0x0000a024, 0x02000205},
-	{0x0000a028, 0x02000208},
-	{0x0000a02c, 0x02000302},
-	{0x0000a030, 0x02000303},
-	{0x0000a034, 0x02000304},
-	{0x0000a038, 0x02000400},
-	{0x0000a03c, 0x02010300},
-	{0x0000a040, 0x02010301},
-	{0x0000a044, 0x02010302},
-	{0x0000a048, 0x02000500},
-	{0x0000a04c, 0x02010400},
-	{0x0000a050, 0x02020300},
-	{0x0000a054, 0x02020301},
-	{0x0000a058, 0x02020302},
-	{0x0000a05c, 0x02020303},
-	{0x0000a060, 0x02020400},
-	{0x0000a064, 0x02030300},
-	{0x0000a068, 0x02030301},
-	{0x0000a06c, 0x02030302},
-	{0x0000a070, 0x02030303},
-	{0x0000a074, 0x02030400},
-	{0x0000a078, 0x02040300},
-	{0x0000a07c, 0x02040301},
-	{0x0000a080, 0x02040302},
-	{0x0000a084, 0x02040303},
-	{0x0000a088, 0x02030500},
-	{0x0000a08c, 0x02040400},
-	{0x0000a090, 0x02050203},
-	{0x0000a094, 0x02050204},
-	{0x0000a098, 0x02050205},
-	{0x0000a09c, 0x02040500},
-	{0x0000a0a0, 0x02050301},
-	{0x0000a0a4, 0x02050302},
-	{0x0000a0a8, 0x02050303},
-	{0x0000a0ac, 0x02050400},
-	{0x0000a0b0, 0x02050401},
-	{0x0000a0b4, 0x02050402},
-	{0x0000a0b8, 0x02050403},
-	{0x0000a0bc, 0x02050500},
-	{0x0000a0c0, 0x02050501},
-	{0x0000a0c4, 0x02050502},
-	{0x0000a0c8, 0x02050503},
-	{0x0000a0cc, 0x02050504},
-	{0x0000a0d0, 0x02050600},
-	{0x0000a0d4, 0x02050601},
-	{0x0000a0d8, 0x02050602},
-	{0x0000a0dc, 0x02050603},
-	{0x0000a0e0, 0x02050604},
-	{0x0000a0e4, 0x02050700},
-	{0x0000a0e8, 0x02050701},
-	{0x0000a0ec, 0x02050702},
-	{0x0000a0f0, 0x02050703},
-	{0x0000a0f4, 0x02050704},
-	{0x0000a0f8, 0x02050705},
-	{0x0000a0fc, 0x02050708},
-	{0x0000a100, 0x02050709},
-	{0x0000a104, 0x0205070a},
-	{0x0000a108, 0x0205070b},
-	{0x0000a10c, 0x0205070c},
-	{0x0000a110, 0x0205070d},
-	{0x0000a114, 0x02050710},
-	{0x0000a118, 0x02050711},
-	{0x0000a11c, 0x02050712},
-	{0x0000a120, 0x02050713},
-	{0x0000a124, 0x02050714},
-	{0x0000a128, 0x02050715},
-	{0x0000a12c, 0x02050730},
-	{0x0000a130, 0x02050731},
-	{0x0000a134, 0x02050732},
-	{0x0000a138, 0x02050733},
-	{0x0000a13c, 0x02050734},
-	{0x0000a140, 0x02050735},
-	{0x0000a144, 0x02050750},
-	{0x0000a148, 0x02050751},
-	{0x0000a14c, 0x02050752},
-	{0x0000a150, 0x02050753},
-	{0x0000a154, 0x02050754},
-	{0x0000a158, 0x02050755},
-	{0x0000a15c, 0x02050770},
-	{0x0000a160, 0x02050771},
-	{0x0000a164, 0x02050772},
-	{0x0000a168, 0x02050773},
-	{0x0000a16c, 0x02050774},
-	{0x0000a170, 0x02050775},
-	{0x0000a174, 0x00000776},
-	{0x0000a178, 0x00000776},
-	{0x0000a17c, 0x00000776},
-	{0x0000a180, 0x00000776},
-	{0x0000a184, 0x00000776},
-	{0x0000a188, 0x00000776},
-	{0x0000a18c, 0x00000776},
-	{0x0000a190, 0x00000776},
-	{0x0000a194, 0x00000776},
-	{0x0000a198, 0x00000776},
-	{0x0000a19c, 0x00000776},
-	{0x0000a1a0, 0x00000776},
-	{0x0000a1a4, 0x00000776},
-	{0x0000a1a8, 0x00000776},
-	{0x0000a1ac, 0x00000776},
-	{0x0000a1b0, 0x00000776},
-	{0x0000a1b4, 0x00000776},
-	{0x0000a1b8, 0x00000776},
-	{0x0000a1bc, 0x00000776},
-	{0x0000a1c0, 0x00000776},
-	{0x0000a1c4, 0x00000776},
-	{0x0000a1c8, 0x00000776},
-	{0x0000a1cc, 0x00000776},
-	{0x0000a1d0, 0x00000776},
-	{0x0000a1d4, 0x00000776},
-	{0x0000a1d8, 0x00000776},
-	{0x0000a1dc, 0x00000776},
-	{0x0000a1e0, 0x00000776},
-	{0x0000a1e4, 0x00000776},
-	{0x0000a1e8, 0x00000776},
-	{0x0000a1ec, 0x00000776},
-	{0x0000a1f0, 0x00000776},
-	{0x0000a1f4, 0x00000776},
-	{0x0000a1f8, 0x00000776},
-	{0x0000a1fc, 0x00000776},
-	{0x0000b000, 0x02000101},
-	{0x0000b004, 0x02000102},
-	{0x0000b008, 0x02000103},
-	{0x0000b00c, 0x02000104},
-	{0x0000b010, 0x02000200},
-	{0x0000b014, 0x02000201},
-	{0x0000b018, 0x02000202},
-	{0x0000b01c, 0x02000203},
-	{0x0000b020, 0x02000204},
-	{0x0000b024, 0x02000205},
-	{0x0000b028, 0x02000208},
-	{0x0000b02c, 0x02000302},
-	{0x0000b030, 0x02000303},
-	{0x0000b034, 0x02000304},
-	{0x0000b038, 0x02000400},
-	{0x0000b03c, 0x02010300},
-	{0x0000b040, 0x02010301},
-	{0x0000b044, 0x02010302},
-	{0x0000b048, 0x02000500},
-	{0x0000b04c, 0x02010400},
-	{0x0000b050, 0x02020300},
-	{0x0000b054, 0x02020301},
-	{0x0000b058, 0x02020302},
-	{0x0000b05c, 0x02020303},
-	{0x0000b060, 0x02020400},
-	{0x0000b064, 0x02030300},
-	{0x0000b068, 0x02030301},
-	{0x0000b06c, 0x02030302},
-	{0x0000b070, 0x02030303},
-	{0x0000b074, 0x02030400},
-	{0x0000b078, 0x02040300},
-	{0x0000b07c, 0x02040301},
-	{0x0000b080, 0x02040302},
-	{0x0000b084, 0x02040303},
-	{0x0000b088, 0x02030500},
-	{0x0000b08c, 0x02040400},
-	{0x0000b090, 0x02050203},
-	{0x0000b094, 0x02050204},
-	{0x0000b098, 0x02050205},
-	{0x0000b09c, 0x02040500},
-	{0x0000b0a0, 0x02050301},
-	{0x0000b0a4, 0x02050302},
-	{0x0000b0a8, 0x02050303},
-	{0x0000b0ac, 0x02050400},
-	{0x0000b0b0, 0x02050401},
-	{0x0000b0b4, 0x02050402},
-	{0x0000b0b8, 0x02050403},
-	{0x0000b0bc, 0x02050500},
-	{0x0000b0c0, 0x02050501},
-	{0x0000b0c4, 0x02050502},
-	{0x0000b0c8, 0x02050503},
-	{0x0000b0cc, 0x02050504},
-	{0x0000b0d0, 0x02050600},
-	{0x0000b0d4, 0x02050601},
-	{0x0000b0d8, 0x02050602},
-	{0x0000b0dc, 0x02050603},
-	{0x0000b0e0, 0x02050604},
-	{0x0000b0e4, 0x02050700},
-	{0x0000b0e8, 0x02050701},
-	{0x0000b0ec, 0x02050702},
-	{0x0000b0f0, 0x02050703},
-	{0x0000b0f4, 0x02050704},
-	{0x0000b0f8, 0x02050705},
-	{0x0000b0fc, 0x02050708},
-	{0x0000b100, 0x02050709},
-	{0x0000b104, 0x0205070a},
-	{0x0000b108, 0x0205070b},
-	{0x0000b10c, 0x0205070c},
-	{0x0000b110, 0x0205070d},
-	{0x0000b114, 0x02050710},
-	{0x0000b118, 0x02050711},
-	{0x0000b11c, 0x02050712},
-	{0x0000b120, 0x02050713},
-	{0x0000b124, 0x02050714},
-	{0x0000b128, 0x02050715},
-	{0x0000b12c, 0x02050730},
-	{0x0000b130, 0x02050731},
-	{0x0000b134, 0x02050732},
-	{0x0000b138, 0x02050733},
-	{0x0000b13c, 0x02050734},
-	{0x0000b140, 0x02050735},
-	{0x0000b144, 0x02050750},
-	{0x0000b148, 0x02050751},
-	{0x0000b14c, 0x02050752},
-	{0x0000b150, 0x02050753},
-	{0x0000b154, 0x02050754},
-	{0x0000b158, 0x02050755},
-	{0x0000b15c, 0x02050770},
-	{0x0000b160, 0x02050771},
-	{0x0000b164, 0x02050772},
-	{0x0000b168, 0x02050773},
-	{0x0000b16c, 0x02050774},
-	{0x0000b170, 0x02050775},
-	{0x0000b174, 0x00000776},
-	{0x0000b178, 0x00000776},
-	{0x0000b17c, 0x00000776},
-	{0x0000b180, 0x00000776},
-	{0x0000b184, 0x00000776},
-	{0x0000b188, 0x00000776},
-	{0x0000b18c, 0x00000776},
-	{0x0000b190, 0x00000776},
-	{0x0000b194, 0x00000776},
-	{0x0000b198, 0x00000776},
-	{0x0000b19c, 0x00000776},
-	{0x0000b1a0, 0x00000776},
-	{0x0000b1a4, 0x00000776},
-	{0x0000b1a8, 0x00000776},
-	{0x0000b1ac, 0x00000776},
-	{0x0000b1b0, 0x00000776},
-	{0x0000b1b4, 0x00000776},
-	{0x0000b1b8, 0x00000776},
-	{0x0000b1bc, 0x00000776},
-	{0x0000b1c0, 0x00000776},
-	{0x0000b1c4, 0x00000776},
-	{0x0000b1c8, 0x00000776},
-	{0x0000b1cc, 0x00000776},
-	{0x0000b1d0, 0x00000776},
-	{0x0000b1d4, 0x00000776},
-	{0x0000b1d8, 0x00000776},
-	{0x0000b1dc, 0x00000776},
-	{0x0000b1e0, 0x00000776},
-	{0x0000b1e4, 0x00000776},
-	{0x0000b1e8, 0x00000776},
-	{0x0000b1ec, 0x00000776},
-	{0x0000b1f0, 0x00000776},
-	{0x0000b1f4, 0x00000776},
-	{0x0000b1f8, 0x00000776},
-	{0x0000b1fc, 0x00000776},
-};
-
-static const u32 ar9300_2p0_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 ar9300_2p0_soc_postamble[][5] = {
-	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
-};
-
-static const u32 ar9200_merlin_2p0_radio_core[][2] = {
-	/* Addr      allmodes  */
-	{0x00007800, 0x00040000},
-	{0x00007804, 0xdb005012},
-	{0x00007808, 0x04924914},
-	{0x0000780c, 0x21084210},
-	{0x00007810, 0x6d801300},
-	{0x00007814, 0x0019beff},
-	{0x00007818, 0x07e41000},
-	{0x0000781c, 0x00392000},
-	{0x00007820, 0x92592480},
-	{0x00007824, 0x00040000},
-	{0x00007828, 0xdb005012},
-	{0x0000782c, 0x04924914},
-	{0x00007830, 0x21084210},
-	{0x00007834, 0x6d801300},
-	{0x00007838, 0x0019beff},
-	{0x0000783c, 0x07e40000},
-	{0x00007840, 0x00392000},
-	{0x00007844, 0x92592480},
-	{0x00007848, 0x00100000},
-	{0x0000784c, 0x773f0567},
-	{0x00007850, 0x54214514},
-	{0x00007854, 0x12035828},
-	{0x00007858, 0x92592692},
-	{0x0000785c, 0x00000000},
-	{0x00007860, 0x56400000},
-	{0x00007864, 0x0a8e370e},
-	{0x00007868, 0xc0102850},
-	{0x0000786c, 0x812d4000},
-	{0x00007870, 0x807ec400},
-	{0x00007874, 0x001b6db0},
-	{0x00007878, 0x00376b63},
-	{0x0000787c, 0x06db6db6},
-	{0x00007880, 0x006d8000},
-	{0x00007884, 0xffeffffe},
-	{0x00007888, 0xffeffffe},
-	{0x0000788c, 0x00010000},
-	{0x00007890, 0x02060aeb},
-	{0x00007894, 0x5a108000},
-};
-
-static const u32 ar9300_2p0_baseband_postamble[][5] = {
-	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
-	{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
-	{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
-	{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
-	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
-	{0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
-	{0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044},
-	{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
-	{0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
-	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
-	{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
-	{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},
-	{0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
-	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
-	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
-	{0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0},
-	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
-	{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
-	{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, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
-	{0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-	{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
-	{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
-	{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
-	{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
-	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
-	{0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
-	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
-	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
-	{0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
-	{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
-	{0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
-	{0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
-	{0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
-	{0x0000be04, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
-	{0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
-	{0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
-	{0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
-};
-
-static const u32 ar9300_2p0_baseband_core[][2] = {
-	/* Addr      allmodes  */
-	{0x00009800, 0xafe68e30},
-	{0x00009804, 0xfd14e000},
-	{0x00009808, 0x9c0a9f6b},
-	{0x0000980c, 0x04900000},
-	{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, 0xff55ff55},
-	{0x00009c08, 0x0320ff55},
-	{0x00009c0c, 0x00000000},
-	{0x00009c10, 0x00000000},
-	{0x00009c14, 0x00046384},
-	{0x00009c18, 0x05b6b440},
-	{0x00009c1c, 0x00b6b440},
-	{0x00009d00, 0xc080a333},
-	{0x00009d04, 0x40206c10},
-	{0x00009d08, 0x009c4060},
-	{0x00009d0c, 0x9883800a},
-	{0x00009d10, 0x01834061},
-	{0x00009d14, 0x00c0040b},
-	{0x00009d18, 0x00000000},
-	{0x00009e08, 0x0038230c},
-	{0x00009e24, 0x990bb515},
-	{0x00009e28, 0x0c6f0000},
-	{0x00009e30, 0x06336f77},
-	{0x00009e34, 0x6af6532f},
-	{0x00009e38, 0x0cc80c00},
-	{0x00009e3c, 0xcf946222},
-	{0x00009e40, 0x0d261820},
-	{0x00009e4c, 0x00001004},
-	{0x00009e50, 0x00ff03f1},
-	{0x00009e54, 0x00000000},
-	{0x00009fc0, 0x803e4788},
-	{0x00009fc4, 0x0001efb5},
-	{0x00009fcc, 0x40000014},
-	{0x00009fd0, 0x01193b93},
-	{0x0000a20c, 0x00000000},
-	{0x0000a220, 0x00000000},
-	{0x0000a224, 0x00000000},
-	{0x0000a228, 0x10002310},
-	{0x0000a22c, 0x01036a1e},
-	{0x0000a234, 0x10000fff},
-	{0x0000a23c, 0x00000000},
-	{0x0000a244, 0x0c000000},
-	{0x0000a2a0, 0x00000001},
-	{0x0000a2c0, 0x00000001},
-	{0x0000a2c8, 0x00000000},
-	{0x0000a2cc, 0x18c43433},
-	{0x0000a2d4, 0x00000000},
-	{0x0000a2dc, 0x00000000},
-	{0x0000a2e0, 0x00000000},
-	{0x0000a2e4, 0x00000000},
-	{0x0000a2e8, 0x00000000},
-	{0x0000a2ec, 0x00000000},
-	{0x0000a2f0, 0x00000000},
-	{0x0000a2f4, 0x00000000},
-	{0x0000a2f8, 0x00000000},
-	{0x0000a344, 0x00000000},
-	{0x0000a34c, 0x00000000},
-	{0x0000a350, 0x0000a000},
-	{0x0000a364, 0x00000000},
-	{0x0000a370, 0x00000000},
-	{0x0000a390, 0x00000001},
-	{0x0000a394, 0x00000444},
-	{0x0000a398, 0x001f0e0f},
-	{0x0000a39c, 0x0075393f},
-	{0x0000a3a0, 0xb79f6427},
-	{0x0000a3a4, 0x00000000},
-	{0x0000a3a8, 0xaaaaaaaa},
-	{0x0000a3ac, 0x3c466478},
-	{0x0000a3c0, 0x20202020},
-	{0x0000a3c4, 0x22222220},
-	{0x0000a3c8, 0x20200020},
-	{0x0000a3cc, 0x20202020},
-	{0x0000a3d0, 0x20202020},
-	{0x0000a3d4, 0x20202020},
-	{0x0000a3d8, 0x20202020},
-	{0x0000a3dc, 0x20202020},
-	{0x0000a3e0, 0x20202020},
-	{0x0000a3e4, 0x20202020},
-	{0x0000a3e8, 0x20202020},
-	{0x0000a3ec, 0x20202020},
-	{0x0000a3f0, 0x00000000},
-	{0x0000a3f4, 0x00000246},
-	{0x0000a3f8, 0x0cdbd380},
-	{0x0000a3fc, 0x000f0f01},
-	{0x0000a400, 0x8fa91f01},
-	{0x0000a404, 0x00000000},
-	{0x0000a408, 0x0e79e5c6},
-	{0x0000a40c, 0x00820820},
-	{0x0000a414, 0x1ce739ce},
-	{0x0000a418, 0x2d001dce},
-	{0x0000a41c, 0x1ce739ce},
-	{0x0000a420, 0x000001ce},
-	{0x0000a424, 0x1ce739ce},
-	{0x0000a428, 0x000001ce},
-	{0x0000a42c, 0x1ce739ce},
-	{0x0000a430, 0x1ce739ce},
-	{0x0000a434, 0x00000000},
-	{0x0000a438, 0x00001801},
-	{0x0000a43c, 0x00000000},
-	{0x0000a440, 0x00000000},
-	{0x0000a444, 0x00000000},
-	{0x0000a448, 0x04000080},
-	{0x0000a44c, 0x00000001},
-	{0x0000a450, 0x00010000},
-	{0x0000a458, 0x00000000},
-	{0x0000a600, 0x00000000},
-	{0x0000a604, 0x00000000},
-	{0x0000a608, 0x00000000},
-	{0x0000a60c, 0x00000000},
-	{0x0000a610, 0x00000000},
-	{0x0000a614, 0x00000000},
-	{0x0000a618, 0x00000000},
-	{0x0000a61c, 0x00000000},
-	{0x0000a620, 0x00000000},
-	{0x0000a624, 0x00000000},
-	{0x0000a628, 0x00000000},
-	{0x0000a62c, 0x00000000},
-	{0x0000a630, 0x00000000},
-	{0x0000a634, 0x00000000},
-	{0x0000a638, 0x00000000},
-	{0x0000a63c, 0x00000000},
-	{0x0000a640, 0x00000000},
-	{0x0000a644, 0x3fad9d74},
-	{0x0000a648, 0x0048060a},
-	{0x0000a64c, 0x00000637},
-	{0x0000a670, 0x03020100},
-	{0x0000a674, 0x09080504},
-	{0x0000a678, 0x0d0c0b0a},
-	{0x0000a67c, 0x13121110},
-	{0x0000a680, 0x31301514},
-	{0x0000a684, 0x35343332},
-	{0x0000a688, 0x00000036},
-	{0x0000a690, 0x00000838},
-	{0x0000a7c0, 0x00000000},
-	{0x0000a7c4, 0xfffffffc},
-	{0x0000a7c8, 0x00000000},
-	{0x0000a7cc, 0x00000000},
-	{0x0000a7d0, 0x00000000},
-	{0x0000a7d4, 0x00000004},
-	{0x0000a7dc, 0x00000001},
-	{0x0000a8d0, 0x004b6a8e},
-	{0x0000a8d4, 0x00000820},
-	{0x0000a8dc, 0x00000000},
-	{0x0000a8f0, 0x00000000},
-	{0x0000a8f4, 0x00000000},
-	{0x0000b2d0, 0x00000080},
-	{0x0000b2d4, 0x00000000},
-	{0x0000b2dc, 0x00000000},
-	{0x0000b2e0, 0x00000000},
-	{0x0000b2e4, 0x00000000},
-	{0x0000b2e8, 0x00000000},
-	{0x0000b2ec, 0x00000000},
-	{0x0000b2f0, 0x00000000},
-	{0x0000b2f4, 0x00000000},
-	{0x0000b2f8, 0x00000000},
-	{0x0000b408, 0x0e79e5c0},
-	{0x0000b40c, 0x00820820},
-	{0x0000b420, 0x00000000},
-	{0x0000b8d0, 0x004b6a8e},
-	{0x0000b8d4, 0x00000820},
-	{0x0000b8dc, 0x00000000},
-	{0x0000b8f0, 0x00000000},
-	{0x0000b8f4, 0x00000000},
-	{0x0000c2d0, 0x00000080},
-	{0x0000c2d4, 0x00000000},
-	{0x0000c2dc, 0x00000000},
-	{0x0000c2e0, 0x00000000},
-	{0x0000c2e4, 0x00000000},
-	{0x0000c2e8, 0x00000000},
-	{0x0000c2ec, 0x00000000},
-	{0x0000c2f0, 0x00000000},
-	{0x0000c2f4, 0x00000000},
-	{0x0000c2f8, 0x00000000},
-	{0x0000c408, 0x0e79e5c0},
-	{0x0000c40c, 0x00820820},
-	{0x0000c420, 0x00000000},
-};
-
-static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = {
-	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
-	{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
-	{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
-	{0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
-	{0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
-	{0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
-	{0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
-	{0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
-	{0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
-	{0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
-	{0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
-	{0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
-	{0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
-	{0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
-	{0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
-	{0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
-	{0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
-	{0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
-	{0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
-	{0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
-	{0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
-	{0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
-	{0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
-	{0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
-	{0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
-	{0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
-	{0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
-	{0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
-	{0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
-	{0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
-	{0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
-	{0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
-	{0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
-	{0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
-	{0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
-	{0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
-	{0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
-	{0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
-	{0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
-	{0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
-	{0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
-	{0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
-	{0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
-	{0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
-	{0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
-	{0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
-	{0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
-	{0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
-	{0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
-	{0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
-	{0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
-	{0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
-	{0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
-	{0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
-	{0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
-	{0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
-	{0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
-	{0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
-	{0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
-	{0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
-};
-
-static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = {
-	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
-	{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
-	{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
-	{0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
-	{0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
-	{0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
-	{0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
-	{0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
-	{0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
-	{0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
-	{0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
-	{0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
-	{0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
-	{0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
-	{0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
-	{0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
-	{0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
-	{0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
-	{0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
-	{0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
-	{0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
-	{0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
-	{0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
-	{0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
-	{0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
-	{0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
-	{0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-	{0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
-	{0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
-	{0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
-	{0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
-	{0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
-	{0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
-	{0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
-	{0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
-	{0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
-	{0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
-	{0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
-	{0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
-	{0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
-	{0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
-	{0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
-	{0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
-	{0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
-	{0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
-	{0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
-	{0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
-	{0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
-	{0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
-	{0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
-	{0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
-	{0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
-	{0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-	{0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
-	{0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
-	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-	{0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
-	{0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
-	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-	{0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
-	{0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
-	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-};
-
-static const u32 ar9300Common_rx_gain_table_2p0[][2] = {
-	/* Addr      allmodes  */
-	{0x0000a000, 0x00010000},
-	{0x0000a004, 0x00030002},
-	{0x0000a008, 0x00050004},
-	{0x0000a00c, 0x00810080},
-	{0x0000a010, 0x00830082},
-	{0x0000a014, 0x01810180},
-	{0x0000a018, 0x01830182},
-	{0x0000a01c, 0x01850184},
-	{0x0000a020, 0x01890188},
-	{0x0000a024, 0x018b018a},
-	{0x0000a028, 0x018d018c},
-	{0x0000a02c, 0x01910190},
-	{0x0000a030, 0x01930192},
-	{0x0000a034, 0x01950194},
-	{0x0000a038, 0x038a0196},
-	{0x0000a03c, 0x038c038b},
-	{0x0000a040, 0x0390038d},
-	{0x0000a044, 0x03920391},
-	{0x0000a048, 0x03940393},
-	{0x0000a04c, 0x03960395},
-	{0x0000a050, 0x00000000},
-	{0x0000a054, 0x00000000},
-	{0x0000a058, 0x00000000},
-	{0x0000a05c, 0x00000000},
-	{0x0000a060, 0x00000000},
-	{0x0000a064, 0x00000000},
-	{0x0000a068, 0x00000000},
-	{0x0000a06c, 0x00000000},
-	{0x0000a070, 0x00000000},
-	{0x0000a074, 0x00000000},
-	{0x0000a078, 0x00000000},
-	{0x0000a07c, 0x00000000},
-	{0x0000a080, 0x22222229},
-	{0x0000a084, 0x1d1d1d1d},
-	{0x0000a088, 0x1d1d1d1d},
-	{0x0000a08c, 0x1d1d1d1d},
-	{0x0000a090, 0x171d1d1d},
-	{0x0000a094, 0x11111717},
-	{0x0000a098, 0x00030311},
-	{0x0000a09c, 0x00000000},
-	{0x0000a0a0, 0x00000000},
-	{0x0000a0a4, 0x00000000},
-	{0x0000a0a8, 0x00000000},
-	{0x0000a0ac, 0x00000000},
-	{0x0000a0b0, 0x00000000},
-	{0x0000a0b4, 0x00000000},
-	{0x0000a0b8, 0x00000000},
-	{0x0000a0bc, 0x00000000},
-	{0x0000a0c0, 0x001f0000},
-	{0x0000a0c4, 0x01000101},
-	{0x0000a0c8, 0x011e011f},
-	{0x0000a0cc, 0x011c011d},
-	{0x0000a0d0, 0x02030204},
-	{0x0000a0d4, 0x02010202},
-	{0x0000a0d8, 0x021f0200},
-	{0x0000a0dc, 0x0302021e},
-	{0x0000a0e0, 0x03000301},
-	{0x0000a0e4, 0x031e031f},
-	{0x0000a0e8, 0x0402031d},
-	{0x0000a0ec, 0x04000401},
-	{0x0000a0f0, 0x041e041f},
-	{0x0000a0f4, 0x0502041d},
-	{0x0000a0f8, 0x05000501},
-	{0x0000a0fc, 0x051e051f},
-	{0x0000a100, 0x06010602},
-	{0x0000a104, 0x061f0600},
-	{0x0000a108, 0x061d061e},
-	{0x0000a10c, 0x07020703},
-	{0x0000a110, 0x07000701},
-	{0x0000a114, 0x00000000},
-	{0x0000a118, 0x00000000},
-	{0x0000a11c, 0x00000000},
-	{0x0000a120, 0x00000000},
-	{0x0000a124, 0x00000000},
-	{0x0000a128, 0x00000000},
-	{0x0000a12c, 0x00000000},
-	{0x0000a130, 0x00000000},
-	{0x0000a134, 0x00000000},
-	{0x0000a138, 0x00000000},
-	{0x0000a13c, 0x00000000},
-	{0x0000a140, 0x001f0000},
-	{0x0000a144, 0x01000101},
-	{0x0000a148, 0x011e011f},
-	{0x0000a14c, 0x011c011d},
-	{0x0000a150, 0x02030204},
-	{0x0000a154, 0x02010202},
-	{0x0000a158, 0x021f0200},
-	{0x0000a15c, 0x0302021e},
-	{0x0000a160, 0x03000301},
-	{0x0000a164, 0x031e031f},
-	{0x0000a168, 0x0402031d},
-	{0x0000a16c, 0x04000401},
-	{0x0000a170, 0x041e041f},
-	{0x0000a174, 0x0502041d},
-	{0x0000a178, 0x05000501},
-	{0x0000a17c, 0x051e051f},
-	{0x0000a180, 0x06010602},
-	{0x0000a184, 0x061f0600},
-	{0x0000a188, 0x061d061e},
-	{0x0000a18c, 0x07020703},
-	{0x0000a190, 0x07000701},
-	{0x0000a194, 0x00000000},
-	{0x0000a198, 0x00000000},
-	{0x0000a19c, 0x00000000},
-	{0x0000a1a0, 0x00000000},
-	{0x0000a1a4, 0x00000000},
-	{0x0000a1a8, 0x00000000},
-	{0x0000a1ac, 0x00000000},
-	{0x0000a1b0, 0x00000000},
-	{0x0000a1b4, 0x00000000},
-	{0x0000a1b8, 0x00000000},
-	{0x0000a1bc, 0x00000000},
-	{0x0000a1c0, 0x00000000},
-	{0x0000a1c4, 0x00000000},
-	{0x0000a1c8, 0x00000000},
-	{0x0000a1cc, 0x00000000},
-	{0x0000a1d0, 0x00000000},
-	{0x0000a1d4, 0x00000000},
-	{0x0000a1d8, 0x00000000},
-	{0x0000a1dc, 0x00000000},
-	{0x0000a1e0, 0x00000000},
-	{0x0000a1e4, 0x00000000},
-	{0x0000a1e8, 0x00000000},
-	{0x0000a1ec, 0x00000000},
-	{0x0000a1f0, 0x00000396},
-	{0x0000a1f4, 0x00000396},
-	{0x0000a1f8, 0x00000396},
-	{0x0000a1fc, 0x00000196},
-	{0x0000b000, 0x00010000},
-	{0x0000b004, 0x00030002},
-	{0x0000b008, 0x00050004},
-	{0x0000b00c, 0x00810080},
-	{0x0000b010, 0x00830082},
-	{0x0000b014, 0x01810180},
-	{0x0000b018, 0x01830182},
-	{0x0000b01c, 0x01850184},
-	{0x0000b020, 0x02810280},
-	{0x0000b024, 0x02830282},
-	{0x0000b028, 0x02850284},
-	{0x0000b02c, 0x02890288},
-	{0x0000b030, 0x028b028a},
-	{0x0000b034, 0x0388028c},
-	{0x0000b038, 0x038a0389},
-	{0x0000b03c, 0x038c038b},
-	{0x0000b040, 0x0390038d},
-	{0x0000b044, 0x03920391},
-	{0x0000b048, 0x03940393},
-	{0x0000b04c, 0x03960395},
-	{0x0000b050, 0x00000000},
-	{0x0000b054, 0x00000000},
-	{0x0000b058, 0x00000000},
-	{0x0000b05c, 0x00000000},
-	{0x0000b060, 0x00000000},
-	{0x0000b064, 0x00000000},
-	{0x0000b068, 0x00000000},
-	{0x0000b06c, 0x00000000},
-	{0x0000b070, 0x00000000},
-	{0x0000b074, 0x00000000},
-	{0x0000b078, 0x00000000},
-	{0x0000b07c, 0x00000000},
-	{0x0000b080, 0x32323232},
-	{0x0000b084, 0x2f2f3232},
-	{0x0000b088, 0x23282a2d},
-	{0x0000b08c, 0x1c1e2123},
-	{0x0000b090, 0x14171919},
-	{0x0000b094, 0x0e0e1214},
-	{0x0000b098, 0x03050707},
-	{0x0000b09c, 0x00030303},
-	{0x0000b0a0, 0x00000000},
-	{0x0000b0a4, 0x00000000},
-	{0x0000b0a8, 0x00000000},
-	{0x0000b0ac, 0x00000000},
-	{0x0000b0b0, 0x00000000},
-	{0x0000b0b4, 0x00000000},
-	{0x0000b0b8, 0x00000000},
-	{0x0000b0bc, 0x00000000},
-	{0x0000b0c0, 0x003f0020},
-	{0x0000b0c4, 0x00400041},
-	{0x0000b0c8, 0x0140005f},
-	{0x0000b0cc, 0x0160015f},
-	{0x0000b0d0, 0x017e017f},
-	{0x0000b0d4, 0x02410242},
-	{0x0000b0d8, 0x025f0240},
-	{0x0000b0dc, 0x027f0260},
-	{0x0000b0e0, 0x0341027e},
-	{0x0000b0e4, 0x035f0340},
-	{0x0000b0e8, 0x037f0360},
-	{0x0000b0ec, 0x04400441},
-	{0x0000b0f0, 0x0460045f},
-	{0x0000b0f4, 0x0541047f},
-	{0x0000b0f8, 0x055f0540},
-	{0x0000b0fc, 0x057f0560},
-	{0x0000b100, 0x06400641},
-	{0x0000b104, 0x0660065f},
-	{0x0000b108, 0x067e067f},
-	{0x0000b10c, 0x07410742},
-	{0x0000b110, 0x075f0740},
-	{0x0000b114, 0x077f0760},
-	{0x0000b118, 0x07800781},
-	{0x0000b11c, 0x07a0079f},
-	{0x0000b120, 0x07c107bf},
-	{0x0000b124, 0x000007c0},
-	{0x0000b128, 0x00000000},
-	{0x0000b12c, 0x00000000},
-	{0x0000b130, 0x00000000},
-	{0x0000b134, 0x00000000},
-	{0x0000b138, 0x00000000},
-	{0x0000b13c, 0x00000000},
-	{0x0000b140, 0x003f0020},
-	{0x0000b144, 0x00400041},
-	{0x0000b148, 0x0140005f},
-	{0x0000b14c, 0x0160015f},
-	{0x0000b150, 0x017e017f},
-	{0x0000b154, 0x02410242},
-	{0x0000b158, 0x025f0240},
-	{0x0000b15c, 0x027f0260},
-	{0x0000b160, 0x0341027e},
-	{0x0000b164, 0x035f0340},
-	{0x0000b168, 0x037f0360},
-	{0x0000b16c, 0x04400441},
-	{0x0000b170, 0x0460045f},
-	{0x0000b174, 0x0541047f},
-	{0x0000b178, 0x055f0540},
-	{0x0000b17c, 0x057f0560},
-	{0x0000b180, 0x06400641},
-	{0x0000b184, 0x0660065f},
-	{0x0000b188, 0x067e067f},
-	{0x0000b18c, 0x07410742},
-	{0x0000b190, 0x075f0740},
-	{0x0000b194, 0x077f0760},
-	{0x0000b198, 0x07800781},
-	{0x0000b19c, 0x07a0079f},
-	{0x0000b1a0, 0x07c107bf},
-	{0x0000b1a4, 0x000007c0},
-	{0x0000b1a8, 0x00000000},
-	{0x0000b1ac, 0x00000000},
-	{0x0000b1b0, 0x00000000},
-	{0x0000b1b4, 0x00000000},
-	{0x0000b1b8, 0x00000000},
-	{0x0000b1bc, 0x00000000},
-	{0x0000b1c0, 0x00000000},
-	{0x0000b1c4, 0x00000000},
-	{0x0000b1c8, 0x00000000},
-	{0x0000b1cc, 0x00000000},
-	{0x0000b1d0, 0x00000000},
-	{0x0000b1d4, 0x00000000},
-	{0x0000b1d8, 0x00000000},
-	{0x0000b1dc, 0x00000000},
-	{0x0000b1e0, 0x00000000},
-	{0x0000b1e4, 0x00000000},
-	{0x0000b1e8, 0x00000000},
-	{0x0000b1ec, 0x00000000},
-	{0x0000b1f0, 0x00000396},
-	{0x0000b1f4, 0x00000396},
-	{0x0000b1f8, 0x00000396},
-	{0x0000b1fc, 0x00000196},
-};
-
-static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = {
-	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
-	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
-	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
-	{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
-	{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
-	{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
-	{0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
-	{0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
-	{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
-	{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
-	{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
-	{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
-	{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
-	{0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
-	{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
-	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
-	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
-	{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
-	{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
-	{0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
-	{0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
-	{0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
-	{0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
-	{0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
-	{0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
-	{0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
-	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
-	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
-	{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
-	{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
-	{0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
-	{0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402},
-	{0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404},
-	{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
-	{0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
-	{0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
-	{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
-	{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
-	{0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
-	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
-	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
-	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
-	{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
-	{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
-	{0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83},
-	{0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84},
-	{0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3},
-	{0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5},
-	{0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9},
-	{0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb},
-	{0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
-	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-	{0x00016048, 0x64000001, 0x64000001, 0x64000001, 0x64000001},
-	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-	{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-	{0x00016448, 0x64000001, 0x64000001, 0x64000001, 0x64000001},
-	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-	{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-	{0x00016848, 0x64000001, 0x64000001, 0x64000001, 0x64000001},
-	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-};
-
-static const u32 ar9300_2p0_mac_core[][2] = {
-	/* Addr      allmodes  */
-	{0x00000008, 0x00000000},
-	{0x00000030, 0x00020085},
-	{0x00000034, 0x00000005},
-	{0x00000040, 0x00000000},
-	{0x00000044, 0x00000000},
-	{0x00000048, 0x00000008},
-	{0x0000004c, 0x00000010},
-	{0x00000050, 0x00000000},
-	{0x00001040, 0x002ffc0f},
-	{0x00001044, 0x002ffc0f},
-	{0x00001048, 0x002ffc0f},
-	{0x0000104c, 0x002ffc0f},
-	{0x00001050, 0x002ffc0f},
-	{0x00001054, 0x002ffc0f},
-	{0x00001058, 0x002ffc0f},
-	{0x0000105c, 0x002ffc0f},
-	{0x00001060, 0x002ffc0f},
-	{0x00001064, 0x002ffc0f},
-	{0x000010f0, 0x00000100},
-	{0x00001270, 0x00000000},
-	{0x000012b0, 0x00000000},
-	{0x000012f0, 0x00000000},
-	{0x0000143c, 0x00000000},
-	{0x0000147c, 0x00000000},
-	{0x00008000, 0x00000000},
-	{0x00008004, 0x00000000},
-	{0x00008008, 0x00000000},
-	{0x0000800c, 0x00000000},
-	{0x00008018, 0x00000000},
-	{0x00008020, 0x00000000},
-	{0x00008038, 0x00000000},
-	{0x0000803c, 0x00000000},
-	{0x00008040, 0x00000000},
-	{0x00008044, 0x00000000},
-	{0x00008048, 0x00000000},
-	{0x0000804c, 0xffffffff},
-	{0x00008054, 0x00000000},
-	{0x00008058, 0x00000000},
-	{0x0000805c, 0x000fc78f},
-	{0x00008060, 0x0000000f},
-	{0x00008064, 0x00000000},
-	{0x00008070, 0x00000310},
-	{0x00008074, 0x00000020},
-	{0x00008078, 0x00000000},
-	{0x0000809c, 0x0000000f},
-	{0x000080a0, 0x00000000},
-	{0x000080a4, 0x02ff0000},
-	{0x000080a8, 0x0e070605},
-	{0x000080ac, 0x0000000d},
-	{0x000080b0, 0x00000000},
-	{0x000080b4, 0x00000000},
-	{0x000080b8, 0x00000000},
-	{0x000080bc, 0x00000000},
-	{0x000080c0, 0x2a800000},
-	{0x000080c4, 0x06900168},
-	{0x000080c8, 0x13881c20},
-	{0x000080cc, 0x01f40000},
-	{0x000080d0, 0x00252500},
-	{0x000080d4, 0x00a00000},
-	{0x000080d8, 0x00400000},
-	{0x000080dc, 0x00000000},
-	{0x000080e0, 0xffffffff},
-	{0x000080e4, 0x0000ffff},
-	{0x000080e8, 0x3f3f3f3f},
-	{0x000080ec, 0x00000000},
-	{0x000080f0, 0x00000000},
-	{0x000080f4, 0x00000000},
-	{0x000080fc, 0x00020000},
-	{0x00008100, 0x00000000},
-	{0x00008108, 0x00000052},
-	{0x0000810c, 0x00000000},
-	{0x00008110, 0x00000000},
-	{0x00008114, 0x000007ff},
-	{0x00008118, 0x000000aa},
-	{0x0000811c, 0x00003210},
-	{0x00008124, 0x00000000},
-	{0x00008128, 0x00000000},
-	{0x0000812c, 0x00000000},
-	{0x00008130, 0x00000000},
-	{0x00008134, 0x00000000},
-	{0x00008138, 0x00000000},
-	{0x0000813c, 0x0000ffff},
-	{0x00008144, 0xffffffff},
-	{0x00008168, 0x00000000},
-	{0x0000816c, 0x00000000},
-	{0x00008170, 0x18486200},
-	{0x00008174, 0x33332210},
-	{0x00008178, 0x00000000},
-	{0x0000817c, 0x00020000},
-	{0x000081c0, 0x00000000},
-	{0x000081c4, 0x33332210},
-	{0x000081c8, 0x00000000},
-	{0x000081cc, 0x00000000},
-	{0x000081d4, 0x00000000},
-	{0x000081ec, 0x00000000},
-	{0x000081f0, 0x00000000},
-	{0x000081f4, 0x00000000},
-	{0x000081f8, 0x00000000},
-	{0x000081fc, 0x00000000},
-	{0x00008240, 0x00100000},
-	{0x00008244, 0x0010f424},
-	{0x00008248, 0x00000800},
-	{0x0000824c, 0x0001e848},
-	{0x00008250, 0x00000000},
-	{0x00008254, 0x00000000},
-	{0x00008258, 0x00000000},
-	{0x0000825c, 0x40000000},
-	{0x00008260, 0x00080922},
-	{0x00008264, 0x98a00010},
-	{0x00008268, 0xffffffff},
-	{0x0000826c, 0x0000ffff},
-	{0x00008270, 0x00000000},
-	{0x00008274, 0x40000000},
-	{0x00008278, 0x003e4180},
-	{0x0000827c, 0x00000004},
-	{0x00008284, 0x0000002c},
-	{0x00008288, 0x0000002c},
-	{0x0000828c, 0x000000ff},
-	{0x00008294, 0x00000000},
-	{0x00008298, 0x00000000},
-	{0x0000829c, 0x00000000},
-	{0x00008300, 0x00000140},
-	{0x00008314, 0x00000000},
-	{0x0000831c, 0x0000010d},
-	{0x00008328, 0x00000000},
-	{0x0000832c, 0x00000007},
-	{0x00008330, 0x00000302},
-	{0x00008334, 0x00000700},
-	{0x00008338, 0x00ff0000},
-	{0x0000833c, 0x02400000},
-	{0x00008340, 0x000107ff},
-	{0x00008344, 0xaa48105b},
-	{0x00008348, 0x008f0000},
-	{0x0000835c, 0x00000000},
-	{0x00008360, 0xffffffff},
-	{0x00008364, 0xffffffff},
-	{0x00008368, 0x00000000},
-	{0x00008370, 0x00000000},
-	{0x00008374, 0x000000ff},
-	{0x00008378, 0x00000000},
-	{0x0000837c, 0x00000000},
-	{0x00008380, 0xffffffff},
-	{0x00008384, 0xffffffff},
-	{0x00008390, 0xffffffff},
-	{0x00008394, 0xffffffff},
-	{0x00008398, 0x00000000},
-	{0x0000839c, 0x00000000},
-	{0x000083a0, 0x00000000},
-	{0x000083a4, 0x0000fa14},
-	{0x000083a8, 0x000f0c00},
-	{0x000083ac, 0x33332210},
-	{0x000083b0, 0x33332210},
-	{0x000083b4, 0x33332210},
-	{0x000083b8, 0x33332210},
-	{0x000083bc, 0x00000000},
-	{0x000083c0, 0x00000000},
-	{0x000083c4, 0x00000000},
-	{0x000083c8, 0x00000000},
-	{0x000083cc, 0x00000200},
-	{0x000083d0, 0x000301ff},
-};
-
-static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = {
-	/* Addr      allmodes  */
-	{0x0000a000, 0x00010000},
-	{0x0000a004, 0x00030002},
-	{0x0000a008, 0x00050004},
-	{0x0000a00c, 0x00810080},
-	{0x0000a010, 0x00830082},
-	{0x0000a014, 0x01810180},
-	{0x0000a018, 0x01830182},
-	{0x0000a01c, 0x01850184},
-	{0x0000a020, 0x01890188},
-	{0x0000a024, 0x018b018a},
-	{0x0000a028, 0x018d018c},
-	{0x0000a02c, 0x03820190},
-	{0x0000a030, 0x03840383},
-	{0x0000a034, 0x03880385},
-	{0x0000a038, 0x038a0389},
-	{0x0000a03c, 0x038c038b},
-	{0x0000a040, 0x0390038d},
-	{0x0000a044, 0x03920391},
-	{0x0000a048, 0x03940393},
-	{0x0000a04c, 0x03960395},
-	{0x0000a050, 0x00000000},
-	{0x0000a054, 0x00000000},
-	{0x0000a058, 0x00000000},
-	{0x0000a05c, 0x00000000},
-	{0x0000a060, 0x00000000},
-	{0x0000a064, 0x00000000},
-	{0x0000a068, 0x00000000},
-	{0x0000a06c, 0x00000000},
-	{0x0000a070, 0x00000000},
-	{0x0000a074, 0x00000000},
-	{0x0000a078, 0x00000000},
-	{0x0000a07c, 0x00000000},
-	{0x0000a080, 0x29292929},
-	{0x0000a084, 0x29292929},
-	{0x0000a088, 0x29292929},
-	{0x0000a08c, 0x29292929},
-	{0x0000a090, 0x22292929},
-	{0x0000a094, 0x1d1d2222},
-	{0x0000a098, 0x0c111117},
-	{0x0000a09c, 0x00030303},
-	{0x0000a0a0, 0x00000000},
-	{0x0000a0a4, 0x00000000},
-	{0x0000a0a8, 0x00000000},
-	{0x0000a0ac, 0x00000000},
-	{0x0000a0b0, 0x00000000},
-	{0x0000a0b4, 0x00000000},
-	{0x0000a0b8, 0x00000000},
-	{0x0000a0bc, 0x00000000},
-	{0x0000a0c0, 0x001f0000},
-	{0x0000a0c4, 0x01000101},
-	{0x0000a0c8, 0x011e011f},
-	{0x0000a0cc, 0x011c011d},
-	{0x0000a0d0, 0x02030204},
-	{0x0000a0d4, 0x02010202},
-	{0x0000a0d8, 0x021f0200},
-	{0x0000a0dc, 0x0302021e},
-	{0x0000a0e0, 0x03000301},
-	{0x0000a0e4, 0x031e031f},
-	{0x0000a0e8, 0x0402031d},
-	{0x0000a0ec, 0x04000401},
-	{0x0000a0f0, 0x041e041f},
-	{0x0000a0f4, 0x0502041d},
-	{0x0000a0f8, 0x05000501},
-	{0x0000a0fc, 0x051e051f},
-	{0x0000a100, 0x06010602},
-	{0x0000a104, 0x061f0600},
-	{0x0000a108, 0x061d061e},
-	{0x0000a10c, 0x07020703},
-	{0x0000a110, 0x07000701},
-	{0x0000a114, 0x00000000},
-	{0x0000a118, 0x00000000},
-	{0x0000a11c, 0x00000000},
-	{0x0000a120, 0x00000000},
-	{0x0000a124, 0x00000000},
-	{0x0000a128, 0x00000000},
-	{0x0000a12c, 0x00000000},
-	{0x0000a130, 0x00000000},
-	{0x0000a134, 0x00000000},
-	{0x0000a138, 0x00000000},
-	{0x0000a13c, 0x00000000},
-	{0x0000a140, 0x001f0000},
-	{0x0000a144, 0x01000101},
-	{0x0000a148, 0x011e011f},
-	{0x0000a14c, 0x011c011d},
-	{0x0000a150, 0x02030204},
-	{0x0000a154, 0x02010202},
-	{0x0000a158, 0x021f0200},
-	{0x0000a15c, 0x0302021e},
-	{0x0000a160, 0x03000301},
-	{0x0000a164, 0x031e031f},
-	{0x0000a168, 0x0402031d},
-	{0x0000a16c, 0x04000401},
-	{0x0000a170, 0x041e041f},
-	{0x0000a174, 0x0502041d},
-	{0x0000a178, 0x05000501},
-	{0x0000a17c, 0x051e051f},
-	{0x0000a180, 0x06010602},
-	{0x0000a184, 0x061f0600},
-	{0x0000a188, 0x061d061e},
-	{0x0000a18c, 0x07020703},
-	{0x0000a190, 0x07000701},
-	{0x0000a194, 0x00000000},
-	{0x0000a198, 0x00000000},
-	{0x0000a19c, 0x00000000},
-	{0x0000a1a0, 0x00000000},
-	{0x0000a1a4, 0x00000000},
-	{0x0000a1a8, 0x00000000},
-	{0x0000a1ac, 0x00000000},
-	{0x0000a1b0, 0x00000000},
-	{0x0000a1b4, 0x00000000},
-	{0x0000a1b8, 0x00000000},
-	{0x0000a1bc, 0x00000000},
-	{0x0000a1c0, 0x00000000},
-	{0x0000a1c4, 0x00000000},
-	{0x0000a1c8, 0x00000000},
-	{0x0000a1cc, 0x00000000},
-	{0x0000a1d0, 0x00000000},
-	{0x0000a1d4, 0x00000000},
-	{0x0000a1d8, 0x00000000},
-	{0x0000a1dc, 0x00000000},
-	{0x0000a1e0, 0x00000000},
-	{0x0000a1e4, 0x00000000},
-	{0x0000a1e8, 0x00000000},
-	{0x0000a1ec, 0x00000000},
-	{0x0000a1f0, 0x00000396},
-	{0x0000a1f4, 0x00000396},
-	{0x0000a1f8, 0x00000396},
-	{0x0000a1fc, 0x00000196},
-	{0x0000b000, 0x00010000},
-	{0x0000b004, 0x00030002},
-	{0x0000b008, 0x00050004},
-	{0x0000b00c, 0x00810080},
-	{0x0000b010, 0x00830082},
-	{0x0000b014, 0x01810180},
-	{0x0000b018, 0x01830182},
-	{0x0000b01c, 0x01850184},
-	{0x0000b020, 0x02810280},
-	{0x0000b024, 0x02830282},
-	{0x0000b028, 0x02850284},
-	{0x0000b02c, 0x02890288},
-	{0x0000b030, 0x028b028a},
-	{0x0000b034, 0x0388028c},
-	{0x0000b038, 0x038a0389},
-	{0x0000b03c, 0x038c038b},
-	{0x0000b040, 0x0390038d},
-	{0x0000b044, 0x03920391},
-	{0x0000b048, 0x03940393},
-	{0x0000b04c, 0x03960395},
-	{0x0000b050, 0x00000000},
-	{0x0000b054, 0x00000000},
-	{0x0000b058, 0x00000000},
-	{0x0000b05c, 0x00000000},
-	{0x0000b060, 0x00000000},
-	{0x0000b064, 0x00000000},
-	{0x0000b068, 0x00000000},
-	{0x0000b06c, 0x00000000},
-	{0x0000b070, 0x00000000},
-	{0x0000b074, 0x00000000},
-	{0x0000b078, 0x00000000},
-	{0x0000b07c, 0x00000000},
-	{0x0000b080, 0x32323232},
-	{0x0000b084, 0x2f2f3232},
-	{0x0000b088, 0x23282a2d},
-	{0x0000b08c, 0x1c1e2123},
-	{0x0000b090, 0x14171919},
-	{0x0000b094, 0x0e0e1214},
-	{0x0000b098, 0x03050707},
-	{0x0000b09c, 0x00030303},
-	{0x0000b0a0, 0x00000000},
-	{0x0000b0a4, 0x00000000},
-	{0x0000b0a8, 0x00000000},
-	{0x0000b0ac, 0x00000000},
-	{0x0000b0b0, 0x00000000},
-	{0x0000b0b4, 0x00000000},
-	{0x0000b0b8, 0x00000000},
-	{0x0000b0bc, 0x00000000},
-	{0x0000b0c0, 0x003f0020},
-	{0x0000b0c4, 0x00400041},
-	{0x0000b0c8, 0x0140005f},
-	{0x0000b0cc, 0x0160015f},
-	{0x0000b0d0, 0x017e017f},
-	{0x0000b0d4, 0x02410242},
-	{0x0000b0d8, 0x025f0240},
-	{0x0000b0dc, 0x027f0260},
-	{0x0000b0e0, 0x0341027e},
-	{0x0000b0e4, 0x035f0340},
-	{0x0000b0e8, 0x037f0360},
-	{0x0000b0ec, 0x04400441},
-	{0x0000b0f0, 0x0460045f},
-	{0x0000b0f4, 0x0541047f},
-	{0x0000b0f8, 0x055f0540},
-	{0x0000b0fc, 0x057f0560},
-	{0x0000b100, 0x06400641},
-	{0x0000b104, 0x0660065f},
-	{0x0000b108, 0x067e067f},
-	{0x0000b10c, 0x07410742},
-	{0x0000b110, 0x075f0740},
-	{0x0000b114, 0x077f0760},
-	{0x0000b118, 0x07800781},
-	{0x0000b11c, 0x07a0079f},
-	{0x0000b120, 0x07c107bf},
-	{0x0000b124, 0x000007c0},
-	{0x0000b128, 0x00000000},
-	{0x0000b12c, 0x00000000},
-	{0x0000b130, 0x00000000},
-	{0x0000b134, 0x00000000},
-	{0x0000b138, 0x00000000},
-	{0x0000b13c, 0x00000000},
-	{0x0000b140, 0x003f0020},
-	{0x0000b144, 0x00400041},
-	{0x0000b148, 0x0140005f},
-	{0x0000b14c, 0x0160015f},
-	{0x0000b150, 0x017e017f},
-	{0x0000b154, 0x02410242},
-	{0x0000b158, 0x025f0240},
-	{0x0000b15c, 0x027f0260},
-	{0x0000b160, 0x0341027e},
-	{0x0000b164, 0x035f0340},
-	{0x0000b168, 0x037f0360},
-	{0x0000b16c, 0x04400441},
-	{0x0000b170, 0x0460045f},
-	{0x0000b174, 0x0541047f},
-	{0x0000b178, 0x055f0540},
-	{0x0000b17c, 0x057f0560},
-	{0x0000b180, 0x06400641},
-	{0x0000b184, 0x0660065f},
-	{0x0000b188, 0x067e067f},
-	{0x0000b18c, 0x07410742},
-	{0x0000b190, 0x075f0740},
-	{0x0000b194, 0x077f0760},
-	{0x0000b198, 0x07800781},
-	{0x0000b19c, 0x07a0079f},
-	{0x0000b1a0, 0x07c107bf},
-	{0x0000b1a4, 0x000007c0},
-	{0x0000b1a8, 0x00000000},
-	{0x0000b1ac, 0x00000000},
-	{0x0000b1b0, 0x00000000},
-	{0x0000b1b4, 0x00000000},
-	{0x0000b1b8, 0x00000000},
-	{0x0000b1bc, 0x00000000},
-	{0x0000b1c0, 0x00000000},
-	{0x0000b1c4, 0x00000000},
-	{0x0000b1c8, 0x00000000},
-	{0x0000b1cc, 0x00000000},
-	{0x0000b1d0, 0x00000000},
-	{0x0000b1d4, 0x00000000},
-	{0x0000b1d8, 0x00000000},
-	{0x0000b1dc, 0x00000000},
-	{0x0000b1e0, 0x00000000},
-	{0x0000b1e4, 0x00000000},
-	{0x0000b1e8, 0x00000000},
-	{0x0000b1ec, 0x00000000},
-	{0x0000b1f0, 0x00000396},
-	{0x0000b1f4, 0x00000396},
-	{0x0000b1f8, 0x00000396},
-	{0x0000b1fc, 0x00000196},
-};
-
-static const u32 ar9300_2p0_soc_preamble[][2] = {
-	/* Addr      allmodes  */
-	{0x000040a4, 0x00a0c1c9},
-	{0x00007008, 0x00000000},
-	{0x00007020, 0x00000000},
-	{0x00007034, 0x00000002},
-	{0x00007038, 0x000004c2},
-};
-
-static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0[][2] = {
-	/* Addr      allmodes  */
-	{0x00004040, 0x08212e5e},
-	{0x00004040, 0x0008003b},
-	{0x00004044, 0x00000000},
-};
-
-static const u32 ar9300PciePhy_clkreq_enable_L1_2p0[][2] = {
-	/* Addr      allmodes  */
-	{0x00004040, 0x08253e5e},
-	{0x00004040, 0x0008003b},
-	{0x00004044, 0x00000000},
-};
-
-static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = {
-	/* Addr      allmodes  */
-	{0x00004040, 0x08213e5e},
-	{0x00004040, 0x0008003b},
-	{0x00004044, 0x00000000},
-};
-
-#endif /* INITVALS_9003_2P0_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 4674ea8..9e6edff 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -18,6 +18,11 @@
 #include "hw-ops.h"
 #include "ar9003_phy.h"
 
+enum ar9003_cal_types {
+	IQ_MISMATCH_CAL = BIT(0),
+	TEMP_COMP_CAL = BIT(1),
+};
+
 static void ar9003_hw_setup_calibration(struct ath_hw *ah,
 					struct ath9k_cal_list *currCal)
 {
@@ -50,11 +55,6 @@
 		ath_print(common, ATH_DBG_CALIBRATE,
 			  "starting Temperature Compensation Calibration\n");
 		break;
-	case ADC_DC_INIT_CAL:
-	case ADC_GAIN_CAL:
-	case ADC_DC_CAL:
-		/* Not yet */
-		break;
 	}
 }
 
@@ -314,27 +314,6 @@
 static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
 {
 	ah->iq_caldata.calData = &iq_cal_single_sample;
-	ah->supp_cals = IQ_MISMATCH_CAL;
-}
-
-static bool ar9003_hw_iscal_supported(struct ath_hw *ah,
-				      enum ath9k_cal_types calType)
-{
-	switch (calType & ah->supp_cals) {
-	case IQ_MISMATCH_CAL:
-		/*
-		 * XXX: Run IQ Mismatch for non-CCK only
-		 * Note that CHANNEL_B is never set though.
-		 */
-		return true;
-	case ADC_GAIN_CAL:
-	case ADC_DC_CAL:
-		return false;
-	case TEMP_COMP_CAL:
-		return true;
-	}
-
-	return false;
 }
 
 /*
@@ -773,15 +752,16 @@
 
 	/* Initialize list pointers */
 	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
+	ah->supp_cals = IQ_MISMATCH_CAL;
 
-	if (ar9003_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
+	if (ah->supp_cals & IQ_MISMATCH_CAL) {
 		INIT_CAL(&ah->iq_caldata);
 		INSERT_CAL(ah, &ah->iq_caldata);
 		ath_print(common, ATH_DBG_CALIBRATE,
 			  "enabling IQ Calibration.\n");
 	}
 
-	if (ar9003_hw_iscal_supported(ah, TEMP_COMP_CAL)) {
+	if (ah->supp_cals & TEMP_COMP_CAL) {
 		INIT_CAL(&ah->tempCompCalData);
 		INSERT_CAL(ah, &ah->tempCompCalData);
 		ath_print(common, ATH_DBG_CALIBRATE,
@@ -808,7 +788,6 @@
 	priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
 	priv_ops->init_cal = ar9003_hw_init_cal;
 	priv_ops->setup_calibration = ar9003_hw_setup_calibration;
-	priv_ops->iscal_supported = ar9003_hw_iscal_supported;
 
 	ops->calibrate = ar9003_hw_calibrate;
 }
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 057fb69..c418235 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -968,7 +968,7 @@
 }
 
 static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
-					     enum ieee80211_band freq_band)
+					     enum ath9k_hal_freq_band freq_band)
 {
 	return 1;
 }
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 0641689..c2a0571 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -16,7 +16,6 @@
 
 #include "hw.h"
 #include "ar9003_mac.h"
-#include "ar9003_2p0_initvals.h"
 #include "ar9003_2p2_initvals.h"
 
 /* General hardware code for the AR9003 hadware family */
@@ -32,79 +31,12 @@
 	return false;
 }
 
-/* AR9003 2.0 */
-static void ar9003_2p0_hw_init_mode_regs(struct ath_hw *ah)
-{
-	/* mac */
-	INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
-	INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
-		       ar9300_2p0_mac_core,
-		       ARRAY_SIZE(ar9300_2p0_mac_core), 2);
-	INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
-		       ar9300_2p0_mac_postamble,
-		       ARRAY_SIZE(ar9300_2p0_mac_postamble), 5);
-
-	/* bb */
-	INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
-	INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
-		       ar9300_2p0_baseband_core,
-		       ARRAY_SIZE(ar9300_2p0_baseband_core), 2);
-	INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
-		       ar9300_2p0_baseband_postamble,
-		       ARRAY_SIZE(ar9300_2p0_baseband_postamble), 5);
-
-	/* radio */
-	INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
-	INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
-		       ar9300_2p0_radio_core,
-		       ARRAY_SIZE(ar9300_2p0_radio_core), 2);
-	INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
-		       ar9300_2p0_radio_postamble,
-		       ARRAY_SIZE(ar9300_2p0_radio_postamble), 5);
-
-	/* soc */
-	INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
-		       ar9300_2p0_soc_preamble,
-		       ARRAY_SIZE(ar9300_2p0_soc_preamble), 2);
-	INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
-	INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
-		       ar9300_2p0_soc_postamble,
-		       ARRAY_SIZE(ar9300_2p0_soc_postamble), 5);
-
-	/* rx/tx gain */
-	INIT_INI_ARRAY(&ah->iniModesRxGain,
-		       ar9300Common_rx_gain_table_2p0,
-		       ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), 2);
-	INIT_INI_ARRAY(&ah->iniModesTxGain,
-		       ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
-		       ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
-		       5);
-
-	/* Load PCIE SERDES settings from INI */
-
-	/* Awake Setting */
-
-	INIT_INI_ARRAY(&ah->iniPcieSerdes,
-		       ar9300PciePhy_pll_on_clkreq_disable_L1_2p0,
-		       ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p0),
-		       2);
-
-	/* Sleep Setting */
-
-	INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
-		       ar9300PciePhy_clkreq_enable_L1_2p0,
-		       ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p0),
-		       2);
-
-	/* Fast clock modal settings */
-	INIT_INI_ARRAY(&ah->iniModesAdditional,
-		       ar9300Modes_fast_clock_2p0,
-		       ARRAY_SIZE(ar9300Modes_fast_clock_2p0),
-		       3);
-}
-
-/* AR9003 2.2 */
-static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah)
+/*
+ * The AR9003 family uses a new INI format (pre, core, post
+ * arrays per subsystem). This provides support for the
+ * AR9003 2.2 chipsets.
+ */
+static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 {
 	/* mac */
 	INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@@ -174,57 +106,27 @@
 		       3);
 }
 
-/*
- * The AR9003 family uses a new INI format (pre, core, post
- * arrays per subsystem).
- */
-static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
-{
-	if (AR_SREV_9300_20(ah))
-		ar9003_2p0_hw_init_mode_regs(ah);
-	else
-		ar9003_2p2_hw_init_mode_regs(ah);
-}
-
 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_9300_20(ah))
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-				       ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
-				       ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
-				       5);
-		else
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-				       ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
-				       ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
-				       5);
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+			       ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
+			       ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
+			       5);
 		break;
 	case 1:
-		if (AR_SREV_9300_20(ah))
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-				       ar9300Modes_high_ob_db_tx_gain_table_2p0,
-				       ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0),
-				       5);
-		else
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-				       ar9300Modes_high_ob_db_tx_gain_table_2p2,
-				       ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
-				       5);
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+			       ar9300Modes_high_ob_db_tx_gain_table_2p2,
+			       ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
+			       5);
 		break;
 	case 2:
-		if (AR_SREV_9300_20(ah))
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-				       ar9300Modes_low_ob_db_tx_gain_table_2p0,
-				       ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0),
-				       5);
-		else
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-				       ar9300Modes_low_ob_db_tx_gain_table_2p2,
-				       ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
-				       5);
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+			       ar9300Modes_low_ob_db_tx_gain_table_2p2,
+			       ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
+			       5);
 		break;
 	}
 }
@@ -234,28 +136,16 @@
 	switch (ar9003_hw_get_rx_gain_idx(ah)) {
 	case 0:
 	default:
-		if (AR_SREV_9300_20(ah))
-			INIT_INI_ARRAY(&ah->iniModesRxGain,
-				       ar9300Common_rx_gain_table_2p0,
-				       ARRAY_SIZE(ar9300Common_rx_gain_table_2p0),
-				       2);
-		else
-			INIT_INI_ARRAY(&ah->iniModesRxGain,
-				       ar9300Common_rx_gain_table_2p2,
-				       ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
-				       2);
+		INIT_INI_ARRAY(&ah->iniModesRxGain,
+			       ar9300Common_rx_gain_table_2p2,
+			       ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
+			       2);
 		break;
 	case 1:
-		if (AR_SREV_9300_20(ah))
-			INIT_INI_ARRAY(&ah->iniModesRxGain,
-				       ar9300Common_wo_xlna_rx_gain_table_2p0,
-				       ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0),
-				       2);
-		else
-			INIT_INI_ARRAY(&ah->iniModesRxGain,
-				       ar9300Common_wo_xlna_rx_gain_table_2p2,
-				       ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
-				       2);
+		INIT_INI_ARRAY(&ah->iniModesRxGain,
+			       ar9300Common_wo_xlna_rx_gain_table_2p2,
+			       ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
+			       2);
 		break;
 	}
 }
@@ -333,6 +223,4 @@
 	ar9003_hw_attach_phy_ops(ah);
 	ar9003_hw_attach_calib_ops(ah);
 	ar9003_hw_attach_mac_ops(ah);
-
-	ath9k_hw_attach_ani_ops_new(ah);
 }
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 5b995be..3b424ca 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -185,7 +185,7 @@
 			ath_print(common, ATH_DBG_INTERRUPT,
 				  "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
 
-			REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
+		REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
 		(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
 
 	}
@@ -616,7 +616,8 @@
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
 		} else if (rxsp->status11 & AR_MichaelErr) {
 			rxs->rs_status |= ATH9K_RXERR_MIC;
-		}
+		} else if (rxsp->status11 & AR_KeyMiss)
+			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
 
 	return 0;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index a491854..669b777 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -747,9 +747,9 @@
 static bool ar9003_hw_ani_control(struct ath_hw *ah,
 				  enum ath9k_ani_cmd cmd, int param)
 {
-	struct ar5416AniState *aniState = ah->curani;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_channel *chan = ah->curchan;
+	struct ar5416AniState *aniState = &chan->ani;
 	s32 value, value2;
 
 	switch (cmd & ah->ani_function) {
@@ -1005,15 +1005,13 @@
 
 	ath_print(common, ATH_DBG_ANI,
 		  "ANI parameters: SI=%d, ofdmWS=%s FS=%d "
-		  "MRCcck=%s listenTime=%d CC=%d listen=%d "
+		  "MRCcck=%s listenTime=%d "
 		  "ofdmErrs=%d cckErrs=%d\n",
 		  aniState->spurImmunityLevel,
 		  !aniState->ofdmWeakSigDetectOff ? "on" : "off",
 		  aniState->firstepLevel,
 		  !aniState->mrcCCKOff ? "on" : "off",
 		  aniState->listenTime,
-		  aniState->cycleCount,
-		  aniState->listenTime,
 		  aniState->ofdmPhyErrCount,
 		  aniState->cckPhyErrCount);
 	return true;
@@ -1067,12 +1065,9 @@
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_channel *chan = ah->curchan;
 	struct ath9k_ani_default *iniDef;
-	int index;
 	u32 val;
 
-	index = ath9k_hw_get_ani_channel_idx(ah, chan);
-	aniState = &ah->ani[index];
-	ah->curani = aniState;
+	aniState = &ah->curchan->ani;
 	iniDef = &aniState->iniDef;
 
 	ath_print(common, ATH_DBG_ANI,
@@ -1116,8 +1111,6 @@
 	aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
 	aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
 	aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK;
-
-	aniState->cycleCount = 0;
 }
 
 void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
@@ -1232,7 +1225,7 @@
 void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
-	u32 rxc_pcnt = 0, rxf_pcnt = 0, txf_pcnt = 0, status;
+	u32 status;
 
 	if (likely(!(common->debug_mask & ATH_DBG_RESET)))
 		return;
@@ -1261,11 +1254,12 @@
 		  "** BB mode: BB_gen_controls=0x%08x **\n",
 		  REG_READ(ah, AR_PHY_GEN_CTRL));
 
-	if (ath9k_hw_GetMibCycleCountsPct(ah, &rxc_pcnt, &rxf_pcnt, &txf_pcnt))
+#define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles)
+	if (common->cc_survey.cycles)
 		ath_print(common, ATH_DBG_RESET,
 			  "** BB busy times: rx_clear=%d%%, "
 			  "rx_frame=%d%%, tx_frame=%d%% **\n",
-			  rxc_pcnt, rxf_pcnt, txf_pcnt);
+			  PCT(rx_busy), PCT(rx_frame), PCT(tx_frame));
 
 	ath_print(common, ATH_DBG_RESET,
 		  "==== BB update: done ====\n\n");
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 07f26ee..973c919 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -239,13 +239,11 @@
 	struct sk_buff *bf_mpdu;	/* enclosing frame structure */
 	void *bf_desc;			/* virtual addr of desc */
 	dma_addr_t bf_daddr;		/* physical addr of desc */
-	dma_addr_t bf_buf_addr;		/* physical addr of data buffer */
+	dma_addr_t bf_buf_addr;	/* physical addr of data buffer, for DMA */
 	bool bf_stale;
-	bool bf_isnullfunc;
 	bool bf_tx_aborted;
 	u16 bf_flags;
 	struct ath_buf_state bf_state;
-	dma_addr_t bf_dmacontext;
 	struct ath_wiphy *aphy;
 };
 
@@ -254,7 +252,7 @@
 	struct list_head buf_q;
 	struct ath_node *an;
 	struct ath_atx_ac *ac;
-	struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];
+	unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
 	u16 seq_start;
 	u16 seq_next;
 	u16 baw_size;
@@ -345,12 +343,10 @@
 void ath_tx_tasklet(struct ath_softc *sc);
 void ath_tx_edma_tasklet(struct ath_softc *sc);
 void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
-bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
-void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
-		       u16 tid, u16 *ssn);
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+		      u16 tid, u16 *ssn);
 void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
 void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
-void ath9k_enable_ps(struct ath_softc *sc);
 
 /********/
 /* VIFs */
@@ -423,6 +419,7 @@
 #define ATH_AP_SHORT_CALINTERVAL  100     /* 100 ms */
 #define ATH_ANI_POLLINTERVAL_OLD  100     /* 100 ms */
 #define ATH_ANI_POLLINTERVAL_NEW  1000    /* 1000 ms */
+#define ATH_LONG_CALINTERVAL_INT  1000    /* 1000 ms */
 #define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
 #define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
 
@@ -436,14 +433,6 @@
 /* BTCOEX */
 /**********/
 
-/* Defines the BT AR_BT_COEX_WGHT used */
-enum ath_stomp_type {
-	ATH_BTCOEX_NO_STOMP,
-	ATH_BTCOEX_STOMP_ALL,
-	ATH_BTCOEX_STOMP_LOW,
-	ATH_BTCOEX_STOMP_NONE
-};
-
 struct ath_btcoex {
 	bool hw_timer_enabled;
 	spinlock_t btcoex_lock;
@@ -488,6 +477,60 @@
 void ath_init_leds(struct ath_softc *sc);
 void ath_deinit_leds(struct ath_softc *sc);
 
+/* Antenna diversity/combining */
+#define ATH_ANT_RX_CURRENT_SHIFT 4
+#define ATH_ANT_RX_MAIN_SHIFT 2
+#define ATH_ANT_RX_MASK 0x3
+
+#define ATH_ANT_DIV_COMB_SHORT_SCAN_INTR 50
+#define ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT 0x100
+#define ATH_ANT_DIV_COMB_MAX_PKTCOUNT 0x200
+#define ATH_ANT_DIV_COMB_INIT_COUNT 95
+#define ATH_ANT_DIV_COMB_MAX_COUNT 100
+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30
+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20
+
+#define ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA -3
+#define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1
+#define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4
+#define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2
+#define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2
+
+enum ath9k_ant_div_comb_lna_conf {
+	ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
+	ATH_ANT_DIV_COMB_LNA2,
+	ATH_ANT_DIV_COMB_LNA1,
+	ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2,
+};
+
+struct ath_ant_comb {
+	u16 count;
+	u16 total_pkt_count;
+	bool scan;
+	bool scan_not_start;
+	int main_total_rssi;
+	int alt_total_rssi;
+	int alt_recv_cnt;
+	int main_recv_cnt;
+	int rssi_lna1;
+	int rssi_lna2;
+	int rssi_add;
+	int rssi_sub;
+	int rssi_first;
+	int rssi_second;
+	int rssi_third;
+	bool alt_good;
+	int quick_scan_cnt;
+	int main_conf;
+	enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf;
+	enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf;
+	int first_bias;
+	int second_bias;
+	bool first_ratio;
+	bool second_ratio;
+	unsigned long scan_start_time;
+};
+
 /********************/
 /* Main driver core */
 /********************/
@@ -516,7 +559,6 @@
 #define SC_OP_RXFLUSH                BIT(7)
 #define SC_OP_LED_ASSOCIATED         BIT(8)
 #define SC_OP_LED_ON                 BIT(9)
-#define SC_OP_SCANNING               BIT(10)
 #define SC_OP_TSF_RESET              BIT(11)
 #define SC_OP_BT_PRIORITY_DETECTED   BIT(12)
 #define SC_OP_BT_SCAN		     BIT(13)
@@ -528,8 +570,6 @@
 #define PS_WAIT_FOR_PSPOLL_DATA   BIT(2)
 #define PS_WAIT_FOR_TX_ACK        BIT(3)
 #define PS_BEACON_SYNC            BIT(4)
-#define PS_NULLFUNC_COMPLETED     BIT(5)
-#define PS_ENABLED                BIT(6)
 
 struct ath_wiphy;
 struct ath_rate_table;
@@ -552,6 +592,8 @@
 	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];
 
 	struct tasklet_struct intr_tq;
 	struct tasklet_struct bcon_tasklet;
@@ -580,8 +622,6 @@
 	struct ath_rx rx;
 	struct ath_tx tx;
 	struct ath_beacon beacon;
-	const struct ath_rate_table *cur_rate_table;
-	enum wireless_mode cur_rate_mode;
 	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
 
 	struct ath_led radio_led;
@@ -604,6 +644,8 @@
 	struct ath_btcoex btcoex;
 
 	struct ath_descdma txsdma;
+
+	struct ath_ant_comb ant_comb;
 };
 
 struct ath_wiphy {
@@ -670,7 +712,7 @@
 void ath9k_ps_wakeup(struct ath_softc *sc);
 void ath9k_ps_restore(struct ath_softc *sc);
 
-void ath9k_set_bssid_mask(struct ieee80211_hw *hw);
+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);
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 4d4b22d..4ed010d 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -136,9 +136,10 @@
 	bf = avp->av_bcbuf;
 	skb = bf->bf_mpdu;
 	if (skb) {
-		dma_unmap_single(sc->dev, bf->bf_dmacontext,
+		dma_unmap_single(sc->dev, bf->bf_buf_addr,
 				 skb->len, DMA_TO_DEVICE);
 		dev_kfree_skb_any(skb);
+		bf->bf_buf_addr = 0;
 	}
 
 	/* Get a new beacon from mac80211 */
@@ -162,12 +163,12 @@
 		hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
 	}
 
-	bf->bf_buf_addr = bf->bf_dmacontext =
-		dma_map_single(sc->dev, skb->data,
-			       skb->len, DMA_TO_DEVICE);
+	bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+					 skb->len, DMA_TO_DEVICE);
 	if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
 		dev_kfree_skb_any(skb);
 		bf->bf_mpdu = NULL;
+		bf->bf_buf_addr = 0;
 		ath_print(common, ATH_DBG_FATAL,
 			  "dma_mapping_error on beaconing\n");
 		return NULL;
@@ -252,10 +253,11 @@
 	bf = avp->av_bcbuf;
 	if (bf->bf_mpdu != NULL) {
 		skb = bf->bf_mpdu;
-		dma_unmap_single(sc->dev, bf->bf_dmacontext,
+		dma_unmap_single(sc->dev, bf->bf_buf_addr,
 				 skb->len, DMA_TO_DEVICE);
 		dev_kfree_skb_any(skb);
 		bf->bf_mpdu = NULL;
+		bf->bf_buf_addr = 0;
 	}
 
 	/* NB: the beacon data buffer must be 32-bit aligned. */
@@ -296,12 +298,12 @@
 		avp->tsf_adjust = cpu_to_le64(0);
 
 	bf->bf_mpdu = skb;
-	bf->bf_buf_addr = bf->bf_dmacontext =
-		dma_map_single(sc->dev, skb->data,
-			       skb->len, DMA_TO_DEVICE);
+	bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+					 skb->len, DMA_TO_DEVICE);
 	if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
 		dev_kfree_skb_any(skb);
 		bf->bf_mpdu = NULL;
+		bf->bf_buf_addr = 0;
 		ath_print(common, ATH_DBG_FATAL,
 			  "dma_mapping_error on beacon alloc\n");
 		return -ENOMEM;
@@ -324,10 +326,11 @@
 		bf = avp->av_bcbuf;
 		if (bf->bf_mpdu != NULL) {
 			struct sk_buff *skb = bf->bf_mpdu;
-			dma_unmap_single(sc->dev, bf->bf_dmacontext,
+			dma_unmap_single(sc->dev, bf->bf_buf_addr,
 					 skb->len, DMA_TO_DEVICE);
 			dev_kfree_skb_any(skb);
 			bf->bf_mpdu = NULL;
+			bf->bf_buf_addr = 0;
 		}
 		list_add_tail(&bf->list, &sc->beacon.bbuf);
 
@@ -359,11 +362,12 @@
 		sc->beacon.bmisscnt++;
 
 		if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
-			ath_print(common, ATH_DBG_BEACON,
+			ath_print(common, ATH_DBG_BSTUCK,
 				  "missed %u consecutive beacons\n",
 				  sc->beacon.bmisscnt);
+			ath9k_hw_bstuck_nfcal(ah);
 		} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
-			ath_print(common, ATH_DBG_BEACON,
+			ath_print(common, ATH_DBG_BSTUCK,
 				  "beacon is officially stuck\n");
 			sc->sc_flags |= SC_OP_TSF_RESET;
 			ath_reset(sc, false);
@@ -373,7 +377,7 @@
 	}
 
 	if (sc->beacon.bmisscnt != 0) {
-		ath_print(common, ATH_DBG_BEACON,
+		ath_print(common, ATH_DBG_BSTUCK,
 			  "resume beacon xmit after %u misses\n",
 			  sc->beacon.bmisscnt);
 		sc->beacon.bmisscnt = 0;
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index fb4ac15..6a92e57 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -168,6 +168,7 @@
 static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
 {
 	struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+	u32  val;
 
 	/*
 	 * Program coex mode and weight registers to
@@ -177,6 +178,12 @@
 	REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights);
 	REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2);
 
+	if (AR_SREV_9271(ah)) {
+		val = REG_READ(ah, 0x50040);
+		val &= 0xFFFFFEFF;
+		REG_WRITE(ah, 0x50040, val);
+	}
+
 	REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
 	REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
 
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 4520869..6d50948 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -19,8 +19,7 @@
 
 /* Common calibration code */
 
-/* We can tune this as we go by monitoring really low values */
-#define ATH9K_NF_TOO_LOW	-60
+#define ATH9K_NF_TOO_HIGH	-60
 
 static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
 {
@@ -45,11 +44,39 @@
 	return nfval;
 }
 
-static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
+static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah,
+						    struct ath9k_channel *chan)
+{
+	struct ath_nf_limits *limit;
+
+	if (!chan || IS_CHAN_2GHZ(chan))
+		limit = &ah->nf_2g;
+	else
+		limit = &ah->nf_5g;
+
+	return limit;
+}
+
+static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
+				   struct ath9k_channel *chan)
+{
+	return ath9k_hw_get_nf_limits(ah, chan)->nominal;
+}
+
+
+static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
+					      struct ath9k_hw_cal_data *cal,
 					      int16_t *nfarray)
 {
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ath_nf_limits *limit;
+	struct ath9k_nfcal_hist *h;
+	bool high_nf_mid = false;
 	int i;
 
+	h = cal->nfCalHist;
+	limit = ath9k_hw_get_nf_limits(ah, ah->curchan);
+
 	for (i = 0; i < NUM_NF_READINGS; i++) {
 		h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
 
@@ -63,7 +90,39 @@
 			h[i].privNF =
 				ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
 		}
+
+		if (!h[i].privNF)
+			continue;
+
+		if (h[i].privNF > limit->max) {
+			high_nf_mid = true;
+
+			ath_print(common, ATH_DBG_CALIBRATE,
+				  "NFmid[%d] (%d) > MAX (%d), %s\n",
+				  i, h[i].privNF, limit->max,
+				  (cal->nfcal_interference ?
+				   "not corrected (due to interference)" :
+				   "correcting to MAX"));
+
+			/*
+			 * Normally we limit the average noise floor by the
+			 * hardware specific maximum here. However if we have
+			 * encountered stuck beacons because of interference,
+			 * we bypass this limit here in order to better deal
+			 * with our environment.
+			 */
+			if (!cal->nfcal_interference)
+				h[i].privNF = limit->max;
+		}
 	}
+
+	/*
+	 * If the noise floor seems normal for all chains, assume that
+	 * there is no significant interference in the environment anymore.
+	 * Re-enable the enforcement of the NF maximum again.
+	 */
+	if (!high_nf_mid)
+		cal->nfcal_interference = false;
 }
 
 static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah,
@@ -104,19 +163,6 @@
 	ah->cal_samples = 0;
 }
 
-static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
-				   struct ath9k_channel *chan)
-{
-	struct ath_nf_limits *limit;
-
-	if (!chan || IS_CHAN_2GHZ(chan))
-		limit = &ah->nf_2g;
-	else
-		limit = &ah->nf_5g;
-
-	return limit->nominal;
-}
-
 /* This is done for the currently configured channel */
 bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
 {
@@ -140,7 +186,7 @@
 		return true;
 	}
 
-	if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
+	if (!(ah->supp_cals & currCal->calData->calType))
 		return true;
 
 	ath_print(common, ATH_DBG_CALIBRATE,
@@ -254,7 +300,6 @@
 		}
 	}
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 
 
@@ -277,10 +322,10 @@
 			  "NF calibrated [%s] [chain %d] is %d\n",
 			  (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
 
-		if (nf[i] > limit->max) {
+		if (nf[i] > ATH9K_NF_TOO_HIGH) {
 			ath_print(common, ATH_DBG_CALIBRATE,
 				  "NF[%d] (%d) > MAX (%d), correcting to MAX",
-				  i, nf[i], limit->max);
+				  i, nf[i], ATH9K_NF_TOO_HIGH);
 			nf[i] = limit->max;
 		} else if (nf[i] < limit->min) {
 			ath_print(common, ATH_DBG_CALIBRATE,
@@ -300,34 +345,34 @@
 	struct ieee80211_channel *c = chan->chan;
 	struct ath9k_hw_cal_data *caldata = ah->caldata;
 
-	if (!caldata)
-		return false;
-
 	chan->channelFlags &= (~CHANNEL_CW_INT);
 	if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
 		ath_print(common, ATH_DBG_CALIBRATE,
 			  "NF did not complete in calibration window\n");
-		nf = 0;
-		caldata->rawNoiseFloor = nf;
 		return false;
-	} else {
-		ath9k_hw_do_getnf(ah, nfarray);
-		ath9k_hw_nf_sanitize(ah, nfarray);
-		nf = nfarray[0];
-		if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
-		    && nf > nfThresh) {
-			ath_print(common, ATH_DBG_CALIBRATE,
-				  "noise floor failed detected; "
-				  "detected %d, threshold %d\n",
-				  nf, nfThresh);
-			chan->channelFlags |= CHANNEL_CW_INT;
-		}
+	}
+
+	ath9k_hw_do_getnf(ah, nfarray);
+	ath9k_hw_nf_sanitize(ah, nfarray);
+	nf = nfarray[0];
+	if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
+	    && nf > nfThresh) {
+		ath_print(common, ATH_DBG_CALIBRATE,
+			  "noise floor failed detected; "
+			  "detected %d, threshold %d\n",
+			  nf, nfThresh);
+		chan->channelFlags |= CHANNEL_CW_INT;
+	}
+
+	if (!caldata) {
+		chan->noisefloor = nf;
+		return false;
 	}
 
 	h = caldata->nfCalHist;
 	caldata->nfcal_pending = false;
-	ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
-	caldata->rawNoiseFloor = h[0].privNF;
+	ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
+	chan->noisefloor = h[0].privNF;
 	return true;
 }
 
@@ -355,9 +400,34 @@
 
 s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
 {
-	if (!ah->caldata || !ah->caldata->rawNoiseFloor)
+	if (!ah->curchan || !ah->curchan->noisefloor)
 		return ath9k_hw_get_default_nf(ah, chan);
 
-	return ah->caldata->rawNoiseFloor;
+	return ah->curchan->noisefloor;
 }
 EXPORT_SYMBOL(ath9k_hw_getchan_noise);
+
+void ath9k_hw_bstuck_nfcal(struct ath_hw *ah)
+{
+	struct ath9k_hw_cal_data *caldata = ah->caldata;
+
+	if (unlikely(!caldata))
+		return;
+
+	/*
+	 * If beacons are stuck, the most likely cause is interference.
+	 * Triggering a noise floor calibration at this point helps the
+	 * hardware adapt to a noisy environment much faster.
+	 * To ensure that we recover from stuck beacons quickly, let
+	 * the baseband update the internal NF value itself, similar to
+	 * what is being done after a full reset.
+	 */
+	if (!caldata->nfcal_pending)
+		ath9k_hw_start_nfcal(ah, true);
+	else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF))
+		ath9k_hw_getnf(ah, ah->curchan);
+
+	caldata->nfcal_interference = true;
+}
+EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal);
+
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 0a304b3..b8973eb 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -58,14 +58,6 @@
 		}							\
 	} while (0)
 
-enum ath9k_cal_types {
-	ADC_DC_INIT_CAL = 0x1,
-	ADC_GAIN_CAL = 0x2,
-	ADC_DC_CAL = 0x4,
-	IQ_MISMATCH_CAL = 0x8,
-	TEMP_COMP_CAL = 0x10,
-};
-
 enum ath9k_cal_state {
 	CAL_INACTIVE,
 	CAL_WAITING,
@@ -80,7 +72,7 @@
 #define PER_MAX_LOG_COUNT  10
 
 struct ath9k_percal_data {
-	enum ath9k_cal_types calType;
+	u32 calType;
 	u32 calNumSamples;
 	u32 calCountMax;
 	void (*calCollect) (struct ath_hw *);
@@ -113,6 +105,7 @@
 bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan);
 void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
 				  struct ath9k_channel *chan);
+void ath9k_hw_bstuck_nfcal(struct ath_hw *ah);
 s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
 void ath9k_hw_reset_calibration(struct ath_hw *ah,
 				struct ath9k_cal_list *currCal);
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index c86f7d3..f43a2d9 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -46,12 +46,17 @@
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 
 	if (tx_info->control.hw_key) {
-		if (tx_info->control.hw_key->alg == ALG_WEP)
+		switch (tx_info->control.hw_key->cipher) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
 			return ATH9K_KEY_TYPE_WEP;
-		else if (tx_info->control.hw_key->alg == ALG_TKIP)
+		case WLAN_CIPHER_SUITE_TKIP:
 			return ATH9K_KEY_TYPE_TKIP;
-		else if (tx_info->control.hw_key->alg == ALG_CCMP)
+		case WLAN_CIPHER_SUITE_CCMP:
 			return ATH9K_KEY_TYPE_AES;
+		default:
+			break;
+		}
 	}
 
 	return ATH9K_KEY_TYPE_CLEAR;
@@ -143,264 +148,6 @@
 }
 EXPORT_SYMBOL(ath9k_cmn_get_curchannel);
 
-static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
-			   struct ath9k_keyval *hk, const u8 *addr,
-			   bool authenticator)
-{
-	struct ath_hw *ah = common->ah;
-	const u8 *key_rxmic;
-	const u8 *key_txmic;
-
-	key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
-	key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
-
-	if (addr == NULL) {
-		/*
-		 * Group key installation - only two key cache entries are used
-		 * regardless of splitmic capability since group key is only
-		 * used either for TX or RX.
-		 */
-		if (authenticator) {
-			memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
-			memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
-		} else {
-			memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
-			memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
-		}
-		return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
-	}
-	if (!common->splitmic) {
-		/* TX and RX keys share the same key cache entry. */
-		memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
-		memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
-		return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
-	}
-
-	/* Separate key cache entries for TX and RX */
-
-	/* TX key goes at first index, RX key at +32. */
-	memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
-	if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) {
-		/* TX MIC entry failed. No need to proceed further */
-		ath_print(common, ATH_DBG_FATAL,
-			  "Setting TX MIC Key Failed\n");
-		return 0;
-	}
-
-	memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
-	/* XXX delete tx key on failure? */
-	return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr);
-}
-
-static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
-{
-	int i;
-
-	for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
-		if (test_bit(i, common->keymap) ||
-		    test_bit(i + 64, common->keymap))
-			continue; /* At least one part of TKIP key allocated */
-		if (common->splitmic &&
-		    (test_bit(i + 32, common->keymap) ||
-		     test_bit(i + 64 + 32, common->keymap)))
-			continue; /* At least one part of TKIP key allocated */
-
-		/* Found a free slot for a TKIP key */
-		return i;
-	}
-	return -1;
-}
-
-static int ath_reserve_key_cache_slot(struct ath_common *common,
-				      enum ieee80211_key_alg alg)
-{
-	int i;
-
-	if (alg == ALG_TKIP)
-		return ath_reserve_key_cache_slot_tkip(common);
-
-	/* First, try to find slots that would not be available for TKIP. */
-	if (common->splitmic) {
-		for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
-			if (!test_bit(i, common->keymap) &&
-			    (test_bit(i + 32, common->keymap) ||
-			     test_bit(i + 64, common->keymap) ||
-			     test_bit(i + 64 + 32, common->keymap)))
-				return i;
-			if (!test_bit(i + 32, common->keymap) &&
-			    (test_bit(i, common->keymap) ||
-			     test_bit(i + 64, common->keymap) ||
-			     test_bit(i + 64 + 32, common->keymap)))
-				return i + 32;
-			if (!test_bit(i + 64, common->keymap) &&
-			    (test_bit(i , common->keymap) ||
-			     test_bit(i + 32, common->keymap) ||
-			     test_bit(i + 64 + 32, common->keymap)))
-				return i + 64;
-			if (!test_bit(i + 64 + 32, common->keymap) &&
-			    (test_bit(i, common->keymap) ||
-			     test_bit(i + 32, common->keymap) ||
-			     test_bit(i + 64, common->keymap)))
-				return i + 64 + 32;
-		}
-	} else {
-		for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
-			if (!test_bit(i, common->keymap) &&
-			    test_bit(i + 64, common->keymap))
-				return i;
-			if (test_bit(i, common->keymap) &&
-			    !test_bit(i + 64, common->keymap))
-				return i + 64;
-		}
-	}
-
-	/* No partially used TKIP slots, pick any available slot */
-	for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
-		/* Do not allow slots that could be needed for TKIP group keys
-		 * to be used. This limitation could be removed if we know that
-		 * TKIP will not be used. */
-		if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
-			continue;
-		if (common->splitmic) {
-			if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
-				continue;
-			if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
-				continue;
-		}
-
-		if (!test_bit(i, common->keymap))
-			return i; /* Found a free slot for a key */
-	}
-
-	/* No free slot found */
-	return -1;
-}
-
-/*
- * Configure encryption in the HW.
- */
-int ath9k_cmn_key_config(struct ath_common *common,
-			 struct ieee80211_vif *vif,
-			 struct ieee80211_sta *sta,
-			 struct ieee80211_key_conf *key)
-{
-	struct ath_hw *ah = common->ah;
-	struct ath9k_keyval hk;
-	const u8 *mac = NULL;
-	u8 gmac[ETH_ALEN];
-	int ret = 0;
-	int idx;
-
-	memset(&hk, 0, sizeof(hk));
-
-	switch (key->alg) {
-	case ALG_WEP:
-		hk.kv_type = ATH9K_CIPHER_WEP;
-		break;
-	case ALG_TKIP:
-		hk.kv_type = ATH9K_CIPHER_TKIP;
-		break;
-	case ALG_CCMP:
-		hk.kv_type = ATH9K_CIPHER_AES_CCM;
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	hk.kv_len = key->keylen;
-	memcpy(hk.kv_val, key->key, key->keylen);
-
-	if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
-		switch (vif->type) {
-		case NL80211_IFTYPE_AP:
-			memcpy(gmac, vif->addr, ETH_ALEN);
-			gmac[0] |= 0x01;
-			mac = gmac;
-			idx = ath_reserve_key_cache_slot(common, key->alg);
-			break;
-		case NL80211_IFTYPE_ADHOC:
-			if (!sta) {
-				idx = key->keyidx;
-				break;
-			}
-			memcpy(gmac, sta->addr, ETH_ALEN);
-			gmac[0] |= 0x01;
-			mac = gmac;
-			idx = ath_reserve_key_cache_slot(common, key->alg);
-			break;
-		default:
-			idx = key->keyidx;
-			break;
-		}
-	} else if (key->keyidx) {
-		if (WARN_ON(!sta))
-			return -EOPNOTSUPP;
-		mac = sta->addr;
-
-		if (vif->type != NL80211_IFTYPE_AP) {
-			/* Only keyidx 0 should be used with unicast key, but
-			 * allow this for client mode for now. */
-			idx = key->keyidx;
-		} else
-			return -EIO;
-	} else {
-		if (WARN_ON(!sta))
-			return -EOPNOTSUPP;
-		mac = sta->addr;
-
-		idx = ath_reserve_key_cache_slot(common, key->alg);
-	}
-
-	if (idx < 0)
-		return -ENOSPC; /* no free key cache entries */
-
-	if (key->alg == ALG_TKIP)
-		ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
-				      vif->type == NL80211_IFTYPE_AP);
-	else
-		ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac);
-
-	if (!ret)
-		return -EIO;
-
-	set_bit(idx, common->keymap);
-	if (key->alg == ALG_TKIP) {
-		set_bit(idx + 64, common->keymap);
-		if (common->splitmic) {
-			set_bit(idx + 32, common->keymap);
-			set_bit(idx + 64 + 32, common->keymap);
-		}
-	}
-
-	return idx;
-}
-EXPORT_SYMBOL(ath9k_cmn_key_config);
-
-/*
- * Delete Key.
- */
-void ath9k_cmn_key_delete(struct ath_common *common,
-			  struct ieee80211_key_conf *key)
-{
-	struct ath_hw *ah = common->ah;
-
-	ath9k_hw_keyreset(ah, key->hw_key_idx);
-	if (key->hw_key_idx < IEEE80211_WEP_NKID)
-		return;
-
-	clear_bit(key->hw_key_idx, common->keymap);
-	if (key->alg != ALG_TKIP)
-		return;
-
-	clear_bit(key->hw_key_idx + 64, common->keymap);
-	if (common->splitmic) {
-		ath9k_hw_keyreset(ah, key->hw_key_idx + 32);
-		clear_bit(key->hw_key_idx + 32, common->keymap);
-		clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
-	}
-}
-EXPORT_SYMBOL(ath9k_cmn_key_delete);
-
 int ath9k_cmn_count_streams(unsigned int chainmask, int max)
 {
 	int streams = 0;
@@ -414,6 +161,37 @@
 }
 EXPORT_SYMBOL(ath9k_cmn_count_streams);
 
+/*
+ * Configures appropriate weight based on stomp type.
+ */
+void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
+				  enum ath_stomp_type stomp_type)
+{
+	struct ath_hw *ah = common->ah;
+
+	switch (stomp_type) {
+	case ATH_BTCOEX_STOMP_ALL:
+		ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+					   AR_STOMP_ALL_WLAN_WGHT);
+		break;
+	case ATH_BTCOEX_STOMP_LOW:
+		ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+					   AR_STOMP_LOW_WLAN_WGHT);
+		break;
+	case ATH_BTCOEX_STOMP_NONE:
+		ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+					   AR_STOMP_NONE_WLAN_WGHT);
+		break;
+	default:
+		ath_print(common, ATH_DBG_BTCOEX,
+			  "Invalid Stomptype\n");
+		break;
+	}
+
+	ath9k_hw_btcoex_enable(ah);
+}
+EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp);
+
 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 97809d3..fea3b33 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -52,16 +52,20 @@
 #define ATH_EP_RND(x, mul) 						\
 	((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
 
+/* Defines the BT AR_BT_COEX_WGHT used */
+enum ath_stomp_type {
+	ATH_BTCOEX_NO_STOMP,
+	ATH_BTCOEX_STOMP_ALL,
+	ATH_BTCOEX_STOMP_LOW,
+	ATH_BTCOEX_STOMP_NONE
+};
+
 int ath9k_cmn_padpos(__le16 frame_control);
 int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
 void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
 			       struct ath9k_channel *ichan);
 struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
 					       struct ath_hw *ah);
-int ath9k_cmn_key_config(struct ath_common *common,
-			 struct ieee80211_vif *vif,
-			 struct ieee80211_sta *sta,
-			 struct ieee80211_key_conf *key);
-void ath9k_cmn_key_delete(struct ath_common *common,
-			  struct ieee80211_key_conf *key);
 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);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 54aae93..43e71a9 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -71,7 +71,8 @@
 	.read = read_file_debug,
 	.write = write_file_debug,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 #endif
@@ -116,7 +117,8 @@
 	.read = read_file_tx_chainmask,
 	.write = write_file_tx_chainmask,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -158,7 +160,8 @@
 	.read = read_file_rx_chainmask,
 	.write = write_file_rx_chainmask,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -259,7 +262,8 @@
 static const struct file_operations fops_dma = {
 	.read = read_file_dma,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -375,96 +379,8 @@
 static const struct file_operations fops_interrupt = {
 	.read = read_file_interrupt,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
-};
-
-void ath_debug_stat_rc(struct ath_softc *sc, int final_rate)
-{
-	struct ath_rc_stats *stats;
-
-	stats = &sc->debug.stats.rcstats[final_rate];
-	stats->success++;
-}
-
-void ath_debug_stat_retries(struct ath_softc *sc, int rix,
-			    int xretries, int retries, u8 per)
-{
-	struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix];
-
-	stats->xretries += xretries;
-	stats->retries += retries;
-	stats->per = per;
-}
-
-static ssize_t read_file_rcstat(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, max;
-	int i = 0;
-	ssize_t retval;
-
-	if (sc->cur_rate_table == NULL)
-		return 0;
-
-	max = 80 + sc->cur_rate_table->rate_cnt * 1024 + 1;
-	buf = kmalloc(max, GFP_KERNEL);
-	if (buf == NULL)
-		return -ENOMEM;
-
-	len += sprintf(buf, "%6s %6s %6s "
-		       "%10s %10s %10s %10s\n",
-		       "HT", "MCS", "Rate",
-		       "Success", "Retries", "XRetries", "PER");
-
-	for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
-		u32 ratekbps = sc->cur_rate_table->info[i].ratekbps;
-		struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i];
-		char mcs[5];
-		char htmode[5];
-		int used_mcs = 0, used_htmode = 0;
-
-		if (WLAN_RC_PHY_HT(sc->cur_rate_table->info[i].phy)) {
-			used_mcs = snprintf(mcs, 5, "%d",
-				sc->cur_rate_table->info[i].ratecode);
-
-			if (WLAN_RC_PHY_40(sc->cur_rate_table->info[i].phy))
-				used_htmode = snprintf(htmode, 5, "HT40");
-			else if (WLAN_RC_PHY_20(sc->cur_rate_table->info[i].phy))
-				used_htmode = snprintf(htmode, 5, "HT20");
-			else
-				used_htmode = snprintf(htmode, 5, "????");
-		}
-
-		mcs[used_mcs] = '\0';
-		htmode[used_htmode] = '\0';
-
-		len += snprintf(buf + len, max - len,
-			"%6s %6s %3u.%d: "
-			"%10u %10u %10u %10u\n",
-			htmode,
-			mcs,
-			ratekbps / 1000,
-			(ratekbps % 1000) / 100,
-			stats->success,
-			stats->retries,
-			stats->xretries,
-			stats->per);
-	}
-
-	if (len > max)
-		len = max;
-
-	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-	kfree(buf);
-	return retval;
-}
-
-static const struct file_operations fops_rcstat = {
-	.read = read_file_rcstat,
-	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
@@ -488,26 +404,20 @@
 			       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;
 	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),
-			sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (aphy == NULL)
-			continue;
-		len += snprintf(buf + len, sizeof(buf) - len,
-				"secondary: %s (%s chan=%d ht=%d)\n",
-				wiphy_name(aphy->hw->wiphy),
-				ath_wiphy_state_str(aphy->state),
-				aphy->chan_idx, aphy->chan_is_ht);
-	}
+			ieee80211_frequency_to_channel(chan->center_freq),
+			aphy->chan_is_ht);
 
 	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);
@@ -517,7 +427,51 @@
 	put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4);
 	len += snprintf(buf + len, sizeof(buf) - len,
 			"addrmask: %pM\n", addr);
+	tmp = ath9k_hw_getrxfilter(sc->sc_ah);
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"rfilt: 0x%x", tmp);
+	if (tmp & ATH9K_RX_FILTER_UCAST)
+		len += snprintf(buf + len, sizeof(buf) - len, " UCAST");
+	if (tmp & ATH9K_RX_FILTER_MCAST)
+		len += snprintf(buf + len, sizeof(buf) - len, " MCAST");
+	if (tmp & ATH9K_RX_FILTER_BCAST)
+		len += snprintf(buf + len, sizeof(buf) - len, " BCAST");
+	if (tmp & ATH9K_RX_FILTER_CONTROL)
+		len += snprintf(buf + len, sizeof(buf) - len, " CONTROL");
+	if (tmp & ATH9K_RX_FILTER_BEACON)
+		len += snprintf(buf + len, sizeof(buf) - len, " BEACON");
+	if (tmp & ATH9K_RX_FILTER_PROM)
+		len += snprintf(buf + len, sizeof(buf) - len, " PROM");
+	if (tmp & ATH9K_RX_FILTER_PROBEREQ)
+		len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
+	if (tmp & ATH9K_RX_FILTER_PHYERR)
+		len += snprintf(buf + len, sizeof(buf) - len, " PHYERR");
+	if (tmp & ATH9K_RX_FILTER_MYBEACON)
+		len += snprintf(buf + len, sizeof(buf) - len, " MYBEACON");
+	if (tmp & ATH9K_RX_FILTER_COMP_BAR)
+		len += snprintf(buf + len, sizeof(buf) - len, " COMP_BAR");
+	if (tmp & ATH9K_RX_FILTER_PSPOLL)
+		len += snprintf(buf + len, sizeof(buf) - len, " PSPOLL");
+	if (tmp & ATH9K_RX_FILTER_PHYRADAR)
+		len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
+	if (tmp & ATH9K_RX_FILTER_MCAST_BCAST_ALL)
+		len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL\n");
+	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 = sc->sec_wiphy[i];
+		if (aphy == NULL)
+			continue;
+		chan = aphy->hw->conf.channel;
+		len += snprintf(buf + len, sizeof(buf) - len,
+			"secondary: %s (%s chan=%d ht=%d)\n",
+			wiphy_name(aphy->hw->wiphy),
+			ath_wiphy_state_str(aphy->state),
+			ieee80211_frequency_to_channel(chan->center_freq),
+			aphy->chan_is_ht);
+	}
 	if (len > sizeof(buf))
 		len = sizeof(buf);
 
@@ -623,7 +577,8 @@
 	.read = read_file_wiphy,
 	.write = write_file_wiphy,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 #define PR(str, elem)							\
@@ -663,6 +618,8 @@
 	PR("DESC CFG Error:  ", desc_cfg_err);
 	PR("DATA Underrun:   ", data_underrun);
 	PR("DELIM Underrun:  ", delim_underrun);
+	PR("TX-Pkts-All:     ", tx_pkts_all);
+	PR("TX-Bytes-All:    ", tx_bytes_all);
 
 	if (len > size)
 		len = size;
@@ -676,6 +633,9 @@
 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
 		       struct ath_buf *bf, struct ath_tx_status *ts)
 {
+	TX_STAT_INC(txq->axq_qnum, tx_pkts_all);
+	sc->debug.stats.txstats[txq->axq_qnum].tx_bytes_all += bf->bf_mpdu->len;
+
 	if (bf_isampdu(bf)) {
 		if (bf_isxretried(bf))
 			TX_STAT_INC(txq->axq_qnum, a_xretries);
@@ -702,7 +662,8 @@
 static const struct file_operations fops_xmit = {
 	.read = read_file_xmit,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static ssize_t read_file_recv(struct file *file, char __user *user_buf,
@@ -770,6 +731,13 @@
 	PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
 	PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL);
 
+	len += snprintf(buf + len, size - len,
+			"%18s : %10u\n", "RX-Pkts-All",
+			sc->debug.stats.rxstats.rx_pkts_all);
+	len += snprintf(buf + len, size - len,
+			"%18s : %10u\n", "RX-Bytes-All",
+			sc->debug.stats.rxstats.rx_bytes_all);
+
 	if (len > size)
 		len = size;
 
@@ -788,6 +756,9 @@
 
 	u32 phyerr;
 
+	RX_STAT_INC(rx_pkts_all);
+	sc->debug.stats.rxstats.rx_bytes_all += rs->rs_datalen;
+
 	if (rs->rs_status & ATH9K_RXERR_CRC)
 		RX_STAT_INC(crc_err);
 	if (rs->rs_status & ATH9K_RXERR_DECRYPT)
@@ -814,7 +785,8 @@
 static const struct file_operations fops_recv = {
 	.read = read_file_recv,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
@@ -852,7 +824,8 @@
 	.read = read_file_regidx,
 	.write = write_file_regidx,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static ssize_t read_file_regval(struct file *file, char __user *user_buf,
@@ -894,7 +867,8 @@
 	.read = read_file_regval,
 	.write = write_file_regval,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 int ath9k_init_debug(struct ath_hw *ah)
@@ -924,10 +898,6 @@
 			sc, &fops_interrupt))
 		goto err;
 
-	if (!debugfs_create_file("rcstat", S_IRUSR, sc->debug.debugfs_phy,
-			sc, &fops_rcstat))
-		goto err;
-
 	if (!debugfs_create_file("wiphy", S_IRUSR | S_IWUSR,
 			sc->debug.debugfs_phy, sc, &fops_wiphy))
 		goto err;
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 5d21704..bb08232 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -80,15 +80,12 @@
 	u32 bb_watchdog;
 };
 
-struct ath_rc_stats {
-	u32 success;
-	u32 retries;
-	u32 xretries;
-	u8 per;
-};
-
 /**
  * struct ath_tx_stats - Statistics about TX
+ * @tx_pkts_all:  No. of total frames transmitted, including ones that
+	may have had errors.
+ * @tx_bytes_all:  No. of total bytes transmitted, including ones that
+	may have had errors.
  * @queued: Total MPDUs (non-aggr) queued
  * @completed: Total MPDUs (non-aggr) completed
  * @a_aggr: Total no. of aggregates queued
@@ -107,6 +104,8 @@
  * @delim_urn: TX delimiter underrun errors
  */
 struct ath_tx_stats {
+	u32 tx_pkts_all;
+	u32 tx_bytes_all;
 	u32 queued;
 	u32 completed;
 	u32 a_aggr;
@@ -124,6 +123,10 @@
 
 /**
  * struct ath_rx_stats - RX Statistics
+ * @rx_pkts_all:  No. of total frames received, including ones that
+	may have had errors.
+ * @rx_bytes_all:  No. of total bytes received, including ones that
+	may have had errors.
  * @crc_err: No. of frames with incorrect CRC value
  * @decrypt_crc_err: No. of frames whose CRC check failed after
 	decryption process completed
@@ -136,6 +139,8 @@
  * @phy_err_stats: Individual PHY error statistics
  */
 struct ath_rx_stats {
+	u32 rx_pkts_all;
+	u32 rx_bytes_all;
 	u32 crc_err;
 	u32 decrypt_crc_err;
 	u32 phy_err;
@@ -148,7 +153,6 @@
 
 struct ath_stats {
 	struct ath_interrupt_stats istats;
-	struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
 	struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
 	struct ath_rx_stats rxstats;
 };
@@ -165,12 +169,9 @@
 int ath9k_debug_create_root(void);
 void ath9k_debug_remove_root(void);
 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
-void ath_debug_stat_rc(struct ath_softc *sc, int final_rate);
 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
 		       struct ath_buf *bf, struct ath_tx_status *ts);
 void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
-void ath_debug_stat_retries(struct ath_softc *sc, int rix,
-			    int xretries, int retries, u8 per);
 
 #else
 
@@ -197,11 +198,6 @@
 {
 }
 
-static inline void ath_debug_stat_rc(struct ath_softc *sc,
-				     int final_rate)
-{
-}
-
 static inline void ath_debug_stat_tx(struct ath_softc *sc,
 				     struct ath_txq *txq,
 				     struct ath_buf *bf,
@@ -214,11 +210,6 @@
 {
 }
 
-static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
-					  int xretries, int retries, u8 per)
-{
-}
-
 #endif /* CONFIG_ATH9K_DEBUGFS */
 
 #endif /* DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 0b09db0..dacb45e 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -101,7 +101,7 @@
 #define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
 #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
 				 ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
-#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_10_OR_LATER(ah) && \
+#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \
 				 ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
 
 #define AR_EEPROM_RFSILENT_GPIO_SEL     0x001c
@@ -266,6 +266,8 @@
 	EEP_INTERNAL_REGULATOR,
 	EEP_SWREG,
 	EEP_PAPRD,
+	EEP_MODAL_VER,
+	EEP_ANT_DIV_CTL1,
 };
 
 enum ar5416_rates {
@@ -670,7 +672,8 @@
 	bool (*fill_eeprom)(struct ath_hw *hw);
 	int (*get_eeprom_ver)(struct ath_hw *hw);
 	int (*get_eeprom_rev)(struct ath_hw *hw);
-	u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band);
+	u8 (*get_num_ant_config)(struct ath_hw *hw,
+				 enum ath9k_hal_freq_band band);
 	u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw,
 				      struct ath9k_channel *chan);
 	void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 9cccd12..4fa4d8e 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -179,6 +179,9 @@
 	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
 	struct modal_eep_4k_header *pModal = &eep->modalHeader;
 	struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+	u16 ver_minor;
+
+	ver_minor = pBase->version & AR5416_EEP_VER_MINOR_MASK;
 
 	switch (param) {
 	case EEP_NFTHRESH_2:
@@ -204,7 +207,7 @@
 	case EEP_DB_2:
 		return pModal->db1_1;
 	case EEP_MINOR_REV:
-		return pBase->version & AR5416_EEP_VER_MINOR_MASK;
+		return ver_minor;
 	case EEP_TX_MASK:
 		return pBase->txMask;
 	case EEP_RX_MASK:
@@ -213,6 +216,15 @@
 		return 0;
 	case EEP_PWR_TABLE_OFFSET:
 		return AR5416_PWR_TABLE_OFFSET_DB;
+	case EEP_MODAL_VER:
+		return pModal->version;
+	case EEP_ANT_DIV_CTL1:
+		return pModal->antdiv_ctl1;
+	case EEP_TXGAIN_TYPE:
+		if (ver_minor >= AR5416_EEP_MINOR_VER_19)
+			return pBase->txGainType;
+		else
+			return AR5416_EEP_TXGAIN_ORIGINAL;
 	default:
 		return 0;
 	}
@@ -329,7 +341,7 @@
 		}
 
 		if (i == 0) {
-			if (AR_SREV_9280_10_OR_LATER(ah))
+			if (AR_SREV_9280_20_OR_LATER(ah))
 				ss = (int16_t)(0 - (minPwrT4[i] / 2));
 			else
 				ss = 0;
@@ -496,7 +508,6 @@
 			}
 
 			REGWRITE_BUFFER_FLUSH(ah);
-			DISABLE_REGWRITE_BUFFER(ah);
 		}
 	}
 
@@ -757,7 +768,7 @@
 
 	regulatory->max_power_level = ratesArray[i];
 
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		for (i = 0; i < Ar5416RateSize; i++)
 			ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
 	}
@@ -828,7 +839,6 @@
 	}
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 
 static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
@@ -905,9 +915,6 @@
 		      AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
 	REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
 		      AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
-
-	if (AR_SREV_9285_11(ah))
-		REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
 }
 
 /*
@@ -1105,9 +1112,6 @@
 	}
 
 
-	if (AR_SREV_9285_11(ah))
-		REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
-
 	REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
 		      pModal->switchSettling);
 	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
@@ -1157,7 +1161,7 @@
 }
 
 static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
-					 enum ieee80211_band freq_band)
+					 enum ath9k_hal_freq_band freq_band)
 {
 	return 1;
 }
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index dff2da7..966b949 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -324,7 +324,7 @@
 		minDelta = 0;
 
 		if (i == 0) {
-			if (AR_SREV_9280_10_OR_LATER(ah))
+			if (AR_SREV_9280_20_OR_LATER(ah))
 				ss = (int16_t)(0 - (minPwrT4[i] / 2));
 			else
 				ss = 0;
@@ -883,7 +883,7 @@
 			ratesArray[i] = AR9287_MAX_RATE_POWER;
 	}
 
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		for (i = 0; i < Ar5416RateSize; i++)
 			ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
 	}
@@ -977,7 +977,7 @@
 	else
 		i = rate6mb;
 
-	if (AR_SREV_9280_10_OR_LATER(ah))
+	if (AR_SREV_9280_20_OR_LATER(ah))
 		regulatory->max_power_level =
 			ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
 	else
@@ -1126,7 +1126,7 @@
 }
 
 static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah,
-					     enum ieee80211_band freq_band)
+					     enum ath9k_hal_freq_band freq_band)
 {
 	return 1;
 }
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index afa2b73..76b4d65 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -223,7 +223,7 @@
 	}
 
 	/* Enable fixup for AR_AN_TOP2 if necessary */
-	if (AR_SREV_9280_10_OR_LATER(ah) &&
+	if (AR_SREV_9280_20_OR_LATER(ah) &&
 	    (eep->baseEepHeader.version & 0xff) > 0x0a &&
 	    eep->baseEepHeader.pwdclkind == 0)
 		ah->need_an_top2_fixup = 1;
@@ -317,7 +317,7 @@
 	if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
 		txRxAttenLocal = pModal->txRxAttenCh[i];
 
-		if (AR_SREV_9280_10_OR_LATER(ah)) {
+		if (AR_SREV_9280_20_OR_LATER(ah)) {
 			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
 			      AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
 			      pModal->bswMargin[i]);
@@ -344,7 +344,7 @@
 		}
 	}
 
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		REG_RMW_FIELD(ah,
 		      AR_PHY_RXGAIN + regChainOffset,
 		      AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
@@ -408,7 +408,7 @@
 					      regChainOffset, i);
 	}
 
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		if (IS_CHAN_2GHZ(chan)) {
 			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
 						  AR_AN_RF2G1_CH0_OB,
@@ -461,7 +461,7 @@
 	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
 		      pModal->adcDesiredSize);
 
-	if (!AR_SREV_9280_10_OR_LATER(ah))
+	if (!AR_SREV_9280_20_OR_LATER(ah))
 		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
 			      AR_PHY_DESIRED_SZ_PGA,
 			      pModal->pgaDesiredSize);
@@ -478,7 +478,7 @@
 	REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
 		      pModal->txEndToRxOn);
 
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
 			      pModal->thresh62);
 		REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
@@ -696,7 +696,7 @@
 		}
 
 		if (i == 0) {
-			if (AR_SREV_9280_10_OR_LATER(ah))
+			if (AR_SREV_9280_20_OR_LATER(ah))
 				ss = (int16_t)(0 - (minPwrT4[i] / 2));
 			else
 				ss = 0;
@@ -1291,7 +1291,7 @@
 			ratesArray[i] = AR5416_MAX_RATE_POWER;
 	}
 
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		for (i = 0; i < Ar5416RateSize; i++) {
 			int8_t pwr_table_offset;
 
@@ -1395,7 +1395,7 @@
 	else if (IS_CHAN_HT20(chan))
 		i = rateHt20_0;
 
-	if (AR_SREV_9280_10_OR_LATER(ah))
+	if (AR_SREV_9280_20_OR_LATER(ah))
 		regulatory->max_power_level =
 			ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2;
 	else
@@ -1418,11 +1418,11 @@
 }
 
 static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
-					  enum ieee80211_band freq_band)
+					  enum ath9k_hal_freq_band freq_band)
 {
 	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
 	struct modal_eep_header *pModal =
-		&(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]);
+		&(eep->modalHeader[freq_band]);
 	struct base_eep_header *pBase = &eep->baseEepHeader;
 	u8 num_ant_config;
 
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 3a8ee99..4a9a68b 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -251,36 +251,6 @@
 	}
 }
 
-/*
- * Configures appropriate weight based on stomp type.
- */
-static void ath9k_btcoex_bt_stomp(struct ath_softc *sc,
-				  enum ath_stomp_type stomp_type)
-{
-	struct ath_hw *ah = sc->sc_ah;
-
-	switch (stomp_type) {
-	case ATH_BTCOEX_STOMP_ALL:
-		ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
-					   AR_STOMP_ALL_WLAN_WGHT);
-		break;
-	case ATH_BTCOEX_STOMP_LOW:
-		ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
-					   AR_STOMP_LOW_WLAN_WGHT);
-		break;
-	case ATH_BTCOEX_STOMP_NONE:
-		ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
-					   AR_STOMP_NONE_WLAN_WGHT);
-		break;
-	default:
-		ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
-			  "Invalid Stomptype\n");
-		break;
-	}
-
-	ath9k_hw_btcoex_enable(ah);
-}
-
 static void ath9k_gen_timer_start(struct ath_hw *ah,
 				  struct ath_gen_timer *timer,
 				  u32 timer_next,
@@ -319,6 +289,7 @@
 	struct ath_softc *sc = (struct ath_softc *) data;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_btcoex *btcoex = &sc->btcoex;
+	struct ath_common *common = ath9k_hw_common(ah);
 	u32 timer_period;
 	bool is_btscan;
 
@@ -328,7 +299,7 @@
 
 	spin_lock_bh(&btcoex->btcoex_lock);
 
-	ath9k_btcoex_bt_stomp(sc, is_btscan ? ATH_BTCOEX_STOMP_ALL :
+	ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL :
 			      btcoex->bt_stomp_type);
 
 	spin_unlock_bh(&btcoex->btcoex_lock);
@@ -359,17 +330,18 @@
 	struct ath_softc *sc = (struct ath_softc *)arg;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_btcoex *btcoex = &sc->btcoex;
+	struct ath_common *common = ath9k_hw_common(ah);
 	bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
 
-	ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+	ath_print(common, ATH_DBG_BTCOEX,
 		  "no stomp timer running\n");
 
 	spin_lock_bh(&btcoex->btcoex_lock);
 
 	if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
-		ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE);
+		ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE);
 	 else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
-		ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW);
+		ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW);
 
 	spin_unlock_bh(&btcoex->btcoex_lock);
 }
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 17e7a9a..728d904 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -92,10 +92,10 @@
 	cmd->skb = skb;
 	cmd->hif_dev = hif_dev;
 
-	usb_fill_int_urb(urb, hif_dev->udev,
-			 usb_sndintpipe(hif_dev->udev, USB_REG_OUT_PIPE),
+	usb_fill_bulk_urb(urb, hif_dev->udev,
+			 usb_sndbulkpipe(hif_dev->udev, USB_REG_OUT_PIPE),
 			 skb->data, skb->len,
-			 hif_usb_regout_cb, cmd, 1);
+			 hif_usb_regout_cb, cmd);
 
 	usb_anchor_urb(urb, &hif_dev->regout_submitted);
 	ret = usb_submit_urb(urb, GFP_KERNEL);
@@ -541,7 +541,8 @@
 		}
 
 		usb_fill_int_urb(urb, hif_dev->udev,
-				 usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE),
+				 usb_rcvbulkpipe(hif_dev->udev,
+						 USB_REG_IN_PIPE),
 				 nskb->data, MAX_REG_IN_BUF_SIZE,
 				 ath9k_hif_usb_reg_in_cb, nskb, 1);
 
@@ -720,7 +721,8 @@
 		goto err;
 
 	usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev,
-			 usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE),
+			 usb_rcvbulkpipe(hif_dev->udev,
+					 USB_REG_IN_PIPE),
 			 skb->data, MAX_REG_IN_BUF_SIZE,
 			 ath9k_hif_usb_reg_in_cb, skb, 1);
 
@@ -822,7 +824,9 @@
 
 static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev)
 {
-	int ret;
+	int ret, idx;
+	struct usb_host_interface *alt = &hif_dev->interface->altsetting[0];
+	struct usb_endpoint_descriptor *endp;
 
 	/* Request firmware */
 	ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name,
@@ -850,6 +854,22 @@
 		goto err_fw_download;
 	}
 
+	/* On downloading the firmware to the target, the USB descriptor of EP4
+	 * is 'patched' to change the type of the endpoint to Bulk. This will
+	 * bring down CPU usage during the scan period.
+	 */
+	for (idx = 0; idx < alt->desc.bNumEndpoints; idx++) {
+		endp = &alt->endpoint[idx].desc;
+		if (((endp->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
+				== 0x04) &&
+		    ((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+				== USB_ENDPOINT_XFER_INT)) {
+			endp->bmAttributes &= ~USB_ENDPOINT_XFERTYPE_MASK;
+			endp->bmAttributes |= USB_ENDPOINT_XFER_BULK;
+			endp->bInterval = 0;
+		}
+	}
+
 	return 0;
 
 err_fw_download:
@@ -920,7 +940,8 @@
 	}
 
 	ret = ath9k_htc_hw_init(hif_dev->htc_handle,
-				&hif_dev->udev->dev, hif_dev->device_id);
+				&hif_dev->udev->dev, hif_dev->device_id,
+				hif_dev->udev->product);
 	if (ret) {
 		ret = -EINVAL;
 		goto err_htc_hw_init;
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 43b9e21..75ecf6a 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -316,17 +316,32 @@
 	u8 dtim_count;
 };
 
-#define OP_INVALID        BIT(0)
-#define OP_SCANNING       BIT(1)
-#define OP_FULL_RESET     BIT(2)
-#define OP_LED_ASSOCIATED BIT(3)
-#define OP_LED_ON         BIT(4)
-#define OP_PREAMBLE_SHORT BIT(5)
-#define OP_PROTECT_ENABLE BIT(6)
-#define OP_ASSOCIATED     BIT(7)
-#define OP_ENABLE_BEACON  BIT(8)
-#define OP_LED_DEINIT     BIT(9)
-#define OP_UNPLUGGED      BIT(10)
+struct ath_btcoex {
+	u32 bt_priority_cnt;
+	unsigned long bt_priority_time;
+	int bt_stomp_type; /* Types of BT stomping */
+	u32 btcoex_no_stomp;
+	u32 btcoex_period;
+	u32 btscan_no_stomp;
+};
+
+void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv);
+void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv);
+void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv);
+
+#define OP_INVALID		   BIT(0)
+#define OP_SCANNING		   BIT(1)
+#define OP_FULL_RESET		   BIT(2)
+#define OP_LED_ASSOCIATED	   BIT(3)
+#define OP_LED_ON		   BIT(4)
+#define OP_PREAMBLE_SHORT	   BIT(5)
+#define OP_PROTECT_ENABLE	   BIT(6)
+#define OP_ASSOCIATED		   BIT(7)
+#define OP_ENABLE_BEACON	   BIT(8)
+#define OP_LED_DEINIT		   BIT(9)
+#define OP_UNPLUGGED		   BIT(10)
+#define OP_BT_PRIORITY_DETECTED	   BIT(11)
+#define OP_BT_SCAN		   BIT(12)
 
 struct ath9k_htc_priv {
 	struct device *dev;
@@ -391,6 +406,9 @@
 	int cabq;
 	int hwq_map[WME_NUM_AC];
 
+	struct ath_btcoex btcoex;
+	struct delayed_work coex_period_work;
+	struct delayed_work duty_cycle_work;
 #ifdef CONFIG_ATH9K_HTC_DEBUGFS
 	struct ath9k_debug debug;
 #endif
@@ -443,7 +461,7 @@
 void ath9k_deinit_leds(struct ath9k_htc_priv *priv);
 
 int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
-			   u16 devid);
+			   u16 devid, char *product);
 void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug);
 #ifdef CONFIG_PM
 int ath9k_htc_resume(struct htc_target *htc_handle);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index bd1506e..1b72aa48 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -235,7 +235,14 @@
 	ath9k_hw_get_txq_props(ah, qnum, &qi_be);
 
 	qi.tqi_aifs = qi_be.tqi_aifs;
-	qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
+	/* For WIFI Beacon Distribution
+	 * Long slot time  : 2x cwmin
+	 * Short slot time : 4x cwmin
+	 */
+	if (ah->slottime == ATH9K_SLOT_TIME_20)
+		qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
+	else
+		qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
 	qi.tqi_cwmax = qi_be.tqi_cwmax;
 
 	if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) {
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
new file mode 100644
index 0000000..50eec9a
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -0,0 +1,134 @@
+#include "htc.h"
+
+/******************/
+/*     BTCOEX     */
+/******************/
+
+/*
+ * Detects if there is any priority bt traffic
+ */
+static void ath_detect_bt_priority(struct ath9k_htc_priv *priv)
+{
+	struct ath_btcoex *btcoex = &priv->btcoex;
+	struct ath_hw *ah = priv->ah;
+
+	if (ath9k_hw_gpio_get(ah, ah->btcoex_hw.btpriority_gpio))
+		btcoex->bt_priority_cnt++;
+
+	if (time_after(jiffies, btcoex->bt_priority_time +
+			msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
+		priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
+		/* Detect if colocated bt started scanning */
+		if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
+			ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+				  "BT scan detected");
+			priv->op_flags |= (OP_BT_SCAN |
+					 OP_BT_PRIORITY_DETECTED);
+		} else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
+			ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+				    "BT priority traffic detected");
+			priv->op_flags |= OP_BT_PRIORITY_DETECTED;
+		}
+
+		btcoex->bt_priority_cnt = 0;
+		btcoex->bt_priority_time = jiffies;
+	}
+}
+
+/*
+ * This is the master bt coex work which runs for every
+ * 45ms, bt traffic will be given priority during 55% of this
+ * period while wlan gets remaining 45%
+ */
+static void ath_btcoex_period_work(struct work_struct *work)
+{
+	struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
+						   coex_period_work.work);
+	struct ath_btcoex *btcoex = &priv->btcoex;
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+	u32 timer_period;
+	bool is_btscan;
+	int ret;
+	u8 cmd_rsp, aggr;
+
+	ath_detect_bt_priority(priv);
+
+	is_btscan = !!(priv->op_flags & OP_BT_SCAN);
+
+	aggr = priv->op_flags & OP_BT_PRIORITY_DETECTED;
+
+	WMI_CMD_BUF(WMI_AGGR_LIMIT_CMD, &aggr);
+
+	ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL :
+			btcoex->bt_stomp_type);
+
+	timer_period = is_btscan ? btcoex->btscan_no_stomp :
+		btcoex->btcoex_no_stomp;
+	ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work,
+				     msecs_to_jiffies(timer_period));
+	ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work,
+				     msecs_to_jiffies(btcoex->btcoex_period));
+}
+
+/*
+ * Work to time slice between wlan and bt traffic and
+ * configure weight registers
+ */
+static void ath_btcoex_duty_cycle_work(struct work_struct *work)
+{
+	struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
+						   duty_cycle_work.work);
+	struct ath_hw *ah = priv->ah;
+	struct ath_btcoex *btcoex = &priv->btcoex;
+	struct ath_common *common = ath9k_hw_common(ah);
+	bool is_btscan = priv->op_flags & OP_BT_SCAN;
+
+	ath_print(common, ATH_DBG_BTCOEX,
+		  "time slice work for bt and wlan\n");
+
+	if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
+		ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE);
+	else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
+		ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW);
+}
+
+void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv)
+{
+	struct ath_btcoex *btcoex = &priv->btcoex;
+
+	btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
+	btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
+		btcoex->btcoex_period / 100;
+	btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
+				   btcoex->btcoex_period / 100;
+	INIT_DELAYED_WORK(&priv->coex_period_work, ath_btcoex_period_work);
+	INIT_DELAYED_WORK(&priv->duty_cycle_work, ath_btcoex_duty_cycle_work);
+}
+
+/*
+ * (Re)start btcoex work
+ */
+
+void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
+{
+	struct ath_btcoex *btcoex = &priv->btcoex;
+	struct ath_hw *ah = priv->ah;
+
+	ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+		  "Starting btcoex work");
+
+	btcoex->bt_priority_cnt = 0;
+	btcoex->bt_priority_time = jiffies;
+	priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
+	ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0);
+}
+
+
+/*
+ * Cancel btcoex and bt duty cycle work.
+ */
+void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv)
+{
+	cancel_delayed_work_sync(&priv->coex_period_work);
+	cancel_delayed_work_sync(&priv->duty_cycle_work);
+}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 2d42791..3d7b97f 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -41,6 +41,8 @@
 	.max_power = 20, \
 }
 
+#define ATH_HTC_BTCOEX_PRODUCT_ID "wb193"
+
 static struct ieee80211_channel ath9k_2ghz_channels[] = {
 	CHAN2G(2412, 0), /* Channel 1 */
 	CHAN2G(2417, 1), /* Channel 2 */
@@ -378,15 +380,6 @@
 	atomic_inc(&priv->wmi->mwrite_cnt);
 }
 
-static void ath9k_disable_regwrite_buffer(void *hw_priv)
-{
-	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;
-
-	atomic_dec(&priv->wmi->mwrite_cnt);
-}
-
 static void ath9k_regwrite_flush(void *hw_priv)
 {
 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
@@ -395,6 +388,8 @@
 	u32 rsp_status;
 	int r;
 
+	atomic_dec(&priv->wmi->mwrite_cnt);
+
 	mutex_lock(&priv->wmi->multi_write_mutex);
 
 	if (priv->wmi->multi_write_idx) {
@@ -418,7 +413,6 @@
 	.read = ath9k_regread,
 	.write = ath9k_regwrite,
 	.enable_write_buffer = ath9k_enable_regwrite_buffer,
-	.disable_write_buffer = ath9k_disable_regwrite_buffer,
 	.write_flush = ath9k_regwrite_flush,
 };
 
@@ -559,17 +553,20 @@
 		common->keymax = ATH_KEYMAX;
 	}
 
+	if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
+		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
+
 	/*
 	 * Reset the key cache since some parts do not
 	 * reset the contents on initial power up.
 	 */
 	for (i = 0; i < common->keymax; i++)
-		ath9k_hw_keyreset(priv->ah, (u16) i);
+		ath_hw_keyreset(common, (u16) i);
 }
 
 static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
 {
-	if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) {
+	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
 		priv->sbands[IEEE80211_BAND_2GHZ].channels =
 			ath9k_2ghz_channels;
 		priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
@@ -580,7 +577,7 @@
 			ARRAY_SIZE(ath9k_legacy_rates);
 	}
 
-	if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) {
+	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
 		priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
 		priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
 		priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
@@ -599,13 +596,36 @@
 	common->tx_chainmask = priv->ah->caps.tx_chainmask;
 	common->rx_chainmask = priv->ah->caps.rx_chainmask;
 
-	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
-		memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
+	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
 
 	priv->ah->opmode = NL80211_IFTYPE_STATION;
 }
 
-static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid)
+static void ath9k_init_btcoex(struct ath9k_htc_priv *priv)
+{
+	int qnum;
+
+	switch (priv->ah->btcoex_hw.scheme) {
+	case ATH_BTCOEX_CFG_NONE:
+		break;
+	case ATH_BTCOEX_CFG_3WIRE:
+		priv->ah->btcoex_hw.btactive_gpio = 7;
+		priv->ah->btcoex_hw.btpriority_gpio = 6;
+		priv->ah->btcoex_hw.wlanactive_gpio = 8;
+		priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
+		ath9k_hw_btcoex_init_3wire(priv->ah);
+		ath_htc_init_btcoex_work(priv);
+		qnum = priv->hwq_map[WME_AC_BE];
+		ath9k_hw_init_btcoex_hw(priv->ah, qnum);
+		break;
+	default:
+		WARN_ON(1);
+		break;
+	}
+}
+
+static int ath9k_init_priv(struct ath9k_htc_priv *priv,
+			   u16 devid, char *product)
 {
 	struct ath_hw *ah = NULL;
 	struct ath_common *common;
@@ -672,6 +692,11 @@
 	ath9k_init_channels_rates(priv);
 	ath9k_init_misc(priv);
 
+	if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
+		ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
+		ath9k_init_btcoex(priv);
+	}
+
 	return 0;
 
 err_queues:
@@ -715,18 +740,18 @@
 	hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
 		sizeof(struct htc_frame_hdr) + 4;
 
-	if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
+	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
 			&priv->sbands[IEEE80211_BAND_2GHZ];
-	if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
+	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
 			&priv->sbands[IEEE80211_BAND_5GHZ];
 
 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
-		if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
+		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
 			setup_ht_cap(priv,
 				     &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
-		if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
+		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
 			setup_ht_cap(priv,
 				     &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
 	}
@@ -734,7 +759,8 @@
 	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
 }
 
-static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid)
+static int ath9k_init_device(struct ath9k_htc_priv *priv,
+			     u16 devid, char *product)
 {
 	struct ieee80211_hw *hw = priv->hw;
 	struct ath_common *common;
@@ -743,7 +769,7 @@
 	struct ath_regulatory *reg;
 
 	/* Bring up device */
-	error = ath9k_init_priv(priv, devid);
+	error = ath9k_init_priv(priv, devid, product);
 	if (error != 0)
 		goto err_init;
 
@@ -801,7 +827,7 @@
 }
 
 int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
-			   u16 devid)
+			   u16 devid, char *product)
 {
 	struct ieee80211_hw *hw;
 	struct ath9k_htc_priv *priv;
@@ -835,7 +861,7 @@
 	/* The device may have been unplugged earlier. */
 	priv->op_flags &= ~OP_UNPLUGGED;
 
-	ret = ath9k_init_device(priv, devid);
+	ret = ath9k_init_device(priv, devid, product);
 	if (ret)
 		goto err_init;
 
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 7d09b4b..9a3be8d 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -137,8 +137,6 @@
 	if (priv->op_flags & OP_FULL_RESET)
 		fastcc = false;
 
-	/* Fiddle around with fastcc later on, for now just use full reset */
-	fastcc = false;
 	ath9k_htc_ps_wakeup(priv);
 	htc_stop(priv->htc);
 	WMI_CMD(WMI_DISABLE_INTR_CMDID);
@@ -146,9 +144,10 @@
 	WMI_CMD(WMI_STOP_RECV_CMDID);
 
 	ath_print(common, ATH_DBG_CONFIG,
-		  "(%u MHz) -> (%u MHz), HT: %d, HT40: %d\n",
+		  "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n",
 		  priv->ah->curchan->channel,
-		  channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf));
+		  channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf),
+		  fastcc);
 
 	caldata = &priv->caldata[channel->hw_value];
 	ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
@@ -536,7 +535,8 @@
 static const struct file_operations fops_tgt_stats = {
 	.read = read_file_tgt_stats,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
@@ -584,7 +584,8 @@
 static const struct file_operations fops_xmit = {
 	.read = read_file_xmit,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static ssize_t read_file_recv(struct file *file, char __user *user_buf,
@@ -613,7 +614,8 @@
 static const struct file_operations fops_recv = {
 	.read = read_file_recv,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 int ath9k_htc_init_debug(struct ath_hw *ah)
@@ -761,23 +763,12 @@
 			ath9k_hw_ani_monitor(ah, ah->curchan);
 
 		/* Perform calibration if necessary */
-		if (longcal || shortcal) {
+		if (longcal || shortcal)
 			common->ani.caldone =
 				ath9k_hw_calibrate(ah, ah->curchan,
 						   common->rx_chainmask,
 						   longcal);
 
-			if (longcal)
-				common->ani.noise_floor =
-					ath9k_hw_getchan_noise(ah, ah->curchan);
-
-			ath_print(common, ATH_DBG_ANI,
-				  " calibrate chan %u/%x nf: %d\n",
-				  ah->curchan->channel,
-				  ah->curchan->channelFlags,
-				  common->ani.noise_floor);
-		}
-
 		ath9k_htc_ps_restore(priv);
 	}
 
@@ -1210,6 +1201,12 @@
 
 	ieee80211_wake_queues(hw);
 
+	if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) {
+		ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+					   AR_STOMP_LOW_WLAN_WGHT);
+		ath9k_hw_btcoex_enable(ah);
+		ath_htc_resume_btcoex_work(priv);
+	}
 	mutex_unlock(&priv->mutex);
 
 	return ret;
@@ -1233,7 +1230,6 @@
 
 	/* Cancel all the running timers/work .. */
 	cancel_work_sync(&priv->ps_work);
-	cancel_delayed_work_sync(&priv->ath9k_ani_work);
 	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
 	ath9k_led_stop_brightness(priv);
 
@@ -1254,6 +1250,12 @@
 				  "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);
+	}
+
 	ath9k_hw_phy_disable(ah);
 	ath9k_hw_disable(ah);
 	ath9k_hw_configpcipowersave(ah, 1, 1);
@@ -1455,6 +1457,7 @@
 	FIF_PSPOLL |				\
 	FIF_OTHER_BSS |				\
 	FIF_BCN_PRBRESP_PROMISC |		\
+	FIF_PROBE_REQ |				\
 	FIF_FCSFAIL)
 
 static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
@@ -1580,20 +1583,21 @@
 
 	switch (cmd) {
 	case SET_KEY:
-		ret = ath9k_cmn_key_config(common, vif, sta, key);
+		ret = ath_key_config(common, vif, sta, key);
 		if (ret >= 0) {
 			key->hw_key_idx = ret;
 			/* push IV and Michael MIC generation to stack */
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-			if (key->alg == ALG_TKIP)
+			if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
 				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-			if (priv->ah->sw_mgmt_crypto && key->alg == ALG_CCMP)
+			if (priv->ah->sw_mgmt_crypto &&
+			    key->cipher == WLAN_CIPHER_SUITE_CCMP)
 				key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
 			ret = 0;
 		}
 		break;
 	case DISABLE_KEY:
-		ath9k_cmn_key_delete(common, key);
+		ath_key_delete(common, key);
 		break;
 	default:
 		ret = -EINVAL;
@@ -1774,7 +1778,8 @@
 	priv->op_flags |= OP_SCANNING;
 	spin_unlock_bh(&priv->beacon_lock);
 	cancel_work_sync(&priv->ps_work);
-	cancel_delayed_work_sync(&priv->ath9k_ani_work);
+	if (priv->op_flags & OP_ASSOCIATED)
+		cancel_delayed_work_sync(&priv->ath9k_ani_work);
 	mutex_unlock(&priv->mutex);
 }
 
@@ -1788,9 +1793,10 @@
 	priv->op_flags &= ~OP_SCANNING;
 	spin_unlock_bh(&priv->beacon_lock);
 	priv->op_flags |= OP_FULL_RESET;
-	if (priv->op_flags & OP_ASSOCIATED)
+	if (priv->op_flags & OP_ASSOCIATED) {
 		ath9k_htc_beacon_config(priv, priv->vif);
-	ath_start_ani(priv);
+		ath_start_ani(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 2a6e45a..3d19b5b 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -369,8 +369,7 @@
 		| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
 		| ATH9K_RX_FILTER_MCAST;
 
-	/* If not a STA, enable processing of Probe Requests */
-	if (ah->opmode != NL80211_IFTYPE_STATION)
+	if (priv->rxfilter & FIF_PROBE_REQ)
 		rfilt |= ATH9K_RX_FILTER_PROBEREQ;
 
 	/*
@@ -415,8 +414,7 @@
 	ath9k_hw_setrxfilter(ah, rfilt);
 
 	/* configure bssid mask */
-	if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
-		ath_hw_setbssidmask(common);
+	ath_hw_setbssidmask(common);
 
 	/* configure operational mode */
 	ath9k_hw_setopmode(ah);
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index 705c0f3..861ec92 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -462,9 +462,9 @@
 }
 
 int ath9k_htc_hw_init(struct htc_target *target,
-		      struct device *dev, u16 devid)
+		      struct device *dev, u16 devid, char *product)
 {
-	if (ath9k_htc_probe_device(target, dev, devid)) {
+	if (ath9k_htc_probe_device(target, dev, devid, product)) {
 		printk(KERN_ERR "Failed to initialize the device\n");
 		return -ENODEV;
 	}
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h
index faba679..07b6509 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.h
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.h
@@ -239,7 +239,7 @@
 				      struct device *dev);
 void ath9k_htc_hw_free(struct htc_target *htc);
 int ath9k_htc_hw_init(struct htc_target *target,
-		      struct device *dev, u16 devid);
+		      struct device *dev, u16 devid, char *product);
 void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug);
 
 #endif /* HTC_HST_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index ffecbad..0a4ad34 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -128,17 +128,6 @@
 	ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf);
 }
 
-static inline void ath9k_hw_procmibevent(struct ath_hw *ah)
-{
-	ath9k_hw_ops(ah)->ani_proc_mib_event(ah);
-}
-
-static inline void ath9k_hw_ani_monitor(struct ath_hw *ah,
-					struct ath9k_channel *chan)
-{
-	ath9k_hw_ops(ah)->ani_monitor(ah, chan);
-}
-
 /* Private hardware call ops */
 
 /* PHY ops */
@@ -276,15 +265,4 @@
 	ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal);
 }
 
-static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah,
-					    enum ath9k_cal_types calType)
-{
-	return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType);
-}
-
-static inline void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
-{
-	ath9k_hw_private_ops(ah)->ani_reset(ah, is_scanning);
-}
-
 #endif /* ATH9K_HW_OPS_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 3384ca1..cc13ee1 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -88,29 +88,32 @@
 /* Helper Functions */
 /********************/
 
-static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
+static void ath9k_hw_set_clockrate(struct ath_hw *ah)
 {
 	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
+	struct ath_common *common = ath9k_hw_common(ah);
+	unsigned int clockrate;
 
 	if (!ah->curchan) /* should really check for CCK instead */
-		return usecs *ATH9K_CLOCK_RATE_CCK;
-	if (conf->channel->band == IEEE80211_BAND_2GHZ)
-		return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM;
-
-	if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
-		return usecs * ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
+		clockrate = ATH9K_CLOCK_RATE_CCK;
+	else if (conf->channel->band == IEEE80211_BAND_2GHZ)
+		clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
+	else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
+		clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
 	else
-		return usecs * ATH9K_CLOCK_RATE_5GHZ_OFDM;
+		clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
+
+	if (conf_is_ht40(conf))
+		clockrate *= 2;
+
+	common->clockrate = clockrate;
 }
 
 static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
 {
-	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
+	struct ath_common *common = ath9k_hw_common(ah);
 
-	if (conf_is_ht40(conf))
-		return ath9k_hw_mac_clks(ah, usecs) * 2;
-	else
-		return ath9k_hw_mac_clks(ah, usecs);
+	return usecs * common->clockrate;
 }
 
 bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
@@ -299,7 +302,6 @@
 	REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 
 /* This should work for all families including legacy */
@@ -371,10 +373,6 @@
 	ah->config.pcie_clock_req = 0;
 	ah->config.pcie_waen = 0;
 	ah->config.analog_shiftreg = 1;
-	ah->config.ofdm_trig_low = 200;
-	ah->config.ofdm_trig_high = 500;
-	ah->config.cck_trig_high = 200;
-	ah->config.cck_trig_low = 100;
 	ah->config.enable_ani = true;
 
 	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
@@ -565,7 +563,7 @@
 	ath9k_hw_init_cal_settings(ah);
 
 	ah->ani_function = ATH9K_ANI_ALL;
-	if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))
+	if (AR_SREV_9280_20_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))
 		ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
 	if (!AR_SREV_9300_20_OR_LATER(ah))
 		ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
@@ -676,7 +674,6 @@
 	REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 
 static void ath9k_hw_init_pll(struct ath_hw *ah,
@@ -741,7 +738,6 @@
 	}
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	if (AR_SREV_9300_20_OR_LATER(ah)) {
 		REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0);
@@ -885,7 +881,6 @@
 	REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	/*
 	 * Restore TX Trigger Level to its pre-reset value.
@@ -933,7 +928,6 @@
 	}
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	if (AR_SREV_9300_20_OR_LATER(ah))
 		ath9k_hw_reset_txstatus_ring(ah);
@@ -1031,7 +1025,6 @@
 	REG_WRITE(ah, AR_RTC_RC, rst_flags);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	udelay(50);
 
@@ -1070,7 +1063,6 @@
 	udelay(2);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	if (!AR_SREV_9300_20_OR_LATER(ah))
 		udelay(2);
@@ -1167,6 +1159,7 @@
 			  "Failed to set channel\n");
 		return false;
 	}
+	ath9k_hw_set_clockrate(ah);
 
 	ah->eep_ops->set_txpower(ah, chan,
 			     ath9k_regd_get_ctl(regulatory, chan),
@@ -1190,7 +1183,7 @@
 	int count = 50;
 	u32 reg;
 
-	if (AR_SREV_9285_10_OR_LATER(ah))
+	if (AR_SREV_9285_12_OR_LATER(ah))
 		return true;
 
 	do {
@@ -1239,7 +1232,7 @@
 	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
 		return -EIO;
 
-	if (curchan && !ah->chip_fullsleep && ah->caldata)
+	if (curchan && !ah->chip_fullsleep)
 		ath9k_hw_getnf(ah, curchan);
 
 	ah->caldata = caldata;
@@ -1258,11 +1251,13 @@
 	    (chan->channel != ah->curchan->channel) &&
 	    ((chan->channelFlags & CHANNEL_ALL) ==
 	     (ah->curchan->channelFlags & CHANNEL_ALL)) &&
-	    !AR_SREV_9280(ah)) {
+	    (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) {
 
 		if (ath9k_hw_channel_change(ah, chan)) {
 			ath9k_hw_loadnf(ah, ah->curchan);
 			ath9k_hw_start_nfcal(ah, true);
+			if (AR_SREV_9271(ah))
+				ar9002_hw_load_ani_reg(ah, chan);
 			return 0;
 		}
 	}
@@ -1310,7 +1305,7 @@
 	if (tsf)
 		ath9k_hw_settsf64(ah, tsf);
 
-	if (AR_SREV_9280_10_OR_LATER(ah))
+	if (AR_SREV_9280_20_OR_LATER(ah))
 		REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
 
 	if (!AR_SREV_9300_20_OR_LATER(ah))
@@ -1372,19 +1367,19 @@
 	REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	r = ath9k_hw_rf_set_freq(ah, chan);
 	if (r)
 		return r;
 
+	ath9k_hw_set_clockrate(ah);
+
 	ENABLE_REGWRITE_BUFFER(ah);
 
 	for (i = 0; i < AR_NUM_DCU; i++)
 		REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	ah->intr_txqs = 0;
 	for (i = 0; i < ah->caps.total_queues; i++)
@@ -1432,7 +1427,6 @@
 	REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	/*
 	 * For big endian systems turn on swapping for descriptors
@@ -1474,283 +1468,6 @@
 }
 EXPORT_SYMBOL(ath9k_hw_reset);
 
-/************************/
-/* Key Cache Management */
-/************************/
-
-bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
-{
-	u32 keyType;
-
-	if (entry >= ah->caps.keycache_size) {
-		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-			  "keychache entry %u out of range\n", entry);
-		return false;
-	}
-
-	keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
-
-	REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
-	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
-
-	if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
-		u16 micentry = entry + 64;
-
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
-
-	}
-
-	return true;
-}
-EXPORT_SYMBOL(ath9k_hw_keyreset);
-
-static bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
-{
-	u32 macHi, macLo;
-	u32 unicast_flag = AR_KEYTABLE_VALID;
-
-	if (entry >= ah->caps.keycache_size) {
-		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-			  "keychache entry %u out of range\n", entry);
-		return false;
-	}
-
-	if (mac != NULL) {
-		/*
-		 * AR_KEYTABLE_VALID indicates that the address is a unicast
-		 * address, which must match the transmitter address for
-		 * decrypting frames.
-		 * Not setting this bit allows the hardware to use the key
-		 * for multicast frame decryption.
-		 */
-		if (mac[0] & 0x01)
-			unicast_flag = 0;
-
-		macHi = (mac[5] << 8) | mac[4];
-		macLo = (mac[3] << 24) |
-			(mac[2] << 16) |
-			(mac[1] << 8) |
-			mac[0];
-		macLo >>= 1;
-		macLo |= (macHi & 1) << 31;
-		macHi >>= 1;
-	} else {
-		macLo = macHi = 0;
-	}
-	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
-	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag);
-
-	return true;
-}
-
-bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
-				 const struct ath9k_keyval *k,
-				 const u8 *mac)
-{
-	const struct ath9k_hw_capabilities *pCap = &ah->caps;
-	struct ath_common *common = ath9k_hw_common(ah);
-	u32 key0, key1, key2, key3, key4;
-	u32 keyType;
-
-	if (entry >= pCap->keycache_size) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "keycache entry %u out of range\n", entry);
-		return false;
-	}
-
-	switch (k->kv_type) {
-	case ATH9K_CIPHER_AES_OCB:
-		keyType = AR_KEYTABLE_TYPE_AES;
-		break;
-	case ATH9K_CIPHER_AES_CCM:
-		if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
-			ath_print(common, ATH_DBG_ANY,
-				  "AES-CCM not supported by mac rev 0x%x\n",
-				  ah->hw_version.macRev);
-			return false;
-		}
-		keyType = AR_KEYTABLE_TYPE_CCM;
-		break;
-	case ATH9K_CIPHER_TKIP:
-		keyType = AR_KEYTABLE_TYPE_TKIP;
-		if (ATH9K_IS_MIC_ENABLED(ah)
-		    && entry + 64 >= pCap->keycache_size) {
-			ath_print(common, ATH_DBG_ANY,
-				  "entry %u inappropriate for TKIP\n", entry);
-			return false;
-		}
-		break;
-	case ATH9K_CIPHER_WEP:
-		if (k->kv_len < WLAN_KEY_LEN_WEP40) {
-			ath_print(common, ATH_DBG_ANY,
-				  "WEP key length %u too small\n", k->kv_len);
-			return false;
-		}
-		if (k->kv_len <= WLAN_KEY_LEN_WEP40)
-			keyType = AR_KEYTABLE_TYPE_40;
-		else if (k->kv_len <= WLAN_KEY_LEN_WEP104)
-			keyType = AR_KEYTABLE_TYPE_104;
-		else
-			keyType = AR_KEYTABLE_TYPE_128;
-		break;
-	case ATH9K_CIPHER_CLR:
-		keyType = AR_KEYTABLE_TYPE_CLR;
-		break;
-	default:
-		ath_print(common, ATH_DBG_FATAL,
-			  "cipher %u not supported\n", k->kv_type);
-		return false;
-	}
-
-	key0 = get_unaligned_le32(k->kv_val + 0);
-	key1 = get_unaligned_le16(k->kv_val + 4);
-	key2 = get_unaligned_le32(k->kv_val + 6);
-	key3 = get_unaligned_le16(k->kv_val + 10);
-	key4 = get_unaligned_le32(k->kv_val + 12);
-	if (k->kv_len <= WLAN_KEY_LEN_WEP104)
-		key4 &= 0xff;
-
-	/*
-	 * Note: Key cache registers access special memory area that requires
-	 * two 32-bit writes to actually update the values in the internal
-	 * memory. Consequently, the exact order and pairs used here must be
-	 * maintained.
-	 */
-
-	if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
-		u16 micentry = entry + 64;
-
-		/*
-		 * Write inverted key[47:0] first to avoid Michael MIC errors
-		 * on frames that could be sent or received at the same time.
-		 * The correct key will be written in the end once everything
-		 * else is ready.
-		 */
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
-
-		/* Write key[95:48] */
-		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
-		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
-
-		/* Write key[127:96] and key type */
-		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
-		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
-
-		/* Write MAC address for the entry */
-		(void) ath9k_hw_keysetmac(ah, entry, mac);
-
-		if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) {
-			/*
-			 * TKIP uses two key cache entries:
-			 * Michael MIC TX/RX keys in the same key cache entry
-			 * (idx = main index + 64):
-			 * key0 [31:0] = RX key [31:0]
-			 * key1 [15:0] = TX key [31:16]
-			 * key1 [31:16] = reserved
-			 * key2 [31:0] = RX key [63:32]
-			 * key3 [15:0] = TX key [15:0]
-			 * key3 [31:16] = reserved
-			 * key4 [31:0] = TX key [63:32]
-			 */
-			u32 mic0, mic1, mic2, mic3, mic4;
-
-			mic0 = get_unaligned_le32(k->kv_mic + 0);
-			mic2 = get_unaligned_le32(k->kv_mic + 4);
-			mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
-			mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
-			mic4 = get_unaligned_le32(k->kv_txmic + 4);
-
-			/* Write RX[31:0] and TX[31:16] */
-			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
-			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
-
-			/* Write RX[63:32] and TX[15:0] */
-			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
-			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
-
-			/* Write TX[63:32] and keyType(reserved) */
-			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
-			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
-				  AR_KEYTABLE_TYPE_CLR);
-
-		} else {
-			/*
-			 * TKIP uses four key cache entries (two for group
-			 * keys):
-			 * Michael MIC TX/RX keys are in different key cache
-			 * entries (idx = main index + 64 for TX and
-			 * main index + 32 + 96 for RX):
-			 * key0 [31:0] = TX/RX MIC key [31:0]
-			 * key1 [31:0] = reserved
-			 * key2 [31:0] = TX/RX MIC key [63:32]
-			 * key3 [31:0] = reserved
-			 * key4 [31:0] = reserved
-			 *
-			 * Upper layer code will call this function separately
-			 * for TX and RX keys when these registers offsets are
-			 * used.
-			 */
-			u32 mic0, mic2;
-
-			mic0 = get_unaligned_le32(k->kv_mic + 0);
-			mic2 = get_unaligned_le32(k->kv_mic + 4);
-
-			/* Write MIC key[31:0] */
-			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
-			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
-
-			/* Write MIC key[63:32] */
-			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
-			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
-
-			/* Write TX[63:32] and keyType(reserved) */
-			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
-			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
-				  AR_KEYTABLE_TYPE_CLR);
-		}
-
-		/* MAC address registers are reserved for the MIC entry */
-		REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
-
-		/*
-		 * Write the correct (un-inverted) key[47:0] last to enable
-		 * TKIP now that all other registers are set with correct
-		 * values.
-		 */
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
-	} else {
-		/* Write key[47:0] */
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
-
-		/* Write key[95:48] */
-		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
-		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
-
-		/* Write key[127:96] and key type */
-		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
-		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
-
-		/* Write MAC address for the entry */
-		(void) ath9k_hw_keysetmac(ah, entry, mac);
-	}
-
-	return true;
-}
-EXPORT_SYMBOL(ath9k_hw_set_keycache_entry);
-
 /******************************/
 /* Power Management (Chipset) */
 /******************************/
@@ -1959,7 +1676,6 @@
 	REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period));
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	beacon_period &= ~ATH9K_BEACON_ENA;
 	if (beacon_period & ATH9K_BEACON_RESET_TSF) {
@@ -1987,7 +1703,6 @@
 		  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	REG_RMW_FIELD(ah, AR_RSSI_THR,
 		      AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
@@ -2033,7 +1748,6 @@
 	REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	REG_SET_BIT(ah, AR_TIMER_MODE,
 		    AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
@@ -2056,12 +1770,13 @@
 	struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
 
 	u16 capField = 0, eeval;
+	u8 ant_div_ctl1;
 
 	eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
 	regulatory->current_rd = eeval;
 
 	eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
-	if (AR_SREV_9285_10_OR_LATER(ah))
+	if (AR_SREV_9285_12_OR_LATER(ah))
 		eeval |= AR9285_RDEXT_DEFAULT;
 	regulatory->current_rd_ext = eeval;
 
@@ -2085,37 +1800,11 @@
 		return -EINVAL;
 	}
 
-	bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
+	if (eeval & AR5416_OPFLAGS_11A)
+		pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
 
-	if (eeval & AR5416_OPFLAGS_11A) {
-		set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
-		if (ah->config.ht_enable) {
-			if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
-				set_bit(ATH9K_MODE_11NA_HT20,
-					pCap->wireless_modes);
-			if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
-				set_bit(ATH9K_MODE_11NA_HT40PLUS,
-					pCap->wireless_modes);
-				set_bit(ATH9K_MODE_11NA_HT40MINUS,
-					pCap->wireless_modes);
-			}
-		}
-	}
-
-	if (eeval & AR5416_OPFLAGS_11G) {
-		set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
-		if (ah->config.ht_enable) {
-			if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
-				set_bit(ATH9K_MODE_11NG_HT20,
-					pCap->wireless_modes);
-			if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
-				set_bit(ATH9K_MODE_11NG_HT40PLUS,
-					pCap->wireless_modes);
-				set_bit(ATH9K_MODE_11NG_HT40MINUS,
-					pCap->wireless_modes);
-			}
-		}
-	}
+	if (eeval & AR5416_OPFLAGS_11G)
+		pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
 
 	pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
 	/*
@@ -2131,8 +1820,7 @@
 		/* Use rx_chainmask from EEPROM. */
 		pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
 
-	if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0)))
-		ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
+	ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
 
 	pCap->low_2ghz_chan = 2312;
 	pCap->high_2ghz_chan = 2732;
@@ -2140,24 +1828,13 @@
 	pCap->low_5ghz_chan = 4920;
 	pCap->high_5ghz_chan = 6100;
 
-	pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM;
-
-	pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
+	common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
 
 	if (ah->config.ht_enable)
 		pCap->hw_caps |= ATH9K_HW_CAP_HT;
 	else
 		pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
 
-	pCap->hw_caps |= ATH9K_HW_CAP_GTT;
-	pCap->hw_caps |= ATH9K_HW_CAP_VEOL;
-	pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK;
-	pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH;
-
 	if (capField & AR_EEPROM_EEPCAP_MAXQCU)
 		pCap->total_queues =
 			MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
@@ -2170,8 +1847,6 @@
 	else
 		pCap->keycache_size = AR_KEYTABLE_SIZE;
 
-	pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
-
 	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
 		pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1;
 	else
@@ -2181,9 +1856,9 @@
 		pCap->num_gpio_pins = AR9271_NUM_GPIO;
 	else if (AR_DEVID_7010(ah))
 		pCap->num_gpio_pins = AR7010_NUM_GPIO;
-	else if (AR_SREV_9285_10_OR_LATER(ah))
+	else if (AR_SREV_9285_12_OR_LATER(ah))
 		pCap->num_gpio_pins = AR9285_NUM_GPIO;
-	else if (AR_SREV_9280_10_OR_LATER(ah))
+	else if (AR_SREV_9280_20_OR_LATER(ah))
 		pCap->num_gpio_pins = AR928X_NUM_GPIO;
 	else
 		pCap->num_gpio_pins = AR_NUM_GPIO;
@@ -2240,7 +1915,7 @@
 	pCap->num_antcfg_2ghz =
 		ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
 
-	if (AR_SREV_9280_10_OR_LATER(ah) &&
+	if (AR_SREV_9280_20_OR_LATER(ah) &&
 	    ath9k_hw_btcoex_supported(ah)) {
 		btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO;
 		btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO;
@@ -2277,9 +1952,17 @@
 	if (AR_SREV_9300_20_OR_LATER(ah))
 		pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
 
-	if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah))
+	if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))
 		pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
 
+	if (AR_SREV_9285(ah))
+		if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) {
+			ant_div_ctl1 =
+				ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
+			if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1))
+				pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
+		}
+
 	return 0;
 }
 
@@ -2353,11 +2036,11 @@
 		return MS_REG_READ(AR9300, gpio) != 0;
 	else if (AR_SREV_9271(ah))
 		return MS_REG_READ(AR9271, gpio) != 0;
-	else if (AR_SREV_9287_10_OR_LATER(ah))
+	else if (AR_SREV_9287_11_OR_LATER(ah))
 		return MS_REG_READ(AR9287, gpio) != 0;
-	else if (AR_SREV_9285_10_OR_LATER(ah))
+	else if (AR_SREV_9285_12_OR_LATER(ah))
 		return MS_REG_READ(AR9285, gpio) != 0;
-	else if (AR_SREV_9280_10_OR_LATER(ah))
+	else if (AR_SREV_9280_20_OR_LATER(ah))
 		return MS_REG_READ(AR928X, gpio) != 0;
 	else
 		return MS_REG_READ(AR, gpio) != 0;
@@ -2456,7 +2139,6 @@
 			  REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 EXPORT_SYMBOL(ath9k_hw_setrxfilter);
 
@@ -2854,7 +2536,7 @@
 	int used;
 
 	/* chipsets >= AR9280 are single-chip */
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		used = snprintf(hw_name, len,
 			       "Atheros AR%s Rev:%x",
 			       ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 399f7c1..d032939 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -61,6 +61,8 @@
 
 #define ATH9K_RSSI_BAD			-128
 
+#define ATH9K_NUM_CHANNELS	38
+
 /* Register read/write primitives */
 #define REG_WRITE(_ah, _reg, _val) \
 	ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg))
@@ -70,19 +72,13 @@
 
 #define ENABLE_REGWRITE_BUFFER(_ah)					\
 	do {								\
-		if (AR_SREV_9271(_ah))					\
+		if (ath9k_hw_common(_ah)->ops->enable_write_buffer)	\
 			ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \
 	} while (0)
 
-#define DISABLE_REGWRITE_BUFFER(_ah)					\
-	do {								\
-		if (AR_SREV_9271(_ah))					\
-			ath9k_hw_common(_ah)->ops->disable_write_buffer((_ah)); \
-	} while (0)
-
 #define REGWRITE_BUFFER_FLUSH(_ah)					\
 	do {								\
-		if (AR_SREV_9271(_ah))					\
+		if (ath9k_hw_common(_ah)->ops->write_flush)		\
 			ath9k_hw_common(_ah)->ops->write_flush((_ah));	\
 	} while (0)
 
@@ -168,47 +164,26 @@
 	ATH_INI_NUM_SPLIT,
 };
 
-enum wireless_mode {
-	ATH9K_MODE_11A = 0,
-	ATH9K_MODE_11G,
-	ATH9K_MODE_11NA_HT20,
-	ATH9K_MODE_11NG_HT20,
-	ATH9K_MODE_11NA_HT40PLUS,
-	ATH9K_MODE_11NA_HT40MINUS,
-	ATH9K_MODE_11NG_HT40PLUS,
-	ATH9K_MODE_11NG_HT40MINUS,
-	ATH9K_MODE_MAX,
-};
-
 enum ath9k_hw_caps {
-	ATH9K_HW_CAP_MIC_AESCCM                 = BIT(0),
-	ATH9K_HW_CAP_MIC_CKIP                   = BIT(1),
-	ATH9K_HW_CAP_MIC_TKIP                   = BIT(2),
-	ATH9K_HW_CAP_CIPHER_AESCCM              = BIT(3),
-	ATH9K_HW_CAP_CIPHER_CKIP                = BIT(4),
-	ATH9K_HW_CAP_CIPHER_TKIP                = BIT(5),
-	ATH9K_HW_CAP_VEOL                       = BIT(6),
-	ATH9K_HW_CAP_BSSIDMASK                  = BIT(7),
-	ATH9K_HW_CAP_MCAST_KEYSEARCH            = BIT(8),
-	ATH9K_HW_CAP_HT                         = BIT(9),
-	ATH9K_HW_CAP_GTT                        = BIT(10),
-	ATH9K_HW_CAP_FASTCC                     = BIT(11),
-	ATH9K_HW_CAP_RFSILENT                   = BIT(12),
-	ATH9K_HW_CAP_CST                        = BIT(13),
-	ATH9K_HW_CAP_ENHANCEDPM                 = BIT(14),
-	ATH9K_HW_CAP_AUTOSLEEP                  = BIT(15),
-	ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(16),
-	ATH9K_HW_CAP_EDMA			= BIT(17),
-	ATH9K_HW_CAP_RAC_SUPPORTED		= BIT(18),
-	ATH9K_HW_CAP_LDPC			= BIT(19),
-	ATH9K_HW_CAP_FASTCLOCK			= BIT(20),
-	ATH9K_HW_CAP_SGI_20			= BIT(21),
-	ATH9K_HW_CAP_PAPRD			= BIT(22),
+	ATH9K_HW_CAP_HT                         = BIT(0),
+	ATH9K_HW_CAP_RFSILENT                   = BIT(1),
+	ATH9K_HW_CAP_CST                        = BIT(2),
+	ATH9K_HW_CAP_ENHANCEDPM                 = BIT(3),
+	ATH9K_HW_CAP_AUTOSLEEP                  = BIT(4),
+	ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(5),
+	ATH9K_HW_CAP_EDMA			= BIT(6),
+	ATH9K_HW_CAP_RAC_SUPPORTED		= BIT(7),
+	ATH9K_HW_CAP_LDPC			= BIT(8),
+	ATH9K_HW_CAP_FASTCLOCK			= BIT(9),
+	ATH9K_HW_CAP_SGI_20			= BIT(10),
+	ATH9K_HW_CAP_PAPRD			= BIT(11),
+	ATH9K_HW_CAP_ANT_DIV_COMB		= BIT(12),
+	ATH9K_HW_CAP_2GHZ			= BIT(13),
+	ATH9K_HW_CAP_5GHZ			= BIT(14),
 };
 
 struct ath9k_hw_capabilities {
 	u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
-	DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */
 	u16 total_queues;
 	u16 keycache_size;
 	u16 low_5ghz_chan, high_5ghz_chan;
@@ -352,9 +327,9 @@
 	int32_t CalValid;
 	int8_t iCoff;
 	int8_t qCoff;
-	int16_t rawNoiseFloor;
 	bool paprd_done;
 	bool nfcal_pending;
+	bool nfcal_interference;
 	u16 small_signal_gain[AR9300_MAX_CHAINS];
 	u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
 	struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
@@ -362,9 +337,11 @@
 
 struct ath9k_channel {
 	struct ieee80211_channel *chan;
+	struct ar5416AniState ani;
 	u16 channel;
 	u32 channelFlags;
 	u32 chanmode;
+	s16 noisefloor;
 };
 
 #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
@@ -494,6 +471,12 @@
 	} timer_mask;
 };
 
+struct ath_hw_antcomb_conf {
+	u8 main_lna_conf;
+	u8 alt_lna_conf;
+	u8 fast_div_bias;
+};
+
 /**
  * struct ath_hw_private_ops - callbacks used internally by hardware code
  *
@@ -517,14 +500,6 @@
  * @setup_calibration: set up calibration
  * @iscal_supported: used to query if a type of calibration is supported
  *
- * @ani_reset: reset ANI parameters to default values
- * @ani_lower_immunity: lower the noise immunity level. The level controls
- *	the power-based packet detection on hardware. If a power jump is
- *	detected the adapter takes it as an indication that a packet has
- *	arrived. The level ranges from 0-5. Each level corresponds to a
- *	few dB more of noise immunity. If you have a strong time-varying
- *	interference that is causing false detections (OFDM timing errors or
- *	CCK timing errors) the level can be increased.
  * @ani_cache_ini_regs: cache the values for ANI from the initial
  *	register settings through the register initialization.
  */
@@ -538,8 +513,6 @@
 	bool (*macversion_supported)(u32 macversion);
 	void (*setup_calibration)(struct ath_hw *ah,
 				  struct ath9k_cal_list *currCal);
-	bool (*iscal_supported)(struct ath_hw *ah,
-				enum ath9k_cal_types calType);
 
 	/* PHY ops */
 	int (*rf_set_freq)(struct ath_hw *ah,
@@ -571,8 +544,6 @@
 	void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
 
 	/* ANI */
-	void (*ani_reset)(struct ath_hw *ah, bool is_scanning);
-	void (*ani_lower_immunity)(struct ath_hw *ah);
 	void (*ani_cache_ini_regs)(struct ath_hw *ah);
 };
 
@@ -584,11 +555,6 @@
  *
  * @config_pci_powersave:
  * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
- *
- * @ani_proc_mib_event: process MIB events, this would happen upon specific ANI
- *	thresholds being reached or having overflowed.
- * @ani_monitor: called periodically by the core driver to collect
- *	MIB stats and adjust ANI if specific thresholds have been reached.
  */
 struct ath_hw_ops {
 	void (*config_pci_powersave)(struct ath_hw *ah,
@@ -629,9 +595,6 @@
 				     u32 burstDuration);
 	void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds,
 				       u32 vmf);
-
-	void (*ani_proc_mib_event)(struct ath_hw *ah);
-	void (*ani_monitor)(struct ath_hw *ah, struct ath9k_channel *chan);
 };
 
 struct ath_nf_limits {
@@ -646,7 +609,7 @@
 	struct ath9k_hw_version hw_version;
 	struct ath9k_ops_config config;
 	struct ath9k_hw_capabilities caps;
-	struct ath9k_channel channels[38];
+	struct ath9k_channel channels[ATH9K_NUM_CHANNELS];
 	struct ath9k_channel *curchan;
 
 	union {
@@ -692,10 +655,9 @@
 	u32 atim_window;
 
 	/* Calibration */
-	enum ath9k_cal_types supp_cals;
+	u32 supp_cals;
 	struct ath9k_cal_list iq_caldata;
 	struct ath9k_cal_list adcgain_caldata;
-	struct ath9k_cal_list adcdc_calinitdata;
 	struct ath9k_cal_list adcdc_caldata;
 	struct ath9k_cal_list tempCompCalData;
 	struct ath9k_cal_list *cal_list;
@@ -764,8 +726,6 @@
 	/* ANI */
 	u32 proc_phyerr;
 	u32 aniperiod;
-	struct ar5416AniState *curani;
-	struct ar5416AniState ani[255];
 	int totalSizeDesired[5];
 	int coarse_high[5];
 	int coarse_low[5];
@@ -873,12 +833,6 @@
 int ath9k_hw_fill_cap_info(struct ath_hw *ah);
 u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
 
-/* Key Cache Management */
-bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry);
-bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
-				 const struct ath9k_keyval *k,
-				 const u8 *mac);
-
 /* GPIO / RFKILL / Antennae */
 void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);
 u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
@@ -887,6 +841,10 @@
 void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
 u32 ath9k_hw_getdefantenna(struct ath_hw *ah);
 void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
+void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+				   struct ath_hw_antcomb_conf *antconf);
+void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah,
+				   struct ath_hw_antcomb_conf *antconf);
 
 /* General Operation */
 bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
@@ -984,6 +942,7 @@
 void ar9002_hw_attach_ops(struct ath_hw *ah);
 void ar9003_hw_attach_ops(struct ath_hw *ah);
 
+void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
 /*
  * ANI work can be shared between all families but a next
  * generation implementation of ANI will be used only for AR9003 only
@@ -992,8 +951,9 @@
  * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani.
  */
 extern int modparam_force_new_ani;
-void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah);
-void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah);
+void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
+void ath9k_hw_proc_mib_event(struct ath_hw *ah);
+void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
 
 #define ATH_PCIE_CAP_LINK_CTRL	0x70
 #define ATH_PCIE_CAP_LINK_L0S	1
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 243c177..bc6c4df 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -33,7 +33,7 @@
 module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
 
-int led_blink = 1;
+int led_blink;
 module_param_named(blink, led_blink, int, 0444);
 MODULE_PARM_DESC(blink, "Enable LED blink on activity");
 
@@ -56,7 +56,7 @@
  * on 5 MHz steps, we support the channels which we know
  * we have calibration data for all cards though to make
  * this static */
-static struct ieee80211_channel ath9k_2ghz_chantable[] = {
+static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
 	CHAN2G(2412, 0), /* Channel 1 */
 	CHAN2G(2417, 1), /* Channel 2 */
 	CHAN2G(2422, 2), /* Channel 3 */
@@ -77,7 +77,7 @@
  * on 5 MHz steps, we support the channels which we know
  * we have calibration data for all cards though to make
  * this static */
-static struct ieee80211_channel ath9k_5ghz_chantable[] = {
+static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
 	/* _We_ call this UNII 1 */
 	CHAN5G(5180, 14), /* Channel 36 */
 	CHAN5G(5200, 15), /* Channel 40 */
@@ -211,7 +211,7 @@
 	else
 		max_streams = 2;
 
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		if (max_streams >= 2)
 			ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
 		ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
@@ -381,7 +381,7 @@
 	 * reset the contents on initial power up.
 	 */
 	for (i = 0; i < common->keymax; i++)
-		ath9k_hw_keyreset(sc->sc_ah, (u16) i);
+		ath_hw_keyreset(common, (u16) i);
 
 	/*
 	 * Check whether the separate key cache entries
@@ -389,8 +389,8 @@
 	 * With split mic keys the number of stations is limited
 	 * to 27 otherwise 59.
 	 */
-	if (!(sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA))
-		common->splitmic = 1;
+	if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
+		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
 }
 
 static int ath9k_init_btcoex(struct ath_softc *sc)
@@ -477,10 +477,21 @@
 	return -EIO;
 }
 
-static void ath9k_init_channels_rates(struct ath_softc *sc)
+static int ath9k_init_channels_rates(struct ath_softc *sc)
 {
-	if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
-		sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
+	void *channels;
+
+	BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) +
+		     ARRAY_SIZE(ath9k_5ghz_chantable) !=
+		     ATH9K_NUM_CHANNELS);
+
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
+		channels = kmemdup(ath9k_2ghz_chantable,
+			sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
+		if (!channels)
+		    return -ENOMEM;
+
+		sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
 		sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
 		sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
 			ARRAY_SIZE(ath9k_2ghz_chantable);
@@ -489,8 +500,16 @@
 			ARRAY_SIZE(ath9k_legacy_rates);
 	}
 
-	if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
-		sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
+		channels = kmemdup(ath9k_5ghz_chantable,
+			sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
+		if (!channels) {
+			if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
+				kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
+			return -ENOMEM;
+		}
+
+		sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
 		sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
 		sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
 			ARRAY_SIZE(ath9k_5ghz_chantable);
@@ -499,6 +518,7 @@
 		sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
 			ARRAY_SIZE(ath9k_legacy_rates) - 4;
 	}
+	return 0;
 }
 
 static void ath9k_init_misc(struct ath_softc *sc)
@@ -506,7 +526,6 @@
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int i = 0;
 
-	common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
 	setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
 
 	sc->config.txpowlimit = ATH_TXPOWER_MAX;
@@ -522,8 +541,7 @@
 	ath9k_hw_set_diversity(sc->sc_ah, true);
 	sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
 
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
-		memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
+	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
 
 	sc->beacon.slottime = ATH9K_SLOT_TIME_9;
 
@@ -531,6 +549,9 @@
 		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;
 }
 
 static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
@@ -593,8 +614,11 @@
 	if (ret)
 		goto err_btcoex;
 
+	ret = ath9k_init_channels_rates(sc);
+	if (ret)
+		goto err_btcoex;
+
 	ath9k_init_crypto(sc);
-	ath9k_init_channels_rates(sc);
 	ath9k_init_misc(sc);
 
 	return 0;
@@ -637,11 +661,13 @@
 
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_AP) |
+		BIT(NL80211_IFTYPE_WDS) |
 		BIT(NL80211_IFTYPE_STATION) |
 		BIT(NL80211_IFTYPE_ADHOC) |
 		BIT(NL80211_IFTYPE_MESH_POINT);
 
-	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+	if (AR_SREV_5416(sc->sc_ah))
+		hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
 	hw->queues = 4;
 	hw->max_rates = 4;
@@ -651,19 +677,21 @@
 	hw->sta_data_size = sizeof(struct ath_node);
 	hw->vif_data_size = sizeof(struct ath_vif);
 
+#ifdef CONFIG_ATH9K_RATE_CONTROL
 	hw->rate_control_algorithm = "ath9k_rate_control";
+#endif
 
-	if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
 			&sc->sbands[IEEE80211_BAND_2GHZ];
-	if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
 			&sc->sbands[IEEE80211_BAND_5GHZ];
 
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
-		if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
+		if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
 			setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
-		if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
+		if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
 			setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
 	}
 
@@ -751,6 +779,12 @@
 {
 	int i = 0;
 
+	if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
+		kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
+
+	if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
+		kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
+
         if ((sc->btcoex.no_stomp_timer) &&
 	    sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
 		ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index e955bb9..8c13479 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -40,7 +40,6 @@
 	REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 }
 
 u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
@@ -492,8 +491,6 @@
 	REG_WRITE(ah, AR_DMISC(q),
 		  AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
 
-	REGWRITE_BUFFER_FLUSH(ah);
-
 	if (qi->tqi_cbrPeriod) {
 		REG_WRITE(ah, AR_QCBRCFG(q),
 			  SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
@@ -509,8 +506,6 @@
 			  AR_Q_RDYTIMECFG_EN);
 	}
 
-	REGWRITE_BUFFER_FLUSH(ah);
-
 	REG_WRITE(ah, AR_DCHNTIME(q),
 		  SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
 		  (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
@@ -530,7 +525,6 @@
 	}
 
 	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
 
 	if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
 		REG_WRITE(ah, AR_DMISC(q),
@@ -553,7 +547,6 @@
 			  | AR_D_MISC_POST_FR_BKOFF_DIS);
 
 		REGWRITE_BUFFER_FLUSH(ah);
-		DISABLE_REGWRITE_BUFFER(ah);
 
 		/*
 		 * cwmin and cwmax should be 0 for beacon queue
@@ -585,7 +578,6 @@
 			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
 
 		REGWRITE_BUFFER_FLUSH(ah);
-		DISABLE_REGWRITE_BUFFER(ah);
 
 		break;
 	case ATH9K_TX_QUEUE_PSPOLL:
@@ -711,8 +703,11 @@
 			rs->rs_phyerr = phyerr;
 		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
-		else if (ads.ds_rxstatus8 & AR_MichaelErr)
+		else if ((ads.ds_rxstatus8 & AR_MichaelErr) &&
+		         rs->rs_keyix != ATH9K_RXKEYIX_INVALID)
 			rs->rs_status |= ATH9K_RXERR_MIC;
+		else if (ads.ds_rxstatus8 & AR_KeyMiss)
+			rs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
 
 	return 0;
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 2633896..7c1a34d 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -660,17 +660,6 @@
 	u32 RateFlags;
 };
 
-struct ath9k_keyval {
-	u8 kv_type;
-	u8 kv_pad;
-	u16 kv_len;
-	u8 kv_val[16]; /* TK */
-	u8 kv_mic[8]; /* Michael MIC key */
-	u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
-			 * supports both MIC keys in the same key cache entry;
-			 * in that case, kv_mic is the RX key) */
-};
-
 enum ath9k_key_type {
 	ATH9K_KEY_TYPE_CLEAR,
 	ATH9K_KEY_TYPE_WEP,
@@ -678,16 +667,6 @@
 	ATH9K_KEY_TYPE_TKIP,
 };
 
-enum ath9k_cipher {
-	ATH9K_CIPHER_WEP = 0,
-	ATH9K_CIPHER_AES_OCB = 1,
-	ATH9K_CIPHER_AES_CCM = 2,
-	ATH9K_CIPHER_CKIP = 3,
-	ATH9K_CIPHER_TKIP = 4,
-	ATH9K_CIPHER_CLR = 5,
-	ATH9K_CIPHER_MIC = 127
-};
-
 struct ath_hw;
 struct ath9k_channel;
 
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 3caa323..3ff0e47 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -18,36 +18,6 @@
 #include "ath9k.h"
 #include "btcoex.h"
 
-static void ath_cache_conf_rate(struct ath_softc *sc,
-				struct ieee80211_conf *conf)
-{
-	switch (conf->channel->band) {
-	case IEEE80211_BAND_2GHZ:
-		if (conf_is_ht20(conf))
-			sc->cur_rate_mode = ATH9K_MODE_11NG_HT20;
-		else if (conf_is_ht40_minus(conf))
-			sc->cur_rate_mode = ATH9K_MODE_11NG_HT40MINUS;
-		else if (conf_is_ht40_plus(conf))
-			sc->cur_rate_mode = ATH9K_MODE_11NG_HT40PLUS;
-		else
-			sc->cur_rate_mode = ATH9K_MODE_11G;
-		break;
-	case IEEE80211_BAND_5GHZ:
-		if (conf_is_ht20(conf))
-			sc->cur_rate_mode = ATH9K_MODE_11NA_HT20;
-		else if (conf_is_ht40_minus(conf))
-			sc->cur_rate_mode = ATH9K_MODE_11NA_HT40MINUS;
-		else if (conf_is_ht40_plus(conf))
-			sc->cur_rate_mode = ATH9K_MODE_11NA_HT40PLUS;
-		else
-			sc->cur_rate_mode = ATH9K_MODE_11A;
-		break;
-	default:
-		BUG_ON(1);
-		break;
-	}
-}
-
 static void ath_update_txpow(struct ath_softc *sc)
 {
 	struct ath_hw *ah = sc->sc_ah;
@@ -121,6 +91,7 @@
 
 void ath9k_ps_wakeup(struct ath_softc *sc)
 {
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	unsigned long flags;
 
 	spin_lock_irqsave(&sc->sc_pm_lock, flags);
@@ -129,18 +100,33 @@
 
 	ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
 
+	/*
+	 * While the hardware is asleep, the cycle counters contain no
+	 * useful data. Better clear them now so that they don't mess up
+	 * survey data results.
+	 */
+	spin_lock(&common->cc_lock);
+	ath_hw_cycle_counters_update(common);
+	memset(&common->cc_survey, 0, sizeof(common->cc_survey));
+	spin_unlock(&common->cc_lock);
+
  unlock:
 	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 }
 
 void ath9k_ps_restore(struct ath_softc *sc)
 {
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	unsigned long flags;
 
 	spin_lock_irqsave(&sc->sc_pm_lock, flags);
 	if (--sc->ps_usecount != 0)
 		goto unlock;
 
+	spin_lock(&common->cc_lock);
+	ath_hw_cycle_counters_update(common);
+	spin_unlock(&common->cc_lock);
+
 	if (sc->ps_idle)
 		ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
 	else if (sc->ps_enabled &&
@@ -175,6 +161,45 @@
 			msecs_to_jiffies((u32)ah->config.ani_poll_interval));
 }
 
+static void ath_update_survey_nf(struct ath_softc *sc, int channel)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath9k_channel *chan = &ah->channels[channel];
+	struct survey_info *survey = &sc->survey[channel];
+
+	if (chan->noisefloor) {
+		survey->filled |= SURVEY_INFO_NOISE_DBM;
+		survey->noise = chan->noisefloor;
+	}
+}
+
+static void ath_update_survey_stats(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	int pos = ah->curchan - &ah->channels[0];
+	struct survey_info *survey = &sc->survey[pos];
+	struct ath_cycle_counters *cc = &common->cc_survey;
+	unsigned int div = common->clockrate * 1000;
+
+	if (ah->power_mode == ATH9K_PM_AWAKE)
+		ath_hw_cycle_counters_update(common);
+
+	if (cc->cycles > 0) {
+		survey->filled |= SURVEY_INFO_CHANNEL_TIME |
+			SURVEY_INFO_CHANNEL_TIME_BUSY |
+			SURVEY_INFO_CHANNEL_TIME_RX |
+			SURVEY_INFO_CHANNEL_TIME_TX;
+		survey->channel_time += cc->cycles / div;
+		survey->channel_time_busy += cc->rx_busy / div;
+		survey->channel_time_rx += cc->rx_frame / div;
+		survey->channel_time_tx += cc->tx_frame / div;
+	}
+	memset(cc, 0, sizeof(*cc));
+
+	ath_update_survey_nf(sc, pos);
+}
+
 /*
  * Set/change channels.  If the channel is really being changed, it's done
  * by reseting the chip.  To accomplish this we must first cleanup any pending
@@ -226,9 +251,10 @@
 		caldata = &aphy->caldata;
 
 	ath_print(common, ATH_DBG_CONFIG,
-		  "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n",
+		  "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
 		  sc->sc_ah->curchan->channel,
-		  channel->center_freq, conf_is_ht40(conf));
+		  channel->center_freq, conf_is_ht40(conf),
+		  fastcc);
 
 	spin_lock_bh(&sc->sc_resetlock);
 
@@ -250,14 +276,13 @@
 		goto ps_restore;
 	}
 
-	ath_cache_conf_rate(sc, &hw->conf);
 	ath_update_txpow(sc);
 	ath9k_hw_set_interrupts(ah, ah->imask);
 
-	if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) {
-		ath_start_ani(common);
-		ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+	if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
 		ath_beacon_config(sc, NULL);
+		ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+		ath_start_ani(common);
 	}
 
  ps_restore:
@@ -269,6 +294,7 @@
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath9k_hw_cal_data *caldata = ah->caldata;
+	struct ath_common *common = ath9k_hw_common(ah);
 	int chain;
 
 	if (!caldata || !caldata->paprd_done)
@@ -277,7 +303,7 @@
 	ath9k_ps_wakeup(sc);
 	ar9003_paprd_enable(ah, false);
 	for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
-		if (!(ah->caps.tx_chainmask & BIT(chain)))
+		if (!(common->tx_chainmask & BIT(chain)))
 			continue;
 
 		ar9003_paprd_populate_single_table(ah, caldata, chain);
@@ -299,6 +325,7 @@
 	struct ieee80211_supported_band *sband = &sc->sbands[band];
 	struct ath_tx_control txctl;
 	struct ath9k_hw_cal_data *caldata = ah->caldata;
+	struct ath_common *common = ath9k_hw_common(ah);
 	int qnum, ftype;
 	int chain_ok = 0;
 	int chain;
@@ -332,7 +359,7 @@
 	ath9k_ps_wakeup(sc);
 	ar9003_paprd_init_table(ah);
 	for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
-		if (!(ah->caps.tx_chainmask & BIT(chain)))
+		if (!(common->tx_chainmask & BIT(chain)))
 			continue;
 
 		chain_ok = 0;
@@ -395,7 +422,13 @@
 	bool shortcal = false;
 	bool aniflag = false;
 	unsigned int timestamp = jiffies_to_msecs(jiffies);
-	u32 cal_interval, short_cal_interval;
+	u32 cal_interval, short_cal_interval, long_cal_interval;
+	unsigned long flags;
+
+	if (ah->caldata && ah->caldata->nfcal_interference)
+		long_cal_interval = ATH_LONG_CALINTERVAL_INT;
+	else
+		long_cal_interval = ATH_LONG_CALINTERVAL;
 
 	short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
 		ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
@@ -407,7 +440,7 @@
 	ath9k_ps_wakeup(sc);
 
 	/* Long calibration runs independently of short calibration. */
-	if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
+	if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
 		longcal = true;
 		ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
 		common->ani.longcal_timer = timestamp;
@@ -441,8 +474,12 @@
 	/* Skip all processing if there's nothing to do. */
 	if (longcal || shortcal || aniflag) {
 		/* Call ANI routine if necessary */
-		if (aniflag)
+		if (aniflag) {
+			spin_lock_irqsave(&common->cc_lock, flags);
 			ath9k_hw_ani_monitor(ah, ah->curchan);
+			ath_update_survey_stats(sc);
+			spin_unlock_irqrestore(&common->cc_lock, flags);
+		}
 
 		/* Perform calibration if necessary */
 		if (longcal || shortcal) {
@@ -451,16 +488,6 @@
 						   ah->curchan,
 						   common->rx_chainmask,
 						   longcal);
-
-			if (longcal)
-				common->ani.noise_floor = ath9k_hw_getchan_noise(ah,
-								     ah->curchan);
-
-			ath_print(common, ATH_DBG_ANI,
-				  " calibrate chan %u/%x nf: %d\n",
-				  ah->curchan->channel,
-				  ah->curchan->channelFlags,
-				  common->ani.noise_floor);
 		}
 	}
 
@@ -637,6 +664,7 @@
 
 	struct ath_softc *sc = dev;
 	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
 	enum ath9k_int status;
 	bool sched = false;
 
@@ -686,7 +714,12 @@
 
 	if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
 	    (status & ATH9K_INT_BB_WATCHDOG)) {
+
+		spin_lock(&common->cc_lock);
+		ath_hw_cycle_counters_update(common);
 		ar9003_hw_bb_watchdog_dbg_info(ah);
+		spin_unlock(&common->cc_lock);
+
 		goto chip_reset;
 	}
 
@@ -715,7 +748,9 @@
 		 * it will clear whatever condition caused
 		 * the interrupt.
 		 */
-		ath9k_hw_procmibevent(ah);
+		spin_lock(&common->cc_lock);
+		ath9k_hw_proc_mib_event(ah);
+		spin_unlock(&common->cc_lock);
 		ath9k_hw_set_interrupts(ah, ah->imask);
 	}
 
@@ -947,11 +982,9 @@
 	 * that changes the channel so update any state that
 	 * might change as a result.
 	 */
-	ath_cache_conf_rate(sc, &hw->conf);
-
 	ath_update_txpow(sc);
 
-	if (sc->sc_flags & SC_OP_BEACONS)
+	if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
 		ath_beacon_config(sc, NULL);	/* restart beacons */
 
 	ath9k_hw_set_interrupts(ah, ah->imask);
@@ -1150,14 +1183,11 @@
 	else
 		ah->imask |= ATH9K_INT_RX;
 
-	if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT)
-		ah->imask |= ATH9K_INT_GTT;
+	ah->imask |= ATH9K_INT_GTT;
 
 	if (ah->caps.hw_caps & ATH9K_HW_CAP_HT)
 		ah->imask |= ATH9K_INT_CST;
 
-	ath_cache_conf_rate(sc, &hw->conf);
-
 	sc->sc_flags &= ~SC_OP_INVALID;
 
 	/* Disable BMISS interrupt when we're not associated */
@@ -1373,16 +1403,13 @@
 
 	mutex_lock(&sc->mutex);
 
-	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) &&
-	    sc->nvifs > 0) {
-		ret = -ENOBUFS;
-		goto out;
-	}
-
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
 		ic_opmode = NL80211_IFTYPE_STATION;
 		break;
+	case NL80211_IFTYPE_WDS:
+		ic_opmode = NL80211_IFTYPE_WDS;
+		break;
 	case NL80211_IFTYPE_ADHOC:
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_MESH_POINT:
@@ -1408,8 +1435,7 @@
 
 	sc->nvifs++;
 
-	if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
-		ath9k_set_bssid_mask(hw);
+	ath9k_set_bssid_mask(hw, vif);
 
 	if (sc->nvifs > 1)
 		goto out; /* skip global settings for secondary vif */
@@ -1491,7 +1517,7 @@
 	mutex_unlock(&sc->mutex);
 }
 
-void ath9k_enable_ps(struct ath_softc *sc)
+static void ath9k_enable_ps(struct ath_softc *sc)
 {
 	struct ath_hw *ah = sc->sc_ah;
 
@@ -1505,13 +1531,33 @@
 	}
 }
 
+static void ath9k_disable_ps(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+
+	sc->ps_enabled = false;
+	ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
+	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+		ath9k_hw_setrxabort(ah, 0);
+		sc->ps_flags &= ~(PS_WAIT_FOR_BEACON |
+				  PS_WAIT_FOR_CAB |
+				  PS_WAIT_FOR_PSPOLL_DATA |
+				  PS_WAIT_FOR_TX_ACK);
+		if (ah->imask & ATH9K_INT_TIM_TIMER) {
+			ah->imask &= ~ATH9K_INT_TIM_TIMER;
+			ath9k_hw_set_interrupts(ah, ah->imask);
+		}
+	}
+
+}
+
 static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ieee80211_conf *conf = &hw->conf;
 	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ieee80211_conf *conf = &hw->conf;
 	bool disable_radio;
 
 	mutex_lock(&sc->mutex);
@@ -1556,35 +1602,13 @@
 	 * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode.
 	 */
 	if (changed & IEEE80211_CONF_CHANGE_PS) {
-		if (conf->flags & IEEE80211_CONF_PS) {
-			sc->ps_flags |= PS_ENABLED;
-			/*
-			 * At this point we know hardware has received an ACK
-			 * of a previously sent null data frame.
-			 */
-			if ((sc->ps_flags & PS_NULLFUNC_COMPLETED)) {
-				sc->ps_flags &= ~PS_NULLFUNC_COMPLETED;
-				ath9k_enable_ps(sc);
-                        }
-		} else {
-			sc->ps_enabled = false;
-			sc->ps_flags &= ~(PS_ENABLED |
-					  PS_NULLFUNC_COMPLETED);
-			ath9k_setpower(sc, ATH9K_PM_AWAKE);
-			if (!(ah->caps.hw_caps &
-			      ATH9K_HW_CAP_AUTOSLEEP)) {
-				ath9k_hw_setrxabort(sc->sc_ah, 0);
-				sc->ps_flags &= ~(PS_WAIT_FOR_BEACON |
-						  PS_WAIT_FOR_CAB |
-						  PS_WAIT_FOR_PSPOLL_DATA |
-						  PS_WAIT_FOR_TX_ACK);
-				if (ah->imask & ATH9K_INT_TIM_TIMER) {
-					ah->imask &= ~ATH9K_INT_TIM_TIMER;
-					ath9k_hw_set_interrupts(sc->sc_ah,
-							ah->imask);
-				}
-			}
-		}
+		unsigned long flags;
+		spin_lock_irqsave(&sc->sc_pm_lock, flags);
+		if (conf->flags & IEEE80211_CONF_PS)
+			ath9k_enable_ps(sc);
+		else
+			ath9k_disable_ps(sc);
+		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
@@ -1598,6 +1622,11 @@
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
 		struct ieee80211_channel *curchan = hw->conf.channel;
 		int pos = curchan->hw_value;
+		int old_pos = -1;
+		unsigned long flags;
+
+		if (ah->curchan)
+			old_pos = ah->curchan - &ah->channels[0];
 
 		aphy->chan_idx = pos;
 		aphy->chan_is_ht = conf_is_ht(conf);
@@ -1625,12 +1654,45 @@
 
 		ath_update_chainmask(sc, conf_is_ht(conf));
 
+		/* update survey stats for the old channel before switching */
+		spin_lock_irqsave(&common->cc_lock, flags);
+		ath_update_survey_stats(sc);
+		spin_unlock_irqrestore(&common->cc_lock, flags);
+
+		/*
+		 * If the operating channel changes, change the survey in-use flags
+		 * along with it.
+		 * Reset the survey data for the new channel, unless we're switching
+		 * back to the operating channel from an off-channel operation.
+		 */
+		if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) &&
+		    sc->cur_survey != &sc->survey[pos]) {
+
+			if (sc->cur_survey)
+				sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
+
+			sc->cur_survey = &sc->survey[pos];
+
+			memset(sc->cur_survey, 0, sizeof(struct survey_info));
+			sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
+		} else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
+			memset(&sc->survey[pos], 0, sizeof(struct survey_info));
+		}
+
 		if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
 			ath_print(common, ATH_DBG_FATAL,
 				  "Unable to set channel\n");
 			mutex_unlock(&sc->mutex);
 			return -EINVAL;
 		}
+
+		/*
+		 * The most recent snapshot of channel->noisefloor for the old
+		 * channel is only available after the hardware reset. Copy it to
+		 * the survey stats now.
+		 */
+		if (old_pos >= 0)
+			ath_update_survey_nf(sc, old_pos);
 	}
 
 skip_chan_change:
@@ -1661,6 +1723,7 @@
 	FIF_PSPOLL |				\
 	FIF_OTHER_BSS |				\
 	FIF_BCN_PRBRESP_PROMISC |		\
+	FIF_PROBE_REQ |				\
 	FIF_FCSFAIL)
 
 /* FIXME: sc->sc_full_reset ? */
@@ -1771,20 +1834,21 @@
 
 	switch (cmd) {
 	case SET_KEY:
-		ret = ath9k_cmn_key_config(common, vif, sta, key);
+		ret = ath_key_config(common, vif, sta, key);
 		if (ret >= 0) {
 			key->hw_key_idx = ret;
 			/* push IV and Michael MIC generation to stack */
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-			if (key->alg == ALG_TKIP)
+			if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
 				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-			if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP)
+			if (sc->sc_ah->sw_mgmt_crypto &&
+			    key->cipher == WLAN_CIPHER_SUITE_CCMP)
 				key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
 			ret = 0;
 		}
 		break;
 	case DISABLE_KEY:
-		ath9k_cmn_key_delete(common, key);
+		ath_key_delete(common, key);
 		break;
 	default:
 		ret = -EINVAL;
@@ -1968,8 +2032,9 @@
 		break;
 	case IEEE80211_AMPDU_TX_START:
 		ath9k_ps_wakeup(sc);
-		ath_tx_aggr_start(sc, sta, tid, ssn);
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		ret = ath_tx_aggr_start(sc, sta, tid, ssn);
+		if (!ret)
+			ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 		ath9k_ps_restore(sc);
 		break;
 	case IEEE80211_AMPDU_TX_STOP:
@@ -1998,16 +2063,35 @@
 {
 	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 ieee80211_conf *conf = &hw->conf;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *chan;
+	unsigned long flags;
+	int pos;
 
-	 if (idx != 0)
+	spin_lock_irqsave(&common->cc_lock, flags);
+	if (idx == 0)
+		ath_update_survey_stats(sc);
+
+	sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
+	if (sband && idx >= sband->n_channels) {
+		idx -= sband->n_channels;
+		sband = NULL;
+	}
+
+	if (!sband)
+		sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];
+
+	if (!sband || idx >= sband->n_channels) {
+		spin_unlock_irqrestore(&common->cc_lock, flags);
 		return -ENOENT;
+	}
 
-	survey->channel = conf->channel;
-	survey->filled = SURVEY_INFO_NOISE_DBM;
-	survey->noise = common->ani.noise_floor;
+	chan = &sband->channels[idx];
+	pos = chan->hw_value;
+	memcpy(survey, &sc->survey[pos], sizeof(*survey));
+	survey->channel = chan;
+	spin_unlock_irqrestore(&common->cc_lock, flags);
 
 	return 0;
 }
@@ -2032,7 +2116,6 @@
 
 	aphy->state = ATH_WIPHY_SCAN;
 	ath9k_wiphy_pause_all_forced(sc, aphy);
-	sc->sc_flags |= SC_OP_SCANNING;
 	mutex_unlock(&sc->mutex);
 }
 
@@ -2047,7 +2130,6 @@
 
 	mutex_lock(&sc->mutex);
 	aphy->state = ATH_WIPHY_ACTIVE;
-	sc->sc_flags &= ~SC_OP_SCANNING;
 	mutex_unlock(&sc->mutex);
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h
index e724c2c..17969af 100644
--- a/drivers/net/wireless/ath/ath9k/phy.h
+++ b/drivers/net/wireless/ath/ath9k/phy.h
@@ -45,9 +45,6 @@
 		}							\
 	} while (0)
 
-#define ATH9K_IS_MIC_ENABLED(ah)					\
-	((ah)->sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE)
-
 #define ANTSWAP_AB 0x0001
 #define REDUCE_CHAIN_0 0x00000050
 #define REDUCE_CHAIN_1 0x00000051
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index e49be73..0cee90c 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -302,7 +302,7 @@
 		[64] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
 			205100, 20, 20, 8, 64, 65, 65 }, /* 243 Mb */
 		[65] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
-			224700, 20, 20, 8, 64, 65, 65 }, /* 170 Mb */
+			224700, 20, 20, 8, 64, 65, 65 }, /* 270 Mb */
 		[66] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
 			263100, 21, 21, 8, 66, 67, 67 }, /* 324 Mb */
 		[67] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
@@ -378,17 +378,6 @@
 	0,   /* Phy rates allowed initially */
 };
 
-static const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX] = {
-	[ATH9K_MODE_11A] = &ar5416_11a_ratetable,
-	[ATH9K_MODE_11G] = &ar5416_11g_ratetable,
-	[ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable,
-	[ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable,
-	[ATH9K_MODE_11NA_HT40PLUS] = &ar5416_11na_ratetable,
-	[ATH9K_MODE_11NA_HT40MINUS] = &ar5416_11na_ratetable,
-	[ATH9K_MODE_11NG_HT40PLUS] = &ar5416_11ng_ratetable,
-	[ATH9K_MODE_11NG_HT40MINUS] = &ar5416_11ng_ratetable,
-};
-
 static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
 				struct ieee80211_tx_rate *rate);
 
@@ -791,7 +780,7 @@
 	 */
 	try_per_rate = 4;
 
-	rate_table = sc->cur_rate_table;
+	rate_table = ath_rc_priv->rate_table;
 	rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
 
 	/*
@@ -1026,6 +1015,16 @@
 	return state_change;
 }
 
+static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
+				   int xretries, int retries, u8 per)
+{
+	struct ath_rc_stats *stats = &rc->rcstats[rix];
+
+	stats->xretries += xretries;
+	stats->retries += retries;
+	stats->per = per;
+}
+
 /* Update PER, RSSI and whatever else that the code thinks it is doing.
    If you can make sense of all this, you really need to go out more. */
 
@@ -1038,7 +1037,7 @@
 	int rate;
 	u8 last_per;
 	bool state_change = false;
-	const struct ath_rate_table *rate_table = sc->cur_rate_table;
+	const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
 	int size = ath_rc_priv->rate_table_size;
 
 	if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
@@ -1098,7 +1097,7 @@
 		ath_rc_priv->per_down_time = now_msec;
 	}
 
-	ath_debug_stat_retries(sc, tx_rate, xretries, retries,
+	ath_debug_stat_retries(ath_rc_priv, tx_rate, xretries, retries,
 			       ath_rc_priv->per[tx_rate]);
 
 }
@@ -1140,7 +1139,7 @@
 	u8 flags;
 	u32 i = 0, rix;
 
-	rate_table = sc->cur_rate_table;
+	rate_table = ath_rc_priv->rate_table;
 
 	/*
 	 * If the first rate is not the final index, there
@@ -1190,39 +1189,23 @@
 static const
 struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
 					     enum ieee80211_band band,
-					     bool is_ht,
-					     bool is_cw_40)
+					     bool is_ht)
 {
-	int mode = 0;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 
 	switch(band) {
 	case IEEE80211_BAND_2GHZ:
-		mode = ATH9K_MODE_11G;
 		if (is_ht)
-			mode = ATH9K_MODE_11NG_HT20;
-		if (is_cw_40)
-			mode = ATH9K_MODE_11NG_HT40PLUS;
-		break;
+			return &ar5416_11ng_ratetable;
+		return &ar5416_11g_ratetable;
 	case IEEE80211_BAND_5GHZ:
-		mode = ATH9K_MODE_11A;
 		if (is_ht)
-			mode = ATH9K_MODE_11NA_HT20;
-		if (is_cw_40)
-			mode = ATH9K_MODE_11NA_HT40PLUS;
-		break;
+			return &ar5416_11na_ratetable;
+		return &ar5416_11a_ratetable;
 	default:
 		ath_print(common, ATH_DBG_CONFIG, "Invalid band\n");
 		return NULL;
 	}
-
-	BUG_ON(mode >= ATH9K_MODE_MAX);
-
-	ath_print(common, ATH_DBG_CONFIG,
-		  "Choosing rate table for mode: %d\n", mode);
-
-	sc->cur_rate_mode = mode;
-	return hw_rate_table[mode];
 }
 
 static void ath_rc_init(struct ath_softc *sc,
@@ -1293,7 +1276,7 @@
 	ath_rc_priv->max_valid_rate = k;
 	ath_rc_sort_validrates(rate_table, ath_rc_priv);
 	ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
-	sc->cur_rate_table = rate_table;
+	ath_rc_priv->rate_table = rate_table;
 
 	ath_print(common, ATH_DBG_CONFIG,
 		  "RC Initialized with capabilities: 0x%x\n",
@@ -1320,10 +1303,35 @@
 	return caps;
 }
 
+static bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an,
+			      u8 tidno)
+{
+	struct ath_atx_tid *txtid;
+
+	if (!(sc->sc_flags & SC_OP_TXAGGR))
+		return false;
+
+	txtid = ATH_AN_2_TID(an, tidno);
+
+	if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS)))
+			return true;
+	return false;
+}
+
+
 /***********************************/
 /* mac80211 Rate Control callbacks */
 /***********************************/
 
+static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
+{
+	struct ath_rc_stats *stats;
+
+	stats = &rc->rcstats[final_rate];
+	stats->success++;
+}
+
+
 static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
 			  struct ieee80211_sta *sta, void *priv_sta,
 			  struct sk_buff *skb)
@@ -1359,6 +1367,12 @@
 	if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
 		return;
 
+	if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) {
+		tx_info->status.ampdu_ack_len =
+			(tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0);
+		tx_info->status.ampdu_len = 1;
+	}
+
 	/*
 	 * If an underrun error is seen assume it as an excessive retry only
 	 * if max frame trigger level has been reached (2 KB for singel stream,
@@ -1397,8 +1411,9 @@
 		}
 	}
 
-	ath_debug_stat_rc(sc, ath_rc_get_rateindex(sc->cur_rate_table,
-		&tx_info->status.rates[final_ts_idx]));
+	ath_debug_stat_rc(ath_rc_priv,
+		ath_rc_get_rateindex(ath_rc_priv->rate_table,
+			&tx_info->status.rates[final_ts_idx]));
 }
 
 static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
@@ -1438,14 +1453,8 @@
 
 	/* Choose rate table first */
 
-	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
-	    (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) ||
-	    (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
-		rate_table = ath_choose_rate_table(sc, sband->band,
-		                      sta->ht_cap.ht_supported, is_cw40);
-	} else {
-		rate_table = hw_rate_table[sc->cur_rate_mode];
-	}
+	rate_table = ath_choose_rate_table(sc, sband->band,
+	                      sta->ht_cap.ht_supported);
 
 	ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi);
 	ath_rc_init(sc, priv_sta, sband, sta, rate_table);
@@ -1485,8 +1494,7 @@
 
 		if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) {
 			rate_table = ath_choose_rate_table(sc, sband->band,
-						   sta->ht_cap.ht_supported,
-						   oper_cw40);
+						   sta->ht_cap.ht_supported);
 			ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta,
 						   oper_cw40, oper_sgi);
 			ath_rc_init(sc, priv_sta, sband, sta, rate_table);
@@ -1494,11 +1502,98 @@
 			ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
 				  "Operating HT Bandwidth changed to: %d\n",
 				  sc->hw->conf.channel_type);
-			sc->cur_rate_table = hw_rate_table[sc->cur_rate_mode];
 		}
 	}
 }
 
+#ifdef CONFIG_ATH9K_DEBUGFS
+
+static int ath9k_debugfs_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct ath_rate_priv *rc = file->private_data;
+	char *buf;
+	unsigned int len = 0, max;
+	int i = 0;
+	ssize_t retval;
+
+	if (rc->rate_table == NULL)
+		return 0;
+
+	max = 80 + rc->rate_table->rate_cnt * 1024 + 1;
+	buf = kmalloc(max, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	len += sprintf(buf, "%6s %6s %6s "
+		       "%10s %10s %10s %10s\n",
+		       "HT", "MCS", "Rate",
+		       "Success", "Retries", "XRetries", "PER");
+
+	for (i = 0; i < rc->rate_table->rate_cnt; i++) {
+		u32 ratekbps = rc->rate_table->info[i].ratekbps;
+		struct ath_rc_stats *stats = &rc->rcstats[i];
+		char mcs[5];
+		char htmode[5];
+		int used_mcs = 0, used_htmode = 0;
+
+		if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) {
+			used_mcs = snprintf(mcs, 5, "%d",
+				rc->rate_table->info[i].ratecode);
+
+			if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy))
+				used_htmode = snprintf(htmode, 5, "HT40");
+			else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy))
+				used_htmode = snprintf(htmode, 5, "HT20");
+			else
+				used_htmode = snprintf(htmode, 5, "????");
+		}
+
+		mcs[used_mcs] = '\0';
+		htmode[used_htmode] = '\0';
+
+		len += snprintf(buf + len, max - len,
+			"%6s %6s %3u.%d: "
+			"%10u %10u %10u %10u\n",
+			htmode,
+			mcs,
+			ratekbps / 1000,
+			(ratekbps % 1000) / 100,
+			stats->success,
+			stats->retries,
+			stats->xretries,
+			stats->per);
+	}
+
+	if (len > max)
+		len = max;
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+	return retval;
+}
+
+static const struct file_operations fops_rcstat = {
+	.read = read_file_rcstat,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE
+};
+
+static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta,
+				     struct dentry *dir)
+{
+	struct ath_rate_priv *rc = priv_sta;
+	debugfs_create_file("rc_stats", S_IRUGO, dir, rc, &fops_rcstat);
+}
+
+#endif /* CONFIG_ATH9K_DEBUGFS */
+
 static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
 {
 	struct ath_wiphy *aphy = hw->priv;
@@ -1545,6 +1640,9 @@
 	.free = ath_rate_free,
 	.alloc_sta = ath_rate_alloc_sta,
 	.free_sta = ath_rate_free_sta,
+#ifdef CONFIG_ATH9K_DEBUGFS
+	.add_sta_debugfs = ath_rate_add_sta_debugfs,
+#endif
 };
 
 int ath_rate_control_register(void)
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index dc10826..2f46a22 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -135,20 +135,21 @@
 
 /**
  * struct ath_rate_table - Rate Control table
- * @valid: valid for use in rate control
- * @valid_single_stream: valid for use in rate control for
- * 	single stream operation
- * @phy: CCK/OFDM
+ * @rate_cnt: total number of rates for the given wireless mode
+ * @mcs_start: MCS rate index offset
+ * @rate_flags: Rate Control flags
+ * @phy: CCK/OFDM/HT20/HT40
  * @ratekbps: rate in Kbits per second
  * @user_ratekbps: user rate in Kbits per second
  * @ratecode: rate that goes into HW descriptors
- * @short_preamble: Mask for enabling short preamble in ratecode for CCK
  * @dot11rate: value that goes into supported
  * 	rates info element of MLME
  * @ctrl_rate: Index of next lower basic rate, used for duration computation
- * @max_4ms_framelen: maximum frame length(bytes) for tx duration
+ * @cw40index: Index of rates having 40MHz channel width
+ * @sgi_index: Index of rates having Short Guard Interval
+ * @ht_index: high throughput rates having 40MHz channel width and
+ * 	Short Guard Interval
  * @probe_interval: interval for rate control to probe for other rates
- * @rssi_reduce_interval: interval for rate control to reduce rssi
  * @initial_ratemax: initial ratemax value
  */
 struct ath_rate_table {
@@ -175,6 +176,13 @@
 	u8 rs_rates[ATH_RATE_MAX];
 };
 
+struct ath_rc_stats {
+	u32 success;
+	u32 retries;
+	u32 xretries;
+	u8 per;
+};
+
 /**
  * struct ath_rate_priv - Rate Control priv data
  * @state: RC state
@@ -211,6 +219,10 @@
 	struct ath_rateset neg_rates;
 	struct ath_rateset neg_ht_rates;
 	struct ath_rate_softc *asc;
+	const struct ath_rate_table *rate_table;
+
+	struct dentry *debugfs_rcstats;
+	struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
 };
 
 #define ATH_TX_INFO_FRAME_TYPE_INTERNAL	(1 << 0)
@@ -224,7 +236,18 @@
 	ATH9K_IFT_UNPAUSE
 };
 
+#ifdef CONFIG_ATH9K_RATE_CONTROL
 int ath_rate_control_register(void);
 void ath_rate_control_unregister(void);
+#else
+static inline int ath_rate_control_register(void)
+{
+	return 0;
+}
+
+static inline void ath_rate_control_unregister(void)
+{
+}
+#endif
 
 #endif /* RC_H */
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index a3fc987..fe73fc5 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -19,6 +19,15 @@
 
 #define SKB_CB_ATHBUF(__skb)	(*((struct ath_buf **)__skb->cb))
 
+static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta,
+					       int mindelta, int main_rssi_avg,
+					       int alt_rssi_avg, int pkt_count)
+{
+	return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
+		(alt_rssi_avg > main_rssi_avg + maxdelta)) ||
+		(alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50);
+}
+
 static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
 {
 	return sc->ps_enabled &&
@@ -110,8 +119,7 @@
 	ath9k_hw_setrxfilter(ah, rfilt);
 
 	/* configure bssid mask */
-	if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
-		ath_hw_setbssidmask(common);
+	ath_hw_setbssidmask(common);
 
 	/* configure operational mode */
 	ath9k_hw_setopmode(ah);
@@ -260,6 +268,7 @@
 						bf->bf_buf_addr))) {
 				dev_kfree_skb_any(skb);
 				bf->bf_mpdu = NULL;
+				bf->bf_buf_addr = 0;
 				ath_print(common, ATH_DBG_FATAL,
 					"dma_mapping_error() on RX init\n");
 				error = -ENOMEM;
@@ -292,7 +301,7 @@
 
 	ath_opmode_init(sc);
 
-	ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING));
+	ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
 }
 
 static void ath_edma_stop_recv(struct ath_softc *sc)
@@ -350,12 +359,12 @@
 							bf->bf_buf_addr))) {
 				dev_kfree_skb_any(skb);
 				bf->bf_mpdu = NULL;
+				bf->bf_buf_addr = 0;
 				ath_print(common, ATH_DBG_FATAL,
 					  "dma_mapping_error() on RX init\n");
 				error = -ENOMEM;
 				goto err;
 			}
-			bf->bf_dmacontext = bf->bf_buf_addr;
 		}
 		sc->rx.rxlink = NULL;
 	}
@@ -385,6 +394,8 @@
 						common->rx_bufsize,
 						DMA_FROM_DEVICE);
 				dev_kfree_skb(skb);
+				bf->bf_buf_addr = 0;
+				bf->bf_mpdu = NULL;
 			}
 		}
 
@@ -422,8 +433,7 @@
 		| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
 		| ATH9K_RX_FILTER_MCAST;
 
-	/* If not a STA, enable processing of Probe Requests */
-	if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+	if (sc->rx.rxfilter & FIF_PROBE_REQ)
 		rfilt |= ATH9K_RX_FILTER_PROBEREQ;
 
 	/*
@@ -440,13 +450,14 @@
 		rfilt |= ATH9K_RX_FILTER_CONTROL;
 
 	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
+	    (sc->nvifs <= 1) &&
 	    !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC))
 		rfilt |= ATH9K_RX_FILTER_MYBEACON;
 	else
 		rfilt |= ATH9K_RX_FILTER_BEACON;
 
-	if ((AR_SREV_9280_10_OR_LATER(sc->sc_ah) ||
-	    AR_SREV_9285_10_OR_LATER(sc->sc_ah)) &&
+	if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) ||
+	    AR_SREV_9285_12_OR_LATER(sc->sc_ah)) &&
 	    (sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
 	    (sc->rx.rxfilter & FIF_PSPOLL))
 		rfilt |= ATH9K_RX_FILTER_PSPOLL;
@@ -454,9 +465,8 @@
 	if (conf_is_ht(&sc->hw->conf))
 		rfilt |= ATH9K_RX_FILTER_COMP_BAR;
 
-	if (sc->sec_wiphy || (sc->rx.rxfilter & FIF_OTHER_BSS)) {
-		/* TODO: only needed if more than one BSSID is in use in
-		 * station/adhoc mode */
+	if (sc->sec_wiphy || (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;
@@ -498,7 +508,7 @@
 start_recv:
 	spin_unlock_bh(&sc->rx.rxbuflock);
 	ath_opmode_init(sc);
-	ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING));
+	ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
 
 	return 0;
 }
@@ -631,7 +641,7 @@
 		 * No more broadcast/multicast frames to be received at this
 		 * point.
 		 */
-		sc->ps_flags &= ~PS_WAIT_FOR_CAB;
+		sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON);
 		ath_print(common, ATH_DBG_PS,
 			  "All PS CAB frames received, back to sleep\n");
 	} else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) &&
@@ -870,15 +880,18 @@
 		if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
 			*decrypt_error = true;
 		} else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
-			if (ieee80211_is_ctl(fc))
-				/*
-				 * Sometimes, we get invalid
-				 * MIC failures on valid control frames.
-				 * Remove these mic errors.
-				 */
-				rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
-			else
+			/*
+			 * The MIC error bit is only valid if the frame
+			 * is not a control frame or fragment, and it was
+			 * decrypted using a valid TKIP key.
+			 */
+			if (!ieee80211_is_ctl(fc) &&
+			    !ieee80211_has_morefrags(fc) &&
+			    !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
+			    test_bit(rx_stats->rs_keyix, common->tkip_keymap))
 				rxs->flag |= RX_FLAG_MMIC_ERROR;
+			else
+				rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
 		}
 		/*
 		 * Reject error frames with the exception of
@@ -966,7 +979,11 @@
 	 * at least one sdata of a wiphy on mac80211 but with ath9k virtual
 	 * wiphy you'd have to iterate over every wiphy and each sdata.
 	 */
-	sta = ieee80211_find_sta_by_hw(hw, hdr->addr2);
+	if (is_multicast_ether_addr(hdr->addr1))
+		sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
+	else
+		sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
+
 	if (sta) {
 		an = (struct ath_node *) sta->drv_priv;
 		if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
@@ -1073,6 +1090,539 @@
 		rxs->flag &= ~RX_FLAG_DECRYPTED;
 }
 
+static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
+				      struct ath_hw_antcomb_conf ant_conf,
+				      int main_rssi_avg)
+{
+	antcomb->quick_scan_cnt = 0;
+
+	if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
+		antcomb->rssi_lna2 = main_rssi_avg;
+	else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1)
+		antcomb->rssi_lna1 = main_rssi_avg;
+
+	switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
+	case (0x10): /* LNA2 A-B */
+		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+		antcomb->first_quick_scan_conf =
+			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
+		break;
+	case (0x20): /* LNA1 A-B */
+		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+		antcomb->first_quick_scan_conf =
+			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
+		break;
+	case (0x21): /* LNA1 LNA2 */
+		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;
+		antcomb->first_quick_scan_conf =
+			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+		antcomb->second_quick_scan_conf =
+			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+		break;
+	case (0x12): /* LNA2 LNA1 */
+		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;
+		antcomb->first_quick_scan_conf =
+			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+		antcomb->second_quick_scan_conf =
+			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+		break;
+	case (0x13): /* LNA2 A+B */
+		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+		antcomb->first_quick_scan_conf =
+			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
+		break;
+	case (0x23): /* LNA1 A+B */
+		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+		antcomb->first_quick_scan_conf =
+			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
+		break;
+	default:
+		break;
+	}
+}
+
+static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
+				struct ath_hw_antcomb_conf *div_ant_conf,
+				int main_rssi_avg, int alt_rssi_avg,
+				int alt_ratio)
+{
+	/* alt_good */
+	switch (antcomb->quick_scan_cnt) {
+	case 0:
+		/* set alt to main, and alt to first conf */
+		div_ant_conf->main_lna_conf = antcomb->main_conf;
+		div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf;
+		break;
+	case 1:
+		/* set alt to main, and alt to first conf */
+		div_ant_conf->main_lna_conf = antcomb->main_conf;
+		div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf;
+		antcomb->rssi_first = main_rssi_avg;
+		antcomb->rssi_second = alt_rssi_avg;
+
+		if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
+			/* main is LNA1 */
+			if (ath_is_alt_ant_ratio_better(alt_ratio,
+						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
+						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+						main_rssi_avg, alt_rssi_avg,
+						antcomb->total_pkt_count))
+				antcomb->first_ratio = true;
+			else
+				antcomb->first_ratio = false;
+		} else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
+			if (ath_is_alt_ant_ratio_better(alt_ratio,
+						ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
+						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+						main_rssi_avg, alt_rssi_avg,
+						antcomb->total_pkt_count))
+				antcomb->first_ratio = true;
+			else
+				antcomb->first_ratio = false;
+		} else {
+			if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
+			    (alt_rssi_avg > main_rssi_avg +
+			    ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
+			    (alt_rssi_avg > main_rssi_avg)) &&
+			    (antcomb->total_pkt_count > 50))
+				antcomb->first_ratio = true;
+			else
+				antcomb->first_ratio = false;
+		}
+		break;
+	case 2:
+		antcomb->alt_good = false;
+		antcomb->scan_not_start = false;
+		antcomb->scan = false;
+		antcomb->rssi_first = main_rssi_avg;
+		antcomb->rssi_third = alt_rssi_avg;
+
+		if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1)
+			antcomb->rssi_lna1 = alt_rssi_avg;
+		else if (antcomb->second_quick_scan_conf ==
+			 ATH_ANT_DIV_COMB_LNA2)
+			antcomb->rssi_lna2 = alt_rssi_avg;
+		else if (antcomb->second_quick_scan_conf ==
+			 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) {
+			if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)
+				antcomb->rssi_lna2 = main_rssi_avg;
+			else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1)
+				antcomb->rssi_lna1 = main_rssi_avg;
+		}
+
+		if (antcomb->rssi_lna2 > antcomb->rssi_lna1 +
+		    ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)
+			div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+		else
+			div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+
+		if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
+			if (ath_is_alt_ant_ratio_better(alt_ratio,
+						ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
+						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+						main_rssi_avg, alt_rssi_avg,
+						antcomb->total_pkt_count))
+				antcomb->second_ratio = true;
+			else
+				antcomb->second_ratio = false;
+		} else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
+			if (ath_is_alt_ant_ratio_better(alt_ratio,
+						ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
+						ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+						main_rssi_avg, alt_rssi_avg,
+						antcomb->total_pkt_count))
+				antcomb->second_ratio = true;
+			else
+				antcomb->second_ratio = false;
+		} else {
+			if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
+			    (alt_rssi_avg > main_rssi_avg +
+			    ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
+			    (alt_rssi_avg > main_rssi_avg)) &&
+			    (antcomb->total_pkt_count > 50))
+				antcomb->second_ratio = true;
+			else
+				antcomb->second_ratio = false;
+		}
+
+		/* set alt to the conf with maximun ratio */
+		if (antcomb->first_ratio && antcomb->second_ratio) {
+			if (antcomb->rssi_second > antcomb->rssi_third) {
+				/* first alt*/
+				if ((antcomb->first_quick_scan_conf ==
+				    ATH_ANT_DIV_COMB_LNA1) ||
+				    (antcomb->first_quick_scan_conf ==
+				    ATH_ANT_DIV_COMB_LNA2))
+					/* Set alt LNA1 or LNA2*/
+					if (div_ant_conf->main_lna_conf ==
+					    ATH_ANT_DIV_COMB_LNA2)
+						div_ant_conf->alt_lna_conf =
+							ATH_ANT_DIV_COMB_LNA1;
+					else
+						div_ant_conf->alt_lna_conf =
+							ATH_ANT_DIV_COMB_LNA2;
+				else
+					/* Set alt to A+B or A-B */
+					div_ant_conf->alt_lna_conf =
+						antcomb->first_quick_scan_conf;
+			} else if ((antcomb->second_quick_scan_conf ==
+				   ATH_ANT_DIV_COMB_LNA1) ||
+				   (antcomb->second_quick_scan_conf ==
+				   ATH_ANT_DIV_COMB_LNA2)) {
+				/* Set alt LNA1 or LNA2 */
+				if (div_ant_conf->main_lna_conf ==
+				    ATH_ANT_DIV_COMB_LNA2)
+					div_ant_conf->alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1;
+				else
+					div_ant_conf->alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA2;
+			} else {
+				/* Set alt to A+B or A-B */
+				div_ant_conf->alt_lna_conf =
+					antcomb->second_quick_scan_conf;
+			}
+		} else if (antcomb->first_ratio) {
+			/* first alt */
+			if ((antcomb->first_quick_scan_conf ==
+			    ATH_ANT_DIV_COMB_LNA1) ||
+			    (antcomb->first_quick_scan_conf ==
+			    ATH_ANT_DIV_COMB_LNA2))
+					/* Set alt LNA1 or LNA2 */
+				if (div_ant_conf->main_lna_conf ==
+				    ATH_ANT_DIV_COMB_LNA2)
+					div_ant_conf->alt_lna_conf =
+							ATH_ANT_DIV_COMB_LNA1;
+				else
+					div_ant_conf->alt_lna_conf =
+							ATH_ANT_DIV_COMB_LNA2;
+			else
+				/* Set alt to A+B or A-B */
+				div_ant_conf->alt_lna_conf =
+						antcomb->first_quick_scan_conf;
+		} else if (antcomb->second_ratio) {
+				/* second alt */
+			if ((antcomb->second_quick_scan_conf ==
+			    ATH_ANT_DIV_COMB_LNA1) ||
+			    (antcomb->second_quick_scan_conf ==
+			    ATH_ANT_DIV_COMB_LNA2))
+				/* Set alt LNA1 or LNA2 */
+				if (div_ant_conf->main_lna_conf ==
+				    ATH_ANT_DIV_COMB_LNA2)
+					div_ant_conf->alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1;
+				else
+					div_ant_conf->alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA2;
+			else
+				/* Set alt to A+B or A-B */
+				div_ant_conf->alt_lna_conf =
+						antcomb->second_quick_scan_conf;
+		} else {
+			/* main is largest */
+			if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) ||
+			    (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2))
+				/* Set alt LNA1 or LNA2 */
+				if (div_ant_conf->main_lna_conf ==
+				    ATH_ANT_DIV_COMB_LNA2)
+					div_ant_conf->alt_lna_conf =
+							ATH_ANT_DIV_COMB_LNA1;
+				else
+					div_ant_conf->alt_lna_conf =
+							ATH_ANT_DIV_COMB_LNA2;
+			else
+				/* Set alt to A+B or A-B */
+				div_ant_conf->alt_lna_conf = antcomb->main_conf;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf)
+{
+	/* Adjust the fast_div_bias based on main and alt lna conf */
+	switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) {
+	case (0x01): /* A-B LNA2 */
+		ant_conf->fast_div_bias = 0x3b;
+		break;
+	case (0x02): /* A-B LNA1 */
+		ant_conf->fast_div_bias = 0x3d;
+		break;
+	case (0x03): /* A-B A+B */
+		ant_conf->fast_div_bias = 0x1;
+		break;
+	case (0x10): /* LNA2 A-B */
+		ant_conf->fast_div_bias = 0x7;
+		break;
+	case (0x12): /* LNA2 LNA1 */
+		ant_conf->fast_div_bias = 0x2;
+		break;
+	case (0x13): /* LNA2 A+B */
+		ant_conf->fast_div_bias = 0x7;
+		break;
+	case (0x20): /* LNA1 A-B */
+		ant_conf->fast_div_bias = 0x6;
+		break;
+	case (0x21): /* LNA1 LNA2 */
+		ant_conf->fast_div_bias = 0x0;
+		break;
+	case (0x23): /* LNA1 A+B */
+		ant_conf->fast_div_bias = 0x6;
+		break;
+	case (0x30): /* A+B A-B */
+		ant_conf->fast_div_bias = 0x1;
+		break;
+	case (0x31): /* A+B LNA2 */
+		ant_conf->fast_div_bias = 0x3b;
+		break;
+	case (0x32): /* A+B LNA1 */
+		ant_conf->fast_div_bias = 0x3d;
+		break;
+	default:
+		break;
+	}
+}
+
+/* Antenna diversity and combining */
+static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
+{
+	struct ath_hw_antcomb_conf div_ant_conf;
+	struct ath_ant_comb *antcomb = &sc->ant_comb;
+	int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
+	int curr_main_set, curr_bias;
+	int main_rssi = rs->rs_rssi_ctl0;
+	int alt_rssi = rs->rs_rssi_ctl1;
+	int rx_ant_conf,  main_ant_conf;
+	bool short_scan = false;
+
+	rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
+		       ATH_ANT_RX_MASK;
+	main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
+			 ATH_ANT_RX_MASK;
+
+	/* Record packet only when alt_rssi is positive */
+	if (alt_rssi > 0) {
+		antcomb->total_pkt_count++;
+		antcomb->main_total_rssi += main_rssi;
+		antcomb->alt_total_rssi  += alt_rssi;
+		if (main_ant_conf == rx_ant_conf)
+			antcomb->main_recv_cnt++;
+		else
+			antcomb->alt_recv_cnt++;
+	}
+
+	/* Short scan check */
+	if (antcomb->scan && antcomb->alt_good) {
+		if (time_after(jiffies, antcomb->scan_start_time +
+		    msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR)))
+			short_scan = true;
+		else
+			if (antcomb->total_pkt_count ==
+			    ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) {
+				alt_ratio = ((antcomb->alt_recv_cnt * 100) /
+					    antcomb->total_pkt_count);
+				if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
+					short_scan = true;
+			}
+	}
+
+	if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) ||
+	    rs->rs_moreaggr) && !short_scan)
+		return;
+
+	if (antcomb->total_pkt_count) {
+		alt_ratio = ((antcomb->alt_recv_cnt * 100) /
+			     antcomb->total_pkt_count);
+		main_rssi_avg = (antcomb->main_total_rssi /
+				 antcomb->total_pkt_count);
+		alt_rssi_avg = (antcomb->alt_total_rssi /
+				 antcomb->total_pkt_count);
+	}
+
+
+	ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf);
+	curr_alt_set = div_ant_conf.alt_lna_conf;
+	curr_main_set = div_ant_conf.main_lna_conf;
+	curr_bias = div_ant_conf.fast_div_bias;
+
+	antcomb->count++;
+
+	if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) {
+		if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
+			ath_lnaconf_alt_good_scan(antcomb, div_ant_conf,
+						  main_rssi_avg);
+			antcomb->alt_good = true;
+		} else {
+			antcomb->alt_good = false;
+		}
+
+		antcomb->count = 0;
+		antcomb->scan = true;
+		antcomb->scan_not_start = true;
+	}
+
+	if (!antcomb->scan) {
+		if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
+			if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) {
+				/* Switch main and alt LNA */
+				div_ant_conf.main_lna_conf =
+						ATH_ANT_DIV_COMB_LNA2;
+				div_ant_conf.alt_lna_conf  =
+						ATH_ANT_DIV_COMB_LNA1;
+			} else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) {
+				div_ant_conf.main_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1;
+				div_ant_conf.alt_lna_conf  =
+						ATH_ANT_DIV_COMB_LNA2;
+			}
+
+			goto div_comb_done;
+		} else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) &&
+			   (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) {
+			/* Set alt to another LNA */
+			if (curr_main_set == ATH_ANT_DIV_COMB_LNA2)
+				div_ant_conf.alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1;
+			else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1)
+				div_ant_conf.alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA2;
+
+			goto div_comb_done;
+		}
+
+		if ((alt_rssi_avg < (main_rssi_avg +
+		    ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA)))
+			goto div_comb_done;
+	}
+
+	if (!antcomb->scan_not_start) {
+		switch (curr_alt_set) {
+		case ATH_ANT_DIV_COMB_LNA2:
+			antcomb->rssi_lna2 = alt_rssi_avg;
+			antcomb->rssi_lna1 = main_rssi_avg;
+			antcomb->scan = true;
+			/* set to A+B */
+			div_ant_conf.main_lna_conf =
+				ATH_ANT_DIV_COMB_LNA1;
+			div_ant_conf.alt_lna_conf  =
+				ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+			break;
+		case ATH_ANT_DIV_COMB_LNA1:
+			antcomb->rssi_lna1 = alt_rssi_avg;
+			antcomb->rssi_lna2 = main_rssi_avg;
+			antcomb->scan = true;
+			/* set to A+B */
+			div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+			div_ant_conf.alt_lna_conf  =
+				ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+			break;
+		case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2:
+			antcomb->rssi_add = alt_rssi_avg;
+			antcomb->scan = true;
+			/* set to A-B */
+			div_ant_conf.alt_lna_conf =
+				ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+			break;
+		case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2:
+			antcomb->rssi_sub = alt_rssi_avg;
+			antcomb->scan = false;
+			if (antcomb->rssi_lna2 >
+			    (antcomb->rssi_lna1 +
+			    ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) {
+				/* use LNA2 as main LNA */
+				if ((antcomb->rssi_add > antcomb->rssi_lna1) &&
+				    (antcomb->rssi_add > antcomb->rssi_sub)) {
+					/* set to A+B */
+					div_ant_conf.main_lna_conf =
+						ATH_ANT_DIV_COMB_LNA2;
+					div_ant_conf.alt_lna_conf  =
+						ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+				} else if (antcomb->rssi_sub >
+					   antcomb->rssi_lna1) {
+					/* set to A-B */
+					div_ant_conf.main_lna_conf =
+						ATH_ANT_DIV_COMB_LNA2;
+					div_ant_conf.alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+				} else {
+					/* set to LNA1 */
+					div_ant_conf.main_lna_conf =
+						ATH_ANT_DIV_COMB_LNA2;
+					div_ant_conf.alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1;
+				}
+			} else {
+				/* use LNA1 as main LNA */
+				if ((antcomb->rssi_add > antcomb->rssi_lna2) &&
+				    (antcomb->rssi_add > antcomb->rssi_sub)) {
+					/* set to A+B */
+					div_ant_conf.main_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1;
+					div_ant_conf.alt_lna_conf  =
+						ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+				} else if (antcomb->rssi_sub >
+					   antcomb->rssi_lna1) {
+					/* set to A-B */
+					div_ant_conf.main_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1;
+					div_ant_conf.alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+				} else {
+					/* set to LNA2 */
+					div_ant_conf.main_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1;
+					div_ant_conf.alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA2;
+				}
+			}
+			break;
+		default:
+			break;
+		}
+	} else {
+		if (!antcomb->alt_good) {
+			antcomb->scan_not_start = false;
+			/* Set alt to another LNA */
+			if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) {
+				div_ant_conf.main_lna_conf =
+						ATH_ANT_DIV_COMB_LNA2;
+				div_ant_conf.alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1;
+			} else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) {
+				div_ant_conf.main_lna_conf =
+						ATH_ANT_DIV_COMB_LNA1;
+				div_ant_conf.alt_lna_conf =
+						ATH_ANT_DIV_COMB_LNA2;
+			}
+			goto div_comb_done;
+		}
+	}
+
+	ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf,
+					   main_rssi_avg, alt_rssi_avg,
+					   alt_ratio);
+
+	antcomb->quick_scan_cnt++;
+
+div_comb_done:
+	ath_ant_div_conf_fast_divbias(&div_ant_conf);
+
+	ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf);
+
+	antcomb->scan_start_time = jiffies;
+	antcomb->total_pkt_count = 0;
+	antcomb->main_total_rssi = 0;
+	antcomb->alt_total_rssi = 0;
+	antcomb->main_recv_cnt = 0;
+	antcomb->alt_recv_cnt = 0;
+}
+
 int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 {
 	struct ath_buf *bf;
@@ -1096,6 +1646,7 @@
 	u8 rx_status_len = ah->caps.rx_status_len;
 	u64 tsf = 0;
 	u32 tsf_lower = 0;
+	unsigned long flags;
 
 	if (edma)
 		dma_type = DMA_BIDIRECTIONAL;
@@ -1186,12 +1737,12 @@
 			  bf->bf_buf_addr))) {
 			dev_kfree_skb_any(requeue_skb);
 			bf->bf_mpdu = NULL;
+			bf->bf_buf_addr = 0;
 			ath_print(common, ATH_DBG_FATAL,
 				  "dma_mapping_error() on RX\n");
 			ath_rx_send_to_mac80211(hw, sc, skb, rxs);
 			break;
 		}
-		bf->bf_dmacontext = bf->bf_buf_addr;
 
 		/*
 		 * change the default rx antenna if rx diversity chooses the
@@ -1204,11 +1755,16 @@
 			sc->rx.rxotherant = 0;
 		}
 
+		spin_lock_irqsave(&sc->sc_pm_lock, flags);
 		if (unlikely(ath9k_check_auto_sleep(sc) ||
 			     (sc->ps_flags & (PS_WAIT_FOR_BEACON |
 					      PS_WAIT_FOR_CAB |
 					      PS_WAIT_FOR_PSPOLL_DATA))))
 			ath_rx_ps(sc, skb);
+		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+
+		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, rxs);
 
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index d01c4ad..42976b0 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -107,12 +107,6 @@
 #define AR_RXCFG_DMASZ_256B  6
 #define AR_RXCFG_DMASZ_512B  7
 
-#define AR_MIBC              0x0040
-#define AR_MIBC_COW          0x00000001
-#define AR_MIBC_FMC          0x00000002
-#define AR_MIBC_CMC          0x00000004
-#define AR_MIBC_MCS          0x00000008
-
 #define AR_TOPS              0x0044
 #define AR_TOPS_MASK         0x0000FFFF
 
@@ -819,49 +813,23 @@
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11))
 #define AR_SREV_9280(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
-#define AR_SREV_9280_10_OR_LATER(_ah) \
+#define AR_SREV_9280_20_OR_LATER(_ah) \
 	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280))
 #define AR_SREV_9280_20(_ah) \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
-		((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20))
-#define AR_SREV_9280_20_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9280) || \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
-	((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20)))
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
 
 #define AR_SREV_9285(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285))
-#define AR_SREV_9285_10_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
-#define AR_SREV_9285_11(_ah) \
-	(AR_SREV_9285(ah) && \
-	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11))
-#define AR_SREV_9285_11_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
-	 (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
-			       AR_SREV_REVISION_9285_11)))
-#define AR_SREV_9285_12(_ah) \
-	(AR_SREV_9285(ah) && \
-	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12))
 #define AR_SREV_9285_12_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
-	 (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
-			       AR_SREV_REVISION_9285_12)))
+	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
 
 #define AR_SREV_9287(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287))
-#define AR_SREV_9287_10_OR_LATER(_ah) \
+#define AR_SREV_9287_11_OR_LATER(_ah) \
 	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287))
-#define AR_SREV_9287_10(_ah) \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
-	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_10))
 #define AR_SREV_9287_11(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11))
-#define AR_SREV_9287_11_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
-	 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
-	  ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11)))
 #define AR_SREV_9287_12(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12))
@@ -885,9 +853,6 @@
 
 #define AR_SREV_9300(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
-#define AR_SREV_9300_20(_ah) \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \
-	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9300_20))
 #define AR_SREV_9300_20_OR_LATER(_ah) \
 	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \
 	 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \
@@ -1550,11 +1515,6 @@
 #define AR_TPC_CHIRP           0x003f0000
 #define AR_TPC_CHIRP_S         0x16
 
-#define AR_TFCNT           0x80ec
-#define AR_RFCNT           0x80f0
-#define AR_RCCNT           0x80f4
-#define AR_CCCNT           0x80f8
-
 #define AR_QUIET1          0x80fc
 #define AR_QUIET1_NEXT_QUIET_S         0
 #define AR_QUIET1_NEXT_QUIET_M         0x0000ffff
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index fd20241..ec7cf5e 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -19,45 +19,36 @@
 #include "ath9k.h"
 
 struct ath9k_vif_iter_data {
-	int count;
-	u8 *addr;
+	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;
-	u8 *nbuf;
+	int i;
 
-	nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN,
-			GFP_ATOMIC);
-	if (nbuf == NULL)
-		return;
-
-	memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN);
-	iter_data->addr = nbuf;
-	iter_data->count++;
+	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)
+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, j;
-	u8 mask[ETH_ALEN];
+	int i;
 
 	/*
-	 * Add primary MAC address even if it is not in active use since it
-	 * will be configured to the hardware as the starting point and the
-	 * BSSID mask will need to be changed if another address is active.
+	 * Use the hardware MAC address as reference, the hardware uses it
+	 * together with the BSSID mask when matching addresses.
 	 */
-	iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC);
-	if (iter_data.addr) {
-		memcpy(iter_data.addr, common->macaddr, ETH_ALEN);
-		iter_data.count = 1;
-	} else
-		iter_data.count = 0;
+	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);
@@ -71,31 +62,7 @@
 	}
 	spin_unlock_bh(&sc->wiphy_lock);
 
-	/* Generate an address mask to cover all active addresses */
-	memset(mask, 0, ETH_ALEN);
-	for (i = 0; i < iter_data.count; i++) {
-		u8 *a1 = iter_data.addr + i * ETH_ALEN;
-		for (j = i + 1; j < iter_data.count; j++) {
-			u8 *a2 = iter_data.addr + j * ETH_ALEN;
-			mask[0] |= a1[0] ^ a2[0];
-			mask[1] |= a1[1] ^ a2[1];
-			mask[2] |= a1[2] ^ a2[2];
-			mask[3] |= a1[3] ^ a2[3];
-			mask[4] |= a1[4] ^ a2[4];
-			mask[5] |= a1[5] ^ a2[5];
-		}
-	}
-
-	kfree(iter_data.addr);
-
-	/* Invert the mask and configure hardware */
-	common->bssidmask[0] = ~mask[0];
-	common->bssidmask[1] = ~mask[1];
-	common->bssidmask[2] = ~mask[2];
-	common->bssidmask[3] = ~mask[3];
-	common->bssidmask[4] = ~mask[4];
-	common->bssidmask[5] = ~mask[5];
-
+	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
 	ath_hw_setbssidmask(common);
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 6260faa..93a8bda 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -85,6 +85,8 @@
 		return "WMI_TGT_DETACH_CMDID";
 	case WMI_TGT_TXQ_ENABLE_CMDID:
 		return "WMI_TGT_TXQ_ENABLE_CMDID";
+	case WMI_AGGR_LIMIT_CMD:
+		return "WMI_AGGR_LIMIT_CMD";
 	}
 
 	return "Bogus";
@@ -122,55 +124,11 @@
 {
 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
 	struct ath_common *common = ath9k_hw_common(priv->ah);
-	struct wmi_cmd_hdr *hdr;
-	struct wmi_swba *swba_hdr;
-	enum wmi_event_id event;
-	struct sk_buff *skb;
-	void *wmi_event;
-	unsigned long flags;
-#ifdef CONFIG_ATH9K_HTC_DEBUGFS
-	__be32 txrate;
-#endif
 
-	spin_lock_irqsave(&priv->wmi->wmi_lock, flags);
-	skb = priv->wmi->wmi_skb;
-	spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
+	ath_print(common, ATH_DBG_WMI, "SWBA Event received\n");
 
-	hdr = (struct wmi_cmd_hdr *) skb->data;
-	event = be16_to_cpu(hdr->command_id);
-	wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
+	ath9k_htc_swba(priv, priv->wmi->beacon_pending);
 
-	ath_print(common, ATH_DBG_WMI,
-		  "WMI Event: 0x%x\n", event);
-
-	switch (event) {
-	case WMI_TGT_RDY_EVENTID:
-		break;
-	case WMI_SWBA_EVENTID:
-		swba_hdr = (struct wmi_swba *) wmi_event;
-		ath9k_htc_swba(priv, swba_hdr->beacon_pending);
-		break;
-	case WMI_FATAL_EVENTID:
-		break;
-	case WMI_TXTO_EVENTID:
-		break;
-	case WMI_BMISS_EVENTID:
-		break;
-	case WMI_WLAN_TXCOMP_EVENTID:
-		break;
-	case WMI_DELBA_EVENTID:
-		break;
-	case WMI_TXRATE_EVENTID:
-#ifdef CONFIG_ATH9K_HTC_DEBUGFS
-		txrate = ((struct wmi_event_txrate *)wmi_event)->txrate;
-		priv->debug.txrate = be32_to_cpu(txrate);
-#endif
-		break;
-	default:
-		break;
-	}
-
-	kfree_skb(skb);
 }
 
 static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb)
@@ -189,6 +147,10 @@
 	struct wmi *wmi = (struct wmi *) priv;
 	struct wmi_cmd_hdr *hdr;
 	u16 cmd_id;
+	void *wmi_event;
+#ifdef CONFIG_ATH9K_HTC_DEBUGFS
+	__be32 txrate;
+#endif
 
 	if (unlikely(wmi->stopped))
 		goto free_skb;
@@ -197,10 +159,22 @@
 	cmd_id = be16_to_cpu(hdr->command_id);
 
 	if (cmd_id & 0x1000) {
-		spin_lock(&wmi->wmi_lock);
-		wmi->wmi_skb = skb;
-		spin_unlock(&wmi->wmi_lock);
-		tasklet_schedule(&wmi->drv_priv->wmi_tasklet);
+		wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
+		switch (cmd_id) {
+		case WMI_SWBA_EVENTID:
+			wmi->beacon_pending = *(u8 *)wmi_event;
+			tasklet_schedule(&wmi->drv_priv->wmi_tasklet);
+			break;
+		case WMI_TXRATE_EVENTID:
+#ifdef CONFIG_ATH9K_HTC_DEBUGFS
+			txrate = ((struct wmi_event_txrate *)wmi_event)->txrate;
+			wmi->drv_priv->debug.txrate = be32_to_cpu(txrate);
+#endif
+			break;
+		default:
+			break;
+		}
+		kfree_skb(skb);
 		return;
 	}
 
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h
index 765db5f..ac61074a 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.h
+++ b/drivers/net/wireless/ath/ath9k/wmi.h
@@ -31,10 +31,6 @@
 	__be16 seq_no;
 } __packed;
 
-struct wmi_swba {
-	u8 beacon_pending;
-} __packed;
-
 enum wmi_cmd_id {
 	WMI_ECHO_CMDID = 0x0001,
 	WMI_ACCESS_MEMORY_CMDID,
@@ -71,6 +67,7 @@
 	WMI_TX_AGGR_ENABLE_CMDID,
 	WMI_TGT_DETACH_CMDID,
 	WMI_TGT_TXQ_ENABLE_CMDID,
+	WMI_AGGR_LIMIT_CMD = 0x0026,
 };
 
 enum wmi_event_id {
@@ -103,7 +100,7 @@
 	u32 cmd_rsp_len;
 	bool stopped;
 
-	struct sk_buff *wmi_skb;
+	u8 beacon_pending;
 	spinlock_t wmi_lock;
 
 	atomic_t mwrite_cnt;
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 4dda14e..d077186 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -61,6 +61,8 @@
 			      struct ath_tx_status *ts, int txok);
 static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
 			     int nbad, int txok, bool update_rc);
+static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+			      int seqno);
 
 enum {
 	MCS_HT20,
@@ -143,18 +145,23 @@
 	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
 	struct ath_buf *bf;
 	struct list_head bf_head;
+	struct ath_tx_status ts;
+
 	INIT_LIST_HEAD(&bf_head);
 
-	WARN_ON(!tid->paused);
-
+	memset(&ts, 0, sizeof(ts));
 	spin_lock_bh(&txq->axq_lock);
-	tid->paused = false;
 
 	while (!list_empty(&tid->buf_q)) {
 		bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
-		BUG_ON(bf_isretried(bf));
 		list_move_tail(&bf->list, &bf_head);
-		ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
+
+		if (bf_isretried(bf)) {
+			ath_tx_update_baw(sc, tid, bf->bf_seqno);
+			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+		} else {
+			ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
+		}
 	}
 
 	spin_unlock_bh(&txq->axq_lock);
@@ -168,9 +175,9 @@
 	index  = ATH_BA_INDEX(tid->seq_start, seqno);
 	cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
 
-	tid->tx_buf[cindex] = NULL;
+	__clear_bit(cindex, tid->tx_buf);
 
-	while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) {
+	while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) {
 		INCR(tid->seq_start, IEEE80211_SEQ_MAX);
 		INCR(tid->baw_head, ATH_TID_MAX_BUFS);
 	}
@@ -186,9 +193,7 @@
 
 	index  = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
 	cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
-
-	BUG_ON(tid->tx_buf[cindex] != NULL);
-	tid->tx_buf[cindex] = bf;
+	__set_bit(cindex, tid->tx_buf);
 
 	if (index >= ((tid->baw_tail - tid->baw_head) &
 		(ATH_TID_MAX_BUFS - 1))) {
@@ -289,7 +294,6 @@
 	tbf->bf_buf_addr = bf->bf_buf_addr;
 	memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
 	tbf->bf_state = bf->bf_state;
-	tbf->bf_dmacontext = bf->bf_dmacontext;
 
 	return tbf;
 }
@@ -312,6 +316,7 @@
 	int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
 	bool rc_update = true;
 	struct ieee80211_tx_rate rates[4];
+	int nframes;
 
 	skb = bf->bf_mpdu;
 	hdr = (struct ieee80211_hdr *)skb->data;
@@ -320,11 +325,11 @@
 	hw = bf->aphy->hw;
 
 	memcpy(rates, tx_info->control.rates, sizeof(rates));
+	nframes = bf->bf_nframes;
 
 	rcu_read_lock();
 
-	/* XXX: use ieee80211_find_sta! */
-	sta = ieee80211_find_sta_by_hw(hw, hdr->addr1);
+	sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
 	if (!sta) {
 		rcu_read_unlock();
 
@@ -337,7 +342,7 @@
 			    !bf->bf_stale || bf_next != NULL)
 				list_move_tail(&bf->list, &bf_head);
 
-			ath_tx_rc_status(bf, ts, 0, 0, false);
+			ath_tx_rc_status(bf, ts, 1, 0, false);
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
 				0, 0);
 
@@ -431,7 +436,7 @@
 			list_move_tail(&bf->list, &bf_head);
 		}
 
-		if (!txpending) {
+		if (!txpending || (tid->state & AGGR_CLEANUP)) {
 			/*
 			 * complete the acked-ones/xretried ones; update
 			 * block-ack window
@@ -442,6 +447,7 @@
 
 			if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
 				memcpy(tx_info->control.rates, rates, sizeof(rates));
+				bf->bf_nframes = nframes;
 				ath_tx_rc_status(bf, ts, nbad, txok, true);
 				rc_update = false;
 			} else {
@@ -510,15 +516,12 @@
 	}
 
 	if (tid->state & AGGR_CLEANUP) {
+		ath_tx_flush_tid(sc, tid);
+
 		if (tid->baw_head == tid->baw_tail) {
 			tid->state &= ~AGGR_ADDBA_COMPLETE;
 			tid->state &= ~AGGR_CLEANUP;
-
-			/* send buffered frames as singles */
-			ath_tx_flush_tid(sc, tid);
 		}
-		rcu_read_unlock();
-		return;
 	}
 
 	rcu_read_unlock();
@@ -785,17 +788,23 @@
 		 status != ATH_AGGR_BAW_CLOSED);
 }
 
-void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
-		       u16 tid, u16 *ssn)
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+		      u16 tid, u16 *ssn)
 {
 	struct ath_atx_tid *txtid;
 	struct ath_node *an;
 
 	an = (struct ath_node *)sta->drv_priv;
 	txtid = ATH_AN_2_TID(an, tid);
+
+	if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
+		return -EAGAIN;
+
 	txtid->state |= AGGR_ADDBA_PROGRESS;
 	txtid->paused = true;
 	*ssn = txtid->seq_start;
+
+	return 0;
 }
 
 void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
@@ -803,12 +812,6 @@
 	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 	struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
 	struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
-	struct ath_tx_status ts;
-	struct ath_buf *bf;
-	struct list_head bf_head;
-
-	memset(&ts, 0, sizeof(ts));
-	INIT_LIST_HEAD(&bf_head);
 
 	if (txtid->state & AGGR_CLEANUP)
 		return;
@@ -818,31 +821,22 @@
 		return;
 	}
 
-	/* drop all software retried frames and mark this TID */
 	spin_lock_bh(&txq->axq_lock);
 	txtid->paused = true;
-	while (!list_empty(&txtid->buf_q)) {
-		bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
-		if (!bf_isretried(bf)) {
-			/*
-			 * NB: it's based on the assumption that
-			 * software retried frame will always stay
-			 * at the head of software queue.
-			 */
-			break;
-		}
-		list_move_tail(&bf->list, &bf_head);
-		ath_tx_update_baw(sc, txtid, bf->bf_seqno);
-		ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
-	}
+
+	/*
+	 * If frames are still being transmitted for this TID, they will be
+	 * cleaned up during tx completion. To prevent race conditions, this
+	 * TID can only be reused after all in-progress subframes have been
+	 * completed.
+	 */
+	if (txtid->baw_head != txtid->baw_tail)
+		txtid->state |= AGGR_CLEANUP;
+	else
+		txtid->state &= ~AGGR_ADDBA_COMPLETE;
 	spin_unlock_bh(&txq->axq_lock);
 
-	if (txtid->baw_head != txtid->baw_tail) {
-		txtid->state |= AGGR_CLEANUP;
-	} else {
-		txtid->state &= ~AGGR_ADDBA_COMPLETE;
-		ath_tx_flush_tid(sc, txtid);
-	}
+	ath_tx_flush_tid(sc, txtid);
 }
 
 void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
@@ -862,20 +856,6 @@
 	}
 }
 
-bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno)
-{
-	struct ath_atx_tid *txtid;
-
-	if (!(sc->sc_flags & SC_OP_TXAGGR))
-		return false;
-
-	txtid = ATH_AN_2_TID(an, tidno);
-
-	if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS)))
-			return true;
-	return false;
-}
-
 /********************/
 /* Queue Management */
 /********************/
@@ -1407,22 +1387,6 @@
 	return htype;
 }
 
-static int get_hw_crypto_keytype(struct sk_buff *skb)
-{
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-
-	if (tx_info->control.hw_key) {
-		if (tx_info->control.hw_key->alg == ALG_WEP)
-			return ATH9K_KEY_TYPE_WEP;
-		else if (tx_info->control.hw_key->alg == ALG_TKIP)
-			return ATH9K_KEY_TYPE_TKIP;
-		else if (tx_info->control.hw_key->alg == ALG_CCMP)
-			return ATH9K_KEY_TYPE_AES;
-	}
-
-	return ATH9K_KEY_TYPE_CLEAR;
-}
-
 static void assign_aggr_tid_seqno(struct sk_buff *skb,
 				  struct ath_buf *bf)
 {
@@ -1661,7 +1625,7 @@
 		bf->bf_state.bfs_paprd_timestamp = jiffies;
 	bf->bf_flags = setup_tx_flags(skb, use_ldpc);
 
-	bf->bf_keytype = get_hw_crypto_keytype(skb);
+	bf->bf_keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
 	if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) {
 		bf->bf_frmlen += tx_info->control.hw_key->icv_len;
 		bf->bf_keyix = tx_info->control.hw_key->hw_key_idx;
@@ -1675,24 +1639,16 @@
 
 	bf->bf_mpdu = skb;
 
-	bf->bf_dmacontext = dma_map_single(sc->dev, skb->data,
-					   skb->len, DMA_TO_DEVICE);
-	if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) {
+	bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+					 skb->len, DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
 		bf->bf_mpdu = NULL;
+		bf->bf_buf_addr = 0;
 		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
 			  "dma_mapping_error() on TX\n");
 		return -ENOMEM;
 	}
 
-	bf->bf_buf_addr = bf->bf_dmacontext;
-
-	/* tag if this is a nullfunc frame to enable PS when AP acks it */
-	if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) {
-		bf->bf_isnullfunc = true;
-		sc->ps_flags &= ~PS_NULLFUNC_COMPLETED;
-	} else
-		bf->bf_isnullfunc = false;
-
 	bf->bf_tx_aborted = false;
 
 	return 0;
@@ -1956,7 +1912,8 @@
 			tx_flags |= ATH_TX_XRETRY;
 	}
 
-	dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
+	dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
+	bf->bf_buf_addr = 0;
 
 	if (bf->bf_state.bfs_paprd) {
 		if (time_after(jiffies,
@@ -1966,9 +1923,13 @@
 		else
 			complete(&sc->paprd_complete);
 	} else {
-		ath_tx_complete(sc, skb, bf->aphy, tx_flags);
 		ath_debug_stat_tx(sc, txq, bf, ts);
+		ath_tx_complete(sc, skb, bf->aphy, tx_flags);
 	}
+	/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
+	 * accidentally reference it later.
+	 */
+	bf->bf_mpdu = NULL;
 
 	/*
 	 * Return the list of ath_buf of this mpdu to free queue
@@ -2024,9 +1985,15 @@
 
 	if (ts->ts_status & ATH9K_TXERR_FILT)
 		tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
-	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc)
+	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
 		tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
 
+		BUG_ON(nbad > bf->bf_nframes);
+
+		tx_info->status.ampdu_len = bf->bf_nframes;
+		tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
+	}
+
 	if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
 	    (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
 		if (ieee80211_is_data(hdr->frame_control)) {
@@ -2036,8 +2003,6 @@
 			if ((ts->ts_status & ATH9K_TXERR_XRETRY) ||
 			    (ts->ts_status & ATH9K_TXERR_FIFO))
 				tx_info->pad[0] |= ATH_TX_INFO_XRETRY;
-			tx_info->status.ampdu_len = bf->bf_nframes;
-			tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
 		}
 	}
 
@@ -2120,18 +2085,6 @@
 		}
 
 		/*
-		 * We now know the nullfunc frame has been ACKed so we
-		 * can disable RX.
-		 */
-		if (bf->bf_isnullfunc &&
-		    (ts.ts_status & ATH9K_TX_ACKED)) {
-			if ((sc->ps_flags & PS_ENABLED))
-				ath9k_enable_ps(sc);
-			else
-				sc->ps_flags |= PS_NULLFUNC_COMPLETED;
-		}
-
-		/*
 		 * Remove ath_buf's of the same transmit unit from txq,
 		 * however leave the last descriptor back as the holding
 		 * descriptor for hw.
@@ -2159,7 +2112,7 @@
 			 */
 			if (ts.ts_status & ATH9K_TXERR_XRETRY)
 				bf->bf_state.bf_type |= BUF_XRETRY;
-			ath_tx_rc_status(bf, &ts, 0, txok, true);
+			ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
 		}
 
 		if (bf_isampdu(bf))
@@ -2274,21 +2227,10 @@
 
 		txok = !(txs.ts_status & ATH9K_TXERR_MASK);
 
-		/*
-		 * Make sure null func frame is acked before configuring
-		 * hw into ps mode.
-		 */
-		if (bf->bf_isnullfunc && txok) {
-			if ((sc->ps_flags & PS_ENABLED))
-				ath9k_enable_ps(sc);
-			else
-				sc->ps_flags |= PS_NULLFUNC_COMPLETED;
-		}
-
 		if (!bf_isampdu(bf)) {
 			if (txs.ts_status & ATH9K_TXERR_XRETRY)
 				bf->bf_state.bf_type |= BUF_XRETRY;
-			ath_tx_rc_status(bf, &txs, 0, txok, true);
+			ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
 		}
 
 		if (bf_isampdu(bf))
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig
new file mode 100644
index 0000000..2d1b821
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/Kconfig
@@ -0,0 +1,41 @@
+config CARL9170
+	tristate "Linux Community AR9170 802.11n USB support"
+	depends on USB && MAC80211 && EXPERIMENTAL
+	select FW_LOADER
+	select CRC32
+	help
+	  This is another driver for the Atheros "otus" 802.11n USB devices.
+
+	  This driver provides more features than the original,
+	  but it needs a special firmware (carl9170-1.fw) to do that.
+
+	  The firmware can be downloaded from our wiki here:
+	  <http://wireless.kernel.org/en/users/Drivers/carl9170>
+
+	  If you choose to build a module, it'll be called carl9170.
+
+config CARL9170_LEDS
+	bool "SoftLED Support"
+	depends on CARL9170
+	select MAC80211_LEDS
+	select LEDS_CLASS
+	select NEW_LEDS
+	default y
+	help
+	  This option is necessary, if you want your device' LEDs to blink
+
+	  Say Y, unless you need the LEDs for firmware debugging.
+
+config CARL9170_DEBUGFS
+	bool "DebugFS Support"
+	depends on CARL9170 && DEBUG_FS && MAC80211_DEBUGFS
+	default n
+	help
+	  Export several driver and device internals to user space.
+
+	  Say N.
+
+config CARL9170_WPC
+	bool
+	depends on CARL9170 && (INPUT = y || INPUT = CARL9170)
+	default y
diff --git a/drivers/net/wireless/ath/carl9170/Makefile b/drivers/net/wireless/ath/carl9170/Makefile
new file mode 100644
index 0000000..f64ed76
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/Makefile
@@ -0,0 +1,4 @@
+carl9170-objs := main.o usb.o cmd.o mac.o phy.o led.o fw.o tx.o rx.o
+carl9170-$(CONFIG_CARL9170_DEBUGFS) += debug.o
+
+obj-$(CONFIG_CARL9170) += carl9170.o
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
new file mode 100644
index 0000000..6cf0c9e
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -0,0 +1,628 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * Driver specific definitions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __CARL9170_H
+#define __CARL9170_H
+
+#include <linux/kernel.h>
+#include <linux/firmware.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include <linux/usb.h>
+#ifdef CONFIG_CARL9170_LEDS
+#include <linux/leds.h>
+#endif /* CONFIG_CARL170_LEDS */
+#ifdef CONFIG_CARL9170_WPC
+#include <linux/input.h>
+#endif /* CONFIG_CARL9170_WPC */
+#include "eeprom.h"
+#include "wlan.h"
+#include "hw.h"
+#include "fwdesc.h"
+#include "fwcmd.h"
+#include "../regd.h"
+
+#ifdef CONFIG_CARL9170_DEBUGFS
+#include "debug.h"
+#endif /* CONFIG_CARL9170_DEBUGFS */
+
+#define CARL9170FW_NAME	"carl9170-1.fw"
+
+#define PAYLOAD_MAX	(CARL9170_MAX_CMD_LEN / 4 - 1)
+
+enum carl9170_rf_init_mode {
+	CARL9170_RFI_NONE,
+	CARL9170_RFI_WARM,
+	CARL9170_RFI_COLD,
+};
+
+#define CARL9170_MAX_RX_BUFFER_SIZE		8192
+
+enum carl9170_device_state {
+	CARL9170_UNKNOWN_STATE,
+	CARL9170_STOPPED,
+	CARL9170_IDLE,
+	CARL9170_STARTED,
+};
+
+#define CARL9170_NUM_TID		16
+#define WME_BA_BMP_SIZE			64
+#define CARL9170_TX_USER_RATE_TRIES	3
+
+#define WME_AC_BE   2
+#define WME_AC_BK   3
+#define WME_AC_VI   1
+#define WME_AC_VO   0
+
+#define TID_TO_WME_AC(_tid)				\
+	((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE :	\
+	 (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK :	\
+	 (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI :	\
+	 WME_AC_VO)
+
+#define SEQ_DIFF(_start, _seq) \
+	(((_start) - (_seq)) & 0x0fff)
+#define SEQ_PREV(_seq) \
+	(((_seq) - 1) & 0x0fff)
+#define SEQ_NEXT(_seq) \
+	(((_seq) + 1) & 0x0fff)
+#define BAW_WITHIN(_start, _bawsz, _seqno) \
+	((((_seqno) - (_start)) & 0xfff) < (_bawsz))
+
+enum carl9170_tid_state {
+	CARL9170_TID_STATE_INVALID,
+	CARL9170_TID_STATE_KILLED,
+	CARL9170_TID_STATE_SHUTDOWN,
+	CARL9170_TID_STATE_SUSPEND,
+	CARL9170_TID_STATE_PROGRESS,
+	CARL9170_TID_STATE_IDLE,
+	CARL9170_TID_STATE_XMIT,
+};
+
+#define CARL9170_BAW_BITS (2 * WME_BA_BMP_SIZE)
+#define CARL9170_BAW_SIZE (BITS_TO_LONGS(CARL9170_BAW_BITS))
+#define CARL9170_BAW_LEN (DIV_ROUND_UP(CARL9170_BAW_BITS, BITS_PER_BYTE))
+
+struct carl9170_sta_tid {
+	/* must be the first entry! */
+	struct list_head list;
+
+	/* temporary list for RCU unlink procedure */
+	struct list_head tmp_list;
+
+	/* lock for the following data structures */
+	spinlock_t lock;
+
+	unsigned int counter;
+	enum carl9170_tid_state state;
+	u8 tid;		/* TID number ( 0 - 15 ) */
+	u16 max;	/* max. AMPDU size */
+
+	u16 snx;	/* awaiting _next_ frame */
+	u16 hsn;	/* highest _queued_ sequence */
+	u16 bsn;	/* base of the tx/agg bitmap */
+	unsigned long bitmap[CARL9170_BAW_SIZE];
+
+	/* Preaggregation reorder queue */
+	struct sk_buff_head queue;
+};
+
+#define CARL9170_QUEUE_TIMEOUT		256
+#define CARL9170_BUMP_QUEUE		1000
+#define CARL9170_TX_TIMEOUT		2500
+#define CARL9170_JANITOR_DELAY		128
+#define CARL9170_QUEUE_STUCK_TIMEOUT	5500
+
+#define CARL9170_NUM_TX_AGG_MAX		30
+
+/*
+ * Tradeoff between stability/latency and speed.
+ *
+ * AR9170_TXQ_DEPTH is devised by dividing the amount of available
+ * tx buffers with the size of a full ethernet frame + overhead.
+ *
+ * Naturally: The higher the limit, the faster the device CAN send.
+ * However, even a slight over-commitment at the wrong time and the
+ * hardware is doomed to send all already-queued frames at suboptimal
+ * rates. This in turn leads to an enourmous amount of unsuccessful
+ * retries => Latency goes up, whereas the throughput goes down. CRASH!
+ */
+#define CARL9170_NUM_TX_LIMIT_HARD	((AR9170_TXQ_DEPTH * 3) / 2)
+#define CARL9170_NUM_TX_LIMIT_SOFT	(AR9170_TXQ_DEPTH)
+
+struct carl9170_tx_queue_stats {
+	unsigned int count;
+	unsigned int limit;
+	unsigned int len;
+};
+
+struct carl9170_vif {
+	unsigned int id;
+	struct ieee80211_vif *vif;
+};
+
+struct carl9170_vif_info {
+	struct list_head list;
+	bool active;
+	unsigned int id;
+	struct sk_buff *beacon;
+	bool enable_beacon;
+};
+
+#define AR9170_NUM_RX_URBS	16
+#define AR9170_NUM_RX_URBS_MUL	2
+#define AR9170_NUM_TX_URBS	8
+#define AR9170_NUM_RX_URBS_POOL (AR9170_NUM_RX_URBS_MUL * AR9170_NUM_RX_URBS)
+
+enum carl9170_device_features {
+	CARL9170_WPS_BUTTON		= BIT(0),
+	CARL9170_ONE_LED		= BIT(1),
+};
+
+#ifdef CONFIG_CARL9170_LEDS
+struct ar9170;
+
+struct carl9170_led {
+	struct ar9170 *ar;
+	struct led_classdev l;
+	char name[32];
+	unsigned int toggled;
+	bool last_state;
+	bool registered;
+};
+#endif /* CONFIG_CARL9170_LEDS */
+
+enum carl9170_restart_reasons {
+	CARL9170_RR_NO_REASON = 0,
+	CARL9170_RR_FATAL_FIRMWARE_ERROR,
+	CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
+	CARL9170_RR_WATCHDOG,
+	CARL9170_RR_STUCK_TX,
+	CARL9170_RR_SLOW_SYSTEM,
+	CARL9170_RR_COMMAND_TIMEOUT,
+	CARL9170_RR_TOO_MANY_PHY_ERRORS,
+	CARL9170_RR_LOST_RSP,
+	CARL9170_RR_INVALID_RSP,
+	CARL9170_RR_USER_REQUEST,
+
+	__CARL9170_RR_LAST,
+};
+
+enum carl9170_erp_modes {
+	CARL9170_ERP_INVALID,
+	CARL9170_ERP_AUTO,
+	CARL9170_ERP_MAC80211,
+	CARL9170_ERP_OFF,
+	CARL9170_ERP_CTS,
+	CARL9170_ERP_RTS,
+	__CARL9170_ERP_NUM,
+};
+
+struct ar9170 {
+	struct ath_common common;
+	struct ieee80211_hw *hw;
+	struct mutex mutex;
+	enum carl9170_device_state state;
+	spinlock_t state_lock;
+	enum carl9170_restart_reasons last_reason;
+	bool registered;
+
+	/* USB */
+	struct usb_device *udev;
+	struct usb_interface *intf;
+	struct usb_anchor rx_anch;
+	struct usb_anchor rx_work;
+	struct usb_anchor rx_pool;
+	struct usb_anchor tx_wait;
+	struct usb_anchor tx_anch;
+	struct usb_anchor tx_cmd;
+	struct usb_anchor tx_err;
+	struct tasklet_struct usb_tasklet;
+	atomic_t tx_cmd_urbs;
+	atomic_t tx_anch_urbs;
+	atomic_t rx_anch_urbs;
+	atomic_t rx_work_urbs;
+	atomic_t rx_pool_urbs;
+	kernel_ulong_t features;
+
+	/* firmware settings */
+	struct completion fw_load_wait;
+	struct completion fw_boot_wait;
+	struct {
+		const struct carl9170fw_desc_head *desc;
+		const struct firmware *fw;
+		unsigned int offset;
+		unsigned int address;
+		unsigned int cmd_bufs;
+		unsigned int api_version;
+		unsigned int vif_num;
+		unsigned int err_counter;
+		unsigned int bug_counter;
+		u32 beacon_addr;
+		unsigned int beacon_max_len;
+		bool rx_stream;
+		bool tx_stream;
+		bool rx_filter;
+		unsigned int mem_blocks;
+		unsigned int mem_block_size;
+		unsigned int rx_size;
+	} fw;
+
+	/* reset / stuck frames/queue detection */
+	struct work_struct restart_work;
+	unsigned int restart_counter;
+	unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
+	unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
+	bool needs_full_reset;
+	atomic_t pending_restarts;
+
+	/* interface mode settings */
+	struct list_head vif_list;
+	unsigned long vif_bitmap;
+	unsigned int vifs;
+	struct carl9170_vif vif_priv[AR9170_MAX_VIRTUAL_MAC];
+
+	/* beaconing */
+	spinlock_t beacon_lock;
+	unsigned int global_pretbtt;
+	unsigned int global_beacon_int;
+	struct carl9170_vif_info *beacon_iter;
+	unsigned int beacon_enabled;
+
+	/* cryptographic engine */
+	u64 usedkeys;
+	bool rx_software_decryption;
+	bool disable_offload;
+
+	/* filter settings */
+	u64 cur_mc_hash;
+	u32 cur_filter;
+	unsigned int filter_state;
+	unsigned int rx_filter_caps;
+	bool sniffer_enabled;
+
+	/* MAC */
+	enum carl9170_erp_modes erp_mode;
+
+	/* PHY */
+	struct ieee80211_channel *channel;
+	int noise[4];
+	unsigned int chan_fail;
+	unsigned int total_chan_fail;
+	u8 heavy_clip;
+	u8 ht_settings;
+
+	/* power calibration data */
+	u8 power_5G_leg[4];
+	u8 power_2G_cck[4];
+	u8 power_2G_ofdm[4];
+	u8 power_5G_ht20[8];
+	u8 power_5G_ht40[8];
+	u8 power_2G_ht20[8];
+	u8 power_2G_ht40[8];
+
+#ifdef CONFIG_CARL9170_LEDS
+	/* LED */
+	struct delayed_work led_work;
+	struct carl9170_led leds[AR9170_NUM_LEDS];
+#endif /* CONFIG_CARL9170_LEDS */
+
+	/* qos queue settings */
+	spinlock_t tx_stats_lock;
+	struct carl9170_tx_queue_stats tx_stats[__AR9170_NUM_TXQ];
+	struct ieee80211_tx_queue_params edcf[5];
+	struct completion tx_flush;
+
+	/* CMD */
+	int cmd_seq;
+	int readlen;
+	u8 *readbuf;
+	spinlock_t cmd_lock;
+	struct completion cmd_wait;
+	union {
+		__le32 cmd_buf[PAYLOAD_MAX + 1];
+		struct carl9170_cmd cmd;
+		struct carl9170_rsp rsp;
+	};
+
+	/* statistics */
+	unsigned int tx_dropped;
+	unsigned int tx_ack_failures;
+	unsigned int tx_fcs_errors;
+	unsigned int rx_dropped;
+
+	/* EEPROM */
+	struct ar9170_eeprom eeprom;
+
+	/* tx queuing */
+	struct sk_buff_head tx_pending[__AR9170_NUM_TXQ];
+	struct sk_buff_head tx_status[__AR9170_NUM_TXQ];
+	struct delayed_work tx_janitor;
+	unsigned long tx_janitor_last_run;
+	bool tx_schedule;
+
+	/* tx ampdu */
+	struct work_struct ampdu_work;
+	spinlock_t tx_ampdu_list_lock;
+	struct carl9170_sta_tid *tx_ampdu_iter;
+	struct list_head tx_ampdu_list;
+	atomic_t tx_ampdu_upload;
+	atomic_t tx_ampdu_scheduler;
+	atomic_t tx_total_pending;
+	atomic_t tx_total_queued;
+	unsigned int tx_ampdu_list_len;
+	int current_density;
+	int current_factor;
+	bool tx_ampdu_schedule;
+
+	/* internal memory management */
+	spinlock_t mem_lock;
+	unsigned long *mem_bitmap;
+	atomic_t mem_free_blocks;
+	atomic_t mem_allocs;
+
+	/* rxstream mpdu merge */
+	struct ar9170_rx_head rx_plcp;
+	bool rx_has_plcp;
+	struct sk_buff *rx_failover;
+	int rx_failover_missing;
+
+#ifdef CONFIG_CARL9170_WPC
+	struct {
+		bool pbc_state;
+		struct input_dev *pbc;
+		char name[32];
+		char phys[32];
+	} wps;
+#endif /* CONFIG_CARL9170_WPC */
+
+#ifdef CONFIG_CARL9170_DEBUGFS
+	struct carl9170_debug debug;
+	struct dentry *debug_dir;
+#endif /* CONFIG_CARL9170_DEBUGFS */
+
+	/* PSM */
+	struct work_struct ps_work;
+	struct {
+		unsigned int dtim_counter;
+		unsigned long last_beacon;
+		unsigned long last_action;
+		unsigned long last_slept;
+		unsigned int sleep_ms;
+		unsigned int off_override;
+		bool state;
+	} ps;
+};
+
+enum carl9170_ps_off_override_reasons {
+	PS_OFF_VIF	= BIT(0),
+	PS_OFF_BCN	= BIT(1),
+	PS_OFF_5GHZ	= BIT(2),
+};
+
+struct carl9170_ba_stats {
+	u8 ampdu_len;
+	u8 ampdu_ack_len;
+	bool clear;
+};
+
+struct carl9170_sta_info {
+	bool ht_sta;
+	unsigned int ampdu_max_len;
+	struct carl9170_sta_tid *agg[CARL9170_NUM_TID];
+	struct carl9170_ba_stats stats[CARL9170_NUM_TID];
+};
+
+struct carl9170_tx_info {
+	unsigned long timeout;
+	struct ar9170 *ar;
+	struct kref ref;
+};
+
+#define CHK_DEV_STATE(a, s)	(((struct ar9170 *)a)->state >= (s))
+#define IS_INITIALIZED(a)	(CHK_DEV_STATE(a, CARL9170_STOPPED))
+#define IS_ACCEPTING_CMD(a)	(CHK_DEV_STATE(a, CARL9170_IDLE))
+#define IS_STARTED(a)		(CHK_DEV_STATE(a, CARL9170_STARTED))
+
+static inline void __carl9170_set_state(struct ar9170 *ar,
+	enum carl9170_device_state newstate)
+{
+	ar->state = newstate;
+}
+
+static inline void carl9170_set_state(struct ar9170 *ar,
+	enum carl9170_device_state newstate)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ar->state_lock, flags);
+	__carl9170_set_state(ar, newstate);
+	spin_unlock_irqrestore(&ar->state_lock, flags);
+}
+
+static inline void carl9170_set_state_when(struct ar9170 *ar,
+	enum carl9170_device_state min, enum carl9170_device_state newstate)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ar->state_lock, flags);
+	if (CHK_DEV_STATE(ar, min))
+		__carl9170_set_state(ar, newstate);
+	spin_unlock_irqrestore(&ar->state_lock, flags);
+}
+
+/* exported interface */
+void *carl9170_alloc(size_t priv_size);
+int carl9170_register(struct ar9170 *ar);
+void carl9170_unregister(struct ar9170 *ar);
+void carl9170_free(struct ar9170 *ar);
+void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r);
+void carl9170_ps_check(struct ar9170 *ar);
+
+/* USB back-end */
+int carl9170_usb_open(struct ar9170 *ar);
+void carl9170_usb_stop(struct ar9170 *ar);
+void carl9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb);
+void carl9170_usb_handle_tx_err(struct ar9170 *ar);
+int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids,
+		      u32 plen, void *payload, u32 rlen, void *resp);
+int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd,
+			const bool free_buf);
+int carl9170_usb_restart(struct ar9170 *ar);
+void carl9170_usb_reset(struct ar9170 *ar);
+
+/* MAC */
+int carl9170_init_mac(struct ar9170 *ar);
+int carl9170_set_qos(struct ar9170 *ar);
+int carl9170_update_multicast(struct ar9170 *ar, const u64 mc_hast);
+int carl9170_mod_virtual_mac(struct ar9170 *ar, const unsigned int id,
+			     const u8 *mac);
+int carl9170_set_operating_mode(struct ar9170 *ar);
+int carl9170_set_beacon_timers(struct ar9170 *ar);
+int carl9170_set_dyn_sifs_ack(struct ar9170 *ar);
+int carl9170_set_rts_cts_rate(struct ar9170 *ar);
+int carl9170_set_ampdu_settings(struct ar9170 *ar);
+int carl9170_set_slot_time(struct ar9170 *ar);
+int carl9170_set_mac_rates(struct ar9170 *ar);
+int carl9170_set_hwretry_limit(struct ar9170 *ar, const u32 max_retry);
+int carl9170_update_beacon(struct ar9170 *ar, const bool submit);
+int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
+	const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen);
+int carl9170_disable_key(struct ar9170 *ar, const u8 id);
+
+/* RX */
+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_tx_janitor(struct work_struct *work);
+void carl9170_tx_process_status(struct ar9170 *ar,
+				const struct carl9170_rsp *cmd);
+void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
+			const bool success);
+void carl9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb);
+void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb);
+void carl9170_tx_scheduler(struct ar9170 *ar);
+void carl9170_tx_get_skb(struct sk_buff *skb);
+int carl9170_tx_put_skb(struct sk_buff *skb);
+
+/* LEDs */
+#ifdef CONFIG_CARL9170_LEDS
+int carl9170_led_register(struct ar9170 *ar);
+void carl9170_led_unregister(struct ar9170 *ar);
+#endif /* CONFIG_CARL9170_LEDS */
+int carl9170_led_init(struct ar9170 *ar);
+int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state);
+
+/* PHY / RF */
+int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
+	enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi);
+int carl9170_get_noisefloor(struct ar9170 *ar);
+
+/* FW */
+int carl9170_parse_firmware(struct ar9170 *ar);
+int carl9170_fw_fix_eeprom(struct ar9170 *ar);
+
+extern struct ieee80211_rate __carl9170_ratetable[];
+extern int modparam_noht;
+
+static inline struct ar9170 *carl9170_get_priv(struct carl9170_vif *carl_vif)
+{
+	return container_of(carl_vif, struct ar9170,
+			    vif_priv[carl_vif->id]);
+}
+
+static inline struct ieee80211_hdr *carl9170_get_hdr(struct sk_buff *skb)
+{
+	return (void *)((struct _carl9170_tx_superframe *)
+		skb->data)->frame_data;
+}
+
+static inline u16 get_seq_h(struct ieee80211_hdr *hdr)
+{
+	return le16_to_cpu(hdr->seq_ctrl) >> 4;
+}
+
+static inline u16 carl9170_get_seq(struct sk_buff *skb)
+{
+	return get_seq_h(carl9170_get_hdr(skb));
+}
+
+static inline u16 get_tid_h(struct ieee80211_hdr *hdr)
+{
+	return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK;
+}
+
+static inline u16 carl9170_get_tid(struct sk_buff *skb)
+{
+	return get_tid_h(carl9170_get_hdr(skb));
+}
+
+static inline struct ieee80211_vif *
+carl9170_get_vif(struct carl9170_vif_info *priv)
+{
+	return container_of((void *)priv, struct ieee80211_vif, drv_priv);
+}
+
+/* Protected by ar->mutex or RCU */
+static inline struct ieee80211_vif *carl9170_get_main_vif(struct ar9170 *ar)
+{
+	struct carl9170_vif_info *cvif;
+
+	list_for_each_entry_rcu(cvif, &ar->vif_list, list) {
+		if (cvif->active)
+			return carl9170_get_vif(cvif);
+	}
+
+	return NULL;
+}
+
+static inline bool is_main_vif(struct ar9170 *ar, struct ieee80211_vif *vif)
+{
+	bool ret;
+
+	rcu_read_lock();
+	ret = (carl9170_get_main_vif(ar) == vif);
+	rcu_read_unlock();
+	return ret;
+}
+
+#endif /* __CARL9170_H */
diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c
new file mode 100644
index 0000000..c21f336
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/cmd.c
@@ -0,0 +1,188 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * Basic HW register/memory/command access functions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 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 "carl9170.h"
+#include "cmd.h"
+
+int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
+{
+	__le32 buf[2] = {
+		cpu_to_le32(reg),
+		cpu_to_le32(val),
+	};
+	int err;
+
+	err = carl9170_exec_cmd(ar, CARL9170_CMD_WREG, sizeof(buf),
+				(u8 *) buf, 0, NULL);
+	if (err) {
+		if (net_ratelimit()) {
+			wiphy_err(ar->hw->wiphy, "writing reg %#x "
+				"(val %#x) failed (%d)\n", reg, val, err);
+		}
+	}
+	return err;
+}
+
+int carl9170_read_mreg(struct ar9170 *ar, const int nregs,
+		       const u32 *regs, u32 *out)
+{
+	int i, err;
+	__le32 *offs, *res;
+
+	/* abuse "out" for the register offsets, must be same length */
+	offs = (__le32 *)out;
+	for (i = 0; i < nregs; i++)
+		offs[i] = cpu_to_le32(regs[i]);
+
+	/* also use the same buffer for the input */
+	res = (__le32 *)out;
+
+	err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,
+				4 * nregs, (u8 *)offs,
+				4 * nregs, (u8 *)res);
+	if (err) {
+		if (net_ratelimit()) {
+			wiphy_err(ar->hw->wiphy, "reading regs failed (%d)\n",
+				  err);
+		}
+		return err;
+	}
+
+	/* convert result to cpu endian */
+	for (i = 0; i < nregs; i++)
+		out[i] = le32_to_cpu(res[i]);
+
+	return 0;
+}
+
+int carl9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val)
+{
+	return carl9170_read_mreg(ar, 1, &reg, val);
+}
+
+int carl9170_echo_test(struct ar9170 *ar, const u32 v)
+{
+	u32 echores;
+	int err;
+
+	err = carl9170_exec_cmd(ar, CARL9170_CMD_ECHO,
+				4, (u8 *)&v,
+				4, (u8 *)&echores);
+	if (err)
+		return err;
+
+	if (v != echores) {
+		wiphy_info(ar->hw->wiphy, "wrong echo %x != %x", v, echores);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar,
+	const enum carl9170_cmd_oids cmd, const unsigned int len)
+{
+	struct carl9170_cmd *tmp;
+
+	tmp = kzalloc(sizeof(struct carl9170_cmd_head) + len, GFP_ATOMIC);
+	if (tmp) {
+		tmp->hdr.cmd = cmd;
+		tmp->hdr.len = len;
+	}
+
+	return tmp;
+}
+
+int carl9170_reboot(struct ar9170 *ar)
+{
+	struct carl9170_cmd *cmd;
+	int err;
+
+	cmd = carl9170_cmd_buf(ar, CARL9170_CMD_REBOOT_ASYNC, 0);
+	if (!cmd)
+		return -ENOMEM;
+
+	err = __carl9170_exec_cmd(ar, (struct carl9170_cmd *)cmd, true);
+	return err;
+}
+
+int carl9170_mac_reset(struct ar9170 *ar)
+{
+	return carl9170_exec_cmd(ar, CARL9170_CMD_SWRST,
+				 0, NULL, 0, NULL);
+}
+
+int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
+		       const u32 mode, const u32 addr, const u32 len)
+{
+	struct carl9170_cmd *cmd;
+
+	cmd = carl9170_cmd_buf(ar, CARL9170_CMD_BCN_CTRL_ASYNC,
+			       sizeof(struct carl9170_bcn_ctrl_cmd));
+	if (!cmd)
+		return -ENOMEM;
+
+	cmd->bcn_ctrl.vif_id = cpu_to_le32(vif_id);
+	cmd->bcn_ctrl.mode = cpu_to_le32(mode);
+	cmd->bcn_ctrl.bcn_addr = cpu_to_le32(addr);
+	cmd->bcn_ctrl.bcn_len = cpu_to_le32(len);
+
+	return __carl9170_exec_cmd(ar, cmd, true);
+}
+
+int carl9170_powersave(struct ar9170 *ar, const bool ps)
+{
+	struct carl9170_cmd *cmd;
+	u32 state;
+
+	cmd = carl9170_cmd_buf(ar, CARL9170_CMD_PSM_ASYNC,
+			       sizeof(struct carl9170_psm));
+	if (!cmd)
+		return -ENOMEM;
+
+	if (ps) {
+		/* Sleep until next TBTT */
+		state = CARL9170_PSM_SLEEP | 1;
+	} else {
+		/* wake up immediately */
+		state = 1;
+	}
+
+	cmd->psm.state = cpu_to_le32(state);
+	return __carl9170_exec_cmd(ar, cmd, true);
+}
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h
new file mode 100644
index 0000000..f78728c
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/cmd.h
@@ -0,0 +1,168 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * Basic HW register/memory/command access functions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __CMD_H
+#define __CMD_H
+
+#include "carl9170.h"
+
+/* basic HW access */
+int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val);
+int carl9170_read_reg(struct ar9170 *ar, const u32 reg, u32 *val);
+int carl9170_read_mreg(struct ar9170 *ar, const int nregs,
+		       const u32 *regs, u32 *out);
+int carl9170_echo_test(struct ar9170 *ar, u32 v);
+int carl9170_reboot(struct ar9170 *ar);
+int carl9170_mac_reset(struct ar9170 *ar);
+int carl9170_powersave(struct ar9170 *ar, const bool power_on);
+int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
+		       const u32 mode, const u32 addr, const u32 len);
+
+static inline int carl9170_flush_cab(struct ar9170 *ar,
+				     const unsigned int vif_id)
+{
+	return carl9170_bcn_ctrl(ar, vif_id, CARL9170_BCN_CTRL_DRAIN, 0, 0);
+}
+
+static inline int carl9170_rx_filter(struct ar9170 *ar,
+				     const unsigned int _rx_filter)
+{
+	__le32 rx_filter = cpu_to_le32(_rx_filter);
+
+	return carl9170_exec_cmd(ar, CARL9170_CMD_RX_FILTER,
+				sizeof(rx_filter), (u8 *)&rx_filter,
+				0, NULL);
+}
+
+struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar,
+	const enum carl9170_cmd_oids cmd, const unsigned int len);
+
+/*
+ * Macros to facilitate writing multiple registers in a single
+ * write-combining USB command. Note that when the first group
+ * fails the whole thing will fail without any others attempted,
+ * but you won't know which write in the group failed.
+ */
+#define carl9170_regwrite_begin(ar)					\
+do {									\
+	int __nreg = 0, __err = 0;					\
+	struct ar9170 *__ar = ar;
+
+#define carl9170_regwrite(r, v) do {					\
+	__ar->cmd_buf[2 * __nreg + 1] = cpu_to_le32(r);			\
+	__ar->cmd_buf[2 * __nreg + 2] = cpu_to_le32(v);			\
+	__nreg++;							\
+	if ((__nreg >= PAYLOAD_MAX/2)) {				\
+		if (IS_ACCEPTING_CMD(__ar))				\
+			__err = carl9170_exec_cmd(__ar,			\
+				CARL9170_CMD_WREG, 8 * __nreg,		\
+				(u8 *) &__ar->cmd_buf[1], 0, NULL);	\
+		else							\
+			goto __regwrite_out;				\
+									\
+		__nreg = 0;						\
+		if (__err)						\
+			goto __regwrite_out;				\
+	}								\
+} while (0)
+
+#define carl9170_regwrite_finish()					\
+__regwrite_out :							\
+	if (__err == 0 && __nreg) {					\
+		if (IS_ACCEPTING_CMD(__ar))				\
+			__err = carl9170_exec_cmd(__ar,			\
+				CARL9170_CMD_WREG, 8 * __nreg,		\
+				(u8 *) &__ar->cmd_buf[1], 0, NULL);	\
+		__nreg = 0;						\
+	}
+
+#define carl9170_regwrite_result()					\
+	__err;								\
+} while (0);
+
+
+#define carl9170_async_get_buf()					\
+do {									\
+	__cmd = carl9170_cmd_buf(__carl, CARL9170_CMD_WREG_ASYNC,	\
+				 CARL9170_MAX_CMD_PAYLOAD_LEN);		\
+	if (__cmd == NULL) {						\
+		__err = -ENOMEM;					\
+		goto __async_regwrite_out;				\
+	}								\
+} while (0);
+
+#define carl9170_async_regwrite_begin(carl)				\
+do {									\
+	int __nreg = 0, __err = 0;					\
+	struct ar9170 *__carl = carl;					\
+	struct carl9170_cmd *__cmd;					\
+	carl9170_async_get_buf();					\
+
+#define carl9170_async_regwrite(r, v) do {				\
+	__cmd->wreg.regs[__nreg].addr = cpu_to_le32(r);			\
+	__cmd->wreg.regs[__nreg].val = cpu_to_le32(v);			\
+	__nreg++;							\
+	if ((__nreg >= PAYLOAD_MAX/2)) {				\
+		if (IS_ACCEPTING_CMD(__carl)) {				\
+			__cmd->hdr.len = 8 * __nreg;			\
+			__err = __carl9170_exec_cmd(__carl, __cmd, true);\
+			__cmd = NULL;					\
+			carl9170_async_get_buf();			\
+		} else {						\
+			goto __async_regwrite_out;			\
+		}							\
+		__nreg = 0;						\
+		if (__err)						\
+			goto __async_regwrite_out;			\
+	}								\
+} while (0)
+
+#define carl9170_async_regwrite_finish()				\
+__async_regwrite_out :							\
+	if (__err == 0 && __nreg) {					\
+		__cmd->hdr.len = 8 * __nreg;				\
+		if (IS_ACCEPTING_CMD(__carl))				\
+			__err = __carl9170_exec_cmd(__carl, __cmd, true);\
+		__nreg = 0;						\
+	}
+
+#define carl9170_async_regwrite_result()				\
+	__err;								\
+} while (0);
+
+#endif /* __CMD_H */
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
new file mode 100644
index 0000000..0ac1124
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -0,0 +1,902 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * debug(fs) probing
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    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/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
+#include "carl9170.h"
+#include "cmd.h"
+
+#define ADD(buf, off, max, fmt, args...)				\
+	off += snprintf(&buf[off], max - off, fmt, ##args);
+
+static int carl9170_debugfs_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+struct carl9170_debugfs_fops {
+	unsigned int read_bufsize;
+	mode_t attr;
+	char *(*read)(struct ar9170 *ar, char *buf, size_t bufsize,
+		      ssize_t *len);
+	ssize_t (*write)(struct ar9170 *aru, const char *buf, size_t size);
+	const struct file_operations fops;
+
+	enum carl9170_device_state req_dev_state;
+};
+
+static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf,
+				     size_t count, loff_t *ppos)
+{
+	struct carl9170_debugfs_fops *dfops;
+	struct ar9170 *ar;
+	char *buf = NULL, *res_buf = NULL;
+	ssize_t ret = 0;
+	int err = 0;
+
+	if (!count)
+		return 0;
+
+	ar = file->private_data;
+
+	if (!ar)
+		return -ENODEV;
+	dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops);
+
+	if (!dfops->read)
+		return -ENOSYS;
+
+	if (dfops->read_bufsize) {
+		buf = vmalloc(dfops->read_bufsize);
+		if (!buf)
+			return -ENOMEM;
+	}
+
+	mutex_lock(&ar->mutex);
+	if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) {
+		err = -ENODEV;
+		res_buf = buf;
+		goto out_free;
+	}
+
+	res_buf = dfops->read(ar, buf, dfops->read_bufsize, &ret);
+
+	if (ret > 0)
+		err = simple_read_from_buffer(userbuf, count, ppos,
+					      res_buf, ret);
+	else
+		err = ret;
+
+	WARN_ON_ONCE(dfops->read_bufsize && (res_buf != buf));
+
+out_free:
+	vfree(res_buf);
+	mutex_unlock(&ar->mutex);
+	return err;
+}
+
+static ssize_t carl9170_debugfs_write(struct file *file,
+	const char __user *userbuf, size_t count, loff_t *ppos)
+{
+	struct carl9170_debugfs_fops *dfops;
+	struct ar9170 *ar;
+	char *buf = NULL;
+	int err = 0;
+
+	if (!count)
+		return 0;
+
+	if (count > PAGE_SIZE)
+		return -E2BIG;
+
+	ar = file->private_data;
+
+	if (!ar)
+		return -ENODEV;
+	dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops);
+
+	if (!dfops->write)
+		return -ENOSYS;
+
+	buf = vmalloc(count);
+	if (!buf)
+		return -ENOMEM;
+
+	if (copy_from_user(buf, userbuf, count)) {
+		err = -EFAULT;
+		goto out_free;
+	}
+
+	if (mutex_trylock(&ar->mutex) == 0) {
+		err = -EAGAIN;
+		goto out_free;
+	}
+
+	if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) {
+		err = -ENODEV;
+		goto out_unlock;
+	}
+
+	err = dfops->write(ar, buf, count);
+	if (err)
+		goto out_unlock;
+
+out_unlock:
+	mutex_unlock(&ar->mutex);
+
+out_free:
+	vfree(buf);
+	return err;
+}
+
+#define __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize,	\
+			       _attr, _dstate)				\
+static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\
+	.read_bufsize = _read_bufsize,					\
+	.read = _read,							\
+	.write = _write,						\
+	.attr = _attr,							\
+	.req_dev_state = _dstate,					\
+	.fops = {							\
+		.open	= carl9170_debugfs_open,			\
+		.read	= carl9170_debugfs_read,			\
+		.write	= carl9170_debugfs_write,			\
+		.owner	= THIS_MODULE					\
+	},								\
+}
+
+#define DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, _attr)	\
+	__DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize,	\
+			       _attr, CARL9170_STARTED)			\
+
+#define DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize)			\
+	DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read,	\
+			     NULL, _read_bufsize, S_IRUSR)
+
+#define DEBUGFS_DECLARE_WO_FILE(name)					\
+	DEBUGFS_DECLARE_FILE(name, NULL, carl9170_debugfs_##name ##_write,\
+			     0, S_IWUSR)
+
+#define DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize)			\
+	DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read,	\
+			     carl9170_debugfs_##name ##_write,		\
+			     _read_bufsize, S_IRUSR | S_IWUSR)
+
+#define __DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize, _dstate)		\
+	__DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read,	\
+			     carl9170_debugfs_##name ##_write,		\
+			     _read_bufsize, S_IRUSR | S_IWUSR, _dstate)
+
+#define DEBUGFS_READONLY_FILE(name, _read_bufsize, fmt, value...)	\
+static char *carl9170_debugfs_ ##name ## _read(struct ar9170 *ar,	\
+					     char *buf, size_t buf_size,\
+					     ssize_t *len)		\
+{									\
+	ADD(buf, *len, buf_size, fmt "\n", ##value);			\
+	return buf;							\
+}									\
+DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize)
+
+static char *carl9170_debugfs_mem_usage_read(struct ar9170 *ar, char *buf,
+					     size_t bufsize, ssize_t *len)
+{
+	ADD(buf, *len, bufsize, "jar: [");
+
+	spin_lock_bh(&ar->mem_lock);
+
+	*len += bitmap_scnprintf(&buf[*len], bufsize - *len,
+				  ar->mem_bitmap, ar->fw.mem_blocks);
+
+	ADD(buf, *len, bufsize, "]\n");
+
+	ADD(buf, *len, bufsize, "cookies: used:%3d / total:%3d, allocs:%d\n",
+	    bitmap_weight(ar->mem_bitmap, ar->fw.mem_blocks),
+	    ar->fw.mem_blocks, atomic_read(&ar->mem_allocs));
+
+	ADD(buf, *len, bufsize, "memory: free:%3d (%3d KiB) / total:%3d KiB)\n",
+	    atomic_read(&ar->mem_free_blocks),
+	    (atomic_read(&ar->mem_free_blocks) * ar->fw.mem_block_size) / 1024,
+	    (ar->fw.mem_blocks * ar->fw.mem_block_size) / 1024);
+
+	spin_unlock_bh(&ar->mem_lock);
+
+	return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(mem_usage, 512);
+
+static char *carl9170_debugfs_qos_stat_read(struct ar9170 *ar, char *buf,
+					    size_t bufsize, ssize_t *len)
+{
+	ADD(buf, *len, bufsize, "%s QoS AC\n", modparam_noht ? "Hardware" :
+	    "Software");
+
+	ADD(buf, *len, bufsize, "[     VO            VI       "
+				 "     BE            BK      ]\n");
+
+	spin_lock_bh(&ar->tx_stats_lock);
+	ADD(buf, *len, bufsize, "[length/limit  length/limit  "
+				 "length/limit  length/limit ]\n"
+				"[   %3d/%3d       %3d/%3d    "
+				 "   %3d/%3d       %3d/%3d   ]\n\n",
+	    ar->tx_stats[0].len, ar->tx_stats[0].limit,
+	    ar->tx_stats[1].len, ar->tx_stats[1].limit,
+	    ar->tx_stats[2].len, ar->tx_stats[2].limit,
+	    ar->tx_stats[3].len, ar->tx_stats[3].limit);
+
+	ADD(buf, *len, bufsize, "[    total         total     "
+				 "    total         total    ]\n"
+				"[%10d    %10d    %10d    %10d   ]\n\n",
+	    ar->tx_stats[0].count, ar->tx_stats[1].count,
+	    ar->tx_stats[2].count, ar->tx_stats[3].count);
+
+	spin_unlock_bh(&ar->tx_stats_lock);
+
+	ADD(buf, *len, bufsize, "[  pend/waittx   pend/waittx "
+				 "  pend/waittx   pend/waittx]\n"
+				"[   %3d/%3d       %3d/%3d    "
+				 "   %3d/%3d       %3d/%3d   ]\n\n",
+	    skb_queue_len(&ar->tx_pending[0]),
+	    skb_queue_len(&ar->tx_status[0]),
+	    skb_queue_len(&ar->tx_pending[1]),
+	    skb_queue_len(&ar->tx_status[1]),
+	    skb_queue_len(&ar->tx_pending[2]),
+	    skb_queue_len(&ar->tx_status[2]),
+	    skb_queue_len(&ar->tx_pending[3]),
+	    skb_queue_len(&ar->tx_status[3]));
+
+	return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(qos_stat, 512);
+
+static void carl9170_debugfs_format_frame(struct ar9170 *ar,
+	struct sk_buff *skb, const char *prefix, char *buf,
+	ssize_t *off, ssize_t bufsize)
+{
+	struct _carl9170_tx_superframe *txc = (void *) skb->data;
+	struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
+	struct carl9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
+	struct ieee80211_hdr *hdr = (void *) txc->frame_data;
+
+	ADD(buf, *off, bufsize, "%s %p, c:%2x, DA:%pM, sq:%4d, mc:%.4x, "
+	    "pc:%.8x, to:%d ms\n", prefix, skb, txc->s.cookie,
+	    ieee80211_get_DA(hdr), get_seq_h(hdr),
+	    le16_to_cpu(txc->f.mac_control), le32_to_cpu(txc->f.phy_control),
+	    jiffies_to_msecs(jiffies - arinfo->timeout));
+}
+
+
+static char *carl9170_debugfs_ampdu_state_read(struct ar9170 *ar, char *buf,
+					       size_t bufsize, ssize_t *len)
+{
+	struct carl9170_sta_tid *iter;
+	struct sk_buff *skb;
+	int cnt = 0, fc;
+	int offset;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) {
+
+		spin_lock_bh(&iter->lock);
+		ADD(buf, *len, bufsize, "Entry: #%2d TID:%1d, BSN:%4d, "
+		    "SNX:%4d, HSN:%4d, BAW:%2d, state:%1d, toggles:%d\n",
+		    cnt, iter->tid, iter->bsn, iter->snx, iter->hsn,
+		    iter->max, iter->state, iter->counter);
+
+		ADD(buf, *len, bufsize, "\tWindow:  [");
+
+		*len += bitmap_scnprintf(&buf[*len], bufsize - *len,
+			iter->bitmap, CARL9170_BAW_BITS);
+
+#define BM_STR_OFF(offset)					\
+	((CARL9170_BAW_BITS - (offset) - 1) / 4 +		\
+	 (CARL9170_BAW_BITS - (offset) - 1) / 32 + 1)
+
+		ADD(buf, *len, bufsize, ",W]\n");
+
+		offset = BM_STR_OFF(0);
+		ADD(buf, *len, bufsize, "\tBase Seq: %*s\n", offset, "T");
+
+		offset = BM_STR_OFF(SEQ_DIFF(iter->snx, iter->bsn));
+		ADD(buf, *len, bufsize, "\tNext Seq: %*s\n", offset, "W");
+
+		offset = BM_STR_OFF(((int)iter->hsn - (int)iter->bsn) %
+				     CARL9170_BAW_BITS);
+		ADD(buf, *len, bufsize, "\tLast Seq: %*s\n", offset, "N");
+
+		ADD(buf, *len, bufsize, "\tPre-Aggregation reorder buffer: "
+		    " currently queued:%d\n", skb_queue_len(&iter->queue));
+
+		fc = 0;
+		skb_queue_walk(&iter->queue, skb) {
+			char prefix[32];
+
+			snprintf(prefix, sizeof(prefix), "\t\t%3d :", fc);
+			carl9170_debugfs_format_frame(ar, skb, prefix, buf,
+						      len, bufsize);
+
+			fc++;
+		}
+		spin_unlock_bh(&iter->lock);
+		cnt++;
+	}
+	rcu_read_unlock();
+
+	return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(ampdu_state, 8000);
+
+static void carl9170_debugfs_queue_dump(struct ar9170 *ar, char *buf,
+	ssize_t *len, size_t bufsize, struct sk_buff_head *queue)
+{
+	struct sk_buff *skb;
+	char prefix[16];
+	int fc = 0;
+
+	spin_lock_bh(&queue->lock);
+	skb_queue_walk(queue, skb) {
+		snprintf(prefix, sizeof(prefix), "%3d :", fc);
+		carl9170_debugfs_format_frame(ar, skb, prefix, buf,
+					      len, bufsize);
+		fc++;
+	}
+	spin_unlock_bh(&queue->lock);
+}
+
+#define DEBUGFS_QUEUE_DUMP(q, qi)					\
+static char *carl9170_debugfs_##q ##_##qi ##_read(struct ar9170 *ar,	\
+	char *buf, size_t bufsize, ssize_t *len)			\
+{									\
+	carl9170_debugfs_queue_dump(ar, buf, len, bufsize, &ar->q[qi]);	\
+	return buf;							\
+}									\
+DEBUGFS_DECLARE_RO_FILE(q##_##qi, 8000);
+
+static char *carl9170_debugfs_sta_psm_read(struct ar9170 *ar, char *buf,
+					   size_t bufsize, ssize_t *len)
+{
+	ADD(buf, *len, bufsize, "psm state: %s\n", (ar->ps.off_override ?
+	    "FORCE CAM" : (ar->ps.state ? "PSM" : "CAM")));
+
+	ADD(buf, *len, bufsize, "sleep duration: %d ms.\n", ar->ps.sleep_ms);
+	ADD(buf, *len, bufsize, "last power-state transition: %d ms ago.\n",
+	    jiffies_to_msecs(jiffies - ar->ps.last_action));
+	ADD(buf, *len, bufsize, "last CAM->PSM transition: %d ms ago.\n",
+	    jiffies_to_msecs(jiffies - ar->ps.last_slept));
+
+	return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(sta_psm, 160);
+
+static char *carl9170_debugfs_tx_stuck_read(struct ar9170 *ar, char *buf,
+					    size_t bufsize, ssize_t *len)
+{
+	int i;
+
+	for (i = 0; i < ar->hw->queues; i++) {
+		ADD(buf, *len, bufsize, "TX queue [%d]: %10d max:%10d ms.\n",
+		    i, ieee80211_queue_stopped(ar->hw, i) ?
+		    jiffies_to_msecs(jiffies - ar->queue_stop_timeout[i]) : 0,
+		    jiffies_to_msecs(ar->max_queue_stop_timeout[i]));
+
+		ar->max_queue_stop_timeout[i] = 0;
+	}
+
+	return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(tx_stuck, 180);
+
+static char *carl9170_debugfs_phy_noise_read(struct ar9170 *ar, char *buf,
+					     size_t bufsize, ssize_t *len)
+{
+	int err;
+
+	err = carl9170_get_noisefloor(ar);
+	if (err) {
+		*len = err;
+		return buf;
+	}
+
+	ADD(buf, *len, bufsize, "Chain 0: %10d dBm, ext. chan.:%10d dBm\n",
+	    ar->noise[0], ar->noise[2]);
+	ADD(buf, *len, bufsize, "Chain 2: %10d dBm, ext. chan.:%10d dBm\n",
+	    ar->noise[1], ar->noise[3]);
+
+	return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(phy_noise, 180);
+
+static char *carl9170_debugfs_vif_dump_read(struct ar9170 *ar, char *buf,
+					    size_t bufsize, ssize_t *len)
+{
+	struct carl9170_vif_info *iter;
+	int i = 0;
+
+	ADD(buf, *len, bufsize, "registered VIFs:%d \\ %d\n",
+	    ar->vifs, ar->fw.vif_num);
+
+	ADD(buf, *len, bufsize, "VIF bitmap: [");
+
+	*len += bitmap_scnprintf(&buf[*len], bufsize - *len,
+				 &ar->vif_bitmap, ar->fw.vif_num);
+
+	ADD(buf, *len, bufsize, "]\n");
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(iter, &ar->vif_list, list) {
+		struct ieee80211_vif *vif = carl9170_get_vif(iter);
+		ADD(buf, *len, bufsize, "\t%d = [%s VIF, id:%d, type:%x "
+		    " mac:%pM %s]\n", i, (carl9170_get_main_vif(ar) == vif ?
+		    "Master" : " Slave"), iter->id, vif->type, vif->addr,
+		    iter->enable_beacon ? "beaconing " : "");
+		i++;
+	}
+	rcu_read_unlock();
+
+	return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(vif_dump, 8000);
+
+#define UPDATE_COUNTER(ar, name)	({				\
+	u32 __tmp[ARRAY_SIZE(name##_regs)];				\
+	unsigned int __i, __err = -ENODEV;				\
+									\
+	for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) {		\
+		__tmp[__i] = name##_regs[__i].reg;			\
+		ar->debug.stats.name##_counter[__i] = 0;		\
+	}								\
+									\
+	if (IS_STARTED(ar))						\
+		__err = carl9170_read_mreg(ar, ARRAY_SIZE(name##_regs),	\
+			__tmp, ar->debug.stats.name##_counter);		\
+	(__err); })
+
+#define TALLY_SUM_UP(ar, name)	do {					\
+	unsigned int __i;						\
+									\
+	for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) {		\
+		ar->debug.stats.name##_sum[__i] +=			\
+			ar->debug.stats.name##_counter[__i];		\
+	}								\
+} while (0)
+
+#define DEBUGFS_HW_TALLY_FILE(name, f)					\
+static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar,	\
+	 char *dum, size_t bufsize, ssize_t *ret)			\
+{									\
+	char *buf;							\
+	int i, max_len, err;						\
+									\
+	max_len = ARRAY_SIZE(name##_regs) * 80;				\
+	buf = vmalloc(max_len);						\
+	if (!buf)							\
+		return NULL;						\
+									\
+	err = UPDATE_COUNTER(ar, name);					\
+	if (err) {							\
+		*ret = err;						\
+		return buf;						\
+	}								\
+									\
+	TALLY_SUM_UP(ar, name);						\
+									\
+	for (i = 0; i < ARRAY_SIZE(name##_regs); i++) {			\
+		ADD(buf, *ret, max_len, "%22s = %" f "[+%" f "]\n",	\
+		    name##_regs[i].nreg, ar->debug.stats.name ##_sum[i],\
+		    ar->debug.stats.name ##_counter[i]);		\
+	}								\
+									\
+	return buf;							\
+}									\
+DEBUGFS_DECLARE_RO_FILE(name, 0);
+
+#define DEBUGFS_HW_REG_FILE(name, f)					\
+static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar,	\
+	char *dum, size_t bufsize, ssize_t *ret)			\
+{									\
+	char *buf;							\
+	int i, max_len, err;						\
+									\
+	max_len = ARRAY_SIZE(name##_regs) * 80;				\
+	buf = vmalloc(max_len);						\
+	if (!buf)							\
+		return NULL;						\
+									\
+	err = UPDATE_COUNTER(ar, name);					\
+	if (err) {							\
+		*ret = err;						\
+		return buf;						\
+	}								\
+									\
+	for (i = 0; i < ARRAY_SIZE(name##_regs); i++) {			\
+		ADD(buf, *ret, max_len, "%22s = %" f "\n",		\
+		    name##_regs[i].nreg,				\
+		    ar->debug.stats.name##_counter[i]);			\
+	}								\
+									\
+	return buf;							\
+}									\
+DEBUGFS_DECLARE_RO_FILE(name, 0);
+
+static ssize_t carl9170_debugfs_hw_ioread32_write(struct ar9170 *ar,
+	const char *buf, size_t count)
+{
+	int err = 0, i, n = 0, max_len = 32, res;
+	unsigned int reg, tmp;
+
+	if (!count)
+		return 0;
+
+	if (count > max_len)
+		return -E2BIG;
+
+	res = sscanf(buf, "0x%X %d", &reg, &n);
+	if (res < 1) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (res == 1)
+		n = 1;
+
+	if (n > 15) {
+		err = -EMSGSIZE;
+		goto out;
+	}
+
+	if ((reg >= 0x280000) || ((reg + (n << 2)) >= 0x280000)) {
+		err = -EADDRNOTAVAIL;
+		goto out;
+	}
+
+	if (reg & 3) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	for (i = 0; i < n; i++) {
+		err = carl9170_read_reg(ar, reg + (i << 2), &tmp);
+		if (err)
+			goto out;
+
+		ar->debug.ring[ar->debug.ring_tail].reg = reg + (i << 2);
+		ar->debug.ring[ar->debug.ring_tail].value = tmp;
+		ar->debug.ring_tail++;
+		ar->debug.ring_tail %= CARL9170_DEBUG_RING_SIZE;
+	}
+
+out:
+	return err ? err : count;
+}
+
+static char *carl9170_debugfs_hw_ioread32_read(struct ar9170 *ar, char *buf,
+					       size_t bufsize, ssize_t *ret)
+{
+	int i = 0;
+
+	while (ar->debug.ring_head != ar->debug.ring_tail) {
+		ADD(buf, *ret, bufsize, "%.8x = %.8x\n",
+		    ar->debug.ring[ar->debug.ring_head].reg,
+		    ar->debug.ring[ar->debug.ring_head].value);
+
+		ar->debug.ring_head++;
+		ar->debug.ring_head %= CARL9170_DEBUG_RING_SIZE;
+
+		if (i++ == 64)
+			break;
+	}
+	ar->debug.ring_head = ar->debug.ring_tail;
+	return buf;
+}
+DEBUGFS_DECLARE_RW_FILE(hw_ioread32, CARL9170_DEBUG_RING_SIZE * 40);
+
+static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
+					  size_t count)
+{
+	int err;
+
+	if (count < 1)
+		return -EINVAL;
+
+	switch (buf[0]) {
+	case 'F':
+		ar->needs_full_reset = true;
+		break;
+
+	case 'R':
+		if (!IS_STARTED(ar)) {
+			err = -EAGAIN;
+			goto out;
+		}
+
+		ar->needs_full_reset = false;
+		break;
+
+	case 'M':
+		err = carl9170_mac_reset(ar);
+		if (err < 0)
+			count = err;
+
+		goto out;
+
+	case 'P':
+		err = carl9170_set_channel(ar, ar->hw->conf.channel,
+			ar->hw->conf.channel_type, CARL9170_RFI_COLD);
+		if (err < 0)
+			count = err;
+
+		goto out;
+
+	default:
+		return -EINVAL;
+	}
+
+	carl9170_restart(ar, CARL9170_RR_USER_REQUEST);
+
+out:
+	return count;
+}
+
+static char *carl9170_debugfs_bug_read(struct ar9170 *ar, char *buf,
+				       size_t bufsize, ssize_t *ret)
+{
+	ADD(buf, *ret, bufsize, "[P]hy reinit, [R]estart, [F]ull usb reset, "
+	    "[M]ac reset\n");
+	ADD(buf, *ret, bufsize, "firmware restarts:%d, last reason:%d\n",
+		ar->restart_counter, ar->last_reason);
+	ADD(buf, *ret, bufsize, "phy reinit errors:%d (%d)\n",
+		ar->total_chan_fail, ar->chan_fail);
+	ADD(buf, *ret, bufsize, "reported firmware errors:%d\n",
+		ar->fw.err_counter);
+	ADD(buf, *ret, bufsize, "reported firmware BUGs:%d\n",
+		ar->fw.bug_counter);
+	ADD(buf, *ret, bufsize, "pending restart requests:%d\n",
+		atomic_read(&ar->pending_restarts));
+	return buf;
+}
+__DEBUGFS_DECLARE_RW_FILE(bug, 400, CARL9170_STOPPED);
+
+static const char *erp_modes[] = {
+	[CARL9170_ERP_INVALID] = "INVALID",
+	[CARL9170_ERP_AUTO] = "Automatic",
+	[CARL9170_ERP_MAC80211] = "Set by MAC80211",
+	[CARL9170_ERP_OFF] = "Force Off",
+	[CARL9170_ERP_RTS] = "Force RTS",
+	[CARL9170_ERP_CTS] = "Force CTS"
+};
+
+static char *carl9170_debugfs_erp_read(struct ar9170 *ar, char *buf,
+				       size_t bufsize, ssize_t *ret)
+{
+	ADD(buf, *ret, bufsize, "ERP Setting: (%d) -> %s\n", ar->erp_mode,
+	    erp_modes[ar->erp_mode]);
+	return buf;
+}
+
+static ssize_t carl9170_debugfs_erp_write(struct ar9170 *ar, const char *buf,
+					  size_t count)
+{
+	int res, val;
+
+	if (count < 1)
+		return -EINVAL;
+
+	res = sscanf(buf, "%d", &val);
+	if (res != 1)
+		return -EINVAL;
+
+	if (!((val > CARL9170_ERP_INVALID) &&
+	      (val < __CARL9170_ERP_NUM)))
+		return -EINVAL;
+
+	ar->erp_mode = val;
+	return count;
+}
+
+DEBUGFS_DECLARE_RW_FILE(erp, 80);
+
+static ssize_t carl9170_debugfs_hw_iowrite32_write(struct ar9170 *ar,
+	const char *buf, size_t count)
+{
+	int err = 0, max_len = 22, res;
+	u32 reg, val;
+
+	if (!count)
+		return 0;
+
+	if (count > max_len)
+		return -E2BIG;
+
+	res = sscanf(buf, "0x%X 0x%X", &reg, &val);
+	if (res != 2) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (reg <= 0x100000 || reg >= 0x280000) {
+		err = -EADDRNOTAVAIL;
+		goto out;
+	}
+
+	if (reg & 3) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	err = carl9170_write_reg(ar, reg, val);
+	if (err)
+		goto out;
+
+out:
+	return err ? err : count;
+}
+DEBUGFS_DECLARE_WO_FILE(hw_iowrite32);
+
+DEBUGFS_HW_TALLY_FILE(hw_tx_tally, "u");
+DEBUGFS_HW_TALLY_FILE(hw_rx_tally, "u");
+DEBUGFS_HW_TALLY_FILE(hw_phy_errors, "u");
+DEBUGFS_HW_REG_FILE(hw_wlan_queue, ".8x");
+DEBUGFS_HW_REG_FILE(hw_pta_queue, ".8x");
+DEBUGFS_HW_REG_FILE(hw_ampdu_info, ".8x");
+DEBUGFS_QUEUE_DUMP(tx_status, 0);
+DEBUGFS_QUEUE_DUMP(tx_status, 1);
+DEBUGFS_QUEUE_DUMP(tx_status, 2);
+DEBUGFS_QUEUE_DUMP(tx_status, 3);
+DEBUGFS_QUEUE_DUMP(tx_pending, 0);
+DEBUGFS_QUEUE_DUMP(tx_pending, 1);
+DEBUGFS_QUEUE_DUMP(tx_pending, 2);
+DEBUGFS_QUEUE_DUMP(tx_pending, 3);
+DEBUGFS_READONLY_FILE(usb_tx_anch_urbs, 20, "%d",
+		      atomic_read(&ar->tx_anch_urbs));
+DEBUGFS_READONLY_FILE(usb_rx_anch_urbs, 20, "%d",
+		      atomic_read(&ar->rx_anch_urbs));
+DEBUGFS_READONLY_FILE(usb_rx_work_urbs, 20, "%d",
+		      atomic_read(&ar->rx_work_urbs));
+DEBUGFS_READONLY_FILE(usb_rx_pool_urbs, 20, "%d",
+		      atomic_read(&ar->rx_pool_urbs));
+
+DEBUGFS_READONLY_FILE(tx_total_queued, 20, "%d",
+		      atomic_read(&ar->tx_total_queued));
+DEBUGFS_READONLY_FILE(tx_ampdu_scheduler, 20, "%d",
+		      atomic_read(&ar->tx_ampdu_scheduler));
+
+DEBUGFS_READONLY_FILE(tx_total_pending, 20, "%d",
+		      atomic_read(&ar->tx_total_pending));
+
+DEBUGFS_READONLY_FILE(tx_ampdu_list_len, 20, "%d",
+		      ar->tx_ampdu_list_len);
+
+DEBUGFS_READONLY_FILE(tx_ampdu_upload, 20, "%d",
+		      atomic_read(&ar->tx_ampdu_upload));
+
+DEBUGFS_READONLY_FILE(tx_janitor_last_run, 64, "last run:%d ms ago",
+	jiffies_to_msecs(jiffies - ar->tx_janitor_last_run));
+
+DEBUGFS_READONLY_FILE(tx_dropped, 20, "%d", ar->tx_dropped);
+
+DEBUGFS_READONLY_FILE(rx_dropped, 20, "%d", ar->rx_dropped);
+
+DEBUGFS_READONLY_FILE(sniffer_enabled, 20, "%d", ar->sniffer_enabled);
+DEBUGFS_READONLY_FILE(rx_software_decryption, 20, "%d",
+		      ar->rx_software_decryption);
+DEBUGFS_READONLY_FILE(ampdu_factor, 20, "%d",
+		      ar->current_factor);
+DEBUGFS_READONLY_FILE(ampdu_density, 20, "%d",
+		      ar->current_density);
+
+DEBUGFS_READONLY_FILE(beacon_int, 20, "%d TU", ar->global_beacon_int);
+DEBUGFS_READONLY_FILE(pretbtt, 20, "%d TU", ar->global_pretbtt);
+
+void carl9170_debugfs_register(struct ar9170 *ar)
+{
+	ar->debug_dir = debugfs_create_dir(KBUILD_MODNAME,
+		ar->hw->wiphy->debugfsdir);
+
+#define DEBUGFS_ADD(name)						\
+	debugfs_create_file(#name, carl_debugfs_##name ##_ops.attr,	\
+			    ar->debug_dir, ar,				\
+			    &carl_debugfs_##name ## _ops.fops);
+
+	DEBUGFS_ADD(usb_tx_anch_urbs);
+	DEBUGFS_ADD(usb_rx_pool_urbs);
+	DEBUGFS_ADD(usb_rx_anch_urbs);
+	DEBUGFS_ADD(usb_rx_work_urbs);
+
+	DEBUGFS_ADD(tx_total_queued);
+	DEBUGFS_ADD(tx_total_pending);
+	DEBUGFS_ADD(tx_dropped);
+	DEBUGFS_ADD(tx_stuck);
+	DEBUGFS_ADD(tx_ampdu_upload);
+	DEBUGFS_ADD(tx_ampdu_scheduler);
+	DEBUGFS_ADD(tx_ampdu_list_len);
+
+	DEBUGFS_ADD(rx_dropped);
+	DEBUGFS_ADD(sniffer_enabled);
+	DEBUGFS_ADD(rx_software_decryption);
+
+	DEBUGFS_ADD(mem_usage);
+	DEBUGFS_ADD(qos_stat);
+	DEBUGFS_ADD(sta_psm);
+	DEBUGFS_ADD(ampdu_state);
+
+	DEBUGFS_ADD(hw_tx_tally);
+	DEBUGFS_ADD(hw_rx_tally);
+	DEBUGFS_ADD(hw_phy_errors);
+	DEBUGFS_ADD(phy_noise);
+
+	DEBUGFS_ADD(hw_wlan_queue);
+	DEBUGFS_ADD(hw_pta_queue);
+	DEBUGFS_ADD(hw_ampdu_info);
+
+	DEBUGFS_ADD(ampdu_density);
+	DEBUGFS_ADD(ampdu_factor);
+
+	DEBUGFS_ADD(tx_janitor_last_run);
+
+	DEBUGFS_ADD(tx_status_0);
+	DEBUGFS_ADD(tx_status_1);
+	DEBUGFS_ADD(tx_status_2);
+	DEBUGFS_ADD(tx_status_3);
+
+	DEBUGFS_ADD(tx_pending_0);
+	DEBUGFS_ADD(tx_pending_1);
+	DEBUGFS_ADD(tx_pending_2);
+	DEBUGFS_ADD(tx_pending_3);
+
+	DEBUGFS_ADD(hw_ioread32);
+	DEBUGFS_ADD(hw_iowrite32);
+	DEBUGFS_ADD(bug);
+
+	DEBUGFS_ADD(erp);
+
+	DEBUGFS_ADD(vif_dump);
+
+	DEBUGFS_ADD(beacon_int);
+	DEBUGFS_ADD(pretbtt);
+
+#undef DEBUGFS_ADD
+}
+
+void carl9170_debugfs_unregister(struct ar9170 *ar)
+{
+	debugfs_remove_recursive(ar->debug_dir);
+}
diff --git a/drivers/net/wireless/ath/carl9170/debug.h b/drivers/net/wireless/ath/carl9170/debug.h
new file mode 100644
index 0000000..ea4b975
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/debug.h
@@ -0,0 +1,134 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * debug header
+ *
+ * Copyright 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __DEBUG_H
+#define __DEBUG_H
+
+#include "eeprom.h"
+#include "wlan.h"
+#include "hw.h"
+#include "fwdesc.h"
+#include "fwcmd.h"
+#include "../regd.h"
+
+struct hw_stat_reg_entry {
+	u32 reg;
+	char nreg[32];
+};
+
+#define	STAT_MAC_REG(reg)	\
+	{ (AR9170_MAC_REG_##reg), #reg }
+
+#define	STAT_PTA_REG(reg)	\
+	{ (AR9170_PTA_REG_##reg), #reg }
+
+#define	STAT_USB_REG(reg)	\
+	{ (AR9170_USB_REG_##reg), #reg }
+
+static const struct hw_stat_reg_entry hw_rx_tally_regs[] = {
+	STAT_MAC_REG(RX_CRC32),		STAT_MAC_REG(RX_CRC16),
+	STAT_MAC_REG(RX_TIMEOUT_COUNT),	STAT_MAC_REG(RX_ERR_DECRYPTION_UNI),
+	STAT_MAC_REG(RX_ERR_DECRYPTION_MUL), STAT_MAC_REG(RX_MPDU),
+	STAT_MAC_REG(RX_DROPPED_MPDU),	STAT_MAC_REG(RX_DEL_MPDU),
+};
+
+static const struct hw_stat_reg_entry hw_phy_errors_regs[] = {
+	STAT_MAC_REG(RX_PHY_MISC_ERROR), STAT_MAC_REG(RX_PHY_XR_ERROR),
+	STAT_MAC_REG(RX_PHY_OFDM_ERROR), STAT_MAC_REG(RX_PHY_CCK_ERROR),
+	STAT_MAC_REG(RX_PHY_HT_ERROR), STAT_MAC_REG(RX_PHY_TOTAL),
+};
+
+static const struct hw_stat_reg_entry hw_tx_tally_regs[] = {
+	STAT_MAC_REG(TX_TOTAL),		STAT_MAC_REG(TX_UNDERRUN),
+	STAT_MAC_REG(TX_RETRY),
+};
+
+static const struct hw_stat_reg_entry hw_wlan_queue_regs[] = {
+	STAT_MAC_REG(DMA_STATUS),	STAT_MAC_REG(DMA_TRIGGER),
+	STAT_MAC_REG(DMA_TXQ0_ADDR),	STAT_MAC_REG(DMA_TXQ0_CURR_ADDR),
+	STAT_MAC_REG(DMA_TXQ1_ADDR),	STAT_MAC_REG(DMA_TXQ1_CURR_ADDR),
+	STAT_MAC_REG(DMA_TXQ2_ADDR),	STAT_MAC_REG(DMA_TXQ2_CURR_ADDR),
+	STAT_MAC_REG(DMA_TXQ3_ADDR),	STAT_MAC_REG(DMA_TXQ3_CURR_ADDR),
+	STAT_MAC_REG(DMA_RXQ_ADDR),	STAT_MAC_REG(DMA_RXQ_CURR_ADDR),
+};
+
+static const struct hw_stat_reg_entry hw_ampdu_info_regs[] = {
+	STAT_MAC_REG(AMPDU_DENSITY),	STAT_MAC_REG(AMPDU_FACTOR),
+};
+
+static const struct hw_stat_reg_entry hw_pta_queue_regs[] = {
+	STAT_PTA_REG(DN_CURR_ADDRH),	STAT_PTA_REG(DN_CURR_ADDRL),
+	STAT_PTA_REG(UP_CURR_ADDRH),	STAT_PTA_REG(UP_CURR_ADDRL),
+	STAT_PTA_REG(DMA_STATUS),	STAT_PTA_REG(DMA_MODE_CTRL),
+};
+
+#define	DEFINE_TALLY(name)					\
+	u32 name##_sum[ARRAY_SIZE(name##_regs)],		\
+	    name##_counter[ARRAY_SIZE(name##_regs)]		\
+
+#define	DEFINE_STAT(name)					\
+	u32 name##_counter[ARRAY_SIZE(name##_regs)]		\
+
+struct ath_stats {
+	DEFINE_TALLY(hw_tx_tally);
+	DEFINE_TALLY(hw_rx_tally);
+	DEFINE_TALLY(hw_phy_errors);
+	DEFINE_STAT(hw_wlan_queue);
+	DEFINE_STAT(hw_pta_queue);
+	DEFINE_STAT(hw_ampdu_info);
+};
+
+struct carl9170_debug_mem_rbe {
+	u32 reg;
+	u32 value;
+};
+
+#define	CARL9170_DEBUG_RING_SIZE			64
+
+struct carl9170_debug {
+	struct ath_stats stats;
+	struct carl9170_debug_mem_rbe ring[CARL9170_DEBUG_RING_SIZE];
+	struct mutex ring_lock;
+	unsigned int ring_head, ring_tail;
+	struct delayed_work update_tally;
+};
+
+struct ar9170;
+
+void carl9170_debugfs_register(struct ar9170 *ar);
+void carl9170_debugfs_unregister(struct ar9170 *ar);
+#endif /* __DEBUG_H */
diff --git a/drivers/net/wireless/ath/carl9170/eeprom.h b/drivers/net/wireless/ath/carl9170/eeprom.h
new file mode 100644
index 0000000..7cff40a
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/eeprom.h
@@ -0,0 +1,216 @@
+/*
+ * Shared Atheros AR9170 Header
+ *
+ * EEPROM layout
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __CARL9170_SHARED_EEPROM_H
+#define __CARL9170_SHARED_EEPROM_H
+
+#define AR9170_EEPROM_START		0x1600
+
+#define AR5416_MAX_CHAINS		2
+#define AR5416_MODAL_SPURS		5
+
+struct ar9170_eeprom_modal {
+	__le32	antCtrlChain[AR5416_MAX_CHAINS];
+	__le32	antCtrlCommon;
+	s8	antennaGainCh[AR5416_MAX_CHAINS];
+	u8	switchSettling;
+	u8	txRxAttenCh[AR5416_MAX_CHAINS];
+	u8	rxTxMarginCh[AR5416_MAX_CHAINS];
+	s8	adcDesiredSize;
+	s8	pgaDesiredSize;
+	u8	xlnaGainCh[AR5416_MAX_CHAINS];
+	u8	txEndToXpaOff;
+	u8	txEndToRxOn;
+	u8	txFrameToXpaOn;
+	u8	thresh62;
+	s8	noiseFloorThreshCh[AR5416_MAX_CHAINS];
+	u8	xpdGain;
+	u8	xpd;
+	s8	iqCalICh[AR5416_MAX_CHAINS];
+	s8	iqCalQCh[AR5416_MAX_CHAINS];
+	u8	pdGainOverlap;
+	u8	ob;
+	u8	db;
+	u8	xpaBiasLvl;
+	u8	pwrDecreaseFor2Chain;
+	u8	pwrDecreaseFor3Chain;
+	u8	txFrameToDataStart;
+	u8	txFrameToPaOn;
+	u8	ht40PowerIncForPdadc;
+	u8	bswAtten[AR5416_MAX_CHAINS];
+	u8	bswMargin[AR5416_MAX_CHAINS];
+	u8	swSettleHt40;
+	u8	reserved[22];
+	struct spur_channel {
+		__le16 spurChan;
+		u8	spurRangeLow;
+		u8	spurRangeHigh;
+	} __packed spur_channels[AR5416_MODAL_SPURS];
+} __packed;
+
+#define AR5416_NUM_PD_GAINS		4
+#define AR5416_PD_GAIN_ICEPTS		5
+
+struct ar9170_calibration_data_per_freq {
+	u8	pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+	u8	vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+} __packed;
+
+#define AR5416_NUM_5G_CAL_PIERS		8
+#define AR5416_NUM_2G_CAL_PIERS		4
+
+#define AR5416_NUM_5G_TARGET_PWRS	8
+#define AR5416_NUM_2G_CCK_TARGET_PWRS	3
+#define AR5416_NUM_2G_OFDM_TARGET_PWRS	4
+#define AR5416_MAX_NUM_TGT_PWRS		8
+
+struct ar9170_calibration_target_power_legacy {
+	u8	freq;
+	u8	power[4];
+} __packed;
+
+struct ar9170_calibration_target_power_ht {
+	u8	freq;
+	u8	power[8];
+} __packed;
+
+#define AR5416_NUM_CTLS			24
+
+struct ar9170_calctl_edges {
+	u8	channel;
+#define AR9170_CALCTL_EDGE_FLAGS	0xC0
+	u8	power_flags;
+} __packed;
+
+#define AR5416_NUM_BAND_EDGES		8
+
+struct ar9170_calctl_data {
+	struct ar9170_calctl_edges
+		control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
+} __packed;
+
+struct ar9170_eeprom {
+	__le16	length;
+	__le16	checksum;
+	__le16	version;
+	u8	operating_flags;
+#define AR9170_OPFLAG_5GHZ		1
+#define AR9170_OPFLAG_2GHZ		2
+	u8	misc;
+	__le16	reg_domain[2];
+	u8	mac_address[6];
+	u8	rx_mask;
+	u8	tx_mask;
+	__le16	rf_silent;
+	__le16	bluetooth_options;
+	__le16	device_capabilities;
+	__le32	build_number;
+	u8	deviceType;
+	u8	reserved[33];
+
+	u8	customer_data[64];
+
+	struct ar9170_eeprom_modal
+		modal_header[2];
+
+	u8	cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS];
+	u8	cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS];
+
+	struct ar9170_calibration_data_per_freq
+		cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS],
+		cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
+
+	/* power calibration data */
+	struct ar9170_calibration_target_power_legacy
+		cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS];
+	struct ar9170_calibration_target_power_ht
+		cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS],
+		cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS];
+
+	struct ar9170_calibration_target_power_legacy
+		cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS],
+		cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS];
+	struct ar9170_calibration_target_power_ht
+		cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS],
+		cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS];
+
+	/* conformance testing limits */
+	u8	ctl_index[AR5416_NUM_CTLS];
+	struct ar9170_calctl_data
+		ctl_data[AR5416_NUM_CTLS];
+
+	u8	pad;
+	__le16	subsystem_id;
+} __packed;
+
+#define AR9170_LED_MODE_POWER_ON		0x0001
+#define AR9170_LED_MODE_RESERVED		0x0002
+#define AR9170_LED_MODE_DISABLE_STATE		0x0004
+#define AR9170_LED_MODE_OFF_IN_PSM		0x0008
+
+/* AR9170_LED_MODE BIT is set */
+#define AR9170_LED_MODE_FREQUENCY_S		4
+#define AR9170_LED_MODE_FREQUENCY		0x0030
+#define AR9170_LED_MODE_FREQUENCY_1HZ		0x0000
+#define AR9170_LED_MODE_FREQUENCY_0_5HZ		0x0010
+#define AR9170_LED_MODE_FREQUENCY_0_25HZ	0x0020
+#define AR9170_LED_MODE_FREQUENCY_0_125HZ	0x0030
+
+/* AR9170_LED_MODE BIT is not set */
+#define AR9170_LED_MODE_CONN_STATE_S		4
+#define AR9170_LED_MODE_CONN_STATE		0x0030
+#define AR9170_LED_MODE_CONN_STATE_FORCE_OFF	0x0000
+#define AR9170_LED_MODE_CONN_STATE_FORCE_ON	0x0010
+/* Idle off / Active on */
+#define AR9170_LED_MODE_CONN_STATE_IOFF_AON	0x0020
+/* Idle on / Active off */
+#define AR9170_LED_MODE_CONN_STATE_ION_AOFF	0x0010
+
+#define AR9170_LED_MODE_MODE			0x0040
+#define AR9170_LED_MODE_RESERVED2		0x0080
+
+#define AR9170_LED_MODE_TON_SCAN_S		8
+#define AR9170_LED_MODE_TON_SCAN		0x0f00
+
+#define AR9170_LED_MODE_TOFF_SCAN_S		12
+#define AR9170_LED_MODE_TOFF_SCAN		0xf000
+
+struct ar9170_led_mode {
+	__le16 led;
+};
+
+#endif /* __CARL9170_SHARED_EEPROM_H */
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
new file mode 100644
index 0000000..ae6c006
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -0,0 +1,402 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * firmware parser
+ *
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ */
+
+#include <linux/kernel.h>
+#include <linux/firmware.h>
+#include <linux/crc32.h>
+#include "carl9170.h"
+#include "fwcmd.h"
+#include "version.h"
+
+#define MAKE_STR(symbol) #symbol
+#define TO_STR(symbol) MAKE_STR(symbol)
+#define CARL9170FW_API_VER_STR TO_STR(CARL9170FW_API_MAX_VER)
+MODULE_VERSION(CARL9170FW_API_VER_STR ":" CARL9170FW_VERSION_GIT);
+
+static const u8 otus_magic[4] = { OTUS_MAGIC };
+
+static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4],
+	const unsigned int len, const u8 compatible_revision)
+{
+	const struct carl9170fw_desc_head *iter;
+
+	carl9170fw_for_each_hdr(iter, ar->fw.desc) {
+		if (carl9170fw_desc_cmp(iter, descid, len,
+					compatible_revision))
+			return (void *)iter;
+	}
+
+	/* needed to find the LAST desc */
+	if (carl9170fw_desc_cmp(iter, descid, len,
+				compatible_revision))
+		return (void *)iter;
+
+	return NULL;
+}
+
+static int carl9170_fw_verify_descs(struct ar9170 *ar,
+	const struct carl9170fw_desc_head *head, unsigned int max_len)
+{
+	const struct carl9170fw_desc_head *pos;
+	unsigned long pos_addr, end_addr;
+	unsigned int pos_length;
+
+	if (max_len < sizeof(*pos))
+		return -ENODATA;
+
+	max_len = min_t(unsigned int, CARL9170FW_DESC_MAX_LENGTH, max_len);
+
+	pos = head;
+	pos_addr = (unsigned long) pos;
+	end_addr = pos_addr + max_len;
+
+	while (pos_addr < end_addr) {
+		if (pos_addr + sizeof(*head) > end_addr)
+			return -E2BIG;
+
+		pos_length = le16_to_cpu(pos->length);
+
+		if (pos_length < sizeof(*head))
+			return -EBADMSG;
+
+		if (pos_length > max_len)
+			return -EOVERFLOW;
+
+		if (pos_addr + pos_length > end_addr)
+			return -EMSGSIZE;
+
+		if (carl9170fw_desc_cmp(pos, LAST_MAGIC,
+					CARL9170FW_LAST_DESC_SIZE,
+					CARL9170FW_LAST_DESC_CUR_VER))
+			return 0;
+
+		pos_addr += pos_length;
+		pos = (void *)pos_addr;
+		max_len -= pos_length;
+	}
+	return -EINVAL;
+}
+
+static void carl9170_fw_info(struct ar9170 *ar)
+{
+	const struct carl9170fw_motd_desc *motd_desc;
+	unsigned int str_ver_len;
+	u32 fw_date;
+
+	dev_info(&ar->udev->dev, "driver   API: %s 2%03d-%02d-%02d [%d-%d]\n",
+		CARL9170FW_VERSION_GIT, CARL9170FW_VERSION_YEAR,
+		CARL9170FW_VERSION_MONTH, CARL9170FW_VERSION_DAY,
+		CARL9170FW_API_MIN_VER, CARL9170FW_API_MAX_VER);
+
+	motd_desc = carl9170_fw_find_desc(ar, MOTD_MAGIC,
+		sizeof(*motd_desc), CARL9170FW_MOTD_DESC_CUR_VER);
+
+	if (motd_desc) {
+		str_ver_len = strnlen(motd_desc->release,
+			CARL9170FW_MOTD_RELEASE_LEN);
+
+		fw_date = le32_to_cpu(motd_desc->fw_year_month_day);
+
+		dev_info(&ar->udev->dev, "firmware API: %.*s 2%03d-%02d-%02d\n",
+			 str_ver_len, motd_desc->release,
+			 CARL9170FW_GET_YEAR(fw_date),
+			 CARL9170FW_GET_MONTH(fw_date),
+			 CARL9170FW_GET_DAY(fw_date));
+
+		strlcpy(ar->hw->wiphy->fw_version, motd_desc->release,
+			sizeof(ar->hw->wiphy->fw_version));
+	}
+}
+
+static bool valid_dma_addr(const u32 address)
+{
+	if (address >= AR9170_SRAM_OFFSET &&
+	    address < (AR9170_SRAM_OFFSET + AR9170_SRAM_SIZE))
+		return true;
+
+	return false;
+}
+
+static bool valid_cpu_addr(const u32 address)
+{
+	if (valid_dma_addr(address) || (address >= AR9170_PRAM_OFFSET &&
+	    address < (AR9170_PRAM_OFFSET + AR9170_PRAM_SIZE)))
+		return true;
+
+	return false;
+}
+
+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;
+
+	last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC,
+		sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER);
+	if (!last_desc)
+		return -EINVAL;
+
+	otus_desc = carl9170_fw_find_desc(ar, OTUS_MAGIC,
+		sizeof(*otus_desc), CARL9170FW_OTUS_DESC_CUR_VER);
+	if (!otus_desc) {
+		dev_err(&ar->udev->dev, "failed to find compatible firmware "
+			"descriptor.\n");
+		return -ENODATA;
+	}
+
+	chk_desc = carl9170_fw_find_desc(ar, CHK_MAGIC,
+		sizeof(*chk_desc), CARL9170FW_CHK_DESC_CUR_VER);
+
+	if (chk_desc) {
+		unsigned long fin, diff;
+		unsigned int dsc_len;
+		u32 crc32;
+
+		dsc_len = min_t(unsigned int, len,
+			(unsigned long)chk_desc - (unsigned long)otus_desc);
+
+		fin = (unsigned long) last_desc + sizeof(*last_desc);
+		diff = fin - (unsigned long) otus_desc;
+
+		if (diff < len)
+			len -= diff;
+
+		if (len < 256)
+			return -EIO;
+
+		crc32 = crc32_le(~0, data, len);
+		if (cpu_to_le32(crc32) != chk_desc->fw_crc32) {
+			dev_err(&ar->udev->dev, "fw checksum test failed.\n");
+			return -ENOEXEC;
+		}
+
+		crc32 = crc32_le(crc32, (void *)otus_desc, dsc_len);
+		if (cpu_to_le32(crc32) != chk_desc->hdr_crc32) {
+			dev_err(&ar->udev->dev, "descriptor check failed.\n");
+			return -EINVAL;
+		}
+	} else {
+		dev_warn(&ar->udev->dev, "Unprotected firmware image.\n");
+	}
+
+#define SUPP(feat)						\
+	(carl9170fw_supports(otus_desc->feature_set, feat))
+
+	if (!SUPP(CARL9170FW_DUMMY_FEATURE)) {
+		dev_err(&ar->udev->dev, "invalid firmware descriptor "
+			"format detected.\n");
+		return -EINVAL;
+	}
+
+	ar->fw.api_version = otus_desc->api_ver;
+
+	if (ar->fw.api_version < CARL9170FW_API_MIN_VER ||
+	    ar->fw.api_version > CARL9170FW_API_MAX_VER) {
+		dev_err(&ar->udev->dev, "unsupported firmware api version.\n");
+		return -EINVAL;
+	}
+
+	if (!SUPP(CARL9170FW_COMMAND_PHY) || SUPP(CARL9170FW_UNUSABLE) ||
+	    !SUPP(CARL9170FW_HANDLE_BACK_REQ)) {
+		dev_err(&ar->udev->dev, "firmware does support "
+			"mandatory features.\n");
+		return -ECANCELED;
+	}
+
+	if (ilog2(le32_to_cpu(otus_desc->feature_set)) >=
+		__CARL9170FW_FEATURE_NUM) {
+		dev_warn(&ar->udev->dev, "driver does not support all "
+			 "firmware features.\n");
+	}
+
+	if (!SUPP(CARL9170FW_COMMAND_CAM)) {
+		dev_info(&ar->udev->dev, "crypto offloading is disabled "
+			 "by firmware.\n");
+		ar->disable_offload = true;
+	}
+
+	if (SUPP(CARL9170FW_PSM))
+		ar->hw->flags |= IEEE80211_HW_SUPPORTS_PS;
+
+	if (!SUPP(CARL9170FW_USB_INIT_FIRMWARE)) {
+		dev_err(&ar->udev->dev, "firmware does not provide "
+			"mandatory interfaces.\n");
+		return -EINVAL;
+	}
+
+	if (SUPP(CARL9170FW_MINIBOOT))
+		ar->fw.offset = le16_to_cpu(otus_desc->miniboot_size);
+	else
+		ar->fw.offset = 0;
+
+	if (SUPP(CARL9170FW_USB_DOWN_STREAM)) {
+		ar->hw->extra_tx_headroom += sizeof(struct ar9170_stream);
+		ar->fw.tx_stream = true;
+	}
+
+	if (SUPP(CARL9170FW_USB_UP_STREAM))
+		ar->fw.rx_stream = true;
+
+	if (SUPP(CARL9170FW_RX_FILTER)) {
+		ar->fw.rx_filter = true;
+		ar->rx_filter_caps = FIF_FCSFAIL | FIF_PLCPFAIL |
+			FIF_CONTROL | FIF_PSPOLL | FIF_OTHER_BSS |
+			FIF_PROMISC_IN_BSS;
+	}
+
+	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);
+	ar->fw.rx_size = le16_to_cpu(otus_desc->rx_max_frame_len);
+	ar->fw.mem_blocks = min_t(unsigned int, otus_desc->tx_descs, 0xfe);
+	atomic_set(&ar->mem_free_blocks, ar->fw.mem_blocks);
+	ar->fw.mem_block_size = le16_to_cpu(otus_desc->tx_frag_len);
+
+	if (ar->fw.vif_num >= AR9170_MAX_VIRTUAL_MAC || !ar->fw.vif_num ||
+	    ar->fw.mem_blocks < 16 || !ar->fw.cmd_bufs ||
+	    ar->fw.mem_block_size < 64 || ar->fw.mem_block_size > 512 ||
+	    ar->fw.rx_size > 32768 || ar->fw.rx_size < 4096 ||
+	    !valid_cpu_addr(ar->fw.address)) {
+		dev_err(&ar->udev->dev, "firmware shows obvious signs of "
+			"malicious tampering.\n");
+		return -EINVAL;
+	}
+
+	ar->fw.beacon_addr = le32_to_cpu(otus_desc->bcn_addr);
+	ar->fw.beacon_max_len = le16_to_cpu(otus_desc->bcn_len);
+
+	if (valid_dma_addr(ar->fw.beacon_addr) && ar->fw.beacon_max_len >=
+	    AR9170_MAC_BCN_LENGTH_MAX) {
+		ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
+
+		if (SUPP(CARL9170FW_WLANTX_CAB)) {
+			ar->hw->wiphy->interface_modes |=
+				BIT(NL80211_IFTYPE_AP);
+		}
+	}
+
+#undef SUPPORTED
+	return 0;
+}
+
+static struct carl9170fw_desc_head *
+carl9170_find_fw_desc(struct ar9170 *ar, const __u8 *fw_data, const size_t len)
+
+{
+	int scan = 0, found = 0;
+
+	if (!carl9170fw_size_check(len)) {
+		dev_err(&ar->udev->dev, "firmware size is out of bound.\n");
+		return NULL;
+	}
+
+	while (scan < len - sizeof(struct carl9170fw_desc_head)) {
+		if (fw_data[scan++] == otus_magic[found])
+			found++;
+		else
+			found = 0;
+
+		if (scan >= len)
+			break;
+
+		if (found == sizeof(otus_magic))
+			break;
+	}
+
+	if (found != sizeof(otus_magic))
+		return NULL;
+
+	return (void *)&fw_data[scan - found];
+}
+
+int carl9170_fw_fix_eeprom(struct ar9170 *ar)
+{
+	const struct carl9170fw_fix_desc *fix_desc = NULL;
+	unsigned int i, n, off;
+	u32 *data = (void *)&ar->eeprom;
+
+	fix_desc = carl9170_fw_find_desc(ar, FIX_MAGIC,
+		sizeof(*fix_desc), CARL9170FW_FIX_DESC_CUR_VER);
+
+	if (!fix_desc)
+		return 0;
+
+	n = (le16_to_cpu(fix_desc->head.length) - sizeof(*fix_desc)) /
+	    sizeof(struct carl9170fw_fix_entry);
+
+	for (i = 0; i < n; i++) {
+		off = le32_to_cpu(fix_desc->data[i].address) -
+		      AR9170_EEPROM_START;
+
+		if (off >= sizeof(struct ar9170_eeprom) || (off & 3)) {
+			dev_err(&ar->udev->dev, "Skip invalid entry %d\n", i);
+			continue;
+		}
+
+		data[off / sizeof(*data)] &=
+			le32_to_cpu(fix_desc->data[i].mask);
+		data[off / sizeof(*data)] |=
+			le32_to_cpu(fix_desc->data[i].value);
+	}
+
+	return 0;
+}
+
+int carl9170_parse_firmware(struct ar9170 *ar)
+{
+	const struct carl9170fw_desc_head *fw_desc = NULL;
+	const struct firmware *fw = ar->fw.fw;
+	unsigned long header_offset = 0;
+	int err;
+
+	if (WARN_ON(!fw))
+		return -EINVAL;
+
+	fw_desc = carl9170_find_fw_desc(ar, fw->data, fw->size);
+
+	if (!fw_desc) {
+		dev_err(&ar->udev->dev, "unsupported firmware.\n");
+		return -ENODATA;
+	}
+
+	header_offset = (unsigned long)fw_desc - (unsigned long)fw->data;
+
+	err = carl9170_fw_verify_descs(ar, fw_desc, fw->size - header_offset);
+	if (err) {
+		dev_err(&ar->udev->dev, "damaged firmware (%d).\n", err);
+		return err;
+	}
+
+	ar->fw.desc = fw_desc;
+
+	carl9170_fw_info(ar);
+
+	err = carl9170_fw(ar, fw->data, fw->size);
+	if (err) {
+		dev_err(&ar->udev->dev, "failed to parse firmware (%d).\n",
+			err);
+		return err;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
new file mode 100644
index 0000000..d552166
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -0,0 +1,284 @@
+/*
+ * Shared Atheros AR9170 Header
+ *
+ * Firmware command interface definitions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __CARL9170_SHARED_FWCMD_H
+#define __CARL9170_SHARED_FWCMD_H
+
+#define	CARL9170_MAX_CMD_LEN		64
+#define	CARL9170_MAX_CMD_PAYLOAD_LEN	60
+
+#define CARL9170FW_API_MIN_VER		1
+#define CARL9170FW_API_MAX_VER		1
+
+enum carl9170_cmd_oids {
+	CARL9170_CMD_RREG		= 0x00,
+	CARL9170_CMD_WREG		= 0x01,
+	CARL9170_CMD_ECHO		= 0x02,
+	CARL9170_CMD_SWRST		= 0x03,
+	CARL9170_CMD_REBOOT		= 0x04,
+	CARL9170_CMD_BCN_CTRL		= 0x05,
+	CARL9170_CMD_READ_TSF		= 0x06,
+	CARL9170_CMD_RX_FILTER		= 0x07,
+
+	/* CAM */
+	CARL9170_CMD_EKEY		= 0x10,
+	CARL9170_CMD_DKEY		= 0x11,
+
+	/* RF / PHY */
+	CARL9170_CMD_FREQUENCY		= 0x20,
+	CARL9170_CMD_RF_INIT		= 0x21,
+	CARL9170_CMD_SYNTH		= 0x22,
+	CARL9170_CMD_FREQ_START		= 0x23,
+	CARL9170_CMD_PSM		= 0x24,
+
+	/* Asychronous command flag */
+	CARL9170_CMD_ASYNC_FLAG		= 0x40,
+	CARL9170_CMD_WREG_ASYNC		= (CARL9170_CMD_WREG |
+					   CARL9170_CMD_ASYNC_FLAG),
+	CARL9170_CMD_REBOOT_ASYNC	= (CARL9170_CMD_REBOOT |
+					   CARL9170_CMD_ASYNC_FLAG),
+	CARL9170_CMD_BCN_CTRL_ASYNC	= (CARL9170_CMD_BCN_CTRL |
+					   CARL9170_CMD_ASYNC_FLAG),
+	CARL9170_CMD_PSM_ASYNC		= (CARL9170_CMD_PSM |
+					   CARL9170_CMD_ASYNC_FLAG),
+
+	/* responses and traps */
+	CARL9170_RSP_FLAG		= 0xc0,
+	CARL9170_RSP_PRETBTT		= 0xc0,
+	CARL9170_RSP_TXCOMP		= 0xc1,
+	CARL9170_RSP_BEACON_CONFIG	= 0xc2,
+	CARL9170_RSP_ATIM		= 0xc3,
+	CARL9170_RSP_WATCHDOG		= 0xc6,
+	CARL9170_RSP_TEXT		= 0xca,
+	CARL9170_RSP_HEXDUMP		= 0xcc,
+	CARL9170_RSP_RADAR		= 0xcd,
+	CARL9170_RSP_GPIO		= 0xce,
+	CARL9170_RSP_BOOT		= 0xcf,
+};
+
+struct carl9170_set_key_cmd {
+	__le16		user;
+	__le16		keyId;
+	__le16		type;
+	u8		macAddr[6];
+	u32		key[4];
+} __packed;
+#define CARL9170_SET_KEY_CMD_SIZE		28
+
+struct carl9170_disable_key_cmd {
+	__le16		user;
+	__le16		padding;
+} __packed;
+#define CARL9170_DISABLE_KEY_CMD_SIZE		4
+
+struct carl9170_u32_list {
+	u32	vals[0];
+} __packed;
+
+struct carl9170_reg_list {
+	__le32		regs[0];
+} __packed;
+
+struct carl9170_write_reg {
+	struct {
+		__le32		addr;
+		__le32		val;
+	} regs[0] __packed;
+} __packed;
+
+#define	CARL9170FW_PHY_HT_ENABLE		0x4
+#define	CARL9170FW_PHY_HT_DYN2040		0x8
+#define	CARL9170FW_PHY_HT_EXT_CHAN_OFF		0x3
+#define	CARL9170FW_PHY_HT_EXT_CHAN_OFF_S	2
+
+struct carl9170_rf_init {
+	__le32		freq;
+	u8		ht_settings;
+	u8		padding2[3];
+	__le32		delta_slope_coeff_exp;
+	__le32		delta_slope_coeff_man;
+	__le32		delta_slope_coeff_exp_shgi;
+	__le32		delta_slope_coeff_man_shgi;
+	__le32		finiteLoopCount;
+} __packed;
+#define CARL9170_RF_INIT_SIZE		28
+
+struct carl9170_rf_init_result {
+	__le32		ret;		/* AR9170_PHY_REG_AGC_CONTROL */
+} __packed;
+#define	CARL9170_RF_INIT_RESULT_SIZE	4
+
+#define	CARL9170_PSM_SLEEP		0x1000
+#define	CARL9170_PSM_SOFTWARE		0
+#define	CARL9170_PSM_WAKE		0 /* internally used. */
+#define	CARL9170_PSM_COUNTER		0xfff
+#define	CARL9170_PSM_COUNTER_S		0
+
+struct carl9170_psm {
+	__le32		state;
+} __packed;
+#define CARL9170_PSM_SIZE		4
+
+struct carl9170_rx_filter_cmd {
+	__le32		rx_filter;
+} __packed;
+#define CARL9170_RX_FILTER_CMD_SIZE	4
+
+#define CARL9170_RX_FILTER_BAD		0x01
+#define CARL9170_RX_FILTER_OTHER_RA	0x02
+#define CARL9170_RX_FILTER_DECRY_FAIL	0x04
+#define CARL9170_RX_FILTER_CTL_OTHER	0x08
+#define CARL9170_RX_FILTER_CTL_PSPOLL	0x10
+#define CARL9170_RX_FILTER_CTL_BACKR	0x20
+#define CARL9170_RX_FILTER_MGMT		0x40
+#define CARL9170_RX_FILTER_DATA		0x80
+
+struct carl9170_bcn_ctrl_cmd {
+	__le32		vif_id;
+	__le32		mode;
+	__le32		bcn_addr;
+	__le32		bcn_len;
+} __packed;
+#define CARL9170_BCN_CTRL_CMD_SIZE	16
+
+#define CARL9170_BCN_CTRL_DRAIN	0
+#define CARL9170_BCN_CTRL_CAB_TRIGGER	1
+
+struct carl9170_cmd_head {
+	union {
+		struct {
+			u8	len;
+			u8	cmd;
+			u8	seq;
+			u8	ext;
+		} __packed;
+
+		u32 hdr_data;
+	} __packed;
+} __packed;
+
+struct carl9170_cmd {
+	struct carl9170_cmd_head hdr;
+	union {
+		struct carl9170_set_key_cmd	setkey;
+		struct carl9170_disable_key_cmd	disablekey;
+		struct carl9170_u32_list	echo;
+		struct carl9170_reg_list	rreg;
+		struct carl9170_write_reg	wreg;
+		struct carl9170_rf_init		rf_init;
+		struct carl9170_psm		psm;
+		struct carl9170_bcn_ctrl_cmd	bcn_ctrl;
+		struct carl9170_rx_filter_cmd	rx_filter;
+		u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
+	} __packed;
+} __packed;
+
+#define	CARL9170_TX_STATUS_QUEUE	3
+#define	CARL9170_TX_STATUS_QUEUE_S	0
+#define	CARL9170_TX_STATUS_RIX_S	2
+#define	CARL9170_TX_STATUS_RIX		(3 << CARL9170_TX_STATUS_RIX_S)
+#define	CARL9170_TX_STATUS_TRIES_S	4
+#define	CARL9170_TX_STATUS_TRIES	(7 << CARL9170_TX_STATUS_TRIES_S)
+#define	CARL9170_TX_STATUS_SUCCESS	0x80
+
+/*
+ * NOTE:
+ * Both structs [carl9170_tx_status and _carl9170_tx_status]
+ * need to be "bit for bit" in sync.
+ */
+struct carl9170_tx_status {
+	/*
+	 * Beware of compiler bugs in all gcc pre 4.4!
+	 */
+
+	u8 cookie;
+	u8 queue:2;
+	u8 rix:2;
+	u8 tries:3;
+	u8 success:1;
+} __packed;
+struct _carl9170_tx_status {
+	/*
+	 * This version should be immune to all alignment bugs.
+	 */
+
+	u8 cookie;
+	u8 info;
+} __packed;
+#define CARL9170_TX_STATUS_SIZE		2
+
+#define	CARL9170_RSP_TX_STATUS_NUM	(CARL9170_MAX_CMD_PAYLOAD_LEN /	\
+					 sizeof(struct _carl9170_tx_status))
+
+#define	CARL9170_TX_MAX_RATE_TRIES	7
+
+#define	CARL9170_TX_MAX_RATES		4
+#define	CARL9170_TX_MAX_RETRY_RATES	(CARL9170_TX_MAX_RATES - 1)
+#define	CARL9170_ERR_MAGIC		"ERR:"
+#define	CARL9170_BUG_MAGIC		"BUG:"
+
+struct carl9170_gpio {
+	__le32 gpio;
+} __packed;
+#define CARL9170_GPIO_SIZE		4
+
+struct carl9170_tsf_rsp {
+	union {
+		__le32 tsf[2];
+		__le64 tsf_64;
+	} __packed;
+} __packed;
+#define CARL9170_TSF_RSP_SIZE		8
+
+struct carl9170_rsp {
+	struct carl9170_cmd_head hdr;
+
+	union {
+		struct carl9170_rf_init_result	rf_init_res;
+		struct carl9170_u32_list	rreg_res;
+		struct carl9170_u32_list	echo;
+		struct carl9170_tx_status	tx_status[0];
+		struct _carl9170_tx_status	_tx_status[0];
+		struct carl9170_gpio		gpio;
+		struct carl9170_tsf_rsp		tsf;
+		struct carl9170_psm		psm;
+		u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
+	} __packed;
+} __packed;
+
+#endif /* __CARL9170_SHARED_FWCMD_H */
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h
new file mode 100644
index 0000000..71f3821
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/fwdesc.h
@@ -0,0 +1,241 @@
+/*
+ * Shared CARL9170 Header
+ *
+ * Firmware descriptor format
+ *
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ */
+
+#ifndef __CARL9170_SHARED_FWDESC_H
+#define __CARL9170_SHARED_FWDESC_H
+
+/* NOTE: Don't mess with the order of the flags! */
+enum carl9170fw_feature_list {
+	/* Always set */
+	CARL9170FW_DUMMY_FEATURE,
+
+	/*
+	 * Indicates that this image has special boot block which prevents
+	 * legacy drivers to drive the firmware.
+	 */
+	CARL9170FW_MINIBOOT,
+
+	/* usb registers are initialized by the firmware */
+	CARL9170FW_USB_INIT_FIRMWARE,
+
+	/* command traps & notifications are send through EP2 */
+	CARL9170FW_USB_RESP_EP2,
+
+	/* usb download (app -> fw) stream */
+	CARL9170FW_USB_DOWN_STREAM,
+
+	/* usb upload (fw -> app) stream */
+	CARL9170FW_USB_UP_STREAM,
+
+	/* unusable - reserved to flag non-functional debug firmwares */
+	CARL9170FW_UNUSABLE,
+
+	/* AR9170_CMD_RF_INIT, AR9170_CMD_FREQ_START, AR9170_CMD_FREQUENCY */
+	CARL9170FW_COMMAND_PHY,
+
+	/* AR9170_CMD_EKEY, AR9170_CMD_DKEY */
+	CARL9170FW_COMMAND_CAM,
+
+	/* Firmware has a software Content After Beacon Queueing mechanism */
+	CARL9170FW_WLANTX_CAB,
+
+	/* The firmware is capable of responding to incoming BAR frames */
+	CARL9170FW_HANDLE_BACK_REQ,
+
+	/* GPIO Interrupt | CARL9170_RSP_GPIO */
+	CARL9170FW_GPIO_INTERRUPT,
+
+	/* Firmware PSM support | CARL9170_CMD_PSM */
+	CARL9170FW_PSM,
+
+	/* Firmware RX filter | CARL9170_CMD_RX_FILTER */
+	CARL9170FW_RX_FILTER,
+
+	/* KEEP LAST */
+	__CARL9170FW_FEATURE_NUM
+};
+
+#define OTUS_MAGIC	"OTAR"
+#define MOTD_MAGIC	"MOTD"
+#define FIX_MAGIC	"FIX\0"
+#define DBG_MAGIC	"DBG\0"
+#define CHK_MAGIC	"CHK\0"
+#define LAST_MAGIC	"LAST"
+
+#define CARL9170FW_SET_DAY(d) (((d) - 1) % 31)
+#define CARL9170FW_SET_MONTH(m) ((((m) - 1) % 12) * 31)
+#define CARL9170FW_SET_YEAR(y) (((y) - 10) * 372)
+
+#define CARL9170FW_GET_DAY(d) (((d) % 31) + 1)
+#define CARL9170FW_GET_MONTH(m) ((((m) / 31) % 12) + 1)
+#define CARL9170FW_GET_YEAR(y) ((y) / 372 + 10)
+
+struct carl9170fw_desc_head {
+	u8	magic[4];
+	__le16 length;
+	u8 min_ver;
+	u8 cur_ver;
+} __packed;
+#define CARL9170FW_DESC_HEAD_SIZE			\
+	(sizeof(struct carl9170fw_desc_head))
+
+#define CARL9170FW_OTUS_DESC_MIN_VER		6
+#define CARL9170FW_OTUS_DESC_CUR_VER		6
+struct carl9170fw_otus_desc {
+	struct carl9170fw_desc_head head;
+	__le32 feature_set;
+	__le32 fw_address;
+	__le32 bcn_addr;
+	__le16 bcn_len;
+	__le16 miniboot_size;
+	__le16 tx_frag_len;
+	__le16 rx_max_frame_len;
+	u8 tx_descs;
+	u8 cmd_bufs;
+	u8 api_ver;
+	u8 vif_num;
+} __packed;
+#define CARL9170FW_OTUS_DESC_SIZE			\
+	(sizeof(struct carl9170fw_otus_desc))
+
+#define CARL9170FW_MOTD_STRING_LEN			24
+#define CARL9170FW_MOTD_RELEASE_LEN			20
+#define CARL9170FW_MOTD_DESC_MIN_VER			1
+#define CARL9170FW_MOTD_DESC_CUR_VER			2
+struct carl9170fw_motd_desc {
+	struct carl9170fw_desc_head head;
+	__le32 fw_year_month_day;
+	char desc[CARL9170FW_MOTD_STRING_LEN];
+	char release[CARL9170FW_MOTD_RELEASE_LEN];
+} __packed;
+#define CARL9170FW_MOTD_DESC_SIZE			\
+	(sizeof(struct carl9170fw_motd_desc))
+
+#define CARL9170FW_FIX_DESC_MIN_VER			1
+#define CARL9170FW_FIX_DESC_CUR_VER			2
+struct carl9170fw_fix_entry {
+	__le32 address;
+	__le32 mask;
+	__le32 value;
+} __packed;
+
+struct carl9170fw_fix_desc {
+	struct carl9170fw_desc_head head;
+	struct carl9170fw_fix_entry data[0];
+} __packed;
+#define CARL9170FW_FIX_DESC_SIZE			\
+	(sizeof(struct carl9170fw_fix_desc))
+
+#define CARL9170FW_DBG_DESC_MIN_VER			1
+#define CARL9170FW_DBG_DESC_CUR_VER			3
+struct carl9170fw_dbg_desc {
+	struct carl9170fw_desc_head head;
+
+	__le32 bogoclock_addr;
+	__le32 counter_addr;
+	__le32 rx_total_addr;
+	__le32 rx_overrun_addr;
+	__le32 rx_filter;
+
+	/* Put your debugging definitions here */
+} __packed;
+#define CARL9170FW_DBG_DESC_SIZE			\
+	(sizeof(struct carl9170fw_dbg_desc))
+
+#define CARL9170FW_CHK_DESC_MIN_VER			1
+#define CARL9170FW_CHK_DESC_CUR_VER			2
+struct carl9170fw_chk_desc {
+	struct carl9170fw_desc_head head;
+	__le32 fw_crc32;
+	__le32 hdr_crc32;
+} __packed;
+#define CARL9170FW_CHK_DESC_SIZE			\
+	(sizeof(struct carl9170fw_chk_desc))
+
+#define CARL9170FW_LAST_DESC_MIN_VER			1
+#define CARL9170FW_LAST_DESC_CUR_VER			2
+struct carl9170fw_last_desc {
+	struct carl9170fw_desc_head head;
+} __packed;
+#define CARL9170FW_LAST_DESC_SIZE			\
+	(sizeof(struct carl9170fw_fix_desc))
+
+#define CARL9170FW_DESC_MAX_LENGTH			8192
+
+#define CARL9170FW_FILL_DESC(_magic, _length, _min_ver, _cur_ver)	\
+	.head = {							\
+		.magic = _magic,					\
+		.length = cpu_to_le16(_length),				\
+		.min_ver = _min_ver,					\
+		.cur_ver = _cur_ver,					\
+	}
+
+static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head,
+					 u8 magic[4], __le16 length,
+					 u8 min_ver, u8 cur_ver)
+{
+	head->magic[0] = magic[0];
+	head->magic[1] = magic[1];
+	head->magic[2] = magic[2];
+	head->magic[3] = magic[3];
+
+	head->length = length;
+	head->min_ver = min_ver;
+	head->cur_ver = cur_ver;
+}
+
+#define carl9170fw_for_each_hdr(desc, fw_desc)				\
+	for (desc = fw_desc;						\
+	     memcmp(desc->magic, LAST_MAGIC, 4) &&			\
+	     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)))
+
+#define CHECK_HDR_VERSION(head, _min_ver)				\
+	(((head)->cur_ver < _min_ver) || ((head)->min_ver > _min_ver))	\
+
+static inline bool carl9170fw_supports(__le32 list, u8 feature)
+{
+	return le32_to_cpu(list) & BIT(feature);
+}
+
+static inline bool carl9170fw_desc_cmp(const struct carl9170fw_desc_head *head,
+				       const u8 descid[4], 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] &&
+	    !CHECK_HDR_VERSION(head, compatible_revision) &&
+	    (le16_to_cpu(head->length) >= min_len))
+		return true;
+
+	return false;
+}
+
+#define CARL9170FW_MIN_SIZE	32
+#define CARL9170FW_MAX_SIZE	16384
+
+static inline bool carl9170fw_size_check(unsigned int len)
+{
+	return (len <= CARL9170FW_MAX_SIZE && len >= CARL9170FW_MIN_SIZE);
+}
+
+#endif /* __CARL9170_SHARED_FWDESC_H */
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h
new file mode 100644
index 0000000..2f471b3
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/hw.h
@@ -0,0 +1,739 @@
+/*
+ * Shared Atheros AR9170 Header
+ *
+ * Register map, hardware-specific definitions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __CARL9170_SHARED_HW_H
+#define __CARL9170_SHARED_HW_H
+
+/* High Speed UART */
+#define	AR9170_UART_REG_BASE			0x1c0000
+
+/* Definitions of interrupt registers */
+#define	AR9170_UART_REG_RX_BUFFER		(AR9170_UART_REG_BASE + 0x000)
+#define	AR9170_UART_REG_TX_HOLDING		(AR9170_UART_REG_BASE + 0x004)
+#define	AR9170_UART_REG_FIFO_CONTROL		(AR9170_UART_REG_BASE + 0x010)
+#define		AR9170_UART_FIFO_CTRL_RESET_RX_FIFO	0x02
+#define		AR9170_UART_FIFO_CTRL_RESET_TX_FIFO	0x04
+
+#define	AR9170_UART_REG_LINE_CONTROL		(AR9170_UART_REG_BASE + 0x014)
+#define	AR9170_UART_REG_MODEM_CONTROL		(AR9170_UART_REG_BASE + 0x018)
+#define		AR9170_UART_MODEM_CTRL_DTR_BIT		0x01
+#define		AR9170_UART_MODEM_CTRL_RTS_BIT		0x02
+#define		AR9170_UART_MODEM_CTRL_INTERNAL_LOOP_BACK	0x10
+#define		AR9170_UART_MODEM_CTRL_AUTO_RTS		0x20
+#define		AR9170_UART_MODEM_CTRL_AUTO_CTR		0x40
+
+#define	AR9170_UART_REG_LINE_STATUS		(AR9170_UART_REG_BASE + 0x01c)
+#define		AR9170_UART_LINE_STS_RX_DATA_READY	0x01
+#define		AR9170_UART_LINE_STS_RX_BUFFER_OVERRUN	0x02
+#define		AR9170_UART_LINE_STS_RX_BREAK_IND	0x10
+#define		AR9170_UART_LINE_STS_TX_FIFO_NEAR_EMPTY	0x20
+#define		AR9170_UART_LINE_STS_TRANSMITTER_EMPTY	0x40
+
+#define	AR9170_UART_REG_MODEM_STATUS		(AR9170_UART_REG_BASE + 0x020)
+#define		AR9170_UART_MODEM_STS_CTS_CHANGE	0x01
+#define		AR9170_UART_MODEM_STS_DSR_CHANGE	0x02
+#define		AR9170_UART_MODEM_STS_DCD_CHANGE	0x08
+#define		AR9170_UART_MODEM_STS_CTS_COMPL		0x10
+#define		AR9170_UART_MODEM_STS_DSR_COMPL		0x20
+#define		AR9170_UART_MODEM_STS_DCD_COMPL		0x80
+
+#define	AR9170_UART_REG_SCRATCH			(AR9170_UART_REG_BASE + 0x024)
+#define	AR9170_UART_REG_DIVISOR_LSB		(AR9170_UART_REG_BASE + 0x028)
+#define	AR9170_UART_REG_DIVISOR_MSB		(AR9170_UART_REG_BASE + 0x02c)
+#define	AR9170_UART_REG_WORD_RX_BUFFER		(AR9170_UART_REG_BASE + 0x034)
+#define	AR9170_UART_REG_WORD_TX_HOLDING		(AR9170_UART_REG_BASE + 0x038)
+#define	AR9170_UART_REG_FIFO_COUNT		(AR9170_UART_REG_BASE + 0x03c)
+#define	AR9170_UART_REG_REMAINDER		(AR9170_UART_REG_BASE + 0x04c)
+
+/* Timer */
+#define	AR9170_TIMER_REG_BASE			0x1c1000
+
+#define	AR9170_TIMER_REG_WATCH_DOG		(AR9170_TIMER_REG_BASE + 0x000)
+#define	AR9170_TIMER_REG_TIMER0			(AR9170_TIMER_REG_BASE + 0x010)
+#define	AR9170_TIMER_REG_TIMER1			(AR9170_TIMER_REG_BASE + 0x014)
+#define	AR9170_TIMER_REG_TIMER2			(AR9170_TIMER_REG_BASE + 0x018)
+#define	AR9170_TIMER_REG_TIMER3			(AR9170_TIMER_REG_BASE + 0x01c)
+#define	AR9170_TIMER_REG_TIMER4			(AR9170_TIMER_REG_BASE + 0x020)
+#define	AR9170_TIMER_REG_CONTROL		(AR9170_TIMER_REG_BASE + 0x024)
+#define		AR9170_TIMER_CTRL_DISABLE_CLOCK		0x100
+
+#define	AR9170_TIMER_REG_INTERRUPT		(AR9170_TIMER_REG_BASE + 0x028)
+#define		AR9170_TIMER_INT_TIMER0			0x001
+#define		AR9170_TIMER_INT_TIMER1			0x002
+#define		AR9170_TIMER_INT_TIMER2			0x004
+#define		AR9170_TIMER_INT_TIMER3			0x008
+#define		AR9170_TIMER_INT_TIMER4			0x010
+#define		AR9170_TIMER_INT_TICK_TIMER		0x100
+
+#define	AR9170_TIMER_REG_TICK_TIMER		(AR9170_TIMER_REG_BASE + 0x030)
+#define	AR9170_TIMER_REG_CLOCK_LOW		(AR9170_TIMER_REG_BASE + 0x040)
+#define	AR9170_TIMER_REG_CLOCK_HIGH		(AR9170_TIMER_REG_BASE + 0x044)
+
+#define	AR9170_MAC_REG_BASE			0x1c3000
+
+#define	AR9170_MAC_REG_POWER_STATE_CTRL		(AR9170_MAC_REG_BASE + 0x500)
+#define		AR9170_MAC_POWER_STATE_CTRL_RESET	0x20
+
+#define	AR9170_MAC_REG_MAC_POWER_STATE_CTRL	(AR9170_MAC_REG_BASE + 0x50c)
+
+#define	AR9170_MAC_REG_INT_CTRL			(AR9170_MAC_REG_BASE + 0x510)
+#define		AR9170_MAC_INT_TXC			BIT(0)
+#define		AR9170_MAC_INT_RXC			BIT(1)
+#define		AR9170_MAC_INT_RETRY_FAIL		BIT(2)
+#define		AR9170_MAC_INT_WAKEUP			BIT(3)
+#define		AR9170_MAC_INT_ATIM			BIT(4)
+#define		AR9170_MAC_INT_DTIM			BIT(5)
+#define		AR9170_MAC_INT_CFG_BCN			BIT(6)
+#define		AR9170_MAC_INT_ABORT			BIT(7)
+#define		AR9170_MAC_INT_QOS			BIT(8)
+#define		AR9170_MAC_INT_MIMO_PS			BIT(9)
+#define		AR9170_MAC_INT_KEY_GEN			BIT(10)
+#define		AR9170_MAC_INT_DECRY_NOUSER		BIT(11)
+#define		AR9170_MAC_INT_RADAR			BIT(12)
+#define		AR9170_MAC_INT_QUIET_FRAME		BIT(13)
+#define		AR9170_MAC_INT_PRETBTT			BIT(14)
+
+#define	AR9170_MAC_REG_TSF_L			(AR9170_MAC_REG_BASE + 0x514)
+#define	AR9170_MAC_REG_TSF_H			(AR9170_MAC_REG_BASE + 0x518)
+
+#define	AR9170_MAC_REG_ATIM_WINDOW		(AR9170_MAC_REG_BASE + 0x51c)
+#define		AR9170_MAC_ATIM_PERIOD_S		0
+#define		AR9170_MAC_ATIM_PERIOD			0x0000ffff
+
+#define	AR9170_MAC_REG_BCN_PERIOD		(AR9170_MAC_REG_BASE + 0x520)
+#define		AR9170_MAC_BCN_PERIOD_S			0
+#define		AR9170_MAC_BCN_PERIOD			0x0000ffff
+#define		AR9170_MAC_BCN_DTIM_S			16
+#define		AR9170_MAC_BCN_DTIM			0x00ff0000
+#define		AR9170_MAC_BCN_AP_MODE			BIT(24)
+#define		AR9170_MAC_BCN_IBSS_MODE		BIT(25)
+#define		AR9170_MAC_BCN_PWR_MGT			BIT(26)
+#define		AR9170_MAC_BCN_STA_PS			BIT(27)
+
+#define	AR9170_MAC_REG_PRETBTT			(AR9170_MAC_REG_BASE + 0x524)
+#define		AR9170_MAC_PRETBTT_S			0
+#define		AR9170_MAC_PRETBTT			0x0000ffff
+#define		AR9170_MAC_PRETBTT2_S			16
+#define		AR9170_MAC_PRETBTT2			0xffff0000
+
+#define	AR9170_MAC_REG_MAC_ADDR_L		(AR9170_MAC_REG_BASE + 0x610)
+#define	AR9170_MAC_REG_MAC_ADDR_H		(AR9170_MAC_REG_BASE + 0x614)
+#define	AR9170_MAC_REG_BSSID_L			(AR9170_MAC_REG_BASE + 0x618)
+#define	AR9170_MAC_REG_BSSID_H			(AR9170_MAC_REG_BASE + 0x61c)
+
+#define	AR9170_MAC_REG_GROUP_HASH_TBL_L		(AR9170_MAC_REG_BASE + 0x624)
+#define	AR9170_MAC_REG_GROUP_HASH_TBL_H		(AR9170_MAC_REG_BASE + 0x628)
+
+#define	AR9170_MAC_REG_RX_TIMEOUT		(AR9170_MAC_REG_BASE + 0x62c)
+
+#define	AR9170_MAC_REG_BASIC_RATE		(AR9170_MAC_REG_BASE + 0x630)
+#define	AR9170_MAC_REG_MANDATORY_RATE		(AR9170_MAC_REG_BASE + 0x634)
+#define	AR9170_MAC_REG_RTS_CTS_RATE		(AR9170_MAC_REG_BASE + 0x638)
+#define	AR9170_MAC_REG_BACKOFF_PROTECT		(AR9170_MAC_REG_BASE + 0x63c)
+#define	AR9170_MAC_REG_RX_THRESHOLD		(AR9170_MAC_REG_BASE + 0x640)
+#define	AR9170_MAC_REG_AFTER_PNP		(AR9170_MAC_REG_BASE + 0x648)
+#define	AR9170_MAC_REG_RX_PE_DELAY		(AR9170_MAC_REG_BASE + 0x64c)
+
+#define	AR9170_MAC_REG_DYNAMIC_SIFS_ACK		(AR9170_MAC_REG_BASE + 0x658)
+#define	AR9170_MAC_REG_SNIFFER			(AR9170_MAC_REG_BASE + 0x674)
+#define		AR9170_MAC_SNIFFER_ENABLE_PROMISC	BIT(0)
+#define		AR9170_MAC_SNIFFER_DEFAULTS		0x02000000
+#define	AR9170_MAC_REG_ENCRYPTION		(AR9170_MAC_REG_BASE + 0x678)
+#define		AR9170_MAC_ENCRYPTION_RX_SOFTWARE	BIT(3)
+#define		AR9170_MAC_ENCRYPTION_DEFAULTS		0x70
+
+#define	AR9170_MAC_REG_MISC_680			(AR9170_MAC_REG_BASE + 0x680)
+#define	AR9170_MAC_REG_MISC_684			(AR9170_MAC_REG_BASE + 0x684)
+#define	AR9170_MAC_REG_TX_UNDERRUN		(AR9170_MAC_REG_BASE + 0x688)
+
+#define	AR9170_MAC_REG_FRAMETYPE_FILTER		(AR9170_MAC_REG_BASE + 0x68c)
+#define		AR9170_MAC_FTF_ASSOC_REQ		BIT(0)
+#define		AR9170_MAC_FTF_ASSOC_RESP		BIT(1)
+#define		AR9170_MAC_FTF_REASSOC_REQ		BIT(2)
+#define		AR9170_MAC_FTF_REASSOC_RESP		BIT(3)
+#define		AR9170_MAC_FTF_PRB_REQ			BIT(4)
+#define		AR9170_MAC_FTF_PRB_RESP			BIT(5)
+#define		AR9170_MAC_FTF_BIT6			BIT(6)
+#define		AR9170_MAC_FTF_BIT7			BIT(7)
+#define		AR9170_MAC_FTF_BEACON			BIT(8)
+#define		AR9170_MAC_FTF_ATIM			BIT(9)
+#define		AR9170_MAC_FTF_DEASSOC			BIT(10)
+#define		AR9170_MAC_FTF_AUTH			BIT(11)
+#define		AR9170_MAC_FTF_DEAUTH			BIT(12)
+#define		AR9170_MAC_FTF_BIT13			BIT(13)
+#define		AR9170_MAC_FTF_BIT14			BIT(14)
+#define		AR9170_MAC_FTF_BIT15			BIT(15)
+#define		AR9170_MAC_FTF_BAR			BIT(24)
+#define		AR9170_MAC_FTF_BA			BIT(25)
+#define		AR9170_MAC_FTF_PSPOLL			BIT(26)
+#define		AR9170_MAC_FTF_RTS			BIT(27)
+#define		AR9170_MAC_FTF_CTS			BIT(28)
+#define		AR9170_MAC_FTF_ACK			BIT(29)
+#define		AR9170_MAC_FTF_CFE			BIT(30)
+#define		AR9170_MAC_FTF_CFE_ACK			BIT(31)
+#define		AR9170_MAC_FTF_DEFAULTS			0x0500ffff
+#define		AR9170_MAC_FTF_MONITOR			0xff00ffff
+
+#define	AR9170_MAC_REG_ACK_EXTENSION		(AR9170_MAC_REG_BASE + 0x690)
+#define	AR9170_MAC_REG_ACK_TPC			(AR9170_MAC_REG_BASE + 0x694)
+#define	AR9170_MAC_REG_EIFS_AND_SIFS		(AR9170_MAC_REG_BASE + 0x698)
+#define	AR9170_MAC_REG_RX_TIMEOUT_COUNT		(AR9170_MAC_REG_BASE + 0x69c)
+#define	AR9170_MAC_REG_RX_TOTAL			(AR9170_MAC_REG_BASE + 0x6a0)
+#define	AR9170_MAC_REG_RX_CRC32			(AR9170_MAC_REG_BASE + 0x6a4)
+#define	AR9170_MAC_REG_RX_CRC16			(AR9170_MAC_REG_BASE + 0x6a8)
+#define	AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI	(AR9170_MAC_REG_BASE + 0x6ac)
+#define	AR9170_MAC_REG_RX_OVERRUN		(AR9170_MAC_REG_BASE + 0x6b0)
+#define	AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL	(AR9170_MAC_REG_BASE + 0x6bc)
+#define AR9170_MAC_REG_TX_BLOCKACKS		(AR9170_MAC_REG_BASE + 0x6c0)
+#define AR9170_MAC_REG_NAV_COUNT		(AR9170_MAC_REG_BASE + 0x6c4)
+#define AR9170_MAC_REG_BACKOFF_STATUS		(AR9170_MAC_REG_BASE + 0x6c8)
+#define	AR9170_MAC_REG_TX_RETRY			(AR9170_MAC_REG_BASE + 0x6cc)
+
+#define AR9170_MAC_REG_TX_COMPLETE		(AR9170_MAC_REG_BASE + 0x6d4)
+
+#define	AR9170_MAC_REG_CHANNEL_BUSY		(AR9170_MAC_REG_BASE + 0x6e8)
+#define	AR9170_MAC_REG_EXT_BUSY			(AR9170_MAC_REG_BASE + 0x6ec)
+
+#define	AR9170_MAC_REG_SLOT_TIME		(AR9170_MAC_REG_BASE + 0x6f0)
+#define	AR9170_MAC_REG_TX_TOTAL			(AR9170_MAC_REG_BASE + 0x6f4)
+#define AR9170_MAC_REG_ACK_FC			(AR9170_MAC_REG_BASE + 0x6f8)
+
+#define	AR9170_MAC_REG_CAM_MODE			(AR9170_MAC_REG_BASE + 0x700)
+#define		AR9170_MAC_CAM_IBSS			0xe0
+#define		AR9170_MAC_CAM_AP			0xa1
+#define		AR9170_MAC_CAM_STA			0x2
+#define		AR9170_MAC_CAM_AP_WDS			0x3
+#define		AR9170_MAC_CAM_DEFAULTS			(0xf << 24)
+#define		AR9170_MAC_CAM_HOST_PENDING		0x80000000
+
+#define	AR9170_MAC_REG_CAM_ROLL_CALL_TBL_L	(AR9170_MAC_REG_BASE + 0x704)
+#define	AR9170_MAC_REG_CAM_ROLL_CALL_TBL_H	(AR9170_MAC_REG_BASE + 0x708)
+
+#define	AR9170_MAC_REG_CAM_ADDR			(AR9170_MAC_REG_BASE + 0x70c)
+#define		AR9170_MAC_CAM_ADDR_WRITE		0x80000000
+#define	AR9170_MAC_REG_CAM_DATA0		(AR9170_MAC_REG_BASE + 0x720)
+#define	AR9170_MAC_REG_CAM_DATA1		(AR9170_MAC_REG_BASE + 0x724)
+#define	AR9170_MAC_REG_CAM_DATA2		(AR9170_MAC_REG_BASE + 0x728)
+#define	AR9170_MAC_REG_CAM_DATA3		(AR9170_MAC_REG_BASE + 0x72c)
+
+#define	AR9170_MAC_REG_CAM_DBG0			(AR9170_MAC_REG_BASE + 0x730)
+#define	AR9170_MAC_REG_CAM_DBG1			(AR9170_MAC_REG_BASE + 0x734)
+#define	AR9170_MAC_REG_CAM_DBG2			(AR9170_MAC_REG_BASE + 0x738)
+#define	AR9170_MAC_REG_CAM_STATE		(AR9170_MAC_REG_BASE + 0x73c)
+#define		AR9170_MAC_CAM_STATE_READ_PENDING	0x40000000
+#define		AR9170_MAC_CAM_STATE_WRITE_PENDING	0x80000000
+
+#define	AR9170_MAC_REG_CAM_TXKEY		(AR9170_MAC_REG_BASE + 0x740)
+#define	AR9170_MAC_REG_CAM_RXKEY		(AR9170_MAC_REG_BASE + 0x750)
+
+#define	AR9170_MAC_REG_CAM_TX_ENC_TYPE		(AR9170_MAC_REG_BASE + 0x760)
+#define	AR9170_MAC_REG_CAM_RX_ENC_TYPE		(AR9170_MAC_REG_BASE + 0x770)
+#define	AR9170_MAC_REG_CAM_TX_SERACH_HIT	(AR9170_MAC_REG_BASE + 0x780)
+#define	AR9170_MAC_REG_CAM_RX_SERACH_HIT	(AR9170_MAC_REG_BASE + 0x790)
+
+#define	AR9170_MAC_REG_AC0_CW			(AR9170_MAC_REG_BASE + 0xb00)
+#define	AR9170_MAC_REG_AC1_CW			(AR9170_MAC_REG_BASE + 0xb04)
+#define	AR9170_MAC_REG_AC2_CW			(AR9170_MAC_REG_BASE + 0xb08)
+#define	AR9170_MAC_REG_AC3_CW			(AR9170_MAC_REG_BASE + 0xb0c)
+#define	AR9170_MAC_REG_AC4_CW			(AR9170_MAC_REG_BASE + 0xb10)
+#define	AR9170_MAC_REG_AC2_AC1_AC0_AIFS		(AR9170_MAC_REG_BASE + 0xb14)
+#define	AR9170_MAC_REG_AC4_AC3_AC2_AIFS		(AR9170_MAC_REG_BASE + 0xb18)
+#define AR9170_MAC_REG_TXOP_ACK_EXTENSION	(AR9170_MAC_REG_BASE + 0xb1c)
+#define AR9170_MAC_REG_TXOP_ACK_INTERVAL	(AR9170_MAC_REG_BASE + 0xb20)
+#define AR9170_MAC_REG_CONTENTION_POINT		(AR9170_MAC_REG_BASE + 0xb24)
+#define	AR9170_MAC_REG_RETRY_MAX		(AR9170_MAC_REG_BASE + 0xb28)
+#define AR9170_MAC_REG_TID_CFACK_CFEND_RATE	(AR9170_MAC_REG_BASE + 0xb2c)
+#define	AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND	(AR9170_MAC_REG_BASE + 0xb30)
+#define AR9170_MAC_REG_TKIP_TSC			(AR9170_MAC_REG_BASE + 0xb34)
+#define AR9170_MAC_REG_TXOP_DURATION		(AR9170_MAC_REG_BASE + 0xb38)
+#define AR9170_MAC_REG_TX_QOS_THRESHOLD		(AR9170_MAC_REG_BASE + 0xb3c)
+#define	AR9170_MAC_REG_QOS_PRIORITY_VIRTUAL_CCA	(AR9170_MAC_REG_BASE + 0xb40)
+#define		AR9170_MAC_VIRTUAL_CCA_Q0		BIT(15)
+#define		AR9170_MAC_VIRTUAL_CCA_Q1		BIT(16)
+#define		AR9170_MAC_VIRTUAL_CCA_Q2		BIT(17)
+#define		AR9170_MAC_VIRTUAL_CCA_Q3		BIT(18)
+#define		AR9170_MAC_VIRTUAL_CCA_Q4		BIT(19)
+#define		AR9170_MAC_VIRTUAL_CCA_ALL		(0xf8000)
+
+#define	AR9170_MAC_REG_AC1_AC0_TXOP		(AR9170_MAC_REG_BASE + 0xb44)
+#define	AR9170_MAC_REG_AC3_AC2_TXOP		(AR9170_MAC_REG_BASE + 0xb48)
+
+#define	AR9170_MAC_REG_AMPDU_COUNT		(AR9170_MAC_REG_BASE + 0xb88)
+#define	AR9170_MAC_REG_MPDU_COUNT		(AR9170_MAC_REG_BASE + 0xb8c)
+
+#define	AR9170_MAC_REG_AMPDU_FACTOR		(AR9170_MAC_REG_BASE + 0xb9c)
+#define		AR9170_MAC_AMPDU_FACTOR			0x7f0000
+#define		AR9170_MAC_AMPDU_FACTOR_S		16
+#define	AR9170_MAC_REG_AMPDU_DENSITY		(AR9170_MAC_REG_BASE + 0xba0)
+#define		AR9170_MAC_AMPDU_DENSITY		0x7
+#define		AR9170_MAC_AMPDU_DENSITY_S		0
+
+#define	AR9170_MAC_REG_FCS_SELECT		(AR9170_MAC_REG_BASE + 0xbb0)
+#define		AR9170_MAC_FCS_SWFCS			0x1
+#define		AR9170_MAC_FCS_FIFO_PROT		0x4
+
+#define	AR9170_MAC_REG_RTS_CTS_TPC		(AR9170_MAC_REG_BASE + 0xbb4)
+#define AR9170_MAC_REG_CFEND_QOSNULL_TPC	(AR9170_MAC_REG_BASE + 0xbb8)
+
+#define	AR9170_MAC_REG_ACK_TABLE		(AR9170_MAC_REG_BASE + 0xc00)
+#define AR9170_MAC_REG_RX_CONTROL		(AR9170_MAC_REG_BASE + 0xc40)
+#define		AR9170_MAC_RX_CTRL_DEAGG		0x1
+#define		AR9170_MAC_RX_CTRL_SHORT_FILTER		0x2
+#define		AR9170_MAC_RX_CTRL_SA_DA_SEARCH		0x20
+#define		AR9170_MAC_RX_CTRL_PASS_TO_HOST		BIT(28)
+#define		AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER	BIT(30)
+
+#define AR9170_MAC_REG_RX_CONTROL_1		(AR9170_MAC_REG_BASE + 0xc44)
+
+#define	AR9170_MAC_REG_AMPDU_RX_THRESH		(AR9170_MAC_REG_BASE + 0xc50)
+
+#define	AR9170_MAC_REG_RX_MPDU			(AR9170_MAC_REG_BASE + 0xca0)
+#define	AR9170_MAC_REG_RX_DROPPED_MPDU		(AR9170_MAC_REG_BASE + 0xca4)
+#define	AR9170_MAC_REG_RX_DEL_MPDU		(AR9170_MAC_REG_BASE + 0xca8)
+#define	AR9170_MAC_REG_RX_PHY_MISC_ERROR	(AR9170_MAC_REG_BASE + 0xcac)
+#define	AR9170_MAC_REG_RX_PHY_XR_ERROR		(AR9170_MAC_REG_BASE + 0xcb0)
+#define	AR9170_MAC_REG_RX_PHY_OFDM_ERROR	(AR9170_MAC_REG_BASE + 0xcb4)
+#define	AR9170_MAC_REG_RX_PHY_CCK_ERROR		(AR9170_MAC_REG_BASE + 0xcb8)
+#define	AR9170_MAC_REG_RX_PHY_HT_ERROR		(AR9170_MAC_REG_BASE + 0xcbc)
+#define	AR9170_MAC_REG_RX_PHY_TOTAL		(AR9170_MAC_REG_BASE + 0xcc0)
+
+#define	AR9170_MAC_REG_DMA_TXQ_ADDR		(AR9170_MAC_REG_BASE + 0xd00)
+#define	AR9170_MAC_REG_DMA_TXQ_CURR_ADDR	(AR9170_MAC_REG_BASE + 0xd04)
+#define	AR9170_MAC_REG_DMA_TXQ0_ADDR		(AR9170_MAC_REG_BASE + 0xd00)
+#define	AR9170_MAC_REG_DMA_TXQ0_CURR_ADDR	(AR9170_MAC_REG_BASE + 0xd04)
+#define	AR9170_MAC_REG_DMA_TXQ1_ADDR		(AR9170_MAC_REG_BASE + 0xd08)
+#define	AR9170_MAC_REG_DMA_TXQ1_CURR_ADDR	(AR9170_MAC_REG_BASE + 0xd0c)
+#define	AR9170_MAC_REG_DMA_TXQ2_ADDR		(AR9170_MAC_REG_BASE + 0xd10)
+#define	AR9170_MAC_REG_DMA_TXQ2_CURR_ADDR	(AR9170_MAC_REG_BASE + 0xd14)
+#define	AR9170_MAC_REG_DMA_TXQ3_ADDR		(AR9170_MAC_REG_BASE + 0xd18)
+#define	AR9170_MAC_REG_DMA_TXQ3_CURR_ADDR	(AR9170_MAC_REG_BASE + 0xd1c)
+#define	AR9170_MAC_REG_DMA_TXQ4_ADDR		(AR9170_MAC_REG_BASE + 0xd20)
+#define	AR9170_MAC_REG_DMA_TXQ4_CURR_ADDR	(AR9170_MAC_REG_BASE + 0xd24)
+#define	AR9170_MAC_REG_DMA_RXQ_ADDR		(AR9170_MAC_REG_BASE + 0xd28)
+#define	AR9170_MAC_REG_DMA_RXQ_CURR_ADDR	(AR9170_MAC_REG_BASE + 0xd2c)
+
+#define	AR9170_MAC_REG_DMA_TRIGGER		(AR9170_MAC_REG_BASE + 0xd30)
+#define		AR9170_DMA_TRIGGER_TXQ0			BIT(0)
+#define		AR9170_DMA_TRIGGER_TXQ1			BIT(1)
+#define		AR9170_DMA_TRIGGER_TXQ2			BIT(2)
+#define		AR9170_DMA_TRIGGER_TXQ3			BIT(3)
+#define		AR9170_DMA_TRIGGER_TXQ4			BIT(4)
+#define		AR9170_DMA_TRIGGER_RXQ			BIT(8)
+
+#define AR9170_MAC_REG_DMA_WLAN_STATUS		(AR9170_MAC_REG_BASE + 0xd38)
+#define	AR9170_MAC_REG_DMA_STATUS		(AR9170_MAC_REG_BASE + 0xd3c)
+
+#define	AR9170_MAC_REG_TXRX_MPI			(AR9170_MAC_REG_BASE + 0xd7c)
+#define		AR9170_MAC_TXRX_MPI_TX_MPI_MASK		0x0000000f
+#define		AR9170_MAC_TXRX_MPI_TX_TO_MASK		0x0000fff0
+#define		AR9170_MAC_TXRX_MPI_RX_MPI_MASK		0x000f0000
+#define		AR9170_MAC_TXRX_MPI_RX_TO_MASK		0xfff00000
+
+#define	AR9170_MAC_REG_BCN_ADDR			(AR9170_MAC_REG_BASE + 0xd84)
+#define	AR9170_MAC_REG_BCN_LENGTH		(AR9170_MAC_REG_BASE + 0xd88)
+#define		AR9170_MAC_BCN_LENGTH_MAX		256
+
+#define AR9170_MAC_REG_BCN_STATUS		(AR9170_MAC_REG_BASE + 0xd8c)
+
+#define	AR9170_MAC_REG_BCN_PLCP			(AR9170_MAC_REG_BASE + 0xd90)
+#define	AR9170_MAC_REG_BCN_CTRL			(AR9170_MAC_REG_BASE + 0xd94)
+#define		AR9170_BCN_CTRL_READY			0x01
+#define		AR9170_BCN_CTRL_LOCK			0x02
+
+#define AR9170_MAC_REG_BCN_CURR_ADDR		(AR9170_MAC_REG_BASE + 0xd98)
+#define	AR9170_MAC_REG_BCN_COUNT		(AR9170_MAC_REG_BASE + 0xd9c)
+
+
+#define	AR9170_MAC_REG_BCN_HT1			(AR9170_MAC_REG_BASE + 0xda0)
+#define	AR9170_MAC_REG_BCN_HT2			(AR9170_MAC_REG_BASE + 0xda4)
+
+#define	AR9170_MAC_REG_DMA_TXQX_ADDR_CURR	(AR9170_MAC_REG_BASE + 0xdc0)
+
+/* Random number generator */
+#define	AR9170_RAND_REG_BASE			0x1d0000
+
+#define	AR9170_RAND_REG_NUM			(AR9170_RAND_REG_BASE + 0x000)
+#define	AR9170_RAND_REG_MODE			(AR9170_RAND_REG_BASE + 0x004)
+#define		AR9170_RAND_MODE_MANUAL			0x000
+#define		AR9170_RAND_MODE_FREE			0x001
+
+/* GPIO */
+#define	AR9170_GPIO_REG_BASE			0x1d0100
+#define	AR9170_GPIO_REG_PORT_TYPE		(AR9170_GPIO_REG_BASE + 0x000)
+#define	AR9170_GPIO_REG_PORT_DATA		(AR9170_GPIO_REG_BASE + 0x004)
+#define		AR9170_GPIO_PORT_LED_0			1
+#define		AR9170_GPIO_PORT_LED_1			2
+/* WPS Button GPIO for TP-Link TL-WN821N */
+#define		AR9170_GPIO_PORT_WPS_BUTTON_PRESSED	4
+
+/* Memory Controller */
+#define	AR9170_MC_REG_BASE			0x1d1000
+
+#define	AR9170_MC_REG_FLASH_WAIT_STATE		(AR9170_MC_REG_BASE + 0x000)
+#define	AR9170_MC_REG_SEEPROM_WP0		(AR9170_MC_REG_BASE + 0x400)
+#define	AR9170_MC_REG_SEEPROM_WP1		(AR9170_MC_REG_BASE + 0x404)
+#define	AR9170_MC_REG_SEEPROM_WP2		(AR9170_MC_REG_BASE + 0x408)
+
+/* Interrupt Controller */
+#define	AR9170_MAX_INT_SRC			9
+#define	AR9170_INT_REG_BASE			0x1d2000
+
+#define	AR9170_INT_REG_FLAG			(AR9170_INT_REG_BASE + 0x000)
+#define	AR9170_INT_REG_FIQ_MASK			(AR9170_INT_REG_BASE + 0x004)
+#define	AR9170_INT_REG_IRQ_MASK			(AR9170_INT_REG_BASE + 0x008)
+/* INT_REG_FLAG, INT_REG_FIQ_MASK and INT_REG_IRQ_MASK */
+#define		AR9170_INT_FLAG_WLAN			0x001
+#define		AR9170_INT_FLAG_PTAB_BIT		0x002
+#define		AR9170_INT_FLAG_SE_BIT			0x004
+#define		AR9170_INT_FLAG_UART_BIT		0x008
+#define		AR9170_INT_FLAG_TIMER_BIT		0x010
+#define		AR9170_INT_FLAG_EXT_BIT			0x020
+#define		AR9170_INT_FLAG_SW_BIT			0x040
+#define		AR9170_INT_FLAG_USB_BIT			0x080
+#define		AR9170_INT_FLAG_ETHERNET_BIT		0x100
+
+#define	AR9170_INT_REG_PRIORITY1		(AR9170_INT_REG_BASE + 0x00c)
+#define	AR9170_INT_REG_PRIORITY2		(AR9170_INT_REG_BASE + 0x010)
+#define	AR9170_INT_REG_PRIORITY3		(AR9170_INT_REG_BASE + 0x014)
+#define	AR9170_INT_REG_EXT_INT_CONTROL		(AR9170_INT_REG_BASE + 0x018)
+#define	AR9170_INT_REG_SW_INT_CONTROL		(AR9170_INT_REG_BASE + 0x01c)
+#define		AR9170_INT_SW_INT_ENABLE		0x1
+
+#define	AR9170_INT_REG_FIQ_ENCODE		(AR9170_INT_REG_BASE + 0x020)
+#define	AR9170_INT_INT_IRQ_ENCODE		(AR9170_INT_REG_BASE + 0x024)
+
+/* Power Management */
+#define	AR9170_PWR_REG_BASE			0x1d4000
+
+#define AR9170_PWR_REG_POWER_STATE		(AR9170_PWR_REG_BASE + 0x000)
+
+#define	AR9170_PWR_REG_RESET			(AR9170_PWR_REG_BASE + 0x004)
+#define		AR9170_PWR_RESET_COMMIT_RESET_MASK	BIT(0)
+#define		AR9170_PWR_RESET_WLAN_MASK		BIT(1)
+#define		AR9170_PWR_RESET_DMA_MASK		BIT(2)
+#define		AR9170_PWR_RESET_BRIDGE_MASK		BIT(3)
+#define		AR9170_PWR_RESET_AHB_MASK		BIT(9)
+#define		AR9170_PWR_RESET_BB_WARM_RESET		BIT(10)
+#define		AR9170_PWR_RESET_BB_COLD_RESET		BIT(11)
+#define		AR9170_PWR_RESET_ADDA_CLK_COLD_RESET	BIT(12)
+#define		AR9170_PWR_RESET_PLL			BIT(13)
+#define		AR9170_PWR_RESET_USB_PLL		BIT(14)
+
+#define	AR9170_PWR_REG_CLOCK_SEL		(AR9170_PWR_REG_BASE + 0x008)
+#define		AR9170_PWR_CLK_AHB_40MHZ		0
+#define		AR9170_PWR_CLK_AHB_20_22MHZ		1
+#define		AR9170_PWR_CLK_AHB_40_44MHZ		2
+#define		AR9170_PWR_CLK_AHB_80_88MHZ		3
+#define		AR9170_PWR_CLK_DAC_160_INV_DLY		0x70
+
+#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_REG_WATCH_DOG_MAGIC		(AR9170_PWR_REG_BASE + 0x020)
+
+/* Faraday USB Controller */
+#define	AR9170_USB_REG_BASE			0x1e1000
+
+#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_HIGHSPEED		BIT(6)
+
+#define	AR9170_USB_REG_DEVICE_ADDRESS		(AR9170_USB_REG_BASE + 0x001)
+#define		AR9170_USB_DEVICE_ADDRESS_CONFIGURE	BIT(7)
+
+#define	AR9170_USB_REG_TEST			(AR9170_USB_REG_BASE + 0x002)
+#define	AR9170_USB_REG_PHY_TEST_SELECT		(AR9170_USB_REG_BASE + 0x008)
+#define	AR9170_USB_REG_CX_CONFIG_STATUS		(AR9170_USB_REG_BASE + 0x00b)
+#define	AR9170_USB_REG_EP0_DATA			(AR9170_USB_REG_BASE + 0x00c)
+#define	AR9170_USB_REG_EP0_DATA1		(AR9170_USB_REG_BASE + 0x00c)
+#define	AR9170_USB_REG_EP0_DATA2		(AR9170_USB_REG_BASE + 0x00d)
+
+#define	AR9170_USB_REG_INTR_MASK_BYTE_0		(AR9170_USB_REG_BASE + 0x011)
+#define	AR9170_USB_REG_INTR_MASK_BYTE_1		(AR9170_USB_REG_BASE + 0x012)
+#define	AR9170_USB_REG_INTR_MASK_BYTE_2		(AR9170_USB_REG_BASE + 0x013)
+#define	AR9170_USB_REG_INTR_MASK_BYTE_3		(AR9170_USB_REG_BASE + 0x014)
+#define	AR9170_USB_REG_INTR_MASK_BYTE_4		(AR9170_USB_REG_BASE + 0x015)
+#define		AR9170_USB_INTR_DISABLE_OUT_INT		(BIT(7) | BIT(6))
+
+#define	AR9170_USB_REG_INTR_MASK_BYTE_5		(AR9170_USB_REG_BASE + 0x016)
+#define	AR9170_USB_REG_INTR_MASK_BYTE_6		(AR9170_USB_REG_BASE + 0x017)
+#define		AR9170_USB_INTR_DISABLE_IN_INT		BIT(6)
+
+#define	AR9170_USB_REG_INTR_MASK_BYTE_7		(AR9170_USB_REG_BASE + 0x018)
+
+#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_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)
+#define	AR9170_USB_REG_INTR_SOURCE_4		(AR9170_USB_REG_BASE + 0x025)
+#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_REG_EP_MAP			(AR9170_USB_REG_BASE + 0x030)
+#define	AR9170_USB_REG_EP1_MAP			(AR9170_USB_REG_BASE + 0x030)
+#define	AR9170_USB_REG_EP2_MAP			(AR9170_USB_REG_BASE + 0x031)
+#define	AR9170_USB_REG_EP3_MAP			(AR9170_USB_REG_BASE + 0x032)
+#define	AR9170_USB_REG_EP4_MAP			(AR9170_USB_REG_BASE + 0x033)
+#define	AR9170_USB_REG_EP5_MAP			(AR9170_USB_REG_BASE + 0x034)
+#define	AR9170_USB_REG_EP6_MAP			(AR9170_USB_REG_BASE + 0x035)
+#define	AR9170_USB_REG_EP7_MAP			(AR9170_USB_REG_BASE + 0x036)
+#define	AR9170_USB_REG_EP8_MAP			(AR9170_USB_REG_BASE + 0x037)
+#define	AR9170_USB_REG_EP9_MAP			(AR9170_USB_REG_BASE + 0x038)
+#define	AR9170_USB_REG_EP10_MAP			(AR9170_USB_REG_BASE + 0x039)
+
+#define	AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH	(AR9170_USB_REG_BASE + 0x03f)
+#define		AR9170_USB_EP_IN_TOGGLE			0x10
+
+#define	AR9170_USB_REG_EP_IN_MAX_SIZE_LOW	(AR9170_USB_REG_BASE + 0x03e)
+
+#define	AR9170_USB_REG_EP_OUT_MAX_SIZE_HIGH	(AR9170_USB_REG_BASE + 0x05f)
+#define		AR9170_USB_EP_OUT_TOGGLE		0x10
+
+#define	AR9170_USB_REG_EP_OUT_MAX_SIZE_LOW	(AR9170_USB_REG_BASE + 0x05e)
+
+#define	AR9170_USB_REG_EP3_BYTE_COUNT_HIGH	(AR9170_USB_REG_BASE + 0x0ae)
+#define	AR9170_USB_REG_EP3_BYTE_COUNT_LOW	(AR9170_USB_REG_BASE + 0x0be)
+#define	AR9170_USB_REG_EP4_BYTE_COUNT_HIGH	(AR9170_USB_REG_BASE + 0x0af)
+#define	AR9170_USB_REG_EP4_BYTE_COUNT_LOW	(AR9170_USB_REG_BASE + 0x0bf)
+
+#define	AR9170_USB_REG_FIFO_MAP			(AR9170_USB_REG_BASE + 0x080)
+#define	AR9170_USB_REG_FIFO0_MAP		(AR9170_USB_REG_BASE + 0x080)
+#define	AR9170_USB_REG_FIFO1_MAP		(AR9170_USB_REG_BASE + 0x081)
+#define	AR9170_USB_REG_FIFO2_MAP		(AR9170_USB_REG_BASE + 0x082)
+#define	AR9170_USB_REG_FIFO3_MAP		(AR9170_USB_REG_BASE + 0x083)
+#define	AR9170_USB_REG_FIFO4_MAP		(AR9170_USB_REG_BASE + 0x084)
+#define	AR9170_USB_REG_FIFO5_MAP		(AR9170_USB_REG_BASE + 0x085)
+#define	AR9170_USB_REG_FIFO6_MAP		(AR9170_USB_REG_BASE + 0x086)
+#define	AR9170_USB_REG_FIFO7_MAP		(AR9170_USB_REG_BASE + 0x087)
+#define	AR9170_USB_REG_FIFO8_MAP		(AR9170_USB_REG_BASE + 0x088)
+#define	AR9170_USB_REG_FIFO9_MAP		(AR9170_USB_REG_BASE + 0x089)
+
+#define	AR9170_USB_REG_FIFO_CONFIG		(AR9170_USB_REG_BASE + 0x090)
+#define	AR9170_USB_REG_FIFO0_CONFIG		(AR9170_USB_REG_BASE + 0x090)
+#define	AR9170_USB_REG_FIFO1_CONFIG		(AR9170_USB_REG_BASE + 0x091)
+#define	AR9170_USB_REG_FIFO2_CONFIG		(AR9170_USB_REG_BASE + 0x092)
+#define	AR9170_USB_REG_FIFO3_CONFIG		(AR9170_USB_REG_BASE + 0x093)
+#define	AR9170_USB_REG_FIFO4_CONFIG		(AR9170_USB_REG_BASE + 0x094)
+#define	AR9170_USB_REG_FIFO5_CONFIG		(AR9170_USB_REG_BASE + 0x095)
+#define	AR9170_USB_REG_FIFO6_CONFIG		(AR9170_USB_REG_BASE + 0x096)
+#define	AR9170_USB_REG_FIFO7_CONFIG		(AR9170_USB_REG_BASE + 0x097)
+#define	AR9170_USB_REG_FIFO8_CONFIG		(AR9170_USB_REG_BASE + 0x098)
+#define	AR9170_USB_REG_FIFO9_CONFIG		(AR9170_USB_REG_BASE + 0x099)
+
+#define	AR9170_USB_REG_EP3_DATA			(AR9170_USB_REG_BASE + 0x0f8)
+#define	AR9170_USB_REG_EP4_DATA			(AR9170_USB_REG_BASE + 0x0fc)
+
+#define	AR9170_USB_REG_FIFO_SIZE		(AR9170_USB_REG_BASE + 0x100)
+#define	AR9170_USB_REG_DMA_CTL			(AR9170_USB_REG_BASE + 0x108)
+#define		AR9170_USB_DMA_CTL_ENABLE_TO_DEVICE	BIT(0)
+#define		AR9170_USB_DMA_CTL_ENABLE_FROM_DEVICE	BIT(1)
+#define		AR9170_USB_DMA_CTL_HIGH_SPEED		BIT(2)
+#define		AR9170_USB_DMA_CTL_UP_PACKET_MODE	BIT(3)
+#define		AR9170_USB_DMA_CTL_UP_STREAM_S		4
+#define		AR9170_USB_DMA_CTL_UP_STREAM		(BIT(4) | BIT(5))
+#define		AR9170_USB_DMA_CTL_UP_STREAM_4K		(0)
+#define		AR9170_USB_DMA_CTL_UP_STREAM_8K		BIT(4)
+#define		AR9170_USB_DMA_CTL_UP_STREAM_16K	BIT(5)
+#define		AR9170_USB_DMA_CTL_UP_STREAM_32K	(BIT(4) | BIT(5))
+#define		AR9170_USB_DMA_CTL_DOWN_STREAM		BIT(6)
+
+#define	AR9170_USB_REG_DMA_STATUS		(AR9170_USB_REG_BASE + 0x10c)
+#define		AR9170_USB_DMA_STATUS_UP_IDLE		BIT(8)
+#define		AR9170_USB_DMA_STATUS_DN_IDLE		BIT(16)
+
+#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_CBUS_CTRL		(AR9170_USB_REG_BASE + 0x1f0)
+#define		AR9170_USB_CBUS_CTRL_BUFFER_END		(BIT(1))
+
+/* PCI/USB to AHB Bridge */
+#define	AR9170_PTA_REG_BASE			0x1e2000
+
+#define	AR9170_PTA_REG_CMD			(AR9170_PTA_REG_BASE + 0x000)
+#define	AR9170_PTA_REG_PARAM1			(AR9170_PTA_REG_BASE + 0x004)
+#define	AR9170_PTA_REG_PARAM2			(AR9170_PTA_REG_BASE + 0x008)
+#define	AR9170_PTA_REG_PARAM3			(AR9170_PTA_REG_BASE + 0x00c)
+#define	AR9170_PTA_REG_RSP			(AR9170_PTA_REG_BASE + 0x010)
+#define	AR9170_PTA_REG_STATUS1			(AR9170_PTA_REG_BASE + 0x014)
+#define	AR9170_PTA_REG_STATUS2			(AR9170_PTA_REG_BASE + 0x018)
+#define	AR9170_PTA_REG_STATUS3			(AR9170_PTA_REG_BASE + 0x01c)
+#define	AR9170_PTA_REG_AHB_INT_FLAG		(AR9170_PTA_REG_BASE + 0x020)
+#define	AR9170_PTA_REG_AHB_INT_MASK		(AR9170_PTA_REG_BASE + 0x024)
+#define	AR9170_PTA_REG_AHB_INT_ACK		(AR9170_PTA_REG_BASE + 0x028)
+#define	AR9170_PTA_REG_AHB_SCRATCH1		(AR9170_PTA_REG_BASE + 0x030)
+#define	AR9170_PTA_REG_AHB_SCRATCH2		(AR9170_PTA_REG_BASE + 0x034)
+#define	AR9170_PTA_REG_AHB_SCRATCH3		(AR9170_PTA_REG_BASE + 0x038)
+#define	AR9170_PTA_REG_AHB_SCRATCH4		(AR9170_PTA_REG_BASE + 0x03c)
+
+#define	AR9170_PTA_REG_SHARE_MEM_CTRL		(AR9170_PTA_REG_BASE + 0x124)
+
+/*
+ * PCI to AHB Bridge
+ */
+
+#define	AR9170_PTA_REG_INT_FLAG			(AR9170_PTA_REG_BASE + 0x100)
+#define		AR9170_PTA_INT_FLAG_DN			0x01
+#define		AR9170_PTA_INT_FLAG_UP			0x02
+#define		AR9170_PTA_INT_FLAG_CMD			0x04
+
+#define	AR9170_PTA_REG_INT_MASK			(AR9170_PTA_REG_BASE + 0x104)
+#define	AR9170_PTA_REG_DN_DMA_ADDRL		(AR9170_PTA_REG_BASE + 0x108)
+#define	AR9170_PTA_REG_DN_DMA_ADDRH		(AR9170_PTA_REG_BASE + 0x10c)
+#define	AR9170_PTA_REG_UP_DMA_ADDRL		(AR9170_PTA_REG_BASE + 0x110)
+#define	AR9170_PTA_REG_UP_DMA_ADDRH		(AR9170_PTA_REG_BASE + 0x114)
+#define	AR9170_PTA_REG_DN_PEND_TIME		(AR9170_PTA_REG_BASE + 0x118)
+#define	AR9170_PTA_REG_UP_PEND_TIME		(AR9170_PTA_REG_BASE + 0x11c)
+#define	AR9170_PTA_REG_CONTROL			(AR9170_PTA_REG_BASE + 0x120)
+#define		AR9170_PTA_CTRL_4_BEAT_BURST		0x00
+#define		AR9170_PTA_CTRL_8_BEAT_BURST		0x01
+#define		AR9170_PTA_CTRL_16_BEAT_BURST		0x02
+#define		AR9170_PTA_CTRL_LOOPBACK_MODE		0x10
+
+#define	AR9170_PTA_REG_MEM_CTRL			(AR9170_PTA_REG_BASE + 0x124)
+#define	AR9170_PTA_REG_MEM_ADDR			(AR9170_PTA_REG_BASE + 0x128)
+#define	AR9170_PTA_REG_DN_DMA_TRIGGER		(AR9170_PTA_REG_BASE + 0x12c)
+#define	AR9170_PTA_REG_UP_DMA_TRIGGER		(AR9170_PTA_REG_BASE + 0x130)
+#define	AR9170_PTA_REG_DMA_STATUS		(AR9170_PTA_REG_BASE + 0x134)
+#define	AR9170_PTA_REG_DN_CURR_ADDRL		(AR9170_PTA_REG_BASE + 0x138)
+#define	AR9170_PTA_REG_DN_CURR_ADDRH		(AR9170_PTA_REG_BASE + 0x13c)
+#define	AR9170_PTA_REG_UP_CURR_ADDRL		(AR9170_PTA_REG_BASE + 0x140)
+#define	AR9170_PTA_REG_UP_CURR_ADDRH		(AR9170_PTA_REG_BASE + 0x144)
+#define	AR9170_PTA_REG_DMA_MODE_CTRL		(AR9170_PTA_REG_BASE + 0x148)
+#define		AR9170_PTA_DMA_MODE_CTRL_RESET		BIT(0)
+#define		AR9170_PTA_DMA_MODE_CTRL_DISABLE_USB	BIT(1)
+
+/* Protocol Controller Module */
+#define	AR9170_MAC_REG_PC_REG_BASE		(AR9170_MAC_REG_BASE + 0xe00)
+
+
+#define	AR9170_NUM_LEDS				2
+
+/* CAM */
+#define	AR9170_CAM_MAX_USER			64
+#define	AR9170_CAM_MAX_KEY_LENGTH		16
+
+#define AR9170_SRAM_OFFSET		0x100000
+#define AR9170_SRAM_SIZE		0x18000
+
+#define AR9170_PRAM_OFFSET		0x200000
+#define AR9170_PRAM_SIZE		0x8000
+
+enum cpu_clock {
+	AHB_STATIC_40MHZ = 0,
+	AHB_GMODE_22MHZ = 1,
+	AHB_AMODE_20MHZ = 1,
+	AHB_GMODE_44MHZ = 2,
+	AHB_AMODE_40MHZ = 2,
+	AHB_GMODE_88MHZ = 3,
+	AHB_AMODE_80MHZ = 3
+};
+
+/* USB endpoints */
+enum ar9170_usb_ep {
+	/*
+	 * Control EP is always EP 0 (USB SPEC)
+	 *
+	 * The weird thing is: the original firmware has a few
+	 * comments that suggest that the actual EP numbers
+	 * are in the 1 to 10 range?!
+	 */
+	AR9170_USB_EP_CTRL		= 0,
+
+	AR9170_USB_EP_TX,
+	AR9170_USB_EP_RX,
+	AR9170_USB_EP_IRQ,
+	AR9170_USB_EP_CMD,
+	AR9170_USB_NUM_EXTRA_EP		= 4,
+
+	__AR9170_USB_NUM_EP,
+
+	__AR9170_USB_NUM_MAX_EP		= 10
+};
+
+enum ar9170_usb_fifo {
+	__AR9170_USB_NUM_MAX_FIFO	= 10
+};
+
+enum ar9170_tx_queues {
+	AR9170_TXQ0	= 0,
+	AR9170_TXQ1,
+	AR9170_TXQ2,
+	AR9170_TXQ3,
+	AR9170_TXQ_SPECIAL,
+
+	/* keep last */
+	__AR9170_NUM_TX_QUEUES = 5
+};
+
+#define	AR9170_TX_STREAM_TAG		0x697e
+#define	AR9170_RX_STREAM_TAG		0x4e00
+#define	AR9170_RX_STREAM_MAX_SIZE	0xffff
+
+struct ar9170_stream {
+	__le16 length;
+	__le16 tag;
+
+	u8 payload[0];
+};
+
+#define AR9170_MAX_ACKTABLE_ENTRIES			8
+#define AR9170_MAX_VIRTUAL_MAC				7
+
+#define	AR9170_USB_EP_CTRL_MAX				64
+#define	AR9170_USB_EP_TX_MAX				512
+#define	AR9170_USB_EP_RX_MAX				512
+#define	AR9170_USB_EP_IRQ_MAX				64
+#define	AR9170_USB_EP_CMD_MAX				64
+
+/* Trigger PRETBTT interrupt 6 Kus earlier */
+#define CARL9170_PRETBTT_KUS				6
+
+#define	AR5416_MAX_RATE_POWER				63
+
+#define SET_VAL(reg, value, newvalue)					\
+	(value = ((value) & ~reg) | (((newvalue) << reg##_S) & reg))
+
+#define SET_CONSTVAL(reg, newvalue)					\
+	(((newvalue) << reg##_S) & reg)
+
+#define MOD_VAL(reg, value, newvalue)					\
+	(((value) & ~reg) | (((newvalue) << reg##_S) & reg))
+#endif	/* __CARL9170_SHARED_HW_H */
diff --git a/drivers/net/wireless/ath/carl9170/led.c b/drivers/net/wireless/ath/carl9170/led.c
new file mode 100644
index 0000000..4bb2cbd
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/led.c
@@ -0,0 +1,190 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * LED handling
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparer <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 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 "carl9170.h"
+#include "cmd.h"
+
+int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state)
+{
+	return carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_DATA, led_state);
+}
+
+int carl9170_led_init(struct ar9170 *ar)
+{
+	int err;
+
+	/* disable LEDs */
+	/* GPIO [0/1 mode: output, 2/3: input] */
+	err = carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3);
+	if (err)
+		goto out;
+
+	/* GPIO 0/1 value: off */
+	err = carl9170_led_set_state(ar, 0);
+
+out:
+	return err;
+}
+
+#ifdef CONFIG_CARL9170_LEDS
+static void carl9170_led_update(struct work_struct *work)
+{
+	struct ar9170 *ar = container_of(work, struct ar9170, led_work.work);
+	int i, tmp = 300, blink_delay = 1000;
+	u32 led_val = 0;
+	bool rerun = false;
+
+	if (!IS_ACCEPTING_CMD(ar))
+		return;
+
+	mutex_lock(&ar->mutex);
+	for (i = 0; i < AR9170_NUM_LEDS; i++) {
+		if (ar->leds[i].registered) {
+			if (ar->leds[i].last_state ||
+			    ar->leds[i].toggled) {
+
+				if (ar->leds[i].toggled)
+					tmp = 70 + 200 / (ar->leds[i].toggled);
+
+				if (tmp < blink_delay)
+					blink_delay = tmp;
+
+				led_val |= 1 << i;
+				ar->leds[i].toggled = 0;
+				rerun = true;
+			}
+		}
+	}
+
+	carl9170_led_set_state(ar, led_val);
+	mutex_unlock(&ar->mutex);
+
+	if (!rerun)
+		return;
+
+	ieee80211_queue_delayed_work(ar->hw,
+				     &ar->led_work,
+				     msecs_to_jiffies(blink_delay));
+}
+
+static void carl9170_led_set_brightness(struct led_classdev *led,
+					enum led_brightness brightness)
+{
+	struct carl9170_led *arl = container_of(led, struct carl9170_led, l);
+	struct ar9170 *ar = arl->ar;
+
+	if (!arl->registered)
+		return;
+
+	if (arl->last_state != !!brightness) {
+		arl->toggled++;
+		arl->last_state = !!brightness;
+	}
+
+	if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
+		ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10);
+}
+
+static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name,
+				     char *trigger)
+{
+	int err;
+
+	snprintf(ar->leds[i].name, sizeof(ar->leds[i].name),
+		 "carl9170-%s::%s", wiphy_name(ar->hw->wiphy), name);
+
+	ar->leds[i].ar = ar;
+	ar->leds[i].l.name = ar->leds[i].name;
+	ar->leds[i].l.brightness_set = carl9170_led_set_brightness;
+	ar->leds[i].l.brightness = 0;
+	ar->leds[i].l.default_trigger = trigger;
+
+	err = led_classdev_register(wiphy_dev(ar->hw->wiphy),
+				    &ar->leds[i].l);
+	if (err) {
+		wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n",
+			ar->leds[i].name, err);
+	} else {
+		ar->leds[i].registered = true;
+	}
+
+	return err;
+}
+
+void carl9170_led_unregister(struct ar9170 *ar)
+{
+	int i;
+
+	for (i = 0; i < AR9170_NUM_LEDS; i++)
+		if (ar->leds[i].registered) {
+			led_classdev_unregister(&ar->leds[i].l);
+			ar->leds[i].registered = false;
+			ar->leds[i].toggled = 0;
+		}
+
+	cancel_delayed_work_sync(&ar->led_work);
+}
+
+int carl9170_led_register(struct ar9170 *ar)
+{
+	int err;
+
+	INIT_DELAYED_WORK(&ar->led_work, carl9170_led_update);
+
+	err = carl9170_led_register_led(ar, 0, "tx",
+					ieee80211_get_tx_led_name(ar->hw));
+	if (err)
+		goto fail;
+
+	if (ar->features & CARL9170_ONE_LED)
+		return 0;
+
+	err = carl9170_led_register_led(ar, 1, "assoc",
+					ieee80211_get_assoc_led_name(ar->hw));
+	if (err)
+		goto fail;
+
+	return 0;
+
+fail:
+	carl9170_led_unregister(ar);
+	return err;
+}
+
+#endif /* CONFIG_CARL9170_LEDS */
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
new file mode 100644
index 0000000..2305bc2
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -0,0 +1,604 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * MAC programming
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 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 <asm/unaligned.h>
+
+#include "carl9170.h"
+#include "cmd.h"
+
+int carl9170_set_dyn_sifs_ack(struct ar9170 *ar)
+{
+	u32 val;
+
+	if (conf_is_ht40(&ar->hw->conf))
+		val = 0x010a;
+	else {
+		if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+			val = 0x105;
+		else
+			val = 0x104;
+	}
+
+	return carl9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val);
+}
+
+int carl9170_set_rts_cts_rate(struct ar9170 *ar)
+{
+	u32 rts_rate, cts_rate;
+
+	if (conf_is_ht(&ar->hw->conf)) {
+		/* 12 mbit OFDM */
+		rts_rate = 0x1da;
+		cts_rate = 0x10a;
+	} else {
+		if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+			/* 11 mbit CCK */
+			rts_rate = 033;
+			cts_rate = 003;
+		} else {
+			/* 6 mbit OFDM */
+			rts_rate = 0x1bb;
+			cts_rate = 0x10b;
+		}
+	}
+
+	return carl9170_write_reg(ar, AR9170_MAC_REG_RTS_CTS_RATE,
+				  rts_rate | (cts_rate) << 16);
+}
+
+int carl9170_set_slot_time(struct ar9170 *ar)
+{
+	struct ieee80211_vif *vif;
+	u32 slottime = 20;
+
+	rcu_read_lock();
+	vif = carl9170_get_main_vif(ar);
+	if (!vif) {
+		rcu_read_unlock();
+		return 0;
+	}
+
+	if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) ||
+	    vif->bss_conf.use_short_slot)
+		slottime = 9;
+
+	rcu_read_unlock();
+
+	return carl9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME,
+				  slottime << 10);
+}
+
+int carl9170_set_mac_rates(struct ar9170 *ar)
+{
+	struct ieee80211_vif *vif;
+	u32 basic, mandatory;
+
+	rcu_read_lock();
+	vif = carl9170_get_main_vif(ar);
+
+	if (!vif) {
+		rcu_read_unlock();
+		return 0;
+	}
+
+	basic = (vif->bss_conf.basic_rates & 0xf);
+	basic |= (vif->bss_conf.basic_rates & 0xff0) << 4;
+	rcu_read_unlock();
+
+	if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
+		mandatory = 0xff00; /* OFDM 6/9/12/18/24/36/48/54 */
+	else
+		mandatory = 0xff0f; /* OFDM (6/9../54) + CCK (1/2/5.5/11) */
+
+	carl9170_regwrite_begin(ar);
+	carl9170_regwrite(AR9170_MAC_REG_BASIC_RATE, basic);
+	carl9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, mandatory);
+	carl9170_regwrite_finish();
+
+	return carl9170_regwrite_result();
+}
+
+int carl9170_set_qos(struct ar9170 *ar)
+{
+	carl9170_regwrite_begin(ar);
+
+	carl9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min |
+			  (ar->edcf[0].cw_max << 16));
+	carl9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min |
+			  (ar->edcf[1].cw_max << 16));
+	carl9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min |
+			  (ar->edcf[2].cw_max << 16));
+	carl9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min |
+			  (ar->edcf[3].cw_max << 16));
+	carl9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min |
+			  (ar->edcf[4].cw_max << 16));
+
+	carl9170_regwrite(AR9170_MAC_REG_AC2_AC1_AC0_AIFS,
+			  ((ar->edcf[0].aifs * 9 + 10)) |
+			  ((ar->edcf[1].aifs * 9 + 10) << 12) |
+			  ((ar->edcf[2].aifs * 9 + 10) << 24));
+	carl9170_regwrite(AR9170_MAC_REG_AC4_AC3_AC2_AIFS,
+			  ((ar->edcf[2].aifs * 9 + 10) >> 8) |
+			  ((ar->edcf[3].aifs * 9 + 10) << 4) |
+			  ((ar->edcf[4].aifs * 9 + 10) << 16));
+
+	carl9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP,
+			  ar->edcf[0].txop | ar->edcf[1].txop << 16);
+	carl9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP,
+			  ar->edcf[2].txop | ar->edcf[3].txop << 16 |
+			  ar->edcf[4].txop << 24);
+
+	carl9170_regwrite_finish();
+
+	return carl9170_regwrite_result();
+}
+
+int carl9170_init_mac(struct ar9170 *ar)
+{
+	carl9170_regwrite_begin(ar);
+
+	/* switch MAC to OTUS interface */
+	carl9170_regwrite(0x1c3600, 0x3);
+
+	carl9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40);
+
+	carl9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0x0);
+
+	carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
+			  AR9170_MAC_FTF_MONITOR);
+
+	/* enable MMIC */
+	carl9170_regwrite(AR9170_MAC_REG_SNIFFER,
+			AR9170_MAC_SNIFFER_DEFAULTS);
+
+	carl9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80);
+
+	carl9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70);
+	carl9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000);
+	carl9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10);
+
+	/* CF-END & CF-ACK rate => 24M OFDM */
+	carl9170_regwrite(AR9170_MAC_REG_TID_CFACK_CFEND_RATE, 0x59900000);
+
+	/* NAV protects ACK only (in TXOP) */
+	carl9170_regwrite(AR9170_MAC_REG_TXOP_DURATION, 0x201);
+
+	/* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */
+	/* OTUS set AM to 0x1 */
+	carl9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170);
+
+	carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
+
+	/* Aggregation MAX number and timeout */
+	carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0xa);
+	carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a00);
+
+	carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
+			  AR9170_MAC_FTF_DEFAULTS);
+
+	carl9170_regwrite(AR9170_MAC_REG_RX_CONTROL,
+			  AR9170_MAC_RX_CTRL_DEAGG |
+			  AR9170_MAC_RX_CTRL_SHORT_FILTER);
+
+	/* rate sets */
+	carl9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f);
+	carl9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f);
+	carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x0030033);
+
+	/* MIMO response control */
+	carl9170_regwrite(AR9170_MAC_REG_ACK_TPC, 0x4003c1e);
+
+	carl9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff);
+
+	/* set PHY register read timeout (??) */
+	carl9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008);
+
+	/* Disable Rx TimeOut, workaround for BB. */
+	carl9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0);
+
+	/* Set WLAN DMA interrupt mode: generate int per packet */
+	carl9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011);
+
+	carl9170_regwrite(AR9170_MAC_REG_FCS_SELECT,
+			AR9170_MAC_FCS_FIFO_PROT);
+
+	/* Disables the CF_END frame, undocumented register */
+	carl9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND,
+			0x141e0f48);
+
+	/* reset group hash table */
+	carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, 0xffffffff);
+	carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, 0xffffffff);
+
+	/* disable PRETBTT interrupt */
+	carl9170_regwrite(AR9170_MAC_REG_PRETBTT, 0x0);
+	carl9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, 0x0);
+
+	carl9170_regwrite_finish();
+
+	return carl9170_regwrite_result();
+}
+
+static int carl9170_set_mac_reg(struct ar9170 *ar,
+				const u32 reg, const u8 *mac)
+{
+	static const u8 zero[ETH_ALEN] = { 0 };
+
+	if (!mac)
+		mac = zero;
+
+	carl9170_regwrite_begin(ar);
+
+	carl9170_regwrite(reg, get_unaligned_le32(mac));
+	carl9170_regwrite(reg + 4, get_unaligned_le16(mac + 4));
+
+	carl9170_regwrite_finish();
+
+	return carl9170_regwrite_result();
+}
+
+int carl9170_mod_virtual_mac(struct ar9170 *ar, const unsigned int id,
+			     const u8 *mac)
+{
+	if (WARN_ON(id >= ar->fw.vif_num))
+		return -EINVAL;
+
+	return carl9170_set_mac_reg(ar,
+		AR9170_MAC_REG_ACK_TABLE + (id - 1) * 8, mac);
+}
+
+int carl9170_update_multicast(struct ar9170 *ar, const u64 mc_hash)
+{
+	int err;
+
+	carl9170_regwrite_begin(ar);
+	carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32);
+	carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash);
+	carl9170_regwrite_finish();
+	err = carl9170_regwrite_result();
+	if (err)
+		return err;
+
+	ar->cur_mc_hash = mc_hash;
+	return 0;
+}
+
+int carl9170_set_operating_mode(struct ar9170 *ar)
+{
+	struct ieee80211_vif *vif;
+	struct ath_common *common = &ar->common;
+	u8 *mac_addr, *bssid;
+	u32 cam_mode = AR9170_MAC_CAM_DEFAULTS;
+	u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS;
+	u32 rx_ctrl = AR9170_MAC_RX_CTRL_DEAGG |
+		      AR9170_MAC_RX_CTRL_SHORT_FILTER;
+	u32 sniffer = AR9170_MAC_SNIFFER_DEFAULTS;
+	int err = 0;
+
+	rcu_read_lock();
+	vif = carl9170_get_main_vif(ar);
+
+	if (vif) {
+		mac_addr = common->macaddr;
+		bssid = common->curbssid;
+
+		switch (vif->type) {
+		case NL80211_IFTYPE_MESH_POINT:
+		case NL80211_IFTYPE_ADHOC:
+			cam_mode |= AR9170_MAC_CAM_IBSS;
+			break;
+		case NL80211_IFTYPE_AP:
+			cam_mode |= AR9170_MAC_CAM_AP;
+
+			/* iwlagn 802.11n STA Workaround */
+			rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
+			break;
+		case NL80211_IFTYPE_WDS:
+			cam_mode |= AR9170_MAC_CAM_AP_WDS;
+			rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
+			break;
+		case NL80211_IFTYPE_STATION:
+			cam_mode |= AR9170_MAC_CAM_STA;
+			rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
+			break;
+		default:
+			WARN(1, "Unsupported operation mode %x\n", vif->type);
+			err = -EOPNOTSUPP;
+			break;
+		}
+	} else {
+		mac_addr = NULL;
+		bssid = NULL;
+	}
+	rcu_read_unlock();
+
+	if (err)
+		return err;
+
+	if (ar->rx_software_decryption)
+		enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
+
+	if (ar->sniffer_enabled) {
+		rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER;
+		sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
+		enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
+	}
+
+	err = carl9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr);
+	if (err)
+		return err;
+
+	err = carl9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid);
+	if (err)
+		return err;
+
+	carl9170_regwrite_begin(ar);
+	carl9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer);
+	carl9170_regwrite(AR9170_MAC_REG_CAM_MODE, cam_mode);
+	carl9170_regwrite(AR9170_MAC_REG_ENCRYPTION, enc_mode);
+	carl9170_regwrite(AR9170_MAC_REG_RX_CONTROL, rx_ctrl);
+	carl9170_regwrite_finish();
+
+	return carl9170_regwrite_result();
+}
+
+int carl9170_set_hwretry_limit(struct ar9170 *ar, const unsigned int max_retry)
+{
+	u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111);
+
+	return carl9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp);
+}
+
+int carl9170_set_beacon_timers(struct ar9170 *ar)
+{
+	struct ieee80211_vif *vif;
+	u32 v = 0;
+	u32 pretbtt = 0;
+
+	rcu_read_lock();
+	vif = carl9170_get_main_vif(ar);
+
+	if (vif) {
+		struct carl9170_vif_info *mvif;
+		mvif = (void *) vif->drv_priv;
+
+		if (mvif->enable_beacon && !WARN_ON(!ar->beacon_enabled)) {
+			ar->global_beacon_int = vif->bss_conf.beacon_int /
+						ar->beacon_enabled;
+
+			SET_VAL(AR9170_MAC_BCN_DTIM, v,
+				vif->bss_conf.dtim_period);
+
+			switch (vif->type) {
+			case NL80211_IFTYPE_MESH_POINT:
+			case NL80211_IFTYPE_ADHOC:
+				v |= AR9170_MAC_BCN_IBSS_MODE;
+				break;
+			case NL80211_IFTYPE_AP:
+				v |= AR9170_MAC_BCN_AP_MODE;
+				break;
+			default:
+				WARN_ON_ONCE(1);
+				break;
+			}
+		} else if (vif->type == NL80211_IFTYPE_STATION) {
+			ar->global_beacon_int = vif->bss_conf.beacon_int;
+
+			SET_VAL(AR9170_MAC_BCN_DTIM, v,
+				ar->hw->conf.ps_dtim_period);
+
+			v |= AR9170_MAC_BCN_STA_PS |
+			     AR9170_MAC_BCN_PWR_MGT;
+		}
+
+		if (ar->global_beacon_int) {
+			if (ar->global_beacon_int < 15) {
+				rcu_read_unlock();
+				return -ERANGE;
+			}
+
+			ar->global_pretbtt = ar->global_beacon_int -
+					CARL9170_PRETBTT_KUS;
+		} else {
+			ar->global_pretbtt = 0;
+		}
+	} else {
+		ar->global_beacon_int = 0;
+		ar->global_pretbtt = 0;
+	}
+
+	rcu_read_unlock();
+
+	SET_VAL(AR9170_MAC_BCN_PERIOD, v, ar->global_beacon_int);
+	SET_VAL(AR9170_MAC_PRETBTT, pretbtt, ar->global_pretbtt);
+	SET_VAL(AR9170_MAC_PRETBTT2, pretbtt, ar->global_pretbtt);
+
+	carl9170_regwrite_begin(ar);
+	carl9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt);
+	carl9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v);
+	carl9170_regwrite_finish();
+	return carl9170_regwrite_result();
+}
+
+int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
+{
+	struct sk_buff *skb;
+	struct carl9170_vif_info *cvif;
+	__le32 *data, *old = NULL;
+	u32 word, off, addr, len;
+	int i = 0, err = 0;
+
+	rcu_read_lock();
+	cvif = rcu_dereference(ar->beacon_iter);
+retry:
+	if (ar->vifs == 0 || !cvif)
+		goto out_unlock;
+
+	list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
+		if (cvif->active && cvif->enable_beacon)
+			goto found;
+	}
+
+	if (!ar->beacon_enabled || i++)
+		goto out_unlock;
+
+	goto retry;
+
+found:
+	rcu_assign_pointer(ar->beacon_iter, cvif);
+
+	skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
+		NULL, NULL);
+
+	if (!skb) {
+		err = -ENOMEM;
+		goto out_unlock;
+	}
+
+	spin_lock_bh(&ar->beacon_lock);
+	data = (__le32 *)skb->data;
+	if (cvif->beacon)
+		old = (__le32 *)cvif->beacon->data;
+
+	off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX;
+	addr = ar->fw.beacon_addr + off;
+	len = roundup(skb->len + FCS_LEN, 4);
+
+	if ((off + len) > ar->fw.beacon_max_len) {
+		if (net_ratelimit()) {
+			wiphy_err(ar->hw->wiphy, "beacon does not "
+				  "fit into device memory!\n");
+		}
+
+		spin_unlock_bh(&ar->beacon_lock);
+		dev_kfree_skb_any(skb);
+		err = -EINVAL;
+		goto out_unlock;
+	}
+
+	if (len > AR9170_MAC_BCN_LENGTH_MAX) {
+		if (net_ratelimit()) {
+			wiphy_err(ar->hw->wiphy, "no support for beacons "
+				"bigger than %d (yours:%d).\n",
+				 AR9170_MAC_BCN_LENGTH_MAX, len);
+		}
+
+		spin_unlock_bh(&ar->beacon_lock);
+		dev_kfree_skb_any(skb);
+		err = -EMSGSIZE;
+		goto out_unlock;
+	}
+
+	carl9170_async_regwrite_begin(ar);
+
+	/* XXX: use skb->cb info */
+	if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+		carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
+				((skb->len + FCS_LEN) << (3 + 16)) + 0x0400);
+	} else {
+		carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
+				((skb->len + FCS_LEN) << 16) + 0x001b);
+	}
+
+	for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
+		/*
+		 * XXX: This accesses beyond skb data for up
+		 *	to the last 3 bytes!!
+		 */
+
+		if (old && (data[i] == old[i]))
+			continue;
+
+		word = le32_to_cpu(data[i]);
+		carl9170_async_regwrite(addr + 4 * i, word);
+	}
+	carl9170_async_regwrite_finish();
+
+	dev_kfree_skb_any(cvif->beacon);
+	cvif->beacon = NULL;
+
+	err = carl9170_async_regwrite_result();
+	if (!err)
+		cvif->beacon = skb;
+	spin_unlock_bh(&ar->beacon_lock);
+	if (err)
+		goto out_unlock;
+
+	if (submit) {
+		err = carl9170_bcn_ctrl(ar, cvif->id,
+					CARL9170_BCN_CTRL_CAB_TRIGGER,
+					addr, skb->len + FCS_LEN);
+
+		if (err)
+			goto out_unlock;
+	}
+out_unlock:
+	rcu_read_unlock();
+	return err;
+}
+
+int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
+			const u8 ktype, const u8 keyidx, const u8 *keydata,
+			const int keylen)
+{
+	struct carl9170_set_key_cmd key = { };
+	static const u8 bcast[ETH_ALEN] = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+	mac = mac ? : bcast;
+
+	key.user = cpu_to_le16(id);
+	key.keyId = cpu_to_le16(keyidx);
+	key.type = cpu_to_le16(ktype);
+	memcpy(&key.macAddr, mac, ETH_ALEN);
+	if (keydata)
+		memcpy(&key.key, keydata, keylen);
+
+	return carl9170_exec_cmd(ar, CARL9170_CMD_EKEY,
+		sizeof(key), (u8 *)&key, 0, NULL);
+}
+
+int carl9170_disable_key(struct ar9170 *ar, const u8 id)
+{
+	struct carl9170_disable_key_cmd key = { };
+
+	key.user = cpu_to_le16(id);
+
+	return carl9170_exec_cmd(ar, CARL9170_CMD_DKEY,
+		sizeof(key), (u8 *)&key, 0, NULL);
+}
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
new file mode 100644
index 0000000..3cc99f3
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -0,0 +1,1891 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * mac80211 interaction code
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 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/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/random.h>
+#include <net/mac80211.h>
+#include <net/cfg80211.h>
+#include "hw.h"
+#include "carl9170.h"
+#include "cmd.h"
+
+static int modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware crypto offload.");
+
+int modparam_noht;
+module_param_named(noht, modparam_noht, int, S_IRUGO);
+MODULE_PARM_DESC(noht, "Disable MPDU aggregation.");
+
+#define RATE(_bitrate, _hw_rate, _txpidx, _flags) {	\
+	.bitrate	= (_bitrate),			\
+	.flags		= (_flags),			\
+	.hw_value	= (_hw_rate) | (_txpidx) << 4,	\
+}
+
+struct ieee80211_rate __carl9170_ratetable[] = {
+	RATE(10, 0, 0, 0),
+	RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(60, 0xb, 0, 0),
+	RATE(90, 0xf, 0, 0),
+	RATE(120, 0xa, 0, 0),
+	RATE(180, 0xe, 0, 0),
+	RATE(240, 0x9, 0, 0),
+	RATE(360, 0xd, 1, 0),
+	RATE(480, 0x8, 2, 0),
+	RATE(540, 0xc, 3, 0),
+};
+#undef RATE
+
+#define carl9170_g_ratetable	(__carl9170_ratetable + 0)
+#define carl9170_g_ratetable_size	12
+#define carl9170_a_ratetable	(__carl9170_ratetable + 4)
+#define carl9170_a_ratetable_size	8
+
+/*
+ * NB: The hw_value is used as an index into the carl9170_phy_freq_params
+ *     array in phy.c so that we don't have to do frequency lookups!
+ */
+#define CHAN(_freq, _idx) {		\
+	.center_freq	= (_freq),	\
+	.hw_value	= (_idx),	\
+	.max_power	= 18, /* XXX */	\
+}
+
+static struct ieee80211_channel carl9170_2ghz_chantable[] = {
+	CHAN(2412,  0),
+	CHAN(2417,  1),
+	CHAN(2422,  2),
+	CHAN(2427,  3),
+	CHAN(2432,  4),
+	CHAN(2437,  5),
+	CHAN(2442,  6),
+	CHAN(2447,  7),
+	CHAN(2452,  8),
+	CHAN(2457,  9),
+	CHAN(2462, 10),
+	CHAN(2467, 11),
+	CHAN(2472, 12),
+	CHAN(2484, 13),
+};
+
+static struct ieee80211_channel carl9170_5ghz_chantable[] = {
+	CHAN(4920, 14),
+	CHAN(4940, 15),
+	CHAN(4960, 16),
+	CHAN(4980, 17),
+	CHAN(5040, 18),
+	CHAN(5060, 19),
+	CHAN(5080, 20),
+	CHAN(5180, 21),
+	CHAN(5200, 22),
+	CHAN(5220, 23),
+	CHAN(5240, 24),
+	CHAN(5260, 25),
+	CHAN(5280, 26),
+	CHAN(5300, 27),
+	CHAN(5320, 28),
+	CHAN(5500, 29),
+	CHAN(5520, 30),
+	CHAN(5540, 31),
+	CHAN(5560, 32),
+	CHAN(5580, 33),
+	CHAN(5600, 34),
+	CHAN(5620, 35),
+	CHAN(5640, 36),
+	CHAN(5660, 37),
+	CHAN(5680, 38),
+	CHAN(5700, 39),
+	CHAN(5745, 40),
+	CHAN(5765, 41),
+	CHAN(5785, 42),
+	CHAN(5805, 43),
+	CHAN(5825, 44),
+	CHAN(5170, 45),
+	CHAN(5190, 46),
+	CHAN(5210, 47),
+	CHAN(5230, 48),
+};
+#undef CHAN
+
+#define CARL9170_HT_CAP							\
+{									\
+	.ht_supported	= true,						\
+	.cap		= IEEE80211_HT_CAP_MAX_AMSDU |			\
+			  IEEE80211_HT_CAP_SUP_WIDTH_20_40 |		\
+			  IEEE80211_HT_CAP_SGI_40 |			\
+			  IEEE80211_HT_CAP_DSSSCCK40 |			\
+			  IEEE80211_HT_CAP_SM_PS,			\
+	.ampdu_factor	= IEEE80211_HT_MAX_AMPDU_64K,			\
+	.ampdu_density	= IEEE80211_HT_MPDU_DENSITY_8,			\
+	.mcs		= {						\
+		.rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, },	\
+		.rx_highest = cpu_to_le16(300),				\
+		.tx_params = IEEE80211_HT_MCS_TX_DEFINED,		\
+	},								\
+}
+
+static struct ieee80211_supported_band carl9170_band_2GHz = {
+	.channels	= carl9170_2ghz_chantable,
+	.n_channels	= ARRAY_SIZE(carl9170_2ghz_chantable),
+	.bitrates	= carl9170_g_ratetable,
+	.n_bitrates	= carl9170_g_ratetable_size,
+	.ht_cap		= CARL9170_HT_CAP,
+};
+
+static struct ieee80211_supported_band carl9170_band_5GHz = {
+	.channels	= carl9170_5ghz_chantable,
+	.n_channels	= ARRAY_SIZE(carl9170_5ghz_chantable),
+	.bitrates	= carl9170_a_ratetable,
+	.n_bitrates	= carl9170_a_ratetable_size,
+	.ht_cap		= CARL9170_HT_CAP,
+};
+
+static void carl9170_ampdu_gc(struct ar9170 *ar)
+{
+	struct carl9170_sta_tid *tid_info;
+	LIST_HEAD(tid_gc);
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(tid_info, &ar->tx_ampdu_list, list) {
+		spin_lock_bh(&ar->tx_ampdu_list_lock);
+		if (tid_info->state == CARL9170_TID_STATE_SHUTDOWN) {
+			tid_info->state = CARL9170_TID_STATE_KILLED;
+			list_del_rcu(&tid_info->list);
+			ar->tx_ampdu_list_len--;
+			list_add_tail(&tid_info->tmp_list, &tid_gc);
+		}
+		spin_unlock_bh(&ar->tx_ampdu_list_lock);
+
+	}
+	rcu_assign_pointer(ar->tx_ampdu_iter, tid_info);
+	rcu_read_unlock();
+
+	synchronize_rcu();
+
+	while (!list_empty(&tid_gc)) {
+		struct sk_buff *skb;
+		tid_info = list_first_entry(&tid_gc, struct carl9170_sta_tid,
+					    tmp_list);
+
+		while ((skb = __skb_dequeue(&tid_info->queue)))
+			carl9170_tx_status(ar, skb, false);
+
+		list_del_init(&tid_info->tmp_list);
+		kfree(tid_info);
+	}
+}
+
+static void carl9170_flush(struct ar9170 *ar, bool drop_queued)
+{
+	if (drop_queued) {
+		int i;
+
+		/*
+		 * We can only drop frames which have not been uploaded
+		 * to the device yet.
+		 */
+
+		for (i = 0; i < ar->hw->queues; i++) {
+			struct sk_buff *skb;
+
+			while ((skb = skb_dequeue(&ar->tx_pending[i]))) {
+				struct ieee80211_tx_info *info;
+
+				info = IEEE80211_SKB_CB(skb);
+				if (info->flags & IEEE80211_TX_CTL_AMPDU)
+					atomic_dec(&ar->tx_ampdu_upload);
+
+				carl9170_tx_status(ar, skb, false);
+			}
+		}
+	}
+
+	/* Wait for all other outstanding frames to timeout. */
+	if (atomic_read(&ar->tx_total_queued))
+		WARN_ON(wait_for_completion_timeout(&ar->tx_flush, HZ) == 0);
+}
+
+static void carl9170_flush_ba(struct ar9170 *ar)
+{
+	struct sk_buff_head free;
+	struct carl9170_sta_tid *tid_info;
+	struct sk_buff *skb;
+
+	__skb_queue_head_init(&free);
+
+	rcu_read_lock();
+	spin_lock_bh(&ar->tx_ampdu_list_lock);
+	list_for_each_entry_rcu(tid_info, &ar->tx_ampdu_list, list) {
+		if (tid_info->state > CARL9170_TID_STATE_SUSPEND) {
+			tid_info->state = CARL9170_TID_STATE_SUSPEND;
+
+			spin_lock(&tid_info->lock);
+			while ((skb = __skb_dequeue(&tid_info->queue)))
+				__skb_queue_tail(&free, skb);
+			spin_unlock(&tid_info->lock);
+		}
+	}
+	spin_unlock_bh(&ar->tx_ampdu_list_lock);
+	rcu_read_unlock();
+
+	while ((skb = __skb_dequeue(&free)))
+		carl9170_tx_status(ar, skb, false);
+}
+
+static void carl9170_zap_queues(struct ar9170 *ar)
+{
+	struct carl9170_vif_info *cvif;
+	unsigned int i;
+
+	carl9170_ampdu_gc(ar);
+
+	carl9170_flush_ba(ar);
+	carl9170_flush(ar, true);
+
+	for (i = 0; i < ar->hw->queues; i++) {
+		spin_lock_bh(&ar->tx_status[i].lock);
+		while (!skb_queue_empty(&ar->tx_status[i])) {
+			struct sk_buff *skb;
+
+			skb = skb_peek(&ar->tx_status[i]);
+			carl9170_tx_get_skb(skb);
+			spin_unlock_bh(&ar->tx_status[i].lock);
+			carl9170_tx_drop(ar, skb);
+			spin_lock_bh(&ar->tx_status[i].lock);
+			carl9170_tx_put_skb(skb);
+		}
+		spin_unlock_bh(&ar->tx_status[i].lock);
+	}
+
+	BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_SOFT < 1);
+	BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_HARD < CARL9170_NUM_TX_LIMIT_SOFT);
+	BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_HARD >= CARL9170_BAW_BITS);
+
+	/* reinitialize queues statistics */
+	memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
+	for (i = 0; i < ar->hw->queues; i++)
+		ar->tx_stats[i].limit = CARL9170_NUM_TX_LIMIT_HARD;
+
+	for (i = 0; i < DIV_ROUND_UP(ar->fw.mem_blocks, BITS_PER_LONG); i++)
+		ar->mem_bitmap[i] = 0;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(cvif, &ar->vif_list, list) {
+		spin_lock_bh(&ar->beacon_lock);
+		dev_kfree_skb_any(cvif->beacon);
+		cvif->beacon = NULL;
+		spin_unlock_bh(&ar->beacon_lock);
+	}
+	rcu_read_unlock();
+
+	atomic_set(&ar->tx_ampdu_upload, 0);
+	atomic_set(&ar->tx_ampdu_scheduler, 0);
+	atomic_set(&ar->tx_total_pending, 0);
+	atomic_set(&ar->tx_total_queued, 0);
+	atomic_set(&ar->mem_free_blocks, ar->fw.mem_blocks);
+}
+
+#define CARL9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop)		\
+do {									\
+	queue.aifs = ai_fs;						\
+	queue.cw_min = cwmin;						\
+	queue.cw_max = cwmax;						\
+	queue.txop = _txop;						\
+} while (0)
+
+static int carl9170_op_start(struct ieee80211_hw *hw)
+{
+	struct ar9170 *ar = hw->priv;
+	int err, i;
+
+	mutex_lock(&ar->mutex);
+
+	carl9170_zap_queues(ar);
+
+	/* reset QoS defaults */
+	CARL9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023,  0); /* BEST EFFORT */
+	CARL9170_FILL_QUEUE(ar->edcf[1], 2, 7,    15, 94); /* VIDEO */
+	CARL9170_FILL_QUEUE(ar->edcf[2], 2, 3,     7, 47); /* VOICE */
+	CARL9170_FILL_QUEUE(ar->edcf[3], 7, 15, 1023,  0); /* BACKGROUND */
+	CARL9170_FILL_QUEUE(ar->edcf[4], 2, 3,     7,  0); /* SPECIAL */
+
+	ar->current_factor = ar->current_density = -1;
+	/* "The first key is unique." */
+	ar->usedkeys = 1;
+	ar->filter_state = 0;
+	ar->ps.last_action = jiffies;
+	ar->ps.last_slept = jiffies;
+	ar->erp_mode = CARL9170_ERP_AUTO;
+	ar->rx_software_decryption = false;
+	ar->disable_offload = false;
+
+	for (i = 0; i < ar->hw->queues; i++) {
+		ar->queue_stop_timeout[i] = jiffies;
+		ar->max_queue_stop_timeout[i] = 0;
+	}
+
+	atomic_set(&ar->mem_allocs, 0);
+
+	err = carl9170_usb_open(ar);
+	if (err)
+		goto out;
+
+	err = carl9170_init_mac(ar);
+	if (err)
+		goto out;
+
+	err = carl9170_set_qos(ar);
+	if (err)
+		goto out;
+
+	if (ar->fw.rx_filter) {
+		err = carl9170_rx_filter(ar, CARL9170_RX_FILTER_OTHER_RA |
+			CARL9170_RX_FILTER_CTL_OTHER | CARL9170_RX_FILTER_BAD);
+		if (err)
+			goto out;
+	}
+
+	err = carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER,
+				 AR9170_DMA_TRIGGER_RXQ);
+	if (err)
+		goto out;
+
+	/* Clear key-cache */
+	for (i = 0; i < AR9170_CAM_MAX_USER + 4; i++) {
+		err = carl9170_upload_key(ar, i, NULL, AR9170_ENC_ALG_NONE,
+					  0, NULL, 0);
+		if (err)
+			goto out;
+
+		err = carl9170_upload_key(ar, i, NULL, AR9170_ENC_ALG_NONE,
+					  1, NULL, 0);
+		if (err)
+			goto out;
+
+		if (i < AR9170_CAM_MAX_USER) {
+			err = carl9170_disable_key(ar, i);
+			if (err)
+				goto out;
+		}
+	}
+
+	carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED);
+
+	ieee80211_wake_queues(ar->hw);
+	err = 0;
+
+out:
+	mutex_unlock(&ar->mutex);
+	return err;
+}
+
+static void carl9170_cancel_worker(struct ar9170 *ar)
+{
+	cancel_delayed_work_sync(&ar->tx_janitor);
+#ifdef CONFIG_CARL9170_LEDS
+	cancel_delayed_work_sync(&ar->led_work);
+#endif /* CONFIG_CARL9170_LEDS */
+	cancel_work_sync(&ar->ps_work);
+	cancel_work_sync(&ar->ampdu_work);
+}
+
+static void carl9170_op_stop(struct ieee80211_hw *hw)
+{
+	struct ar9170 *ar = hw->priv;
+
+	carl9170_set_state_when(ar, CARL9170_STARTED, CARL9170_IDLE);
+
+	ieee80211_stop_queues(ar->hw);
+
+	mutex_lock(&ar->mutex);
+	if (IS_ACCEPTING_CMD(ar)) {
+		rcu_assign_pointer(ar->beacon_iter, NULL);
+
+		carl9170_led_set_state(ar, 0);
+
+		/* stop DMA */
+		carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER, 0);
+		carl9170_usb_stop(ar);
+	}
+
+	carl9170_zap_queues(ar);
+	mutex_unlock(&ar->mutex);
+
+	carl9170_cancel_worker(ar);
+}
+
+static void carl9170_restart_work(struct work_struct *work)
+{
+	struct ar9170 *ar = container_of(work, struct ar9170,
+					 restart_work);
+	int err;
+
+	ar->usedkeys = 0;
+	ar->filter_state = 0;
+	carl9170_cancel_worker(ar);
+
+	mutex_lock(&ar->mutex);
+	err = carl9170_usb_restart(ar);
+	if (net_ratelimit()) {
+		if (err) {
+			dev_err(&ar->udev->dev, "Failed to restart device "
+				" (%d).\n", err);
+		 } else {
+			dev_info(&ar->udev->dev, "device restarted "
+				 "successfully.\n");
+		}
+	}
+
+	carl9170_zap_queues(ar);
+	mutex_unlock(&ar->mutex);
+	if (!err) {
+		ar->restart_counter++;
+		atomic_set(&ar->pending_restarts, 0);
+
+		ieee80211_restart_hw(ar->hw);
+	} else {
+		/*
+		 * The reset was unsuccessful and the device seems to
+		 * be dead. But there's still one option: a low-level
+		 * usb subsystem reset...
+		 */
+
+		carl9170_usb_reset(ar);
+	}
+}
+
+void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
+{
+	carl9170_set_state_when(ar, CARL9170_STARTED, CARL9170_IDLE);
+
+	/*
+	 * Sometimes, an error can trigger several different reset events.
+	 * By ignoring these *surplus* reset events, the device won't be
+	 * killed again, right after it has recovered.
+	 */
+	if (atomic_inc_return(&ar->pending_restarts) > 1) {
+		dev_dbg(&ar->udev->dev, "ignoring restart (%d)\n", r);
+		return;
+	}
+
+	ieee80211_stop_queues(ar->hw);
+
+	dev_err(&ar->udev->dev, "restart device (%d)\n", r);
+
+	if (!WARN_ON(r == CARL9170_RR_NO_REASON) ||
+	    !WARN_ON(r >= __CARL9170_RR_LAST))
+		ar->last_reason = r;
+
+	if (!ar->registered)
+		return;
+
+	if (IS_ACCEPTING_CMD(ar) && !ar->needs_full_reset)
+		ieee80211_queue_work(ar->hw, &ar->restart_work);
+	else
+		carl9170_usb_reset(ar);
+
+	/*
+	 * At this point, the device instance might have vanished/disabled.
+	 * So, don't put any code which access the ar9170 struct
+	 * without proper protection.
+	 */
+}
+
+static int carl9170_init_interface(struct ar9170 *ar,
+				   struct ieee80211_vif *vif)
+{
+	struct ath_common *common = &ar->common;
+	int err;
+
+	if (!vif) {
+		WARN_ON_ONCE(IS_STARTED(ar));
+		return 0;
+	}
+
+	memcpy(common->macaddr, vif->addr, ETH_ALEN);
+
+	if (modparam_nohwcrypt ||
+	    ((vif->type != NL80211_IFTYPE_STATION) &&
+	     (vif->type != NL80211_IFTYPE_AP))) {
+		ar->rx_software_decryption = true;
+		ar->disable_offload = true;
+	}
+
+	err = carl9170_set_operating_mode(ar);
+	return err;
+}
+
+static int carl9170_op_add_interface(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif)
+{
+	struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv;
+	struct ieee80211_vif *main_vif;
+	struct ar9170 *ar = hw->priv;
+	int vif_id = -1, err = 0;
+
+	mutex_lock(&ar->mutex);
+	rcu_read_lock();
+	if (vif_priv->active) {
+		/*
+		 * Skip the interface structure initialization,
+		 * if the vif survived the _restart call.
+		 */
+		vif_id = vif_priv->id;
+		vif_priv->enable_beacon = false;
+
+		spin_lock_bh(&ar->beacon_lock);
+		dev_kfree_skb_any(vif_priv->beacon);
+		vif_priv->beacon = NULL;
+		spin_unlock_bh(&ar->beacon_lock);
+
+		goto init;
+	}
+
+	main_vif = carl9170_get_main_vif(ar);
+
+	if (main_vif) {
+		switch (main_vif->type) {
+		case NL80211_IFTYPE_STATION:
+			if (vif->type == NL80211_IFTYPE_STATION)
+				break;
+
+			err = -EBUSY;
+			rcu_read_unlock();
+
+			goto unlock;
+
+		case NL80211_IFTYPE_AP:
+			if ((vif->type == NL80211_IFTYPE_STATION) ||
+			    (vif->type == NL80211_IFTYPE_WDS) ||
+			    (vif->type == NL80211_IFTYPE_AP))
+				break;
+
+			err = -EBUSY;
+			rcu_read_unlock();
+			goto unlock;
+
+		default:
+			rcu_read_unlock();
+			goto unlock;
+		}
+	}
+
+	vif_id = bitmap_find_free_region(&ar->vif_bitmap, ar->fw.vif_num, 0);
+
+	if (vif_id < 0) {
+		rcu_read_unlock();
+
+		err = -ENOSPC;
+		goto unlock;
+	}
+
+	BUG_ON(ar->vif_priv[vif_id].id != vif_id);
+
+	vif_priv->active = true;
+	vif_priv->id = vif_id;
+	vif_priv->enable_beacon = false;
+	ar->vifs++;
+	list_add_tail_rcu(&vif_priv->list, &ar->vif_list);
+	rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif);
+
+init:
+	if (carl9170_get_main_vif(ar) == vif) {
+		rcu_assign_pointer(ar->beacon_iter, vif_priv);
+		rcu_read_unlock();
+
+		err = carl9170_init_interface(ar, vif);
+		if (err)
+			goto unlock;
+	} else {
+		err = carl9170_mod_virtual_mac(ar, vif_id, vif->addr);
+		rcu_read_unlock();
+
+		if (err)
+			goto unlock;
+	}
+
+unlock:
+	if (err && (vif_id != -1)) {
+		vif_priv->active = false;
+		bitmap_release_region(&ar->vif_bitmap, vif_id, 0);
+		ar->vifs--;
+		rcu_assign_pointer(ar->vif_priv[vif_id].vif, NULL);
+		list_del_rcu(&vif_priv->list);
+		mutex_unlock(&ar->mutex);
+		synchronize_rcu();
+	} else {
+		if (ar->vifs > 1)
+			ar->ps.off_override |= PS_OFF_VIF;
+
+		mutex_unlock(&ar->mutex);
+	}
+
+	return err;
+}
+
+static void carl9170_op_remove_interface(struct ieee80211_hw *hw,
+					 struct ieee80211_vif *vif)
+{
+	struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv;
+	struct ieee80211_vif *main_vif;
+	struct ar9170 *ar = hw->priv;
+	unsigned int id;
+
+	mutex_lock(&ar->mutex);
+
+	if (WARN_ON_ONCE(!vif_priv->active))
+		goto unlock;
+
+	ar->vifs--;
+
+	rcu_read_lock();
+	main_vif = carl9170_get_main_vif(ar);
+
+	id = vif_priv->id;
+
+	vif_priv->active = false;
+	WARN_ON(vif_priv->enable_beacon);
+	vif_priv->enable_beacon = false;
+	list_del_rcu(&vif_priv->list);
+	rcu_assign_pointer(ar->vif_priv[id].vif, NULL);
+
+	if (vif == main_vif) {
+		rcu_read_unlock();
+
+		if (ar->vifs) {
+			WARN_ON(carl9170_init_interface(ar,
+					carl9170_get_main_vif(ar)));
+		} else {
+			carl9170_set_operating_mode(ar);
+		}
+	} else {
+		rcu_read_unlock();
+
+		WARN_ON(carl9170_mod_virtual_mac(ar, id, NULL));
+	}
+
+	carl9170_update_beacon(ar, false);
+	carl9170_flush_cab(ar, id);
+
+	spin_lock_bh(&ar->beacon_lock);
+	dev_kfree_skb_any(vif_priv->beacon);
+	vif_priv->beacon = NULL;
+	spin_unlock_bh(&ar->beacon_lock);
+
+	bitmap_release_region(&ar->vif_bitmap, id, 0);
+
+	carl9170_set_beacon_timers(ar);
+
+	if (ar->vifs == 1)
+		ar->ps.off_override &= ~PS_OFF_VIF;
+
+unlock:
+	mutex_unlock(&ar->mutex);
+
+	synchronize_rcu();
+}
+
+void carl9170_ps_check(struct ar9170 *ar)
+{
+	ieee80211_queue_work(ar->hw, &ar->ps_work);
+}
+
+/* caller must hold ar->mutex */
+static int carl9170_ps_update(struct ar9170 *ar)
+{
+	bool ps = false;
+	int err = 0;
+
+	if (!ar->ps.off_override)
+		ps = (ar->hw->conf.flags & IEEE80211_CONF_PS);
+
+	if (ps != ar->ps.state) {
+		err = carl9170_powersave(ar, ps);
+		if (err)
+			return err;
+
+		if (ar->ps.state && !ps) {
+			ar->ps.sleep_ms = jiffies_to_msecs(jiffies -
+				ar->ps.last_action);
+		}
+
+		if (ps)
+			ar->ps.last_slept = jiffies;
+
+		ar->ps.last_action = jiffies;
+		ar->ps.state = ps;
+	}
+
+	return 0;
+}
+
+static void carl9170_ps_work(struct work_struct *work)
+{
+	struct ar9170 *ar = container_of(work, struct ar9170,
+					 ps_work);
+	mutex_lock(&ar->mutex);
+	if (IS_STARTED(ar))
+		WARN_ON_ONCE(carl9170_ps_update(ar) != 0);
+	mutex_unlock(&ar->mutex);
+}
+
+
+static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct ar9170 *ar = hw->priv;
+	int err = 0;
+
+	mutex_lock(&ar->mutex);
+	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
+		/* TODO */
+		err = 0;
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_PS) {
+		err = carl9170_ps_update(ar);
+		if (err)
+			goto out;
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		/* TODO */
+		err = 0;
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_SMPS) {
+		/* TODO */
+		err = 0;
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+		/* adjust slot time for 5 GHz */
+		err = carl9170_set_slot_time(ar);
+		if (err)
+			goto out;
+
+		err = carl9170_set_channel(ar, hw->conf.channel,
+			hw->conf.channel_type, CARL9170_RFI_NONE);
+		if (err)
+			goto out;
+
+		err = carl9170_set_dyn_sifs_ack(ar);
+		if (err)
+			goto out;
+
+		err = carl9170_set_rts_cts_rate(ar);
+		if (err)
+			goto out;
+	}
+
+out:
+	mutex_unlock(&ar->mutex);
+	return err;
+}
+
+static u64 carl9170_op_prepare_multicast(struct ieee80211_hw *hw,
+					 struct netdev_hw_addr_list *mc_list)
+{
+	struct netdev_hw_addr *ha;
+	u64 mchash;
+
+	/* always get broadcast frames */
+	mchash = 1ULL << (0xff >> 2);
+
+	netdev_hw_addr_list_for_each(ha, mc_list)
+		mchash |= 1ULL << (ha->addr[5] >> 2);
+
+	return mchash;
+}
+
+static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
+					 unsigned int changed_flags,
+					 unsigned int *new_flags,
+					 u64 multicast)
+{
+	struct ar9170 *ar = hw->priv;
+
+	/* mask supported flags */
+	*new_flags &= FIF_ALLMULTI | ar->rx_filter_caps;
+
+	if (!IS_ACCEPTING_CMD(ar))
+		return;
+
+	mutex_lock(&ar->mutex);
+
+	ar->filter_state = *new_flags;
+	/*
+	 * We can support more by setting the sniffer bit and
+	 * then checking the error flags, later.
+	 */
+
+	if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI)
+		multicast = ~0ULL;
+
+	if (multicast != ar->cur_mc_hash)
+		WARN_ON(carl9170_update_multicast(ar, multicast));
+
+	if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) {
+		ar->sniffer_enabled = !!(*new_flags &
+			(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS));
+
+		WARN_ON(carl9170_set_operating_mode(ar));
+	}
+
+	if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) {
+		u32 rx_filter = 0;
+
+		if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)))
+			rx_filter |= CARL9170_RX_FILTER_BAD;
+
+		if (!(*new_flags & FIF_CONTROL))
+			rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
+
+		if (!(*new_flags & FIF_PSPOLL))
+			rx_filter |= CARL9170_RX_FILTER_CTL_PSPOLL;
+
+		if (!(*new_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))) {
+			rx_filter |= CARL9170_RX_FILTER_OTHER_RA;
+			rx_filter |= CARL9170_RX_FILTER_DECRY_FAIL;
+		}
+
+		WARN_ON(carl9170_rx_filter(ar, rx_filter));
+	}
+
+	mutex_unlock(&ar->mutex);
+}
+
+
+static void carl9170_op_bss_info_changed(struct ieee80211_hw *hw,
+					 struct ieee80211_vif *vif,
+					 struct ieee80211_bss_conf *bss_conf,
+					 u32 changed)
+{
+	struct ar9170 *ar = hw->priv;
+	struct ath_common *common = &ar->common;
+	int err = 0;
+	struct carl9170_vif_info *vif_priv;
+	struct ieee80211_vif *main_vif;
+
+	mutex_lock(&ar->mutex);
+	vif_priv = (void *) vif->drv_priv;
+	main_vif = carl9170_get_main_vif(ar);
+	if (WARN_ON(!main_vif))
+		goto out;
+
+	if (changed & BSS_CHANGED_BEACON_ENABLED) {
+		struct carl9170_vif_info *iter;
+		int i = 0;
+
+		vif_priv->enable_beacon = bss_conf->enable_beacon;
+		rcu_read_lock();
+		list_for_each_entry_rcu(iter, &ar->vif_list, list) {
+			if (iter->active && iter->enable_beacon)
+				i++;
+
+		}
+		rcu_read_unlock();
+
+		ar->beacon_enabled = i;
+	}
+
+	if (changed & BSS_CHANGED_BEACON) {
+		err = carl9170_update_beacon(ar, false);
+		if (err)
+			goto out;
+	}
+
+	if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON |
+		       BSS_CHANGED_BEACON_INT)) {
+
+		if (main_vif != vif) {
+			bss_conf->beacon_int = main_vif->bss_conf.beacon_int;
+			bss_conf->dtim_period = main_vif->bss_conf.dtim_period;
+		}
+
+		/*
+		 * Therefore a hard limit for the broadcast traffic should
+		 * prevent false alarms.
+		 */
+		if (vif->type != NL80211_IFTYPE_STATION &&
+		    (bss_conf->beacon_int * bss_conf->dtim_period >=
+		     (CARL9170_QUEUE_STUCK_TIMEOUT / 2))) {
+			err = -EINVAL;
+			goto out;
+		}
+
+		err = carl9170_set_beacon_timers(ar);
+		if (err)
+			goto out;
+	}
+
+	if (changed & BSS_CHANGED_HT) {
+		/* TODO */
+		err = 0;
+		if (err)
+			goto out;
+	}
+
+	if (main_vif != vif)
+		goto out;
+
+	/*
+	 * The following settings can only be changed by the
+	 * master interface.
+	 */
+
+	if (changed & BSS_CHANGED_BSSID) {
+		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+		err = carl9170_set_operating_mode(ar);
+		if (err)
+			goto out;
+	}
+
+	if (changed & BSS_CHANGED_ASSOC) {
+		ar->common.curaid = bss_conf->aid;
+		err = carl9170_set_beacon_timers(ar);
+		if (err)
+			goto out;
+	}
+
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		err = carl9170_set_slot_time(ar);
+		if (err)
+			goto out;
+	}
+
+	if (changed & BSS_CHANGED_BASIC_RATES) {
+		err = carl9170_set_mac_rates(ar);
+		if (err)
+			goto out;
+	}
+
+out:
+	WARN_ON_ONCE(err && IS_STARTED(ar));
+	mutex_unlock(&ar->mutex);
+}
+
+static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw)
+{
+	struct ar9170 *ar = hw->priv;
+	struct carl9170_tsf_rsp tsf;
+	int err;
+
+	mutex_lock(&ar->mutex);
+	err = carl9170_exec_cmd(ar, CARL9170_CMD_READ_TSF,
+				0, NULL, sizeof(tsf), &tsf);
+	mutex_unlock(&ar->mutex);
+	if (WARN_ON(err))
+		return 0;
+
+	return le64_to_cpu(tsf.tsf_64);
+}
+
+static int carl9170_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)
+{
+	struct ar9170 *ar = hw->priv;
+	int err = 0, i;
+	u8 ktype;
+
+	if (ar->disable_offload || !vif)
+		return -EOPNOTSUPP;
+
+	/*
+	 * We have to fall back to software encryption, whenever
+	 * the user choose to participates in an IBSS or is connected
+	 * to more than one network.
+	 *
+	 * This is very unfortunate, because some machines cannot handle
+	 * the high througput speed in 802.11n networks.
+	 */
+
+	if (!is_main_vif(ar, vif))
+		goto err_softw;
+
+	/*
+	 * While the hardware supports *catch-all* key, for offloading
+	 * group-key en-/de-cryption. The way of how the hardware
+	 * decides which keyId maps to which key, remains a mystery...
+	 */
+	if ((vif->type != NL80211_IFTYPE_STATION &&
+	     vif->type != NL80211_IFTYPE_ADHOC) &&
+	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+		return -EOPNOTSUPP;
+
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+		ktype = AR9170_ENC_ALG_WEP64;
+		break;
+	case WLAN_CIPHER_SUITE_WEP104:
+		ktype = AR9170_ENC_ALG_WEP128;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		ktype = AR9170_ENC_ALG_TKIP;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		ktype = AR9170_ENC_ALG_AESCCMP;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	mutex_lock(&ar->mutex);
+	if (cmd == SET_KEY) {
+		if (!IS_STARTED(ar)) {
+			err = -EOPNOTSUPP;
+			goto out;
+		}
+
+		if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+			sta = NULL;
+
+			i = 64 + key->keyidx;
+		} else {
+			for (i = 0; i < 64; i++)
+				if (!(ar->usedkeys & BIT(i)))
+					break;
+			if (i == 64)
+				goto err_softw;
+		}
+
+		key->hw_key_idx = i;
+
+		err = carl9170_upload_key(ar, i, sta ? sta->addr : NULL,
+					  ktype, 0, key->key,
+					  min_t(u8, 16, key->keylen));
+		if (err)
+			goto out;
+
+		if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+			err = carl9170_upload_key(ar, i, sta ? sta->addr :
+						  NULL, ktype, 1,
+						  key->key + 16, 16);
+			if (err)
+				goto out;
+
+			/*
+			 * hardware is not capable generating MMIC
+			 * of fragmented frames!
+			 */
+			key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+		}
+
+		if (i < 64)
+			ar->usedkeys |= BIT(i);
+
+		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+	} else {
+		if (!IS_STARTED(ar)) {
+			/* The device is gone... together with the key ;-) */
+			err = 0;
+			goto out;
+		}
+
+		if (key->hw_key_idx < 64) {
+			ar->usedkeys &= ~BIT(key->hw_key_idx);
+		} else {
+			err = carl9170_upload_key(ar, key->hw_key_idx, NULL,
+						  AR9170_ENC_ALG_NONE, 0,
+						  NULL, 0);
+			if (err)
+				goto out;
+
+			if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+				err = carl9170_upload_key(ar, key->hw_key_idx,
+							  NULL,
+							  AR9170_ENC_ALG_NONE,
+							  1, NULL, 0);
+				if (err)
+					goto out;
+			}
+
+		}
+
+		err = carl9170_disable_key(ar, key->hw_key_idx);
+		if (err)
+			goto out;
+	}
+
+out:
+	mutex_unlock(&ar->mutex);
+	return err;
+
+err_softw:
+	if (!ar->rx_software_decryption) {
+		ar->rx_software_decryption = true;
+		carl9170_set_operating_mode(ar);
+	}
+	mutex_unlock(&ar->mutex);
+	return -ENOSPC;
+}
+
+static int carl9170_op_sta_add(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct ieee80211_sta *sta)
+{
+	struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
+	unsigned int i;
+
+	if (sta->ht_cap.ht_supported) {
+		if (sta->ht_cap.ampdu_density > 6) {
+			/*
+			 * HW does support 16us AMPDU density.
+			 * No HT-Xmit for station.
+			 */
+
+			return 0;
+		}
+
+		for (i = 0; i < CARL9170_NUM_TID; i++)
+			rcu_assign_pointer(sta_info->agg[i], NULL);
+
+		sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
+		sta_info->ht_sta = true;
+	}
+
+	return 0;
+}
+
+static int carl9170_op_sta_remove(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_sta *sta)
+{
+	struct ar9170 *ar = hw->priv;
+	struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
+	unsigned int i;
+	bool cleanup = false;
+
+	if (sta->ht_cap.ht_supported) {
+
+		sta_info->ht_sta = false;
+
+		rcu_read_lock();
+		for (i = 0; i < CARL9170_NUM_TID; i++) {
+			struct carl9170_sta_tid *tid_info;
+
+			tid_info = rcu_dereference(sta_info->agg[i]);
+			rcu_assign_pointer(sta_info->agg[i], NULL);
+
+			if (!tid_info)
+				continue;
+
+			spin_lock_bh(&ar->tx_ampdu_list_lock);
+			if (tid_info->state > CARL9170_TID_STATE_SHUTDOWN)
+				tid_info->state = CARL9170_TID_STATE_SHUTDOWN;
+			spin_unlock_bh(&ar->tx_ampdu_list_lock);
+			cleanup = true;
+		}
+		rcu_read_unlock();
+
+		if (cleanup)
+			carl9170_ampdu_gc(ar);
+	}
+
+	return 0;
+}
+
+static int carl9170_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+			       const struct ieee80211_tx_queue_params *param)
+{
+	struct ar9170 *ar = hw->priv;
+	int ret;
+
+	mutex_lock(&ar->mutex);
+	if (queue < ar->hw->queues) {
+		memcpy(&ar->edcf[ar9170_qmap[queue]], param, sizeof(*param));
+		ret = carl9170_set_qos(ar);
+	} else {
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&ar->mutex);
+	return ret;
+}
+
+static void carl9170_ampdu_work(struct work_struct *work)
+{
+	struct ar9170 *ar = container_of(work, struct ar9170,
+					 ampdu_work);
+
+	if (!IS_STARTED(ar))
+		return;
+
+	mutex_lock(&ar->mutex);
+	carl9170_ampdu_gc(ar);
+	mutex_unlock(&ar->mutex);
+}
+
+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)
+{
+	struct ar9170 *ar = hw->priv;
+	struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
+	struct carl9170_sta_tid *tid_info;
+
+	if (modparam_noht)
+		return -EOPNOTSUPP;
+
+	switch (action) {
+	case IEEE80211_AMPDU_TX_START:
+		if (!sta_info->ht_sta)
+			return -EOPNOTSUPP;
+
+		rcu_read_lock();
+		if (rcu_dereference(sta_info->agg[tid])) {
+			rcu_read_unlock();
+			return -EBUSY;
+		}
+
+		tid_info = kzalloc(sizeof(struct carl9170_sta_tid),
+				   GFP_ATOMIC);
+		if (!tid_info) {
+			rcu_read_unlock();
+			return -ENOMEM;
+		}
+
+		tid_info->hsn = tid_info->bsn = tid_info->snx = (*ssn);
+		tid_info->state = CARL9170_TID_STATE_PROGRESS;
+		tid_info->tid = tid;
+		tid_info->max = sta_info->ampdu_max_len;
+
+		INIT_LIST_HEAD(&tid_info->list);
+		INIT_LIST_HEAD(&tid_info->tmp_list);
+		skb_queue_head_init(&tid_info->queue);
+		spin_lock_init(&tid_info->lock);
+
+		spin_lock_bh(&ar->tx_ampdu_list_lock);
+		ar->tx_ampdu_list_len++;
+		list_add_tail_rcu(&tid_info->list, &ar->tx_ampdu_list);
+		rcu_assign_pointer(sta_info->agg[tid], tid_info);
+		spin_unlock_bh(&ar->tx_ampdu_list_lock);
+		rcu_read_unlock();
+
+		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+
+	case IEEE80211_AMPDU_TX_STOP:
+		rcu_read_lock();
+		tid_info = rcu_dereference(sta_info->agg[tid]);
+		if (tid_info) {
+			spin_lock_bh(&ar->tx_ampdu_list_lock);
+			if (tid_info->state > CARL9170_TID_STATE_SHUTDOWN)
+				tid_info->state = CARL9170_TID_STATE_SHUTDOWN;
+			spin_unlock_bh(&ar->tx_ampdu_list_lock);
+		}
+
+		rcu_assign_pointer(sta_info->agg[tid], NULL);
+		rcu_read_unlock();
+
+		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		ieee80211_queue_work(ar->hw, &ar->ampdu_work);
+		break;
+
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		rcu_read_lock();
+		tid_info = rcu_dereference(sta_info->agg[tid]);
+
+		sta_info->stats[tid].clear = true;
+
+		if (tid_info) {
+			bitmap_zero(tid_info->bitmap, CARL9170_BAW_SIZE);
+			tid_info->state = CARL9170_TID_STATE_IDLE;
+		}
+		rcu_read_unlock();
+
+		if (WARN_ON_ONCE(!tid_info))
+			return -EFAULT;
+
+		break;
+
+	case IEEE80211_AMPDU_RX_START:
+	case IEEE80211_AMPDU_RX_STOP:
+		/* Handled by hardware */
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_CARL9170_WPC
+static int carl9170_register_wps_button(struct ar9170 *ar)
+{
+	struct input_dev *input;
+	int err;
+
+	if (!(ar->features & CARL9170_WPS_BUTTON))
+		return 0;
+
+	input = input_allocate_device();
+	if (!input)
+		return -ENOMEM;
+
+	snprintf(ar->wps.name, sizeof(ar->wps.name), "%s WPS Button",
+		 wiphy_name(ar->hw->wiphy));
+
+	snprintf(ar->wps.phys, sizeof(ar->wps.phys),
+		 "ieee80211/%s/input0", wiphy_name(ar->hw->wiphy));
+
+	input->name = ar->wps.name;
+	input->phys = ar->wps.phys;
+	input->id.bustype = BUS_USB;
+	input->dev.parent = &ar->hw->wiphy->dev;
+
+	input_set_capability(input, EV_KEY, KEY_WPS_BUTTON);
+
+	err = input_register_device(input);
+	if (err) {
+		input_free_device(input);
+		return err;
+	}
+
+	ar->wps.pbc = input;
+	return 0;
+}
+#endif /* CONFIG_CARL9170_WPC */
+
+static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
+				struct survey_info *survey)
+{
+	struct ar9170 *ar = hw->priv;
+	int err;
+
+	if (idx != 0)
+		return -ENOENT;
+
+	mutex_lock(&ar->mutex);
+	err = carl9170_get_noisefloor(ar);
+	mutex_unlock(&ar->mutex);
+	if (err)
+		return err;
+
+	survey->channel = ar->channel;
+	survey->filled = SURVEY_INFO_NOISE_DBM;
+	survey->noise = ar->noise[0];
+	return 0;
+}
+
+static void carl9170_op_flush(struct ieee80211_hw *hw, bool drop)
+{
+	struct ar9170 *ar = hw->priv;
+	unsigned int vid;
+
+	mutex_lock(&ar->mutex);
+	for_each_set_bit(vid, &ar->vif_bitmap, ar->fw.vif_num)
+		carl9170_flush_cab(ar, vid);
+
+	carl9170_flush(ar, drop);
+	mutex_unlock(&ar->mutex);
+}
+
+static int carl9170_op_get_stats(struct ieee80211_hw *hw,
+				 struct ieee80211_low_level_stats *stats)
+{
+	struct ar9170 *ar = hw->priv;
+
+	memset(stats, 0, sizeof(*stats));
+	stats->dot11ACKFailureCount = ar->tx_ack_failures;
+	stats->dot11FCSErrorCount = ar->tx_fcs_errors;
+	return 0;
+}
+
+static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif,
+				   enum sta_notify_cmd cmd,
+				   struct ieee80211_sta *sta)
+{
+	struct ar9170 *ar = hw->priv;
+	struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
+	struct sk_buff *skb, *tmp;
+	struct sk_buff_head free;
+	int i;
+
+	switch (cmd) {
+	case STA_NOTIFY_SLEEP:
+		/*
+		 * Since the peer is no longer listening, we have to return
+		 * as many SKBs as possible back to the mac80211 stack.
+		 * It will deal with the retry procedure, once the peer
+		 * has become available again.
+		 *
+		 * NB: Ideally, the driver should return the all frames in
+		 * the correct, ascending order. However, I think that this
+		 * functionality should be implemented in the stack and not
+		 * here...
+		 */
+
+		__skb_queue_head_init(&free);
+
+		if (sta->ht_cap.ht_supported) {
+			rcu_read_lock();
+			for (i = 0; i < CARL9170_NUM_TID; i++) {
+				struct carl9170_sta_tid *tid_info;
+
+				tid_info = rcu_dereference(sta_info->agg[i]);
+
+				if (!tid_info)
+					continue;
+
+				spin_lock_bh(&ar->tx_ampdu_list_lock);
+				if (tid_info->state >
+				    CARL9170_TID_STATE_SUSPEND)
+					tid_info->state =
+						CARL9170_TID_STATE_SUSPEND;
+				spin_unlock_bh(&ar->tx_ampdu_list_lock);
+
+				spin_lock_bh(&tid_info->lock);
+				while ((skb = __skb_dequeue(&tid_info->queue)))
+					__skb_queue_tail(&free, skb);
+				spin_unlock_bh(&tid_info->lock);
+			}
+			rcu_read_unlock();
+		}
+
+		for (i = 0; i < ar->hw->queues; i++) {
+			spin_lock_bh(&ar->tx_pending[i].lock);
+			skb_queue_walk_safe(&ar->tx_pending[i], skb, tmp) {
+				struct _carl9170_tx_superframe *super;
+				struct ieee80211_hdr *hdr;
+				struct ieee80211_tx_info *info;
+
+				super = (void *) skb->data;
+				hdr = (void *) super->frame_data;
+
+				if (compare_ether_addr(hdr->addr1, sta->addr))
+					continue;
+
+				__skb_unlink(skb, &ar->tx_pending[i]);
+
+				info = IEEE80211_SKB_CB(skb);
+				if (info->flags & IEEE80211_TX_CTL_AMPDU)
+					atomic_dec(&ar->tx_ampdu_upload);
+
+				carl9170_tx_status(ar, skb, false);
+			}
+			spin_unlock_bh(&ar->tx_pending[i].lock);
+		}
+
+		while ((skb = __skb_dequeue(&free)))
+			carl9170_tx_status(ar, skb, false);
+
+		break;
+
+	case STA_NOTIFY_AWAKE:
+		if (!sta->ht_cap.ht_supported)
+			return;
+
+		rcu_read_lock();
+		for (i = 0; i < CARL9170_NUM_TID; i++) {
+			struct carl9170_sta_tid *tid_info;
+
+			tid_info = rcu_dereference(sta_info->agg[i]);
+
+			if (!tid_info)
+				continue;
+
+			if ((tid_info->state == CARL9170_TID_STATE_SUSPEND))
+				tid_info->state = CARL9170_TID_STATE_IDLE;
+		}
+		rcu_read_unlock();
+		break;
+	}
+}
+
+static const struct ieee80211_ops carl9170_ops = {
+	.start			= carl9170_op_start,
+	.stop			= carl9170_op_stop,
+	.tx			= carl9170_op_tx,
+	.flush			= carl9170_op_flush,
+	.add_interface		= carl9170_op_add_interface,
+	.remove_interface	= carl9170_op_remove_interface,
+	.config			= carl9170_op_config,
+	.prepare_multicast	= carl9170_op_prepare_multicast,
+	.configure_filter	= carl9170_op_configure_filter,
+	.conf_tx		= carl9170_op_conf_tx,
+	.bss_info_changed	= carl9170_op_bss_info_changed,
+	.get_tsf		= carl9170_op_get_tsf,
+	.set_key		= carl9170_op_set_key,
+	.sta_add		= carl9170_op_sta_add,
+	.sta_remove		= carl9170_op_sta_remove,
+	.sta_notify		= carl9170_op_sta_notify,
+	.get_survey		= carl9170_op_get_survey,
+	.get_stats		= carl9170_op_get_stats,
+	.ampdu_action		= carl9170_op_ampdu_action,
+};
+
+void *carl9170_alloc(size_t priv_size)
+{
+	struct ieee80211_hw *hw;
+	struct ar9170 *ar;
+	struct sk_buff *skb;
+	int i;
+
+	/*
+	 * this buffer is used for rx stream reconstruction.
+	 * Under heavy load this device (or the transport layer?)
+	 * tends to split the streams into separate rx descriptors.
+	 */
+
+	skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL);
+	if (!skb)
+		goto err_nomem;
+
+	hw = ieee80211_alloc_hw(priv_size, &carl9170_ops);
+	if (!hw)
+		goto err_nomem;
+
+	ar = hw->priv;
+	ar->hw = hw;
+	ar->rx_failover = skb;
+
+	memset(&ar->rx_plcp, 0, sizeof(struct ar9170_rx_head));
+	ar->rx_has_plcp = false;
+
+	/*
+	 * Here's a hidden pitfall!
+	 *
+	 * All 4 AC queues work perfectly well under _legacy_ operation.
+	 * However as soon as aggregation is enabled, the traffic flow
+	 * gets very bumpy. Therefore we have to _switch_ to a
+	 * software AC with a single HW queue.
+	 */
+	hw->queues = __AR9170_NUM_TXQ;
+
+	mutex_init(&ar->mutex);
+	spin_lock_init(&ar->beacon_lock);
+	spin_lock_init(&ar->cmd_lock);
+	spin_lock_init(&ar->tx_stats_lock);
+	spin_lock_init(&ar->tx_ampdu_list_lock);
+	spin_lock_init(&ar->mem_lock);
+	spin_lock_init(&ar->state_lock);
+	atomic_set(&ar->pending_restarts, 0);
+	ar->vifs = 0;
+	for (i = 0; i < ar->hw->queues; i++) {
+		skb_queue_head_init(&ar->tx_status[i]);
+		skb_queue_head_init(&ar->tx_pending[i]);
+	}
+	INIT_WORK(&ar->ps_work, carl9170_ps_work);
+	INIT_WORK(&ar->restart_work, carl9170_restart_work);
+	INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
+	INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
+	INIT_LIST_HEAD(&ar->tx_ampdu_list);
+	rcu_assign_pointer(ar->tx_ampdu_iter,
+			   (struct carl9170_sta_tid *) &ar->tx_ampdu_list);
+
+	bitmap_zero(&ar->vif_bitmap, ar->fw.vif_num);
+	INIT_LIST_HEAD(&ar->vif_list);
+	init_completion(&ar->tx_flush);
+
+	/*
+	 * Note:
+	 * IBSS/ADHOC and AP mode are only enabled, if the firmware
+	 * supports these modes. The code which will add the
+	 * additional interface_modes is in fw.c.
+	 */
+	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+	hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
+		     IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+		     IEEE80211_HW_SUPPORTS_PS |
+		     IEEE80211_HW_PS_NULLFUNC_STACK |
+		     IEEE80211_HW_SIGNAL_DBM;
+
+	if (!modparam_noht) {
+		/*
+		 * see the comment above, why we allow the user
+		 * to disable HT by a module parameter.
+		 */
+		hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
+	}
+
+	hw->extra_tx_headroom = sizeof(struct _carl9170_tx_superframe);
+	hw->sta_data_size = sizeof(struct carl9170_sta_info);
+	hw->vif_data_size = sizeof(struct carl9170_vif_info);
+
+	hw->max_rates = CARL9170_TX_MAX_RATES;
+	hw->max_rate_tries = CARL9170_TX_USER_RATE_TRIES;
+
+	for (i = 0; i < ARRAY_SIZE(ar->noise); i++)
+		ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
+
+	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+	return ar;
+
+err_nomem:
+	kfree_skb(skb);
+	return ERR_PTR(-ENOMEM);
+}
+
+static int carl9170_read_eeprom(struct ar9170 *ar)
+{
+#define RW	8	/* number of words to read at once */
+#define RB	(sizeof(u32) * RW)
+	u8 *eeprom = (void *)&ar->eeprom;
+	__le32 offsets[RW];
+	int i, j, err;
+
+	BUILD_BUG_ON(sizeof(ar->eeprom) & 3);
+
+	BUILD_BUG_ON(RB > CARL9170_MAX_CMD_LEN - 4);
+#ifndef __CHECKER__
+	/* don't want to handle trailing remains */
+	BUILD_BUG_ON(sizeof(ar->eeprom) % RB);
+#endif
+
+	for (i = 0; i < sizeof(ar->eeprom)/RB; i++) {
+		for (j = 0; j < RW; j++)
+			offsets[j] = cpu_to_le32(AR9170_EEPROM_START +
+						 RB * i + 4 * j);
+
+		err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,
+					RB, (u8 *) &offsets,
+					RB, eeprom + RB * i);
+		if (err)
+			return err;
+	}
+
+#undef RW
+#undef RB
+	return 0;
+}
+
+static int carl9170_parse_eeprom(struct ar9170 *ar)
+{
+	struct ath_regulatory *regulatory = &ar->common.regulatory;
+	unsigned int rx_streams, tx_streams, tx_params = 0;
+	int bands = 0;
+
+	if (ar->eeprom.length == cpu_to_le16(0xffff))
+		return -ENODATA;
+
+	rx_streams = hweight8(ar->eeprom.rx_mask);
+	tx_streams = hweight8(ar->eeprom.tx_mask);
+
+	if (rx_streams != tx_streams) {
+		tx_params = IEEE80211_HT_MCS_TX_RX_DIFF;
+
+		WARN_ON(!(tx_streams >= 1 && tx_streams <=
+			IEEE80211_HT_MCS_TX_MAX_STREAMS));
+
+		tx_params = (tx_streams - 1) <<
+			    IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+
+		carl9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params;
+		carl9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params;
+	}
+
+	if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
+		ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+			&carl9170_band_2GHz;
+		bands++;
+	}
+	if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
+		ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+			&carl9170_band_5GHz;
+		bands++;
+	}
+
+	/*
+	 * I measured this, a bandswitch takes roughly
+	 * 135 ms and a frequency switch about 80.
+	 *
+	 * FIXME: measure these values again once EEPROM settings
+	 *	  are used, that will influence them!
+	 */
+	if (bands == 2)
+		ar->hw->channel_change_time = 135 * 1000;
+	else
+		ar->hw->channel_change_time = 80 * 1000;
+
+	regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
+	regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
+
+	/* second part of wiphy init */
+	SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address);
+
+	return bands ? 0 : -EINVAL;
+}
+
+static int carl9170_reg_notifier(struct wiphy *wiphy,
+				 struct regulatory_request *request)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct ar9170 *ar = hw->priv;
+
+	return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
+}
+
+int carl9170_register(struct ar9170 *ar)
+{
+	struct ath_regulatory *regulatory = &ar->common.regulatory;
+	int err = 0, i;
+
+	if (WARN_ON(ar->mem_bitmap))
+		return -EINVAL;
+
+	ar->mem_bitmap = kzalloc(roundup(ar->fw.mem_blocks, BITS_PER_LONG) *
+				 sizeof(unsigned long), GFP_KERNEL);
+
+	if (!ar->mem_bitmap)
+		return -ENOMEM;
+
+	/* try to read EEPROM, init MAC addr */
+	err = carl9170_read_eeprom(ar);
+	if (err)
+		return err;
+
+	err = carl9170_fw_fix_eeprom(ar);
+	if (err)
+		return err;
+
+	err = carl9170_parse_eeprom(ar);
+	if (err)
+		return err;
+
+	err = ath_regd_init(regulatory, ar->hw->wiphy,
+			    carl9170_reg_notifier);
+	if (err)
+		return err;
+
+	if (modparam_noht) {
+		carl9170_band_2GHz.ht_cap.ht_supported = false;
+		carl9170_band_5GHz.ht_cap.ht_supported = false;
+	}
+
+	for (i = 0; i < ar->fw.vif_num; i++) {
+		ar->vif_priv[i].id = i;
+		ar->vif_priv[i].vif = NULL;
+	}
+
+	err = ieee80211_register_hw(ar->hw);
+	if (err)
+		return err;
+
+	/* mac80211 interface is now registered */
+	ar->registered = true;
+
+	if (!ath_is_world_regd(regulatory))
+		regulatory_hint(ar->hw->wiphy, regulatory->alpha2);
+
+#ifdef CONFIG_CARL9170_DEBUGFS
+	carl9170_debugfs_register(ar);
+#endif /* CONFIG_CARL9170_DEBUGFS */
+
+	err = carl9170_led_init(ar);
+	if (err)
+		goto err_unreg;
+
+#ifdef CONFIG_CARL9170_LEDS
+	err = carl9170_led_register(ar);
+	if (err)
+		goto err_unreg;
+#endif /* CONFIG_CAR9L170_LEDS */
+
+#ifdef CONFIG_CARL9170_WPC
+	err = carl9170_register_wps_button(ar);
+	if (err)
+		goto err_unreg;
+#endif /* CONFIG_CARL9170_WPC */
+
+	dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n",
+		 wiphy_name(ar->hw->wiphy));
+
+	return 0;
+
+err_unreg:
+	carl9170_unregister(ar);
+	return err;
+}
+
+void carl9170_unregister(struct ar9170 *ar)
+{
+	if (!ar->registered)
+		return;
+
+	ar->registered = false;
+
+#ifdef CONFIG_CARL9170_LEDS
+	carl9170_led_unregister(ar);
+#endif /* CONFIG_CARL9170_LEDS */
+
+#ifdef CONFIG_CARL9170_DEBUGFS
+	carl9170_debugfs_unregister(ar);
+#endif /* CONFIG_CARL9170_DEBUGFS */
+
+#ifdef CONFIG_CARL9170_WPC
+	if (ar->wps.pbc) {
+		input_unregister_device(ar->wps.pbc);
+		ar->wps.pbc = NULL;
+	}
+#endif /* CONFIG_CARL9170_WPC */
+
+	carl9170_cancel_worker(ar);
+	cancel_work_sync(&ar->restart_work);
+
+	ieee80211_unregister_hw(ar->hw);
+}
+
+void carl9170_free(struct ar9170 *ar)
+{
+	WARN_ON(ar->registered);
+	WARN_ON(IS_INITIALIZED(ar));
+
+	kfree_skb(ar->rx_failover);
+	ar->rx_failover = NULL;
+
+	kfree(ar->mem_bitmap);
+	ar->mem_bitmap = NULL;
+
+	mutex_destroy(&ar->mutex);
+
+	ieee80211_free_hw(ar->hw);
+}
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
new file mode 100644
index 0000000..89deca3
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -0,0 +1,1810 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * PHY and RF code
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 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/bitrev.h>
+#include "carl9170.h"
+#include "cmd.h"
+#include "phy.h"
+
+static int carl9170_init_power_cal(struct ar9170 *ar)
+{
+	carl9170_regwrite_begin(ar);
+
+	carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE_MAX, 0x7f);
+	carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE1, 0x3f3f3f3f);
+	carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE2, 0x3f3f3f3f);
+	carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE3, 0x3f3f3f3f);
+	carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE4, 0x3f3f3f3f);
+	carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE5, 0x3f3f3f3f);
+	carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE6, 0x3f3f3f3f);
+	carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE7, 0x3f3f3f3f);
+	carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE8, 0x3f3f3f3f);
+	carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE9, 0x3f3f3f3f);
+
+	carl9170_regwrite_finish();
+	return carl9170_regwrite_result();
+}
+
+struct carl9170_phy_init {
+	u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20;
+};
+
+static struct carl9170_phy_init ar5416_phy_init[] = {
+	{ 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+	{ 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, },
+	{ 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, },
+	{ 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, },
+	{ 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, },
+	{ 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, },
+	{ 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, },
+	{ 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, },
+	{ 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, },
+	{ 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, },
+	{ 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, },
+	{ 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+	{ 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, },
+	{ 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, },
+	{ 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, },
+	{ 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, },
+	{ 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, },
+	{ 0x1c5850, 0x6c48b4e4, 0x6d48b4e4, 0x6d48b0e4, 0x6c48b0e4, },
+	{ 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, },
+	{ 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, },
+	{ 0x1c585c, 0x31395c5e, 0x3139605e, 0x3139605e, 0x31395c5e, },
+	{ 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, },
+	{ 0x1c5864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, },
+	{ 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, },
+	{ 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, },
+	{ 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, },
+	{ 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, },
+	{ 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, },
+	{ 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, },
+	{ 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, },
+	{ 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+	{ 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, },
+	{ 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, },
+	{ 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, },
+	{ 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, },
+	{ 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, },
+	{ 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, },
+	{ 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, },
+	{ 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
+	{ 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, },
+	{ 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, },
+	{ 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+	{ 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+	{ 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, },
+	{ 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, },
+	{ 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, },
+	{ 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, },
+	{ 0x1c59bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, },
+	{ 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, },
+	{ 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, },
+	{ 0x1c59c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, },
+	{ 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, },
+	{ 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, },
+	{ 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, },
+	{ 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, },
+	{ 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, },
+	{ 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, },
+	{ 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, },
+	{ 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, },
+	{ 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, },
+	{ 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, },
+	{ 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, },
+	{ 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, },
+	{ 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, },
+	{ 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, },
+	{ 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, },
+	{ 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, },
+	{ 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, },
+	{ 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, },
+	{ 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, },
+	{ 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, },
+	{ 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, },
+	{ 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, },
+	{ 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, },
+	{ 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, },
+	{ 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, },
+	{ 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, },
+	{ 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, },
+	{ 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, },
+	{ 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, },
+	{ 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, },
+	{ 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, },
+	{ 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, },
+	{ 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, },
+	{ 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, },
+	{ 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, },
+	{ 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, },
+	{ 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, },
+	{ 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, },
+	{ 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, },
+	{ 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, },
+	{ 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, },
+	{ 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, },
+	{ 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, },
+	{ 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, },
+	{ 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, },
+	{ 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, },
+	{ 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+	{ 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, },
+	{ 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, },
+	{ 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, },
+	{ 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, },
+	{ 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, },
+	{ 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, },
+	{ 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, },
+	{ 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, },
+	{ 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, },
+	{ 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, },
+	{ 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, },
+	{ 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, },
+	{ 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, },
+	{ 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, },
+	{ 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, },
+	{ 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, },
+	{ 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, },
+	{ 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, },
+	{ 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, },
+	{ 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, },
+	{ 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, },
+	{ 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, },
+	{ 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, },
+	{ 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, },
+	{ 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, },
+	{ 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, },
+	{ 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, },
+	{ 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, },
+	{ 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, },
+	{ 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, },
+	{ 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, },
+	{ 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, },
+	{ 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, },
+	{ 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, },
+	{ 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, },
+	{ 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, },
+	{ 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, },
+	{ 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, },
+	{ 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, },
+	{ 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, },
+	{ 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, },
+	{ 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, },
+	{ 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, },
+	{ 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, },
+	{ 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
+	{ 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, },
+	{ 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, },
+	{ 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, },
+	{ 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, },
+	{ 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, },
+	{ 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, },
+	{ 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, },
+	{ 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, },
+	{ 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, },
+	{ 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, },
+	{ 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, },
+	{ 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, },
+	{ 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+	{ 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, },
+	{ 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, },
+	{ 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, },
+	{ 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, },
+	{ 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, },
+	{ 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
+	{ 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, },
+	{ 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
+	{ 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, },
+	{ 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, },
+	{ 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, },
+	{ 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, },
+	{ 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, },
+	{ 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, },
+	{ 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, },
+	{ 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, },
+	{ 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, },
+	{ 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, },
+	{ 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, },
+	{ 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, },
+	{ 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
+	{ 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
+	{ 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
+	{ 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, },
+	{ 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, },
+	{ 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, },
+	{ 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
+	{ 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, },
+	{ 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+	{ 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
+	{ 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, },
+	{ 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, },
+	{ 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, },
+	{ 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
+	{ 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
+	{ 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
+	{ 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, },
+	{ 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, },
+	{ 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
+	{ 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
+	{ 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
+/*	{ 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */
+	{ 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, },
+	{ 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, },
+	{ 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, },
+	{ 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, },
+	{ 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, },
+	{ 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, },
+	{ 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, },
+	{ 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, },
+	{ 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, },
+	{ 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, },
+	{ 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, },
+	{ 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, },
+	{ 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, },
+	{ 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, },
+	{ 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, },
+	{ 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, }
+};
+
+/*
+ * look up a certain register in ar5416_phy_init[] and return the init. value
+ * for the band and bandwidth given. Return 0 if register address not found.
+ */
+static u32 carl9170_def_val(u32 reg, bool is_2ghz, bool is_40mhz)
+{
+	unsigned int i;
+	for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) {
+		if (ar5416_phy_init[i].reg != reg)
+			continue;
+
+		if (is_2ghz) {
+			if (is_40mhz)
+				return ar5416_phy_init[i]._2ghz_40;
+			else
+				return ar5416_phy_init[i]._2ghz_20;
+		} else {
+			if (is_40mhz)
+				return ar5416_phy_init[i]._5ghz_40;
+			else
+				return ar5416_phy_init[i]._5ghz_20;
+		}
+	}
+	return 0;
+}
+
+/*
+ * initialize some phy regs from eeprom values in modal_header[]
+ * acc. to band and bandwith
+ */
+static int carl9170_init_phy_from_eeprom(struct ar9170 *ar,
+				bool is_2ghz, bool is_40mhz)
+{
+	static const u8 xpd2pd[16] = {
+		0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2,
+		0x2, 0x3, 0x7, 0x2, 0xb, 0x2, 0x2, 0x2
+	};
+	/* pointer to the modal_header acc. to band */
+	struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz];
+	u32 val;
+
+	carl9170_regwrite_begin(ar);
+
+	/* ant common control (index 0) */
+	carl9170_regwrite(AR9170_PHY_REG_SWITCH_COM,
+		le32_to_cpu(m->antCtrlCommon));
+
+	/* ant control chain 0 (index 1) */
+	carl9170_regwrite(AR9170_PHY_REG_SWITCH_CHAIN_0,
+		le32_to_cpu(m->antCtrlChain[0]));
+
+	/* ant control chain 2 (index 2) */
+	carl9170_regwrite(AR9170_PHY_REG_SWITCH_CHAIN_2,
+		le32_to_cpu(m->antCtrlChain[1]));
+
+	/* SwSettle (index 3) */
+	if (!is_40mhz) {
+		val = carl9170_def_val(AR9170_PHY_REG_SETTLING,
+				     is_2ghz, is_40mhz);
+		SET_VAL(AR9170_PHY_SETTLING_SWITCH, val, m->switchSettling);
+		carl9170_regwrite(AR9170_PHY_REG_SETTLING, val);
+	}
+
+	/* adcDesired, pdaDesired (index 4) */
+	val = carl9170_def_val(AR9170_PHY_REG_DESIRED_SZ, is_2ghz, is_40mhz);
+	SET_VAL(AR9170_PHY_DESIRED_SZ_PGA, val, m->pgaDesiredSize);
+	SET_VAL(AR9170_PHY_DESIRED_SZ_ADC, val, m->adcDesiredSize);
+	carl9170_regwrite(AR9170_PHY_REG_DESIRED_SZ, val);
+
+	/* TxEndToXpaOff, TxFrameToXpaOn (index 5) */
+	val = carl9170_def_val(AR9170_PHY_REG_RF_CTL4, is_2ghz, is_40mhz);
+	SET_VAL(AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF, val, m->txEndToXpaOff);
+	SET_VAL(AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF, val, m->txEndToXpaOff);
+	SET_VAL(AR9170_PHY_RF_CTL4_FRAME_XPAB_ON, val, m->txFrameToXpaOn);
+	SET_VAL(AR9170_PHY_RF_CTL4_FRAME_XPAA_ON, val, m->txFrameToXpaOn);
+	carl9170_regwrite(AR9170_PHY_REG_RF_CTL4, val);
+
+	/* TxEndToRxOn (index 6) */
+	val = carl9170_def_val(AR9170_PHY_REG_RF_CTL3, is_2ghz, is_40mhz);
+	SET_VAL(AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON, val, m->txEndToRxOn);
+	carl9170_regwrite(AR9170_PHY_REG_RF_CTL3, val);
+
+	/* thresh62 (index 7) */
+	val = carl9170_def_val(0x1c8864, is_2ghz, is_40mhz);
+	val = (val & ~0x7f000) | (m->thresh62 << 12);
+	carl9170_regwrite(0x1c8864, val);
+
+	/* tx/rx attenuation chain 0 (index 8) */
+	val = carl9170_def_val(AR9170_PHY_REG_RXGAIN, is_2ghz, is_40mhz);
+	SET_VAL(AR9170_PHY_RXGAIN_TXRX_ATTEN, val, m->txRxAttenCh[0]);
+	carl9170_regwrite(AR9170_PHY_REG_RXGAIN, val);
+
+	/* tx/rx attenuation chain 2 (index 9) */
+	val = carl9170_def_val(AR9170_PHY_REG_RXGAIN_CHAIN_2,
+			       is_2ghz, is_40mhz);
+	SET_VAL(AR9170_PHY_RXGAIN_TXRX_ATTEN, val, m->txRxAttenCh[1]);
+	carl9170_regwrite(AR9170_PHY_REG_RXGAIN_CHAIN_2, val);
+
+	/* tx/rx margin chain 0 (index 10) */
+	val = carl9170_def_val(AR9170_PHY_REG_GAIN_2GHZ, is_2ghz, is_40mhz);
+	SET_VAL(AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN, val, m->rxTxMarginCh[0]);
+	/* bsw margin chain 0 for 5GHz only */
+	if (!is_2ghz)
+		SET_VAL(AR9170_PHY_GAIN_2GHZ_BSW_MARGIN, val, m->bswMargin[0]);
+	carl9170_regwrite(AR9170_PHY_REG_GAIN_2GHZ, val);
+
+	/* tx/rx margin chain 2 (index 11) */
+	val = carl9170_def_val(AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2,
+			       is_2ghz, is_40mhz);
+	SET_VAL(AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN, val, m->rxTxMarginCh[1]);
+	carl9170_regwrite(AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2, val);
+
+	/* iqCall, iqCallq chain 0 (index 12) */
+	val = carl9170_def_val(AR9170_PHY_REG_TIMING_CTRL4(0),
+			       is_2ghz, is_40mhz);
+	SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, val, m->iqCalICh[0]);
+	SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, val, m->iqCalQCh[0]);
+	carl9170_regwrite(AR9170_PHY_REG_TIMING_CTRL4(0), val);
+
+	/* iqCall, iqCallq chain 2 (index 13) */
+	val = carl9170_def_val(AR9170_PHY_REG_TIMING_CTRL4(2),
+			       is_2ghz, is_40mhz);
+	SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, val, m->iqCalICh[1]);
+	SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, val, m->iqCalQCh[1]);
+	carl9170_regwrite(AR9170_PHY_REG_TIMING_CTRL4(2), val);
+
+	/* xpd gain mask (index 14) */
+	val = carl9170_def_val(AR9170_PHY_REG_TPCRG1, is_2ghz, is_40mhz);
+	SET_VAL(AR9170_PHY_TPCRG1_PD_GAIN_1, val,
+		xpd2pd[m->xpdGain & 0xf] & 3);
+	SET_VAL(AR9170_PHY_TPCRG1_PD_GAIN_2, val,
+		xpd2pd[m->xpdGain & 0xf] >> 2);
+	carl9170_regwrite(AR9170_PHY_REG_TPCRG1, val);
+
+	carl9170_regwrite(AR9170_PHY_REG_RX_CHAINMASK, ar->eeprom.rx_mask);
+	carl9170_regwrite(AR9170_PHY_REG_CAL_CHAINMASK, ar->eeprom.rx_mask);
+
+	carl9170_regwrite_finish();
+	return carl9170_regwrite_result();
+}
+
+static int carl9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
+{
+	int i, err;
+	u32 val;
+	bool is_2ghz = band == IEEE80211_BAND_2GHZ;
+	bool is_40mhz = conf_is_ht40(&ar->hw->conf);
+
+	carl9170_regwrite_begin(ar);
+
+	for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) {
+		if (is_40mhz) {
+			if (is_2ghz)
+				val = ar5416_phy_init[i]._2ghz_40;
+			else
+				val = ar5416_phy_init[i]._5ghz_40;
+		} else {
+			if (is_2ghz)
+				val = ar5416_phy_init[i]._2ghz_20;
+			else
+				val = ar5416_phy_init[i]._5ghz_20;
+		}
+
+		carl9170_regwrite(ar5416_phy_init[i].reg, val);
+	}
+
+	carl9170_regwrite_finish();
+	err = carl9170_regwrite_result();
+	if (err)
+		return err;
+
+	err = carl9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz);
+	if (err)
+		return err;
+
+	err = carl9170_init_power_cal(ar);
+	if (err)
+		return err;
+
+	/* XXX: remove magic! */
+	if (is_2ghz)
+		err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5163);
+	else
+		err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5143);
+
+	return err;
+}
+
+struct carl9170_rf_initvals {
+	u32 reg, _5ghz, _2ghz;
+};
+
+static struct carl9170_rf_initvals carl9170_rf_initval[] = {
+	/* bank 0 */
+	{ 0x1c58b0, 0x1e5795e5, 0x1e5795e5},
+	{ 0x1c58e0, 0x02008020, 0x02008020},
+	/* bank 1 */
+	{ 0x1c58b0, 0x02108421, 0x02108421},
+	{ 0x1c58ec, 0x00000008, 0x00000008},
+	/* bank 2 */
+	{ 0x1c58b0, 0x0e73ff17, 0x0e73ff17},
+	{ 0x1c58e0, 0x00000420, 0x00000420},
+	/* bank 3 */
+	{ 0x1c58f0, 0x01400018, 0x01c00018},
+	/* bank 4 */
+	{ 0x1c58b0, 0x000001a1, 0x000001a1},
+	{ 0x1c58e8, 0x00000001, 0x00000001},
+	/* bank 5 */
+	{ 0x1c58b0, 0x00000013, 0x00000013},
+	{ 0x1c58e4, 0x00000002, 0x00000002},
+	/* bank 6 */
+	{ 0x1c58b0, 0x00000000, 0x00000000},
+	{ 0x1c58b0, 0x00000000, 0x00000000},
+	{ 0x1c58b0, 0x00000000, 0x00000000},
+	{ 0x1c58b0, 0x00000000, 0x00000000},
+	{ 0x1c58b0, 0x00000000, 0x00000000},
+	{ 0x1c58b0, 0x00004000, 0x00004000},
+	{ 0x1c58b0, 0x00006c00, 0x00006c00},
+	{ 0x1c58b0, 0x00002c00, 0x00002c00},
+	{ 0x1c58b0, 0x00004800, 0x00004800},
+	{ 0x1c58b0, 0x00004000, 0x00004000},
+	{ 0x1c58b0, 0x00006000, 0x00006000},
+	{ 0x1c58b0, 0x00001000, 0x00001000},
+	{ 0x1c58b0, 0x00004000, 0x00004000},
+	{ 0x1c58b0, 0x00007c00, 0x00007c00},
+	{ 0x1c58b0, 0x00007c00, 0x00007c00},
+	{ 0x1c58b0, 0x00007c00, 0x00007c00},
+	{ 0x1c58b0, 0x00007c00, 0x00007c00},
+	{ 0x1c58b0, 0x00007c00, 0x00007c00},
+	{ 0x1c58b0, 0x00087c00, 0x00087c00},
+	{ 0x1c58b0, 0x00007c00, 0x00007c00},
+	{ 0x1c58b0, 0x00005400, 0x00005400},
+	{ 0x1c58b0, 0x00000c00, 0x00000c00},
+	{ 0x1c58b0, 0x00001800, 0x00001800},
+	{ 0x1c58b0, 0x00007c00, 0x00007c00},
+	{ 0x1c58b0, 0x00006c00, 0x00006c00},
+	{ 0x1c58b0, 0x00006c00, 0x00006c00},
+	{ 0x1c58b0, 0x00007c00, 0x00007c00},
+	{ 0x1c58b0, 0x00002c00, 0x00002c00},
+	{ 0x1c58b0, 0x00003c00, 0x00003c00},
+	{ 0x1c58b0, 0x00003800, 0x00003800},
+	{ 0x1c58b0, 0x00001c00, 0x00001c00},
+	{ 0x1c58b0, 0x00000800, 0x00000800},
+	{ 0x1c58b0, 0x00000408, 0x00000408},
+	{ 0x1c58b0, 0x00004c15, 0x00004c15},
+	{ 0x1c58b0, 0x00004188, 0x00004188},
+	{ 0x1c58b0, 0x0000201e, 0x0000201e},
+	{ 0x1c58b0, 0x00010408, 0x00010408},
+	{ 0x1c58b0, 0x00000801, 0x00000801},
+	{ 0x1c58b0, 0x00000c08, 0x00000c08},
+	{ 0x1c58b0, 0x0000181e, 0x0000181e},
+	{ 0x1c58b0, 0x00001016, 0x00001016},
+	{ 0x1c58b0, 0x00002800, 0x00002800},
+	{ 0x1c58b0, 0x00004010, 0x00004010},
+	{ 0x1c58b0, 0x0000081c, 0x0000081c},
+	{ 0x1c58b0, 0x00000115, 0x00000115},
+	{ 0x1c58b0, 0x00000015, 0x00000015},
+	{ 0x1c58b0, 0x00000066, 0x00000066},
+	{ 0x1c58b0, 0x0000001c, 0x0000001c},
+	{ 0x1c58b0, 0x00000000, 0x00000000},
+	{ 0x1c58b0, 0x00000004, 0x00000004},
+	{ 0x1c58b0, 0x00000015, 0x00000015},
+	{ 0x1c58b0, 0x0000001f, 0x0000001f},
+	{ 0x1c58e0, 0x00000000, 0x00000400},
+	/* bank 7 */
+	{ 0x1c58b0, 0x000000a0, 0x000000a0},
+	{ 0x1c58b0, 0x00000000, 0x00000000},
+	{ 0x1c58b0, 0x00000040, 0x00000040},
+	{ 0x1c58f0, 0x0000001c, 0x0000001c},
+};
+
+static int carl9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz)
+{
+	int err, i;
+
+	carl9170_regwrite_begin(ar);
+
+	for (i = 0; i < ARRAY_SIZE(carl9170_rf_initval); i++)
+		carl9170_regwrite(carl9170_rf_initval[i].reg,
+				  band5ghz ? carl9170_rf_initval[i]._5ghz
+					   : carl9170_rf_initval[i]._2ghz);
+
+	carl9170_regwrite_finish();
+	err = carl9170_regwrite_result();
+	if (err)
+		wiphy_err(ar->hw->wiphy, "rf init failed\n");
+
+	return err;
+}
+
+struct carl9170_phy_freq_params {
+	u8 coeff_exp;
+	u16 coeff_man;
+	u8 coeff_exp_shgi;
+	u16 coeff_man_shgi;
+};
+
+enum carl9170_bw {
+	CARL9170_BW_20,
+	CARL9170_BW_40_BELOW,
+	CARL9170_BW_40_ABOVE,
+
+	__CARL9170_NUM_BW,
+};
+
+struct carl9170_phy_freq_entry {
+	u16 freq;
+	struct carl9170_phy_freq_params params[__CARL9170_NUM_BW];
+};
+
+/* NB: must be in sync with channel tables in main! */
+static const struct carl9170_phy_freq_entry carl9170_phy_freq_params[] = {
+/*
+ *	freq,
+ *		20MHz,
+ *		40MHz (below),
+ *		40Mhz (above),
+ */
+	{ 2412, {
+		{ 3, 21737, 3, 19563, },
+		{ 3, 21827, 3, 19644, },
+		{ 3, 21647, 3, 19482, },
+	} },
+	{ 2417, {
+		{ 3, 21692, 3, 19523, },
+		{ 3, 21782, 3, 19604, },
+		{ 3, 21602, 3, 19442, },
+	} },
+	{ 2422, {
+		{ 3, 21647, 3, 19482, },
+		{ 3, 21737, 3, 19563, },
+		{ 3, 21558, 3, 19402, },
+	} },
+	{ 2427, {
+		{ 3, 21602, 3, 19442, },
+		{ 3, 21692, 3, 19523, },
+		{ 3, 21514, 3, 19362, },
+	} },
+	{ 2432, {
+		{ 3, 21558, 3, 19402, },
+		{ 3, 21647, 3, 19482, },
+		{ 3, 21470, 3, 19323, },
+	} },
+	{ 2437, {
+		{ 3, 21514, 3, 19362, },
+		{ 3, 21602, 3, 19442, },
+		{ 3, 21426, 3, 19283, },
+	} },
+	{ 2442, {
+		{ 3, 21470, 3, 19323, },
+		{ 3, 21558, 3, 19402, },
+		{ 3, 21382, 3, 19244, },
+	} },
+	{ 2447, {
+		{ 3, 21426, 3, 19283, },
+		{ 3, 21514, 3, 19362, },
+		{ 3, 21339, 3, 19205, },
+	} },
+	{ 2452, {
+		{ 3, 21382, 3, 19244, },
+		{ 3, 21470, 3, 19323, },
+		{ 3, 21295, 3, 19166, },
+	} },
+	{ 2457, {
+		{ 3, 21339, 3, 19205, },
+		{ 3, 21426, 3, 19283, },
+		{ 3, 21252, 3, 19127, },
+	} },
+	{ 2462, {
+		{ 3, 21295, 3, 19166, },
+		{ 3, 21382, 3, 19244, },
+		{ 3, 21209, 3, 19088, },
+	} },
+	{ 2467, {
+		{ 3, 21252, 3, 19127, },
+		{ 3, 21339, 3, 19205, },
+		{ 3, 21166, 3, 19050, },
+	} },
+	{ 2472, {
+		{ 3, 21209, 3, 19088, },
+		{ 3, 21295, 3, 19166, },
+		{ 3, 21124, 3, 19011, },
+	} },
+	{ 2484, {
+		{ 3, 21107, 3, 18996, },
+		{ 3, 21192, 3, 19073, },
+		{ 3, 21022, 3, 18920, },
+	} },
+	{ 4920, {
+		{ 4, 21313, 4, 19181, },
+		{ 4, 21356, 4, 19220, },
+		{ 4, 21269, 4, 19142, },
+	} },
+	{ 4940, {
+		{ 4, 21226, 4, 19104, },
+		{ 4, 21269, 4, 19142, },
+		{ 4, 21183, 4, 19065, },
+	} },
+	{ 4960, {
+		{ 4, 21141, 4, 19027, },
+		{ 4, 21183, 4, 19065, },
+		{ 4, 21098, 4, 18988, },
+	} },
+	{ 4980, {
+		{ 4, 21056, 4, 18950, },
+		{ 4, 21098, 4, 18988, },
+		{ 4, 21014, 4, 18912, },
+	} },
+	{ 5040, {
+		{ 4, 20805, 4, 18725, },
+		{ 4, 20846, 4, 18762, },
+		{ 4, 20764, 4, 18687, },
+	} },
+	{ 5060, {
+		{ 4, 20723, 4, 18651, },
+		{ 4, 20764, 4, 18687, },
+		{ 4, 20682, 4, 18614, },
+	} },
+	{ 5080, {
+		{ 4, 20641, 4, 18577, },
+		{ 4, 20682, 4, 18614, },
+		{ 4, 20601, 4, 18541, },
+	} },
+	{ 5180, {
+		{ 4, 20243, 4, 18219, },
+		{ 4, 20282, 4, 18254, },
+		{ 4, 20204, 4, 18183, },
+	} },
+	{ 5200, {
+		{ 4, 20165, 4, 18148, },
+		{ 4, 20204, 4, 18183, },
+		{ 4, 20126, 4, 18114, },
+	} },
+	{ 5220, {
+		{ 4, 20088, 4, 18079, },
+		{ 4, 20126, 4, 18114, },
+		{ 4, 20049, 4, 18044, },
+	} },
+	{ 5240, {
+		{ 4, 20011, 4, 18010, },
+		{ 4, 20049, 4, 18044, },
+		{ 4, 19973, 4, 17976, },
+	} },
+	{ 5260, {
+		{ 4, 19935, 4, 17941, },
+		{ 4, 19973, 4, 17976, },
+		{ 4, 19897, 4, 17907, },
+	} },
+	{ 5280, {
+		{ 4, 19859, 4, 17873, },
+		{ 4, 19897, 4, 17907, },
+		{ 4, 19822, 4, 17840, },
+	} },
+	{ 5300, {
+		{ 4, 19784, 4, 17806, },
+		{ 4, 19822, 4, 17840, },
+		{ 4, 19747, 4, 17772, },
+	} },
+	{ 5320, {
+		{ 4, 19710, 4, 17739, },
+		{ 4, 19747, 4, 17772, },
+		{ 4, 19673, 4, 17706, },
+	} },
+	{ 5500, {
+		{ 4, 19065, 4, 17159, },
+		{ 4, 19100, 4, 17190, },
+		{ 4, 19030, 4, 17127, },
+	} },
+	{ 5520, {
+		{ 4, 18996, 4, 17096, },
+		{ 4, 19030, 4, 17127, },
+		{ 4, 18962, 4, 17065, },
+	} },
+	{ 5540, {
+		{ 4, 18927, 4, 17035, },
+		{ 4, 18962, 4, 17065, },
+		{ 4, 18893, 4, 17004, },
+	} },
+	{ 5560, {
+		{ 4, 18859, 4, 16973, },
+		{ 4, 18893, 4, 17004, },
+		{ 4, 18825, 4, 16943, },
+	} },
+	{ 5580, {
+		{ 4, 18792, 4, 16913, },
+		{ 4, 18825, 4, 16943, },
+		{ 4, 18758, 4, 16882, },
+	} },
+	{ 5600, {
+		{ 4, 18725, 4, 16852, },
+		{ 4, 18758, 4, 16882, },
+		{ 4, 18691, 4, 16822, },
+	} },
+	{ 5620, {
+		{ 4, 18658, 4, 16792, },
+		{ 4, 18691, 4, 16822, },
+		{ 4, 18625, 4, 16762, },
+	} },
+	{ 5640, {
+		{ 4, 18592, 4, 16733, },
+		{ 4, 18625, 4, 16762, },
+		{ 4, 18559, 4, 16703, },
+	} },
+	{ 5660, {
+		{ 4, 18526, 4, 16673, },
+		{ 4, 18559, 4, 16703, },
+		{ 4, 18493, 4, 16644, },
+	} },
+	{ 5680, {
+		{ 4, 18461, 4, 16615, },
+		{ 4, 18493, 4, 16644, },
+		{ 4, 18428, 4, 16586, },
+	} },
+	{ 5700, {
+		{ 4, 18396, 4, 16556, },
+		{ 4, 18428, 4, 16586, },
+		{ 4, 18364, 4, 16527, },
+	} },
+	{ 5745, {
+		{ 4, 18252, 4, 16427, },
+		{ 4, 18284, 4, 16455, },
+		{ 4, 18220, 4, 16398, },
+	} },
+	{ 5765, {
+		{ 4, 18189, 5, 32740, },
+		{ 4, 18220, 4, 16398, },
+		{ 4, 18157, 5, 32683, },
+	} },
+	{ 5785, {
+		{ 4, 18126, 5, 32626, },
+		{ 4, 18157, 5, 32683, },
+		{ 4, 18094, 5, 32570, },
+	} },
+	{ 5805, {
+		{ 4, 18063, 5, 32514, },
+		{ 4, 18094, 5, 32570, },
+		{ 4, 18032, 5, 32458, },
+	} },
+	{ 5825, {
+		{ 4, 18001, 5, 32402, },
+		{ 4, 18032, 5, 32458, },
+		{ 4, 17970, 5, 32347, },
+	} },
+	{ 5170, {
+		{ 4, 20282, 4, 18254, },
+		{ 4, 20321, 4, 18289, },
+		{ 4, 20243, 4, 18219, },
+	} },
+	{ 5190, {
+		{ 4, 20204, 4, 18183, },
+		{ 4, 20243, 4, 18219, },
+		{ 4, 20165, 4, 18148, },
+	} },
+	{ 5210, {
+		{ 4, 20126, 4, 18114, },
+		{ 4, 20165, 4, 18148, },
+		{ 4, 20088, 4, 18079, },
+	} },
+	{ 5230, {
+		{ 4, 20049, 4, 18044, },
+		{ 4, 20088, 4, 18079, },
+		{ 4, 20011, 4, 18010, },
+	} },
+};
+
+static int carl9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz,
+				      u32 freq, enum carl9170_bw bw)
+{
+	int err;
+	u32 d0, d1, td0, td1, fd0, fd1;
+	u8 chansel;
+	u8 refsel0 = 1, refsel1 = 0;
+	u8 lf_synth = 0;
+
+	switch (bw) {
+	case CARL9170_BW_40_ABOVE:
+		freq += 10;
+		break;
+	case CARL9170_BW_40_BELOW:
+		freq -= 10;
+		break;
+	case CARL9170_BW_20:
+		break;
+	default:
+		BUG();
+		return -ENOSYS;
+	}
+
+	if (band5ghz) {
+		if (freq % 10) {
+			chansel = (freq - 4800) / 5;
+		} else {
+			chansel = ((freq - 4800) / 10) * 2;
+			refsel0 = 0;
+			refsel1 = 1;
+		}
+		chansel = byte_rev_table[chansel];
+	} else {
+		if (freq == 2484) {
+			chansel = 10 + (freq - 2274) / 5;
+			lf_synth = 1;
+		} else
+			chansel = 16 + (freq - 2272) / 5;
+		chansel *= 4;
+		chansel = byte_rev_table[chansel];
+	}
+
+	d1 =	chansel;
+	d0 =	0x21 |
+		refsel0 << 3 |
+		refsel1 << 2 |
+		lf_synth << 1;
+	td0 =	d0 & 0x1f;
+	td1 =	d1 & 0x1f;
+	fd0 =	td1 << 5 | td0;
+
+	td0 =	(d0 >> 5) & 0x7;
+	td1 =	(d1 >> 5) & 0x7;
+	fd1 =	td1 << 5 | td0;
+
+	carl9170_regwrite_begin(ar);
+
+	carl9170_regwrite(0x1c58b0, fd0);
+	carl9170_regwrite(0x1c58e8, fd1);
+
+	carl9170_regwrite_finish();
+	err = carl9170_regwrite_result();
+	if (err)
+		return err;
+
+	msleep(20);
+
+	return 0;
+}
+
+static const struct carl9170_phy_freq_params *
+carl9170_get_hw_dyn_params(struct ieee80211_channel *channel,
+			   enum carl9170_bw bw)
+{
+	unsigned int chanidx = 0;
+	u16 freq = 2412;
+
+	if (channel) {
+		chanidx = channel->hw_value;
+		freq = channel->center_freq;
+	}
+
+	BUG_ON(chanidx >= ARRAY_SIZE(carl9170_phy_freq_params));
+
+	BUILD_BUG_ON(__CARL9170_NUM_BW != 3);
+
+	WARN_ON(carl9170_phy_freq_params[chanidx].freq != freq);
+
+	return &carl9170_phy_freq_params[chanidx].params[bw];
+}
+
+static int carl9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f)
+{
+	int idx = nfreqs - 2;
+
+	while (idx >= 0) {
+		if (f >= freqs[idx])
+			return idx;
+		idx--;
+	}
+
+	return 0;
+}
+
+static s32 carl9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
+{
+	/* nothing to interpolate, it's horizontal */
+	if (y2 == y1)
+		return y1;
+
+	/* check if we hit one of the edges */
+	if (x == x1)
+		return y1;
+	if (x == x2)
+		return y2;
+
+	/* x1 == x2 is bad, hopefully == x */
+	if (x2 == x1)
+		return y1;
+
+	return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1));
+}
+
+static u8 carl9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2)
+{
+#define SHIFT		8
+	s32 y;
+
+	y = carl9170_interpolate_s32(x << SHIFT, x1 << SHIFT,
+		y1 << SHIFT, x2 << SHIFT, y2 << SHIFT);
+
+	/*
+	 * XXX: unwrap this expression
+	 *	Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)?
+	 *	Can we rely on the compiler to optimise away the div?
+	 */
+	return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1));
+#undef SHIFT
+}
+
+static u8 carl9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array)
+{
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		if (x <= x_array[i + 1])
+			break;
+	}
+
+	return carl9170_interpolate_u8(x, x_array[i], y_array[i],
+		x_array[i + 1], y_array[i + 1]);
+}
+
+static int carl9170_set_freq_cal_data(struct ar9170 *ar,
+	struct ieee80211_channel *channel)
+{
+	u8 *cal_freq_pier;
+	u8 vpds[2][AR5416_PD_GAIN_ICEPTS];
+	u8 pwrs[2][AR5416_PD_GAIN_ICEPTS];
+	int chain, idx, i;
+	u32 phy_data = 0;
+	u8 f, tmp;
+
+	switch (channel->band) {
+	case IEEE80211_BAND_2GHZ:
+		f = channel->center_freq - 2300;
+		cal_freq_pier = ar->eeprom.cal_freq_pier_2G;
+		i = AR5416_NUM_2G_CAL_PIERS - 1;
+		break;
+
+	case IEEE80211_BAND_5GHZ:
+		f = (channel->center_freq - 4800) / 5;
+		cal_freq_pier = ar->eeprom.cal_freq_pier_5G;
+		i = AR5416_NUM_5G_CAL_PIERS - 1;
+		break;
+
+	default:
+		return -EINVAL;
+		break;
+	}
+
+	for (; i >= 0; i--) {
+		if (cal_freq_pier[i] != 0xff)
+			break;
+	}
+	if (i < 0)
+		return -EINVAL;
+
+	idx = carl9170_find_freq_idx(i, cal_freq_pier, f);
+
+	carl9170_regwrite_begin(ar);
+
+	for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) {
+		for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) {
+			struct ar9170_calibration_data_per_freq *cal_pier_data;
+			int j;
+
+			switch (channel->band) {
+			case IEEE80211_BAND_2GHZ:
+				cal_pier_data = &ar->eeprom.
+					cal_pier_data_2G[chain][idx];
+				break;
+
+			case IEEE80211_BAND_5GHZ:
+				cal_pier_data = &ar->eeprom.
+					cal_pier_data_5G[chain][idx];
+				break;
+
+			default:
+				return -EINVAL;
+			}
+
+			for (j = 0; j < 2; j++) {
+				vpds[j][i] = carl9170_interpolate_u8(f,
+					cal_freq_pier[idx],
+					cal_pier_data->vpd_pdg[j][i],
+					cal_freq_pier[idx + 1],
+					cal_pier_data[1].vpd_pdg[j][i]);
+
+				pwrs[j][i] = carl9170_interpolate_u8(f,
+					cal_freq_pier[idx],
+					cal_pier_data->pwr_pdg[j][i],
+					cal_freq_pier[idx + 1],
+					cal_pier_data[1].pwr_pdg[j][i]) / 2;
+			}
+		}
+
+		for (i = 0; i < 76; i++) {
+			if (i < 25) {
+				tmp = carl9170_interpolate_val(i, &pwrs[0][0],
+							       &vpds[0][0]);
+			} else {
+				tmp = carl9170_interpolate_val(i - 12,
+							       &pwrs[1][0],
+							       &vpds[1][0]);
+			}
+
+			phy_data |= tmp << ((i & 3) << 3);
+			if ((i & 3) == 3) {
+				carl9170_regwrite(0x1c6280 + chain * 0x1000 +
+						  (i & ~3), phy_data);
+				phy_data = 0;
+			}
+		}
+
+		for (i = 19; i < 32; i++)
+			carl9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2),
+					  0x0);
+	}
+
+	carl9170_regwrite_finish();
+	return carl9170_regwrite_result();
+}
+
+static u8 carl9170_get_max_edge_power(struct ar9170 *ar,
+	u32 freq, struct ar9170_calctl_edges edges[])
+{
+	int i;
+	u8 rc = AR5416_MAX_RATE_POWER;
+	u8 f;
+	if (freq < 3000)
+		f = freq - 2300;
+	else
+		f = (freq - 4800) / 5;
+
+	for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) {
+		if (edges[i].channel == 0xff)
+			break;
+		if (f == edges[i].channel) {
+			/* exact freq match */
+			rc = edges[i].power_flags & ~AR9170_CALCTL_EDGE_FLAGS;
+			break;
+		}
+		if (i > 0 && f < edges[i].channel) {
+			if (f > edges[i - 1].channel &&
+			    edges[i - 1].power_flags &
+			    AR9170_CALCTL_EDGE_FLAGS) {
+				/* lower channel has the inband flag set */
+				rc = edges[i - 1].power_flags &
+					~AR9170_CALCTL_EDGE_FLAGS;
+			}
+			break;
+		}
+	}
+
+	if (i == AR5416_NUM_BAND_EDGES) {
+		if (f > edges[i - 1].channel &&
+		    edges[i - 1].power_flags & AR9170_CALCTL_EDGE_FLAGS) {
+			/* lower channel has the inband flag set */
+			rc = edges[i - 1].power_flags &
+				~AR9170_CALCTL_EDGE_FLAGS;
+		}
+	}
+	return rc;
+}
+
+static u8 carl9170_get_heavy_clip(struct ar9170 *ar, u32 freq,
+	enum carl9170_bw bw, struct ar9170_calctl_edges edges[])
+{
+	u8 f;
+	int i;
+	u8 rc = 0;
+
+	if (freq < 3000)
+		f = freq - 2300;
+	else
+		f = (freq - 4800) / 5;
+
+	if (bw == CARL9170_BW_40_BELOW || bw == CARL9170_BW_40_ABOVE)
+		rc |= 0xf0;
+
+	for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) {
+		if (edges[i].channel == 0xff)
+			break;
+		if (f == edges[i].channel) {
+			if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS))
+				rc |= 0x0f;
+			break;
+		}
+	}
+
+	return rc;
+}
+
+/*
+ * calculate the conformance test limits and the heavy clip parameter
+ * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706)
+ */
+static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
+{
+	u8 ctl_grp; /* CTL group */
+	u8 ctl_idx; /* CTL index */
+	int i, j;
+	struct ctl_modes {
+		u8 ctl_mode;
+		u8 max_power;
+		u8 *pwr_cal_data;
+		int pwr_cal_len;
+	} *modes;
+
+	/*
+	 * order is relevant in the mode_list_*: we fall back to the
+	 * lower indices if any mode is missed in the EEPROM.
+	 */
+	struct ctl_modes mode_list_2ghz[] = {
+		{ CTL_11B, 0, ar->power_2G_cck, 4 },
+		{ CTL_11G, 0, ar->power_2G_ofdm, 4 },
+		{ CTL_2GHT20, 0, ar->power_2G_ht20, 8 },
+		{ CTL_2GHT40, 0, ar->power_2G_ht40, 8 },
+	};
+	struct ctl_modes mode_list_5ghz[] = {
+		{ CTL_11A, 0, ar->power_5G_leg, 4 },
+		{ CTL_5GHT20, 0, ar->power_5G_ht20, 8 },
+		{ CTL_5GHT40, 0, ar->power_5G_ht40, 8 },
+	};
+	int nr_modes;
+
+#define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n])
+
+	ar->heavy_clip = 0;
+
+	/*
+	 * TODO: investigate the differences between OTUS'
+	 * hpreg.c::zfHpGetRegulatoryDomain() and
+	 * ath/regd.c::ath_regd_get_band_ctl() -
+	 * e.g. for FCC3_WORLD the OTUS procedure
+	 * always returns CTL_FCC, while the one in ath/ delivers
+	 * CTL_ETSI for 2GHz and CTL_FCC for 5GHz.
+	 */
+	ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory,
+					ar->hw->conf.channel->band);
+
+	/* ctl group not found - either invalid band (NO_CTL) or ww roaming */
+	if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL)
+		ctl_grp = CTL_FCC;
+
+	if (ctl_grp != CTL_FCC)
+		/* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */
+		return;
+
+	if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+		modes = mode_list_2ghz;
+		nr_modes = ARRAY_SIZE(mode_list_2ghz);
+	} else {
+		modes = mode_list_5ghz;
+		nr_modes = ARRAY_SIZE(mode_list_5ghz);
+	}
+
+	for (i = 0; i < nr_modes; i++) {
+		u8 c = ctl_grp | modes[i].ctl_mode;
+		for (ctl_idx = 0; ctl_idx < AR5416_NUM_CTLS; ctl_idx++)
+			if (c == ar->eeprom.ctl_index[ctl_idx])
+				break;
+		if (ctl_idx < AR5416_NUM_CTLS) {
+			int f_off = 0;
+
+			/*
+			 * determine heavy clip parameter
+			 * from the 11G edges array
+			 */
+			if (modes[i].ctl_mode == CTL_11G) {
+				ar->heavy_clip =
+					carl9170_get_heavy_clip(ar,
+						freq, bw, EDGES(ctl_idx, 1));
+			}
+
+			/* adjust freq for 40MHz */
+			if (modes[i].ctl_mode == CTL_2GHT40 ||
+			    modes[i].ctl_mode == CTL_5GHT40) {
+				if (bw == CARL9170_BW_40_BELOW)
+					f_off = -10;
+				else
+					f_off = 10;
+			}
+
+			modes[i].max_power =
+				carl9170_get_max_edge_power(ar,
+					freq+f_off, EDGES(ctl_idx, 1));
+
+			/*
+			 * TODO: check if the regulatory max. power is
+			 * controlled by cfg80211 for DFS.
+			 * (hpmain applies it to max_power itself for DFS freq)
+			 */
+
+		} else {
+			/*
+			 * Workaround in otus driver, hpmain.c, line 3906:
+			 * if no data for 5GHT20 are found, take the
+			 * legacy 5G value. We extend this here to fallback
+			 * from any other HT* or 11G, too.
+			 */
+			int k = i;
+
+			modes[i].max_power = AR5416_MAX_RATE_POWER;
+			while (k-- > 0) {
+				if (modes[k].max_power !=
+				    AR5416_MAX_RATE_POWER) {
+					modes[i].max_power = modes[k].max_power;
+					break;
+				}
+			}
+		}
+
+		/* apply max power to pwr_cal_data (ar->power_*) */
+		for (j = 0; j < modes[i].pwr_cal_len; j++) {
+			modes[i].pwr_cal_data[j] = min(modes[i].pwr_cal_data[j],
+						       modes[i].max_power);
+		}
+	}
+
+	if (ar->heavy_clip & 0xf0) {
+		ar->power_2G_ht40[0]--;
+		ar->power_2G_ht40[1]--;
+		ar->power_2G_ht40[2]--;
+	}
+	if (ar->heavy_clip & 0xf) {
+		ar->power_2G_ht20[0]++;
+		ar->power_2G_ht20[1]++;
+		ar->power_2G_ht20[2]++;
+	}
+
+#undef EDGES
+}
+
+static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
+				  enum carl9170_bw bw)
+{
+	struct ar9170_calibration_target_power_legacy *ctpl;
+	struct ar9170_calibration_target_power_ht *ctph;
+	u8 *ctpres;
+	int ntargets;
+	int idx, i, n;
+	u8 ackpower, ackchains, f;
+	u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS];
+
+	if (freq < 3000)
+		f = freq - 2300;
+	else
+		f = (freq - 4800)/5;
+
+	/*
+	 * cycle through the various modes
+	 *
+	 * legacy modes first: 5G, 2G CCK, 2G OFDM
+	 */
+	for (i = 0; i < 3; i++) {
+		switch (i) {
+		case 0: /* 5 GHz legacy */
+			ctpl = &ar->eeprom.cal_tgt_pwr_5G[0];
+			ntargets = AR5416_NUM_5G_TARGET_PWRS;
+			ctpres = ar->power_5G_leg;
+			break;
+		case 1: /* 2.4 GHz CCK */
+			ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0];
+			ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS;
+			ctpres = ar->power_2G_cck;
+			break;
+		case 2: /* 2.4 GHz OFDM */
+			ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0];
+			ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
+			ctpres = ar->power_2G_ofdm;
+			break;
+		default:
+			BUG();
+		}
+
+		for (n = 0; n < ntargets; n++) {
+			if (ctpl[n].freq == 0xff)
+				break;
+			pwr_freqs[n] = ctpl[n].freq;
+		}
+		ntargets = n;
+		idx = carl9170_find_freq_idx(ntargets, pwr_freqs, f);
+		for (n = 0; n < 4; n++)
+			ctpres[n] = carl9170_interpolate_u8(f,
+				ctpl[idx + 0].freq, ctpl[idx + 0].power[n],
+				ctpl[idx + 1].freq, ctpl[idx + 1].power[n]);
+	}
+
+	/* HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 */
+	for (i = 0; i < 4; i++) {
+		switch (i) {
+		case 0: /* 5 GHz HT 20 */
+			ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0];
+			ntargets = AR5416_NUM_5G_TARGET_PWRS;
+			ctpres = ar->power_5G_ht20;
+			break;
+		case 1: /* 5 GHz HT 40 */
+			ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0];
+			ntargets = AR5416_NUM_5G_TARGET_PWRS;
+			ctpres = ar->power_5G_ht40;
+			break;
+		case 2: /* 2.4 GHz HT 20 */
+			ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0];
+			ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
+			ctpres = ar->power_2G_ht20;
+			break;
+		case 3: /* 2.4 GHz HT 40 */
+			ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0];
+			ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
+			ctpres = ar->power_2G_ht40;
+			break;
+		default:
+			BUG();
+		}
+
+		for (n = 0; n < ntargets; n++) {
+			if (ctph[n].freq == 0xff)
+				break;
+			pwr_freqs[n] = ctph[n].freq;
+		}
+		ntargets = n;
+		idx = carl9170_find_freq_idx(ntargets, pwr_freqs, f);
+		for (n = 0; n < 8; n++)
+			ctpres[n] = carl9170_interpolate_u8(f,
+				ctph[idx + 0].freq, ctph[idx + 0].power[n],
+				ctph[idx + 1].freq, ctph[idx + 1].power[n]);
+	}
+
+	/* calc. conformance test limits and apply to ar->power*[] */
+	carl9170_calc_ctl(ar, freq, bw);
+
+	/* set ACK/CTS TX power */
+	carl9170_regwrite_begin(ar);
+
+	if (ar->eeprom.tx_mask != 1)
+		ackchains = AR9170_TX_PHY_TXCHAIN_2;
+	else
+		ackchains = AR9170_TX_PHY_TXCHAIN_1;
+
+	if (freq < 3000)
+		ackpower = ar->power_2G_ofdm[0] & 0x3f;
+	else
+		ackpower = ar->power_5G_leg[0] & 0x3f;
+
+	carl9170_regwrite(AR9170_MAC_REG_ACK_TPC,
+			  0x3c1e | ackpower << 20 | ackchains << 26);
+	carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_TPC,
+			  ackpower << 5 | ackchains << 11 |
+			  ackpower << 21 | ackchains << 27);
+
+	carl9170_regwrite(AR9170_MAC_REG_CFEND_QOSNULL_TPC,
+			  ackpower << 5 | ackchains << 11 |
+			  ackpower << 21 | ackchains << 27);
+
+	carl9170_regwrite_finish();
+	return carl9170_regwrite_result();
+}
+
+/* TODO: replace this with sign_extend32(noise, 8) */
+static int carl9170_calc_noise_dbm(u32 raw_noise)
+{
+	if (raw_noise & 0x100)
+		return ~0x1ff | raw_noise;
+	else
+		return raw_noise;
+}
+
+int carl9170_get_noisefloor(struct ar9170 *ar)
+{
+	static const u32 phy_regs[] = {
+		AR9170_PHY_REG_CCA, AR9170_PHY_REG_CH2_CCA,
+		AR9170_PHY_REG_EXT_CCA, AR9170_PHY_REG_CH2_EXT_CCA };
+	u32 phy_res[ARRAY_SIZE(phy_regs)];
+	int err, i;
+
+	BUILD_BUG_ON(ARRAY_SIZE(phy_regs) != ARRAY_SIZE(ar->noise));
+
+	err = carl9170_read_mreg(ar, ARRAY_SIZE(phy_regs), phy_regs, phy_res);
+	if (err)
+		return err;
+
+	for (i = 0; i < 2; i++) {
+		ar->noise[i] = carl9170_calc_noise_dbm(
+			(phy_res[i] >> 19) & 0x1ff);
+
+		ar->noise[i + 2] = carl9170_calc_noise_dbm(
+			(phy_res[i + 2] >> 23) & 0x1ff);
+	}
+
+	return 0;
+}
+
+static enum carl9170_bw nl80211_to_carl(enum nl80211_channel_type type)
+{
+	switch (type) {
+	case NL80211_CHAN_NO_HT:
+	case NL80211_CHAN_HT20:
+		return CARL9170_BW_20;
+	case NL80211_CHAN_HT40MINUS:
+		return CARL9170_BW_40_BELOW;
+	case NL80211_CHAN_HT40PLUS:
+		return CARL9170_BW_40_ABOVE;
+	default:
+		BUG();
+	}
+}
+
+int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
+			 enum nl80211_channel_type _bw,
+			 enum carl9170_rf_init_mode rfi)
+{
+	const struct carl9170_phy_freq_params *freqpar;
+	struct carl9170_rf_init_result rf_res;
+	struct carl9170_rf_init rf;
+	u32 cmd, tmp, offs = 0, new_ht = 0;
+	int err;
+	enum carl9170_bw bw;
+	bool warm_reset;
+	struct ieee80211_channel *old_channel = NULL;
+
+	bw = nl80211_to_carl(_bw);
+
+	if (conf_is_ht(&ar->hw->conf))
+		new_ht |= CARL9170FW_PHY_HT_ENABLE;
+
+	if (conf_is_ht40(&ar->hw->conf))
+		new_ht |= CARL9170FW_PHY_HT_DYN2040;
+
+	/* may be NULL at first setup */
+	if (ar->channel) {
+		old_channel = ar->channel;
+		warm_reset = (old_channel->band != channel->band) ||
+			     (old_channel->center_freq ==
+			      channel->center_freq) ||
+			     (ar->ht_settings != new_ht);
+
+		ar->channel = NULL;
+	} else {
+		warm_reset = true;
+	}
+
+	/* HW workaround */
+	if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] &&
+	    channel->center_freq <= 2417)
+		warm_reset = true;
+
+	if (rfi != CARL9170_RFI_NONE || warm_reset) {
+		u32 val;
+
+		if (rfi == CARL9170_RFI_COLD)
+			val = AR9170_PWR_RESET_BB_COLD_RESET;
+		else
+			val = AR9170_PWR_RESET_BB_WARM_RESET;
+
+		/* warm/cold reset BB/ADDA */
+		err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val);
+		if (err)
+			return err;
+
+		err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
+		if (err)
+			return err;
+
+		err = carl9170_init_phy(ar, channel->band);
+		if (err)
+			return err;
+
+		err = carl9170_init_rf_banks_0_7(ar,
+			channel->band == IEEE80211_BAND_5GHZ);
+		if (err)
+			return err;
+
+		cmd = CARL9170_CMD_RF_INIT;
+
+		msleep(100);
+
+		err = carl9170_echo_test(ar, 0xaabbccdd);
+		if (err)
+			return err;
+	} else {
+		cmd = CARL9170_CMD_FREQUENCY;
+	}
+
+	err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL);
+	if (err)
+		return err;
+
+	err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE,
+				 0x200);
+
+	err = carl9170_init_rf_bank4_pwr(ar,
+		channel->band == IEEE80211_BAND_5GHZ,
+		channel->center_freq, bw);
+	if (err)
+		return err;
+
+	tmp = AR9170_PHY_TURBO_FC_SINGLE_HT_LTF1 |
+	      AR9170_PHY_TURBO_FC_HT_EN;
+
+	switch (bw) {
+	case CARL9170_BW_20:
+		break;
+	case CARL9170_BW_40_BELOW:
+		tmp |= AR9170_PHY_TURBO_FC_DYN2040_EN |
+		       AR9170_PHY_TURBO_FC_SHORT_GI_40;
+		offs = 3;
+		break;
+	case CARL9170_BW_40_ABOVE:
+		tmp |= AR9170_PHY_TURBO_FC_DYN2040_EN |
+		       AR9170_PHY_TURBO_FC_SHORT_GI_40 |
+		       AR9170_PHY_TURBO_FC_DYN2040_PRI_CH;
+		offs = 1;
+		break;
+	default:
+		BUG();
+		return -ENOSYS;
+	}
+
+	if (ar->eeprom.tx_mask != 1)
+		tmp |= AR9170_PHY_TURBO_FC_WALSH;
+
+	err = carl9170_write_reg(ar, AR9170_PHY_REG_TURBO, tmp);
+	if (err)
+		return err;
+
+	err = carl9170_set_freq_cal_data(ar, channel);
+	if (err)
+		return err;
+
+	err = carl9170_set_power_cal(ar, channel->center_freq, bw);
+	if (err)
+		return err;
+
+	freqpar = carl9170_get_hw_dyn_params(channel, bw);
+
+	rf.ht_settings = new_ht;
+	if (conf_is_ht40(&ar->hw->conf))
+		SET_VAL(CARL9170FW_PHY_HT_EXT_CHAN_OFF, rf.ht_settings, offs);
+
+	rf.freq = cpu_to_le32(channel->center_freq * 1000);
+	rf.delta_slope_coeff_exp = cpu_to_le32(freqpar->coeff_exp);
+	rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man);
+	rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi);
+	rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi);
+
+	if (rfi != CARL9170_RFI_NONE)
+		rf.finiteLoopCount = cpu_to_le32(2000);
+	else
+		rf.finiteLoopCount = cpu_to_le32(1000);
+
+	err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf,
+				sizeof(rf_res), &rf_res);
+	if (err)
+		return err;
+
+	err = le32_to_cpu(rf_res.ret);
+	if (err != 0) {
+		ar->chan_fail++;
+		ar->total_chan_fail++;
+
+		wiphy_err(ar->hw->wiphy, "channel change: %d -> %d "
+			  "failed (%d).\n", old_channel ?
+			  old_channel->center_freq : -1, channel->center_freq,
+			  err);
+
+		if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) {
+			/*
+			 * We have tried very hard to change to _another_
+			 * channel and we've failed to do so!
+			 * Chances are that the PHY/RF is no longer
+			 * operable (due to corruptions/fatal events/bugs?)
+			 * and we need to reset at a higher level.
+			 */
+			carl9170_restart(ar, CARL9170_RR_TOO_MANY_PHY_ERRORS);
+			return 0;
+		}
+
+		err = carl9170_set_channel(ar, channel, _bw,
+					   CARL9170_RFI_COLD);
+		if (err)
+			return err;
+	} else {
+		ar->chan_fail = 0;
+	}
+
+	err = carl9170_get_noisefloor(ar);
+	if (err)
+		return err;
+
+	if (ar->heavy_clip) {
+		err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE,
+					 0x200 | ar->heavy_clip);
+		if (err) {
+			if (net_ratelimit()) {
+				wiphy_err(ar->hw->wiphy, "failed to set "
+				       "heavy clip\n");
+			}
+
+			return err;
+		}
+	}
+
+	/* FIXME: PSM does not work in 5GHz Band */
+	if (channel->band == IEEE80211_BAND_5GHZ)
+		ar->ps.off_override |= PS_OFF_5GHZ;
+	else
+		ar->ps.off_override &= ~PS_OFF_5GHZ;
+
+	ar->channel = channel;
+	ar->ht_settings = new_ht;
+	return 0;
+}
diff --git a/drivers/net/wireless/ath/carl9170/phy.h b/drivers/net/wireless/ath/carl9170/phy.h
new file mode 100644
index 0000000..02c34eb
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/phy.h
@@ -0,0 +1,564 @@
+/*
+ * Shared Atheros AR9170 Header
+ *
+ * PHY register map
+ *
+ * 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.
+ */
+
+#ifndef __CARL9170_SHARED_PHY_H
+#define __CARL9170_SHARED_PHY_H
+
+#define	AR9170_PHY_REG_BASE			(0x1bc000 + 0x9800)
+#define	AR9170_PHY_REG(_n)			(AR9170_PHY_REG_BASE + \
+						 ((_n) << 2))
+
+#define	AR9170_PHY_REG_TEST			(AR9170_PHY_REG_BASE + 0x0000)
+#define		AR9170_PHY_TEST_AGC_CLR			0x10000000
+#define		AR9170_PHY_TEST_RFSILENT_BB		0x00002000
+
+#define	AR9170_PHY_REG_TURBO			(AR9170_PHY_REG_BASE + 0x0004)
+#define		AR9170_PHY_TURBO_FC_TURBO_MODE		0x00000001
+#define		AR9170_PHY_TURBO_FC_TURBO_SHORT		0x00000002
+#define		AR9170_PHY_TURBO_FC_DYN2040_EN		0x00000004
+#define		AR9170_PHY_TURBO_FC_DYN2040_PRI_ONLY	0x00000008
+#define		AR9170_PHY_TURBO_FC_DYN2040_PRI_CH	0x00000010
+/* For 25 MHz channel spacing -- not used but supported by hw */
+#define		AR9170_PHY_TURBO_FC_DYN2040_EXT_CH	0x00000020
+#define		AR9170_PHY_TURBO_FC_HT_EN		0x00000040
+#define		AR9170_PHY_TURBO_FC_SHORT_GI_40		0x00000080
+#define		AR9170_PHY_TURBO_FC_WALSH		0x00000100
+#define		AR9170_PHY_TURBO_FC_SINGLE_HT_LTF1	0x00000200
+#define		AR9170_PHY_TURBO_FC_ENABLE_DAC_FIFO	0x00000800
+
+#define	AR9170_PHY_REG_TEST2			(AR9170_PHY_REG_BASE + 0x0008)
+
+#define	AR9170_PHY_REG_TIMING2			(AR9170_PHY_REG_BASE + 0x0010)
+#define		AR9170_PHY_TIMING2_USE_FORCE		0x00001000
+#define		AR9170_PHY_TIMING2_FORCE		0x00000fff
+#define		AR9170_PHY_TIMING2_FORCE_S			 0
+
+#define	AR9170_PHY_REG_TIMING3			(AR9170_PHY_REG_BASE + 0x0014)
+#define		AR9170_PHY_TIMING3_DSC_EXP		0x0001e000
+#define		AR9170_PHY_TIMING3_DSC_EXP_S		13
+#define		AR9170_PHY_TIMING3_DSC_MAN		0xfffe0000
+#define		AR9170_PHY_TIMING3_DSC_MAN_S		17
+
+#define	AR9170_PHY_REG_CHIP_ID			(AR9170_PHY_REG_BASE + 0x0018)
+#define		AR9170_PHY_CHIP_ID_REV_0		0x80
+#define		AR9170_PHY_CHIP_ID_REV_1		0x81
+#define		AR9170_PHY_CHIP_ID_9160_REV_0		0xb0
+
+#define	AR9170_PHY_REG_ACTIVE			(AR9170_PHY_REG_BASE + 0x001c)
+#define		AR9170_PHY_ACTIVE_EN			0x00000001
+#define		AR9170_PHY_ACTIVE_DIS			0x00000000
+
+#define	AR9170_PHY_REG_RF_CTL2			(AR9170_PHY_REG_BASE + 0x0024)
+#define		AR9170_PHY_RF_CTL2_TX_END_DATA_START	0x000000ff
+#define		AR9170_PHY_RF_CTL2_TX_END_DATA_START_S	0
+#define		AR9170_PHY_RF_CTL2_TX_END_PA_ON		0x0000ff00
+#define		AR9170_PHY_RF_CTL2_TX_END_PA_ON_S	8
+
+#define	AR9170_PHY_REG_RF_CTL3                  (AR9170_PHY_REG_BASE + 0x0028)
+#define		AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON	0x00ff0000
+#define		AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON_S	16
+
+#define	AR9170_PHY_REG_ADC_CTL			(AR9170_PHY_REG_BASE + 0x002c)
+#define		AR9170_PHY_ADC_CTL_OFF_INBUFGAIN	0x00000003
+#define		AR9170_PHY_ADC_CTL_OFF_INBUFGAIN_S	0
+#define		AR9170_PHY_ADC_CTL_OFF_PWDDAC		0x00002000
+#define		AR9170_PHY_ADC_CTL_OFF_PWDBANDGAP	0x00004000
+#define		AR9170_PHY_ADC_CTL_OFF_PWDADC		0x00008000
+#define		AR9170_PHY_ADC_CTL_ON_INBUFGAIN		0x00030000
+#define		AR9170_PHY_ADC_CTL_ON_INBUFGAIN_S	16
+
+#define	AR9170_PHY_REG_ADC_SERIAL_CTL		(AR9170_PHY_REG_BASE + 0x0030)
+#define		AR9170_PHY_ADC_SCTL_SEL_INTERNAL_ADDAC	0x00000000
+#define		AR9170_PHY_ADC_SCTL_SEL_EXTERNAL_RADIO	0x00000001
+
+#define	AR9170_PHY_REG_RF_CTL4			(AR9170_PHY_REG_BASE + 0x0034)
+#define		AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF	0xff000000
+#define		AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF_S	24
+#define		AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF	0x00ff0000
+#define		AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF_S	16
+#define		AR9170_PHY_RF_CTL4_FRAME_XPAB_ON	0x0000ff00
+#define		AR9170_PHY_RF_CTL4_FRAME_XPAB_ON_S	8
+#define		AR9170_PHY_RF_CTL4_FRAME_XPAA_ON	0x000000ff
+#define		AR9170_PHY_RF_CTL4_FRAME_XPAA_ON_S	0
+
+#define	AR9170_PHY_REG_TSTDAC_CONST		(AR9170_PHY_REG_BASE + 0x003c)
+
+#define	AR9170_PHY_REG_SETTLING			(AR9170_PHY_REG_BASE + 0x0044)
+#define		AR9170_PHY_SETTLING_SWITCH		0x00003f80
+#define		AR9170_PHY_SETTLING_SWITCH_S		7
+
+#define	AR9170_PHY_REG_RXGAIN			(AR9170_PHY_REG_BASE + 0x0048)
+#define	AR9170_PHY_REG_RXGAIN_CHAIN_2		(AR9170_PHY_REG_BASE + 0x2048)
+#define		AR9170_PHY_RXGAIN_TXRX_ATTEN		0x0003f000
+#define		AR9170_PHY_RXGAIN_TXRX_ATTEN_S		12
+#define		AR9170_PHY_RXGAIN_TXRX_RF_MAX		0x007c0000
+#define		AR9170_PHY_RXGAIN_TXRX_RF_MAX_S		18
+
+#define	AR9170_PHY_REG_DESIRED_SZ		(AR9170_PHY_REG_BASE + 0x0050)
+#define		AR9170_PHY_DESIRED_SZ_ADC		0x000000ff
+#define		AR9170_PHY_DESIRED_SZ_ADC_S		0
+#define		AR9170_PHY_DESIRED_SZ_PGA		0x0000ff00
+#define		AR9170_PHY_DESIRED_SZ_PGA_S		8
+#define		AR9170_PHY_DESIRED_SZ_TOT_DES		0x0ff00000
+#define		AR9170_PHY_DESIRED_SZ_TOT_DES_S		20
+
+#define	AR9170_PHY_REG_FIND_SIG			(AR9170_PHY_REG_BASE + 0x0058)
+#define		AR9170_PHY_FIND_SIG_FIRSTEP		0x0003f000
+#define		AR9170_PHY_FIND_SIG_FIRSTEP_S		12
+#define		AR9170_PHY_FIND_SIG_FIRPWR		0x03fc0000
+#define		AR9170_PHY_FIND_SIG_FIRPWR_S		18
+
+#define	AR9170_PHY_REG_AGC_CTL1			(AR9170_PHY_REG_BASE + 0x005c)
+#define		AR9170_PHY_AGC_CTL1_COARSE_LOW		0x00007f80
+#define		AR9170_PHY_AGC_CTL1_COARSE_LOW_S	7
+#define		AR9170_PHY_AGC_CTL1_COARSE_HIGH		0x003f8000
+#define		AR9170_PHY_AGC_CTL1_COARSE_HIGH_S	15
+
+#define	AR9170_PHY_REG_AGC_CONTROL		(AR9170_PHY_REG_BASE + 0x0060)
+#define		AR9170_PHY_AGC_CONTROL_CAL		0x00000001
+#define		AR9170_PHY_AGC_CONTROL_NF		0x00000002
+#define		AR9170_PHY_AGC_CONTROL_ENABLE_NF	0x00008000
+#define		AR9170_PHY_AGC_CONTROL_FLTR_CAL		0x00010000
+#define		AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF	0x00020000
+
+#define	AR9170_PHY_REG_CCA			(AR9170_PHY_REG_BASE + 0x0064)
+#define		AR9170_PHY_CCA_MINCCA_PWR		0x0ff80000
+#define		AR9170_PHY_CCA_MINCCA_PWR_S		19
+#define		AR9170_PHY_CCA_THRESH62			0x0007f000
+#define		AR9170_PHY_CCA_THRESH62_S		12
+
+#define	AR9170_PHY_REG_SFCORR			(AR9170_PHY_REG_BASE + 0x0068)
+#define		AR9170_PHY_SFCORR_M2COUNT_THR		0x0000001f
+#define		AR9170_PHY_SFCORR_M2COUNT_THR_S		0
+#define		AR9170_PHY_SFCORR_M1_THRESH		0x00fe0000
+#define		AR9170_PHY_SFCORR_M1_THRESH_S		17
+#define		AR9170_PHY_SFCORR_M2_THRESH		0x7f000000
+#define		AR9170_PHY_SFCORR_M2_THRESH_S		24
+
+#define	AR9170_PHY_REG_SFCORR_LOW		(AR9170_PHY_REG_BASE + 0x006c)
+#define		AR9170_PHY_SFCORR_LOW_USE_SELF_CORR_LOW	0x00000001
+#define		AR9170_PHY_SFCORR_LOW_M2COUNT_THR_LOW	0x00003f00
+#define		AR9170_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S	8
+#define		AR9170_PHY_SFCORR_LOW_M1_THRESH_LOW	0x001fc000
+#define		AR9170_PHY_SFCORR_LOW_M1_THRESH_LOW_S	14
+#define		AR9170_PHY_SFCORR_LOW_M2_THRESH_LOW	0x0fe00000
+#define		AR9170_PHY_SFCORR_LOW_M2_THRESH_LOW_S	21
+
+#define	AR9170_PHY_REG_SLEEP_CTR_CONTROL	(AR9170_PHY_REG_BASE + 0x0070)
+#define	AR9170_PHY_REG_SLEEP_CTR_LIMIT		(AR9170_PHY_REG_BASE + 0x0074)
+#define	AR9170_PHY_REG_SLEEP_SCAL		(AR9170_PHY_REG_BASE + 0x0078)
+
+#define	AR9170_PHY_REG_PLL_CTL			(AR9170_PHY_REG_BASE + 0x007c)
+#define		AR9170_PHY_PLL_CTL_40			0xaa
+#define		AR9170_PHY_PLL_CTL_40_5413		0x04
+#define		AR9170_PHY_PLL_CTL_44			0xab
+#define		AR9170_PHY_PLL_CTL_44_2133		0xeb
+#define		AR9170_PHY_PLL_CTL_40_2133		0xea
+
+#define	AR9170_PHY_REG_BIN_MASK_1		(AR9170_PHY_REG_BASE + 0x0100)
+#define	AR9170_PHY_REG_BIN_MASK_2		(AR9170_PHY_REG_BASE + 0x0104)
+#define	AR9170_PHY_REG_BIN_MASK_3		(AR9170_PHY_REG_BASE + 0x0108)
+#define	AR9170_PHY_REG_MASK_CTL			(AR9170_PHY_REG_BASE + 0x010c)
+
+/* analogue power on time (100ns) */
+#define	AR9170_PHY_REG_RX_DELAY			(AR9170_PHY_REG_BASE + 0x0114)
+#define	AR9170_PHY_REG_SEARCH_START_DELAY	(AR9170_PHY_REG_BASE + 0x0118)
+#define		AR9170_PHY_RX_DELAY_DELAY		0x00003fff
+
+#define	AR9170_PHY_REG_TIMING_CTRL4(_i)		(AR9170_PHY_REG_BASE + \
+						(0x0120 + ((_i) << 12)))
+#define		AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF		0x01f
+#define		AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S	0
+#define		AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF		0x7e0
+#define		AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S	5
+#define		AR9170_PHY_TIMING_CTRL4_IQCORR_ENABLE		0x800
+#define		AR9170_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX	0xf000
+#define		AR9170_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S	12
+#define		AR9170_PHY_TIMING_CTRL4_DO_IQCAL		0x10000
+#define		AR9170_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI	0x80000000
+#define		AR9170_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER	0x40000000
+#define		AR9170_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK	0x20000000
+#define		AR9170_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK	0x10000000
+
+#define	AR9170_PHY_REG_TIMING5			(AR9170_PHY_REG_BASE + 0x0124)
+#define		AR9170_PHY_TIMING5_CYCPWR_THR1		0x000000fe
+#define		AR9170_PHY_TIMING5_CYCPWR_THR1_S	1
+
+#define	AR9170_PHY_REG_POWER_TX_RATE1		(AR9170_PHY_REG_BASE + 0x0134)
+#define	AR9170_PHY_REG_POWER_TX_RATE2		(AR9170_PHY_REG_BASE + 0x0138)
+#define	AR9170_PHY_REG_POWER_TX_RATE_MAX	(AR9170_PHY_REG_BASE + 0x013c)
+#define		AR9170_PHY_POWER_TX_RATE_MAX_TPC_ENABLE	0x00000040
+
+#define	AR9170_PHY_REG_FRAME_CTL		(AR9170_PHY_REG_BASE + 0x0144)
+#define		AR9170_PHY_FRAME_CTL_TX_CLIP		0x00000038
+#define		AR9170_PHY_FRAME_CTL_TX_CLIP_S		3
+
+#define	AR9170_PHY_REG_SPUR_REG			(AR9170_PHY_REG_BASE + 0x014c)
+#define		AR9170_PHY_SPUR_REG_MASK_RATE_CNTL	(0xff << 18)
+#define		AR9170_PHY_SPUR_REG_MASK_RATE_CNTL_S	18
+#define		AR9170_PHY_SPUR_REG_ENABLE_MASK_PPM	0x20000
+#define		AR9170_PHY_SPUR_REG_MASK_RATE_SELECT	(0xff << 9)
+#define		AR9170_PHY_SPUR_REG_MASK_RATE_SELECT_S	9
+#define		AR9170_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI	0x100
+#define		AR9170_PHY_SPUR_REG_SPUR_RSSI_THRESH	0x7f
+#define		AR9170_PHY_SPUR_REG_SPUR_RSSI_THRESH_S	0
+
+#define	AR9170_PHY_REG_RADAR_EXT		(AR9170_PHY_REG_BASE + 0x0140)
+#define		AR9170_PHY_RADAR_EXT_ENA		0x00004000
+
+#define	AR9170_PHY_REG_RADAR_0			(AR9170_PHY_REG_BASE + 0x0154)
+#define		AR9170_PHY_RADAR_0_ENA			0x00000001
+#define		AR9170_PHY_RADAR_0_FFT_ENA		0x80000000
+/* inband pulse threshold */
+#define		AR9170_PHY_RADAR_0_INBAND		0x0000003e
+#define		AR9170_PHY_RADAR_0_INBAND_S		1
+/* pulse RSSI threshold */
+#define		AR9170_PHY_RADAR_0_PRSSI		0x00000fc0
+#define		AR9170_PHY_RADAR_0_PRSSI_S		6
+/* pulse height threshold */
+#define		AR9170_PHY_RADAR_0_HEIGHT		0x0003f000
+#define		AR9170_PHY_RADAR_0_HEIGHT_S		12
+/* radar RSSI threshold */
+#define		AR9170_PHY_RADAR_0_RRSSI		0x00fc0000
+#define		AR9170_PHY_RADAR_0_RRSSI_S		18
+/* radar firepower threshold */
+#define		AR9170_PHY_RADAR_0_FIRPWR		0x7f000000
+#define		AR9170_PHY_RADAR_0_FIRPWR_S		24
+
+#define	AR9170_PHY_REG_RADAR_1			(AR9170_PHY_REG_BASE + 0x0158)
+#define		AR9170_PHY_RADAR_1_RELPWR_ENA		0x00800000
+#define		AR9170_PHY_RADAR_1_USE_FIR128		0x00400000
+#define		AR9170_PHY_RADAR_1_RELPWR_THRESH	0x003f0000
+#define		AR9170_PHY_RADAR_1_RELPWR_THRESH_S	16
+#define		AR9170_PHY_RADAR_1_BLOCK_CHECK		0x00008000
+#define		AR9170_PHY_RADAR_1_MAX_RRSSI		0x00004000
+#define		AR9170_PHY_RADAR_1_RELSTEP_CHECK	0x00002000
+#define		AR9170_PHY_RADAR_1_RELSTEP_THRESH	0x00001f00
+#define		AR9170_PHY_RADAR_1_RELSTEP_THRESH_S	8
+#define		AR9170_PHY_RADAR_1_MAXLEN		0x000000ff
+#define		AR9170_PHY_RADAR_1_MAXLEN_S		0
+
+#define	AR9170_PHY_REG_SWITCH_CHAIN_0		(AR9170_PHY_REG_BASE + 0x0160)
+#define	AR9170_PHY_REG_SWITCH_CHAIN_2		(AR9170_PHY_REG_BASE + 0x2160)
+
+#define	AR9170_PHY_REG_SWITCH_COM		(AR9170_PHY_REG_BASE + 0x0164)
+
+#define	AR9170_PHY_REG_CCA_THRESHOLD		(AR9170_PHY_REG_BASE + 0x0168)
+
+#define	AR9170_PHY_REG_SIGMA_DELTA		(AR9170_PHY_REG_BASE + 0x016c)
+#define		AR9170_PHY_SIGMA_DELTA_ADC_SEL		0x00000003
+#define		AR9170_PHY_SIGMA_DELTA_ADC_SEL_S	0
+#define		AR9170_PHY_SIGMA_DELTA_FILT2		0x000000f8
+#define		AR9170_PHY_SIGMA_DELTA_FILT2_S		3
+#define		AR9170_PHY_SIGMA_DELTA_FILT1		0x00001f00
+#define		AR9170_PHY_SIGMA_DELTA_FILT1_S		8
+#define		AR9170_PHY_SIGMA_DELTA_ADC_CLIP		0x01ffe000
+#define		AR9170_PHY_SIGMA_DELTA_ADC_CLIP_S	13
+
+#define	AR9170_PHY_REG_RESTART			(AR9170_PHY_REG_BASE + 0x0170)
+#define		AR9170_PHY_RESTART_DIV_GC		0x001c0000
+#define		AR9170_PHY_RESTART_DIV_GC_S		18
+
+#define	AR9170_PHY_REG_RFBUS_REQ		(AR9170_PHY_REG_BASE + 0x017c)
+#define		AR9170_PHY_RFBUS_REQ_EN			0x00000001
+
+#define	AR9170_PHY_REG_TIMING7			(AR9170_PHY_REG_BASE + 0x0180)
+#define	AR9170_PHY_REG_TIMING8			(AR9170_PHY_REG_BASE + 0x0184)
+#define		AR9170_PHY_TIMING8_PILOT_MASK_2		0x000fffff
+#define		AR9170_PHY_TIMING8_PILOT_MASK_2_S	0
+
+#define	AR9170_PHY_REG_BIN_MASK2_1		(AR9170_PHY_REG_BASE + 0x0188)
+#define	AR9170_PHY_REG_BIN_MASK2_2		(AR9170_PHY_REG_BASE + 0x018c)
+#define	AR9170_PHY_REG_BIN_MASK2_3		(AR9170_PHY_REG_BASE + 0x0190)
+#define	AR9170_PHY_REG_BIN_MASK2_4		(AR9170_PHY_REG_BASE + 0x0194)
+#define		AR9170_PHY_BIN_MASK2_4_MASK_4		0x00003fff
+#define		AR9170_PHY_BIN_MASK2_4_MASK_4_S		0
+
+#define	AR9170_PHY_REG_TIMING9			(AR9170_PHY_REG_BASE + 0x0198)
+#define	AR9170_PHY_REG_TIMING10			(AR9170_PHY_REG_BASE + 0x019c)
+#define		AR9170_PHY_TIMING10_PILOT_MASK_2	0x000fffff
+#define		AR9170_PHY_TIMING10_PILOT_MASK_2_S	0
+
+#define	AR9170_PHY_REG_TIMING11			(AR9170_PHY_REG_BASE + 0x01a0)
+#define		AR9170_PHY_TIMING11_SPUR_DELTA_PHASE	0x000fffff
+#define		AR9170_PHY_TIMING11_SPUR_DELTA_PHASE_S	0
+#define		AR9170_PHY_TIMING11_SPUR_FREQ_SD	0x3ff00000
+#define		AR9170_PHY_TIMING11_SPUR_FREQ_SD_S	20
+#define		AR9170_PHY_TIMING11_USE_SPUR_IN_AGC	0x40000000
+#define		AR9170_PHY_TIMING11_USE_SPUR_IN_SELFCOR	0x80000000
+
+#define	AR9170_PHY_REG_RX_CHAINMASK		(AR9170_PHY_REG_BASE + 0x01a4)
+#define	AR9170_PHY_REG_NEW_ADC_DC_GAIN_CORR(_i)	(AR9170_PHY_REG_BASE + \
+						 0x01b4 + ((_i) << 12))
+#define		AR9170_PHY_NEW_ADC_GAIN_CORR_ENABLE		0x40000000
+#define		AR9170_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE	0x80000000
+
+#define	AR9170_PHY_REG_MULTICHAIN_GAIN_CTL	(AR9170_PHY_REG_BASE + 0x01ac)
+#define		AR9170_PHY_9285_ANT_DIV_CTL_ALL		0x7f000000
+#define		AR9170_PHY_9285_ANT_DIV_CTL		0x01000000
+#define		AR9170_PHY_9285_ANT_DIV_CTL_S		24
+#define		AR9170_PHY_9285_ANT_DIV_ALT_LNACONF	0x06000000
+#define		AR9170_PHY_9285_ANT_DIV_ALT_LNACONF_S	25
+#define		AR9170_PHY_9285_ANT_DIV_MAIN_LNACONF	0x18000000
+#define		AR9170_PHY_9285_ANT_DIV_MAIN_LNACONF_S	27
+#define		AR9170_PHY_9285_ANT_DIV_ALT_GAINTB	0x20000000
+#define		AR9170_PHY_9285_ANT_DIV_ALT_GAINTB_S	29
+#define		AR9170_PHY_9285_ANT_DIV_MAIN_GAINTB	0x40000000
+#define		AR9170_PHY_9285_ANT_DIV_MAIN_GAINTB_S	30
+#define		AR9170_PHY_9285_ANT_DIV_LNA1		2
+#define		AR9170_PHY_9285_ANT_DIV_LNA2		1
+#define		AR9170_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2	3
+#define		AR9170_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2	0
+#define		AR9170_PHY_9285_ANT_DIV_GAINTB_0	0
+#define		AR9170_PHY_9285_ANT_DIV_GAINTB_1	1
+
+#define	AR9170_PHY_REG_EXT_CCA0			(AR9170_PHY_REG_BASE + 0x01b8)
+#define		AR9170_PHY_REG_EXT_CCA0_THRESH62	0x000000ff
+#define		AR9170_PHY_REG_EXT_CCA0_THRESH62_S	0
+
+#define	AR9170_PHY_REG_EXT_CCA			(AR9170_PHY_REG_BASE + 0x01bc)
+#define		AR9170_PHY_EXT_CCA_CYCPWR_THR1		0x0000fe00
+#define		AR9170_PHY_EXT_CCA_CYCPWR_THR1_S	9
+#define		AR9170_PHY_EXT_CCA_THRESH62		0x007f0000
+#define		AR9170_PHY_EXT_CCA_THRESH62_S		16
+#define		AR9170_PHY_EXT_MINCCA_PWR		0xff800000
+#define		AR9170_PHY_EXT_MINCCA_PWR_S		23
+
+#define	AR9170_PHY_REG_SFCORR_EXT		(AR9170_PHY_REG_BASE + 0x01c0)
+#define		AR9170_PHY_SFCORR_EXT_M1_THRESH		0x0000007f
+#define		AR9170_PHY_SFCORR_EXT_M1_THRESH_S	0
+#define		AR9170_PHY_SFCORR_EXT_M2_THRESH		0x00003f80
+#define		AR9170_PHY_SFCORR_EXT_M2_THRESH_S	7
+#define		AR9170_PHY_SFCORR_EXT_M1_THRESH_LOW	0x001fc000
+#define		AR9170_PHY_SFCORR_EXT_M1_THRESH_LOW_S	14
+#define		AR9170_PHY_SFCORR_EXT_M2_THRESH_LOW	0x0fe00000
+#define		AR9170_PHY_SFCORR_EXT_M2_THRESH_LOW_S	21
+#define		AR9170_PHY_SFCORR_SPUR_SUBCHNL_SD_S	28
+
+#define	AR9170_PHY_REG_HALFGI			(AR9170_PHY_REG_BASE + 0x01d0)
+#define		AR9170_PHY_HALFGI_DSC_MAN		0x0007fff0
+#define		AR9170_PHY_HALFGI_DSC_MAN_S		4
+#define		AR9170_PHY_HALFGI_DSC_EXP		0x0000000f
+#define		AR9170_PHY_HALFGI_DSC_EXP_S		0
+
+#define	AR9170_PHY_REG_CHANNEL_MASK_01_30	(AR9170_PHY_REG_BASE + 0x01d4)
+#define	AR9170_PHY_REG_CHANNEL_MASK_31_60	(AR9170_PHY_REG_BASE + 0x01d8)
+
+#define	AR9170_PHY_REG_CHAN_INFO_MEMORY		(AR9170_PHY_REG_BASE + 0x01dc)
+#define		AR9170_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK	0x0001
+
+#define	AR9170_PHY_REG_HEAVY_CLIP_ENABLE	(AR9170_PHY_REG_BASE + 0x01e0)
+#define	AR9170_PHY_REG_HEAVY_CLIP_FACTOR_RIFS	(AR9170_PHY_REG_BASE + 0x01ec)
+#define		AR9170_PHY_RIFS_INIT_DELAY		0x03ff0000
+
+#define	AR9170_PHY_REG_CALMODE			(AR9170_PHY_REG_BASE + 0x01f0)
+#define		AR9170_PHY_CALMODE_IQ			0x00000000
+#define		AR9170_PHY_CALMODE_ADC_GAIN		0x00000001
+#define		AR9170_PHY_CALMODE_ADC_DC_PER		0x00000002
+#define		AR9170_PHY_CALMODE_ADC_DC_INIT		0x00000003
+
+#define	AR9170_PHY_REG_REFCLKDLY		(AR9170_PHY_REG_BASE + 0x01f4)
+#define	AR9170_PHY_REG_REFCLKPD			(AR9170_PHY_REG_BASE + 0x01f8)
+
+
+#define	AR9170_PHY_REG_CAL_MEAS_0(_i)		(AR9170_PHY_REG_BASE + \
+						 0x0410 + ((_i) << 12))
+#define	AR9170_PHY_REG_CAL_MEAS_1(_i)		(AR9170_PHY_REG_BASE + \
+						 0x0414 \ + ((_i) << 12))
+#define	AR9170_PHY_REG_CAL_MEAS_2(_i)		(AR9170_PHY_REG_BASE + \
+						 0x0418 + ((_i) << 12))
+#define	AR9170_PHY_REG_CAL_MEAS_3(_i)		(AR9170_PHY_REG_BASE + \
+						 0x041c + ((_i) << 12))
+
+#define	AR9170_PHY_REG_CURRENT_RSSI		(AR9170_PHY_REG_BASE + 0x041c)
+
+#define	AR9170_PHY_REG_RFBUS_GRANT		(AR9170_PHY_REG_BASE + 0x0420)
+#define		AR9170_PHY_RFBUS_GRANT_EN		0x00000001
+
+#define	AR9170_PHY_REG_CHAN_INFO_GAIN_DIFF	(AR9170_PHY_REG_BASE + 0x04f4)
+#define		AR9170_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT	320
+
+#define	AR9170_PHY_REG_CHAN_INFO_GAIN		(AR9170_PHY_REG_BASE + 0x04fc)
+
+#define	AR9170_PHY_REG_MODE			(AR9170_PHY_REG_BASE + 0x0a00)
+#define		AR9170_PHY_MODE_ASYNCFIFO		0x80
+#define		AR9170_PHY_MODE_AR2133			0x08
+#define		AR9170_PHY_MODE_AR5111			0x00
+#define		AR9170_PHY_MODE_AR5112			0x08
+#define		AR9170_PHY_MODE_DYNAMIC			0x04
+#define		AR9170_PHY_MODE_RF2GHZ			0x02
+#define		AR9170_PHY_MODE_RF5GHZ			0x00
+#define		AR9170_PHY_MODE_CCK			0x01
+#define		AR9170_PHY_MODE_OFDM			0x00
+#define		AR9170_PHY_MODE_DYN_CCK_DISABLE		0x100
+
+#define	AR9170_PHY_REG_CCK_TX_CTRL		(AR9170_PHY_REG_BASE + 0x0a04)
+#define		AR9170_PHY_CCK_TX_CTRL_JAPAN			0x00000010
+#define		AR9170_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK         0x0000000c
+#define		AR9170_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S       2
+
+#define	AR9170_PHY_REG_CCK_DETECT		(AR9170_PHY_REG_BASE + 0x0a08)
+#define		AR9170_PHY_CCK_DETECT_WEAK_SIG_THR_CCK		0x0000003f
+#define		AR9170_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S	0
+/* [12:6] settling time for antenna switch */
+#define		AR9170_PHY_CCK_DETECT_ANT_SWITCH_TIME		0x00001fc0
+#define		AR9170_PHY_CCK_DETECT_ANT_SWITCH_TIME_S		6
+#define		AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV	0x2000
+#define		AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S	13
+
+#define	AR9170_PHY_REG_GAIN_2GHZ		(AR9170_PHY_REG_BASE + 0x0a0c)
+#define	AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2	(AR9170_PHY_REG_BASE + 0x2a0c)
+#define		AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN	0x00fc0000
+#define		AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN_S	18
+#define		AR9170_PHY_GAIN_2GHZ_BSW_MARGIN		0x00003c00
+#define		AR9170_PHY_GAIN_2GHZ_BSW_MARGIN_S	10
+#define		AR9170_PHY_GAIN_2GHZ_BSW_ATTEN		0x0000001f
+#define		AR9170_PHY_GAIN_2GHZ_BSW_ATTEN_S	0
+#define		AR9170_PHY_GAIN_2GHZ_XATTEN2_MARGIN	0x003e0000
+#define		AR9170_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S	17
+#define		AR9170_PHY_GAIN_2GHZ_XATTEN1_MARGIN	0x0001f000
+#define		AR9170_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S	12
+#define		AR9170_PHY_GAIN_2GHZ_XATTEN2_DB		0x00000fc0
+#define		AR9170_PHY_GAIN_2GHZ_XATTEN2_DB_S	6
+#define		AR9170_PHY_GAIN_2GHZ_XATTEN1_DB		0x0000003f
+#define		AR9170_PHY_GAIN_2GHZ_XATTEN1_DB_S	0
+
+#define	AR9170_PHY_REG_CCK_RXCTRL4		(AR9170_PHY_REG_BASE + 0x0a1c)
+#define		AR9170_PHY_CCK_RXCTRL4_FREQ_EST_SHORT	0x01f80000
+#define		AR9170_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S	19
+
+#define	AR9170_PHY_REG_DAG_CTRLCCK		(AR9170_PHY_REG_BASE + 0x0a28)
+#define		AR9170_REG_DAG_CTRLCCK_EN_RSSI_THR	0x00000200
+#define		AR9170_REG_DAG_CTRLCCK_RSSI_THR		0x0001fc00
+#define		AR9170_REG_DAG_CTRLCCK_RSSI_THR_S	10
+
+#define	AR9170_PHY_REG_FORCE_CLKEN_CCK		(AR9170_PHY_REG_BASE + 0x0a2c)
+#define		AR9170_FORCE_CLKEN_CCK_MRC_MUX		0x00000040
+
+#define	AR9170_PHY_REG_POWER_TX_RATE3		(AR9170_PHY_REG_BASE + 0x0a34)
+#define	AR9170_PHY_REG_POWER_TX_RATE4		(AR9170_PHY_REG_BASE + 0x0a38)
+
+#define	AR9170_PHY_REG_SCRM_SEQ_XR		(AR9170_PHY_REG_BASE + 0x0a3c)
+#define	AR9170_PHY_REG_HEADER_DETECT_XR		(AR9170_PHY_REG_BASE + 0x0a40)
+#define	AR9170_PHY_REG_CHIRP_DETECTED_XR	(AR9170_PHY_REG_BASE + 0x0a44)
+#define	AR9170_PHY_REG_BLUETOOTH		(AR9170_PHY_REG_BASE + 0x0a54)
+
+#define	AR9170_PHY_REG_TPCRG1			(AR9170_PHY_REG_BASE + 0x0a58)
+#define		AR9170_PHY_TPCRG1_NUM_PD_GAIN		0x0000c000
+#define		AR9170_PHY_TPCRG1_NUM_PD_GAIN_S		14
+#define		AR9170_PHY_TPCRG1_PD_GAIN_1		0x00030000
+#define		AR9170_PHY_TPCRG1_PD_GAIN_1_S		16
+#define		AR9170_PHY_TPCRG1_PD_GAIN_2		0x000c0000
+#define		AR9170_PHY_TPCRG1_PD_GAIN_2_S		18
+#define		AR9170_PHY_TPCRG1_PD_GAIN_3		0x00300000
+#define		AR9170_PHY_TPCRG1_PD_GAIN_3_S		20
+#define		AR9170_PHY_TPCRG1_PD_CAL_ENABLE		0x00400000
+#define		AR9170_PHY_TPCRG1_PD_CAL_ENABLE_S	22
+
+#define	AR9170_PHY_REG_TX_PWRCTRL4		(AR9170_PHY_REG_BASE + 0x0a64)
+#define		AR9170_PHY_TX_PWRCTRL_PD_AVG_VALID	0x00000001
+#define		AR9170_PHY_TX_PWRCTRL_PD_AVG_VALID_S	0
+#define		AR9170_PHY_TX_PWRCTRL_PD_AVG_OUT	0x000001fe
+#define		AR9170_PHY_TX_PWRCTRL_PD_AVG_OUT_S	1
+
+#define	AR9170_PHY_REG_ANALOG_SWAP		(AR9170_PHY_REG_BASE + 0x0a68)
+#define		AR9170_PHY_ANALOG_SWAP_AB		0x0001
+#define		AR9170_PHY_ANALOG_SWAP_ALT_CHAIN	0x00000040
+
+#define	AR9170_PHY_REG_TPCRG5			(AR9170_PHY_REG_BASE + 0x0a6c)
+#define		AR9170_PHY_TPCRG5_PD_GAIN_OVERLAP	0x0000000f
+#define		AR9170_PHY_TPCRG5_PD_GAIN_OVERLAP_S	0
+#define		AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_1	0x000003f0
+#define		AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S	4
+#define		AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_2	0x0000fc00
+#define		AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S	10
+#define		AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_3    0x003f0000
+#define		AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S  16
+#define		AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_4    0x0fc00000
+#define		AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S  22
+
+#define	AR9170_PHY_REG_TX_PWRCTRL6_0		(AR9170_PHY_REG_BASE + 0x0a70)
+#define	AR9170_PHY_REG_TX_PWRCTRL6_1		(AR9170_PHY_REG_BASE + 0x1a70)
+#define		AR9170_PHY_TX_PWRCTRL_ERR_EST_MODE	0x03000000
+#define		AR9170_PHY_TX_PWRCTRL_ERR_EST_MODE_S	24
+
+#define	AR9170_PHY_REG_TX_PWRCTRL7		(AR9170_PHY_REG_BASE + 0x0a74)
+#define		AR9170_PHY_TX_PWRCTRL_INIT_TX_GAIN	0x01f80000
+#define		AR9170_PHY_TX_PWRCTRL_INIT_TX_GAIN_S	19
+
+#define	AR9170_PHY_REG_TX_PWRCTRL9		(AR9170_PHY_REG_BASE + 0x0a7c)
+#define		AR9170_PHY_TX_DESIRED_SCALE_CCK		0x00007c00
+#define		AR9170_PHY_TX_DESIRED_SCALE_CCK_S	10
+#define		AR9170_PHY_TX_PWRCTRL9_RES_DC_REMOVAL	0x80000000
+#define		AR9170_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S	31
+
+#define	AR9170_PHY_REG_TX_GAIN_TBL1		(AR9170_PHY_REG_BASE + 0x0b00)
+#define		AR9170_PHY_TX_GAIN			0x0007f000
+#define		AR9170_PHY_TX_GAIN_S			12
+
+/* Carrier leak calibration control, do it after AGC calibration */
+#define	AR9170_PHY_REG_CL_CAL_CTL		(AR9170_PHY_REG_BASE + 0x0b58)
+#define		AR9170_PHY_CL_CAL_ENABLE		0x00000002
+#define		AR9170_PHY_CL_CAL_PARALLEL_CAL_ENABLE	0x00000001
+
+#define	AR9170_PHY_REG_POWER_TX_RATE5		(AR9170_PHY_REG_BASE + 0x0b8c)
+#define	AR9170_PHY_REG_POWER_TX_RATE6		(AR9170_PHY_REG_BASE + 0x0b90)
+
+#define	AR9170_PHY_REG_CH0_TX_PWRCTRL11		(AR9170_PHY_REG_BASE + 0x0b98)
+#define	AR9170_PHY_REG_CH1_TX_PWRCTRL11		(AR9170_PHY_REG_BASE + 0x1b98)
+#define		AR9170_PHY_TX_CHX_PWRCTRL_OLPC_TEMP_COMP	0x0000fc00
+#define		AR9170_PHY_TX_CHX_PWRCTRL_OLPC_TEMP_COMP_S	10
+
+#define	AR9170_PHY_REG_CAL_CHAINMASK		(AR9170_PHY_REG_BASE + 0x0b9c)
+#define	AR9170_PHY_REG_VIT_MASK2_M_46_61	(AR9170_PHY_REG_BASE + 0x0ba0)
+#define	AR9170_PHY_REG_MASK2_M_31_45		(AR9170_PHY_REG_BASE + 0x0ba4)
+#define	AR9170_PHY_REG_MASK2_M_16_30		(AR9170_PHY_REG_BASE + 0x0ba8)
+#define	AR9170_PHY_REG_MASK2_M_00_15		(AR9170_PHY_REG_BASE + 0x0bac)
+#define	AR9170_PHY_REG_PILOT_MASK_01_30		(AR9170_PHY_REG_BASE + 0x0bb0)
+#define	AR9170_PHY_REG_PILOT_MASK_31_60		(AR9170_PHY_REG_BASE + 0x0bb4)
+#define	AR9170_PHY_REG_MASK2_P_15_01		(AR9170_PHY_REG_BASE + 0x0bb8)
+#define	AR9170_PHY_REG_MASK2_P_30_16		(AR9170_PHY_REG_BASE + 0x0bbc)
+#define	AR9170_PHY_REG_MASK2_P_45_31		(AR9170_PHY_REG_BASE + 0x0bc0)
+#define	AR9170_PHY_REG_MASK2_P_61_45		(AR9170_PHY_REG_BASE + 0x0bc4)
+#define	AR9170_PHY_REG_POWER_TX_SUB		(AR9170_PHY_REG_BASE + 0x0bc8)
+#define	AR9170_PHY_REG_POWER_TX_RATE7		(AR9170_PHY_REG_BASE + 0x0bcc)
+#define	AR9170_PHY_REG_POWER_TX_RATE8		(AR9170_PHY_REG_BASE + 0x0bd0)
+#define	AR9170_PHY_REG_POWER_TX_RATE9		(AR9170_PHY_REG_BASE + 0x0bd4)
+#define	AR9170_PHY_REG_XPA_CFG			(AR9170_PHY_REG_BASE + 0x0bd8)
+#define		AR9170_PHY_FORCE_XPA_CFG		0x000000001
+#define		AR9170_PHY_FORCE_XPA_CFG_S		0
+
+#define	AR9170_PHY_REG_CH1_CCA			(AR9170_PHY_REG_BASE + 0x1064)
+#define		AR9170_PHY_CH1_MINCCA_PWR		0x0ff80000
+#define		AR9170_PHY_CH1_MINCCA_PWR_S		19
+
+#define	AR9170_PHY_REG_CH2_CCA			(AR9170_PHY_REG_BASE + 0x2064)
+#define		AR9170_PHY_CH2_MINCCA_PWR		0x0ff80000
+#define		AR9170_PHY_CH2_MINCCA_PWR_S		19
+
+#define	AR9170_PHY_REG_CH1_EXT_CCA		(AR9170_PHY_REG_BASE + 0x11bc)
+#define		AR9170_PHY_CH1_EXT_MINCCA_PWR		0xff800000
+#define		AR9170_PHY_CH1_EXT_MINCCA_PWR_S		23
+
+#define	AR9170_PHY_REG_CH2_EXT_CCA		(AR9170_PHY_REG_BASE + 0x21bc)
+#define		AR9170_PHY_CH2_EXT_MINCCA_PWR		0xff800000
+#define		AR9170_PHY_CH2_EXT_MINCCA_PWR_S		23
+
+#endif	/* __CARL9170_SHARED_PHY_H */
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
new file mode 100644
index 0000000..939a0e9
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -0,0 +1,938 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * 802.11 & command trap routines
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 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/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/crc32.h>
+#include <net/mac80211.h>
+#include "carl9170.h"
+#include "hw.h"
+#include "cmd.h"
+
+static void carl9170_dbg_message(struct ar9170 *ar, const char *buf, u32 len)
+{
+	bool restart = false;
+	enum carl9170_restart_reasons reason = CARL9170_RR_NO_REASON;
+
+	if (len > 3) {
+		if (memcmp(buf, CARL9170_ERR_MAGIC, 3) == 0) {
+			ar->fw.err_counter++;
+			if (ar->fw.err_counter > 3) {
+				restart = true;
+				reason = CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS;
+			}
+		}
+
+		if (memcmp(buf, CARL9170_BUG_MAGIC, 3) == 0) {
+			ar->fw.bug_counter++;
+			restart = true;
+			reason = CARL9170_RR_FATAL_FIRMWARE_ERROR;
+		}
+	}
+
+	wiphy_info(ar->hw->wiphy, "FW: %.*s\n", len, buf);
+
+	if (restart)
+		carl9170_restart(ar, reason);
+}
+
+static void carl9170_handle_ps(struct ar9170 *ar, struct carl9170_rsp *rsp)
+{
+	u32 ps;
+	bool new_ps;
+
+	ps = le32_to_cpu(rsp->psm.state);
+
+	new_ps = (ps & CARL9170_PSM_COUNTER) != CARL9170_PSM_WAKE;
+	if (ar->ps.state != new_ps) {
+		if (!new_ps) {
+			ar->ps.sleep_ms = jiffies_to_msecs(jiffies -
+				ar->ps.last_action);
+		}
+
+		ar->ps.last_action = jiffies;
+
+		ar->ps.state = new_ps;
+	}
+}
+
+static int carl9170_check_sequence(struct ar9170 *ar, unsigned int seq)
+{
+	if (ar->cmd_seq < -1)
+		return 0;
+
+	/*
+	 * Initialize Counter
+	 */
+	if (ar->cmd_seq < 0)
+		ar->cmd_seq = seq;
+
+	/*
+	 * The sequence is strictly monotonic increasing and it never skips!
+	 *
+	 * Therefore we can safely assume that whenever we received an
+	 * unexpected sequence we have lost some valuable data.
+	 */
+	if (seq != ar->cmd_seq) {
+		int count;
+
+		count = (seq - ar->cmd_seq) % ar->fw.cmd_bufs;
+
+		wiphy_err(ar->hw->wiphy, "lost %d command responses/traps! "
+			  "w:%d g:%d\n", count, ar->cmd_seq, seq);
+
+		carl9170_restart(ar, CARL9170_RR_LOST_RSP);
+		return -EIO;
+	}
+
+	ar->cmd_seq = (ar->cmd_seq + 1) % ar->fw.cmd_bufs;
+	return 0;
+}
+
+static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer)
+{
+	/*
+	 * Some commands may have a variable response length
+	 * and we cannot predict the correct length in advance.
+	 * So we only check if we provided enough space for the data.
+	 */
+	if (unlikely(ar->readlen != (len - 4))) {
+		dev_warn(&ar->udev->dev, "received invalid command response:"
+			 "got %d, instead of %d\n", len - 4, ar->readlen);
+		print_hex_dump_bytes("carl9170 cmd:", DUMP_PREFIX_OFFSET,
+			ar->cmd_buf, (ar->cmd.hdr.len + 4) & 0x3f);
+		print_hex_dump_bytes("carl9170 rsp:", DUMP_PREFIX_OFFSET,
+			buffer, len);
+		/*
+		 * Do not complete. The command times out,
+		 * and we get a stack trace from there.
+		 */
+		carl9170_restart(ar, CARL9170_RR_INVALID_RSP);
+	}
+
+	spin_lock(&ar->cmd_lock);
+	if (ar->readbuf) {
+		if (len >= 4)
+			memcpy(ar->readbuf, buffer + 4, len - 4);
+
+		ar->readbuf = NULL;
+	}
+	complete(&ar->cmd_wait);
+	spin_unlock(&ar->cmd_lock);
+}
+
+void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
+{
+	struct carl9170_rsp *cmd = (void *) buf;
+	struct ieee80211_vif *vif;
+
+	if (carl9170_check_sequence(ar, cmd->hdr.seq))
+		return;
+
+	if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) {
+		if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG))
+			carl9170_cmd_callback(ar, len, buf);
+
+		return;
+	}
+
+	if (unlikely(cmd->hdr.len != (len - 4))) {
+		if (net_ratelimit()) {
+			wiphy_err(ar->hw->wiphy, "FW: received over-/under"
+				"sized event %x (%d, but should be %d).\n",
+			       cmd->hdr.cmd, cmd->hdr.len, len - 4);
+
+			print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE,
+					     buf, len);
+		}
+
+		return;
+	}
+
+	/* hardware event handlers */
+	switch (cmd->hdr.cmd) {
+	case CARL9170_RSP_PRETBTT:
+		/* pre-TBTT event */
+		rcu_read_lock();
+		vif = carl9170_get_main_vif(ar);
+
+		if (!vif) {
+			rcu_read_unlock();
+			break;
+		}
+
+		switch (vif->type) {
+		case NL80211_IFTYPE_STATION:
+			carl9170_handle_ps(ar, cmd);
+			break;
+
+		case NL80211_IFTYPE_AP:
+		case NL80211_IFTYPE_ADHOC:
+			carl9170_update_beacon(ar, true);
+			break;
+
+		default:
+			break;
+		}
+		rcu_read_unlock();
+
+		break;
+
+
+	case CARL9170_RSP_TXCOMP:
+		/* TX status notification */
+		carl9170_tx_process_status(ar, cmd);
+		break;
+
+	case CARL9170_RSP_BEACON_CONFIG:
+		/*
+		 * (IBSS) beacon send notification
+		 * bytes: 04 c2 XX YY B4 B3 B2 B1
+		 *
+		 * XX always 80
+		 * YY always 00
+		 * B1-B4 "should" be the number of send out beacons.
+		 */
+		break;
+
+	case CARL9170_RSP_ATIM:
+		/* End of Atim Window */
+		break;
+
+	case CARL9170_RSP_WATCHDOG:
+		/* Watchdog Interrupt */
+		carl9170_restart(ar, CARL9170_RR_WATCHDOG);
+		break;
+
+	case CARL9170_RSP_TEXT:
+		/* firmware debug */
+		carl9170_dbg_message(ar, (char *)buf + 4, len - 4);
+		break;
+
+	case CARL9170_RSP_HEXDUMP:
+		wiphy_dbg(ar->hw->wiphy, "FW: HD %d\n", len - 4);
+		print_hex_dump_bytes("FW:", DUMP_PREFIX_NONE,
+				     (char *)buf + 4, len - 4);
+		break;
+
+	case CARL9170_RSP_RADAR:
+		if (!net_ratelimit())
+			break;
+
+		wiphy_info(ar->hw->wiphy, "FW: RADAR! Please report this "
+		       "incident to linux-wireless@vger.kernel.org !\n");
+		break;
+
+	case CARL9170_RSP_GPIO:
+#ifdef CONFIG_CARL9170_WPC
+		if (ar->wps.pbc) {
+			bool state = !!(cmd->gpio.gpio & cpu_to_le32(
+				AR9170_GPIO_PORT_WPS_BUTTON_PRESSED));
+
+			if (state != ar->wps.pbc_state) {
+				ar->wps.pbc_state = state;
+				input_report_key(ar->wps.pbc, KEY_WPS_BUTTON,
+						 state);
+				input_sync(ar->wps.pbc);
+			}
+		}
+#endif /* CONFIG_CARL9170_WPC */
+		break;
+
+	case CARL9170_RSP_BOOT:
+		complete(&ar->fw_boot_wait);
+		break;
+
+	default:
+		wiphy_err(ar->hw->wiphy, "FW: received unhandled event %x\n",
+			cmd->hdr.cmd);
+		print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len);
+		break;
+	}
+}
+
+static int carl9170_rx_mac_status(struct ar9170 *ar,
+	struct ar9170_rx_head *head, struct ar9170_rx_macstatus *mac,
+	struct ieee80211_rx_status *status)
+{
+	struct ieee80211_channel *chan;
+	u8 error, decrypt;
+
+	BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12);
+	BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4);
+
+	error = mac->error;
+
+	if (error & AR9170_RX_ERROR_WRONG_RA) {
+		if (!ar->sniffer_enabled)
+			return -EINVAL;
+	}
+
+	if (error & AR9170_RX_ERROR_PLCP) {
+		if (!(ar->filter_state & FIF_PLCPFAIL))
+			return -EINVAL;
+
+		status->flag |= RX_FLAG_FAILED_PLCP_CRC;
+	}
+
+	if (error & AR9170_RX_ERROR_FCS) {
+		ar->tx_fcs_errors++;
+
+		if (!(ar->filter_state & FIF_FCSFAIL))
+			return -EINVAL;
+
+		status->flag |= RX_FLAG_FAILED_FCS_CRC;
+	}
+
+	decrypt = ar9170_get_decrypt_type(mac);
+	if (!(decrypt & AR9170_RX_ENC_SOFTWARE) &&
+	    decrypt != AR9170_ENC_ALG_NONE) {
+		if ((decrypt == AR9170_ENC_ALG_TKIP) &&
+		    (error & AR9170_RX_ERROR_MMIC))
+			status->flag |= RX_FLAG_MMIC_ERROR;
+
+		status->flag |= RX_FLAG_DECRYPTED;
+	}
+
+	if (error & AR9170_RX_ERROR_DECRYPT && !ar->sniffer_enabled)
+		return -ENODATA;
+
+	error &= ~(AR9170_RX_ERROR_MMIC |
+		   AR9170_RX_ERROR_FCS |
+		   AR9170_RX_ERROR_WRONG_RA |
+		   AR9170_RX_ERROR_DECRYPT |
+		   AR9170_RX_ERROR_PLCP);
+
+	/* drop any other error frames */
+	if (unlikely(error)) {
+		/* TODO: update netdevice's RX dropped/errors statistics */
+
+		if (net_ratelimit())
+			wiphy_dbg(ar->hw->wiphy, "received frame with "
+			       "suspicious error code (%#x).\n", error);
+
+		return -EINVAL;
+	}
+
+	chan = ar->channel;
+	if (chan) {
+		status->band = chan->band;
+		status->freq = chan->center_freq;
+	}
+
+	switch (mac->status & AR9170_RX_STATUS_MODULATION) {
+	case AR9170_RX_STATUS_MODULATION_CCK:
+		if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE)
+			status->flag |= RX_FLAG_SHORTPRE;
+		switch (head->plcp[0]) {
+		case AR9170_RX_PHY_RATE_CCK_1M:
+			status->rate_idx = 0;
+			break;
+		case AR9170_RX_PHY_RATE_CCK_2M:
+			status->rate_idx = 1;
+			break;
+		case AR9170_RX_PHY_RATE_CCK_5M:
+			status->rate_idx = 2;
+			break;
+		case AR9170_RX_PHY_RATE_CCK_11M:
+			status->rate_idx = 3;
+			break;
+		default:
+			if (net_ratelimit()) {
+				wiphy_err(ar->hw->wiphy, "invalid plcp cck "
+				       "rate (%x).\n", head->plcp[0]);
+			}
+
+			return -EINVAL;
+		}
+		break;
+
+	case AR9170_RX_STATUS_MODULATION_DUPOFDM:
+	case AR9170_RX_STATUS_MODULATION_OFDM:
+		switch (head->plcp[0] & 0xf) {
+		case AR9170_TXRX_PHY_RATE_OFDM_6M:
+			status->rate_idx = 0;
+			break;
+		case AR9170_TXRX_PHY_RATE_OFDM_9M:
+			status->rate_idx = 1;
+			break;
+		case AR9170_TXRX_PHY_RATE_OFDM_12M:
+			status->rate_idx = 2;
+			break;
+		case AR9170_TXRX_PHY_RATE_OFDM_18M:
+			status->rate_idx = 3;
+			break;
+		case AR9170_TXRX_PHY_RATE_OFDM_24M:
+			status->rate_idx = 4;
+			break;
+		case AR9170_TXRX_PHY_RATE_OFDM_36M:
+			status->rate_idx = 5;
+			break;
+		case AR9170_TXRX_PHY_RATE_OFDM_48M:
+			status->rate_idx = 6;
+			break;
+		case AR9170_TXRX_PHY_RATE_OFDM_54M:
+			status->rate_idx = 7;
+			break;
+		default:
+			if (net_ratelimit()) {
+				wiphy_err(ar->hw->wiphy, "invalid plcp ofdm "
+					"rate (%x).\n", head->plcp[0]);
+			}
+
+			return -EINVAL;
+		}
+		if (status->band == IEEE80211_BAND_2GHZ)
+			status->rate_idx += 4;
+		break;
+
+	case AR9170_RX_STATUS_MODULATION_HT:
+		if (head->plcp[3] & 0x80)
+			status->flag |= RX_FLAG_40MHZ;
+		if (head->plcp[6] & 0x80)
+			status->flag |= RX_FLAG_SHORT_GI;
+
+		status->rate_idx = clamp(0, 75, head->plcp[3] & 0x7f);
+		status->flag |= RX_FLAG_HT;
+		break;
+
+	default:
+		BUG();
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+
+static void carl9170_rx_phy_status(struct ar9170 *ar,
+	struct ar9170_rx_phystatus *phy, struct ieee80211_rx_status *status)
+{
+	int i;
+
+	BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20);
+
+	for (i = 0; i < 3; i++)
+		if (phy->rssi[i] != 0x80)
+			status->antenna |= BIT(i);
+
+	/* post-process RSSI */
+	for (i = 0; i < 7; i++)
+		if (phy->rssi[i] & 0x80)
+			phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f;
+
+	/* TODO: we could do something with phy_errors */
+	status->signal = ar->noise[0] + phy->rssi_combined;
+}
+
+static struct sk_buff *carl9170_rx_copy_data(u8 *buf, int len)
+{
+	struct sk_buff *skb;
+	int reserved = 0;
+	struct ieee80211_hdr *hdr = (void *) buf;
+
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		reserved += NET_IP_ALIGN;
+
+		if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+			reserved += NET_IP_ALIGN;
+	}
+
+	if (ieee80211_has_a4(hdr->frame_control))
+		reserved += NET_IP_ALIGN;
+
+	reserved = 32 + (reserved & NET_IP_ALIGN);
+
+	skb = dev_alloc_skb(len + reserved);
+	if (likely(skb)) {
+		skb_reserve(skb, reserved);
+		memcpy(skb_put(skb, len), buf, len);
+	}
+
+	return skb;
+}
+
+static u8 *carl9170_find_ie(u8 *data, unsigned int len, u8 ie)
+{
+	struct ieee80211_mgmt *mgmt = (void *)data;
+	u8 *pos, *end;
+
+	pos = (u8 *)mgmt->u.beacon.variable;
+	end = data + len;
+	while (pos < end) {
+		if (pos + 2 + pos[1] > end)
+			return NULL;
+
+		if (pos[0] == ie)
+			return pos;
+
+		pos += 2 + pos[1];
+	}
+	return NULL;
+}
+
+/*
+ * NOTE:
+ *
+ * The firmware is in charge of waking up the device just before
+ * the AP is expected to transmit the next beacon.
+ *
+ * This leaves the driver with the important task of deciding when
+ * to set the PHY back to bed again.
+ */
+static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
+{
+	struct ieee80211_hdr *hdr = (void *) data;
+	struct ieee80211_tim_ie *tim_ie;
+	u8 *tim;
+	u8 tim_len;
+	bool cam;
+
+	if (likely(!(ar->hw->conf.flags & IEEE80211_CONF_PS)))
+		return;
+
+	/* check if this really is a beacon */
+	if (!ieee80211_is_beacon(hdr->frame_control))
+		return;
+
+	/* min. beacon length + FCS_LEN */
+	if (len <= 40 + FCS_LEN)
+		return;
+
+	/* and only beacons from the associated BSSID, please */
+	if (compare_ether_addr(hdr->addr3, ar->common.curbssid) ||
+	    !ar->common.curaid)
+		return;
+
+	ar->ps.last_beacon = jiffies;
+
+	tim = carl9170_find_ie(data, len - FCS_LEN, WLAN_EID_TIM);
+	if (!tim)
+		return;
+
+	if (tim[1] < sizeof(*tim_ie))
+		return;
+
+	tim_len = tim[1];
+	tim_ie = (struct ieee80211_tim_ie *) &tim[2];
+
+	if (!WARN_ON_ONCE(!ar->hw->conf.ps_dtim_period))
+		ar->ps.dtim_counter = (tim_ie->dtim_count - 1) %
+			ar->hw->conf.ps_dtim_period;
+
+	/* Check whenever the PHY can be turned off again. */
+
+	/* 1. What about buffered unicast traffic for our AID? */
+	cam = ieee80211_check_tim(tim_ie, tim_len, ar->common.curaid);
+
+	/* 2. Maybe the AP wants to send multicast/broadcast data? */
+	cam = !!(tim_ie->bitmap_ctrl & 0x01);
+
+	if (!cam) {
+		/* back to low-power land. */
+		ar->ps.off_override &= ~PS_OFF_BCN;
+		carl9170_ps_check(ar);
+	} else {
+		/* force CAM */
+		ar->ps.off_override |= PS_OFF_BCN;
+	}
+}
+
+static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
+{
+	__le16 fc;
+
+	if ((ms & AR9170_RX_STATUS_MPDU) == AR9170_RX_STATUS_MPDU_SINGLE) {
+		/*
+		 * This frame is not part of an aMPDU.
+		 * Therefore it is not subjected to any
+		 * of the following content restrictions.
+		 */
+		return true;
+	}
+
+	/*
+	 * "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts
+	 * certain frame types can be part of an aMPDU.
+	 *
+	 * In order to keep the processing cost down, I opted for a
+	 * stateless filter solely based on the frame control field.
+	 */
+
+	fc = ((struct ieee80211_hdr *)buf)->frame_control;
+	if (ieee80211_is_data_qos(fc) && ieee80211_is_data_present(fc))
+		return true;
+
+	if (ieee80211_is_ack(fc) || ieee80211_is_back(fc) ||
+	    ieee80211_is_back_req(fc))
+		return true;
+
+	if (ieee80211_is_action(fc))
+		return true;
+
+	return false;
+}
+
+/*
+ * If the frame alignment is right (or the kernel has
+ * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
+ * is only a single MPDU in the USB frame, then we could
+ * submit to mac80211 the SKB directly. However, since
+ * there may be multiple packets in one SKB in stream
+ * mode, and we need to observe the proper ordering,
+ * this is non-trivial.
+ */
+
+static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
+{
+	struct ar9170_rx_head *head;
+	struct ar9170_rx_macstatus *mac;
+	struct ar9170_rx_phystatus *phy = NULL;
+	struct ieee80211_rx_status status;
+	struct sk_buff *skb;
+	int mpdu_len;
+	u8 mac_status;
+
+	if (!IS_STARTED(ar))
+		return;
+
+	if (unlikely(len < sizeof(*mac)))
+		goto drop;
+
+	mpdu_len = len - sizeof(*mac);
+
+	mac = (void *)(buf + mpdu_len);
+	mac_status = mac->status;
+	switch (mac_status & AR9170_RX_STATUS_MPDU) {
+	case AR9170_RX_STATUS_MPDU_FIRST:
+		/* Aggregated MPDUs start with an PLCP header */
+		if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) {
+			head = (void *) buf;
+
+			/*
+			 * The PLCP header needs to be cached for the
+			 * following MIDDLE + LAST A-MPDU packets.
+			 *
+			 * So, if you are wondering why all frames seem
+			 * to share a common RX status information,
+			 * then you have the answer right here...
+			 */
+			memcpy(&ar->rx_plcp, (void *) buf,
+			       sizeof(struct ar9170_rx_head));
+
+			mpdu_len -= sizeof(struct ar9170_rx_head);
+			buf += sizeof(struct ar9170_rx_head);
+
+			ar->rx_has_plcp = true;
+		} else {
+			if (net_ratelimit()) {
+				wiphy_err(ar->hw->wiphy, "plcp info "
+					"is clipped.\n");
+			}
+
+			goto drop;
+		}
+		break;
+
+	case AR9170_RX_STATUS_MPDU_LAST:
+		/*
+		 * The last frame of an A-MPDU has an extra tail
+		 * which does contain the phy status of the whole
+		 * aggregate.
+		 */
+
+		if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) {
+			mpdu_len -= sizeof(struct ar9170_rx_phystatus);
+			phy = (void *)(buf + mpdu_len);
+		} else {
+			if (net_ratelimit()) {
+				wiphy_err(ar->hw->wiphy, "frame tail "
+					"is clipped.\n");
+			}
+
+			goto drop;
+		}
+
+	case AR9170_RX_STATUS_MPDU_MIDDLE:
+		/*  These are just data + mac status */
+		if (unlikely(!ar->rx_has_plcp)) {
+			if (!net_ratelimit())
+				return;
+
+			wiphy_err(ar->hw->wiphy, "rx stream does not start "
+					"with a first_mpdu frame tag.\n");
+
+			goto drop;
+		}
+
+		head = &ar->rx_plcp;
+		break;
+
+	case AR9170_RX_STATUS_MPDU_SINGLE:
+		/* single mpdu has both: plcp (head) and phy status (tail) */
+		head = (void *) buf;
+
+		mpdu_len -= sizeof(struct ar9170_rx_head);
+		mpdu_len -= sizeof(struct ar9170_rx_phystatus);
+
+		buf += sizeof(struct ar9170_rx_head);
+		phy = (void *)(buf + mpdu_len);
+		break;
+
+	default:
+		BUG_ON(1);
+		break;
+	}
+
+	/* FC + DU + RA + FCS */
+	if (unlikely(mpdu_len < (2 + 2 + ETH_ALEN + FCS_LEN)))
+		goto drop;
+
+	memset(&status, 0, sizeof(status));
+	if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status)))
+		goto drop;
+
+	if (!carl9170_ampdu_check(ar, buf, mac_status))
+		goto drop;
+
+	if (phy)
+		carl9170_rx_phy_status(ar, phy, &status);
+
+	carl9170_ps_beacon(ar, buf, mpdu_len);
+
+	skb = carl9170_rx_copy_data(buf, mpdu_len);
+	if (!skb)
+		goto drop;
+
+	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+	ieee80211_rx(ar->hw, skb);
+	return;
+
+drop:
+	ar->rx_dropped++;
+}
+
+static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf,
+				   const unsigned int resplen)
+{
+	struct carl9170_rsp *cmd;
+	int i = 0;
+
+	while (i < resplen) {
+		cmd = (void *) &respbuf[i];
+
+		i += cmd->hdr.len + 4;
+		if (unlikely(i > resplen))
+			break;
+
+		carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4);
+	}
+
+	if (unlikely(i != resplen)) {
+		if (!net_ratelimit())
+			return;
+
+		wiphy_err(ar->hw->wiphy, "malformed firmware trap:\n");
+		print_hex_dump_bytes("rxcmd:", DUMP_PREFIX_OFFSET,
+				     respbuf, resplen);
+	}
+}
+
+static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len)
+{
+	unsigned int i = 0;
+
+	/* weird thing, but this is the same in the original driver */
+	while (len > 2 && i < 12 && buf[0] == 0xff && buf[1] == 0xff) {
+		i += 2;
+		len -= 2;
+		buf += 2;
+	}
+
+	if (unlikely(len < 4))
+		return;
+
+	/* found the 6 * 0xffff marker? */
+	if (i == 12)
+		carl9170_rx_untie_cmds(ar, buf, len);
+	else
+		carl9170_handle_mpdu(ar, buf, len);
+}
+
+static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len)
+{
+	unsigned int tlen, wlen = 0, clen = 0;
+	struct ar9170_stream *rx_stream;
+	u8 *tbuf;
+
+	tbuf = buf;
+	tlen = len;
+
+	while (tlen >= 4) {
+		rx_stream = (void *) tbuf;
+		clen = le16_to_cpu(rx_stream->length);
+		wlen = ALIGN(clen, 4);
+
+		/* check if this is stream has a valid tag.*/
+		if (rx_stream->tag != cpu_to_le16(AR9170_RX_STREAM_TAG)) {
+			/*
+			 * TODO: handle the highly unlikely event that the
+			 * corrupted stream has the TAG at the right position.
+			 */
+
+			/* check if the frame can be repaired. */
+			if (!ar->rx_failover_missing) {
+
+				/* this is not "short read". */
+				if (net_ratelimit()) {
+					wiphy_err(ar->hw->wiphy,
+						"missing tag!\n");
+				}
+
+				__carl9170_rx(ar, tbuf, tlen);
+				return;
+			}
+
+			if (ar->rx_failover_missing > tlen) {
+				if (net_ratelimit()) {
+					wiphy_err(ar->hw->wiphy,
+						"possible multi "
+						"stream corruption!\n");
+					goto err_telluser;
+				} else {
+					goto err_silent;
+				}
+			}
+
+			memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
+			ar->rx_failover_missing -= tlen;
+
+			if (ar->rx_failover_missing <= 0) {
+				/*
+				 * nested carl9170_rx_stream call!
+				 *
+				 * termination is guranteed, even when the
+				 * combined frame also have an element with
+				 * a bad tag.
+				 */
+
+				ar->rx_failover_missing = 0;
+				carl9170_rx_stream(ar, ar->rx_failover->data,
+						   ar->rx_failover->len);
+
+				skb_reset_tail_pointer(ar->rx_failover);
+				skb_trim(ar->rx_failover, 0);
+			}
+
+			return;
+		}
+
+		/* check if stream is clipped */
+		if (wlen > tlen - 4) {
+			if (ar->rx_failover_missing) {
+				/* TODO: handle double stream corruption. */
+				if (net_ratelimit()) {
+					wiphy_err(ar->hw->wiphy, "double rx "
+						"stream corruption!\n");
+					goto err_telluser;
+				} else {
+					goto err_silent;
+				}
+			}
+
+			/*
+			 * save incomplete data set.
+			 * the firmware will resend the missing bits when
+			 * the rx - descriptor comes round again.
+			 */
+
+			memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
+			ar->rx_failover_missing = clen - tlen;
+			return;
+		}
+		__carl9170_rx(ar, rx_stream->payload, clen);
+
+		tbuf += wlen + 4;
+		tlen -= wlen + 4;
+	}
+
+	if (tlen) {
+		if (net_ratelimit()) {
+			wiphy_err(ar->hw->wiphy, "%d bytes of unprocessed "
+				"data left in rx stream!\n", tlen);
+		}
+
+		goto err_telluser;
+	}
+
+	return;
+
+err_telluser:
+	wiphy_err(ar->hw->wiphy, "damaged RX stream data [want:%d, "
+		"data:%d, rx:%d, pending:%d ]\n", clen, wlen, tlen,
+		ar->rx_failover_missing);
+
+	if (ar->rx_failover_missing)
+		print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET,
+				     ar->rx_failover->data,
+				     ar->rx_failover->len);
+
+	print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET,
+			     buf, len);
+
+	wiphy_err(ar->hw->wiphy, "please check your hardware and cables, if "
+		"you see this message frequently.\n");
+
+err_silent:
+	if (ar->rx_failover_missing) {
+		skb_reset_tail_pointer(ar->rx_failover);
+		skb_trim(ar->rx_failover, 0);
+		ar->rx_failover_missing = 0;
+	}
+}
+
+void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len)
+{
+	if (ar->fw.rx_stream)
+		carl9170_rx_stream(ar, buf, len);
+	else
+		__carl9170_rx(ar, buf, len);
+}
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
new file mode 100644
index 0000000..b575c86
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -0,0 +1,1335 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * 802.11 xmit & status routines
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 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/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+#include "carl9170.h"
+#include "hw.h"
+#include "cmd.h"
+
+static inline unsigned int __carl9170_get_queue(struct ar9170 *ar,
+						unsigned int queue)
+{
+	if (unlikely(modparam_noht)) {
+		return queue;
+	} else {
+		/*
+		 * This is just another workaround, until
+		 * someone figures out how to get QoS and
+		 * AMPDU to play nicely together.
+		 */
+
+		return 2;		/* AC_BE */
+	}
+}
+
+static inline unsigned int carl9170_get_queue(struct ar9170 *ar,
+					      struct sk_buff *skb)
+{
+	return __carl9170_get_queue(ar, skb_get_queue_mapping(skb));
+}
+
+static bool is_mem_full(struct ar9170 *ar)
+{
+	return (DIV_ROUND_UP(IEEE80211_MAX_FRAME_LEN, ar->fw.mem_block_size) >
+		atomic_read(&ar->mem_free_blocks));
+}
+
+static void carl9170_tx_accounting(struct ar9170 *ar, struct sk_buff *skb)
+{
+	int queue, i;
+	bool mem_full;
+
+	atomic_inc(&ar->tx_total_queued);
+
+	queue = skb_get_queue_mapping(skb);
+	spin_lock_bh(&ar->tx_stats_lock);
+
+	/*
+	 * The driver has to accept the frame, regardless if the queue is
+	 * full to the brim, or not. We have to do the queuing internally,
+	 * since mac80211 assumes that a driver which can operate with
+	 * aggregated frames does not reject frames for this reason.
+	 */
+	ar->tx_stats[queue].len++;
+	ar->tx_stats[queue].count++;
+
+	mem_full = is_mem_full(ar);
+	for (i = 0; i < ar->hw->queues; i++) {
+		if (mem_full || ar->tx_stats[i].len >= ar->tx_stats[i].limit) {
+			ieee80211_stop_queue(ar->hw, i);
+			ar->queue_stop_timeout[i] = jiffies;
+		}
+	}
+
+	spin_unlock_bh(&ar->tx_stats_lock);
+}
+
+static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *txinfo;
+	int queue;
+
+	txinfo = IEEE80211_SKB_CB(skb);
+	queue = skb_get_queue_mapping(skb);
+
+	spin_lock_bh(&ar->tx_stats_lock);
+
+	ar->tx_stats[queue].len--;
+
+	if (!is_mem_full(ar)) {
+		unsigned int i;
+		for (i = 0; i < ar->hw->queues; i++) {
+			if (ar->tx_stats[i].len >= CARL9170_NUM_TX_LIMIT_SOFT)
+				continue;
+
+			if (ieee80211_queue_stopped(ar->hw, i)) {
+				unsigned long tmp;
+
+				tmp = jiffies - ar->queue_stop_timeout[i];
+				if (tmp > ar->max_queue_stop_timeout[i])
+					ar->max_queue_stop_timeout[i] = tmp;
+			}
+
+			ieee80211_wake_queue(ar->hw, i);
+		}
+	}
+
+	spin_unlock_bh(&ar->tx_stats_lock);
+	if (atomic_dec_and_test(&ar->tx_total_queued))
+		complete(&ar->tx_flush);
+}
+
+static int carl9170_alloc_dev_space(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct _carl9170_tx_superframe *super = (void *) skb->data;
+	unsigned int chunks;
+	int cookie = -1;
+
+	atomic_inc(&ar->mem_allocs);
+
+	chunks = DIV_ROUND_UP(skb->len, ar->fw.mem_block_size);
+	if (unlikely(atomic_sub_return(chunks, &ar->mem_free_blocks) < 0)) {
+		atomic_add(chunks, &ar->mem_free_blocks);
+		return -ENOSPC;
+	}
+
+	spin_lock_bh(&ar->mem_lock);
+	cookie = bitmap_find_free_region(ar->mem_bitmap, ar->fw.mem_blocks, 0);
+	spin_unlock_bh(&ar->mem_lock);
+
+	if (unlikely(cookie < 0)) {
+		atomic_add(chunks, &ar->mem_free_blocks);
+		return -ENOSPC;
+	}
+
+	super = (void *) skb->data;
+
+	/*
+	 * Cookie #0 serves two special purposes:
+	 *  1. The firmware might use it generate BlockACK frames
+	 *     in responds of an incoming BlockAckReqs.
+	 *
+	 *  2. Prevent double-free bugs.
+	 */
+	super->s.cookie = (u8) cookie + 1;
+	return 0;
+}
+
+static void carl9170_release_dev_space(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct _carl9170_tx_superframe *super = (void *) skb->data;
+	int cookie;
+
+	/* make a local copy of the cookie */
+	cookie = super->s.cookie;
+	/* invalidate cookie */
+	super->s.cookie = 0;
+
+	/*
+	 * Do a out-of-bounds check on the cookie:
+	 *
+	 *  * cookie "0" is reserved and won't be assigned to any
+	 *    out-going frame. Internally however, it is used to
+	 *    mark no longer/un-accounted frames and serves as a
+	 *    cheap way of preventing frames from being freed
+	 *    twice by _accident_. NB: There is a tiny race...
+	 *
+	 *  * obviously, cookie number is limited by the amount
+	 *    of available memory blocks, so the number can
+	 *    never execeed the mem_blocks count.
+	 */
+	if (unlikely(WARN_ON_ONCE(cookie == 0) ||
+	    WARN_ON_ONCE(cookie > ar->fw.mem_blocks)))
+		return;
+
+	atomic_add(DIV_ROUND_UP(skb->len, ar->fw.mem_block_size),
+		   &ar->mem_free_blocks);
+
+	spin_lock_bh(&ar->mem_lock);
+	bitmap_release_region(ar->mem_bitmap, cookie - 1, 0);
+	spin_unlock_bh(&ar->mem_lock);
+}
+
+/* Called from any context */
+static void carl9170_tx_release(struct kref *ref)
+{
+	struct ar9170 *ar;
+	struct carl9170_tx_info *arinfo;
+	struct ieee80211_tx_info *txinfo;
+	struct sk_buff *skb;
+
+	arinfo = container_of(ref, struct carl9170_tx_info, ref);
+	txinfo = container_of((void *) arinfo, struct ieee80211_tx_info,
+			      rate_driver_data);
+	skb = container_of((void *) txinfo, struct sk_buff, cb);
+
+	ar = arinfo->ar;
+	if (WARN_ON_ONCE(!ar))
+		return;
+
+	BUILD_BUG_ON(
+	    offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23);
+
+	memset(&txinfo->status.ampdu_ack_len, 0,
+	       sizeof(struct ieee80211_tx_info) -
+	       offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
+
+	if (atomic_read(&ar->tx_total_queued))
+		ar->tx_schedule = true;
+
+	if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) {
+		if (!atomic_read(&ar->tx_ampdu_upload))
+			ar->tx_ampdu_schedule = true;
+
+		if (txinfo->flags & IEEE80211_TX_STAT_AMPDU) {
+			txinfo->status.ampdu_len = txinfo->pad[0];
+			txinfo->status.ampdu_ack_len = txinfo->pad[1];
+			txinfo->pad[0] = txinfo->pad[1] = 0;
+		} else if (txinfo->flags & IEEE80211_TX_STAT_ACK) {
+			/*
+			 * drop redundant tx_status reports:
+			 *
+			 * 1. ampdu_ack_len of the final tx_status does
+			 *    include the feedback of this particular frame.
+			 *
+			 * 2. tx_status_irqsafe only queues up to 128
+			 *    tx feedback reports and discards the rest.
+			 *
+			 * 3. minstrel_ht is picky, it only accepts
+			 *    reports of frames with the TX_STATUS_AMPDU flag.
+			 */
+
+			dev_kfree_skb_any(skb);
+			return;
+		} else {
+			/*
+			 * Frame has failed, but we want to keep it in
+			 * case it was lost due to a power-state
+			 * transition.
+			 */
+		}
+	}
+
+	skb_pull(skb, sizeof(struct _carl9170_tx_superframe));
+	ieee80211_tx_status_irqsafe(ar->hw, skb);
+}
+
+void carl9170_tx_get_skb(struct sk_buff *skb)
+{
+	struct carl9170_tx_info *arinfo = (void *)
+		(IEEE80211_SKB_CB(skb))->rate_driver_data;
+	kref_get(&arinfo->ref);
+}
+
+int carl9170_tx_put_skb(struct sk_buff *skb)
+{
+	struct carl9170_tx_info *arinfo = (void *)
+		(IEEE80211_SKB_CB(skb))->rate_driver_data;
+
+	return kref_put(&arinfo->ref, carl9170_tx_release);
+}
+
+/* Caller must hold the tid_info->lock & rcu_read_lock */
+static void carl9170_tx_shift_bm(struct ar9170 *ar,
+	struct carl9170_sta_tid *tid_info, u16 seq)
+{
+	u16 off;
+
+	off = SEQ_DIFF(seq, tid_info->bsn);
+
+	if (WARN_ON_ONCE(off >= CARL9170_BAW_BITS))
+		return;
+
+	/*
+	 * Sanity check. For each MPDU we set the bit in bitmap and
+	 * clear it once we received the tx_status.
+	 * But if the bit is already cleared then we've been bitten
+	 * by a bug.
+	 */
+	WARN_ON_ONCE(!test_and_clear_bit(off, tid_info->bitmap));
+
+	off = SEQ_DIFF(tid_info->snx, tid_info->bsn);
+	if (WARN_ON_ONCE(off >= CARL9170_BAW_BITS))
+		return;
+
+	if (!bitmap_empty(tid_info->bitmap, off))
+		off = find_first_bit(tid_info->bitmap, off);
+
+	tid_info->bsn += off;
+	tid_info->bsn &= 0x0fff;
+
+	bitmap_shift_right(tid_info->bitmap, tid_info->bitmap,
+			   off, CARL9170_BAW_BITS);
+}
+
+static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
+	struct sk_buff *skb, struct ieee80211_tx_info *txinfo)
+{
+	struct _carl9170_tx_superframe *super = (void *) skb->data;
+	struct ieee80211_hdr *hdr = (void *) super->frame_data;
+	struct ieee80211_tx_info *tx_info;
+	struct carl9170_tx_info *ar_info;
+	struct carl9170_sta_info *sta_info;
+	struct ieee80211_sta *sta;
+	struct carl9170_sta_tid *tid_info;
+	struct ieee80211_vif *vif;
+	unsigned int vif_id;
+	u8 tid;
+
+	if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) ||
+	    txinfo->flags & IEEE80211_TX_CTL_INJECTED)
+		return;
+
+	tx_info = IEEE80211_SKB_CB(skb);
+	ar_info = (void *) tx_info->rate_driver_data;
+
+	vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >>
+		 CARL9170_TX_SUPER_MISC_VIF_ID_S;
+
+	if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC))
+		return;
+
+	rcu_read_lock();
+	vif = rcu_dereference(ar->vif_priv[vif_id].vif);
+	if (unlikely(!vif))
+		goto out_rcu;
+
+	/*
+	 * Normally we should use wrappers like ieee80211_get_DA to get
+	 * the correct peer ieee80211_sta.
+	 *
+	 * But there is a problem with indirect traffic (broadcasts, or
+	 * data which is designated for other stations) in station mode.
+	 * The frame will be directed to the AP for distribution and not
+	 * to the actual destination.
+	 */
+	sta = ieee80211_find_sta(vif, hdr->addr1);
+	if (unlikely(!sta))
+		goto out_rcu;
+
+	tid = get_tid_h(hdr);
+
+	sta_info = (void *) sta->drv_priv;
+	tid_info = rcu_dereference(sta_info->agg[tid]);
+	if (!tid_info)
+		goto out_rcu;
+
+	spin_lock_bh(&tid_info->lock);
+	if (likely(tid_info->state >= CARL9170_TID_STATE_IDLE))
+		carl9170_tx_shift_bm(ar, tid_info, get_seq_h(hdr));
+
+	if (sta_info->stats[tid].clear) {
+		sta_info->stats[tid].clear = false;
+		sta_info->stats[tid].ampdu_len = 0;
+		sta_info->stats[tid].ampdu_ack_len = 0;
+	}
+
+	sta_info->stats[tid].ampdu_len++;
+	if (txinfo->status.rates[0].count == 1)
+		sta_info->stats[tid].ampdu_ack_len++;
+
+	if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) {
+		txinfo->pad[0] = sta_info->stats[tid].ampdu_len;
+		txinfo->pad[1] = sta_info->stats[tid].ampdu_ack_len;
+		txinfo->flags |= IEEE80211_TX_STAT_AMPDU;
+		sta_info->stats[tid].clear = true;
+	}
+	spin_unlock_bh(&tid_info->lock);
+
+out_rcu:
+	rcu_read_unlock();
+}
+
+void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
+			const bool success)
+{
+	struct ieee80211_tx_info *txinfo;
+
+	carl9170_tx_accounting_free(ar, skb);
+
+	txinfo = IEEE80211_SKB_CB(skb);
+
+	if (success)
+		txinfo->flags |= IEEE80211_TX_STAT_ACK;
+	else
+		ar->tx_ack_failures++;
+
+	if (txinfo->flags & IEEE80211_TX_CTL_AMPDU)
+		carl9170_tx_status_process_ampdu(ar, skb, txinfo);
+
+	carl9170_tx_put_skb(skb);
+}
+
+/* This function may be called form any context */
+void carl9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
+
+	atomic_dec(&ar->tx_total_pending);
+
+	if (txinfo->flags & IEEE80211_TX_CTL_AMPDU)
+		atomic_dec(&ar->tx_ampdu_upload);
+
+	if (carl9170_tx_put_skb(skb))
+		tasklet_hi_schedule(&ar->usb_tasklet);
+}
+
+static struct sk_buff *carl9170_get_queued_skb(struct ar9170 *ar, u8 cookie,
+					       struct sk_buff_head *queue)
+{
+	struct sk_buff *skb;
+
+	spin_lock_bh(&queue->lock);
+	skb_queue_walk(queue, skb) {
+		struct _carl9170_tx_superframe *txc = (void *) skb->data;
+
+		if (txc->s.cookie != cookie)
+			continue;
+
+		__skb_unlink(skb, queue);
+		spin_unlock_bh(&queue->lock);
+
+		carl9170_release_dev_space(ar, skb);
+		return skb;
+	}
+	spin_unlock_bh(&queue->lock);
+
+	return NULL;
+}
+
+static void carl9170_tx_fill_rateinfo(struct ar9170 *ar, unsigned int rix,
+	unsigned int tries, struct ieee80211_tx_info *txinfo)
+{
+	unsigned int i;
+
+	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+		if (txinfo->status.rates[i].idx < 0)
+			break;
+
+		if (i == rix) {
+			txinfo->status.rates[i].count = tries;
+			i++;
+			break;
+		}
+	}
+
+	for (; i < IEEE80211_TX_MAX_RATES; i++) {
+		txinfo->status.rates[i].idx = -1;
+		txinfo->status.rates[i].count = 0;
+	}
+}
+
+static void carl9170_check_queue_stop_timeout(struct ar9170 *ar)
+{
+	int i;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *txinfo;
+	struct carl9170_tx_info *arinfo;
+	bool restart = false;
+
+	for (i = 0; i < ar->hw->queues; i++) {
+		spin_lock_bh(&ar->tx_status[i].lock);
+
+		skb = skb_peek(&ar->tx_status[i]);
+
+		if (!skb)
+			goto next;
+
+		txinfo = IEEE80211_SKB_CB(skb);
+		arinfo = (void *) txinfo->rate_driver_data;
+
+		if (time_is_before_jiffies(arinfo->timeout +
+		    msecs_to_jiffies(CARL9170_QUEUE_STUCK_TIMEOUT)) == true)
+			restart = true;
+
+next:
+		spin_unlock_bh(&ar->tx_status[i].lock);
+	}
+
+	if (restart) {
+		/*
+		 * At least one queue has been stuck for long enough.
+		 * Give the device a kick and hope it gets back to
+		 * work.
+		 *
+		 * possible reasons may include:
+		 *  - frames got lost/corrupted (bad connection to the device)
+		 *  - stalled rx processing/usb controller hiccups
+		 *  - firmware errors/bugs
+		 *  - every bug you can think of.
+		 *  - all bugs you can't...
+		 *  - ...
+		 */
+		carl9170_restart(ar, CARL9170_RR_STUCK_TX);
+	}
+}
+
+void carl9170_tx_janitor(struct work_struct *work)
+{
+	struct ar9170 *ar = container_of(work, struct ar9170,
+					 tx_janitor.work);
+	if (!IS_STARTED(ar))
+		return;
+
+	ar->tx_janitor_last_run = jiffies;
+
+	carl9170_check_queue_stop_timeout(ar);
+
+	if (!atomic_read(&ar->tx_total_queued))
+		return;
+
+	ieee80211_queue_delayed_work(ar->hw, &ar->tx_janitor,
+		msecs_to_jiffies(CARL9170_TX_TIMEOUT));
+}
+
+static void __carl9170_tx_process_status(struct ar9170 *ar,
+	const uint8_t cookie, const uint8_t info)
+{
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *txinfo;
+	struct carl9170_tx_info *arinfo;
+	unsigned int r, t, q;
+	bool success = true;
+
+	q = ar9170_qmap[info & CARL9170_TX_STATUS_QUEUE];
+
+	skb = carl9170_get_queued_skb(ar, cookie, &ar->tx_status[q]);
+	if (!skb) {
+		/*
+		 * We have lost the race to another thread.
+		 */
+
+		return ;
+	}
+
+	txinfo = IEEE80211_SKB_CB(skb);
+	arinfo = (void *) txinfo->rate_driver_data;
+
+	if (!(info & CARL9170_TX_STATUS_SUCCESS))
+		success = false;
+
+	r = (info & CARL9170_TX_STATUS_RIX) >> CARL9170_TX_STATUS_RIX_S;
+	t = (info & CARL9170_TX_STATUS_TRIES) >> CARL9170_TX_STATUS_TRIES_S;
+
+	carl9170_tx_fill_rateinfo(ar, r, t, txinfo);
+	carl9170_tx_status(ar, skb, success);
+}
+
+void carl9170_tx_process_status(struct ar9170 *ar,
+				const struct carl9170_rsp *cmd)
+{
+	unsigned int i;
+
+	for (i = 0;  i < cmd->hdr.ext; i++) {
+		if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) {
+			print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE,
+					     (void *) cmd, cmd->hdr.len + 4);
+			break;
+		}
+
+		__carl9170_tx_process_status(ar, cmd->_tx_status[i].cookie,
+					     cmd->_tx_status[i].info);
+	}
+}
+
+static __le32 carl9170_tx_physet(struct ar9170 *ar,
+	struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate)
+{
+	struct ieee80211_rate *rate = NULL;
+	u32 power, chains;
+	__le32 tmp;
+
+	tmp = cpu_to_le32(0);
+
+	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		tmp |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ <<
+			AR9170_TX_PHY_BW_S);
+	/* this works because 40 MHz is 2 and dup is 3 */
+	if (txrate->flags & IEEE80211_TX_RC_DUP_DATA)
+		tmp |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP <<
+			AR9170_TX_PHY_BW_S);
+
+	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
+		tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI);
+
+	if (txrate->flags & IEEE80211_TX_RC_MCS) {
+		u32 r = txrate->idx;
+		u8 *txpower;
+
+		/* heavy clip control */
+		tmp |= cpu_to_le32((r & 0x7) <<
+			AR9170_TX_PHY_TX_HEAVY_CLIP_S);
+
+		if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+			if (info->band == IEEE80211_BAND_5GHZ)
+				txpower = ar->power_5G_ht40;
+			else
+				txpower = ar->power_2G_ht40;
+		} else {
+			if (info->band == IEEE80211_BAND_5GHZ)
+				txpower = ar->power_5G_ht20;
+			else
+				txpower = ar->power_2G_ht20;
+		}
+
+		power = txpower[r & 7];
+
+		/* +1 dBm for HT40 */
+		if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+			power += 2;
+
+		r <<= AR9170_TX_PHY_MCS_S;
+		BUG_ON(r & ~AR9170_TX_PHY_MCS);
+
+		tmp |= cpu_to_le32(r & AR9170_TX_PHY_MCS);
+		tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
+
+		/*
+		 * green field preamble does not work.
+		 *
+		 * if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
+		 * tmp |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
+		 */
+	} else {
+		u8 *txpower;
+		u32 mod;
+		u32 phyrate;
+		u8 idx = txrate->idx;
+
+		if (info->band != IEEE80211_BAND_2GHZ) {
+			idx += 4;
+			txpower = ar->power_5G_leg;
+			mod = AR9170_TX_PHY_MOD_OFDM;
+		} else {
+			if (idx < 4) {
+				txpower = ar->power_2G_cck;
+				mod = AR9170_TX_PHY_MOD_CCK;
+			} else {
+				mod = AR9170_TX_PHY_MOD_OFDM;
+				txpower = ar->power_2G_ofdm;
+			}
+		}
+
+		rate = &__carl9170_ratetable[idx];
+
+		phyrate = rate->hw_value & 0xF;
+		power = txpower[(rate->hw_value & 0x30) >> 4];
+		phyrate <<= AR9170_TX_PHY_MCS_S;
+
+		tmp |= cpu_to_le32(mod);
+		tmp |= cpu_to_le32(phyrate);
+
+		/*
+		 * short preamble seems to be broken too.
+		 *
+		 * if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+		 *	tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE);
+		 */
+	}
+	power <<= AR9170_TX_PHY_TX_PWR_S;
+	power &= AR9170_TX_PHY_TX_PWR;
+	tmp |= cpu_to_le32(power);
+
+	/* set TX chains */
+	if (ar->eeprom.tx_mask == 1) {
+		chains = AR9170_TX_PHY_TXCHAIN_1;
+	} else {
+		chains = AR9170_TX_PHY_TXCHAIN_2;
+
+		/* >= 36M legacy OFDM - use only one chain */
+		if (rate && rate->bitrate >= 360 &&
+		    !(txrate->flags & IEEE80211_TX_RC_MCS))
+			chains = AR9170_TX_PHY_TXCHAIN_1;
+	}
+	tmp |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_S);
+
+	return tmp;
+}
+
+static bool carl9170_tx_rts_check(struct ar9170 *ar,
+				  struct ieee80211_tx_rate *rate,
+				  bool ampdu, bool multi)
+{
+	switch (ar->erp_mode) {
+	case CARL9170_ERP_AUTO:
+		if (ampdu)
+			break;
+
+	case CARL9170_ERP_MAC80211:
+		if (!(rate->flags & IEEE80211_TX_RC_USE_RTS_CTS))
+			break;
+
+	case CARL9170_ERP_RTS:
+		if (likely(!multi))
+			return true;
+
+	default:
+		break;
+	}
+
+	return false;
+}
+
+static bool carl9170_tx_cts_check(struct ar9170 *ar,
+				  struct ieee80211_tx_rate *rate)
+{
+	switch (ar->erp_mode) {
+	case CARL9170_ERP_AUTO:
+	case CARL9170_ERP_MAC80211:
+		if (!(rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
+			break;
+
+	case CARL9170_ERP_CTS:
+		return true;
+
+	default:
+		break;
+	}
+
+	return false;
+}
+
+static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr;
+	struct _carl9170_tx_superframe *txc;
+	struct carl9170_vif_info *cvif;
+	struct ieee80211_tx_info *info;
+	struct ieee80211_tx_rate *txrate;
+	struct ieee80211_sta *sta;
+	struct carl9170_tx_info *arinfo;
+	unsigned int hw_queue;
+	int i;
+	__le16 mac_tmp;
+	u16 len;
+	bool ampdu, no_ack;
+
+	BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
+	BUILD_BUG_ON(sizeof(struct _carl9170_tx_superdesc) !=
+		     CARL9170_TX_SUPERDESC_LEN);
+
+	BUILD_BUG_ON(sizeof(struct _ar9170_tx_hwdesc) !=
+		     AR9170_TX_HWDESC_LEN);
+
+	BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES);
+
+	BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC >
+		((CARL9170_TX_SUPER_MISC_VIF_ID >>
+		 CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1));
+
+	hw_queue = ar9170_qmap[carl9170_get_queue(ar, skb)];
+
+	hdr = (void *)skb->data;
+	info = IEEE80211_SKB_CB(skb);
+	len = skb->len;
+
+	/*
+	 * Note: If the frame was sent through a monitor interface,
+	 * the ieee80211_vif pointer can be NULL.
+	 */
+	if (likely(info->control.vif))
+		cvif = (void *) info->control.vif->drv_priv;
+	else
+		cvif = NULL;
+
+	sta = info->control.sta;
+
+	txc = (void *)skb_push(skb, sizeof(*txc));
+	memset(txc, 0, sizeof(*txc));
+
+	SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txc->s.misc, hw_queue);
+
+	if (likely(cvif))
+		SET_VAL(CARL9170_TX_SUPER_MISC_VIF_ID, txc->s.misc, cvif->id);
+
+	if (unlikely(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM))
+		txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB;
+
+	if (unlikely(ieee80211_is_probe_resp(hdr->frame_control)))
+		txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF;
+
+	mac_tmp = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
+			      AR9170_TX_MAC_BACKOFF);
+	mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) &&
+			       AR9170_TX_MAC_QOS);
+
+	no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK);
+	if (unlikely(no_ack))
+		mac_tmp |= cpu_to_le16(AR9170_TX_MAC_NO_ACK);
+
+	if (info->control.hw_key) {
+		len += info->control.hw_key->icv_len;
+
+		switch (info->control.hw_key->cipher) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+		case WLAN_CIPHER_SUITE_TKIP:
+			mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_RC4);
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_AES);
+			break;
+		default:
+			WARN_ON(1);
+			goto err_out;
+		}
+	}
+
+	ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU);
+	if (ampdu) {
+		unsigned int density, factor;
+
+		if (unlikely(!sta || !cvif))
+			goto err_out;
+
+		factor = min_t(unsigned int, 1u,
+			 info->control.sta->ht_cap.ampdu_factor);
+
+		density = info->control.sta->ht_cap.ampdu_density;
+
+		if (density) {
+			/*
+			 * Watch out!
+			 *
+			 * Otus uses slightly different density values than
+			 * those from the 802.11n spec.
+			 */
+
+			density = max_t(unsigned int, density + 1, 7u);
+		}
+
+		SET_VAL(CARL9170_TX_SUPER_AMPDU_DENSITY,
+			txc->s.ampdu_settings, density);
+
+		SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR,
+			txc->s.ampdu_settings, factor);
+
+		for (i = 0; i < CARL9170_TX_MAX_RATES; i++) {
+			txrate = &info->control.rates[i];
+			if (txrate->idx >= 0) {
+				txc->s.ri[i] =
+					CARL9170_TX_SUPER_RI_AMPDU;
+
+				if (WARN_ON(!(txrate->flags &
+					      IEEE80211_TX_RC_MCS))) {
+					/*
+					 * Not sure if it's even possible
+					 * to aggregate non-ht rates with
+					 * this HW.
+					 */
+					goto err_out;
+				}
+				continue;
+			}
+
+			txrate->idx = 0;
+			txrate->count = ar->hw->max_rate_tries;
+		}
+
+		mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR);
+	}
+
+	/*
+	 * NOTE: For the first rate, the ERP & AMPDU flags are directly
+	 * taken from mac_control. For all fallback rate, the firmware
+	 * updates the mac_control flags from the rate info field.
+	 */
+	for (i = 1; i < CARL9170_TX_MAX_RATES; i++) {
+		txrate = &info->control.rates[i];
+		if (txrate->idx < 0)
+			break;
+
+		SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i],
+			txrate->count);
+
+		if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
+			txc->s.ri[i] |= (AR9170_TX_MAC_PROT_RTS <<
+				CARL9170_TX_SUPER_RI_ERP_PROT_S);
+		else if (carl9170_tx_cts_check(ar, txrate))
+			txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS <<
+				CARL9170_TX_SUPER_RI_ERP_PROT_S);
+
+		txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate);
+	}
+
+	txrate = &info->control.rates[0];
+	SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count);
+
+	if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
+		mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
+	else if (carl9170_tx_cts_check(ar, txrate))
+		mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
+
+	txc->s.len = cpu_to_le16(skb->len);
+	txc->f.length = cpu_to_le16(len + FCS_LEN);
+	txc->f.mac_control = mac_tmp;
+	txc->f.phy_control = carl9170_tx_physet(ar, info, txrate);
+
+	arinfo = (void *)info->rate_driver_data;
+	arinfo->timeout = jiffies;
+	arinfo->ar = ar;
+	kref_init(&arinfo->ref);
+	return 0;
+
+err_out:
+	skb_pull(skb, sizeof(*txc));
+	return -EINVAL;
+}
+
+static void carl9170_set_immba(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct _carl9170_tx_superframe *super;
+
+	super = (void *) skb->data;
+	super->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_BA);
+}
+
+static void carl9170_set_ampdu_params(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct _carl9170_tx_superframe *super;
+	int tmp;
+
+	super = (void *) skb->data;
+
+	tmp = (super->s.ampdu_settings & CARL9170_TX_SUPER_AMPDU_DENSITY) <<
+		CARL9170_TX_SUPER_AMPDU_DENSITY_S;
+
+	/*
+	 * If you haven't noticed carl9170_tx_prepare has already filled
+	 * in all ampdu spacing & factor parameters.
+	 * Now it's the time to check whenever the settings have to be
+	 * updated by the firmware, or if everything is still the same.
+	 *
+	 * There's no sane way to handle different density values with
+	 * this hardware, so we may as well just do the compare in the
+	 * driver.
+	 */
+
+	if (tmp != ar->current_density) {
+		ar->current_density = tmp;
+		super->s.ampdu_settings |=
+			CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY;
+	}
+
+	tmp = (super->s.ampdu_settings & CARL9170_TX_SUPER_AMPDU_FACTOR) <<
+		CARL9170_TX_SUPER_AMPDU_FACTOR_S;
+
+	if (tmp != ar->current_factor) {
+		ar->current_factor = tmp;
+		super->s.ampdu_settings |=
+			CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR;
+	}
+}
+
+static bool carl9170_tx_rate_check(struct ar9170 *ar, struct sk_buff *_dest,
+				   struct sk_buff *_src)
+{
+	struct _carl9170_tx_superframe *dest, *src;
+
+	dest = (void *) _dest->data;
+	src = (void *) _src->data;
+
+	/*
+	 * The mac80211 rate control algorithm expects that all MPDUs in
+	 * an AMPDU share the same tx vectors.
+	 * This is not really obvious right now, because the hardware
+	 * does the AMPDU setup according to its own rulebook.
+	 * Our nicely assembled, strictly monotonic increasing mpdu
+	 * chains will be broken up, mashed back together...
+	 */
+
+	return (dest->f.phy_control == src->f.phy_control);
+}
+
+static void carl9170_tx_ampdu(struct ar9170 *ar)
+{
+	struct sk_buff_head agg;
+	struct carl9170_sta_tid *tid_info;
+	struct sk_buff *skb, *first;
+	unsigned int i = 0, done_ampdus = 0;
+	u16 seq, queue, tmpssn;
+
+	atomic_inc(&ar->tx_ampdu_scheduler);
+	ar->tx_ampdu_schedule = false;
+
+	if (atomic_read(&ar->tx_ampdu_upload))
+		return;
+
+	if (!ar->tx_ampdu_list_len)
+		return;
+
+	__skb_queue_head_init(&agg);
+
+	rcu_read_lock();
+	tid_info = rcu_dereference(ar->tx_ampdu_iter);
+	if (WARN_ON_ONCE(!tid_info)) {
+		rcu_read_unlock();
+		return;
+	}
+
+retry:
+	list_for_each_entry_continue_rcu(tid_info, &ar->tx_ampdu_list, list) {
+		i++;
+
+		if (tid_info->state < CARL9170_TID_STATE_PROGRESS)
+			continue;
+
+		queue = TID_TO_WME_AC(tid_info->tid);
+
+		spin_lock_bh(&tid_info->lock);
+		if (tid_info->state != CARL9170_TID_STATE_XMIT)
+			goto processed;
+
+		tid_info->counter++;
+		first = skb_peek(&tid_info->queue);
+		tmpssn = carl9170_get_seq(first);
+		seq = tid_info->snx;
+
+		if (unlikely(tmpssn != seq)) {
+			tid_info->state = CARL9170_TID_STATE_IDLE;
+
+			goto processed;
+		}
+
+		while ((skb = skb_peek(&tid_info->queue))) {
+			/* strict 0, 1, ..., n - 1, n frame sequence order */
+			if (unlikely(carl9170_get_seq(skb) != seq))
+				break;
+
+			/* don't upload more than AMPDU FACTOR allows. */
+			if (unlikely(SEQ_DIFF(tid_info->snx, tid_info->bsn) >=
+			    (tid_info->max - 1)))
+				break;
+
+			if (!carl9170_tx_rate_check(ar, skb, first))
+				break;
+
+			atomic_inc(&ar->tx_ampdu_upload);
+			tid_info->snx = seq = SEQ_NEXT(seq);
+			__skb_unlink(skb, &tid_info->queue);
+
+			__skb_queue_tail(&agg, skb);
+
+			if (skb_queue_len(&agg) >= CARL9170_NUM_TX_AGG_MAX)
+				break;
+		}
+
+		if (skb_queue_empty(&tid_info->queue) ||
+		    carl9170_get_seq(skb_peek(&tid_info->queue)) !=
+		    tid_info->snx) {
+			/*
+			 * stop TID, if A-MPDU frames are still missing,
+			 * or whenever the queue is empty.
+			 */
+
+			tid_info->state = CARL9170_TID_STATE_IDLE;
+		}
+		done_ampdus++;
+
+processed:
+		spin_unlock_bh(&tid_info->lock);
+
+		if (skb_queue_empty(&agg))
+			continue;
+
+		/* apply ampdu spacing & factor settings */
+		carl9170_set_ampdu_params(ar, skb_peek(&agg));
+
+		/* set aggregation push bit */
+		carl9170_set_immba(ar, skb_peek_tail(&agg));
+
+		spin_lock_bh(&ar->tx_pending[queue].lock);
+		skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]);
+		spin_unlock_bh(&ar->tx_pending[queue].lock);
+		ar->tx_schedule = true;
+	}
+	if ((done_ampdus++ == 0) && (i++ == 0))
+		goto retry;
+
+	rcu_assign_pointer(ar->tx_ampdu_iter, tid_info);
+	rcu_read_unlock();
+}
+
+static struct sk_buff *carl9170_tx_pick_skb(struct ar9170 *ar,
+					    struct sk_buff_head *queue)
+{
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *info;
+	struct carl9170_tx_info *arinfo;
+
+	BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
+
+	spin_lock_bh(&queue->lock);
+	skb = skb_peek(queue);
+	if (unlikely(!skb))
+		goto err_unlock;
+
+	if (carl9170_alloc_dev_space(ar, skb))
+		goto err_unlock;
+
+	__skb_unlink(skb, queue);
+	spin_unlock_bh(&queue->lock);
+
+	info = IEEE80211_SKB_CB(skb);
+	arinfo = (void *) info->rate_driver_data;
+
+	arinfo->timeout = jiffies;
+
+	/*
+	 * increase ref count to "2".
+	 * Ref counting is the easiest way to solve the race between
+	 * the the urb's completion routine: carl9170_tx_callback and
+	 * wlan tx status functions: carl9170_tx_status/janitor.
+	 */
+	carl9170_tx_get_skb(skb);
+
+	return skb;
+
+err_unlock:
+	spin_unlock_bh(&queue->lock);
+	return NULL;
+}
+
+void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct _carl9170_tx_superframe *super;
+	uint8_t q = 0;
+
+	ar->tx_dropped++;
+
+	super = (void *)skb->data;
+	SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, q,
+		ar9170_qmap[carl9170_get_queue(ar, skb)]);
+	__carl9170_tx_process_status(ar, super->s.cookie, q);
+}
+
+static void carl9170_tx(struct ar9170 *ar)
+{
+	struct sk_buff *skb;
+	unsigned int i, q;
+	bool schedule_garbagecollector = false;
+
+	ar->tx_schedule = false;
+
+	if (unlikely(!IS_STARTED(ar)))
+		return;
+
+	carl9170_usb_handle_tx_err(ar);
+
+	for (i = 0; i < ar->hw->queues; i++) {
+		while (!skb_queue_empty(&ar->tx_pending[i])) {
+			skb = carl9170_tx_pick_skb(ar, &ar->tx_pending[i]);
+			if (unlikely(!skb))
+				break;
+
+			atomic_inc(&ar->tx_total_pending);
+
+			q = __carl9170_get_queue(ar, i);
+			/*
+			 * NB: tx_status[i] vs. tx_status[q],
+			 * TODO: Move into pick_skb or alloc_dev_space.
+			 */
+			skb_queue_tail(&ar->tx_status[q], skb);
+
+			carl9170_usb_tx(ar, skb);
+			schedule_garbagecollector = true;
+		}
+	}
+
+	if (!schedule_garbagecollector)
+		return;
+
+	ieee80211_queue_delayed_work(ar->hw, &ar->tx_janitor,
+		msecs_to_jiffies(CARL9170_TX_TIMEOUT));
+}
+
+static bool carl9170_tx_ampdu_queue(struct ar9170 *ar,
+	struct ieee80211_sta *sta, struct sk_buff *skb)
+{
+	struct carl9170_sta_info *sta_info;
+	struct carl9170_sta_tid *agg;
+	struct sk_buff *iter;
+	unsigned int max;
+	u16 tid, seq, qseq, off;
+	bool run = false;
+
+	tid = carl9170_get_tid(skb);
+	seq = carl9170_get_seq(skb);
+	sta_info = (void *) sta->drv_priv;
+
+	rcu_read_lock();
+	agg = rcu_dereference(sta_info->agg[tid]);
+	max = sta_info->ampdu_max_len;
+
+	if (!agg)
+		goto err_unlock_rcu;
+
+	spin_lock_bh(&agg->lock);
+	if (unlikely(agg->state < CARL9170_TID_STATE_IDLE))
+		goto err_unlock;
+
+	/* check if sequence is within the BA window */
+	if (unlikely(!BAW_WITHIN(agg->bsn, CARL9170_BAW_BITS, seq)))
+		goto err_unlock;
+
+	if (WARN_ON_ONCE(!BAW_WITHIN(agg->snx, CARL9170_BAW_BITS, seq)))
+		goto err_unlock;
+
+	off = SEQ_DIFF(seq, agg->bsn);
+	if (WARN_ON_ONCE(test_and_set_bit(off, agg->bitmap)))
+		goto err_unlock;
+
+	if (likely(BAW_WITHIN(agg->hsn, CARL9170_BAW_BITS, seq))) {
+		__skb_queue_tail(&agg->queue, skb);
+		agg->hsn = seq;
+		goto queued;
+	}
+
+	skb_queue_reverse_walk(&agg->queue, iter) {
+		qseq = carl9170_get_seq(iter);
+
+		if (BAW_WITHIN(qseq, CARL9170_BAW_BITS, seq)) {
+			__skb_queue_after(&agg->queue, iter, skb);
+			goto queued;
+		}
+	}
+
+	__skb_queue_head(&agg->queue, skb);
+queued:
+
+	if (unlikely(agg->state != CARL9170_TID_STATE_XMIT)) {
+		if (agg->snx == carl9170_get_seq(skb_peek(&agg->queue))) {
+			agg->state = CARL9170_TID_STATE_XMIT;
+			run = true;
+		}
+	}
+
+	spin_unlock_bh(&agg->lock);
+	rcu_read_unlock();
+
+	return run;
+
+err_unlock:
+	spin_unlock_bh(&agg->lock);
+
+err_unlock_rcu:
+	rcu_read_unlock();
+	carl9170_tx_status(ar, skb, false);
+	ar->tx_dropped++;
+	return false;
+}
+
+int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct ar9170 *ar = hw->priv;
+	struct ieee80211_tx_info *info;
+	struct ieee80211_sta *sta;
+	bool run;
+
+	if (unlikely(!IS_STARTED(ar)))
+		goto err_free;
+
+	info = IEEE80211_SKB_CB(skb);
+	sta = info->control.sta;
+
+	if (unlikely(carl9170_tx_prepare(ar, skb)))
+		goto err_free;
+
+	carl9170_tx_accounting(ar, skb);
+	/*
+	 * from now on, one has to use carl9170_tx_status to free
+	 * all ressouces which are associated with the frame.
+	 */
+
+	if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+		if (WARN_ON_ONCE(!sta))
+			goto err_free;
+
+		run = carl9170_tx_ampdu_queue(ar, sta, skb);
+		if (run)
+			carl9170_tx_ampdu(ar);
+
+	} else {
+		unsigned int queue = skb_get_queue_mapping(skb);
+
+		skb_queue_tail(&ar->tx_pending[queue], skb);
+	}
+
+	carl9170_tx(ar);
+	return NETDEV_TX_OK;
+
+err_free:
+	ar->tx_dropped++;
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+void carl9170_tx_scheduler(struct ar9170 *ar)
+{
+
+	if (ar->tx_ampdu_schedule)
+		carl9170_tx_ampdu(ar);
+
+	if (ar->tx_schedule)
+		carl9170_tx(ar);
+}
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
new file mode 100644
index 0000000..c7f6193
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -0,0 +1,1136 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * USB - frontend
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 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/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <linux/device.h>
+#include <net/mac80211.h>
+#include "carl9170.h"
+#include "cmd.h"
+#include "hw.h"
+#include "fwcmd.h"
+
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_AUTHOR("Christian Lamparter <chunkeey@googlemail.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless");
+MODULE_FIRMWARE(CARL9170FW_NAME);
+MODULE_ALIAS("ar9170usb");
+MODULE_ALIAS("arusb_lnx");
+
+/*
+ * Note:
+ *
+ * Always update our wiki's device list (located at:
+ * http://wireless.kernel.org/en/users/Drivers/ar9170/devices ),
+ * whenever you add a new device.
+ */
+static struct usb_device_id carl9170_usb_ids[] = {
+	/* Atheros 9170 */
+	{ USB_DEVICE(0x0cf3, 0x9170) },
+	/* Atheros TG121N */
+	{ USB_DEVICE(0x0cf3, 0x1001) },
+	/* TP-Link TL-WN821N v2 */
+	{ USB_DEVICE(0x0cf3, 0x1002), .driver_info = CARL9170_WPS_BUTTON |
+		 CARL9170_ONE_LED },
+	/* 3Com Dual Band 802.11n USB Adapter */
+	{ USB_DEVICE(0x0cf3, 0x1010) },
+	/* H3C Dual Band 802.11n USB Adapter */
+	{ USB_DEVICE(0x0cf3, 0x1011) },
+	/* Cace Airpcap NX */
+	{ USB_DEVICE(0xcace, 0x0300) },
+	/* D-Link DWA 160 A1 */
+	{ USB_DEVICE(0x07d1, 0x3c10) },
+	/* D-Link DWA 160 A2 */
+	{ USB_DEVICE(0x07d1, 0x3a09) },
+	/* Netgear WNA1000 */
+	{ USB_DEVICE(0x0846, 0x9040) },
+	/* Netgear WNDA3100 */
+	{ USB_DEVICE(0x0846, 0x9010) },
+	/* Netgear WN111 v2 */
+	{ USB_DEVICE(0x0846, 0x9001), .driver_info = CARL9170_ONE_LED },
+	/* Zydas ZD1221 */
+	{ USB_DEVICE(0x0ace, 0x1221) },
+	/* Proxim ORiNOCO 802.11n USB */
+	{ USB_DEVICE(0x1435, 0x0804) },
+	/* WNC Generic 11n USB Dongle */
+	{ USB_DEVICE(0x1435, 0x0326) },
+	/* ZyXEL NWD271N */
+	{ USB_DEVICE(0x0586, 0x3417) },
+	/* Z-Com UB81 BG */
+	{ USB_DEVICE(0x0cde, 0x0023) },
+	/* Z-Com UB82 ABG */
+	{ USB_DEVICE(0x0cde, 0x0026) },
+	/* Sphairon Homelink 1202 */
+	{ USB_DEVICE(0x0cde, 0x0027) },
+	/* Arcadyan WN7512 */
+	{ USB_DEVICE(0x083a, 0xf522) },
+	/* Planex GWUS300 */
+	{ USB_DEVICE(0x2019, 0x5304) },
+	/* IO-Data WNGDNUS2 */
+	{ USB_DEVICE(0x04bb, 0x093f) },
+	/* NEC WL300NU-G */
+	{ USB_DEVICE(0x0409, 0x0249) },
+	/* AVM FRITZ!WLAN USB Stick N */
+	{ USB_DEVICE(0x057c, 0x8401) },
+	/* AVM FRITZ!WLAN USB Stick N 2.4 */
+	{ USB_DEVICE(0x057c, 0x8402) },
+	/* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */
+	{ USB_DEVICE(0x1668, 0x1200) },
+
+	/* terminate */
+	{}
+};
+MODULE_DEVICE_TABLE(usb, carl9170_usb_ids);
+
+static void carl9170_usb_submit_data_urb(struct ar9170 *ar)
+{
+	struct urb *urb;
+	int err;
+
+	if (atomic_inc_return(&ar->tx_anch_urbs) > AR9170_NUM_TX_URBS)
+		goto err_acc;
+
+	urb = usb_get_from_anchor(&ar->tx_wait);
+	if (!urb)
+		goto err_acc;
+
+	usb_anchor_urb(urb, &ar->tx_anch);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (unlikely(err)) {
+		if (net_ratelimit()) {
+			dev_err(&ar->udev->dev, "tx submit failed (%d)\n",
+				urb->status);
+		}
+
+		usb_unanchor_urb(urb);
+		usb_anchor_urb(urb, &ar->tx_err);
+	}
+
+	usb_free_urb(urb);
+
+	if (likely(err == 0))
+		return;
+
+err_acc:
+	atomic_dec(&ar->tx_anch_urbs);
+}
+
+static void carl9170_usb_tx_data_complete(struct urb *urb)
+{
+	struct ar9170 *ar = (struct ar9170 *)
+	      usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+
+	if (WARN_ON_ONCE(!ar)) {
+		dev_kfree_skb_irq(urb->context);
+		return;
+	}
+
+	atomic_dec(&ar->tx_anch_urbs);
+
+	switch (urb->status) {
+	/* everything is fine */
+	case 0:
+		carl9170_tx_callback(ar, (void *)urb->context);
+		break;
+
+	/* disconnect */
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ENODEV:
+	case -ESHUTDOWN:
+		/*
+		 * Defer the frame clean-up to the tasklet worker.
+		 * This is necessary, because carl9170_tx_drop
+		 * does not work in an irqsave context.
+		 */
+		usb_anchor_urb(urb, &ar->tx_err);
+		return;
+
+	/* a random transmission error has occurred? */
+	default:
+		if (net_ratelimit()) {
+			dev_err(&ar->udev->dev, "tx failed (%d)\n",
+				urb->status);
+		}
+
+		usb_anchor_urb(urb, &ar->tx_err);
+		break;
+	}
+
+	if (likely(IS_STARTED(ar)))
+		carl9170_usb_submit_data_urb(ar);
+}
+
+static int carl9170_usb_submit_cmd_urb(struct ar9170 *ar)
+{
+	struct urb *urb;
+	int err;
+
+	if (atomic_inc_return(&ar->tx_cmd_urbs) != 1) {
+		atomic_dec(&ar->tx_cmd_urbs);
+		return 0;
+	}
+
+	urb = usb_get_from_anchor(&ar->tx_cmd);
+	if (!urb) {
+		atomic_dec(&ar->tx_cmd_urbs);
+		return 0;
+	}
+
+	usb_anchor_urb(urb, &ar->tx_anch);
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (unlikely(err)) {
+		usb_unanchor_urb(urb);
+		atomic_dec(&ar->tx_cmd_urbs);
+	}
+	usb_free_urb(urb);
+
+	return err;
+}
+
+static void carl9170_usb_cmd_complete(struct urb *urb)
+{
+	struct ar9170 *ar = urb->context;
+	int err = 0;
+
+	if (WARN_ON_ONCE(!ar))
+		return;
+
+	atomic_dec(&ar->tx_cmd_urbs);
+
+	switch (urb->status) {
+	/* everything is fine */
+	case 0:
+		break;
+
+	/* disconnect */
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ENODEV:
+	case -ESHUTDOWN:
+		return;
+
+	default:
+		err = urb->status;
+		break;
+	}
+
+	if (!IS_INITIALIZED(ar))
+		return;
+
+	if (err)
+		dev_err(&ar->udev->dev, "submit cmd cb failed (%d).\n", err);
+
+	err = carl9170_usb_submit_cmd_urb(ar);
+	if (err)
+		dev_err(&ar->udev->dev, "submit cmd failed (%d).\n", err);
+}
+
+static void carl9170_usb_rx_irq_complete(struct urb *urb)
+{
+	struct ar9170 *ar = urb->context;
+
+	if (WARN_ON_ONCE(!ar))
+		return;
+
+	switch (urb->status) {
+	/* everything is fine */
+	case 0:
+		break;
+
+	/* disconnect */
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ENODEV:
+	case -ESHUTDOWN:
+		return;
+
+	default:
+		goto resubmit;
+	}
+
+	carl9170_handle_command_response(ar, urb->transfer_buffer,
+					 urb->actual_length);
+
+resubmit:
+	usb_anchor_urb(urb, &ar->rx_anch);
+	if (unlikely(usb_submit_urb(urb, GFP_ATOMIC)))
+		usb_unanchor_urb(urb);
+}
+
+static int carl9170_usb_submit_rx_urb(struct ar9170 *ar, gfp_t gfp)
+{
+	struct urb *urb;
+	int err = 0, runs = 0;
+
+	while ((atomic_read(&ar->rx_anch_urbs) < AR9170_NUM_RX_URBS) &&
+		(runs++ < AR9170_NUM_RX_URBS)) {
+		err = -ENOSPC;
+		urb = usb_get_from_anchor(&ar->rx_pool);
+		if (urb) {
+			usb_anchor_urb(urb, &ar->rx_anch);
+			err = usb_submit_urb(urb, gfp);
+			if (unlikely(err)) {
+				usb_unanchor_urb(urb);
+				usb_anchor_urb(urb, &ar->rx_pool);
+			} else {
+				atomic_dec(&ar->rx_pool_urbs);
+				atomic_inc(&ar->rx_anch_urbs);
+			}
+			usb_free_urb(urb);
+		}
+	}
+
+	return err;
+}
+
+static void carl9170_usb_rx_work(struct ar9170 *ar)
+{
+	struct urb *urb;
+	int i;
+
+	for (i = 0; i < AR9170_NUM_RX_URBS_POOL; i++) {
+		urb = usb_get_from_anchor(&ar->rx_work);
+		if (!urb)
+			break;
+
+		atomic_dec(&ar->rx_work_urbs);
+		if (IS_INITIALIZED(ar)) {
+			carl9170_rx(ar, urb->transfer_buffer,
+				    urb->actual_length);
+		}
+
+		usb_anchor_urb(urb, &ar->rx_pool);
+		atomic_inc(&ar->rx_pool_urbs);
+
+		usb_free_urb(urb);
+
+		carl9170_usb_submit_rx_urb(ar, GFP_ATOMIC);
+	}
+}
+
+void carl9170_usb_handle_tx_err(struct ar9170 *ar)
+{
+	struct urb *urb;
+
+	while ((urb = usb_get_from_anchor(&ar->tx_err))) {
+		struct sk_buff *skb = (void *)urb->context;
+
+		carl9170_tx_drop(ar, skb);
+		carl9170_tx_callback(ar, skb);
+		usb_free_urb(urb);
+	}
+}
+
+static void carl9170_usb_tasklet(unsigned long data)
+{
+	struct ar9170 *ar = (struct ar9170 *) data;
+
+	if (!IS_INITIALIZED(ar))
+		return;
+
+	carl9170_usb_rx_work(ar);
+
+	/*
+	 * Strictly speaking: The tx scheduler is not part of the USB system.
+	 * But the rx worker returns frames back to the mac80211-stack and
+	 * this is the _perfect_ place to generate the next transmissions.
+	 */
+	if (IS_STARTED(ar))
+		carl9170_tx_scheduler(ar);
+}
+
+static void carl9170_usb_rx_complete(struct urb *urb)
+{
+	struct ar9170 *ar = (struct ar9170 *)urb->context;
+	int err;
+
+	if (WARN_ON_ONCE(!ar))
+		return;
+
+	atomic_dec(&ar->rx_anch_urbs);
+
+	switch (urb->status) {
+	case 0:
+		/* rx path */
+		usb_anchor_urb(urb, &ar->rx_work);
+		atomic_inc(&ar->rx_work_urbs);
+		break;
+
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ENODEV:
+	case -ESHUTDOWN:
+		/* handle disconnect events*/
+		return;
+
+	default:
+		/* handle all other errors */
+		usb_anchor_urb(urb, &ar->rx_pool);
+		atomic_inc(&ar->rx_pool_urbs);
+		break;
+	}
+
+	err = carl9170_usb_submit_rx_urb(ar, GFP_ATOMIC);
+	if (unlikely(err)) {
+		/*
+		 * usb_submit_rx_urb reported a problem.
+		 * In case this is due to a rx buffer shortage,
+		 * elevate the tasklet worker priority to
+		 * the highest available level.
+		 */
+		tasklet_hi_schedule(&ar->usb_tasklet);
+
+		if (atomic_read(&ar->rx_anch_urbs) == 0) {
+			/*
+			 * The system is too slow to cope with
+			 * the enormous workload. We have simply
+			 * run out of active rx urbs and this
+			 * unfortunatly leads to an unpredictable
+			 * device.
+			 */
+
+			carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
+		}
+	} else {
+		/*
+		 * Using anything less than _high_ priority absolutely
+		 * kills the rx performance my UP-System...
+		 */
+		tasklet_hi_schedule(&ar->usb_tasklet);
+	}
+}
+
+static struct urb *carl9170_usb_alloc_rx_urb(struct ar9170 *ar, gfp_t gfp)
+{
+	struct urb *urb;
+	void *buf;
+
+	buf = kmalloc(ar->fw.rx_size, gfp);
+	if (!buf)
+		return NULL;
+
+	urb = usb_alloc_urb(0, gfp);
+	if (!urb) {
+		kfree(buf);
+		return NULL;
+	}
+
+	usb_fill_bulk_urb(urb, ar->udev, usb_rcvbulkpipe(ar->udev,
+			  AR9170_USB_EP_RX), buf, ar->fw.rx_size,
+			  carl9170_usb_rx_complete, ar);
+
+	urb->transfer_flags |= URB_FREE_BUFFER;
+
+	return urb;
+}
+
+static int carl9170_usb_send_rx_irq_urb(struct ar9170 *ar)
+{
+	struct urb *urb = NULL;
+	void *ibuf;
+	int err = -ENOMEM;
+
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb)
+		goto out;
+
+	ibuf = kmalloc(AR9170_USB_EP_CTRL_MAX, GFP_KERNEL);
+	if (!ibuf)
+		goto out;
+
+	usb_fill_int_urb(urb, ar->udev, usb_rcvintpipe(ar->udev,
+			 AR9170_USB_EP_IRQ), ibuf, AR9170_USB_EP_CTRL_MAX,
+			 carl9170_usb_rx_irq_complete, ar, 1);
+
+	urb->transfer_flags |= URB_FREE_BUFFER;
+
+	usb_anchor_urb(urb, &ar->rx_anch);
+	err = usb_submit_urb(urb, GFP_KERNEL);
+	if (err)
+		usb_unanchor_urb(urb);
+
+out:
+	usb_free_urb(urb);
+	return err;
+}
+
+static int carl9170_usb_init_rx_bulk_urbs(struct ar9170 *ar)
+{
+	struct urb *urb;
+	int i, err = -EINVAL;
+
+	/*
+	 * The driver actively maintains a second shadow
+	 * pool for inactive, but fully-prepared rx urbs.
+	 *
+	 * The pool should help the driver to master huge
+	 * workload spikes without running the risk of
+	 * undersupplying the hardware or wasting time by
+	 * processing rx data (streams) inside the urb
+	 * completion (hardirq context).
+	 */
+	for (i = 0; i < AR9170_NUM_RX_URBS_POOL; i++) {
+		urb = carl9170_usb_alloc_rx_urb(ar, GFP_KERNEL);
+		if (!urb) {
+			err = -ENOMEM;
+			goto err_out;
+		}
+
+		usb_anchor_urb(urb, &ar->rx_pool);
+		atomic_inc(&ar->rx_pool_urbs);
+		usb_free_urb(urb);
+	}
+
+	err = carl9170_usb_submit_rx_urb(ar, GFP_KERNEL);
+	if (err)
+		goto err_out;
+
+	/* the device now waiting for the firmware. */
+	carl9170_set_state_when(ar, CARL9170_STOPPED, CARL9170_IDLE);
+	return 0;
+
+err_out:
+
+	usb_scuttle_anchored_urbs(&ar->rx_pool);
+	usb_scuttle_anchored_urbs(&ar->rx_work);
+	usb_kill_anchored_urbs(&ar->rx_anch);
+	return err;
+}
+
+static int carl9170_usb_flush(struct ar9170 *ar)
+{
+	struct urb *urb;
+	int ret, err = 0;
+
+	while ((urb = usb_get_from_anchor(&ar->tx_wait))) {
+		struct sk_buff *skb = (void *)urb->context;
+		carl9170_tx_drop(ar, skb);
+		carl9170_tx_callback(ar, skb);
+		usb_free_urb(urb);
+	}
+
+	ret = usb_wait_anchor_empty_timeout(&ar->tx_cmd, HZ);
+	if (ret == 0)
+		err = -ETIMEDOUT;
+
+	/* lets wait a while until the tx - queues are dried out */
+	ret = usb_wait_anchor_empty_timeout(&ar->tx_anch, HZ);
+	if (ret == 0)
+		err = -ETIMEDOUT;
+
+	usb_kill_anchored_urbs(&ar->tx_anch);
+	carl9170_usb_handle_tx_err(ar);
+
+	return err;
+}
+
+static void carl9170_usb_cancel_urbs(struct ar9170 *ar)
+{
+	int err;
+
+	carl9170_set_state(ar, CARL9170_UNKNOWN_STATE);
+
+	err = carl9170_usb_flush(ar);
+	if (err)
+		dev_err(&ar->udev->dev, "stuck tx urbs!\n");
+
+	usb_poison_anchored_urbs(&ar->tx_anch);
+	carl9170_usb_handle_tx_err(ar);
+	usb_poison_anchored_urbs(&ar->rx_anch);
+
+	tasklet_kill(&ar->usb_tasklet);
+
+	usb_scuttle_anchored_urbs(&ar->rx_work);
+	usb_scuttle_anchored_urbs(&ar->rx_pool);
+	usb_scuttle_anchored_urbs(&ar->tx_cmd);
+}
+
+int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd,
+			const bool free_buf)
+{
+	struct urb *urb;
+
+	if (!IS_INITIALIZED(ar))
+		return -EPERM;
+
+	if (WARN_ON(cmd->hdr.len > CARL9170_MAX_CMD_LEN - 4))
+		return -EINVAL;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb)
+		return -ENOMEM;
+
+	usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev,
+		AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4,
+		carl9170_usb_cmd_complete, ar, 1);
+
+	if (free_buf)
+		urb->transfer_flags |= URB_FREE_BUFFER;
+
+	usb_anchor_urb(urb, &ar->tx_cmd);
+	usb_free_urb(urb);
+
+	return carl9170_usb_submit_cmd_urb(ar);
+}
+
+int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd,
+	unsigned int plen, void *payload, unsigned int outlen, void *out)
+{
+	int err = -ENOMEM;
+
+	if (!IS_ACCEPTING_CMD(ar))
+		return -EIO;
+
+	if (!(cmd & CARL9170_CMD_ASYNC_FLAG))
+		might_sleep();
+
+	ar->cmd.hdr.len = plen;
+	ar->cmd.hdr.cmd = cmd;
+	/* writing multiple regs fills this buffer already */
+	if (plen && payload != (u8 *)(ar->cmd.data))
+		memcpy(ar->cmd.data, payload, plen);
+
+	spin_lock_bh(&ar->cmd_lock);
+	ar->readbuf = (u8 *)out;
+	ar->readlen = outlen;
+	spin_unlock_bh(&ar->cmd_lock);
+
+	err = __carl9170_exec_cmd(ar, &ar->cmd, false);
+
+	if (!(cmd & CARL9170_CMD_ASYNC_FLAG)) {
+		err = wait_for_completion_timeout(&ar->cmd_wait, HZ);
+		if (err == 0) {
+			err = -ETIMEDOUT;
+			goto err_unbuf;
+		}
+
+		if (ar->readlen != outlen) {
+			err = -EMSGSIZE;
+			goto err_unbuf;
+		}
+	}
+
+	return 0;
+
+err_unbuf:
+	/* Maybe the device was removed in the moment we were waiting? */
+	if (IS_STARTED(ar)) {
+		dev_err(&ar->udev->dev, "no command feedback "
+			"received (%d).\n", err);
+
+		/* provide some maybe useful debug information */
+		print_hex_dump_bytes("carl9170 cmd: ", DUMP_PREFIX_NONE,
+				     &ar->cmd, plen + 4);
+
+		carl9170_restart(ar, CARL9170_RR_COMMAND_TIMEOUT);
+	}
+
+	/* invalidate to avoid completing the next command prematurely */
+	spin_lock_bh(&ar->cmd_lock);
+	ar->readbuf = NULL;
+	ar->readlen = 0;
+	spin_unlock_bh(&ar->cmd_lock);
+
+	return err;
+}
+
+void carl9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct urb *urb;
+	struct ar9170_stream *tx_stream;
+	void *data;
+	unsigned int len;
+
+	if (!IS_STARTED(ar))
+		goto err_drop;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb)
+		goto err_drop;
+
+	if (ar->fw.tx_stream) {
+		tx_stream = (void *) (skb->data - sizeof(*tx_stream));
+
+		len = skb->len + sizeof(*tx_stream);
+		tx_stream->length = cpu_to_le16(len);
+		tx_stream->tag = cpu_to_le16(AR9170_TX_STREAM_TAG);
+		data = tx_stream;
+	} else {
+		data = skb->data;
+		len = skb->len;
+	}
+
+	usb_fill_bulk_urb(urb, ar->udev, usb_sndbulkpipe(ar->udev,
+		AR9170_USB_EP_TX), data, len,
+		carl9170_usb_tx_data_complete, skb);
+
+	urb->transfer_flags |= URB_ZERO_PACKET;
+
+	usb_anchor_urb(urb, &ar->tx_wait);
+
+	usb_free_urb(urb);
+
+	carl9170_usb_submit_data_urb(ar);
+	return;
+
+err_drop:
+	carl9170_tx_drop(ar, skb);
+	carl9170_tx_callback(ar, skb);
+}
+
+static void carl9170_release_firmware(struct ar9170 *ar)
+{
+	if (ar->fw.fw) {
+		release_firmware(ar->fw.fw);
+		memset(&ar->fw, 0, sizeof(ar->fw));
+	}
+}
+
+void carl9170_usb_stop(struct ar9170 *ar)
+{
+	int ret;
+
+	carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STOPPED);
+
+	ret = carl9170_usb_flush(ar);
+	if (ret)
+		dev_err(&ar->udev->dev, "kill pending tx urbs.\n");
+
+	usb_poison_anchored_urbs(&ar->tx_anch);
+	carl9170_usb_handle_tx_err(ar);
+
+	/* kill any pending command */
+	spin_lock_bh(&ar->cmd_lock);
+	ar->readlen = 0;
+	spin_unlock_bh(&ar->cmd_lock);
+	complete_all(&ar->cmd_wait);
+
+	/* This is required to prevent an early completion on _start */
+	INIT_COMPLETION(ar->cmd_wait);
+
+	/*
+	 * Note:
+	 * So far we freed all tx urbs, but we won't dare to touch any rx urbs.
+	 * Else we would end up with a unresponsive device...
+	 */
+}
+
+int carl9170_usb_open(struct ar9170 *ar)
+{
+	usb_unpoison_anchored_urbs(&ar->tx_anch);
+
+	carl9170_set_state_when(ar, CARL9170_STOPPED, CARL9170_IDLE);
+	return 0;
+}
+
+static int carl9170_usb_load_firmware(struct ar9170 *ar)
+{
+	const u8 *data;
+	u8 *buf;
+	unsigned int transfer;
+	size_t len;
+	u32 addr;
+	int err = 0;
+
+	buf = kmalloc(4096, GFP_KERNEL);
+	if (!buf) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	data = ar->fw.fw->data;
+	len = ar->fw.fw->size;
+	addr = ar->fw.address;
+
+	/* this removes the miniboot image */
+	data += ar->fw.offset;
+	len -= ar->fw.offset;
+
+	while (len) {
+		transfer = min_t(unsigned int, len, 4096u);
+		memcpy(buf, data, transfer);
+
+		err = usb_control_msg(ar->udev, usb_sndctrlpipe(ar->udev, 0),
+				      0x30 /* FW DL */, 0x40 | USB_DIR_OUT,
+				      addr >> 8, 0, buf, transfer, 100);
+
+		if (err < 0) {
+			kfree(buf);
+			goto err_out;
+		}
+
+		len -= transfer;
+		data += transfer;
+		addr += transfer;
+	}
+	kfree(buf);
+
+	err = usb_control_msg(ar->udev, usb_sndctrlpipe(ar->udev, 0),
+			      0x31 /* FW DL COMPLETE */,
+			      0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 200);
+
+	if (wait_for_completion_timeout(&ar->fw_boot_wait, HZ) == 0) {
+		err = -ETIMEDOUT;
+		goto err_out;
+	}
+
+	err = carl9170_echo_test(ar, 0x4a110123);
+	if (err)
+		goto err_out;
+
+	/* firmware restarts cmd counter */
+	ar->cmd_seq = -1;
+
+	return 0;
+
+err_out:
+	dev_err(&ar->udev->dev, "firmware upload failed (%d).\n", err);
+	return err;
+}
+
+int carl9170_usb_restart(struct ar9170 *ar)
+{
+	int err = 0;
+
+	if (ar->intf->condition != USB_INTERFACE_BOUND)
+		return 0;
+
+	/* Disable command response sequence counter. */
+	ar->cmd_seq = -2;
+
+	err = carl9170_reboot(ar);
+
+	carl9170_usb_stop(ar);
+
+	if (err)
+		goto err_out;
+
+	tasklet_schedule(&ar->usb_tasklet);
+
+	/* The reboot procedure can take quite a while to complete. */
+	msleep(1100);
+
+	err = carl9170_usb_open(ar);
+	if (err)
+		goto err_out;
+
+	err = carl9170_usb_load_firmware(ar);
+	if (err)
+		goto err_out;
+
+	return 0;
+
+err_out:
+	carl9170_usb_cancel_urbs(ar);
+	return err;
+}
+
+void carl9170_usb_reset(struct ar9170 *ar)
+{
+	/*
+	 * This is the last resort to get the device going again
+	 * without any *user replugging action*.
+	 *
+	 * But there is a catch: usb_reset really is like a physical
+	 * *reconnect*. The mac80211 state will be lost in the process.
+	 * Therefore a userspace application, which is monitoring
+	 * the link must step in.
+	 */
+	carl9170_usb_cancel_urbs(ar);
+
+	carl9170_usb_stop(ar);
+
+	usb_queue_reset_device(ar->intf);
+}
+
+static int carl9170_usb_init_device(struct ar9170 *ar)
+{
+	int err;
+
+	err = carl9170_usb_send_rx_irq_urb(ar);
+	if (err)
+		goto err_out;
+
+	err = carl9170_usb_init_rx_bulk_urbs(ar);
+	if (err)
+		goto err_unrx;
+
+	mutex_lock(&ar->mutex);
+	err = carl9170_usb_load_firmware(ar);
+	mutex_unlock(&ar->mutex);
+	if (err)
+		goto err_unrx;
+
+	return 0;
+
+err_unrx:
+	carl9170_usb_cancel_urbs(ar);
+
+err_out:
+	return err;
+}
+
+static void carl9170_usb_firmware_failed(struct ar9170 *ar)
+{
+	struct device *parent = ar->udev->dev.parent;
+	struct usb_device *udev;
+
+	/*
+	 * Store a copy of the usb_device pointer locally.
+	 * This is because device_release_driver initiates
+	 * carl9170_usb_disconnect, which in turn frees our
+	 * driver context (ar).
+	 */
+	udev = ar->udev;
+
+	complete(&ar->fw_load_wait);
+
+	/* unbind anything failed */
+	if (parent)
+		device_lock(parent);
+
+	device_release_driver(&udev->dev);
+	if (parent)
+		device_unlock(parent);
+
+	usb_put_dev(udev);
+}
+
+static void carl9170_usb_firmware_finish(struct ar9170 *ar)
+{
+	int err;
+
+	err = carl9170_parse_firmware(ar);
+	if (err)
+		goto err_freefw;
+
+	err = carl9170_usb_init_device(ar);
+	if (err)
+		goto err_freefw;
+
+	err = carl9170_usb_open(ar);
+	if (err)
+		goto err_unrx;
+
+	err = carl9170_register(ar);
+
+	carl9170_usb_stop(ar);
+	if (err)
+		goto err_unrx;
+
+	complete(&ar->fw_load_wait);
+	usb_put_dev(ar->udev);
+	return;
+
+err_unrx:
+	carl9170_usb_cancel_urbs(ar);
+
+err_freefw:
+	carl9170_release_firmware(ar);
+	carl9170_usb_firmware_failed(ar);
+}
+
+static void carl9170_usb_firmware_step2(const struct firmware *fw,
+					void *context)
+{
+	struct ar9170 *ar = context;
+
+	if (fw) {
+		ar->fw.fw = fw;
+		carl9170_usb_firmware_finish(ar);
+		return;
+	}
+
+	dev_err(&ar->udev->dev, "firmware not found.\n");
+	carl9170_usb_firmware_failed(ar);
+}
+
+static int carl9170_usb_probe(struct usb_interface *intf,
+			      const struct usb_device_id *id)
+{
+	struct ar9170 *ar;
+	struct usb_device *udev;
+	int err;
+
+	err = usb_reset_device(interface_to_usbdev(intf));
+	if (err)
+		return err;
+
+	ar = carl9170_alloc(sizeof(*ar));
+	if (IS_ERR(ar))
+		return PTR_ERR(ar);
+
+	udev = interface_to_usbdev(intf);
+	usb_get_dev(udev);
+	ar->udev = udev;
+	ar->intf = intf;
+	ar->features = id->driver_info;
+
+	usb_set_intfdata(intf, ar);
+	SET_IEEE80211_DEV(ar->hw, &intf->dev);
+
+	init_usb_anchor(&ar->rx_anch);
+	init_usb_anchor(&ar->rx_pool);
+	init_usb_anchor(&ar->rx_work);
+	init_usb_anchor(&ar->tx_wait);
+	init_usb_anchor(&ar->tx_anch);
+	init_usb_anchor(&ar->tx_cmd);
+	init_usb_anchor(&ar->tx_err);
+	init_completion(&ar->cmd_wait);
+	init_completion(&ar->fw_boot_wait);
+	init_completion(&ar->fw_load_wait);
+	tasklet_init(&ar->usb_tasklet, carl9170_usb_tasklet,
+		     (unsigned long)ar);
+
+	atomic_set(&ar->tx_cmd_urbs, 0);
+	atomic_set(&ar->tx_anch_urbs, 0);
+	atomic_set(&ar->rx_work_urbs, 0);
+	atomic_set(&ar->rx_anch_urbs, 0);
+	atomic_set(&ar->rx_pool_urbs, 0);
+	ar->cmd_seq = -2;
+
+	usb_get_dev(ar->udev);
+
+	carl9170_set_state(ar, CARL9170_STOPPED);
+
+	return request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME,
+		&ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2);
+}
+
+static void carl9170_usb_disconnect(struct usb_interface *intf)
+{
+	struct ar9170 *ar = usb_get_intfdata(intf);
+	struct usb_device *udev;
+
+	if (WARN_ON(!ar))
+		return;
+
+	udev = ar->udev;
+	wait_for_completion(&ar->fw_load_wait);
+
+	if (IS_INITIALIZED(ar)) {
+		carl9170_reboot(ar);
+		carl9170_usb_stop(ar);
+	}
+
+	carl9170_usb_cancel_urbs(ar);
+	carl9170_unregister(ar);
+
+	usb_set_intfdata(intf, NULL);
+
+	carl9170_release_firmware(ar);
+	carl9170_free(ar);
+	usb_put_dev(udev);
+}
+
+#ifdef CONFIG_PM
+static int carl9170_usb_suspend(struct usb_interface *intf,
+				pm_message_t message)
+{
+	struct ar9170 *ar = usb_get_intfdata(intf);
+
+	if (!ar)
+		return -ENODEV;
+
+	carl9170_usb_cancel_urbs(ar);
+
+	/*
+	 * firmware automatically reboots for usb suspend.
+	 */
+
+	return 0;
+}
+
+static int carl9170_usb_resume(struct usb_interface *intf)
+{
+	struct ar9170 *ar = usb_get_intfdata(intf);
+	int err;
+
+	if (!ar)
+		return -ENODEV;
+
+	usb_unpoison_anchored_urbs(&ar->rx_anch);
+
+	err = carl9170_usb_init_device(ar);
+	if (err)
+		goto err_unrx;
+
+	err = carl9170_usb_open(ar);
+	if (err)
+		goto err_unrx;
+
+	return 0;
+
+err_unrx:
+	carl9170_usb_cancel_urbs(ar);
+
+	return err;
+}
+#endif /* CONFIG_PM */
+
+static struct usb_driver carl9170_driver = {
+	.name = KBUILD_MODNAME,
+	.probe = carl9170_usb_probe,
+	.disconnect = carl9170_usb_disconnect,
+	.id_table = carl9170_usb_ids,
+	.soft_unbind = 1,
+#ifdef CONFIG_PM
+	.suspend = carl9170_usb_suspend,
+	.resume = carl9170_usb_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init carl9170_usb_init(void)
+{
+	return usb_register(&carl9170_driver);
+}
+
+static void __exit carl9170_usb_exit(void)
+{
+	usb_deregister(&carl9170_driver);
+}
+
+module_init(carl9170_usb_init);
+module_exit(carl9170_usb_exit);
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
new file mode 100644
index 0000000..ff53f07
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/version.h
@@ -0,0 +1,7 @@
+#ifndef __CARL9170_SHARED_VERSION_H
+#define __CARL9170_SHARED_VERSION_H
+#define CARL9170FW_VERSION_YEAR 10
+#define CARL9170FW_VERSION_MONTH 9
+#define CARL9170FW_VERSION_DAY 28
+#define CARL9170FW_VERSION_GIT "1.8.8.3"
+#endif /* __CARL9170_SHARED_VERSION_H */
diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h
new file mode 100644
index 0000000..24d63b5
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/wlan.h
@@ -0,0 +1,420 @@
+/*
+ * Shared Atheros AR9170 Header
+ *
+ * RX/TX meta descriptor format
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __CARL9170_SHARED_WLAN_H
+#define __CARL9170_SHARED_WLAN_H
+
+#include "fwcmd.h"
+
+#define	AR9170_RX_PHY_RATE_CCK_1M		0x0a
+#define	AR9170_RX_PHY_RATE_CCK_2M		0x14
+#define	AR9170_RX_PHY_RATE_CCK_5M		0x37
+#define	AR9170_RX_PHY_RATE_CCK_11M		0x6e
+
+#define	AR9170_ENC_ALG_NONE			0x0
+#define	AR9170_ENC_ALG_WEP64			0x1
+#define	AR9170_ENC_ALG_TKIP			0x2
+#define	AR9170_ENC_ALG_AESCCMP			0x4
+#define	AR9170_ENC_ALG_WEP128			0x5
+#define	AR9170_ENC_ALG_WEP256			0x6
+#define	AR9170_ENC_ALG_CENC			0x7
+
+#define	AR9170_RX_ENC_SOFTWARE			0x8
+
+#define	AR9170_RX_STATUS_MODULATION		0x03
+#define	AR9170_RX_STATUS_MODULATION_S		0
+#define	AR9170_RX_STATUS_MODULATION_CCK		0x00
+#define	AR9170_RX_STATUS_MODULATION_OFDM	0x01
+#define	AR9170_RX_STATUS_MODULATION_HT		0x02
+#define	AR9170_RX_STATUS_MODULATION_DUPOFDM	0x03
+
+/* depends on modulation */
+#define	AR9170_RX_STATUS_SHORT_PREAMBLE		0x08
+#define	AR9170_RX_STATUS_GREENFIELD		0x08
+
+#define	AR9170_RX_STATUS_MPDU			0x30
+#define	AR9170_RX_STATUS_MPDU_S			4
+#define	AR9170_RX_STATUS_MPDU_SINGLE		0x00
+#define	AR9170_RX_STATUS_MPDU_FIRST		0x20
+#define	AR9170_RX_STATUS_MPDU_MIDDLE		0x30
+#define	AR9170_RX_STATUS_MPDU_LAST		0x10
+
+#define	AR9170_RX_STATUS_CONT_AGGR		0x40
+#define	AR9170_RX_STATUS_TOTAL_ERROR		0x80
+
+#define	AR9170_RX_ERROR_RXTO			0x01
+#define	AR9170_RX_ERROR_OVERRUN			0x02
+#define	AR9170_RX_ERROR_DECRYPT			0x04
+#define	AR9170_RX_ERROR_FCS			0x08
+#define	AR9170_RX_ERROR_WRONG_RA		0x10
+#define	AR9170_RX_ERROR_PLCP			0x20
+#define	AR9170_RX_ERROR_MMIC			0x40
+
+/* these are either-or */
+#define	AR9170_TX_MAC_PROT_RTS			0x0001
+#define	AR9170_TX_MAC_PROT_CTS			0x0002
+#define	AR9170_TX_MAC_PROT			0x0003
+
+#define	AR9170_TX_MAC_NO_ACK			0x0004
+/* if unset, MAC will only do SIFS space before frame */
+#define	AR9170_TX_MAC_BACKOFF			0x0008
+#define	AR9170_TX_MAC_BURST			0x0010
+#define	AR9170_TX_MAC_AGGR			0x0020
+
+/* encryption is a two-bit field */
+#define	AR9170_TX_MAC_ENCR_NONE			0x0000
+#define	AR9170_TX_MAC_ENCR_RC4			0x0040
+#define	AR9170_TX_MAC_ENCR_CENC			0x0080
+#define	AR9170_TX_MAC_ENCR_AES			0x00c0
+
+#define	AR9170_TX_MAC_MMIC			0x0100
+#define	AR9170_TX_MAC_HW_DURATION		0x0200
+#define	AR9170_TX_MAC_QOS_S			10
+#define	AR9170_TX_MAC_QOS			0x0c00
+#define	AR9170_TX_MAC_DISABLE_TXOP		0x1000
+#define	AR9170_TX_MAC_TXOP_RIFS			0x2000
+#define	AR9170_TX_MAC_IMM_BA			0x4000
+
+/* either-or */
+#define	AR9170_TX_PHY_MOD_CCK			0x00000000
+#define	AR9170_TX_PHY_MOD_OFDM			0x00000001
+#define	AR9170_TX_PHY_MOD_HT			0x00000002
+
+/* depends on modulation */
+#define	AR9170_TX_PHY_SHORT_PREAMBLE		0x00000004
+#define	AR9170_TX_PHY_GREENFIELD		0x00000004
+
+#define	AR9170_TX_PHY_BW_S			3
+#define	AR9170_TX_PHY_BW			(3 << AR9170_TX_PHY_BW_SHIFT)
+#define	AR9170_TX_PHY_BW_20MHZ			0
+#define	AR9170_TX_PHY_BW_40MHZ			2
+#define	AR9170_TX_PHY_BW_40MHZ_DUP		3
+
+#define	AR9170_TX_PHY_TX_HEAVY_CLIP_S		6
+#define	AR9170_TX_PHY_TX_HEAVY_CLIP		(7 << \
+						 AR9170_TX_PHY_TX_HEAVY_CLIP_S)
+
+#define	AR9170_TX_PHY_TX_PWR_S			9
+#define	AR9170_TX_PHY_TX_PWR			(0x3f << \
+						 AR9170_TX_PHY_TX_PWR_S)
+
+#define	AR9170_TX_PHY_TXCHAIN_S			15
+#define	AR9170_TX_PHY_TXCHAIN			(7 << \
+						 AR9170_TX_PHY_TXCHAIN_S)
+#define	AR9170_TX_PHY_TXCHAIN_1			1
+/* use for cck, ofdm 6/9/12/18/24 and HT if capable */
+#define	AR9170_TX_PHY_TXCHAIN_2			5
+
+#define	AR9170_TX_PHY_MCS_S			18
+#define	AR9170_TX_PHY_MCS			(0x7f << \
+						 AR9170_TX_PHY_MCS_S)
+
+#define	AR9170_TX_PHY_RATE_CCK_1M		0x0
+#define	AR9170_TX_PHY_RATE_CCK_2M		0x1
+#define	AR9170_TX_PHY_RATE_CCK_5M		0x2
+#define	AR9170_TX_PHY_RATE_CCK_11M		0x3
+
+/* same as AR9170_RX_PHY_RATE */
+#define	AR9170_TXRX_PHY_RATE_OFDM_6M		0xb
+#define	AR9170_TXRX_PHY_RATE_OFDM_9M		0xf
+#define	AR9170_TXRX_PHY_RATE_OFDM_12M		0xa
+#define	AR9170_TXRX_PHY_RATE_OFDM_18M		0xe
+#define	AR9170_TXRX_PHY_RATE_OFDM_24M		0x9
+#define	AR9170_TXRX_PHY_RATE_OFDM_36M		0xd
+#define	AR9170_TXRX_PHY_RATE_OFDM_48M		0x8
+#define	AR9170_TXRX_PHY_RATE_OFDM_54M		0xc
+
+#define	AR9170_TXRX_PHY_RATE_HT_MCS0		0x0
+#define	AR9170_TXRX_PHY_RATE_HT_MCS1		0x1
+#define	AR9170_TXRX_PHY_RATE_HT_MCS2		0x2
+#define	AR9170_TXRX_PHY_RATE_HT_MCS3		0x3
+#define	AR9170_TXRX_PHY_RATE_HT_MCS4		0x4
+#define	AR9170_TXRX_PHY_RATE_HT_MCS5		0x5
+#define	AR9170_TXRX_PHY_RATE_HT_MCS6		0x6
+#define	AR9170_TXRX_PHY_RATE_HT_MCS7		0x7
+#define	AR9170_TXRX_PHY_RATE_HT_MCS8		0x8
+#define	AR9170_TXRX_PHY_RATE_HT_MCS9		0x9
+#define	AR9170_TXRX_PHY_RATE_HT_MCS10		0xa
+#define	AR9170_TXRX_PHY_RATE_HT_MCS11		0xb
+#define	AR9170_TXRX_PHY_RATE_HT_MCS12		0xc
+#define	AR9170_TXRX_PHY_RATE_HT_MCS13		0xd
+#define	AR9170_TXRX_PHY_RATE_HT_MCS14		0xe
+#define	AR9170_TXRX_PHY_RATE_HT_MCS15		0xf
+
+#define	AR9170_TX_PHY_SHORT_GI			0x80000000
+
+#ifdef __CARL9170FW__
+struct ar9170_tx_hw_mac_control {
+	union {
+		struct {
+			/*
+			 * Beware of compiler bugs in all gcc pre 4.4!
+			 */
+
+			u8 erp_prot:2;
+			u8 no_ack:1;
+			u8 backoff:1;
+			u8 burst:1;
+			u8 ampdu:1;
+
+			u8 enc_mode:2;
+
+			u8 hw_mmic:1;
+			u8 hw_duration:1;
+
+			u8 qos_queue:2;
+
+			u8 disable_txop:1;
+			u8 txop_rifs:1;
+
+			u8 ba_end:1;
+			u8 probe:1;
+		} __packed;
+
+		__le16 set;
+	} __packed;
+} __packed;
+
+struct ar9170_tx_hw_phy_control {
+	union {
+		struct {
+			/*
+			 * Beware of compiler bugs in all gcc pre 4.4!
+			 */
+
+			u8 modulation:2;
+			u8 preamble:1;
+			u8 bandwidth:2;
+			u8:1;
+			u8 heavy_clip:3;
+			u8 tx_power:6;
+			u8 chains:3;
+			u8 mcs:7;
+			u8:6;
+			u8 short_gi:1;
+		} __packed;
+
+		__le32 set;
+	} __packed;
+} __packed;
+
+struct ar9170_tx_rate_info {
+	u8 tries:3;
+	u8 erp_prot:2;
+	u8 ampdu:1;
+	u8 free:2; /* free for use (e.g.:RIFS/TXOP/AMPDU) */
+} __packed;
+
+struct carl9170_tx_superdesc {
+	__le16 len;
+	u8 rix;
+	u8 cnt;
+	u8 cookie;
+	u8 ampdu_density:3;
+	u8 ampdu_factor:2;
+	u8 ampdu_commit_density:1;
+	u8 ampdu_commit_factor:1;
+	u8 ampdu_unused_bit:1;
+	u8 queue:2;
+	u8 reserved:1;
+	u8 vif_id:3;
+	u8 fill_in_tsf:1;
+	u8 cab:1;
+	u8 padding2;
+	struct ar9170_tx_rate_info ri[CARL9170_TX_MAX_RATES];
+	struct ar9170_tx_hw_phy_control rr[CARL9170_TX_MAX_RETRY_RATES];
+} __packed;
+
+struct ar9170_tx_hwdesc {
+	__le16 length;
+	struct ar9170_tx_hw_mac_control mac;
+	struct ar9170_tx_hw_phy_control phy;
+} __packed;
+
+struct ar9170_tx_frame {
+	struct ar9170_tx_hwdesc hdr;
+
+	union {
+		struct ieee80211_hdr i3e;
+		u8 payload[0];
+	} data;
+} __packed;
+
+struct carl9170_tx_superframe {
+	struct carl9170_tx_superdesc s;
+	struct ar9170_tx_frame f;
+} __packed;
+
+#endif /* __CARL9170FW__ */
+
+struct _ar9170_tx_hwdesc {
+	__le16 length;
+	__le16 mac_control;
+	__le32 phy_control;
+} __packed;
+
+#define	CARL9170_TX_SUPER_AMPDU_DENSITY_S		0
+#define	CARL9170_TX_SUPER_AMPDU_DENSITY			0x7
+#define	CARL9170_TX_SUPER_AMPDU_FACTOR			0x18
+#define	CARL9170_TX_SUPER_AMPDU_FACTOR_S		3
+#define	CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY		0x20
+#define	CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY_S	5
+#define	CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR		0x40
+#define	CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR_S		6
+
+#define CARL9170_TX_SUPER_MISC_QUEUE			0x3
+#define CARL9170_TX_SUPER_MISC_QUEUE_S			0
+#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
+#define	CARL9170_TX_SUPER_MISC_CAB			0x80
+
+#define CARL9170_TX_SUPER_RI_TRIES			0x7
+#define CARL9170_TX_SUPER_RI_TRIES_S			0
+#define CARL9170_TX_SUPER_RI_ERP_PROT			0x18
+#define CARL9170_TX_SUPER_RI_ERP_PROT_S			3
+#define CARL9170_TX_SUPER_RI_AMPDU			0x20
+#define CARL9170_TX_SUPER_RI_AMPDU_S			5
+
+struct _carl9170_tx_superdesc {
+	__le16 len;
+	u8 rix;
+	u8 cnt;
+	u8 cookie;
+	u8 ampdu_settings;
+	u8 misc;
+	u8 padding;
+	u8 ri[CARL9170_TX_MAX_RATES];
+	__le32 rr[CARL9170_TX_MAX_RETRY_RATES];
+} __packed;
+
+struct _carl9170_tx_superframe {
+	struct _carl9170_tx_superdesc s;
+	struct _ar9170_tx_hwdesc f;
+	u8 frame_data[0];
+} __packed;
+
+#define	CARL9170_TX_SUPERDESC_LEN		24
+#define	AR9170_TX_HWDESC_LEN			8
+#define	CARL9170_TX_SUPERFRAME_LEN		(CARL9170_TX_SUPERDESC_LEN + \
+						 AR9170_TX_HWDESC_LEN)
+
+struct ar9170_rx_head {
+	u8 plcp[12];
+} __packed;
+
+#define	AR9170_RX_HEAD_LEN			12
+
+struct ar9170_rx_phystatus {
+	union {
+		struct {
+			u8 rssi_ant0, rssi_ant1, rssi_ant2,
+				rssi_ant0x, rssi_ant1x, rssi_ant2x,
+				rssi_combined;
+		} __packed;
+		u8 rssi[7];
+	} __packed;
+
+	u8 evm_stream0[6], evm_stream1[6];
+	u8 phy_err;
+} __packed;
+
+#define	AR9170_RX_PHYSTATUS_LEN			20
+
+struct ar9170_rx_macstatus {
+	u8 SAidx, DAidx;
+	u8 error;
+	u8 status;
+} __packed;
+
+#define	AR9170_RX_MACSTATUS_LEN			4
+
+struct ar9170_rx_frame_single {
+	struct ar9170_rx_head phy_head;
+	struct ieee80211_hdr i3e;
+	struct ar9170_rx_phystatus phy_tail;
+	struct ar9170_rx_macstatus macstatus;
+} __packed;
+
+struct ar9170_rx_frame_head {
+	struct ar9170_rx_head phy_head;
+	struct ieee80211_hdr i3e;
+	struct ar9170_rx_macstatus macstatus;
+} __packed;
+
+struct ar9170_rx_frame_middle {
+	struct ieee80211_hdr i3e;
+	struct ar9170_rx_macstatus macstatus;
+} __packed;
+
+struct ar9170_rx_frame_tail {
+	struct ieee80211_hdr i3e;
+	struct ar9170_rx_phystatus phy_tail;
+	struct ar9170_rx_macstatus macstatus;
+} __packed;
+
+struct ar9170_rx_frame {
+	union {
+		struct ar9170_rx_frame_single single;
+		struct ar9170_rx_frame_head head;
+		struct ar9170_rx_frame_middle middle;
+		struct ar9170_rx_frame_tail tail;
+	} __packed;
+} __packed;
+
+static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t)
+{
+	return (t->SAidx & 0xc0) >> 4 |
+	       (t->DAidx & 0xc0) >> 6;
+}
+
+enum ar9170_txq {
+	AR9170_TXQ_BE,
+
+	AR9170_TXQ_VI,
+	AR9170_TXQ_VO,
+	AR9170_TXQ_BK,
+
+	__AR9170_NUM_TXQ,
+};
+
+static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 };
+
+#define	AR9170_TXQ_DEPTH			32
+
+#endif /* __CARL9170_SHARED_WLAN_H */
diff --git a/drivers/net/wireless/ath/debug.c b/drivers/net/wireless/ath/debug.c
index 53e77bd..dacfb23 100644
--- a/drivers/net/wireless/ath/debug.c
+++ b/drivers/net/wireless/ath/debug.c
@@ -30,3 +30,32 @@
 	va_end(args);
 }
 EXPORT_SYMBOL(ath_print);
+
+const char *ath_opmode_to_string(enum nl80211_iftype opmode)
+{
+	switch (opmode) {
+	case NL80211_IFTYPE_UNSPECIFIED:
+		return "UNSPEC";
+	case NL80211_IFTYPE_ADHOC:
+		return "ADHOC";
+	case NL80211_IFTYPE_STATION:
+		return "STATION";
+	case NL80211_IFTYPE_AP:
+		return "AP";
+	case NL80211_IFTYPE_AP_VLAN:
+		return "AP-VLAN";
+	case NL80211_IFTYPE_WDS:
+		return "WDS";
+	case NL80211_IFTYPE_MONITOR:
+		return "MONITOR";
+	case NL80211_IFTYPE_MESH_POINT:
+		return "MESH";
+	case NL80211_IFTYPE_P2P_CLIENT:
+		return "P2P-CLIENT";
+	case NL80211_IFTYPE_P2P_GO:
+		return "P2P-GO";
+	default:
+		return "UNKNOWN";
+	}
+}
+EXPORT_SYMBOL(ath_opmode_to_string);
diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h
index 873bf52..64e4af2 100644
--- a/drivers/net/wireless/ath/debug.h
+++ b/drivers/net/wireless/ath/debug.h
@@ -36,6 +36,7 @@
  * @ATH_DBG_PS: power save processing
  * @ATH_DBG_HWTIMER: hardware timer handling
  * @ATH_DBG_BTCOEX: bluetooth coexistance
+ * @ATH_DBG_BSTUCK: stuck beacons
  * @ATH_DBG_ANY: enable all debugging
  *
  * The debug level is used to control the amount and type of debugging output
@@ -60,6 +61,7 @@
 	ATH_DBG_HWTIMER		= 0x00001000,
 	ATH_DBG_BTCOEX		= 0x00002000,
 	ATH_DBG_WMI		= 0x00004000,
+	ATH_DBG_BSTUCK		= 0x00008000,
 	ATH_DBG_ANY		= 0xffffffff
 };
 
@@ -75,4 +77,14 @@
 }
 #endif /* CONFIG_ATH_DEBUG */
 
+/** Returns string describing opmode, or NULL if unknown mode. */
+#ifdef CONFIG_ATH_DEBUG
+const char *ath_opmode_to_string(enum nl80211_iftype opmode);
+#else
+static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
+{
+	return "UNKNOWN";
+}
+#endif
+
 #endif /* ATH_DEBUG_H */
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c
index a8f81ea..183c282 100644
--- a/drivers/net/wireless/ath/hw.c
+++ b/drivers/net/wireless/ath/hw.c
@@ -124,3 +124,62 @@
 	REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
 }
 EXPORT_SYMBOL(ath_hw_setbssidmask);
+
+
+/**
+ * ath_hw_cycle_counters_update - common function to update cycle counters
+ *
+ * @common: the ath_common struct for the device.
+ *
+ * This function is used to update all cycle counters in one place.
+ * It has to be called while holding common->cc_lock!
+ */
+void ath_hw_cycle_counters_update(struct ath_common *common)
+{
+	u32 cycles, busy, rx, tx;
+	void *ah = common->ah;
+
+	/* freeze */
+	REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
+
+	/* read */
+	cycles = REG_READ(ah, AR_CCCNT);
+	busy = REG_READ(ah, AR_RCCNT);
+	rx = REG_READ(ah, AR_RFCNT);
+	tx = REG_READ(ah, AR_TFCNT);
+
+	/* clear */
+	REG_WRITE(ah, 0, AR_CCCNT);
+	REG_WRITE(ah, 0, AR_RFCNT);
+	REG_WRITE(ah, 0, AR_RCCNT);
+	REG_WRITE(ah, 0, AR_TFCNT);
+
+	/* unfreeze */
+	REG_WRITE(ah, 0, AR_MIBC);
+
+	/* update all cycle counters here */
+	common->cc_ani.cycles += cycles;
+	common->cc_ani.rx_busy += busy;
+	common->cc_ani.rx_frame += rx;
+	common->cc_ani.tx_frame += tx;
+
+	common->cc_survey.cycles += cycles;
+	common->cc_survey.rx_busy += busy;
+	common->cc_survey.rx_frame += rx;
+	common->cc_survey.tx_frame += tx;
+}
+EXPORT_SYMBOL(ath_hw_cycle_counters_update);
+
+int32_t ath_hw_get_listen_time(struct ath_common *common)
+{
+	struct ath_cycle_counters *cc = &common->cc_ani;
+	int32_t listen_time;
+
+	listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) /
+		      (common->clockrate * 1000);
+
+	memset(cc, 0, sizeof(*cc));
+
+	return listen_time;
+}
+EXPORT_SYMBOL(ath_hw_get_listen_time);
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c
new file mode 100644
index 0000000..bd21a4d
--- /dev/null
+++ b/drivers/net/wireless/ath/key.c
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2009 Atheros Communications Inc.
+ * Copyright (c) 2010 Bruno Randolf <br1@einfach.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 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 <asm/unaligned.h>
+#include <net/mac80211.h>
+
+#include "ath.h"
+#include "reg.h"
+#include "debug.h"
+
+#define REG_READ			(common->ops->read)
+#define REG_WRITE(_ah, _reg, _val)	(common->ops->write)(_ah, _val, _reg)
+
+#define IEEE80211_WEP_NKID      4       /* number of key ids */
+
+/************************/
+/* Key Cache Management */
+/************************/
+
+bool ath_hw_keyreset(struct ath_common *common, u16 entry)
+{
+	u32 keyType;
+	void *ah = common->ah;
+
+	if (entry >= common->keymax) {
+		ath_print(common, ATH_DBG_FATAL,
+			  "keychache entry %u out of range\n", entry);
+		return false;
+	}
+
+	keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
+
+	REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
+	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
+
+	if (keyType == AR_KEYTABLE_TYPE_TKIP) {
+		u16 micentry = entry + 64;
+
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+
+	}
+
+	return true;
+}
+EXPORT_SYMBOL(ath_hw_keyreset);
+
+bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac)
+{
+	u32 macHi, macLo;
+	u32 unicast_flag = AR_KEYTABLE_VALID;
+	void *ah = common->ah;
+
+	if (entry >= common->keymax) {
+		ath_print(common, ATH_DBG_FATAL,
+			  "keychache entry %u out of range\n", entry);
+		return false;
+	}
+
+	if (mac != NULL) {
+		/*
+		 * AR_KEYTABLE_VALID indicates that the address is a unicast
+		 * address, which must match the transmitter address for
+		 * decrypting frames.
+		 * Not setting this bit allows the hardware to use the key
+		 * for multicast frame decryption.
+		 */
+		if (mac[0] & 0x01)
+			unicast_flag = 0;
+
+		macHi = (mac[5] << 8) | mac[4];
+		macLo = (mac[3] << 24) |
+			(mac[2] << 16) |
+			(mac[1] << 8) |
+			mac[0];
+		macLo >>= 1;
+		macLo |= (macHi & 1) << 31;
+		macHi >>= 1;
+	} else {
+		macLo = macHi = 0;
+	}
+	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
+	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag);
+
+	return true;
+}
+
+bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
+				 const struct ath_keyval *k,
+				 const u8 *mac)
+{
+	void *ah = common->ah;
+	u32 key0, key1, key2, key3, key4;
+	u32 keyType;
+
+	if (entry >= common->keymax) {
+		ath_print(common, ATH_DBG_FATAL,
+			  "keycache entry %u out of range\n", entry);
+		return false;
+	}
+
+	switch (k->kv_type) {
+	case ATH_CIPHER_AES_OCB:
+		keyType = AR_KEYTABLE_TYPE_AES;
+		break;
+	case ATH_CIPHER_AES_CCM:
+		if (!(common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)) {
+			ath_print(common, ATH_DBG_ANY,
+				  "AES-CCM not supported by this mac rev\n");
+			return false;
+		}
+		keyType = AR_KEYTABLE_TYPE_CCM;
+		break;
+	case ATH_CIPHER_TKIP:
+		keyType = AR_KEYTABLE_TYPE_TKIP;
+		if (entry + 64 >= common->keymax) {
+			ath_print(common, ATH_DBG_ANY,
+				  "entry %u inappropriate for TKIP\n", entry);
+			return false;
+		}
+		break;
+	case ATH_CIPHER_WEP:
+		if (k->kv_len < WLAN_KEY_LEN_WEP40) {
+			ath_print(common, ATH_DBG_ANY,
+				  "WEP key length %u too small\n", k->kv_len);
+			return false;
+		}
+		if (k->kv_len <= WLAN_KEY_LEN_WEP40)
+			keyType = AR_KEYTABLE_TYPE_40;
+		else if (k->kv_len <= WLAN_KEY_LEN_WEP104)
+			keyType = AR_KEYTABLE_TYPE_104;
+		else
+			keyType = AR_KEYTABLE_TYPE_128;
+		break;
+	case ATH_CIPHER_CLR:
+		keyType = AR_KEYTABLE_TYPE_CLR;
+		break;
+	default:
+		ath_print(common, ATH_DBG_FATAL,
+			  "cipher %u not supported\n", k->kv_type);
+		return false;
+	}
+
+	key0 = get_unaligned_le32(k->kv_val + 0);
+	key1 = get_unaligned_le16(k->kv_val + 4);
+	key2 = get_unaligned_le32(k->kv_val + 6);
+	key3 = get_unaligned_le16(k->kv_val + 10);
+	key4 = get_unaligned_le32(k->kv_val + 12);
+	if (k->kv_len <= WLAN_KEY_LEN_WEP104)
+		key4 &= 0xff;
+
+	/*
+	 * Note: Key cache registers access special memory area that requires
+	 * two 32-bit writes to actually update the values in the internal
+	 * memory. Consequently, the exact order and pairs used here must be
+	 * maintained.
+	 */
+
+	if (keyType == AR_KEYTABLE_TYPE_TKIP) {
+		u16 micentry = entry + 64;
+
+		/*
+		 * Write inverted key[47:0] first to avoid Michael MIC errors
+		 * on frames that could be sent or received at the same time.
+		 * The correct key will be written in the end once everything
+		 * else is ready.
+		 */
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
+
+		/* Write key[95:48] */
+		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+
+		/* Write key[127:96] and key type */
+		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+
+		/* Write MAC address for the entry */
+		(void) ath_hw_keysetmac(common, entry, mac);
+
+		if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
+			/*
+			 * TKIP uses two key cache entries:
+			 * Michael MIC TX/RX keys in the same key cache entry
+			 * (idx = main index + 64):
+			 * key0 [31:0] = RX key [31:0]
+			 * key1 [15:0] = TX key [31:16]
+			 * key1 [31:16] = reserved
+			 * key2 [31:0] = RX key [63:32]
+			 * key3 [15:0] = TX key [15:0]
+			 * key3 [31:16] = reserved
+			 * key4 [31:0] = TX key [63:32]
+			 */
+			u32 mic0, mic1, mic2, mic3, mic4;
+
+			mic0 = get_unaligned_le32(k->kv_mic + 0);
+			mic2 = get_unaligned_le32(k->kv_mic + 4);
+			mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
+			mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
+			mic4 = get_unaligned_le32(k->kv_txmic + 4);
+
+			/* Write RX[31:0] and TX[31:16] */
+			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
+
+			/* Write RX[63:32] and TX[15:0] */
+			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
+
+			/* Write TX[63:32] and keyType(reserved) */
+			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
+			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+				  AR_KEYTABLE_TYPE_CLR);
+
+		} else {
+			/*
+			 * TKIP uses four key cache entries (two for group
+			 * keys):
+			 * Michael MIC TX/RX keys are in different key cache
+			 * entries (idx = main index + 64 for TX and
+			 * main index + 32 + 96 for RX):
+			 * key0 [31:0] = TX/RX MIC key [31:0]
+			 * key1 [31:0] = reserved
+			 * key2 [31:0] = TX/RX MIC key [63:32]
+			 * key3 [31:0] = reserved
+			 * key4 [31:0] = reserved
+			 *
+			 * Upper layer code will call this function separately
+			 * for TX and RX keys when these registers offsets are
+			 * used.
+			 */
+			u32 mic0, mic2;
+
+			mic0 = get_unaligned_le32(k->kv_mic + 0);
+			mic2 = get_unaligned_le32(k->kv_mic + 4);
+
+			/* Write MIC key[31:0] */
+			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+
+			/* Write MIC key[63:32] */
+			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+
+			/* Write TX[63:32] and keyType(reserved) */
+			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
+			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+				  AR_KEYTABLE_TYPE_CLR);
+		}
+
+		/* MAC address registers are reserved for the MIC entry */
+		REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
+
+		/*
+		 * Write the correct (un-inverted) key[47:0] last to enable
+		 * TKIP now that all other registers are set with correct
+		 * values.
+		 */
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+	} else {
+		/* Write key[47:0] */
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+
+		/* Write key[95:48] */
+		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+
+		/* Write key[127:96] and key type */
+		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+
+		/* Write MAC address for the entry */
+		(void) ath_hw_keysetmac(common, entry, mac);
+	}
+
+	return true;
+}
+
+static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
+			   struct ath_keyval *hk, const u8 *addr,
+			   bool authenticator)
+{
+	const u8 *key_rxmic;
+	const u8 *key_txmic;
+
+	key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
+	key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
+
+	if (addr == NULL) {
+		/*
+		 * Group key installation - only two key cache entries are used
+		 * regardless of splitmic capability since group key is only
+		 * used either for TX or RX.
+		 */
+		if (authenticator) {
+			memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
+			memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
+		} else {
+			memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
+			memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
+		}
+		return ath_hw_set_keycache_entry(common, keyix, hk, addr);
+	}
+	if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
+		/* TX and RX keys share the same key cache entry. */
+		memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
+		memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
+		return ath_hw_set_keycache_entry(common, keyix, hk, addr);
+	}
+
+	/* Separate key cache entries for TX and RX */
+
+	/* TX key goes at first index, RX key at +32. */
+	memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
+	if (!ath_hw_set_keycache_entry(common, keyix, hk, NULL)) {
+		/* TX MIC entry failed. No need to proceed further */
+		ath_print(common, ATH_DBG_FATAL,
+			  "Setting TX MIC Key Failed\n");
+		return 0;
+	}
+
+	memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
+	/* XXX delete tx key on failure? */
+	return ath_hw_set_keycache_entry(common, keyix + 32, hk, addr);
+}
+
+static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
+{
+	int i;
+
+	for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
+		if (test_bit(i, common->keymap) ||
+		    test_bit(i + 64, common->keymap))
+			continue; /* At least one part of TKIP key allocated */
+		if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) &&
+		    (test_bit(i + 32, common->keymap) ||
+		     test_bit(i + 64 + 32, common->keymap)))
+			continue; /* At least one part of TKIP key allocated */
+
+		/* Found a free slot for a TKIP key */
+		return i;
+	}
+	return -1;
+}
+
+static int ath_reserve_key_cache_slot(struct ath_common *common,
+				      u32 cipher)
+{
+	int i;
+
+	if (cipher == WLAN_CIPHER_SUITE_TKIP)
+		return ath_reserve_key_cache_slot_tkip(common);
+
+	/* First, try to find slots that would not be available for TKIP. */
+	if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
+		for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
+			if (!test_bit(i, common->keymap) &&
+			    (test_bit(i + 32, common->keymap) ||
+			     test_bit(i + 64, common->keymap) ||
+			     test_bit(i + 64 + 32, common->keymap)))
+				return i;
+			if (!test_bit(i + 32, common->keymap) &&
+			    (test_bit(i, common->keymap) ||
+			     test_bit(i + 64, common->keymap) ||
+			     test_bit(i + 64 + 32, common->keymap)))
+				return i + 32;
+			if (!test_bit(i + 64, common->keymap) &&
+			    (test_bit(i , common->keymap) ||
+			     test_bit(i + 32, common->keymap) ||
+			     test_bit(i + 64 + 32, common->keymap)))
+				return i + 64;
+			if (!test_bit(i + 64 + 32, common->keymap) &&
+			    (test_bit(i, common->keymap) ||
+			     test_bit(i + 32, common->keymap) ||
+			     test_bit(i + 64, common->keymap)))
+				return i + 64 + 32;
+		}
+	} else {
+		for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
+			if (!test_bit(i, common->keymap) &&
+			    test_bit(i + 64, common->keymap))
+				return i;
+			if (test_bit(i, common->keymap) &&
+			    !test_bit(i + 64, common->keymap))
+				return i + 64;
+		}
+	}
+
+	/* No partially used TKIP slots, pick any available slot */
+	for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
+		/* Do not allow slots that could be needed for TKIP group keys
+		 * to be used. This limitation could be removed if we know that
+		 * TKIP will not be used. */
+		if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
+			continue;
+		if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
+			if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
+				continue;
+			if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
+				continue;
+		}
+
+		if (!test_bit(i, common->keymap))
+			return i; /* Found a free slot for a key */
+	}
+
+	/* No free slot found */
+	return -1;
+}
+
+/*
+ * Configure encryption in the HW.
+ */
+int ath_key_config(struct ath_common *common,
+			  struct ieee80211_vif *vif,
+			  struct ieee80211_sta *sta,
+			  struct ieee80211_key_conf *key)
+{
+	struct ath_keyval hk;
+	const u8 *mac = NULL;
+	u8 gmac[ETH_ALEN];
+	int ret = 0;
+	int idx;
+
+	memset(&hk, 0, sizeof(hk));
+
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		hk.kv_type = ATH_CIPHER_WEP;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		hk.kv_type = ATH_CIPHER_TKIP;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		hk.kv_type = ATH_CIPHER_AES_CCM;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	hk.kv_len = key->keylen;
+	memcpy(hk.kv_val, key->key, key->keylen);
+
+	if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+		switch (vif->type) {
+		case NL80211_IFTYPE_AP:
+			memcpy(gmac, vif->addr, ETH_ALEN);
+			gmac[0] |= 0x01;
+			mac = gmac;
+			idx = ath_reserve_key_cache_slot(common, key->cipher);
+			break;
+		case NL80211_IFTYPE_ADHOC:
+			if (!sta) {
+				idx = key->keyidx;
+				break;
+			}
+			memcpy(gmac, sta->addr, ETH_ALEN);
+			gmac[0] |= 0x01;
+			mac = gmac;
+			idx = ath_reserve_key_cache_slot(common, key->cipher);
+			break;
+		default:
+			idx = key->keyidx;
+			break;
+		}
+	} else if (key->keyidx) {
+		if (WARN_ON(!sta))
+			return -EOPNOTSUPP;
+		mac = sta->addr;
+
+		if (vif->type != NL80211_IFTYPE_AP) {
+			/* Only keyidx 0 should be used with unicast key, but
+			 * allow this for client mode for now. */
+			idx = key->keyidx;
+		} else
+			return -EIO;
+	} else {
+		if (WARN_ON(!sta))
+			return -EOPNOTSUPP;
+		mac = sta->addr;
+
+		idx = ath_reserve_key_cache_slot(common, key->cipher);
+	}
+
+	if (idx < 0)
+		return -ENOSPC; /* no free key cache entries */
+
+	if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
+		ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
+				      vif->type == NL80211_IFTYPE_AP);
+	else
+		ret = ath_hw_set_keycache_entry(common, idx, &hk, mac);
+
+	if (!ret)
+		return -EIO;
+
+	set_bit(idx, common->keymap);
+	if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+		set_bit(idx + 64, common->keymap);
+		set_bit(idx, common->tkip_keymap);
+		set_bit(idx + 64, common->tkip_keymap);
+		if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
+			set_bit(idx + 32, common->keymap);
+			set_bit(idx + 64 + 32, common->keymap);
+			set_bit(idx + 32, common->tkip_keymap);
+			set_bit(idx + 64 + 32, common->tkip_keymap);
+		}
+	}
+
+	return idx;
+}
+EXPORT_SYMBOL(ath_key_config);
+
+/*
+ * Delete Key.
+ */
+void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
+{
+	ath_hw_keyreset(common, key->hw_key_idx);
+	if (key->hw_key_idx < IEEE80211_WEP_NKID)
+		return;
+
+	clear_bit(key->hw_key_idx, common->keymap);
+	if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
+		return;
+
+	clear_bit(key->hw_key_idx + 64, common->keymap);
+
+	clear_bit(key->hw_key_idx, common->tkip_keymap);
+	clear_bit(key->hw_key_idx + 64, common->tkip_keymap);
+
+	if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
+		ath_hw_keyreset(common, key->hw_key_idx + 32);
+		clear_bit(key->hw_key_idx + 32, common->keymap);
+		clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
+
+		clear_bit(key->hw_key_idx + 32, common->tkip_keymap);
+		clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap);
+	}
+}
+EXPORT_SYMBOL(ath_key_delete);
diff --git a/drivers/net/wireless/ath/reg.h b/drivers/net/wireless/ath/reg.h
index dfe1fbe..298e53f 100644
--- a/drivers/net/wireless/ath/reg.h
+++ b/drivers/net/wireless/ath/reg.h
@@ -17,6 +17,12 @@
 #ifndef ATH_REGISTERS_H
 #define ATH_REGISTERS_H
 
+#define AR_MIBC			0x0040
+#define AR_MIBC_COW		0x00000001
+#define AR_MIBC_FMC		0x00000002
+#define AR_MIBC_CMC		0x00000004
+#define AR_MIBC_MCS		0x00000008
+
 /*
  * BSSID mask registers. See ath_hw_set_bssid_mask()
  * for detailed documentation about these registers.
@@ -24,4 +30,32 @@
 #define AR_BSSMSKL		0x80e0
 #define AR_BSSMSKU		0x80e4
 
+#define AR_TFCNT		0x80ec
+#define AR_RFCNT		0x80f0
+#define AR_RCCNT		0x80f4
+#define AR_CCCNT		0x80f8
+
+#define AR_KEYTABLE_0           0x8800
+#define AR_KEYTABLE(_n)         (AR_KEYTABLE_0 + ((_n)*32))
+#define AR_KEY_CACHE_SIZE       128
+#define AR_RSVD_KEYTABLE_ENTRIES 4
+#define AR_KEY_TYPE             0x00000007
+#define AR_KEYTABLE_TYPE_40     0x00000000
+#define AR_KEYTABLE_TYPE_104    0x00000001
+#define AR_KEYTABLE_TYPE_128    0x00000003
+#define AR_KEYTABLE_TYPE_TKIP   0x00000004
+#define AR_KEYTABLE_TYPE_AES    0x00000005
+#define AR_KEYTABLE_TYPE_CCM    0x00000006
+#define AR_KEYTABLE_TYPE_CLR    0x00000007
+#define AR_KEYTABLE_ANT         0x00000008
+#define AR_KEYTABLE_VALID       0x00008000
+#define AR_KEYTABLE_KEY0(_n)    (AR_KEYTABLE(_n) + 0)
+#define AR_KEYTABLE_KEY1(_n)    (AR_KEYTABLE(_n) + 4)
+#define AR_KEYTABLE_KEY2(_n)    (AR_KEYTABLE(_n) + 8)
+#define AR_KEYTABLE_KEY3(_n)    (AR_KEYTABLE(_n) + 12)
+#define AR_KEYTABLE_KEY4(_n)    (AR_KEYTABLE(_n) + 16)
+#define AR_KEYTABLE_TYPE(_n)    (AR_KEYTABLE(_n) + 20)
+#define AR_KEYTABLE_MAC0(_n)    (AR_KEYTABLE(_n) + 24)
+#define AR_KEYTABLE_MAC1(_n)    (AR_KEYTABLE(_n) + 28)
+
 #endif /* ATH_REGISTERS_H */
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 3b63216..c96e19d 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -42,7 +42,6 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -64,58 +63,21 @@
 
 /*====================================================================*/
 
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card
-   insertion and ejection events.  They are invoked from the atmel_cs
-   event handler.
-*/
-
 static int atmel_config(struct pcmcia_device *link);
 static void atmel_release(struct pcmcia_device *link);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void atmel_detach(struct pcmcia_device *p_dev);
 
 typedef struct local_info_t {
 	struct net_device *eth_dev;
 } local_info_t;
 
-/*======================================================================
-
-  atmel_attach() creates an "instance" of the driver, allocating
-  local data structures for one device.  The device is registered
-  with Card Services.
-
-  The dev_link 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 atmel_probe(struct pcmcia_device *p_dev)
 {
 	local_info_t *local;
 
 	dev_dbg(&p_dev->dev, "atmel_attach()\n");
 
-	/*
-	  General socket configuration defaults can go here.  In this
-	  client, we assume very little, and rely on the CIS for almost
-	  everything.  In most clients, many details (i.e., number, sizes,
-	  and attributes of IO windows) are fixed by the nature of the
-	  device, and can be hard-wired here.
-	*/
-	p_dev->conf.Attributes = 0;
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
-
 	/* Allocate space for private device-specific data */
 	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
 	if (!local) {
@@ -127,15 +89,6 @@
 	return atmel_config(p_dev);
 } /* atmel_attach */
 
-/*======================================================================
-
-  This deletes a driver "instance".  The device is de-registered
-  with Card Services.  If it has been released, all local data
-  structures are freed.  Otherwise, the structures will be freed
-  when the device is released.
-
-  ======================================================================*/
-
 static void atmel_detach(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "atmel_detach\n");
@@ -145,14 +98,6 @@
 	kfree(link->priv);
 }
 
-/*======================================================================
-
-  atmel_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.
-
-  ======================================================================*/
-
 /* Call-back function to interrogate PCMCIA-specific information
    about the current existance of the card */
 static int card_present(void *arg)
@@ -165,47 +110,11 @@
 	return 0;
 }
 
-static int atmel_config_check(struct pcmcia_device *p_dev,
-			      cistpl_cftable_entry_t *cfg,
-			      cistpl_cftable_entry_t *dflt,
-			      unsigned int vcc,
-			      void *priv_data)
+static int atmel_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-		p_dev->conf.Status = CCSR_AUDIO_ENA;
-	}
-
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-					pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-	}
-
-	/* This reserves IO space but doesn't actually enable it */
 	return pcmcia_request_io(p_dev);
 }
 
@@ -220,18 +129,9 @@
 
 	dev_dbg(&link->dev, "atmel_config\n");
 
-	/*
-	  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.
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+		CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
 
-	  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.
-	*/
 	if (pcmcia_loop_config(link, atmel_config_check, NULL))
 		goto failed;
 
@@ -240,12 +140,7 @@
 		goto failed;
 	}
 
-	/*
-	  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.
-	*/
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -267,14 +162,6 @@
 	return -ENODEV;
 }
 
-/*======================================================================
-
-  After a card is removed, atmel_release() will unregister the
-  device, and release the PCMCIA configuration.  If the device is
-  still open, this will be postponed until it is closed.
-
-  ======================================================================*/
-
 static void atmel_release(struct pcmcia_device *link)
 {
 	struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
@@ -353,9 +240,7 @@
 
 static struct pcmcia_driver atmel_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "atmel_cs",
-        },
+	.name		= "atmel_cs",
 	.probe          = atmel_probe,
 	.remove		= atmel_detach,
 	.id_table	= atmel_ids,
@@ -363,12 +248,12 @@
 	.resume		= atmel_resume,
 };
 
-static int atmel_cs_init(void)
+static int __init atmel_cs_init(void)
 {
         return pcmcia_register_driver(&atmel_driver);
 }
 
-static void atmel_cs_cleanup(void)
+static void __exit atmel_cs_cleanup(void)
 {
         pcmcia_unregister_driver(&atmel_driver);
 }
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index 5e83b6f..69d4af0 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -1,6 +1,8 @@
 b43-y				+= main.o
 b43-y				+= tables.o
 b43-$(CONFIG_B43_NPHY)		+= tables_nphy.o
+b43-$(CONFIG_B43_NPHY)		+= radio_2055.o
+b43-$(CONFIG_B43_NPHY)		+= radio_2056.o
 b43-y				+= phy_common.o
 b43-y				+= phy_g.o
 b43-y				+= phy_a.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 8674a9935..72821c4 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -186,7 +186,8 @@
 #define B43_SHM_SH_PHYTXNOI		0x006E	/* PHY noise directly after TX (lower 8bit only) */
 #define B43_SHM_SH_RFRXSP1		0x0072	/* RF RX SP Register 1 */
 #define B43_SHM_SH_CHAN			0x00A0	/* Current channel (low 8bit only) */
-#define  B43_SHM_SH_CHAN_5GHZ		0x0100	/* Bit set, if 5Ghz channel */
+#define  B43_SHM_SH_CHAN_5GHZ		0x0100	/* Bit set, if 5 Ghz channel */
+#define  B43_SHM_SH_CHAN_40MHZ		0x0200	/* Bit set, if 40 Mhz channel width */
 #define B43_SHM_SH_BCMCFIFOID		0x0108	/* Last posted cookie to the bcast/mcast FIFO */
 /* TSSI information */
 #define B43_SHM_SH_TSSI_CCK		0x0058	/* TSSI for last 4 CCK frames (32bit) */
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 80b19a4..59f59fa 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -627,6 +627,7 @@
 			.open	= b43_debugfs_open,		\
 			.read	= b43_debugfs_read,		\
 			.write	= b43_debugfs_write,		\
+			.llseek = generic_file_llseek,		\
 		},						\
 		.file_struct_offset = offsetof(struct b43_dfsentry, \
 					       file_##name),	\
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 20631ae..a118652 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2280,6 +2280,7 @@
 
 static int b43_upload_microcode(struct b43_wldev *dev)
 {
+	struct wiphy *wiphy = dev->wl->hw->wiphy;
 	const size_t hdr_len = sizeof(struct b43_fw_header);
 	const __be32 *data;
 	unsigned int i, len;
@@ -2405,6 +2406,10 @@
 		}
 	}
 
+	snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
+			dev->fw.rev, dev->fw.patch);
+	wiphy->hw_version = dev->dev->id.coreid;
+
 	if (b43_is_old_txhdr_format(dev)) {
 		/* We're over the deadline, but we keep support for old fw
 		 * until it turns out to be in major conflict with something new. */
@@ -3754,17 +3759,17 @@
 	}
 
 	err = -EINVAL;
-	switch (key->alg) {
-	case ALG_WEP:
-		if (key->keylen == WLAN_KEY_LEN_WEP40)
-			algorithm = B43_SEC_ALGO_WEP40;
-		else
-			algorithm = B43_SEC_ALGO_WEP104;
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+		algorithm = B43_SEC_ALGO_WEP40;
 		break;
-	case ALG_TKIP:
+	case WLAN_CIPHER_SUITE_WEP104:
+		algorithm = B43_SEC_ALGO_WEP104;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
 		algorithm = B43_SEC_ALGO_TKIP;
 		break;
-	case ALG_CCMP:
+	case WLAN_CIPHER_SUITE_CCMP:
 		algorithm = B43_SEC_ALGO_AES;
 		break;
 	default:
@@ -4250,6 +4255,10 @@
 	B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED);
 	if (!dev || b43_status(dev) != B43_STAT_INITIALIZED)
 		return;
+
+	/* Unregister HW RNG driver */
+	b43_rng_exit(dev->wl);
+
 	b43_set_status(dev, B43_STAT_UNINIT);
 
 	/* Stop the microcode PSM. */
@@ -4379,6 +4388,9 @@
 
 	b43_set_status(dev, B43_STAT_INITIALIZED);
 
+	/* Register HW RNG driver */
+	b43_rng_init(dev->wl);
+
 out:
 	return err;
 
@@ -4984,7 +4996,6 @@
 		if (err)
 			goto err_one_core_detach;
 		b43_leds_register(wl->current_dev);
-		b43_rng_init(wl);
 	}
 
       out:
@@ -5020,7 +5031,6 @@
 	b43_one_core_detach(dev);
 
 	if (list_empty(&wl->devlist)) {
-		b43_rng_exit(wl);
 		b43_leds_unregister(wl);
 		/* Last core on the chip unregistered.
 		 * We can destroy common struct b43_wl.
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index dfbc41d..7dcba5f 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -26,7 +26,6 @@
 #include <linux/ssb/ssb.h>
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -63,7 +62,6 @@
 static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 {
 	struct ssb_bus *ssb;
-	win_req_t win;
 	int err = -ENOMEM;
 	int res = 0;
 
@@ -73,30 +71,28 @@
 
 	err = -ENODEV;
 
-	dev->conf.Attributes = CONF_ENABLE_IRQ;
-	dev->conf.IntType = INT_MEMORY_AND_IO;
+	dev->config_flags |= CONF_ENABLE_IRQ;
 
-	win.Attributes =  WIN_ENABLE | WIN_DATA_WIDTH_16 |
+	dev->resource[2]->flags |=  WIN_ENABLE | WIN_DATA_WIDTH_16 |
 			 WIN_USE_WAIT;
-	win.Base = 0;
-	win.Size = SSB_CORE_SIZE;
-	win.AccessSpeed = 250;
-	res = pcmcia_request_window(dev, &win, &dev->win);
+	dev->resource[2]->start = 0;
+	dev->resource[2]->end = SSB_CORE_SIZE;
+	res = pcmcia_request_window(dev, dev->resource[2], 250);
 	if (res != 0)
 		goto err_kfree_ssb;
 
-	res = pcmcia_map_mem_page(dev, dev->win, 0);
+	res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
 	if (res != 0)
 		goto err_disable;
 
 	if (!dev->irq)
 		goto err_disable;
 
-	res = pcmcia_request_configuration(dev, &dev->conf);
+	res = pcmcia_enable_device(dev);
 	if (res != 0)
 		goto err_disable;
 
-	err = ssb_bus_pcmciabus_register(ssb, dev, win.Base);
+	err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
 	if (err)
 		goto err_disable;
 	dev->priv = ssb;
@@ -125,9 +121,7 @@
 
 static struct pcmcia_driver b43_pcmcia_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-				.name = "b43-pcmcia",
-			},
+	.name		= "b43-pcmcia",
 	.id_table	= b43_pcmcia_tbl,
 	.probe		= b43_pcmcia_probe,
 	.remove		= __devexit_p(b43_pcmcia_remove),
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 8f7d7ef..7b2ea67 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -294,8 +294,10 @@
 	 */
 	channelcookie = new_channel;
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
-		channelcookie |= 0x100;
-	//FIXME set 40Mhz flag if required
+		channelcookie |= B43_SHM_SH_CHAN_5GHZ;
+	/* FIXME: set 40Mhz flag if required */
+	if (0)
+		channelcookie |= B43_SHM_SH_CHAN_40MHZ;
 	savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN);
 	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie);
 
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index bd480b4..0e61942 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -2,6 +2,7 @@
 #define LINUX_B43_PHY_COMMON_H_
 
 #include <linux/types.h>
+#include <linux/nl80211.h>
 
 struct b43_wldev;
 
@@ -250,8 +251,10 @@
 	 * check is needed. */
 	unsigned long next_txpwr_check_time;
 
-	/* current channel */
+	/* Current channel */
 	unsigned int channel;
+	u16 channel_freq;
+	enum nl80211_channel_type channel_type;
 
 	/* PHY TX errors counter. */
 	atomic_t txerr_cnt;
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 5a72570..dfec549 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -29,6 +29,8 @@
 #include "b43.h"
 #include "phy_n.h"
 #include "tables_nphy.h"
+#include "radio_2055.h"
+#include "radio_2056.h"
 #include "main.h"
 
 struct nphy_txgains {
@@ -73,21 +75,12 @@
 						u16 value, u8 core, bool off);
 static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
 						u16 value, u8 core);
-static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel);
 
-static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec)
+static inline bool b43_channel_type_is_40mhz(
+					enum nl80211_channel_type channel_type)
 {
-	return !chanspec->channel && !chanspec->sideband &&
-		!chanspec->b_width && !chanspec->b_freq;
-}
-
-static inline bool b43_eq_chanspecs(struct b43_chanspec *chanspec1,
-					struct b43_chanspec *chanspec2)
-{
-	return (chanspec1->channel == chanspec2->channel &&
-		chanspec1->sideband == chanspec2->sideband &&
-		chanspec1->b_width == chanspec2->b_width &&
-		chanspec1->b_freq == chanspec2->b_freq);
+	return (channel_type == NL80211_CHAN_HT40MINUS ||
+		channel_type == NL80211_CHAN_HT40PLUS);
 }
 
 void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
@@ -223,7 +216,7 @@
 	if (i)
 		b43err(dev->wl, "radio post init timeout\n");
 	b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
-	nphy_channel_switch(dev, dev->phy.channel);
+	b43_switch_channel(dev, dev->phy.channel);
 	b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
 	b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
 	b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
@@ -782,7 +775,7 @@
 {
 	struct b43_phy_n *nphy = dev->phy.n;
 
-	u8 channel = nphy->radio_chanspec.channel;
+	u8 channel = dev->phy.channel;
 	int tone[2] = { 57, 58 };
 	u32 noise[2] = { 0x3FF, 0x3FF };
 
@@ -856,9 +849,9 @@
 			gain[0] = 6;
 			gain[1] = 6;
 		} else {
-			tmp = 40370 - 315 * nphy->radio_chanspec.channel;
+			tmp = 40370 - 315 * dev->phy.channel;
 			gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
-			tmp = 23242 - 224 * nphy->radio_chanspec.channel;
+			tmp = 23242 - 224 * dev->phy.channel;
 			gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
 		}
 	} else {
@@ -893,7 +886,7 @@
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
-static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev)
+static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
 {
 	struct b43_phy_n *nphy = dev->phy.n;
 	u8 i, j;
@@ -1094,11 +1087,12 @@
 		b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
 		b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
 
-		b43_nphy_gain_crtl_workarounds(dev);
+		b43_nphy_gain_ctrl_workarounds(dev);
 
 		if (dev->phy.rev < 2) {
 			if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
-				; /*TODO: b43_mhf(dev, 2, 0x0010, 0x0010, 3);*/
+				b43_hf_write(dev, b43_hf_read(dev) |
+						B43_HF_MLADVW);
 		} else if (dev->phy.rev == 2) {
 			b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
 			b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
@@ -1182,7 +1176,7 @@
 		len = bw << 1;
 	}
 
-	samples = kzalloc(len * sizeof(struct b43_c32), GFP_KERNEL);
+	samples = kcalloc(len, sizeof(struct b43_c32), GFP_KERNEL);
 	if (!samples) {
 		b43err(dev->wl, "allocation for samples generation failed\n");
 		return 0;
@@ -2083,12 +2077,12 @@
 	u16 *rssical_phy_regs = NULL;
 
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-		if (b43_empty_chanspec(&nphy->rssical_chanspec_2G))
+		if (!nphy->rssical_chanspec_2G.center_freq)
 			return;
 		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
 		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
 	} else {
-		if (b43_empty_chanspec(&nphy->rssical_chanspec_5G))
+		if (!nphy->rssical_chanspec_5G.center_freq)
 			return;
 		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
 		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
@@ -2544,8 +2538,9 @@
 		txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
 		txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
 	}
-	*iqcal_chanspec = nphy->radio_chanspec;
-	b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 8, table);
+	iqcal_chanspec->center_freq = dev->phy.channel_freq;
+	iqcal_chanspec->channel_type = dev->phy.channel_type;
+	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
 
 	if (nphy->hang_avoid)
 		b43_nphy_stay_in_carrier_search(dev, 0);
@@ -2565,12 +2560,12 @@
 	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
 
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-		if (b43_empty_chanspec(&nphy->iqcal_chanspec_2G))
+		if (!nphy->iqcal_chanspec_2G.center_freq)
 			return;
 		table = nphy->cal_cache.txcal_coeffs_2G;
 		loft = &nphy->cal_cache.txcal_coeffs_2G[5];
 	} else {
-		if (b43_empty_chanspec(&nphy->iqcal_chanspec_5G))
+		if (!nphy->iqcal_chanspec_5G.center_freq)
 			return;
 		table = nphy->cal_cache.txcal_coeffs_5G;
 		loft = &nphy->cal_cache.txcal_coeffs_5G[5];
@@ -2815,7 +2810,10 @@
 			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
 						nphy->txiqlocal_bestc);
 			nphy->txiqlocal_coeffsvalid = true;
-			nphy->txiqlocal_chanspec = nphy->radio_chanspec;
+			nphy->txiqlocal_chanspec.center_freq =
+							dev->phy.channel_freq;
+			nphy->txiqlocal_chanspec.channel_type =
+							dev->phy.channel_type;
 		} else {
 			length = 11;
 			if (dev->phy.rev < 3)
@@ -2851,7 +2849,8 @@
 	bool equal = true;
 
 	if (!nphy->txiqlocal_coeffsvalid ||
-	    b43_eq_chanspecs(&nphy->txiqlocal_chanspec, &nphy->radio_chanspec))
+	    nphy->txiqlocal_chanspec.center_freq != dev->phy.channel_freq ||
+	    nphy->txiqlocal_chanspec.channel_type != dev->phy.channel_type)
 		return;
 
 	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
@@ -3073,6 +3072,57 @@
 		return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
 }
 
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
+static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on)
+{
+	u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
+	if (on)
+		tmslow |= SSB_TMSLOW_PHYCLK;
+	else
+		tmslow &= ~SSB_TMSLOW_PHYCLK;
+	ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
+static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = phy->n;
+	u16 buf[16];
+
+	nphy->phyrxchain = mask;
+
+	if (0 /* FIXME clk */)
+		return;
+
+	b43_mac_suspend(dev);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, true);
+
+	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
+			(mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT);
+
+	if ((mask & 0x3) != 0x3) {
+		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1);
+		if (dev->phy.rev >= 3) {
+			/* TODO */
+		}
+	} else {
+		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E);
+		if (dev->phy.rev >= 3) {
+			/* TODO */
+		}
+	}
+
+	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, false);
+
+	b43_mac_enable(dev);
+}
+
 /*
  * Init N-PHY
  * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
@@ -3173,7 +3223,7 @@
 	b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
 	b43_nphy_bmac_clock_fgc(dev, 0);
 
-	/* TODO N PHY MAC PHY Clock Set with argument 1 */
+	b43_nphy_mac_phy_clock_set(dev, true);
 
 	b43_nphy_pa_override(dev, false);
 	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
@@ -3199,18 +3249,16 @@
 	}
 
 	if (nphy->phyrxchain != 3)
-		;/* TODO N PHY RX Core Set State with phyrxchain as argument */
+		b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
 	if (nphy->mphase_cal_phase_id > 0)
 		;/* TODO PHY Periodic Calibration Multi-Phase Restart */
 
 	do_rssi_cal = false;
 	if (phy->rev >= 3) {
 		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-			do_rssi_cal =
-				b43_empty_chanspec(&nphy->rssical_chanspec_2G);
+			do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;
 		else
-			do_rssi_cal =
-				b43_empty_chanspec(&nphy->rssical_chanspec_5G);
+			do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;
 
 		if (do_rssi_cal)
 			b43_nphy_rssi_cal(dev);
@@ -3222,9 +3270,9 @@
 
 	if (!((nphy->measure_hold & 0x6) != 0)) {
 		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-			do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_2G);
+			do_cal = !nphy->iqcal_chanspec_2G.center_freq;
 		else
-			do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_5G);
+			do_cal = !nphy->iqcal_chanspec_5G.center_freq;
 
 		if (nphy->mute)
 			do_cal = false;
@@ -3272,24 +3320,25 @@
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
-static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
+static void b43_nphy_channel_setup(struct b43_wldev *dev,
 				const struct b43_phy_n_sfo_cfg *e,
-				struct b43_chanspec chanspec)
+				struct ieee80211_channel *new_channel)
 {
 	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 
-	u16 tmp;
+	u16 old_band_5ghz;
 	u32 tmp32;
 
-	tmp = b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
-	if (chanspec.b_freq == 1 && tmp == 0) {
+	old_band_5ghz =
+		b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
+	if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
 		tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
 		b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
 		b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
 		b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
 		b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
-	} else if (chanspec.b_freq == 1) {
+	} else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
 		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
 		tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
 		b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
@@ -3299,19 +3348,12 @@
 
 	b43_chantab_phy_upload(dev, e);
 
-	tmp = chanspec.channel;
-	if (chanspec.b_freq == 1)
-		tmp |= 0x0100;
-	if (chanspec.b_width == 3)
-		tmp |= 0x0200;
-	b43_shm_write16(dev, B43_SHM_SHARED, 0xA0, tmp);
-
-	if (nphy->radio_chanspec.channel == 14) {
+	if (new_channel->hw_value == 14) {
 		b43_nphy_classifier(dev, 2, 0);
 		b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);
 	} else {
 		b43_nphy_classifier(dev, 2, 2);
-		if (chanspec.b_freq == 2)
+		if (new_channel->band == IEEE80211_BAND_2GHZ)
 			b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
 	}
 
@@ -3334,70 +3376,62 @@
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
-static int b43_nphy_set_chanspec(struct b43_wldev *dev,
-					struct b43_chanspec chanspec)
+static int b43_nphy_set_channel(struct b43_wldev *dev,
+				struct ieee80211_channel *channel,
+				enum nl80211_channel_type channel_type)
 {
+	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = dev->phy.n;
 
 	const struct b43_nphy_channeltab_entry_rev2 *tabent_r2;
 	const struct b43_nphy_channeltab_entry_rev3 *tabent_r3;
 
 	u8 tmp;
-	u8 channel = chanspec.channel;
 
 	if (dev->phy.rev >= 3) {
-		/* TODO */
+		tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
+							channel->center_freq);
 		tabent_r3 = NULL;
 		if (!tabent_r3)
 			return -ESRCH;
 	} else {
-		tabent_r2 = b43_nphy_get_chantabent_rev2(dev, channel);
+		tabent_r2 = b43_nphy_get_chantabent_rev2(dev,
+							channel->hw_value);
 		if (!tabent_r2)
 			return -ESRCH;
 	}
 
-	nphy->radio_chanspec = chanspec;
+	/* Channel is set later in common code, but we need to set it on our
+	   own to let this function's subcalls work properly. */
+	phy->channel = channel->hw_value;
+	phy->channel_freq = channel->center_freq;
 
-	if (chanspec.b_width != nphy->b_width)
-		; /* TODO: BMAC BW Set (chanspec.b_width) */
+	if (b43_channel_type_is_40mhz(phy->channel_type) !=
+		b43_channel_type_is_40mhz(channel_type))
+		; /* TODO: BMAC BW Set (channel_type) */
 
-	/* TODO: use defines */
-	if (chanspec.b_width == 3) {
-		if (chanspec.sideband == 2)
-			b43_phy_set(dev, B43_NPHY_RXCTL,
-					B43_NPHY_RXCTL_BSELU20);
-		else
-			b43_phy_mask(dev, B43_NPHY_RXCTL,
-					~B43_NPHY_RXCTL_BSELU20);
-	}
+	if (channel_type == NL80211_CHAN_HT40PLUS)
+		b43_phy_set(dev, B43_NPHY_RXCTL,
+				B43_NPHY_RXCTL_BSELU20);
+	else if (channel_type == NL80211_CHAN_HT40MINUS)
+		b43_phy_mask(dev, B43_NPHY_RXCTL,
+				~B43_NPHY_RXCTL_BSELU20);
 
 	if (dev->phy.rev >= 3) {
-		tmp = (chanspec.b_freq == 1) ? 4 : 0;
+		tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
 		b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
 		/* TODO: PHY Radio2056 Setup (dev, tabent_r3); */
-		b43_nphy_chanspec_setup(dev, &(tabent_r3->phy_regs), chanspec);
+		b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
 	} else {
-		tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050;
+		tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050;
 		b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
 		b43_radio_2055_setup(dev, tabent_r2);
-		b43_nphy_chanspec_setup(dev, &(tabent_r2->phy_regs), chanspec);
+		b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel);
 	}
 
 	return 0;
 }
 
-/* Tune the hardware to a new channel */
-static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
-{
-	struct b43_phy_n *nphy = dev->phy.n;
-
-	struct b43_chanspec chanspec;
-	chanspec = nphy->radio_chanspec;
-	chanspec.channel = channel;
-
-	return b43_nphy_set_chanspec(dev, chanspec);
-}
-
 static int b43_nphy_op_allocate(struct b43_wldev *dev)
 {
 	struct b43_phy_n *nphy;
@@ -3518,7 +3552,7 @@
 	} else {
 		if (dev->phy.rev >= 3) {
 			b43_radio_init2056(dev);
-			b43_nphy_set_chanspec(dev, nphy->radio_chanspec);
+			b43_switch_channel(dev, dev->phy.channel);
 		} else {
 			b43_radio_init2055(dev);
 		}
@@ -3534,6 +3568,9 @@
 static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
 				      unsigned int new_channel)
 {
+	struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
+	enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
 		if ((new_channel < 1) || (new_channel > 14))
 			return -EINVAL;
@@ -3542,7 +3579,7 @@
 			return -EINVAL;
 	}
 
-	return nphy_channel_switch(dev, new_channel);
+	return b43_nphy_set_channel(dev, channel, channel_type);
 }
 
 static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h
index 8b6d570..c144e59 100644
--- a/drivers/net/wireless/b43/phy_n.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -714,223 +714,11 @@
 #define B43_PHY_B_BBCFG				B43_PHY_N_BMODE(0x001) /* BB config */
 #define B43_PHY_B_TEST				B43_PHY_N_BMODE(0x00A)
 
-
-/* Broadcom 2055 radio registers */
-
-#define B2055_GEN_SPARE			0x00 /* GEN spare */
-#define B2055_SP_PINPD			0x02 /* SP PIN PD */
-#define B2055_C1_SP_RSSI		0x03 /* SP RSSI Core 1 */
-#define B2055_C1_SP_PDMISC		0x04 /* SP PD MISC Core 1 */
-#define B2055_C2_SP_RSSI		0x05 /* SP RSSI Core 2 */
-#define B2055_C2_SP_PDMISC		0x06 /* SP PD MISC Core 2 */
-#define B2055_C1_SP_RXGC1		0x07 /* SP RX GC1 Core 1 */
-#define B2055_C1_SP_RXGC2		0x08 /* SP RX GC2 Core 1 */
-#define B2055_C2_SP_RXGC1		0x09 /* SP RX GC1 Core 2 */
-#define B2055_C2_SP_RXGC2		0x0A /* SP RX GC2 Core 2 */
-#define B2055_C1_SP_LPFBWSEL		0x0B /* SP LPF BW select Core 1 */
-#define B2055_C2_SP_LPFBWSEL		0x0C /* SP LPF BW select Core 2 */
-#define B2055_C1_SP_TXGC1		0x0D /* SP TX GC1 Core 1 */
-#define B2055_C1_SP_TXGC2		0x0E /* SP TX GC2 Core 1 */
-#define B2055_C2_SP_TXGC1		0x0F /* SP TX GC1 Core 2 */
-#define B2055_C2_SP_TXGC2		0x10 /* SP TX GC2 Core 2 */
-#define B2055_MASTER1			0x11 /* Master control 1 */
-#define B2055_MASTER2			0x12 /* Master control 2 */
-#define B2055_PD_LGEN			0x13 /* PD LGEN */
-#define B2055_PD_PLLTS			0x14 /* PD PLL TS */
-#define B2055_C1_PD_LGBUF		0x15 /* PD Core 1 LGBUF */
-#define B2055_C1_PD_TX			0x16 /* PD Core 1 TX */
-#define B2055_C1_PD_RXTX		0x17 /* PD Core 1 RXTX */
-#define B2055_C1_PD_RSSIMISC		0x18 /* PD Core 1 RSSI MISC */
-#define B2055_C2_PD_LGBUF		0x19 /* PD Core 2 LGBUF */
-#define B2055_C2_PD_TX			0x1A /* PD Core 2 TX */
-#define B2055_C2_PD_RXTX		0x1B /* PD Core 2 RXTX */
-#define B2055_C2_PD_RSSIMISC		0x1C /* PD Core 2 RSSI MISC */
-#define B2055_PWRDET_LGEN		0x1D /* PWRDET LGEN */
-#define B2055_C1_PWRDET_LGBUF		0x1E /* PWRDET LGBUF Core 1 */
-#define B2055_C1_PWRDET_RXTX		0x1F /* PWRDET RXTX Core 1 */
-#define B2055_C2_PWRDET_LGBUF		0x20 /* PWRDET LGBUF Core 2 */
-#define B2055_C2_PWRDET_RXTX		0x21 /* PWRDET RXTX Core 2 */
-#define B2055_RRCCAL_CS			0x22 /* RRCCAL Control spare */
-#define B2055_RRCCAL_NOPTSEL		0x23 /* RRCCAL N OPT SEL */
-#define B2055_CAL_MISC			0x24 /* CAL MISC */
-#define B2055_CAL_COUT			0x25 /* CAL Counter out */
-#define B2055_CAL_COUT2			0x26 /* CAL Counter out 2 */
-#define B2055_CAL_CVARCTL		0x27 /* CAL CVAR Control */
-#define B2055_CAL_RVARCTL		0x28 /* CAL RVAR Control */
-#define B2055_CAL_LPOCTL		0x29 /* CAL LPO Control */
-#define B2055_CAL_TS			0x2A /* CAL TS */
-#define B2055_CAL_RCCALRTS		0x2B /* CAL RCCAL READ TS */
-#define B2055_CAL_RCALRTS		0x2C /* CAL RCAL READ TS */
-#define B2055_PADDRV			0x2D /* PAD driver */
-#define B2055_XOCTL1			0x2E /* XO Control 1 */
-#define B2055_XOCTL2			0x2F /* XO Control 2 */
-#define B2055_XOREGUL			0x30 /* XO Regulator */
-#define B2055_XOMISC			0x31 /* XO misc */
-#define B2055_PLL_LFC1			0x32 /* PLL LF C1 */
-#define B2055_PLL_CALVTH		0x33 /* PLL CAL VTH */
-#define B2055_PLL_LFC2			0x34 /* PLL LF C2 */
-#define B2055_PLL_REF			0x35 /* PLL reference */
-#define B2055_PLL_LFR1			0x36 /* PLL LF R1 */
-#define B2055_PLL_PFDCP			0x37 /* PLL PFD CP */
-#define B2055_PLL_IDAC_CPOPAMP		0x38 /* PLL IDAC CPOPAMP */
-#define B2055_PLL_CPREG			0x39 /* PLL CP Regulator */
-#define B2055_PLL_RCAL			0x3A /* PLL RCAL */
-#define B2055_RF_PLLMOD0		0x3B /* RF PLL MOD0 */
-#define B2055_RF_PLLMOD1		0x3C /* RF PLL MOD1 */
-#define B2055_RF_MMDIDAC1		0x3D /* RF MMD IDAC 1 */
-#define B2055_RF_MMDIDAC0		0x3E /* RF MMD IDAC 0 */
-#define B2055_RF_MMDSP			0x3F /* RF MMD spare */
-#define B2055_VCO_CAL1			0x40 /* VCO cal 1 */
-#define B2055_VCO_CAL2			0x41 /* VCO cal 2 */
-#define B2055_VCO_CAL3			0x42 /* VCO cal 3 */
-#define B2055_VCO_CAL4			0x43 /* VCO cal 4 */
-#define B2055_VCO_CAL5			0x44 /* VCO cal 5 */
-#define B2055_VCO_CAL6			0x45 /* VCO cal 6 */
-#define B2055_VCO_CAL7			0x46 /* VCO cal 7 */
-#define B2055_VCO_CAL8			0x47 /* VCO cal 8 */
-#define B2055_VCO_CAL9			0x48 /* VCO cal 9 */
-#define B2055_VCO_CAL10			0x49 /* VCO cal 10 */
-#define B2055_VCO_CAL11			0x4A /* VCO cal 11 */
-#define B2055_VCO_CAL12			0x4B /* VCO cal 12 */
-#define B2055_VCO_CAL13			0x4C /* VCO cal 13 */
-#define B2055_VCO_CAL14			0x4D /* VCO cal 14 */
-#define B2055_VCO_CAL15			0x4E /* VCO cal 15 */
-#define B2055_VCO_CAL16			0x4F /* VCO cal 16 */
-#define B2055_VCO_KVCO			0x50 /* VCO KVCO */
-#define B2055_VCO_CAPTAIL		0x51 /* VCO CAP TAIL */
-#define B2055_VCO_IDACVCO		0x52 /* VCO IDAC VCO */
-#define B2055_VCO_REG			0x53 /* VCO Regulator */
-#define B2055_PLL_RFVTH			0x54 /* PLL RF VTH */
-#define B2055_LGBUF_CENBUF		0x55 /* LGBUF CEN BUF */
-#define B2055_LGEN_TUNE1		0x56 /* LGEN tune 1 */
-#define B2055_LGEN_TUNE2		0x57 /* LGEN tune 2 */
-#define B2055_LGEN_IDAC1		0x58 /* LGEN IDAC 1 */
-#define B2055_LGEN_IDAC2		0x59 /* LGEN IDAC 2 */
-#define B2055_LGEN_BIASC		0x5A /* LGEN BIAS counter */
-#define B2055_LGEN_BIASIDAC		0x5B /* LGEN BIAS IDAC */
-#define B2055_LGEN_RCAL			0x5C /* LGEN RCAL */
-#define B2055_LGEN_DIV			0x5D /* LGEN div */
-#define B2055_LGEN_SPARE2		0x5E /* LGEN spare 2 */
-#define B2055_C1_LGBUF_ATUNE		0x5F /* Core 1 LGBUF A tune */
-#define B2055_C1_LGBUF_GTUNE		0x60 /* Core 1 LGBUF G tune */
-#define B2055_C1_LGBUF_DIV		0x61 /* Core 1 LGBUF div */
-#define B2055_C1_LGBUF_AIDAC		0x62 /* Core 1 LGBUF A IDAC */
-#define B2055_C1_LGBUF_GIDAC		0x63 /* Core 1 LGBUF G IDAC */
-#define B2055_C1_LGBUF_IDACFO		0x64 /* Core 1 LGBUF IDAC filter override */
-#define B2055_C1_LGBUF_SPARE		0x65 /* Core 1 LGBUF spare */
-#define B2055_C1_RX_RFSPC1		0x66 /* Core 1 RX RF SPC1 */
-#define B2055_C1_RX_RFR1		0x67 /* Core 1 RX RF reg 1 */
-#define B2055_C1_RX_RFR2		0x68 /* Core 1 RX RF reg 2 */
-#define B2055_C1_RX_RFRCAL		0x69 /* Core 1 RX RF RCAL */
-#define B2055_C1_RX_BB_BLCMP		0x6A /* Core 1 RX Baseband BUFI LPF CMP */
-#define B2055_C1_RX_BB_LPF		0x6B /* Core 1 RX Baseband LPF */
-#define B2055_C1_RX_BB_MIDACHP		0x6C /* Core 1 RX Baseband MIDAC High-pass */
-#define B2055_C1_RX_BB_VGA1IDAC		0x6D /* Core 1 RX Baseband VGA1 IDAC */
-#define B2055_C1_RX_BB_VGA2IDAC		0x6E /* Core 1 RX Baseband VGA2 IDAC */
-#define B2055_C1_RX_BB_VGA3IDAC		0x6F /* Core 1 RX Baseband VGA3 IDAC */
-#define B2055_C1_RX_BB_BUFOCTL		0x70 /* Core 1 RX Baseband BUFO Control */
-#define B2055_C1_RX_BB_RCCALCTL		0x71 /* Core 1 RX Baseband RCCAL Control */
-#define B2055_C1_RX_BB_RSSICTL1		0x72 /* Core 1 RX Baseband RSSI Control 1 */
-#define B2055_C1_RX_BB_RSSICTL2		0x73 /* Core 1 RX Baseband RSSI Control 2 */
-#define B2055_C1_RX_BB_RSSICTL3		0x74 /* Core 1 RX Baseband RSSI Control 3 */
-#define B2055_C1_RX_BB_RSSICTL4		0x75 /* Core 1 RX Baseband RSSI Control 4 */
-#define B2055_C1_RX_BB_RSSICTL5		0x76 /* Core 1 RX Baseband RSSI Control 5 */
-#define B2055_C1_RX_BB_REG		0x77 /* Core 1 RX Baseband Regulator */
-#define B2055_C1_RX_BB_SPARE1		0x78 /* Core 1 RX Baseband spare 1 */
-#define B2055_C1_RX_TXBBRCAL		0x79 /* Core 1 RX TX BB RCAL */
-#define B2055_C1_TX_RF_SPGA		0x7A /* Core 1 TX RF SGM PGA */
-#define B2055_C1_TX_RF_SPAD		0x7B /* Core 1 TX RF SGM PAD */
-#define B2055_C1_TX_RF_CNTPGA1		0x7C /* Core 1 TX RF counter PGA 1 */
-#define B2055_C1_TX_RF_CNTPAD1		0x7D /* Core 1 TX RF counter PAD 1 */
-#define B2055_C1_TX_RF_PGAIDAC		0x7E /* Core 1 TX RF PGA IDAC */
-#define B2055_C1_TX_PGAPADTN		0x7F /* Core 1 TX PGA PAD TN */
-#define B2055_C1_TX_PADIDAC1		0x80 /* Core 1 TX PAD IDAC 1 */
-#define B2055_C1_TX_PADIDAC2		0x81 /* Core 1 TX PAD IDAC 2 */
-#define B2055_C1_TX_MXBGTRIM		0x82 /* Core 1 TX MX B/G TRIM */
-#define B2055_C1_TX_RF_RCAL		0x83 /* Core 1 TX RF RCAL */
-#define B2055_C1_TX_RF_PADTSSI1		0x84 /* Core 1 TX RF PAD TSSI1 */
-#define B2055_C1_TX_RF_PADTSSI2		0x85 /* Core 1 TX RF PAD TSSI2 */
-#define B2055_C1_TX_RF_SPARE		0x86 /* Core 1 TX RF spare */
-#define B2055_C1_TX_RF_IQCAL1		0x87 /* Core 1 TX RF I/Q CAL 1 */
-#define B2055_C1_TX_RF_IQCAL2		0x88 /* Core 1 TX RF I/Q CAL 2 */
-#define B2055_C1_TXBB_RCCAL		0x89 /* Core 1 TXBB RC CAL Control */
-#define B2055_C1_TXBB_LPF1		0x8A /* Core 1 TXBB LPF 1 */
-#define B2055_C1_TX_VOSCNCL		0x8B /* Core 1 TX VOS CNCL */
-#define B2055_C1_TX_LPF_MXGMIDAC	0x8C /* Core 1 TX LPF MXGM IDAC */
-#define B2055_C1_TX_BB_MXGM		0x8D /* Core 1 TX BB MXGM */
-#define B2055_C2_LGBUF_ATUNE		0x8E /* Core 2 LGBUF A tune */
-#define B2055_C2_LGBUF_GTUNE		0x8F /* Core 2 LGBUF G tune */
-#define B2055_C2_LGBUF_DIV		0x90 /* Core 2 LGBUF div */
-#define B2055_C2_LGBUF_AIDAC		0x91 /* Core 2 LGBUF A IDAC */
-#define B2055_C2_LGBUF_GIDAC		0x92 /* Core 2 LGBUF G IDAC */
-#define B2055_C2_LGBUF_IDACFO		0x93 /* Core 2 LGBUF IDAC filter override */
-#define B2055_C2_LGBUF_SPARE		0x94 /* Core 2 LGBUF spare */
-#define B2055_C2_RX_RFSPC1		0x95 /* Core 2 RX RF SPC1 */
-#define B2055_C2_RX_RFR1		0x96 /* Core 2 RX RF reg 1 */
-#define B2055_C2_RX_RFR2		0x97 /* Core 2 RX RF reg 2 */
-#define B2055_C2_RX_RFRCAL		0x98 /* Core 2 RX RF RCAL */
-#define B2055_C2_RX_BB_BLCMP		0x99 /* Core 2 RX Baseband BUFI LPF CMP */
-#define B2055_C2_RX_BB_LPF		0x9A /* Core 2 RX Baseband LPF */
-#define B2055_C2_RX_BB_MIDACHP		0x9B /* Core 2 RX Baseband MIDAC High-pass */
-#define B2055_C2_RX_BB_VGA1IDAC		0x9C /* Core 2 RX Baseband VGA1 IDAC */
-#define B2055_C2_RX_BB_VGA2IDAC		0x9D /* Core 2 RX Baseband VGA2 IDAC */
-#define B2055_C2_RX_BB_VGA3IDAC		0x9E /* Core 2 RX Baseband VGA3 IDAC */
-#define B2055_C2_RX_BB_BUFOCTL		0x9F /* Core 2 RX Baseband BUFO Control */
-#define B2055_C2_RX_BB_RCCALCTL		0xA0 /* Core 2 RX Baseband RCCAL Control */
-#define B2055_C2_RX_BB_RSSICTL1		0xA1 /* Core 2 RX Baseband RSSI Control 1 */
-#define B2055_C2_RX_BB_RSSICTL2		0xA2 /* Core 2 RX Baseband RSSI Control 2 */
-#define B2055_C2_RX_BB_RSSICTL3		0xA3 /* Core 2 RX Baseband RSSI Control 3 */
-#define B2055_C2_RX_BB_RSSICTL4		0xA4 /* Core 2 RX Baseband RSSI Control 4 */
-#define B2055_C2_RX_BB_RSSICTL5		0xA5 /* Core 2 RX Baseband RSSI Control 5 */
-#define B2055_C2_RX_BB_REG		0xA6 /* Core 2 RX Baseband Regulator */
-#define B2055_C2_RX_BB_SPARE1		0xA7 /* Core 2 RX Baseband spare 1 */
-#define B2055_C2_RX_TXBBRCAL		0xA8 /* Core 2 RX TX BB RCAL */
-#define B2055_C2_TX_RF_SPGA		0xA9 /* Core 2 TX RF SGM PGA */
-#define B2055_C2_TX_RF_SPAD		0xAA /* Core 2 TX RF SGM PAD */
-#define B2055_C2_TX_RF_CNTPGA1		0xAB /* Core 2 TX RF counter PGA 1 */
-#define B2055_C2_TX_RF_CNTPAD1		0xAC /* Core 2 TX RF counter PAD 1 */
-#define B2055_C2_TX_RF_PGAIDAC		0xAD /* Core 2 TX RF PGA IDAC */
-#define B2055_C2_TX_PGAPADTN		0xAE /* Core 2 TX PGA PAD TN */
-#define B2055_C2_TX_PADIDAC1		0xAF /* Core 2 TX PAD IDAC 1 */
-#define B2055_C2_TX_PADIDAC2		0xB0 /* Core 2 TX PAD IDAC 2 */
-#define B2055_C2_TX_MXBGTRIM		0xB1 /* Core 2 TX MX B/G TRIM */
-#define B2055_C2_TX_RF_RCAL		0xB2 /* Core 2 TX RF RCAL */
-#define B2055_C2_TX_RF_PADTSSI1		0xB3 /* Core 2 TX RF PAD TSSI1 */
-#define B2055_C2_TX_RF_PADTSSI2		0xB4 /* Core 2 TX RF PAD TSSI2 */
-#define B2055_C2_TX_RF_SPARE		0xB5 /* Core 2 TX RF spare */
-#define B2055_C2_TX_RF_IQCAL1		0xB6 /* Core 2 TX RF I/Q CAL 1 */
-#define B2055_C2_TX_RF_IQCAL2		0xB7 /* Core 2 TX RF I/Q CAL 2 */
-#define B2055_C2_TXBB_RCCAL		0xB8 /* Core 2 TXBB RC CAL Control */
-#define B2055_C2_TXBB_LPF1		0xB9 /* Core 2 TXBB LPF 1 */
-#define B2055_C2_TX_VOSCNCL		0xBA /* Core 2 TX VOS CNCL */
-#define B2055_C2_TX_LPF_MXGMIDAC	0xBB /* Core 2 TX LPF MXGM IDAC */
-#define B2055_C2_TX_BB_MXGM		0xBC /* Core 2 TX BB MXGM */
-#define B2055_PRG_GCHP21		0xBD /* PRG GC HPVGA23 21 */
-#define B2055_PRG_GCHP22		0xBE /* PRG GC HPVGA23 22 */
-#define B2055_PRG_GCHP23		0xBF /* PRG GC HPVGA23 23 */
-#define B2055_PRG_GCHP24		0xC0 /* PRG GC HPVGA23 24 */
-#define B2055_PRG_GCHP25		0xC1 /* PRG GC HPVGA23 25 */
-#define B2055_PRG_GCHP26		0xC2 /* PRG GC HPVGA23 26 */
-#define B2055_PRG_GCHP27		0xC3 /* PRG GC HPVGA23 27 */
-#define B2055_PRG_GCHP28		0xC4 /* PRG GC HPVGA23 28 */
-#define B2055_PRG_GCHP29		0xC5 /* PRG GC HPVGA23 29 */
-#define B2055_PRG_GCHP30		0xC6 /* PRG GC HPVGA23 30 */
-#define B2055_C1_LNA_GAINBST		0xCD /* Core 1 LNA GAINBST */
-#define B2055_C1_B0NB_RSSIVCM		0xD2 /* Core 1 B0 narrow-band RSSI VCM */
-#define B2055_C1_GENSPARE2		0xD6 /* Core 1 GEN spare 2 */
-#define B2055_C2_LNA_GAINBST		0xD9 /* Core 2 LNA GAINBST */
-#define B2055_C2_B0NB_RSSIVCM		0xDE /* Core 2 B0 narrow-band RSSI VCM */
-#define B2055_C2_GENSPARE2		0xE2 /* Core 2 GEN spare 2 */
-
-
-
 struct b43_wldev;
 
 struct b43_chanspec {
-	u8 channel;
-	u8 sideband;
-	u8 b_width;
-	u8 b_freq;
+	u16 center_freq;
+	enum nl80211_channel_type channel_type;
 };
 
 struct b43_phy_n_iq_comp {
@@ -984,8 +772,6 @@
 	u16 papd_epsilon_offset[2];
 	s32 preamble_override;
 	u32 bb_mult_save;
-	u8 b_width;
-	struct b43_chanspec radio_chanspec;
 
 	bool gain_boost;
 	bool elna_gain_config;
diff --git a/drivers/net/wireless/b43/radio_2055.c b/drivers/net/wireless/b43/radio_2055.c
new file mode 100644
index 0000000..1b53165
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2055.c
@@ -0,0 +1,1332 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n PHY and radio device data tables
+
+  Copyright (c) 2008 Michael Buesch <mb@bu3sch.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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "radio_2055.h"
+#include "phy_common.h"
+
+struct b2055_inittab_entry {
+	/* Value to write if we use the 5GHz band. */
+	u16 ghz5;
+	/* Value to write if we use the 2.4GHz band. */
+	u16 ghz2;
+	/* Flags */
+	u8 flags;
+#define B2055_INITTAB_ENTRY_OK	0x01
+#define B2055_INITTAB_UPLOAD	0x02
+};
+#define UPLOAD		.flags = B2055_INITTAB_ENTRY_OK | B2055_INITTAB_UPLOAD
+#define NOUPLOAD	.flags = B2055_INITTAB_ENTRY_OK
+
+static const struct b2055_inittab_entry b2055_inittab [] = {
+  [B2055_SP_PINPD]		= { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+  [B2055_C1_SP_RSSI]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_SP_PDMISC]		= { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
+  [B2055_C2_SP_RSSI]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_SP_PDMISC]		= { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
+  [B2055_C1_SP_RXGC1]		= { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
+  [B2055_C1_SP_RXGC2]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+  [B2055_C2_SP_RXGC1]		= { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
+  [B2055_C2_SP_RXGC2]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+  [B2055_C1_SP_LPFBWSEL]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+  [B2055_C2_SP_LPFBWSEL]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+  [B2055_C1_SP_TXGC1]		= { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
+  [B2055_C1_SP_TXGC2]		= { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+  [B2055_C2_SP_TXGC1]		= { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
+  [B2055_C2_SP_TXGC2]		= { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+  [B2055_MASTER1]		= { .ghz5 = 0x00D0, .ghz2 = 0x00D0, NOUPLOAD, },
+  [B2055_MASTER2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+  [B2055_PD_LGEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_PD_PLLTS]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+  [B2055_C1_PD_LGBUF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_PD_TX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_PD_RXTX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_PD_RSSIMISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_PD_LGBUF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_PD_TX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_PD_RXTX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_PD_RSSIMISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_PWRDET_LGEN]		= { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+  [B2055_C1_PWRDET_LGBUF]	= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+  [B2055_C1_PWRDET_RXTX]	= { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+  [B2055_C2_PWRDET_LGBUF]	= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+  [B2055_C2_PWRDET_RXTX]	= { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+  [B2055_RRCCAL_CS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_RRCCAL_NOPTSEL]	= { .ghz5 = 0x002C, .ghz2 = 0x002C, NOUPLOAD, },
+  [B2055_CAL_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_COUT]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_COUT2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_CVARCTL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_RVARCTL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_LPOCTL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_TS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_RCCALRTS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_RCALRTS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_PADDRV]		= { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+  [B2055_XOCTL1]		= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+  [B2055_XOCTL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_XOREGUL]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+  [B2055_XOMISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_PLL_LFC1]		= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+  [B2055_PLL_CALVTH]		= { .ghz5 = 0x0087, .ghz2 = 0x0087, NOUPLOAD, },
+  [B2055_PLL_LFC2]		= { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
+  [B2055_PLL_REF]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+  [B2055_PLL_LFR1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+  [B2055_PLL_PFDCP]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, UPLOAD, },
+  [B2055_PLL_IDAC_CPOPAMP]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_PLL_CPREG]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+  [B2055_PLL_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_RF_PLLMOD0]		= { .ghz5 = 0x009E, .ghz2 = 0x009E, NOUPLOAD, },
+  [B2055_RF_PLLMOD1]		= { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
+  [B2055_RF_MMDIDAC1]		= { .ghz5 = 0x00C8, .ghz2 = 0x00C8, UPLOAD, },
+  [B2055_RF_MMDIDAC0]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_RF_MMDSP]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL3]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+  [B2055_VCO_CAL4]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+  [B2055_VCO_CAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+  [B2055_VCO_CAL6]		= { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
+  [B2055_VCO_CAL7]		= { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
+  [B2055_VCO_CAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+  [B2055_VCO_CAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+  [B2055_VCO_CAL10]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+  [B2055_VCO_CAL11]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+  [B2055_VCO_CAL12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_KVCO]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_VCO_CAPTAIL]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_VCO_IDACVCO]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_VCO_REG]		= { .ghz5 = 0x0084, .ghz2 = 0x0084, UPLOAD, },
+  [B2055_PLL_RFVTH]		= { .ghz5 = 0x00C3, .ghz2 = 0x00C3, NOUPLOAD, },
+  [B2055_LGBUF_CENBUF]		= { .ghz5 = 0x008F, .ghz2 = 0x008F, NOUPLOAD, },
+  [B2055_LGEN_TUNE1]		= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+  [B2055_LGEN_TUNE2]		= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+  [B2055_LGEN_IDAC1]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_LGEN_IDAC2]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_LGEN_BIASC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_LGEN_BIASIDAC]		= { .ghz5 = 0x00CC, .ghz2 = 0x00CC, NOUPLOAD, },
+  [B2055_LGEN_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_LGEN_DIV]		= { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+  [B2055_LGEN_SPARE2]		= { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+  [B2055_C1_LGBUF_ATUNE]	= { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
+  [B2055_C1_LGBUF_GTUNE]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C1_LGBUF_DIV]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C1_LGBUF_AIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
+  [B2055_C1_LGBUF_GIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C1_LGBUF_IDACFO]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_LGBUF_SPARE]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
+  [B2055_C1_RX_RFSPC1]		= { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
+  [B2055_C1_RX_RFR1]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_C1_RX_RFR2]		= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+  [B2055_C1_RX_RFRCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C1_RX_BB_BLCMP]	= { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
+  [B2055_C1_RX_BB_LPF]		= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+  [B2055_C1_RX_BB_MIDACHP]	= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+  [B2055_C1_RX_BB_VGA1IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C1_RX_BB_VGA2IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C1_RX_BB_VGA3IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C1_RX_BB_BUFOCTL]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C1_RX_BB_RCCALCTL]	= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C1_RX_BB_RSSICTL1]	= { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
+  [B2055_C1_RX_BB_RSSICTL2]	= { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
+  [B2055_C1_RX_BB_RSSICTL3]	= { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
+  [B2055_C1_RX_BB_RSSICTL4]	= { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
+  [B2055_C1_RX_BB_RSSICTL5]	= { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
+  [B2055_C1_RX_BB_REG]		= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+  [B2055_C1_RX_BB_SPARE1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_RX_TXBBRCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C1_TX_RF_SPGA]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+  [B2055_C1_TX_RF_SPAD]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+  [B2055_C1_TX_RF_CNTPGA1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+  [B2055_C1_TX_RF_CNTPAD1]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+  [B2055_C1_TX_RF_PGAIDAC]	= { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
+  [B2055_C1_TX_PGAPADTN]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_C1_TX_PADIDAC1]	= { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
+  [B2055_C1_TX_PADIDAC2]	= { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
+  [B2055_C1_TX_MXBGTRIM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C1_TX_RF_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C1_TX_RF_PADTSSI1]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+  [B2055_C1_TX_RF_PADTSSI2]	= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+  [B2055_C1_TX_RF_SPARE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+  [B2055_C1_TX_RF_IQCAL1]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C1_TX_RF_IQCAL2]	= { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+  [B2055_C1_TXBB_RCCAL]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C1_TXBB_LPF1]		= { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
+  [B2055_C1_TX_VOSCNCL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_TX_LPF_MXGMIDAC]	= { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
+  [B2055_C1_TX_BB_MXGM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_LGBUF_ATUNE]	= { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
+  [B2055_C2_LGBUF_GTUNE]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C2_LGBUF_DIV]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C2_LGBUF_AIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
+  [B2055_C2_LGBUF_GIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C2_LGBUF_IDACFO]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_LGBUF_SPARE]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
+  [B2055_C2_RX_RFSPC1]		= { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
+  [B2055_C2_RX_RFR1]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_C2_RX_RFR2]		= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+  [B2055_C2_RX_RFRCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C2_RX_BB_BLCMP]	= { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
+  [B2055_C2_RX_BB_LPF]		= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+  [B2055_C2_RX_BB_MIDACHP]	= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+  [B2055_C2_RX_BB_VGA1IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C2_RX_BB_VGA2IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C2_RX_BB_VGA3IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C2_RX_BB_BUFOCTL]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C2_RX_BB_RCCALCTL]	= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C2_RX_BB_RSSICTL1]	= { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
+  [B2055_C2_RX_BB_RSSICTL2]	= { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
+  [B2055_C2_RX_BB_RSSICTL3]	= { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
+  [B2055_C2_RX_BB_RSSICTL4]	= { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
+  [B2055_C2_RX_BB_RSSICTL5]	= { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
+  [B2055_C2_RX_BB_REG]		= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+  [B2055_C2_RX_BB_SPARE1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_RX_TXBBRCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C2_TX_RF_SPGA]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+  [B2055_C2_TX_RF_SPAD]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+  [B2055_C2_TX_RF_CNTPGA1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+  [B2055_C2_TX_RF_CNTPAD1]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+  [B2055_C2_TX_RF_PGAIDAC]	= { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
+  [B2055_C2_TX_PGAPADTN]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_C2_TX_PADIDAC1]	= { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
+  [B2055_C2_TX_PADIDAC2]	= { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
+  [B2055_C2_TX_MXBGTRIM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C2_TX_RF_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C2_TX_RF_PADTSSI1]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+  [B2055_C2_TX_RF_PADTSSI2]	= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+  [B2055_C2_TX_RF_SPARE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+  [B2055_C2_TX_RF_IQCAL1]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C2_TX_RF_IQCAL2]	= { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+  [B2055_C2_TXBB_RCCAL]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C2_TXBB_LPF1]		= { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
+  [B2055_C2_TX_VOSCNCL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_TX_LPF_MXGMIDAC]	= { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
+  [B2055_C2_TX_BB_MXGM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_PRG_GCHP21]		= { .ghz5 = 0x0071, .ghz2 = 0x0071, NOUPLOAD, },
+  [B2055_PRG_GCHP22]		= { .ghz5 = 0x0072, .ghz2 = 0x0072, NOUPLOAD, },
+  [B2055_PRG_GCHP23]		= { .ghz5 = 0x0073, .ghz2 = 0x0073, NOUPLOAD, },
+  [B2055_PRG_GCHP24]		= { .ghz5 = 0x0074, .ghz2 = 0x0074, NOUPLOAD, },
+  [B2055_PRG_GCHP25]		= { .ghz5 = 0x0075, .ghz2 = 0x0075, NOUPLOAD, },
+  [B2055_PRG_GCHP26]		= { .ghz5 = 0x0076, .ghz2 = 0x0076, NOUPLOAD, },
+  [B2055_PRG_GCHP27]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+  [B2055_PRG_GCHP28]		= { .ghz5 = 0x0078, .ghz2 = 0x0078, NOUPLOAD, },
+  [B2055_PRG_GCHP29]		= { .ghz5 = 0x0079, .ghz2 = 0x0079, NOUPLOAD, },
+  [B2055_PRG_GCHP30]		= { .ghz5 = 0x007A, .ghz2 = 0x007A, NOUPLOAD, },
+  [0xC7]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xC8]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xC9]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xCA]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xCB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xCC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xCE]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xCF]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD0]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD1]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C1_B0NB_RSSIVCM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [0xD3]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD4]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD5]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_GENSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD7]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD8]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xDA]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xDB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xDC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xDD]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C2_B0NB_RSSIVCM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [0xDF]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xE0]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xE1]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_GENSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+#define RADIOREGS(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, \
+		  r12, r13, r14, r15, r16, r17, r18, r19, r20, r21) \
+	.radio_pll_ref		= r0,	\
+	.radio_rf_pllmod0	= r1,	\
+	.radio_rf_pllmod1	= r2,	\
+	.radio_vco_captail	= r3,	\
+	.radio_vco_cal1		= r4,	\
+	.radio_vco_cal2		= r5,	\
+	.radio_pll_lfc1		= r6,	\
+	.radio_pll_lfr1		= r7,	\
+	.radio_pll_lfc2		= r8,	\
+	.radio_lgbuf_cenbuf	= r9,	\
+	.radio_lgen_tune1	= r10,	\
+	.radio_lgen_tune2	= r11,	\
+	.radio_c1_lgbuf_atune	= r12,	\
+	.radio_c1_lgbuf_gtune	= r13,	\
+	.radio_c1_rx_rfr1	= r14,	\
+	.radio_c1_tx_pgapadtn	= r15,	\
+	.radio_c1_tx_mxbgtrim	= r16,	\
+	.radio_c2_lgbuf_atune	= r17,	\
+	.radio_c2_lgbuf_gtune	= r18,	\
+	.radio_c2_rx_rfr1	= r19,	\
+	.radio_c2_tx_pgapadtn	= r20,	\
+	.radio_c2_tx_mxbgtrim	= r21
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5)	\
+	.phy_regs.phy_bw1a	= r0,	\
+	.phy_regs.phy_bw2	= r1,	\
+	.phy_regs.phy_bw3	= r2,	\
+	.phy_regs.phy_bw4	= r3,	\
+	.phy_regs.phy_bw5	= r4,	\
+	.phy_regs.phy_bw6	= r5
+
+static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab_rev2[] = {
+  {	.channel		= 184,
+	.freq			= 4920, /* MHz */
+	.unk2			= 3280,
+	RADIOREGS(0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xB407, 0xB007, 0xAC07, 0x1402, 0x1502, 0x1602),
+  },
+  {	.channel		= 186,
+	.freq			= 4930, /* MHz */
+	.unk2			= 3287,
+	RADIOREGS(0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xB807, 0xB407, 0xB007, 0x1302, 0x1402, 0x1502),
+  },
+  {	.channel		= 188,
+	.freq			= 4940, /* MHz */
+	.unk2			= 3293,
+	RADIOREGS(0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xBC07, 0xB807, 0xB407, 0x1202, 0x1302, 0x1402),
+  },
+  {	.channel		= 190,
+	.freq			= 4950, /* MHz */
+	.unk2			= 3300,
+	RADIOREGS(0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xC007, 0xBC07, 0xB807, 0x1102, 0x1202, 0x1302),
+  },
+  {	.channel		= 192,
+	.freq			= 4960, /* MHz */
+	.unk2			= 3307,
+	RADIOREGS(0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xC407, 0xC007, 0xBC07, 0x0F02, 0x1102, 0x1202),
+  },
+  {	.channel		= 194,
+	.freq			= 4970, /* MHz */
+	.unk2			= 3313,
+	RADIOREGS(0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xC807, 0xC407, 0xC007, 0x0E02, 0x0F02, 0x1102),
+  },
+  {	.channel		= 196,
+	.freq			= 4980, /* MHz */
+	.unk2			= 3320,
+	RADIOREGS(0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xCC07, 0xC807, 0xC407, 0x0D02, 0x0E02, 0x0F02),
+  },
+  {	.channel		= 198,
+	.freq			= 4990, /* MHz */
+	.unk2			= 3327,
+	RADIOREGS(0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xD007, 0xCC07, 0xC807, 0x0C02, 0x0D02, 0x0E02),
+  },
+  {	.channel		= 200,
+	.freq			= 5000, /* MHz */
+	.unk2			= 3333,
+	RADIOREGS(0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xD407, 0xD007, 0xCC07, 0x0B02, 0x0C02, 0x0D02),
+  },
+  {	.channel		= 202,
+	.freq			= 5010, /* MHz */
+	.unk2			= 3340,
+	RADIOREGS(0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xD807, 0xD407, 0xD007, 0x0A02, 0x0B02, 0x0C02),
+  },
+  {	.channel		= 204,
+	.freq			= 5020, /* MHz */
+	.unk2			= 3347,
+	RADIOREGS(0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xDC07, 0xD807, 0xD407, 0x0902, 0x0A02, 0x0B02),
+  },
+  {	.channel		= 206,
+	.freq			= 5030, /* MHz */
+	.unk2			= 3353,
+	RADIOREGS(0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xE007, 0xDC07, 0xD807, 0x0802, 0x0902, 0x0A02),
+  },
+  {	.channel		= 208,
+	.freq			= 5040, /* MHz */
+	.unk2			= 3360,
+	RADIOREGS(0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xE407, 0xE007, 0xDC07, 0x0702, 0x0802, 0x0902),
+  },
+  {	.channel		= 210,
+	.freq			= 5050, /* MHz */
+	.unk2			= 3367,
+	RADIOREGS(0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0xE807, 0xE407, 0xE007, 0x0602, 0x0702, 0x0802),
+  },
+  {	.channel		= 212,
+	.freq			= 5060, /* MHz */
+	.unk2			= 3373,
+	RADIOREGS(0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
+		  0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
+	PHYREGS(0xEC07, 0xE807, 0xE407, 0x0502, 0x0602, 0x0702),
+  },
+  {	.channel		= 214,
+	.freq			= 5070, /* MHz */
+	.unk2			= 3380,
+	RADIOREGS(0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
+		  0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
+	PHYREGS(0xF007, 0xEC07, 0xE807, 0x0402, 0x0502, 0x0602),
+  },
+  {	.channel		= 216,
+	.freq			= 5080, /* MHz */
+	.unk2			= 3387,
+	RADIOREGS(0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
+		  0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
+	PHYREGS(0xF407, 0xF007, 0xEC07, 0x0302, 0x0402, 0x0502),
+  },
+  {	.channel		= 218,
+	.freq			= 5090, /* MHz */
+	.unk2			= 3393,
+	RADIOREGS(0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
+		  0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
+	PHYREGS(0xF807, 0xF407, 0xF007, 0x0202, 0x0302, 0x0402),
+  },
+  {	.channel		= 220,
+	.freq			= 5100, /* MHz */
+	.unk2			= 3400,
+	RADIOREGS(0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
+		  0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
+	PHYREGS(0xFC07, 0xF807, 0xF407, 0x0102, 0x0202, 0x0302),
+  },
+  {	.channel		= 222,
+	.freq			= 5110, /* MHz */
+	.unk2			= 3407,
+	RADIOREGS(0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
+		  0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
+	PHYREGS(0x0008, 0xFC07, 0xF807, 0x0002, 0x0102, 0x0202),
+  },
+  {	.channel		= 224,
+	.freq			= 5120, /* MHz */
+	.unk2			= 3413,
+	RADIOREGS(0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
+		  0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
+	PHYREGS(0x0408, 0x0008, 0xFC07, 0xFF01, 0x0002, 0x0102),
+  },
+  {	.channel		= 226,
+	.freq			= 5130, /* MHz */
+	.unk2			= 3420,
+	RADIOREGS(0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
+		  0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
+	PHYREGS(0x0808, 0x0408, 0x0008, 0xFE01, 0xFF01, 0x0002),
+  },
+  {	.channel		= 228,
+	.freq			= 5140, /* MHz */
+	.unk2			= 3427,
+	RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E,
+		  0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B),
+	PHYREGS(0x0C08, 0x0808, 0x0408, 0xFD01, 0xFE01, 0xFF01),
+  },
+  {	.channel		= 32,
+	.freq			= 5160, /* MHz */
+	.unk2			= 3440,
+	RADIOREGS(0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
+		  0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
+	PHYREGS(0x1408, 0x1008, 0x0C08, 0xFB01, 0xFC01, 0xFD01),
+  },
+  {	.channel		= 34,
+	.freq			= 5170, /* MHz */
+	.unk2			= 3447,
+	RADIOREGS(0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
+		  0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
+	PHYREGS(0x1808, 0x1408, 0x1008, 0xFA01, 0xFB01, 0xFC01),
+  },
+  {	.channel		= 36,
+	.freq			= 5180, /* MHz */
+	.unk2			= 3453,
+	RADIOREGS(0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
+		  0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
+	PHYREGS(0x1C08, 0x1808, 0x1408, 0xF901, 0xFA01, 0xFB01),
+  },
+  {	.channel		= 38,
+	.freq			= 5190, /* MHz */
+	.unk2			= 3460,
+	RADIOREGS(0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
+		  0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
+	PHYREGS(0x2008, 0x1C08, 0x1808, 0xF801, 0xF901, 0xFA01),
+  },
+  {	.channel		= 40,
+	.freq			= 5200, /* MHz */
+	.unk2			= 3467,
+	RADIOREGS(0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
+		  0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
+	PHYREGS(0x2408, 0x2008, 0x1C08, 0xF701, 0xF801, 0xF901),
+  },
+  {	.channel		= 42,
+	.freq			= 5210, /* MHz */
+	.unk2			= 3473,
+	RADIOREGS(0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
+		  0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
+	PHYREGS(0x2808, 0x2408, 0x2008, 0xF601, 0xF701, 0xF801),
+  },
+  {	.channel		= 44,
+	.freq			= 5220, /* MHz */
+	.unk2			= 3480,
+	RADIOREGS(0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+		  0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
+		  0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
+	PHYREGS(0x2C08, 0x2808, 0x2408, 0xF501, 0xF601, 0xF701),
+  },
+  {	.channel		= 46,
+	.freq			= 5230, /* MHz */
+	.unk2			= 3487,
+	RADIOREGS(0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+		  0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
+		  0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
+	PHYREGS(0x3008, 0x2C08, 0x2808, 0xF401, 0xF501, 0xF601),
+  },
+  {	.channel		= 48,
+	.freq			= 5240, /* MHz */
+	.unk2			= 3493,
+	RADIOREGS(0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+		  0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
+		  0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
+	PHYREGS(0x3408, 0x3008, 0x2C08, 0xF301, 0xF401, 0xF501),
+  },
+  {	.channel		= 50,
+	.freq			= 5250, /* MHz */
+	.unk2			= 3500,
+	RADIOREGS(0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+		  0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
+		  0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
+	PHYREGS(0x3808, 0x3408, 0x3008, 0xF201, 0xF301, 0xF401),
+  },
+  {	.channel		= 52,
+	.freq			= 5260, /* MHz */
+	.unk2			= 3507,
+	RADIOREGS(0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+		  0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
+		  0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
+	PHYREGS(0x3C08, 0x3808, 0x3408, 0xF101, 0xF201, 0xF301),
+  },
+  {	.channel		= 54,
+	.freq			= 5270, /* MHz */
+	.unk2			= 3513,
+	RADIOREGS(0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+		  0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
+		  0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
+	PHYREGS(0x4008, 0x3C08, 0x3808, 0xF001, 0xF101, 0xF201),
+  },
+  {	.channel		= 56,
+	.freq			= 5280, /* MHz */
+	.unk2			= 3520,
+	RADIOREGS(0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
+		  0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
+		  0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
+	PHYREGS(0x4408, 0x4008, 0x3C08, 0xF001, 0xF001, 0xF101),
+  },
+  {	.channel		= 58,
+	.freq			= 5290, /* MHz */
+	.unk2			= 3527,
+	RADIOREGS(0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
+		  0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
+		  0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
+	PHYREGS(0x4808, 0x4408, 0x4008, 0xEF01, 0xF001, 0xF001),
+  },
+  {	.channel		= 60,
+	.freq			= 5300, /* MHz */
+	.unk2			= 3533,
+	RADIOREGS(0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+		  0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
+		  0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
+	PHYREGS(0x4C08, 0x4808, 0x4408, 0xEE01, 0xEF01, 0xF001),
+  },
+  {	.channel		= 62,
+	.freq			= 5310, /* MHz */
+	.unk2			= 3540,
+	RADIOREGS(0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+		  0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
+		  0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
+	PHYREGS(0x5008, 0x4C08, 0x4808, 0xED01, 0xEE01, 0xEF01),
+  },
+  {	.channel		= 64,
+	.freq			= 5320, /* MHz */
+	.unk2			= 3547,
+	RADIOREGS(0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
+		  0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
+		  0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
+	PHYREGS(0x5408, 0x5008, 0x4C08, 0xEC01, 0xED01, 0xEE01),
+  },
+  {	.channel		= 66,
+	.freq			= 5330, /* MHz */
+	.unk2			= 3553,
+	RADIOREGS(0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
+		  0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
+		  0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
+	PHYREGS(0x5808, 0x5408, 0x5008, 0xEB01, 0xEC01, 0xED01),
+  },
+  {	.channel		= 68,
+	.freq			= 5340, /* MHz */
+	.unk2			= 3560,
+	RADIOREGS(0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+		  0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
+		  0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
+	PHYREGS(0x5C08, 0x5808, 0x5408, 0xEA01, 0xEB01, 0xEC01),
+  },
+  {	.channel		= 70,
+	.freq			= 5350, /* MHz */
+	.unk2			= 3567,
+	RADIOREGS(0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+		  0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
+		  0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
+	PHYREGS(0x6008, 0x5C08, 0x5808, 0xE901, 0xEA01, 0xEB01),
+  },
+  {	.channel		= 72,
+	.freq			= 5360, /* MHz */
+	.unk2			= 3573,
+	RADIOREGS(0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
+		  0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
+		  0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
+	PHYREGS(0x6408, 0x6008, 0x5C08, 0xE801, 0xE901, 0xEA01),
+  },
+  {	.channel		= 74,
+	.freq			= 5370, /* MHz */
+	.unk2			= 3580,
+	RADIOREGS(0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
+		  0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
+		  0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
+	PHYREGS(0x6808, 0x6408, 0x6008, 0xE701, 0xE801, 0xE901),
+  },
+  {	.channel		= 76,
+	.freq			= 5380, /* MHz */
+	.unk2			= 3587,
+	RADIOREGS(0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+		  0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
+		  0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
+	PHYREGS(0x6C08, 0x6808, 0x6408, 0xE601, 0xE701, 0xE801),
+  },
+  {	.channel		= 78,
+	.freq			= 5390, /* MHz */
+	.unk2			= 3593,
+	RADIOREGS(0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+		  0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
+		  0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
+	PHYREGS(0x7008, 0x6C08, 0x6808, 0xE501, 0xE601, 0xE701),
+  },
+  {	.channel		= 80,
+	.freq			= 5400, /* MHz */
+	.unk2			= 3600,
+	RADIOREGS(0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
+		  0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
+		  0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
+	PHYREGS(0x7408, 0x7008, 0x6C08, 0xE501, 0xE501, 0xE601),
+  },
+  {	.channel		= 82,
+	.freq			= 5410, /* MHz */
+	.unk2			= 3607,
+	RADIOREGS(0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
+		  0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
+		  0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
+	PHYREGS(0x7808, 0x7408, 0x7008, 0xE401, 0xE501, 0xE501),
+  },
+  {	.channel		= 84,
+	.freq			= 5420, /* MHz */
+	.unk2			= 3613,
+	RADIOREGS(0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
+		  0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
+		  0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
+	PHYREGS(0x7C08, 0x7808, 0x7408, 0xE301, 0xE401, 0xE501),
+  },
+  {	.channel		= 86,
+	.freq			= 5430, /* MHz */
+	.unk2			= 3620,
+	RADIOREGS(0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
+		  0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
+		  0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
+	PHYREGS(0x8008, 0x7C08, 0x7808, 0xE201, 0xE301, 0xE401),
+  },
+  {	.channel		= 88,
+	.freq			= 5440, /* MHz */
+	.unk2			= 3627,
+	RADIOREGS(0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+		  0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
+		  0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
+	PHYREGS(0x8408, 0x8008, 0x7C08, 0xE101, 0xE201, 0xE301),
+  },
+  {	.channel		= 90,
+	.freq			= 5450, /* MHz */
+	.unk2			= 3633,
+	RADIOREGS(0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+		  0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
+		  0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
+	PHYREGS(0x8808, 0x8408, 0x8008, 0xE001, 0xE101, 0xE201),
+  },
+  {	.channel		= 92,
+	.freq			= 5460, /* MHz */
+	.unk2			= 3640,
+	RADIOREGS(0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
+		  0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
+		  0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
+	PHYREGS(0x8C08, 0x8808, 0x8408, 0xDF01, 0xE001, 0xE101),
+  },
+  {	.channel		= 94,
+	.freq			= 5470, /* MHz */
+	.unk2			= 3647,
+	RADIOREGS(0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
+		  0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
+		  0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
+	PHYREGS(0x9008, 0x8C08, 0x8808, 0xDE01, 0xDF01, 0xE001),
+  },
+  {	.channel		= 96,
+	.freq			= 5480, /* MHz */
+	.unk2			= 3653,
+	RADIOREGS(0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+		  0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
+		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+	PHYREGS(0x9408, 0x9008, 0x8C08, 0xDD01, 0xDE01, 0xDF01),
+  },
+  {	.channel		= 98,
+	.freq			= 5490, /* MHz */
+	.unk2			= 3660,
+	RADIOREGS(0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+		  0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
+		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+	PHYREGS(0x9808, 0x9408, 0x9008, 0xDD01, 0xDD01, 0xDE01),
+  },
+  {	.channel		= 100,
+	.freq			= 5500, /* MHz */
+	.unk2			= 3667,
+	RADIOREGS(0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
+		  0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
+		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+	PHYREGS(0x9C08, 0x9808, 0x9408, 0xDC01, 0xDD01, 0xDD01),
+  },
+  {	.channel		= 102,
+	.freq			= 5510, /* MHz */
+	.unk2			= 3673,
+	RADIOREGS(0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
+		  0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
+		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+	PHYREGS(0xA008, 0x9C08, 0x9808, 0xDB01, 0xDC01, 0xDD01),
+  },
+  {	.channel		= 104,
+	.freq			= 5520, /* MHz */
+	.unk2			= 3680,
+	RADIOREGS(0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
+		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+	PHYREGS(0xA408, 0xA008, 0x9C08, 0xDA01, 0xDB01, 0xDC01),
+  },
+  {	.channel		= 106,
+	.freq			= 5530, /* MHz */
+	.unk2			= 3687,
+	RADIOREGS(0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
+		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+	PHYREGS(0xA808, 0xA408, 0xA008, 0xD901, 0xDA01, 0xDB01),
+  },
+  {	.channel		= 108,
+	.freq			= 5540, /* MHz */
+	.unk2			= 3693,
+	RADIOREGS(0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+	PHYREGS(0xAC08, 0xA808, 0xA408, 0xD801, 0xD901, 0xDA01),
+  },
+  {	.channel		= 110,
+	.freq			= 5550, /* MHz */
+	.unk2			= 3700,
+	RADIOREGS(0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+	PHYREGS(0xB008, 0xAC08, 0xA808, 0xD701, 0xD801, 0xD901),
+  },
+  {	.channel		= 112,
+	.freq			= 5560, /* MHz */
+	.unk2			= 3707,
+	RADIOREGS(0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
+		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0xB408, 0xB008, 0xAC08, 0xD701, 0xD701, 0xD801),
+  },
+  {	.channel		= 114,
+	.freq			= 5570, /* MHz */
+	.unk2			= 3713,
+	RADIOREGS(0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
+		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0xB808, 0xB408, 0xB008, 0xD601, 0xD701, 0xD701),
+  },
+  {	.channel		= 116,
+	.freq			= 5580, /* MHz */
+	.unk2			= 3720,
+	RADIOREGS(0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0xBC08, 0xB808, 0xB408, 0xD501, 0xD601, 0xD701),
+  },
+  {	.channel		= 118,
+	.freq			= 5590, /* MHz */
+	.unk2			= 3727,
+	RADIOREGS(0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0xC008, 0xBC08, 0xB808, 0xD401, 0xD501, 0xD601),
+  },
+  {	.channel		= 120,
+	.freq			= 5600, /* MHz */
+	.unk2			= 3733,
+	RADIOREGS(0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
+		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
+		  0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0xC408, 0xC008, 0xBC08, 0xD301, 0xD401, 0xD501),
+  },
+  {	.channel		= 122,
+	.freq			= 5610, /* MHz */
+	.unk2			= 3740,
+	RADIOREGS(0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
+		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
+		  0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0xC808, 0xC408, 0xC008, 0xD201, 0xD301, 0xD401),
+  },
+  {	.channel		= 124,
+	.freq			= 5620, /* MHz */
+	.unk2			= 3747,
+	RADIOREGS(0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
+		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+		  0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xCC08, 0xC808, 0xC408, 0xD201, 0xD201, 0xD301),
+  },
+  {	.channel		= 126,
+	.freq			= 5630, /* MHz */
+	.unk2			= 3753,
+	RADIOREGS(0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
+		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+		  0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xD008, 0xCC08, 0xC808, 0xD101, 0xD201, 0xD201),
+  },
+  {	.channel		= 128,
+	.freq			= 5640, /* MHz */
+	.unk2			= 3760,
+	RADIOREGS(0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xD408, 0xD008, 0xCC08, 0xD001, 0xD101, 0xD201),
+  },
+  {	.channel		= 130,
+	.freq			= 5650, /* MHz */
+	.unk2			= 3767,
+	RADIOREGS(0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xD808, 0xD408, 0xD008, 0xCF01, 0xD001, 0xD101),
+  },
+  {	.channel		= 132,
+	.freq			= 5660, /* MHz */
+	.unk2			= 3773,
+	RADIOREGS(0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xDC08, 0xD808, 0xD408, 0xCE01, 0xCF01, 0xD001),
+  },
+  {	.channel		= 134,
+	.freq			= 5670, /* MHz */
+	.unk2			= 3780,
+	RADIOREGS(0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xE008, 0xDC08, 0xD808, 0xCE01, 0xCE01, 0xCF01),
+  },
+  {	.channel		= 136,
+	.freq			= 5680, /* MHz */
+	.unk2			= 3787,
+	RADIOREGS(0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xE408, 0xE008, 0xDC08, 0xCD01, 0xCE01, 0xCE01),
+  },
+  {	.channel		= 138,
+	.freq			= 5690, /* MHz */
+	.unk2			= 3793,
+	RADIOREGS(0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xE808, 0xE408, 0xE008, 0xCC01, 0xCD01, 0xCE01),
+  },
+  {	.channel		= 140,
+	.freq			= 5700, /* MHz */
+	.unk2			= 3800,
+	RADIOREGS(0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xEC08, 0xE808, 0xE408, 0xCB01, 0xCC01, 0xCD01),
+  },
+  {	.channel		= 142,
+	.freq			= 5710, /* MHz */
+	.unk2			= 3807,
+	RADIOREGS(0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xF008, 0xEC08, 0xE808, 0xCA01, 0xCB01, 0xCC01),
+  },
+  {	.channel		= 144,
+	.freq			= 5720, /* MHz */
+	.unk2			= 3813,
+	RADIOREGS(0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xF408, 0xF008, 0xEC08, 0xC901, 0xCA01, 0xCB01),
+  },
+  {	.channel		= 145,
+	.freq			= 5725, /* MHz */
+	.unk2			= 3817,
+	RADIOREGS(0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xF608, 0xF208, 0xEE08, 0xC901, 0xCA01, 0xCB01),
+  },
+  {	.channel		= 146,
+	.freq			= 5730, /* MHz */
+	.unk2			= 3820,
+	RADIOREGS(0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xF808, 0xF408, 0xF008, 0xC901, 0xC901, 0xCA01),
+  },
+  {	.channel		= 147,
+	.freq			= 5735, /* MHz */
+	.unk2			= 3823,
+	RADIOREGS(0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xFA08, 0xF608, 0xF208, 0xC801, 0xC901, 0xCA01),
+  },
+  {	.channel		= 148,
+	.freq			= 5740, /* MHz */
+	.unk2			= 3827,
+	RADIOREGS(0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xFC08, 0xF808, 0xF408, 0xC801, 0xC901, 0xC901),
+  },
+  {	.channel		= 149,
+	.freq			= 5745, /* MHz */
+	.unk2			= 3830,
+	RADIOREGS(0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0xFE08, 0xFA08, 0xF608, 0xC801, 0xC801, 0xC901),
+  },
+  {	.channel		= 150,
+	.freq			= 5750, /* MHz */
+	.unk2			= 3833,
+	RADIOREGS(0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0009, 0xFC08, 0xF808, 0xC701, 0xC801, 0xC901),
+  },
+  {	.channel		= 151,
+	.freq			= 5755, /* MHz */
+	.unk2			= 3837,
+	RADIOREGS(0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0209, 0xFE08, 0xFA08, 0xC701, 0xC801, 0xC801),
+  },
+  {	.channel		= 152,
+	.freq			= 5760, /* MHz */
+	.unk2			= 3840,
+	RADIOREGS(0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0409, 0x0009, 0xFC08, 0xC601, 0xC701, 0xC801),
+  },
+  {	.channel		= 153,
+	.freq			= 5765, /* MHz */
+	.unk2			= 3843,
+	RADIOREGS(0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0609, 0x0209, 0xFE08, 0xC601, 0xC701, 0xC801),
+  },
+  {	.channel		= 154,
+	.freq			= 5770, /* MHz */
+	.unk2			= 3847,
+	RADIOREGS(0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0809, 0x0409, 0x0009, 0xC601, 0xC601, 0xC701),
+  },
+  {	.channel		= 155,
+	.freq			= 5775, /* MHz */
+	.unk2			= 3850,
+	RADIOREGS(0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0A09, 0x0609, 0x0209, 0xC501, 0xC601, 0xC701),
+  },
+  {	.channel		= 156,
+	.freq			= 5780, /* MHz */
+	.unk2			= 3853,
+	RADIOREGS(0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0C09, 0x0809, 0x0409, 0xC501, 0xC601, 0xC601),
+  },
+  {	.channel		= 157,
+	.freq			= 5785, /* MHz */
+	.unk2			= 3857,
+	RADIOREGS(0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0E09, 0x0A09, 0x0609, 0xC401, 0xC501, 0xC601),
+  },
+  {	.channel		= 158,
+	.freq			= 5790, /* MHz */
+	.unk2			= 3860,
+	RADIOREGS(0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x1009, 0x0C09, 0x0809, 0xC401, 0xC501, 0xC601),
+  },
+  {	.channel		= 159,
+	.freq			= 5795, /* MHz */
+	.unk2			= 3863,
+	RADIOREGS(0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x1209, 0x0E09, 0x0A09, 0xC401, 0xC401, 0xC501),
+  },
+  {	.channel		= 160,
+	.freq			= 5800, /* MHz */
+	.unk2			= 3867,
+	RADIOREGS(0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x1409, 0x1009, 0x0C09, 0xC301, 0xC401, 0xC501),
+  },
+  {	.channel		= 161,
+	.freq			= 5805, /* MHz */
+	.unk2			= 3870,
+	RADIOREGS(0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x1609, 0x1209, 0x0E09, 0xC301, 0xC401, 0xC401),
+  },
+  {	.channel		= 162,
+	.freq			= 5810, /* MHz */
+	.unk2			= 3873,
+	RADIOREGS(0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x1809, 0x1409, 0x1009, 0xC201, 0xC301, 0xC401),
+  },
+  {	.channel		= 163,
+	.freq			= 5815, /* MHz */
+	.unk2			= 3877,
+	RADIOREGS(0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x1A09, 0x1609, 0x1209, 0xC201, 0xC301, 0xC401),
+  },
+  {	.channel		= 164,
+	.freq			= 5820, /* MHz */
+	.unk2			= 3880,
+	RADIOREGS(0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x1C09, 0x1809, 0x1409, 0xC201, 0xC201, 0xC301),
+  },
+  {	.channel		= 165,
+	.freq			= 5825, /* MHz */
+	.unk2			= 3883,
+	RADIOREGS(0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x1E09, 0x1A09, 0x1609, 0xC101, 0xC201, 0xC301),
+  },
+  {	.channel		= 166,
+	.freq			= 5830, /* MHz */
+	.unk2			= 3887,
+	RADIOREGS(0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x2009, 0x1C09, 0x1809, 0xC101, 0xC201, 0xC201),
+  },
+  {	.channel		= 168,
+	.freq			= 5840, /* MHz */
+	.unk2			= 3893,
+	RADIOREGS(0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x2409, 0x2009, 0x1C09, 0xC001, 0xC101, 0xC201),
+  },
+  {	.channel		= 170,
+	.freq			= 5850, /* MHz */
+	.unk2			= 3900,
+	RADIOREGS(0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x2809, 0x2409, 0x2009, 0xBF01, 0xC001, 0xC101),
+  },
+  {	.channel		= 172,
+	.freq			= 5860, /* MHz */
+	.unk2			= 3907,
+	RADIOREGS(0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x2C09, 0x2809, 0x2409, 0xBF01, 0xBF01, 0xC001),
+  },
+  {	.channel		= 174,
+	.freq			= 5870, /* MHz */
+	.unk2			= 3913,
+	RADIOREGS(0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x3009, 0x2C09, 0x2809, 0xBE01, 0xBF01, 0xBF01),
+  },
+  {	.channel		= 176,
+	.freq			= 5880, /* MHz */
+	.unk2			= 3920,
+	RADIOREGS(0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x3409, 0x3009, 0x2C09, 0xBD01, 0xBE01, 0xBF01),
+  },
+  {	.channel		= 178,
+	.freq			= 5890, /* MHz */
+	.unk2			= 3927,
+	RADIOREGS(0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x3809, 0x3409, 0x3009, 0xBC01, 0xBD01, 0xBE01),
+  },
+  {	.channel		= 180,
+	.freq			= 5900, /* MHz */
+	.unk2			= 3933,
+	RADIOREGS(0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x3C09, 0x3809, 0x3409, 0xBC01, 0xBC01, 0xBD01),
+  },
+  {	.channel		= 182,
+	.freq			= 5910, /* MHz */
+	.unk2			= 3940,
+	RADIOREGS(0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x4009, 0x3C09, 0x3809, 0xBB01, 0xBC01, 0xBC01),
+  },
+  {	.channel		= 1,
+	.freq			= 2412, /* MHz */
+	.unk2			= 3216,
+	RADIOREGS(0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C,
+		  0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80),
+	PHYREGS(0xC903, 0xC503, 0xC103, 0x3A04, 0x3F04, 0x4304),
+  },
+  {	.channel		= 2,
+	.freq			= 2417, /* MHz */
+	.unk2			= 3223,
+	RADIOREGS(0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B,
+		  0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80),
+	PHYREGS(0xCB03, 0xC703, 0xC303, 0x3804, 0x3D04, 0x4104),
+  },
+  {	.channel		= 3,
+	.freq			= 2422, /* MHz */
+	.unk2			= 3229,
+	RADIOREGS(0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
+		  0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
+	PHYREGS(0xCD03, 0xC903, 0xC503, 0x3604, 0x3A04, 0x3F04),
+  },
+  {	.channel		= 4,
+	.freq			= 2427, /* MHz */
+	.unk2			= 3236,
+	RADIOREGS(0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
+		  0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
+	PHYREGS(0xCF03, 0xCB03, 0xC703, 0x3404, 0x3804, 0x3D04),
+  },
+  {	.channel		= 5,
+	.freq			= 2432, /* MHz */
+	.unk2			= 3243,
+	RADIOREGS(0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09,
+		  0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80),
+	PHYREGS(0xD103, 0xCD03, 0xC903, 0x3104, 0x3604, 0x3A04),
+  },
+  {	.channel		= 6,
+	.freq			= 2437, /* MHz */
+	.unk2			= 3249,
+	RADIOREGS(0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08,
+		  0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80),
+	PHYREGS(0xD303, 0xCF03, 0xCB03, 0x2F04, 0x3404, 0x3804),
+  },
+  {	.channel		= 7,
+	.freq			= 2442, /* MHz */
+	.unk2			= 3256,
+	RADIOREGS(0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07,
+		  0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80),
+	PHYREGS(0xD503, 0xD103, 0xCD03, 0x2D04, 0x3104, 0x3604),
+  },
+  {	.channel		= 8,
+	.freq			= 2447, /* MHz */
+	.unk2			= 3263,
+	RADIOREGS(0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06,
+		  0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80),
+	PHYREGS(0xD703, 0xD303, 0xCF03, 0x2B04, 0x2F04, 0x3404),
+  },
+  {	.channel		= 9,
+	.freq			= 2452, /* MHz */
+	.unk2			= 3269,
+	RADIOREGS(0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06,
+		  0x80, 0xFF, 0x88, 0x09, 0x06, 0x80),
+	PHYREGS(0xD903, 0xD503, 0xD103, 0x2904, 0x2D04, 0x3104),
+  },
+  {	.channel		= 10,
+	.freq			= 2457, /* MHz */
+	.unk2			= 3276,
+	RADIOREGS(0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05,
+		  0x80, 0xFF, 0x88, 0x08, 0x05, 0x80),
+	PHYREGS(0xDB03, 0xD703, 0xD303, 0x2704, 0x2B04, 0x2F04),
+  },
+  {	.channel		= 11,
+	.freq			= 2462, /* MHz */
+	.unk2			= 3283,
+	RADIOREGS(0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04,
+		  0x80, 0xFF, 0x88, 0x08, 0x04, 0x80),
+	PHYREGS(0xDD03, 0xD903, 0xD503, 0x2404, 0x2904, 0x2D04),
+  },
+  {	.channel		= 12,
+	.freq			= 2467, /* MHz */
+	.unk2			= 3289,
+	RADIOREGS(0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03,
+		  0x80, 0xFF, 0x88, 0x08, 0x03, 0x80),
+	PHYREGS(0xDF03, 0xDB03, 0xD703, 0x2204, 0x2704, 0x2B04),
+  },
+  {	.channel		= 13,
+	.freq			= 2472, /* MHz */
+	.unk2			= 3296,
+	RADIOREGS(0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03,
+		  0x80, 0xFF, 0x88, 0x07, 0x03, 0x80),
+	PHYREGS(0xE103, 0xDD03, 0xD903, 0x2004, 0x2404, 0x2904),
+  },
+  {	.channel		= 14,
+	.freq			= 2484, /* MHz */
+	.unk2			= 3312,
+	RADIOREGS(0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01,
+		  0x80, 0xFF, 0x88, 0x07, 0x01, 0x80),
+	PHYREGS(0xE603, 0xE203, 0xDE03, 0x1B04, 0x1F04, 0x2404),
+  },
+};
+
+void b2055_upload_inittab(struct b43_wldev *dev,
+			  bool ghz5, bool ignore_uploadflag)
+{
+	const struct b2055_inittab_entry *e;
+	unsigned int i;
+	u16 value;
+
+	for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) {
+		e = &(b2055_inittab[i]);
+		if (!(e->flags & B2055_INITTAB_ENTRY_OK))
+			continue;
+		if ((e->flags & B2055_INITTAB_UPLOAD) || ignore_uploadflag) {
+			if (ghz5)
+				value = e->ghz5;
+			else
+				value = e->ghz2;
+			b43_radio_write16(dev, i, value);
+		}
+	}
+}
+
+const struct b43_nphy_channeltab_entry_rev2 *
+b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel)
+{
+	const struct b43_nphy_channeltab_entry_rev2 *e;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev2); i++) {
+		e = &(b43_nphy_channeltab_rev2[i]);
+		if (e->channel == channel)
+			return e;
+	}
+
+	return NULL;
+}
diff --git a/drivers/net/wireless/b43/radio_2055.h b/drivers/net/wireless/b43/radio_2055.h
new file mode 100644
index 0000000..d9bfa0f
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2055.h
@@ -0,0 +1,254 @@
+#ifndef B43_RADIO_2055_H_
+#define B43_RADIO_2055_H_
+
+#include <linux/types.h>
+
+#include "tables_nphy.h"
+
+#define B2055_GEN_SPARE			0x00 /* GEN spare */
+#define B2055_SP_PINPD			0x02 /* SP PIN PD */
+#define B2055_C1_SP_RSSI		0x03 /* SP RSSI Core 1 */
+#define B2055_C1_SP_PDMISC		0x04 /* SP PD MISC Core 1 */
+#define B2055_C2_SP_RSSI		0x05 /* SP RSSI Core 2 */
+#define B2055_C2_SP_PDMISC		0x06 /* SP PD MISC Core 2 */
+#define B2055_C1_SP_RXGC1		0x07 /* SP RX GC1 Core 1 */
+#define B2055_C1_SP_RXGC2		0x08 /* SP RX GC2 Core 1 */
+#define B2055_C2_SP_RXGC1		0x09 /* SP RX GC1 Core 2 */
+#define B2055_C2_SP_RXGC2		0x0A /* SP RX GC2 Core 2 */
+#define B2055_C1_SP_LPFBWSEL		0x0B /* SP LPF BW select Core 1 */
+#define B2055_C2_SP_LPFBWSEL		0x0C /* SP LPF BW select Core 2 */
+#define B2055_C1_SP_TXGC1		0x0D /* SP TX GC1 Core 1 */
+#define B2055_C1_SP_TXGC2		0x0E /* SP TX GC2 Core 1 */
+#define B2055_C2_SP_TXGC1		0x0F /* SP TX GC1 Core 2 */
+#define B2055_C2_SP_TXGC2		0x10 /* SP TX GC2 Core 2 */
+#define B2055_MASTER1			0x11 /* Master control 1 */
+#define B2055_MASTER2			0x12 /* Master control 2 */
+#define B2055_PD_LGEN			0x13 /* PD LGEN */
+#define B2055_PD_PLLTS			0x14 /* PD PLL TS */
+#define B2055_C1_PD_LGBUF		0x15 /* PD Core 1 LGBUF */
+#define B2055_C1_PD_TX			0x16 /* PD Core 1 TX */
+#define B2055_C1_PD_RXTX		0x17 /* PD Core 1 RXTX */
+#define B2055_C1_PD_RSSIMISC		0x18 /* PD Core 1 RSSI MISC */
+#define B2055_C2_PD_LGBUF		0x19 /* PD Core 2 LGBUF */
+#define B2055_C2_PD_TX			0x1A /* PD Core 2 TX */
+#define B2055_C2_PD_RXTX		0x1B /* PD Core 2 RXTX */
+#define B2055_C2_PD_RSSIMISC		0x1C /* PD Core 2 RSSI MISC */
+#define B2055_PWRDET_LGEN		0x1D /* PWRDET LGEN */
+#define B2055_C1_PWRDET_LGBUF		0x1E /* PWRDET LGBUF Core 1 */
+#define B2055_C1_PWRDET_RXTX		0x1F /* PWRDET RXTX Core 1 */
+#define B2055_C2_PWRDET_LGBUF		0x20 /* PWRDET LGBUF Core 2 */
+#define B2055_C2_PWRDET_RXTX		0x21 /* PWRDET RXTX Core 2 */
+#define B2055_RRCCAL_CS			0x22 /* RRCCAL Control spare */
+#define B2055_RRCCAL_NOPTSEL		0x23 /* RRCCAL N OPT SEL */
+#define B2055_CAL_MISC			0x24 /* CAL MISC */
+#define B2055_CAL_COUT			0x25 /* CAL Counter out */
+#define B2055_CAL_COUT2			0x26 /* CAL Counter out 2 */
+#define B2055_CAL_CVARCTL		0x27 /* CAL CVAR Control */
+#define B2055_CAL_RVARCTL		0x28 /* CAL RVAR Control */
+#define B2055_CAL_LPOCTL		0x29 /* CAL LPO Control */
+#define B2055_CAL_TS			0x2A /* CAL TS */
+#define B2055_CAL_RCCALRTS		0x2B /* CAL RCCAL READ TS */
+#define B2055_CAL_RCALRTS		0x2C /* CAL RCAL READ TS */
+#define B2055_PADDRV			0x2D /* PAD driver */
+#define B2055_XOCTL1			0x2E /* XO Control 1 */
+#define B2055_XOCTL2			0x2F /* XO Control 2 */
+#define B2055_XOREGUL			0x30 /* XO Regulator */
+#define B2055_XOMISC			0x31 /* XO misc */
+#define B2055_PLL_LFC1			0x32 /* PLL LF C1 */
+#define B2055_PLL_CALVTH		0x33 /* PLL CAL VTH */
+#define B2055_PLL_LFC2			0x34 /* PLL LF C2 */
+#define B2055_PLL_REF			0x35 /* PLL reference */
+#define B2055_PLL_LFR1			0x36 /* PLL LF R1 */
+#define B2055_PLL_PFDCP			0x37 /* PLL PFD CP */
+#define B2055_PLL_IDAC_CPOPAMP		0x38 /* PLL IDAC CPOPAMP */
+#define B2055_PLL_CPREG			0x39 /* PLL CP Regulator */
+#define B2055_PLL_RCAL			0x3A /* PLL RCAL */
+#define B2055_RF_PLLMOD0		0x3B /* RF PLL MOD0 */
+#define B2055_RF_PLLMOD1		0x3C /* RF PLL MOD1 */
+#define B2055_RF_MMDIDAC1		0x3D /* RF MMD IDAC 1 */
+#define B2055_RF_MMDIDAC0		0x3E /* RF MMD IDAC 0 */
+#define B2055_RF_MMDSP			0x3F /* RF MMD spare */
+#define B2055_VCO_CAL1			0x40 /* VCO cal 1 */
+#define B2055_VCO_CAL2			0x41 /* VCO cal 2 */
+#define B2055_VCO_CAL3			0x42 /* VCO cal 3 */
+#define B2055_VCO_CAL4			0x43 /* VCO cal 4 */
+#define B2055_VCO_CAL5			0x44 /* VCO cal 5 */
+#define B2055_VCO_CAL6			0x45 /* VCO cal 6 */
+#define B2055_VCO_CAL7			0x46 /* VCO cal 7 */
+#define B2055_VCO_CAL8			0x47 /* VCO cal 8 */
+#define B2055_VCO_CAL9			0x48 /* VCO cal 9 */
+#define B2055_VCO_CAL10			0x49 /* VCO cal 10 */
+#define B2055_VCO_CAL11			0x4A /* VCO cal 11 */
+#define B2055_VCO_CAL12			0x4B /* VCO cal 12 */
+#define B2055_VCO_CAL13			0x4C /* VCO cal 13 */
+#define B2055_VCO_CAL14			0x4D /* VCO cal 14 */
+#define B2055_VCO_CAL15			0x4E /* VCO cal 15 */
+#define B2055_VCO_CAL16			0x4F /* VCO cal 16 */
+#define B2055_VCO_KVCO			0x50 /* VCO KVCO */
+#define B2055_VCO_CAPTAIL		0x51 /* VCO CAP TAIL */
+#define B2055_VCO_IDACVCO		0x52 /* VCO IDAC VCO */
+#define B2055_VCO_REG			0x53 /* VCO Regulator */
+#define B2055_PLL_RFVTH			0x54 /* PLL RF VTH */
+#define B2055_LGBUF_CENBUF		0x55 /* LGBUF CEN BUF */
+#define B2055_LGEN_TUNE1		0x56 /* LGEN tune 1 */
+#define B2055_LGEN_TUNE2		0x57 /* LGEN tune 2 */
+#define B2055_LGEN_IDAC1		0x58 /* LGEN IDAC 1 */
+#define B2055_LGEN_IDAC2		0x59 /* LGEN IDAC 2 */
+#define B2055_LGEN_BIASC		0x5A /* LGEN BIAS counter */
+#define B2055_LGEN_BIASIDAC		0x5B /* LGEN BIAS IDAC */
+#define B2055_LGEN_RCAL			0x5C /* LGEN RCAL */
+#define B2055_LGEN_DIV			0x5D /* LGEN div */
+#define B2055_LGEN_SPARE2		0x5E /* LGEN spare 2 */
+#define B2055_C1_LGBUF_ATUNE		0x5F /* Core 1 LGBUF A tune */
+#define B2055_C1_LGBUF_GTUNE		0x60 /* Core 1 LGBUF G tune */
+#define B2055_C1_LGBUF_DIV		0x61 /* Core 1 LGBUF div */
+#define B2055_C1_LGBUF_AIDAC		0x62 /* Core 1 LGBUF A IDAC */
+#define B2055_C1_LGBUF_GIDAC		0x63 /* Core 1 LGBUF G IDAC */
+#define B2055_C1_LGBUF_IDACFO		0x64 /* Core 1 LGBUF IDAC filter override */
+#define B2055_C1_LGBUF_SPARE		0x65 /* Core 1 LGBUF spare */
+#define B2055_C1_RX_RFSPC1		0x66 /* Core 1 RX RF SPC1 */
+#define B2055_C1_RX_RFR1		0x67 /* Core 1 RX RF reg 1 */
+#define B2055_C1_RX_RFR2		0x68 /* Core 1 RX RF reg 2 */
+#define B2055_C1_RX_RFRCAL		0x69 /* Core 1 RX RF RCAL */
+#define B2055_C1_RX_BB_BLCMP		0x6A /* Core 1 RX Baseband BUFI LPF CMP */
+#define B2055_C1_RX_BB_LPF		0x6B /* Core 1 RX Baseband LPF */
+#define B2055_C1_RX_BB_MIDACHP		0x6C /* Core 1 RX Baseband MIDAC High-pass */
+#define B2055_C1_RX_BB_VGA1IDAC		0x6D /* Core 1 RX Baseband VGA1 IDAC */
+#define B2055_C1_RX_BB_VGA2IDAC		0x6E /* Core 1 RX Baseband VGA2 IDAC */
+#define B2055_C1_RX_BB_VGA3IDAC		0x6F /* Core 1 RX Baseband VGA3 IDAC */
+#define B2055_C1_RX_BB_BUFOCTL		0x70 /* Core 1 RX Baseband BUFO Control */
+#define B2055_C1_RX_BB_RCCALCTL		0x71 /* Core 1 RX Baseband RCCAL Control */
+#define B2055_C1_RX_BB_RSSICTL1		0x72 /* Core 1 RX Baseband RSSI Control 1 */
+#define B2055_C1_RX_BB_RSSICTL2		0x73 /* Core 1 RX Baseband RSSI Control 2 */
+#define B2055_C1_RX_BB_RSSICTL3		0x74 /* Core 1 RX Baseband RSSI Control 3 */
+#define B2055_C1_RX_BB_RSSICTL4		0x75 /* Core 1 RX Baseband RSSI Control 4 */
+#define B2055_C1_RX_BB_RSSICTL5		0x76 /* Core 1 RX Baseband RSSI Control 5 */
+#define B2055_C1_RX_BB_REG		0x77 /* Core 1 RX Baseband Regulator */
+#define B2055_C1_RX_BB_SPARE1		0x78 /* Core 1 RX Baseband spare 1 */
+#define B2055_C1_RX_TXBBRCAL		0x79 /* Core 1 RX TX BB RCAL */
+#define B2055_C1_TX_RF_SPGA		0x7A /* Core 1 TX RF SGM PGA */
+#define B2055_C1_TX_RF_SPAD		0x7B /* Core 1 TX RF SGM PAD */
+#define B2055_C1_TX_RF_CNTPGA1		0x7C /* Core 1 TX RF counter PGA 1 */
+#define B2055_C1_TX_RF_CNTPAD1		0x7D /* Core 1 TX RF counter PAD 1 */
+#define B2055_C1_TX_RF_PGAIDAC		0x7E /* Core 1 TX RF PGA IDAC */
+#define B2055_C1_TX_PGAPADTN		0x7F /* Core 1 TX PGA PAD TN */
+#define B2055_C1_TX_PADIDAC1		0x80 /* Core 1 TX PAD IDAC 1 */
+#define B2055_C1_TX_PADIDAC2		0x81 /* Core 1 TX PAD IDAC 2 */
+#define B2055_C1_TX_MXBGTRIM		0x82 /* Core 1 TX MX B/G TRIM */
+#define B2055_C1_TX_RF_RCAL		0x83 /* Core 1 TX RF RCAL */
+#define B2055_C1_TX_RF_PADTSSI1		0x84 /* Core 1 TX RF PAD TSSI1 */
+#define B2055_C1_TX_RF_PADTSSI2		0x85 /* Core 1 TX RF PAD TSSI2 */
+#define B2055_C1_TX_RF_SPARE		0x86 /* Core 1 TX RF spare */
+#define B2055_C1_TX_RF_IQCAL1		0x87 /* Core 1 TX RF I/Q CAL 1 */
+#define B2055_C1_TX_RF_IQCAL2		0x88 /* Core 1 TX RF I/Q CAL 2 */
+#define B2055_C1_TXBB_RCCAL		0x89 /* Core 1 TXBB RC CAL Control */
+#define B2055_C1_TXBB_LPF1		0x8A /* Core 1 TXBB LPF 1 */
+#define B2055_C1_TX_VOSCNCL		0x8B /* Core 1 TX VOS CNCL */
+#define B2055_C1_TX_LPF_MXGMIDAC	0x8C /* Core 1 TX LPF MXGM IDAC */
+#define B2055_C1_TX_BB_MXGM		0x8D /* Core 1 TX BB MXGM */
+#define B2055_C2_LGBUF_ATUNE		0x8E /* Core 2 LGBUF A tune */
+#define B2055_C2_LGBUF_GTUNE		0x8F /* Core 2 LGBUF G tune */
+#define B2055_C2_LGBUF_DIV		0x90 /* Core 2 LGBUF div */
+#define B2055_C2_LGBUF_AIDAC		0x91 /* Core 2 LGBUF A IDAC */
+#define B2055_C2_LGBUF_GIDAC		0x92 /* Core 2 LGBUF G IDAC */
+#define B2055_C2_LGBUF_IDACFO		0x93 /* Core 2 LGBUF IDAC filter override */
+#define B2055_C2_LGBUF_SPARE		0x94 /* Core 2 LGBUF spare */
+#define B2055_C2_RX_RFSPC1		0x95 /* Core 2 RX RF SPC1 */
+#define B2055_C2_RX_RFR1		0x96 /* Core 2 RX RF reg 1 */
+#define B2055_C2_RX_RFR2		0x97 /* Core 2 RX RF reg 2 */
+#define B2055_C2_RX_RFRCAL		0x98 /* Core 2 RX RF RCAL */
+#define B2055_C2_RX_BB_BLCMP		0x99 /* Core 2 RX Baseband BUFI LPF CMP */
+#define B2055_C2_RX_BB_LPF		0x9A /* Core 2 RX Baseband LPF */
+#define B2055_C2_RX_BB_MIDACHP		0x9B /* Core 2 RX Baseband MIDAC High-pass */
+#define B2055_C2_RX_BB_VGA1IDAC		0x9C /* Core 2 RX Baseband VGA1 IDAC */
+#define B2055_C2_RX_BB_VGA2IDAC		0x9D /* Core 2 RX Baseband VGA2 IDAC */
+#define B2055_C2_RX_BB_VGA3IDAC		0x9E /* Core 2 RX Baseband VGA3 IDAC */
+#define B2055_C2_RX_BB_BUFOCTL		0x9F /* Core 2 RX Baseband BUFO Control */
+#define B2055_C2_RX_BB_RCCALCTL		0xA0 /* Core 2 RX Baseband RCCAL Control */
+#define B2055_C2_RX_BB_RSSICTL1		0xA1 /* Core 2 RX Baseband RSSI Control 1 */
+#define B2055_C2_RX_BB_RSSICTL2		0xA2 /* Core 2 RX Baseband RSSI Control 2 */
+#define B2055_C2_RX_BB_RSSICTL3		0xA3 /* Core 2 RX Baseband RSSI Control 3 */
+#define B2055_C2_RX_BB_RSSICTL4		0xA4 /* Core 2 RX Baseband RSSI Control 4 */
+#define B2055_C2_RX_BB_RSSICTL5		0xA5 /* Core 2 RX Baseband RSSI Control 5 */
+#define B2055_C2_RX_BB_REG		0xA6 /* Core 2 RX Baseband Regulator */
+#define B2055_C2_RX_BB_SPARE1		0xA7 /* Core 2 RX Baseband spare 1 */
+#define B2055_C2_RX_TXBBRCAL		0xA8 /* Core 2 RX TX BB RCAL */
+#define B2055_C2_TX_RF_SPGA		0xA9 /* Core 2 TX RF SGM PGA */
+#define B2055_C2_TX_RF_SPAD		0xAA /* Core 2 TX RF SGM PAD */
+#define B2055_C2_TX_RF_CNTPGA1		0xAB /* Core 2 TX RF counter PGA 1 */
+#define B2055_C2_TX_RF_CNTPAD1		0xAC /* Core 2 TX RF counter PAD 1 */
+#define B2055_C2_TX_RF_PGAIDAC		0xAD /* Core 2 TX RF PGA IDAC */
+#define B2055_C2_TX_PGAPADTN		0xAE /* Core 2 TX PGA PAD TN */
+#define B2055_C2_TX_PADIDAC1		0xAF /* Core 2 TX PAD IDAC 1 */
+#define B2055_C2_TX_PADIDAC2		0xB0 /* Core 2 TX PAD IDAC 2 */
+#define B2055_C2_TX_MXBGTRIM		0xB1 /* Core 2 TX MX B/G TRIM */
+#define B2055_C2_TX_RF_RCAL		0xB2 /* Core 2 TX RF RCAL */
+#define B2055_C2_TX_RF_PADTSSI1		0xB3 /* Core 2 TX RF PAD TSSI1 */
+#define B2055_C2_TX_RF_PADTSSI2		0xB4 /* Core 2 TX RF PAD TSSI2 */
+#define B2055_C2_TX_RF_SPARE		0xB5 /* Core 2 TX RF spare */
+#define B2055_C2_TX_RF_IQCAL1		0xB6 /* Core 2 TX RF I/Q CAL 1 */
+#define B2055_C2_TX_RF_IQCAL2		0xB7 /* Core 2 TX RF I/Q CAL 2 */
+#define B2055_C2_TXBB_RCCAL		0xB8 /* Core 2 TXBB RC CAL Control */
+#define B2055_C2_TXBB_LPF1		0xB9 /* Core 2 TXBB LPF 1 */
+#define B2055_C2_TX_VOSCNCL		0xBA /* Core 2 TX VOS CNCL */
+#define B2055_C2_TX_LPF_MXGMIDAC	0xBB /* Core 2 TX LPF MXGM IDAC */
+#define B2055_C2_TX_BB_MXGM		0xBC /* Core 2 TX BB MXGM */
+#define B2055_PRG_GCHP21		0xBD /* PRG GC HPVGA23 21 */
+#define B2055_PRG_GCHP22		0xBE /* PRG GC HPVGA23 22 */
+#define B2055_PRG_GCHP23		0xBF /* PRG GC HPVGA23 23 */
+#define B2055_PRG_GCHP24		0xC0 /* PRG GC HPVGA23 24 */
+#define B2055_PRG_GCHP25		0xC1 /* PRG GC HPVGA23 25 */
+#define B2055_PRG_GCHP26		0xC2 /* PRG GC HPVGA23 26 */
+#define B2055_PRG_GCHP27		0xC3 /* PRG GC HPVGA23 27 */
+#define B2055_PRG_GCHP28		0xC4 /* PRG GC HPVGA23 28 */
+#define B2055_PRG_GCHP29		0xC5 /* PRG GC HPVGA23 29 */
+#define B2055_PRG_GCHP30		0xC6 /* PRG GC HPVGA23 30 */
+#define B2055_C1_LNA_GAINBST		0xCD /* Core 1 LNA GAINBST */
+#define B2055_C1_B0NB_RSSIVCM		0xD2 /* Core 1 B0 narrow-band RSSI VCM */
+#define B2055_C1_GENSPARE2		0xD6 /* Core 1 GEN spare 2 */
+#define B2055_C2_LNA_GAINBST		0xD9 /* Core 2 LNA GAINBST */
+#define B2055_C2_B0NB_RSSIVCM		0xDE /* Core 2 B0 narrow-band RSSI VCM */
+#define B2055_C2_GENSPARE2		0xE2 /* Core 2 GEN spare 2 */
+
+struct b43_nphy_channeltab_entry_rev2 {
+	/* The channel number */
+	u8 channel;
+	/* The channel frequency in MHz */
+	u16 freq;
+	/* An unknown value */
+	u16 unk2;
+	/* Radio register values on channelswitch */
+	u8 radio_pll_ref;
+	u8 radio_rf_pllmod0;
+	u8 radio_rf_pllmod1;
+	u8 radio_vco_captail;
+	u8 radio_vco_cal1;
+	u8 radio_vco_cal2;
+	u8 radio_pll_lfc1;
+	u8 radio_pll_lfr1;
+	u8 radio_pll_lfc2;
+	u8 radio_lgbuf_cenbuf;
+	u8 radio_lgen_tune1;
+	u8 radio_lgen_tune2;
+	u8 radio_c1_lgbuf_atune;
+	u8 radio_c1_lgbuf_gtune;
+	u8 radio_c1_rx_rfr1;
+	u8 radio_c1_tx_pgapadtn;
+	u8 radio_c1_tx_mxbgtrim;
+	u8 radio_c2_lgbuf_atune;
+	u8 radio_c2_lgbuf_gtune;
+	u8 radio_c2_rx_rfr1;
+	u8 radio_c2_tx_pgapadtn;
+	u8 radio_c2_tx_mxbgtrim;
+	/* PHY register values on channelswitch */
+	struct b43_phy_n_sfo_cfg phy_regs;
+};
+
+/* Upload the default register value table.
+ * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz
+ * table is uploaded. If "ignore_uploadflag" is true, we upload any value
+ * and ignore the "UPLOAD" flag. */
+void b2055_upload_inittab(struct b43_wldev *dev,
+			  bool ghz5, bool ignore_uploadflag);
+
+#endif /* B43_RADIO_2055_H_ */
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c
new file mode 100644
index 0000000..d856319
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2056.c
@@ -0,0 +1,43 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n 2056 radio device data tables
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "radio_2056.h"
+#include "phy_common.h"
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = {
+};
+
+const struct b43_nphy_channeltab_entry_rev3 *
+b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
+{
+	const struct b43_nphy_channeltab_entry_rev3 *e;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev3); i++) {
+		e = &(b43_nphy_channeltab_rev3[i]);
+		if (e->freq == freq)
+			return e;
+	}
+
+	return NULL;
+}
diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h
new file mode 100644
index 0000000..fda6daf
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2056.h
@@ -0,0 +1,42 @@
+/*
+
+  Broadcom B43 wireless driver
+
+  Copyright (c) 2010 Rafał Miłecki <zajec5@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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef B43_RADIO_2056_H_
+#define B43_RADIO_2056_H_
+
+#include <linux/types.h>
+
+#include "tables_nphy.h"
+
+struct b43_nphy_channeltab_entry_rev3 {
+	/* The channel number */
+	u8 channel;
+	/* The channel frequency in MHz */
+	u16 freq;
+	/* Radio register values on channelswitch */
+	/* TODO */
+	/* PHY register values on channelswitch */
+	struct b43_phy_n_sfo_cfg phy_regs;
+};
+
+#endif /* B43_RADIO_2056_H_ */
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index d96e870..d60db07 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -1,7 +1,7 @@
 /*
 
   Broadcom B43 wireless driver
-  IEEE 802.11n PHY and radio device data tables
+  IEEE 802.11n PHY data tables
 
   Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
 
@@ -27,1315 +27,6 @@
 #include "phy_common.h"
 #include "phy_n.h"
 
-
-struct b2055_inittab_entry {
-	/* Value to write if we use the 5GHz band. */
-	u16 ghz5;
-	/* Value to write if we use the 2.4GHz band. */
-	u16 ghz2;
-	/* Flags */
-	u8 flags;
-#define B2055_INITTAB_ENTRY_OK	0x01
-#define B2055_INITTAB_UPLOAD	0x02
-};
-#define UPLOAD		.flags = B2055_INITTAB_ENTRY_OK | B2055_INITTAB_UPLOAD
-#define NOUPLOAD	.flags = B2055_INITTAB_ENTRY_OK
-
-static const struct b2055_inittab_entry b2055_inittab [] = {
-  [B2055_SP_PINPD]		= { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
-  [B2055_C1_SP_RSSI]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C1_SP_PDMISC]		= { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
-  [B2055_C2_SP_RSSI]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C2_SP_PDMISC]		= { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
-  [B2055_C1_SP_RXGC1]		= { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
-  [B2055_C1_SP_RXGC2]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
-  [B2055_C2_SP_RXGC1]		= { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
-  [B2055_C2_SP_RXGC2]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
-  [B2055_C1_SP_LPFBWSEL]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
-  [B2055_C2_SP_LPFBWSEL]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
-  [B2055_C1_SP_TXGC1]		= { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
-  [B2055_C1_SP_TXGC2]		= { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
-  [B2055_C2_SP_TXGC1]		= { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
-  [B2055_C2_SP_TXGC2]		= { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
-  [B2055_MASTER1]		= { .ghz5 = 0x00D0, .ghz2 = 0x00D0, NOUPLOAD, },
-  [B2055_MASTER2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
-  [B2055_PD_LGEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_PD_PLLTS]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
-  [B2055_C1_PD_LGBUF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C1_PD_TX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C1_PD_RXTX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C1_PD_RSSIMISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C2_PD_LGBUF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C2_PD_TX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C2_PD_RXTX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C2_PD_RSSIMISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_PWRDET_LGEN]		= { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
-  [B2055_C1_PWRDET_LGBUF]	= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
-  [B2055_C1_PWRDET_RXTX]	= { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
-  [B2055_C2_PWRDET_LGBUF]	= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
-  [B2055_C2_PWRDET_RXTX]	= { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
-  [B2055_RRCCAL_CS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_RRCCAL_NOPTSEL]	= { .ghz5 = 0x002C, .ghz2 = 0x002C, NOUPLOAD, },
-  [B2055_CAL_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_CAL_COUT]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_CAL_COUT2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_CAL_CVARCTL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_CAL_RVARCTL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_CAL_LPOCTL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_CAL_TS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_CAL_RCCALRTS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_CAL_RCALRTS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_PADDRV]		= { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
-  [B2055_XOCTL1]		= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
-  [B2055_XOCTL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_XOREGUL]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
-  [B2055_XOMISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_PLL_LFC1]		= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
-  [B2055_PLL_CALVTH]		= { .ghz5 = 0x0087, .ghz2 = 0x0087, NOUPLOAD, },
-  [B2055_PLL_LFC2]		= { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
-  [B2055_PLL_REF]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
-  [B2055_PLL_LFR1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
-  [B2055_PLL_PFDCP]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, UPLOAD, },
-  [B2055_PLL_IDAC_CPOPAMP]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
-  [B2055_PLL_CPREG]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
-  [B2055_PLL_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
-  [B2055_RF_PLLMOD0]		= { .ghz5 = 0x009E, .ghz2 = 0x009E, NOUPLOAD, },
-  [B2055_RF_PLLMOD1]		= { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
-  [B2055_RF_MMDIDAC1]		= { .ghz5 = 0x00C8, .ghz2 = 0x00C8, UPLOAD, },
-  [B2055_RF_MMDIDAC0]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [B2055_RF_MMDSP]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_VCO_CAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_VCO_CAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_VCO_CAL3]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
-  [B2055_VCO_CAL4]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
-  [B2055_VCO_CAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
-  [B2055_VCO_CAL6]		= { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
-  [B2055_VCO_CAL7]		= { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
-  [B2055_VCO_CAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
-  [B2055_VCO_CAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
-  [B2055_VCO_CAL10]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
-  [B2055_VCO_CAL11]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
-  [B2055_VCO_CAL12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_VCO_CAL13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_VCO_CAL14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_VCO_CAL15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_VCO_CAL16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_VCO_KVCO]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
-  [B2055_VCO_CAPTAIL]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
-  [B2055_VCO_IDACVCO]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
-  [B2055_VCO_REG]		= { .ghz5 = 0x0084, .ghz2 = 0x0084, UPLOAD, },
-  [B2055_PLL_RFVTH]		= { .ghz5 = 0x00C3, .ghz2 = 0x00C3, NOUPLOAD, },
-  [B2055_LGBUF_CENBUF]		= { .ghz5 = 0x008F, .ghz2 = 0x008F, NOUPLOAD, },
-  [B2055_LGEN_TUNE1]		= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
-  [B2055_LGEN_TUNE2]		= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
-  [B2055_LGEN_IDAC1]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [B2055_LGEN_IDAC2]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [B2055_LGEN_BIASC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_LGEN_BIASIDAC]		= { .ghz5 = 0x00CC, .ghz2 = 0x00CC, NOUPLOAD, },
-  [B2055_LGEN_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
-  [B2055_LGEN_DIV]		= { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
-  [B2055_LGEN_SPARE2]		= { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
-  [B2055_C1_LGBUF_ATUNE]	= { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
-  [B2055_C1_LGBUF_GTUNE]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [B2055_C1_LGBUF_DIV]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [B2055_C1_LGBUF_AIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
-  [B2055_C1_LGBUF_GIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [B2055_C1_LGBUF_IDACFO]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C1_LGBUF_SPARE]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
-  [B2055_C1_RX_RFSPC1]		= { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
-  [B2055_C1_RX_RFR1]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
-  [B2055_C1_RX_RFR2]		= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
-  [B2055_C1_RX_RFRCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
-  [B2055_C1_RX_BB_BLCMP]	= { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
-  [B2055_C1_RX_BB_LPF]		= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
-  [B2055_C1_RX_BB_MIDACHP]	= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
-  [B2055_C1_RX_BB_VGA1IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
-  [B2055_C1_RX_BB_VGA2IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
-  [B2055_C1_RX_BB_VGA3IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
-  [B2055_C1_RX_BB_BUFOCTL]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
-  [B2055_C1_RX_BB_RCCALCTL]	= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
-  [B2055_C1_RX_BB_RSSICTL1]	= { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
-  [B2055_C1_RX_BB_RSSICTL2]	= { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
-  [B2055_C1_RX_BB_RSSICTL3]	= { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
-  [B2055_C1_RX_BB_RSSICTL4]	= { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
-  [B2055_C1_RX_BB_RSSICTL5]	= { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
-  [B2055_C1_RX_BB_REG]		= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
-  [B2055_C1_RX_BB_SPARE1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C1_RX_TXBBRCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
-  [B2055_C1_TX_RF_SPGA]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
-  [B2055_C1_TX_RF_SPAD]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
-  [B2055_C1_TX_RF_CNTPGA1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
-  [B2055_C1_TX_RF_CNTPAD1]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
-  [B2055_C1_TX_RF_PGAIDAC]	= { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
-  [B2055_C1_TX_PGAPADTN]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
-  [B2055_C1_TX_PADIDAC1]	= { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
-  [B2055_C1_TX_PADIDAC2]	= { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
-  [B2055_C1_TX_MXBGTRIM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [B2055_C1_TX_RF_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
-  [B2055_C1_TX_RF_PADTSSI1]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
-  [B2055_C1_TX_RF_PADTSSI2]	= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
-  [B2055_C1_TX_RF_SPARE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
-  [B2055_C1_TX_RF_IQCAL1]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
-  [B2055_C1_TX_RF_IQCAL2]	= { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
-  [B2055_C1_TXBB_RCCAL]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
-  [B2055_C1_TXBB_LPF1]		= { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
-  [B2055_C1_TX_VOSCNCL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C1_TX_LPF_MXGMIDAC]	= { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
-  [B2055_C1_TX_BB_MXGM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C2_LGBUF_ATUNE]	= { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
-  [B2055_C2_LGBUF_GTUNE]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [B2055_C2_LGBUF_DIV]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [B2055_C2_LGBUF_AIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
-  [B2055_C2_LGBUF_GIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [B2055_C2_LGBUF_IDACFO]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C2_LGBUF_SPARE]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
-  [B2055_C2_RX_RFSPC1]		= { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
-  [B2055_C2_RX_RFR1]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
-  [B2055_C2_RX_RFR2]		= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
-  [B2055_C2_RX_RFRCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
-  [B2055_C2_RX_BB_BLCMP]	= { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
-  [B2055_C2_RX_BB_LPF]		= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
-  [B2055_C2_RX_BB_MIDACHP]	= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
-  [B2055_C2_RX_BB_VGA1IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
-  [B2055_C2_RX_BB_VGA2IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
-  [B2055_C2_RX_BB_VGA3IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
-  [B2055_C2_RX_BB_BUFOCTL]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
-  [B2055_C2_RX_BB_RCCALCTL]	= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
-  [B2055_C2_RX_BB_RSSICTL1]	= { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
-  [B2055_C2_RX_BB_RSSICTL2]	= { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
-  [B2055_C2_RX_BB_RSSICTL3]	= { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
-  [B2055_C2_RX_BB_RSSICTL4]	= { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
-  [B2055_C2_RX_BB_RSSICTL5]	= { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
-  [B2055_C2_RX_BB_REG]		= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
-  [B2055_C2_RX_BB_SPARE1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C2_RX_TXBBRCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
-  [B2055_C2_TX_RF_SPGA]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
-  [B2055_C2_TX_RF_SPAD]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
-  [B2055_C2_TX_RF_CNTPGA1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
-  [B2055_C2_TX_RF_CNTPAD1]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
-  [B2055_C2_TX_RF_PGAIDAC]	= { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
-  [B2055_C2_TX_PGAPADTN]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
-  [B2055_C2_TX_PADIDAC1]	= { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
-  [B2055_C2_TX_PADIDAC2]	= { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
-  [B2055_C2_TX_MXBGTRIM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [B2055_C2_TX_RF_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
-  [B2055_C2_TX_RF_PADTSSI1]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
-  [B2055_C2_TX_RF_PADTSSI2]	= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
-  [B2055_C2_TX_RF_SPARE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
-  [B2055_C2_TX_RF_IQCAL1]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
-  [B2055_C2_TX_RF_IQCAL2]	= { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
-  [B2055_C2_TXBB_RCCAL]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
-  [B2055_C2_TXBB_LPF1]		= { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
-  [B2055_C2_TX_VOSCNCL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C2_TX_LPF_MXGMIDAC]	= { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
-  [B2055_C2_TX_BB_MXGM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_PRG_GCHP21]		= { .ghz5 = 0x0071, .ghz2 = 0x0071, NOUPLOAD, },
-  [B2055_PRG_GCHP22]		= { .ghz5 = 0x0072, .ghz2 = 0x0072, NOUPLOAD, },
-  [B2055_PRG_GCHP23]		= { .ghz5 = 0x0073, .ghz2 = 0x0073, NOUPLOAD, },
-  [B2055_PRG_GCHP24]		= { .ghz5 = 0x0074, .ghz2 = 0x0074, NOUPLOAD, },
-  [B2055_PRG_GCHP25]		= { .ghz5 = 0x0075, .ghz2 = 0x0075, NOUPLOAD, },
-  [B2055_PRG_GCHP26]		= { .ghz5 = 0x0076, .ghz2 = 0x0076, NOUPLOAD, },
-  [B2055_PRG_GCHP27]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
-  [B2055_PRG_GCHP28]		= { .ghz5 = 0x0078, .ghz2 = 0x0078, NOUPLOAD, },
-  [B2055_PRG_GCHP29]		= { .ghz5 = 0x0079, .ghz2 = 0x0079, NOUPLOAD, },
-  [B2055_PRG_GCHP30]		= { .ghz5 = 0x007A, .ghz2 = 0x007A, NOUPLOAD, },
-  [0xC7]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xC8]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xC9]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xCA]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xCB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xCC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C1_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xCE]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xCF]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xD0]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xD1]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
-  [B2055_C1_B0NB_RSSIVCM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [0xD3]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xD4]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xD5]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C1_GENSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xD7]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xD8]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C2_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xDA]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xDB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xDC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xDD]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
-  [B2055_C2_B0NB_RSSIVCM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
-  [0xDF]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xE0]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xE1]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [B2055_C2_GENSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-};
-
-
-void b2055_upload_inittab(struct b43_wldev *dev,
-			  bool ghz5, bool ignore_uploadflag)
-{
-	const struct b2055_inittab_entry *e;
-	unsigned int i;
-	u16 value;
-
-	for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) {
-		e = &(b2055_inittab[i]);
-		if (!(e->flags & B2055_INITTAB_ENTRY_OK))
-			continue;
-		if ((e->flags & B2055_INITTAB_UPLOAD) || ignore_uploadflag) {
-			if (ghz5)
-				value = e->ghz5;
-			else
-				value = e->ghz2;
-			b43_radio_write16(dev, i, value);
-		}
-	}
-}
-
-
-#define RADIOREGS(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, \
-		  r12, r13, r14, r15, r16, r17, r18, r19, r20, r21) \
-	.radio_pll_ref		= r0,	\
-	.radio_rf_pllmod0	= r1,	\
-	.radio_rf_pllmod1	= r2,	\
-	.radio_vco_captail	= r3,	\
-	.radio_vco_cal1		= r4,	\
-	.radio_vco_cal2		= r5,	\
-	.radio_pll_lfc1		= r6,	\
-	.radio_pll_lfr1		= r7,	\
-	.radio_pll_lfc2		= r8,	\
-	.radio_lgbuf_cenbuf	= r9,	\
-	.radio_lgen_tune1	= r10,	\
-	.radio_lgen_tune2	= r11,	\
-	.radio_c1_lgbuf_atune	= r12,	\
-	.radio_c1_lgbuf_gtune	= r13,	\
-	.radio_c1_rx_rfr1	= r14,	\
-	.radio_c1_tx_pgapadtn	= r15,	\
-	.radio_c1_tx_mxbgtrim	= r16,	\
-	.radio_c2_lgbuf_atune	= r17,	\
-	.radio_c2_lgbuf_gtune	= r18,	\
-	.radio_c2_rx_rfr1	= r19,	\
-	.radio_c2_tx_pgapadtn	= r20,	\
-	.radio_c2_tx_mxbgtrim	= r21
-
-#define PHYREGS(r0, r1, r2, r3, r4, r5)	\
-	.phy_regs.phy_bw1a	= r0,	\
-	.phy_regs.phy_bw2	= r1,	\
-	.phy_regs.phy_bw3	= r2,	\
-	.phy_regs.phy_bw4	= r3,	\
-	.phy_regs.phy_bw5	= r4,	\
-	.phy_regs.phy_bw6	= r5
-
-static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab[] = {
-  {	.channel		= 184,
-	.freq			= 4920, /* MHz */
-	.unk2			= 3280,
-	RADIOREGS(0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xB407, 0xB007, 0xAC07, 0x1402, 0x1502, 0x1602),
-  },
-  {	.channel		= 186,
-	.freq			= 4930, /* MHz */
-	.unk2			= 3287,
-	RADIOREGS(0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xB807, 0xB407, 0xB007, 0x1302, 0x1402, 0x1502),
-  },
-  {	.channel		= 188,
-	.freq			= 4940, /* MHz */
-	.unk2			= 3293,
-	RADIOREGS(0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xBC07, 0xB807, 0xB407, 0x1202, 0x1302, 0x1402),
-  },
-  {	.channel		= 190,
-	.freq			= 4950, /* MHz */
-	.unk2			= 3300,
-	RADIOREGS(0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xC007, 0xBC07, 0xB807, 0x1102, 0x1202, 0x1302),
-  },
-  {	.channel		= 192,
-	.freq			= 4960, /* MHz */
-	.unk2			= 3307,
-	RADIOREGS(0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xC407, 0xC007, 0xBC07, 0x0F02, 0x1102, 0x1202),
-  },
-  {	.channel		= 194,
-	.freq			= 4970, /* MHz */
-	.unk2			= 3313,
-	RADIOREGS(0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xC807, 0xC407, 0xC007, 0x0E02, 0x0F02, 0x1102),
-  },
-  {	.channel		= 196,
-	.freq			= 4980, /* MHz */
-	.unk2			= 3320,
-	RADIOREGS(0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xCC07, 0xC807, 0xC407, 0x0D02, 0x0E02, 0x0F02),
-  },
-  {	.channel		= 198,
-	.freq			= 4990, /* MHz */
-	.unk2			= 3327,
-	RADIOREGS(0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xD007, 0xCC07, 0xC807, 0x0C02, 0x0D02, 0x0E02),
-  },
-  {	.channel		= 200,
-	.freq			= 5000, /* MHz */
-	.unk2			= 3333,
-	RADIOREGS(0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xD407, 0xD007, 0xCC07, 0x0B02, 0x0C02, 0x0D02),
-  },
-  {	.channel		= 202,
-	.freq			= 5010, /* MHz */
-	.unk2			= 3340,
-	RADIOREGS(0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xD807, 0xD407, 0xD007, 0x0A02, 0x0B02, 0x0C02),
-  },
-  {	.channel		= 204,
-	.freq			= 5020, /* MHz */
-	.unk2			= 3347,
-	RADIOREGS(0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xDC07, 0xD807, 0xD407, 0x0902, 0x0A02, 0x0B02),
-  },
-  {	.channel		= 206,
-	.freq			= 5030, /* MHz */
-	.unk2			= 3353,
-	RADIOREGS(0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xE007, 0xDC07, 0xD807, 0x0802, 0x0902, 0x0A02),
-  },
-  {	.channel		= 208,
-	.freq			= 5040, /* MHz */
-	.unk2			= 3360,
-	RADIOREGS(0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xE407, 0xE007, 0xDC07, 0x0702, 0x0802, 0x0902),
-  },
-  {	.channel		= 210,
-	.freq			= 5050, /* MHz */
-	.unk2			= 3367,
-	RADIOREGS(0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
-		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
-	PHYREGS(0xE807, 0xE407, 0xE007, 0x0602, 0x0702, 0x0802),
-  },
-  {	.channel		= 212,
-	.freq			= 5060, /* MHz */
-	.unk2			= 3373,
-	RADIOREGS(0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
-		  0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
-	PHYREGS(0xEC07, 0xE807, 0xE407, 0x0502, 0x0602, 0x0702),
-  },
-  {	.channel		= 214,
-	.freq			= 5070, /* MHz */
-	.unk2			= 3380,
-	RADIOREGS(0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
-		  0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
-		  0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
-	PHYREGS(0xF007, 0xEC07, 0xE807, 0x0402, 0x0502, 0x0602),
-  },
-  {	.channel		= 216,
-	.freq			= 5080, /* MHz */
-	.unk2			= 3387,
-	RADIOREGS(0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
-		  0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
-		  0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
-	PHYREGS(0xF407, 0xF007, 0xEC07, 0x0302, 0x0402, 0x0502),
-  },
-  {	.channel		= 218,
-	.freq			= 5090, /* MHz */
-	.unk2			= 3393,
-	RADIOREGS(0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
-		  0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
-		  0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
-	PHYREGS(0xF807, 0xF407, 0xF007, 0x0202, 0x0302, 0x0402),
-  },
-  {	.channel		= 220,
-	.freq			= 5100, /* MHz */
-	.unk2			= 3400,
-	RADIOREGS(0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
-		  0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
-		  0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
-	PHYREGS(0xFC07, 0xF807, 0xF407, 0x0102, 0x0202, 0x0302),
-  },
-  {	.channel		= 222,
-	.freq			= 5110, /* MHz */
-	.unk2			= 3407,
-	RADIOREGS(0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
-		  0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
-		  0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
-	PHYREGS(0x0008, 0xFC07, 0xF807, 0x0002, 0x0102, 0x0202),
-  },
-  {	.channel		= 224,
-	.freq			= 5120, /* MHz */
-	.unk2			= 3413,
-	RADIOREGS(0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
-		  0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
-		  0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
-	PHYREGS(0x0408, 0x0008, 0xFC07, 0xFF01, 0x0002, 0x0102),
-  },
-  {	.channel		= 226,
-	.freq			= 5130, /* MHz */
-	.unk2			= 3420,
-	RADIOREGS(0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
-		  0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
-		  0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
-	PHYREGS(0x0808, 0x0408, 0x0008, 0xFE01, 0xFF01, 0x0002),
-  },
-  {	.channel		= 228,
-	.freq			= 5140, /* MHz */
-	.unk2			= 3427,
-	RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
-		  0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E,
-		  0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B),
-	PHYREGS(0x0C08, 0x0808, 0x0408, 0xFD01, 0xFE01, 0xFF01),
-  },
-  {	.channel		= 32,
-	.freq			= 5160, /* MHz */
-	.unk2			= 3440,
-	RADIOREGS(0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
-		  0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
-		  0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
-	PHYREGS(0x1408, 0x1008, 0x0C08, 0xFB01, 0xFC01, 0xFD01),
-  },
-  {	.channel		= 34,
-	.freq			= 5170, /* MHz */
-	.unk2			= 3447,
-	RADIOREGS(0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
-		  0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
-		  0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
-	PHYREGS(0x1808, 0x1408, 0x1008, 0xFA01, 0xFB01, 0xFC01),
-  },
-  {	.channel		= 36,
-	.freq			= 5180, /* MHz */
-	.unk2			= 3453,
-	RADIOREGS(0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
-		  0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
-		  0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
-	PHYREGS(0x1C08, 0x1808, 0x1408, 0xF901, 0xFA01, 0xFB01),
-  },
-  {	.channel		= 38,
-	.freq			= 5190, /* MHz */
-	.unk2			= 3460,
-	RADIOREGS(0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
-		  0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
-		  0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
-	PHYREGS(0x2008, 0x1C08, 0x1808, 0xF801, 0xF901, 0xFA01),
-  },
-  {	.channel		= 40,
-	.freq			= 5200, /* MHz */
-	.unk2			= 3467,
-	RADIOREGS(0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
-		  0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
-	PHYREGS(0x2408, 0x2008, 0x1C08, 0xF701, 0xF801, 0xF901),
-  },
-  {	.channel		= 42,
-	.freq			= 5210, /* MHz */
-	.unk2			= 3473,
-	RADIOREGS(0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
-		  0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
-		  0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
-	PHYREGS(0x2808, 0x2408, 0x2008, 0xF601, 0xF701, 0xF801),
-  },
-  {	.channel		= 44,
-	.freq			= 5220, /* MHz */
-	.unk2			= 3480,
-	RADIOREGS(0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
-		  0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
-		  0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
-	PHYREGS(0x2C08, 0x2808, 0x2408, 0xF501, 0xF601, 0xF701),
-  },
-  {	.channel		= 46,
-	.freq			= 5230, /* MHz */
-	.unk2			= 3487,
-	RADIOREGS(0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
-		  0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
-		  0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
-	PHYREGS(0x3008, 0x2C08, 0x2808, 0xF401, 0xF501, 0xF601),
-  },
-  {	.channel		= 48,
-	.freq			= 5240, /* MHz */
-	.unk2			= 3493,
-	RADIOREGS(0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
-		  0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
-		  0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
-	PHYREGS(0x3408, 0x3008, 0x2C08, 0xF301, 0xF401, 0xF501),
-  },
-  {	.channel		= 50,
-	.freq			= 5250, /* MHz */
-	.unk2			= 3500,
-	RADIOREGS(0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
-		  0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
-		  0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
-	PHYREGS(0x3808, 0x3408, 0x3008, 0xF201, 0xF301, 0xF401),
-  },
-  {	.channel		= 52,
-	.freq			= 5260, /* MHz */
-	.unk2			= 3507,
-	RADIOREGS(0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
-		  0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
-		  0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
-	PHYREGS(0x3C08, 0x3808, 0x3408, 0xF101, 0xF201, 0xF301),
-  },
-  {	.channel		= 54,
-	.freq			= 5270, /* MHz */
-	.unk2			= 3513,
-	RADIOREGS(0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
-		  0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
-		  0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
-	PHYREGS(0x4008, 0x3C08, 0x3808, 0xF001, 0xF101, 0xF201),
-  },
-  {	.channel		= 56,
-	.freq			= 5280, /* MHz */
-	.unk2			= 3520,
-	RADIOREGS(0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
-		  0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
-		  0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
-	PHYREGS(0x4408, 0x4008, 0x3C08, 0xF001, 0xF001, 0xF101),
-  },
-  {	.channel		= 58,
-	.freq			= 5290, /* MHz */
-	.unk2			= 3527,
-	RADIOREGS(0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
-		  0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
-		  0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
-	PHYREGS(0x4808, 0x4408, 0x4008, 0xEF01, 0xF001, 0xF001),
-  },
-  {	.channel		= 60,
-	.freq			= 5300, /* MHz */
-	.unk2			= 3533,
-	RADIOREGS(0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
-		  0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
-		  0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
-	PHYREGS(0x4C08, 0x4808, 0x4408, 0xEE01, 0xEF01, 0xF001),
-  },
-  {	.channel		= 62,
-	.freq			= 5310, /* MHz */
-	.unk2			= 3540,
-	RADIOREGS(0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
-		  0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
-		  0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
-	PHYREGS(0x5008, 0x4C08, 0x4808, 0xED01, 0xEE01, 0xEF01),
-  },
-  {	.channel		= 64,
-	.freq			= 5320, /* MHz */
-	.unk2			= 3547,
-	RADIOREGS(0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
-		  0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
-		  0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
-	PHYREGS(0x5408, 0x5008, 0x4C08, 0xEC01, 0xED01, 0xEE01),
-  },
-  {	.channel		= 66,
-	.freq			= 5330, /* MHz */
-	.unk2			= 3553,
-	RADIOREGS(0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
-		  0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
-		  0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
-	PHYREGS(0x5808, 0x5408, 0x5008, 0xEB01, 0xEC01, 0xED01),
-  },
-  {	.channel		= 68,
-	.freq			= 5340, /* MHz */
-	.unk2			= 3560,
-	RADIOREGS(0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
-		  0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
-		  0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
-	PHYREGS(0x5C08, 0x5808, 0x5408, 0xEA01, 0xEB01, 0xEC01),
-  },
-  {	.channel		= 70,
-	.freq			= 5350, /* MHz */
-	.unk2			= 3567,
-	RADIOREGS(0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
-		  0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
-		  0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
-	PHYREGS(0x6008, 0x5C08, 0x5808, 0xE901, 0xEA01, 0xEB01),
-  },
-  {	.channel		= 72,
-	.freq			= 5360, /* MHz */
-	.unk2			= 3573,
-	RADIOREGS(0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
-		  0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
-		  0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
-	PHYREGS(0x6408, 0x6008, 0x5C08, 0xE801, 0xE901, 0xEA01),
-  },
-  {	.channel		= 74,
-	.freq			= 5370, /* MHz */
-	.unk2			= 3580,
-	RADIOREGS(0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
-		  0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
-		  0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
-	PHYREGS(0x6808, 0x6408, 0x6008, 0xE701, 0xE801, 0xE901),
-  },
-  {	.channel		= 76,
-	.freq			= 5380, /* MHz */
-	.unk2			= 3587,
-	RADIOREGS(0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
-		  0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
-		  0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
-	PHYREGS(0x6C08, 0x6808, 0x6408, 0xE601, 0xE701, 0xE801),
-  },
-  {	.channel		= 78,
-	.freq			= 5390, /* MHz */
-	.unk2			= 3593,
-	RADIOREGS(0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
-		  0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
-		  0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
-	PHYREGS(0x7008, 0x6C08, 0x6808, 0xE501, 0xE601, 0xE701),
-  },
-  {	.channel		= 80,
-	.freq			= 5400, /* MHz */
-	.unk2			= 3600,
-	RADIOREGS(0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
-		  0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
-		  0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
-	PHYREGS(0x7408, 0x7008, 0x6C08, 0xE501, 0xE501, 0xE601),
-  },
-  {	.channel		= 82,
-	.freq			= 5410, /* MHz */
-	.unk2			= 3607,
-	RADIOREGS(0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
-		  0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
-		  0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
-	PHYREGS(0x7808, 0x7408, 0x7008, 0xE401, 0xE501, 0xE501),
-  },
-  {	.channel		= 84,
-	.freq			= 5420, /* MHz */
-	.unk2			= 3613,
-	RADIOREGS(0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
-		  0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
-		  0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
-	PHYREGS(0x7C08, 0x7808, 0x7408, 0xE301, 0xE401, 0xE501),
-  },
-  {	.channel		= 86,
-	.freq			= 5430, /* MHz */
-	.unk2			= 3620,
-	RADIOREGS(0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
-		  0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
-		  0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
-	PHYREGS(0x8008, 0x7C08, 0x7808, 0xE201, 0xE301, 0xE401),
-  },
-  {	.channel		= 88,
-	.freq			= 5440, /* MHz */
-	.unk2			= 3627,
-	RADIOREGS(0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
-		  0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
-		  0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
-	PHYREGS(0x8408, 0x8008, 0x7C08, 0xE101, 0xE201, 0xE301),
-  },
-  {	.channel		= 90,
-	.freq			= 5450, /* MHz */
-	.unk2			= 3633,
-	RADIOREGS(0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
-		  0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
-		  0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
-	PHYREGS(0x8808, 0x8408, 0x8008, 0xE001, 0xE101, 0xE201),
-  },
-  {	.channel		= 92,
-	.freq			= 5460, /* MHz */
-	.unk2			= 3640,
-	RADIOREGS(0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
-		  0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
-		  0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
-	PHYREGS(0x8C08, 0x8808, 0x8408, 0xDF01, 0xE001, 0xE101),
-  },
-  {	.channel		= 94,
-	.freq			= 5470, /* MHz */
-	.unk2			= 3647,
-	RADIOREGS(0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
-		  0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
-		  0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
-	PHYREGS(0x9008, 0x8C08, 0x8808, 0xDE01, 0xDF01, 0xE001),
-  },
-  {	.channel		= 96,
-	.freq			= 5480, /* MHz */
-	.unk2			= 3653,
-	RADIOREGS(0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
-		  0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
-		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
-	PHYREGS(0x9408, 0x9008, 0x8C08, 0xDD01, 0xDE01, 0xDF01),
-  },
-  {	.channel		= 98,
-	.freq			= 5490, /* MHz */
-	.unk2			= 3660,
-	RADIOREGS(0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
-		  0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
-		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
-	PHYREGS(0x9808, 0x9408, 0x9008, 0xDD01, 0xDD01, 0xDE01),
-  },
-  {	.channel		= 100,
-	.freq			= 5500, /* MHz */
-	.unk2			= 3667,
-	RADIOREGS(0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
-		  0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
-		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
-	PHYREGS(0x9C08, 0x9808, 0x9408, 0xDC01, 0xDD01, 0xDD01),
-  },
-  {	.channel		= 102,
-	.freq			= 5510, /* MHz */
-	.unk2			= 3673,
-	RADIOREGS(0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
-		  0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
-		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
-	PHYREGS(0xA008, 0x9C08, 0x9808, 0xDB01, 0xDC01, 0xDD01),
-  },
-  {	.channel		= 104,
-	.freq			= 5520, /* MHz */
-	.unk2			= 3680,
-	RADIOREGS(0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
-		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
-		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
-	PHYREGS(0xA408, 0xA008, 0x9C08, 0xDA01, 0xDB01, 0xDC01),
-  },
-  {	.channel		= 106,
-	.freq			= 5530, /* MHz */
-	.unk2			= 3687,
-	RADIOREGS(0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
-		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
-		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
-	PHYREGS(0xA808, 0xA408, 0xA008, 0xD901, 0xDA01, 0xDB01),
-  },
-  {	.channel		= 108,
-	.freq			= 5540, /* MHz */
-	.unk2			= 3693,
-	RADIOREGS(0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
-		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
-		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
-	PHYREGS(0xAC08, 0xA808, 0xA408, 0xD801, 0xD901, 0xDA01),
-  },
-  {	.channel		= 110,
-	.freq			= 5550, /* MHz */
-	.unk2			= 3700,
-	RADIOREGS(0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
-		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
-		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
-	PHYREGS(0xB008, 0xAC08, 0xA808, 0xD701, 0xD801, 0xD901),
-  },
-  {	.channel		= 112,
-	.freq			= 5560, /* MHz */
-	.unk2			= 3707,
-	RADIOREGS(0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
-		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
-		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xB408, 0xB008, 0xAC08, 0xD701, 0xD701, 0xD801),
-  },
-  {	.channel		= 114,
-	.freq			= 5570, /* MHz */
-	.unk2			= 3713,
-	RADIOREGS(0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
-		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
-		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xB808, 0xB408, 0xB008, 0xD601, 0xD701, 0xD701),
-  },
-  {	.channel		= 116,
-	.freq			= 5580, /* MHz */
-	.unk2			= 3720,
-	RADIOREGS(0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
-		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
-		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xBC08, 0xB808, 0xB408, 0xD501, 0xD601, 0xD701),
-  },
-  {	.channel		= 118,
-	.freq			= 5590, /* MHz */
-	.unk2			= 3727,
-	RADIOREGS(0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
-		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
-		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xC008, 0xBC08, 0xB808, 0xD401, 0xD501, 0xD601),
-  },
-  {	.channel		= 120,
-	.freq			= 5600, /* MHz */
-	.unk2			= 3733,
-	RADIOREGS(0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
-		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
-		  0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xC408, 0xC008, 0xBC08, 0xD301, 0xD401, 0xD501),
-  },
-  {	.channel		= 122,
-	.freq			= 5610, /* MHz */
-	.unk2			= 3740,
-	RADIOREGS(0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
-		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
-		  0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
-	PHYREGS(0xC808, 0xC408, 0xC008, 0xD201, 0xD301, 0xD401),
-  },
-  {	.channel		= 124,
-	.freq			= 5620, /* MHz */
-	.unk2			= 3747,
-	RADIOREGS(0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
-		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
-		  0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xCC08, 0xC808, 0xC408, 0xD201, 0xD201, 0xD301),
-  },
-  {	.channel		= 126,
-	.freq			= 5630, /* MHz */
-	.unk2			= 3753,
-	RADIOREGS(0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
-		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
-		  0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xD008, 0xCC08, 0xC808, 0xD101, 0xD201, 0xD201),
-  },
-  {	.channel		= 128,
-	.freq			= 5640, /* MHz */
-	.unk2			= 3760,
-	RADIOREGS(0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xD408, 0xD008, 0xCC08, 0xD001, 0xD101, 0xD201),
-  },
-  {	.channel		= 130,
-	.freq			= 5650, /* MHz */
-	.unk2			= 3767,
-	RADIOREGS(0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xD808, 0xD408, 0xD008, 0xCF01, 0xD001, 0xD101),
-  },
-  {	.channel		= 132,
-	.freq			= 5660, /* MHz */
-	.unk2			= 3773,
-	RADIOREGS(0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xDC08, 0xD808, 0xD408, 0xCE01, 0xCF01, 0xD001),
-  },
-  {	.channel		= 134,
-	.freq			= 5670, /* MHz */
-	.unk2			= 3780,
-	RADIOREGS(0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xE008, 0xDC08, 0xD808, 0xCE01, 0xCE01, 0xCF01),
-  },
-  {	.channel		= 136,
-	.freq			= 5680, /* MHz */
-	.unk2			= 3787,
-	RADIOREGS(0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xE408, 0xE008, 0xDC08, 0xCD01, 0xCE01, 0xCE01),
-  },
-  {	.channel		= 138,
-	.freq			= 5690, /* MHz */
-	.unk2			= 3793,
-	RADIOREGS(0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xE808, 0xE408, 0xE008, 0xCC01, 0xCD01, 0xCE01),
-  },
-  {	.channel		= 140,
-	.freq			= 5700, /* MHz */
-	.unk2			= 3800,
-	RADIOREGS(0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xEC08, 0xE808, 0xE408, 0xCB01, 0xCC01, 0xCD01),
-  },
-  {	.channel		= 142,
-	.freq			= 5710, /* MHz */
-	.unk2			= 3807,
-	RADIOREGS(0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xF008, 0xEC08, 0xE808, 0xCA01, 0xCB01, 0xCC01),
-  },
-  {	.channel		= 144,
-	.freq			= 5720, /* MHz */
-	.unk2			= 3813,
-	RADIOREGS(0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xF408, 0xF008, 0xEC08, 0xC901, 0xCA01, 0xCB01),
-  },
-  {	.channel		= 145,
-	.freq			= 5725, /* MHz */
-	.unk2			= 3817,
-	RADIOREGS(0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xF608, 0xF208, 0xEE08, 0xC901, 0xCA01, 0xCB01),
-  },
-  {	.channel		= 146,
-	.freq			= 5730, /* MHz */
-	.unk2			= 3820,
-	RADIOREGS(0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xF808, 0xF408, 0xF008, 0xC901, 0xC901, 0xCA01),
-  },
-  {	.channel		= 147,
-	.freq			= 5735, /* MHz */
-	.unk2			= 3823,
-	RADIOREGS(0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xFA08, 0xF608, 0xF208, 0xC801, 0xC901, 0xCA01),
-  },
-  {	.channel		= 148,
-	.freq			= 5740, /* MHz */
-	.unk2			= 3827,
-	RADIOREGS(0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xFC08, 0xF808, 0xF408, 0xC801, 0xC901, 0xC901),
-  },
-  {	.channel		= 149,
-	.freq			= 5745, /* MHz */
-	.unk2			= 3830,
-	RADIOREGS(0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0xFE08, 0xFA08, 0xF608, 0xC801, 0xC801, 0xC901),
-  },
-  {	.channel		= 150,
-	.freq			= 5750, /* MHz */
-	.unk2			= 3833,
-	RADIOREGS(0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0009, 0xFC08, 0xF808, 0xC701, 0xC801, 0xC901),
-  },
-  {	.channel		= 151,
-	.freq			= 5755, /* MHz */
-	.unk2			= 3837,
-	RADIOREGS(0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0209, 0xFE08, 0xFA08, 0xC701, 0xC801, 0xC801),
-  },
-  {	.channel		= 152,
-	.freq			= 5760, /* MHz */
-	.unk2			= 3840,
-	RADIOREGS(0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0409, 0x0009, 0xFC08, 0xC601, 0xC701, 0xC801),
-  },
-  {	.channel		= 153,
-	.freq			= 5765, /* MHz */
-	.unk2			= 3843,
-	RADIOREGS(0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0609, 0x0209, 0xFE08, 0xC601, 0xC701, 0xC801),
-  },
-  {	.channel		= 154,
-	.freq			= 5770, /* MHz */
-	.unk2			= 3847,
-	RADIOREGS(0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0809, 0x0409, 0x0009, 0xC601, 0xC601, 0xC701),
-  },
-  {	.channel		= 155,
-	.freq			= 5775, /* MHz */
-	.unk2			= 3850,
-	RADIOREGS(0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0A09, 0x0609, 0x0209, 0xC501, 0xC601, 0xC701),
-  },
-  {	.channel		= 156,
-	.freq			= 5780, /* MHz */
-	.unk2			= 3853,
-	RADIOREGS(0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0C09, 0x0809, 0x0409, 0xC501, 0xC601, 0xC601),
-  },
-  {	.channel		= 157,
-	.freq			= 5785, /* MHz */
-	.unk2			= 3857,
-	RADIOREGS(0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x0E09, 0x0A09, 0x0609, 0xC401, 0xC501, 0xC601),
-  },
-  {	.channel		= 158,
-	.freq			= 5790, /* MHz */
-	.unk2			= 3860,
-	RADIOREGS(0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1009, 0x0C09, 0x0809, 0xC401, 0xC501, 0xC601),
-  },
-  {	.channel		= 159,
-	.freq			= 5795, /* MHz */
-	.unk2			= 3863,
-	RADIOREGS(0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1209, 0x0E09, 0x0A09, 0xC401, 0xC401, 0xC501),
-  },
-  {	.channel		= 160,
-	.freq			= 5800, /* MHz */
-	.unk2			= 3867,
-	RADIOREGS(0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1409, 0x1009, 0x0C09, 0xC301, 0xC401, 0xC501),
-  },
-  {	.channel		= 161,
-	.freq			= 5805, /* MHz */
-	.unk2			= 3870,
-	RADIOREGS(0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1609, 0x1209, 0x0E09, 0xC301, 0xC401, 0xC401),
-  },
-  {	.channel		= 162,
-	.freq			= 5810, /* MHz */
-	.unk2			= 3873,
-	RADIOREGS(0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1809, 0x1409, 0x1009, 0xC201, 0xC301, 0xC401),
-  },
-  {	.channel		= 163,
-	.freq			= 5815, /* MHz */
-	.unk2			= 3877,
-	RADIOREGS(0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1A09, 0x1609, 0x1209, 0xC201, 0xC301, 0xC401),
-  },
-  {	.channel		= 164,
-	.freq			= 5820, /* MHz */
-	.unk2			= 3880,
-	RADIOREGS(0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1C09, 0x1809, 0x1409, 0xC201, 0xC201, 0xC301),
-  },
-  {	.channel		= 165,
-	.freq			= 5825, /* MHz */
-	.unk2			= 3883,
-	RADIOREGS(0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x1E09, 0x1A09, 0x1609, 0xC101, 0xC201, 0xC301),
-  },
-  {	.channel		= 166,
-	.freq			= 5830, /* MHz */
-	.unk2			= 3887,
-	RADIOREGS(0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x2009, 0x1C09, 0x1809, 0xC101, 0xC201, 0xC201),
-  },
-  {	.channel		= 168,
-	.freq			= 5840, /* MHz */
-	.unk2			= 3893,
-	RADIOREGS(0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x2409, 0x2009, 0x1C09, 0xC001, 0xC101, 0xC201),
-  },
-  {	.channel		= 170,
-	.freq			= 5850, /* MHz */
-	.unk2			= 3900,
-	RADIOREGS(0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x2809, 0x2409, 0x2009, 0xBF01, 0xC001, 0xC101),
-  },
-  {	.channel		= 172,
-	.freq			= 5860, /* MHz */
-	.unk2			= 3907,
-	RADIOREGS(0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x2C09, 0x2809, 0x2409, 0xBF01, 0xBF01, 0xC001),
-  },
-  {	.channel		= 174,
-	.freq			= 5870, /* MHz */
-	.unk2			= 3913,
-	RADIOREGS(0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x3009, 0x2C09, 0x2809, 0xBE01, 0xBF01, 0xBF01),
-  },
-  {	.channel		= 176,
-	.freq			= 5880, /* MHz */
-	.unk2			= 3920,
-	RADIOREGS(0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x3409, 0x3009, 0x2C09, 0xBD01, 0xBE01, 0xBF01),
-  },
-  {	.channel		= 178,
-	.freq			= 5890, /* MHz */
-	.unk2			= 3927,
-	RADIOREGS(0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x3809, 0x3409, 0x3009, 0xBC01, 0xBD01, 0xBE01),
-  },
-  {	.channel		= 180,
-	.freq			= 5900, /* MHz */
-	.unk2			= 3933,
-	RADIOREGS(0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x3C09, 0x3809, 0x3409, 0xBC01, 0xBC01, 0xBD01),
-  },
-  {	.channel		= 182,
-	.freq			= 5910, /* MHz */
-	.unk2			= 3940,
-	RADIOREGS(0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
-		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
-	PHYREGS(0x4009, 0x3C09, 0x3809, 0xBB01, 0xBC01, 0xBC01),
-  },
-  {	.channel		= 1,
-	.freq			= 2412, /* MHz */
-	.unk2			= 3216,
-	RADIOREGS(0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C,
-		  0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80),
-	PHYREGS(0xC903, 0xC503, 0xC103, 0x3A04, 0x3F04, 0x4304),
-  },
-  {	.channel		= 2,
-	.freq			= 2417, /* MHz */
-	.unk2			= 3223,
-	RADIOREGS(0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B,
-		  0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80),
-	PHYREGS(0xCB03, 0xC703, 0xC303, 0x3804, 0x3D04, 0x4104),
-  },
-  {	.channel		= 3,
-	.freq			= 2422, /* MHz */
-	.unk2			= 3229,
-	RADIOREGS(0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
-		  0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
-	PHYREGS(0xCD03, 0xC903, 0xC503, 0x3604, 0x3A04, 0x3F04),
-  },
-  {	.channel		= 4,
-	.freq			= 2427, /* MHz */
-	.unk2			= 3236,
-	RADIOREGS(0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
-		  0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
-	PHYREGS(0xCF03, 0xCB03, 0xC703, 0x3404, 0x3804, 0x3D04),
-  },
-  {	.channel		= 5,
-	.freq			= 2432, /* MHz */
-	.unk2			= 3243,
-	RADIOREGS(0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09,
-		  0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80),
-	PHYREGS(0xD103, 0xCD03, 0xC903, 0x3104, 0x3604, 0x3A04),
-  },
-  {	.channel		= 6,
-	.freq			= 2437, /* MHz */
-	.unk2			= 3249,
-	RADIOREGS(0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08,
-		  0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80),
-	PHYREGS(0xD303, 0xCF03, 0xCB03, 0x2F04, 0x3404, 0x3804),
-  },
-  {	.channel		= 7,
-	.freq			= 2442, /* MHz */
-	.unk2			= 3256,
-	RADIOREGS(0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07,
-		  0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80),
-	PHYREGS(0xD503, 0xD103, 0xCD03, 0x2D04, 0x3104, 0x3604),
-  },
-  {	.channel		= 8,
-	.freq			= 2447, /* MHz */
-	.unk2			= 3263,
-	RADIOREGS(0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06,
-		  0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80),
-	PHYREGS(0xD703, 0xD303, 0xCF03, 0x2B04, 0x2F04, 0x3404),
-  },
-  {	.channel		= 9,
-	.freq			= 2452, /* MHz */
-	.unk2			= 3269,
-	RADIOREGS(0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06,
-		  0x80, 0xFF, 0x88, 0x09, 0x06, 0x80),
-	PHYREGS(0xD903, 0xD503, 0xD103, 0x2904, 0x2D04, 0x3104),
-  },
-  {	.channel		= 10,
-	.freq			= 2457, /* MHz */
-	.unk2			= 3276,
-	RADIOREGS(0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05,
-		  0x80, 0xFF, 0x88, 0x08, 0x05, 0x80),
-	PHYREGS(0xDB03, 0xD703, 0xD303, 0x2704, 0x2B04, 0x2F04),
-  },
-  {	.channel		= 11,
-	.freq			= 2462, /* MHz */
-	.unk2			= 3283,
-	RADIOREGS(0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04,
-		  0x80, 0xFF, 0x88, 0x08, 0x04, 0x80),
-	PHYREGS(0xDD03, 0xD903, 0xD503, 0x2404, 0x2904, 0x2D04),
-  },
-  {	.channel		= 12,
-	.freq			= 2467, /* MHz */
-	.unk2			= 3289,
-	RADIOREGS(0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03,
-		  0x80, 0xFF, 0x88, 0x08, 0x03, 0x80),
-	PHYREGS(0xDF03, 0xDB03, 0xD703, 0x2204, 0x2704, 0x2B04),
-  },
-  {	.channel		= 13,
-	.freq			= 2472, /* MHz */
-	.unk2			= 3296,
-	RADIOREGS(0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03,
-		  0x80, 0xFF, 0x88, 0x07, 0x03, 0x80),
-	PHYREGS(0xE103, 0xDD03, 0xD903, 0x2004, 0x2404, 0x2904),
-  },
-  {	.channel		= 14,
-	.freq			= 2484, /* MHz */
-	.unk2			= 3312,
-	RADIOREGS(0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
-		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01,
-		  0x80, 0xFF, 0x88, 0x07, 0x01, 0x80),
-	PHYREGS(0xE603, 0xE203, 0xDE03, 0x1B04, 0x1F04, 0x2404),
-  },
-};
-
-const struct b43_nphy_channeltab_entry_rev2 *
-b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel)
-{
-	const struct b43_nphy_channeltab_entry_rev2 *e;
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) {
-		e = &(b43_nphy_channeltab[i]);
-		if (e->channel == channel)
-			return e;
-	}
-
-	return NULL;
-}
-
-
 static const u8 b43_ntab_adjustpower0[] = {
 	0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
 	0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index 8fc1da9..4ec593b 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -3,7 +3,6 @@
 
 #include <linux/types.h>
 
-
 struct b43_phy_n_sfo_cfg {
 	u16 phy_bw1a;
 	u16 phy_bw2;
@@ -13,52 +12,6 @@
 	u16 phy_bw6;
 };
 
-struct b43_nphy_channeltab_entry_rev2 {
-	/* The channel number */
-	u8 channel;
-	/* The channel frequency in MHz */
-	u16 freq;
-	/* An unknown value */
-	u16 unk2;
-	/* Radio register values on channelswitch */
-	u8 radio_pll_ref;
-	u8 radio_rf_pllmod0;
-	u8 radio_rf_pllmod1;
-	u8 radio_vco_captail;
-	u8 radio_vco_cal1;
-	u8 radio_vco_cal2;
-	u8 radio_pll_lfc1;
-	u8 radio_pll_lfr1;
-	u8 radio_pll_lfc2;
-	u8 radio_lgbuf_cenbuf;
-	u8 radio_lgen_tune1;
-	u8 radio_lgen_tune2;
-	u8 radio_c1_lgbuf_atune;
-	u8 radio_c1_lgbuf_gtune;
-	u8 radio_c1_rx_rfr1;
-	u8 radio_c1_tx_pgapadtn;
-	u8 radio_c1_tx_mxbgtrim;
-	u8 radio_c2_lgbuf_atune;
-	u8 radio_c2_lgbuf_gtune;
-	u8 radio_c2_rx_rfr1;
-	u8 radio_c2_tx_pgapadtn;
-	u8 radio_c2_tx_mxbgtrim;
-	/* PHY register values on channelswitch */
-	struct b43_phy_n_sfo_cfg phy_regs;
-};
-
-struct b43_nphy_channeltab_entry_rev3 {
-	/* The channel number */
-	u8 channel;
-	/* The channel frequency in MHz */
-	u16 freq;
-	/* Radio register values on channelswitch */
-	/* TODO */
-	/* PHY register values on channelswitch */
-	struct b43_phy_n_sfo_cfg phy_regs;
-};
-
-
 struct b43_wldev;
 
 struct nphy_txiqcal_ladder {
@@ -82,18 +35,12 @@
 	u8 val_addr1;
 };
 
-/* Upload the default register value table.
- * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz
- * table is uploaded. If "ignore_uploadflag" is true, we upload any value
- * and ignore the "UPLOAD" flag. */
-void b2055_upload_inittab(struct b43_wldev *dev,
-			  bool ghz5, bool ignore_uploadflag);
-
-
-/* Get the NPHY Channel Switch Table entry for a channel number.
+/* Get the NPHY Channel Switch Table entry for a channel.
  * Returns NULL on failure to find an entry. */
 const struct b43_nphy_channeltab_entry_rev2 *
 b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
+const struct b43_nphy_channeltab_entry_rev3 *
+b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
 
 
 /* The N-PHY tables. */
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index 1f85ac5..f232618 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -334,6 +334,7 @@
 			.open	= b43legacy_debugfs_open,		\
 			.read	= b43legacy_debugfs_read,		\
 			.write	= b43legacy_debugfs_write,		\
+			.llseek = generic_file_llseek,			\
 		},						\
 		.file_struct_offset = offsetof(struct b43legacy_dfsentry, \
 					       file_##name),	\
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 1713f5f..67f18ec 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1623,6 +1623,7 @@
 
 static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 {
+	struct wiphy *wiphy = dev->wl->hw->wiphy;
 	const size_t hdr_len = sizeof(struct b43legacy_fw_header);
 	const __be32 *data;
 	unsigned int i;
@@ -1732,6 +1733,10 @@
 	dev->fw.rev = fwrev;
 	dev->fw.patch = fwpatch;
 
+	snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
+			dev->fw.rev, dev->fw.patch);
+	wiphy->hw_version = dev->dev->id.coreid;
+
 	return 0;
 
 error:
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index ba54d1b..bd8a413 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -12,7 +12,6 @@
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -437,7 +436,6 @@
 	int ret;
 
 	PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
 	ret = prism2_config(p_dev);
 	if (ret) {
@@ -468,74 +466,11 @@
 }
 
 
-/* run after a CARD_INSERTION event is received to configure the PCMCIA
- * socket and make the device available to the system */
-
-static int prism2_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cfg,
-			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
-			       void *priv_data)
+static int prism2_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
-	       "(default 0x%02X)\n", cfg->index, dflt->index);
-
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-		p_dev->conf.Status = CCSR_AUDIO_ENA;
-	}
-
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
-		    10000 && !ignore_cis_vcc) {
-			PDEBUG(DEBUG_EXTRA, "  Vcc mismatch - skipping"
-			       " this entry\n");
-			return -ENODEV;
-		}
-	} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] /
-		    10000 && !ignore_cis_vcc) {
-			PDEBUG(DEBUG_EXTRA, "  Vcc (default) mismatch "
-			       "- skipping this entry\n");
-			return -ENODEV;
-		}
-	}
-
-	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
-	       "dflt->io.nwin=%d\n",
-	       cfg->io.nwin, dflt->io.nwin);
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-					pcmcia_io_cfg_data_width(io->flags);
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-	}
-
-	/* This reserves IO space but doesn't actually enable it */
 	return pcmcia_request_io(p_dev);
 }
 
@@ -557,6 +492,10 @@
 	}
 
 	/* Look for an appropriate configuration table entry in the CIS */
+	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO |
+		CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+	if (ignore_cis_vcc)
+		link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 	ret = pcmcia_loop_config(link, prism2_config_check, NULL);
 	if (ret) {
 		if (!ignore_cis_vcc)
@@ -588,12 +527,7 @@
 	if (ret)
 		goto failed_unlock;
 
-	/*
-	 * 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.
-	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed_unlock;
 
@@ -602,20 +536,6 @@
 
 	spin_unlock_irqrestore(&local->irq_init_lock, flags);
 
-	/* Finally, report what we've done */
-	printk(KERN_INFO "%s: index 0x%02x: ",
-	       dev_info, link->conf.ConfigIndex);
-	if (link->conf.Vpp)
-		printk(", Vpp %d.%d", link->conf.Vpp / 10,
-		       link->conf.Vpp % 10);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %d", link->irq);
-	if (link->resource[0])
-		printk(" & %pR", link->resource[0]);
-	if (link->resource[1])
-		printk(" & %pR", link->resource[1]);
-	printk("\n");
-
 	local->shutdown = 0;
 
 	sandisk_enable_wireless(dev);
@@ -627,7 +547,7 @@
 	return ret;
 
  failed_unlock:
-	 spin_unlock_irqrestore(&local->irq_init_lock, flags);
+	spin_unlock_irqrestore(&local->irq_init_lock, flags);
  failed:
 	kfree(hw_priv);
 	prism2_release((u_long)link);
@@ -779,9 +699,7 @@
 
 
 static struct pcmcia_driver hostap_driver = {
-	.drv		= {
-		.name	= "hostap_cs",
-	},
+	.name		= "hostap_cs",
 	.probe		= hostap_cs_probe,
 	.remove		= prism2_detach,
 	.owner		= THIS_MODULE,
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index a85e43a..6038633 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1696,7 +1696,7 @@
 		hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE,
 				HFA384X_ROAMING_FIRMWARE);
 
-	return 0;
+	return ret;
 }
 
 #else /* !PRISM2_NO_STATION_MODES */
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 996e9d7..61915f3 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -1921,9 +1921,9 @@
 
 		bg_band->band = IEEE80211_BAND_2GHZ;
 		bg_band->n_channels = geo->bg_channels;
-		bg_band->channels =
-			kzalloc(geo->bg_channels *
-				sizeof(struct ieee80211_channel), GFP_KERNEL);
+		bg_band->channels = kcalloc(geo->bg_channels,
+					    sizeof(struct ieee80211_channel),
+					    GFP_KERNEL);
 		if (!bg_band->channels) {
 			ipw2100_down(priv);
 			return -ENOMEM;
@@ -3056,9 +3056,9 @@
 
 		packet = list_entry(element, struct ipw2100_tx_packet, list);
 
-		IPW_DEBUG_TX("using TBD at virt=%p, phys=%p\n",
+		IPW_DEBUG_TX("using TBD at virt=%p, phys=%04X\n",
 			     &txq->drv[txq->next],
-			     (void *)(txq->nic + txq->next *
+			     (u32) (txq->nic + txq->next *
 				      sizeof(struct ipw2100_bd)));
 
 		packet->index = txq->next;
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index cb2552a..8d6ed5f 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -11467,9 +11467,13 @@
 
 		bg_band->band = IEEE80211_BAND_2GHZ;
 		bg_band->n_channels = geo->bg_channels;
-		bg_band->channels =
-			kzalloc(geo->bg_channels *
-				sizeof(struct ieee80211_channel), GFP_KERNEL);
+		bg_band->channels = kcalloc(geo->bg_channels,
+					    sizeof(struct ieee80211_channel),
+					    GFP_KERNEL);
+		if (!bg_band->channels) {
+			rc = -ENOMEM;
+			goto out;
+		}
 		/* translate geo->bg to bg_band.channels */
 		for (i = 0; i < geo->bg_channels; i++) {
 			bg_band->channels[i].band = IEEE80211_BAND_2GHZ;
@@ -11502,9 +11506,13 @@
 
 		a_band->band = IEEE80211_BAND_5GHZ;
 		a_band->n_channels = geo->a_channels;
-		a_band->channels =
-			kzalloc(geo->a_channels *
-				sizeof(struct ieee80211_channel), GFP_KERNEL);
+		a_band->channels = kcalloc(geo->a_channels,
+					   sizeof(struct ieee80211_channel),
+					   GFP_KERNEL);
+		if (!a_band->channels) {
+			rc = -ENOMEM;
+			goto out;
+		}
 		/* translate geo->bg to a_band.channels */
 		for (i = 0; i < geo->a_channels; i++) {
 			a_band->channels[i].band = IEEE80211_BAND_2GHZ;
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index a51e4da..b823642 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -3,6 +3,9 @@
 	depends on PCI && MAC80211
 	select FW_LOADER
 
+menu "Debugging Options"
+	depends on IWLWIFI
+
 config IWLWIFI_DEBUG
 	bool "Enable full debugging output in iwlagn and iwl3945 drivers"
 	depends on IWLWIFI
@@ -36,6 +39,12 @@
 	  is a low-impact option that allows getting insight into the
 	  driver's state at runtime.
 
+config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
+        bool "Experimental uCode support"
+        depends on IWLWIFI && IWLWIFI_DEBUG
+        ---help---
+	  Enable use of experimental ucode for testing and debugging.
+
 config IWLWIFI_DEVICE_TRACING
 	bool "iwlwifi device access tracing"
 	depends on IWLWIFI
@@ -53,6 +62,7 @@
 
 	  If unsure, say Y so we can help you better when problems
 	  occur.
+endmenu
 
 config IWLAGN
 	tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)"
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 728bb85..63edbe2 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -12,6 +12,7 @@
 iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
 iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
 iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.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
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 0b779a4..db54091 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -50,14 +50,20 @@
 
 /* Highest firmware API version supported */
 #define IWL1000_UCODE_API_MAX 3
+#define IWL100_UCODE_API_MAX 5
 
 /* Lowest firmware API version supported */
 #define IWL1000_UCODE_API_MIN 1
+#define IWL100_UCODE_API_MIN 5
 
 #define IWL1000_FW_PRE "iwlwifi-1000-"
 #define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode"
 #define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api)
 
+#define IWL100_FW_PRE "iwlwifi-100-"
+#define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode"
+#define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api)
+
 
 /*
  * For 1000, use advance thermal throttling critical temperature threshold,
@@ -120,17 +126,17 @@
 {
 	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
 	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
-		priv->cfg->num_of_queues =
+		priv->cfg->base_params->num_of_queues =
 			priv->cfg->mod_params->num_of_queues;
 
-	priv->hw_params.max_txq_num = priv->cfg->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->num_of_queues *
+			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->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
+	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
 
 	priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
 	priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
@@ -145,8 +151,7 @@
 	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
 	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
 
-	if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
-		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+	iwl1000_set_ct_threshold(priv);
 
 	/* Set initial sensitivity parameters */
 	/* Set initial calibration set */
@@ -189,9 +194,7 @@
 	.update_chain_flags = iwl_update_chain_flags,
 	.apm_ops = {
 		.init = iwl_apm_init,
-		.stop = iwl_apm_stop,
 		.config = iwl1000_nic_config,
-		.set_pwr_src = iwl_set_pwr_src,
 	},
 	.eeprom_ops = {
 		.regulatory_bands = {
@@ -203,7 +206,6 @@
 			EEPROM_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REG_BAND_52_HT40_CHANNELS
 		},
-		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
 		.release_semaphore = iwlcore_eeprom_release_semaphore,
 		.calib_version	= iwlagn_eeprom_calib_version,
@@ -214,21 +216,26 @@
 	.config_ap = iwl_config_ap,
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
-		.set_ct_kill = iwl1000_set_ct_threshold,
 	 },
 	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_station = iwl_update_bcast_station,
+	.update_bcast_stations = iwl_update_bcast_stations,
 	.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,
 	},
 	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.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 = {
+		.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 iwl1000_ops = {
@@ -238,29 +245,16 @@
 	.led = &iwlagn_led_ops,
 };
 
-struct iwl_cfg iwl1000_bgn_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
-	.fw_name_pre = IWL1000_FW_PRE,
-	.ucode_api_max = IWL1000_UCODE_API_MAX,
-	.ucode_api_min = IWL1000_UCODE_API_MIN,
-	.sku = IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl1000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
+static struct iwl_base_params iwl1000_base_params = {
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
-	.valid_tx_ant = ANT_A,
-	.valid_rx_ant = ANT_AB,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
 	.set_l0s = true,
 	.use_bsm = false,
 	.max_ll_items = OTP_MAX_LL_ITEMS_1000,
 	.shadow_ram_support = false,
-	.ht_greenfield_support = true,
 	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.support_ct_kill_exit = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
@@ -271,6 +265,26 @@
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
 };
+static struct iwl_ht_params iwl1000_ht_params = {
+	.ht_greenfield_support = true,
+	.use_rts_for_aggregation = true, /* use rts/cts protection */
+};
+
+struct iwl_cfg iwl1000_bgn_cfg = {
+	.name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
+	.fw_name_pre = IWL1000_FW_PRE,
+	.ucode_api_max = IWL1000_UCODE_API_MAX,
+	.ucode_api_min = IWL1000_UCODE_API_MIN,
+	.sku = IWL_SKU_G|IWL_SKU_N,
+	.valid_tx_ant = ANT_A,
+	.valid_rx_ant = ANT_AB,
+	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
+	.ops = &iwl1000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl1000_base_params,
+	.ht_params = &iwl1000_ht_params,
+};
 
 struct iwl_cfg iwl1000_bg_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
@@ -278,30 +292,45 @@
 	.ucode_api_max = IWL1000_UCODE_API_MAX,
 	.ucode_api_min = IWL1000_UCODE_API_MIN,
 	.sku = IWL_SKU_G,
-	.ops = &iwl1000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_A,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
-	.set_l0s = true,
-	.use_bsm = false,
-	.max_ll_items = OTP_MAX_LL_ITEMS_1000,
-	.shadow_ram_support = false,
-	.led_compensation = 51,
-	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.support_ct_kill_exit = true,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
-	.max_event_log_size = 128,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
+	.ops = &iwl1000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl1000_base_params,
+};
+
+struct iwl_cfg iwl100_bgn_cfg = {
+	.name = "Intel(R) 100 Series 1x1 BGN",
+	.fw_name_pre = IWL100_FW_PRE,
+	.ucode_api_max = IWL100_UCODE_API_MAX,
+	.ucode_api_min = IWL100_UCODE_API_MIN,
+	.sku = IWL_SKU_G|IWL_SKU_N,
+	.valid_tx_ant = ANT_A,
+	.valid_rx_ant = ANT_A,
+	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
+	.ops = &iwl1000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl1000_base_params,
+	.ht_params = &iwl1000_ht_params,
+};
+
+struct iwl_cfg iwl100_bg_cfg = {
+	.name = "Intel(R) 100 Series 1x1 BG",
+	.fw_name_pre = IWL100_FW_PRE,
+	.ucode_api_max = IWL100_UCODE_API_MAX,
+	.ucode_api_min = IWL100_UCODE_API_MIN,
+	.sku = IWL_SKU_G,
+	.valid_tx_ant = ANT_A,
+	.valid_rx_ant = ANT_A,
+	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
+	.ops = &iwl1000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl1000_base_params,
 };
 
 MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index 7c731a7..65b5834 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -62,7 +62,7 @@
  *****************************************************************************/
 /*
  * Please use this file (iwl-3945-hw.h) only for hardware-related definitions.
- * Please use iwl-3945-commands.h for uCode API definitions.
+ * Please use iwl-commands.h for uCode API definitions.
  * Please use iwl-3945.h for driver implementation definitions.
  */
 
@@ -226,6 +226,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
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 8e84a08..1f3e7e3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -343,7 +343,7 @@
 	int i;
 
 	IWL_DEBUG_INFO(priv, "enter\n");
-	if (sta_id == priv->hw_params.bcast_sta_id)
+	if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
 		goto out;
 
 	psta = (struct iwl3945_sta_priv *) sta->drv_priv;
@@ -873,6 +873,7 @@
 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,
@@ -932,7 +933,7 @@
 
 	rcu_read_lock();
 
-	sta = ieee80211_find_sta(priv->vif,
+	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");
@@ -949,7 +950,8 @@
 	switch (priv->band) {
 	case IEEE80211_BAND_2GHZ:
 		/* TODO: this always does G, not a regression */
-		if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
+		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
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 8ccfcd0..176e525 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -87,6 +87,15 @@
 	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)
@@ -245,7 +254,7 @@
 		break;
 	case IEEE80211_BAND_2GHZ:
 		if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
-		    iwl_is_associated(priv)) {
+		    iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
 			if (rate == IWL_RATE_11M_INDEX)
 				next_rate = IWL_RATE_5M_INDEX;
 		}
@@ -273,7 +282,7 @@
 	struct iwl_queue *q = &txq->q;
 	struct iwl_tx_info *tx_info;
 
-	BUG_ON(txq_id == IWL_CMD_QUEUE_NUM);
+	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)) {
@@ -285,7 +294,7 @@
 	}
 
 	if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
-			(txq_id != IWL_CMD_QUEUE_NUM) &&
+			(txq_id != IWL39_CMD_QUEUE_NUM) &&
 			priv->mac80211_registered)
 		iwl_wake_queue(priv, txq_id);
 }
@@ -339,7 +348,7 @@
 	IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index);
 	iwl3945_tx_queue_reclaim(priv, txq_id, index);
 
-	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
+	if (status & TX_ABORT_REQUIRED_MSK)
 		IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
 }
 
@@ -406,7 +415,7 @@
 	unsigned int plcp_msec;
 	unsigned long plcp_received_jiffies;
 
-	if (priv->cfg->plcp_delta_threshold ==
+	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;
@@ -432,7 +441,7 @@
 
 		if ((combined_plcp_delta > 0) &&
 			((combined_plcp_delta * 100) / plcp_msec) >
-			priv->cfg->plcp_delta_threshold) {
+			priv->cfg->base_params->plcp_delta_threshold) {
 			/*
 			 * if plcp_err exceed the threshold, the following
 			 * data is printed in csv format:
@@ -444,7 +453,7 @@
 			 */
 			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
 				"%u, %d, %u mSecs\n",
-				priv->cfg->plcp_delta_threshold,
+				priv->cfg->base_params->plcp_delta_threshold,
 				le32_to_cpu(current_stat.rx.ofdm.plcp_err),
 				combined_plcp_delta, plcp_msec);
 			/*
@@ -760,7 +769,7 @@
 		data_retry_limit = IWL_DEFAULT_TX_RETRY;
 	tx_cmd->data_retry_limit = data_retry_limit;
 
-	if (tx_id >= IWL_CMD_QUEUE_NUM)
+	if (tx_id >= IWL39_CMD_QUEUE_NUM)
 		rts_retry_limit = 3;
 	else
 		rts_retry_limit = 7;
@@ -807,9 +816,12 @@
 	return sta_id;
 }
 
-static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
+static void iwl3945_set_pwr_vmain(struct iwl_priv *priv)
 {
-	if (src == IWL_PWR_SRC_VAUX) {
+/*
+ * (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,
@@ -819,16 +831,14 @@
 				     CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
 				     CSR_GPIO_IN_BIT_AUX_POWER, 5000);
 		}
-	} else {
-		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 */
-	}
+	iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+			APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+			~APMG_PS_CTRL_MSK_PWR_SRC);
 
-	return 0;
+	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)
@@ -909,7 +919,7 @@
 
 	/* Tx queue(s) */
 	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-		slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
+		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);
@@ -1022,9 +1032,7 @@
 	priv->cfg->ops->lib->apm_ops.init(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
-	if (rc)
-		return rc;
+	iwl3945_set_pwr_vmain(priv);
 
 	priv->cfg->ops->lib->apm_ops.config(priv);
 
@@ -1072,7 +1080,7 @@
 	if (priv->txq)
 		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
 		     txq_id++)
-			if (txq_id == IWL_CMD_QUEUE_NUM)
+			if (txq_id == IWL39_CMD_QUEUE_NUM)
 				iwl_cmd_queue_free(priv);
 			else
 				iwl_tx_queue_free(priv, txq_id);
@@ -1439,17 +1447,18 @@
 	int rate_idx, i;
 	const struct iwl_channel_info *ch_info = NULL;
 	struct iwl3945_txpowertable_cmd txpower = {
-		.channel = priv->active_rxon.channel,
+		.channel = priv->contexts[IWL_RXON_CTX_BSS].active.channel,
 	};
+	u16 chan;
+
+	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,
-				       le16_to_cpu(priv->active_rxon.channel));
+	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",
-			le16_to_cpu(priv->active_rxon.channel), priv->band);
+			chan, priv->band);
 		return -EINVAL;
 	}
 
@@ -1710,7 +1719,8 @@
 	return 0;
 }
 
-static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
+static int iwl3945_send_rxon_assoc(struct iwl_priv *priv,
+				   struct iwl_rxon_context *ctx)
 {
 	int rc = 0;
 	struct iwl_rx_packet *pkt;
@@ -1721,8 +1731,8 @@
 		.flags = CMD_WANT_SKB,
 		.data = &rxon_assoc,
 	};
-	const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
-	const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
+	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) &&
@@ -1732,10 +1742,10 @@
 		return 0;
 	}
 
-	rxon_assoc.flags = priv->staging_rxon.flags;
-	rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
-	rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
-	rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
+	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);
@@ -1761,14 +1771,13 @@
  * function correctly transitions out of the RXON_ASSOC_MSK state if
  * a HW tune is required based on the RXON structure changes.
  */
-static int iwl3945_commit_rxon(struct iwl_priv *priv)
+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 *)&priv->active_rxon;
-	struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon;
+	struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active;
+	struct iwl3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
 	int rc = 0;
-	bool new_assoc =
-		!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
+	bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
 
 	if (!iwl_is_alive(priv))
 		return -1;
@@ -1781,7 +1790,7 @@
 	    ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
 	staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
 
-	rc = iwl_check_rxon_cmd(priv);
+	rc = iwl_check_rxon_cmd(priv, ctx);
 	if (rc) {
 		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
 		return -EINVAL;
@@ -1790,8 +1799,9 @@
 	/* 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)) {
-		rc = iwl_send_rxon_assoc(priv);
+	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);
@@ -1807,7 +1817,7 @@
 	 * 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) && new_assoc) {
+	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;
 
@@ -1819,7 +1829,7 @@
 		active_rxon->reserved5 = 0;
 		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
 				      sizeof(struct iwl3945_rxon_cmd),
-				      &priv->active_rxon);
+				      &priv->contexts[IWL_RXON_CTX_BSS].active);
 
 		/* If the mask clearing failed then we set
 		 * active_rxon back to what it was previously */
@@ -1829,8 +1839,9 @@
 				  "configuration (%d).\n", rc);
 			return rc;
 		}
-		iwl_clear_ucode_stations(priv);
-		iwl_restore_stations(priv);
+		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"
@@ -1848,7 +1859,7 @@
 	staging_rxon->reserved4 = 0;
 	staging_rxon->reserved5 = 0;
 
-	iwl_set_rxon_hwcrypto(priv, !iwl3945_mod_params.sw_crypto);
+	iwl_set_rxon_hwcrypto(priv, ctx, !iwl3945_mod_params.sw_crypto);
 
 	/* Apply the new configuration */
 	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
@@ -1862,8 +1873,9 @@
 	memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
 
 	if (!new_assoc) {
-		iwl_clear_ucode_stations(priv);
-		iwl_restore_stations(priv);
+		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
@@ -2295,6 +2307,32 @@
 	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)
 {
@@ -2302,8 +2340,8 @@
 	int ret;
 
 	if (add) {
-		ret = iwl_add_bssid_station(priv, vif->bss_conf.bssid, false,
-					    &vif_priv->ibss_bssid_sta_id);
+		ret = iwl3945_add_bssid_station(priv, vif->bss_conf.bssid,
+						&vif_priv->ibss_bssid_sta_id);
 		if (ret)
 			return ret;
 
@@ -2366,7 +2404,7 @@
 		 * 1M CCK rates */
 
 		if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
-		    iwl_is_associated(priv)) {
+		    iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
 
 			index = IWL_FIRST_CCK_RATE;
 			for (i = IWL_RATE_6M_INDEX_TABLE;
@@ -2414,14 +2452,16 @@
 	}
 
 	/* Assign number of Usable TX queues */
-	priv->hw_params.max_txq_num = priv->cfg->num_of_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->hw_params.bcast_sta_id = IWL3945_BROADCAST_ID;
+	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;
@@ -2439,7 +2479,8 @@
 	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->hw_params.bcast_sta_id;
+	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,
@@ -2663,9 +2704,7 @@
 	.dump_nic_error_log = iwl3945_dump_nic_error_log,
 	.apm_ops = {
 		.init = iwl3945_apm_init,
-		.stop = iwl_apm_stop,
 		.config = iwl3945_nic_config,
-		.set_pwr_src = iwl3945_set_pwr_src,
 	},
 	.eeprom_ops = {
 		.regulatory_bands = {
@@ -2677,7 +2716,6 @@
 			EEPROM_REGULATORY_BAND_NO_HT40,
 			EEPROM_REGULATORY_BAND_NO_HT40,
 		},
-		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
 		.release_semaphore = iwl3945_eeprom_release_semaphore,
 		.query_addr = iwlcore_eeprom_query_addr,
@@ -2703,6 +2741,7 @@
 	.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
 	.tx_cmd_protection = iwlcore_tx_cmd_protection,
 	.request_scan = iwl3945_request_scan,
+	.post_scan = iwl3945_post_scan,
 };
 
 static const struct iwl_ops iwl3945_ops = {
@@ -2712,22 +2751,13 @@
 	.led = &iwl3945_led_ops,
 };
 
-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,
+static struct iwl_base_params iwl3945_base_params = {
 	.eeprom_size = IWL3945_EEPROM_IMG_SIZE,
-	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
-	.ops = &iwl3945_ops,
 	.num_of_queues = IWL39_NUM_QUEUES,
-	.mod_params = &iwl3945_mod_params,
 	.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
 	.set_l0s = false,
 	.use_bsm = true,
 	.use_isr_legacy = true,
-	.ht_greenfield_support = false,
 	.led_compensation = 64,
 	.broken_powersave = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
@@ -2736,25 +2766,28 @@
 	.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,
+};
+
 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_size = IWL3945_EEPROM_IMG_SIZE,
 	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
 	.ops = &iwl3945_ops,
-	.num_of_queues = IWL39_NUM_QUEUES,
 	.mod_params = &iwl3945_mod_params,
-	.use_isr_legacy = true,
-	.ht_greenfield_support = false,
-	.led_compensation = 64,
-	.broken_powersave = true,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.tx_power_by_driver = true,
+	.base_params = &iwl3945_base_params,
 };
 
 DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index bb2aeeb..09391f0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -138,8 +138,6 @@
 #define	DEFAULT_SHORT_RETRY_LIMIT 7U
 #define	DEFAULT_LONG_RETRY_LIMIT  4U
 
-#include "iwl-agn-rs.h"
-
 #define IWL_TX_FIFO_AC0	0
 #define IWL_TX_FIFO_AC1	1
 #define IWL_TX_FIFO_AC2	2
@@ -271,6 +269,9 @@
 extern void iwl3945_config_ap(struct iwl_priv *priv,
 			      struct ieee80211_vif *vif);
 
+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
@@ -295,7 +296,11 @@
 extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
 
 /* scanning */
-void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
+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"
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index d92b729..b207e3e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -43,7 +43,7 @@
 #include "iwl-core.h"
 #include "iwl-io.h"
 #include "iwl-helpers.h"
-#include "iwl-calib.h"
+#include "iwl-agn-calib.h"
 #include "iwl-sta.h"
 #include "iwl-agn-led.h"
 #include "iwl-agn.h"
@@ -347,7 +347,7 @@
 	struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
 
 	if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
-	     iwl_is_associated(priv)) {
+	    iwl_is_any_associated(priv)) {
 		struct iwl_calib_diff_gain_cmd cmd;
 
 		/* clear data for chain noise calibration algorithm */
@@ -576,7 +576,7 @@
 	/* Activate all Tx DMA/FIFO channels */
 	priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6));
 
-	iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+	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));
@@ -587,6 +587,7 @@
 	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];
 
@@ -646,17 +647,17 @@
 {
 	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
 	    priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES)
-		priv->cfg->num_of_queues =
+		priv->cfg->base_params->num_of_queues =
 			priv->cfg->mod_params->num_of_queues;
 
-	priv->hw_params.max_txq_num = priv->cfg->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->num_of_queues *
+			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->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
+	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;
@@ -668,8 +669,8 @@
 	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;
-	if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
-		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+
+	iwl4965_set_ct_threshold(priv);
 
 	priv->hw_params.sens = &iwl4965_sensitivity;
 	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
@@ -1374,6 +1375,7 @@
 	u8 band = 0;
 	bool is_ht40 = false;
 	u8 ctrl_chan_high = 0;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
 	if (test_bit(STATUS_SCANNING, &priv->status)) {
 		/* If this gets hit a lot, switch it to a BUG() and catch
@@ -1385,17 +1387,16 @@
 
 	band = priv->band == IEEE80211_BAND_2GHZ;
 
-	is_ht40 =  is_ht40_channel(priv->active_rxon.flags);
+	is_ht40 = is_ht40_channel(ctx->active.flags);
 
-	if (is_ht40 &&
-	    (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+	if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
 		ctrl_chan_high = 1;
 
 	cmd.band = band;
-	cmd.channel = priv->active_rxon.channel;
+	cmd.channel = ctx->active.channel;
 
 	ret = iwl4965_fill_txpower_tbl(priv, band,
-				le16_to_cpu(priv->active_rxon.channel),
+				le16_to_cpu(ctx->active.channel),
 				is_ht40, ctrl_chan_high, &cmd.tx_power);
 	if (ret)
 		goto out;
@@ -1406,12 +1407,13 @@
 	return ret;
 }
 
-static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
+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 = &priv->staging_rxon;
-	const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
+	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) &&
@@ -1426,16 +1428,16 @@
 		return 0;
 	}
 
-	rxon_assoc.flags = priv->staging_rxon.flags;
-	rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
-	rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
-	rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
+	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 =
-	    priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
+	    ctx->staging.ofdm_ht_single_stream_basic_rates;
 	rxon_assoc.ofdm_ht_dual_stream_basic_rates =
-	    priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
-	rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
+	    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);
@@ -1448,6 +1450,7 @@
 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;
@@ -1458,22 +1461,22 @@
 	u16 ch;
 	u32 tsf_low;
 	u8 switch_count;
-	u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
-	struct ieee80211_vif *vif = priv->vif;
+	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(priv->staging_rxon.flags);
+	is_ht40 = is_ht40_channel(ctx->staging.flags);
 
 	if (is_ht40 &&
-	    (priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+	    (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
 		ctrl_chan_high = 1;
 
 	cmd.band = band;
 	cmd.expect_beacon = 0;
-	ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
+	ch = ch_switch->channel->hw_value;
 	cmd.channel = cpu_to_le16(ch);
-	cmd.rxon_flags = priv->staging_rxon.flags;
-	cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
+	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;
 	/*
@@ -1508,7 +1511,7 @@
 		cmd.expect_beacon = is_channel_radar(ch_info);
 	else {
 		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
-			priv->active_rxon.channel, ch);
+			ctx->active.channel, ch);
 		return -EFAULT;
 	}
 
@@ -1721,13 +1724,13 @@
 				   u16 ssn_idx, u8 tx_fifo)
 {
 	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
-	    (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
-	     <= 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->num_of_ampdu_queues - 1);
+			priv->cfg->base_params->num_of_ampdu_queues - 1);
 		return -EINVAL;
 	}
 
@@ -1789,13 +1792,13 @@
 	int ret;
 
 	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
-	    (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
-	     <= 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->num_of_ampdu_queues - 1);
+			priv->cfg->base_params->num_of_ampdu_queues - 1);
 		return -EINVAL;
 	}
 
@@ -2007,7 +2010,7 @@
 		start = IWL_STA_ID;
 
 	if (is_broadcast_ether_addr(addr))
-		return priv->hw_params.bcast_sta_id;
+		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++)
@@ -2213,11 +2216,23 @@
 
 static struct iwl_hcmd_ops iwl4965_hcmd = {
 	.rxon_assoc = iwl4965_send_rxon_assoc,
-	.commit_rxon = iwl_commit_rxon,
-	.set_rxon_chain = iwl_set_rxon_chain,
+	.commit_rxon = iwlagn_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 struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
 	.get_hcmd_size = iwl4965_get_hcmd_size,
 	.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
@@ -2226,6 +2241,7 @@
 	.tx_cmd_protection = iwlcore_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 = {
@@ -2250,9 +2266,7 @@
 	.set_channel_switch = iwl4965_hw_channel_switch,
 	.apm_ops = {
 		.init = iwl_apm_init,
-		.stop = iwl_apm_stop,
 		.config = iwl4965_nic_config,
-		.set_pwr_src = iwl_set_pwr_src,
 	},
 	.eeprom_ops = {
 		.regulatory_bands = {
@@ -2264,7 +2278,6 @@
 			EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
 			EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
 		},
-		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
 		.release_semaphore = iwlcore_eeprom_release_semaphore,
 		.calib_version = iwl4965_eeprom_calib_version,
@@ -2277,15 +2290,15 @@
 	.isr = iwl_isr_legacy,
 	.temp_ops = {
 		.temperature = iwl4965_temperature_calib,
-		.set_ct_kill = iwl4965_set_ct_threshold,
 	},
 	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_station = iwl_update_bcast_station,
+	.update_bcast_stations = iwl_update_bcast_stations,
 	.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,
 	},
 	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.check_plcp_health = iwl_good_plcp_health,
@@ -2298,26 +2311,14 @@
 	.led = &iwlagn_led_ops,
 };
 
-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,
+static struct iwl_base_params iwl4965_base_params = {
 	.eeprom_size = IWL4965_EEPROM_IMG_SIZE,
-	.eeprom_ver = EEPROM_4965_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
-	.ops = &iwl4965_ops,
 	.num_of_queues = IWL49_NUM_QUEUES,
 	.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_ABC,
 	.pll_cfg_val = 0,
 	.set_l0s = true,
 	.use_bsm = true,
 	.use_isr_legacy = true,
-	.ht_greenfield_support = false,
 	.broken_powersave = true,
 	.led_compensation = 61,
 	.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
@@ -2329,6 +2330,21 @@
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = 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,
 	/*
 	 * Force use of chains B and C for scan RX on 5 GHz band
 	 * because the device has off-channel reception on chain A.
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index 146e643..3975e45 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -62,7 +62,7 @@
  *****************************************************************************/
 /*
  * Please use this file (iwl-5000-hw.h) only for hardware-related definitions.
- * Use iwl-5000-commands.h for uCode API definitions.
+ * Use iwl-commands.h for uCode API definitions.
  */
 
 #ifndef __iwl_5000_hw_h__
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 48bdcd8..fd9fbc9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -170,17 +170,17 @@
 {
 	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
 	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
-		priv->cfg->num_of_queues =
+		priv->cfg->base_params->num_of_queues =
 			priv->cfg->mod_params->num_of_queues;
 
-	priv->hw_params.max_txq_num = priv->cfg->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->num_of_queues *
+			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->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
+	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
 
 	priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
 	priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
@@ -195,8 +195,7 @@
 	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
 	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
 
-	if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
-		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+	iwl5000_set_ct_threshold(priv);
 
 	/* Set initial sensitivity parameters */
 	/* Set initial calibration set */
@@ -217,17 +216,17 @@
 {
 	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
 	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
-		priv->cfg->num_of_queues =
+		priv->cfg->base_params->num_of_queues =
 			priv->cfg->mod_params->num_of_queues;
 
-	priv->hw_params.max_txq_num = priv->cfg->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->num_of_queues *
+			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->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
+	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
 
 	priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
 	priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
@@ -242,8 +241,7 @@
 	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
 	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
 
-	if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
-		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+	iwl5150_set_ct_threshold(priv);
 
 	/* Set initial sensitivity parameters */
 	/* Set initial calibration set */
@@ -275,14 +273,19 @@
 static int iwl5000_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 iwl5000_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(priv->rxon_timing.beacon_interval);
-	struct ieee80211_vif *vif = priv->vif;
+	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),
@@ -291,12 +294,12 @@
 	};
 
 	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
-	ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
+	ch = ch_switch->channel->hw_value;
 	IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
-		priv->active_rxon.channel, ch);
+		      ctx->active.channel, ch);
 	cmd.channel = cpu_to_le16(ch);
-	cmd.rxon_flags = priv->staging_rxon.flags;
-	cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
+	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;
 	/*
@@ -331,7 +334,7 @@
 		cmd.expect_beacon = is_channel_radar(ch_info);
 	else {
 		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
-			priv->active_rxon.channel, ch);
+			ctx->active.channel, ch);
 		return -EFAULT;
 	}
 	priv->switch_rxon.channel = cmd.channel;
@@ -365,9 +368,7 @@
 	.set_channel_switch = iwl5000_hw_channel_switch,
 	.apm_ops = {
 		.init = iwl_apm_init,
-		.stop = iwl_apm_stop,
 		.config = iwl5000_nic_config,
-		.set_pwr_src = iwl_set_pwr_src,
 	},
 	.eeprom_ops = {
 		.regulatory_bands = {
@@ -379,7 +380,6 @@
 			EEPROM_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REG_BAND_52_HT40_CHANNELS
 		},
-		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
 		.release_semaphore = iwlcore_eeprom_release_semaphore,
 		.calib_version	= iwlagn_eeprom_calib_version,
@@ -390,21 +390,26 @@
 	.config_ap = iwl_config_ap,
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
-		.set_ct_kill = iwl5000_set_ct_threshold,
 	 },
 	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_station = iwl_update_bcast_station,
+	.update_bcast_stations = iwl_update_bcast_stations,
 	.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,
 	},
 	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.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 = {
+		.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 struct iwl_lib_ops iwl5150_lib = {
@@ -431,9 +436,7 @@
 	.set_channel_switch = iwl5000_hw_channel_switch,
 	.apm_ops = {
 		.init = iwl_apm_init,
-		.stop = iwl_apm_stop,
 		.config = iwl5000_nic_config,
-		.set_pwr_src = iwl_set_pwr_src,
 	},
 	.eeprom_ops = {
 		.regulatory_bands = {
@@ -445,7 +448,6 @@
 			EEPROM_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REG_BAND_52_HT40_CHANNELS
 		},
-		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
 		.release_semaphore = iwlcore_eeprom_release_semaphore,
 		.calib_version	= iwlagn_eeprom_calib_version,
@@ -456,20 +458,26 @@
 	.config_ap = iwl_config_ap,
 	.temp_ops = {
 		.temperature = iwl5150_temperature,
-		.set_ct_kill = iwl5150_set_ct_threshold,
 	 },
 	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_station = iwl_update_bcast_station,
+	.update_bcast_stations = iwl_update_bcast_stations,
 	.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,
 	},
 	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.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 = {
+		.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 iwl5000_ops = {
@@ -486,27 +494,14 @@
 	.led = &iwlagn_led_ops,
 };
 
-struct iwl_cfg iwl5300_agn_cfg = {
-	.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
-	.fw_name_pre = IWL5000_FW_PRE,
-	.ucode_api_max = IWL5000_UCODE_API_MAX,
-	.ucode_api_min = IWL5000_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl5000_ops,
+static struct iwl_base_params iwl5000_base_params = {
 	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
-	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
-	.valid_tx_ant = ANT_ABC,
-	.valid_rx_ant = ANT_ABC,
 	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
 	.set_l0s = true,
 	.use_bsm = false,
-	.ht_greenfield_support = true,
 	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
 	.chain_noise_scale = 1000,
@@ -516,6 +511,26 @@
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
 };
+static struct iwl_ht_params iwl5000_ht_params = {
+	.ht_greenfield_support = true,
+	.use_rts_for_aggregation = true, /* use rts/cts protection */
+};
+
+struct iwl_cfg iwl5300_agn_cfg = {
+	.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
+	.fw_name_pre = IWL5000_FW_PRE,
+	.ucode_api_max = IWL5000_UCODE_API_MAX,
+	.ucode_api_min = IWL5000_UCODE_API_MIN,
+	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
+	.valid_tx_ant = ANT_ABC,
+	.valid_rx_ant = ANT_ABC,
+	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
+	.ops = &iwl5000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl5000_base_params,
+	.ht_params = &iwl5000_ht_params,
+};
 
 struct iwl_cfg iwl5100_bgn_cfg = {
 	.name = "Intel(R) WiFi Link 5100 BGN",
@@ -523,29 +538,14 @@
 	.ucode_api_max = IWL5000_UCODE_API_MAX,
 	.ucode_api_min = IWL5000_UCODE_API_MIN,
 	.sku = IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl5000_ops,
-	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
-	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_B,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
-	.set_l0s = true,
-	.use_bsm = false,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
+	.ops = &iwl5000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl5000_base_params,
+	.ht_params = &iwl5000_ht_params,
 };
 
 struct iwl_cfg iwl5100_abg_cfg = {
@@ -554,27 +554,13 @@
 	.ucode_api_max = IWL5000_UCODE_API_MAX,
 	.ucode_api_min = IWL5000_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G,
-	.ops = &iwl5000_ops,
-	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
-	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_B,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
-	.set_l0s = true,
-	.use_bsm = false,
-	.led_compensation = 51,
-	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
+	.ops = &iwl5000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl5000_base_params,
 };
 
 struct iwl_cfg iwl5100_agn_cfg = {
@@ -583,29 +569,14 @@
 	.ucode_api_max = IWL5000_UCODE_API_MAX,
 	.ucode_api_min = IWL5000_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl5000_ops,
-	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
-	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_B,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
-	.set_l0s = true,
-	.use_bsm = false,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
+	.ops = &iwl5000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl5000_base_params,
+	.ht_params = &iwl5000_ht_params,
 };
 
 struct iwl_cfg iwl5350_agn_cfg = {
@@ -614,29 +585,14 @@
 	.ucode_api_max = IWL5000_UCODE_API_MAX,
 	.ucode_api_min = IWL5000_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl5000_ops,
-	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
-	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_ABC,
 	.valid_rx_ant = ANT_ABC,
-	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
-	.set_l0s = true,
-	.use_bsm = false,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
+	.ops = &iwl5000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl5000_base_params,
+	.ht_params = &iwl5000_ht_params,
 };
 
 struct iwl_cfg iwl5150_agn_cfg = {
@@ -645,29 +601,14 @@
 	.ucode_api_max = IWL5150_UCODE_API_MAX,
 	.ucode_api_min = IWL5150_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl5150_ops,
-	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
-	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_A,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
-	.set_l0s = true,
-	.use_bsm = false,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
+	.ops = &iwl5150_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl5000_base_params,
+	.ht_params = &iwl5000_ht_params,
 	.need_dc_calib = true,
 };
 
@@ -677,27 +618,13 @@
 	.ucode_api_max = IWL5150_UCODE_API_MAX,
 	.ucode_api_min = IWL5150_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G,
-	.ops = &iwl5150_ops,
-	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
-	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_A,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
-	.set_l0s = true,
-	.use_bsm = false,
-	.led_compensation = 51,
-	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
+	.ops = &iwl5150_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl5000_base_params,
 	.need_dc_calib = true,
 };
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
index ddba399..47891e1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
@@ -62,7 +62,7 @@
  *****************************************************************************/
 /*
  * Please use this file (iwl-6000-hw.h) only for hardware-related definitions.
- * Use iwl-5000-commands.h for uCode API definitions.
+ * Use iwl-commands.h for uCode API definitions.
  */
 
 #ifndef __iwl_6000_hw_h__
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index cee06b9..11e6532 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -51,13 +51,15 @@
 
 /* Highest firmware API version supported */
 #define IWL6000_UCODE_API_MAX 4
-#define IWL6050_UCODE_API_MAX 4
-#define IWL6000G2_UCODE_API_MAX 4
+#define IWL6050_UCODE_API_MAX 5
+#define IWL6000G2_UCODE_API_MAX 5
+#define IWL130_UCODE_API_MAX 5
 
 /* Lowest firmware API version supported */
 #define IWL6000_UCODE_API_MIN 4
 #define IWL6050_UCODE_API_MIN 4
 #define IWL6000G2_UCODE_API_MIN 4
+#define IWL130_UCODE_API_MIN 5
 
 #define IWL6000_FW_PRE "iwlwifi-6000-"
 #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
@@ -75,6 +77,9 @@
 #define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode"
 #define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api)
 
+#define IWL130_FW_PRE "iwlwifi-130-"
+#define _IWL130_MODULE_FIRMWARE(api) IWL130_FW_PRE #api ".ucode"
+#define IWL130_MODULE_FIRMWARE(api) _IWL130_MODULE_FIRMWARE(api)
 
 static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
 {
@@ -83,15 +88,24 @@
 	priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
 }
 
-/* Indicate calibration version to uCode. */
-static void iwl6000_set_calib_version(struct iwl_priv *priv)
+static void iwl6050_additional_nic_config(struct iwl_priv *priv)
 {
-	if (priv->cfg->need_dc_calib &&
-	    (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6))
+	/* Indicate calibration version to uCode. */
+	if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)
 		iwl_set_bit(priv, CSR_GP_DRIVER_REG,
 				CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
 }
 
+static void iwl6050g2_additional_nic_config(struct iwl_priv *priv)
+{
+	/* Indicate calibration version to uCode. */
+	if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)
+		iwl_set_bit(priv, CSR_GP_DRIVER_REG,
+				CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
+	iwl_set_bit(priv, CSR_GP_DRIVER_REG,
+		    CSR_GP_DRIVER_REG_BIT_6050_1x2);
+}
+
 /* NIC configuration for 6000 series */
 static void iwl6000_nic_config(struct iwl_priv *priv)
 {
@@ -117,9 +131,11 @@
 		iwl_write32(priv, CSR_GP_DRIVER_REG,
 			     CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
 	}
-	/* else do nothing, uCode configured */
-	if (priv->cfg->ops->lib->temp_ops.set_calib_version)
-		priv->cfg->ops->lib->temp_ops.set_calib_version(priv);
+	/* do additional nic configuration if needed */
+	if (priv->cfg->ops->nic &&
+		priv->cfg->ops->nic->additional_nic_config) {
+			priv->cfg->ops->nic->additional_nic_config(priv);
+	}
 }
 
 static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
@@ -151,17 +167,17 @@
 {
 	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
 	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
-		priv->cfg->num_of_queues =
+		priv->cfg->base_params->num_of_queues =
 			priv->cfg->mod_params->num_of_queues;
 
-	priv->hw_params.max_txq_num = priv->cfg->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->num_of_queues *
+			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->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
+	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;
@@ -176,8 +192,7 @@
 	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
 	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
 
-	if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
-		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+	iwl6000_set_ct_threshold(priv);
 
 	/* Set initial sensitivity parameters */
 	/* Set initial calibration set */
@@ -188,7 +203,9 @@
 		BIT(IWL_CALIB_TX_IQ)		|
 		BIT(IWL_CALIB_BASE_BAND);
 	if (priv->cfg->need_dc_calib)
-		priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
+		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;
 
@@ -198,14 +215,19 @@
 static int iwl6000_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(priv->rxon_timing.beacon_interval);
-	struct ieee80211_vif *vif = priv->vif;
+	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),
@@ -214,12 +236,12 @@
 	};
 
 	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
-	ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
+	ch = ch_switch->channel->hw_value;
 	IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
-		      priv->active_rxon.channel, ch);
+		      ctx->active.channel, ch);
 	cmd.channel = cpu_to_le16(ch);
-	cmd.rxon_flags = priv->staging_rxon.flags;
-	cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
+	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;
 	/*
@@ -254,7 +276,7 @@
 		cmd.expect_beacon = is_channel_radar(ch_info);
 	else {
 		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
-			priv->active_rxon.channel, ch);
+			ctx->active.channel, ch);
 		return -EFAULT;
 	}
 	priv->switch_rxon.channel = cmd.channel;
@@ -288,9 +310,7 @@
 	.set_channel_switch = iwl6000_hw_channel_switch,
 	.apm_ops = {
 		.init = iwl_apm_init,
-		.stop = iwl_apm_stop,
 		.config = iwl6000_nic_config,
-		.set_pwr_src = iwl_set_pwr_src,
 	},
 	.eeprom_ops = {
 		.regulatory_bands = {
@@ -302,7 +322,6 @@
 			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REG_BAND_52_HT40_CHANNELS
 		},
-		.verify_signature  = iwlcore_eeprom_verify_signature,
 		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
 		.release_semaphore = iwlcore_eeprom_release_semaphore,
 		.calib_version	= iwlagn_eeprom_calib_version,
@@ -314,22 +333,105 @@
 	.config_ap = iwl_config_ap,
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
-		.set_ct_kill = iwl6000_set_ct_threshold,
-		.set_calib_version = iwl6000_set_calib_version,
 	 },
 	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_station = iwl_update_bcast_station,
+	.update_bcast_stations = iwl_update_bcast_stations,
 	.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,
 	},
 	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.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 = {
+		.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 struct iwl_lib_ops iwl6000g2b_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,
+	.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_bt_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 = iwl6000_hw_channel_switch,
+	.apm_ops = {
+		.init = iwl_apm_init,
+		.config = iwl6000_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,
+	},
+	.post_associate = iwl_post_associate,
+	.isr = iwl_isr_ict,
+	.config_ap = iwl_config_ap,
+	.temp_ops = {
+		.temperature = iwlagn_temperature,
+	 },
+	.manage_ibss_station = iwlagn_manage_ibss_station,
+	.update_bcast_stations = iwl_update_bcast_stations,
+	.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,
+	},
+	.recover_from_tx_stall = iwl_bg_monitor_recover,
+	.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 = {
+		.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 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 const struct iwl_ops iwl6000_ops = {
@@ -339,49 +441,39 @@
 	.led = &iwlagn_led_ops,
 };
 
-static void do_not_send_bt_config(struct iwl_priv *priv)
-{
-}
+static const struct iwl_ops iwl6050_ops = {
+	.lib = &iwl6000_lib,
+	.hcmd = &iwlagn_hcmd,
+	.utils = &iwlagn_hcmd_utils,
+	.led = &iwlagn_led_ops,
+	.nic = &iwl6050_nic_ops,
+};
 
-static struct iwl_hcmd_ops iwl6000g2b_hcmd = {
-	.rxon_assoc = iwlagn_send_rxon_assoc,
-	.commit_rxon = iwl_commit_rxon,
-	.set_rxon_chain = iwl_set_rxon_chain,
-	.set_tx_ant = iwlagn_send_tx_ant_config,
-	.send_bt_config = do_not_send_bt_config,
+static const struct iwl_ops iwl6050g2_ops = {
+	.lib = &iwl6000_lib,
+	.hcmd = &iwlagn_hcmd,
+	.utils = &iwlagn_hcmd_utils,
+	.led = &iwlagn_led_ops,
+	.nic = &iwl6050g2_nic_ops,
 };
 
 static const struct iwl_ops iwl6000g2b_ops = {
-	.lib = &iwl6000_lib,
-	.hcmd = &iwl6000g2b_hcmd,
+	.lib = &iwl6000g2b_lib,
+	.hcmd = &iwlagn_bt_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
 };
 
-struct iwl_cfg iwl6000g2a_2agn_cfg = {
-	.name = "6000 Series 2x2 AGN Gen2a",
-	.fw_name_pre = IWL6000G2A_FW_PRE,
-	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
-	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl6000_ops,
+static struct iwl_base_params iwl6000_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
 	.pll_cfg_val = 0,
 	.set_l0s = true,
 	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
 	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
 	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.supports_idle = true,
 	.adv_thermal_throttle = true,
@@ -393,7 +485,82 @@
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+};
+
+static struct iwl_base_params iwl6050_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_6x50,
+	.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,
+	.chain_noise_scale = 1500,
+	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
+	.max_event_log_size = 1024,
+	.ucode_tracing = true,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+};
+static struct iwl_base_params iwl6000_coex_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_6x00,
+	.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,
+	.chain_noise_scale = 1000,
+	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
+	.max_event_log_size = 512,
+	.ucode_tracing = true,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+};
+
+static struct iwl_ht_params iwl6000_ht_params = {
+	.ht_greenfield_support = true,
+	.use_rts_for_aggregation = true, /* use rts/cts protection */
+};
+
+static struct iwl_bt_params iwl6000_bt_params = {
+	.bt_statistics = true,
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.advanced_bt_coexist = true,
+	.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
+	.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT,
+};
+
+struct iwl_cfg iwl6000g2a_2agn_cfg = {
+	.name = "6000 Series 2x2 AGN Gen2a",
+	.fw_name_pre = IWL6000G2A_FW_PRE,
+	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
+	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
+	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
+	.valid_tx_ant = ANT_AB,
+	.valid_rx_ant = ANT_AB,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+	.ops = &iwl6000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_base_params,
+	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
+	.need_temp_offset_calib = true,
 };
 
 struct iwl_cfg iwl6000g2a_2abg_cfg = {
@@ -402,33 +569,15 @@
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_AB,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+	.ops = &iwl6000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_base_params,
 	.need_dc_calib = true,
+	.need_temp_offset_calib = true,
 };
 
 struct iwl_cfg iwl6000g2a_2bg_cfg = {
@@ -437,33 +586,15 @@
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
 	.sku = IWL_SKU_G,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_AB,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+	.ops = &iwl6000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_base_params,
 	.need_dc_calib = true,
+	.need_temp_offset_calib = true,
 };
 
 struct iwl_cfg iwl6000g2b_2agn_cfg = {
@@ -472,36 +603,19 @@
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl6000g2b_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_AB,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+	.ops = &iwl6000g2b_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_coex_base_params,
+	.bt_params = &iwl6000_bt_params,
+	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
-	.bt_statistics = true,
+	.need_temp_offset_calib = true,
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
 };
 
 struct iwl_cfg iwl6000g2b_2abg_cfg = {
@@ -510,34 +624,18 @@
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G,
-	.ops = &iwl6000g2b_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_AB,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+	.ops = &iwl6000g2b_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_coex_base_params,
+	.bt_params = &iwl6000_bt_params,
 	.need_dc_calib = true,
-	.bt_statistics = true,
+	.need_temp_offset_calib = true,
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
 };
 
 struct iwl_cfg iwl6000g2b_2bgn_cfg = {
@@ -546,36 +644,19 @@
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
 	.sku = IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl6000g2b_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_AB,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+	.ops = &iwl6000g2b_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_coex_base_params,
+	.bt_params = &iwl6000_bt_params,
+	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
-	.bt_statistics = true,
+	.need_temp_offset_calib = true,
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
 };
 
 struct iwl_cfg iwl6000g2b_2bg_cfg = {
@@ -584,34 +665,18 @@
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
 	.sku = IWL_SKU_G,
-	.ops = &iwl6000g2b_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_AB,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+	.ops = &iwl6000g2b_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_coex_base_params,
+	.bt_params = &iwl6000_bt_params,
 	.need_dc_calib = true,
-	.bt_statistics = true,
+	.need_temp_offset_calib = true,
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
 };
 
 struct iwl_cfg iwl6000g2b_bgn_cfg = {
@@ -620,36 +685,19 @@
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
 	.sku = IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl6000g2b_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_A,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+	.ops = &iwl6000g2b_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_coex_base_params,
+	.bt_params = &iwl6000_bt_params,
+	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
-	.bt_statistics = true,
+	.need_temp_offset_calib = true,
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
 };
 
 struct iwl_cfg iwl6000g2b_bg_cfg = {
@@ -658,34 +706,18 @@
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
 	.sku = IWL_SKU_G,
-	.ops = &iwl6000g2b_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_A,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
-	.max_event_log_size = 512,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+	.ops = &iwl6000g2b_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_coex_base_params,
+	.bt_params = &iwl6000_bt_params,
 	.need_dc_calib = true,
-	.bt_statistics = true,
+	.need_temp_offset_calib = true,
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
 };
 
 /*
@@ -697,35 +729,15 @@
 	.ucode_api_max = IWL6000_UCODE_API_MAX,
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_BC,
 	.valid_rx_ant = ANT_BC,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
+	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
+	.ops = &iwl6000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_base_params,
+	.ht_params = &iwl6000_ht_params,
 	.pa_type = IWL_PA_INTERNAL,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
-	.max_event_log_size = 1024,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
 };
 
 struct iwl_cfg iwl6000i_2abg_cfg = {
@@ -734,33 +746,14 @@
 	.ucode_api_max = IWL6000_UCODE_API_MAX,
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_BC,
 	.valid_rx_ant = ANT_BC,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
+	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
+	.ops = &iwl6000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_base_params,
 	.pa_type = IWL_PA_INTERNAL,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
-	.max_event_log_size = 1024,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
 };
 
 struct iwl_cfg iwl6000i_2bg_cfg = {
@@ -769,33 +762,14 @@
 	.ucode_api_max = IWL6000_UCODE_API_MAX,
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
 	.sku = IWL_SKU_G,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_BC,
 	.valid_rx_ant = ANT_BC,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
+	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
+	.ops = &iwl6000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_base_params,
 	.pa_type = IWL_PA_INTERNAL,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
-	.max_event_log_size = 1024,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
 };
 
 struct iwl_cfg iwl6050_2agn_cfg = {
@@ -804,35 +778,14 @@
 	.ucode_api_max = IWL6050_UCODE_API_MAX,
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_AB,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
-	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.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,
-	.chain_noise_scale = 1500,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
-	.max_event_log_size = 1024,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.ops = &iwl6050_ops,
+	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6050_base_params,
+	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
 };
 
@@ -842,35 +795,14 @@
 	.ucode_api_max = IWL6050_UCODE_API_MAX,
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
 	.sku = IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6050G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_A,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
-	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.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,
-	.chain_noise_scale = 1500,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
-	.max_event_log_size = 1024,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_6050G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION,
+	.ops = &iwl6050g2_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6050_base_params,
+	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
 };
 
@@ -880,33 +812,13 @@
 	.ucode_api_max = IWL6050_UCODE_API_MAX,
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_AB,
 	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
-	.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,
-	.chain_noise_scale = 1500,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
-	.max_event_log_size = 1024,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
+	.ops = &iwl6050_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6050_base_params,
 	.need_dc_calib = true,
 };
 
@@ -916,38 +828,58 @@
 	.ucode_api_max = IWL6000_UCODE_API_MAX,
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
-	.num_of_queues = IWLAGN_NUM_QUEUES,
-	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
-	.mod_params = &iwlagn_mod_params,
 	.valid_tx_ant = ANT_ABC,
 	.valid_rx_ant = ANT_ABC,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_SYSTEM,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_aggregation = true, /* use rts/cts protection */
-	.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,
-	.chain_noise_scale = 1000,
-	.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
-	.max_event_log_size = 1024,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
+	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
+	.ops = &iwl6000_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_base_params,
+	.ht_params = &iwl6000_ht_params,
+	.need_dc_calib = true,
+};
+
+struct iwl_cfg iwl130_bgn_cfg = {
+	.name = "Intel(R) 130 Series 1x1 BGN",
+	.fw_name_pre = IWL6000G2B_FW_PRE,
+	.ucode_api_max = IWL130_UCODE_API_MAX,
+	.ucode_api_min = IWL130_UCODE_API_MIN,
+	.sku = IWL_SKU_G|IWL_SKU_N,
+	.valid_tx_ant = ANT_A,
+	.valid_rx_ant = ANT_A,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+	.ops = &iwl6000g2b_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_coex_base_params,
+	.bt_params = &iwl6000_bt_params,
+	.ht_params = &iwl6000_ht_params,
+	.need_dc_calib = true,
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+};
+
+struct iwl_cfg iwl130_bg_cfg = {
+	.name = "Intel(R) 130 Series 1x2 BG",
+	.fw_name_pre = IWL6000G2B_FW_PRE,
+	.ucode_api_max = IWL130_UCODE_API_MAX,
+	.ucode_api_min = IWL130_UCODE_API_MIN,
+	.sku = IWL_SKU_G,
+	.valid_tx_ant = ANT_A,
+	.valid_rx_ant = ANT_A,
+	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+	.ops = &iwl6000g2b_ops,
+	.mod_params = &iwlagn_mod_params,
+	.base_params = &iwl6000_coex_base_params,
+	.bt_params = &iwl6000_bt_params,
+	.need_dc_calib = true,
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
 };
 
 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(IWL130_MODULE_FIRMWARE(IWL130_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index c4c5691..e2019e7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -65,7 +65,7 @@
 
 #include "iwl-dev.h"
 #include "iwl-core.h"
-#include "iwl-calib.h"
+#include "iwl-agn-calib.h"
 
 /*****************************************************************************
  * INIT calibrations framework
@@ -625,13 +625,14 @@
 
 	data = &(priv->sensitivity_data);
 
-	if (!iwl_is_associated(priv)) {
+	if (!iwl_is_any_associated(priv)) {
 		IWL_DEBUG_CALIB(priv, "<< - not associated\n");
 		return;
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (priv->cfg->bt_statistics) {
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->bt_statistics) {
 		rx_info = &(((struct iwl_bt_notif_statistics *)resp)->
 			      rx.general.common);
 		ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm);
@@ -763,6 +764,12 @@
 	unsigned long flags;
 	struct statistics_rx_non_phy *rx_info;
 	u8 first_chain;
+	/*
+	 * MULTI-FIXME:
+	 * When we support multiple interfaces on different channels,
+	 * this must be modified/fixed.
+	 */
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
 	if (priv->disable_chain_noise_cal)
 		return;
@@ -780,7 +787,8 @@
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (priv->cfg->bt_statistics) {
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->bt_statistics) {
 		rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)->
 			      rx.general.common);
 	} else {
@@ -793,9 +801,10 @@
 		return;
 	}
 
-	rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK);
-	rxon_chnum = le16_to_cpu(priv->staging_rxon.channel);
-	if (priv->cfg->bt_statistics) {
+	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) {
 		stat_band24 = !!(((struct iwl_bt_notif_statistics *)
 				 stat_resp)->flag &
 				 STATISTICS_REPLY_FLG_BAND_24G_MSK);
@@ -855,16 +864,17 @@
 	/* 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->chain_noise_num_beacons)
+	if (data->beacon_count !=
+		priv->cfg->base_params->chain_noise_num_beacons)
 		return;
 
 	/* Analyze signal for disconnected antenna */
-	average_sig[0] =
-		(data->chain_signal_a) / priv->cfg->chain_noise_num_beacons;
-	average_sig[1] =
-		(data->chain_signal_b) / priv->cfg->chain_noise_num_beacons;
-	average_sig[2] =
-		(data->chain_signal_c) / priv->cfg->chain_noise_num_beacons;
+	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];
@@ -914,7 +924,13 @@
 	 * To be safe, simply mask out any chains that we know
 	 * are not on the device.
 	 */
-	active_chains &= priv->hw_params.valid_rx_ant;
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist &&
+	    priv->bt_full_concurrent) {
+		/* operated as 1x1 in full concurrency mode */
+		active_chains &= first_antenna(priv->hw_params.valid_rx_ant);
+	} else
+		active_chains &= priv->hw_params.valid_rx_ant;
 
 	num_tx_chains = 0;
 	for (i = 0; i < NUM_RX_CHAINS; i++) {
@@ -957,12 +973,12 @@
 			active_chains);
 
 	/* Analyze noise for rx balance */
-	average_noise[0] =
-		((data->chain_noise_a) / priv->cfg->chain_noise_num_beacons);
-	average_noise[1] =
-		((data->chain_noise_b) / priv->cfg->chain_noise_num_beacons);
-	average_noise[2] =
-		((data->chain_noise_c) / priv->cfg->chain_noise_num_beacons);
+	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]) &&
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
new file mode 100644
index 0000000..e37ae726
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
@@ -0,0 +1,86 @@
+/******************************************************************************
+ *
+ * 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_calib_h__
+#define __iwl_calib_h__
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-commands.h"
+
+void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp);
+void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp);
+
+void iwl_init_sensitivity(struct iwl_priv *priv);
+void iwl_reset_run_time_calib(struct iwl_priv *priv);
+static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
+{
+
+	if (!priv->disable_chain_noise_cal &&
+	    priv->cfg->ops->utils->chain_noise_reset)
+		priv->cfg->ops->utils->chain_noise_reset(priv);
+}
+
+int iwl_send_calib_results(struct iwl_priv *priv);
+int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
+void iwl_calib_free_results(struct iwl_priv *priv);
+
+#endif /* __iwl_calib_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
index d706b8a..a358d43 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
@@ -25,15 +25,22 @@
 *  Intel Linux Wireless <ilw@linux.intel.com>
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *****************************************************************************/
-
+#include "iwl-agn.h"
 #include "iwl-agn-debugfs.h"
 
+static const char *fmt_value = "  %-30s %10u\n";
+static const char *fmt_hex   = "  %-30s       0x%02X\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 iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
 {
 	int p = 0;
 	u32 flag;
 
-	if (priv->cfg->bt_statistics)
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->bt_statistics)
 		flag = le32_to_cpu(priv->_agn.statistics_bt.flag);
 	else
 		flag = le32_to_cpu(priv->_agn.statistics.flag);
@@ -82,7 +89,8 @@
 	 * the last statistics notification from uCode
 	 * might not reflect the current uCode activity
 	 */
-	if (priv->cfg->bt_statistics) {
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->bt_statistics) {
 		ofdm = &priv->_agn.statistics_bt.rx.ofdm;
 		cck = &priv->_agn.statistics_bt.rx.cck;
 		general = &priv->_agn.statistics_bt.rx.general.common;
@@ -121,436 +129,380 @@
 	}
 
 	pos += iwl_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),
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "plcp_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "crc32_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "overrun_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "early_overrun_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "crc32_good:", le32_to_cpu(ofdm->crc32_good),
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "false_alarm_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_sync_err_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "sfd_timeout:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "fina_timeout:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "unresponded_rts:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "rxe_frame_lmt_ovrun:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "sent_ack_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "sent_cts_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sent_ba_rsp_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "dsp_self_kill:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "mh_format_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "re_acq_main_rssi_sum:",
+			 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, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_Rx - CCK:");
 	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "ina_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "plcp_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "crc32_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "overrun_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "early_overrun_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "crc32_good:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "false_alarm_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_sync_err_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sfd_timeout:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "fina_timeout:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "unresponded_rts:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "rxe_frame_lmt_ovrun:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "sent_ack_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "sent_cts_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "sent_ba_rsp_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "dsp_self_kill:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "mh_format_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "re_acq_main_rssi_sum:",
+			 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, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_Rx - GENERAL:");
 	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "bogus_cts:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "bogus_ack:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "non_bssid_frames:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "filtered_frames:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "non_channel_beacons:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "channel_beacons:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "num_missed_bcon:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "adc_rx_saturation_time:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "ina_detect_search_tm:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "beacon_silence_rssi_a:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "beacon_silence_rssi_b:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "beacon_silence_rssi_c:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "interference_data_flag:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "channel_load:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "dsp_false_alarms:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "beacon_rssi_a:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "beacon_rssi_b:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "beacon_rssi_c:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "beacon_energy_a:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "beacon_energy_b:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "beacon_energy_c:",
+			 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, "Statistics_Rx - OFDM_HT:\n");
-	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_Rx - OFDM_HT:");
 	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "plcp_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "overrun_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "early_overrun_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "crc32_good:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "crc32_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "mh_format_err:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg_crc32_good:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg_mpdu_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "unsupport_mcs:",
+			 fmt_table, "unsupport_mcs:",
 			 le32_to_cpu(ht->unsupport_mcs),
 			 accum_ht->unsupport_mcs,
 			 delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
@@ -584,7 +536,8 @@
 	  * the last statistics notification from uCode
 	  * might not reflect the current uCode activity
 	  */
-	if (priv->cfg->bt_statistics) {
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->bt_statistics) {
 		tx = &priv->_agn.statistics_bt.tx;
 		accum_tx = &priv->_agn.accum_statistics_bt.tx;
 		delta_tx = &priv->_agn.delta_statistics_bt.tx;
@@ -597,166 +550,141 @@
 	}
 
 	pos += iwl_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:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "rx_detected_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "bt_prio_defer_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "bt_prio_kill_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "few_bytes_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "cts_timeout:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "ack_timeout:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "expected_ack_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "actual_ack_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "dump_msdu_cnt:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "abort_nxt_frame_mismatch:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "abort_missing_nxt_frame:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "cts_timeout_collision:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "ack_ba_timeout_collision:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg ba_timeout:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg ba_resched_frames:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg scd_query_agg_frame:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg scd_query_no_agg:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg scd_query_agg:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg scd_query_mismatch:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg frame_not_ready:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg underrun:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg bt_prio_kill:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "agg rx_ba_rsp_cnt:",
+			 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,
@@ -767,15 +695,15 @@
 			"tx power: (1/2 dB step)\n");
 		if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a)
 			pos += scnprintf(buf + pos, bufsz - pos,
-					"\tantenna A: 0x%X\n",
+					fmt_hex, "antenna A:",
 					tx->tx_power.ant_a);
 		if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b)
 			pos += scnprintf(buf + pos, bufsz - pos,
-					"\tantenna B: 0x%X\n",
+					fmt_hex, "antenna B:",
 					tx->tx_power.ant_b);
 		if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c)
 			pos += scnprintf(buf + pos, bufsz - pos,
-					"\tantenna C: 0x%X\n",
+					fmt_hex, "antenna C:",
 					tx->tx_power.ant_c);
 	}
 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
@@ -809,7 +737,8 @@
 	  * the last statistics notification from uCode
 	  * might not reflect the current uCode activity
 	  */
-	if (priv->cfg->bt_statistics) {
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->bt_statistics) {
 		general = &priv->_agn.statistics_bt.general.common;
 		dbg = &priv->_agn.statistics_bt.general.common.dbg;
 		div = &priv->_agn.statistics_bt.general.common.div;
@@ -838,84 +767,72 @@
 	}
 
 	pos += iwl_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\n",
-			 "temperature:",
+	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, "  %-30s %10u\n",
-			 "temperature_m:",
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_value, "temperature_m:",
 			 le32_to_cpu(general->temperature_m));
 	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "burst_check:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "burst_count:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "wait_for_silence_timeout_count:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sleep_time:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "slots_out:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "slots_idle:",
+			 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, "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:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "tx_on_b:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "exec_time:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "probe_time:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "rx_enable_counter:",
+			 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,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "num_of_sos_states:",
+			 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,
@@ -1011,3 +928,147 @@
 	kfree(buf);
 	return ret;
 }
+
+ssize_t iwl_reply_tx_error_read(struct file *file,
+				char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = (sizeof(struct reply_tx_error_statistics) * 24) +
+		(sizeof(struct reply_agg_tx_error_statistics) * 24) + 200;
+	ssize_t ret;
+
+	if (!iwl_is_alive(priv))
+		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, "Statistics_TX_Error:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY),
+			 priv->_agn.reply_tx_stats.pp_delay);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES),
+			 priv->_agn.reply_tx_stats.pp_few_bytes);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO),
+			 priv->_agn.reply_tx_stats.pp_bt_prio);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD),
+			 priv->_agn.reply_tx_stats.pp_quiet_period);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK),
+			 priv->_agn.reply_tx_stats.pp_calc_ttak);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+			 iwl_get_tx_fail_reason(
+				TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY),
+			 priv->_agn.reply_tx_stats.int_crossed_retry);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT),
+			 priv->_agn.reply_tx_stats.short_limit);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT),
+			 priv->_agn.reply_tx_stats.long_limit);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN),
+			 priv->_agn.reply_tx_stats.fifo_underrun);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW),
+			 priv->_agn.reply_tx_stats.drain_flow);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH),
+			 priv->_agn.reply_tx_stats.rfkill_flush);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE),
+			 priv->_agn.reply_tx_stats.life_expire);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS),
+			 priv->_agn.reply_tx_stats.dest_ps);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED),
+			 priv->_agn.reply_tx_stats.host_abort);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY),
+			 priv->_agn.reply_tx_stats.pp_delay);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID),
+			 priv->_agn.reply_tx_stats.sta_invalid);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED),
+			 priv->_agn.reply_tx_stats.frag_drop);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE),
+			 priv->_agn.reply_tx_stats.tid_disable);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED),
+			 priv->_agn.reply_tx_stats.fifo_flush);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+			 iwl_get_tx_fail_reason(
+				TX_STATUS_FAIL_INSUFFICIENT_CF_POLL),
+			 priv->_agn.reply_tx_stats.insuff_cf_poll);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX),
+			 priv->_agn.reply_tx_stats.fail_hw_drop);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+			 iwl_get_tx_fail_reason(
+				TX_STATUS_FAIL_NO_BEACON_ON_RADAR),
+			 priv->_agn.reply_tx_stats.sta_color_mismatch);
+	pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
+			 priv->_agn.reply_tx_stats.unknown);
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "\nStatistics_Agg_TX_Error:\n");
+
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK),
+			 priv->_agn.reply_agg_tx_stats.underrun);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK),
+			 priv->_agn.reply_agg_tx_stats.bt_prio);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK),
+			 priv->_agn.reply_agg_tx_stats.few_bytes);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK),
+			 priv->_agn.reply_agg_tx_stats.abort);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(
+				AGG_TX_STATE_LAST_SENT_TTL_MSK),
+			 priv->_agn.reply_agg_tx_stats.last_sent_ttl);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(
+				AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK),
+			 priv->_agn.reply_agg_tx_stats.last_sent_try);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(
+				AGG_TX_STATE_LAST_SENT_BT_KILL_MSK),
+			 priv->_agn.reply_agg_tx_stats.last_sent_bt_kill);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK),
+			 priv->_agn.reply_agg_tx_stats.scd_query);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(
+				AGG_TX_STATE_TEST_BAD_CRC32_MSK),
+			 priv->_agn.reply_agg_tx_stats.bad_crc32);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK),
+			 priv->_agn.reply_agg_tx_stats.response);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK),
+			 priv->_agn.reply_agg_tx_stats.dump_tx);
+	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK),
+			 priv->_agn.reply_agg_tx_stats.delay_tx);
+	pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
+			 priv->_agn.reply_agg_tx_stats.unknown);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h
index bbdce59..f2573b5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h
@@ -39,6 +39,8 @@
 				     size_t count, loff_t *ppos);
 ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf,
 				size_t count, loff_t *ppos);
+ssize_t iwl_reply_tx_error_read(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos);
 #else
 static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
 				       size_t count, loff_t *ppos)
@@ -60,4 +62,9 @@
 {
 	return 0;
 }
+static ssize_t iwl_reply_tx_error_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-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
new file mode 100644
index 0000000..a650bab
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
@@ -0,0 +1,454 @@
+/******************************************************************************
+ *
+ * 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.
+ *****************************************************************************/
+
+
+#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-agn.h"
+#include "iwl-io.h"
+
+/************************** EEPROM BANDS ****************************
+ *
+ * The iwl_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.
+ *
+ *********************************************************************/
+
+/**
+ * struct iwl_txpwr_section: eeprom section information
+ * @offset: indirect address into eeprom image
+ * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
+ * @band: band type for the section
+ * @is_common - true: common section, false: channel section
+ * @is_cck - true: cck section, false: not cck section
+ * @is_ht_40 - true: all channel in the section are HT40 channel,
+ *	       false: legacy or HT 20 MHz
+ *	       ignore if it is common section
+ * @iwl_eeprom_section_channel: channel array in the section,
+ *	       ignore if common section
+ */
+struct iwl_txpwr_section {
+	u32 offset;
+	u8 count;
+	enum ieee80211_band band;
+	bool is_common;
+	bool is_cck;
+	bool is_ht40;
+	u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
+};
+
+/**
+ * section 1 - 3 are regulatory tx power apply to all channels based on
+ *    modulation: CCK, OFDM
+ *    Band: 2.4GHz, 5.2GHz
+ * section 4 - 10 are regulatory tx power apply to specified channels
+ *    For example:
+ *	1L - Channel 1 Legacy
+ *	1HT - Channel 1 HT
+ *	(1,+1) - Channel 1 HT40 "_above_"
+ *
+ * Section 1: all CCK channels
+ * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
+ * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
+ * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
+ * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
+ * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
+ * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
+ * Section 8: 2.4 GHz channel: 13L, 13HT
+ * Section 9: 2.4 GHz channel: 140L, 140HT
+ * Section 10: 2.4 GHz 40MHz channels: (132,+1)  (44,+1)
+ *
+ */
+static const struct iwl_txpwr_section enhinfo[] = {
+	{ EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
+	{ EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
+	{ EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
+	{ EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
+		false, false, false,
+		{1, 1, 2, 2, 10, 10, 11, 11 } },
+	{ EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
+		false, false, true,
+		{ 1, 2, 6, 7, 9 } },
+	{ EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
+		false, false, false,
+		{ 36, 64, 100, 36, 64, 100 } },
+	{ EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
+		false, false, true,
+		{ 36, 60, 100 } },
+	{ EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
+		false, false, false,
+		{ 13, 13 } },
+	{ EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
+		false, false, false,
+		{ 140, 140 } },
+	{ EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
+		false, false, true,
+		{ 132, 44 } },
+};
+
+/******************************************************************************
+ *
+ * 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 iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
+{
+	u16 count;
+	int ret;
+
+	for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
+		/* Request semaphore */
+		iwl_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 iwlcore_eeprom_release_semaphore(struct iwl_priv *priv)
+{
+	iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+		CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+}
+
+int iwl_eeprom_check_version(struct iwl_priv *priv)
+{
+	u16 eeprom_ver;
+	u16 calib_ver;
+
+	eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+	calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv);
+
+	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 iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
+{
+	const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
+					EEPROM_MAC_ADDRESS);
+	memcpy(mac, addr, ETH_ALEN);
+}
+
+/**
+ * iwl_get_max_txpower_avg - get the highest tx power from all chains.
+ *     find the highest tx power from all chains for the channel
+ */
+static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
+		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+		int element, s8 *max_txpower_in_half_dbm)
+{
+	s8 max_txpower_avg = 0; /* (dBm) */
+
+	IWL_DEBUG_INFO(priv, "%d - "
+			"chain_a: %d dB chain_b: %d dB "
+			"chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
+			element,
+			enhanced_txpower[element].chain_a_max >> 1,
+			enhanced_txpower[element].chain_b_max >> 1,
+			enhanced_txpower[element].chain_c_max >> 1,
+			enhanced_txpower[element].mimo2_max >> 1,
+			enhanced_txpower[element].mimo3_max >> 1);
+	/* Take the highest tx power from any valid chains */
+	if ((priv->cfg->valid_tx_ant & ANT_A) &&
+	    (enhanced_txpower[element].chain_a_max > max_txpower_avg))
+		max_txpower_avg = enhanced_txpower[element].chain_a_max;
+	if ((priv->cfg->valid_tx_ant & ANT_B) &&
+	    (enhanced_txpower[element].chain_b_max > max_txpower_avg))
+		max_txpower_avg = enhanced_txpower[element].chain_b_max;
+	if ((priv->cfg->valid_tx_ant & ANT_C) &&
+	    (enhanced_txpower[element].chain_c_max > max_txpower_avg))
+		max_txpower_avg = enhanced_txpower[element].chain_c_max;
+	if (((priv->cfg->valid_tx_ant == ANT_AB) |
+	    (priv->cfg->valid_tx_ant == ANT_BC) |
+	    (priv->cfg->valid_tx_ant == ANT_AC)) &&
+	    (enhanced_txpower[element].mimo2_max > max_txpower_avg))
+		max_txpower_avg =  enhanced_txpower[element].mimo2_max;
+	if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
+	    (enhanced_txpower[element].mimo3_max > max_txpower_avg))
+		max_txpower_avg = enhanced_txpower[element].mimo3_max;
+
+	/*
+	 * max. tx power in EEPROM is in 1/2 dBm format
+	 * convert from 1/2 dBm to dBm (round-up convert)
+	 * but we also do not want to loss 1/2 dBm resolution which
+	 * will impact performance
+	 */
+	*max_txpower_in_half_dbm = max_txpower_avg;
+	return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
+}
+
+/**
+ * iwl_update_common_txpower: update channel tx power
+ *     update tx power per band based on EEPROM enhanced tx power info.
+ */
+static s8 iwl_update_common_txpower(struct iwl_priv *priv,
+		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+		int section, int element, s8 *max_txpower_in_half_dbm)
+{
+	struct iwl_channel_info *ch_info;
+	int ch;
+	bool is_ht40 = false;
+	s8 max_txpower_avg; /* (dBm) */
+
+	/* it is common section, contain all type (Legacy, HT and HT40)
+	 * based on the element in the section to determine
+	 * is it HT 40 or not
+	 */
+	if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
+		is_ht40 = true;
+	max_txpower_avg =
+		iwl_get_max_txpower_avg(priv, enhanced_txpower,
+					element, max_txpower_in_half_dbm);
+
+	ch_info = priv->channel_info;
+
+	for (ch = 0; ch < priv->channel_count; ch++) {
+		/* find matching band and update tx power if needed */
+		if ((ch_info->band == enhinfo[section].band) &&
+		    (ch_info->max_power_avg < max_txpower_avg) &&
+		    (!is_ht40)) {
+			/* Update regulatory-based run-time data */
+			ch_info->max_power_avg = ch_info->curr_txpow =
+				max_txpower_avg;
+			ch_info->scan_power = max_txpower_avg;
+		}
+		if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
+		    (ch_info->ht40_max_power_avg < max_txpower_avg)) {
+			/* Update regulatory-based run-time data */
+			ch_info->ht40_max_power_avg = max_txpower_avg;
+		}
+		ch_info++;
+	}
+	return max_txpower_avg;
+}
+
+/**
+ * iwl_update_channel_txpower: update channel tx power
+ *      update channel tx power based on EEPROM enhanced tx power info.
+ */
+static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
+		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+		int section, int element, s8 *max_txpower_in_half_dbm)
+{
+	struct iwl_channel_info *ch_info;
+	int ch;
+	u8 channel;
+	s8 max_txpower_avg; /* (dBm) */
+
+	channel = enhinfo[section].iwl_eeprom_section_channel[element];
+	max_txpower_avg =
+		iwl_get_max_txpower_avg(priv, enhanced_txpower,
+					element, max_txpower_in_half_dbm);
+
+	ch_info = priv->channel_info;
+	for (ch = 0; ch < priv->channel_count; ch++) {
+		/* find matching channel and update tx power if needed */
+		if (ch_info->channel == channel) {
+			if ((ch_info->max_power_avg < max_txpower_avg) &&
+			    (!enhinfo[section].is_ht40)) {
+				/* Update regulatory-based run-time data */
+				ch_info->max_power_avg = max_txpower_avg;
+				ch_info->curr_txpow = max_txpower_avg;
+				ch_info->scan_power = max_txpower_avg;
+			}
+			if ((enhinfo[section].is_ht40) &&
+			    (ch_info->ht40_max_power_avg < max_txpower_avg)) {
+				/* Update regulatory-based run-time data */
+				ch_info->ht40_max_power_avg = max_txpower_avg;
+			}
+			break;
+		}
+		ch_info++;
+	}
+	return max_txpower_avg;
+}
+
+/**
+ * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
+ */
+void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
+{
+	int eeprom_section_count = 0;
+	int section, element;
+	struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
+	u32 offset;
+	s8 max_txpower_avg; /* (dBm) */
+	s8 max_txpower_in_half_dbm; /* (half-dBm) */
+
+	/* Loop through all the sections
+	 * adjust bands and channel's max tx power
+	 * Set the tx_power_user_lmt to the highest power
+	 * supported by any channels and chains
+	 */
+	for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
+		eeprom_section_count = enhinfo[section].count;
+		offset = enhinfo[section].offset;
+		enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
+				iwl_eeprom_query_addr(priv, offset);
+
+		/*
+		 * check for valid entry -
+		 * different version of EEPROM might contain different set
+		 * of enhanced tx power table
+		 * always check for valid entry before process
+		 * the information
+		 */
+		if (!enhanced_txpower->common || enhanced_txpower->reserved)
+			continue;
+
+		for (element = 0; element < eeprom_section_count; element++) {
+			if (enhinfo[section].is_common)
+				max_txpower_avg =
+					iwl_update_common_txpower(priv,
+						enhanced_txpower, section,
+						element,
+						&max_txpower_in_half_dbm);
+			else
+				max_txpower_avg =
+					iwl_update_channel_txpower(priv,
+						enhanced_txpower, section,
+						element,
+						&max_txpower_in_half_dbm);
+
+			/* Update the tx_power_user_lmt to the highest power
+			 * supported by any channel */
+			if (max_txpower_avg > priv->tx_power_user_lmt)
+				priv->tx_power_user_lmt = max_txpower_avg;
+
+			/*
+			 * Update the tx_power_lmt_in_half_dbm to
+			 * the highest power supported by any channel
+			 */
+			if (max_txpower_in_half_dbm >
+			    priv->tx_power_lmt_in_half_dbm)
+				priv->tx_power_lmt_in_half_dbm =
+					max_txpower_in_half_dbm;
+		}
+	}
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
index 75b901b3..ffb2f41 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
@@ -37,12 +37,13 @@
 #include "iwl-io.h"
 #include "iwl-agn.h"
 
-int iwlagn_send_rxon_assoc(struct iwl_priv *priv)
+int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
+			   struct iwl_rxon_context *ctx)
 {
 	int ret = 0;
 	struct iwl5000_rxon_assoc_cmd rxon_assoc;
-	const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
-	const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
+	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) &&
@@ -60,23 +61,23 @@
 		return 0;
 	}
 
-	rxon_assoc.flags = priv->staging_rxon.flags;
-	rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
-	rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
-	rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
+	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.reserved1 = 0;
 	rxon_assoc.reserved2 = 0;
 	rxon_assoc.reserved3 = 0;
 	rxon_assoc.ofdm_ht_single_stream_basic_rates =
-	    priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
+	    ctx->staging.ofdm_ht_single_stream_basic_rates;
 	rxon_assoc.ofdm_ht_dual_stream_basic_rates =
-	    priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
-	rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
+	    ctx->staging.ofdm_ht_dual_stream_basic_rates;
+	rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
 	rxon_assoc.ofdm_ht_triple_stream_basic_rates =
-		 priv->staging_rxon.ofdm_ht_triple_stream_basic_rates;
-	rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data;
+		 ctx->staging.ofdm_ht_triple_stream_basic_rates;
+	rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
 
-	ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
+	ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd,
 				     sizeof(rxon_assoc), &rxon_assoc, NULL);
 	if (ret)
 		return ret;
@@ -136,7 +137,7 @@
 			continue;
 		}
 
-		delta_g = (priv->cfg->chain_noise_scale *
+		delta_g = (priv->cfg->base_params->chain_noise_scale *
 			((s32)average_noise[default_chain] -
 			(s32)average_noise[i])) / 1500;
 
@@ -184,7 +185,7 @@
 	int ret;
 
 	if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
-	     iwl_is_associated(priv)) {
+	    iwl_is_any_associated(priv)) {
 		struct iwl_calib_chain_noise_reset_cmd cmd;
 
 		/* clear data for chain noise calibration algorithm */
@@ -221,7 +222,8 @@
 		return;
 	}
 
-	if (priv->cfg->use_rts_for_aggregation &&
+	if (priv->cfg->ht_params &&
+	    priv->cfg->ht_params->use_rts_for_aggregation &&
 	    info->flags & IEEE80211_TX_CTL_AMPDU) {
 		*tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
 		return;
@@ -235,13 +237,13 @@
 	/* data from PHY/DSP regarding signal strength, etc.,
 	 *   contents are always there, not configurable by host
 	 */
-	struct iwl5000_non_cfg_phy *ncphy =
-		(struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
+	struct iwlagn_non_cfg_phy *ncphy =
+		(struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
 	u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
 	u8 agc;
 
-	val  = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]);
-	agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS;
+	val  = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]);
+	agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS;
 
 	/* Find max rssi among 3 possible receivers.
 	 * These values are measured by the digital signal processor (DSP).
@@ -249,11 +251,14 @@
 	 *   if the radio's automatic gain control (AGC) is working right.
 	 * AGC value (see below) will provide the "interesting" info.
 	 */
-	val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]);
-	rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS;
-	rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS;
-	val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]);
-	rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS;
+	val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]);
+	rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >>
+		IWLAGN_OFDM_RSSI_A_BIT_POS;
+	rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >>
+		IWLAGN_OFDM_RSSI_B_BIT_POS;
+	val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]);
+	rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >>
+		IWLAGN_OFDM_RSSI_C_BIT_POS;
 
 	max_rssi = max_t(u32, rssi_a, rssi_b);
 	max_rssi = max_t(u32, max_rssi, rssi_c);
@@ -266,12 +271,109 @@
 	return max_rssi - agc - IWLAGN_RSSI_OFFSET;
 }
 
+static int iwlagn_set_pan_params(struct iwl_priv *priv)
+{
+	struct iwl_wipan_params_cmd cmd;
+	struct iwl_rxon_context *ctx_bss, *ctx_pan;
+	int slot0 = 300, slot1 = 0;
+	int ret;
+
+	if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
+		return 0;
+
+	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
+	lockdep_assert_held(&priv->mutex);
+
+	ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
+	ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
+
+	/*
+	 * If the PAN context is inactive, then we don't need
+	 * to update the PAN parameters, the last thing we'll
+	 * have done before it goes inactive is making the PAN
+	 * parameters be WLAN-only.
+	 */
+	if (!ctx_pan->is_active)
+		return 0;
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	/* only 2 slots are currently allowed */
+	cmd.num_slots = 2;
+
+	cmd.slots[0].type = 0; /* BSS */
+	cmd.slots[1].type = 1; /* PAN */
+
+	if (ctx_bss->vif && ctx_pan->vif) {
+		int bcnint = ctx_pan->vif->bss_conf.beacon_int;
+
+		/* should be set, but seems unused?? */
+		cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE);
+
+		if (ctx_pan->vif->type == NL80211_IFTYPE_AP &&
+		    bcnint &&
+		    bcnint != ctx_bss->vif->bss_conf.beacon_int) {
+			IWL_ERR(priv,
+				"beacon intervals don't match (%d, %d)\n",
+				ctx_bss->vif->bss_conf.beacon_int,
+				ctx_pan->vif->bss_conf.beacon_int);
+		} else
+			bcnint = max_t(int, bcnint,
+				       ctx_bss->vif->bss_conf.beacon_int);
+		if (!bcnint)
+			bcnint = DEFAULT_BEACON_INTERVAL;
+		slot0 = bcnint / 2;
+		slot1 = bcnint - slot0;
+
+		if (test_bit(STATUS_SCAN_HW, &priv->status) ||
+		    (!ctx_bss->vif->bss_conf.idle &&
+		     !ctx_bss->vif->bss_conf.assoc)) {
+			slot0 = bcnint * 3 - 20;
+			slot1 = 20;
+		} else if (!ctx_pan->vif->bss_conf.idle &&
+                           !ctx_pan->vif->bss_conf.assoc) {
+			slot1 = bcnint * 3 - 20;
+			slot0 = 20;
+		}
+	} else if (ctx_pan->vif) {
+		slot0 = 0;
+		slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) *
+					ctx_pan->vif->bss_conf.beacon_int;
+		slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
+
+		if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+			slot0 = slot1 * 3 - 20;
+			slot1 = 20;
+		}
+	}
+
+	cmd.slots[0].width = cpu_to_le16(slot0);
+	cmd.slots[1].width = cpu_to_le16(slot1);
+
+	ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd);
+	if (ret)
+		IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
+
+	return ret;
+}
+
 struct iwl_hcmd_ops iwlagn_hcmd = {
 	.rxon_assoc = iwlagn_send_rxon_assoc,
-	.commit_rxon = iwl_commit_rxon,
-	.set_rxon_chain = iwl_set_rxon_chain,
+	.commit_rxon = iwlagn_commit_rxon,
+	.set_rxon_chain = iwlagn_set_rxon_chain,
 	.set_tx_ant = iwlagn_send_tx_ant_config,
 	.send_bt_config = iwl_send_bt_config,
+	.set_pan_params = iwlagn_set_pan_params,
+};
+
+struct iwl_hcmd_ops iwlagn_bt_hcmd = {
+	.rxon_assoc = iwlagn_send_rxon_assoc,
+	.commit_rxon = iwlagn_commit_rxon,
+	.set_rxon_chain = iwlagn_set_rxon_chain,
+	.set_tx_ant = iwlagn_send_tx_ant_config,
+	.send_bt_config = iwlagn_send_advance_bt_config,
+	.set_pan_params = iwlagn_set_pan_params,
 };
 
 struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
@@ -282,4 +384,5 @@
 	.tx_cmd_protection = iwlagn_tx_cmd_protection,
 	.calc_rssi = iwlagn_calc_rssi,
 	.request_scan = iwlagn_request_scan,
+	.post_scan = iwlagn_post_scan,
 };
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
index c92b2c0..a5dbfea 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
@@ -59,7 +59,7 @@
 int iwl_alloc_isr_ict(struct iwl_priv *priv)
 {
 
-	if (priv->cfg->use_isr_legacy)
+	if (priv->cfg->base_params->use_isr_legacy)
 		return 0;
 	/* allocate shrared data table */
 	priv->_agn.ict_tbl_vir =
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 9dd9e64..b555edd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -40,22 +40,195 @@
 #include "iwl-agn.h"
 #include "iwl-sta.h"
 
-static inline u32 iwlagn_get_scd_ssn(struct iwl5000_tx_resp *tx_resp)
+static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)
 {
 	return le32_to_cpup((__le32 *)&tx_resp->status +
 			    tx_resp->frame_count) & MAX_SN;
 }
 
+static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
+{
+	status &= TX_STATUS_MSK;
+
+	switch (status) {
+	case TX_STATUS_POSTPONE_DELAY:
+		priv->_agn.reply_tx_stats.pp_delay++;
+		break;
+	case TX_STATUS_POSTPONE_FEW_BYTES:
+		priv->_agn.reply_tx_stats.pp_few_bytes++;
+		break;
+	case TX_STATUS_POSTPONE_BT_PRIO:
+		priv->_agn.reply_tx_stats.pp_bt_prio++;
+		break;
+	case TX_STATUS_POSTPONE_QUIET_PERIOD:
+		priv->_agn.reply_tx_stats.pp_quiet_period++;
+		break;
+	case TX_STATUS_POSTPONE_CALC_TTAK:
+		priv->_agn.reply_tx_stats.pp_calc_ttak++;
+		break;
+	case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY:
+		priv->_agn.reply_tx_stats.int_crossed_retry++;
+		break;
+	case TX_STATUS_FAIL_SHORT_LIMIT:
+		priv->_agn.reply_tx_stats.short_limit++;
+		break;
+	case TX_STATUS_FAIL_LONG_LIMIT:
+		priv->_agn.reply_tx_stats.long_limit++;
+		break;
+	case TX_STATUS_FAIL_FIFO_UNDERRUN:
+		priv->_agn.reply_tx_stats.fifo_underrun++;
+		break;
+	case TX_STATUS_FAIL_DRAIN_FLOW:
+		priv->_agn.reply_tx_stats.drain_flow++;
+		break;
+	case TX_STATUS_FAIL_RFKILL_FLUSH:
+		priv->_agn.reply_tx_stats.rfkill_flush++;
+		break;
+	case TX_STATUS_FAIL_LIFE_EXPIRE:
+		priv->_agn.reply_tx_stats.life_expire++;
+		break;
+	case TX_STATUS_FAIL_DEST_PS:
+		priv->_agn.reply_tx_stats.dest_ps++;
+		break;
+	case TX_STATUS_FAIL_HOST_ABORTED:
+		priv->_agn.reply_tx_stats.host_abort++;
+		break;
+	case TX_STATUS_FAIL_BT_RETRY:
+		priv->_agn.reply_tx_stats.bt_retry++;
+		break;
+	case TX_STATUS_FAIL_STA_INVALID:
+		priv->_agn.reply_tx_stats.sta_invalid++;
+		break;
+	case TX_STATUS_FAIL_FRAG_DROPPED:
+		priv->_agn.reply_tx_stats.frag_drop++;
+		break;
+	case TX_STATUS_FAIL_TID_DISABLE:
+		priv->_agn.reply_tx_stats.tid_disable++;
+		break;
+	case TX_STATUS_FAIL_FIFO_FLUSHED:
+		priv->_agn.reply_tx_stats.fifo_flush++;
+		break;
+	case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL:
+		priv->_agn.reply_tx_stats.insuff_cf_poll++;
+		break;
+	case TX_STATUS_FAIL_PASSIVE_NO_RX:
+		priv->_agn.reply_tx_stats.fail_hw_drop++;
+		break;
+	case TX_STATUS_FAIL_NO_BEACON_ON_RADAR:
+		priv->_agn.reply_tx_stats.sta_color_mismatch++;
+		break;
+	default:
+		priv->_agn.reply_tx_stats.unknown++;
+		break;
+	}
+}
+
+static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)
+{
+	status &= AGG_TX_STATUS_MSK;
+
+	switch (status) {
+	case AGG_TX_STATE_UNDERRUN_MSK:
+		priv->_agn.reply_agg_tx_stats.underrun++;
+		break;
+	case AGG_TX_STATE_BT_PRIO_MSK:
+		priv->_agn.reply_agg_tx_stats.bt_prio++;
+		break;
+	case AGG_TX_STATE_FEW_BYTES_MSK:
+		priv->_agn.reply_agg_tx_stats.few_bytes++;
+		break;
+	case AGG_TX_STATE_ABORT_MSK:
+		priv->_agn.reply_agg_tx_stats.abort++;
+		break;
+	case AGG_TX_STATE_LAST_SENT_TTL_MSK:
+		priv->_agn.reply_agg_tx_stats.last_sent_ttl++;
+		break;
+	case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK:
+		priv->_agn.reply_agg_tx_stats.last_sent_try++;
+		break;
+	case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK:
+		priv->_agn.reply_agg_tx_stats.last_sent_bt_kill++;
+		break;
+	case AGG_TX_STATE_SCD_QUERY_MSK:
+		priv->_agn.reply_agg_tx_stats.scd_query++;
+		break;
+	case AGG_TX_STATE_TEST_BAD_CRC32_MSK:
+		priv->_agn.reply_agg_tx_stats.bad_crc32++;
+		break;
+	case AGG_TX_STATE_RESPONSE_MSK:
+		priv->_agn.reply_agg_tx_stats.response++;
+		break;
+	case AGG_TX_STATE_DUMP_TX_MSK:
+		priv->_agn.reply_agg_tx_stats.dump_tx++;
+		break;
+	case AGG_TX_STATE_DELAY_TX_MSK:
+		priv->_agn.reply_agg_tx_stats.delay_tx++;
+		break;
+	default:
+		priv->_agn.reply_agg_tx_stats.unknown++;
+		break;
+	}
+}
+
+static void iwlagn_set_tx_status(struct iwl_priv *priv,
+				 struct ieee80211_tx_info *info,
+				 struct iwlagn_tx_resp *tx_resp,
+				 int txq_id, bool is_agg)
+{
+	u16  status = le16_to_cpu(tx_resp->status.status);
+
+	info->status.rates[0].count = tx_resp->failure_frame + 1;
+	if (is_agg)
+		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+	info->flags |= iwl_tx_status_to_mac80211(status);
+	iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
+				    info);
+	if (!iwl_is_tx_success(status))
+		iwlagn_count_tx_err_status(priv, status);
+
+	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);
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+#define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x
+
+const char *iwl_get_agg_tx_fail_reason(u16 status)
+{
+	status &= AGG_TX_STATUS_MSK;
+	switch (status) {
+	case AGG_TX_STATE_TRANSMITTED:
+		return "SUCCESS";
+		AGG_TX_STATE_FAIL(UNDERRUN_MSK);
+		AGG_TX_STATE_FAIL(BT_PRIO_MSK);
+		AGG_TX_STATE_FAIL(FEW_BYTES_MSK);
+		AGG_TX_STATE_FAIL(ABORT_MSK);
+		AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK);
+		AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK);
+		AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK);
+		AGG_TX_STATE_FAIL(SCD_QUERY_MSK);
+		AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK);
+		AGG_TX_STATE_FAIL(RESPONSE_MSK);
+		AGG_TX_STATE_FAIL(DUMP_TX_MSK);
+		AGG_TX_STATE_FAIL(DELAY_TX_MSK);
+	}
+
+	return "UNKNOWN";
+}
+#endif /* CONFIG_IWLWIFI_DEBUG */
+
 static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
 				      struct iwl_ht_agg *agg,
-				      struct iwl5000_tx_resp *tx_resp,
+				      struct iwlagn_tx_resp *tx_resp,
 				      int txq_id, u16 start_idx)
 {
 	u16 status;
 	struct agg_tx_status *frame_status = &tx_resp->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;
 
@@ -64,31 +237,20 @@
 
 	agg->frame_count = tx_resp->frame_count;
 	agg->start_idx = start_idx;
-	agg->rate_n_flags = rate_n_flags;
+	agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
 	agg->bitmap = 0;
 
 	/* # 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);
-
+		iwlagn_set_tx_status(priv,
+				     IEEE80211_SKB_CB(
+					priv->txq[txq_id].txb[idx].skb),
+				     tx_resp, txq_id, true);
 		agg->wait_for_ba = 0;
 	} else {
 		/* Two or more frames were attempted; expect block-ack */
@@ -109,12 +271,20 @@
 			idx = SEQ_TO_INDEX(seq);
 			txq_id = SEQ_TO_QUEUE(seq);
 
+			if (status & AGG_TX_STATUS_MSK)
+				iwlagn_count_agg_tx_err_status(priv, status);
+
 			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);
+			IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), "
+					   "try-count (0x%08x)\n",
+					   iwl_get_agg_tx_fail_reason(status),
+					   status & AGG_TX_STATUS_MSK,
+					   status & AGG_TX_TRY_MSK);
 
 			hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
 			if (!hdr) {
@@ -220,7 +390,7 @@
 	int index = SEQ_TO_INDEX(sequence);
 	struct iwl_tx_queue *txq = &priv->txq[txq_id];
 	struct ieee80211_tx_info *info;
-	struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+	struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
 	u32  status = le16_to_cpu(tx_resp->status.status);
 	int tid;
 	int sta_id;
@@ -238,8 +408,10 @@
 	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
 	memset(&info->status, 0, sizeof(info->status));
 
-	tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS;
-	sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS;
+	tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
+		IWLAGN_TX_RES_TID_POS;
+	sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
+		IWLAGN_TX_RES_RA_POS;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
 	if (txq->sched_retry) {
@@ -247,7 +419,15 @@
 		struct iwl_ht_agg *agg;
 
 		agg = &priv->stations[sta_id].tid[tid].agg;
-
+		/*
+		 * If the BT kill count is non-zero, we'll get this
+		 * notification again.
+		 */
+		if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
+		    priv->cfg->bt_params &&
+		    priv->cfg->bt_params->advanced_bt_coexist) {
+			IWL_WARN(priv, "receive reply tx with bt_kill\n");
+		}
 		iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
 
 		/* check if BAR is needed */
@@ -274,20 +454,7 @@
 		}
 	} else {
 		BUG_ON(txq_id != txq->swq_id);
-
-		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);
-
+		iwlagn_set_tx_status(priv, info, tx_resp, txq_id, false);
 		freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
 		iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
 
@@ -326,7 +493,7 @@
 
 int iwlagn_send_tx_power(struct iwl_priv *priv)
 {
-	struct iwl5000_tx_power_dbm_cmd tx_power_cmd;
+	struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
 	u8 tx_ant_cfg_cmd;
 
 	/* half dBm need to multiply */
@@ -347,8 +514,8 @@
 		 */
 		tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm;
 	}
-	tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED;
-	tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO;
+	tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED;
+	tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO;
 
 	if (IWL_UCODE_API(priv->ucode_ver) == 1)
 		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
@@ -425,7 +592,7 @@
 					   size_t offset)
 {
 	u32 address = eeprom_indirect_address(priv, offset);
-	BUG_ON(address >= priv->cfg->eeprom_size);
+	BUG_ON(address >= priv->cfg->base_params->eeprom_size);
 	return &priv->eeprom[address];
 }
 
@@ -473,7 +640,7 @@
 	const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
 	u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */
 
-	if (!priv->cfg->use_isr_legacy)
+	if (!priv->cfg->base_params->use_isr_legacy)
 		rb_timeout = RX_RB_TIMEOUT;
 
 	if (priv->cfg->mod_params->amsdu_size_8K)
@@ -518,6 +685,23 @@
 	return 0;
 }
 
+static void iwlagn_set_pwr_vmain(struct iwl_priv *priv)
+{
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do:
+
+		if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
+			iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+					       APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+					       ~APMG_PS_CTRL_MSK_PWR_SRC);
+ */
+
+	iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+			       APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+			       ~APMG_PS_CTRL_MSK_PWR_SRC);
+}
+
 int iwlagn_hw_nic_init(struct iwl_priv *priv)
 {
 	unsigned long flags;
@@ -533,7 +717,7 @@
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
+	iwlagn_set_pwr_vmain(priv);
 
 	priv->cfg->ops->lib->apm_ops.config(priv);
 
@@ -1098,7 +1282,7 @@
 		if (chan->band != band)
 			continue;
 
-		channel = ieee80211_frequency_to_channel(chan->center_freq);
+		channel = chan->hw_value;
 		scan_ch->channel = cpu_to_le16(channel);
 
 		ch_info = iwl_get_channel_info(priv, band, channel);
@@ -1147,7 +1331,7 @@
 	return added;
 }
 
-void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
+int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
 	struct iwl_host_cmd cmd = {
 		.id = REPLY_SCAN_CMD,
@@ -1155,7 +1339,7 @@
 		.flags = CMD_SIZE_HUGE,
 	};
 	struct iwl_scan_cmd *scan;
-	struct ieee80211_conf *conf = NULL;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 	u32 rate_flags = 0;
 	u16 cmd_len;
 	u16 rx_chain = 0;
@@ -1167,48 +1351,12 @@
 	int  chan_mod;
 	u8 active_chains;
 	u8 scan_tx_antennas = priv->hw_params.valid_tx_ant;
+	int ret;
 
-	conf = ieee80211_get_hw_conf(priv->hw);
+	lockdep_assert_held(&priv->mutex);
 
-	cancel_delayed_work(&priv->scan_check);
-
-	if (!iwl_is_ready(priv)) {
-		IWL_WARN(priv, "request scan called when driver not ready.\n");
-		goto done;
-	}
-
-	/* Make sure the scan wasn't canceled before this queued work
-	 * was given the chance to run... */
-	if (!test_bit(STATUS_SCANNING, &priv->status))
-		goto done;
-
-	/* This should never be called or scheduled if there is currently
-	 * a scan active in the hardware. */
-	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
-		IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. "
-			       "Ignoring second request.\n");
-		goto done;
-	}
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-		IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n");
-		goto done;
-	}
-
-	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-		IWL_DEBUG_HC(priv, "Scan request while abort pending.  Queuing.\n");
-		goto done;
-	}
-
-	if (iwl_is_rfkill(priv)) {
-		IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n");
-		goto done;
-	}
-
-	if (!test_bit(STATUS_READY, &priv->status)) {
-		IWL_DEBUG_HC(priv, "Scan request while uninitialized.  Queuing.\n");
-		goto done;
-	}
+	if (vif)
+		ctx = iwl_rxon_ctx_from_vif(vif);
 
 	if (!priv->scan_cmd) {
 		priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
@@ -1216,7 +1364,7 @@
 		if (!priv->scan_cmd) {
 			IWL_DEBUG_SCAN(priv,
 				       "fail to allocate memory for scan\n");
-			goto done;
+			return -ENOMEM;
 		}
 	}
 	scan = priv->scan_cmd;
@@ -1225,7 +1373,7 @@
 	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
 	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
 
-	if (iwl_is_associated(priv)) {
+	if (iwl_is_any_associated(priv)) {
 		u16 interval = 0;
 		u32 extra;
 		u32 suspend_time = 100;
@@ -1276,13 +1424,15 @@
 		IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
 
 	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
-	scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
+	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->active_rxon.flags & RXON_FLG_CHANNEL_MODE_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;
@@ -1290,35 +1440,42 @@
 			rate = IWL_RATE_1M_PLCP;
 			rate_flags = RATE_MCS_CCK_MSK;
 		}
-		scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED;
+		/*
+		 * Internal scans are passive, so we can indiscriminately set
+		 * the BT ignore flag on 2.4 GHz since it applies to TX only.
+		 */
+		if (priv->cfg->bt_params &&
+		    priv->cfg->bt_params->advanced_bt_coexist)
+			scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
 		break;
 	case IEEE80211_BAND_5GHZ:
 		rate = IWL_RATE_6M_PLCP;
-		/*
-		 * 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;
 		break;
 	default:
-		IWL_WARN(priv, "Invalid scan band count\n");
-		goto done;
+		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])
@@ -1327,6 +1484,14 @@
 	if (priv->cfg->scan_tx_antennas[band])
 		scan_tx_antennas = priv->cfg->scan_tx_antennas[band];
 
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist &&
+	    priv->bt_full_concurrent) {
+		/* operated as 1x1 in full concurrency mode */
+		scan_tx_antennas = first_antenna(
+			priv->cfg->scan_tx_antennas[band]);
+	}
+
 	priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band],
 						    scan_tx_antennas);
 	rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
@@ -1345,6 +1510,13 @@
 
 		rx_ant = first_antenna(active_chains);
 	}
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist &&
+	    priv->bt_full_concurrent) {
+		/* operated as 1x1 in full concurrency mode */
+		rx_ant = first_antenna(rx_ant);
+	}
+
 	/* 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;
@@ -1385,7 +1557,7 @@
 	}
 	if (scan->channel_count == 0) {
 		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
-		goto done;
+		return -EIO;
 	}
 
 	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
@@ -1393,25 +1565,39 @@
 	cmd.data = scan;
 	scan->len = cpu_to_le16(cmd.len);
 
+	/* set scan bit here for PAN params */
 	set_bit(STATUS_SCAN_HW, &priv->status);
-	if (iwl_send_cmd_sync(priv, &cmd))
-		goto done;
 
-	queue_delayed_work(priv->workqueue, &priv->scan_check,
-			   IWL_SCAN_CHECK_WATCHDOG);
+	if (priv->cfg->ops->hcmd->set_pan_params) {
+		ret = priv->cfg->ops->hcmd->set_pan_params(priv);
+		if (ret)
+			return ret;
+	}
 
-	return;
+	ret = iwl_send_cmd_sync(priv, &cmd);
+	if (ret) {
+		clear_bit(STATUS_SCAN_HW, &priv->status);
+		if (priv->cfg->ops->hcmd->set_pan_params)
+			priv->cfg->ops->hcmd->set_pan_params(priv);
+	}
 
- done:
-	/* Cannot perform scan. Make sure we clear scanning
-	* bits from status so next scan request can be performed.
-	* If we don't clear scanning status bit here all next scan
-	* will fail
-	*/
-	clear_bit(STATUS_SCAN_HW, &priv->status);
-	clear_bit(STATUS_SCANNING, &priv->status);
-	/* inform mac80211 scan aborted */
-	queue_work(priv->workqueue, &priv->scan_completed);
+	return ret;
+}
+
+void iwlagn_post_scan(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx;
+
+	/*
+	 * Since setting the RXON may have been deferred while
+	 * performing the scan, fire one off if needed
+	 */
+	for_each_context(priv, ctx)
+		if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+			iwlagn_commit_rxon(priv, ctx);
+
+	if (priv->cfg->ops->hcmd->set_pan_params)
+		priv->cfg->ops->hcmd->set_pan_params(priv);
 }
 
 int iwlagn_manage_ibss_station(struct iwl_priv *priv,
@@ -1420,8 +1606,9 @@
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 
 	if (add)
-		return iwl_add_bssid_station(priv, vif->bss_conf.bssid, true,
-					     &vif_priv->ibss_bssid_sta_id);
+		return iwlagn_add_bssid_station(priv, vif_priv->ctx,
+						vif->bss_conf.bssid,
+						&vif_priv->ibss_bssid_sta_id);
 	return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
 				  vif->bss_conf.bssid);
 }
@@ -1453,7 +1640,7 @@
 
 	/* waiting for all the tx frames complete might take a while */
 	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
-		if (cnt == IWL_CMD_QUEUE_NUM)
+		if (cnt == priv->cmd_queue)
 			continue;
 		txq = &priv->txq[cnt];
 		q = &txq->q;
@@ -1518,3 +1705,669 @@
 	ieee80211_wake_queues(priv->hw);
 	mutex_unlock(&priv->mutex);
 }
+
+/*
+ * BT coex
+ */
+/*
+ * Macros to access the lookup table.
+ *
+ * The lookup table has 7 inputs: bt3_prio, bt3_txrx, bt_rf_act, wifi_req,
+* wifi_prio, wifi_txrx and wifi_sh_ant_req.
+ *
+ * It has three outputs: WLAN_ACTIVE, WLAN_KILL and ANT_SWITCH
+ *
+ * The format is that "registers" 8 through 11 contain the WLAN_ACTIVE bits
+ * one after another in 32-bit registers, and "registers" 0 through 7 contain
+ * the WLAN_KILL and ANT_SWITCH bits interleaved (in that order).
+ *
+ * These macros encode that format.
+ */
+#define LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, wifi_req, wifi_prio, \
+		  wifi_txrx, wifi_sh_ant_req) \
+	(bt3_prio | (bt3_txrx << 1) | (bt_rf_act << 2) | (wifi_req << 3) | \
+	(wifi_prio << 4) | (wifi_txrx << 5) | (wifi_sh_ant_req << 6))
+
+#define LUT_PTA_WLAN_ACTIVE_OP(lut, op, val) \
+	lut[8 + ((val) >> 5)] op (cpu_to_le32(BIT((val) & 0x1f)))
+#define LUT_TEST_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+				 wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+	(!!(LUT_PTA_WLAN_ACTIVE_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, \
+				   bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
+				   wifi_sh_ant_req))))
+#define LUT_SET_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+				wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+	LUT_PTA_WLAN_ACTIVE_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, \
+			       bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
+			       wifi_sh_ant_req))
+#define LUT_CLEAR_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \
+				  wifi_req, wifi_prio, wifi_txrx, \
+				  wifi_sh_ant_req) \
+	LUT_PTA_WLAN_ACTIVE_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, \
+			       bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
+			       wifi_sh_ant_req))
+
+#define LUT_WLAN_KILL_OP(lut, op, val) \
+	lut[(val) >> 4] op (cpu_to_le32(BIT(((val) << 1) & 0x1e)))
+#define LUT_TEST_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+			   wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+	(!!(LUT_WLAN_KILL_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+			     wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))))
+#define LUT_SET_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+			  wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+	LUT_WLAN_KILL_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+			 wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+#define LUT_CLEAR_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+			    wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+	LUT_WLAN_KILL_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+			 wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+
+#define LUT_ANT_SWITCH_OP(lut, op, val) \
+	lut[(val) >> 4] op (cpu_to_le32(BIT((((val) << 1) & 0x1e) + 1)))
+#define LUT_TEST_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+			    wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+	(!!(LUT_ANT_SWITCH_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+			      wifi_req, wifi_prio, wifi_txrx, \
+			      wifi_sh_ant_req))))
+#define LUT_SET_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+			   wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+	LUT_ANT_SWITCH_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+			  wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+#define LUT_CLEAR_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+			     wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+	LUT_ANT_SWITCH_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+			  wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+
+static const __le32 iwlagn_def_3w_lookup[12] = {
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaeaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xcc00ff28),
+	cpu_to_le32(0x0000aaaa),
+	cpu_to_le32(0xcc00aaaa),
+	cpu_to_le32(0x0000aaaa),
+	cpu_to_le32(0xc0004000),
+	cpu_to_le32(0x00004000),
+	cpu_to_le32(0xf0005000),
+	cpu_to_le32(0xf0004000),
+};
+
+static const __le32 iwlagn_concurrent_lookup[12] = {
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0xaaaaaaaa),
+	cpu_to_le32(0x00000000),
+	cpu_to_le32(0x00000000),
+	cpu_to_le32(0x00000000),
+	cpu_to_le32(0x00000000),
+};
+
+void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
+{
+	struct iwlagn_bt_cmd bt_cmd = {
+		.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,
+	};
+
+	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;
+	bt_cmd.valid = priv->bt_valid;
+	bt_cmd.tx_prio_boost = 0;
+	bt_cmd.rx_prio_boost = 0;
+
+	/*
+	 * Configure BT coex mode to "no coexistence" when the
+	 * user disabled BT coexistence, we have no interface
+	 * (might be in monitor mode), or the interface is in
+	 * IBSS mode (no proper uCode support for coex then).
+	 */
+	if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) {
+		bt_cmd.flags = 0;
+	} else {
+		bt_cmd.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
+					IWLAGN_BT_FLAG_COEX_MODE_SHIFT;
+		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);
+	}
+	if (priv->bt_full_concurrent)
+		memcpy(bt_cmd.bt3_lookup_table, iwlagn_concurrent_lookup,
+			sizeof(iwlagn_concurrent_lookup));
+	else
+		memcpy(bt_cmd.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",
+		       priv->bt_full_concurrent ?
+		       "full concurrency" : "3-wire");
+
+	if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd))
+		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)
+{
+	struct iwl_priv *priv =
+		container_of(work, struct iwl_priv, bt_traffic_change_work);
+	struct iwl_rxon_context *ctx;
+	int smps_request = -1;
+
+	IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
+		       priv->bt_traffic_load);
+
+	switch (priv->bt_traffic_load) {
+	case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+		smps_request = IEEE80211_SMPS_AUTOMATIC;
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+		smps_request = IEEE80211_SMPS_DYNAMIC;
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+		smps_request = IEEE80211_SMPS_STATIC;
+		break;
+	default:
+		IWL_ERR(priv, "Invalid BT traffic load: %d\n",
+			priv->bt_traffic_load);
+		break;
+	}
+
+	mutex_lock(&priv->mutex);
+
+	if (priv->cfg->ops->lib->update_chain_flags)
+		priv->cfg->ops->lib->update_chain_flags(priv);
+
+	if (smps_request != -1) {
+		for_each_context(priv, ctx) {
+			if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION)
+				ieee80211_request_smps(ctx->vif, smps_request);
+		}
+	}
+
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwlagn_print_uartmsg(struct iwl_priv *priv,
+				struct iwl_bt_uart_msg *uart_msg)
+{
+	IWL_DEBUG_NOTIF(priv, "Message Type = 0x%X, SSN = 0x%X, "
+			"Update Req = 0x%X",
+		(BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >>
+			BT_UART_MSG_FRAME1MSGTYPE_POS,
+		(BT_UART_MSG_FRAME1SSN_MSK & uart_msg->frame1) >>
+			BT_UART_MSG_FRAME1SSN_POS,
+		(BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >>
+			BT_UART_MSG_FRAME1UPDATEREQ_POS);
+
+	IWL_DEBUG_NOTIF(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
+			"Chl_SeqN = 0x%X, In band = 0x%X",
+		(BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >>
+			BT_UART_MSG_FRAME2OPENCONNECTIONS_POS,
+		(BT_UART_MSG_FRAME2TRAFFICLOAD_MSK & uart_msg->frame2) >>
+			BT_UART_MSG_FRAME2TRAFFICLOAD_POS,
+		(BT_UART_MSG_FRAME2CHLSEQN_MSK & uart_msg->frame2) >>
+			BT_UART_MSG_FRAME2CHLSEQN_POS,
+		(BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >>
+			BT_UART_MSG_FRAME2INBAND_POS);
+
+	IWL_DEBUG_NOTIF(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
+			"ACL = 0x%X, Master = 0x%X, OBEX = 0x%X",
+		(BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
+			BT_UART_MSG_FRAME3SCOESCO_POS,
+		(BT_UART_MSG_FRAME3SNIFF_MSK & uart_msg->frame3) >>
+			BT_UART_MSG_FRAME3SNIFF_POS,
+		(BT_UART_MSG_FRAME3A2DP_MSK & uart_msg->frame3) >>
+			BT_UART_MSG_FRAME3A2DP_POS,
+		(BT_UART_MSG_FRAME3ACL_MSK & uart_msg->frame3) >>
+			BT_UART_MSG_FRAME3ACL_POS,
+		(BT_UART_MSG_FRAME3MASTER_MSK & uart_msg->frame3) >>
+			BT_UART_MSG_FRAME3MASTER_POS,
+		(BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >>
+			BT_UART_MSG_FRAME3OBEX_POS);
+
+	IWL_DEBUG_NOTIF(priv, "Idle duration = 0x%X",
+		(BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >>
+			BT_UART_MSG_FRAME4IDLEDURATION_POS);
+
+	IWL_DEBUG_NOTIF(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
+			"eSCO Retransmissions = 0x%X",
+		(BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >>
+			BT_UART_MSG_FRAME5TXACTIVITY_POS,
+		(BT_UART_MSG_FRAME5RXACTIVITY_MSK & uart_msg->frame5) >>
+			BT_UART_MSG_FRAME5RXACTIVITY_POS,
+		(BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >>
+			BT_UART_MSG_FRAME5ESCORETRANSMIT_POS);
+
+	IWL_DEBUG_NOTIF(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",
+		(BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >>
+			BT_UART_MSG_FRAME6SNIFFINTERVAL_POS,
+		(BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >>
+			BT_UART_MSG_FRAME6DISCOVERABLE_POS);
+
+	IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Inquiry/Page SR Mode = "
+			"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_FRAME7CONNECTABLE_MSK & uart_msg->frame7) >>
+			BT_UART_MSG_FRAME7CONNECTABLE_POS);
+}
+
+static void iwlagn_set_kill_ack_msk(struct iwl_priv *priv,
+				     struct iwl_bt_uart_msg *uart_msg)
+{
+	u8 kill_ack_msk;
+	__le32 bt_kill_ack_msg[2] = {
+			cpu_to_le32(0xFFFFFFF), cpu_to_le32(0xFFFFFC00) };
+
+	kill_ack_msk = (((BT_UART_MSG_FRAME3A2DP_MSK |
+			BT_UART_MSG_FRAME3SNIFF_MSK |
+			BT_UART_MSG_FRAME3SCOESCO_MSK) &
+			uart_msg->frame3) == 0) ? 1 : 0;
+	if (priv->kill_ack_mask != bt_kill_ack_msg[kill_ack_msk]) {
+		priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK;
+		priv->kill_ack_mask = bt_kill_ack_msg[kill_ack_msk];
+		/* schedule to send runtime bt_config */
+		queue_work(priv->workqueue, &priv->bt_runtime_config);
+	}
+
+}
+
+void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
+					     struct iwl_rx_mem_buffer *rxb)
+{
+	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;
+	u8 last_traffic_load;
+
+	IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
+	IWL_DEBUG_NOTIF(priv, "    status: %d\n", coex->bt_status);
+	IWL_DEBUG_NOTIF(priv, "    traffic load: %d\n", coex->bt_traffic_load);
+	IWL_DEBUG_NOTIF(priv, "    CI compliance: %d\n",
+			coex->bt_ci_compliance);
+	iwlagn_print_uartmsg(priv, uart_msg);
+
+	last_traffic_load = priv->notif_bt_traffic_load;
+	priv->notif_bt_traffic_load = coex->bt_traffic_load;
+	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
+		if (priv->bt_status != coex->bt_status ||
+		    last_traffic_load != coex->bt_traffic_load) {
+			if (coex->bt_status) {
+				/* BT on */
+				if (!priv->bt_ch_announce)
+					priv->bt_traffic_load =
+						IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
+				else
+					priv->bt_traffic_load =
+						coex->bt_traffic_load;
+			} else {
+				/* BT off */
+				priv->bt_traffic_load =
+					IWL_BT_COEX_TRAFFIC_LOAD_NONE;
+			}
+			priv->bt_status = coex->bt_status;
+			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_ack_msk(priv, uart_msg);
+
+	/* FIXME: based on notification, adjust the prio_boost */
+
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->bt_ci_compliance = coex->bt_ci_compliance;
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv)
+{
+	iwlagn_rx_handler_setup(priv);
+	priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] =
+		iwlagn_bt_coex_profile_notif;
+}
+
+void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv)
+{
+	iwlagn_setup_deferred_work(priv);
+
+	INIT_WORK(&priv->bt_traffic_change_work,
+		  iwlagn_bt_traffic_change_work);
+}
+
+void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv)
+{
+	cancel_work_sync(&priv->bt_traffic_change_work);
+}
+
+static bool 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 iwl_get_active_rx_chain_count(struct iwl_priv *priv)
+{
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist &&
+	    (priv->bt_full_concurrent ||
+	     priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
+		/*
+		 * only use chain 'A' in bt high traffic load or
+		 * full concurrency mode
+		 */
+		return IWL_NUM_RX_CHAINS_SINGLE;
+	}
+	/* # of Rx chains to use when expecting MIMO. */
+	if (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 iwl_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 iwl_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;
+}
+
+/**
+ * iwlagn_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 iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	bool is_single = 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, iwl_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;
+
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist &&
+	    (priv->bt_full_concurrent ||
+	     priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
+		/*
+		 * only use chain 'A' in bt high traffic load or
+		 * full concurrency mode
+		 */
+		active_chains = first_antenna(active_chains);
+	}
+
+	rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
+
+	/* How many receivers should we use? */
+	active_rx_cnt = iwl_get_active_rx_chain_count(priv);
+	idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
+
+
+	/* correct rx chain count according hw settings
+	 * and chain noise calibration
+	 */
+	valid_rx_cnt = iwl_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 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
+{
+	int i;
+	u8 ind = ant;
+
+	if (priv->band == IEEE80211_BAND_2GHZ &&
+	    priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)
+		return 0;
+
+	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 *get_csr_string(int cmd)
+{
+	switch (cmd) {
+	IWL_CMD(CSR_HW_IF_CONFIG_REG);
+	IWL_CMD(CSR_INT_COALESCING);
+	IWL_CMD(CSR_INT);
+	IWL_CMD(CSR_INT_MASK);
+	IWL_CMD(CSR_FH_INT_STATUS);
+	IWL_CMD(CSR_GPIO_IN);
+	IWL_CMD(CSR_RESET);
+	IWL_CMD(CSR_GP_CNTRL);
+	IWL_CMD(CSR_HW_REV);
+	IWL_CMD(CSR_EEPROM_REG);
+	IWL_CMD(CSR_EEPROM_GP);
+	IWL_CMD(CSR_OTP_GP_REG);
+	IWL_CMD(CSR_GIO_REG);
+	IWL_CMD(CSR_GP_UCODE_REG);
+	IWL_CMD(CSR_GP_DRIVER_REG);
+	IWL_CMD(CSR_UCODE_DRV_GP1);
+	IWL_CMD(CSR_UCODE_DRV_GP2);
+	IWL_CMD(CSR_LED_REG);
+	IWL_CMD(CSR_DRAM_INT_TBL_REG);
+	IWL_CMD(CSR_GIO_CHICKEN_BITS);
+	IWL_CMD(CSR_ANA_PLL_CFG);
+	IWL_CMD(CSR_HW_REV_WA_REG);
+	IWL_CMD(CSR_DBG_HPET_MEM_REG);
+	default:
+		return "UNKNOWN";
+	}
+}
+
+void iwl_dump_csr(struct iwl_priv *priv)
+{
+	int i;
+	u32 csr_tbl[] = {
+		CSR_HW_IF_CONFIG_REG,
+		CSR_INT_COALESCING,
+		CSR_INT,
+		CSR_INT_MASK,
+		CSR_FH_INT_STATUS,
+		CSR_GPIO_IN,
+		CSR_RESET,
+		CSR_GP_CNTRL,
+		CSR_HW_REV,
+		CSR_EEPROM_REG,
+		CSR_EEPROM_GP,
+		CSR_OTP_GP_REG,
+		CSR_GIO_REG,
+		CSR_GP_UCODE_REG,
+		CSR_GP_DRIVER_REG,
+		CSR_UCODE_DRV_GP1,
+		CSR_UCODE_DRV_GP2,
+		CSR_LED_REG,
+		CSR_DRAM_INT_TBL_REG,
+		CSR_GIO_CHICKEN_BITS,
+		CSR_ANA_PLL_CFG,
+		CSR_HW_REV_WA_REG,
+		CSR_DBG_HPET_MEM_REG
+	};
+	IWL_ERR(priv, "CSR values:\n");
+	IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is "
+		"CSR_INT_PERIODIC_REG)\n");
+	for (i = 0; i <  ARRAY_SIZE(csr_tbl); i++) {
+		IWL_ERR(priv, "  %25s: 0X%08x\n",
+			get_csr_string(csr_tbl[i]),
+			iwl_read32(priv, csr_tbl[i]));
+	}
+}
+
+static const char *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 iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
+{
+	int i;
+#ifdef CONFIG_IWLWIFI_DEBUG
+	int pos = 0;
+	size_t bufsz = 0;
+#endif
+	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_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",
+				get_fh_string(fh_tbl[i]),
+				iwl_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",
+			get_fh_string(fh_tbl[i]),
+			iwl_read_direct32(priv, fh_tbl[i]));
+	}
+	return 0;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 23e5c42..0655536 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -39,6 +39,7 @@
 #include "iwl-dev.h"
 #include "iwl-sta.h"
 #include "iwl-core.h"
+#include "iwl-agn.h"
 
 #define RS_NAME "iwl-agn-rs"
 
@@ -76,12 +77,81 @@
 	/*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_MIMO3_##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 iwl_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 */
+	/* FIXME:RS:          ^^    should be INV (legacy) */
+};
+
+static int iwl_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_MIMO3_6M_PLCP)
+			idx = idx - IWL_RATE_MIMO3_6M_PLCP;
+		else 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(iwl_rates); idx++)
+			if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
+				return idx;
+	}
+
+	return -1;
+}
+
 static void rs_rate_scale_perform(struct iwl_priv *priv,
 				   struct sk_buff *skb,
 				   struct ieee80211_sta *sta,
 				   struct iwl_lq_sta *lq_sta);
 static void rs_fill_link_cmd(struct iwl_priv *priv,
 			     struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
+static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search);
 
 
 #ifdef CONFIG_MAC80211_DEBUGFS
@@ -300,7 +370,19 @@
 				      struct ieee80211_sta *sta)
 {
 	int ret = -EAGAIN;
-	u32 load = rs_tl_get_load(lq_data, tid);
+	u32 load;
+
+	/*
+	 * Don't create TX aggregation sessions when in high
+	 * BT traffic, as they would just be disrupted by BT.
+	 */
+	if (priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) {
+		IWL_ERR(priv, "BT traffic (%d), no aggregation allowed\n",
+			priv->bt_traffic_load);
+		return ret;
+	}
+
+	load = 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",
@@ -502,6 +584,7 @@
 	u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags);
 	u8 mcs;
 
+	memset(tbl, 0, sizeof(struct iwl_scale_tbl_info));
 	*rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags);
 
 	if (*rate_idx  == IWL_RATE_INVALID) {
@@ -588,11 +671,13 @@
  * Green-field mode is valid if the station supports it and
  * there are no non-GF stations present in the BSS.
  */
-static inline u8 rs_use_green(struct ieee80211_sta *sta,
-			      struct iwl_ht_config *ht_conf)
+static bool 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) &&
-		!(ht_conf->non_GF_STA_present);
+		!(ctx->ht.non_gf_sta_present);
 }
 
 /**
@@ -744,6 +829,32 @@
 		(a->is_SGI == b->is_SGI);
 }
 
+static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+			    struct iwl_lq_sta *lq_sta)
+{
+	struct iwl_scale_tbl_info *tbl;
+	bool full_concurrent;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->bt_ci_compliance && priv->bt_ant_couple_ok)
+		full_concurrent = true;
+	else
+		full_concurrent = false;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (priv->bt_full_concurrent != full_concurrent) {
+		priv->bt_full_concurrent = full_concurrent;
+
+		/* Update uCode's rate table. */
+		tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+		rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
+		iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
+
+		queue_work(priv->workqueue, &priv->bt_full_concurrency);
+	}
+}
+
 /*
  * mac80211 sends us Tx status
  */
@@ -763,6 +874,8 @@
 	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");
 
@@ -829,7 +942,7 @@
 		lq_sta->missed_rate_counter++;
 		if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
 			lq_sta->missed_rate_counter = 0;
-			iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
+			iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
 		}
 		/* Regardless, ignore this status info for outdated rate */
 		return;
@@ -848,7 +961,20 @@
 		other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
 	} else {
 		IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n");
-		return;
+		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
+		 */
+		rs_stay_in_table(lq_sta, true);
+		goto done;
 	}
 
 	/*
@@ -909,10 +1035,14 @@
 	}
 	/* 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])
 		rs_rate_scale_perform(priv, skb, sta, lq_sta);
+
+	/* Is there a need to switch between full concurrency and 3-wire? */
+	if (priv->bt_ant_couple_ok)
+		rs_bt_update_lq(priv, ctx, lq_sta);
 }
 
 /*
@@ -1106,6 +1236,8 @@
 	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;
@@ -1126,7 +1258,7 @@
 	tbl->max_search = IWL_MAX_SEARCH;
 	rate_mask = lq_sta->active_mimo2_rate;
 
-	if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+	if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
 		tbl->is_ht40 = 1;
 	else
 		tbl->is_ht40 = 0;
@@ -1160,6 +1292,8 @@
 	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;
@@ -1180,7 +1314,7 @@
 	tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
 	rate_mask = lq_sta->active_mimo3_rate;
 
-	if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+	if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
 		tbl->is_ht40 = 1;
 	else
 		tbl->is_ht40 = 0;
@@ -1215,6 +1349,8 @@
 	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;
@@ -1227,7 +1363,7 @@
 	tbl->max_search = IWL_MAX_SEARCH;
 	rate_mask = lq_sta->active_siso_rate;
 
-	if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+	if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
 		tbl->is_ht40 = 1;
 	else
 		tbl->is_ht40 = 0;
@@ -1265,18 +1401,52 @@
 	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 = tbl->action;
+	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;
 
+	switch (priv->bt_traffic_load) {
+	case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+		/* nothing */
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+		/* avoid antenna B unless MIMO */
+		valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+		if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2)
+			tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+		/* avoid antenna B and MIMO */
+		valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+		if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 &&
+		    tbl->action != IWL_LEGACY_SWITCH_SISO)
+			tbl->action = IWL_LEGACY_SWITCH_SISO;
+		break;
+	default:
+		IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+		break;
+	}
+
 	if (!iwl_ht_enabled(priv))
 		/* stay in Legacy */
 		tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
 	else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE &&
 		   tbl->action > IWL_LEGACY_SWITCH_SISO)
 		tbl->action = IWL_LEGACY_SWITCH_SISO;
+
+	/* configure as 1x1 if bt full concurrency */
+	if (priv->bt_full_concurrent) {
+		if (!iwl_ht_enabled(priv))
+			tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
+		else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
+			tbl->action = IWL_LEGACY_SWITCH_SISO;
+		valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+	}
+
+	start_action = tbl->action;
 	for (; ;) {
 		lq_sta->action_counter++;
 		switch (tbl->action) {
@@ -1291,7 +1461,10 @@
 				break;
 
 			/* Don't change antenna if success has been great */
-			if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+			if (window->success_ratio >= IWL_RS_GOOD_RATIO &&
+			    !priv->bt_full_concurrent &&
+			    priv->bt_traffic_load ==
+					IWL_BT_COEX_TRAFFIC_LOAD_NONE)
 				break;
 
 			/* Set up search table to try other antenna */
@@ -1403,31 +1576,64 @@
 	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 = tbl->action;
+	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;
 
+	switch (priv->bt_traffic_load) {
+	case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+		/* nothing */
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+		/* avoid antenna B unless MIMO */
+		valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+		if (tbl->action == IWL_SISO_SWITCH_ANTENNA2)
+			tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+		/* avoid antenna B and MIMO */
+		valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+		if (tbl->action != IWL_SISO_SWITCH_ANTENNA1)
+			tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+		break;
+	default:
+		IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+		break;
+	}
+
 	if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE &&
 	    tbl->action > IWL_SISO_SWITCH_ANTENNA2) {
 		/* stay in SISO */
 		tbl->action = IWL_SISO_SWITCH_ANTENNA1;
 	}
+
+	/* configure as 1x1 if bt full concurrency */
+	if (priv->bt_full_concurrent) {
+		valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+		if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
+			tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+	}
+
+	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) ||
+						tx_chains_num <= 1) ||
 			    (tbl->action == IWL_SISO_SWITCH_ANTENNA2 &&
-							tx_chains_num <= 2))
+						tx_chains_num <= 2))
 				break;
 
-			if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+			if (window->success_ratio >= IWL_RS_GOOD_RATIO &&
+			    !priv->bt_full_concurrent &&
+			    priv->bt_traffic_load ==
+					IWL_BT_COEX_TRAFFIC_LOAD_NONE)
 				break;
 
 			memcpy(search_tbl, tbl, sz);
@@ -1541,18 +1747,47 @@
 	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 = tbl->action;
+	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;
 
+	switch (priv->bt_traffic_load) {
+	case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+		/* nothing */
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+		/* avoid antenna B and MIMO */
+		if (tbl->action != IWL_MIMO2_SWITCH_SISO_A)
+			tbl->action = IWL_MIMO2_SWITCH_SISO_A;
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+		/* avoid antenna B unless MIMO */
+		if (tbl->action == IWL_MIMO2_SWITCH_SISO_B ||
+		    tbl->action == IWL_MIMO2_SWITCH_SISO_C)
+			tbl->action = IWL_MIMO2_SWITCH_SISO_A;
+		break;
+	default:
+		IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+		break;
+	}
+
 	if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) &&
 	    (tbl->action < IWL_MIMO2_SWITCH_SISO_A ||
 	     tbl->action > IWL_MIMO2_SWITCH_SISO_C)) {
 		/* switch in SISO */
 		tbl->action = IWL_MIMO2_SWITCH_SISO_A;
 	}
+
+	/* configure as 1x1 if bt full concurrency */
+	if (priv->bt_full_concurrent &&
+	    (tbl->action < IWL_MIMO2_SWITCH_SISO_A ||
+	     tbl->action > IWL_MIMO2_SWITCH_SISO_C))
+		tbl->action = IWL_MIMO2_SWITCH_SISO_A;
+
+	start_action = tbl->action;
 	for (;;) {
 		lq_sta->action_counter++;
 		switch (tbl->action) {
@@ -1682,18 +1917,47 @@
 	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 = tbl->action;
+	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;
 	u8 update_search_tbl_counter = 0;
 
+	switch (priv->bt_traffic_load) {
+	case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+		/* nothing */
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+		/* avoid antenna B and MIMO */
+		if (tbl->action != IWL_MIMO3_SWITCH_SISO_A)
+			tbl->action = IWL_MIMO3_SWITCH_SISO_A;
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+		/* avoid antenna B unless MIMO */
+		if (tbl->action == IWL_MIMO3_SWITCH_SISO_B ||
+		    tbl->action == IWL_MIMO3_SWITCH_SISO_C)
+			tbl->action = IWL_MIMO3_SWITCH_SISO_A;
+		break;
+	default:
+		IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+		break;
+	}
+
 	if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) &&
 	    (tbl->action < IWL_MIMO3_SWITCH_SISO_A ||
 	     tbl->action > IWL_MIMO3_SWITCH_SISO_C)) {
 		/* switch in SISO */
 		tbl->action = IWL_MIMO3_SWITCH_SISO_A;
 	}
+
+	/* configure as 1x1 if bt full concurrency */
+	if (priv->bt_full_concurrent &&
+	    (tbl->action < IWL_MIMO3_SWITCH_SISO_A ||
+	     tbl->action > IWL_MIMO3_SWITCH_SISO_C))
+		tbl->action = IWL_MIMO3_SWITCH_SISO_A;
+
+	start_action = tbl->action;
 	for (;;) {
 		lq_sta->action_counter++;
 		switch (tbl->action) {
@@ -1820,7 +2084,7 @@
  * 2) # times calling this function
  * 3) elapsed time in this mode (not used, for now)
  */
-static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
+static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
 {
 	struct iwl_scale_tbl_info *tbl;
 	int i;
@@ -1851,7 +2115,8 @@
 		 * allow a new search.  Also (below) reset all bitmaps and
 		 * stats in active history.
 		 */
-		if ((lq_sta->total_failed > lq_sta->max_failure_limit) ||
+		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))) {
@@ -1900,6 +2165,7 @@
  * return rate_n_flags as used in the table
  */
 static u32 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)
@@ -1909,7 +2175,7 @@
 	/* Update uCode's rate table. */
 	rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
 	rs_fill_link_cmd(priv, lq_sta, rate);
-	iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
+	iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
 
 	return rate;
 }
@@ -1948,6 +2214,8 @@
 	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");
 
@@ -1986,7 +2254,7 @@
 	if (is_legacy(tbl->lq_type))
 		lq_sta->is_green = 0;
 	else
-		lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
+		lq_sta->is_green = rs_use_green(sta);
 	is_green = lq_sta->is_green;
 
 	/* current tx rate */
@@ -2025,7 +2293,7 @@
 			tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
 			/* get "active" rate info */
 			index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
-			rate = rs_update_rate_tbl(priv, lq_sta,
+			rate = rs_update_rate_tbl(priv, ctx, lq_sta,
 						  tbl, index, is_green);
 		}
 		return;
@@ -2067,7 +2335,7 @@
 
 		/* Should we stay with this modulation mode,
 		 * or search for a new one? */
-		rs_stay_in_table(lq_sta);
+		rs_stay_in_table(lq_sta, false);
 
 		goto out;
 	}
@@ -2215,6 +2483,28 @@
 	if (iwl_tx_ant_restriction(priv) != IWL_ANT_OK_MULTI &&
 		(is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type)))
 		scale_action = -1;
+
+	if ((priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) &&
+	     (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) {
+		if (lq_sta->last_bt_traffic > priv->bt_traffic_load) {
+			/*
+			 * don't set scale_action, don't want to scale up if
+			 * the rate scale doesn't otherwise think that is a
+			 * good idea.
+			 */
+		} else if (lq_sta->last_bt_traffic <= priv->bt_traffic_load) {
+			scale_action = -1;
+		}
+	}
+	lq_sta->last_bt_traffic = priv->bt_traffic_load;
+
+	if ((priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) &&
+	     (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) {
+		/* search for a new modulation */
+		rs_stay_in_table(lq_sta, true);
+		goto lq_update;
+	}
+
 	switch (scale_action) {
 	case -1:
 		/* Decrease starting rate, update uCode's rate table */
@@ -2245,13 +2535,13 @@
 lq_update:
 	/* Replace uCode's rate table for the destination station. */
 	if (update_lq)
-		rate = rs_update_rate_tbl(priv, lq_sta,
+		rate = rs_update_rate_tbl(priv, ctx, lq_sta,
 					  tbl, index, is_green);
 
 	if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) {
 		/* Should we stay with this modulation mode,
 		 * or search for a new one? */
-		rs_stay_in_table(lq_sta);
+	  rs_stay_in_table(lq_sta, false);
 	}
 	/*
 	 * Search for new modulation mode if we're:
@@ -2287,7 +2577,7 @@
 			IWL_DEBUG_RATE(priv, "Switch current  mcs: %X index: %d\n",
 				     tbl->current_rate, index);
 			rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
-			iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
+			iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
 		} else
 			done_search = 1;
 	}
@@ -2357,12 +2647,17 @@
 	int rate_idx;
 	int i;
 	u32 rate;
-	u8 use_green = rs_use_green(sta, &priv->current_ht_config);
+	u8 use_green = 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)
-		goto out;
+		return;
+
+	sta_priv = (void *)sta->drv_priv;
+	ctx = sta_priv->common.ctx;
 
 	i = lq_sta->last_txrate_idx;
 
@@ -2394,9 +2689,7 @@
 	rs_set_expected_tpt_table(lq_sta, tbl);
 	rs_fill_link_cmd(NULL, lq_sta, rate);
 	priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq;
-	iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true);
- out:
-	return;
+	iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_SYNC, true);
 }
 
 static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
@@ -2524,7 +2817,7 @@
 	lq_sta->is_dup = 0;
 	lq_sta->max_rate_idx = -1;
 	lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
-	lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
+	lq_sta->is_green = rs_use_green(sta);
 	lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
 	lq_sta->band = priv->band;
 	/*
@@ -2594,10 +2887,15 @@
 	rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
 
 	/* Interpret new_rate (rate_n_flags) */
-	memset(&tbl_type, 0, sizeof(tbl_type));
 	rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
 				  &tbl_type, &rate_idx);
 
+	if (priv && priv->bt_full_concurrent) {
+		/* 1x1 only */
+		tbl_type.ant_type =
+			first_antenna(priv->hw_params.valid_tx_ant);
+	}
+
 	/* How many times should we repeat the initial rate? */
 	if (is_legacy(tbl_type.lq_type)) {
 		ant_toggle_cnt = 1;
@@ -2622,9 +2920,12 @@
 
 	index++;
 	repeat_rate--;
-
-	if (priv)
-		valid_tx_ant = priv->hw_params.valid_tx_ant;
+	if (priv) {
+		if (priv->bt_full_concurrent)
+			valid_tx_ant = ANT_A;
+		else
+			valid_tx_ant = priv->hw_params.valid_tx_ant;
+	}
 
 	/* Fill rest of rate table */
 	while (index < LINK_QUAL_MAX_RETRY_NUM) {
@@ -2639,7 +2940,7 @@
 					 rs_toggle_antenna(valid_tx_ant,
 							&new_rate, &tbl_type))
 					ant_toggle_cnt = 1;
-}
+			}
 
 			/* Override next rate if needed for debug purposes */
 			rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
@@ -2654,6 +2955,12 @@
 		rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type,
 						&rate_idx);
 
+		if (priv && priv->bt_full_concurrent) {
+			/* 1x1 only */
+			tbl_type.ant_type =
+				first_antenna(priv->hw_params.valid_tx_ant);
+		}
+
 		/* 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. */
@@ -2694,8 +3001,21 @@
 
 	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);
+	/*
+	 * overwrite if needed, pass aggregation time limit
+	 * to uCode in uSec
+	 */
+	if (priv && priv->cfg->bt_params &&
+	    priv->cfg->bt_params->agg_time_limit &&
+	    priv->cfg->bt_params->agg_time_limit >=
+		LINK_QUAL_AGG_TIME_LIMIT_MIN &&
+	    priv->cfg->bt_params->agg_time_limit <=
+		 LINK_QUAL_AGG_TIME_LIMIT_MAX)
+		lq_cmd->agg_params.agg_time_limit =
+			cpu_to_le16(priv->cfg->bt_params->agg_time_limit);
 }
 
 static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
@@ -2760,6 +3080,9 @@
 	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));
@@ -2782,7 +3105,8 @@
 
 	if (lq_sta->dbg_fixed_rate) {
 		rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
-		iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false);
+		iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
+				false);
 	}
 
 	return count;
@@ -2873,6 +3197,7 @@
 	.write = rs_sta_dbgfs_scale_table_write,
 	.read = rs_sta_dbgfs_scale_table_read,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
 			char __user *user_buf, size_t count, loff_t *ppos)
@@ -2915,6 +3240,7 @@
 static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
 	.read = rs_sta_dbgfs_stats_table_read,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
@@ -2946,6 +3272,7 @@
 static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
 	.read = rs_sta_dbgfs_rate_scale_data_read,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static void rs_add_debugfs(void *priv, void *priv_sta,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index 8292f6d..75e50d3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -299,7 +299,6 @@
 #define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
 
 extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
-extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
 
 enum iwl_table_type {
 	LQ_NONE,
@@ -432,6 +431,8 @@
 	u32 last_rate_n_flags;
 	/* packets destined for this STA are aggregated */
 	u8 is_agg;
+	/* BT traffic this sta was last updated in */
+	u8 last_bt_traffic;
 };
 
 static inline u8 num_of_ant(u8 mask)
@@ -451,24 +452,6 @@
 }
 
 
-static inline u8 iwl_get_prev_ieee_rate(u8 rate_index)
-{
-	u8 rate = iwl_rates[rate_index].prev_ieee;
-
-	if (rate == IWL_RATE_INVALID)
-		rate = rate_index;
-	return rate;
-}
-
-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;
-}
-
 /**
  * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info
  *
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 9490ece..bbd40b7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -34,7 +34,7 @@
 
 #include "iwl-dev.h"
 #include "iwl-core.h"
-#include "iwl-calib.h"
+#include "iwl-agn-calib.h"
 #include "iwl-sta.h"
 #include "iwl-io.h"
 #include "iwl-helpers.h"
@@ -73,7 +73,8 @@
 	int bcn_silence_a, bcn_silence_b, bcn_silence_c;
 	int last_rx_noise;
 
-	if (priv->cfg->bt_statistics)
+	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);
@@ -124,7 +125,8 @@
 	struct statistics_general_common *general, *accum_general;
 	struct statistics_tx *tx, *accum_tx;
 
-	if (priv->cfg->bt_statistics) {
+	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);
@@ -183,7 +185,7 @@
 	unsigned int plcp_msec;
 	unsigned long plcp_received_jiffies;
 
-	if (priv->cfg->plcp_delta_threshold ==
+	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;
@@ -205,7 +207,8 @@
 		struct statistics_rx_phy *ofdm;
 		struct statistics_rx_ht_phy *ofdm_ht;
 
-		if (priv->cfg->bt_statistics) {
+		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 =
@@ -229,7 +232,7 @@
 
 		if ((combined_plcp_delta > 0) &&
 		    ((combined_plcp_delta * 100) / plcp_msec) >
-			priv->cfg->plcp_delta_threshold) {
+			priv->cfg->base_params->plcp_delta_threshold) {
 			/*
 			 * if plcp_err exceed the threshold,
 			 * the following data is printed in csv format:
@@ -242,13 +245,13 @@
 			 *    plcp_msec
 			 */
 			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
-				    "%u, %u, %u, %u, %d, %u mSecs\n",
-				    priv->cfg->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);
+				"%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;
 		}
@@ -262,7 +265,8 @@
 	int change;
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 
-	if (priv->cfg->bt_statistics) {
+	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),
@@ -300,7 +304,8 @@
 
 	iwl_recover_from_statistics(priv, pkt);
 
-	if (priv->cfg->bt_statistics)
+	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
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
new file mode 100644
index 0000000..35a30d2
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -0,0 +1,716 @@
+/******************************************************************************
+ *
+ * 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
+ *
+ *****************************************************************************/
+
+#include <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-agn.h"
+
+static struct iwl_link_quality_cmd *
+iwl_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 |= first_antenna(priv->hw_params.valid_tx_ant) <<
+				RATE_MCS_ANT_POS;
+	rate_n_flags = iwl_hw_set_rate_n_flags(iwl_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 =
+				first_antenna(priv->hw_params.valid_tx_ant);
+
+	link_cmd->general_params.dual_stream_ant_msk =
+		priv->hw_params.valid_tx_ant &
+		~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 (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;
+}
+
+/*
+ * iwlagn_add_bssid_station - Add the special IBSS BSSID station
+ *
+ * Function sleeps.
+ */
+int iwlagn_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_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 = iwl_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_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 iwl_send_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_send_cmd(priv, &cmd);
+	else
+		return 0;
+}
+
+int iwl_restore_default_wep_keys(struct iwl_priv *priv,
+				 struct iwl_rxon_context *ctx)
+{
+	lockdep_assert_held(&priv->mutex);
+
+	return iwl_send_static_wepkey_cmd(priv, ctx, false);
+}
+
+int iwl_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_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 = iwl_send_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 iwl_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 = iwl_send_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 iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
+					struct iwl_rxon_context *ctx,
+					struct ieee80211_key_conf *keyconf,
+					u8 sta_id)
+{
+	unsigned long flags;
+	__le16 key_flags = 0;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
+
+	key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
+	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+	key_flags &= ~STA_KEY_FLG_INVALID;
+
+	if (keyconf->keylen == WEP_KEY_LEN_128)
+		key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
+
+	if (sta_id == ctx->bcast_sta_id)
+		key_flags |= STA_KEY_MULTICAST_MSK;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+	priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
+
+	memcpy(priv->stations[sta_id].keyinfo.key,
+				keyconf->key, keyconf->keylen);
+
+	memcpy(&priv->stations[sta_id].sta.key.key[3],
+				keyconf->key, keyconf->keylen);
+
+	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+			== STA_KEY_FLG_NO_ENC)
+		priv->stations[sta_id].sta.key.key_offset =
+				 iwl_get_free_ucode_key_index(priv);
+	/* else, we are overriding an existing key => no need to allocated room
+	 * in uCode. */
+
+	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+		"no space for a new key");
+
+	priv->stations[sta_id].sta.key.key_flags = key_flags;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
+					 struct iwl_rxon_context *ctx,
+					 struct ieee80211_key_conf *keyconf,
+					 u8 sta_id)
+{
+	unsigned long flags;
+	__le16 key_flags = 0;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
+	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+	key_flags &= ~STA_KEY_FLG_INVALID;
+
+	if (sta_id == ctx->bcast_sta_id)
+		key_flags |= STA_KEY_MULTICAST_MSK;
+
+	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+
+	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
+	       keyconf->keylen);
+
+	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
+	       keyconf->keylen);
+
+	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+			== STA_KEY_FLG_NO_ENC)
+		priv->stations[sta_id].sta.key.key_offset =
+				 iwl_get_free_ucode_key_index(priv);
+	/* else, we are overriding an existing key => no need to allocated room
+	 * in uCode. */
+
+	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+		"no space for a new key");
+
+	priv->stations[sta_id].sta.key.key_flags = key_flags;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
+					 struct iwl_rxon_context *ctx,
+					 struct ieee80211_key_conf *keyconf,
+					 u8 sta_id)
+{
+	unsigned long flags;
+	int ret = 0;
+	__le16 key_flags = 0;
+
+	key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
+	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+	key_flags &= ~STA_KEY_FLG_INVALID;
+
+	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_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 iwl_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_scan_cancel(priv)) {
+		/* cancel scan failed, just live w/ bad key and rely
+		   briefly on SW decryption */
+		return;
+	}
+
+	sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta);
+	if (sta_id == IWL_INVALID_STATION)
+		return;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
+
+	for (i = 0; i < 5; i++)
+		priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
+			cpu_to_le16(phase1key[i]);
+
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+}
+
+int iwl_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_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_is_rfkill(priv)) {
+		IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+		return 0;
+	}
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+			struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+	int 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 = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id);
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id);
+		break;
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		ret = iwl_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;
+}
+
+/**
+ * iwlagn_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 iwlagn_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_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);
+
+	link_cmd = iwl_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;
+}
+
+/**
+ * iwl_update_bcast_station - update broadcast station's LQ command
+ *
+ * Only used by iwlagn. Placed here to have all bcast station management
+ * code together.
+ */
+static int iwl_update_bcast_station(struct iwl_priv *priv,
+				    struct iwl_rxon_context *ctx)
+{
+	unsigned long flags;
+	struct iwl_link_quality_cmd *link_cmd;
+	u8 sta_id = ctx->bcast_sta_id;
+
+	link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+	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 iwl_update_bcast_stations(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx;
+	int ret = 0;
+
+	for_each_context(priv, ctx) {
+		ret = iwl_update_bcast_station(priv, ctx);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+/**
+ * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
+ */
+int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
+{
+	unsigned long flags;
+	struct iwl_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_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			 int tid, u16 ssn)
+{
+	unsigned long flags;
+	int sta_id;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	sta_id = iwl_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_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			int tid)
+{
+	unsigned long flags;
+	int sta_id;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	sta_id = iwl_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_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
+{
+	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 = 0;
+	priv->stations[sta_id].sta.sleep_tx_count = 0;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+}
+
+void iwl_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_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
new file mode 100644
index 0000000..e3a8216
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
@@ -0,0 +1,699 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 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
+ *****************************************************************************/
+
+
+#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-agn-tt.h"
+
+/* default Thermal Throttling transaction table
+ * Current state   |         Throttling Down               |  Throttling Up
+ *=============================================================================
+ *                 Condition Nxt State  Condition Nxt State Condition Nxt State
+ *-----------------------------------------------------------------------------
+ *     IWL_TI_0     T >= 114   CT_KILL  114>T>=105   TI_1      N/A      N/A
+ *     IWL_TI_1     T >= 114   CT_KILL  114>T>=110   TI_2     T<=95     TI_0
+ *     IWL_TI_2     T >= 114   CT_KILL                        T<=100    TI_1
+ *    IWL_CT_KILL      N/A       N/A       N/A        N/A     T<=95     TI_0
+ *=============================================================================
+ */
+static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
+	{IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
+	{IWL_TI_1, 105, CT_KILL_THRESHOLD - 1},
+	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
+	{IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
+	{IWL_TI_2, 110, CT_KILL_THRESHOLD - 1},
+	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
+	{IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
+	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX},
+	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
+	{IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
+	{IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
+	{IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
+};
+
+/* Advance Thermal Throttling default restriction table */
+static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
+	{IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true },
+	{IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true },
+	{IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false },
+	{IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
+};
+
+bool iwl_tt_is_low_power_state(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	if (tt->state >= IWL_TI_1)
+		return true;
+	return false;
+}
+
+u8 iwl_tt_current_power_mode(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	return tt->tt_power_mode;
+}
+
+bool iwl_ht_enabled(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	struct iwl_tt_restriction *restriction;
+
+	if (!priv->thermal_throttle.advanced_tt)
+		return true;
+	restriction = tt->restriction + tt->state;
+	return restriction->is_ht;
+}
+
+static bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
+{
+	s32 temp = priv->temperature; /* degrees CELSIUS except specified */
+	bool within_margin = false;
+
+	if (priv->cfg->base_params->temperature_kelvin)
+		temp = KELVIN_TO_CELSIUS(priv->temperature);
+
+	if (!priv->thermal_throttle.advanced_tt)
+		within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
+				CT_KILL_THRESHOLD_LEGACY) ? true : false;
+	else
+		within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
+				CT_KILL_THRESHOLD) ? true : false;
+	return within_margin;
+}
+
+bool iwl_check_for_ct_kill(struct iwl_priv *priv)
+{
+	bool is_ct_kill = false;
+
+	if (iwl_within_ct_kill_margin(priv)) {
+		iwl_tt_enter_ct_kill(priv);
+		is_ct_kill = true;
+	}
+	return is_ct_kill;
+}
+
+enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	struct iwl_tt_restriction *restriction;
+
+	if (!priv->thermal_throttle.advanced_tt)
+		return IWL_ANT_OK_MULTI;
+	restriction = tt->restriction + tt->state;
+	return restriction->tx_stream;
+}
+
+enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	struct iwl_tt_restriction *restriction;
+
+	if (!priv->thermal_throttle.advanced_tt)
+		return IWL_ANT_OK_MULTI;
+	restriction = tt->restriction + tt->state;
+	return restriction->rx_stream;
+}
+
+#define CT_KILL_EXIT_DURATION (5)	/* 5 seconds duration */
+#define CT_KILL_WAITING_DURATION (300)	/* 300ms duration */
+
+/*
+ * toggle the bit to wake up uCode and check the temperature
+ * if the temperature is below CT, uCode will stay awake and send card
+ * state notification with CT_KILL bit clear to inform Thermal Throttling
+ * Management to change state. Otherwise, uCode will go back to sleep
+ * without doing anything, driver should continue the 5 seconds timer
+ * to wake up uCode for temperature check until temperature drop below CT
+ */
+static void iwl_tt_check_exit_ct_kill(unsigned long data)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)data;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	unsigned long flags;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (tt->state == IWL_TI_CT_KILL) {
+		if (priv->thermal_throttle.ct_kill_toggle) {
+			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+			priv->thermal_throttle.ct_kill_toggle = false;
+		} else {
+			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+			priv->thermal_throttle.ct_kill_toggle = true;
+		}
+		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);
+
+		/* Reschedule the ct_kill timer to occur in
+		 * CT_KILL_EXIT_DURATION seconds to ensure we get a
+		 * thermal update */
+		IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
+		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
+			  jiffies + CT_KILL_EXIT_DURATION * HZ);
+	}
+}
+
+static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
+			   bool stop)
+{
+	if (stop) {
+		IWL_DEBUG_POWER(priv, "Stop all queues\n");
+		if (priv->mac80211_registered)
+			ieee80211_stop_queues(priv->hw);
+		IWL_DEBUG_POWER(priv,
+				"Schedule 5 seconds CT_KILL Timer\n");
+		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
+			  jiffies + CT_KILL_EXIT_DURATION * HZ);
+	} else {
+		IWL_DEBUG_POWER(priv, "Wake all queues\n");
+		if (priv->mac80211_registered)
+			ieee80211_wake_queues(priv->hw);
+	}
+}
+
+static void iwl_tt_ready_for_ct_kill(unsigned long data)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)data;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* temperature timer expired, ready to go into CT_KILL state */
+	if (tt->state != IWL_TI_CT_KILL) {
+		IWL_DEBUG_POWER(priv, "entering CT_KILL state when "
+				"temperature timer expired\n");
+		tt->state = IWL_TI_CT_KILL;
+		set_bit(STATUS_CT_KILL, &priv->status);
+		iwl_perform_ct_kill_task(priv, true);
+	}
+}
+
+static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
+{
+	IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
+	/* make request to retrieve statistics information */
+	iwl_send_statistics_request(priv, CMD_SYNC, false);
+	/* Reschedule the ct_kill wait timer */
+	mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
+		 jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
+}
+
+#define IWL_MINIMAL_POWER_THRESHOLD		(CT_KILL_THRESHOLD_LEGACY)
+#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2	(100)
+#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1	(90)
+
+/*
+ * Legacy thermal throttling
+ * 1) Avoid NIC destruction due to high temperatures
+ *	Chip will identify dangerously high temperatures that can
+ *	harm the device and will power down
+ * 2) Avoid the NIC power down due to high temperature
+ *	Throttle early enough to lower the power consumption before
+ *	drastic steps are needed
+ */
+static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	enum iwl_tt_state old_state;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+	if ((tt->tt_previous_temp) &&
+	    (temp > tt->tt_previous_temp) &&
+	    ((temp - tt->tt_previous_temp) >
+	    IWL_TT_INCREASE_MARGIN)) {
+		IWL_DEBUG_POWER(priv,
+			"Temperature increase %d degree Celsius\n",
+			(temp - tt->tt_previous_temp));
+	}
+#endif
+	old_state = tt->state;
+	/* in Celsius */
+	if (temp >= IWL_MINIMAL_POWER_THRESHOLD)
+		tt->state = IWL_TI_CT_KILL;
+	else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)
+		tt->state = IWL_TI_2;
+	else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)
+		tt->state = IWL_TI_1;
+	else
+		tt->state = IWL_TI_0;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+	tt->tt_previous_temp = temp;
+#endif
+	/* stop ct_kill_waiting_tm timer */
+	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
+	if (tt->state != old_state) {
+		switch (tt->state) {
+		case IWL_TI_0:
+			/*
+			 * When the system is ready to go back to IWL_TI_0
+			 * we only have to call iwl_power_update_mode() to
+			 * do so.
+			 */
+			break;
+		case IWL_TI_1:
+			tt->tt_power_mode = IWL_POWER_INDEX_3;
+			break;
+		case IWL_TI_2:
+			tt->tt_power_mode = IWL_POWER_INDEX_4;
+			break;
+		default:
+			tt->tt_power_mode = IWL_POWER_INDEX_5;
+			break;
+		}
+		mutex_lock(&priv->mutex);
+		if (old_state == IWL_TI_CT_KILL)
+			clear_bit(STATUS_CT_KILL, &priv->status);
+		if (tt->state != IWL_TI_CT_KILL &&
+		    iwl_power_update_mode(priv, true)) {
+			/* TT state not updated
+			 * try again during next temperature read
+			 */
+			if (old_state == IWL_TI_CT_KILL)
+				set_bit(STATUS_CT_KILL, &priv->status);
+			tt->state = old_state;
+			IWL_ERR(priv, "Cannot update power mode, "
+					"TT state not updated\n");
+		} else {
+			if (tt->state == IWL_TI_CT_KILL) {
+				if (force) {
+					set_bit(STATUS_CT_KILL, &priv->status);
+					iwl_perform_ct_kill_task(priv, true);
+				} else {
+					iwl_prepare_ct_kill_task(priv);
+					tt->state = old_state;
+				}
+			} else if (old_state == IWL_TI_CT_KILL &&
+				 tt->state != IWL_TI_CT_KILL)
+				iwl_perform_ct_kill_task(priv, false);
+			IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
+					tt->state);
+			IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
+					tt->tt_power_mode);
+		}
+		mutex_unlock(&priv->mutex);
+	}
+}
+
+/*
+ * Advance thermal throttling
+ * 1) Avoid NIC destruction due to high temperatures
+ *	Chip will identify dangerously high temperatures that can
+ *	harm the device and will power down
+ * 2) Avoid the NIC power down due to high temperature
+ *	Throttle early enough to lower the power consumption before
+ *	drastic steps are needed
+ *	Actions include relaxing the power down sleep thresholds and
+ *	decreasing the number of TX streams
+ * 3) Avoid throughput performance impact as much as possible
+ *
+ *=============================================================================
+ *                 Condition Nxt State  Condition Nxt State Condition Nxt State
+ *-----------------------------------------------------------------------------
+ *     IWL_TI_0     T >= 114   CT_KILL  114>T>=105   TI_1      N/A      N/A
+ *     IWL_TI_1     T >= 114   CT_KILL  114>T>=110   TI_2     T<=95     TI_0
+ *     IWL_TI_2     T >= 114   CT_KILL                        T<=100    TI_1
+ *    IWL_CT_KILL      N/A       N/A       N/A        N/A     T<=95     TI_0
+ *=============================================================================
+ */
+static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	int i;
+	bool changed = false;
+	enum iwl_tt_state old_state;
+	struct iwl_tt_trans *transaction;
+
+	old_state = tt->state;
+	for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) {
+		/* based on the current TT state,
+		 * find the curresponding transaction table
+		 * each table has (IWL_TI_STATE_MAX - 1) entries
+		 * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1))
+		 * will advance to the correct table.
+		 * then based on the current temperature
+		 * find the next state need to transaction to
+		 * go through all the possible (IWL_TI_STATE_MAX - 1) entries
+		 * in the current table to see if transaction is needed
+		 */
+		transaction = tt->transaction +
+			((old_state * (IWL_TI_STATE_MAX - 1)) + i);
+		if (temp >= transaction->tt_low &&
+		    temp <= transaction->tt_high) {
+#ifdef CONFIG_IWLWIFI_DEBUG
+			if ((tt->tt_previous_temp) &&
+			    (temp > tt->tt_previous_temp) &&
+			    ((temp - tt->tt_previous_temp) >
+			    IWL_TT_INCREASE_MARGIN)) {
+				IWL_DEBUG_POWER(priv,
+					"Temperature increase %d "
+					"degree Celsius\n",
+					(temp - tt->tt_previous_temp));
+			}
+			tt->tt_previous_temp = temp;
+#endif
+			if (old_state !=
+			    transaction->next_state) {
+				changed = true;
+				tt->state =
+					transaction->next_state;
+			}
+			break;
+		}
+	}
+	/* stop ct_kill_waiting_tm timer */
+	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
+	if (changed) {
+		if (tt->state >= IWL_TI_1) {
+			/* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
+			tt->tt_power_mode = IWL_POWER_INDEX_5;
+
+			if (!iwl_ht_enabled(priv)) {
+				struct iwl_rxon_context *ctx;
+
+				for_each_context(priv, ctx) {
+					struct iwl_rxon_cmd *rxon;
+
+					rxon = &ctx->staging;
+
+					/* disable HT */
+					rxon->flags &= ~(
+						RXON_FLG_CHANNEL_MODE_MSK |
+						RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
+						RXON_FLG_HT40_PROT_MSK |
+						RXON_FLG_HT_PROT_MSK);
+				}
+			} else {
+				/* check HT capability and set
+				 * according to the system HT capability
+				 * in case get disabled before */
+				iwl_set_rxon_ht(priv, &priv->current_ht_config);
+			}
+
+		} else {
+			/*
+			 * restore system power setting -- it will be
+			 * recalculated automatically.
+			 */
+
+			/* check HT capability and set
+			 * according to the system HT capability
+			 * in case get disabled before */
+			iwl_set_rxon_ht(priv, &priv->current_ht_config);
+		}
+		mutex_lock(&priv->mutex);
+		if (old_state == IWL_TI_CT_KILL)
+			clear_bit(STATUS_CT_KILL, &priv->status);
+		if (tt->state != IWL_TI_CT_KILL &&
+		    iwl_power_update_mode(priv, true)) {
+			/* TT state not updated
+			 * try again during next temperature read
+			 */
+			IWL_ERR(priv, "Cannot update power mode, "
+					"TT state not updated\n");
+			if (old_state == IWL_TI_CT_KILL)
+				set_bit(STATUS_CT_KILL, &priv->status);
+			tt->state = old_state;
+		} else {
+			IWL_DEBUG_POWER(priv,
+					"Thermal Throttling to new state: %u\n",
+					tt->state);
+			if (old_state != IWL_TI_CT_KILL &&
+			    tt->state == IWL_TI_CT_KILL) {
+				if (force) {
+					IWL_DEBUG_POWER(priv,
+						"Enter IWL_TI_CT_KILL\n");
+					set_bit(STATUS_CT_KILL, &priv->status);
+					iwl_perform_ct_kill_task(priv, true);
+				} else {
+					iwl_prepare_ct_kill_task(priv);
+					tt->state = old_state;
+				}
+			} else if (old_state == IWL_TI_CT_KILL &&
+				  tt->state != IWL_TI_CT_KILL) {
+				IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
+				iwl_perform_ct_kill_task(priv, false);
+			}
+		}
+		mutex_unlock(&priv->mutex);
+	}
+}
+
+/* Card State Notification indicated reach critical temperature
+ * if PSP not enable, no Thermal Throttling function will be performed
+ * just set the GP1 bit to acknowledge the event
+ * otherwise, go into IWL_TI_CT_KILL state
+ * since Card State Notification will not provide any temperature reading
+ * for Legacy mode
+ * so just pass the CT_KILL temperature to iwl_legacy_tt_handler()
+ * for advance mode
+ * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
+ */
+static void iwl_bg_ct_enter(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (!iwl_is_ready(priv))
+		return;
+
+	if (tt->state != IWL_TI_CT_KILL) {
+		IWL_ERR(priv, "Device reached critical temperature "
+			      "- ucode going to sleep!\n");
+		if (!priv->thermal_throttle.advanced_tt)
+			iwl_legacy_tt_handler(priv,
+					      IWL_MINIMAL_POWER_THRESHOLD,
+					      true);
+		else
+			iwl_advance_tt_handler(priv,
+					       CT_KILL_THRESHOLD + 1, true);
+	}
+}
+
+/* Card State Notification indicated out of critical temperature
+ * since Card State Notification will not provide any temperature reading
+ * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature
+ * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state
+ */
+static void iwl_bg_ct_exit(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (!iwl_is_ready(priv))
+		return;
+
+	/* stop ct_kill_exit_tm timer */
+	del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
+
+	if (tt->state == IWL_TI_CT_KILL) {
+		IWL_ERR(priv,
+			"Device temperature below critical"
+			"- ucode awake!\n");
+		/*
+		 * exit from CT_KILL state
+		 * reset the current temperature reading
+		 */
+		priv->temperature = 0;
+		if (!priv->thermal_throttle.advanced_tt)
+			iwl_legacy_tt_handler(priv,
+				      IWL_REDUCED_PERFORMANCE_THRESHOLD_2,
+				      true);
+		else
+			iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,
+					       true);
+	}
+}
+
+void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
+	queue_work(priv->workqueue, &priv->ct_enter);
+}
+
+void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
+	queue_work(priv->workqueue, &priv->ct_exit);
+}
+
+static void iwl_bg_tt_work(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
+	s32 temp = priv->temperature; /* degrees CELSIUS except specified */
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (priv->cfg->base_params->temperature_kelvin)
+		temp = KELVIN_TO_CELSIUS(priv->temperature);
+
+	if (!priv->thermal_throttle.advanced_tt)
+		iwl_legacy_tt_handler(priv, temp, false);
+	else
+		iwl_advance_tt_handler(priv, temp, false);
+}
+
+void iwl_tt_handler(struct iwl_priv *priv)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
+	queue_work(priv->workqueue, &priv->tt_work);
+}
+
+/* Thermal throttling initialization
+ * For advance thermal throttling:
+ *     Initialize Thermal Index and temperature threshold table
+ *     Initialize thermal throttling restriction table
+ */
+void iwl_tt_initialize(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
+	struct iwl_tt_trans *transaction;
+
+	IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n");
+
+	memset(tt, 0, sizeof(struct iwl_tt_mgmt));
+
+	tt->state = IWL_TI_0;
+	init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
+	priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
+	priv->thermal_throttle.ct_kill_exit_tm.function =
+		iwl_tt_check_exit_ct_kill;
+	init_timer(&priv->thermal_throttle.ct_kill_waiting_tm);
+	priv->thermal_throttle.ct_kill_waiting_tm.data =
+		(unsigned long)priv;
+	priv->thermal_throttle.ct_kill_waiting_tm.function =
+		iwl_tt_ready_for_ct_kill;
+	/* setup deferred ct kill work */
+	INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
+	INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
+	INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
+
+	if (priv->cfg->base_params->adv_thermal_throttle) {
+		IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
+		tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
+					 IWL_TI_STATE_MAX, GFP_KERNEL);
+		tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
+			IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1),
+			GFP_KERNEL);
+		if (!tt->restriction || !tt->transaction) {
+			IWL_ERR(priv, "Fallback to Legacy Throttling\n");
+			priv->thermal_throttle.advanced_tt = false;
+			kfree(tt->restriction);
+			tt->restriction = NULL;
+			kfree(tt->transaction);
+			tt->transaction = NULL;
+		} else {
+			transaction = tt->transaction +
+				(IWL_TI_0 * (IWL_TI_STATE_MAX - 1));
+			memcpy(transaction, &tt_range_0[0], size);
+			transaction = tt->transaction +
+				(IWL_TI_1 * (IWL_TI_STATE_MAX - 1));
+			memcpy(transaction, &tt_range_1[0], size);
+			transaction = tt->transaction +
+				(IWL_TI_2 * (IWL_TI_STATE_MAX - 1));
+			memcpy(transaction, &tt_range_2[0], size);
+			transaction = tt->transaction +
+				(IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1));
+			memcpy(transaction, &tt_range_3[0], size);
+			size = sizeof(struct iwl_tt_restriction) *
+				IWL_TI_STATE_MAX;
+			memcpy(tt->restriction,
+				&restriction_range[0], size);
+			priv->thermal_throttle.advanced_tt = true;
+		}
+	} else {
+		IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
+		priv->thermal_throttle.advanced_tt = false;
+	}
+}
+
+/* cleanup thermal throttling management related memory and timer */
+void iwl_tt_exit(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	/* stop ct_kill_exit_tm timer if activated */
+	del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
+	/* stop ct_kill_waiting_tm timer if activated */
+	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
+	cancel_work_sync(&priv->tt_work);
+	cancel_work_sync(&priv->ct_enter);
+	cancel_work_sync(&priv->ct_exit);
+
+	if (priv->thermal_throttle.advanced_tt) {
+		/* free advance thermal throttling memory */
+		kfree(tt->restriction);
+		tt->restriction = NULL;
+		kfree(tt->transaction);
+		tt->transaction = NULL;
+	}
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h
new file mode 100644
index 0000000..d550604
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 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
+ *****************************************************************************/
+#ifndef __iwl_tt_setting_h__
+#define __iwl_tt_setting_h__
+
+#include "iwl-commands.h"
+
+#define IWL_ABSOLUTE_ZERO		0
+#define IWL_ABSOLUTE_MAX		0xFFFFFFFF
+#define IWL_TT_INCREASE_MARGIN	5
+#define IWL_TT_CT_KILL_MARGIN	3
+
+enum iwl_antenna_ok {
+	IWL_ANT_OK_NONE,
+	IWL_ANT_OK_SINGLE,
+	IWL_ANT_OK_MULTI,
+};
+
+/* Thermal Throttling State Machine states */
+enum  iwl_tt_state {
+	IWL_TI_0,	/* normal temperature, system power state */
+	IWL_TI_1,	/* high temperature detect, low power state */
+	IWL_TI_2,	/* higher temperature detected, lower power state */
+	IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */
+	IWL_TI_STATE_MAX
+};
+
+/**
+ * struct iwl_tt_restriction - Thermal Throttling restriction table
+ * @tx_stream: number of tx stream allowed
+ * @is_ht: ht enable/disable
+ * @rx_stream: number of rx stream allowed
+ *
+ * This table is used by advance thermal throttling management
+ * based on the current thermal throttling state, and determines
+ * the number of tx/rx streams and the status of HT operation.
+ */
+struct iwl_tt_restriction {
+	enum iwl_antenna_ok tx_stream;
+	enum iwl_antenna_ok rx_stream;
+	bool is_ht;
+};
+
+/**
+ * struct iwl_tt_trans - Thermal Throttling transaction table
+ * @next_state:  next thermal throttling mode
+ * @tt_low: low temperature threshold to change state
+ * @tt_high: high temperature threshold to change state
+ *
+ * This is used by the advanced thermal throttling algorithm
+ * to determine the next thermal state to go based on the
+ * current temperature.
+ */
+struct iwl_tt_trans {
+	enum iwl_tt_state next_state;
+	u32 tt_low;
+	u32 tt_high;
+};
+
+/**
+ * struct iwl_tt_mgnt - Thermal Throttling Management structure
+ * @advanced_tt:    advanced thermal throttle required
+ * @state:          current Thermal Throttling state
+ * @tt_power_mode:  Thermal Throttling power mode index
+ *		    being used to set power level when
+ *		    when thermal throttling state != IWL_TI_0
+ *		    the tt_power_mode should set to different
+ *		    power mode based on the current tt state
+ * @tt_previous_temperature: last measured temperature
+ * @iwl_tt_restriction: ptr to restriction tbl, used by advance
+ *		    thermal throttling to determine how many tx/rx streams
+ *		    should be used in tt state; and can HT be enabled or not
+ * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling
+ *		    state transaction
+ * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature
+ * @ct_kill_exit_tm: timer to exit thermal kill
+ */
+struct iwl_tt_mgmt {
+	enum iwl_tt_state state;
+	bool advanced_tt;
+	u8 tt_power_mode;
+	bool ct_kill_toggle;
+#ifdef CONFIG_IWLWIFI_DEBUG
+	s32 tt_previous_temp;
+#endif
+	struct iwl_tt_restriction *restriction;
+	struct iwl_tt_trans *transaction;
+	struct timer_list ct_kill_exit_tm;
+	struct timer_list ct_kill_waiting_tm;
+};
+
+u8 iwl_tt_current_power_mode(struct iwl_priv *priv);
+bool iwl_tt_is_low_power_state(struct iwl_priv *priv);
+bool iwl_ht_enabled(struct iwl_priv *priv);
+bool iwl_check_for_ct_kill(struct iwl_priv *priv);
+enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
+enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
+void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
+void iwl_tt_exit_ct_kill(struct iwl_priv *priv);
+void iwl_tt_handler(struct iwl_priv *priv);
+void iwl_tt_initialize(struct iwl_priv *priv);
+void iwl_tt_exit(struct iwl_priv *priv);
+
+#endif  /* __iwl_tt_setting_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 69155aa..db57aea 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -71,18 +71,6 @@
 	2, 3, 3, 2, 1, 1, 0, 0
 };
 
-static const u8 ac_to_fifo[] = {
-	IWL_TX_FIFO_VO,
-	IWL_TX_FIFO_VI,
-	IWL_TX_FIFO_BE,
-	IWL_TX_FIFO_BK,
-};
-
-static inline int get_fifo_from_ac(u8 ac)
-{
-	return ac_to_fifo[ac];
-}
-
 static inline int get_ac_from_tid(u16 tid)
 {
 	if (likely(tid < ARRAY_SIZE(tid_to_ac)))
@@ -92,10 +80,10 @@
 	return -EINVAL;
 }
 
-static inline int get_fifo_from_tid(u16 tid)
+static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid)
 {
 	if (likely(tid < ARRAY_SIZE(tid_to_ac)))
-		return get_fifo_from_ac(tid_to_ac[tid]);
+		return ctx->ac_to_fifo[tid_to_ac[tid]];
 
 	/* no support for TIDs 8-15 yet */
 	return -EINVAL;
@@ -118,7 +106,7 @@
 
 	WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
 
-	if (txq_id != IWL_CMD_QUEUE_NUM) {
+	if (txq_id != priv->cmd_queue) {
 		sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
 		sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
 
@@ -155,7 +143,7 @@
 
 	WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
 
-	if (txq_id != IWL_CMD_QUEUE_NUM)
+	if (txq_id != priv->cmd_queue)
 		sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
 
 	bc_ent = cpu_to_le16(1 | (sta_id << 12));
@@ -236,13 +224,13 @@
 	int ret;
 
 	if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
-	    (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
-	     <= txq_id)) {
+	    (IWLAGN_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, IWLAGN_FIRST_AMPDU_QUEUE,
 			IWLAGN_FIRST_AMPDU_QUEUE +
-			priv->cfg->num_of_ampdu_queues - 1);
+			priv->cfg->base_params->num_of_ampdu_queues - 1);
 		return -EINVAL;
 	}
 
@@ -298,13 +286,13 @@
 			   u16 ssn_idx, u8 tx_fifo)
 {
 	if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
-	    (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
-	     <= txq_id)) {
+	    (IWLAGN_FIRST_AMPDU_QUEUE +
+		priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
 		IWL_ERR(priv,
 			"queue number out of range: %d, must be %d to %d\n",
 			txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
 			IWLAGN_FIRST_AMPDU_QUEUE +
-			priv->cfg->num_of_ampdu_queues - 1);
+			priv->cfg->base_params->num_of_ampdu_queues - 1);
 		return -EINVAL;
 	}
 
@@ -333,19 +321,15 @@
 	iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask);
 }
 
-static inline int get_queue_from_ac(u16 ac)
-{
-	return ac;
-}
-
 /*
  * handle build REPLY_TX command notification.
  */
 static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
-				  struct iwl_tx_cmd *tx_cmd,
-				  struct ieee80211_tx_info *info,
-				  struct ieee80211_hdr *hdr,
-				  u8 std_id)
+					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;
@@ -365,6 +349,13 @@
 
 	if (ieee80211_is_back_req(fc))
 		tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
+	else if (info->band == IEEE80211_BAND_2GHZ &&
+		 priv->cfg->bt_params &&
+		 priv->cfg->bt_params->advanced_bt_coexist &&
+		 (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) ||
+		 ieee80211_is_reassoc_req(fc) ||
+		 skb->protocol == cpu_to_be16(ETH_P_PAE)))
+		tx_flags |= TX_CMD_FLG_IGNORE_BT;
 
 
 	tx_cmd->sta_id = std_id;
@@ -454,7 +445,14 @@
 		rate_flags |= RATE_MCS_CCK_MSK;
 
 	/* Set up antennas */
-	priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
+	 if (priv->cfg->bt_params &&
+	     priv->cfg->bt_params->advanced_bt_coexist &&
+	     priv->bt_full_concurrent) {
+		/* operated as 1x1 in full concurrency mode */
+		priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
+				first_antenna(priv->hw_params.valid_tx_ant));
+	} else
+		priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
 					      priv->hw_params.valid_tx_ant);
 	rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
 
@@ -470,8 +468,8 @@
 {
 	struct ieee80211_key_conf *keyconf = info->control.hw_key;
 
-	switch (keyconf->alg) {
-	case ALG_CCMP:
+	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)
@@ -479,20 +477,20 @@
 		IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
 		break;
 
-	case ALG_TKIP:
+	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 ALG_WEP:
+	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);
 
-		if (keyconf->keylen == WEP_KEY_LEN_128)
-			tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
-
 		memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
 
 		IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
@@ -500,7 +498,7 @@
 		break;
 
 	default:
-		IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg);
+		IWL_ERR(priv, "Unknown encode cipher %x\n", keyconf->cipher);
 		break;
 	}
 }
@@ -519,6 +517,7 @@
 	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 swq_id, txq_id;
 	dma_addr_t phys_addr;
 	dma_addr_t txcmd_phys;
@@ -533,6 +532,9 @@
 	u8 *qc = NULL;
 	unsigned long flags;
 
+	if (info->control.vif)
+		ctx = iwl_rxon_ctx_from_vif(info->control.vif);
+
 	spin_lock_irqsave(&priv->lock, flags);
 	if (iwl_is_rfkill(priv)) {
 		IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
@@ -553,7 +555,7 @@
 	hdr_len = ieee80211_hdrlen(fc);
 
 	/* Find index into station table for destination station */
-	sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta);
+	sta_id = iwl_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);
@@ -565,8 +567,7 @@
 	if (sta)
 		sta_priv = (void *)sta->drv_priv;
 
-	if (sta_priv && sta_id != priv->hw_params.bcast_sta_id &&
-	    sta_priv->asleep) {
+	if (sta_priv && sta_priv->asleep) {
 		WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE));
 		/*
 		 * This sends an asynchronous command to the device,
@@ -580,7 +581,20 @@
 		iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
 	}
 
-	txq_id = get_queue_from_ac(skb_get_queue_mapping(skb));
+	/*
+	 * 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);
@@ -625,6 +639,7 @@
 	/* 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];
@@ -655,7 +670,7 @@
 		iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
 
 	/* TODO need this for burst mode later on */
-	iwlagn_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
+	iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id);
 	iwl_dbg_log_tx_data_frame(priv, len, hdr);
 
 	iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc);
@@ -813,7 +828,7 @@
 	/* Tx queues */
 	if (priv->txq) {
 		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
-			if (txq_id == IWL_CMD_QUEUE_NUM)
+			if (txq_id == priv->cmd_queue)
 				iwl_cmd_queue_free(priv);
 			else
 				iwl_tx_queue_free(priv, txq_id);
@@ -870,9 +885,9 @@
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	/* Alloc and init all Tx queues, including the command queue (#4) */
+	/* 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 == IWL_CMD_QUEUE_NUM) ?
+		slots_num = (txq_id == priv->cmd_queue) ?
 					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
 		ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
 				       txq_id);
@@ -910,7 +925,7 @@
 
 	/* 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 == IWL_CMD_QUEUE_NUM ?
+		slots_num = txq_id == priv->cmd_queue ?
 			    TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
 		iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
 	}
@@ -968,7 +983,7 @@
 	unsigned long flags;
 	struct iwl_tid_data *tid_data;
 
-	tx_fifo = get_fifo_from_tid(tid);
+	tx_fifo = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid);
 	if (unlikely(tx_fifo < 0))
 		return tx_fifo;
 
@@ -1024,12 +1039,12 @@
 int iwlagn_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 = -1;
+	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 = get_fifo_from_tid(tid);
+	tx_fifo_id = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid);
 	if (unlikely(tx_fifo_id < 0))
 		return tx_fifo_id;
 
@@ -1042,21 +1057,26 @@
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
 
-	if (priv->stations[sta_id].tid[tid].agg.state ==
-				IWL_EMPTYING_HW_QUEUE_ADDBA) {
-		IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
-		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
-		spin_unlock_irqrestore(&priv->sta_lock, flags);
-		return 0;
-	}
-
-	if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON)
-		IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
-
 	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;
 
@@ -1070,6 +1090,7 @@
 	}
 
 	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 */
@@ -1098,6 +1119,9 @@
 	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);
 
@@ -1108,12 +1132,12 @@
 		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 = get_fifo_from_tid(tid);
+			int tx_fifo = get_fifo_from_tid(ctx, tid);
 			IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
 			priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
 							     ssn, tx_fifo);
 			tid_data->agg.state = IWL_AGG_OFF;
-			ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid);
+			ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
 		}
 		break;
 	case IWL_EMPTYING_HW_QUEUE_ADDBA:
@@ -1121,7 +1145,7 @@
 		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(priv->vif, addr, tid);
+			ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
 		}
 		break;
 	}
@@ -1129,14 +1153,14 @@
 	return 0;
 }
 
-static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
+static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info)
 {
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data;
 	struct ieee80211_sta *sta;
 	struct iwl_station_priv *sta_priv;
 
 	rcu_read_lock();
-	sta = ieee80211_find_sta(priv->vif, hdr->addr1);
+	sta = ieee80211_find_sta(tx_info->ctx->vif, hdr->addr1);
 	if (sta) {
 		sta_priv = (void *)sta->drv_priv;
 		/* avoid atomic ops if this isn't a client */
@@ -1146,7 +1170,7 @@
 	}
 	rcu_read_unlock();
 
-	ieee80211_tx_status_irqsafe(priv->hw, skb);
+	ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
 }
 
 int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
@@ -1169,7 +1193,7 @@
 	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
 		tx_info = &txq->txb[txq->q.read_ptr];
-		iwlagn_tx_status(priv, tx_info->skb);
+		iwlagn_tx_status(priv, tx_info);
 
 		hdr = (struct ieee80211_hdr *)tx_info->skb->data;
 		if (hdr && ieee80211_is_data_qos(hdr->frame_control))
@@ -1367,3 +1391,43 @@
 
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+const char *iwl_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(BT_PRIO);
+	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_DEBUG */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 6f77441..7036211 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -38,6 +38,7 @@
 #include "iwl-helpers.h"
 #include "iwl-agn-hw.h"
 #include "iwl-agn.h"
+#include "iwl-agn-calib.h"
 
 static const s8 iwlagn_default_queue_to_tx_fifo[] = {
 	IWL_TX_FIFO_VO,
@@ -52,6 +53,19 @@
 	IWL_TX_FIFO_UNUSED,
 };
 
+static const s8 iwlagn_ipan_queue_to_tx_fifo[] = {
+	IWL_TX_FIFO_VO,
+	IWL_TX_FIFO_VI,
+	IWL_TX_FIFO_BE,
+	IWL_TX_FIFO_BK,
+	IWL_TX_FIFO_BK_IPAN,
+	IWL_TX_FIFO_BE_IPAN,
+	IWL_TX_FIFO_VI_IPAN,
+	IWL_TX_FIFO_VO_IPAN,
+	IWL_TX_FIFO_BE_IPAN,
+	IWLAGN_CMD_FIFO_NUM,
+};
+
 static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
 	{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
 	 0, COEX_UNASSOC_IDLE_FLAGS},
@@ -201,6 +215,25 @@
 			     (u8 *)&cmd, sizeof(cmd));
 }
 
+static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
+{
+	struct iwl_calib_temperature_offset_cmd cmd;
+	__le16 *offset_calib =
+		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE);
+	cmd.hdr.op_code = IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD;
+	cmd.hdr.first_group = 0;
+	cmd.hdr.groups_num = 1;
+	cmd.hdr.data_valid = 1;
+	cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]);
+	if (!(cmd.radio_sensor_offset))
+		cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
+	cmd.reserved = 0;
+	IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
+			cmd.radio_sensor_offset);
+	return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET],
+			     (u8 *)&cmd, sizeof(cmd));
+}
+
 static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
 {
 	struct iwl_calib_cfg_cmd calib_cfg_cmd;
@@ -294,7 +327,27 @@
 		goto restart;
 	}
 
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist) {
+		/*
+		 * Tell uCode we are ready to perform calibration
+		 * need to perform this before any calibration
+		 * no need to close the envlope since we are going
+		 * to load the runtime uCode later.
+		 */
+		iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
+			BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+
+	}
 	iwlagn_send_calib_cfg(priv);
+
+	/**
+	 * temperature offset calibration is only needed for runtime ucode,
+	 * so prepare the value now.
+	 */
+	if (priv->cfg->need_temp_offset_calib)
+		iwlagn_set_temperature_offset_calib(priv);
+
 	return;
 
 restart:
@@ -306,7 +359,7 @@
 {
 	struct iwl_wimax_coex_cmd coex_cmd;
 
-	if (priv->cfg->support_wimax_coexist) {
+	if (priv->cfg->base_params->support_wimax_coexist) {
 		/* UnMask wake up src at associated sleep */
 		coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
 
@@ -329,8 +382,54 @@
 				sizeof(coex_cmd), &coex_cmd);
 }
 
+static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
+	((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+	((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+		(1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+	((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+	((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+		(1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+	((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+	((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+		(1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+	((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+	((BT_COEX_PRIO_TBL_PRIO_COEX_OFF << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+	((BT_COEX_PRIO_TBL_PRIO_COEX_ON << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+	0, 0, 0, 0, 0, 0, 0
+};
+
+void iwlagn_send_prio_tbl(struct iwl_priv *priv)
+{
+	struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd;
+
+	memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl,
+		sizeof(iwlagn_bt_prio_tbl));
+	if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PRIO_TABLE,
+				sizeof(prio_tbl_cmd), &prio_tbl_cmd))
+		IWL_ERR(priv, "failed to send BT prio tbl command\n");
+}
+
+void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
+{
+	struct iwl_bt_coex_prot_env_cmd env_cmd;
+
+	env_cmd.action = action;
+	env_cmd.type = type;
+	if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV,
+			     sizeof(env_cmd), &env_cmd))
+		IWL_ERR(priv, "failed to send BT env command\n");
+}
+
+
 int iwlagn_alive_notify(struct iwl_priv *priv)
 {
+	const s8 *queues;
 	u32 a;
 	unsigned long flags;
 	int i, chan;
@@ -365,7 +464,7 @@
 			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
 
 	iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL,
-		IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num));
+		IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv));
 	iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0);
 
 	/* initiate the queues */
@@ -391,7 +490,13 @@
 	/* Activate all Tx DMA/FIFO channels */
 	priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
 
-	iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+	/* map queues to FIFOs */
+	if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
+		queues = iwlagn_ipan_queue_to_tx_fifo;
+	else
+		queues = iwlagn_default_queue_to_tx_fifo;
+
+	iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0);
 
 	/* make sure all queue are not stopped */
 	memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
@@ -400,11 +505,12 @@
 
 	/* reset to 0 to enable all the queue first */
 	priv->txq_ctx_active_msk = 0;
-	/* map qos queues to fifos one-to-one */
-	BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10);
 
-	for (i = 0; i < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) {
-		int ac = iwlagn_default_queue_to_tx_fifo[i];
+	BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10);
+	BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10);
+
+	for (i = 0; i < 10; i++) {
+		int ac = queues[i];
 
 		iwl_txq_ctx_activate(priv, i);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 10d7b9b..c2636a7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -33,6 +33,7 @@
 #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>
@@ -56,7 +57,7 @@
 #include "iwl-io.h"
 #include "iwl-helpers.h"
 #include "iwl-sta.h"
-#include "iwl-calib.h"
+#include "iwl-agn-calib.h"
 #include "iwl-agn.h"
 
 
@@ -86,29 +87,36 @@
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("iwl4965");
 
+static int iwlagn_ant_coupling;
+static bool iwlagn_bt_ch_announce = 1;
+
 /**
- * iwl_commit_rxon - commit staging_rxon to hardware
+ * iwlagn_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 iwl_commit_rxon(struct iwl_priv *priv)
+int iwlagn_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 *)&priv->active_rxon;
+	struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
 	int ret;
 	bool new_assoc =
-		!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
+		!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
+	bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
 
 	if (!iwl_is_alive(priv))
 		return -EBUSY;
 
-	/* always get timestamp with Rx frame */
-	priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
+	if (!ctx->is_active)
+		return 0;
 
-	ret = iwl_check_rxon_cmd(priv);
+	/* 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;
@@ -119,7 +127,7 @@
 	 * abort any previous channel switch if still in process
 	 */
 	if (priv->switch_rxon.switch_in_progress &&
-	    (priv->switch_rxon.channel != priv->staging_rxon.channel)) {
+	    (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);
@@ -128,15 +136,15 @@
 	/* 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)) {
-		ret = iwl_send_rxon_assoc(priv);
+	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, &priv->staging_rxon, sizeof(*active_rxon));
-		iwl_print_rx_config_cmd(priv);
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+		iwl_print_rx_config_cmd(priv, ctx);
 		return 0;
 	}
 
@@ -144,13 +152,13 @@
 	 * 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) && new_assoc) {
+	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, REPLY_RXON,
-				      sizeof(struct iwl_rxon_cmd),
-				      &priv->active_rxon);
+		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 */
@@ -159,9 +167,9 @@
 			IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
 			return ret;
 		}
-		iwl_clear_ucode_stations(priv);
-		iwl_restore_stations(priv);
-		ret = iwl_restore_default_wep_keys(priv);
+		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;
@@ -173,47 +181,65 @@
 		       "* channel = %d\n"
 		       "* bssid = %pM\n",
 		       (new_assoc ? "" : "out"),
-		       le16_to_cpu(priv->staging_rxon.channel),
-		       priv->staging_rxon.bssid_addr);
+		       le16_to_cpu(ctx->staging.channel),
+		       ctx->staging.bssid_addr);
 
-	iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto);
+	iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
+
+	if (!old_assoc) {
+		/*
+		 * First of all, before setting associated, we need to
+		 * send RXON timing so the device knows about the DTIM
+		 * period and other timing values
+		 */
+		ret = iwl_send_rxon_timing(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Error setting RXON timing!\n");
+			return ret;
+		}
+	}
+
+	if (priv->cfg->ops->hcmd->set_pan_params) {
+		ret = priv->cfg->ops->hcmd->set_pan_params(priv);
+		if (ret)
+			return ret;
+	}
 
 	/* 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, REPLY_RXON,
-			      sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
+		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, &priv->staging_rxon, sizeof(*active_rxon));
-		iwl_clear_ucode_stations(priv);
-		iwl_restore_stations(priv);
-		ret = iwl_restore_default_wep_keys(priv);
+		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;
 		}
 	}
-
-	priv->start_calib = 0;
 	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, REPLY_RXON,
-			      sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
+		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, &priv->staging_rxon, sizeof(*active_rxon));
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
 	}
-	iwl_print_rx_config_cmd(priv);
+	iwl_print_rx_config_cmd(priv, ctx);
 
 	iwl_init_sensitivity(priv);
 
@@ -230,10 +256,14 @@
 
 void iwl_update_chain_flags(struct iwl_priv *priv)
 {
+	struct iwl_rxon_context *ctx;
 
-	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv);
-	iwlcore_commit_rxon(priv);
+	if (priv->cfg->ops->hcmd->set_rxon_chain) {
+		for_each_context(priv, ctx) {
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+			iwlcore_commit_rxon(priv, ctx);
+		}
+	}
 }
 
 static void iwl_clear_free_frames(struct iwl_priv *priv)
@@ -284,24 +314,26 @@
 }
 
 static u32 iwl_fill_beacon_frame(struct iwl_priv *priv,
-					  struct ieee80211_hdr *hdr,
-					  int left)
+				 struct ieee80211_hdr *hdr,
+				 int left)
 {
-	if (!priv->ibss_beacon)
+	lockdep_assert_held(&priv->mutex);
+
+	if (!priv->beacon_skb)
 		return 0;
 
-	if (priv->ibss_beacon->len > left)
+	if (priv->beacon_skb->len > left)
 		return 0;
 
-	memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
+	memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
 
-	return priv->ibss_beacon->len;
+	return priv->beacon_skb->len;
 }
 
 /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
 static void iwl_set_beacon_tim(struct iwl_priv *priv,
-		struct iwl_tx_beacon_cmd *tx_beacon_cmd,
-		u8 *beacon, u32 frame_size)
+			       struct iwl_tx_beacon_cmd *tx_beacon_cmd,
+			       u8 *beacon, u32 frame_size)
 {
 	u16 tim_idx;
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
@@ -337,6 +369,13 @@
 	 * 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));
@@ -346,20 +385,22 @@
 				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->hw_params.bcast_sta_id;
+	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 */
 	iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame,
-			frame_size);
+			   frame_size);
 
 	/* Set up packet rate and flags */
-	rate = iwl_rate_get_lowest_plcp(priv);
+	rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx);
 	priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
 					      priv->hw_params.valid_tx_ant);
 	rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
@@ -592,23 +633,83 @@
 		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->vif);
-
-	if (!beacon) {
-		IWL_ERR(priv, "update beacon failed\n");
-		return;
+	mutex_lock(&priv->mutex);
+	if (!priv->beacon_ctx) {
+		IWL_ERR(priv, "updating beacon w/o beacon context!\n");
+		goto out;
 	}
 
-	mutex_lock(&priv->mutex);
-	/* new beacon skb is allocated every time; dispose previous.*/
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	if (priv->beacon_ctx->vif->type != NL80211_IFTYPE_AP) {
+		/*
+		 * The ucode will send beacon notifications even in
+		 * IBSS mode, but we don't want to process them. But
+		 * we need to defer the type check to here due to
+		 * requiring locking around the beacon_ctx access.
+		 */
+		goto out;
+	}
 
-	priv->ibss_beacon = beacon;
-	mutex_unlock(&priv->mutex);
+	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
+	beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif);
+	if (!beacon) {
+		IWL_ERR(priv, "update beacon failed -- keeping old\n");
+		goto out;
+	}
+
+	/* new beacon skb is allocated every time; dispose previous.*/
+	dev_kfree_skb(priv->beacon_skb);
+
+	priv->beacon_skb = beacon;
 
 	iwl_send_beacon_cmd(priv);
+ out:
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl_bg_bt_runtime_config(struct work_struct *work)
+{
+	struct iwl_priv *priv =
+		container_of(work, struct iwl_priv, bt_runtime_config);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* dont send host command if rf-kill is on */
+	if (!iwl_is_ready_rf(priv))
+		return;
+	priv->cfg->ops->hcmd->send_bt_config(priv);
+}
+
+static void iwl_bg_bt_full_concurrency(struct work_struct *work)
+{
+	struct iwl_priv *priv =
+		container_of(work, struct iwl_priv, bt_full_concurrency);
+	struct iwl_rxon_context *ctx;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* dont send host command if rf-kill is on */
+	if (!iwl_is_ready_rf(priv))
+		return;
+
+	IWL_DEBUG_INFO(priv, "BT coex in %s mode\n",
+		       priv->bt_full_concurrent ?
+		       "full concurrency" : "3-wire");
+
+	/*
+	 * LQ & RXON updated cmds must be sent before BT Config cmd
+	 * to avoid 3-wire collisions
+	 */
+	mutex_lock(&priv->mutex);
+	for_each_context(priv, ctx) {
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+		iwlcore_commit_rxon(priv, ctx);
+	}
+	mutex_unlock(&priv->mutex);
+
+	priv->cfg->ops->hcmd->send_bt_config(priv);
 }
 
 /**
@@ -763,10 +864,10 @@
 static void iwl_rx_beacon_notif(struct iwl_priv *priv,
 				struct iwl_rx_mem_buffer *rxb)
 {
-#ifdef CONFIG_IWLWIFI_DEBUG
 	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 "
@@ -778,8 +879,9 @@
 		le32_to_cpu(beacon->low_tsf), rate);
 #endif
 
-	if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
-	    (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
+	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);
 }
 
@@ -836,22 +938,6 @@
 		wake_up_interruptible(&priv->wait_command_queue);
 }
 
-int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
-{
-	if (src == IWL_PWR_SRC_VAUX) {
-		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);
-	} else {
-		iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-				       APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
-				       ~APMG_PS_CTRL_MSK_PWR_SRC);
-	}
-
-	return 0;
-}
-
 static void iwl_bg_tx_flush(struct work_struct *work)
 {
 	struct iwl_priv *priv =
@@ -1181,7 +1267,6 @@
 		IWL_ERR(priv, "Microcode SW error detected. "
 			" Restarting 0x%X.\n", inta);
 		priv->isr_stats.sw++;
-		priv->isr_stats.sw_err = inta;
 		iwl_irq_handle_error(priv);
 		handled |= CSR_INT_BIT_SW_ERR;
 	}
@@ -1362,7 +1447,6 @@
 		IWL_ERR(priv, "Microcode SW error detected. "
 			" Restarting 0x%X.\n", inta);
 		priv->isr_stats.sw++;
-		priv->isr_stats.sw_err = inta;
 		iwl_irq_handle_error(priv);
 		handled |= CSR_INT_BIT_SW_ERR;
 	}
@@ -1650,30 +1734,44 @@
 struct iwlagn_ucode_capabilities {
 	u32 max_probe_length;
 	u32 standard_phy_calibration_size;
+	bool pan;
 };
 
 static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
 static int iwl_mac_setup_register(struct iwl_priv *priv,
 				  struct iwlagn_ucode_capabilities *capa);
 
+#define UCODE_EXPERIMENTAL_INDEX	100
+#define UCODE_EXPERIMENTAL_TAG		"exp"
+
 static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
 {
 	const char *name_pre = priv->cfg->fw_name_pre;
+	char tag[8];
 
-	if (first)
+	if (first) {
+#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
+		priv->fw_index = UCODE_EXPERIMENTAL_INDEX;
+		strcpy(tag, UCODE_EXPERIMENTAL_TAG);
+	} else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) {
+#endif
 		priv->fw_index = priv->cfg->ucode_api_max;
-	else
+		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%d%s",
-		name_pre, priv->fw_index, ".ucode");
+	sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
 
-	IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n",
+	IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n",
+		       (priv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+				? "EXPERIMENTAL " : "",
 		       priv->firmware_name);
 
 	return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
@@ -1874,6 +1972,11 @@
 			capa->max_probe_length =
 					le32_to_cpup((__le32 *)tlv_data);
 			break;
+		case IWL_UCODE_TLV_PAN:
+			if (tlv_len)
+				goto invalid_tlv_len;
+			capa->pan = true;
+			break;
 		case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
 			if (tlv_len != sizeof(u32))
 				goto invalid_tlv_len;
@@ -1962,14 +2065,16 @@
 	struct iwlagn_ucode_capabilities ucode_capa = {
 		.max_probe_length = 200,
 		.standard_phy_calibration_size =
-			IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE,
+			IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE,
 	};
 
 	memset(&pieces, 0, sizeof(pieces));
 
 	if (!ucode_raw) {
-		IWL_ERR(priv, "request for firmware file '%s' failed.\n",
-			priv->firmware_name);
+		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;
 	}
 
@@ -2002,21 +2107,28 @@
 	 * 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;
+	/* no api version check required for experimental uCode */
+	if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) {
+		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);
 	}
 
-	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);
-
 	if (build)
-		sprintf(buildstr, " build %u", build);
+		sprintf(buildstr, " build %u%s", build,
+		       (priv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+				? " (EXP)" : "");
 	else
 		buildstr[0] = '\0';
 
@@ -2136,15 +2248,23 @@
 	if (pieces.init_evtlog_size)
 		priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
 	else
-		priv->_agn.init_evtlog_size = priv->cfg->max_event_log_size;
+		priv->_agn.init_evtlog_size =
+			priv->cfg->base_params->max_event_log_size;
 	priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr;
 	priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr;
 	if (pieces.inst_evtlog_size)
 		priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
 	else
-		priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size;
+		priv->_agn.inst_evtlog_size =
+			priv->cfg->base_params->max_event_log_size;
 	priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr;
 
+	if (ucode_capa.pan) {
+		priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
+		priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
+	} else
+		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) */
@@ -2341,6 +2461,7 @@
 	}
 
 	desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
+	priv->isr_stats.err_code = desc;
 	pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32));
 	blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
 	blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
@@ -2543,6 +2664,9 @@
 		return pos;
 	}
 
+	/* enable/disable bt channel announcement */
+	priv->bt_ch_announce = iwlagn_bt_ch_announce;
+
 #ifdef CONFIG_IWLWIFI_DEBUG
 	if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
 		size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
@@ -2589,6 +2713,69 @@
 	return pos;
 }
 
+static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
+{
+	struct iwl_ct_kill_config cmd;
+	struct iwl_ct_kill_throttling_config adv_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);
+	priv->thermal_throttle.ct_kill_toggle = false;
+
+	if (priv->cfg->base_params->support_ct_kill_exit) {
+		adv_cmd.critical_temperature_enter =
+			cpu_to_le32(priv->hw_params.ct_kill_threshold);
+		adv_cmd.critical_temperature_exit =
+			cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
+
+		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+				       sizeof(adv_cmd), &adv_cmd);
+		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 enter is %d,"
+					"exit is %d\n",
+				       priv->hw_params.ct_kill_threshold,
+				       priv->hw_params.ct_kill_exit_threshold);
+	} else {
+		cmd.critical_temperature_R =
+			cpu_to_le32(priv->hw_params.ct_kill_threshold);
+
+		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+				       sizeof(cmd), &cmd);
+		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 int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
+{
+	struct iwl_calib_cfg_cmd calib_cfg_cmd;
+	struct iwl_host_cmd cmd = {
+		.id = CALIBRATION_CFG_CMD,
+		.len = sizeof(struct iwl_calib_cfg_cmd),
+		.data = &calib_cfg_cmd,
+	};
+
+	memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
+	calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
+	calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
+
+	return iwl_send_cmd(priv, &cmd);
+}
+
+
 /**
  * iwl_alive_start - called after REPLY_ALIVE notification received
  *                   from protocol/runtime uCode (initialization uCode's
@@ -2597,6 +2784,7 @@
 static void iwl_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");
 
@@ -2624,6 +2812,7 @@
 		goto restart;
 	}
 
+
 	/* After the ALIVE response, we can send host commands to the uCode */
 	set_bit(STATUS_ALIVE, &priv->status);
 
@@ -2631,12 +2820,33 @@
 		/* Enable timer to monitor the driver queues */
 		mod_timer(&priv->monitor_recover,
 			jiffies +
-			msecs_to_jiffies(priv->cfg->monitor_recover_period));
+			msecs_to_jiffies(
+			  priv->cfg->base_params->monitor_recover_period));
 	}
 
 	if (iwl_is_rfkill(priv))
 		return;
 
+	/* download priority table before any calibration request */
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist) {
+		/* Configure Bluetooth device coexistence support */
+		priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
+		priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
+		priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
+		priv->cfg->ops->hcmd->send_bt_config(priv);
+		priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
+		iwlagn_send_prio_tbl(priv);
+
+		/* FIXME: w/a to force change uCode BT state machine */
+		iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
+			BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+		iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
+			BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+	}
+	if (priv->hw_params.calib_rt_cfg)
+		iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
+
 	ieee80211_wake_queues(priv->hw);
 
 	priv->active_rate = IWL_RATES_MASK;
@@ -2645,27 +2855,32 @@
 	if (priv->cfg->ops->hcmd->set_tx_ant)
 		priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant);
 
-	if (iwl_is_associated(priv)) {
+	if (iwl_is_associated_ctx(ctx)) {
 		struct iwl_rxon_cmd *active_rxon =
-				(struct iwl_rxon_cmd *)&priv->active_rxon;
+				(struct iwl_rxon_cmd *)&ctx->active;
 		/* apply any changes in staging */
-		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		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 */
-		iwl_connection_init_rx_config(priv, NULL);
+		for_each_context(priv, tmp)
+			iwl_connection_init_rx_config(priv, tmp);
 
 		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv);
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 	}
 
-	/* Configure Bluetooth device coexistence support */
-	priv->cfg->ops->hcmd->send_bt_config(priv);
+	if (priv->cfg->bt_params &&
+	    !priv->cfg->bt_params->advanced_bt_coexist) {
+		/* Configure Bluetooth device coexistence support */
+		priv->cfg->ops->hcmd->send_bt_config(priv);
+	}
 
 	iwl_reset_run_time_calib(priv);
 
 	/* Configure the adapter for unassociated operation */
-	iwlcore_commit_rxon(priv);
+	iwlcore_commit_rxon(priv, ctx);
 
 	/* At this point, the NIC is initialized and operational */
 	iwl_rf_kill_ct_config(priv);
@@ -2695,13 +2910,30 @@
 
 	IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
 
-	if (!exit_pending)
-		set_bit(STATUS_EXIT_PENDING, &priv->status);
+	iwl_scan_cancel_timeout(priv, 200);
 
-	iwl_clear_ucode_stations(priv);
-	iwl_dealloc_bcast_station(priv);
+	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 */
+	if (priv->cfg->ops->lib->recover_from_tx_stall)
+		del_timer_sync(&priv->monitor_recover);
+
+	iwl_clear_ucode_stations(priv, NULL);
+	iwl_dealloc_bcast_stations(priv);
 	iwl_clear_driver_stations(priv);
 
+	/* reset BT coex data */
+	priv->bt_status = 0;
+	if (priv->cfg->bt_params)
+		priv->bt_traffic_load =
+			 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;
+
 	/* Unblock any waiting calls */
 	wake_up_interruptible_all(&priv->wait_command_queue);
 
@@ -2759,14 +2991,13 @@
 	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 
 	/* Stop the device, and put it in low power state */
-	priv->cfg->ops->lib->apm_ops.stop(priv);
+	iwl_apm_stop(priv);
 
  exit:
 	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
 
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
-	priv->ibss_beacon = NULL;
+	dev_kfree_skb(priv->beacon_skb);
+	priv->beacon_skb = NULL;
 
 	/* clear out any free frames */
 	iwl_clear_free_frames(priv);
@@ -2834,6 +3065,7 @@
 
 static int __iwl_up(struct iwl_priv *priv)
 {
+	struct iwl_rxon_context *ctx;
 	int i;
 	int ret;
 
@@ -2847,9 +3079,13 @@
 		return -EIO;
 	}
 
-	ret = iwl_alloc_bcast_station(priv, true);
-	if (ret)
-		return ret;
+	for_each_context(priv, ctx) {
+		ret = iwlagn_alloc_bcast_station(priv, ctx);
+		if (ret) {
+			iwl_dealloc_bcast_stations(priv);
+			return ret;
+		}
+	}
 
 	iwl_prepare_card_hw(priv);
 
@@ -2874,6 +3110,12 @@
 
 	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
 
+	/* must be initialised before iwl_hw_nic_init */
+	if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
+		priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
+	else
+		priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+
 	ret = iwlagn_hw_nic_init(priv);
 	if (ret) {
 		IWL_ERR(priv, "Unable to init nic\n");
@@ -2980,7 +3222,8 @@
 	}
 
 	if (priv->start_calib) {
-		if (priv->cfg->bt_statistics) {
+		if (priv->cfg->bt_params &&
+		    priv->cfg->bt_params->bt_statistics) {
 			iwl_chain_noise_calibration(priv,
 					(void *)&priv->_agn.statistics_bt);
 			iwl_sensitivity_calibration(priv,
@@ -3004,11 +3247,42 @@
 		return;
 
 	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+		struct iwl_rxon_context *ctx;
+		bool bt_sco, bt_full_concurrent;
+		u8 bt_ci_compliance;
+		u8 bt_load;
+		u8 bt_status;
+
 		mutex_lock(&priv->mutex);
-		priv->vif = NULL;
+		for_each_context(priv, ctx)
+			ctx->vif = NULL;
 		priv->is_open = 0;
+
+		/*
+		 * __iwl_down() will clear the BT status variables,
+		 * which is correct, but when we restart we really
+		 * want to keep them so restore them afterwards.
+		 *
+		 * The restart process will later pick them up and
+		 * 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;
+		bt_status = priv->bt_status;
+
+		__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;
+		priv->bt_status = bt_status;
+
 		mutex_unlock(&priv->mutex);
-		iwl_down(priv);
+		iwl_cancel_deferred_work(priv);
 		ieee80211_restart_hw(priv->hw);
 	} else {
 		iwl_down(priv);
@@ -3039,12 +3313,15 @@
 
 void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
+	struct iwl_rxon_context *ctx;
 	struct ieee80211_conf *conf = NULL;
 	int ret = 0;
 
 	if (!vif || !priv->is_open)
 		return;
 
+	ctx = iwl_rxon_ctx_from_vif(vif);
+
 	if (vif->type == NL80211_IFTYPE_AP) {
 		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
 		return;
@@ -3057,44 +3334,42 @@
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 
-	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwlcore_commit_rxon(priv);
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwlcore_commit_rxon(priv, ctx);
 
-	iwl_setup_rxon_timing(priv, vif);
-	ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
-			      sizeof(priv->rxon_timing), &priv->rxon_timing);
+	ret = iwl_send_rxon_timing(priv, ctx);
 	if (ret)
-		IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
+		IWL_WARN(priv, "RXON timing - "
 			    "Attempting to continue.\n");
 
-	priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+	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);
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 
-	priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+	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)
-		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 	else
-		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 
-	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
+	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
 		if (vif->bss_conf.use_short_slot)
-			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
 		else
-			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 	}
 
-	iwlcore_commit_rxon(priv);
+	iwlcore_commit_rxon(priv, ctx);
 
 	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-			vif->bss_conf.aid, priv->active_rxon.bssid_addr);
+			vif->bss_conf.aid, ctx->active.bssid_addr);
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
@@ -3137,14 +3412,17 @@
 {
 	int ret;
 	struct ieee80211_hw *hw = priv->hw;
+	struct iwl_rxon_context *ctx;
+
 	hw->rate_control_algorithm = "iwl-agn-rs";
 
 	/* Tell mac80211 our characteristics */
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 		    IEEE80211_HW_AMPDU_AGGREGATION |
+		    IEEE80211_HW_NEED_DTIM_PERIOD |
 		    IEEE80211_HW_SPECTRUM_MGMT;
 
-	if (!priv->cfg->broken_powersave)
+	if (!priv->cfg->base_params->broken_powersave)
 		hw->flags |= IEEE80211_HW_SUPPORTS_PS |
 			     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
@@ -3155,9 +3433,10 @@
 	hw->sta_data_size = sizeof(struct iwl_station_priv);
 	hw->vif_data_size = sizeof(struct iwl_vif_priv);
 
-	hw->wiphy->interface_modes =
-		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC);
+	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;
@@ -3247,15 +3526,6 @@
 
 	priv->is_open = 0;
 
-	if (iwl_is_ready_rf(priv) || test_bit(STATUS_SCAN_HW, &priv->status)) {
-		/* stop mac, cancel any scan request and clear
-		 * RXON_FILTER_ASSOC_MSK BIT
-		 */
-		mutex_lock(&priv->mutex);
-		iwl_scan_cancel_timeout(priv, 100);
-		mutex_unlock(&priv->mutex);
-	}
-
 	iwl_down(priv);
 
 	flush_workqueue(priv->workqueue);
@@ -3285,24 +3555,25 @@
 
 void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(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(priv)) {
+	if (!iwl_is_associated_ctx(ctx)) {
 
 		/* RXON - unassoc (to set timing command) */
-		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv);
+		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+		iwlcore_commit_rxon(priv, ctx);
 
 		/* RXON Timing */
-		iwl_setup_rxon_timing(priv, vif);
-		ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
-				sizeof(priv->rxon_timing), &priv->rxon_timing);
+		ret = iwl_send_rxon_timing(priv, ctx);
 		if (ret)
-			IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
+			IWL_WARN(priv, "RXON timing failed - "
 					"Attempting to continue.\n");
 
 		/* AP has all antennas */
@@ -3310,28 +3581,30 @@
 			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);
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 
-		priv->staging_rxon.assoc_id = 0;
+		ctx->staging.assoc_id = 0;
 
 		if (vif->bss_conf.use_short_preamble)
-			priv->staging_rxon.flags |=
+			ctx->staging.flags |=
 				RXON_FLG_SHORT_PREAMBLE_MSK;
 		else
-			priv->staging_rxon.flags &=
+			ctx->staging.flags &=
 				~RXON_FLG_SHORT_PREAMBLE_MSK;
 
-		if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
+		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
 			if (vif->bss_conf.use_short_slot)
-				priv->staging_rxon.flags |=
+				ctx->staging.flags |=
 					RXON_FLG_SHORT_SLOT_MSK;
 			else
-				priv->staging_rxon.flags &=
+				ctx->staging.flags &=
 					~RXON_FLG_SHORT_SLOT_MSK;
 		}
+		/* need to send beacon cmd before committing assoc RXON! */
+		iwl_send_beacon_cmd(priv);
 		/* restore RXON assoc */
-		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv);
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		iwlcore_commit_rxon(priv, ctx);
 	}
 	iwl_send_beacon_cmd(priv);
 
@@ -3348,9 +3621,11 @@
 {
 
 	struct iwl_priv *priv = hw->priv;
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
-	iwl_update_tkip_key(priv, keyconf, sta,
+	iwl_update_tkip_key(priv, vif_priv->ctx, keyconf, sta,
 			    iv32, phase1key);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -3362,6 +3637,8 @@
 			   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;
@@ -3373,7 +3650,7 @@
 		return -EOPNOTSUPP;
 	}
 
-	sta_id = iwl_sta_id_or_broadcast(priv, sta);
+	sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
 	if (sta_id == IWL_INVALID_STATION)
 		return -EINVAL;
 
@@ -3386,9 +3663,11 @@
 	 * in 1X mode.
 	 * In legacy wep mode, we use another host command to the uCode.
 	 */
-	if (key->alg == ALG_WEP && !sta && vif->type != NL80211_IFTYPE_AP) {
+	if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+	     key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
+	    !sta) {
 		if (cmd == SET_KEY)
-			is_default_wep_key = !priv->key_mapping_key;
+			is_default_wep_key = !ctx->key_mapping_keys;
 		else
 			is_default_wep_key =
 					(key->hw_key_idx == HW_KEY_DEFAULT);
@@ -3397,17 +3676,18 @@
 	switch (cmd) {
 	case SET_KEY:
 		if (is_default_wep_key)
-			ret = iwl_set_default_wep_key(priv, key);
+			ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key);
 		else
-			ret = iwl_set_dynamic_key(priv, key, sta_id);
+			ret = iwl_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 = iwl_remove_default_wep_key(priv, key);
+			ret = iwl_remove_default_wep_key(priv, ctx, key);
 		else
-			ret = iwl_remove_dynamic_key(priv, key, sta_id);
+			ret = iwl_remove_dynamic_key(priv, ctx, key, sta_id);
 
 		IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
 		break;
@@ -3467,7 +3747,8 @@
 		}
 		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 			ret = 0;
-		if (priv->cfg->use_rts_for_aggregation) {
+		if (priv->cfg->ht_params &&
+		    priv->cfg->ht_params->use_rts_for_aggregation) {
 			struct iwl_station_priv *sta_priv =
 				(void *) sta->drv_priv;
 			/*
@@ -3476,12 +3757,13 @@
 
 			sta_priv->lq_sta.lq.general_params.flags &=
 				~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
-			iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq,
-				CMD_ASYNC, false);
+			iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
+					&sta_priv->lq_sta.lq, CMD_ASYNC, false);
 		}
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
-		if (priv->cfg->use_rts_for_aggregation) {
+		if (priv->cfg->ht_params &&
+		    priv->cfg->ht_params->use_rts_for_aggregation) {
 			struct iwl_station_priv *sta_priv =
 				(void *) sta->drv_priv;
 
@@ -3492,8 +3774,8 @@
 
 			sta_priv->lq_sta.lq.general_params.flags |=
 				LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
-			iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq,
-				CMD_ASYNC, false);
+			iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
+					&sta_priv->lq_sta.lq, CMD_ASYNC, false);
 		}
 		ret = 0;
 		break;
@@ -3539,6 +3821,7 @@
 {
 	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;
@@ -3554,8 +3837,8 @@
 	if (vif->type == NL80211_IFTYPE_AP)
 		sta_priv->client = true;
 
-	ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
-				     &sta_id);
+	ret = iwl_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);
@@ -3581,7 +3864,17 @@
 	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;
+	/*
+	 * MULTI-FIXME
+	 * When we add support for multiple interfaces, we need to
+	 * revisit this. The channel switch command in the device
+	 * only affects the BSS context, but what does that really
+	 * mean? And what if we get a CSA on the second interface?
+	 * This needs a lot of work.
+	 */
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 	u16 ch;
 	unsigned long flags = 0;
 
@@ -3594,7 +3887,7 @@
 	    test_bit(STATUS_SCANNING, &priv->status))
 		goto out_exit;
 
-	if (!iwl_is_associated(priv))
+	if (!iwl_is_associated_ctx(ctx))
 		goto out_exit;
 
 	/* channel switch in progress */
@@ -3604,11 +3897,10 @@
 	mutex_lock(&priv->mutex);
 	if (priv->cfg->ops->lib->set_channel_switch) {
 
-		ch = ieee80211_frequency_to_channel(
-			ch_switch->channel->center_freq);
-		if (le16_to_cpu(priv->active_rxon.channel) != ch) {
+		ch = channel->hw_value;
+		if (le16_to_cpu(ctx->active.channel) != ch) {
 			ch_info = iwl_get_channel_info(priv,
-						       conf->channel->band,
+						       channel->band,
 						       ch);
 			if (!is_channel_valid(ch_info)) {
 				IWL_DEBUG_MAC80211(priv, "invalid channel\n");
@@ -3619,34 +3911,31 @@
 			priv->current_ht_config.smps = conf->smps_mode;
 
 			/* Configure HT40 channels */
-			ht_conf->is_ht = conf_is_ht(conf);
-			if (ht_conf->is_ht) {
+			ctx->ht.enabled = conf_is_ht(conf);
+			if (ctx->ht.enabled) {
 				if (conf_is_ht40_minus(conf)) {
-					ht_conf->extension_chan_offset =
+					ctx->ht.extension_chan_offset =
 						IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-					ht_conf->is_40mhz = true;
+					ctx->ht.is_40mhz = true;
 				} else if (conf_is_ht40_plus(conf)) {
-					ht_conf->extension_chan_offset =
+					ctx->ht.extension_chan_offset =
 						IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-					ht_conf->is_40mhz = true;
+					ctx->ht.is_40mhz = true;
 				} else {
-					ht_conf->extension_chan_offset =
+					ctx->ht.extension_chan_offset =
 						IEEE80211_HT_PARAM_CHA_SEC_NONE;
-					ht_conf->is_40mhz = false;
+					ctx->ht.is_40mhz = false;
 				}
 			} else
-				ht_conf->is_40mhz = false;
+				ctx->ht.is_40mhz = false;
 
-			/* 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(priv->staging_rxon.channel) != ch))
-				priv->staging_rxon.flags = 0;
+			if ((le16_to_cpu(ctx->staging.channel) != ch))
+				ctx->staging.flags = 0;
 
-			iwl_set_rxon_channel(priv, conf->channel);
+			iwl_set_rxon_channel(priv, channel, ctx);
 			iwl_set_rxon_ht(priv, ht_conf);
-			iwl_set_flags_for_band(priv, conf->channel->band,
-					       priv->vif);
+			iwl_set_flags_for_band(priv, ctx, channel->band,
+					       ctx->vif);
 			spin_unlock_irqrestore(&priv->lock, flags);
 
 			iwl_set_rate(priv);
@@ -3663,7 +3952,7 @@
 	mutex_unlock(&priv->mutex);
 out_exit:
 	if (!priv->switch_rxon.switch_in_progress)
-		ieee80211_chswitch_done(priv->vif, false);
+		ieee80211_chswitch_done(ctx->vif, false);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
@@ -3674,6 +3963,7 @@
 {
 	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))		\
@@ -3693,10 +3983,11 @@
 
 	mutex_lock(&priv->mutex);
 
-	priv->staging_rxon.filter_flags &= ~filter_nand;
-	priv->staging_rxon.filter_flags |= filter_or;
-
-	iwlcore_commit_rxon(priv);
+	for_each_context(priv, ctx) {
+		ctx->staging.filter_flags &= ~filter_nand;
+		ctx->staging.filter_flags |= filter_or;
+		iwlcore_commit_rxon(priv, ctx);
+	}
 
 	mutex_unlock(&priv->mutex);
 
@@ -3765,6 +4056,8 @@
 	INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
 	INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
 	INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
+	INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
+	INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
 	INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
 	INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
 
@@ -3788,7 +4081,7 @@
 			priv->cfg->ops->lib->recover_from_tx_stall;
 	}
 
-	if (!priv->cfg->use_isr_legacy)
+	if (!priv->cfg->base_params->use_isr_legacy)
 		tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
 			iwl_irq_tasklet, (unsigned long)priv);
 	else
@@ -3802,15 +4095,17 @@
 		priv->cfg->ops->lib->cancel_deferred_work(priv);
 
 	cancel_delayed_work_sync(&priv->init_alive_start);
-	cancel_delayed_work(&priv->scan_check);
-	cancel_work_sync(&priv->start_internal_scan);
 	cancel_delayed_work(&priv->alive_start);
 	cancel_work_sync(&priv->run_time_calib_work);
 	cancel_work_sync(&priv->beacon_update);
+
+	iwl_cancel_scan_deferred_work(priv);
+
+	cancel_work_sync(&priv->bt_full_concurrency);
+	cancel_work_sync(&priv->bt_runtime_config);
+
 	del_timer_sync(&priv->statistics_periodic);
 	del_timer_sync(&priv->ucode_trace);
-	if (priv->cfg->ops->lib->recover_from_tx_stall)
-		del_timer_sync(&priv->monitor_recover);
 }
 
 static void iwl_init_hw_rates(struct iwl_priv *priv,
@@ -3838,8 +4133,6 @@
 {
 	int ret;
 
-	priv->ibss_beacon = NULL;
-
 	spin_lock_init(&priv->sta_lock);
 	spin_lock_init(&priv->hcmd_lock);
 
@@ -3865,10 +4158,23 @@
 
 	/* Choose which receivers/antennas to use */
 	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv);
+		priv->cfg->ops->hcmd->set_rxon_chain(priv,
+					&priv->contexts[IWL_RXON_CTX_BSS]);
 
 	iwl_init_scan_params(priv);
 
+	/* init bt coex */
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist) {
+		priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
+		priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
+		priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
+		priv->bt_on_thresh = BT_ON_THRESHOLD_DEF;
+		priv->bt_duration = BT_DURATION_LIMIT_DEF;
+		priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF;
+		priv->dynamic_agg_thresh = BT_AGG_THRESHOLD_DEF;
+	}
+
 	/* Set the tx_power_user_lmt to the lowest power level
 	 * this value will get overwritten by channel max power avg
 	 * from eeprom */
@@ -3923,11 +4229,60 @@
 	.sta_remove = iwl_mac_sta_remove,
 	.channel_switch = iwl_mac_channel_switch,
 	.flush = iwl_mac_flush,
+	.tx_last_beacon = iwl_mac_tx_last_beacon,
+};
+
+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);
+	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
+}
+
+static int iwl_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 iwlagn_bss_ac_to_fifo[] = {
+	IWL_TX_FIFO_VO,
+	IWL_TX_FIFO_VI,
+	IWL_TX_FIFO_BE,
+	IWL_TX_FIFO_BK,
+};
+
+static const u8 iwlagn_bss_ac_to_queue[] = {
+	0, 1, 2, 3,
+};
+
+static const u8 iwlagn_pan_ac_to_fifo[] = {
+	IWL_TX_FIFO_VO_IPAN,
+	IWL_TX_FIFO_VI_IPAN,
+	IWL_TX_FIFO_BE_IPAN,
+	IWL_TX_FIFO_BK_IPAN,
+};
+
+static const u8 iwlagn_pan_ac_to_queue[] = {
+	7, 6, 5, 4,
 };
 
 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	int err = 0;
+	int err = 0, i;
 	struct iwl_priv *priv;
 	struct ieee80211_hw *hw;
 	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
@@ -3941,9 +4296,8 @@
 	/* Disabling hardware scan means that mac80211 will perform scans
 	 * "the hard way", rather than using device's scan. */
 	if (cfg->mod_params->disable_hw_scan) {
-		if (iwl_debug_level & IWL_DL_INFO)
-			dev_printk(KERN_DEBUG, &(pdev->dev),
-				   "Disabling hw_scan\n");
+		dev_printk(KERN_DEBUG, &(pdev->dev),
+			"sw scan support is deprecated\n");
 		iwl_hw_ops.hw_scan = NULL;
 	}
 
@@ -3955,6 +4309,53 @@
 	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 = iwlagn_bss_ac_to_fifo;
+	priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_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].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;
+
+	priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
+	priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING;
+	priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd = REPLY_WIPAN_RXON_ASSOC;
+	priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
+	priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
+	priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
+	priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID;
+	priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION;
+	priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo;
+	priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue;
+	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);
+	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;
+
+	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
 	SET_IEEE80211_DEV(hw, &pdev->dev);
 
 	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
@@ -3962,12 +4363,23 @@
 	priv->pci_dev = pdev;
 	priv->inta_mask = CSR_INI_SET_MASK;
 
+	/* is antenna coupling more than 35dB ? */
+	priv->bt_ant_couple_ok =
+		(iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
+		true : false;
+
+	/* enable/disable bt channel announcement */
+	priv->bt_ch_announce = iwlagn_bt_ch_announce;
+
 	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;
@@ -4190,7 +4602,7 @@
 	 * paths to avoid running iwl_down() at all before leaving driver.
 	 * This (inexpensive) call *makes sure* device is reset.
 	 */
-	priv->cfg->ops->lib->apm_ops.stop(priv);
+	iwl_apm_stop(priv);
 
 	iwl_tt_exit(priv);
 
@@ -4233,8 +4645,7 @@
 
 	iwl_free_isr_ict(priv);
 
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	dev_kfree_skb(priv->beacon_skb);
 
 	ieee80211_free_hw(priv->hw);
 }
@@ -4398,6 +4809,22 @@
 	{IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
 	{IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
 	{IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
+
+/* 100 Series WiFi */
+	{IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
+	{IWL_PCI_DEVICE(0x08AE, 0x1017, iwl100_bg_cfg)},
+
+/* 130 Series WiFi */
+	{IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
+
 #endif /* CONFIG_IWL5000 */
 
 	{0}
@@ -4486,9 +4913,18 @@
 MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
 module_param_named(
 	disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO);
-MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
+MODULE_PARM_DESC(disable_hw_scan,
+		 "disable hardware scanning (default 0) (deprecated)");
 
 module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int,
 		   S_IRUGO);
 MODULE_PARM_DESC(ucode_alternative,
 		 "specify ucode alternative to use from ucode file");
+
+module_param_named(antenna_coupling, iwlagn_ant_coupling, int, S_IRUGO);
+MODULE_PARM_DESC(antenna_coupling,
+		 "specify antenna coupling in dB (defualt: 0 dB)");
+
+module_param_named(bt_ch_announce, iwlagn_bt_ch_announce, bool, S_IRUGO);
+MODULE_PARM_DESC(bt_ch_announce,
+		 "Enable BT channel announcement mode (default: enable)");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index cc6464d..f525d55f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -92,9 +92,14 @@
 extern struct iwl_cfg iwl6050g2_bgn_cfg;
 extern struct iwl_cfg iwl1000_bgn_cfg;
 extern struct iwl_cfg iwl1000_bg_cfg;
+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_mod_params iwlagn_mod_params;
 extern struct iwl_hcmd_ops iwlagn_hcmd;
+extern struct iwl_hcmd_ops iwlagn_bt_hcmd;
 extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
 
 int iwl_reset_ict(struct iwl_priv *priv);
@@ -124,6 +129,10 @@
 void iwl_free_tfds_in_queue(struct iwl_priv *priv,
 			    int sta_id, int tid, int freed);
 
+/* RXON */
+int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+
 /* uCode */
 int iwlagn_load_ucode(struct iwl_priv *priv);
 void iwlagn_rx_calib_result(struct iwl_priv *priv,
@@ -133,6 +142,8 @@
 void iwlagn_init_alive_start(struct iwl_priv *priv);
 int iwlagn_alive_notify(struct iwl_priv *priv);
 int iwl_verify_ucode(struct iwl_priv *priv);
+void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
+void iwlagn_send_prio_tbl(struct iwl_priv *priv);
 
 /* lib */
 void iwl_check_abort_status(struct iwl_priv *priv,
@@ -151,6 +162,8 @@
 int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
 int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
 void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
+void iwl_dump_csr(struct iwl_priv *priv);
+int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
 
 /* rx */
 void iwlagn_rx_queue_restock(struct iwl_priv *priv);
@@ -164,8 +177,15 @@
 		     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);
 
 /* tx */
+void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+int iwl_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 iwl_hw_tx_queue_init(struct iwl_priv *priv,
+			 struct iwl_tx_queue *txq);
 void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
 			      struct ieee80211_tx_info *info);
 int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
@@ -205,6 +225,8 @@
 	       (status == TX_STATUS_DIRECT_DONE);
 }
 
+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);
@@ -216,14 +238,84 @@
 			  struct iwl_rx_mem_buffer *rxb);
 
 /* scan */
-void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
+int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
+void iwlagn_post_scan(struct iwl_priv *priv);
 
 /* station mgmt */
 int iwlagn_manage_ibss_station(struct iwl_priv *priv,
 			       struct ieee80211_vif *vif, bool add);
 
 /* hcmd */
-int iwlagn_send_rxon_assoc(struct iwl_priv *priv);
+int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
+			   struct iwl_rxon_context *ctx);
 int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
 
+/* bt coex */
+void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
+void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
+				  struct iwl_rx_mem_buffer *rxb);
+void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);
+void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);
+void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv);
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+const char *iwl_get_tx_fail_reason(u32 status);
+const char *iwl_get_agg_tx_fail_reason(u16 status);
+#else
+static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; }
+static inline const char *iwl_get_agg_tx_fail_reason(u16 status) { return ""; }
+#endif
+
+/* station management */
+int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx);
+int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+			     const u8 *addr, u8 *sta_id_r);
+int iwl_remove_default_wep_key(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx,
+			       struct ieee80211_key_conf *key);
+int iwl_set_default_wep_key(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    struct ieee80211_key_conf *key);
+int iwl_restore_default_wep_keys(struct iwl_priv *priv,
+				 struct iwl_rxon_context *ctx);
+int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+			struct ieee80211_key_conf *key, u8 sta_id);
+int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+			   struct ieee80211_key_conf *key, u8 sta_id);
+void iwl_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 iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
+int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			 int tid, u16 ssn);
+int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			int tid);
+void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id);
+void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
+int iwl_update_bcast_stations(struct iwl_priv *priv);
+
+/* rate */
+static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
+{
+	return BIT(ant_idx) << RATE_MCS_ANT_POS;
+}
+
+static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
+{
+	return le32_to_cpu(rate_n_flags) & 0xFF;
+}
+
+static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
+{
+	return cpu_to_le32(flags|(u32)rate);
+}
+
+/* eeprom */
+void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv);
+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);
+
 #endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h
deleted file mode 100644
index ba9523f..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-calib.h
+++ /dev/null
@@ -1,82 +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_calib_h__
-#define __iwl_calib_h__
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-commands.h"
-
-void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp);
-void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp);
-
-void iwl_init_sensitivity(struct iwl_priv *priv);
-void iwl_reset_run_time_calib(struct iwl_priv *priv);
-static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
-{
-
-	if (!priv->disable_chain_noise_cal &&
-	    priv->cfg->ops->utils->chain_noise_reset)
-		priv->cfg->ops->utils->chain_noise_reset(priv);
-}
-
-#endif /* __iwl_calib_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 60725a5..424801a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -62,7 +62,7 @@
  *****************************************************************************/
 /*
  * Please use this file (iwl-commands.h) only for uCode API definitions.
- * Please use iwl-4965-hw.h for hardware-related definitions.
+ * Please use iwl-xxxx-hw.h for hardware-related definitions.
  * Please use iwl-dev.h for driver implementation definitions.
  */
 
@@ -173,6 +173,23 @@
 	REPLY_RX_MPDU_CMD = 0xc1,
 	REPLY_RX = 0xc3,
 	REPLY_COMPRESSED_BA = 0xc5,
+
+	/* BT Coex */
+	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,
+	REPLY_WIPAN_RXON = 0xb3,	/* use REPLY_RXON structure */
+	REPLY_WIPAN_RXON_TIMING = 0xb4,	/* use REPLY_RXON_TIMING structure */
+	REPLY_WIPAN_RXON_ASSOC = 0xb6,	/* use REPLY_RXON_ASSOC structure */
+	REPLY_WIPAN_QOS_PARAM = 0xb7,	/* use REPLY_QOS_PARAM structure */
+	REPLY_WIPAN_WEPKEY = 0xb8,	/* use REPLY_WEPKEY structure */
+	REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9,
+	REPLY_WIPAN_NOA_NOTIFICATION = 0xbc,
+
 	REPLY_MAX = 0xff
 };
 
@@ -403,12 +420,12 @@
 
 /**
  * Command REPLY_TX_POWER_DBM_CMD = 0x98
- * struct iwl5000_tx_power_dbm_cmd
+ * struct iwlagn_tx_power_dbm_cmd
  */
-#define IWL50_TX_POWER_AUTO 0x7f
-#define IWL50_TX_POWER_NO_CLOSED (0x1 << 6)
+#define IWLAGN_TX_POWER_AUTO 0x7f
+#define IWLAGN_TX_POWER_NO_CLOSED (0x1 << 6)
 
-struct iwl5000_tx_power_dbm_cmd {
+struct iwlagn_tx_power_dbm_cmd {
 	s8 global_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */
 	u8 flags;
 	s8 srv_chan_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */
@@ -600,6 +617,9 @@
 	RXON_DEV_TYPE_ESS = 3,
 	RXON_DEV_TYPE_IBSS = 4,
 	RXON_DEV_TYPE_SNIFFER = 6,
+	RXON_DEV_TYPE_CP = 7,
+	RXON_DEV_TYPE_2STA = 8,
+	RXON_DEV_TYPE_P2P = 9,
 };
 
 
@@ -816,7 +836,8 @@
 	__le16 atim_window;
 	__le32 beacon_init_val;
 	__le16 listen_interval;
-	__le16 reserved;
+	u8 dtim_period;
+	u8 delta_cp_bss_tbtts;
 } __packed;
 
 /*
@@ -953,11 +974,13 @@
 
 /* Special, dedicated locations within device's station table */
 #define	IWL_AP_ID		0
+#define	IWL_AP_ID_PAN		1
 #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 IWLAGN_PAN_BCAST_ID	14
 #define IWLAGN_BROADCAST_ID	15
 #define	IWLAGN_STATION_COUNT	16
 
@@ -966,6 +989,7 @@
 
 #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_PAN_STATION		cpu_to_le32(1 << 13)
 #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)
@@ -994,6 +1018,7 @@
 #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
+#define STA_KEY_MAX_NUM_PAN	16
 
 /* Flags indicate whether to modify vs. don't change various station params */
 #define	STA_MODIFY_KEY_MASK		0x01
@@ -1017,7 +1042,7 @@
 	u8 key[16];		/* 16-byte unicast decryption key */
 } __packed;
 
-/* 5000 */
+/* agn */
 struct iwl_keyinfo {
 	__le16 key_flags;
 	u8 tkip_rx_tsc_byte2;	/* TSC[2] for key mix ph1 detection */
@@ -1056,7 +1081,8 @@
  *
  * 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 uses REPLY_TX_LINK_QUALITY_CMD,
+ * initial Tx attempt and any retries (agn 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
@@ -1142,7 +1168,7 @@
 	__le16 reserved2;
 } __packed;
 
-/* 5000 */
+/* agn */
 struct iwl_addsta_cmd {
 	u8 mode;		/* 1: modify existing, 0: add new station */
 	u8 reserved[3];
@@ -1367,21 +1393,24 @@
 } __packed;
 
 
-#define IWL50_RX_RES_PHY_CNT 8
-#define IWL50_RX_RES_AGC_IDX     1
-#define IWL50_RX_RES_RSSI_AB_IDX 2
-#define IWL50_RX_RES_RSSI_C_IDX  3
-#define IWL50_OFDM_AGC_MSK 0xfe00
-#define IWL50_OFDM_AGC_BIT_POS 9
-#define IWL50_OFDM_RSSI_A_MSK 0x00ff
-#define IWL50_OFDM_RSSI_A_BIT_POS 0
-#define IWL50_OFDM_RSSI_B_MSK 0xff0000
-#define IWL50_OFDM_RSSI_B_BIT_POS 16
-#define IWL50_OFDM_RSSI_C_MSK 0x00ff
-#define IWL50_OFDM_RSSI_C_BIT_POS 0
+#define IWLAGN_RX_RES_PHY_CNT 8
+#define IWLAGN_RX_RES_AGC_IDX     1
+#define IWLAGN_RX_RES_RSSI_AB_IDX 2
+#define IWLAGN_RX_RES_RSSI_C_IDX  3
+#define IWLAGN_OFDM_AGC_MSK 0xfe00
+#define IWLAGN_OFDM_AGC_BIT_POS 9
+#define IWLAGN_OFDM_RSSI_INBAND_A_BITMSK 0x00ff
+#define IWLAGN_OFDM_RSSI_ALLBAND_A_BITMSK 0xff00
+#define IWLAGN_OFDM_RSSI_A_BIT_POS 0
+#define IWLAGN_OFDM_RSSI_INBAND_B_BITMSK 0xff0000
+#define IWLAGN_OFDM_RSSI_ALLBAND_B_BITMSK 0xff000000
+#define IWLAGN_OFDM_RSSI_B_BIT_POS 16
+#define IWLAGN_OFDM_RSSI_INBAND_C_BITMSK 0x00ff
+#define IWLAGN_OFDM_RSSI_ALLBAND_C_BITMSK 0xff00
+#define IWLAGN_OFDM_RSSI_C_BIT_POS 0
 
-struct iwl5000_non_cfg_phy {
-	__le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT];  /* up to 8 phy entries */
+struct iwlagn_non_cfg_phy {
+	__le32 non_cfg_phy[IWLAGN_RX_RES_PHY_CNT];  /* up to 8 phy entries */
 } __packed;
 
 
@@ -1401,7 +1430,7 @@
 	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 reserved3;
+	__le16 frame_time;	/* frame's time on the air */
 } __packed;
 
 struct iwl_rx_mpdu_res_start {
@@ -1424,12 +1453,12 @@
  * 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 (4965).
+ * 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).
+ * REPLY_TX_LINK_QUALITY_CMD (agn).
  *
  * 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.
@@ -1465,7 +1494,7 @@
  * Set this for unicast frames, but not broadcast/multicast. */
 #define TX_CMD_FLG_ACK_MSK cpu_to_le32(1 << 3)
 
-/* For 4965:
+/* For agn 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.
@@ -1484,7 +1513,7 @@
  */
 #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.
+/* Tx antenna selection field; used only for 3945, reserved (0) for agn 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)
@@ -1791,13 +1820,8 @@
 	TX_STATUS_FAIL_TID_DISABLE = 0x8d,
 	TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e,
 	TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f,
-	/* uCode drop due to FW drop request */
-	TX_STATUS_FAIL_FW_DROP = 0x90,
-	/*
-	 * uCode drop due to station color mismatch
-	 * between tx command and station table
-	 */
-	TX_STATUS_FAIL_STA_COLOR_MISMATCH_DROP = 0x91,
+	TX_STATUS_FAIL_PASSIVE_NO_RX = 0x90,
+	TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91,
 };
 
 #define	TX_PACKET_MODE_REGULAR		0x0000
@@ -1839,6 +1863,9 @@
 	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 | \
 				     AGG_TX_STATE_LAST_SENT_BT_KILL_MSK)
@@ -1867,9 +1894,10 @@
  *     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 records this status.
+ *     block-ack has not been received by the time the agn device records
+ *     this status.
  *     This status relates to reasons the tx might have been blocked or aborted
- *     within the sending station (this 4965), rather than whether it was
+ *     within the sending station (this agn device), rather than whether it was
  *     received successfully by the destination station.
  */
 struct agg_tx_status {
@@ -1931,12 +1959,12 @@
 #define IWL50_TX_RES_INV_RATE_INDEX_MSK	0x80
 
 /* refer to ra_tid */
-#define IWL50_TX_RES_TID_POS	0
-#define IWL50_TX_RES_TID_MSK	0x0f
-#define IWL50_TX_RES_RA_POS	4
-#define IWL50_TX_RES_RA_MSK	0xf0
+#define IWLAGN_TX_RES_TID_POS	0
+#define IWLAGN_TX_RES_TID_MSK	0x0f
+#define IWLAGN_TX_RES_RA_POS	4
+#define IWLAGN_TX_RES_RA_MSK	0xf0
 
-struct iwl5000_tx_resp {
+struct iwlagn_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 */
@@ -2092,8 +2120,8 @@
 } __packed;
 
 #define LINK_QUAL_AGG_TIME_LIMIT_DEF	(4000) /* 4 milliseconds */
-#define LINK_QUAL_AGG_TIME_LIMIT_MAX	(65535)
-#define LINK_QUAL_AGG_TIME_LIMIT_MIN	(0)
+#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)
@@ -2110,8 +2138,10 @@
  */
 struct iwl_link_qual_agg_params {
 
-	/* Maximum number of uSec in aggregation.
-	 * Driver should set this to 4000 (4 milliseconds). */
+	/*
+	 *Maximum number of uSec in aggregation.
+	 * default set to 4000 (4 milliseconds) if not configured in .cfg
+	 */
 	__le16 agg_time_limit;
 
 	/*
@@ -2135,14 +2165,16 @@
 /*
  * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
  *
- * For 4965 only; 3945 uses REPLY_RATE_SCALE.
+ * For agn devices only; 3945 uses REPLY_RATE_SCALE.
  *
- * Each station in the 4965's internal station table has its own table of 16
+ * Each station in the agn 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's station table.  Use REPLY_ADD_STA.
+ * NOTE:  Station must already be in agn 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.
@@ -2179,12 +2211,12 @@
  *
  * ACCUMULATING HISTORY
  *
- * The rate scaling algorithm for 4965, 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.
+ * The rate scaling algorithm for agn 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
@@ -2195,12 +2227,12 @@
  * 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 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
+ * When the agn 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
@@ -2330,7 +2362,7 @@
 	/*
 	 * Rate info; when using rate-scaling, Tx command's initial_rate_index
 	 * specifies 1st Tx rate attempted, via index into this table.
-	 * 4965 works its way through table when retrying Tx.
+	 * agn devices works its way through table when retrying Tx.
 	 */
 	struct {
 		__le32 rate_n_flags;	/* RATE_MCS_*, IWL_RATE_* */
@@ -2363,10 +2395,26 @@
 #define BT_MAX_KILL_DEF (0x5)
 #define BT_MAX_KILL_MAX (0xFF)
 
+#define BT_DURATION_LIMIT_DEF	625
+#define BT_DURATION_LIMIT_MAX	1250
+#define BT_DURATION_LIMIT_MIN	625
+
+#define BT_ON_THRESHOLD_DEF	4
+#define BT_ON_THRESHOLD_MAX	1000
+#define BT_ON_THRESHOLD_MIN	1
+
+#define BT_FRAG_THRESHOLD_DEF	0
+#define BT_FRAG_THRESHOLD_MAX	0
+#define BT_FRAG_THRESHOLD_MIN	0
+
+#define BT_AGG_THRESHOLD_DEF	0
+#define BT_AGG_THRESHOLD_MAX	0
+#define BT_AGG_THRESHOLD_MIN	0
+
 /*
  * REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
  *
- * 3945 and 4965 support hardware handshake with Bluetooth device on
+ * 3945 and agn 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.
  */
@@ -2379,6 +2427,79 @@
 	__le32 kill_cts_mask;
 } __packed;
 
+#define IWLAGN_BT_FLAG_CHANNEL_INHIBITION	BIT(0)
+
+#define IWLAGN_BT_FLAG_COEX_MODE_MASK		(BIT(3)|BIT(4)|BIT(5))
+#define IWLAGN_BT_FLAG_COEX_MODE_SHIFT		3
+#define IWLAGN_BT_FLAG_COEX_MODE_DISABLED	0
+#define IWLAGN_BT_FLAG_COEX_MODE_LEGACY_2W	1
+#define IWLAGN_BT_FLAG_COEX_MODE_3W		2
+#define IWLAGN_BT_FLAG_COEX_MODE_4W		3
+
+#define IWLAGN_BT_FLAG_UCODE_DEFAULT	BIT(6)
+#define IWLAGN_BT_FLAG_NOCOEX_NOTIF	BIT(7)
+
+#define IWLAGN_BT_PRIO_BOOST_MAX	0xFF
+#define IWLAGN_BT_PRIO_BOOST_MIN	0x00
+#define IWLAGN_BT_PRIO_BOOST_DEFAULT	0xF0
+
+#define IWLAGN_BT_MAX_KILL_DEFAULT	5
+
+#define IWLAGN_BT3_T7_DEFAULT		1
+
+#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT	cpu_to_le32(0xffffffff)
+#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT	cpu_to_le32(0xffffffff)
+
+#define IWLAGN_BT3_PRIO_SAMPLE_DEFAULT	2
+
+#define IWLAGN_BT3_T2_DEFAULT		0xc
+
+#define IWLAGN_BT_VALID_ENABLE_FLAGS	cpu_to_le16(BIT(0))
+#define IWLAGN_BT_VALID_BOOST		cpu_to_le16(BIT(1))
+#define IWLAGN_BT_VALID_MAX_KILL	cpu_to_le16(BIT(2))
+#define IWLAGN_BT_VALID_3W_TIMERS	cpu_to_le16(BIT(3))
+#define IWLAGN_BT_VALID_KILL_ACK_MASK	cpu_to_le16(BIT(4))
+#define IWLAGN_BT_VALID_KILL_CTS_MASK	cpu_to_le16(BIT(5))
+#define IWLAGN_BT_VALID_BT4_TIMES	cpu_to_le16(BIT(6))
+#define IWLAGN_BT_VALID_3W_LUT		cpu_to_le16(BIT(7))
+
+#define IWLAGN_BT_ALL_VALID_MSK		(IWLAGN_BT_VALID_ENABLE_FLAGS | \
+					IWLAGN_BT_VALID_BOOST | \
+					IWLAGN_BT_VALID_MAX_KILL | \
+					IWLAGN_BT_VALID_3W_TIMERS | \
+					IWLAGN_BT_VALID_KILL_ACK_MASK | \
+					IWLAGN_BT_VALID_KILL_CTS_MASK | \
+					IWLAGN_BT_VALID_BT4_TIMES | \
+					IWLAGN_BT_VALID_3W_LUT)
+
+struct iwlagn_bt_cmd {
+	u8 flags;
+	u8 ledtime; /* unused */
+	u8 max_kill;
+	u8 bt3_timer_t7_value;
+	__le32 kill_ack_mask;
+	__le32 kill_cts_mask;
+	u8 bt3_prio_sample_time;
+	u8 bt3_timer_t2_value;
+	__le16 bt4_reaction_time; /* unused */
+	__le32 bt3_lookup_table[12];
+	__le16 bt4_decision_time; /* unused */
+	__le16 valid;
+	u8 prio_boost;
+	/*
+	 * set IWLAGN_BT_VALID_BOOST to "1" in "valid" bitmask
+	 * if configure the following patterns
+	 */
+	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 {
+	__le32 flags;
+};
+
 /******************************************************************************
  * (6)
  * Spectrum Management (802.11h) Commands, Responses, Notifications:
@@ -2567,7 +2688,7 @@
 
 /*
  * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
- * 3945 and 4965 identical.
+ * all devices identical.
  */
 struct iwl_sleep_notification {
 	u8 pm_sleep_mode;
@@ -2578,7 +2699,7 @@
 	__le32 bcon_timer;
 } __packed;
 
-/* Sleep states.  3945 and 4965 identical. */
+/* Sleep states.  all devices identical. */
 enum {
 	IWL_PM_NO_SLEEP = 0,
 	IWL_PM_SLP_MAC = 1,
@@ -2887,6 +3008,12 @@
 #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)
@@ -2894,7 +3021,8 @@
 struct iwl_scanresults_notification {
 	u8 channel;
 	u8 band;
-	u8 reserved[2];
+	u8 probe_status;
+	u8 num_probe_not_sent; /* not enough time to send */
 	__le32 tsf_low;
 	__le32 tsf_high;
 	__le32 statistics[NUMBER_OF_STATISTICS];
@@ -2906,7 +3034,7 @@
 struct iwl_scancomplete_notification {
 	u8 scanned_channels;
 	u8 status;
-	u8 reserved;
+	u8 bt_status;	/* BT On/Off status */
 	u8 last_channel;
 	__le32 tsf_low;
 	__le32 tsf_high;
@@ -2919,6 +3047,11 @@
  *
  *****************************************************************************/
 
+enum iwl_ibss_manager {
+	IWL_NOT_IBSS_MANAGER = 0,
+	IWL_IBSS_MANAGER = 1,
+};
+
 /*
  * BEACON_NOTIFICATION = 0x90 (notification only, not a command)
  */
@@ -3260,7 +3393,7 @@
 
 /*
  * REPLY_STATISTICS_CMD = 0x9c,
- * 3945 and 4965 identical.
+ * all devices identical.
  *
  * This command triggers an immediate response containing uCode statistics.
  * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below.
@@ -3598,7 +3731,7 @@
 /**
  * REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response)
  *
- * This command sets the relative gains of 4965's 3 radio receiver chains.
+ * This command sets the relative gains of agn 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
@@ -3651,7 +3784,8 @@
  */
 
 /* 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_PHY_CALIBRATE_DC_CMD		= 8,
@@ -3660,13 +3794,29 @@
 	IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD	= 15,
 	IWL_PHY_CALIBRATE_BASE_BAND_CMD		= 16,
 	IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD	= 17,
-	IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE	= 18,
+	IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD	= 18,
+	IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE	= 19,
 };
 
 #define IWL_MAX_PHY_CALIBRATE_TBL_SIZE		(253)
 
 #define IWL_CALIB_INIT_CFG_ALL	cpu_to_le32(0xffffffff)
 
+/* This enum defines the bitmap of various calibrations to enable in both
+ * init ucode and runtime ucode through CALIBRATION_CFG_CMD.
+ */
+enum iwl_ucode_calib_cfg {
+	IWL_CALIB_CFG_RX_BB_IDX,
+	IWL_CALIB_CFG_DC_IDX,
+	IWL_CALIB_CFG_TX_IQ_IDX,
+	IWL_CALIB_CFG_RX_IQ_IDX,
+	IWL_CALIB_CFG_NOISE_IDX,
+	IWL_CALIB_CFG_CRYSTAL_IDX,
+	IWL_CALIB_CFG_TEMPERATURE_IDX,
+	IWL_CALIB_CFG_PAPD_IDX,
+};
+
+
 struct iwl_calib_cfg_elmnt_s {
 	__le32 is_enable;
 	__le32 start;
@@ -3715,6 +3865,13 @@
 	u8 pad[2];
 } __packed;
 
+#define DEFAULT_RADIO_SENSOR_OFFSET    2700
+struct iwl_calib_temperature_offset_cmd {
+	struct iwl_calib_hdr hdr;
+	s16 radio_sensor_offset;
+	s16 reserved;
+} __packed;
+
 /* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
 struct iwl_calib_chain_noise_reset_cmd {
 	struct iwl_calib_hdr hdr;
@@ -3955,6 +4112,201 @@
 
 
 /******************************************************************************
+ * Bluetooth Coexistence commands
+ *
+ *****************************************************************************/
+
+/*
+ * BT Status notification
+ * REPLY_BT_COEX_PROFILE_NOTIF = 0xce
+ */
+enum iwl_bt_coex_profile_traffic_load {
+	IWL_BT_COEX_TRAFFIC_LOAD_NONE = 	0,
+	IWL_BT_COEX_TRAFFIC_LOAD_LOW =		1,
+	IWL_BT_COEX_TRAFFIC_LOAD_HIGH = 	2,
+	IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS =	3,
+/*
+ * There are no more even though below is a u8, the
+ * indication from the BT device only has two bits.
+ */
+};
+
+#define BT_UART_MSG_FRAME1MSGTYPE_POS		(0)
+#define BT_UART_MSG_FRAME1MSGTYPE_MSK		\
+		(0x7 << BT_UART_MSG_FRAME1MSGTYPE_POS)
+#define BT_UART_MSG_FRAME1SSN_POS		(3)
+#define BT_UART_MSG_FRAME1SSN_MSK		\
+		(0x3 << BT_UART_MSG_FRAME1SSN_POS)
+#define BT_UART_MSG_FRAME1UPDATEREQ_POS		(5)
+#define BT_UART_MSG_FRAME1UPDATEREQ_MSK		\
+		(0x1 << BT_UART_MSG_FRAME1UPDATEREQ_POS)
+#define BT_UART_MSG_FRAME1RESERVED_POS		(6)
+#define BT_UART_MSG_FRAME1RESERVED_MSK		\
+		(0x3 << BT_UART_MSG_FRAME1RESERVED_POS)
+
+#define BT_UART_MSG_FRAME2OPENCONNECTIONS_POS	(0)
+#define BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK	\
+		(0x3 << BT_UART_MSG_FRAME2OPENCONNECTIONS_POS)
+#define BT_UART_MSG_FRAME2TRAFFICLOAD_POS	(2)
+#define BT_UART_MSG_FRAME2TRAFFICLOAD_MSK	\
+		(0x3 << BT_UART_MSG_FRAME2TRAFFICLOAD_POS)
+#define BT_UART_MSG_FRAME2CHLSEQN_POS		(4)
+#define BT_UART_MSG_FRAME2CHLSEQN_MSK		\
+		(0x1 << BT_UART_MSG_FRAME2CHLSEQN_POS)
+#define BT_UART_MSG_FRAME2INBAND_POS		(5)
+#define BT_UART_MSG_FRAME2INBAND_MSK		\
+		(0x1 << BT_UART_MSG_FRAME2INBAND_POS)
+#define BT_UART_MSG_FRAME2RESERVED_POS		(6)
+#define BT_UART_MSG_FRAME2RESERVED_MSK		\
+		(0x3 << BT_UART_MSG_FRAME2RESERVED_POS)
+
+#define BT_UART_MSG_FRAME3SCOESCO_POS		(0)
+#define BT_UART_MSG_FRAME3SCOESCO_MSK		\
+		(0x1 << BT_UART_MSG_FRAME3SCOESCO_POS)
+#define BT_UART_MSG_FRAME3SNIFF_POS		(1)
+#define BT_UART_MSG_FRAME3SNIFF_MSK		\
+		(0x1 << BT_UART_MSG_FRAME3SNIFF_POS)
+#define BT_UART_MSG_FRAME3A2DP_POS		(2)
+#define BT_UART_MSG_FRAME3A2DP_MSK		\
+		(0x1 << BT_UART_MSG_FRAME3A2DP_POS)
+#define BT_UART_MSG_FRAME3ACL_POS		(3)
+#define BT_UART_MSG_FRAME3ACL_MSK		\
+		(0x1 << BT_UART_MSG_FRAME3ACL_POS)
+#define BT_UART_MSG_FRAME3MASTER_POS		(4)
+#define BT_UART_MSG_FRAME3MASTER_MSK		\
+		(0x1 << BT_UART_MSG_FRAME3MASTER_POS)
+#define BT_UART_MSG_FRAME3OBEX_POS		(5)
+#define BT_UART_MSG_FRAME3OBEX_MSK		\
+		(0x1 << BT_UART_MSG_FRAME3OBEX_POS)
+#define BT_UART_MSG_FRAME3RESERVED_POS		(6)
+#define BT_UART_MSG_FRAME3RESERVED_MSK		\
+		(0x3 << BT_UART_MSG_FRAME3RESERVED_POS)
+
+#define BT_UART_MSG_FRAME4IDLEDURATION_POS	(0)
+#define BT_UART_MSG_FRAME4IDLEDURATION_MSK	\
+		(0x3F << BT_UART_MSG_FRAME4IDLEDURATION_POS)
+#define BT_UART_MSG_FRAME4RESERVED_POS		(6)
+#define BT_UART_MSG_FRAME4RESERVED_MSK		\
+		(0x3 << BT_UART_MSG_FRAME4RESERVED_POS)
+
+#define BT_UART_MSG_FRAME5TXACTIVITY_POS	(0)
+#define BT_UART_MSG_FRAME5TXACTIVITY_MSK	\
+		(0x3 << BT_UART_MSG_FRAME5TXACTIVITY_POS)
+#define BT_UART_MSG_FRAME5RXACTIVITY_POS	(2)
+#define BT_UART_MSG_FRAME5RXACTIVITY_MSK	\
+		(0x3 << BT_UART_MSG_FRAME5RXACTIVITY_POS)
+#define BT_UART_MSG_FRAME5ESCORETRANSMIT_POS	(4)
+#define BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK	\
+		(0x3 << BT_UART_MSG_FRAME5ESCORETRANSMIT_POS)
+#define BT_UART_MSG_FRAME5RESERVED_POS		(6)
+#define BT_UART_MSG_FRAME5RESERVED_MSK		\
+		(0x3 << BT_UART_MSG_FRAME5RESERVED_POS)
+
+#define BT_UART_MSG_FRAME6SNIFFINTERVAL_POS	(0)
+#define BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK	\
+		(0x1F << BT_UART_MSG_FRAME6SNIFFINTERVAL_POS)
+#define BT_UART_MSG_FRAME6DISCOVERABLE_POS	(5)
+#define BT_UART_MSG_FRAME6DISCOVERABLE_MSK	\
+		(0x1 << BT_UART_MSG_FRAME6DISCOVERABLE_POS)
+#define BT_UART_MSG_FRAME6RESERVED_POS		(6)
+#define BT_UART_MSG_FRAME6RESERVED_MSK		\
+		(0x3 << BT_UART_MSG_FRAME6RESERVED_POS)
+
+#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_FRAME7CONNECTABLE_POS	(5)
+#define BT_UART_MSG_FRAME7CONNECTABLE_MSK	\
+		(0x1 << BT_UART_MSG_FRAME7CONNECTABLE_POS)
+#define BT_UART_MSG_FRAME7RESERVED_POS		(6)
+#define BT_UART_MSG_FRAME7RESERVED_MSK		\
+		(0x3 << BT_UART_MSG_FRAME7RESERVED_POS)
+
+
+struct iwl_bt_uart_msg {
+	u8 header;
+	u8 frame1;
+	u8 frame2;
+	u8 frame3;
+	u8 frame4;
+	u8 frame5;
+	u8 frame6;
+	u8 frame7;
+} __attribute__((packed));
+
+struct iwl_bt_coex_profile_notif {
+	struct iwl_bt_uart_msg last_bt_uart_msg;
+	u8 bt_status; /* 0 - off, 1 - on */
+	u8 bt_traffic_load; /* 0 .. 3? */
+	u8 bt_ci_compliance; /* 0 - not complied, 1 - complied */
+	u8 reserved;
+} __attribute__((packed));
+
+#define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS	0
+#define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_MSK	0x1
+#define IWL_BT_COEX_PRIO_TBL_PRIO_POS		1
+#define IWL_BT_COEX_PRIO_TBL_PRIO_MASK		0x0e
+#define IWL_BT_COEX_PRIO_TBL_RESERVED_POS	4
+#define IWL_BT_COEX_PRIO_TBL_RESERVED_MASK	0xf0
+#define IWL_BT_COEX_PRIO_TBL_PRIO_SHIFT		1
+
+/*
+ * BT Coexistence Priority table
+ * REPLY_BT_COEX_PRIO_TABLE = 0xcc
+ */
+enum bt_coex_prio_table_events {
+	BT_COEX_PRIO_TBL_EVT_INIT_CALIB1 = 0,
+	BT_COEX_PRIO_TBL_EVT_INIT_CALIB2 = 1,
+	BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1 = 2,
+	BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2 = 3, /* DC calib */
+	BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1 = 4,
+	BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2 = 5,
+	BT_COEX_PRIO_TBL_EVT_DTIM = 6,
+	BT_COEX_PRIO_TBL_EVT_SCAN52 = 7,
+	BT_COEX_PRIO_TBL_EVT_SCAN24 = 8,
+	BT_COEX_PRIO_TBL_EVT_RESERVED0 = 9,
+	BT_COEX_PRIO_TBL_EVT_RESERVED1 = 10,
+	BT_COEX_PRIO_TBL_EVT_RESERVED2 = 11,
+	BT_COEX_PRIO_TBL_EVT_RESERVED3 = 12,
+	BT_COEX_PRIO_TBL_EVT_RESERVED4 = 13,
+	BT_COEX_PRIO_TBL_EVT_RESERVED5 = 14,
+	BT_COEX_PRIO_TBL_EVT_RESERVED6 = 15,
+	/* BT_COEX_PRIO_TBL_EVT_MAX should always be last */
+	BT_COEX_PRIO_TBL_EVT_MAX,
+};
+
+enum bt_coex_prio_table_priorities {
+	BT_COEX_PRIO_TBL_DISABLED = 0,
+	BT_COEX_PRIO_TBL_PRIO_LOW = 1,
+	BT_COEX_PRIO_TBL_PRIO_HIGH = 2,
+	BT_COEX_PRIO_TBL_PRIO_BYPASS = 3,
+	BT_COEX_PRIO_TBL_PRIO_COEX_OFF = 4,
+	BT_COEX_PRIO_TBL_PRIO_COEX_ON = 5,
+	BT_COEX_PRIO_TBL_PRIO_RSRVD1 = 6,
+	BT_COEX_PRIO_TBL_PRIO_RSRVD2 = 7,
+	BT_COEX_PRIO_TBL_MAX,
+};
+
+struct iwl_bt_coex_prio_table_cmd {
+	u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX];
+} __attribute__((packed));
+
+#define IWL_BT_COEX_ENV_CLOSE	0
+#define IWL_BT_COEX_ENV_OPEN	1
+/*
+ * BT Protection Envelope
+ * REPLY_BT_COEX_PROT_ENV = 0xcd
+ */
+struct iwl_bt_coex_prot_env_cmd {
+	u8 action; /* 0 = closed, 1 = open */
+	u8 type; /* 0 .. 15 */
+	u8 reserved[2];
+} __attribute__((packed));
+
+/******************************************************************************
  * (13)
  * Union of all expected notifications/responses:
  *
@@ -3993,6 +4345,7 @@
 		struct iwl_missed_beacon_notif missed_beacon;
 		struct iwl_coex_medium_notification coex_medium_notif;
 		struct iwl_coex_event_resp coex_event;
+		struct iwl_bt_coex_profile_notif bt_coex_profile_notif;
 		__le32 status;
 		u8 raw[0];
 	} u;
@@ -4000,4 +4353,94 @@
 
 int iwl_agn_check_rxon_cmd(struct iwl_priv *priv);
 
+/*
+ * REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification)
+ */
+
+/**
+ * struct iwl_wipan_slot
+ * @width: Time in TU
+ * @type:
+ *   0 - BSS
+ *   1 - PAN
+ */
+struct iwl_wipan_slot {
+	__le16 width;
+	u8 type;
+	u8 reserved;
+} __packed;
+
+#define IWL_WIPAN_PARAMS_FLG_LEAVE_CHANNEL_CTS		BIT(1)	/* reserved */
+#define IWL_WIPAN_PARAMS_FLG_LEAVE_CHANNEL_QUIET	BIT(2)	/* reserved */
+#define IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE		BIT(3)	/* reserved */
+#define IWL_WIPAN_PARAMS_FLG_FILTER_BEACON_NOTIF	BIT(4)
+#define IWL_WIPAN_PARAMS_FLG_FULL_SLOTTED_MODE		BIT(5)
+
+/**
+ * struct iwl_wipan_params_cmd
+ * @flags:
+ *   bit0: reserved
+ *   bit1: CP leave channel with CTS
+ *   bit2: CP leave channel qith Quiet
+ *   bit3: slotted mode
+ *     1 - work in slotted mode
+ *     0 - work in non slotted mode
+ *   bit4: filter beacon notification
+ *   bit5: full tx slotted mode. if this flag is set,
+ *         uCode will perform leaving channel methods in context switch
+ *         also when working in same channel mode
+ * @num_slots: 1 - 10
+ */
+struct iwl_wipan_params_cmd {
+	__le16 flags;
+	u8 reserved;
+	u8 num_slots;
+	struct iwl_wipan_slot slots[10];
+} __packed;
+
+/*
+ * REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9
+ *
+ * TODO: Figure out what this is used for,
+ *	 it can only switch between 2.4 GHz
+ *	 channels!!
+ */
+
+struct iwl_wipan_p2p_channel_switch_cmd {
+	__le16 channel;
+	__le16 reserved;
+};
+
+/*
+ * REPLY_WIPAN_NOA_NOTIFICATION = 0xbc
+ *
+ * This is used by the device to notify us of the
+ * NoA schedule it determined so we can forward it
+ * to userspace for inclusion in probe responses.
+ *
+ * In beacons, the NoA schedule is simply appended
+ * to the frame we give the device.
+ */
+
+struct iwl_wipan_noa_descriptor {
+	u8 count;
+	__le32 duration;
+	__le32 interval;
+	__le32 starttime;
+} __packed;
+
+struct iwl_wipan_noa_attribute {
+	u8 id;
+	__le16 length;
+	u8 index;
+	u8 ct_window;
+	struct iwl_wipan_noa_descriptor descr0, descr1;
+	u8 reserved;
+} __packed;
+
+struct iwl_wipan_noa_notification {
+	u32 noa_active;
+	struct iwl_wipan_noa_attribute noa_attribute;
+} __packed;
+
 #endif				/* __iwl_commands_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 07dbc27..25fb391 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -64,97 +64,14 @@
  *
  * default: bt_coex_active = true (BT_COEX_ENABLE)
  */
-static bool bt_coex_active = true;
+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");
 
-#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_MIMO3_##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 }
-
 u32 iwl_debug_level;
 EXPORT_SYMBOL(iwl_debug_level);
 
-/*
- * 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 iwl_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 */
-	/* FIXME:RS:          ^^    should be INV (legacy) */
-};
-EXPORT_SYMBOL(iwl_rates);
-
-int iwl_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_MIMO3_6M_PLCP)
-			idx = idx - IWL_RATE_MIMO3_6M_PLCP;
-		else 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(iwl_rates); idx++)
-			if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
-				return idx;
-	}
-
-	return -1;
-}
-EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx);
-
-u8 iwl_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;
-}
-EXPORT_SYMBOL(iwl_toggle_tx_ant);
-
 const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 EXPORT_SYMBOL(iwl_bcast_addr);
 
@@ -183,38 +100,33 @@
 }
 EXPORT_SYMBOL(iwl_alloc_all);
 
-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);
-}
-EXPORT_SYMBOL(iwl_hw_detect);
-
 /*
  * QoS  support
 */
-static void iwl_update_qos(struct iwl_priv *priv)
+static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	priv->qos_data.def_qos_parm.qos_flags = 0;
+	if (!ctx->is_active)
+		return;
 
-	if (priv->qos_data.qos_active)
-		priv->qos_data.def_qos_parm.qos_flags |=
+	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 (priv->current_ht_config.is_ht)
-		priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_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",
-		      priv->qos_data.qos_active,
-		      priv->qos_data.def_qos_parm.qos_flags);
+		      ctx->qos_data.qos_active,
+		      ctx->qos_data.def_qos_parm.qos_flags);
 
-	iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM,
+	iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
 			       sizeof(struct iwl_qosparam_cmd),
-			       &priv->qos_data.def_qos_parm, NULL);
+			       &ctx->qos_data.def_qos_parm, NULL);
 }
 
 #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
@@ -232,7 +144,8 @@
 
 	ht_info->ht_supported = true;
 
-	if (priv->cfg->ht_greenfield_support)
+	if (priv->cfg->ht_params &&
+	    priv->cfg->ht_params->ht_greenfield_support)
 		ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
 	ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
 	max_bit_rate = MAX_BIT_RATE_20_MHZ;
@@ -247,7 +160,11 @@
 		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
 
 	ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
+	if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_factor)
+		ht_info->ampdu_factor = priv->cfg->bt_params->ampdu_factor;
 	ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
+	if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_density)
+		ht_info->ampdu_density = priv->cfg->bt_params->ampdu_density;
 
 	ht_info->mcs.rx_mask[0] = 0xFF;
 	if (rx_chains_num >= 2)
@@ -434,21 +351,15 @@
 EXPORT_SYMBOL(iwlcore_tx_cmd_protection);
 
 
-static bool is_single_rx_stream(struct iwl_priv *priv)
-{
-	return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
-	       priv->current_ht_config.single_chain_sufficient;
-}
-
-static u8 iwl_is_channel_extension(struct iwl_priv *priv,
-				   enum ieee80211_band band,
-				   u16 channel, u8 extension_chan_offset)
+static bool iwl_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_get_channel_info(priv, band, channel);
 	if (!is_channel_valid(ch_info))
-		return 0;
+		return false;
 
 	if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
 		return !(ch_info->ht40_extension_channel &
@@ -457,38 +368,59 @@
 		return !(ch_info->ht40_extension_channel &
 					IEEE80211_CHAN_NO_HT40MINUS);
 
-	return 0;
+	return false;
 }
 
-u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
-			 struct ieee80211_sta_ht_cap *sta_ht_inf)
+bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    struct ieee80211_sta_ht_cap *ht_cap)
 {
-	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
+		return false;
 
-	if (!ht_conf->is_ht || !ht_conf->is_40mhz)
-		return 0;
-
-	/* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
+	/*
+	 * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
 	 * the bit will not set if it is pure 40MHz case
 	 */
-	if (sta_ht_inf) {
-		if (!sta_ht_inf->ht_supported)
-			return 0;
-	}
+	if (ht_cap && !ht_cap->ht_supported)
+		return false;
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 	if (priv->disable_ht40)
-		return 0;
+		return false;
 #endif
+
 	return iwl_is_channel_extension(priv, priv->band,
-			le16_to_cpu(priv->staging_rxon.channel),
-			ht_conf->extension_chan_offset);
+			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)
 {
-	u16 new_val = 0;
-	u16 beacon_factor = 0;
+	u16 new_val;
+	u16 beacon_factor;
+
+	/*
+	 * If mac80211 hasn't given us a beacon interval, program
+	 * the default into the device (not checking this here
+	 * would cause the adjustment below to return the maximum
+	 * value, which may break PAN.)
+	 */
+	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;
@@ -499,51 +431,76 @@
 	return new_val;
 }
 
-void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif)
+int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
 	u64 tsf;
 	s32 interval_tm, rem;
-	unsigned long flags;
 	struct ieee80211_conf *conf = NULL;
 	u16 beacon_int;
+	struct ieee80211_vif *vif = ctx->vif;
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
-	priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval);
+	lockdep_assert_held(&priv->mutex);
 
-	beacon_int = vif->bss_conf.beacon_int;
+	memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
 
-	if (vif->type == NL80211_IFTYPE_ADHOC) {
-		/* TODO: we need to get atim_window from upper stack
-		 * for now we set to 0 */
-		priv->rxon_timing.atim_window = 0;
+	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;
+
+	if (ctx->ctxid == IWL_RXON_CTX_PAN &&
+	    (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION) &&
+	    iwl_is_associated(priv, IWL_RXON_CTX_BSS) &&
+	    priv->contexts[IWL_RXON_CTX_BSS].vif &&
+	    priv->contexts[IWL_RXON_CTX_BSS].vif->bss_conf.beacon_int) {
+		ctx->timing.beacon_interval =
+			priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval;
+		beacon_int = le16_to_cpu(ctx->timing.beacon_interval);
+	} else if (ctx->ctxid == IWL_RXON_CTX_BSS &&
+		   iwl_is_associated(priv, IWL_RXON_CTX_PAN) &&
+		   priv->contexts[IWL_RXON_CTX_PAN].vif &&
+		   priv->contexts[IWL_RXON_CTX_PAN].vif->bss_conf.beacon_int &&
+		   (!iwl_is_associated_ctx(ctx) || !ctx->vif ||
+		    !ctx->vif->bss_conf.beacon_int)) {
+		ctx->timing.beacon_interval =
+			priv->contexts[IWL_RXON_CTX_PAN].timing.beacon_interval;
+		beacon_int = le16_to_cpu(ctx->timing.beacon_interval);
 	} else {
-		priv->rxon_timing.atim_window = 0;
-	}
-
-	beacon_int = iwl_adjust_beacon_interval(beacon_int,
+		beacon_int = iwl_adjust_beacon_interval(beacon_int,
 				priv->hw_params.max_beacon_itrvl * TIME_UNIT);
-	priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int);
+		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);
-	priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
+	ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	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(priv->rxon_timing.beacon_interval),
-			le32_to_cpu(priv->rxon_timing.beacon_init_val),
-			le16_to_cpu(priv->rxon_timing.atim_window));
-}
-EXPORT_SYMBOL(iwl_setup_rxon_timing);
+			le16_to_cpu(ctx->timing.beacon_interval),
+			le32_to_cpu(ctx->timing.beacon_init_val),
+			le16_to_cpu(ctx->timing.atim_window));
 
-void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
+	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)
 {
-	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+	struct iwl_rxon_cmd *rxon = &ctx->staging;
 
 	if (hw_decrypt)
 		rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
@@ -553,76 +510,74 @@
 }
 EXPORT_SYMBOL(iwl_set_rxon_hwcrypto);
 
-/**
- * iwl_check_rxon_cmd - validate RXON structure is valid
- *
- * NOTE:  This is really only useful during development and can eventually
- * be #ifdef'd out once the driver is stable and folks aren't actively
- * making changes
- */
-int iwl_check_rxon_cmd(struct iwl_priv *priv)
+/* validate RXON structure is valid */
+int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
-	int error = 0;
-	int counter = 1;
-	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+	struct iwl_rxon_cmd *rxon = &ctx->staging;
+	bool error = false;
 
 	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
-		error |= le32_to_cpu(rxon->flags &
-				(RXON_FLG_TGJ_NARROW_BAND_MSK |
-				 RXON_FLG_RADAR_DETECT_MSK));
-		if (error)
-			IWL_WARN(priv, "check 24G fields %d | %d\n",
-				    counter++, error);
+		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 {
-		error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ?
-				0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK);
-		if (error)
-			IWL_WARN(priv, "check 52 fields %d | %d\n",
-				    counter++, error);
-		error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK);
-		if (error)
-			IWL_WARN(priv, "check 52 CCK %d | %d\n",
-				    counter++, error);
+		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;
+		}
 	}
-	error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1;
-	if (error)
-		IWL_WARN(priv, "check mac addr %d | %d\n", counter++, error);
+	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 */
-	error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) &&
-		  ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0));
-	if (error)
-		IWL_WARN(priv, "check basic rate %d | %d\n", counter++, error);
+	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;
+	}
 
-	error |= (le16_to_cpu(rxon->assoc_id) > 2007);
-	if (error)
-		IWL_WARN(priv, "check assoc id %d | %d\n", counter++, error);
+	if (le16_to_cpu(rxon->assoc_id) > 2007) {
+		IWL_WARN(priv, "aid > 2007\n");
+		error = true;
+	}
 
-	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
-			== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK));
-	if (error)
-		IWL_WARN(priv, "check CCK and short slot %d | %d\n",
-			    counter++, error);
+	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;
+	}
 
-	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
-			== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK));
-	if (error)
-		IWL_WARN(priv, "check CCK & auto detect %d | %d\n",
-			    counter++, error);
+	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;
+	}
 
-	error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
-			RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK);
-	if (error)
-		IWL_WARN(priv, "check TGG and auto detect %d | %d\n",
-			    counter++, error);
+	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, "Not a valid iwl_rxon_assoc_cmd field values\n");
-		return -1;
+		IWL_ERR(priv, "Invalid RXON\n");
+		return -EINVAL;
 	}
 	return 0;
 }
@@ -636,66 +591,83 @@
  * 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_full_rxon_required(struct iwl_priv *priv)
+int iwl_full_rxon_required(struct iwl_priv *priv,
+			   struct iwl_rxon_context *ctx)
 {
+	const struct iwl_rxon_cmd *staging = &ctx->staging;
+	const struct iwl_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 */
-	if (!(iwl_is_associated(priv)) ||
-	    compare_ether_addr(priv->staging_rxon.bssid_addr,
-			       priv->active_rxon.bssid_addr) ||
-	    compare_ether_addr(priv->staging_rxon.node_addr,
-			       priv->active_rxon.node_addr) ||
-	    compare_ether_addr(priv->staging_rxon.wlap_bssid_addr,
-			       priv->active_rxon.wlap_bssid_addr) ||
-	    (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) ||
-	    (priv->staging_rxon.channel != priv->active_rxon.channel) ||
-	    (priv->staging_rxon.air_propagation !=
-	     priv->active_rxon.air_propagation) ||
-	    (priv->staging_rxon.ofdm_ht_single_stream_basic_rates !=
-	     priv->active_rxon.ofdm_ht_single_stream_basic_rates) ||
-	    (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates !=
-	     priv->active_rxon.ofdm_ht_dual_stream_basic_rates) ||
-	    (priv->staging_rxon.ofdm_ht_triple_stream_basic_rates !=
-	     priv->active_rxon.ofdm_ht_triple_stream_basic_rates) ||
-	    (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id))
-		return 1;
+	CHK(!iwl_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->ofdm_ht_triple_stream_basic_rates,
+		active->ofdm_ht_triple_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 */
-	if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) !=
-	    (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK))
-		return 1;
+	CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK,
+		active->flags & RXON_FLG_BAND_24G_MSK);
 
 	/* Check if we are switching association toggle */
-	if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) !=
-		(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK))
-		return 1;
+	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_full_rxon_required);
 
-u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv)
+u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx)
 {
 	/*
 	 * Assign the lowest rate -- should really get this from
 	 * the beacon skb from mac80211.
 	 */
-	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
+	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
 		return IWL_RATE_1M_PLCP;
 	else
 		return IWL_RATE_6M_PLCP;
 }
 EXPORT_SYMBOL(iwl_rate_get_lowest_plcp);
 
-void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
+static void _iwl_set_rxon_ht(struct iwl_priv *priv,
+			     struct iwl_ht_config *ht_conf,
+			     struct iwl_rxon_context *ctx)
 {
-	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+	struct iwl_rxon_cmd *rxon = &ctx->staging;
 
-	if (!ht_conf->is_ht) {
+	if (!ctx->ht.enabled) {
 		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
 			RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
 			RXON_FLG_HT40_PROT_MSK |
@@ -703,22 +675,22 @@
 		return;
 	}
 
-	/* FIXME: if the definition of ht_protection changed, the "translation"
+	/* FIXME: if the definition of ht.protection changed, the "translation"
 	 * will be needed for rxon->flags
 	 */
-	rxon->flags |= cpu_to_le32(ht_conf->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS);
+	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_is_ht40_tx_allowed(priv, NULL)) {
+	if (iwl_is_ht40_tx_allowed(priv, ctx, NULL)) {
 		/* pure ht40 */
-		if (ht_conf->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
+		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 (ht_conf->extension_chan_offset) {
+			switch (ctx->ht.extension_chan_offset) {
 			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
 				rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
 				break;
@@ -728,7 +700,7 @@
 			}
 		} else {
 			/* Note: control channel is opposite of extension channel */
-			switch (ht_conf->extension_chan_offset) {
+			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;
@@ -749,162 +721,58 @@
 	}
 
 	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv);
+		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), ht_conf->ht_protection,
-			ht_conf->extension_chan_offset);
+			le32_to_cpu(rxon->flags), ctx->ht.protection,
+			ctx->ht.extension_chan_offset);
+}
+
+void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
+{
+	struct iwl_rxon_context *ctx;
+
+	for_each_context(priv, ctx)
+		_iwl_set_rxon_ht(priv, ht_conf, ctx);
 }
 EXPORT_SYMBOL(iwl_set_rxon_ht);
 
-#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 iwl_get_active_rx_chain_count(struct iwl_priv *priv)
-{
-	/* # of Rx chains to use when expecting MIMO. */
-	if (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 iwl_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 iwl_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;
-}
-
-/**
- * iwl_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 iwl_set_rxon_chain(struct iwl_priv *priv)
-{
-	bool is_single = 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, iwl_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 = iwl_get_active_rx_chain_count(priv);
-	idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
-
-
-	/* correct rx chain count according hw settings
-	 * and chain noise calibration
-	 */
-	valid_rx_cnt = iwl_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;
-
-	priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
-
-	if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
-		priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
-	else
-		priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
-
-	IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
-			priv->staging_rxon.rx_chain,
-			active_rx_cnt, idle_rx_cnt);
-
-	WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
-		active_rx_cnt < idle_rx_cnt);
-}
-EXPORT_SYMBOL(iwl_set_rxon_chain);
-
-/* Return valid channel */
+/* Return valid, unused, channel for a passive scan to reset the RF */
 u8 iwl_get_single_channel_number(struct iwl_priv *priv,
-				  enum ieee80211_band band)
+				 enum ieee80211_band band)
 {
 	const struct iwl_channel_info *ch_info;
 	int i;
 	u8 channel = 0;
+	u8 min, max;
+	struct iwl_rxon_context *ctx;
 
-	/* only scan single channel, good enough to reset the RF */
-	/* pick the first valid not in-use channel */
 	if (band == IEEE80211_BAND_5GHZ) {
-		for (i = 14; i < priv->channel_count; i++) {
-			if (priv->channel_info[i].channel !=
-			    le16_to_cpu(priv->staging_rxon.channel)) {
-				channel = priv->channel_info[i].channel;
-				ch_info = iwl_get_channel_info(priv,
-					band, channel);
-				if (is_channel_valid(ch_info))
-					break;
-			}
-		}
+		min = 14;
+		max = priv->channel_count;
 	} else {
-		for (i = 0; i < 14; i++) {
-			if (priv->channel_info[i].channel !=
-			    le16_to_cpu(priv->staging_rxon.channel)) {
-					channel =
-						priv->channel_info[i].channel;
-					ch_info = iwl_get_channel_info(priv,
-						band, channel);
-					if (is_channel_valid(ch_info))
-						break;
-			}
+		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_get_channel_info(priv, band, channel);
+		if (is_channel_valid(ch_info))
+			break;
 	}
 
 	return channel;
@@ -912,35 +780,27 @@
 EXPORT_SYMBOL(iwl_get_single_channel_number);
 
 /**
- * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
- * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
- * @channel: Any channel valid for the requested phymode
+ * iwl_set_rxon_channel - Set the band and channel values in staging RXON
+ * @ch: requested channel as a pointer to struct ieee80211_channel
 
- * In addition to setting the staging RXON, priv->phymode is also set.
- *
  * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
- * in the staging RXON flag structure based on the phymode
+ * in the staging RXON flag structure based on the ch->band
  */
-int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch)
+int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
+			 struct iwl_rxon_context *ctx)
 {
 	enum ieee80211_band band = ch->band;
-	u16 channel = ieee80211_frequency_to_channel(ch->center_freq);
+	u16 channel = ch->hw_value;
 
-	if (!iwl_get_channel_info(priv, band, channel)) {
-		IWL_DEBUG_INFO(priv, "Could not set channel to %d [%d]\n",
-			       channel, band);
-		return -EINVAL;
-	}
-
-	if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
+	if ((le16_to_cpu(ctx->staging.channel) == channel) &&
 	    (priv->band == band))
 		return 0;
 
-	priv->staging_rxon.channel = cpu_to_le16(channel);
+	ctx->staging.channel = cpu_to_le16(channel);
 	if (band == IEEE80211_BAND_5GHZ)
-		priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
+		ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
 	else
-		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
+		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
 
 	priv->band = band;
 
@@ -951,24 +811,25 @@
 EXPORT_SYMBOL(iwl_set_rxon_channel);
 
 void iwl_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) {
-		priv->staging_rxon.flags &=
+		ctx->staging.flags &=
 		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
 		      | RXON_FLG_CCK_MSK);
-		priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
 	} else {
 		/* Copied from iwl_post_associate() */
 		if (vif && vif->bss_conf.use_short_slot)
-			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
 		else
-			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
-		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
-		priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK;
-		priv->staging_rxon.flags &= ~RXON_FLG_CCK_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_set_flags_for_band);
@@ -977,35 +838,34 @@
  * initialize rxon structure with default values from eeprom
  */
 void iwl_connection_init_rx_config(struct iwl_priv *priv,
-				   struct ieee80211_vif *vif)
+				   struct iwl_rxon_context *ctx)
 {
 	const struct iwl_channel_info *ch_info;
-	enum nl80211_iftype type = NL80211_IFTYPE_STATION;
 
-	if (vif)
-		type = vif->type;
+	memset(&ctx->staging, 0, sizeof(ctx->staging));
 
-	memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
-
-	switch (type) {
+	if (!ctx->vif) {
+		ctx->staging.dev_type = ctx->unused_devtype;
+	} else switch (ctx->vif->type) {
 	case NL80211_IFTYPE_AP:
-		priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
+		ctx->staging.dev_type = ctx->ap_devtype;
 		break;
 
 	case NL80211_IFTYPE_STATION:
-		priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
-		priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
+		ctx->staging.dev_type = ctx->station_devtype;
+		ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
 		break;
 
 	case NL80211_IFTYPE_ADHOC:
-		priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
-		priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
-		priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
+		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", type);
+		IWL_ERR(priv, "Unsupported interface type %d\n",
+			ctx->vif->type);
 		break;
 	}
 
@@ -1013,37 +873,36 @@
 	/* TODO:  Figure out when short_preamble would be set and cache from
 	 * that */
 	if (!hw_to_local(priv->hw)->short_preamble)
-		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 	else
-		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 #endif
 
 	ch_info = iwl_get_channel_info(priv, priv->band,
-				       le16_to_cpu(priv->active_rxon.channel));
+				       le16_to_cpu(ctx->active.channel));
 
 	if (!ch_info)
 		ch_info = &priv->channel_info[0];
 
-	priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
+	ctx->staging.channel = cpu_to_le16(ch_info->channel);
 	priv->band = ch_info->band;
 
-	iwl_set_flags_for_band(priv, priv->band, vif);
+	iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
 
-	priv->staging_rxon.ofdm_basic_rates =
+	ctx->staging.ofdm_basic_rates =
 	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
-	priv->staging_rxon.cck_basic_rates =
+	ctx->staging.cck_basic_rates =
 	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
 
 	/* clear both MIX and PURE40 mode flag */
-	priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
+	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);
 
-	if (vif)
-		memcpy(priv->staging_rxon.node_addr, vif->addr, ETH_ALEN);
-
-	priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff;
-	priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff;
-	priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff;
+	ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff;
+	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);
 
@@ -1051,6 +910,7 @@
 {
 	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);
@@ -1069,21 +929,29 @@
 
 	IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate);
 
-	priv->staging_rxon.cck_basic_rates =
-	    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
+	for_each_context(priv, ctx) {
+		ctx->staging.cck_basic_rates =
+		    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
 
-	priv->staging_rxon.ofdm_basic_rates =
-	   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+		ctx->staging.ofdm_basic_rates =
+		   (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)
 {
+	/*
+	 * MULTI-FIXME
+	 * See iwl_mac_channel_switch.
+	 */
+	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(priv->vif, is_success);
+		ieee80211_chswitch_done(ctx->vif, is_success);
 		mutex_lock(&priv->mutex);
 		priv->switch_rxon.switch_in_progress = false;
 		mutex_unlock(&priv->mutex);
@@ -1094,14 +962,19 @@
 void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
 	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;
-			priv->staging_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);
@@ -1115,9 +988,10 @@
 EXPORT_SYMBOL(iwl_rx_csa);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-void iwl_print_rx_config_cmd(struct iwl_priv *priv)
+void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+			     struct iwl_rxon_context *ctx)
 {
-	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+	struct iwl_rxon_cmd *rxon = &ctx->staging;
 
 	IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
 	iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
@@ -1157,7 +1031,8 @@
 	priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
 #ifdef CONFIG_IWLWIFI_DEBUG
 	if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
-		iwl_print_rx_config_cmd(priv);
+		iwl_print_rx_config_cmd(priv,
+					&priv->contexts[IWL_RXON_CTX_BSS]);
 #endif
 
 	wake_up_interruptible(&priv->wait_command_queue);
@@ -1261,7 +1136,7 @@
 	 * If not (unlikely), enable L0S, so there is at least some
 	 *    power savings, even without L1.
 	 */
-	if (priv->cfg->set_l0s) {
+	if (priv->cfg->base_params->set_l0s) {
 		lctl = iwl_pcie_link_ctl(priv);
 		if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
 					PCI_CFG_LINK_CTRL_VAL_L1_EN) {
@@ -1278,8 +1153,9 @@
 	}
 
 	/* Configure analog phase-lock-loop before activating to D0A */
-	if (priv->cfg->pll_cfg_val)
-		iwl_set_bit(priv, CSR_ANA_PLL_CFG, priv->cfg->pll_cfg_val);
+	if (priv->cfg->base_params->pll_cfg_val)
+		iwl_set_bit(priv, CSR_ANA_PLL_CFG,
+			    priv->cfg->base_params->pll_cfg_val);
 
 	/*
 	 * Set "initialization complete" bit to move adapter from
@@ -1310,7 +1186,7 @@
 	 * do not disable clocks.  This preserves any hardware bits already
 	 * set by default in "CLK_CTRL_REG" after reset.
 	 */
-	if (priv->cfg->use_bsm)
+	if (priv->cfg->base_params->use_bsm)
 		iwl_write_prph(priv, APMG_CLK_EN_REG,
 			APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
 	else
@@ -1328,25 +1204,6 @@
 EXPORT_SYMBOL(iwl_apm_init);
 
 
-int iwl_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);
-}
-EXPORT_SYMBOL(iwl_set_hw_params);
-
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 {
 	int ret = 0;
@@ -1496,76 +1353,6 @@
 }
 EXPORT_SYMBOL(iwl_send_statistics_request);
 
-void iwl_rf_kill_ct_config(struct iwl_priv *priv)
-{
-	struct iwl_ct_kill_config cmd;
-	struct iwl_ct_kill_throttling_config adv_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);
-	priv->thermal_throttle.ct_kill_toggle = false;
-
-	if (priv->cfg->support_ct_kill_exit) {
-		adv_cmd.critical_temperature_enter =
-			cpu_to_le32(priv->hw_params.ct_kill_threshold);
-		adv_cmd.critical_temperature_exit =
-			cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
-
-		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
-				       sizeof(adv_cmd), &adv_cmd);
-		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 enter is %d,"
-					"exit is %d\n",
-				       priv->hw_params.ct_kill_threshold,
-				       priv->hw_params.ct_kill_exit_threshold);
-	} else {
-		cmd.critical_temperature_R =
-			cpu_to_le32(priv->hw_params.ct_kill_threshold);
-
-		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
-				       sizeof(cmd), &cmd);
-		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);
-	}
-}
-EXPORT_SYMBOL(iwl_rf_kill_ct_config);
-
-
-/*
- * CARD_STATE_CMD
- *
- * Use: Sets the device's internal card state to enable, disable, or halt
- *
- * When in the 'enable' state the card operates as normal.
- * When in the 'disable' state, the card enters into a low power mode.
- * When in the 'halt' state, the card is shut down and must be fully
- * restarted to come back on.
- */
-int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
-{
-	struct iwl_host_cmd cmd = {
-		.id = REPLY_CARD_STATE_CMD,
-		.len = sizeof(u32),
-		.data = &flags,
-		.flags = meta_flag,
-	};
-
-	return iwl_send_cmd(priv, &cmd);
-}
-
 void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
 			   struct iwl_rx_mem_buffer *rxb)
 {
@@ -1614,6 +1401,7 @@
 			   const struct ieee80211_tx_queue_params *params)
 {
 	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx;
 	unsigned long flags;
 	int q;
 
@@ -1633,13 +1421,21 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min);
-	priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
-	priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
-	priv->qos_data.def_qos_parm.ac[q].edca_txop =
-			cpu_to_le16((params->txop * 32));
+	/*
+	 * MULTI-FIXME
+	 * This may need to be done per interface in nl80211/cfg80211/mac80211.
+	 */
+	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));
 
-	priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
+		ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
+	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -1648,21 +1444,30 @@
 }
 EXPORT_SYMBOL(iwl_mac_conf_tx);
 
+int iwl_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_mac_tx_last_beacon);
+
 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_MAC80211(priv, "enter:\n");
 
-	if (!ht_conf->is_ht)
+	if (!ctx->ht.enabled)
 		return;
 
-	ht_conf->ht_protection =
+	ctx->ht.protection =
 		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
-	ht_conf->non_GF_STA_present =
+	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;
@@ -1706,49 +1511,63 @@
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-static inline void iwl_set_no_assoc(struct iwl_priv *priv)
+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
 	 */
-	priv->staging_rxon.filter_flags &=
-		~RXON_FILTER_ASSOC_MSK;
-	priv->staging_rxon.assoc_id = 0;
-	iwlcore_commit_rxon(priv);
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	ctx->staging.assoc_id = 0;
+	iwlcore_commit_rxon(priv, ctx);
 }
 
-static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
+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);
 
-	IWL_DEBUG_MAC80211(priv, "enter\n");
+	if (!skb)
+		return;
 
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-		return -EIO;
+	IWL_DEBUG_ASSOC(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->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
 
-	priv->ibss_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");
+	IWL_DEBUG_ASSOC(priv, "leave\n");
+
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	priv->cfg->ops->lib->post_associate(priv, priv->vif);
+	if (!iwl_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+		return;
+	}
 
-	return 0;
+	priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif);
 }
 
 void iwl_bss_info_changed(struct ieee80211_hw *hw,
@@ -1757,6 +1576,7 @@
 			  u32 changes)
 {
 	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
 	int ret;
 
 	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
@@ -1770,20 +1590,31 @@
 		unsigned long flags;
 
 		spin_lock_irqsave(&priv->lock, flags);
-		priv->qos_data.qos_active = bss_conf->qos;
-		iwl_update_qos(priv);
+		ctx->qos_data.qos_active = bss_conf->qos;
+		iwl_update_qos(priv, ctx);
 		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 
-	if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
-		dev_kfree_skb(priv->ibss_beacon);
-		priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
+	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_INT) {
-		/* TODO: in AP mode, do something to make this take effect */
+	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);
 
@@ -1801,13 +1632,13 @@
 
 		/* mac80211 only sets assoc when in STATION mode */
 		if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
-			memcpy(priv->staging_rxon.bssid_addr,
+			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 {
-			priv->staging_rxon.filter_flags &=
+			ctx->staging.filter_flags &=
 				~RXON_FILTER_ASSOC_MSK;
 		}
 
@@ -1818,33 +1649,28 @@
 	 * mac80211 decides to do both changes at once because
 	 * it will invoke post_associate.
 	 */
-	if (vif->type == NL80211_IFTYPE_ADHOC &&
-	    changes & BSS_CHANGED_BEACON) {
-		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
-
-		if (beacon)
-			iwl_mac_beacon_update(hw, beacon);
-	}
+	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)
-			priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+			ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 		else
-			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+			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))
-			priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
+			ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
 		else
-			priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+			ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
 		if (bss_conf->use_cts_prot)
-			priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
+			ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
 		else
-			priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
+			ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
 	}
 
 	if (changes & BSS_CHANGED_BASIC_RATES) {
@@ -1854,12 +1680,12 @@
 		 * like this here:
 		 *
 		if (A-band)
-			priv->staging_rxon.ofdm_basic_rates =
+			ctx->staging.ofdm_basic_rates =
 				bss_conf->basic_rates;
 		else
-			priv->staging_rxon.ofdm_basic_rates =
+			ctx->staging.ofdm_basic_rates =
 				bss_conf->basic_rates >> 4;
-			priv->staging_rxon.cck_basic_rates =
+			ctx->staging.cck_basic_rates =
 				bss_conf->basic_rates & 0xF;
 		 */
 	}
@@ -1868,7 +1694,7 @@
 		iwl_ht_conf(priv, vif);
 
 		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv);
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 	}
 
 	if (changes & BSS_CHANGED_ASSOC) {
@@ -1881,29 +1707,30 @@
 			if (!iwl_is_rfkill(priv))
 				priv->cfg->ops->lib->post_associate(priv, vif);
 		} else
-			iwl_set_no_assoc(priv);
+			iwl_set_no_assoc(priv, vif);
 	}
 
-	if (changes && iwl_is_associated(priv) && bss_conf->aid) {
+	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);
+		ret = iwl_send_rxon_assoc(priv, ctx);
 		if (!ret) {
 			/* Sync active_rxon with latest change. */
-			memcpy((void *)&priv->active_rxon,
-				&priv->staging_rxon,
+			memcpy((void *)&ctx->active,
+				&ctx->staging,
 				sizeof(struct iwl_rxon_cmd));
 		}
 	}
 
 	if (changes & BSS_CHANGED_BEACON_ENABLED) {
 		if (vif->bss_conf.enable_beacon) {
-			memcpy(priv->staging_rxon.bssid_addr,
+			memcpy(ctx->staging.bssid_addr,
 			       bss_conf->bssid, ETH_ALEN);
 			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+			iwl_led_associate(priv);
 			iwlcore_config_ap(priv, vif);
 		} else
-			iwl_set_no_assoc(priv);
+			iwl_set_no_assoc(priv, vif);
 	}
 
 	if (changes & BSS_CHANGED_IBSS) {
@@ -1915,6 +1742,12 @@
 				bss_conf->bssid);
 	}
 
+	if (changes & BSS_CHANGED_IDLE &&
+	    priv->cfg->ops->hcmd->set_pan_params) {
+		if (priv->cfg->ops->hcmd->set_pan_params(priv))
+			IWL_ERR(priv, "failed to update PAN params\n");
+	}
+
 	mutex_unlock(&priv->mutex);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -1923,17 +1756,21 @@
 
 static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
-	iwl_connection_init_rx_config(priv, vif);
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+
+	iwl_connection_init_rx_config(priv, ctx);
 
 	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv);
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 
-	return iwlcore_commit_rxon(priv);
+	return iwlcore_commit_rxon(priv, ctx);
 }
 
 int iwl_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 = 0;
 
 	IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
@@ -1941,28 +1778,72 @@
 
 	mutex_lock(&priv->mutex);
 
-	if (WARN_ON(!iwl_is_ready_rf(priv))) {
+	if (!iwl_is_ready_rf(priv)) {
+		IWL_WARN(priv, "Try to add interface when device not ready\n");
 		err = -EINVAL;
 		goto out;
 	}
 
-	if (priv->vif) {
-		IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
+	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;
 	}
 
-	priv->vif = vif;
+	vif_priv->ctx = ctx;
+	ctx->vif = vif;
+	/*
+	 * 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_set_mode(priv, vif);
-	if (err)
+	if (err) {
+		if (!ctx->always_active)
+			ctx->is_active = false;
 		goto out_err;
+	}
+
+	if (priv->cfg->bt_params &&
+	    priv->cfg->bt_params->advanced_bt_coexist &&
+	    vif->type == NL80211_IFTYPE_ADHOC) {
+		/*
+		 * pretend to have high BT traffic as long as we
+		 * are operating in IBSS mode, as this will cause
+		 * the rate scaling etc. to behave as intended.
+		 */
+		priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
+	}
 
 	goto out;
 
  out_err:
-	priv->vif = NULL;
+	ctx->vif = NULL;
 	priv->iw_mode = NL80211_IFTYPE_STATION;
  out:
 	mutex_unlock(&priv->mutex);
@@ -1976,30 +1857,36 @@
 			      struct ieee80211_vif *vif)
 {
 	struct iwl_priv *priv = hw->priv;
-	bool scan_completed = false;
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
 	mutex_lock(&priv->mutex);
 
-	if (iwl_is_ready_rf(priv)) {
-		iwl_scan_cancel_timeout(priv, 100);
-		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv);
-	}
-	if (priv->vif == vif) {
-		priv->vif = NULL;
-		if (priv->scan_vif == vif) {
-			scan_completed = true;
-			priv->scan_vif = NULL;
-			priv->scan_request = NULL;
-		}
-		memset(priv->bssid, 0, ETH_ALEN);
-	}
-	mutex_unlock(&priv->mutex);
+	WARN_ON(ctx->vif != vif);
+	ctx->vif = NULL;
 
-	if (scan_completed)
-		ieee80211_scan_completed(priv->hw, true);
+	if (priv->scan_vif == vif) {
+		iwl_scan_cancel_timeout(priv, 200);
+		iwl_force_scan_end(priv);
+	}
+	iwl_set_mode(priv, vif);
+
+	if (!ctx->always_active)
+		ctx->is_active = false;
+
+	/*
+	 * When removing the IBSS interface, overwrite the
+	 * BT traffic load with the stored one from the last
+	 * notification, if any. If this is a device that
+	 * doesn't implement this, this has no effect since
+	 * both values are the same and zero.
+	 */
+	if (vif->type == NL80211_IFTYPE_ADHOC)
+		priv->bt_traffic_load = priv->notif_bt_traffic_load;
+
+	memset(priv->bssid, 0, ETH_ALEN);
+	mutex_unlock(&priv->mutex);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
@@ -2014,7 +1901,9 @@
 	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;
@@ -2023,7 +1912,7 @@
 	mutex_lock(&priv->mutex);
 
 	IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
-					conf->channel->hw_value, changed);
+					channel->hw_value, changed);
 
 	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
 			test_bit(STATUS_SCANNING, &priv->status))) {
@@ -2044,7 +1933,8 @@
 		 * configured.
 		 */
 		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv);
+			for_each_context(priv, ctx)
+				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 	}
 
 	/* during scanning mac80211 will delay channel setting until
@@ -2054,8 +1944,8 @@
 		if (scan_active)
 			goto set_ch_out;
 
-		ch = ieee80211_frequency_to_channel(conf->channel->center_freq);
-		ch_info = iwl_get_channel_info(priv, conf->channel->band, ch);
+		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;
@@ -2064,42 +1954,49 @@
 
 		spin_lock_irqsave(&priv->lock, flags);
 
-		/* Configure HT40 channels */
-		ht_conf->is_ht = conf_is_ht(conf);
-		if (ht_conf->is_ht) {
-			if (conf_is_ht40_minus(conf)) {
-				ht_conf->extension_chan_offset =
-					IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-				ht_conf->is_40mhz = true;
-			} else if (conf_is_ht40_plus(conf)) {
-				ht_conf->extension_chan_offset =
-					IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-				ht_conf->is_40mhz = true;
-			} else {
-				ht_conf->extension_chan_offset =
-					IEEE80211_HT_PARAM_CHA_SEC_NONE;
-				ht_conf->is_40mhz = false;
-			}
-		} else
-			ht_conf->is_40mhz = false;
-		/* Default to no protection. Protection mode will later be set
-		 * from BSS config in iwl_ht_conf */
-		ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
+		for_each_context(priv, ctx) {
+			/* 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 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(priv->staging_rxon.channel) != ch))
-			priv->staging_rxon.flags = 0;
+			/*
+			 * 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;
 
-		iwl_set_rxon_channel(priv, conf->channel);
-		iwl_set_rxon_ht(priv, ht_conf);
+			/* 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_flags_for_band(priv, conf->channel->band, priv->vif);
+			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->lib->update_bcast_station)
-			ret = priv->cfg->ops->lib->update_bcast_station(priv);
+		if (priv->cfg->ops->lib->update_bcast_stations)
+			ret = priv->cfg->ops->lib->update_bcast_stations(priv);
 
  set_ch_out:
 		/* The list of supported rates and rate mask can be different
@@ -2130,12 +2027,13 @@
 	if (scan_active)
 		goto out;
 
-	if (memcmp(&priv->active_rxon,
-		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
-		iwlcore_commit_rxon(priv);
-	else
-		IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration.\n");
-
+	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");
+	}
 
 out:
 	IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -2148,6 +2046,8 @@
 {
 	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];
 
 	mutex_lock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -2159,15 +2059,16 @@
 	spin_lock_irqsave(&priv->lock, flags);
 
 	/* new association get rid of ibss beacon skb */
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
 
-	priv->ibss_beacon = NULL;
+	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);
@@ -2177,9 +2078,8 @@
 	/* we are restarting association process
 	 * clear RXON_FILTER_ASSOC_MSK bit
 	 */
-	iwl_scan_cancel_timeout(priv, 100);
-	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwlcore_commit_rxon(priv);
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwlcore_commit_rxon(priv, ctx);
 
 	iwl_set_rate(priv);
 
@@ -2193,7 +2093,8 @@
 {
 	if (!priv->txq)
 		priv->txq = kzalloc(
-			sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues,
+			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");
@@ -2449,146 +2350,12 @@
 EXPORT_SYMBOL(iwl_update_stats);
 #endif
 
-static const char *get_csr_string(int cmd)
-{
-	switch (cmd) {
-		IWL_CMD(CSR_HW_IF_CONFIG_REG);
-		IWL_CMD(CSR_INT_COALESCING);
-		IWL_CMD(CSR_INT);
-		IWL_CMD(CSR_INT_MASK);
-		IWL_CMD(CSR_FH_INT_STATUS);
-		IWL_CMD(CSR_GPIO_IN);
-		IWL_CMD(CSR_RESET);
-		IWL_CMD(CSR_GP_CNTRL);
-		IWL_CMD(CSR_HW_REV);
-		IWL_CMD(CSR_EEPROM_REG);
-		IWL_CMD(CSR_EEPROM_GP);
-		IWL_CMD(CSR_OTP_GP_REG);
-		IWL_CMD(CSR_GIO_REG);
-		IWL_CMD(CSR_GP_UCODE_REG);
-		IWL_CMD(CSR_GP_DRIVER_REG);
-		IWL_CMD(CSR_UCODE_DRV_GP1);
-		IWL_CMD(CSR_UCODE_DRV_GP2);
-		IWL_CMD(CSR_LED_REG);
-		IWL_CMD(CSR_DRAM_INT_TBL_REG);
-		IWL_CMD(CSR_GIO_CHICKEN_BITS);
-		IWL_CMD(CSR_ANA_PLL_CFG);
-		IWL_CMD(CSR_HW_REV_WA_REG);
-		IWL_CMD(CSR_DBG_HPET_MEM_REG);
-	default:
-		return "UNKNOWN";
-
-	}
-}
-
-void iwl_dump_csr(struct iwl_priv *priv)
-{
-	int i;
-	u32 csr_tbl[] = {
-		CSR_HW_IF_CONFIG_REG,
-		CSR_INT_COALESCING,
-		CSR_INT,
-		CSR_INT_MASK,
-		CSR_FH_INT_STATUS,
-		CSR_GPIO_IN,
-		CSR_RESET,
-		CSR_GP_CNTRL,
-		CSR_HW_REV,
-		CSR_EEPROM_REG,
-		CSR_EEPROM_GP,
-		CSR_OTP_GP_REG,
-		CSR_GIO_REG,
-		CSR_GP_UCODE_REG,
-		CSR_GP_DRIVER_REG,
-		CSR_UCODE_DRV_GP1,
-		CSR_UCODE_DRV_GP2,
-		CSR_LED_REG,
-		CSR_DRAM_INT_TBL_REG,
-		CSR_GIO_CHICKEN_BITS,
-		CSR_ANA_PLL_CFG,
-		CSR_HW_REV_WA_REG,
-		CSR_DBG_HPET_MEM_REG
-	};
-	IWL_ERR(priv, "CSR values:\n");
-	IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is "
-		"CSR_INT_PERIODIC_REG)\n");
-	for (i = 0; i <  ARRAY_SIZE(csr_tbl); i++) {
-		IWL_ERR(priv, "  %25s: 0X%08x\n",
-			get_csr_string(csr_tbl[i]),
-			iwl_read32(priv, csr_tbl[i]));
-	}
-}
-EXPORT_SYMBOL(iwl_dump_csr);
-
-static const char *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 iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
-{
-	int i;
-#ifdef CONFIG_IWLWIFI_DEBUG
-	int pos = 0;
-	size_t bufsz = 0;
-#endif
-	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_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",
-				get_fh_string(fh_tbl[i]),
-				iwl_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",
-			get_fh_string(fh_tbl[i]),
-			iwl_read_direct32(priv, fh_tbl[i]));
-	}
-	return 0;
-}
-EXPORT_SYMBOL(iwl_dump_fh);
-
 static void iwl_force_rf_reset(struct iwl_priv *priv)
 {
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	if (!iwl_is_associated(priv)) {
+	if (!iwl_is_any_associated(priv)) {
 		IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
 		return;
 	}
@@ -2663,7 +2430,6 @@
 	}
 	return 0;
 }
-EXPORT_SYMBOL(iwl_force_reset);
 
 /**
  * iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover
@@ -2699,29 +2465,31 @@
 	txq = &priv->txq[cnt];
 	q = &txq->q;
 	/* queue is empty, skip */
-	if (q->read_ptr != q->write_ptr) {
-		if (q->read_ptr == q->last_read_ptr) {
-			/* a queue has not been read from last time */
-			if (q->repeat_same_read_ptr > MAX_REPEAT) {
-				IWL_ERR(priv,
-					"queue %d stuck %d time. Fw reload.\n",
-					q->id, q->repeat_same_read_ptr);
-				q->repeat_same_read_ptr = 0;
-				iwl_force_reset(priv, IWL_FW_RESET, false);
-			} else {
-				q->repeat_same_read_ptr++;
-				IWL_DEBUG_RADIO(priv,
-						"queue %d, not read %d time\n",
-						q->id,
-						q->repeat_same_read_ptr);
-				mod_timer(&priv->monitor_recover, jiffies +
-					msecs_to_jiffies(IWL_ONE_HUNDRED_MSECS));
-			}
-			return 1;
-		} else {
-			q->last_read_ptr = q->read_ptr;
+	if (q->read_ptr == q->write_ptr)
+		return 0;
+
+	if (q->read_ptr == q->last_read_ptr) {
+		/* a queue has not been read from last time */
+		if (q->repeat_same_read_ptr > MAX_REPEAT) {
+			IWL_ERR(priv,
+				"queue %d stuck %d time. Fw reload.\n",
+				q->id, q->repeat_same_read_ptr);
 			q->repeat_same_read_ptr = 0;
+			iwl_force_reset(priv, IWL_FW_RESET, false);
+		} else {
+			q->repeat_same_read_ptr++;
+			IWL_DEBUG_RADIO(priv,
+					"queue %d, not read %d time\n",
+					q->id,
+					q->repeat_same_read_ptr);
+			mod_timer(&priv->monitor_recover,
+				jiffies + msecs_to_jiffies(
+				IWL_ONE_HUNDRED_MSECS));
+			return 1;
 		}
+	} else {
+		q->last_read_ptr = q->read_ptr;
+		q->repeat_same_read_ptr = 0;
 	}
 	return 0;
 }
@@ -2735,25 +2503,27 @@
 		return;
 
 	/* monitor and check for stuck cmd queue */
-	if (iwl_check_stuck_queue(priv, IWL_CMD_QUEUE_NUM))
+	if (iwl_check_stuck_queue(priv, priv->cmd_queue))
 		return;
 
 	/* monitor and check for other stuck queues */
-	if (iwl_is_associated(priv)) {
+	if (iwl_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 == IWL_CMD_QUEUE_NUM)
+			if (cnt == priv->cmd_queue)
 				continue;
 			if (iwl_check_stuck_queue(priv, cnt))
 				return;
 		}
 	}
-	/*
-	 * Reschedule the timer to occur in
-	 * priv->cfg->monitor_recover_period
-	 */
-	mod_timer(&priv->monitor_recover,
-		jiffies + msecs_to_jiffies(priv->cfg->monitor_recover_period));
+	if (priv->cfg->base_params->monitor_recover_period) {
+		/*
+		 * Reschedule the timer to occur in
+		 * priv->cfg->base_params->monitor_recover_period
+		 */
+		mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies(
+			  priv->cfg->base_params->monitor_recover_period));
+	}
 }
 EXPORT_SYMBOL(iwl_bg_monitor_recover);
 
@@ -2825,7 +2595,7 @@
 	 * it will not call apm_ops.stop() to stop the DMA operation.
 	 * Calling apm_ops.stop here to make sure we stop the DMA.
 	 */
-	priv->cfg->ops->lib->apm_ops.stop(priv);
+	iwl_apm_stop(priv);
 
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 5e6ee3d..64527de 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -88,11 +88,13 @@
 #define IWL_CMD(x) case x: return #x
 
 struct iwl_hcmd_ops {
-	int (*rxon_assoc)(struct iwl_priv *priv);
-	int (*commit_rxon)(struct iwl_priv *priv);
-	void (*set_rxon_chain)(struct iwl_priv *priv);
+	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);
 	int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant);
 	void (*send_bt_config)(struct iwl_priv *priv);
+	int (*set_pan_params)(struct iwl_priv *priv);
 };
 
 struct iwl_hcmd_utils_ops {
@@ -109,14 +111,13 @@
 				  __le16 fc, __le32 *tx_flags);
 	int  (*calc_rssi)(struct iwl_priv *priv,
 			  struct iwl_rx_phy_res *rx_resp);
-	void (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
+	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 (*stop)(struct iwl_priv *priv);
 	void (*config)(struct iwl_priv *priv);
-	int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
 };
 
 struct iwl_debugfs_ops {
@@ -128,12 +129,18 @@
 				      size_t count, loff_t *ppos);
 	ssize_t (*bt_stats_read)(struct file *file, char __user *user_buf,
 				 size_t count, loff_t *ppos);
+	ssize_t (*reply_tx_error)(struct file *file, char __user *user_buf,
+				 size_t count, loff_t *ppos);
 };
 
 struct iwl_temp_ops {
 	void (*temperature)(struct iwl_priv *priv);
-	void (*set_ct_kill)(struct iwl_priv *priv);
-	void (*set_calib_version)(struct iwl_priv *priv);
+};
+
+struct iwl_tt_ops {
+	bool (*lower_power_detection)(struct iwl_priv *priv);
+	u8 (*tt_power_mode)(struct iwl_priv *priv);
+	bool (*ct_kill_check)(struct iwl_priv *priv);
 };
 
 struct iwl_lib_ops {
@@ -199,7 +206,7 @@
 	/* station management */
 	int (*manage_ibss_station)(struct iwl_priv *priv,
 				   struct ieee80211_vif *vif, bool add);
-	int (*update_bcast_station)(struct iwl_priv *priv);
+	int (*update_bcast_stations)(struct iwl_priv *priv);
 	/* recover from tx queue stall */
 	void (*recover_from_tx_stall)(unsigned long data);
 	/* check for plcp health */
@@ -212,6 +219,9 @@
 	void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
 
 	struct iwl_debugfs_ops debugfs_ops;
+
+	/* thermal throttling */
+	struct iwl_tt_ops tt_ops;
 };
 
 struct iwl_led_ops {
@@ -220,11 +230,17 @@
 	int (*off)(struct iwl_priv *priv);
 };
 
+/* NIC specific ops */
+struct iwl_nic_ops {
+	void (*additional_nic_config)(struct iwl_priv *priv);
+};
+
 struct iwl_ops {
 	const struct iwl_lib_ops *lib;
 	const struct iwl_hcmd_ops *hcmd;
 	const struct iwl_hcmd_utils_ops *utils;
 	const struct iwl_led_ops *led;
+	const struct iwl_nic_ops *nic;
 };
 
 struct iwl_mod_params {
@@ -237,20 +253,12 @@
 	int restart_fw;		/* def: 1 = restart firmware */
 };
 
-/**
- * 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.
- * @pa_type: used by 6000 series only to identify the type of Power Amplifier
+/*
  * @max_ll_items: max number of OTP blocks
  * @shadow_ram_support: shadow support for OTP memory
  * @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
- * @use_rts_for_aggregation: use rts/cts protection for HT traffic
  * @chain_noise_num_beacons: number of beacons used to compute chain noise
  * @adv_thermal_throttle: support advance thermal throttle
  * @support_ct_kill_exit: support ct kill exit condition
@@ -268,58 +276,21 @@
  *	sensitivity calibration operation
  * @chain_noise_calib_by_driver: driver has the capability to perform
  *	chain noise calibration operation
- * @scan_antennas: available antenna for scan operation
- *
- * 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 (4965/5000) as well as their API
- * versions.
- *
- */
-struct iwl_cfg {
-	const char *name;
-	const char *fw_name_pre;
-	const unsigned int ucode_api_max;
-	const unsigned int ucode_api_min;
-	unsigned int sku;
+*/
+struct iwl_base_params {
 	int eeprom_size;
-	u16  eeprom_ver;
-	u16  eeprom_calib_ver;
 	int num_of_queues;	/* def: HW dependent */
 	int num_of_ampdu_queues;/* def: HW dependent */
-	const struct iwl_ops *ops;
-	const struct iwl_mod_params *mod_params;
-	u8   valid_tx_ant;
-	u8   valid_rx_ant;
-
 	/* for iwl_apm_init() */
 	u32 pll_cfg_val;
 	bool set_l0s;
 	bool use_bsm;
 
 	bool use_isr_legacy;
-	enum iwl_pa_type pa_type;
 	const u16 max_ll_items;
 	const bool shadow_ram_support;
-	const bool ht_greenfield_support;
 	u16 led_compensation;
 	const bool broken_powersave;
-	bool use_rts_for_aggregation;
 	int chain_noise_num_beacons;
 	const bool supports_idle;
 	bool adv_thermal_throttle;
@@ -335,10 +306,90 @@
 	const bool ucode_tracing;
 	const bool sensitivity_calib_by_driver;
 	const bool chain_noise_calib_by_driver;
+};
+/*
+ * @advanced_bt_coexist: support advanced bt coexist
+ * @bt_init_traffic_load: specify initial bt traffic load
+ * @bt_prio_boost: default bt priority boost value
+ * @bt_statistics: use BT version of statistics notification
+ * @agg_time_limit: maximum number of uSec in aggregation
+ * @ampdu_factor: Maximum A-MPDU length factor
+ * @ampdu_density: Minimum A-MPDU spacing
+*/
+struct iwl_bt_params {
+	bool advanced_bt_coexist;
+	u8 bt_init_traffic_load;
+	u8 bt_prio_boost;
+	const bool bt_statistics;
+	u16 agg_time_limit;
+	u8 ampdu_factor;
+	u8 ampdu_density;
+};
+/*
+ * @use_rts_for_aggregation: use rts/cts protection for HT traffic
+*/
+struct iwl_ht_params {
+	const bool ht_greenfield_support; /* if used set to true */
+	bool use_rts_for_aggregation;
+};
+
+/**
+ * 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.
+ * @pa_type: used by 6000 series only to identify the type of Power Amplifier
+ * @need_dc_calib: need to perform init dc calibration
+ * @need_temp_offset_calib: need to perform temperature offset calibration
+ * @scan_antennas: available antenna for scan operation
+ *
+ * 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 (4965/5000) 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 */
+	struct iwl_ht_params *ht_params;
+	struct iwl_bt_params *bt_params;
+	enum iwl_pa_type pa_type;	  /* if used set to IWL_PA_SYSTEM */
+	const bool need_dc_calib;	  /* if used set to true */
+	const bool need_temp_offset_calib; /* if used set to true */
 	u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
 	u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
-	const bool need_dc_calib;
-	const bool bt_statistics;
 };
 
 /***************************
@@ -347,38 +398,38 @@
 
 struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
 		struct ieee80211_ops *hw_ops);
-void iwl_hw_detect(struct iwl_priv *priv);
-void iwl_activate_qos(struct iwl_priv *priv);
 int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 		    const struct ieee80211_tx_queue_params *params);
-void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt);
-int iwl_check_rxon_cmd(struct iwl_priv *priv);
-int iwl_full_rxon_required(struct iwl_priv *priv);
-void iwl_set_rxon_chain(struct iwl_priv *priv);
-int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
+int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
+void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+			   int hw_decrypt);
+int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
+			 struct iwl_rxon_context *ctx);
 void iwl_set_flags_for_band(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
 			    enum ieee80211_band band,
 			    struct ieee80211_vif *vif);
 u8 iwl_get_single_channel_number(struct iwl_priv *priv,
 				  enum ieee80211_band band);
 void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
-u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
-			 struct ieee80211_sta_ht_cap *sta_ht_inf);
+bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    struct ieee80211_sta_ht_cap *ht_cap);
 void iwl_connection_init_rx_config(struct iwl_priv *priv,
-				   struct ieee80211_vif *vif);
+				   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_set_hw_params(struct iwl_priv *priv);
 void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif);
 void iwl_bss_info_changed(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_bss_conf *bss_conf,
 				     u32 changes);
-int iwl_commit_rxon(struct iwl_priv *priv);
 int iwl_mac_add_interface(struct ieee80211_hw *hw,
 			  struct ieee80211_vif *vif);
 void iwl_mac_remove_interface(struct ieee80211_hw *hw,
@@ -455,7 +506,6 @@
 ******************************************************/
 void iwl_cmd_queue_free(struct iwl_priv *priv);
 int iwl_rx_queue_alloc(struct iwl_priv *priv);
-void iwl_rx_handle(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);
@@ -473,12 +523,6 @@
 /*****************************************************
 * TX
 ******************************************************/
-void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
-int iwl_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 iwl_hw_tx_queue_init(struct iwl_priv *priv,
-			 struct iwl_tx_queue *txq);
 void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
 int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
 		      int slots_num, u32 txq_id);
@@ -494,29 +538,8 @@
  * Rate
  ******************************************************************************/
 
-int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
-
-u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv);
-
-u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
-
-static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
-{
-	return BIT(ant_idx) << RATE_MCS_ANT_POS;
-}
-
-static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
-{
-	return le32_to_cpu(rate_n_flags) & 0xFF;
-}
-static inline u32 iwl_hw_get_rate_n_flags(__le32 rate_n_flags)
-{
-	return le32_to_cpu(rate_n_flags) & 0x1FFFF;
-}
-static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
-{
-	return cpu_to_le32(flags|(u32)rate);
-}
+u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx);
 
 /*******************************************************************************
  * Scanning
@@ -524,10 +547,10 @@
 void iwl_init_scan_params(struct iwl_priv *priv);
 int iwl_scan_cancel(struct iwl_priv *priv);
 int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
+void iwl_force_scan_end(struct iwl_priv *priv);
 int iwl_mac_hw_scan(struct ieee80211_hw *hw,
 		    struct ieee80211_vif *vif,
 		    struct cfg80211_scan_request *req);
-void iwl_bg_start_internal_scan(struct work_struct *work);
 void iwl_internal_short_hw_scan(struct iwl_priv *priv);
 int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
 u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
@@ -539,10 +562,8 @@
 u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
 			       enum ieee80211_band band,
 			       struct ieee80211_vif *vif);
-void iwl_bg_scan_check(struct work_struct *data);
-void iwl_bg_abort_scan(struct work_struct *work);
-void iwl_bg_scan_completed(struct work_struct *work);
 void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
+void iwl_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
@@ -555,13 +576,6 @@
 
 #define IWL_SCAN_CHECK_WATCHDOG		(HZ * 7)
 
-/*******************************************************************************
- * Calibrations - implemented in iwl-calib.c
- ******************************************************************************/
-int iwl_send_calib_results(struct iwl_priv *priv);
-int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
-void iwl_calib_free_results(struct iwl_priv *priv);
-
 /*****************************************************
  *   S e n d i n g     H o s t     C o m m a n d s   *
  *****************************************************/
@@ -580,8 +594,6 @@
 
 int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
 
-int iwl_send_card_state(struct iwl_priv *priv, u32 flags,
-			u8 meta_flag);
 
 /*****************************************************
  * PCI						     *
@@ -613,12 +625,12 @@
 void iwl_dump_nic_error_log(struct iwl_priv *priv);
 int iwl_dump_nic_event_log(struct iwl_priv *priv,
 			   bool full_log, char **buf, bool display);
-void iwl_dump_csr(struct iwl_priv *priv);
-int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
 #ifdef CONFIG_IWLWIFI_DEBUG
-void iwl_print_rx_config_cmd(struct iwl_priv *priv);
+void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+			     struct iwl_rxon_context *ctx);
 #else
-static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv)
+static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+					   struct iwl_rxon_context *ctx)
 {
 }
 #endif
@@ -695,23 +707,22 @@
 	return iwl_is_ready(priv);
 }
 
-extern void iwl_rf_kill_ct_config(struct iwl_priv *priv);
 extern void iwl_send_bt_config(struct iwl_priv *priv);
 extern int iwl_send_statistics_request(struct iwl_priv *priv,
 				       u8 flags, bool clear);
-extern int iwl_send_lq_cmd(struct iwl_priv *priv,
-		struct iwl_link_quality_cmd *lq, u8 flags, bool init);
 void iwl_apm_stop(struct iwl_priv *priv);
 int iwl_apm_init(struct iwl_priv *priv);
 
-void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif);
-static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
+int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+static inline int iwl_send_rxon_assoc(struct iwl_priv *priv,
+				      struct iwl_rxon_context *ctx)
 {
-	return priv->cfg->ops->hcmd->rxon_assoc(priv);
+	return priv->cfg->ops->hcmd->rxon_assoc(priv, ctx);
 }
-static inline int iwlcore_commit_rxon(struct iwl_priv *priv)
+static inline int iwlcore_commit_rxon(struct iwl_priv *priv,
+				      struct iwl_rxon_context *ctx)
 {
-	return priv->cfg->ops->hcmd->commit_rxon(priv);
+	return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
 }
 static inline void iwlcore_config_ap(struct iwl_priv *priv,
 				     struct ieee80211_vif *vif)
@@ -723,4 +734,8 @@
 {
 	return priv->hw->wiphy->bands[band];
 }
+
+extern bool bt_coex_active;
+extern bool bt_siso_mode;
+
 #endif /* __iwl_core_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index ecf98e7..2aa15ab 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -371,7 +371,8 @@
 #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB	    (0x00000000)
 #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB	    (0x00000001)
 #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA	    (0x00000002)
-#define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6	(0x00000004)
+#define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6	    (0x00000004)
+#define CSR_GP_DRIVER_REG_BIT_6050_1x2		    (0x00000008)
 
 /* GIO Chicken Bits (PCI Express bus link power management) */
 #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index e96a1bb..8fdd4ef 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -39,7 +39,6 @@
 #include "iwl-debug.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
-#include "iwl-calib.h"
 
 /* create and remove of files */
 #define DEBUGFS_ADD_FILE(name, parent, mode) do {			\
@@ -87,6 +86,7 @@
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 	.read = iwl_dbgfs_##name##_read,                       		\
 	.open = iwl_dbgfs_open_file_generic,                    	\
+	.llseek = generic_file_llseek,					\
 };
 
 #define DEBUGFS_WRITE_FILE_OPS(name)                                    \
@@ -94,6 +94,7 @@
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 	.write = iwl_dbgfs_##name##_write,                              \
 	.open = iwl_dbgfs_open_file_generic,                    	\
+	.llseek = generic_file_llseek,					\
 };
 
 
@@ -104,6 +105,7 @@
 	.write = iwl_dbgfs_##name##_write,                              \
 	.read = iwl_dbgfs_##name##_read,                                \
 	.open = iwl_dbgfs_open_file_generic,                            \
+	.llseek = generic_file_llseek,					\
 };
 
 static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
@@ -356,7 +358,7 @@
 	const u8 *ptr;
 	char *buf;
 	u16 eeprom_ver;
-	size_t eeprom_len = priv->cfg->eeprom_size;
+	size_t eeprom_len = priv->cfg->base_params->eeprom_size;
 	buf_size = 4 * eeprom_len + 256;
 
 	if (eeprom_len % 16) {
@@ -467,8 +469,7 @@
 		for (i = 0; i < supp_band->n_channels; i++)
 			pos += scnprintf(buf + pos, bufsz - pos,
 					"%d: %ddBm: BSS%s%s, %s.\n",
-					ieee80211_frequency_to_channel(
-					channels[i].center_freq),
+					channels[i].hw_value,
 					channels[i].max_power,
 					channels[i].flags & IEEE80211_CHAN_RADAR ?
 					" (IEEE 802.11h required)" : "",
@@ -491,8 +492,7 @@
 		for (i = 0; i < supp_band->n_channels; i++)
 			pos += scnprintf(buf + pos, bufsz - pos,
 					"%d: %ddBm: BSS%s%s, %s.\n",
-					ieee80211_frequency_to_channel(
-					channels[i].center_freq),
+					channels[i].hw_value,
 					channels[i].max_power,
 					channels[i].flags & IEEE80211_CHAN_RADAR ?
 					" (IEEE 802.11h required)" : "",
@@ -577,10 +577,10 @@
 		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 > 0) {
+	if (priv->isr_stats.sw || priv->isr_stats.hw) {
 		pos += scnprintf(buf + pos, bufsz - pos,
 			"\tLast Restarting Code:  0x%X\n",
-			priv->isr_stats.sw_err);
+			priv->isr_stats.err_code);
 	}
 #ifdef CONFIG_IWLWIFI_DEBUG
 	pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
@@ -645,19 +645,25 @@
 				       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];
+	char buf[256 * NUM_IWL_RXON_CTX];
 	const size_t bufsz = sizeof(buf);
 
-	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,
+	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,
-				priv->qos_data.def_qos_parm.ac[i].cw_min,
-				priv->qos_data.def_qos_parm.ac[i].cw_max,
-				priv->qos_data.def_qos_parm.ac[i].aifsn,
-				priv->qos_data.def_qos_parm.ac[i].edca_txop);
+				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);
 }
@@ -732,7 +738,7 @@
 		return -EFAULT;
 	if (sscanf(buf, "%d", &ht40) != 1)
 		return -EFAULT;
-	if (!iwl_is_associated(priv))
+	if (!iwl_is_any_associated(priv))
 		priv->disable_ht40 = ht40 ? true : false;
 	else {
 		IWL_ERR(priv, "Sta associated with AP - "
@@ -868,7 +874,7 @@
 	struct iwl_rx_queue *rxq = &priv->rxq;
 	char *buf;
 	int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
-		(priv->cfg->num_of_queues * 32 * 8) + 400;
+		(priv->cfg->base_params->num_of_queues * 32 * 8) + 400;
 	const u8 *ptr;
 	ssize_t ret;
 
@@ -967,7 +973,8 @@
 	int pos = 0;
 	int cnt;
 	int ret;
-	const size_t bufsz = sizeof(char) * 64 * priv->cfg->num_of_queues;
+	const size_t bufsz = sizeof(char) * 64 *
+				priv->cfg->base_params->num_of_queues;
 
 	if (!priv->txq) {
 		IWL_ERR(priv, "txq not ready\n");
@@ -1321,7 +1328,8 @@
 	int len = 0;
 	char buf[20];
 
-	len = sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.flags));
+	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);
 }
 
@@ -1334,7 +1342,7 @@
 	char buf[20];
 
 	len = sprintf(buf, "0x%04X\n",
-		      le32_to_cpu(priv->active_rxon.filter_flags));
+		le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags));
 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
@@ -1410,7 +1418,7 @@
 	const size_t bufsz = sizeof(buf);
 
 	pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
-			priv->cfg->plcp_delta_threshold);
+			priv->cfg->base_params->plcp_delta_threshold);
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
@@ -1432,10 +1440,10 @@
 		return -EINVAL;
 	if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
 		(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
-		priv->cfg->plcp_delta_threshold =
+		priv->cfg->base_params->plcp_delta_threshold =
 			IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
 	else
-		priv->cfg->plcp_delta_threshold = plcp;
+		priv->cfg->base_params->plcp_delta_threshold = plcp;
 	return count;
 }
 
@@ -1529,6 +1537,135 @@
 			user_buf, count, ppos);
 }
 
+static ssize_t iwl_dbgfs_monitor_period_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 period;
+
+	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", &period) != 1)
+		return -EINVAL;
+	if (period < 0 || period > IWL_MAX_MONITORING_PERIOD)
+		priv->cfg->base_params->monitor_recover_period =
+			IWL_DEF_MONITORING_PERIOD;
+	else
+		priv->cfg->base_params->monitor_recover_period = period;
+
+	if (priv->cfg->base_params->monitor_recover_period)
+		mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies(
+			  priv->cfg->base_params->monitor_recover_period));
+	else
+		del_timer_sync(&priv->monitor_recover);
+	return count;
+}
+
+static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+	int pos = 0;
+	char buf[200];
+	const size_t bufsz = sizeof(buf);
+	ssize_t ret;
+
+	pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n",
+		priv->bt_full_concurrent ? "full concurrency" : "3-wire");
+	pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, "
+			 "last traffic notif: %d\n",
+		priv->bt_status ? "On" : "Off", priv->notif_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);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: ");
+	switch (priv->bt_traffic_load) {
+	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+		pos += scnprintf(buf + pos, bufsz - pos, "Continuous\n");
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+		pos += scnprintf(buf + pos, bufsz - pos, "High\n");
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+		pos += scnprintf(buf + pos, bufsz - pos, "Low\n");
+		break;
+	case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+	default:
+		pos += scnprintf(buf + pos, bufsz - pos, "None\n");
+		break;
+	}
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	return ret;
+}
+
+static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+
+	int pos = 0;
+	char buf[40];
+	const size_t bufsz = sizeof(buf);
+
+	if (priv->cfg->ht_params)
+		pos += scnprintf(buf + pos, bufsz - pos,
+			 "use %s for aggregation\n",
+			 (priv->cfg->ht_params->use_rts_for_aggregation) ?
+				"rts/cts" : "cts-to-self");
+	else
+		pos += scnprintf(buf + pos, bufsz - pos, "N/A");
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_dbgfs_protection_mode_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 rts;
+
+	if (!priv->cfg->ht_params)
+		return -EINVAL;
+
+	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", &rts) != 1)
+		return -EINVAL;
+	if (rts)
+		priv->cfg->ht_params->use_rts_for_aggregation = true;
+	else
+		priv->cfg->ht_params->use_rts_for_aggregation = false;
+	return count;
+}
+
+static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+
+	if (priv->cfg->ops->lib->debugfs_ops.reply_tx_error)
+		return priv->cfg->ops->lib->debugfs_ops.reply_tx_error(
+			file, user_buf, count, ppos);
+	else
+		return -ENODATA;
+}
 DEBUGFS_READ_FILE_OPS(rx_statistics);
 DEBUGFS_READ_FILE_OPS(tx_statistics);
 DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
@@ -1552,6 +1689,10 @@
 DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
 DEBUGFS_WRITE_FILE_OPS(txfifo_flush);
 DEBUGFS_READ_FILE_OPS(ucode_bt_stats);
+DEBUGFS_WRITE_FILE_OPS(monitor_period);
+DEBUGFS_READ_FILE_OPS(bt_traffic);
+DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
+DEBUGFS_READ_FILE_OPS(reply_tx_error);
 
 /*
  * Create the debugfs files and directories
@@ -1587,7 +1728,7 @@
 	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->broken_powersave) {
+	if (!priv->cfg->base_params->broken_powersave) {
 		DEBUGFS_ADD_FILE(sleep_level_override, dir_data,
 				 S_IWUSR | S_IRUSR);
 		DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
@@ -1612,24 +1753,29 @@
 	DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
 	if (priv->cfg->ops->lib->dev_txfifo_flush)
 		DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR);
 
-	if (priv->cfg->sensitivity_calib_by_driver)
+	if (priv->cfg->base_params->sensitivity_calib_by_driver)
 		DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
-	if (priv->cfg->chain_noise_calib_by_driver)
+	if (priv->cfg->base_params->chain_noise_calib_by_driver)
 		DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
-	if (priv->cfg->ucode_tracing)
+	if (priv->cfg->base_params->ucode_tracing)
 		DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
-	if (priv->cfg->bt_statistics)
+	if (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics)
 		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);
-	if (priv->cfg->sensitivity_calib_by_driver)
+	DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR);
+	if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
+		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,
 				 &priv->disable_sens_cal);
-	if (priv->cfg->chain_noise_calib_by_driver)
+	if (priv->cfg->base_params->chain_noise_calib_by_driver)
 		DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
 				 &priv->disable_chain_noise_cal);
-	if (priv->cfg->tx_power_by_driver)
+	if (priv->cfg->base_params->tx_power_by_driver)
 		DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf,
 				&priv->disable_tx_power_cal);
 	return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 2e97cd2..70e07fa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -47,6 +47,7 @@
 #include "iwl-led.h"
 #include "iwl-power.h"
 #include "iwl-agn-rs.h"
+#include "iwl-agn-tt.h"
 
 struct iwl_tx_queue;
 
@@ -143,6 +144,7 @@
 /* One for each TFD */
 struct iwl_tx_info {
 	struct sk_buff *skb;
+	struct iwl_rxon_context *ctx;
 };
 
 /**
@@ -252,10 +254,14 @@
 	struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
 };
 
-#define IWL_TX_FIFO_BK		0
+#define IWL_TX_FIFO_BK		0	/* shared */
 #define IWL_TX_FIFO_BE		1
-#define IWL_TX_FIFO_VI		2
+#define IWL_TX_FIFO_VI		2	/* shared */
 #define IWL_TX_FIFO_VO		3
+#define IWL_TX_FIFO_BK_IPAN	IWL_TX_FIFO_BK
+#define IWL_TX_FIFO_BE_IPAN	4
+#define IWL_TX_FIFO_VI_IPAN	IWL_TX_FIFO_VI
+#define IWL_TX_FIFO_VO_IPAN	5
 #define IWL_TX_FIFO_UNUSED	-1
 
 /* Minimum number of queues. MAX_NUM is defined in hw specific files.
@@ -264,18 +270,17 @@
 #define IWL_MIN_NUM_QUEUES	10
 
 /*
- * Queue #4 is the command queue for 3945/4965/5x00/1000/6x00,
- * the driver maps it into the appropriate device FIFO for the
- * uCode.
+ * Command queue depends on iPAN support.
  */
-#define IWL_CMD_QUEUE_NUM	4
+#define IWL_DEFAULT_CMD_QUEUE_NUM	4
+#define IWL_IPAN_CMD_QUEUE_NUM		9
 
-/* Power management (not Tx power) structures */
-
-enum iwl_pwr_src {
-	IWL_PWR_SRC_VMAIN,
-	IWL_PWR_SRC_VAUX,
-};
+/*
+ * This queue number is required for proper operation
+ * because the ucode will stop/start the scheduler as
+ * required.
+ */
+#define IWL_IPAN_MCAST_QUEUE		8
 
 #define IEEE80211_DATA_LEN              2304
 #define IEEE80211_4ADDR_LEN             30
@@ -420,7 +425,7 @@
 };
 
 struct iwl_hw_key {
-	enum ieee80211_key_alg alg;
+	u32 cipher;
 	int keylen;
 	u8 keyidx;
 	u8 key[32];
@@ -434,7 +439,13 @@
 	};
 };
 
-#define CFG_HT_RX_AMPDU_FACTOR_DEF  (0x3)
+#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
@@ -443,19 +454,17 @@
  * 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 {
-	/* self configuration data */
-	bool is_ht;
-	bool is_40mhz;
 	bool single_chain_sufficient;
 	enum ieee80211_smps_mode smps; /* current smps mode */
-	/* BSS related data */
-	u8 extension_chan_offset;
-	u8 ht_protection;
-	u8 non_GF_STA_present;
 };
 
 /* QoS structures */
@@ -473,12 +482,13 @@
 struct iwl_station_entry {
 	struct iwl_addsta_cmd sta;
 	struct iwl_tid_data tid[MAX_TID_COUNT];
-	u8 used;
+	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;
 };
 
@@ -507,6 +517,7 @@
  * space for us to put data into.
  */
 struct iwl_vif_priv {
+	struct iwl_rxon_context *ctx;
 	u8 ibss_bssid_sta_id;
 };
 
@@ -564,6 +575,7 @@
 	IWL_UCODE_TLV_INIT_DATA		= 4,
 	IWL_UCODE_TLV_BOOT		= 5,
 	IWL_UCODE_TLV_PROBE_MAX_LEN	= 6, /* a u32 value */
+	IWL_UCODE_TLV_PAN		= 7,
 	IWL_UCODE_TLV_RUNT_EVTLOG_PTR	= 8,
 	IWL_UCODE_TLV_RUNT_EVTLOG_SIZE	= 9,
 	IWL_UCODE_TLV_RUNT_ERRLOG_PTR	= 10,
@@ -658,7 +670,6 @@
  * @rx_page_order: Rx buffer page order
  * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
  * @max_stations:
- * @bcast_sta_id:
  * @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
@@ -666,6 +677,7 @@
  * @ct_kill_threshold: temperature threshold
  * @beacon_time_tsf_bits: number of valid tsf bits for beacon time
  * @calib_init_cfg: setup initial calibrations for the hw
+ * @calib_rt_cfg: setup runtime calibrations for the hw
  * @struct iwl_sensitivity_ranges: range of sensitivity values
  */
 struct iwl_hw_params {
@@ -682,7 +694,6 @@
 	u32 rx_page_order;
 	u32 rx_wrt_ptr_reg;
 	u8  max_stations;
-	u8  bcast_sta_id;
 	u8  ht40_channel;
 	u8  max_beacon_itrvl;	/* in 1024 ms */
 	u32 max_inst_size;
@@ -693,6 +704,7 @@
 				    /* for 1000, 6000 series and up */
 	u16 beacon_time_tsf_bits;
 	u32 calib_init_cfg;
+	u32 calib_rt_cfg;
 	const struct iwl_sensitivity_ranges *sens;
 };
 
@@ -713,7 +725,6 @@
  *
  ****************************************************************************/
 extern void iwl_update_chain_flags(struct iwl_priv *priv);
-extern int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
 extern const u8 iwl_bcast_addr[ETH_ALEN];
 extern int iwl_rxq_stop(struct iwl_priv *priv);
 extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
@@ -824,6 +835,7 @@
 	IWL_CALIB_TX_IQ,
 	IWL_CALIB_TX_IQ_PERD,
 	IWL_CALIB_BASE_BAND,
+	IWL_CALIB_TEMP_OFFSET,
 	IWL_CALIB_MAX
 };
 
@@ -928,7 +940,7 @@
 struct isr_statistics {
 	u32 hw;
 	u32 sw;
-	u32 sw_err;
+	u32 err_code;
 	u32 sch;
 	u32 alive;
 	u32 rfkill;
@@ -940,6 +952,50 @@
 	u32 unhandled;
 };
 
+/* reply_tx_statistics (for _agn devices) */
+struct reply_tx_error_statistics {
+	u32 pp_delay;
+	u32 pp_few_bytes;
+	u32 pp_bt_prio;
+	u32 pp_quiet_period;
+	u32 pp_calc_ttak;
+	u32 int_crossed_retry;
+	u32 short_limit;
+	u32 long_limit;
+	u32 fifo_underrun;
+	u32 drain_flow;
+	u32 rfkill_flush;
+	u32 life_expire;
+	u32 dest_ps;
+	u32 host_abort;
+	u32 bt_retry;
+	u32 sta_invalid;
+	u32 frag_drop;
+	u32 tid_disable;
+	u32 fifo_flush;
+	u32 insuff_cf_poll;
+	u32 fail_hw_drop;
+	u32 sta_color_mismatch;
+	u32 unknown;
+};
+
+/* reply_agg_tx_statistics (for _agn devices) */
+struct reply_agg_tx_error_statistics {
+	u32 underrun;
+	u32 bt_prio;
+	u32 few_bytes;
+	u32 abort;
+	u32 last_sent_ttl;
+	u32 last_sent_try;
+	u32 last_sent_bt_kill;
+	u32 scd_query;
+	u32 bad_crc32;
+	u32 response;
+	u32 dump_tx;
+	u32 delay_tx;
+	u32 unknown;
+};
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 /* management statistics */
 enum iwl_mgmt_stats {
@@ -1052,7 +1108,10 @@
 #define IWL_DEF_MONITORING_PERIOD	(1000)
 #define IWL_LONG_MONITORING_PERIOD	(5000)
 #define IWL_ONE_HUNDRED_MSECS   (100)
-#define IWL_SIXTY_SECS          (60000)
+#define IWL_MAX_MONITORING_PERIOD	(60000)
+
+/* BT Antenna Coupling Threshold (dB) */
+#define IWL_BT_ANTENNA_COUPLING_THRESHOLD	(35)
 
 enum iwl_reset {
 	IWL_RF_RESET = 0,
@@ -1082,6 +1141,64 @@
  */
 #define IWLAGN_EXT_BEACON_TIME_POS	22
 
+enum iwl_rxon_context_id {
+	IWL_RXON_CTX_BSS,
+	IWL_RXON_CTX_PAN,
+
+	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;
+
+	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_rxon_cmd active;
+	struct iwl_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 */
@@ -1110,6 +1227,9 @@
 	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;
 
@@ -1155,6 +1275,15 @@
 	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[2];
 
@@ -1172,15 +1301,7 @@
 	u8 ucode_write_complete;	/* the image write is complete */
 	char firmware_name[25];
 
-
-	struct iwl_rxon_time_cmd rxon_timing;
-
-	/* 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_rxon_cmd active_rxon;
-	struct iwl_rxon_cmd staging_rxon;
+	struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
 
 	struct iwl_switch_rxon switch_rxon;
 
@@ -1242,8 +1363,6 @@
 	spinlock_t sta_lock;
 	int num_stations;
 	struct iwl_station_entry stations[IWL_STATION_COUNT];
-	struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */
-	u8 key_mapping_key;
 	unsigned long ucode_key_table;
 
 	/* queue refcounts */
@@ -1264,11 +1383,8 @@
 
 	enum nl80211_iftype iw_mode;
 
-	struct sk_buff *ibss_beacon;
-
 	/* Last Rx'd beacon timestamp */
 	u64 timestamp;
-	struct ieee80211_vif *vif;
 
 	union {
 #if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE)
@@ -1336,6 +1452,9 @@
 
 			struct iwl_notif_statistics statistics;
 			struct iwl_bt_notif_statistics statistics_bt;
+			/* counts reply_tx error */
+			struct reply_tx_error_statistics reply_tx_stats;
+			struct reply_agg_tx_error_statistics reply_agg_tx_stats;
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 			struct iwl_notif_statistics accum_statistics;
 			struct iwl_notif_statistics delta_statistics;
@@ -1348,24 +1467,45 @@
 #endif
 	};
 
+	/* bt coex */
+	u8 bt_status;
+	u8 bt_traffic_load, notif_bt_traffic_load;
+	bool bt_ch_announce;
+	bool bt_sco_active;
+	bool bt_full_concurrent;
+	bool bt_ant_couple_ok;
+	__le32 kill_ack_mask;
+	__le32 kill_cts_mask;
+	__le16 bt_valid;
+	u16 bt_on_thresh;
+	u16 bt_duration;
+	u16 dynamic_frag_thresh;
+	u16 dynamic_agg_thresh;
+	u8 bt_ci_compliance;
+	struct work_struct bt_traffic_change_work;
+
 	struct iwl_hw_params hw_params;
 
 	u32 inta_mask;
 
-	struct iwl_qos_info qos_data;
-
 	struct workqueue_struct *workqueue;
 
 	struct work_struct restart;
 	struct work_struct scan_completed;
 	struct work_struct rx_replenish;
 	struct work_struct abort_scan;
+
 	struct work_struct beacon_update;
+	struct iwl_rxon_context *beacon_ctx;
+	struct sk_buff *beacon_skb;
+
 	struct work_struct tt_work;
 	struct work_struct ct_enter;
 	struct work_struct ct_exit;
 	struct work_struct start_internal_scan;
 	struct work_struct tx_flush;
+	struct work_struct bt_full_concurrency;
+	struct work_struct bt_runtime_config;
 
 	struct tasklet_struct irq_tasklet;
 
@@ -1419,7 +1559,6 @@
 }
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-const char *iwl_get_tx_fail_reason(u32 status);
 /*
  * iwl_get_debug_level: Return active debug level for device
  *
@@ -1435,8 +1574,6 @@
 		return iwl_debug_level;
 }
 #else
-static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; }
-
 static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
 {
 	return iwl_debug_level;
@@ -1453,10 +1590,34 @@
 	return NULL;
 }
 
-
-static inline int iwl_is_associated(struct iwl_priv *priv)
+static inline struct iwl_rxon_context *
+iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
 {
-	return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+	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_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_is_any_associated(struct iwl_priv *priv)
+{
+	return iwl_is_associated(priv, IWL_RXON_CTX_BSS);
+}
+
+static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx)
+{
+	return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
 }
 
 static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index a45d02e..87cd10f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -136,85 +136,13 @@
 	36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
 };
 
-/**
- * struct iwl_txpwr_section: eeprom section information
- * @offset: indirect address into eeprom image
- * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
- * @band: band type for the section
- * @is_common - true: common section, false: channel section
- * @is_cck - true: cck section, false: not cck section
- * @is_ht_40 - true: all channel in the section are HT40 channel,
- * 	       false: legacy or HT 20 MHz
- *	       ignore if it is common section
- * @iwl_eeprom_section_channel: channel array in the section,
- *	       ignore if common section
- */
-struct iwl_txpwr_section {
-	u32 offset;
-	u8 count;
-	enum ieee80211_band band;
-	bool is_common;
-	bool is_cck;
-	bool is_ht40;
-	u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
-};
-
-/**
- * section 1 - 3 are regulatory tx power apply to all channels based on
- *    modulation: CCK, OFDM
- *    Band: 2.4GHz, 5.2GHz
- * section 4 - 10 are regulatory tx power apply to specified channels
- *    For example:
- *	1L - Channel 1 Legacy
- *	1HT - Channel 1 HT
- *	(1,+1) - Channel 1 HT40 "_above_"
- *
- * Section 1: all CCK channels
- * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
- * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
- * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
- * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
- * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
- * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
- * Section 8: 2.4 GHz channel: 13L, 13HT
- * Section 9: 2.4 GHz channel: 140L, 140HT
- * Section 10: 2.4 GHz 40MHz channels: (132,+1)  (44,+1)
- *
- */
-static const struct iwl_txpwr_section enhinfo[] = {
-	{ EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
-	{ EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
-	{ EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
-	{ EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
-		false, false, false,
-		{1, 1, 2, 2, 10, 10, 11, 11 } },
-	{ EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
-		false, false, true,
-		{ 1, 2, 6, 7, 9 } },
-	{ EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
-		false, false, false,
-		{ 36, 64, 100, 36, 64, 100 } },
-	{ EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
-		false, false, true,
-		{ 36, 60, 100 } },
-	{ EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
-		false, false, false,
-		{ 13, 13 } },
-	{ EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
-		false, false, false,
-		{ 140, 140 } },
-	{ EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
-		false, false, true,
-		{ 132, 44 } },
-};
-
 /******************************************************************************
  *
  * EEPROM related functions
  *
 ******************************************************************************/
 
-int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
+static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
 {
 	u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
 	int ret = 0;
@@ -246,7 +174,6 @@
 	}
 	return ret;
 }
-EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
 
 static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
 {
@@ -290,49 +217,9 @@
 	return  nvm_type;
 }
 
-/*
- * 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 iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
-{
-	u16 count;
-	int ret;
-
-	for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
-		/* Request semaphore */
-		iwl_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;
-}
-EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore);
-
-void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv)
-{
-	iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-		CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-
-}
-EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore);
-
 const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
 {
-	BUG_ON(offset >= priv->cfg->eeprom_size);
+	BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
 	return &priv->eeprom[offset];
 }
 EXPORT_SYMBOL(iwlcore_eeprom_query_addr);
@@ -364,7 +251,7 @@
 		 * CSR auto clock gate disable bit -
 		 * this is only applicable for HW with OTP shadow RAM
 		 */
-		if (priv->cfg->shadow_ram_support)
+		if (priv->cfg->base_params->shadow_ram_support)
 			iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG,
 				CSR_RESET_LINK_PWR_MGMT_DISABLED);
 	}
@@ -484,13 +371,27 @@
 		}
 		/* more in the link list, continue */
 		usedblocks++;
-	} while (usedblocks <= priv->cfg->max_ll_items);
+	} while (usedblocks <= priv->cfg->base_params->max_ll_items);
 
 	/* OTP has no valid blocks */
 	IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n");
 	return -EINVAL;
 }
 
+const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
+{
+	return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
+}
+EXPORT_SYMBOL(iwl_eeprom_query_addr);
+
+u16 iwl_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_eeprom_query16);
+
 /**
  * iwl_eeprom_init - read EEPROM contents
  *
@@ -512,8 +413,8 @@
 	if (priv->nvm_device_type == -ENOENT)
 		return -ENOENT;
 	/* allocate eeprom */
-	IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size);
-	sz = priv->cfg->eeprom_size;
+	sz = priv->cfg->base_params->eeprom_size;
+	IWL_DEBUG_INFO(priv, "NVM size = %d\n", sz);
 	priv->eeprom = kzalloc(sz, GFP_KERNEL);
 	if (!priv->eeprom) {
 		ret = -ENOMEM;
@@ -523,7 +424,7 @@
 
 	priv->cfg->ops->lib->apm_ops.init(priv);
 
-	ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv);
+	ret = iwl_eeprom_verify_signature(priv);
 	if (ret < 0) {
 		IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
 		ret = -ENOENT;
@@ -554,7 +455,7 @@
 			     CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
 			     CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
 		/* traversing the linked list if no shadow ram supported */
-		if (!priv->cfg->shadow_ram_support) {
+		if (!priv->cfg->base_params->shadow_ram_support) {
 			if (iwl_find_otp_image(priv, &validblockaddr)) {
 				ret = -ENOENT;
 				goto done;
@@ -604,7 +505,7 @@
 	if (ret)
 		iwl_eeprom_free(priv);
 	/* Reset chip to save power until we load uCode during "up". */
-	priv->cfg->ops->lib->apm_ops.stop(priv);
+	iwl_apm_stop(priv);
 alloc_err:
 	return ret;
 }
@@ -617,53 +518,6 @@
 }
 EXPORT_SYMBOL(iwl_eeprom_free);
 
-int iwl_eeprom_check_version(struct iwl_priv *priv)
-{
-	u16 eeprom_ver;
-	u16 calib_ver;
-
-	eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
-	calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv);
-
-	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;
-
-}
-EXPORT_SYMBOL(iwl_eeprom_check_version);
-
-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)
-{
-	if (!priv->eeprom)
-		return 0;
-	return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
-}
-EXPORT_SYMBOL(iwl_eeprom_query16);
-
-void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
-{
-	const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
-					EEPROM_MAC_ADDRESS);
-	memcpy(mac, addr, ETH_ALEN);
-}
-EXPORT_SYMBOL(iwl_eeprom_get_mac);
-
 static void iwl_init_band_reference(const struct iwl_priv *priv,
 			int eep_band, int *eeprom_ch_count,
 			const struct iwl_eeprom_channel **eeprom_ch_info,
@@ -722,7 +576,6 @@
 
 #define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
 			    ? # x " " : "")
-
 /**
  * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv.
  *
@@ -766,205 +619,6 @@
 	return 0;
 }
 
-/**
- * iwl_get_max_txpower_avg - get the highest tx power from all chains.
- *     find the highest tx power from all chains for the channel
- */
-static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
-		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
-		int element, s8 *max_txpower_in_half_dbm)
-{
-	s8 max_txpower_avg = 0; /* (dBm) */
-
-	IWL_DEBUG_INFO(priv, "%d - "
-			"chain_a: %d dB chain_b: %d dB "
-			"chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
-			element,
-			enhanced_txpower[element].chain_a_max >> 1,
-			enhanced_txpower[element].chain_b_max >> 1,
-			enhanced_txpower[element].chain_c_max >> 1,
-			enhanced_txpower[element].mimo2_max >> 1,
-			enhanced_txpower[element].mimo3_max >> 1);
-	/* Take the highest tx power from any valid chains */
-	if ((priv->cfg->valid_tx_ant & ANT_A) &&
-	    (enhanced_txpower[element].chain_a_max > max_txpower_avg))
-		max_txpower_avg = enhanced_txpower[element].chain_a_max;
-	if ((priv->cfg->valid_tx_ant & ANT_B) &&
-	    (enhanced_txpower[element].chain_b_max > max_txpower_avg))
-		max_txpower_avg = enhanced_txpower[element].chain_b_max;
-	if ((priv->cfg->valid_tx_ant & ANT_C) &&
-	    (enhanced_txpower[element].chain_c_max > max_txpower_avg))
-		max_txpower_avg = enhanced_txpower[element].chain_c_max;
-	if (((priv->cfg->valid_tx_ant == ANT_AB) |
-	    (priv->cfg->valid_tx_ant == ANT_BC) |
-	    (priv->cfg->valid_tx_ant == ANT_AC)) &&
-	    (enhanced_txpower[element].mimo2_max > max_txpower_avg))
-		max_txpower_avg =  enhanced_txpower[element].mimo2_max;
-	if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
-	    (enhanced_txpower[element].mimo3_max > max_txpower_avg))
-		max_txpower_avg = enhanced_txpower[element].mimo3_max;
-
-	/*
-	 * max. tx power in EEPROM is in 1/2 dBm format
-	 * convert from 1/2 dBm to dBm (round-up convert)
-	 * but we also do not want to loss 1/2 dBm resolution which
-	 * will impact performance
-	 */
-	*max_txpower_in_half_dbm = max_txpower_avg;
-	return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
-}
-
-/**
- * iwl_update_common_txpower: update channel tx power
- *     update tx power per band based on EEPROM enhanced tx power info.
- */
-static s8 iwl_update_common_txpower(struct iwl_priv *priv,
-		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
-		int section, int element, s8 *max_txpower_in_half_dbm)
-{
-	struct iwl_channel_info *ch_info;
-	int ch;
-	bool is_ht40 = false;
-	s8 max_txpower_avg; /* (dBm) */
-
-	/* it is common section, contain all type (Legacy, HT and HT40)
-	 * based on the element in the section to determine
-	 * is it HT 40 or not
-	 */
-	if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
-		is_ht40 = true;
-	max_txpower_avg =
-		iwl_get_max_txpower_avg(priv, enhanced_txpower,
-					element, max_txpower_in_half_dbm);
-
-	ch_info = priv->channel_info;
-
-	for (ch = 0; ch < priv->channel_count; ch++) {
-		/* find matching band and update tx power if needed */
-		if ((ch_info->band == enhinfo[section].band) &&
-		    (ch_info->max_power_avg < max_txpower_avg) &&
-		    (!is_ht40)) {
-			/* Update regulatory-based run-time data */
-			ch_info->max_power_avg = ch_info->curr_txpow =
-				max_txpower_avg;
-			ch_info->scan_power = max_txpower_avg;
-		}
-		if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
-		    (ch_info->ht40_max_power_avg < max_txpower_avg)) {
-			/* Update regulatory-based run-time data */
-			ch_info->ht40_max_power_avg = max_txpower_avg;
-		}
-		ch_info++;
-	}
-	return max_txpower_avg;
-}
-
-/**
- * iwl_update_channel_txpower: update channel tx power
- *      update channel tx power based on EEPROM enhanced tx power info.
- */
-static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
-		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
-		int section, int element, s8 *max_txpower_in_half_dbm)
-{
-	struct iwl_channel_info *ch_info;
-	int ch;
-	u8 channel;
-	s8 max_txpower_avg; /* (dBm) */
-
-	channel = enhinfo[section].iwl_eeprom_section_channel[element];
-	max_txpower_avg =
-		iwl_get_max_txpower_avg(priv, enhanced_txpower,
-					element, max_txpower_in_half_dbm);
-
-	ch_info = priv->channel_info;
-	for (ch = 0; ch < priv->channel_count; ch++) {
-		/* find matching channel and update tx power if needed */
-		if (ch_info->channel == channel) {
-			if ((ch_info->max_power_avg < max_txpower_avg) &&
-			    (!enhinfo[section].is_ht40)) {
-				/* Update regulatory-based run-time data */
-				ch_info->max_power_avg = max_txpower_avg;
-				ch_info->curr_txpow = max_txpower_avg;
-				ch_info->scan_power = max_txpower_avg;
-			}
-			if ((enhinfo[section].is_ht40) &&
-			    (ch_info->ht40_max_power_avg < max_txpower_avg)) {
-				/* Update regulatory-based run-time data */
-				ch_info->ht40_max_power_avg = max_txpower_avg;
-			}
-			break;
-		}
-		ch_info++;
-	}
-	return max_txpower_avg;
-}
-
-/**
- * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
- */
-void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
-{
-	int eeprom_section_count = 0;
-	int section, element;
-	struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
-	u32 offset;
-	s8 max_txpower_avg; /* (dBm) */
-	s8 max_txpower_in_half_dbm; /* (half-dBm) */
-
-	/* Loop through all the sections
-	 * adjust bands and channel's max tx power
-	 * Set the tx_power_user_lmt to the highest power
-	 * supported by any channels and chains
-	 */
-	for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
-		eeprom_section_count = enhinfo[section].count;
-		offset = enhinfo[section].offset;
-		enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
-				iwl_eeprom_query_addr(priv, offset);
-
-		/*
-		 * check for valid entry -
-		 * different version of EEPROM might contain different set
-		 * of enhanced tx power table
-		 * always check for valid entry before process
-		 * the information
-		 */
-		if (!enhanced_txpower->common || enhanced_txpower->reserved)
-			continue;
-
-		for (element = 0; element < eeprom_section_count; element++) {
-			if (enhinfo[section].is_common)
-				max_txpower_avg =
-					iwl_update_common_txpower(priv,
-						enhanced_txpower, section,
-						element,
-						&max_txpower_in_half_dbm);
-			else
-				max_txpower_avg =
-					iwl_update_channel_txpower(priv,
-						enhanced_txpower, section,
-						element,
-						&max_txpower_in_half_dbm);
-
-			/* Update the tx_power_user_lmt to the highest power
-			 * supported by any channel */
-			if (max_txpower_avg > priv->tx_power_user_lmt)
-				priv->tx_power_user_lmt = max_txpower_avg;
-
-			/*
-			 * Update the tx_power_lmt_in_half_dbm to
-			 * the highest power supported by any channel
-			 */
-			if (max_txpower_in_half_dbm >
-			    priv->tx_power_lmt_in_half_dbm)
-				priv->tx_power_lmt_in_half_dbm =
-					max_txpower_in_half_dbm;
-		}
-	}
-}
-EXPORT_SYMBOL(iwlcore_eeprom_enhanced_txpower);
-
 #define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
 			    ? # x " " : "")
 
@@ -1162,4 +816,3 @@
 	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 a4772af..d9b5906 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -493,7 +493,6 @@
 
 struct iwl_eeprom_ops {
 	const u32 regulatory_bands[7];
-	int (*verify_signature) (struct iwl_priv *priv);
 	int (*acquire_semaphore) (struct iwl_priv *priv);
 	void (*release_semaphore) (struct iwl_priv *priv);
 	u16 (*calib_version) (struct iwl_priv *priv);
@@ -502,18 +501,13 @@
 };
 
 
-void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
 int iwl_eeprom_init(struct iwl_priv *priv);
 void iwl_eeprom_free(struct iwl_priv *priv);
 int  iwl_eeprom_check_version(struct iwl_priv *priv);
 const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
-u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
-
 int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
-int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
-void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
+u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
 const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
-void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv);
 int iwl_init_channel_map(struct iwl_priv *priv);
 void iwl_free_channel_map(struct iwl_priv *priv);
 const struct iwl_channel_info *iwl_get_channel_info(
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 258d059..c373b53 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -97,6 +97,17 @@
 		IWL_CMD(REPLY_TX_POWER_DBM_CMD);
 		IWL_CMD(TEMPERATURE_NOTIFICATION);
 		IWL_CMD(TX_ANT_CONFIGURATION_CMD);
+		IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
+		IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
+		IWL_CMD(REPLY_BT_COEX_PROT_ENV);
+		IWL_CMD(REPLY_WIPAN_PARAMS);
+		IWL_CMD(REPLY_WIPAN_RXON);
+		IWL_CMD(REPLY_WIPAN_RXON_TIMING);
+		IWL_CMD(REPLY_WIPAN_RXON_ASSOC);
+		IWL_CMD(REPLY_WIPAN_QOS_PARAM);
+		IWL_CMD(REPLY_WIPAN_WEPKEY);
+		IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
+		IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
 	default:
 		return "UNKNOWN";
 
@@ -229,7 +240,7 @@
 		 * in later, it will possibly set an invalid
 		 * address (cmd->meta.source).
 		 */
-		priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_idx].flags &=
+		priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
 							~CMD_WANT_SKB;
 	}
 fail:
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 621abe3..1aaef70 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -44,11 +44,6 @@
 	return &hw->conf;
 }
 
-static inline int iwl_check_bits(unsigned long field, unsigned long mask)
-{
-	return ((field & mask) == mask) ? 1 : 0;
-}
-
 static inline unsigned long elapsed_jiffies(unsigned long start,
 					    unsigned long end)
 {
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index db5bfcb..86c2b6f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -108,13 +108,13 @@
 	BUG_ON(idx > IWL_MAX_BLINK_TBL);
 
 	IWL_DEBUG_LED(priv, "Led blink time compensation= %u\n",
-			priv->cfg->led_compensation);
+			priv->cfg->base_params->led_compensation);
 	led_cmd.on =
 		iwl_blink_compensation(priv, blink_tbl[idx].on_time,
-					priv->cfg->led_compensation);
+				priv->cfg->base_params->led_compensation);
 	led_cmd.off =
 		iwl_blink_compensation(priv, blink_tbl[idx].off_time,
-					priv->cfg->led_compensation);
+				priv->cfg->base_params->led_compensation);
 
 	return priv->cfg->ops->led->cmd(priv, &led_cmd);
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index cda6a94..49d7788 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -192,47 +192,6 @@
 	IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
 }
 
-/* default Thermal Throttling transaction table
- * Current state   |         Throttling Down               |  Throttling Up
- *=============================================================================
- *                 Condition Nxt State  Condition Nxt State Condition Nxt State
- *-----------------------------------------------------------------------------
- *     IWL_TI_0     T >= 114   CT_KILL  114>T>=105   TI_1      N/A      N/A
- *     IWL_TI_1     T >= 114   CT_KILL  114>T>=110   TI_2     T<=95     TI_0
- *     IWL_TI_2     T >= 114   CT_KILL                        T<=100    TI_1
- *    IWL_CT_KILL      N/A       N/A       N/A        N/A     T<=95     TI_0
- *=============================================================================
- */
-static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
-	{IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
-	{IWL_TI_1, 105, CT_KILL_THRESHOLD - 1},
-	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
-};
-static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
-	{IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
-	{IWL_TI_2, 110, CT_KILL_THRESHOLD - 1},
-	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
-};
-static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
-	{IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
-	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX},
-	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
-};
-static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
-	{IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
-	{IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
-	{IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
-};
-
-/* Advance Thermal Throttling default restriction table */
-static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
-	{IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true },
-	{IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true },
-	{IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false },
-	{IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
-};
-
-
 static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
 				    struct iwl_powertable_cmd *cmd)
 {
@@ -308,7 +267,6 @@
 int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 {
 	int ret = 0;
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
 	bool update_chains;
 	struct iwl_powertable_cmd cmd;
@@ -320,14 +278,18 @@
 
 	dtimper = priv->hw->conf.ps_dtim_period ?: 1;
 
-	if (priv->cfg->broken_powersave)
+	if (priv->cfg->base_params->broken_powersave)
 		iwl_power_sleep_cam_cmd(priv, &cmd);
-	else if (priv->cfg->supports_idle &&
+	else if (priv->cfg->base_params->supports_idle &&
 		 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
 		iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20);
-	else if (tt->state >= IWL_TI_1)
-		iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper);
-	else if (!enabled)
+	else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
+		 priv->cfg->ops->lib->tt_ops.tt_power_mode &&
+		 priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) {
+		/* in thermal throttling low power state */
+		iwl_static_sleep_cmd(priv, &cmd,
+		    priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper);
+	} else if (!enabled)
 		iwl_power_sleep_cam_cmd(priv, &cmd);
 	else if (priv->power_data.debug_sleep_level_override >= 0)
 		iwl_static_sleep_cmd(priv, &cmd,
@@ -367,592 +329,6 @@
 }
 EXPORT_SYMBOL(iwl_power_update_mode);
 
-bool iwl_ht_enabled(struct iwl_priv *priv)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	struct iwl_tt_restriction *restriction;
-
-	if (!priv->thermal_throttle.advanced_tt)
-		return true;
-	restriction = tt->restriction + tt->state;
-	return restriction->is_ht;
-}
-EXPORT_SYMBOL(iwl_ht_enabled);
-
-bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
-{
-	s32 temp = priv->temperature; /* degrees CELSIUS except specified */
-	bool within_margin = false;
-
-	if (priv->cfg->temperature_kelvin)
-		temp = KELVIN_TO_CELSIUS(priv->temperature);
-
-	if (!priv->thermal_throttle.advanced_tt)
-		within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
-				CT_KILL_THRESHOLD_LEGACY) ? true : false;
-	else
-		within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
-				CT_KILL_THRESHOLD) ? true : false;
-	return within_margin;
-}
-
-enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	struct iwl_tt_restriction *restriction;
-
-	if (!priv->thermal_throttle.advanced_tt)
-		return IWL_ANT_OK_MULTI;
-	restriction = tt->restriction + tt->state;
-	return restriction->tx_stream;
-}
-EXPORT_SYMBOL(iwl_tx_ant_restriction);
-
-enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	struct iwl_tt_restriction *restriction;
-
-	if (!priv->thermal_throttle.advanced_tt)
-		return IWL_ANT_OK_MULTI;
-	restriction = tt->restriction + tt->state;
-	return restriction->rx_stream;
-}
-
-#define CT_KILL_EXIT_DURATION (5)	/* 5 seconds duration */
-#define CT_KILL_WAITING_DURATION (300)	/* 300ms duration */
-
-/*
- * toggle the bit to wake up uCode and check the temperature
- * if the temperature is below CT, uCode will stay awake and send card
- * state notification with CT_KILL bit clear to inform Thermal Throttling
- * Management to change state. Otherwise, uCode will go back to sleep
- * without doing anything, driver should continue the 5 seconds timer
- * to wake up uCode for temperature check until temperature drop below CT
- */
-static void iwl_tt_check_exit_ct_kill(unsigned long data)
-{
-	struct iwl_priv *priv = (struct iwl_priv *)data;
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	unsigned long flags;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (tt->state == IWL_TI_CT_KILL) {
-		if (priv->thermal_throttle.ct_kill_toggle) {
-			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-			priv->thermal_throttle.ct_kill_toggle = false;
-		} else {
-			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-			priv->thermal_throttle.ct_kill_toggle = true;
-		}
-		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);
-
-		/* Reschedule the ct_kill timer to occur in
-		 * CT_KILL_EXIT_DURATION seconds to ensure we get a
-		 * thermal update */
-		IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
-		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
-			  CT_KILL_EXIT_DURATION * HZ);
-	}
-}
-
-static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
-			   bool stop)
-{
-	if (stop) {
-		IWL_DEBUG_POWER(priv, "Stop all queues\n");
-		if (priv->mac80211_registered)
-			ieee80211_stop_queues(priv->hw);
-		IWL_DEBUG_POWER(priv,
-				"Schedule 5 seconds CT_KILL Timer\n");
-		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
-			  CT_KILL_EXIT_DURATION * HZ);
-	} else {
-		IWL_DEBUG_POWER(priv, "Wake all queues\n");
-		if (priv->mac80211_registered)
-			ieee80211_wake_queues(priv->hw);
-	}
-}
-
-static void iwl_tt_ready_for_ct_kill(unsigned long data)
-{
-	struct iwl_priv *priv = (struct iwl_priv *)data;
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	/* temperature timer expired, ready to go into CT_KILL state */
-	if (tt->state != IWL_TI_CT_KILL) {
-		IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n");
-		tt->state = IWL_TI_CT_KILL;
-		set_bit(STATUS_CT_KILL, &priv->status);
-		iwl_perform_ct_kill_task(priv, true);
-	}
-}
-
-static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
-{
-	IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
-	/* make request to retrieve statistics information */
-	iwl_send_statistics_request(priv, CMD_SYNC, false);
-	/* Reschedule the ct_kill wait timer */
-	mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
-		 jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
-}
-
-#define IWL_MINIMAL_POWER_THRESHOLD		(CT_KILL_THRESHOLD_LEGACY)
-#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2	(100)
-#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1	(90)
-
-/*
- * Legacy thermal throttling
- * 1) Avoid NIC destruction due to high temperatures
- *	Chip will identify dangerously high temperatures that can
- *	harm the device and will power down
- * 2) Avoid the NIC power down due to high temperature
- *	Throttle early enough to lower the power consumption before
- *	drastic steps are needed
- */
-static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	enum iwl_tt_state old_state;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if ((tt->tt_previous_temp) &&
-	    (temp > tt->tt_previous_temp) &&
-	    ((temp - tt->tt_previous_temp) >
-	    IWL_TT_INCREASE_MARGIN)) {
-		IWL_DEBUG_POWER(priv,
-			"Temperature increase %d degree Celsius\n",
-			(temp - tt->tt_previous_temp));
-	}
-#endif
-	old_state = tt->state;
-	/* in Celsius */
-	if (temp >= IWL_MINIMAL_POWER_THRESHOLD)
-		tt->state = IWL_TI_CT_KILL;
-	else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)
-		tt->state = IWL_TI_2;
-	else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)
-		tt->state = IWL_TI_1;
-	else
-		tt->state = IWL_TI_0;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	tt->tt_previous_temp = temp;
-#endif
-	/* stop ct_kill_waiting_tm timer */
-	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
-	if (tt->state != old_state) {
-		switch (tt->state) {
-		case IWL_TI_0:
-			/*
-			 * When the system is ready to go back to IWL_TI_0
-			 * we only have to call iwl_power_update_mode() to
-			 * do so.
-			 */
-			break;
-		case IWL_TI_1:
-			tt->tt_power_mode = IWL_POWER_INDEX_3;
-			break;
-		case IWL_TI_2:
-			tt->tt_power_mode = IWL_POWER_INDEX_4;
-			break;
-		default:
-			tt->tt_power_mode = IWL_POWER_INDEX_5;
-			break;
-		}
-		mutex_lock(&priv->mutex);
-		if (old_state == IWL_TI_CT_KILL)
-			clear_bit(STATUS_CT_KILL, &priv->status);
-		if (tt->state != IWL_TI_CT_KILL &&
-		    iwl_power_update_mode(priv, true)) {
-			/* TT state not updated
-			 * try again during next temperature read
-			 */
-			if (old_state == IWL_TI_CT_KILL)
-				set_bit(STATUS_CT_KILL, &priv->status);
-			tt->state = old_state;
-			IWL_ERR(priv, "Cannot update power mode, "
-					"TT state not updated\n");
-		} else {
-			if (tt->state == IWL_TI_CT_KILL) {
-				if (force) {
-					set_bit(STATUS_CT_KILL, &priv->status);
-					iwl_perform_ct_kill_task(priv, true);
-				} else {
-					iwl_prepare_ct_kill_task(priv);
-					tt->state = old_state;
-				}
-			} else if (old_state == IWL_TI_CT_KILL &&
-				 tt->state != IWL_TI_CT_KILL)
-				iwl_perform_ct_kill_task(priv, false);
-			IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
-					tt->state);
-			IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
-					tt->tt_power_mode);
-		}
-		mutex_unlock(&priv->mutex);
-	}
-}
-
-/*
- * Advance thermal throttling
- * 1) Avoid NIC destruction due to high temperatures
- *	Chip will identify dangerously high temperatures that can
- *	harm the device and will power down
- * 2) Avoid the NIC power down due to high temperature
- *	Throttle early enough to lower the power consumption before
- *	drastic steps are needed
- *	Actions include relaxing the power down sleep thresholds and
- *	decreasing the number of TX streams
- * 3) Avoid throughput performance impact as much as possible
- *
- *=============================================================================
- *                 Condition Nxt State  Condition Nxt State Condition Nxt State
- *-----------------------------------------------------------------------------
- *     IWL_TI_0     T >= 114   CT_KILL  114>T>=105   TI_1      N/A      N/A
- *     IWL_TI_1     T >= 114   CT_KILL  114>T>=110   TI_2     T<=95     TI_0
- *     IWL_TI_2     T >= 114   CT_KILL                        T<=100    TI_1
- *    IWL_CT_KILL      N/A       N/A       N/A        N/A     T<=95     TI_0
- *=============================================================================
- */
-static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	int i;
-	bool changed = false;
-	enum iwl_tt_state old_state;
-	struct iwl_tt_trans *transaction;
-
-	old_state = tt->state;
-	for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) {
-		/* based on the current TT state,
-		 * find the curresponding transaction table
-		 * each table has (IWL_TI_STATE_MAX - 1) entries
-		 * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1))
-		 * will advance to the correct table.
-		 * then based on the current temperature
-		 * find the next state need to transaction to
-		 * go through all the possible (IWL_TI_STATE_MAX - 1) entries
-		 * in the current table to see if transaction is needed
-		 */
-		transaction = tt->transaction +
-			((old_state * (IWL_TI_STATE_MAX - 1)) + i);
-		if (temp >= transaction->tt_low &&
-		    temp <= transaction->tt_high) {
-#ifdef CONFIG_IWLWIFI_DEBUG
-			if ((tt->tt_previous_temp) &&
-			    (temp > tt->tt_previous_temp) &&
-			    ((temp - tt->tt_previous_temp) >
-			    IWL_TT_INCREASE_MARGIN)) {
-				IWL_DEBUG_POWER(priv,
-					"Temperature increase %d "
-					"degree Celsius\n",
-					(temp - tt->tt_previous_temp));
-			}
-			tt->tt_previous_temp = temp;
-#endif
-			if (old_state !=
-			    transaction->next_state) {
-				changed = true;
-				tt->state =
-					transaction->next_state;
-			}
-			break;
-		}
-	}
-	/* stop ct_kill_waiting_tm timer */
-	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
-	if (changed) {
-		struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
-
-		if (tt->state >= IWL_TI_1) {
-			/* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
-			tt->tt_power_mode = IWL_POWER_INDEX_5;
-			if (!iwl_ht_enabled(priv))
-				/* disable HT */
-				rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
-					RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
-					RXON_FLG_HT40_PROT_MSK |
-					RXON_FLG_HT_PROT_MSK);
-			else {
-				/* check HT capability and set
-				 * according to the system HT capability
-				 * in case get disabled before */
-				iwl_set_rxon_ht(priv, &priv->current_ht_config);
-			}
-
-		} else {
-			/*
-			 * restore system power setting -- it will be
-			 * recalculated automatically.
-			 */
-
-			/* check HT capability and set
-			 * according to the system HT capability
-			 * in case get disabled before */
-			iwl_set_rxon_ht(priv, &priv->current_ht_config);
-		}
-		mutex_lock(&priv->mutex);
-		if (old_state == IWL_TI_CT_KILL)
-			clear_bit(STATUS_CT_KILL, &priv->status);
-		if (tt->state != IWL_TI_CT_KILL &&
-		    iwl_power_update_mode(priv, true)) {
-			/* TT state not updated
-			 * try again during next temperature read
-			 */
-			IWL_ERR(priv, "Cannot update power mode, "
-					"TT state not updated\n");
-			if (old_state == IWL_TI_CT_KILL)
-				set_bit(STATUS_CT_KILL, &priv->status);
-			tt->state = old_state;
-		} else {
-			IWL_DEBUG_POWER(priv,
-					"Thermal Throttling to new state: %u\n",
-					tt->state);
-			if (old_state != IWL_TI_CT_KILL &&
-			    tt->state == IWL_TI_CT_KILL) {
-				if (force) {
-					IWL_DEBUG_POWER(priv,
-						"Enter IWL_TI_CT_KILL\n");
-					set_bit(STATUS_CT_KILL, &priv->status);
-					iwl_perform_ct_kill_task(priv, true);
-				} else {
-					iwl_prepare_ct_kill_task(priv);
-					tt->state = old_state;
-				}
-			} else if (old_state == IWL_TI_CT_KILL &&
-				  tt->state != IWL_TI_CT_KILL) {
-				IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
-				iwl_perform_ct_kill_task(priv, false);
-			}
-		}
-		mutex_unlock(&priv->mutex);
-	}
-}
-
-/* Card State Notification indicated reach critical temperature
- * if PSP not enable, no Thermal Throttling function will be performed
- * just set the GP1 bit to acknowledge the event
- * otherwise, go into IWL_TI_CT_KILL state
- * since Card State Notification will not provide any temperature reading
- * for Legacy mode
- * so just pass the CT_KILL temperature to iwl_legacy_tt_handler()
- * for advance mode
- * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
- */
-static void iwl_bg_ct_enter(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (!iwl_is_ready(priv))
-		return;
-
-	if (tt->state != IWL_TI_CT_KILL) {
-		IWL_ERR(priv, "Device reached critical temperature "
-			      "- ucode going to sleep!\n");
-		if (!priv->thermal_throttle.advanced_tt)
-			iwl_legacy_tt_handler(priv,
-					      IWL_MINIMAL_POWER_THRESHOLD,
-					      true);
-		else
-			iwl_advance_tt_handler(priv,
-					       CT_KILL_THRESHOLD + 1, true);
-	}
-}
-
-/* Card State Notification indicated out of critical temperature
- * since Card State Notification will not provide any temperature reading
- * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature
- * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state
- */
-static void iwl_bg_ct_exit(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (!iwl_is_ready(priv))
-		return;
-
-	/* stop ct_kill_exit_tm timer */
-	del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
-
-	if (tt->state == IWL_TI_CT_KILL) {
-		IWL_ERR(priv,
-			"Device temperature below critical"
-			"- ucode awake!\n");
-		/*
-		 * exit from CT_KILL state
-		 * reset the current temperature reading
-		 */
-		priv->temperature = 0;
-		if (!priv->thermal_throttle.advanced_tt)
-			iwl_legacy_tt_handler(priv,
-					      IWL_REDUCED_PERFORMANCE_THRESHOLD_2,
-					      true);
-		else
-			iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,
-					       true);
-	}
-}
-
-void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
-	queue_work(priv->workqueue, &priv->ct_enter);
-}
-EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
-
-void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
-	queue_work(priv->workqueue, &priv->ct_exit);
-}
-EXPORT_SYMBOL(iwl_tt_exit_ct_kill);
-
-static void iwl_bg_tt_work(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
-	s32 temp = priv->temperature; /* degrees CELSIUS except specified */
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (priv->cfg->temperature_kelvin)
-		temp = KELVIN_TO_CELSIUS(priv->temperature);
-
-	if (!priv->thermal_throttle.advanced_tt)
-		iwl_legacy_tt_handler(priv, temp, false);
-	else
-		iwl_advance_tt_handler(priv, temp, false);
-}
-
-void iwl_tt_handler(struct iwl_priv *priv)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
-	queue_work(priv->workqueue, &priv->tt_work);
-}
-EXPORT_SYMBOL(iwl_tt_handler);
-
-/* Thermal throttling initialization
- * For advance thermal throttling:
- *     Initialize Thermal Index and temperature threshold table
- *     Initialize thermal throttling restriction table
- */
-void iwl_tt_initialize(struct iwl_priv *priv)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
-	struct iwl_tt_trans *transaction;
-
-	IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n");
-
-	memset(tt, 0, sizeof(struct iwl_tt_mgmt));
-
-	tt->state = IWL_TI_0;
-	init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
-	priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
-	priv->thermal_throttle.ct_kill_exit_tm.function =
-		iwl_tt_check_exit_ct_kill;
-	init_timer(&priv->thermal_throttle.ct_kill_waiting_tm);
-	priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv;
-	priv->thermal_throttle.ct_kill_waiting_tm.function =
-		iwl_tt_ready_for_ct_kill;
-	/* setup deferred ct kill work */
-	INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
-	INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
-	INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
-
-	if (priv->cfg->adv_thermal_throttle) {
-		IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
-		tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
-					 IWL_TI_STATE_MAX, GFP_KERNEL);
-		tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
-			IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1),
-			GFP_KERNEL);
-		if (!tt->restriction || !tt->transaction) {
-			IWL_ERR(priv, "Fallback to Legacy Throttling\n");
-			priv->thermal_throttle.advanced_tt = false;
-			kfree(tt->restriction);
-			tt->restriction = NULL;
-			kfree(tt->transaction);
-			tt->transaction = NULL;
-		} else {
-			transaction = tt->transaction +
-				(IWL_TI_0 * (IWL_TI_STATE_MAX - 1));
-			memcpy(transaction, &tt_range_0[0], size);
-			transaction = tt->transaction +
-				(IWL_TI_1 * (IWL_TI_STATE_MAX - 1));
-			memcpy(transaction, &tt_range_1[0], size);
-			transaction = tt->transaction +
-				(IWL_TI_2 * (IWL_TI_STATE_MAX - 1));
-			memcpy(transaction, &tt_range_2[0], size);
-			transaction = tt->transaction +
-				(IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1));
-			memcpy(transaction, &tt_range_3[0], size);
-			size = sizeof(struct iwl_tt_restriction) *
-				IWL_TI_STATE_MAX;
-			memcpy(tt->restriction,
-				&restriction_range[0], size);
-			priv->thermal_throttle.advanced_tt = true;
-		}
-	} else {
-		IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
-		priv->thermal_throttle.advanced_tt = false;
-	}
-}
-EXPORT_SYMBOL(iwl_tt_initialize);
-
-/* cleanup thermal throttling management related memory and timer */
-void iwl_tt_exit(struct iwl_priv *priv)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
-	/* stop ct_kill_exit_tm timer if activated */
-	del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
-	/* stop ct_kill_waiting_tm timer if activated */
-	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
-	cancel_work_sync(&priv->tt_work);
-	cancel_work_sync(&priv->ct_enter);
-	cancel_work_sync(&priv->ct_exit);
-
-	if (priv->thermal_throttle.advanced_tt) {
-		/* free advance thermal throttling memory */
-		kfree(tt->restriction);
-		tt->restriction = NULL;
-		kfree(tt->transaction);
-		tt->transaction = NULL;
-	}
-}
-EXPORT_SYMBOL(iwl_tt_exit);
-
 /* initialize to default */
 void iwl_power_initialize(struct iwl_priv *priv)
 {
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 5db91c1..df81565 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -30,90 +30,6 @@
 
 #include "iwl-commands.h"
 
-#define IWL_ABSOLUTE_ZERO		0
-#define IWL_ABSOLUTE_MAX		0xFFFFFFFF
-#define IWL_TT_INCREASE_MARGIN	5
-#define IWL_TT_CT_KILL_MARGIN	3
-
-enum iwl_antenna_ok {
-	IWL_ANT_OK_NONE,
-	IWL_ANT_OK_SINGLE,
-	IWL_ANT_OK_MULTI,
-};
-
-/* Thermal Throttling State Machine states */
-enum  iwl_tt_state {
-	IWL_TI_0,	/* normal temperature, system power state */
-	IWL_TI_1,	/* high temperature detect, low power state */
-	IWL_TI_2,	/* higher temperature detected, lower power state */
-	IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */
-	IWL_TI_STATE_MAX
-};
-
-/**
- * struct iwl_tt_restriction - Thermal Throttling restriction table
- * @tx_stream: number of tx stream allowed
- * @is_ht: ht enable/disable
- * @rx_stream: number of rx stream allowed
- *
- * This table is used by advance thermal throttling management
- * based on the current thermal throttling state, and determines
- * the number of tx/rx streams and the status of HT operation.
- */
-struct iwl_tt_restriction {
-	enum iwl_antenna_ok tx_stream;
-	enum iwl_antenna_ok rx_stream;
-	bool is_ht;
-};
-
-/**
- * struct iwl_tt_trans - Thermal Throttling transaction table
- * @next_state:  next thermal throttling mode
- * @tt_low: low temperature threshold to change state
- * @tt_high: high temperature threshold to change state
- *
- * This is used by the advanced thermal throttling algorithm
- * to determine the next thermal state to go based on the
- * current temperature.
- */
-struct iwl_tt_trans {
-	enum iwl_tt_state next_state;
-	u32 tt_low;
-	u32 tt_high;
-};
-
-/**
- * struct iwl_tt_mgnt - Thermal Throttling Management structure
- * @advanced_tt:    advanced thermal throttle required
- * @state:          current Thermal Throttling state
- * @tt_power_mode:  Thermal Throttling power mode index
- *		    being used to set power level when
- * 		    when thermal throttling state != IWL_TI_0
- *		    the tt_power_mode should set to different
- *		    power mode based on the current tt state
- * @tt_previous_temperature: last measured temperature
- * @iwl_tt_restriction: ptr to restriction tbl, used by advance
- *		    thermal throttling to determine how many tx/rx streams
- *		    should be used in tt state; and can HT be enabled or not
- * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling
- *		    state transaction
- * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature
- * @ct_kill_exit_tm: timer to exit thermal kill
- */
-struct iwl_tt_mgmt {
-	enum iwl_tt_state state;
-	bool advanced_tt;
-	u8 tt_power_mode;
-	bool ct_kill_toggle;
-#ifdef CONFIG_IWLWIFI_DEBUG
-	s32 tt_previous_temp;
-#endif
-	struct iwl_tt_restriction *restriction;
-	struct iwl_tt_trans *transaction;
-	struct timer_list ct_kill_exit_tm;
-	struct timer_list ct_kill_waiting_tm;
-};
-
 enum iwl_power_level {
 	IWL_POWER_INDEX_1,
 	IWL_POWER_INDEX_2,
@@ -130,15 +46,6 @@
 };
 
 int iwl_power_update_mode(struct iwl_priv *priv, bool force);
-bool iwl_ht_enabled(struct iwl_priv *priv);
-bool iwl_within_ct_kill_margin(struct iwl_priv *priv);
-enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
-enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
-void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
-void iwl_tt_exit_ct_kill(struct iwl_priv *priv);
-void iwl_tt_handler(struct iwl_priv *priv);
-void iwl_tt_initialize(struct iwl_priv *priv);
-void iwl_tt_exit(struct iwl_priv *priv);
 void iwl_power_initialize(struct iwl_priv *priv);
 
 extern bool no_sleep_autoadjust;
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index b1f101c..5469655 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -306,7 +306,7 @@
  *     at a time, until receiving ACK from receiving station, or reaching
  *     retry limit and giving up.
  *
- *     The command queue (#4) must use this mode!
+ *     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:
@@ -322,7 +322,7 @@
  *     (1024 bytes for each queue).
  *
  * After receiving "Alive" response from uCode, driver must initialize
- * the scheduler (especially for queue #4, the command queue, otherwise
+ * the scheduler (especially for queue #4/#9, the command queue, otherwise
  * the driver can't issue commands!):
  */
 
@@ -555,8 +555,9 @@
 #define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
 	((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc)
 
-#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(x)		(((1<<(x)) - 1) &\
-	(~(1<<IWL_CMD_QUEUE_NUM)))
+#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv)	\
+	(((1<<(priv)->hw_params.max_txq_num) - 1) &\
+	(~(1<<(priv)->cmd_queue)))
 
 #define IWLAGN_SCD_BASE			(PRPH_BASE + 0xa02c00)
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 79773e3..f436270 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -36,7 +36,6 @@
 #include "iwl-core.h"
 #include "iwl-sta.h"
 #include "iwl-io.h"
-#include "iwl-calib.h"
 #include "iwl-helpers.h"
 /************************** RX-FUNCTIONS ****************************/
 /*
@@ -228,7 +227,7 @@
 {
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
-	if (iwl_is_associated(priv)) {
+	if (iwl_is_any_associated(priv)) {
 		if (priv->cfg->ops->lib->check_ack_health) {
 			if (!priv->cfg->ops->lib->check_ack_health(
 			    priv, pkt)) {
@@ -266,7 +265,12 @@
 {
 	u16 fc = le16_to_cpu(hdr->frame_control);
 
-	if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
+	/*
+	 * 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))
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index a4b3663..67da312 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -54,82 +54,28 @@
 #define IWL_PASSIVE_DWELL_BASE      (100)
 #define IWL_CHANNEL_TUNE_TIME       5
 
-
-
-/**
- * iwl_scan_cancel - Cancel any currently executing HW scan
- *
- * NOTE: priv->mutex is not required before calling this function
- */
-int iwl_scan_cancel(struct iwl_priv *priv)
-{
-	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
-		clear_bit(STATUS_SCANNING, &priv->status);
-		return 0;
-	}
-
-	if (test_bit(STATUS_SCANNING, &priv->status)) {
-		if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-			IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n");
-			queue_work(priv->workqueue, &priv->abort_scan);
-
-		} else
-			IWL_DEBUG_SCAN(priv, "Scan abort already in progress.\n");
-
-		return test_bit(STATUS_SCANNING, &priv->status);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(iwl_scan_cancel);
-/**
- * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
- * @ms: amount of time to wait (in milliseconds) for scan to abort
- *
- * NOTE: priv->mutex must be held before calling this function
- */
-int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
-{
-	unsigned long now = jiffies;
-	int ret;
-
-	ret = iwl_scan_cancel(priv);
-	if (ret && ms) {
-		mutex_unlock(&priv->mutex);
-		while (!time_after(jiffies, now + msecs_to_jiffies(ms)) &&
-				test_bit(STATUS_SCANNING, &priv->status))
-			msleep(1);
-		mutex_lock(&priv->mutex);
-
-		return test_bit(STATUS_SCANNING, &priv->status);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(iwl_scan_cancel_timeout);
-
 static int iwl_send_scan_abort(struct iwl_priv *priv)
 {
-	int ret = 0;
+	int ret;
 	struct iwl_rx_packet *pkt;
 	struct iwl_host_cmd cmd = {
 		.id = REPLY_SCAN_ABORT_CMD,
 		.flags = CMD_WANT_SKB,
 	};
 
-	/* If there isn't a scan actively going on in the hardware
-	 * then we are in between scan bands and not actually
-	 * actively scanning, so don't send the abort command */
-	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
-		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-		return 0;
-	}
+	/* 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_send_cmd_sync(priv, &cmd);
-	if (ret) {
-		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+	if (ret)
 		return ret;
-	}
 
 	pkt = (struct iwl_rx_packet *)cmd.reply_page;
 	if (pkt->u.status != CAN_ABORT_STATUS) {
@@ -139,16 +85,103 @@
 		 * can occur if we send the scan abort before we
 		 * the microcode has notified us that a scan is
 		 * completed. */
-		IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", pkt->u.status);
-		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
-		clear_bit(STATUS_SCAN_HW, &priv->status);
+		IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status);
+		ret = -EIO;
 	}
 
 	iwl_free_pages(priv, cmd.reply_page);
-
 	return ret;
 }
 
+static void iwl_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_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_complete_scan(priv, true);
+}
+
+static void iwl_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_send_scan_abort(priv);
+	if (ret) {
+		IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret);
+		iwl_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_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_scan_cancel);
+
+/**
+ * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
+ * @ms: amount of time to wait (in milliseconds) for scan to abort
+ *
+ */
+int iwl_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_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_scan_cancel_timeout);
+
 /* Service response to REPLY_SCAN_CMD (0x80) */
 static void iwl_rx_reply_scan(struct iwl_priv *priv,
 			      struct iwl_rx_mem_buffer *rxb)
@@ -158,7 +191,7 @@
 	struct iwl_scanreq_notification *notif =
 	    (struct iwl_scanreq_notification *)pkt->u.raw;
 
-	IWL_DEBUG_RX(priv, "Scan request status = 0x%x\n", notif->status);
+	IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
 #endif
 }
 
@@ -206,7 +239,6 @@
 static void iwl_rx_scan_complete_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_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
 
@@ -214,29 +246,38 @@
 		       scan_notif->scanned_channels,
 		       scan_notif->tsf_low,
 		       scan_notif->tsf_high, scan_notif->status);
-#endif
 
 	/* The HW is no longer scanning */
 	clear_bit(STATUS_SCAN_HW, &priv->status);
 
-	IWL_DEBUG_INFO(priv, "Scan on %sGHz took %dms\n",
+	IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
 		       (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
 		       jiffies_to_msecs(elapsed_jiffies
 					(priv->scan_start, jiffies)));
 
-	/*
-	 * If a request to abort was given, or the scan did not succeed
-	 * then we reset the scan state machine and terminate,
-	 * re-queuing another scan if one has been requested
-	 */
-	if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status))
-		IWL_DEBUG_INFO(priv, "Aborted scan completed.\n");
-
-	IWL_DEBUG_INFO(priv, "Setting scan to off\n");
-
-	clear_bit(STATUS_SCANNING, &priv->status);
-
 	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 &&
+	    priv->bt_status != scan_notif->bt_status) {
+		if (scan_notif->bt_status) {
+			/* BT on */
+			if (!priv->bt_ch_announce)
+				priv->bt_traffic_load =
+					IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
+			/*
+			 * otherwise, no traffic load information provided
+			 * no changes made
+			 */
+		} else {
+			/* BT off */
+			priv->bt_traffic_load =
+				IWL_BT_COEX_TRAFFIC_LOAD_NONE;
+		}
+		priv->bt_status = scan_notif->bt_status;
+		queue_work(priv->workqueue, &priv->bt_traffic_change_work);
+	}
 }
 
 void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
@@ -268,18 +309,28 @@
 			       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_is_associated(priv)) {
-		/* If we're associated, we clamp the maximum passive
-		 * dwell time to be 98% of the beacon interval (minus
-		 * 2 * channel tune time) */
-		passive = vif ? vif->bss_conf.beacon_int : 0;
-		if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive)
-			passive = IWL_PASSIVE_DWELL_BASE;
-		passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
+	if (iwl_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_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;
@@ -296,19 +347,53 @@
 }
 EXPORT_SYMBOL(iwl_init_scan_params);
 
-static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif)
+static int __must_check iwl_scan_initiate(struct iwl_priv *priv,
+					  struct ieee80211_vif *vif,
+					  bool internal,
+					  enum ieee80211_band band)
 {
-	lockdep_assert_held(&priv->mutex);
+	int ret;
 
-	IWL_DEBUG_INFO(priv, "Starting scan...\n");
-	set_bit(STATUS_SCANNING, &priv->status);
-	priv->is_internal_short_scan = false;
-	priv->scan_start = jiffies;
+	lockdep_assert_held(&priv->mutex);
 
 	if (WARN_ON(!priv->cfg->ops->utils->request_scan))
 		return -EOPNOTSUPP;
 
-	priv->cfg->ops->utils->request_scan(priv, vif);
+	cancel_delayed_work(&priv->scan_check);
+
+	if (!iwl_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;
 }
@@ -327,12 +412,6 @@
 
 	mutex_lock(&priv->mutex);
 
-	if (!iwl_is_ready_rf(priv)) {
-		ret = -EIO;
-		IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n");
-		goto out_unlock;
-	}
-
 	if (test_bit(STATUS_SCANNING, &priv->status) &&
 	    !priv->is_internal_short_scan) {
 		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
@@ -340,14 +419,7 @@
 		goto out_unlock;
 	}
 
-	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-		IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
-		ret = -EAGAIN;
-		goto out_unlock;
-	}
-
 	/* mac80211 will only ask for one band at a time */
-	priv->scan_band = req->channels[0]->band;
 	priv->scan_request = req;
 	priv->scan_vif = vif;
 
@@ -355,10 +427,12 @@
 	 * If an internal scan is in progress, just set
 	 * up the scan_request as per above.
 	 */
-	if (priv->is_internal_short_scan)
+	if (priv->is_internal_short_scan) {
+		IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
 		ret = 0;
-	else
-		ret = iwl_scan_initiate(priv, vif);
+	} else
+		ret = iwl_scan_initiate(priv, vif, false,
+					req->channels[0]->band);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
@@ -378,11 +452,13 @@
 	queue_work(priv->workqueue, &priv->start_internal_scan);
 }
 
-void iwl_bg_start_internal_scan(struct work_struct *work)
+static void iwl_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) {
@@ -390,56 +466,31 @@
 		goto unlock;
 	}
 
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_SCAN(priv, "not ready or exit pending\n");
-		goto unlock;
-	}
-
 	if (test_bit(STATUS_SCANNING, &priv->status)) {
 		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
 		goto unlock;
 	}
 
-	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-		IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
-		goto unlock;
-	}
-
-	priv->scan_band = priv->band;
-
-	IWL_DEBUG_SCAN(priv, "Start internal short scan...\n");
-	set_bit(STATUS_SCANNING, &priv->status);
-	priv->is_internal_short_scan = true;
-
-	if (WARN_ON(!priv->cfg->ops->utils->request_scan))
-		goto unlock;
-
-	priv->cfg->ops->utils->request_scan(priv, NULL);
+	if (iwl_scan_initiate(priv, NULL, true, priv->band))
+		IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
  unlock:
 	mutex_unlock(&priv->mutex);
 }
-EXPORT_SYMBOL(iwl_bg_start_internal_scan);
 
-void iwl_bg_scan_check(struct work_struct *data)
+static void iwl_bg_scan_check(struct work_struct *data)
 {
 	struct iwl_priv *priv =
 	    container_of(data, struct iwl_priv, scan_check.work);
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
+	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);
-	if (test_bit(STATUS_SCANNING, &priv->status) &&
-	    !test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-		IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n",
-			       jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
-
-		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
-			iwl_send_scan_abort(priv);
-	}
+	iwl_force_scan_end(priv);
 	mutex_unlock(&priv->mutex);
 }
-EXPORT_SYMBOL(iwl_bg_scan_check);
 
 /**
  * iwl_fill_probe_req - fill in all required fields and IE for probe request
@@ -489,73 +540,78 @@
 }
 EXPORT_SYMBOL(iwl_fill_probe_req);
 
-void iwl_bg_abort_scan(struct work_struct *work)
+static void iwl_bg_abort_scan(struct work_struct *work)
 {
 	struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
 
-	if (!test_bit(STATUS_READY, &priv->status) ||
-	    !test_bit(STATUS_GEO_CONFIGURED, &priv->status))
-		return;
+	IWL_DEBUG_SCAN(priv, "Abort scan work\n");
 
-	cancel_delayed_work(&priv->scan_check);
-
+	/* We keep scan_check work queued in case when firmware will not
+	 * report back scan completed notification */
 	mutex_lock(&priv->mutex);
-	if (test_bit(STATUS_SCAN_ABORTING, &priv->status))
-		iwl_send_scan_abort(priv);
+	iwl_scan_cancel_timeout(priv, 200);
 	mutex_unlock(&priv->mutex);
 }
-EXPORT_SYMBOL(iwl_bg_abort_scan);
 
-void iwl_bg_scan_completed(struct work_struct *work)
+static void iwl_bg_scan_completed(struct work_struct *work)
 {
 	struct iwl_priv *priv =
 	    container_of(work, struct iwl_priv, scan_completed);
-	bool internal = false;
+	bool aborted;
 
-	IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
+	IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
+		       priv->is_internal_short_scan ? "internal short " : "");
 
 	cancel_delayed_work(&priv->scan_check);
 
 	mutex_lock(&priv->mutex);
-	if (priv->is_internal_short_scan) {
-		priv->is_internal_short_scan = false;
-		IWL_DEBUG_SCAN(priv, "internal short scan completed\n");
-		internal = true;
-	} else {
-		priv->scan_request = NULL;
-		priv->scan_vif = NULL;
+
+	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 (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		goto out;
+	if (priv->is_internal_short_scan && !aborted) {
+		int err;
 
-	if (internal && priv->scan_request)
-		iwl_scan_initiate(priv, priv->scan_vif);
+		/* 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_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_complete_scan(priv, aborted);
+
+out_settings:
+	/* Can we still talk to firmware ? */
+	if (!iwl_is_ready_rf(priv))
+		goto out;
 
 	/* Since setting the TXPOWER may have been deferred while
 	 * performing the scan, fire one off */
 	iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
 
-	/*
-	 * Since setting the RXON may have been deferred while
-	 * performing the scan, fire one off if needed
-	 */
-	if (memcmp(&priv->active_rxon,
-		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
-		iwlcore_commit_rxon(priv);
+	priv->cfg->ops->utils->post_scan(priv);
 
  out:
 	mutex_unlock(&priv->mutex);
-
-	/*
-	 * Do not hold mutex here since this will cause mac80211 to call
-	 * into driver again into functions that will attempt to take
-	 * mutex.
-	 */
-	if (!internal)
-		ieee80211_scan_completed(priv->hw, false);
 }
-EXPORT_SYMBOL(iwl_bg_scan_completed);
 
 void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
 {
@@ -566,3 +622,16 @@
 }
 EXPORT_SYMBOL(iwl_setup_scan_deferred_work);
 
+void iwl_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_force_scan_end(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 7e0829b..7c7f7dc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -172,12 +172,14 @@
 EXPORT_SYMBOL(iwl_send_add_sta);
 
 static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
-				   struct ieee80211_sta_ht_cap *sta_ht_inf)
+				   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_ht_inf || !sta_ht_inf->ht_supported)
+	if (!sta || !sta_ht_inf->ht_supported)
 		goto done;
 
 	mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
@@ -211,7 +213,7 @@
 	sta_flags |= cpu_to_le32(
 	      (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
 
-	if (iwl_is_ht40_tx_allowed(priv, sta_ht_inf))
+	if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
 		sta_flags |= STA_FLG_HT40_EN_MSK;
 	else
 		sta_flags &= ~STA_FLG_HT40_EN_MSK;
@@ -226,9 +228,8 @@
  *
  * should be called with sta_lock held
  */
-static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr,
-			   bool is_ap,
-			   struct ieee80211_sta_ht_cap *ht_info)
+u8 iwl_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;
@@ -236,9 +237,9 @@
 	u16 rate;
 
 	if (is_ap)
-		sta_id = IWL_AP_ID;
+		sta_id = ctx->ap_sta_id;
 	else if (is_broadcast_ether_addr(addr))
-		sta_id = priv->hw_params.bcast_sta_id;
+		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,
@@ -289,14 +290,22 @@
 	memcpy(station->sta.sta.addr, addr, ETH_ALEN);
 	station->sta.mode = 0;
 	station->sta.sta.sta_id = sta_id;
-	station->sta.station_flags = 0;
+	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 ht_info, and mac80211
+	 * STA and broadcast STA) pass in a NULL sta, and mac80211
 	 * doesn't allow HT IBSS.
 	 */
-	iwl_set_ht_add_station(priv, sta_id, ht_info);
+	iwl_set_ht_add_station(priv, sta_id, sta, ctx);
 
 	/* 3945 only */
 	rate = (priv->band == IEEE80211_BAND_5GHZ) ?
@@ -307,16 +316,16 @@
 	return sta_id;
 
 }
+EXPORT_SYMBOL_GPL(iwl_prep_station);
 
 #define STA_WAIT_TIMEOUT (HZ/2)
 
 /**
  * iwl_add_station_common -
  */
-int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
-				  bool is_ap,
-				  struct ieee80211_sta_ht_cap *ht_info,
-				  u8 *sta_id_r)
+int iwl_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;
@@ -325,7 +334,7 @@
 
 	*sta_id_r = 0;
 	spin_lock_irqsave(&priv->sta_lock, flags_spin);
-	sta_id = iwl_prep_station(priv, addr, is_ap, ht_info);
+	sta_id = iwl_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);
@@ -372,111 +381,6 @@
 }
 EXPORT_SYMBOL(iwl_add_station_common);
 
-static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv,
-						     u8 sta_id)
-{
-	int i, r;
-	struct iwl_link_quality_cmd *link_cmd;
-	u32 rate_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;
-
-	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
-		rate_flags = 0;
-		if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
-			rate_flags |= RATE_MCS_CCK_MSK;
-
-		rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
-				RATE_MCS_ANT_POS;
-
-		link_cmd->rs_table[i].rate_n_flags =
-			iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
-		r = iwl_get_prev_ieee_rate(r);
-	}
-
-	link_cmd->general_params.single_stream_ant_msk =
-				first_antenna(priv->hw_params.valid_tx_ant);
-
-	link_cmd->general_params.dual_stream_ant_msk =
-		priv->hw_params.valid_tx_ant &
-		~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 (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;
-}
-
-/*
- * iwl_add_bssid_station - Add the special IBSS BSSID station
- *
- * Function sleeps.
- */
-int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
-			  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_add_station_common(priv, 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);
-
-	if (init_rs) {
-		/* Set up default rate scaling table in device's station table */
-		link_cmd = iwl_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_send_lq_cmd(priv, 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;
-}
-EXPORT_SYMBOL(iwl_add_bssid_station);
-
 /**
  * iwl_sta_ucode_deactivate - deactivate ucode status for a station
  *
@@ -616,7 +520,8 @@
  * other than explicit station management would cause this in
  * the ucode, e.g. unassociated RXON.
  */
-void iwl_clear_ucode_stations(struct iwl_priv *priv)
+void iwl_clear_ucode_stations(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx)
 {
 	int i;
 	unsigned long flags_spin;
@@ -626,6 +531,9 @@
 
 	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;
@@ -647,7 +555,7 @@
  *
  * Function sleeps.
  */
-void iwl_restore_stations(struct iwl_priv *priv)
+void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
 	struct iwl_addsta_cmd sta_cmd;
 	struct iwl_link_quality_cmd lq;
@@ -665,6 +573,8 @@
 	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",
@@ -700,7 +610,7 @@
 			 * current LQ command
 			 */
 			if (send_lq)
-				iwl_send_lq_cmd(priv, &lq, CMD_SYNC, true);
+				iwl_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;
 		}
@@ -718,7 +628,7 @@
 {
 	int i;
 
-	for (i = 0; i < STA_KEY_MAX_NUM; i++)
+	for (i = 0; i < priv->sta_key_max_num; i++)
 		if (!test_and_set_bit(i, &priv->ucode_key_table))
 			return i;
 
@@ -726,393 +636,25 @@
 }
 EXPORT_SYMBOL(iwl_get_free_ucode_key_index);
 
-static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
+void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
 {
-	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 = REPLY_WEPKEY,
-		.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 (priv->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 = priv->wep_keys[i].key_size;
-		memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key,
-				priv->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_send_cmd(priv, &cmd);
-	else
-		return 0;
-}
-
-int iwl_restore_default_wep_keys(struct iwl_priv *priv)
-{
-	lockdep_assert_held(&priv->mutex);
-
-	return iwl_send_static_wepkey_cmd(priv, 0);
-}
-EXPORT_SYMBOL(iwl_restore_default_wep_keys);
-
-int iwl_remove_default_wep_key(struct iwl_priv *priv,
-			       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(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
-	if (iwl_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 = iwl_send_static_wepkey_cmd(priv, 1);
-	IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
-		      keyconf->keyidx, ret);
-
-	return ret;
-}
-EXPORT_SYMBOL(iwl_remove_default_wep_key);
-
-int iwl_set_default_wep_key(struct iwl_priv *priv,
-			    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[IWL_AP_ID].keyinfo.alg = ALG_WEP;
-
-	priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
-	memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key,
-							keyconf->keylen);
-
-	ret = iwl_send_static_wepkey_cmd(priv, 0);
-	IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
-		keyconf->keylen, keyconf->keyidx, ret);
-
-	return ret;
-}
-EXPORT_SYMBOL(iwl_set_default_wep_key);
-
-static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
-				struct ieee80211_key_conf *keyconf,
-				u8 sta_id)
-{
-	unsigned long flags;
-	__le16 key_flags = 0;
-	struct iwl_addsta_cmd sta_cmd;
-
-	lockdep_assert_held(&priv->mutex);
-
-	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-
-	key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
-	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-	key_flags &= ~STA_KEY_FLG_INVALID;
-
-	if (keyconf->keylen == WEP_KEY_LEN_128)
-		key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
-
-	if (sta_id == priv->hw_params.bcast_sta_id)
-		key_flags |= STA_KEY_MULTICAST_MSK;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-
-	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
-	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-	priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
-
-	memcpy(priv->stations[sta_id].keyinfo.key,
-				keyconf->key, keyconf->keylen);
-
-	memcpy(&priv->stations[sta_id].sta.key.key[3],
-				keyconf->key, keyconf->keylen);
-
-	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-			== STA_KEY_FLG_NO_ENC)
-		priv->stations[sta_id].sta.key.key_offset =
-				 iwl_get_free_ucode_key_index(priv);
-	/* else, we are overriding an existing key => no need to allocated room
-	 * in uCode. */
-
-	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-		"no space for a new key");
-
-	priv->stations[sta_id].sta.key.key_flags = key_flags;
-	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
-	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
-				   struct ieee80211_key_conf *keyconf,
-				   u8 sta_id)
-{
-	unsigned long flags;
-	__le16 key_flags = 0;
-	struct iwl_addsta_cmd sta_cmd;
-
-	lockdep_assert_held(&priv->mutex);
-
-	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 == priv->hw_params.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.alg = keyconf->alg;
-	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-
-	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
-	       keyconf->keylen);
-
-	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
-	       keyconf->keylen);
-
-	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-			== STA_KEY_FLG_NO_ENC)
-		priv->stations[sta_id].sta.key.key_offset =
-				 iwl_get_free_ucode_key_index(priv);
-	/* else, we are overriding an existing key => no need to allocated room
-	 * in uCode. */
-
-	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-		"no space for a new key");
-
-	priv->stations[sta_id].sta.key.key_flags = key_flags;
-	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
-	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
-				   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 == priv->hw_params.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.alg = keyconf->alg;
-	priv->stations[sta_id].keyinfo.keylen = 16;
-
-	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-			== STA_KEY_FLG_NO_ENC)
-		priv->stations[sta_id].sta.key.key_offset =
-				 iwl_get_free_ucode_key_index(priv);
-	/* else, we are overriding an existing key => no need to allocated room
-	 * in uCode. */
-
-	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-		"no space for a new key");
-
-	priv->stations[sta_id].sta.key.key_flags = key_flags;
-
-
-	/* 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 iwl_update_tkip_key(struct iwl_priv *priv,
-			struct ieee80211_key_conf *keyconf,
-			struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
-{
-	u8 sta_id;
 	unsigned long flags;
 	int i;
 
-	if (iwl_scan_cancel(priv)) {
-		/* cancel scan failed, just live w/ bad key and rely
-		   briefly on SW decryption */
-		return;
-	}
-
-	sta_id = iwl_sta_id_or_broadcast(priv, sta);
-	if (sta_id == IWL_INVALID_STATION)
-		return;
-
 	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[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
-
-	for (i = 0; i < 5; i++)
-		priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
-			cpu_to_le16(phase1key[i]);
-
-	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
-	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-
+		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(iwl_update_tkip_key);
-
-int iwl_remove_dynamic_key(struct iwl_priv *priv,
-				struct ieee80211_key_conf *keyconf,
-				u8 sta_id)
-{
-	unsigned long flags;
-	u16 key_flags;
-	u8 keyidx;
-	struct iwl_addsta_cmd sta_cmd;
-
-	lockdep_assert_held(&priv->mutex);
-
-	priv->key_mapping_key--;
-
-	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_is_rfkill(priv)) {
-		IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
-		spin_unlock_irqrestore(&priv->sta_lock, flags);
-		return 0;
-	}
-	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-EXPORT_SYMBOL(iwl_remove_dynamic_key);
-
-int iwl_set_dynamic_key(struct iwl_priv *priv,
-				struct ieee80211_key_conf *keyconf, u8 sta_id)
-{
-	int ret;
-
-	lockdep_assert_held(&priv->mutex);
-
-	priv->key_mapping_key++;
-	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
-
-	switch (keyconf->alg) {
-	case ALG_CCMP:
-		ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
-		break;
-	case ALG_TKIP:
-		ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
-		break;
-	case ALG_WEP:
-		ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id);
-		break;
-	default:
-		IWL_ERR(priv,
-			"Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
-		ret = -EINVAL;
-	}
-
-	IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n",
-		      keyconf->alg, keyconf->keylen, keyconf->keyidx,
-		      sta_id, ret);
-
-	return ret;
-}
-EXPORT_SYMBOL(iwl_set_dynamic_key);
+EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 static void iwl_dump_lq_cmd(struct iwl_priv *priv,
@@ -1147,16 +689,16 @@
  * RXON flags are updated and when LQ command is updated.
  */
 static bool is_lq_table_valid(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx,
 			      struct iwl_link_quality_cmd *lq)
 {
 	int i;
-	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
 
-	if (ht_conf->is_ht)
+	if (ctx->ht.enabled)
 		return true;
 
 	IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n",
-		       priv->active_rxon.channel);
+		       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,
@@ -1178,7 +720,7 @@
  * this case to clear the state indicating that station creation is in
  * progress.
  */
-int iwl_send_lq_cmd(struct iwl_priv *priv,
+int iwl_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;
@@ -1197,7 +739,7 @@
 	iwl_dump_lq_cmd(priv, lq);
 	BUG_ON(init && (cmd.flags & CMD_ASYNC));
 
-	if (is_lq_table_valid(priv, lq))
+	if (is_lq_table_valid(priv, ctx, lq))
 		ret = iwl_send_cmd(priv, &cmd);
 	else
 		ret = -EINVAL;
@@ -1216,207 +758,6 @@
 }
 EXPORT_SYMBOL(iwl_send_lq_cmd);
 
-/**
- * iwl_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 iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq)
-{
-	struct iwl_link_quality_cmd *link_cmd;
-	unsigned long flags;
-	u8 sta_id;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	sta_id = iwl_prep_station(priv, 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);
-
-	if (init_lq) {
-		link_cmd = iwl_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;
-}
-EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station);
-
-/**
- * iwl_update_bcast_station - update broadcast station's LQ command
- *
- * Only used by iwlagn. Placed here to have all bcast station management
- * code together.
- */
-int iwl_update_bcast_station(struct iwl_priv *priv)
-{
-	unsigned long flags;
-	struct iwl_link_quality_cmd *link_cmd;
-	u8 sta_id = priv->hw_params.bcast_sta_id;
-
-	link_cmd = iwl_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;
-}
-EXPORT_SYMBOL_GPL(iwl_update_bcast_station);
-
-void iwl_dealloc_bcast_station(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_dealloc_bcast_station);
-
-/**
- * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
- */
-int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
-{
-	unsigned long flags;
-	struct iwl_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_addsta_cmd));
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
-
-int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
-			 int tid, u16 ssn)
-{
-	unsigned long flags;
-	int sta_id;
-	struct iwl_addsta_cmd sta_cmd;
-
-	lockdep_assert_held(&priv->mutex);
-
-	sta_id = iwl_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_addsta_cmd));
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-EXPORT_SYMBOL(iwl_sta_rx_agg_start);
-
-int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
-			int tid)
-{
-	unsigned long flags;
-	int sta_id;
-	struct iwl_addsta_cmd sta_cmd;
-
-	lockdep_assert_held(&priv->mutex);
-
-	sta_id = iwl_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_addsta_cmd));
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-EXPORT_SYMBOL(iwl_sta_rx_agg_stop);
-
-void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
-{
-	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 = 0;
-	priv->stations[sta_id].sta.sleep_tx_count = 0;
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-}
-EXPORT_SYMBOL(iwl_sta_modify_ps_wake);
-
-void iwl_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_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-}
-EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count);
-
 int iwl_mac_sta_remove(struct ieee80211_hw *hw,
 		       struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta)
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index d38a350..0647587 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -43,44 +43,26 @@
 #define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */
 
 
-int iwl_remove_default_wep_key(struct iwl_priv *priv,
-			       struct ieee80211_key_conf *key);
-int iwl_set_default_wep_key(struct iwl_priv *priv,
-			    struct ieee80211_key_conf *key);
-int iwl_restore_default_wep_keys(struct iwl_priv *priv);
-int iwl_set_dynamic_key(struct iwl_priv *priv,
-			struct ieee80211_key_conf *key, u8 sta_id);
-int iwl_remove_dynamic_key(struct iwl_priv *priv,
-			   struct ieee80211_key_conf *key, u8 sta_id);
-void iwl_update_tkip_key(struct iwl_priv *priv,
-			struct ieee80211_key_conf *keyconf,
-			struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
-
-void iwl_restore_stations(struct iwl_priv *priv);
-void iwl_clear_ucode_stations(struct iwl_priv *priv);
-int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq);
-void iwl_dealloc_bcast_station(struct iwl_priv *priv);
-int iwl_update_bcast_station(struct iwl_priv *priv);
+void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+void iwl_clear_ucode_stations(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx);
+void iwl_dealloc_bcast_stations(struct iwl_priv *priv);
 int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
 int iwl_send_add_sta(struct iwl_priv *priv,
 		     struct iwl_addsta_cmd *sta, u8 flags);
-int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
-			  u8 *sta_id_r);
-int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
-				  bool is_ap,
-				  struct ieee80211_sta_ht_cap *ht_info,
-				  u8 *sta_id_r);
+int iwl_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_remove_station(struct iwl_priv *priv, const u8 sta_id,
 		       const u8 *addr);
 int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta);
-int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
-int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
-			 int tid, u16 ssn);
-int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
-			int tid);
-void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id);
-void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
+
+u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+		    const u8 *addr, bool is_ap, struct ieee80211_sta *sta);
+
+int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+		    struct iwl_link_quality_cmd *lq, u8 flags, bool init);
 
 /**
  * iwl_clear_driver_stations - clear knowledge of all stations from driver
@@ -94,20 +76,25 @@
 static inline void iwl_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;
 
-	/*
-	 * 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.
-	 */
 	priv->ucode_key_table = 0;
-	priv->key_mapping_key = 0;
-	memset(priv->wep_keys, 0, sizeof(priv->wep_keys));
+
+	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);
 }
@@ -123,6 +110,7 @@
 /**
  * iwl_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
@@ -131,12 +119,13 @@
  * inline wraps that pattern.
  */
 static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv,
+					  struct iwl_rxon_context *context,
 					  struct ieee80211_sta *sta)
 {
 	int sta_id;
 
 	if (!sta)
-		return priv->hw_params.bcast_sta_id;
+		return context->bcast_sta_id;
 
 	sta_id = iwl_sta_id(sta);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index a81989c..7261ee4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -134,7 +134,7 @@
  */
 void iwl_cmd_queue_free(struct iwl_priv *priv)
 {
-	struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+	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;
@@ -271,7 +271,7 @@
 
 	/* Driver private data, only for Tx (not command) queues,
 	 * not shared with device. */
-	if (id != IWL_CMD_QUEUE_NUM) {
+	if (id != priv->cmd_queue) {
 		txq->txb = kzalloc(sizeof(txq->txb[0]) *
 				   TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
 		if (!txq->txb) {
@@ -314,13 +314,13 @@
 
 	/*
 	 * Alloc buffer array for commands (Tx or other types of commands).
-	 * For the command queue (#4), allocate command space + one big
+	 * 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 == IWL_CMD_QUEUE_NUM)
+	if (txq_id == priv->cmd_queue)
 		actual_slots++;
 
 	txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots,
@@ -355,7 +355,7 @@
 	 * need an swq_id so don't set one to catch errors, all others can
 	 * be set up to the identity mapping.
 	 */
-	if (txq_id != IWL_CMD_QUEUE_NUM)
+	if (txq_id != priv->cmd_queue)
 		txq->swq_id = txq_id;
 
 	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
@@ -385,7 +385,7 @@
 {
 	int actual_slots = slots_num;
 
-	if (txq_id == IWL_CMD_QUEUE_NUM)
+	if (txq_id == priv->cmd_queue)
 		actual_slots++;
 
 	memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots);
@@ -413,7 +413,7 @@
  */
 int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 {
-	struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+	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;
@@ -422,6 +422,7 @@
 	int len;
 	u32 idx;
 	u16 fix_size;
+	bool is_ct_kill = false;
 
 	cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
 	fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
@@ -443,9 +444,11 @@
 
 	if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
 		IWL_ERR(priv, "No space in command queue\n");
-		if (iwl_within_ct_kill_margin(priv))
-			iwl_tt_enter_ct_kill(priv);
-		else {
+		if (priv->cfg->ops->lib->tt_ops.ct_kill_check) {
+			is_ct_kill =
+				priv->cfg->ops->lib->tt_ops.ct_kill_check(priv);
+		}
+		if (!is_ct_kill) {
 			IWL_ERR(priv, "Restarting adapter due to queue full\n");
 			queue_work(priv->workqueue, &priv->restart);
 		}
@@ -480,7 +483,7 @@
 	 * information */
 
 	out_cmd->hdr.flags = 0;
-	out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
+	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;
@@ -497,15 +500,15 @@
 				get_cmd_string(out_cmd->hdr.cmd),
 				out_cmd->hdr.cmd,
 				le16_to_cpu(out_cmd->hdr.sequence), fix_size,
-				q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
-				break;
+				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",
 				get_cmd_string(out_cmd->hdr.cmd),
 				out_cmd->hdr.cmd,
 				le16_to_cpu(out_cmd->hdr.sequence), fix_size,
-				q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
+				q->write_ptr, idx, priv->cmd_queue);
 	}
 #endif
 	txq->need_update = 1;
@@ -584,16 +587,16 @@
 	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[IWL_CMD_QUEUE_NUM];
+	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 != IWL_CMD_QUEUE_NUM,
-		 "wrong command queue %d, sequence 0x%X readp=%d writep=%d\n",
-		  txq_id, sequence,
-		  priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr,
-		  priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) {
+	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;
 	}
@@ -633,41 +636,3 @@
 	meta->flags = 0;
 }
 EXPORT_SYMBOL(iwl_tx_cmd_complete);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
-#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
-
-const char *iwl_get_tx_fail_reason(u32 status)
-{
-	switch (status & TX_STATUS_MSK) {
-	case TX_STATUS_SUCCESS:
-		return "SUCCESS";
-		TX_STATUS_POSTPONE(DELAY);
-		TX_STATUS_POSTPONE(FEW_BYTES);
-		TX_STATUS_POSTPONE(BT_PRIO);
-		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(FW_DROP);
-		TX_STATUS_FAIL(STA_COLOR_MISMATCH_DROP);
-	}
-
-	return "UNKNOWN";
-}
-EXPORT_SYMBOL(iwl_get_tx_fail_reason);
-#endif /* CONFIG_IWLWIFI_DEBUG */
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 59a308b..8f8c4b7 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -33,6 +33,7 @@
 #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>
@@ -143,7 +144,7 @@
 	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->hw_params.bcast_sta_id)
+	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;
@@ -151,7 +152,7 @@
 	key_flags &= ~STA_KEY_FLG_INVALID;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
-	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
+	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);
@@ -222,23 +223,25 @@
 
 	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
 
-	switch (keyconf->alg) {
-	case ALG_CCMP:
+	switch (keyconf->cipher) {
+	case WLAN_CIPHER_SUITE_CCMP:
 		ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
 		break;
-	case ALG_TKIP:
+	case WLAN_CIPHER_SUITE_TKIP:
 		ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
 		break;
-	case ALG_WEP:
+	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 = %d\n", __func__, keyconf->alg);
+		IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__,
+			keyconf->cipher);
 		ret = -EINVAL;
 	}
 
-	IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n",
-		      keyconf->alg, keyconf->keylen, keyconf->keyidx,
+	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;
@@ -254,10 +257,11 @@
 static int iwl3945_set_static_key(struct iwl_priv *priv,
 				struct ieee80211_key_conf *key)
 {
-	if (key->alg == ALG_WEP)
+	if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+	    key->cipher == WLAN_CIPHER_SUITE_WEP104)
 		return -EOPNOTSUPP;
 
-	IWL_ERR(priv, "Static key invalid: alg %d\n", key->alg);
+	IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher);
 	return -EINVAL;
 }
 
@@ -313,15 +317,15 @@
 				int left)
 {
 
-	if (!iwl_is_associated(priv) || !priv->ibss_beacon)
+	if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb)
 		return 0;
 
-	if (priv->ibss_beacon->len > left)
+	if (priv->beacon_skb->len > left)
 		return 0;
 
-	memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
+	memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
 
-	return priv->ibss_beacon->len;
+	return priv->beacon_skb->len;
 }
 
 static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
@@ -339,7 +343,8 @@
 		return -ENOMEM;
 	}
 
-	rate = iwl_rate_get_lowest_plcp(priv);
+	rate = iwl_rate_get_lowest_plcp(priv,
+				&priv->contexts[IWL_RXON_CTX_BSS]);
 
 	frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
 
@@ -369,23 +374,25 @@
 	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
 	struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
 
-	switch (keyinfo->alg) {
-	case ALG_CCMP:
+	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 ALG_TKIP:
+	case WLAN_CIPHER_SUITE_TKIP:
 		break;
 
-	case ALG_WEP:
-		tx_cmd->sec_ctl = TX_CMD_SEC_WEP |
+	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;
 
-		if (keyinfo->keylen == 13)
-			tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
-
 		memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
 
 		IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
@@ -393,7 +400,7 @@
 		break;
 
 	default:
-		IWL_ERR(priv, "Unknown encode alg %d\n", keyinfo->alg);
+		IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher);
 		break;
 	}
 }
@@ -506,7 +513,9 @@
 	hdr_len = ieee80211_hdrlen(fc);
 
 	/* Find index into station table for destination station */
-	sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta);
+	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);
@@ -536,6 +545,7 @@
 	/* 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];
@@ -677,11 +687,12 @@
 	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))
+	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(priv->rxon_timing.beacon_interval));
+			le16_to_cpu(ctx->timing.beacon_interval));
 
 	memset(&spectrum, 0, sizeof(spectrum));
 
@@ -692,18 +703,18 @@
 	cmd.len = sizeof(spectrum);
 	spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
 
-	if (iwl_is_associated(priv))
+	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(priv->rxon_timing.beacon_interval));
+				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 (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
+	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;
 
@@ -792,7 +803,8 @@
 	struct sk_buff *beacon;
 
 	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
-	beacon = ieee80211_beacon_get(priv->hw, priv->vif);
+	beacon = ieee80211_beacon_get(priv->hw,
+			priv->contexts[IWL_RXON_CTX_BSS].vif);
 
 	if (!beacon) {
 		IWL_ERR(priv, "update beacon failed\n");
@@ -801,10 +813,10 @@
 
 	mutex_lock(&priv->mutex);
 	/* new beacon skb is allocated every time; dispose previous.*/
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
 
-	priv->ibss_beacon = beacon;
+	priv->beacon_skb = beacon;
 	mutex_unlock(&priv->mutex);
 
 	iwl3945_send_beacon_cmd(priv);
@@ -813,9 +825,9 @@
 static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
 				struct iwl_rx_mem_buffer *rxb)
 {
-#ifdef CONFIG_IWLWIFI_DEBUG
 	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 "
@@ -827,6 +839,8 @@
 		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);
@@ -1567,16 +1581,16 @@
 	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->max_event_log_size) {
+	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->max_event_log_size);
-		capacity = priv->cfg->max_event_log_size;
+			capacity, priv->cfg->base_params->max_event_log_size);
+		capacity = priv->cfg->base_params->max_event_log_size;
 	}
 
-	if (next_entry > priv->cfg->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->max_event_log_size);
-		next_entry = priv->cfg->max_event_log_size;
+			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;
@@ -1716,7 +1730,6 @@
 		IWL_ERR(priv, "Microcode SW error detected. "
 			"Restarting 0x%X.\n", inta);
 		priv->isr_stats.sw++;
-		priv->isr_stats.sw_err = inta;
 		iwl_irq_handle_error(priv);
 		handled |= CSR_INT_BIT_SW_ERR;
 	}
@@ -2460,6 +2473,7 @@
 {
 	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");
 
@@ -2505,7 +2519,8 @@
 		/* Enable timer to monitor the driver queues */
 		mod_timer(&priv->monitor_recover,
 			jiffies +
-			msecs_to_jiffies(priv->cfg->monitor_recover_period));
+			msecs_to_jiffies(
+			  priv->cfg->base_params->monitor_recover_period));
 	}
 
 	if (iwl_is_rfkill(priv))
@@ -2517,22 +2532,22 @@
 
 	iwl_power_update_mode(priv, true);
 
-	if (iwl_is_associated(priv)) {
+	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
 		struct iwl3945_rxon_cmd *active_rxon =
-				(struct iwl3945_rxon_cmd *)(&priv->active_rxon);
+				(struct iwl3945_rxon_cmd *)(&ctx->active);
 
-		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		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, NULL);
+		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 */
-	iwlcore_commit_rxon(priv);
+	iwl3945_commit_rxon(priv, ctx);
 
 	iwl3945_reg_txpower_periodic(priv);
 
@@ -2553,19 +2568,22 @@
 static void __iwl3945_down(struct iwl_priv *priv)
 {
 	unsigned long flags;
-	int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
-	struct ieee80211_conf *conf = NULL;
+	int exit_pending;
 
 	IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
 
-	conf = ieee80211_get_hw_conf(priv->hw);
+	iwl_scan_cancel_timeout(priv, 200);
 
-	if (!exit_pending)
-		set_bit(STATUS_EXIT_PENDING, &priv->status);
+	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 */
+	if (priv->cfg->ops->lib->recover_from_tx_stall)
+		del_timer_sync(&priv->monitor_recover);
 
 	/* Station information will now be cleared in device */
-	iwl_clear_ucode_stations(priv);
-	iwl_dealloc_bcast_station(priv);
+	iwl_clear_ucode_stations(priv, NULL);
+	iwl_dealloc_bcast_stations(priv);
 	iwl_clear_driver_stations(priv);
 
 	/* Unblock any waiting calls */
@@ -2619,14 +2637,14 @@
 	udelay(5);
 
 	/* Stop the device, and put it in low power state */
-	priv->cfg->ops->lib->apm_ops.stop(priv);
+	iwl_apm_stop(priv);
 
  exit:
 	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
 
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
-	priv->ibss_beacon = NULL;
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+	priv->beacon_skb = NULL;
 
 	/* clear out any free frames */
 	iwl3945_clear_free_frames(priv);
@@ -2643,11 +2661,33 @@
 
 #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 = iwl_alloc_bcast_station(priv, false);
+	rc = iwl3945_alloc_bcast_station(priv);
 	if (rc)
 		return rc;
 
@@ -2799,7 +2839,7 @@
 
 }
 
-void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
+int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
 	struct iwl_host_cmd cmd = {
 		.id = REPLY_SCAN_CMD,
@@ -2807,61 +2847,19 @@
 		.flags = CMD_SIZE_HUGE,
 	};
 	struct iwl3945_scan_cmd *scan;
-	struct ieee80211_conf *conf = NULL;
 	u8 n_probes = 0;
 	enum ieee80211_band band;
 	bool is_active = false;
+	int ret;
 
-	conf = ieee80211_get_hw_conf(priv->hw);
-
-	cancel_delayed_work(&priv->scan_check);
-
-	if (!iwl_is_ready(priv)) {
-		IWL_WARN(priv, "request scan called when driver not ready.\n");
-		goto done;
-	}
-
-	/* Make sure the scan wasn't canceled before this queued work
-	 * was given the chance to run... */
-	if (!test_bit(STATUS_SCANNING, &priv->status))
-		goto done;
-
-	/* This should never be called or scheduled if there is currently
-	 * a scan active in the hardware. */
-	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
-		IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests  "
-				"Ignoring second request.\n");
-		goto done;
-	}
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-		IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n");
-		goto done;
-	}
-
-	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-		IWL_DEBUG_HC(priv,
-			"Scan request while abort pending. Queuing.\n");
-		goto done;
-	}
-
-	if (iwl_is_rfkill(priv)) {
-		IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n");
-		goto done;
-	}
-
-	if (!test_bit(STATUS_READY, &priv->status)) {
-		IWL_DEBUG_HC(priv,
-			"Scan request while uninitialized. Queuing.\n");
-		goto done;
-	}
+	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");
-			goto done;
+			return -ENOMEM;
 		}
 	}
 	scan = priv->scan_cmd;
@@ -2870,7 +2868,7 @@
 	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
 	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
 
-	if (iwl_is_associated(priv)) {
+	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
 		u16 interval = 0;
 		u32 extra;
 		u32 suspend_time = 100;
@@ -2931,7 +2929,7 @@
 	/* 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->hw_params.bcast_sta_id;
+	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 */
@@ -2940,25 +2938,25 @@
 	case IEEE80211_BAND_2GHZ:
 		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
 		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
-		scan->good_CRC_th = 0;
 		band = IEEE80211_BAND_2GHZ;
 		break;
 	case IEEE80211_BAND_5GHZ:
 		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
-		/*
-		 * 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;
 		band = IEEE80211_BAND_5GHZ;
 		break;
 	default:
 		IWL_WARN(priv, "Invalid scan band\n");
-		goto done;
+		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,
@@ -2991,7 +2989,7 @@
 
 	if (scan->channel_count == 0) {
 		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
-		goto done;
+		return -EIO;
 	}
 
 	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
@@ -3000,25 +2998,22 @@
 	scan->len = cpu_to_le16(cmd.len);
 
 	set_bit(STATUS_SCAN_HW, &priv->status);
-	if (iwl_send_cmd_sync(priv, &cmd))
-		goto done;
+	ret = iwl_send_cmd_sync(priv, &cmd);
+	if (ret)
+		clear_bit(STATUS_SCAN_HW, &priv->status);
+	return ret;
+}
 
-	queue_delayed_work(priv->workqueue, &priv->scan_check,
-			   IWL_SCAN_CHECK_WATCHDOG);
+void iwl3945_post_scan(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
-	return;
-
- done:
-	/* can not perform scan make sure we clear scanning
-	 * bits from status so next scan request can be performed.
-	 * if we dont clear scanning status bit here all next scan
-	 * will fail
-	*/
-	clear_bit(STATUS_SCAN_HW, &priv->status);
-	clear_bit(STATUS_SCANNING, &priv->status);
-
-	/* inform mac80211 scan aborted */
-	queue_work(priv->workqueue, &priv->scan_completed);
+	/*
+	 * 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)
@@ -3029,8 +3024,10 @@
 		return;
 
 	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+		struct iwl_rxon_context *ctx;
 		mutex_lock(&priv->mutex);
-		priv->vif = NULL;
+		for_each_context(priv, ctx)
+			ctx->vif = NULL;
 		priv->is_open = 0;
 		mutex_unlock(&priv->mutex);
 		iwl3945_down(priv);
@@ -3064,6 +3061,7 @@
 {
 	int rc = 0;
 	struct ieee80211_conf *conf = NULL;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
 	if (!vif || !priv->is_open)
 		return;
@@ -3074,7 +3072,7 @@
 	}
 
 	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-			vif->bss_conf.aid, priv->active_rxon.bssid_addr);
+			vif->bss_conf.aid, ctx->active.bssid_addr);
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
@@ -3083,37 +3081,34 @@
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 
-	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwlcore_commit_rxon(priv);
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwl3945_commit_rxon(priv, ctx);
 
-	memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
-	iwl_setup_rxon_timing(priv, vif);
-	rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
-			      sizeof(priv->rxon_timing), &priv->rxon_timing);
+	rc = iwl_send_rxon_timing(priv, ctx);
 	if (rc)
 		IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
 			    "Attempting to continue.\n");
 
-	priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 
-	priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+	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)
-		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 	else
-		priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 
-	if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
+	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
 		if (vif->bss_conf.use_short_slot)
-			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
 		else
-			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 	}
 
-	iwlcore_commit_rxon(priv);
+	iwl3945_commit_rxon(priv, ctx);
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
@@ -3212,15 +3207,6 @@
 
 	priv->is_open = 0;
 
-	if (iwl_is_ready_rf(priv)) {
-		/* stop mac, cancel any scan request and clear
-		 * RXON_FILTER_ASSOC_MSK BIT
-		 */
-		mutex_lock(&priv->mutex);
-		iwl_scan_cancel_timeout(priv, 100);
-		mutex_unlock(&priv->mutex);
-	}
-
 	iwl3945_down(priv);
 
 	flush_workqueue(priv->workqueue);
@@ -3250,48 +3236,45 @@
 
 void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 	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))) {
+	if (!(iwl_is_associated(priv, IWL_RXON_CTX_BSS))) {
 
 		/* RXON - unassoc (to set timing command) */
-		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv);
+		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+		iwl3945_commit_rxon(priv, ctx);
 
 		/* RXON Timing */
-		memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
-		iwl_setup_rxon_timing(priv, vif);
-		rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
-				      sizeof(priv->rxon_timing),
-				      &priv->rxon_timing);
+		rc = iwl_send_rxon_timing(priv, ctx);
 		if (rc)
 			IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
 					"Attempting to continue.\n");
 
-		priv->staging_rxon.assoc_id = 0;
+		ctx->staging.assoc_id = 0;
 
 		if (vif->bss_conf.use_short_preamble)
-			priv->staging_rxon.flags |=
+			ctx->staging.flags |=
 				RXON_FLG_SHORT_PREAMBLE_MSK;
 		else
-			priv->staging_rxon.flags &=
+			ctx->staging.flags &=
 				~RXON_FLG_SHORT_PREAMBLE_MSK;
 
-		if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
+		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
 			if (vif->bss_conf.use_short_slot)
-				priv->staging_rxon.flags |=
+				ctx->staging.flags |=
 					RXON_FLG_SHORT_SLOT_MSK;
 			else
-				priv->staging_rxon.flags &=
+				ctx->staging.flags &=
 					~RXON_FLG_SHORT_SLOT_MSK;
 		}
 		/* restore RXON assoc */
-		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv);
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		iwl3945_commit_rxon(priv, ctx);
 	}
 	iwl3945_send_beacon_cmd(priv);
 
@@ -3317,10 +3300,11 @@
 		return -EOPNOTSUPP;
 	}
 
-	static_key = !iwl_is_associated(priv);
+	static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS);
 
 	if (!static_key) {
-		sta_id = iwl_sta_id_or_broadcast(priv, sta);
+		sta_id = iwl_sta_id_or_broadcast(
+				priv, &priv->contexts[IWL_RXON_CTX_BSS], sta);
 		if (sta_id == IWL_INVALID_STATION)
 			return -EINVAL;
 	}
@@ -3371,8 +3355,8 @@
 	sta_priv->common.sta_id = IWL_INVALID_STATION;
 
 
-	ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
-				     &sta_id);
+	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);
@@ -3399,6 +3383,7 @@
 {
 	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))		\
@@ -3418,8 +3403,8 @@
 
 	mutex_lock(&priv->mutex);
 
-	priv->staging_rxon.filter_flags &= ~filter_nand;
-	priv->staging_rxon.filter_flags |= filter_or;
+	ctx->staging.filter_flags &= ~filter_nand;
+	ctx->staging.filter_flags |= filter_or;
 
 	/*
 	 * Committing directly here breaks for some reason,
@@ -3533,8 +3518,9 @@
 			  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", priv->active_rxon.flags);
+	return sprintf(buf, "0x%04X\n", ctx->active.flags);
 }
 
 static ssize_t store_flags(struct device *d,
@@ -3543,17 +3529,18 @@
 {
 	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(priv->staging_rxon.flags) != flags) {
+	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);
-			priv->staging_rxon.flags = cpu_to_le32(flags);
-			iwlcore_commit_rxon(priv);
+			ctx->staging.flags = cpu_to_le32(flags);
+			iwl3945_commit_rxon(priv, ctx);
 		}
 	}
 	mutex_unlock(&priv->mutex);
@@ -3567,9 +3554,10 @@
 				 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(priv->active_rxon.filter_flags));
+		le32_to_cpu(ctx->active.filter_flags));
 }
 
 static ssize_t store_filter_flags(struct device *d,
@@ -3577,19 +3565,20 @@
 				  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(priv->staging_rxon.filter_flags) != filter_flags) {
+	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);
-			priv->staging_rxon.filter_flags =
+			ctx->staging.filter_flags =
 				cpu_to_le32(filter_flags);
-			iwlcore_commit_rxon(priv);
+			iwl3945_commit_rxon(priv, ctx);
 		}
 	}
 	mutex_unlock(&priv->mutex);
@@ -3637,8 +3626,9 @@
 				 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(priv->active_rxon.channel),
+		.channel = le16_to_cpu(ctx->active.channel),
 		.start_time = cpu_to_le64(priv->_3945.last_tsf),
 		.duration = cpu_to_le16(1),
 	};
@@ -3785,10 +3775,8 @@
 	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);
-	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
-	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
-	INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
-	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
+
+	iwl_setup_scan_deferred_work(priv);
 
 	iwl3945_hw_setup_deferred_work(priv);
 
@@ -3808,12 +3796,10 @@
 	iwl3945_hw_cancel_deferred_work(priv);
 
 	cancel_delayed_work_sync(&priv->init_alive_start);
-	cancel_delayed_work(&priv->scan_check);
 	cancel_delayed_work(&priv->alive_start);
-	cancel_work_sync(&priv->start_internal_scan);
 	cancel_work_sync(&priv->beacon_update);
-	if (priv->cfg->ops->lib->recover_from_tx_stall)
-		del_timer_sync(&priv->monitor_recover);
+
+	iwl_cancel_scan_deferred_work(priv);
 }
 
 static struct attribute *iwl3945_sysfs_entries[] = {
@@ -3853,6 +3839,7 @@
 	.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)
@@ -3861,7 +3848,7 @@
 	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
 
 	priv->retry_rate = 1;
-	priv->ibss_beacon = NULL;
+	priv->beacon_skb = NULL;
 
 	spin_lock_init(&priv->sta_lock);
 	spin_lock_init(&priv->hcmd_lock);
@@ -3928,13 +3915,12 @@
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 		    IEEE80211_HW_SPECTRUM_MGMT;
 
-	if (!priv->cfg->broken_powersave)
+	if (!priv->cfg->base_params->broken_powersave)
 		hw->flags |= IEEE80211_HW_SUPPORTS_PS |
 			     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
 	hw->wiphy->interface_modes =
-		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC);
+		priv->contexts[IWL_RXON_CTX_BSS].interface_modes;
 
 	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
 			    WIPHY_FLAG_DISABLE_BEACON_HINTS;
@@ -3966,7 +3952,7 @@
 
 static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	int err = 0;
+	int err = 0, i;
 	struct iwl_priv *priv;
 	struct ieee80211_hw *hw;
 	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
@@ -3988,12 +3974,33 @@
 	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) {
-		IWL_DEBUG_INFO(priv, "Disabling hw_scan\n");
+		IWL_ERR(priv, "sw scan support is deprecated\n");
 		iwl3945_hw_ops.hw_scan = NULL;
 	}
 
@@ -4009,6 +4016,9 @@
 	/***************************
 	 * 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;
@@ -4120,7 +4130,8 @@
 	}
 
 	iwl_set_rxon_channel(priv,
-			     &priv->bands[IEEE80211_BAND_2GHZ].channels[5]);
+			     &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);
@@ -4201,7 +4212,7 @@
 	 * paths to avoid running iwl_down() at all before leaving driver.
 	 * This (inexpensive) call *makes sure* device is reset.
 	 */
-	priv->cfg->ops->lib->apm_ops.stop(priv);
+	iwl_apm_stop(priv);
 
 	/* make sure we flush any pending irq or
 	 * tasklet for the driver
@@ -4245,8 +4256,8 @@
 	iwl_free_channel_map(priv);
 	iwlcore_free_geos(priv);
 	kfree(priv->scan_cmd);
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
 
 	ieee80211_free_hw(priv->hw);
 }
@@ -4314,7 +4325,8 @@
 #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)");
+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");
 
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
index 6061967..c6c0eff 100644
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
+++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
@@ -161,7 +161,7 @@
 }
 
 static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
-				u8 key_index, const u8 *mac_addr,
+				u8 key_index, bool pairwise, const u8 *mac_addr,
 				struct key_params *params)
 {
 	struct iwm_priv *iwm = ndev_to_iwm(ndev);
@@ -181,7 +181,8 @@
 }
 
 static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
-				u8 key_index, const u8 *mac_addr, void *cookie,
+				u8 key_index, bool pairwise, const u8 *mac_addr,
+				void *cookie,
 				void (*callback)(void *cookie,
 						 struct key_params*))
 {
@@ -206,7 +207,7 @@
 
 
 static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
-				u8 key_index, const u8 *mac_addr)
+				u8 key_index, bool pairwise, const u8 *mac_addr)
 {
 	struct iwm_priv *iwm = ndev_to_iwm(ndev);
 	struct iwm_key *key = &iwm->keys[key_index];
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
index 53b0b77..0a0cc96 100644
--- a/drivers/net/wireless/iwmc3200wifi/debugfs.c
+++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c
@@ -402,24 +402,28 @@
 	.owner =	THIS_MODULE,
 	.open =		iwm_generic_open,
 	.read =		iwm_debugfs_txq_read,
+	.llseek =	default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_tx_credit_fops = {
 	.owner =	THIS_MODULE,
 	.open =		iwm_generic_open,
 	.read =		iwm_debugfs_tx_credit_read,
+	.llseek =	default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_rx_ticket_fops = {
 	.owner =	THIS_MODULE,
 	.open =		iwm_generic_open,
 	.read =		iwm_debugfs_rx_ticket_read,
+	.llseek =	default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_fw_err_fops = {
 	.owner =	THIS_MODULE,
 	.open =		iwm_generic_open,
 	.read =		iwm_debugfs_fw_err_read,
+	.llseek =	default_llseek,
 };
 
 void iwm_debugfs_init(struct iwm_priv *iwm)
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index c02fced..a944893 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -1195,11 +1195,8 @@
 	IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: "
 		    "oid is 0x%x\n", hdr->oid);
 
-	if (hdr->oid <= WIFI_IF_NTFY_MAX) {
-		set_bit(hdr->oid, &iwm->wifi_ntfy[0]);
-		wake_up_interruptible(&iwm->wifi_ntfy_queue);
-	} else
-		return -EINVAL;
+	set_bit(hdr->oid, &iwm->wifi_ntfy[0]);
+	wake_up_interruptible(&iwm->wifi_ntfy_queue);
 
 	switch (hdr->oid) {
 	case UMAC_WIFI_IF_CMD_SET_PROFILE:
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c
index edcb523..56383e7 100644
--- a/drivers/net/wireless/iwmc3200wifi/sdio.c
+++ b/drivers/net/wireless/iwmc3200wifi/sdio.c
@@ -364,6 +364,7 @@
 	.owner =	THIS_MODULE,
 	.open =		iwm_debugfs_sdio_open,
 	.read =		iwm_debugfs_sdio_read,
+	.llseek =	default_llseek,
 };
 
 static void if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 3e82f16..5046a00 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -10,6 +10,7 @@
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/wait.h>
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
 #include <asm/unaligned.h>
@@ -480,7 +481,6 @@
 	struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
 	int bsssize;
 	const u8 *pos;
-	u16 nr_sets;
 	const u8 *tsfdesc;
 	int tsfsize;
 	int i;
@@ -489,12 +489,11 @@
 	lbs_deb_enter(LBS_DEB_CFG80211);
 
 	bsssize = get_unaligned_le16(&scanresp->bssdescriptsize);
-	nr_sets = le16_to_cpu(scanresp->nr_sets);
 
 	lbs_deb_scan("scan response: %d BSSs (%d bytes); resp size %d bytes\n",
-			nr_sets, bsssize, le16_to_cpu(resp->size));
+			scanresp->nr_sets, bsssize, le16_to_cpu(resp->size));
 
-	if (nr_sets == 0) {
+	if (scanresp->nr_sets == 0) {
 		ret = 0;
 		goto done;
 	}
@@ -526,20 +525,31 @@
 
 	pos = scanresp->bssdesc_and_tlvbuffer;
 
+	lbs_deb_hex(LBS_DEB_SCAN, "SCAN_RSP", scanresp->bssdesc_and_tlvbuffer,
+			scanresp->bssdescriptsize);
+
 	tsfdesc = pos + bsssize;
 	tsfsize = 4 + 8 * scanresp->nr_sets;
+	lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TSF", (u8 *) tsfdesc, tsfsize);
 
 	/* Validity check: we expect a Marvell-Local TLV */
 	i = get_unaligned_le16(tsfdesc);
 	tsfdesc += 2;
-	if (i != TLV_TYPE_TSFTIMESTAMP)
+	if (i != TLV_TYPE_TSFTIMESTAMP) {
+		lbs_deb_scan("scan response: invalid TSF Timestamp %d\n", i);
 		goto done;
+	}
+
 	/* Validity check: the TLV holds TSF values with 8 bytes each, so
 	 * the size in the TLV must match the nr_sets value */
 	i = get_unaligned_le16(tsfdesc);
 	tsfdesc += 2;
-	if (i / 8 != scanresp->nr_sets)
+	if (i / 8 != scanresp->nr_sets) {
+		lbs_deb_scan("scan response: invalid number of TSF timestamp "
+			     "sets (expected %d got %d)\n", scanresp->nr_sets,
+			     i / 8);
 		goto done;
+	}
 
 	for (i = 0; i < scanresp->nr_sets; i++) {
 		const u8 *bssid;
@@ -581,8 +591,11 @@
 			id = *pos++;
 			elen = *pos++;
 			left -= 2;
-			if (elen > left || elen == 0)
+			if (elen > left || elen == 0) {
+				lbs_deb_scan("scan response: invalid IE fmt\n");
 				goto done;
+			}
+
 			if (id == WLAN_EID_DS_PARAMS)
 				chan_no = *pos;
 			if (id == WLAN_EID_SSID) {
@@ -613,7 +626,9 @@
 					capa, intvl, ie, ielen,
 					LBS_SCAN_RSSI_TO_MBM(rssi),
 					GFP_KERNEL);
-		}
+		} else
+			lbs_deb_scan("scan response: missing BSS channel IE\n");
+
 		tsfdesc += 8;
 	}
 	ret = 0;
@@ -1103,7 +1118,7 @@
 	lbs_deb_hex(LBS_DEB_ASSOC, "Common Rates", tmp, pos - tmp);
 
 	/* add auth type TLV */
-	if (priv->fwrelease >= 0x09000000)
+	if (MRVL_FW_MAJOR_REV(priv->fwrelease) >= 9)
 		pos += lbs_add_auth_type_tlv(pos, sme->auth_type);
 
 	/* add WPA/WPA2 TLV */
@@ -1114,6 +1129,9 @@
 		(u16)(pos - (u8 *) &cmd->iebuf);
 	cmd->hdr.size = cpu_to_le16(len);
 
+	lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_CMD", (u8 *) cmd,
+			le16_to_cpu(cmd->hdr.size));
+
 	/* store for later use */
 	memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN);
 
@@ -1121,14 +1139,28 @@
 	if (ret)
 		goto done;
 
-
 	/* generate connect message to cfg80211 */
 
 	resp = (void *) cmd; /* recast for easier field access */
 	status = le16_to_cpu(resp->statuscode);
 
-	/* Convert statis code of old firmware */
-	if (priv->fwrelease < 0x09000000)
+	/* Older FW versions map the IEEE 802.11 Status Code in the association
+	 * response to the following values returned in resp->statuscode:
+	 *
+	 *    IEEE Status Code                Marvell Status Code
+	 *    0                       ->      0x0000 ASSOC_RESULT_SUCCESS
+	 *    13                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
+	 *    14                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
+	 *    15                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
+	 *    16                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
+	 *    others                  ->      0x0003 ASSOC_RESULT_REFUSED
+	 *
+	 * Other response codes:
+	 *    0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
+	 *    0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
+	 *                                    association response from the AP)
+	 */
+	if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) {
 		switch (status) {
 		case 0:
 			break;
@@ -1150,11 +1182,16 @@
 			break;
 		default:
 			lbs_deb_assoc("association failure %d\n", status);
-			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			/* v5 OLPC firmware does return the AP status code if
+			 * it's not one of the values above.  Let that through.
+			 */
+			break;
+		}
 	}
 
-	lbs_deb_assoc("status %d, capability 0x%04x\n", status,
-		      le16_to_cpu(resp->capability));
+	lbs_deb_assoc("status %d, statuscode 0x%04x, capability 0x%04x, "
+		      "aid 0x%04x\n", status, le16_to_cpu(resp->statuscode),
+		      le16_to_cpu(resp->capability), le16_to_cpu(resp->aid));
 
 	resp_ie_len = le16_to_cpu(resp->hdr.size)
 		- sizeof(resp->hdr)
@@ -1174,7 +1211,6 @@
 			netif_tx_wake_all_queues(priv->dev);
 	}
 
-
 done:
 	lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
 	return ret;
@@ -1404,7 +1440,7 @@
 
 
 static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
-			   u8 idx, const u8 *mac_addr,
+			   u8 idx, bool pairwise, const u8 *mac_addr,
 			   struct key_params *params)
 {
 	struct lbs_private *priv = wiphy_priv(wiphy);
@@ -1464,7 +1500,7 @@
 
 
 static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev,
-			   u8 key_index, const u8 *mac_addr)
+			   u8 key_index, bool pairwise, const u8 *mac_addr)
 {
 
 	lbs_deb_enter(LBS_DEB_CFG80211);
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 651a79c..fbf3b033 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -696,6 +696,7 @@
 	.open = open_file_generic, \
 	.read = (fread), \
 	.write = (fwrite), \
+	.llseek = generic_file_llseek, \
 }
 
 struct lbs_debugfs_files {
@@ -961,6 +962,7 @@
 	.open = open_file_generic,
 	.write = lbs_debugfs_write,
 	.read = lbs_debugfs_read,
+	.llseek = default_llseek,
 };
 
 /**
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 1d141fe..2ae752d 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -8,7 +8,14 @@
 #define _LBS_DECL_H_
 
 #include <linux/netdevice.h>
+#include <linux/firmware.h>
 
+/* Should be terminated by a NULL entry */
+struct lbs_fw_table {
+	int model;
+	const char *helper;
+	const char *fwname;
+};
 
 struct lbs_private;
 struct sk_buff;
@@ -53,4 +60,10 @@
 u32 lbs_fw_index_to_data_rate(u8 index);
 u8 lbs_data_rate_to_fw_index(u32 rate);
 
+int lbs_get_firmware(struct device *dev, const char *user_helper,
+			const char *user_mainfw, u32 card_model,
+			const struct lbs_fw_table *fw_table,
+			const struct firmware **helper,
+			const struct firmware **mainfw);
+
 #endif
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 9c29839..fc81211 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -28,7 +28,6 @@
 #include <linux/firmware.h>
 #include <linux/netdevice.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -48,7 +47,6 @@
 MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>");
 MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards");
 MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("libertas_cs_helper.fw");
 
 
 
@@ -61,9 +59,34 @@
 	struct lbs_private *priv;
 	void __iomem *iobase;
 	bool align_regs;
+	u32 model;
 };
 
 
+enum {
+	MODEL_UNKNOWN = 0x00,
+	MODEL_8305 = 0x01,
+	MODEL_8381 = 0x02,
+	MODEL_8385 = 0x03
+};
+
+static const struct lbs_fw_table fw_table[] = {
+	{ MODEL_8305, "libertas/cf8305.bin", NULL },
+	{ MODEL_8305, "libertas_cs_helper.fw", NULL },
+	{ MODEL_8381, "libertas/cf8381_helper.bin", "libertas/cf8381.bin" },
+	{ MODEL_8381, "libertas_cs_helper.fw", "libertas_cs.fw" },
+	{ MODEL_8385, "libertas/cf8385_helper.bin", "libertas/cf8385.bin" },
+	{ MODEL_8385, "libertas_cs_helper.fw", "libertas_cs.fw" },
+	{ 0, NULL, NULL }
+};
+MODULE_FIRMWARE("libertas/cf8305.bin");
+MODULE_FIRMWARE("libertas/cf8381_helper.bin");
+MODULE_FIRMWARE("libertas/cf8381.bin");
+MODULE_FIRMWARE("libertas/cf8385_helper.bin");
+MODULE_FIRMWARE("libertas/cf8385.bin");
+MODULE_FIRMWARE("libertas_cs_helper.fw");
+MODULE_FIRMWARE("libertas_cs.fw");
+
 
 /********************************************************************/
 /* Hardware access                                                  */
@@ -289,22 +312,19 @@
 #define CF8385_MANFID		0x02df
 #define CF8385_CARDID		0x8103
 
-static inline int if_cs_hw_is_cf8305(struct pcmcia_device *p_dev)
+/* FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when
+ * that gets fixed.  Currently there's no way to access it from the probe hook.
+ */
+static inline u32 get_model(u16 manf_id, u16 card_id)
 {
-	return (p_dev->manf_id == CF8305_MANFID &&
-		p_dev->card_id == CF8305_CARDID);
-}
-
-static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev)
-{
-	return (p_dev->manf_id == CF8381_MANFID &&
-		p_dev->card_id == CF8381_CARDID);
-}
-
-static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev)
-{
-	return (p_dev->manf_id == CF8385_MANFID &&
-		p_dev->card_id == CF8385_CARDID);
+	/* NOTE: keep in sync with if_cs_ids */
+	if (manf_id == CF8305_MANFID && card_id == CF8305_CARDID)
+		return MODEL_8305;
+	else if (manf_id == CF8381_MANFID && card_id == CF8381_CARDID)
+		return MODEL_8381;
+	else if (manf_id == CF8385_MANFID && card_id == CF8385_CARDID)
+		return MODEL_8385;
+	return MODEL_UNKNOWN;
 }
 
 /********************************************************************/
@@ -558,12 +578,11 @@
  *
  * Return 0 on success
  */
-static int if_cs_prog_helper(struct if_cs_card *card)
+static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw)
 {
 	int ret = 0;
 	int sent = 0;
 	u8  scratch;
-	const struct firmware *fw;
 
 	lbs_deb_enter(LBS_DEB_CS);
 
@@ -589,14 +608,6 @@
 		goto done;
 	}
 
-	/* TODO: make firmware file configurable */
-	ret = request_firmware(&fw, "libertas_cs_helper.fw",
-		&card->p_dev->dev);
-	if (ret) {
-		lbs_pr_err("can't load helper firmware\n");
-		ret = -ENODEV;
-		goto done;
-	}
 	lbs_deb_cs("helper size %td\n", fw->size);
 
 	/* "Set the 5 bytes of the helper image to 0" */
@@ -635,7 +646,7 @@
 		if (ret < 0) {
 			lbs_pr_err("can't download helper at 0x%x, ret %d\n",
 				sent, ret);
-			goto err_release;
+			goto done;
 		}
 
 		if (count == 0)
@@ -644,17 +655,14 @@
 		sent += count;
 	}
 
-err_release:
-	release_firmware(fw);
 done:
 	lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
 	return ret;
 }
 
 
-static int if_cs_prog_real(struct if_cs_card *card)
+static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw)
 {
-	const struct firmware *fw;
 	int ret = 0;
 	int retry = 0;
 	int len = 0;
@@ -662,21 +670,13 @@
 
 	lbs_deb_enter(LBS_DEB_CS);
 
-	/* TODO: make firmware file configurable */
-	ret = request_firmware(&fw, "libertas_cs.fw",
-		&card->p_dev->dev);
-	if (ret) {
-		lbs_pr_err("can't load firmware\n");
-		ret = -ENODEV;
-		goto done;
-	}
 	lbs_deb_cs("fw size %td\n", fw->size);
 
 	ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW,
 		IF_CS_SQ_HELPER_OK);
 	if (ret < 0) {
 		lbs_pr_err("helper firmware doesn't answer\n");
-		goto err_release;
+		goto done;
 	}
 
 	for (sent = 0; sent < fw->size; sent += len) {
@@ -691,7 +691,7 @@
 		if (retry > 20) {
 			lbs_pr_err("could not download firmware\n");
 			ret = -ENODEV;
-			goto err_release;
+			goto done;
 		}
 		if (retry) {
 			sent -= len;
@@ -710,7 +710,7 @@
 			IF_CS_BIT_COMMAND);
 		if (ret < 0) {
 			lbs_pr_err("can't download firmware at 0x%x\n", sent);
-			goto err_release;
+			goto done;
 		}
 	}
 
@@ -718,9 +718,6 @@
 	if (ret < 0)
 		lbs_pr_err("firmware download failed\n");
 
-err_release:
-	release_firmware(fw);
-
 done:
 	lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
 	return ret;
@@ -761,15 +758,6 @@
 }
 
 
-/********************************************************************/
-/* Card Services                                                    */
-/********************************************************************/
-
-/*
- * After a card is removed, if_cs_release() will unregister the
- * device, and release the PCMCIA configuration.  If the device is
- * still open, this will be postponed until it is closed.
- */
 static void if_cs_release(struct pcmcia_device *p_dev)
 {
 	struct if_cs_card *card = p_dev->priv;
@@ -785,31 +773,12 @@
 }
 
 
-/*
- * This creates an "instance" of the driver, allocating local data
- * structures for one device.  The device is registered with Card
- * Services.
- *
- * The dev_link 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 if_cs_ioprobe(struct pcmcia_device *p_dev,
-			 cistpl_cftable_entry_t *cfg,
-			 cistpl_cftable_entry_t *dflt,
-			 unsigned int vcc,
-			 void *priv_data)
+static int if_cs_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
 {
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
 	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
 
-	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	if (cfg->io.nwin != 1) {
+	if (p_dev->resource[1]->end) {
 		lbs_pr_err("wrong CIS (check number of IO windows)\n");
 		return -ENODEV;
 	}
@@ -824,6 +793,8 @@
 	unsigned int prod_id;
 	struct lbs_private *priv;
 	struct if_cs_card *card;
+	const struct firmware *helper = NULL;
+	const struct firmware *mainfw = NULL;
 
 	lbs_deb_enter(LBS_DEB_CS);
 
@@ -835,15 +806,13 @@
 	card->p_dev = p_dev;
 	p_dev->priv = card;
 
-	p_dev->conf.Attributes = 0;
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
+	p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
 	if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) {
 		lbs_pr_err("error in pcmcia_loop_config\n");
 		goto out1;
 	}
 
-
 	/*
 	 * Allocate an interrupt line.  Note that this does not assign
 	 * a handler to the interrupt, unless the 'Handler' member of
@@ -861,14 +830,9 @@
 		goto out1;
 	}
 
-	/*
-	 * 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.
-	 */
-	ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+	ret = pcmcia_enable_device(p_dev);
 	if (ret) {
-		lbs_pr_err("error in pcmcia_request_configuration\n");
+		lbs_pr_err("error in pcmcia_enable_device\n");
 		goto out2;
 	}
 
@@ -881,34 +845,47 @@
 	 */
 	card->align_regs = 0;
 
+	card->model = get_model(p_dev->manf_id, p_dev->card_id);
+	if (card->model == MODEL_UNKNOWN) {
+		lbs_pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n",
+			   p_dev->manf_id, p_dev->card_id);
+		goto out2;
+	}
+
 	/* Check if we have a current silicon */
 	prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID);
-	if (if_cs_hw_is_cf8305(p_dev)) {
+	if (card->model == MODEL_8305) {
 		card->align_regs = 1;
 		if (prod_id < IF_CS_CF8305_B1_REV) {
-			lbs_pr_err("old chips like 8305 rev B3 "
-				"aren't supported\n");
+			lbs_pr_err("8305 rev B0 and older are not supported\n");
 			ret = -ENODEV;
 			goto out2;
 		}
 	}
 
-	if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) {
-		lbs_pr_err("old chips like 8381 rev B3 aren't supported\n");
+	if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) {
+		lbs_pr_err("8381 rev B2 and older are not supported\n");
 		ret = -ENODEV;
 		goto out2;
 	}
 
-	if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) {
-		lbs_pr_err("old chips like 8385 rev B1 aren't supported\n");
+	if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) {
+		lbs_pr_err("8385 rev B0 and older are not supported\n");
 		ret = -ENODEV;
 		goto out2;
 	}
 
+	ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model,
+				&fw_table[0], &helper, &mainfw);
+	if (ret) {
+		lbs_pr_err("failed to find firmware (%d)\n", ret);
+		goto out2;
+	}
+
 	/* Load the firmware early, before calling into libertas.ko */
-	ret = if_cs_prog_helper(card);
-	if (ret == 0 && !if_cs_hw_is_cf8305(p_dev))
-		ret = if_cs_prog_real(card);
+	ret = if_cs_prog_helper(card, helper);
+	if (ret == 0 && (card->model != MODEL_8305))
+		ret = if_cs_prog_real(card, mainfw);
 	if (ret)
 		goto out2;
 
@@ -957,17 +934,16 @@
 out1:
 	pcmcia_disable_device(p_dev);
 out:
+	if (helper)
+		release_firmware(helper);
+	if (mainfw)
+		release_firmware(mainfw);
+
 	lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
 	return ret;
 }
 
 
-/*
- * 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 if_cs_detach(struct pcmcia_device *p_dev)
 {
 	struct if_cs_card *card = p_dev->priv;
@@ -993,6 +969,7 @@
 	PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID),
 	PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID),
 	PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID),
+	/* NOTE: keep in sync with get_model() */
 	PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
@@ -1000,9 +977,7 @@
 
 static struct pcmcia_driver lbs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= DRV_NAME,
-	},
+	.name		= DRV_NAME,
 	.probe		= if_cs_probe,
 	.remove		= if_cs_detach,
 	.id_table       = if_cs_ids,
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 87b6349..296fd00a 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -76,36 +76,32 @@
 
 MODULE_DEVICE_TABLE(sdio, if_sdio_ids);
 
-struct if_sdio_model {
-	int model;
-	const char *helper;
-	const char *firmware;
-};
+#define MODEL_8385	0x04
+#define MODEL_8686	0x0b
+#define MODEL_8688	0x10
 
-static struct if_sdio_model if_sdio_models[] = {
-	{
-		/* 8385 */
-		.model = IF_SDIO_MODEL_8385,
-		.helper = "sd8385_helper.bin",
-		.firmware = "sd8385.bin",
-	},
-	{
-		/* 8686 */
-		.model = IF_SDIO_MODEL_8686,
-		.helper = "sd8686_helper.bin",
-		.firmware = "sd8686.bin",
-	},
-	{
-		/* 8688 */
-		.model = IF_SDIO_MODEL_8688,
-		.helper = "sd8688_helper.bin",
-		.firmware = "sd8688.bin",
-	},
+static const struct lbs_fw_table fw_table[] = {
+	{ MODEL_8385, "libertas/sd8385_helper.bin", "libertas/sd8385.bin" },
+	{ MODEL_8385, "sd8385_helper.bin", "sd8385.bin" },
+	{ MODEL_8686, "libertas/sd8686_v9_helper.bin", "libertas/sd8686_v9.bin" },
+	{ MODEL_8686, "libertas/sd8686_v8_helper.bin", "libertas/sd8686_v8.bin" },
+	{ MODEL_8686, "sd8686_helper.bin", "sd8686.bin" },
+	{ MODEL_8688, "libertas/sd8688_helper.bin", "libertas/sd8688.bin" },
+	{ MODEL_8688, "sd8688_helper.bin", "sd8688.bin" },
+	{ 0, NULL, NULL }
 };
+MODULE_FIRMWARE("libertas/sd8385_helper.bin");
+MODULE_FIRMWARE("libertas/sd8385.bin");
 MODULE_FIRMWARE("sd8385_helper.bin");
 MODULE_FIRMWARE("sd8385.bin");
+MODULE_FIRMWARE("libertas/sd8686_v9_helper.bin");
+MODULE_FIRMWARE("libertas/sd8686_v9.bin");
+MODULE_FIRMWARE("libertas/sd8686_v8_helper.bin");
+MODULE_FIRMWARE("libertas/sd8686_v8.bin");
 MODULE_FIRMWARE("sd8686_helper.bin");
 MODULE_FIRMWARE("sd8686.bin");
+MODULE_FIRMWARE("libertas/sd8688_helper.bin");
+MODULE_FIRMWARE("libertas/sd8688.bin");
 MODULE_FIRMWARE("sd8688_helper.bin");
 MODULE_FIRMWARE("sd8688.bin");
 
@@ -187,11 +183,11 @@
 	u16 rx_len;
 
 	switch (card->model) {
-	case IF_SDIO_MODEL_8385:
-	case IF_SDIO_MODEL_8686:
+	case MODEL_8385:
+	case MODEL_8686:
 		rx_len = if_sdio_read_scratch(card, &ret);
 		break;
-	case IF_SDIO_MODEL_8688:
+	case MODEL_8688:
 	default: /* for newer chipsets */
 		rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret);
 		if (!ret)
@@ -288,7 +284,7 @@
 
 	lbs_deb_enter(LBS_DEB_SDIO);
 
-	if (card->model == IF_SDIO_MODEL_8385) {
+	if (card->model == MODEL_8385) {
 		event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);
 		if (ret)
 			goto out;
@@ -466,10 +462,10 @@
 
 #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY)
 
-static int if_sdio_prog_helper(struct if_sdio_card *card)
+static int if_sdio_prog_helper(struct if_sdio_card *card,
+				const struct firmware *fw)
 {
 	int ret;
-	const struct firmware *fw;
 	unsigned long timeout;
 	u8 *chunk_buffer;
 	u32 chunk_size;
@@ -478,16 +474,10 @@
 
 	lbs_deb_enter(LBS_DEB_SDIO);
 
-	ret = request_firmware(&fw, card->helper, &card->func->dev);
-	if (ret) {
-		lbs_pr_err("can't load helper firmware\n");
-		goto out;
-	}
-
 	chunk_buffer = kzalloc(64, GFP_KERNEL);
 	if (!chunk_buffer) {
 		ret = -ENOMEM;
-		goto release_fw;
+		goto out;
 	}
 
 	sdio_claim_host(card->func);
@@ -562,22 +552,19 @@
 release:
 	sdio_release_host(card->func);
 	kfree(chunk_buffer);
-release_fw:
-	release_firmware(fw);
 
 out:
 	if (ret)
 		lbs_pr_err("failed to load helper firmware\n");
 
 	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
 	return ret;
 }
 
-static int if_sdio_prog_real(struct if_sdio_card *card)
+static int if_sdio_prog_real(struct if_sdio_card *card,
+				const struct firmware *fw)
 {
 	int ret;
-	const struct firmware *fw;
 	unsigned long timeout;
 	u8 *chunk_buffer;
 	u32 chunk_size;
@@ -586,16 +573,10 @@
 
 	lbs_deb_enter(LBS_DEB_SDIO);
 
-	ret = request_firmware(&fw, card->firmware, &card->func->dev);
-	if (ret) {
-		lbs_pr_err("can't load firmware\n");
-		goto out;
-	}
-
 	chunk_buffer = kzalloc(512, GFP_KERNEL);
 	if (!chunk_buffer) {
 		ret = -ENOMEM;
-		goto release_fw;
+		goto out;
 	}
 
 	sdio_claim_host(card->func);
@@ -685,15 +666,12 @@
 release:
 	sdio_release_host(card->func);
 	kfree(chunk_buffer);
-release_fw:
-	release_firmware(fw);
 
 out:
 	if (ret)
 		lbs_pr_err("failed to load firmware\n");
 
 	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
 	return ret;
 }
 
@@ -701,6 +679,8 @@
 {
 	int ret;
 	u16 scratch;
+	const struct firmware *helper = NULL;
+	const struct firmware *mainfw = NULL;
 
 	lbs_deb_enter(LBS_DEB_SDIO);
 
@@ -718,11 +698,18 @@
 		goto success;
 	}
 
-	ret = if_sdio_prog_helper(card);
+	ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name,
+				card->model, &fw_table[0], &helper, &mainfw);
+	if (ret) {
+		lbs_pr_err("failed to find firmware (%d)\n", ret);
+		goto out;
+	}
+
+	ret = if_sdio_prog_helper(card, helper);
 	if (ret)
 		goto out;
 
-	ret = if_sdio_prog_real(card);
+	ret = if_sdio_prog_real(card, mainfw);
 	if (ret)
 		goto out;
 
@@ -733,8 +720,12 @@
 	ret = 0;
 
 out:
-	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+	if (helper)
+		release_firmware(helper);
+	if (mainfw)
+		release_firmware(mainfw);
 
+	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
 	return ret;
 }
 
@@ -938,7 +929,7 @@
 				"ID: %x", &model) == 1)
 			break;
 		if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) {
-			model = IF_SDIO_MODEL_8385;
+			model = MODEL_8385;
 			break;
 		}
 	}
@@ -956,13 +947,13 @@
 	card->model = model;
 
 	switch (card->model) {
-	case IF_SDIO_MODEL_8385:
+	case MODEL_8385:
 		card->scratch_reg = IF_SDIO_SCRATCH_OLD;
 		break;
-	case IF_SDIO_MODEL_8686:
+	case MODEL_8686:
 		card->scratch_reg = IF_SDIO_SCRATCH;
 		break;
-	case IF_SDIO_MODEL_8688:
+	case MODEL_8688:
 	default: /* for newer chipsets */
 		card->scratch_reg = IF_SDIO_FW_STATUS;
 		break;
@@ -972,49 +963,17 @@
 	card->workqueue = create_workqueue("libertas_sdio");
 	INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
 
-	for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) {
-		if (card->model == if_sdio_models[i].model)
+	/* Check if we support this card */
+	for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
+		if (card->model == fw_table[i].model)
 			break;
 	}
-
-	if (i == ARRAY_SIZE(if_sdio_models)) {
+	if (i == ARRAY_SIZE(fw_table)) {
 		lbs_pr_err("unknown card model 0x%x\n", card->model);
 		ret = -ENODEV;
 		goto free;
 	}
 
-	card->helper = if_sdio_models[i].helper;
-	card->firmware = if_sdio_models[i].firmware;
-
-	kparam_block_sysfs_write(helper_name);
-	if (lbs_helper_name) {
-		char *helper = kstrdup(lbs_helper_name, GFP_KERNEL);
-		if (!helper) {
-			kparam_unblock_sysfs_write(helper_name);
-			ret = -ENOMEM;
-			goto free;
-		}
-		lbs_deb_sdio("overriding helper firmware: %s\n",
-			lbs_helper_name);
-		card->helper = helper;
-		card->helper_allocated = true;
-	}
-	kparam_unblock_sysfs_write(helper_name);
-
-	kparam_block_sysfs_write(fw_name);
-	if (lbs_fw_name) {
-		char *fw_name = kstrdup(lbs_fw_name, GFP_KERNEL);
-		if (!fw_name) {
-			kparam_unblock_sysfs_write(fw_name);
-			ret = -ENOMEM;
-			goto free;
-		}
-		lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name);
-		card->firmware = fw_name;
-		card->firmware_allocated = true;
-	}
-	kparam_unblock_sysfs_write(fw_name);
-
 	sdio_claim_host(func);
 
 	ret = sdio_enable_func(func);
@@ -1028,7 +987,7 @@
 	/* For 1-bit transfers to the 8686 model, we need to enable the
 	 * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
 	 * bit to allow access to non-vendor registers. */
-	if ((card->model == IF_SDIO_MODEL_8686) &&
+	if ((card->model == MODEL_8686) &&
 	    (host->caps & MMC_CAP_SDIO_IRQ) &&
 	    (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
 		u8 reg;
@@ -1091,8 +1050,8 @@
 	 * Get rx_unit if the chip is SD8688 or newer.
 	 * SD8385 & SD8686 do not have rx_unit.
 	 */
-	if ((card->model != IF_SDIO_MODEL_8385)
-			&& (card->model != IF_SDIO_MODEL_8686))
+	if ((card->model != MODEL_8385)
+			&& (card->model != MODEL_8686))
 		card->rx_unit = if_sdio_read_rx_unit(card);
 	else
 		card->rx_unit = 0;
@@ -1108,7 +1067,7 @@
 	/*
 	 * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
 	 */
-	if (card->model == IF_SDIO_MODEL_8688) {
+	if (card->model == MODEL_8688) {
 		struct cmd_header cmd;
 
 		memset(&cmd, 0, sizeof(cmd));
@@ -1165,7 +1124,7 @@
 
 	card = sdio_get_drvdata(func);
 
-	if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) {
+	if (user_rmmod && (card->model == MODEL_8688)) {
 		/*
 		 * FUNC_SHUTDOWN is required for SD8688 WLAN/BT
 		 * multiple functions
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h
index 12179c1..62fda35 100644
--- a/drivers/net/wireless/libertas/if_sdio.h
+++ b/drivers/net/wireless/libertas/if_sdio.h
@@ -12,10 +12,6 @@
 #ifndef _LBS_IF_SDIO_H
 #define _LBS_IF_SDIO_H
 
-#define IF_SDIO_MODEL_8385	0x04
-#define IF_SDIO_MODEL_8686	0x0b
-#define IF_SDIO_MODEL_8688	0x10
-
 #define IF_SDIO_IOPORT		0x00
 
 #define IF_SDIO_H_INT_MASK	0x04
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index fe3f080..79bcb4e5 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -39,9 +39,6 @@
 	struct lbs_private		*priv;
 	struct libertas_spi_platform_data *pdata;
 
-	char				helper_fw_name[IF_SPI_FW_NAME_MAX];
-	char				main_fw_name[IF_SPI_FW_NAME_MAX];
-
 	/* The card ID and card revision, as reported by the hardware. */
 	u16				card_id;
 	u8				card_rev;
@@ -70,10 +67,28 @@
 	kfree(card);
 }
 
-static struct chip_ident chip_id_to_device_name[] = {
-	{ .chip_id = 0x04, .name = 8385 },
-	{ .chip_id = 0x0b, .name = 8686 },
+#define MODEL_8385	0x04
+#define MODEL_8686	0x0b
+#define MODEL_8688	0x10
+
+static const struct lbs_fw_table fw_table[] = {
+	{ MODEL_8385, "libertas/gspi8385_helper.bin", "libertas/gspi8385.bin" },
+	{ MODEL_8385, "libertas/gspi8385_hlp.bin", "libertas/gspi8385.bin" },
+	{ MODEL_8686, "libertas/gspi8686_v9_helper.bin", "libertas/gspi8686_v9.bin" },
+	{ MODEL_8686, "libertas/gspi8686_hlp.bin", "libertas/gspi8686.bin" },
+	{ MODEL_8688, "libertas/gspi8688_helper.bin", "libertas/gspi8688.bin" },
+	{ 0, NULL, NULL }
 };
+MODULE_FIRMWARE("libertas/gspi8385_helper.bin");
+MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
+MODULE_FIRMWARE("libertas/gspi8385.bin");
+MODULE_FIRMWARE("libertas/gspi8686_v9_helper.bin");
+MODULE_FIRMWARE("libertas/gspi8686_v9.bin");
+MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
+MODULE_FIRMWARE("libertas/gspi8686.bin");
+MODULE_FIRMWARE("libertas/gspi8688_helper.bin");
+MODULE_FIRMWARE("libertas/gspi8688.bin");
+
 
 /*
  * SPI Interface Unit Routines
@@ -399,26 +414,20 @@
  * Firmware Loading
  */
 
-static int if_spi_prog_helper_firmware(struct if_spi_card *card)
+static int if_spi_prog_helper_firmware(struct if_spi_card *card,
+					const struct firmware *firmware)
 {
 	int err = 0;
-	const struct firmware *firmware = NULL;
 	int bytes_remaining;
 	const u8 *fw;
 	u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
-	struct spi_device *spi = card->spi;
 
 	lbs_deb_enter(LBS_DEB_SPI);
 
 	err = spu_set_interrupt_mode(card, 1, 0);
 	if (err)
 		goto out;
-	/* Get helper firmware image */
-	err = request_firmware(&firmware, card->helper_fw_name, &spi->dev);
-	if (err) {
-		lbs_pr_err("request_firmware failed with err = %d\n", err);
-		goto out;
-	}
+
 	bytes_remaining = firmware->size;
 	fw = firmware->data;
 
@@ -429,13 +438,13 @@
 		err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,
 					HELPER_FW_LOAD_CHUNK_SZ);
 		if (err)
-			goto release_firmware;
+			goto out;
 
 		err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
 					IF_SPI_HIST_CMD_DOWNLOAD_RDY,
 					IF_SPI_HIST_CMD_DOWNLOAD_RDY);
 		if (err)
-			goto release_firmware;
+			goto out;
 
 		/* Feed the data into the command read/write port reg
 		 * in chunks of 64 bytes */
@@ -446,16 +455,16 @@
 		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
 					temp, HELPER_FW_LOAD_CHUNK_SZ);
 		if (err)
-			goto release_firmware;
+			goto out;
 
 		/* Interrupt the boot code */
 		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
 		if (err)
-			goto release_firmware;
+			goto out;
 		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
 				       IF_SPI_CIC_CMD_DOWNLOAD_OVER);
 		if (err)
-			goto release_firmware;
+			goto out;
 		bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ;
 		fw += HELPER_FW_LOAD_CHUNK_SZ;
 	}
@@ -465,18 +474,16 @@
 	 * bootloader. This completes the helper download. */
 	err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);
 	if (err)
-		goto release_firmware;
+		goto out;
 	err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
 	if (err)
-		goto release_firmware;
+		goto out;
 	err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
 				IF_SPI_CIC_CMD_DOWNLOAD_OVER);
-		goto release_firmware;
+		goto out;
 
 	lbs_deb_spi("waiting for helper to boot...\n");
 
-release_firmware:
-	release_firmware(firmware);
 out:
 	if (err)
 		lbs_pr_err("failed to load helper firmware (err=%d)\n", err);
@@ -523,13 +530,12 @@
 	return len;
 }
 
-static int if_spi_prog_main_firmware(struct if_spi_card *card)
+static int if_spi_prog_main_firmware(struct if_spi_card *card,
+					const struct firmware *firmware)
 {
 	int len, prev_len;
 	int bytes, crc_err = 0, err = 0;
-	const struct firmware *firmware = NULL;
 	const u8 *fw;
-	struct spi_device *spi = card->spi;
 	u16 num_crc_errs;
 
 	lbs_deb_enter(LBS_DEB_SPI);
@@ -538,19 +544,11 @@
 	if (err)
 		goto out;
 
-	/* Get firmware image */
-	err = request_firmware(&firmware, card->main_fw_name, &spi->dev);
-	if (err) {
-		lbs_pr_err("%s: can't get firmware '%s' from kernel. "
-			"err = %d\n", __func__, card->main_fw_name, err);
-		goto out;
-	}
-
 	err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);
 	if (err) {
 		lbs_pr_err("%s: timed out waiting for initial "
 			   "scratch reg = 0\n", __func__);
-		goto release_firmware;
+		goto out;
 	}
 
 	num_crc_errs = 0;
@@ -560,7 +558,7 @@
 	while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) {
 		if (len < 0) {
 			err = len;
-			goto release_firmware;
+			goto out;
 		}
 		if (bytes < 0) {
 			/* If there are no more bytes left, we would normally
@@ -575,7 +573,7 @@
 				lbs_pr_err("Too many CRC errors encountered "
 					   "in firmware load.\n");
 				err = -EIO;
-				goto release_firmware;
+				goto out;
 			}
 		} else {
 			/* Previous transfer succeeded. Advance counters. */
@@ -590,15 +588,15 @@
 
 		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
 		if (err)
-			goto release_firmware;
+			goto out;
 		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
 				card->cmd_buffer, len);
 		if (err)
-			goto release_firmware;
+			goto out;
 		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG ,
 					IF_SPI_CIC_CMD_DOWNLOAD_OVER);
 		if (err)
-			goto release_firmware;
+			goto out;
 		prev_len = len;
 	}
 	if (bytes > prev_len) {
@@ -611,12 +609,9 @@
 					SUCCESSFUL_FW_DOWNLOAD_MAGIC);
 	if (err) {
 		lbs_pr_err("failed to confirm the firmware download\n");
-		goto release_firmware;
+		goto out;
 	}
 
-release_firmware:
-	release_firmware(firmware);
-
 out:
 	if (err)
 		lbs_pr_err("failed to load firmware (err=%d)\n", err);
@@ -800,14 +795,16 @@
 			goto err;
 		}
 
-		if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY)
+		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)
+		}
+		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. */
@@ -886,37 +883,16 @@
  * SPI callbacks
  */
 
-static int if_spi_calculate_fw_names(u16 card_id,
-			      char *helper_fw, char *main_fw)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) {
-		if (card_id == chip_id_to_device_name[i].chip_id)
-			break;
-	}
-	if (i == ARRAY_SIZE(chip_id_to_device_name)) {
-		lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id);
-		return -EAFNOSUPPORT;
-	}
-	snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin",
-		 chip_id_to_device_name[i].name);
-	snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin",
-		 chip_id_to_device_name[i].name);
-	return 0;
-}
-MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
-MODULE_FIRMWARE("libertas/gspi8385.bin");
-MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
-MODULE_FIRMWARE("libertas/gspi8686.bin");
-
 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;
+	int err = 0, 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);
 
@@ -961,10 +937,25 @@
 		lbs_deb_spi("Firmware is already loaded for "
 			    "Marvell WLAN 802.11 adapter\n");
 	else {
-		err = if_spi_calculate_fw_names(card->card_id,
-				card->helper_fw_name, card->main_fw_name);
-		if (err)
+		/* Check if we support this card */
+		for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
+			if (card->card_id == fw_table[i].model)
+				break;
+		}
+		if (i == ARRAY_SIZE(fw_table)) {
+			lbs_pr_err("Unsupported chip_id: 0x%02x\n",
+					card->card_id);
+			err = -ENODEV;
 			goto free_card;
+		}
+
+		err = lbs_get_firmware(&card->spi->dev, NULL, NULL,
+					card->card_id, &fw_table[0], &helper,
+					&mainfw);
+		if (err) {
+			lbs_pr_err("failed to find firmware (%d)\n", err);
+			goto free_card;
+		}
 
 		lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
 				"(chip_id = 0x%04x, chip_rev = 0x%02x) "
@@ -973,10 +964,10 @@
 				card->card_id, card->card_rev,
 				spi->master->bus_num, spi->chip_select,
 				spi->max_speed_hz);
-		err = if_spi_prog_helper_firmware(card);
+		err = if_spi_prog_helper_firmware(card, helper);
 		if (err)
 			goto free_card;
-		err = if_spi_prog_main_firmware(card);
+		err = if_spi_prog_main_firmware(card, mainfw);
 		if (err)
 			goto free_card;
 		lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
@@ -1044,6 +1035,11 @@
 free_card:
 	free_if_spi_card(card);
 out:
+	if (helper)
+		release_firmware(helper);
+	if (mainfw)
+		release_firmware(mainfw);
+
 	lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
 	return err;
 }
diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h
index f87eec4..8b1417d 100644
--- a/drivers/net/wireless/libertas/if_spi.h
+++ b/drivers/net/wireless/libertas/if_spi.h
@@ -25,11 +25,6 @@
 
 #define IF_SPI_FW_NAME_MAX 30
 
-struct chip_ident {
-	u16 chip_id;
-	u16 name;
-};
-
 #define MAX_MAIN_FW_LOAD_CRC_ERR 10
 
 /* Chunk size when loading the helper firmware */
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 3ff6106..efaf850 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -26,15 +26,25 @@
 
 #define MESSAGE_HEADER_LEN	4
 
-static char *lbs_fw_name = "usb8388.bin";
+static char *lbs_fw_name = NULL;
 module_param_named(fw_name, lbs_fw_name, charp, 0644);
 
+MODULE_FIRMWARE("libertas/usb8388_v9.bin");
+MODULE_FIRMWARE("libertas/usb8388_v5.bin");
+MODULE_FIRMWARE("libertas/usb8388.bin");
+MODULE_FIRMWARE("libertas/usb8682.bin");
 MODULE_FIRMWARE("usb8388.bin");
 
+enum {
+	MODEL_UNKNOWN = 0x0,
+	MODEL_8388 = 0x1,
+	MODEL_8682 = 0x2
+};
+
 static struct usb_device_id if_usb_table[] = {
 	/* Enter the device signature inside */
-	{ USB_DEVICE(0x1286, 0x2001) },
-	{ USB_DEVICE(0x05a3, 0x8388) },
+	{ USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 },
+	{ USB_DEVICE(0x05a3, 0x8388), .driver_info = MODEL_8388 },
 	{}	/* Terminating entry */
 };
 
@@ -66,6 +76,8 @@
 	struct if_usb_card *cardp = priv->card;
 	int ret;
 
+	BUG_ON(buf == NULL);
+
 	ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW);
 	if (ret == 0)
 		return count;
@@ -91,6 +103,8 @@
 	struct if_usb_card *cardp = priv->card;
 	int ret;
 
+	BUG_ON(buf == NULL);
+
 	ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2);
 	if (ret == 0)
 		return count;
@@ -244,6 +258,7 @@
 	init_waitqueue_head(&cardp->fw_wq);
 
 	cardp->udev = udev;
+	cardp->model = (uint32_t) id->driver_info;
 	iface_desc = intf->cur_altsetting;
 
 	lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
@@ -472,11 +487,12 @@
  */
 static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb)
 {
-	int ret = -1;
+	int ret;
 
 	/* check if device is removed */
 	if (cardp->surprise_removed) {
 		lbs_deb_usbd(&cardp->udev->dev, "Device removed\n");
+		ret = -ENODEV;
 		goto tx_ret;
 	}
 
@@ -489,7 +505,6 @@
 
 	if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
 		lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
-		ret = -1;
 	} else {
 		lbs_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
 		ret = 0;
@@ -924,6 +939,38 @@
 	return ret;
 }
 
+/* table of firmware file names */
+static const struct {
+	u32 model;
+	const char *fwname;
+} fw_table[] = {
+	{ MODEL_8388, "libertas/usb8388_v9.bin" },
+	{ MODEL_8388, "libertas/usb8388_v5.bin" },
+	{ MODEL_8388, "libertas/usb8388.bin" },
+	{ MODEL_8388, "usb8388.bin" },
+	{ MODEL_8682, "libertas/usb8682.bin" }
+};
+
+static int get_fw(struct if_usb_card *cardp, const char *fwname)
+{
+	int i;
+
+	/* Try user-specified firmware first */
+	if (fwname)
+		return request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
+
+	/* Otherwise search for firmware to use */
+	for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
+		if (fw_table[i].model != cardp->model)
+			continue;
+		if (request_firmware(&cardp->fw, fw_table[i].fwname,
+					&cardp->udev->dev) == 0)
+			return 0;
+	}
+
+	return -ENOENT;
+}
+
 static int __if_usb_prog_firmware(struct if_usb_card *cardp,
 					const char *fwname, int cmd)
 {
@@ -933,10 +980,9 @@
 
 	lbs_deb_enter(LBS_DEB_USB);
 
-	ret = request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
-	if (ret < 0) {
-		lbs_pr_err("request_firmware() failed with %#x\n", ret);
-		lbs_pr_err("firmware %s not found\n", fwname);
+	ret = get_fw(cardp, fwname);
+	if (ret) {
+		lbs_pr_err("failed to find firmware (%d)\n", ret);
 		goto done;
 	}
 
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
index 5ba0aee..d819e7e 100644
--- a/drivers/net/wireless/libertas/if_usb.h
+++ b/drivers/net/wireless/libertas/if_usb.h
@@ -43,6 +43,7 @@
 /** USB card description structure*/
 struct if_usb_card {
 	struct usb_device *udev;
+	uint32_t model;  /* MODEL_* */
 	struct urb *rx_urb, *tx_urb;
 	struct lbs_private *priv;
 
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 24958a8..47ce5a6 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1047,6 +1047,111 @@
 }
 EXPORT_SYMBOL_GPL(lbs_notify_command_response);
 
+/**
+ *  @brief Retrieves two-stage firmware
+ *
+ *  @param dev     	A pointer to device structure
+ *  @param user_helper	User-defined helper firmware file
+ *  @param user_mainfw	User-defined main firmware file
+ *  @param card_model	Bus-specific card model ID used to filter firmware table
+ *                         elements
+ *  @param fw_table	Table of firmware file names and device model numbers
+ *                         terminated by an entry with a NULL helper name
+ *  @param helper	On success, the helper firmware; caller must free
+ *  @param mainfw	On success, the main firmware; caller must free
+ *
+ *  @return		0 on success, non-zero on failure
+ */
+int lbs_get_firmware(struct device *dev, const char *user_helper,
+			const char *user_mainfw, u32 card_model,
+			const struct lbs_fw_table *fw_table,
+			const struct firmware **helper,
+			const struct firmware **mainfw)
+{
+	const struct lbs_fw_table *iter;
+	int ret;
+
+	BUG_ON(helper == NULL);
+	BUG_ON(mainfw == NULL);
+
+	/* Try user-specified firmware first */
+	if (user_helper) {
+		ret = request_firmware(helper, user_helper, dev);
+		if (ret) {
+			lbs_pr_err("couldn't find helper firmware %s",
+					user_helper);
+			goto fail;
+		}
+	}
+	if (user_mainfw) {
+		ret = request_firmware(mainfw, user_mainfw, dev);
+		if (ret) {
+			lbs_pr_err("couldn't find main firmware %s",
+					user_mainfw);
+			goto fail;
+		}
+	}
+
+	if (*helper && *mainfw)
+		return 0;
+
+	/* Otherwise search for firmware to use.  If neither the helper or
+	 * the main firmware were specified by the user, then we need to
+	 * make sure that found helper & main are from the same entry in
+	 * fw_table.
+	 */
+	iter = fw_table;
+	while (iter && iter->helper) {
+		if (iter->model != card_model)
+			goto next;
+
+		if (*helper == NULL) {
+			ret = request_firmware(helper, iter->helper, dev);
+			if (ret)
+				goto next;
+
+			/* If the device has one-stage firmware (ie cf8305) and
+			 * we've got it then we don't need to bother with the
+			 * main firmware.
+			 */
+			if (iter->fwname == NULL)
+				return 0;
+		}
+
+		if (*mainfw == NULL) {
+			ret = request_firmware(mainfw, iter->fwname, dev);
+			if (ret && !user_helper) {
+				/* Clear the helper if it wasn't user-specified
+				 * and the main firmware load failed, to ensure
+				 * we don't have mismatched firmware pairs.
+				 */
+				release_firmware(*helper);
+				*helper = NULL;
+			}
+		}
+
+		if (*helper && *mainfw)
+			return 0;
+
+  next:
+		iter++;
+	}
+
+  fail:
+	/* Failed */
+	if (*helper) {
+		release_firmware(*helper);
+		*helper = NULL;
+	}
+	if (*mainfw) {
+		release_firmware(*mainfw);
+		*mainfw = NULL;
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(lbs_get_firmware);
+
 static int __init lbs_init_module(void)
 {
 	lbs_deb_enter(LBS_DEB_MAIN);
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 194762a..acf3bf6 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -574,7 +574,7 @@
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
-	cmd.id = !!inverted;
+	cmd.id = cpu_to_le32(!!inverted);
 
 	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
 
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c
index 41a4f21..ba7d965 100644
--- a/drivers/net/wireless/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/libertas_tf/if_usb.c
@@ -54,7 +54,7 @@
 /**
  *  if_usb_wrike_bulk_callback -  call back to handle URB status
  *
- *  @param urb 		pointer to urb structure
+ *  @param urb		pointer to urb structure
  */
 static void if_usb_write_bulk_callback(struct urb *urb)
 {
@@ -178,16 +178,19 @@
 				le16_to_cpu(endpoint->wMaxPacketSize);
 			cardp->ep_in = usb_endpoint_num(endpoint);
 
-			lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in);
-			lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size);
+			lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n",
+				cardp->ep_in);
+			lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n",
+				cardp->ep_in_size);
 		} else if (usb_endpoint_is_bulk_out(endpoint)) {
 			cardp->ep_out_size =
 				le16_to_cpu(endpoint->wMaxPacketSize);
 			cardp->ep_out = usb_endpoint_num(endpoint);
 
-			lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out);
+			lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n",
+				cardp->ep_out);
 			lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n",
-			              cardp->ep_out_size);
+				cardp->ep_out_size);
 		}
 	}
 	if (!cardp->ep_out_size || !cardp->ep_in_size) {
@@ -318,10 +321,12 @@
 
 	if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
 		lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n");
-		lbtf_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n",
-			     cardp->fwseqnum, cardp->totalbytes);
+		lbtf_deb_usb2(&cardp->udev->dev,
+			"seqnum = %d totalbytes = %d\n",
+			cardp->fwseqnum, cardp->totalbytes);
 	} else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
-		lbtf_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n");
+		lbtf_deb_usb2(&cardp->udev->dev,
+			"Host has finished FW downloading\n");
 		lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n");
 
 		/* Host has finished FW downloading
@@ -367,7 +372,7 @@
 /**
  *  usb_tx_block - transfer data to the device
  *
- *  @priv 	pointer to struct lbtf_private
+ *  @priv	pointer to struct lbtf_private
  *  @payload	pointer to payload data
  *  @nb		data length
  *  @data	non-zero for data, zero for commands
@@ -400,7 +405,8 @@
 	urb->transfer_flags |= URB_ZERO_PACKET;
 
 	if (usb_submit_urb(urb, GFP_ATOMIC)) {
-		lbtf_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
+		lbtf_deb_usbd(&cardp->udev->dev,
+			"usb_submit_urb failed: %d\n", ret);
 		goto tx_ret;
 	}
 
@@ -438,10 +444,12 @@
 
 	cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
 
-	lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
+	lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n",
+		cardp->rx_urb);
 	ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC);
 	if (ret) {
-		lbtf_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret);
+		lbtf_deb_usbd(&cardp->udev->dev,
+			"Submit Rx URB failed: %d\n", ret);
 		kfree_skb(skb);
 		cardp->rx_skb = NULL;
 		lbtf_deb_leave(LBTF_DEB_USB);
@@ -522,14 +530,14 @@
 			}
 		} else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) {
 			pr_info("boot cmd response cmd_tag error (%d)\n",
-				    bcmdresp.cmd);
+				bcmdresp.cmd);
 		} else if (bcmdresp.result != BOOT_CMD_RESP_OK) {
 			pr_info("boot cmd response result error (%d)\n",
-				    bcmdresp.result);
+				bcmdresp.result);
 		} else {
 			cardp->bootcmdresp = 1;
 			lbtf_deb_usbd(&cardp->udev->dev,
-				     "Received valid boot command response\n");
+				"Received valid boot command response\n");
 		}
 
 		kfree_skb(skb);
@@ -541,19 +549,23 @@
 	syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader),
 			       GFP_ATOMIC);
 	if (!syncfwheader) {
-		lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
+		lbtf_deb_usbd(&cardp->udev->dev,
+			"Failure to allocate syncfwheader\n");
 		kfree_skb(skb);
 		lbtf_deb_leave(LBTF_DEB_USB);
 		return;
 	}
 
 	if (!syncfwheader->cmd) {
-		lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
-		lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
-			     le32_to_cpu(syncfwheader->seqnum));
+		lbtf_deb_usb2(&cardp->udev->dev,
+			"FW received Blk with correct CRC\n");
+		lbtf_deb_usb2(&cardp->udev->dev,
+			"FW received Blk seqnum = %d\n",
+			le32_to_cpu(syncfwheader->seqnum));
 		cardp->CRC_OK = 1;
 	} else {
-		lbtf_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n");
+		lbtf_deb_usbd(&cardp->udev->dev,
+			"FW received Blk with CRC error\n");
 		cardp->CRC_OK = 0;
 	}
 
@@ -666,7 +678,8 @@
 	{
 		/* Event cause handling */
 		u32 event_cause = le32_to_cpu(pkt[1]);
-		lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event_cause);
+		lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n",
+			event_cause);
 
 		/* Icky undocumented magic special case */
 		if (event_cause & 0xffff0000) {
@@ -689,7 +702,7 @@
 	}
 	default:
 		lbtf_deb_usbd(&cardp->udev->dev,
-		         "libertastf: unknown command type 0x%X\n", recvtype);
+			"libertastf: unknown command type 0x%X\n", recvtype);
 		kfree_skb(skb);
 		break;
 	}
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 86fa8ab..7eaaa3b 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -9,7 +9,8 @@
 
 /*
  * TODO:
- * - IBSS mode simulation (Beacon transmission with competition for "air time")
+ * - Add TSF sync and fix IBSS beacon transmission by adding
+ *   competition for "air time" at TBTT
  * - RX filtering based on filter configuration (data->rx_filter)
  */
 
@@ -594,17 +595,34 @@
 					struct ieee80211_vif *vif)
 {
 	wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
-		    __func__, vif->type, vif->addr);
+		    __func__, ieee80211_vif_type_p2p(vif),
+		    vif->addr);
 	hwsim_set_magic(vif);
 	return 0;
 }
 
 
+static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw,
+					   struct ieee80211_vif *vif,
+					   enum nl80211_iftype newtype,
+					   bool newp2p)
+{
+	newtype = ieee80211_iftype_p2p(newtype, newp2p);
+	wiphy_debug(hw->wiphy,
+		    "%s (old type=%d, new type=%d, mac_addr=%pM)\n",
+		    __func__, ieee80211_vif_type_p2p(vif),
+		    newtype, vif->addr);
+	hwsim_check_magic(vif);
+
+	return 0;
+}
+
 static void mac80211_hwsim_remove_interface(
 	struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
 	wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
-		    __func__, vif->type, vif->addr);
+		    __func__, ieee80211_vif_type_p2p(vif),
+		    vif->addr);
 	hwsim_check_magic(vif);
 	hwsim_clear_magic(vif);
 }
@@ -620,7 +638,8 @@
 	hwsim_check_magic(vif);
 
 	if (vif->type != NL80211_IFTYPE_AP &&
-	    vif->type != NL80211_IFTYPE_MESH_POINT)
+	    vif->type != NL80211_IFTYPE_MESH_POINT &&
+	    vif->type != NL80211_IFTYPE_ADHOC)
 		return;
 
 	skb = ieee80211_beacon_get(hw, vif);
@@ -1025,6 +1044,7 @@
 	.start = mac80211_hwsim_start,
 	.stop = mac80211_hwsim_stop,
 	.add_interface = mac80211_hwsim_add_interface,
+	.change_interface = mac80211_hwsim_change_interface,
 	.remove_interface = mac80211_hwsim_remove_interface,
 	.config = mac80211_hwsim_config,
 	.configure_filter = mac80211_hwsim_configure_filter,
@@ -1295,6 +1315,9 @@
 		hw->wiphy->interface_modes =
 			BIT(NL80211_IFTYPE_STATION) |
 			BIT(NL80211_IFTYPE_AP) |
+			BIT(NL80211_IFTYPE_P2P_CLIENT) |
+			BIT(NL80211_IFTYPE_P2P_GO) |
+			BIT(NL80211_IFTYPE_ADHOC) |
 			BIT(NL80211_IFTYPE_MESH_POINT);
 
 		hw->flags = IEEE80211_HW_MFP_CAPABLE |
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 077baa8..b4772c1 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -762,14 +762,17 @@
 	case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
 	case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
 		for (i = 0; i < BITRATE_TABLE_SIZE; i++)
-			if (bitrate_table[i].intersil_txratectrl == val)
+			if (bitrate_table[i].intersil_txratectrl == val) {
+				*bitrate = bitrate_table[i].bitrate * 100000;
 				break;
+			}
 
-		if (i >= BITRATE_TABLE_SIZE)
+		if (i >= BITRATE_TABLE_SIZE) {
 			printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
 			       priv->ndev->name, val);
+			err = -EIO;
+		}
 
-		*bitrate = bitrate_table[i].bitrate * 100000;
 		break;
 	default:
 		BUG();
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index ef46a2d..71b3d68 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -93,14 +92,6 @@
 /* PCMCIA stuff     						    */
 /********************************************************************/
 
-/*
- * This creates an "instance" of the driver, allocating local data
- * structures for one device.  The device is registered with Card
- * Services.
- *
- * The dev_link 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
 orinoco_cs_probe(struct pcmcia_device *link)
 {
@@ -117,23 +108,9 @@
 	card->p_dev = link;
 	link->priv = priv;
 
-	/* General socket configuration defaults can go here.  In this
-	 * client, we assume very little, and rely on the CIS for
-	 * almost everything.  In most clients, many details (i.e.,
-	 * number, sizes, and attributes of IO windows) are fixed by
-	 * the nature of the device, and can be hard-wired here. */
-	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	return orinoco_cs_config(link);
 }				/* orinoco_cs_attach */
 
-/*
- * This deletes a driver "instance".  The device is de-registered with
- * Card Services.  If it has been released, all local data structures
- * are freed.  Otherwise, the structures will be freed when the device
- * is released.
- */
 static void orinoco_cs_detach(struct pcmcia_device *link)
 {
 	struct orinoco_private *priv = link->priv;
@@ -145,76 +122,12 @@
 	free_orinocodev(priv);
 }				/* orinoco_cs_detach */
 
-/*
- * orinoco_cs_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.
- */
-
-static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
-				   cistpl_cftable_entry_t *cfg,
-				   cistpl_cftable_entry_t *dflt,
-				   unsigned int vcc,
-				   void *priv_data)
+static int orinoco_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		goto next_entry;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Use power settings for Vcc and Vpp if present */
-	/* Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-			DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-			      __func__, vcc,
-			      cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
-			if (!ignore_cis_vcc)
-				goto next_entry;
-		}
-	} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-			DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-			      __func__, vcc,
-			      dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
-			if (!ignore_cis_vcc)
-				goto next_entry;
-		}
-	}
-
-	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
-			cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
-			dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-
-		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev) != 0)
-			goto next_entry;
-	}
-	return 0;
-
-next_entry:
-	pcmcia_disable_device(p_dev);
-	return -ENODEV;
+	return pcmcia_request_io(p_dev);
 };
 
 static int
@@ -225,20 +138,10 @@
 	int ret;
 	void __iomem *mem;
 
-	/*
-	 * 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.
-	 */
+	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
+		CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+	if (ignore_cis_vcc)
+		link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 	ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
 	if (ret) {
 		if (!ignore_cis_vcc)
@@ -262,12 +165,7 @@
 
 	hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
 
-	/*
-	 * 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.
-	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -291,11 +189,6 @@
 	return -ENODEV;
 }				/* orinoco_cs_config */
 
-/*
- * After a card is removed, orinoco_cs_release() will unregister the
- * device, and release the PCMCIA configuration.  If the device is
- * still open, this will be postponed until it is closed.
- */
 static void
 orinoco_cs_release(struct pcmcia_device *link)
 {
@@ -344,12 +237,6 @@
 /* Module initialization					    */
 /********************************************************************/
 
-/* Can't be declared "const" or the whole __initdata section will
- * become const */
-static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
-	" (David Gibson <hermes@gibson.dropbear.id.au>, "
-	"Pavel Roskin <proski@gnu.org>, et al)";
-
 static struct pcmcia_device_id orinoco_cs_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
 	PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
@@ -441,9 +328,7 @@
 
 static struct pcmcia_driver orinoco_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= DRIVER_NAME,
-	},
+	.name		= DRIVER_NAME,
 	.probe		= orinoco_cs_probe,
 	.remove		= orinoco_cs_detach,
 	.id_table       = orinoco_cs_ids,
@@ -454,8 +339,6 @@
 static int __init
 init_orinoco_cs(void)
 {
-	printk(KERN_DEBUG "%s\n", version);
-
 	return pcmcia_register_driver(&orinoco_driver);
 }
 
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 873877e..fb859a5 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -154,14 +153,6 @@
 /* PCMCIA stuff     						    */
 /********************************************************************/
 
-/*
- * This creates an "instance" of the driver, allocating local data
- * structures for one device.  The device is registered with Card
- * Services.
- *
- * The dev_link 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
 spectrum_cs_probe(struct pcmcia_device *link)
 {
@@ -179,23 +170,9 @@
 	card->p_dev = link;
 	link->priv = priv;
 
-	/* General socket configuration defaults can go here.  In this
-	 * client, we assume very little, and rely on the CIS for
-	 * almost everything.  In most clients, many details (i.e.,
-	 * number, sizes, and attributes of IO windows) are fixed by
-	 * the nature of the device, and can be hard-wired here. */
-	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	return spectrum_cs_config(link);
 }				/* spectrum_cs_attach */
 
-/*
- * This deletes a driver "instance".  The device is de-registered with
- * Card Services.  If it has been released, all local data structures
- * are freed.  Otherwise, the structures will be freed when the device
- * is released.
- */
 static void spectrum_cs_detach(struct pcmcia_device *link)
 {
 	struct orinoco_private *priv = link->priv;
@@ -207,76 +184,13 @@
 	free_orinocodev(priv);
 }				/* spectrum_cs_detach */
 
-/*
- * spectrum_cs_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.
- */
-
 static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
-				    cistpl_cftable_entry_t *cfg,
-				    cistpl_cftable_entry_t *dflt,
-				    unsigned int vcc,
 				    void *priv_data)
 {
-	if (cfg->index == 0)
-		goto next_entry;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Use power settings for Vcc and Vpp if present */
-	/* Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-			DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-			      __func__, vcc,
-			      cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
-			if (!ignore_cis_vcc)
-				goto next_entry;
-		}
-	} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-			DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-			      __func__, vcc,
-			      dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
-			if (!ignore_cis_vcc)
-				goto next_entry;
-		}
-	}
-
-	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
-			cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
-			dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-
-		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev) != 0)
-			goto next_entry;
-	}
-	return 0;
-
-next_entry:
-	pcmcia_disable_device(p_dev);
-	return -ENODEV;
+	return pcmcia_request_io(p_dev);
 };
 
 static int
@@ -287,20 +201,10 @@
 	int ret;
 	void __iomem *mem;
 
-	/*
-	 * 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.
-	 */
+	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
+		CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+	if (ignore_cis_vcc)
+		link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 	ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
 	if (ret) {
 		if (!ignore_cis_vcc)
@@ -325,12 +229,7 @@
 	hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
 	hw->eeprom_pda = true;
 
-	/*
-	 * 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.
-	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -358,11 +257,6 @@
 	return -ENODEV;
 }				/* spectrum_cs_config */
 
-/*
- * After a card is removed, spectrum_cs_release() will unregister the
- * device, and release the PCMCIA configuration.  If the device is
- * still open, this will be postponed until it is closed.
- */
 static void
 spectrum_cs_release(struct pcmcia_device *link)
 {
@@ -407,12 +301,6 @@
 /* Module initialization					    */
 /********************************************************************/
 
-/* Can't be declared "const" or the whole __initdata section will
- * become const */
-static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
-	" (Pavel Roskin <proski@gnu.org>,"
-	" David Gibson <hermes@gibson.dropbear.id.au>, et al)";
-
 static struct pcmcia_device_id spectrum_cs_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */
 	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
@@ -423,9 +311,7 @@
 
 static struct pcmcia_driver orinoco_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= DRIVER_NAME,
-	},
+	.name		= DRIVER_NAME,
 	.probe		= spectrum_cs_probe,
 	.remove		= spectrum_cs_detach,
 	.suspend	= spectrum_cs_suspend,
@@ -436,8 +322,6 @@
 static int __init
 init_spectrum_cs(void)
 {
-	printk(KERN_DEBUG "%s\n", version);
-
 	return pcmcia_register_driver(&orinoco_driver);
 }
 
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index cf7be1e..93505f9 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -589,8 +589,15 @@
 
 	/* If the interface is running we try to find more about the
 	   current mode */
-	if (netif_running(dev))
-		err = orinoco_hw_get_act_bitrate(priv, &bitrate);
+	if (netif_running(dev)) {
+		int act_bitrate;
+		int lerr;
+
+		/* Ignore errors if we can't get the actual bitrate */
+		lerr = orinoco_hw_get_act_bitrate(priv, &act_bitrate);
+		if (!lerr)
+			bitrate = act_bitrate;
+	}
 
 	orinoco_unlock(priv, &flags);
 
diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig
index b0342a5..e5f45cb 100644
--- a/drivers/net/wireless/p54/Kconfig
+++ b/drivers/net/wireless/p54/Kconfig
@@ -2,6 +2,7 @@
 	tristate "Softmac Prism54 support"
 	depends on MAC80211 && EXPERIMENTAL
 	select FW_LOADER
+	select CRC_CCITT
 	---help---
 	  This is common code for isl38xx/stlc45xx based modules.
 	  This module does nothing by itself - the USB/PCI/SPI front-ends
@@ -48,6 +49,23 @@
 
 	  If you choose to build a module, it'll be called p54spi.
 
+config P54_SPI_DEFAULT_EEPROM
+	bool "Include fallback EEPROM blob"
+	depends on P54_SPI
+	default n
+	---help---
+	 Unlike the PCI or USB devices, the SPI variants don't have
+	 a dedicated EEPROM chip to store all device specific values
+	 for calibration, country and interface settings.
+
+	 The driver will try to load the image "3826.eeprom", if the
+	 file is put at the right place. (usually /lib/firmware.)
+
+	 Only if this request fails, this option will provide a
+	 backup set of generic values to get the device working.
+
+	 Enabling this option adds about 4k to p54spi.
+
 config P54_LEDS
 	bool
 	depends on P54_COMMON && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = P54_COMMON)
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index 78347041..35b09aa 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 
 #include <net/mac80211.h>
+#include <linux/crc-ccitt.h>
 
 #include "p54.h"
 #include "eeprom.h"
@@ -260,8 +261,10 @@
 	list->max_entries = max_channel_num;
 	list->channels = kzalloc(sizeof(struct p54_channel_entry) *
 				 max_channel_num, GFP_KERNEL);
-	if (!list->channels)
+	if (!list->channels) {
+		ret = -ENOMEM;
 		goto free;
+	}
 
 	for (i = 0; i < max_channel_num; i++) {
 		if (i < priv->iq_autocal_len) {
@@ -540,6 +543,7 @@
 	int err;
 	u8 *end = (u8 *)eeprom + len;
 	u16 synth = 0;
+	u16 crc16 = ~0;
 
 	wrap = (struct eeprom_pda_wrap *) eeprom;
 	entry = (void *)wrap->data + le16_to_cpu(wrap->len);
@@ -655,16 +659,29 @@
 			}
 			break;
 		case PDR_END:
-			/* make it overrun */
-			entry_len = len;
+			crc16 = ~crc_ccitt(crc16, (u8 *) entry, sizeof(*entry));
+			if (crc16 != le16_to_cpup((__le16 *)entry->data)) {
+				wiphy_err(dev->wiphy, "eeprom failed checksum "
+					 "test!\n");
+				err = -ENOMSG;
+				goto err;
+			} else {
+				goto good_eeprom;
+			}
 			break;
 		default:
 			break;
 		}
 
-		entry = (void *)entry + (entry_len + 1)*2;
+		crc16 = crc_ccitt(crc16, (u8 *)entry, (entry_len + 1) * 2);
+		entry = (void *)entry + (entry_len + 1) * 2;
 	}
 
+	wiphy_err(dev->wiphy, "unexpected end of eeprom data.\n");
+	err = -ENODATA;
+	goto err;
+
+good_eeprom:
 	if (!synth || !priv->iq_autocal || !priv->output_limit ||
 	    !priv->curve_data) {
 		wiphy_err(dev->wiphy,
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index 15b20c2..92b9b1f 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -123,10 +123,14 @@
 		bootrec = (struct bootrec *)&bootrec->data[len];
 	}
 
-	if (fw_version)
+	if (fw_version) {
 		wiphy_info(priv->hw->wiphy,
 			   "FW rev %s - Softmac protocol %x.%x\n",
 			   fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
+		snprintf(dev->wiphy->fw_version, sizeof(dev->wiphy->fw_version),
+				"%s - %x.%x", fw_version,
+				priv->fw_var >> 8, priv->fw_var & 0xff);
+	}
 
 	if (priv->fw_var < 0x500)
 		wiphy_info(priv->hw->wiphy,
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index 47db439..622d27b6 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -429,8 +429,8 @@
 
 	mutex_lock(&priv->conf_mutex);
 	if (cmd == SET_KEY) {
-		switch (key->alg) {
-		case ALG_TKIP:
+		switch (key->cipher) {
+		case WLAN_CIPHER_SUITE_TKIP:
 			if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL |
 			      BR_DESC_PRIV_CAP_TKIP))) {
 				ret = -EOPNOTSUPP;
@@ -439,7 +439,8 @@
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 			algo = P54_CRYPTO_TKIPMICHAEL;
 			break;
-		case ALG_WEP:
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
 			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) {
 				ret = -EOPNOTSUPP;
 				goto out_unlock;
@@ -447,7 +448,7 @@
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 			algo = P54_CRYPTO_WEP;
 			break;
-		case ALG_CCMP:
+		case WLAN_CIPHER_SUITE_CCMP:
 			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) {
 				ret = -EOPNOTSUPP;
 				goto out_unlock;
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index 087bf06..18d24b7 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -32,11 +32,14 @@
 #include <linux/slab.h>
 
 #include "p54spi.h"
-#include "p54spi_eeprom.h"
 #include "p54.h"
 
 #include "lmac.h"
 
+#ifdef CONFIG_P54_SPI_DEFAULT_EEPROM
+#include "p54spi_eeprom.h"
+#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
+
 MODULE_FIRMWARE("3826.arm");
 MODULE_ALIAS("stlc45xx");
 
@@ -195,9 +198,13 @@
 
 	ret = request_firmware(&eeprom, "3826.eeprom", &priv->spi->dev);
 	if (ret < 0) {
+#ifdef CONFIG_P54_SPI_DEFAULT_EEPROM
 		dev_info(&priv->spi->dev, "loading default eeprom...\n");
 		ret = p54_parse_eeprom(dev, (void *) p54spi_eeprom,
 				       sizeof(p54spi_eeprom));
+#else
+		dev_err(&priv->spi->dev, "Failed to request user eeprom\n");
+#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
 	} else {
 		dev_info(&priv->spi->dev, "loading user eeprom...\n");
 		ret = p54_parse_eeprom(dev, (void *) eeprom->data,
diff --git a/drivers/net/wireless/p54/p54spi_eeprom.h b/drivers/net/wireless/p54/p54spi_eeprom.h
index 1ea1050..d592cbd 100644
--- a/drivers/net/wireless/p54/p54spi_eeprom.h
+++ b/drivers/net/wireless/p54/p54spi_eeprom.h
@@ -671,7 +671,7 @@
 	0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01,
 
 0x02, 0x00, 0x00, 0x00,		/* PDR_END */
-	0xa8, 0xf5			/* bogus data */
+	0x67, 0x99,
 };
 
 #endif /* P54SPI_EEPROM_H */
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index ad59595..d5bc21e 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -33,8 +33,17 @@
 MODULE_FIRMWARE("isl3886usb");
 MODULE_FIRMWARE("isl3887usb");
 
+/*
+ * Note:
+ *
+ * Always update our wiki's device list (located at:
+ * http://wireless.kernel.org/en/users/Drivers/p54/devices ),
+ * whenever you add a new device.
+ */
+
 static struct usb_device_id p54u_table[] __devinitdata = {
 	/* Version 1 devices (pci chip + net2280) */
+	{USB_DEVICE(0x045e, 0x00c2)},	/* Microsoft MN-710 */
 	{USB_DEVICE(0x0506, 0x0a11)},	/* 3COM 3CRWE254G72 */
 	{USB_DEVICE(0x06b9, 0x0120)},	/* Thomson SpeedTouch 120g */
 	{USB_DEVICE(0x0707, 0xee06)},	/* SMC 2862W-G */
@@ -47,7 +56,9 @@
 	{USB_DEVICE(0x0846, 0x4220)},	/* Netgear WG111 */
 	{USB_DEVICE(0x09aa, 0x1000)},	/* Spinnaker Proto board */
 	{USB_DEVICE(0x0cde, 0x0006)},	/* Medion 40900, Roper Europe */
+	{USB_DEVICE(0x107b, 0x55f2)},	/* Gateway WGU-210 (Gemtek) */
 	{USB_DEVICE(0x124a, 0x4023)},	/* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
+	{USB_DEVICE(0x1630, 0x0005)},	/* 2Wire 802.11g USB (v1) / Z-Com */
 	{USB_DEVICE(0x1915, 0x2234)},	/* Linksys WUSB54G OEM */
 	{USB_DEVICE(0x1915, 0x2235)},	/* Linksys WUSB54G Portable OEM */
 	{USB_DEVICE(0x2001, 0x3701)},	/* DLink DWL-G120 Spinnaker */
@@ -60,6 +71,7 @@
 	{USB_DEVICE(0x050d, 0x7050)},	/* Belkin F5D7050 ver 1000 */
 	{USB_DEVICE(0x0572, 0x2000)},	/* Cohiba Proto board */
 	{USB_DEVICE(0x0572, 0x2002)},	/* Cohiba Proto board */
+	{USB_DEVICE(0x06a9, 0x000e)},	/* Westell 802.11g USB (A90-211WG-01) */
 	{USB_DEVICE(0x06b9, 0x0121)},	/* Thomson SpeedTouch 121g */
 	{USB_DEVICE(0x0707, 0xee13)},   /* SMC 2862W-G version 2 */
 	{USB_DEVICE(0x083a, 0x4521)},   /* Siemens Gigaset USB Adapter 54 version 2 */
@@ -80,6 +92,7 @@
 	{USB_DEVICE(0x13B1, 0x000C)},	/* Linksys WUSB54AG */
 	{USB_DEVICE(0x1413, 0x5400)},   /* Telsey 802.11g USB2.0 Adapter */
 	{USB_DEVICE(0x1435, 0x0427)},	/* Inventel UR054G */
+	{USB_DEVICE(0x1668, 0x1050)},	/* Actiontec 802UIG-1 */
 	{USB_DEVICE(0x2001, 0x3704)},	/* DLink DWL-G122 rev A2 */
 	{USB_DEVICE(0x413c, 0x5513)},	/* Dell WLA3310 USB Wireless Adapter */
 	{USB_DEVICE(0x413c, 0x8102)},	/* Spinnaker DUT */
@@ -930,8 +943,8 @@
 #ifdef CONFIG_PM
 		/* ISL3887 needs a full reset on resume */
 		udev->reset_resume = 1;
+#endif /* CONFIG_PM */
 		err = p54u_device_reset(dev);
-#endif
 
 		priv->hw_type = P54U_3887;
 		dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 0e937dc..76b2318a 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -275,15 +275,15 @@
 {
 	int band = priv->hw->conf.channel->band;
 
-	if (priv->rxhw != 5)
+	if (priv->rxhw != 5) {
 		return ((rssi * priv->rssical_db[band].mul) / 64 +
 			 priv->rssical_db[band].add) / 4;
-	else
+	} else {
 		/*
 		 * TODO: find the correct formula
 		 */
-		return ((rssi * priv->rssical_db[band].mul) / 64 +
-			 priv->rssical_db[band].add) / 4;
+		return rssi / 2 - 110;
+	}
 }
 
 /*
@@ -683,14 +683,15 @@
 	}
 }
 
-static u8 p54_convert_algo(enum ieee80211_key_alg alg)
+static u8 p54_convert_algo(u32 cipher)
 {
-	switch (alg) {
-	case ALG_WEP:
+	switch (cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
 		return P54_CRYPTO_WEP;
-	case ALG_TKIP:
+	case WLAN_CIPHER_SUITE_TKIP:
 		return P54_CRYPTO_TKIPMICHAEL;
-	case ALG_CCMP:
+	case WLAN_CIPHER_SUITE_CCMP:
 		return P54_CRYPTO_AESCCMP;
 	default:
 		return 0;
@@ -731,7 +732,7 @@
 
 	if (info->control.hw_key) {
 		crypt_offset = ieee80211_get_hdrlen_from_skb(skb);
-		if (info->control.hw_key->alg == ALG_TKIP) {
+		if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
 			u8 *iv = (u8 *)(skb->data + crypt_offset);
 			/*
 			 * The firmware excepts that the IV has to have
@@ -827,10 +828,10 @@
 	hdr->tries = ridx;
 	txhdr->rts_rate_idx = 0;
 	if (info->control.hw_key) {
-		txhdr->key_type = p54_convert_algo(info->control.hw_key->alg);
+		txhdr->key_type = p54_convert_algo(info->control.hw_key->cipher);
 		txhdr->key_len = min((u8)16, info->control.hw_key->keylen);
 		memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len);
-		if (info->control.hw_key->alg == ALG_TKIP) {
+		if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
 			/* reserve space for the MIC key */
 			len += 8;
 			memcpy(skb_put(skb, 8), &(info->control.hw_key->key
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 77cd65d..d97a2caf 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -3234,7 +3234,7 @@
 	switch (cmd) {
 		case PRISM54_HOSTAPD:
 		if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
+			return -EPERM;
 		ret = prism54_hostapd(ndev, &wrq->u.data);
 		return ret;
 	}
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 88560d0..97007d9 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -43,10 +43,8 @@
 #include <linux/if_arp.h>
 #include <linux/ioport.h>
 #include <linux/skbuff.h>
-#include <linux/ethtool.h>
 #include <linux/ieee80211.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -80,8 +78,6 @@
 static struct net_device_stats *ray_get_stats(struct net_device *dev);
 static int ray_dev_init(struct net_device *dev);
 
-static const struct ethtool_ops netdev_ethtool_ops;
-
 static int ray_open(struct net_device *dev);
 static netdev_tx_t ray_dev_start_xmit(struct sk_buff *skb,
 					    struct net_device *dev);
@@ -169,13 +165,6 @@
  */
 static char *phy_addr = NULL;
 
-
-/* A struct pcmcia_device structure has fields for most things that are needed
-   to keep track of a socket, but there will usually be some device
-   specific information that also needs to be kept track of.  The
-   'priv' pointer in a struct pcmcia_device structure can be used to point to
-   a device-specific private data structure, like this.
-*/
 static unsigned int ray_mem_speed = 500;
 
 /* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */
@@ -197,7 +186,7 @@
 module_param(phy_addr, charp, 0);
 module_param(ray_mem_speed, int, 0);
 
-static UCHAR b5_default_startup_parms[] = {
+static const UCHAR b5_default_startup_parms[] = {
 	0, 0,			/* Adhoc station */
 	'L', 'I', 'N', 'U', 'X', 0, 0, 0,	/* 32 char ESSID */
 	0, 0, 0, 0, 0, 0, 0, 0,
@@ -232,7 +221,7 @@
 	2, 0, 0, 0, 0, 0, 0, 0	/* basic rate set */
 };
 
-static UCHAR b4_default_startup_parms[] = {
+static const UCHAR b4_default_startup_parms[] = {
 	0, 0,			/* Adhoc station */
 	'L', 'I', 'N', 'U', 'X', 0, 0, 0,	/* 32 char ESSID */
 	0, 0, 0, 0, 0, 0, 0, 0,
@@ -264,9 +253,9 @@
 };
 
 /*===========================================================================*/
-static unsigned char eth2_llc[] = { 0xaa, 0xaa, 3, 0, 0, 0 };
+static const u8 eth2_llc[] = { 0xaa, 0xaa, 3, 0, 0, 0 };
 
-static char hop_pattern_length[] = { 1,
+static const char hop_pattern_length[] = { 1,
 	USA_HOP_MOD, EUROPE_HOP_MOD,
 	JAPAN_HOP_MOD, KOREA_HOP_MOD,
 	SPAIN_HOP_MOD, FRANCE_HOP_MOD,
@@ -274,7 +263,7 @@
 	JAPAN_TEST_HOP_MOD
 };
 
-static char rcsid[] =
+static const char rcsid[] =
     "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.std.com>";
 
 static const struct net_device_ops ray_netdev_ops = {
@@ -290,14 +279,6 @@
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
-/*=============================================================================
-    ray_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-    The dev_link 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 ray_probe(struct pcmcia_device *p_dev)
 {
 	ray_dev_t *local;
@@ -318,9 +299,8 @@
 	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
 	/* General socket configuration */
-	p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
-	p_dev->conf.ConfigIndex = 1;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
+	p_dev->config_index = 1;
 
 	p_dev->priv = dev;
 
@@ -333,7 +313,6 @@
 
 	/* Raylink entries in the device structure */
 	dev->netdev_ops = &ray_netdev_ops;
-	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 	dev->wireless_handlers = &ray_handler_def;
 #ifdef WIRELESS_SPY
 	local->wireless_data.spy_data = &local->spy_data;
@@ -353,12 +332,6 @@
 	return -ENOMEM;
 } /* ray_attach */
 
-/*=============================================================================
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-=============================================================================*/
 static void ray_detach(struct pcmcia_device *link)
 {
 	struct net_device *dev;
@@ -381,17 +354,11 @@
 	dev_dbg(&link->dev, "ray_cs ray_detach ending\n");
 } /* ray_detach */
 
-/*=============================================================================
-    ray_config() is run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-=============================================================================*/
 #define MAX_TUPLE_SIZE 128
 static int ray_config(struct pcmcia_device *link)
 {
 	int ret = 0;
 	int i;
-	win_req_t req;
 	struct net_device *dev = (struct net_device *)link->priv;
 	ray_dev_t *local = netdev_priv(dev);
 
@@ -412,54 +379,50 @@
 		goto failed;
 	dev->irq = link->irq;
 
-	/* This actually configures the PCMCIA socket -- setting up
-	   the I/O windows and the interrupt mapping.
-	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
 /*** Set up 32k window for shared memory (transmit and control) ************/
-	req.Attributes =
-	    WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
-	req.Base = 0;
-	req.Size = 0x8000;
-	req.AccessSpeed = ray_mem_speed;
-	ret = pcmcia_request_window(link, &req, &link->win);
+	link->resource[2]->flags |= WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
+	link->resource[2]->start = 0;
+	link->resource[2]->end = 0x8000;
+	ret = pcmcia_request_window(link, link->resource[2], ray_mem_speed);
 	if (ret)
 		goto failed;
-	ret = pcmcia_map_mem_page(link, link->win, 0);
+	ret = pcmcia_map_mem_page(link, link->resource[2], 0);
 	if (ret)
 		goto failed;
-	local->sram = ioremap(req.Base, req.Size);
+	local->sram = ioremap(link->resource[2]->start,
+			resource_size(link->resource[2]));
 
 /*** Set up 16k window for shared memory (receive buffer) ***************/
-	req.Attributes =
+	link->resource[3]->flags |=
 	    WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
-	req.Base = 0;
-	req.Size = 0x4000;
-	req.AccessSpeed = ray_mem_speed;
-	ret = pcmcia_request_window(link, &req, &local->rmem_handle);
+	link->resource[3]->start = 0;
+	link->resource[3]->end = 0x4000;
+	ret = pcmcia_request_window(link, link->resource[3], ray_mem_speed);
 	if (ret)
 		goto failed;
-	ret = pcmcia_map_mem_page(link, local->rmem_handle, 0x8000);
+	ret = pcmcia_map_mem_page(link, link->resource[3], 0x8000);
 	if (ret)
 		goto failed;
-	local->rmem = ioremap(req.Base, req.Size);
+	local->rmem = ioremap(link->resource[3]->start,
+			resource_size(link->resource[3]));
 
 /*** Set up window for attribute memory ***********************************/
-	req.Attributes =
+	link->resource[4]->flags |=
 	    WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT;
-	req.Base = 0;
-	req.Size = 0x1000;
-	req.AccessSpeed = ray_mem_speed;
-	ret = pcmcia_request_window(link, &req, &local->amem_handle);
+	link->resource[4]->start = 0;
+	link->resource[4]->end = 0x1000;
+	ret = pcmcia_request_window(link, link->resource[4], ray_mem_speed);
 	if (ret)
 		goto failed;
-	ret = pcmcia_map_mem_page(link, local->amem_handle, 0);
+	ret = pcmcia_map_mem_page(link, link->resource[4], 0);
 	if (ret)
 		goto failed;
-	local->amem = ioremap(req.Base, req.Size);
+	local->amem = ioremap(link->resource[4]->start,
+			resource_size(link->resource[4]));
 
 	dev_dbg(&link->dev, "ray_config sram=%p\n", local->sram);
 	dev_dbg(&link->dev, "ray_config rmem=%p\n", local->rmem);
@@ -608,7 +571,7 @@
 	/* Start kernel timer to wait for dl startup to complete. */
 	local->timer.expires = jiffies + HZ / 2;
 	local->timer.data = (long)local;
-	local->timer.function = &verify_dl_startup;
+	local->timer.function = verify_dl_startup;
 	add_timer(&local->timer);
 	dev_dbg(&link->dev,
 	      "ray_cs dl_startup_params started timer for verify_dl_startup\n");
@@ -775,11 +738,7 @@
 	local->card_status = CARD_DOING_ACQ;
 }
 
-/*============================================================================
-    After a card is removed, ray_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-=============================================================================*/
+
 static void ray_release(struct pcmcia_device *link)
 {
 	struct net_device *dev = link->priv;
@@ -1062,18 +1021,6 @@
 	}
 } /* end encapsulate_frame */
 
-/*===========================================================================*/
-
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strcpy(info->driver, "ray_cs");
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo = netdev_get_drvinfo,
-};
-
 /*====================================================================*/
 
 /*------------------------------------------------------------------*/
@@ -1997,12 +1944,12 @@
 					dev_dbg(&link->dev,
 					      "ray_cs interrupt network \"%s\" start failed\n",
 					      local->sparm.b4.a_current_ess_id);
-					local->timer.function = &start_net;
+					local->timer.function = start_net;
 				} else {
 					dev_dbg(&link->dev,
 					      "ray_cs interrupt network \"%s\" join failed\n",
 					      local->sparm.b4.a_current_ess_id);
-					local->timer.function = &join_net;
+					local->timer.function = join_net;
 				}
 				add_timer(&local->timer);
 			}
@@ -2470,9 +2417,9 @@
 
 	del_timer(&local->timer);
 	if (build_auth_frame(local, local->bss_id, OPEN_AUTH_REQUEST)) {
-		local->timer.function = &join_net;
+		local->timer.function = join_net;
 	} else {
-		local->timer.function = &authenticate_timeout;
+		local->timer.function = authenticate_timeout;
 	}
 	local->timer.expires = jiffies + HZ * 2;
 	local->timer.data = (long)local;
@@ -2557,7 +2504,7 @@
 		del_timer(&local->timer);
 		local->timer.expires = jiffies + HZ * 2;
 		local->timer.data = (long)local;
-		local->timer.function = &join_net;
+		local->timer.function = join_net;
 		add_timer(&local->timer);
 		local->card_status = CARD_ASSOC_FAILED;
 		return;
@@ -2591,7 +2538,7 @@
 #ifdef CONFIG_PROC_FS
 #define MAXDATA (PAGE_SIZE - 80)
 
-static char *card_status[] = {
+static const char *card_status[] = {
 	"Card inserted - uninitialized",	/* 0 */
 	"Card not downloaded",			/* 1 */
 	"Waiting for download parameters",	/* 2 */
@@ -2608,8 +2555,8 @@
 	"Association failed"			/* 16 */
 };
 
-static char *nettype[] = { "Adhoc", "Infra " };
-static char *framing[] = { "Encapsulation", "Translation" }
+static const char *nettype[] = { "Adhoc", "Infra " };
+static const char *framing[] = { "Encapsulation", "Translation" }
 
 ;
 /*===========================================================================*/
@@ -2802,6 +2749,7 @@
 static const struct file_operations ray_cs_essid_proc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= ray_cs_essid_proc_write,
+	.llseek		= noop_llseek,
 };
 
 static ssize_t int_proc_write(struct file *file, const char __user *buffer,
@@ -2835,6 +2783,7 @@
 static const struct file_operations int_proc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= int_proc_write,
+	.llseek		= noop_llseek,
 };
 #endif
 
@@ -2847,9 +2796,7 @@
 
 static struct pcmcia_driver ray_driver = {
 	.owner = THIS_MODULE,
-	.drv = {
-		.name = "ray_cs",
-		},
+	.name = "ray_cs",
 	.probe = ray_probe,
 	.remove = ray_detach,
 	.id_table = ray_ids,
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h
index 9f01ddb..e79848f 100644
--- a/drivers/net/wireless/ray_cs.h
+++ b/drivers/net/wireless/ray_cs.h
@@ -25,8 +25,6 @@
 typedef struct ray_dev_t {
     int card_status;
     int authentication_state;
-    window_handle_t amem_handle;   /* handle to window for attribute memory  */
-    window_handle_t rmem_handle;   /* handle to window for rx buffer on card */
     void __iomem *sram;            /* pointer to beginning of shared RAM     */
     void __iomem *amem;            /* pointer to attribute mem window        */
     void __iomem *rmem;            /* pointer to receive buffer window       */
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 719573b..71b5971 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -540,11 +540,11 @@
 	struct ieee80211_channel *chan, enum nl80211_channel_type channel_type);
 
 static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
-					u8 key_index, const u8 *mac_addr,
-					struct key_params *params);
+			 u8 key_index, bool pairwise, const u8 *mac_addr,
+			 struct key_params *params);
 
 static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
-					u8 key_index, const u8 *mac_addr);
+			 u8 key_index, bool pairwise, const u8 *mac_addr);
 
 static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 								u8 key_index);
@@ -2308,8 +2308,8 @@
 }
 
 static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
-					u8 key_index, const u8 *mac_addr,
-					struct key_params *params)
+			 u8 key_index, bool pairwise, const u8 *mac_addr,
+			 struct key_params *params)
 {
 	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
 	struct usbnet *usbdev = priv->usbdev;
@@ -2344,7 +2344,7 @@
 }
 
 static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
-					u8 key_index, const u8 *mac_addr)
+			 u8 key_index, bool pairwise, const u8 *mac_addr)
 {
 	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
 	struct usbnet *usbdev = priv->usbdev;
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 5063e01..4f420a9 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -321,7 +321,8 @@
 }
 
 static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
-				 struct rt2x00lib_erp *erp)
+				 struct rt2x00lib_erp *erp,
+				 u32 changed)
 {
 	int preamble_mask;
 	u32 reg;
@@ -329,59 +330,72 @@
 	/*
 	 * When short preamble is enabled, we should set bit 0x08
 	 */
-	preamble_mask = erp->short_preamble << 3;
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		preamble_mask = erp->short_preamble << 3;
 
-	rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
-	rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
-	rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
-	rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
-	rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
-	rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+		rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
+		rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
+		rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
+		rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
+		rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
+		rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
 
-	rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
-	rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
-	rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
-	rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10));
-	rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
+		rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
+		rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
+		rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
+		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+				   GET_DURATION(ACK_SIZE, 10));
+		rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
 
-	rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
-	rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
-	rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
-	rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20));
-	rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
+		rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
+		rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
+		rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
+		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+				   GET_DURATION(ACK_SIZE, 20));
+		rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
 
-	rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
-	rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
-	rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
-	rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55));
-	rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
+		rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
+		rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
+		rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
+		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+				   GET_DURATION(ACK_SIZE, 55));
+		rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
 
-	rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
-	rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
-	rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
-	rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110));
-	rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+		rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
+		rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
+		rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
+		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+				   GET_DURATION(ACK_SIZE, 110));
+		rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+	}
 
-	rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+	if (changed & BSS_CHANGED_BASIC_RATES)
+		rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
 
-	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
-	rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
-	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+		rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
+		rt2x00pci_register_write(rt2x00dev, CSR11, reg);
 
-	rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
-	rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, erp->beacon_int * 16);
-	rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16);
-	rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+		rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+		rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
+		rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
+		rt2x00pci_register_write(rt2x00dev, CSR18, reg);
 
-	rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
-	rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
-	rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
-	rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+		rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+		rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
+		rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
+		rt2x00pci_register_write(rt2x00dev, CSR19, reg);
+	}
 
-	rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
-	rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
-	rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
-	rt2x00pci_register_write(rt2x00dev, CSR19, reg);
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
+		rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
+				   erp->beacon_int * 16);
+		rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
+				   erp->beacon_int * 16);
+		rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+	}
 }
 
 static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev,
@@ -1007,12 +1021,11 @@
 /*
  * TX descriptor initialization
  */
-static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-				    struct sk_buff *skb,
+static void rt2400pci_write_tx_desc(struct queue_entry *entry,
 				    struct txentry_desc *txdesc)
 {
-	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-	struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 	__le32 *txd = entry_priv->desc;
 	u32 word;
 
@@ -1091,12 +1104,12 @@
 	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
 	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 
-	rt2x00queue_map_txskb(rt2x00dev, entry->skb);
+	rt2x00queue_map_txskb(entry);
 
 	/*
 	 * Write the TX descriptor for the beacon.
 	 */
-	rt2400pci_write_tx_desc(rt2x00dev, entry->skb, txdesc);
+	rt2400pci_write_tx_desc(entry, txdesc);
 
 	/*
 	 * Dump beacon to userspace through debugfs.
@@ -1112,24 +1125,24 @@
 	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 }
 
-static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-				    const enum data_queue_qid queue)
+static void rt2400pci_kick_tx_queue(struct data_queue *queue)
 {
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 	u32 reg;
 
 	rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
-	rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue == QID_AC_BE));
-	rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue == QID_AC_BK));
-	rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue == QID_ATIM));
+	rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE));
+	rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK));
+	rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM));
 	rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
 }
 
-static void rt2400pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
-				    const enum data_queue_qid qid)
+static void rt2400pci_kill_tx_queue(struct data_queue *queue)
 {
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 	u32 reg;
 
-	if (qid == QID_BEACON) {
+	if (queue->qid == QID_BEACON) {
 		rt2x00pci_register_write(rt2x00dev, CSR14, 0);
 	} else {
 		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
@@ -1481,15 +1494,17 @@
 	/*
 	 * Create channel information array
 	 */
-	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+	info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
 	spec->channels_info = info;
 
 	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
-	for (i = 0; i < 14; i++)
-		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+	for (i = 0; i < 14; i++) {
+		info[i].max_power = TXPOWER_FROM_DEV(MAX_TXPOWER);
+		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+	}
 
 	return 0;
 }
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index c2a555d..97feb7a 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -327,7 +327,8 @@
 }
 
 static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
-				 struct rt2x00lib_erp *erp)
+				 struct rt2x00lib_erp *erp,
+				 u32 changed)
 {
 	int preamble_mask;
 	u32 reg;
@@ -335,59 +336,73 @@
 	/*
 	 * When short preamble is enabled, we should set bit 0x08
 	 */
-	preamble_mask = erp->short_preamble << 3;
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		preamble_mask = erp->short_preamble << 3;
 
-	rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
-	rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162);
-	rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2);
-	rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
-	rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
-	rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+		rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
+		rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162);
+		rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2);
+		rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
+		rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
+		rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
 
-	rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
-	rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
-	rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
-	rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10));
-	rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
+		rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
+		rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
+		rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
+		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+				   GET_DURATION(ACK_SIZE, 10));
+		rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
 
-	rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
-	rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
-	rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
-	rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20));
-	rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
+		rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
+		rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
+		rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
+		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+				   GET_DURATION(ACK_SIZE, 20));
+		rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
 
-	rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
-	rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
-	rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
-	rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55));
-	rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
+		rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
+		rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
+		rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
+		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+				   GET_DURATION(ACK_SIZE, 55));
+		rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
 
-	rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
-	rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
-	rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
-	rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110));
-	rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+		rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
+		rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
+		rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
+		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+				   GET_DURATION(ACK_SIZE, 110));
+		rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+	}
 
-	rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+	if (changed & BSS_CHANGED_BASIC_RATES)
+		rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
 
-	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
-	rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
-	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+		rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
+		rt2x00pci_register_write(rt2x00dev, CSR11, reg);
 
-	rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
-	rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, erp->beacon_int * 16);
-	rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16);
-	rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+		rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+		rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
+		rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
+		rt2x00pci_register_write(rt2x00dev, CSR18, reg);
 
-	rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
-	rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
-	rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
-	rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+		rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+		rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
+		rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
+		rt2x00pci_register_write(rt2x00dev, CSR19, reg);
+	}
 
-	rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
-	rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
-	rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
-	rt2x00pci_register_write(rt2x00dev, CSR19, reg);
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
+		rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
+				   erp->beacon_int * 16);
+		rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
+				   erp->beacon_int * 16);
+		rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+	}
+
 }
 
 static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
@@ -1161,12 +1176,11 @@
 /*
  * TX descriptor initialization
  */
-static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-				    struct sk_buff *skb,
+static void rt2500pci_write_tx_desc(struct queue_entry *entry,
 				    struct txentry_desc *txdesc)
 {
-	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-	struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 	__le32 *txd = entry_priv->desc;
 	u32 word;
 
@@ -1244,12 +1258,12 @@
 	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
 	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 
-	rt2x00queue_map_txskb(rt2x00dev, entry->skb);
+	rt2x00queue_map_txskb(entry);
 
 	/*
 	 * Write the TX descriptor for the beacon.
 	 */
-	rt2500pci_write_tx_desc(rt2x00dev, entry->skb, txdesc);
+	rt2500pci_write_tx_desc(entry, txdesc);
 
 	/*
 	 * Dump beacon to userspace through debugfs.
@@ -1265,24 +1279,24 @@
 	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 }
 
-static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-				    const enum data_queue_qid queue)
+static void rt2500pci_kick_tx_queue(struct data_queue *queue)
 {
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 	u32 reg;
 
 	rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
-	rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue == QID_AC_BE));
-	rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue == QID_AC_BK));
-	rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue == QID_ATIM));
+	rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE));
+	rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK));
+	rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM));
 	rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
 }
 
-static void rt2500pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
-				    const enum data_queue_qid qid)
+static void rt2500pci_kill_tx_queue(struct data_queue *queue)
 {
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 	u32 reg;
 
-	if (qid == QID_BEACON) {
+	if (queue->qid == QID_BEACON) {
 		rt2x00pci_register_write(rt2x00dev, CSR14, 0);
 	} else {
 		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
@@ -1795,19 +1809,23 @@
 	/*
 	 * Create channel information array
 	 */
-	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+	info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
 	spec->channels_info = info;
 
 	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
-	for (i = 0; i < 14; i++)
-		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+	for (i = 0; i < 14; i++) {
+		info[i].max_power = MAX_TXPOWER;
+		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+	}
 
 	if (spec->num_channels > 14) {
-		for (i = 14; i < spec->num_channels; i++)
-			info[i].tx_power1 = DEFAULT_TXPOWER;
+		for (i = 14; i < spec->num_channels; i++) {
+			info[i].max_power = MAX_TXPOWER;
+			info[i].default_power1 = DEFAULT_TXPOWER;
+		}
 	}
 
 	return 0;
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index cdaf93f..93e44c7f 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -355,7 +355,9 @@
 		 * it is known that not work at least on some hardware.
 		 * SW crypto will be used in that case.
 		 */
-		if (key->alg == ALG_WEP && key->keyidx != 0)
+		if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+		     key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
+		    key->keyidx != 0)
 			return -EOPNOTSUPP;
 
 		/*
@@ -492,24 +494,34 @@
 }
 
 static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
-				 struct rt2x00lib_erp *erp)
+				 struct rt2x00lib_erp *erp,
+				 u32 changed)
 {
 	u16 reg;
 
-	rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
-	rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
-			   !!erp->short_preamble);
-	rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
+		rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
+				   !!erp->short_preamble);
+		rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
+	}
 
-	rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates);
+	if (changed & BSS_CHANGED_BASIC_RATES)
+		rt2500usb_register_write(rt2x00dev, TXRX_CSR11,
+					 erp->basic_rates);
 
-	rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
-	rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL, erp->beacon_int * 4);
-	rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
+		rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
+				   erp->beacon_int * 4);
+		rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
+	}
 
-	rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
-	rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
-	rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
+		rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
+		rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
+	}
 }
 
 static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
@@ -1039,12 +1051,11 @@
 /*
  * TX descriptor initialization
  */
-static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-				    struct sk_buff *skb,
+static void rt2500usb_write_tx_desc(struct queue_entry *entry,
 				    struct txentry_desc *txdesc)
 {
-	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-	__le32 *txd = (__le32 *) skb->data;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+	__le32 *txd = (__le32 *) entry->skb->data;
 	u32 word;
 
 	/*
@@ -1127,7 +1138,7 @@
 	/*
 	 * Write the TX descriptor for the beacon.
 	 */
-	rt2500usb_write_tx_desc(rt2x00dev, entry->skb, txdesc);
+	rt2500usb_write_tx_desc(entry, txdesc);
 
 	/*
 	 * Dump beacon to userspace through debugfs.
@@ -1195,6 +1206,14 @@
 	return length;
 }
 
+static void rt2500usb_kill_tx_queue(struct data_queue *queue)
+{
+	if (queue->qid == QID_BEACON)
+		rt2500usb_register_write(queue->rt2x00dev, TXRX_CSR19, 0);
+
+	rt2x00usb_kill_tx_queue(queue);
+}
+
 /*
  * RX control handlers
  */
@@ -1655,10 +1674,15 @@
 
 	/*
 	 * Initialize all hw fields.
+	 *
+	 * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING unless we are
+	 * capable of sending the buffered frames out after the DTIM
+	 * transmission using rt2x00lib_beacondone. This will send out
+	 * multicast and broadcast traffic immediately instead of buffering it
+	 * infinitly and thus dropping it after some time.
 	 */
 	rt2x00dev->hw->flags =
 	    IEEE80211_HW_RX_INCLUDES_FCS |
-	    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 	    IEEE80211_HW_SIGNAL_DBM |
 	    IEEE80211_HW_SUPPORTS_PS |
 	    IEEE80211_HW_PS_NULLFUNC_STACK;
@@ -1698,19 +1722,23 @@
 	/*
 	 * Create channel information array
 	 */
-	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+	info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
 	spec->channels_info = info;
 
 	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
-	for (i = 0; i < 14; i++)
-		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+	for (i = 0; i < 14; i++) {
+		info[i].max_power = MAX_TXPOWER;
+		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+	}
 
 	if (spec->num_channels > 14) {
-		for (i = 14; i < spec->num_channels; i++)
-			info[i].tx_power1 = DEFAULT_TXPOWER;
+		for (i = 14; i < spec->num_channels; i++) {
+			info[i].max_power = MAX_TXPOWER;
+			info[i].default_power1 = DEFAULT_TXPOWER;
+		}
 	}
 
 	return 0;
@@ -1789,7 +1817,7 @@
 	.write_beacon		= rt2500usb_write_beacon,
 	.get_tx_data_len	= rt2500usb_get_tx_data_len,
 	.kick_tx_queue		= rt2x00usb_kick_tx_queue,
-	.kill_tx_queue		= rt2x00usb_kill_tx_queue,
+	.kill_tx_queue		= rt2500usb_kill_tx_queue,
 	.fill_rxdone		= rt2500usb_fill_rxdone,
 	.config_shared_key	= rt2500usb_config_key,
 	.config_pairwise_key	= rt2500usb_config_key,
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index ed4ebcd..eb8b6ca 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -1,5 +1,6 @@
 /*
-	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
 	Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
 	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
 	Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
@@ -639,6 +640,18 @@
 #define LED_CFG_LED_POLAR		FIELD32(0x40000000)
 
 /*
+ * AMPDU_BA_WINSIZE: Force BlockAck window size
+ * FORCE_WINSIZE_ENABLE:
+ *   0: Disable forcing of BlockAck window size
+ *   1: Enable forcing of BlockAck window size, overwrites values BlockAck
+ *      window size values in the TXWI
+ * FORCE_WINSIZE: BlockAck window size
+ */
+#define AMPDU_BA_WINSIZE		0x1040
+#define AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE FIELD32(0x00000020)
+#define AMPDU_BA_WINSIZE_FORCE_WINSIZE	FIELD32(0x0000001f)
+
+/*
  * XIFS_TIME_CFG: MAC timing
  * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX
  * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX
@@ -698,8 +711,14 @@
 
 /*
  * TBTT_SYNC_CFG:
+ * BCN_AIFSN: Beacon AIFSN after TBTT interrupt in slots
+ * BCN_CWMIN: Beacon CWMin after TBTT interrupt in slots
  */
 #define TBTT_SYNC_CFG			0x1118
+#define TBTT_SYNC_CFG_TBTT_ADJUST	FIELD32(0x000000ff)
+#define TBTT_SYNC_CFG_BCN_EXP_WIN	FIELD32(0x0000ff00)
+#define TBTT_SYNC_CFG_BCN_AIFSN		FIELD32(0x000f0000)
+#define TBTT_SYNC_CFG_BCN_CWMIN		FIELD32(0x00f00000)
 
 /*
  * TSF_TIMER_DW0: Local lsb TSF timer, read-only
@@ -735,16 +754,21 @@
 #define INT_TIMER_EN_GP_TIMER		FIELD32(0x00000002)
 
 /*
- * CH_IDLE_STA: channel idle time
+ * CH_IDLE_STA: channel idle time (in us)
  */
 #define CH_IDLE_STA			0x1130
 
 /*
- * CH_BUSY_STA: channel busy time
+ * CH_BUSY_STA: channel busy time on primary channel (in us)
  */
 #define CH_BUSY_STA			0x1134
 
 /*
+ * CH_BUSY_STA_SEC: channel busy time on secondary channel in HT40 mode (in us)
+ */
+#define CH_BUSY_STA_SEC			0x1138
+
+/*
  * MAC_STATUS_CFG:
  * BBP_RF_BUSY: When set to 0, BBP and RF are stable.
  *	if 1 or higher one of the 2 registers is busy.
@@ -1318,11 +1342,34 @@
 #define TX_STA_CNT2_TX_UNDER_FLOW_COUNT	FIELD32(0xffff0000)
 
 /*
- * TX_STA_FIFO: TX Result for specific PID status fifo register
+ * TX_STA_FIFO: TX Result for specific PID status fifo register.
+ *
+ * This register is implemented as FIFO with 16 entries in the HW. Each
+ * register read fetches the next tx result. If the FIFO is full because
+ * it wasn't read fast enough after the according interrupt (TX_FIFO_STATUS)
+ * triggered, the hw seems to simply drop further tx results.
+ *
+ * VALID: 1: this tx result is valid
+ *        0: no valid tx result -> driver should stop reading
+ * PID_TYPE: The PID latched from the PID field in the TXWI, can be used
+ *           to match a frame with its tx result (even though the PID is
+ *           only 4 bits wide).
+ * PID_QUEUE: Part of PID_TYPE, this is the queue index number (0-3)
+ * PID_ENTRY: Part of PID_TYPE, this is the queue entry index number (1-3)
+ *            This identification number is calculated by ((idx % 3) + 1).
+ * TX_SUCCESS: Indicates tx success (1) or failure (0)
+ * TX_AGGRE: Indicates if the frame was part of an aggregate (1) or not (0)
+ * TX_ACK_REQUIRED: Indicates if the frame needed to get ack'ed (1) or not (0)
+ * WCID: The wireless client ID.
+ * MCS: The tx rate used during the last transmission of this frame, be it
+ *      successful or not.
+ * PHYMODE: The phymode used for the transmission.
  */
 #define TX_STA_FIFO			0x1718
 #define TX_STA_FIFO_VALID		FIELD32(0x00000001)
 #define TX_STA_FIFO_PID_TYPE		FIELD32(0x0000001e)
+#define TX_STA_FIFO_PID_QUEUE		FIELD32(0x00000006)
+#define TX_STA_FIFO_PID_ENTRY		FIELD32(0x00000018)
 #define TX_STA_FIFO_TX_SUCCESS		FIELD32(0x00000020)
 #define TX_STA_FIFO_TX_AGGRE		FIELD32(0x00000040)
 #define TX_STA_FIFO_TX_ACK_REQUIRED	FIELD32(0x00000080)
@@ -1405,6 +1452,24 @@
 
 /*
  * Security key table memory.
+ *
+ * The pairwise key table shares some memory with the beacon frame
+ * buffers 6 and 7. That basically means that when beacon 6 & 7
+ * are used we should only use the reduced pairwise key table which
+ * has a maximum of 222 entries.
+ *
+ * ---------------------------------------------
+ * |0x4000 | Pairwise Key   | Reduced Pairwise |
+ * |       | Table          | Key Table        |
+ * |       | Size: 256 * 32 | Size: 222 * 32   |
+ * |0x5BC0 |                |-------------------
+ * |       |                | Beacon 6         |
+ * |0x5DC0 |                |-------------------
+ * |       |                | Beacon 7         |
+ * |0x5FC0 |                |-------------------
+ * |0x5FFF |                |
+ * --------------------------
+ *
  * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry
  * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry
  * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry
@@ -1554,7 +1619,8 @@
  * 2. Extract memory from FCE table for BCN 4~5
  * 3. Extract memory from Pair-wise key table for BCN 6~7
  *    It occupied those memory of wcid 238~253 for BCN 6
- *    and wcid 222~237 for BCN 7
+ *    and wcid 222~237 for BCN 7 (see Security key table memory
+ *    for more info).
  *
  * IMPORTANT NOTE: Not sure why legacy driver does this,
  * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6.
@@ -1841,6 +1907,13 @@
 #define EEPROM_RSSI_A2_LNA_A2		FIELD16(0xff00)
 
 /*
+ * EEPROM Maximum TX power values
+ */
+#define EEPROM_MAX_TX_POWER		0x0027
+#define EEPROM_MAX_TX_POWER_24GHZ	FIELD16(0x00ff)
+#define EEPROM_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)
@@ -1926,8 +1999,17 @@
  * FRAG: 1 To inform TKIP engine this is a fragment.
  * MIMO_PS: The remote peer is in dynamic MIMO-PS mode
  * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs
- * BW: Channel bandwidth 20MHz or 40 MHz
+ * BW: Channel bandwidth 0:20MHz, 1:40 MHz (for legacy rates this will
+ *     duplicate the frame to both channels).
  * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED
+ * AMPDU: 1: this frame is eligible for AMPDU aggregation, the hw will
+ *        aggregate consecutive frames with the same RA and QoS TID. If
+ *        a frame A with the same RA and QoS TID but AMPDU=0 is queued
+ *        directly after a frame B with AMPDU=1, frame A might still
+ *        get aggregated into the AMPDU started by frame B. So, setting
+ *        AMPDU to 0 does _not_ necessarily mean the frame is sent as
+ *        MPDU, it can still end up in an AMPDU if the previous frame
+ *        was tagged as AMPDU.
  */
 #define TXWI_W0_FRAG			FIELD32(0x00000001)
 #define TXWI_W0_MIMO_PS			FIELD32(0x00000002)
@@ -1945,6 +2027,19 @@
 
 /*
  * Word1
+ * ACK: 0: No Ack needed, 1: Ack needed
+ * NSEQ: 0: Don't assign hw sequence number, 1: Assign hw sequence number
+ * BW_WIN_SIZE: BA windows size of the recipient
+ * WIRELESS_CLI_ID: Client ID for WCID table access
+ * MPDU_TOTAL_BYTE_COUNT: Length of 802.11 frame
+ * PACKETID: Will be latched into the TX_STA_FIFO register once the according
+ *           frame was processed. If multiple frames are aggregated together
+ *           (AMPDU==1) the reported tx status will always contain the packet
+ *           id of the first frame. 0: Don't report tx status for this frame.
+ * PACKETID_QUEUE: Part of PACKETID, This is the queue index (0-3)
+ * PACKETID_ENTRY: Part of PACKETID, THis is the queue entry index (1-3)
+ *                 This identification number is calculated by ((idx % 3) + 1).
+ *		   The (+1) is required to prevent PACKETID to become 0.
  */
 #define TXWI_W1_ACK			FIELD32(0x00000001)
 #define TXWI_W1_NSEQ			FIELD32(0x00000002)
@@ -1952,6 +2047,8 @@
 #define TXWI_W1_WIRELESS_CLI_ID		FIELD32(0x0000ff00)
 #define TXWI_W1_MPDU_TOTAL_BYTE_COUNT	FIELD32(0x0fff0000)
 #define TXWI_W1_PACKETID		FIELD32(0xf0000000)
+#define TXWI_W1_PACKETID_QUEUE		FIELD32(0x30000000)
+#define TXWI_W1_PACKETID_ENTRY		FIELD32(0xc0000000)
 
 /*
  * Word2
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index b66e0fd..5f00e00 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1,4 +1,5 @@
 /*
+	Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
 	Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com>
 	Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
 	Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com>
@@ -254,6 +255,23 @@
 }
 EXPORT_SYMBOL_GPL(rt2800_mcu_request);
 
+int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev)
+{
+	unsigned int i = 0;
+	u32 reg;
+
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+		if (reg && reg != ~0)
+			return 0;
+		msleep(1);
+	}
+
+	ERROR(rt2x00dev, "Unstable hardware.\n");
+	return -EBUSY;
+}
+EXPORT_SYMBOL_GPL(rt2800_wait_csr_ready);
+
 int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
 {
 	unsigned int i;
@@ -367,19 +385,16 @@
 	u32 reg;
 
 	/*
+	 * If driver doesn't wake up firmware here,
+	 * rt2800_load_firmware will hang forever when interface is up again.
+	 */
+	rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000);
+
+	/*
 	 * Wait for stable hardware.
 	 */
-	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-		rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
-		if (reg && reg != ~0)
-			break;
-		msleep(1);
-	}
-
-	if (i == REGISTER_BUSY_COUNT) {
-		ERROR(rt2x00dev, "Unstable hardware.\n");
+	if (rt2800_wait_csr_ready(rt2x00dev))
 		return -EBUSY;
-	}
 
 	if (rt2x00_is_pci(rt2x00dev))
 		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002);
@@ -427,8 +442,10 @@
 }
 EXPORT_SYMBOL_GPL(rt2800_load_firmware);
 
-void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc)
+void rt2800_write_tx_data(struct queue_entry *entry,
+			  struct txentry_desc *txdesc)
 {
+	__le32 *txwi = rt2800_drv_get_txwi(entry);
 	u32 word;
 
 	/*
@@ -437,7 +454,8 @@
 	rt2x00_desc_read(txwi, 0, &word);
 	rt2x00_set_field32(&word, TXWI_W0_FRAG,
 			   test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
-	rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0);
+	rt2x00_set_field32(&word, TXWI_W0_MIMO_PS,
+			   test_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags));
 	rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0);
 	rt2x00_set_field32(&word, TXWI_W0_TS,
 			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
@@ -465,7 +483,8 @@
 			   txdesc->key_idx : 0xff);
 	rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
 			   txdesc->length);
-	rt2x00_set_field32(&word, TXWI_W1_PACKETID, txdesc->queue + 1);
+	rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, txdesc->qid);
+	rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1);
 	rt2x00_desc_write(txwi, 1, word);
 
 	/*
@@ -478,9 +497,9 @@
 	_rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */);
 	_rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */);
 }
-EXPORT_SYMBOL_GPL(rt2800_write_txwi);
+EXPORT_SYMBOL_GPL(rt2800_write_tx_data);
 
-static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2)
+static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
 {
 	int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
 	int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
@@ -490,7 +509,7 @@
 	u8 offset1;
 	u8 offset2;
 
-	if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) {
+	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);
 		offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);
 		offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1);
@@ -569,6 +588,181 @@
 }
 EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
 
+static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
+{
+	__le32 *txwi;
+	u32 word;
+	int wcid, ack, pid;
+	int tx_wcid, tx_ack, tx_pid;
+
+	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
+	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
+	pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
+
+	/*
+	 * This frames has returned with an IO error,
+	 * so the status report is not intended for this
+	 * frame.
+	 */
+	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
+		rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+		return false;
+	}
+
+	/*
+	 * Validate if this TX status report is intended for
+	 * this entry by comparing the WCID/ACK/PID fields.
+	 */
+	txwi = rt2800_drv_get_txwi(entry);
+
+	rt2x00_desc_read(txwi, 1, &word);
+	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+	tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK);
+	tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID);
+
+	if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
+		WARNING(entry->queue->rt2x00dev,
+			"TX status report missed for queue %d entry %d\n",
+		entry->queue->qid, entry->entry_idx);
+		rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+		return false;
+	}
+
+	return true;
+}
+
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+	struct txdone_entry_desc txdesc;
+	u32 word;
+	u16 mcs, real_mcs;
+	int aggr, ampdu;
+	__le32 *txwi;
+
+	/*
+	 * Obtain the status about this packet.
+	 */
+	txdesc.flags = 0;
+	txwi = rt2800_drv_get_txwi(entry);
+	rt2x00_desc_read(txwi, 0, &word);
+
+	mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
+	ampdu = rt2x00_get_field32(word, TXWI_W0_AMPDU);
+
+	real_mcs = rt2x00_get_field32(status, TX_STA_FIFO_MCS);
+	aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE);
+
+	/*
+	 * If a frame was meant to be sent as a single non-aggregated MPDU
+	 * but ended up in an aggregate the used tx rate doesn't correlate
+	 * with the one specified in the TXWI as the whole aggregate is sent
+	 * with the same rate.
+	 *
+	 * For example: two frames are sent to rt2x00, the first one sets
+	 * AMPDU=1 and requests MCS7 whereas the second frame sets AMDPU=0
+	 * and requests MCS15. If the hw aggregates both frames into one
+	 * AMDPU the tx status for both frames will contain MCS7 although
+	 * the frame was sent successfully.
+	 *
+	 * Hence, replace the requested rate with the real tx rate to not
+	 * confuse the rate control algortihm by providing clearly wrong
+	 * data.
+	 */
+	if (aggr == 1 && ampdu == 0 && real_mcs != mcs) {
+		skbdesc->tx_rate_idx = real_mcs;
+		mcs = real_mcs;
+	}
+
+	/*
+	 * Ralink has a retry mechanism using a global fallback
+	 * table. We setup this fallback table to try the immediate
+	 * lower rate for all rates. In the TX_STA_FIFO, the MCS field
+	 * always contains the MCS used for the last transmission, be
+	 * it successful or not.
+	 */
+	if (rt2x00_get_field32(status, TX_STA_FIFO_TX_SUCCESS)) {
+		/*
+		 * Transmission succeeded. The number of retries is
+		 * mcs - real_mcs
+		 */
+		__set_bit(TXDONE_SUCCESS, &txdesc.flags);
+		txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0);
+	} else {
+		/*
+		 * Transmission failed. The number of retries is
+		 * always 7 in this case (for a total number of 8
+		 * frames sent).
+		 */
+		__set_bit(TXDONE_FAILURE, &txdesc.flags);
+		txdesc.retry = rt2x00dev->long_retry;
+	}
+
+	/*
+	 * the frame was retried at least once
+	 * -> hw used fallback rates
+	 */
+	if (txdesc.retry)
+		__set_bit(TXDONE_FALLBACK, &txdesc.flags);
+
+	rt2x00lib_txdone(entry, &txdesc);
+}
+EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
+
+void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue;
+	struct queue_entry *entry;
+	u32 reg;
+	u8 pid;
+	int i;
+
+	/*
+	 * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
+	 * at most X times and also stop processing once the TX_STA_FIFO_VALID
+	 * flag is not set anymore.
+	 *
+	 * The legacy drivers use X=TX_RING_SIZE but state in a comment
+	 * that the TX_STA_FIFO stack has a size of 16. We stick to our
+	 * tx ring size for now.
+	 */
+	for (i = 0; i < TX_ENTRIES; i++) {
+		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
+		if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
+			break;
+
+		/*
+		 * Skip this entry when it contains an invalid
+		 * queue identication number.
+		 */
+		pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+		if (pid >= QID_RX)
+			continue;
+
+		queue = rt2x00queue_get_queue(rt2x00dev, pid);
+		if (unlikely(!queue))
+			continue;
+
+		/*
+		 * Inside each queue, we process each entry in a chronological
+		 * order. We first check that the queue is not empty.
+		 */
+		entry = NULL;
+		while (!rt2x00queue_empty(queue)) {
+			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+			if (rt2800_txdone_entry_check(entry, reg))
+				break;
+		}
+
+		if (!entry || rt2x00queue_empty(queue))
+			break;
+
+		rt2800_txdone_entry(entry, reg);
+	}
+}
+EXPORT_SYMBOL_GPL(rt2800_txdone);
+
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -600,7 +794,7 @@
 	/*
 	 * Add the TXWI for the beacon to the skb.
 	 */
-	rt2800_write_txwi((__le32 *)entry->skb->data, txdesc);
+	rt2800_write_tx_data(entry, txdesc);
 
 	/*
 	 * Dump beacon to userspace through debugfs.
@@ -871,8 +1065,12 @@
 		 * 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 > (256 - 32))
+		if (crypto->aid > (222 - 32))
 			return -ENOSPC;
 
 		key->hw_key_idx = 32 + crypto->aid;
@@ -975,19 +1173,23 @@
 	}
 
 	if (flags & CONFIG_UPDATE_MAC) {
-		reg = le32_to_cpu(conf->mac[1]);
-		rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
-		conf->mac[1] = cpu_to_le32(reg);
+		if (!is_zero_ether_addr((const u8 *)conf->mac)) {
+			reg = le32_to_cpu(conf->mac[1]);
+			rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
+			conf->mac[1] = cpu_to_le32(reg);
+		}
 
 		rt2800_register_multiwrite(rt2x00dev, MAC_ADDR_DW0,
 					      conf->mac, sizeof(conf->mac));
 	}
 
 	if (flags & CONFIG_UPDATE_BSSID) {
-		reg = le32_to_cpu(conf->bssid[1]);
-		rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
-		rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
-		conf->bssid[1] = cpu_to_le32(reg);
+		if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
+			reg = le32_to_cpu(conf->bssid[1]);
+			rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
+			rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
+			conf->bssid[1] = cpu_to_le32(reg);
+		}
 
 		rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,
 					      conf->bssid, sizeof(conf->bssid));
@@ -995,38 +1197,149 @@
 }
 EXPORT_SYMBOL_GPL(rt2800_config_intf);
 
-void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp)
+static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
+				    struct rt2x00lib_erp *erp)
+{
+	bool any_sta_nongf = !!(erp->ht_opmode &
+				IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+	u8 protection = erp->ht_opmode & IEEE80211_HT_OP_MODE_PROTECTION;
+	u8 mm20_mode, mm40_mode, gf20_mode, gf40_mode;
+	u16 mm20_rate, mm40_rate, gf20_rate, gf40_rate;
+	u32 reg;
+
+	/* default protection rate for HT20: OFDM 24M */
+	mm20_rate = gf20_rate = 0x4004;
+
+	/* default protection rate for HT40: duplicate OFDM 24M */
+	mm40_rate = gf40_rate = 0x4084;
+
+	switch (protection) {
+	case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
+		/*
+		 * All STAs in this BSS are HT20/40 but there might be
+		 * STAs not supporting greenfield mode.
+		 * => Disable protection for HT transmissions.
+		 */
+		mm20_mode = mm40_mode = gf20_mode = gf40_mode = 0;
+
+		break;
+	case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
+		/*
+		 * All STAs in this BSS are HT20 or HT20/40 but there
+		 * might be STAs not supporting greenfield mode.
+		 * => Protect all HT40 transmissions.
+		 */
+		mm20_mode = gf20_mode = 0;
+		mm40_mode = gf40_mode = 2;
+
+		break;
+	case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
+		/*
+		 * Nonmember protection:
+		 * According to 802.11n we _should_ protect all
+		 * HT transmissions (but we don't have to).
+		 *
+		 * But if cts_protection is enabled we _shall_ protect
+		 * all HT transmissions using a CCK rate.
+		 *
+		 * And if any station is non GF we _shall_ protect
+		 * GF transmissions.
+		 *
+		 * We decide to protect everything
+		 * -> fall through to mixed mode.
+		 */
+	case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
+		/*
+		 * Legacy STAs are present
+		 * => Protect all HT transmissions.
+		 */
+		mm20_mode = mm40_mode = gf20_mode = gf40_mode = 2;
+
+		/*
+		 * If erp protection is needed we have to protect HT
+		 * transmissions with CCK 11M long preamble.
+		 */
+		if (erp->cts_protection) {
+			/* don't duplicate RTS/CTS in CCK mode */
+			mm20_rate = mm40_rate = 0x0003;
+			gf20_rate = gf40_rate = 0x0003;
+		}
+		break;
+	};
+
+	/* check for STAs not supporting greenfield mode */
+	if (any_sta_nongf)
+		gf20_mode = gf40_mode = 2;
+
+	/* Update HT protection config */
+	rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, mm20_rate);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, mm20_mode);
+	rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
+
+	rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, mm40_rate);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, mm40_mode);
+	rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
+
+	rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, gf20_rate);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, gf20_mode);
+	rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
+
+	rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, gf40_rate);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, gf40_mode);
+	rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
+}
+
+void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
+		       u32 changed)
 {
 	u32 reg;
 
-	rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
-	rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
-			   !!erp->short_preamble);
-	rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
-			   !!erp->short_preamble);
-	rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+		rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
+				   !!erp->short_preamble);
+		rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
+				   !!erp->short_preamble);
+		rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
+	}
 
-	rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
-	rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
-			   erp->cts_protection ? 2 : 0);
-	rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
+		rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+		rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
+				   erp->cts_protection ? 2 : 0);
+		rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+	}
 
-	rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE,
-				 erp->basic_rates);
-	rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+	if (changed & BSS_CHANGED_BASIC_RATES) {
+		rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE,
+					 erp->basic_rates);
+		rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+	}
 
-	rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
-	rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time);
-	rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
+		rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME,
+				   erp->slot_time);
+		rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
 
-	rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
-	rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
-	rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
+		rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
+		rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
+		rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
+	}
 
-	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
-			   erp->beacon_int * 16);
-	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
+				   erp->beacon_int * 16);
+		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+	}
+
+	if (changed & BSS_CHANGED_HT)
+		rt2800_config_ht_opmode(rt2x00dev, erp);
 }
 EXPORT_SYMBOL_GPL(rt2800_config_erp);
 
@@ -1120,27 +1433,23 @@
 		 * double meaning, and we should set a 7DBm boost flag.
 		 */
 		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,
-				   (info->tx_power1 >= 0));
+				   (info->default_power1 >= 0));
 
-		if (info->tx_power1 < 0)
-			info->tx_power1 += 7;
+		if (info->default_power1 < 0)
+			info->default_power1 += 7;
 
-		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A,
-				   TXPOWER_A_TO_DEV(info->tx_power1));
+		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->default_power1);
 
 		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,
-				   (info->tx_power2 >= 0));
+				   (info->default_power2 >= 0));
 
-		if (info->tx_power2 < 0)
-			info->tx_power2 += 7;
+		if (info->default_power2 < 0)
+			info->default_power2 += 7;
 
-		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A,
-				   TXPOWER_A_TO_DEV(info->tx_power2));
+		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->default_power2);
 	} else {
-		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G,
-				   TXPOWER_G_TO_DEV(info->tx_power1));
-		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G,
-				   TXPOWER_G_TO_DEV(info->tx_power2));
+		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->default_power1);
+		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->default_power2);
 	}
 
 	rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));
@@ -1180,13 +1489,11 @@
 	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
 
 	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
-	rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
-			  TXPOWER_G_TO_DEV(info->tx_power1));
+	rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->default_power1);
 	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
 
 	rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
-	rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
-			  TXPOWER_G_TO_DEV(info->tx_power2));
+	rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2);
 	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
 
 	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
@@ -1210,10 +1517,19 @@
 	unsigned int tx_pin;
 	u8 bbp;
 
+	if (rf->channel <= 14) {
+		info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1);
+		info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2);
+	} else {
+		info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1);
+		info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2);
+	}
+
 	if (rt2x00_rf(rt2x00dev, RF2020) ||
 	    rt2x00_rf(rt2x00dev, RF3020) ||
 	    rt2x00_rf(rt2x00dev, RF3021) ||
-	    rt2x00_rf(rt2x00dev, RF3022))
+	    rt2x00_rf(rt2x00dev, RF3022) ||
+	    rt2x00_rf(rt2x00dev, RF3052))
 		rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
 	else
 		rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
@@ -1536,7 +1852,7 @@
 /*
  * Initialization functions.
  */
-int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
+static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 {
 	u32 reg;
 	u16 eeprom;
@@ -1728,8 +2044,7 @@
 
 	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,
-			   !rt2x00_is_usb(rt2x00dev));
+	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_TX_OP_ALLOW_CCK, 1);
 	rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
@@ -1886,6 +2201,14 @@
 	rt2800_register_write(rt2x00dev, LG_FBK_CFG1, reg);
 
 	/*
+	 * Do not force the BA window size, we use the TXWI to set it
+	 */
+	rt2800_register_read(rt2x00dev, AMPDU_BA_WINSIZE, &reg);
+	rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE, 0);
+	rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE, 0);
+	rt2800_register_write(rt2x00dev, AMPDU_BA_WINSIZE, reg);
+
+	/*
 	 * We must clear the error counters.
 	 * These registers are cleared on read,
 	 * so we may pass a useless variable to store the value.
@@ -1906,7 +2229,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(rt2800_init_registers);
 
 static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
 {
@@ -1949,7 +2271,7 @@
 	return -EACCES;
 }
 
-int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 {
 	unsigned int i;
 	u16 eeprom;
@@ -2044,7 +2366,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(rt2800_init_bbp);
 
 static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,
 				bool bw40, u8 rfcsr24, u8 filter_target)
@@ -2106,7 +2427,7 @@
 	return rfcsr24;
 }
 
-int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 {
 	u8 rfcsr;
 	u8 bbp;
@@ -2360,7 +2681,100 @@
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(rt2800_init_rfcsr);
+
+int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+	u16 word;
+
+	/*
+	 * Initialize all registers.
+	 */
+	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
+		     rt2800_init_registers(rt2x00dev) ||
+		     rt2800_init_bbp(rt2x00dev) ||
+		     rt2800_init_rfcsr(rt2x00dev)))
+		return -EIO;
+
+	/*
+	 * Send signal to firmware during boot time.
+	 */
+	rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
+
+	if (rt2x00_is_usb(rt2x00dev) &&
+	    (rt2x00_rt(rt2x00dev, RT3070) ||
+	     rt2x00_rt(rt2x00dev, RT3071) ||
+	     rt2x00_rt(rt2x00dev, RT3572))) {
+		udelay(200);
+		rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);
+		udelay(10);
+	}
+
+	/*
+	 * Enable RX.
+	 */
+	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
+	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
+	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+	udelay(50);
+
+	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
+	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+
+	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
+	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
+	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+	/*
+	 * Initialize LED control
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word);
+	rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
+			   word & 0xff, (word >> 8) & 0xff);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word);
+	rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
+			   word & 0xff, (word >> 8) & 0xff);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word);
+	rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
+			   word & 0xff, (word >> 8) & 0xff);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_enable_radio);
+
+void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+
+	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 */
+	rt2800_wait_wpdma_ready(rt2x00dev);
+
+	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+	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);
 
 int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
 {
@@ -2516,6 +2930,13 @@
 				   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);
@@ -2755,9 +3176,10 @@
 {
 	struct hw_mode_spec *spec = &rt2x00dev->spec;
 	struct channel_info *info;
-	char *tx_power1;
-	char *tx_power2;
+	char *default_power1;
+	char *default_power2;
 	unsigned int i;
+	unsigned short max_power;
 	u16 eeprom;
 
 	/*
@@ -2770,11 +3192,20 @@
 	 * Initialize all hw fields.
 	 */
 	rt2x00dev->hw->flags =
-	    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 	    IEEE80211_HW_SIGNAL_DBM |
 	    IEEE80211_HW_SUPPORTS_PS |
 	    IEEE80211_HW_PS_NULLFUNC_STACK |
 	    IEEE80211_HW_AMPDU_AGGREGATION;
+	/*
+	 * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices
+	 * unless we are capable of sending the buffered frames out after the
+	 * DTIM transmission using rt2x00lib_beacondone. This will send out
+	 * multicast and broadcast traffic immediately instead of buffering it
+	 * infinitly and thus dropping it after some time.
+	 */
+	if (!rt2x00_is_usb(rt2x00dev))
+		rt2x00dev->hw->flags |=
+			IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
 	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -2785,12 +3216,13 @@
 	 * As rt2800 has a global fallback table we cannot specify
 	 * more then one tx rate per frame but since the hw will
 	 * try several rates (based on the fallback table) we should
-	 * still initialize max_rates to the maximum number of rates
+	 * initialize max_report_rates to the maximum number of rates
 	 * we are going to try. Otherwise mac80211 will truncate our
 	 * reported tx rates and the rc algortihm will end up with
 	 * incorrect data.
 	 */
-	rt2x00dev->hw->max_rates = 7;
+	rt2x00dev->hw->max_rates = 1;
+	rt2x00dev->hw->max_report_rates = 7;
 	rt2x00dev->hw->max_rate_tries = 1;
 
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
@@ -2865,27 +3297,32 @@
 	/*
 	 * Create channel information array
 	 */
-	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+	info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
 	spec->channels_info = info;
 
-	tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
-	tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
+	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].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]);
-		info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[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]);
 	}
 
 	if (spec->num_channels > 14) {
-		tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
-		tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
+		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].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]);
-			info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[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]);
 		}
 	}
 
@@ -3042,8 +3479,12 @@
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
 	case IEEE80211_AMPDU_RX_STOP:
-		/* we don't support RX aggregation yet */
-		ret = -ENOTSUPP;
+		/*
+		 * The hw itself takes care of setting up BlockAck mechanisms.
+		 * So, we only have to allow mac80211 to nagotiate a BlockAck
+		 * agreement. Once that is done, the hw will BlockAck incoming
+		 * AMPDUs without further setup.
+		 */
 		break;
 	case IEEE80211_AMPDU_TX_START:
 		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 091641e..81cbc92 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -1,4 +1,6 @@
 /*
+	Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+	Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com>
 	Copyright (C) 2009 Bartlomiej Zolnierkiewicz
 
 	This program is free software; you can redistribute it and/or modify
@@ -44,6 +46,7 @@
 	int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev,
 				  const u8 *data, const size_t len);
 	int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
+	__le32 *(*drv_get_txwi)(struct queue_entry *entry);
 };
 
 static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
@@ -126,18 +129,32 @@
 	return rt2800ops->drv_init_registers(rt2x00dev);
 }
 
+static inline __le32 *rt2800_drv_get_txwi(struct queue_entry *entry)
+{
+	const struct rt2800_ops *rt2800ops = entry->queue->rt2x00dev->ops->drv;
+
+	return rt2800ops->drv_get_txwi(entry);
+}
+
 void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
 			const u8 command, const u8 token,
 			const u8 arg0, const u8 arg1);
 
+int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev);
+int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev);
+
 int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
 			  const u8 *data, const size_t len);
 int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
 			 const u8 *data, const size_t len);
 
-void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc);
+void rt2800_write_tx_data(struct queue_entry *entry,
+			  struct txentry_desc *txdesc);
 void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
 
+void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status);
+
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
 
 extern const struct rt2x00debug rt2800_rt2x00debug;
@@ -153,7 +170,8 @@
 			  const unsigned int filter_flags);
 void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 			struct rt2x00intf_conf *conf, const unsigned int flags);
-void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp);
+void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
+		       u32 changed);
 void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant);
 void rt2800_config(struct rt2x00_dev *rt2x00dev,
 		   struct rt2x00lib_conf *libconf,
@@ -163,10 +181,8 @@
 void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
 		       const u32 count);
 
-int rt2800_init_registers(struct rt2x00_dev *rt2x00dev);
-int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev);
-int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev);
-int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev);
+int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
+void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
 
 int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev);
 void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 39b3846..b267395 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1,5 +1,5 @@
 /*
-	Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
 	Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
 	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
 	Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
@@ -196,8 +196,6 @@
 {
 	u32 reg;
 
-	rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000);
-
 	/*
 	 * enable Host program ram write selection
 	 */
@@ -243,6 +241,7 @@
 {
 	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	u32 word;
 
 	if (entry->queue->qid == QID_RX) {
@@ -253,6 +252,13 @@
 		rt2x00_desc_read(entry_priv->desc, 1, &word);
 		rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0);
 		rt2x00_desc_write(entry_priv->desc, 1, word);
+
+		/*
+		 * Set RX IDX in register to inform hardware that we have
+		 * handled this entry and it is available for reuse again.
+		 */
+		rt2800_register_write(rt2x00dev, RX_CRX_IDX,
+				      entry->entry_idx);
 	} else {
 		rt2x00_desc_read(entry_priv->desc, 1, &word);
 		rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
@@ -344,24 +350,24 @@
 	}
 
 	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, mask);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_AC0_DMA_DONE, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_AC1_DMA_DONE, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_AC2_DMA_DONE, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_AC3_DMA_DONE, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_HCCA_DMA_DONE, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_MGMT_DMA_DONE, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_MCU_COMMAND, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_RXTX_COHERENT, mask);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_AC0_DMA_DONE, 0);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_AC1_DMA_DONE, 0);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_AC2_DMA_DONE, 0);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_AC3_DMA_DONE, 0);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_HCCA_DMA_DONE, 0);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_MGMT_DMA_DONE, 0);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_MCU_COMMAND, 0);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_RXTX_COHERENT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, mask);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, mask);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, mask);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, mask);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, mask);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
+	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);
 }
 
@@ -399,78 +405,18 @@
 
 static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
 {
-	u32 reg;
-	u16 word;
-
-	/*
-	 * Initialize all registers.
-	 */
 	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
-		     rt2800pci_init_queues(rt2x00dev) ||
-		     rt2800_init_registers(rt2x00dev) ||
-		     rt2800_wait_wpdma_ready(rt2x00dev) ||
-		     rt2800_init_bbp(rt2x00dev) ||
-		     rt2800_init_rfcsr(rt2x00dev)))
+		     rt2800pci_init_queues(rt2x00dev)))
 		return -EIO;
 
-	/*
-	 * Send signal to firmware during boot time.
-	 */
-	rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
-
-	/*
-	 * Enable RX.
-	 */
-	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
-	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
-	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
-	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
-	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-
-	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
-	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
-	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
-	/*
-	 * Initialize LED control
-	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word);
-	rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
-			      word & 0xff, (word >> 8) & 0xff);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word);
-	rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
-			      word & 0xff, (word >> 8) & 0xff);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word);
-	rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
-			      word & 0xff, (word >> 8) & 0xff);
-
-	return 0;
+	return rt2800_enable_radio(rt2x00dev);
 }
 
 static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
 	u32 reg;
 
-	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);
-
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
-	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
-	rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
+	rt2800_disable_radio(rt2x00dev);
 
 	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280);
 
@@ -486,9 +432,6 @@
 
 	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
 	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
-
-	/* Wait for DMA, ignore error */
-	rt2800_wait_wpdma_ready(rt2x00dev);
 }
 
 static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -566,21 +509,16 @@
 /*
  * TX descriptor initialization
  */
-static void rt2800pci_write_tx_data(struct queue_entry* entry,
-				    struct txentry_desc *txdesc)
+static __le32 *rt2800pci_get_txwi(struct queue_entry *entry)
 {
-	__le32 *txwi = (__le32 *) entry->skb->data;
-
-	rt2800_write_txwi(txwi, txdesc);
+	return (__le32 *) entry->skb->data;
 }
 
-
-static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-				    struct sk_buff *skb,
+static void rt2800pci_write_tx_desc(struct queue_entry *entry,
 				    struct txentry_desc *txdesc)
 {
-	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-	struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 	__le32 *txd = entry_priv->desc;
 	u32 word;
 
@@ -600,7 +538,7 @@
 	rt2x00_desc_write(txd, 0, word);
 
 	rt2x00_desc_read(txd, 1, &word);
-	rt2x00_set_field32(&word, TXD_W1_SD_LEN1, skb->len);
+	rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len);
 	rt2x00_set_field32(&word, TXD_W1_LAST_SEC1,
 			   !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W1_BURST,
@@ -631,41 +569,35 @@
 /*
  * TX data initialization
  */
-static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-				    const enum data_queue_qid queue_idx)
+static void rt2800pci_kick_tx_queue(struct data_queue *queue)
 {
-	struct data_queue *queue;
-	unsigned int idx, qidx = 0;
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
+	unsigned int qidx;
 
-	if (queue_idx > QID_HCCA && queue_idx != QID_MGMT)
-		return;
-
-	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
-	idx = queue->index[Q_INDEX];
-
-	if (queue_idx == QID_MGMT)
+	if (queue->qid == QID_MGMT)
 		qidx = 5;
 	else
-		qidx = queue_idx;
+		qidx = queue->qid;
 
-	rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx);
+	rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), entry->entry_idx);
 }
 
-static void rt2800pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
-				    const enum data_queue_qid qid)
+static void rt2800pci_kill_tx_queue(struct data_queue *queue)
 {
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 	u32 reg;
 
-	if (qid == QID_BEACON) {
+	if (queue->qid == QID_BEACON) {
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, 0);
 		return;
 	}
 
 	rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, (qid == QID_AC_BE));
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, (qid == QID_AC_BK));
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, (qid == QID_AC_VI));
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, (qid == QID_AC_VO));
+	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, (queue->qid == QID_AC_BE));
+	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, (queue->qid == QID_AC_BK));
+	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, (queue->qid == QID_AC_VI));
+	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, (queue->qid == QID_AC_VO));
 	rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
 }
 
@@ -675,7 +607,6 @@
 static void rt2800pci_fill_rxdone(struct queue_entry *entry,
 				  struct rxdone_entry_desc *rxdesc)
 {
-	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 	__le32 *rxd = entry_priv->desc;
 	u32 word;
@@ -717,121 +648,11 @@
 	 * Process the RXWI structure that is at the start of the buffer.
 	 */
 	rt2800_process_rxwi(entry, rxdesc);
-
-	/*
-	 * Set RX IDX in register to inform hardware that we have handled
-	 * this entry and it is available for reuse again.
-	 */
-	rt2800_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx);
 }
 
 /*
  * Interrupt functions.
  */
-static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
-{
-	struct data_queue *queue;
-	struct queue_entry *entry;
-	__le32 *txwi;
-	struct txdone_entry_desc txdesc;
-	u32 word;
-	u32 reg;
-	int wcid, ack, pid, tx_wcid, tx_ack, tx_pid;
-	u16 mcs, real_mcs;
-	int i;
-
-	/*
-	 * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
-	 * at most X times and also stop processing once the TX_STA_FIFO_VALID
-	 * flag is not set anymore.
-	 *
-	 * The legacy drivers use X=TX_RING_SIZE but state in a comment
-	 * that the TX_STA_FIFO stack has a size of 16. We stick to our
-	 * tx ring size for now.
-	 */
-	for (i = 0; i < TX_ENTRIES; i++) {
-		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
-		if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
-			break;
-
-		wcid    = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
-		ack     = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
-		pid     = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
-
-		/*
-		 * Skip this entry when it contains an invalid
-		 * queue identication number.
-		 */
-		if (pid <= 0 || pid > QID_RX)
-			continue;
-
-		queue = rt2x00queue_get_queue(rt2x00dev, pid - 1);
-		if (unlikely(!queue))
-			continue;
-
-		/*
-		 * Inside each queue, we process each entry in a chronological
-		 * order. We first check that the queue is not empty.
-		 */
-		if (rt2x00queue_empty(queue))
-			continue;
-		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-
-		/* Check if we got a match by looking at WCID/ACK/PID
-		 * fields */
-		txwi = (__le32 *) entry->skb->data;
-
-		rt2x00_desc_read(txwi, 1, &word);
-		tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
-		tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK);
-		tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID);
-
-		if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid))
-			WARNING(rt2x00dev, "invalid TX_STA_FIFO content\n");
-
-		/*
-		 * Obtain the status about this packet.
-		 */
-		txdesc.flags = 0;
-		rt2x00_desc_read(txwi, 0, &word);
-		mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
-		real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS);
-
-		/*
-		 * Ralink has a retry mechanism using a global fallback
-		 * table. We setup this fallback table to try the immediate
-		 * lower rate for all rates. In the TX_STA_FIFO, the MCS field
-		 * always contains the MCS used for the last transmission, be
-		 * it successful or not.
-		 */
-		if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) {
-			/*
-			 * Transmission succeeded. The number of retries is
-			 * mcs - real_mcs
-			 */
-			__set_bit(TXDONE_SUCCESS, &txdesc.flags);
-			txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0);
-		} else {
-			/*
-			 * Transmission failed. The number of retries is
-			 * always 7 in this case (for a total number of 8
-			 * frames sent).
-			 */
-			__set_bit(TXDONE_FAILURE, &txdesc.flags);
-			txdesc.retry = 7;
-		}
-
-		/*
-		 * the frame was retried at least once
-		 * -> hw used fallback rates
-		 */
-		if (txdesc.retry)
-			__set_bit(TXDONE_FALLBACK, &txdesc.flags);
-
-		rt2x00lib_txdone(entry, &txdesc);
-	}
-}
-
 static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
 {
 	struct ieee80211_conf conf = { .flags = 0 };
@@ -840,6 +661,63 @@
 	rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 }
 
+static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue;
+	struct queue_entry *entry;
+	u32 status;
+	u8 qid;
+
+	while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
+		/* Now remove the tx status from the FIFO */
+		if (kfifo_out(&rt2x00dev->txstatus_fifo, &status,
+			      sizeof(status)) != sizeof(status)) {
+			WARN_ON(1);
+			break;
+		}
+
+		qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
+		if (qid >= QID_RX) {
+			/*
+			 * Unknown queue, this shouldn't happen. Just drop
+			 * this tx status.
+			 */
+			WARNING(rt2x00dev, "Got TX status report with "
+					   "unexpected pid %u, dropping", qid);
+			break;
+		}
+
+		queue = rt2x00queue_get_queue(rt2x00dev, qid);
+		if (unlikely(queue == NULL)) {
+			/*
+			 * The queue is NULL, this shouldn't happen. Stop
+			 * processing here and drop the tx status
+			 */
+			WARNING(rt2x00dev, "Got TX status for an unavailable "
+					   "queue %u, dropping", qid);
+			break;
+		}
+
+		if (rt2x00queue_empty(queue)) {
+			/*
+			 * The queue is empty. Stop processing here
+			 * and drop the tx status.
+			 */
+			WARNING(rt2x00dev, "Got TX status for an empty "
+					   "queue %u, dropping", qid);
+			break;
+		}
+
+		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+		rt2800_txdone_entry(entry, status);
+	}
+}
+
+static void rt2800pci_txstatus_tasklet(unsigned long data)
+{
+	rt2800pci_txdone((struct rt2x00_dev *)data);
+}
+
 static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
@@ -864,13 +742,7 @@
 		rt2x00pci_rxdone(rt2x00dev);
 
 	/*
-	 * 4 - Tx done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
-		rt2800pci_txdone(rt2x00dev);
-
-	/*
-	 * 5 - Auto wakeup interrupt.
+	 * 4 - Auto wakeup interrupt.
 	 */
 	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
 		rt2800pci_wakeup(rt2x00dev);
@@ -882,10 +754,58 @@
 	return IRQ_HANDLED;
 }
 
+static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
+{
+	u32 status;
+	int i;
+
+	/*
+	 * The TX_FIFO_STATUS interrupt needs special care. We should
+	 * read TX_STA_FIFO but we should do it immediately as otherwise
+	 * the register can overflow and we would lose status reports.
+	 *
+	 * Hence, read the TX_STA_FIFO register and copy all tx status
+	 * reports into a kernel FIFO which is handled in the txstatus
+	 * tasklet. We use a tasklet to process the tx status reports
+	 * because we can schedule the tasklet multiple times (when the
+	 * interrupt fires again during tx status processing).
+	 *
+	 * 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.
+	 *
+	 * Since we have only one producer and one consumer we don't
+	 * need to lock the kfifo.
+	 */
+	for (i = 0; i < TX_ENTRIES; i++) {
+		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status);
+
+		if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
+			break;
+
+		if (kfifo_is_full(&rt2x00dev->txstatus_fifo)) {
+			WARNING(rt2x00dev, "TX status FIFO overrun,"
+				" drop tx status report.\n");
+			break;
+		}
+
+		if (kfifo_in(&rt2x00dev->txstatus_fifo, &status,
+			     sizeof(status)) != sizeof(status)) {
+			WARNING(rt2x00dev, "TX status FIFO overrun,"
+				"drop tx status report.\n");
+			break;
+		}
+	}
+
+	/* Schedule the tasklet for processing the tx status. */
+	tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+}
+
 static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
 	u32 reg;
+	irqreturn_t ret = IRQ_HANDLED;
 
 	/* Read status and ACK all interrupts */
 	rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
@@ -897,15 +817,38 @@
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return IRQ_HANDLED;
 
-	/* Store irqvalue for use in the interrupt thread. */
-	rt2x00dev->irqvalue[0] = reg;
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
+		rt2800pci_txstatus_interrupt(rt2x00dev);
 
-	/* 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) ||
+	    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)) {
+		/*
+		 * All other interrupts are handled in the interrupt thread.
+		 * Store irqvalue for use in the interrupt thread.
+		 */
+		rt2x00dev->irqvalue[0] = reg;
 
+		/*
+		 * 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;
+		/*
+		 * 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);
+
+		ret = IRQ_WAKE_THREAD;
+	}
+
+	return ret;
 }
 
 /*
@@ -968,6 +911,7 @@
 		__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
 	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
 	__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags);
 	if (!modparam_nohwcrypt)
 		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
 	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
@@ -1011,11 +955,13 @@
 	.regbusy_read		= rt2x00pci_regbusy_read,
 	.drv_write_firmware	= rt2800pci_write_firmware,
 	.drv_init_registers	= rt2800pci_init_registers,
+	.drv_get_txwi		= rt2800pci_get_txwi,
 };
 
 static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.irq_handler		= rt2800pci_interrupt,
 	.irq_handler_thread	= rt2800pci_interrupt_thread,
+	.txstatus_tasklet       = rt2800pci_txstatus_tasklet,
 	.probe_hw		= rt2800pci_probe_hw,
 	.get_firmware_name	= rt2800pci_get_firmware_name,
 	.check_firmware		= rt2800_check_firmware,
@@ -1030,7 +976,7 @@
 	.reset_tuner		= rt2800_reset_tuner,
 	.link_tuner		= rt2800_link_tuner,
 	.write_tx_desc		= rt2800pci_write_tx_desc,
-	.write_tx_data		= rt2800pci_write_tx_data,
+	.write_tx_data		= rt2800_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
 	.kick_tx_queue		= rt2800pci_kick_tx_queue,
 	.kill_tx_queue		= rt2800pci_kill_tx_queue,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 5a2dfe8..3dff56e 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1,5 +1,6 @@
 /*
-	Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+	Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
 	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
 	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
 	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
@@ -100,19 +101,6 @@
 	msleep(10);
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 
-	/*
-	 * Send signal to firmware during boot time.
-	 */
-	rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
-
-	if (rt2x00_rt(rt2x00dev, RT3070) ||
-	    rt2x00_rt(rt2x00dev, RT3071) ||
-	    rt2x00_rt(rt2x00dev, RT3572)) {
-		udelay(200);
-		rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);
-		udelay(10);
-	}
-
 	return 0;
 }
 
@@ -134,26 +122,18 @@
 static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
 {
 	u32 reg;
-	int i;
 
 	/*
 	 * Wait until BBP and RF are ready.
 	 */
-	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-		rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
-		if (reg && reg != ~0)
-			break;
-		msleep(1);
-	}
-
-	if (i == REGISTER_BUSY_COUNT) {
-		ERROR(rt2x00dev, "Unstable hardware.\n");
+	if (rt2800_wait_csr_ready(rt2x00dev))
 		return -EBUSY;
-	}
 
 	rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
 	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
 
+	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+
 	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
@@ -172,30 +152,10 @@
 static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
 {
 	u32 reg;
-	u16 word;
 
-	/*
-	 * Initialize all registers.
-	 */
-	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
-		     rt2800_init_registers(rt2x00dev) ||
-		     rt2800_init_bbp(rt2x00dev) ||
-		     rt2800_init_rfcsr(rt2x00dev)))
+	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
 		return -EIO;
 
-	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
-	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
-	udelay(50);
-
-	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
-	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-
-
 	rt2800_register_read(rt2x00dev, USB_DMA_CFG, &reg);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
@@ -210,45 +170,12 @@
 	rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
 	rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg);
 
-	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
-	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
-	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
-	/*
-	 * Initialize LED control
-	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word);
-	rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
-			      word & 0xff, (word >> 8) & 0xff);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word);
-	rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
-			      word & 0xff, (word >> 8) & 0xff);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word);
-	rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
-			      word & 0xff, (word >> 8) & 0xff);
-
-	return 0;
+	return rt2800_enable_radio(rt2x00dev);
 }
 
 static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
-	u32 reg;
-
-	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_ENABLE_RX_DMA, 0);
-	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
-	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
-	rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
-
-	/* Wait for DMA, ignore error */
-	rt2800_wait_wpdma_ready(rt2x00dev);
-
+	rt2800_disable_radio(rt2x00dev);
 	rt2x00usb_disable_radio(rt2x00dev);
 }
 
@@ -320,21 +247,19 @@
 /*
  * TX descriptor initialization
  */
-static void rt2800usb_write_tx_data(struct queue_entry* entry,
-				    struct txentry_desc *txdesc)
+static __le32 *rt2800usb_get_txwi(struct queue_entry *entry)
 {
-	__le32 *txwi = (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE);
-
-	rt2800_write_txwi(txwi, txdesc);
+	if (entry->queue->qid == QID_BEACON)
+		return (__le32 *) (entry->skb->data);
+	else
+		return (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE);
 }
 
-
-static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-				    struct sk_buff *skb,
+static void rt2800usb_write_tx_desc(struct queue_entry *entry,
 				    struct txentry_desc *txdesc)
 {
-	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-	__le32 *txi = (__le32 *) skb->data;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+	__le32 *txi = (__le32 *) entry->skb->data;
 	u32 word;
 
 	/*
@@ -342,7 +267,7 @@
 	 */
 	rt2x00_desc_read(txi, 0, &word);
 	rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
-			   skb->len - TXINFO_DESC_SIZE);
+			   entry->skb->len - TXINFO_DESC_SIZE);
 	rt2x00_set_field32(&word, TXINFO_W0_WIV,
 			   !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
 	rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
@@ -379,6 +304,46 @@
 }
 
 /*
+ * TX control handlers
+ */
+static void rt2800usb_work_txdone(struct work_struct *work)
+{
+	struct rt2x00_dev *rt2x00dev =
+	    container_of(work, struct rt2x00_dev, txdone_work);
+	struct data_queue *queue;
+	struct queue_entry *entry;
+
+	rt2800_txdone(rt2x00dev);
+
+	/*
+	 * Process any trailing TX status reports for IO failures,
+	 * we loop until we find the first non-IO error entry. This
+	 * can either be a frame which is free, is being uploaded,
+	 * or has completed the upload but didn't have an entry
+	 * in the TX_STAT_FIFO register yet.
+	 */
+	tx_queue_for_each(rt2x00dev, queue) {
+		while (!rt2x00queue_empty(queue)) {
+			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+
+			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+			    !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+				break;
+
+			rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+		}
+	}
+}
+
+static void rt2800usb_kill_tx_queue(struct data_queue *queue)
+{
+	if (queue->qid == QID_BEACON)
+		rt2x00usb_register_write(queue->rt2x00dev, BCN_TIME_CFG, 0);
+
+	rt2x00usb_kill_tx_queue(queue);
+}
+
+/*
  * RX control handlers
  */
 static void rt2800usb_fill_rxdone(struct queue_entry *entry,
@@ -514,6 +479,11 @@
 	 */
 	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
 
+	/*
+	 * Overwrite TX done handler
+	 */
+	PREPARE_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);
+
 	return 0;
 }
 
@@ -549,6 +519,7 @@
 	.regbusy_read		= rt2x00usb_regbusy_read,
 	.drv_write_firmware	= rt2800usb_write_firmware,
 	.drv_init_registers	= rt2800usb_init_registers,
+	.drv_get_txwi		= rt2800usb_get_txwi,
 };
 
 static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
@@ -566,11 +537,11 @@
 	.link_tuner		= rt2800_link_tuner,
 	.watchdog		= rt2x00usb_watchdog,
 	.write_tx_desc		= rt2800usb_write_tx_desc,
-	.write_tx_data		= rt2800usb_write_tx_data,
+	.write_tx_data		= rt2800_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
 	.get_tx_data_len	= rt2800usb_get_tx_data_len,
 	.kick_tx_queue		= rt2x00usb_kick_tx_queue,
-	.kill_tx_queue		= rt2x00usb_kill_tx_queue,
+	.kill_tx_queue		= rt2800usb_kill_tx_queue,
 	.fill_rxdone		= rt2800usb_fill_rxdone,
 	.config_shared_key	= rt2800_config_shared_key,
 	.config_pairwise_key	= rt2800_config_pairwise_key,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index c21af38..94fe589 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1,5 +1,6 @@
 /*
-	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+	Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
 	Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 
@@ -35,6 +36,7 @@
 #include <linux/mutex.h>
 #include <linux/etherdevice.h>
 #include <linux/input-polldev.h>
+#include <linux/kfifo.h>
 
 #include <net/mac80211.h>
 
@@ -212,8 +214,9 @@
 	unsigned int flags;
 #define GEOGRAPHY_ALLOWED	0x00000001
 
-	short tx_power1;
-	short tx_power2;
+	short max_power;
+	short default_power1;
+	short default_power2;
 };
 
 /*
@@ -335,6 +338,11 @@
 
 	/*
 	 * Work structure for scheduling periodic watchdog monitoring.
+	 * This work must be scheduled on the kernel workqueue, while
+	 * all other work structures must be queued on the mac80211
+	 * workqueue. This guarantees that the watchdog can schedule
+	 * other work structures and wait for their completion in order
+	 * to bring the device/driver back into the desired state.
 	 */
 	struct delayed_work watchdog_work;
 };
@@ -455,6 +463,7 @@
 	short eifs;
 
 	u16 beacon_int;
+	u16 ht_opmode;
 };
 
 /*
@@ -520,6 +529,11 @@
 	irq_handler_t irq_handler_thread;
 
 	/*
+	 * TX status tasklet handler.
+	 */
+	void (*txstatus_tasklet) (unsigned long data);
+
+	/*
 	 * Device init handlers.
 	 */
 	int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
@@ -558,18 +572,15 @@
 	/*
 	 * TX control handlers
 	 */
-	void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
-			       struct sk_buff *skb,
+	void (*write_tx_desc) (struct queue_entry *entry,
 			       struct txentry_desc *txdesc);
 	void (*write_tx_data) (struct queue_entry *entry,
 			       struct txentry_desc *txdesc);
 	void (*write_beacon) (struct queue_entry *entry,
 			      struct txentry_desc *txdesc);
 	int (*get_tx_data_len) (struct queue_entry *entry);
-	void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
-			       const enum data_queue_qid queue);
-	void (*kill_tx_queue) (struct rt2x00_dev *rt2x00dev,
-			       const enum data_queue_qid queue);
+	void (*kick_tx_queue) (struct data_queue *queue);
+	void (*kill_tx_queue) (struct data_queue *queue);
 
 	/*
 	 * RX control handlers
@@ -597,7 +608,8 @@
 #define CONFIG_UPDATE_BSSID		( 1 << 3 )
 
 	void (*config_erp) (struct rt2x00_dev *rt2x00dev,
-			    struct rt2x00lib_erp *erp);
+			    struct rt2x00lib_erp *erp,
+			    u32 changed);
 	void (*config_ant) (struct rt2x00_dev *rt2x00dev,
 			    struct antenna_setup *ant);
 	void (*config) (struct rt2x00_dev *rt2x00dev,
@@ -651,6 +663,7 @@
 	DRIVER_REQUIRE_DMA,
 	DRIVER_REQUIRE_COPY_IV,
 	DRIVER_REQUIRE_L2PAD,
+	DRIVER_REQUIRE_TXSTATUS_FIFO,
 
 	/*
 	 * Driver features
@@ -698,6 +711,7 @@
 	struct ieee80211_hw *hw;
 	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
 	enum ieee80211_band curr_band;
+	int curr_freq;
 
 	/*
 	 * If enabled, the debugfs interface structures
@@ -850,11 +864,6 @@
 	struct ieee80211_low_level_stats low_level_stats;
 
 	/*
-	 * RX configuration information.
-	 */
-	struct ieee80211_rx_status rx_status;
-
-	/*
 	 * Scheduled work.
 	 * NOTE: intf_work will use ieee80211_iterate_active_interfaces()
 	 * which means it cannot be placed on the hw->workqueue
@@ -862,6 +871,12 @@
 	 */
 	struct work_struct intf_work;
 
+	/**
+	 * Scheduled work for TX/RX done handling (USB devices)
+	 */
+	struct work_struct rxdone_work;
+	struct work_struct txdone_work;
+
 	/*
 	 * Data queue arrays for RX, TX and Beacon.
 	 * The Beacon array also contains the Atim queue
@@ -882,6 +897,16 @@
 	 * and interrupt thread routine.
 	 */
 	u32 irqvalue[2];
+
+	/*
+	 * FIFO for storing tx status reports between isr and tasklet.
+	 */
+	struct kfifo txstatus_fifo;
+
+	/*
+	 * Tasklet for processing tx status reports (rt2800pci).
+	 */
+	struct tasklet_struct txstatus_tasklet;
 };
 
 /*
@@ -1016,17 +1041,15 @@
 
 /**
  * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @skb: The skb to map.
+ * @entry: Pointer to &struct queue_entry
  */
-void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
+void rt2x00queue_map_txskb(struct queue_entry *entry);
 
 /**
  * rt2x00queue_unmap_skb - Unmap a skb from DMA.
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @skb: The skb to unmap.
+ * @entry: Pointer to &struct queue_entry
  */
-void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
+void rt2x00queue_unmap_skb(struct queue_entry *entry);
 
 /**
  * rt2x00queue_get_queue - Convert queue index to queue pointer
@@ -1069,10 +1092,11 @@
  */
 void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
 void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_dmadone(struct queue_entry *entry);
 void rt2x00lib_txdone(struct queue_entry *entry,
 		      struct txdone_entry_desc *txdesc);
-void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
-		      struct queue_entry *entry);
+void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status);
+void rt2x00lib_rxdone(struct queue_entry *entry);
 
 /*
  * mac80211 handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 953dc4f..54ffb5a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -81,7 +81,8 @@
 
 void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
 			  struct rt2x00_intf *intf,
-			  struct ieee80211_bss_conf *bss_conf)
+			  struct ieee80211_bss_conf *bss_conf,
+			  u32 changed)
 {
 	struct rt2x00lib_erp erp;
 
@@ -102,7 +103,10 @@
 	/* Update global beacon interval time, this is needed for PS support */
 	rt2x00dev->beacon_int = bss_conf->beacon_int;
 
-	rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
+	if (changed & BSS_CHANGED_HT)
+		erp.ht_opmode = bss_conf->ht_operation_mode;
+
+	rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);
 }
 
 static inline
@@ -126,25 +130,17 @@
 	 * ANTENNA_SW_DIVERSITY state to the driver.
 	 * If that happens, fallback to hardware defaults,
 	 * or our own default.
-	 * If diversity handling is active for a particular antenna,
-	 * we shouldn't overwrite that antenna.
-	 * The calls to rt2x00lib_config_antenna_check()
-	 * might have caused that we restore back to the already
-	 * active setting. If that has happened we can quit.
 	 */
 	if (!(ant->flags & ANTENNA_RX_DIVERSITY))
 		config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
-	else
+	else if(config.rx == ANTENNA_SW_DIVERSITY)
 		config.rx = active->rx;
 
 	if (!(ant->flags & ANTENNA_TX_DIVERSITY))
 		config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx);
-	else
+	else if (config.tx == ANTENNA_SW_DIVERSITY)
 		config.tx = active->tx;
 
-	if (config.rx == active->rx && config.tx == active->tx)
-		return;
-
 	/*
 	 * Antenna setup changes require the RX to be disabled,
 	 * else the changes will be ignored by the device.
@@ -209,10 +205,8 @@
 		rt2x00link_reset_tuner(rt2x00dev, false);
 
 	rt2x00dev->curr_band = conf->channel->band;
+	rt2x00dev->curr_freq = conf->channel->center_freq;
 	rt2x00dev->tx_power = conf->power_level;
 	rt2x00dev->short_retry = conf->short_frame_max_tx_count;
 	rt2x00dev->long_retry = conf->long_frame_max_tx_count;
-
-	rt2x00dev->rx_status.band = conf->channel->band;
-	rt2x00dev->rx_status.freq = conf->channel->center_freq;
 }
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 583dacd..5e9074b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -31,15 +31,14 @@
 
 enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
 {
-	switch (key->alg) {
-	case ALG_WEP:
-		if (key->keylen == WLAN_KEY_LEN_WEP40)
-			return CIPHER_WEP64;
-		else
-			return CIPHER_WEP128;
-	case ALG_TKIP:
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+		return CIPHER_WEP64;
+	case WLAN_CIPHER_SUITE_WEP104:
+		return CIPHER_WEP128;
+	case WLAN_CIPHER_SUITE_TKIP:
 		return CIPHER_TKIP;
-	case ALG_CCMP:
+	case WLAN_CIPHER_SUITE_CCMP:
 		return CIPHER_AES;
 	default:
 		return CIPHER_NONE;
@@ -95,7 +94,7 @@
 		overhead += key->iv_len;
 
 	if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
-		if (key->alg == ALG_TKIP)
+		if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
 			overhead += 8;
 	}
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index b0498e7..fcdb6b0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -315,6 +315,7 @@
 	.poll		= rt2x00debug_poll_queue_dump,
 	.open		= rt2x00debug_open_queue_dump,
 	.release	= rt2x00debug_release_queue_dump,
+	.llseek		= default_llseek,
 };
 
 static ssize_t rt2x00debug_read_queue_stats(struct file *file,
@@ -333,12 +334,12 @@
 	if (*offset)
 		return 0;
 
-	data = kzalloc(lines * MAX_LINE_LENGTH, GFP_KERNEL);
+	data = kcalloc(lines, MAX_LINE_LENGTH, GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
 	temp = data +
-	    sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n");
+	    sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
 
 	queue_for_each(intf->rt2x00dev, queue) {
 		spin_lock_irqsave(&queue->lock, irqflags);
@@ -346,8 +347,8 @@
 		temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid,
 				queue->count, queue->limit, queue->length,
 				queue->index[Q_INDEX],
-				queue->index[Q_INDEX_DONE],
-				queue->index[Q_INDEX_CRYPTO]);
+				queue->index[Q_INDEX_DMA_DONE],
+				queue->index[Q_INDEX_DONE]);
 
 		spin_unlock_irqrestore(&queue->lock, irqflags);
 	}
@@ -371,6 +372,7 @@
 	.read		= rt2x00debug_read_queue_stats,
 	.open		= rt2x00debug_file_open,
 	.release	= rt2x00debug_file_release,
+	.llseek		= default_llseek,
 };
 
 #ifdef CONFIG_RT2X00_LIB_CRYPTO
@@ -380,7 +382,7 @@
 					     loff_t *offset)
 {
 	struct rt2x00debug_intf *intf = file->private_data;
-	char *name[] = { "WEP64", "WEP128", "TKIP", "AES" };
+	static const char * const name[] = { "WEP64", "WEP128", "TKIP", "AES" };
 	char *data;
 	char *temp;
 	size_t size;
@@ -423,6 +425,7 @@
 	.read		= rt2x00debug_read_crypto_stats,
 	.open		= rt2x00debug_file_open,
 	.release	= rt2x00debug_file_release,
+	.llseek		= default_llseek,
 };
 #endif
 
@@ -481,6 +484,9 @@
 	if (index >= debug->__name.word_count)			\
 		return -EINVAL;					\
 								\
+	if (length > sizeof(line))				\
+		return -EINVAL;					\
+								\
 	if (copy_from_user(line, buf, length))			\
 		return -EFAULT;					\
 								\
@@ -509,6 +515,7 @@
 	.write		= rt2x00debug_write_##__name,		\
 	.open		= rt2x00debug_file_open,		\
 	.release	= rt2x00debug_file_release,		\
+	.llseek		= generic_file_llseek,			\
 };
 
 RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
@@ -542,6 +549,7 @@
 	.read		= rt2x00debug_read_dev_flags,
 	.open		= rt2x00debug_file_open,
 	.release	= rt2x00debug_file_release,
+	.llseek		= default_llseek,
 };
 
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 585e816..5ba79b9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1,5 +1,6 @@
 /*
-	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+	Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 
 	This program is free software; you can redistribute it and/or modify
@@ -250,6 +251,13 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
 
+void rt2x00lib_dmadone(struct queue_entry *entry)
+{
+	clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+	rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
+
 void rt2x00lib_txdone(struct queue_entry *entry,
 		      struct txdone_entry_desc *txdesc)
 {
@@ -266,7 +274,7 @@
 	/*
 	 * Unmap the skb.
 	 */
-	rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
+	rt2x00queue_unmap_skb(entry);
 
 	/*
 	 * Remove the extra tx headroom from the skb.
@@ -383,15 +391,7 @@
 	 * send the status report back.
 	 */
 	if (!(skbdesc_flags & SKBDESC_NOT_MAC80211))
-		/*
-		 * Only PCI and SOC devices process the tx status in process
-		 * context. Hence use ieee80211_tx_status for PCI and SOC
-		 * devices and stick to ieee80211_tx_status_irqsafe for USB.
-		 */
-		if (rt2x00_is_usb(rt2x00dev))
-			ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb);
-		else
-			ieee80211_tx_status(rt2x00dev->hw, entry->skb);
+		ieee80211_tx_status(rt2x00dev->hw, entry->skb);
 	else
 		dev_kfree_skb_any(entry->skb);
 
@@ -403,7 +403,6 @@
 
 	rt2x00dev->ops->lib->clear_entry(entry);
 
-	clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
 	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
 
 	/*
@@ -416,65 +415,89 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
 
+void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status)
+{
+	struct txdone_entry_desc txdesc;
+
+	txdesc.flags = 0;
+	__set_bit(status, &txdesc.flags);
+	txdesc.retry = 0;
+
+	rt2x00lib_txdone(entry, &txdesc);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo);
+
 static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
 					struct rxdone_entry_desc *rxdesc)
 {
 	struct ieee80211_supported_band *sband;
 	const struct rt2x00_rate *rate;
 	unsigned int i;
-	int signal;
-	int type;
+	int signal = rxdesc->signal;
+	int type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK);
 
-	/*
-	 * For non-HT rates the MCS value needs to contain the
-	 * actually used rate modulation (CCK or OFDM).
-	 */
-	if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS)
-		signal = RATE_MCS(rxdesc->rate_mode, rxdesc->signal);
-	else
-		signal = rxdesc->signal;
+	switch (rxdesc->rate_mode) {
+	case RATE_MODE_CCK:
+	case RATE_MODE_OFDM:
+		/*
+		 * For non-HT rates the MCS value needs to contain the
+		 * actually used rate modulation (CCK or OFDM).
+		 */
+		if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS)
+			signal = RATE_MCS(rxdesc->rate_mode, signal);
 
-	type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK);
-
-	sband = &rt2x00dev->bands[rt2x00dev->curr_band];
-	for (i = 0; i < sband->n_bitrates; i++) {
-		rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
-
-		if (((type == RXDONE_SIGNAL_PLCP) &&
-		     (rate->plcp == signal)) ||
-		    ((type == RXDONE_SIGNAL_BITRATE) &&
-		      (rate->bitrate == signal)) ||
-		    ((type == RXDONE_SIGNAL_MCS) &&
-		      (rate->mcs == signal))) {
-			return i;
+		sband = &rt2x00dev->bands[rt2x00dev->curr_band];
+		for (i = 0; i < sband->n_bitrates; i++) {
+			rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
+			if (((type == RXDONE_SIGNAL_PLCP) &&
+			     (rate->plcp == signal)) ||
+			    ((type == RXDONE_SIGNAL_BITRATE) &&
+			      (rate->bitrate == signal)) ||
+			    ((type == RXDONE_SIGNAL_MCS) &&
+			      (rate->mcs == signal))) {
+				return i;
+			}
 		}
+		break;
+	case RATE_MODE_HT_MIX:
+	case RATE_MODE_HT_GREENFIELD:
+		if (signal >= 0 && signal <= 76)
+			return signal;
+		break;
+	default:
+		break;
 	}
 
 	WARNING(rt2x00dev, "Frame received with unrecognized signal, "
-		"signal=0x%.4x, type=%d.\n", signal, type);
+		"mode=0x%.4x, signal=0x%.4x, type=%d.\n",
+		rxdesc->rate_mode, signal, type);
 	return 0;
 }
 
-void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
-		      struct queue_entry *entry)
+void rt2x00lib_rxdone(struct queue_entry *entry)
 {
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct rxdone_entry_desc rxdesc;
 	struct sk_buff *skb;
-	struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
+	struct ieee80211_rx_status *rx_status;
 	unsigned int header_length;
 	int rate_idx;
+
+	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+		goto submit_entry;
+
 	/*
 	 * Allocate a new sk_buffer. If no new buffer available, drop the
 	 * received frame and reuse the existing buffer.
 	 */
-	skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry);
+	skb = rt2x00queue_alloc_rxskb(entry);
 	if (!skb)
-		return;
+		goto submit_entry;
 
 	/*
 	 * Unmap the skb.
 	 */
-	rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
+	rt2x00queue_unmap_skb(entry);
 
 	/*
 	 * Extract the RXD details.
@@ -509,57 +532,44 @@
 	skb_trim(entry->skb, rxdesc.size);
 
 	/*
-	 * Check if the frame was received using HT. In that case,
-	 * the rate is the MCS index and should be passed to mac80211
-	 * directly. Otherwise we need to translate the signal to
-	 * the correct bitrate index.
+	 * Translate the signal to the correct bitrate index.
 	 */
-	if (rxdesc.rate_mode == RATE_MODE_CCK ||
-	    rxdesc.rate_mode == RATE_MODE_OFDM) {
-		rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
-	} else {
+	rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
+	if (rxdesc.rate_mode == RATE_MODE_HT_MIX ||
+	    rxdesc.rate_mode == RATE_MODE_HT_GREENFIELD)
 		rxdesc.flags |= RX_FLAG_HT;
-		rate_idx = rxdesc.signal;
-	}
 
 	/*
 	 * Update extra components
 	 */
 	rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc);
 	rt2x00debug_update_crypto(rt2x00dev, &rxdesc);
+	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
 
+	/*
+	 * Initialize RX status information, and send frame
+	 * to mac80211.
+	 */
+	rx_status = IEEE80211_SKB_RXCB(entry->skb);
 	rx_status->mactime = rxdesc.timestamp;
+	rx_status->band = rt2x00dev->curr_band;
+	rx_status->freq = rt2x00dev->curr_freq;
 	rx_status->rate_idx = rate_idx;
 	rx_status->signal = rxdesc.rssi;
 	rx_status->flag = rxdesc.flags;
 	rx_status->antenna = rt2x00dev->link.ant.active.rx;
 
-	/*
-	 * Send frame to mac80211 & debugfs.
-	 * mac80211 will clean up the skb structure.
-	 */
-	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
-	memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status));
-
-	/*
-	 * Currently only PCI and SOC devices handle rx interrupts in process
-	 * context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni
-	 * for PCI and SOC devices.
-	 */
-	if (rt2x00_is_usb(rt2x00dev))
-		ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb);
-	else
-		ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
+	ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
 
 	/*
 	 * Replace the skb with the freshly allocated one.
 	 */
 	entry->skb = skb;
-	entry->flags = 0;
 
+submit_entry:
 	rt2x00dev->ops->lib->clear_entry(entry);
-
 	rt2x00queue_index_inc(entry->queue, Q_INDEX);
+	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
 
@@ -710,7 +720,7 @@
 	for (i = 0; i < spec->num_channels; i++) {
 		rt2x00lib_channel(&channels[i],
 				  spec->channels[i].channel,
-				  spec->channels_info[i].tx_power1, i);
+				  spec->channels_info[i].max_power, i);
 	}
 
 	/*
@@ -806,6 +816,30 @@
 		rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
 
 	/*
+	 * Allocate tx status FIFO for driver use.
+	 */
+	if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags) &&
+	    rt2x00dev->ops->lib->txstatus_tasklet) {
+		/*
+		 * Allocate txstatus fifo and tasklet, we use a size of 512
+		 * for the kfifo which is big enough to store 512/4=128 tx
+		 * status reports. In the worst case (tx status for all tx
+		 * queues gets reported before we've got a chance to handle
+		 * them) 24*4=384 tx status reports need to be cached.
+		 */
+		status = kfifo_alloc(&rt2x00dev->txstatus_fifo, 512,
+				     GFP_KERNEL);
+		if (status)
+			return status;
+
+		/* tasklet for processing the tx status reports. */
+		tasklet_init(&rt2x00dev->txstatus_tasklet,
+			     rt2x00dev->ops->lib->txstatus_tasklet,
+			     (unsigned long)rt2x00dev);
+
+	}
+
+	/*
 	 * Register HW.
 	 */
 	status = ieee80211_register_hw(rt2x00dev->hw);
@@ -902,10 +936,8 @@
 
 	/* Enable the radio */
 	retval = rt2x00lib_enable_radio(rt2x00dev);
-	if (retval) {
-		rt2x00queue_uninitialize(rt2x00dev);
+	if (retval)
 		return retval;
-	}
 
 	set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
 
@@ -1017,6 +1049,18 @@
 	 * Stop all work.
 	 */
 	cancel_work_sync(&rt2x00dev->intf_work);
+	cancel_work_sync(&rt2x00dev->rxdone_work);
+	cancel_work_sync(&rt2x00dev->txdone_work);
+
+	/*
+	 * Free the tx status fifo.
+	 */
+	kfifo_free(&rt2x00dev->txstatus_fifo);
+
+	/*
+	 * Kill the tx status tasklet.
+	 */
+	tasklet_kill(&rt2x00dev->txstatus_tasklet);
 
 	/*
 	 * Uninitialize device.
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
index b818a43..f0e1eb7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
@@ -63,6 +63,9 @@
 
 	INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n",
 	     fw->data[fw->size - 4], fw->data[fw->size - 3]);
+	snprintf(rt2x00dev->hw->wiphy->fw_version,
+			sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d",
+			fw->data[fw->size - 4], fw->data[fw->size - 3]);
 
 	retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size);
 	switch (retval) {
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c
index c004cd3..c637bca 100644
--- a/drivers/net/wireless/rt2x00/rt2x00ht.c
+++ b/drivers/net/wireless/rt2x00/rt2x00ht.c
@@ -54,6 +54,17 @@
 	 */
 	if (txrate->flags & IEEE80211_TX_RC_MCS) {
 		txdesc->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 &&
+		    ((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);
 		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
@@ -62,9 +73,11 @@
 
 
 	/*
-	 * Convert flags
+	 * This frame is eligible for an AMPDU, however, don't aggregate
+	 * frames that are intended to probe a specific tx rate.
 	 */
-	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
+	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
+	    !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
 		__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
 
 	/*
@@ -74,7 +87,13 @@
 		txdesc->rate_mode = RATE_MODE_HT_MIX;
 	if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
 		txdesc->rate_mode = RATE_MODE_HT_GREENFIELD;
-	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+
+	/*
+	 * Set 40Mhz mode if necessary (for legacy rates this will
+	 * duplicate the frame to both channels).
+	 */
+	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
+	    txrate->flags & IEEE80211_TX_RC_DUP_DATA)
 		__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
 	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
 		__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index dc5c657..619da23 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -86,7 +86,8 @@
 			   const u8 *mac, const u8 *bssid);
 void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
 			  struct rt2x00_intf *intf,
-			  struct ieee80211_bss_conf *conf);
+			  struct ieee80211_bss_conf *conf,
+			  u32 changed);
 void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 			      struct antenna_setup ant);
 void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
@@ -99,18 +100,15 @@
 
 /**
  * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes.
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @queue: The queue for which the skb will be applicable.
+ * @entry: The entry for which the skb will be applicable.
  */
-struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
-					struct queue_entry *entry);
+struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry);
 
 /**
  * rt2x00queue_free_skb - free a skb
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @skb: The skb to free.
+ * @entry: The entry for which the skb will be applicable.
  */
-void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
+void rt2x00queue_free_skb(struct queue_entry *entry);
 
 /**
  * rt2x00queue_align_frame - Align 802.11 frame to 4-byte boundary
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 666cef3..b971d87 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -188,7 +188,6 @@
 static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
 {
 	struct link_ant *ant = &rt2x00dev->link.ant;
-	unsigned int flags = ant->flags;
 
 	/*
 	 * Determine if software diversity is enabled for
@@ -196,13 +195,13 @@
 	 * Always perform this check since within the link
 	 * tuner interval the configuration might have changed.
 	 */
-	flags &= ~ANTENNA_RX_DIVERSITY;
-	flags &= ~ANTENNA_TX_DIVERSITY;
+	ant->flags &= ~ANTENNA_RX_DIVERSITY;
+	ant->flags &= ~ANTENNA_TX_DIVERSITY;
 
 	if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
-		flags |= ANTENNA_RX_DIVERSITY;
+		ant->flags |= ANTENNA_RX_DIVERSITY;
 	if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
-		flags |= ANTENNA_TX_DIVERSITY;
+		ant->flags |= ANTENNA_TX_DIVERSITY;
 
 	if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
 	    !(ant->flags & ANTENNA_TX_DIVERSITY)) {
@@ -210,9 +209,6 @@
 		return true;
 	}
 
-	/* Update flags */
-	ant->flags = flags;
-
 	/*
 	 * If we have only sampled the data over the last period
 	 * we should now harvest the data. Otherwise just evaluate
@@ -240,6 +236,12 @@
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 
 	/*
+	 * No need to update the stats for !=STA interfaces
+	 */
+	if (!rt2x00dev->intf_sta_count)
+		return;
+
+	/*
 	 * Frame was received successfully since non-succesfull
 	 * frames would have been dropped by the hardware.
 	 */
@@ -415,8 +417,7 @@
 	    !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags))
 		return;
 
-	ieee80211_queue_delayed_work(rt2x00dev->hw,
-				     &link->watchdog_work, WATCHDOG_INTERVAL);
+	schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL);
 }
 
 void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
@@ -440,8 +441,7 @@
 	rt2x00dev->ops->lib->watchdog(rt2x00dev);
 
 	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-		ieee80211_queue_delayed_work(rt2x00dev->hw,
-					     &link->watchdog_work, WATCHDOG_INTERVAL);
+		schedule_delayed_work(&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 235e037..c3c206a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -669,8 +669,10 @@
 	 * When the erp information has changed, we should perform
 	 * additional configuration steps. For all other changes we are done.
 	 */
-	if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT))
-		rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
+	if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE |
+		       BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES |
+		       BSS_CHANGED_BEACON_INT | BSS_CHANGED_HT))
+		rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 63c2cc4..2449d78 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -84,7 +84,7 @@
 		/*
 		 * Send the frame to rt2x00lib for further processing.
 		 */
-		rt2x00lib_rxdone(rt2x00dev, entry);
+		rt2x00lib_rxdone(entry);
 	}
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index a3401d3..e360d28 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -1,5 +1,6 @@
 /*
-	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+	Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
 	Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 
@@ -32,9 +33,9 @@
 #include "rt2x00.h"
 #include "rt2x00lib.h"
 
-struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
-					struct queue_entry *entry)
+struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
 {
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct sk_buff *skb;
 	struct skb_frame_desc *skbdesc;
 	unsigned int frame_size;
@@ -96,41 +97,42 @@
 	return skb;
 }
 
-void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
+void rt2x00queue_map_txskb(struct queue_entry *entry)
 {
-	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+	struct device *dev = entry->queue->rt2x00dev->dev;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
 
 	skbdesc->skb_dma =
-	    dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE);
+	    dma_map_single(dev, entry->skb->data, entry->skb->len, DMA_TO_DEVICE);
 	skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
 }
 EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb);
 
-void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
+void rt2x00queue_unmap_skb(struct queue_entry *entry)
 {
-	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+	struct device *dev = entry->queue->rt2x00dev->dev;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
 
 	if (skbdesc->flags & SKBDESC_DMA_MAPPED_RX) {
-		dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len,
+		dma_unmap_single(dev, skbdesc->skb_dma, entry->skb->len,
 				 DMA_FROM_DEVICE);
 		skbdesc->flags &= ~SKBDESC_DMA_MAPPED_RX;
-	}
-
-	if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) {
-		dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len,
+	} else if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) {
+		dma_unmap_single(dev, skbdesc->skb_dma, entry->skb->len,
 				 DMA_TO_DEVICE);
 		skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX;
 	}
 }
 EXPORT_SYMBOL_GPL(rt2x00queue_unmap_skb);
 
-void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
+void rt2x00queue_free_skb(struct queue_entry *entry)
 {
-	if (!skb)
+	if (!entry->skb)
 		return;
 
-	rt2x00queue_unmap_skb(rt2x00dev, skb);
-	dev_kfree_skb_any(skb);
+	rt2x00queue_unmap_skb(entry);
+	dev_kfree_skb_any(entry->skb);
+	entry->skb = NULL;
 }
 
 void rt2x00queue_align_frame(struct sk_buff *skb)
@@ -311,7 +313,7 @@
 	/*
 	 * Initialize information from queue
 	 */
-	txdesc->queue = entry->queue->qid;
+	txdesc->qid = entry->queue->qid;
 	txdesc->cw_min = entry->queue->cw_min;
 	txdesc->cw_max = entry->queue->cw_max;
 	txdesc->aifs = entry->queue->aifs;
@@ -439,7 +441,7 @@
 	 * Map the skb to DMA.
 	 */
 	if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
-		rt2x00queue_map_txskb(rt2x00dev, entry->skb);
+		rt2x00queue_map_txskb(entry);
 
 	return 0;
 }
@@ -448,15 +450,14 @@
 					    struct txentry_desc *txdesc)
 {
 	struct data_queue *queue = entry->queue;
-	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 
-	rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc);
+	queue->rt2x00dev->ops->lib->write_tx_desc(entry, txdesc);
 
 	/*
 	 * All processing on the frame has been completed, this means
 	 * it is now ready to be dumped to userspace through debugfs.
 	 */
-	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb);
+	rt2x00debug_dump_frame(queue->rt2x00dev, DUMP_FRAME_TX, entry->skb);
 }
 
 static void rt2x00queue_kick_tx_queue(struct queue_entry *entry,
@@ -476,7 +477,7 @@
 	 */
 	if (rt2x00queue_threshold(queue) ||
 	    !test_bit(ENTRY_TXD_BURST, &txdesc->flags))
-		rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid);
+		rt2x00dev->ops->lib->kick_tx_queue(queue);
 }
 
 int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
@@ -491,7 +492,8 @@
 	if (unlikely(rt2x00queue_full(queue)))
 		return -ENOBUFS;
 
-	if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
+	if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
+				      &entry->flags))) {
 		ERROR(queue->rt2x00dev,
 		      "Arrived at non-free entry in the non-full queue %d.\n"
 		      "Please file bug report to %s.\n",
@@ -586,11 +588,10 @@
 	/*
 	 * Clean up the beacon skb.
 	 */
-	rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb);
-	intf->beacon->skb = NULL;
+	rt2x00queue_free_skb(intf->beacon);
 
 	if (!enable_beacon) {
-		rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_BEACON);
+		rt2x00dev->ops->lib->kill_tx_queue(intf->beacon->queue);
 		mutex_unlock(&intf->beacon_skb_mutex);
 		return 0;
 	}
@@ -625,6 +626,51 @@
 	return 0;
 }
 
+void rt2x00queue_for_each_entry(struct data_queue *queue,
+				enum queue_index start,
+				enum queue_index end,
+				void (*fn)(struct queue_entry *entry))
+{
+	unsigned long irqflags;
+	unsigned int index_start;
+	unsigned int index_end;
+	unsigned int i;
+
+	if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) {
+		ERROR(queue->rt2x00dev,
+		      "Entry requested from invalid index range (%d - %d)\n",
+		      start, end);
+		return;
+	}
+
+	/*
+	 * Only protect the range we are going to loop over,
+	 * if during our loop a extra entry is set to pending
+	 * it should not be kicked during this run, since it
+	 * is part of another TX operation.
+	 */
+	spin_lock_irqsave(&queue->lock, irqflags);
+	index_start = queue->index[start];
+	index_end = queue->index[end];
+	spin_unlock_irqrestore(&queue->lock, irqflags);
+
+	/*
+	 * Start from the TX done pointer, this guarentees that we will
+	 * send out all frames in the correct order.
+	 */
+	if (index_start < index_end) {
+		for (i = index_start; i < index_end; i++)
+			fn(&queue->entries[i]);
+	} else {
+		for (i = index_start; i < queue->limit; i++)
+			fn(&queue->entries[i]);
+
+		for (i = 0; i < index_end; i++)
+			fn(&queue->entries[i]);
+	}
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
+
 struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
 					 const enum data_queue_qid queue)
 {
@@ -686,13 +732,13 @@
 	if (queue->index[index] >= queue->limit)
 		queue->index[index] = 0;
 
+	queue->last_action[index] = jiffies;
+
 	if (index == Q_INDEX) {
 		queue->length++;
-		queue->last_index = jiffies;
 	} else if (index == Q_INDEX_DONE) {
 		queue->length--;
 		queue->count++;
-		queue->last_index_done = jiffies;
 	}
 
 	spin_unlock_irqrestore(&queue->lock, irqflags);
@@ -701,14 +747,17 @@
 static void rt2x00queue_reset(struct data_queue *queue)
 {
 	unsigned long irqflags;
+	unsigned int i;
 
 	spin_lock_irqsave(&queue->lock, irqflags);
 
 	queue->count = 0;
 	queue->length = 0;
-	queue->last_index = jiffies;
-	queue->last_index_done = jiffies;
-	memset(queue->index, 0, sizeof(queue->index));
+
+	for (i = 0; i < Q_INDEX_MAX; i++) {
+		queue->index[i] = 0;
+		queue->last_action[i] = jiffies;
+	}
 
 	spin_unlock_irqrestore(&queue->lock, irqflags);
 }
@@ -718,7 +767,7 @@
 	struct data_queue *queue;
 
 	txall_queue_for_each(rt2x00dev, queue)
-		rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, queue->qid);
+		rt2x00dev->ops->lib->kill_tx_queue(queue);
 }
 
 void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev)
@@ -730,9 +779,9 @@
 		rt2x00queue_reset(queue);
 
 		for (i = 0; i < queue->limit; i++) {
-			queue->entries[i].flags = 0;
-
 			rt2x00dev->ops->lib->clear_entry(&queue->entries[i]);
+			if (queue->qid == QID_RX)
+				rt2x00queue_index_inc(queue, Q_INDEX);
 		}
 	}
 }
@@ -755,7 +804,7 @@
 	 * Allocate all queue entries.
 	 */
 	entry_size = sizeof(*entries) + qdesc->priv_size;
-	entries = kzalloc(queue->limit * entry_size, GFP_KERNEL);
+	entries = kcalloc(queue->limit, entry_size, GFP_KERNEL);
 	if (!entries)
 		return -ENOMEM;
 
@@ -780,8 +829,7 @@
 	return 0;
 }
 
-static void rt2x00queue_free_skbs(struct rt2x00_dev *rt2x00dev,
-				  struct data_queue *queue)
+static void rt2x00queue_free_skbs(struct data_queue *queue)
 {
 	unsigned int i;
 
@@ -789,19 +837,17 @@
 		return;
 
 	for (i = 0; i < queue->limit; i++) {
-		if (queue->entries[i].skb)
-			rt2x00queue_free_skb(rt2x00dev, queue->entries[i].skb);
+		rt2x00queue_free_skb(&queue->entries[i]);
 	}
 }
 
-static int rt2x00queue_alloc_rxskbs(struct rt2x00_dev *rt2x00dev,
-				    struct data_queue *queue)
+static int rt2x00queue_alloc_rxskbs(struct data_queue *queue)
 {
 	unsigned int i;
 	struct sk_buff *skb;
 
 	for (i = 0; i < queue->limit; i++) {
-		skb = rt2x00queue_alloc_rxskb(rt2x00dev, &queue->entries[i]);
+		skb = rt2x00queue_alloc_rxskb(&queue->entries[i]);
 		if (!skb)
 			return -ENOMEM;
 		queue->entries[i].skb = skb;
@@ -836,7 +882,7 @@
 			goto exit;
 	}
 
-	status = rt2x00queue_alloc_rxskbs(rt2x00dev, rt2x00dev->rx);
+	status = rt2x00queue_alloc_rxskbs(rt2x00dev->rx);
 	if (status)
 		goto exit;
 
@@ -854,7 +900,7 @@
 {
 	struct data_queue *queue;
 
-	rt2x00queue_free_skbs(rt2x00dev, rt2x00dev->rx);
+	rt2x00queue_free_skbs(rt2x00dev->rx);
 
 	queue_for_each(rt2x00dev, queue) {
 		kfree(queue->entries);
@@ -891,7 +937,7 @@
 	 */
 	rt2x00dev->data_queues = 2 + rt2x00dev->ops->tx_queues + req_atim;
 
-	queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL);
+	queue = kcalloc(rt2x00dev->data_queues, sizeof(*queue), GFP_KERNEL);
 	if (!queue) {
 		ERROR(rt2x00dev, "Queue allocation failed.\n");
 		return -ENOMEM;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 191e777..d81d85f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -1,5 +1,5 @@
 /*
-	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 
 	This program is free software; you can redistribute it and/or modify
@@ -268,6 +268,7 @@
  * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU.
  * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth.
  * @ENTRY_TXD_HT_SHORT_GI: Use short GI.
+ * @ENTRY_TXD_HT_MIMO_PS: The receiving STA is in dynamic SM PS mode.
  */
 enum txentry_desc_flags {
 	ENTRY_TXD_RTS_FRAME,
@@ -286,6 +287,7 @@
 	ENTRY_TXD_HT_AMPDU,
 	ENTRY_TXD_HT_BW_40,
 	ENTRY_TXD_HT_SHORT_GI,
+	ENTRY_TXD_HT_MIMO_PS,
 };
 
 /**
@@ -294,7 +296,7 @@
  * Summary of information for the frame descriptor before sending a TX frame.
  *
  * @flags: Descriptor flags (See &enum queue_entry_flags).
- * @queue: Queue identification (See &enum data_queue_qid).
+ * @qid: Queue identification (See &enum data_queue_qid).
  * @length: Length of the entire frame.
  * @header_length: Length of 802.11 header.
  * @length_high: PLCP length high word.
@@ -320,7 +322,7 @@
 struct txentry_desc {
 	unsigned long flags;
 
-	enum data_queue_qid queue;
+	enum data_queue_qid qid;
 
 	u16 length;
 	u16 header_length;
@@ -358,17 +360,17 @@
  * @ENTRY_OWNER_DEVICE_DATA: This entry is owned by the device for data
  *	transfer (either TX or RX depending on the queue). The entry should
  *	only be touched after the device has signaled it is done with it.
- * @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data
- *	encryption or decryption. The entry should only be touched after
- *	the device has signaled it is done with it.
  * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting
  *	for the signal to start sending.
+ * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured
+ *	while transfering the data to the hardware. No TX status report will
+ *	be expected from the hardware.
  */
 enum queue_entry_flags {
 	ENTRY_BCN_ASSIGNED,
 	ENTRY_OWNER_DEVICE_DATA,
-	ENTRY_OWNER_DEVICE_CRYPTO,
 	ENTRY_DATA_PENDING,
+	ENTRY_DATA_IO_FAILED
 };
 
 /**
@@ -399,18 +401,18 @@
  *
  * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is
  *	owned by the hardware then the queue is considered to be full.
+ * @Q_INDEX_DMA_DONE: Index pointer for the next entry which will have been
+ *	transfered to the hardware.
  * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by
  *	the hardware and for which we need to run the txdone handler. If this
  *	entry is not owned by the hardware the queue is considered to be empty.
- * @Q_INDEX_CRYPTO: Index pointer to the next entry which encryption/decription
- *	will be completed by the hardware next.
  * @Q_INDEX_MAX: Keep last, used in &struct data_queue to determine the size
  *	of the index array.
  */
 enum queue_index {
 	Q_INDEX,
+	Q_INDEX_DMA_DONE,
 	Q_INDEX_DONE,
-	Q_INDEX_CRYPTO,
 	Q_INDEX_MAX,
 };
 
@@ -446,13 +448,12 @@
 	enum data_queue_qid qid;
 
 	spinlock_t lock;
-	unsigned long last_index;
-	unsigned long last_index_done;
 	unsigned int count;
 	unsigned short limit;
 	unsigned short threshold;
 	unsigned short length;
 	unsigned short index[Q_INDEX_MAX];
+	unsigned long last_action[Q_INDEX_MAX];
 
 	unsigned short txop;
 	unsigned short aifs;
@@ -565,6 +566,22 @@
 	queue_loop(__entry, (__dev)->tx, queue_end(__dev))
 
 /**
+ * rt2x00queue_for_each_entry - Loop through all entries in the queue
+ * @queue: Pointer to @data_queue
+ * @start: &enum queue_index Pointer to start index
+ * @end: &enum queue_index Pointer to end index
+ * @fn: The function to call for each &struct queue_entry
+ *
+ * This will walk through all entries in the queue, in chronological
+ * order. This means it will start at the current @start pointer
+ * and will walk through the queue until it reaches the @end pointer.
+ */
+void rt2x00queue_for_each_entry(struct data_queue *queue,
+				enum queue_index start,
+				enum queue_index end,
+				void (*fn)(struct queue_entry *entry));
+
+/**
  * rt2x00queue_empty - Check if the queue is empty.
  * @queue: Queue to check if empty.
  */
@@ -601,12 +618,23 @@
 }
 
 /**
- * rt2x00queue_timeout - Check if a timeout occured for this queue
+ * rt2x00queue_timeout - Check if a timeout occured for STATUS reorts
  * @queue: Queue to check.
  */
 static inline int rt2x00queue_timeout(struct data_queue *queue)
 {
-	return time_after(queue->last_index, queue->last_index_done + (HZ / 10));
+	return time_after(queue->last_action[Q_INDEX_DMA_DONE],
+			  queue->last_action[Q_INDEX_DONE] + (HZ / 10));
+}
+
+/**
+ * rt2x00queue_timeout - Check if a timeout occured for DMA transfers
+ * @queue: Queue to check.
+ */
+static inline int rt2x00queue_dma_timeout(struct data_queue *queue)
+{
+	return time_after(queue->last_action[Q_INDEX],
+			  queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10));
 }
 
 /**
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index ff3a366..b3317df 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -1,5 +1,6 @@
 /*
-	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+	Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 
 	This program is free software; you can redistribute it and/or modify
@@ -167,137 +168,137 @@
 /*
  * TX data handlers.
  */
-static void rt2x00usb_interrupt_txdone(struct urb *urb)
+static void rt2x00usb_work_txdone_entry(struct queue_entry *entry)
 {
-	struct queue_entry *entry = (struct queue_entry *)urb->context;
-	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-	struct txdone_entry_desc txdesc;
-
-	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
-	    !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
-		return;
-
 	/*
-	 * Obtain the status about this packet.
-	 * Note that when the status is 0 it does not mean the
+	 * If the transfer to hardware succeeded, it does not mean the
 	 * frame was send out correctly. It only means the frame
 	 * was succesfully pushed to the hardware, we have no
 	 * way to determine the transmission status right now.
 	 * (Only indirectly by looking at the failed TX counters
 	 * in the register).
 	 */
-	txdesc.flags = 0;
-	if (!urb->status)
-		__set_bit(TXDONE_UNKNOWN, &txdesc.flags);
+	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+		rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
 	else
-		__set_bit(TXDONE_FAILURE, &txdesc.flags);
-	txdesc.retry = 0;
-
-	rt2x00lib_txdone(entry, &txdesc);
+		rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
 }
 
-static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
+static void rt2x00usb_work_txdone(struct work_struct *work)
+{
+	struct rt2x00_dev *rt2x00dev =
+	    container_of(work, struct rt2x00_dev, txdone_work);
+	struct data_queue *queue;
+	struct queue_entry *entry;
+
+	tx_queue_for_each(rt2x00dev, queue) {
+		while (!rt2x00queue_empty(queue)) {
+			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+
+			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+				break;
+
+			rt2x00usb_work_txdone_entry(entry);
+		}
+	}
+}
+
+static void rt2x00usb_interrupt_txdone(struct urb *urb)
+{
+	struct queue_entry *entry = (struct queue_entry *)urb->context;
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+	if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+		return;
+
+	/*
+	 * Report the frame as DMA done
+	 */
+	rt2x00lib_dmadone(entry);
+
+	/*
+	 * Check if the frame was correctly uploaded
+	 */
+	if (urb->status)
+		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+
+	/*
+	 * Schedule the delayed work for reading the TX status
+	 * from the device.
+	 */
+	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+	    test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+		ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work);
+}
+
+static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
 	struct queue_entry_priv_usb *entry_priv = entry->priv_data;
 	u32 length;
 
-	if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) {
-		/*
-		 * USB devices cannot blindly pass the skb->len as the
-		 * length of the data to usb_fill_bulk_urb. Pass the skb
-		 * to the driver to determine what the length should be.
-		 */
-		length = rt2x00dev->ops->lib->get_tx_data_len(entry);
+	if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
+		return;
 
-		usb_fill_bulk_urb(entry_priv->urb, usb_dev,
-				  usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
-				  entry->skb->data, length,
-				  rt2x00usb_interrupt_txdone, entry);
+	/*
+	 * USB devices cannot blindly pass the skb->len as the
+	 * length of the data to usb_fill_bulk_urb. Pass the skb
+	 * to the driver to determine what the length should be.
+	 */
+	length = rt2x00dev->ops->lib->get_tx_data_len(entry);
 
-		usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+	usb_fill_bulk_urb(entry_priv->urb, usb_dev,
+			  usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
+			  entry->skb->data, length,
+			  rt2x00usb_interrupt_txdone, entry);
+
+	if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) {
+		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+		rt2x00lib_dmadone(entry);
 	}
 }
 
-void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-			     const enum data_queue_qid qid)
+void rt2x00usb_kick_tx_queue(struct data_queue *queue)
 {
-	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid);
-	unsigned long irqflags;
-	unsigned int index;
-	unsigned int index_done;
-	unsigned int i;
-
-	/*
-	 * Only protect the range we are going to loop over,
-	 * if during our loop a extra entry is set to pending
-	 * it should not be kicked during this run, since it
-	 * is part of another TX operation.
-	 */
-	spin_lock_irqsave(&queue->lock, irqflags);
-	index = queue->index[Q_INDEX];
-	index_done = queue->index[Q_INDEX_DONE];
-	spin_unlock_irqrestore(&queue->lock, irqflags);
-
-	/*
-	 * Start from the TX done pointer, this guarentees that we will
-	 * send out all frames in the correct order.
-	 */
-	if (index_done < index) {
-		for (i = index_done; i < index; i++)
-			rt2x00usb_kick_tx_entry(&queue->entries[i]);
-	} else {
-		for (i = index_done; i < queue->limit; i++)
-			rt2x00usb_kick_tx_entry(&queue->entries[i]);
-
-		for (i = 0; i < index; i++)
-			rt2x00usb_kick_tx_entry(&queue->entries[i]);
-	}
+	rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+				   rt2x00usb_kick_tx_entry);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue);
 
-void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
-			     const enum data_queue_qid qid)
+static void rt2x00usb_kill_tx_entry(struct queue_entry *entry)
 {
-	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid);
-	struct queue_entry_priv_usb *entry_priv;
-	struct queue_entry_priv_usb_bcn *bcn_priv;
-	unsigned int i;
-	bool kill_guard;
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+	struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+	struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
+
+	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+		return;
+
+	usb_kill_urb(entry_priv->urb);
 
 	/*
-	 * When killing the beacon queue, we must also kill
-	 * the beacon guard byte.
+	 * Kill guardian urb (if required by driver).
 	 */
-	kill_guard =
-	    (qid == QID_BEACON) &&
-	    (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags));
+	if ((entry->queue->qid == QID_BEACON) &&
+	    (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
+		usb_kill_urb(bcn_priv->guardian_urb);
+}
 
-	/*
-	 * Cancel all entries.
-	 */
-	for (i = 0; i < queue->limit; i++) {
-		entry_priv = queue->entries[i].priv_data;
-		usb_kill_urb(entry_priv->urb);
-
-		/*
-		 * Kill guardian urb (if required by driver).
-		 */
-		if (kill_guard) {
-			bcn_priv = queue->entries[i].priv_data;
-			usb_kill_urb(bcn_priv->guardian_urb);
-		}
-	}
+void rt2x00usb_kill_tx_queue(struct data_queue *queue)
+{
+	rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+				   rt2x00usb_kill_tx_entry);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue);
 
-static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue)
+static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
 {
-	struct queue_entry_priv_usb *entry_priv;
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 	unsigned short threshold = queue->threshold;
 
-	WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid);
+	WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
+		" invoke forced forced reset", queue->qid);
 
 	/*
 	 * Temporarily disable the TX queue, this will force mac80211
@@ -307,20 +308,33 @@
 	 * queue from being enabled during the txdone handler.
 	 */
 	queue->threshold = queue->limit;
-	ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid);
+	ieee80211_stop_queue(rt2x00dev->hw, queue->qid);
 
 	/*
-	 * Reset all currently uploaded TX frames.
+	 * Kill all entries in the queue, afterwards we need to
+	 * wait a bit for all URBs to be cancelled.
 	 */
-	while (!rt2x00queue_empty(queue)) {
-		entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data;
-		usb_kill_urb(entry_priv->urb);
+	rt2x00usb_kill_tx_queue(queue);
 
-		/*
-		 * We need a short delay here to wait for
-		 * the URB to be canceled and invoked the tx_done handler.
-		 */
-		udelay(200);
+	/*
+	 * In case that a driver has overriden the txdone_work
+	 * function, we invoke the TX done through there.
+	 */
+	rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work);
+
+	/*
+	 * Security measure: if the driver did override the
+	 * txdone_work function, and the hardware did arrive
+	 * in a state which causes it to malfunction, it is
+	 * possible that the driver couldn't handle the txdone
+	 * event correctly. So after giving the driver the
+	 * chance to cleanup, we now force a cleanup of any
+	 * leftovers.
+	 */
+	if (!rt2x00queue_empty(queue)) {
+		WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
+			" status handling failed, invoke hard reset", queue->qid);
+		rt2x00usb_work_txdone(&rt2x00dev->txdone_work);
 	}
 
 	/*
@@ -328,7 +342,15 @@
 	 * queue again.
 	 */
 	queue->threshold = threshold;
-	ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
+	ieee80211_wake_queue(rt2x00dev->hw, queue->qid);
+}
+
+static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
+{
+	WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
+		" invoke forced tx handler", queue->qid);
+
+	ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work);
 }
 
 void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
@@ -336,8 +358,12 @@
 	struct data_queue *queue;
 
 	tx_queue_for_each(rt2x00dev, queue) {
-		if (rt2x00queue_timeout(queue))
-			rt2x00usb_watchdog_reset_tx(queue);
+		if (!rt2x00queue_empty(queue)) {
+			if (rt2x00queue_dma_timeout(queue))
+				rt2x00usb_watchdog_tx_dma(queue);
+			if (rt2x00queue_timeout(queue))
+				rt2x00usb_watchdog_tx_status(queue);
+		}
 	}
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
@@ -345,38 +371,62 @@
 /*
  * RX data handlers.
  */
+static void rt2x00usb_work_rxdone(struct work_struct *work)
+{
+	struct rt2x00_dev *rt2x00dev =
+	    container_of(work, struct rt2x00_dev, rxdone_work);
+	struct queue_entry *entry;
+	struct skb_frame_desc *skbdesc;
+	u8 rxd[32];
+
+	while (!rt2x00queue_empty(rt2x00dev->rx)) {
+		entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE);
+
+		if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+			break;
+
+		/*
+		 * Fill in desc fields of the skb descriptor
+		 */
+		skbdesc = get_skb_frame_desc(entry->skb);
+		skbdesc->desc = rxd;
+		skbdesc->desc_len = entry->queue->desc_size;
+
+		/*
+		 * Send the frame to rt2x00lib for further processing.
+		 */
+		rt2x00lib_rxdone(entry);
+	}
+}
+
 static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 {
 	struct queue_entry *entry = (struct queue_entry *)urb->context;
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-	u8 rxd[32];
 
-	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
-	    !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+	if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
 		return;
 
 	/*
+	 * Report the frame as DMA done
+	 */
+	rt2x00lib_dmadone(entry);
+
+	/*
 	 * Check if the received data is simply too small
 	 * to be actually valid, or if the urb is signaling
 	 * a problem.
 	 */
-	if (urb->actual_length < entry->queue->desc_size || urb->status) {
-		set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-		usb_submit_urb(urb, GFP_ATOMIC);
-		return;
-	}
+	if (urb->actual_length < entry->queue->desc_size || urb->status)
+		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
 
 	/*
-	 * Fill in desc fields of the skb descriptor
+	 * Schedule the delayed work for reading the RX status
+	 * from the device.
 	 */
-	skbdesc->desc = rxd;
-	skbdesc->desc_len = entry->queue->desc_size;
-
-	/*
-	 * Send the frame to rt2x00lib for further processing.
-	 */
-	rt2x00lib_rxdone(rt2x00dev, entry);
+	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+	    test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+		ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work);
 }
 
 /*
@@ -391,7 +441,7 @@
 	 * The USB version of kill_tx_queue also works
 	 * on the RX queue.
 	 */
-	rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_RX);
+	rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev->rx);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
 
@@ -405,6 +455,8 @@
 	struct queue_entry_priv_usb *entry_priv = entry->priv_data;
 	int pipe;
 
+	entry->flags = 0;
+
 	if (entry->queue->qid == QID_RX) {
 		pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint);
 		usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe,
@@ -412,9 +464,10 @@
 				rt2x00usb_interrupt_rxdone, entry);
 
 		set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-		usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
-	} else {
-		entry->flags = 0;
+		if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) {
+			set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+			rt2x00lib_dmadone(entry);
+		}
 	}
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
@@ -489,9 +542,9 @@
 	return 0;
 }
 
-static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
-			       struct data_queue *queue)
+static int rt2x00usb_alloc_entries(struct data_queue *queue)
 {
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 	struct queue_entry_priv_usb *entry_priv;
 	struct queue_entry_priv_usb_bcn *bcn_priv;
 	unsigned int i;
@@ -508,7 +561,7 @@
 	 * no guardian byte was required for the beacon,
 	 * then we are done.
 	 */
-	if (rt2x00dev->bcn != queue ||
+	if (queue->qid != QID_BEACON ||
 	    !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
 		return 0;
 
@@ -522,9 +575,9 @@
 	return 0;
 }
 
-static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
-			       struct data_queue *queue)
+static void rt2x00usb_free_entries(struct data_queue *queue)
 {
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 	struct queue_entry_priv_usb *entry_priv;
 	struct queue_entry_priv_usb_bcn *bcn_priv;
 	unsigned int i;
@@ -543,7 +596,7 @@
 	 * no guardian byte was required for the beacon,
 	 * then we are done.
 	 */
-	if (rt2x00dev->bcn != queue ||
+	if (queue->qid != QID_BEACON ||
 	    !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
 		return;
 
@@ -570,7 +623,7 @@
 	 * Allocate DMA
 	 */
 	queue_for_each(rt2x00dev, queue) {
-		status = rt2x00usb_alloc_urb(rt2x00dev, queue);
+		status = rt2x00usb_alloc_entries(queue);
 		if (status)
 			goto exit;
 	}
@@ -589,7 +642,7 @@
 	struct data_queue *queue;
 
 	queue_for_each(rt2x00dev, queue)
-		rt2x00usb_free_urb(rt2x00dev, queue);
+		rt2x00usb_free_entries(queue);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
 
@@ -659,6 +712,9 @@
 
 	rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
 
+	INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
+	INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
+
 	retval = rt2x00usb_alloc_reg(rt2x00dev);
 	if (retval)
 		goto exit_free_device;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index d3d3ddc..c2d997f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -379,25 +379,21 @@
 
 /**
  * rt2x00usb_kick_tx_queue - Kick data queue
- * @rt2x00dev: Pointer to &struct rt2x00_dev
- * @qid: Data queue to kick
+ * @queue: Data queue to kick
  *
  * This will walk through all entries of the queue and push all pending
  * frames to the hardware as a single burst.
  */
-void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-			     const enum data_queue_qid qid);
+void rt2x00usb_kick_tx_queue(struct data_queue *queue);
 
 /**
  * rt2x00usb_kill_tx_queue - Kill data queue
- * @rt2x00dev: Pointer to &struct rt2x00_dev
- * @qid: Data queue to kill
+ * @queue: Data queue to kill
  *
  * This will walk through all entries of the queue and kill all
  * previously kicked frames before they can be send.
  */
-void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
-			      const enum data_queue_qid qid);
+void rt2x00usb_kill_tx_queue(struct data_queue *queue);
 
 /**
  * rt2x00usb_watchdog - Watchdog for USB communication
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index e539c6c..af548c8 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -594,7 +594,8 @@
 }
 
 static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
-			       struct rt2x00lib_erp *erp)
+			       struct rt2x00lib_erp *erp,
+			       u32 changed)
 {
 	u32 reg;
 
@@ -603,28 +604,36 @@
 	rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
 
-	rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
-	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
-			   !!erp->short_preamble);
-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+		rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
+		rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+				   !!erp->short_preamble);
+		rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+	}
 
-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
+	if (changed & BSS_CHANGED_BASIC_RATES)
+		rt2x00pci_register_write(rt2x00dev, TXRX_CSR5,
+					 erp->basic_rates);
 
-	rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
-			   erp->beacon_int * 16);
-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+		rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+				   erp->beacon_int * 16);
+		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+	}
 
-	rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
-	rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
-	rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
+		rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
+		rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
 
-	rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
-	rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
-	rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
-	rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
-	rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
+		rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
+		rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
+		rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
+		rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
+		rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
+	}
 }
 
 static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
@@ -1050,7 +1059,7 @@
 	/*
 	 * Determine r17 bounds.
 	 */
-	if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		low_bound = 0x28;
 		up_bound = 0x48;
 		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
@@ -1645,6 +1654,7 @@
 	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);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, mask);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, mask);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
 	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
@@ -1658,6 +1668,7 @@
 	rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_5, mask);
 	rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_6, mask);
 	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);
 }
 
@@ -1766,12 +1777,11 @@
 /*
  * TX descriptor initialization
  */
-static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-				  struct sk_buff *skb,
+static void rt61pci_write_tx_desc(struct queue_entry *entry,
 				  struct txentry_desc *txdesc)
 {
-	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-	struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 	__le32 *txd = entry_priv->desc;
 	u32 word;
 
@@ -1779,7 +1789,7 @@
 	 * Start writing the descriptor words.
 	 */
 	rt2x00_desc_read(txd, 1, &word);
-	rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
+	rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid);
 	rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
 	rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
 	rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
@@ -1802,15 +1812,15 @@
 	}
 
 	rt2x00_desc_read(txd, 5, &word);
-	rt2x00_set_field32(&word, TXD_W5_PID_TYPE, skbdesc->entry->queue->qid);
+	rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
 	rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
 			   skbdesc->entry->entry_idx);
 	rt2x00_set_field32(&word, TXD_W5_TX_POWER,
-			   TXPOWER_TO_DEV(rt2x00dev->tx_power));
+			   TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
 	rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
 	rt2x00_desc_write(txd, 5, word);
 
-	if (txdesc->queue != QID_BEACON) {
+	if (txdesc->qid != QID_BEACON) {
 		rt2x00_desc_read(txd, 6, &word);
 		rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
 				   skbdesc->skb_dma);
@@ -1857,7 +1867,7 @@
 	 */
 	skbdesc->desc = txd;
 	skbdesc->desc_len =
-		(txdesc->queue == QID_BEACON) ?  TXINFO_SIZE : TXD_DESC_SIZE;
+		(txdesc->qid == QID_BEACON) ?  TXINFO_SIZE : TXD_DESC_SIZE;
 }
 
 /*
@@ -1882,7 +1892,7 @@
 	/*
 	 * Write the TX descriptor for the beacon.
 	 */
-	rt61pci_write_tx_desc(rt2x00dev, entry->skb, txdesc);
+	rt61pci_write_tx_desc(entry, txdesc);
 
 	/*
 	 * Dump beacon to userspace through debugfs.
@@ -1918,34 +1928,34 @@
 	entry->skb = NULL;
 }
 
-static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-				  const enum data_queue_qid queue)
+static void rt61pci_kick_tx_queue(struct data_queue *queue)
 {
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 	u32 reg;
 
 	rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
-	rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, (queue == QID_AC_BE));
-	rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, (queue == QID_AC_BK));
-	rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, (queue == QID_AC_VI));
-	rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, (queue == QID_AC_VO));
+	rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, (queue->qid == QID_AC_BE));
+	rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, (queue->qid == QID_AC_BK));
+	rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, (queue->qid == QID_AC_VI));
+	rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, (queue->qid == QID_AC_VO));
 	rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
 }
 
-static void rt61pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
-				  const enum data_queue_qid qid)
+static void rt61pci_kill_tx_queue(struct data_queue *queue)
 {
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
 	u32 reg;
 
-	if (qid == QID_BEACON) {
+	if (queue->qid == QID_BEACON) {
 		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0);
 		return;
 	}
 
 	rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
-	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, (qid == QID_AC_BE));
-	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, (qid == QID_AC_BK));
-	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, (qid == QID_AC_VI));
-	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, (qid == QID_AC_VO));
+	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, (queue->qid == QID_AC_BE));
+	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, (queue->qid == QID_AC_BK));
+	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, (queue->qid == QID_AC_VI));
+	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, (queue->qid == QID_AC_VO));
 	rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
 }
 
@@ -1972,7 +1982,7 @@
 		return 0;
 	}
 
-	if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		if (lna == 3 || lna == 2)
 			offset += 10;
 	}
@@ -2107,11 +2117,7 @@
 				"TX status report missed for entry %d\n",
 				entry_done->entry_idx);
 
-			txdesc.flags = 0;
-			__set_bit(TXDONE_UNKNOWN, &txdesc.flags);
-			txdesc.retry = 0;
-
-			rt2x00lib_txdone(entry_done, &txdesc);
+			rt2x00lib_txdone_noinfo(entry_done, TXDONE_UNKNOWN);
 			entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
 		}
 
@@ -2624,12 +2630,13 @@
 	 * As rt61 has a global fallback table we cannot specify
 	 * more then one tx rate per frame but since the hw will
 	 * try several rates (based on the fallback table) we should
-	 * still initialize max_rates to the maximum number of rates
+	 * initialize max_report_rates to the maximum number of rates
 	 * we are going to try. Otherwise mac80211 will truncate our
 	 * reported tx rates and the rc algortihm will end up with
 	 * incorrect data.
 	 */
-	rt2x00dev->hw->max_rates = 7;
+	rt2x00dev->hw->max_rates = 1;
+	rt2x00dev->hw->max_report_rates = 7;
 	rt2x00dev->hw->max_rate_tries = 1;
 
 	/*
@@ -2654,20 +2661,24 @@
 	/*
 	 * Create channel information array
 	 */
-	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+	info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
 	spec->channels_info = info;
 
 	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
-	for (i = 0; i < 14; i++)
-		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+	for (i = 0; i < 14; i++) {
+		info[i].max_power = MAX_TXPOWER;
+		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+	}
 
 	if (spec->num_channels > 14) {
 		tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
-		for (i = 14; i < spec->num_channels; i++)
-			info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+		for (i = 14; i < spec->num_channels; i++) {
+			info[i].max_power = MAX_TXPOWER;
+			info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+		}
 	}
 
 	return 0;
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index aa9de18..9be8089 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -545,7 +545,8 @@
 }
 
 static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
-			       struct rt2x00lib_erp *erp)
+			       struct rt2x00lib_erp *erp,
+			       u32 changed)
 {
 	u32 reg;
 
@@ -554,28 +555,36 @@
 	rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
 	rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 
-	rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
-	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
-			   !!erp->short_preamble);
-	rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+		rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
+		rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+				   !!erp->short_preamble);
+		rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+	}
 
-	rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
+	if (changed & BSS_CHANGED_BASIC_RATES)
+		rt2x00usb_register_write(rt2x00dev, TXRX_CSR5,
+					 erp->basic_rates);
 
-	rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
-			   erp->beacon_int * 16);
-	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+		rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+				   erp->beacon_int * 16);
+		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+	}
 
-	rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
-	rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
-	rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+		rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
+		rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
 
-	rt2x00usb_register_read(rt2x00dev, MAC_CSR8, &reg);
-	rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
-	rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
-	rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
-	rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg);
+		rt2x00usb_register_read(rt2x00dev, MAC_CSR8, &reg);
+		rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
+		rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
+		rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
+		rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg);
+	}
 }
 
 static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
@@ -929,7 +938,7 @@
 	/*
 	 * Determine r17 bounds.
 	 */
-	if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		low_bound = 0x28;
 		up_bound = 0x48;
 
@@ -1426,12 +1435,11 @@
 /*
  * TX descriptor initialization
  */
-static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-				  struct sk_buff *skb,
+static void rt73usb_write_tx_desc(struct queue_entry *entry,
 				  struct txentry_desc *txdesc)
 {
-	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-	__le32 *txd = (__le32 *) skb->data;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+	__le32 *txd = (__le32 *) entry->skb->data;
 	u32 word;
 
 	/*
@@ -1464,7 +1472,7 @@
 	rt2x00_desc_write(txd, 0, word);
 
 	rt2x00_desc_read(txd, 1, &word);
-	rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
+	rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid);
 	rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
 	rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
 	rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
@@ -1487,7 +1495,7 @@
 
 	rt2x00_desc_read(txd, 5, &word);
 	rt2x00_set_field32(&word, TXD_W5_TX_POWER,
-			   TXPOWER_TO_DEV(rt2x00dev->tx_power));
+			   TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
 	rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
 	rt2x00_desc_write(txd, 5, word);
 
@@ -1526,7 +1534,7 @@
 	/*
 	 * Write the TX descriptor for the beacon.
 	 */
-	rt73usb_write_tx_desc(rt2x00dev, entry->skb, txdesc);
+	rt73usb_write_tx_desc(entry, txdesc);
 
 	/*
 	 * Dump beacon to userspace through debugfs.
@@ -1574,6 +1582,14 @@
 	return length;
 }
 
+static void rt73usb_kill_tx_queue(struct data_queue *queue)
+{
+	if (queue->qid == QID_BEACON)
+		rt2x00usb_register_write(queue->rt2x00dev, TXRX_CSR9, 0);
+
+	rt2x00usb_kill_tx_queue(queue);
+}
+
 /*
  * RX control handlers
  */
@@ -1597,7 +1613,7 @@
 		return 0;
 	}
 
-	if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
 			if (lna == 3 || lna == 2)
 				offset += 10;
@@ -2047,9 +2063,14 @@
 
 	/*
 	 * Initialize all hw fields.
+	 *
+	 * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING unless we are
+	 * capable of sending the buffered frames out after the DTIM
+	 * transmission using rt2x00lib_beacondone. This will send out
+	 * multicast and broadcast traffic immediately instead of buffering it
+	 * infinitly and thus dropping it after some time.
 	 */
 	rt2x00dev->hw->flags =
-	    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 	    IEEE80211_HW_SIGNAL_DBM |
 	    IEEE80211_HW_SUPPORTS_PS |
 	    IEEE80211_HW_PS_NULLFUNC_STACK;
@@ -2084,20 +2105,24 @@
 	/*
 	 * Create channel information array
 	 */
-	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+	info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
 	spec->channels_info = info;
 
 	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
-	for (i = 0; i < 14; i++)
-		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+	for (i = 0; i < 14; i++) {
+		info[i].max_power = MAX_TXPOWER;
+		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+	}
 
 	if (spec->num_channels > 14) {
 		tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
-		for (i = 14; i < spec->num_channels; i++)
-			info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+		for (i = 14; i < spec->num_channels; i++) {
+			info[i].max_power = MAX_TXPOWER;
+			info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+		}
 	}
 
 	return 0;
@@ -2259,7 +2284,7 @@
 	.write_beacon		= rt73usb_write_beacon,
 	.get_tx_data_len	= rt73usb_get_tx_data_len,
 	.kick_tx_queue		= rt2x00usb_kick_tx_queue,
-	.kill_tx_queue		= rt2x00usb_kill_tx_queue,
+	.kill_tx_queue		= rt73usb_kill_tx_queue,
 	.fill_rxdone		= rt73usb_fill_rxdone,
 	.config_shared_key	= rt73usb_config_shared_key,
 	.config_pairwise_key	= rt73usb_config_pairwise_key,
@@ -2345,6 +2370,7 @@
 	{ USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0411, 0x0137), USB_DEVICE_DATA(&rt73usb_ops) },
 	/* CEIVA */
 	{ USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) },
 	/* CNet */
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index 30107ce..707c688 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -783,6 +783,7 @@
 	struct rtl8180_priv *priv = dev->priv;
 	struct rtl8180_vif *vif_priv;
 	int i;
+	u8 reg;
 
 	vif_priv = (struct rtl8180_vif *)&vif->drv_priv;
 
@@ -791,12 +792,14 @@
 			rtl818x_iowrite8(priv, &priv->map->BSSID[i],
 					 info->bssid[i]);
 
-		if (is_valid_ether_addr(info->bssid))
-			rtl818x_iowrite8(priv, &priv->map->MSR,
-					 RTL818X_MSR_INFRA);
-		else
-			rtl818x_iowrite8(priv, &priv->map->MSR,
-					 RTL818X_MSR_NO_LINK);
+		if (is_valid_ether_addr(info->bssid)) {
+			if (vif->type == NL80211_IFTYPE_ADHOC)
+				reg = RTL818X_MSR_ADHOC;
+			else
+				reg = RTL818X_MSR_INFRA;
+		} else
+			reg = RTL818X_MSR_NO_LINK;
+		rtl818x_iowrite8(priv, &priv->map->MSR, reg);
 	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp)
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 98e0351..38fa824 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -1176,13 +1176,12 @@
 		else
 			reg = 0;
 
-		if (is_valid_ether_addr(info->bssid)) {
+		if (is_valid_ether_addr(info->bssid))
 			reg |= RTL818X_MSR_INFRA;
-			rtl818x_iowrite8(priv, &priv->map->MSR, reg);
-		} else {
+		else
 			reg |= RTL818X_MSR_NO_LINK;
-			rtl818x_iowrite8(priv, &priv->map->MSR, reg);
-		}
+
+		rtl818x_iowrite8(priv, &priv->map->MSR, reg);
 
 		mutex_unlock(&priv->conf_mutex);
 	}
diff --git a/drivers/net/wireless/wl1251/Kconfig b/drivers/net/wireless/wl1251/Kconfig
new file mode 100644
index 0000000..1fb6584
--- /dev/null
+++ b/drivers/net/wireless/wl1251/Kconfig
@@ -0,0 +1,33 @@
+menuconfig WL1251
+	tristate "TI wl1251 driver support"
+	depends on MAC80211 && EXPERIMENTAL && GENERIC_HARDIRQS
+	select FW_LOADER
+	select CRC7
+	---help---
+	  This will enable TI wl1251 driver support. The drivers make
+	  use of the mac80211 stack.
+
+	  If you choose to build a module, it'll be called wl1251. Say
+	  N if unsure.
+
+config WL1251_SPI
+	tristate "TI wl1251 SPI support"
+	depends on WL1251 && SPI_MASTER
+	---help---
+	  This module adds support for the SPI interface of adapters using
+	  TI wl1251 chipset.  Select this if your platform is using
+	  the SPI bus.
+
+	  If you choose to build a module, it'll be called wl1251_spi.
+	  Say N if unsure.
+
+config WL1251_SDIO
+	tristate "TI wl1251 SDIO support"
+	depends on WL1251 && MMC
+	---help---
+	  This module adds support for the SDIO interface of adapters using
+	  TI wl1251 chipset.  Select this if your platform is using
+	  the SDIO bus.
+
+	  If you choose to build a module, it'll be called
+	  wl1251_sdio. Say N if unsure.
diff --git a/drivers/net/wireless/wl1251/Makefile b/drivers/net/wireless/wl1251/Makefile
new file mode 100644
index 0000000..4fe2468
--- /dev/null
+++ b/drivers/net/wireless/wl1251/Makefile
@@ -0,0 +1,6 @@
+wl1251-objs		= main.o event.o tx.o rx.o ps.o cmd.o \
+			  acx.o boot.o init.o debugfs.o io.o
+
+obj-$(CONFIG_WL1251)	+= wl1251.o
+obj-$(CONFIG_WL1251_SPI)	+= spi.o
+obj-$(CONFIG_WL1251_SDIO)	+= sdio.o
diff --git a/drivers/net/wireless/wl1251/acx.c b/drivers/net/wireless/wl1251/acx.c
new file mode 100644
index 0000000..64a0214
--- /dev/null
+++ b/drivers/net/wireless/wl1251/acx.c
@@ -0,0 +1,1048 @@
+#include "acx.h"
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/crc7.h>
+
+#include "wl1251.h"
+#include "reg.h"
+#include "cmd.h"
+#include "ps.h"
+
+int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
+			   u8 mgt_rate, u8 mgt_mod)
+{
+	struct acx_fw_gen_frame_rates *rates;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx frame rates");
+
+	rates = kzalloc(sizeof(*rates), GFP_KERNEL);
+	if (!rates) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	rates->tx_ctrl_frame_rate = ctrl_rate;
+	rates->tx_ctrl_frame_mod = ctrl_mod;
+	rates->tx_mgt_frame_rate = mgt_rate;
+	rates->tx_mgt_frame_mod = mgt_mod;
+
+	ret = wl1251_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES,
+				   rates, sizeof(*rates));
+	if (ret < 0) {
+		wl1251_error("Failed to set FW rates and modulation");
+		goto out;
+	}
+
+out:
+	kfree(rates);
+	return ret;
+}
+
+
+int wl1251_acx_station_id(struct wl1251 *wl)
+{
+	struct acx_dot11_station_id *mac;
+	int ret, i;
+
+	wl1251_debug(DEBUG_ACX, "acx dot11_station_id");
+
+	mac = kzalloc(sizeof(*mac), GFP_KERNEL);
+	if (!mac) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	for (i = 0; i < ETH_ALEN; i++)
+		mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
+
+	ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac));
+	if (ret < 0)
+		goto out;
+
+out:
+	kfree(mac);
+	return ret;
+}
+
+int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id)
+{
+	struct acx_dot11_default_key *default_key;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);
+
+	default_key = kzalloc(sizeof(*default_key), GFP_KERNEL);
+	if (!default_key) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	default_key->id = key_id;
+
+	ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY,
+				   default_key, sizeof(*default_key));
+	if (ret < 0) {
+		wl1251_error("Couldn't set default key");
+		goto out;
+	}
+
+	wl->default_key = key_id;
+
+out:
+	kfree(default_key);
+	return ret;
+}
+
+int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
+				  u8 listen_interval)
+{
+	struct acx_wake_up_condition *wake_up;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx wake up conditions");
+
+	wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
+	if (!wake_up) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	wake_up->wake_up_event = wake_up_event;
+	wake_up->listen_interval = listen_interval;
+
+	ret = wl1251_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
+				   wake_up, sizeof(*wake_up));
+	if (ret < 0) {
+		wl1251_warning("could not set wake up conditions: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(wake_up);
+	return ret;
+}
+
+int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth)
+{
+	struct acx_sleep_auth *auth;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx sleep auth");
+
+	auth = kzalloc(sizeof(*auth), GFP_KERNEL);
+	if (!auth) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	auth->sleep_auth = sleep_auth;
+
+	ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
+	if (ret < 0)
+		return ret;
+
+out:
+	kfree(auth);
+	return ret;
+}
+
+int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len)
+{
+	struct acx_revision *rev;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx fw rev");
+
+	rev = kzalloc(sizeof(*rev), GFP_KERNEL);
+	if (!rev) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
+	if (ret < 0) {
+		wl1251_warning("ACX_FW_REV interrogate failed");
+		goto out;
+	}
+
+	/* be careful with the buffer sizes */
+	strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
+
+	/*
+	 * if the firmware version string is exactly
+	 * sizeof(rev->fw_version) long or fw_len is less than
+	 * sizeof(rev->fw_version) it won't be null terminated
+	 */
+	buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
+
+out:
+	kfree(rev);
+	return ret;
+}
+
+int wl1251_acx_tx_power(struct wl1251 *wl, int power)
+{
+	struct acx_current_tx_power *acx;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
+
+	if (power < 0 || power > 25)
+		return -EINVAL;
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->current_tx_power = power * 10;
+
+	ret = wl1251_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("configure of tx power failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1251_acx_feature_cfg(struct wl1251 *wl)
+{
+	struct acx_feature_config *feature;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx feature cfg");
+
+	feature = kzalloc(sizeof(*feature), GFP_KERNEL);
+	if (!feature) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
+	feature->data_flow_options = 0;
+	feature->options = 0;
+
+	ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
+				   feature, sizeof(*feature));
+	if (ret < 0) {
+		wl1251_error("Couldn't set HW encryption");
+		goto out;
+	}
+
+out:
+	kfree(feature);
+	return ret;
+}
+
+int wl1251_acx_mem_map(struct wl1251 *wl, struct acx_header *mem_map,
+		       size_t len)
+{
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx mem map");
+
+	ret = wl1251_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int wl1251_acx_data_path_params(struct wl1251 *wl,
+				struct acx_data_path_params_resp *resp)
+{
+	struct acx_data_path_params *params;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx data path params");
+
+	params = kzalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE;
+	params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE;
+
+	params->rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM;
+	params->tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM;
+
+	params->tx_complete_threshold = 1;
+
+	params->tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE;
+
+	params->tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT;
+
+	ret = wl1251_cmd_configure(wl, ACX_DATA_PATH_PARAMS,
+				   params, sizeof(*params));
+	if (ret < 0)
+		goto out;
+
+	/* FIXME: shouldn't this be ACX_DATA_PATH_RESP_PARAMS? */
+	ret = wl1251_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS,
+				     resp, sizeof(*resp));
+
+	if (ret < 0) {
+		wl1251_warning("failed to read data path parameters: %d", ret);
+		goto out;
+	} else if (resp->header.cmd.status != CMD_STATUS_SUCCESS) {
+		wl1251_warning("data path parameter acx status failed");
+		ret = -EIO;
+		goto out;
+	}
+
+out:
+	kfree(params);
+	return ret;
+}
+
+int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time)
+{
+	struct acx_rx_msdu_lifetime *acx;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx rx msdu life time");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->lifetime = life_time;
+	ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
+				   acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("failed to set rx msdu life time: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter)
+{
+	struct acx_rx_config *rx_config;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx rx config");
+
+	rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
+	if (!rx_config) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	rx_config->config_options = config;
+	rx_config->filter_options = filter;
+
+	ret = wl1251_cmd_configure(wl, ACX_RX_CFG,
+				   rx_config, sizeof(*rx_config));
+	if (ret < 0) {
+		wl1251_warning("failed to set rx config: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(rx_config);
+	return ret;
+}
+
+int wl1251_acx_pd_threshold(struct wl1251 *wl)
+{
+	struct acx_packet_detection *pd;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx data pd threshold");
+
+	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+	if (!pd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* FIXME: threshold value not set */
+
+	ret = wl1251_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
+	if (ret < 0) {
+		wl1251_warning("failed to set pd threshold: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(pd);
+	return ret;
+}
+
+int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time)
+{
+	struct acx_slot *slot;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx slot");
+
+	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+	if (!slot) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	slot->wone_index = STATION_WONE_INDEX;
+	slot->slot_time = slot_time;
+
+	ret = wl1251_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
+	if (ret < 0) {
+		wl1251_warning("failed to set slot time: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(slot);
+	return ret;
+}
+
+int wl1251_acx_group_address_tbl(struct wl1251 *wl)
+{
+	struct acx_dot11_grp_addr_tbl *acx;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx group address tbl");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* MAC filtering */
+	acx->enabled = 0;
+	acx->num_groups = 0;
+	memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
+
+	ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
+				   acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("failed to set group addr table: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1251_acx_service_period_timeout(struct wl1251 *wl)
+{
+	struct acx_rx_timeout *rx_timeout;
+	int ret;
+
+	rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
+	if (!rx_timeout) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	wl1251_debug(DEBUG_ACX, "acx service period timeout");
+
+	rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
+	rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF;
+
+	ret = wl1251_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
+				   rx_timeout, sizeof(*rx_timeout));
+	if (ret < 0) {
+		wl1251_warning("failed to set service period timeout: %d",
+			       ret);
+		goto out;
+	}
+
+out:
+	kfree(rx_timeout);
+	return ret;
+}
+
+int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold)
+{
+	struct acx_rts_threshold *rts;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx rts threshold");
+
+	rts = kzalloc(sizeof(*rts), GFP_KERNEL);
+	if (!rts) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	rts->threshold = rts_threshold;
+
+	ret = wl1251_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
+	if (ret < 0) {
+		wl1251_warning("failed to set rts threshold: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(rts);
+	return ret;
+}
+
+int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter)
+{
+	struct acx_beacon_filter_option *beacon_filter;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx beacon filter opt");
+
+	beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
+	if (!beacon_filter) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	beacon_filter->enable = enable_filter;
+	beacon_filter->max_num_beacons = 0;
+
+	ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
+				   beacon_filter, sizeof(*beacon_filter));
+	if (ret < 0) {
+		wl1251_warning("failed to set beacon filter opt: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(beacon_filter);
+	return ret;
+}
+
+int wl1251_acx_beacon_filter_table(struct wl1251 *wl)
+{
+	struct acx_beacon_filter_ie_table *ie_table;
+	int idx = 0;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx beacon filter table");
+
+	ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
+	if (!ie_table) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* configure default beacon pass-through rules */
+	ie_table->num_ie = 1;
+	ie_table->table[idx++] = BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN;
+	ie_table->table[idx++] = BEACON_RULE_PASS_ON_APPEARANCE;
+
+	ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
+				   ie_table, sizeof(*ie_table));
+	if (ret < 0) {
+		wl1251_warning("failed to set beacon filter table: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(ie_table);
+	return ret;
+}
+
+int wl1251_acx_conn_monit_params(struct wl1251 *wl)
+{
+	struct acx_conn_monit_params *acx;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx connection monitor parameters");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD;
+	acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT;
+
+	ret = wl1251_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
+				   acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("failed to set connection monitor "
+			       "parameters: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1251_acx_sg_enable(struct wl1251 *wl)
+{
+	struct acx_bt_wlan_coex *pta;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx sg enable");
+
+	pta = kzalloc(sizeof(*pta), GFP_KERNEL);
+	if (!pta) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	pta->enable = SG_ENABLE;
+
+	ret = wl1251_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
+	if (ret < 0) {
+		wl1251_warning("failed to set softgemini enable: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(pta);
+	return ret;
+}
+
+int wl1251_acx_sg_cfg(struct wl1251 *wl)
+{
+	struct acx_bt_wlan_coex_param *param;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx sg cfg");
+
+	param = kzalloc(sizeof(*param), GFP_KERNEL);
+	if (!param) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* BT-WLAN coext parameters */
+	param->min_rate = RATE_INDEX_24MBPS;
+	param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
+	param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
+	param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
+	param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
+	param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
+	param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
+	param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
+	param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
+	param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
+	param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
+	param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
+	param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
+	param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
+	param->antenna_type = PTA_ANTENNA_TYPE_DEF;
+	param->signal_type = PTA_SIGNALING_TYPE_DEF;
+	param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
+	param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
+	param->max_cts = PTA_MAX_NUM_CTS_DEF;
+	param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
+	param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
+	param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
+	param->wlan_elp_hp = PTA_ELP_HP_DEF;
+	param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
+	param->ack_mode_dual_ant = PTA_ACK_MODE_DEF;
+	param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
+	param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
+	param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;
+
+	ret = wl1251_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
+	if (ret < 0) {
+		wl1251_warning("failed to set sg config: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(param);
+	return ret;
+}
+
+int wl1251_acx_cca_threshold(struct wl1251 *wl)
+{
+	struct acx_energy_detection *detection;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx cca threshold");
+
+	detection = kzalloc(sizeof(*detection), GFP_KERNEL);
+	if (!detection) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
+	detection->tx_energy_detection = 0;
+
+	ret = wl1251_cmd_configure(wl, ACX_CCA_THRESHOLD,
+				   detection, sizeof(*detection));
+	if (ret < 0) {
+		wl1251_warning("failed to set cca threshold: %d", ret);
+		return ret;
+	}
+
+out:
+	kfree(detection);
+	return ret;
+}
+
+int wl1251_acx_bcn_dtim_options(struct wl1251 *wl)
+{
+	struct acx_beacon_broadcast *bb;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx bcn dtim options");
+
+	bb = kzalloc(sizeof(*bb), GFP_KERNEL);
+	if (!bb) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
+	bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
+	bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
+	bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
+
+	ret = wl1251_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
+	if (ret < 0) {
+		wl1251_warning("failed to set rx config: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(bb);
+	return ret;
+}
+
+int wl1251_acx_aid(struct wl1251 *wl, u16 aid)
+{
+	struct acx_aid *acx_aid;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx aid");
+
+	acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
+	if (!acx_aid) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx_aid->aid = aid;
+
+	ret = wl1251_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
+	if (ret < 0) {
+		wl1251_warning("failed to set aid: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx_aid);
+	return ret;
+}
+
+int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask)
+{
+	struct acx_event_mask *mask;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx event mbox mask");
+
+	mask = kzalloc(sizeof(*mask), GFP_KERNEL);
+	if (!mask) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* high event mask is unused */
+	mask->high_event_mask = 0xffffffff;
+
+	mask->event_mask = event_mask;
+
+	ret = wl1251_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
+				   mask, sizeof(*mask));
+	if (ret < 0) {
+		wl1251_warning("failed to set acx_event_mbox_mask: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(mask);
+	return ret;
+}
+
+int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble)
+{
+	struct acx_preamble *acx;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx_set_preamble");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->preamble = preamble;
+
+	ret = wl1251_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("Setting of preamble failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1251_acx_cts_protect(struct wl1251 *wl,
+			   enum acx_ctsprotect_type ctsprotect)
+{
+	struct acx_ctsprotect *acx;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->ctsprotect = ctsprotect;
+
+	ret = wl1251_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("Setting of ctsprotect failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime)
+{
+	struct acx_tsf_info *tsf_info;
+	int ret;
+
+	tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL);
+	if (!tsf_info) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO,
+				     tsf_info, sizeof(*tsf_info));
+	if (ret < 0) {
+		wl1251_warning("ACX_FW_REV interrogate failed");
+		goto out;
+	}
+
+	*mactime = tsf_info->current_tsf_lsb |
+		(tsf_info->current_tsf_msb << 31);
+
+out:
+	kfree(tsf_info);
+	return ret;
+}
+
+int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats)
+{
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx statistics");
+
+	ret = wl1251_cmd_interrogate(wl, ACX_STATISTICS, stats,
+				     sizeof(*stats));
+	if (ret < 0) {
+		wl1251_warning("acx statistics failed: %d", ret);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+int wl1251_acx_rate_policies(struct wl1251 *wl)
+{
+	struct acx_rate_policy *acx;
+	int ret = 0;
+
+	wl1251_debug(DEBUG_ACX, "acx rate policies");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* configure one default (one-size-fits-all) rate class */
+	acx->rate_class_cnt = 1;
+	acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
+	acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT;
+	acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT;
+	acx->rate_class[0].aflags = 0;
+
+	ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("Setting of rate policies failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1251_acx_mem_cfg(struct wl1251 *wl)
+{
+	struct wl1251_acx_config_memory *mem_conf;
+	int ret, i;
+
+	wl1251_debug(DEBUG_ACX, "acx mem cfg");
+
+	mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
+	if (!mem_conf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* memory config */
+	mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
+	mem_conf->mem_config.rx_mem_block_num = 35;
+	mem_conf->mem_config.tx_min_mem_block_num = 64;
+	mem_conf->mem_config.num_tx_queues = MAX_TX_QUEUES;
+	mem_conf->mem_config.host_if_options = HOSTIF_PKT_RING;
+	mem_conf->mem_config.num_ssid_profiles = 1;
+	mem_conf->mem_config.debug_buffer_size =
+		cpu_to_le16(TRACE_BUFFER_MAX_SIZE);
+
+	/* RX queue config */
+	mem_conf->rx_queue_config.dma_address = 0;
+	mem_conf->rx_queue_config.num_descs = ACX_RX_DESC_DEF;
+	mem_conf->rx_queue_config.priority = DEFAULT_RXQ_PRIORITY;
+	mem_conf->rx_queue_config.type = DEFAULT_RXQ_TYPE;
+
+	/* TX queue config */
+	for (i = 0; i < MAX_TX_QUEUES; i++) {
+		mem_conf->tx_queue_config[i].num_descs = ACX_TX_DESC_DEF;
+		mem_conf->tx_queue_config[i].attributes = i;
+	}
+
+	ret = wl1251_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
+				   sizeof(*mem_conf));
+	if (ret < 0) {
+		wl1251_warning("wl1251 mem config failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(mem_conf);
+	return ret;
+}
+
+int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim)
+{
+	struct wl1251_acx_wr_tbtt_and_dtim *acx;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx tbtt and dtim");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->tbtt = tbtt;
+	acx->dtim = dtim;
+
+	ret = wl1251_cmd_configure(wl, ACX_WR_TBTT_AND_DTIM,
+				   acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("failed to set tbtt and dtim: %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)
+{
+	struct wl1251_acx_ac_cfg *acx;
+	int ret = 0;
+
+	wl1251_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d "
+		     "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop);
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->ac = ac;
+	acx->cw_min = cw_min;
+	acx->cw_max = cw_max;
+	acx->aifsn = aifs;
+	acx->txop_limit = txop;
+
+	ret = wl1251_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("acx ac cfg failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
+		       enum wl1251_acx_channel_type type,
+		       u8 tsid, enum wl1251_acx_ps_scheme ps_scheme,
+		       enum wl1251_acx_ack_policy ack_policy)
+{
+	struct wl1251_acx_tid_cfg *acx;
+	int ret = 0;
+
+	wl1251_debug(DEBUG_ACX, "acx tid cfg %d type %d tsid %d "
+		     "ps_scheme %d ack_policy %d", queue, type, tsid,
+		     ps_scheme, ack_policy);
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->queue = queue;
+	acx->type = type;
+	acx->tsid = tsid;
+	acx->ps_scheme = ps_scheme;
+	acx->ack_policy = ack_policy;
+
+	ret = wl1251_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("acx tid cfg failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
diff --git a/drivers/net/wireless/wl1251/acx.h b/drivers/net/wireless/wl1251/acx.h
new file mode 100644
index 0000000..e54b21a
--- /dev/null
+++ b/drivers/net/wireless/wl1251/acx.h
@@ -0,0 +1,1411 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 __WL1251_ACX_H__
+#define __WL1251_ACX_H__
+
+#include "wl1251.h"
+#include "cmd.h"
+
+/* Target's information element */
+struct acx_header {
+	struct wl1251_cmd_header cmd;
+
+	/* acx (or information element) header */
+	u16 id;
+
+	/* payload length (not including headers */
+	u16 len;
+} __packed;
+
+struct acx_error_counter {
+	struct acx_header header;
+
+	/* The number of PLCP errors since the last time this */
+	/* information element was interrogated. This field is */
+	/* automatically cleared when it is interrogated.*/
+	u32 PLCP_error;
+
+	/* The number of FCS errors since the last time this */
+	/* information element was interrogated. This field is */
+	/* automatically cleared when it is interrogated.*/
+	u32 FCS_error;
+
+	/* The number of MPDUs without PLCP header errors received*/
+	/* since the last time this information element was interrogated. */
+	/* This field is automatically cleared when it is interrogated.*/
+	u32 valid_frame;
+
+	/* the number of missed sequence numbers in the squentially */
+	/* values of frames seq numbers */
+	u32 seq_num_miss;
+} __packed;
+
+struct acx_revision {
+	struct acx_header header;
+
+	/*
+	 * The WiLink firmware version, an ASCII string x.x.x.x,
+	 * that uniquely identifies the current firmware.
+	 * The left most digit is incremented each time a
+	 * significant change is made to the firmware, such as
+	 * code redesign or new platform support.
+	 * The second digit is incremented when major enhancements
+	 * are added or major fixes are made.
+	 * The third digit is incremented for each GA release.
+	 * The fourth digit is incremented for each build.
+	 * The first two digits identify a firmware release version,
+	 * in other words, a unique set of features.
+	 * The first three digits identify a GA release.
+	 */
+	char fw_version[20];
+
+	/*
+	 * This 4 byte field specifies the WiLink hardware version.
+	 * bits 0  - 15: Reserved.
+	 * bits 16 - 23: Version ID - The WiLink version ID
+	 *              (1 = first spin, 2 = second spin, and so on).
+	 * bits 24 - 31: Chip ID - The WiLink chip ID.
+	 */
+	u32 hw_version;
+} __packed;
+
+enum wl1251_psm_mode {
+	/* Active mode */
+	WL1251_PSM_CAM = 0,
+
+	/* Power save mode */
+	WL1251_PSM_PS = 1,
+
+	/* Extreme low power */
+	WL1251_PSM_ELP = 2,
+};
+
+struct acx_sleep_auth {
+	struct acx_header header;
+
+	/* The sleep level authorization of the device. */
+	/* 0 - Always active*/
+	/* 1 - Power down mode: light / fast sleep*/
+	/* 2 - ELP mode: Deep / Max sleep*/
+	u8  sleep_auth;
+	u8  padding[3];
+} __packed;
+
+enum {
+	HOSTIF_PCI_MASTER_HOST_INDIRECT,
+	HOSTIF_PCI_MASTER_HOST_DIRECT,
+	HOSTIF_SLAVE,
+	HOSTIF_PKT_RING,
+	HOSTIF_DONTCARE = 0xFF
+};
+
+#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
+
+#define  DP_RX_PACKET_RING_CHUNK_SIZE 1600
+#define  DP_TX_PACKET_RING_CHUNK_SIZE 1600
+#define  DP_RX_PACKET_RING_CHUNK_NUM 2
+#define  DP_TX_PACKET_RING_CHUNK_NUM 2
+#define  DP_TX_COMPLETE_TIME_OUT 20
+#define  FW_TX_CMPLT_BLOCK_SIZE 16
+
+struct acx_data_path_params {
+	struct acx_header header;
+
+	u16 rx_packet_ring_chunk_size;
+	u16 tx_packet_ring_chunk_size;
+
+	u8 rx_packet_ring_chunk_num;
+	u8 tx_packet_ring_chunk_num;
+
+	/*
+	 * Maximum number of packets that can be gathered
+	 * in the TX complete ring before an interrupt
+	 * is generated.
+	 */
+	u8 tx_complete_threshold;
+
+	/* Number of pending TX complete entries in cyclic ring.*/
+	u8 tx_complete_ring_depth;
+
+	/*
+	 * Max num microseconds since a packet enters the TX
+	 * complete ring until an interrupt is generated.
+	 */
+	u32 tx_complete_timeout;
+} __packed;
+
+
+struct acx_data_path_params_resp {
+	struct acx_header header;
+
+	u16 rx_packet_ring_chunk_size;
+	u16 tx_packet_ring_chunk_size;
+
+	u8 rx_packet_ring_chunk_num;
+	u8 tx_packet_ring_chunk_num;
+
+	u8 pad[2];
+
+	u32 rx_packet_ring_addr;
+	u32 tx_packet_ring_addr;
+
+	u32 rx_control_addr;
+	u32 tx_control_addr;
+
+	u32 tx_complete_addr;
+} __packed;
+
+#define TX_MSDU_LIFETIME_MIN       0
+#define TX_MSDU_LIFETIME_MAX       3000
+#define TX_MSDU_LIFETIME_DEF       512
+#define RX_MSDU_LIFETIME_MIN       0
+#define RX_MSDU_LIFETIME_MAX       0xFFFFFFFF
+#define RX_MSDU_LIFETIME_DEF       512000
+
+struct acx_rx_msdu_lifetime {
+	struct acx_header header;
+
+	/*
+	 * The maximum amount of time, in TU, before the
+	 * firmware discards the MSDU.
+	 */
+	u32 lifetime;
+} __packed;
+
+/*
+ * RX Config Options Table
+ * Bit		Definition
+ * ===		==========
+ * 31:14		Reserved
+ * 13		Copy RX Status - when set, write three receive status words
+ * 	 	to top of rx'd MPDUs.
+ * 		When cleared, do not write three status words (added rev 1.5)
+ * 12		Reserved
+ * 11		RX Complete upon FCS error - when set, give rx complete
+ *	 	interrupt for FCS errors, after the rx filtering, e.g. unicast
+ *	 	frames not to us with FCS error will not generate an interrupt.
+ * 10		SSID Filter Enable - When set, the WiLink discards all beacon,
+ *	        probe request, and probe response frames with an SSID that does
+ *		not match the SSID specified by the host in the START/JOIN
+ *		command.
+ *		When clear, the WiLink receives frames with any SSID.
+ * 9		Broadcast Filter Enable - When set, the WiLink discards all
+ * 	 	broadcast frames. When clear, the WiLink receives all received
+ *		broadcast frames.
+ * 8:6		Reserved
+ * 5		BSSID Filter Enable - When set, the WiLink discards any frames
+ * 	 	with a BSSID that does not match the BSSID specified by the
+ *		host.
+ *		When clear, the WiLink receives frames from any BSSID.
+ * 4		MAC Addr Filter - When set, the WiLink discards any frames
+ * 	 	with a destination address that does not match the MAC address
+ *		of the adaptor.
+ *		When clear, the WiLink receives frames destined to any MAC
+ *		address.
+ * 3		Promiscuous - When set, the WiLink receives all valid frames
+ * 	 	(i.e., all frames that pass the FCS check).
+ *		When clear, only frames that pass the other filters specified
+ *		are received.
+ * 2		FCS - When set, the WiLink includes the FCS with the received
+ *	 	frame.
+ *		When cleared, the FCS is discarded.
+ * 1		PLCP header - When set, write all data from baseband to frame
+ * 	 	buffer including PHY header.
+ * 0		Reserved - Always equal to 0.
+ *
+ * RX Filter Options Table
+ * Bit		Definition
+ * ===		==========
+ * 31:12		Reserved - Always equal to 0.
+ * 11		Association - When set, the WiLink receives all association
+ * 	 	related frames (association request/response, reassocation
+ *		request/response, and disassociation). When clear, these frames
+ *		are discarded.
+ * 10		Auth/De auth - When set, the WiLink receives all authentication
+ * 	 	and de-authentication frames. When clear, these frames are
+ *		discarded.
+ * 9		Beacon - When set, the WiLink receives all beacon frames.
+ * 	 	When clear, these frames are discarded.
+ * 8		Contention Free - When set, the WiLink receives all contention
+ * 	 	free frames.
+ *		When clear, these frames are discarded.
+ * 7		Control - When set, the WiLink receives all control frames.
+ * 	 	When clear, these frames are discarded.
+ * 6		Data - When set, the WiLink receives all data frames.
+ * 	 	When clear, these frames are discarded.
+ * 5		FCS Error - When set, the WiLink receives frames that have FCS
+ *	 	errors.
+ *		When clear, these frames are discarded.
+ * 4		Management - When set, the WiLink receives all management
+ *		frames.
+ * 	 	When clear, these frames are discarded.
+ * 3		Probe Request - When set, the WiLink receives all probe request
+ * 	 	frames.
+ *		When clear, these frames are discarded.
+ * 2		Probe Response - When set, the WiLink receives all probe
+ * 		response frames.
+ *		When clear, these frames are discarded.
+ * 1		RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK
+ * 	 	frames.
+ *		When clear, these frames are discarded.
+ * 0		Rsvd Type/Sub Type - When set, the WiLink receives all frames
+ * 	 	that have reserved frame types and sub types as defined by the
+ *		802.11 specification.
+ *		When clear, these frames are discarded.
+ */
+struct acx_rx_config {
+	struct acx_header header;
+
+	u32 config_options;
+	u32 filter_options;
+} __packed;
+
+enum {
+	QOS_AC_BE = 0,
+	QOS_AC_BK,
+	QOS_AC_VI,
+	QOS_AC_VO,
+	QOS_HIGHEST_AC_INDEX = QOS_AC_VO,
+};
+
+#define MAX_NUM_OF_AC             (QOS_HIGHEST_AC_INDEX+1)
+#define FIRST_AC_INDEX            QOS_AC_BE
+#define MAX_NUM_OF_802_1d_TAGS    8
+#define AC_PARAMS_MAX_TSID        15
+#define MAX_APSD_CONF             0xffff
+
+#define  QOS_TX_HIGH_MIN      (0)
+#define  QOS_TX_HIGH_MAX      (100)
+
+#define  QOS_TX_HIGH_BK_DEF   (25)
+#define  QOS_TX_HIGH_BE_DEF   (35)
+#define  QOS_TX_HIGH_VI_DEF   (35)
+#define  QOS_TX_HIGH_VO_DEF   (35)
+
+#define  QOS_TX_LOW_BK_DEF    (15)
+#define  QOS_TX_LOW_BE_DEF    (25)
+#define  QOS_TX_LOW_VI_DEF    (25)
+#define  QOS_TX_LOW_VO_DEF    (25)
+
+struct acx_tx_queue_qos_config {
+	struct acx_header header;
+
+	u8 qid;
+	u8 pad[3];
+
+	/* Max number of blocks allowd in the queue */
+	u16 high_threshold;
+
+	/* Lowest memory blocks guaranteed for this queue */
+	u16 low_threshold;
+} __packed;
+
+struct acx_packet_detection {
+	struct acx_header header;
+
+	u32 threshold;
+} __packed;
+
+
+enum acx_slot_type {
+	SLOT_TIME_LONG = 0,
+	SLOT_TIME_SHORT = 1,
+	DEFAULT_SLOT_TIME = SLOT_TIME_SHORT,
+	MAX_SLOT_TIMES = 0xFF
+};
+
+#define STATION_WONE_INDEX 0
+
+struct acx_slot {
+	struct acx_header header;
+
+	u8 wone_index; /* Reserved */
+	u8 slot_time;
+	u8 reserved[6];
+} __packed;
+
+
+#define ADDRESS_GROUP_MAX	(8)
+#define ADDRESS_GROUP_MAX_LEN	(ETH_ALEN * ADDRESS_GROUP_MAX)
+
+struct acx_dot11_grp_addr_tbl {
+	struct acx_header header;
+
+	u8 enabled;
+	u8 num_groups;
+	u8 pad[2];
+	u8 mac_table[ADDRESS_GROUP_MAX_LEN];
+} __packed;
+
+
+#define  RX_TIMEOUT_PS_POLL_MIN    0
+#define  RX_TIMEOUT_PS_POLL_MAX    (200000)
+#define  RX_TIMEOUT_PS_POLL_DEF    (15)
+#define  RX_TIMEOUT_UPSD_MIN       0
+#define  RX_TIMEOUT_UPSD_MAX       (200000)
+#define  RX_TIMEOUT_UPSD_DEF       (15)
+
+struct acx_rx_timeout {
+	struct acx_header header;
+
+	/*
+	 * The longest time the STA will wait to receive
+	 * traffic from the AP after a PS-poll has been
+	 * transmitted.
+	 */
+	u16 ps_poll_timeout;
+
+	/*
+	 * The longest time the STA will wait to receive
+	 * traffic from the AP after a frame has been sent
+	 * from an UPSD enabled queue.
+	 */
+	u16 upsd_timeout;
+} __packed;
+
+#define RTS_THRESHOLD_MIN              0
+#define RTS_THRESHOLD_MAX              4096
+#define RTS_THRESHOLD_DEF              2347
+
+struct acx_rts_threshold {
+	struct acx_header header;
+
+	u16 threshold;
+	u8 pad[2];
+} __packed;
+
+struct acx_beacon_filter_option {
+	struct acx_header header;
+
+	u8 enable;
+
+	/*
+	 * The number of beacons without the unicast TIM
+	 * bit set that the firmware buffers before
+	 * signaling the host about ready frames.
+	 * When set to 0 and the filter is enabled, beacons
+	 * without the unicast TIM bit set are dropped.
+	 */
+	u8 max_num_beacons;
+	u8 pad[2];
+} __packed;
+
+/*
+ * ACXBeaconFilterEntry (not 221)
+ * Byte Offset     Size (Bytes)    Definition
+ * ===========     ============    ==========
+ * 0				1               IE identifier
+ * 1               1               Treatment bit mask
+ *
+ * ACXBeaconFilterEntry (221)
+ * Byte Offset     Size (Bytes)    Definition
+ * ===========     ============    ==========
+ * 0               1               IE identifier
+ * 1               1               Treatment bit mask
+ * 2               3               OUI
+ * 5               1               Type
+ * 6               2               Version
+ *
+ *
+ * Treatment bit mask - The information element handling:
+ * bit 0 - The information element is compared and transferred
+ * in case of change.
+ * bit 1 - The information element is transferred to the host
+ * with each appearance or disappearance.
+ * Note that both bits can be set at the same time.
+ */
+#define	BEACON_FILTER_TABLE_MAX_IE_NUM		       (32)
+#define BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM (6)
+#define BEACON_FILTER_TABLE_IE_ENTRY_SIZE	       (2)
+#define BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE (6)
+#define BEACON_FILTER_TABLE_MAX_SIZE ((BEACON_FILTER_TABLE_MAX_IE_NUM * \
+			    BEACON_FILTER_TABLE_IE_ENTRY_SIZE) + \
+			   (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \
+			    BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE))
+
+#define BEACON_RULE_PASS_ON_CHANGE                     BIT(0)
+#define BEACON_RULE_PASS_ON_APPEARANCE                 BIT(1)
+
+#define BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN         (37)
+
+struct acx_beacon_filter_ie_table {
+	struct acx_header header;
+
+	u8 num_ie;
+	u8 pad[3];
+	u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
+} __packed;
+
+#define SYNCH_FAIL_DEFAULT_THRESHOLD    10     /* number of beacons */
+#define NO_BEACON_DEFAULT_TIMEOUT       (500) /* in microseconds */
+
+struct acx_conn_monit_params {
+	struct acx_header header;
+
+	u32 synch_fail_thold; /* number of beacons missed */
+	u32 bss_lose_timeout; /* number of TU's from synch fail */
+} __packed;
+
+enum {
+	SG_ENABLE = 0,
+	SG_DISABLE,
+	SG_SENSE_NO_ACTIVITY,
+	SG_SENSE_ACTIVE
+};
+
+struct acx_bt_wlan_coex {
+	struct acx_header header;
+
+	/*
+	 * 0 -> PTA enabled
+	 * 1 -> PTA disabled
+	 * 2 -> sense no active mode, i.e.
+	 *      an interrupt is sent upon
+	 *      BT activity.
+	 * 3 -> PTA is switched on in response
+	 *      to the interrupt sending.
+	 */
+	u8 enable;
+	u8 pad[3];
+} __packed;
+
+#define PTA_ANTENNA_TYPE_DEF		  (0)
+#define PTA_BT_HP_MAXTIME_DEF		  (2000)
+#define PTA_WLAN_HP_MAX_TIME_DEF	  (5000)
+#define PTA_SENSE_DISABLE_TIMER_DEF	  (1350)
+#define PTA_PROTECTIVE_RX_TIME_DEF	  (1500)
+#define PTA_PROTECTIVE_TX_TIME_DEF	  (1500)
+#define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000)
+#define PTA_SIGNALING_TYPE_DEF		  (1)
+#define PTA_AFH_LEVERAGE_ON_DEF		  (0)
+#define PTA_NUMBER_QUIET_CYCLE_DEF	  (0)
+#define PTA_MAX_NUM_CTS_DEF		  (3)
+#define PTA_NUMBER_OF_WLAN_PACKETS_DEF	  (2)
+#define PTA_NUMBER_OF_BT_PACKETS_DEF	  (2)
+#define PTA_PROTECTIVE_RX_TIME_FAST_DEF	  (1500)
+#define PTA_PROTECTIVE_TX_TIME_FAST_DEF	  (3000)
+#define PTA_CYCLE_TIME_FAST_DEF		  (8700)
+#define PTA_RX_FOR_AVALANCHE_DEF	  (5)
+#define PTA_ELP_HP_DEF			  (0)
+#define PTA_ANTI_STARVE_PERIOD_DEF	  (500)
+#define PTA_ANTI_STARVE_NUM_CYCLE_DEF	  (4)
+#define PTA_ALLOW_PA_SD_DEF		  (1)
+#define PTA_TIME_BEFORE_BEACON_DEF	  (6300)
+#define PTA_HPDM_MAX_TIME_DEF		  (1600)
+#define PTA_TIME_OUT_NEXT_WLAN_DEF	  (2550)
+#define PTA_AUTO_MODE_NO_CTS_DEF	  (0)
+#define PTA_BT_HP_RESPECTED_DEF		  (3)
+#define PTA_WLAN_RX_MIN_RATE_DEF	  (24)
+#define PTA_ACK_MODE_DEF		  (1)
+
+struct acx_bt_wlan_coex_param {
+	struct acx_header header;
+
+	/*
+	 * The minimum rate of a received WLAN packet in the STA,
+	 * during protective mode, of which a new BT-HP request
+	 * during this Rx will always be respected and gain the antenna.
+	 */
+	u32 min_rate;
+
+	/* Max time the BT HP will be respected. */
+	u16 bt_hp_max_time;
+
+	/* Max time the WLAN HP will be respected. */
+	u16 wlan_hp_max_time;
+
+	/*
+	 * The time between the last BT activity
+	 * and the moment when the sense mode returns
+	 * to SENSE_INACTIVE.
+	 */
+	u16 sense_disable_timer;
+
+	/* Time before the next BT HP instance */
+	u16 rx_time_bt_hp;
+	u16 tx_time_bt_hp;
+
+	/* range: 10-20000    default: 1500 */
+	u16 rx_time_bt_hp_fast;
+	u16 tx_time_bt_hp_fast;
+
+	/* range: 2000-65535  default: 8700 */
+	u16 wlan_cycle_fast;
+
+	/* range: 0 - 15000 (Msec) default: 1000 */
+	u16 bt_anti_starvation_period;
+
+	/* range 400-10000(Usec) default: 3000 */
+	u16 next_bt_lp_packet;
+
+	/* Deafult: worst case for BT DH5 traffic */
+	u16 wake_up_beacon;
+
+	/* range: 0-50000(Usec) default: 1050 */
+	u16 hp_dm_max_guard_time;
+
+	/*
+	 * This is to prevent both BT & WLAN antenna
+	 * starvation.
+	 * Range: 100-50000(Usec) default:2550
+	 */
+	u16 next_wlan_packet;
+
+	/* 0 -> shared antenna */
+	u8 antenna_type;
+
+	/*
+	 * 0 -> TI legacy
+	 * 1 -> Palau
+	 */
+	u8 signal_type;
+
+	/*
+	 * BT AFH status
+	 * 0 -> no AFH
+	 * 1 -> from dedicated GPIO
+	 * 2 -> AFH on (from host)
+	 */
+	u8 afh_leverage_on;
+
+	/*
+	 * The number of cycles during which no
+	 * TX will be sent after 1 cycle of RX
+	 * transaction in protective mode
+	 */
+	u8 quiet_cycle_num;
+
+	/*
+	 * The maximum number of CTSs that will
+	 * be sent for receiving RX packet in
+	 * protective mode
+	 */
+	u8 max_cts;
+
+	/*
+	 * The number of WLAN packets
+	 * transferred in common mode before
+	 * switching to BT.
+	 */
+	u8 wlan_packets_num;
+
+	/*
+	 * The number of BT packets
+	 * transferred in common mode before
+	 * switching to WLAN.
+	 */
+	u8 bt_packets_num;
+
+	/* range: 1-255  default: 5 */
+	u8 missed_rx_avalanche;
+
+	/* range: 0-1    default: 1 */
+	u8 wlan_elp_hp;
+
+	/* range: 0 - 15  default: 4 */
+	u8 bt_anti_starvation_cycles;
+
+	u8 ack_mode_dual_ant;
+
+	/*
+	 * Allow PA_SD assertion/de-assertion
+	 * during enabled BT activity.
+	 */
+	u8 pa_sd_enable;
+
+	/*
+	 * Enable/Disable PTA in auto mode:
+	 * Support Both Active & P.S modes
+	 */
+	u8 pta_auto_mode_enable;
+
+	/* range: 0 - 20  default: 1 */
+	u8 bt_hp_respected_num;
+} __packed;
+
+#define CCA_THRSH_ENABLE_ENERGY_D       0x140A
+#define CCA_THRSH_DISABLE_ENERGY_D      0xFFEF
+
+struct acx_energy_detection {
+	struct acx_header header;
+
+	/* The RX Clear Channel Assessment threshold in the PHY */
+	u16 rx_cca_threshold;
+	u8 tx_energy_detection;
+	u8 pad;
+} __packed;
+
+#define BCN_RX_TIMEOUT_DEF_VALUE        10000
+#define BROADCAST_RX_TIMEOUT_DEF_VALUE  20000
+#define RX_BROADCAST_IN_PS_DEF_VALUE    1
+#define CONSECUTIVE_PS_POLL_FAILURE_DEF 4
+
+struct acx_beacon_broadcast {
+	struct acx_header header;
+
+	u16 beacon_rx_timeout;
+	u16 broadcast_timeout;
+
+	/* Enables receiving of broadcast packets in PS mode */
+	u8 rx_broadcast_in_ps;
+
+	/* Consecutive PS Poll failures before updating the host */
+	u8 ps_poll_threshold;
+	u8 pad[2];
+} __packed;
+
+struct acx_event_mask {
+	struct acx_header header;
+
+	u32 event_mask;
+	u32 high_event_mask; /* Unused */
+} __packed;
+
+#define CFG_RX_FCS		BIT(2)
+#define CFG_RX_ALL_GOOD		BIT(3)
+#define CFG_UNI_FILTER_EN	BIT(4)
+#define CFG_BSSID_FILTER_EN	BIT(5)
+#define CFG_MC_FILTER_EN	BIT(6)
+#define CFG_MC_ADDR0_EN		BIT(7)
+#define CFG_MC_ADDR1_EN		BIT(8)
+#define CFG_BC_REJECT_EN	BIT(9)
+#define CFG_SSID_FILTER_EN	BIT(10)
+#define CFG_RX_INT_FCS_ERROR	BIT(11)
+#define CFG_RX_INT_ENCRYPTED	BIT(12)
+#define CFG_RX_WR_RX_STATUS	BIT(13)
+#define CFG_RX_FILTER_NULTI	BIT(14)
+#define CFG_RX_RESERVE		BIT(15)
+#define CFG_RX_TIMESTAMP_TSF	BIT(16)
+
+#define CFG_RX_RSV_EN		BIT(0)
+#define CFG_RX_RCTS_ACK		BIT(1)
+#define CFG_RX_PRSP_EN		BIT(2)
+#define CFG_RX_PREQ_EN		BIT(3)
+#define CFG_RX_MGMT_EN		BIT(4)
+#define CFG_RX_FCS_ERROR	BIT(5)
+#define CFG_RX_DATA_EN		BIT(6)
+#define CFG_RX_CTL_EN		BIT(7)
+#define CFG_RX_CF_EN		BIT(8)
+#define CFG_RX_BCN_EN		BIT(9)
+#define CFG_RX_AUTH_EN		BIT(10)
+#define CFG_RX_ASSOC_EN		BIT(11)
+
+#define SCAN_PASSIVE		BIT(0)
+#define SCAN_5GHZ_BAND		BIT(1)
+#define SCAN_TRIGGERED		BIT(2)
+#define SCAN_PRIORITY_HIGH	BIT(3)
+
+struct acx_fw_gen_frame_rates {
+	struct acx_header header;
+
+	u8 tx_ctrl_frame_rate; /* RATE_* */
+	u8 tx_ctrl_frame_mod; /* CCK_* or PBCC_* */
+	u8 tx_mgt_frame_rate;
+	u8 tx_mgt_frame_mod;
+} __packed;
+
+/* STA MAC */
+struct acx_dot11_station_id {
+	struct acx_header header;
+
+	u8 mac[ETH_ALEN];
+	u8 pad[2];
+} __packed;
+
+struct acx_feature_config {
+	struct acx_header header;
+
+	u32 options;
+	u32 data_flow_options;
+} __packed;
+
+struct acx_current_tx_power {
+	struct acx_header header;
+
+	u8  current_tx_power;
+	u8  padding[3];
+} __packed;
+
+struct acx_dot11_default_key {
+	struct acx_header header;
+
+	u8 id;
+	u8 pad[3];
+} __packed;
+
+struct acx_tsf_info {
+	struct acx_header header;
+
+	u32 current_tsf_msb;
+	u32 current_tsf_lsb;
+	u32 last_TBTT_msb;
+	u32 last_TBTT_lsb;
+	u8 last_dtim_count;
+	u8 pad[3];
+} __packed;
+
+enum acx_wake_up_event {
+	WAKE_UP_EVENT_BEACON_BITMAP	= 0x01, /* Wake on every Beacon*/
+	WAKE_UP_EVENT_DTIM_BITMAP	= 0x02,	/* Wake on every DTIM*/
+	WAKE_UP_EVENT_N_DTIM_BITMAP	= 0x04, /* Wake on every Nth DTIM */
+	WAKE_UP_EVENT_N_BEACONS_BITMAP	= 0x08, /* Wake on every Nth Beacon */
+	WAKE_UP_EVENT_BITS_MASK		= 0x0F
+};
+
+struct acx_wake_up_condition {
+	struct acx_header header;
+
+	u8 wake_up_event; /* Only one bit can be set */
+	u8 listen_interval;
+	u8 pad[2];
+} __packed;
+
+struct acx_aid {
+	struct acx_header header;
+
+	/*
+	 * To be set when associated with an AP.
+	 */
+	u16 aid;
+	u8 pad[2];
+} __packed;
+
+enum acx_preamble_type {
+	ACX_PREAMBLE_LONG = 0,
+	ACX_PREAMBLE_SHORT = 1
+};
+
+struct acx_preamble {
+	struct acx_header header;
+
+	/*
+	 * When set, the WiLink transmits the frames with a short preamble and
+	 * when cleared, the WiLink transmits the frames with a long preamble.
+	 */
+	u8 preamble;
+	u8 padding[3];
+} __packed;
+
+enum acx_ctsprotect_type {
+	CTSPROTECT_DISABLE = 0,
+	CTSPROTECT_ENABLE = 1
+};
+
+struct acx_ctsprotect {
+	struct acx_header header;
+	u8 ctsprotect;
+	u8 padding[3];
+} __packed;
+
+struct acx_tx_statistics {
+	u32 internal_desc_overflow;
+}  __packed;
+
+struct acx_rx_statistics {
+	u32 out_of_mem;
+	u32 hdr_overflow;
+	u32 hw_stuck;
+	u32 dropped;
+	u32 fcs_err;
+	u32 xfr_hint_trig;
+	u32 path_reset;
+	u32 reset_counter;
+} __packed;
+
+struct acx_dma_statistics {
+	u32 rx_requested;
+	u32 rx_errors;
+	u32 tx_requested;
+	u32 tx_errors;
+}  __packed;
+
+struct acx_isr_statistics {
+	/* host command complete */
+	u32 cmd_cmplt;
+
+	/* fiqisr() */
+	u32 fiqs;
+
+	/* (INT_STS_ND & INT_TRIG_RX_HEADER) */
+	u32 rx_headers;
+
+	/* (INT_STS_ND & INT_TRIG_RX_CMPLT) */
+	u32 rx_completes;
+
+	/* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */
+	u32 rx_mem_overflow;
+
+	/* (INT_STS_ND & INT_TRIG_S_RX_RDY) */
+	u32 rx_rdys;
+
+	/* irqisr() */
+	u32 irqs;
+
+	/* (INT_STS_ND & INT_TRIG_TX_PROC) */
+	u32 tx_procs;
+
+	/* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */
+	u32 decrypt_done;
+
+	/* (INT_STS_ND & INT_TRIG_DMA0) */
+	u32 dma0_done;
+
+	/* (INT_STS_ND & INT_TRIG_DMA1) */
+	u32 dma1_done;
+
+	/* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */
+	u32 tx_exch_complete;
+
+	/* (INT_STS_ND & INT_TRIG_COMMAND) */
+	u32 commands;
+
+	/* (INT_STS_ND & INT_TRIG_RX_PROC) */
+	u32 rx_procs;
+
+	/* (INT_STS_ND & INT_TRIG_PM_802) */
+	u32 hw_pm_mode_changes;
+
+	/* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */
+	u32 host_acknowledges;
+
+	/* (INT_STS_ND & INT_TRIG_PM_PCI) */
+	u32 pci_pm;
+
+	/* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */
+	u32 wakeups;
+
+	/* (INT_STS_ND & INT_TRIG_LOW_RSSI) */
+	u32 low_rssi;
+} __packed;
+
+struct acx_wep_statistics {
+	/* WEP address keys configured */
+	u32 addr_key_count;
+
+	/* default keys configured */
+	u32 default_key_count;
+
+	u32 reserved;
+
+	/* number of times that WEP key not found on lookup */
+	u32 key_not_found;
+
+	/* number of times that WEP key decryption failed */
+	u32 decrypt_fail;
+
+	/* WEP packets decrypted */
+	u32 packets;
+
+	/* WEP decrypt interrupts */
+	u32 interrupt;
+} __packed;
+
+#define ACX_MISSED_BEACONS_SPREAD 10
+
+struct acx_pwr_statistics {
+	/* the amount of enters into power save mode (both PD & ELP) */
+	u32 ps_enter;
+
+	/* the amount of enters into ELP mode */
+	u32 elp_enter;
+
+	/* the amount of missing beacon interrupts to the host */
+	u32 missing_bcns;
+
+	/* the amount of wake on host-access times */
+	u32 wake_on_host;
+
+	/* the amount of wake on timer-expire */
+	u32 wake_on_timer_exp;
+
+	/* the number of packets that were transmitted with PS bit set */
+	u32 tx_with_ps;
+
+	/* the number of packets that were transmitted with PS bit clear */
+	u32 tx_without_ps;
+
+	/* the number of received beacons */
+	u32 rcvd_beacons;
+
+	/* the number of entering into PowerOn (power save off) */
+	u32 power_save_off;
+
+	/* the number of entries into power save mode */
+	u16 enable_ps;
+
+	/*
+	 * the number of exits from power save, not including failed PS
+	 * transitions
+	 */
+	u16 disable_ps;
+
+	/*
+	 * the number of times the TSF counter was adjusted because
+	 * of drift
+	 */
+	u32 fix_tsf_ps;
+
+	/* Gives statistics about the spread continuous missed beacons.
+	 * The 16 LSB are dedicated for the PS mode.
+	 * The 16 MSB are dedicated for the PS mode.
+	 * cont_miss_bcns_spread[0] - single missed beacon.
+	 * cont_miss_bcns_spread[1] - two continuous missed beacons.
+	 * cont_miss_bcns_spread[2] - three continuous missed beacons.
+	 * ...
+	 * cont_miss_bcns_spread[9] - ten and more continuous missed beacons.
+	*/
+	u32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD];
+
+	/* the number of beacons in awake mode */
+	u32 rcvd_awake_beacons;
+} __packed;
+
+struct acx_mic_statistics {
+	u32 rx_pkts;
+	u32 calc_failure;
+} __packed;
+
+struct acx_aes_statistics {
+	u32 encrypt_fail;
+	u32 decrypt_fail;
+	u32 encrypt_packets;
+	u32 decrypt_packets;
+	u32 encrypt_interrupt;
+	u32 decrypt_interrupt;
+} __packed;
+
+struct acx_event_statistics {
+	u32 heart_beat;
+	u32 calibration;
+	u32 rx_mismatch;
+	u32 rx_mem_empty;
+	u32 rx_pool;
+	u32 oom_late;
+	u32 phy_transmit_error;
+	u32 tx_stuck;
+} __packed;
+
+struct acx_ps_statistics {
+	u32 pspoll_timeouts;
+	u32 upsd_timeouts;
+	u32 upsd_max_sptime;
+	u32 upsd_max_apturn;
+	u32 pspoll_max_apturn;
+	u32 pspoll_utilization;
+	u32 upsd_utilization;
+} __packed;
+
+struct acx_rxpipe_statistics {
+	u32 rx_prep_beacon_drop;
+	u32 descr_host_int_trig_rx_data;
+	u32 beacon_buffer_thres_host_int_trig_rx_data;
+	u32 missed_beacon_host_int_trig_rx_data;
+	u32 tx_xfr_host_int_trig_rx_data;
+} __packed;
+
+struct acx_statistics {
+	struct acx_header header;
+
+	struct acx_tx_statistics tx;
+	struct acx_rx_statistics rx;
+	struct acx_dma_statistics dma;
+	struct acx_isr_statistics isr;
+	struct acx_wep_statistics wep;
+	struct acx_pwr_statistics pwr;
+	struct acx_aes_statistics aes;
+	struct acx_mic_statistics mic;
+	struct acx_event_statistics event;
+	struct acx_ps_statistics ps;
+	struct acx_rxpipe_statistics rxpipe;
+} __packed;
+
+#define ACX_MAX_RATE_CLASSES       8
+#define ACX_RATE_MASK_UNSPECIFIED  0
+#define ACX_RATE_RETRY_LIMIT      10
+
+struct acx_rate_class {
+	u32 enabled_rates;
+	u8 short_retry_limit;
+	u8 long_retry_limit;
+	u8 aflags;
+	u8 reserved;
+} __packed;
+
+struct acx_rate_policy {
+	struct acx_header header;
+
+	u32 rate_class_cnt;
+	struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES];
+} __packed;
+
+struct wl1251_acx_memory {
+	__le16 num_stations; /* number of STAs to be supported. */
+	u16 reserved_1;
+
+	/*
+	 * Nmber of memory buffers for the RX mem pool.
+	 * The actual number may be less if there are
+	 * not enough blocks left for the minimum num
+	 * of TX ones.
+	 */
+	u8 rx_mem_block_num;
+	u8 reserved_2;
+	u8 num_tx_queues; /* From 1 to 16 */
+	u8 host_if_options; /* HOST_IF* */
+	u8 tx_min_mem_block_num;
+	u8 num_ssid_profiles;
+	__le16 debug_buffer_size;
+} __packed;
+
+
+#define ACX_RX_DESC_MIN                1
+#define ACX_RX_DESC_MAX                127
+#define ACX_RX_DESC_DEF                32
+struct wl1251_acx_rx_queue_config {
+	u8 num_descs;
+	u8 pad;
+	u8 type;
+	u8 priority;
+	__le32 dma_address;
+} __packed;
+
+#define ACX_TX_DESC_MIN                1
+#define ACX_TX_DESC_MAX                127
+#define ACX_TX_DESC_DEF                16
+struct wl1251_acx_tx_queue_config {
+    u8 num_descs;
+    u8 pad[2];
+    u8 attributes;
+} __packed;
+
+#define MAX_TX_QUEUE_CONFIGS 5
+#define MAX_TX_QUEUES 4
+struct wl1251_acx_config_memory {
+	struct acx_header header;
+
+	struct wl1251_acx_memory mem_config;
+	struct wl1251_acx_rx_queue_config rx_queue_config;
+	struct wl1251_acx_tx_queue_config tx_queue_config[MAX_TX_QUEUE_CONFIGS];
+} __packed;
+
+struct wl1251_acx_mem_map {
+	struct acx_header header;
+
+	void *code_start;
+	void *code_end;
+
+	void *wep_defkey_start;
+	void *wep_defkey_end;
+
+	void *sta_table_start;
+	void *sta_table_end;
+
+	void *packet_template_start;
+	void *packet_template_end;
+
+	void *queue_memory_start;
+	void *queue_memory_end;
+
+	void *packet_memory_pool_start;
+	void *packet_memory_pool_end;
+
+	void *debug_buffer1_start;
+	void *debug_buffer1_end;
+
+	void *debug_buffer2_start;
+	void *debug_buffer2_end;
+
+	/* Number of blocks FW allocated for TX packets */
+	u32 num_tx_mem_blocks;
+
+	/* Number of blocks FW allocated for RX packets */
+	u32 num_rx_mem_blocks;
+} __packed;
+
+
+struct wl1251_acx_wr_tbtt_and_dtim {
+
+	struct acx_header header;
+
+	/* Time in TUs between two consecutive beacons */
+	u16 tbtt;
+
+	/*
+	 * DTIM period
+	 * For BSS: Number of TBTTs in a DTIM period (range: 1-10)
+	 * For IBSS: value shall be set to 1
+	*/
+	u8  dtim;
+	u8  padding;
+} __packed;
+
+struct wl1251_acx_ac_cfg {
+	struct acx_header header;
+
+	/*
+	 * Access Category - The TX queue's access category
+	 * (refer to AccessCategory_enum)
+	 */
+	u8 ac;
+
+	/*
+	 * The contention window minimum size (in slots) for
+	 * the access class.
+	 */
+	u8 cw_min;
+
+	/*
+	 * The contention window maximum size (in slots) for
+	 * the access class.
+	 */
+	u16 cw_max;
+
+	/* The AIF value (in slots) for the access class. */
+	u8 aifsn;
+
+	u8 reserved;
+
+	/* The TX Op Limit (in microseconds) for the access class. */
+	u16 txop_limit;
+} __packed;
+
+
+enum wl1251_acx_channel_type {
+	CHANNEL_TYPE_DCF	= 0,
+	CHANNEL_TYPE_EDCF	= 1,
+	CHANNEL_TYPE_HCCA	= 2,
+};
+
+enum wl1251_acx_ps_scheme {
+	/* regular ps: simple sending of packets */
+	WL1251_ACX_PS_SCHEME_LEGACY	= 0,
+
+	/* sending a packet triggers a unscheduled apsd downstream */
+	WL1251_ACX_PS_SCHEME_UPSD_TRIGGER	= 1,
+
+	/* a pspoll packet will be sent before every data packet */
+	WL1251_ACX_PS_SCHEME_LEGACY_PSPOLL	= 2,
+
+	/* scheduled apsd mode */
+	WL1251_ACX_PS_SCHEME_SAPSD		= 3,
+};
+
+enum wl1251_acx_ack_policy {
+	WL1251_ACX_ACK_POLICY_LEGACY	= 0,
+	WL1251_ACX_ACK_POLICY_NO_ACK	= 1,
+	WL1251_ACX_ACK_POLICY_BLOCK	= 2,
+};
+
+struct wl1251_acx_tid_cfg {
+	struct acx_header header;
+
+	/* tx queue id number (0-7) */
+	u8 queue;
+
+	/* channel access type for the queue, enum wl1251_acx_channel_type */
+	u8 type;
+
+	/* EDCA: ac index (0-3), HCCA: traffic stream id (8-15) */
+	u8 tsid;
+
+	/* ps scheme of the specified queue, enum wl1251_acx_ps_scheme */
+	u8 ps_scheme;
+
+	/* the tx queue ack policy, enum wl1251_acx_ack_policy */
+	u8 ack_policy;
+
+	u8 padding[3];
+
+	/* not supported */
+	u32 apsdconf[2];
+} __packed;
+
+/*************************************************************************
+
+    Host Interrupt Register (WiLink -> Host)
+
+**************************************************************************/
+
+/* RX packet is ready in Xfer buffer #0 */
+#define WL1251_ACX_INTR_RX0_DATA      BIT(0)
+
+/* TX result(s) are in the TX complete buffer */
+#define WL1251_ACX_INTR_TX_RESULT	BIT(1)
+
+/* OBSOLETE */
+#define WL1251_ACX_INTR_TX_XFR		BIT(2)
+
+/* RX packet is ready in Xfer buffer #1 */
+#define WL1251_ACX_INTR_RX1_DATA	BIT(3)
+
+/* Event was entered to Event MBOX #A */
+#define WL1251_ACX_INTR_EVENT_A		BIT(4)
+
+/* Event was entered to Event MBOX #B */
+#define WL1251_ACX_INTR_EVENT_B		BIT(5)
+
+/* OBSOLETE */
+#define WL1251_ACX_INTR_WAKE_ON_HOST	BIT(6)
+
+/* Trace meassge on MBOX #A */
+#define WL1251_ACX_INTR_TRACE_A		BIT(7)
+
+/* Trace meassge on MBOX #B */
+#define WL1251_ACX_INTR_TRACE_B		BIT(8)
+
+/* Command processing completion */
+#define WL1251_ACX_INTR_CMD_COMPLETE	BIT(9)
+
+/* Init sequence is done */
+#define WL1251_ACX_INTR_INIT_COMPLETE	BIT(14)
+
+#define WL1251_ACX_INTR_ALL           0xFFFFFFFF
+
+enum {
+	ACX_WAKE_UP_CONDITIONS      = 0x0002,
+	ACX_MEM_CFG                 = 0x0003,
+	ACX_SLOT                    = 0x0004,
+	ACX_QUEUE_HEAD              = 0x0005, /* for MASTER mode only */
+	ACX_AC_CFG                  = 0x0007,
+	ACX_MEM_MAP                 = 0x0008,
+	ACX_AID                     = 0x000A,
+	ACX_RADIO_PARAM             = 0x000B, /* Not used */
+	ACX_CFG                     = 0x000C, /* Not used */
+	ACX_FW_REV                  = 0x000D,
+	ACX_MEDIUM_USAGE            = 0x000F,
+	ACX_RX_CFG                  = 0x0010,
+	ACX_TX_QUEUE_CFG            = 0x0011, /* FIXME: only used by wl1251 */
+	ACX_BSS_IN_PS               = 0x0012, /* for AP only */
+	ACX_STATISTICS              = 0x0013, /* Debug API */
+	ACX_FEATURE_CFG             = 0x0015,
+	ACX_MISC_CFG                = 0x0017, /* Not used */
+	ACX_TID_CFG                 = 0x001A,
+	ACX_BEACON_FILTER_OPT       = 0x001F,
+	ACX_LOW_RSSI                = 0x0020,
+	ACX_NOISE_HIST              = 0x0021,
+	ACX_HDK_VERSION             = 0x0022, /* ??? */
+	ACX_PD_THRESHOLD            = 0x0023,
+	ACX_DATA_PATH_PARAMS        = 0x0024, /* WO */
+	ACX_DATA_PATH_RESP_PARAMS   = 0x0024, /* RO */
+	ACX_CCA_THRESHOLD           = 0x0025,
+	ACX_EVENT_MBOX_MASK         = 0x0026,
+#ifdef FW_RUNNING_AS_AP
+	ACX_DTIM_PERIOD             = 0x0027, /* for AP only */
+#else
+	ACX_WR_TBTT_AND_DTIM        = 0x0027, /* STA only */
+#endif
+	ACX_ACI_OPTION_CFG          = 0x0029, /* OBSOLETE (for 1251)*/
+	ACX_GPIO_CFG                = 0x002A, /* Not used */
+	ACX_GPIO_SET                = 0x002B, /* Not used */
+	ACX_PM_CFG                  = 0x002C, /* To Be Documented */
+	ACX_CONN_MONIT_PARAMS       = 0x002D,
+	ACX_AVERAGE_RSSI            = 0x002E, /* Not used */
+	ACX_CONS_TX_FAILURE         = 0x002F,
+	ACX_BCN_DTIM_OPTIONS        = 0x0031,
+	ACX_SG_ENABLE               = 0x0032,
+	ACX_SG_CFG                  = 0x0033,
+	ACX_ANTENNA_DIVERSITY_CFG   = 0x0035, /* To Be Documented */
+	ACX_LOW_SNR		    = 0x0037, /* To Be Documented */
+	ACX_BEACON_FILTER_TABLE     = 0x0038,
+	ACX_ARP_IP_FILTER           = 0x0039,
+	ACX_ROAMING_STATISTICS_TBL  = 0x003B,
+	ACX_RATE_POLICY             = 0x003D,
+	ACX_CTS_PROTECTION          = 0x003E,
+	ACX_SLEEP_AUTH              = 0x003F,
+	ACX_PREAMBLE_TYPE	    = 0x0040,
+	ACX_ERROR_CNT               = 0x0041,
+	ACX_FW_GEN_FRAME_RATES      = 0x0042,
+	ACX_IBSS_FILTER		    = 0x0044,
+	ACX_SERVICE_PERIOD_TIMEOUT  = 0x0045,
+	ACX_TSF_INFO                = 0x0046,
+	ACX_CONFIG_PS_WMM           = 0x0049,
+	ACX_ENABLE_RX_DATA_FILTER   = 0x004A,
+	ACX_SET_RX_DATA_FILTER      = 0x004B,
+	ACX_GET_DATA_FILTER_STATISTICS = 0x004C,
+	ACX_POWER_LEVEL_TABLE       = 0x004D,
+	ACX_BET_ENABLE              = 0x0050,
+	DOT11_STATION_ID            = 0x1001,
+	DOT11_RX_MSDU_LIFE_TIME     = 0x1004,
+	DOT11_CUR_TX_PWR            = 0x100D,
+	DOT11_DEFAULT_KEY           = 0x1010,
+	DOT11_RX_DOT11_MODE         = 0x1012,
+	DOT11_RTS_THRESHOLD         = 0x1013,
+	DOT11_GROUP_ADDRESS_TBL     = 0x1014,
+
+	MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
+
+	MAX_IE = 0xFFFF
+};
+
+
+int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
+			   u8 mgt_rate, u8 mgt_mod);
+int wl1251_acx_station_id(struct wl1251 *wl);
+int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id);
+int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
+				  u8 listen_interval);
+int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth);
+int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len);
+int wl1251_acx_tx_power(struct wl1251 *wl, int power);
+int wl1251_acx_feature_cfg(struct wl1251 *wl);
+int wl1251_acx_mem_map(struct wl1251 *wl,
+		       struct acx_header *mem_map, size_t len);
+int wl1251_acx_data_path_params(struct wl1251 *wl,
+				struct acx_data_path_params_resp *data_path);
+int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time);
+int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter);
+int wl1251_acx_pd_threshold(struct wl1251 *wl);
+int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time);
+int wl1251_acx_group_address_tbl(struct wl1251 *wl);
+int wl1251_acx_service_period_timeout(struct wl1251 *wl);
+int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
+int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter);
+int wl1251_acx_beacon_filter_table(struct wl1251 *wl);
+int wl1251_acx_conn_monit_params(struct wl1251 *wl);
+int wl1251_acx_sg_enable(struct wl1251 *wl);
+int wl1251_acx_sg_cfg(struct wl1251 *wl);
+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_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble);
+int wl1251_acx_cts_protect(struct wl1251 *wl,
+			    enum acx_ctsprotect_type ctsprotect);
+int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats);
+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_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,
+		       enum wl1251_acx_channel_type type,
+		       u8 tsid, enum wl1251_acx_ps_scheme ps_scheme,
+		       enum wl1251_acx_ack_policy ack_policy);
+
+#endif /* __WL1251_ACX_H__ */
diff --git a/drivers/net/wireless/wl1251/boot.c b/drivers/net/wireless/wl1251/boot.c
new file mode 100644
index 0000000..61572df
--- /dev/null
+++ b/drivers/net/wireless/wl1251/boot.c
@@ -0,0 +1,557 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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/gpio.h>
+#include <linux/slab.h>
+
+#include "reg.h"
+#include "boot.h"
+#include "io.h"
+#include "spi.h"
+#include "event.h"
+#include "acx.h"
+
+void wl1251_boot_target_enable_interrupts(struct wl1251 *wl)
+{
+	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
+	wl1251_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
+}
+
+int wl1251_boot_soft_reset(struct wl1251 *wl)
+{
+	unsigned long timeout;
+	u32 boot_data;
+
+	/* perform soft reset */
+	wl1251_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
+
+	/* SOFT_RESET is self clearing */
+	timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
+	while (1) {
+		boot_data = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
+		wl1251_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
+		if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
+			break;
+
+		if (time_after(jiffies, timeout)) {
+			/* 1.2 check pWhalBus->uSelfClearTime if the
+			 * timeout was reached */
+			wl1251_error("soft reset timeout");
+			return -1;
+		}
+
+		udelay(SOFT_RESET_STALL_TIME);
+	}
+
+	/* disable Rx/Tx */
+	wl1251_reg_write32(wl, ENABLE, 0x0);
+
+	/* disable auto calibration on start*/
+	wl1251_reg_write32(wl, SPARE_A2, 0xffff);
+
+	return 0;
+}
+
+int wl1251_boot_init_seq(struct wl1251 *wl)
+{
+	u32 scr_pad6, init_data, tmp, elp_cmd, ref_freq;
+
+	/*
+	 * col #1: INTEGER_DIVIDER
+	 * col #2: FRACTIONAL_DIVIDER
+	 * col #3: ATTN_BB
+	 * col #4: ALPHA_BB
+	 * col #5: STOP_TIME_BB
+	 * col #6: BB_PLL_LOOP_FILTER
+	 */
+	static const u32 LUT[REF_FREQ_NUM][LUT_PARAM_NUM] = {
+
+		{   83, 87381,  0xB, 5, 0xF00,  3}, /* REF_FREQ_19_2*/
+		{   61, 141154, 0xB, 5, 0x1450, 2}, /* REF_FREQ_26_0*/
+		{   41, 174763, 0xC, 6, 0x2D00, 1}, /* REF_FREQ_38_4*/
+		{   40, 0,      0xC, 6, 0x2EE0, 1}, /* REF_FREQ_40_0*/
+		{   47, 162280, 0xC, 6, 0x2760, 1}  /* REF_FREQ_33_6        */
+	};
+
+	/* read NVS params */
+	scr_pad6 = wl1251_reg_read32(wl, SCR_PAD6);
+	wl1251_debug(DEBUG_BOOT, "scr_pad6 0x%x", scr_pad6);
+
+	/* read ELP_CMD */
+	elp_cmd = wl1251_reg_read32(wl, ELP_CMD);
+	wl1251_debug(DEBUG_BOOT, "elp_cmd 0x%x", elp_cmd);
+
+	/* set the BB calibration time to be 300 usec (PLL_CAL_TIME) */
+	ref_freq = scr_pad6 & 0x000000FF;
+	wl1251_debug(DEBUG_BOOT, "ref_freq 0x%x", ref_freq);
+
+	wl1251_reg_write32(wl, PLL_CAL_TIME, 0x9);
+
+	/*
+	 * PG 1.2: set the clock buffer time to be 210 usec (CLK_BUF_TIME)
+	 */
+	wl1251_reg_write32(wl, CLK_BUF_TIME, 0x6);
+
+	/*
+	 * set the clock detect feature to work in the restart wu procedure
+	 * (ELP_CFG_MODE[14]) and Select the clock source type
+	 * (ELP_CFG_MODE[13:12])
+	 */
+	tmp = ((scr_pad6 & 0x0000FF00) << 4) | 0x00004000;
+	wl1251_reg_write32(wl, ELP_CFG_MODE, tmp);
+
+	/* PG 1.2: enable the BB PLL fix. Enable the PLL_LIMP_CLK_EN_CMD */
+	elp_cmd |= 0x00000040;
+	wl1251_reg_write32(wl, ELP_CMD, elp_cmd);
+
+	/* PG 1.2: Set the BB PLL stable time to be 1000usec
+	 * (PLL_STABLE_TIME) */
+	wl1251_reg_write32(wl, CFG_PLL_SYNC_CNT, 0x20);
+
+	/* PG 1.2: read clock request time */
+	init_data = wl1251_reg_read32(wl, CLK_REQ_TIME);
+
+	/*
+	 * PG 1.2: set the clock request time to be ref_clk_settling_time -
+	 * 1ms = 4ms
+	 */
+	if (init_data > 0x21)
+		tmp = init_data - 0x21;
+	else
+		tmp = 0;
+	wl1251_reg_write32(wl, CLK_REQ_TIME, tmp);
+
+	/* set BB PLL configurations in RF AFE */
+	wl1251_reg_write32(wl, 0x003058cc, 0x4B5);
+
+	/* set RF_AFE_REG_5 */
+	wl1251_reg_write32(wl, 0x003058d4, 0x50);
+
+	/* set RF_AFE_CTRL_REG_2 */
+	wl1251_reg_write32(wl, 0x00305948, 0x11c001);
+
+	/*
+	 * change RF PLL and BB PLL divider for VCO clock and adjust VCO
+	 * bais current(RF_AFE_REG_13)
+	 */
+	wl1251_reg_write32(wl, 0x003058f4, 0x1e);
+
+	/* set BB PLL configurations */
+	tmp = LUT[ref_freq][LUT_PARAM_INTEGER_DIVIDER] | 0x00017000;
+	wl1251_reg_write32(wl, 0x00305840, tmp);
+
+	/* set fractional divider according to Appendix C-BB PLL
+	 * Calculations
+	 */
+	tmp = LUT[ref_freq][LUT_PARAM_FRACTIONAL_DIVIDER];
+	wl1251_reg_write32(wl, 0x00305844, tmp);
+
+	/* set the initial data for the sigma delta */
+	wl1251_reg_write32(wl, 0x00305848, 0x3039);
+
+	/*
+	 * set the accumulator attenuation value, calibration loop1
+	 * (alpha), calibration loop2 (beta), calibration loop3 (gamma) and
+	 * the VCO gain
+	 */
+	tmp = (LUT[ref_freq][LUT_PARAM_ATTN_BB] << 16) |
+		(LUT[ref_freq][LUT_PARAM_ALPHA_BB] << 12) | 0x1;
+	wl1251_reg_write32(wl, 0x00305854, tmp);
+
+	/*
+	 * set the calibration stop time after holdoff time expires and set
+	 * settling time HOLD_OFF_TIME_BB
+	 */
+	tmp = LUT[ref_freq][LUT_PARAM_STOP_TIME_BB] | 0x000A0000;
+	wl1251_reg_write32(wl, 0x00305858, tmp);
+
+	/*
+	 * set BB PLL Loop filter capacitor3- BB_C3[2:0] and set BB PLL
+	 * constant leakage current to linearize PFD to 0uA -
+	 * BB_ILOOPF[7:3]
+	 */
+	tmp = LUT[ref_freq][LUT_PARAM_BB_PLL_LOOP_FILTER] | 0x00000030;
+	wl1251_reg_write32(wl, 0x003058f8, tmp);
+
+	/*
+	 * set regulator output voltage for n divider to
+	 * 1.35-BB_REFDIV[1:0], set charge pump current- BB_CPGAIN[4:2],
+	 * set BB PLL Loop filter capacitor2- BB_C2[7:5], set gain of BB
+	 * PLL auto-call to normal mode- BB_CALGAIN_3DB[8]
+	 */
+	wl1251_reg_write32(wl, 0x003058f0, 0x29);
+
+	/* enable restart wakeup sequence (ELP_CMD[0]) */
+	wl1251_reg_write32(wl, ELP_CMD, elp_cmd | 0x1);
+
+	/* restart sequence completed */
+	udelay(2000);
+
+	return 0;
+}
+
+static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag)
+{
+	u32 cpu_ctrl;
+
+	/* 10.5.0 run the firmware (I) */
+	cpu_ctrl = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
+
+	/* 10.5.1 run the firmware (II) */
+	cpu_ctrl &= ~flag;
+	wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
+}
+
+int wl1251_boot_run_firmware(struct wl1251 *wl)
+{
+	int loop, ret;
+	u32 chip_id, acx_intr;
+
+	wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
+
+	chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
+
+	wl1251_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
+
+	if (chip_id != wl->chip_id) {
+		wl1251_error("chip id doesn't match after firmware boot");
+		return -EIO;
+	}
+
+	/* wait for init to complete */
+	loop = 0;
+	while (loop++ < INIT_LOOP) {
+		udelay(INIT_LOOP_DELAY);
+		acx_intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+
+		if (acx_intr == 0xffffffff) {
+			wl1251_error("error reading hardware complete "
+				     "init indication");
+			return -EIO;
+		}
+		/* check that ACX_INTR_INIT_COMPLETE is enabled */
+		else if (acx_intr & WL1251_ACX_INTR_INIT_COMPLETE) {
+			wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
+					   WL1251_ACX_INTR_INIT_COMPLETE);
+			break;
+		}
+	}
+
+	if (loop > INIT_LOOP) {
+		wl1251_error("timeout waiting for the hardware to "
+			     "complete initialization");
+		return -EIO;
+	}
+
+	/* get hardware config command mail box */
+	wl->cmd_box_addr = wl1251_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);
+
+	/* get hardware config event mail box */
+	wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
+
+	/* set the working partition to its "running" mode offset */
+	wl1251_set_partition(wl, WL1251_PART_WORK_MEM_START,
+			     WL1251_PART_WORK_MEM_SIZE,
+			     WL1251_PART_WORK_REG_START,
+			     WL1251_PART_WORK_REG_SIZE);
+
+	wl1251_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
+		     wl->cmd_box_addr, wl->event_box_addr);
+
+	wl1251_acx_fw_version(wl, wl->fw_ver, sizeof(wl->fw_ver));
+
+	/*
+	 * in case of full asynchronous mode the firmware event must be
+	 * ready to receive event from the command mailbox
+	 */
+
+	/* enable gpio interrupts */
+	wl1251_enable_interrupts(wl);
+
+	/* Enable target's interrupts */
+	wl->intr_mask = WL1251_ACX_INTR_RX0_DATA |
+		WL1251_ACX_INTR_RX1_DATA |
+		WL1251_ACX_INTR_TX_RESULT |
+		WL1251_ACX_INTR_EVENT_A |
+		WL1251_ACX_INTR_EVENT_B |
+		WL1251_ACX_INTR_INIT_COMPLETE;
+	wl1251_boot_target_enable_interrupts(wl);
+
+	wl->event_mask = SCAN_COMPLETE_EVENT_ID | BSS_LOSE_EVENT_ID |
+		SYNCHRONIZATION_TIMEOUT_EVENT_ID |
+		ROAMING_TRIGGER_LOW_RSSI_EVENT_ID |
+		ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID |
+		REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID |
+		BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID;
+
+	ret = wl1251_event_unmask(wl);
+	if (ret < 0) {
+		wl1251_error("EVENT mask setting failed");
+		return ret;
+	}
+
+	wl1251_event_mbox_config(wl);
+
+	/* firmware startup completed */
+	return 0;
+}
+
+static int wl1251_boot_upload_firmware(struct wl1251 *wl)
+{
+	int addr, chunk_num, partition_limit;
+	size_t fw_data_len, len;
+	u8 *p, *buf;
+
+	/* whal_FwCtrl_LoadFwImageSm() */
+
+	wl1251_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x",
+		     wl1251_reg_read32(wl, CHIP_ID_B));
+
+	/* 10.0 check firmware length and set partition */
+	fw_data_len =  (wl->fw[4] << 24) | (wl->fw[5] << 16) |
+		(wl->fw[6] << 8) | (wl->fw[7]);
+
+	wl1251_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len,
+		CHUNK_SIZE);
+
+	if ((fw_data_len % 4) != 0) {
+		wl1251_error("firmware length not multiple of four");
+		return -EIO;
+	}
+
+	buf = kmalloc(CHUNK_SIZE, GFP_KERNEL);
+	if (!buf) {
+		wl1251_error("allocation for firmware upload chunk failed");
+		return -ENOMEM;
+	}
+
+	wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START,
+			     WL1251_PART_DOWN_MEM_SIZE,
+			     WL1251_PART_DOWN_REG_START,
+			     WL1251_PART_DOWN_REG_SIZE);
+
+	/* 10.1 set partition limit and chunk num */
+	chunk_num = 0;
+	partition_limit = WL1251_PART_DOWN_MEM_SIZE;
+
+	while (chunk_num < fw_data_len / CHUNK_SIZE) {
+		/* 10.2 update partition, if needed */
+		addr = WL1251_PART_DOWN_MEM_START +
+			(chunk_num + 2) * CHUNK_SIZE;
+		if (addr > partition_limit) {
+			addr = WL1251_PART_DOWN_MEM_START +
+				chunk_num * CHUNK_SIZE;
+			partition_limit = chunk_num * CHUNK_SIZE +
+				WL1251_PART_DOWN_MEM_SIZE;
+			wl1251_set_partition(wl,
+					     addr,
+					     WL1251_PART_DOWN_MEM_SIZE,
+					     WL1251_PART_DOWN_REG_START,
+					     WL1251_PART_DOWN_REG_SIZE);
+		}
+
+		/* 10.3 upload the chunk */
+		addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
+		p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
+		wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
+			     p, addr);
+
+		/* need to copy the chunk for dma */
+		len = CHUNK_SIZE;
+		memcpy(buf, p, len);
+		wl1251_mem_write(wl, addr, buf, len);
+
+		chunk_num++;
+	}
+
+	/* 10.4 upload the last chunk */
+	addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
+	p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
+
+	/* need to copy the chunk for dma */
+	len = fw_data_len % CHUNK_SIZE;
+	memcpy(buf, p, len);
+
+	wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
+		     len, p, addr);
+	wl1251_mem_write(wl, addr, buf, len);
+
+	kfree(buf);
+
+	return 0;
+}
+
+static int wl1251_boot_upload_nvs(struct wl1251 *wl)
+{
+	size_t nvs_len, nvs_bytes_written, burst_len;
+	int nvs_start, i;
+	u32 dest_addr, val;
+	u8 *nvs_ptr, *nvs;
+
+	nvs = wl->nvs;
+	if (nvs == NULL)
+		return -ENODEV;
+
+	nvs_ptr = nvs;
+
+	nvs_len = wl->nvs_len;
+	nvs_start = wl->fw_len;
+
+	/*
+	 * Layout before the actual NVS tables:
+	 * 1 byte : burst length.
+	 * 2 bytes: destination address.
+	 * n bytes: data to burst copy.
+	 *
+	 * This is ended by a 0 length, then the NVS tables.
+	 */
+
+	while (nvs_ptr[0]) {
+		burst_len = nvs_ptr[0];
+		dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
+
+		/* We move our pointer to the data */
+		nvs_ptr += 3;
+
+		for (i = 0; i < burst_len; i++) {
+			val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
+			       | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
+
+			wl1251_debug(DEBUG_BOOT,
+				     "nvs burst write 0x%x: 0x%x",
+				     dest_addr, val);
+			wl1251_mem_write32(wl, dest_addr, val);
+
+			nvs_ptr += 4;
+			dest_addr += 4;
+		}
+	}
+
+	/*
+	 * We've reached the first zero length, the first NVS table
+	 * is 7 bytes further.
+	 */
+	nvs_ptr += 7;
+	nvs_len -= nvs_ptr - nvs;
+	nvs_len = ALIGN(nvs_len, 4);
+
+	/* Now we must set the partition correctly */
+	wl1251_set_partition(wl, nvs_start,
+			     WL1251_PART_DOWN_MEM_SIZE,
+			     WL1251_PART_DOWN_REG_START,
+			     WL1251_PART_DOWN_REG_SIZE);
+
+	/* And finally we upload the NVS tables */
+	nvs_bytes_written = 0;
+	while (nvs_bytes_written < nvs_len) {
+		val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
+		       | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
+
+		val = cpu_to_le32(val);
+
+		wl1251_debug(DEBUG_BOOT,
+			     "nvs write table 0x%x: 0x%x",
+			     nvs_start, val);
+		wl1251_mem_write32(wl, nvs_start, val);
+
+		nvs_ptr += 4;
+		nvs_bytes_written += 4;
+		nvs_start += 4;
+	}
+
+	return 0;
+}
+
+int wl1251_boot(struct wl1251 *wl)
+{
+	int ret = 0, minor_minor_e2_ver;
+	u32 tmp, boot_data;
+
+	/* halt embedded ARM CPU while loading firmware */
+	wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT);
+
+	ret = wl1251_boot_soft_reset(wl);
+	if (ret < 0)
+		goto out;
+
+	/* 2. start processing NVS file */
+	if (wl->use_eeprom) {
+		wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR);
+		/* Wait for EEPROM NVS burst read to complete */
+		msleep(40);
+		wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM);
+	} else {
+		ret = wl1251_boot_upload_nvs(wl);
+		if (ret < 0)
+			goto out;
+
+		/* write firmware's last address (ie. it's length) to
+		 * ACX_EEPROMLESS_IND_REG */
+		wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len);
+	}
+
+	/* 6. read the EEPROM parameters */
+	tmp = wl1251_reg_read32(wl, SCR_PAD2);
+
+	/* 7. read bootdata */
+	wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8;
+	wl->boot_attr.major = (tmp & 0x00FF0000) >> 16;
+	tmp = wl1251_reg_read32(wl, SCR_PAD3);
+
+	/* 8. check bootdata and call restart sequence */
+	wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16;
+	minor_minor_e2_ver = (tmp & 0xFF000000) >> 24;
+
+	wl1251_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x "
+		     "minorE2Ver 0x%x minor_minor_e2_ver 0x%x",
+		     wl->boot_attr.radio_type, wl->boot_attr.major,
+		     wl->boot_attr.minor, minor_minor_e2_ver);
+
+	ret = wl1251_boot_init_seq(wl);
+	if (ret < 0)
+		goto out;
+
+	/* 9. NVS processing done */
+	boot_data = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
+
+	wl1251_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data);
+
+	/* 10. check that ECPU_CONTROL_HALT bits are set in
+	 * pWhalBus->uBootData and start uploading firmware
+	 */
+	if ((boot_data & ECPU_CONTROL_HALT) == 0) {
+		wl1251_error("boot failed, ECPU_CONTROL_HALT not set");
+		ret = -EIO;
+		goto out;
+	}
+
+	ret = wl1251_boot_upload_firmware(wl);
+	if (ret < 0)
+		goto out;
+
+	/* 10.5 start firmware */
+	ret = wl1251_boot_run_firmware(wl);
+	if (ret < 0)
+		goto out;
+
+out:
+	return ret;
+}
diff --git a/drivers/net/wireless/wl1251/boot.h b/drivers/net/wireless/wl1251/boot.h
new file mode 100644
index 0000000..7661bc5
--- /dev/null
+++ b/drivers/net/wireless/wl1251/boot.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 __BOOT_H__
+#define __BOOT_H__
+
+#include "wl1251.h"
+
+int wl1251_boot_soft_reset(struct wl1251 *wl);
+int wl1251_boot_init_seq(struct wl1251 *wl);
+int wl1251_boot_run_firmware(struct wl1251 *wl);
+void wl1251_boot_target_enable_interrupts(struct wl1251 *wl);
+int wl1251_boot(struct wl1251 *wl);
+
+/* number of times we try to read the INIT interrupt */
+#define INIT_LOOP 20000
+
+/* delay between retries */
+#define INIT_LOOP_DELAY 50
+
+#endif
diff --git a/drivers/net/wireless/wl1251/cmd.c b/drivers/net/wireless/wl1251/cmd.c
new file mode 100644
index 0000000..0ade4bd
--- /dev/null
+++ b/drivers/net/wireless/wl1251/cmd.c
@@ -0,0 +1,496 @@
+#include "cmd.h"
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/crc7.h>
+
+#include "wl1251.h"
+#include "reg.h"
+#include "io.h"
+#include "ps.h"
+#include "acx.h"
+
+/**
+ * send command to firmware
+ *
+ * @wl: wl struct
+ * @id: command id
+ * @buf: buffer containing the command, must work with dma
+ * @len: length of the buffer
+ */
+int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len)
+{
+	struct wl1251_cmd_header *cmd;
+	unsigned long timeout;
+	u32 intr;
+	int ret = 0;
+
+	cmd = buf;
+	cmd->id = id;
+	cmd->status = 0;
+
+	WARN_ON(len % 4 != 0);
+
+	wl1251_mem_write(wl, wl->cmd_box_addr, buf, len);
+
+	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
+
+	timeout = jiffies + msecs_to_jiffies(WL1251_COMMAND_TIMEOUT);
+
+	intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+	while (!(intr & WL1251_ACX_INTR_CMD_COMPLETE)) {
+		if (time_after(jiffies, timeout)) {
+			wl1251_error("command complete timeout");
+			ret = -ETIMEDOUT;
+			goto out;
+		}
+
+		msleep(1);
+
+		intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+	}
+
+	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
+			   WL1251_ACX_INTR_CMD_COMPLETE);
+
+out:
+	return ret;
+}
+
+/**
+ * send test command to firmware
+ *
+ * @wl: wl struct
+ * @buf: buffer containing the command, with all headers, must work with dma
+ * @len: length of the buffer
+ * @answer: is answer needed
+ */
+int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer)
+{
+	int ret;
+
+	wl1251_debug(DEBUG_CMD, "cmd test");
+
+	ret = wl1251_cmd_send(wl, CMD_TEST, buf, buf_len);
+
+	if (ret < 0) {
+		wl1251_warning("TEST command failed");
+		return ret;
+	}
+
+	if (answer) {
+		struct wl1251_command *cmd_answer;
+
+		/*
+		 * The test command got in, we can read the answer.
+		 * The answer would be a wl1251_command, where the
+		 * parameter array contains the actual answer.
+		 */
+		wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len);
+
+		cmd_answer = buf;
+
+		if (cmd_answer->header.status != CMD_STATUS_SUCCESS)
+			wl1251_error("TEST command answer error: %d",
+				     cmd_answer->header.status);
+	}
+
+	return 0;
+}
+
+/**
+ * read acx from firmware
+ *
+ * @wl: wl struct
+ * @id: acx id
+ * @buf: buffer for the response, including all headers, must work with dma
+ * @len: lenght of buf
+ */
+int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len)
+{
+	struct acx_header *acx = buf;
+	int ret;
+
+	wl1251_debug(DEBUG_CMD, "cmd interrogate");
+
+	acx->id = id;
+
+	/* payload length, does not include any headers */
+	acx->len = len - sizeof(*acx);
+
+	ret = wl1251_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_error("INTERROGATE command failed");
+		goto out;
+	}
+
+	/* the interrogate command got in, we can read the answer */
+	wl1251_mem_read(wl, wl->cmd_box_addr, buf, len);
+
+	acx = buf;
+	if (acx->cmd.status != CMD_STATUS_SUCCESS)
+		wl1251_error("INTERROGATE command error: %d",
+			     acx->cmd.status);
+
+out:
+	return ret;
+}
+
+/**
+ * write acx value to firmware
+ *
+ * @wl: wl struct
+ * @id: acx id
+ * @buf: buffer containing acx, including all headers, must work with dma
+ * @len: length of buf
+ */
+int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len)
+{
+	struct acx_header *acx = buf;
+	int ret;
+
+	wl1251_debug(DEBUG_CMD, "cmd configure");
+
+	acx->id = id;
+
+	/* payload length, does not include any headers */
+	acx->len = len - sizeof(*acx);
+
+	ret = wl1251_cmd_send(wl, CMD_CONFIGURE, acx, len);
+	if (ret < 0) {
+		wl1251_warning("CONFIGURE command NOK");
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
+		   void *bitmap, u16 bitmap_len, u8 bitmap_control)
+{
+	struct wl1251_cmd_vbm_update *vbm;
+	int ret;
+
+	wl1251_debug(DEBUG_CMD, "cmd vbm");
+
+	vbm = kzalloc(sizeof(*vbm), GFP_KERNEL);
+	if (!vbm) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Count and period will be filled by the target */
+	vbm->tim.bitmap_ctrl = bitmap_control;
+	if (bitmap_len > PARTIAL_VBM_MAX) {
+		wl1251_warning("cmd vbm len is %d B, truncating to %d",
+			       bitmap_len, PARTIAL_VBM_MAX);
+		bitmap_len = PARTIAL_VBM_MAX;
+	}
+	memcpy(vbm->tim.pvb_field, bitmap, bitmap_len);
+	vbm->tim.identity = identity;
+	vbm->tim.length = bitmap_len + 3;
+
+	vbm->len = cpu_to_le16(bitmap_len + 5);
+
+	ret = wl1251_cmd_send(wl, CMD_VBM, vbm, sizeof(*vbm));
+	if (ret < 0) {
+		wl1251_error("VBM command failed");
+		goto out;
+	}
+
+out:
+	kfree(vbm);
+	return ret;
+}
+
+int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
+{
+	struct cmd_enabledisable_path *cmd;
+	int ret;
+	u16 cmd_rx, cmd_tx;
+
+	wl1251_debug(DEBUG_CMD, "cmd data path");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->channel = channel;
+
+	if (enable) {
+		cmd_rx = CMD_ENABLE_RX;
+		cmd_tx = CMD_ENABLE_TX;
+	} else {
+		cmd_rx = CMD_DISABLE_RX;
+		cmd_tx = CMD_DISABLE_TX;
+	}
+
+	ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
+	if (ret < 0) {
+		wl1251_error("rx %s cmd for channel %d failed",
+			     enable ? "start" : "stop", channel);
+		goto out;
+	}
+
+	wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d",
+		     enable ? "start" : "stop", channel);
+
+	ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
+	if (ret < 0) {
+		wl1251_error("tx %s cmd for channel %d failed",
+			     enable ? "start" : "stop", channel);
+		return ret;
+	}
+
+	wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
+		     enable ? "start" : "stop", channel);
+
+out:
+	kfree(cmd);
+	return ret;
+}
+
+int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
+		    u16 beacon_interval, u8 dtim_interval)
+{
+	struct cmd_join *join;
+	int ret, i;
+	u8 *bssid;
+
+	join = kzalloc(sizeof(*join), GFP_KERNEL);
+	if (!join) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	wl1251_debug(DEBUG_CMD, "cmd join%s ch %d %d/%d",
+		     bss_type == BSS_TYPE_IBSS ? " ibss" : "",
+		     channel, beacon_interval, dtim_interval);
+
+	/* Reverse order BSSID */
+	bssid = (u8 *) &join->bssid_lsb;
+	for (i = 0; i < ETH_ALEN; i++)
+		bssid[i] = wl->bssid[ETH_ALEN - i - 1];
+
+	join->rx_config_options = wl->rx_config;
+	join->rx_filter_options = wl->rx_filter;
+
+	/*
+	 * FIXME: disable temporarily all filters because after commit
+	 * 9cef8737 "mac80211: fix managed mode BSSID handling" broke
+	 * association. The filter logic needs to be implemented properly
+	 * and once that is done, this hack can be removed.
+	 */
+	join->rx_config_options = 0;
+	join->rx_filter_options = WL1251_DEFAULT_RX_FILTER;
+
+	join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
+		RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
+
+	join->beacon_interval = beacon_interval;
+	join->dtim_interval = dtim_interval;
+	join->bss_type = bss_type;
+	join->channel = channel;
+	join->ctrl = JOIN_CMD_CTRL_TX_FLUSH;
+
+	ret = wl1251_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
+	if (ret < 0) {
+		wl1251_error("failed to initiate cmd join");
+		goto out;
+	}
+
+out:
+	kfree(join);
+	return ret;
+}
+
+int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode)
+{
+	struct wl1251_cmd_ps_params *ps_params = NULL;
+	int ret = 0;
+
+	wl1251_debug(DEBUG_CMD, "cmd set ps mode");
+
+	ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
+	if (!ps_params) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ps_params->ps_mode = ps_mode;
+	ps_params->send_null_data = 1;
+	ps_params->retries = 5;
+	ps_params->hang_over_period = 128;
+	ps_params->null_data_rate = 1; /* 1 Mbps */
+
+	ret = wl1251_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
+			      sizeof(*ps_params));
+	if (ret < 0) {
+		wl1251_error("cmd set_ps_mode failed");
+		goto out;
+	}
+
+out:
+	kfree(ps_params);
+	return ret;
+}
+
+int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
+			   size_t len)
+{
+	struct cmd_read_write_memory *cmd;
+	int ret = 0;
+
+	wl1251_debug(DEBUG_CMD, "cmd read memory");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	WARN_ON(len > MAX_READ_SIZE);
+	len = min_t(size_t, len, MAX_READ_SIZE);
+
+	cmd->addr = addr;
+	cmd->size = len;
+
+	ret = wl1251_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd));
+	if (ret < 0) {
+		wl1251_error("read memory command failed: %d", ret);
+		goto out;
+	}
+
+	/* the read command got in, we can now read the answer */
+	wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
+
+	if (cmd->header.status != CMD_STATUS_SUCCESS)
+		wl1251_error("error in read command result: %d",
+			     cmd->header.status);
+
+	memcpy(answer, cmd->value, len);
+
+out:
+	kfree(cmd);
+	return ret;
+}
+
+int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id,
+			    void *buf, size_t buf_len)
+{
+	struct wl1251_cmd_packet_template *cmd;
+	size_t cmd_len;
+	int ret = 0;
+
+	wl1251_debug(DEBUG_CMD, "cmd template %d", cmd_id);
+
+	WARN_ON(buf_len > WL1251_MAX_TEMPLATE_SIZE);
+	buf_len = min_t(size_t, buf_len, WL1251_MAX_TEMPLATE_SIZE);
+	cmd_len = ALIGN(sizeof(*cmd) + buf_len, 4);
+
+	cmd = kzalloc(cmd_len, GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->size = cpu_to_le16(buf_len);
+
+	if (buf)
+		memcpy(cmd->data, buf, buf_len);
+
+	ret = wl1251_cmd_send(wl, cmd_id, cmd, cmd_len);
+	if (ret < 0) {
+		wl1251_warning("cmd set_template failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(cmd);
+	return ret;
+}
+
+int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
+		    struct ieee80211_channel *channels[],
+		    unsigned int n_channels, unsigned int n_probes)
+{
+	struct wl1251_cmd_scan *cmd;
+	int i, ret = 0;
+
+	wl1251_debug(DEBUG_CMD, "cmd scan");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+
+	cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
+	cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN |
+						    CFG_RX_MGMT_EN |
+						    CFG_RX_BCN_EN);
+	cmd->params.scan_options = 0;
+	cmd->params.num_channels = n_channels;
+	cmd->params.num_probe_requests = n_probes;
+	cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
+	cmd->params.tid_trigger = 0;
+
+	for (i = 0; i < n_channels; i++) {
+		cmd->channels[i].min_duration =
+			cpu_to_le32(WL1251_SCAN_MIN_DURATION);
+		cmd->channels[i].max_duration =
+			cpu_to_le32(WL1251_SCAN_MAX_DURATION);
+		memset(&cmd->channels[i].bssid_lsb, 0xff, 4);
+		memset(&cmd->channels[i].bssid_msb, 0xff, 2);
+		cmd->channels[i].early_termination = 0;
+		cmd->channels[i].tx_power_att = 0;
+		cmd->channels[i].channel = channels[i]->hw_value;
+	}
+
+	cmd->params.ssid_len = ssid_len;
+	if (ssid)
+		memcpy(cmd->params.ssid, ssid, ssid_len);
+
+	ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd));
+	if (ret < 0) {
+		wl1251_error("cmd scan failed: %d", ret);
+		goto out;
+	}
+
+	wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
+
+	if (cmd->header.status != CMD_STATUS_SUCCESS) {
+		wl1251_error("cmd scan status wasn't success: %d",
+			     cmd->header.status);
+		ret = -EIO;
+		goto out;
+	}
+
+out:
+	kfree(cmd);
+	return ret;
+}
+
+int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout)
+{
+	struct wl1251_cmd_trigger_scan_to *cmd;
+	int ret;
+
+	wl1251_debug(DEBUG_CMD, "cmd trigger scan to");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+
+	cmd->timeout = timeout;
+
+	ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, cmd, sizeof(*cmd));
+	if (ret < 0) {
+		wl1251_error("cmd trigger scan to failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(cmd);
+	return ret;
+}
diff --git a/drivers/net/wireless/wl1251/cmd.h b/drivers/net/wireless/wl1251/cmd.h
new file mode 100644
index 0000000..e5c74c6
--- /dev/null
+++ b/drivers/net/wireless/wl1251/cmd.h
@@ -0,0 +1,415 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 __WL1251_CMD_H__
+#define __WL1251_CMD_H__
+
+#include "wl1251.h"
+
+#include <net/cfg80211.h>
+
+struct acx_header;
+
+int wl1251_cmd_send(struct wl1251 *wl, u16 type, void *buf, size_t buf_len);
+int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer);
+int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len);
+int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len);
+int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
+		   void *bitmap, u16 bitmap_len, u8 bitmap_control);
+int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable);
+int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
+		    u16 beacon_interval, u8 dtim_interval);
+int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode);
+int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
+			   size_t len);
+int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id,
+			    void *buf, size_t buf_len);
+int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
+		    struct ieee80211_channel *channels[],
+		    unsigned int n_channels, unsigned int n_probes);
+int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout);
+
+/* unit ms */
+#define WL1251_COMMAND_TIMEOUT 2000
+
+enum wl1251_commands {
+	CMD_RESET           = 0,
+	CMD_INTERROGATE     = 1,    /*use this to read information elements*/
+	CMD_CONFIGURE       = 2,    /*use this to write information elements*/
+	CMD_ENABLE_RX       = 3,
+	CMD_ENABLE_TX       = 4,
+	CMD_DISABLE_RX      = 5,
+	CMD_DISABLE_TX      = 6,
+	CMD_SCAN            = 8,
+	CMD_STOP_SCAN       = 9,
+	CMD_VBM             = 10,
+	CMD_START_JOIN      = 11,
+	CMD_SET_KEYS        = 12,
+	CMD_READ_MEMORY     = 13,
+	CMD_WRITE_MEMORY    = 14,
+	CMD_BEACON          = 19,
+	CMD_PROBE_RESP      = 20,
+	CMD_NULL_DATA       = 21,
+	CMD_PROBE_REQ       = 22,
+	CMD_TEST            = 23,
+	CMD_RADIO_CALIBRATE     = 25,   /* OBSOLETE */
+	CMD_ENABLE_RX_PATH      = 27,   /* OBSOLETE */
+	CMD_NOISE_HIST      = 28,
+	CMD_RX_RESET        = 29,
+	CMD_PS_POLL         = 30,
+	CMD_QOS_NULL_DATA   = 31,
+	CMD_LNA_CONTROL     = 32,
+	CMD_SET_BCN_MODE    = 33,
+	CMD_MEASUREMENT      = 34,
+	CMD_STOP_MEASUREMENT = 35,
+	CMD_DISCONNECT       = 36,
+	CMD_SET_PS_MODE      = 37,
+	CMD_CHANNEL_SWITCH   = 38,
+	CMD_STOP_CHANNEL_SWICTH = 39,
+	CMD_AP_DISCOVERY     = 40,
+	CMD_STOP_AP_DISCOVERY = 41,
+	CMD_SPS_SCAN = 42,
+	CMD_STOP_SPS_SCAN = 43,
+	CMD_HEALTH_CHECK     = 45,
+	CMD_DEBUG            = 46,
+	CMD_TRIGGER_SCAN_TO  = 47,
+
+	NUM_COMMANDS,
+	MAX_COMMAND_ID = 0xFFFF,
+};
+
+#define MAX_CMD_PARAMS 572
+
+struct wl1251_cmd_header {
+	u16 id;
+	u16 status;
+	/* payload */
+	u8 data[0];
+} __packed;
+
+struct  wl1251_command {
+	struct wl1251_cmd_header header;
+	u8  parameters[MAX_CMD_PARAMS];
+} __packed;
+
+enum {
+	CMD_MAILBOX_IDLE              		=  0,
+	CMD_STATUS_SUCCESS            		=  1,
+	CMD_STATUS_UNKNOWN_CMD        		=  2,
+	CMD_STATUS_UNKNOWN_IE         		=  3,
+	CMD_STATUS_REJECT_MEAS_SG_ACTIVE 	= 11,
+	CMD_STATUS_RX_BUSY            		= 13,
+	CMD_STATUS_INVALID_PARAM      		= 14,
+	CMD_STATUS_TEMPLATE_TOO_LARGE 		= 15,
+	CMD_STATUS_OUT_OF_MEMORY      		= 16,
+	CMD_STATUS_STA_TABLE_FULL     		= 17,
+	CMD_STATUS_RADIO_ERROR        		= 18,
+	CMD_STATUS_WRONG_NESTING      		= 19,
+	CMD_STATUS_TIMEOUT            		= 21, /* Driver internal use.*/
+	CMD_STATUS_FW_RESET           		= 22, /* Driver internal use.*/
+	MAX_COMMAND_STATUS            		= 0xff
+};
+
+
+/*
+ * CMD_READ_MEMORY
+ *
+ * The host issues this command to read the WiLink device memory/registers.
+ *
+ * Note: The Base Band address has special handling (16 bits registers and
+ * addresses). For more information, see the hardware specification.
+ */
+/*
+ * CMD_WRITE_MEMORY
+ *
+ * The host issues this command to write the WiLink device memory/registers.
+ *
+ * The Base Band address has special handling (16 bits registers and
+ * addresses). For more information, see the hardware specification.
+ */
+#define MAX_READ_SIZE 256
+
+struct cmd_read_write_memory {
+	struct wl1251_cmd_header header;
+
+	/* The address of the memory to read from or write to.*/
+	u32 addr;
+
+	/* The amount of data in bytes to read from or write to the WiLink
+	 * device.*/
+	u32 size;
+
+	/* The actual value read from or written to the Wilink. The source
+	   of this field is the Host in WRITE command or the Wilink in READ
+	   command. */
+	u8 value[MAX_READ_SIZE];
+} __packed;
+
+#define CMDMBOX_HEADER_LEN 4
+#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
+
+#define WL1251_SCAN_MIN_DURATION 30000
+#define WL1251_SCAN_MAX_DURATION 60000
+
+#define WL1251_SCAN_NUM_PROBES 3
+
+struct wl1251_scan_parameters {
+	__le32 rx_config_options;
+	__le32 rx_filter_options;
+
+	/*
+	 * Scan options:
+	 * bit 0: When this bit is set, passive scan.
+	 * bit 1: Band, when this bit is set we scan
+	 * in the 5Ghz band.
+	 * bit 2: voice mode, 0 for normal scan.
+	 * bit 3: scan priority, 1 for high priority.
+	 */
+	__le16 scan_options;
+
+	/* Number of channels to scan */
+	u8 num_channels;
+
+	/* Number opf probe requests to send, per channel */
+	u8 num_probe_requests;
+
+	/* Rate and modulation for probe requests */
+	__le16 tx_rate;
+
+	u8 tid_trigger;
+	u8 ssid_len;
+	u8 ssid[32];
+
+} __packed;
+
+struct wl1251_scan_ch_parameters {
+	__le32 min_duration; /* in TU */
+	__le32 max_duration; /* in TU */
+	u32 bssid_lsb;
+	u16 bssid_msb;
+
+	/*
+	 * bits 0-3: Early termination count.
+	 * bits 4-5: Early termination condition.
+	 */
+	u8 early_termination;
+
+	u8 tx_power_att;
+	u8 channel;
+	u8 pad[3];
+} __packed;
+
+/* SCAN parameters */
+#define SCAN_MAX_NUM_OF_CHANNELS 16
+
+struct wl1251_cmd_scan {
+	struct wl1251_cmd_header header;
+
+	struct wl1251_scan_parameters params;
+	struct wl1251_scan_ch_parameters channels[SCAN_MAX_NUM_OF_CHANNELS];
+} __packed;
+
+enum {
+	BSS_TYPE_IBSS = 0,
+	BSS_TYPE_STA_BSS = 2,
+	BSS_TYPE_AP_BSS = 3,
+	MAX_BSS_TYPE = 0xFF
+};
+
+#define JOIN_CMD_CTRL_TX_FLUSH             0x80 /* Firmware flushes all Tx */
+#define JOIN_CMD_CTRL_EARLY_WAKEUP_ENABLE  0x01 /* Early wakeup time */
+
+
+struct cmd_join {
+	struct wl1251_cmd_header header;
+
+	u32 bssid_lsb;
+	u16 bssid_msb;
+	u16 beacon_interval; /* in TBTTs */
+	u32 rx_config_options;
+	u32 rx_filter_options;
+
+	/*
+	 * The target uses this field to determine the rate at
+	 * which to transmit control frame responses (such as
+	 * ACK or CTS frames).
+	 */
+	u16 basic_rate_set;
+	u8 dtim_interval;
+	u8 tx_ctrl_frame_rate; /* OBSOLETE */
+	u8 tx_ctrl_frame_mod;  /* OBSOLETE */
+	/*
+	 * bits 0-2: This bitwise field specifies the type
+	 * of BSS to start or join (BSS_TYPE_*).
+	 * bit 4: Band - The radio band in which to join
+	 * or start.
+	 *  0 - 2.4GHz band
+	 *  1 - 5GHz band
+	 * bits 3, 5-7: Reserved
+	 */
+	u8 bss_type;
+	u8 channel;
+	u8 ssid_len;
+	u8 ssid[IW_ESSID_MAX_SIZE];
+	u8 ctrl; /* JOIN_CMD_CTRL_* */
+	u8 tx_mgt_frame_rate; /* OBSOLETE */
+	u8 tx_mgt_frame_mod;  /* OBSOLETE */
+	u8 reserved;
+} __packed;
+
+struct cmd_enabledisable_path {
+	struct wl1251_cmd_header header;
+
+	u8 channel;
+	u8 padding[3];
+} __packed;
+
+#define WL1251_MAX_TEMPLATE_SIZE 300
+
+struct wl1251_cmd_packet_template {
+	struct wl1251_cmd_header header;
+
+	__le16 size;
+	u8 data[0];
+} __packed;
+
+#define TIM_ELE_ID    5
+#define PARTIAL_VBM_MAX    251
+
+struct wl1251_tim {
+	u8 identity;
+	u8 length;
+	u8 dtim_count;
+	u8 dtim_period;
+	u8 bitmap_ctrl;
+	u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */
+} __packed;
+
+/* Virtual Bit Map update */
+struct wl1251_cmd_vbm_update {
+	struct wl1251_cmd_header header;
+	__le16 len;
+	u8  padding[2];
+	struct wl1251_tim tim;
+} __packed;
+
+enum wl1251_cmd_ps_mode {
+	STATION_ACTIVE_MODE,
+	STATION_POWER_SAVE_MODE
+};
+
+struct wl1251_cmd_ps_params {
+	struct wl1251_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;
+	u16 null_data_rate;
+	u8 pad[2];
+} __packed;
+
+struct wl1251_cmd_trigger_scan_to {
+	struct wl1251_cmd_header header;
+
+	u32 timeout;
+} __packed;
+
+/* HW encryption keys */
+#define NUM_ACCESS_CATEGORIES_COPY 4
+#define MAX_KEY_SIZE 32
+
+/* When set, disable HW encryption */
+#define DF_ENCRYPTION_DISABLE      0x01
+/* When set, disable HW decryption */
+#define DF_SNIFF_MODE_ENABLE       0x80
+
+enum wl1251_cmd_key_action {
+	KEY_ADD_OR_REPLACE = 1,
+	KEY_REMOVE         = 2,
+	KEY_SET_ID         = 3,
+	MAX_KEY_ACTION     = 0xffff,
+};
+
+enum wl1251_cmd_key_type {
+	KEY_WEP_DEFAULT       = 0,
+	KEY_WEP_ADDR          = 1,
+	KEY_AES_GROUP         = 4,
+	KEY_AES_PAIRWISE      = 5,
+	KEY_WEP_GROUP         = 6,
+	KEY_TKIP_MIC_GROUP    = 10,
+	KEY_TKIP_MIC_PAIRWISE = 11,
+};
+
+/*
+ *
+ * key_type_e   key size    key format
+ * ----------   ---------   ----------
+ * 0x00         5, 13, 29   Key data
+ * 0x01         5, 13, 29   Key data
+ * 0x04         16          16 bytes of key data
+ * 0x05         16          16 bytes of key data
+ * 0x0a         32          16 bytes of TKIP key data
+ *                          8 bytes of RX MIC key data
+ *                          8 bytes of TX MIC key data
+ * 0x0b         32          16 bytes of TKIP key data
+ *                          8 bytes of RX MIC key data
+ *                          8 bytes of TX MIC key data
+ *
+ */
+
+struct wl1251_cmd_set_keys {
+	struct wl1251_cmd_header header;
+
+	/* Ignored for default WEP key */
+	u8 addr[ETH_ALEN];
+
+	/* key_action_e */
+	u16 key_action;
+
+	u16 reserved_1;
+
+	/* key size in bytes */
+	u8 key_size;
+
+	/* key_type_e */
+	u8 key_type;
+	u8 ssid_profile;
+
+	/*
+	 * TKIP, AES: frame's key id field.
+	 * For WEP default key: key id;
+	 */
+	u8 id;
+	u8 reserved_2[6];
+	u8 key[MAX_KEY_SIZE];
+	u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
+	u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
+} __packed;
+
+
+#endif /* __WL1251_CMD_H__ */
diff --git a/drivers/net/wireless/wl1251/debugfs.c b/drivers/net/wireless/wl1251/debugfs.c
new file mode 100644
index 0000000..6c27400
--- /dev/null
+++ b/drivers/net/wireless/wl1251/debugfs.c
@@ -0,0 +1,545 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "debugfs.h"
+
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+
+#include "wl1251.h"
+#include "acx.h"
+#include "ps.h"
+
+/* ms */
+#define WL1251_DEBUGFS_STATS_LIFETIME 1000
+
+/* debugfs macros idea from mac80211 */
+
+#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)		\
+static ssize_t name## _read(struct file *file, char __user *userbuf,	\
+			    size_t count, loff_t *ppos)			\
+{									\
+	struct wl1251 *wl = file->private_data;				\
+	char buf[buflen];						\
+	int res;							\
+									\
+	res = scnprintf(buf, buflen, fmt "\n", ##value);		\
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
+}									\
+									\
+static const struct file_operations name## _ops = {			\
+	.read = name## _read,						\
+	.open = wl1251_open_file_generic,				\
+	.llseek	= generic_file_llseek,					\
+};
+
+#define DEBUGFS_ADD(name, parent)					\
+	wl->debugfs.name = debugfs_create_file(#name, 0400, parent,	\
+					       wl, &name## _ops);	\
+	if (IS_ERR(wl->debugfs.name)) {					\
+		ret = PTR_ERR(wl->debugfs.name);			\
+		wl->debugfs.name = NULL;				\
+		goto out;						\
+	}
+
+#define DEBUGFS_DEL(name)						\
+	do {								\
+		debugfs_remove(wl->debugfs.name);			\
+		wl->debugfs.name = NULL;				\
+	} while (0)
+
+#define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt)			\
+static ssize_t sub## _ ##name## _read(struct file *file,		\
+				      char __user *userbuf,		\
+				      size_t count, loff_t *ppos)	\
+{									\
+	struct wl1251 *wl = file->private_data;				\
+	char buf[buflen];						\
+	int res;							\
+									\
+	wl1251_debugfs_update_stats(wl);				\
+									\
+	res = scnprintf(buf, buflen, fmt "\n",				\
+			wl->stats.fw_stats->sub.name);			\
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
+}									\
+									\
+static const struct file_operations sub## _ ##name## _ops = {		\
+	.read = sub## _ ##name## _read,					\
+	.open = wl1251_open_file_generic,				\
+	.llseek	= generic_file_llseek,					\
+};
+
+#define DEBUGFS_FWSTATS_ADD(sub, name)				\
+	DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics)
+
+#define DEBUGFS_FWSTATS_DEL(sub, name)				\
+	DEBUGFS_DEL(sub## _ ##name)
+
+static void wl1251_debugfs_update_stats(struct wl1251 *wl)
+{
+	int ret;
+
+	mutex_lock(&wl->mutex);
+
+	ret = wl1251_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	if (wl->state == WL1251_STATE_ON &&
+	    time_after(jiffies, wl->stats.fw_stats_update +
+		       msecs_to_jiffies(WL1251_DEBUGFS_STATS_LIFETIME))) {
+		wl1251_acx_statistics(wl, wl->stats.fw_stats);
+		wl->stats.fw_stats_update = jiffies;
+	}
+
+	wl1251_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+}
+
+static int wl1251_open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u");
+DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u");
+DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u");
+DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u");
+/* skipping wep.reserved */
+DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u");
+/* skipping cont_miss_bcns_spread for now */
+DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u");
+DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data,
+		     20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u");
+
+DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count);
+DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u",
+		      wl->stats.excessive_retries);
+
+static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	struct wl1251 *wl = file->private_data;
+	u32 queue_len;
+	char buf[20];
+	int res;
+
+	queue_len = skb_queue_len(&wl->tx_queue);
+
+	res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+
+static const struct file_operations tx_queue_len_ops = {
+	.read = tx_queue_len_read,
+	.open = wl1251_open_file_generic,
+	.llseek = generic_file_llseek,
+};
+
+static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf,
+				    size_t count, loff_t *ppos)
+{
+	struct wl1251 *wl = file->private_data;
+	char buf[3], status;
+	int len;
+
+	if (wl->tx_queue_stopped)
+		status = 's';
+	else
+		status = 'r';
+
+	len = scnprintf(buf, sizeof(buf), "%c\n", status);
+	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+static const struct file_operations tx_queue_status_ops = {
+	.read = tx_queue_status_read,
+	.open = wl1251_open_file_generic,
+	.llseek = generic_file_llseek,
+};
+
+static void wl1251_debugfs_delete_files(struct wl1251 *wl)
+{
+	DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
+
+	DEBUGFS_FWSTATS_DEL(rx, out_of_mem);
+	DEBUGFS_FWSTATS_DEL(rx, hdr_overflow);
+	DEBUGFS_FWSTATS_DEL(rx, hw_stuck);
+	DEBUGFS_FWSTATS_DEL(rx, dropped);
+	DEBUGFS_FWSTATS_DEL(rx, fcs_err);
+	DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig);
+	DEBUGFS_FWSTATS_DEL(rx, path_reset);
+	DEBUGFS_FWSTATS_DEL(rx, reset_counter);
+
+	DEBUGFS_FWSTATS_DEL(dma, rx_requested);
+	DEBUGFS_FWSTATS_DEL(dma, rx_errors);
+	DEBUGFS_FWSTATS_DEL(dma, tx_requested);
+	DEBUGFS_FWSTATS_DEL(dma, tx_errors);
+
+	DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt);
+	DEBUGFS_FWSTATS_DEL(isr, fiqs);
+	DEBUGFS_FWSTATS_DEL(isr, rx_headers);
+	DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow);
+	DEBUGFS_FWSTATS_DEL(isr, rx_rdys);
+	DEBUGFS_FWSTATS_DEL(isr, irqs);
+	DEBUGFS_FWSTATS_DEL(isr, tx_procs);
+	DEBUGFS_FWSTATS_DEL(isr, decrypt_done);
+	DEBUGFS_FWSTATS_DEL(isr, dma0_done);
+	DEBUGFS_FWSTATS_DEL(isr, dma1_done);
+	DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete);
+	DEBUGFS_FWSTATS_DEL(isr, commands);
+	DEBUGFS_FWSTATS_DEL(isr, rx_procs);
+	DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes);
+	DEBUGFS_FWSTATS_DEL(isr, host_acknowledges);
+	DEBUGFS_FWSTATS_DEL(isr, pci_pm);
+	DEBUGFS_FWSTATS_DEL(isr, wakeups);
+	DEBUGFS_FWSTATS_DEL(isr, low_rssi);
+
+	DEBUGFS_FWSTATS_DEL(wep, addr_key_count);
+	DEBUGFS_FWSTATS_DEL(wep, default_key_count);
+	/* skipping wep.reserved */
+	DEBUGFS_FWSTATS_DEL(wep, key_not_found);
+	DEBUGFS_FWSTATS_DEL(wep, decrypt_fail);
+	DEBUGFS_FWSTATS_DEL(wep, packets);
+	DEBUGFS_FWSTATS_DEL(wep, interrupt);
+
+	DEBUGFS_FWSTATS_DEL(pwr, ps_enter);
+	DEBUGFS_FWSTATS_DEL(pwr, elp_enter);
+	DEBUGFS_FWSTATS_DEL(pwr, missing_bcns);
+	DEBUGFS_FWSTATS_DEL(pwr, wake_on_host);
+	DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp);
+	DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps);
+	DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps);
+	DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons);
+	DEBUGFS_FWSTATS_DEL(pwr, power_save_off);
+	DEBUGFS_FWSTATS_DEL(pwr, enable_ps);
+	DEBUGFS_FWSTATS_DEL(pwr, disable_ps);
+	DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps);
+	/* skipping cont_miss_bcns_spread for now */
+	DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons);
+
+	DEBUGFS_FWSTATS_DEL(mic, rx_pkts);
+	DEBUGFS_FWSTATS_DEL(mic, calc_failure);
+
+	DEBUGFS_FWSTATS_DEL(aes, encrypt_fail);
+	DEBUGFS_FWSTATS_DEL(aes, decrypt_fail);
+	DEBUGFS_FWSTATS_DEL(aes, encrypt_packets);
+	DEBUGFS_FWSTATS_DEL(aes, decrypt_packets);
+	DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt);
+	DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt);
+
+	DEBUGFS_FWSTATS_DEL(event, heart_beat);
+	DEBUGFS_FWSTATS_DEL(event, calibration);
+	DEBUGFS_FWSTATS_DEL(event, rx_mismatch);
+	DEBUGFS_FWSTATS_DEL(event, rx_mem_empty);
+	DEBUGFS_FWSTATS_DEL(event, rx_pool);
+	DEBUGFS_FWSTATS_DEL(event, oom_late);
+	DEBUGFS_FWSTATS_DEL(event, phy_transmit_error);
+	DEBUGFS_FWSTATS_DEL(event, tx_stuck);
+
+	DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts);
+	DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts);
+	DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime);
+	DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn);
+	DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn);
+	DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization);
+	DEBUGFS_FWSTATS_DEL(ps, upsd_utilization);
+
+	DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop);
+	DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data);
+	DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
+	DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data);
+	DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data);
+
+	DEBUGFS_DEL(tx_queue_len);
+	DEBUGFS_DEL(tx_queue_status);
+	DEBUGFS_DEL(retry_count);
+	DEBUGFS_DEL(excessive_retries);
+}
+
+static int wl1251_debugfs_add_files(struct wl1251 *wl)
+{
+	int ret = 0;
+
+	DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow);
+
+	DEBUGFS_FWSTATS_ADD(rx, out_of_mem);
+	DEBUGFS_FWSTATS_ADD(rx, hdr_overflow);
+	DEBUGFS_FWSTATS_ADD(rx, hw_stuck);
+	DEBUGFS_FWSTATS_ADD(rx, dropped);
+	DEBUGFS_FWSTATS_ADD(rx, fcs_err);
+	DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig);
+	DEBUGFS_FWSTATS_ADD(rx, path_reset);
+	DEBUGFS_FWSTATS_ADD(rx, reset_counter);
+
+	DEBUGFS_FWSTATS_ADD(dma, rx_requested);
+	DEBUGFS_FWSTATS_ADD(dma, rx_errors);
+	DEBUGFS_FWSTATS_ADD(dma, tx_requested);
+	DEBUGFS_FWSTATS_ADD(dma, tx_errors);
+
+	DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt);
+	DEBUGFS_FWSTATS_ADD(isr, fiqs);
+	DEBUGFS_FWSTATS_ADD(isr, rx_headers);
+	DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow);
+	DEBUGFS_FWSTATS_ADD(isr, rx_rdys);
+	DEBUGFS_FWSTATS_ADD(isr, irqs);
+	DEBUGFS_FWSTATS_ADD(isr, tx_procs);
+	DEBUGFS_FWSTATS_ADD(isr, decrypt_done);
+	DEBUGFS_FWSTATS_ADD(isr, dma0_done);
+	DEBUGFS_FWSTATS_ADD(isr, dma1_done);
+	DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete);
+	DEBUGFS_FWSTATS_ADD(isr, commands);
+	DEBUGFS_FWSTATS_ADD(isr, rx_procs);
+	DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes);
+	DEBUGFS_FWSTATS_ADD(isr, host_acknowledges);
+	DEBUGFS_FWSTATS_ADD(isr, pci_pm);
+	DEBUGFS_FWSTATS_ADD(isr, wakeups);
+	DEBUGFS_FWSTATS_ADD(isr, low_rssi);
+
+	DEBUGFS_FWSTATS_ADD(wep, addr_key_count);
+	DEBUGFS_FWSTATS_ADD(wep, default_key_count);
+	/* skipping wep.reserved */
+	DEBUGFS_FWSTATS_ADD(wep, key_not_found);
+	DEBUGFS_FWSTATS_ADD(wep, decrypt_fail);
+	DEBUGFS_FWSTATS_ADD(wep, packets);
+	DEBUGFS_FWSTATS_ADD(wep, interrupt);
+
+	DEBUGFS_FWSTATS_ADD(pwr, ps_enter);
+	DEBUGFS_FWSTATS_ADD(pwr, elp_enter);
+	DEBUGFS_FWSTATS_ADD(pwr, missing_bcns);
+	DEBUGFS_FWSTATS_ADD(pwr, wake_on_host);
+	DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp);
+	DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps);
+	DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps);
+	DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons);
+	DEBUGFS_FWSTATS_ADD(pwr, power_save_off);
+	DEBUGFS_FWSTATS_ADD(pwr, enable_ps);
+	DEBUGFS_FWSTATS_ADD(pwr, disable_ps);
+	DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps);
+	/* skipping cont_miss_bcns_spread for now */
+	DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons);
+
+	DEBUGFS_FWSTATS_ADD(mic, rx_pkts);
+	DEBUGFS_FWSTATS_ADD(mic, calc_failure);
+
+	DEBUGFS_FWSTATS_ADD(aes, encrypt_fail);
+	DEBUGFS_FWSTATS_ADD(aes, decrypt_fail);
+	DEBUGFS_FWSTATS_ADD(aes, encrypt_packets);
+	DEBUGFS_FWSTATS_ADD(aes, decrypt_packets);
+	DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt);
+	DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt);
+
+	DEBUGFS_FWSTATS_ADD(event, heart_beat);
+	DEBUGFS_FWSTATS_ADD(event, calibration);
+	DEBUGFS_FWSTATS_ADD(event, rx_mismatch);
+	DEBUGFS_FWSTATS_ADD(event, rx_mem_empty);
+	DEBUGFS_FWSTATS_ADD(event, rx_pool);
+	DEBUGFS_FWSTATS_ADD(event, oom_late);
+	DEBUGFS_FWSTATS_ADD(event, phy_transmit_error);
+	DEBUGFS_FWSTATS_ADD(event, tx_stuck);
+
+	DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts);
+	DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts);
+	DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime);
+	DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn);
+	DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn);
+	DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization);
+	DEBUGFS_FWSTATS_ADD(ps, upsd_utilization);
+
+	DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop);
+	DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data);
+	DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
+	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->debugfs.rootdir);
+	DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir);
+	DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
+	DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
+
+out:
+	if (ret < 0)
+		wl1251_debugfs_delete_files(wl);
+
+	return ret;
+}
+
+void wl1251_debugfs_reset(struct wl1251 *wl)
+{
+	if (wl->stats.fw_stats != NULL)
+		memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
+	wl->stats.retry_count = 0;
+	wl->stats.excessive_retries = 0;
+}
+
+int wl1251_debugfs_init(struct wl1251 *wl)
+{
+	int ret;
+
+	wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+
+	if (IS_ERR(wl->debugfs.rootdir)) {
+		ret = PTR_ERR(wl->debugfs.rootdir);
+		wl->debugfs.rootdir = NULL;
+		goto err;
+	}
+
+	wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics",
+						       wl->debugfs.rootdir);
+
+	if (IS_ERR(wl->debugfs.fw_statistics)) {
+		ret = PTR_ERR(wl->debugfs.fw_statistics);
+		wl->debugfs.fw_statistics = NULL;
+		goto err_root;
+	}
+
+	wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats),
+				      GFP_KERNEL);
+
+	if (!wl->stats.fw_stats) {
+		ret = -ENOMEM;
+		goto err_fw;
+	}
+
+	wl->stats.fw_stats_update = jiffies;
+
+	ret = wl1251_debugfs_add_files(wl);
+
+	if (ret < 0)
+		goto err_file;
+
+	return 0;
+
+err_file:
+	kfree(wl->stats.fw_stats);
+	wl->stats.fw_stats = NULL;
+
+err_fw:
+	debugfs_remove(wl->debugfs.fw_statistics);
+	wl->debugfs.fw_statistics = NULL;
+
+err_root:
+	debugfs_remove(wl->debugfs.rootdir);
+	wl->debugfs.rootdir = NULL;
+
+err:
+	return ret;
+}
+
+void wl1251_debugfs_exit(struct wl1251 *wl)
+{
+	wl1251_debugfs_delete_files(wl);
+
+	kfree(wl->stats.fw_stats);
+	wl->stats.fw_stats = NULL;
+
+	debugfs_remove(wl->debugfs.fw_statistics);
+	wl->debugfs.fw_statistics = NULL;
+
+	debugfs_remove(wl->debugfs.rootdir);
+	wl->debugfs.rootdir = NULL;
+
+}
diff --git a/drivers/net/wireless/wl1251/debugfs.h b/drivers/net/wireless/wl1251/debugfs.h
new file mode 100644
index 0000000..b3417c0
--- /dev/null
+++ b/drivers/net/wireless/wl1251/debugfs.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef WL1251_DEBUGFS_H
+#define WL1251_DEBUGFS_H
+
+#include "wl1251.h"
+
+int wl1251_debugfs_init(struct wl1251 *wl);
+void wl1251_debugfs_exit(struct wl1251 *wl);
+void wl1251_debugfs_reset(struct wl1251 *wl);
+
+#endif /* WL1251_DEBUGFS_H */
diff --git a/drivers/net/wireless/wl1251/event.c b/drivers/net/wireless/wl1251/event.c
new file mode 100644
index 0000000..712372e
--- /dev/null
+++ b/drivers/net/wireless/wl1251/event.c
@@ -0,0 +1,168 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 "wl1251.h"
+#include "reg.h"
+#include "io.h"
+#include "event.h"
+#include "ps.h"
+
+static int wl1251_event_scan_complete(struct wl1251 *wl,
+				      struct event_mailbox *mbox)
+{
+	wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d",
+		     mbox->scheduled_scan_status,
+		     mbox->scheduled_scan_channels);
+
+	if (wl->scanning) {
+		ieee80211_scan_completed(wl->hw, false);
+		wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed");
+		wl->scanning = false;
+	}
+
+	return 0;
+}
+
+static void wl1251_event_mbox_dump(struct event_mailbox *mbox)
+{
+	wl1251_debug(DEBUG_EVENT, "MBOX DUMP:");
+	wl1251_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector);
+	wl1251_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
+}
+
+static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
+{
+	int ret;
+	u32 vector;
+
+	wl1251_event_mbox_dump(mbox);
+
+	vector = mbox->events_vector & ~(mbox->events_mask);
+	wl1251_debug(DEBUG_EVENT, "vector: 0x%x", vector);
+
+	if (vector & SCAN_COMPLETE_EVENT_ID) {
+		ret = wl1251_event_scan_complete(wl, mbox);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (vector & BSS_LOSE_EVENT_ID) {
+		wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
+
+		if (wl->psm_requested && wl->psm) {
+			ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && wl->psm) {
+		wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");
+
+		/* indicate to the stack, that beacons have been lost */
+		ieee80211_beacon_loss(wl->vif);
+	}
+
+	if (vector & REGAINED_BSS_EVENT_ID) {
+		if (wl->psm_requested) {
+			ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Poll the mailbox event field until any of the bits in the mask is set or a
+ * timeout occurs (WL1251_EVENT_TIMEOUT in msecs)
+ */
+int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms)
+{
+	u32 events_vector, event;
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(timeout_ms);
+
+	do {
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+
+		msleep(1);
+
+		/* read from both event fields */
+		wl1251_mem_read(wl, wl->mbox_ptr[0], &events_vector,
+				sizeof(events_vector));
+		event = events_vector & mask;
+		wl1251_mem_read(wl, wl->mbox_ptr[1], &events_vector,
+				sizeof(events_vector));
+		event |= events_vector & mask;
+	} while (!event);
+
+	return 0;
+}
+
+int wl1251_event_unmask(struct wl1251 *wl)
+{
+	int ret;
+
+	ret = wl1251_acx_event_mbox_mask(wl, ~(wl->event_mask));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void wl1251_event_mbox_config(struct wl1251 *wl)
+{
+	wl->mbox_ptr[0] = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
+	wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
+
+	wl1251_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
+		     wl->mbox_ptr[0], wl->mbox_ptr[1]);
+}
+
+int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num)
+{
+	struct event_mailbox mbox;
+	int ret;
+
+	wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
+
+	if (mbox_num > 1)
+		return -EINVAL;
+
+	/* first we read the mbox descriptor */
+	wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
+			    sizeof(struct event_mailbox));
+
+	/* process the descriptor */
+	ret = wl1251_event_process(wl, &mbox);
+	if (ret < 0)
+		return ret;
+
+	/* then we let the firmware know it can go on...*/
+	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
+
+	return 0;
+}
diff --git a/drivers/net/wireless/wl1251/event.h b/drivers/net/wireless/wl1251/event.h
new file mode 100644
index 0000000..30eb5d1
--- /dev/null
+++ b/drivers/net/wireless/wl1251/event.h
@@ -0,0 +1,120 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 __WL1251_EVENT_H__
+#define __WL1251_EVENT_H__
+
+/*
+ * Mbox events
+ *
+ * The event mechanism is based on a pair of event buffers (buffers A and
+ * B) at fixed locations in the target's memory. The host processes one
+ * buffer while the other buffer continues to collect events. If the host
+ * is not processing events, an interrupt is issued to signal that a buffer
+ * is ready. Once the host is done with processing events from one buffer,
+ * it signals the target (with an ACK interrupt) that the event buffer is
+ * free.
+ */
+
+enum {
+	RESERVED1_EVENT_ID                       = BIT(0),
+	RESERVED2_EVENT_ID                       = BIT(1),
+	MEASUREMENT_START_EVENT_ID               = BIT(2),
+	SCAN_COMPLETE_EVENT_ID                   = BIT(3),
+	CALIBRATION_COMPLETE_EVENT_ID            = BIT(4),
+	ROAMING_TRIGGER_LOW_RSSI_EVENT_ID        = BIT(5),
+	PS_REPORT_EVENT_ID                       = BIT(6),
+	SYNCHRONIZATION_TIMEOUT_EVENT_ID         = BIT(7),
+	HEALTH_REPORT_EVENT_ID                   = BIT(8),
+	ACI_DETECTION_EVENT_ID                   = BIT(9),
+	DEBUG_REPORT_EVENT_ID                    = BIT(10),
+	MAC_STATUS_EVENT_ID                      = BIT(11),
+	DISCONNECT_EVENT_COMPLETE_ID             = BIT(12),
+	JOIN_EVENT_COMPLETE_ID                   = BIT(13),
+	CHANNEL_SWITCH_COMPLETE_EVENT_ID         = BIT(14),
+	BSS_LOSE_EVENT_ID                        = BIT(15),
+	ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID    = BIT(16),
+	MEASUREMENT_COMPLETE_EVENT_ID            = BIT(17),
+	AP_DISCOVERY_COMPLETE_EVENT_ID           = BIT(18),
+	SCHEDULED_SCAN_COMPLETE_EVENT_ID         = BIT(19),
+	PSPOLL_DELIVERY_FAILURE_EVENT_ID 	 = BIT(20),
+	RESET_BSS_EVENT_ID                       = BIT(21),
+	REGAINED_BSS_EVENT_ID                    = BIT(22),
+	ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID   = BIT(23),
+	ROAMING_TRIGGER_LOW_SNR_EVENT_ID         = BIT(24),
+	ROAMING_TRIGGER_REGAINED_SNR_EVENT_ID    = BIT(25),
+
+	DBG_EVENT_ID                             = BIT(26),
+	BT_PTA_SENSE_EVENT_ID                    = BIT(27),
+	BT_PTA_PREDICTION_EVENT_ID               = BIT(28),
+	BT_PTA_AVALANCHE_EVENT_ID                = BIT(29),
+
+	PLT_RX_CALIBRATION_COMPLETE_EVENT_ID     = BIT(30),
+
+	EVENT_MBOX_ALL_EVENT_ID                  = 0x7fffffff,
+};
+
+struct event_debug_report {
+	u8 debug_event_id;
+	u8 num_params;
+	u16 pad;
+	u32 report_1;
+	u32 report_2;
+	u32 report_3;
+} __packed;
+
+struct event_mailbox {
+	u32 events_vector;
+	u32 events_mask;
+	u32 reserved_1;
+	u32 reserved_2;
+
+	char average_rssi_level;
+	u8 ps_status;
+	u8 channel_switch_status;
+	u8 scheduled_scan_status;
+
+	/* Channels scanned by the scheduled scan */
+	u16 scheduled_scan_channels;
+
+	/* If bit 0 is set -> target's fatal error */
+	u16 health_report;
+	u16 bad_fft_counter;
+	u8 bt_pta_sense_info;
+	u8 bt_pta_protective_info;
+	u32 reserved;
+	u32 debug_report[2];
+
+	/* Number of FCS errors since last event */
+	u32 fcs_err_counter;
+
+	struct event_debug_report report;
+	u8 average_snr_level;
+	u8 padding[19];
+} __packed;
+
+int wl1251_event_unmask(struct wl1251 *wl);
+void wl1251_event_mbox_config(struct wl1251 *wl);
+int wl1251_event_handle(struct wl1251 *wl, u8 mbox);
+int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms);
+
+#endif
diff --git a/drivers/net/wireless/wl1251/init.c b/drivers/net/wireless/wl1251/init.c
new file mode 100644
index 0000000..89b43d3
--- /dev/null
+++ b/drivers/net/wireless/wl1251/init.c
@@ -0,0 +1,423 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "init.h"
+#include "wl12xx_80211.h"
+#include "acx.h"
+#include "cmd.h"
+#include "reg.h"
+
+int wl1251_hw_init_hwenc_config(struct wl1251 *wl)
+{
+	int ret;
+
+	ret = wl1251_acx_feature_cfg(wl);
+	if (ret < 0) {
+		wl1251_warning("couldn't set feature config");
+		return ret;
+	}
+
+	ret = wl1251_acx_default_key(wl, wl->default_key);
+	if (ret < 0) {
+		wl1251_warning("couldn't set default key");
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl1251_hw_init_templates_config(struct wl1251 *wl)
+{
+	int ret;
+	u8 partial_vbm[PARTIAL_VBM_MAX];
+
+	/* send empty templates for fw memory reservation */
+	ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, NULL,
+				      sizeof(struct wl12xx_probe_req_template));
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, NULL,
+				      sizeof(struct wl12xx_null_data_template));
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_cmd_template_set(wl, CMD_PS_POLL, NULL,
+				      sizeof(struct wl12xx_ps_poll_template));
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, NULL,
+				      sizeof
+				      (struct wl12xx_qos_null_data_template));
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, NULL,
+				      sizeof
+				      (struct wl12xx_probe_resp_template));
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_cmd_template_set(wl, CMD_BEACON, NULL,
+				      sizeof
+				      (struct wl12xx_beacon_template));
+	if (ret < 0)
+		return ret;
+
+	/* tim templates, first reserve space then allocate an empty one */
+	memset(partial_vbm, 0, PARTIAL_VBM_MAX);
+	ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, PARTIAL_VBM_MAX, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, 1, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter)
+{
+	int ret;
+
+	ret = wl1251_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_acx_rx_config(wl, config, filter);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int wl1251_hw_init_phy_config(struct wl1251 *wl)
+{
+	int ret;
+
+	ret = wl1251_acx_pd_threshold(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_acx_slot(wl, DEFAULT_SLOT_TIME);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_acx_group_address_tbl(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_acx_service_period_timeout(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_acx_rts_threshold(wl, RTS_THRESHOLD_DEF);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int wl1251_hw_init_beacon_filter(struct wl1251 *wl)
+{
+	int ret;
+
+	/* disable beacon filtering at this stage */
+	ret = wl1251_acx_beacon_filter_opt(wl, false);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_acx_beacon_filter_table(wl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int wl1251_hw_init_pta(struct wl1251 *wl)
+{
+	int ret;
+
+	ret = wl1251_acx_sg_enable(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_acx_sg_cfg(wl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int wl1251_hw_init_energy_detection(struct wl1251 *wl)
+{
+	int ret;
+
+	ret = wl1251_acx_cca_threshold(wl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl)
+{
+	int ret;
+
+	ret = wl1251_acx_bcn_dtim_options(wl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int wl1251_hw_init_power_auth(struct wl1251 *wl)
+{
+	return wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM);
+}
+
+int wl1251_hw_init_mem_config(struct wl1251 *wl)
+{
+	int ret;
+
+	ret = wl1251_acx_mem_cfg(wl);
+	if (ret < 0)
+		return ret;
+
+	wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map),
+					  GFP_KERNEL);
+	if (!wl->target_mem_map) {
+		wl1251_error("couldn't allocate target memory map");
+		return -ENOMEM;
+	}
+
+	/* we now ask for the firmware built memory map */
+	ret = wl1251_acx_mem_map(wl, wl->target_mem_map,
+				 sizeof(struct wl1251_acx_mem_map));
+	if (ret < 0) {
+		wl1251_error("couldn't retrieve firmware memory map");
+		kfree(wl->target_mem_map);
+		wl->target_mem_map = NULL;
+		return ret;
+	}
+
+	return 0;
+}
+
+static int wl1251_hw_init_txq_fill(u8 qid,
+				   struct acx_tx_queue_qos_config *config,
+				   u32 num_blocks)
+{
+	config->qid = qid;
+
+	switch (qid) {
+	case QOS_AC_BE:
+		config->high_threshold =
+			(QOS_TX_HIGH_BE_DEF * num_blocks) / 100;
+		config->low_threshold =
+			(QOS_TX_LOW_BE_DEF * num_blocks) / 100;
+		break;
+	case QOS_AC_BK:
+		config->high_threshold =
+			(QOS_TX_HIGH_BK_DEF * num_blocks) / 100;
+		config->low_threshold =
+			(QOS_TX_LOW_BK_DEF * num_blocks) / 100;
+		break;
+	case QOS_AC_VI:
+		config->high_threshold =
+			(QOS_TX_HIGH_VI_DEF * num_blocks) / 100;
+		config->low_threshold =
+			(QOS_TX_LOW_VI_DEF * num_blocks) / 100;
+		break;
+	case QOS_AC_VO:
+		config->high_threshold =
+			(QOS_TX_HIGH_VO_DEF * num_blocks) / 100;
+		config->low_threshold =
+			(QOS_TX_LOW_VO_DEF * num_blocks) / 100;
+		break;
+	default:
+		wl1251_error("Invalid TX queue id: %d", qid);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl)
+{
+	struct acx_tx_queue_qos_config *config;
+	struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map;
+	int ret, i;
+
+	wl1251_debug(DEBUG_ACX, "acx tx queue config");
+
+	config = kzalloc(sizeof(*config), GFP_KERNEL);
+	if (!config) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	for (i = 0; i < MAX_NUM_OF_AC; i++) {
+		ret = wl1251_hw_init_txq_fill(i, config,
+					      wl_mem_map->num_tx_mem_blocks);
+		if (ret < 0)
+			goto out;
+
+		ret = wl1251_cmd_configure(wl, ACX_TX_QUEUE_CFG,
+					   config, sizeof(*config));
+		if (ret < 0)
+			goto out;
+	}
+
+	wl1251_acx_ac_cfg(wl, AC_BE, CWMIN_BE, CWMAX_BE, AIFS_DIFS, TXOP_BE);
+	wl1251_acx_ac_cfg(wl, AC_BK, CWMIN_BK, CWMAX_BK, AIFS_DIFS, TXOP_BK);
+	wl1251_acx_ac_cfg(wl, AC_VI, CWMIN_VI, CWMAX_VI, AIFS_DIFS, TXOP_VI);
+	wl1251_acx_ac_cfg(wl, AC_VO, CWMIN_VO, CWMAX_VO, AIFS_DIFS, TXOP_VO);
+
+out:
+	kfree(config);
+	return ret;
+}
+
+static int wl1251_hw_init_data_path_config(struct wl1251 *wl)
+{
+	int ret;
+
+	/* asking for the data path parameters */
+	wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp),
+				GFP_KERNEL);
+	if (!wl->data_path) {
+		wl1251_error("Couldnt allocate data path parameters");
+		return -ENOMEM;
+	}
+
+	ret = wl1251_acx_data_path_params(wl, wl->data_path);
+	if (ret < 0) {
+		kfree(wl->data_path);
+		wl->data_path = NULL;
+		return ret;
+	}
+
+	return 0;
+}
+
+
+int wl1251_hw_init(struct wl1251 *wl)
+{
+	struct wl1251_acx_mem_map *wl_mem_map;
+	int ret;
+
+	ret = wl1251_hw_init_hwenc_config(wl);
+	if (ret < 0)
+		return ret;
+
+	/* Template settings */
+	ret = wl1251_hw_init_templates_config(wl);
+	if (ret < 0)
+		return ret;
+
+	/* Default memory configuration */
+	ret = wl1251_hw_init_mem_config(wl);
+	if (ret < 0)
+		return ret;
+
+	/* Default data path configuration  */
+	ret = wl1251_hw_init_data_path_config(wl);
+	if (ret < 0)
+		goto out_free_memmap;
+
+	/* RX config */
+	ret = wl1251_hw_init_rx_config(wl,
+				       RX_CFG_PROMISCUOUS | RX_CFG_TSF,
+				       RX_FILTER_OPTION_DEF);
+	/* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
+	   RX_FILTER_OPTION_FILTER_ALL); */
+	if (ret < 0)
+		goto out_free_data_path;
+
+	/* TX queues config */
+	ret = wl1251_hw_init_tx_queue_config(wl);
+	if (ret < 0)
+		goto out_free_data_path;
+
+	/* PHY layer config */
+	ret = wl1251_hw_init_phy_config(wl);
+	if (ret < 0)
+		goto out_free_data_path;
+
+	/* Initialize connection monitoring thresholds */
+	ret = wl1251_acx_conn_monit_params(wl);
+	if (ret < 0)
+		goto out_free_data_path;
+
+	/* Beacon filtering */
+	ret = wl1251_hw_init_beacon_filter(wl);
+	if (ret < 0)
+		goto out_free_data_path;
+
+	/* Bluetooth WLAN coexistence */
+	ret = wl1251_hw_init_pta(wl);
+	if (ret < 0)
+		goto out_free_data_path;
+
+	/* Energy detection */
+	ret = wl1251_hw_init_energy_detection(wl);
+	if (ret < 0)
+		goto out_free_data_path;
+
+	/* Beacons and boradcast settings */
+	ret = wl1251_hw_init_beacon_broadcast(wl);
+	if (ret < 0)
+		goto out_free_data_path;
+
+	/* Enable data path */
+	ret = wl1251_cmd_data_path(wl, wl->channel, 1);
+	if (ret < 0)
+		goto out_free_data_path;
+
+	/* Default power state */
+	ret = wl1251_hw_init_power_auth(wl);
+	if (ret < 0)
+		goto out_free_data_path;
+
+	wl_mem_map = wl->target_mem_map;
+	wl1251_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x",
+		    wl_mem_map->num_tx_mem_blocks,
+		    wl->data_path->tx_control_addr,
+		    wl_mem_map->num_rx_mem_blocks,
+		    wl->data_path->rx_control_addr);
+
+	return 0;
+
+ out_free_data_path:
+	kfree(wl->data_path);
+
+ out_free_memmap:
+	kfree(wl->target_mem_map);
+
+	return ret;
+}
diff --git a/drivers/net/wireless/wl1251/init.h b/drivers/net/wireless/wl1251/init.h
new file mode 100644
index 0000000..543f175
--- /dev/null
+++ b/drivers/net/wireless/wl1251/init.h
@@ -0,0 +1,86 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1251_INIT_H__
+#define __WL1251_INIT_H__
+
+#include "wl1251.h"
+
+enum {
+	/* best effort/legacy */
+	AC_BE = 0,
+
+	/* background */
+	AC_BK = 1,
+
+	/* video */
+	AC_VI = 2,
+
+	/* voice */
+	AC_VO = 3,
+
+	/* broadcast dummy access category */
+	AC_BCAST = 4,
+
+	NUM_ACCESS_CATEGORIES = 4
+};
+
+/* following are defult values for the IE fields*/
+#define CWMIN_BK  15
+#define CWMIN_BE  15
+#define CWMIN_VI  7
+#define CWMIN_VO  3
+#define CWMAX_BK  1023
+#define CWMAX_BE  63
+#define CWMAX_VI  15
+#define CWMAX_VO  7
+
+/* slot number setting to start transmission at PIFS interval */
+#define AIFS_PIFS 1
+
+/*
+ * slot number setting to start transmission at DIFS interval - normal DCF
+ * access
+ */
+#define AIFS_DIFS 2
+
+#define AIFSN_BK  7
+#define AIFSN_BE  3
+#define AIFSN_VI  AIFS_PIFS
+#define AIFSN_VO  AIFS_PIFS
+#define TXOP_BK   0
+#define TXOP_BE   0
+#define TXOP_VI   3008
+#define TXOP_VO   1504
+
+int wl1251_hw_init_hwenc_config(struct wl1251 *wl);
+int wl1251_hw_init_templates_config(struct wl1251 *wl);
+int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter);
+int wl1251_hw_init_phy_config(struct wl1251 *wl);
+int wl1251_hw_init_beacon_filter(struct wl1251 *wl);
+int wl1251_hw_init_pta(struct wl1251 *wl);
+int wl1251_hw_init_energy_detection(struct wl1251 *wl);
+int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl);
+int wl1251_hw_init_power_auth(struct wl1251 *wl);
+int wl1251_hw_init_mem_config(struct wl1251 *wl);
+int wl1251_hw_init(struct wl1251 *wl);
+
+#endif
diff --git a/drivers/net/wireless/wl1251/io.c b/drivers/net/wireless/wl1251/io.c
new file mode 100644
index 0000000..cdcadbf
--- /dev/null
+++ b/drivers/net/wireless/wl1251/io.c
@@ -0,0 +1,194 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 "wl1251.h"
+#include "reg.h"
+#include "io.h"
+
+/* FIXME: this is static data nowadays and the table can be removed */
+static enum wl12xx_acx_int_reg wl1251_io_reg_table[ACX_REG_TABLE_LEN] = {
+	[ACX_REG_INTERRUPT_TRIG]     = (REGISTERS_BASE + 0x0474),
+	[ACX_REG_INTERRUPT_TRIG_H]   = (REGISTERS_BASE + 0x0478),
+	[ACX_REG_INTERRUPT_MASK]     = (REGISTERS_BASE + 0x0494),
+	[ACX_REG_HINT_MASK_SET]      = (REGISTERS_BASE + 0x0498),
+	[ACX_REG_HINT_MASK_CLR]      = (REGISTERS_BASE + 0x049C),
+	[ACX_REG_INTERRUPT_NO_CLEAR] = (REGISTERS_BASE + 0x04B0),
+	[ACX_REG_INTERRUPT_CLEAR]    = (REGISTERS_BASE + 0x04A4),
+	[ACX_REG_INTERRUPT_ACK]      = (REGISTERS_BASE + 0x04A8),
+	[ACX_REG_SLV_SOFT_RESET]     = (REGISTERS_BASE + 0x0000),
+	[ACX_REG_EE_START]           = (REGISTERS_BASE + 0x080C),
+	[ACX_REG_ECPU_CONTROL]       = (REGISTERS_BASE + 0x0804)
+};
+
+static int wl1251_translate_reg_addr(struct wl1251 *wl, int addr)
+{
+	/* If the address is lower than REGISTERS_BASE, it means that this is
+	 * a chip-specific register address, so look it up in the registers
+	 * table */
+	if (addr < REGISTERS_BASE) {
+		/* Make sure we don't go over the table */
+		if (addr >= ACX_REG_TABLE_LEN) {
+			wl1251_error("address out of range (%d)", addr);
+			return -EINVAL;
+		}
+		addr = wl1251_io_reg_table[addr];
+	}
+
+	return addr - wl->physical_reg_addr + wl->virtual_reg_addr;
+}
+
+static int wl1251_translate_mem_addr(struct wl1251 *wl, int addr)
+{
+	return addr - wl->physical_mem_addr + wl->virtual_mem_addr;
+}
+
+void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len)
+{
+	int physical;
+
+	physical = wl1251_translate_mem_addr(wl, addr);
+
+	wl->if_ops->read(wl, physical, buf, len);
+}
+
+void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len)
+{
+	int physical;
+
+	physical = wl1251_translate_mem_addr(wl, addr);
+
+	wl->if_ops->write(wl, physical, buf, len);
+}
+
+u32 wl1251_mem_read32(struct wl1251 *wl, int addr)
+{
+	return wl1251_read32(wl, wl1251_translate_mem_addr(wl, addr));
+}
+
+void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val)
+{
+	wl1251_write32(wl, wl1251_translate_mem_addr(wl, addr), val);
+}
+
+u32 wl1251_reg_read32(struct wl1251 *wl, int addr)
+{
+	return wl1251_read32(wl, wl1251_translate_reg_addr(wl, addr));
+}
+
+void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val)
+{
+	wl1251_write32(wl, wl1251_translate_reg_addr(wl, addr), val);
+}
+
+/* Set the partitions to access the chip addresses.
+ *
+ * There are two VIRTUAL partitions (the memory partition and the
+ * registers partition), which are mapped to two different areas of the
+ * PHYSICAL (hardware) memory.  This function also makes other checks to
+ * ensure that the partitions are not overlapping.  In the diagram below, the
+ * memory partition comes before the register partition, but the opposite is
+ * also supported.
+ *
+ *                               PHYSICAL address
+ *                                     space
+ *
+ *                                    |    |
+ *                                 ...+----+--> mem_start
+ *          VIRTUAL address     ...   |    |
+ *               space       ...      |    | [PART_0]
+ *                        ...         |    |
+ * 0x00000000 <--+----+...         ...+----+--> mem_start + mem_size
+ *               |    |         ...   |    |
+ *               |MEM |      ...      |    |
+ *               |    |   ...         |    |
+ *  part_size <--+----+...            |    | {unused area)
+ *               |    |   ...         |    |
+ *               |REG |      ...      |    |
+ *  part_size    |    |         ...   |    |
+ *      +     <--+----+...         ...+----+--> reg_start
+ *  reg_size              ...         |    |
+ *                           ...      |    | [PART_1]
+ *                              ...   |    |
+ *                                 ...+----+--> reg_start + reg_size
+ *                                    |    |
+ *
+ */
+void wl1251_set_partition(struct wl1251 *wl,
+			  u32 mem_start, u32 mem_size,
+			  u32 reg_start, u32 reg_size)
+{
+	struct wl1251_partition partition[2];
+
+	wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+		     mem_start, mem_size);
+	wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+		     reg_start, reg_size);
+
+	/* Make sure that the two partitions together don't exceed the
+	 * address range */
+	if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) {
+		wl1251_debug(DEBUG_SPI, "Total size exceeds maximum virtual"
+			     " address range.  Truncating partition[0].");
+		mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size;
+		wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+			     mem_start, mem_size);
+		wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+			     reg_start, reg_size);
+	}
+
+	if ((mem_start < reg_start) &&
+	    ((mem_start + mem_size) > reg_start)) {
+		/* Guarantee that the memory partition doesn't overlap the
+		 * registers partition */
+		wl1251_debug(DEBUG_SPI, "End of partition[0] is "
+			     "overlapping partition[1].  Adjusted.");
+		mem_size = reg_start - mem_start;
+		wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+			     mem_start, mem_size);
+		wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+			     reg_start, reg_size);
+	} else if ((reg_start < mem_start) &&
+		   ((reg_start + reg_size) > mem_start)) {
+		/* Guarantee that the register partition doesn't overlap the
+		 * memory partition */
+		wl1251_debug(DEBUG_SPI, "End of partition[1] is"
+			     " overlapping partition[0].  Adjusted.");
+		reg_size = mem_start - reg_start;
+		wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+			     mem_start, mem_size);
+		wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+			     reg_start, reg_size);
+	}
+
+	partition[0].start = mem_start;
+	partition[0].size  = mem_size;
+	partition[1].start = reg_start;
+	partition[1].size  = reg_size;
+
+	wl->physical_mem_addr = mem_start;
+	wl->physical_reg_addr = reg_start;
+
+	wl->virtual_mem_addr = 0;
+	wl->virtual_reg_addr = mem_size;
+
+	wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition,
+		sizeof(partition));
+}
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl1251/io.h
similarity index 100%
rename from drivers/net/wireless/wl12xx/wl1251_io.h
rename to drivers/net/wireless/wl1251/io.h
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c
new file mode 100644
index 0000000..7a87625
--- /dev/null
+++ b/drivers/net/wireless/wl1251/main.c
@@ -0,0 +1,1435 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/crc32.h>
+#include <linux/etherdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+
+#include "wl1251.h"
+#include "wl12xx_80211.h"
+#include "reg.h"
+#include "io.h"
+#include "cmd.h"
+#include "event.h"
+#include "tx.h"
+#include "rx.h"
+#include "ps.h"
+#include "init.h"
+#include "debugfs.h"
+#include "boot.h"
+
+void wl1251_enable_interrupts(struct wl1251 *wl)
+{
+	wl->if_ops->enable_irq(wl);
+}
+
+void wl1251_disable_interrupts(struct wl1251 *wl)
+{
+	wl->if_ops->disable_irq(wl);
+}
+
+static void wl1251_power_off(struct wl1251 *wl)
+{
+	wl->set_power(false);
+}
+
+static void wl1251_power_on(struct wl1251 *wl)
+{
+	wl->set_power(true);
+}
+
+static int wl1251_fetch_firmware(struct wl1251 *wl)
+{
+	const struct firmware *fw;
+	struct device *dev = wiphy_dev(wl->hw->wiphy);
+	int ret;
+
+	ret = request_firmware(&fw, WL1251_FW_NAME, dev);
+
+	if (ret < 0) {
+		wl1251_error("could not get firmware: %d", ret);
+		return ret;
+	}
+
+	if (fw->size % 4) {
+		wl1251_error("firmware size is not multiple of 32 bits: %zu",
+			     fw->size);
+		ret = -EILSEQ;
+		goto out;
+	}
+
+	wl->fw_len = fw->size;
+	wl->fw = vmalloc(wl->fw_len);
+
+	if (!wl->fw) {
+		wl1251_error("could not allocate memory for the firmware");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memcpy(wl->fw, fw->data, wl->fw_len);
+
+	ret = 0;
+
+out:
+	release_firmware(fw);
+
+	return ret;
+}
+
+static int wl1251_fetch_nvs(struct wl1251 *wl)
+{
+	const struct firmware *fw;
+	struct device *dev = wiphy_dev(wl->hw->wiphy);
+	int ret;
+
+	ret = request_firmware(&fw, WL1251_NVS_NAME, dev);
+
+	if (ret < 0) {
+		wl1251_error("could not get nvs file: %d", ret);
+		return ret;
+	}
+
+	if (fw->size % 4) {
+		wl1251_error("nvs size is not multiple of 32 bits: %zu",
+			     fw->size);
+		ret = -EILSEQ;
+		goto out;
+	}
+
+	wl->nvs_len = fw->size;
+	wl->nvs = kmemdup(fw->data, wl->nvs_len, GFP_KERNEL);
+
+	if (!wl->nvs) {
+		wl1251_error("could not allocate memory for the nvs file");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	release_firmware(fw);
+
+	return ret;
+}
+
+static void wl1251_fw_wakeup(struct wl1251 *wl)
+{
+	u32 elp_reg;
+
+	elp_reg = ELPCTRL_WAKE_UP;
+	wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
+	elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
+
+	if (!(elp_reg & ELPCTRL_WLAN_READY))
+		wl1251_warning("WLAN not ready");
+}
+
+static int wl1251_chip_wakeup(struct wl1251 *wl)
+{
+	int ret = 0;
+
+	wl1251_power_on(wl);
+	msleep(WL1251_POWER_ON_SLEEP);
+	wl->if_ops->reset(wl);
+
+	/* We don't need a real memory partition here, because we only want
+	 * to use the registers at this point. */
+	wl1251_set_partition(wl,
+			     0x00000000,
+			     0x00000000,
+			     REGISTERS_BASE,
+			     REGISTERS_DOWN_SIZE);
+
+	/* ELP module wake up */
+	wl1251_fw_wakeup(wl);
+
+	/* whal_FwCtrl_BootSm() */
+
+	/* 0. read chip id from CHIP_ID */
+	wl->chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
+
+	/* 1. check if chip id is valid */
+
+	switch (wl->chip_id) {
+	case CHIP_ID_1251_PG12:
+		wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)",
+			     wl->chip_id);
+		break;
+	case CHIP_ID_1251_PG11:
+		wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG11)",
+			     wl->chip_id);
+		break;
+	case CHIP_ID_1251_PG10:
+	default:
+		wl1251_error("unsupported chip id: 0x%x", wl->chip_id);
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (wl->fw == NULL) {
+		ret = wl1251_fetch_firmware(wl);
+		if (ret < 0)
+			goto out;
+	}
+
+	if (wl->nvs == NULL && !wl->use_eeprom) {
+		/* No NVS from netlink, try to get it from the filesystem */
+		ret = wl1251_fetch_nvs(wl);
+		if (ret < 0)
+			goto out;
+	}
+
+out:
+	return ret;
+}
+
+#define WL1251_IRQ_LOOP_COUNT 10
+static void wl1251_irq_work(struct work_struct *work)
+{
+	u32 intr, ctr = WL1251_IRQ_LOOP_COUNT;
+	struct wl1251 *wl =
+		container_of(work, struct wl1251, irq_work);
+	int ret;
+
+	mutex_lock(&wl->mutex);
+
+	wl1251_debug(DEBUG_IRQ, "IRQ work");
+
+	if (wl->state == WL1251_STATE_OFF)
+		goto out;
+
+	ret = wl1251_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL);
+
+	intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
+	wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr);
+
+	do {
+		if (wl->data_path) {
+			wl->rx_counter = wl1251_mem_read32(
+				wl, wl->data_path->rx_control_addr);
+
+			/* We handle a frmware bug here */
+			switch ((wl->rx_counter - wl->rx_handled) & 0xf) {
+			case 0:
+				wl1251_debug(DEBUG_IRQ,
+					     "RX: FW and host in sync");
+				intr &= ~WL1251_ACX_INTR_RX0_DATA;
+				intr &= ~WL1251_ACX_INTR_RX1_DATA;
+				break;
+			case 1:
+				wl1251_debug(DEBUG_IRQ, "RX: FW +1");
+				intr |= WL1251_ACX_INTR_RX0_DATA;
+				intr &= ~WL1251_ACX_INTR_RX1_DATA;
+				break;
+			case 2:
+				wl1251_debug(DEBUG_IRQ, "RX: FW +2");
+				intr |= WL1251_ACX_INTR_RX0_DATA;
+				intr |= WL1251_ACX_INTR_RX1_DATA;
+				break;
+			default:
+				wl1251_warning(
+					"RX: FW and host out of sync: %d",
+					wl->rx_counter - wl->rx_handled);
+				break;
+			}
+
+			wl->rx_handled = wl->rx_counter;
+
+			wl1251_debug(DEBUG_IRQ, "RX counter: %d",
+				     wl->rx_counter);
+		}
+
+		intr &= wl->intr_mask;
+
+		if (intr == 0) {
+			wl1251_debug(DEBUG_IRQ, "INTR is 0");
+			goto out_sleep;
+		}
+
+		if (intr & WL1251_ACX_INTR_RX0_DATA) {
+			wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA");
+			wl1251_rx(wl);
+		}
+
+		if (intr & WL1251_ACX_INTR_RX1_DATA) {
+			wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA");
+			wl1251_rx(wl);
+		}
+
+		if (intr & WL1251_ACX_INTR_TX_RESULT) {
+			wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT");
+			wl1251_tx_complete(wl);
+		}
+
+		if (intr & WL1251_ACX_INTR_EVENT_A) {
+			wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_A");
+			wl1251_event_handle(wl, 0);
+		}
+
+		if (intr & WL1251_ACX_INTR_EVENT_B) {
+			wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_B");
+			wl1251_event_handle(wl, 1);
+		}
+
+		if (intr & WL1251_ACX_INTR_INIT_COMPLETE)
+			wl1251_debug(DEBUG_IRQ,
+				     "WL1251_ACX_INTR_INIT_COMPLETE");
+
+		if (--ctr == 0)
+			break;
+
+		intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
+	} while (intr);
+
+out_sleep:
+	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
+	wl1251_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+}
+
+static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel,
+		       u16 beacon_interval, u8 dtim_period)
+{
+	int ret;
+
+	ret = wl1251_acx_frame_rates(wl, DEFAULT_HW_GEN_TX_RATE,
+				     DEFAULT_HW_GEN_MODULATION_TYPE,
+				     wl->tx_mgmt_frm_rate,
+				     wl->tx_mgmt_frm_mod);
+	if (ret < 0)
+		goto out;
+
+
+	ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval,
+			      dtim_period);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1251_event_wait(wl, JOIN_EVENT_COMPLETE_ID, 100);
+	if (ret < 0)
+		wl1251_warning("join timeout");
+
+out:
+	return ret;
+}
+
+static void wl1251_filter_work(struct work_struct *work)
+{
+	struct wl1251 *wl =
+		container_of(work, struct wl1251, filter_work);
+	int ret;
+
+	mutex_lock(&wl->mutex);
+
+	if (wl->state == WL1251_STATE_OFF)
+		goto out;
+
+	ret = wl1251_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int,
+			  wl->dtim_period);
+	if (ret < 0)
+		goto out_sleep;
+
+out_sleep:
+	wl1251_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+}
+
+static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct wl1251 *wl = hw->priv;
+	unsigned long flags;
+
+	skb_queue_tail(&wl->tx_queue, skb);
+
+	/*
+	 * The chip specific setup must run before the first TX packet -
+	 * before that, the tx_work will not be initialized!
+	 */
+
+	ieee80211_queue_work(wl->hw, &wl->tx_work);
+
+	/*
+	 * The workqueue is slow to process the tx_queue and we need stop
+	 * the queue here, otherwise the queue will get too long.
+	 */
+	if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_HIGH_WATERMARK) {
+		wl1251_debug(DEBUG_TX, "op_tx: tx_queue full, stop queues");
+
+		spin_lock_irqsave(&wl->wl_lock, flags);
+		ieee80211_stop_queues(wl->hw);
+		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)
+{
+	struct wl1251 *wl = hw->priv;
+	struct wiphy *wiphy = hw->wiphy;
+	int ret = 0;
+
+	wl1251_debug(DEBUG_MAC80211, "mac80211 start");
+
+	mutex_lock(&wl->mutex);
+
+	if (wl->state != WL1251_STATE_OFF) {
+		wl1251_error("cannot start because not in off state: %d",
+			     wl->state);
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ret = wl1251_chip_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1251_boot(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1251_hw_init(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1251_acx_station_id(wl);
+	if (ret < 0)
+		goto out;
+
+	wl->state = WL1251_STATE_ON;
+
+	wl1251_info("firmware booted (%s)", wl->fw_ver);
+
+	/* update hw/fw version info in wiphy struct */
+	wiphy->hw_version = wl->chip_id;
+	strncpy(wiphy->fw_version, wl->fw_ver, sizeof(wiphy->fw_version));
+
+out:
+	if (ret < 0)
+		wl1251_power_off(wl);
+
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
+static void wl1251_op_stop(struct ieee80211_hw *hw)
+{
+	struct wl1251 *wl = hw->priv;
+
+	wl1251_info("down");
+
+	wl1251_debug(DEBUG_MAC80211, "mac80211 stop");
+
+	mutex_lock(&wl->mutex);
+
+	WARN_ON(wl->state != WL1251_STATE_ON);
+
+	if (wl->scanning) {
+		ieee80211_scan_completed(wl->hw, true);
+		wl->scanning = false;
+	}
+
+	wl->state = WL1251_STATE_OFF;
+
+	wl1251_disable_interrupts(wl);
+
+	mutex_unlock(&wl->mutex);
+
+	cancel_work_sync(&wl->irq_work);
+	cancel_work_sync(&wl->tx_work);
+	cancel_work_sync(&wl->filter_work);
+
+	mutex_lock(&wl->mutex);
+
+	/* let's notify MAC80211 about the remaining pending TX frames */
+	wl1251_tx_flush(wl);
+	wl1251_power_off(wl);
+
+	memset(wl->bssid, 0, ETH_ALEN);
+	wl->listen_int = 1;
+	wl->bss_type = MAX_BSS_TYPE;
+
+	wl->data_in_count = 0;
+	wl->rx_counter = 0;
+	wl->rx_handled = 0;
+	wl->rx_current_buffer = 0;
+	wl->rx_last_id = 0;
+	wl->next_tx_complete = 0;
+	wl->elp = false;
+	wl->psm = 0;
+	wl->tx_queue_stopped = false;
+	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
+	wl->channel = WL1251_DEFAULT_CHANNEL;
+
+	wl1251_debugfs_reset(wl);
+
+	mutex_unlock(&wl->mutex);
+}
+
+static int wl1251_op_add_interface(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif)
+{
+	struct wl1251 *wl = hw->priv;
+	int ret = 0;
+
+	wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
+		     vif->type, vif->addr);
+
+	mutex_lock(&wl->mutex);
+	if (wl->vif) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	wl->vif = vif;
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		wl->bss_type = BSS_TYPE_STA_BSS;
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		wl->bss_type = BSS_TYPE_IBSS;
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) {
+		memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
+		SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
+		ret = wl1251_acx_station_id(wl);
+		if (ret < 0)
+			goto out;
+	}
+
+out:
+	mutex_unlock(&wl->mutex);
+	return ret;
+}
+
+static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
+					 struct ieee80211_vif *vif)
+{
+	struct wl1251 *wl = hw->priv;
+
+	mutex_lock(&wl->mutex);
+	wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface");
+	wl->vif = NULL;
+	mutex_unlock(&wl->mutex);
+}
+
+static int wl1251_build_qos_null_data(struct wl1251 *wl)
+{
+	struct ieee80211_qos_hdr template;
+
+	memset(&template, 0, sizeof(template));
+
+	memcpy(template.addr1, wl->bssid, ETH_ALEN);
+	memcpy(template.addr2, wl->mac_addr, ETH_ALEN);
+	memcpy(template.addr3, wl->bssid, ETH_ALEN);
+
+	template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+					     IEEE80211_STYPE_QOS_NULLFUNC |
+					     IEEE80211_FCTL_TODS);
+
+	/* FIXME: not sure what priority to use here */
+	template.qos_ctrl = cpu_to_le16(0);
+
+	return wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, &template,
+				       sizeof(template));
+}
+
+static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct wl1251 *wl = hw->priv;
+	struct ieee80211_conf *conf = &hw->conf;
+	int channel, ret = 0;
+
+	channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+
+	wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
+		     channel,
+		     conf->flags & IEEE80211_CONF_PS ? "on" : "off",
+		     conf->power_level);
+
+	mutex_lock(&wl->mutex);
+
+	ret = wl1251_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	if (channel != wl->channel) {
+		wl->channel = channel;
+
+		ret = wl1251_join(wl, wl->bss_type, wl->channel,
+				  wl->beacon_int, wl->dtim_period);
+		if (ret < 0)
+			goto out_sleep;
+	}
+
+	if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
+		wl1251_debug(DEBUG_PSM, "psm enabled");
+
+		wl->psm_requested = true;
+
+		wl->dtim_period = conf->ps_dtim_period;
+
+		ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int,
+						  wl->dtim_period);
+
+		/*
+		 * mac80211 enables PSM only if we're already associated.
+		 */
+		ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
+		if (ret < 0)
+			goto out_sleep;
+	} else if (!(conf->flags & IEEE80211_CONF_PS) &&
+		   wl->psm_requested) {
+		wl1251_debug(DEBUG_PSM, "psm disabled");
+
+		wl->psm_requested = false;
+
+		if (wl->psm) {
+			ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
+			if (ret < 0)
+				goto out_sleep;
+		}
+	}
+
+	if (conf->power_level != wl->power_level) {
+		ret = wl1251_acx_tx_power(wl, conf->power_level);
+		if (ret < 0)
+			goto out_sleep;
+
+		wl->power_level = conf->power_level;
+	}
+
+out_sleep:
+	wl1251_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
+#define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
+				  FIF_ALLMULTI | \
+				  FIF_FCSFAIL | \
+				  FIF_BCN_PRBRESP_PROMISC | \
+				  FIF_CONTROL | \
+				  FIF_OTHER_BSS)
+
+static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
+				       unsigned int changed,
+				       unsigned int *total,u64 multicast)
+{
+	struct wl1251 *wl = hw->priv;
+
+	wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter");
+
+	*total &= WL1251_SUPPORTED_FILTERS;
+	changed &= WL1251_SUPPORTED_FILTERS;
+
+	if (changed == 0)
+		/* no filters which we support changed */
+		return;
+
+	/* FIXME: wl->rx_config and wl->rx_filter are not protected */
+
+	wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
+	wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
+
+	if (*total & FIF_PROMISC_IN_BSS) {
+		wl->rx_config |= CFG_BSSID_FILTER_EN;
+		wl->rx_config |= CFG_RX_ALL_GOOD;
+	}
+	if (*total & FIF_ALLMULTI)
+		/*
+		 * CFG_MC_FILTER_EN in rx_config needs to be 0 to receive
+		 * all multicast frames
+		 */
+		wl->rx_config &= ~CFG_MC_FILTER_EN;
+	if (*total & FIF_FCSFAIL)
+		wl->rx_filter |= CFG_RX_FCS_ERROR;
+	if (*total & FIF_BCN_PRBRESP_PROMISC) {
+		wl->rx_config &= ~CFG_BSSID_FILTER_EN;
+		wl->rx_config &= ~CFG_SSID_FILTER_EN;
+	}
+	if (*total & FIF_CONTROL)
+		wl->rx_filter |= CFG_RX_CTL_EN;
+	if (*total & FIF_OTHER_BSS)
+		wl->rx_filter &= ~CFG_BSSID_FILTER_EN;
+
+	/*
+	 * FIXME: workqueues need to be properly cancelled on stop(), for
+	 * now let's just disable changing the filter settings. They will
+	 * be updated any on config().
+	 */
+	/* schedule_work(&wl->filter_work); */
+}
+
+/* HW encryption */
+static int wl1251_set_key_type(struct wl1251 *wl,
+			       struct wl1251_cmd_set_keys *key,
+			       enum set_key_cmd cmd,
+			       struct ieee80211_key_conf *mac80211_key,
+			       const u8 *addr)
+{
+	switch (mac80211_key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		if (is_broadcast_ether_addr(addr))
+			key->key_type = KEY_WEP_DEFAULT;
+		else
+			key->key_type = KEY_WEP_ADDR;
+
+		mac80211_key->hw_key_idx = mac80211_key->keyidx;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		if (is_broadcast_ether_addr(addr))
+			key->key_type = KEY_TKIP_MIC_GROUP;
+		else
+			key->key_type = KEY_TKIP_MIC_PAIRWISE;
+
+		mac80211_key->hw_key_idx = mac80211_key->keyidx;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		if (is_broadcast_ether_addr(addr))
+			key->key_type = KEY_AES_GROUP;
+		else
+			key->key_type = KEY_AES_PAIRWISE;
+		mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+		break;
+	default:
+		wl1251_error("Unknown key cipher 0x%x", mac80211_key->cipher);
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int wl1251_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)
+{
+	struct wl1251 *wl = hw->priv;
+	struct wl1251_cmd_set_keys *wl_cmd;
+	const u8 *addr;
+	int ret;
+
+	static const u8 bcast_addr[ETH_ALEN] =
+		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+	wl1251_debug(DEBUG_MAC80211, "mac80211 set key");
+
+	wl_cmd = kzalloc(sizeof(*wl_cmd), GFP_KERNEL);
+	if (!wl_cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	addr = sta ? sta->addr : bcast_addr;
+
+	wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
+	wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
+	wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
+		     key->cipher, key->keyidx, key->keylen, key->flags);
+	wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen);
+
+	if (is_zero_ether_addr(addr)) {
+		/* We dont support TX only encryption */
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	mutex_lock(&wl->mutex);
+
+	ret = wl1251_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out_unlock;
+
+	switch (cmd) {
+	case SET_KEY:
+		wl_cmd->key_action = KEY_ADD_OR_REPLACE;
+		break;
+	case DISABLE_KEY:
+		wl_cmd->key_action = KEY_REMOVE;
+		break;
+	default:
+		wl1251_error("Unsupported key cmd 0x%x", cmd);
+		break;
+	}
+
+	ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr);
+	if (ret < 0) {
+		wl1251_error("Set KEY type failed");
+		goto out_sleep;
+	}
+
+	if (wl_cmd->key_type != KEY_WEP_DEFAULT)
+		memcpy(wl_cmd->addr, addr, ETH_ALEN);
+
+	if ((wl_cmd->key_type == KEY_TKIP_MIC_GROUP) ||
+	    (wl_cmd->key_type == KEY_TKIP_MIC_PAIRWISE)) {
+		/*
+		 * 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(wl_cmd->key, key->key, 16);
+		memcpy(wl_cmd->key + 16, key->key + 24, 8);
+		memcpy(wl_cmd->key + 24, key->key + 16, 8);
+
+	} else {
+		memcpy(wl_cmd->key, key->key, key->keylen);
+	}
+	wl_cmd->key_size = key->keylen;
+
+	wl_cmd->id = key->keyidx;
+	wl_cmd->ssid_profile = 0;
+
+	wl1251_dump(DEBUG_CRYPT, "TARGET KEY: ", wl_cmd, sizeof(*wl_cmd));
+
+	ret = wl1251_cmd_send(wl, CMD_SET_KEYS, wl_cmd, sizeof(*wl_cmd));
+	if (ret < 0) {
+		wl1251_warning("could not set keys");
+		goto out_sleep;
+	}
+
+out_sleep:
+	wl1251_ps_elp_sleep(wl);
+
+out_unlock:
+	mutex_unlock(&wl->mutex);
+
+out:
+	kfree(wl_cmd);
+
+	return ret;
+}
+
+static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     struct cfg80211_scan_request *req)
+{
+	struct wl1251 *wl = hw->priv;
+	struct sk_buff *skb;
+	size_t ssid_len = 0;
+	u8 *ssid = NULL;
+	int ret;
+
+	wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan");
+
+	if (req->n_ssids) {
+		ssid = req->ssids[0].ssid;
+		ssid_len = req->ssids[0].ssid_len;
+	}
+
+	mutex_lock(&wl->mutex);
+
+	if (wl->scanning) {
+		wl1251_debug(DEBUG_SCAN, "scan already in progress");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = wl1251_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
+				     req->ie, req->ie_len);
+	if (!skb) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data,
+				      skb->len);
+	dev_kfree_skb(skb);
+	if (ret < 0)
+		goto out_sleep;
+
+	ret = wl1251_cmd_trigger_scan_to(wl, 0);
+	if (ret < 0)
+		goto out_sleep;
+
+	wl->scanning = true;
+
+	ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels,
+			      req->n_channels, WL1251_SCAN_NUM_PROBES);
+	if (ret < 0) {
+		wl->scanning = false;
+		goto out_sleep;
+	}
+
+out_sleep:
+	wl1251_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
+static int wl1251_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+	struct wl1251 *wl = hw->priv;
+	int ret;
+
+	mutex_lock(&wl->mutex);
+
+	ret = wl1251_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1251_acx_rts_threshold(wl, (u16) value);
+	if (ret < 0)
+		wl1251_warning("wl1251_op_set_rts_threshold failed: %d", ret);
+
+	wl1251_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
+static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_bss_conf *bss_conf,
+				       u32 changed)
+{
+	struct wl1251 *wl = hw->priv;
+	struct sk_buff *beacon, *skb;
+	int ret;
+
+	wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed");
+
+	mutex_lock(&wl->mutex);
+
+	ret = wl1251_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	if (changed & BSS_CHANGED_BSSID) {
+		memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
+
+		skb = ieee80211_nullfunc_get(wl->hw, wl->vif);
+		if (!skb)
+			goto out_sleep;
+
+		ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA,
+					      skb->data, skb->len);
+		dev_kfree_skb(skb);
+		if (ret < 0)
+			goto out_sleep;
+
+		ret = wl1251_build_qos_null_data(wl);
+		if (ret < 0)
+			goto out;
+
+		if (wl->bss_type != BSS_TYPE_IBSS) {
+			ret = wl1251_join(wl, wl->bss_type, wl->channel,
+					  wl->beacon_int, wl->dtim_period);
+			if (ret < 0)
+				goto out_sleep;
+		}
+	}
+
+	if (changed & BSS_CHANGED_ASSOC) {
+		if (bss_conf->assoc) {
+			wl->beacon_int = bss_conf->beacon_int;
+
+			skb = ieee80211_pspoll_get(wl->hw, wl->vif);
+			if (!skb)
+				goto out_sleep;
+
+			ret = wl1251_cmd_template_set(wl, CMD_PS_POLL,
+						      skb->data,
+						      skb->len);
+			dev_kfree_skb(skb);
+			if (ret < 0)
+				goto out_sleep;
+
+			ret = wl1251_acx_aid(wl, bss_conf->aid);
+			if (ret < 0)
+				goto out_sleep;
+		} else {
+			/* use defaults when not associated */
+			wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
+			wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
+		}
+	}
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		if (bss_conf->use_short_slot)
+			ret = wl1251_acx_slot(wl, SLOT_TIME_SHORT);
+		else
+			ret = wl1251_acx_slot(wl, SLOT_TIME_LONG);
+		if (ret < 0) {
+			wl1251_warning("Set slot time failed %d", ret);
+			goto out_sleep;
+		}
+	}
+
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		if (bss_conf->use_short_preamble)
+			wl1251_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
+		else
+			wl1251_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
+	}
+
+	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
+		if (bss_conf->use_cts_prot)
+			ret = wl1251_acx_cts_protect(wl, CTSPROTECT_ENABLE);
+		else
+			ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE);
+		if (ret < 0) {
+			wl1251_warning("Set ctsprotect failed %d", ret);
+			goto out_sleep;
+		}
+	}
+
+	if (changed & BSS_CHANGED_BEACON) {
+		beacon = ieee80211_beacon_get(hw, vif);
+		ret = wl1251_cmd_template_set(wl, CMD_BEACON, beacon->data,
+					      beacon->len);
+
+		if (ret < 0) {
+			dev_kfree_skb(beacon);
+			goto out_sleep;
+		}
+
+		ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data,
+					      beacon->len);
+
+		dev_kfree_skb(beacon);
+
+		if (ret < 0)
+			goto out_sleep;
+
+		ret = wl1251_join(wl, wl->bss_type, wl->beacon_int,
+				  wl->channel, wl->dtim_period);
+
+		if (ret < 0)
+			goto out_sleep;
+	}
+
+out_sleep:
+	wl1251_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+}
+
+
+/* can't be const, mac80211 writes to this */
+static struct ieee80211_rate wl1251_rates[] = {
+	{ .bitrate = 10,
+	  .hw_value = 0x1,
+	  .hw_value_short = 0x1, },
+	{ .bitrate = 20,
+	  .hw_value = 0x2,
+	  .hw_value_short = 0x2,
+	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 55,
+	  .hw_value = 0x4,
+	  .hw_value_short = 0x4,
+	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 110,
+	  .hw_value = 0x20,
+	  .hw_value_short = 0x20,
+	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 60,
+	  .hw_value = 0x8,
+	  .hw_value_short = 0x8, },
+	{ .bitrate = 90,
+	  .hw_value = 0x10,
+	  .hw_value_short = 0x10, },
+	{ .bitrate = 120,
+	  .hw_value = 0x40,
+	  .hw_value_short = 0x40, },
+	{ .bitrate = 180,
+	  .hw_value = 0x80,
+	  .hw_value_short = 0x80, },
+	{ .bitrate = 240,
+	  .hw_value = 0x200,
+	  .hw_value_short = 0x200, },
+	{ .bitrate = 360,
+	 .hw_value = 0x400,
+	 .hw_value_short = 0x400, },
+	{ .bitrate = 480,
+	  .hw_value = 0x800,
+	  .hw_value_short = 0x800, },
+	{ .bitrate = 540,
+	  .hw_value = 0x1000,
+	  .hw_value_short = 0x1000, },
+};
+
+/* can't be const, mac80211 writes to this */
+static struct ieee80211_channel wl1251_channels[] = {
+	{ .hw_value = 1, .center_freq = 2412},
+	{ .hw_value = 2, .center_freq = 2417},
+	{ .hw_value = 3, .center_freq = 2422},
+	{ .hw_value = 4, .center_freq = 2427},
+	{ .hw_value = 5, .center_freq = 2432},
+	{ .hw_value = 6, .center_freq = 2437},
+	{ .hw_value = 7, .center_freq = 2442},
+	{ .hw_value = 8, .center_freq = 2447},
+	{ .hw_value = 9, .center_freq = 2452},
+	{ .hw_value = 10, .center_freq = 2457},
+	{ .hw_value = 11, .center_freq = 2462},
+	{ .hw_value = 12, .center_freq = 2467},
+	{ .hw_value = 13, .center_freq = 2472},
+};
+
+static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+			     const struct ieee80211_tx_queue_params *params)
+{
+	enum wl1251_acx_ps_scheme ps_scheme;
+	struct wl1251 *wl = hw->priv;
+	int ret;
+
+	mutex_lock(&wl->mutex);
+
+	wl1251_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue);
+
+	ret = wl1251_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	/* mac80211 uses units of 32 usec */
+	ret = wl1251_acx_ac_cfg(wl, wl1251_tx_get_queue(queue),
+				params->cw_min, params->cw_max,
+				params->aifs, params->txop * 32);
+	if (ret < 0)
+		goto out_sleep;
+
+	if (params->uapsd)
+		ps_scheme = WL1251_ACX_PS_SCHEME_UPSD_TRIGGER;
+	else
+		ps_scheme = WL1251_ACX_PS_SCHEME_LEGACY;
+
+	ret = wl1251_acx_tid_cfg(wl, wl1251_tx_get_queue(queue),
+				 CHANNEL_TYPE_EDCF,
+				 wl1251_tx_get_queue(queue), ps_scheme,
+				 WL1251_ACX_ACK_POLICY_LEGACY);
+	if (ret < 0)
+		goto out_sleep;
+
+out_sleep:
+	wl1251_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
+static int wl1251_op_get_survey(struct ieee80211_hw *hw, int idx,
+				struct survey_info *survey)
+{
+	struct wl1251 *wl = hw->priv;
+	struct ieee80211_conf *conf = &hw->conf;
+ 
+	if (idx != 0)
+		return -ENOENT;
+ 
+	survey->channel = conf->channel;
+	survey->filled = SURVEY_INFO_NOISE_DBM;
+	survey->noise = wl->noise;
+ 
+	return 0;
+}
+
+/* can't be const, mac80211 writes to this */
+static struct ieee80211_supported_band wl1251_band_2ghz = {
+	.channels = wl1251_channels,
+	.n_channels = ARRAY_SIZE(wl1251_channels),
+	.bitrates = wl1251_rates,
+	.n_bitrates = ARRAY_SIZE(wl1251_rates),
+};
+
+static const struct ieee80211_ops wl1251_ops = {
+	.start = wl1251_op_start,
+	.stop = wl1251_op_stop,
+	.add_interface = wl1251_op_add_interface,
+	.remove_interface = wl1251_op_remove_interface,
+	.config = wl1251_op_config,
+	.configure_filter = wl1251_op_configure_filter,
+	.tx = wl1251_op_tx,
+	.set_key = wl1251_op_set_key,
+	.hw_scan = wl1251_op_hw_scan,
+	.bss_info_changed = wl1251_op_bss_info_changed,
+	.set_rts_threshold = wl1251_op_set_rts_threshold,
+	.conf_tx = wl1251_op_conf_tx,
+	.get_survey = wl1251_op_get_survey,
+};
+
+static int wl1251_read_eeprom_byte(struct wl1251 *wl, off_t offset, u8 *data)
+{
+	unsigned long timeout;
+
+	wl1251_reg_write32(wl, EE_ADDR, offset);
+	wl1251_reg_write32(wl, EE_CTL, EE_CTL_READ);
+
+	/* EE_CTL_READ clears when data is ready */
+	timeout = jiffies + msecs_to_jiffies(100);
+	while (1) {
+		if (!(wl1251_reg_read32(wl, EE_CTL) & EE_CTL_READ))
+			break;
+
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+
+		msleep(1);
+	}
+
+	*data = wl1251_reg_read32(wl, EE_DATA);
+	return 0;
+}
+
+static int wl1251_read_eeprom(struct wl1251 *wl, off_t offset,
+			      u8 *data, size_t len)
+{
+	size_t i;
+	int ret;
+
+	wl1251_reg_write32(wl, EE_START, 0);
+
+	for (i = 0; i < len; i++) {
+		ret = wl1251_read_eeprom_byte(wl, offset + i, &data[i]);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int wl1251_read_eeprom_mac(struct wl1251 *wl)
+{
+	u8 mac[ETH_ALEN];
+	int i, ret;
+
+	wl1251_set_partition(wl, 0, 0, REGISTERS_BASE, REGISTERS_DOWN_SIZE);
+
+	ret = wl1251_read_eeprom(wl, 0x1c, mac, sizeof(mac));
+	if (ret < 0) {
+		wl1251_warning("failed to read MAC address from EEPROM");
+		return ret;
+	}
+
+	/* MAC is stored in reverse order */
+	for (i = 0; i < ETH_ALEN; i++)
+		wl->mac_addr[i] = mac[ETH_ALEN - i - 1];
+
+	return 0;
+}
+
+static int wl1251_register_hw(struct wl1251 *wl)
+{
+	int ret;
+
+	if (wl->mac80211_registered)
+		return 0;
+
+	SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
+
+	ret = ieee80211_register_hw(wl->hw);
+	if (ret < 0) {
+		wl1251_error("unable to register mac80211 hw: %d", ret);
+		return ret;
+	}
+
+	wl->mac80211_registered = true;
+
+	wl1251_notice("loaded");
+
+	return 0;
+}
+
+int wl1251_init_ieee80211(struct wl1251 *wl)
+{
+	int ret;
+
+	/* The tx descriptor buffer and the TKIP space */
+	wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc)
+		+ WL1251_TKIP_IV_SPACE;
+
+	/* unit us */
+	/* FIXME: find a proper value */
+	wl->hw->channel_change_time = 10000;
+
+	wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
+		IEEE80211_HW_SUPPORTS_PS |
+		IEEE80211_HW_BEACON_FILTER |
+		IEEE80211_HW_SUPPORTS_UAPSD;
+
+	wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+	wl->hw->wiphy->max_scan_ssids = 1;
+	wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz;
+
+	wl->hw->queues = 4;
+
+	if (wl->use_eeprom)
+		wl1251_read_eeprom_mac(wl);
+
+	ret = wl1251_register_hw(wl);
+	if (ret)
+		goto out;
+
+	wl1251_debugfs_init(wl);
+	wl1251_notice("initialized");
+
+	ret = 0;
+
+out:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wl1251_init_ieee80211);
+
+struct ieee80211_hw *wl1251_alloc_hw(void)
+{
+	struct ieee80211_hw *hw;
+	struct wl1251 *wl;
+	int i;
+	static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
+
+	hw = ieee80211_alloc_hw(sizeof(*wl), &wl1251_ops);
+	if (!hw) {
+		wl1251_error("could not alloc ieee80211_hw");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	wl = hw->priv;
+	memset(wl, 0, sizeof(*wl));
+
+	wl->hw = hw;
+
+	wl->data_in_count = 0;
+
+	skb_queue_head_init(&wl->tx_queue);
+
+	INIT_WORK(&wl->filter_work, wl1251_filter_work);
+	INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work);
+	wl->channel = WL1251_DEFAULT_CHANNEL;
+	wl->scanning = false;
+	wl->default_key = 0;
+	wl->listen_int = 1;
+	wl->rx_counter = 0;
+	wl->rx_handled = 0;
+	wl->rx_current_buffer = 0;
+	wl->rx_last_id = 0;
+	wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
+	wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
+	wl->elp = false;
+	wl->psm = 0;
+	wl->psm_requested = false;
+	wl->tx_queue_stopped = false;
+	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
+	wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
+	wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
+	wl->vif = NULL;
+
+	for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
+		wl->tx_frames[i] = NULL;
+
+	wl->next_tx_complete = 0;
+
+	INIT_WORK(&wl->irq_work, wl1251_irq_work);
+	INIT_WORK(&wl->tx_work, wl1251_tx_work);
+
+	/*
+	 * In case our MAC address is not correctly set,
+	 * we use a random but Nokia MAC.
+	 */
+	memcpy(wl->mac_addr, nokia_oui, 3);
+	get_random_bytes(wl->mac_addr + 3, 3);
+
+	wl->state = WL1251_STATE_OFF;
+	mutex_init(&wl->mutex);
+
+	wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE;
+	wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE;
+
+	wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL);
+	if (!wl->rx_descriptor) {
+		wl1251_error("could not allocate memory for rx descriptor");
+		ieee80211_free_hw(hw);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	return hw;
+}
+EXPORT_SYMBOL_GPL(wl1251_alloc_hw);
+
+int wl1251_free_hw(struct wl1251 *wl)
+{
+	ieee80211_unregister_hw(wl->hw);
+
+	wl1251_debugfs_exit(wl);
+
+	kfree(wl->target_mem_map);
+	kfree(wl->data_path);
+	vfree(wl->fw);
+	wl->fw = NULL;
+	kfree(wl->nvs);
+	wl->nvs = NULL;
+
+	kfree(wl->rx_descriptor);
+	wl->rx_descriptor = NULL;
+
+	ieee80211_free_hw(wl->hw);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wl1251_free_hw);
+
+MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
+MODULE_FIRMWARE(WL1251_FW_NAME);
diff --git a/drivers/net/wireless/wl1251/ps.c b/drivers/net/wireless/wl1251/ps.c
new file mode 100644
index 0000000..5ed47c8
--- /dev/null
+++ b/drivers/net/wireless/wl1251/ps.c
@@ -0,0 +1,194 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 "reg.h"
+#include "ps.h"
+#include "cmd.h"
+#include "io.h"
+
+/* in ms */
+#define WL1251_WAKEUP_TIMEOUT 100
+
+void wl1251_elp_work(struct work_struct *work)
+{
+	struct delayed_work *dwork;
+	struct wl1251 *wl;
+
+	dwork = container_of(work, struct delayed_work, work);
+	wl = container_of(dwork, struct wl1251, elp_work);
+
+	wl1251_debug(DEBUG_PSM, "elp work");
+
+	mutex_lock(&wl->mutex);
+
+	if (wl->elp || !wl->psm)
+		goto out;
+
+	wl1251_debug(DEBUG_PSM, "chip to elp");
+	wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
+	wl->elp = true;
+
+out:
+	mutex_unlock(&wl->mutex);
+}
+
+#define ELP_ENTRY_DELAY  5
+
+/* Routines to toggle sleep mode while in ELP */
+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);
+	}
+}
+
+int wl1251_ps_elp_wakeup(struct wl1251 *wl)
+{
+	unsigned long timeout, start;
+	u32 elp_reg;
+
+	if (!wl->elp)
+		return 0;
+
+	wl1251_debug(DEBUG_PSM, "waking up chip from elp");
+
+	start = jiffies;
+	timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT);
+
+	wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
+
+	elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
+
+	/*
+	 * FIXME: we should wait for irq from chip but, as a temporary
+	 * solution to simplify locking, let's poll instead
+	 */
+	while (!(elp_reg & ELPCTRL_WLAN_READY)) {
+		if (time_after(jiffies, timeout)) {
+			wl1251_error("elp wakeup timeout");
+			return -ETIMEDOUT;
+		}
+		msleep(1);
+		elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
+	}
+
+	wl1251_debug(DEBUG_PSM, "wakeup time: %u ms",
+		     jiffies_to_msecs(jiffies - start));
+
+	wl->elp = false;
+
+	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;
+
+	switch (mode) {
+	case STATION_POWER_SAVE_MODE:
+		wl1251_debug(DEBUG_PSM, "entering psm");
+
+		/* enable beacon filtering */
+		ret = wl1251_acx_beacon_filter_opt(wl, true);
+		if (ret < 0)
+			return ret;
+
+		ret = wl1251_acx_wake_up_conditions(wl,
+						    WAKE_UP_EVENT_DTIM_BITMAP,
+						    wl->listen_int);
+		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);
+		if (ret < 0)
+			return ret;
+
+		wl->psm = 1;
+		break;
+	case STATION_ACTIVE_MODE:
+	default:
+		wl1251_debug(DEBUG_PSM, "leaving psm");
+		ret = wl1251_ps_set_elp(wl, false);
+		if (ret < 0)
+			return ret;
+
+		/* disable beacon filtering */
+		ret = wl1251_acx_beacon_filter_opt(wl, false);
+		if (ret < 0)
+			return ret;
+
+		ret = wl1251_acx_wake_up_conditions(wl,
+						    WAKE_UP_EVENT_DTIM_BITMAP,
+						    wl->listen_int);
+		if (ret < 0)
+			return ret;
+
+		ret = wl1251_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
+		if (ret < 0)
+			return ret;
+
+		wl->psm = 0;
+		break;
+	}
+
+	return ret;
+}
+
diff --git a/drivers/net/wireless/wl1251/ps.h b/drivers/net/wireless/wl1251/ps.h
new file mode 100644
index 0000000..55c3dda
--- /dev/null
+++ b/drivers/net/wireless/wl1251/ps.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 __WL1251_PS_H__
+#define __WL1251_PS_H__
+
+#include "wl1251.h"
+#include "acx.h"
+
+int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode);
+void wl1251_ps_elp_sleep(struct wl1251 *wl);
+int wl1251_ps_elp_wakeup(struct wl1251 *wl);
+void wl1251_elp_work(struct work_struct *work);
+
+
+#endif /* __WL1251_PS_H__ */
diff --git a/drivers/net/wireless/wl1251/reg.h b/drivers/net/wireless/wl1251/reg.h
new file mode 100644
index 0000000..a580901
--- /dev/null
+++ b/drivers/net/wireless/wl1251/reg.h
@@ -0,0 +1,655 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 __REG_H__
+#define __REG_H__
+
+#include <linux/bitops.h>
+
+#define REGISTERS_BASE 0x00300000
+#define DRPW_BASE      0x00310000
+
+#define REGISTERS_DOWN_SIZE 0x00008800
+#define REGISTERS_WORK_SIZE 0x0000b000
+
+#define HW_ACCESS_ELP_CTRL_REG_ADDR         0x1FFFC
+
+/* ELP register commands */
+#define ELPCTRL_WAKE_UP             0x1
+#define ELPCTRL_WAKE_UP_WLAN_READY  0x5
+#define ELPCTRL_SLEEP               0x0
+/* ELP WLAN_READY bit */
+#define ELPCTRL_WLAN_READY          0x2
+
+/* Device Configuration registers*/
+#define SOR_CFG                        (REGISTERS_BASE + 0x0800)
+#define ECPU_CTRL                      (REGISTERS_BASE + 0x0804)
+#define HI_CFG                         (REGISTERS_BASE + 0x0808)
+
+/* EEPROM registers */
+#define EE_START                       (REGISTERS_BASE + 0x080C)
+#define EE_CTL                         (REGISTERS_BASE + 0x2000)
+#define EE_DATA                        (REGISTERS_BASE + 0x2004)
+#define EE_ADDR                        (REGISTERS_BASE + 0x2008)
+
+#define EE_CTL_READ                   2
+
+#define CHIP_ID_B                      (REGISTERS_BASE + 0x5674)
+
+#define CHIP_ID_1251_PG10	           (0x7010101)
+#define CHIP_ID_1251_PG11	           (0x7020101)
+#define CHIP_ID_1251_PG12	           (0x7030101)
+
+#define ENABLE                         (REGISTERS_BASE + 0x5450)
+
+/* Power Management registers */
+#define ELP_CFG_MODE                   (REGISTERS_BASE + 0x5804)
+#define ELP_CMD                        (REGISTERS_BASE + 0x5808)
+#define PLL_CAL_TIME                   (REGISTERS_BASE + 0x5810)
+#define CLK_REQ_TIME                   (REGISTERS_BASE + 0x5814)
+#define CLK_BUF_TIME                   (REGISTERS_BASE + 0x5818)
+
+#define CFG_PLL_SYNC_CNT               (REGISTERS_BASE + 0x5820)
+
+/* Scratch Pad registers*/
+#define SCR_PAD0                       (REGISTERS_BASE + 0x5608)
+#define SCR_PAD1                       (REGISTERS_BASE + 0x560C)
+#define SCR_PAD2                       (REGISTERS_BASE + 0x5610)
+#define SCR_PAD3                       (REGISTERS_BASE + 0x5614)
+#define SCR_PAD4                       (REGISTERS_BASE + 0x5618)
+#define SCR_PAD4_SET                   (REGISTERS_BASE + 0x561C)
+#define SCR_PAD4_CLR                   (REGISTERS_BASE + 0x5620)
+#define SCR_PAD5                       (REGISTERS_BASE + 0x5624)
+#define SCR_PAD5_SET                   (REGISTERS_BASE + 0x5628)
+#define SCR_PAD5_CLR                   (REGISTERS_BASE + 0x562C)
+#define SCR_PAD6                       (REGISTERS_BASE + 0x5630)
+#define SCR_PAD7                       (REGISTERS_BASE + 0x5634)
+#define SCR_PAD8                       (REGISTERS_BASE + 0x5638)
+#define SCR_PAD9                       (REGISTERS_BASE + 0x563C)
+
+/* Spare registers*/
+#define SPARE_A1                       (REGISTERS_BASE + 0x0994)
+#define SPARE_A2                       (REGISTERS_BASE + 0x0998)
+#define SPARE_A3                       (REGISTERS_BASE + 0x099C)
+#define SPARE_A4                       (REGISTERS_BASE + 0x09A0)
+#define SPARE_A5                       (REGISTERS_BASE + 0x09A4)
+#define SPARE_A6                       (REGISTERS_BASE + 0x09A8)
+#define SPARE_A7                       (REGISTERS_BASE + 0x09AC)
+#define SPARE_A8                       (REGISTERS_BASE + 0x09B0)
+#define SPARE_B1                       (REGISTERS_BASE + 0x5420)
+#define SPARE_B2                       (REGISTERS_BASE + 0x5424)
+#define SPARE_B3                       (REGISTERS_BASE + 0x5428)
+#define SPARE_B4                       (REGISTERS_BASE + 0x542C)
+#define SPARE_B5                       (REGISTERS_BASE + 0x5430)
+#define SPARE_B6                       (REGISTERS_BASE + 0x5434)
+#define SPARE_B7                       (REGISTERS_BASE + 0x5438)
+#define SPARE_B8                       (REGISTERS_BASE + 0x543C)
+
+enum wl12xx_acx_int_reg {
+	ACX_REG_INTERRUPT_TRIG,
+	ACX_REG_INTERRUPT_TRIG_H,
+
+/*=============================================
+  Host Interrupt Mask Register - 32bit (RW)
+  ------------------------------------------
+  Setting a bit in this register masks the
+  corresponding interrupt to the host.
+  0 - RX0		- Rx first dubble buffer Data Interrupt
+  1 - TXD		- Tx Data Interrupt
+  2 - TXXFR		- Tx Transfer Interrupt
+  3 - RX1		- Rx second dubble buffer Data Interrupt
+  4 - RXXFR		- Rx Transfer Interrupt
+  5 - EVENT_A	- Event Mailbox interrupt
+  6 - EVENT_B	- Event Mailbox interrupt
+  7 - WNONHST	- Wake On Host Interrupt
+  8 - TRACE_A	- Debug Trace interrupt
+  9 - TRACE_B	- Debug Trace interrupt
+ 10 - CDCMP		- Command Complete Interrupt
+ 11 -
+ 12 -
+ 13 -
+ 14 - ICOMP		- Initialization Complete Interrupt
+ 16 - SG SE		- Soft Gemini - Sense enable interrupt
+ 17 - SG SD		- Soft Gemini - Sense disable interrupt
+ 18 -			-
+ 19 -			-
+ 20 -			-
+ 21-			-
+ Default: 0x0001
+*==============================================*/
+	ACX_REG_INTERRUPT_MASK,
+
+/*=============================================
+  Host Interrupt Mask Set 16bit, (Write only)
+  ------------------------------------------
+ Setting a bit in this register sets
+ the corresponding bin in ACX_HINT_MASK register
+ without effecting the mask
+ state of other bits (0 = no effect).
+==============================================*/
+	ACX_REG_HINT_MASK_SET,
+
+/*=============================================
+  Host Interrupt Mask Clear 16bit,(Write only)
+  ------------------------------------------
+ Setting a bit in this register clears
+ the corresponding bin in ACX_HINT_MASK register
+ without effecting the mask
+ state of other bits (0 = no effect).
+=============================================*/
+	ACX_REG_HINT_MASK_CLR,
+
+/*=============================================
+  Host Interrupt Status Nondestructive Read
+  16bit,(Read only)
+  ------------------------------------------
+ The host can read this register to determine
+ which interrupts are active.
+ Reading this register doesn't
+ effect its content.
+=============================================*/
+	ACX_REG_INTERRUPT_NO_CLEAR,
+
+/*=============================================
+  Host Interrupt Status Clear on Read  Register
+  16bit,(Read only)
+  ------------------------------------------
+ The host can read this register to determine
+ which interrupts are active.
+ Reading this register clears it,
+ thus making all interrupts inactive.
+==============================================*/
+	ACX_REG_INTERRUPT_CLEAR,
+
+/*=============================================
+  Host Interrupt Acknowledge Register
+  16bit,(Write only)
+  ------------------------------------------
+ The host can set individual bits in this
+ register to clear (acknowledge) the corresp.
+ interrupt status bits in the HINT_STS_CLR and
+ HINT_STS_ND registers, thus making the
+ assotiated interrupt inactive. (0-no effect)
+==============================================*/
+	ACX_REG_INTERRUPT_ACK,
+
+/*===============================================
+   Host Software Reset - 32bit RW
+ ------------------------------------------
+    [31:1] Reserved
+    0  SOFT_RESET Soft Reset  - When this bit is set,
+    it holds the Wlan hardware in a soft reset state.
+    This reset disables all MAC and baseband processor
+    clocks except the CardBus/PCI interface clock.
+    It also initializes all MAC state machines except
+    the host interface. It does not reload the
+    contents of the EEPROM. When this bit is cleared
+    (not self-clearing), the Wlan hardware
+    exits the software reset state.
+===============================================*/
+	ACX_REG_SLV_SOFT_RESET,
+
+/*===============================================
+ EEPROM Burst Read Start  - 32bit RW
+ ------------------------------------------
+ [31:1] Reserved
+ 0  ACX_EE_START -  EEPROM Burst Read Start 0
+ Setting this bit starts a burst read from
+ the external EEPROM.
+ If this bit is set (after reset) before an EEPROM read/write,
+ the burst read starts at EEPROM address 0.
+ Otherwise, it starts at the address
+ following the address of the previous access.
+ TheWlan hardware hardware clears this bit automatically.
+
+ Default: 0x00000000
+*================================================*/
+	ACX_REG_EE_START,
+
+/* Embedded ARM CPU Control */
+
+/*===============================================
+ Halt eCPU   - 32bit RW
+ ------------------------------------------
+ 0 HALT_ECPU Halt Embedded CPU - This bit is the
+ compliment of bit 1 (MDATA2) in the SOR_CFG register.
+ During a hardware reset, this bit holds
+ the inverse of MDATA2.
+ When downloading firmware from the host,
+ set this bit (pull down MDATA2).
+ The host clears this bit after downloading the firmware into
+ zero-wait-state SSRAM.
+ When loading firmware from Flash, clear this bit (pull up MDATA2)
+ so that the eCPU can run the bootloader code in Flash
+ HALT_ECPU eCPU State
+ --------------------
+ 1 halt eCPU
+ 0 enable eCPU
+ ===============================================*/
+	ACX_REG_ECPU_CONTROL,
+
+	ACX_REG_TABLE_LEN
+};
+
+#define ACX_SLV_SOFT_RESET_BIT   BIT(0)
+#define ACX_REG_EEPROM_START_BIT BIT(0)
+
+/* Command/Information Mailbox Pointers */
+
+/*===============================================
+  Command Mailbox Pointer - 32bit RW
+ ------------------------------------------
+ This register holds the start address of
+ the command mailbox located in the Wlan hardware memory.
+ The host must read this pointer after a reset to
+ find the location of the command mailbox.
+ The Wlan hardware initializes the command mailbox
+ pointer with the default address of the command mailbox.
+ The command mailbox pointer is not valid until after
+ the host receives the Init Complete interrupt from
+ the Wlan hardware.
+ ===============================================*/
+#define REG_COMMAND_MAILBOX_PTR				(SCR_PAD0)
+
+/*===============================================
+  Information Mailbox Pointer - 32bit RW
+ ------------------------------------------
+ This register holds the start address of
+ the information mailbox located in the Wlan hardware memory.
+ The host must read this pointer after a reset to find
+ the location of the information mailbox.
+ The Wlan hardware initializes the information mailbox pointer
+ with the default address of the information mailbox.
+ The information mailbox pointer is not valid
+ until after the host receives the Init Complete interrupt from
+ the Wlan hardware.
+ ===============================================*/
+#define REG_EVENT_MAILBOX_PTR				(SCR_PAD1)
+
+
+/* Misc */
+
+#define REG_ENABLE_TX_RX				(ENABLE)
+/*
+ * Rx configuration (filter) information element
+ * ---------------------------------------------
+ */
+#define REG_RX_CONFIG				(RX_CFG)
+#define REG_RX_FILTER				(RX_FILTER_CFG)
+
+
+#define RX_CFG_ENABLE_PHY_HEADER_PLCP	 0x0002
+
+/* promiscuous - receives all valid frames */
+#define RX_CFG_PROMISCUOUS		 0x0008
+
+/* receives frames from any BSSID */
+#define RX_CFG_BSSID			 0x0020
+
+/* receives frames destined to any MAC address */
+#define RX_CFG_MAC			 0x0010
+
+#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC	 0x0010
+#define RX_CFG_ENABLE_ANY_DEST_MAC	 0x0000
+#define RX_CFG_ENABLE_ONLY_MY_BSSID	 0x0020
+#define RX_CFG_ENABLE_ANY_BSSID		 0x0000
+
+/* discards all broadcast frames */
+#define RX_CFG_DISABLE_BCAST		 0x0200
+
+#define RX_CFG_ENABLE_ONLY_MY_SSID	 0x0400
+#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800
+#define RX_CFG_COPY_RX_STATUS		 0x2000
+#define RX_CFG_TSF			 0x10000
+
+#define RX_CONFIG_OPTION_ANY_DST_MY_BSS	 (RX_CFG_ENABLE_ANY_DEST_MAC | \
+					  RX_CFG_ENABLE_ONLY_MY_BSSID)
+
+#define RX_CONFIG_OPTION_MY_DST_ANY_BSS	 (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
+					  | RX_CFG_ENABLE_ANY_BSSID)
+
+#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
+					  RX_CFG_ENABLE_ANY_BSSID)
+
+#define RX_CONFIG_OPTION_MY_DST_MY_BSS	 (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
+					  | RX_CFG_ENABLE_ONLY_MY_BSSID)
+
+#define RX_CONFIG_OPTION_FOR_SCAN  (RX_CFG_ENABLE_PHY_HEADER_PLCP \
+				    | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \
+				    | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF)
+
+#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC)
+
+#define RX_CONFIG_OPTION_FOR_JOIN	 (RX_CFG_ENABLE_ONLY_MY_BSSID | \
+					  RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
+
+#define RX_CONFIG_OPTION_FOR_IBSS_JOIN   (RX_CFG_ENABLE_ONLY_MY_SSID | \
+					  RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
+
+#define RX_FILTER_OPTION_DEF	      (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 RX_FILTER_OPTION_FILTER_ALL	 0
+
+#define RX_FILTER_OPTION_DEF_PRSP_BCN  (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\
+					| CFG_RX_RCTS_ACK | CFG_RX_BCN_EN)
+
+#define RX_FILTER_OPTION_JOIN	     (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
+				      | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\
+				      | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\
+				      | CFG_RX_PRSP_EN)
+
+
+/*===============================================
+ EEPROM Read/Write Request 32bit RW
+ ------------------------------------------
+ 1 EE_READ - EEPROM Read Request 1 - Setting this bit
+ loads a single byte of data into the EE_DATA
+ register from the EEPROM location specified in
+ the EE_ADDR register.
+ The Wlan hardware hardware clears this bit automatically.
+ EE_DATA is valid when this bit is cleared.
+
+ 0 EE_WRITE  - EEPROM Write Request  - Setting this bit
+ writes a single byte of data from the EE_DATA register into the
+ EEPROM location specified in the EE_ADDR register.
+ The Wlan hardware hardware clears this bit automatically.
+*===============================================*/
+#define EE_CTL                              (REGISTERS_BASE + 0x2000)
+#define ACX_EE_CTL_REG                      EE_CTL
+#define EE_WRITE                            0x00000001ul
+#define EE_READ                             0x00000002ul
+
+/*===============================================
+  EEPROM Address  - 32bit RW
+  ------------------------------------------
+  This register specifies the address
+  within the EEPROM from/to which to read/write data.
+  ===============================================*/
+#define EE_ADDR                             (REGISTERS_BASE + 0x2008)
+#define ACX_EE_ADDR_REG                     EE_ADDR
+
+/*===============================================
+  EEPROM Data  - 32bit RW
+  ------------------------------------------
+  This register either holds the read 8 bits of
+  data from the EEPROM or the write data
+  to be written to the EEPROM.
+  ===============================================*/
+#define EE_DATA                             (REGISTERS_BASE + 0x2004)
+#define ACX_EE_DATA_REG                     EE_DATA
+
+#define EEPROM_ACCESS_TO                    10000   /* timeout counter */
+#define START_EEPROM_MGR                    0x00000001
+
+/*===============================================
+  EEPROM Base Address  - 32bit RW
+  ------------------------------------------
+  This register holds the upper nine bits
+  [23:15] of the 24-bit Wlan hardware memory
+  address for burst reads from EEPROM accesses.
+  The EEPROM provides the lower 15 bits of this address.
+  The MSB of the address from the EEPROM is ignored.
+  ===============================================*/
+#define ACX_EE_CFG                          EE_CFG
+
+/*===============================================
+  GPIO Output Values  -32bit, RW
+  ------------------------------------------
+  [31:16]  Reserved
+  [15: 0]  Specify the output values (at the output driver inputs) for
+  GPIO[15:0], respectively.
+  ===============================================*/
+#define ACX_GPIO_OUT_REG            GPIO_OUT
+#define ACX_MAX_GPIO_LINES          15
+
+/*===============================================
+  Contention window  -32bit, RW
+  ------------------------------------------
+  [31:26]  Reserved
+  [25:16]  Max (0x3ff)
+  [15:07]  Reserved
+  [06:00]  Current contention window value - default is 0x1F
+  ===============================================*/
+#define ACX_CONT_WIND_CFG_REG    CONT_WIND_CFG
+#define ACX_CONT_WIND_MIN_MASK   0x0000007f
+#define ACX_CONT_WIND_MAX        0x03ff0000
+
+/*===============================================
+  HI_CFG Interface Configuration Register Values
+  ------------------------------------------
+  ===============================================*/
+#define HI_CFG_UART_ENABLE          0x00000004
+#define HI_CFG_RST232_ENABLE        0x00000008
+#define HI_CFG_CLOCK_REQ_SELECT     0x00000010
+#define HI_CFG_HOST_INT_ENABLE      0x00000020
+#define HI_CFG_VLYNQ_OUTPUT_ENABLE  0x00000040
+#define HI_CFG_HOST_INT_ACTIVE_LOW  0x00000080
+#define HI_CFG_UART_TX_OUT_GPIO_15  0x00000100
+#define HI_CFG_UART_TX_OUT_GPIO_14  0x00000200
+#define HI_CFG_UART_TX_OUT_GPIO_7   0x00000400
+
+/*
+ * NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile
+ *       for platforms using active high interrupt level
+ */
+#ifdef USE_ACTIVE_HIGH
+#define HI_CFG_DEF_VAL              \
+	(HI_CFG_UART_ENABLE |        \
+	HI_CFG_RST232_ENABLE |      \
+	HI_CFG_CLOCK_REQ_SELECT |   \
+	HI_CFG_HOST_INT_ENABLE)
+#else
+#define HI_CFG_DEF_VAL              \
+	(HI_CFG_UART_ENABLE |        \
+	HI_CFG_RST232_ENABLE |      \
+	HI_CFG_CLOCK_REQ_SELECT |   \
+	HI_CFG_HOST_INT_ENABLE)
+
+#endif
+
+#define REF_FREQ_19_2                       0
+#define REF_FREQ_26_0                       1
+#define REF_FREQ_38_4                       2
+#define REF_FREQ_40_0                       3
+#define REF_FREQ_33_6                       4
+#define REF_FREQ_NUM                        5
+
+#define LUT_PARAM_INTEGER_DIVIDER           0
+#define LUT_PARAM_FRACTIONAL_DIVIDER        1
+#define LUT_PARAM_ATTN_BB                   2
+#define LUT_PARAM_ALPHA_BB                  3
+#define LUT_PARAM_STOP_TIME_BB              4
+#define LUT_PARAM_BB_PLL_LOOP_FILTER        5
+#define LUT_PARAM_NUM                       6
+
+#define ACX_EEPROMLESS_IND_REG              (SCR_PAD4)
+#define USE_EEPROM                          0
+#define SOFT_RESET_MAX_TIME                 1000000
+#define SOFT_RESET_STALL_TIME               1000
+#define NVS_DATA_BUNDARY_ALIGNMENT          4
+
+
+/* Firmware image load chunk size */
+#define CHUNK_SIZE          512
+
+/* Firmware image header size */
+#define FW_HDR_SIZE 8
+
+#define ECPU_CONTROL_HALT					0x00000101
+
+
+/******************************************************************************
+
+    CHANNELS, BAND & REG DOMAINS definitions
+
+******************************************************************************/
+
+
+enum {
+	RADIO_BAND_2_4GHZ = 0,  /* 2.4 Ghz band */
+	RADIO_BAND_5GHZ = 1,    /* 5 Ghz band */
+	RADIO_BAND_JAPAN_4_9_GHZ = 2,
+	DEFAULT_BAND = RADIO_BAND_2_4GHZ,
+	INVALID_BAND = 0xFE,
+	MAX_RADIO_BANDS = 0xFF
+};
+
+enum {
+	NO_RATE      = 0,
+	RATE_1MBPS   = 0x0A,
+	RATE_2MBPS   = 0x14,
+	RATE_5_5MBPS = 0x37,
+	RATE_6MBPS   = 0x0B,
+	RATE_9MBPS   = 0x0F,
+	RATE_11MBPS  = 0x6E,
+	RATE_12MBPS  = 0x0A,
+	RATE_18MBPS  = 0x0E,
+	RATE_22MBPS  = 0xDC,
+	RATE_24MBPS  = 0x09,
+	RATE_36MBPS  = 0x0D,
+	RATE_48MBPS  = 0x08,
+	RATE_54MBPS  = 0x0C
+};
+
+enum {
+	RATE_INDEX_1MBPS   =  0,
+	RATE_INDEX_2MBPS   =  1,
+	RATE_INDEX_5_5MBPS =  2,
+	RATE_INDEX_6MBPS   =  3,
+	RATE_INDEX_9MBPS   =  4,
+	RATE_INDEX_11MBPS  =  5,
+	RATE_INDEX_12MBPS  =  6,
+	RATE_INDEX_18MBPS  =  7,
+	RATE_INDEX_22MBPS  =  8,
+	RATE_INDEX_24MBPS  =  9,
+	RATE_INDEX_36MBPS  =  10,
+	RATE_INDEX_48MBPS  =  11,
+	RATE_INDEX_54MBPS  =  12,
+	RATE_INDEX_MAX     =  RATE_INDEX_54MBPS,
+	MAX_RATE_INDEX,
+	INVALID_RATE_INDEX = MAX_RATE_INDEX,
+	RATE_INDEX_ENUM_MAX_SIZE = 0x7FFFFFFF
+};
+
+enum {
+	RATE_MASK_1MBPS = 0x1,
+	RATE_MASK_2MBPS = 0x2,
+	RATE_MASK_5_5MBPS = 0x4,
+	RATE_MASK_11MBPS = 0x20,
+};
+
+#define SHORT_PREAMBLE_BIT   BIT(0) /* CCK or Barker depending on the rate */
+#define OFDM_RATE_BIT        BIT(6)
+#define PBCC_RATE_BIT        BIT(7)
+
+enum {
+	CCK_LONG = 0,
+	CCK_SHORT = SHORT_PREAMBLE_BIT,
+	PBCC_LONG = PBCC_RATE_BIT,
+	PBCC_SHORT = PBCC_RATE_BIT | SHORT_PREAMBLE_BIT,
+	OFDM = OFDM_RATE_BIT
+};
+
+/******************************************************************************
+
+Transmit-Descriptor RATE-SET field definitions...
+
+Define a new "Rate-Set" for TX path that incorporates the
+Rate & Modulation info into a single 16-bit field.
+
+TxdRateSet_t:
+b15   - Indicates Preamble type (1=SHORT, 0=LONG).
+	Notes:
+	Must be LONG (0) for 1Mbps rate.
+	Does not apply (set to 0) for RevG-OFDM rates.
+b14   - Indicates PBCC encoding (1=PBCC, 0=not).
+	Notes:
+	Does not apply (set to 0) for rates 1 and 2 Mbps.
+	Does not apply (set to 0) for RevG-OFDM rates.
+b13    - Unused (set to 0).
+b12-b0 - Supported Rate indicator bits as defined below.
+
+******************************************************************************/
+
+
+/*************************************************************************
+
+    Interrupt Trigger Register (Host -> WiLink)
+
+**************************************************************************/
+
+/* Hardware to Embedded CPU Interrupts - first 32-bit register set */
+
+/*
+ * Host Command Interrupt. Setting this bit masks
+ * the interrupt that the host issues to inform
+ * the FW that it has sent a command
+ * to the Wlan hardware Command Mailbox.
+ */
+#define INTR_TRIG_CMD       BIT(0)
+
+/*
+ * Host Event Acknowlegde Interrupt. The host
+ * sets this bit to acknowledge that it received
+ * the unsolicited information from the event
+ * mailbox.
+ */
+#define INTR_TRIG_EVENT_ACK BIT(1)
+
+/*
+ * The host sets this bit to inform the Wlan
+ * FW that a TX packet is in the XFER
+ * Buffer #0.
+ */
+#define INTR_TRIG_TX_PROC0 BIT(2)
+
+/*
+ * The host sets this bit to inform the FW
+ * that it read a packet from RX XFER
+ * Buffer #0.
+ */
+#define INTR_TRIG_RX_PROC0 BIT(3)
+
+#define INTR_TRIG_DEBUG_ACK BIT(4)
+
+#define INTR_TRIG_STATE_CHANGED BIT(5)
+
+
+/* Hardware to Embedded CPU Interrupts - second 32-bit register set */
+
+/*
+ * The host sets this bit to inform the FW
+ * that it read a packet from RX XFER
+ * Buffer #1.
+ */
+#define INTR_TRIG_RX_PROC1 BIT(17)
+
+/*
+ * The host sets this bit to inform the Wlan
+ * hardware that a TX packet is in the XFER
+ * Buffer #1.
+ */
+#define INTR_TRIG_TX_PROC1 BIT(18)
+
+#endif
diff --git a/drivers/net/wireless/wl1251/rx.c b/drivers/net/wireless/wl1251/rx.c
new file mode 100644
index 0000000..efa5360
--- /dev/null
+++ b/drivers/net/wireless/wl1251/rx.c
@@ -0,0 +1,190 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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/skbuff.h>
+#include <linux/gfp.h>
+#include <net/mac80211.h>
+
+#include "wl1251.h"
+#include "reg.h"
+#include "io.h"
+#include "rx.h"
+#include "cmd.h"
+#include "acx.h"
+
+static void wl1251_rx_header(struct wl1251 *wl,
+			     struct wl1251_rx_descriptor *desc)
+{
+	u32 rx_packet_ring_addr;
+
+	rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr;
+	if (wl->rx_current_buffer)
+		rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size;
+
+	wl1251_mem_read(wl, rx_packet_ring_addr, desc, sizeof(*desc));
+}
+
+static void wl1251_rx_status(struct wl1251 *wl,
+			     struct wl1251_rx_descriptor *desc,
+			     struct ieee80211_rx_status *status,
+			     u8 beacon)
+{
+	u64 mactime;
+	int ret;
+
+	memset(status, 0, sizeof(struct ieee80211_rx_status));
+
+	status->band = IEEE80211_BAND_2GHZ;
+	status->mactime = desc->timestamp;
+
+	/*
+	 * The rx status timestamp is a 32 bits value while the TSF is a
+	 * 64 bits one.
+	 * For IBSS merging, TSF is mandatory, so we have to get it
+	 * somehow, so we ask for ACX_TSF_INFO.
+	 * That could be moved to the get_tsf() hook, but unfortunately,
+	 * this one must be atomic, while our SPI routines can sleep.
+	 */
+	if ((wl->bss_type == BSS_TYPE_IBSS) && beacon) {
+		ret = wl1251_acx_tsf_info(wl, &mactime);
+		if (ret == 0)
+			status->mactime = mactime;
+	}
+
+	status->signal = desc->rssi;
+
+	/*
+	 * FIXME: guessing that snr needs to be divided by two, otherwise
+	 * the values don't make any sense
+	 */
+	wl->noise = desc->rssi - desc->snr / 2;
+
+	status->freq = ieee80211_channel_to_frequency(desc->channel);
+
+	status->flag |= RX_FLAG_TSFT;
+
+	if (desc->flags & RX_DESC_ENCRYPTION_MASK) {
+		status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
+
+		if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL)))
+			status->flag |= RX_FLAG_DECRYPTED;
+
+		if (unlikely(desc->flags & RX_DESC_MIC_FAIL))
+			status->flag |= RX_FLAG_MMIC_ERROR;
+	}
+
+	if (unlikely(!(desc->flags & RX_DESC_VALID_FCS)))
+		status->flag |= RX_FLAG_FAILED_FCS_CRC;
+
+
+	/* FIXME: set status->rate_idx */
+}
+
+static void wl1251_rx_body(struct wl1251 *wl,
+			   struct wl1251_rx_descriptor *desc)
+{
+	struct sk_buff *skb;
+	struct ieee80211_rx_status status;
+	u8 *rx_buffer, beacon = 0;
+	u16 length, *fc;
+	u32 curr_id, last_id_inc, rx_packet_ring_addr;
+
+	length = WL1251_RX_ALIGN(desc->length  - PLCP_HEADER_LENGTH);
+	curr_id = (desc->flags & RX_DESC_SEQNUM_MASK) >> RX_DESC_PACKETID_SHIFT;
+	last_id_inc = (wl->rx_last_id + 1) % (RX_MAX_PACKET_ID + 1);
+
+	if (last_id_inc != curr_id) {
+		wl1251_warning("curr ID:%d, last ID inc:%d",
+			       curr_id, last_id_inc);
+		wl->rx_last_id = curr_id;
+	} else {
+		wl->rx_last_id = last_id_inc;
+	}
+
+	rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr +
+		sizeof(struct wl1251_rx_descriptor) + 20;
+	if (wl->rx_current_buffer)
+		rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size;
+
+	skb = __dev_alloc_skb(length, GFP_KERNEL);
+	if (!skb) {
+		wl1251_error("Couldn't allocate RX frame");
+		return;
+	}
+
+	rx_buffer = skb_put(skb, length);
+	wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length);
+
+	/* The actual lenght doesn't include the target's alignment */
+	skb->len = desc->length  - PLCP_HEADER_LENGTH;
+
+	fc = (u16 *)skb->data;
+
+	if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
+		beacon = 1;
+
+	wl1251_rx_status(wl, desc, &status, beacon);
+
+	wl1251_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
+		     beacon ? "beacon" : "");
+
+	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+	ieee80211_rx_ni(wl->hw, skb);
+}
+
+static void wl1251_rx_ack(struct wl1251 *wl)
+{
+	u32 data, addr;
+
+	if (wl->rx_current_buffer) {
+		addr = ACX_REG_INTERRUPT_TRIG_H;
+		data = INTR_TRIG_RX_PROC1;
+	} else {
+		addr = ACX_REG_INTERRUPT_TRIG;
+		data = INTR_TRIG_RX_PROC0;
+	}
+
+	wl1251_reg_write32(wl, addr, data);
+
+	/* Toggle buffer ring */
+	wl->rx_current_buffer = !wl->rx_current_buffer;
+}
+
+
+void wl1251_rx(struct wl1251 *wl)
+{
+	struct wl1251_rx_descriptor *rx_desc;
+
+	if (wl->state != WL1251_STATE_ON)
+		return;
+
+	rx_desc = wl->rx_descriptor;
+
+	/* We first read the frame's header */
+	wl1251_rx_header(wl, rx_desc);
+
+	/* Now we can read the body */
+	wl1251_rx_body(wl, rx_desc);
+
+	/* Finally, we need to ACK the RX */
+	wl1251_rx_ack(wl);
+}
diff --git a/drivers/net/wireless/wl1251/rx.h b/drivers/net/wireless/wl1251/rx.h
new file mode 100644
index 0000000..4448f63
--- /dev/null
+++ b/drivers/net/wireless/wl1251/rx.h
@@ -0,0 +1,122 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 __WL1251_RX_H__
+#define __WL1251_RX_H__
+
+#include <linux/bitops.h>
+
+#include "wl1251.h"
+
+/*
+ * RX PATH
+ *
+ * The Rx path uses a double buffer and an rx_contro structure, each located
+ * at a fixed address in the device memory. The host keeps track of which
+ * buffer is available and alternates between them on a per packet basis.
+ * The size of each of the two buffers is large enough to hold the longest
+ * 802.3 packet.
+ * The RX path goes like that:
+ * 1) The target generates an interrupt each time a new packet is received.
+ *   There are 2 RX interrupts, one for each buffer.
+ * 2) The host reads the received packet from one of the double buffers.
+ * 3) The host triggers a target interrupt.
+ * 4) The target prepares the next RX packet.
+ */
+
+#define WL1251_RX_MAX_RSSI -30
+#define WL1251_RX_MIN_RSSI -95
+
+#define WL1251_RX_ALIGN_TO 4
+#define WL1251_RX_ALIGN(len) (((len) + WL1251_RX_ALIGN_TO - 1) & \
+			     ~(WL1251_RX_ALIGN_TO - 1))
+
+#define SHORT_PREAMBLE_BIT   BIT(0)
+#define OFDM_RATE_BIT        BIT(6)
+#define PBCC_RATE_BIT        BIT(7)
+
+#define PLCP_HEADER_LENGTH 8
+#define RX_DESC_PACKETID_SHIFT 11
+#define RX_MAX_PACKET_ID 3
+
+#define RX_DESC_VALID_FCS         0x0001
+#define RX_DESC_MATCH_RXADDR1     0x0002
+#define RX_DESC_MCAST             0x0004
+#define RX_DESC_STAINTIM          0x0008
+#define RX_DESC_VIRTUAL_BM        0x0010
+#define RX_DESC_BCAST             0x0020
+#define RX_DESC_MATCH_SSID        0x0040
+#define RX_DESC_MATCH_BSSID       0x0080
+#define RX_DESC_ENCRYPTION_MASK   0x0300
+#define RX_DESC_MEASURMENT        0x0400
+#define RX_DESC_SEQNUM_MASK       0x1800
+#define	RX_DESC_MIC_FAIL	  0x2000
+#define	RX_DESC_DECRYPT_FAIL	  0x4000
+
+struct wl1251_rx_descriptor {
+	u32 timestamp; /* In microseconds */
+	u16 length; /* Paylod length, including headers */
+	u16 flags;
+
+	/*
+	 * 0 - 802.11
+	 * 1 - 802.3
+	 * 2 - IP
+	 * 3 - Raw Codec
+	 */
+	u8 type;
+
+	/*
+	 * Received Rate:
+	 * 0x0A - 1MBPS
+	 * 0x14 - 2MBPS
+	 * 0x37 - 5_5MBPS
+	 * 0x0B - 6MBPS
+	 * 0x0F - 9MBPS
+	 * 0x6E - 11MBPS
+	 * 0x0A - 12MBPS
+	 * 0x0E - 18MBPS
+	 * 0xDC - 22MBPS
+	 * 0x09 - 24MBPS
+	 * 0x0D - 36MBPS
+	 * 0x08 - 48MBPS
+	 * 0x0C - 54MBPS
+	 */
+	u8 rate;
+
+	u8 mod_pre; /* Modulation and preamble */
+	u8 channel;
+
+	/*
+	 * 0 - 2.4 Ghz
+	 * 1 - 5 Ghz
+	 */
+	u8 band;
+
+	s8 rssi; /* in dB */
+	u8 rcpi; /* in dB */
+	u8 snr; /* in dB */
+} __packed;
+
+void wl1251_rx(struct wl1251 *wl);
+
+#endif
diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c
new file mode 100644
index 0000000..74ba9ce
--- /dev/null
+++ b/drivers/net/wireless/wl1251/sdio.c
@@ -0,0 +1,342 @@
+/*
+ * wl12xx SDIO routines
+ *
+ * This program is free software; you can 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
+ *
+ * Copyright (C) 2005 Texas Instruments Incorporated
+ * Copyright (C) 2008 Google Inc
+ * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com)
+ */
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/platform_device.h>
+#include <linux/wl12xx.h>
+#include <linux/irq.h>
+
+#include "wl1251.h"
+
+#ifndef SDIO_VENDOR_ID_TI
+#define SDIO_VENDOR_ID_TI		0x104c
+#endif
+
+#ifndef SDIO_DEVICE_ID_TI_WL1251
+#define SDIO_DEVICE_ID_TI_WL1251	0x9066
+#endif
+
+struct wl1251_sdio {
+	struct sdio_func *func;
+	u32 elp_val;
+};
+
+static struct wl12xx_platform_data *wl12xx_board_data;
+
+static struct sdio_func *wl_to_func(struct wl1251 *wl)
+{
+	struct wl1251_sdio *wl_sdio = wl->if_priv;
+	return wl_sdio->func;
+}
+
+static void wl1251_sdio_interrupt(struct sdio_func *func)
+{
+	struct wl1251 *wl = sdio_get_drvdata(func);
+
+	wl1251_debug(DEBUG_IRQ, "IRQ");
+
+	/* FIXME should be synchronous for sdio */
+	ieee80211_queue_work(wl->hw, &wl->irq_work);
+}
+
+static const struct sdio_device_id wl1251_devices[] = {
+	{ SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1251) },
+	{}
+};
+MODULE_DEVICE_TABLE(sdio, wl1251_devices);
+
+
+static void wl1251_sdio_read(struct wl1251 *wl, int addr,
+			     void *buf, size_t len)
+{
+	int ret;
+	struct sdio_func *func = wl_to_func(wl);
+
+	sdio_claim_host(func);
+	ret = sdio_memcpy_fromio(func, buf, addr, len);
+	if (ret)
+		wl1251_error("sdio read failed (%d)", ret);
+	sdio_release_host(func);
+}
+
+static void wl1251_sdio_write(struct wl1251 *wl, int addr,
+			      void *buf, size_t len)
+{
+	int ret;
+	struct sdio_func *func = wl_to_func(wl);
+
+	sdio_claim_host(func);
+	ret = sdio_memcpy_toio(func, addr, buf, len);
+	if (ret)
+		wl1251_error("sdio write failed (%d)", ret);
+	sdio_release_host(func);
+}
+
+static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
+{
+	int ret = 0;
+	struct wl1251_sdio *wl_sdio = wl->if_priv;
+	struct sdio_func *func = wl_sdio->func;
+
+	/*
+	 * The hardware only supports RAW (read after write) access for
+	 * reading, regular sdio_readb won't work here (it interprets
+	 * the unused bits of CMD52 as write data even if we send read
+	 * request).
+	 */
+	sdio_claim_host(func);
+	*val = sdio_writeb_readb(func, wl_sdio->elp_val, addr, &ret);
+	sdio_release_host(func);
+
+	if (ret)
+		wl1251_error("sdio_readb failed (%d)", ret);
+}
+
+static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
+{
+	int ret = 0;
+	struct wl1251_sdio *wl_sdio = wl->if_priv;
+	struct sdio_func *func = wl_sdio->func;
+
+	sdio_claim_host(func);
+	sdio_writeb(func, val, addr, &ret);
+	sdio_release_host(func);
+
+	if (ret)
+		wl1251_error("sdio_writeb failed (%d)", ret);
+	else
+		wl_sdio->elp_val = val;
+}
+
+static void wl1251_sdio_reset(struct wl1251 *wl)
+{
+}
+
+static void wl1251_sdio_enable_irq(struct wl1251 *wl)
+{
+	struct sdio_func *func = wl_to_func(wl);
+
+	sdio_claim_host(func);
+	sdio_claim_irq(func, wl1251_sdio_interrupt);
+	sdio_release_host(func);
+}
+
+static void wl1251_sdio_disable_irq(struct wl1251 *wl)
+{
+	struct sdio_func *func = wl_to_func(wl);
+
+	sdio_claim_host(func);
+	sdio_release_irq(func);
+	sdio_release_host(func);
+}
+
+/* Interrupts when using dedicated WLAN_IRQ pin */
+static irqreturn_t wl1251_line_irq(int irq, void *cookie)
+{
+	struct wl1251 *wl = cookie;
+
+	ieee80211_queue_work(wl->hw, &wl->irq_work);
+
+	return IRQ_HANDLED;
+}
+
+static void wl1251_enable_line_irq(struct wl1251 *wl)
+{
+	return enable_irq(wl->irq);
+}
+
+static void wl1251_disable_line_irq(struct wl1251 *wl)
+{
+	return disable_irq(wl->irq);
+}
+
+static void wl1251_sdio_set_power(bool enable)
+{
+}
+
+static struct wl1251_if_operations wl1251_sdio_ops = {
+	.read = wl1251_sdio_read,
+	.write = wl1251_sdio_write,
+	.write_elp = wl1251_sdio_write_elp,
+	.read_elp = wl1251_sdio_read_elp,
+	.reset = wl1251_sdio_reset,
+};
+
+static int wl1251_platform_probe(struct platform_device *pdev)
+{
+	if (pdev->id != -1) {
+		wl1251_error("can only handle single device");
+		return -ENODEV;
+	}
+
+	wl12xx_board_data = pdev->dev.platform_data;
+	return 0;
+}
+
+/*
+ * Dummy platform_driver for passing platform_data to this driver,
+ * until we have a way to pass this through SDIO subsystem or
+ * some other way.
+ */
+static struct platform_driver wl1251_platform_driver = {
+	.driver = {
+		.name	= "wl1251_data",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= wl1251_platform_probe,
+};
+
+static int wl1251_sdio_probe(struct sdio_func *func,
+			     const struct sdio_device_id *id)
+{
+	int ret;
+	struct wl1251 *wl;
+	struct ieee80211_hw *hw;
+	struct wl1251_sdio *wl_sdio;
+
+	hw = wl1251_alloc_hw();
+	if (IS_ERR(hw))
+		return PTR_ERR(hw);
+
+	wl = hw->priv;
+
+	wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL);
+	if (wl_sdio == NULL) {
+		ret = -ENOMEM;
+		goto out_free_hw;
+	}
+
+	sdio_claim_host(func);
+	ret = sdio_enable_func(func);
+	if (ret)
+		goto release;
+
+	sdio_set_block_size(func, 512);
+	sdio_release_host(func);
+
+	SET_IEEE80211_DEV(hw, &func->dev);
+	wl_sdio->func = func;
+	wl->if_priv = wl_sdio;
+	wl->if_ops = &wl1251_sdio_ops;
+	wl->set_power = wl1251_sdio_set_power;
+
+	if (wl12xx_board_data != NULL) {
+		wl->set_power = wl12xx_board_data->set_power;
+		wl->irq = wl12xx_board_data->irq;
+		wl->use_eeprom = wl12xx_board_data->use_eeprom;
+	}
+
+	if (wl->irq) {
+		ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
+		if (ret < 0) {
+			wl1251_error("request_irq() failed: %d", ret);
+			goto disable;
+		}
+
+		set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
+		disable_irq(wl->irq);
+
+		wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
+		wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
+
+		wl1251_info("using dedicated interrupt line");
+	} else {
+		wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq;
+		wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq;
+
+		wl1251_info("using SDIO interrupt");
+	}
+
+	ret = wl1251_init_ieee80211(wl);
+	if (ret)
+		goto out_free_irq;
+
+	sdio_set_drvdata(func, wl);
+	return ret;
+
+out_free_irq:
+	if (wl->irq)
+		free_irq(wl->irq, wl);
+disable:
+	sdio_claim_host(func);
+	sdio_disable_func(func);
+release:
+	sdio_release_host(func);
+	kfree(wl_sdio);
+out_free_hw:
+	wl1251_free_hw(wl);
+	return ret;
+}
+
+static void __devexit wl1251_sdio_remove(struct sdio_func *func)
+{
+	struct wl1251 *wl = sdio_get_drvdata(func);
+	struct wl1251_sdio *wl_sdio = wl->if_priv;
+
+	if (wl->irq)
+		free_irq(wl->irq, wl);
+	kfree(wl_sdio);
+	wl1251_free_hw(wl);
+
+	sdio_claim_host(func);
+	sdio_release_irq(func);
+	sdio_disable_func(func);
+	sdio_release_host(func);
+}
+
+static struct sdio_driver wl1251_sdio_driver = {
+	.name		= "wl1251_sdio",
+	.id_table	= wl1251_devices,
+	.probe		= wl1251_sdio_probe,
+	.remove		= __devexit_p(wl1251_sdio_remove),
+};
+
+static int __init wl1251_sdio_init(void)
+{
+	int err;
+
+	err = platform_driver_register(&wl1251_platform_driver);
+	if (err) {
+		wl1251_error("failed to register platform driver: %d", err);
+		return err;
+	}
+
+	err = sdio_register_driver(&wl1251_sdio_driver);
+	if (err)
+		wl1251_error("failed to register sdio driver: %d", err);
+	return err;
+}
+
+static void __exit wl1251_sdio_exit(void)
+{
+	sdio_unregister_driver(&wl1251_sdio_driver);
+	platform_driver_unregister(&wl1251_platform_driver);
+	wl1251_notice("unloaded");
+}
+
+module_init(wl1251_sdio_init);
+module_exit(wl1251_sdio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c
new file mode 100644
index 0000000..88fa8e6
--- /dev/null
+++ b/drivers/net/wireless/wl1251/spi.c
@@ -0,0 +1,346 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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/irq.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/crc7.h>
+#include <linux/spi/spi.h>
+#include <linux/wl12xx.h>
+
+#include "wl1251.h"
+#include "reg.h"
+#include "spi.h"
+
+static irqreturn_t wl1251_irq(int irq, void *cookie)
+{
+	struct wl1251 *wl;
+
+	wl1251_debug(DEBUG_IRQ, "IRQ");
+
+	wl = cookie;
+
+	ieee80211_queue_work(wl->hw, &wl->irq_work);
+
+	return IRQ_HANDLED;
+}
+
+static struct spi_device *wl_to_spi(struct wl1251 *wl)
+{
+	return wl->if_priv;
+}
+
+static void wl1251_spi_reset(struct wl1251 *wl)
+{
+	u8 *cmd;
+	struct spi_transfer t;
+	struct spi_message m;
+
+	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
+	if (!cmd) {
+		wl1251_error("could not allocate cmd for spi reset");
+		return;
+	}
+
+	memset(&t, 0, sizeof(t));
+	spi_message_init(&m);
+
+	memset(cmd, 0xff, WSPI_INIT_CMD_LEN);
+
+	t.tx_buf = cmd;
+	t.len = WSPI_INIT_CMD_LEN;
+	spi_message_add_tail(&t, &m);
+
+	spi_sync(wl_to_spi(wl), &m);
+
+	wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
+}
+
+static void wl1251_spi_wake(struct wl1251 *wl)
+{
+	u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
+	struct spi_transfer t;
+	struct spi_message m;
+
+	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
+	if (!cmd) {
+		wl1251_error("could not allocate cmd for spi init");
+		return;
+	}
+
+	memset(crc, 0, sizeof(crc));
+	memset(&t, 0, sizeof(t));
+	spi_message_init(&m);
+
+	/*
+	 * Set WSPI_INIT_COMMAND
+	 * the data is being send from the MSB to LSB
+	 */
+	cmd[2] = 0xff;
+	cmd[3] = 0xff;
+	cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
+	cmd[0] = 0;
+	cmd[7] = 0;
+	cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
+	cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
+
+	if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
+		cmd[5] |=  WSPI_INIT_CMD_DIS_FIXEDBUSY;
+	else
+		cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
+
+	cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
+		| WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
+
+	crc[0] = cmd[1];
+	crc[1] = cmd[0];
+	crc[2] = cmd[7];
+	crc[3] = cmd[6];
+	crc[4] = cmd[5];
+
+	cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
+	cmd[4] |= WSPI_INIT_CMD_END;
+
+	t.tx_buf = cmd;
+	t.len = WSPI_INIT_CMD_LEN;
+	spi_message_add_tail(&t, &m);
+
+	spi_sync(wl_to_spi(wl), &m);
+
+	wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
+}
+
+static void wl1251_spi_reset_wake(struct wl1251 *wl)
+{
+	wl1251_spi_reset(wl);
+	wl1251_spi_wake(wl);
+}
+
+static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
+			    size_t len)
+{
+	struct spi_transfer t[3];
+	struct spi_message m;
+	u8 *busy_buf;
+	u32 *cmd;
+
+	cmd = &wl->buffer_cmd;
+	busy_buf = wl->buffer_busyword;
+
+	*cmd = 0;
+	*cmd |= WSPI_CMD_READ;
+	*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
+	*cmd |= addr & WSPI_CMD_BYTE_ADDR;
+
+	spi_message_init(&m);
+	memset(t, 0, sizeof(t));
+
+	t[0].tx_buf = cmd;
+	t[0].len = 4;
+	spi_message_add_tail(&t[0], &m);
+
+	/* Busy and non busy words read */
+	t[1].rx_buf = busy_buf;
+	t[1].len = WL1251_BUSY_WORD_LEN;
+	spi_message_add_tail(&t[1], &m);
+
+	t[2].rx_buf = buf;
+	t[2].len = len;
+	spi_message_add_tail(&t[2], &m);
+
+	spi_sync(wl_to_spi(wl), &m);
+
+	/* FIXME: check busy words */
+
+	wl1251_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
+	wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
+}
+
+static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
+			     size_t len)
+{
+	struct spi_transfer t[2];
+	struct spi_message m;
+	u32 *cmd;
+
+	cmd = &wl->buffer_cmd;
+
+	*cmd = 0;
+	*cmd |= WSPI_CMD_WRITE;
+	*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
+	*cmd |= addr & WSPI_CMD_BYTE_ADDR;
+
+	spi_message_init(&m);
+	memset(t, 0, sizeof(t));
+
+	t[0].tx_buf = cmd;
+	t[0].len = sizeof(*cmd);
+	spi_message_add_tail(&t[0], &m);
+
+	t[1].tx_buf = buf;
+	t[1].len = len;
+	spi_message_add_tail(&t[1], &m);
+
+	spi_sync(wl_to_spi(wl), &m);
+
+	wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
+	wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
+}
+
+static void wl1251_spi_enable_irq(struct wl1251 *wl)
+{
+	return enable_irq(wl->irq);
+}
+
+static void wl1251_spi_disable_irq(struct wl1251 *wl)
+{
+	return disable_irq(wl->irq);
+}
+
+static const struct wl1251_if_operations wl1251_spi_ops = {
+	.read = wl1251_spi_read,
+	.write = wl1251_spi_write,
+	.reset = wl1251_spi_reset_wake,
+	.enable_irq = wl1251_spi_enable_irq,
+	.disable_irq = wl1251_spi_disable_irq,
+};
+
+static int __devinit wl1251_spi_probe(struct spi_device *spi)
+{
+	struct wl12xx_platform_data *pdata;
+	struct ieee80211_hw *hw;
+	struct wl1251 *wl;
+	int ret;
+
+	pdata = spi->dev.platform_data;
+	if (!pdata) {
+		wl1251_error("no platform data");
+		return -ENODEV;
+	}
+
+	hw = wl1251_alloc_hw();
+	if (IS_ERR(hw))
+		return PTR_ERR(hw);
+
+	wl = hw->priv;
+
+	SET_IEEE80211_DEV(hw, &spi->dev);
+	dev_set_drvdata(&spi->dev, wl);
+	wl->if_priv = spi;
+	wl->if_ops = &wl1251_spi_ops;
+
+	/* This is the only SPI value that we need to set here, the rest
+	 * comes from the board-peripherals file */
+	spi->bits_per_word = 32;
+
+	ret = spi_setup(spi);
+	if (ret < 0) {
+		wl1251_error("spi_setup failed");
+		goto out_free;
+	}
+
+	wl->set_power = pdata->set_power;
+	if (!wl->set_power) {
+		wl1251_error("set power function missing in platform data");
+		return -ENODEV;
+	}
+
+	wl->irq = spi->irq;
+	if (wl->irq < 0) {
+		wl1251_error("irq missing in platform data");
+		return -ENODEV;
+	}
+
+	wl->use_eeprom = pdata->use_eeprom;
+
+	ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
+	if (ret < 0) {
+		wl1251_error("request_irq() failed: %d", ret);
+		goto out_free;
+	}
+
+	set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
+
+	disable_irq(wl->irq);
+
+	ret = wl1251_init_ieee80211(wl);
+	if (ret)
+		goto out_irq;
+
+	return 0;
+
+ out_irq:
+	free_irq(wl->irq, wl);
+
+ out_free:
+	ieee80211_free_hw(hw);
+
+	return ret;
+}
+
+static int __devexit wl1251_spi_remove(struct spi_device *spi)
+{
+	struct wl1251 *wl = dev_get_drvdata(&spi->dev);
+
+	free_irq(wl->irq, wl);
+	wl1251_free_hw(wl);
+
+	return 0;
+}
+
+static struct spi_driver wl1251_spi_driver = {
+	.driver = {
+		.name		= DRIVER_NAME,
+		.bus		= &spi_bus_type,
+		.owner		= THIS_MODULE,
+	},
+
+	.probe		= wl1251_spi_probe,
+	.remove		= __devexit_p(wl1251_spi_remove),
+};
+
+static int __init wl1251_spi_init(void)
+{
+	int ret;
+
+	ret = spi_register_driver(&wl1251_spi_driver);
+	if (ret < 0) {
+		wl1251_error("failed to register spi driver: %d", ret);
+		goto out;
+	}
+
+out:
+	return ret;
+}
+
+static void __exit wl1251_spi_exit(void)
+{
+	spi_unregister_driver(&wl1251_spi_driver);
+
+	wl1251_notice("unloaded");
+}
+
+module_init(wl1251_spi_init);
+module_exit(wl1251_spi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
+MODULE_ALIAS("spi:wl1251");
diff --git a/drivers/net/wireless/wl1251/spi.h b/drivers/net/wireless/wl1251/spi.h
new file mode 100644
index 0000000..16d5069
--- /dev/null
+++ b/drivers/net/wireless/wl1251/spi.h
@@ -0,0 +1,59 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 __WL1251_SPI_H__
+#define __WL1251_SPI_H__
+
+#include "cmd.h"
+#include "acx.h"
+#include "reg.h"
+
+#define WSPI_CMD_READ                 0x40000000
+#define WSPI_CMD_WRITE                0x00000000
+#define WSPI_CMD_FIXED                0x20000000
+#define WSPI_CMD_BYTE_LENGTH          0x1FFE0000
+#define WSPI_CMD_BYTE_LENGTH_OFFSET   17
+#define WSPI_CMD_BYTE_ADDR            0x0001FFFF
+
+#define WSPI_INIT_CMD_CRC_LEN       5
+
+#define WSPI_INIT_CMD_START         0x00
+#define WSPI_INIT_CMD_TX            0x40
+/* the extra bypass bit is sampled by the TNET as '1' */
+#define WSPI_INIT_CMD_BYPASS_BIT    0x80
+#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07
+#define WSPI_INIT_CMD_EN_FIXEDBUSY  0x80
+#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00
+#define WSPI_INIT_CMD_IOD           0x40
+#define WSPI_INIT_CMD_IP            0x20
+#define WSPI_INIT_CMD_CS            0x10
+#define WSPI_INIT_CMD_WS            0x08
+#define WSPI_INIT_CMD_WSPI          0x01
+#define WSPI_INIT_CMD_END           0x01
+
+#define WSPI_INIT_CMD_LEN           8
+
+#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \
+		((WL1251_BUSY_WORD_LEN - 4) / sizeof(u32))
+#define HW_ACCESS_WSPI_INIT_CMD_MASK  0
+
+#endif /* __WL1251_SPI_H__ */
diff --git a/drivers/net/wireless/wl1251/tx.c b/drivers/net/wireless/wl1251/tx.c
new file mode 100644
index 0000000..554b4f9
--- /dev/null
+++ b/drivers/net/wireless/wl1251/tx.c
@@ -0,0 +1,570 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "wl1251.h"
+#include "reg.h"
+#include "tx.h"
+#include "ps.h"
+#include "io.h"
+
+static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count)
+{
+	int used, data_in_count;
+
+	data_in_count = wl->data_in_count;
+
+	if (data_in_count < data_out_count)
+		/* data_in_count has wrapped */
+		data_in_count += TX_STATUS_DATA_OUT_COUNT_MASK + 1;
+
+	used = data_in_count - data_out_count;
+
+	WARN_ON(used < 0);
+	WARN_ON(used > DP_TX_PACKET_RING_CHUNK_NUM);
+
+	if (used >= DP_TX_PACKET_RING_CHUNK_NUM)
+		return true;
+	else
+		return false;
+}
+
+static int wl1251_tx_path_status(struct wl1251 *wl)
+{
+	u32 status, addr, data_out_count;
+	bool busy;
+
+	addr = wl->data_path->tx_control_addr;
+	status = wl1251_mem_read32(wl, addr);
+	data_out_count = status & TX_STATUS_DATA_OUT_COUNT_MASK;
+	busy = wl1251_tx_double_buffer_busy(wl, data_out_count);
+
+	if (busy)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int wl1251_tx_id(struct wl1251 *wl, struct sk_buff *skb)
+{
+	int i;
+
+	for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
+		if (wl->tx_frames[i] == NULL) {
+			wl->tx_frames[i] = skb;
+			return i;
+		}
+
+	return -EBUSY;
+}
+
+static void wl1251_tx_control(struct tx_double_buffer_desc *tx_hdr,
+			      struct ieee80211_tx_info *control, u16 fc)
+{
+	*(u16 *)&tx_hdr->control = 0;
+
+	tx_hdr->control.rate_policy = 0;
+
+	/* 802.11 packets */
+	tx_hdr->control.packet_type = 0;
+
+	if (control->flags & IEEE80211_TX_CTL_NO_ACK)
+		tx_hdr->control.ack_policy = 1;
+
+	tx_hdr->control.tx_complete = 1;
+
+	if ((fc & IEEE80211_FTYPE_DATA) &&
+	    ((fc & IEEE80211_STYPE_QOS_DATA) ||
+	     (fc & IEEE80211_STYPE_QOS_NULLFUNC)))
+		tx_hdr->control.qos = 1;
+}
+
+/* RSN + MIC = 8 + 8 = 16 bytes (worst case - AES). */
+#define MAX_MSDU_SECURITY_LENGTH      16
+#define MAX_MPDU_SECURITY_LENGTH      16
+#define WLAN_QOS_HDR_LEN              26
+#define MAX_MPDU_HEADER_AND_SECURITY  (MAX_MPDU_SECURITY_LENGTH + \
+				       WLAN_QOS_HDR_LEN)
+#define HW_BLOCK_SIZE                 252
+static void wl1251_tx_frag_block_num(struct tx_double_buffer_desc *tx_hdr)
+{
+	u16 payload_len, frag_threshold, mem_blocks;
+	u16 num_mpdus, mem_blocks_per_frag;
+
+	frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+	tx_hdr->frag_threshold = cpu_to_le16(frag_threshold);
+
+	payload_len = le16_to_cpu(tx_hdr->length) + MAX_MSDU_SECURITY_LENGTH;
+
+	if (payload_len > frag_threshold) {
+		mem_blocks_per_frag =
+			((frag_threshold + MAX_MPDU_HEADER_AND_SECURITY) /
+			 HW_BLOCK_SIZE) + 1;
+		num_mpdus = payload_len / frag_threshold;
+		mem_blocks = num_mpdus * mem_blocks_per_frag;
+		payload_len -= num_mpdus * frag_threshold;
+		num_mpdus++;
+
+	} else {
+		mem_blocks_per_frag = 0;
+		mem_blocks = 0;
+		num_mpdus = 1;
+	}
+
+	mem_blocks += (payload_len / HW_BLOCK_SIZE) + 1;
+
+	if (num_mpdus > 1)
+		mem_blocks += min(num_mpdus, mem_blocks_per_frag);
+
+	tx_hdr->num_mem_blocks = mem_blocks;
+}
+
+static int wl1251_tx_fill_hdr(struct wl1251 *wl, struct sk_buff *skb,
+			      struct ieee80211_tx_info *control)
+{
+	struct tx_double_buffer_desc *tx_hdr;
+	struct ieee80211_rate *rate;
+	int id;
+	u16 fc;
+
+	if (!skb)
+		return -EINVAL;
+
+	id = wl1251_tx_id(wl, skb);
+	if (id < 0)
+		return id;
+
+	fc = *(u16 *)skb->data;
+	tx_hdr = (struct tx_double_buffer_desc *) skb_push(skb,
+							   sizeof(*tx_hdr));
+
+	tx_hdr->length = cpu_to_le16(skb->len - sizeof(*tx_hdr));
+	rate = ieee80211_get_tx_rate(wl->hw, control);
+	tx_hdr->rate = cpu_to_le16(rate->hw_value);
+	tx_hdr->expiry_time = cpu_to_le32(1 << 16);
+	tx_hdr->id = id;
+
+	tx_hdr->xmit_queue = wl1251_tx_get_queue(skb_get_queue_mapping(skb));
+
+	wl1251_tx_control(tx_hdr, control, fc);
+	wl1251_tx_frag_block_num(tx_hdr);
+
+	return 0;
+}
+
+/* We copy the packet to the target */
+static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb,
+				 struct ieee80211_tx_info *control)
+{
+	struct tx_double_buffer_desc *tx_hdr;
+	int len;
+	u32 addr;
+
+	if (!skb)
+		return -EINVAL;
+
+	tx_hdr = (struct tx_double_buffer_desc *) skb->data;
+
+	if (control->control.hw_key &&
+	    control->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+		int hdrlen;
+		__le16 fc;
+		u16 length;
+		u8 *pos;
+
+		fc = *(__le16 *)(skb->data + sizeof(*tx_hdr));
+		length = le16_to_cpu(tx_hdr->length) + WL1251_TKIP_IV_SPACE;
+		tx_hdr->length = cpu_to_le16(length);
+
+		hdrlen = ieee80211_hdrlen(fc);
+
+		pos = skb_push(skb, WL1251_TKIP_IV_SPACE);
+		memmove(pos, pos + WL1251_TKIP_IV_SPACE,
+			sizeof(*tx_hdr) + hdrlen);
+	}
+
+	/* Revisit. This is a workaround for getting non-aligned packets.
+	   This happens at least with EAPOL packets from the user space.
+	   Our DMA requires packets to be aligned on a 4-byte boundary.
+	*/
+	if (unlikely((long)skb->data & 0x03)) {
+		int offset = (4 - (long)skb->data) & 0x03;
+		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;
+
+			/* align the buffer on a 4-byte boundary */
+			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;
+		}
+	}
+
+	/* Our skb->data at this point includes the HW header */
+	len = WL1251_TX_ALIGN(skb->len);
+
+	if (wl->data_in_count & 0x1)
+		addr = wl->data_path->tx_packet_ring_addr +
+			wl->data_path->tx_packet_ring_chunk_size;
+	else
+		addr = wl->data_path->tx_packet_ring_addr;
+
+	wl1251_mem_write(wl, addr, skb->data, len);
+
+	wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x "
+		     "queue %d", tx_hdr->id, skb, tx_hdr->length,
+		     tx_hdr->rate, tx_hdr->xmit_queue);
+
+	return 0;
+}
+
+static void wl1251_tx_trigger(struct wl1251 *wl)
+{
+	u32 data, addr;
+
+	if (wl->data_in_count & 0x1) {
+		addr = ACX_REG_INTERRUPT_TRIG_H;
+		data = INTR_TRIG_TX_PROC1;
+	} else {
+		addr = ACX_REG_INTERRUPT_TRIG;
+		data = INTR_TRIG_TX_PROC0;
+	}
+
+	wl1251_reg_write32(wl, addr, data);
+
+	/* Bumping data in */
+	wl->data_in_count = (wl->data_in_count + 1) &
+		TX_STATUS_DATA_OUT_COUNT_MASK;
+}
+
+/* caller must hold wl->mutex */
+static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *info;
+	int ret = 0;
+	u8 idx;
+
+	info = IEEE80211_SKB_CB(skb);
+
+	if (info->control.hw_key) {
+		idx = info->control.hw_key->hw_key_idx;
+		if (unlikely(wl->default_key != idx)) {
+			ret = wl1251_acx_default_key(wl, idx);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	ret = wl1251_tx_path_status(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_tx_fill_hdr(wl, skb, info);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1251_tx_send_packet(wl, skb, info);
+	if (ret < 0)
+		return ret;
+
+	wl1251_tx_trigger(wl);
+
+	return ret;
+}
+
+void wl1251_tx_work(struct work_struct *work)
+{
+	struct wl1251 *wl = container_of(work, struct wl1251, tx_work);
+	struct sk_buff *skb;
+	bool woken_up = false;
+	int ret;
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state == WL1251_STATE_OFF))
+		goto out;
+
+	while ((skb = skb_dequeue(&wl->tx_queue))) {
+		if (!woken_up) {
+			ret = wl1251_ps_elp_wakeup(wl);
+			if (ret < 0)
+				goto out;
+			woken_up = true;
+		}
+
+		ret = wl1251_tx_frame(wl, skb);
+		if (ret == -EBUSY) {
+			skb_queue_head(&wl->tx_queue, skb);
+			goto out;
+		} else if (ret < 0) {
+			dev_kfree_skb(skb);
+			goto out;
+		}
+	}
+
+out:
+	if (woken_up)
+		wl1251_ps_elp_sleep(wl);
+
+	mutex_unlock(&wl->mutex);
+}
+
+static const char *wl1251_tx_parse_status(u8 status)
+{
+	/* 8 bit status field, one character per bit plus null */
+	static char buf[9];
+	int i = 0;
+
+	memset(buf, 0, sizeof(buf));
+
+	if (status & TX_DMA_ERROR)
+		buf[i++] = 'm';
+	if (status & TX_DISABLED)
+		buf[i++] = 'd';
+	if (status & TX_RETRY_EXCEEDED)
+		buf[i++] = 'r';
+	if (status & TX_TIMEOUT)
+		buf[i++] = 't';
+	if (status & TX_KEY_NOT_FOUND)
+		buf[i++] = 'k';
+	if (status & TX_ENCRYPT_FAIL)
+		buf[i++] = 'e';
+	if (status & TX_UNAVAILABLE_PRIORITY)
+		buf[i++] = 'p';
+
+	/* bit 0 is unused apparently */
+
+	return buf;
+}
+
+static void wl1251_tx_packet_cb(struct wl1251 *wl,
+				struct tx_result *result)
+{
+	struct ieee80211_tx_info *info;
+	struct sk_buff *skb;
+	int hdrlen, ret;
+	u8 *frame;
+
+	skb = wl->tx_frames[result->id];
+	if (skb == NULL) {
+		wl1251_error("SKB for packet %d is NULL", result->id);
+		return;
+	}
+
+	info = IEEE80211_SKB_CB(skb);
+
+	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+	    (result->status == TX_SUCCESS))
+		info->flags |= IEEE80211_TX_STAT_ACK;
+
+	info->status.rates[0].count = result->ack_failures + 1;
+	wl->stats.retry_count += result->ack_failures;
+
+	/*
+	 * We have to remove our private TX header before pushing
+	 * the skb back to mac80211.
+	 */
+	frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc));
+	if (info->control.hw_key &&
+	    info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+		hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+		memmove(frame + WL1251_TKIP_IV_SPACE, frame, hdrlen);
+		skb_pull(skb, WL1251_TKIP_IV_SPACE);
+	}
+
+	wl1251_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x"
+		     " status 0x%x (%s)",
+		     result->id, skb, result->ack_failures, result->rate,
+		     result->status, wl1251_tx_parse_status(result->status));
+
+
+	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;
+	struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr;
+	unsigned long flags;
+
+	if (unlikely(wl->state != WL1251_STATE_ON))
+		return;
+
+	/* First we read the result */
+	wl1251_mem_read(wl, wl->data_path->tx_complete_addr,
+			    result, sizeof(result));
+
+	result_index = wl->next_tx_complete;
+
+	for (i = 0; i < ARRAY_SIZE(result); i++) {
+		result_ptr = &result[result_index];
+
+		if (result_ptr->done_1 == 1 &&
+		    result_ptr->done_2 == 1) {
+			wl1251_tx_packet_cb(wl, result_ptr);
+
+			result_ptr->done_1 = 0;
+			result_ptr->done_2 = 0;
+
+			result_index = (result_index + 1) &
+				(FW_TX_CMPLT_BLOCK_SIZE - 1);
+			num_complete++;
+		} else {
+			break;
+		}
+	}
+
+	if (wl->tx_queue_stopped
+	    &&
+	    skb_queue_len(&wl->tx_queue) <= WL1251_TX_QUEUE_LOW_WATERMARK){
+
+		/* firmware buffer 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 */
+	if (num_complete) {
+		/*
+		 * If we've wrapped, we have to clear
+		 * the results in 2 steps.
+		 */
+		if (result_index > wl->next_tx_complete) {
+			/* Only 1 write is needed */
+			wl1251_mem_write(wl,
+					 wl->data_path->tx_complete_addr +
+					 (wl->next_tx_complete *
+					  sizeof(struct tx_result)),
+					 &result[wl->next_tx_complete],
+					 num_complete *
+					 sizeof(struct tx_result));
+
+
+		} else if (result_index < wl->next_tx_complete) {
+			/* 2 writes are needed */
+			wl1251_mem_write(wl,
+					 wl->data_path->tx_complete_addr +
+					 (wl->next_tx_complete *
+					  sizeof(struct tx_result)),
+					 &result[wl->next_tx_complete],
+					 (FW_TX_CMPLT_BLOCK_SIZE -
+					  wl->next_tx_complete) *
+					 sizeof(struct tx_result));
+
+			wl1251_mem_write(wl,
+					 wl->data_path->tx_complete_addr,
+					 result,
+					 (num_complete -
+					  FW_TX_CMPLT_BLOCK_SIZE +
+					  wl->next_tx_complete) *
+					 sizeof(struct tx_result));
+
+		} else {
+			/* We have to write the whole array */
+			wl1251_mem_write(wl,
+					 wl->data_path->tx_complete_addr,
+					 result,
+					 FW_TX_CMPLT_BLOCK_SIZE *
+					 sizeof(struct tx_result));
+		}
+
+	}
+
+	wl->next_tx_complete = result_index;
+}
+
+/* caller must hold wl->mutex */
+void wl1251_tx_flush(struct wl1251 *wl)
+{
+	int i;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *info;
+
+	/* TX failure */
+/* 	control->flags = 0; FIXME */
+
+	while ((skb = skb_dequeue(&wl->tx_queue))) {
+		info = IEEE80211_SKB_CB(skb);
+
+		wl1251_debug(DEBUG_TX, "flushing skb 0x%p", skb);
+
+		if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
+				continue;
+
+		ieee80211_tx_status(wl->hw, skb);
+	}
+
+	for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
+		if (wl->tx_frames[i] != NULL) {
+			skb = wl->tx_frames[i];
+			info = IEEE80211_SKB_CB(skb);
+
+			if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
+				continue;
+
+			ieee80211_tx_status(wl->hw, skb);
+			wl->tx_frames[i] = NULL;
+		}
+}
diff --git a/drivers/net/wireless/wl1251/tx.h b/drivers/net/wireless/wl1251/tx.h
new file mode 100644
index 0000000..81338d3
--- /dev/null
+++ b/drivers/net/wireless/wl1251/tx.h
@@ -0,0 +1,231 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 __WL1251_TX_H__
+#define __WL1251_TX_H__
+
+#include <linux/bitops.h>
+#include "acx.h"
+
+/*
+ *
+ * TX PATH
+ *
+ * The Tx path uses a double buffer and a tx_control structure, each located
+ * at a fixed address in the device's memory. On startup, the host retrieves
+ * the pointers to these addresses. A double buffer allows for continuous data
+ * flow towards the device. The host keeps track of which buffer is available
+ * and alternates between these two buffers on a per packet basis.
+ *
+ * The size of each of the two buffers is large enough to hold the longest
+ * 802.3 packet - maximum size Ethernet packet + header + descriptor.
+ * TX complete indication will be received a-synchronously in a TX done cyclic
+ * buffer which is composed of 16 tx_result descriptors structures and is used
+ * in a cyclic manner.
+ *
+ * The TX (HOST) procedure is as follows:
+ * 1. Read the Tx path status, that will give the data_out_count.
+ * 2. goto 1, if not possible.
+ *    i.e. if data_in_count - data_out_count >= HwBuffer size (2 for double
+ *    buffer).
+ * 3. Copy the packet (preceded by double_buffer_desc), if possible.
+ *    i.e. if data_in_count - data_out_count < HwBuffer size (2 for double
+ *    buffer).
+ * 4. increment data_in_count.
+ * 5. Inform the firmware by generating a firmware internal interrupt.
+ * 6. FW will increment data_out_count after it reads the buffer.
+ *
+ * The TX Complete procedure:
+ * 1. To get a TX complete indication the host enables the tx_complete flag in
+ *    the TX descriptor Structure.
+ * 2. For each packet with a Tx Complete field set, the firmware adds the
+ *    transmit results to the cyclic buffer (txDoneRing) and sets both done_1
+ *    and done_2 to 1 to indicate driver ownership.
+ * 3. The firmware sends a Tx Complete interrupt to the host to trigger the
+ *    host to process the new data. Note: interrupt will be send per packet if
+ *    TX complete indication was requested in tx_control or per crossing
+ *    aggregation threshold.
+ * 4. After receiving the Tx Complete interrupt, the host reads the
+ *    TxDescriptorDone information in a cyclic manner and clears both done_1
+ *    and done_2 fields.
+ *
+ */
+
+#define TX_COMPLETE_REQUIRED_BIT	0x80
+#define TX_STATUS_DATA_OUT_COUNT_MASK   0xf
+
+#define WL1251_TX_ALIGN_TO 4
+#define WL1251_TX_ALIGN(len) (((len) + WL1251_TX_ALIGN_TO - 1) & \
+			     ~(WL1251_TX_ALIGN_TO - 1))
+#define WL1251_TKIP_IV_SPACE 4
+
+struct tx_control {
+	/* Rate Policy (class) index */
+	unsigned rate_policy:3;
+
+	/* When set, no ack policy is expected */
+	unsigned ack_policy:1;
+
+	/*
+	 * Packet type:
+	 * 0 -> 802.11
+	 * 1 -> 802.3
+	 * 2 -> IP
+	 * 3 -> raw codec
+	 */
+	unsigned packet_type:2;
+
+	/* If set, this is a QoS-Null or QoS-Data frame */
+	unsigned qos:1;
+
+	/*
+	 * If set, the target triggers the tx complete INT
+	 * upon frame sending completion.
+	 */
+	unsigned tx_complete:1;
+
+	/* 2 bytes padding before packet header */
+	unsigned xfer_pad:1;
+
+	unsigned reserved:7;
+} __packed;
+
+
+struct tx_double_buffer_desc {
+	/* Length of payload, including headers. */
+	__le16 length;
+
+	/*
+	 * A bit mask that specifies the initial rate to be used
+	 * Possible values are:
+	 * 0x0001 - 1Mbits
+	 * 0x0002 - 2Mbits
+	 * 0x0004 - 5.5Mbits
+	 * 0x0008 - 6Mbits
+	 * 0x0010 - 9Mbits
+	 * 0x0020 - 11Mbits
+	 * 0x0040 - 12Mbits
+	 * 0x0080 - 18Mbits
+	 * 0x0100 - 22Mbits
+	 * 0x0200 - 24Mbits
+	 * 0x0400 - 36Mbits
+	 * 0x0800 - 48Mbits
+	 * 0x1000 - 54Mbits
+	 */
+	__le16 rate;
+
+	/* Time in us that a packet can spend in the target */
+	__le32 expiry_time;
+
+	/* index of the TX queue used for this packet */
+	u8 xmit_queue;
+
+	/* Used to identify a packet */
+	u8 id;
+
+	struct tx_control control;
+
+	/*
+	 * The FW should cut the packet into fragments
+	 * of this size.
+	 */
+	__le16 frag_threshold;
+
+	/* Numbers of HW queue blocks to be allocated */
+	u8 num_mem_blocks;
+
+	u8 reserved;
+} __packed;
+
+enum {
+	TX_SUCCESS              = 0,
+	TX_DMA_ERROR            = BIT(7),
+	TX_DISABLED             = BIT(6),
+	TX_RETRY_EXCEEDED       = BIT(5),
+	TX_TIMEOUT              = BIT(4),
+	TX_KEY_NOT_FOUND        = BIT(3),
+	TX_ENCRYPT_FAIL         = BIT(2),
+	TX_UNAVAILABLE_PRIORITY = BIT(1),
+};
+
+struct tx_result {
+	/*
+	 * Ownership synchronization between the host and
+	 * the firmware. If done_1 and done_2 are cleared,
+	 * owned by the FW (no info ready).
+	 */
+	u8 done_1;
+
+	/* same as double_buffer_desc->id */
+	u8 id;
+
+	/*
+	 * Total air access duration consumed by this
+	 * packet, including all retries and overheads.
+	 */
+	u16 medium_usage;
+
+	/* Total media delay (from 1st EDCA AIFS counter until TX Complete). */
+	u32 medium_delay;
+
+	/* Time between host xfer and tx complete */
+	u32 fw_hnadling_time;
+
+	/* The LS-byte of the last TKIP sequence number. */
+	u8 lsb_seq_num;
+
+	/* Retry count */
+	u8 ack_failures;
+
+	/* At which rate we got a ACK */
+	u16 rate;
+
+	u16 reserved;
+
+	/* TX_* */
+	u8 status;
+
+	/* See done_1 */
+	u8 done_2;
+} __packed;
+
+static inline int wl1251_tx_get_queue(int queue)
+{
+	switch (queue) {
+	case 0:
+		return QOS_AC_VO;
+	case 1:
+		return QOS_AC_VI;
+	case 2:
+		return QOS_AC_BE;
+	case 3:
+		return QOS_AC_BK;
+	default:
+		return QOS_AC_BE;
+	}
+}
+
+void wl1251_tx_work(struct work_struct *work);
+void wl1251_tx_complete(struct wl1251 *wl);
+void wl1251_tx_flush(struct wl1251 *wl);
+
+#endif
diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h
new file mode 100644
index 0000000..e113d4c
--- /dev/null
+++ b/drivers/net/wireless/wl1251/wl1251.h
@@ -0,0 +1,433 @@
+/*
+ * This file is part of wl1251
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1251_H__
+#define __WL1251_H__
+
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/bitops.h>
+#include <net/mac80211.h>
+
+#define DRIVER_NAME "wl1251"
+#define DRIVER_PREFIX DRIVER_NAME ": "
+
+enum {
+	DEBUG_NONE	= 0,
+	DEBUG_IRQ	= BIT(0),
+	DEBUG_SPI	= BIT(1),
+	DEBUG_BOOT	= BIT(2),
+	DEBUG_MAILBOX	= BIT(3),
+	DEBUG_NETLINK	= BIT(4),
+	DEBUG_EVENT	= BIT(5),
+	DEBUG_TX	= BIT(6),
+	DEBUG_RX	= BIT(7),
+	DEBUG_SCAN	= BIT(8),
+	DEBUG_CRYPT	= BIT(9),
+	DEBUG_PSM	= BIT(10),
+	DEBUG_MAC80211	= BIT(11),
+	DEBUG_CMD	= BIT(12),
+	DEBUG_ACX	= BIT(13),
+	DEBUG_ALL	= ~0,
+};
+
+#define DEBUG_LEVEL (DEBUG_NONE)
+
+#define DEBUG_DUMP_LIMIT 1024
+
+#define wl1251_error(fmt, arg...) \
+	printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg)
+
+#define wl1251_warning(fmt, arg...) \
+	printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg)
+
+#define wl1251_notice(fmt, arg...) \
+	printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg)
+
+#define wl1251_info(fmt, arg...) \
+	printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg)
+
+#define wl1251_debug(level, fmt, arg...) \
+	do { \
+		if (level & DEBUG_LEVEL) \
+			printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \
+	} while (0)
+
+#define wl1251_dump(level, prefix, buf, len)	\
+	do { \
+		if (level & DEBUG_LEVEL) \
+			print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
+				       DUMP_PREFIX_OFFSET, 16, 1,	\
+				       buf,				\
+				       min_t(size_t, len, DEBUG_DUMP_LIMIT), \
+				       0);				\
+	} while (0)
+
+#define wl1251_dump_ascii(level, prefix, buf, len)	\
+	do { \
+		if (level & DEBUG_LEVEL) \
+			print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
+				       DUMP_PREFIX_OFFSET, 16, 1,	\
+				       buf,				\
+				       min_t(size_t, len, DEBUG_DUMP_LIMIT), \
+				       true);				\
+	} while (0)
+
+#define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN |	\
+				  CFG_BSSID_FILTER_EN)
+
+#define WL1251_DEFAULT_RX_FILTER (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 WL1251_BUSY_WORD_LEN 8
+
+struct boot_attr {
+	u32 radio_type;
+	u8 mac_clock;
+	u8 arm_clock;
+	int firmware_debug;
+	u32 minor;
+	u32 major;
+	u32 bugfix;
+};
+
+enum wl1251_state {
+	WL1251_STATE_OFF,
+	WL1251_STATE_ON,
+	WL1251_STATE_PLT,
+};
+
+enum wl1251_partition_type {
+	PART_DOWN,
+	PART_WORK,
+	PART_DRPW,
+
+	PART_TABLE_LEN
+};
+
+struct wl1251_partition {
+	u32 size;
+	u32 start;
+};
+
+struct wl1251_partition_set {
+	struct wl1251_partition mem;
+	struct wl1251_partition reg;
+};
+
+struct wl1251;
+
+struct wl1251_stats {
+	struct acx_statistics *fw_stats;
+	unsigned long fw_stats_update;
+
+	unsigned int retry_count;
+	unsigned int excessive_retries;
+};
+
+struct wl1251_debugfs {
+	struct dentry *rootdir;
+	struct dentry *fw_statistics;
+
+	struct dentry *tx_internal_desc_overflow;
+
+	struct dentry *rx_out_of_mem;
+	struct dentry *rx_hdr_overflow;
+	struct dentry *rx_hw_stuck;
+	struct dentry *rx_dropped;
+	struct dentry *rx_fcs_err;
+	struct dentry *rx_xfr_hint_trig;
+	struct dentry *rx_path_reset;
+	struct dentry *rx_reset_counter;
+
+	struct dentry *dma_rx_requested;
+	struct dentry *dma_rx_errors;
+	struct dentry *dma_tx_requested;
+	struct dentry *dma_tx_errors;
+
+	struct dentry *isr_cmd_cmplt;
+	struct dentry *isr_fiqs;
+	struct dentry *isr_rx_headers;
+	struct dentry *isr_rx_mem_overflow;
+	struct dentry *isr_rx_rdys;
+	struct dentry *isr_irqs;
+	struct dentry *isr_tx_procs;
+	struct dentry *isr_decrypt_done;
+	struct dentry *isr_dma0_done;
+	struct dentry *isr_dma1_done;
+	struct dentry *isr_tx_exch_complete;
+	struct dentry *isr_commands;
+	struct dentry *isr_rx_procs;
+	struct dentry *isr_hw_pm_mode_changes;
+	struct dentry *isr_host_acknowledges;
+	struct dentry *isr_pci_pm;
+	struct dentry *isr_wakeups;
+	struct dentry *isr_low_rssi;
+
+	struct dentry *wep_addr_key_count;
+	struct dentry *wep_default_key_count;
+	/* skipping wep.reserved */
+	struct dentry *wep_key_not_found;
+	struct dentry *wep_decrypt_fail;
+	struct dentry *wep_packets;
+	struct dentry *wep_interrupt;
+
+	struct dentry *pwr_ps_enter;
+	struct dentry *pwr_elp_enter;
+	struct dentry *pwr_missing_bcns;
+	struct dentry *pwr_wake_on_host;
+	struct dentry *pwr_wake_on_timer_exp;
+	struct dentry *pwr_tx_with_ps;
+	struct dentry *pwr_tx_without_ps;
+	struct dentry *pwr_rcvd_beacons;
+	struct dentry *pwr_power_save_off;
+	struct dentry *pwr_enable_ps;
+	struct dentry *pwr_disable_ps;
+	struct dentry *pwr_fix_tsf_ps;
+	/* skipping cont_miss_bcns_spread for now */
+	struct dentry *pwr_rcvd_awake_beacons;
+
+	struct dentry *mic_rx_pkts;
+	struct dentry *mic_calc_failure;
+
+	struct dentry *aes_encrypt_fail;
+	struct dentry *aes_decrypt_fail;
+	struct dentry *aes_encrypt_packets;
+	struct dentry *aes_decrypt_packets;
+	struct dentry *aes_encrypt_interrupt;
+	struct dentry *aes_decrypt_interrupt;
+
+	struct dentry *event_heart_beat;
+	struct dentry *event_calibration;
+	struct dentry *event_rx_mismatch;
+	struct dentry *event_rx_mem_empty;
+	struct dentry *event_rx_pool;
+	struct dentry *event_oom_late;
+	struct dentry *event_phy_transmit_error;
+	struct dentry *event_tx_stuck;
+
+	struct dentry *ps_pspoll_timeouts;
+	struct dentry *ps_upsd_timeouts;
+	struct dentry *ps_upsd_max_sptime;
+	struct dentry *ps_upsd_max_apturn;
+	struct dentry *ps_pspoll_max_apturn;
+	struct dentry *ps_pspoll_utilization;
+	struct dentry *ps_upsd_utilization;
+
+	struct dentry *rxpipe_rx_prep_beacon_drop;
+	struct dentry *rxpipe_descr_host_int_trig_rx_data;
+	struct dentry *rxpipe_beacon_buffer_thres_host_int_trig_rx_data;
+	struct dentry *rxpipe_missed_beacon_host_int_trig_rx_data;
+	struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data;
+
+	struct dentry *tx_queue_len;
+	struct dentry *tx_queue_status;
+
+	struct dentry *retry_count;
+	struct dentry *excessive_retries;
+};
+
+struct wl1251_if_operations {
+	void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len);
+	void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len);
+	void (*read_elp)(struct wl1251 *wl, int addr, u32 *val);
+	void (*write_elp)(struct wl1251 *wl, int addr, u32 val);
+	void (*reset)(struct wl1251 *wl);
+	void (*enable_irq)(struct wl1251 *wl);
+	void (*disable_irq)(struct wl1251 *wl);
+};
+
+struct wl1251 {
+	struct ieee80211_hw *hw;
+	bool mac80211_registered;
+
+	void *if_priv;
+	const struct wl1251_if_operations *if_ops;
+
+	void (*set_power)(bool enable);
+	int irq;
+	bool use_eeprom;
+
+	spinlock_t wl_lock;
+
+	enum wl1251_state state;
+	struct mutex mutex;
+
+	int physical_mem_addr;
+	int physical_reg_addr;
+	int virtual_mem_addr;
+	int virtual_reg_addr;
+
+	int cmd_box_addr;
+	int event_box_addr;
+	struct boot_attr boot_attr;
+
+	u8 *fw;
+	size_t fw_len;
+	u8 *nvs;
+	size_t nvs_len;
+
+	u8 bssid[ETH_ALEN];
+	u8 mac_addr[ETH_ALEN];
+	u8 bss_type;
+	u8 listen_int;
+	int channel;
+
+	void *target_mem_map;
+	struct acx_data_path_params_resp *data_path;
+
+	/* Number of TX packets transferred to the FW, modulo 16 */
+	u32 data_in_count;
+
+	/* Frames scheduled for transmission, not handled yet */
+	struct sk_buff_head tx_queue;
+	bool tx_queue_stopped;
+
+	struct work_struct tx_work;
+	struct work_struct filter_work;
+
+	/* Pending TX frames */
+	struct sk_buff *tx_frames[16];
+
+	/*
+	 * Index pointing to the next TX complete entry
+	 * in the cyclic XT complete array we get from
+	 * the FW.
+	 */
+	u32 next_tx_complete;
+
+	/* FW Rx counter */
+	u32 rx_counter;
+
+	/* Rx frames handled */
+	u32 rx_handled;
+
+	/* Current double buffer */
+	u32 rx_current_buffer;
+	u32 rx_last_id;
+
+	/* The target interrupt mask */
+	u32 intr_mask;
+	struct work_struct irq_work;
+
+	/* The mbox event mask */
+	u32 event_mask;
+
+	/* Mailbox pointers */
+	u32 mbox_ptr[2];
+
+	/* Are we currently scanning */
+	bool scanning;
+
+	/* Default key (for WEP) */
+	u32 default_key;
+
+	unsigned int tx_mgmt_frm_rate;
+	unsigned int tx_mgmt_frm_mod;
+
+	unsigned int rx_config;
+	unsigned int rx_filter;
+
+	/* is firmware in elp mode */
+	bool elp;
+
+	struct delayed_work elp_work;
+
+	/* we can be in psm, but not in elp, we have to differentiate */
+	bool psm;
+
+	/* PSM mode requested */
+	bool psm_requested;
+
+	u16 beacon_int;
+	u8 dtim_period;
+
+	/* in dBm */
+	int power_level;
+
+	struct wl1251_stats stats;
+	struct wl1251_debugfs debugfs;
+
+	u32 buffer_32;
+	u32 buffer_cmd;
+	u8 buffer_busyword[WL1251_BUSY_WORD_LEN];
+	struct wl1251_rx_descriptor *rx_descriptor;
+
+	struct ieee80211_vif *vif;
+
+	u32 chip_id;
+	char fw_ver[21];
+
+	/* Most recently reported noise in dBm */
+	s8 noise;
+};
+
+int wl1251_plt_start(struct wl1251 *wl);
+int wl1251_plt_stop(struct wl1251 *wl);
+
+struct ieee80211_hw *wl1251_alloc_hw(void);
+int wl1251_free_hw(struct wl1251 *wl);
+int wl1251_init_ieee80211(struct wl1251 *wl);
+void wl1251_enable_interrupts(struct wl1251 *wl);
+void wl1251_disable_interrupts(struct wl1251 *wl);
+
+#define DEFAULT_HW_GEN_MODULATION_TYPE    CCK_LONG /* Long Preamble */
+#define DEFAULT_HW_GEN_TX_RATE          RATE_2MBPS
+#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
+
+#define WL1251_DEFAULT_POWER_LEVEL 20
+
+#define WL1251_TX_QUEUE_LOW_WATERMARK  10
+#define WL1251_TX_QUEUE_HIGH_WATERMARK 25
+
+#define WL1251_DEFAULT_BEACON_INT 100
+#define WL1251_DEFAULT_DTIM_PERIOD 1
+
+#define WL1251_DEFAULT_CHANNEL 0
+
+#define CHIP_ID_1251_PG10	           (0x7010101)
+#define CHIP_ID_1251_PG11	           (0x7020101)
+#define CHIP_ID_1251_PG12	           (0x7030101)
+#define CHIP_ID_1271_PG10	           (0x4030101)
+#define CHIP_ID_1271_PG20	           (0x4030111)
+
+#define WL1251_FW_NAME "wl1251-fw.bin"
+#define WL1251_NVS_NAME "wl1251-nvs.bin"
+
+#define WL1251_POWER_ON_SLEEP 10 /* in miliseconds */
+
+#define WL1251_PART_DOWN_MEM_START	0x0
+#define WL1251_PART_DOWN_MEM_SIZE	0x16800
+#define WL1251_PART_DOWN_REG_START	REGISTERS_BASE
+#define WL1251_PART_DOWN_REG_SIZE	REGISTERS_DOWN_SIZE
+
+#define WL1251_PART_WORK_MEM_START	0x28000
+#define WL1251_PART_WORK_MEM_SIZE	0x14000
+#define WL1251_PART_WORK_REG_START	REGISTERS_BASE
+#define WL1251_PART_WORK_REG_SIZE	REGISTERS_WORK_SIZE
+
+#endif
diff --git a/drivers/net/wireless/wl1251/wl12xx_80211.h b/drivers/net/wireless/wl1251/wl12xx_80211.h
new file mode 100644
index 0000000..1846280
--- /dev/null
+++ b/drivers/net/wireless/wl1251/wl12xx_80211.h
@@ -0,0 +1,156 @@
+#ifndef __WL12XX_80211_H__
+#define __WL12XX_80211_H__
+
+#include <linux/if_ether.h>	/* ETH_ALEN */
+
+/* RATES */
+#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_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)
+
+
+/* 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 */
+struct ieee80211_header {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 da[ETH_ALEN];
+	u8 sa[ETH_ALEN];
+	u8 bssid[ETH_ALEN];
+	__le16 seq_ctl;
+	u8 payload[0];
+} __packed;
+
+struct wl12xx_ie_header {
+	u8 id;
+	u8 len;
+} __packed;
+
+/* IEs */
+
+struct wl12xx_ie_ssid {
+	struct wl12xx_ie_header header;
+	char ssid[IW_ESSID_MAX_SIZE];
+} __packed;
+
+struct wl12xx_ie_rates {
+	struct wl12xx_ie_header header;
+	u8 rates[MAX_SUPPORTED_RATES];
+} __packed;
+
+struct wl12xx_ie_ds_params {
+	struct wl12xx_ie_header header;
+	u8 channel;
+} __packed;
+
+struct country_triplet {
+	u8 channel;
+	u8 num_channels;
+	u8 max_tx_power;
+} __packed;
+
+struct wl12xx_ie_country {
+	struct wl12xx_ie_header header;
+	u8 country_string[COUNTRY_STRING_LEN];
+	struct country_triplet triplets[MAX_COUNTRY_TRIPLETS];
+} __packed;
+
+
+/* Templates */
+
+struct wl12xx_beacon_template {
+	struct ieee80211_header header;
+	__le32 time_stamp[2];
+	__le16 beacon_interval;
+	__le16 capability;
+	struct wl12xx_ie_ssid ssid;
+	struct wl12xx_ie_rates rates;
+	struct wl12xx_ie_rates ext_rates;
+	struct wl12xx_ie_ds_params ds_params;
+	struct wl12xx_ie_country country;
+} __packed;
+
+struct wl12xx_null_data_template {
+	struct ieee80211_header header;
+} __packed;
+
+struct wl12xx_ps_poll_template {
+	__le16 fc;
+	__le16 aid;
+	u8 bssid[ETH_ALEN];
+	u8 ta[ETH_ALEN];
+} __packed;
+
+struct wl12xx_qos_null_data_template {
+	struct ieee80211_header header;
+	__le16 qos_ctl;
+} __packed;
+
+struct wl12xx_probe_req_template {
+	struct ieee80211_header header;
+	struct wl12xx_ie_ssid ssid;
+	struct wl12xx_ie_rates rates;
+	struct wl12xx_ie_rates ext_rates;
+} __packed;
+
+
+struct wl12xx_probe_resp_template {
+	struct ieee80211_header header;
+	__le32 time_stamp[2];
+	__le16 beacon_interval;
+	__le16 capability;
+	struct wl12xx_ie_ssid ssid;
+	struct wl12xx_ie_rates rates;
+	struct wl12xx_ie_rates ext_rates;
+	struct wl12xx_ie_ds_params ds_params;
+	struct wl12xx_ie_country country;
+} __packed;
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 2f98058..b447559 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -5,40 +5,6 @@
 	  This will enable TI wl12xx driver support. The drivers make
 	  use of the mac80211 stack.
 
-config WL1251
-	tristate "TI wl1251 support"
-	depends on WL12XX && GENERIC_HARDIRQS
-	select FW_LOADER
-	select CRC7
-	---help---
-	  This module adds support for wireless adapters based on
-	  TI wl1251 chipset.
-
-	  If you choose to build a module, it'll be called wl1251. Say
-	  N if unsure.
-
-config WL1251_SPI
-	tristate "TI wl1251 SPI support"
-	depends on WL1251 && SPI_MASTER
-	---help---
-	  This module adds support for the SPI interface of adapters using
-	  TI wl1251 chipset.  Select this if your platform is using
-	  the SPI bus.
-
-	  If you choose to build a module, it'll be called wl1251_spi.
-	  Say N if unsure.
-
-config WL1251_SDIO
-	tristate "TI wl1251 SDIO support"
-	depends on WL1251 && MMC
-	---help---
-	  This module adds support for the SDIO interface of adapters using
-	  TI wl1251 chipset.  Select this if your platform is using
-	  the SDIO bus.
-
-	  If you choose to build a module, it'll be called
-	  wl1251_sdio. Say N if unsure.
-
 config WL1271
 	tristate "TI wl1271 support"
 	depends on WL12XX && GENERIC_HARDIRQS
@@ -74,4 +40,7 @@
 	  If you choose to build a module, it'll be called
 	  wl1271_sdio. Say N if unsure.
 
-
+config WL12XX_PLATFORM_DATA
+	bool
+	depends on WL1271_SDIO != n
+	default y
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index 078b439..3a80744 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -1,12 +1,3 @@
-wl1251-objs		= wl1251_main.o wl1251_event.o \
-			  wl1251_tx.o wl1251_rx.o wl1251_ps.o wl1251_cmd.o \
-			  wl1251_acx.o wl1251_boot.o wl1251_init.o \
-			  wl1251_debugfs.o wl1251_io.o
-
-obj-$(CONFIG_WL1251)	+= wl1251.o
-obj-$(CONFIG_WL1251_SPI)	+= wl1251_spi.o
-obj-$(CONFIG_WL1251_SDIO)	+= wl1251_sdio.o
-
 wl1271-objs		= wl1271_main.o  wl1271_cmd.o wl1271_io.o \
 			  wl1271_event.o wl1271_tx.o  wl1271_rx.o   \
 			  wl1271_ps.o    wl1271_acx.o wl1271_boot.o \
@@ -16,3 +7,6 @@
 obj-$(CONFIG_WL1271)	+= wl1271.o
 obj-$(CONFIG_WL1271_SPI)	+= wl1271_spi.o
 obj-$(CONFIG_WL1271_SDIO)	+= wl1271_sdio.o
+
+# small builtin driver bit
+obj-$(CONFIG_WL12XX_PLATFORM_DATA)	+= wl12xx_platform_data.o
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
deleted file mode 100644
index 6b942a2..0000000
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef __WL1251_H__
-#define __WL1251_H__
-
-#include <linux/mutex.h>
-#include <linux/list.h>
-#include <linux/bitops.h>
-#include <net/mac80211.h>
-
-#define DRIVER_NAME "wl1251"
-#define DRIVER_PREFIX DRIVER_NAME ": "
-
-enum {
-	DEBUG_NONE	= 0,
-	DEBUG_IRQ	= BIT(0),
-	DEBUG_SPI	= BIT(1),
-	DEBUG_BOOT	= BIT(2),
-	DEBUG_MAILBOX	= BIT(3),
-	DEBUG_NETLINK	= BIT(4),
-	DEBUG_EVENT	= BIT(5),
-	DEBUG_TX	= BIT(6),
-	DEBUG_RX	= BIT(7),
-	DEBUG_SCAN	= BIT(8),
-	DEBUG_CRYPT	= BIT(9),
-	DEBUG_PSM	= BIT(10),
-	DEBUG_MAC80211	= BIT(11),
-	DEBUG_CMD	= BIT(12),
-	DEBUG_ACX	= BIT(13),
-	DEBUG_ALL	= ~0,
-};
-
-#define DEBUG_LEVEL (DEBUG_NONE)
-
-#define DEBUG_DUMP_LIMIT 1024
-
-#define wl1251_error(fmt, arg...) \
-	printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg)
-
-#define wl1251_warning(fmt, arg...) \
-	printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg)
-
-#define wl1251_notice(fmt, arg...) \
-	printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg)
-
-#define wl1251_info(fmt, arg...) \
-	printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg)
-
-#define wl1251_debug(level, fmt, arg...) \
-	do { \
-		if (level & DEBUG_LEVEL) \
-			printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \
-	} while (0)
-
-#define wl1251_dump(level, prefix, buf, len)	\
-	do { \
-		if (level & DEBUG_LEVEL) \
-			print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
-				       DUMP_PREFIX_OFFSET, 16, 1,	\
-				       buf,				\
-				       min_t(size_t, len, DEBUG_DUMP_LIMIT), \
-				       0);				\
-	} while (0)
-
-#define wl1251_dump_ascii(level, prefix, buf, len)	\
-	do { \
-		if (level & DEBUG_LEVEL) \
-			print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
-				       DUMP_PREFIX_OFFSET, 16, 1,	\
-				       buf,				\
-				       min_t(size_t, len, DEBUG_DUMP_LIMIT), \
-				       true);				\
-	} while (0)
-
-#define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN |	\
-				  CFG_BSSID_FILTER_EN)
-
-#define WL1251_DEFAULT_RX_FILTER (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 WL1251_BUSY_WORD_LEN 8
-
-struct boot_attr {
-	u32 radio_type;
-	u8 mac_clock;
-	u8 arm_clock;
-	int firmware_debug;
-	u32 minor;
-	u32 major;
-	u32 bugfix;
-};
-
-enum wl1251_state {
-	WL1251_STATE_OFF,
-	WL1251_STATE_ON,
-	WL1251_STATE_PLT,
-};
-
-enum wl1251_partition_type {
-	PART_DOWN,
-	PART_WORK,
-	PART_DRPW,
-
-	PART_TABLE_LEN
-};
-
-struct wl1251_partition {
-	u32 size;
-	u32 start;
-};
-
-struct wl1251_partition_set {
-	struct wl1251_partition mem;
-	struct wl1251_partition reg;
-};
-
-struct wl1251;
-
-struct wl1251_stats {
-	struct acx_statistics *fw_stats;
-	unsigned long fw_stats_update;
-
-	unsigned int retry_count;
-	unsigned int excessive_retries;
-};
-
-struct wl1251_debugfs {
-	struct dentry *rootdir;
-	struct dentry *fw_statistics;
-
-	struct dentry *tx_internal_desc_overflow;
-
-	struct dentry *rx_out_of_mem;
-	struct dentry *rx_hdr_overflow;
-	struct dentry *rx_hw_stuck;
-	struct dentry *rx_dropped;
-	struct dentry *rx_fcs_err;
-	struct dentry *rx_xfr_hint_trig;
-	struct dentry *rx_path_reset;
-	struct dentry *rx_reset_counter;
-
-	struct dentry *dma_rx_requested;
-	struct dentry *dma_rx_errors;
-	struct dentry *dma_tx_requested;
-	struct dentry *dma_tx_errors;
-
-	struct dentry *isr_cmd_cmplt;
-	struct dentry *isr_fiqs;
-	struct dentry *isr_rx_headers;
-	struct dentry *isr_rx_mem_overflow;
-	struct dentry *isr_rx_rdys;
-	struct dentry *isr_irqs;
-	struct dentry *isr_tx_procs;
-	struct dentry *isr_decrypt_done;
-	struct dentry *isr_dma0_done;
-	struct dentry *isr_dma1_done;
-	struct dentry *isr_tx_exch_complete;
-	struct dentry *isr_commands;
-	struct dentry *isr_rx_procs;
-	struct dentry *isr_hw_pm_mode_changes;
-	struct dentry *isr_host_acknowledges;
-	struct dentry *isr_pci_pm;
-	struct dentry *isr_wakeups;
-	struct dentry *isr_low_rssi;
-
-	struct dentry *wep_addr_key_count;
-	struct dentry *wep_default_key_count;
-	/* skipping wep.reserved */
-	struct dentry *wep_key_not_found;
-	struct dentry *wep_decrypt_fail;
-	struct dentry *wep_packets;
-	struct dentry *wep_interrupt;
-
-	struct dentry *pwr_ps_enter;
-	struct dentry *pwr_elp_enter;
-	struct dentry *pwr_missing_bcns;
-	struct dentry *pwr_wake_on_host;
-	struct dentry *pwr_wake_on_timer_exp;
-	struct dentry *pwr_tx_with_ps;
-	struct dentry *pwr_tx_without_ps;
-	struct dentry *pwr_rcvd_beacons;
-	struct dentry *pwr_power_save_off;
-	struct dentry *pwr_enable_ps;
-	struct dentry *pwr_disable_ps;
-	struct dentry *pwr_fix_tsf_ps;
-	/* skipping cont_miss_bcns_spread for now */
-	struct dentry *pwr_rcvd_awake_beacons;
-
-	struct dentry *mic_rx_pkts;
-	struct dentry *mic_calc_failure;
-
-	struct dentry *aes_encrypt_fail;
-	struct dentry *aes_decrypt_fail;
-	struct dentry *aes_encrypt_packets;
-	struct dentry *aes_decrypt_packets;
-	struct dentry *aes_encrypt_interrupt;
-	struct dentry *aes_decrypt_interrupt;
-
-	struct dentry *event_heart_beat;
-	struct dentry *event_calibration;
-	struct dentry *event_rx_mismatch;
-	struct dentry *event_rx_mem_empty;
-	struct dentry *event_rx_pool;
-	struct dentry *event_oom_late;
-	struct dentry *event_phy_transmit_error;
-	struct dentry *event_tx_stuck;
-
-	struct dentry *ps_pspoll_timeouts;
-	struct dentry *ps_upsd_timeouts;
-	struct dentry *ps_upsd_max_sptime;
-	struct dentry *ps_upsd_max_apturn;
-	struct dentry *ps_pspoll_max_apturn;
-	struct dentry *ps_pspoll_utilization;
-	struct dentry *ps_upsd_utilization;
-
-	struct dentry *rxpipe_rx_prep_beacon_drop;
-	struct dentry *rxpipe_descr_host_int_trig_rx_data;
-	struct dentry *rxpipe_beacon_buffer_thres_host_int_trig_rx_data;
-	struct dentry *rxpipe_missed_beacon_host_int_trig_rx_data;
-	struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data;
-
-	struct dentry *tx_queue_len;
-	struct dentry *tx_queue_status;
-
-	struct dentry *retry_count;
-	struct dentry *excessive_retries;
-};
-
-struct wl1251_if_operations {
-	void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len);
-	void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len);
-	void (*read_elp)(struct wl1251 *wl, int addr, u32 *val);
-	void (*write_elp)(struct wl1251 *wl, int addr, u32 val);
-	void (*reset)(struct wl1251 *wl);
-	void (*enable_irq)(struct wl1251 *wl);
-	void (*disable_irq)(struct wl1251 *wl);
-};
-
-struct wl1251 {
-	struct ieee80211_hw *hw;
-	bool mac80211_registered;
-
-	void *if_priv;
-	const struct wl1251_if_operations *if_ops;
-
-	void (*set_power)(bool enable);
-	int irq;
-	bool use_eeprom;
-
-	enum wl1251_state state;
-	struct mutex mutex;
-
-	int physical_mem_addr;
-	int physical_reg_addr;
-	int virtual_mem_addr;
-	int virtual_reg_addr;
-
-	int cmd_box_addr;
-	int event_box_addr;
-	struct boot_attr boot_attr;
-
-	u8 *fw;
-	size_t fw_len;
-	u8 *nvs;
-	size_t nvs_len;
-
-	u8 bssid[ETH_ALEN];
-	u8 mac_addr[ETH_ALEN];
-	u8 bss_type;
-	u8 listen_int;
-	int channel;
-
-	void *target_mem_map;
-	struct acx_data_path_params_resp *data_path;
-
-	/* Number of TX packets transferred to the FW, modulo 16 */
-	u32 data_in_count;
-
-	/* Frames scheduled for transmission, not handled yet */
-	struct sk_buff_head tx_queue;
-	bool tx_queue_stopped;
-
-	struct work_struct tx_work;
-	struct work_struct filter_work;
-
-	/* Pending TX frames */
-	struct sk_buff *tx_frames[16];
-
-	/*
-	 * Index pointing to the next TX complete entry
-	 * in the cyclic XT complete array we get from
-	 * the FW.
-	 */
-	u32 next_tx_complete;
-
-	/* FW Rx counter */
-	u32 rx_counter;
-
-	/* Rx frames handled */
-	u32 rx_handled;
-
-	/* Current double buffer */
-	u32 rx_current_buffer;
-	u32 rx_last_id;
-
-	/* The target interrupt mask */
-	u32 intr_mask;
-	struct work_struct irq_work;
-
-	/* The mbox event mask */
-	u32 event_mask;
-
-	/* Mailbox pointers */
-	u32 mbox_ptr[2];
-
-	/* Are we currently scanning */
-	bool scanning;
-
-	/* Default key (for WEP) */
-	u32 default_key;
-
-	unsigned int tx_mgmt_frm_rate;
-	unsigned int tx_mgmt_frm_mod;
-
-	unsigned int rx_config;
-	unsigned int rx_filter;
-
-	/* is firmware in elp mode */
-	bool elp;
-
-	struct delayed_work elp_work;
-
-	/* we can be in psm, but not in elp, we have to differentiate */
-	bool psm;
-
-	/* PSM mode requested */
-	bool psm_requested;
-
-	u16 beacon_int;
-	u8 dtim_period;
-
-	/* in dBm */
-	int power_level;
-
-	struct wl1251_stats stats;
-	struct wl1251_debugfs debugfs;
-
-	u32 buffer_32;
-	u32 buffer_cmd;
-	u8 buffer_busyword[WL1251_BUSY_WORD_LEN];
-	struct wl1251_rx_descriptor *rx_descriptor;
-
-	struct ieee80211_vif *vif;
-
-	u32 chip_id;
-	char fw_ver[21];
-
-	/* Most recently reported noise in dBm */
-	s8 noise;
-};
-
-int wl1251_plt_start(struct wl1251 *wl);
-int wl1251_plt_stop(struct wl1251 *wl);
-
-struct ieee80211_hw *wl1251_alloc_hw(void);
-int wl1251_free_hw(struct wl1251 *wl);
-int wl1251_init_ieee80211(struct wl1251 *wl);
-void wl1251_enable_interrupts(struct wl1251 *wl);
-void wl1251_disable_interrupts(struct wl1251 *wl);
-
-#define DEFAULT_HW_GEN_MODULATION_TYPE    CCK_LONG /* Long Preamble */
-#define DEFAULT_HW_GEN_TX_RATE          RATE_2MBPS
-#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
-
-#define WL1251_DEFAULT_POWER_LEVEL 20
-
-#define WL1251_TX_QUEUE_MAX_LENGTH 20
-
-#define WL1251_DEFAULT_BEACON_INT 100
-#define WL1251_DEFAULT_DTIM_PERIOD 1
-
-#define WL1251_DEFAULT_CHANNEL 0
-
-#define CHIP_ID_1251_PG10	           (0x7010101)
-#define CHIP_ID_1251_PG11	           (0x7020101)
-#define CHIP_ID_1251_PG12	           (0x7030101)
-#define CHIP_ID_1271_PG10	           (0x4030101)
-#define CHIP_ID_1271_PG20	           (0x4030111)
-
-#define WL1251_FW_NAME "wl1251-fw.bin"
-#define WL1251_NVS_NAME "wl1251-nvs.bin"
-
-#define WL1251_POWER_ON_SLEEP 10 /* in miliseconds */
-
-#define WL1251_PART_DOWN_MEM_START	0x0
-#define WL1251_PART_DOWN_MEM_SIZE	0x16800
-#define WL1251_PART_DOWN_REG_START	REGISTERS_BASE
-#define WL1251_PART_DOWN_REG_SIZE	REGISTERS_DOWN_SIZE
-
-#define WL1251_PART_WORK_MEM_START	0x28000
-#define WL1251_PART_WORK_MEM_SIZE	0x14000
-#define WL1251_PART_WORK_REG_START	REGISTERS_BASE
-#define WL1251_PART_WORK_REG_SIZE	REGISTERS_WORK_SIZE
-
-#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c
deleted file mode 100644
index 91891f9..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_acx.c
+++ /dev/null
@@ -1,1048 +0,0 @@
-#include "wl1251_acx.h"
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/crc7.h>
-
-#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_cmd.h"
-#include "wl1251_ps.h"
-
-int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
-			   u8 mgt_rate, u8 mgt_mod)
-{
-	struct acx_fw_gen_frame_rates *rates;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx frame rates");
-
-	rates = kzalloc(sizeof(*rates), GFP_KERNEL);
-	if (!rates) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	rates->tx_ctrl_frame_rate = ctrl_rate;
-	rates->tx_ctrl_frame_mod = ctrl_mod;
-	rates->tx_mgt_frame_rate = mgt_rate;
-	rates->tx_mgt_frame_mod = mgt_mod;
-
-	ret = wl1251_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES,
-				   rates, sizeof(*rates));
-	if (ret < 0) {
-		wl1251_error("Failed to set FW rates and modulation");
-		goto out;
-	}
-
-out:
-	kfree(rates);
-	return ret;
-}
-
-
-int wl1251_acx_station_id(struct wl1251 *wl)
-{
-	struct acx_dot11_station_id *mac;
-	int ret, i;
-
-	wl1251_debug(DEBUG_ACX, "acx dot11_station_id");
-
-	mac = kzalloc(sizeof(*mac), GFP_KERNEL);
-	if (!mac) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	for (i = 0; i < ETH_ALEN; i++)
-		mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
-
-	ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac));
-	if (ret < 0)
-		goto out;
-
-out:
-	kfree(mac);
-	return ret;
-}
-
-int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id)
-{
-	struct acx_dot11_default_key *default_key;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);
-
-	default_key = kzalloc(sizeof(*default_key), GFP_KERNEL);
-	if (!default_key) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	default_key->id = key_id;
-
-	ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY,
-				   default_key, sizeof(*default_key));
-	if (ret < 0) {
-		wl1251_error("Couldn't set default key");
-		goto out;
-	}
-
-	wl->default_key = key_id;
-
-out:
-	kfree(default_key);
-	return ret;
-}
-
-int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
-				  u8 listen_interval)
-{
-	struct acx_wake_up_condition *wake_up;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx wake up conditions");
-
-	wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
-	if (!wake_up) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	wake_up->wake_up_event = wake_up_event;
-	wake_up->listen_interval = listen_interval;
-
-	ret = wl1251_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
-				   wake_up, sizeof(*wake_up));
-	if (ret < 0) {
-		wl1251_warning("could not set wake up conditions: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(wake_up);
-	return ret;
-}
-
-int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth)
-{
-	struct acx_sleep_auth *auth;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx sleep auth");
-
-	auth = kzalloc(sizeof(*auth), GFP_KERNEL);
-	if (!auth) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	auth->sleep_auth = sleep_auth;
-
-	ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
-	if (ret < 0)
-		return ret;
-
-out:
-	kfree(auth);
-	return ret;
-}
-
-int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len)
-{
-	struct acx_revision *rev;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx fw rev");
-
-	rev = kzalloc(sizeof(*rev), GFP_KERNEL);
-	if (!rev) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
-	if (ret < 0) {
-		wl1251_warning("ACX_FW_REV interrogate failed");
-		goto out;
-	}
-
-	/* be careful with the buffer sizes */
-	strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
-
-	/*
-	 * if the firmware version string is exactly
-	 * sizeof(rev->fw_version) long or fw_len is less than
-	 * sizeof(rev->fw_version) it won't be null terminated
-	 */
-	buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
-
-out:
-	kfree(rev);
-	return ret;
-}
-
-int wl1251_acx_tx_power(struct wl1251 *wl, int power)
-{
-	struct acx_current_tx_power *acx;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
-
-	if (power < 0 || power > 25)
-		return -EINVAL;
-
-	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-	if (!acx) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	acx->current_tx_power = power * 10;
-
-	ret = wl1251_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1251_warning("configure of tx power failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(acx);
-	return ret;
-}
-
-int wl1251_acx_feature_cfg(struct wl1251 *wl)
-{
-	struct acx_feature_config *feature;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx feature cfg");
-
-	feature = kzalloc(sizeof(*feature), GFP_KERNEL);
-	if (!feature) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
-	feature->data_flow_options = 0;
-	feature->options = 0;
-
-	ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
-				   feature, sizeof(*feature));
-	if (ret < 0) {
-		wl1251_error("Couldn't set HW encryption");
-		goto out;
-	}
-
-out:
-	kfree(feature);
-	return ret;
-}
-
-int wl1251_acx_mem_map(struct wl1251 *wl, struct acx_header *mem_map,
-		       size_t len)
-{
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx mem map");
-
-	ret = wl1251_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-int wl1251_acx_data_path_params(struct wl1251 *wl,
-				struct acx_data_path_params_resp *resp)
-{
-	struct acx_data_path_params *params;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx data path params");
-
-	params = kzalloc(sizeof(*params), GFP_KERNEL);
-	if (!params) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE;
-	params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE;
-
-	params->rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM;
-	params->tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM;
-
-	params->tx_complete_threshold = 1;
-
-	params->tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE;
-
-	params->tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT;
-
-	ret = wl1251_cmd_configure(wl, ACX_DATA_PATH_PARAMS,
-				   params, sizeof(*params));
-	if (ret < 0)
-		goto out;
-
-	/* FIXME: shouldn't this be ACX_DATA_PATH_RESP_PARAMS? */
-	ret = wl1251_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS,
-				     resp, sizeof(*resp));
-
-	if (ret < 0) {
-		wl1251_warning("failed to read data path parameters: %d", ret);
-		goto out;
-	} else if (resp->header.cmd.status != CMD_STATUS_SUCCESS) {
-		wl1251_warning("data path parameter acx status failed");
-		ret = -EIO;
-		goto out;
-	}
-
-out:
-	kfree(params);
-	return ret;
-}
-
-int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time)
-{
-	struct acx_rx_msdu_lifetime *acx;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx rx msdu life time");
-
-	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-	if (!acx) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	acx->lifetime = life_time;
-	ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
-				   acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1251_warning("failed to set rx msdu life time: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(acx);
-	return ret;
-}
-
-int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter)
-{
-	struct acx_rx_config *rx_config;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx rx config");
-
-	rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
-	if (!rx_config) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	rx_config->config_options = config;
-	rx_config->filter_options = filter;
-
-	ret = wl1251_cmd_configure(wl, ACX_RX_CFG,
-				   rx_config, sizeof(*rx_config));
-	if (ret < 0) {
-		wl1251_warning("failed to set rx config: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(rx_config);
-	return ret;
-}
-
-int wl1251_acx_pd_threshold(struct wl1251 *wl)
-{
-	struct acx_packet_detection *pd;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx data pd threshold");
-
-	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
-	if (!pd) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* FIXME: threshold value not set */
-
-	ret = wl1251_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
-	if (ret < 0) {
-		wl1251_warning("failed to set pd threshold: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(pd);
-	return 0;
-}
-
-int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time)
-{
-	struct acx_slot *slot;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx slot");
-
-	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
-	if (!slot) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	slot->wone_index = STATION_WONE_INDEX;
-	slot->slot_time = slot_time;
-
-	ret = wl1251_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
-	if (ret < 0) {
-		wl1251_warning("failed to set slot time: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(slot);
-	return ret;
-}
-
-int wl1251_acx_group_address_tbl(struct wl1251 *wl)
-{
-	struct acx_dot11_grp_addr_tbl *acx;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx group address tbl");
-
-	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-	if (!acx) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* MAC filtering */
-	acx->enabled = 0;
-	acx->num_groups = 0;
-	memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
-
-	ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
-				   acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1251_warning("failed to set group addr table: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(acx);
-	return ret;
-}
-
-int wl1251_acx_service_period_timeout(struct wl1251 *wl)
-{
-	struct acx_rx_timeout *rx_timeout;
-	int ret;
-
-	rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
-	if (!rx_timeout) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	wl1251_debug(DEBUG_ACX, "acx service period timeout");
-
-	rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
-	rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF;
-
-	ret = wl1251_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
-				   rx_timeout, sizeof(*rx_timeout));
-	if (ret < 0) {
-		wl1251_warning("failed to set service period timeout: %d",
-			       ret);
-		goto out;
-	}
-
-out:
-	kfree(rx_timeout);
-	return ret;
-}
-
-int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold)
-{
-	struct acx_rts_threshold *rts;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx rts threshold");
-
-	rts = kzalloc(sizeof(*rts), GFP_KERNEL);
-	if (!rts) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	rts->threshold = rts_threshold;
-
-	ret = wl1251_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
-	if (ret < 0) {
-		wl1251_warning("failed to set rts threshold: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(rts);
-	return ret;
-}
-
-int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter)
-{
-	struct acx_beacon_filter_option *beacon_filter;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx beacon filter opt");
-
-	beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
-	if (!beacon_filter) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	beacon_filter->enable = enable_filter;
-	beacon_filter->max_num_beacons = 0;
-
-	ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
-				   beacon_filter, sizeof(*beacon_filter));
-	if (ret < 0) {
-		wl1251_warning("failed to set beacon filter opt: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(beacon_filter);
-	return ret;
-}
-
-int wl1251_acx_beacon_filter_table(struct wl1251 *wl)
-{
-	struct acx_beacon_filter_ie_table *ie_table;
-	int idx = 0;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx beacon filter table");
-
-	ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
-	if (!ie_table) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* configure default beacon pass-through rules */
-	ie_table->num_ie = 1;
-	ie_table->table[idx++] = BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN;
-	ie_table->table[idx++] = BEACON_RULE_PASS_ON_APPEARANCE;
-
-	ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
-				   ie_table, sizeof(*ie_table));
-	if (ret < 0) {
-		wl1251_warning("failed to set beacon filter table: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(ie_table);
-	return ret;
-}
-
-int wl1251_acx_conn_monit_params(struct wl1251 *wl)
-{
-	struct acx_conn_monit_params *acx;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx connection monitor parameters");
-
-	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-	if (!acx) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD;
-	acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT;
-
-	ret = wl1251_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
-				   acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1251_warning("failed to set connection monitor "
-			       "parameters: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(acx);
-	return ret;
-}
-
-int wl1251_acx_sg_enable(struct wl1251 *wl)
-{
-	struct acx_bt_wlan_coex *pta;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx sg enable");
-
-	pta = kzalloc(sizeof(*pta), GFP_KERNEL);
-	if (!pta) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	pta->enable = SG_ENABLE;
-
-	ret = wl1251_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
-	if (ret < 0) {
-		wl1251_warning("failed to set softgemini enable: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(pta);
-	return ret;
-}
-
-int wl1251_acx_sg_cfg(struct wl1251 *wl)
-{
-	struct acx_bt_wlan_coex_param *param;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx sg cfg");
-
-	param = kzalloc(sizeof(*param), GFP_KERNEL);
-	if (!param) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* BT-WLAN coext parameters */
-	param->min_rate = RATE_INDEX_24MBPS;
-	param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
-	param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
-	param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
-	param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
-	param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
-	param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
-	param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
-	param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
-	param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
-	param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
-	param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
-	param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
-	param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
-	param->antenna_type = PTA_ANTENNA_TYPE_DEF;
-	param->signal_type = PTA_SIGNALING_TYPE_DEF;
-	param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
-	param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
-	param->max_cts = PTA_MAX_NUM_CTS_DEF;
-	param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
-	param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
-	param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
-	param->wlan_elp_hp = PTA_ELP_HP_DEF;
-	param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
-	param->ack_mode_dual_ant = PTA_ACK_MODE_DEF;
-	param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
-	param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
-	param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;
-
-	ret = wl1251_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
-	if (ret < 0) {
-		wl1251_warning("failed to set sg config: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(param);
-	return ret;
-}
-
-int wl1251_acx_cca_threshold(struct wl1251 *wl)
-{
-	struct acx_energy_detection *detection;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx cca threshold");
-
-	detection = kzalloc(sizeof(*detection), GFP_KERNEL);
-	if (!detection) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
-	detection->tx_energy_detection = 0;
-
-	ret = wl1251_cmd_configure(wl, ACX_CCA_THRESHOLD,
-				   detection, sizeof(*detection));
-	if (ret < 0) {
-		wl1251_warning("failed to set cca threshold: %d", ret);
-		return ret;
-	}
-
-out:
-	kfree(detection);
-	return ret;
-}
-
-int wl1251_acx_bcn_dtim_options(struct wl1251 *wl)
-{
-	struct acx_beacon_broadcast *bb;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx bcn dtim options");
-
-	bb = kzalloc(sizeof(*bb), GFP_KERNEL);
-	if (!bb) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
-	bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
-	bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
-	bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
-
-	ret = wl1251_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
-	if (ret < 0) {
-		wl1251_warning("failed to set rx config: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(bb);
-	return ret;
-}
-
-int wl1251_acx_aid(struct wl1251 *wl, u16 aid)
-{
-	struct acx_aid *acx_aid;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx aid");
-
-	acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
-	if (!acx_aid) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	acx_aid->aid = aid;
-
-	ret = wl1251_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
-	if (ret < 0) {
-		wl1251_warning("failed to set aid: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(acx_aid);
-	return ret;
-}
-
-int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask)
-{
-	struct acx_event_mask *mask;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx event mbox mask");
-
-	mask = kzalloc(sizeof(*mask), GFP_KERNEL);
-	if (!mask) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* high event mask is unused */
-	mask->high_event_mask = 0xffffffff;
-
-	mask->event_mask = event_mask;
-
-	ret = wl1251_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
-				   mask, sizeof(*mask));
-	if (ret < 0) {
-		wl1251_warning("failed to set acx_event_mbox_mask: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(mask);
-	return ret;
-}
-
-int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble)
-{
-	struct acx_preamble *acx;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx_set_preamble");
-
-	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-	if (!acx) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	acx->preamble = preamble;
-
-	ret = wl1251_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1251_warning("Setting of preamble failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(acx);
-	return ret;
-}
-
-int wl1251_acx_cts_protect(struct wl1251 *wl,
-			   enum acx_ctsprotect_type ctsprotect)
-{
-	struct acx_ctsprotect *acx;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect");
-
-	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-	if (!acx) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	acx->ctsprotect = ctsprotect;
-
-	ret = wl1251_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1251_warning("Setting of ctsprotect failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(acx);
-	return ret;
-}
-
-int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime)
-{
-	struct acx_tsf_info *tsf_info;
-	int ret;
-
-	tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL);
-	if (!tsf_info) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO,
-				     tsf_info, sizeof(*tsf_info));
-	if (ret < 0) {
-		wl1251_warning("ACX_FW_REV interrogate failed");
-		goto out;
-	}
-
-	*mactime = tsf_info->current_tsf_lsb |
-		(tsf_info->current_tsf_msb << 31);
-
-out:
-	kfree(tsf_info);
-	return ret;
-}
-
-int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats)
-{
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx statistics");
-
-	ret = wl1251_cmd_interrogate(wl, ACX_STATISTICS, stats,
-				     sizeof(*stats));
-	if (ret < 0) {
-		wl1251_warning("acx statistics failed: %d", ret);
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-int wl1251_acx_rate_policies(struct wl1251 *wl)
-{
-	struct acx_rate_policy *acx;
-	int ret = 0;
-
-	wl1251_debug(DEBUG_ACX, "acx rate policies");
-
-	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-
-	if (!acx) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* configure one default (one-size-fits-all) rate class */
-	acx->rate_class_cnt = 1;
-	acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
-	acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT;
-	acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT;
-	acx->rate_class[0].aflags = 0;
-
-	ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1251_warning("Setting of rate policies failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(acx);
-	return ret;
-}
-
-int wl1251_acx_mem_cfg(struct wl1251 *wl)
-{
-	struct wl1251_acx_config_memory *mem_conf;
-	int ret, i;
-
-	wl1251_debug(DEBUG_ACX, "acx mem cfg");
-
-	mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
-	if (!mem_conf) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* memory config */
-	mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
-	mem_conf->mem_config.rx_mem_block_num = 35;
-	mem_conf->mem_config.tx_min_mem_block_num = 64;
-	mem_conf->mem_config.num_tx_queues = MAX_TX_QUEUES;
-	mem_conf->mem_config.host_if_options = HOSTIF_PKT_RING;
-	mem_conf->mem_config.num_ssid_profiles = 1;
-	mem_conf->mem_config.debug_buffer_size =
-		cpu_to_le16(TRACE_BUFFER_MAX_SIZE);
-
-	/* RX queue config */
-	mem_conf->rx_queue_config.dma_address = 0;
-	mem_conf->rx_queue_config.num_descs = ACX_RX_DESC_DEF;
-	mem_conf->rx_queue_config.priority = DEFAULT_RXQ_PRIORITY;
-	mem_conf->rx_queue_config.type = DEFAULT_RXQ_TYPE;
-
-	/* TX queue config */
-	for (i = 0; i < MAX_TX_QUEUES; i++) {
-		mem_conf->tx_queue_config[i].num_descs = ACX_TX_DESC_DEF;
-		mem_conf->tx_queue_config[i].attributes = i;
-	}
-
-	ret = wl1251_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
-				   sizeof(*mem_conf));
-	if (ret < 0) {
-		wl1251_warning("wl1251 mem config failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(mem_conf);
-	return ret;
-}
-
-int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim)
-{
-	struct wl1251_acx_wr_tbtt_and_dtim *acx;
-	int ret;
-
-	wl1251_debug(DEBUG_ACX, "acx tbtt and dtim");
-
-	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-	if (!acx) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	acx->tbtt = tbtt;
-	acx->dtim = dtim;
-
-	ret = wl1251_cmd_configure(wl, ACX_WR_TBTT_AND_DTIM,
-				   acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1251_warning("failed to set tbtt and dtim: %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)
-{
-	struct wl1251_acx_ac_cfg *acx;
-	int ret = 0;
-
-	wl1251_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d "
-		     "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop);
-
-	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-
-	if (!acx) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	acx->ac = ac;
-	acx->cw_min = cw_min;
-	acx->cw_max = cw_max;
-	acx->aifsn = aifs;
-	acx->txop_limit = txop;
-
-	ret = wl1251_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1251_warning("acx ac cfg failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(acx);
-	return ret;
-}
-
-int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
-		       enum wl1251_acx_channel_type type,
-		       u8 tsid, enum wl1251_acx_ps_scheme ps_scheme,
-		       enum wl1251_acx_ack_policy ack_policy)
-{
-	struct wl1251_acx_tid_cfg *acx;
-	int ret = 0;
-
-	wl1251_debug(DEBUG_ACX, "acx tid cfg %d type %d tsid %d "
-		     "ps_scheme %d ack_policy %d", queue, type, tsid,
-		     ps_scheme, ack_policy);
-
-	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-
-	if (!acx) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	acx->queue = queue;
-	acx->type = type;
-	acx->tsid = tsid;
-	acx->ps_scheme = ps_scheme;
-	acx->ack_policy = ack_policy;
-
-	ret = wl1251_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1251_warning("acx tid cfg failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(acx);
-	return ret;
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h
deleted file mode 100644
index 842df31..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_acx.h
+++ /dev/null
@@ -1,1413 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef __WL1251_ACX_H__
-#define __WL1251_ACX_H__
-
-#include "wl1251.h"
-#include "wl1251_cmd.h"
-
-/* Target's information element */
-struct acx_header {
-	struct wl1251_cmd_header cmd;
-
-	/* acx (or information element) header */
-	u16 id;
-
-	/* payload length (not including headers */
-	u16 len;
-};
-
-struct acx_error_counter {
-	struct acx_header header;
-
-	/* The number of PLCP errors since the last time this */
-	/* information element was interrogated. This field is */
-	/* automatically cleared when it is interrogated.*/
-	u32 PLCP_error;
-
-	/* The number of FCS errors since the last time this */
-	/* information element was interrogated. This field is */
-	/* automatically cleared when it is interrogated.*/
-	u32 FCS_error;
-
-	/* The number of MPDUs without PLCP header errors received*/
-	/* since the last time this information element was interrogated. */
-	/* This field is automatically cleared when it is interrogated.*/
-	u32 valid_frame;
-
-	/* the number of missed sequence numbers in the squentially */
-	/* values of frames seq numbers */
-	u32 seq_num_miss;
-} __packed;
-
-struct acx_revision {
-	struct acx_header header;
-
-	/*
-	 * The WiLink firmware version, an ASCII string x.x.x.x,
-	 * that uniquely identifies the current firmware.
-	 * The left most digit is incremented each time a
-	 * significant change is made to the firmware, such as
-	 * code redesign or new platform support.
-	 * The second digit is incremented when major enhancements
-	 * are added or major fixes are made.
-	 * The third digit is incremented for each GA release.
-	 * The fourth digit is incremented for each build.
-	 * The first two digits identify a firmware release version,
-	 * in other words, a unique set of features.
-	 * The first three digits identify a GA release.
-	 */
-	char fw_version[20];
-
-	/*
-	 * This 4 byte field specifies the WiLink hardware version.
-	 * bits 0  - 15: Reserved.
-	 * bits 16 - 23: Version ID - The WiLink version ID
-	 *              (1 = first spin, 2 = second spin, and so on).
-	 * bits 24 - 31: Chip ID - The WiLink chip ID.
-	 */
-	u32 hw_version;
-} __packed;
-
-enum wl1251_psm_mode {
-	/* Active mode */
-	WL1251_PSM_CAM = 0,
-
-	/* Power save mode */
-	WL1251_PSM_PS = 1,
-
-	/* Extreme low power */
-	WL1251_PSM_ELP = 2,
-};
-
-struct acx_sleep_auth {
-	struct acx_header header;
-
-	/* The sleep level authorization of the device. */
-	/* 0 - Always active*/
-	/* 1 - Power down mode: light / fast sleep*/
-	/* 2 - ELP mode: Deep / Max sleep*/
-	u8  sleep_auth;
-	u8  padding[3];
-} __packed;
-
-enum {
-	HOSTIF_PCI_MASTER_HOST_INDIRECT,
-	HOSTIF_PCI_MASTER_HOST_DIRECT,
-	HOSTIF_SLAVE,
-	HOSTIF_PKT_RING,
-	HOSTIF_DONTCARE = 0xFF
-};
-
-#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
-
-#define  DP_RX_PACKET_RING_CHUNK_SIZE 1600
-#define  DP_TX_PACKET_RING_CHUNK_SIZE 1600
-#define  DP_RX_PACKET_RING_CHUNK_NUM 2
-#define  DP_TX_PACKET_RING_CHUNK_NUM 2
-#define  DP_TX_COMPLETE_TIME_OUT 20
-#define  FW_TX_CMPLT_BLOCK_SIZE 16
-
-struct acx_data_path_params {
-	struct acx_header header;
-
-	u16 rx_packet_ring_chunk_size;
-	u16 tx_packet_ring_chunk_size;
-
-	u8 rx_packet_ring_chunk_num;
-	u8 tx_packet_ring_chunk_num;
-
-	/*
-	 * Maximum number of packets that can be gathered
-	 * in the TX complete ring before an interrupt
-	 * is generated.
-	 */
-	u8 tx_complete_threshold;
-
-	/* Number of pending TX complete entries in cyclic ring.*/
-	u8 tx_complete_ring_depth;
-
-	/*
-	 * Max num microseconds since a packet enters the TX
-	 * complete ring until an interrupt is generated.
-	 */
-	u32 tx_complete_timeout;
-} __packed;
-
-
-struct acx_data_path_params_resp {
-	struct acx_header header;
-
-	u16 rx_packet_ring_chunk_size;
-	u16 tx_packet_ring_chunk_size;
-
-	u8 rx_packet_ring_chunk_num;
-	u8 tx_packet_ring_chunk_num;
-
-	u8 pad[2];
-
-	u32 rx_packet_ring_addr;
-	u32 tx_packet_ring_addr;
-
-	u32 rx_control_addr;
-	u32 tx_control_addr;
-
-	u32 tx_complete_addr;
-} __packed;
-
-#define TX_MSDU_LIFETIME_MIN       0
-#define TX_MSDU_LIFETIME_MAX       3000
-#define TX_MSDU_LIFETIME_DEF       512
-#define RX_MSDU_LIFETIME_MIN       0
-#define RX_MSDU_LIFETIME_MAX       0xFFFFFFFF
-#define RX_MSDU_LIFETIME_DEF       512000
-
-struct acx_rx_msdu_lifetime {
-	struct acx_header header;
-
-	/*
-	 * The maximum amount of time, in TU, before the
-	 * firmware discards the MSDU.
-	 */
-	u32 lifetime;
-} __packed;
-
-/*
- * RX Config Options Table
- * Bit		Definition
- * ===		==========
- * 31:14		Reserved
- * 13		Copy RX Status - when set, write three receive status words
- * 	 	to top of rx'd MPDUs.
- * 		When cleared, do not write three status words (added rev 1.5)
- * 12		Reserved
- * 11		RX Complete upon FCS error - when set, give rx complete
- *	 	interrupt for FCS errors, after the rx filtering, e.g. unicast
- *	 	frames not to us with FCS error will not generate an interrupt.
- * 10		SSID Filter Enable - When set, the WiLink discards all beacon,
- *	        probe request, and probe response frames with an SSID that does
- *		not match the SSID specified by the host in the START/JOIN
- *		command.
- *		When clear, the WiLink receives frames with any SSID.
- * 9		Broadcast Filter Enable - When set, the WiLink discards all
- * 	 	broadcast frames. When clear, the WiLink receives all received
- *		broadcast frames.
- * 8:6		Reserved
- * 5		BSSID Filter Enable - When set, the WiLink discards any frames
- * 	 	with a BSSID that does not match the BSSID specified by the
- *		host.
- *		When clear, the WiLink receives frames from any BSSID.
- * 4		MAC Addr Filter - When set, the WiLink discards any frames
- * 	 	with a destination address that does not match the MAC address
- *		of the adaptor.
- *		When clear, the WiLink receives frames destined to any MAC
- *		address.
- * 3		Promiscuous - When set, the WiLink receives all valid frames
- * 	 	(i.e., all frames that pass the FCS check).
- *		When clear, only frames that pass the other filters specified
- *		are received.
- * 2		FCS - When set, the WiLink includes the FCS with the received
- *	 	frame.
- *		When cleared, the FCS is discarded.
- * 1		PLCP header - When set, write all data from baseband to frame
- * 	 	buffer including PHY header.
- * 0		Reserved - Always equal to 0.
- *
- * RX Filter Options Table
- * Bit		Definition
- * ===		==========
- * 31:12		Reserved - Always equal to 0.
- * 11		Association - When set, the WiLink receives all association
- * 	 	related frames (association request/response, reassocation
- *		request/response, and disassociation). When clear, these frames
- *		are discarded.
- * 10		Auth/De auth - When set, the WiLink receives all authentication
- * 	 	and de-authentication frames. When clear, these frames are
- *		discarded.
- * 9		Beacon - When set, the WiLink receives all beacon frames.
- * 	 	When clear, these frames are discarded.
- * 8		Contention Free - When set, the WiLink receives all contention
- * 	 	free frames.
- *		When clear, these frames are discarded.
- * 7		Control - When set, the WiLink receives all control frames.
- * 	 	When clear, these frames are discarded.
- * 6		Data - When set, the WiLink receives all data frames.
- * 	 	When clear, these frames are discarded.
- * 5		FCS Error - When set, the WiLink receives frames that have FCS
- *	 	errors.
- *		When clear, these frames are discarded.
- * 4		Management - When set, the WiLink receives all management
- *		frames.
- * 	 	When clear, these frames are discarded.
- * 3		Probe Request - When set, the WiLink receives all probe request
- * 	 	frames.
- *		When clear, these frames are discarded.
- * 2		Probe Response - When set, the WiLink receives all probe
- * 		response frames.
- *		When clear, these frames are discarded.
- * 1		RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK
- * 	 	frames.
- *		When clear, these frames are discarded.
- * 0		Rsvd Type/Sub Type - When set, the WiLink receives all frames
- * 	 	that have reserved frame types and sub types as defined by the
- *		802.11 specification.
- *		When clear, these frames are discarded.
- */
-struct acx_rx_config {
-	struct acx_header header;
-
-	u32 config_options;
-	u32 filter_options;
-} __packed;
-
-enum {
-	QOS_AC_BE = 0,
-	QOS_AC_BK,
-	QOS_AC_VI,
-	QOS_AC_VO,
-	QOS_HIGHEST_AC_INDEX = QOS_AC_VO,
-};
-
-#define MAX_NUM_OF_AC             (QOS_HIGHEST_AC_INDEX+1)
-#define FIRST_AC_INDEX            QOS_AC_BE
-#define MAX_NUM_OF_802_1d_TAGS    8
-#define AC_PARAMS_MAX_TSID        15
-#define MAX_APSD_CONF             0xffff
-
-#define  QOS_TX_HIGH_MIN      (0)
-#define  QOS_TX_HIGH_MAX      (100)
-
-#define  QOS_TX_HIGH_BK_DEF   (25)
-#define  QOS_TX_HIGH_BE_DEF   (35)
-#define  QOS_TX_HIGH_VI_DEF   (35)
-#define  QOS_TX_HIGH_VO_DEF   (35)
-
-#define  QOS_TX_LOW_BK_DEF    (15)
-#define  QOS_TX_LOW_BE_DEF    (25)
-#define  QOS_TX_LOW_VI_DEF    (25)
-#define  QOS_TX_LOW_VO_DEF    (25)
-
-struct acx_tx_queue_qos_config {
-	struct acx_header header;
-
-	u8 qid;
-	u8 pad[3];
-
-	/* Max number of blocks allowd in the queue */
-	u16 high_threshold;
-
-	/* Lowest memory blocks guaranteed for this queue */
-	u16 low_threshold;
-} __packed;
-
-struct acx_packet_detection {
-	struct acx_header header;
-
-	u32 threshold;
-} __packed;
-
-
-enum acx_slot_type {
-	SLOT_TIME_LONG = 0,
-	SLOT_TIME_SHORT = 1,
-	DEFAULT_SLOT_TIME = SLOT_TIME_SHORT,
-	MAX_SLOT_TIMES = 0xFF
-};
-
-#define STATION_WONE_INDEX 0
-
-struct acx_slot {
-	struct acx_header header;
-
-	u8 wone_index; /* Reserved */
-	u8 slot_time;
-	u8 reserved[6];
-} __packed;
-
-
-#define ADDRESS_GROUP_MAX	(8)
-#define ADDRESS_GROUP_MAX_LEN	(ETH_ALEN * ADDRESS_GROUP_MAX)
-
-struct acx_dot11_grp_addr_tbl {
-	struct acx_header header;
-
-	u8 enabled;
-	u8 num_groups;
-	u8 pad[2];
-	u8 mac_table[ADDRESS_GROUP_MAX_LEN];
-} __packed;
-
-
-#define  RX_TIMEOUT_PS_POLL_MIN    0
-#define  RX_TIMEOUT_PS_POLL_MAX    (200000)
-#define  RX_TIMEOUT_PS_POLL_DEF    (15)
-#define  RX_TIMEOUT_UPSD_MIN       0
-#define  RX_TIMEOUT_UPSD_MAX       (200000)
-#define  RX_TIMEOUT_UPSD_DEF       (15)
-
-struct acx_rx_timeout {
-	struct acx_header header;
-
-	/*
-	 * The longest time the STA will wait to receive
-	 * traffic from the AP after a PS-poll has been
-	 * transmitted.
-	 */
-	u16 ps_poll_timeout;
-
-	/*
-	 * The longest time the STA will wait to receive
-	 * traffic from the AP after a frame has been sent
-	 * from an UPSD enabled queue.
-	 */
-	u16 upsd_timeout;
-} __packed;
-
-#define RTS_THRESHOLD_MIN              0
-#define RTS_THRESHOLD_MAX              4096
-#define RTS_THRESHOLD_DEF              2347
-
-struct acx_rts_threshold {
-	struct acx_header header;
-
-	u16 threshold;
-	u8 pad[2];
-} __packed;
-
-struct acx_beacon_filter_option {
-	struct acx_header header;
-
-	u8 enable;
-
-	/*
-	 * The number of beacons without the unicast TIM
-	 * bit set that the firmware buffers before
-	 * signaling the host about ready frames.
-	 * When set to 0 and the filter is enabled, beacons
-	 * without the unicast TIM bit set are dropped.
-	 */
-	u8 max_num_beacons;
-	u8 pad[2];
-} __packed;
-
-/*
- * ACXBeaconFilterEntry (not 221)
- * Byte Offset     Size (Bytes)    Definition
- * ===========     ============    ==========
- * 0				1               IE identifier
- * 1               1               Treatment bit mask
- *
- * ACXBeaconFilterEntry (221)
- * Byte Offset     Size (Bytes)    Definition
- * ===========     ============    ==========
- * 0               1               IE identifier
- * 1               1               Treatment bit mask
- * 2               3               OUI
- * 5               1               Type
- * 6               2               Version
- *
- *
- * Treatment bit mask - The information element handling:
- * bit 0 - The information element is compared and transferred
- * in case of change.
- * bit 1 - The information element is transferred to the host
- * with each appearance or disappearance.
- * Note that both bits can be set at the same time.
- */
-#define	BEACON_FILTER_TABLE_MAX_IE_NUM		       (32)
-#define BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM (6)
-#define BEACON_FILTER_TABLE_IE_ENTRY_SIZE	       (2)
-#define BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE (6)
-#define BEACON_FILTER_TABLE_MAX_SIZE ((BEACON_FILTER_TABLE_MAX_IE_NUM * \
-			    BEACON_FILTER_TABLE_IE_ENTRY_SIZE) + \
-			   (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \
-			    BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE))
-
-#define BEACON_RULE_PASS_ON_CHANGE                     BIT(0)
-#define BEACON_RULE_PASS_ON_APPEARANCE                 BIT(1)
-
-#define BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN         (37)
-
-struct acx_beacon_filter_ie_table {
-	struct acx_header header;
-
-	u8 num_ie;
-	u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
-	u8 pad[3];
-} __packed;
-
-#define SYNCH_FAIL_DEFAULT_THRESHOLD    10     /* number of beacons */
-#define NO_BEACON_DEFAULT_TIMEOUT       (500) /* in microseconds */
-
-struct acx_conn_monit_params {
-	struct acx_header header;
-
-	u32 synch_fail_thold; /* number of beacons missed */
-	u32 bss_lose_timeout; /* number of TU's from synch fail */
-};
-
-enum {
-	SG_ENABLE = 0,
-	SG_DISABLE,
-	SG_SENSE_NO_ACTIVITY,
-	SG_SENSE_ACTIVE
-};
-
-struct acx_bt_wlan_coex {
-	struct acx_header header;
-
-	/*
-	 * 0 -> PTA enabled
-	 * 1 -> PTA disabled
-	 * 2 -> sense no active mode, i.e.
-	 *      an interrupt is sent upon
-	 *      BT activity.
-	 * 3 -> PTA is switched on in response
-	 *      to the interrupt sending.
-	 */
-	u8 enable;
-	u8 pad[3];
-} __packed;
-
-#define PTA_ANTENNA_TYPE_DEF		  (0)
-#define PTA_BT_HP_MAXTIME_DEF		  (2000)
-#define PTA_WLAN_HP_MAX_TIME_DEF	  (5000)
-#define PTA_SENSE_DISABLE_TIMER_DEF	  (1350)
-#define PTA_PROTECTIVE_RX_TIME_DEF	  (1500)
-#define PTA_PROTECTIVE_TX_TIME_DEF	  (1500)
-#define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000)
-#define PTA_SIGNALING_TYPE_DEF		  (1)
-#define PTA_AFH_LEVERAGE_ON_DEF		  (0)
-#define PTA_NUMBER_QUIET_CYCLE_DEF	  (0)
-#define PTA_MAX_NUM_CTS_DEF		  (3)
-#define PTA_NUMBER_OF_WLAN_PACKETS_DEF	  (2)
-#define PTA_NUMBER_OF_BT_PACKETS_DEF	  (2)
-#define PTA_PROTECTIVE_RX_TIME_FAST_DEF	  (1500)
-#define PTA_PROTECTIVE_TX_TIME_FAST_DEF	  (3000)
-#define PTA_CYCLE_TIME_FAST_DEF		  (8700)
-#define PTA_RX_FOR_AVALANCHE_DEF	  (5)
-#define PTA_ELP_HP_DEF			  (0)
-#define PTA_ANTI_STARVE_PERIOD_DEF	  (500)
-#define PTA_ANTI_STARVE_NUM_CYCLE_DEF	  (4)
-#define PTA_ALLOW_PA_SD_DEF		  (1)
-#define PTA_TIME_BEFORE_BEACON_DEF	  (6300)
-#define PTA_HPDM_MAX_TIME_DEF		  (1600)
-#define PTA_TIME_OUT_NEXT_WLAN_DEF	  (2550)
-#define PTA_AUTO_MODE_NO_CTS_DEF	  (0)
-#define PTA_BT_HP_RESPECTED_DEF		  (3)
-#define PTA_WLAN_RX_MIN_RATE_DEF	  (24)
-#define PTA_ACK_MODE_DEF		  (1)
-
-struct acx_bt_wlan_coex_param {
-	struct acx_header header;
-
-	/*
-	 * The minimum rate of a received WLAN packet in the STA,
-	 * during protective mode, of which a new BT-HP request
-	 * during this Rx will always be respected and gain the antenna.
-	 */
-	u32 min_rate;
-
-	/* Max time the BT HP will be respected. */
-	u16 bt_hp_max_time;
-
-	/* Max time the WLAN HP will be respected. */
-	u16 wlan_hp_max_time;
-
-	/*
-	 * The time between the last BT activity
-	 * and the moment when the sense mode returns
-	 * to SENSE_INACTIVE.
-	 */
-	u16 sense_disable_timer;
-
-	/* Time before the next BT HP instance */
-	u16 rx_time_bt_hp;
-	u16 tx_time_bt_hp;
-
-	/* range: 10-20000    default: 1500 */
-	u16 rx_time_bt_hp_fast;
-	u16 tx_time_bt_hp_fast;
-
-	/* range: 2000-65535  default: 8700 */
-	u16 wlan_cycle_fast;
-
-	/* range: 0 - 15000 (Msec) default: 1000 */
-	u16 bt_anti_starvation_period;
-
-	/* range 400-10000(Usec) default: 3000 */
-	u16 next_bt_lp_packet;
-
-	/* Deafult: worst case for BT DH5 traffic */
-	u16 wake_up_beacon;
-
-	/* range: 0-50000(Usec) default: 1050 */
-	u16 hp_dm_max_guard_time;
-
-	/*
-	 * This is to prevent both BT & WLAN antenna
-	 * starvation.
-	 * Range: 100-50000(Usec) default:2550
-	 */
-	u16 next_wlan_packet;
-
-	/* 0 -> shared antenna */
-	u8 antenna_type;
-
-	/*
-	 * 0 -> TI legacy
-	 * 1 -> Palau
-	 */
-	u8 signal_type;
-
-	/*
-	 * BT AFH status
-	 * 0 -> no AFH
-	 * 1 -> from dedicated GPIO
-	 * 2 -> AFH on (from host)
-	 */
-	u8 afh_leverage_on;
-
-	/*
-	 * The number of cycles during which no
-	 * TX will be sent after 1 cycle of RX
-	 * transaction in protective mode
-	 */
-	u8 quiet_cycle_num;
-
-	/*
-	 * The maximum number of CTSs that will
-	 * be sent for receiving RX packet in
-	 * protective mode
-	 */
-	u8 max_cts;
-
-	/*
-	 * The number of WLAN packets
-	 * transferred in common mode before
-	 * switching to BT.
-	 */
-	u8 wlan_packets_num;
-
-	/*
-	 * The number of BT packets
-	 * transferred in common mode before
-	 * switching to WLAN.
-	 */
-	u8 bt_packets_num;
-
-	/* range: 1-255  default: 5 */
-	u8 missed_rx_avalanche;
-
-	/* range: 0-1    default: 1 */
-	u8 wlan_elp_hp;
-
-	/* range: 0 - 15  default: 4 */
-	u8 bt_anti_starvation_cycles;
-
-	u8 ack_mode_dual_ant;
-
-	/*
-	 * Allow PA_SD assertion/de-assertion
-	 * during enabled BT activity.
-	 */
-	u8 pa_sd_enable;
-
-	/*
-	 * Enable/Disable PTA in auto mode:
-	 * Support Both Active & P.S modes
-	 */
-	u8 pta_auto_mode_enable;
-
-	/* range: 0 - 20  default: 1 */
-	u8 bt_hp_respected_num;
-} __packed;
-
-#define CCA_THRSH_ENABLE_ENERGY_D       0x140A
-#define CCA_THRSH_DISABLE_ENERGY_D      0xFFEF
-
-struct acx_energy_detection {
-	struct acx_header header;
-
-	/* The RX Clear Channel Assessment threshold in the PHY */
-	u16 rx_cca_threshold;
-	u8 tx_energy_detection;
-	u8 pad;
-} __packed;
-
-#define BCN_RX_TIMEOUT_DEF_VALUE        10000
-#define BROADCAST_RX_TIMEOUT_DEF_VALUE  20000
-#define RX_BROADCAST_IN_PS_DEF_VALUE    1
-#define CONSECUTIVE_PS_POLL_FAILURE_DEF 4
-
-struct acx_beacon_broadcast {
-	struct acx_header header;
-
-	u16 beacon_rx_timeout;
-	u16 broadcast_timeout;
-
-	/* Enables receiving of broadcast packets in PS mode */
-	u8 rx_broadcast_in_ps;
-
-	/* Consecutive PS Poll failures before updating the host */
-	u8 ps_poll_threshold;
-	u8 pad[2];
-} __packed;
-
-struct acx_event_mask {
-	struct acx_header header;
-
-	u32 event_mask;
-	u32 high_event_mask; /* Unused */
-} __packed;
-
-#define CFG_RX_FCS		BIT(2)
-#define CFG_RX_ALL_GOOD		BIT(3)
-#define CFG_UNI_FILTER_EN	BIT(4)
-#define CFG_BSSID_FILTER_EN	BIT(5)
-#define CFG_MC_FILTER_EN	BIT(6)
-#define CFG_MC_ADDR0_EN		BIT(7)
-#define CFG_MC_ADDR1_EN		BIT(8)
-#define CFG_BC_REJECT_EN	BIT(9)
-#define CFG_SSID_FILTER_EN	BIT(10)
-#define CFG_RX_INT_FCS_ERROR	BIT(11)
-#define CFG_RX_INT_ENCRYPTED	BIT(12)
-#define CFG_RX_WR_RX_STATUS	BIT(13)
-#define CFG_RX_FILTER_NULTI	BIT(14)
-#define CFG_RX_RESERVE		BIT(15)
-#define CFG_RX_TIMESTAMP_TSF	BIT(16)
-
-#define CFG_RX_RSV_EN		BIT(0)
-#define CFG_RX_RCTS_ACK		BIT(1)
-#define CFG_RX_PRSP_EN		BIT(2)
-#define CFG_RX_PREQ_EN		BIT(3)
-#define CFG_RX_MGMT_EN		BIT(4)
-#define CFG_RX_FCS_ERROR	BIT(5)
-#define CFG_RX_DATA_EN		BIT(6)
-#define CFG_RX_CTL_EN		BIT(7)
-#define CFG_RX_CF_EN		BIT(8)
-#define CFG_RX_BCN_EN		BIT(9)
-#define CFG_RX_AUTH_EN		BIT(10)
-#define CFG_RX_ASSOC_EN		BIT(11)
-
-#define SCAN_PASSIVE		BIT(0)
-#define SCAN_5GHZ_BAND		BIT(1)
-#define SCAN_TRIGGERED		BIT(2)
-#define SCAN_PRIORITY_HIGH	BIT(3)
-
-struct acx_fw_gen_frame_rates {
-	struct acx_header header;
-
-	u8 tx_ctrl_frame_rate; /* RATE_* */
-	u8 tx_ctrl_frame_mod; /* CCK_* or PBCC_* */
-	u8 tx_mgt_frame_rate;
-	u8 tx_mgt_frame_mod;
-} __packed;
-
-/* STA MAC */
-struct acx_dot11_station_id {
-	struct acx_header header;
-
-	u8 mac[ETH_ALEN];
-	u8 pad[2];
-} __packed;
-
-struct acx_feature_config {
-	struct acx_header header;
-
-	u32 options;
-	u32 data_flow_options;
-} __packed;
-
-struct acx_current_tx_power {
-	struct acx_header header;
-
-	u8  current_tx_power;
-	u8  padding[3];
-} __packed;
-
-struct acx_dot11_default_key {
-	struct acx_header header;
-
-	u8 id;
-	u8 pad[3];
-} __packed;
-
-struct acx_tsf_info {
-	struct acx_header header;
-
-	u32 current_tsf_msb;
-	u32 current_tsf_lsb;
-	u32 last_TBTT_msb;
-	u32 last_TBTT_lsb;
-	u8 last_dtim_count;
-	u8 pad[3];
-} __packed;
-
-enum acx_wake_up_event {
-	WAKE_UP_EVENT_BEACON_BITMAP	= 0x01, /* Wake on every Beacon*/
-	WAKE_UP_EVENT_DTIM_BITMAP	= 0x02,	/* Wake on every DTIM*/
-	WAKE_UP_EVENT_N_DTIM_BITMAP	= 0x04, /* Wake on every Nth DTIM */
-	WAKE_UP_EVENT_N_BEACONS_BITMAP	= 0x08, /* Wake on every Nth Beacon */
-	WAKE_UP_EVENT_BITS_MASK		= 0x0F
-};
-
-struct acx_wake_up_condition {
-	struct acx_header header;
-
-	u8 wake_up_event; /* Only one bit can be set */
-	u8 listen_interval;
-	u8 pad[2];
-} __packed;
-
-struct acx_aid {
-	struct acx_header header;
-
-	/*
-	 * To be set when associated with an AP.
-	 */
-	u16 aid;
-	u8 pad[2];
-} __packed;
-
-enum acx_preamble_type {
-	ACX_PREAMBLE_LONG = 0,
-	ACX_PREAMBLE_SHORT = 1
-};
-
-struct acx_preamble {
-	struct acx_header header;
-
-	/*
-	 * When set, the WiLink transmits the frames with a short preamble and
-	 * when cleared, the WiLink transmits the frames with a long preamble.
-	 */
-	u8 preamble;
-	u8 padding[3];
-} __packed;
-
-enum acx_ctsprotect_type {
-	CTSPROTECT_DISABLE = 0,
-	CTSPROTECT_ENABLE = 1
-};
-
-struct acx_ctsprotect {
-	struct acx_header header;
-	u8 ctsprotect;
-	u8 padding[3];
-} __packed;
-
-struct acx_tx_statistics {
-	u32 internal_desc_overflow;
-}  __packed;
-
-struct acx_rx_statistics {
-	u32 out_of_mem;
-	u32 hdr_overflow;
-	u32 hw_stuck;
-	u32 dropped;
-	u32 fcs_err;
-	u32 xfr_hint_trig;
-	u32 path_reset;
-	u32 reset_counter;
-} __packed;
-
-struct acx_dma_statistics {
-	u32 rx_requested;
-	u32 rx_errors;
-	u32 tx_requested;
-	u32 tx_errors;
-}  __packed;
-
-struct acx_isr_statistics {
-	/* host command complete */
-	u32 cmd_cmplt;
-
-	/* fiqisr() */
-	u32 fiqs;
-
-	/* (INT_STS_ND & INT_TRIG_RX_HEADER) */
-	u32 rx_headers;
-
-	/* (INT_STS_ND & INT_TRIG_RX_CMPLT) */
-	u32 rx_completes;
-
-	/* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */
-	u32 rx_mem_overflow;
-
-	/* (INT_STS_ND & INT_TRIG_S_RX_RDY) */
-	u32 rx_rdys;
-
-	/* irqisr() */
-	u32 irqs;
-
-	/* (INT_STS_ND & INT_TRIG_TX_PROC) */
-	u32 tx_procs;
-
-	/* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */
-	u32 decrypt_done;
-
-	/* (INT_STS_ND & INT_TRIG_DMA0) */
-	u32 dma0_done;
-
-	/* (INT_STS_ND & INT_TRIG_DMA1) */
-	u32 dma1_done;
-
-	/* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */
-	u32 tx_exch_complete;
-
-	/* (INT_STS_ND & INT_TRIG_COMMAND) */
-	u32 commands;
-
-	/* (INT_STS_ND & INT_TRIG_RX_PROC) */
-	u32 rx_procs;
-
-	/* (INT_STS_ND & INT_TRIG_PM_802) */
-	u32 hw_pm_mode_changes;
-
-	/* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */
-	u32 host_acknowledges;
-
-	/* (INT_STS_ND & INT_TRIG_PM_PCI) */
-	u32 pci_pm;
-
-	/* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */
-	u32 wakeups;
-
-	/* (INT_STS_ND & INT_TRIG_LOW_RSSI) */
-	u32 low_rssi;
-} __packed;
-
-struct acx_wep_statistics {
-	/* WEP address keys configured */
-	u32 addr_key_count;
-
-	/* default keys configured */
-	u32 default_key_count;
-
-	u32 reserved;
-
-	/* number of times that WEP key not found on lookup */
-	u32 key_not_found;
-
-	/* number of times that WEP key decryption failed */
-	u32 decrypt_fail;
-
-	/* WEP packets decrypted */
-	u32 packets;
-
-	/* WEP decrypt interrupts */
-	u32 interrupt;
-} __packed;
-
-#define ACX_MISSED_BEACONS_SPREAD 10
-
-struct acx_pwr_statistics {
-	/* the amount of enters into power save mode (both PD & ELP) */
-	u32 ps_enter;
-
-	/* the amount of enters into ELP mode */
-	u32 elp_enter;
-
-	/* the amount of missing beacon interrupts to the host */
-	u32 missing_bcns;
-
-	/* the amount of wake on host-access times */
-	u32 wake_on_host;
-
-	/* the amount of wake on timer-expire */
-	u32 wake_on_timer_exp;
-
-	/* the number of packets that were transmitted with PS bit set */
-	u32 tx_with_ps;
-
-	/* the number of packets that were transmitted with PS bit clear */
-	u32 tx_without_ps;
-
-	/* the number of received beacons */
-	u32 rcvd_beacons;
-
-	/* the number of entering into PowerOn (power save off) */
-	u32 power_save_off;
-
-	/* the number of entries into power save mode */
-	u16 enable_ps;
-
-	/*
-	 * the number of exits from power save, not including failed PS
-	 * transitions
-	 */
-	u16 disable_ps;
-
-	/*
-	 * the number of times the TSF counter was adjusted because
-	 * of drift
-	 */
-	u32 fix_tsf_ps;
-
-	/* Gives statistics about the spread continuous missed beacons.
-	 * The 16 LSB are dedicated for the PS mode.
-	 * The 16 MSB are dedicated for the PS mode.
-	 * cont_miss_bcns_spread[0] - single missed beacon.
-	 * cont_miss_bcns_spread[1] - two continuous missed beacons.
-	 * cont_miss_bcns_spread[2] - three continuous missed beacons.
-	 * ...
-	 * cont_miss_bcns_spread[9] - ten and more continuous missed beacons.
-	*/
-	u32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD];
-
-	/* the number of beacons in awake mode */
-	u32 rcvd_awake_beacons;
-} __packed;
-
-struct acx_mic_statistics {
-	u32 rx_pkts;
-	u32 calc_failure;
-} __packed;
-
-struct acx_aes_statistics {
-	u32 encrypt_fail;
-	u32 decrypt_fail;
-	u32 encrypt_packets;
-	u32 decrypt_packets;
-	u32 encrypt_interrupt;
-	u32 decrypt_interrupt;
-} __packed;
-
-struct acx_event_statistics {
-	u32 heart_beat;
-	u32 calibration;
-	u32 rx_mismatch;
-	u32 rx_mem_empty;
-	u32 rx_pool;
-	u32 oom_late;
-	u32 phy_transmit_error;
-	u32 tx_stuck;
-} __packed;
-
-struct acx_ps_statistics {
-	u32 pspoll_timeouts;
-	u32 upsd_timeouts;
-	u32 upsd_max_sptime;
-	u32 upsd_max_apturn;
-	u32 pspoll_max_apturn;
-	u32 pspoll_utilization;
-	u32 upsd_utilization;
-} __packed;
-
-struct acx_rxpipe_statistics {
-	u32 rx_prep_beacon_drop;
-	u32 descr_host_int_trig_rx_data;
-	u32 beacon_buffer_thres_host_int_trig_rx_data;
-	u32 missed_beacon_host_int_trig_rx_data;
-	u32 tx_xfr_host_int_trig_rx_data;
-} __packed;
-
-struct acx_statistics {
-	struct acx_header header;
-
-	struct acx_tx_statistics tx;
-	struct acx_rx_statistics rx;
-	struct acx_dma_statistics dma;
-	struct acx_isr_statistics isr;
-	struct acx_wep_statistics wep;
-	struct acx_pwr_statistics pwr;
-	struct acx_aes_statistics aes;
-	struct acx_mic_statistics mic;
-	struct acx_event_statistics event;
-	struct acx_ps_statistics ps;
-	struct acx_rxpipe_statistics rxpipe;
-} __packed;
-
-#define ACX_MAX_RATE_CLASSES       8
-#define ACX_RATE_MASK_UNSPECIFIED  0
-#define ACX_RATE_RETRY_LIMIT      10
-
-struct acx_rate_class {
-	u32 enabled_rates;
-	u8 short_retry_limit;
-	u8 long_retry_limit;
-	u8 aflags;
-	u8 reserved;
-};
-
-struct acx_rate_policy {
-	struct acx_header header;
-
-	u32 rate_class_cnt;
-	struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES];
-} __packed;
-
-struct wl1251_acx_memory {
-	__le16 num_stations; /* number of STAs to be supported. */
-	u16 reserved_1;
-
-	/*
-	 * Nmber of memory buffers for the RX mem pool.
-	 * The actual number may be less if there are
-	 * not enough blocks left for the minimum num
-	 * of TX ones.
-	 */
-	u8 rx_mem_block_num;
-	u8 reserved_2;
-	u8 num_tx_queues; /* From 1 to 16 */
-	u8 host_if_options; /* HOST_IF* */
-	u8 tx_min_mem_block_num;
-	u8 num_ssid_profiles;
-	__le16 debug_buffer_size;
-} __packed;
-
-
-#define ACX_RX_DESC_MIN                1
-#define ACX_RX_DESC_MAX                127
-#define ACX_RX_DESC_DEF                32
-struct wl1251_acx_rx_queue_config {
-	u8 num_descs;
-	u8 pad;
-	u8 type;
-	u8 priority;
-	__le32 dma_address;
-} __packed;
-
-#define ACX_TX_DESC_MIN                1
-#define ACX_TX_DESC_MAX                127
-#define ACX_TX_DESC_DEF                16
-struct wl1251_acx_tx_queue_config {
-    u8 num_descs;
-    u8 pad[2];
-    u8 attributes;
-} __packed;
-
-#define MAX_TX_QUEUE_CONFIGS 5
-#define MAX_TX_QUEUES 4
-struct wl1251_acx_config_memory {
-	struct acx_header header;
-
-	struct wl1251_acx_memory mem_config;
-	struct wl1251_acx_rx_queue_config rx_queue_config;
-	struct wl1251_acx_tx_queue_config tx_queue_config[MAX_TX_QUEUE_CONFIGS];
-} __packed;
-
-struct wl1251_acx_mem_map {
-	struct acx_header header;
-
-	void *code_start;
-	void *code_end;
-
-	void *wep_defkey_start;
-	void *wep_defkey_end;
-
-	void *sta_table_start;
-	void *sta_table_end;
-
-	void *packet_template_start;
-	void *packet_template_end;
-
-	void *queue_memory_start;
-	void *queue_memory_end;
-
-	void *packet_memory_pool_start;
-	void *packet_memory_pool_end;
-
-	void *debug_buffer1_start;
-	void *debug_buffer1_end;
-
-	void *debug_buffer2_start;
-	void *debug_buffer2_end;
-
-	/* Number of blocks FW allocated for TX packets */
-	u32 num_tx_mem_blocks;
-
-	/* Number of blocks FW allocated for RX packets */
-	u32 num_rx_mem_blocks;
-} __packed;
-
-
-struct wl1251_acx_wr_tbtt_and_dtim {
-
-	struct acx_header header;
-
-	/* Time in TUs between two consecutive beacons */
-	u16 tbtt;
-
-	/*
-	 * DTIM period
-	 * For BSS: Number of TBTTs in a DTIM period (range: 1-10)
-	 * For IBSS: value shall be set to 1
-	*/
-	u8  dtim;
-	u8  padding;
-} __packed;
-
-struct wl1251_acx_ac_cfg {
-	struct acx_header header;
-
-	/*
-	 * Access Category - The TX queue's access category
-	 * (refer to AccessCategory_enum)
-	 */
-	u8 ac;
-
-	/*
-	 * The contention window minimum size (in slots) for
-	 * the access class.
-	 */
-	u8 cw_min;
-
-	/*
-	 * The contention window maximum size (in slots) for
-	 * the access class.
-	 */
-	u16 cw_max;
-
-	/* The AIF value (in slots) for the access class. */
-	u8 aifsn;
-
-	u8 reserved;
-
-	/* The TX Op Limit (in microseconds) for the access class. */
-	u16 txop_limit;
-} __packed;
-
-
-enum wl1251_acx_channel_type {
-	CHANNEL_TYPE_DCF	= 0,
-	CHANNEL_TYPE_EDCF	= 1,
-	CHANNEL_TYPE_HCCA	= 2,
-};
-
-enum wl1251_acx_ps_scheme {
-	/* regular ps: simple sending of packets */
-	WL1251_ACX_PS_SCHEME_LEGACY	= 0,
-
-	/* sending a packet triggers a unscheduled apsd downstream */
-	WL1251_ACX_PS_SCHEME_UPSD_TRIGGER	= 1,
-
-	/* a pspoll packet will be sent before every data packet */
-	WL1251_ACX_PS_SCHEME_LEGACY_PSPOLL	= 2,
-
-	/* scheduled apsd mode */
-	WL1251_ACX_PS_SCHEME_SAPSD		= 3,
-};
-
-enum wl1251_acx_ack_policy {
-	WL1251_ACX_ACK_POLICY_LEGACY	= 0,
-	WL1251_ACX_ACK_POLICY_NO_ACK	= 1,
-	WL1251_ACX_ACK_POLICY_BLOCK	= 2,
-};
-
-struct wl1251_acx_tid_cfg {
-	struct acx_header header;
-
-	/* tx queue id number (0-7) */
-	u8 queue;
-
-	/* channel access type for the queue, enum wl1251_acx_channel_type */
-	u8 type;
-
-	/* EDCA: ac index (0-3), HCCA: traffic stream id (8-15) */
-	u8 tsid;
-
-	/* ps scheme of the specified queue, enum wl1251_acx_ps_scheme */
-	u8 ps_scheme;
-
-	/* the tx queue ack policy, enum wl1251_acx_ack_policy */
-	u8 ack_policy;
-
-	u8 padding[3];
-
-	/* not supported */
-	u32 apsdconf[2];
-} __packed;
-
-/*************************************************************************
-
-    Host Interrupt Register (WiLink -> Host)
-
-**************************************************************************/
-
-/* RX packet is ready in Xfer buffer #0 */
-#define WL1251_ACX_INTR_RX0_DATA      BIT(0)
-
-/* TX result(s) are in the TX complete buffer */
-#define WL1251_ACX_INTR_TX_RESULT	BIT(1)
-
-/* OBSOLETE */
-#define WL1251_ACX_INTR_TX_XFR		BIT(2)
-
-/* RX packet is ready in Xfer buffer #1 */
-#define WL1251_ACX_INTR_RX1_DATA	BIT(3)
-
-/* Event was entered to Event MBOX #A */
-#define WL1251_ACX_INTR_EVENT_A		BIT(4)
-
-/* Event was entered to Event MBOX #B */
-#define WL1251_ACX_INTR_EVENT_B		BIT(5)
-
-/* OBSOLETE */
-#define WL1251_ACX_INTR_WAKE_ON_HOST	BIT(6)
-
-/* Trace meassge on MBOX #A */
-#define WL1251_ACX_INTR_TRACE_A		BIT(7)
-
-/* Trace meassge on MBOX #B */
-#define WL1251_ACX_INTR_TRACE_B		BIT(8)
-
-/* Command processing completion */
-#define WL1251_ACX_INTR_CMD_COMPLETE	BIT(9)
-
-/* Init sequence is done */
-#define WL1251_ACX_INTR_INIT_COMPLETE	BIT(14)
-
-#define WL1251_ACX_INTR_ALL           0xFFFFFFFF
-
-enum {
-	ACX_WAKE_UP_CONDITIONS      = 0x0002,
-	ACX_MEM_CFG                 = 0x0003,
-	ACX_SLOT                    = 0x0004,
-	ACX_QUEUE_HEAD              = 0x0005, /* for MASTER mode only */
-	ACX_AC_CFG                  = 0x0007,
-	ACX_MEM_MAP                 = 0x0008,
-	ACX_AID                     = 0x000A,
-	ACX_RADIO_PARAM             = 0x000B, /* Not used */
-	ACX_CFG                     = 0x000C, /* Not used */
-	ACX_FW_REV                  = 0x000D,
-	ACX_MEDIUM_USAGE            = 0x000F,
-	ACX_RX_CFG                  = 0x0010,
-	ACX_TX_QUEUE_CFG            = 0x0011, /* FIXME: only used by wl1251 */
-	ACX_BSS_IN_PS               = 0x0012, /* for AP only */
-	ACX_STATISTICS              = 0x0013, /* Debug API */
-	ACX_FEATURE_CFG             = 0x0015,
-	ACX_MISC_CFG                = 0x0017, /* Not used */
-	ACX_TID_CFG                 = 0x001A,
-	ACX_BEACON_FILTER_OPT       = 0x001F,
-	ACX_LOW_RSSI                = 0x0020,
-	ACX_NOISE_HIST              = 0x0021,
-	ACX_HDK_VERSION             = 0x0022, /* ??? */
-	ACX_PD_THRESHOLD            = 0x0023,
-	ACX_DATA_PATH_PARAMS        = 0x0024, /* WO */
-	ACX_DATA_PATH_RESP_PARAMS   = 0x0024, /* RO */
-	ACX_CCA_THRESHOLD           = 0x0025,
-	ACX_EVENT_MBOX_MASK         = 0x0026,
-#ifdef FW_RUNNING_AS_AP
-	ACX_DTIM_PERIOD             = 0x0027, /* for AP only */
-#else
-	ACX_WR_TBTT_AND_DTIM        = 0x0027, /* STA only */
-#endif
-	ACX_ACI_OPTION_CFG          = 0x0029, /* OBSOLETE (for 1251)*/
-	ACX_GPIO_CFG                = 0x002A, /* Not used */
-	ACX_GPIO_SET                = 0x002B, /* Not used */
-	ACX_PM_CFG                  = 0x002C, /* To Be Documented */
-	ACX_CONN_MONIT_PARAMS       = 0x002D,
-	ACX_AVERAGE_RSSI            = 0x002E, /* Not used */
-	ACX_CONS_TX_FAILURE         = 0x002F,
-	ACX_BCN_DTIM_OPTIONS        = 0x0031,
-	ACX_SG_ENABLE               = 0x0032,
-	ACX_SG_CFG                  = 0x0033,
-	ACX_ANTENNA_DIVERSITY_CFG   = 0x0035, /* To Be Documented */
-	ACX_LOW_SNR		    = 0x0037, /* To Be Documented */
-	ACX_BEACON_FILTER_TABLE     = 0x0038,
-	ACX_ARP_IP_FILTER           = 0x0039,
-	ACX_ROAMING_STATISTICS_TBL  = 0x003B,
-	ACX_RATE_POLICY             = 0x003D,
-	ACX_CTS_PROTECTION          = 0x003E,
-	ACX_SLEEP_AUTH              = 0x003F,
-	ACX_PREAMBLE_TYPE	    = 0x0040,
-	ACX_ERROR_CNT               = 0x0041,
-	ACX_FW_GEN_FRAME_RATES      = 0x0042,
-	ACX_IBSS_FILTER		    = 0x0044,
-	ACX_SERVICE_PERIOD_TIMEOUT  = 0x0045,
-	ACX_TSF_INFO                = 0x0046,
-	ACX_CONFIG_PS_WMM           = 0x0049,
-	ACX_ENABLE_RX_DATA_FILTER   = 0x004A,
-	ACX_SET_RX_DATA_FILTER      = 0x004B,
-	ACX_GET_DATA_FILTER_STATISTICS = 0x004C,
-	ACX_POWER_LEVEL_TABLE       = 0x004D,
-	ACX_BET_ENABLE              = 0x0050,
-	DOT11_STATION_ID            = 0x1001,
-	DOT11_RX_MSDU_LIFE_TIME     = 0x1004,
-	DOT11_CUR_TX_PWR            = 0x100D,
-	DOT11_DEFAULT_KEY           = 0x1010,
-	DOT11_RX_DOT11_MODE         = 0x1012,
-	DOT11_RTS_THRESHOLD         = 0x1013,
-	DOT11_GROUP_ADDRESS_TBL     = 0x1014,
-
-	MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
-
-	MAX_IE = 0xFFFF
-};
-
-
-int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
-			   u8 mgt_rate, u8 mgt_mod);
-int wl1251_acx_station_id(struct wl1251 *wl);
-int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id);
-int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
-				  u8 listen_interval);
-int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth);
-int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len);
-int wl1251_acx_tx_power(struct wl1251 *wl, int power);
-int wl1251_acx_feature_cfg(struct wl1251 *wl);
-int wl1251_acx_mem_map(struct wl1251 *wl,
-		       struct acx_header *mem_map, size_t len);
-int wl1251_acx_data_path_params(struct wl1251 *wl,
-				struct acx_data_path_params_resp *data_path);
-int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time);
-int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter);
-int wl1251_acx_pd_threshold(struct wl1251 *wl);
-int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time);
-int wl1251_acx_group_address_tbl(struct wl1251 *wl);
-int wl1251_acx_service_period_timeout(struct wl1251 *wl);
-int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
-int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter);
-int wl1251_acx_beacon_filter_table(struct wl1251 *wl);
-int wl1251_acx_conn_monit_params(struct wl1251 *wl);
-int wl1251_acx_sg_enable(struct wl1251 *wl);
-int wl1251_acx_sg_cfg(struct wl1251 *wl);
-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_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble);
-int wl1251_acx_cts_protect(struct wl1251 *wl,
-			    enum acx_ctsprotect_type ctsprotect);
-int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats);
-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_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,
-		       enum wl1251_acx_channel_type type,
-		       u8 tsid, enum wl1251_acx_ps_scheme ps_scheme,
-		       enum wl1251_acx_ack_policy ack_policy);
-
-#endif /* __WL1251_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
deleted file mode 100644
index 65e0416..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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/gpio.h>
-#include <linux/slab.h>
-
-#include "wl1251_reg.h"
-#include "wl1251_boot.h"
-#include "wl1251_io.h"
-#include "wl1251_spi.h"
-#include "wl1251_event.h"
-#include "wl1251_acx.h"
-
-void wl1251_boot_target_enable_interrupts(struct wl1251 *wl)
-{
-	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
-	wl1251_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
-}
-
-int wl1251_boot_soft_reset(struct wl1251 *wl)
-{
-	unsigned long timeout;
-	u32 boot_data;
-
-	/* perform soft reset */
-	wl1251_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
-
-	/* SOFT_RESET is self clearing */
-	timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
-	while (1) {
-		boot_data = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
-		wl1251_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
-		if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
-			break;
-
-		if (time_after(jiffies, timeout)) {
-			/* 1.2 check pWhalBus->uSelfClearTime if the
-			 * timeout was reached */
-			wl1251_error("soft reset timeout");
-			return -1;
-		}
-
-		udelay(SOFT_RESET_STALL_TIME);
-	}
-
-	/* disable Rx/Tx */
-	wl1251_reg_write32(wl, ENABLE, 0x0);
-
-	/* disable auto calibration on start*/
-	wl1251_reg_write32(wl, SPARE_A2, 0xffff);
-
-	return 0;
-}
-
-int wl1251_boot_init_seq(struct wl1251 *wl)
-{
-	u32 scr_pad6, init_data, tmp, elp_cmd, ref_freq;
-
-	/*
-	 * col #1: INTEGER_DIVIDER
-	 * col #2: FRACTIONAL_DIVIDER
-	 * col #3: ATTN_BB
-	 * col #4: ALPHA_BB
-	 * col #5: STOP_TIME_BB
-	 * col #6: BB_PLL_LOOP_FILTER
-	 */
-	static const u32 LUT[REF_FREQ_NUM][LUT_PARAM_NUM] = {
-
-		{   83, 87381,  0xB, 5, 0xF00,  3}, /* REF_FREQ_19_2*/
-		{   61, 141154, 0xB, 5, 0x1450, 2}, /* REF_FREQ_26_0*/
-		{   41, 174763, 0xC, 6, 0x2D00, 1}, /* REF_FREQ_38_4*/
-		{   40, 0,      0xC, 6, 0x2EE0, 1}, /* REF_FREQ_40_0*/
-		{   47, 162280, 0xC, 6, 0x2760, 1}  /* REF_FREQ_33_6        */
-	};
-
-	/* read NVS params */
-	scr_pad6 = wl1251_reg_read32(wl, SCR_PAD6);
-	wl1251_debug(DEBUG_BOOT, "scr_pad6 0x%x", scr_pad6);
-
-	/* read ELP_CMD */
-	elp_cmd = wl1251_reg_read32(wl, ELP_CMD);
-	wl1251_debug(DEBUG_BOOT, "elp_cmd 0x%x", elp_cmd);
-
-	/* set the BB calibration time to be 300 usec (PLL_CAL_TIME) */
-	ref_freq = scr_pad6 & 0x000000FF;
-	wl1251_debug(DEBUG_BOOT, "ref_freq 0x%x", ref_freq);
-
-	wl1251_reg_write32(wl, PLL_CAL_TIME, 0x9);
-
-	/*
-	 * PG 1.2: set the clock buffer time to be 210 usec (CLK_BUF_TIME)
-	 */
-	wl1251_reg_write32(wl, CLK_BUF_TIME, 0x6);
-
-	/*
-	 * set the clock detect feature to work in the restart wu procedure
-	 * (ELP_CFG_MODE[14]) and Select the clock source type
-	 * (ELP_CFG_MODE[13:12])
-	 */
-	tmp = ((scr_pad6 & 0x0000FF00) << 4) | 0x00004000;
-	wl1251_reg_write32(wl, ELP_CFG_MODE, tmp);
-
-	/* PG 1.2: enable the BB PLL fix. Enable the PLL_LIMP_CLK_EN_CMD */
-	elp_cmd |= 0x00000040;
-	wl1251_reg_write32(wl, ELP_CMD, elp_cmd);
-
-	/* PG 1.2: Set the BB PLL stable time to be 1000usec
-	 * (PLL_STABLE_TIME) */
-	wl1251_reg_write32(wl, CFG_PLL_SYNC_CNT, 0x20);
-
-	/* PG 1.2: read clock request time */
-	init_data = wl1251_reg_read32(wl, CLK_REQ_TIME);
-
-	/*
-	 * PG 1.2: set the clock request time to be ref_clk_settling_time -
-	 * 1ms = 4ms
-	 */
-	if (init_data > 0x21)
-		tmp = init_data - 0x21;
-	else
-		tmp = 0;
-	wl1251_reg_write32(wl, CLK_REQ_TIME, tmp);
-
-	/* set BB PLL configurations in RF AFE */
-	wl1251_reg_write32(wl, 0x003058cc, 0x4B5);
-
-	/* set RF_AFE_REG_5 */
-	wl1251_reg_write32(wl, 0x003058d4, 0x50);
-
-	/* set RF_AFE_CTRL_REG_2 */
-	wl1251_reg_write32(wl, 0x00305948, 0x11c001);
-
-	/*
-	 * change RF PLL and BB PLL divider for VCO clock and adjust VCO
-	 * bais current(RF_AFE_REG_13)
-	 */
-	wl1251_reg_write32(wl, 0x003058f4, 0x1e);
-
-	/* set BB PLL configurations */
-	tmp = LUT[ref_freq][LUT_PARAM_INTEGER_DIVIDER] | 0x00017000;
-	wl1251_reg_write32(wl, 0x00305840, tmp);
-
-	/* set fractional divider according to Appendix C-BB PLL
-	 * Calculations
-	 */
-	tmp = LUT[ref_freq][LUT_PARAM_FRACTIONAL_DIVIDER];
-	wl1251_reg_write32(wl, 0x00305844, tmp);
-
-	/* set the initial data for the sigma delta */
-	wl1251_reg_write32(wl, 0x00305848, 0x3039);
-
-	/*
-	 * set the accumulator attenuation value, calibration loop1
-	 * (alpha), calibration loop2 (beta), calibration loop3 (gamma) and
-	 * the VCO gain
-	 */
-	tmp = (LUT[ref_freq][LUT_PARAM_ATTN_BB] << 16) |
-		(LUT[ref_freq][LUT_PARAM_ALPHA_BB] << 12) | 0x1;
-	wl1251_reg_write32(wl, 0x00305854, tmp);
-
-	/*
-	 * set the calibration stop time after holdoff time expires and set
-	 * settling time HOLD_OFF_TIME_BB
-	 */
-	tmp = LUT[ref_freq][LUT_PARAM_STOP_TIME_BB] | 0x000A0000;
-	wl1251_reg_write32(wl, 0x00305858, tmp);
-
-	/*
-	 * set BB PLL Loop filter capacitor3- BB_C3[2:0] and set BB PLL
-	 * constant leakage current to linearize PFD to 0uA -
-	 * BB_ILOOPF[7:3]
-	 */
-	tmp = LUT[ref_freq][LUT_PARAM_BB_PLL_LOOP_FILTER] | 0x00000030;
-	wl1251_reg_write32(wl, 0x003058f8, tmp);
-
-	/*
-	 * set regulator output voltage for n divider to
-	 * 1.35-BB_REFDIV[1:0], set charge pump current- BB_CPGAIN[4:2],
-	 * set BB PLL Loop filter capacitor2- BB_C2[7:5], set gain of BB
-	 * PLL auto-call to normal mode- BB_CALGAIN_3DB[8]
-	 */
-	wl1251_reg_write32(wl, 0x003058f0, 0x29);
-
-	/* enable restart wakeup sequence (ELP_CMD[0]) */
-	wl1251_reg_write32(wl, ELP_CMD, elp_cmd | 0x1);
-
-	/* restart sequence completed */
-	udelay(2000);
-
-	return 0;
-}
-
-static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag)
-{
-	u32 cpu_ctrl;
-
-	/* 10.5.0 run the firmware (I) */
-	cpu_ctrl = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
-
-	/* 10.5.1 run the firmware (II) */
-	cpu_ctrl &= ~flag;
-	wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
-}
-
-int wl1251_boot_run_firmware(struct wl1251 *wl)
-{
-	int loop, ret;
-	u32 chip_id, acx_intr;
-
-	wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
-
-	chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
-
-	wl1251_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
-
-	if (chip_id != wl->chip_id) {
-		wl1251_error("chip id doesn't match after firmware boot");
-		return -EIO;
-	}
-
-	/* wait for init to complete */
-	loop = 0;
-	while (loop++ < INIT_LOOP) {
-		udelay(INIT_LOOP_DELAY);
-		acx_intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
-
-		if (acx_intr == 0xffffffff) {
-			wl1251_error("error reading hardware complete "
-				     "init indication");
-			return -EIO;
-		}
-		/* check that ACX_INTR_INIT_COMPLETE is enabled */
-		else if (acx_intr & WL1251_ACX_INTR_INIT_COMPLETE) {
-			wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
-					   WL1251_ACX_INTR_INIT_COMPLETE);
-			break;
-		}
-	}
-
-	if (loop > INIT_LOOP) {
-		wl1251_error("timeout waiting for the hardware to "
-			     "complete initialization");
-		return -EIO;
-	}
-
-	/* get hardware config command mail box */
-	wl->cmd_box_addr = wl1251_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);
-
-	/* get hardware config event mail box */
-	wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
-
-	/* set the working partition to its "running" mode offset */
-	wl1251_set_partition(wl, WL1251_PART_WORK_MEM_START,
-			     WL1251_PART_WORK_MEM_SIZE,
-			     WL1251_PART_WORK_REG_START,
-			     WL1251_PART_WORK_REG_SIZE);
-
-	wl1251_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
-		     wl->cmd_box_addr, wl->event_box_addr);
-
-	wl1251_acx_fw_version(wl, wl->fw_ver, sizeof(wl->fw_ver));
-
-	/*
-	 * in case of full asynchronous mode the firmware event must be
-	 * ready to receive event from the command mailbox
-	 */
-
-	/* enable gpio interrupts */
-	wl1251_enable_interrupts(wl);
-
-	/* Enable target's interrupts */
-	wl->intr_mask = WL1251_ACX_INTR_RX0_DATA |
-		WL1251_ACX_INTR_RX1_DATA |
-		WL1251_ACX_INTR_TX_RESULT |
-		WL1251_ACX_INTR_EVENT_A |
-		WL1251_ACX_INTR_EVENT_B |
-		WL1251_ACX_INTR_INIT_COMPLETE;
-	wl1251_boot_target_enable_interrupts(wl);
-
-	wl->event_mask = SCAN_COMPLETE_EVENT_ID | BSS_LOSE_EVENT_ID |
-		SYNCHRONIZATION_TIMEOUT_EVENT_ID |
-		ROAMING_TRIGGER_LOW_RSSI_EVENT_ID |
-		ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID |
-		REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID |
-		BT_PTA_PREDICTION_EVENT_ID;
-
-	ret = wl1251_event_unmask(wl);
-	if (ret < 0) {
-		wl1251_error("EVENT mask setting failed");
-		return ret;
-	}
-
-	wl1251_event_mbox_config(wl);
-
-	/* firmware startup completed */
-	return 0;
-}
-
-static int wl1251_boot_upload_firmware(struct wl1251 *wl)
-{
-	int addr, chunk_num, partition_limit;
-	size_t fw_data_len, len;
-	u8 *p, *buf;
-
-	/* whal_FwCtrl_LoadFwImageSm() */
-
-	wl1251_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x",
-		     wl1251_reg_read32(wl, CHIP_ID_B));
-
-	/* 10.0 check firmware length and set partition */
-	fw_data_len =  (wl->fw[4] << 24) | (wl->fw[5] << 16) |
-		(wl->fw[6] << 8) | (wl->fw[7]);
-
-	wl1251_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len,
-		CHUNK_SIZE);
-
-	if ((fw_data_len % 4) != 0) {
-		wl1251_error("firmware length not multiple of four");
-		return -EIO;
-	}
-
-	buf = kmalloc(CHUNK_SIZE, GFP_KERNEL);
-	if (!buf) {
-		wl1251_error("allocation for firmware upload chunk failed");
-		return -ENOMEM;
-	}
-
-	wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START,
-			     WL1251_PART_DOWN_MEM_SIZE,
-			     WL1251_PART_DOWN_REG_START,
-			     WL1251_PART_DOWN_REG_SIZE);
-
-	/* 10.1 set partition limit and chunk num */
-	chunk_num = 0;
-	partition_limit = WL1251_PART_DOWN_MEM_SIZE;
-
-	while (chunk_num < fw_data_len / CHUNK_SIZE) {
-		/* 10.2 update partition, if needed */
-		addr = WL1251_PART_DOWN_MEM_START +
-			(chunk_num + 2) * CHUNK_SIZE;
-		if (addr > partition_limit) {
-			addr = WL1251_PART_DOWN_MEM_START +
-				chunk_num * CHUNK_SIZE;
-			partition_limit = chunk_num * CHUNK_SIZE +
-				WL1251_PART_DOWN_MEM_SIZE;
-			wl1251_set_partition(wl,
-					     addr,
-					     WL1251_PART_DOWN_MEM_SIZE,
-					     WL1251_PART_DOWN_REG_START,
-					     WL1251_PART_DOWN_REG_SIZE);
-		}
-
-		/* 10.3 upload the chunk */
-		addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
-		p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
-		wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
-			     p, addr);
-
-		/* need to copy the chunk for dma */
-		len = CHUNK_SIZE;
-		memcpy(buf, p, len);
-		wl1251_mem_write(wl, addr, buf, len);
-
-		chunk_num++;
-	}
-
-	/* 10.4 upload the last chunk */
-	addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
-	p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
-
-	/* need to copy the chunk for dma */
-	len = fw_data_len % CHUNK_SIZE;
-	memcpy(buf, p, len);
-
-	wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
-		     len, p, addr);
-	wl1251_mem_write(wl, addr, buf, len);
-
-	kfree(buf);
-
-	return 0;
-}
-
-static int wl1251_boot_upload_nvs(struct wl1251 *wl)
-{
-	size_t nvs_len, nvs_bytes_written, burst_len;
-	int nvs_start, i;
-	u32 dest_addr, val;
-	u8 *nvs_ptr, *nvs;
-
-	nvs = wl->nvs;
-	if (nvs == NULL)
-		return -ENODEV;
-
-	nvs_ptr = nvs;
-
-	nvs_len = wl->nvs_len;
-	nvs_start = wl->fw_len;
-
-	/*
-	 * Layout before the actual NVS tables:
-	 * 1 byte : burst length.
-	 * 2 bytes: destination address.
-	 * n bytes: data to burst copy.
-	 *
-	 * This is ended by a 0 length, then the NVS tables.
-	 */
-
-	while (nvs_ptr[0]) {
-		burst_len = nvs_ptr[0];
-		dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
-
-		/* We move our pointer to the data */
-		nvs_ptr += 3;
-
-		for (i = 0; i < burst_len; i++) {
-			val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
-			       | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
-
-			wl1251_debug(DEBUG_BOOT,
-				     "nvs burst write 0x%x: 0x%x",
-				     dest_addr, val);
-			wl1251_mem_write32(wl, dest_addr, val);
-
-			nvs_ptr += 4;
-			dest_addr += 4;
-		}
-	}
-
-	/*
-	 * We've reached the first zero length, the first NVS table
-	 * is 7 bytes further.
-	 */
-	nvs_ptr += 7;
-	nvs_len -= nvs_ptr - nvs;
-	nvs_len = ALIGN(nvs_len, 4);
-
-	/* Now we must set the partition correctly */
-	wl1251_set_partition(wl, nvs_start,
-			     WL1251_PART_DOWN_MEM_SIZE,
-			     WL1251_PART_DOWN_REG_START,
-			     WL1251_PART_DOWN_REG_SIZE);
-
-	/* And finally we upload the NVS tables */
-	nvs_bytes_written = 0;
-	while (nvs_bytes_written < nvs_len) {
-		val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
-		       | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
-
-		val = cpu_to_le32(val);
-
-		wl1251_debug(DEBUG_BOOT,
-			     "nvs write table 0x%x: 0x%x",
-			     nvs_start, val);
-		wl1251_mem_write32(wl, nvs_start, val);
-
-		nvs_ptr += 4;
-		nvs_bytes_written += 4;
-		nvs_start += 4;
-	}
-
-	return 0;
-}
-
-int wl1251_boot(struct wl1251 *wl)
-{
-	int ret = 0, minor_minor_e2_ver;
-	u32 tmp, boot_data;
-
-	/* halt embedded ARM CPU while loading firmware */
-	wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT);
-
-	ret = wl1251_boot_soft_reset(wl);
-	if (ret < 0)
-		goto out;
-
-	/* 2. start processing NVS file */
-	if (wl->use_eeprom) {
-		wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR);
-		/* Wait for EEPROM NVS burst read to complete */
-		msleep(40);
-		wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM);
-	} else {
-		ret = wl1251_boot_upload_nvs(wl);
-		if (ret < 0)
-			goto out;
-
-		/* write firmware's last address (ie. it's length) to
-		 * ACX_EEPROMLESS_IND_REG */
-		wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len);
-	}
-
-	/* 6. read the EEPROM parameters */
-	tmp = wl1251_reg_read32(wl, SCR_PAD2);
-
-	/* 7. read bootdata */
-	wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8;
-	wl->boot_attr.major = (tmp & 0x00FF0000) >> 16;
-	tmp = wl1251_reg_read32(wl, SCR_PAD3);
-
-	/* 8. check bootdata and call restart sequence */
-	wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16;
-	minor_minor_e2_ver = (tmp & 0xFF000000) >> 24;
-
-	wl1251_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x "
-		     "minorE2Ver 0x%x minor_minor_e2_ver 0x%x",
-		     wl->boot_attr.radio_type, wl->boot_attr.major,
-		     wl->boot_attr.minor, minor_minor_e2_ver);
-
-	ret = wl1251_boot_init_seq(wl);
-	if (ret < 0)
-		goto out;
-
-	/* 9. NVS processing done */
-	boot_data = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
-
-	wl1251_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data);
-
-	/* 10. check that ECPU_CONTROL_HALT bits are set in
-	 * pWhalBus->uBootData and start uploading firmware
-	 */
-	if ((boot_data & ECPU_CONTROL_HALT) == 0) {
-		wl1251_error("boot failed, ECPU_CONTROL_HALT not set");
-		ret = -EIO;
-		goto out;
-	}
-
-	ret = wl1251_boot_upload_firmware(wl);
-	if (ret < 0)
-		goto out;
-
-	/* 10.5 start firmware */
-	ret = wl1251_boot_run_firmware(wl);
-	if (ret < 0)
-		goto out;
-
-out:
-	return ret;
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.h b/drivers/net/wireless/wl12xx/wl1251_boot.h
deleted file mode 100644
index 9006369..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_boot.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef __BOOT_H__
-#define __BOOT_H__
-
-#include "wl1251.h"
-
-int wl1251_boot_soft_reset(struct wl1251 *wl);
-int wl1251_boot_init_seq(struct wl1251 *wl);
-int wl1251_boot_run_firmware(struct wl1251 *wl);
-void wl1251_boot_target_enable_interrupts(struct wl1251 *wl);
-int wl1251_boot(struct wl1251 *wl);
-
-/* number of times we try to read the INIT interrupt */
-#define INIT_LOOP 20000
-
-/* delay between retries */
-#define INIT_LOOP_DELAY 50
-
-#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c
deleted file mode 100644
index ce3722f..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.c
+++ /dev/null
@@ -1,496 +0,0 @@
-#include "wl1251_cmd.h"
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/crc7.h>
-
-#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_io.h"
-#include "wl1251_ps.h"
-#include "wl1251_acx.h"
-
-/**
- * send command to firmware
- *
- * @wl: wl struct
- * @id: command id
- * @buf: buffer containing the command, must work with dma
- * @len: length of the buffer
- */
-int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len)
-{
-	struct wl1251_cmd_header *cmd;
-	unsigned long timeout;
-	u32 intr;
-	int ret = 0;
-
-	cmd = buf;
-	cmd->id = id;
-	cmd->status = 0;
-
-	WARN_ON(len % 4 != 0);
-
-	wl1251_mem_write(wl, wl->cmd_box_addr, buf, len);
-
-	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
-
-	timeout = jiffies + msecs_to_jiffies(WL1251_COMMAND_TIMEOUT);
-
-	intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
-	while (!(intr & WL1251_ACX_INTR_CMD_COMPLETE)) {
-		if (time_after(jiffies, timeout)) {
-			wl1251_error("command complete timeout");
-			ret = -ETIMEDOUT;
-			goto out;
-		}
-
-		msleep(1);
-
-		intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
-	}
-
-	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
-			   WL1251_ACX_INTR_CMD_COMPLETE);
-
-out:
-	return ret;
-}
-
-/**
- * send test command to firmware
- *
- * @wl: wl struct
- * @buf: buffer containing the command, with all headers, must work with dma
- * @len: length of the buffer
- * @answer: is answer needed
- */
-int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer)
-{
-	int ret;
-
-	wl1251_debug(DEBUG_CMD, "cmd test");
-
-	ret = wl1251_cmd_send(wl, CMD_TEST, buf, buf_len);
-
-	if (ret < 0) {
-		wl1251_warning("TEST command failed");
-		return ret;
-	}
-
-	if (answer) {
-		struct wl1251_command *cmd_answer;
-
-		/*
-		 * The test command got in, we can read the answer.
-		 * The answer would be a wl1251_command, where the
-		 * parameter array contains the actual answer.
-		 */
-		wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len);
-
-		cmd_answer = buf;
-
-		if (cmd_answer->header.status != CMD_STATUS_SUCCESS)
-			wl1251_error("TEST command answer error: %d",
-				     cmd_answer->header.status);
-	}
-
-	return 0;
-}
-
-/**
- * read acx from firmware
- *
- * @wl: wl struct
- * @id: acx id
- * @buf: buffer for the response, including all headers, must work with dma
- * @len: lenght of buf
- */
-int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len)
-{
-	struct acx_header *acx = buf;
-	int ret;
-
-	wl1251_debug(DEBUG_CMD, "cmd interrogate");
-
-	acx->id = id;
-
-	/* payload length, does not include any headers */
-	acx->len = len - sizeof(*acx);
-
-	ret = wl1251_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1251_error("INTERROGATE command failed");
-		goto out;
-	}
-
-	/* the interrogate command got in, we can read the answer */
-	wl1251_mem_read(wl, wl->cmd_box_addr, buf, len);
-
-	acx = buf;
-	if (acx->cmd.status != CMD_STATUS_SUCCESS)
-		wl1251_error("INTERROGATE command error: %d",
-			     acx->cmd.status);
-
-out:
-	return ret;
-}
-
-/**
- * write acx value to firmware
- *
- * @wl: wl struct
- * @id: acx id
- * @buf: buffer containing acx, including all headers, must work with dma
- * @len: length of buf
- */
-int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len)
-{
-	struct acx_header *acx = buf;
-	int ret;
-
-	wl1251_debug(DEBUG_CMD, "cmd configure");
-
-	acx->id = id;
-
-	/* payload length, does not include any headers */
-	acx->len = len - sizeof(*acx);
-
-	ret = wl1251_cmd_send(wl, CMD_CONFIGURE, acx, len);
-	if (ret < 0) {
-		wl1251_warning("CONFIGURE command NOK");
-		return ret;
-	}
-
-	return 0;
-}
-
-int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
-		   void *bitmap, u16 bitmap_len, u8 bitmap_control)
-{
-	struct wl1251_cmd_vbm_update *vbm;
-	int ret;
-
-	wl1251_debug(DEBUG_CMD, "cmd vbm");
-
-	vbm = kzalloc(sizeof(*vbm), GFP_KERNEL);
-	if (!vbm) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* Count and period will be filled by the target */
-	vbm->tim.bitmap_ctrl = bitmap_control;
-	if (bitmap_len > PARTIAL_VBM_MAX) {
-		wl1251_warning("cmd vbm len is %d B, truncating to %d",
-			       bitmap_len, PARTIAL_VBM_MAX);
-		bitmap_len = PARTIAL_VBM_MAX;
-	}
-	memcpy(vbm->tim.pvb_field, bitmap, bitmap_len);
-	vbm->tim.identity = identity;
-	vbm->tim.length = bitmap_len + 3;
-
-	vbm->len = cpu_to_le16(bitmap_len + 5);
-
-	ret = wl1251_cmd_send(wl, CMD_VBM, vbm, sizeof(*vbm));
-	if (ret < 0) {
-		wl1251_error("VBM command failed");
-		goto out;
-	}
-
-out:
-	kfree(vbm);
-	return 0;
-}
-
-int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
-{
-	struct cmd_enabledisable_path *cmd;
-	int ret;
-	u16 cmd_rx, cmd_tx;
-
-	wl1251_debug(DEBUG_CMD, "cmd data path");
-
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-	if (!cmd) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	cmd->channel = channel;
-
-	if (enable) {
-		cmd_rx = CMD_ENABLE_RX;
-		cmd_tx = CMD_ENABLE_TX;
-	} else {
-		cmd_rx = CMD_DISABLE_RX;
-		cmd_tx = CMD_DISABLE_TX;
-	}
-
-	ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
-	if (ret < 0) {
-		wl1251_error("rx %s cmd for channel %d failed",
-			     enable ? "start" : "stop", channel);
-		goto out;
-	}
-
-	wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d",
-		     enable ? "start" : "stop", channel);
-
-	ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
-	if (ret < 0) {
-		wl1251_error("tx %s cmd for channel %d failed",
-			     enable ? "start" : "stop", channel);
-		return ret;
-	}
-
-	wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
-		     enable ? "start" : "stop", channel);
-
-out:
-	kfree(cmd);
-	return ret;
-}
-
-int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
-		    u16 beacon_interval, u8 dtim_interval)
-{
-	struct cmd_join *join;
-	int ret, i;
-	u8 *bssid;
-
-	join = kzalloc(sizeof(*join), GFP_KERNEL);
-	if (!join) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	wl1251_debug(DEBUG_CMD, "cmd join%s ch %d %d/%d",
-		     bss_type == BSS_TYPE_IBSS ? " ibss" : "",
-		     channel, beacon_interval, dtim_interval);
-
-	/* Reverse order BSSID */
-	bssid = (u8 *) &join->bssid_lsb;
-	for (i = 0; i < ETH_ALEN; i++)
-		bssid[i] = wl->bssid[ETH_ALEN - i - 1];
-
-	join->rx_config_options = wl->rx_config;
-	join->rx_filter_options = wl->rx_filter;
-
-	/*
-	 * FIXME: disable temporarily all filters because after commit
-	 * 9cef8737 "mac80211: fix managed mode BSSID handling" broke
-	 * association. The filter logic needs to be implemented properly
-	 * and once that is done, this hack can be removed.
-	 */
-	join->rx_config_options = 0;
-	join->rx_filter_options = WL1251_DEFAULT_RX_FILTER;
-
-	join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
-		RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
-
-	join->beacon_interval = beacon_interval;
-	join->dtim_interval = dtim_interval;
-	join->bss_type = bss_type;
-	join->channel = channel;
-	join->ctrl = JOIN_CMD_CTRL_TX_FLUSH;
-
-	ret = wl1251_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
-	if (ret < 0) {
-		wl1251_error("failed to initiate cmd join");
-		goto out;
-	}
-
-out:
-	kfree(join);
-	return ret;
-}
-
-int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode)
-{
-	struct wl1251_cmd_ps_params *ps_params = NULL;
-	int ret = 0;
-
-	wl1251_debug(DEBUG_CMD, "cmd set ps mode");
-
-	ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
-	if (!ps_params) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	ps_params->ps_mode = ps_mode;
-	ps_params->send_null_data = 1;
-	ps_params->retries = 5;
-	ps_params->hang_over_period = 128;
-	ps_params->null_data_rate = 1; /* 1 Mbps */
-
-	ret = wl1251_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
-			      sizeof(*ps_params));
-	if (ret < 0) {
-		wl1251_error("cmd set_ps_mode failed");
-		goto out;
-	}
-
-out:
-	kfree(ps_params);
-	return ret;
-}
-
-int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
-			   size_t len)
-{
-	struct cmd_read_write_memory *cmd;
-	int ret = 0;
-
-	wl1251_debug(DEBUG_CMD, "cmd read memory");
-
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-	if (!cmd) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	WARN_ON(len > MAX_READ_SIZE);
-	len = min_t(size_t, len, MAX_READ_SIZE);
-
-	cmd->addr = addr;
-	cmd->size = len;
-
-	ret = wl1251_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd));
-	if (ret < 0) {
-		wl1251_error("read memory command failed: %d", ret);
-		goto out;
-	}
-
-	/* the read command got in, we can now read the answer */
-	wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
-
-	if (cmd->header.status != CMD_STATUS_SUCCESS)
-		wl1251_error("error in read command result: %d",
-			     cmd->header.status);
-
-	memcpy(answer, cmd->value, len);
-
-out:
-	kfree(cmd);
-	return ret;
-}
-
-int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id,
-			    void *buf, size_t buf_len)
-{
-	struct wl1251_cmd_packet_template *cmd;
-	size_t cmd_len;
-	int ret = 0;
-
-	wl1251_debug(DEBUG_CMD, "cmd template %d", cmd_id);
-
-	WARN_ON(buf_len > WL1251_MAX_TEMPLATE_SIZE);
-	buf_len = min_t(size_t, buf_len, WL1251_MAX_TEMPLATE_SIZE);
-	cmd_len = ALIGN(sizeof(*cmd) + buf_len, 4);
-
-	cmd = kzalloc(cmd_len, GFP_KERNEL);
-	if (!cmd) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	cmd->size = cpu_to_le16(buf_len);
-
-	if (buf)
-		memcpy(cmd->data, buf, buf_len);
-
-	ret = wl1251_cmd_send(wl, cmd_id, cmd, cmd_len);
-	if (ret < 0) {
-		wl1251_warning("cmd set_template failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(cmd);
-	return ret;
-}
-
-int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
-		    struct ieee80211_channel *channels[],
-		    unsigned int n_channels, unsigned int n_probes)
-{
-	struct wl1251_cmd_scan *cmd;
-	int i, ret = 0;
-
-	wl1251_debug(DEBUG_CMD, "cmd scan");
-
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-	if (!cmd)
-		return -ENOMEM;
-
-	cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
-	cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN |
-						    CFG_RX_MGMT_EN |
-						    CFG_RX_BCN_EN);
-	cmd->params.scan_options = 0;
-	cmd->params.num_channels = n_channels;
-	cmd->params.num_probe_requests = n_probes;
-	cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
-	cmd->params.tid_trigger = 0;
-
-	for (i = 0; i < n_channels; i++) {
-		cmd->channels[i].min_duration =
-			cpu_to_le32(WL1251_SCAN_MIN_DURATION);
-		cmd->channels[i].max_duration =
-			cpu_to_le32(WL1251_SCAN_MAX_DURATION);
-		memset(&cmd->channels[i].bssid_lsb, 0xff, 4);
-		memset(&cmd->channels[i].bssid_msb, 0xff, 2);
-		cmd->channels[i].early_termination = 0;
-		cmd->channels[i].tx_power_att = 0;
-		cmd->channels[i].channel = channels[i]->hw_value;
-	}
-
-	cmd->params.ssid_len = ssid_len;
-	if (ssid)
-		memcpy(cmd->params.ssid, ssid, ssid_len);
-
-	ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd));
-	if (ret < 0) {
-		wl1251_error("cmd scan failed: %d", ret);
-		goto out;
-	}
-
-	wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
-
-	if (cmd->header.status != CMD_STATUS_SUCCESS) {
-		wl1251_error("cmd scan status wasn't success: %d",
-			     cmd->header.status);
-		ret = -EIO;
-		goto out;
-	}
-
-out:
-	kfree(cmd);
-	return ret;
-}
-
-int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout)
-{
-	struct wl1251_cmd_trigger_scan_to *cmd;
-	int ret;
-
-	wl1251_debug(DEBUG_CMD, "cmd trigger scan to");
-
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-	if (!cmd)
-		return -ENOMEM;
-
-	cmd->timeout = timeout;
-
-	ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, cmd, sizeof(*cmd));
-	if (ret < 0) {
-		wl1251_error("cmd trigger scan to failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(cmd);
-	return ret;
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h
deleted file mode 100644
index a9e4991..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.h
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef __WL1251_CMD_H__
-#define __WL1251_CMD_H__
-
-#include "wl1251.h"
-
-#include <net/cfg80211.h>
-
-struct acx_header;
-
-int wl1251_cmd_send(struct wl1251 *wl, u16 type, void *buf, size_t buf_len);
-int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer);
-int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len);
-int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len);
-int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
-		   void *bitmap, u16 bitmap_len, u8 bitmap_control);
-int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable);
-int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
-		    u16 beacon_interval, u8 dtim_interval);
-int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode);
-int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
-			   size_t len);
-int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id,
-			    void *buf, size_t buf_len);
-int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
-		    struct ieee80211_channel *channels[],
-		    unsigned int n_channels, unsigned int n_probes);
-int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout);
-
-/* unit ms */
-#define WL1251_COMMAND_TIMEOUT 2000
-
-enum wl1251_commands {
-	CMD_RESET           = 0,
-	CMD_INTERROGATE     = 1,    /*use this to read information elements*/
-	CMD_CONFIGURE       = 2,    /*use this to write information elements*/
-	CMD_ENABLE_RX       = 3,
-	CMD_ENABLE_TX       = 4,
-	CMD_DISABLE_RX      = 5,
-	CMD_DISABLE_TX      = 6,
-	CMD_SCAN            = 8,
-	CMD_STOP_SCAN       = 9,
-	CMD_VBM             = 10,
-	CMD_START_JOIN      = 11,
-	CMD_SET_KEYS        = 12,
-	CMD_READ_MEMORY     = 13,
-	CMD_WRITE_MEMORY    = 14,
-	CMD_BEACON          = 19,
-	CMD_PROBE_RESP      = 20,
-	CMD_NULL_DATA       = 21,
-	CMD_PROBE_REQ       = 22,
-	CMD_TEST            = 23,
-	CMD_RADIO_CALIBRATE     = 25,   /* OBSOLETE */
-	CMD_ENABLE_RX_PATH      = 27,   /* OBSOLETE */
-	CMD_NOISE_HIST      = 28,
-	CMD_RX_RESET        = 29,
-	CMD_PS_POLL         = 30,
-	CMD_QOS_NULL_DATA   = 31,
-	CMD_LNA_CONTROL     = 32,
-	CMD_SET_BCN_MODE    = 33,
-	CMD_MEASUREMENT      = 34,
-	CMD_STOP_MEASUREMENT = 35,
-	CMD_DISCONNECT       = 36,
-	CMD_SET_PS_MODE      = 37,
-	CMD_CHANNEL_SWITCH   = 38,
-	CMD_STOP_CHANNEL_SWICTH = 39,
-	CMD_AP_DISCOVERY     = 40,
-	CMD_STOP_AP_DISCOVERY = 41,
-	CMD_SPS_SCAN = 42,
-	CMD_STOP_SPS_SCAN = 43,
-	CMD_HEALTH_CHECK     = 45,
-	CMD_DEBUG            = 46,
-	CMD_TRIGGER_SCAN_TO  = 47,
-
-	NUM_COMMANDS,
-	MAX_COMMAND_ID = 0xFFFF,
-};
-
-#define MAX_CMD_PARAMS 572
-
-struct wl1251_cmd_header {
-	u16 id;
-	u16 status;
-	/* payload */
-	u8 data[0];
-} __packed;
-
-struct  wl1251_command {
-	struct wl1251_cmd_header header;
-	u8  parameters[MAX_CMD_PARAMS];
-};
-
-enum {
-	CMD_MAILBOX_IDLE              		=  0,
-	CMD_STATUS_SUCCESS            		=  1,
-	CMD_STATUS_UNKNOWN_CMD        		=  2,
-	CMD_STATUS_UNKNOWN_IE         		=  3,
-	CMD_STATUS_REJECT_MEAS_SG_ACTIVE 	= 11,
-	CMD_STATUS_RX_BUSY            		= 13,
-	CMD_STATUS_INVALID_PARAM      		= 14,
-	CMD_STATUS_TEMPLATE_TOO_LARGE 		= 15,
-	CMD_STATUS_OUT_OF_MEMORY      		= 16,
-	CMD_STATUS_STA_TABLE_FULL     		= 17,
-	CMD_STATUS_RADIO_ERROR        		= 18,
-	CMD_STATUS_WRONG_NESTING      		= 19,
-	CMD_STATUS_TIMEOUT            		= 21, /* Driver internal use.*/
-	CMD_STATUS_FW_RESET           		= 22, /* Driver internal use.*/
-	MAX_COMMAND_STATUS            		= 0xff
-};
-
-
-/*
- * CMD_READ_MEMORY
- *
- * The host issues this command to read the WiLink device memory/registers.
- *
- * Note: The Base Band address has special handling (16 bits registers and
- * addresses). For more information, see the hardware specification.
- */
-/*
- * CMD_WRITE_MEMORY
- *
- * The host issues this command to write the WiLink device memory/registers.
- *
- * The Base Band address has special handling (16 bits registers and
- * addresses). For more information, see the hardware specification.
- */
-#define MAX_READ_SIZE 256
-
-struct cmd_read_write_memory {
-	struct wl1251_cmd_header header;
-
-	/* The address of the memory to read from or write to.*/
-	u32 addr;
-
-	/* The amount of data in bytes to read from or write to the WiLink
-	 * device.*/
-	u32 size;
-
-	/* The actual value read from or written to the Wilink. The source
-	   of this field is the Host in WRITE command or the Wilink in READ
-	   command. */
-	u8 value[MAX_READ_SIZE];
-};
-
-#define CMDMBOX_HEADER_LEN 4
-#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
-
-#define WL1251_SCAN_MIN_DURATION 30000
-#define WL1251_SCAN_MAX_DURATION 60000
-
-#define WL1251_SCAN_NUM_PROBES 3
-
-struct wl1251_scan_parameters {
-	__le32 rx_config_options;
-	__le32 rx_filter_options;
-
-	/*
-	 * Scan options:
-	 * bit 0: When this bit is set, passive scan.
-	 * bit 1: Band, when this bit is set we scan
-	 * in the 5Ghz band.
-	 * bit 2: voice mode, 0 for normal scan.
-	 * bit 3: scan priority, 1 for high priority.
-	 */
-	__le16 scan_options;
-
-	/* Number of channels to scan */
-	u8 num_channels;
-
-	/* Number opf probe requests to send, per channel */
-	u8 num_probe_requests;
-
-	/* Rate and modulation for probe requests */
-	__le16 tx_rate;
-
-	u8 tid_trigger;
-	u8 ssid_len;
-	u8 ssid[32];
-
-} __packed;
-
-struct wl1251_scan_ch_parameters {
-	__le32 min_duration; /* in TU */
-	__le32 max_duration; /* in TU */
-	u32 bssid_lsb;
-	u16 bssid_msb;
-
-	/*
-	 * bits 0-3: Early termination count.
-	 * bits 4-5: Early termination condition.
-	 */
-	u8 early_termination;
-
-	u8 tx_power_att;
-	u8 channel;
-	u8 pad[3];
-} __packed;
-
-/* SCAN parameters */
-#define SCAN_MAX_NUM_OF_CHANNELS 16
-
-struct wl1251_cmd_scan {
-	struct wl1251_cmd_header header;
-
-	struct wl1251_scan_parameters params;
-	struct wl1251_scan_ch_parameters channels[SCAN_MAX_NUM_OF_CHANNELS];
-} __packed;
-
-enum {
-	BSS_TYPE_IBSS = 0,
-	BSS_TYPE_STA_BSS = 2,
-	BSS_TYPE_AP_BSS = 3,
-	MAX_BSS_TYPE = 0xFF
-};
-
-#define JOIN_CMD_CTRL_TX_FLUSH             0x80 /* Firmware flushes all Tx */
-#define JOIN_CMD_CTRL_EARLY_WAKEUP_ENABLE  0x01 /* Early wakeup time */
-
-
-struct cmd_join {
-	struct wl1251_cmd_header header;
-
-	u32 bssid_lsb;
-	u16 bssid_msb;
-	u16 beacon_interval; /* in TBTTs */
-	u32 rx_config_options;
-	u32 rx_filter_options;
-
-	/*
-	 * The target uses this field to determine the rate at
-	 * which to transmit control frame responses (such as
-	 * ACK or CTS frames).
-	 */
-	u16 basic_rate_set;
-	u8 dtim_interval;
-	u8 tx_ctrl_frame_rate; /* OBSOLETE */
-	u8 tx_ctrl_frame_mod;  /* OBSOLETE */
-	/*
-	 * bits 0-2: This bitwise field specifies the type
-	 * of BSS to start or join (BSS_TYPE_*).
-	 * bit 4: Band - The radio band in which to join
-	 * or start.
-	 *  0 - 2.4GHz band
-	 *  1 - 5GHz band
-	 * bits 3, 5-7: Reserved
-	 */
-	u8 bss_type;
-	u8 channel;
-	u8 ssid_len;
-	u8 ssid[IW_ESSID_MAX_SIZE];
-	u8 ctrl; /* JOIN_CMD_CTRL_* */
-	u8 tx_mgt_frame_rate; /* OBSOLETE */
-	u8 tx_mgt_frame_mod;  /* OBSOLETE */
-	u8 reserved;
-} __packed;
-
-struct cmd_enabledisable_path {
-	struct wl1251_cmd_header header;
-
-	u8 channel;
-	u8 padding[3];
-} __packed;
-
-#define WL1251_MAX_TEMPLATE_SIZE 300
-
-struct wl1251_cmd_packet_template {
-	struct wl1251_cmd_header header;
-
-	__le16 size;
-	u8 data[0];
-} __packed;
-
-#define TIM_ELE_ID    5
-#define PARTIAL_VBM_MAX    251
-
-struct wl1251_tim {
-	u8 identity;
-	u8 length;
-	u8 dtim_count;
-	u8 dtim_period;
-	u8 bitmap_ctrl;
-	u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */
-} __packed;
-
-/* Virtual Bit Map update */
-struct wl1251_cmd_vbm_update {
-	struct wl1251_cmd_header header;
-	__le16 len;
-	u8  padding[2];
-	struct wl1251_tim tim;
-} __packed;
-
-enum wl1251_cmd_ps_mode {
-	STATION_ACTIVE_MODE,
-	STATION_POWER_SAVE_MODE
-};
-
-struct wl1251_cmd_ps_params {
-	struct wl1251_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;
-	u16 null_data_rate;
-	u8 pad[2];
-} __packed;
-
-struct wl1251_cmd_trigger_scan_to {
-	struct wl1251_cmd_header header;
-
-	u32 timeout;
-};
-
-/* HW encryption keys */
-#define NUM_ACCESS_CATEGORIES_COPY 4
-#define MAX_KEY_SIZE 32
-
-/* When set, disable HW encryption */
-#define DF_ENCRYPTION_DISABLE      0x01
-/* When set, disable HW decryption */
-#define DF_SNIFF_MODE_ENABLE       0x80
-
-enum wl1251_cmd_key_action {
-	KEY_ADD_OR_REPLACE = 1,
-	KEY_REMOVE         = 2,
-	KEY_SET_ID         = 3,
-	MAX_KEY_ACTION     = 0xffff,
-};
-
-enum wl1251_cmd_key_type {
-	KEY_WEP_DEFAULT       = 0,
-	KEY_WEP_ADDR          = 1,
-	KEY_AES_GROUP         = 4,
-	KEY_AES_PAIRWISE      = 5,
-	KEY_WEP_GROUP         = 6,
-	KEY_TKIP_MIC_GROUP    = 10,
-	KEY_TKIP_MIC_PAIRWISE = 11,
-};
-
-/*
- *
- * key_type_e   key size    key format
- * ----------   ---------   ----------
- * 0x00         5, 13, 29   Key data
- * 0x01         5, 13, 29   Key data
- * 0x04         16          16 bytes of key data
- * 0x05         16          16 bytes of key data
- * 0x0a         32          16 bytes of TKIP key data
- *                          8 bytes of RX MIC key data
- *                          8 bytes of TX MIC key data
- * 0x0b         32          16 bytes of TKIP key data
- *                          8 bytes of RX MIC key data
- *                          8 bytes of TX MIC key data
- *
- */
-
-struct wl1251_cmd_set_keys {
-	struct wl1251_cmd_header header;
-
-	/* Ignored for default WEP key */
-	u8 addr[ETH_ALEN];
-
-	/* key_action_e */
-	u16 key_action;
-
-	u16 reserved_1;
-
-	/* key size in bytes */
-	u8 key_size;
-
-	/* key_type_e */
-	u8 key_type;
-	u8 ssid_profile;
-
-	/*
-	 * TKIP, AES: frame's key id field.
-	 * For WEP default key: key id;
-	 */
-	u8 id;
-	u8 reserved_2[6];
-	u8 key[MAX_KEY_SIZE];
-	u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
-	u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
-} __packed;
-
-
-#endif /* __WL1251_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/drivers/net/wireless/wl12xx/wl1251_debugfs.c
deleted file mode 100644
index 5e4465a..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_debugfs.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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 "wl1251_debugfs.h"
-
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-
-#include "wl1251.h"
-#include "wl1251_acx.h"
-#include "wl1251_ps.h"
-
-/* ms */
-#define WL1251_DEBUGFS_STATS_LIFETIME 1000
-
-/* debugfs macros idea from mac80211 */
-
-#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)		\
-static ssize_t name## _read(struct file *file, char __user *userbuf,	\
-			    size_t count, loff_t *ppos)			\
-{									\
-	struct wl1251 *wl = file->private_data;				\
-	char buf[buflen];						\
-	int res;							\
-									\
-	res = scnprintf(buf, buflen, fmt "\n", ##value);		\
-	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
-}									\
-									\
-static const struct file_operations name## _ops = {			\
-	.read = name## _read,						\
-	.open = wl1251_open_file_generic,				\
-};
-
-#define DEBUGFS_ADD(name, parent)					\
-	wl->debugfs.name = debugfs_create_file(#name, 0400, parent,	\
-					       wl, &name## _ops);	\
-	if (IS_ERR(wl->debugfs.name)) {					\
-		ret = PTR_ERR(wl->debugfs.name);			\
-		wl->debugfs.name = NULL;				\
-		goto out;						\
-	}
-
-#define DEBUGFS_DEL(name)						\
-	do {								\
-		debugfs_remove(wl->debugfs.name);			\
-		wl->debugfs.name = NULL;				\
-	} while (0)
-
-#define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt)			\
-static ssize_t sub## _ ##name## _read(struct file *file,		\
-				      char __user *userbuf,		\
-				      size_t count, loff_t *ppos)	\
-{									\
-	struct wl1251 *wl = file->private_data;				\
-	char buf[buflen];						\
-	int res;							\
-									\
-	wl1251_debugfs_update_stats(wl);				\
-									\
-	res = scnprintf(buf, buflen, fmt "\n",				\
-			wl->stats.fw_stats->sub.name);			\
-	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
-}									\
-									\
-static const struct file_operations sub## _ ##name## _ops = {		\
-	.read = sub## _ ##name## _read,					\
-	.open = wl1251_open_file_generic,				\
-};
-
-#define DEBUGFS_FWSTATS_ADD(sub, name)				\
-	DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics)
-
-#define DEBUGFS_FWSTATS_DEL(sub, name)				\
-	DEBUGFS_DEL(sub## _ ##name)
-
-static void wl1251_debugfs_update_stats(struct wl1251 *wl)
-{
-	int ret;
-
-	mutex_lock(&wl->mutex);
-
-	ret = wl1251_ps_elp_wakeup(wl);
-	if (ret < 0)
-		goto out;
-
-	if (wl->state == WL1251_STATE_ON &&
-	    time_after(jiffies, wl->stats.fw_stats_update +
-		       msecs_to_jiffies(WL1251_DEBUGFS_STATS_LIFETIME))) {
-		wl1251_acx_statistics(wl, wl->stats.fw_stats);
-		wl->stats.fw_stats_update = jiffies;
-	}
-
-	wl1251_ps_elp_sleep(wl);
-
-out:
-	mutex_unlock(&wl->mutex);
-}
-
-static int wl1251_open_file_generic(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u");
-
-DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u");
-DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u");
-DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u");
-DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u");
-DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u");
-DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u");
-DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u");
-DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u");
-
-DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u");
-DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u");
-DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u");
-DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u");
-
-DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u");
-DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u");
-
-DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u");
-DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u");
-/* skipping wep.reserved */
-DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u");
-DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u");
-DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u");
-DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u");
-
-DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u");
-DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u");
-DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u");
-DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u");
-DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u");
-DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u");
-DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u");
-DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u");
-DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u");
-DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u");
-DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u");
-DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u");
-/* skipping cont_miss_bcns_spread for now */
-DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u");
-
-DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u");
-DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u");
-
-DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u");
-DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u");
-DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u");
-DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u");
-DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u");
-DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u");
-
-DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u");
-DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u");
-DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u");
-DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u");
-DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u");
-DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u");
-DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u");
-DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u");
-
-DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u");
-DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u");
-DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u");
-DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u");
-DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u");
-DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u");
-DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u");
-
-DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u");
-DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u");
-DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data,
-		     20, "%u");
-DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u");
-DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u");
-
-DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count);
-DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u",
-		      wl->stats.excessive_retries);
-
-static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
-				 size_t count, loff_t *ppos)
-{
-	struct wl1251 *wl = file->private_data;
-	u32 queue_len;
-	char buf[20];
-	int res;
-
-	queue_len = skb_queue_len(&wl->tx_queue);
-
-	res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
-	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
-}
-
-static const struct file_operations tx_queue_len_ops = {
-	.read = tx_queue_len_read,
-	.open = wl1251_open_file_generic,
-};
-
-static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf,
-				    size_t count, loff_t *ppos)
-{
-	struct wl1251 *wl = file->private_data;
-	char buf[3], status;
-	int len;
-
-	if (wl->tx_queue_stopped)
-		status = 's';
-	else
-		status = 'r';
-
-	len = scnprintf(buf, sizeof(buf), "%c\n", status);
-	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
-}
-
-static const struct file_operations tx_queue_status_ops = {
-	.read = tx_queue_status_read,
-	.open = wl1251_open_file_generic,
-};
-
-static void wl1251_debugfs_delete_files(struct wl1251 *wl)
-{
-	DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
-
-	DEBUGFS_FWSTATS_DEL(rx, out_of_mem);
-	DEBUGFS_FWSTATS_DEL(rx, hdr_overflow);
-	DEBUGFS_FWSTATS_DEL(rx, hw_stuck);
-	DEBUGFS_FWSTATS_DEL(rx, dropped);
-	DEBUGFS_FWSTATS_DEL(rx, fcs_err);
-	DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig);
-	DEBUGFS_FWSTATS_DEL(rx, path_reset);
-	DEBUGFS_FWSTATS_DEL(rx, reset_counter);
-
-	DEBUGFS_FWSTATS_DEL(dma, rx_requested);
-	DEBUGFS_FWSTATS_DEL(dma, rx_errors);
-	DEBUGFS_FWSTATS_DEL(dma, tx_requested);
-	DEBUGFS_FWSTATS_DEL(dma, tx_errors);
-
-	DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt);
-	DEBUGFS_FWSTATS_DEL(isr, fiqs);
-	DEBUGFS_FWSTATS_DEL(isr, rx_headers);
-	DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow);
-	DEBUGFS_FWSTATS_DEL(isr, rx_rdys);
-	DEBUGFS_FWSTATS_DEL(isr, irqs);
-	DEBUGFS_FWSTATS_DEL(isr, tx_procs);
-	DEBUGFS_FWSTATS_DEL(isr, decrypt_done);
-	DEBUGFS_FWSTATS_DEL(isr, dma0_done);
-	DEBUGFS_FWSTATS_DEL(isr, dma1_done);
-	DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete);
-	DEBUGFS_FWSTATS_DEL(isr, commands);
-	DEBUGFS_FWSTATS_DEL(isr, rx_procs);
-	DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes);
-	DEBUGFS_FWSTATS_DEL(isr, host_acknowledges);
-	DEBUGFS_FWSTATS_DEL(isr, pci_pm);
-	DEBUGFS_FWSTATS_DEL(isr, wakeups);
-	DEBUGFS_FWSTATS_DEL(isr, low_rssi);
-
-	DEBUGFS_FWSTATS_DEL(wep, addr_key_count);
-	DEBUGFS_FWSTATS_DEL(wep, default_key_count);
-	/* skipping wep.reserved */
-	DEBUGFS_FWSTATS_DEL(wep, key_not_found);
-	DEBUGFS_FWSTATS_DEL(wep, decrypt_fail);
-	DEBUGFS_FWSTATS_DEL(wep, packets);
-	DEBUGFS_FWSTATS_DEL(wep, interrupt);
-
-	DEBUGFS_FWSTATS_DEL(pwr, ps_enter);
-	DEBUGFS_FWSTATS_DEL(pwr, elp_enter);
-	DEBUGFS_FWSTATS_DEL(pwr, missing_bcns);
-	DEBUGFS_FWSTATS_DEL(pwr, wake_on_host);
-	DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp);
-	DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps);
-	DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps);
-	DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons);
-	DEBUGFS_FWSTATS_DEL(pwr, power_save_off);
-	DEBUGFS_FWSTATS_DEL(pwr, enable_ps);
-	DEBUGFS_FWSTATS_DEL(pwr, disable_ps);
-	DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps);
-	/* skipping cont_miss_bcns_spread for now */
-	DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons);
-
-	DEBUGFS_FWSTATS_DEL(mic, rx_pkts);
-	DEBUGFS_FWSTATS_DEL(mic, calc_failure);
-
-	DEBUGFS_FWSTATS_DEL(aes, encrypt_fail);
-	DEBUGFS_FWSTATS_DEL(aes, decrypt_fail);
-	DEBUGFS_FWSTATS_DEL(aes, encrypt_packets);
-	DEBUGFS_FWSTATS_DEL(aes, decrypt_packets);
-	DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt);
-	DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt);
-
-	DEBUGFS_FWSTATS_DEL(event, heart_beat);
-	DEBUGFS_FWSTATS_DEL(event, calibration);
-	DEBUGFS_FWSTATS_DEL(event, rx_mismatch);
-	DEBUGFS_FWSTATS_DEL(event, rx_mem_empty);
-	DEBUGFS_FWSTATS_DEL(event, rx_pool);
-	DEBUGFS_FWSTATS_DEL(event, oom_late);
-	DEBUGFS_FWSTATS_DEL(event, phy_transmit_error);
-	DEBUGFS_FWSTATS_DEL(event, tx_stuck);
-
-	DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts);
-	DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts);
-	DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime);
-	DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn);
-	DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn);
-	DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization);
-	DEBUGFS_FWSTATS_DEL(ps, upsd_utilization);
-
-	DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop);
-	DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data);
-	DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
-	DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data);
-	DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data);
-
-	DEBUGFS_DEL(tx_queue_len);
-	DEBUGFS_DEL(tx_queue_status);
-	DEBUGFS_DEL(retry_count);
-	DEBUGFS_DEL(excessive_retries);
-}
-
-static int wl1251_debugfs_add_files(struct wl1251 *wl)
-{
-	int ret = 0;
-
-	DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow);
-
-	DEBUGFS_FWSTATS_ADD(rx, out_of_mem);
-	DEBUGFS_FWSTATS_ADD(rx, hdr_overflow);
-	DEBUGFS_FWSTATS_ADD(rx, hw_stuck);
-	DEBUGFS_FWSTATS_ADD(rx, dropped);
-	DEBUGFS_FWSTATS_ADD(rx, fcs_err);
-	DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig);
-	DEBUGFS_FWSTATS_ADD(rx, path_reset);
-	DEBUGFS_FWSTATS_ADD(rx, reset_counter);
-
-	DEBUGFS_FWSTATS_ADD(dma, rx_requested);
-	DEBUGFS_FWSTATS_ADD(dma, rx_errors);
-	DEBUGFS_FWSTATS_ADD(dma, tx_requested);
-	DEBUGFS_FWSTATS_ADD(dma, tx_errors);
-
-	DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt);
-	DEBUGFS_FWSTATS_ADD(isr, fiqs);
-	DEBUGFS_FWSTATS_ADD(isr, rx_headers);
-	DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow);
-	DEBUGFS_FWSTATS_ADD(isr, rx_rdys);
-	DEBUGFS_FWSTATS_ADD(isr, irqs);
-	DEBUGFS_FWSTATS_ADD(isr, tx_procs);
-	DEBUGFS_FWSTATS_ADD(isr, decrypt_done);
-	DEBUGFS_FWSTATS_ADD(isr, dma0_done);
-	DEBUGFS_FWSTATS_ADD(isr, dma1_done);
-	DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete);
-	DEBUGFS_FWSTATS_ADD(isr, commands);
-	DEBUGFS_FWSTATS_ADD(isr, rx_procs);
-	DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes);
-	DEBUGFS_FWSTATS_ADD(isr, host_acknowledges);
-	DEBUGFS_FWSTATS_ADD(isr, pci_pm);
-	DEBUGFS_FWSTATS_ADD(isr, wakeups);
-	DEBUGFS_FWSTATS_ADD(isr, low_rssi);
-
-	DEBUGFS_FWSTATS_ADD(wep, addr_key_count);
-	DEBUGFS_FWSTATS_ADD(wep, default_key_count);
-	/* skipping wep.reserved */
-	DEBUGFS_FWSTATS_ADD(wep, key_not_found);
-	DEBUGFS_FWSTATS_ADD(wep, decrypt_fail);
-	DEBUGFS_FWSTATS_ADD(wep, packets);
-	DEBUGFS_FWSTATS_ADD(wep, interrupt);
-
-	DEBUGFS_FWSTATS_ADD(pwr, ps_enter);
-	DEBUGFS_FWSTATS_ADD(pwr, elp_enter);
-	DEBUGFS_FWSTATS_ADD(pwr, missing_bcns);
-	DEBUGFS_FWSTATS_ADD(pwr, wake_on_host);
-	DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp);
-	DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps);
-	DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps);
-	DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons);
-	DEBUGFS_FWSTATS_ADD(pwr, power_save_off);
-	DEBUGFS_FWSTATS_ADD(pwr, enable_ps);
-	DEBUGFS_FWSTATS_ADD(pwr, disable_ps);
-	DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps);
-	/* skipping cont_miss_bcns_spread for now */
-	DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons);
-
-	DEBUGFS_FWSTATS_ADD(mic, rx_pkts);
-	DEBUGFS_FWSTATS_ADD(mic, calc_failure);
-
-	DEBUGFS_FWSTATS_ADD(aes, encrypt_fail);
-	DEBUGFS_FWSTATS_ADD(aes, decrypt_fail);
-	DEBUGFS_FWSTATS_ADD(aes, encrypt_packets);
-	DEBUGFS_FWSTATS_ADD(aes, decrypt_packets);
-	DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt);
-	DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt);
-
-	DEBUGFS_FWSTATS_ADD(event, heart_beat);
-	DEBUGFS_FWSTATS_ADD(event, calibration);
-	DEBUGFS_FWSTATS_ADD(event, rx_mismatch);
-	DEBUGFS_FWSTATS_ADD(event, rx_mem_empty);
-	DEBUGFS_FWSTATS_ADD(event, rx_pool);
-	DEBUGFS_FWSTATS_ADD(event, oom_late);
-	DEBUGFS_FWSTATS_ADD(event, phy_transmit_error);
-	DEBUGFS_FWSTATS_ADD(event, tx_stuck);
-
-	DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts);
-	DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts);
-	DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime);
-	DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn);
-	DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn);
-	DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization);
-	DEBUGFS_FWSTATS_ADD(ps, upsd_utilization);
-
-	DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop);
-	DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data);
-	DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
-	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->debugfs.rootdir);
-	DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir);
-	DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
-	DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
-
-out:
-	if (ret < 0)
-		wl1251_debugfs_delete_files(wl);
-
-	return ret;
-}
-
-void wl1251_debugfs_reset(struct wl1251 *wl)
-{
-	if (wl->stats.fw_stats != NULL)
-		memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
-	wl->stats.retry_count = 0;
-	wl->stats.excessive_retries = 0;
-}
-
-int wl1251_debugfs_init(struct wl1251 *wl)
-{
-	int ret;
-
-	wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
-
-	if (IS_ERR(wl->debugfs.rootdir)) {
-		ret = PTR_ERR(wl->debugfs.rootdir);
-		wl->debugfs.rootdir = NULL;
-		goto err;
-	}
-
-	wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics",
-						       wl->debugfs.rootdir);
-
-	if (IS_ERR(wl->debugfs.fw_statistics)) {
-		ret = PTR_ERR(wl->debugfs.fw_statistics);
-		wl->debugfs.fw_statistics = NULL;
-		goto err_root;
-	}
-
-	wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats),
-				      GFP_KERNEL);
-
-	if (!wl->stats.fw_stats) {
-		ret = -ENOMEM;
-		goto err_fw;
-	}
-
-	wl->stats.fw_stats_update = jiffies;
-
-	ret = wl1251_debugfs_add_files(wl);
-
-	if (ret < 0)
-		goto err_file;
-
-	return 0;
-
-err_file:
-	kfree(wl->stats.fw_stats);
-	wl->stats.fw_stats = NULL;
-
-err_fw:
-	debugfs_remove(wl->debugfs.fw_statistics);
-	wl->debugfs.fw_statistics = NULL;
-
-err_root:
-	debugfs_remove(wl->debugfs.rootdir);
-	wl->debugfs.rootdir = NULL;
-
-err:
-	return ret;
-}
-
-void wl1251_debugfs_exit(struct wl1251 *wl)
-{
-	wl1251_debugfs_delete_files(wl);
-
-	kfree(wl->stats.fw_stats);
-	wl->stats.fw_stats = NULL;
-
-	debugfs_remove(wl->debugfs.fw_statistics);
-	wl->debugfs.fw_statistics = NULL;
-
-	debugfs_remove(wl->debugfs.rootdir);
-	wl->debugfs.rootdir = NULL;
-
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.h b/drivers/net/wireless/wl12xx/wl1251_debugfs.h
deleted file mode 100644
index 6dc3d08..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_debugfs.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef WL1251_DEBUGFS_H
-#define WL1251_DEBUGFS_H
-
-#include "wl1251.h"
-
-int wl1251_debugfs_init(struct wl1251 *wl);
-void wl1251_debugfs_exit(struct wl1251 *wl);
-void wl1251_debugfs_reset(struct wl1251 *wl);
-
-#endif /* WL1251_DEBUGFS_H */
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c
deleted file mode 100644
index 020d764..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_event.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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 "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_io.h"
-#include "wl1251_event.h"
-#include "wl1251_ps.h"
-
-static int wl1251_event_scan_complete(struct wl1251 *wl,
-				      struct event_mailbox *mbox)
-{
-	wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d",
-		     mbox->scheduled_scan_status,
-		     mbox->scheduled_scan_channels);
-
-	if (wl->scanning) {
-		mutex_unlock(&wl->mutex);
-		ieee80211_scan_completed(wl->hw, false);
-		mutex_lock(&wl->mutex);
-		wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed");
-		wl->scanning = false;
-	}
-
-	return 0;
-}
-
-static void wl1251_event_mbox_dump(struct event_mailbox *mbox)
-{
-	wl1251_debug(DEBUG_EVENT, "MBOX DUMP:");
-	wl1251_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector);
-	wl1251_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
-}
-
-static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
-{
-	int ret;
-	u32 vector;
-
-	wl1251_event_mbox_dump(mbox);
-
-	vector = mbox->events_vector & ~(mbox->events_mask);
-	wl1251_debug(DEBUG_EVENT, "vector: 0x%x", vector);
-
-	if (vector & SCAN_COMPLETE_EVENT_ID) {
-		ret = wl1251_event_scan_complete(wl, mbox);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (vector & BSS_LOSE_EVENT_ID) {
-		wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
-
-		if (wl->psm_requested && wl->psm) {
-			ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
-			if (ret < 0)
-				return ret;
-		}
-	}
-
-	if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && wl->psm) {
-		wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");
-
-		/* indicate to the stack, that beacons have been lost */
-		ieee80211_beacon_loss(wl->vif);
-	}
-
-	if (vector & REGAINED_BSS_EVENT_ID) {
-		if (wl->psm_requested) {
-			ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
-			if (ret < 0)
-				return ret;
-		}
-	}
-
-	return 0;
-}
-
-int wl1251_event_unmask(struct wl1251 *wl)
-{
-	int ret;
-
-	ret = wl1251_acx_event_mbox_mask(wl, ~(wl->event_mask));
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-void wl1251_event_mbox_config(struct wl1251 *wl)
-{
-	wl->mbox_ptr[0] = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
-	wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
-
-	wl1251_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
-		     wl->mbox_ptr[0], wl->mbox_ptr[1]);
-}
-
-int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num)
-{
-	struct event_mailbox mbox;
-	int ret;
-
-	wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
-
-	if (mbox_num > 1)
-		return -EINVAL;
-
-	/* first we read the mbox descriptor */
-	wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
-			    sizeof(struct event_mailbox));
-
-	/* process the descriptor */
-	ret = wl1251_event_process(wl, &mbox);
-	if (ret < 0)
-		return ret;
-
-	/* then we let the firmware know it can go on...*/
-	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
-
-	return 0;
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.h b/drivers/net/wireless/wl12xx/wl1251_event.h
deleted file mode 100644
index f48a2b6..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_event.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef __WL1251_EVENT_H__
-#define __WL1251_EVENT_H__
-
-/*
- * Mbox events
- *
- * The event mechanism is based on a pair of event buffers (buffers A and
- * B) at fixed locations in the target's memory. The host processes one
- * buffer while the other buffer continues to collect events. If the host
- * is not processing events, an interrupt is issued to signal that a buffer
- * is ready. Once the host is done with processing events from one buffer,
- * it signals the target (with an ACK interrupt) that the event buffer is
- * free.
- */
-
-enum {
-	RESERVED1_EVENT_ID                       = BIT(0),
-	RESERVED2_EVENT_ID                       = BIT(1),
-	MEASUREMENT_START_EVENT_ID               = BIT(2),
-	SCAN_COMPLETE_EVENT_ID                   = BIT(3),
-	CALIBRATION_COMPLETE_EVENT_ID            = BIT(4),
-	ROAMING_TRIGGER_LOW_RSSI_EVENT_ID        = BIT(5),
-	PS_REPORT_EVENT_ID                       = BIT(6),
-	SYNCHRONIZATION_TIMEOUT_EVENT_ID         = BIT(7),
-	HEALTH_REPORT_EVENT_ID                   = BIT(8),
-	ACI_DETECTION_EVENT_ID                   = BIT(9),
-	DEBUG_REPORT_EVENT_ID                    = BIT(10),
-	MAC_STATUS_EVENT_ID                      = BIT(11),
-	DISCONNECT_EVENT_COMPLETE_ID             = BIT(12),
-	JOIN_EVENT_COMPLETE_ID                   = BIT(13),
-	CHANNEL_SWITCH_COMPLETE_EVENT_ID         = BIT(14),
-	BSS_LOSE_EVENT_ID                        = BIT(15),
-	ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID    = BIT(16),
-	MEASUREMENT_COMPLETE_EVENT_ID            = BIT(17),
-	AP_DISCOVERY_COMPLETE_EVENT_ID           = BIT(18),
-	SCHEDULED_SCAN_COMPLETE_EVENT_ID         = BIT(19),
-	PSPOLL_DELIVERY_FAILURE_EVENT_ID 	 = BIT(20),
-	RESET_BSS_EVENT_ID                       = BIT(21),
-	REGAINED_BSS_EVENT_ID                    = BIT(22),
-	ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID   = BIT(23),
-	ROAMING_TRIGGER_LOW_SNR_EVENT_ID         = BIT(24),
-	ROAMING_TRIGGER_REGAINED_SNR_EVENT_ID    = BIT(25),
-
-	DBG_EVENT_ID                             = BIT(26),
-	BT_PTA_SENSE_EVENT_ID                    = BIT(27),
-	BT_PTA_PREDICTION_EVENT_ID               = BIT(28),
-	BT_PTA_AVALANCHE_EVENT_ID                = BIT(29),
-
-	PLT_RX_CALIBRATION_COMPLETE_EVENT_ID     = BIT(30),
-
-	EVENT_MBOX_ALL_EVENT_ID                  = 0x7fffffff,
-};
-
-struct event_debug_report {
-	u8 debug_event_id;
-	u8 num_params;
-	u16 pad;
-	u32 report_1;
-	u32 report_2;
-	u32 report_3;
-} __packed;
-
-struct event_mailbox {
-	u32 events_vector;
-	u32 events_mask;
-	u32 reserved_1;
-	u32 reserved_2;
-
-	char average_rssi_level;
-	u8 ps_status;
-	u8 channel_switch_status;
-	u8 scheduled_scan_status;
-
-	/* Channels scanned by the scheduled scan */
-	u16 scheduled_scan_channels;
-
-	/* If bit 0 is set -> target's fatal error */
-	u16 health_report;
-	u16 bad_fft_counter;
-	u8 bt_pta_sense_info;
-	u8 bt_pta_protective_info;
-	u32 reserved;
-	u32 debug_report[2];
-
-	/* Number of FCS errors since last event */
-	u32 fcs_err_counter;
-
-	struct event_debug_report report;
-	u8 average_snr_level;
-	u8 padding[19];
-} __packed;
-
-int wl1251_event_unmask(struct wl1251 *wl);
-void wl1251_event_mbox_config(struct wl1251 *wl);
-int wl1251_event_handle(struct wl1251 *wl, u8 mbox);
-
-#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c
deleted file mode 100644
index b538bdd..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_init.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include "wl1251_init.h"
-#include "wl12xx_80211.h"
-#include "wl1251_acx.h"
-#include "wl1251_cmd.h"
-#include "wl1251_reg.h"
-
-int wl1251_hw_init_hwenc_config(struct wl1251 *wl)
-{
-	int ret;
-
-	ret = wl1251_acx_feature_cfg(wl);
-	if (ret < 0) {
-		wl1251_warning("couldn't set feature config");
-		return ret;
-	}
-
-	ret = wl1251_acx_default_key(wl, wl->default_key);
-	if (ret < 0) {
-		wl1251_warning("couldn't set default key");
-		return ret;
-	}
-
-	return 0;
-}
-
-int wl1251_hw_init_templates_config(struct wl1251 *wl)
-{
-	int ret;
-	u8 partial_vbm[PARTIAL_VBM_MAX];
-
-	/* send empty templates for fw memory reservation */
-	ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, NULL,
-				      sizeof(struct wl12xx_probe_req_template));
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, NULL,
-				      sizeof(struct wl12xx_null_data_template));
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_cmd_template_set(wl, CMD_PS_POLL, NULL,
-				      sizeof(struct wl12xx_ps_poll_template));
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, NULL,
-				      sizeof
-				      (struct wl12xx_qos_null_data_template));
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, NULL,
-				      sizeof
-				      (struct wl12xx_probe_resp_template));
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_cmd_template_set(wl, CMD_BEACON, NULL,
-				      sizeof
-				      (struct wl12xx_beacon_template));
-	if (ret < 0)
-		return ret;
-
-	/* tim templates, first reserve space then allocate an empty one */
-	memset(partial_vbm, 0, PARTIAL_VBM_MAX);
-	ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, PARTIAL_VBM_MAX, 0);
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, 1, 0);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter)
-{
-	int ret;
-
-	ret = wl1251_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF);
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_acx_rx_config(wl, config, filter);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-int wl1251_hw_init_phy_config(struct wl1251 *wl)
-{
-	int ret;
-
-	ret = wl1251_acx_pd_threshold(wl);
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_acx_slot(wl, DEFAULT_SLOT_TIME);
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_acx_group_address_tbl(wl);
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_acx_service_period_timeout(wl);
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_acx_rts_threshold(wl, RTS_THRESHOLD_DEF);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-int wl1251_hw_init_beacon_filter(struct wl1251 *wl)
-{
-	int ret;
-
-	/* disable beacon filtering at this stage */
-	ret = wl1251_acx_beacon_filter_opt(wl, false);
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_acx_beacon_filter_table(wl);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-int wl1251_hw_init_pta(struct wl1251 *wl)
-{
-	int ret;
-
-	ret = wl1251_acx_sg_enable(wl);
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_acx_sg_cfg(wl);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-int wl1251_hw_init_energy_detection(struct wl1251 *wl)
-{
-	int ret;
-
-	ret = wl1251_acx_cca_threshold(wl);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl)
-{
-	int ret;
-
-	ret = wl1251_acx_bcn_dtim_options(wl);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-int wl1251_hw_init_power_auth(struct wl1251 *wl)
-{
-	return wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM);
-}
-
-int wl1251_hw_init_mem_config(struct wl1251 *wl)
-{
-	int ret;
-
-	ret = wl1251_acx_mem_cfg(wl);
-	if (ret < 0)
-		return ret;
-
-	wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map),
-					  GFP_KERNEL);
-	if (!wl->target_mem_map) {
-		wl1251_error("couldn't allocate target memory map");
-		return -ENOMEM;
-	}
-
-	/* we now ask for the firmware built memory map */
-	ret = wl1251_acx_mem_map(wl, wl->target_mem_map,
-				 sizeof(struct wl1251_acx_mem_map));
-	if (ret < 0) {
-		wl1251_error("couldn't retrieve firmware memory map");
-		kfree(wl->target_mem_map);
-		wl->target_mem_map = NULL;
-		return ret;
-	}
-
-	return 0;
-}
-
-static int wl1251_hw_init_txq_fill(u8 qid,
-				   struct acx_tx_queue_qos_config *config,
-				   u32 num_blocks)
-{
-	config->qid = qid;
-
-	switch (qid) {
-	case QOS_AC_BE:
-		config->high_threshold =
-			(QOS_TX_HIGH_BE_DEF * num_blocks) / 100;
-		config->low_threshold =
-			(QOS_TX_LOW_BE_DEF * num_blocks) / 100;
-		break;
-	case QOS_AC_BK:
-		config->high_threshold =
-			(QOS_TX_HIGH_BK_DEF * num_blocks) / 100;
-		config->low_threshold =
-			(QOS_TX_LOW_BK_DEF * num_blocks) / 100;
-		break;
-	case QOS_AC_VI:
-		config->high_threshold =
-			(QOS_TX_HIGH_VI_DEF * num_blocks) / 100;
-		config->low_threshold =
-			(QOS_TX_LOW_VI_DEF * num_blocks) / 100;
-		break;
-	case QOS_AC_VO:
-		config->high_threshold =
-			(QOS_TX_HIGH_VO_DEF * num_blocks) / 100;
-		config->low_threshold =
-			(QOS_TX_LOW_VO_DEF * num_blocks) / 100;
-		break;
-	default:
-		wl1251_error("Invalid TX queue id: %d", qid);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl)
-{
-	struct acx_tx_queue_qos_config *config;
-	struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map;
-	int ret, i;
-
-	wl1251_debug(DEBUG_ACX, "acx tx queue config");
-
-	config = kzalloc(sizeof(*config), GFP_KERNEL);
-	if (!config) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	for (i = 0; i < MAX_NUM_OF_AC; i++) {
-		ret = wl1251_hw_init_txq_fill(i, config,
-					      wl_mem_map->num_tx_mem_blocks);
-		if (ret < 0)
-			goto out;
-
-		ret = wl1251_cmd_configure(wl, ACX_TX_QUEUE_CFG,
-					   config, sizeof(*config));
-		if (ret < 0)
-			goto out;
-	}
-
-	wl1251_acx_ac_cfg(wl, AC_BE, CWMIN_BE, CWMAX_BE, AIFS_DIFS, TXOP_BE);
-	wl1251_acx_ac_cfg(wl, AC_BK, CWMIN_BK, CWMAX_BK, AIFS_DIFS, TXOP_BK);
-	wl1251_acx_ac_cfg(wl, AC_VI, CWMIN_VI, CWMAX_VI, AIFS_DIFS, TXOP_VI);
-	wl1251_acx_ac_cfg(wl, AC_VO, CWMIN_VO, CWMAX_VO, AIFS_DIFS, TXOP_VO);
-
-out:
-	kfree(config);
-	return ret;
-}
-
-static int wl1251_hw_init_data_path_config(struct wl1251 *wl)
-{
-	int ret;
-
-	/* asking for the data path parameters */
-	wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp),
-				GFP_KERNEL);
-	if (!wl->data_path) {
-		wl1251_error("Couldnt allocate data path parameters");
-		return -ENOMEM;
-	}
-
-	ret = wl1251_acx_data_path_params(wl, wl->data_path);
-	if (ret < 0) {
-		kfree(wl->data_path);
-		wl->data_path = NULL;
-		return ret;
-	}
-
-	return 0;
-}
-
-
-int wl1251_hw_init(struct wl1251 *wl)
-{
-	struct wl1251_acx_mem_map *wl_mem_map;
-	int ret;
-
-	ret = wl1251_hw_init_hwenc_config(wl);
-	if (ret < 0)
-		return ret;
-
-	/* Template settings */
-	ret = wl1251_hw_init_templates_config(wl);
-	if (ret < 0)
-		return ret;
-
-	/* Default memory configuration */
-	ret = wl1251_hw_init_mem_config(wl);
-	if (ret < 0)
-		return ret;
-
-	/* Default data path configuration  */
-	ret = wl1251_hw_init_data_path_config(wl);
-	if (ret < 0)
-		goto out_free_memmap;
-
-	/* RX config */
-	ret = wl1251_hw_init_rx_config(wl,
-				       RX_CFG_PROMISCUOUS | RX_CFG_TSF,
-				       RX_FILTER_OPTION_DEF);
-	/* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
-	   RX_FILTER_OPTION_FILTER_ALL); */
-	if (ret < 0)
-		goto out_free_data_path;
-
-	/* TX queues config */
-	ret = wl1251_hw_init_tx_queue_config(wl);
-	if (ret < 0)
-		goto out_free_data_path;
-
-	/* PHY layer config */
-	ret = wl1251_hw_init_phy_config(wl);
-	if (ret < 0)
-		goto out_free_data_path;
-
-	/* Initialize connection monitoring thresholds */
-	ret = wl1251_acx_conn_monit_params(wl);
-	if (ret < 0)
-		goto out_free_data_path;
-
-	/* Beacon filtering */
-	ret = wl1251_hw_init_beacon_filter(wl);
-	if (ret < 0)
-		goto out_free_data_path;
-
-	/* Bluetooth WLAN coexistence */
-	ret = wl1251_hw_init_pta(wl);
-	if (ret < 0)
-		goto out_free_data_path;
-
-	/* Energy detection */
-	ret = wl1251_hw_init_energy_detection(wl);
-	if (ret < 0)
-		goto out_free_data_path;
-
-	/* Beacons and boradcast settings */
-	ret = wl1251_hw_init_beacon_broadcast(wl);
-	if (ret < 0)
-		goto out_free_data_path;
-
-	/* Enable data path */
-	ret = wl1251_cmd_data_path(wl, wl->channel, 1);
-	if (ret < 0)
-		goto out_free_data_path;
-
-	/* Default power state */
-	ret = wl1251_hw_init_power_auth(wl);
-	if (ret < 0)
-		goto out_free_data_path;
-
-	wl_mem_map = wl->target_mem_map;
-	wl1251_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x",
-		    wl_mem_map->num_tx_mem_blocks,
-		    wl->data_path->tx_control_addr,
-		    wl_mem_map->num_rx_mem_blocks,
-		    wl->data_path->rx_control_addr);
-
-	return 0;
-
- out_free_data_path:
-	kfree(wl->data_path);
-
- out_free_memmap:
-	kfree(wl->target_mem_map);
-
-	return ret;
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl12xx/wl1251_init.h
deleted file mode 100644
index 269cefb..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_init.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef __WL1251_INIT_H__
-#define __WL1251_INIT_H__
-
-#include "wl1251.h"
-
-enum {
-	/* best effort/legacy */
-	AC_BE = 0,
-
-	/* background */
-	AC_BK = 1,
-
-	/* video */
-	AC_VI = 2,
-
-	/* voice */
-	AC_VO = 3,
-
-	/* broadcast dummy access category */
-	AC_BCAST = 4,
-
-	NUM_ACCESS_CATEGORIES = 4
-};
-
-/* following are defult values for the IE fields*/
-#define CWMIN_BK  15
-#define CWMIN_BE  15
-#define CWMIN_VI  7
-#define CWMIN_VO  3
-#define CWMAX_BK  1023
-#define CWMAX_BE  63
-#define CWMAX_VI  15
-#define CWMAX_VO  7
-
-/* slot number setting to start transmission at PIFS interval */
-#define AIFS_PIFS 1
-
-/*
- * slot number setting to start transmission at DIFS interval - normal DCF
- * access
- */
-#define AIFS_DIFS 2
-
-#define AIFSN_BK  7
-#define AIFSN_BE  3
-#define AIFSN_VI  AIFS_PIFS
-#define AIFSN_VO  AIFS_PIFS
-#define TXOP_BK   0
-#define TXOP_BE   0
-#define TXOP_VI   3008
-#define TXOP_VO   1504
-
-int wl1251_hw_init_hwenc_config(struct wl1251 *wl);
-int wl1251_hw_init_templates_config(struct wl1251 *wl);
-int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter);
-int wl1251_hw_init_phy_config(struct wl1251 *wl);
-int wl1251_hw_init_beacon_filter(struct wl1251 *wl);
-int wl1251_hw_init_pta(struct wl1251 *wl);
-int wl1251_hw_init_energy_detection(struct wl1251 *wl);
-int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl);
-int wl1251_hw_init_power_auth(struct wl1251 *wl);
-int wl1251_hw_init_mem_config(struct wl1251 *wl);
-int wl1251_hw_init(struct wl1251 *wl);
-
-#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.c b/drivers/net/wireless/wl12xx/wl1251_io.c
deleted file mode 100644
index f1c232e..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_io.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * This file is part of wl12xx
- *
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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 "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_io.h"
-
-/* FIXME: this is static data nowadays and the table can be removed */
-static enum wl12xx_acx_int_reg wl1251_io_reg_table[ACX_REG_TABLE_LEN] = {
-	[ACX_REG_INTERRUPT_TRIG]     = (REGISTERS_BASE + 0x0474),
-	[ACX_REG_INTERRUPT_TRIG_H]   = (REGISTERS_BASE + 0x0478),
-	[ACX_REG_INTERRUPT_MASK]     = (REGISTERS_BASE + 0x0494),
-	[ACX_REG_HINT_MASK_SET]      = (REGISTERS_BASE + 0x0498),
-	[ACX_REG_HINT_MASK_CLR]      = (REGISTERS_BASE + 0x049C),
-	[ACX_REG_INTERRUPT_NO_CLEAR] = (REGISTERS_BASE + 0x04B0),
-	[ACX_REG_INTERRUPT_CLEAR]    = (REGISTERS_BASE + 0x04A4),
-	[ACX_REG_INTERRUPT_ACK]      = (REGISTERS_BASE + 0x04A8),
-	[ACX_REG_SLV_SOFT_RESET]     = (REGISTERS_BASE + 0x0000),
-	[ACX_REG_EE_START]           = (REGISTERS_BASE + 0x080C),
-	[ACX_REG_ECPU_CONTROL]       = (REGISTERS_BASE + 0x0804)
-};
-
-static int wl1251_translate_reg_addr(struct wl1251 *wl, int addr)
-{
-	/* If the address is lower than REGISTERS_BASE, it means that this is
-	 * a chip-specific register address, so look it up in the registers
-	 * table */
-	if (addr < REGISTERS_BASE) {
-		/* Make sure we don't go over the table */
-		if (addr >= ACX_REG_TABLE_LEN) {
-			wl1251_error("address out of range (%d)", addr);
-			return -EINVAL;
-		}
-		addr = wl1251_io_reg_table[addr];
-	}
-
-	return addr - wl->physical_reg_addr + wl->virtual_reg_addr;
-}
-
-static int wl1251_translate_mem_addr(struct wl1251 *wl, int addr)
-{
-	return addr - wl->physical_mem_addr + wl->virtual_mem_addr;
-}
-
-void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len)
-{
-	int physical;
-
-	physical = wl1251_translate_mem_addr(wl, addr);
-
-	wl->if_ops->read(wl, physical, buf, len);
-}
-
-void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len)
-{
-	int physical;
-
-	physical = wl1251_translate_mem_addr(wl, addr);
-
-	wl->if_ops->write(wl, physical, buf, len);
-}
-
-u32 wl1251_mem_read32(struct wl1251 *wl, int addr)
-{
-	return wl1251_read32(wl, wl1251_translate_mem_addr(wl, addr));
-}
-
-void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val)
-{
-	wl1251_write32(wl, wl1251_translate_mem_addr(wl, addr), val);
-}
-
-u32 wl1251_reg_read32(struct wl1251 *wl, int addr)
-{
-	return wl1251_read32(wl, wl1251_translate_reg_addr(wl, addr));
-}
-
-void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val)
-{
-	wl1251_write32(wl, wl1251_translate_reg_addr(wl, addr), val);
-}
-
-/* Set the partitions to access the chip addresses.
- *
- * There are two VIRTUAL partitions (the memory partition and the
- * registers partition), which are mapped to two different areas of the
- * PHYSICAL (hardware) memory.  This function also makes other checks to
- * ensure that the partitions are not overlapping.  In the diagram below, the
- * memory partition comes before the register partition, but the opposite is
- * also supported.
- *
- *                               PHYSICAL address
- *                                     space
- *
- *                                    |    |
- *                                 ...+----+--> mem_start
- *          VIRTUAL address     ...   |    |
- *               space       ...      |    | [PART_0]
- *                        ...         |    |
- * 0x00000000 <--+----+...         ...+----+--> mem_start + mem_size
- *               |    |         ...   |    |
- *               |MEM |      ...      |    |
- *               |    |   ...         |    |
- *  part_size <--+----+...            |    | {unused area)
- *               |    |   ...         |    |
- *               |REG |      ...      |    |
- *  part_size    |    |         ...   |    |
- *      +     <--+----+...         ...+----+--> reg_start
- *  reg_size              ...         |    |
- *                           ...      |    | [PART_1]
- *                              ...   |    |
- *                                 ...+----+--> reg_start + reg_size
- *                                    |    |
- *
- */
-void wl1251_set_partition(struct wl1251 *wl,
-			  u32 mem_start, u32 mem_size,
-			  u32 reg_start, u32 reg_size)
-{
-	struct wl1251_partition partition[2];
-
-	wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
-		     mem_start, mem_size);
-	wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
-		     reg_start, reg_size);
-
-	/* Make sure that the two partitions together don't exceed the
-	 * address range */
-	if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) {
-		wl1251_debug(DEBUG_SPI, "Total size exceeds maximum virtual"
-			     " address range.  Truncating partition[0].");
-		mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size;
-		wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
-			     mem_start, mem_size);
-		wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
-			     reg_start, reg_size);
-	}
-
-	if ((mem_start < reg_start) &&
-	    ((mem_start + mem_size) > reg_start)) {
-		/* Guarantee that the memory partition doesn't overlap the
-		 * registers partition */
-		wl1251_debug(DEBUG_SPI, "End of partition[0] is "
-			     "overlapping partition[1].  Adjusted.");
-		mem_size = reg_start - mem_start;
-		wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
-			     mem_start, mem_size);
-		wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
-			     reg_start, reg_size);
-	} else if ((reg_start < mem_start) &&
-		   ((reg_start + reg_size) > mem_start)) {
-		/* Guarantee that the register partition doesn't overlap the
-		 * memory partition */
-		wl1251_debug(DEBUG_SPI, "End of partition[1] is"
-			     " overlapping partition[0].  Adjusted.");
-		reg_size = mem_start - reg_start;
-		wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
-			     mem_start, mem_size);
-		wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
-			     reg_start, reg_size);
-	}
-
-	partition[0].start = mem_start;
-	partition[0].size  = mem_size;
-	partition[1].start = reg_start;
-	partition[1].size  = reg_size;
-
-	wl->physical_mem_addr = mem_start;
-	wl->physical_reg_addr = reg_start;
-
-	wl->virtual_mem_addr = 0;
-	wl->virtual_reg_addr = mem_size;
-
-	wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition,
-		sizeof(partition));
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
deleted file mode 100644
index 861a5f3..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ /dev/null
@@ -1,1442 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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/interrupt.h>
-#include <linux/firmware.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/crc32.h>
-#include <linux/etherdevice.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-
-#include "wl1251.h"
-#include "wl12xx_80211.h"
-#include "wl1251_reg.h"
-#include "wl1251_io.h"
-#include "wl1251_cmd.h"
-#include "wl1251_event.h"
-#include "wl1251_tx.h"
-#include "wl1251_rx.h"
-#include "wl1251_ps.h"
-#include "wl1251_init.h"
-#include "wl1251_debugfs.h"
-#include "wl1251_boot.h"
-
-void wl1251_enable_interrupts(struct wl1251 *wl)
-{
-	wl->if_ops->enable_irq(wl);
-}
-
-void wl1251_disable_interrupts(struct wl1251 *wl)
-{
-	wl->if_ops->disable_irq(wl);
-}
-
-static void wl1251_power_off(struct wl1251 *wl)
-{
-	wl->set_power(false);
-}
-
-static void wl1251_power_on(struct wl1251 *wl)
-{
-	wl->set_power(true);
-}
-
-static int wl1251_fetch_firmware(struct wl1251 *wl)
-{
-	const struct firmware *fw;
-	struct device *dev = wiphy_dev(wl->hw->wiphy);
-	int ret;
-
-	ret = request_firmware(&fw, WL1251_FW_NAME, dev);
-
-	if (ret < 0) {
-		wl1251_error("could not get firmware: %d", ret);
-		return ret;
-	}
-
-	if (fw->size % 4) {
-		wl1251_error("firmware size is not multiple of 32 bits: %zu",
-			     fw->size);
-		ret = -EILSEQ;
-		goto out;
-	}
-
-	wl->fw_len = fw->size;
-	wl->fw = vmalloc(wl->fw_len);
-
-	if (!wl->fw) {
-		wl1251_error("could not allocate memory for the firmware");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	memcpy(wl->fw, fw->data, wl->fw_len);
-
-	ret = 0;
-
-out:
-	release_firmware(fw);
-
-	return ret;
-}
-
-static int wl1251_fetch_nvs(struct wl1251 *wl)
-{
-	const struct firmware *fw;
-	struct device *dev = wiphy_dev(wl->hw->wiphy);
-	int ret;
-
-	ret = request_firmware(&fw, WL1251_NVS_NAME, dev);
-
-	if (ret < 0) {
-		wl1251_error("could not get nvs file: %d", ret);
-		return ret;
-	}
-
-	if (fw->size % 4) {
-		wl1251_error("nvs size is not multiple of 32 bits: %zu",
-			     fw->size);
-		ret = -EILSEQ;
-		goto out;
-	}
-
-	wl->nvs_len = fw->size;
-	wl->nvs = kmemdup(fw->data, wl->nvs_len, GFP_KERNEL);
-
-	if (!wl->nvs) {
-		wl1251_error("could not allocate memory for the nvs file");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	ret = 0;
-
-out:
-	release_firmware(fw);
-
-	return ret;
-}
-
-static void wl1251_fw_wakeup(struct wl1251 *wl)
-{
-	u32 elp_reg;
-
-	elp_reg = ELPCTRL_WAKE_UP;
-	wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
-	elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
-
-	if (!(elp_reg & ELPCTRL_WLAN_READY))
-		wl1251_warning("WLAN not ready");
-}
-
-static int wl1251_chip_wakeup(struct wl1251 *wl)
-{
-	int ret = 0;
-
-	wl1251_power_on(wl);
-	msleep(WL1251_POWER_ON_SLEEP);
-	wl->if_ops->reset(wl);
-
-	/* We don't need a real memory partition here, because we only want
-	 * to use the registers at this point. */
-	wl1251_set_partition(wl,
-			     0x00000000,
-			     0x00000000,
-			     REGISTERS_BASE,
-			     REGISTERS_DOWN_SIZE);
-
-	/* ELP module wake up */
-	wl1251_fw_wakeup(wl);
-
-	/* whal_FwCtrl_BootSm() */
-
-	/* 0. read chip id from CHIP_ID */
-	wl->chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
-
-	/* 1. check if chip id is valid */
-
-	switch (wl->chip_id) {
-	case CHIP_ID_1251_PG12:
-		wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)",
-			     wl->chip_id);
-		break;
-	case CHIP_ID_1251_PG11:
-		wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG11)",
-			     wl->chip_id);
-		break;
-	case CHIP_ID_1251_PG10:
-	default:
-		wl1251_error("unsupported chip id: 0x%x", wl->chip_id);
-		ret = -ENODEV;
-		goto out;
-	}
-
-	if (wl->fw == NULL) {
-		ret = wl1251_fetch_firmware(wl);
-		if (ret < 0)
-			goto out;
-	}
-
-	if (wl->nvs == NULL && !wl->use_eeprom) {
-		/* No NVS from netlink, try to get it from the filesystem */
-		ret = wl1251_fetch_nvs(wl);
-		if (ret < 0)
-			goto out;
-	}
-
-out:
-	return ret;
-}
-
-#define WL1251_IRQ_LOOP_COUNT 10
-static void wl1251_irq_work(struct work_struct *work)
-{
-	u32 intr, ctr = WL1251_IRQ_LOOP_COUNT;
-	struct wl1251 *wl =
-		container_of(work, struct wl1251, irq_work);
-	int ret;
-
-	mutex_lock(&wl->mutex);
-
-	wl1251_debug(DEBUG_IRQ, "IRQ work");
-
-	if (wl->state == WL1251_STATE_OFF)
-		goto out;
-
-	ret = wl1251_ps_elp_wakeup(wl);
-	if (ret < 0)
-		goto out;
-
-	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL);
-
-	intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
-	wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr);
-
-	do {
-		if (wl->data_path) {
-			wl->rx_counter = wl1251_mem_read32(
-				wl, wl->data_path->rx_control_addr);
-
-			/* We handle a frmware bug here */
-			switch ((wl->rx_counter - wl->rx_handled) & 0xf) {
-			case 0:
-				wl1251_debug(DEBUG_IRQ,
-					     "RX: FW and host in sync");
-				intr &= ~WL1251_ACX_INTR_RX0_DATA;
-				intr &= ~WL1251_ACX_INTR_RX1_DATA;
-				break;
-			case 1:
-				wl1251_debug(DEBUG_IRQ, "RX: FW +1");
-				intr |= WL1251_ACX_INTR_RX0_DATA;
-				intr &= ~WL1251_ACX_INTR_RX1_DATA;
-				break;
-			case 2:
-				wl1251_debug(DEBUG_IRQ, "RX: FW +2");
-				intr |= WL1251_ACX_INTR_RX0_DATA;
-				intr |= WL1251_ACX_INTR_RX1_DATA;
-				break;
-			default:
-				wl1251_warning(
-					"RX: FW and host out of sync: %d",
-					wl->rx_counter - wl->rx_handled);
-				break;
-			}
-
-			wl->rx_handled = wl->rx_counter;
-
-			wl1251_debug(DEBUG_IRQ, "RX counter: %d",
-				     wl->rx_counter);
-		}
-
-		intr &= wl->intr_mask;
-
-		if (intr == 0) {
-			wl1251_debug(DEBUG_IRQ, "INTR is 0");
-			goto out_sleep;
-		}
-
-		if (intr & WL1251_ACX_INTR_RX0_DATA) {
-			wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA");
-			wl1251_rx(wl);
-		}
-
-		if (intr & WL1251_ACX_INTR_RX1_DATA) {
-			wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA");
-			wl1251_rx(wl);
-		}
-
-		if (intr & WL1251_ACX_INTR_TX_RESULT) {
-			wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT");
-			wl1251_tx_complete(wl);
-		}
-
-		if (intr & (WL1251_ACX_INTR_EVENT_A |
-			    WL1251_ACX_INTR_EVENT_B)) {
-			wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)",
-				     intr);
-			if (intr & WL1251_ACX_INTR_EVENT_A)
-				wl1251_event_handle(wl, 0);
-			else
-				wl1251_event_handle(wl, 1);
-		}
-
-		if (intr & WL1251_ACX_INTR_INIT_COMPLETE)
-			wl1251_debug(DEBUG_IRQ,
-				     "WL1251_ACX_INTR_INIT_COMPLETE");
-
-		if (--ctr == 0)
-			break;
-
-		intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
-	} while (intr);
-
-out_sleep:
-	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
-	wl1251_ps_elp_sleep(wl);
-
-out:
-	mutex_unlock(&wl->mutex);
-}
-
-static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel,
-		       u16 beacon_interval, u8 dtim_period)
-{
-	int ret;
-
-	ret = wl1251_acx_frame_rates(wl, DEFAULT_HW_GEN_TX_RATE,
-				     DEFAULT_HW_GEN_MODULATION_TYPE,
-				     wl->tx_mgmt_frm_rate,
-				     wl->tx_mgmt_frm_mod);
-	if (ret < 0)
-		goto out;
-
-
-	ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval,
-			      dtim_period);
-	if (ret < 0)
-		goto out;
-
-	/*
-	 * FIXME: we should wait for JOIN_EVENT_COMPLETE_ID but to simplify
-	 * locking we just sleep instead, for now
-	 */
-	msleep(10);
-
-out:
-	return ret;
-}
-
-static void wl1251_filter_work(struct work_struct *work)
-{
-	struct wl1251 *wl =
-		container_of(work, struct wl1251, filter_work);
-	int ret;
-
-	mutex_lock(&wl->mutex);
-
-	if (wl->state == WL1251_STATE_OFF)
-		goto out;
-
-	ret = wl1251_ps_elp_wakeup(wl);
-	if (ret < 0)
-		goto out;
-
-	ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int,
-			  wl->dtim_period);
-	if (ret < 0)
-		goto out_sleep;
-
-out_sleep:
-	wl1251_ps_elp_sleep(wl);
-
-out:
-	mutex_unlock(&wl->mutex);
-}
-
-static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct wl1251 *wl = hw->priv;
-
-	skb_queue_tail(&wl->tx_queue, skb);
-
-	/*
-	 * The chip specific setup must run before the first TX packet -
-	 * before that, the tx_work will not be initialized!
-	 */
-
-	ieee80211_queue_work(wl->hw, &wl->tx_work);
-
-	/*
-	 * The workqueue is slow to process the tx_queue and we need stop
-	 * the queue here, otherwise the queue will get too long.
-	 */
-	if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) {
-		wl1251_debug(DEBUG_TX, "op_tx: tx_queue full, stop queues");
-		ieee80211_stop_queues(wl->hw);
-
-		/*
-		 * FIXME: this is racy, the variable is not properly
-		 * protected. Maybe fix this by removing the stupid
-		 * variable altogether and checking the real queue state?
-		 */
-		wl->tx_queue_stopped = true;
-	}
-
-	return NETDEV_TX_OK;
-}
-
-static int wl1251_op_start(struct ieee80211_hw *hw)
-{
-	struct wl1251 *wl = hw->priv;
-	struct wiphy *wiphy = hw->wiphy;
-	int ret = 0;
-
-	wl1251_debug(DEBUG_MAC80211, "mac80211 start");
-
-	mutex_lock(&wl->mutex);
-
-	if (wl->state != WL1251_STATE_OFF) {
-		wl1251_error("cannot start because not in off state: %d",
-			     wl->state);
-		ret = -EBUSY;
-		goto out;
-	}
-
-	ret = wl1251_chip_wakeup(wl);
-	if (ret < 0)
-		goto out;
-
-	ret = wl1251_boot(wl);
-	if (ret < 0)
-		goto out;
-
-	ret = wl1251_hw_init(wl);
-	if (ret < 0)
-		goto out;
-
-	ret = wl1251_acx_station_id(wl);
-	if (ret < 0)
-		goto out;
-
-	wl->state = WL1251_STATE_ON;
-
-	wl1251_info("firmware booted (%s)", wl->fw_ver);
-
-	/* update hw/fw version info in wiphy struct */
-	wiphy->hw_version = wl->chip_id;
-	strncpy(wiphy->fw_version, wl->fw_ver, sizeof(wiphy->fw_version));
-
-out:
-	if (ret < 0)
-		wl1251_power_off(wl);
-
-	mutex_unlock(&wl->mutex);
-
-	return ret;
-}
-
-static void wl1251_op_stop(struct ieee80211_hw *hw)
-{
-	struct wl1251 *wl = hw->priv;
-
-	wl1251_info("down");
-
-	wl1251_debug(DEBUG_MAC80211, "mac80211 stop");
-
-	mutex_lock(&wl->mutex);
-
-	WARN_ON(wl->state != WL1251_STATE_ON);
-
-	if (wl->scanning) {
-		mutex_unlock(&wl->mutex);
-		ieee80211_scan_completed(wl->hw, true);
-		mutex_lock(&wl->mutex);
-		wl->scanning = false;
-	}
-
-	wl->state = WL1251_STATE_OFF;
-
-	wl1251_disable_interrupts(wl);
-
-	mutex_unlock(&wl->mutex);
-
-	cancel_work_sync(&wl->irq_work);
-	cancel_work_sync(&wl->tx_work);
-	cancel_work_sync(&wl->filter_work);
-
-	mutex_lock(&wl->mutex);
-
-	/* let's notify MAC80211 about the remaining pending TX frames */
-	wl1251_tx_flush(wl);
-	wl1251_power_off(wl);
-
-	memset(wl->bssid, 0, ETH_ALEN);
-	wl->listen_int = 1;
-	wl->bss_type = MAX_BSS_TYPE;
-
-	wl->data_in_count = 0;
-	wl->rx_counter = 0;
-	wl->rx_handled = 0;
-	wl->rx_current_buffer = 0;
-	wl->rx_last_id = 0;
-	wl->next_tx_complete = 0;
-	wl->elp = false;
-	wl->psm = 0;
-	wl->tx_queue_stopped = false;
-	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
-	wl->channel = WL1251_DEFAULT_CHANNEL;
-
-	wl1251_debugfs_reset(wl);
-
-	mutex_unlock(&wl->mutex);
-}
-
-static int wl1251_op_add_interface(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif)
-{
-	struct wl1251 *wl = hw->priv;
-	int ret = 0;
-
-	wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
-		     vif->type, vif->addr);
-
-	mutex_lock(&wl->mutex);
-	if (wl->vif) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	wl->vif = vif;
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		wl->bss_type = BSS_TYPE_STA_BSS;
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		wl->bss_type = BSS_TYPE_IBSS;
-		break;
-	default:
-		ret = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) {
-		memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
-		SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
-		ret = wl1251_acx_station_id(wl);
-		if (ret < 0)
-			goto out;
-	}
-
-out:
-	mutex_unlock(&wl->mutex);
-	return ret;
-}
-
-static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
-					 struct ieee80211_vif *vif)
-{
-	struct wl1251 *wl = hw->priv;
-
-	mutex_lock(&wl->mutex);
-	wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface");
-	wl->vif = NULL;
-	mutex_unlock(&wl->mutex);
-}
-
-static int wl1251_build_qos_null_data(struct wl1251 *wl)
-{
-	struct ieee80211_qos_hdr template;
-
-	memset(&template, 0, sizeof(template));
-
-	memcpy(template.addr1, wl->bssid, ETH_ALEN);
-	memcpy(template.addr2, wl->mac_addr, ETH_ALEN);
-	memcpy(template.addr3, wl->bssid, ETH_ALEN);
-
-	template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
-					     IEEE80211_STYPE_QOS_NULLFUNC |
-					     IEEE80211_FCTL_TODS);
-
-	/* FIXME: not sure what priority to use here */
-	template.qos_ctrl = cpu_to_le16(0);
-
-	return wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, &template,
-				       sizeof(template));
-}
-
-static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct wl1251 *wl = hw->priv;
-	struct ieee80211_conf *conf = &hw->conf;
-	int channel, ret = 0;
-
-	channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
-
-	wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
-		     channel,
-		     conf->flags & IEEE80211_CONF_PS ? "on" : "off",
-		     conf->power_level);
-
-	mutex_lock(&wl->mutex);
-
-	ret = wl1251_ps_elp_wakeup(wl);
-	if (ret < 0)
-		goto out;
-
-	if (channel != wl->channel) {
-		wl->channel = channel;
-
-		ret = wl1251_join(wl, wl->bss_type, wl->channel,
-				  wl->beacon_int, wl->dtim_period);
-		if (ret < 0)
-			goto out_sleep;
-	}
-
-	if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
-		wl1251_debug(DEBUG_PSM, "psm enabled");
-
-		wl->psm_requested = true;
-
-		wl->dtim_period = conf->ps_dtim_period;
-
-		ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int,
-						  wl->dtim_period);
-
-		/*
-		 * mac80211 enables PSM only if we're already associated.
-		 */
-		ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
-		if (ret < 0)
-			goto out_sleep;
-	} else if (!(conf->flags & IEEE80211_CONF_PS) &&
-		   wl->psm_requested) {
-		wl1251_debug(DEBUG_PSM, "psm disabled");
-
-		wl->psm_requested = false;
-
-		if (wl->psm) {
-			ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
-			if (ret < 0)
-				goto out_sleep;
-		}
-	}
-
-	if (conf->power_level != wl->power_level) {
-		ret = wl1251_acx_tx_power(wl, conf->power_level);
-		if (ret < 0)
-			goto out_sleep;
-
-		wl->power_level = conf->power_level;
-	}
-
-out_sleep:
-	wl1251_ps_elp_sleep(wl);
-
-out:
-	mutex_unlock(&wl->mutex);
-
-	return ret;
-}
-
-#define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
-				  FIF_ALLMULTI | \
-				  FIF_FCSFAIL | \
-				  FIF_BCN_PRBRESP_PROMISC | \
-				  FIF_CONTROL | \
-				  FIF_OTHER_BSS)
-
-static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
-				       unsigned int changed,
-				       unsigned int *total,u64 multicast)
-{
-	struct wl1251 *wl = hw->priv;
-
-	wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter");
-
-	*total &= WL1251_SUPPORTED_FILTERS;
-	changed &= WL1251_SUPPORTED_FILTERS;
-
-	if (changed == 0)
-		/* no filters which we support changed */
-		return;
-
-	/* FIXME: wl->rx_config and wl->rx_filter are not protected */
-
-	wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
-	wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
-
-	if (*total & FIF_PROMISC_IN_BSS) {
-		wl->rx_config |= CFG_BSSID_FILTER_EN;
-		wl->rx_config |= CFG_RX_ALL_GOOD;
-	}
-	if (*total & FIF_ALLMULTI)
-		/*
-		 * CFG_MC_FILTER_EN in rx_config needs to be 0 to receive
-		 * all multicast frames
-		 */
-		wl->rx_config &= ~CFG_MC_FILTER_EN;
-	if (*total & FIF_FCSFAIL)
-		wl->rx_filter |= CFG_RX_FCS_ERROR;
-	if (*total & FIF_BCN_PRBRESP_PROMISC) {
-		wl->rx_config &= ~CFG_BSSID_FILTER_EN;
-		wl->rx_config &= ~CFG_SSID_FILTER_EN;
-	}
-	if (*total & FIF_CONTROL)
-		wl->rx_filter |= CFG_RX_CTL_EN;
-	if (*total & FIF_OTHER_BSS)
-		wl->rx_filter &= ~CFG_BSSID_FILTER_EN;
-
-	/*
-	 * FIXME: workqueues need to be properly cancelled on stop(), for
-	 * now let's just disable changing the filter settings. They will
-	 * be updated any on config().
-	 */
-	/* schedule_work(&wl->filter_work); */
-}
-
-/* HW encryption */
-static int wl1251_set_key_type(struct wl1251 *wl,
-			       struct wl1251_cmd_set_keys *key,
-			       enum set_key_cmd cmd,
-			       struct ieee80211_key_conf *mac80211_key,
-			       const u8 *addr)
-{
-	switch (mac80211_key->alg) {
-	case ALG_WEP:
-		if (is_broadcast_ether_addr(addr))
-			key->key_type = KEY_WEP_DEFAULT;
-		else
-			key->key_type = KEY_WEP_ADDR;
-
-		mac80211_key->hw_key_idx = mac80211_key->keyidx;
-		break;
-	case ALG_TKIP:
-		if (is_broadcast_ether_addr(addr))
-			key->key_type = KEY_TKIP_MIC_GROUP;
-		else
-			key->key_type = KEY_TKIP_MIC_PAIRWISE;
-
-		mac80211_key->hw_key_idx = mac80211_key->keyidx;
-		break;
-	case ALG_CCMP:
-		if (is_broadcast_ether_addr(addr))
-			key->key_type = KEY_AES_GROUP;
-		else
-			key->key_type = KEY_AES_PAIRWISE;
-		mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-		break;
-	default:
-		wl1251_error("Unknown key algo 0x%x", mac80211_key->alg);
-		return -EOPNOTSUPP;
-	}
-
-	return 0;
-}
-
-static int wl1251_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)
-{
-	struct wl1251 *wl = hw->priv;
-	struct wl1251_cmd_set_keys *wl_cmd;
-	const u8 *addr;
-	int ret;
-
-	static const u8 bcast_addr[ETH_ALEN] =
-		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-	wl1251_debug(DEBUG_MAC80211, "mac80211 set key");
-
-	wl_cmd = kzalloc(sizeof(*wl_cmd), GFP_KERNEL);
-	if (!wl_cmd) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	addr = sta ? sta->addr : bcast_addr;
-
-	wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
-	wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
-	wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
-		     key->alg, key->keyidx, key->keylen, key->flags);
-	wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen);
-
-	if (is_zero_ether_addr(addr)) {
-		/* We dont support TX only encryption */
-		ret = -EOPNOTSUPP;
-		goto out;
-	}
-
-	mutex_lock(&wl->mutex);
-
-	ret = wl1251_ps_elp_wakeup(wl);
-	if (ret < 0)
-		goto out_unlock;
-
-	switch (cmd) {
-	case SET_KEY:
-		wl_cmd->key_action = KEY_ADD_OR_REPLACE;
-		break;
-	case DISABLE_KEY:
-		wl_cmd->key_action = KEY_REMOVE;
-		break;
-	default:
-		wl1251_error("Unsupported key cmd 0x%x", cmd);
-		break;
-	}
-
-	ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr);
-	if (ret < 0) {
-		wl1251_error("Set KEY type failed");
-		goto out_sleep;
-	}
-
-	if (wl_cmd->key_type != KEY_WEP_DEFAULT)
-		memcpy(wl_cmd->addr, addr, ETH_ALEN);
-
-	if ((wl_cmd->key_type == KEY_TKIP_MIC_GROUP) ||
-	    (wl_cmd->key_type == KEY_TKIP_MIC_PAIRWISE)) {
-		/*
-		 * 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(wl_cmd->key, key->key, 16);
-		memcpy(wl_cmd->key + 16, key->key + 24, 8);
-		memcpy(wl_cmd->key + 24, key->key + 16, 8);
-
-	} else {
-		memcpy(wl_cmd->key, key->key, key->keylen);
-	}
-	wl_cmd->key_size = key->keylen;
-
-	wl_cmd->id = key->keyidx;
-	wl_cmd->ssid_profile = 0;
-
-	wl1251_dump(DEBUG_CRYPT, "TARGET KEY: ", wl_cmd, sizeof(*wl_cmd));
-
-	ret = wl1251_cmd_send(wl, CMD_SET_KEYS, wl_cmd, sizeof(*wl_cmd));
-	if (ret < 0) {
-		wl1251_warning("could not set keys");
-		goto out_sleep;
-	}
-
-out_sleep:
-	wl1251_ps_elp_sleep(wl);
-
-out_unlock:
-	mutex_unlock(&wl->mutex);
-
-out:
-	kfree(wl_cmd);
-
-	return ret;
-}
-
-static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
-			     struct ieee80211_vif *vif,
-			     struct cfg80211_scan_request *req)
-{
-	struct wl1251 *wl = hw->priv;
-	struct sk_buff *skb;
-	size_t ssid_len = 0;
-	u8 *ssid = NULL;
-	int ret;
-
-	wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan");
-
-	if (req->n_ssids) {
-		ssid = req->ssids[0].ssid;
-		ssid_len = req->ssids[0].ssid_len;
-	}
-
-	mutex_lock(&wl->mutex);
-
-	if (wl->scanning) {
-		wl1251_debug(DEBUG_SCAN, "scan already in progress");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	ret = wl1251_ps_elp_wakeup(wl);
-	if (ret < 0)
-		goto out;
-
-	skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
-				     req->ie, req->ie_len);
-	if (!skb) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data,
-				      skb->len);
-	dev_kfree_skb(skb);
-	if (ret < 0)
-		goto out_sleep;
-
-	ret = wl1251_cmd_trigger_scan_to(wl, 0);
-	if (ret < 0)
-		goto out_sleep;
-
-	wl->scanning = true;
-
-	ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels,
-			      req->n_channels, WL1251_SCAN_NUM_PROBES);
-	if (ret < 0) {
-		wl->scanning = false;
-		goto out_sleep;
-	}
-
-out_sleep:
-	wl1251_ps_elp_sleep(wl);
-
-out:
-	mutex_unlock(&wl->mutex);
-
-	return ret;
-}
-
-static int wl1251_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
-{
-	struct wl1251 *wl = hw->priv;
-	int ret;
-
-	mutex_lock(&wl->mutex);
-
-	ret = wl1251_ps_elp_wakeup(wl);
-	if (ret < 0)
-		goto out;
-
-	ret = wl1251_acx_rts_threshold(wl, (u16) value);
-	if (ret < 0)
-		wl1251_warning("wl1251_op_set_rts_threshold failed: %d", ret);
-
-	wl1251_ps_elp_sleep(wl);
-
-out:
-	mutex_unlock(&wl->mutex);
-
-	return ret;
-}
-
-static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
-				       struct ieee80211_vif *vif,
-				       struct ieee80211_bss_conf *bss_conf,
-				       u32 changed)
-{
-	struct wl1251 *wl = hw->priv;
-	struct sk_buff *beacon, *skb;
-	int ret;
-
-	wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed");
-
-	mutex_lock(&wl->mutex);
-
-	ret = wl1251_ps_elp_wakeup(wl);
-	if (ret < 0)
-		goto out;
-
-	if (changed & BSS_CHANGED_BSSID) {
-		memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
-
-		skb = ieee80211_nullfunc_get(wl->hw, wl->vif);
-		if (!skb)
-			goto out_sleep;
-
-		ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA,
-					      skb->data, skb->len);
-		dev_kfree_skb(skb);
-		if (ret < 0)
-			goto out_sleep;
-
-		ret = wl1251_build_qos_null_data(wl);
-		if (ret < 0)
-			goto out;
-
-		if (wl->bss_type != BSS_TYPE_IBSS) {
-			ret = wl1251_join(wl, wl->bss_type, wl->channel,
-					  wl->beacon_int, wl->dtim_period);
-			if (ret < 0)
-				goto out_sleep;
-		}
-	}
-
-	if (changed & BSS_CHANGED_ASSOC) {
-		if (bss_conf->assoc) {
-			wl->beacon_int = bss_conf->beacon_int;
-
-			skb = ieee80211_pspoll_get(wl->hw, wl->vif);
-			if (!skb)
-				goto out_sleep;
-
-			ret = wl1251_cmd_template_set(wl, CMD_PS_POLL,
-						      skb->data,
-						      skb->len);
-			dev_kfree_skb(skb);
-			if (ret < 0)
-				goto out_sleep;
-
-			ret = wl1251_acx_aid(wl, bss_conf->aid);
-			if (ret < 0)
-				goto out_sleep;
-		} else {
-			/* use defaults when not associated */
-			wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
-			wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
-		}
-	}
-	if (changed & BSS_CHANGED_ERP_SLOT) {
-		if (bss_conf->use_short_slot)
-			ret = wl1251_acx_slot(wl, SLOT_TIME_SHORT);
-		else
-			ret = wl1251_acx_slot(wl, SLOT_TIME_LONG);
-		if (ret < 0) {
-			wl1251_warning("Set slot time failed %d", ret);
-			goto out_sleep;
-		}
-	}
-
-	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		if (bss_conf->use_short_preamble)
-			wl1251_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
-		else
-			wl1251_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
-	}
-
-	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		if (bss_conf->use_cts_prot)
-			ret = wl1251_acx_cts_protect(wl, CTSPROTECT_ENABLE);
-		else
-			ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE);
-		if (ret < 0) {
-			wl1251_warning("Set ctsprotect failed %d", ret);
-			goto out_sleep;
-		}
-	}
-
-	if (changed & BSS_CHANGED_BEACON) {
-		beacon = ieee80211_beacon_get(hw, vif);
-		ret = wl1251_cmd_template_set(wl, CMD_BEACON, beacon->data,
-					      beacon->len);
-
-		if (ret < 0) {
-			dev_kfree_skb(beacon);
-			goto out_sleep;
-		}
-
-		ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data,
-					      beacon->len);
-
-		dev_kfree_skb(beacon);
-
-		if (ret < 0)
-			goto out_sleep;
-
-		ret = wl1251_join(wl, wl->bss_type, wl->beacon_int,
-				  wl->channel, wl->dtim_period);
-
-		if (ret < 0)
-			goto out_sleep;
-	}
-
-out_sleep:
-	wl1251_ps_elp_sleep(wl);
-
-out:
-	mutex_unlock(&wl->mutex);
-}
-
-
-/* can't be const, mac80211 writes to this */
-static struct ieee80211_rate wl1251_rates[] = {
-	{ .bitrate = 10,
-	  .hw_value = 0x1,
-	  .hw_value_short = 0x1, },
-	{ .bitrate = 20,
-	  .hw_value = 0x2,
-	  .hw_value_short = 0x2,
-	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-	{ .bitrate = 55,
-	  .hw_value = 0x4,
-	  .hw_value_short = 0x4,
-	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-	{ .bitrate = 110,
-	  .hw_value = 0x20,
-	  .hw_value_short = 0x20,
-	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-	{ .bitrate = 60,
-	  .hw_value = 0x8,
-	  .hw_value_short = 0x8, },
-	{ .bitrate = 90,
-	  .hw_value = 0x10,
-	  .hw_value_short = 0x10, },
-	{ .bitrate = 120,
-	  .hw_value = 0x40,
-	  .hw_value_short = 0x40, },
-	{ .bitrate = 180,
-	  .hw_value = 0x80,
-	  .hw_value_short = 0x80, },
-	{ .bitrate = 240,
-	  .hw_value = 0x200,
-	  .hw_value_short = 0x200, },
-	{ .bitrate = 360,
-	 .hw_value = 0x400,
-	 .hw_value_short = 0x400, },
-	{ .bitrate = 480,
-	  .hw_value = 0x800,
-	  .hw_value_short = 0x800, },
-	{ .bitrate = 540,
-	  .hw_value = 0x1000,
-	  .hw_value_short = 0x1000, },
-};
-
-/* can't be const, mac80211 writes to this */
-static struct ieee80211_channel wl1251_channels[] = {
-	{ .hw_value = 1, .center_freq = 2412},
-	{ .hw_value = 2, .center_freq = 2417},
-	{ .hw_value = 3, .center_freq = 2422},
-	{ .hw_value = 4, .center_freq = 2427},
-	{ .hw_value = 5, .center_freq = 2432},
-	{ .hw_value = 6, .center_freq = 2437},
-	{ .hw_value = 7, .center_freq = 2442},
-	{ .hw_value = 8, .center_freq = 2447},
-	{ .hw_value = 9, .center_freq = 2452},
-	{ .hw_value = 10, .center_freq = 2457},
-	{ .hw_value = 11, .center_freq = 2462},
-	{ .hw_value = 12, .center_freq = 2467},
-	{ .hw_value = 13, .center_freq = 2472},
-};
-
-static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
-			     const struct ieee80211_tx_queue_params *params)
-{
-	enum wl1251_acx_ps_scheme ps_scheme;
-	struct wl1251 *wl = hw->priv;
-	int ret;
-
-	mutex_lock(&wl->mutex);
-
-	wl1251_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue);
-
-	ret = wl1251_ps_elp_wakeup(wl);
-	if (ret < 0)
-		goto out;
-
-	/* mac80211 uses units of 32 usec */
-	ret = wl1251_acx_ac_cfg(wl, wl1251_tx_get_queue(queue),
-				params->cw_min, params->cw_max,
-				params->aifs, params->txop * 32);
-	if (ret < 0)
-		goto out_sleep;
-
-	if (params->uapsd)
-		ps_scheme = WL1251_ACX_PS_SCHEME_UPSD_TRIGGER;
-	else
-		ps_scheme = WL1251_ACX_PS_SCHEME_LEGACY;
-
-	ret = wl1251_acx_tid_cfg(wl, wl1251_tx_get_queue(queue),
-				 CHANNEL_TYPE_EDCF,
-				 wl1251_tx_get_queue(queue), ps_scheme,
-				 WL1251_ACX_ACK_POLICY_LEGACY);
-	if (ret < 0)
-		goto out_sleep;
-
-out_sleep:
-	wl1251_ps_elp_sleep(wl);
-
-out:
-	mutex_unlock(&wl->mutex);
-
-	return ret;
-}
-
-static int wl1251_op_get_survey(struct ieee80211_hw *hw, int idx,
-				struct survey_info *survey)
-{
-	struct wl1251 *wl = hw->priv;
-	struct ieee80211_conf *conf = &hw->conf;
- 
-	if (idx != 0)
-		return -ENOENT;
- 
-	survey->channel = conf->channel;
-	survey->filled = SURVEY_INFO_NOISE_DBM;
-	survey->noise = wl->noise;
- 
-	return 0;
-}
-
-/* can't be const, mac80211 writes to this */
-static struct ieee80211_supported_band wl1251_band_2ghz = {
-	.channels = wl1251_channels,
-	.n_channels = ARRAY_SIZE(wl1251_channels),
-	.bitrates = wl1251_rates,
-	.n_bitrates = ARRAY_SIZE(wl1251_rates),
-};
-
-static const struct ieee80211_ops wl1251_ops = {
-	.start = wl1251_op_start,
-	.stop = wl1251_op_stop,
-	.add_interface = wl1251_op_add_interface,
-	.remove_interface = wl1251_op_remove_interface,
-	.config = wl1251_op_config,
-	.configure_filter = wl1251_op_configure_filter,
-	.tx = wl1251_op_tx,
-	.set_key = wl1251_op_set_key,
-	.hw_scan = wl1251_op_hw_scan,
-	.bss_info_changed = wl1251_op_bss_info_changed,
-	.set_rts_threshold = wl1251_op_set_rts_threshold,
-	.conf_tx = wl1251_op_conf_tx,
-	.get_survey = wl1251_op_get_survey,
-};
-
-static int wl1251_read_eeprom_byte(struct wl1251 *wl, off_t offset, u8 *data)
-{
-	unsigned long timeout;
-
-	wl1251_reg_write32(wl, EE_ADDR, offset);
-	wl1251_reg_write32(wl, EE_CTL, EE_CTL_READ);
-
-	/* EE_CTL_READ clears when data is ready */
-	timeout = jiffies + msecs_to_jiffies(100);
-	while (1) {
-		if (!(wl1251_reg_read32(wl, EE_CTL) & EE_CTL_READ))
-			break;
-
-		if (time_after(jiffies, timeout))
-			return -ETIMEDOUT;
-
-		msleep(1);
-	}
-
-	*data = wl1251_reg_read32(wl, EE_DATA);
-	return 0;
-}
-
-static int wl1251_read_eeprom(struct wl1251 *wl, off_t offset,
-			      u8 *data, size_t len)
-{
-	size_t i;
-	int ret;
-
-	wl1251_reg_write32(wl, EE_START, 0);
-
-	for (i = 0; i < len; i++) {
-		ret = wl1251_read_eeprom_byte(wl, offset + i, &data[i]);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int wl1251_read_eeprom_mac(struct wl1251 *wl)
-{
-	u8 mac[ETH_ALEN];
-	int i, ret;
-
-	wl1251_set_partition(wl, 0, 0, REGISTERS_BASE, REGISTERS_DOWN_SIZE);
-
-	ret = wl1251_read_eeprom(wl, 0x1c, mac, sizeof(mac));
-	if (ret < 0) {
-		wl1251_warning("failed to read MAC address from EEPROM");
-		return ret;
-	}
-
-	/* MAC is stored in reverse order */
-	for (i = 0; i < ETH_ALEN; i++)
-		wl->mac_addr[i] = mac[ETH_ALEN - i - 1];
-
-	return 0;
-}
-
-static int wl1251_register_hw(struct wl1251 *wl)
-{
-	int ret;
-
-	if (wl->mac80211_registered)
-		return 0;
-
-	SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
-
-	ret = ieee80211_register_hw(wl->hw);
-	if (ret < 0) {
-		wl1251_error("unable to register mac80211 hw: %d", ret);
-		return ret;
-	}
-
-	wl->mac80211_registered = true;
-
-	wl1251_notice("loaded");
-
-	return 0;
-}
-
-int wl1251_init_ieee80211(struct wl1251 *wl)
-{
-	int ret;
-
-	/* The tx descriptor buffer and the TKIP space */
-	wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc)
-		+ WL1251_TKIP_IV_SPACE;
-
-	/* unit us */
-	/* FIXME: find a proper value */
-	wl->hw->channel_change_time = 10000;
-
-	wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
-		IEEE80211_HW_SUPPORTS_PS |
-		IEEE80211_HW_BEACON_FILTER |
-		IEEE80211_HW_SUPPORTS_UAPSD;
-
-	wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
-	wl->hw->wiphy->max_scan_ssids = 1;
-	wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz;
-
-	wl->hw->queues = 4;
-
-	if (wl->use_eeprom)
-		wl1251_read_eeprom_mac(wl);
-
-	ret = wl1251_register_hw(wl);
-	if (ret)
-		goto out;
-
-	wl1251_debugfs_init(wl);
-	wl1251_notice("initialized");
-
-	ret = 0;
-
-out:
-	return ret;
-}
-EXPORT_SYMBOL_GPL(wl1251_init_ieee80211);
-
-struct ieee80211_hw *wl1251_alloc_hw(void)
-{
-	struct ieee80211_hw *hw;
-	struct wl1251 *wl;
-	int i;
-	static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
-
-	hw = ieee80211_alloc_hw(sizeof(*wl), &wl1251_ops);
-	if (!hw) {
-		wl1251_error("could not alloc ieee80211_hw");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	wl = hw->priv;
-	memset(wl, 0, sizeof(*wl));
-
-	wl->hw = hw;
-
-	wl->data_in_count = 0;
-
-	skb_queue_head_init(&wl->tx_queue);
-
-	INIT_WORK(&wl->filter_work, wl1251_filter_work);
-	INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work);
-	wl->channel = WL1251_DEFAULT_CHANNEL;
-	wl->scanning = false;
-	wl->default_key = 0;
-	wl->listen_int = 1;
-	wl->rx_counter = 0;
-	wl->rx_handled = 0;
-	wl->rx_current_buffer = 0;
-	wl->rx_last_id = 0;
-	wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
-	wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
-	wl->elp = false;
-	wl->psm = 0;
-	wl->psm_requested = false;
-	wl->tx_queue_stopped = false;
-	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
-	wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
-	wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
-	wl->vif = NULL;
-
-	for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
-		wl->tx_frames[i] = NULL;
-
-	wl->next_tx_complete = 0;
-
-	INIT_WORK(&wl->irq_work, wl1251_irq_work);
-	INIT_WORK(&wl->tx_work, wl1251_tx_work);
-
-	/*
-	 * In case our MAC address is not correctly set,
-	 * we use a random but Nokia MAC.
-	 */
-	memcpy(wl->mac_addr, nokia_oui, 3);
-	get_random_bytes(wl->mac_addr + 3, 3);
-
-	wl->state = WL1251_STATE_OFF;
-	mutex_init(&wl->mutex);
-
-	wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE;
-	wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE;
-
-	wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL);
-	if (!wl->rx_descriptor) {
-		wl1251_error("could not allocate memory for rx descriptor");
-		ieee80211_free_hw(hw);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	return hw;
-}
-EXPORT_SYMBOL_GPL(wl1251_alloc_hw);
-
-int wl1251_free_hw(struct wl1251 *wl)
-{
-	ieee80211_unregister_hw(wl->hw);
-
-	wl1251_debugfs_exit(wl);
-
-	kfree(wl->target_mem_map);
-	kfree(wl->data_path);
-	vfree(wl->fw);
-	wl->fw = NULL;
-	kfree(wl->nvs);
-	wl->nvs = NULL;
-
-	kfree(wl->rx_descriptor);
-	wl->rx_descriptor = NULL;
-
-	ieee80211_free_hw(wl->hw);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(wl1251_free_hw);
-
-MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
-MODULE_FIRMWARE(WL1251_FW_NAME);
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c
deleted file mode 100644
index b55cb2b..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_ps.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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 "wl1251_reg.h"
-#include "wl1251_ps.h"
-#include "wl1251_cmd.h"
-#include "wl1251_io.h"
-
-/* in ms */
-#define WL1251_WAKEUP_TIMEOUT 100
-
-void wl1251_elp_work(struct work_struct *work)
-{
-	struct delayed_work *dwork;
-	struct wl1251 *wl;
-
-	dwork = container_of(work, struct delayed_work, work);
-	wl = container_of(dwork, struct wl1251, elp_work);
-
-	wl1251_debug(DEBUG_PSM, "elp work");
-
-	mutex_lock(&wl->mutex);
-
-	if (wl->elp || !wl->psm)
-		goto out;
-
-	wl1251_debug(DEBUG_PSM, "chip to elp");
-	wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
-	wl->elp = true;
-
-out:
-	mutex_unlock(&wl->mutex);
-}
-
-#define ELP_ENTRY_DELAY  5
-
-/* Routines to toggle sleep mode while in ELP */
-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);
-	}
-}
-
-int wl1251_ps_elp_wakeup(struct wl1251 *wl)
-{
-	unsigned long timeout, start;
-	u32 elp_reg;
-
-	if (!wl->elp)
-		return 0;
-
-	wl1251_debug(DEBUG_PSM, "waking up chip from elp");
-
-	start = jiffies;
-	timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT);
-
-	wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
-
-	elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
-
-	/*
-	 * FIXME: we should wait for irq from chip but, as a temporary
-	 * solution to simplify locking, let's poll instead
-	 */
-	while (!(elp_reg & ELPCTRL_WLAN_READY)) {
-		if (time_after(jiffies, timeout)) {
-			wl1251_error("elp wakeup timeout");
-			return -ETIMEDOUT;
-		}
-		msleep(1);
-		elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
-	}
-
-	wl1251_debug(DEBUG_PSM, "wakeup time: %u ms",
-		     jiffies_to_msecs(jiffies - start));
-
-	wl->elp = false;
-
-	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;
-
-	switch (mode) {
-	case STATION_POWER_SAVE_MODE:
-		wl1251_debug(DEBUG_PSM, "entering psm");
-
-		/* enable beacon filtering */
-		ret = wl1251_acx_beacon_filter_opt(wl, true);
-		if (ret < 0)
-			return ret;
-
-		ret = wl1251_acx_wake_up_conditions(wl,
-						    WAKE_UP_EVENT_DTIM_BITMAP,
-						    wl->listen_int);
-		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);
-		if (ret < 0)
-			return ret;
-
-		wl->psm = 1;
-		break;
-	case STATION_ACTIVE_MODE:
-	default:
-		wl1251_debug(DEBUG_PSM, "leaving psm");
-		ret = wl1251_ps_set_elp(wl, false);
-		if (ret < 0)
-			return ret;
-
-		/* disable beacon filtering */
-		ret = wl1251_acx_beacon_filter_opt(wl, false);
-		if (ret < 0)
-			return ret;
-
-		ret = wl1251_acx_wake_up_conditions(wl,
-						    WAKE_UP_EVENT_DTIM_BITMAP,
-						    wl->listen_int);
-		if (ret < 0)
-			return ret;
-
-		ret = wl1251_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
-		if (ret < 0)
-			return ret;
-
-		wl->psm = 0;
-		break;
-	}
-
-	return ret;
-}
-
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.h b/drivers/net/wireless/wl12xx/wl1251_ps.h
deleted file mode 100644
index c688ac5..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_ps.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef __WL1251_PS_H__
-#define __WL1251_PS_H__
-
-/*
- * This file is part of wl1251
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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 "wl1251.h"
-#include "wl1251_acx.h"
-
-int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode);
-void wl1251_ps_elp_sleep(struct wl1251 *wl);
-int wl1251_ps_elp_wakeup(struct wl1251 *wl);
-void wl1251_elp_work(struct work_struct *work);
-
-
-#endif /* __WL1251_PS_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h
deleted file mode 100644
index d16edd9..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_reg.h
+++ /dev/null
@@ -1,657 +0,0 @@
-/*
- * This file is part of wl12xx
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef __REG_H__
-#define __REG_H__
-
-#include <linux/bitops.h>
-
-#define REGISTERS_BASE 0x00300000
-#define DRPW_BASE      0x00310000
-
-#define REGISTERS_DOWN_SIZE 0x00008800
-#define REGISTERS_WORK_SIZE 0x0000b000
-
-#define HW_ACCESS_ELP_CTRL_REG_ADDR         0x1FFFC
-
-/* ELP register commands */
-#define ELPCTRL_WAKE_UP             0x1
-#define ELPCTRL_WAKE_UP_WLAN_READY  0x5
-#define ELPCTRL_SLEEP               0x0
-/* ELP WLAN_READY bit */
-#define ELPCTRL_WLAN_READY          0x2
-
-/* Device Configuration registers*/
-#define SOR_CFG                        (REGISTERS_BASE + 0x0800)
-#define ECPU_CTRL                      (REGISTERS_BASE + 0x0804)
-#define HI_CFG                         (REGISTERS_BASE + 0x0808)
-
-/* EEPROM registers */
-#define EE_START                       (REGISTERS_BASE + 0x080C)
-#define EE_CTL                         (REGISTERS_BASE + 0x2000)
-#define EE_DATA                        (REGISTERS_BASE + 0x2004)
-#define EE_ADDR                        (REGISTERS_BASE + 0x2008)
-
-#define EE_CTL_READ                   2
-
-#define CHIP_ID_B                      (REGISTERS_BASE + 0x5674)
-
-#define CHIP_ID_1251_PG10	           (0x7010101)
-#define CHIP_ID_1251_PG11	           (0x7020101)
-#define CHIP_ID_1251_PG12	           (0x7030101)
-
-#define ENABLE                         (REGISTERS_BASE + 0x5450)
-
-/* Power Management registers */
-#define ELP_CFG_MODE                   (REGISTERS_BASE + 0x5804)
-#define ELP_CMD                        (REGISTERS_BASE + 0x5808)
-#define PLL_CAL_TIME                   (REGISTERS_BASE + 0x5810)
-#define CLK_REQ_TIME                   (REGISTERS_BASE + 0x5814)
-#define CLK_BUF_TIME                   (REGISTERS_BASE + 0x5818)
-
-#define CFG_PLL_SYNC_CNT               (REGISTERS_BASE + 0x5820)
-
-/* Scratch Pad registers*/
-#define SCR_PAD0                       (REGISTERS_BASE + 0x5608)
-#define SCR_PAD1                       (REGISTERS_BASE + 0x560C)
-#define SCR_PAD2                       (REGISTERS_BASE + 0x5610)
-#define SCR_PAD3                       (REGISTERS_BASE + 0x5614)
-#define SCR_PAD4                       (REGISTERS_BASE + 0x5618)
-#define SCR_PAD4_SET                   (REGISTERS_BASE + 0x561C)
-#define SCR_PAD4_CLR                   (REGISTERS_BASE + 0x5620)
-#define SCR_PAD5                       (REGISTERS_BASE + 0x5624)
-#define SCR_PAD5_SET                   (REGISTERS_BASE + 0x5628)
-#define SCR_PAD5_CLR                   (REGISTERS_BASE + 0x562C)
-#define SCR_PAD6                       (REGISTERS_BASE + 0x5630)
-#define SCR_PAD7                       (REGISTERS_BASE + 0x5634)
-#define SCR_PAD8                       (REGISTERS_BASE + 0x5638)
-#define SCR_PAD9                       (REGISTERS_BASE + 0x563C)
-
-/* Spare registers*/
-#define SPARE_A1                       (REGISTERS_BASE + 0x0994)
-#define SPARE_A2                       (REGISTERS_BASE + 0x0998)
-#define SPARE_A3                       (REGISTERS_BASE + 0x099C)
-#define SPARE_A4                       (REGISTERS_BASE + 0x09A0)
-#define SPARE_A5                       (REGISTERS_BASE + 0x09A4)
-#define SPARE_A6                       (REGISTERS_BASE + 0x09A8)
-#define SPARE_A7                       (REGISTERS_BASE + 0x09AC)
-#define SPARE_A8                       (REGISTERS_BASE + 0x09B0)
-#define SPARE_B1                       (REGISTERS_BASE + 0x5420)
-#define SPARE_B2                       (REGISTERS_BASE + 0x5424)
-#define SPARE_B3                       (REGISTERS_BASE + 0x5428)
-#define SPARE_B4                       (REGISTERS_BASE + 0x542C)
-#define SPARE_B5                       (REGISTERS_BASE + 0x5430)
-#define SPARE_B6                       (REGISTERS_BASE + 0x5434)
-#define SPARE_B7                       (REGISTERS_BASE + 0x5438)
-#define SPARE_B8                       (REGISTERS_BASE + 0x543C)
-
-enum wl12xx_acx_int_reg {
-	ACX_REG_INTERRUPT_TRIG,
-	ACX_REG_INTERRUPT_TRIG_H,
-
-/*=============================================
-  Host Interrupt Mask Register - 32bit (RW)
-  ------------------------------------------
-  Setting a bit in this register masks the
-  corresponding interrupt to the host.
-  0 - RX0		- Rx first dubble buffer Data Interrupt
-  1 - TXD		- Tx Data Interrupt
-  2 - TXXFR		- Tx Transfer Interrupt
-  3 - RX1		- Rx second dubble buffer Data Interrupt
-  4 - RXXFR		- Rx Transfer Interrupt
-  5 - EVENT_A	- Event Mailbox interrupt
-  6 - EVENT_B	- Event Mailbox interrupt
-  7 - WNONHST	- Wake On Host Interrupt
-  8 - TRACE_A	- Debug Trace interrupt
-  9 - TRACE_B	- Debug Trace interrupt
- 10 - CDCMP		- Command Complete Interrupt
- 11 -
- 12 -
- 13 -
- 14 - ICOMP		- Initialization Complete Interrupt
- 16 - SG SE		- Soft Gemini - Sense enable interrupt
- 17 - SG SD		- Soft Gemini - Sense disable interrupt
- 18 -			-
- 19 -			-
- 20 -			-
- 21-			-
- Default: 0x0001
-*==============================================*/
-	ACX_REG_INTERRUPT_MASK,
-
-/*=============================================
-  Host Interrupt Mask Set 16bit, (Write only)
-  ------------------------------------------
- Setting a bit in this register sets
- the corresponding bin in ACX_HINT_MASK register
- without effecting the mask
- state of other bits (0 = no effect).
-==============================================*/
-	ACX_REG_HINT_MASK_SET,
-
-/*=============================================
-  Host Interrupt Mask Clear 16bit,(Write only)
-  ------------------------------------------
- Setting a bit in this register clears
- the corresponding bin in ACX_HINT_MASK register
- without effecting the mask
- state of other bits (0 = no effect).
-=============================================*/
-	ACX_REG_HINT_MASK_CLR,
-
-/*=============================================
-  Host Interrupt Status Nondestructive Read
-  16bit,(Read only)
-  ------------------------------------------
- The host can read this register to determine
- which interrupts are active.
- Reading this register doesn't
- effect its content.
-=============================================*/
-	ACX_REG_INTERRUPT_NO_CLEAR,
-
-/*=============================================
-  Host Interrupt Status Clear on Read  Register
-  16bit,(Read only)
-  ------------------------------------------
- The host can read this register to determine
- which interrupts are active.
- Reading this register clears it,
- thus making all interrupts inactive.
-==============================================*/
-	ACX_REG_INTERRUPT_CLEAR,
-
-/*=============================================
-  Host Interrupt Acknowledge Register
-  16bit,(Write only)
-  ------------------------------------------
- The host can set individual bits in this
- register to clear (acknowledge) the corresp.
- interrupt status bits in the HINT_STS_CLR and
- HINT_STS_ND registers, thus making the
- assotiated interrupt inactive. (0-no effect)
-==============================================*/
-	ACX_REG_INTERRUPT_ACK,
-
-/*===============================================
-   Host Software Reset - 32bit RW
- ------------------------------------------
-    [31:1] Reserved
-    0  SOFT_RESET Soft Reset  - When this bit is set,
-    it holds the Wlan hardware in a soft reset state.
-    This reset disables all MAC and baseband processor
-    clocks except the CardBus/PCI interface clock.
-    It also initializes all MAC state machines except
-    the host interface. It does not reload the
-    contents of the EEPROM. When this bit is cleared
-    (not self-clearing), the Wlan hardware
-    exits the software reset state.
-===============================================*/
-	ACX_REG_SLV_SOFT_RESET,
-
-/*===============================================
- EEPROM Burst Read Start  - 32bit RW
- ------------------------------------------
- [31:1] Reserved
- 0  ACX_EE_START -  EEPROM Burst Read Start 0
- Setting this bit starts a burst read from
- the external EEPROM.
- If this bit is set (after reset) before an EEPROM read/write,
- the burst read starts at EEPROM address 0.
- Otherwise, it starts at the address
- following the address of the previous access.
- TheWlan hardware hardware clears this bit automatically.
-
- Default: 0x00000000
-*================================================*/
-	ACX_REG_EE_START,
-
-/* Embedded ARM CPU Control */
-
-/*===============================================
- Halt eCPU   - 32bit RW
- ------------------------------------------
- 0 HALT_ECPU Halt Embedded CPU - This bit is the
- compliment of bit 1 (MDATA2) in the SOR_CFG register.
- During a hardware reset, this bit holds
- the inverse of MDATA2.
- When downloading firmware from the host,
- set this bit (pull down MDATA2).
- The host clears this bit after downloading the firmware into
- zero-wait-state SSRAM.
- When loading firmware from Flash, clear this bit (pull up MDATA2)
- so that the eCPU can run the bootloader code in Flash
- HALT_ECPU eCPU State
- --------------------
- 1 halt eCPU
- 0 enable eCPU
- ===============================================*/
-	ACX_REG_ECPU_CONTROL,
-
-	ACX_REG_TABLE_LEN
-};
-
-#define ACX_SLV_SOFT_RESET_BIT   BIT(0)
-#define ACX_REG_EEPROM_START_BIT BIT(0)
-
-/* Command/Information Mailbox Pointers */
-
-/*===============================================
-  Command Mailbox Pointer - 32bit RW
- ------------------------------------------
- This register holds the start address of
- the command mailbox located in the Wlan hardware memory.
- The host must read this pointer after a reset to
- find the location of the command mailbox.
- The Wlan hardware initializes the command mailbox
- pointer with the default address of the command mailbox.
- The command mailbox pointer is not valid until after
- the host receives the Init Complete interrupt from
- the Wlan hardware.
- ===============================================*/
-#define REG_COMMAND_MAILBOX_PTR				(SCR_PAD0)
-
-/*===============================================
-  Information Mailbox Pointer - 32bit RW
- ------------------------------------------
- This register holds the start address of
- the information mailbox located in the Wlan hardware memory.
- The host must read this pointer after a reset to find
- the location of the information mailbox.
- The Wlan hardware initializes the information mailbox pointer
- with the default address of the information mailbox.
- The information mailbox pointer is not valid
- until after the host receives the Init Complete interrupt from
- the Wlan hardware.
- ===============================================*/
-#define REG_EVENT_MAILBOX_PTR				(SCR_PAD1)
-
-
-/* Misc */
-
-#define REG_ENABLE_TX_RX				(ENABLE)
-/*
- * Rx configuration (filter) information element
- * ---------------------------------------------
- */
-#define REG_RX_CONFIG				(RX_CFG)
-#define REG_RX_FILTER				(RX_FILTER_CFG)
-
-
-#define RX_CFG_ENABLE_PHY_HEADER_PLCP	 0x0002
-
-/* promiscuous - receives all valid frames */
-#define RX_CFG_PROMISCUOUS		 0x0008
-
-/* receives frames from any BSSID */
-#define RX_CFG_BSSID			 0x0020
-
-/* receives frames destined to any MAC address */
-#define RX_CFG_MAC			 0x0010
-
-#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC	 0x0010
-#define RX_CFG_ENABLE_ANY_DEST_MAC	 0x0000
-#define RX_CFG_ENABLE_ONLY_MY_BSSID	 0x0020
-#define RX_CFG_ENABLE_ANY_BSSID		 0x0000
-
-/* discards all broadcast frames */
-#define RX_CFG_DISABLE_BCAST		 0x0200
-
-#define RX_CFG_ENABLE_ONLY_MY_SSID	 0x0400
-#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800
-#define RX_CFG_COPY_RX_STATUS		 0x2000
-#define RX_CFG_TSF			 0x10000
-
-#define RX_CONFIG_OPTION_ANY_DST_MY_BSS	 (RX_CFG_ENABLE_ANY_DEST_MAC | \
-					  RX_CFG_ENABLE_ONLY_MY_BSSID)
-
-#define RX_CONFIG_OPTION_MY_DST_ANY_BSS	 (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
-					  | RX_CFG_ENABLE_ANY_BSSID)
-
-#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
-					  RX_CFG_ENABLE_ANY_BSSID)
-
-#define RX_CONFIG_OPTION_MY_DST_MY_BSS	 (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
-					  | RX_CFG_ENABLE_ONLY_MY_BSSID)
-
-#define RX_CONFIG_OPTION_FOR_SCAN  (RX_CFG_ENABLE_PHY_HEADER_PLCP \
-				    | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \
-				    | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF)
-
-#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC)
-
-#define RX_CONFIG_OPTION_FOR_JOIN	 (RX_CFG_ENABLE_ONLY_MY_BSSID | \
-					  RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
-
-#define RX_CONFIG_OPTION_FOR_IBSS_JOIN   (RX_CFG_ENABLE_ONLY_MY_SSID | \
-					  RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
-
-#define RX_FILTER_OPTION_DEF	      (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 RX_FILTER_OPTION_FILTER_ALL	 0
-
-#define RX_FILTER_OPTION_DEF_PRSP_BCN  (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\
-					| CFG_RX_RCTS_ACK | CFG_RX_BCN_EN)
-
-#define RX_FILTER_OPTION_JOIN	     (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
-				      | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\
-				      | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\
-				      | CFG_RX_PRSP_EN)
-
-
-/*===============================================
- EEPROM Read/Write Request 32bit RW
- ------------------------------------------
- 1 EE_READ - EEPROM Read Request 1 - Setting this bit
- loads a single byte of data into the EE_DATA
- register from the EEPROM location specified in
- the EE_ADDR register.
- The Wlan hardware hardware clears this bit automatically.
- EE_DATA is valid when this bit is cleared.
-
- 0 EE_WRITE  - EEPROM Write Request  - Setting this bit
- writes a single byte of data from the EE_DATA register into the
- EEPROM location specified in the EE_ADDR register.
- The Wlan hardware hardware clears this bit automatically.
-*===============================================*/
-#define EE_CTL                              (REGISTERS_BASE + 0x2000)
-#define ACX_EE_CTL_REG                      EE_CTL
-#define EE_WRITE                            0x00000001ul
-#define EE_READ                             0x00000002ul
-
-/*===============================================
-  EEPROM Address  - 32bit RW
-  ------------------------------------------
-  This register specifies the address
-  within the EEPROM from/to which to read/write data.
-  ===============================================*/
-#define EE_ADDR                             (REGISTERS_BASE + 0x2008)
-#define ACX_EE_ADDR_REG                     EE_ADDR
-
-/*===============================================
-  EEPROM Data  - 32bit RW
-  ------------------------------------------
-  This register either holds the read 8 bits of
-  data from the EEPROM or the write data
-  to be written to the EEPROM.
-  ===============================================*/
-#define EE_DATA                             (REGISTERS_BASE + 0x2004)
-#define ACX_EE_DATA_REG                     EE_DATA
-
-#define EEPROM_ACCESS_TO                    10000   /* timeout counter */
-#define START_EEPROM_MGR                    0x00000001
-
-/*===============================================
-  EEPROM Base Address  - 32bit RW
-  ------------------------------------------
-  This register holds the upper nine bits
-  [23:15] of the 24-bit Wlan hardware memory
-  address for burst reads from EEPROM accesses.
-  The EEPROM provides the lower 15 bits of this address.
-  The MSB of the address from the EEPROM is ignored.
-  ===============================================*/
-#define ACX_EE_CFG                          EE_CFG
-
-/*===============================================
-  GPIO Output Values  -32bit, RW
-  ------------------------------------------
-  [31:16]  Reserved
-  [15: 0]  Specify the output values (at the output driver inputs) for
-  GPIO[15:0], respectively.
-  ===============================================*/
-#define ACX_GPIO_OUT_REG            GPIO_OUT
-#define ACX_MAX_GPIO_LINES          15
-
-/*===============================================
-  Contention window  -32bit, RW
-  ------------------------------------------
-  [31:26]  Reserved
-  [25:16]  Max (0x3ff)
-  [15:07]  Reserved
-  [06:00]  Current contention window value - default is 0x1F
-  ===============================================*/
-#define ACX_CONT_WIND_CFG_REG    CONT_WIND_CFG
-#define ACX_CONT_WIND_MIN_MASK   0x0000007f
-#define ACX_CONT_WIND_MAX        0x03ff0000
-
-/*===============================================
-  HI_CFG Interface Configuration Register Values
-  ------------------------------------------
-  ===============================================*/
-#define HI_CFG_UART_ENABLE          0x00000004
-#define HI_CFG_RST232_ENABLE        0x00000008
-#define HI_CFG_CLOCK_REQ_SELECT     0x00000010
-#define HI_CFG_HOST_INT_ENABLE      0x00000020
-#define HI_CFG_VLYNQ_OUTPUT_ENABLE  0x00000040
-#define HI_CFG_HOST_INT_ACTIVE_LOW  0x00000080
-#define HI_CFG_UART_TX_OUT_GPIO_15  0x00000100
-#define HI_CFG_UART_TX_OUT_GPIO_14  0x00000200
-#define HI_CFG_UART_TX_OUT_GPIO_7   0x00000400
-
-/*
- * NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile
- *       for platforms using active high interrupt level
- */
-#ifdef USE_ACTIVE_HIGH
-#define HI_CFG_DEF_VAL              \
-	(HI_CFG_UART_ENABLE |        \
-	HI_CFG_RST232_ENABLE |      \
-	HI_CFG_CLOCK_REQ_SELECT |   \
-	HI_CFG_HOST_INT_ENABLE)
-#else
-#define HI_CFG_DEF_VAL              \
-	(HI_CFG_UART_ENABLE |        \
-	HI_CFG_RST232_ENABLE |      \
-	HI_CFG_CLOCK_REQ_SELECT |   \
-	HI_CFG_HOST_INT_ENABLE)
-
-#endif
-
-#define REF_FREQ_19_2                       0
-#define REF_FREQ_26_0                       1
-#define REF_FREQ_38_4                       2
-#define REF_FREQ_40_0                       3
-#define REF_FREQ_33_6                       4
-#define REF_FREQ_NUM                        5
-
-#define LUT_PARAM_INTEGER_DIVIDER           0
-#define LUT_PARAM_FRACTIONAL_DIVIDER        1
-#define LUT_PARAM_ATTN_BB                   2
-#define LUT_PARAM_ALPHA_BB                  3
-#define LUT_PARAM_STOP_TIME_BB              4
-#define LUT_PARAM_BB_PLL_LOOP_FILTER        5
-#define LUT_PARAM_NUM                       6
-
-#define ACX_EEPROMLESS_IND_REG              (SCR_PAD4)
-#define USE_EEPROM                          0
-#define SOFT_RESET_MAX_TIME                 1000000
-#define SOFT_RESET_STALL_TIME               1000
-#define NVS_DATA_BUNDARY_ALIGNMENT          4
-
-
-/* Firmware image load chunk size */
-#define CHUNK_SIZE          512
-
-/* Firmware image header size */
-#define FW_HDR_SIZE 8
-
-#define ECPU_CONTROL_HALT					0x00000101
-
-
-/******************************************************************************
-
-    CHANNELS, BAND & REG DOMAINS definitions
-
-******************************************************************************/
-
-
-enum {
-	RADIO_BAND_2_4GHZ = 0,  /* 2.4 Ghz band */
-	RADIO_BAND_5GHZ = 1,    /* 5 Ghz band */
-	RADIO_BAND_JAPAN_4_9_GHZ = 2,
-	DEFAULT_BAND = RADIO_BAND_2_4GHZ,
-	INVALID_BAND = 0xFE,
-	MAX_RADIO_BANDS = 0xFF
-};
-
-enum {
-	NO_RATE      = 0,
-	RATE_1MBPS   = 0x0A,
-	RATE_2MBPS   = 0x14,
-	RATE_5_5MBPS = 0x37,
-	RATE_6MBPS   = 0x0B,
-	RATE_9MBPS   = 0x0F,
-	RATE_11MBPS  = 0x6E,
-	RATE_12MBPS  = 0x0A,
-	RATE_18MBPS  = 0x0E,
-	RATE_22MBPS  = 0xDC,
-	RATE_24MBPS  = 0x09,
-	RATE_36MBPS  = 0x0D,
-	RATE_48MBPS  = 0x08,
-	RATE_54MBPS  = 0x0C
-};
-
-enum {
-	RATE_INDEX_1MBPS   =  0,
-	RATE_INDEX_2MBPS   =  1,
-	RATE_INDEX_5_5MBPS =  2,
-	RATE_INDEX_6MBPS   =  3,
-	RATE_INDEX_9MBPS   =  4,
-	RATE_INDEX_11MBPS  =  5,
-	RATE_INDEX_12MBPS  =  6,
-	RATE_INDEX_18MBPS  =  7,
-	RATE_INDEX_22MBPS  =  8,
-	RATE_INDEX_24MBPS  =  9,
-	RATE_INDEX_36MBPS  =  10,
-	RATE_INDEX_48MBPS  =  11,
-	RATE_INDEX_54MBPS  =  12,
-	RATE_INDEX_MAX     =  RATE_INDEX_54MBPS,
-	MAX_RATE_INDEX,
-	INVALID_RATE_INDEX = MAX_RATE_INDEX,
-	RATE_INDEX_ENUM_MAX_SIZE = 0x7FFFFFFF
-};
-
-enum {
-	RATE_MASK_1MBPS = 0x1,
-	RATE_MASK_2MBPS = 0x2,
-	RATE_MASK_5_5MBPS = 0x4,
-	RATE_MASK_11MBPS = 0x20,
-};
-
-#define SHORT_PREAMBLE_BIT   BIT(0) /* CCK or Barker depending on the rate */
-#define OFDM_RATE_BIT        BIT(6)
-#define PBCC_RATE_BIT        BIT(7)
-
-enum {
-	CCK_LONG = 0,
-	CCK_SHORT = SHORT_PREAMBLE_BIT,
-	PBCC_LONG = PBCC_RATE_BIT,
-	PBCC_SHORT = PBCC_RATE_BIT | SHORT_PREAMBLE_BIT,
-	OFDM = OFDM_RATE_BIT
-};
-
-/******************************************************************************
-
-Transmit-Descriptor RATE-SET field definitions...
-
-Define a new "Rate-Set" for TX path that incorporates the
-Rate & Modulation info into a single 16-bit field.
-
-TxdRateSet_t:
-b15   - Indicates Preamble type (1=SHORT, 0=LONG).
-	Notes:
-	Must be LONG (0) for 1Mbps rate.
-	Does not apply (set to 0) for RevG-OFDM rates.
-b14   - Indicates PBCC encoding (1=PBCC, 0=not).
-	Notes:
-	Does not apply (set to 0) for rates 1 and 2 Mbps.
-	Does not apply (set to 0) for RevG-OFDM rates.
-b13    - Unused (set to 0).
-b12-b0 - Supported Rate indicator bits as defined below.
-
-******************************************************************************/
-
-
-/*************************************************************************
-
-    Interrupt Trigger Register (Host -> WiLink)
-
-**************************************************************************/
-
-/* Hardware to Embedded CPU Interrupts - first 32-bit register set */
-
-/*
- * Host Command Interrupt. Setting this bit masks
- * the interrupt that the host issues to inform
- * the FW that it has sent a command
- * to the Wlan hardware Command Mailbox.
- */
-#define INTR_TRIG_CMD       BIT(0)
-
-/*
- * Host Event Acknowlegde Interrupt. The host
- * sets this bit to acknowledge that it received
- * the unsolicited information from the event
- * mailbox.
- */
-#define INTR_TRIG_EVENT_ACK BIT(1)
-
-/*
- * The host sets this bit to inform the Wlan
- * FW that a TX packet is in the XFER
- * Buffer #0.
- */
-#define INTR_TRIG_TX_PROC0 BIT(2)
-
-/*
- * The host sets this bit to inform the FW
- * that it read a packet from RX XFER
- * Buffer #0.
- */
-#define INTR_TRIG_RX_PROC0 BIT(3)
-
-#define INTR_TRIG_DEBUG_ACK BIT(4)
-
-#define INTR_TRIG_STATE_CHANGED BIT(5)
-
-
-/* Hardware to Embedded CPU Interrupts - second 32-bit register set */
-
-/*
- * The host sets this bit to inform the FW
- * that it read a packet from RX XFER
- * Buffer #1.
- */
-#define INTR_TRIG_RX_PROC1 BIT(17)
-
-/*
- * The host sets this bit to inform the Wlan
- * hardware that a TX packet is in the XFER
- * Buffer #1.
- */
-#define INTR_TRIG_TX_PROC1 BIT(18)
-
-#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c
deleted file mode 100644
index 1b6294b..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_rx.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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/skbuff.h>
-#include <linux/gfp.h>
-#include <net/mac80211.h>
-
-#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_io.h"
-#include "wl1251_rx.h"
-#include "wl1251_cmd.h"
-#include "wl1251_acx.h"
-
-static void wl1251_rx_header(struct wl1251 *wl,
-			     struct wl1251_rx_descriptor *desc)
-{
-	u32 rx_packet_ring_addr;
-
-	rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr;
-	if (wl->rx_current_buffer)
-		rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size;
-
-	wl1251_mem_read(wl, rx_packet_ring_addr, desc, sizeof(*desc));
-}
-
-static void wl1251_rx_status(struct wl1251 *wl,
-			     struct wl1251_rx_descriptor *desc,
-			     struct ieee80211_rx_status *status,
-			     u8 beacon)
-{
-	u64 mactime;
-	int ret;
-
-	memset(status, 0, sizeof(struct ieee80211_rx_status));
-
-	status->band = IEEE80211_BAND_2GHZ;
-	status->mactime = desc->timestamp;
-
-	/*
-	 * The rx status timestamp is a 32 bits value while the TSF is a
-	 * 64 bits one.
-	 * For IBSS merging, TSF is mandatory, so we have to get it
-	 * somehow, so we ask for ACX_TSF_INFO.
-	 * That could be moved to the get_tsf() hook, but unfortunately,
-	 * this one must be atomic, while our SPI routines can sleep.
-	 */
-	if ((wl->bss_type == BSS_TYPE_IBSS) && beacon) {
-		ret = wl1251_acx_tsf_info(wl, &mactime);
-		if (ret == 0)
-			status->mactime = mactime;
-	}
-
-	status->signal = desc->rssi;
-
-	/*
-	 * FIXME: guessing that snr needs to be divided by two, otherwise
-	 * the values don't make any sense
-	 */
-	wl->noise = desc->rssi - desc->snr / 2;
-
-	status->freq = ieee80211_channel_to_frequency(desc->channel);
-
-	status->flag |= RX_FLAG_TSFT;
-
-	if (desc->flags & RX_DESC_ENCRYPTION_MASK) {
-		status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
-
-		if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL)))
-			status->flag |= RX_FLAG_DECRYPTED;
-
-		if (unlikely(desc->flags & RX_DESC_MIC_FAIL))
-			status->flag |= RX_FLAG_MMIC_ERROR;
-	}
-
-	if (unlikely(!(desc->flags & RX_DESC_VALID_FCS)))
-		status->flag |= RX_FLAG_FAILED_FCS_CRC;
-
-
-	/* FIXME: set status->rate_idx */
-}
-
-static void wl1251_rx_body(struct wl1251 *wl,
-			   struct wl1251_rx_descriptor *desc)
-{
-	struct sk_buff *skb;
-	struct ieee80211_rx_status status;
-	u8 *rx_buffer, beacon = 0;
-	u16 length, *fc;
-	u32 curr_id, last_id_inc, rx_packet_ring_addr;
-
-	length = WL1251_RX_ALIGN(desc->length  - PLCP_HEADER_LENGTH);
-	curr_id = (desc->flags & RX_DESC_SEQNUM_MASK) >> RX_DESC_PACKETID_SHIFT;
-	last_id_inc = (wl->rx_last_id + 1) % (RX_MAX_PACKET_ID + 1);
-
-	if (last_id_inc != curr_id) {
-		wl1251_warning("curr ID:%d, last ID inc:%d",
-			       curr_id, last_id_inc);
-		wl->rx_last_id = curr_id;
-	} else {
-		wl->rx_last_id = last_id_inc;
-	}
-
-	rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr +
-		sizeof(struct wl1251_rx_descriptor) + 20;
-	if (wl->rx_current_buffer)
-		rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size;
-
-	skb = __dev_alloc_skb(length, GFP_KERNEL);
-	if (!skb) {
-		wl1251_error("Couldn't allocate RX frame");
-		return;
-	}
-
-	rx_buffer = skb_put(skb, length);
-	wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length);
-
-	/* The actual lenght doesn't include the target's alignment */
-	skb->len = desc->length  - PLCP_HEADER_LENGTH;
-
-	fc = (u16 *)skb->data;
-
-	if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
-		beacon = 1;
-
-	wl1251_rx_status(wl, desc, &status, beacon);
-
-	wl1251_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
-		     beacon ? "beacon" : "");
-
-	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
-	ieee80211_rx_ni(wl->hw, skb);
-}
-
-static void wl1251_rx_ack(struct wl1251 *wl)
-{
-	u32 data, addr;
-
-	if (wl->rx_current_buffer) {
-		addr = ACX_REG_INTERRUPT_TRIG_H;
-		data = INTR_TRIG_RX_PROC1;
-	} else {
-		addr = ACX_REG_INTERRUPT_TRIG;
-		data = INTR_TRIG_RX_PROC0;
-	}
-
-	wl1251_reg_write32(wl, addr, data);
-
-	/* Toggle buffer ring */
-	wl->rx_current_buffer = !wl->rx_current_buffer;
-}
-
-
-void wl1251_rx(struct wl1251 *wl)
-{
-	struct wl1251_rx_descriptor *rx_desc;
-
-	if (wl->state != WL1251_STATE_ON)
-		return;
-
-	rx_desc = wl->rx_descriptor;
-
-	/* We first read the frame's header */
-	wl1251_rx_header(wl, rx_desc);
-
-	/* Now we can read the body */
-	wl1251_rx_body(wl, rx_desc);
-
-	/* Finally, we need to ACK the RX */
-	wl1251_rx_ack(wl);
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.h b/drivers/net/wireless/wl12xx/wl1251_rx.h
deleted file mode 100644
index da4e534..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_rx.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef __WL1251_RX_H__
-#define __WL1251_RX_H__
-
-#include <linux/bitops.h>
-
-#include "wl1251.h"
-
-/*
- * RX PATH
- *
- * The Rx path uses a double buffer and an rx_contro structure, each located
- * at a fixed address in the device memory. The host keeps track of which
- * buffer is available and alternates between them on a per packet basis.
- * The size of each of the two buffers is large enough to hold the longest
- * 802.3 packet.
- * The RX path goes like that:
- * 1) The target generates an interrupt each time a new packet is received.
- *   There are 2 RX interrupts, one for each buffer.
- * 2) The host reads the received packet from one of the double buffers.
- * 3) The host triggers a target interrupt.
- * 4) The target prepares the next RX packet.
- */
-
-#define WL1251_RX_MAX_RSSI -30
-#define WL1251_RX_MIN_RSSI -95
-
-#define WL1251_RX_ALIGN_TO 4
-#define WL1251_RX_ALIGN(len) (((len) + WL1251_RX_ALIGN_TO - 1) & \
-			     ~(WL1251_RX_ALIGN_TO - 1))
-
-#define SHORT_PREAMBLE_BIT   BIT(0)
-#define OFDM_RATE_BIT        BIT(6)
-#define PBCC_RATE_BIT        BIT(7)
-
-#define PLCP_HEADER_LENGTH 8
-#define RX_DESC_PACKETID_SHIFT 11
-#define RX_MAX_PACKET_ID 3
-
-#define RX_DESC_VALID_FCS         0x0001
-#define RX_DESC_MATCH_RXADDR1     0x0002
-#define RX_DESC_MCAST             0x0004
-#define RX_DESC_STAINTIM          0x0008
-#define RX_DESC_VIRTUAL_BM        0x0010
-#define RX_DESC_BCAST             0x0020
-#define RX_DESC_MATCH_SSID        0x0040
-#define RX_DESC_MATCH_BSSID       0x0080
-#define RX_DESC_ENCRYPTION_MASK   0x0300
-#define RX_DESC_MEASURMENT        0x0400
-#define RX_DESC_SEQNUM_MASK       0x1800
-#define	RX_DESC_MIC_FAIL	  0x2000
-#define	RX_DESC_DECRYPT_FAIL	  0x4000
-
-struct wl1251_rx_descriptor {
-	u32 timestamp; /* In microseconds */
-	u16 length; /* Paylod length, including headers */
-	u16 flags;
-
-	/*
-	 * 0 - 802.11
-	 * 1 - 802.3
-	 * 2 - IP
-	 * 3 - Raw Codec
-	 */
-	u8 type;
-
-	/*
-	 * Received Rate:
-	 * 0x0A - 1MBPS
-	 * 0x14 - 2MBPS
-	 * 0x37 - 5_5MBPS
-	 * 0x0B - 6MBPS
-	 * 0x0F - 9MBPS
-	 * 0x6E - 11MBPS
-	 * 0x0A - 12MBPS
-	 * 0x0E - 18MBPS
-	 * 0xDC - 22MBPS
-	 * 0x09 - 24MBPS
-	 * 0x0D - 36MBPS
-	 * 0x08 - 48MBPS
-	 * 0x0C - 54MBPS
-	 */
-	u8 rate;
-
-	u8 mod_pre; /* Modulation and preamble */
-	u8 channel;
-
-	/*
-	 * 0 - 2.4 Ghz
-	 * 1 - 5 Ghz
-	 */
-	u8 band;
-
-	s8 rssi; /* in dB */
-	u8 rcpi; /* in dB */
-	u8 snr; /* in dB */
-} __packed;
-
-void wl1251_rx(struct wl1251 *wl);
-
-#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
deleted file mode 100644
index b901b61..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * wl12xx SDIO routines
- *
- * This program is free software; you can 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
- *
- * Copyright (C) 2005 Texas Instruments Incorporated
- * Copyright (C) 2008 Google Inc
- * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com)
- */
-#include <linux/module.h>
-#include <linux/mod_devicetable.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/platform_device.h>
-#include <linux/spi/wl12xx.h>
-#include <linux/irq.h>
-
-#include "wl1251.h"
-
-#ifndef SDIO_VENDOR_ID_TI
-#define SDIO_VENDOR_ID_TI		0x104c
-#endif
-
-#ifndef SDIO_DEVICE_ID_TI_WL1251
-#define SDIO_DEVICE_ID_TI_WL1251	0x9066
-#endif
-
-struct wl1251_sdio {
-	struct sdio_func *func;
-	u32 elp_val;
-};
-
-static struct wl12xx_platform_data *wl12xx_board_data;
-
-static struct sdio_func *wl_to_func(struct wl1251 *wl)
-{
-	struct wl1251_sdio *wl_sdio = wl->if_priv;
-	return wl_sdio->func;
-}
-
-static void wl1251_sdio_interrupt(struct sdio_func *func)
-{
-	struct wl1251 *wl = sdio_get_drvdata(func);
-
-	wl1251_debug(DEBUG_IRQ, "IRQ");
-
-	/* FIXME should be synchronous for sdio */
-	ieee80211_queue_work(wl->hw, &wl->irq_work);
-}
-
-static const struct sdio_device_id wl1251_devices[] = {
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1251) },
-	{}
-};
-MODULE_DEVICE_TABLE(sdio, wl1251_devices);
-
-
-static void wl1251_sdio_read(struct wl1251 *wl, int addr,
-			     void *buf, size_t len)
-{
-	int ret;
-	struct sdio_func *func = wl_to_func(wl);
-
-	sdio_claim_host(func);
-	ret = sdio_memcpy_fromio(func, buf, addr, len);
-	if (ret)
-		wl1251_error("sdio read failed (%d)", ret);
-	sdio_release_host(func);
-}
-
-static void wl1251_sdio_write(struct wl1251 *wl, int addr,
-			      void *buf, size_t len)
-{
-	int ret;
-	struct sdio_func *func = wl_to_func(wl);
-
-	sdio_claim_host(func);
-	ret = sdio_memcpy_toio(func, addr, buf, len);
-	if (ret)
-		wl1251_error("sdio write failed (%d)", ret);
-	sdio_release_host(func);
-}
-
-static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
-{
-	int ret = 0;
-	struct wl1251_sdio *wl_sdio = wl->if_priv;
-	struct sdio_func *func = wl_sdio->func;
-
-	/*
-	 * The hardware only supports RAW (read after write) access for
-	 * reading, regular sdio_readb won't work here (it interprets
-	 * the unused bits of CMD52 as write data even if we send read
-	 * request).
-	 */
-	sdio_claim_host(func);
-	*val = sdio_writeb_readb(func, wl_sdio->elp_val, addr, &ret);
-	sdio_release_host(func);
-
-	if (ret)
-		wl1251_error("sdio_readb failed (%d)", ret);
-}
-
-static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
-{
-	int ret = 0;
-	struct wl1251_sdio *wl_sdio = wl->if_priv;
-	struct sdio_func *func = wl_sdio->func;
-
-	sdio_claim_host(func);
-	sdio_writeb(func, val, addr, &ret);
-	sdio_release_host(func);
-
-	if (ret)
-		wl1251_error("sdio_writeb failed (%d)", ret);
-	else
-		wl_sdio->elp_val = val;
-}
-
-static void wl1251_sdio_reset(struct wl1251 *wl)
-{
-}
-
-static void wl1251_sdio_enable_irq(struct wl1251 *wl)
-{
-	struct sdio_func *func = wl_to_func(wl);
-
-	sdio_claim_host(func);
-	sdio_claim_irq(func, wl1251_sdio_interrupt);
-	sdio_release_host(func);
-}
-
-static void wl1251_sdio_disable_irq(struct wl1251 *wl)
-{
-	struct sdio_func *func = wl_to_func(wl);
-
-	sdio_claim_host(func);
-	sdio_release_irq(func);
-	sdio_release_host(func);
-}
-
-/* Interrupts when using dedicated WLAN_IRQ pin */
-static irqreturn_t wl1251_line_irq(int irq, void *cookie)
-{
-	struct wl1251 *wl = cookie;
-
-	ieee80211_queue_work(wl->hw, &wl->irq_work);
-
-	return IRQ_HANDLED;
-}
-
-static void wl1251_enable_line_irq(struct wl1251 *wl)
-{
-	return enable_irq(wl->irq);
-}
-
-static void wl1251_disable_line_irq(struct wl1251 *wl)
-{
-	return disable_irq(wl->irq);
-}
-
-static void wl1251_sdio_set_power(bool enable)
-{
-}
-
-static struct wl1251_if_operations wl1251_sdio_ops = {
-	.read = wl1251_sdio_read,
-	.write = wl1251_sdio_write,
-	.write_elp = wl1251_sdio_write_elp,
-	.read_elp = wl1251_sdio_read_elp,
-	.reset = wl1251_sdio_reset,
-};
-
-static int wl1251_platform_probe(struct platform_device *pdev)
-{
-	if (pdev->id != -1) {
-		wl1251_error("can only handle single device");
-		return -ENODEV;
-	}
-
-	wl12xx_board_data = pdev->dev.platform_data;
-	return 0;
-}
-
-/*
- * Dummy platform_driver for passing platform_data to this driver,
- * until we have a way to pass this through SDIO subsystem or
- * some other way.
- */
-static struct platform_driver wl1251_platform_driver = {
-	.driver = {
-		.name	= "wl1251_data",
-		.owner	= THIS_MODULE,
-	},
-	.probe	= wl1251_platform_probe,
-};
-
-static int wl1251_sdio_probe(struct sdio_func *func,
-			     const struct sdio_device_id *id)
-{
-	int ret;
-	struct wl1251 *wl;
-	struct ieee80211_hw *hw;
-	struct wl1251_sdio *wl_sdio;
-
-	hw = wl1251_alloc_hw();
-	if (IS_ERR(hw))
-		return PTR_ERR(hw);
-
-	wl = hw->priv;
-
-	wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL);
-	if (wl_sdio == NULL) {
-		ret = -ENOMEM;
-		goto out_free_hw;
-	}
-
-	sdio_claim_host(func);
-	ret = sdio_enable_func(func);
-	if (ret)
-		goto release;
-
-	sdio_set_block_size(func, 512);
-	sdio_release_host(func);
-
-	SET_IEEE80211_DEV(hw, &func->dev);
-	wl_sdio->func = func;
-	wl->if_priv = wl_sdio;
-	wl->if_ops = &wl1251_sdio_ops;
-	wl->set_power = wl1251_sdio_set_power;
-
-	if (wl12xx_board_data != NULL) {
-		wl->set_power = wl12xx_board_data->set_power;
-		wl->irq = wl12xx_board_data->irq;
-		wl->use_eeprom = wl12xx_board_data->use_eeprom;
-	}
-
-	if (wl->irq) {
-		ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
-		if (ret < 0) {
-			wl1251_error("request_irq() failed: %d", ret);
-			goto disable;
-		}
-
-		set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
-		disable_irq(wl->irq);
-
-		wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
-		wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
-
-		wl1251_info("using dedicated interrupt line");
-	} else {
-		wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq;
-		wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq;
-
-		wl1251_info("using SDIO interrupt");
-	}
-
-	ret = wl1251_init_ieee80211(wl);
-	if (ret)
-		goto out_free_irq;
-
-	sdio_set_drvdata(func, wl);
-	return ret;
-
-out_free_irq:
-	if (wl->irq)
-		free_irq(wl->irq, wl);
-disable:
-	sdio_claim_host(func);
-	sdio_disable_func(func);
-release:
-	sdio_release_host(func);
-	kfree(wl_sdio);
-out_free_hw:
-	wl1251_free_hw(wl);
-	return ret;
-}
-
-static void __devexit wl1251_sdio_remove(struct sdio_func *func)
-{
-	struct wl1251 *wl = sdio_get_drvdata(func);
-	struct wl1251_sdio *wl_sdio = wl->if_priv;
-
-	if (wl->irq)
-		free_irq(wl->irq, wl);
-	kfree(wl_sdio);
-	wl1251_free_hw(wl);
-
-	sdio_claim_host(func);
-	sdio_release_irq(func);
-	sdio_disable_func(func);
-	sdio_release_host(func);
-}
-
-static struct sdio_driver wl1251_sdio_driver = {
-	.name		= "wl1251_sdio",
-	.id_table	= wl1251_devices,
-	.probe		= wl1251_sdio_probe,
-	.remove		= __devexit_p(wl1251_sdio_remove),
-};
-
-static int __init wl1251_sdio_init(void)
-{
-	int err;
-
-	err = platform_driver_register(&wl1251_platform_driver);
-	if (err) {
-		wl1251_error("failed to register platform driver: %d", err);
-		return err;
-	}
-
-	err = sdio_register_driver(&wl1251_sdio_driver);
-	if (err)
-		wl1251_error("failed to register sdio driver: %d", err);
-	return err;
-}
-
-static void __exit wl1251_sdio_exit(void)
-{
-	sdio_unregister_driver(&wl1251_sdio_driver);
-	platform_driver_unregister(&wl1251_platform_driver);
-	wl1251_notice("unloaded");
-}
-
-module_init(wl1251_sdio_init);
-module_exit(wl1251_sdio_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
deleted file mode 100644
index 27fdfaa..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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/irq.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/crc7.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/wl12xx.h>
-
-#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_spi.h"
-
-static irqreturn_t wl1251_irq(int irq, void *cookie)
-{
-	struct wl1251 *wl;
-
-	wl1251_debug(DEBUG_IRQ, "IRQ");
-
-	wl = cookie;
-
-	ieee80211_queue_work(wl->hw, &wl->irq_work);
-
-	return IRQ_HANDLED;
-}
-
-static struct spi_device *wl_to_spi(struct wl1251 *wl)
-{
-	return wl->if_priv;
-}
-
-static void wl1251_spi_reset(struct wl1251 *wl)
-{
-	u8 *cmd;
-	struct spi_transfer t;
-	struct spi_message m;
-
-	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
-	if (!cmd) {
-		wl1251_error("could not allocate cmd for spi reset");
-		return;
-	}
-
-	memset(&t, 0, sizeof(t));
-	spi_message_init(&m);
-
-	memset(cmd, 0xff, WSPI_INIT_CMD_LEN);
-
-	t.tx_buf = cmd;
-	t.len = WSPI_INIT_CMD_LEN;
-	spi_message_add_tail(&t, &m);
-
-	spi_sync(wl_to_spi(wl), &m);
-
-	wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
-}
-
-static void wl1251_spi_wake(struct wl1251 *wl)
-{
-	u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
-	struct spi_transfer t;
-	struct spi_message m;
-
-	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
-	if (!cmd) {
-		wl1251_error("could not allocate cmd for spi init");
-		return;
-	}
-
-	memset(crc, 0, sizeof(crc));
-	memset(&t, 0, sizeof(t));
-	spi_message_init(&m);
-
-	/*
-	 * Set WSPI_INIT_COMMAND
-	 * the data is being send from the MSB to LSB
-	 */
-	cmd[2] = 0xff;
-	cmd[3] = 0xff;
-	cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
-	cmd[0] = 0;
-	cmd[7] = 0;
-	cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
-	cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
-
-	if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
-		cmd[5] |=  WSPI_INIT_CMD_DIS_FIXEDBUSY;
-	else
-		cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
-
-	cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
-		| WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
-
-	crc[0] = cmd[1];
-	crc[1] = cmd[0];
-	crc[2] = cmd[7];
-	crc[3] = cmd[6];
-	crc[4] = cmd[5];
-
-	cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
-	cmd[4] |= WSPI_INIT_CMD_END;
-
-	t.tx_buf = cmd;
-	t.len = WSPI_INIT_CMD_LEN;
-	spi_message_add_tail(&t, &m);
-
-	spi_sync(wl_to_spi(wl), &m);
-
-	wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
-}
-
-static void wl1251_spi_reset_wake(struct wl1251 *wl)
-{
-	wl1251_spi_reset(wl);
-	wl1251_spi_wake(wl);
-}
-
-static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
-			    size_t len)
-{
-	struct spi_transfer t[3];
-	struct spi_message m;
-	u8 *busy_buf;
-	u32 *cmd;
-
-	cmd = &wl->buffer_cmd;
-	busy_buf = wl->buffer_busyword;
-
-	*cmd = 0;
-	*cmd |= WSPI_CMD_READ;
-	*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
-	*cmd |= addr & WSPI_CMD_BYTE_ADDR;
-
-	spi_message_init(&m);
-	memset(t, 0, sizeof(t));
-
-	t[0].tx_buf = cmd;
-	t[0].len = 4;
-	spi_message_add_tail(&t[0], &m);
-
-	/* Busy and non busy words read */
-	t[1].rx_buf = busy_buf;
-	t[1].len = WL1251_BUSY_WORD_LEN;
-	spi_message_add_tail(&t[1], &m);
-
-	t[2].rx_buf = buf;
-	t[2].len = len;
-	spi_message_add_tail(&t[2], &m);
-
-	spi_sync(wl_to_spi(wl), &m);
-
-	/* FIXME: check busy words */
-
-	wl1251_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
-	wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
-}
-
-static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
-			     size_t len)
-{
-	struct spi_transfer t[2];
-	struct spi_message m;
-	u32 *cmd;
-
-	cmd = &wl->buffer_cmd;
-
-	*cmd = 0;
-	*cmd |= WSPI_CMD_WRITE;
-	*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
-	*cmd |= addr & WSPI_CMD_BYTE_ADDR;
-
-	spi_message_init(&m);
-	memset(t, 0, sizeof(t));
-
-	t[0].tx_buf = cmd;
-	t[0].len = sizeof(*cmd);
-	spi_message_add_tail(&t[0], &m);
-
-	t[1].tx_buf = buf;
-	t[1].len = len;
-	spi_message_add_tail(&t[1], &m);
-
-	spi_sync(wl_to_spi(wl), &m);
-
-	wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
-	wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
-}
-
-static void wl1251_spi_enable_irq(struct wl1251 *wl)
-{
-	return enable_irq(wl->irq);
-}
-
-static void wl1251_spi_disable_irq(struct wl1251 *wl)
-{
-	return disable_irq(wl->irq);
-}
-
-static const struct wl1251_if_operations wl1251_spi_ops = {
-	.read = wl1251_spi_read,
-	.write = wl1251_spi_write,
-	.reset = wl1251_spi_reset_wake,
-	.enable_irq = wl1251_spi_enable_irq,
-	.disable_irq = wl1251_spi_disable_irq,
-};
-
-static int __devinit wl1251_spi_probe(struct spi_device *spi)
-{
-	struct wl12xx_platform_data *pdata;
-	struct ieee80211_hw *hw;
-	struct wl1251 *wl;
-	int ret;
-
-	pdata = spi->dev.platform_data;
-	if (!pdata) {
-		wl1251_error("no platform data");
-		return -ENODEV;
-	}
-
-	hw = wl1251_alloc_hw();
-	if (IS_ERR(hw))
-		return PTR_ERR(hw);
-
-	wl = hw->priv;
-
-	SET_IEEE80211_DEV(hw, &spi->dev);
-	dev_set_drvdata(&spi->dev, wl);
-	wl->if_priv = spi;
-	wl->if_ops = &wl1251_spi_ops;
-
-	/* This is the only SPI value that we need to set here, the rest
-	 * comes from the board-peripherals file */
-	spi->bits_per_word = 32;
-
-	ret = spi_setup(spi);
-	if (ret < 0) {
-		wl1251_error("spi_setup failed");
-		goto out_free;
-	}
-
-	wl->set_power = pdata->set_power;
-	if (!wl->set_power) {
-		wl1251_error("set power function missing in platform data");
-		return -ENODEV;
-	}
-
-	wl->irq = spi->irq;
-	if (wl->irq < 0) {
-		wl1251_error("irq missing in platform data");
-		return -ENODEV;
-	}
-
-	wl->use_eeprom = pdata->use_eeprom;
-
-	ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
-	if (ret < 0) {
-		wl1251_error("request_irq() failed: %d", ret);
-		goto out_free;
-	}
-
-	set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
-
-	disable_irq(wl->irq);
-
-	ret = wl1251_init_ieee80211(wl);
-	if (ret)
-		goto out_irq;
-
-	return 0;
-
- out_irq:
-	free_irq(wl->irq, wl);
-
- out_free:
-	ieee80211_free_hw(hw);
-
-	return ret;
-}
-
-static int __devexit wl1251_spi_remove(struct spi_device *spi)
-{
-	struct wl1251 *wl = dev_get_drvdata(&spi->dev);
-
-	free_irq(wl->irq, wl);
-	wl1251_free_hw(wl);
-
-	return 0;
-}
-
-static struct spi_driver wl1251_spi_driver = {
-	.driver = {
-		.name		= DRIVER_NAME,
-		.bus		= &spi_bus_type,
-		.owner		= THIS_MODULE,
-	},
-
-	.probe		= wl1251_spi_probe,
-	.remove		= __devexit_p(wl1251_spi_remove),
-};
-
-static int __init wl1251_spi_init(void)
-{
-	int ret;
-
-	ret = spi_register_driver(&wl1251_spi_driver);
-	if (ret < 0) {
-		wl1251_error("failed to register spi driver: %d", ret);
-		goto out;
-	}
-
-out:
-	return ret;
-}
-
-static void __exit wl1251_spi_exit(void)
-{
-	spi_unregister_driver(&wl1251_spi_driver);
-
-	wl1251_notice("unloaded");
-}
-
-module_init(wl1251_spi_init);
-module_exit(wl1251_spi_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
-MODULE_ALIAS("spi:wl1251");
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl12xx/wl1251_spi.h
deleted file mode 100644
index 2e273a9..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_spi.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef __WL1251_SPI_H__
-#define __WL1251_SPI_H__
-
-#include "wl1251_cmd.h"
-#include "wl1251_acx.h"
-#include "wl1251_reg.h"
-
-#define WSPI_CMD_READ                 0x40000000
-#define WSPI_CMD_WRITE                0x00000000
-#define WSPI_CMD_FIXED                0x20000000
-#define WSPI_CMD_BYTE_LENGTH          0x1FFE0000
-#define WSPI_CMD_BYTE_LENGTH_OFFSET   17
-#define WSPI_CMD_BYTE_ADDR            0x0001FFFF
-
-#define WSPI_INIT_CMD_CRC_LEN       5
-
-#define WSPI_INIT_CMD_START         0x00
-#define WSPI_INIT_CMD_TX            0x40
-/* the extra bypass bit is sampled by the TNET as '1' */
-#define WSPI_INIT_CMD_BYPASS_BIT    0x80
-#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07
-#define WSPI_INIT_CMD_EN_FIXEDBUSY  0x80
-#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00
-#define WSPI_INIT_CMD_IOD           0x40
-#define WSPI_INIT_CMD_IP            0x20
-#define WSPI_INIT_CMD_CS            0x10
-#define WSPI_INIT_CMD_WS            0x08
-#define WSPI_INIT_CMD_WSPI          0x01
-#define WSPI_INIT_CMD_END           0x01
-
-#define WSPI_INIT_CMD_LEN           8
-
-#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \
-		((WL1251_BUSY_WORD_LEN - 4) / sizeof(u32))
-#define HW_ACCESS_WSPI_INIT_CMD_MASK  0
-
-#endif /* __WL1251_SPI_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c
deleted file mode 100644
index a38ec19..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_tx.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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/kernel.h>
-#include <linux/module.h>
-
-#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_tx.h"
-#include "wl1251_ps.h"
-#include "wl1251_io.h"
-
-static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count)
-{
-	int used, data_in_count;
-
-	data_in_count = wl->data_in_count;
-
-	if (data_in_count < data_out_count)
-		/* data_in_count has wrapped */
-		data_in_count += TX_STATUS_DATA_OUT_COUNT_MASK + 1;
-
-	used = data_in_count - data_out_count;
-
-	WARN_ON(used < 0);
-	WARN_ON(used > DP_TX_PACKET_RING_CHUNK_NUM);
-
-	if (used >= DP_TX_PACKET_RING_CHUNK_NUM)
-		return true;
-	else
-		return false;
-}
-
-static int wl1251_tx_path_status(struct wl1251 *wl)
-{
-	u32 status, addr, data_out_count;
-	bool busy;
-
-	addr = wl->data_path->tx_control_addr;
-	status = wl1251_mem_read32(wl, addr);
-	data_out_count = status & TX_STATUS_DATA_OUT_COUNT_MASK;
-	busy = wl1251_tx_double_buffer_busy(wl, data_out_count);
-
-	if (busy)
-		return -EBUSY;
-
-	return 0;
-}
-
-static int wl1251_tx_id(struct wl1251 *wl, struct sk_buff *skb)
-{
-	int i;
-
-	for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
-		if (wl->tx_frames[i] == NULL) {
-			wl->tx_frames[i] = skb;
-			return i;
-		}
-
-	return -EBUSY;
-}
-
-static void wl1251_tx_control(struct tx_double_buffer_desc *tx_hdr,
-			      struct ieee80211_tx_info *control, u16 fc)
-{
-	*(u16 *)&tx_hdr->control = 0;
-
-	tx_hdr->control.rate_policy = 0;
-
-	/* 802.11 packets */
-	tx_hdr->control.packet_type = 0;
-
-	if (control->flags & IEEE80211_TX_CTL_NO_ACK)
-		tx_hdr->control.ack_policy = 1;
-
-	tx_hdr->control.tx_complete = 1;
-
-	if ((fc & IEEE80211_FTYPE_DATA) &&
-	    ((fc & IEEE80211_STYPE_QOS_DATA) ||
-	     (fc & IEEE80211_STYPE_QOS_NULLFUNC)))
-		tx_hdr->control.qos = 1;
-}
-
-/* RSN + MIC = 8 + 8 = 16 bytes (worst case - AES). */
-#define MAX_MSDU_SECURITY_LENGTH      16
-#define MAX_MPDU_SECURITY_LENGTH      16
-#define WLAN_QOS_HDR_LEN              26
-#define MAX_MPDU_HEADER_AND_SECURITY  (MAX_MPDU_SECURITY_LENGTH + \
-				       WLAN_QOS_HDR_LEN)
-#define HW_BLOCK_SIZE                 252
-static void wl1251_tx_frag_block_num(struct tx_double_buffer_desc *tx_hdr)
-{
-	u16 payload_len, frag_threshold, mem_blocks;
-	u16 num_mpdus, mem_blocks_per_frag;
-
-	frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
-	tx_hdr->frag_threshold = cpu_to_le16(frag_threshold);
-
-	payload_len = le16_to_cpu(tx_hdr->length) + MAX_MSDU_SECURITY_LENGTH;
-
-	if (payload_len > frag_threshold) {
-		mem_blocks_per_frag =
-			((frag_threshold + MAX_MPDU_HEADER_AND_SECURITY) /
-			 HW_BLOCK_SIZE) + 1;
-		num_mpdus = payload_len / frag_threshold;
-		mem_blocks = num_mpdus * mem_blocks_per_frag;
-		payload_len -= num_mpdus * frag_threshold;
-		num_mpdus++;
-
-	} else {
-		mem_blocks_per_frag = 0;
-		mem_blocks = 0;
-		num_mpdus = 1;
-	}
-
-	mem_blocks += (payload_len / HW_BLOCK_SIZE) + 1;
-
-	if (num_mpdus > 1)
-		mem_blocks += min(num_mpdus, mem_blocks_per_frag);
-
-	tx_hdr->num_mem_blocks = mem_blocks;
-}
-
-static int wl1251_tx_fill_hdr(struct wl1251 *wl, struct sk_buff *skb,
-			      struct ieee80211_tx_info *control)
-{
-	struct tx_double_buffer_desc *tx_hdr;
-	struct ieee80211_rate *rate;
-	int id;
-	u16 fc;
-
-	if (!skb)
-		return -EINVAL;
-
-	id = wl1251_tx_id(wl, skb);
-	if (id < 0)
-		return id;
-
-	fc = *(u16 *)skb->data;
-	tx_hdr = (struct tx_double_buffer_desc *) skb_push(skb,
-							   sizeof(*tx_hdr));
-
-	tx_hdr->length = cpu_to_le16(skb->len - sizeof(*tx_hdr));
-	rate = ieee80211_get_tx_rate(wl->hw, control);
-	tx_hdr->rate = cpu_to_le16(rate->hw_value);
-	tx_hdr->expiry_time = cpu_to_le32(1 << 16);
-	tx_hdr->id = id;
-
-	tx_hdr->xmit_queue = wl1251_tx_get_queue(skb_get_queue_mapping(skb));
-
-	wl1251_tx_control(tx_hdr, control, fc);
-	wl1251_tx_frag_block_num(tx_hdr);
-
-	return 0;
-}
-
-/* We copy the packet to the target */
-static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb,
-				 struct ieee80211_tx_info *control)
-{
-	struct tx_double_buffer_desc *tx_hdr;
-	int len;
-	u32 addr;
-
-	if (!skb)
-		return -EINVAL;
-
-	tx_hdr = (struct tx_double_buffer_desc *) skb->data;
-
-	if (control->control.hw_key &&
-	    control->control.hw_key->alg == ALG_TKIP) {
-		int hdrlen;
-		__le16 fc;
-		u16 length;
-		u8 *pos;
-
-		fc = *(__le16 *)(skb->data + sizeof(*tx_hdr));
-		length = le16_to_cpu(tx_hdr->length) + WL1251_TKIP_IV_SPACE;
-		tx_hdr->length = cpu_to_le16(length);
-
-		hdrlen = ieee80211_hdrlen(fc);
-
-		pos = skb_push(skb, WL1251_TKIP_IV_SPACE);
-		memmove(pos, pos + WL1251_TKIP_IV_SPACE,
-			sizeof(*tx_hdr) + hdrlen);
-	}
-
-	/* Revisit. This is a workaround for getting non-aligned packets.
-	   This happens at least with EAPOL packets from the user space.
-	   Our DMA requires packets to be aligned on a 4-byte boundary.
-	*/
-	if (unlikely((long)skb->data & 0x03)) {
-		int offset = (4 - (long)skb->data) & 0x03;
-		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;
-
-			/* align the buffer on a 4-byte boundary */
-			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;
-		}
-	}
-
-	/* Our skb->data at this point includes the HW header */
-	len = WL1251_TX_ALIGN(skb->len);
-
-	if (wl->data_in_count & 0x1)
-		addr = wl->data_path->tx_packet_ring_addr +
-			wl->data_path->tx_packet_ring_chunk_size;
-	else
-		addr = wl->data_path->tx_packet_ring_addr;
-
-	wl1251_mem_write(wl, addr, skb->data, len);
-
-	wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x "
-		     "queue %d", tx_hdr->id, skb, tx_hdr->length,
-		     tx_hdr->rate, tx_hdr->xmit_queue);
-
-	return 0;
-}
-
-static void wl1251_tx_trigger(struct wl1251 *wl)
-{
-	u32 data, addr;
-
-	if (wl->data_in_count & 0x1) {
-		addr = ACX_REG_INTERRUPT_TRIG_H;
-		data = INTR_TRIG_TX_PROC1;
-	} else {
-		addr = ACX_REG_INTERRUPT_TRIG;
-		data = INTR_TRIG_TX_PROC0;
-	}
-
-	wl1251_reg_write32(wl, addr, data);
-
-	/* Bumping data in */
-	wl->data_in_count = (wl->data_in_count + 1) &
-		TX_STATUS_DATA_OUT_COUNT_MASK;
-}
-
-/* caller must hold wl->mutex */
-static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
-{
-	struct ieee80211_tx_info *info;
-	int ret = 0;
-	u8 idx;
-
-	info = IEEE80211_SKB_CB(skb);
-
-	if (info->control.hw_key) {
-		idx = info->control.hw_key->hw_key_idx;
-		if (unlikely(wl->default_key != idx)) {
-			ret = wl1251_acx_default_key(wl, idx);
-			if (ret < 0)
-				return ret;
-		}
-	}
-
-	ret = wl1251_tx_path_status(wl);
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_tx_fill_hdr(wl, skb, info);
-	if (ret < 0)
-		return ret;
-
-	ret = wl1251_tx_send_packet(wl, skb, info);
-	if (ret < 0)
-		return ret;
-
-	wl1251_tx_trigger(wl);
-
-	return ret;
-}
-
-void wl1251_tx_work(struct work_struct *work)
-{
-	struct wl1251 *wl = container_of(work, struct wl1251, tx_work);
-	struct sk_buff *skb;
-	bool woken_up = false;
-	int ret;
-
-	mutex_lock(&wl->mutex);
-
-	if (unlikely(wl->state == WL1251_STATE_OFF))
-		goto out;
-
-	while ((skb = skb_dequeue(&wl->tx_queue))) {
-		if (!woken_up) {
-			ret = wl1251_ps_elp_wakeup(wl);
-			if (ret < 0)
-				goto out;
-			woken_up = true;
-		}
-
-		ret = wl1251_tx_frame(wl, skb);
-		if (ret == -EBUSY) {
-			/* firmware buffer is full, stop queues */
-			wl1251_debug(DEBUG_TX, "tx_work: fw buffer full, "
-				     "stop queues");
-			ieee80211_stop_queues(wl->hw);
-			wl->tx_queue_stopped = true;
-			skb_queue_head(&wl->tx_queue, skb);
-			goto out;
-		} else if (ret < 0) {
-			dev_kfree_skb(skb);
-			goto out;
-		}
-	}
-
-out:
-	if (woken_up)
-		wl1251_ps_elp_sleep(wl);
-
-	mutex_unlock(&wl->mutex);
-}
-
-static const char *wl1251_tx_parse_status(u8 status)
-{
-	/* 8 bit status field, one character per bit plus null */
-	static char buf[9];
-	int i = 0;
-
-	memset(buf, 0, sizeof(buf));
-
-	if (status & TX_DMA_ERROR)
-		buf[i++] = 'm';
-	if (status & TX_DISABLED)
-		buf[i++] = 'd';
-	if (status & TX_RETRY_EXCEEDED)
-		buf[i++] = 'r';
-	if (status & TX_TIMEOUT)
-		buf[i++] = 't';
-	if (status & TX_KEY_NOT_FOUND)
-		buf[i++] = 'k';
-	if (status & TX_ENCRYPT_FAIL)
-		buf[i++] = 'e';
-	if (status & TX_UNAVAILABLE_PRIORITY)
-		buf[i++] = 'p';
-
-	/* bit 0 is unused apparently */
-
-	return buf;
-}
-
-static void wl1251_tx_packet_cb(struct wl1251 *wl,
-				struct tx_result *result)
-{
-	struct ieee80211_tx_info *info;
-	struct sk_buff *skb;
-	int hdrlen, ret;
-	u8 *frame;
-
-	skb = wl->tx_frames[result->id];
-	if (skb == NULL) {
-		wl1251_error("SKB for packet %d is NULL", result->id);
-		return;
-	}
-
-	info = IEEE80211_SKB_CB(skb);
-
-	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
-	    (result->status == TX_SUCCESS))
-		info->flags |= IEEE80211_TX_STAT_ACK;
-
-	info->status.rates[0].count = result->ack_failures + 1;
-	wl->stats.retry_count += result->ack_failures;
-
-	/*
-	 * We have to remove our private TX header before pushing
-	 * the skb back to mac80211.
-	 */
-	frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc));
-	if (info->control.hw_key &&
-	    info->control.hw_key->alg == ALG_TKIP) {
-		hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-		memmove(frame + WL1251_TKIP_IV_SPACE, frame, hdrlen);
-		skb_pull(skb, WL1251_TKIP_IV_SPACE);
-	}
-
-	wl1251_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x"
-		     " status 0x%x (%s)",
-		     result->id, skb, result->ack_failures, result->rate,
-		     result->status, wl1251_tx_parse_status(result->status));
-
-
-	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;
-	struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr;
-
-	if (unlikely(wl->state != WL1251_STATE_ON))
-		return;
-
-	/* First we read the result */
-	wl1251_mem_read(wl, wl->data_path->tx_complete_addr,
-			    result, sizeof(result));
-
-	result_index = wl->next_tx_complete;
-
-	for (i = 0; i < ARRAY_SIZE(result); i++) {
-		result_ptr = &result[result_index];
-
-		if (result_ptr->done_1 == 1 &&
-		    result_ptr->done_2 == 1) {
-			wl1251_tx_packet_cb(wl, result_ptr);
-
-			result_ptr->done_1 = 0;
-			result_ptr->done_2 = 0;
-
-			result_index = (result_index + 1) &
-				(FW_TX_CMPLT_BLOCK_SIZE - 1);
-			num_complete++;
-		} else {
-			break;
-		}
-	}
-
-	/* Every completed frame needs to be acknowledged */
-	if (num_complete) {
-		/*
-		 * If we've wrapped, we have to clear
-		 * the results in 2 steps.
-		 */
-		if (result_index > wl->next_tx_complete) {
-			/* Only 1 write is needed */
-			wl1251_mem_write(wl,
-					 wl->data_path->tx_complete_addr +
-					 (wl->next_tx_complete *
-					  sizeof(struct tx_result)),
-					 &result[wl->next_tx_complete],
-					 num_complete *
-					 sizeof(struct tx_result));
-
-
-		} else if (result_index < wl->next_tx_complete) {
-			/* 2 writes are needed */
-			wl1251_mem_write(wl,
-					 wl->data_path->tx_complete_addr +
-					 (wl->next_tx_complete *
-					  sizeof(struct tx_result)),
-					 &result[wl->next_tx_complete],
-					 (FW_TX_CMPLT_BLOCK_SIZE -
-					  wl->next_tx_complete) *
-					 sizeof(struct tx_result));
-
-			wl1251_mem_write(wl,
-					 wl->data_path->tx_complete_addr,
-					 result,
-					 (num_complete -
-					  FW_TX_CMPLT_BLOCK_SIZE +
-					  wl->next_tx_complete) *
-					 sizeof(struct tx_result));
-
-		} else {
-			/* We have to write the whole array */
-			wl1251_mem_write(wl,
-					 wl->data_path->tx_complete_addr,
-					 result,
-					 FW_TX_CMPLT_BLOCK_SIZE *
-					 sizeof(struct tx_result));
-		}
-
-	}
-
-	wl->next_tx_complete = result_index;
-}
-
-/* caller must hold wl->mutex */
-void wl1251_tx_flush(struct wl1251 *wl)
-{
-	int i;
-	struct sk_buff *skb;
-	struct ieee80211_tx_info *info;
-
-	/* TX failure */
-/* 	control->flags = 0; FIXME */
-
-	while ((skb = skb_dequeue(&wl->tx_queue))) {
-		info = IEEE80211_SKB_CB(skb);
-
-		wl1251_debug(DEBUG_TX, "flushing skb 0x%p", skb);
-
-		if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
-				continue;
-
-		ieee80211_tx_status(wl->hw, skb);
-	}
-
-	for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
-		if (wl->tx_frames[i] != NULL) {
-			skb = wl->tx_frames[i];
-			info = IEEE80211_SKB_CB(skb);
-
-			if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
-				continue;
-
-			ieee80211_tx_status(wl->hw, skb);
-			wl->tx_frames[i] = NULL;
-		}
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h
deleted file mode 100644
index f40eeb3..0000000
--- a/drivers/net/wireless/wl12xx/wl1251_tx.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * This file is part of wl1251
- *
- * Copyright (c) 1998-2007 Texas Instruments Incorporated
- * Copyright (C) 2008 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef __WL1251_TX_H__
-#define __WL1251_TX_H__
-
-#include <linux/bitops.h>
-#include "wl1251_acx.h"
-
-/*
- *
- * TX PATH
- *
- * The Tx path uses a double buffer and a tx_control structure, each located
- * at a fixed address in the device's memory. On startup, the host retrieves
- * the pointers to these addresses. A double buffer allows for continuous data
- * flow towards the device. The host keeps track of which buffer is available
- * and alternates between these two buffers on a per packet basis.
- *
- * The size of each of the two buffers is large enough to hold the longest
- * 802.3 packet - maximum size Ethernet packet + header + descriptor.
- * TX complete indication will be received a-synchronously in a TX done cyclic
- * buffer which is composed of 16 tx_result descriptors structures and is used
- * in a cyclic manner.
- *
- * The TX (HOST) procedure is as follows:
- * 1. Read the Tx path status, that will give the data_out_count.
- * 2. goto 1, if not possible.
- *    i.e. if data_in_count - data_out_count >= HwBuffer size (2 for double
- *    buffer).
- * 3. Copy the packet (preceded by double_buffer_desc), if possible.
- *    i.e. if data_in_count - data_out_count < HwBuffer size (2 for double
- *    buffer).
- * 4. increment data_in_count.
- * 5. Inform the firmware by generating a firmware internal interrupt.
- * 6. FW will increment data_out_count after it reads the buffer.
- *
- * The TX Complete procedure:
- * 1. To get a TX complete indication the host enables the tx_complete flag in
- *    the TX descriptor Structure.
- * 2. For each packet with a Tx Complete field set, the firmware adds the
- *    transmit results to the cyclic buffer (txDoneRing) and sets both done_1
- *    and done_2 to 1 to indicate driver ownership.
- * 3. The firmware sends a Tx Complete interrupt to the host to trigger the
- *    host to process the new data. Note: interrupt will be send per packet if
- *    TX complete indication was requested in tx_control or per crossing
- *    aggregation threshold.
- * 4. After receiving the Tx Complete interrupt, the host reads the
- *    TxDescriptorDone information in a cyclic manner and clears both done_1
- *    and done_2 fields.
- *
- */
-
-#define TX_COMPLETE_REQUIRED_BIT	0x80
-#define TX_STATUS_DATA_OUT_COUNT_MASK   0xf
-
-#define WL1251_TX_ALIGN_TO 4
-#define WL1251_TX_ALIGN(len) (((len) + WL1251_TX_ALIGN_TO - 1) & \
-			     ~(WL1251_TX_ALIGN_TO - 1))
-#define WL1251_TKIP_IV_SPACE 4
-
-struct tx_control {
-	/* Rate Policy (class) index */
-	unsigned rate_policy:3;
-
-	/* When set, no ack policy is expected */
-	unsigned ack_policy:1;
-
-	/*
-	 * Packet type:
-	 * 0 -> 802.11
-	 * 1 -> 802.3
-	 * 2 -> IP
-	 * 3 -> raw codec
-	 */
-	unsigned packet_type:2;
-
-	/* If set, this is a QoS-Null or QoS-Data frame */
-	unsigned qos:1;
-
-	/*
-	 * If set, the target triggers the tx complete INT
-	 * upon frame sending completion.
-	 */
-	unsigned tx_complete:1;
-
-	/* 2 bytes padding before packet header */
-	unsigned xfer_pad:1;
-
-	unsigned reserved:7;
-} __packed;
-
-
-struct tx_double_buffer_desc {
-	/* Length of payload, including headers. */
-	__le16 length;
-
-	/*
-	 * A bit mask that specifies the initial rate to be used
-	 * Possible values are:
-	 * 0x0001 - 1Mbits
-	 * 0x0002 - 2Mbits
-	 * 0x0004 - 5.5Mbits
-	 * 0x0008 - 6Mbits
-	 * 0x0010 - 9Mbits
-	 * 0x0020 - 11Mbits
-	 * 0x0040 - 12Mbits
-	 * 0x0080 - 18Mbits
-	 * 0x0100 - 22Mbits
-	 * 0x0200 - 24Mbits
-	 * 0x0400 - 36Mbits
-	 * 0x0800 - 48Mbits
-	 * 0x1000 - 54Mbits
-	 */
-	__le16 rate;
-
-	/* Time in us that a packet can spend in the target */
-	__le32 expiry_time;
-
-	/* index of the TX queue used for this packet */
-	u8 xmit_queue;
-
-	/* Used to identify a packet */
-	u8 id;
-
-	struct tx_control control;
-
-	/*
-	 * The FW should cut the packet into fragments
-	 * of this size.
-	 */
-	__le16 frag_threshold;
-
-	/* Numbers of HW queue blocks to be allocated */
-	u8 num_mem_blocks;
-
-	u8 reserved;
-} __packed;
-
-enum {
-	TX_SUCCESS              = 0,
-	TX_DMA_ERROR            = BIT(7),
-	TX_DISABLED             = BIT(6),
-	TX_RETRY_EXCEEDED       = BIT(5),
-	TX_TIMEOUT              = BIT(4),
-	TX_KEY_NOT_FOUND        = BIT(3),
-	TX_ENCRYPT_FAIL         = BIT(2),
-	TX_UNAVAILABLE_PRIORITY = BIT(1),
-};
-
-struct tx_result {
-	/*
-	 * Ownership synchronization between the host and
-	 * the firmware. If done_1 and done_2 are cleared,
-	 * owned by the FW (no info ready).
-	 */
-	u8 done_1;
-
-	/* same as double_buffer_desc->id */
-	u8 id;
-
-	/*
-	 * Total air access duration consumed by this
-	 * packet, including all retries and overheads.
-	 */
-	u16 medium_usage;
-
-	/* Total media delay (from 1st EDCA AIFS counter until TX Complete). */
-	u32 medium_delay;
-
-	/* Time between host xfer and tx complete */
-	u32 fw_hnadling_time;
-
-	/* The LS-byte of the last TKIP sequence number. */
-	u8 lsb_seq_num;
-
-	/* Retry count */
-	u8 ack_failures;
-
-	/* At which rate we got a ACK */
-	u16 rate;
-
-	u16 reserved;
-
-	/* TX_* */
-	u8 status;
-
-	/* See done_1 */
-	u8 done_2;
-} __packed;
-
-static inline int wl1251_tx_get_queue(int queue)
-{
-	switch (queue) {
-	case 0:
-		return QOS_AC_VO;
-	case 1:
-		return QOS_AC_VI;
-	case 2:
-		return QOS_AC_BE;
-	case 3:
-		return QOS_AC_BK;
-	default:
-		return QOS_AC_BE;
-	}
-}
-
-void wl1251_tx_work(struct work_struct *work);
-void wl1251_tx_complete(struct wl1251 *wl);
-void wl1251_tx_flush(struct wl1251 *wl);
-
-#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index dd3cee6..8a4cd76 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -117,10 +117,7 @@
 #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
 #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
 
-/*
- * Enable/disable 802.11a support for WL1273
- */
-#undef WL1271_80211A_ENABLED
+#define WL1271_CIPHER_SUITE_GEM 0x00147201
 
 #define WL1271_BUSY_WORD_CNT 1
 #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
@@ -133,6 +130,8 @@
 
 #define ACX_TX_DESCRIPTORS         32
 
+#define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
+
 enum wl1271_state {
 	WL1271_STATE_OFF,
 	WL1271_STATE_ON,
@@ -301,6 +300,7 @@
 struct wl1271_scan {
 	struct cfg80211_scan_request *req;
 	bool *scanned_ch;
+	bool failed;
 	u8 state;
 	u8 ssid[IW_ESSID_MAX_SIZE+1];
 	size_t ssid_len;
@@ -313,7 +313,7 @@
 		     bool fixed);
 	void (*reset)(struct wl1271 *wl);
 	void (*init)(struct wl1271 *wl);
-	void (*power)(struct wl1271 *wl, bool enable);
+	int (*power)(struct wl1271 *wl, bool enable);
 	struct device* (*dev)(struct wl1271 *wl);
 	void (*enable_irq)(struct wl1271 *wl);
 	void (*disable_irq)(struct wl1271 *wl);
@@ -330,6 +330,7 @@
 
 	void (*set_power)(bool enable);
 	int irq;
+	int ref_clock;
 
 	spinlock_t wl_lock;
 
@@ -349,6 +350,7 @@
 #define WL1271_FLAG_IDLE              (10)
 #define WL1271_FLAG_IDLE_REQUESTED    (11)
 #define WL1271_FLAG_PSPOLL_FAILURE    (12)
+#define WL1271_FLAG_STA_STATE_SENT    (13)
 	unsigned long flags;
 
 	struct wl1271_partition_set part;
@@ -361,6 +363,7 @@
 	u8 *fw;
 	size_t fw_len;
 	struct wl1271_nvs_file *nvs;
+	size_t nvs_len;
 
 	s8 hw_pg_ver;
 
@@ -407,9 +410,15 @@
 	/* Rx memory pool address */
 	struct wl1271_rx_mem_pool_addr rx_mem_pool_addr;
 
+	/* Intermediate buffer, used for packet aggregation */
+	u8 *aggr_buf;
+
 	/* The target interrupt mask */
 	struct work_struct irq_work;
 
+	/* Hardware recovery work */
+	struct work_struct recovery_work;
+
 	/* The mbox event mask */
 	u32 event_mask;
 
@@ -418,6 +427,7 @@
 
 	/* Are we currently scanning */
 	struct wl1271_scan scan;
+	struct delayed_work scan_complete_work;
 
 	/* Our association ID */
 	u16 aid;
@@ -474,6 +484,8 @@
 
 	bool sg_enabled;
 
+	bool enable_11a;
+
 	struct list_head list;
 
 	/* Most recently reported noise in dBm */
@@ -497,14 +509,4 @@
 #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */
 #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */
 
-static inline bool wl1271_11a_enabled(void)
-{
-	/* FIXME: this could be determined based on the NVS-INI file */
-#ifdef WL1271_80211A_ENABLED
-	return true;
-#else
-	return false;
-#endif
-}
-
 #endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index bb245f0..6189934 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -86,40 +86,6 @@
 	return ret;
 }
 
-int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len)
-{
-	struct acx_revision *rev;
-	int ret;
-
-	wl1271_debug(DEBUG_ACX, "acx fw rev");
-
-	rev = kzalloc(sizeof(*rev), GFP_KERNEL);
-	if (!rev) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
-	if (ret < 0) {
-		wl1271_warning("ACX_FW_REV interrogate failed");
-		goto out;
-	}
-
-	/* be careful with the buffer sizes */
-	strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
-
-	/*
-	 * if the firmware version string is exactly
-	 * sizeof(rev->fw_version) long or fw_len is less than
-	 * sizeof(rev->fw_version) it won't be null terminated
-	 */
-	buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
-
-out:
-	kfree(rev);
-	return ret;
-}
-
 int wl1271_acx_tx_power(struct wl1271 *wl, int power)
 {
 	struct acx_current_tx_power *acx;
@@ -269,7 +235,7 @@
 
 out:
 	kfree(pd);
-	return 0;
+	return ret;
 }
 
 int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 4235bc5..ebb341d 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -100,35 +100,6 @@
 	__le32 seq_num_miss;
 } __packed;
 
-struct acx_revision {
-	struct acx_header header;
-
-	/*
-	 * The WiLink firmware version, an ASCII string x.x.x.x,
-	 * that uniquely identifies the current firmware.
-	 * The left most digit is incremented each time a
-	 * significant change is made to the firmware, such as
-	 * code redesign or new platform support.
-	 * The second digit is incremented when major enhancements
-	 * are added or major fixes are made.
-	 * The third digit is incremented for each GA release.
-	 * The fourth digit is incremented for each build.
-	 * The first two digits identify a firmware release version,
-	 * in other words, a unique set of features.
-	 * The first three digits identify a GA release.
-	 */
-	char fw_version[20];
-
-	/*
-	 * This 4 byte field specifies the WiLink hardware version.
-	 * bits 0  - 15: Reserved.
-	 * bits 16 - 23: Version ID - The WiLink version ID
-	 *              (1 = first spin, 2 = second spin, and so on).
-	 * bits 24 - 31: Chip ID - The WiLink chip ID.
-	 */
-	__le32 hw_version;
-} __packed;
-
 enum wl1271_psm_mode {
 	/* Active mode */
 	WL1271_PSM_CAM = 0,
@@ -1060,7 +1031,6 @@
 	ACX_PEER_HT_CAP             = 0x0057,
 	ACX_HT_BSS_OPERATION        = 0x0058,
 	ACX_COEX_ACTIVITY           = 0x0059,
-	ACX_SET_SMART_REFLEX_DEBUG  = 0x005A,
 	ACX_SET_DCO_ITRIM_PARAMS    = 0x0061,
 	DOT11_RX_MSDU_LIFE_TIME     = 0x1004,
 	DOT11_CUR_TX_PWR            = 0x100D,
@@ -1077,7 +1047,6 @@
 
 int wl1271_acx_wake_up_conditions(struct wl1271 *wl);
 int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth);
-int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len);
 int wl1271_acx_tx_power(struct wl1271 *wl, int power);
 int wl1271_acx_feature_cfg(struct wl1271 *wl);
 int wl1271_acx_mem_map(struct wl1271 *wl,
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index f36430b..b910212 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -225,6 +225,28 @@
 	if (wl->nvs == NULL)
 		return -ENODEV;
 
+	/*
+	 * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
+	 * configurations) can be removed when those NVS files stop floating
+	 * around.
+	 */
+	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)
+			wl->enable_11a = true;
+	}
+
+	if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
+	    (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
+	     wl->enable_11a)) {
+		wl1271_error("nvs size is not as expected: %zu != %zu",
+			     wl->nvs_len, sizeof(struct wl1271_nvs_file));
+		kfree(wl->nvs);
+		wl->nvs = NULL;
+		wl->nvs_len = 0;
+		return -EILSEQ;
+	}
+
 	/* only the first part of the NVS needs to be uploaded */
 	nvs_len = sizeof(wl->nvs->nvs);
 	nvs_ptr = (u8 *)wl->nvs->nvs;
@@ -251,8 +273,10 @@
 		burst_len = nvs_ptr[0];
 		dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
 
-		/* FIXME: Due to our new wl1271_translate_reg_addr function,
-		   we need to add the REGISTER_BASE to the destination */
+		/*
+		 * Due to our new wl1271_translate_reg_addr function,
+		 * we need to add the REGISTER_BASE to the destination
+		 */
 		dest_addr += REGISTERS_BASE;
 
 		/* We move our pointer to the data */
@@ -274,31 +298,21 @@
 
 	/*
 	 * We've reached the first zero length, the first NVS table
-	 * is 7 bytes further.
+	 * is located at an aligned offset which is at least 7 bytes further.
 	 */
-	nvs_ptr += 7;
+	nvs_ptr = (u8 *)wl->nvs->nvs +
+			ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4);
 	nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs;
-	nvs_len = ALIGN(nvs_len, 4);
 
-	/* FIXME: The driver sets the partition here, but this is not needed,
-	   since it sets to the same one as currently in use */
 	/* Now we must set the partition correctly */
 	wl1271_set_partition(wl, &part_table[PART_WORK]);
 
 	/* Copy the NVS tables to a new block to ensure alignment */
-	/* FIXME: We jump 3 more bytes before uploading the NVS.  It seems
-	that our NVS files have three extra zeros here.  I'm not sure whether
-	the problem is in our NVS generation or we should really jumpt these
-	3 bytes here */
-	nvs_ptr += 3;
-
-	nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if
-	(!nvs_aligned) return -ENOMEM;
+	nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
+	if (!nvs_aligned)
+		return -ENOMEM;
 
 	/* And finally we upload the NVS tables */
-	/* FIXME: In wl1271, we upload everything at once.
-	   No endianness handling needed here?! The ref driver doesn't do
-	   anything about it at this point */
 	wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
 
 	kfree(nvs_aligned);
@@ -457,17 +471,20 @@
 {
 	int ret = 0;
 	u32 tmp, clk, pause;
+	int ref_clock = wl->ref_clock;
 
 	wl1271_boot_hw_version(wl);
 
-	if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4)
+	if (ref_clock == 0 || ref_clock == 2 || ref_clock == 4)
 		/* ref clk: 19.2/38.4/38.4-XTAL */
 		clk = 0x3;
-	else if (REF_CLOCK == 1 || REF_CLOCK == 3)
+	else if (ref_clock == 1 || ref_clock == 3)
 		/* ref clk: 26/52 */
 		clk = 0x5;
+	else
+		return -EINVAL;
 
-	if (REF_CLOCK != 0) {
+	if (ref_clock != 0) {
 		u16 val;
 		/* Set clock type (open drain) */
 		val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE);
@@ -493,10 +510,7 @@
 
 	wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
 
-	pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be
-					   * WU_COUNTER_PAUSE_VAL instead of
-					   * 0x3ff (magic number ).  How does
-					   * this work?! */
+	pause &= ~(WU_COUNTER_PAUSE_VAL);
 	pause |= WU_COUNTER_PAUSE_VAL;
 	wl1271_write32(wl, WU_COUNTER_PAUSE, pause);
 
@@ -516,7 +530,7 @@
 	wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
 
 	/* 2 */
-	clk |= (REF_CLOCK << 1) << 4;
+	clk |= (ref_clock << 1) << 4;
 	wl1271_write32(wl, DRPW_SCRATCH_START, clk);
 
 	wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -550,7 +564,6 @@
 	if (ret < 0)
 		goto out;
 
-	/* FIXME: Need to check whether this is really what we want */
 	wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
 		       WL1271_ACX_ALL_EVENTS_VECTOR);
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h
index f829699..f73b0b1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.h
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.h
@@ -46,7 +46,6 @@
 /* delay between retries */
 #define INIT_LOOP_DELAY 50
 
-#define REF_CLOCK            2
 #define WU_COUNTER_PAUSE_VAL 0x3FF
 #define WELP_ARM_COMMAND_VAL 0x4
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index ce503dd..5d3e848 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -94,6 +94,7 @@
 	status = le16_to_cpu(cmd->status);
 	if (status != CMD_STATUS_SUCCESS) {
 		wl1271_error("command execute failure %d", status);
+		ieee80211_queue_work(wl->hw, &wl->recovery_work);
 		ret = -EIO;
 	}
 
@@ -107,6 +108,8 @@
 int wl1271_cmd_general_parms(struct wl1271 *wl)
 {
 	struct wl1271_general_parms_cmd *gen_parms;
+	struct wl1271_ini_general_params *gp = &wl->nvs->general_params;
+	bool answer = false;
 	int ret;
 
 	if (!wl->nvs)
@@ -118,13 +121,24 @@
 
 	gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
 
-	memcpy(&gen_parms->general_params, &wl->nvs->general_params,
-	       sizeof(struct wl1271_ini_general_params));
+	memcpy(&gen_parms->general_params, gp, sizeof(*gp));
 
-	ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
-	if (ret < 0)
+	if (gp->tx_bip_fem_auto_detect)
+		answer = true;
+
+	ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
+	if (ret < 0) {
 		wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
+		goto out;
+	}
 
+	gp->tx_bip_fem_manufacturer =
+		gen_parms->general_params.tx_bip_fem_manufacturer;
+
+	wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
+		     answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);
+
+out:
 	kfree(gen_parms);
 	return ret;
 }
@@ -170,6 +184,39 @@
 	return ret;
 }
 
+int wl1271_cmd_ext_radio_parms(struct wl1271 *wl)
+{
+	struct wl1271_ext_radio_parms_cmd *ext_radio_parms;
+	struct conf_rf_settings *rf = &wl->conf.rf;
+	int ret;
+
+	if (!wl->nvs)
+		return -ENODEV;
+
+	ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL);
+	if (!ext_radio_parms)
+		return -ENOMEM;
+
+	ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM;
+
+	memcpy(ext_radio_parms->tx_per_channel_power_compensation_2,
+	       rf->tx_per_channel_power_compensation_2,
+	       CONF_TX_PWR_COMPENSATION_LEN_2);
+	memcpy(ext_radio_parms->tx_per_channel_power_compensation_5,
+	       rf->tx_per_channel_power_compensation_5,
+	       CONF_TX_PWR_COMPENSATION_LEN_5);
+
+	wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ",
+		    ext_radio_parms, sizeof(*ext_radio_parms));
+
+	ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0);
+	if (ret < 0)
+		wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed");
+
+	kfree(ext_radio_parms);
+	return ret;
+}
+
 /*
  * Poll the mailbox event field until any of the bits in the mask is set or a
  * timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
@@ -182,8 +229,10 @@
 	timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
 
 	do {
-		if (time_after(jiffies, timeout))
+		if (time_after(jiffies, timeout)) {
+			ieee80211_queue_work(wl->hw, &wl->recovery_work);
 			return -ETIMEDOUT;
+		}
 
 		msleep(1);
 
@@ -390,18 +439,11 @@
 	return ret;
 }
 
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
 {
 	struct wl1271_cmd_ps_params *ps_params = NULL;
 	int ret = 0;
 
-	/* FIXME: this should be in ps.c */
-	ret = wl1271_acx_wake_up_conditions(wl);
-	if (ret < 0) {
-		wl1271_error("couldn't set wake up conditions");
-		goto out;
-	}
-
 	wl1271_debug(DEBUG_CMD, "cmd set ps mode");
 
 	ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
@@ -412,9 +454,9 @@
 
 	ps_params->ps_mode = ps_mode;
 	ps_params->send_null_data = send;
-	ps_params->retries = 5;
-	ps_params->hang_over_period = 1;
-	ps_params->null_data_rate = cpu_to_le32(wl->basic_rate_set);
+	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);
@@ -428,41 +470,6 @@
 	return ret;
 }
 
-int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
-			   size_t len)
-{
-	struct cmd_read_write_memory *cmd;
-	int ret = 0;
-
-	wl1271_debug(DEBUG_CMD, "cmd read memory");
-
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-	if (!cmd) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	WARN_ON(len > MAX_READ_SIZE);
-	len = min_t(size_t, len, MAX_READ_SIZE);
-
-	cmd->addr = cpu_to_le32(addr);
-	cmd->size = cpu_to_le32(len);
-
-	ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd),
-			      sizeof(*cmd));
-	if (ret < 0) {
-		wl1271_error("read memory command failed: %d", ret);
-		goto out;
-	}
-
-	/* the read command got in */
-	memcpy(answer, cmd->value, len);
-
-out:
-	kfree(cmd);
-	return ret;
-}
-
 int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
 			    void *buf, size_t buf_len, int index, u32 rates)
 {
@@ -523,7 +530,7 @@
 	}
 
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0,
-				      WL1271_RATE_AUTOMATIC);
+				      wl->basic_rate);
 
 out:
 	dev_kfree_skb(skb);
@@ -546,7 +553,7 @@
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV,
 				      skb->data, skb->len,
 				      CMD_TEMPL_KLV_IDX_NULL_DATA,
-				      WL1271_RATE_AUTOMATIC);
+				      wl->basic_rate);
 
 out:
 	dev_kfree_skb(skb);
@@ -623,7 +630,7 @@
 
 	return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template,
 				       sizeof(template), 0,
-				       WL1271_RATE_AUTOMATIC);
+				       wl->basic_rate);
 }
 
 int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
@@ -746,3 +753,31 @@
 out:
 	return ret;
 }
+
+int wl1271_cmd_set_sta_state(struct wl1271 *wl)
+{
+	struct wl1271_cmd_set_sta_state *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd set sta state");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->state = WL1271_CMD_STA_STATE_CONNECTED;
+
+	ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to send set STA state command");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index af577ee..a0caf4f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -33,12 +33,13 @@
 		    size_t res_len);
 int wl1271_cmd_general_parms(struct wl1271 *wl);
 int wl1271_cmd_radio_parms(struct wl1271 *wl);
+int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
 int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type);
 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, bool send);
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send);
 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,
@@ -55,6 +56,7 @@
 		       u8 key_size, const u8 *key, const u8 *addr,
 		       u32 tx_seq_32, u16 tx_seq_16);
 int wl1271_cmd_disconnect(struct wl1271 *wl);
+int wl1271_cmd_set_sta_state(struct wl1271 *wl);
 
 enum wl1271_commands {
 	CMD_INTERROGATE     = 1,    /*use this to read information elements*/
@@ -160,41 +162,6 @@
 	MAX_COMMAND_STATUS		= 0xff
 };
 
-
-/*
- * CMD_READ_MEMORY
- *
- * The host issues this command to read the WiLink device memory/registers.
- *
- * Note: The Base Band address has special handling (16 bits registers and
- * addresses). For more information, see the hardware specification.
- */
-/*
- * CMD_WRITE_MEMORY
- *
- * The host issues this command to write the WiLink device memory/registers.
- *
- * The Base Band address has special handling (16 bits registers and
- * addresses). For more information, see the hardware specification.
- */
-#define MAX_READ_SIZE 256
-
-struct cmd_read_write_memory {
-	struct wl1271_cmd_header header;
-
-	/* The address of the memory to read from or write to.*/
-	__le32 addr;
-
-	/* The amount of data in bytes to read from or write to the WiLink
-	 * device.*/
-	__le32 size;
-
-	/* The actual value read from or written to the Wilink. The source
-	   of this field is the Host in WRITE command or the Wilink in READ
-	   command. */
-	u8 value[MAX_READ_SIZE];
-} __packed;
-
 #define CMDMBOX_HEADER_LEN 4
 #define CMDMBOX_INFO_ELEM_HEADER_LEN 4
 
@@ -313,7 +280,7 @@
 	KEY_WEP  = 1,
 	KEY_TKIP = 2,
 	KEY_AES  = 3,
-	KEY_GEM  = 4
+	KEY_GEM  = 4,
 };
 
 /* FIXME: Add description for key-types */
@@ -358,13 +325,14 @@
 	WL1271_CHANNEL_TUNE_BAND_4_9
 };
 
-#define WL1271_PD_REFERENCE_POINT_BAND_B_G 0
+#define WL1271_PD_REFERENCE_POINT_BAND_B_G  0
 
-#define TEST_CMD_P2G_CAL                   0x02
-#define TEST_CMD_CHANNEL_TUNE              0x0d
-#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d
-#define TEST_CMD_INI_FILE_RADIO_PARAM      0x19
-#define TEST_CMD_INI_FILE_GENERAL_PARAM    0x1E
+#define TEST_CMD_P2G_CAL                    0x02
+#define TEST_CMD_CHANNEL_TUNE               0x0d
+#define TEST_CMD_UPDATE_PD_REFERENCE_POINT  0x1d
+#define TEST_CMD_INI_FILE_RADIO_PARAM       0x19
+#define TEST_CMD_INI_FILE_GENERAL_PARAM     0x1E
+#define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26
 
 struct wl1271_general_parms_cmd {
 	struct wl1271_cmd_header header;
@@ -397,6 +365,16 @@
 	u8 padding3[2];
 } __packed;
 
+struct wl1271_ext_radio_parms_cmd {
+	struct wl1271_cmd_header header;
+
+	struct wl1271_cmd_test_header test;
+
+	u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
+	u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
+	u8 padding[3];
+} __packed;
+
 struct wl1271_cmd_cal_channel_tune {
 	struct wl1271_cmd_header header;
 
@@ -469,4 +447,13 @@
 	u8  padding;
 } __packed;
 
+#define WL1271_CMD_STA_STATE_CONNECTED  1
+
+struct wl1271_cmd_set_sta_state {
+	struct wl1271_cmd_header header;
+
+	u8 state;
+	u8 padding[3];
+} __packed;
+
 #endif /* __WL1271_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index 0435ffd..5f78a6c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -595,7 +595,7 @@
 	u16 tx_op_limit;
 };
 
-#define CONF_TX_MAX_TID_COUNT 7
+#define CONF_TX_MAX_TID_COUNT 8
 
 enum {
 	CONF_CHANNEL_TYPE_DCF = 0,   /* DC/LEGACY*/
@@ -912,6 +912,22 @@
 	u8 psm_entry_retries;
 
 	/*
+	 * Specifies the maximum number of times to try transmit the PSM entry
+	 * null-func frame for each PSM entry attempt
+	 *
+	 * Range 0 - 255
+	 */
+	u8 psm_entry_nullfunc_retries;
+
+	/*
+	 * Specifies the time to linger in active mode after successfully
+	 * transmitting the PSM entry null-func frame.
+	 *
+	 * Range 0 - 255 TU's
+	 */
+	u8 psm_entry_hangover_period;
+
+	/*
 	 *
 	 * Specifies the interval of the connection keep-alive null-func
 	 * frame in ms.
@@ -1016,6 +1032,64 @@
 	u8 avg_weight_snr_data;
 };
 
+struct conf_scan_settings {
+	/*
+	 * The minimum time to wait on each channel for active scans
+	 *
+	 * Range: 0 - 65536 tu
+	 */
+	u16 min_dwell_time_active;
+
+	/*
+	 * The maximum time to wait on each channel for active scans
+	 *
+	 * Range: 0 - 65536 tu
+	 */
+	u16 max_dwell_time_active;
+
+	/*
+	 * The maximum time to wait on each channel for passive scans
+	 *
+	 * Range: 0 - 65536 tu
+	 */
+	u16 min_dwell_time_passive;
+
+	/*
+	 * The maximum time to wait on each channel for passive scans
+	 *
+	 * Range: 0 - 65536 tu
+	 */
+	u16 max_dwell_time_passive;
+
+	/*
+	 * Number of probe requests to transmit on each active scan channel
+	 *
+	 * Range: u8
+	 */
+	u16 num_probe_reqs;
+
+};
+
+/* these are number of channels on the band divided by two, rounded up */
+#define CONF_TX_PWR_COMPENSATION_LEN_2 7
+#define CONF_TX_PWR_COMPENSATION_LEN_5 18
+
+struct conf_rf_settings {
+	/*
+	 * Per channel power compensation for 2.4GHz
+	 *
+	 * Range: s8
+	 */
+	u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
+
+	/*
+	 * Per channel power compensation for 5GHz
+	 *
+	 * Range: s8
+	 */
+	u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
+};
+
 struct conf_drv_settings {
 	struct conf_sg_settings sg;
 	struct conf_rx_settings rx;
@@ -1024,6 +1098,8 @@
 	struct conf_itrim_settings itrim;
 	struct conf_pm_config_settings pm_config;
 	struct conf_roam_trigger_settings roam_trigger;
+	struct conf_scan_settings scan;
+	struct conf_rf_settings rf;
 };
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
index c239ef4..66c2b90 100644
--- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c
+++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
@@ -51,6 +51,7 @@
 static const struct file_operations name## _ops = {			\
 	.read = name## _read,						\
 	.open = wl1271_open_file_generic,				\
+	.llseek	= generic_file_llseek,					\
 };
 
 #define DEBUGFS_ADD(name, parent)					\
@@ -87,6 +88,7 @@
 static const struct file_operations sub## _ ##name## _ops = {		\
 	.read = sub## _ ##name## _read,					\
 	.open = wl1271_open_file_generic,				\
+	.llseek	= generic_file_llseek,					\
 };
 
 #define DEBUGFS_FWSTATS_ADD(sub, name)				\
@@ -237,6 +239,7 @@
 static const struct file_operations tx_queue_len_ops = {
 	.read = tx_queue_len_read,
 	.open = wl1271_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t gpio_power_read(struct file *file, char __user *user_buf,
@@ -291,7 +294,8 @@
 static const struct file_operations gpio_power_ops = {
 	.read = gpio_power_read,
 	.write = gpio_power_write,
-	.open = wl1271_open_file_generic
+	.open = wl1271_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static void wl1271_debugfs_delete_files(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index 25ce2cd..7b3f503 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -41,6 +41,9 @@
 
 	mutex_lock(&wl->mutex);
 
+	if (unlikely(wl->state == WL1271_STATE_OFF))
+		goto out;
+
 	if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags))
 		goto out;
 
@@ -52,7 +55,7 @@
 	 * delivery failure occurred, and no-one changed state since, so
 	 * we should go back to powersave.
 	 */
-	wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true);
+	wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true);
 
 out:
 	mutex_unlock(&wl->mutex);
@@ -70,7 +73,8 @@
 
 	/* force active mode receive data from the AP */
 	if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
-		ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, true);
+		ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
+					 wl->basic_rate, true);
 		if (ret < 0)
 			return;
 		set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags);
@@ -91,6 +95,7 @@
 				  bool *beacon_loss)
 {
 	int ret = 0;
+	u32 total_retries = wl->conf.conn.psm_entry_retries;
 
 	wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status);
 
@@ -104,10 +109,10 @@
 			break;
 		}
 
-		if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) {
+		if (wl->psm_entry_retry < total_retries) {
 			wl->psm_entry_retry++;
 			ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
-						 true);
+						 wl->basic_rate, true);
 		} else {
 			wl1271_info("No ack to nullfunc from AP.");
 			wl->psm_entry_retry = 0;
@@ -143,7 +148,7 @@
 		/* 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,
-					 false);
+					 wl->basic_rate, false);
 		break;
 	case EVENT_EXIT_POWER_SAVE_SUCCESS:
 	default:
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 4447af1..8044bba 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -53,6 +53,7 @@
 int wl1271_init_templates_config(struct wl1271 *wl)
 {
 	int ret, i;
+	size_t size;
 
 	/* send empty templates for fw memory reservation */
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
@@ -61,14 +62,12 @@
 	if (ret < 0)
 		return ret;
 
-	if (wl1271_11a_enabled()) {
-		size_t size = sizeof(struct wl12xx_probe_req_template);
-		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
-					      NULL, size, 0,
-					      WL1271_RATE_AUTOMATIC);
-		if (ret < 0)
-			return ret;
-	}
+	size = sizeof(struct wl12xx_probe_req_template);
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
+				      NULL, size, 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),
@@ -223,6 +222,10 @@
 	if (ret < 0)
 		return ret;
 
+	ret = wl1271_cmd_ext_radio_parms(wl);
+	if (ret < 0)
+		return ret;
+
 	/* Template settings */
 	ret = wl1271_init_templates_config(wl);
 	if (ret < 0)
@@ -291,8 +294,16 @@
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Default TID configuration */
+	/* Default TID/AC configuration */
+	BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
 	for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
+		conf_ac = &wl->conf.tx.ac_conf[i];
+		ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
+					conf_ac->cw_max, conf_ac->aifsn,
+					conf_ac->tx_op_limit);
+		if (ret < 0)
+			goto out_free_memmap;
+
 		conf_tid = &wl->conf.tx.tid_conf[i];
 		ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
 					 conf_tid->channel_type,
@@ -305,16 +316,6 @@
 			goto out_free_memmap;
 	}
 
-	/* Default AC configuration */
-	for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
-		conf_ac = &wl->conf.tx.ac_conf[i];
-		ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
-					conf_ac->cw_max, conf_ac->aifsn,
-					conf_ac->tx_op_limit);
-		if (ret < 0)
-			goto out_free_memmap;
-	}
-
 	/* Configure TX rate classes */
 	ret = wl1271_acx_rate_policies(wl);
 	if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h
index bc806c7..c1f92e6 100644
--- a/drivers/net/wireless/wl12xx/wl1271_io.h
+++ b/drivers/net/wireless/wl12xx/wl1271_io.h
@@ -144,10 +144,13 @@
 	clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
 }
 
-static inline void wl1271_power_on(struct wl1271 *wl)
+static inline int wl1271_power_on(struct wl1271 *wl)
 {
-	wl->if_ops->power(wl, true);
-	set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+	int ret = wl->if_ops->power(wl, true);
+	if (ret == 0)
+		set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+
+	return ret;
 }
 
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 9d68f00..48a4b99 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -124,28 +124,28 @@
 		},
 		.ac_conf_count               = 4,
 		.ac_conf                     = {
-			[0] = {
+			[CONF_TX_AC_BE] = {
 				.ac          = CONF_TX_AC_BE,
 				.cw_min      = 15,
 				.cw_max      = 63,
 				.aifsn       = 3,
 				.tx_op_limit = 0,
 			},
-			[1] = {
+			[CONF_TX_AC_BK] = {
 				.ac          = CONF_TX_AC_BK,
 				.cw_min      = 15,
 				.cw_max      = 63,
 				.aifsn       = 7,
 				.tx_op_limit = 0,
 			},
-			[2] = {
+			[CONF_TX_AC_VI] = {
 				.ac          = CONF_TX_AC_VI,
 				.cw_min      = 15,
 				.cw_max      = 63,
 				.aifsn       = CONF_TX_AIFS_PIFS,
 				.tx_op_limit = 3008,
 			},
-			[3] = {
+			[CONF_TX_AC_VO] = {
 				.ac          = CONF_TX_AC_VO,
 				.cw_min      = 15,
 				.cw_max      = 63,
@@ -153,64 +153,40 @@
 				.tx_op_limit = 1504,
 			},
 		},
-		.tid_conf_count = 7,
+		.tid_conf_count = 4,
 		.tid_conf = {
-			[0] = {
-				.queue_id    = 0,
-				.channel_type = CONF_CHANNEL_TYPE_DCF,
+			[CONF_TX_AC_BE] = {
+				.queue_id    = CONF_TX_AC_BE,
+				.channel_type = CONF_CHANNEL_TYPE_EDCF,
 				.tsid        = CONF_TX_AC_BE,
 				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
 				.ack_policy  = CONF_ACK_POLICY_LEGACY,
 				.apsd_conf   = {0, 0},
 			},
-			[1] = {
-				.queue_id    = 1,
-				.channel_type = CONF_CHANNEL_TYPE_DCF,
-				.tsid        = CONF_TX_AC_BE,
+			[CONF_TX_AC_BK] = {
+				.queue_id    = CONF_TX_AC_BK,
+				.channel_type = CONF_CHANNEL_TYPE_EDCF,
+				.tsid        = CONF_TX_AC_BK,
 				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
 				.ack_policy  = CONF_ACK_POLICY_LEGACY,
 				.apsd_conf   = {0, 0},
 			},
-			[2] = {
-				.queue_id    = 2,
-				.channel_type = CONF_CHANNEL_TYPE_DCF,
-				.tsid        = CONF_TX_AC_BE,
+			[CONF_TX_AC_VI] = {
+				.queue_id    = CONF_TX_AC_VI,
+				.channel_type = CONF_CHANNEL_TYPE_EDCF,
+				.tsid        = CONF_TX_AC_VI,
 				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
 				.ack_policy  = CONF_ACK_POLICY_LEGACY,
 				.apsd_conf   = {0, 0},
 			},
-			[3] = {
-				.queue_id    = 3,
-				.channel_type = CONF_CHANNEL_TYPE_DCF,
-				.tsid        = CONF_TX_AC_BE,
+			[CONF_TX_AC_VO] = {
+				.queue_id    = CONF_TX_AC_VO,
+				.channel_type = CONF_CHANNEL_TYPE_EDCF,
+				.tsid        = CONF_TX_AC_VO,
 				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
 				.ack_policy  = CONF_ACK_POLICY_LEGACY,
 				.apsd_conf   = {0, 0},
 			},
-			[4] = {
-				.queue_id    = 4,
-				.channel_type = CONF_CHANNEL_TYPE_DCF,
-				.tsid        = CONF_TX_AC_BE,
-				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
-				.ack_policy  = CONF_ACK_POLICY_LEGACY,
-				.apsd_conf   = {0, 0},
-			},
-			[5] = {
-				.queue_id    = 5,
-				.channel_type = CONF_CHANNEL_TYPE_DCF,
-				.tsid        = CONF_TX_AC_BE,
-				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
-				.ack_policy  = CONF_ACK_POLICY_LEGACY,
-				.apsd_conf   = {0, 0},
-			},
-			[6] = {
-				.queue_id    = 6,
-				.channel_type = CONF_CHANNEL_TYPE_DCF,
-				.tsid        = CONF_TX_AC_BE,
-				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
-				.ack_policy  = CONF_ACK_POLICY_LEGACY,
-				.apsd_conf   = {0, 0},
-			}
 		},
 		.frag_threshold              = IEEE80211_MAX_FRAG_THRESHOLD,
 		.tx_compl_timeout            = 700,
@@ -238,7 +214,9 @@
 		.ps_poll_recovery_period     = 700,
 		.bet_enable                  = CONF_BET_MODE_ENABLE,
 		.bet_max_consecutive         = 10,
-		.psm_entry_retries           = 3,
+		.psm_entry_retries           = 5,
+		.psm_entry_nullfunc_retries  = 3,
+		.psm_entry_hangover_period   = 1,
 		.keep_alive_interval         = 55000,
 		.max_listen_interval         = 20,
 	},
@@ -251,15 +229,34 @@
 		.host_fast_wakeup_support = false
 	},
 	.roam_trigger = {
-		/* FIXME: due to firmware bug, must use value 1 for now */
 		.trigger_pacing               = 1,
 		.avg_weight_rssi_beacon       = 20,
 		.avg_weight_rssi_data         = 10,
 		.avg_weight_snr_beacon        = 20,
 		.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,
+		.num_probe_reqs               = 2,
+	},
+	.rf = {
+		.tx_per_channel_power_compensation_2 = {
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+		.tx_per_channel_power_compensation_5 = {
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+	},
 };
 
+static void __wl1271_op_remove_interface(struct wl1271 *wl);
+
+
 static void wl1271_device_release(struct device *dev)
 {
 
@@ -277,6 +274,67 @@
 
 static LIST_HEAD(wl_list);
 
+static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
+			     void *arg)
+{
+	struct net_device *dev = arg;
+	struct wireless_dev *wdev;
+	struct wiphy *wiphy;
+	struct ieee80211_hw *hw;
+	struct wl1271 *wl;
+	struct wl1271 *wl_temp;
+	int ret = 0;
+
+	/* Check that this notification is for us. */
+	if (what != NETDEV_CHANGE)
+		return NOTIFY_DONE;
+
+	wdev = dev->ieee80211_ptr;
+	if (wdev == NULL)
+		return NOTIFY_DONE;
+
+	wiphy = wdev->wiphy;
+	if (wiphy == NULL)
+		return NOTIFY_DONE;
+
+	hw = wiphy_priv(wiphy);
+	if (hw == NULL)
+		return NOTIFY_DONE;
+
+	wl_temp = hw->priv;
+	list_for_each_entry(wl, &wl_list, list) {
+		if (wl == wl_temp)
+			break;
+	}
+	if (wl != wl_temp)
+		return NOTIFY_DONE;
+
+	mutex_lock(&wl->mutex);
+
+	if (wl->state == WL1271_STATE_OFF)
+		goto out;
+
+	if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl, false);
+	if (ret < 0)
+		goto out;
+
+	if ((dev->operstate == IF_OPER_UP) &&
+	    !test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) {
+		wl1271_cmd_set_sta_state(wl);
+		wl1271_info("Association completed.");
+	}
+
+	wl1271_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+
+	return NOTIFY_OK;
+}
+
 static void wl1271_conf_init(struct wl1271 *wl)
 {
 
@@ -309,6 +367,10 @@
 	if (ret < 0)
 		return ret;
 
+	ret = wl1271_cmd_ext_radio_parms(wl);
+	if (ret < 0)
+		return ret;
+
 	ret = wl1271_init_templates_config(wl);
 	if (ret < 0)
 		return ret;
@@ -346,8 +408,16 @@
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Default TID configuration */
+	/* Default TID/AC configuration */
+	BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
 	for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
+		conf_ac = &wl->conf.tx.ac_conf[i];
+		ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
+					conf_ac->cw_max, conf_ac->aifsn,
+					conf_ac->tx_op_limit);
+		if (ret < 0)
+			goto out_free_memmap;
+
 		conf_tid = &wl->conf.tx.tid_conf[i];
 		ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
 					 conf_tid->channel_type,
@@ -360,16 +430,6 @@
 			goto out_free_memmap;
 	}
 
-	/* Default AC configuration */
-	for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
-		conf_ac = &wl->conf.tx.ac_conf[i];
-		ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
-					conf_ac->cw_max, conf_ac->aifsn,
-					conf_ac->tx_op_limit);
-		if (ret < 0)
-			goto out_free_memmap;
-	}
-
 	/* Enable data path */
 	ret = wl1271_cmd_data_path(wl, 1);
 	if (ret < 0)
@@ -562,20 +622,6 @@
 		return ret;
 	}
 
-	/*
-	 * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
-	 * configurations) can be removed when those NVS files stop floating
-	 * around.
-	 */
-	if (fw->size != sizeof(struct wl1271_nvs_file) &&
-	    (fw->size != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
-	     wl1271_11a_enabled())) {
-		wl1271_error("nvs size is not as expected: %zu != %zu",
-			     fw->size, sizeof(struct wl1271_nvs_file));
-		ret = -EILSEQ;
-		goto out;
-	}
-
 	wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL);
 
 	if (!wl->nvs) {
@@ -584,12 +630,37 @@
 		goto out;
 	}
 
+	wl->nvs_len = fw->size;
+
 out:
 	release_firmware(fw);
 
 	return ret;
 }
 
+static void wl1271_recovery_work(struct work_struct *work)
+{
+	struct wl1271 *wl =
+		container_of(work, struct wl1271, recovery_work);
+
+	mutex_lock(&wl->mutex);
+
+	if (wl->state != WL1271_STATE_ON)
+		goto out;
+
+	wl1271_info("Hardware recovery in progress.");
+
+	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+		ieee80211_connection_loss(wl->vif);
+
+	/* reboot the chipset */
+	__wl1271_op_remove_interface(wl);
+	ieee80211_restart_hw(wl->hw);
+
+out:
+	mutex_unlock(&wl->mutex);
+}
+
 static void wl1271_fw_wakeup(struct wl1271 *wl)
 {
 	u32 elp_reg;
@@ -610,8 +681,6 @@
 		return -ENOMEM;
 	}
 
-	INIT_WORK(&wl->irq_work, wl1271_irq_work);
-	INIT_WORK(&wl->tx_work, wl1271_tx_work);
 	return 0;
 }
 
@@ -621,7 +690,9 @@
 	int ret = 0;
 
 	msleep(WL1271_PRE_POWER_ON_SLEEP);
-	wl1271_power_on(wl);
+	ret = wl1271_power_on(wl);
+	if (ret < 0)
+		goto out;
 	msleep(WL1271_POWER_ON_SLEEP);
 	wl1271_io_reset(wl);
 	wl1271_io_init(wl);
@@ -766,10 +837,12 @@
 out:
 	mutex_unlock(&wl->mutex);
 
+	cancel_work_sync(&wl->irq_work);
+	cancel_work_sync(&wl->recovery_work);
+
 	return ret;
 }
 
-
 static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct wl1271 *wl = hw->priv;
@@ -812,6 +885,10 @@
 	return NETDEV_TX_OK;
 }
 
+static struct notifier_block wl1271_dev_notifier = {
+	.notifier_call = wl1271_dev_notify,
+};
+
 static int wl1271_op_start(struct ieee80211_hw *hw)
 {
 	wl1271_debug(DEBUG_MAC80211, "mac80211 start");
@@ -928,13 +1005,10 @@
 	return ret;
 }
 
-static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
-				       struct ieee80211_vif *vif)
+static void __wl1271_op_remove_interface(struct wl1271 *wl)
 {
-	struct wl1271 *wl = hw->priv;
 	int i;
 
-	mutex_lock(&wl->mutex);
 	wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
 
 	wl1271_info("down");
@@ -948,12 +1022,10 @@
 		ieee80211_enable_dyn_ps(wl->vif);
 
 	if (wl->scan.state != WL1271_SCAN_STATE_IDLE) {
-		mutex_unlock(&wl->mutex);
-		ieee80211_scan_completed(wl->hw, true);
-		mutex_lock(&wl->mutex);
 		wl->scan.state = WL1271_SCAN_STATE_IDLE;
 		kfree(wl->scan.scanned_ch);
 		wl->scan.scanned_ch = NULL;
+		ieee80211_scan_completed(wl->hw, true);
 	}
 
 	wl->state = WL1271_STATE_OFF;
@@ -962,9 +1034,11 @@
 
 	mutex_unlock(&wl->mutex);
 
+	cancel_delayed_work_sync(&wl->scan_complete_work);
 	cancel_work_sync(&wl->irq_work);
 	cancel_work_sync(&wl->tx_work);
 	cancel_delayed_work_sync(&wl->pspoll_work);
+	cancel_delayed_work_sync(&wl->elp_work);
 
 	mutex_lock(&wl->mutex);
 
@@ -1006,8 +1080,19 @@
 	wl->tx_res_if = NULL;
 	kfree(wl->target_mem_map);
 	wl->target_mem_map = NULL;
+}
 
+static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif)
+{
+	struct wl1271 *wl = hw->priv;
+
+	mutex_lock(&wl->mutex);
+	WARN_ON(wl->vif != vif);
+	__wl1271_op_remove_interface(wl);
 	mutex_unlock(&wl->mutex);
+
+	cancel_work_sync(&wl->recovery_work);
 }
 
 static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
@@ -1289,7 +1374,7 @@
 		if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
 			wl1271_debug(DEBUG_PSM, "psm enabled");
 			ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
-						 true);
+						 wl->basic_rate, true);
 		}
 	} else if (!(conf->flags & IEEE80211_CONF_PS) &&
 		   test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
@@ -1299,7 +1384,7 @@
 
 		if (test_bit(WL1271_FLAG_PSM, &wl->flags))
 			ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
-						 true);
+						 wl->basic_rate, true);
 	}
 
 	if (conf->power_level != wl->power_level) {
@@ -1439,7 +1524,7 @@
 	wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
 	wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
 	wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
-		     key_conf->alg, key_conf->keyidx,
+		     key_conf->cipher, key_conf->keyidx,
 		     key_conf->keylen, key_conf->flags);
 	wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
 
@@ -1455,28 +1540,34 @@
 	if (ret < 0)
 		goto out_unlock;
 
-	switch (key_conf->alg) {
-	case ALG_WEP:
+	switch (key_conf->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
 		key_type = KEY_WEP;
 
 		key_conf->hw_key_idx = key_conf->keyidx;
 		break;
-	case ALG_TKIP:
+	case WLAN_CIPHER_SUITE_TKIP:
 		key_type = KEY_TKIP;
 
 		key_conf->hw_key_idx = key_conf->keyidx;
 		tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
 		tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
 		break;
-	case ALG_CCMP:
+	case WLAN_CIPHER_SUITE_CCMP:
 		key_type = KEY_AES;
 
 		key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 		tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
 		tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
 		break;
+	case WL1271_CIPHER_SUITE_GEM:
+		key_type = KEY_GEM;
+		tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
+		tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
+		break;
 	default:
-		wl1271_error("Unknown key algo 0x%x", key_conf->alg);
+		wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
 
 		ret = -EOPNOTSUPP;
 		goto out_sleep;
@@ -1558,10 +1649,7 @@
 	if (ret < 0)
 		goto out;
 
-	if (wl1271_11a_enabled())
-		ret = wl1271_scan(hw->priv, ssid, len, req);
-	else
-		ret = wl1271_scan(hw->priv, ssid, len, req);
+	ret = wl1271_scan(hw->priv, ssid, len, req);
 
 	wl1271_ps_elp_sleep(wl);
 
@@ -1633,7 +1721,7 @@
 	if (ret < 0)
 		goto out;
 
-	if ((changed && BSS_CHANGED_BEACON_INT) &&
+	if ((changed & BSS_CHANGED_BEACON_INT) &&
 	    (wl->bss_type == BSS_TYPE_IBSS)) {
 		wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d",
 			bss_conf->beacon_int);
@@ -1642,7 +1730,7 @@
 		do_join = true;
 	}
 
-	if ((changed && BSS_CHANGED_BEACON) &&
+	if ((changed & BSS_CHANGED_BEACON) &&
 	    (wl->bss_type == BSS_TYPE_IBSS)) {
 		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
 
@@ -1776,12 +1864,15 @@
 			if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
 			    !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
 				mode = STATION_POWER_SAVE_MODE;
-				ret = wl1271_ps_set_mode(wl, mode, true);
+				ret = wl1271_ps_set_mode(wl, mode,
+							 wl->basic_rate,
+							 true);
 				if (ret < 0)
 					goto out_sleep;
 			}
 		} else {
 			/* use defaults when not associated */
+			clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags);
 			clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
 			wl->aid = 0;
 
@@ -1993,21 +2084,24 @@
 	  .hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
 };
 
-/* can't be const, mac80211 writes to this */
+/*
+ * Can't be const, mac80211 writes to this. The order of the channels here
+ * is designed to improve scanning.
+ */
 static struct ieee80211_channel wl1271_channels[] = {
 	{ .hw_value = 1, .center_freq = 2412, .max_power = 25 },
-	{ .hw_value = 2, .center_freq = 2417, .max_power = 25 },
-	{ .hw_value = 3, .center_freq = 2422, .max_power = 25 },
-	{ .hw_value = 4, .center_freq = 2427, .max_power = 25 },
 	{ .hw_value = 5, .center_freq = 2432, .max_power = 25 },
-	{ .hw_value = 6, .center_freq = 2437, .max_power = 25 },
-	{ .hw_value = 7, .center_freq = 2442, .max_power = 25 },
-	{ .hw_value = 8, .center_freq = 2447, .max_power = 25 },
 	{ .hw_value = 9, .center_freq = 2452, .max_power = 25 },
-	{ .hw_value = 10, .center_freq = 2457, .max_power = 25 },
-	{ .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 = 4, .center_freq = 2427, .max_power = 25 },
+	{ .hw_value = 8, .center_freq = 2447, .max_power = 25 },
+	{ .hw_value = 12, .center_freq = 2467, .max_power = 25 },
+	{ .hw_value = 3, .center_freq = 2422, .max_power = 25 },
+	{ .hw_value = 7, .center_freq = 2442, .max_power = 25 },
+	{ .hw_value = 11, .center_freq = 2462, .max_power = 25 },
+	{ .hw_value = 2, .center_freq = 2417, .max_power = 25 },
+	{ .hw_value = 6, .center_freq = 2437, .max_power = 25 },
+	{ .hw_value = 10, .center_freq = 2457, .max_power = 25 },
 };
 
 /* mapping to indexes for wl1271_rates */
@@ -2076,49 +2170,52 @@
 	  .hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
 };
 
-/* 5 GHz band channels for WL1273 */
+/*
+ * 5 GHz band channels for WL1273 - can't be const, mac80211 writes to this.
+ * The order of the channels here is designed to improve scanning.
+ */
 static struct ieee80211_channel wl1271_channels_5ghz[] = {
 	{ .hw_value = 183, .center_freq = 4915},
-	{ .hw_value = 184, .center_freq = 4920},
-	{ .hw_value = 185, .center_freq = 4925},
-	{ .hw_value = 187, .center_freq = 4935},
 	{ .hw_value = 188, .center_freq = 4940},
-	{ .hw_value = 189, .center_freq = 4945},
-	{ .hw_value = 192, .center_freq = 4960},
-	{ .hw_value = 196, .center_freq = 4980},
-	{ .hw_value = 7, .center_freq = 5035},
 	{ .hw_value = 8, .center_freq = 5040},
-	{ .hw_value = 9, .center_freq = 5045},
-	{ .hw_value = 11, .center_freq = 5055},
-	{ .hw_value = 12, .center_freq = 5060},
-	{ .hw_value = 16, .center_freq = 5080},
 	{ .hw_value = 34, .center_freq = 5170},
-	{ .hw_value = 36, .center_freq = 5180},
-	{ .hw_value = 38, .center_freq = 5190},
-	{ .hw_value = 40, .center_freq = 5200},
-	{ .hw_value = 42, .center_freq = 5210},
 	{ .hw_value = 44, .center_freq = 5220},
-	{ .hw_value = 46, .center_freq = 5230},
-	{ .hw_value = 48, .center_freq = 5240},
-	{ .hw_value = 52, .center_freq = 5260},
-	{ .hw_value = 56, .center_freq = 5280},
 	{ .hw_value = 60, .center_freq = 5300},
-	{ .hw_value = 64, .center_freq = 5320},
-	{ .hw_value = 100, .center_freq = 5500},
-	{ .hw_value = 104, .center_freq = 5520},
-	{ .hw_value = 108, .center_freq = 5540},
 	{ .hw_value = 112, .center_freq = 5560},
-	{ .hw_value = 116, .center_freq = 5580},
-	{ .hw_value = 120, .center_freq = 5600},
-	{ .hw_value = 124, .center_freq = 5620},
-	{ .hw_value = 128, .center_freq = 5640},
 	{ .hw_value = 132, .center_freq = 5660},
-	{ .hw_value = 136, .center_freq = 5680},
-	{ .hw_value = 140, .center_freq = 5700},
-	{ .hw_value = 149, .center_freq = 5745},
-	{ .hw_value = 153, .center_freq = 5765},
 	{ .hw_value = 157, .center_freq = 5785},
+	{ .hw_value = 184, .center_freq = 4920},
+	{ .hw_value = 189, .center_freq = 4945},
+	{ .hw_value = 9, .center_freq = 5045},
+	{ .hw_value = 36, .center_freq = 5180},
+	{ .hw_value = 46, .center_freq = 5230},
+	{ .hw_value = 64, .center_freq = 5320},
+	{ .hw_value = 116, .center_freq = 5580},
+	{ .hw_value = 136, .center_freq = 5680},
+	{ .hw_value = 192, .center_freq = 4960},
+	{ .hw_value = 11, .center_freq = 5055},
+	{ .hw_value = 38, .center_freq = 5190},
+	{ .hw_value = 48, .center_freq = 5240},
+	{ .hw_value = 100, .center_freq = 5500},
+	{ .hw_value = 120, .center_freq = 5600},
+	{ .hw_value = 140, .center_freq = 5700},
+	{ .hw_value = 185, .center_freq = 4925},
+	{ .hw_value = 196, .center_freq = 4980},
+	{ .hw_value = 12, .center_freq = 5060},
+	{ .hw_value = 40, .center_freq = 5200},
+	{ .hw_value = 52, .center_freq = 5260},
+	{ .hw_value = 104, .center_freq = 5520},
+	{ .hw_value = 124, .center_freq = 5620},
+	{ .hw_value = 149, .center_freq = 5745},
 	{ .hw_value = 161, .center_freq = 5805},
+	{ .hw_value = 187, .center_freq = 4935},
+	{ .hw_value = 7, .center_freq = 5035},
+	{ .hw_value = 16, .center_freq = 5080},
+	{ .hw_value = 42, .center_freq = 5210},
+	{ .hw_value = 56, .center_freq = 5280},
+	{ .hw_value = 108, .center_freq = 5540},
+	{ .hw_value = 128, .center_freq = 5640},
+	{ .hw_value = 153, .center_freq = 5765},
 	{ .hw_value = 165, .center_freq = 5825},
 };
 
@@ -2211,8 +2308,7 @@
 	struct wl1271 *wl = dev_get_drvdata(dev);
 	ssize_t len;
 
-	/* FIXME: what's the maximum length of buf? page size?*/
-	len = 500;
+	len = PAGE_SIZE;
 
 	mutex_lock(&wl->mutex);
 	len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n",
@@ -2273,8 +2369,7 @@
 	struct wl1271 *wl = dev_get_drvdata(dev);
 	ssize_t len;
 
-	/* FIXME: what's the maximum length of buf? page size?*/
-	len = 500;
+	len = PAGE_SIZE;
 
 	mutex_lock(&wl->mutex);
 	if (wl->hw_pg_ver >= 0)
@@ -2306,6 +2401,8 @@
 
 	wl->mac80211_registered = true;
 
+	register_netdevice_notifier(&wl1271_dev_notifier);
+
 	wl1271_notice("loaded");
 
 	return 0;
@@ -2314,6 +2411,7 @@
 
 void wl1271_unregister_hw(struct wl1271 *wl)
 {
+	unregister_netdevice_notifier(&wl1271_dev_notifier);
 	ieee80211_unregister_hw(wl->hw);
 	wl->mac80211_registered = false;
 
@@ -2322,6 +2420,14 @@
 
 int wl1271_init_ieee80211(struct wl1271 *wl)
 {
+	static const u32 cipher_suites[] = {
+		WLAN_CIPHER_SUITE_WEP40,
+		WLAN_CIPHER_SUITE_WEP104,
+		WLAN_CIPHER_SUITE_TKIP,
+		WLAN_CIPHER_SUITE_CCMP,
+		WL1271_CIPHER_SUITE_GEM,
+	};
+
 	/* The tx descriptor buffer and the TKIP space. */
 	wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE +
 		sizeof(struct wl1271_tx_hw_descr);
@@ -2339,13 +2445,14 @@
 		IEEE80211_HW_CONNECTION_MONITOR |
 		IEEE80211_HW_SUPPORTS_CQM_RSSI;
 
+	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);
 	wl->hw->wiphy->max_scan_ssids = 1;
 	wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
-
-	if (wl1271_11a_enabled())
-		wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
+	wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
 
 	wl->hw->queues = 4;
 	wl->hw->max_rates = 1;
@@ -2364,6 +2471,7 @@
 	struct platform_device *plat_dev = NULL;
 	struct wl1271 *wl;
 	int i, ret;
+	unsigned int order;
 
 	hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
 	if (!hw) {
@@ -2391,6 +2499,10 @@
 
 	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->tx_work, wl1271_tx_work);
+	INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
+	INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
 	wl->channel = WL1271_DEFAULT_CHANNEL;
 	wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
 	wl->default_key = 0;
@@ -2422,11 +2534,18 @@
 
 	wl1271_debugfs_init(wl);
 
+	order = get_order(WL1271_AGGR_BUFFER_SIZE);
+	wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
+	if (!wl->aggr_buf) {
+		ret = -ENOMEM;
+		goto err_hw;
+	}
+
 	/* Register platform device */
 	ret = platform_device_register(wl->plat_dev);
 	if (ret) {
 		wl1271_error("couldn't register platform device");
-		goto err_hw;
+		goto err_aggr;
 	}
 	dev_set_drvdata(&wl->plat_dev->dev, wl);
 
@@ -2452,6 +2571,9 @@
 err_platform:
 	platform_device_unregister(wl->plat_dev);
 
+err_aggr:
+	free_pages((unsigned long)wl->aggr_buf, order);
+
 err_hw:
 	wl1271_debugfs_exit(wl);
 	kfree(plat_dev);
@@ -2468,6 +2590,8 @@
 int wl1271_free_hw(struct wl1271 *wl)
 {
 	platform_device_unregister(wl->plat_dev);
+	free_pages((unsigned long)wl->aggr_buf,
+			get_order(WL1271_AGGR_BUFFER_SIZE));
 	kfree(wl->plat_dev);
 
 	wl1271_debugfs_exit(wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index a5e60e0..e3c332e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -39,6 +39,9 @@
 
 	mutex_lock(&wl->mutex);
 
+	if (unlikely(wl->state == WL1271_STATE_OFF))
+		goto out;
+
 	if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) ||
 	    (!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
 	     !test_bit(WL1271_FLAG_IDLE, &wl->flags)))
@@ -61,7 +64,7 @@
 	    test_bit(WL1271_FLAG_IDLE, &wl->flags)) {
 		cancel_delayed_work(&wl->elp_work);
 		ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
-					msecs_to_jiffies(ELP_ENTRY_DELAY));
+					     msecs_to_jiffies(ELP_ENTRY_DELAY));
 	}
 }
 
@@ -96,6 +99,7 @@
 			&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
 		if (ret == 0) {
 			wl1271_error("ELP wakeup timeout!");
+			ieee80211_queue_work(wl->hw, &wl->recovery_work);
 			ret = -ETIMEDOUT;
 			goto err;
 		} else if (ret < 0) {
@@ -121,7 +125,7 @@
 }
 
 int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
-		       bool send)
+		       u32 rates, bool send)
 {
 	int ret;
 
@@ -129,7 +133,14 @@
 	case STATION_POWER_SAVE_MODE:
 		wl1271_debug(DEBUG_PSM, "entering psm");
 
-		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send);
+		ret = wl1271_acx_wake_up_conditions(wl);
+		if (ret < 0) {
+			wl1271_error("couldn't set wake up conditions");
+			return ret;
+		}
+
+		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE,
+					 rates, send);
 		if (ret < 0)
 			return ret;
 
@@ -152,7 +163,8 @@
 		if (ret < 0)
 			return ret;
 
-		ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send);
+		ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE,
+					 rates, send);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h
index 940276f..6ba7b03 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.h
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.h
@@ -28,7 +28,7 @@
 #include "wl1271_acx.h"
 
 int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
-		       bool send);
+		       u32 rates, bool send);
 void wl1271_ps_elp_sleep(struct wl1271 *wl);
 int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
 void wl1271_elp_work(struct work_struct *work);
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index 019aa79..bea133b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -74,9 +74,8 @@
 	}
 }
 
-static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
+static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
 {
-	struct ieee80211_rx_status rx_status;
 	struct wl1271_rx_descriptor *desc;
 	struct sk_buff *skb;
 	u16 *fc;
@@ -88,16 +87,16 @@
 	 * workaround this by not retrieving them at all.
 	 */
 	if (unlikely(wl->state == WL1271_STATE_PLT))
-		return;
+		return -EINVAL;
 
 	skb = __dev_alloc_skb(length, GFP_KERNEL);
 	if (!skb) {
 		wl1271_error("Couldn't allocate RX frame");
-		return;
+		return -ENOMEM;
 	}
 
 	buf = skb_put(skb, length);
-	wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
+	memcpy(buf, data, length);
 
 	/* the data read starts with the descriptor */
 	desc = (struct wl1271_rx_descriptor *) buf;
@@ -109,15 +108,16 @@
 	if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
 		beacon = 1;
 
-	wl1271_rx_status(wl, desc, &rx_status, beacon);
+	wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
 
 	wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
 		     beacon ? "beacon" : "");
 
 	skb_trim(skb, skb->len - desc->pad_len);
 
-	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
 	ieee80211_rx_ni(wl->hw, skb);
+
+	return 0;
 }
 
 void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
@@ -126,31 +126,60 @@
 	u32 buf_size;
 	u32 fw_rx_counter  = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
 	u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
+	u32 rx_counter;
 	u32 mem_block;
+	u32 pkt_length;
+	u32 pkt_offset;
 
 	while (drv_rx_counter != fw_rx_counter) {
-		mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter);
-		buf_size = wl1271_rx_get_buf_size(status, drv_rx_counter);
+		buf_size = 0;
+		rx_counter = drv_rx_counter;
+		while (rx_counter != fw_rx_counter) {
+			pkt_length = wl1271_rx_get_buf_size(status, rx_counter);
+			if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
+				break;
+			buf_size += pkt_length;
+			rx_counter++;
+			rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
+		}
 
 		if (buf_size == 0) {
 			wl1271_warning("received empty data");
 			break;
 		}
 
+		/*
+		 * Choose the block we want to read
+		 * For aggregated packets, only the first memory block should
+		 * be retrieved. The FW takes care of the rest.
+		 */
+		mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter);
 		wl->rx_mem_pool_addr.addr = (mem_block << 8) +
 			le32_to_cpu(wl_mem_map->packet_memory_pool_start);
 		wl->rx_mem_pool_addr.addr_extra =
 			wl->rx_mem_pool_addr.addr + 4;
-
-		/* Choose the block we want to read */
 		wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr,
-			     sizeof(wl->rx_mem_pool_addr), false);
+				sizeof(wl->rx_mem_pool_addr), false);
 
-		wl1271_rx_handle_data(wl, buf_size);
+		/* Read all available packets at once */
+		wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
+				buf_size, true);
 
-		wl->rx_counter++;
-		drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
+		/* Split data into separate packets */
+		pkt_offset = 0;
+		while (pkt_offset < buf_size) {
+			pkt_length = wl1271_rx_get_buf_size(status,
+					drv_rx_counter);
+			if (wl1271_rx_handle_data(wl,
+					wl->aggr_buf + pkt_offset,
+					pkt_length) < 0)
+				break;
+			wl->rx_counter++;
+			drv_rx_counter++;
+			drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
+			pkt_offset += pkt_length;
+		}
 	}
-
-	wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
+	wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS,
+			cpu_to_le32(wl->rx_counter));
 }
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c
index fec43ee..909bb47 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.c
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
@@ -28,11 +28,43 @@
 #include "wl1271_scan.h"
 #include "wl1271_acx.h"
 
+void wl1271_scan_complete_work(struct work_struct *work)
+{
+	struct delayed_work *dwork;
+	struct wl1271 *wl;
+
+	dwork = container_of(work, struct delayed_work, work);
+	wl = container_of(dwork, struct wl1271, scan_complete_work);
+
+	wl1271_debug(DEBUG_SCAN, "Scanning complete");
+
+	mutex_lock(&wl->mutex);
+
+	if (wl->scan.state == WL1271_SCAN_STATE_IDLE) {
+		mutex_unlock(&wl->mutex);
+		return;
+	}
+
+	wl->scan.state = WL1271_SCAN_STATE_IDLE;
+	kfree(wl->scan.scanned_ch);
+	wl->scan.scanned_ch = NULL;
+	mutex_unlock(&wl->mutex);
+
+	ieee80211_scan_completed(wl->hw, false);
+
+	if (wl->scan.failed) {
+		wl1271_info("Scan completed due to error.");
+		ieee80211_queue_work(wl->hw, &wl->recovery_work);
+	}
+}
+
+
 static int wl1271_get_scan_channels(struct wl1271 *wl,
 				    struct cfg80211_scan_request *req,
 				    struct basic_scan_channel_params *channels,
 				    enum ieee80211_band band, bool passive)
 {
+	struct conf_scan_settings *c = &wl->conf.scan;
 	int i, j;
 	u32 flags;
 
@@ -60,10 +92,17 @@
 			wl1271_debug(DEBUG_SCAN, "beacon_found %d",
 				     req->channels[i]->beacon_found);
 
-			channels[j].min_duration =
-				cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
-			channels[j].max_duration =
-				cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
+			if (!passive) {
+				channels[j].min_duration =
+					cpu_to_le32(c->min_dwell_time_active);
+				channels[j].max_duration =
+					cpu_to_le32(c->max_dwell_time_active);
+			} else {
+				channels[j].min_duration =
+					cpu_to_le32(c->min_dwell_time_passive);
+				channels[j].max_duration =
+					cpu_to_le32(c->max_dwell_time_passive);
+			}
 			channels[j].early_termination = 0;
 			channels[j].tx_power_att = req->channels[i]->max_power;
 			channels[j].channel = req->channels[i]->hw_value;
@@ -100,8 +139,11 @@
 
 	/* We always use high priority scans */
 	scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH;
-	if(passive)
+
+	/* No SSIDs means that we have a forced passive scan */
+	if (passive || wl->scan.req->n_ssids == 0)
 		scan_options |= WL1271_SCAN_OPT_PASSIVE;
+
 	cmd->params.scan_options = cpu_to_le16(scan_options);
 
 	cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
@@ -117,7 +159,7 @@
 	cmd->params.rx_filter_options =
 		cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
 
-	cmd->params.n_probe_reqs = WL1271_SCAN_PROBE_REQS;
+	cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
 	cmd->params.tx_rate = cpu_to_le32(basic_rate);
 	cmd->params.tid_trigger = 0;
 	cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
@@ -165,7 +207,7 @@
 
 void wl1271_scan_stm(struct wl1271 *wl)
 {
-	int ret;
+	int ret = 0;
 
 	switch (wl->scan.state) {
 	case WL1271_SCAN_STATE_IDLE:
@@ -185,7 +227,7 @@
 		ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true,
 				       wl->conf.tx.basic_rate);
 		if (ret == WL1271_NOTHING_TO_SCAN) {
-			if (wl1271_11a_enabled())
+			if (wl->enable_11a)
 				wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
 			else
 				wl->scan.state = WL1271_SCAN_STATE_DONE;
@@ -215,20 +257,22 @@
 		break;
 
 	case WL1271_SCAN_STATE_DONE:
-		mutex_unlock(&wl->mutex);
-		ieee80211_scan_completed(wl->hw, false);
-		mutex_lock(&wl->mutex);
-
-		kfree(wl->scan.scanned_ch);
-		wl->scan.scanned_ch = NULL;
-
-		wl->scan.state = WL1271_SCAN_STATE_IDLE;
+		wl->scan.failed = false;
+		cancel_delayed_work(&wl->scan_complete_work);
+		ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
+					     msecs_to_jiffies(0));
 		break;
 
 	default:
 		wl1271_error("invalid scan state");
 		break;
 	}
+
+	if (ret < 0) {
+		cancel_delayed_work(&wl->scan_complete_work);
+		ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
+					     msecs_to_jiffies(0));
+	}
 }
 
 int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
@@ -248,9 +292,14 @@
 
 	wl->scan.req = req;
 
-	wl->scan.scanned_ch = kzalloc(req->n_channels *
+	wl->scan.scanned_ch = kcalloc(req->n_channels,
 				      sizeof(*wl->scan.scanned_ch),
 				      GFP_KERNEL);
+	/* we assume failure so that timeout scenarios are handled correctly */
+	wl->scan.failed = true;
+	ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
+				     msecs_to_jiffies(WL1271_SCAN_TIMEOUT));
+
 	wl1271_scan_stm(wl);
 
 	return 0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h b/drivers/net/wireless/wl12xx/wl1271_scan.h
index f181570..6d57127 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.h
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.h
@@ -32,6 +32,7 @@
 				const u8 *ssid, size_t ssid_len,
 				const u8 *ie, size_t ie_len, u8 band);
 void wl1271_scan_stm(struct wl1271 *wl);
+void wl1271_scan_complete_work(struct work_struct *work);
 
 #define WL1271_SCAN_MAX_CHANNELS       24
 #define WL1271_SCAN_DEFAULT_TAG        1
@@ -39,11 +40,10 @@
 #define WL1271_SCAN_OPT_ACTIVE         0
 #define WL1271_SCAN_OPT_PASSIVE	       1
 #define WL1271_SCAN_OPT_PRIORITY_HIGH  4
-#define WL1271_SCAN_CHAN_MIN_DURATION  30000  /* TU */
-#define WL1271_SCAN_CHAN_MAX_DURATION  60000  /* TU */
 #define WL1271_SCAN_BAND_2_4_GHZ 0
 #define WL1271_SCAN_BAND_5_GHZ 1
-#define WL1271_SCAN_PROBE_REQS 3
+
+#define WL1271_SCAN_TIMEOUT    10000 /* msec */
 
 enum {
 	WL1271_SCAN_STATE_IDLE,
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index 7059b5c..784ef34 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -29,14 +29,13 @@
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/card.h>
 #include <linux/gpio.h>
+#include <linux/wl12xx.h>
+#include <linux/pm_runtime.h>
 
 #include "wl1271.h"
 #include "wl12xx_80211.h"
 #include "wl1271_io.h"
 
-
-#define RX71_WL1271_IRQ_GPIO		42
-
 #ifndef SDIO_VENDOR_ID_TI
 #define SDIO_VENDOR_ID_TI		0x0097
 #endif
@@ -107,6 +106,8 @@
 	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",
@@ -122,9 +123,10 @@
 		wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
 	}
 
+	sdio_release_host(func);
+
 	if (ret)
 		wl1271_error("sdio read failed (%d)", ret);
-
 }
 
 static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
@@ -133,6 +135,8 @@
 	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",
@@ -147,26 +151,49 @@
 		else
 			ret = sdio_memcpy_toio(func, addr, buf, len);
 	}
+
+	sdio_release_host(func);
+
 	if (ret)
 		wl1271_error("sdio write failed (%d)", ret);
-
 }
 
-static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_sdio_power_on(struct wl1271 *wl)
+{
+	struct sdio_func *func = wl_to_func(wl);
+	int ret;
+
+	/* Power up the card */
+	ret = pm_runtime_get_sync(&func->dev);
+	if (ret < 0)
+		goto out;
+
+	sdio_claim_host(func);
+	sdio_enable_func(func);
+	sdio_release_host(func);
+
+out:
+	return ret;
+}
+
+static int wl1271_sdio_power_off(struct wl1271 *wl)
 {
 	struct sdio_func *func = wl_to_func(wl);
 
-	/* Let the SDIO stack handle wlan_enable control, so we
-	 * keep host claimed while wlan is in use to keep wl1271
-	 * alive.
-	 */
-	if (enable) {
-		sdio_claim_host(func);
-		sdio_enable_func(func);
-	} else {
-		sdio_disable_func(func);
-		sdio_release_host(func);
-	}
+	sdio_claim_host(func);
+	sdio_disable_func(func);
+	sdio_release_host(func);
+
+	/* Power down the card */
+	return pm_runtime_put_sync(&func->dev);
+}
+
+static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
+{
+	if (enable)
+		return wl1271_sdio_power_on(wl);
+	else
+		return wl1271_sdio_power_off(wl);
 }
 
 static struct wl1271_if_operations sdio_ops = {
@@ -184,6 +211,7 @@
 				  const struct sdio_device_id *id)
 {
 	struct ieee80211_hw *hw;
+	const struct wl12xx_platform_data *wlan_data;
 	struct wl1271 *wl;
 	int ret;
 
@@ -203,13 +231,16 @@
 	/* Grab access to FN0 for ELP reg. */
 	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
 
-	wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO);
-	if (wl->irq < 0) {
-		ret = wl->irq;
-		wl1271_error("could not get irq!");
+	wlan_data = wl12xx_get_platform_data();
+	if (IS_ERR(wlan_data)) {
+		ret = PTR_ERR(wlan_data);
+		wl1271_error("missing wlan platform data: %d", ret);
 		goto out_free;
 	}
 
+	wl->irq = wlan_data->irq;
+	wl->ref_clock = wlan_data->board_ref_clock;
+
 	ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
 	if (ret < 0) {
 		wl1271_error("request_irq() failed: %d", ret);
@@ -230,6 +261,9 @@
 
 	sdio_set_drvdata(func, wl);
 
+	/* Tell PM core that we don't need the card to be powered now */
+	pm_runtime_put_noidle(&func->dev);
+
 	wl1271_notice("initialized");
 
 	return 0;
@@ -248,17 +282,39 @@
 {
 	struct wl1271 *wl = sdio_get_drvdata(func);
 
-	free_irq(wl->irq, wl);
+	/* Undo decrement done above in wl1271_probe */
+	pm_runtime_get_noresume(&func->dev);
 
 	wl1271_unregister_hw(wl);
+	free_irq(wl->irq, wl);
 	wl1271_free_hw(wl);
 }
 
+static int wl1271_suspend(struct device *dev)
+{
+	/* Tell MMC/SDIO core it's OK to power down the card
+	 * (if it isn't already), but not to remove it completely */
+	return 0;
+}
+
+static int wl1271_resume(struct device *dev)
+{
+	return 0;
+}
+
+static const struct dev_pm_ops wl1271_sdio_pm_ops = {
+	.suspend	= wl1271_suspend,
+	.resume		= wl1271_resume,
+};
+
 static struct sdio_driver wl1271_sdio_driver = {
 	.name		= "wl1271_sdio",
 	.id_table	= wl1271_devices,
 	.probe		= wl1271_probe,
 	.remove		= __devexit_p(wl1271_remove),
+	.drv = {
+		.pm = &wl1271_sdio_pm_ops,
+	},
 };
 
 static int __init wl1271_init(void)
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index 4cb99c5..ef80168 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include <linux/crc7.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/wl12xx.h>
+#include <linux/wl12xx.h>
 #include <linux/slab.h>
 
 #include "wl1271.h"
@@ -63,6 +63,11 @@
 		((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32))
 #define HW_ACCESS_WSPI_INIT_CMD_MASK  0
 
+/* HW limitation: maximum possible chunk size is 4095 bytes */
+#define WSPI_MAX_CHUNK_SIZE    4092
+
+#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
+
 static inline struct spi_device *wl_to_spi(struct wl1271 *wl)
 {
 	return wl->if_priv;
@@ -202,90 +207,117 @@
 static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
 				size_t len, bool fixed)
 {
-	struct spi_transfer t[3];
+	struct spi_transfer t[2];
 	struct spi_message m;
 	u32 *busy_buf;
 	u32 *cmd;
+	u32 chunk_len;
 
-	cmd = &wl->buffer_cmd;
-	busy_buf = wl->buffer_busyword;
+	while (len > 0) {
+		chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
 
-	*cmd = 0;
-	*cmd |= WSPI_CMD_READ;
-	*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
-	*cmd |= addr & WSPI_CMD_BYTE_ADDR;
+		cmd = &wl->buffer_cmd;
+		busy_buf = wl->buffer_busyword;
 
-	if (fixed)
-		*cmd |= WSPI_CMD_FIXED;
+		*cmd = 0;
+		*cmd |= WSPI_CMD_READ;
+		*cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) &
+			WSPI_CMD_BYTE_LENGTH;
+		*cmd |= addr & WSPI_CMD_BYTE_ADDR;
 
-	spi_message_init(&m);
-	memset(t, 0, sizeof(t));
+		if (fixed)
+			*cmd |= WSPI_CMD_FIXED;
 
-	t[0].tx_buf = cmd;
-	t[0].len = 4;
-	t[0].cs_change = true;
-	spi_message_add_tail(&t[0], &m);
+		spi_message_init(&m);
+		memset(t, 0, sizeof(t));
 
-	/* Busy and non busy words read */
-	t[1].rx_buf = busy_buf;
-	t[1].len = WL1271_BUSY_WORD_LEN;
-	t[1].cs_change = true;
-	spi_message_add_tail(&t[1], &m);
+		t[0].tx_buf = cmd;
+		t[0].len = 4;
+		t[0].cs_change = true;
+		spi_message_add_tail(&t[0], &m);
 
-	spi_sync(wl_to_spi(wl), &m);
+		/* Busy and non busy words read */
+		t[1].rx_buf = busy_buf;
+		t[1].len = WL1271_BUSY_WORD_LEN;
+		t[1].cs_change = true;
+		spi_message_add_tail(&t[1], &m);
 
-	if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
-	    wl1271_spi_read_busy(wl)) {
-		memset(buf, 0, len);
-		return;
+		spi_sync(wl_to_spi(wl), &m);
+
+		if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
+		    wl1271_spi_read_busy(wl)) {
+			memset(buf, 0, chunk_len);
+			return;
+		}
+
+		spi_message_init(&m);
+		memset(t, 0, sizeof(t));
+
+		t[0].rx_buf = buf;
+		t[0].len = chunk_len;
+		t[0].cs_change = true;
+		spi_message_add_tail(&t[0], &m);
+
+		spi_sync(wl_to_spi(wl), &m);
+
+		wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
+		wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, chunk_len);
+
+		if (!fixed)
+			addr += chunk_len;
+		buf += chunk_len;
+		len -= chunk_len;
 	}
-
-	spi_message_init(&m);
-	memset(t, 0, sizeof(t));
-
-	t[0].rx_buf = buf;
-	t[0].len = len;
-	t[0].cs_change = true;
-	spi_message_add_tail(&t[0], &m);
-
-	spi_sync(wl_to_spi(wl), &m);
-
-	wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
-	wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
 }
 
 static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
 			  size_t len, bool fixed)
 {
-	struct spi_transfer t[2];
+	struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
 	struct spi_message m;
+	u32 commands[WSPI_MAX_NUM_OF_CHUNKS];
 	u32 *cmd;
+	u32 chunk_len;
+	int i;
 
-	cmd = &wl->buffer_cmd;
-
-	*cmd = 0;
-	*cmd |= WSPI_CMD_WRITE;
-	*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
-	*cmd |= addr & WSPI_CMD_BYTE_ADDR;
-
-	if (fixed)
-		*cmd |= WSPI_CMD_FIXED;
+	WARN_ON(len > WL1271_AGGR_BUFFER_SIZE);
 
 	spi_message_init(&m);
 	memset(t, 0, sizeof(t));
 
-	t[0].tx_buf = cmd;
-	t[0].len = sizeof(*cmd);
-	spi_message_add_tail(&t[0], &m);
+	cmd = &commands[0];
+	i = 0;
+	while (len > 0) {
+		chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
 
-	t[1].tx_buf = buf;
-	t[1].len = len;
-	spi_message_add_tail(&t[1], &m);
+		*cmd = 0;
+		*cmd |= WSPI_CMD_WRITE;
+		*cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) &
+			WSPI_CMD_BYTE_LENGTH;
+		*cmd |= addr & WSPI_CMD_BYTE_ADDR;
+
+		if (fixed)
+			*cmd |= WSPI_CMD_FIXED;
+
+		t[i].tx_buf = cmd;
+		t[i].len = sizeof(*cmd);
+		spi_message_add_tail(&t[i++], &m);
+
+		t[i].tx_buf = buf;
+		t[i].len = chunk_len;
+		spi_message_add_tail(&t[i++], &m);
+
+		wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
+		wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, chunk_len);
+
+		if (!fixed)
+			addr += chunk_len;
+		buf += chunk_len;
+		len -= chunk_len;
+		cmd++;
+	}
 
 	spi_sync(wl_to_spi(wl), &m);
-
-	wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
-	wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
 }
 
 static irqreturn_t wl1271_irq(int irq, void *cookie)
@@ -312,10 +344,12 @@
 	return IRQ_HANDLED;
 }
 
-static void wl1271_spi_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_spi_set_power(struct wl1271 *wl, bool enable)
 {
 	if (wl->set_power)
 		wl->set_power(enable);
+
+	return 0;
 }
 
 static struct wl1271_if_operations spi_ops = {
@@ -370,6 +404,8 @@
 		goto out_free;
 	}
 
+	wl->ref_clock = pdata->board_ref_clock;
+
 	wl->irq = spi->irq;
 	if (wl->irq < 0) {
 		wl1271_error("irq missing in platform data");
@@ -412,9 +448,8 @@
 {
 	struct wl1271 *wl = dev_get_drvdata(&spi->dev);
 
-	free_irq(wl->irq, wl);
-
 	wl1271_unregister_hw(wl);
+	free_irq(wl->irq, wl);
 	wl1271_free_hw(wl);
 
 	return 0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c
index 6e0952f..a3aa843 100644
--- a/drivers/net/wireless/wl12xx/wl1271_testmode.c
+++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c
@@ -199,19 +199,6 @@
 	buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
 	len = nla_len(tb[WL1271_TM_ATTR_DATA]);
 
-	/*
-	 * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
-	 * configurations) can be removed when those NVS files stop floating
-	 * around.
-	 */
-	if (len != sizeof(struct wl1271_nvs_file) &&
-	    (len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
-	     wl1271_11a_enabled())) {
-		wl1271_error("nvs size is not as expected: %zu != %zu",
-			     len, sizeof(struct wl1271_nvs_file));
-		return -EMSGSIZE;
-	}
-
 	mutex_lock(&wl->mutex);
 
 	kfree(wl->nvs);
@@ -224,6 +211,7 @@
 	}
 
 	memcpy(wl->nvs, buf, len);
+	wl->nvs_len = len;
 
 	wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs");
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index c592cc2..e3dc13c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -43,13 +43,17 @@
 	return -EBUSY;
 }
 
-static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
+static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
+				u32 buf_offset)
 {
 	struct wl1271_tx_hw_descr *desc;
 	u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
 	u32 total_blocks;
 	int id, ret = -EBUSY;
 
+	if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
+		return -EBUSY;
+
 	/* allocate free identifier for the packet */
 	id = wl1271_tx_id(wl, skb);
 	if (id < 0)
@@ -82,7 +86,7 @@
 	return ret;
 }
 
-static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
+static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
 			      u32 extra, struct ieee80211_tx_info *control)
 {
 	struct timespec ts;
@@ -110,9 +114,9 @@
 	/* configure the tx attributes */
 	tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
 
-	/* queue */
+	/* queue (we use same identifiers for tid's and ac's */
 	ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
-	desc->tid = wl1271_tx_ac_to_tid(ac);
+	desc->tid = ac;
 
 	desc->aid = TX_HW_DEFAULT_AID;
 	desc->reserved = 0;
@@ -133,59 +137,17 @@
 	desc->tx_attr = cpu_to_le16(tx_attr);
 
 	wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
-	return 0;
-}
-
-static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb,
-				 struct ieee80211_tx_info *control)
-{
-
-	struct wl1271_tx_hw_descr *desc;
-	int len;
-
-	/* FIXME: This is a workaround for getting non-aligned packets.
-	   This happens at least with EAPOL packets from the user space.
-	   Our DMA requires packets to be aligned on a 4-byte boundary.
-	*/
-	if (unlikely((long)skb->data & 0x03)) {
-		int offset = (4 - (long)skb->data) & 0x03;
-		wl1271_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;
-
-			/* align the buffer on a 4-byte boundary */
-			skb_reserve(skb, offset);
-			memmove(skb->data, src, skb->len);
-		} else {
-			wl1271_info("No handler, fixme!");
-			return -EINVAL;
-		}
-	}
-
-	len = WL1271_TX_ALIGN(skb->len);
-
-	/* perform a fixed address block write with the packet */
-	wl1271_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
-
-	/* write packet new counter into the write access register */
-	wl->tx_packets_count++;
-
-	desc = (struct wl1271_tx_hw_descr *) skb->data;
-	wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)",
-		     desc->id, skb, len, desc->length);
-
-	return 0;
 }
 
 /* caller must hold wl->mutex */
-static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
+static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
+							u32 buf_offset)
 {
 	struct ieee80211_tx_info *info;
 	u32 extra = 0;
 	int ret = 0;
 	u8 idx;
+	u32 total_len;
 
 	if (!skb)
 		return -EINVAL;
@@ -193,7 +155,7 @@
 	info = IEEE80211_SKB_CB(skb);
 
 	if (info->control.hw_key &&
-	    info->control.hw_key->alg == ALG_TKIP)
+	    info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP)
 		extra = WL1271_TKIP_IV_SPACE;
 
 	if (info->control.hw_key) {
@@ -208,19 +170,22 @@
 		}
 	}
 
-	ret = wl1271_tx_allocate(wl, skb, extra);
+	ret = wl1271_tx_allocate(wl, skb, extra, buf_offset);
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_tx_fill_hdr(wl, skb, extra, info);
-	if (ret < 0)
-		return ret;
+	wl1271_tx_fill_hdr(wl, skb, extra, info);
 
-	ret = wl1271_tx_send_packet(wl, skb, info);
-	if (ret < 0)
-		return ret;
+	/*
+	 * 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);
+	memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len);
+	memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len);
 
-	return ret;
+	return total_len;
 }
 
 u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
@@ -245,7 +210,7 @@
 	struct sk_buff *skb;
 	bool woken_up = false;
 	u32 sta_rates = 0;
-	u32 prev_tx_packets_count;
+	u32 buf_offset;
 	int ret;
 
 	/* check if the rates supported by the AP have changed */
@@ -262,14 +227,15 @@
 	if (unlikely(wl->state == WL1271_STATE_OFF))
 		goto out;
 
-	prev_tx_packets_count = wl->tx_packets_count;
-
 	/* if rates have changed, re-configure the rate policy */
 	if (unlikely(sta_rates)) {
 		wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
 		wl1271_acx_rate_policies(wl);
 	}
 
+	/* Prepare the transfer buffer, by aggregating all
+	 * available packets */
+	buf_offset = 0;
 	while ((skb = skb_dequeue(&wl->tx_queue))) {
 		if (!woken_up) {
 			ret = wl1271_ps_elp_wakeup(wl, false);
@@ -278,21 +244,30 @@
 			woken_up = true;
 		}
 
-		ret = wl1271_tx_frame(wl, skb);
+		ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);
 		if (ret == -EBUSY) {
-			/* firmware buffer is full, lets stop transmitting. */
+			/*
+			 * Either the firmware buffer is full, or the
+			 * aggregation buffer is.
+			 * Queue back last skb, and stop aggregating.
+			 */
 			skb_queue_head(&wl->tx_queue, skb);
 			goto out_ack;
 		} else if (ret < 0) {
 			dev_kfree_skb(skb);
 			goto out_ack;
 		}
+		buf_offset += ret;
+		wl->tx_packets_count++;
 	}
 
 out_ack:
-	/* interrupt the firmware with the new packets */
-	if (prev_tx_packets_count != wl->tx_packets_count)
+	if (buf_offset) {
+		wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
+				buf_offset, true);
+		/* interrupt the firmware with the new packets */
 		wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
+	}
 
 out:
 	if (woken_up)
@@ -347,7 +322,7 @@
 
 	/* remove TKIP header space if present */
 	if (info->control.hw_key &&
-	    info->control.hw_key->alg == ALG_TKIP) {
+	    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);
@@ -422,8 +397,6 @@
 	struct sk_buff *skb;
 
 	/* TX failure */
-/* 	control->flags = 0; FIXME */
-
 	while ((skb = skb_dequeue(&wl->tx_queue))) {
 		wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
 		ieee80211_tx_status(wl->hw, skb);
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h
index 48bf926..d12a129 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.h
@@ -139,23 +139,6 @@
 	}
 }
 
-/* wl1271 tx descriptor needs the tid and we need to convert it from ac */
-static inline int wl1271_tx_ac_to_tid(int ac)
-{
-	switch (ac) {
-	case 0:
-		return 0;
-	case 1:
-		return 2;
-	case 2:
-		return 4;
-	case 3:
-		return 6;
-	default:
-		return 0;
-	}
-}
-
 void wl1271_tx_work(struct work_struct *work);
 void wl1271_tx_complete(struct wl1271 *wl);
 void wl1271_tx_reset(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c
new file mode 100644
index 0000000..973b110
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c
@@ -0,0 +1,28 @@
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/wl12xx.h>
+
+static const struct wl12xx_platform_data *platform_data;
+
+int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
+{
+	if (platform_data)
+		return -EBUSY;
+	if (!data)
+		return -EINVAL;
+
+	platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
+	if (!platform_data)
+		return -ENOMEM;
+
+	return 0;
+}
+
+const struct wl12xx_platform_data *wl12xx_get_platform_data(void)
+{
+	if (!platform_data)
+		return ERR_PTR(-ENODEV);
+
+	return platform_data;
+}
+EXPORT_SYMBOL(wl12xx_get_platform_data);
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index a1cc2d4..ee82df6 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -29,7 +29,6 @@
 
 #include <linux/delay.h>
 #include <linux/types.h>
-#include <linux/ethtool.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
@@ -48,7 +47,6 @@
 
 #include <net/iw_handler.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -78,13 +76,6 @@
 #define WL3501_RESUME	0
 #define WL3501_SUSPEND	1
 
-/*
- * The event() function is this driver's Card Services event handler.  It will
- * be called by Card Services when an appropriate card status event is
- * received. The config() and release() entry points are used to configure or
- * release a socket, in response to card insertion and ejection events.  They
- * are invoked from the wl24 event handler.
- */
 static int wl3501_config(struct pcmcia_device *link);
 static void wl3501_release(struct pcmcia_device *link);
 
@@ -1411,15 +1402,6 @@
 	return wstats;
 }
 
-static void wl3501_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	strlcpy(info->driver, "wl3501_cs", sizeof(info->driver));
-}
-
-static const struct ethtool_ops ops = {
-	.get_drvinfo = wl3501_get_drvinfo
-};
-
 /**
  * wl3501_detach - deletes a driver "instance"
  * @link - FILL_IN
@@ -1869,15 +1851,6 @@
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
-/**
- * wl3501_attach - creates an "instance" of the driver
- *
- * Creates an "instance" of the driver, allocating local data structures for
- * one device.  The device is registered with Card Services.
- *
- * The dev_link 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 wl3501_probe(struct pcmcia_device *p_dev)
 {
 	struct net_device *dev;
@@ -1888,9 +1861,8 @@
 	p_dev->resource[0]->flags	= IO_DATA_PATH_WIDTH_8;
 
 	/* General socket configuration */
-	p_dev->conf.Attributes	= CONF_ENABLE_IRQ;
-	p_dev->conf.IntType	= INT_MEMORY_AND_IO;
-	p_dev->conf.ConfigIndex	= 1;
+	p_dev->config_flags	= CONF_ENABLE_IRQ;
+	p_dev->config_index	= 1;
 
 	dev = alloc_etherdev(sizeof(struct wl3501_card));
 	if (!dev)
@@ -1905,7 +1877,6 @@
 	this->p_dev = p_dev;
 	dev->wireless_data	= &this->wireless_data;
 	dev->wireless_handlers	= &wl3501_handler_def;
-	SET_ETHTOOL_OPS(dev, &ops);
 	netif_stop_queue(dev);
 	p_dev->priv = dev;
 
@@ -1914,14 +1885,6 @@
 	return -ENOMEM;
 }
 
-/**
- * wl3501_config - configure the PCMCIA socket and make eth device available
- * @link - FILL_IN
- *
- * wl3501_config() is scheduled to run after a CARD_INSERTION event is
- * received, to configure the PCMCIA socket, and to make the ethernet device
- * available to the system.
- */
 static int wl3501_config(struct pcmcia_device *link)
 {
 	struct net_device *dev = link->priv;
@@ -1952,10 +1915,7 @@
 	if (ret)
 		goto failed;
 
-	/* This actually configures the PCMCIA socket -- setting up the I/O
-	 * windows and the interrupt mapping.  */
-
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -2010,14 +1970,6 @@
 	return -ENODEV;
 }
 
-/**
- * wl3501_release - unregister the net, release PCMCIA configuration
- * @arg - link
- *
- * After a card is removed, wl3501_release() will unregister the net device,
- * and release the PCMCIA configuration.  If the device is still open, this
- * will be postponed until it is closed.
- */
 static void wl3501_release(struct pcmcia_device *link)
 {
 	pcmcia_disable_device(link);
@@ -2056,9 +2008,7 @@
 
 static struct pcmcia_driver wl3501_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "wl3501_cs",
-	},
+	.name		= "wl3501_cs",
 	.probe		= wl3501_probe,
 	.remove		= wl3501_detach,
 	.id_table	= wl3501_ids,
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index b2af3c5..87a95bc 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -973,6 +973,7 @@
 
 static int print_fw_version(struct zd_chip *chip)
 {
+	struct wiphy *wiphy = zd_chip_to_mac(chip)->hw->wiphy;
 	int r;
 	u16 version;
 
@@ -982,6 +983,10 @@
 		return r;
 
 	dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version);
+
+	snprintf(wiphy->fw_version, sizeof(wiphy->fw_version),
+			"%04hx", version);
+
 	return 0;
 }
 
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index b50fedc..630fb86 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -135,7 +135,7 @@
 static int skb_entry_is_link(const union skb_entry *list)
 {
 	BUILD_BUG_ON(sizeof(list->skb) != sizeof(list->link));
-	return ((unsigned long)list->skb < PAGE_OFFSET);
+	return (unsigned long)list->skb < PAGE_OFFSET;
 }
 
 /*
@@ -203,8 +203,8 @@
 
 static int netfront_tx_slot_available(struct netfront_info *np)
 {
-	return ((np->tx.req_prod_pvt - np->tx.rsp_cons) <
-		(TX_MAX_TARGET - MAX_SKB_FRAGS - 2));
+	return (np->tx.req_prod_pvt - np->tx.rsp_cons) <
+		(TX_MAX_TARGET - MAX_SKB_FRAGS - 2);
 }
 
 static void xennet_maybe_wake_tx(struct net_device *dev)
@@ -1395,7 +1395,7 @@
 }
 
 /* Common code used when first setting up, and when resuming. */
-static int talk_to_backend(struct xenbus_device *dev,
+static int talk_to_netback(struct xenbus_device *dev,
 			   struct netfront_info *info)
 {
 	const char *message;
@@ -1545,7 +1545,7 @@
 		return -ENODEV;
 	}
 
-	err = talk_to_backend(np->xbdev, np);
+	err = talk_to_netback(np->xbdev, np);
 	if (err)
 		return err;
 
@@ -1599,7 +1599,7 @@
 /**
  * Callback received when the backend's state changes.
  */
-static void backend_changed(struct xenbus_device *dev,
+static void netback_changed(struct xenbus_device *dev,
 			    enum xenbus_state backend_state)
 {
 	struct netfront_info *np = dev_get_drvdata(&dev->dev);
@@ -1801,7 +1801,7 @@
 	.probe = netfront_probe,
 	.remove = __devexit_p(xennet_remove),
 	.resume = netfront_resume,
-	.otherend_changed = backend_changed,
+	.otherend_changed = netback_changed,
 };
 
 static int __init netif_init(void)
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index ecbbb68..f3f8be5 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -641,7 +641,7 @@
 	skb_put(skb, len);	/* Tell the skb how much data we got */
 
 	skb->protocol = eth_type_trans(skb, dev);
-	skb->ip_summed = CHECKSUM_NONE;
+	skb_checksum_none_assert(skb);
 
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += len;
@@ -1269,6 +1269,16 @@
 	return 0;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void
+xemaclite_poll_controller(struct net_device *ndev)
+{
+	disable_irq(ndev->irq);
+	xemaclite_interrupt(ndev->irq, ndev);
+	enable_irq(ndev->irq);
+}
+#endif
+
 static struct net_device_ops xemaclite_netdev_ops = {
 	.ndo_open		= xemaclite_open,
 	.ndo_stop		= xemaclite_close,
@@ -1276,6 +1286,9 @@
 	.ndo_set_mac_address	= xemaclite_set_mac_address,
 	.ndo_tx_timeout		= xemaclite_tx_timeout,
 	.ndo_get_stats		= xemaclite_get_stats,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller = xemaclite_poll_controller,
+#endif
 };
 
 /* Match table for OF platform binding */
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 4eb67ae..cd1b3dc 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -646,7 +646,7 @@
 	init_timer(&yp->timer);
 	yp->timer.expires = jiffies + 3*HZ;
 	yp->timer.data = (unsigned long)dev;
-	yp->timer.function = &yellowfin_timer;				/* timer handler */
+	yp->timer.function = yellowfin_timer;				/* timer handler */
 	add_timer(&yp->timer);
 
 	return 0;
diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c
index b336cd9..f9bda64 100644
--- a/drivers/oprofile/oprof.c
+++ b/drivers/oprofile/oprof.c
@@ -225,26 +225,17 @@
 	mutex_unlock(&start_mutex);
 }
 
-int oprofile_set_backtrace(unsigned long val)
+int oprofile_set_ulong(unsigned long *addr, unsigned long val)
 {
-	int err = 0;
+	int err = -EBUSY;
 
 	mutex_lock(&start_mutex);
-
-	if (oprofile_started) {
-		err = -EBUSY;
-		goto out;
+	if (!oprofile_started) {
+		*addr = val;
+		err = 0;
 	}
-
-	if (!oprofile_ops.backtrace) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	oprofile_backtrace_depth = val;
-
-out:
 	mutex_unlock(&start_mutex);
+
 	return err;
 }
 
@@ -257,16 +248,9 @@
 		printk(KERN_INFO "oprofile: using timer interrupt.\n");
 		err = oprofile_timer_init(&oprofile_ops);
 		if (err)
-			goto out_arch;
+			return err;
 	}
-	err = oprofilefs_register();
-	if (err)
-		goto out_arch;
-	return 0;
-
-out_arch:
-	oprofile_arch_exit();
-	return err;
+	return oprofilefs_register();
 }
 
 
diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h
index 47e12cb..177b73d 100644
--- a/drivers/oprofile/oprof.h
+++ b/drivers/oprofile/oprof.h
@@ -37,7 +37,7 @@
 int oprofile_timer_init(struct oprofile_operations *ops);
 void oprofile_timer_exit(void);
 
-int oprofile_set_backtrace(unsigned long depth);
+int oprofile_set_ulong(unsigned long *addr, unsigned long val);
 int oprofile_set_timeout(unsigned long time);
 
 #endif /* OPROF_H */
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c
index bbd7516..89f6345 100644
--- a/drivers/oprofile/oprofile_files.c
+++ b/drivers/oprofile/oprofile_files.c
@@ -59,6 +59,7 @@
 static const struct file_operations timeout_fops = {
 	.read		= timeout_read,
 	.write		= timeout_write,
+	.llseek		= default_llseek,
 };
 
 #endif
@@ -79,21 +80,25 @@
 	if (*offset)
 		return -EINVAL;
 
+	if (!oprofile_ops.backtrace)
+		return -EINVAL;
+
 	retval = oprofilefs_ulong_from_user(&val, buf, count);
 	if (retval)
 		return retval;
 
-	retval = oprofile_set_backtrace(val);
-
+	retval = oprofile_set_ulong(&oprofile_backtrace_depth, val);
 	if (retval)
 		return retval;
+
 	return count;
 }
 
 
 static const struct file_operations depth_fops = {
 	.read		= depth_read,
-	.write		= depth_write
+	.write		= depth_write,
+	.llseek		= default_llseek,
 };
 
 
@@ -105,6 +110,7 @@
 
 static const struct file_operations pointer_size_fops = {
 	.read		= pointer_size_read,
+	.llseek		= default_llseek,
 };
 
 
@@ -116,6 +122,7 @@
 
 static const struct file_operations cpu_type_fops = {
 	.read		= cpu_type_read,
+	.llseek		= default_llseek,
 };
 
 
@@ -151,6 +158,7 @@
 static const struct file_operations enable_fops = {
 	.read		= enable_read,
 	.write		= enable_write,
+	.llseek		= default_llseek,
 };
 
 
@@ -163,6 +171,7 @@
 
 static const struct file_operations dump_fops = {
 	.write		= dump_write,
+	.llseek		= noop_llseek,
 };
 
 void oprofile_create_files(struct super_block *sb, struct dentry *root)
diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c
new file mode 100644
index 0000000..9046f7b
--- /dev/null
+++ b/drivers/oprofile/oprofile_perf.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2010 ARM Ltd.
+ *
+ * Perf-events backend for OProfile.
+ */
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+#include <linux/oprofile.h>
+#include <linux/slab.h>
+
+/*
+ * Per performance monitor configuration as set via oprofilefs.
+ */
+struct op_counter_config {
+	unsigned long count;
+	unsigned long enabled;
+	unsigned long event;
+	unsigned long unit_mask;
+	unsigned long kernel;
+	unsigned long user;
+	struct perf_event_attr attr;
+};
+
+static int oprofile_perf_enabled;
+static DEFINE_MUTEX(oprofile_perf_mutex);
+
+static struct op_counter_config *counter_config;
+static struct perf_event **perf_events[nr_cpumask_bits];
+static int num_counters;
+
+/*
+ * Overflow callback for oprofile.
+ */
+static void op_overflow_handler(struct perf_event *event, int unused,
+			struct perf_sample_data *data, struct pt_regs *regs)
+{
+	int id;
+	u32 cpu = smp_processor_id();
+
+	for (id = 0; id < num_counters; ++id)
+		if (perf_events[cpu][id] == event)
+			break;
+
+	if (id != num_counters)
+		oprofile_add_sample(regs, id);
+	else
+		pr_warning("oprofile: ignoring spurious overflow "
+				"on cpu %u\n", cpu);
+}
+
+/*
+ * Called by oprofile_perf_setup to create perf attributes to mirror the oprofile
+ * settings in counter_config. Attributes are created as `pinned' events and
+ * so are permanently scheduled on the PMU.
+ */
+static void op_perf_setup(void)
+{
+	int i;
+	u32 size = sizeof(struct perf_event_attr);
+	struct perf_event_attr *attr;
+
+	for (i = 0; i < num_counters; ++i) {
+		attr = &counter_config[i].attr;
+		memset(attr, 0, size);
+		attr->type		= PERF_TYPE_RAW;
+		attr->size		= size;
+		attr->config		= counter_config[i].event;
+		attr->sample_period	= counter_config[i].count;
+		attr->pinned		= 1;
+	}
+}
+
+static int op_create_counter(int cpu, int event)
+{
+	struct perf_event *pevent;
+
+	if (!counter_config[event].enabled || perf_events[cpu][event])
+		return 0;
+
+	pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
+						  cpu, NULL,
+						  op_overflow_handler);
+
+	if (IS_ERR(pevent))
+		return PTR_ERR(pevent);
+
+	if (pevent->state != PERF_EVENT_STATE_ACTIVE) {
+		perf_event_release_kernel(pevent);
+		pr_warning("oprofile: failed to enable event %d "
+				"on CPU %d\n", event, cpu);
+		return -EBUSY;
+	}
+
+	perf_events[cpu][event] = pevent;
+
+	return 0;
+}
+
+static void op_destroy_counter(int cpu, int event)
+{
+	struct perf_event *pevent = perf_events[cpu][event];
+
+	if (pevent) {
+		perf_event_release_kernel(pevent);
+		perf_events[cpu][event] = NULL;
+	}
+}
+
+/*
+ * Called by oprofile_perf_start to create active perf events based on the
+ * perviously configured attributes.
+ */
+static int op_perf_start(void)
+{
+	int cpu, event, ret = 0;
+
+	for_each_online_cpu(cpu) {
+		for (event = 0; event < num_counters; ++event) {
+			ret = op_create_counter(cpu, event);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * Called by oprofile_perf_stop at the end of a profiling run.
+ */
+static void op_perf_stop(void)
+{
+	int cpu, event;
+
+	for_each_online_cpu(cpu)
+		for (event = 0; event < num_counters; ++event)
+			op_destroy_counter(cpu, event);
+}
+
+static int oprofile_perf_create_files(struct super_block *sb, struct dentry *root)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_counters; i++) {
+		struct dentry *dir;
+		char buf[4];
+
+		snprintf(buf, sizeof buf, "%d", i);
+		dir = oprofilefs_mkdir(sb, root, buf);
+		oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
+		oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);
+		oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);
+		oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
+		oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
+		oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
+	}
+
+	return 0;
+}
+
+static int oprofile_perf_setup(void)
+{
+	spin_lock(&oprofilefs_lock);
+	op_perf_setup();
+	spin_unlock(&oprofilefs_lock);
+	return 0;
+}
+
+static int oprofile_perf_start(void)
+{
+	int ret = -EBUSY;
+
+	mutex_lock(&oprofile_perf_mutex);
+	if (!oprofile_perf_enabled) {
+		ret = 0;
+		op_perf_start();
+		oprofile_perf_enabled = 1;
+	}
+	mutex_unlock(&oprofile_perf_mutex);
+	return ret;
+}
+
+static void oprofile_perf_stop(void)
+{
+	mutex_lock(&oprofile_perf_mutex);
+	if (oprofile_perf_enabled)
+		op_perf_stop();
+	oprofile_perf_enabled = 0;
+	mutex_unlock(&oprofile_perf_mutex);
+}
+
+#ifdef CONFIG_PM
+
+static int oprofile_perf_suspend(struct platform_device *dev, pm_message_t state)
+{
+	mutex_lock(&oprofile_perf_mutex);
+	if (oprofile_perf_enabled)
+		op_perf_stop();
+	mutex_unlock(&oprofile_perf_mutex);
+	return 0;
+}
+
+static int oprofile_perf_resume(struct platform_device *dev)
+{
+	mutex_lock(&oprofile_perf_mutex);
+	if (oprofile_perf_enabled && op_perf_start())
+		oprofile_perf_enabled = 0;
+	mutex_unlock(&oprofile_perf_mutex);
+	return 0;
+}
+
+static struct platform_driver oprofile_driver = {
+	.driver		= {
+		.name		= "oprofile-perf",
+	},
+	.resume		= oprofile_perf_resume,
+	.suspend	= oprofile_perf_suspend,
+};
+
+static struct platform_device *oprofile_pdev;
+
+static int __init init_driverfs(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&oprofile_driver);
+	if (ret)
+		return ret;
+
+	oprofile_pdev =	platform_device_register_simple(
+				oprofile_driver.driver.name, 0, NULL, 0);
+	if (IS_ERR(oprofile_pdev)) {
+		ret = PTR_ERR(oprofile_pdev);
+		platform_driver_unregister(&oprofile_driver);
+	}
+
+	return ret;
+}
+
+static void exit_driverfs(void)
+{
+	platform_device_unregister(oprofile_pdev);
+	platform_driver_unregister(&oprofile_driver);
+}
+
+#else
+
+static inline int  init_driverfs(void) { return 0; }
+static inline void exit_driverfs(void) { }
+
+#endif /* CONFIG_PM */
+
+void oprofile_perf_exit(void)
+{
+	int cpu, id;
+	struct perf_event *event;
+
+	for_each_possible_cpu(cpu) {
+		for (id = 0; id < num_counters; ++id) {
+			event = perf_events[cpu][id];
+			if (event)
+				perf_event_release_kernel(event);
+		}
+
+		kfree(perf_events[cpu]);
+	}
+
+	kfree(counter_config);
+	exit_driverfs();
+}
+
+int __init oprofile_perf_init(struct oprofile_operations *ops)
+{
+	int cpu, ret = 0;
+
+	ret = init_driverfs();
+	if (ret)
+		return ret;
+
+	memset(&perf_events, 0, sizeof(perf_events));
+
+	num_counters = perf_num_counters();
+	if (num_counters <= 0) {
+		pr_info("oprofile: no performance counters\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	counter_config = kcalloc(num_counters,
+			sizeof(struct op_counter_config), GFP_KERNEL);
+
+	if (!counter_config) {
+		pr_info("oprofile: failed to allocate %d "
+				"counters\n", num_counters);
+		ret = -ENOMEM;
+		num_counters = 0;
+		goto out;
+	}
+
+	for_each_possible_cpu(cpu) {
+		perf_events[cpu] = kcalloc(num_counters,
+				sizeof(struct perf_event *), GFP_KERNEL);
+		if (!perf_events[cpu]) {
+			pr_info("oprofile: failed to allocate %d perf events "
+					"for cpu %d\n", num_counters, cpu);
+			ret = -ENOMEM;
+			goto out;
+		}
+	}
+
+	ops->create_files	= oprofile_perf_create_files;
+	ops->setup		= oprofile_perf_setup;
+	ops->start		= oprofile_perf_start;
+	ops->stop		= oprofile_perf_stop;
+	ops->shutdown		= oprofile_perf_stop;
+	ops->cpu_type		= op_name_from_perf_id();
+
+	if (!ops->cpu_type)
+		ret = -ENODEV;
+	else
+		pr_info("oprofile: using %s\n", ops->cpu_type);
+
+out:
+	if (ret)
+		oprofile_perf_exit();
+
+	return ret;
+}
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index 2766a6d..95f711b 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -91,16 +91,20 @@
 
 static ssize_t ulong_write_file(struct file *file, char const __user *buf, size_t count, loff_t *offset)
 {
-	unsigned long *value = file->private_data;
+	unsigned long value;
 	int retval;
 
 	if (*offset)
 		return -EINVAL;
 
-	retval = oprofilefs_ulong_from_user(value, buf, count);
-
+	retval = oprofilefs_ulong_from_user(&value, buf, count);
 	if (retval)
 		return retval;
+
+	retval = oprofile_set_ulong(file->private_data, value);
+	if (retval)
+		return retval;
+
 	return count;
 }
 
@@ -117,59 +121,52 @@
 	.read		= ulong_read_file,
 	.write		= ulong_write_file,
 	.open		= default_open,
+	.llseek		= default_llseek,
 };
 
 
 static const struct file_operations ulong_ro_fops = {
 	.read		= ulong_read_file,
 	.open		= default_open,
+	.llseek		= default_llseek,
 };
 
 
-static struct dentry *__oprofilefs_create_file(struct super_block *sb,
+static int __oprofilefs_create_file(struct super_block *sb,
 	struct dentry *root, char const *name, const struct file_operations *fops,
-	int perm)
+	int perm, void *priv)
 {
 	struct dentry *dentry;
 	struct inode *inode;
 
 	dentry = d_alloc_name(root, name);
 	if (!dentry)
-		return NULL;
+		return -ENOMEM;
 	inode = oprofilefs_get_inode(sb, S_IFREG | perm);
 	if (!inode) {
 		dput(dentry);
-		return NULL;
+		return -ENOMEM;
 	}
 	inode->i_fop = fops;
 	d_add(dentry, inode);
-	return dentry;
+	dentry->d_inode->i_private = priv;
+	return 0;
 }
 
 
 int oprofilefs_create_ulong(struct super_block *sb, struct dentry *root,
 	char const *name, unsigned long *val)
 {
-	struct dentry *d = __oprofilefs_create_file(sb, root, name,
-						     &ulong_fops, 0644);
-	if (!d)
-		return -EFAULT;
-
-	d->d_inode->i_private = val;
-	return 0;
+	return __oprofilefs_create_file(sb, root, name,
+					&ulong_fops, 0644, val);
 }
 
 
 int oprofilefs_create_ro_ulong(struct super_block *sb, struct dentry *root,
 	char const *name, unsigned long *val)
 {
-	struct dentry *d = __oprofilefs_create_file(sb, root, name,
-						     &ulong_ro_fops, 0444);
-	if (!d)
-		return -EFAULT;
-
-	d->d_inode->i_private = val;
-	return 0;
+	return __oprofilefs_create_file(sb, root, name,
+					&ulong_ro_fops, 0444, val);
 }
 
 
@@ -183,37 +180,29 @@
 static const struct file_operations atomic_ro_fops = {
 	.read		= atomic_read_file,
 	.open		= default_open,
+	.llseek		= default_llseek,
 };
 
 
 int oprofilefs_create_ro_atomic(struct super_block *sb, struct dentry *root,
 	char const *name, atomic_t *val)
 {
-	struct dentry *d = __oprofilefs_create_file(sb, root, name,
-						     &atomic_ro_fops, 0444);
-	if (!d)
-		return -EFAULT;
-
-	d->d_inode->i_private = val;
-	return 0;
+	return __oprofilefs_create_file(sb, root, name,
+					&atomic_ro_fops, 0444, val);
 }
 
 
 int oprofilefs_create_file(struct super_block *sb, struct dentry *root,
 	char const *name, const struct file_operations *fops)
 {
-	if (!__oprofilefs_create_file(sb, root, name, fops, 0644))
-		return -EFAULT;
-	return 0;
+	return __oprofilefs_create_file(sb, root, name, fops, 0644, NULL);
 }
 
 
 int oprofilefs_create_file_perm(struct super_block *sb, struct dentry *root,
 	char const *name, const struct file_operations *fops, int perm)
 {
-	if (!__oprofilefs_create_file(sb, root, name, fops, perm))
-		return -EFAULT;
-	return 0;
+	return __oprofilefs_create_file(sb, root, name, fops, perm, NULL);
 }
 
 
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 23e50f4..787ebde 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -48,7 +48,6 @@
 #include <linux/parport.h>
 #include <linux/parport_pc.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/cisreg.h>
@@ -81,14 +80,6 @@
 static int parport_config(struct pcmcia_device *link);
 static void parport_cs_release(struct pcmcia_device *);
 
-/*======================================================================
-
-    parport_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int parport_probe(struct pcmcia_device *link)
 {
     parport_info_t *info;
@@ -101,23 +92,11 @@
     link->priv = info;
     info->p_dev = link;
 
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
     return parport_config(link);
 } /* parport_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void parport_detach(struct pcmcia_device *link)
 {
     dev_dbg(&link->dev, "parport_detach\n");
@@ -127,36 +106,14 @@
     kfree(link->priv);
 } /* parport_detach */
 
-/*======================================================================
-
-    parport_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    parport device available to the system.
-
-======================================================================*/
-
-static int parport_config_check(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
-				void *priv_data)
+static int parport_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		if (epp_mode)
-			p_dev->conf.ConfigIndex |= FORCE_EPP_MODE;
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin == 2) {
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		if (pcmcia_request_io(p_dev) != 0)
-			return -ENODEV;
-		return 0;
-	}
-	return -ENODEV;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int parport_config(struct pcmcia_device *link)
@@ -167,13 +124,16 @@
 
     dev_dbg(&link->dev, "parport_config\n");
 
+    if (epp_mode)
+	    link->config_index |= FORCE_EPP_MODE;
+
     ret = pcmcia_loop_config(link, parport_config_check, NULL);
     if (ret)
 	    goto failed;
 
     if (!link->irq)
 	    goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
@@ -202,14 +162,6 @@
     return -ENODEV;
 } /* parport_config */
 
-/*======================================================================
-
-    After a card is removed, parport_cs_release() will unregister the
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-    
-======================================================================*/
-
 static void parport_cs_release(struct pcmcia_device *link)
 {
 	parport_info_t *info = link->priv;
@@ -236,9 +188,7 @@
 
 static struct pcmcia_driver parport_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "parport_cs",
-	},
+	.name		= "parport_cs",
 	.probe		= parport_probe,
 	.remove		= parport_detach,
 	.id_table	= parport_ids,
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index dffa5d4..a2d9d1e 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -306,7 +306,7 @@
 	spin_lock_init(&tmp->pardevice_lock);
 	tmp->ieee1284.mode = IEEE1284_MODE_COMPAT;
 	tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-	init_MUTEX_LOCKED (&tmp->ieee1284.irq); /* actually a semaphore at 0 */
+	sema_init(&tmp->ieee1284.irq, 0);
 	tmp->spintime = parport_default_spintime;
 	atomic_set (&tmp->ref_count, 1);
 	INIT_LIST_HEAD(&tmp->full_list);
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 0a19708..0157708 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -36,6 +36,7 @@
 #include <linux/tboot.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <asm/iommu_table.h>
 
 #define PREFIX "DMAR: "
 
@@ -687,7 +688,7 @@
 	return 0;
 }
 
-void __init detect_intel_iommu(void)
+int __init detect_intel_iommu(void)
 {
 	int ret;
 
@@ -723,6 +724,8 @@
 	}
 	early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size);
 	dmar_tbl = NULL;
+
+	return ret ? 1 : -ENODEV;
 }
 
 
@@ -1221,9 +1224,9 @@
 	}
 }
 
-void dmar_msi_unmask(unsigned int irq)
+void dmar_msi_unmask(struct irq_data *data)
 {
-	struct intel_iommu *iommu = get_irq_data(irq);
+	struct intel_iommu *iommu = irq_data_get_irq_data(data);
 	unsigned long flag;
 
 	/* unmask it */
@@ -1234,10 +1237,10 @@
 	spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
-void dmar_msi_mask(unsigned int irq)
+void dmar_msi_mask(struct irq_data *data)
 {
 	unsigned long flag;
-	struct intel_iommu *iommu = get_irq_data(irq);
+	struct intel_iommu *iommu = irq_data_get_irq_data(data);
 
 	/* mask it */
 	spin_lock_irqsave(&iommu->register_lock, flag);
@@ -1455,3 +1458,4 @@
 		return 0;
 	return dmar->flags & 0x1;
 }
+IOMMU_INIT_POST(detect_intel_iommu);
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 5621532..4cb3044 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -34,10 +34,11 @@
 #include <linux/workqueue.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/debugfs.h>
 #include "cpqphp.h"
 
+static DEFINE_MUTEX(cpqphp_mutex);
 static int show_ctrl (struct controller *ctrl, char *buf)
 {
 	char *out = buf;
@@ -147,7 +148,7 @@
 	struct ctrl_dbg *dbg;
 	int retval = -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&cpqphp_mutex);
 	dbg = kmalloc(sizeof(*dbg), GFP_KERNEL);
 	if (!dbg)
 		goto exit;
@@ -160,7 +161,7 @@
 	file->private_data = dbg;
 	retval = 0;
 exit:
-	unlock_kernel();
+	mutex_unlock(&cpqphp_mutex);
 	return retval;
 }
 
@@ -169,7 +170,7 @@
 	struct ctrl_dbg *dbg;
 	loff_t new = -1;
 
-	lock_kernel();
+	mutex_lock(&cpqphp_mutex);
 	dbg = file->private_data;
 
 	switch (whence) {
@@ -181,10 +182,10 @@
 		break;
 	}
 	if (new < 0 || new > dbg->size) {
-		unlock_kernel();
+		mutex_unlock(&cpqphp_mutex);
 		return -EINVAL;
 	}
-	unlock_kernel();
+	mutex_unlock(&cpqphp_mutex);
 	return (file->f_pos = new);
 }
 
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 73d5139..838f571 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -36,6 +36,7 @@
 #include <linux/sched.h>		/* signal_pending() */
 #include <linux/pcieport_if.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #define MY_NAME	"pciehp"
 
@@ -44,6 +45,7 @@
 extern int pciehp_debug;
 extern int pciehp_force;
 extern struct workqueue_struct *pciehp_wq;
+extern struct workqueue_struct *pciehp_ordered_wq;
 
 #define dbg(format, arg...)						\
 do {									\
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index aa5f3ff..7ac8358 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -43,6 +43,7 @@
 int pciehp_poll_time;
 int pciehp_force;
 struct workqueue_struct *pciehp_wq;
+struct workqueue_struct *pciehp_ordered_wq;
 
 #define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -340,18 +341,33 @@
 {
 	int retval = 0;
 
+	pciehp_wq = alloc_workqueue("pciehp", 0, 0);
+	if (!pciehp_wq)
+		return -ENOMEM;
+
+	pciehp_ordered_wq = alloc_ordered_workqueue("pciehp_ordered", 0);
+	if (!pciehp_ordered_wq) {
+		destroy_workqueue(pciehp_wq);
+		return -ENOMEM;
+	}
+
 	pciehp_firmware_init();
 	retval = pcie_port_service_register(&hpdriver_portdrv);
  	dbg("pcie_port_service_register = %d\n", retval);
   	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
- 	if (retval)
+ 	if (retval) {
+		destroy_workqueue(pciehp_ordered_wq);
+		destroy_workqueue(pciehp_wq);
 		dbg("Failure to register service\n");
+	}
 	return retval;
 }
 
 static void __exit pcied_cleanup(void)
 {
 	dbg("unload_pciehpd()\n");
+	destroy_workqueue(pciehp_ordered_wq);
+	destroy_workqueue(pciehp_wq);
 	pcie_port_service_unregister(&hpdriver_portdrv);
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 8f58148..085dbb5 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -32,7 +32,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/workqueue.h>
 #include "../pci.h"
 #include "pciehp.h"
 
@@ -50,7 +49,7 @@
 	info->p_slot = p_slot;
 	INIT_WORK(&info->work, interrupt_event_handler);
 
-	schedule_work(&info->work);
+	queue_work(pciehp_wq, &info->work);
 
 	return 0;
 }
@@ -345,7 +344,7 @@
 		kfree(info);
 		goto out;
 	}
-	queue_work(pciehp_wq, &info->work);
+	queue_work(pciehp_ordered_wq, &info->work);
  out:
 	mutex_unlock(&p_slot->lock);
 }
@@ -378,7 +377,7 @@
 		if (ATTN_LED(ctrl))
 			pciehp_set_attention_status(p_slot, 0);
 
-		schedule_delayed_work(&p_slot->work, 5*HZ);
+		queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ);
 		break;
 	case BLINKINGOFF_STATE:
 	case BLINKINGON_STATE:
@@ -440,7 +439,7 @@
 	else
 		p_slot->state = POWERON_STATE;
 
-	queue_work(pciehp_wq, &info->work);
+	queue_work(pciehp_ordered_wq, &info->work);
 }
 
 static void interrupt_event_handler(struct work_struct *work)
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 0cd4204..50a23da 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -41,8 +41,6 @@
 #include "../pci.h"
 #include "pciehp.h"
 
-static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
-
 static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value)
 {
 	struct pci_dev *dev = ctrl->pcie->port;
@@ -805,8 +803,8 @@
 {
 	struct slot *slot = ctrl->slot;
 	cancel_delayed_work(&slot->work);
-	flush_scheduled_work();
 	flush_workqueue(pciehp_wq);
+	flush_workqueue(pciehp_ordered_wq);
 	kfree(slot);
 }
 
@@ -912,16 +910,6 @@
 	/* Disable sotfware notification */
 	pcie_disable_notification(ctrl);
 
-	/*
-	 * If this is the first controller to be initialized,
-	 * initialize the pciehp work queue
-	 */
-	if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
-		pciehp_wq = create_singlethread_workqueue("pciehpd");
-		if (!pciehp_wq)
-			goto abort_ctrl;
-	}
-
 	ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
 		  pdev->vendor, pdev->device, pdev->subsystem_vendor,
 		  pdev->subsystem_device);
@@ -941,11 +929,5 @@
 {
 	pcie_shutdown_notification(ctrl);
 	pcie_cleanup_slot(ctrl);
-	/*
-	 * If this is the last controller to be released, destroy the
-	 * pciehp work queue
-	 */
-	if (atomic_dec_and_test(&pciehp_num_controllers))
-		destroy_workqueue(pciehp_wq);
 	kfree(ctrl);
 }
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index d2627e1..e0c90e6 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -35,6 +35,7 @@
 #include <linux/delay.h>
 #include <linux/sched.h>	/* signal_pending(), struct timer_list */
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #if !defined(MODULE)
 	#define MY_NAME	"shpchp"
@@ -46,6 +47,7 @@
 extern int shpchp_poll_time;
 extern int shpchp_debug;
 extern struct workqueue_struct *shpchp_wq;
+extern struct workqueue_struct *shpchp_ordered_wq;
 
 #define dbg(format, arg...)						\
 do {									\
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index a7bd504..aca972b 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -33,7 +33,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/workqueue.h>
 #include "shpchp.h"
 
 /* Global variables */
@@ -41,6 +40,7 @@
 int shpchp_poll_mode;
 int shpchp_poll_time;
 struct workqueue_struct *shpchp_wq;
+struct workqueue_struct *shpchp_ordered_wq;
 
 #define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -174,8 +174,8 @@
 		slot = list_entry(tmp, struct slot, slot_list);
 		list_del(&slot->slot_list);
 		cancel_delayed_work(&slot->work);
-		flush_scheduled_work();
 		flush_workqueue(shpchp_wq);
+		flush_workqueue(shpchp_ordered_wq);
 		pci_hp_deregister(slot->hotplug_slot);
 	}
 }
@@ -360,9 +360,23 @@
 {
 	int retval = 0;
 
+	shpchp_wq = alloc_ordered_workqueue("shpchp", 0);
+	if (!shpchp_wq)
+		return -ENOMEM;
+
+	shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0);
+	if (!shpchp_ordered_wq) {
+		destroy_workqueue(shpchp_wq);
+		return -ENOMEM;
+	}
+
 	retval = pci_register_driver(&shpc_driver);
 	dbg("%s: pci_register_driver = %d\n", __func__, retval);
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+	if (retval) {
+		destroy_workqueue(shpchp_ordered_wq);
+		destroy_workqueue(shpchp_wq);
+	}
 	return retval;
 }
 
@@ -370,6 +384,8 @@
 {
 	dbg("unload_shpchpd()\n");
 	pci_unregister_driver(&shpc_driver);
+	destroy_workqueue(shpchp_ordered_wq);
+	destroy_workqueue(shpchp_wq);
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 3387fbf..b00b09b 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -32,7 +32,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/workqueue.h>
 #include "../pci.h"
 #include "shpchp.h"
 
@@ -52,7 +51,7 @@
 	info->p_slot = p_slot;
 	INIT_WORK(&info->work, interrupt_event_handler);
 
-	schedule_work(&info->work);
+	queue_work(shpchp_wq, &info->work);
 
 	return 0;
 }
@@ -457,7 +456,7 @@
 		kfree(info);
 		goto out;
 	}
-	queue_work(shpchp_wq, &info->work);
+	queue_work(shpchp_ordered_wq, &info->work);
  out:
 	mutex_unlock(&p_slot->lock);
 }
@@ -505,7 +504,7 @@
 		p_slot->hpc_ops->green_led_blink(p_slot);
 		p_slot->hpc_ops->set_attention_status(p_slot, 0);
 
-		schedule_delayed_work(&p_slot->work, 5*HZ);
+		queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ);
 		break;
 	case BLINKINGOFF_STATE:
 	case BLINKINGON_STATE:
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index d3985e7..36547f0 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -179,8 +179,6 @@
 #define SLOT_EVENT_LATCH	0x2
 #define SLOT_SERR_INT_MASK	0x3
 
-static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
-
 static irqreturn_t shpc_isr(int irq, void *dev_id);
 static void start_int_poll_timer(struct controller *ctrl, int sec);
 static int hpc_check_cmd_status(struct controller *ctrl);
@@ -614,13 +612,6 @@
 
 	iounmap(ctrl->creg);
 	release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
-
-	/*
-	 * If this is the last controller to be released, destroy the
-	 * shpchpd work queue
-	 */
-	if (atomic_dec_and_test(&shpchp_num_controllers))
-		destroy_workqueue(shpchp_wq);
 }
 
 static int hpc_power_on_slot(struct slot * slot)
@@ -1077,9 +1068,8 @@
 
 		rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
 				 MY_NAME, (void *)ctrl);
-		ctrl_dbg(ctrl, "request_irq %d for hpc%d (returns %d)\n",
-			 ctrl->pci_dev->irq,
-		    atomic_read(&shpchp_num_controllers), rc);
+		ctrl_dbg(ctrl, "request_irq %d (returns %d)\n",
+			 ctrl->pci_dev->irq, rc);
 		if (rc) {
 			ctrl_err(ctrl, "Can't get irq %d for the hotplug "
 				 "controller\n", ctrl->pci_dev->irq);
@@ -1092,18 +1082,6 @@
 	shpc_get_cur_bus_speed(ctrl);
 
 	/*
-	 * If this is the first controller to be initialized,
-	 * initialize the shpchpd work queue
-	 */
-	if (atomic_add_return(1, &shpchp_num_controllers) == 1) {
-		shpchp_wq = create_singlethread_workqueue("shpchpd");
-		if (!shpchp_wq) {
-			rc = -ENOMEM;
-			goto abort_iounmap;
-		}
-	}
-
-	/*
 	 * Unmask all event interrupts of all slots
 	 */
 	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c
index 98abf8b..834842a 100644
--- a/drivers/pci/htirq.c
+++ b/drivers/pci/htirq.c
@@ -57,28 +57,22 @@
 	*msg = cfg->msg;
 }
 
-void mask_ht_irq(unsigned int irq)
+void mask_ht_irq(struct irq_data *data)
 {
-	struct ht_irq_cfg *cfg;
-	struct ht_irq_msg msg;
+	struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+	struct ht_irq_msg msg = cfg->msg;
 
-	cfg = get_irq_data(irq);
-
-	msg = cfg->msg;
 	msg.address_lo |= 1;
-	write_ht_irq_msg(irq, &msg);
+	write_ht_irq_msg(data->irq, &msg);
 }
 
-void unmask_ht_irq(unsigned int irq)
+void unmask_ht_irq(struct irq_data *data)
 {
-	struct ht_irq_cfg *cfg;
-	struct ht_irq_msg msg;
+	struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+	struct ht_irq_msg msg = cfg->msg;
 
-	cfg = get_irq_data(irq);
-
-	msg = cfg->msg;
 	msg.address_lo &= ~1;
-	write_ht_irq_msg(irq, &msg);
+	write_ht_irq_msg(data->irq, &msg);
 }
 
 /**
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 5ac2aa7..4789f8e 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -3757,6 +3757,33 @@
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
 
+#define GGC 0x52
+#define GGC_MEMORY_SIZE_MASK	(0xf << 8)
+#define GGC_MEMORY_SIZE_NONE	(0x0 << 8)
+#define GGC_MEMORY_SIZE_1M	(0x1 << 8)
+#define GGC_MEMORY_SIZE_2M	(0x3 << 8)
+#define GGC_MEMORY_VT_ENABLED	(0x8 << 8)
+#define GGC_MEMORY_SIZE_2M_VT	(0x9 << 8)
+#define GGC_MEMORY_SIZE_3M_VT	(0xa << 8)
+#define GGC_MEMORY_SIZE_4M_VT	(0xb << 8)
+
+static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
+{
+	unsigned short ggc;
+
+	if (pci_read_config_word(dev, GGC, &ggc))
+		return;
+
+	if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
+		printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
+		dmar_map_gfx = 0;
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
+
 /* On Tylersburg chipsets, some BIOSes have been known to enable the
    ISOCH DMAR unit for the Azalia sound device, but not give it any
    TLB entries, which causes it to deadlock. Check for that.  We do
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index fd1d286..ec87cd6 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -46,109 +46,24 @@
 }
 early_param("intremap", setup_intremap);
 
-struct irq_2_iommu {
-	struct intel_iommu *iommu;
-	u16 irte_index;
-	u16 sub_handle;
-	u8  irte_mask;
-};
-
-#ifdef CONFIG_GENERIC_HARDIRQS
-static struct irq_2_iommu *get_one_free_irq_2_iommu(int node)
-{
-	struct irq_2_iommu *iommu;
-
-	iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
-	printk(KERN_DEBUG "alloc irq_2_iommu on node %d\n", node);
-
-	return iommu;
-}
-
-static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
-{
-	struct irq_desc *desc;
-
-	desc = irq_to_desc(irq);
-
-	if (WARN_ON_ONCE(!desc))
-		return NULL;
-
-	return desc->irq_2_iommu;
-}
-
-static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
-{
-	struct irq_desc *desc;
-	struct irq_2_iommu *irq_iommu;
-
-	desc = irq_to_desc(irq);
-	if (!desc) {
-		printk(KERN_INFO "can not get irq_desc for %d\n", irq);
-		return NULL;
-	}
-
-	irq_iommu = desc->irq_2_iommu;
-
-	if (!irq_iommu)
-		desc->irq_2_iommu = get_one_free_irq_2_iommu(irq_node(irq));
-
-	return desc->irq_2_iommu;
-}
-
-#else /* !CONFIG_SPARSE_IRQ */
-
-static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
-
-static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
-{
-	if (irq < nr_irqs)
-		return &irq_2_iommuX[irq];
-
-	return NULL;
-}
-static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
-{
-	return irq_2_iommu(irq);
-}
-#endif
-
 static DEFINE_SPINLOCK(irq_2_ir_lock);
 
-static struct irq_2_iommu *valid_irq_2_iommu(unsigned int irq)
+static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
 {
-	struct irq_2_iommu *irq_iommu;
-
-	irq_iommu = irq_2_iommu(irq);
-
-	if (!irq_iommu)
-		return NULL;
-
-	if (!irq_iommu->iommu)
-		return NULL;
-
-	return irq_iommu;
-}
-
-int irq_remapped(int irq)
-{
-	return valid_irq_2_iommu(irq) != NULL;
+	struct irq_cfg *cfg = get_irq_chip_data(irq);
+	return cfg ? &cfg->irq_2_iommu : NULL;
 }
 
 int get_irte(int irq, struct irte *entry)
 {
-	int index;
-	struct irq_2_iommu *irq_iommu;
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
 	unsigned long flags;
+	int index;
 
-	if (!entry)
+	if (!entry || !irq_iommu)
 		return -1;
 
 	spin_lock_irqsave(&irq_2_ir_lock, flags);
-	irq_iommu = valid_irq_2_iommu(irq);
-	if (!irq_iommu) {
-		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-		return -1;
-	}
 
 	index = irq_iommu->irte_index + irq_iommu->sub_handle;
 	*entry = *(irq_iommu->iommu->ir_table->base + index);
@@ -160,21 +75,15 @@
 int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
 {
 	struct ir_table *table = iommu->ir_table;
-	struct irq_2_iommu *irq_iommu;
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
 	u16 index, start_index;
 	unsigned int mask = 0;
 	unsigned long flags;
 	int i;
 
-	if (!count)
+	if (!count || !irq_iommu)
 		return -1;
 
-#ifndef CONFIG_SPARSE_IRQ
-	/* protect irq_2_iommu_alloc later */
-	if (irq >= nr_irqs)
-		return -1;
-#endif
-
 	/*
 	 * start the IRTE search from index 0.
 	 */
@@ -214,13 +123,6 @@
 	for (i = index; i < index + count; i++)
 		table->base[i].present = 1;
 
-	irq_iommu = irq_2_iommu_alloc(irq);
-	if (!irq_iommu) {
-		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-		printk(KERN_ERR "can't allocate irq_2_iommu\n");
-		return -1;
-	}
-
 	irq_iommu->iommu = iommu;
 	irq_iommu->irte_index =  index;
 	irq_iommu->sub_handle = 0;
@@ -244,17 +146,14 @@
 
 int map_irq_to_irte_handle(int irq, u16 *sub_handle)
 {
-	int index;
-	struct irq_2_iommu *irq_iommu;
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
 	unsigned long flags;
+	int index;
+
+	if (!irq_iommu)
+		return -1;
 
 	spin_lock_irqsave(&irq_2_ir_lock, flags);
-	irq_iommu = valid_irq_2_iommu(irq);
-	if (!irq_iommu) {
-		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-		return -1;
-	}
-
 	*sub_handle = irq_iommu->sub_handle;
 	index = irq_iommu->irte_index;
 	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
@@ -263,18 +162,13 @@
 
 int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
 {
-	struct irq_2_iommu *irq_iommu;
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
 	unsigned long flags;
 
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
-
-	irq_iommu = irq_2_iommu_alloc(irq);
-
-	if (!irq_iommu) {
-		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-		printk(KERN_ERR "can't allocate irq_2_iommu\n");
+	if (!irq_iommu)
 		return -1;
-	}
+
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
 
 	irq_iommu->iommu = iommu;
 	irq_iommu->irte_index = index;
@@ -286,43 +180,18 @@
 	return 0;
 }
 
-int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
-{
-	struct irq_2_iommu *irq_iommu;
-	unsigned long flags;
-
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
-	irq_iommu = valid_irq_2_iommu(irq);
-	if (!irq_iommu) {
-		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-		return -1;
-	}
-
-	irq_iommu->iommu = NULL;
-	irq_iommu->irte_index = 0;
-	irq_iommu->sub_handle = 0;
-	irq_2_iommu(irq)->irte_mask = 0;
-
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
-	return 0;
-}
-
 int modify_irte(int irq, struct irte *irte_modified)
 {
-	int rc;
-	int index;
-	struct irte *irte;
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
 	struct intel_iommu *iommu;
-	struct irq_2_iommu *irq_iommu;
 	unsigned long flags;
+	struct irte *irte;
+	int rc, index;
+
+	if (!irq_iommu)
+		return -1;
 
 	spin_lock_irqsave(&irq_2_ir_lock, flags);
-	irq_iommu = valid_irq_2_iommu(irq);
-	if (!irq_iommu) {
-		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-		return -1;
-	}
 
 	iommu = irq_iommu->iommu;
 
@@ -339,31 +208,6 @@
 	return rc;
 }
 
-int flush_irte(int irq)
-{
-	int rc;
-	int index;
-	struct intel_iommu *iommu;
-	struct irq_2_iommu *irq_iommu;
-	unsigned long flags;
-
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
-	irq_iommu = valid_irq_2_iommu(irq);
-	if (!irq_iommu) {
-		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-		return -1;
-	}
-
-	iommu = irq_iommu->iommu;
-
-	index = irq_iommu->irte_index + irq_iommu->sub_handle;
-
-	rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
-	return rc;
-}
-
 struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
 {
 	int i;
@@ -420,16 +264,14 @@
 
 int free_irte(int irq)
 {
-	int rc = 0;
-	struct irq_2_iommu *irq_iommu;
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
 	unsigned long flags;
+	int rc;
+
+	if (!irq_iommu)
+		return -1;
 
 	spin_lock_irqsave(&irq_2_ir_lock, flags);
-	irq_iommu = valid_irq_2_iommu(irq);
-	if (!irq_iommu) {
-		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-		return -1;
-	}
 
 	rc = clear_entries(irq_iommu);
 
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index ce6a366..553d8ee 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -608,7 +608,7 @@
  * the VF BAR size multiplied by the number of VFs.  The alignment
  * is just the VF BAR size.
  */
-int pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
+resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
 {
 	struct resource tmp;
 	enum pci_bar_type type;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 69b7be3..5fcf5ae 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -170,33 +170,31 @@
 	desc->masked = __msix_mask_irq(desc, flag);
 }
 
-static void msi_set_mask_bit(unsigned irq, u32 flag)
+static void msi_set_mask_bit(struct irq_data *data, u32 flag)
 {
-	struct msi_desc *desc = get_irq_msi(irq);
+	struct msi_desc *desc = irq_data_get_msi(data);
 
 	if (desc->msi_attrib.is_msix) {
 		msix_mask_irq(desc, flag);
 		readl(desc->mask_base);		/* Flush write to device */
 	} else {
-		unsigned offset = irq - desc->dev->irq;
+		unsigned offset = data->irq - desc->dev->irq;
 		msi_mask_irq(desc, 1 << offset, flag << offset);
 	}
 }
 
-void mask_msi_irq(unsigned int irq)
+void mask_msi_irq(struct irq_data *data)
 {
-	msi_set_mask_bit(irq, 1);
+	msi_set_mask_bit(data, 1);
 }
 
-void unmask_msi_irq(unsigned int irq)
+void unmask_msi_irq(struct irq_data *data)
 {
-	msi_set_mask_bit(irq, 0);
+	msi_set_mask_bit(data, 0);
 }
 
-void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
-	struct msi_desc *entry = get_irq_desc_msi(desc);
-
 	BUG_ON(entry->dev->current_state != PCI_D0);
 
 	if (entry->msi_attrib.is_msix) {
@@ -227,15 +225,13 @@
 
 void read_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
+	struct msi_desc *entry = get_irq_msi(irq);
 
-	read_msi_msg_desc(desc, msg);
+	__read_msi_msg(entry, msg);
 }
 
-void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
-	struct msi_desc *entry = get_irq_desc_msi(desc);
-
 	/* Assert that the cache is valid, assuming that
 	 * valid messages are not all-zeroes. */
 	BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo |
@@ -246,15 +242,13 @@
 
 void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
+	struct msi_desc *entry = get_irq_msi(irq);
 
-	get_cached_msi_msg_desc(desc, msg);
+	__get_cached_msi_msg(entry, msg);
 }
 
-void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
-	struct msi_desc *entry = get_irq_desc_msi(desc);
-
 	if (entry->dev->current_state != PCI_D0) {
 		/* Don't touch the hardware now */
 	} else if (entry->msi_attrib.is_msix) {
@@ -292,9 +286,9 @@
 
 void write_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
+	struct msi_desc *entry = get_irq_msi(irq);
 
-	write_msi_msg_desc(desc, msg);
+	__write_msi_msg(entry, msg);
 }
 
 static void free_msi_irqs(struct pci_dev *dev)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 7754a67..6beb11b 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -264,7 +264,8 @@
 extern void pci_iov_release(struct pci_dev *dev);
 extern int pci_iov_resource_bar(struct pci_dev *dev, int resno,
 				enum pci_bar_type *type);
-extern int pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
+extern resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev,
+						    int resno);
 extern void pci_restore_iov_state(struct pci_dev *dev);
 extern int pci_iov_bus_range(struct pci_bus *bus);
 
@@ -320,7 +321,7 @@
 }
 #endif /* CONFIG_PCI_IOV */
 
-static inline int pci_resource_alignment(struct pci_dev *dev,
+static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
 					 struct resource *res)
 {
 #ifdef CONFIG_PCI_IOV
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
index 9099246..b3cf622 100644
--- a/drivers/pci/pcie/aer/aer_inject.c
+++ b/drivers/pci/pcie/aer/aer_inject.c
@@ -472,6 +472,7 @@
 static const struct file_operations aer_inject_fops = {
 	.write = aer_inject_write,
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice aer_inject_device = {
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 89ed181..857ae01 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -163,6 +163,26 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_dma_hangs);
 
 /*
+ * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear
+ * for some HT machines to use C4 w/o hanging.
+ */
+static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev)
+{
+	u32 pmbase;
+	u16 pm1a;
+
+	pci_read_config_dword(dev, 0x40, &pmbase);
+	pmbase = pmbase & 0xff80;
+	pm1a = inw(pmbase);
+
+	if (pm1a & 0x10) {
+		dev_info(&dev->dev, FW_BUG "TigerPoint LPC.BM_STS cleared\n");
+		outw(0x10, pmbase);
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk_tigerpoint_bm_sts);
+
+/*
  *	Chipsets where PCI->PCI transfers vanish or hang
  */
 static void __devinit quirk_nopcipci(struct pci_dev *dev)
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 88c4c40..95dd7c6 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -441,14 +441,12 @@
 
 
 out_err:
-	flush_scheduled_work();
 	ops->hw_shutdown(skt);
 	while (i-- > 0) {
 		skt = PCMCIA_SOCKET(i);
 
 		del_timer_sync(&skt->poll_timer);
 		pcmcia_unregister_socket(&skt->socket);
-		flush_scheduled_work();
 		if (i == 0) {
 			iounmap(skt->virt_io + (u32)mips_io_port_base);
 			skt->virt_io = NULL;
@@ -480,7 +478,6 @@
 
 		del_timer_sync(&skt->poll_timer);
 		pcmcia_unregister_socket(&skt->socket);
-		flush_scheduled_work();
 		skt->ops->hw_shutdown(skt);
 		au1x00_pcmcia_config_skt(skt, &dead_socket);
 		iounmap(skt->virt_io + (u32)mips_io_port_base);
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h
index 67530ce..5c36bda 100644
--- a/drivers/pcmcia/au1000_generic.h
+++ b/drivers/pcmcia/au1000_generic.h
@@ -23,7 +23,6 @@
 
 /* include the world */
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c
index 807f2d7..b239664 100644
--- a/drivers/pcmcia/au1000_pb1x00.c
+++ b/drivers/pcmcia/au1000_pb1x00.c
@@ -31,7 +31,6 @@
 #include <linux/proc_fs.h>
 #include <linux/types.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 91414a0..884a984 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -28,7 +28,6 @@
 #include <asm/unaligned.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 2ec8ac9..d9ea192 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -33,7 +33,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -845,7 +844,7 @@
 	return __pcmcia_pm_op(dev, socket_early_resume);
 }
 
-static int pcmcia_socket_dev_resume(struct device *dev)
+static int __used pcmcia_socket_dev_resume(struct device *dev)
 {
 	return __pcmcia_pm_op(dev, socket_late_resume);
 }
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index da055dc..7f1953f 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -33,18 +33,9 @@
 typedef struct config_t {
 	struct kref	ref;
 	unsigned int	state;
-	unsigned int	Attributes;
-	unsigned int	IntType;
-	unsigned int	ConfigBase;
-	unsigned char	Status, Pin, Copy, Option, ExtStatus;
-	unsigned int	CardValues;
 
 	struct resource io[MAX_IO_WIN]; /* io ports */
 	struct resource mem[MAX_WIN];   /* mem areas */
-
-	struct {
-		u_int	Attributes;
-	} irq;
 } config_t;
 
 
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 55570d9..100c441 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -26,7 +26,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ss.h>
@@ -52,7 +51,7 @@
 
 	if (!p_drv->probe || !p_drv->remove)
 		printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
-		       "function\n", p_drv->drv.name);
+		       "function\n", p_drv->name);
 
 	while (did && did->match_flags) {
 		for (i = 0; i < 4; i++) {
@@ -65,7 +64,7 @@
 
 			printk(KERN_DEBUG "pcmcia: %s: invalid hash for "
 			       "product string \"%s\": is 0x%x, should "
-			       "be 0x%x\n", p_drv->drv.name, did->prod_id[i],
+			       "be 0x%x\n", p_drv->name, did->prod_id[i],
 			       did->prod_id_hash[i], hash);
 			printk(KERN_DEBUG "pcmcia: see "
 				"Documentation/pcmcia/devicetable.txt for "
@@ -180,10 +179,11 @@
 	/* initialize common fields */
 	driver->drv.bus = &pcmcia_bus_type;
 	driver->drv.owner = driver->owner;
+	driver->drv.name = driver->name;
 	mutex_init(&driver->dynids.lock);
 	INIT_LIST_HEAD(&driver->dynids.list);
 
-	pr_debug("registering driver %s\n", driver->drv.name);
+	pr_debug("registering driver %s\n", driver->name);
 
 	error = driver_register(&driver->drv);
 	if (error < 0)
@@ -203,7 +203,7 @@
  */
 void pcmcia_unregister_driver(struct pcmcia_driver *driver)
 {
-	pr_debug("unregistering driver %s\n", driver->drv.name);
+	pr_debug("unregistering driver %s\n", driver->name);
 	driver_unregister(&driver->drv);
 	pcmcia_free_dynids(driver);
 }
@@ -264,7 +264,7 @@
 	p_drv = to_pcmcia_drv(dev->driver);
 	s = p_dev->socket;
 
-	dev_dbg(dev, "trying to bind to %s\n", p_drv->drv.name);
+	dev_dbg(dev, "trying to bind to %s\n", p_drv->name);
 
 	if ((!p_drv->probe) || (!p_dev->function_config) ||
 	    (!try_module_get(p_drv->owner))) {
@@ -276,21 +276,28 @@
 	ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG,
 				&cis_config);
 	if (!ret) {
-		p_dev->conf.ConfigBase = cis_config.base;
-		p_dev->conf.Present = cis_config.rmask[0];
+		p_dev->config_base = cis_config.base;
+		p_dev->config_regs = cis_config.rmask[0];
+		dev_dbg(dev, "base %x, regs %x", p_dev->config_base,
+			p_dev->config_regs);
 	} else {
 		dev_printk(KERN_INFO, dev,
 			   "pcmcia: could not parse base and rmask0 of CIS\n");
-		p_dev->conf.ConfigBase = 0;
-		p_dev->conf.Present = 0;
+		p_dev->config_base = 0;
+		p_dev->config_regs = 0;
 	}
 
 	ret = p_drv->probe(p_dev);
 	if (ret) {
 		dev_dbg(dev, "binding to %s failed with %d\n",
-			   p_drv->drv.name, ret);
+			   p_drv->name, ret);
 		goto put_module;
 	}
+	dev_dbg(dev, "%s bound: Vpp %d.%d, idx %x, IRQ %d", p_drv->name,
+		p_dev->vpp/10, p_dev->vpp%10, p_dev->config_index, p_dev->irq);
+	dev_dbg(dev, "resources: ioport %pR %pR iomem %pR %pR %pR",
+		p_dev->resource[0], p_dev->resource[1], p_dev->resource[2],
+		p_dev->resource[3], p_dev->resource[4]);
 
 	mutex_lock(&s->ops_mutex);
 	if ((s->pcmcia_pfc) &&
@@ -374,13 +381,13 @@
 	if (p_dev->_irq || p_dev->_io || p_dev->_locked)
 		dev_printk(KERN_INFO, dev,
 			"pcmcia: driver %s did not release config properly\n",
-			p_drv->drv.name);
+			p_drv->name);
 
 	for (i = 0; i < MAX_WIN; i++)
 		if (p_dev->_win & CLIENT_WIN_REQ(i))
 			dev_printk(KERN_INFO, dev,
 			  "pcmcia: driver %s did not release window properly\n",
-			   p_drv->drv.name);
+			   p_drv->name);
 
 	/* references from pcmcia_probe_device */
 	pcmcia_put_dev(p_dev);
@@ -1136,7 +1143,7 @@
 			dev_printk(KERN_ERR, dev,
 				   "pcmcia: device %s (driver %s) did "
 				   "not want to go to sleep (%d)\n",
-				   p_dev->devname, p_drv->drv.name, ret);
+				   p_dev->devname, p_drv->name, ret);
 			mutex_lock(&p_dev->socket->ops_mutex);
 			p_dev->suspended = 0;
 			mutex_unlock(&p_dev->socket->ops_mutex);
@@ -1178,7 +1185,7 @@
 
 	if (p_dev->device_no == p_dev->func) {
 		dev_dbg(dev, "requesting configuration\n");
-		ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+		ret = pcmcia_enable_device(p_dev);
 		if (ret)
 			goto out;
 	}
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 05d0879..fc7906e 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -16,7 +16,6 @@
 #include <linux/device.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 61746bd..72a033a 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -51,7 +51,6 @@
 #include <asm/system.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include <linux/isapnp.h>
 
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 24de499..2adb010 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -27,7 +27,6 @@
 #include <asm/system.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #undef MAX_IO_WIN	/* FIXME */
 #define MAX_IO_WIN 1
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 8e47238..1511ff7 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -28,7 +28,6 @@
 #include <asm/addrspace.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 /* XXX: should be moved into asm/irq.h */
 #define PCC0_IRQ 24
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index f0ecad9..99d4f23 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -59,7 +59,6 @@
 #include <asm/irq.h>
 #include <asm/fs_pd.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 
 #define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h
index e74beba..5096e92 100644
--- a/drivers/pcmcia/o2micro.h
+++ b/drivers/pcmcia/o2micro.h
@@ -153,14 +153,14 @@
 
 		if (use_speedup) {
 			dev_info(&socket->dev->dev,
-				"O2: enabling read prefetch/write burst\n");
+				"O2: enabling read prefetch/write burst. If you experience problems or performance issues, use the yenta_socket parameter 'o2_speedup=off'\n");
 			config_writeb(socket, O2_RESERVED1,
 				      a | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST);
 			config_writeb(socket, O2_RESERVED2,
 				      b | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST);
 		} else {
 			dev_info(&socket->dev->dev,
-				"O2: disabling read prefetch/write burst\n");
+				"O2: disabling read prefetch/write burst. If you experience problems or performance issues, use the yenta_socket parameter 'o2_speedup=on'\n");
 			config_writeb(socket, O2_RESERVED1,
 				      a & ~(O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST));
 			config_writeb(socket, O2_RESERVED2,
diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c
index 0ac54da..e2c9241 100644
--- a/drivers/pcmcia/pcmcia_cis.c
+++ b/drivers/pcmcia/pcmcia_cis.c
@@ -6,7 +6,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Copyright (C) 1999	     David A. Hinds
- * Copyright (C) 2004-2009   Dominik Brodowski
+ * Copyright (C) 2004-2010   Dominik Brodowski
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -22,7 +22,6 @@
 #include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/ds.h>
 #include "cs_internal.h"
 
@@ -126,14 +125,24 @@
 	return ret;
 }
 
+
+/**
+ * pcmcia_io_cfg_data_width() - convert cfgtable to data path width parameter
+ */
+static int pcmcia_io_cfg_data_width(unsigned int flags)
+{
+	if (!(flags & CISTPL_IO_8BIT))
+		return IO_DATA_PATH_WIDTH_16;
+	if (!(flags & CISTPL_IO_16BIT))
+		return IO_DATA_PATH_WIDTH_8;
+	return IO_DATA_PATH_WIDTH_AUTO;
+}
+
+
 struct pcmcia_cfg_mem {
 	struct pcmcia_device *p_dev;
+	int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data);
 	void *priv_data;
-	int (*conf_check) (struct pcmcia_device *p_dev,
-			   cistpl_cftable_entry_t *cfg,
-			   cistpl_cftable_entry_t *dflt,
-			   unsigned int vcc,
-			   void *priv_data);
 	cisparse_t parse;
 	cistpl_cftable_entry_t dflt;
 };
@@ -147,25 +156,102 @@
  */
 static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
 {
-	cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
 	struct pcmcia_cfg_mem *cfg_mem = priv;
+	struct pcmcia_device *p_dev = cfg_mem->p_dev;
+	cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
+	cistpl_cftable_entry_t *dflt = &cfg_mem->dflt;
+	unsigned int flags = p_dev->config_flags;
+	unsigned int vcc = p_dev->socket->socket.Vcc;
+
+	dev_dbg(&p_dev->dev, "testing configuration %x, autoconf %x\n",
+		cfg->index, flags);
 
 	/* default values */
-	cfg_mem->p_dev->conf.ConfigIndex = cfg->index;
+	cfg_mem->p_dev->config_index = cfg->index;
 	if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
 		cfg_mem->dflt = *cfg;
 
-	return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt,
-				   cfg_mem->p_dev->socket->socket.Vcc,
-				   cfg_mem->priv_data);
+	/* check for matching Vcc? */
+	if (flags & CONF_AUTO_CHECK_VCC) {
+		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+			if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
+				return -ENODEV;
+		} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+			if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
+				return -ENODEV;
+		}
+	}
+
+	/* set Vpp? */
+	if (flags & CONF_AUTO_SET_VPP) {
+		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+			p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+			p_dev->vpp =
+				dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+	}
+
+	/* enable audio? */
+	if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
+		p_dev->config_flags |= CONF_ENABLE_SPKR;
+
+
+	/* IO window settings? */
+	if (flags & CONF_AUTO_SET_IO) {
+		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+		int i = 0;
+
+		p_dev->resource[0]->start = p_dev->resource[0]->end = 0;
+		p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
+		if (io->nwin == 0)
+			return -ENODEV;
+
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+					pcmcia_io_cfg_data_width(io->flags);
+		if (io->nwin > 1) {
+			/* For multifunction cards, by convention, we
+			 * configure the network function with window 0,
+			 * and serial with window 1 */
+			i = (io->win[1].len > io->win[0].len);
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1-i].base;
+			p_dev->resource[1]->end = io->win[1-i].len;
+		}
+		p_dev->resource[0]->start = io->win[i].base;
+		p_dev->resource[0]->end = io->win[i].len;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+	}
+
+	/* MEM window settings? */
+	if (flags & CONF_AUTO_SET_IOMEM) {
+		/* so far, we only set one memory window */
+		cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+
+		p_dev->resource[2]->start = p_dev->resource[2]->end = 0;
+		if (mem->nwin == 0)
+			return -ENODEV;
+
+		p_dev->resource[2]->start = mem->win[0].host_addr;
+		p_dev->resource[2]->end = mem->win[0].len;
+		if (p_dev->resource[2]->end < 0x1000)
+			p_dev->resource[2]->end = 0x1000;
+		p_dev->card_addr = mem->win[0].card_addr;
+	}
+
+	dev_dbg(&p_dev->dev,
+		"checking configuration %x: %pr %pr %pr (%d lines)\n",
+		p_dev->config_index, p_dev->resource[0], p_dev->resource[1],
+		p_dev->resource[2], p_dev->io_lines);
+
+	return cfg_mem->conf_check(p_dev, cfg_mem->priv_data);
 }
 
 /**
  * pcmcia_loop_config() - loop over configuration options
  * @p_dev:	the struct pcmcia_device which we need to loop for.
  * @conf_check:	function to call for each configuration option.
- *		It gets passed the struct pcmcia_device, the CIS data
- *		describing the configuration option, and private data
+ *		It gets passed the struct pcmcia_device and private data
  *		being passed to pcmcia_loop_config()
  * @priv_data:	private data to be passed to the conf_check function.
  *
@@ -175,9 +261,6 @@
  */
 int pcmcia_loop_config(struct pcmcia_device *p_dev,
 		       int	(*conf_check)	(struct pcmcia_device *p_dev,
-						 cistpl_cftable_entry_t *cfg,
-						 cistpl_cftable_entry_t *dflt,
-						 unsigned int vcc,
 						 void *priv_data),
 		       void *priv_data)
 {
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index a5c1765..0bdda5b3 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -6,7 +6,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Copyright (C) 1999	     David A. Hinds
- * Copyright (C) 2004-2005   Dominik Brodowski
+ * Copyright (C) 2004-2010   Dominik Brodowski
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -26,7 +26,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -56,6 +55,12 @@
 }
 
 
+/**
+ * release_io_space() - release IO ports allocated with alloc_io_space()
+ * @s: pcmcia socket
+ * @res: resource to release
+ *
+ */
 static void release_io_space(struct pcmcia_socket *s, struct resource *res)
 {
 	resource_size_t num = resource_size(res);
@@ -81,9 +86,14 @@
 			}
 		}
 	}
-} /* release_io_space */
+}
 
-/** alloc_io_space
+
+/**
+ * alloc_io_space() - allocate IO ports for use by a PCMCIA device
+ * @s: pcmcia socket
+ * @res: resource to allocate (begin: begin, end: size)
+ * @lines: number of IO lines decoded by the PCMCIA card
  *
  * Special stuff for managing IO windows, because they are scarce
  */
@@ -135,7 +145,7 @@
 	}
 	dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res);
 	return ret;
-} /* alloc_io_space */
+}
 
 
 /**
@@ -168,14 +178,14 @@
 		return -EACCES;
 	}
 
-	addr = (c->ConfigBase + where) >> 1;
+	addr = (p_dev->config_base + where) >> 1;
 
 	ret = accessf(s, 1, addr, 1, val);
 
 	mutex_unlock(&s->ops_mutex);
 
 	return ret;
-} /* pcmcia_access_config */
+}
 
 
 /**
@@ -204,11 +214,20 @@
 EXPORT_SYMBOL(pcmcia_write_config_byte);
 
 
-int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
+/**
+ * pcmcia_map_mem_page() - modify iomem window to point to a different offset
+ * @p_dev: pcmcia device
+ * @res: iomem resource already enabled by pcmcia_request_window()
+ * @offset: card_offset to map
+ *
+ * pcmcia_map_mem_page() modifies what can be read and written by accessing
+ * an iomem range previously enabled by pcmcia_request_window(), by setting
+ * the card_offset value to @offset.
+ */
+int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
 			unsigned int offset)
 {
 	struct pcmcia_socket *s = p_dev->socket;
-	struct resource *res = wh;
 	unsigned int w;
 	int ret;
 
@@ -223,98 +242,111 @@
 		dev_warn(&p_dev->dev, "failed to set_mem_map\n");
 	mutex_unlock(&s->ops_mutex);
 	return ret;
-} /* pcmcia_map_mem_page */
+}
 EXPORT_SYMBOL(pcmcia_map_mem_page);
 
 
-/** pcmcia_modify_configuration
+/**
+ * pcmcia_fixup_iowidth() - reduce io width to 8bit
+ * @p_dev: pcmcia device
  *
- * Modify a locked socket configuration
+ * pcmcia_fixup_iowidth() allows a PCMCIA device driver to reduce the
+ * IO width to 8bit after having called pcmcia_enable_device()
+ * previously.
  */
-int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
-				modconf_t *mod)
+int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev)
 {
-	struct pcmcia_socket *s;
-	config_t *c;
-	int ret;
-
-	s = p_dev->socket;
+	struct pcmcia_socket *s = p_dev->socket;
+	pccard_io_map io_off = { 0, 0, 0, 0, 1 };
+	pccard_io_map io_on;
+	int i, ret = 0;
 
 	mutex_lock(&s->ops_mutex);
-	c = p_dev->function_config;
 
-	if (!(s->state & SOCKET_PRESENT)) {
-		dev_dbg(&p_dev->dev, "No card present\n");
-		ret = -ENODEV;
-		goto unlock;
-	}
-	if (!(c->state & CONFIG_LOCKED)) {
-		dev_dbg(&p_dev->dev, "Configuration isnt't locked\n");
+	dev_dbg(&p_dev->dev, "fixup iowidth to 8bit\n");
+
+	if (!(s->state & SOCKET_PRESENT) ||
+		!(p_dev->function_config->state & CONFIG_LOCKED)) {
+		dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
 		ret = -EACCES;
 		goto unlock;
 	}
 
-	if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) {
-		dev_dbg(&p_dev->dev,
-			"changing Vcc or IRQ is not allowed at this time\n");
-		ret = -EINVAL;
-		goto unlock;
+	io_on.speed = io_speed;
+	for (i = 0; i < MAX_IO_WIN; i++) {
+		if (!s->io[i].res)
+			continue;
+		io_off.map = i;
+		io_on.map = i;
+
+		io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
+		io_on.start = s->io[i].res->start;
+		io_on.stop = s->io[i].res->end;
+
+		s->ops->set_io_map(s, &io_off);
+		mdelay(40);
+		s->ops->set_io_map(s, &io_on);
 	}
-
-	/* We only allow changing Vpp1 and Vpp2 to the same value */
-	if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
-	    (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
-		if (mod->Vpp1 != mod->Vpp2) {
-			dev_dbg(&p_dev->dev,
-				"Vpp1 and Vpp2 must be the same\n");
-			ret = -EINVAL;
-			goto unlock;
-		}
-		s->socket.Vpp = mod->Vpp1;
-		if (s->ops->set_socket(s, &s->socket)) {
-			dev_printk(KERN_WARNING, &p_dev->dev,
-				   "Unable to set VPP\n");
-			ret = -EIO;
-			goto unlock;
-		}
-	} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
-		   (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
-		dev_dbg(&p_dev->dev,
-			"changing Vcc is not allowed at this time\n");
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-	if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
-		pccard_io_map io_off = { 0, 0, 0, 0, 1 };
-		pccard_io_map io_on;
-		int i;
-
-		io_on.speed = io_speed;
-		for (i = 0; i < MAX_IO_WIN; i++) {
-			if (!s->io[i].res)
-				continue;
-			io_off.map = i;
-			io_on.map = i;
-
-			io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
-			io_on.start = s->io[i].res->start;
-			io_on.stop = s->io[i].res->end;
-
-			s->ops->set_io_map(s, &io_off);
-			mdelay(40);
-			s->ops->set_io_map(s, &io_on);
-		}
-	}
-	ret = 0;
 unlock:
 	mutex_unlock(&s->ops_mutex);
 
 	return ret;
-} /* modify_configuration */
-EXPORT_SYMBOL(pcmcia_modify_configuration);
+}
+EXPORT_SYMBOL(pcmcia_fixup_iowidth);
 
 
+/**
+ * pcmcia_fixup_vpp() - set Vpp to a new voltage level
+ * @p_dev: pcmcia device
+ * @new_vpp: new Vpp voltage
+ *
+ * pcmcia_fixup_vpp() allows a PCMCIA device driver to set Vpp to
+ * a new voltage level between calls to pcmcia_enable_device()
+ * and pcmcia_disable_device().
+ */
+int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp)
+{
+	struct pcmcia_socket *s = p_dev->socket;
+	int ret = 0;
+
+	mutex_lock(&s->ops_mutex);
+
+	dev_dbg(&p_dev->dev, "fixup Vpp to %d\n", new_vpp);
+
+	if (!(s->state & SOCKET_PRESENT) ||
+		!(p_dev->function_config->state & CONFIG_LOCKED)) {
+		dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
+		ret = -EACCES;
+		goto unlock;
+	}
+
+	s->socket.Vpp = new_vpp;
+	if (s->ops->set_socket(s, &s->socket)) {
+		dev_warn(&p_dev->dev, "Unable to set VPP\n");
+		ret = -EIO;
+		goto unlock;
+	}
+	p_dev->vpp = new_vpp;
+
+unlock:
+	mutex_unlock(&s->ops_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL(pcmcia_fixup_vpp);
+
+
+/**
+ * pcmcia_release_configuration() - physically disable a PCMCIA device
+ * @p_dev: pcmcia device
+ *
+ * pcmcia_release_configuration() is the 1:1 counterpart to
+ * pcmcia_enable_device(): If a PCMCIA device is no longer used by any
+ * driver, the Vpp voltage is set to 0, IRQs will no longer be generated,
+ * and I/O ranges will be disabled. As pcmcia_release_io() and
+ * pcmcia_release_window() still need to be called, device drivers are
+ * expected to call pcmcia_disable_device() instead.
+ */
 int pcmcia_release_configuration(struct pcmcia_device *p_dev)
 {
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -327,7 +359,7 @@
 	if (p_dev->_locked) {
 		p_dev->_locked = 0;
 		if (--(s->lock_count) == 0) {
-			s->socket.flags = SS_OUTPUT_ENA;   /* Is this correct? */
+			s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
 			s->socket.Vpp = 0;
 			s->socket.io_irq = 0;
 			s->ops->set_socket(s, &s->socket);
@@ -349,16 +381,18 @@
 	mutex_unlock(&s->ops_mutex);
 
 	return 0;
-} /* pcmcia_release_configuration */
+}
 
 
-/** pcmcia_release_io
+/**
+ * pcmcia_release_io() - release I/O allocated by a PCMCIA device
+ * @p_dev: pcmcia device
  *
- * Release_io() releases the I/O ranges allocated by a client.  This
- * may be invoked some time after a card ejection has already dumped
- * the actual socket configuration, so if the client is "stale", we
- * don't bother checking the port ranges against the current socket
- * values.
+ * pcmcia_release_io() releases the I/O ranges allocated by a PCMCIA
+ * device.  This may be invoked some time after a card ejection has
+ * already dumped the actual socket configuration, so if the client is
+ * "stale", we don't bother checking the port ranges against the
+ * current socket values.
  */
 static int pcmcia_release_io(struct pcmcia_device *p_dev)
 {
@@ -387,6 +421,14 @@
 } /* pcmcia_release_io */
 
 
+/**
+ * pcmcia_release_window() - release reserved iomem for PCMCIA devices
+ * @p_dev: pcmcia device
+ * @res: iomem resource to release
+ *
+ * pcmcia_release_window() releases &struct resource *res which was
+ * previously reserved by calling pcmcia_request_window().
+ */
 int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
 {
 	struct pcmcia_socket *s = p_dev->socket;
@@ -420,6 +462,8 @@
 		kfree(win->res);
 		win->res = NULL;
 	}
+	res->start = res->end = 0;
+	res->flags = IORESOURCE_MEM;
 	p_dev->_win &= ~CLIENT_WIN_REQ(w);
 	mutex_unlock(&s->ops_mutex);
 
@@ -428,23 +472,30 @@
 EXPORT_SYMBOL(pcmcia_release_window);
 
 
-int pcmcia_request_configuration(struct pcmcia_device *p_dev,
-				 config_req_t *req)
+/**
+ * pcmcia_enable_device() - set up and activate a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ *
+ * pcmcia_enable_device() physically enables a PCMCIA device. It parses
+ * the flags passed to in @flags and stored in @p_dev->flags and sets up
+ * the Vpp voltage, enables the speaker line, I/O ports and store proper
+ * values to configuration registers.
+ */
+int pcmcia_enable_device(struct pcmcia_device *p_dev)
 {
 	int i;
-	u_int base;
+	unsigned int base;
 	struct pcmcia_socket *s = p_dev->socket;
 	config_t *c;
 	pccard_io_map iomap;
+	unsigned char status = 0;
+	unsigned char ext_status = 0;
+	unsigned char option = 0;
+	unsigned int flags = p_dev->config_flags;
 
 	if (!(s->state & SOCKET_PRESENT))
 		return -ENODEV;
 
-	if (req->IntType & INT_CARDBUS) {
-		dev_dbg(&p_dev->dev, "IntType may not be INT_CARDBUS\n");
-		return -EINVAL;
-	}
-
 	mutex_lock(&s->ops_mutex);
 	c = p_dev->function_config;
 	if (c->state & CONFIG_LOCKED) {
@@ -454,7 +505,7 @@
 	}
 
 	/* Do power control.  We don't allow changes in Vcc. */
-	s->socket.Vpp = req->Vpp;
+	s->socket.Vpp = p_dev->vpp;
 	if (s->ops->set_socket(s, &s->socket)) {
 		mutex_unlock(&s->ops_mutex);
 		dev_printk(KERN_WARNING, &p_dev->dev,
@@ -463,64 +514,74 @@
 	}
 
 	/* Pick memory or I/O card, DMA mode, interrupt */
-	c->IntType = req->IntType;
-	c->Attributes = req->Attributes;
-	if (req->IntType & INT_MEMORY_AND_IO)
+	if (p_dev->_io || flags & CONF_ENABLE_IRQ)
+		flags |= CONF_ENABLE_IOCARD;
+	if (flags & CONF_ENABLE_IOCARD)
 		s->socket.flags |= SS_IOCARD;
-	if (req->IntType & INT_ZOOMED_VIDEO)
-		s->socket.flags |= SS_ZVCARD | SS_IOCARD;
-	if (req->Attributes & CONF_ENABLE_DMA)
-		s->socket.flags |= SS_DMA_MODE;
-	if (req->Attributes & CONF_ENABLE_SPKR)
+	if (flags & CONF_ENABLE_SPKR) {
 		s->socket.flags |= SS_SPKR_ENA;
-	if (req->Attributes & CONF_ENABLE_IRQ)
+		status = CCSR_AUDIO_ENA;
+		if (!(p_dev->config_regs & PRESENT_STATUS))
+			dev_warn(&p_dev->dev, "speaker requested, but "
+					      "PRESENT_STATUS not set!\n");
+	}
+	if (flags & CONF_ENABLE_IRQ)
 		s->socket.io_irq = s->pcmcia_irq;
 	else
 		s->socket.io_irq = 0;
+	if (flags & CONF_ENABLE_ESR) {
+		p_dev->config_regs |= PRESENT_EXT_STATUS;
+		ext_status = ESR_REQ_ATTN_ENA;
+	}
 	s->ops->set_socket(s, &s->socket);
 	s->lock_count++;
 
+	dev_dbg(&p_dev->dev,
+		"enable_device: V %d, flags %x, base %x, regs %x, idx %x\n",
+		p_dev->vpp, flags, p_dev->config_base, p_dev->config_regs,
+		p_dev->config_index);
+
 	/* Set up CIS configuration registers */
-	base = c->ConfigBase = req->ConfigBase;
-	c->CardValues = req->Present;
-	if (req->Present & PRESENT_COPY) {
-		c->Copy = req->Copy;
-		pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
+	base = p_dev->config_base;
+	if (p_dev->config_regs & PRESENT_COPY) {
+		u16 tmp = 0;
+		dev_dbg(&p_dev->dev, "clearing CISREG_SCR\n");
+		pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &tmp);
 	}
-	if (req->Present & PRESENT_OPTION) {
+	if (p_dev->config_regs & PRESENT_PIN_REPLACE) {
+		u16 tmp = 0;
+		dev_dbg(&p_dev->dev, "clearing CISREG_PRR\n");
+		pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &tmp);
+	}
+	if (p_dev->config_regs & PRESENT_OPTION) {
 		if (s->functions == 1) {
-			c->Option = req->ConfigIndex & COR_CONFIG_MASK;
+			option = p_dev->config_index & COR_CONFIG_MASK;
 		} else {
-			c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
-			c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
-			if (req->Present & PRESENT_IOBASE_0)
-				c->Option |= COR_ADDR_DECODE;
+			option = p_dev->config_index & COR_MFC_CONFIG_MASK;
+			option |= COR_FUNC_ENA|COR_IREQ_ENA;
+			if (p_dev->config_regs & PRESENT_IOBASE_0)
+				option |= COR_ADDR_DECODE;
 		}
-		if ((req->Attributes & CONF_ENABLE_IRQ) &&
-			!(req->Attributes & CONF_ENABLE_PULSE_IRQ))
-			c->Option |= COR_LEVEL_REQ;
-		pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
+		if ((flags & CONF_ENABLE_IRQ) &&
+			!(flags & CONF_ENABLE_PULSE_IRQ))
+			option |= COR_LEVEL_REQ;
+		pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &option);
 		mdelay(40);
 	}
-	if (req->Present & PRESENT_STATUS) {
-		c->Status = req->Status;
-		pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
-	}
-	if (req->Present & PRESENT_PIN_REPLACE) {
-		c->Pin = req->Pin;
-		pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin);
-	}
-	if (req->Present & PRESENT_EXT_STATUS) {
-		c->ExtStatus = req->ExtStatus;
-		pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus);
-	}
-	if (req->Present & PRESENT_IOBASE_0) {
+	if (p_dev->config_regs & PRESENT_STATUS)
+		pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &status);
+
+	if (p_dev->config_regs & PRESENT_EXT_STATUS)
+		pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1,
+					&ext_status);
+
+	if (p_dev->config_regs & PRESENT_IOBASE_0) {
 		u8 b = c->io[0].start & 0xff;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
 		b = (c->io[0].start >> 8) & 0xff;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
 	}
-	if (req->Present & PRESENT_IOSIZE) {
+	if (p_dev->config_regs & PRESENT_IOSIZE) {
 		u8 b = resource_size(&c->io[0]) + resource_size(&c->io[1]) - 1;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
 	}
@@ -551,14 +612,15 @@
 	p_dev->_locked = 1;
 	mutex_unlock(&s->ops_mutex);
 	return 0;
-} /* pcmcia_request_configuration */
-EXPORT_SYMBOL(pcmcia_request_configuration);
+} /* pcmcia_enable_device */
+EXPORT_SYMBOL(pcmcia_enable_device);
 
 
 /**
  * pcmcia_request_io() - attempt to reserve port ranges for PCMCIA devices
+ * @p_dev: the associated PCMCIA device
  *
- * pcmcia_request_io() attepts to reserve the IO port ranges specified in
+ * pcmcia_request_io() attempts to reserve the IO port ranges specified in
  * &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The
  * "start" value is the requested start of the IO port resource; "end"
  * reflects the number of ports requested. The number of IO lines requested
@@ -595,7 +657,13 @@
 	if (c->io[1].end) {
 		ret = alloc_io_space(s, &c->io[1], p_dev->io_lines);
 		if (ret) {
+			struct resource tmp = c->io[0];
+			/* release the previously allocated resource */
 			release_io_space(s, &c->io[0]);
+			/* but preserve the settings, for they worked... */
+			c->io[0].end = resource_size(&tmp);
+			c->io[0].start = tmp.start;
+			c->io[0].flags = tmp.flags;
 			goto out;
 		}
 	} else
@@ -616,11 +684,13 @@
 
 /**
  * pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ * @handler: IRQ handler to register
  *
- * pcmcia_request_irq() is a wrapper around request_irq which will allow
+ * pcmcia_request_irq() is a wrapper around request_irq() which allows
  * the PCMCIA core to clean up the registration in pcmcia_disable_device().
  * Drivers are free to use request_irq() directly, but then they need to
- * call free_irq themselfves, too. Also, only IRQF_SHARED capable IRQ
+ * call free_irq() themselfves, too. Also, only %IRQF_SHARED capable IRQ
  * handlers are allowed.
  */
 int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
@@ -643,12 +713,14 @@
 
 /**
  * pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first
+ * @p_dev: the associated PCMCIA device
+ * @handler: IRQ handler to register
  *
- * pcmcia_request_exclusive_irq() is a wrapper around request_irq which
+ * pcmcia_request_exclusive_irq() is a wrapper around request_irq() which
  * attempts first to request an exclusive IRQ. If it fails, it also accepts
  * a shared IRQ, but prints out a warning. PCMCIA drivers should allow for
  * IRQ sharing and either use request_irq directly (then they need to call
- * free_irq themselves, too), or the pcmcia_request_irq() function.
+ * free_irq() themselves, too), or the pcmcia_request_irq() function.
  */
 int __must_check
 __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
@@ -789,38 +861,47 @@
 }
 
 
-/** pcmcia_request_window
+/**
+ * pcmcia_request_window() - attempt to reserve iomem for PCMCIA devices
+ * @p_dev: the associated PCMCIA device
+ * @res: &struct resource pointing to p_dev->resource[2..5]
+ * @speed: access speed
  *
- * Request_window() establishes a mapping between card memory space
- * and system memory space.
+ * pcmcia_request_window() attepts to reserve an iomem ranges specified in
+ * &struct resource @res pointing to one of the entries in
+ * &struct pcmcia_device @p_dev->resource[2..5]. The "start" value is the
+ * requested start of the IO mem resource; "end" reflects the size
+ * requested.
  */
-int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh)
+int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res,
+			unsigned int speed)
 {
 	struct pcmcia_socket *s = p_dev->socket;
 	pccard_mem_map *win;
 	u_long align;
-	struct resource *res;
 	int w;
 
+	dev_dbg(&p_dev->dev, "request_window %pR %d\n", res, speed);
+
 	if (!(s->state & SOCKET_PRESENT)) {
 		dev_dbg(&p_dev->dev, "No card present\n");
 		return -ENODEV;
 	}
 
 	/* Window size defaults to smallest available */
-	if (req->Size == 0)
-		req->Size = s->map_size;
-	align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size;
-	if (req->Size & (s->map_size-1)) {
+	if (res->end == 0)
+		res->end = s->map_size;
+	align = (s->features & SS_CAP_MEM_ALIGN) ? res->end : s->map_size;
+	if (res->end & (s->map_size-1)) {
 		dev_dbg(&p_dev->dev, "invalid map size\n");
 		return -EINVAL;
 	}
-	if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
-	    (req->Base & (align-1))) {
+	if ((res->start && (s->features & SS_CAP_STATIC_MAP)) ||
+	    (res->start & (align-1))) {
 		dev_dbg(&p_dev->dev, "invalid base address\n");
 		return -EINVAL;
 	}
-	if (req->Base)
+	if (res->start)
 		align = 0;
 
 	/* Allocate system memory window */
@@ -837,7 +918,7 @@
 	win = &s->win[w];
 
 	if (!(s->features & SS_CAP_STATIC_MAP)) {
-		win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
+		win->res = pcmcia_find_mem_region(res->start, res->end, align,
 						0, s);
 		if (!win->res) {
 			dev_dbg(&p_dev->dev, "allocating mem region failed\n");
@@ -849,8 +930,8 @@
 
 	/* Configure the socket controller */
 	win->map = w+1;
-	win->flags = req->Attributes;
-	win->speed = req->AccessSpeed;
+	win->flags = res->flags & WIN_FLAGS_MAP;
+	win->speed = speed;
 	win->card_start = 0;
 
 	if (s->ops->set_mem_map(s, win) != 0) {
@@ -862,17 +943,14 @@
 
 	/* Return window handle */
 	if (s->features & SS_CAP_STATIC_MAP)
-		req->Base = win->static_start;
+		res->start = win->static_start;
 	else
-		req->Base = win->res->start;
+		res->start = win->res->start;
 
 	/* convert to new-style resources */
-	res = p_dev->resource[w + MAX_IO_WIN];
-	res->start = req->Base;
-	res->end = req->Base + req->Size - 1;
-	res->flags &= ~IORESOURCE_BITS;
-	res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2);
-	res->flags |= IORESOURCE_MEM;
+	res->end += res->start - 1;
+	res->flags &= ~WIN_FLAGS_REQ;
+	res->flags |= (win->map << 2) | IORESOURCE_MEM;
 	res->parent = win->res;
 	if (win->res)
 		request_resource(&iomem_resource, res);
@@ -880,15 +958,30 @@
 	dev_dbg(&p_dev->dev, "request_window results in %pR\n", res);
 
 	mutex_unlock(&s->ops_mutex);
-	*wh = res;
 
 	return 0;
 } /* pcmcia_request_window */
 EXPORT_SYMBOL(pcmcia_request_window);
 
+
+/**
+ * pcmcia_disable_device() - disable and clean up a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ *
+ * pcmcia_disable_device() is the driver-callable counterpart to
+ * pcmcia_enable_device(): If a PCMCIA device is no longer used,
+ * drivers are expected to clean up and disable the device by calling
+ * this function. Any I/O ranges (iomem and ioports) will be released,
+ * the Vpp voltage will be set to 0, and IRQs will no longer be
+ * generated -- at least if there is no other card function (of
+ * multifunction devices) being used.
+ */
 void pcmcia_disable_device(struct pcmcia_device *p_dev)
 {
 	int i;
+
+	dev_dbg(&p_dev->dev, "disabling device\n");
+
 	for (i = 0; i < MAX_WIN; i++) {
 		struct resource *res = p_dev->resource[MAX_IO_WIN + i];
 		if (res->flags & WIN_FLAGS_REQ)
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index b8a869a..8cbfa06 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include <asm/system.h>
 
@@ -646,7 +645,7 @@
 	if (!pci_resource_start(dev, 0)) {
 		dev_warn(&dev->dev, "refusing to load the driver as the "
 			"io_base is NULL.\n");
-		goto err_out_free_mem;
+		goto err_out_disable;
 	}
 
 	dev_info(&dev->dev, "Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx "
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c
index 8510c35..523eb69 100644
--- a/drivers/pcmcia/rsrc_iodyn.c
+++ b/drivers/pcmcia/rsrc_iodyn.c
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 4e80421..aa628ed 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 96f348b..b187555 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -29,7 +29,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index e098514..945857f 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -35,7 +35,6 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 
 #include <asm/hardware/scoop.h>
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 6f1a86b..689e3c0 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -627,8 +627,6 @@
 
 	pcmcia_unregister_socket(&skt->socket);
 
-	flush_scheduled_work();
-
 	skt->ops->hw_shutdown(skt);
 
 	soc_common_pcmcia_config_skt(skt, &dead_socket);
@@ -720,8 +718,6 @@
 	pcmcia_unregister_socket(&skt->socket);
 
  out_err_7:
-	flush_scheduled_work();
-
 	skt->ops->hw_shutdown(skt);
  out_err_6:
 	list_del(&skt->node);
diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h
index 3fba3a6..bbcd538 100644
--- a/drivers/pcmcia/soc_common.h
+++ b/drivers/pcmcia/soc_common.h
@@ -11,7 +11,6 @@
 
 /* include the world */
 #include <linux/cpufreq.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index cb0d3ac..71aeed9 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -27,7 +27,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index be0d841..310160b 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -49,7 +49,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include "tcic.h"
 
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index 9b3c158..c6d36b3 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -461,7 +461,7 @@
 {
 	vrc4173_socket_t *socket;
 	unsigned long start, len, flags;
-	int slot, err;
+	int slot, err, ret;
 
 	slot = vrc4173_cardu_slots++;
 	socket = &cardu_sockets[slot];
@@ -474,43 +474,63 @@
 		return err;
 
 	start = pci_resource_start(dev, 0);
-	if (start == 0)
-		return -ENODEV;
+	if (start == 0) {
+		ret = -ENODEV;
+		goto disable;
+	}
 
 	len = pci_resource_len(dev, 0);
-	if (len == 0)
-		return -ENODEV;
+	if (len == 0) {
+		ret = -ENODEV;
+		goto disable;
+	}
 
-	if (((flags = pci_resource_flags(dev, 0)) & IORESOURCE_MEM) == 0)
-		return -EBUSY;
+	flags = pci_resource_flags(dev, 0);
+	if ((flags & IORESOURCE_MEM) == 0) {
+		ret = -EBUSY;
+		goto disable;
+	}
 
-	if ((err = pci_request_regions(dev, socket->name)) < 0)
-		return err;
+	err = pci_request_regions(dev, socket->name);
+	if (err < 0) {
+		ret = err;
+		goto disable;
+	}
 
 	socket->base = ioremap(start, len);
-	if (socket->base == NULL)
-		return -ENODEV;
+	if (socket->base == NULL) {
+		ret = -ENODEV;
+		goto release;
+	}
 
 	socket->dev = dev;
 
 	socket->pcmcia_socket = pcmcia_register_socket(slot, &cardu_operations, 1);
 	if (socket->pcmcia_socket == NULL) {
-		iounmap(socket->base);
-		socket->base = NULL;
-		return -ENOMEM;
+		ret =  -ENOMEM;
+		goto unmap;
 	}
 
 	if (request_irq(dev->irq, cardu_interrupt, IRQF_SHARED, socket->name, socket) < 0) {
-		pcmcia_unregister_socket(socket->pcmcia_socket);
-		socket->pcmcia_socket = NULL;
-		iounmap(socket->base);
-		socket->base = NULL;
-		return -EBUSY;
+		ret = -EBUSY;
+		goto unregister;
 	}
 
 	printk(KERN_INFO "%s at %#08lx, IRQ %d\n", socket->name, start, dev->irq);
 
 	return 0;
+
+unregister:
+	pcmcia_unregister_socket(socket->pcmcia_socket);
+	socket->pcmcia_socket = NULL;
+unmap:
+	iounmap(socket->base);
+	socket->base = NULL;
+release:
+	pci_release_regions(dev);
+disable:
+	pci_disable_device(dev);
+	return ret;
 }
 
 static int __devinit vrc4173_cardu_setup(char *options)
diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
index fa88c36..3b67a1b 100644
--- a/drivers/pcmcia/xxs1500_ss.c
+++ b/drivers/pcmcia/xxs1500_ss.c
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 414d9a6..408dbaa 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -20,7 +20,6 @@
 #include <linux/slab.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include "yenta_socket.h"
 #include "i82365.h"
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index 9024480..c44a5e8 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -51,7 +51,6 @@
  * TODO:
  *   - handle CPU hotplug
  *   - provide turbo enable/disable api
- *   - make sure we can write turbo enable/disable reg based on MISC_EN
  *
  * Related documents:
  *   - CDI 403777, 403778 - Auburndale EDS vol 1 & 2
@@ -230,7 +229,7 @@
 #define THM_TC2		0xac
 #define THM_DTV		0xb0
 #define THM_ITV		0xd8
-#define   ITV_ME_SEQNO_MASK 0x000f0000 /* ME should update every ~200ms */
+#define   ITV_ME_SEQNO_MASK 0x00ff0000 /* ME should update every ~200ms */
 #define   ITV_ME_SEQNO_SHIFT (16)
 #define   ITV_MCH_TEMP_MASK 0x0000ff00
 #define   ITV_MCH_TEMP_SHIFT (8)
@@ -325,6 +324,7 @@
 	bool gpu_preferred;
 	bool poll_turbo_status;
 	bool second_cpu;
+	bool turbo_toggle_allowed;
 	struct ips_mcp_limits *limits;
 
 	/* Optional MCH interfaces for if i915 is in use */
@@ -415,7 +415,7 @@
 	new_limit = cur_limit - 8; /* 1W decrease */
 
 	/* Clamp to SKU TDP limit */
-	if (((new_limit * 10) / 8) < (ips->orig_turbo_limit & TURBO_TDP_MASK))
+	if (new_limit  < (ips->orig_turbo_limit & TURBO_TDP_MASK))
 		new_limit = ips->orig_turbo_limit & TURBO_TDP_MASK;
 
 	thm_writew(THM_MPCPC, (new_limit * 10) / 8);
@@ -461,7 +461,8 @@
 	if (ips->__cpu_turbo_on)
 		return;
 
-	on_each_cpu(do_enable_cpu_turbo, ips, 1);
+	if (ips->turbo_toggle_allowed)
+		on_each_cpu(do_enable_cpu_turbo, ips, 1);
 
 	ips->__cpu_turbo_on = true;
 }
@@ -498,7 +499,8 @@
 	if (!ips->__cpu_turbo_on)
 		return;
 
-	on_each_cpu(do_disable_cpu_turbo, ips, 1);
+	if (ips->turbo_toggle_allowed)
+		on_each_cpu(do_disable_cpu_turbo, ips, 1);
 
 	ips->__cpu_turbo_on = false;
 }
@@ -598,17 +600,29 @@
 {
 	unsigned long flags;
 	bool ret = false;
+	u32 temp_limit;
+	u32 avg_power;
+	const char *msg = "MCP limit exceeded: ";
 
 	spin_lock_irqsave(&ips->turbo_status_lock, flags);
-	if (ips->mcp_avg_temp > (ips->mcp_temp_limit * 100))
-		ret = true;
-	if (ips->cpu_avg_power + ips->mch_avg_power > ips->mcp_power_limit)
-		ret = true;
-	spin_unlock_irqrestore(&ips->turbo_status_lock, flags);
 
-	if (ret)
+	temp_limit = ips->mcp_temp_limit * 100;
+	if (ips->mcp_avg_temp > temp_limit) {
 		dev_info(&ips->dev->dev,
-			 "MCP power or thermal limit exceeded\n");
+			"%sAvg temp %u, limit %u\n", msg, ips->mcp_avg_temp,
+			temp_limit);
+		ret = true;
+	}
+
+	avg_power = ips->cpu_avg_power + ips->mch_avg_power;
+	if (avg_power > ips->mcp_power_limit) {
+		dev_info(&ips->dev->dev,
+			"%sAvg power %u, limit %u\n", msg, avg_power,
+			ips->mcp_power_limit);
+		ret = true;
+	}
+
+	spin_unlock_irqrestore(&ips->turbo_status_lock, flags);
 
 	return ret;
 }
@@ -663,6 +677,27 @@
 }
 
 /**
+ * verify_limits - verify BIOS provided limits
+ * @ips: IPS structure
+ *
+ * BIOS can optionally provide non-default limits for power and temp.  Check
+ * them here and use the defaults if the BIOS values are not provided or
+ * are otherwise unusable.
+ */
+static void verify_limits(struct ips_driver *ips)
+{
+	if (ips->mcp_power_limit < ips->limits->mcp_power_limit ||
+	    ips->mcp_power_limit > 35000)
+		ips->mcp_power_limit = ips->limits->mcp_power_limit;
+
+	if (ips->mcp_temp_limit < ips->limits->core_temp_limit ||
+	    ips->mcp_temp_limit < ips->limits->mch_temp_limit ||
+	    ips->mcp_temp_limit > 150)
+		ips->mcp_temp_limit = min(ips->limits->core_temp_limit,
+					  ips->limits->mch_temp_limit);
+}
+
+/**
  * update_turbo_limits - get various limits & settings from regs
  * @ips: IPS driver struct
  *
@@ -680,12 +715,21 @@
 	u32 hts = thm_readl(THM_HTS);
 
 	ips->cpu_turbo_enabled = !(hts & HTS_PCTD_DIS);
-	ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS);
+	/* 
+	 * Disable turbo for now, until we can figure out why the power figures
+	 * are wrong
+	 */
+	ips->cpu_turbo_enabled = false;
+
+	if (ips->gpu_busy)
+		ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS);
+
 	ips->core_power_limit = thm_readw(THM_MPCPC);
 	ips->mch_power_limit = thm_readw(THM_MMGPC);
 	ips->mcp_temp_limit = thm_readw(THM_PTL);
 	ips->mcp_power_limit = thm_readw(THM_MPPC);
 
+	verify_limits(ips);
 	/* Ignore BIOS CPU vs GPU pref */
 }
 
@@ -858,7 +902,7 @@
 	ret = (ret * 1000) / 65535;
 	*last = val;
 
-	return ret;
+	return 0;
 }
 
 static const u16 temp_decay_factor = 2;
@@ -940,7 +984,6 @@
 		kfree(mch_samples);
 		kfree(cpu_samples);
 		kfree(mchp_samples);
-		kthread_stop(ips->adjust);
 		return -ENOMEM;
 	}
 
@@ -948,7 +991,7 @@
 		ITV_ME_SEQNO_SHIFT;
 	seqno_timestamp = get_jiffies_64();
 
-	old_cpu_power = thm_readl(THM_CEC) / 65535;
+	old_cpu_power = thm_readl(THM_CEC);
 	schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD));
 
 	/* Collect an initial average */
@@ -1150,11 +1193,18 @@
 				STS_GPL_SHIFT;
 			/* ignore EC CPU vs GPU pref */
 			ips->cpu_turbo_enabled = !(sts & STS_PCTD_DIS);
-			ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS);
+			/* 
+			 * Disable turbo for now, until we can figure
+			 * out why the power figures are wrong
+			 */
+			ips->cpu_turbo_enabled = false;
+			if (ips->gpu_busy)
+				ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS);
 			ips->mcp_temp_limit = (sts & STS_PTL_MASK) >>
 				STS_PTL_SHIFT;
 			ips->mcp_power_limit = (tc1 & STS_PPL_MASK) >>
 				STS_PPL_SHIFT;
+			verify_limits(ips);
 			spin_unlock(&ips->turbo_status_lock);
 
 			thm_writeb(THM_SEC, SEC_ACK);
@@ -1333,8 +1383,10 @@
 	 * turbo manually or we'll get an illegal MSR access, even though
 	 * turbo will still be available.
 	 */
-	if (!(misc_en & IA32_MISC_TURBO_EN))
-		; /* add turbo MSR write allowed flag if necessary */
+	if (misc_en & IA32_MISC_TURBO_EN)
+		ips->turbo_toggle_allowed = true;
+	else
+		ips->turbo_toggle_allowed = false;
 
 	if (strstr(boot_cpu_data.x86_model_id, "CPU       M"))
 		limits = &ips_sv_limits;
@@ -1351,9 +1403,10 @@
 	tdp = turbo_power & TURBO_TDP_MASK;
 
 	/* Sanity check TDP against CPU */
-	if (limits->mcp_power_limit != (tdp / 8) * 1000) {
-		dev_warn(&ips->dev->dev, "Warning: CPU TDP doesn't match expected value (found %d, expected %d)\n",
-			 tdp / 8, limits->mcp_power_limit / 1000);
+	if (limits->core_power_limit != (tdp / 8) * 1000) {
+		dev_info(&ips->dev->dev, "CPU TDP doesn't match expected value (found %d, expected %d)\n",
+			 tdp / 8, limits->core_power_limit / 1000);
+		limits->core_power_limit = (tdp / 8) * 1000;
 	}
 
 out:
@@ -1390,7 +1443,7 @@
 	return true;
 
 out_put_busy:
-	symbol_put(i915_gpu_turbo_disable);
+	symbol_put(i915_gpu_busy);
 out_put_lower:
 	symbol_put(i915_gpu_lower);
 out_put_raise:
@@ -1532,23 +1585,28 @@
 	/* Save turbo limits & ratios */
 	rdmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit);
 
-	ips_enable_cpu_turbo(ips);
-	ips->cpu_turbo_enabled = true;
+	ips_disable_cpu_turbo(ips);
+	ips->cpu_turbo_enabled = false;
 
-	/* Set up the work queue and monitor/adjust threads */
-	ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor");
-	if (IS_ERR(ips->monitor)) {
-		dev_err(&dev->dev,
-			"failed to create thermal monitor thread, aborting\n");
-		ret = -ENOMEM;
-		goto error_free_irq;
-	}
-
+	/* Create thermal adjust thread */
 	ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust");
 	if (IS_ERR(ips->adjust)) {
 		dev_err(&dev->dev,
 			"failed to create thermal adjust thread, aborting\n");
 		ret = -ENOMEM;
+		goto error_free_irq;
+
+	}
+
+	/*
+	 * Set up the work queue and monitor thread. The monitor thread
+	 * will wake up ips_adjust thread.
+	 */
+	ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor");
+	if (IS_ERR(ips->monitor)) {
+		dev_err(&dev->dev,
+			"failed to create thermal monitor thread, aborting\n");
+		ret = -ENOMEM;
 		goto error_thread_cleanup;
 	}
 
@@ -1566,7 +1624,7 @@
 	return ret;
 
 error_thread_cleanup:
-	kthread_stop(ips->monitor);
+	kthread_stop(ips->adjust);
 error_free_irq:
 	free_irq(ips->dev->irq, ips);
 error_unmap:
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index e3154ff..f200677 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -2360,6 +2360,7 @@
 	.release	= sonypi_misc_release,
 	.fasync		= sonypi_misc_fasync,
 	.unlocked_ioctl	= sonypi_misc_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice sonypi_misc_device = {
diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
index 3f94eda..e73ebef 100644
--- a/drivers/pnp/isapnp/proc.c
+++ b/drivers/pnp/isapnp/proc.c
@@ -31,8 +31,9 @@
 static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
 {
 	loff_t new = -1;
+	struct inode *inode = file->f_path.dentry->d_inode;
 
-	lock_kernel();
+	mutex_lock(&inode->i_mutex);
 	switch (whence) {
 	case 0:
 		new = off;
@@ -44,12 +45,12 @@
 		new = 256 + off;
 		break;
 	}
-	if (new < 0 || new > 256) {
-		unlock_kernel();
-		return -EINVAL;
-	}
-	unlock_kernel();
-	return (file->f_pos = new);
+	if (new < 0 || new > 256)
+		new = -EINVAL;
+	else
+		file->f_pos = new;
+	mutex_unlock(&inode->i_mutex);
+	return new;
 }
 
 static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf,
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index df1fb53..a4be416 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -256,7 +256,6 @@
 
 	regulator_unregister(chip->rdev);
 	kfree(chip);
-	i2c_set_clientdata(client, NULL);
 
 	return 0;
 }
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 422a709..cc8b337 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -700,7 +700,7 @@
 	    constraints->min_uA != constraints->max_uA) {
 		ret = _regulator_get_current_limit(rdev);
 		if (ret > 0)
-			count += sprintf(buf + count, "at %d uA ", ret / 1000);
+			count += sprintf(buf + count, "at %d mA ", ret / 1000);
 	}
 
 	if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
@@ -2302,8 +2302,10 @@
 	dev_set_name(&rdev->dev, "regulator.%d",
 		     atomic_inc_return(&regulator_no) - 1);
 	ret = device_register(&rdev->dev);
-	if (ret != 0)
+	if (ret != 0) {
+		put_device(&rdev->dev);
 		goto clean;
+	}
 
 	dev_set_drvdata(&rdev->dev, rdev);
 
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index d61ecb8..b8cc638 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -191,8 +191,6 @@
 	struct isl_pmic *pmic = i2c_get_clientdata(i2c);
 	int i;
 
-	i2c_set_clientdata(i2c, NULL);
-
 	for (i = 0; i < 3; i++)
 		regulator_unregister(pmic->rdev[i]);
 
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index 4520ace..6b60a9c 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -330,7 +330,7 @@
 		/* set external clock frequency */
 		info->extclk_freq = pdata->extclk_freq;
 		max8649_set_bits(info->i2c, MAX8649_SYNC, MAX8649_EXT_MASK,
-				 info->extclk_freq);
+				 info->extclk_freq << 6);
 	}
 
 	if (pdata->ramp_timing) {
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index 9daed8d..9de8516 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -268,7 +268,6 @@
 		free_irq(client->irq, client);
 
 out_free:
-	i2c_set_clientdata(client, NULL);
 	kfree(ds3232);
 	return ret;
 }
@@ -287,7 +286,6 @@
 	}
 
 	rtc_device_unregister(ds3232->rtc);
-	i2c_set_clientdata(client, NULL);
 	kfree(ds3232);
 	return 0;
 }
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index d60557c..5a8daa3 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -20,7 +20,7 @@
 #include <linux/module.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/string.h>
 #ifdef CONFIG_RTC_DRV_M41T80_WDT
 #include <linux/fs.h>
@@ -68,6 +68,7 @@
 
 #define DRV_VERSION "0.05"
 
+static DEFINE_MUTEX(m41t80_rtc_mutex);
 static const struct i2c_device_id m41t80_id[] = {
 	{ "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT },
 	{ "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD },
@@ -677,9 +678,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&m41t80_rtc_mutex);
 	ret = wdt_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&m41t80_rtc_mutex);
 
 	return ret;
 }
@@ -693,16 +694,16 @@
 static int wdt_open(struct inode *inode, struct file *file)
 {
 	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
-		lock_kernel();
+		mutex_lock(&m41t80_rtc_mutex);
 		if (test_and_set_bit(0, &wdt_is_open)) {
-			unlock_kernel();
+			mutex_unlock(&m41t80_rtc_mutex);
 			return -EBUSY;
 		}
 		/*
 		 *	Activate
 		 */
 		wdt_is_open = 1;
-		unlock_kernel();
+		mutex_unlock(&m41t80_rtc_mutex);
 		return nonseekable_open(inode, file);
 	}
 	return -ENODEV;
@@ -748,6 +749,7 @@
 	.write	= wdt_write,
 	.open	= wdt_open,
 	.release = wdt_release,
+	.llseek = no_llseek,
 };
 
 static struct miscdevice wdt_dev = {
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 8373ca0..aa95f10 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -21,7 +21,6 @@
 #include <linux/hdreg.h>
 #include <linux/async.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/ccwdev.h>
 #include <asm/ebcdic.h>
@@ -2197,7 +2196,6 @@
 	 */
 	blk_queue_max_segment_size(block->request_queue, PAGE_SIZE);
 	blk_queue_segment_boundary(block->request_queue, PAGE_SIZE - 1);
-	blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN);
 }
 
 /*
@@ -2236,7 +2234,6 @@
 	if (!block)
 		return -ENODEV;
 
-	lock_kernel();
 	base = block->base;
 	atomic_inc(&block->open_count);
 	if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) {
@@ -2271,14 +2268,12 @@
 		goto out;
 	}
 
-	unlock_kernel();
 	return 0;
 
 out:
 	module_put(base->discipline->owner);
 unlock:
 	atomic_dec(&block->open_count);
-	unlock_kernel();
 	return rc;
 }
 
@@ -2286,10 +2281,8 @@
 {
 	struct dasd_block *block = disk->private_data;
 
-	lock_kernel();
 	atomic_dec(&block->open_count);
 	module_put(block->base->discipline->owner);
-	unlock_kernel();
 	return 0;
 }
 
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 7158f95..c71d89d 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -670,6 +670,7 @@
 	.read		= &dasd_eer_read,
 	.poll		= &dasd_eer_poll,
 	.owner		= THIS_MODULE,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice *dasd_eer_dev = NULL;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 1557214..26075e9 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -16,7 +16,6 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/blkpg.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/compat.h>
 #include <asm/ccwdev.h>
@@ -370,9 +369,8 @@
 	return ret;
 }
 
-static int
-dasd_do_ioctl(struct block_device *bdev, fmode_t mode,
-	      unsigned int cmd, unsigned long arg)
+int dasd_ioctl(struct block_device *bdev, fmode_t mode,
+	       unsigned int cmd, unsigned long arg)
 {
 	struct dasd_block *block = bdev->bd_disk->private_data;
 	void __user *argp;
@@ -430,14 +428,3 @@
 		return -EINVAL;
 	}
 }
-
-int dasd_ioctl(struct block_device *bdev, fmode_t mode,
-	       unsigned int cmd, unsigned long arg)
-{
-	int rc;
-
-	lock_kernel();
-	rc = dasd_do_ioctl(bdev, mode, cmd, arg);
-	unlock_kernel();
-	return rc;
-}
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 2bd72aa..9b43ae9 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
@@ -776,7 +775,6 @@
 	struct dcssblk_dev_info *dev_info;
 	int rc;
 
-	lock_kernel();
 	dev_info = bdev->bd_disk->private_data;
 	if (NULL == dev_info) {
 		rc = -ENODEV;
@@ -786,7 +784,6 @@
 	bdev->bd_block_size = 4096;
 	rc = 0;
 out:
-	unlock_kernel();
 	return rc;
 }
 
@@ -797,7 +794,6 @@
 	struct segment_info *entry;
 	int rc;
 
-	lock_kernel();
 	if (!dev_info) {
 		rc = -ENODEV;
 		goto out;
@@ -815,7 +811,6 @@
 	up_write(&dcssblk_devices_sem);
 	rc = 0;
 out:
-	unlock_kernel();
 	return rc;
 }
 
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 857dfcb..eb28fb0 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -520,6 +520,7 @@
 	.compat_ioctl	 = fs3270_ioctl,	/* ioctl */
 	.open		 = fs3270_open,		/* open */
 	.release	 = fs3270_close,	/* release */
+	.llseek		= no_llseek,
 };
 
 /*
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index e021ec6..5b8b859 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -447,6 +447,7 @@
 	.release = &mon_close,
 	.read    = &mon_read,
 	.poll    = &mon_poll,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice mon_dev = {
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 572a1e7..e0702d3 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -274,6 +274,7 @@
 	.open	 = &monwrite_open,
 	.release = &monwrite_close,
 	.write	 = &monwrite_write,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice mon_dev = {
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index f6d72e1..5707a80 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -468,7 +468,7 @@
 	cr0_sync &= 0xffff00a0;
 	cr0_sync |= 0x00000200;
 	__ctl_load(cr0_sync, 0, 0);
-	__raw_local_irq_stosm(0x01);
+	__arch_local_irq_stosm(0x01);
 	/* Loop until driver state indicates finished request */
 	while (sclp_running_state != sclp_running_state_idle) {
 		/* Check for expired request timer */
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 85cf607..f0fa9ca 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -16,7 +16,7 @@
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <linux/buffer_head.h>
 #include <linux/kernel.h>
@@ -45,6 +45,7 @@
 /*
  * file operation structure for tape block frontend
  */
+static DEFINE_MUTEX(tape_block_mutex);
 static int tapeblock_open(struct block_device *, fmode_t);
 static int tapeblock_release(struct gendisk *, fmode_t);
 static int tapeblock_medium_changed(struct gendisk *);
@@ -361,7 +362,7 @@
 	struct tape_device *	device;
 	int			rc;
 
-	lock_kernel();
+	mutex_lock(&tape_block_mutex);
 	device = tape_get_device(disk->private_data);
 
 	if (device->required_tapemarks) {
@@ -385,14 +386,14 @@
 	 *       is called.
 	 */
 	tape_state_set(device, TS_BLKUSE);
-	unlock_kernel();
+	mutex_unlock(&tape_block_mutex);
 	return 0;
 
 release:
 	tape_release(device);
  put_device:
 	tape_put_device(device);
-	unlock_kernel();
+	mutex_unlock(&tape_block_mutex);
 	return rc;
 }
 
@@ -407,11 +408,11 @@
 {
 	struct tape_device *device = disk->private_data;
  
-	lock_kernel();
+	mutex_lock(&tape_block_mutex);
 	tape_state_set(device, TS_IN_USE);
 	tape_release(device);
 	tape_put_device(device);
-	unlock_kernel();
+	mutex_unlock(&tape_block_mutex);
 
 	return 0;
 }
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 539045a..883e2db 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -53,6 +53,7 @@
 #endif
 	.open = tapechar_open,
 	.release = tapechar_release,
+	.llseek = no_llseek,
 };
 
 static int tapechar_major = TAPECHAR_MAJOR;
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 04e532e..0e7cb1a 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -177,6 +177,7 @@
 	.write		= vmcp_write,
 	.unlocked_ioctl	= vmcp_ioctl,
 	.compat_ioctl	= vmcp_ioctl,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice vmcp_dev = {
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index e40a1b8..0d6dc4b 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -97,6 +97,7 @@
 	.open    = vmlogrdr_open,
 	.release = vmlogrdr_release,
 	.read    = vmlogrdr_read,
+	.llseek  = no_llseek,
 };
 
 
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index e13508c..12ef912 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -297,6 +297,7 @@
 	.unlocked_ioctl = &vmwdt_ioctl,
 	.write   = &vmwdt_write,
 	.owner   = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice vmwdt_dev = {
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index f5ea338..3b94044 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -459,6 +459,7 @@
 	.read		= zcore_memmap_read,
 	.open		= zcore_memmap_open,
 	.release	= zcore_memmap_release,
+	.llseek		= no_llseek,
 };
 
 static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf,
@@ -486,6 +487,7 @@
 	.write		= zcore_reipl_write,
 	.open		= zcore_reipl_open,
 	.release	= zcore_reipl_release,
+	.llseek		= no_llseek,
 };
 
 #ifdef CONFIG_32BIT
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index a83877c..f2b77e7 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -806,6 +806,7 @@
 	.open = nonseekable_open,
 	.unlocked_ioctl = chsc_ioctl,
 	.compat_ioctl = chsc_ioctl,
+	.llseek = no_llseek,
 };
 
 static struct miscdevice chsc_misc_device = {
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index ac94ac75..ca8e1c2 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1067,6 +1067,7 @@
 static const struct file_operations cio_settle_proc_fops = {
 	.open = nonseekable_open,
 	.write = cio_settle_write,
+	.llseek = no_llseek,
 };
 
 static int __init cio_settle_init(void)
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index f0037ee..0f4ef87 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -208,6 +208,7 @@
 	unsigned int eqbs_partial;
 	unsigned int sqbs;
 	unsigned int sqbs_partial;
+	unsigned int int_discarded;
 } ____cacheline_aligned;
 
 struct qdio_queue_perf_stat {
@@ -222,6 +223,10 @@
 	unsigned int nr_sbal_total;
 };
 
+enum qdio_queue_irq_states {
+	QDIO_QUEUE_IRQS_DISABLED,
+};
+
 struct qdio_input_q {
 	/* input buffer acknowledgement flag */
 	int polling;
@@ -231,6 +236,10 @@
 	int ack_count;
 	/* last time of noticing incoming data */
 	u64 timestamp;
+	/* upper-layer polling flag */
+	unsigned long queue_irq_state;
+	/* callback to start upper-layer polling */
+	void (*queue_start_poll) (struct ccw_device *, int, unsigned long);
 };
 
 struct qdio_output_q {
@@ -399,6 +408,26 @@
 #define sub_buf(bufnr, dec) \
 	((bufnr - dec) & QDIO_MAX_BUFFERS_MASK)
 
+#define queue_irqs_enabled(q)			\
+	(test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) == 0)
+#define queue_irqs_disabled(q)			\
+	(test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) != 0)
+
+#define TIQDIO_SHARED_IND		63
+
+/* device state change indicators */
+struct indicator_t {
+	u32 ind;	/* u32 because of compare-and-swap performance */
+	atomic_t count; /* use count, 0 or 1 for non-shared indicators */
+};
+
+extern struct indicator_t *q_indicators;
+
+static inline int shared_ind(struct qdio_irq *irq_ptr)
+{
+	return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
+}
+
 /* prototypes for thin interrupt */
 void qdio_setup_thinint(struct qdio_irq *irq_ptr);
 int qdio_establish_thinint(struct qdio_irq *irq_ptr);
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index 6ce83f5..28868e7 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -56,9 +56,16 @@
 
 	seq_printf(m, "DSCI: %d   nr_used: %d\n",
 		   *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
-	seq_printf(m, "ftc: %d  last_move: %d\n", q->first_to_check, q->last_move);
-	seq_printf(m, "polling: %d  ack start: %d  ack count: %d\n",
-		   q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count);
+	seq_printf(m, "ftc: %d  last_move: %d\n",
+		   q->first_to_check, q->last_move);
+	if (q->is_input_q) {
+		seq_printf(m, "polling: %d  ack start: %d  ack count: %d\n",
+			   q->u.in.polling, q->u.in.ack_start,
+			   q->u.in.ack_count);
+		seq_printf(m, "IRQs disabled: %u\n",
+			   test_bit(QDIO_QUEUE_IRQS_DISABLED,
+			   &q->u.in.queue_irq_state));
+	}
 	seq_printf(m, "SBAL states:\n");
 	seq_printf(m, "|0      |8      |16     |24     |32     |40     |48     |56  63|\n");
 
@@ -113,22 +120,6 @@
 	return 0;
 }
 
-static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
-			       size_t count, loff_t *off)
-{
-	struct seq_file *seq = file->private_data;
-	struct qdio_q *q = seq->private;
-
-	if (!q)
-		return 0;
-	if (q->is_input_q)
-		xchg(q->irq_ptr->dsci, 1);
-	local_bh_disable();
-	tasklet_schedule(&q->tasklet);
-	local_bh_enable();
-	return count;
-}
-
 static int qstat_seq_open(struct inode *inode, struct file *filp)
 {
 	return single_open(filp, qstat_show,
@@ -139,7 +130,6 @@
 	.owner	 = THIS_MODULE,
 	.open	 = qstat_seq_open,
 	.read	 = seq_read,
-	.write	 = qstat_seq_write,
 	.llseek  = seq_lseek,
 	.release = single_release,
 };
@@ -166,7 +156,8 @@
 	"QEBSM eqbs",
 	"QEBSM eqbs partial",
 	"QEBSM sqbs",
-	"QEBSM sqbs partial"
+	"QEBSM sqbs partial",
+	"Discarded interrupts"
 };
 
 static int qperf_show(struct seq_file *m, void *v)
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 00520f9..5fcfa7f 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -884,8 +884,19 @@
 	if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
 		return;
 
-	for_each_input_queue(irq_ptr, q, i)
-		tasklet_schedule(&q->tasklet);
+	for_each_input_queue(irq_ptr, q, i) {
+		if (q->u.in.queue_start_poll) {
+			/* skip if polling is enabled or already in work */
+			if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
+				     &q->u.in.queue_irq_state)) {
+				qperf_inc(q, int_discarded);
+				continue;
+			}
+			q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
+						 q->irq_ptr->int_parm);
+		} else
+			tasklet_schedule(&q->tasklet);
+	}
 
 	if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED))
 		return;
@@ -1519,6 +1530,129 @@
 }
 EXPORT_SYMBOL_GPL(do_QDIO);
 
+/**
+ * qdio_start_irq - process input buffers
+ * @cdev: associated ccw_device for the qdio subchannel
+ * @nr: input queue number
+ *
+ * Return codes
+ *   0 - success
+ *   1 - irqs not started since new data is available
+ */
+int qdio_start_irq(struct ccw_device *cdev, int nr)
+{
+	struct qdio_q *q;
+	struct qdio_irq *irq_ptr = cdev->private->qdio_data;
+
+	if (!irq_ptr)
+		return -ENODEV;
+	q = irq_ptr->input_qs[nr];
+
+	WARN_ON(queue_irqs_enabled(q));
+
+	if (!shared_ind(q->irq_ptr))
+		xchg(q->irq_ptr->dsci, 0);
+
+	qdio_stop_polling(q);
+	clear_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state);
+
+	/*
+	 * We need to check again to not lose initiative after
+	 * resetting the ACK state.
+	 */
+	if (!shared_ind(q->irq_ptr) && *q->irq_ptr->dsci)
+		goto rescan;
+	if (!qdio_inbound_q_done(q))
+		goto rescan;
+	return 0;
+
+rescan:
+	if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
+			     &q->u.in.queue_irq_state))
+		return 0;
+	else
+		return 1;
+
+}
+EXPORT_SYMBOL(qdio_start_irq);
+
+/**
+ * qdio_get_next_buffers - process input buffers
+ * @cdev: associated ccw_device for the qdio subchannel
+ * @nr: input queue number
+ * @bufnr: first filled buffer number
+ * @error: buffers are in error state
+ *
+ * Return codes
+ *   < 0 - error
+ *   = 0 - no new buffers found
+ *   > 0 - number of processed buffers
+ */
+int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr,
+			  int *error)
+{
+	struct qdio_q *q;
+	int start, end;
+	struct qdio_irq *irq_ptr = cdev->private->qdio_data;
+
+	if (!irq_ptr)
+		return -ENODEV;
+	q = irq_ptr->input_qs[nr];
+	WARN_ON(queue_irqs_enabled(q));
+
+	qdio_sync_after_thinint(q);
+
+	/*
+	 * The interrupt could be caused by a PCI request. Check the
+	 * PCI capable outbound queues.
+	 */
+	qdio_check_outbound_after_thinint(q);
+
+	if (!qdio_inbound_q_moved(q))
+		return 0;
+
+	/* Note: upper-layer MUST stop processing immediately here ... */
+	if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE))
+		return -EIO;
+
+	start = q->first_to_kick;
+	end = q->first_to_check;
+	*bufnr = start;
+	*error = q->qdio_error;
+
+	/* for the next time */
+	q->first_to_kick = end;
+	q->qdio_error = 0;
+	return sub_buf(end, start);
+}
+EXPORT_SYMBOL(qdio_get_next_buffers);
+
+/**
+ * qdio_stop_irq - disable interrupt processing for the device
+ * @cdev: associated ccw_device for the qdio subchannel
+ * @nr: input queue number
+ *
+ * Return codes
+ *   0 - interrupts were already disabled
+ *   1 - interrupts successfully disabled
+ */
+int qdio_stop_irq(struct ccw_device *cdev, int nr)
+{
+	struct qdio_q *q;
+	struct qdio_irq *irq_ptr = cdev->private->qdio_data;
+
+	if (!irq_ptr)
+		return -ENODEV;
+	q = irq_ptr->input_qs[nr];
+
+	if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
+			     &q->u.in.queue_irq_state))
+		return 0;
+	else
+		return 1;
+}
+EXPORT_SYMBOL(qdio_stop_irq);
+
 static int __init init_QDIO(void)
 {
 	int rc;
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 34c7e40..a13cf7e 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -161,6 +161,7 @@
 		setup_queues_misc(q, irq_ptr, qdio_init->input_handler, i);
 
 		q->is_input_q = 1;
+		q->u.in.queue_start_poll = qdio_init->queue_start_poll;
 		setup_storage_lists(q, irq_ptr, input_sbal_array, i);
 		input_sbal_array += QDIO_MAX_BUFFERS_PER_Q;
 
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 8daf1b9..752dbee 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -25,24 +25,20 @@
  */
 #define TIQDIO_NR_NONSHARED_IND		63
 #define TIQDIO_NR_INDICATORS		(TIQDIO_NR_NONSHARED_IND + 1)
-#define TIQDIO_SHARED_IND		63
 
 /* list of thin interrupt input queues */
 static LIST_HEAD(tiq_list);
 DEFINE_MUTEX(tiq_list_lock);
 
 /* adapter local summary indicator */
-static unsigned char *tiqdio_alsi;
+static u8 *tiqdio_alsi;
 
-/* device state change indicators */
-struct indicator_t {
-	u32 ind;	/* u32 because of compare-and-swap performance */
-	atomic_t count; /* use count, 0 or 1 for non-shared indicators */
-};
-static struct indicator_t *q_indicators;
+struct indicator_t *q_indicators;
 
 static int css_qdio_omit_svs;
 
+static u64 last_ai_time;
+
 static inline unsigned long do_clear_global_summary(void)
 {
 	register unsigned long __fn asm("1") = 3;
@@ -116,59 +112,73 @@
 	}
 }
 
-static inline int shared_ind(struct qdio_irq *irq_ptr)
+static inline int shared_ind_used(void)
 {
-	return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
+	return atomic_read(&q_indicators[TIQDIO_SHARED_IND].count);
 }
 
 /**
  * tiqdio_thinint_handler - thin interrupt handler for qdio
- * @ind: pointer to adapter local summary indicator
- * @drv_data: NULL
+ * @alsi: pointer to adapter local summary indicator
+ * @data: NULL
  */
-static void tiqdio_thinint_handler(void *ind, void *drv_data)
+static void tiqdio_thinint_handler(void *alsi, void *data)
 {
 	struct qdio_q *q;
 
+	last_ai_time = S390_lowcore.int_clock;
+
 	/*
 	 * SVS only when needed: issue SVS to benefit from iqdio interrupt
-	 * avoidance (SVS clears adapter interrupt suppression overwrite)
+	 * avoidance (SVS clears adapter interrupt suppression overwrite).
 	 */
 	if (!css_qdio_omit_svs)
 		do_clear_global_summary();
 
-	/*
-	 * reset local summary indicator (tiqdio_alsi) to stop adapter
-	 * interrupts for now
-	 */
-	xchg((u8 *)ind, 0);
+	/* reset local summary indicator */
+	if (shared_ind_used())
+		xchg(tiqdio_alsi, 0);
 
 	/* protect tiq_list entries, only changed in activate or shutdown */
 	rcu_read_lock();
 
 	/* check for work on all inbound thinint queues */
-	list_for_each_entry_rcu(q, &tiq_list, entry)
-		/* only process queues from changed sets */
-		if (*q->irq_ptr->dsci) {
-			qperf_inc(q, adapter_int);
+	list_for_each_entry_rcu(q, &tiq_list, entry) {
 
+		/* only process queues from changed sets */
+		if (!*q->irq_ptr->dsci)
+			continue;
+
+		if (q->u.in.queue_start_poll) {
+			/* skip if polling is enabled or already in work */
+			if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
+					     &q->u.in.queue_irq_state)) {
+				qperf_inc(q, int_discarded);
+				continue;
+			}
+
+			/* avoid dsci clear here, done after processing */
+			q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
+						 q->irq_ptr->int_parm);
+		} else {
 			/* only clear it if the indicator is non-shared */
 			if (!shared_ind(q->irq_ptr))
 				xchg(q->irq_ptr->dsci, 0);
 			/*
-			 * don't call inbound processing directly since
-			 * that could starve other thinint queues
+			 * Call inbound processing but not directly
+			 * since that could starve other thinint queues.
 			 */
 			tasklet_schedule(&q->tasklet);
 		}
-
+		qperf_inc(q, adapter_int);
+	}
 	rcu_read_unlock();
 
 	/*
-	 * if we used the shared indicator clear it now after all queues
-	 * were processed
+	 * If the shared indicator was used clear it now after all queues
+	 * were processed.
 	 */
-	if (atomic_read(&q_indicators[TIQDIO_SHARED_IND].count)) {
+	if (shared_ind_used()) {
 		xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
 
 		/* prevent racing */
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 41e0aae..f522174 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -897,7 +897,8 @@
 	.compat_ioctl	= zcrypt_compat_ioctl,
 #endif
 	.open		= zcrypt_open,
-	.release	= zcrypt_release
+	.release	= zcrypt_release,
+	.llseek		= no_llseek,
 };
 
 /*
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index 977bb4d..456b187 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -100,6 +100,6 @@
 
 config CCWGROUP
 	tristate
-	default (LCS || CTCM || QETH)
+	default (LCS || CTCM || QETH || CLAW)
 
 endmenu
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 6edf20b..2c7d2d9 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -1154,7 +1154,7 @@
 				dev_fsm, dev_fsm_len, GFP_KERNEL);
 	if (priv->fsm == NULL) {
 		CTCMY_DBF_DEV(SETUP, dev, "init_fsm error");
-		kfree(dev);
+		free_netdev(dev);
 		return NULL;
 	}
 	fsm_newstate(priv->fsm, DEV_STATE_STOPPED);
@@ -1165,7 +1165,7 @@
 		grp = ctcmpc_init_mpc_group(priv);
 		if (grp == NULL) {
 			MPC_DBF_DEV(SETUP, dev, "init_mpc_group error");
-			kfree(dev);
+			free_netdev(dev);
 			return NULL;
 		}
 		tasklet_init(&grp->mpc_tasklet2,
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index 2861e78..b64881f 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -540,7 +540,7 @@
 
 	CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG,
 			"%s: %s: refcount = %d\n",
-			CTCM_FUNTAIL, dev->name, atomic_read(&dev->refcnt));
+			CTCM_FUNTAIL, dev->name, netdev_refcnt_read(dev));
 
 	fsm_deltimer(&priv->restart_timer);
 	grp->channels_terminating = 0;
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index d125776..6be43eb 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -676,6 +676,7 @@
 };
 
 struct qeth_discipline {
+	void (*start_poll)(struct ccw_device *, int, unsigned long);
 	qdio_handler_t *input_handler;
 	qdio_handler_t *output_handler;
 	int (*recover)(void *ptr);
@@ -702,6 +703,16 @@
 #define QETH_SKB_MAGIC 0x71657468
 #define QETH_SIGA_CC2_RETRIES 3
 
+struct qeth_rx {
+	int b_count;
+	int b_index;
+	struct qdio_buffer_element *b_element;
+	int e_offset;
+	int qdio_err;
+};
+
+#define QETH_NAPI_WEIGHT 128
+
 struct qeth_card {
 	struct list_head list;
 	enum qeth_card_states state;
@@ -749,6 +760,8 @@
 	debug_info_t *debug;
 	struct mutex conf_mutex;
 	struct mutex discipline_mutex;
+	struct napi_struct napi;
+	struct qeth_rx rx;
 };
 
 struct qeth_card_list_struct {
@@ -831,6 +844,10 @@
 		struct qdio_buffer *, struct qdio_buffer_element **, int *,
 		struct qeth_hdr **);
 void qeth_schedule_recovery(struct qeth_card *);
+void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long);
+void qeth_qdio_input_handler(struct ccw_device *,
+		unsigned int, unsigned int, int,
+		int, unsigned long);
 void qeth_qdio_output_handler(struct ccw_device *, unsigned int,
 			int, int, int, unsigned long);
 void qeth_clear_ipacmd_list(struct qeth_card *);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 3a5a18a..7642670 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -2911,6 +2911,27 @@
 	}
 }
 
+void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue,
+		unsigned long card_ptr)
+{
+	struct qeth_card *card = (struct qeth_card *)card_ptr;
+
+	if (card->dev)
+		napi_schedule(&card->napi);
+}
+EXPORT_SYMBOL_GPL(qeth_qdio_start_poll);
+
+void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err,
+		unsigned int queue, int first_element, int count,
+		unsigned long card_ptr)
+{
+	struct qeth_card *card = (struct qeth_card *)card_ptr;
+
+	if (qdio_err)
+		qeth_schedule_recovery(card);
+}
+EXPORT_SYMBOL_GPL(qeth_qdio_input_handler);
+
 void qeth_qdio_output_handler(struct ccw_device *ccwdev,
 		unsigned int qdio_error, int __queue, int first_element,
 		int count, unsigned long card_ptr)
@@ -3843,6 +3864,7 @@
 	init_data.no_output_qs           = card->qdio.no_out_queues;
 	init_data.input_handler          = card->discipline.input_handler;
 	init_data.output_handler         = card->discipline.output_handler;
+	init_data.queue_start_poll	 = card->discipline.start_poll;
 	init_data.int_parm               = (unsigned long) card;
 	init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
 	init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
@@ -4513,8 +4535,8 @@
 /* 20 */{"queue 1 buffer usage"},
 	{"queue 2 buffer usage"},
 	{"queue 3 buffer usage"},
-	{"rx handler time"},
-	{"rx handler count"},
+	{"rx poll time"},
+	{"rx poll count"},
 	{"rx do_QDIO time"},
 	{"rx do_QDIO count"},
 	{"tx handler time"},
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 830d6352..847e8797 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -310,6 +310,8 @@
 	struct qeth_vlan_vid *id;
 
 	QETH_CARD_TEXT_(card, 4, "aid:%d", vid);
+	if (!vid)
+		return;
 	if (card->info.type == QETH_CARD_TYPE_OSM) {
 		QETH_CARD_TEXT(card, 3, "aidOSM");
 		return;
@@ -407,29 +409,25 @@
 	return rc;
 }
 
-static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
-			    struct qeth_qdio_buffer *buf, int index)
+static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
+				int budget, int *done)
 {
-	struct qdio_buffer_element *element;
+	int work_done = 0;
 	struct sk_buff *skb;
 	struct qeth_hdr *hdr;
-	int offset;
 	unsigned int len;
 
-	/* get first element of current buffer */
-	element = (struct qdio_buffer_element *)&buf->buffer->element[0];
-	offset = 0;
-	if (card->options.performance_stats)
-		card->perf_stats.bufs_rec++;
-	while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
-				       &offset, &hdr))) {
-		skb->dev = card->dev;
-		/* is device UP ? */
-		if (!(card->dev->flags & IFF_UP)) {
-			dev_kfree_skb_any(skb);
-			continue;
+	*done = 0;
+	BUG_ON(!budget);
+	while (budget) {
+		skb = qeth_core_get_next_skb(card,
+			card->qdio.in_q->bufs[card->rx.b_index].buffer,
+			&card->rx.b_element, &card->rx.e_offset, &hdr);
+		if (!skb) {
+			*done = 1;
+			break;
 		}
-
+		skb->dev = card->dev;
 		switch (hdr->hdr.l2.id) {
 		case QETH_HEADER_TYPE_LAYER2:
 			skb->pkt_type = PACKET_HOST;
@@ -441,7 +439,7 @@
 			if (skb->protocol == htons(ETH_P_802_2))
 				*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
 			len = skb->len;
-			netif_rx(skb);
+			netif_receive_skb(skb);
 			break;
 		case QETH_HEADER_TYPE_OSN:
 			if (card->info.type == QETH_CARD_TYPE_OSN) {
@@ -459,9 +457,87 @@
 			QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
 			continue;
 		}
+		work_done++;
+		budget--;
 		card->stats.rx_packets++;
 		card->stats.rx_bytes += len;
 	}
+	return work_done;
+}
+
+static int qeth_l2_poll(struct napi_struct *napi, int budget)
+{
+	struct qeth_card *card = container_of(napi, struct qeth_card, napi);
+	int work_done = 0;
+	struct qeth_qdio_buffer *buffer;
+	int done;
+	int new_budget = budget;
+
+	if (card->options.performance_stats) {
+		card->perf_stats.inbound_cnt++;
+		card->perf_stats.inbound_start_time = qeth_get_micros();
+	}
+
+	while (1) {
+		if (!card->rx.b_count) {
+			card->rx.qdio_err = 0;
+			card->rx.b_count = qdio_get_next_buffers(
+				card->data.ccwdev, 0, &card->rx.b_index,
+				&card->rx.qdio_err);
+			if (card->rx.b_count <= 0) {
+				card->rx.b_count = 0;
+				break;
+			}
+			card->rx.b_element =
+				&card->qdio.in_q->bufs[card->rx.b_index]
+				.buffer->element[0];
+			card->rx.e_offset = 0;
+		}
+
+		while (card->rx.b_count) {
+			buffer = &card->qdio.in_q->bufs[card->rx.b_index];
+			if (!(card->rx.qdio_err &&
+			    qeth_check_qdio_errors(card, buffer->buffer,
+			    card->rx.qdio_err, "qinerr")))
+				work_done += qeth_l2_process_inbound_buffer(
+					card, new_budget, &done);
+			else
+				done = 1;
+
+			if (done) {
+				if (card->options.performance_stats)
+					card->perf_stats.bufs_rec++;
+				qeth_put_buffer_pool_entry(card,
+					buffer->pool_entry);
+				qeth_queue_input_buffer(card, card->rx.b_index);
+				card->rx.b_count--;
+				if (card->rx.b_count) {
+					card->rx.b_index =
+						(card->rx.b_index + 1) %
+						QDIO_MAX_BUFFERS_PER_Q;
+					card->rx.b_element =
+						&card->qdio.in_q
+						->bufs[card->rx.b_index]
+						.buffer->element[0];
+					card->rx.e_offset = 0;
+				}
+			}
+
+			if (work_done >= budget)
+				goto out;
+			else
+				new_budget = budget - work_done;
+		}
+	}
+
+	napi_complete(napi);
+	if (qdio_start_irq(card->data.ccwdev, 0))
+		napi_schedule(&card->napi);
+out:
+	if (card->options.performance_stats)
+		card->perf_stats.inbound_time += qeth_get_micros() -
+			card->perf_stats.inbound_start_time;
+	return work_done;
 }
 
 static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
@@ -755,49 +831,10 @@
 	return NETDEV_TX_OK;
 }
 
-static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
-			unsigned int qdio_err, unsigned int queue,
-			int first_element, int count, unsigned long card_ptr)
-{
-	struct net_device *net_dev;
-	struct qeth_card *card;
-	struct qeth_qdio_buffer *buffer;
-	int index;
-	int i;
-
-	card = (struct qeth_card *) card_ptr;
-	net_dev = card->dev;
-	if (card->options.performance_stats) {
-		card->perf_stats.inbound_cnt++;
-		card->perf_stats.inbound_start_time = qeth_get_micros();
-	}
-	if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
-		QETH_CARD_TEXT(card, 1, "qdinchk");
-		QETH_CARD_TEXT_(card, 1, "%04X%04X", first_element,
-				count);
-		QETH_CARD_TEXT_(card, 1, "%04X", queue);
-		qeth_schedule_recovery(card);
-		return;
-	}
-	for (i = first_element; i < (first_element + count); ++i) {
-		index = i % QDIO_MAX_BUFFERS_PER_Q;
-		buffer = &card->qdio.in_q->bufs[index];
-		if (!(qdio_err &&
-		      qeth_check_qdio_errors(card, buffer->buffer, qdio_err,
-					     "qinerr")))
-			qeth_l2_process_inbound_buffer(card, buffer, index);
-		/* clear buffer and give back to hardware */
-		qeth_put_buffer_pool_entry(card, buffer->pool_entry);
-		qeth_queue_input_buffer(card, index);
-	}
-	if (card->options.performance_stats)
-		card->perf_stats.inbound_time += qeth_get_micros() -
-			card->perf_stats.inbound_start_time;
-}
-
 static int qeth_l2_open(struct net_device *dev)
 {
 	struct qeth_card *card = dev->ml_priv;
+	int rc = 0;
 
 	QETH_CARD_TEXT(card, 4, "qethopen");
 	if (card->state != CARD_STATE_SOFTSETUP)
@@ -814,18 +851,24 @@
 
 	if (!card->lan_online && netif_carrier_ok(dev))
 		netif_carrier_off(dev);
-	return 0;
+	if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
+		napi_enable(&card->napi);
+		napi_schedule(&card->napi);
+	} else
+		rc = -EIO;
+	return rc;
 }
 
-
 static int qeth_l2_stop(struct net_device *dev)
 {
 	struct qeth_card *card = dev->ml_priv;
 
 	QETH_CARD_TEXT(card, 4, "qethstop");
 	netif_tx_disable(dev);
-	if (card->state == CARD_STATE_UP)
+	if (card->state == CARD_STATE_UP) {
 		card->state = CARD_STATE_SOFTSETUP;
+		napi_disable(&card->napi);
+	}
 	return 0;
 }
 
@@ -836,8 +879,9 @@
 	INIT_LIST_HEAD(&card->vid_list);
 	INIT_LIST_HEAD(&card->mc_list);
 	card->options.layer2 = 1;
+	card->discipline.start_poll = qeth_qdio_start_poll;
 	card->discipline.input_handler = (qdio_handler_t *)
-		qeth_l2_qdio_input_handler;
+		qeth_qdio_input_handler;
 	card->discipline.output_handler = (qdio_handler_t *)
 		qeth_qdio_output_handler;
 	card->discipline.recover = qeth_l2_recover;
@@ -923,6 +967,7 @@
 	card->info.broadcast_capable = 1;
 	qeth_l2_request_initial_mac(card);
 	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
+	netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT);
 	return register_netdev(card->dev);
 }
 
@@ -955,6 +1000,7 @@
 		qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
 
 	card->state = CARD_STATE_HARDSETUP;
+	memset(&card->rx, 0, sizeof(struct qeth_rx));
 	qeth_print_status_message(card);
 
 	/* softsetup */
@@ -1086,9 +1132,6 @@
 	card->use_hard_stop = 1;
 	__qeth_l2_set_offline(card->gdev, 1);
 	rc = __qeth_l2_set_online(card->gdev, 1);
-	/* don't run another scheduled recovery */
-	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
-	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
 	if (!rc)
 		dev_info(&card->gdev->dev,
 			"Device successfully recovered!\n");
@@ -1099,6 +1142,8 @@
 		dev_warn(&card->gdev->dev, "The qeth device driver "
 			"failed to recover an error on the device\n");
 	}
+	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
+	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
 	return 0;
 }
 
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index e22ae24..74d1401 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -103,12 +103,7 @@
 
 void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf)
 {
-	sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x"
-		     ":%02x%02x:%02x%02x:%02x%02x:%02x%02x",
-		     addr[0], addr[1], addr[2], addr[3],
-		     addr[4], addr[5], addr[6], addr[7],
-		     addr[8], addr[9], addr[10], addr[11],
-		     addr[12], addr[13], addr[14], addr[15]);
+	sprintf(buf, "%pI6", addr);
 }
 
 int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr)
@@ -1825,7 +1820,7 @@
 		return;
 
 	vg = card->vlangrp;
-	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+	for (i = 0; i < VLAN_N_VID; i++) {
 		struct net_device *netdev = vlan_group_get_device(vg, i);
 		if (netdev == NULL ||
 		    !(netdev->flags & IFF_UP))
@@ -1888,7 +1883,7 @@
 		return;
 
 	vg = card->vlangrp;
-	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+	for (i = 0; i < VLAN_N_VID; i++) {
 		struct net_device *netdev = vlan_group_get_device(vg, i);
 		if (netdev == NULL ||
 		    !(netdev->flags & IFF_UP))
@@ -2018,13 +2013,14 @@
 	qeth_l3_set_multicast_list(card->dev);
 }
 
-static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
-			struct sk_buff *skb, struct qeth_hdr *hdr)
+static inline int qeth_l3_rebuild_skb(struct qeth_card *card,
+			struct sk_buff *skb, struct qeth_hdr *hdr,
+			unsigned short *vlan_id)
 {
-	unsigned short vlan_id = 0;
 	__be16 prot;
 	struct iphdr *ip_hdr;
 	unsigned char tg_addr[MAX_ADDR_LEN];
+	int is_vlan = 0;
 
 	if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) {
 		prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 :
@@ -2087,8 +2083,9 @@
 
 	if (hdr->hdr.l3.ext_flags &
 	    (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) {
-		vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)?
+		*vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME) ?
 		 hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]);
+		is_vlan = 1;
 	}
 
 	switch (card->options.checksum_type) {
@@ -2109,54 +2106,44 @@
 			skb->ip_summed = CHECKSUM_NONE;
 	}
 
-	return vlan_id;
+	return is_vlan;
 }
 
-static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
-			    struct qeth_qdio_buffer *buf, int index)
+static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
+				int budget, int *done)
 {
-	struct qdio_buffer_element *element;
+	int work_done = 0;
 	struct sk_buff *skb;
 	struct qeth_hdr *hdr;
-	int offset;
 	__u16 vlan_tag = 0;
+	int is_vlan;
 	unsigned int len;
-	/* get first element of current buffer */
-	element = (struct qdio_buffer_element *)&buf->buffer->element[0];
-	offset = 0;
-	if (card->options.performance_stats)
-		card->perf_stats.bufs_rec++;
-	while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
-				       &offset, &hdr))) {
-		skb->dev = card->dev;
-		/* is device UP ? */
-		if (!(card->dev->flags & IFF_UP)) {
-			dev_kfree_skb_any(skb);
-			continue;
-		}
 
+	*done = 0;
+	BUG_ON(!budget);
+	while (budget) {
+		skb = qeth_core_get_next_skb(card,
+			card->qdio.in_q->bufs[card->rx.b_index].buffer,
+			&card->rx.b_element, &card->rx.e_offset, &hdr);
+		if (!skb) {
+			*done = 1;
+			break;
+		}
+		skb->dev = card->dev;
 		switch (hdr->hdr.l3.id) {
 		case QETH_HEADER_TYPE_LAYER3:
-			vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr);
+			is_vlan = qeth_l3_rebuild_skb(card, skb, hdr,
+						      &vlan_tag);
 			len = skb->len;
-			if (vlan_tag && !card->options.sniffer)
-				if (card->vlangrp)
-					vlan_hwaccel_rx(skb, card->vlangrp,
-						vlan_tag);
-				else {
-					dev_kfree_skb_any(skb);
-					continue;
-				}
+			if (is_vlan && !card->options.sniffer)
+				vlan_gro_receive(&card->napi, card->vlangrp,
+					vlan_tag, skb);
 			else
-				netif_rx(skb);
+				napi_gro_receive(&card->napi, skb);
 			break;
 		case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
 			skb->pkt_type = PACKET_HOST;
 			skb->protocol = eth_type_trans(skb, skb->dev);
-			if (card->options.checksum_type == NO_CHECKSUMMING)
-				skb->ip_summed = CHECKSUM_UNNECESSARY;
-			else
-				skb->ip_summed = CHECKSUM_NONE;
 			len = skb->len;
 			netif_receive_skb(skb);
 			break;
@@ -2166,10 +2153,87 @@
 			QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
 			continue;
 		}
-
+		work_done++;
+		budget--;
 		card->stats.rx_packets++;
 		card->stats.rx_bytes += len;
 	}
+	return work_done;
+}
+
+static int qeth_l3_poll(struct napi_struct *napi, int budget)
+{
+	struct qeth_card *card = container_of(napi, struct qeth_card, napi);
+	int work_done = 0;
+	struct qeth_qdio_buffer *buffer;
+	int done;
+	int new_budget = budget;
+
+	if (card->options.performance_stats) {
+		card->perf_stats.inbound_cnt++;
+		card->perf_stats.inbound_start_time = qeth_get_micros();
+	}
+
+	while (1) {
+		if (!card->rx.b_count) {
+			card->rx.qdio_err = 0;
+			card->rx.b_count = qdio_get_next_buffers(
+				card->data.ccwdev, 0, &card->rx.b_index,
+				&card->rx.qdio_err);
+			if (card->rx.b_count <= 0) {
+				card->rx.b_count = 0;
+				break;
+			}
+			card->rx.b_element =
+				&card->qdio.in_q->bufs[card->rx.b_index]
+				.buffer->element[0];
+			card->rx.e_offset = 0;
+		}
+
+		while (card->rx.b_count) {
+			buffer = &card->qdio.in_q->bufs[card->rx.b_index];
+			if (!(card->rx.qdio_err &&
+			    qeth_check_qdio_errors(card, buffer->buffer,
+			    card->rx.qdio_err, "qinerr")))
+				work_done += qeth_l3_process_inbound_buffer(
+					card, new_budget, &done);
+			else
+				done = 1;
+
+			if (done) {
+				if (card->options.performance_stats)
+					card->perf_stats.bufs_rec++;
+				qeth_put_buffer_pool_entry(card,
+					buffer->pool_entry);
+				qeth_queue_input_buffer(card, card->rx.b_index);
+				card->rx.b_count--;
+				if (card->rx.b_count) {
+					card->rx.b_index =
+						(card->rx.b_index + 1) %
+						QDIO_MAX_BUFFERS_PER_Q;
+					card->rx.b_element =
+						&card->qdio.in_q
+						->bufs[card->rx.b_index]
+						.buffer->element[0];
+					card->rx.e_offset = 0;
+				}
+			}
+
+			if (work_done >= budget)
+				goto out;
+			else
+				new_budget = budget - work_done;
+		}
+	}
+
+	napi_complete(napi);
+	if (qdio_start_irq(card->data.ccwdev, 0))
+		napi_schedule(&card->napi);
+out:
+	if (card->options.performance_stats)
+		card->perf_stats.inbound_time += qeth_get_micros() -
+			card->perf_stats.inbound_start_time;
+	return work_done;
 }
 
 static int qeth_l3_verify_vlan_dev(struct net_device *dev,
@@ -2183,7 +2247,7 @@
 	if (!vg)
 		return rc;
 
-	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+	for (i = 0; i < VLAN_N_VID; i++) {
 		if (vlan_group_get_device(vg, i) == dev) {
 			rc = QETH_VLAN_CARD;
 			break;
@@ -3103,6 +3167,7 @@
 static int qeth_l3_open(struct net_device *dev)
 {
 	struct qeth_card *card = dev->ml_priv;
+	int rc = 0;
 
 	QETH_CARD_TEXT(card, 4, "qethopen");
 	if (card->state != CARD_STATE_SOFTSETUP)
@@ -3113,7 +3178,12 @@
 
 	if (!card->lan_online && netif_carrier_ok(dev))
 		netif_carrier_off(dev);
-	return 0;
+	if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
+		napi_enable(&card->napi);
+		napi_schedule(&card->napi);
+	} else
+		rc = -EIO;
+	return rc;
 }
 
 static int qeth_l3_stop(struct net_device *dev)
@@ -3122,8 +3192,10 @@
 
 	QETH_CARD_TEXT(card, 4, "qethstop");
 	netif_tx_disable(dev);
-	if (card->state == CARD_STATE_UP)
+	if (card->state == CARD_STATE_UP) {
 		card->state = CARD_STATE_SOFTSETUP;
+		napi_disable(&card->napi);
+	}
 	return 0;
 }
 
@@ -3293,57 +3365,19 @@
 	card->dev->gso_max_size = 15 * PAGE_SIZE;
 
 	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
+	netif_napi_add(card->dev, &card->napi, qeth_l3_poll, QETH_NAPI_WEIGHT);
 	return register_netdev(card->dev);
 }
 
-static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
-		unsigned int qdio_err, unsigned int queue, int first_element,
-		int count, unsigned long card_ptr)
-{
-	struct net_device *net_dev;
-	struct qeth_card *card;
-	struct qeth_qdio_buffer *buffer;
-	int index;
-	int i;
-
-	card = (struct qeth_card *) card_ptr;
-	net_dev = card->dev;
-	if (card->options.performance_stats) {
-		card->perf_stats.inbound_cnt++;
-		card->perf_stats.inbound_start_time = qeth_get_micros();
-	}
-	if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
-		QETH_CARD_TEXT(card, 1, "qdinchk");
-		QETH_CARD_TEXT_(card, 1, "%04X%04X",
-				first_element, count);
-		QETH_CARD_TEXT_(card, 1, "%04X", queue);
-		qeth_schedule_recovery(card);
-		return;
-	}
-	for (i = first_element; i < (first_element + count); ++i) {
-		index = i % QDIO_MAX_BUFFERS_PER_Q;
-		buffer = &card->qdio.in_q->bufs[index];
-		if (!(qdio_err &&
-		      qeth_check_qdio_errors(card, buffer->buffer,
-					     qdio_err, "qinerr")))
-			qeth_l3_process_inbound_buffer(card, buffer, index);
-		/* clear buffer and give back to hardware */
-		qeth_put_buffer_pool_entry(card, buffer->pool_entry);
-		qeth_queue_input_buffer(card, index);
-	}
-	if (card->options.performance_stats)
-		card->perf_stats.inbound_time += qeth_get_micros() -
-			card->perf_stats.inbound_start_time;
-}
-
 static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
 
 	qeth_l3_create_device_attributes(&gdev->dev);
 	card->options.layer2 = 0;
+	card->discipline.start_poll = qeth_qdio_start_poll;
 	card->discipline.input_handler = (qdio_handler_t *)
-		qeth_l3_qdio_input_handler;
+		qeth_qdio_input_handler;
 	card->discipline.output_handler = (qdio_handler_t *)
 		qeth_qdio_output_handler;
 	card->discipline.recover = qeth_l3_recover;
@@ -3402,6 +3436,7 @@
 	}
 
 	card->state = CARD_STATE_HARDSETUP;
+	memset(&card->rx, 0, sizeof(struct qeth_rx));
 	qeth_print_status_message(card);
 
 	/* softsetup */
@@ -3538,9 +3573,6 @@
 	card->use_hard_stop = 1;
 	__qeth_l3_set_offline(card->gdev, 1);
 	rc = __qeth_l3_set_online(card->gdev, 1);
-	/* don't run another scheduled recovery */
-	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
-	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
 	if (!rc)
 		dev_info(&card->gdev->dev,
 			"Device successfully recovered!\n");
@@ -3551,6 +3583,8 @@
 		dev_warn(&card->gdev->dev, "The qeth device driver "
 			"failed to recover an error on the device\n");
 	}
+	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
+	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
 	return 0;
 }
 
diff --git a/drivers/s390/scsi/Makefile b/drivers/s390/scsi/Makefile
index cb301cc..c454ffe 100644
--- a/drivers/s390/scsi/Makefile
+++ b/drivers/s390/scsi/Makefile
@@ -2,7 +2,8 @@
 # Makefile for the S/390 specific device drivers
 #
 
-zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \
-	     zfcp_fsf.o zfcp_dbf.o zfcp_sysfs.o zfcp_fc.o zfcp_cfdc.o
+zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_cfdc.o zfcp_dbf.o zfcp_erp.o \
+	     zfcp_fc.o zfcp_fsf.o zfcp_qdio.o zfcp_scsi.o zfcp_sysfs.o \
+	     zfcp_unit.o
 
 obj-$(CONFIG_ZFCP) += zfcp.o
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 96fa1f5..044fb22 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -56,7 +56,6 @@
 	struct ccw_device *cdev;
 	struct zfcp_adapter *adapter;
 	struct zfcp_port *port;
-	struct zfcp_unit *unit;
 
 	cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
 	if (!cdev)
@@ -72,17 +71,11 @@
 	port = zfcp_get_port_by_wwpn(adapter, wwpn);
 	if (!port)
 		goto out_port;
+	flush_work(&port->rport_work);
 
-	unit = zfcp_unit_enqueue(port, lun);
-	if (IS_ERR(unit))
-		goto out_unit;
-
-	zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL);
-	zfcp_erp_wait(adapter);
-	flush_work(&unit->scsi_work);
-
-out_unit:
+	zfcp_unit_add(port, lun);
 	put_device(&port->dev);
+
 out_port:
 	zfcp_ccw_adapter_put(adapter);
 out_ccw_device:
@@ -158,6 +151,9 @@
 		fc_attach_transport(&zfcp_transport_functions);
 	if (!zfcp_data.scsi_transport_template)
 		goto out_transport;
+	scsi_transport_reserve_device(zfcp_data.scsi_transport_template,
+				      sizeof(struct zfcp_scsi_dev));
+
 
 	retval = misc_register(&zfcp_cfdc_misc);
 	if (retval) {
@@ -211,30 +207,6 @@
 module_exit(zfcp_module_exit);
 
 /**
- * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN
- * @port: pointer to port to search for unit
- * @fcp_lun: FCP LUN to search for
- *
- * Returns: pointer to zfcp_unit or NULL
- */
-struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
-{
-	unsigned long flags;
-	struct zfcp_unit *unit;
-
-	read_lock_irqsave(&port->unit_list_lock, flags);
-	list_for_each_entry(unit, &port->unit_list, list)
-		if (unit->fcp_lun == fcp_lun) {
-			if (!get_device(&unit->dev))
-				unit = NULL;
-			read_unlock_irqrestore(&port->unit_list_lock, flags);
-			return unit;
-		}
-	read_unlock_irqrestore(&port->unit_list_lock, flags);
-	return NULL;
-}
-
-/**
  * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn
  * @adapter: pointer to adapter to search for port
  * @wwpn: wwpn to search for
@@ -259,92 +231,6 @@
 	return NULL;
 }
 
-/**
- * zfcp_unit_release - dequeue unit
- * @dev: pointer to device
- *
- * waits until all work is done on unit and removes it then from the unit->list
- * of the associated port.
- */
-static void zfcp_unit_release(struct device *dev)
-{
-	struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
-
-	put_device(&unit->port->dev);
-	kfree(unit);
-}
-
-/**
- * zfcp_unit_enqueue - enqueue unit to unit list of a port.
- * @port: pointer to port where unit is added
- * @fcp_lun: FCP LUN of unit to be enqueued
- * Returns: pointer to enqueued unit on success, ERR_PTR on error
- *
- * Sets up some unit internal structures and creates sysfs entry.
- */
-struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
-{
-	struct zfcp_unit *unit;
-	int retval = -ENOMEM;
-
-	get_device(&port->dev);
-
-	unit = zfcp_get_unit_by_lun(port, fcp_lun);
-	if (unit) {
-		put_device(&unit->dev);
-		retval = -EEXIST;
-		goto err_out;
-	}
-
-	unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
-	if (!unit)
-		goto err_out;
-
-	unit->port = port;
-	unit->fcp_lun = fcp_lun;
-	unit->dev.parent = &port->dev;
-	unit->dev.release = zfcp_unit_release;
-
-	if (dev_set_name(&unit->dev, "0x%016llx",
-			 (unsigned long long) fcp_lun)) {
-		kfree(unit);
-		goto err_out;
-	}
-	retval = -EINVAL;
-
-	INIT_WORK(&unit->scsi_work, zfcp_scsi_scan_work);
-
-	spin_lock_init(&unit->latencies.lock);
-	unit->latencies.write.channel.min = 0xFFFFFFFF;
-	unit->latencies.write.fabric.min = 0xFFFFFFFF;
-	unit->latencies.read.channel.min = 0xFFFFFFFF;
-	unit->latencies.read.fabric.min = 0xFFFFFFFF;
-	unit->latencies.cmd.channel.min = 0xFFFFFFFF;
-	unit->latencies.cmd.fabric.min = 0xFFFFFFFF;
-
-	if (device_register(&unit->dev)) {
-		put_device(&unit->dev);
-		goto err_out;
-	}
-
-	if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs))
-		goto err_out_put;
-
-	write_lock_irq(&port->unit_list_lock);
-	list_add_tail(&unit->list, &port->unit_list);
-	write_unlock_irq(&port->unit_list_lock);
-
-	atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
-
-	return unit;
-
-err_out_put:
-	device_unregister(&unit->dev);
-err_out:
-	put_device(&port->dev);
-	return ERR_PTR(retval);
-}
-
 static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
 {
 	adapter->pool.erp_req =
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index ce1cc7a..0833c2b 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -46,8 +46,7 @@
 	if (!adapter)
 		return 0;
 
-	zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL,
-				       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
 				"ccresu2", NULL);
 	zfcp_erp_wait(adapter);
@@ -164,14 +163,7 @@
 	BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
 	adapter->req_no = 0;
 
-	zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL,
-				       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
-	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
-				"ccsonl2", NULL);
-	zfcp_erp_wait(adapter);
-
-	flush_work(&adapter->scan_work);
-
+	zfcp_ccw_activate(cdev);
 	zfcp_ccw_adapter_put(adapter);
 	return 0;
 }
@@ -224,9 +216,8 @@
 		break;
 	case CIO_OPER:
 		dev_info(&cdev->dev, "The FCP device is operational again\n");
-		zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL,
-					       ZFCP_STATUS_COMMON_RUNNING,
-					       ZFCP_SET);
+		zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_RUNNING);
 		zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
 					"ccnoti4", NULL);
 		break;
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c
index fcbd2b7..d692e229 100644
--- a/drivers/s390/scsi/zfcp_cfdc.c
+++ b/drivers/s390/scsi/zfcp_cfdc.c
@@ -2,9 +2,10 @@
  * zfcp device driver
  *
  * Userspace interface for accessing the
- * Access Control Lists / Control File Data Channel
+ * Access Control Lists / Control File Data Channel;
+ * handling of response code and states for ports and LUNs.
  *
- * Copyright IBM Corporation 2008, 2009
+ * Copyright IBM Corporation 2008, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -251,8 +252,9 @@
 	.open = nonseekable_open,
 	.unlocked_ioctl = zfcp_cfdc_dev_ioctl,
 #ifdef CONFIG_COMPAT
-	.compat_ioctl = zfcp_cfdc_dev_ioctl
+	.compat_ioctl = zfcp_cfdc_dev_ioctl,
 #endif
+	.llseek = no_llseek,
 };
 
 struct miscdevice zfcp_cfdc_misc = {
@@ -260,3 +262,184 @@
 	.name = "zfcp_cfdc",
 	.fops = &zfcp_cfdc_fops,
 };
+
+/**
+ * zfcp_cfdc_adapter_access_changed - Process change in adapter ACT
+ * @adapter: Adapter where the Access Control Table (ACT) changed
+ *
+ * After a change in the adapter ACT, check if access to any
+ * previously denied resources is now possible.
+ */
+void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter)
+{
+	unsigned long flags;
+	struct zfcp_port *port;
+	struct scsi_device *sdev;
+	struct zfcp_scsi_dev *zfcp_sdev;
+	int status;
+
+	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+		return;
+
+	read_lock_irqsave(&adapter->port_list_lock, flags);
+	list_for_each_entry(port, &adapter->port_list, list) {
+		status = atomic_read(&port->status);
+		if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
+		    (status & ZFCP_STATUS_COMMON_ACCESS_BOXED))
+			zfcp_erp_port_reopen(port,
+					     ZFCP_STATUS_COMMON_ERP_FAILED,
+					     "cfaac_1", NULL);
+	}
+	read_unlock_irqrestore(&adapter->port_list_lock, flags);
+
+	shost_for_each_device(sdev, port->adapter->scsi_host) {
+		zfcp_sdev = sdev_to_zfcp(sdev);
+		status = atomic_read(&zfcp_sdev->status);
+		if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
+		    (status & ZFCP_STATUS_COMMON_ACCESS_BOXED))
+			zfcp_erp_lun_reopen(sdev,
+					    ZFCP_STATUS_COMMON_ERP_FAILED,
+					    "cfaac_2", NULL);
+	}
+}
+
+static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
+{
+	u16 subtable = table >> 16;
+	u16 rule = table & 0xffff;
+	const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
+
+	if (subtable && subtable < ARRAY_SIZE(act_type))
+		dev_warn(&adapter->ccw_device->dev,
+			 "Access denied according to ACT rule type %s, "
+			 "rule %d\n", act_type[subtable], rule);
+}
+
+/**
+ * zfcp_cfdc_port_denied - Process "access denied" for port
+ * @port: The port where the acces has been denied
+ * @qual: The FSF status qualifier for the access denied FSF status
+ */
+void zfcp_cfdc_port_denied(struct zfcp_port *port,
+			   union fsf_status_qual *qual)
+{
+	dev_warn(&port->adapter->ccw_device->dev,
+		 "Access denied to port 0x%016Lx\n",
+		 (unsigned long long)port->wwpn);
+
+	zfcp_act_eval_err(port->adapter, qual->halfword[0]);
+	zfcp_act_eval_err(port->adapter, qual->halfword[1]);
+	zfcp_erp_set_port_status(port,
+				 ZFCP_STATUS_COMMON_ERP_FAILED |
+				 ZFCP_STATUS_COMMON_ACCESS_DENIED);
+}
+
+/**
+ * zfcp_cfdc_lun_denied - Process "access denied" for LUN
+ * @sdev: The SCSI device / LUN where the access has been denied
+ * @qual: The FSF status qualifier for the access denied FSF status
+ */
+void zfcp_cfdc_lun_denied(struct scsi_device *sdev,
+			  union fsf_status_qual *qual)
+{
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev,
+		 "Access denied to LUN 0x%016Lx on port 0x%016Lx\n",
+		 zfcp_scsi_dev_lun(sdev),
+		 (unsigned long long)zfcp_sdev->port->wwpn);
+	zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[0]);
+	zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[1]);
+	zfcp_erp_set_lun_status(sdev,
+				ZFCP_STATUS_COMMON_ERP_FAILED |
+				ZFCP_STATUS_COMMON_ACCESS_DENIED);
+
+	atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
+	atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
+}
+
+/**
+ * zfcp_cfdc_lun_shrng_vltn - Evaluate LUN sharing violation status
+ * @sdev: The LUN / SCSI device where sharing violation occurred
+ * @qual: The FSF status qualifier from the LUN sharing violation
+ */
+void zfcp_cfdc_lun_shrng_vltn(struct scsi_device *sdev,
+			      union fsf_status_qual *qual)
+{
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	if (qual->word[0])
+		dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev,
+			 "LUN 0x%Lx on port 0x%Lx is already in "
+			 "use by CSS%d, MIF Image ID %x\n",
+			 zfcp_scsi_dev_lun(sdev),
+			 (unsigned long long)zfcp_sdev->port->wwpn,
+			 qual->fsf_queue_designator.cssid,
+			 qual->fsf_queue_designator.hla);
+	else
+		zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->word[2]);
+
+	zfcp_erp_set_lun_status(sdev,
+				ZFCP_STATUS_COMMON_ERP_FAILED |
+				ZFCP_STATUS_COMMON_ACCESS_DENIED);
+	atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
+	atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
+}
+
+/**
+ * zfcp_cfdc_open_lun_eval - Eval access ctrl. status for successful "open lun"
+ * @sdev: The SCSI device / LUN where to evaluate the status
+ * @bottom: The qtcb bottom with the status from the "open lun"
+ *
+ * Returns: 0 if LUN is usable, -EACCES if the access control table
+ *          reports an unsupported configuration.
+ */
+int zfcp_cfdc_open_lun_eval(struct scsi_device *sdev,
+			    struct fsf_qtcb_bottom_support *bottom)
+{
+	int shared, rw;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
+
+	if ((adapter->connection_features & FSF_FEATURE_NPIV_MODE) ||
+	    !(adapter->adapter_features & FSF_FEATURE_LUN_SHARING) ||
+	    zfcp_ccw_priv_sch(adapter))
+		return 0;
+
+	shared = !(bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE);
+	rw = (bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
+
+	if (shared)
+		atomic_set_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
+
+	if (!rw) {
+		atomic_set_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
+		dev_info(&adapter->ccw_device->dev, "SCSI device at LUN "
+			 "0x%016Lx on port 0x%016Lx opened read-only\n",
+			 zfcp_scsi_dev_lun(sdev),
+			 (unsigned long long)zfcp_sdev->port->wwpn);
+	}
+
+	if (!shared && !rw) {
+		dev_err(&adapter->ccw_device->dev, "Exclusive read-only access "
+			"not supported (LUN 0x%016Lx, port 0x%016Lx)\n",
+			zfcp_scsi_dev_lun(sdev),
+			(unsigned long long)zfcp_sdev->port->wwpn);
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
+		zfcp_erp_lun_shutdown(sdev, 0, "fsouh_6", NULL);
+		return -EACCES;
+	}
+
+	if (shared && rw) {
+		dev_err(&adapter->ccw_device->dev,
+			"Shared read-write access not supported "
+			"(LUN 0x%016Lx, port 0x%016Lx)\n",
+			zfcp_scsi_dev_lun(sdev),
+			(unsigned long long)zfcp_sdev->port->wwpn);
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
+		zfcp_erp_lun_shutdown(sdev, 0, "fsosh_8", NULL);
+		return -EACCES;
+	}
+
+	return 0;
+}
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index a86117b..2cdd6b2 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -154,7 +154,6 @@
 		scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
 		if (scsi_cmnd) {
 			response->u.fcp.cmnd = (unsigned long)scsi_cmnd;
-			response->u.fcp.serial = scsi_cmnd->serial_number;
 			response->u.fcp.data_dir =
 				qtcb->bottom.io.data_direction;
 		}
@@ -330,7 +329,6 @@
 			break;
 		zfcp_dbf_out(p, "data_direction", "0x%04x", r->u.fcp.data_dir);
 		zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd);
-		zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial);
 		*p += sprintf(*p, "\n");
 		break;
 
@@ -482,7 +480,7 @@
 		zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.trigger.fcp_lun);
 		zfcp_dbf_out(&p, "adapter_status", "0x%08x", r->u.trigger.as);
 		zfcp_dbf_out(&p, "port_status", "0x%08x", r->u.trigger.ps);
-		zfcp_dbf_out(&p, "unit_status", "0x%08x", r->u.trigger.us);
+		zfcp_dbf_out(&p, "lun_status", "0x%08x", r->u.trigger.ls);
 		break;
 	case ZFCP_REC_DBF_ID_ACTION:
 		zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.action.action);
@@ -600,19 +598,20 @@
 }
 
 /**
- * zfcp_dbf_rec_unit - trace event for unit state change
+ * zfcp_dbf_rec_lun - trace event for LUN state change
  * @id: identifier for trigger of state change
  * @ref: additional reference (e.g. request)
- * @unit: unit
+ * @sdev: SCSI device
  */
-void zfcp_dbf_rec_unit(char *id, void *ref, struct zfcp_unit *unit)
+void zfcp_dbf_rec_lun(char *id, void *ref, struct scsi_device *sdev)
 {
-	struct zfcp_port *port = unit->port;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_port *port = zfcp_sdev->port;
 	struct zfcp_dbf *dbf = port->adapter->dbf;
 
-	zfcp_dbf_rec_target(id, ref, dbf, &unit->status,
-				  &unit->erp_counter, port->wwpn, port->d_id,
-				  unit->fcp_lun);
+	zfcp_dbf_rec_target(id, ref, dbf, &zfcp_sdev->status,
+			    &zfcp_sdev->erp_counter, port->wwpn, port->d_id,
+			    zfcp_scsi_dev_lun(sdev));
 }
 
 /**
@@ -624,11 +623,11 @@
  * @action: address of error recovery action struct
  * @adapter: adapter
  * @port: port
- * @unit: unit
+ * @sdev: SCSI device
  */
 void zfcp_dbf_rec_trigger(char *id2, void *ref, u8 want, u8 need, void *action,
 			  struct zfcp_adapter *adapter, struct zfcp_port *port,
-			  struct zfcp_unit *unit)
+			  struct scsi_device *sdev)
 {
 	struct zfcp_dbf *dbf = adapter->dbf;
 	struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
@@ -647,9 +646,10 @@
 		r->u.trigger.ps = atomic_read(&port->status);
 		r->u.trigger.wwpn = port->wwpn;
 	}
-	if (unit)
-		r->u.trigger.us = atomic_read(&unit->status);
-	r->u.trigger.fcp_lun = unit ? unit->fcp_lun : ZFCP_DBF_INVALID_LUN;
+	if (sdev)
+		r->u.trigger.ls = atomic_read(&sdev_to_zfcp(sdev)->status);
+	r->u.trigger.fcp_lun = sdev ? zfcp_scsi_dev_lun(sdev) :
+				      ZFCP_DBF_INVALID_LUN;
 	debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r));
 	spin_unlock_irqrestore(&dbf->rec_lock, flags);
 }
@@ -879,7 +879,6 @@
 				}
 				rec->scsi_result = scsi_cmnd->result;
 				rec->scsi_cmnd = (unsigned long)scsi_cmnd;
-				rec->scsi_serial = scsi_cmnd->serial_number;
 				memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
 					min((int)scsi_cmnd->cmd_len,
 						ZFCP_DBF_SCSI_OPCODE));
@@ -948,7 +947,6 @@
 	zfcp_dbf_out(&p, "scsi_lun", "0x%08x", r->scsi_lun);
 	zfcp_dbf_out(&p, "scsi_result", "0x%08x", r->scsi_result);
 	zfcp_dbf_out(&p, "scsi_cmnd", "0x%0Lx", r->scsi_cmnd);
-	zfcp_dbf_out(&p, "scsi_serial", "0x%016Lx", r->scsi_serial);
 	zfcp_dbf_outd(&p, "scsi_opcode", r->scsi_opcode, ZFCP_DBF_SCSI_OPCODE,
 		      0, ZFCP_DBF_SCSI_OPCODE);
 	zfcp_dbf_out(&p, "scsi_retries", "0x%02x", r->scsi_retries);
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 2bcc340..04081b1 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -60,7 +60,7 @@
 	u8 need;
 	u32 as;
 	u32 ps;
-	u32 us;
+	u32 ls;
 	u64 ref;
 	u64 action;
 	u64 wwpn;
@@ -110,7 +110,6 @@
 	union {
 		struct {
 			u64 cmnd;
-			u64 serial;
 			u32 data_dir;
 		} fcp;
 		struct {
@@ -206,7 +205,6 @@
 	u32 scsi_lun;
 	u32 scsi_result;
 	u64 scsi_cmnd;
-	u64 scsi_serial;
 #define ZFCP_DBF_SCSI_OPCODE	16
 	u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
 	u8 scsi_retries;
@@ -350,16 +348,16 @@
 /**
  * zfcp_dbf_scsi_devreset - trace event for Logical Unit or Target Reset
  * @tag: tag indicating success or failure of reset operation
+ * @scmnd: SCSI command which caused this error recovery
  * @flag: indicates type of reset (Target Reset, Logical Unit Reset)
- * @unit: unit that needs reset
- * @scsi_cmnd: SCSI command which caused this error recovery
  */
 static inline
-void zfcp_dbf_scsi_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
-			    struct scsi_cmnd *scsi_cmnd)
+void zfcp_dbf_scsi_devreset(const char *tag, struct scsi_cmnd *scmnd, u8 flag)
 {
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
+
 	zfcp_dbf_scsi(flag == FCP_TMF_TGT_RESET ? "trst" : "lrst", tag, 1,
-			    unit->port->adapter->dbf, scsi_cmnd, NULL, 0);
+		      zfcp_sdev->port->adapter->dbf, scmnd, NULL, 0);
 }
 
 #endif /* ZFCP_DBF_H */
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index e1c6b6e..9ae1d0a 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -85,8 +85,8 @@
 #define ZFCP_STATUS_PORT_LINK_TEST		0x00000002
 
 /* logical unit status */
-#define ZFCP_STATUS_UNIT_SHARED			0x00000004
-#define ZFCP_STATUS_UNIT_READONLY		0x00000008
+#define ZFCP_STATUS_LUN_SHARED			0x00000004
+#define ZFCP_STATUS_LUN_READONLY		0x00000008
 
 /* FSF request status (this does not have a common part) */
 #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT	0x00000002
@@ -118,7 +118,7 @@
 	int action;	              /* requested action code */
 	struct zfcp_adapter *adapter; /* device which should be recovered */
 	struct zfcp_port *port;
-	struct zfcp_unit *unit;
+	struct scsi_device *sdev;
 	u32		status;	      /* recovery status */
 	u32 step;	              /* active step of this erp action */
 	unsigned long		fsf_req_id;
@@ -219,21 +219,66 @@
 	unsigned int		starget_id;
 };
 
+/**
+ * struct zfcp_unit - LUN configured via zfcp sysfs
+ * @dev: struct device for sysfs representation and reference counting
+ * @list: entry in LUN/unit list per zfcp_port
+ * @port: reference to zfcp_port where this LUN is configured
+ * @fcp_lun: 64 bit LUN value
+ * @scsi_work: for running scsi_scan_target
+ *
+ * This is the representation of a LUN that has been configured for
+ * usage. The main data here is the 64 bit LUN value, data for
+ * running I/O and recovery is in struct zfcp_scsi_dev.
+ */
 struct zfcp_unit {
-	struct device          dev;
-	struct list_head       list;	       /* list of logical units */
-	struct zfcp_port       *port;	       /* remote port of unit */
-	atomic_t	       status;	       /* status of this logical unit */
-	u64		       fcp_lun;	       /* own FCP_LUN */
-	u32		       handle;	       /* handle assigned by FSF */
-        struct scsi_device     *device;        /* scsi device struct pointer */
-	struct zfcp_erp_action erp_action;     /* pending error recovery */
-        atomic_t               erp_counter;
-	struct zfcp_latencies	latencies;
+	struct device		dev;
+	struct list_head	list;
+	struct zfcp_port	*port;
+	u64			fcp_lun;
 	struct work_struct	scsi_work;
 };
 
 /**
+ * struct zfcp_scsi_dev - zfcp data per SCSI device
+ * @status: zfcp internal status flags
+ * @lun_handle: handle from "open lun" for issuing FSF requests
+ * @erp_action: zfcp erp data for opening and recovering this LUN
+ * @erp_counter: zfcp erp counter for this LUN
+ * @latencies: FSF channel and fabric latencies
+ * @port: zfcp_port where this LUN belongs to
+ */
+struct zfcp_scsi_dev {
+	atomic_t		status;
+	u32			lun_handle;
+	struct zfcp_erp_action	erp_action;
+	atomic_t		erp_counter;
+	struct zfcp_latencies	latencies;
+	struct zfcp_port	*port;
+};
+
+/**
+ * sdev_to_zfcp - Access zfcp LUN data for SCSI device
+ * @sdev: scsi_device where to get the zfcp_scsi_dev pointer
+ */
+static inline struct zfcp_scsi_dev *sdev_to_zfcp(struct scsi_device *sdev)
+{
+	return scsi_transport_device_data(sdev);
+}
+
+/**
+ * zfcp_scsi_dev_lun - Return SCSI device LUN as 64 bit FCP LUN
+ * @sdev: SCSI device where to get the LUN from
+ */
+static inline u64 zfcp_scsi_dev_lun(struct scsi_device *sdev)
+{
+	u64 fcp_lun;
+
+	int_to_scsilun(sdev->lun, (struct scsi_lun *)&fcp_lun);
+	return fcp_lun;
+}
+
+/**
  * struct zfcp_fsf_req - basic FSF request structure
  * @list: list of FSF requests
  * @req_id: unique request ID
@@ -249,7 +294,6 @@
  * @erp_action: reference to erp action if request issued on behalf of ERP
  * @pool: reference to memory pool if used for this request
  * @issued: time when request was send (STCK)
- * @unit: reference to unit if this request is a SCSI request
  * @handler: handler which should be called to process response
  */
 struct zfcp_fsf_req {
@@ -267,7 +311,6 @@
 	struct zfcp_erp_action	*erp_action;
 	mempool_t		*pool;
 	unsigned long long	issued;
-	struct zfcp_unit	*unit;
 	void			(*handler)(struct zfcp_fsf_req *);
 };
 
@@ -282,9 +325,4 @@
 	struct kmem_cache	*adisc_cache;
 };
 
-/********************** ZFCP SPECIFIC DEFINES ********************************/
-
-#define ZFCP_SET                0x00000100
-#define ZFCP_CLEAR              0x00000200
-
 #endif /* ZFCP_DEF_H */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 160b432..d37c733 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -21,6 +21,7 @@
 	ZFCP_STATUS_ERP_DISMISSING	= 0x00100000,
 	ZFCP_STATUS_ERP_DISMISSED	= 0x00200000,
 	ZFCP_STATUS_ERP_LOWMEM		= 0x00400000,
+	ZFCP_STATUS_ERP_NO_REF		= 0x00800000,
 };
 
 enum zfcp_erp_steps {
@@ -29,12 +30,12 @@
 	ZFCP_ERP_STEP_PHYS_PORT_CLOSING	= 0x0010,
 	ZFCP_ERP_STEP_PORT_CLOSING	= 0x0100,
 	ZFCP_ERP_STEP_PORT_OPENING	= 0x0800,
-	ZFCP_ERP_STEP_UNIT_CLOSING	= 0x1000,
-	ZFCP_ERP_STEP_UNIT_OPENING	= 0x2000,
+	ZFCP_ERP_STEP_LUN_CLOSING	= 0x1000,
+	ZFCP_ERP_STEP_LUN_OPENING	= 0x2000,
 };
 
 enum zfcp_erp_act_type {
-	ZFCP_ERP_ACTION_REOPEN_UNIT        = 1,
+	ZFCP_ERP_ACTION_REOPEN_LUN         = 1,
 	ZFCP_ERP_ACTION_REOPEN_PORT	   = 2,
 	ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3,
 	ZFCP_ERP_ACTION_REOPEN_ADAPTER     = 4,
@@ -56,9 +57,8 @@
 
 static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask)
 {
-	zfcp_erp_modify_adapter_status(adapter, "erablk1", NULL,
-				       ZFCP_STATUS_COMMON_UNBLOCKED | mask,
-				       ZFCP_CLEAR);
+	zfcp_erp_clear_adapter_status(adapter,
+				       ZFCP_STATUS_COMMON_UNBLOCKED | mask);
 }
 
 static int zfcp_erp_action_exists(struct zfcp_erp_action *act)
@@ -88,24 +88,24 @@
 		zfcp_erp_action_ready(act);
 }
 
-static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
+static void zfcp_erp_action_dismiss_lun(struct scsi_device *sdev)
 {
-	if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
-		zfcp_erp_action_dismiss(&unit->erp_action);
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
+		zfcp_erp_action_dismiss(&zfcp_sdev->erp_action);
 }
 
 static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
 {
-	struct zfcp_unit *unit;
+	struct scsi_device *sdev;
 
 	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
 		zfcp_erp_action_dismiss(&port->erp_action);
-	else {
-		read_lock(&port->unit_list_lock);
-		list_for_each_entry(unit, &port->unit_list, list)
-			zfcp_erp_action_dismiss_unit(unit);
-		read_unlock(&port->unit_list_lock);
-	}
+	else
+		shost_for_each_device(sdev, port->adapter->scsi_host)
+			if (sdev_to_zfcp(sdev)->port == port)
+				zfcp_erp_action_dismiss_lun(sdev);
 }
 
 static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
@@ -124,15 +124,17 @@
 
 static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
 				 struct zfcp_port *port,
-				 struct zfcp_unit *unit)
+				 struct scsi_device *sdev)
 {
 	int need = want;
-	int u_status, p_status, a_status;
+	int l_status, p_status, a_status;
+	struct zfcp_scsi_dev *zfcp_sdev;
 
 	switch (want) {
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		u_status = atomic_read(&unit->status);
-		if (u_status & ZFCP_STATUS_COMMON_ERP_INUSE)
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		zfcp_sdev = sdev_to_zfcp(sdev);
+		l_status = atomic_read(&zfcp_sdev->status);
+		if (l_status & ZFCP_STATUS_COMMON_ERP_INUSE)
 			return 0;
 		p_status = atomic_read(&port->status);
 		if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) ||
@@ -169,22 +171,26 @@
 	return need;
 }
 
-static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
+static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
 						  struct zfcp_adapter *adapter,
 						  struct zfcp_port *port,
-						  struct zfcp_unit *unit)
+						  struct scsi_device *sdev)
 {
 	struct zfcp_erp_action *erp_action;
-	u32 status = 0;
+	struct zfcp_scsi_dev *zfcp_sdev;
 
 	switch (need) {
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		if (!get_device(&unit->dev))
-			return NULL;
-		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status);
-		erp_action = &unit->erp_action;
-		if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING))
-			status = ZFCP_STATUS_ERP_CLOSE_ONLY;
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		zfcp_sdev = sdev_to_zfcp(sdev);
+		if (!(act_status & ZFCP_STATUS_ERP_NO_REF))
+			if (scsi_device_get(sdev))
+				return NULL;
+		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
+				&zfcp_sdev->status);
+		erp_action = &zfcp_sdev->erp_action;
+		if (!(atomic_read(&zfcp_sdev->status) &
+		      ZFCP_STATUS_COMMON_RUNNING))
+			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
@@ -195,7 +201,7 @@
 		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
 		erp_action = &port->erp_action;
 		if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
-			status = ZFCP_STATUS_ERP_CLOSE_ONLY;
+			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
@@ -205,7 +211,7 @@
 		erp_action = &adapter->erp_action;
 		if (!(atomic_read(&adapter->status) &
 		      ZFCP_STATUS_COMMON_RUNNING))
-			status = ZFCP_STATUS_ERP_CLOSE_ONLY;
+			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
 		break;
 
 	default:
@@ -215,16 +221,17 @@
 	memset(erp_action, 0, sizeof(struct zfcp_erp_action));
 	erp_action->adapter = adapter;
 	erp_action->port = port;
-	erp_action->unit = unit;
+	erp_action->sdev = sdev;
 	erp_action->action = need;
-	erp_action->status = status;
+	erp_action->status = act_status;
 
 	return erp_action;
 }
 
 static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
 				   struct zfcp_port *port,
-				   struct zfcp_unit *unit, char *id, void *ref)
+				   struct scsi_device *sdev,
+				   char *id, void *ref, u32 act_status)
 {
 	int retval = 1, need;
 	struct zfcp_erp_action *act = NULL;
@@ -232,21 +239,21 @@
 	if (!adapter->erp_thread)
 		return -EIO;
 
-	need = zfcp_erp_required_act(want, adapter, port, unit);
+	need = zfcp_erp_required_act(want, adapter, port, sdev);
 	if (!need)
 		goto out;
 
-	atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
-	act = zfcp_erp_setup_act(need, adapter, port, unit);
+	act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev);
 	if (!act)
 		goto out;
+	atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
 	++adapter->erp_total_count;
 	list_add_tail(&act->list, &adapter->erp_ready_head);
 	wake_up(&adapter->erp_ready_wq);
 	zfcp_dbf_rec_thread("eracte1", adapter->dbf);
 	retval = 0;
  out:
-	zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, unit);
+	zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, sdev);
 	return retval;
 }
 
@@ -258,11 +265,12 @@
 
 	/* ensure propagation of failed status to new devices */
 	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
-		zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
+		zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_ERP_FAILED);
 		return -EIO;
 	}
 	return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
-				       adapter, NULL, NULL, id, ref);
+				       adapter, NULL, NULL, id, ref, 0);
 }
 
 /**
@@ -282,10 +290,11 @@
 
 	write_lock_irqsave(&adapter->erp_lock, flags);
 	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
-		zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
+		zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_ERP_FAILED);
 	else
 		zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
-					NULL, NULL, id, ref);
+					NULL, NULL, id, ref, 0);
 	write_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
@@ -317,25 +326,10 @@
 	zfcp_erp_port_reopen(port, clear | flags, id, ref);
 }
 
-/**
- * zfcp_erp_unit_shutdown - Shutdown unit
- * @unit: Unit to shut down.
- * @clear: Status flags to clear.
- * @id: Id for debug trace event.
- * @ref: Reference for debug trace event.
- */
-void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, char *id,
-			    void *ref)
-{
-	int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
-	zfcp_erp_unit_reopen(unit, clear | flags, id, ref);
-}
-
 static void zfcp_erp_port_block(struct zfcp_port *port, int clear)
 {
-	zfcp_erp_modify_port_status(port, "erpblk1", NULL,
-				    ZFCP_STATUS_COMMON_UNBLOCKED | clear,
-				    ZFCP_CLEAR);
+	zfcp_erp_clear_port_status(port,
+				    ZFCP_STATUS_COMMON_UNBLOCKED | clear);
 }
 
 static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port,
@@ -348,7 +342,7 @@
 		return;
 
 	zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
-				port->adapter, port, NULL, id, ref);
+				port->adapter, port, NULL, id, ref, 0);
 }
 
 /**
@@ -376,12 +370,12 @@
 
 	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
 		/* ensure propagation of failed status to new devices */
-		zfcp_erp_port_failed(port, "erpreo1", NULL);
+		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
 		return -EIO;
 	}
 
 	return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
-				       port->adapter, port, NULL, id, ref);
+				       port->adapter, port, NULL, id, ref, 0);
 }
 
 /**
@@ -404,55 +398,90 @@
 	return retval;
 }
 
-static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
+static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask)
 {
-	zfcp_erp_modify_unit_status(unit, "erublk1", NULL,
-				    ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
-				    ZFCP_CLEAR);
+	zfcp_erp_clear_lun_status(sdev,
+				  ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask);
 }
 
-static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
-				  void *ref)
+static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
+				 void *ref, u32 act_status)
 {
-	struct zfcp_adapter *adapter = unit->port->adapter;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 
-	zfcp_erp_unit_block(unit, clear);
+	zfcp_erp_lun_block(sdev, clear);
 
-	if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
+	if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
 		return;
 
-	zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT,
-				adapter, unit->port, unit, id, ref);
+	zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter,
+				zfcp_sdev->port, sdev, id, ref, act_status);
 }
 
 /**
- * zfcp_erp_unit_reopen - initiate reopen of a unit
- * @unit: unit to be reopened
- * @clear_mask: specifies flags in unit status to be cleared
+ * zfcp_erp_lun_reopen - initiate reopen of a LUN
+ * @sdev: SCSI device / LUN to be reopened
+ * @clear_mask: specifies flags in LUN status to be cleared
  * Return: 0 on success, < 0 on error
  */
-void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
-			  void *ref)
+void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
+			 void *ref)
 {
 	unsigned long flags;
-	struct zfcp_port *port = unit->port;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_port *port = zfcp_sdev->port;
 	struct zfcp_adapter *adapter = port->adapter;
 
 	write_lock_irqsave(&adapter->erp_lock, flags);
-	_zfcp_erp_unit_reopen(unit, clear, id, ref);
+	_zfcp_erp_lun_reopen(sdev, clear, id, ref, 0);
 	write_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
+/**
+ * zfcp_erp_lun_shutdown - Shutdown LUN
+ * @sdev: SCSI device / LUN to shut down.
+ * @clear: Status flags to clear.
+ * @id: Id for debug trace event.
+ * @ref: Reference for debug trace event.
+ */
+void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id,
+			   void *ref)
+{
+	int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
+	zfcp_erp_lun_reopen(sdev, clear | flags, id, ref);
+}
+
+/**
+ * zfcp_erp_lun_shutdown_wait - Shutdown LUN and wait for erp completion
+ * @sdev: SCSI device / LUN to shut down.
+ * @id: Id for debug trace event.
+ *
+ * Do not acquire a reference for the LUN when creating the ERP
+ * action. It is safe, because this function waits for the ERP to
+ * complete first. This allows to shutdown the LUN, even when the SCSI
+ * device is in the state SDEV_DEL when scsi_device_get will fail.
+ */
+void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id)
+{
+	unsigned long flags;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_port *port = zfcp_sdev->port;
+	struct zfcp_adapter *adapter = port->adapter;
+	int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
+
+	write_lock_irqsave(&adapter->erp_lock, flags);
+	_zfcp_erp_lun_reopen(sdev, clear, id, NULL, ZFCP_STATUS_ERP_NO_REF);
+	write_unlock_irqrestore(&adapter->erp_lock, flags);
+
+	zfcp_erp_wait(adapter);
+}
+
 static int status_change_set(unsigned long mask, atomic_t *status)
 {
 	return (atomic_read(status) ^ mask) & mask;
 }
 
-static int status_change_clear(unsigned long mask, atomic_t *status)
-{
-	return atomic_read(status) & mask;
-}
-
 static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
 {
 	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
@@ -467,11 +496,13 @@
 	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
 }
 
-static void zfcp_erp_unit_unblock(struct zfcp_unit *unit)
+static void zfcp_erp_lun_unblock(struct scsi_device *sdev)
 {
-	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))
-		zfcp_dbf_rec_unit("eruubl1", NULL, unit);
-	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status))
+		zfcp_dbf_rec_lun("erlubl1", NULL, sdev);
+	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status);
 }
 
 static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
@@ -559,15 +590,14 @@
 	read_unlock(&adapter->port_list_lock);
 }
 
-static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear,
-				      char *id, void *ref)
+static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear,
+				     char *id, void *ref)
 {
-	struct zfcp_unit *unit;
+	struct scsi_device *sdev;
 
-	read_lock(&port->unit_list_lock);
-	list_for_each_entry(unit, &port->unit_list, list)
-		_zfcp_erp_unit_reopen(unit, clear, id, ref);
-	read_unlock(&port->unit_list_lock);
+	shost_for_each_device(sdev, port->adapter->scsi_host)
+		if (sdev_to_zfcp(sdev)->port == port)
+			_zfcp_erp_lun_reopen(sdev, clear, id, ref, 0);
 }
 
 static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
@@ -582,8 +612,8 @@
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
 		_zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL);
 		break;
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		_zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL);
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		_zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", NULL, 0);
 		break;
 	}
 }
@@ -598,7 +628,7 @@
 		_zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL);
 		break;
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
-		_zfcp_erp_unit_reopen_all(act->port, 0, "ersfs_3", NULL);
+		_zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3", NULL);
 		break;
 	}
 }
@@ -742,9 +772,8 @@
 	zfcp_fsf_req_dismiss_all(adapter);
 	adapter->fsf_req_seq_no = 0;
 	zfcp_fc_wka_ports_force_offline(adapter->gs);
-	/* all ports and units are closed */
-	zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
-				       ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
+	/* all ports and LUNs are closed */
+	zfcp_erp_clear_adapter_status(adapter, ZFCP_STATUS_COMMON_OPEN);
 
 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
 			  ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
@@ -861,7 +890,7 @@
 	struct zfcp_port *port = act->port;
 
 	if (port->wwpn != adapter->peer_wwpn) {
-		zfcp_erp_port_failed(port, "eroptp1", NULL);
+		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
 		return ZFCP_ERP_FAILED;
 	}
 	port->d_id = adapter->peer_d_id;
@@ -933,82 +962,87 @@
 	return zfcp_erp_port_strategy_open_common(erp_action);
 }
 
-static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
+static void zfcp_erp_lun_strategy_clearstati(struct scsi_device *sdev)
 {
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
 	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
-			  ZFCP_STATUS_UNIT_SHARED |
-			  ZFCP_STATUS_UNIT_READONLY,
-			  &unit->status);
+			  ZFCP_STATUS_LUN_SHARED | ZFCP_STATUS_LUN_READONLY,
+			  &zfcp_sdev->status);
 }
 
-static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
+static int zfcp_erp_lun_strategy_close(struct zfcp_erp_action *erp_action)
 {
-	int retval = zfcp_fsf_close_unit(erp_action);
+	int retval = zfcp_fsf_close_lun(erp_action);
 	if (retval == -ENOMEM)
 		return ZFCP_ERP_NOMEM;
-	erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING;
+	erp_action->step = ZFCP_ERP_STEP_LUN_CLOSING;
 	if (retval)
 		return ZFCP_ERP_FAILED;
 	return ZFCP_ERP_CONTINUES;
 }
 
-static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
+static int zfcp_erp_lun_strategy_open(struct zfcp_erp_action *erp_action)
 {
-	int retval = zfcp_fsf_open_unit(erp_action);
+	int retval = zfcp_fsf_open_lun(erp_action);
 	if (retval == -ENOMEM)
 		return ZFCP_ERP_NOMEM;
-	erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING;
+	erp_action->step = ZFCP_ERP_STEP_LUN_OPENING;
 	if (retval)
 		return  ZFCP_ERP_FAILED;
 	return ZFCP_ERP_CONTINUES;
 }
 
-static int zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
+static int zfcp_erp_lun_strategy(struct zfcp_erp_action *erp_action)
 {
-	struct zfcp_unit *unit = erp_action->unit;
+	struct scsi_device *sdev = erp_action->sdev;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 
 	switch (erp_action->step) {
 	case ZFCP_ERP_STEP_UNINITIALIZED:
-		zfcp_erp_unit_strategy_clearstati(unit);
-		if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
-			return zfcp_erp_unit_strategy_close(erp_action);
+		zfcp_erp_lun_strategy_clearstati(sdev);
+		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
+			return zfcp_erp_lun_strategy_close(erp_action);
 		/* already closed, fall through */
-	case ZFCP_ERP_STEP_UNIT_CLOSING:
-		if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
+	case ZFCP_ERP_STEP_LUN_CLOSING:
+		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
 			return ZFCP_ERP_FAILED;
 		if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
 			return ZFCP_ERP_EXIT;
-		return zfcp_erp_unit_strategy_open(erp_action);
+		return zfcp_erp_lun_strategy_open(erp_action);
 
-	case ZFCP_ERP_STEP_UNIT_OPENING:
-		if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
+	case ZFCP_ERP_STEP_LUN_OPENING:
+		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
 			return ZFCP_ERP_SUCCEEDED;
 	}
 	return ZFCP_ERP_FAILED;
 }
 
-static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
+static int zfcp_erp_strategy_check_lun(struct scsi_device *sdev, int result)
 {
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
 	switch (result) {
 	case ZFCP_ERP_SUCCEEDED :
-		atomic_set(&unit->erp_counter, 0);
-		zfcp_erp_unit_unblock(unit);
+		atomic_set(&zfcp_sdev->erp_counter, 0);
+		zfcp_erp_lun_unblock(sdev);
 		break;
 	case ZFCP_ERP_FAILED :
-		atomic_inc(&unit->erp_counter);
-		if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) {
-			dev_err(&unit->port->adapter->ccw_device->dev,
-				"ERP failed for unit 0x%016Lx on "
+		atomic_inc(&zfcp_sdev->erp_counter);
+		if (atomic_read(&zfcp_sdev->erp_counter) > ZFCP_MAX_ERPS) {
+			dev_err(&zfcp_sdev->port->adapter->ccw_device->dev,
+				"ERP failed for LUN 0x%016Lx on "
 				"port 0x%016Lx\n",
-				(unsigned long long)unit->fcp_lun,
-				(unsigned long long)unit->port->wwpn);
-			zfcp_erp_unit_failed(unit, "erusck1", NULL);
+				(unsigned long long)zfcp_scsi_dev_lun(sdev),
+				(unsigned long long)zfcp_sdev->port->wwpn);
+			zfcp_erp_set_lun_status(sdev,
+						ZFCP_STATUS_COMMON_ERP_FAILED);
 		}
 		break;
 	}
 
-	if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
-		zfcp_erp_unit_block(unit, 0);
+	if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
+		zfcp_erp_lun_block(sdev, 0);
 		result = ZFCP_ERP_EXIT;
 	}
 	return result;
@@ -1032,7 +1066,8 @@
 			dev_err(&port->adapter->ccw_device->dev,
 				"ERP failed for remote port 0x%016Lx\n",
 				(unsigned long long)port->wwpn);
-			zfcp_erp_port_failed(port, "erpsck1", NULL);
+			zfcp_erp_set_port_status(port,
+					 ZFCP_STATUS_COMMON_ERP_FAILED);
 		}
 		break;
 	}
@@ -1059,7 +1094,8 @@
 			dev_err(&adapter->ccw_device->dev,
 				"ERP cannot recover an error "
 				"on the FCP device\n");
-			zfcp_erp_adapter_failed(adapter, "erasck1", NULL);
+			zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_ERP_FAILED);
 		}
 		break;
 	}
@@ -1076,12 +1112,12 @@
 {
 	struct zfcp_adapter *adapter = erp_action->adapter;
 	struct zfcp_port *port = erp_action->port;
-	struct zfcp_unit *unit = erp_action->unit;
+	struct scsi_device *sdev = erp_action->sdev;
 
 	switch (erp_action->action) {
 
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		result = zfcp_erp_strategy_check_unit(unit, result);
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		result = zfcp_erp_strategy_check_lun(sdev, result);
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
@@ -1116,7 +1152,8 @@
 	int action = act->action;
 	struct zfcp_adapter *adapter = act->adapter;
 	struct zfcp_port *port = act->port;
-	struct zfcp_unit *unit = act->unit;
+	struct scsi_device *sdev = act->sdev;
+	struct zfcp_scsi_dev *zfcp_sdev;
 	u32 erp_status = act->status;
 
 	switch (action) {
@@ -1139,11 +1176,12 @@
 		}
 		break;
 
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		if (zfcp_erp_strat_change_det(&unit->status, erp_status)) {
-			_zfcp_erp_unit_reopen(unit,
-					      ZFCP_STATUS_COMMON_ERP_FAILED,
-					      "ersscg3", NULL);
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		zfcp_sdev = sdev_to_zfcp(sdev);
+		if (zfcp_erp_strat_change_det(&zfcp_sdev->status, erp_status)) {
+			_zfcp_erp_lun_reopen(sdev,
+					     ZFCP_STATUS_COMMON_ERP_FAILED,
+					     "ersscg3", NULL, 0);
 			return ZFCP_ERP_EXIT;
 		}
 		break;
@@ -1154,6 +1192,7 @@
 static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
 {
 	struct zfcp_adapter *adapter = erp_action->adapter;
+	struct zfcp_scsi_dev *zfcp_sdev;
 
 	adapter->erp_total_count--;
 	if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
@@ -1165,9 +1204,10 @@
 	zfcp_dbf_rec_action("eractd1", erp_action);
 
 	switch (erp_action->action) {
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
 		atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
-				  &erp_action->unit->status);
+				  &zfcp_sdev->status);
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
@@ -1187,11 +1227,12 @@
 {
 	struct zfcp_adapter *adapter = act->adapter;
 	struct zfcp_port *port = act->port;
-	struct zfcp_unit *unit = act->unit;
+	struct scsi_device *sdev = act->sdev;
 
 	switch (act->action) {
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		put_device(&unit->dev);
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
+			scsi_device_put(sdev);
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
@@ -1222,8 +1263,8 @@
 		return zfcp_erp_port_forced_strategy(erp_action);
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
 		return zfcp_erp_port_strategy(erp_action);
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		return zfcp_erp_unit_strategy(erp_action);
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		return zfcp_erp_lun_strategy(erp_action);
 	}
 	return ZFCP_ERP_FAILED;
 }
@@ -1376,42 +1417,6 @@
 }
 
 /**
- * zfcp_erp_adapter_failed - Set adapter status to failed.
- * @adapter: Failed adapter.
- * @id: Event id for debug trace.
- * @ref: Reference for debug trace.
- */
-void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, char *id, void *ref)
-{
-	zfcp_erp_modify_adapter_status(adapter, id, ref,
-				       ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-}
-
-/**
- * zfcp_erp_port_failed - Set port status to failed.
- * @port: Failed port.
- * @id: Event id for debug trace.
- * @ref: Reference for debug trace.
- */
-void zfcp_erp_port_failed(struct zfcp_port *port, char *id, void *ref)
-{
-	zfcp_erp_modify_port_status(port, id, ref,
-				    ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-}
-
-/**
- * zfcp_erp_unit_failed - Set unit status to failed.
- * @unit: Failed unit.
- * @id: Event id for debug trace.
- * @ref: Reference for debug trace.
- */
-void zfcp_erp_unit_failed(struct zfcp_unit *unit, char *id, void *ref)
-{
-	zfcp_erp_modify_unit_status(unit, id, ref,
-				    ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-}
-
-/**
  * zfcp_erp_wait - wait for completion of error recovery on an adapter
  * @adapter: adapter for which to wait for completion of its error recovery
  */
@@ -1423,210 +1428,148 @@
 }
 
 /**
- * zfcp_erp_modify_adapter_status - change adapter status bits
+ * zfcp_erp_set_adapter_status - set adapter status bits
  * @adapter: adapter to change the status
- * @id: id for the debug trace
- * @ref: reference for the debug trace
  * @mask: status bits to change
- * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
  *
- * Changes in common status bits are propagated to attached ports and units.
+ * Changes in common status bits are propagated to attached ports and LUNs.
  */
-void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
-				    void *ref, u32 mask, int set_or_clear)
+void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask)
 {
 	struct zfcp_port *port;
+	struct scsi_device *sdev;
 	unsigned long flags;
 	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
 
-	if (set_or_clear == ZFCP_SET) {
-		if (status_change_set(mask, &adapter->status))
-			zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
-		atomic_set_mask(mask, &adapter->status);
-	} else {
-		if (status_change_clear(mask, &adapter->status))
-			zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
-		atomic_clear_mask(mask, &adapter->status);
-		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
-			atomic_set(&adapter->erp_counter, 0);
-	}
+	atomic_set_mask(mask, &adapter->status);
 
-	if (common_mask) {
-		read_lock_irqsave(&adapter->port_list_lock, flags);
-		list_for_each_entry(port, &adapter->port_list, list)
-			zfcp_erp_modify_port_status(port, id, ref, common_mask,
-						    set_or_clear);
-		read_unlock_irqrestore(&adapter->port_list_lock, flags);
-	}
-}
-
-/**
- * zfcp_erp_modify_port_status - change port status bits
- * @port: port to change the status bits
- * @id: id for the debug trace
- * @ref: reference for the debug trace
- * @mask: status bits to change
- * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
- *
- * Changes in common status bits are propagated to attached units.
- */
-void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
-				 u32 mask, int set_or_clear)
-{
-	struct zfcp_unit *unit;
-	unsigned long flags;
-	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
-
-	if (set_or_clear == ZFCP_SET) {
-		if (status_change_set(mask, &port->status))
-			zfcp_dbf_rec_port(id, ref, port);
-		atomic_set_mask(mask, &port->status);
-	} else {
-		if (status_change_clear(mask, &port->status))
-			zfcp_dbf_rec_port(id, ref, port);
-		atomic_clear_mask(mask, &port->status);
-		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
-			atomic_set(&port->erp_counter, 0);
-	}
-
-	if (common_mask) {
-		read_lock_irqsave(&port->unit_list_lock, flags);
-		list_for_each_entry(unit, &port->unit_list, list)
-			zfcp_erp_modify_unit_status(unit, id, ref, common_mask,
-						    set_or_clear);
-		read_unlock_irqrestore(&port->unit_list_lock, flags);
-	}
-}
-
-/**
- * zfcp_erp_modify_unit_status - change unit status bits
- * @unit: unit to change the status bits
- * @id: id for the debug trace
- * @ref: reference for the debug trace
- * @mask: status bits to change
- * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
- */
-void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref,
-				 u32 mask, int set_or_clear)
-{
-	if (set_or_clear == ZFCP_SET) {
-		if (status_change_set(mask, &unit->status))
-			zfcp_dbf_rec_unit(id, ref, unit);
-		atomic_set_mask(mask, &unit->status);
-	} else {
-		if (status_change_clear(mask, &unit->status))
-			zfcp_dbf_rec_unit(id, ref, unit);
-		atomic_clear_mask(mask, &unit->status);
-		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
-			atomic_set(&unit->erp_counter, 0);
-		}
-	}
-}
-
-/**
- * zfcp_erp_port_boxed - Mark port as "boxed" and start ERP
- * @port: The "boxed" port.
- * @id: The debug trace id.
- * @id: Reference for the debug trace.
- */
-void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref)
-{
-	zfcp_erp_modify_port_status(port, id, ref,
-				    ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
-	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
-}
-
-/**
- * zfcp_erp_unit_boxed - Mark unit as "boxed" and start ERP
- * @port: The "boxed" unit.
- * @id: The debug trace id.
- * @id: Reference for the debug trace.
- */
-void zfcp_erp_unit_boxed(struct zfcp_unit *unit, char *id, void *ref)
-{
-	zfcp_erp_modify_unit_status(unit, id, ref,
-				    ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
-	zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
-}
-
-/**
- * zfcp_erp_port_access_denied - Adapter denied access to port.
- * @port: port where access has been denied
- * @id: id for debug trace
- * @ref: reference for debug trace
- *
- * Since the adapter has denied access, stop using the port and the
- * attached units.
- */
-void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref)
-{
-	zfcp_erp_modify_port_status(port, id, ref,
-				    ZFCP_STATUS_COMMON_ERP_FAILED |
-				    ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
-}
-
-/**
- * zfcp_erp_unit_access_denied - Adapter denied access to unit.
- * @unit: unit where access has been denied
- * @id: id for debug trace
- * @ref: reference for debug trace
- *
- * Since the adapter has denied access, stop using the unit.
- */
-void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, char *id, void *ref)
-{
-	zfcp_erp_modify_unit_status(unit, id, ref,
-				    ZFCP_STATUS_COMMON_ERP_FAILED |
-				    ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
-}
-
-static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, char *id,
-					 void *ref)
-{
-	int status = atomic_read(&unit->status);
-	if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
-			ZFCP_STATUS_COMMON_ACCESS_BOXED)))
-		return;
-
-	zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
-}
-
-static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id,
-					 void *ref)
-{
-	struct zfcp_unit *unit;
-	unsigned long flags;
-	int status = atomic_read(&port->status);
-
-	if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
-			ZFCP_STATUS_COMMON_ACCESS_BOXED))) {
-		read_lock_irqsave(&port->unit_list_lock, flags);
-		list_for_each_entry(unit, &port->unit_list, list)
-				    zfcp_erp_unit_access_changed(unit, id, ref);
-		read_unlock_irqrestore(&port->unit_list_lock, flags);
-		return;
-	}
-
-	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
-}
-
-/**
- * zfcp_erp_adapter_access_changed - Process change in adapter ACT
- * @adapter: Adapter where the Access Control Table (ACT) changed
- * @id: Id for debug trace
- * @ref: Reference for debug trace
- */
-void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id,
-				     void *ref)
-{
-	unsigned long flags;
-	struct zfcp_port *port;
-
-	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+	if (!common_mask)
 		return;
 
 	read_lock_irqsave(&adapter->port_list_lock, flags);
 	list_for_each_entry(port, &adapter->port_list, list)
-		zfcp_erp_port_access_changed(port, id, ref);
+		atomic_set_mask(common_mask, &port->status);
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
+
+	shost_for_each_device(sdev, adapter->scsi_host)
+		atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status);
 }
+
+/**
+ * zfcp_erp_clear_adapter_status - clear adapter status bits
+ * @adapter: adapter to change the status
+ * @mask: status bits to change
+ *
+ * Changes in common status bits are propagated to attached ports and LUNs.
+ */
+void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask)
+{
+	struct zfcp_port *port;
+	struct scsi_device *sdev;
+	unsigned long flags;
+	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+	u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
+
+	atomic_clear_mask(mask, &adapter->status);
+
+	if (!common_mask)
+		return;
+
+	if (clear_counter)
+		atomic_set(&adapter->erp_counter, 0);
+
+	read_lock_irqsave(&adapter->port_list_lock, flags);
+	list_for_each_entry(port, &adapter->port_list, list) {
+		atomic_clear_mask(common_mask, &port->status);
+		if (clear_counter)
+			atomic_set(&port->erp_counter, 0);
+	}
+	read_unlock_irqrestore(&adapter->port_list_lock, flags);
+
+	shost_for_each_device(sdev, adapter->scsi_host) {
+		atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status);
+		if (clear_counter)
+			atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
+	}
+}
+
+/**
+ * zfcp_erp_set_port_status - set port status bits
+ * @port: port to change the status
+ * @mask: status bits to change
+ *
+ * Changes in common status bits are propagated to attached LUNs.
+ */
+void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask)
+{
+	struct scsi_device *sdev;
+	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+
+	atomic_set_mask(mask, &port->status);
+
+	if (!common_mask)
+		return;
+
+	shost_for_each_device(sdev, port->adapter->scsi_host)
+		if (sdev_to_zfcp(sdev)->port == port)
+			atomic_set_mask(common_mask,
+					&sdev_to_zfcp(sdev)->status);
+}
+
+/**
+ * zfcp_erp_clear_port_status - clear port status bits
+ * @port: adapter to change the status
+ * @mask: status bits to change
+ *
+ * Changes in common status bits are propagated to attached LUNs.
+ */
+void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
+{
+	struct scsi_device *sdev;
+	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+	u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
+
+	atomic_clear_mask(mask, &port->status);
+
+	if (!common_mask)
+		return;
+
+	if (clear_counter)
+		atomic_set(&port->erp_counter, 0);
+
+	shost_for_each_device(sdev, port->adapter->scsi_host)
+		if (sdev_to_zfcp(sdev)->port == port) {
+			atomic_clear_mask(common_mask,
+					  &sdev_to_zfcp(sdev)->status);
+			if (clear_counter)
+				atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
+		}
+}
+
+/**
+ * zfcp_erp_set_lun_status - set lun status bits
+ * @sdev: SCSI device / lun to set the status bits
+ * @mask: status bits to change
+ */
+void zfcp_erp_set_lun_status(struct scsi_device *sdev, u32 mask)
+{
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	atomic_set_mask(mask, &zfcp_sdev->status);
+}
+
+/**
+ * zfcp_erp_clear_lun_status - clear lun status bits
+ * @sdev: SCSi device / lun to clear the status bits
+ * @mask: status bits to change
+ */
+void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask)
+{
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	atomic_clear_mask(mask, &zfcp_sdev->status);
+
+	if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
+		atomic_set(&zfcp_sdev->erp_counter, 0);
+}
+
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 3b93239..bf8f3e5 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -15,12 +15,10 @@
 #include "zfcp_fc.h"
 
 /* zfcp_aux.c */
-extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64);
 extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64);
 extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *);
 extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32,
 					   u32);
-extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64);
 extern void zfcp_sg_free_table(struct scatterlist *, int);
 extern int zfcp_sg_setup_table(struct scatterlist *, int);
 extern void zfcp_device_unregister(struct device *,
@@ -36,6 +34,14 @@
 
 /* zfcp_cfdc.c */
 extern struct miscdevice zfcp_cfdc_misc;
+extern void zfcp_cfdc_port_denied(struct zfcp_port *, union fsf_status_qual *);
+extern void zfcp_cfdc_lun_denied(struct scsi_device *, union fsf_status_qual *);
+extern void zfcp_cfdc_lun_shrng_vltn(struct scsi_device *,
+				     union fsf_status_qual *);
+extern int zfcp_cfdc_open_lun_eval(struct scsi_device *,
+				   struct fsf_qtcb_bottom_support *);
+extern void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *);
+
 
 /* zfcp_dbf.c */
 extern int zfcp_dbf_adapter_register(struct zfcp_adapter *);
@@ -44,10 +50,10 @@
 extern void zfcp_dbf_rec_thread_lock(char *, struct zfcp_dbf *);
 extern void zfcp_dbf_rec_adapter(char *, void *, struct zfcp_dbf *);
 extern void zfcp_dbf_rec_port(char *, void *, struct zfcp_port *);
-extern void zfcp_dbf_rec_unit(char *, void *, struct zfcp_unit *);
+extern void zfcp_dbf_rec_lun(char *, void *, struct scsi_device *);
 extern void zfcp_dbf_rec_trigger(char *, void *, u8, u8, void *,
 				 struct zfcp_adapter *, struct zfcp_port *,
-				 struct zfcp_unit *);
+				 struct scsi_device *);
 extern void zfcp_dbf_rec_action(char *, struct zfcp_erp_action *);
 extern void _zfcp_dbf_hba_fsf_response(const char *, int, struct zfcp_fsf_req *,
 				       struct zfcp_dbf *);
@@ -65,34 +71,26 @@
 			   unsigned long);
 
 /* zfcp_erp.c */
-extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, char *,
-					   void *, u32, int);
+extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32);
+extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32);
 extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *, void *);
 extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *,
 				      void *);
-extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, char *, void *);
-extern void zfcp_erp_modify_port_status(struct zfcp_port *, char *, void *, u32,
-					int);
+extern void zfcp_erp_set_port_status(struct zfcp_port *, u32);
+extern void zfcp_erp_clear_port_status(struct zfcp_port *, u32);
 extern int  zfcp_erp_port_reopen(struct zfcp_port *, int, char *, void *);
 extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *, void *);
 extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *,
 					void *);
-extern void zfcp_erp_port_failed(struct zfcp_port *, char *, void *);
-extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, char *, void *, u32,
-					int);
-extern void zfcp_erp_unit_reopen(struct zfcp_unit *, int, char *, void *);
-extern void zfcp_erp_unit_shutdown(struct zfcp_unit *, int, char *, void *);
-extern void zfcp_erp_unit_failed(struct zfcp_unit *, char *, void *);
+extern void zfcp_erp_set_lun_status(struct scsi_device *, u32);
+extern void zfcp_erp_clear_lun_status(struct scsi_device *, u32);
+extern void zfcp_erp_lun_reopen(struct scsi_device *, int, char *, void *);
+extern void zfcp_erp_lun_shutdown(struct scsi_device *, int, char *, void *);
+extern void zfcp_erp_lun_shutdown_wait(struct scsi_device *, char *);
 extern int  zfcp_erp_thread_setup(struct zfcp_adapter *);
 extern void zfcp_erp_thread_kill(struct zfcp_adapter *);
 extern void zfcp_erp_wait(struct zfcp_adapter *);
 extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long);
-extern void zfcp_erp_port_boxed(struct zfcp_port *, char *, void *);
-extern void zfcp_erp_unit_boxed(struct zfcp_unit *, char *, void *);
-extern void zfcp_erp_port_access_denied(struct zfcp_port *, char *, void *);
-extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, char *, void *);
-extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, char *,
-					    void *);
 extern void zfcp_erp_timeout_handler(unsigned long);
 
 /* zfcp_fc.c */
@@ -118,8 +116,8 @@
 extern int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *);
 extern int zfcp_fsf_close_port(struct zfcp_erp_action *);
 extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *);
-extern int zfcp_fsf_open_unit(struct zfcp_erp_action *);
-extern int zfcp_fsf_close_unit(struct zfcp_erp_action *);
+extern int zfcp_fsf_open_lun(struct zfcp_erp_action *);
+extern int zfcp_fsf_close_lun(struct zfcp_erp_action *);
 extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
 extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *,
 					      struct fsf_qtcb_bottom_config *);
@@ -135,12 +133,10 @@
 			    mempool_t *, unsigned int);
 extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32,
 			     struct zfcp_fsf_ct_els *, unsigned int);
-extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *,
-					  struct scsi_cmnd *);
+extern int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *);
 extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
-extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *, u8);
-extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long,
-						       struct zfcp_unit *);
+extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *, u8);
+extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *);
 extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int);
 
 /* zfcp_qdio.c */
@@ -163,8 +159,6 @@
 extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
 extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
 extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
-extern void zfcp_scsi_scan(struct zfcp_unit *);
-extern void zfcp_scsi_scan_work(struct work_struct *);
 extern void zfcp_scsi_set_prot(struct zfcp_adapter *);
 extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int);
 
@@ -175,4 +169,13 @@
 extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
 extern struct device_attribute *zfcp_sysfs_shost_attrs[];
 
+/* zfcp_unit.c */
+extern int zfcp_unit_add(struct zfcp_port *, u64);
+extern int zfcp_unit_remove(struct zfcp_port *, u64);
+extern struct zfcp_unit *zfcp_unit_find(struct zfcp_port *, u64);
+extern struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit);
+extern void zfcp_unit_scsi_scan(struct zfcp_unit *);
+extern void zfcp_unit_queue_scsi_scan(struct zfcp_port *);
+extern unsigned int zfcp_unit_sdev_status(struct zfcp_unit *);
+
 #endif	/* ZFCP_EXT_H */
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 6f3ed2b..86fd905 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -365,7 +365,7 @@
 	}
 
 	if (!port->d_id) {
-		zfcp_erp_port_failed(port, "fcgpn_2", NULL);
+		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
 		goto out;
 	}
 
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 9d1d7d1..beaf091 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -61,45 +61,6 @@
 	[FSF_QTCB_UPLOAD_CONTROL_FILE] =  FSF_SUPPORT_COMMAND
 };
 
-static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
-{
-	u16 subtable = table >> 16;
-	u16 rule = table & 0xffff;
-	const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
-
-	if (subtable && subtable < ARRAY_SIZE(act_type))
-		dev_warn(&adapter->ccw_device->dev,
-			 "Access denied according to ACT rule type %s, "
-			 "rule %d\n", act_type[subtable], rule);
-}
-
-static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
-					struct zfcp_port *port)
-{
-	struct fsf_qtcb_header *header = &req->qtcb->header;
-	dev_warn(&req->adapter->ccw_device->dev,
-		 "Access denied to port 0x%016Lx\n",
-		 (unsigned long long)port->wwpn);
-	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
-	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
-	zfcp_erp_port_access_denied(port, "fspad_1", req);
-	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-}
-
-static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
-					struct zfcp_unit *unit)
-{
-	struct fsf_qtcb_header *header = &req->qtcb->header;
-	dev_warn(&req->adapter->ccw_device->dev,
-		 "Access denied to unit 0x%016Lx on port 0x%016Lx\n",
-		 (unsigned long long)unit->fcp_lun,
-		 (unsigned long long)unit->port->wwpn);
-	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
-	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
-	zfcp_erp_unit_access_denied(unit, "fsuad_1", req);
-	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-}
-
 static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
 {
 	dev_err(&req->adapter->ccw_device->dev, "FCP device not "
@@ -143,7 +104,7 @@
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 }
 
-static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
+static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req,
 					 struct fsf_link_down_info *link_down)
 {
 	struct zfcp_adapter *adapter = req->adapter;
@@ -223,7 +184,7 @@
 			 "the FC fabric is down\n");
 	}
 out:
-	zfcp_erp_adapter_failed(adapter, id, req);
+	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
 }
 
 static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
@@ -234,13 +195,13 @@
 
 	switch (sr_buf->status_subtype) {
 	case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
-		zfcp_fsf_link_down_info_eval(req, "fssrld1", ldi);
+		zfcp_fsf_link_down_info_eval(req, ldi);
 		break;
 	case FSF_STATUS_READ_SUB_FDISC_FAILED:
-		zfcp_fsf_link_down_info_eval(req, "fssrld2", ldi);
+		zfcp_fsf_link_down_info_eval(req, ldi);
 		break;
 	case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
-		zfcp_fsf_link_down_info_eval(req, "fssrld3", NULL);
+		zfcp_fsf_link_down_info_eval(req, NULL);
 	};
 }
 
@@ -281,9 +242,8 @@
 		dev_info(&adapter->ccw_device->dev,
 			 "The local link has been restored\n");
 		/* All ports should be marked as ready to run again */
-		zfcp_erp_modify_adapter_status(adapter, "fssrh_1", NULL,
-					       ZFCP_STATUS_COMMON_RUNNING,
-					       ZFCP_SET);
+		zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_RUNNING);
 		zfcp_erp_adapter_reopen(adapter,
 					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
 					ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -293,13 +253,12 @@
 		break;
 	case FSF_STATUS_READ_NOTIFICATION_LOST:
 		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
-			zfcp_erp_adapter_access_changed(adapter, "fssrh_3",
-							req);
+			zfcp_cfdc_adapter_access_changed(adapter);
 		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
 			queue_work(adapter->work_queue, &adapter->scan_work);
 		break;
 	case FSF_STATUS_READ_CFDC_UPDATED:
-		zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req);
+		zfcp_cfdc_adapter_access_changed(adapter);
 		break;
 	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
 		adapter->adapter_features = sr_buf->payload.word[0];
@@ -399,16 +358,14 @@
 		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req);
 		break;
 	case FSF_PROT_LINK_DOWN:
-		zfcp_fsf_link_down_info_eval(req, "fspse_5",
-					     &psq->link_down_info);
+		zfcp_fsf_link_down_info_eval(req, &psq->link_down_info);
 		/* go through reopen to flush pending requests */
 		zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req);
 		break;
 	case FSF_PROT_REEST_QUEUE:
 		/* All ports should be marked as ready to run again */
-		zfcp_erp_modify_adapter_status(adapter, "fspse_7", NULL,
-					       ZFCP_STATUS_COMMON_RUNNING,
-					       ZFCP_SET);
+		zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_RUNNING);
 		zfcp_erp_adapter_reopen(adapter,
 					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
 					ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -578,7 +535,7 @@
 		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
 				&adapter->status);
 
-		zfcp_fsf_link_down_info_eval(req, "fsecdh2",
+		zfcp_fsf_link_down_info_eval(req,
 			&qtcb->header.fsf_status_qual.link_down_info);
 		break;
 	default:
@@ -644,7 +601,7 @@
 		break;
 	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
 		zfcp_fsf_exchange_port_evaluate(req);
-		zfcp_fsf_link_down_info_eval(req, "fsepdh1",
+		zfcp_fsf_link_down_info_eval(req,
 			&qtcb->header.fsf_status_qual.link_down_info);
 		break;
 	}
@@ -771,7 +728,7 @@
 	struct fsf_status_read_buffer *sr_buf;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -805,13 +762,14 @@
 	zfcp_fsf_req_free(req);
 	zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
 static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
 {
-	struct zfcp_unit *unit = req->data;
+	struct scsi_device *sdev = req->data;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 	union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
@@ -820,14 +778,15 @@
 	switch (req->qtcb->header.fsf_status) {
 	case FSF_PORT_HANDLE_NOT_VALID:
 		if (fsq->word[0] == fsq->word[1]) {
-			zfcp_erp_adapter_reopen(unit->port->adapter, 0,
+			zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0,
 						"fsafch1", req);
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		}
 		break;
 	case FSF_LUN_HANDLE_NOT_VALID:
 		if (fsq->word[0] == fsq->word[1]) {
-			zfcp_erp_port_reopen(unit->port, 0, "fsafch2", req);
+			zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2",
+					     req);
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		}
 		break;
@@ -835,17 +794,23 @@
 		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
 		break;
 	case FSF_PORT_BOXED:
-		zfcp_erp_port_boxed(unit->port, "fsafch3", req);
+		zfcp_erp_set_port_status(zfcp_sdev->port,
+					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_port_reopen(zfcp_sdev->port,
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3",
+				     req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_BOXED:
-		zfcp_erp_unit_boxed(unit, "fsafch4", req);
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+				    "fsafch4", req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                 break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (fsq->word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			zfcp_fc_test_link(unit->port);
+			zfcp_fc_test_link(zfcp_sdev->port);
 			/* fall through */
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -859,19 +824,20 @@
 }
 
 /**
- * zfcp_fsf_abort_fcp_command - abort running SCSI command
- * @old_req_id: unsigned long
- * @unit: pointer to struct zfcp_unit
+ * zfcp_fsf_abort_fcp_cmnd - abort running SCSI command
+ * @scmnd: The SCSI command to abort
  * Returns: pointer to struct zfcp_fsf_req
  */
 
-struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
-						struct zfcp_unit *unit)
+struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
 {
 	struct zfcp_fsf_req *req = NULL;
-	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
+	struct scsi_device *sdev = scmnd->device;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
+	unsigned long old_req_id = (unsigned long) scmnd->host_scribble;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 	req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
@@ -882,16 +848,16 @@
 		goto out;
 	}
 
-	if (unlikely(!(atomic_read(&unit->status) &
+	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
 		       ZFCP_STATUS_COMMON_UNBLOCKED)))
 		goto out_error_free;
 
 	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
-	req->data = unit;
+	req->data = zfcp_sdev;
 	req->handler = zfcp_fsf_abort_fcp_command_handler;
-	req->qtcb->header.lun_handle = unit->handle;
-	req->qtcb->header.port_handle = unit->port->handle;
+	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
 	req->qtcb->bottom.support.req_handle = (u64) old_req_id;
 
 	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
@@ -902,7 +868,7 @@
 	zfcp_fsf_req_free(req);
 	req = NULL;
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return req;
 }
 
@@ -1041,7 +1007,7 @@
 	struct zfcp_fsf_req *req;
 	int ret = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1073,7 +1039,7 @@
 failed_send:
 	zfcp_fsf_req_free(req);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return ret;
 }
 
@@ -1111,8 +1077,10 @@
 	case FSF_RESPONSE_SIZE_TOO_LARGE:
 		break;
 	case FSF_ACCESS_DENIED:
-		if (port)
-			zfcp_fsf_access_denied_port(req, port);
+		if (port) {
+			zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
+			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		}
 		break;
 	case FSF_SBAL_MISMATCH:
 		/* should never occure, avoided in zfcp_fsf_send_els */
@@ -1137,7 +1105,7 @@
 	struct zfcp_qdio *qdio = adapter->qdio;
 	int ret = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1173,7 +1141,7 @@
 failed_send:
 	zfcp_fsf_req_free(req);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return ret;
 }
 
@@ -1183,7 +1151,7 @@
 	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1215,7 +1183,7 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1225,7 +1193,7 @@
 	struct zfcp_fsf_req *req = NULL;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out_unlock;
 
@@ -1251,7 +1219,7 @@
 
 	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
 	retval = zfcp_fsf_req_send(req);
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	if (!retval)
 		wait_for_completion(&req->completion);
 
@@ -1259,7 +1227,7 @@
 	return retval;
 
 out_unlock:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1277,7 +1245,7 @@
 	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
 		return -EOPNOTSUPP;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1304,7 +1272,7 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1323,7 +1291,7 @@
 	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
 		return -EOPNOTSUPP;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out_unlock;
 
@@ -1343,7 +1311,7 @@
 	req->handler = zfcp_fsf_exchange_port_data_handler;
 	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
 	retval = zfcp_fsf_req_send(req);
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 
 	if (!retval)
 		wait_for_completion(&req->completion);
@@ -1353,7 +1321,7 @@
 	return retval;
 
 out_unlock:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1370,14 +1338,16 @@
 	case FSF_PORT_ALREADY_OPEN:
 		break;
 	case FSF_ACCESS_DENIED:
-		zfcp_fsf_access_denied_port(req, port);
+		zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
 		dev_warn(&req->adapter->ccw_device->dev,
 			 "Not enough FCP adapter resources to open "
 			 "remote port 0x%016Lx\n",
 			 (unsigned long long)port->wwpn);
-		zfcp_erp_port_failed(port, "fsoph_1", req);
+		zfcp_erp_set_port_status(port,
+					 ZFCP_STATUS_COMMON_ERP_FAILED);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -1437,7 +1407,7 @@
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1468,7 +1438,7 @@
 		put_device(&port->dev);
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1487,9 +1457,7 @@
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		break;
 	case FSF_GOOD:
-		zfcp_erp_modify_port_status(port, "fscph_2", req,
-					    ZFCP_STATUS_COMMON_OPEN,
-					    ZFCP_CLEAR);
+		zfcp_erp_clear_port_status(port, ZFCP_STATUS_COMMON_OPEN);
 		break;
 	}
 }
@@ -1505,7 +1473,7 @@
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1534,7 +1502,7 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1580,7 +1548,7 @@
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1605,7 +1573,7 @@
 	if (retval)
 		zfcp_fsf_req_free(req);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1633,7 +1601,7 @@
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1658,7 +1626,7 @@
 	if (retval)
 		zfcp_fsf_req_free(req);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1666,7 +1634,7 @@
 {
 	struct zfcp_port *port = req->data;
 	struct fsf_qtcb_header *header = &req->qtcb->header;
-	struct zfcp_unit *unit;
+	struct scsi_device *sdev;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		return;
@@ -1677,18 +1645,19 @@
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ACCESS_DENIED:
-		zfcp_fsf_access_denied_port(req, port);
+		zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
 		break;
 	case FSF_PORT_BOXED:
 		/* can't use generic zfcp_erp_modify_port_status because
 		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
 		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
-		read_lock(&port->unit_list_lock);
-		list_for_each_entry(unit, &port->unit_list, list)
-			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
-					  &unit->status);
-		read_unlock(&port->unit_list_lock);
-		zfcp_erp_port_boxed(port, "fscpph2", req);
+		shost_for_each_device(sdev, port->adapter->scsi_host)
+			if (sdev_to_zfcp(sdev)->port == port)
+				atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
+						  &sdev_to_zfcp(sdev)->status);
+		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
+				     "fscpph2", req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -1705,11 +1674,10 @@
 		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port
 		 */
 		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
-		read_lock(&port->unit_list_lock);
-		list_for_each_entry(unit, &port->unit_list, list)
-			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
-					  &unit->status);
-		read_unlock(&port->unit_list_lock);
+		shost_for_each_device(sdev, port->adapter->scsi_host)
+			if (sdev_to_zfcp(sdev)->port == port)
+				atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
+						  &sdev_to_zfcp(sdev)->status);
 		break;
 	}
 }
@@ -1725,7 +1693,7 @@
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1754,69 +1722,57 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
-static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
 {
 	struct zfcp_adapter *adapter = req->adapter;
-	struct zfcp_unit *unit = req->data;
+	struct scsi_device *sdev = req->data;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 	struct fsf_qtcb_header *header = &req->qtcb->header;
 	struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
-	struct fsf_queue_designator *queue_designator =
-				&header->fsf_status_qual.fsf_queue_designator;
-	int exclusive, readwrite;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		return;
 
 	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
 			  ZFCP_STATUS_COMMON_ACCESS_BOXED |
-			  ZFCP_STATUS_UNIT_SHARED |
-			  ZFCP_STATUS_UNIT_READONLY,
-			  &unit->status);
+			  ZFCP_STATUS_LUN_SHARED |
+			  ZFCP_STATUS_LUN_READONLY,
+			  &zfcp_sdev->status);
 
 	switch (header->fsf_status) {
 
 	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fsouh_1", req);
+		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1", req);
 		/* fall through */
 	case FSF_LUN_ALREADY_OPEN:
 		break;
 	case FSF_ACCESS_DENIED:
-		zfcp_fsf_access_denied_unit(req, unit);
-		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
-		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+		zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_PORT_BOXED:
-		zfcp_erp_port_boxed(unit->port, "fsouh_2", req);
+		zfcp_erp_set_port_status(zfcp_sdev->port,
+					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_port_reopen(zfcp_sdev->port,
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2",
+				     req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_SHARING_VIOLATION:
-		if (header->fsf_status_qual.word[0])
-			dev_warn(&adapter->ccw_device->dev,
-				 "LUN 0x%Lx on port 0x%Lx is already in "
-				 "use by CSS%d, MIF Image ID %x\n",
-				 (unsigned long long)unit->fcp_lun,
-				 (unsigned long long)unit->port->wwpn,
-				 queue_designator->cssid,
-				 queue_designator->hla);
-		else
-			zfcp_act_eval_err(adapter,
-					  header->fsf_status_qual.word[2]);
-		zfcp_erp_unit_access_denied(unit, "fsouh_3", req);
-		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
-		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+		zfcp_cfdc_lun_shrng_vltn(sdev, &header->fsf_status_qual);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
 		dev_warn(&adapter->ccw_device->dev,
 			 "No handle is available for LUN "
 			 "0x%016Lx on port 0x%016Lx\n",
-			 (unsigned long long)unit->fcp_lun,
-			 (unsigned long long)unit->port->wwpn);
-		zfcp_erp_unit_failed(unit, "fsouh_4", req);
+			 (unsigned long long)zfcp_scsi_dev_lun(sdev),
+			 (unsigned long long)zfcp_sdev->port->wwpn);
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
 		/* fall through */
 	case FSF_INVALID_COMMAND_OPTION:
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1824,7 +1780,7 @@
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			zfcp_fc_test_link(unit->port);
+			zfcp_fc_test_link(zfcp_sdev->port);
 			/* fall through */
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1833,70 +1789,26 @@
 		break;
 
 	case FSF_GOOD:
-		unit->handle = header->lun_handle;
-		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
-
-		if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) &&
-		    (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) &&
-		    !zfcp_ccw_priv_sch(adapter)) {
-			exclusive = (bottom->lun_access_info &
-					FSF_UNIT_ACCESS_EXCLUSIVE);
-			readwrite = (bottom->lun_access_info &
-					FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
-
-			if (!exclusive)
-		                atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
-						&unit->status);
-
-			if (!readwrite) {
-                		atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
-						&unit->status);
-				dev_info(&adapter->ccw_device->dev,
-					 "SCSI device at LUN 0x%016Lx on port "
-					 "0x%016Lx opened read-only\n",
-					 (unsigned long long)unit->fcp_lun,
-					 (unsigned long long)unit->port->wwpn);
-        		}
-
-        		if (exclusive && !readwrite) {
-				dev_err(&adapter->ccw_device->dev,
-					"Exclusive read-only access not "
-					"supported (unit 0x%016Lx, "
-					"port 0x%016Lx)\n",
-					(unsigned long long)unit->fcp_lun,
-					(unsigned long long)unit->port->wwpn);
-				zfcp_erp_unit_failed(unit, "fsouh_5", req);
-				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-				zfcp_erp_unit_shutdown(unit, 0, "fsouh_6", req);
-        		} else if (!exclusive && readwrite) {
-				dev_err(&adapter->ccw_device->dev,
-					"Shared read-write access not "
-					"supported (unit 0x%016Lx, port "
-					"0x%016Lx)\n",
-					(unsigned long long)unit->fcp_lun,
-					(unsigned long long)unit->port->wwpn);
-				zfcp_erp_unit_failed(unit, "fsouh_7", req);
-				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-				zfcp_erp_unit_shutdown(unit, 0, "fsouh_8", req);
-        		}
-		}
+		zfcp_sdev->lun_handle = header->lun_handle;
+		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
+		zfcp_cfdc_open_lun_eval(sdev, bottom);
 		break;
 	}
 }
 
 /**
- * zfcp_fsf_open_unit - open unit
+ * zfcp_fsf_open_lun - open LUN
  * @erp_action: pointer to struct zfcp_erp_action
  * Returns: 0 on success, error otherwise
  */
-int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
+int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
 {
 	struct zfcp_adapter *adapter = erp_action->adapter;
 	struct zfcp_qdio *qdio = adapter->qdio;
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1913,9 +1825,9 @@
 	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
 	req->qtcb->header.port_handle = erp_action->port->handle;
-	req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun;
-	req->handler = zfcp_fsf_open_unit_handler;
-	req->data = erp_action->unit;
+	req->qtcb->bottom.support.fcp_lun = zfcp_scsi_dev_lun(erp_action->sdev);
+	req->handler = zfcp_fsf_open_lun_handler;
+	req->data = erp_action->sdev;
 	req->erp_action = erp_action;
 	erp_action->fsf_req_id = req->req_id;
 
@@ -1929,34 +1841,40 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
-static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
 {
-	struct zfcp_unit *unit = req->data;
+	struct scsi_device *sdev = req->data;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		return;
 
 	switch (req->qtcb->header.fsf_status) {
 	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fscuh_1", req);
+		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1",
+					req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_HANDLE_NOT_VALID:
-		zfcp_erp_port_reopen(unit->port, 0, "fscuh_2", req);
+		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2", req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_PORT_BOXED:
-		zfcp_erp_port_boxed(unit->port, "fscuh_3", req);
+		zfcp_erp_set_port_status(zfcp_sdev->port,
+					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_port_reopen(zfcp_sdev->port,
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3",
+				     req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (req->qtcb->header.fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			zfcp_fc_test_link(unit->port);
+			zfcp_fc_test_link(zfcp_sdev->port);
 			/* fall through */
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1964,23 +1882,24 @@
 		}
 		break;
 	case FSF_GOOD:
-		atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
+		atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
 		break;
 	}
 }
 
 /**
- * zfcp_fsf_close_unit - close zfcp unit
- * @erp_action: pointer to struct zfcp_unit
+ * zfcp_fsf_close_LUN - close LUN
+ * @erp_action: pointer to erp_action triggering the "close LUN"
  * Returns: 0 on success, error otherwise
  */
-int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
+int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
 {
 	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1997,9 +1916,9 @@
 	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
 	req->qtcb->header.port_handle = erp_action->port->handle;
-	req->qtcb->header.lun_handle = erp_action->unit->handle;
-	req->handler = zfcp_fsf_close_unit_handler;
-	req->data = erp_action->unit;
+	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+	req->handler = zfcp_fsf_close_lun_handler;
+	req->data = erp_action->sdev;
 	req->erp_action = erp_action;
 	erp_action->fsf_req_id = req->req_id;
 
@@ -2010,7 +1929,7 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -2025,7 +1944,7 @@
 {
 	struct fsf_qual_latency_info *lat_in;
 	struct latency_cont *lat = NULL;
-	struct zfcp_unit *unit = req->unit;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device);
 	struct zfcp_blk_drv_data blktrc;
 	int ticks = req->adapter->timer_ticks;
 
@@ -2048,24 +1967,24 @@
 		case FSF_DATADIR_DIF_READ_STRIP:
 		case FSF_DATADIR_DIF_READ_CONVERT:
 		case FSF_DATADIR_READ:
-			lat = &unit->latencies.read;
+			lat = &zfcp_sdev->latencies.read;
 			break;
 		case FSF_DATADIR_DIF_WRITE_INSERT:
 		case FSF_DATADIR_DIF_WRITE_CONVERT:
 		case FSF_DATADIR_WRITE:
-			lat = &unit->latencies.write;
+			lat = &zfcp_sdev->latencies.write;
 			break;
 		case FSF_DATADIR_CMND:
-			lat = &unit->latencies.cmd;
+			lat = &zfcp_sdev->latencies.cmd;
 			break;
 		}
 
 		if (lat) {
-			spin_lock(&unit->latencies.lock);
+			spin_lock(&zfcp_sdev->latencies.lock);
 			zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
 			zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
 			lat->counter++;
-			spin_unlock(&unit->latencies.lock);
+			spin_unlock(&zfcp_sdev->latencies.lock);
 		}
 	}
 
@@ -2073,12 +1992,88 @@
 			    sizeof(blktrc));
 }
 
-static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
+{
+	struct scsi_cmnd *scmnd = req->data;
+	struct scsi_device *sdev = scmnd->device;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct fsf_qtcb_header *header = &req->qtcb->header;
+
+	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
+		return;
+
+	switch (header->fsf_status) {
+	case FSF_HANDLE_MISMATCH:
+	case FSF_PORT_HANDLE_NOT_VALID:
+		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1",
+					req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_FCPLUN_NOT_VALID:
+	case FSF_LUN_HANDLE_NOT_VALID:
+		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2", req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
+		zfcp_fsf_class_not_supp(req);
+		break;
+	case FSF_ACCESS_DENIED:
+		zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_DIRECTION_INDICATOR_NOT_VALID:
+		dev_err(&req->adapter->ccw_device->dev,
+			"Incorrect direction %d, LUN 0x%016Lx on port "
+			"0x%016Lx closed\n",
+			req->qtcb->bottom.io.data_direction,
+			(unsigned long long)zfcp_scsi_dev_lun(sdev),
+			(unsigned long long)zfcp_sdev->port->wwpn);
+		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
+					  "fssfch3", req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_CMND_LENGTH_NOT_VALID:
+		dev_err(&req->adapter->ccw_device->dev,
+			"Incorrect CDB length %d, LUN 0x%016Lx on "
+			"port 0x%016Lx closed\n",
+			req->qtcb->bottom.io.fcp_cmnd_length,
+			(unsigned long long)zfcp_scsi_dev_lun(sdev),
+			(unsigned long long)zfcp_sdev->port->wwpn);
+		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
+					  "fssfch4", req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_PORT_BOXED:
+		zfcp_erp_set_port_status(zfcp_sdev->port,
+					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_port_reopen(zfcp_sdev->port,
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5",
+				     req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_LUN_BOXED:
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+				    "fssfch6", req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_ADAPTER_STATUS_AVAILABLE:
+		if (header->fsf_status_qual.word[0] ==
+		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
+			zfcp_fc_test_link(zfcp_sdev->port);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	}
+}
+
+static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
 {
 	struct scsi_cmnd *scpnt;
 	struct fcp_resp_with_ext *fcp_rsp;
 	unsigned long flags;
 
+	zfcp_fsf_fcp_handler_common(req);
+
 	read_lock_irqsave(&req->adapter->abort_lock, flags);
 
 	scpnt = req->data;
@@ -2125,97 +2120,6 @@
 	read_unlock_irqrestore(&req->adapter->abort_lock, flags);
 }
 
-static void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req)
-{
-	struct fcp_resp_with_ext *fcp_rsp;
-	struct fcp_resp_rsp_info *rsp_info;
-
-	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
-	rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
-
-	if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
-	     (req->status & ZFCP_STATUS_FSFREQ_ERROR))
-		req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
-}
-
-
-static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
-{
-	struct zfcp_unit *unit;
-	struct fsf_qtcb_header *header = &req->qtcb->header;
-
-	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT))
-		unit = req->data;
-	else
-		unit = req->unit;
-
-	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
-		goto skip_fsfstatus;
-
-	switch (header->fsf_status) {
-	case FSF_HANDLE_MISMATCH:
-	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fssfch1", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_FCPLUN_NOT_VALID:
-	case FSF_LUN_HANDLE_NOT_VALID:
-		zfcp_erp_port_reopen(unit->port, 0, "fssfch2", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
-		zfcp_fsf_class_not_supp(req);
-		break;
-	case FSF_ACCESS_DENIED:
-		zfcp_fsf_access_denied_unit(req, unit);
-		break;
-	case FSF_DIRECTION_INDICATOR_NOT_VALID:
-		dev_err(&req->adapter->ccw_device->dev,
-			"Incorrect direction %d, unit 0x%016Lx on port "
-			"0x%016Lx closed\n",
-			req->qtcb->bottom.io.data_direction,
-			(unsigned long long)unit->fcp_lun,
-			(unsigned long long)unit->port->wwpn);
-		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch3",
-					  req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_CMND_LENGTH_NOT_VALID:
-		dev_err(&req->adapter->ccw_device->dev,
-			"Incorrect CDB length %d, unit 0x%016Lx on "
-			"port 0x%016Lx closed\n",
-			req->qtcb->bottom.io.fcp_cmnd_length,
-			(unsigned long long)unit->fcp_lun,
-			(unsigned long long)unit->port->wwpn);
-		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch4",
-					  req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_PORT_BOXED:
-		zfcp_erp_port_boxed(unit->port, "fssfch5", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_LUN_BOXED:
-		zfcp_erp_unit_boxed(unit, "fssfch6", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_ADAPTER_STATUS_AVAILABLE:
-		if (header->fsf_status_qual.word[0] ==
-		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
-			zfcp_fc_test_link(unit->port);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	}
-skip_fsfstatus:
-	if (req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
-		zfcp_fsf_send_fcp_ctm_handler(req);
-	else {
-		zfcp_fsf_send_fcp_command_task_handler(req);
-		req->unit = NULL;
-		put_device(&unit->dev);
-	}
-}
-
 static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir)
 {
 	switch (scsi_get_prot_op(scsi_cmnd)) {
@@ -2255,22 +2159,22 @@
 }
 
 /**
- * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
- * @unit: unit where command is sent to
+ * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command)
  * @scsi_cmnd: scsi command to be sent
  */
-int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
-				   struct scsi_cmnd *scsi_cmnd)
+int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
 {
 	struct zfcp_fsf_req *req;
 	struct fcp_cmnd *fcp_cmnd;
 	unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
 	int real_bytes, retval = -EIO, dix_bytes = 0;
-	struct zfcp_adapter *adapter = unit->port->adapter;
+	struct scsi_device *sdev = scsi_cmnd->device;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	struct zfcp_qdio *qdio = adapter->qdio;
 	struct fsf_qtcb_bottom_io *io;
 
-	if (unlikely(!(atomic_read(&unit->status) &
+	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
 		       ZFCP_STATUS_COMMON_UNBLOCKED)))
 		return -EBUSY;
 
@@ -2295,11 +2199,10 @@
 
 	io = &req->qtcb->bottom.io;
 	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-	req->unit = unit;
 	req->data = scsi_cmnd;
-	req->handler = zfcp_fsf_send_fcp_command_handler;
-	req->qtcb->header.lun_handle = unit->handle;
-	req->qtcb->header.port_handle = unit->port->handle;
+	req->handler = zfcp_fsf_fcp_cmnd_handler;
+	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
 	io->service_class = FSF_CLASS_3;
 	io->fcp_cmnd_length = FCP_CMND_LEN;
 
@@ -2310,8 +2213,6 @@
 
 	zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction);
 
-	get_device(&unit->dev);
-
 	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
 	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
 
@@ -2338,7 +2239,6 @@
 	goto out;
 
 failed_scsi_cmnd:
-	put_device(&unit->dev);
 	zfcp_fsf_req_free(req);
 	scsi_cmnd->host_scribble = NULL;
 out:
@@ -2346,23 +2246,40 @@
 	return retval;
 }
 
+static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req)
+{
+	struct fcp_resp_with_ext *fcp_rsp;
+	struct fcp_resp_rsp_info *rsp_info;
+
+	zfcp_fsf_fcp_handler_common(req);
+
+	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
+	rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
+
+	if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
+	     (req->status & ZFCP_STATUS_FSFREQ_ERROR))
+		req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
+}
+
 /**
- * zfcp_fsf_send_fcp_ctm - send SCSI task management command
- * @unit: pointer to struct zfcp_unit
+ * zfcp_fsf_fcp_task_mgmt - send SCSI task management command
+ * @scmnd: SCSI command to send the task management command for
  * @tm_flags: unsigned byte for task management flags
  * Returns: on success pointer to struct fsf_req, NULL otherwise
  */
-struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
+struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
+					    u8 tm_flags)
 {
 	struct zfcp_fsf_req *req = NULL;
 	struct fcp_cmnd *fcp_cmnd;
-	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
+	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
 
-	if (unlikely(!(atomic_read(&unit->status) &
+	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
 		       ZFCP_STATUS_COMMON_UNBLOCKED)))
 		return NULL;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -2376,10 +2293,10 @@
 	}
 
 	req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
-	req->data = unit;
-	req->handler = zfcp_fsf_send_fcp_command_handler;
-	req->qtcb->header.lun_handle = unit->handle;
-	req->qtcb->header.port_handle = unit->port->handle;
+	req->data = scmnd;
+	req->handler = zfcp_fsf_fcp_task_mgmt_handler;
+	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
 	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
 	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
 	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
@@ -2387,7 +2304,7 @@
 	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, unit->device, tm_flags);
+	zfcp_fc_fcp_tm(fcp_cmnd, scmnd->device, tm_flags);
 
 	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
 	if (!zfcp_fsf_req_send(req))
@@ -2396,7 +2313,7 @@
 	zfcp_fsf_req_free(req);
 	req = NULL;
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return req;
 }
 
@@ -2432,7 +2349,7 @@
 		return ERR_PTR(-EINVAL);
 	}
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -2459,7 +2376,7 @@
 	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
 	retval = zfcp_fsf_req_send(req);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 
 	if (!retval) {
 		wait_for_completion(&req->completion);
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index b263575..a0554be 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -60,13 +60,11 @@
 	unsigned long long now, span;
 	int used;
 
-	spin_lock(&qdio->stat_lock);
 	now = get_clock_monotonic();
 	span = (now - qdio->req_q_time) >> 12;
 	used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free);
 	qdio->req_q_util += used * span;
 	qdio->req_q_time = now;
-	spin_unlock(&qdio->stat_lock);
 }
 
 static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
@@ -84,7 +82,9 @@
 	/* cleanup all SBALs being program-owned now */
 	zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
 
+	spin_lock_irq(&qdio->stat_lock);
 	zfcp_qdio_account(qdio);
+	spin_unlock_irq(&qdio->stat_lock);
 	atomic_add(count, &qdio->req_q_free);
 	wake_up(&qdio->req_q_wq);
 }
@@ -201,11 +201,11 @@
 
 static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
 {
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (atomic_read(&qdio->req_q_free) ||
 	    !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
 		return 1;
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return 0;
 }
 
@@ -223,7 +223,7 @@
 {
 	long ret;
 
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	ret = wait_event_interruptible_timeout(qdio->req_q_wq,
 			       zfcp_qdio_sbal_check(qdio), 5 * HZ);
 
@@ -239,7 +239,7 @@
 		zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1", NULL);
 	}
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	return -EIO;
 }
 
@@ -254,7 +254,9 @@
 	int retval;
 	u8 sbal_number = q_req->sbal_number;
 
+	spin_lock(&qdio->stat_lock);
 	zfcp_qdio_account(qdio);
+	spin_unlock(&qdio->stat_lock);
 
 	retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0,
 			 q_req->sbal_first, sbal_number);
@@ -277,16 +279,12 @@
 static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
 				      struct zfcp_qdio *qdio)
 {
-
+	memset(id, 0, sizeof(*id));
 	id->cdev = qdio->adapter->ccw_device;
 	id->q_format = QDIO_ZFCP_QFMT;
 	memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8);
 	ASCEBC(id->adapter_name, 8);
 	id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV;
-	id->qib_param_field_format = 0;
-	id->qib_param_field = NULL;
-	id->input_slib_elements = NULL;
-	id->output_slib_elements = NULL;
 	id->no_input_qs = 1;
 	id->no_output_qs = 1;
 	id->input_handler = zfcp_qdio_int_resp;
@@ -328,9 +326,9 @@
 		return;
 
 	/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 
 	wake_up(&qdio->req_q_wq);
 
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index cb000c9..50286d8 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -49,11 +49,12 @@
 	return sdev->queue_depth;
 }
 
-static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
+static void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
 {
-	struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
-	unit->device = NULL;
-	put_device(&unit->dev);
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	zfcp_erp_lun_shutdown_wait(sdev, "scssd_1");
+	put_device(&zfcp_sdev->port->dev);
 }
 
 static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
@@ -78,23 +79,16 @@
 static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 				  void (*done) (struct scsi_cmnd *))
 {
-	struct zfcp_unit *unit;
-	struct zfcp_adapter *adapter;
-	int    status, scsi_result, ret;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
+	int    status, scsi_result, ret;
 
 	/* reset the status for this request */
 	scpnt->result = 0;
 	scpnt->host_scribble = NULL;
 	scpnt->scsi_done = done;
 
-	/*
-	 * figure out adapter and target device
-	 * (stored there by zfcp_scsi_slave_alloc)
-	 */
-	adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
-	unit = scpnt->device->hostdata;
-
 	scsi_result = fc_remote_port_chkready(rport);
 	if (unlikely(scsi_result)) {
 		scpnt->result = scsi_result;
@@ -103,11 +97,11 @@
 		return 0;
 	}
 
-	status = atomic_read(&unit->status);
+	status = atomic_read(&zfcp_sdev->status);
 	if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) &&
-		     !(atomic_read(&unit->port->status) &
+		     !(atomic_read(&zfcp_sdev->port->status) &
 		       ZFCP_STATUS_COMMON_ERP_FAILED)) {
-		/* only unit access denied, but port is good
+		/* only LUN access denied, but port is good
 		 * not covered by FC transport, have to fail here */
 		zfcp_scsi_command_fail(scpnt, DID_ERROR);
 		return 0;
@@ -115,8 +109,8 @@
 
 	if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) {
 		/* This could be either
-		 * open unit pending: this is temporary, will result in
-		 * 	open unit or ERP_FAILED, so retry command
+		 * open LUN pending: this is temporary, will result in
+		 *	open LUN or ERP_FAILED, so retry command
 		 * call to rport_delete pending: mimic retry from
 		 * 	fc_remote_port_chkready until rport is BLOCKED
 		 */
@@ -124,7 +118,7 @@
 		return 0;
 	}
 
-	ret = zfcp_fsf_send_fcp_command_task(unit, scpnt);
+	ret = zfcp_fsf_fcp_cmnd(scpnt);
 	if (unlikely(ret == -EBUSY))
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	else if (unlikely(ret < 0))
@@ -133,45 +127,42 @@
 	return ret;
 }
 
-static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter,
-					  unsigned int id, u64 lun)
+static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
 {
-	unsigned long flags;
+	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+	struct zfcp_adapter *adapter =
+		(struct zfcp_adapter *) sdev->host->hostdata[0];
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 	struct zfcp_port *port;
-	struct zfcp_unit *unit = NULL;
-
-	read_lock_irqsave(&adapter->port_list_lock, flags);
-	list_for_each_entry(port, &adapter->port_list, list) {
-		if (!port->rport || (id != port->rport->scsi_target_id))
-			continue;
-		unit = zfcp_get_unit_by_lun(port, lun);
-		if (unit)
-			break;
-	}
-	read_unlock_irqrestore(&adapter->port_list_lock, flags);
-
-	return unit;
-}
-
-static int zfcp_scsi_slave_alloc(struct scsi_device *sdp)
-{
-	struct zfcp_adapter *adapter;
 	struct zfcp_unit *unit;
-	u64 lun;
 
-	adapter = (struct zfcp_adapter *) sdp->host->hostdata[0];
-	if (!adapter)
-		goto out;
+	port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
+	if (!port)
+		return -ENXIO;
 
-	int_to_scsilun(sdp->lun, (struct scsi_lun *)&lun);
-	unit = zfcp_unit_lookup(adapter, sdp->id, lun);
-	if (unit) {
-		sdp->hostdata = unit;
-		unit->device = sdp;
-		return 0;
+	unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
+	if (unit)
+		put_device(&unit->dev);
+
+	if (!unit && !(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) {
+		put_device(&port->dev);
+		return -ENXIO;
 	}
-out:
-	return -ENXIO;
+
+	zfcp_sdev->port = port;
+	zfcp_sdev->latencies.write.channel.min = 0xFFFFFFFF;
+	zfcp_sdev->latencies.write.fabric.min = 0xFFFFFFFF;
+	zfcp_sdev->latencies.read.channel.min = 0xFFFFFFFF;
+	zfcp_sdev->latencies.read.fabric.min = 0xFFFFFFFF;
+	zfcp_sdev->latencies.cmd.channel.min = 0xFFFFFFFF;
+	zfcp_sdev->latencies.cmd.fabric.min = 0xFFFFFFFF;
+	spin_lock_init(&zfcp_sdev->latencies.lock);
+
+	zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
+	zfcp_erp_lun_reopen(sdev, 0, "scsla_1", NULL);
+	zfcp_erp_wait(port->adapter);
+
+	return 0;
 }
 
 static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
@@ -179,7 +170,6 @@
 	struct Scsi_Host *scsi_host = scpnt->device->host;
 	struct zfcp_adapter *adapter =
 		(struct zfcp_adapter *) scsi_host->hostdata[0];
-	struct zfcp_unit *unit = scpnt->device->hostdata;
 	struct zfcp_fsf_req *old_req, *abrt_req;
 	unsigned long flags;
 	unsigned long old_reqid = (unsigned long) scpnt->host_scribble;
@@ -203,7 +193,7 @@
 	write_unlock_irqrestore(&adapter->abort_lock, flags);
 
 	while (retry--) {
-		abrt_req = zfcp_fsf_abort_fcp_command(old_reqid, unit);
+		abrt_req = zfcp_fsf_abort_fcp_cmnd(scpnt);
 		if (abrt_req)
 			break;
 
@@ -238,14 +228,14 @@
 
 static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
 {
-	struct zfcp_unit *unit = scpnt->device->hostdata;
-	struct zfcp_adapter *adapter = unit->port->adapter;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	struct zfcp_fsf_req *fsf_req = NULL;
 	int retval = SUCCESS, ret;
 	int retry = 3;
 
 	while (retry--) {
-		fsf_req = zfcp_fsf_send_fcp_ctm(unit, tm_flags);
+		fsf_req = zfcp_fsf_fcp_task_mgmt(scpnt, tm_flags);
 		if (fsf_req)
 			break;
 
@@ -256,7 +246,7 @@
 
 		if (!(atomic_read(&adapter->status) &
 		      ZFCP_STATUS_COMMON_RUNNING)) {
-			zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt);
+			zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags);
 			return SUCCESS;
 		}
 	}
@@ -266,10 +256,10 @@
 	wait_for_completion(&fsf_req->completion);
 
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
-		zfcp_dbf_scsi_devreset("fail", tm_flags, unit, scpnt);
+		zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags);
 		retval = FAILED;
 	} else
-		zfcp_dbf_scsi_devreset("okay", tm_flags, unit, scpnt);
+		zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags);
 
 	zfcp_fsf_req_free(fsf_req);
 	return retval;
@@ -287,8 +277,8 @@
 
 static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 {
-	struct zfcp_unit *unit = scpnt->device->hostdata;
-	struct zfcp_adapter *adapter = unit->port->adapter;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	int ret;
 
 	zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt);
@@ -319,8 +309,8 @@
 	}
 
 	/* tell the SCSI stack some characteristics of this adapter */
-	adapter->scsi_host->max_id = 1;
-	adapter->scsi_host->max_lun = 1;
+	adapter->scsi_host->max_id = 511;
+	adapter->scsi_host->max_lun = 0xFFFFFFFF;
 	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 */
@@ -534,20 +524,6 @@
 	}
 }
 
-static void zfcp_scsi_queue_unit_register(struct zfcp_port *port)
-{
-	struct zfcp_unit *unit;
-
-	read_lock_irq(&port->unit_list_lock);
-	list_for_each_entry(unit, &port->unit_list, list) {
-		get_device(&unit->dev);
-		if (scsi_queue_work(port->adapter->scsi_host,
-				    &unit->scsi_work) <= 0)
-			put_device(&unit->dev);
-	}
-	read_unlock_irq(&port->unit_list_lock);
-}
-
 static void zfcp_scsi_rport_register(struct zfcp_port *port)
 {
 	struct fc_rport_identifiers ids;
@@ -574,7 +550,7 @@
 	port->rport = rport;
 	port->starget_id = rport->scsi_target_id;
 
-	zfcp_scsi_queue_unit_register(port);
+	zfcp_unit_queue_scsi_scan(port);
 }
 
 static void zfcp_scsi_rport_block(struct zfcp_port *port)
@@ -638,29 +614,6 @@
 }
 
 /**
- * zfcp_scsi_scan - Register LUN with SCSI midlayer
- * @unit: The LUN/unit to register
- */
-void zfcp_scsi_scan(struct zfcp_unit *unit)
-{
-	struct fc_rport *rport = unit->port->rport;
-
-	if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
-		scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
-				 scsilun_to_int((struct scsi_lun *)
-						&unit->fcp_lun), 0);
-}
-
-void zfcp_scsi_scan_work(struct work_struct *work)
-{
-	struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
-					      scsi_work);
-
-	zfcp_scsi_scan(unit);
-	put_device(&unit->dev);
-}
-
-/**
  * zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host
  * @adapter: The adapter where to configure DIF/DIX for the SCSI host
  */
@@ -681,6 +634,7 @@
 	    adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) {
 		mask |= SHOST_DIX_TYPE1_PROTECTION;
 		scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP);
+		shost->sg_prot_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
 		shost->sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
 		shost->max_sectors = ZFCP_QDIO_MAX_SBALES_PER_REQ * 8 / 2;
 	}
@@ -734,7 +688,6 @@
 	.show_host_port_type = 1,
 	.show_host_speed = 1,
 	.show_host_port_id = 1,
-	.disable_target_scan = 1,
 	.dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),
 };
 
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index b4561c86..2f2c54f 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -68,63 +68,96 @@
 		  ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
 
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n",
-		 atomic_read(&unit->status));
+		 zfcp_unit_sdev_status(unit));
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n",
-		 (atomic_read(&unit->status) &
+		 (zfcp_unit_sdev_status(unit) &
 		  ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n",
-		 (atomic_read(&unit->status) &
+		 (zfcp_unit_sdev_status(unit) &
 		  ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_shared, "%d\n",
-		 (atomic_read(&unit->status) &
-		  ZFCP_STATUS_UNIT_SHARED) != 0);
+		 (zfcp_unit_sdev_status(unit) &
+		  ZFCP_STATUS_LUN_SHARED) != 0);
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_readonly, "%d\n",
-		 (atomic_read(&unit->status) &
-		  ZFCP_STATUS_UNIT_READONLY) != 0);
+		 (zfcp_unit_sdev_status(unit) &
+		  ZFCP_STATUS_LUN_READONLY) != 0);
 
-#define ZFCP_SYSFS_FAILED(_feat_def, _feat, _adapter, _mod_id, _reopen_id)     \
-static ssize_t zfcp_sysfs_##_feat##_failed_show(struct device *dev,	       \
-						struct device_attribute *attr, \
-						char *buf)		       \
-{									       \
-	struct _feat_def *_feat = container_of(dev, struct _feat_def, dev);    \
-									       \
-	if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED)       \
-		return sprintf(buf, "1\n");				       \
-	else								       \
-		return sprintf(buf, "0\n");				       \
-}									       \
-static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev,	       \
-						 struct device_attribute *attr,\
-						 const char *buf, size_t count)\
-{									       \
-	struct _feat_def *_feat = container_of(dev, struct _feat_def, dev);    \
-	unsigned long val;						       \
-	int retval = 0;							       \
-									       \
-	if (!(_feat && get_device(&_feat->dev)))			       \
-		return -EBUSY;						       \
-									       \
-	if (strict_strtoul(buf, 0, &val) || val != 0) {			       \
-		retval = -EINVAL;					       \
-		goto out;						       \
-	}								       \
-									       \
-	zfcp_erp_modify_##_feat##_status(_feat, _mod_id, NULL,		       \
-					 ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);\
-	zfcp_erp_##_feat##_reopen(_feat, ZFCP_STATUS_COMMON_ERP_FAILED,	       \
-				  _reopen_id, NULL);			       \
-	zfcp_erp_wait(_adapter);					       \
-out:									       \
-	put_device(&_feat->dev);					       \
-	return retval ? retval : (ssize_t) count;			       \
-}									       \
-static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO,			       \
-		     zfcp_sysfs_##_feat##_failed_show,			       \
-		     zfcp_sysfs_##_feat##_failed_store);
+static ssize_t zfcp_sysfs_port_failed_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
 
-ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2");
-ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2");
+	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
+		return sprintf(buf, "1\n");
+
+	return sprintf(buf, "0\n");
+}
+
+static ssize_t zfcp_sysfs_port_failed_store(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf, size_t count)
+{
+	struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
+	unsigned long val;
+
+	if (strict_strtoul(buf, 0, &val) || val != 0)
+		return -EINVAL;
+
+	zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_RUNNING);
+	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "sypfai2",
+			     NULL);
+	zfcp_erp_wait(port->adapter);
+
+	return count;
+}
+static ZFCP_DEV_ATTR(port, failed, S_IWUSR | S_IRUGO,
+		     zfcp_sysfs_port_failed_show,
+		     zfcp_sysfs_port_failed_store);
+
+static ssize_t zfcp_sysfs_unit_failed_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
+	struct scsi_device *sdev;
+	unsigned int status, failed = 1;
+
+	sdev = zfcp_unit_sdev(unit);
+	if (sdev) {
+		status = atomic_read(&sdev_to_zfcp(sdev)->status);
+		failed = status & ZFCP_STATUS_COMMON_ERP_FAILED ? 1 : 0;
+		scsi_device_put(sdev);
+	}
+
+	return sprintf(buf, "%d\n", failed);
+}
+
+static ssize_t zfcp_sysfs_unit_failed_store(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf, size_t count)
+{
+	struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
+	unsigned long val;
+	struct scsi_device *sdev;
+
+	if (strict_strtoul(buf, 0, &val) || val != 0)
+		return -EINVAL;
+
+	sdev = zfcp_unit_sdev(unit);
+	if (sdev) {
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
+		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+				    "syufai2", NULL);
+		zfcp_erp_wait(unit->port->adapter);
+	} else
+		zfcp_unit_scsi_scan(unit);
+
+	return count;
+}
+static ZFCP_DEV_ATTR(unit, failed, S_IWUSR | S_IRUGO,
+		     zfcp_sysfs_unit_failed_show,
+		     zfcp_sysfs_unit_failed_store);
 
 static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev,
 					      struct device_attribute *attr,
@@ -163,8 +196,7 @@
 		goto out;
 	}
 
-	zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL,
-				       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
 				"syafai2", NULL);
 	zfcp_erp_wait(adapter);
@@ -257,28 +289,15 @@
 					 const char *buf, size_t count)
 {
 	struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
-	struct zfcp_unit *unit;
 	u64 fcp_lun;
-	int retval = -EINVAL;
-
-	if (!(port && get_device(&port->dev)))
-		return -EBUSY;
 
 	if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
-		goto out;
+		return -EINVAL;
 
-	unit = zfcp_unit_enqueue(port, fcp_lun);
-	if (IS_ERR(unit))
-		goto out;
-	else
-		retval = 0;
+	if (zfcp_unit_add(port, fcp_lun))
+		return -EINVAL;
 
-	zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
-	zfcp_erp_wait(unit->port->adapter);
-	zfcp_scsi_scan(unit);
-out:
-	put_device(&port->dev);
-	return retval ? retval : (ssize_t) count;
+	return count;
 }
 static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
 
@@ -287,42 +306,15 @@
 					    const char *buf, size_t count)
 {
 	struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
-	struct zfcp_unit *unit;
 	u64 fcp_lun;
-	int retval = -EINVAL;
-	struct scsi_device *sdev;
-
-	if (!(port && get_device(&port->dev)))
-		return -EBUSY;
 
 	if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
-		goto out;
+		return -EINVAL;
 
-	unit = zfcp_get_unit_by_lun(port, fcp_lun);
-	if (!unit)
-		goto out;
-	else
-		retval = 0;
+	if (zfcp_unit_remove(port, fcp_lun))
+		return -EINVAL;
 
-	sdev = scsi_device_lookup(port->adapter->scsi_host, 0,
-				  port->starget_id,
-				  scsilun_to_int((struct scsi_lun *)&fcp_lun));
-	if (sdev) {
-		scsi_remove_device(sdev);
-		scsi_device_put(sdev);
-	}
-
-	write_lock_irq(&port->unit_list_lock);
-	list_del(&unit->list);
-	write_unlock_irq(&port->unit_list_lock);
-
-	put_device(&unit->dev);
-
-	zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
-	zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
-out:
-	put_device(&port->dev);
-	return retval ? retval : (ssize_t) count;
+	return count;
 }
 static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
 
@@ -363,9 +355,9 @@
 				       struct device_attribute *attr,	\
 				       char *buf) {			\
 	struct scsi_device *sdev = to_scsi_device(dev);			\
-	struct zfcp_unit *unit = sdev->hostdata;			\
-	struct zfcp_latencies *lat = &unit->latencies;			\
-	struct zfcp_adapter *adapter = unit->port->adapter;		\
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);		\
+	struct zfcp_latencies *lat = &zfcp_sdev->latencies;		\
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;	\
 	unsigned long long fsum, fmin, fmax, csum, cmin, cmax, cc;	\
 									\
 	spin_lock_bh(&lat->lock);					\
@@ -394,8 +386,8 @@
 					const char *buf, size_t count)	\
 {									\
 	struct scsi_device *sdev = to_scsi_device(dev);			\
-	struct zfcp_unit *unit = sdev->hostdata;			\
-	struct zfcp_latencies *lat = &unit->latencies;			\
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);		\
+	struct zfcp_latencies *lat = &zfcp_sdev->latencies;		\
 	unsigned long flags;						\
 									\
 	spin_lock_irqsave(&lat->lock, flags);				\
@@ -423,19 +415,28 @@
 					      struct device_attribute *attr,\
 					      char *buf)                 \
 {                                                                        \
-	struct scsi_device *sdev  = to_scsi_device(dev);		 \
-	struct zfcp_unit *unit = sdev->hostdata;			 \
+	struct scsi_device *sdev = to_scsi_device(dev);			 \
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);		 \
+	struct zfcp_port *port = zfcp_sdev->port;			 \
 									 \
 	return sprintf(buf, _format, _value);                            \
 }                                                                        \
 static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
 
 ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
-		      dev_name(&unit->port->adapter->ccw_device->dev));
+		      dev_name(&port->adapter->ccw_device->dev));
 ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
-		      (unsigned long long) unit->port->wwpn);
-ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n",
-		      (unsigned long long) unit->fcp_lun);
+		      (unsigned long long) port->wwpn);
+
+static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+
+	return sprintf(buf, "0x%016llx\n", zfcp_scsi_dev_lun(sdev));
+}
+static DEVICE_ATTR(fcp_lun, S_IRUGO, zfcp_sysfs_scsi_fcp_lun_show, NULL);
 
 struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
 	&dev_attr_fcp_lun,
diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c
new file mode 100644
index 0000000..1119c53
--- /dev/null
+++ b/drivers/s390/scsi/zfcp_unit.c
@@ -0,0 +1,244 @@
+/*
+ * zfcp device driver
+ *
+ * Tracking of manually configured LUNs and helper functions to
+ * register the LUNs with the SCSI midlayer.
+ *
+ * Copyright IBM Corporation 2010
+ */
+
+#include "zfcp_def.h"
+#include "zfcp_ext.h"
+
+/**
+ * zfcp_unit_scsi_scan - Register LUN with SCSI midlayer
+ * @unit: The zfcp LUN/unit to register
+ *
+ * When the SCSI midlayer is not allowed to automatically scan and
+ * attach SCSI devices, zfcp has to register the single devices with
+ * the SCSI midlayer.
+ */
+void zfcp_unit_scsi_scan(struct zfcp_unit *unit)
+{
+	struct fc_rport *rport = unit->port->rport;
+	unsigned int lun;
+
+	lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
+
+	if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
+		scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, 1);
+}
+
+static void zfcp_unit_scsi_scan_work(struct work_struct *work)
+{
+	struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
+					      scsi_work);
+
+	zfcp_unit_scsi_scan(unit);
+	put_device(&unit->dev);
+}
+
+/**
+ * zfcp_unit_queue_scsi_scan - Register configured units on port
+ * @port: The zfcp_port where to register units
+ *
+ * After opening a port, all units configured on this port have to be
+ * registered with the SCSI midlayer. This function should be called
+ * after calling fc_remote_port_add, so that the fc_rport is already
+ * ONLINE and the call to scsi_scan_target runs the same way as the
+ * call in the FC transport class.
+ */
+void zfcp_unit_queue_scsi_scan(struct zfcp_port *port)
+{
+	struct zfcp_unit *unit;
+
+	read_lock_irq(&port->unit_list_lock);
+	list_for_each_entry(unit, &port->unit_list, list) {
+		get_device(&unit->dev);
+		if (scsi_queue_work(port->adapter->scsi_host,
+				    &unit->scsi_work) <= 0)
+			put_device(&unit->dev);
+	}
+	read_unlock_irq(&port->unit_list_lock);
+}
+
+static struct zfcp_unit *_zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun)
+{
+	struct zfcp_unit *unit;
+
+	list_for_each_entry(unit, &port->unit_list, list)
+		if (unit->fcp_lun == fcp_lun) {
+			get_device(&unit->dev);
+			return unit;
+		}
+
+	return NULL;
+}
+
+/**
+ * zfcp_unit_find - Find and return zfcp_unit with specified FCP LUN
+ * @port: zfcp_port where to look for the unit
+ * @fcp_lun: 64 Bit FCP LUN used to identify the zfcp_unit
+ *
+ * If zfcp_unit is found, a reference is acquired that has to be
+ * released later.
+ *
+ * Returns: Pointer to the zfcp_unit, or NULL if there is no zfcp_unit
+ *          with the specified FCP LUN.
+ */
+struct zfcp_unit *zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun)
+{
+	struct zfcp_unit *unit;
+
+	read_lock_irq(&port->unit_list_lock);
+	unit = _zfcp_unit_find(port, fcp_lun);
+	read_unlock_irq(&port->unit_list_lock);
+	return unit;
+}
+
+/**
+ * zfcp_unit_release - Drop reference to zfcp_port and free memory of zfcp_unit.
+ * @dev: pointer to device in zfcp_unit
+ */
+static void zfcp_unit_release(struct device *dev)
+{
+	struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
+
+	put_device(&unit->port->dev);
+	kfree(unit);
+}
+
+/**
+ * zfcp_unit_enqueue - enqueue unit to unit list of a port.
+ * @port: pointer to port where unit is added
+ * @fcp_lun: FCP LUN of unit to be enqueued
+ * Returns: 0 success
+ *
+ * Sets up some unit internal structures and creates sysfs entry.
+ */
+int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
+{
+	struct zfcp_unit *unit;
+
+	unit = zfcp_unit_find(port, fcp_lun);
+	if (unit) {
+		put_device(&unit->dev);
+		return -EEXIST;
+	}
+
+	unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
+	if (!unit)
+		return -ENOMEM;
+
+	unit->port = port;
+	unit->fcp_lun = fcp_lun;
+	unit->dev.parent = &port->dev;
+	unit->dev.release = zfcp_unit_release;
+	INIT_WORK(&unit->scsi_work, zfcp_unit_scsi_scan_work);
+
+	if (dev_set_name(&unit->dev, "0x%016llx",
+			 (unsigned long long) fcp_lun)) {
+		kfree(unit);
+		return -ENOMEM;
+	}
+
+	if (device_register(&unit->dev)) {
+		put_device(&unit->dev);
+		return -ENOMEM;
+	}
+
+	if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) {
+		device_unregister(&unit->dev);
+		return -EINVAL;
+	}
+
+	get_device(&port->dev);
+
+	write_lock_irq(&port->unit_list_lock);
+	list_add_tail(&unit->list, &port->unit_list);
+	write_unlock_irq(&port->unit_list_lock);
+
+	zfcp_unit_scsi_scan(unit);
+
+	return 0;
+}
+
+/**
+ * zfcp_unit_sdev - Return SCSI device for zfcp_unit
+ * @unit: The zfcp_unit where to get the SCSI device for
+ *
+ * Returns: scsi_device pointer on success, NULL if there is no SCSI
+ *          device for this zfcp_unit
+ *
+ * On success, the caller also holds a reference to the SCSI device
+ * that must be released with scsi_device_put.
+ */
+struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit)
+{
+	struct Scsi_Host *shost;
+	struct zfcp_port *port;
+	unsigned int lun;
+
+	lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
+	port = unit->port;
+	shost = port->adapter->scsi_host;
+	return scsi_device_lookup(shost, 0, port->starget_id, lun);
+}
+
+/**
+ * zfcp_unit_sdev_status - Return zfcp LUN status for SCSI device
+ * @unit: The unit to lookup the SCSI device for
+ *
+ * Returns the zfcp LUN status field of the SCSI device if the SCSI device
+ * for the zfcp_unit exists, 0 otherwise.
+ */
+unsigned int zfcp_unit_sdev_status(struct zfcp_unit *unit)
+{
+	unsigned int status = 0;
+	struct scsi_device *sdev;
+	struct zfcp_scsi_dev *zfcp_sdev;
+
+	sdev = zfcp_unit_sdev(unit);
+	if (sdev) {
+		zfcp_sdev = sdev_to_zfcp(sdev);
+		status = atomic_read(&zfcp_sdev->status);
+		scsi_device_put(sdev);
+	}
+
+	return status;
+}
+
+/**
+ * zfcp_unit_remove - Remove entry from list of configured units
+ * @port: The port where to remove the unit from the configuration
+ * @fcp_lun: The 64 bit LUN of the unit to remove
+ *
+ * Returns: -EINVAL if a unit with the specified LUN does not exist,
+ *          0 on success.
+ */
+int zfcp_unit_remove(struct zfcp_port *port, u64 fcp_lun)
+{
+	struct zfcp_unit *unit;
+	struct scsi_device *sdev;
+
+	write_lock_irq(&port->unit_list_lock);
+	unit = _zfcp_unit_find(port, fcp_lun);
+	if (unit)
+		list_del(&unit->list);
+	write_unlock_irq(&port->unit_list_lock);
+
+	if (!unit)
+		return -EINVAL;
+
+	sdev = zfcp_unit_sdev(unit);
+	if (sdev) {
+		scsi_remove_device(sdev);
+		scsi_device_put(sdev);
+	}
+
+	put_device(&unit->dev);
+
+	zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
+
+	return 0;
+}
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 1690e53..55f71ea 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -162,6 +162,7 @@
 	.compat_ioctl =		d7s_ioctl,
 	.open =			d7s_open,
 	.release =		d7s_release,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice d7s_miscdev = {
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index 078e5f4..8ce414e 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -720,6 +720,7 @@
 #endif
 	.open =			envctrl_open,
 	.release =		envctrl_release,
+	.llseek =		noop_llseek,
 };	
 
 static struct miscdevice envctrl_dev = {
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index 4942050..13f48e2 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -27,7 +27,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
@@ -68,6 +68,8 @@
 #define JSF_PART_BITS	 2	/* 2 bits of minors to cover JSF_NPART */
 #define JSF_PART_MASK	 0x3	/* 2 bits mask */
 
+static DEFINE_MUTEX(jsf_mutex);
+
 /*
  * Access functions.
  * We could ioremap(), but it's easier this way.
@@ -225,7 +227,7 @@
 {
 	loff_t ret;
 
-	lock_kernel();
+	mutex_lock(&jsf_mutex);
 	switch (orig) {
 		case 0:
 			file->f_pos = offset;
@@ -238,7 +240,7 @@
 		default:
 			ret = -EINVAL;
 	}
-	unlock_kernel();
+	mutex_unlock(&jsf_mutex);
 	return ret;
 }
 
@@ -384,18 +386,18 @@
 
 static long jsf_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 {
-	lock_kernel();
+	mutex_lock(&jsf_mutex);
 	int error = -ENOTTY;
 	void __user *argp = (void __user *)arg;
 
 	if (!capable(CAP_SYS_ADMIN)) {
-		unlock_kernel();
+		mutex_unlock(&jsf_mutex);
 		return -EPERM;
 	}
 	switch (cmd) {
 	case JSFLASH_IDENT:
 		if (copy_to_user(argp, &jsf0.id, JSFIDSZ)) {
-			unlock_kernel();
+			mutex_unlock(&jsf_mutex);
 			return -EFAULT;
 		}
 		break;
@@ -407,7 +409,7 @@
 		break;
 	}
 
-	unlock_kernel();
+	mutex_unlock(&jsf_mutex);
 	return error;
 }
 
@@ -418,17 +420,17 @@
 
 static int jsf_open(struct inode * inode, struct file * filp)
 {
-	lock_kernel();
+	mutex_lock(&jsf_mutex);
 	if (jsf0.base == 0) {
-		unlock_kernel();
+		mutex_unlock(&jsf_mutex);
 		return -ENXIO;
 	}
 	if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) {
-		unlock_kernel();
+		mutex_unlock(&jsf_mutex);
 		return -EBUSY;
 	}
 
-	unlock_kernel();
+	mutex_unlock(&jsf_mutex);
 	return 0;	/* XXX What security? */
 }
 
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index e20b7bd..fcf08b3 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -92,7 +92,6 @@
 #include <linux/pci.h>
 #include <linux/time.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -105,6 +104,7 @@
 
 /* Globals */
 #define TW_DRIVER_VERSION "2.26.02.014"
+static DEFINE_MUTEX(twa_chrdev_mutex);
 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
 static unsigned int twa_device_extension_count;
 static int twa_major = -1;
@@ -222,7 +222,8 @@
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= twa_chrdev_ioctl,
 	.open		= twa_chrdev_open,
-	.release	= NULL
+	.release	= NULL,
+	.llseek		= noop_llseek,
 };
 
 /* This function will complete an aen request from the isr */
@@ -658,7 +659,7 @@
 	int retval = TW_IOCTL_ERROR_OS_EFAULT;
 	void __user *argp = (void __user *)arg;
 
-	lock_kernel();
+	mutex_lock(&twa_chrdev_mutex);
 
 	/* Only let one of these through at a time */
 	if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
@@ -879,7 +880,7 @@
 out2:
 	mutex_unlock(&tw_dev->ioctl_lock);
 out:
-	unlock_kernel();
+	mutex_unlock(&twa_chrdev_mutex);
 	return retval;
 } /* End twa_chrdev_ioctl() */
 
@@ -890,7 +891,6 @@
 	unsigned int minor_number;
 	int retval = TW_IOCTL_ERROR_OS_ENODEV;
 
-	cycle_kernel_lock();
 	minor_number = iminor(inode);
 	if (minor_number >= twa_device_extension_count)
 		goto out;
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index f481e73..6a95d11 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -64,7 +64,6 @@
 #include <linux/pci.h>
 #include <linux/time.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -77,6 +76,7 @@
 
 /* Globals */
 #define TW_DRIVER_VERSION "3.26.02.000"
+static DEFINE_MUTEX(twl_chrdev_mutex);
 static TW_Device_Extension *twl_device_extension_list[TW_MAX_SLOT];
 static unsigned int twl_device_extension_count;
 static int twl_major = -1;
@@ -764,7 +764,7 @@
 	int retval = -EFAULT;
 	void __user *argp = (void __user *)arg;
 
-	lock_kernel();
+	mutex_lock(&twl_chrdev_mutex);
 
 	/* Only let one of these through at a time */
 	if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
@@ -861,7 +861,7 @@
 out2:
 	mutex_unlock(&tw_dev->ioctl_lock);
 out:
-	unlock_kernel();
+	mutex_unlock(&twl_chrdev_mutex);
 	return retval;
 } /* End twl_chrdev_ioctl() */
 
@@ -876,7 +876,6 @@
 		goto out;
 	}
 
-	cycle_kernel_lock();
 	minor_number = iminor(inode);
 	if (minor_number >= twl_device_extension_count)
 		goto out;
@@ -890,7 +889,8 @@
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= twl_chrdev_ioctl,
 	.open		= twl_chrdev_open,
-	.release	= NULL
+	.release	= NULL,
+	.llseek		= noop_llseek,
 };
 
 /* This function passes sense data from firmware to scsi layer */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 30d735a..b112534 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -199,7 +199,6 @@
 
 #include <linux/module.h>
 #include <linux/reboot.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/moduleparam.h>
@@ -221,6 +220,7 @@
 
 /* Globals */
 #define TW_DRIVER_VERSION "1.26.02.003"
+static DEFINE_MUTEX(tw_mutex);
 static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 static int tw_device_extension_count = 0;
 static int twe_major = -1;
@@ -900,10 +900,10 @@
 
 	dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
 
-	lock_kernel();
+	mutex_lock(&tw_mutex);
 	/* Only let one of these through at a time */
 	if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
-		unlock_kernel();
+		mutex_unlock(&tw_mutex);
 		return -EINTR;
 	}
 
@@ -1034,7 +1034,7 @@
 	dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
 out:
 	mutex_unlock(&tw_dev->ioctl_lock);
-	unlock_kernel();
+	mutex_unlock(&tw_mutex);
 	return retval;
 } /* End tw_chrdev_ioctl() */
 
@@ -1044,7 +1044,6 @@
 {
 	unsigned int minor_number;
 
-	cycle_kernel_lock();
 	dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n");
 
 	minor_number = iminor(inode);
@@ -1059,7 +1058,8 @@
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= tw_chrdev_ioctl,
 	.open		= tw_chrdev_open,
-	.release	= NULL
+	.release	= NULL,
+	.llseek		= noop_llseek,
 };
 
 /* This function will free up device extension resources */
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index bbf91ae..2e9632e 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -316,7 +316,8 @@
 
 config SCSI_SAS_ATTRS
 	tristate "SAS Transport Attributes"
-	depends on SCSI && BLK_DEV_BSG
+	depends on SCSI
+	select BLK_DEV_BSG
 	help
 	  If you wish to export transport-specific information about
 	  each attached SAS device to sysfs, say Y.
@@ -378,7 +379,7 @@
 	  via sysfs to userspace. If you wish to export this information,
 	  say Y. Otherwise, say N.
 
-source "drivers/scsi/cxgb3i/Kconfig"
+source "drivers/scsi/cxgbi/Kconfig"
 source "drivers/scsi/bnx2i/Kconfig"
 source "drivers/scsi/be2iscsi/Kconfig"
 
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 2703c6e..2e9a87e 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -133,7 +133,8 @@
 obj-$(CONFIG_SCSI_STEX)		+= stex.o
 obj-$(CONFIG_SCSI_MVSAS)	+= mvsas/
 obj-$(CONFIG_PS3_ROM)		+= ps3rom.o
-obj-$(CONFIG_SCSI_CXGB3_ISCSI)	+= libiscsi.o libiscsi_tcp.o cxgb3i/
+obj-$(CONFIG_SCSI_CXGB3_ISCSI)	+= libiscsi.o libiscsi_tcp.o cxgbi/
+obj-$(CONFIG_SCSI_CXGB4_ISCSI)	+= libiscsi.o libiscsi_tcp.o cxgbi/
 obj-$(CONFIG_SCSI_BNX2_ISCSI)	+= libiscsi.o bnx2i/
 obj-$(CONFIG_BE2ISCSI)		+= libiscsi.o be2iscsi/
 obj-$(CONFIG_SCSI_PMCRAID)	+= pmcraid.o
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 1a5bf57..645ddd9 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -190,7 +190,7 @@
 		/*
 		 *	Initialize the mutex used to wait for the next AIF.
 		 */
-		init_MUTEX_LOCKED(&fibctx->wait_sem);
+		sema_init(&fibctx->wait_sem, 0);
 		fibctx->wait = 0;
 		/*
 		 *	Initialize the fibs and set the count of fibs on
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 7007914..afc9aeb 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -124,7 +124,7 @@
 		fibptr->hw_fib_va = hw_fib;
 		fibptr->data = (void *) fibptr->hw_fib_va->data;
 		fibptr->next = fibptr+1;	/* Forward chain the fibs */
-		init_MUTEX_LOCKED(&fibptr->event_wait);
+		sema_init(&fibptr->event_wait, 0);
 		spin_lock_init(&fibptr->event_lock);
 		hw_fib->header.XferState = cpu_to_le32(0xffffffff);
 		hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index cad6f9a..dae46d7 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -38,7 +38,7 @@
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/syscalls.h>
 #include <linux/delay.h>
@@ -76,6 +76,7 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
 
+static DEFINE_MUTEX(aac_mutex);
 static LIST_HEAD(aac_devices);
 static int aac_cfg_major = -1;
 char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
@@ -678,7 +679,7 @@
 	unsigned minor_number = iminor(inode);
 	int err = -ENODEV;
 
-	lock_kernel();  /* BKL pushdown: nothing else protects this list */
+	mutex_lock(&aac_mutex);  /* BKL pushdown: nothing else protects this list */
 	list_for_each_entry(aac, &aac_devices, entry) {
 		if (aac->id == minor_number) {
 			file->private_data = aac;
@@ -686,7 +687,7 @@
 			break;
 		}
 	}
-	unlock_kernel();
+	mutex_unlock(&aac_mutex);
 
 	return err;
 }
@@ -711,9 +712,9 @@
 	int ret;
 	if (!capable(CAP_SYS_RAWIO))
 		return -EPERM;
-	lock_kernel();
+	mutex_lock(&aac_mutex);
 	ret = aac_do_ioctl(file->private_data, cmd, (void __user *)arg);
-	unlock_kernel();
+	mutex_unlock(&aac_mutex);
 
 	return ret;
 }
@@ -722,7 +723,7 @@
 static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&aac_mutex);
 	switch (cmd) {
 	case FSACTL_MINIPORT_REV_CHECK:
 	case FSACTL_SENDFIB:
@@ -756,7 +757,7 @@
 		ret = -ENOIOCTLCMD;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&aac_mutex);
 	return ret;
 }
 
@@ -1039,6 +1040,7 @@
 	.compat_ioctl   = aac_compat_cfg_ioctl,
 #endif
 	.open		= aac_cfg_open,
+	.llseek		= noop_llseek,
 };
 
 static struct scsi_host_template aac_driver_template = {
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 93984c9..aee73fa 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -2850,12 +2850,6 @@
       aic_dev->r_total++;
       ptr = aic_dev->r_bins;
     }
-    if(cmd->device->simple_tags && cmd->request->cmd_flags & REQ_HARDBARRIER)
-    {
-      aic_dev->barrier_total++;
-      if(scb->tag_action == MSG_ORDERED_Q_TAG)
-        aic_dev->ordered_total++;
-    }
     x = scb->sg_length;
     x >>= 10;
     for(i=0; i<6; i++)
@@ -10125,7 +10119,6 @@
   struct aic_dev_data *aic_dev = cmd->device->hostdata;
   struct scsi_device *sdptr = cmd->device;
   unsigned char tindex = TARGET_INDEX(cmd);
-  struct request *req = cmd->request;
   int use_sg;
 
   mask = (0x01 << tindex);
@@ -10144,19 +10137,8 @@
     /* We always force TEST_UNIT_READY to untagged */
     if (cmd->cmnd[0] != TEST_UNIT_READY && sdptr->simple_tags)
     {
-      if (req->cmd_flags & REQ_HARDBARRIER)
-      {
-	if(sdptr->ordered_tags)
-	{
-          hscb->control |= MSG_ORDERED_Q_TAG;
-          scb->tag_action = MSG_ORDERED_Q_TAG;
-	}
-      }
-      else
-      {
-        hscb->control |= MSG_SIMPLE_Q_TAG;
-        scb->tag_action = MSG_SIMPLE_Q_TAG;
-      }
+      hscb->control |= MSG_SIMPLE_Q_TAG;
+      scb->tag_action = MSG_SIMPLE_Q_TAG;
     }
   }
   if ( !(aic_dev->dtr_pending) &&
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index c8dc392..05a78e5 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -878,8 +878,8 @@
 	if (!error) {
 		if (acb->devstate[id][lun] == ARECA_RAID_GONE)
 			acb->devstate[id][lun] = ARECA_RAID_GOOD;
-			ccb->pcmd->result = DID_OK << 16;
-			arcmsr_ccb_complete(ccb);
+		ccb->pcmd->result = DID_OK << 16;
+		arcmsr_ccb_complete(ccb);
 	}else{
 		switch (ccb->arcmsr_cdb.DeviceStatus) {
 		case ARCMSR_DEV_SELECT_TIMEOUT: {
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index 7c75373..ad24636 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -335,7 +335,7 @@
 		if (ready)
 			break;
 
-		if (cnt > 6000000) {
+		if (cnt > 12000000) {
 			dev_err(&ctrl->pdev->dev, "mbox_db poll timed out\n");
 			return -EBUSY;
 		}
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index 7f11f3e..eaaa881 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -522,7 +522,6 @@
 	if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
 				  phba->params.cxns_per_ctrl * 2)) {
 		SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
-		beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
 		goto free_ep;
 	}
 
@@ -559,7 +558,6 @@
 		SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed"
 				    " status = %d extd_status = %d\n",
 				    status, extd_status);
-		beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
 		free_mcc_tag(&phba->ctrl, tag);
 		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 			    nonemb_cmd.va, nonemb_cmd.dma);
@@ -574,7 +572,6 @@
 		beiscsi_ep->cid_vld = 1;
 		SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
 	}
-	beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
 	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 			    nonemb_cmd.va, nonemb_cmd.dma);
 	return 0;
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 8220bde..75a85aa 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -2040,7 +2040,7 @@
 	      unsigned int num_sg, struct beiscsi_io_task *io_task)
 {
 	struct iscsi_sge *psgl;
-	unsigned short sg_len, index;
+	unsigned int sg_len, index;
 	unsigned int sge_len = 0;
 	unsigned long long addr;
 	struct scatterlist *l_sg;
diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile
index ac3fdf0..d2eefd3 100644
--- a/drivers/scsi/bfa/Makefile
+++ b/drivers/scsi/bfa/Makefile
@@ -1,15 +1,8 @@
 obj-$(CONFIG_SCSI_BFA_FC) := bfa.o
 
-bfa-y := bfad.o bfad_intr.o bfad_os.o bfad_im.o bfad_attr.o bfad_fwimg.o
-bfa-y += bfad_debugfs.o
-bfa-y += bfa_core.o bfa_ioc.o bfa_ioc_ct.o bfa_ioc_cb.o bfa_iocfc.o bfa_fcxp.o
-bfa-y += bfa_lps.o bfa_hw_cb.o bfa_hw_ct.o bfa_intr.o bfa_timer.o bfa_rport.o
-bfa-y += bfa_fcport.o bfa_port.o bfa_uf.o bfa_sgpg.o bfa_module.o bfa_ioim.o
-bfa-y += bfa_itnim.o bfa_fcpim.o bfa_tskim.o bfa_log.o bfa_log_module.o
-bfa-y += bfa_csdebug.o bfa_sm.o plog.o
+bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o
+bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o
+bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o
+bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_drv.o bfa_svc.o
 
-bfa-y += fcbuild.o fabric.o fcpim.o vfapi.o fcptm.o bfa_fcs.o bfa_fcs_port.o
-bfa-y += bfa_fcs_uf.o bfa_fcs_lport.o fab.o fdmi.o ms.o ns.o scn.o loop.o
-bfa-y += lport_api.o n2n.o rport.o rport_api.o rport_ftrs.o vport.o
-
-ccflags-y := -I$(obj) -I$(obj)/include -I$(obj)/include/cna -DBFA_PERF_BUILD
+ccflags-y := -DBFA_PERF_BUILD
diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h
new file mode 100644
index 0000000..ceaac65
--- /dev/null
+++ b/drivers/scsi/bfa/bfa.h
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_H__
+#define __BFA_H__
+
+#include "bfa_os_inc.h"
+#include "bfa_cs.h"
+#include "bfa_plog.h"
+#include "bfa_defs_svc.h"
+#include "bfi.h"
+#include "bfa_ioc.h"
+
+struct bfa_s;
+
+typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
+typedef void    (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
+
+/**
+ * Interrupt message handlers
+ */
+void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
+void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
+
+/**
+ * Request and response queue related defines
+ */
+#define BFA_REQQ_NELEMS_MIN	(4)
+#define BFA_RSPQ_NELEMS_MIN	(4)
+
+#define bfa_reqq_pi(__bfa, __reqq)	((__bfa)->iocfc.req_cq_pi[__reqq])
+#define bfa_reqq_ci(__bfa, __reqq)					\
+	(*(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva))
+
+#define bfa_reqq_full(__bfa, __reqq)				\
+	(((bfa_reqq_pi(__bfa, __reqq) + 1) &			\
+	  ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1)) ==	\
+	 bfa_reqq_ci(__bfa, __reqq))
+
+#define bfa_reqq_next(__bfa, __reqq)					\
+	(bfa_reqq_full(__bfa, __reqq) ? NULL :				\
+	 ((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
+		   + bfa_reqq_pi((__bfa), (__reqq)))))
+
+#define bfa_reqq_produce(__bfa, __reqq)	do {				\
+		(__bfa)->iocfc.req_cq_pi[__reqq]++;			\
+		(__bfa)->iocfc.req_cq_pi[__reqq] &=			\
+			((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1);      \
+		bfa_reg_write((__bfa)->iocfc.bfa_regs.cpe_q_pi[__reqq],	\
+			      (__bfa)->iocfc.req_cq_pi[__reqq]);      \
+		mmiowb();      \
+	} while (0)
+
+#define bfa_rspq_pi(__bfa, __rspq)					\
+	(*(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva))
+
+#define bfa_rspq_ci(__bfa, __rspq)	((__bfa)->iocfc.rsp_cq_ci[__rspq])
+#define bfa_rspq_elem(__bfa, __rspq, __ci)				\
+	(&((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci])
+
+#define CQ_INCR(__index, __size) do {			\
+	(__index)++;					\
+	(__index) &= ((__size) - 1);			\
+} while (0)
+
+/**
+ * Queue element to wait for room in request queue. FIFO order is
+ * maintained when fullfilling requests.
+ */
+struct bfa_reqq_wait_s {
+	struct list_head	qe;
+	void		(*qresume) (void *cbarg);
+	void		*cbarg;
+};
+
+/**
+ * Circular queue usage assignments
+ */
+enum {
+	BFA_REQQ_IOC	= 0,	/*  all low-priority IOC msgs	*/
+	BFA_REQQ_FCXP	= 0,	/*  all FCXP messages		*/
+	BFA_REQQ_LPS	= 0,	/*  all lport service msgs	*/
+	BFA_REQQ_PORT	= 0,	/*  all port messages		*/
+	BFA_REQQ_FLASH	= 0,	/*  for flash module		*/
+	BFA_REQQ_DIAG	= 0,	/*  for diag module		*/
+	BFA_REQQ_RPORT	= 0,	/*  all port messages		*/
+	BFA_REQQ_SBOOT	= 0,	/*  all san boot messages	*/
+	BFA_REQQ_QOS_LO	= 1,	/*  all low priority IO	*/
+	BFA_REQQ_QOS_MD	= 2,	/*  all medium priority IO	*/
+	BFA_REQQ_QOS_HI	= 3,	/*  all high priority IO	*/
+};
+
+static inline void
+bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
+	       void *cbarg)
+{
+	wqe->qresume = qresume;
+	wqe->cbarg = cbarg;
+}
+
+#define bfa_reqq(__bfa, __reqq)	(&(__bfa)->reqq_waitq[__reqq])
+
+/**
+ * static inline void
+ * bfa_reqq_wait(struct bfa_s *bfa, int reqq, struct bfa_reqq_wait_s *wqe)
+ */
+#define bfa_reqq_wait(__bfa, __reqq, __wqe) do {			\
+									\
+		struct list_head *waitq = bfa_reqq(__bfa, __reqq);      \
+									\
+		bfa_assert(((__reqq) < BFI_IOC_MAX_CQS));      \
+		bfa_assert((__wqe)->qresume && (__wqe)->cbarg);      \
+									\
+		list_add_tail(&(__wqe)->qe, waitq);      \
+	} while (0)
+
+#define bfa_reqq_wcancel(__wqe)	list_del(&(__wqe)->qe)
+
+
+/**
+ * Generic BFA callback element.
+ */
+struct bfa_cb_qe_s {
+	struct list_head         qe;
+	bfa_cb_cbfn_t  cbfn;
+	bfa_boolean_t   once;
+	u32		rsvd;
+	void           *cbarg;
+};
+
+#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do {	\
+		(__hcb_qe)->cbfn  = (__cbfn);      \
+		(__hcb_qe)->cbarg = (__cbarg);      \
+		list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);      \
+	} while (0)
+
+#define bfa_cb_dequeue(__hcb_qe)	list_del(&(__hcb_qe)->qe)
+
+#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do {	\
+		(__hcb_qe)->cbfn  = (__cbfn);      \
+		(__hcb_qe)->cbarg = (__cbarg);      \
+		if (!(__hcb_qe)->once) {      \
+			list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);      \
+			(__hcb_qe)->once = BFA_TRUE;			\
+		}							\
+	} while (0)
+
+#define bfa_cb_queue_done(__hcb_qe) do {	\
+		(__hcb_qe)->once = BFA_FALSE;	\
+	} while (0)
+
+
+/**
+ * PCI devices supported by the current BFA
+ */
+struct bfa_pciid_s {
+	u16	device_id;
+	u16	vendor_id;
+};
+
+extern char     bfa_version[];
+
+/**
+ * BFA memory resources
+ */
+enum bfa_mem_type {
+	BFA_MEM_TYPE_KVA = 1,	/*  Kernel Virtual Memory *(non-dma-able) */
+	BFA_MEM_TYPE_DMA = 2,	/*  DMA-able memory */
+	BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA,
+};
+
+struct bfa_mem_elem_s {
+	enum bfa_mem_type mem_type;	/* see enum bfa_mem_type */
+	u32	mem_len;	/*  Total Length in Bytes	*/
+	u8		*kva;		/*  kernel virtual address	*/
+	u64	dma;		/*  dma address if DMA memory	*/
+	u8		*kva_curp;	/*  kva allocation cursor	*/
+	u64	dma_curp;	/*  dma allocation cursor	*/
+};
+
+struct bfa_meminfo_s {
+	struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
+};
+#define bfa_meminfo_kva(_m)				\
+	((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp)
+#define bfa_meminfo_dma_virt(_m)			\
+	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp)
+#define bfa_meminfo_dma_phys(_m)			\
+	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp)
+
+struct bfa_iocfc_regs_s {
+	bfa_os_addr_t   intr_status;
+	bfa_os_addr_t   intr_mask;
+	bfa_os_addr_t   cpe_q_pi[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   cpe_q_ci[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   cpe_q_depth[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   cpe_q_ctrl[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   rme_q_ci[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   rme_q_pi[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   rme_q_depth[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   rme_q_ctrl[BFI_IOC_MAX_CQS];
+};
+
+/**
+ * MSIX vector handlers
+ */
+#define BFA_MSIX_MAX_VECTORS	22
+typedef void (*bfa_msix_handler_t)(struct bfa_s *bfa, int vec);
+struct bfa_msix_s {
+	int	nvecs;
+	bfa_msix_handler_t handler[BFA_MSIX_MAX_VECTORS];
+};
+
+/**
+ * Chip specific interfaces
+ */
+struct bfa_hwif_s {
+	void (*hw_reginit)(struct bfa_s *bfa);
+	void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
+	void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
+	void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
+	void (*hw_msix_install)(struct bfa_s *bfa);
+	void (*hw_msix_uninstall)(struct bfa_s *bfa);
+	void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
+	void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
+				u32 *nvecs, u32 *maxvec);
+	void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,
+				       u32 *end);
+};
+typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
+
+struct bfa_iocfc_s {
+	struct bfa_s		*bfa;
+	struct bfa_iocfc_cfg_s	cfg;
+	int			action;
+	u32		req_cq_pi[BFI_IOC_MAX_CQS];
+	u32		rsp_cq_ci[BFI_IOC_MAX_CQS];
+	struct bfa_cb_qe_s	init_hcb_qe;
+	struct bfa_cb_qe_s	stop_hcb_qe;
+	struct bfa_cb_qe_s	dis_hcb_qe;
+	struct bfa_cb_qe_s	stats_hcb_qe;
+	bfa_boolean_t		cfgdone;
+
+	struct bfa_dma_s	cfg_info;
+	struct bfi_iocfc_cfg_s *cfginfo;
+	struct bfa_dma_s	cfgrsp_dma;
+	struct bfi_iocfc_cfgrsp_s *cfgrsp;
+	struct bfi_iocfc_cfg_reply_s *cfg_reply;
+	struct bfa_dma_s	req_cq_ba[BFI_IOC_MAX_CQS];
+	struct bfa_dma_s	req_cq_shadow_ci[BFI_IOC_MAX_CQS];
+	struct bfa_dma_s	rsp_cq_ba[BFI_IOC_MAX_CQS];
+	struct bfa_dma_s	rsp_cq_shadow_pi[BFI_IOC_MAX_CQS];
+	struct bfa_iocfc_regs_s	bfa_regs;	/*  BFA device registers */
+	struct bfa_hwif_s	hwif;
+	bfa_cb_iocfc_t		updateq_cbfn; /*  bios callback function */
+	void			*updateq_cbarg;	/*  bios callback arg */
+	u32	intr_mask;
+};
+
+#define bfa_lpuid(__bfa)						\
+	bfa_ioc_portid(&(__bfa)->ioc)
+#define bfa_msix_init(__bfa, __nvecs)					\
+	((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs))
+#define bfa_msix_install(__bfa)						\
+	((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
+#define bfa_msix_uninstall(__bfa)					\
+	((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
+#define bfa_isr_mode_set(__bfa, __msix)					\
+	((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
+#define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec)		\
+	((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap,		\
+					__nvecs, __maxvec))
+#define bfa_msix_get_rme_range(__bfa, __start, __end)			\
+	((__bfa)->iocfc.hwif.hw_msix_get_rme_range(__bfa, __start, __end))
+#define bfa_msix(__bfa, __vec)						\
+	((__bfa)->msix.handler[__vec](__bfa, __vec))
+
+/*
+ * FC specific IOC functions.
+ */
+void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+		       u32 *dm_len);
+void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
+		      struct bfa_iocfc_cfg_s *cfg,
+		      struct bfa_meminfo_s *meminfo,
+		      struct bfa_pcidev_s *pcidev);
+void bfa_iocfc_detach(struct bfa_s *bfa);
+void bfa_iocfc_init(struct bfa_s *bfa);
+void bfa_iocfc_start(struct bfa_s *bfa);
+void bfa_iocfc_stop(struct bfa_s *bfa);
+void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
+void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
+bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
+void bfa_iocfc_reset_queues(struct bfa_s *bfa);
+
+void bfa_msix_all(struct bfa_s *bfa, int vec);
+void bfa_msix_reqq(struct bfa_s *bfa, int vec);
+void bfa_msix_rspq(struct bfa_s *bfa, int vec);
+void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
+
+void bfa_hwcb_reginit(struct bfa_s *bfa);
+void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
+void bfa_hwcb_msix_install(struct bfa_s *bfa);
+void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
+void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
+void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
+			   u32 *maxvec);
+void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
+				 u32 *end);
+void bfa_hwct_reginit(struct bfa_s *bfa);
+void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
+void bfa_hwct_msix_install(struct bfa_s *bfa);
+void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
+void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
+void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
+			   u32 *maxvec);
+void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
+				 u32 *end);
+void bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi);
+void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns);
+wwn_t bfa_iocfc_get_pwwn(struct bfa_s *bfa);
+wwn_t bfa_iocfc_get_nwwn(struct bfa_s *bfa);
+void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa,
+				struct bfa_boot_pbc_s *pbcfg);
+int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,
+				struct bfi_pbc_vport_s *pbc_vport);
+
+
+/**
+ *----------------------------------------------------------------------
+ *		BFA public interfaces
+ *----------------------------------------------------------------------
+ */
+#define bfa_stats(_mod, _stats)	((_mod)->stats._stats++)
+#define bfa_ioc_get_stats(__bfa, __ioc_stats)		\
+	bfa_ioc_fetch_stats(&(__bfa)->ioc, __ioc_stats)
+#define bfa_ioc_clear_stats(__bfa)		\
+	bfa_ioc_clr_stats(&(__bfa)->ioc)
+#define bfa_get_nports(__bfa)			\
+	bfa_ioc_get_nports(&(__bfa)->ioc)
+#define bfa_get_adapter_manufacturer(__bfa, __manufacturer)		\
+	bfa_ioc_get_adapter_manufacturer(&(__bfa)->ioc, __manufacturer)
+#define bfa_get_adapter_model(__bfa, __model)			\
+	bfa_ioc_get_adapter_model(&(__bfa)->ioc, __model)
+#define bfa_get_adapter_serial_num(__bfa, __serial_num)			\
+	bfa_ioc_get_adapter_serial_num(&(__bfa)->ioc, __serial_num)
+#define bfa_get_adapter_fw_ver(__bfa, __fw_ver)			\
+	bfa_ioc_get_adapter_fw_ver(&(__bfa)->ioc, __fw_ver)
+#define bfa_get_adapter_optrom_ver(__bfa, __optrom_ver)			\
+	bfa_ioc_get_adapter_optrom_ver(&(__bfa)->ioc, __optrom_ver)
+#define bfa_get_pci_chip_rev(__bfa, __chip_rev)			\
+	bfa_ioc_get_pci_chip_rev(&(__bfa)->ioc, __chip_rev)
+#define bfa_get_ioc_state(__bfa)		\
+	bfa_ioc_get_state(&(__bfa)->ioc)
+#define bfa_get_type(__bfa)			\
+	bfa_ioc_get_type(&(__bfa)->ioc)
+#define bfa_get_mac(__bfa)			\
+	bfa_ioc_get_mac(&(__bfa)->ioc)
+#define bfa_get_mfg_mac(__bfa)			\
+	bfa_ioc_get_mfg_mac(&(__bfa)->ioc)
+#define bfa_get_fw_clock_res(__bfa)		\
+	((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res)
+
+void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
+void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
+void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
+void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
+			 struct bfa_meminfo_s *meminfo);
+void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		struct bfa_meminfo_s *meminfo,
+		struct bfa_pcidev_s *pcidev);
+void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod);
+void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog);
+void bfa_detach(struct bfa_s *bfa);
+void bfa_init(struct bfa_s *bfa);
+void bfa_start(struct bfa_s *bfa);
+void bfa_stop(struct bfa_s *bfa);
+void bfa_attach_fcs(struct bfa_s *bfa);
+void bfa_cb_init(void *bfad, bfa_status_t status);
+void bfa_cb_updateq(void *bfad, bfa_status_t status);
+
+bfa_boolean_t bfa_intx(struct bfa_s *bfa);
+void bfa_intx_disable(struct bfa_s *bfa);
+void bfa_intx_enable(struct bfa_s *bfa);
+void bfa_isr_enable(struct bfa_s *bfa);
+void bfa_isr_disable(struct bfa_s *bfa);
+
+void bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q);
+void bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q);
+void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q);
+
+typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status);
+void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr);
+void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr);
+
+void bfa_adapter_get_attr(struct bfa_s *bfa,
+			  struct bfa_adapter_attr_s *ad_attr);
+u64 bfa_adapter_get_id(struct bfa_s *bfa);
+
+bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,
+				   struct bfa_iocfc_intr_attr_s *attr);
+
+void bfa_iocfc_enable(struct bfa_s *bfa);
+void bfa_iocfc_disable(struct bfa_s *bfa);
+void bfa_chip_reset(struct bfa_s *bfa);
+void bfa_timer_tick(struct bfa_s *bfa);
+#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout)		\
+	bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
+
+/*
+ * BFA debug API functions
+ */
+bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen);
+bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen);
+bfa_status_t bfa_debug_fwcore(struct bfa_s *bfa, void *buf,
+			      u32 *offset, int *buflen);
+void bfa_debug_fwsave_clear(struct bfa_s *bfa);
+bfa_status_t bfa_fw_stats_get(struct bfa_s *bfa, void *data);
+bfa_status_t bfa_fw_stats_clear(struct bfa_s *bfa);
+
+#endif /* __BFA_H__ */
diff --git a/drivers/scsi/bfa/bfa_callback_priv.h b/drivers/scsi/bfa/bfa_callback_priv.h
deleted file mode 100644
index 1e3265c..0000000
--- a/drivers/scsi/bfa/bfa_callback_priv.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_CALLBACK_PRIV_H__
-#define __BFA_CALLBACK_PRIV_H__
-
-#include <cs/bfa_q.h>
-
-typedef void    (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
-
-/**
- * Generic BFA callback element.
- */
-struct bfa_cb_qe_s {
-	struct list_head         qe;
-	bfa_cb_cbfn_t  cbfn;
-	bfa_boolean_t   once;
-	u32		rsvd;
-	void           *cbarg;
-};
-
-#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do {		\
-	(__hcb_qe)->cbfn  = (__cbfn);      \
-	(__hcb_qe)->cbarg = (__cbarg);      \
-	list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);      \
-} while (0)
-
-#define bfa_cb_dequeue(__hcb_qe)	list_del(&(__hcb_qe)->qe)
-
-#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do {	\
-	(__hcb_qe)->cbfn  = (__cbfn);      \
-	(__hcb_qe)->cbarg = (__cbarg);      \
-	if (!(__hcb_qe)->once) {      \
-		list_add_tail((__hcb_qe), &(__bfa)->comp_q);      \
-		(__hcb_qe)->once = BFA_TRUE;				\
-	}								\
-} while (0)
-
-#define bfa_cb_queue_done(__hcb_qe) do {				\
-	(__hcb_qe)->once = BFA_FALSE;					\
-} while (0)
-
-#endif /* __BFA_CALLBACK_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_cb_ioim.h b/drivers/scsi/bfa/bfa_cb_ioim.h
new file mode 100644
index 0000000..a989a94
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_cb_ioim.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_HCB_IOIM_H__
+#define __BFA_HCB_IOIM_H__
+
+#include "bfa_os_inc.h"
+/*
+ * task attribute values in FCP-2 FCP_CMND IU
+ */
+#define SIMPLE_Q    0
+#define HEAD_OF_Q   1
+#define ORDERED_Q   2
+#define ACA_Q	    4
+#define UNTAGGED    5
+
+static inline lun_t
+bfad_int_to_lun(u32 luno)
+{
+	union {
+		u16	scsi_lun[4];
+		lun_t		bfa_lun;
+	} lun;
+
+	lun.bfa_lun     = 0;
+	lun.scsi_lun[0] = bfa_os_htons(luno);
+
+	return lun.bfa_lun;
+}
+
+/**
+ * Get LUN for the I/O request
+ */
+#define bfa_cb_ioim_get_lun(__dio)	\
+	bfad_int_to_lun(((struct scsi_cmnd *)__dio)->device->lun)
+
+/**
+ * Get CDB for the I/O request
+ */
+static inline u8 *
+bfa_cb_ioim_get_cdb(struct bfad_ioim_s *dio)
+{
+	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+
+	return (u8 *) cmnd->cmnd;
+}
+
+/**
+ * Get I/O direction (read/write) for the I/O request
+ */
+static inline enum fcp_iodir
+bfa_cb_ioim_get_iodir(struct bfad_ioim_s *dio)
+{
+	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+	enum dma_data_direction dmadir;
+
+	dmadir = cmnd->sc_data_direction;
+	if (dmadir == DMA_TO_DEVICE)
+		return FCP_IODIR_WRITE;
+	else if (dmadir == DMA_FROM_DEVICE)
+		return FCP_IODIR_READ;
+	else
+		return FCP_IODIR_NONE;
+}
+
+/**
+ * Get IO size in bytes for the I/O request
+ */
+static inline u32
+bfa_cb_ioim_get_size(struct bfad_ioim_s *dio)
+{
+	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+
+	return scsi_bufflen(cmnd);
+}
+
+/**
+ * Get timeout for the I/O request
+ */
+static inline u8
+bfa_cb_ioim_get_timeout(struct bfad_ioim_s *dio)
+{
+	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+	/*
+	 * TBD: need a timeout for scsi passthru
+	 */
+	if (cmnd->device->host == NULL)
+		return 4;
+
+	return 0;
+}
+
+/**
+ * Get Command Reference Number for the I/O request. 0 if none.
+ */
+static inline u8
+bfa_cb_ioim_get_crn(struct bfad_ioim_s *dio)
+{
+	return 0;
+}
+
+/**
+ * Get SAM-3 priority for the I/O request. 0 is default.
+ */
+static inline u8
+bfa_cb_ioim_get_priority(struct bfad_ioim_s *dio)
+{
+	return 0;
+}
+
+/**
+ * Get task attributes for the I/O request. Default is FCP_TASK_ATTR_SIMPLE(0).
+ */
+static inline u8
+bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio)
+{
+	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+	u8	task_attr = UNTAGGED;
+
+	if (cmnd->device->tagged_supported) {
+		switch (cmnd->tag) {
+		case HEAD_OF_QUEUE_TAG:
+			task_attr = HEAD_OF_Q;
+			break;
+		case ORDERED_QUEUE_TAG:
+			task_attr = ORDERED_Q;
+			break;
+		default:
+			task_attr = SIMPLE_Q;
+			break;
+		}
+	}
+
+	return task_attr;
+}
+
+/**
+ * Get CDB length in bytes for the I/O request. Default is FCP_CMND_CDB_LEN(16).
+ */
+static inline u8
+bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio)
+{
+	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+
+	return cmnd->cmd_len;
+}
+
+/**
+ * Assign queue to be used for the I/O request. This value depends on whether
+ * the driver wants to use the queues via any specific algorithm. Currently,
+ * this is not supported.
+ */
+#define bfa_cb_ioim_get_reqq(__dio) BFA_FALSE
+
+#endif /* __BFA_HCB_IOIM_H__ */
diff --git a/drivers/scsi/bfa/bfa_cb_ioim_macros.h b/drivers/scsi/bfa/bfa_cb_ioim_macros.h
deleted file mode 100644
index 3906ed9..0000000
--- a/drivers/scsi/bfa/bfa_cb_ioim_macros.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_cb_ioim_macros.h BFA IOIM driver interface macros.
- */
-
-#ifndef __BFA_HCB_IOIM_MACROS_H__
-#define __BFA_HCB_IOIM_MACROS_H__
-
-#include <bfa_os_inc.h>
-/*
- * #include <linux/dma-mapping.h>
- *
- * #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include
- * <scsi/scsi_device.h> #include <scsi/scsi_host.h>
- */
-#include "bfad_im_compat.h"
-
-/*
- * task attribute values in FCP-2 FCP_CMND IU
- */
-#define SIMPLE_Q    0
-#define HEAD_OF_Q   1
-#define ORDERED_Q   2
-#define ACA_Q       4
-#define UNTAGGED    5
-
-static inline lun_t
-bfad_int_to_lun(u32 luno)
-{
-	union {
-		u16        scsi_lun[4];
-		lun_t           bfa_lun;
-	} lun;
-
-	lun.bfa_lun     = 0;
-	lun.scsi_lun[0] = bfa_os_htons(luno);
-
-	return lun.bfa_lun;
-}
-
-/**
- * Get LUN for the I/O request
- */
-#define bfa_cb_ioim_get_lun(__dio)	\
-	bfad_int_to_lun(((struct scsi_cmnd *)__dio)->device->lun)
-
-/**
- * Get CDB for the I/O request
- */
-static inline u8 *
-bfa_cb_ioim_get_cdb(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-
-	return (u8 *) cmnd->cmnd;
-}
-
-/**
- * Get I/O direction (read/write) for the I/O request
- */
-static inline enum fcp_iodir
-bfa_cb_ioim_get_iodir(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-	enum dma_data_direction dmadir;
-
-	dmadir = cmnd->sc_data_direction;
-	if (dmadir == DMA_TO_DEVICE)
-		return FCP_IODIR_WRITE;
-	else if (dmadir == DMA_FROM_DEVICE)
-		return FCP_IODIR_READ;
-	else
-		return FCP_IODIR_NONE;
-}
-
-/**
- * Get IO size in bytes for the I/O request
- */
-static inline u32
-bfa_cb_ioim_get_size(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-
-	return scsi_bufflen(cmnd);
-}
-
-/**
- * Get timeout for the I/O request
- */
-static inline u8
-bfa_cb_ioim_get_timeout(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-	/*
-	 * TBD: need a timeout for scsi passthru
-	 */
-	if (cmnd->device->host == NULL)
-		return 4;
-
-	return 0;
-}
-
-/**
- * Get Command Reference Number for the I/O request. 0 if none.
- */
-static inline u8
-bfa_cb_ioim_get_crn(struct bfad_ioim_s *dio)
-{
-	return 0;
-}
-
-/**
- * Get SAM-3 priority for the I/O request. 0 is default.
- */
-static inline u8
-bfa_cb_ioim_get_priority(struct bfad_ioim_s *dio)
-{
-	return 0;
-}
-
-/**
- * Get task attributes for the I/O request. Default is FCP_TASK_ATTR_SIMPLE(0).
- */
-static inline u8
-bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-	u8         task_attr = UNTAGGED;
-
-	if (cmnd->device->tagged_supported) {
-		switch (cmnd->tag) {
-		case HEAD_OF_QUEUE_TAG:
-			task_attr = HEAD_OF_Q;
-			break;
-		case ORDERED_QUEUE_TAG:
-			task_attr = ORDERED_Q;
-			break;
-		default:
-			task_attr = SIMPLE_Q;
-			break;
-		}
-	}
-
-	return task_attr;
-}
-
-/**
- * Get CDB length in bytes for the I/O request. Default is FCP_CMND_CDB_LEN(16).
- */
-static inline u8
-bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-
-	return cmnd->cmd_len;
-}
-
-/**
- * Assign queue to be used for the I/O request. This value depends on whether
- * the driver wants to use the queues via any specific algorithm. Currently,
- * this is not supported.
- */
-#define bfa_cb_ioim_get_reqq(__dio) BFA_FALSE
-
-#endif /* __BFA_HCB_IOIM_MACROS_H__ */
diff --git a/drivers/scsi/bfa/bfa_cee.c b/drivers/scsi/bfa/bfa_cee.c
deleted file mode 100644
index 2b91779..0000000
--- a/drivers/scsi/bfa/bfa_cee.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <defs/bfa_defs_cee.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-#include <cs/bfa_debug.h>
-#include <cee/bfa_cee.h>
-#include <bfi/bfi_cee.h>
-#include <bfi/bfi.h>
-#include <bfa_ioc.h>
-#include <cna/bfa_cna_trcmod.h>
-
-BFA_TRC_FILE(CNA, CEE);
-
-#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
-#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
-
-static void     bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg);
-static void     bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s
-					   *dcbcx_stats);
-static void     bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s
-					  *lldp_stats);
-static void     bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats);
-static void     bfa_cee_format_cee_cfg(void *buffer);
-static void     bfa_cee_format_cee_stats(void *buffer);
-
-static void
-bfa_cee_format_cee_stats(void *buffer)
-{
-	struct bfa_cee_stats_s *cee_stats = buffer;
-	bfa_cee_format_dcbcx_stats(&cee_stats->dcbx_stats);
-	bfa_cee_format_lldp_stats(&cee_stats->lldp_stats);
-	bfa_cee_format_cfg_stats(&cee_stats->cfg_stats);
-}
-
-static void
-bfa_cee_format_cee_cfg(void *buffer)
-{
-	struct bfa_cee_attr_s *cee_cfg = buffer;
-	bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote);
-}
-
-static void
-bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s *dcbcx_stats)
-{
-	dcbcx_stats->subtlvs_unrecognized =
-		bfa_os_ntohl(dcbcx_stats->subtlvs_unrecognized);
-	dcbcx_stats->negotiation_failed =
-		bfa_os_ntohl(dcbcx_stats->negotiation_failed);
-	dcbcx_stats->remote_cfg_changed =
-		bfa_os_ntohl(dcbcx_stats->remote_cfg_changed);
-	dcbcx_stats->tlvs_received = bfa_os_ntohl(dcbcx_stats->tlvs_received);
-	dcbcx_stats->tlvs_invalid = bfa_os_ntohl(dcbcx_stats->tlvs_invalid);
-	dcbcx_stats->seqno = bfa_os_ntohl(dcbcx_stats->seqno);
-	dcbcx_stats->ackno = bfa_os_ntohl(dcbcx_stats->ackno);
-	dcbcx_stats->recvd_seqno = bfa_os_ntohl(dcbcx_stats->recvd_seqno);
-	dcbcx_stats->recvd_ackno = bfa_os_ntohl(dcbcx_stats->recvd_ackno);
-}
-
-static void
-bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s *lldp_stats)
-{
-	lldp_stats->frames_transmitted =
-		bfa_os_ntohl(lldp_stats->frames_transmitted);
-	lldp_stats->frames_aged_out = bfa_os_ntohl(lldp_stats->frames_aged_out);
-	lldp_stats->frames_discarded =
-		bfa_os_ntohl(lldp_stats->frames_discarded);
-	lldp_stats->frames_in_error = bfa_os_ntohl(lldp_stats->frames_in_error);
-	lldp_stats->frames_rcvd = bfa_os_ntohl(lldp_stats->frames_rcvd);
-	lldp_stats->tlvs_discarded = bfa_os_ntohl(lldp_stats->tlvs_discarded);
-	lldp_stats->tlvs_unrecognized =
-		bfa_os_ntohl(lldp_stats->tlvs_unrecognized);
-}
-
-static void
-bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats)
-{
-	cfg_stats->cee_status_down = bfa_os_ntohl(cfg_stats->cee_status_down);
-	cfg_stats->cee_status_up = bfa_os_ntohl(cfg_stats->cee_status_up);
-	cfg_stats->cee_hw_cfg_changed =
-		bfa_os_ntohl(cfg_stats->cee_hw_cfg_changed);
-	cfg_stats->recvd_invalid_cfg =
-		bfa_os_ntohl(cfg_stats->recvd_invalid_cfg);
-}
-
-static void
-bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg)
-{
-	lldp_cfg->time_to_interval = bfa_os_ntohs(lldp_cfg->time_to_interval);
-	lldp_cfg->enabled_system_cap =
-		bfa_os_ntohs(lldp_cfg->enabled_system_cap);
-}
-
-/**
- * bfa_cee_attr_meminfo()
- *
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-static          u32
-bfa_cee_attr_meminfo(void)
-{
-	return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
-}
-
-/**
- * bfa_cee_stats_meminfo()
- *
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-static          u32
-bfa_cee_stats_meminfo(void)
-{
-	return BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- *
- * @param[in] cee - Pointer to the CEE module
- *            status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status)
-{
-	cee->get_attr_status = status;
-	bfa_trc(cee, 0);
-	if (status == BFA_STATUS_OK) {
-		bfa_trc(cee, 0);
-		/*
-		 * The requested data has been copied to the DMA area, *process
-		 * it.
-		 */
-		memcpy(cee->attr, cee->attr_dma.kva,
-		       sizeof(struct bfa_cee_attr_s));
-		bfa_cee_format_cee_cfg(cee->attr);
-	}
-	cee->get_attr_pending = BFA_FALSE;
-	if (cee->cbfn.get_attr_cbfn) {
-		bfa_trc(cee, 0);
-		cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
-	}
-	bfa_trc(cee, 0);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- *
- * @param[in] cee - Pointer to the CEE module
- *            status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
-{
-	cee->get_stats_status = status;
-	bfa_trc(cee, 0);
-	if (status == BFA_STATUS_OK) {
-		bfa_trc(cee, 0);
-		/*
-		 * The requested data has been copied to the DMA area, process
-		 * it.
-		 */
-		memcpy(cee->stats, cee->stats_dma.kva,
-		       sizeof(struct bfa_cee_stats_s));
-		bfa_cee_format_cee_stats(cee->stats);
-	}
-	cee->get_stats_pending = BFA_FALSE;
-	bfa_trc(cee, 0);
-	if (cee->cbfn.get_stats_cbfn) {
-		bfa_trc(cee, 0);
-		cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
-	}
-	bfa_trc(cee, 0);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- *
- * @param[in] cee - Pointer to the CEE module
- *            status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
-{
-	cee->reset_stats_status = status;
-	cee->reset_stats_pending = BFA_FALSE;
-	if (cee->cbfn.reset_stats_cbfn)
-		cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
-}
-
-/**
- * bfa_cee_meminfo()
- *
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-u32
-bfa_cee_meminfo(void)
-{
-	return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo();
-}
-
-/**
- * bfa_cee_mem_claim()
- *
- *
- * @param[in] cee CEE module pointer
- * 	      dma_kva Kernel Virtual Address of CEE DMA Memory
- * 	      dma_pa  Physical Address of CEE DMA Memory
- *
- * @return void
- */
-void
-bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa)
-{
-	cee->attr_dma.kva = dma_kva;
-	cee->attr_dma.pa = dma_pa;
-	cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo();
-	cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo();
-	cee->attr = (struct bfa_cee_attr_s *)dma_kva;
-	cee->stats =
-		(struct bfa_cee_stats_s *)(dma_kva + bfa_cee_attr_meminfo());
-}
-
-/**
- * bfa_cee_get_attr()
- *
- *   Send the request to the f/w to fetch CEE attributes.
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return Status
- */
-
-bfa_status_t
-bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr,
-		 bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
-{
-	struct bfi_cee_get_req_s *cmd;
-
-	bfa_assert((cee != NULL) && (cee->ioc != NULL));
-	bfa_trc(cee, 0);
-	if (!bfa_ioc_is_operational(cee->ioc)) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_IOC_FAILURE;
-	}
-	if (cee->get_attr_pending == BFA_TRUE) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_DEVBUSY;
-	}
-	cee->get_attr_pending = BFA_TRUE;
-	cmd = (struct bfi_cee_get_req_s *)cee->get_cfg_mb.msg;
-	cee->attr = attr;
-	cee->cbfn.get_attr_cbfn = cbfn;
-	cee->cbfn.get_attr_cbarg = cbarg;
-	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
-		    bfa_ioc_portid(cee->ioc));
-	bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
-	bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb);
-	bfa_trc(cee, 0);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * bfa_cee_get_stats()
- *
- *   Send the request to the f/w to fetch CEE statistics.
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return Status
- */
-
-bfa_status_t
-bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats,
-		  bfa_cee_get_stats_cbfn_t cbfn, void *cbarg)
-{
-	struct bfi_cee_get_req_s *cmd;
-
-	bfa_assert((cee != NULL) && (cee->ioc != NULL));
-
-	if (!bfa_ioc_is_operational(cee->ioc)) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_IOC_FAILURE;
-	}
-	if (cee->get_stats_pending == BFA_TRUE) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_DEVBUSY;
-	}
-	cee->get_stats_pending = BFA_TRUE;
-	cmd = (struct bfi_cee_get_req_s *)cee->get_stats_mb.msg;
-	cee->stats = stats;
-	cee->cbfn.get_stats_cbfn = cbfn;
-	cee->cbfn.get_stats_cbarg = cbarg;
-	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ,
-		    bfa_ioc_portid(cee->ioc));
-	bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa);
-	bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb);
-	bfa_trc(cee, 0);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * bfa_cee_reset_stats()
- *
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return Status
- */
-
-bfa_status_t
-bfa_cee_reset_stats(struct bfa_cee_s *cee, bfa_cee_reset_stats_cbfn_t cbfn,
-		    void *cbarg)
-{
-	struct bfi_cee_reset_stats_s *cmd;
-
-	bfa_assert((cee != NULL) && (cee->ioc != NULL));
-	if (!bfa_ioc_is_operational(cee->ioc)) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_IOC_FAILURE;
-	}
-	if (cee->reset_stats_pending == BFA_TRUE) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_DEVBUSY;
-	}
-	cee->reset_stats_pending = BFA_TRUE;
-	cmd = (struct bfi_cee_reset_stats_s *)cee->reset_stats_mb.msg;
-	cee->cbfn.reset_stats_cbfn = cbfn;
-	cee->cbfn.reset_stats_cbarg = cbarg;
-	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS,
-		    bfa_ioc_portid(cee->ioc));
-	bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb);
-	bfa_trc(cee, 0);
-	return BFA_STATUS_OK;
-}
-
-/**
- * bfa_cee_isrs()
- *
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return void
- */
-
-void
-bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m)
-{
-	union bfi_cee_i2h_msg_u *msg;
-	struct bfi_cee_get_rsp_s *get_rsp;
-	struct bfa_cee_s *cee = (struct bfa_cee_s *)cbarg;
-	msg = (union bfi_cee_i2h_msg_u *)m;
-	get_rsp = (struct bfi_cee_get_rsp_s *)m;
-	bfa_trc(cee, msg->mh.msg_id);
-	switch (msg->mh.msg_id) {
-	case BFI_CEE_I2H_GET_CFG_RSP:
-		bfa_trc(cee, get_rsp->cmd_status);
-		bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
-		break;
-	case BFI_CEE_I2H_GET_STATS_RSP:
-		bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
-		break;
-	case BFI_CEE_I2H_RESET_STATS_RSP:
-		bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
-		break;
-	default:
-		bfa_assert(0);
-	}
-}
-
-/**
- * bfa_cee_hbfail()
- *
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return void
- */
-
-void
-bfa_cee_hbfail(void *arg)
-{
-	struct bfa_cee_s *cee;
-	cee = (struct bfa_cee_s *)arg;
-
-	if (cee->get_attr_pending == BFA_TRUE) {
-		cee->get_attr_status = BFA_STATUS_FAILED;
-		cee->get_attr_pending = BFA_FALSE;
-		if (cee->cbfn.get_attr_cbfn) {
-			cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg,
-						BFA_STATUS_FAILED);
-		}
-	}
-	if (cee->get_stats_pending == BFA_TRUE) {
-		cee->get_stats_status = BFA_STATUS_FAILED;
-		cee->get_stats_pending = BFA_FALSE;
-		if (cee->cbfn.get_stats_cbfn) {
-			cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg,
-						 BFA_STATUS_FAILED);
-		}
-	}
-	if (cee->reset_stats_pending == BFA_TRUE) {
-		cee->reset_stats_status = BFA_STATUS_FAILED;
-		cee->reset_stats_pending = BFA_FALSE;
-		if (cee->cbfn.reset_stats_cbfn) {
-			cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg,
-						   BFA_STATUS_FAILED);
-		}
-	}
-}
-
-/**
- * bfa_cee_attach()
- *
- *
- * @param[in] cee - Pointer to the CEE module data structure
- *            ioc - Pointer to the ioc module data structure
- *            dev - Pointer to the device driver module data structure
- *                  The device driver specific mbox ISR functions have
- *                  this pointer as one of the parameters.
- *            trcmod -
- *            logmod -
- *
- * @return void
- */
-void
-bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
-	       struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
-{
-	bfa_assert(cee != NULL);
-	cee->dev = dev;
-	cee->trcmod = trcmod;
-	cee->logmod = logmod;
-	cee->ioc = ioc;
-
-	bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
-	bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee);
-	bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail);
-	bfa_trc(cee, 0);
-}
-
-/**
- * bfa_cee_detach()
- *
- *
- * @param[in] cee - Pointer to the CEE module data structure
- *
- * @return void
- */
-void
-bfa_cee_detach(struct bfa_cee_s *cee)
-{
-	/*
-	 * For now, just check if there is some ioctl pending and mark that as
-	 * failed?
-	 */
-	/* bfa_cee_hbfail(cee); */
-}
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 76fa5c5..c2fa07f 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,27 +15,992 @@
  * General Public License for more details.
  */
 
-#include <bfa.h>
-#include <defs/bfa_defs_pci.h>
-#include <cs/bfa_debug.h>
-#include <bfa_iocfc.h>
+#include "bfa_modules.h"
+#include "bfi_ctreg.h"
+#include "bfad_drv.h"
 
-#define DEF_CFG_NUM_FABRICS         1
-#define DEF_CFG_NUM_LPORTS          256
-#define DEF_CFG_NUM_CQS             4
-#define DEF_CFG_NUM_IOIM_REQS       (BFA_IOIM_MAX)
-#define DEF_CFG_NUM_TSKIM_REQS      128
-#define DEF_CFG_NUM_FCXP_REQS       64
-#define DEF_CFG_NUM_UF_BUFS         64
-#define DEF_CFG_NUM_RPORTS          1024
-#define DEF_CFG_NUM_ITNIMS          (DEF_CFG_NUM_RPORTS)
-#define DEF_CFG_NUM_TINS            256
+BFA_TRC_FILE(HAL, CORE);
 
-#define DEF_CFG_NUM_SGPGS           2048
-#define DEF_CFG_NUM_REQQ_ELEMS      256
-#define DEF_CFG_NUM_RSPQ_ELEMS      64
-#define DEF_CFG_NUM_SBOOT_TGTS      16
-#define DEF_CFG_NUM_SBOOT_LUNS      16
+/**
+ * BFA IOC FC related definitions
+ */
+
+/**
+ * IOC local definitions
+ */
+#define BFA_IOCFC_TOV		5000	/* msecs */
+
+enum {
+	BFA_IOCFC_ACT_NONE	= 0,
+	BFA_IOCFC_ACT_INIT	= 1,
+	BFA_IOCFC_ACT_STOP	= 2,
+	BFA_IOCFC_ACT_DISABLE	= 3,
+};
+
+#define DEF_CFG_NUM_FABRICS		1
+#define DEF_CFG_NUM_LPORTS		256
+#define DEF_CFG_NUM_CQS			4
+#define DEF_CFG_NUM_IOIM_REQS		(BFA_IOIM_MAX)
+#define DEF_CFG_NUM_TSKIM_REQS		128
+#define DEF_CFG_NUM_FCXP_REQS		64
+#define DEF_CFG_NUM_UF_BUFS		64
+#define DEF_CFG_NUM_RPORTS		1024
+#define DEF_CFG_NUM_ITNIMS		(DEF_CFG_NUM_RPORTS)
+#define DEF_CFG_NUM_TINS		256
+
+#define DEF_CFG_NUM_SGPGS		2048
+#define DEF_CFG_NUM_REQQ_ELEMS		256
+#define DEF_CFG_NUM_RSPQ_ELEMS		64
+#define DEF_CFG_NUM_SBOOT_TGTS		16
+#define DEF_CFG_NUM_SBOOT_LUNS		16
+
+/**
+ * forward declaration for IOC FC functions
+ */
+static void bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status);
+static void bfa_iocfc_disable_cbfn(void *bfa_arg);
+static void bfa_iocfc_hbfail_cbfn(void *bfa_arg);
+static void bfa_iocfc_reset_cbfn(void *bfa_arg);
+static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn;
+
+/**
+ * BFA Interrupt handling functions
+ */
+static void
+bfa_msix_errint(struct bfa_s *bfa, u32 intr)
+{
+	bfa_ioc_error_isr(&bfa->ioc);
+}
+
+static void
+bfa_msix_lpu(struct bfa_s *bfa)
+{
+	bfa_ioc_mbox_isr(&bfa->ioc);
+}
+
+static void
+bfa_reqq_resume(struct bfa_s *bfa, int qid)
+{
+	struct list_head *waitq, *qe, *qen;
+	struct bfa_reqq_wait_s *wqe;
+
+	waitq = bfa_reqq(bfa, qid);
+	list_for_each_safe(qe, qen, waitq) {
+		/**
+		 * Callback only as long as there is room in request queue
+		 */
+		if (bfa_reqq_full(bfa, qid))
+			break;
+
+		list_del(qe);
+		wqe = (struct bfa_reqq_wait_s *) qe;
+		wqe->qresume(wqe->cbarg);
+	}
+}
+
+void
+bfa_msix_all(struct bfa_s *bfa, int vec)
+{
+	bfa_intx(bfa);
+}
+
+/**
+ *  hal_intr_api
+ */
+bfa_boolean_t
+bfa_intx(struct bfa_s *bfa)
+{
+	u32 intr, qintr;
+	int queue;
+
+	intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
+	if (!intr)
+		return BFA_FALSE;
+
+	/**
+	 * RME completion queue interrupt
+	 */
+	qintr = intr & __HFN_INT_RME_MASK;
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
+
+	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
+		if (intr & (__HFN_INT_RME_Q0 << queue))
+			bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+	}
+	intr &= ~qintr;
+	if (!intr)
+		return BFA_TRUE;
+
+	/**
+	 * CPE completion queue interrupt
+	 */
+	qintr = intr & __HFN_INT_CPE_MASK;
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
+
+	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
+		if (intr & (__HFN_INT_CPE_Q0 << queue))
+			bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+	}
+	intr &= ~qintr;
+	if (!intr)
+		return BFA_TRUE;
+
+	bfa_msix_lpu_err(bfa, intr);
+
+	return BFA_TRUE;
+}
+
+void
+bfa_intx_enable(struct bfa_s *bfa)
+{
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, bfa->iocfc.intr_mask);
+}
+
+void
+bfa_intx_disable(struct bfa_s *bfa)
+{
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L);
+}
+
+void
+bfa_isr_enable(struct bfa_s *bfa)
+{
+	u32 intr_unmask;
+	int pci_func = bfa_ioc_pcifn(&bfa->ioc);
+
+	bfa_trc(bfa, pci_func);
+
+	bfa_msix_install(bfa);
+	intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
+		       __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS |
+		       __HFN_INT_LL_HALT);
+
+	if (pci_func == 0)
+		intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
+				__HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
+				__HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
+				__HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
+				__HFN_INT_MBOX_LPU0);
+	else
+		intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
+				__HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
+				__HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
+				__HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
+				__HFN_INT_MBOX_LPU1);
+
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr_unmask);
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, ~intr_unmask);
+	bfa->iocfc.intr_mask = ~intr_unmask;
+	bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
+}
+
+void
+bfa_isr_disable(struct bfa_s *bfa)
+{
+	bfa_isr_mode_set(bfa, BFA_FALSE);
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L);
+	bfa_msix_uninstall(bfa);
+}
+
+void
+bfa_msix_reqq(struct bfa_s *bfa, int qid)
+{
+	struct list_head *waitq;
+
+	qid &= (BFI_IOC_MAX_CQS - 1);
+
+	bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);
+
+	/**
+	 * Resume any pending requests in the corresponding reqq.
+	 */
+	waitq = bfa_reqq(bfa, qid);
+	if (!list_empty(waitq))
+		bfa_reqq_resume(bfa, qid);
+}
+
+void
+bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	bfa_trc(bfa, m->mhdr.msg_class);
+	bfa_trc(bfa, m->mhdr.msg_id);
+	bfa_trc(bfa, m->mhdr.mtag.i2htok);
+	bfa_assert(0);
+	bfa_trc_stop(bfa->trcmod);
+}
+
+void
+bfa_msix_rspq(struct bfa_s *bfa, int qid)
+{
+	struct bfi_msg_s *m;
+	u32 pi, ci;
+	struct list_head *waitq;
+
+	bfa_trc_fp(bfa, qid);
+
+	qid &= (BFI_IOC_MAX_CQS - 1);
+
+	bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
+
+	ci = bfa_rspq_ci(bfa, qid);
+	pi = bfa_rspq_pi(bfa, qid);
+
+	bfa_trc_fp(bfa, ci);
+	bfa_trc_fp(bfa, pi);
+
+	if (bfa->rme_process) {
+		while (ci != pi) {
+			m = bfa_rspq_elem(bfa, qid, ci);
+			bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);
+
+			bfa_isrs[m->mhdr.msg_class] (bfa, m);
+
+			CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
+		}
+	}
+
+	/**
+	 * update CI
+	 */
+	bfa_rspq_ci(bfa, qid) = pi;
+	bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[qid], pi);
+	mmiowb();
+
+	/**
+	 * Resume any pending requests in the corresponding reqq.
+	 */
+	waitq = bfa_reqq(bfa, qid);
+	if (!list_empty(waitq))
+		bfa_reqq_resume(bfa, qid);
+}
+
+void
+bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
+{
+	u32 intr, curr_value;
+
+	intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
+
+	if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
+		bfa_msix_lpu(bfa);
+
+	intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
+		__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
+
+	if (intr) {
+		if (intr & __HFN_INT_LL_HALT) {
+			/**
+			 * If LL_HALT bit is set then FW Init Halt LL Port
+			 * Register needs to be cleared as well so Interrupt
+			 * Status Register will be cleared.
+			 */
+			curr_value = bfa_reg_read(bfa->ioc.ioc_regs.ll_halt);
+			curr_value &= ~__FW_INIT_HALT_P;
+			bfa_reg_write(bfa->ioc.ioc_regs.ll_halt, curr_value);
+		}
+
+		if (intr & __HFN_INT_ERR_PSS) {
+			/**
+			 * ERR_PSS bit needs to be cleared as well in case
+			 * interrups are shared so driver's interrupt handler is
+			 * still called eventhough it is already masked out.
+			 */
+			curr_value = bfa_reg_read(
+					bfa->ioc.ioc_regs.pss_err_status_reg);
+			curr_value &= __PSS_ERR_STATUS_SET;
+			bfa_reg_write(bfa->ioc.ioc_regs.pss_err_status_reg,
+					curr_value);
+		}
+
+		bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr);
+		bfa_msix_errint(bfa, intr);
+	}
+}
+
+void
+bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func)
+{
+	bfa_isrs[mc] = isr_func;
+}
+
+/**
+ * BFA IOC FC related functions
+ */
+
+/**
+ *  hal_ioc_pvt BFA IOC private functions
+ */
+
+static void
+bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
+{
+	int		i, per_reqq_sz, per_rspq_sz;
+
+	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
+				  BFA_DMA_ALIGN_SZ);
+	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
+				  BFA_DMA_ALIGN_SZ);
+
+	/*
+	 * Calculate CQ size
+	 */
+	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+		*dm_len = *dm_len + per_reqq_sz;
+		*dm_len = *dm_len + per_rspq_sz;
+	}
+
+	/*
+	 * Calculate Shadow CI/PI size
+	 */
+	for (i = 0; i < cfg->fwcfg.num_cqs; i++)
+		*dm_len += (2 * BFA_CACHELINE_SZ);
+}
+
+static void
+bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
+{
+	*dm_len +=
+		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+	*dm_len +=
+		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+			    BFA_CACHELINE_SZ);
+}
+
+/**
+ * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ
+ */
+static void
+bfa_iocfc_send_cfg(void *bfa_arg)
+{
+	struct bfa_s *bfa = bfa_arg;
+	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+	struct bfi_iocfc_cfg_req_s cfg_req;
+	struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo;
+	struct bfa_iocfc_cfg_s	*cfg = &iocfc->cfg;
+	int		i;
+
+	bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS);
+	bfa_trc(bfa, cfg->fwcfg.num_cqs);
+
+	bfa_iocfc_reset_queues(bfa);
+
+	/**
+	 * initialize IOC configuration info
+	 */
+	cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
+	cfg_info->num_cqs = cfg->fwcfg.num_cqs;
+
+	bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
+	/**
+	 * dma map REQ and RSP circular queues and shadow pointers
+	 */
+	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+		bfa_dma_be_addr_set(cfg_info->req_cq_ba[i],
+				    iocfc->req_cq_ba[i].pa);
+		bfa_dma_be_addr_set(cfg_info->req_shadow_ci[i],
+				    iocfc->req_cq_shadow_ci[i].pa);
+		cfg_info->req_cq_elems[i] =
+			bfa_os_htons(cfg->drvcfg.num_reqq_elems);
+
+		bfa_dma_be_addr_set(cfg_info->rsp_cq_ba[i],
+				    iocfc->rsp_cq_ba[i].pa);
+		bfa_dma_be_addr_set(cfg_info->rsp_shadow_pi[i],
+				    iocfc->rsp_cq_shadow_pi[i].pa);
+		cfg_info->rsp_cq_elems[i] =
+			bfa_os_htons(cfg->drvcfg.num_rspq_elems);
+	}
+
+	/**
+	 * Enable interrupt coalescing if it is driver init path
+	 * and not ioc disable/enable path.
+	 */
+	if (!iocfc->cfgdone)
+		cfg_info->intr_attr.coalesce = BFA_TRUE;
+
+	iocfc->cfgdone = BFA_FALSE;
+
+	/**
+	 * dma map IOC configuration itself
+	 */
+	bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ,
+		    bfa_lpuid(bfa));
+	bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);
+
+	bfa_ioc_mbox_send(&bfa->ioc, &cfg_req,
+			  sizeof(struct bfi_iocfc_cfg_req_s));
+}
+
+static void
+bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		   struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
+
+	bfa->bfad = bfad;
+	iocfc->bfa = bfa;
+	iocfc->action = BFA_IOCFC_ACT_NONE;
+
+	bfa_os_assign(iocfc->cfg, *cfg);
+
+	/**
+	 * Initialize chip specific handlers.
+	 */
+	if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) {
+		iocfc->hwif.hw_reginit = bfa_hwct_reginit;
+		iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;
+		iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
+		iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
+		iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
+		iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;
+		iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
+		iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
+		iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range;
+	} else {
+		iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
+		iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack;
+		iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
+		iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
+		iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
+		iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;
+		iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
+		iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
+		iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range;
+	}
+
+	iocfc->hwif.hw_reginit(bfa);
+	bfa->msix.nvecs = 0;
+}
+
+static void
+bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
+		    struct bfa_meminfo_s *meminfo)
+{
+	u8	       *dm_kva;
+	u64	dm_pa;
+	int		i, per_reqq_sz, per_rspq_sz;
+	struct bfa_iocfc_s  *iocfc = &bfa->iocfc;
+	int		dbgsz;
+
+	dm_kva = bfa_meminfo_dma_virt(meminfo);
+	dm_pa = bfa_meminfo_dma_phys(meminfo);
+
+	/*
+	 * First allocate dma memory for IOC.
+	 */
+	bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
+	dm_kva += bfa_ioc_meminfo();
+	dm_pa  += bfa_ioc_meminfo();
+
+	/*
+	 * Claim DMA-able memory for the request/response queues and for shadow
+	 * ci/pi registers
+	 */
+	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
+				  BFA_DMA_ALIGN_SZ);
+	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
+				  BFA_DMA_ALIGN_SZ);
+
+	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+		iocfc->req_cq_ba[i].kva = dm_kva;
+		iocfc->req_cq_ba[i].pa = dm_pa;
+		bfa_os_memset(dm_kva, 0, per_reqq_sz);
+		dm_kva += per_reqq_sz;
+		dm_pa += per_reqq_sz;
+
+		iocfc->rsp_cq_ba[i].kva = dm_kva;
+		iocfc->rsp_cq_ba[i].pa = dm_pa;
+		bfa_os_memset(dm_kva, 0, per_rspq_sz);
+		dm_kva += per_rspq_sz;
+		dm_pa += per_rspq_sz;
+	}
+
+	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+		iocfc->req_cq_shadow_ci[i].kva = dm_kva;
+		iocfc->req_cq_shadow_ci[i].pa = dm_pa;
+		dm_kva += BFA_CACHELINE_SZ;
+		dm_pa += BFA_CACHELINE_SZ;
+
+		iocfc->rsp_cq_shadow_pi[i].kva = dm_kva;
+		iocfc->rsp_cq_shadow_pi[i].pa = dm_pa;
+		dm_kva += BFA_CACHELINE_SZ;
+		dm_pa += BFA_CACHELINE_SZ;
+	}
+
+	/*
+	 * Claim DMA-able memory for the config info page
+	 */
+	bfa->iocfc.cfg_info.kva = dm_kva;
+	bfa->iocfc.cfg_info.pa = dm_pa;
+	bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;
+	dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+
+	/*
+	 * Claim DMA-able memory for the config response
+	 */
+	bfa->iocfc.cfgrsp_dma.kva = dm_kva;
+	bfa->iocfc.cfgrsp_dma.pa = dm_pa;
+	bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva;
+
+	dm_kva +=
+		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+			    BFA_CACHELINE_SZ);
+	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+			     BFA_CACHELINE_SZ);
+
+
+	bfa_meminfo_dma_virt(meminfo) = dm_kva;
+	bfa_meminfo_dma_phys(meminfo) = dm_pa;
+
+	dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover);
+	if (dbgsz > 0) {
+		bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
+		bfa_meminfo_kva(meminfo) += dbgsz;
+	}
+}
+
+/**
+ * Start BFA submodules.
+ */
+static void
+bfa_iocfc_start_submod(struct bfa_s *bfa)
+{
+	int		i;
+
+	bfa->rme_process = BFA_TRUE;
+
+	for (i = 0; hal_mods[i]; i++)
+		hal_mods[i]->start(bfa);
+}
+
+/**
+ * Disable BFA submodules.
+ */
+static void
+bfa_iocfc_disable_submod(struct bfa_s *bfa)
+{
+	int		i;
+
+	for (i = 0; hal_mods[i]; i++)
+		hal_mods[i]->iocdisable(bfa);
+}
+
+static void
+bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete)
+{
+	struct bfa_s	*bfa = bfa_arg;
+
+	if (complete) {
+		if (bfa->iocfc.cfgdone)
+			bfa_cb_init(bfa->bfad, BFA_STATUS_OK);
+		else
+			bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED);
+	} else {
+		if (bfa->iocfc.cfgdone)
+			bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
+	}
+}
+
+static void
+bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
+{
+	struct bfa_s  *bfa = bfa_arg;
+	struct bfad_s *bfad = bfa->bfad;
+
+	if (compl)
+		complete(&bfad->comp);
+	else
+		bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
+}
+
+static void
+bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
+{
+	struct bfa_s  *bfa = bfa_arg;
+	struct bfad_s *bfad = bfa->bfad;
+
+	if (compl)
+		complete(&bfad->disable_comp);
+}
+
+/**
+ * Update BFA configuration from firmware configuration.
+ */
+static void
+bfa_iocfc_cfgrsp(struct bfa_s *bfa)
+{
+	struct bfa_iocfc_s		*iocfc	 = &bfa->iocfc;
+	struct bfi_iocfc_cfgrsp_s	*cfgrsp	 = iocfc->cfgrsp;
+	struct bfa_iocfc_fwcfg_s	*fwcfg	 = &cfgrsp->fwcfg;
+
+	fwcfg->num_cqs	      = fwcfg->num_cqs;
+	fwcfg->num_ioim_reqs  = bfa_os_ntohs(fwcfg->num_ioim_reqs);
+	fwcfg->num_tskim_reqs = bfa_os_ntohs(fwcfg->num_tskim_reqs);
+	fwcfg->num_fcxp_reqs  = bfa_os_ntohs(fwcfg->num_fcxp_reqs);
+	fwcfg->num_uf_bufs    = bfa_os_ntohs(fwcfg->num_uf_bufs);
+	fwcfg->num_rports     = bfa_os_ntohs(fwcfg->num_rports);
+
+	iocfc->cfgdone = BFA_TRUE;
+
+	/**
+	 * Configuration is complete - initialize/start submodules
+	 */
+	bfa_fcport_init(bfa);
+
+	if (iocfc->action == BFA_IOCFC_ACT_INIT)
+		bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
+	else
+		bfa_iocfc_start_submod(bfa);
+}
+void
+bfa_iocfc_reset_queues(struct bfa_s *bfa)
+{
+	int		q;
+
+	for (q = 0; q < BFI_IOC_MAX_CQS; q++) {
+		bfa_reqq_ci(bfa, q) = 0;
+		bfa_reqq_pi(bfa, q) = 0;
+		bfa_rspq_ci(bfa, q) = 0;
+		bfa_rspq_pi(bfa, q) = 0;
+	}
+}
+
+/**
+ * IOC enable request is complete
+ */
+static void
+bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
+{
+	struct bfa_s	*bfa = bfa_arg;
+
+	if (status != BFA_STATUS_OK) {
+		bfa_isr_disable(bfa);
+		if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
+			bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
+				     bfa_iocfc_init_cb, bfa);
+		return;
+	}
+
+	bfa_iocfc_send_cfg(bfa);
+}
+
+/**
+ * IOC disable request is complete
+ */
+static void
+bfa_iocfc_disable_cbfn(void *bfa_arg)
+{
+	struct bfa_s	*bfa = bfa_arg;
+
+	bfa_isr_disable(bfa);
+	bfa_iocfc_disable_submod(bfa);
+
+	if (bfa->iocfc.action == BFA_IOCFC_ACT_STOP)
+		bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb,
+			     bfa);
+	else {
+		bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE);
+		bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb,
+			     bfa);
+	}
+}
+
+/**
+ * Notify sub-modules of hardware failure.
+ */
+static void
+bfa_iocfc_hbfail_cbfn(void *bfa_arg)
+{
+	struct bfa_s	*bfa = bfa_arg;
+
+	bfa->rme_process = BFA_FALSE;
+
+	bfa_isr_disable(bfa);
+	bfa_iocfc_disable_submod(bfa);
+
+	if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
+		bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, bfa_iocfc_init_cb,
+			     bfa);
+}
+
+/**
+ * Actions on chip-reset completion.
+ */
+static void
+bfa_iocfc_reset_cbfn(void *bfa_arg)
+{
+	struct bfa_s	*bfa = bfa_arg;
+
+	bfa_iocfc_reset_queues(bfa);
+	bfa_isr_enable(bfa);
+}
+
+/**
+ *  hal_ioc_public
+ */
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+		  u32 *dm_len)
+{
+	/* dma memory for IOC */
+	*dm_len += bfa_ioc_meminfo();
+
+	bfa_iocfc_fw_cfg_sz(cfg, dm_len);
+	bfa_iocfc_cqs_sz(cfg, dm_len);
+	*km_len += bfa_ioc_debug_trcsz(bfa_auto_recover);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	int		i;
+	struct bfa_ioc_s *ioc = &bfa->ioc;
+
+	bfa_iocfc_cbfn.enable_cbfn = bfa_iocfc_enable_cbfn;
+	bfa_iocfc_cbfn.disable_cbfn = bfa_iocfc_disable_cbfn;
+	bfa_iocfc_cbfn.hbfail_cbfn = bfa_iocfc_hbfail_cbfn;
+	bfa_iocfc_cbfn.reset_cbfn = bfa_iocfc_reset_cbfn;
+
+	ioc->trcmod = bfa->trcmod;
+	bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod);
+
+	/**
+	 * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC.
+	 */
+	if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC)
+		bfa_ioc_set_fcmode(&bfa->ioc);
+
+	bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC);
+	bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
+
+	bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
+	bfa_iocfc_mem_claim(bfa, cfg, meminfo);
+	bfa_timer_init(&bfa->timer_mod);
+
+	INIT_LIST_HEAD(&bfa->comp_q);
+	for (i = 0; i < BFI_IOC_MAX_CQS; i++)
+		INIT_LIST_HEAD(&bfa->reqq_waitq[i]);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_detach(struct bfa_s *bfa)
+{
+	bfa_ioc_detach(&bfa->ioc);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_init(struct bfa_s *bfa)
+{
+	bfa->iocfc.action = BFA_IOCFC_ACT_INIT;
+	bfa_ioc_enable(&bfa->ioc);
+}
+
+/**
+ * IOC start called from bfa_start(). Called to start IOC operations
+ * at driver instantiation for this instance.
+ */
+void
+bfa_iocfc_start(struct bfa_s *bfa)
+{
+	if (bfa->iocfc.cfgdone)
+		bfa_iocfc_start_submod(bfa);
+}
+
+/**
+ * IOC stop called from bfa_stop(). Called only when driver is unloaded
+ * for this instance.
+ */
+void
+bfa_iocfc_stop(struct bfa_s *bfa)
+{
+	bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
+
+	bfa->rme_process = BFA_FALSE;
+	bfa_ioc_disable(&bfa->ioc);
+}
+
+void
+bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
+{
+	struct bfa_s		*bfa = bfaarg;
+	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
+	union bfi_iocfc_i2h_msg_u	*msg;
+
+	msg = (union bfi_iocfc_i2h_msg_u *) m;
+	bfa_trc(bfa, msg->mh.msg_id);
+
+	switch (msg->mh.msg_id) {
+	case BFI_IOCFC_I2H_CFG_REPLY:
+		iocfc->cfg_reply = &msg->cfg_reply;
+		bfa_iocfc_cfgrsp(bfa);
+		break;
+	case BFI_IOCFC_I2H_UPDATEQ_RSP:
+		iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
+		break;
+	default:
+		bfa_assert(0);
+	}
+}
+
+void
+bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr)
+{
+	bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr);
+}
+
+u64
+bfa_adapter_get_id(struct bfa_s *bfa)
+{
+	return bfa_ioc_get_adid(&bfa->ioc);
+}
+
+void
+bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr)
+{
+	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
+
+	attr->intr_attr.coalesce = iocfc->cfginfo->intr_attr.coalesce;
+
+	attr->intr_attr.delay = iocfc->cfginfo->intr_attr.delay ?
+				bfa_os_ntohs(iocfc->cfginfo->intr_attr.delay) :
+				bfa_os_ntohs(iocfc->cfgrsp->intr_attr.delay);
+
+	attr->intr_attr.latency = iocfc->cfginfo->intr_attr.latency ?
+			bfa_os_ntohs(iocfc->cfginfo->intr_attr.latency) :
+			bfa_os_ntohs(iocfc->cfgrsp->intr_attr.latency);
+
+	attr->config	= iocfc->cfg;
+}
+
+bfa_status_t
+bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
+{
+	struct bfa_iocfc_s		*iocfc = &bfa->iocfc;
+	struct bfi_iocfc_set_intr_req_s *m;
+
+	iocfc->cfginfo->intr_attr.coalesce = attr->coalesce;
+	iocfc->cfginfo->intr_attr.delay = bfa_os_htons(attr->delay);
+	iocfc->cfginfo->intr_attr.latency = bfa_os_htons(attr->latency);
+
+	if (!bfa_iocfc_is_operational(bfa))
+		return BFA_STATUS_OK;
+
+	m = bfa_reqq_next(bfa, BFA_REQQ_IOC);
+	if (!m)
+		return BFA_STATUS_DEVBUSY;
+
+	bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ,
+		    bfa_lpuid(bfa));
+	m->coalesce = iocfc->cfginfo->intr_attr.coalesce;
+	m->delay    = iocfc->cfginfo->intr_attr.delay;
+	m->latency  = iocfc->cfginfo->intr_attr.latency;
+
+	bfa_trc(bfa, attr->delay);
+	bfa_trc(bfa, attr->latency);
+
+	bfa_reqq_produce(bfa, BFA_REQQ_IOC);
+	return BFA_STATUS_OK;
+}
+
+void
+bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
+{
+	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
+
+	iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
+	bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
+}
+/**
+ * Enable IOC after it is disabled.
+ */
+void
+bfa_iocfc_enable(struct bfa_s *bfa)
+{
+	bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
+		     "IOC Enable");
+	bfa_ioc_enable(&bfa->ioc);
+}
+
+void
+bfa_iocfc_disable(struct bfa_s *bfa)
+{
+	bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
+		     "IOC Disable");
+	bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE;
+
+	bfa->rme_process = BFA_FALSE;
+	bfa_ioc_disable(&bfa->ioc);
+}
+
+
+bfa_boolean_t
+bfa_iocfc_is_operational(struct bfa_s *bfa)
+{
+	return bfa_ioc_is_operational(&bfa->ioc) && bfa->iocfc.cfgdone;
+}
+
+/**
+ * Return boot target port wwns -- read from boot information in flash.
+ */
+void
+bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns)
+{
+	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+	int i;
+
+	if (cfgrsp->pbc_cfg.boot_enabled && cfgrsp->pbc_cfg.nbluns) {
+		bfa_trc(bfa, cfgrsp->pbc_cfg.nbluns);
+		*nwwns = cfgrsp->pbc_cfg.nbluns;
+		for (i = 0; i < cfgrsp->pbc_cfg.nbluns; i++)
+			wwns[i] = cfgrsp->pbc_cfg.blun[i].tgt_pwwn;
+
+		return;
+	}
+
+	*nwwns = cfgrsp->bootwwns.nwwns;
+	memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(cfgrsp->bootwwns.wwn));
+}
+
+void
+bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg)
+{
+	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+
+	pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled;
+	pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns;
+	pbcfg->speed = cfgrsp->pbc_cfg.port_speed;
+	memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun));
+}
+
+int
+bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
+{
+	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+
+	memcpy(pbc_vport, cfgrsp->pbc_cfg.vport, sizeof(cfgrsp->pbc_cfg.vport));
+	return cfgrsp->pbc_cfg.nvports;
+}
+
+/**
+ *  hal_api
+ */
 
 /**
  * Use this function query the memory requirement of the BFA library.
@@ -45,16 +1010,16 @@
  * This call will fail, if the cap is out of range compared to pre-defined
  * values within the BFA library
  *
- * @param[in] cfg - 	pointer to bfa_ioc_cfg_t. Driver layer should indicate
- * 			its configuration in this structure.
+ * @param[in] cfg -	pointer to bfa_ioc_cfg_t. Driver layer should indicate
+ *			its configuration in this structure.
  *			The default values for struct bfa_iocfc_cfg_s can be
  *			fetched using bfa_cfg_get_default() API.
  *
- * 			If cap's boundary check fails, the library will use
+ *			If cap's boundary check fails, the library will use
  *			the default bfa_cap_t values (and log a warning msg).
  *
  * @param[out] meminfo - pointer to bfa_meminfo_t. This content
- * 			indicates the memory type (see bfa_mem_type_t) and
+ *			indicates the memory type (see bfa_mem_type_t) and
  *			amount of memory required.
  *
  *			Driver should allocate the memory, populate the
@@ -68,8 +1033,8 @@
 void
 bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo)
 {
-	int             i;
-	u32        km_len = 0, dm_len = 0;
+	int		i;
+	u32	km_len = 0, dm_len = 0;
 
 	bfa_assert((cfg != NULL) && (meminfo != NULL));
 
@@ -90,26 +1055,6 @@
 	meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len;
 }
 
-static void
-bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
-{
-	struct bfa_port_s       *port = &bfa->modules.port;
-	uint32_t                dm_len;
-	uint8_t                 *dm_kva;
-	uint64_t                dm_pa;
-
-	dm_len = bfa_port_meminfo();
-	dm_kva = bfa_meminfo_dma_virt(mi);
-	dm_pa  = bfa_meminfo_dma_phys(mi);
-
-	memset(port, 0, sizeof(struct bfa_port_s));
-	bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod, bfa->logm);
-	bfa_port_mem_claim(port, dm_kva, dm_pa);
-
-	bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
-	bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
-}
-
 /**
  * Use this function to do attach the driver instance with the BFA
  * library. This function will not trigger any HW initialization
@@ -119,14 +1064,14 @@
  * pre-defined values within the BFA library
  *
  * @param[out]	bfa	Pointer to bfa_t.
- * @param[in]	bfad 	Opaque handle back to the driver's IOC structure
+ * @param[in]	bfad	Opaque handle back to the driver's IOC structure
  * @param[in]	cfg	Pointer to bfa_ioc_cfg_t. Should be same structure
- * 			that was used in bfa_cfg_get_meminfo().
- * @param[in] 	meminfo Pointer to bfa_meminfo_t. The driver should
- * 			use the bfa_cfg_get_meminfo() call to
- * 			find the memory blocks required, allocate the
- * 			required memory and provide the starting addresses.
- * @param[in] 	pcidev	pointer to struct bfa_pcidev_s
+ *			that was used in bfa_cfg_get_meminfo().
+ * @param[in]	meminfo	Pointer to bfa_meminfo_t. The driver should
+ *			use the bfa_cfg_get_meminfo() call to
+ *			find the memory blocks required, allocate the
+ *			required memory and provide the starting addresses.
+ * @param[in]	pcidev	pointer to struct bfa_pcidev_s
  *
  * @return
  * void
@@ -140,8 +1085,8 @@
 bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 	       struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
 {
-	int             i;
-	struct bfa_mem_elem_s *melem;
+	int			i;
+	struct bfa_mem_elem_s	*melem;
 
 	bfa->fcs = BFA_FALSE;
 
@@ -195,20 +1140,6 @@
 	bfa->trcmod = trcmod;
 }
 
-
-void
-bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod)
-{
-	bfa->logm = logmod;
-}
-
-
-void
-bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen)
-{
-	bfa->aen = aen;
-}
-
 void
 bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog)
 {
@@ -254,14 +1185,14 @@
 
 /**
  * Use this function quiese the IOC. This function will return immediately,
- * when the IOC is actually stopped, the bfa_cb_stop() will be called.
+ * when the IOC is actually stopped, the bfad->comp will be set.
  *
- * @param[in] 	bfa - pointer to bfa_t.
+ * @param[in]bfa - pointer to bfa_t.
  *
  * @return None
  *
  * Special Considerations:
- * bfa_cb_stop() could be called before or after bfa_stop() returns.
+ * bfad->comp can be set before or after bfa_stop() returns.
  *
  * @note
  * In case of any failure, we could handle it automatically by doing a
@@ -283,9 +1214,9 @@
 void
 bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)
 {
-	struct list_head        *qe;
-	struct list_head        *qen;
-	struct bfa_cb_qe_s   *hcb_qe;
+	struct list_head		*qe;
+	struct list_head		*qen;
+	struct bfa_cb_qe_s	*hcb_qe;
 
 	list_for_each_safe(qe, qen, comp_q) {
 		hcb_qe = (struct bfa_cb_qe_s *) qe;
@@ -296,8 +1227,8 @@
 void
 bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q)
 {
-	struct list_head        *qe;
-	struct bfa_cb_qe_s   *hcb_qe;
+	struct list_head		*qe;
+	struct bfa_cb_qe_s	*hcb_qe;
 
 	while (!list_empty(comp_q)) {
 		bfa_q_deq(comp_q, &qe);
@@ -321,7 +1252,6 @@
 	bfa_timer_beat(&bfa->timer_mod);
 }
 
-#ifndef BFA_BIOS_BUILD
 /**
  * Return the list of PCI vendor/device id lists supported by this
  * BFA instance.
@@ -336,7 +1266,7 @@
 		{BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_CT_FC},
 	};
 
-	*npciids = ARRAY_SIZE(__pciids);
+	*npciids = sizeof(__pciids) / sizeof(__pciids[0]);
 	*pciids = __pciids;
 }
 
@@ -351,7 +1281,7 @@
  *	void
  *
  * Special Considerations:
- * 	note
+ * note
  */
 void
 bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg)
@@ -389,7 +1319,7 @@
 	cfg->drvcfg.num_sgpgs      = BFA_SGPG_MIN;
 	cfg->drvcfg.num_reqq_elems = BFA_REQQ_NELEMS_MIN;
 	cfg->drvcfg.num_rspq_elems = BFA_RSPQ_NELEMS_MIN;
-	cfg->drvcfg.min_cfg        = BFA_TRUE;
+	cfg->drvcfg.min_cfg	   = BFA_TRUE;
 }
 
 void
@@ -417,7 +1347,7 @@
 }
 
 /**
- * 		Fetch firmware trace data.
+ * Fetch firmware trace data.
  *
  * @param[in]		bfa			BFA instance
  * @param[out]		trcdata		Firmware trace buffer
@@ -433,6 +1363,22 @@
 }
 
 /**
+ * Dump firmware memory.
+ *
+ * @param[in]		bfa		BFA instance
+ * @param[out]		buf		buffer for dump
+ * @param[in,out]	offset		smem offset to start read
+ * @param[in,out]	buflen		length of buffer
+ *
+ * @retval BFA_STATUS_OK		Firmware memory is dumped.
+ * @retval BFA_STATUS_INPROGRESS	Firmware memory dump is in progress.
+ */
+bfa_status_t
+bfa_debug_fwcore(struct bfa_s *bfa, void *buf, u32 *offset, int *buflen)
+{
+	return bfa_ioc_debug_fwcore(&bfa->ioc, buf, offset, buflen);
+}
+/**
  * Reset hw semaphore & usage cnt regs and initialize.
  */
 void
@@ -441,4 +1387,23 @@
 	bfa_ioc_ownership_reset(&bfa->ioc);
 	bfa_ioc_pll_init(&bfa->ioc);
 }
-#endif
+
+/**
+ * Fetch firmware statistics data.
+ *
+ * @param[in]		bfa		BFA instance
+ * @param[out]		data		Firmware stats buffer
+ *
+ * @retval BFA_STATUS_OK		Firmware trace is fetched.
+ */
+bfa_status_t
+bfa_fw_stats_get(struct bfa_s *bfa, void *data)
+{
+	return bfa_ioc_fw_stats_get(&bfa->ioc, data);
+}
+
+bfa_status_t
+bfa_fw_stats_clear(struct bfa_s *bfa)
+{
+	return bfa_ioc_fw_stats_clear(&bfa->ioc);
+}
diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h
new file mode 100644
index 0000000..7260c74
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_cs.h
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+/**
+ *  bfa_cs.h BFA common services
+ */
+
+#ifndef __BFA_CS_H__
+#define __BFA_CS_H__
+
+#include "bfa_os_inc.h"
+
+/**
+ * BFA TRC
+ */
+
+#ifndef BFA_TRC_MAX
+#define BFA_TRC_MAX	(4 * 1024)
+#endif
+
+#ifndef BFA_TRC_TS
+#define BFA_TRC_TS(_trcm)	((_trcm)->ticks++)
+#endif
+
+struct bfa_trc_s {
+#ifdef __BIGENDIAN
+	u16	fileno;
+	u16	line;
+#else
+	u16	line;
+	u16	fileno;
+#endif
+	u32	timestamp;
+	union {
+		struct {
+			u32	rsvd;
+			u32	u32;
+		} u32;
+		u64	u64;
+	} data;
+};
+
+struct bfa_trc_mod_s {
+	u32	head;
+	u32	tail;
+	u32	ntrc;
+	u32	stopped;
+	u32	ticks;
+	u32	rsvd[3];
+	struct bfa_trc_s trc[BFA_TRC_MAX];
+};
+
+enum {
+	BFA_TRC_HAL  = 1,	/*  BFA modules */
+	BFA_TRC_FCS  = 2,	/*  BFA FCS modules */
+	BFA_TRC_LDRV = 3,	/*  Linux driver modules */
+	BFA_TRC_CNA  = 4,	/*  Common modules */
+};
+#define BFA_TRC_MOD_SH	10
+#define BFA_TRC_MOD(__mod)	((BFA_TRC_ ## __mod) << BFA_TRC_MOD_SH)
+
+/**
+ * Define a new tracing file (module). Module should match one defined above.
+ */
+#define BFA_TRC_FILE(__mod, __submod)					\
+	static int __trc_fileno = ((BFA_TRC_ ## __mod ## _ ## __submod) | \
+						 BFA_TRC_MOD(__mod))
+
+
+#define bfa_trc32(_trcp, _data)	\
+	__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
+#define bfa_trc(_trcp, _data)	\
+	__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u64)_data)
+
+static inline void
+bfa_trc_init(struct bfa_trc_mod_s *trcm)
+{
+	trcm->head = trcm->tail = trcm->stopped = 0;
+	trcm->ntrc = BFA_TRC_MAX;
+}
+
+static inline void
+bfa_trc_stop(struct bfa_trc_mod_s *trcm)
+{
+	trcm->stopped = 1;
+}
+
+#ifdef FWTRC
+extern void dc_flush(void *data);
+#else
+#define dc_flush(data)
+#endif
+
+
+static inline void
+__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
+{
+	int		tail = trcm->tail;
+	struct bfa_trc_s	*trc = &trcm->trc[tail];
+
+	if (trcm->stopped)
+		return;
+
+	trc->fileno = (u16) fileno;
+	trc->line = (u16) line;
+	trc->data.u64 = data;
+	trc->timestamp = BFA_TRC_TS(trcm);
+	dc_flush(trc);
+
+	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
+	if (trcm->tail == trcm->head)
+		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
+	dc_flush(trcm);
+}
+
+
+static inline void
+__bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
+{
+	int		tail = trcm->tail;
+	struct bfa_trc_s *trc = &trcm->trc[tail];
+
+	if (trcm->stopped)
+		return;
+
+	trc->fileno = (u16) fileno;
+	trc->line = (u16) line;
+	trc->data.u32.u32 = data;
+	trc->timestamp = BFA_TRC_TS(trcm);
+	dc_flush(trc);
+
+	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
+	if (trcm->tail == trcm->head)
+		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
+	dc_flush(trcm);
+}
+
+#ifndef BFA_PERF_BUILD
+#define bfa_trc_fp(_trcp, _data)	bfa_trc(_trcp, _data)
+#else
+#define bfa_trc_fp(_trcp, _data)
+#endif
+
+/**
+ * @ BFA LOG interfaces
+ */
+#define bfa_assert(__cond)	do {					\
+	if (!(__cond)) {						\
+		printk(KERN_ERR "assert(%s) failed at %s:%d\\n",         \
+		#__cond, __FILE__, __LINE__);				\
+	}								\
+} while (0)
+
+#define bfa_sm_fault(__mod, __event)	do {				\
+	bfa_trc(__mod, (((u32)0xDEAD << 16) | __event));		\
+	printk(KERN_ERR	"Assertion failure: %s:%d: %d",			\
+		__FILE__, __LINE__, (__event));				\
+} while (0)
+
+#ifndef BFA_PERF_BUILD
+#define bfa_assert_fp(__cond)	bfa_assert(__cond)
+#else
+#define bfa_assert_fp(__cond)
+#endif
+
+/* BFA queue definitions */
+#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
+#define bfa_q_next(_qe) (((struct list_head *) (_qe))->next)
+#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev)
+
+/*
+ * bfa_q_qe_init - to initialize a queue element
+ */
+#define bfa_q_qe_init(_qe) {				\
+	bfa_q_next(_qe) = (struct list_head *) NULL;	\
+	bfa_q_prev(_qe) = (struct list_head *) NULL;	\
+}
+
+/*
+ * bfa_q_deq - dequeue an element from head of the queue
+ */
+#define bfa_q_deq(_q, _qe) {						\
+	if (!list_empty(_q)) {						\
+		(*((struct list_head **) (_qe))) = bfa_q_next(_q);	\
+		bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) =	\
+				(struct list_head *) (_q);		\
+		bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe));\
+		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		\
+	} else {							\
+		*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
+	}								\
+}
+
+/*
+ * bfa_q_deq_tail - dequeue an element from tail of the queue
+ */
+#define bfa_q_deq_tail(_q, _qe) {					\
+	if (!list_empty(_q)) {						\
+		*((struct list_head **) (_qe)) = bfa_q_prev(_q);	\
+		bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) =	\
+			(struct list_head *) (_q);			\
+		bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);\
+		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		\
+	} else {							\
+		*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
+	}								\
+}
+
+static inline int
+bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
+{
+	struct list_head        *tqe;
+
+	tqe = bfa_q_next(q);
+	while (tqe != q) {
+		if (tqe == qe)
+			return 1;
+		tqe = bfa_q_next(tqe);
+		if (tqe == NULL)
+			break;
+	}
+	return 0;
+}
+
+/*
+ * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not
+ * consistent across modules)
+ */
+#ifndef BFA_PERF_BUILD
+#define BFA_Q_DBG_INIT(_qe) bfa_q_qe_init(_qe)
+#else
+#define BFA_Q_DBG_INIT(_qe)
+#endif
+
+#define bfa_q_is_on_q(_q, _qe)      \
+	bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
+
+/**
+ * @ BFA state machine interfaces
+ */
+
+typedef void (*bfa_sm_t)(void *sm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc_s
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_sm_state_decl(oc, st, otype, etype)		\
+	static void oc ## _sm_ ## st(otype * fsm, etype event)
+
+#define bfa_sm_set_state(_sm, _state)	((_sm)->sm = (bfa_sm_t)(_state))
+#define bfa_sm_send_event(_sm, _event)	((_sm)->sm((_sm), (_event)))
+#define bfa_sm_get_state(_sm)		((_sm)->sm)
+#define bfa_sm_cmp_state(_sm, _state)	((_sm)->sm == (bfa_sm_t)(_state))
+
+/**
+ * For converting from state machine function to state encoding.
+ */
+struct bfa_sm_table_s {
+	bfa_sm_t	sm;	/*  state machine function	*/
+	int		state;	/*  state machine encoding	*/
+	char		*name;	/*  state name for display	*/
+};
+#define BFA_SM(_sm)	((bfa_sm_t)(_sm))
+
+/**
+ * State machine with entry actions.
+ */
+typedef void (*bfa_fsm_t)(void *fsm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc_s
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_fsm_state_decl(oc, st, otype, etype)		\
+	static void oc ## _sm_ ## st(otype * fsm, etype event);      \
+	static void oc ## _sm_ ## st ## _entry(otype * fsm)
+
+#define bfa_fsm_set_state(_fsm, _state) do {	\
+	(_fsm)->fsm = (bfa_fsm_t)(_state);      \
+	_state ## _entry(_fsm);      \
+} while (0)
+
+#define bfa_fsm_send_event(_fsm, _event)	((_fsm)->fsm((_fsm), (_event)))
+#define bfa_fsm_get_state(_fsm)			((_fsm)->fsm)
+#define bfa_fsm_cmp_state(_fsm, _state)		\
+	((_fsm)->fsm == (bfa_fsm_t)(_state))
+
+static inline int
+bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm)
+{
+	int	i = 0;
+
+	while (smt[i].sm && smt[i].sm != sm)
+		i++;
+	return smt[i].state;
+}
+
+/**
+ * @ Generic wait counter.
+ */
+
+typedef void (*bfa_wc_resume_t) (void *cbarg);
+
+struct bfa_wc_s {
+	bfa_wc_resume_t wc_resume;
+	void		*wc_cbarg;
+	int		wc_count;
+};
+
+static inline void
+bfa_wc_up(struct bfa_wc_s *wc)
+{
+	wc->wc_count++;
+}
+
+static inline void
+bfa_wc_down(struct bfa_wc_s *wc)
+{
+	wc->wc_count--;
+	if (wc->wc_count == 0)
+		wc->wc_resume(wc->wc_cbarg);
+}
+
+/**
+ * Initialize a waiting counter.
+ */
+static inline void
+bfa_wc_init(struct bfa_wc_s *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
+{
+	wc->wc_resume = wc_resume;
+	wc->wc_cbarg = wc_cbarg;
+	wc->wc_count = 0;
+	bfa_wc_up(wc);
+}
+
+/**
+ * Wait for counter to reach zero
+ */
+static inline void
+bfa_wc_wait(struct bfa_wc_s *wc)
+{
+	bfa_wc_down(wc);
+}
+
+#endif /* __BFA_CS_H__ */
diff --git a/drivers/scsi/bfa/bfa_csdebug.c b/drivers/scsi/bfa/bfa_csdebug.c
deleted file mode 100644
index caeb114..0000000
--- a/drivers/scsi/bfa/bfa_csdebug.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <cs/bfa_debug.h>
-#include <bfa_os_inc.h>
-#include <cs/bfa_q.h>
-#include <log/bfa_log_hal.h>
-
-/**
- *  cs_debug_api
- */
-
-
-void
-bfa_panic(int line, char *file, char *panicstr)
-{
-	bfa_log(NULL, BFA_LOG_HAL_ASSERT, file, line, panicstr);
-	bfa_os_panic();
-}
-
-void
-bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event)
-{
-	bfa_log(logm, BFA_LOG_HAL_SM_ASSERT, file, line, event);
-	bfa_os_panic();
-}
-
-int
-bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
-{
-	struct list_head        *tqe;
-
-	tqe = bfa_q_next(q);
-	while (tqe != q) {
-		if (tqe == qe)
-			return 1;
-		tqe = bfa_q_next(tqe);
-		if (tqe == NULL)
-			break;
-	}
-	return 0;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
new file mode 100644
index 0000000..d49877f
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_H__
+#define __BFA_DEFS_H__
+
+#include "bfa_fc.h"
+#include "bfa_os_inc.h"
+
+#define BFA_MFG_SERIALNUM_SIZE                  11
+#define STRSZ(_n)                               (((_n) + 4) & ~3)
+
+/**
+ * Manufacturing card type
+ */
+enum {
+	BFA_MFG_TYPE_CB_MAX  = 825,      /*  Crossbow card type max     */
+	BFA_MFG_TYPE_FC8P2   = 825,      /*  8G 2port FC card           */
+	BFA_MFG_TYPE_FC8P1   = 815,      /*  8G 1port FC card           */
+	BFA_MFG_TYPE_FC4P2   = 425,      /*  4G 2port FC card           */
+	BFA_MFG_TYPE_FC4P1   = 415,      /*  4G 1port FC card           */
+	BFA_MFG_TYPE_CNA10P2 = 1020,     /*  10G 2port CNA card */
+	BFA_MFG_TYPE_CNA10P1 = 1010,     /*  10G 1port CNA card */
+	BFA_MFG_TYPE_JAYHAWK = 804,      /*  Jayhawk mezz card          */
+	BFA_MFG_TYPE_WANCHESE = 1007,    /*  Wanchese mezz card */
+	BFA_MFG_TYPE_ASTRA    = 807,     /*  Astra mezz card            */
+	BFA_MFG_TYPE_LIGHTNING_P0 = 902, /*  Lightning mezz card - old  */
+	BFA_MFG_TYPE_LIGHTNING = 1741,   /*  Lightning mezz card        */
+	BFA_MFG_TYPE_INVALID = 0,        /*  Invalid card type          */
+};
+
+#pragma pack(1)
+
+/**
+ * Check if Mezz card
+ */
+#define bfa_mfg_is_mezz(type) (( \
+	(type) == BFA_MFG_TYPE_JAYHAWK || \
+	(type) == BFA_MFG_TYPE_WANCHESE || \
+	(type) == BFA_MFG_TYPE_ASTRA || \
+	(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
+	(type) == BFA_MFG_TYPE_LIGHTNING))
+
+/**
+ * Check if the card having old wwn/mac handling
+ */
+#define bfa_mfg_is_old_wwn_mac_model(type) (( \
+	(type) == BFA_MFG_TYPE_FC8P2 || \
+	(type) == BFA_MFG_TYPE_FC8P1 || \
+	(type) == BFA_MFG_TYPE_FC4P2 || \
+	(type) == BFA_MFG_TYPE_FC4P1 || \
+	(type) == BFA_MFG_TYPE_CNA10P2 || \
+	(type) == BFA_MFG_TYPE_CNA10P1 || \
+	(type) == BFA_MFG_TYPE_JAYHAWK || \
+	(type) == BFA_MFG_TYPE_WANCHESE))
+
+#define bfa_mfg_increment_wwn_mac(m, i)                         \
+do {                                                            \
+	u32 t = ((u32)(m)[0] << 16) | ((u32)(m)[1] << 8) | \
+		(u32)(m)[2];  \
+	t += (i);      \
+	(m)[0] = (t >> 16) & 0xFF;                              \
+	(m)[1] = (t >> 8) & 0xFF;                               \
+	(m)[2] = t & 0xFF;                                      \
+} while (0)
+
+/**
+ * VPD data length
+ */
+#define BFA_MFG_VPD_LEN                 512
+
+/**
+ * VPD vendor tag
+ */
+enum {
+	BFA_MFG_VPD_UNKNOWN     = 0,     /*  vendor unknown             */
+	BFA_MFG_VPD_IBM         = 1,     /*  vendor IBM                 */
+	BFA_MFG_VPD_HP          = 2,     /*  vendor HP                  */
+	BFA_MFG_VPD_DELL        = 3,     /*  vendor DELL                */
+	BFA_MFG_VPD_PCI_IBM     = 0x08,  /*  PCI VPD IBM                */
+	BFA_MFG_VPD_PCI_HP      = 0x10,  /*  PCI VPD HP         */
+	BFA_MFG_VPD_PCI_DELL    = 0x20,  /*  PCI VPD DELL               */
+	BFA_MFG_VPD_PCI_BRCD    = 0xf8,  /*  PCI VPD Brocade            */
+};
+
+/**
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_vpd_s {
+	u8              version;        /*  vpd data version */
+	u8              vpd_sig[3];     /*  characters 'V', 'P', 'D' */
+	u8              chksum;         /*  u8 checksum */
+	u8              vendor;         /*  vendor */
+	u8      len;            /*  vpd data length excluding header */
+	u8      rsv;
+	u8              data[BFA_MFG_VPD_LEN];  /*  vpd data */
+};
+
+#pragma pack()
+
+/**
+ * Status return values
+ */
+enum bfa_status {
+	BFA_STATUS_OK		= 0,	/*  Success */
+	BFA_STATUS_FAILED	= 1,	/*  Operation failed */
+	BFA_STATUS_EINVAL	= 2,	/*  Invalid params Check input
+					 *  parameters */
+	BFA_STATUS_ENOMEM	= 3,	/*  Out of resources */
+	BFA_STATUS_ETIMER	= 5,	/*  Timer expired - Retry, if persists,
+					 *  contact support */
+	BFA_STATUS_EPROTOCOL	= 6,	/*  Protocol error */
+	BFA_STATUS_DEVBUSY	= 13,	/*  Device busy - Retry operation */
+	BFA_STATUS_UNKNOWN_LWWN = 18,	/*  LPORT PWWN not found */
+	BFA_STATUS_UNKNOWN_RWWN = 19,	/*  RPORT PWWN not found */
+	BFA_STATUS_VPORT_EXISTS = 21,	/*  VPORT already exists */
+	BFA_STATUS_VPORT_MAX	= 22,	/*  Reached max VPORT supported limit */
+	BFA_STATUS_UNSUPP_SPEED	= 23,	/*  Invalid Speed Check speed setting */
+	BFA_STATUS_INVLD_DFSZ	= 24,	/*  Invalid Max data field size */
+	BFA_STATUS_FABRIC_RJT	= 29,	/*  Reject from attached fabric */
+	BFA_STATUS_VPORT_WWN_BP	= 46,	/*  WWN is same as base port's WWN */
+	BFA_STATUS_NO_FCPIM_NEXUS = 52,	/* No FCP Nexus exists with the rport */
+	BFA_STATUS_IOC_FAILURE	= 56,	/* IOC failure - Retry, if persists
+					 * contact support */
+	BFA_STATUS_INVALID_WWN	= 57,	/*  Invalid WWN */
+	BFA_STATUS_DIAG_BUSY	= 71,	/*  diag busy */
+	BFA_STATUS_ENOFSAVE	= 78,	/*  No saved firmware trace */
+	BFA_STATUS_IOC_DISABLED = 82,   /* IOC is already disabled */
+	BFA_STATUS_INVALID_MAC  = 134, /*  Invalid MAC address */
+	BFA_STATUS_PBC		= 154, /*  Operation not allowed for pre-boot
+					*  configuration */
+	BFA_STATUS_TRUNK_ENABLED = 164, /* Trunk is already enabled on
+					 * this adapter */
+	BFA_STATUS_TRUNK_DISABLED  = 165, /* Trunking is disabled on
+					   * the adapter */
+	BFA_STATUS_IOPROFILE_OFF = 175, /* IO profile OFF */
+	BFA_STATUS_MAX_VAL		/* Unknown error code */
+};
+#define bfa_status_t enum bfa_status
+
+enum bfa_eproto_status {
+	BFA_EPROTO_BAD_ACCEPT = 0,
+	BFA_EPROTO_UNKNOWN_RSP = 1
+};
+#define bfa_eproto_status_t enum bfa_eproto_status
+
+enum bfa_boolean {
+	BFA_FALSE = 0,
+	BFA_TRUE  = 1
+};
+#define bfa_boolean_t enum bfa_boolean
+
+#define BFA_STRING_32	32
+#define BFA_VERSION_LEN 64
+
+/**
+ * ---------------------- adapter definitions ------------
+ */
+
+/**
+ * BFA adapter level attributes.
+ */
+enum {
+	BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE),
+					/*
+					 *!< adapter serial num length
+					 */
+	BFA_ADAPTER_MODEL_NAME_LEN  = 16,  /*  model name length */
+	BFA_ADAPTER_MODEL_DESCR_LEN = 128, /*  model description length */
+	BFA_ADAPTER_MFG_NAME_LEN    = 8,   /*  manufacturer name length */
+	BFA_ADAPTER_SYM_NAME_LEN    = 64,  /*  adapter symbolic name length */
+	BFA_ADAPTER_OS_TYPE_LEN	    = 64,  /*  adapter os type length */
+};
+
+struct bfa_adapter_attr_s {
+	char		manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
+	char		serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+	u32	card_type;
+	char		model[BFA_ADAPTER_MODEL_NAME_LEN];
+	char		model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
+	wwn_t		pwwn;
+	char		node_symname[FC_SYMNAME_MAX];
+	char		hw_ver[BFA_VERSION_LEN];
+	char		fw_ver[BFA_VERSION_LEN];
+	char		optrom_ver[BFA_VERSION_LEN];
+	char		os_type[BFA_ADAPTER_OS_TYPE_LEN];
+	struct bfa_mfg_vpd_s	vpd;
+	struct mac_s	mac;
+
+	u8		nports;
+	u8		max_speed;
+	u8		prototype;
+	char	        asic_rev;
+
+	u8		pcie_gen;
+	u8		pcie_lanes_orig;
+	u8		pcie_lanes;
+	u8	        cna_capable;
+
+	u8		is_mezz;
+	u8		trunk_capable;
+};
+
+/**
+ * ---------------------- IOC definitions ------------
+ */
+
+enum {
+	BFA_IOC_DRIVER_LEN	= 16,
+	BFA_IOC_CHIP_REV_LEN	= 8,
+};
+
+/**
+ * Driver and firmware versions.
+ */
+struct bfa_ioc_driver_attr_s {
+	char		driver[BFA_IOC_DRIVER_LEN];	/*  driver name */
+	char		driver_ver[BFA_VERSION_LEN];	/*  driver version */
+	char		fw_ver[BFA_VERSION_LEN];	/*  firmware version */
+	char		bios_ver[BFA_VERSION_LEN];	/*  bios version */
+	char		efi_ver[BFA_VERSION_LEN];	/*  EFI version */
+	char		ob_ver[BFA_VERSION_LEN];	/*  openboot version */
+};
+
+/**
+ * IOC PCI device attributes
+ */
+struct bfa_ioc_pci_attr_s {
+	u16	vendor_id;	/*  PCI vendor ID */
+	u16	device_id;	/*  PCI device ID */
+	u16	ssid;		/*  subsystem ID */
+	u16	ssvid;		/*  subsystem vendor ID */
+	u32	pcifn;		/*  PCI device function */
+	u32	rsvd;		/* padding */
+	char		chip_rev[BFA_IOC_CHIP_REV_LEN];	 /*  chip revision */
+};
+
+/**
+ * IOC states
+ */
+enum bfa_ioc_state {
+	BFA_IOC_UNINIT		= 1,	/*  IOC is in uninit state */
+	BFA_IOC_RESET		= 2,	/*  IOC is in reset state */
+	BFA_IOC_SEMWAIT		= 3,	/*  Waiting for IOC h/w semaphore */
+	BFA_IOC_HWINIT		= 4,	/*  IOC h/w is being initialized */
+	BFA_IOC_GETATTR		= 5,	/*  IOC is being configured */
+	BFA_IOC_OPERATIONAL	= 6,	/*  IOC is operational */
+	BFA_IOC_INITFAIL	= 7,	/*  IOC hardware failure */
+	BFA_IOC_FAIL		= 8,	/*  IOC heart-beat failure */
+	BFA_IOC_DISABLING	= 9,	/*  IOC is being disabled */
+	BFA_IOC_DISABLED	= 10,	/*  IOC is disabled */
+	BFA_IOC_FWMISMATCH	= 11,	/*  IOC f/w different from drivers */
+	BFA_IOC_ENABLING	= 12,	/*  IOC is being enabled */
+};
+
+/**
+ * IOC firmware stats
+ */
+struct bfa_fw_ioc_stats_s {
+	u32	enable_reqs;
+	u32	disable_reqs;
+	u32	get_attr_reqs;
+	u32	dbg_sync;
+	u32	dbg_dump;
+	u32	unknown_reqs;
+};
+
+/**
+ * IOC driver stats
+ */
+struct bfa_ioc_drv_stats_s {
+	u32	ioc_isrs;
+	u32	ioc_enables;
+	u32	ioc_disables;
+	u32	ioc_hbfails;
+	u32	ioc_boots;
+	u32	stats_tmos;
+	u32	hb_count;
+	u32	disable_reqs;
+	u32	enable_reqs;
+	u32	disable_replies;
+	u32	enable_replies;
+};
+
+/**
+ * IOC statistics
+ */
+struct bfa_ioc_stats_s {
+	struct bfa_ioc_drv_stats_s	drv_stats; /*  driver IOC stats */
+	struct bfa_fw_ioc_stats_s	fw_stats;  /*  firmware IOC stats */
+};
+
+enum bfa_ioc_type_e {
+	BFA_IOC_TYPE_FC		= 1,
+	BFA_IOC_TYPE_FCoE	= 2,
+	BFA_IOC_TYPE_LL		= 3,
+};
+
+/**
+ * IOC attributes returned in queries
+ */
+struct bfa_ioc_attr_s {
+	enum bfa_ioc_type_e		ioc_type;
+	enum bfa_ioc_state		state;		/*  IOC state      */
+	struct bfa_adapter_attr_s	adapter_attr;	/*  HBA attributes */
+	struct bfa_ioc_driver_attr_s	driver_attr;	/*  driver attr    */
+	struct bfa_ioc_pci_attr_s	pci_attr;
+	u8				port_id;	/*  port number    */
+	u8				rsvd[7];	/*  64bit align    */
+};
+
+/**
+ * ---------------------- mfg definitions ------------
+ */
+
+/**
+ * Checksum size
+ */
+#define BFA_MFG_CHKSUM_SIZE			16
+
+#define BFA_MFG_PARTNUM_SIZE			14
+#define BFA_MFG_SUPPLIER_ID_SIZE		10
+#define BFA_MFG_SUPPLIER_PARTNUM_SIZE		20
+#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE		20
+#define BFA_MFG_SUPPLIER_REVISION_SIZE		4
+
+#pragma pack(1)
+
+/**
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_block_s {
+	u8		version;	/*  manufacturing block version */
+	u8		mfg_sig[3];	/*  characters 'M', 'F', 'G' */
+	u16	mfgsize;	/*  mfg block size */
+	u16	u16_chksum;	/*  old u16 checksum */
+	char		brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+	char		brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
+	u8		mfg_day;	/*  manufacturing day */
+	u8		mfg_month;	/*  manufacturing month */
+	u16	mfg_year;	/*  manufacturing year */
+	wwn_t		mfg_wwn;	/*  wwn base for this adapter */
+	u8		num_wwn;	/*  number of wwns assigned */
+	u8		mfg_speeds;	/*  speeds allowed for this adapter */
+	u8		rsv[2];
+	char		supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
+	char		supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
+	char
+		supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
+	char
+		supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
+	mac_t		mfg_mac;	/*  mac address */
+	u8		num_mac;	/*  number of mac addresses */
+	u8		rsv2;
+	u32	mfg_type;	/*  card type */
+	u8		rsv3[108];
+	u8		md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*  md5 checksum */
+};
+
+#pragma pack()
+
+/**
+ * ---------------------- pci definitions ------------
+ */
+
+/**
+ * PCI device and vendor ID information
+ */
+enum {
+	BFA_PCI_VENDOR_ID_BROCADE	= 0x1657,
+	BFA_PCI_DEVICE_ID_FC_8G2P	= 0x13,
+	BFA_PCI_DEVICE_ID_FC_8G1P	= 0x17,
+	BFA_PCI_DEVICE_ID_CT		= 0x14,
+	BFA_PCI_DEVICE_ID_CT_FC		= 0x21,
+};
+
+#define bfa_asic_id_ct(devid)			\
+	((devid) == BFA_PCI_DEVICE_ID_CT ||	\
+	 (devid) == BFA_PCI_DEVICE_ID_CT_FC)
+
+/**
+ * PCI sub-system device and vendor ID information
+ */
+enum {
+	BFA_PCI_FCOE_SSDEVICE_ID	= 0x14,
+};
+
+/**
+ * Maximum number of device address ranges mapped through different BAR(s)
+ */
+#define BFA_PCI_ACCESS_RANGES 1
+
+/*
+ *	Port speed settings. Each specific speed is a bit field. Use multiple
+ *	bits to specify speeds to be selected for auto-negotiation.
+ */
+enum bfa_port_speed {
+	BFA_PORT_SPEED_UNKNOWN = 0,
+	BFA_PORT_SPEED_1GBPS	= 1,
+	BFA_PORT_SPEED_2GBPS	= 2,
+	BFA_PORT_SPEED_4GBPS	= 4,
+	BFA_PORT_SPEED_8GBPS	= 8,
+	BFA_PORT_SPEED_10GBPS	= 10,
+	BFA_PORT_SPEED_16GBPS	= 16,
+	BFA_PORT_SPEED_AUTO =
+		(BFA_PORT_SPEED_1GBPS | BFA_PORT_SPEED_2GBPS |
+		 BFA_PORT_SPEED_4GBPS | BFA_PORT_SPEED_8GBPS),
+};
+#define bfa_port_speed_t enum bfa_port_speed
+
+enum {
+	BFA_BOOT_BOOTLUN_MAX = 4,       /*  maximum boot lun per IOC */
+	BFA_PREBOOT_BOOTLUN_MAX = 8,    /*  maximum preboot lun per IOC */
+};
+
+#define BOOT_CFG_REV1   1
+#define BOOT_CFG_VLAN   1
+
+/**
+ *      Boot options setting. Boot options setting determines from where
+ *      to get the boot lun information
+ */
+enum bfa_boot_bootopt {
+	BFA_BOOT_AUTO_DISCOVER  = 0, /*  Boot from blun provided by fabric */
+	BFA_BOOT_STORED_BLUN = 1, /*  Boot from bluns stored in flash */
+	BFA_BOOT_FIRST_LUN      = 2, /*  Boot from first discovered blun */
+	BFA_BOOT_PBC    = 3, /*  Boot from pbc configured blun  */
+};
+
+#pragma pack(1)
+/**
+ * Boot lun information.
+ */
+struct bfa_boot_bootlun_s {
+	wwn_t   pwwn;   /*  port wwn of target */
+	lun_t   lun;    /*  64-bit lun */
+};
+#pragma pack()
+
+/**
+ * BOOT boot configuraton
+ */
+struct bfa_boot_pbc_s {
+	u8              enable;         /*  enable/disable SAN boot */
+	u8              speed;          /*  boot speed settings */
+	u8              topology;       /*  boot topology setting */
+	u8              rsvd1;
+	u32     nbluns;         /*  number of boot luns */
+	struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX];
+};
+
+#endif /* __BFA_DEFS_H__ */
diff --git a/drivers/scsi/bfa/bfa_defs_fcs.h b/drivers/scsi/bfa/bfa_defs_fcs.h
new file mode 100644
index 0000000..96905d3
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_defs_fcs.h
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_FCS_H__
+#define __BFA_DEFS_FCS_H__
+
+#include "bfa_fc.h"
+#include "bfa_defs_svc.h"
+
+/**
+ * VF states
+ */
+enum bfa_vf_state {
+	BFA_VF_UNINIT    = 0,	/*  fabric is not yet initialized */
+	BFA_VF_LINK_DOWN = 1,	/*  link is down */
+	BFA_VF_FLOGI     = 2,	/*  flogi is in progress */
+	BFA_VF_AUTH      = 3,	/*  authentication in progress */
+	BFA_VF_NOFABRIC  = 4,	/*  fabric is not present */
+	BFA_VF_ONLINE    = 5,	/*  login to fabric is complete */
+	BFA_VF_EVFP      = 6,	/*  EVFP is in progress */
+	BFA_VF_ISOLATED  = 7,	/*  port isolated due to vf_id mismatch */
+};
+
+/**
+ * VF statistics
+ */
+struct bfa_vf_stats_s {
+	u32	flogi_sent;	/*  Num FLOGIs sent */
+	u32	flogi_rsp_err;	/*  FLOGI response errors */
+	u32	flogi_acc_err;	/*  FLOGI accept errors */
+	u32	flogi_accepts;	/*  FLOGI accepts received */
+	u32	flogi_rejects;	/*  FLOGI rejects received */
+	u32	flogi_unknown_rsp; /*  Unknown responses for FLOGI */
+	u32	flogi_alloc_wait; /*  Allocation waits prior to sending FLOGI */
+	u32	flogi_rcvd;	/*  FLOGIs received */
+	u32	flogi_rejected;	/*  Incoming FLOGIs rejected */
+	u32	fabric_onlines;	/*  Internal fabric online notification sent
+				 *  to other modules */
+	u32	fabric_offlines; /* Internal fabric offline notification sent
+				  * to other modules */
+	u32	resvd; /*  padding for 64 bit alignment */
+};
+
+/**
+ * VF attributes returned in queries
+ */
+struct bfa_vf_attr_s {
+	enum bfa_vf_state  state;		/*  VF state */
+	u32        rsvd;
+	wwn_t           fabric_name;	/*  fabric name */
+};
+
+#define BFA_FCS_MAX_LPORTS 256
+#define BFA_FCS_FABRIC_IPADDR_SZ  16
+
+/**
+ * symbolic names for base port/virtual port
+ */
+#define BFA_SYMNAME_MAXLEN	128	/* 128 bytes */
+struct bfa_lport_symname_s {
+	char	    symname[BFA_SYMNAME_MAXLEN];
+};
+
+/**
+* Roles of FCS port:
+ *     - FCP IM and FCP TM roles cannot be enabled together for a FCS port
+ *     - Create multiple ports if both IM and TM functions required.
+ *     - Atleast one role must be specified.
+ */
+enum bfa_lport_role {
+	BFA_LPORT_ROLE_FCP_IM	= 0x01,	/*  FCP initiator role */
+	BFA_LPORT_ROLE_FCP_MAX	= BFA_LPORT_ROLE_FCP_IM,
+};
+
+/**
+ * FCS port configuration.
+ */
+struct bfa_lport_cfg_s {
+    wwn_t	       pwwn;       /*  port wwn */
+    wwn_t	       nwwn;       /*  node wwn */
+    struct bfa_lport_symname_s  sym_name;   /*  vm port symbolic name */
+	bfa_boolean_t       preboot_vp;  /*  vport created from PBC */
+    enum bfa_lport_role     roles;      /*  FCS port roles */
+    u8	     tag[16];	/*  opaque tag from application */
+};
+
+/**
+ * FCS port states
+ */
+enum bfa_lport_state {
+	BFA_LPORT_UNINIT  = 0,	/*  PORT is not yet initialized */
+	BFA_LPORT_FDISC   = 1,	/*  FDISC is in progress */
+	BFA_LPORT_ONLINE  = 2,	/*  login to fabric is complete */
+	BFA_LPORT_OFFLINE = 3,	/*  No login to fabric */
+};
+
+/**
+ * FCS port type.
+ */
+enum bfa_lport_type {
+	BFA_LPORT_TYPE_PHYSICAL = 0,
+	BFA_LPORT_TYPE_VIRTUAL,
+};
+
+/**
+ * FCS port offline reason.
+ */
+enum bfa_lport_offline_reason {
+	BFA_LPORT_OFFLINE_UNKNOWN = 0,
+	BFA_LPORT_OFFLINE_LINKDOWN,
+	BFA_LPORT_OFFLINE_FAB_UNSUPPORTED,	/*  NPIV not supported by the
+	 *    fabric */
+	BFA_LPORT_OFFLINE_FAB_NORESOURCES,
+	BFA_LPORT_OFFLINE_FAB_LOGOUT,
+};
+
+/**
+ * FCS lport info.
+ */
+struct bfa_lport_info_s {
+	u8	 port_type;	/* bfa_lport_type_t : physical or
+	 * virtual */
+	u8	 port_state;	/* one of bfa_lport_state values */
+	u8	 offline_reason;	/* one of bfa_lport_offline_reason_t
+	 * values */
+	wwn_t	   port_wwn;
+	wwn_t	   node_wwn;
+
+	/*
+	 * following 4 feilds are valid for Physical Ports only
+	 */
+	u32	max_vports_supp;	/* Max supported vports */
+	u32	num_vports_inuse;	/* Num of in use vports */
+	u32	max_rports_supp;	/* Max supported rports */
+	u32	num_rports_inuse;	/* Num of doscovered rports */
+
+};
+
+/**
+ * FCS port statistics
+ */
+struct bfa_lport_stats_s {
+	u32	ns_plogi_sent;
+	u32	ns_plogi_rsp_err;
+	u32	ns_plogi_acc_err;
+	u32	ns_plogi_accepts;
+	u32	ns_rejects;	/* NS command rejects */
+	u32	ns_plogi_unknown_rsp;
+	u32	ns_plogi_alloc_wait;
+
+	u32	ns_retries;	/* NS command retries */
+	u32	ns_timeouts;	/* NS command timeouts */
+
+	u32	ns_rspnid_sent;
+	u32	ns_rspnid_accepts;
+	u32	ns_rspnid_rsp_err;
+	u32	ns_rspnid_rejects;
+	u32	ns_rspnid_alloc_wait;
+
+	u32	ns_rftid_sent;
+	u32	ns_rftid_accepts;
+	u32	ns_rftid_rsp_err;
+	u32	ns_rftid_rejects;
+	u32	ns_rftid_alloc_wait;
+
+	u32	ns_rffid_sent;
+	u32	ns_rffid_accepts;
+	u32	ns_rffid_rsp_err;
+	u32	ns_rffid_rejects;
+	u32	ns_rffid_alloc_wait;
+
+	u32	ns_gidft_sent;
+	u32	ns_gidft_accepts;
+	u32	ns_gidft_rsp_err;
+	u32	ns_gidft_rejects;
+	u32	ns_gidft_unknown_rsp;
+	u32	ns_gidft_alloc_wait;
+
+	/*
+	 * Mgmt Server stats
+	 */
+	u32	ms_retries;	/* MS command retries */
+	u32	ms_timeouts;	/* MS command timeouts */
+	u32	ms_plogi_sent;
+	u32	ms_plogi_rsp_err;
+	u32	ms_plogi_acc_err;
+	u32	ms_plogi_accepts;
+	u32	ms_rejects;	/* MS command rejects */
+	u32	ms_plogi_unknown_rsp;
+	u32	ms_plogi_alloc_wait;
+
+	u32	num_rscn;	/* Num of RSCN received */
+	u32	num_portid_rscn;/* Num portid format RSCN
+	* received */
+
+	u32	uf_recvs;	/* Unsolicited recv frames	*/
+	u32	uf_recv_drops;	/* Dropped received frames	*/
+
+	u32	plogi_rcvd;	/* Received plogi	*/
+	u32	prli_rcvd;	/* Received prli	*/
+	u32	adisc_rcvd;	/* Received adisc	*/
+	u32	prlo_rcvd;	/* Received prlo	*/
+	u32	logo_rcvd;	/* Received logo	*/
+	u32	rpsc_rcvd;	/* Received rpsc	*/
+	u32	un_handled_els_rcvd;	/* Received unhandled ELS	*/
+	u32	rport_plogi_timeouts; /* Rport plogi retry timeout count */
+	u32	rport_del_max_plogi_retry; /* Deleted rport
+					    * (max retry of plogi) */
+};
+
+/**
+ * BFA port attribute returned in queries
+ */
+struct bfa_lport_attr_s {
+	enum bfa_lport_state state;	/*  port state */
+	u32	 pid;	/*  port ID */
+	struct bfa_lport_cfg_s   port_cfg;	/*  port configuration */
+	enum bfa_port_type port_type;	/*  current topology */
+	u32	 loopback;	/*  cable is externally looped back */
+	wwn_t	fabric_name; /*  attached switch's nwwn */
+	u8	fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; /*  attached
+	* fabric's ip addr */
+	mac_t	   fpma_mac;	/*  Lport's FPMA Mac address */
+	u16	authfail;	/*  auth failed state */
+};
+
+
+/**
+ * VPORT states
+ */
+enum bfa_vport_state {
+	BFA_FCS_VPORT_UNINIT		= 0,
+	BFA_FCS_VPORT_CREATED		= 1,
+	BFA_FCS_VPORT_OFFLINE		= 1,
+	BFA_FCS_VPORT_FDISC_SEND	= 2,
+	BFA_FCS_VPORT_FDISC		= 3,
+	BFA_FCS_VPORT_FDISC_RETRY	= 4,
+	BFA_FCS_VPORT_ONLINE		= 5,
+	BFA_FCS_VPORT_DELETING		= 6,
+	BFA_FCS_VPORT_CLEANUP		= 6,
+	BFA_FCS_VPORT_LOGO_SEND		= 7,
+	BFA_FCS_VPORT_LOGO		= 8,
+	BFA_FCS_VPORT_ERROR		= 9,
+	BFA_FCS_VPORT_MAX_STATE,
+};
+
+/**
+ * vport statistics
+ */
+struct bfa_vport_stats_s {
+	struct bfa_lport_stats_s port_stats;	/*  base class (port) stats */
+	/*
+	 * TODO - remove
+	 */
+
+	u32        fdisc_sent;	/*  num fdisc sent */
+	u32        fdisc_accepts;	/*  fdisc accepts */
+	u32        fdisc_retries;	/*  fdisc retries */
+	u32        fdisc_timeouts;	/*  fdisc timeouts */
+	u32        fdisc_rsp_err;	/*  fdisc response error */
+	u32        fdisc_acc_bad;	/*  bad fdisc accepts */
+	u32        fdisc_rejects;	/*  fdisc rejects */
+	u32        fdisc_unknown_rsp;
+	/*
+	 *!< fdisc rsp unknown error
+	 */
+	u32        fdisc_alloc_wait;/*  fdisc req (fcxp)alloc wait */
+
+	u32        logo_alloc_wait;/*  logo req (fcxp) alloc wait */
+	u32        logo_sent;	/*  logo sent */
+	u32        logo_accepts;	/*  logo accepts */
+	u32        logo_rejects;	/*  logo rejects */
+	u32        logo_rsp_err;	/*  logo rsp errors */
+	u32        logo_unknown_rsp;
+			/*  logo rsp unknown errors */
+
+	u32        fab_no_npiv;	/*  fabric does not support npiv */
+
+	u32        fab_offline;	/*  offline events from fab SM */
+	u32        fab_online;	/*  online events from fab SM */
+	u32        fab_cleanup;	/*  cleanup request from fab SM */
+	u32        rsvd;
+};
+
+/**
+ * BFA vport attribute returned in queries
+ */
+struct bfa_vport_attr_s {
+	struct bfa_lport_attr_s   port_attr; /*  base class (port) attributes */
+	enum bfa_vport_state vport_state; /*  vport state */
+	u32          rsvd;
+};
+
+/**
+ * FCS remote port states
+ */
+enum bfa_rport_state {
+	BFA_RPORT_UNINIT	= 0,	/*  PORT is not yet initialized */
+	BFA_RPORT_OFFLINE	= 1,	/*  rport is offline */
+	BFA_RPORT_PLOGI		= 2,	/*  PLOGI to rport is in progress */
+	BFA_RPORT_ONLINE	= 3,	/*  login to rport is complete */
+	BFA_RPORT_PLOGI_RETRY	= 4,	/*  retrying login to rport */
+	BFA_RPORT_NSQUERY	= 5,	/*  nameserver query */
+	BFA_RPORT_ADISC		= 6,	/*  ADISC authentication */
+	BFA_RPORT_LOGO		= 7,	/*  logging out with rport */
+	BFA_RPORT_LOGORCV	= 8,	/*  handling LOGO from rport */
+	BFA_RPORT_NSDISC	= 9,	/*  re-discover rport */
+};
+
+/**
+ *  Rport Scsi Function : Initiator/Target.
+ */
+enum bfa_rport_function {
+	BFA_RPORT_INITIATOR	= 0x01,	/*  SCSI Initiator	*/
+	BFA_RPORT_TARGET	= 0x02,	/*  SCSI Target	*/
+};
+
+/**
+ * port/node symbolic names for rport
+ */
+#define BFA_RPORT_SYMNAME_MAXLEN	255
+struct bfa_rport_symname_s {
+	char            symname[BFA_RPORT_SYMNAME_MAXLEN];
+};
+
+/**
+ * FCS remote port statistics
+ */
+struct bfa_rport_stats_s {
+	u32        offlines;           /*  remote port offline count  */
+	u32        onlines;            /*  remote port online count   */
+	u32        rscns;              /*  RSCN affecting rport       */
+	u32        plogis;		    /*  plogis sent                */
+	u32        plogi_accs;	    /*  plogi accepts              */
+	u32        plogi_timeouts;	    /*  plogi timeouts             */
+	u32        plogi_rejects;	    /*  rcvd plogi rejects         */
+	u32        plogi_failed;	    /*  local failure              */
+	u32        plogi_rcvd;	    /*  plogis rcvd                */
+	u32        prli_rcvd;          /*  inbound PRLIs              */
+	u32        adisc_rcvd;         /*  ADISCs received            */
+	u32        adisc_rejects;      /*  recvd  ADISC rejects       */
+	u32        adisc_sent;         /*  ADISC requests sent        */
+	u32        adisc_accs;         /*  ADISC accepted by rport    */
+	u32        adisc_failed;       /*  ADISC failed (no response) */
+	u32        adisc_rejected;     /*  ADISC rejected by us    */
+	u32        logos;              /*  logos sent                 */
+	u32        logo_accs;          /*  LOGO accepts from rport    */
+	u32        logo_failed;        /*  LOGO failures              */
+	u32        logo_rejected;      /*  LOGO rejects from rport    */
+	u32        logo_rcvd;          /*  LOGO from remote port      */
+
+	u32        rpsc_rcvd;         /*  RPSC received            */
+	u32        rpsc_rejects;      /*  recvd  RPSC rejects       */
+	u32        rpsc_sent;         /*  RPSC requests sent        */
+	u32        rpsc_accs;         /*  RPSC accepted by rport    */
+	u32        rpsc_failed;       /*  RPSC failed (no response) */
+	u32        rpsc_rejected;     /*  RPSC rejected by us    */
+
+	u32	rjt_insuff_res;	/*  LS RJT with insuff resources */
+	struct bfa_rport_hal_stats_s	hal_stats;  /*  BFA rport stats    */
+};
+
+/**
+ * FCS remote port attributes returned in queries
+ */
+struct bfa_rport_attr_s {
+	wwn_t		nwwn;	/*  node wwn */
+	wwn_t		pwwn;	/*  port wwn */
+	enum fc_cos cos_supported;	/*  supported class of services */
+	u32		pid;	/*  port ID */
+	u32		df_sz;	/*  Max payload size */
+	enum bfa_rport_state	state;	/*  Rport State machine state */
+	enum fc_cos	fc_cos;	/*  FC classes of services */
+	bfa_boolean_t	cisc;	/*  CISC capable device */
+	struct bfa_rport_symname_s symname; /*  Symbolic Name */
+	enum bfa_rport_function	scsi_function; /*  Initiator/Target */
+	struct bfa_rport_qos_attr_s qos_attr; /*  qos attributes  */
+	enum bfa_port_speed curr_speed;   /*  operating speed got from
+					    * RPSC ELS. UNKNOWN, if RPSC
+					    * is not supported */
+	bfa_boolean_t	trl_enforced;	/*  TRL enforced ? TRUE/FALSE */
+	enum bfa_port_speed	assigned_speed;	/* Speed assigned by the user.
+						 * will be used if RPSC is not
+						 * supported by the rport */
+};
+
+struct bfa_rport_remote_link_stats_s {
+	u32 lfc; /*  Link Failure Count */
+	u32 lsyc; /*  Loss of Synchronization Count */
+	u32 lsic; /*  Loss of Signal Count */
+	u32 pspec; /*  Primitive Sequence Protocol Error Count */
+	u32 itwc; /*  Invalid Transmission Word Count */
+	u32 icc; /*  Invalid CRC Count */
+};
+
+
+#define BFA_MAX_IO_INDEX 7
+#define BFA_NO_IO_INDEX 9
+
+/**
+ * FCS itnim states
+ */
+enum bfa_itnim_state {
+	BFA_ITNIM_OFFLINE	= 0,	/*  offline */
+	BFA_ITNIM_PRLI_SEND	= 1,	/*  prli send */
+	BFA_ITNIM_PRLI_SENT	= 2,	/*  prli sent */
+	BFA_ITNIM_PRLI_RETRY	= 3,	/*  prli retry */
+	BFA_ITNIM_HCB_ONLINE	= 4,	/*  online callback */
+	BFA_ITNIM_ONLINE	= 5,	/*  online */
+	BFA_ITNIM_HCB_OFFLINE	= 6,	/*  offline callback */
+	BFA_ITNIM_INITIATIOR	= 7,	/*  initiator */
+};
+
+/**
+ * FCS remote port statistics
+ */
+struct bfa_itnim_stats_s {
+	u32        onlines;	/*  num rport online */
+	u32        offlines;	/*  num rport offline */
+	u32        prli_sent;	/*  num prli sent out */
+	u32        fcxp_alloc_wait;/*  num fcxp alloc waits */
+	u32        prli_rsp_err;	/*  num prli rsp errors */
+	u32        prli_rsp_acc;	/*  num prli rsp accepts */
+	u32        initiator;	/*  rport is an initiator */
+	u32        prli_rsp_parse_err;	/*  prli rsp parsing errors */
+	u32        prli_rsp_rjt;	/*  num prli rsp rejects */
+	u32        timeout;	/*  num timeouts detected */
+	u32        sler;		/*  num sler notification from BFA */
+	u32	rsvd;		/* padding for 64 bit alignment */
+};
+
+/**
+ * FCS itnim attributes returned in queries
+ */
+struct bfa_itnim_attr_s {
+	enum bfa_itnim_state state; /*  FCS itnim state        */
+	u8 retry;		/*  data retransmision support */
+	u8	task_retry_id;  /*  task retry ident support   */
+	u8 rec_support;    /*  REC supported              */
+	u8 conf_comp;      /*  confirmed completion supp  */
+};
+
+#endif /* __BFA_DEFS_FCS_H__ */
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
new file mode 100644
index 0000000..56226fc
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -0,0 +1,1081 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_SVC_H__
+#define __BFA_DEFS_SVC_H__
+
+#include "bfa_defs.h"
+#include "bfa_fc.h"
+#include "bfi.h"
+
+#define BFA_IOCFC_INTR_DELAY	1125
+#define BFA_IOCFC_INTR_LATENCY	225
+#define BFA_IOCFCOE_INTR_DELAY	25
+#define BFA_IOCFCOE_INTR_LATENCY 5
+
+/**
+ * Interrupt coalescing configuration.
+ */
+#pragma pack(1)
+struct bfa_iocfc_intr_attr_s {
+	u8		coalesce;	/*  enable/disable coalescing */
+	u8		rsvd[3];
+	u16	latency;	/*  latency in microseconds   */
+	u16	delay;		/*  delay in microseconds     */
+};
+
+/**
+ * IOC firmware configuraton
+ */
+struct bfa_iocfc_fwcfg_s {
+	u16        num_fabrics;	/*  number of fabrics		*/
+	u16        num_lports;	/*  number of local lports	*/
+	u16        num_rports;	/*  number of remote ports	*/
+	u16        num_ioim_reqs;	/*  number of IO reqs		*/
+	u16        num_tskim_reqs;	/*  task management requests	*/
+	u16        num_iotm_reqs;	/*  number of TM IO reqs	*/
+	u16        num_tsktm_reqs;	/*  TM task management requests*/
+	u16        num_fcxp_reqs;	/*  unassisted FC exchanges	*/
+	u16        num_uf_bufs;	/*  unsolicited recv buffers	*/
+	u8		num_cqs;
+	u8		fw_tick_res;	/*  FW clock resolution in ms */
+	u8		rsvd[4];
+};
+#pragma pack()
+
+struct bfa_iocfc_drvcfg_s {
+	u16        num_reqq_elems;	/*  number of req queue elements */
+	u16        num_rspq_elems;	/*  number of rsp queue elements */
+	u16        num_sgpgs;	/*  number of total SG pages	  */
+	u16        num_sboot_tgts;	/*  number of SAN boot targets	  */
+	u16        num_sboot_luns;	/*  number of SAN boot luns	  */
+	u16	    ioc_recover;	/*  IOC recovery mode		  */
+	u16	    min_cfg;	/*  minimum configuration	  */
+	u16        path_tov;	/*  device path timeout	  */
+	bfa_boolean_t   delay_comp; /*  delay completion of
+							failed inflight IOs */
+	u32		rsvd;
+};
+
+/**
+ * IOC configuration
+ */
+struct bfa_iocfc_cfg_s {
+	struct bfa_iocfc_fwcfg_s	fwcfg;	/*  firmware side config */
+	struct bfa_iocfc_drvcfg_s	drvcfg;	/*  driver side config	  */
+};
+
+/**
+ * IOC firmware IO stats
+ */
+struct bfa_fw_io_stats_s {
+	u32	host_abort;		/*  IO aborted by host driver*/
+	u32	host_cleanup;		/*  IO clean up by host driver */
+
+	u32	fw_io_timeout;		/*  IOs timedout */
+	u32	fw_frm_parse;		/*  frame parsed by f/w */
+	u32	fw_frm_data;		/*  fcp_data frame parsed by f/w */
+	u32	fw_frm_rsp;		/*  fcp_rsp frame parsed by f/w */
+	u32	fw_frm_xfer_rdy;	/*  xfer_rdy frame parsed by f/w */
+	u32	fw_frm_bls_acc;		/*  BLS ACC  frame parsed by f/w */
+	u32	fw_frm_tgt_abort;	/*  target ABTS parsed by f/w */
+	u32	fw_frm_unknown;		/*  unknown parsed by f/w */
+	u32	fw_data_dma;		/*  f/w DMA'ed the data frame */
+	u32	fw_frm_drop;		/*  f/w drop the frame */
+
+	u32	rec_timeout;		/*  FW rec timed out */
+	u32	error_rec;			/*  FW sending rec on
+							* an error condition*/
+	u32	wait_for_si;		/*  FW wait for SI */
+	u32	rec_rsp_inval;		/*  REC rsp invalid */
+	u32	seqr_io_abort;		/*  target does not know cmd so abort */
+	u32	seqr_io_retry;		/*  SEQR failed so retry IO */
+
+	u32	itn_cisc_upd_rsp;	/*  ITN cisc updated on fcp_rsp */
+	u32	itn_cisc_upd_data;	/*  ITN cisc updated on fcp_data */
+	u32	itn_cisc_upd_xfer_rdy;	/*  ITN cisc updated on fcp_data */
+
+	u32	fcp_data_lost;		/*  fcp data lost */
+
+	u32	ro_set_in_xfer_rdy;	/*  Target set RO in Xfer_rdy frame */
+	u32	xfer_rdy_ooo_err;	/*  Out of order Xfer_rdy received */
+	u32	xfer_rdy_unknown_err;	/*  unknown error in xfer_rdy frame */
+
+	u32	io_abort_timeout;	/*  ABTS timedout  */
+	u32	sler_initiated;		/*  SLER initiated */
+
+	u32	unexp_fcp_rsp;		/*  fcp response in wrong state */
+
+	u32	fcp_rsp_under_run;	/*  fcp rsp IO underrun */
+	u32        fcp_rsp_under_run_wr;   /*  fcp rsp IO underrun for write */
+	u32	fcp_rsp_under_run_err;	/*  fcp rsp IO underrun error */
+	u32        fcp_rsp_resid_inval;    /*  invalid residue */
+	u32	fcp_rsp_over_run;	/*  fcp rsp IO overrun */
+	u32	fcp_rsp_over_run_err;	/*  fcp rsp IO overrun error */
+	u32	fcp_rsp_proto_err;	/*  protocol error in fcp rsp */
+	u32	fcp_rsp_sense_err;	/*  error in sense info in fcp rsp */
+	u32	fcp_conf_req;		/*  FCP conf requested */
+
+	u32	tgt_aborted_io;		/*  target initiated abort */
+
+	u32	ioh_edtov_timeout_event;/*  IOH edtov timer popped */
+	u32	ioh_fcp_rsp_excp_event;	/*  IOH FCP_RSP exception */
+	u32	ioh_fcp_conf_event;	/*  IOH FCP_CONF */
+	u32	ioh_mult_frm_rsp_event;	/*  IOH multi_frame FCP_RSP */
+	u32	ioh_hit_class2_event;	/*  IOH hit class2 */
+	u32	ioh_miss_other_event;	/*  IOH miss other */
+	u32	ioh_seq_cnt_err_event;	/*  IOH seq cnt error */
+	u32	ioh_len_err_event;		/*  IOH len error - fcp_dl !=
+							* bytes xfered */
+	u32	ioh_seq_len_err_event;	/*  IOH seq len error */
+	u32	ioh_data_oor_event;	/*  Data out of range */
+	u32	ioh_ro_ooo_event;	/*  Relative offset out of range */
+	u32	ioh_cpu_owned_event;	/*  IOH hit -iost owned by f/w */
+	u32	ioh_unexp_frame_event;	/*  unexpected frame recieved
+						 *   count */
+	u32	ioh_err_int;		/*  IOH error int during data-phase
+						 *   for scsi write
+						 */
+};
+
+/**
+ * IOC port firmware stats
+ */
+
+struct bfa_fw_port_fpg_stats_s {
+    u32    intr_evt;
+    u32    intr;
+    u32    intr_excess;
+    u32    intr_cause0;
+    u32    intr_other;
+    u32    intr_other_ign;
+    u32    sig_lost;
+    u32    sig_regained;
+    u32    sync_lost;
+    u32    sync_to;
+    u32    sync_regained;
+    u32    div2_overflow;
+    u32    div2_underflow;
+    u32    efifo_overflow;
+    u32    efifo_underflow;
+    u32    idle_rx;
+    u32    lrr_rx;
+    u32    lr_rx;
+    u32    ols_rx;
+    u32    nos_rx;
+    u32    lip_rx;
+    u32    arbf0_rx;
+    u32    arb_rx;
+    u32    mrk_rx;
+    u32    const_mrk_rx;
+    u32    prim_unknown;
+};
+
+
+struct bfa_fw_port_lksm_stats_s {
+    u32    hwsm_success;       /*  hwsm state machine success          */
+    u32    hwsm_fails;         /*  hwsm fails                          */
+    u32    hwsm_wdtov;         /*  hwsm timed out                      */
+    u32    swsm_success;       /*  swsm success                        */
+    u32    swsm_fails;         /*  swsm fails                          */
+    u32    swsm_wdtov;         /*  swsm timed out                      */
+    u32    busybufs;           /*  link init failed due to busybuf     */
+    u32    buf_waits;          /*  bufwait state entries               */
+    u32    link_fails;         /*  link failures                       */
+    u32    psp_errors;         /*  primitive sequence protocol errors  */
+    u32    lr_unexp;           /*  No. of times LR rx-ed unexpectedly  */
+    u32    lrr_unexp;          /*  No. of times LRR rx-ed unexpectedly */
+    u32    lr_tx;              /*  No. of times LR tx started          */
+    u32    lrr_tx;             /*  No. of times LRR tx started         */
+    u32    ols_tx;             /*  No. of times OLS tx started         */
+    u32    nos_tx;             /*  No. of times NOS tx started         */
+    u32    hwsm_lrr_rx;        /*  No. of times LRR rx-ed by HWSM      */
+    u32    hwsm_lr_rx;         /*  No. of times LR rx-ed by HWSM      */
+};
+
+struct bfa_fw_port_snsm_stats_s {
+    u32    hwsm_success;       /*  Successful hwsm terminations        */
+    u32    hwsm_fails;         /*  hwsm fail count                     */
+    u32    hwsm_wdtov;         /*  hwsm timed out                      */
+    u32    swsm_success;       /*  swsm success                        */
+    u32    swsm_wdtov;         /*  swsm timed out                      */
+    u32    error_resets;       /*  error resets initiated by upsm      */
+    u32    sync_lost;          /*  Sync loss count                     */
+    u32    sig_lost;           /*  Signal loss count                   */
+};
+
+struct bfa_fw_port_physm_stats_s {
+    u32    module_inserts;     /*  Module insert count                 */
+    u32    module_xtracts;     /*  Module extracts count               */
+    u32    module_invalids;    /*  Invalid module inserted count       */
+    u32    module_read_ign;    /*  Module validation status ignored    */
+    u32    laser_faults;       /*  Laser fault count                   */
+    u32    rsvd;
+};
+
+struct bfa_fw_fip_stats_s {
+    u32    vlan_req;           /*  vlan discovery requests             */
+    u32    vlan_notify;        /*  vlan notifications                  */
+    u32    vlan_err;           /*  vlan response error                 */
+    u32    vlan_timeouts;      /*  vlan disvoery timeouts              */
+    u32    vlan_invalids;      /*  invalid vlan in discovery advert.   */
+    u32    disc_req;           /*  Discovery solicit requests          */
+    u32    disc_rsp;           /*  Discovery solicit response          */
+    u32    disc_err;           /*  Discovery advt. parse errors        */
+    u32    disc_unsol;         /*  Discovery unsolicited               */
+    u32    disc_timeouts;      /*  Discovery timeouts                  */
+    u32    disc_fcf_unavail;   /*  Discovery FCF Not Avail.            */
+    u32    linksvc_unsupp;     /*  Unsupported link service req        */
+    u32    linksvc_err;        /*  Parse error in link service req     */
+    u32    logo_req;           /*  FIP logos received                  */
+    u32    clrvlink_req;       /*  Clear virtual link req              */
+    u32    op_unsupp;          /*  Unsupported FIP operation           */
+    u32    untagged;           /*  Untagged frames (ignored)           */
+    u32    invalid_version;    /*  Invalid FIP version                 */
+};
+
+struct bfa_fw_lps_stats_s {
+    u32    mac_invalids;       /*  Invalid mac assigned                */
+    u32    rsvd;
+};
+
+struct bfa_fw_fcoe_stats_s {
+    u32    cee_linkups;        /*  CEE link up count                   */
+    u32    cee_linkdns;        /*  CEE link down count                 */
+    u32    fip_linkups;        /*  FIP link up count                   */
+    u32    fip_linkdns;        /*  FIP link up count                   */
+    u32    fip_fails;          /*  FIP fail count                      */
+    u32    mac_invalids;       /*  Invalid mac assigned                */
+};
+
+/**
+ * IOC firmware FCoE port stats
+ */
+struct bfa_fw_fcoe_port_stats_s {
+    struct bfa_fw_fcoe_stats_s  fcoe_stats;
+    struct bfa_fw_fip_stats_s   fip_stats;
+};
+
+/**
+ * IOC firmware FC uport stats
+ */
+struct bfa_fw_fc_uport_stats_s {
+	struct bfa_fw_port_snsm_stats_s		snsm_stats;
+	struct bfa_fw_port_lksm_stats_s		lksm_stats;
+};
+
+/**
+ * IOC firmware FC port stats
+ */
+union bfa_fw_fc_port_stats_s {
+	struct bfa_fw_fc_uport_stats_s	fc_stats;
+	struct bfa_fw_fcoe_port_stats_s	fcoe_stats;
+};
+
+/**
+ * IOC firmware port stats
+ */
+struct bfa_fw_port_stats_s {
+	struct bfa_fw_port_fpg_stats_s		fpg_stats;
+	struct bfa_fw_port_physm_stats_s	physm_stats;
+	union  bfa_fw_fc_port_stats_s		fc_port;
+};
+
+/**
+ * fcxchg module statistics
+ */
+struct bfa_fw_fcxchg_stats_s {
+	u32	ua_tag_inv;
+	u32	ua_state_inv;
+};
+
+struct bfa_fw_lpsm_stats_s {
+	u32	cls_rx;
+	u32	cls_tx;
+};
+
+/**
+ *  Trunk statistics
+ */
+struct bfa_fw_trunk_stats_s {
+	u32 emt_recvd;		/*  Trunk EMT received		*/
+	u32 emt_accepted;		/*  Trunk EMT Accepted		*/
+	u32 emt_rejected;		/*  Trunk EMT rejected		*/
+	u32 etp_recvd;		/*  Trunk ETP received		*/
+	u32 etp_accepted;		/*  Trunk ETP Accepted		*/
+	u32 etp_rejected;		/*  Trunk ETP rejected		*/
+	u32 lr_recvd;		/*  Trunk LR received		*/
+	u32 rsvd;			/*  padding for 64 bit alignment */
+};
+
+struct bfa_fw_advsm_stats_s {
+	u32 flogi_sent;		/*  Flogi sent			*/
+	u32 flogi_acc_recvd;	/*  Flogi Acc received		*/
+	u32 flogi_rjt_recvd;	/*  Flogi rejects received	*/
+	u32 flogi_retries;		/*  Flogi retries		*/
+
+	u32 elp_recvd;		/*  ELP received		*/
+	u32 elp_accepted;		/*  ELP Accepted		*/
+	u32 elp_rejected;		/*  ELP rejected		*/
+	u32 elp_dropped;		/*  ELP dropped		*/
+};
+
+/**
+ * IOCFC firmware stats
+ */
+struct bfa_fw_iocfc_stats_s {
+	u32	cfg_reqs;	/*  cfg request */
+	u32	updq_reqs;	/*  update queue request */
+	u32	ic_reqs;	/*  interrupt coalesce reqs */
+	u32	unknown_reqs;
+	u32	set_intr_reqs;	/*  set interrupt reqs */
+};
+
+/**
+ * IOC attributes returned in queries
+ */
+struct bfa_iocfc_attr_s {
+	struct bfa_iocfc_cfg_s		config;		/*  IOCFC config   */
+	struct bfa_iocfc_intr_attr_s	intr_attr;	/*  interrupt attr */
+};
+
+/**
+ * Eth_sndrcv mod stats
+ */
+struct bfa_fw_eth_sndrcv_stats_s {
+	u32	crc_err;
+	u32	rsvd;		/*  64bit align    */
+};
+
+/**
+ * CT MAC mod stats
+ */
+struct bfa_fw_mac_mod_stats_s {
+	u32	mac_on;		/*  MAC got turned-on */
+	u32	link_up;	/*  link-up */
+	u32	signal_off;	/*  lost signal */
+	u32	dfe_on;		/*  DFE on */
+	u32	mac_reset;	/*  # of MAC reset to bring lnk up */
+	u32	pcs_reset;	/*  # of PCS reset to bring lnk up */
+	u32	loopback;	/*  MAC got into serdes loopback */
+	u32	lb_mac_reset;
+			/*  # of MAC reset to bring link up in loopback */
+	u32	lb_pcs_reset;
+			/*  # of PCS reset to bring link up in loopback */
+	u32	rsvd;		/*  64bit align    */
+};
+
+/**
+ * CT MOD stats
+ */
+struct bfa_fw_ct_mod_stats_s {
+	u32	rxa_rds_undrun;	/*  RxA RDS underrun */
+	u32	rad_bpc_ovfl;	/*  RAD BPC overflow */
+	u32	rad_rlb_bpc_ovfl; /*  RAD RLB BPC overflow */
+	u32	bpc_fcs_err;	/*  BPC FCS_ERR */
+	u32	txa_tso_hdr;	/*  TxA TSO header too long */
+	u32	rsvd;		/*  64bit align    */
+};
+
+/**
+ * IOC firmware stats
+ */
+struct bfa_fw_stats_s {
+	struct bfa_fw_ioc_stats_s	ioc_stats;
+	struct bfa_fw_iocfc_stats_s	iocfc_stats;
+	struct bfa_fw_io_stats_s	io_stats;
+	struct bfa_fw_port_stats_s	port_stats;
+	struct bfa_fw_fcxchg_stats_s	fcxchg_stats;
+	struct bfa_fw_lpsm_stats_s	lpsm_stats;
+	struct bfa_fw_lps_stats_s	lps_stats;
+	struct bfa_fw_trunk_stats_s	trunk_stats;
+	struct bfa_fw_advsm_stats_s	advsm_stats;
+	struct bfa_fw_mac_mod_stats_s	macmod_stats;
+	struct bfa_fw_ct_mod_stats_s	ctmod_stats;
+	struct bfa_fw_eth_sndrcv_stats_s	ethsndrcv_stats;
+};
+
+#define BFA_IOCFC_PATHTOV_MAX	60
+#define BFA_IOCFC_QDEPTH_MAX	2000
+
+/**
+ * QoS states
+ */
+enum bfa_qos_state {
+	BFA_QOS_ONLINE = 1,		/*  QoS is online */
+	BFA_QOS_OFFLINE = 2,		/*  QoS is offline */
+};
+
+/**
+ * QoS  Priority levels.
+ */
+enum bfa_qos_priority {
+	BFA_QOS_UNKNOWN = 0,
+	BFA_QOS_HIGH  = 1,	/*  QoS Priority Level High */
+	BFA_QOS_MED  =  2,	/*  QoS Priority Level Medium */
+	BFA_QOS_LOW  =  3,	/*  QoS Priority Level Low */
+};
+
+/**
+ * QoS  bandwidth allocation for each priority level
+ */
+enum bfa_qos_bw_alloc {
+	BFA_QOS_BW_HIGH  = 60,	/*  bandwidth allocation for High */
+	BFA_QOS_BW_MED  =  30,	/*  bandwidth allocation for Medium */
+	BFA_QOS_BW_LOW  =  10,	/*  bandwidth allocation for Low */
+};
+#pragma pack(1)
+/**
+ * QoS attribute returned in QoS Query
+ */
+struct bfa_qos_attr_s {
+	u8		state;		/*  QoS current state */
+	u8		rsvd[3];
+	u32  total_bb_cr;		/*  Total BB Credits */
+};
+
+/**
+ * These fields should be displayed only from the CLI.
+ * There will be a separate BFAL API (get_qos_vc_attr ?)
+ * to retrieve this.
+ *
+ */
+#define  BFA_QOS_MAX_VC  16
+
+struct bfa_qos_vc_info_s {
+	u8 vc_credit;
+	u8 borrow_credit;
+	u8 priority;
+	u8 resvd;
+};
+
+struct bfa_qos_vc_attr_s {
+	u16  total_vc_count;                    /*  Total VC Count */
+	u16  shared_credit;
+	u32  elp_opmode_flags;
+	struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC];  /*   as many as
+							    * total_vc_count */
+};
+
+/**
+ * QoS statistics
+ */
+struct bfa_qos_stats_s {
+	u32	flogi_sent;		/*  QoS Flogi sent */
+	u32	flogi_acc_recvd;	/*  QoS Flogi Acc received */
+	u32	flogi_rjt_recvd; /*  QoS Flogi rejects received */
+	u32	flogi_retries;		/*  QoS Flogi retries */
+
+	u32	elp_recvd;		/*  QoS ELP received */
+	u32	elp_accepted;		/*  QoS ELP Accepted */
+	u32	elp_rejected;       /*  QoS ELP rejected */
+	u32	elp_dropped;        /*  QoS ELP dropped  */
+
+	u32	qos_rscn_recvd;     /*  QoS RSCN received */
+	u32	rsvd;		    /* padding for 64 bit alignment */
+};
+
+/**
+ * FCoE statistics
+ */
+struct bfa_fcoe_stats_s {
+	u64	secs_reset;	/*  Seconds since stats reset	     */
+	u64	cee_linkups;	/*  CEE link up		     */
+	u64	cee_linkdns;	/*  CEE link down		     */
+	u64	fip_linkups;	/*  FIP link up		     */
+	u64	fip_linkdns;	/*  FIP link down		     */
+	u64	fip_fails;	/*  FIP failures		     */
+	u64	mac_invalids;	/*  Invalid mac assignments	     */
+	u64	vlan_req;	/*  Vlan requests		     */
+	u64	vlan_notify;	/*  Vlan notifications		     */
+	u64	vlan_err;	/*  Vlan notification errors	     */
+	u64	vlan_timeouts;	/*  Vlan request timeouts	     */
+	u64	vlan_invalids;	/*  Vlan invalids		     */
+	u64	disc_req;	/*  Discovery requests		     */
+	u64	disc_rsp;	/*  Discovery responses	     */
+	u64	disc_err;	/*  Discovery error frames	     */
+	u64	disc_unsol;	/*  Discovery unsolicited	     */
+	u64	disc_timeouts;	/*  Discovery timeouts		     */
+	u64	disc_fcf_unavail; /*  Discovery FCF not avail	     */
+	u64	linksvc_unsupp;	/*  FIP link service req unsupp.    */
+	u64	linksvc_err;	/*  FIP link service req errors     */
+	u64	logo_req;	/*  FIP logos received		     */
+	u64	clrvlink_req;	/*  Clear virtual link requests     */
+	u64	op_unsupp;	/*  FIP operation unsupp.	     */
+	u64	untagged;	/*  FIP untagged frames	     */
+	u64	txf_ucast;	/*  Tx FCoE unicast frames	     */
+	u64	txf_ucast_vlan;	/*  Tx FCoE unicast vlan frames     */
+	u64	txf_ucast_octets; /*  Tx FCoE unicast octets	     */
+	u64	txf_mcast;	/*  Tx FCoE multicast frames	     */
+	u64	txf_mcast_vlan;	/*  Tx FCoE multicast vlan frames   */
+	u64	txf_mcast_octets; /*  Tx FCoE multicast octets	     */
+	u64	txf_bcast;	/*  Tx FCoE broadcast frames	     */
+	u64	txf_bcast_vlan;	/*  Tx FCoE broadcast vlan frames   */
+	u64	txf_bcast_octets; /*  Tx FCoE broadcast octets	     */
+	u64	txf_timeout;	/*  Tx timeouts		     */
+	u64	txf_parity_errors; /*  Transmit parity err	     */
+	u64	txf_fid_parity_errors; /*  Transmit FID parity err  */
+	u64	rxf_ucast_octets; /*  Rx FCoE unicast octets	     */
+	u64	rxf_ucast;	/*  Rx FCoE unicast frames	     */
+	u64	rxf_ucast_vlan;	/*  Rx FCoE unicast vlan frames     */
+	u64	rxf_mcast_octets; /*  Rx FCoE multicast octets	     */
+	u64	rxf_mcast;	/*  Rx FCoE multicast frames	     */
+	u64	rxf_mcast_vlan;	/*  Rx FCoE multicast vlan frames   */
+	u64	rxf_bcast_octets; /*  Rx FCoE broadcast octets	     */
+	u64	rxf_bcast;	/*  Rx FCoE broadcast frames	     */
+	u64	rxf_bcast_vlan;	/*  Rx FCoE broadcast vlan frames   */
+};
+
+/**
+ * QoS or FCoE stats (fcport stats excluding physical FC port stats)
+ */
+union bfa_fcport_stats_u {
+	struct bfa_qos_stats_s	fcqos;
+	struct bfa_fcoe_stats_s	fcoe;
+};
+#pragma pack()
+
+struct bfa_fcpim_del_itn_stats_s {
+	u32	del_itn_iocomp_aborted;	   /* Aborted IO requests	      */
+	u32	del_itn_iocomp_timedout;   /* IO timeouts		      */
+	u32	del_itn_iocom_sqer_needed; /* IO retry for SQ error recovery  */
+	u32	del_itn_iocom_res_free;    /* Delayed freeing of IO resources */
+	u32	del_itn_iocom_hostabrts;   /* Host IO abort requests	      */
+	u32	del_itn_total_ios;	   /* Total IO count		      */
+	u32	del_io_iocdowns;	   /* IO cleaned-up due to IOC down   */
+	u32	del_tm_iocdowns;	   /* TM cleaned-up due to IOC down   */
+};
+
+struct bfa_itnim_iostats_s {
+
+	u32	total_ios;		/*  Total IO Requests		*/
+	u32	input_reqs;		/*  Data in-bound requests	*/
+	u32	output_reqs;		/*  Data out-bound requests	*/
+	u32	io_comps;		/*  Total IO Completions	*/
+	u32	wr_throughput;		/*  Write data transfered in bytes */
+	u32	rd_throughput;		/*  Read data transfered in bytes  */
+
+	u32	iocomp_ok;		/*  Slowpath IO completions	*/
+	u32	iocomp_underrun;	/*  IO underrun		*/
+	u32	iocomp_overrun;		/*  IO overrun			*/
+	u32	qwait;			/*  IO Request-Q wait		*/
+	u32	qresumes;		/*  IO Request-Q wait done	*/
+	u32	no_iotags;		/*  No free IO tag		*/
+	u32	iocomp_timedout;	/*  IO timeouts		*/
+	u32	iocom_nexus_abort;	/*  IO failure due to target offline */
+	u32	iocom_proto_err;	/*  IO protocol errors		*/
+	u32	iocom_dif_err;		/*  IO SBC-3 protection errors	*/
+
+	u32	iocom_sqer_needed;	/*  fcp-2 error recovery failed	*/
+	u32	iocom_res_free;		/*  Delayed freeing of IO tag	*/
+
+
+	u32	io_aborts;		/*  Host IO abort requests	*/
+	u32	iocom_hostabrts;	/*  Host IO abort completions	*/
+	u32	io_cleanups;		/*  IO clean-up requests	*/
+	u32	path_tov_expired;	/*  IO path tov expired	*/
+	u32	iocomp_aborted;		/*  IO abort completions	*/
+	u32	io_iocdowns;		/*  IO cleaned-up due to IOC down */
+	u32	iocom_utags;		/*  IO comp with unknown tags	*/
+
+	u32	io_tmaborts;		/*  Abort request due to TM command */
+	u32	tm_io_comps;		/* Abort completion due to TM command */
+
+	u32	creates;		/*  IT Nexus create requests	*/
+	u32	fw_create;		/*  IT Nexus FW create requests	*/
+	u32	create_comps;		/*  IT Nexus FW create completions */
+	u32	onlines;		/*  IT Nexus onlines		*/
+	u32	offlines;		/*  IT Nexus offlines		*/
+	u32	fw_delete;		/*  IT Nexus FW delete requests	*/
+	u32	delete_comps;		/*  IT Nexus FW delete completions */
+	u32	deletes;		/*  IT Nexus delete requests	   */
+	u32	sler_events;		/*  SLER events		*/
+	u32	ioc_disabled;		/*  Num IOC disables		*/
+	u32	cleanup_comps;		/*  IT Nexus cleanup completions    */
+
+	u32	tm_cmnds;		/*  TM Requests		*/
+	u32	tm_fw_rsps;		/*  TM Completions		*/
+	u32	tm_success;		/*  TM initiated IO cleanup success */
+	u32	tm_failures;		/*  TM initiated IO cleanup failure */
+	u32	no_tskims;		/*  No free TM tag		*/
+	u32	tm_qwait;		/*  TM Request-Q wait		*/
+	u32	tm_qresumes;		/*  TM Request-Q wait done	*/
+
+	u32	tm_iocdowns;		/*  TM cleaned-up due to IOC down   */
+	u32	tm_cleanups;		/*  TM cleanup requests	*/
+	u32	tm_cleanup_comps;	/*  TM cleanup completions	*/
+};
+
+/* Modify char* port_stt[] in bfal_port.c if a new state was added */
+enum bfa_port_states {
+	BFA_PORT_ST_UNINIT		= 1,
+	BFA_PORT_ST_ENABLING_QWAIT	= 2,
+	BFA_PORT_ST_ENABLING		= 3,
+	BFA_PORT_ST_LINKDOWN		= 4,
+	BFA_PORT_ST_LINKUP		= 5,
+	BFA_PORT_ST_DISABLING_QWAIT	= 6,
+	BFA_PORT_ST_DISABLING		= 7,
+	BFA_PORT_ST_DISABLED		= 8,
+	BFA_PORT_ST_STOPPED		= 9,
+	BFA_PORT_ST_IOCDOWN		= 10,
+	BFA_PORT_ST_IOCDIS		= 11,
+	BFA_PORT_ST_FWMISMATCH		= 12,
+	BFA_PORT_ST_PREBOOT_DISABLED	= 13,
+	BFA_PORT_ST_TOGGLING_QWAIT	= 14,
+	BFA_PORT_ST_MAX_STATE,
+};
+
+/**
+ *	Port operational type (in sync with SNIA port type).
+ */
+enum bfa_port_type {
+	BFA_PORT_TYPE_UNKNOWN	= 1,	/*  port type is unknown */
+	BFA_PORT_TYPE_NPORT	= 5,	/*  P2P with switched fabric */
+	BFA_PORT_TYPE_NLPORT	= 6,	/*  public loop */
+	BFA_PORT_TYPE_LPORT	= 20,	/*  private loop */
+	BFA_PORT_TYPE_P2P	= 21,	/*  P2P with no switched fabric */
+	BFA_PORT_TYPE_VPORT	= 22,	/*  NPIV - virtual port */
+};
+
+/**
+ *	Port topology setting. A port's topology and fabric login status
+ *	determine its operational type.
+ */
+enum bfa_port_topology {
+	BFA_PORT_TOPOLOGY_NONE = 0,	/*  No valid topology */
+	BFA_PORT_TOPOLOGY_P2P  = 1,	/*  P2P only */
+	BFA_PORT_TOPOLOGY_LOOP = 2,	/*  LOOP topology */
+	BFA_PORT_TOPOLOGY_AUTO = 3,	/*  auto topology selection */
+};
+
+/**
+ *	Physical port loopback types.
+ */
+enum bfa_port_opmode {
+	BFA_PORT_OPMODE_NORMAL   = 0x00, /*  normal non-loopback mode */
+	BFA_PORT_OPMODE_LB_INT   = 0x01, /*  internal loop back */
+	BFA_PORT_OPMODE_LB_SLW   = 0x02, /*  serial link wrapback (serdes) */
+	BFA_PORT_OPMODE_LB_EXT   = 0x04, /*  external loop back (serdes) */
+	BFA_PORT_OPMODE_LB_CBL   = 0x08, /*  cabled loop back */
+	BFA_PORT_OPMODE_LB_NLINT = 0x20, /*  NL_Port internal loopback */
+};
+
+#define BFA_PORT_OPMODE_LB_HARD(_mode)			\
+	((_mode == BFA_PORT_OPMODE_LB_INT) ||		\
+	(_mode == BFA_PORT_OPMODE_LB_SLW) ||		\
+	(_mode == BFA_PORT_OPMODE_LB_EXT))
+
+/**
+ *	Port link state
+ */
+enum bfa_port_linkstate {
+	BFA_PORT_LINKUP		= 1,	/*  Physical port/Trunk link up */
+	BFA_PORT_LINKDOWN	= 2,	/*  Physical port/Trunk link down */
+};
+
+/**
+ *	Port link state reason code
+ */
+enum bfa_port_linkstate_rsn {
+	BFA_PORT_LINKSTATE_RSN_NONE		= 0,
+	BFA_PORT_LINKSTATE_RSN_DISABLED		= 1,
+	BFA_PORT_LINKSTATE_RSN_RX_NOS		= 2,
+	BFA_PORT_LINKSTATE_RSN_RX_OLS		= 3,
+	BFA_PORT_LINKSTATE_RSN_RX_LIP		= 4,
+	BFA_PORT_LINKSTATE_RSN_RX_LIPF7		= 5,
+	BFA_PORT_LINKSTATE_RSN_SFP_REMOVED	= 6,
+	BFA_PORT_LINKSTATE_RSN_PORT_FAULT	= 7,
+	BFA_PORT_LINKSTATE_RSN_RX_LOS		= 8,
+	BFA_PORT_LINKSTATE_RSN_LOCAL_FAULT	= 9,
+	BFA_PORT_LINKSTATE_RSN_REMOTE_FAULT	= 10,
+	BFA_PORT_LINKSTATE_RSN_TIMEOUT		= 11,
+
+
+
+	/* CEE related reason codes/errors */
+	CEE_LLDP_INFO_AGED_OUT			= 20,
+	CEE_LLDP_SHUTDOWN_TLV_RCVD		= 21,
+	CEE_PEER_NOT_ADVERTISE_DCBX		= 22,
+	CEE_PEER_NOT_ADVERTISE_PG		= 23,
+	CEE_PEER_NOT_ADVERTISE_PFC		= 24,
+	CEE_PEER_NOT_ADVERTISE_FCOE		= 25,
+	CEE_PG_NOT_COMPATIBLE			= 26,
+	CEE_PFC_NOT_COMPATIBLE			= 27,
+	CEE_FCOE_NOT_COMPATIBLE			= 28,
+	CEE_BAD_PG_RCVD				= 29,
+	CEE_BAD_BW_RCVD				= 30,
+	CEE_BAD_PFC_RCVD			= 31,
+	CEE_BAD_APP_PRI_RCVD			= 32,
+	CEE_FCOE_PRI_PFC_OFF			= 33,
+	CEE_DUP_CONTROL_TLV_RCVD		= 34,
+	CEE_DUP_FEAT_TLV_RCVD			= 35,
+	CEE_APPLY_NEW_CFG			= 36, /* reason, not error */
+	CEE_PROTOCOL_INIT			= 37, /* reason, not error */
+	CEE_PHY_LINK_DOWN			= 38,
+	CEE_LLS_FCOE_ABSENT			= 39,
+	CEE_LLS_FCOE_DOWN			= 40,
+	CEE_ISCSI_NOT_COMPATIBLE		= 41,
+	CEE_ISCSI_PRI_PFC_OFF			= 42,
+	CEE_ISCSI_PRI_OVERLAP_FCOE_PRI		= 43
+};
+#pragma pack(1)
+/**
+ *      Physical port configuration
+ */
+struct bfa_port_cfg_s {
+	u8	 topology;	/*  bfa_port_topology		*/
+	u8	 speed;		/*  enum bfa_port_speed	*/
+	u8	 trunked;	/*  trunked or not		*/
+	u8	 qos_enabled;	/*  qos enabled or not		*/
+	u8	 cfg_hardalpa;	/*  is hard alpa configured	*/
+	u8	 hardalpa;	/*  configured hard alpa	*/
+	u16 maxfrsize;	/*  maximum frame size		*/
+	u8	 rx_bbcredit;	/*  receive buffer credits	*/
+	u8	 tx_bbcredit;	/*  transmit buffer credits	*/
+	u8	 ratelimit;	/*  ratelimit enabled or not	*/
+	u8	 trl_def_speed;	/*  ratelimit default speed	*/
+	u16 path_tov;	/*  device path timeout	*/
+	u16 q_depth;	/*  SCSI Queue depth		*/
+};
+#pragma pack()
+
+/**
+ *	Port attribute values.
+ */
+struct bfa_port_attr_s {
+	/*
+	 * Static fields
+	 */
+	wwn_t	   nwwn;		/*  node wwn */
+	wwn_t	   pwwn;		/*  port wwn */
+	wwn_t	   factorynwwn;	/*  factory node wwn */
+	wwn_t	   factorypwwn;	/*  factory port wwn */
+	enum fc_cos	cos_supported;	/*  supported class of services */
+	u32	rsvd;
+	struct fc_symname_s	port_symname;	/*  port symbolic name */
+	enum bfa_port_speed speed_supported; /*  supported speeds */
+	bfa_boolean_t   pbind_enabled;
+
+	/*
+	 * Configured values
+	 */
+	struct bfa_port_cfg_s pport_cfg;	/*  pport cfg */
+
+	/*
+	 * Dynamic field - info from BFA
+	 */
+	enum bfa_port_states	port_state;	/*  current port state */
+	enum bfa_port_speed	speed;		/*  current speed */
+	enum bfa_port_topology	topology;	/*  current topology */
+	bfa_boolean_t		beacon;		/*  current beacon status */
+	bfa_boolean_t		link_e2e_beacon; /*  link beacon is on */
+	bfa_boolean_t		plog_enabled;	/*  portlog is enabled */
+
+	/*
+	 * Dynamic field - info from FCS
+	 */
+	u32		pid;		/*  port ID */
+	enum bfa_port_type	port_type;	/*  current topology */
+	u32		loopback;	/*  external loopback */
+	u32		authfail;	/*  auth fail state */
+	bfa_boolean_t		io_profile;	/*  get it from fcpim mod */
+	u8			pad[4];		/*  for 64-bit alignement */
+
+	/* FCoE specific  */
+	u16		fcoe_vlan;
+	u8			rsvd1[6];
+};
+
+/**
+ *	      Port FCP mappings.
+ */
+struct bfa_port_fcpmap_s {
+	char		osdevname[256];
+	u32	bus;
+	u32	target;
+	u32	oslun;
+	u32	fcid;
+	wwn_t	   nwwn;
+	wwn_t	   pwwn;
+	u64	fcplun;
+	char		luid[256];
+};
+
+/**
+ *	      Port RNID info.
+ */
+struct bfa_port_rnid_s {
+	wwn_t	     wwn;
+	u32	  unittype;
+	u32	  portid;
+	u32	  attached_nodes_num;
+	u16	  ip_version;
+	u16	  udp_port;
+	u8	   ipaddr[16];
+	u16	  rsvd;
+	u16	  topologydiscoveryflags;
+};
+
+#pragma pack(1)
+struct bfa_fcport_fcf_s {
+	wwn_t	   name;	   /*  FCF name		 */
+	wwn_t	   fabric_name;    /*  Fabric Name	      */
+	u8		fipenabled;	/*  FIP enabled or not */
+	u8		fipfailed;	/*  FIP failed or not	*/
+	u8		resv[2];
+	u8	 pri;	    /*  FCF priority	     */
+	u8	 version;	/*  FIP version used	 */
+	u8	 available;      /*  Available  for  login    */
+	u8	 fka_disabled;   /*  FKA is disabled	  */
+	u8	 maxsz_verified; /*  FCoE max size verified   */
+	u8	 fc_map[3];      /*  FC map		   */
+	u16	vlan;	   /*  FCoE vlan tag/priority   */
+	u32	fka_adv_per;    /*  FIP  ka advert. period   */
+	mac_t	   mac;	    /*  FCF mac		  */
+};
+
+/**
+ *	Trunk states for BCU/BFAL
+ */
+enum bfa_trunk_state {
+	BFA_TRUNK_DISABLED	= 0,	/*  Trunk is not configured	*/
+	BFA_TRUNK_ONLINE	= 1,	/*  Trunk is online		*/
+	BFA_TRUNK_OFFLINE	= 2,	/*  Trunk is offline		*/
+};
+
+/**
+ *	VC attributes for trunked link
+ */
+struct bfa_trunk_vc_attr_s {
+	u32 bb_credit;
+	u32 elp_opmode_flags;
+	u32 req_credit;
+	u16 vc_credits[8];
+};
+
+/**
+ *	Link state information
+ */
+struct bfa_port_link_s {
+	u8	 linkstate;	/*  Link state bfa_port_linkstate */
+	u8	 linkstate_rsn;	/*  bfa_port_linkstate_rsn_t */
+	u8	 topology;	/*  P2P/LOOP bfa_port_topology */
+	u8	 speed;		/*  Link speed (1/2/4/8 G) */
+	u32	linkstate_opt;  /*  Linkstate optional data (debug) */
+	u8	 trunked;	/*  Trunked or not (1 or 0) */
+	u8	 resvd[3];
+	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
+	union {
+		struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
+		struct bfa_trunk_vc_attr_s trunk_vc_attr;
+		struct bfa_fcport_fcf_s fcf; /*  FCF information (for FCoE) */
+	} vc_fcf;
+};
+#pragma pack()
+
+enum bfa_trunk_link_fctl {
+	BFA_TRUNK_LINK_FCTL_NORMAL,
+	BFA_TRUNK_LINK_FCTL_VC,
+	BFA_TRUNK_LINK_FCTL_VC_QOS,
+};
+
+enum bfa_trunk_link_state {
+	BFA_TRUNK_LINK_STATE_UP = 1,		/* link part of trunk */
+	BFA_TRUNK_LINK_STATE_DN_LINKDN = 2,	/* physical link down */
+	BFA_TRUNK_LINK_STATE_DN_GRP_MIS = 3,	/* trunk group different */
+	BFA_TRUNK_LINK_STATE_DN_SPD_MIS = 4,	/* speed mismatch */
+	BFA_TRUNK_LINK_STATE_DN_MODE_MIS = 5,	/* remote port not trunked */
+};
+
+#define BFA_TRUNK_MAX_PORTS	2
+struct bfa_trunk_link_attr_s {
+	wwn_t    trunk_wwn;
+	enum bfa_trunk_link_fctl fctl;
+	enum bfa_trunk_link_state link_state;
+	enum bfa_port_speed	speed;
+	u32 deskew;
+};
+
+struct bfa_trunk_attr_s {
+	enum bfa_trunk_state	state;
+	enum bfa_port_speed	speed;
+	u32		port_id;
+	u32		rsvd;
+	struct bfa_trunk_link_attr_s link_attr[BFA_TRUNK_MAX_PORTS];
+};
+
+struct bfa_rport_hal_stats_s {
+	u32        sm_un_cr;	    /*  uninit: create events      */
+	u32        sm_un_unexp;	    /*  uninit: exception events   */
+	u32        sm_cr_on;	    /*  created: online events     */
+	u32        sm_cr_del;	    /*  created: delete events     */
+	u32        sm_cr_hwf;	    /*  created: IOC down          */
+	u32        sm_cr_unexp;	    /*  created: exception events  */
+	u32        sm_fwc_rsp;	    /*  fw create: f/w responses   */
+	u32        sm_fwc_del;	    /*  fw create: delete events   */
+	u32        sm_fwc_off;	    /*  fw create: offline events  */
+	u32        sm_fwc_hwf;	    /*  fw create: IOC down        */
+	u32        sm_fwc_unexp;	    /*  fw create: exception events*/
+	u32        sm_on_off;	    /*  online: offline events     */
+	u32        sm_on_del;	    /*  online: delete events      */
+	u32        sm_on_hwf;	    /*  online: IOC down events    */
+	u32        sm_on_unexp;	    /*  online: exception events   */
+	u32        sm_fwd_rsp;	    /*  fw delete: fw responses    */
+	u32        sm_fwd_del;	    /*  fw delete: delete events   */
+	u32        sm_fwd_hwf;	    /*  fw delete: IOC down events */
+	u32        sm_fwd_unexp;	    /*  fw delete: exception events*/
+	u32        sm_off_del;	    /*  offline: delete events     */
+	u32        sm_off_on;	    /*  offline: online events     */
+	u32        sm_off_hwf;	    /*  offline: IOC down events   */
+	u32        sm_off_unexp;	    /*  offline: exception events  */
+	u32        sm_del_fwrsp;	    /*  delete: fw responses       */
+	u32        sm_del_hwf;	    /*  delete: IOC down events    */
+	u32        sm_del_unexp;	    /*  delete: exception events   */
+	u32        sm_delp_fwrsp;	    /*  delete pend: fw responses  */
+	u32        sm_delp_hwf;	    /*  delete pend: IOC downs     */
+	u32        sm_delp_unexp;	    /*  delete pend: exceptions    */
+	u32        sm_offp_fwrsp;	    /*  off-pending: fw responses  */
+	u32        sm_offp_del;	    /*  off-pending: deletes       */
+	u32        sm_offp_hwf;	    /*  off-pending: IOC downs     */
+	u32        sm_offp_unexp;	    /*  off-pending: exceptions    */
+	u32        sm_iocd_off;	    /*  IOC down: offline events   */
+	u32        sm_iocd_del;	    /*  IOC down: delete events    */
+	u32        sm_iocd_on;	    /*  IOC down: online events    */
+	u32        sm_iocd_unexp;	    /*  IOC down: exceptions       */
+	u32        rsvd;
+};
+#pragma pack(1)
+/**
+ *  Rport's QoS attributes
+ */
+struct bfa_rport_qos_attr_s {
+	u8			qos_priority;  /*  rport's QoS priority   */
+	u8			rsvd[3];
+	u32	       qos_flow_id;	  /*  QoS flow Id	 */
+};
+#pragma pack()
+
+#define BFA_IOBUCKET_MAX 14
+
+struct bfa_itnim_latency_s {
+	u32 min[BFA_IOBUCKET_MAX];
+	u32 max[BFA_IOBUCKET_MAX];
+	u32 count[BFA_IOBUCKET_MAX];
+	u32 avg[BFA_IOBUCKET_MAX];
+};
+
+struct bfa_itnim_ioprofile_s {
+	u32 clock_res_mul;
+	u32 clock_res_div;
+	u32 index;
+	u32 io_profile_start_time;	/*  IO profile start time	*/
+	u32 iocomps[BFA_IOBUCKET_MAX];	/*  IO completed	*/
+	struct bfa_itnim_latency_s io_latency;
+};
+
+/**
+ * FC physical port statistics.
+ */
+struct bfa_port_fc_stats_s {
+	u64     secs_reset;     /*  Seconds since stats is reset */
+	u64     tx_frames;      /*  Tx frames                   */
+	u64     tx_words;       /*  Tx words                    */
+	u64     tx_lip;         /*  Tx LIP                      */
+	u64     tx_nos;         /*  Tx NOS                      */
+	u64     tx_ols;         /*  Tx OLS                      */
+	u64     tx_lr;          /*  Tx LR                       */
+	u64     tx_lrr;         /*  Tx LRR                      */
+	u64     rx_frames;      /*  Rx frames                   */
+	u64     rx_words;       /*  Rx words                    */
+	u64     lip_count;      /*  Rx LIP                      */
+	u64     nos_count;      /*  Rx NOS                      */
+	u64     ols_count;      /*  Rx OLS                      */
+	u64     lr_count;       /*  Rx LR                       */
+	u64     lrr_count;      /*  Rx LRR                      */
+	u64     invalid_crcs;   /*  Rx CRC err frames           */
+	u64     invalid_crc_gd_eof; /*  Rx CRC err good EOF frames */
+	u64     undersized_frm; /*  Rx undersized frames        */
+	u64     oversized_frm;  /*  Rx oversized frames */
+	u64     bad_eof_frm;    /*  Rx frames with bad EOF      */
+	u64     error_frames;   /*  Errored frames              */
+	u64     dropped_frames; /*  Dropped frames              */
+	u64     link_failures;  /*  Link Failure (LF) count     */
+	u64     loss_of_syncs;  /*  Loss of sync count          */
+	u64     loss_of_signals; /*  Loss of signal count       */
+	u64     primseq_errs;   /*  Primitive sequence protocol err. */
+	u64     bad_os_count;   /*  Invalid ordered sets        */
+	u64     err_enc_out;    /*  Encoding err nonframe_8b10b */
+	u64     err_enc;        /*  Encoding err frame_8b10b    */
+};
+
+/**
+ * Eth Physical Port statistics.
+ */
+struct bfa_port_eth_stats_s {
+	u64     secs_reset;     /*  Seconds since stats is reset */
+	u64     frame_64;       /*  Frames 64 bytes             */
+	u64     frame_65_127;   /*  Frames 65-127 bytes */
+	u64     frame_128_255;  /*  Frames 128-255 bytes        */
+	u64     frame_256_511;  /*  Frames 256-511 bytes        */
+	u64     frame_512_1023; /*  Frames 512-1023 bytes       */
+	u64     frame_1024_1518; /*  Frames 1024-1518 bytes     */
+	u64     frame_1519_1522; /*  Frames 1519-1522 bytes     */
+	u64     tx_bytes;       /*  Tx bytes                    */
+	u64     tx_packets;      /*  Tx packets         */
+	u64     tx_mcast_packets; /*  Tx multicast packets      */
+	u64     tx_bcast_packets; /*  Tx broadcast packets      */
+	u64     tx_control_frame; /*  Tx control frame          */
+	u64     tx_drop;        /*  Tx drops                    */
+	u64     tx_jabber;      /*  Tx jabber                   */
+	u64     tx_fcs_error;   /*  Tx FCS errors               */
+	u64     tx_fragments;   /*  Tx fragments                */
+	u64     rx_bytes;       /*  Rx bytes                    */
+	u64     rx_packets;     /*  Rx packets                  */
+	u64     rx_mcast_packets; /*  Rx multicast packets      */
+	u64     rx_bcast_packets; /*  Rx broadcast packets      */
+	u64     rx_control_frames; /*  Rx control frames        */
+	u64     rx_unknown_opcode; /*  Rx unknown opcode        */
+	u64     rx_drop;        /*  Rx drops                    */
+	u64     rx_jabber;      /*  Rx jabber                   */
+	u64     rx_fcs_error;   /*  Rx FCS errors               */
+	u64     rx_alignment_error; /*  Rx alignment errors     */
+	u64     rx_frame_length_error; /*  Rx frame len errors  */
+	u64     rx_code_error;  /*  Rx code errors              */
+	u64     rx_fragments;   /*  Rx fragments                */
+	u64     rx_pause;       /*  Rx pause                    */
+	u64     rx_zero_pause;  /*  Rx zero pause               */
+	u64     tx_pause;       /*  Tx pause                    */
+	u64     tx_zero_pause;  /*  Tx zero pause               */
+	u64     rx_fcoe_pause;  /*  Rx FCoE pause               */
+	u64     rx_fcoe_zero_pause; /*  Rx FCoE zero pause      */
+	u64     tx_fcoe_pause;  /*  Tx FCoE pause               */
+	u64     tx_fcoe_zero_pause; /*  Tx FCoE zero pause      */
+	u64     rx_iscsi_pause; /*  Rx iSCSI pause              */
+	u64     rx_iscsi_zero_pause; /*  Rx iSCSI zero pause    */
+	u64     tx_iscsi_pause; /*  Tx iSCSI pause              */
+	u64     tx_iscsi_zero_pause; /*  Tx iSCSI zero pause    */
+};
+
+/**
+ *              Port statistics.
+ */
+union bfa_port_stats_u {
+	struct bfa_port_fc_stats_s      fc;
+	struct bfa_port_eth_stats_s     eth;
+};
+
+#endif /* __BFA_DEFS_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfa_drv.c b/drivers/scsi/bfa/bfa_drv.c
new file mode 100644
index 0000000..1412764
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_drv.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include "bfa_modules.h"
+
+/**
+ * BFA module list terminated by NULL
+ */
+struct bfa_module_s *hal_mods[] = {
+	&hal_mod_sgpg,
+	&hal_mod_fcport,
+	&hal_mod_fcxp,
+	&hal_mod_lps,
+	&hal_mod_uf,
+	&hal_mod_rport,
+	&hal_mod_fcpim,
+	NULL
+};
+
+/**
+ * Message handlers for various modules.
+ */
+bfa_isr_func_t  bfa_isrs[BFI_MC_MAX] = {
+	bfa_isr_unhandled,	/* NONE */
+	bfa_isr_unhandled,	/* BFI_MC_IOC */
+	bfa_isr_unhandled,	/* BFI_MC_DIAG */
+	bfa_isr_unhandled,	/* BFI_MC_FLASH */
+	bfa_isr_unhandled,	/* BFI_MC_CEE */
+	bfa_fcport_isr,		/* BFI_MC_FCPORT */
+	bfa_isr_unhandled,	/* BFI_MC_IOCFC */
+	bfa_isr_unhandled,	/* BFI_MC_LL */
+	bfa_uf_isr,		/* BFI_MC_UF */
+	bfa_fcxp_isr,		/* BFI_MC_FCXP */
+	bfa_lps_isr,		/* BFI_MC_LPS */
+	bfa_rport_isr,		/* BFI_MC_RPORT */
+	bfa_itnim_isr,		/* BFI_MC_ITNIM */
+	bfa_isr_unhandled,	/* BFI_MC_IOIM_READ */
+	bfa_isr_unhandled,	/* BFI_MC_IOIM_WRITE */
+	bfa_isr_unhandled,	/* BFI_MC_IOIM_IO */
+	bfa_ioim_isr,		/* BFI_MC_IOIM */
+	bfa_ioim_good_comp_isr,	/* BFI_MC_IOIM_IOCOM */
+	bfa_tskim_isr,		/* BFI_MC_TSKIM */
+	bfa_isr_unhandled,	/* BFI_MC_SBOOT */
+	bfa_isr_unhandled,	/* BFI_MC_IPFC */
+	bfa_isr_unhandled,	/* BFI_MC_PORT */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+};
+
+
+/**
+ * Message handlers for mailbox command classes
+ */
+bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[BFI_MC_MAX] = {
+	NULL,
+	NULL,			/* BFI_MC_IOC   */
+	NULL,			/* BFI_MC_DIAG  */
+	NULL,		/* BFI_MC_FLASH */
+	NULL,			/* BFI_MC_CEE   */
+	NULL,			/* BFI_MC_PORT  */
+	bfa_iocfc_isr,		/* BFI_MC_IOCFC */
+	NULL,
+};
+
+
+
+void
+bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
+{
+	struct bfa_port_s	*port = &bfa->modules.port;
+	u32		dm_len;
+	u8			*dm_kva;
+	u64		dm_pa;
+
+	dm_len = bfa_port_meminfo();
+	dm_kva = bfa_meminfo_dma_virt(mi);
+	dm_pa  = bfa_meminfo_dma_phys(mi);
+
+	memset(port, 0, sizeof(struct bfa_port_s));
+	bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod);
+	bfa_port_mem_claim(port, dm_kva, dm_pa);
+
+	bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
+	bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
+}
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
new file mode 100644
index 0000000..6eff705
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -0,0 +1,1916 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FC_H__
+#define __BFA_FC_H__
+
+#include "bfa_os_inc.h"
+
+typedef u64 wwn_t;
+typedef u64 lun_t;
+
+#define WWN_NULL	(0)
+#define FC_SYMNAME_MAX	256	/*  max name server symbolic name size */
+#define FC_ALPA_MAX	128
+
+#pragma pack(1)
+
+#define MAC_ADDRLEN	(6)
+struct mac_s { u8 mac[MAC_ADDRLEN]; };
+#define mac_t struct mac_s
+
+/*
+ * generic SCSI cdb definition
+ */
+#define SCSI_MAX_CDBLEN     16
+struct scsi_cdb_s {
+	u8         scsi_cdb[SCSI_MAX_CDBLEN];
+};
+#define scsi_cdb_t struct scsi_cdb_s
+
+/* ------------------------------------------------------------
+ * SCSI status byte values
+ * ------------------------------------------------------------
+ */
+#define SCSI_STATUS_GOOD                   0x00
+#define SCSI_STATUS_CHECK_CONDITION        0x02
+#define SCSI_STATUS_CONDITION_MET          0x04
+#define SCSI_STATUS_BUSY                   0x08
+#define SCSI_STATUS_INTERMEDIATE           0x10
+#define SCSI_STATUS_ICM                    0x14 /* intermediate condition met */
+#define SCSI_STATUS_RESERVATION_CONFLICT   0x18
+#define SCSI_STATUS_COMMAND_TERMINATED     0x22
+#define SCSI_STATUS_QUEUE_FULL             0x28
+#define SCSI_STATUS_ACA_ACTIVE             0x30
+
+#define SCSI_MAX_ALLOC_LEN      0xFF    /* maximum allocarion length */
+
+/*
+ * Fibre Channel Header Structure (FCHS) definition
+ */
+struct fchs_s {
+#ifdef __BIGENDIAN
+	u32        routing:4;	/* routing bits */
+	u32        cat_info:4;	/* category info */
+#else
+	u32        cat_info:4;	/* category info */
+	u32        routing:4;	/* routing bits */
+#endif
+	u32        d_id:24;	/* destination identifier */
+
+	u32        cs_ctl:8;	/* class specific control */
+	u32        s_id:24;	/* source identifier */
+
+	u32        type:8;		/* data structure type */
+	u32        f_ctl:24;	/* initial frame control */
+
+	u8         seq_id;		/* sequence identifier */
+	u8         df_ctl;		/* data field control */
+	u16        seq_cnt;	/* sequence count */
+
+	u16        ox_id;		/* originator exchange ID */
+	u16        rx_id;		/* responder exchange ID */
+
+	u32        ro;		/* relative offset */
+};
+
+#define FC_SOF_LEN		4
+#define FC_EOF_LEN		4
+#define FC_CRC_LEN		4
+
+/*
+ * Fibre Channel BB_E Header Structure
+ */
+struct fcbbehs_s {
+	u16	ver_rsvd;
+	u32	rsvd[2];
+	u32	rsvd__sof;
+};
+
+#define FC_SEQ_ID_MAX		256
+
+/*
+ * routing bit definitions
+ */
+enum {
+	FC_RTG_FC4_DEV_DATA	= 0x0,	/* FC-4 Device Data */
+	FC_RTG_EXT_LINK		= 0x2,	/* Extended Link Data */
+	FC_RTG_FC4_LINK_DATA	= 0x3,	/* FC-4 Link Data */
+	FC_RTG_VIDEO_DATA	= 0x4,	/* Video Data */
+	FC_RTG_EXT_HDR		= 0x5,	/* VFT, IFR or Encapsuled */
+	FC_RTG_BASIC_LINK	= 0x8,	/* Basic Link data */
+	FC_RTG_LINK_CTRL	= 0xC,	/* Link Control */
+};
+
+/*
+ * information category for extended link data and FC-4 Link Data
+ */
+enum {
+	FC_CAT_LD_REQUEST	= 0x2,	/* Request */
+	FC_CAT_LD_REPLY		= 0x3,	/* Reply */
+	FC_CAT_LD_DIAG		= 0xF,	/* for DIAG use only */
+};
+
+/*
+ * information category for extended headers (VFT, IFR or encapsulation)
+ */
+enum {
+	FC_CAT_VFT_HDR = 0x0,	/* Virtual fabric tagging header */
+	FC_CAT_IFR_HDR = 0x1,	/* Inter-Fabric routing header */
+	FC_CAT_ENC_HDR = 0x2,	/* Encapsulation header */
+};
+
+/*
+ * information category for FC-4 device data
+ */
+enum {
+	FC_CAT_UNCATEG_INFO	= 0x0,	/* Uncategorized information */
+	FC_CAT_SOLICIT_DATA	= 0x1,	/* Solicited Data */
+	FC_CAT_UNSOLICIT_CTRL	= 0x2,	/* Unsolicited Control */
+	FC_CAT_SOLICIT_CTRL	= 0x3,	/* Solicited Control */
+	FC_CAT_UNSOLICIT_DATA	= 0x4,	/* Unsolicited Data */
+	FC_CAT_DATA_DESC	= 0x5,	/* Data Descriptor */
+	FC_CAT_UNSOLICIT_CMD	= 0x6,	/* Unsolicited Command */
+	FC_CAT_CMD_STATUS	= 0x7,	/* Command Status */
+};
+
+/*
+ * information category for Link Control
+ */
+enum {
+	FC_CAT_ACK_1		= 0x00,
+	FC_CAT_ACK_0_N		= 0x01,
+	FC_CAT_P_RJT		= 0x02,
+	FC_CAT_F_RJT		= 0x03,
+	FC_CAT_P_BSY		= 0x04,
+	FC_CAT_F_BSY_DATA	= 0x05,
+	FC_CAT_F_BSY_LINK_CTL	= 0x06,
+	FC_CAT_F_LCR		= 0x07,
+	FC_CAT_NTY		= 0x08,
+	FC_CAT_END		= 0x09,
+};
+
+/*
+ * Type Field Definitions. FC-PH Section 18.5 pg. 165
+ */
+enum {
+	FC_TYPE_BLS		= 0x0,	/* Basic Link Service */
+	FC_TYPE_ELS		= 0x1,	/* Extended Link Service */
+	FC_TYPE_IP		= 0x5,	/* IP */
+	FC_TYPE_FCP		= 0x8,	/* SCSI-FCP */
+	FC_TYPE_GPP		= 0x9,	/* SCSI_GPP */
+	FC_TYPE_SERVICES	= 0x20,	/* Fibre Channel Services */
+	FC_TYPE_FC_FSS		= 0x22,	/* Fabric Switch Services */
+	FC_TYPE_FC_AL		= 0x23,	/* FC-AL */
+	FC_TYPE_FC_SNMP		= 0x24,	/* FC-SNMP */
+	FC_TYPE_FC_SPINFAB	= 0xEE,	/* SPINFAB */
+	FC_TYPE_FC_DIAG		= 0xEF,	/* DIAG */
+	FC_TYPE_MAX		= 256,	/* 256 FC-4 types */
+};
+
+struct fc_fc4types_s {
+	u8         bits[FC_TYPE_MAX / 8];
+};
+
+/*
+ * Frame Control Definitions. FC-PH Table-45. pg. 168
+ */
+enum {
+	FCTL_EC_ORIG = 0x000000,	/* exchange originator */
+	FCTL_EC_RESP = 0x800000,	/* exchange responder */
+	FCTL_SEQ_INI = 0x000000,	/* sequence initiator */
+	FCTL_SEQ_REC = 0x400000,	/* sequence recipient */
+	FCTL_FS_EXCH = 0x200000,	/* first sequence of xchg */
+	FCTL_LS_EXCH = 0x100000,	/* last sequence of xchg */
+	FCTL_END_SEQ = 0x080000,	/* last frame of sequence */
+	FCTL_SI_XFER = 0x010000,	/* seq initiative transfer */
+	FCTL_RO_PRESENT = 0x000008,	/* relative offset present */
+	FCTL_FILLBYTE_MASK = 0x000003	/* , fill byte mask */
+};
+
+/*
+ * Fabric Well Known Addresses
+ */
+enum {
+	FC_MIN_WELL_KNOWN_ADDR		= 0xFFFFF0,
+	FC_DOMAIN_CONTROLLER_MASK	= 0xFFFC00,
+	FC_ALIAS_SERVER			= 0xFFFFF8,
+	FC_MGMT_SERVER			= 0xFFFFFA,
+	FC_TIME_SERVER			= 0xFFFFFB,
+	FC_NAME_SERVER			= 0xFFFFFC,
+	FC_FABRIC_CONTROLLER		= 0xFFFFFD,
+	FC_FABRIC_PORT			= 0xFFFFFE,
+	FC_BROADCAST_SERVER		= 0xFFFFFF
+};
+
+/*
+ * domain/area/port defines
+ */
+#define FC_DOMAIN_MASK  0xFF0000
+#define FC_DOMAIN_SHIFT 16
+#define FC_AREA_MASK    0x00FF00
+#define FC_AREA_SHIFT   8
+#define FC_PORT_MASK    0x0000FF
+#define FC_PORT_SHIFT   0
+
+#define FC_GET_DOMAIN(p)	(((p) & FC_DOMAIN_MASK) >> FC_DOMAIN_SHIFT)
+#define FC_GET_AREA(p)		(((p) & FC_AREA_MASK) >> FC_AREA_SHIFT)
+#define FC_GET_PORT(p)		(((p) & FC_PORT_MASK) >> FC_PORT_SHIFT)
+
+#define FC_DOMAIN_CTRLR(p)	(FC_DOMAIN_CONTROLLER_MASK | (FC_GET_DOMAIN(p)))
+
+enum {
+	FC_RXID_ANY = 0xFFFFU,
+};
+
+/*
+ * generic ELS command
+ */
+struct fc_els_cmd_s {
+	u32        els_code:8;	/* ELS Command Code */
+	u32        reserved:24;
+};
+
+/*
+ * ELS Command Codes. FC-PH Table-75. pg. 223
+ */
+enum {
+	FC_ELS_LS_RJT = 0x1,	/* Link Service Reject. */
+	FC_ELS_ACC = 0x02,	/* Accept */
+	FC_ELS_PLOGI = 0x03,	/* N_Port Login. */
+	FC_ELS_FLOGI = 0x04,	/* F_Port Login. */
+	FC_ELS_LOGO = 0x05,	/* Logout. */
+	FC_ELS_ABTX = 0x06,	/* Abort Exchange */
+	FC_ELS_RES = 0x08,	/* Read Exchange status */
+	FC_ELS_RSS = 0x09,	/* Read sequence status block */
+	FC_ELS_RSI = 0x0A,	/* Request Sequence Initiative */
+	FC_ELS_ESTC = 0x0C,	/* Estimate Credit. */
+	FC_ELS_RTV = 0x0E,	/* Read Timeout Value. */
+	FC_ELS_RLS = 0x0F,	/* Read Link Status. */
+	FC_ELS_ECHO = 0x10,	/* Echo */
+	FC_ELS_TEST = 0x11,	/* Test */
+	FC_ELS_RRQ = 0x12,	/* Reinstate Recovery Qualifier. */
+	FC_ELS_REC = 0x13,	/* Add this for TAPE support in FCR */
+	FC_ELS_PRLI = 0x20,	/* Process Login */
+	FC_ELS_PRLO = 0x21,	/* Process Logout. */
+	FC_ELS_SCN = 0x22,	/* State Change Notification. */
+	FC_ELS_TPRLO = 0x24,	/* Third Party Process Logout. */
+	FC_ELS_PDISC = 0x50,	/* Discover N_Port Parameters. */
+	FC_ELS_FDISC = 0x51,	/* Discover F_Port Parameters. */
+	FC_ELS_ADISC = 0x52,	/* Discover Address. */
+	FC_ELS_FARP_REQ = 0x54,	/* FARP Request. */
+	FC_ELS_FARP_REP = 0x55,	/* FARP Reply. */
+	FC_ELS_FAN = 0x60,	/* Fabric Address Notification */
+	FC_ELS_RSCN = 0x61,	/* Reg State Change Notification */
+	FC_ELS_SCR = 0x62,	/* State Change Registration. */
+	FC_ELS_RTIN = 0x77,	/* Mangement server request */
+	FC_ELS_RNID = 0x78,	/* Mangement server request */
+	FC_ELS_RLIR = 0x79,	/* Registered Link Incident Record */
+
+	FC_ELS_RPSC = 0x7D,	/* Report Port Speed Capabilities */
+	FC_ELS_QSA = 0x7E,	/* Query Security Attributes. Ref FC-SP */
+	FC_ELS_E2E_LBEACON = 0x81,
+				/* End-to-End Link Beacon */
+	FC_ELS_AUTH = 0x90,	/* Authentication. Ref FC-SP */
+	FC_ELS_RFCN = 0x97,	/* Request Fabric Change Notification. Ref
+				 *FC-SP */
+
+};
+
+/*
+ *  Version numbers for FC-PH standards,
+ *  used in login to indicate what port
+ *  supports. See FC-PH-X table 158.
+ */
+enum {
+	FC_PH_VER_4_3 = 0x09,
+	FC_PH_VER_PH_3 = 0x20,
+};
+
+/*
+ * PDU size defines
+ */
+enum {
+	FC_MIN_PDUSZ = 512,
+	FC_MAX_PDUSZ = 2112,
+};
+
+/*
+ * N_Port PLOGI Common Service Parameters.
+ * FC-PH-x. Figure-76. pg. 308.
+ */
+struct fc_plogi_csp_s {
+	u8         verhi;	/* FC-PH high version */
+	u8         verlo;	/* FC-PH low version */
+	u16        bbcred;	/* BB_Credit */
+
+#ifdef __BIGENDIAN
+	u8         ciro:1,		/* continuously increasing RO */
+			rro:1,		/* random relative offset */
+			npiv_supp:1,	/* NPIV supported */
+			port_type:1,	/* N_Port/F_port */
+			altbbcred:1,	/* alternate BB_Credit */
+			resolution:1,	/* ms/ns ED_TOV resolution */
+			vvl_info:1,	/* VVL Info included */
+			reserved1:1;
+
+	u8         hg_supp:1,
+			query_dbc:1,
+			security:1,
+			sync_cap:1,
+			r_t_tov:1,
+			dh_dup_supp:1,
+			cisc:1,		/* continuously increasing seq count */
+			payload:1;
+#else
+	u8         reserved2:2,
+			resolution:1,	/* ms/ns ED_TOV resolution */
+			altbbcred:1,	/* alternate BB_Credit */
+			port_type:1,	/* N_Port/F_port */
+			npiv_supp:1,	/* NPIV supported */
+			rro:1,		/* random relative offset */
+			ciro:1;		/* continuously increasing RO */
+
+	u8         payload:1,
+			cisc:1,		/* continuously increasing seq count */
+			dh_dup_supp:1,
+			r_t_tov:1,
+			sync_cap:1,
+			security:1,
+			query_dbc:1,
+			hg_supp:1;
+#endif
+
+	u16        rxsz;		/* recieve data_field size */
+
+	u16        conseq;
+	u16        ro_bitmap;
+
+	u32        e_d_tov;
+};
+
+/*
+ * N_Port PLOGI Class Specific Parameters.
+ * FC-PH-x. Figure 78. pg. 318.
+ */
+struct fc_plogi_clp_s {
+#ifdef __BIGENDIAN
+	u32        class_valid:1;
+	u32        intermix:1;	/* class intermix supported if set =1.
+					 * valid only for class1. Reserved for
+					 * class2 & class3
+					 */
+	u32        reserved1:2;
+	u32        sequential:1;
+	u32        reserved2:3;
+#else
+	u32        reserved2:3;
+	u32        sequential:1;
+	u32        reserved1:2;
+	u32        intermix:1;	/* class intermix supported if set =1.
+					 * valid only for class1. Reserved for
+					 * class2 & class3
+					 */
+	u32        class_valid:1;
+#endif
+
+	u32        reserved3:24;
+
+	u32        reserved4:16;
+	u32        rxsz:16;	/* Receive data_field size */
+
+	u32        reserved5:8;
+	u32        conseq:8;
+	u32        e2e_credit:16;	/* end to end credit */
+
+	u32        reserved7:8;
+	u32        ospx:8;
+	u32        reserved8:16;
+};
+
+/* ASCII value for each character in string "BRCD" */
+#define FLOGI_VVL_BRCD    0x42524344
+
+/*
+ * PLOGI els command and reply payload
+ */
+struct fc_logi_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	struct fc_plogi_csp_s csp;		/* common service params */
+	wwn_t           port_name;
+	wwn_t           node_name;
+	struct fc_plogi_clp_s class1;		/* class 1 service parameters */
+	struct fc_plogi_clp_s class2;		/* class 2 service parameters */
+	struct fc_plogi_clp_s class3;		/* class 3 service parameters */
+	struct fc_plogi_clp_s class4;		/* class 4 service parameters */
+	u8         vvl[16];	/* vendor version level */
+};
+
+/*
+ * LOGO els command payload
+ */
+struct fc_logo_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        res1:8;
+	u32        nport_id:24;	/* N_Port identifier of source */
+	wwn_t           orig_port_name;	/* Port name of the LOGO originator */
+};
+
+/*
+ * ADISC els command payload
+ */
+struct fc_adisc_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        res1:8;
+	u32        orig_HA:24;	/* originator hard address */
+	wwn_t           orig_port_name;	/* originator port name */
+	wwn_t           orig_node_name;	/* originator node name */
+	u32        res2:8;
+	u32        nport_id:24;	/* originator NPortID */
+};
+
+/*
+ * Exchange status block
+ */
+struct fc_exch_status_blk_s {
+	u32        oxid:16;
+	u32        rxid:16;
+	u32        res1:8;
+	u32        orig_np:24;	/* originator NPortID */
+	u32        res2:8;
+	u32        resp_np:24;	/* responder NPortID */
+	u32        es_bits;
+	u32        res3;
+	/*
+	 * un modified section of the fields
+	 */
+};
+
+/*
+ * RES els command payload
+ */
+struct fc_res_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        res1:8;
+	u32        nport_id:24;	/* N_Port identifier of source */
+	u32        oxid:16;
+	u32        rxid:16;
+	u8         assoc_hdr[32];
+};
+
+/*
+ * RES els accept payload
+ */
+struct fc_res_acc_s {
+	struct fc_els_cmd_s		els_cmd;	/* ELS command code */
+	struct fc_exch_status_blk_s	fc_exch_blk; /* Exchange status block */
+};
+
+/*
+ * REC els command payload
+ */
+struct fc_rec_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        res1:8;
+	u32        nport_id:24;	/* N_Port identifier of source */
+	u32        oxid:16;
+	u32        rxid:16;
+};
+
+#define FC_REC_ESB_OWN_RSP	0x80000000	/* responder owns */
+#define FC_REC_ESB_SI		0x40000000	/* SI is owned	*/
+#define FC_REC_ESB_COMP		0x20000000	/* exchange is complete	*/
+#define FC_REC_ESB_ENDCOND_ABN	0x10000000	/* abnormal ending	*/
+#define FC_REC_ESB_RQACT	0x04000000	/* recovery qual active	*/
+#define FC_REC_ESB_ERRP_MSK	0x03000000
+#define FC_REC_ESB_OXID_INV	0x00800000	/* invalid OXID		*/
+#define FC_REC_ESB_RXID_INV	0x00400000	/* invalid RXID		*/
+#define FC_REC_ESB_PRIO_INUSE	0x00200000
+
+/*
+ * REC els accept payload
+ */
+struct fc_rec_acc_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        oxid:16;
+	u32        rxid:16;
+	u32        res1:8;
+	u32        orig_id:24;	/* N_Port id of exchange originator */
+	u32        res2:8;
+	u32        resp_id:24;	/* N_Port id of exchange responder */
+	u32        count;		/* data transfer count */
+	u32        e_stat;		/* exchange status */
+};
+
+/*
+ * RSI els payload
+ */
+struct fc_rsi_s {
+	struct fc_els_cmd_s els_cmd;
+	u32        res1:8;
+	u32        orig_sid:24;
+	u32        oxid:16;
+	u32        rxid:16;
+};
+
+/*
+ * structure for PRLI paramater pages, both request & response
+ * see FC-PH-X table 113 & 115 for explanation also FCP table 8
+ */
+struct fc_prli_params_s {
+	u32        reserved:16;
+#ifdef __BIGENDIAN
+	u32        reserved1:5;
+	u32        rec_support:1;
+	u32        task_retry_id:1;
+	u32        retry:1;
+
+	u32        confirm:1;
+	u32        doverlay:1;
+	u32        initiator:1;
+	u32        target:1;
+	u32        cdmix:1;
+	u32        drmix:1;
+	u32        rxrdisab:1;
+	u32        wxrdisab:1;
+#else
+	u32        retry:1;
+	u32        task_retry_id:1;
+	u32        rec_support:1;
+	u32        reserved1:5;
+
+	u32        wxrdisab:1;
+	u32        rxrdisab:1;
+	u32        drmix:1;
+	u32        cdmix:1;
+	u32        target:1;
+	u32        initiator:1;
+	u32        doverlay:1;
+	u32        confirm:1;
+#endif
+};
+
+/*
+ * valid values for rspcode in PRLI ACC payload
+ */
+enum {
+	FC_PRLI_ACC_XQTD = 0x1,		/* request executed */
+	FC_PRLI_ACC_PREDEF_IMG = 0x5,	/* predefined image - no prli needed */
+};
+
+struct fc_prli_params_page_s {
+	u32        type:8;
+	u32        codext:8;
+#ifdef __BIGENDIAN
+	u32        origprocasv:1;
+	u32        rsppav:1;
+	u32        imagepair:1;
+	u32        reserved1:1;
+	u32        rspcode:4;
+#else
+	u32        rspcode:4;
+	u32        reserved1:1;
+	u32        imagepair:1;
+	u32        rsppav:1;
+	u32        origprocasv:1;
+#endif
+	u32        reserved2:8;
+
+	u32        origprocas;
+	u32        rspprocas;
+	struct fc_prli_params_s servparams;
+};
+
+/*
+ * PRLI request and accept payload, FC-PH-X tables 112 & 114
+ */
+struct fc_prli_s {
+	u32        command:8;
+	u32        pglen:8;
+	u32        pagebytes:16;
+	struct fc_prli_params_page_s parampage;
+};
+
+/*
+ * PRLO logout params page
+ */
+struct fc_prlo_params_page_s {
+	u32        type:8;
+	u32        type_ext:8;
+#ifdef __BIGENDIAN
+	u32        opa_valid:1;	/* originator process associator
+					 * valid
+					 */
+	u32        rpa_valid:1;	/* responder process associator valid */
+	u32        res1:14;
+#else
+	u32        res1:14;
+	u32        rpa_valid:1;	/* responder process associator valid */
+	u32        opa_valid:1;	/* originator process associator
+					 * valid
+					 */
+#endif
+	u32        orig_process_assc;
+	u32        resp_process_assc;
+
+	u32        res2;
+};
+
+/*
+ * PRLO els command payload
+ */
+struct fc_prlo_s {
+	u32	command:8;
+	u32	page_len:8;
+	u32	payload_len:16;
+	struct fc_prlo_params_page_s	prlo_params[1];
+};
+
+/*
+ * PRLO Logout response parameter page
+ */
+struct fc_prlo_acc_params_page_s {
+	u32        type:8;
+	u32        type_ext:8;
+
+#ifdef __BIGENDIAN
+	u32        opa_valid:1;	/* originator process associator
+					 * valid
+					 */
+	u32        rpa_valid:1;	/* responder process associator valid */
+	u32        res1:14;
+#else
+	u32        res1:14;
+	u32        rpa_valid:1;	/* responder process associator valid */
+	u32        opa_valid:1;	/* originator process associator
+					 * valid
+					 */
+#endif
+	u32        orig_process_assc;
+	u32        resp_process_assc;
+
+	u32        fc4type_csp;
+};
+
+/*
+ * PRLO els command ACC payload
+ */
+struct fc_prlo_acc_s {
+	u32        command:8;
+	u32        page_len:8;
+	u32        payload_len:16;
+	struct fc_prlo_acc_params_page_s prlo_acc_params[1];
+};
+
+/*
+ * SCR els command payload
+ */
+enum {
+	FC_SCR_REG_FUNC_FABRIC_DETECTED = 0x01,
+	FC_SCR_REG_FUNC_N_PORT_DETECTED = 0x02,
+	FC_SCR_REG_FUNC_FULL = 0x03,
+	FC_SCR_REG_FUNC_CLEAR_REG = 0xFF,
+};
+
+/* SCR VU registrations */
+enum {
+	FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE = 0x01
+};
+
+struct fc_scr_s {
+	u32 command:8;
+	u32 res:24;
+	u32 vu_reg_func:8; /* Vendor Unique Registrations */
+	u32 res1:16;
+	u32 reg_func:8;
+};
+
+/*
+ * Information category for Basic link data
+ */
+enum {
+	FC_CAT_NOP	= 0x0,
+	FC_CAT_ABTS	= 0x1,
+	FC_CAT_RMC	= 0x2,
+	FC_CAT_BA_ACC	= 0x4,
+	FC_CAT_BA_RJT	= 0x5,
+	FC_CAT_PRMT	= 0x6,
+};
+
+/*
+ * LS_RJT els reply payload
+ */
+struct fc_ls_rjt_s {
+	struct fc_els_cmd_s els_cmd;		/* ELS command code */
+	u32        res1:8;
+	u32        reason_code:8;		/* Reason code for reject */
+	u32        reason_code_expl:8;	/* Reason code explanation */
+	u32        vendor_unique:8;	/* Vendor specific */
+};
+
+/*
+ * LS_RJT reason codes
+ */
+enum {
+	FC_LS_RJT_RSN_INV_CMD_CODE	= 0x01,
+	FC_LS_RJT_RSN_LOGICAL_ERROR	= 0x03,
+	FC_LS_RJT_RSN_LOGICAL_BUSY	= 0x05,
+	FC_LS_RJT_RSN_PROTOCOL_ERROR	= 0x07,
+	FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD = 0x09,
+	FC_LS_RJT_RSN_CMD_NOT_SUPP	= 0x0B,
+};
+
+/*
+ * LS_RJT reason code explanation
+ */
+enum {
+	FC_LS_RJT_EXP_NO_ADDL_INFO		= 0x00,
+	FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS	= 0x01,
+	FC_LS_RJT_EXP_SPARMS_ERR_INI_CTL	= 0x03,
+	FC_LS_RJT_EXP_SPARMS_ERR_REC_CTL	= 0x05,
+	FC_LS_RJT_EXP_SPARMS_ERR_RXSZ		= 0x07,
+	FC_LS_RJT_EXP_SPARMS_ERR_CONSEQ		= 0x09,
+	FC_LS_RJT_EXP_SPARMS_ERR_CREDIT		= 0x0B,
+	FC_LS_RJT_EXP_INV_PORT_NAME		= 0x0D,
+	FC_LS_RJT_EXP_INV_NODE_FABRIC_NAME	= 0x0E,
+	FC_LS_RJT_EXP_INV_CSP			= 0x0F,
+	FC_LS_RJT_EXP_INV_ASSOC_HDR		= 0x11,
+	FC_LS_RJT_EXP_ASSOC_HDR_REQD		= 0x13,
+	FC_LS_RJT_EXP_INV_ORIG_S_ID		= 0x15,
+	FC_LS_RJT_EXP_INV_OXID_RXID_COMB	= 0x17,
+	FC_LS_RJT_EXP_CMD_ALREADY_IN_PROG	= 0x19,
+	FC_LS_RJT_EXP_LOGIN_REQUIRED		= 0x1E,
+	FC_LS_RJT_EXP_INVALID_NPORT_ID		= 0x1F,
+	FC_LS_RJT_EXP_INSUFF_RES		= 0x29,
+	FC_LS_RJT_EXP_CMD_NOT_SUPP		= 0x2C,
+	FC_LS_RJT_EXP_INV_PAYLOAD_LEN		= 0x2D,
+};
+
+/*
+ * RRQ els command payload
+ */
+struct fc_rrq_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        res1:8;
+	u32        s_id:24;	/* exchange originator S_ID */
+
+	u32        ox_id:16;	/* originator exchange ID */
+	u32        rx_id:16;	/* responder exchange ID */
+
+	u32        res2[8];	/* optional association header */
+};
+
+/*
+ * ABTS BA_ACC reply payload
+ */
+struct fc_ba_acc_s {
+	u32        seq_id_valid:8;	/* set to 0x00 for Abort Exchange */
+	u32        seq_id:8;	/* invalid for Abort Exchange */
+	u32        res2:16;
+	u32        ox_id:16;	/* OX_ID from ABTS frame */
+	u32        rx_id:16;	/* RX_ID from ABTS frame */
+	u32        low_seq_cnt:16;	/* set to 0x0000 for Abort Exchange */
+	u32        high_seq_cnt:16;/* set to 0xFFFF for Abort Exchange */
+};
+
+/*
+ * ABTS BA_RJT reject payload
+ */
+struct fc_ba_rjt_s {
+	u32        res1:8;		/* Reserved */
+	u32        reason_code:8;	/* reason code for reject */
+	u32        reason_expl:8;	/* reason code explanation */
+	u32        vendor_unique:8;/* vendor unique reason code,set to 0 */
+};
+
+/*
+ * TPRLO logout parameter page
+ */
+struct fc_tprlo_params_page_s {
+u32        type:8;
+u32        type_ext:8;
+
+#ifdef __BIGENDIAN
+	u32        opa_valid:1;
+	u32        rpa_valid:1;
+	u32        tpo_nport_valid:1;
+	u32        global_process_logout:1;
+	u32        res1:12;
+#else
+	u32        res1:12;
+	u32        global_process_logout:1;
+	u32        tpo_nport_valid:1;
+	u32        rpa_valid:1;
+	u32        opa_valid:1;
+#endif
+
+	u32        orig_process_assc;
+	u32        resp_process_assc;
+
+	u32        res2:8;
+	u32        tpo_nport_id;
+};
+
+/*
+ * TPRLO ELS command payload
+ */
+struct fc_tprlo_s {
+	u32        command:8;
+	u32        page_len:8;
+	u32        payload_len:16;
+
+	struct fc_tprlo_params_page_s tprlo_params[1];
+};
+
+enum fc_tprlo_type {
+	FC_GLOBAL_LOGO = 1,
+	FC_TPR_LOGO
+};
+
+/*
+ * TPRLO els command ACC payload
+ */
+struct fc_tprlo_acc_s {
+	u32	command:8;
+	u32	page_len:8;
+	u32	payload_len:16;
+	struct fc_prlo_acc_params_page_s tprlo_acc_params[1];
+};
+
+/*
+ * RSCN els command req payload
+ */
+#define FC_RSCN_PGLEN	0x4
+
+enum fc_rscn_format {
+	FC_RSCN_FORMAT_PORTID	= 0x0,
+	FC_RSCN_FORMAT_AREA	= 0x1,
+	FC_RSCN_FORMAT_DOMAIN	= 0x2,
+	FC_RSCN_FORMAT_FABRIC	= 0x3,
+};
+
+struct fc_rscn_event_s {
+	u32        format:2;
+	u32        qualifier:4;
+	u32        resvd:2;
+	u32        portid:24;
+};
+
+struct fc_rscn_pl_s {
+	u8         command;
+	u8         pagelen;
+	u16        payldlen;
+	struct fc_rscn_event_s event[1];
+};
+
+/*
+ * ECHO els command req payload
+ */
+struct fc_echo_s {
+	struct fc_els_cmd_s els_cmd;
+};
+
+/*
+ * RNID els command
+ */
+
+#define RNID_NODEID_DATA_FORMAT_COMMON			0x00
+#define RNID_NODEID_DATA_FORMAT_FCP3			0x08
+#define RNID_NODEID_DATA_FORMAT_DISCOVERY		0xDF
+
+#define RNID_ASSOCIATED_TYPE_UNKNOWN			0x00000001
+#define RNID_ASSOCIATED_TYPE_OTHER                      0x00000002
+#define RNID_ASSOCIATED_TYPE_HUB                        0x00000003
+#define RNID_ASSOCIATED_TYPE_SWITCH                     0x00000004
+#define RNID_ASSOCIATED_TYPE_GATEWAY                    0x00000005
+#define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE             0x00000009
+#define RNID_ASSOCIATED_TYPE_HOST                       0x0000000A
+#define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM          0x0000000B
+#define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE      0x0000000E
+#define RNID_ASSOCIATED_TYPE_NAS_SERVER                 0x00000011
+#define RNID_ASSOCIATED_TYPE_BRIDGE                     0x00000002
+#define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE      0x00000003
+#define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE      0x000000FF
+
+/*
+ * RNID els command payload
+ */
+struct fc_rnid_cmd_s {
+	struct fc_els_cmd_s els_cmd;
+	u32        node_id_data_format:8;
+	u32        reserved:24;
+};
+
+/*
+ * RNID els response payload
+ */
+
+struct fc_rnid_common_id_data_s {
+	wwn_t           port_name;
+	wwn_t           node_name;
+};
+
+struct fc_rnid_general_topology_data_s {
+	u32        vendor_unique[4];
+	u32        asso_type;
+	u32        phy_port_num;
+	u32        num_attached_nodes;
+	u32        node_mgmt:8;
+	u32        ip_version:8;
+	u32        udp_tcp_port_num:16;
+	u32        ip_address[4];
+	u32        reserved:16;
+	u32        vendor_specific:16;
+};
+
+struct fc_rnid_acc_s {
+	struct fc_els_cmd_s els_cmd;
+	u32        node_id_data_format:8;
+	u32        common_id_data_length:8;
+	u32        reserved:8;
+	u32        specific_id_data_length:8;
+	struct fc_rnid_common_id_data_s common_id_data;
+	struct fc_rnid_general_topology_data_s gen_topology_data;
+};
+
+#define RNID_ASSOCIATED_TYPE_UNKNOWN                    0x00000001
+#define RNID_ASSOCIATED_TYPE_OTHER                      0x00000002
+#define RNID_ASSOCIATED_TYPE_HUB                        0x00000003
+#define RNID_ASSOCIATED_TYPE_SWITCH                     0x00000004
+#define RNID_ASSOCIATED_TYPE_GATEWAY                    0x00000005
+#define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE             0x00000009
+#define RNID_ASSOCIATED_TYPE_HOST                       0x0000000A
+#define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM          0x0000000B
+#define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE      0x0000000E
+#define RNID_ASSOCIATED_TYPE_NAS_SERVER                 0x00000011
+#define RNID_ASSOCIATED_TYPE_BRIDGE                     0x00000002
+#define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE      0x00000003
+#define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE      0x000000FF
+
+enum fc_rpsc_speed_cap {
+	RPSC_SPEED_CAP_1G = 0x8000,
+	RPSC_SPEED_CAP_2G = 0x4000,
+	RPSC_SPEED_CAP_4G = 0x2000,
+	RPSC_SPEED_CAP_10G = 0x1000,
+	RPSC_SPEED_CAP_8G = 0x0800,
+	RPSC_SPEED_CAP_16G = 0x0400,
+
+	RPSC_SPEED_CAP_UNKNOWN = 0x0001,
+};
+
+enum fc_rpsc_op_speed {
+	RPSC_OP_SPEED_1G = 0x8000,
+	RPSC_OP_SPEED_2G = 0x4000,
+	RPSC_OP_SPEED_4G = 0x2000,
+	RPSC_OP_SPEED_10G = 0x1000,
+	RPSC_OP_SPEED_8G = 0x0800,
+	RPSC_OP_SPEED_16G = 0x0400,
+
+	RPSC_OP_SPEED_NOT_EST = 0x0001,	/*! speed not established */
+};
+
+struct fc_rpsc_speed_info_s {
+	u16        port_speed_cap;	/*! see enum fc_rpsc_speed_cap */
+	u16        port_op_speed;	/*! see enum fc_rpsc_op_speed */
+};
+
+enum link_e2e_beacon_subcmd {
+	LINK_E2E_BEACON_ON = 1,
+	LINK_E2E_BEACON_OFF = 2
+};
+
+enum beacon_type {
+	BEACON_TYPE_NORMAL	= 1,	/*! Normal Beaconing. Green */
+	BEACON_TYPE_WARN	= 2,	/*! Warning Beaconing. Yellow/Amber */
+	BEACON_TYPE_CRITICAL	= 3	/*! Critical Beaconing. Red */
+};
+
+struct link_e2e_beacon_param_s {
+	u8         beacon_type;	/* Beacon Type. See enum beacon_type */
+	u8         beacon_frequency;
+					/* Beacon frequency. Number of blinks
+					 * per 10 seconds
+					 */
+	u16        beacon_duration;/* Beacon duration (in Seconds). The
+					 * command operation should be
+					 * terminated at the end of this
+					 * timeout value.
+					 *
+					 * Ignored if diag_sub_cmd is
+					 * LINK_E2E_BEACON_OFF.
+					 *
+					 * If 0, beaconing will continue till a
+					 * BEACON OFF request is received
+					 */
+};
+
+/*
+ * Link E2E beacon request/good response format.
+ * For LS_RJTs use struct fc_ls_rjt_s
+ */
+struct link_e2e_beacon_req_s {
+	u32        ls_code;	/*! FC_ELS_E2E_LBEACON in requests *
+					 *or FC_ELS_ACC in good replies */
+	u32        ls_sub_cmd;	/*! See enum link_e2e_beacon_subcmd */
+	struct link_e2e_beacon_param_s beacon_parm;
+};
+
+/**
+ * If RPSC request is sent to the Domain Controller, the request is for
+ * all the ports within that domain (TODO - I don't think FOS implements
+ * this...).
+ */
+struct fc_rpsc_cmd_s {
+	struct fc_els_cmd_s els_cmd;
+};
+
+/*
+ * RPSC Acc
+ */
+struct fc_rpsc_acc_s {
+	u32        command:8;
+	u32        rsvd:8;
+	u32        num_entries:16;
+
+	struct fc_rpsc_speed_info_s speed_info[1];
+};
+
+/**
+ * If RPSC2 request is sent to the Domain Controller,
+ */
+#define FC_BRCD_TOKEN    0x42524344
+
+struct fc_rpsc2_cmd_s {
+	struct fc_els_cmd_s els_cmd;
+	u32	token;
+	u16	resvd;
+	u16	num_pids;	/* Number of pids in the request */
+	struct  {
+		u32	rsvd1:8;
+		u32	pid:24;		/* port identifier */
+	} pid_list[1];
+};
+
+enum fc_rpsc2_port_type {
+	RPSC2_PORT_TYPE_UNKNOWN = 0,
+	RPSC2_PORT_TYPE_NPORT   = 1,
+	RPSC2_PORT_TYPE_NLPORT  = 2,
+	RPSC2_PORT_TYPE_NPIV_PORT  = 0x5f,
+	RPSC2_PORT_TYPE_NPORT_TRUNK  = 0x6f,
+};
+/*
+ * RPSC2 portInfo entry structure
+ */
+struct fc_rpsc2_port_info_s {
+    u32    pid;        /* PID */
+    u16    resvd1;
+    u16    index;      /* port number / index */
+    u8     resvd2;
+    u8	   type;	/* port type N/NL/... */
+    u16    speed;      /* port Operating Speed */
+};
+
+/*
+ * RPSC2 Accept payload
+ */
+struct fc_rpsc2_acc_s {
+	u8        els_cmd;
+	u8        resvd;
+    u16       num_pids;  /* Number of pids in the request */
+    struct fc_rpsc2_port_info_s port_info[1];    /* port information */
+};
+
+/**
+ * bit fields so that multiple classes can be specified
+ */
+enum fc_cos {
+	FC_CLASS_2	= 0x04,
+	FC_CLASS_3	= 0x08,
+	FC_CLASS_2_3	= 0x0C,
+};
+
+/*
+ * symbolic name
+ */
+struct fc_symname_s {
+	u8         symname[FC_SYMNAME_MAX];
+};
+
+struct fc_alpabm_s {
+	u8         alpa_bm[FC_ALPA_MAX / 8];
+};
+
+/*
+ * protocol default timeout values
+ */
+#define FC_ED_TOV		2
+#define FC_REC_TOV		(FC_ED_TOV + 1)
+#define FC_RA_TOV		10
+#define FC_ELS_TOV		(2 * FC_RA_TOV)
+#define FC_FCCT_TOV		(3 * FC_RA_TOV)
+
+/*
+ * virtual fabric related defines
+ */
+#define FC_VF_ID_NULL    0	/*  must not be used as VF_ID */
+#define FC_VF_ID_MIN     1
+#define FC_VF_ID_MAX     0xEFF
+#define FC_VF_ID_CTL     0xFEF	/*  control VF_ID */
+
+/**
+ * Virtual Fabric Tagging header format
+ * @caution This is defined only in BIG ENDIAN format.
+ */
+struct fc_vft_s {
+	u32        r_ctl:8;
+	u32        ver:2;
+	u32        type:4;
+	u32        res_a:2;
+	u32        priority:3;
+	u32        vf_id:12;
+	u32        res_b:1;
+	u32        hopct:8;
+	u32        res_c:24;
+};
+
+/*
+ * FCP
+ */
+enum {
+	FCP_RJT		= 0x01000000,	/* SRR reject */
+	FCP_SRR_ACCEPT	= 0x02000000,	/* SRR accept */
+	FCP_SRR		= 0x14000000,	/* Sequence Retransmission Request */
+};
+
+/*
+ * SRR FC-4 LS payload
+ */
+struct fc_srr_s {
+	u32	ls_cmd;
+	u32        ox_id:16;	/* ox-id */
+	u32        rx_id:16;	/* rx-id */
+	u32        ro;		/* relative offset */
+	u32        r_ctl:8;		/* R_CTL for I.U. */
+	u32        res:24;
+};
+
+
+/*
+ * FCP_CMND definitions
+ */
+#define FCP_CMND_CDB_LEN    16
+#define FCP_CMND_LUN_LEN    8
+
+struct fcp_cmnd_s {
+	lun_t           lun;		/* 64-bit LU number */
+	u8         crn;		/* command reference number */
+#ifdef __BIGENDIAN
+	u8         resvd:1,
+			priority:4,	/* FCP-3: SAM-3 priority */
+			taskattr:3;	/* scsi task attribute */
+#else
+	u8         taskattr:3,	/* scsi task attribute */
+			priority:4,	/* FCP-3: SAM-3 priority */
+			resvd:1;
+#endif
+	u8         tm_flags;	/* task management flags */
+#ifdef __BIGENDIAN
+	u8         addl_cdb_len:6,	/* additional CDB length words */
+			iodir:2;	/* read/write FCP_DATA IUs */
+#else
+	u8         iodir:2,	/* read/write FCP_DATA IUs */
+			addl_cdb_len:6;	/* additional CDB length */
+#endif
+	scsi_cdb_t      cdb;
+
+	/*
+	 * !!! additional cdb bytes follows here!!!
+	 */
+	u32        fcp_dl;	/* bytes to be transferred */
+};
+
+#define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN)
+#define fcp_cmnd_fcpdl(_cmnd)	((&(_cmnd)->fcp_dl)[(_cmnd)->addl_cdb_len])
+
+/*
+ * struct fcp_cmnd_s .iodir field values
+ */
+enum fcp_iodir {
+	FCP_IODIR_NONE	= 0,
+	FCP_IODIR_WRITE = 1,
+	FCP_IODIR_READ	= 2,
+	FCP_IODIR_RW	= 3,
+};
+
+/*
+ * Task attribute field
+ */
+enum {
+	FCP_TASK_ATTR_SIMPLE	= 0,
+	FCP_TASK_ATTR_HOQ	= 1,
+	FCP_TASK_ATTR_ORDERED	= 2,
+	FCP_TASK_ATTR_ACA	= 4,
+	FCP_TASK_ATTR_UNTAGGED	= 5,	/* obsolete in FCP-3 */
+};
+
+/*
+ * Task management flags field - only one bit shall be set
+ */
+enum fcp_tm_cmnd {
+	FCP_TM_ABORT_TASK_SET	= BIT(1),
+	FCP_TM_CLEAR_TASK_SET	= BIT(2),
+	FCP_TM_LUN_RESET	= BIT(4),
+	FCP_TM_TARGET_RESET	= BIT(5),	/* obsolete in FCP-3 */
+	FCP_TM_CLEAR_ACA	= BIT(6),
+};
+
+/*
+ * FCP_XFER_RDY IU defines
+ */
+struct fcp_xfer_rdy_s {
+	u32        data_ro;
+	u32        burst_len;
+	u32        reserved;
+};
+
+/*
+ * FCP_RSP residue flags
+ */
+enum fcp_residue {
+	FCP_NO_RESIDUE = 0,	/* no residue */
+	FCP_RESID_OVER = 1,	/* more data left that was not sent */
+	FCP_RESID_UNDER = 2,	/* less data than requested */
+};
+
+enum {
+	FCP_RSPINFO_GOOD = 0,
+	FCP_RSPINFO_DATALEN_MISMATCH = 1,
+	FCP_RSPINFO_CMND_INVALID = 2,
+	FCP_RSPINFO_ROLEN_MISMATCH = 3,
+	FCP_RSPINFO_TM_NOT_SUPP = 4,
+	FCP_RSPINFO_TM_FAILED = 5,
+};
+
+struct fcp_rspinfo_s {
+	u32        res0:24;
+	u32        rsp_code:8;	/* response code (as above) */
+	u32        res1;
+};
+
+struct fcp_resp_s {
+	u32        reserved[2];	/* 2 words reserved */
+	u16        reserved2;
+#ifdef __BIGENDIAN
+	u8         reserved3:3;
+	u8         fcp_conf_req:1;	/* FCP_CONF is requested */
+	u8         resid_flags:2;	/* underflow/overflow */
+	u8         sns_len_valid:1;/* sense len is valid */
+	u8         rsp_len_valid:1;/* response len is valid */
+#else
+	u8         rsp_len_valid:1;/* response len is valid */
+	u8         sns_len_valid:1;/* sense len is valid */
+	u8         resid_flags:2;	/* underflow/overflow */
+	u8         fcp_conf_req:1;	/* FCP_CONF is requested */
+	u8         reserved3:3;
+#endif
+	u8         scsi_status;	/* one byte SCSI status */
+	u32        residue;	/* residual data bytes */
+	u32        sns_len;	/* length od sense info */
+	u32        rsp_len;	/* length of response info */
+};
+
+#define fcp_snslen(__fcprsp)	((__fcprsp)->sns_len_valid ?		\
+					(__fcprsp)->sns_len : 0)
+#define fcp_rsplen(__fcprsp)	((__fcprsp)->rsp_len_valid ?		\
+					(__fcprsp)->rsp_len : 0)
+#define fcp_rspinfo(__fcprsp)	((struct fcp_rspinfo_s *)((__fcprsp) + 1))
+#define fcp_snsinfo(__fcprsp)	(((u8 *)fcp_rspinfo(__fcprsp)) +	\
+						fcp_rsplen(__fcprsp))
+
+struct fcp_cmnd_fr_s {
+	struct fchs_s fchs;
+	struct fcp_cmnd_s fcp;
+};
+
+/*
+ * CT
+ */
+struct ct_hdr_s {
+	u32	rev_id:8;	/* Revision of the CT */
+	u32	in_id:24;	/* Initiator Id */
+	u32	gs_type:8;	/* Generic service Type */
+	u32	gs_sub_type:8;	/* Generic service sub type */
+	u32	options:8;	/* options */
+	u32	rsvrd:8;	/* reserved */
+	u32	cmd_rsp_code:16;/* ct command/response code */
+	u32	max_res_size:16;/* maximum/residual size */
+	u32	frag_id:8;	/* fragment ID */
+	u32	reason_code:8;	/* reason code */
+	u32	exp_code:8;	/* explanation code */
+	u32	vendor_unq:8;	/* vendor unique */
+};
+
+/*
+ * defines for the Revision
+ */
+enum {
+	CT_GS3_REVISION = 0x01,
+};
+
+/*
+ * defines for gs_type
+ */
+enum {
+	CT_GSTYPE_KEYSERVICE	= 0xF7,
+	CT_GSTYPE_ALIASSERVICE	= 0xF8,
+	CT_GSTYPE_MGMTSERVICE	= 0xFA,
+	CT_GSTYPE_TIMESERVICE	= 0xFB,
+	CT_GSTYPE_DIRSERVICE	= 0xFC,
+};
+
+/*
+ * defines for gs_sub_type for gs type directory service
+ */
+enum {
+	CT_GSSUBTYPE_NAMESERVER = 0x02,
+};
+
+/*
+ * defines for gs_sub_type for gs type management service
+ */
+enum {
+	CT_GSSUBTYPE_CFGSERVER	= 0x01,
+	CT_GSSUBTYPE_UNZONED_NS = 0x02,
+	CT_GSSUBTYPE_ZONESERVER = 0x03,
+	CT_GSSUBTYPE_LOCKSERVER = 0x04,
+	CT_GSSUBTYPE_HBA_MGMTSERVER = 0x10,	/* for FDMI */
+};
+
+/*
+ * defines for CT response code field
+ */
+enum {
+	CT_RSP_REJECT = 0x8001,
+	CT_RSP_ACCEPT = 0x8002,
+};
+
+/*
+ * defintions for CT reason code
+ */
+enum {
+	CT_RSN_INV_CMD		= 0x01,
+	CT_RSN_INV_VER		= 0x02,
+	CT_RSN_LOGIC_ERR	= 0x03,
+	CT_RSN_INV_SIZE		= 0x04,
+	CT_RSN_LOGICAL_BUSY	= 0x05,
+	CT_RSN_PROTO_ERR	= 0x07,
+	CT_RSN_UNABLE_TO_PERF	= 0x09,
+	CT_RSN_NOT_SUPP			= 0x0B,
+	CT_RSN_SERVER_NOT_AVBL  = 0x0D,
+	CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E,
+	CT_RSN_VENDOR_SPECIFIC  = 0xFF,
+
+};
+
+/*
+ * definitions for explanations code for Name server
+ */
+enum {
+	CT_NS_EXP_NOADDITIONAL	= 0x00,
+	CT_NS_EXP_ID_NOT_REG	= 0x01,
+	CT_NS_EXP_PN_NOT_REG	= 0x02,
+	CT_NS_EXP_NN_NOT_REG	= 0x03,
+	CT_NS_EXP_CS_NOT_REG	= 0x04,
+	CT_NS_EXP_IPN_NOT_REG	= 0x05,
+	CT_NS_EXP_IPA_NOT_REG	= 0x06,
+	CT_NS_EXP_FT_NOT_REG	= 0x07,
+	CT_NS_EXP_SPN_NOT_REG	= 0x08,
+	CT_NS_EXP_SNN_NOT_REG	= 0x09,
+	CT_NS_EXP_PT_NOT_REG	= 0x0A,
+	CT_NS_EXP_IPP_NOT_REG	= 0x0B,
+	CT_NS_EXP_FPN_NOT_REG	= 0x0C,
+	CT_NS_EXP_HA_NOT_REG	= 0x0D,
+	CT_NS_EXP_FD_NOT_REG	= 0x0E,
+	CT_NS_EXP_FF_NOT_REG	= 0x0F,
+	CT_NS_EXP_ACCESSDENIED	= 0x10,
+	CT_NS_EXP_UNACCEPTABLE_ID = 0x11,
+	CT_NS_EXP_DATABASEEMPTY		= 0x12,
+	CT_NS_EXP_NOT_REG_IN_SCOPE	= 0x13,
+	CT_NS_EXP_DOM_ID_NOT_PRESENT	= 0x14,
+	CT_NS_EXP_PORT_NUM_NOT_PRESENT	= 0x15,
+	CT_NS_EXP_NO_DEVICE_ATTACHED	= 0x16
+};
+
+/*
+ * defintions for the explanation code for all servers
+ */
+enum {
+	CT_EXP_AUTH_EXCEPTION			= 0xF1,
+	CT_EXP_DB_FULL					= 0xF2,
+	CT_EXP_DB_EMPTY					= 0xF3,
+	CT_EXP_PROCESSING_REQ			= 0xF4,
+	CT_EXP_UNABLE_TO_VERIFY_CONN	= 0xF5,
+	CT_EXP_DEVICES_NOT_IN_CMN_ZONE  = 0xF6
+};
+
+/*
+ * Command codes for Name server
+ */
+enum {
+	GS_GID_PN	= 0x0121,	/* Get Id on port name */
+	GS_GPN_ID	= 0x0112,	/* Get port name on ID */
+	GS_GNN_ID	= 0x0113,	/* Get node name on ID */
+	GS_GID_FT	= 0x0171,	/* Get Id on FC4 type */
+	GS_GSPN_ID	= 0x0118,	/* Get symbolic PN on ID */
+	GS_RFT_ID	= 0x0217,	/* Register fc4type on ID */
+	GS_RSPN_ID	= 0x0218,	/* Register symbolic PN on ID */
+	GS_RPN_ID	= 0x0212,	/* Register port name */
+	GS_RNN_ID	= 0x0213,	/* Register node name */
+	GS_RCS_ID	= 0x0214,	/* Register class of service */
+	GS_RPT_ID	= 0x021A,	/* Register port type */
+	GS_GA_NXT	= 0x0100,	/* Get all next */
+	GS_RFF_ID	= 0x021F,	/* Register FC4 Feature		*/
+};
+
+struct fcgs_id_req_s{
+	u32 rsvd:8;
+	u32 dap:24; /* port identifier */
+};
+#define fcgs_gpnid_req_t struct fcgs_id_req_s
+#define fcgs_gnnid_req_t struct fcgs_id_req_s
+#define fcgs_gspnid_req_t struct fcgs_id_req_s
+
+struct fcgs_gidpn_req_s {
+	wwn_t	port_name;	/* port wwn */
+};
+
+struct fcgs_gidpn_resp_s {
+	u32	rsvd:8;
+	u32	dap:24;	/* port identifier */
+};
+
+/**
+ * RFT_ID
+ */
+struct fcgs_rftid_req_s {
+	u32	rsvd:8;
+	u32	dap:24;		/* port identifier */
+	u32	fc4_type[8];	/* fc4 types */
+};
+
+/**
+ * RFF_ID : Register FC4 features.
+ */
+
+#define FC_GS_FCP_FC4_FEATURE_INITIATOR  0x02
+#define FC_GS_FCP_FC4_FEATURE_TARGET	 0x01
+
+struct fcgs_rffid_req_s {
+    u32    rsvd:8;
+    u32    dap:24;		/* port identifier	*/
+    u32    rsvd1:16;
+    u32    fc4ftr_bits:8;		/* fc4 feature bits	*/
+    u32    fc4_type:8;		/* corresponding FC4 Type */
+};
+
+/**
+ * GID_FT Request
+ */
+struct fcgs_gidft_req_s {
+	u8	reserved;
+	u8	domain_id;	/* domain, 0 - all fabric */
+	u8	area_id;	/* area, 0 - whole domain */
+	u8	fc4_type;	/* FC_TYPE_FCP for SCSI devices */
+};		/* GID_FT Request */
+
+/**
+ * GID_FT Response
+ */
+struct fcgs_gidft_resp_s {
+	u8		last:1;	/* last port identifier flag */
+	u8		reserved:7;
+	u32	pid:24;	/* port identifier */
+};		/* GID_FT Response */
+
+/**
+ * RSPN_ID
+ */
+struct fcgs_rspnid_req_s {
+	u32	rsvd:8;
+	u32	dap:24;		/* port identifier */
+	u8		spn_len;	/* symbolic port name length */
+	u8		spn[256];	/* symbolic port name */
+};
+
+/**
+ * RPN_ID
+ */
+struct fcgs_rpnid_req_s {
+	u32	rsvd:8;
+	u32	port_id:24;
+	wwn_t		port_name;
+};
+
+/**
+ * RNN_ID
+ */
+struct fcgs_rnnid_req_s {
+	u32	rsvd:8;
+	u32	port_id:24;
+	wwn_t		node_name;
+};
+
+/**
+ * RCS_ID
+ */
+struct fcgs_rcsid_req_s {
+	u32	rsvd:8;
+	u32	port_id:24;
+	u32	cos;
+};
+
+/**
+ * RPT_ID
+ */
+struct fcgs_rptid_req_s {
+	u32	rsvd:8;
+	u32	port_id:24;
+	u32	port_type:8;
+	u32	rsvd1:24;
+};
+
+/**
+ * GA_NXT Request
+ */
+struct fcgs_ganxt_req_s {
+	u32	rsvd:8;
+	u32	port_id:24;
+};
+
+/**
+ * GA_NXT Response
+ */
+struct fcgs_ganxt_rsp_s {
+	u32	port_type:8;	/* Port Type */
+	u32	port_id:24;	/* Port Identifier */
+	wwn_t		port_name;	/* Port Name */
+	u8		spn_len;	/* Length of Symbolic Port Name */
+	char		spn[255];	/* Symbolic Port Name */
+	wwn_t		node_name;	/* Node Name */
+	u8		snn_len;	/* Length of Symbolic Node Name */
+	char		snn[255];	/* Symbolic Node Name */
+	u8		ipa[8];		/* Initial Process Associator */
+	u8		ip[16];		/* IP Address */
+	u32	cos;		/* Class of Service */
+	u32	fc4types[8];	/* FC-4 TYPEs */
+	wwn_t		fabric_port_name;
+					/* Fabric Port Name */
+	u32	rsvd:8;		/* Reserved */
+	u32	hard_addr:24;	/* Hard Address */
+};
+
+/*
+ * Fabric Config Server
+ */
+
+/*
+ * Command codes for Fabric Configuration Server
+ */
+enum {
+	GS_FC_GFN_CMD	= 0x0114,	/* GS FC Get Fabric Name  */
+	GS_FC_GMAL_CMD	= 0x0116,	/* GS FC GMAL  */
+	GS_FC_TRACE_CMD	= 0x0400,	/* GS FC Trace Route */
+	GS_FC_PING_CMD	= 0x0401,	/* GS FC Ping */
+};
+
+/*
+ * Source or Destination Port Tags.
+ */
+enum {
+	GS_FTRACE_TAG_NPORT_ID		= 1,
+	GS_FTRACE_TAG_NPORT_NAME	= 2,
+};
+
+/*
+* Port Value : Could be a Port id or wwn
+ */
+union fcgs_port_val_u {
+	u32	nport_id;
+	wwn_t		nport_wwn;
+};
+
+#define GS_FTRACE_MAX_HOP_COUNT	20
+#define GS_FTRACE_REVISION	1
+
+/*
+ * Ftrace Related Structures.
+ */
+
+/*
+ * STR (Switch Trace) Reject Reason Codes. From FC-SW.
+ */
+enum {
+	GS_FTRACE_STR_CMD_COMPLETED_SUCC	= 0,
+	GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH,
+	GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH,
+	GS_FTRACE_STR_MAX_HOP_CNT_REACHED,
+	GS_FTRACE_STR_SRC_PORT_NOT_FOUND,
+	GS_FTRACE_STR_DST_PORT_NOT_FOUND,
+	GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE,
+	GS_FTRACE_STR_NO_ROUTE_BW_PORTS,
+	GS_FTRACE_STR_NO_ADDL_EXPLN,
+	GS_FTRACE_STR_FABRIC_BUSY,
+	GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS,
+	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0,
+	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff,
+};
+
+/*
+ * Ftrace Request
+ */
+struct fcgs_ftrace_req_s {
+	u32	revision;
+	u16	src_port_tag;	/* Source Port tag */
+	u16	src_port_len;	/* Source Port len */
+	union fcgs_port_val_u src_port_val;	/* Source Port value */
+	u16	dst_port_tag;	/* Destination Port tag */
+	u16	dst_port_len;	/* Destination Port len */
+	union fcgs_port_val_u dst_port_val;	/* Destination Port value */
+	u32	token;
+	u8		vendor_id[8];	/* T10 Vendor Identifier */
+	u8		vendor_info[8];	/* Vendor specific Info */
+	u32	max_hop_cnt;	/* Max Hop Count */
+};
+
+/*
+ * Path info structure
+ */
+struct fcgs_ftrace_path_info_s {
+	wwn_t		switch_name;		/* Switch WWN */
+	u32	domain_id;
+	wwn_t		ingress_port_name;	/* Ingress ports wwn */
+	u32	ingress_phys_port_num;	/* Ingress ports physical port
+						 * number
+						 */
+	wwn_t		egress_port_name;	/* Ingress ports wwn */
+	u32	egress_phys_port_num;	/* Ingress ports physical port
+						 * number
+						 */
+};
+
+/*
+ * Ftrace Acc Response
+ */
+struct fcgs_ftrace_resp_s {
+	u32	revision;
+	u32	token;
+	u8		vendor_id[8];		/* T10 Vendor Identifier */
+	u8		vendor_info[8];		/* Vendor specific Info */
+	u32	str_rej_reason_code;	/* STR Reject Reason Code */
+	u32	num_path_info_entries;	/* No. of path info entries */
+	/*
+	 * path info entry/entries.
+	 */
+	struct fcgs_ftrace_path_info_s path_info[1];
+
+};
+
+/*
+* Fabric Config Server : FCPing
+ */
+
+/*
+ * FC Ping Request
+ */
+struct fcgs_fcping_req_s {
+	u32	revision;
+	u16	port_tag;
+	u16	port_len;	/* Port len */
+	union fcgs_port_val_u port_val;	/* Port value */
+	u32	token;
+};
+
+/*
+ * FC Ping Response
+ */
+struct fcgs_fcping_resp_s {
+	u32	token;
+};
+
+/*
+ * Command codes for zone server query.
+ */
+enum {
+	ZS_GZME = 0x0124,	/* Get zone member extended */
+};
+
+/*
+ * ZS GZME request
+ */
+#define ZS_GZME_ZNAMELEN	32
+struct zs_gzme_req_s {
+	u8	znamelen;
+	u8	rsvd[3];
+	u8	zname[ZS_GZME_ZNAMELEN];
+};
+
+enum zs_mbr_type {
+	ZS_MBR_TYPE_PWWN	= 1,
+	ZS_MBR_TYPE_DOMPORT	= 2,
+	ZS_MBR_TYPE_PORTID	= 3,
+	ZS_MBR_TYPE_NWWN	= 4,
+};
+
+struct zs_mbr_wwn_s {
+	u8	mbr_type;
+	u8	rsvd[3];
+	wwn_t	wwn;
+};
+
+struct zs_query_resp_s {
+	u32	nmbrs;	/*  number of zone members */
+	struct zs_mbr_wwn_s	mbr[1];
+};
+
+/*
+ * GMAL Command ( Get ( interconnect Element) Management Address List)
+ * To retrieve the IP Address of a Switch.
+ */
+
+#define CT_GMAL_RESP_PREFIX_TELNET	 "telnet://"
+#define CT_GMAL_RESP_PREFIX_HTTP	 "http://"
+
+/*  GMAL/GFN request */
+struct fcgs_req_s {
+	wwn_t    wwn;   /* PWWN/NWWN */
+};
+
+#define fcgs_gmal_req_t struct fcgs_req_s
+#define fcgs_gfn_req_t struct fcgs_req_s
+
+/* Accept Response to GMAL */
+struct fcgs_gmal_resp_s {
+	u32	ms_len;   /* Num of entries */
+	u8	ms_ma[256];
+};
+
+struct fcgs_gmal_entry_s {
+	u8  len;
+	u8  prefix[7]; /* like "http://" */
+	u8  ip_addr[248];
+};
+
+/*
+ * FDMI
+ */
+/*
+ * FDMI Command Codes
+ */
+#define	FDMI_GRHL		0x0100
+#define	FDMI_GHAT		0x0101
+#define	FDMI_GRPL		0x0102
+#define	FDMI_GPAT		0x0110
+#define	FDMI_RHBA		0x0200
+#define	FDMI_RHAT		0x0201
+#define	FDMI_RPRT		0x0210
+#define	FDMI_RPA		0x0211
+#define	FDMI_DHBA		0x0300
+#define	FDMI_DPRT		0x0310
+
+/*
+ * FDMI reason codes
+ */
+#define	FDMI_NO_ADDITIONAL_EXP		0x00
+#define	FDMI_HBA_ALREADY_REG		0x10
+#define	FDMI_HBA_ATTRIB_NOT_REG		0x11
+#define	FDMI_HBA_ATTRIB_MULTIPLE	0x12
+#define	FDMI_HBA_ATTRIB_LENGTH_INVALID	0x13
+#define	FDMI_HBA_ATTRIB_NOT_PRESENT	0x14
+#define	FDMI_PORT_ORIG_NOT_IN_LIST	0x15
+#define	FDMI_PORT_HBA_NOT_IN_LIST	0x16
+#define	FDMI_PORT_ATTRIB_NOT_REG	0x20
+#define	FDMI_PORT_NOT_REG		0x21
+#define	FDMI_PORT_ATTRIB_MULTIPLE	0x22
+#define	FDMI_PORT_ATTRIB_LENGTH_INVALID	0x23
+#define	FDMI_PORT_ALREADY_REGISTEREED	0x24
+
+/*
+ * FDMI Transmission Speed Mask values
+ */
+#define	FDMI_TRANS_SPEED_1G		0x00000001
+#define	FDMI_TRANS_SPEED_2G		0x00000002
+#define	FDMI_TRANS_SPEED_10G		0x00000004
+#define	FDMI_TRANS_SPEED_4G		0x00000008
+#define	FDMI_TRANS_SPEED_8G		0x00000010
+#define	FDMI_TRANS_SPEED_16G		0x00000020
+#define	FDMI_TRANS_SPEED_UNKNOWN	0x00008000
+
+/*
+ * FDMI HBA attribute types
+ */
+enum fdmi_hba_attribute_type {
+	FDMI_HBA_ATTRIB_NODENAME = 1,	/* 0x0001 */
+	FDMI_HBA_ATTRIB_MANUFACTURER,	/* 0x0002 */
+	FDMI_HBA_ATTRIB_SERIALNUM,	/* 0x0003 */
+	FDMI_HBA_ATTRIB_MODEL,		/* 0x0004 */
+	FDMI_HBA_ATTRIB_MODEL_DESC,	/* 0x0005 */
+	FDMI_HBA_ATTRIB_HW_VERSION,	/* 0x0006 */
+	FDMI_HBA_ATTRIB_DRIVER_VERSION,	/* 0x0007 */
+	FDMI_HBA_ATTRIB_ROM_VERSION,	/* 0x0008 */
+	FDMI_HBA_ATTRIB_FW_VERSION,	/* 0x0009 */
+	FDMI_HBA_ATTRIB_OS_NAME,	/* 0x000A */
+	FDMI_HBA_ATTRIB_MAX_CT,		/* 0x000B */
+
+	FDMI_HBA_ATTRIB_MAX_TYPE
+};
+
+/*
+ * FDMI Port attribute types
+ */
+enum fdmi_port_attribute_type {
+	FDMI_PORT_ATTRIB_FC4_TYPES = 1,	/* 0x0001 */
+	FDMI_PORT_ATTRIB_SUPP_SPEED,	/* 0x0002 */
+	FDMI_PORT_ATTRIB_PORT_SPEED,	/* 0x0003 */
+	FDMI_PORT_ATTRIB_FRAME_SIZE,	/* 0x0004 */
+	FDMI_PORT_ATTRIB_DEV_NAME,	/* 0x0005 */
+	FDMI_PORT_ATTRIB_HOST_NAME,	/* 0x0006 */
+
+	FDMI_PORT_ATTR_MAX_TYPE
+};
+
+/*
+ * FDMI attribute
+ */
+struct fdmi_attr_s {
+	u16        type;
+	u16        len;
+	u8         value[1];
+};
+
+/*
+ * HBA Attribute Block
+ */
+struct fdmi_hba_attr_s {
+	u32        attr_count;	/* # of attributes */
+	struct fdmi_attr_s hba_attr;	/* n attributes */
+};
+
+/*
+ * Registered Port List
+ */
+struct fdmi_port_list_s {
+	u32        num_ports;	/* number Of Port Entries */
+	wwn_t           port_entry;	/* one or more */
+};
+
+/*
+ * Port Attribute Block
+ */
+struct fdmi_port_attr_s {
+	u32        attr_count;	/* # of attributes */
+	struct fdmi_attr_s port_attr;	/* n attributes */
+};
+
+/*
+ * FDMI Register HBA Attributes
+ */
+struct fdmi_rhba_s {
+	wwn_t           hba_id;		/* HBA Identifier */
+	struct fdmi_port_list_s port_list;	/* Registered Port List */
+	struct fdmi_hba_attr_s hba_attr_blk;	/* HBA attribute block */
+};
+
+/*
+ * FDMI Register Port
+ */
+struct fdmi_rprt_s {
+	wwn_t           hba_id;		/* HBA Identifier */
+	wwn_t           port_name;	/* Port wwn */
+	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */
+};
+
+/*
+ * FDMI Register Port Attributes
+ */
+struct fdmi_rpa_s {
+	wwn_t           port_name;	/* port wwn */
+	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */
+};
+
+#pragma pack()
+
+#endif	/* __BFA_FC_H__ */
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
new file mode 100644
index 0000000..b7d2657
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -0,0 +1,1410 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * fcbuild.c - FC link service frame building and parsing routines
+ */
+
+#include "bfa_os_inc.h"
+#include "bfa_fcbuild.h"
+
+/*
+ * static build functions
+ */
+static void     fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+				 u16 ox_id);
+static void     fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+				 u16 ox_id);
+static struct fchs_s fc_els_req_tmpl;
+static struct fchs_s fc_els_rsp_tmpl;
+static struct fchs_s fc_bls_req_tmpl;
+static struct fchs_s fc_bls_rsp_tmpl;
+static struct fc_ba_acc_s ba_acc_tmpl;
+static struct fc_logi_s plogi_tmpl;
+static struct fc_prli_s prli_tmpl;
+static struct fc_rrq_s rrq_tmpl;
+static struct fchs_s fcp_fchs_tmpl;
+
+void
+fcbuild_init(void)
+{
+	/*
+	 * fc_els_req_tmpl
+	 */
+	fc_els_req_tmpl.routing = FC_RTG_EXT_LINK;
+	fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST;
+	fc_els_req_tmpl.type = FC_TYPE_ELS;
+	fc_els_req_tmpl.f_ctl =
+		bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
+			      FCTL_SI_XFER);
+	fc_els_req_tmpl.rx_id = FC_RXID_ANY;
+
+	/*
+	 * fc_els_rsp_tmpl
+	 */
+	fc_els_rsp_tmpl.routing = FC_RTG_EXT_LINK;
+	fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY;
+	fc_els_rsp_tmpl.type = FC_TYPE_ELS;
+	fc_els_rsp_tmpl.f_ctl =
+		bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
+			      FCTL_END_SEQ | FCTL_SI_XFER);
+	fc_els_rsp_tmpl.rx_id = FC_RXID_ANY;
+
+	/*
+	 * fc_bls_req_tmpl
+	 */
+	fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK;
+	fc_bls_req_tmpl.type = FC_TYPE_BLS;
+	fc_bls_req_tmpl.f_ctl = bfa_os_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
+	fc_bls_req_tmpl.rx_id = FC_RXID_ANY;
+
+	/*
+	 * fc_bls_rsp_tmpl
+	 */
+	fc_bls_rsp_tmpl.routing = FC_RTG_BASIC_LINK;
+	fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC;
+	fc_bls_rsp_tmpl.type = FC_TYPE_BLS;
+	fc_bls_rsp_tmpl.f_ctl =
+		bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
+			      FCTL_END_SEQ | FCTL_SI_XFER);
+	fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY;
+
+	/*
+	 * ba_acc_tmpl
+	 */
+	ba_acc_tmpl.seq_id_valid = 0;
+	ba_acc_tmpl.low_seq_cnt = 0;
+	ba_acc_tmpl.high_seq_cnt = 0xFFFF;
+
+	/*
+	 * plogi_tmpl
+	 */
+	plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
+	plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
+	plogi_tmpl.csp.bbcred = bfa_os_htons(0x0004);
+	plogi_tmpl.csp.ciro = 0x1;
+	plogi_tmpl.csp.cisc = 0x0;
+	plogi_tmpl.csp.altbbcred = 0x0;
+	plogi_tmpl.csp.conseq = bfa_os_htons(0x00FF);
+	plogi_tmpl.csp.ro_bitmap = bfa_os_htons(0x0002);
+	plogi_tmpl.csp.e_d_tov = bfa_os_htonl(2000);
+
+	plogi_tmpl.class3.class_valid = 1;
+	plogi_tmpl.class3.sequential = 1;
+	plogi_tmpl.class3.conseq = 0xFF;
+	plogi_tmpl.class3.ospx = 1;
+
+	/*
+	 * prli_tmpl
+	 */
+	prli_tmpl.command = FC_ELS_PRLI;
+	prli_tmpl.pglen = 0x10;
+	prli_tmpl.pagebytes = bfa_os_htons(0x0014);
+	prli_tmpl.parampage.type = FC_TYPE_FCP;
+	prli_tmpl.parampage.imagepair = 1;
+	prli_tmpl.parampage.servparams.rxrdisab = 1;
+
+	/*
+	 * rrq_tmpl
+	 */
+	rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ;
+
+	/*
+	 * fcp_struct fchs_s mpl
+	 */
+	fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA;
+	fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
+	fcp_fchs_tmpl.type = FC_TYPE_FCP;
+	fcp_fchs_tmpl.f_ctl =
+		bfa_os_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
+	fcp_fchs_tmpl.seq_id = 1;
+	fcp_fchs_tmpl.rx_id = FC_RXID_ANY;
+}
+
+static void
+fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
+{
+	bfa_os_memset(fchs, 0, sizeof(struct fchs_s));
+
+	fchs->routing = FC_RTG_FC4_DEV_DATA;
+	fchs->cat_info = FC_CAT_UNSOLICIT_CTRL;
+	fchs->type = FC_TYPE_SERVICES;
+	fchs->f_ctl =
+		bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
+			      FCTL_SI_XFER);
+	fchs->rx_id = FC_RXID_ANY;
+	fchs->d_id = (d_id);
+	fchs->s_id = (s_id);
+	fchs->ox_id = bfa_os_htons(ox_id);
+
+	/**
+	 * @todo no need to set ox_id for request
+	 *       no need to set rx_id for response
+	 */
+}
+
+void
+fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+{
+	bfa_os_memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
+	fchs->d_id = (d_id);
+	fchs->s_id = (s_id);
+	fchs->ox_id = bfa_os_htons(ox_id);
+}
+
+static void
+fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+{
+	bfa_os_memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
+	fchs->d_id = d_id;
+	fchs->s_id = s_id;
+	fchs->ox_id = ox_id;
+}
+
+enum fc_parse_status
+fc_els_rsp_parse(struct fchs_s *fchs, int len)
+{
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+	struct fc_ls_rjt_s *ls_rjt = (struct fc_ls_rjt_s *) els_cmd;
+
+	len = len;
+
+	switch (els_cmd->els_code) {
+	case FC_ELS_LS_RJT:
+		if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
+			return FC_PARSE_BUSY;
+		else
+			return FC_PARSE_FAILURE;
+
+	case FC_ELS_ACC:
+		return FC_PARSE_OK;
+	}
+	return FC_PARSE_OK;
+}
+
+static void
+fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+{
+	bfa_os_memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
+	fchs->d_id = d_id;
+	fchs->s_id = s_id;
+	fchs->ox_id = ox_id;
+}
+
+static          u16
+fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+		 u16 ox_id, wwn_t port_name, wwn_t node_name,
+		 u16 pdu_size, u8 els_code)
+{
+	struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
+
+	bfa_os_memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
+
+	plogi->els_cmd.els_code = els_code;
+	if (els_code == FC_ELS_PLOGI)
+		fc_els_req_build(fchs, d_id, s_id, ox_id);
+	else
+		fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+	plogi->csp.rxsz = plogi->class3.rxsz = bfa_os_htons(pdu_size);
+
+	bfa_os_memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
+	bfa_os_memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
+
+	return sizeof(struct fc_logi_s);
+}
+
+u16
+fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
+		u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size,
+	       u8 set_npiv, u8 set_auth, u16 local_bb_credits)
+{
+	u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT);
+	u32	*vvl_info;
+
+	bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
+
+	flogi->els_cmd.els_code = FC_ELS_FLOGI;
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+	flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size);
+	flogi->port_name = port_name;
+	flogi->node_name = node_name;
+
+	/*
+	 * Set the NPIV Capability Bit ( word 1, bit 31) of Common
+	 * Service Parameters.
+	 */
+	flogi->csp.ciro = set_npiv;
+
+	/* set AUTH capability */
+	flogi->csp.security = set_auth;
+
+	flogi->csp.bbcred = bfa_os_htons(local_bb_credits);
+
+	/* Set brcd token in VVL */
+	vvl_info = (u32 *)&flogi->vvl[0];
+
+	/* set the flag to indicate the presence of VVL */
+	flogi->csp.npiv_supp    = 1; /* @todo. field name is not correct */
+	vvl_info[0]	= bfa_os_htonl(FLOGI_VVL_BRCD);
+
+	return sizeof(struct fc_logi_s);
+}
+
+u16
+fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
+		   u16 ox_id, wwn_t port_name, wwn_t node_name,
+		   u16 pdu_size, u16 local_bb_credits)
+{
+	u32        d_id = 0;
+
+	bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
+	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+	flogi->els_cmd.els_code = FC_ELS_ACC;
+	flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size);
+	flogi->port_name = port_name;
+	flogi->node_name = node_name;
+
+	flogi->csp.bbcred = bfa_os_htons(local_bb_credits);
+
+	return sizeof(struct fc_logi_s);
+}
+
+u16
+fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
+		u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size)
+{
+	u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT);
+
+	bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
+
+	flogi->els_cmd.els_code = FC_ELS_FDISC;
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+	flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size);
+	flogi->port_name = port_name;
+	flogi->node_name = node_name;
+
+	return sizeof(struct fc_logi_s);
+}
+
+u16
+fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+	       u16 ox_id, wwn_t port_name, wwn_t node_name,
+	       u16 pdu_size)
+{
+	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
+				node_name, pdu_size, FC_ELS_PLOGI);
+}
+
+u16
+fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+		   u16 ox_id, wwn_t port_name, wwn_t node_name,
+		   u16 pdu_size)
+{
+	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
+				node_name, pdu_size, FC_ELS_ACC);
+}
+
+enum fc_parse_status
+fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
+{
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+	struct fc_logi_s *plogi;
+	struct fc_ls_rjt_s *ls_rjt;
+
+	switch (els_cmd->els_code) {
+	case FC_ELS_LS_RJT:
+		ls_rjt = (struct fc_ls_rjt_s *) (fchs + 1);
+		if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
+			return FC_PARSE_BUSY;
+		else
+			return FC_PARSE_FAILURE;
+	case FC_ELS_ACC:
+		plogi = (struct fc_logi_s *) (fchs + 1);
+		if (len < sizeof(struct fc_logi_s))
+			return FC_PARSE_FAILURE;
+
+		if (!wwn_is_equal(plogi->port_name, port_name))
+			return FC_PARSE_FAILURE;
+
+		if (!plogi->class3.class_valid)
+			return FC_PARSE_FAILURE;
+
+		if (bfa_os_ntohs(plogi->class3.rxsz) < (FC_MIN_PDUSZ))
+			return FC_PARSE_FAILURE;
+
+		return FC_PARSE_OK;
+	default:
+		return FC_PARSE_FAILURE;
+	}
+}
+
+enum fc_parse_status
+fc_plogi_parse(struct fchs_s *fchs)
+{
+	struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1);
+
+	if (plogi->class3.class_valid != 1)
+		return FC_PARSE_FAILURE;
+
+	if ((bfa_os_ntohs(plogi->class3.rxsz) < FC_MIN_PDUSZ)
+	    || (bfa_os_ntohs(plogi->class3.rxsz) > FC_MAX_PDUSZ)
+	    || (plogi->class3.rxsz == 0))
+		return FC_PARSE_FAILURE;
+
+	return FC_PARSE_OK;
+}
+
+u16
+fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+	      u16 ox_id)
+{
+	struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
+
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+	bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
+
+	prli->command = FC_ELS_PRLI;
+	prli->parampage.servparams.initiator     = 1;
+	prli->parampage.servparams.retry         = 1;
+	prli->parampage.servparams.rec_support   = 1;
+	prli->parampage.servparams.task_retry_id = 0;
+	prli->parampage.servparams.confirm       = 1;
+
+	return sizeof(struct fc_prli_s);
+}
+
+u16
+fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+		  u16 ox_id, enum bfa_lport_role role)
+{
+	struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
+
+	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+	bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
+
+	prli->command = FC_ELS_ACC;
+
+	prli->parampage.servparams.initiator = 1;
+
+	prli->parampage.rspcode = FC_PRLI_ACC_XQTD;
+
+	return sizeof(struct fc_prli_s);
+}
+
+enum fc_parse_status
+fc_prli_rsp_parse(struct fc_prli_s *prli, int len)
+{
+	if (len < sizeof(struct fc_prli_s))
+		return FC_PARSE_FAILURE;
+
+	if (prli->command != FC_ELS_ACC)
+		return FC_PARSE_FAILURE;
+
+	if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD)
+	    && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG))
+		return FC_PARSE_FAILURE;
+
+	if (prli->parampage.servparams.target != 1)
+		return FC_PARSE_FAILURE;
+
+	return FC_PARSE_OK;
+}
+
+enum fc_parse_status
+fc_prli_parse(struct fc_prli_s *prli)
+{
+	if (prli->parampage.type != FC_TYPE_FCP)
+		return FC_PARSE_FAILURE;
+
+	if (!prli->parampage.imagepair)
+		return FC_PARSE_FAILURE;
+
+	if (!prli->parampage.servparams.initiator)
+		return FC_PARSE_FAILURE;
+
+	return FC_PARSE_OK;
+}
+
+u16
+fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id,
+	      u16 ox_id, wwn_t port_name)
+{
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+	bfa_os_memset(logo, '\0', sizeof(struct fc_logo_s));
+	logo->els_cmd.els_code = FC_ELS_LOGO;
+	logo->nport_id = (s_id);
+	logo->orig_port_name = port_name;
+
+	return sizeof(struct fc_logo_s);
+}
+
+static          u16
+fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
+		 u32 s_id, u16 ox_id, wwn_t port_name,
+		 wwn_t node_name, u8 els_code)
+{
+	bfa_os_memset(adisc, '\0', sizeof(struct fc_adisc_s));
+
+	adisc->els_cmd.els_code = els_code;
+
+	if (els_code == FC_ELS_ADISC)
+		fc_els_req_build(fchs, d_id, s_id, ox_id);
+	else
+		fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+	adisc->orig_HA = 0;
+	adisc->orig_port_name = port_name;
+	adisc->orig_node_name = node_name;
+	adisc->nport_id = (s_id);
+
+	return sizeof(struct fc_adisc_s);
+}
+
+u16
+fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
+		u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name)
+{
+	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
+				node_name, FC_ELS_ADISC);
+}
+
+u16
+fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
+		   u32 s_id, u16 ox_id, wwn_t port_name,
+		   wwn_t node_name)
+{
+	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
+				node_name, FC_ELS_ACC);
+}
+
+enum fc_parse_status
+fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name,
+				 wwn_t node_name)
+{
+
+	if (len < sizeof(struct fc_adisc_s))
+		return FC_PARSE_FAILURE;
+
+	if (adisc->els_cmd.els_code != FC_ELS_ACC)
+		return FC_PARSE_FAILURE;
+
+	if (!wwn_is_equal(adisc->orig_port_name, port_name))
+		return FC_PARSE_FAILURE;
+
+	return FC_PARSE_OK;
+}
+
+enum fc_parse_status
+fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap, wwn_t node_name,
+	       wwn_t port_name)
+{
+	struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld;
+
+	if (adisc->els_cmd.els_code != FC_ELS_ACC)
+		return FC_PARSE_FAILURE;
+
+	if ((adisc->nport_id == (host_dap))
+	    && wwn_is_equal(adisc->orig_port_name, port_name)
+	    && wwn_is_equal(adisc->orig_node_name, node_name))
+		return FC_PARSE_OK;
+
+	return FC_PARSE_FAILURE;
+}
+
+enum fc_parse_status
+fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name)
+{
+	struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
+
+	if (pdisc->class3.class_valid != 1)
+		return FC_PARSE_FAILURE;
+
+	if ((bfa_os_ntohs(pdisc->class3.rxsz) <
+		(FC_MIN_PDUSZ - sizeof(struct fchs_s)))
+	    || (pdisc->class3.rxsz == 0))
+		return FC_PARSE_FAILURE;
+
+	if (!wwn_is_equal(pdisc->port_name, port_name))
+		return FC_PARSE_FAILURE;
+
+	if (!wwn_is_equal(pdisc->node_name, node_name))
+		return FC_PARSE_FAILURE;
+
+	return FC_PARSE_OK;
+}
+
+u16
+fc_abts_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+{
+	bfa_os_memcpy(fchs, &fc_bls_req_tmpl, sizeof(struct fchs_s));
+	fchs->cat_info = FC_CAT_ABTS;
+	fchs->d_id = (d_id);
+	fchs->s_id = (s_id);
+	fchs->ox_id = bfa_os_htons(ox_id);
+
+	return sizeof(struct fchs_s);
+}
+
+enum fc_parse_status
+fc_abts_rsp_parse(struct fchs_s *fchs, int len)
+{
+	if ((fchs->cat_info == FC_CAT_BA_ACC)
+	    || (fchs->cat_info == FC_CAT_BA_RJT))
+		return FC_PARSE_OK;
+
+	return FC_PARSE_FAILURE;
+}
+
+u16
+fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id,
+	     u16 ox_id, u16 rrq_oxid)
+{
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+	/*
+	 * build rrq payload
+	 */
+	bfa_os_memcpy(rrq, &rrq_tmpl, sizeof(struct fc_rrq_s));
+	rrq->s_id = (s_id);
+	rrq->ox_id = bfa_os_htons(rrq_oxid);
+	rrq->rx_id = FC_RXID_ANY;
+
+	return sizeof(struct fc_rrq_s);
+}
+
+u16
+fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+		  u16 ox_id)
+{
+	struct fc_els_cmd_s *acc = pld;
+
+	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+	bfa_os_memset(acc, 0, sizeof(struct fc_els_cmd_s));
+	acc->els_code = FC_ELS_ACC;
+
+	return sizeof(struct fc_els_cmd_s);
+}
+
+u16
+fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
+		u32 s_id, u16 ox_id, u8 reason_code,
+		u8 reason_code_expl)
+{
+	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+	bfa_os_memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
+
+	ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT;
+	ls_rjt->reason_code = reason_code;
+	ls_rjt->reason_code_expl = reason_code_expl;
+	ls_rjt->vendor_unique = 0x00;
+
+	return sizeof(struct fc_ls_rjt_s);
+}
+
+u16
+fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
+		u32 s_id, u16 ox_id, u16 rx_id)
+{
+	fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
+
+	bfa_os_memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s));
+
+	fchs->rx_id = rx_id;
+
+	ba_acc->ox_id = fchs->ox_id;
+	ba_acc->rx_id = fchs->rx_id;
+
+	return sizeof(struct fc_ba_acc_s);
+}
+
+u16
+fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id,
+		u32 s_id, u16 ox_id)
+{
+	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+	bfa_os_memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
+	els_cmd->els_code = FC_ELS_ACC;
+
+	return sizeof(struct fc_els_cmd_s);
+}
+
+int
+fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
+{
+	int             num_pages = 0;
+	struct fc_prlo_s *prlo;
+	struct fc_tprlo_s *tprlo;
+
+	if (els_code == FC_ELS_PRLO) {
+		prlo = (struct fc_prlo_s *) (fc_frame + 1);
+		num_pages = (bfa_os_ntohs(prlo->payload_len) - 4) / 16;
+	} else {
+		tprlo = (struct fc_tprlo_s *) (fc_frame + 1);
+		num_pages = (bfa_os_ntohs(tprlo->payload_len) - 4) / 16;
+	}
+	return num_pages;
+}
+
+u16
+fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
+		u32 d_id, u32 s_id, u16 ox_id, int num_pages)
+{
+	int             page;
+
+	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+	bfa_os_memset(tprlo_acc, 0, (num_pages * 16) + 4);
+	tprlo_acc->command = FC_ELS_ACC;
+
+	tprlo_acc->page_len = 0x10;
+	tprlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4);
+
+	for (page = 0; page < num_pages; page++) {
+		tprlo_acc->tprlo_acc_params[page].opa_valid = 0;
+		tprlo_acc->tprlo_acc_params[page].rpa_valid = 0;
+		tprlo_acc->tprlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
+		tprlo_acc->tprlo_acc_params[page].orig_process_assc = 0;
+		tprlo_acc->tprlo_acc_params[page].resp_process_assc = 0;
+	}
+	return bfa_os_ntohs(tprlo_acc->payload_len);
+}
+
+u16
+fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
+		  u32 s_id, u16 ox_id, int num_pages)
+{
+	int             page;
+
+	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+	bfa_os_memset(prlo_acc, 0, (num_pages * 16) + 4);
+	prlo_acc->command = FC_ELS_ACC;
+	prlo_acc->page_len = 0x10;
+	prlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4);
+
+	for (page = 0; page < num_pages; page++) {
+		prlo_acc->prlo_acc_params[page].opa_valid = 0;
+		prlo_acc->prlo_acc_params[page].rpa_valid = 0;
+		prlo_acc->prlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
+		prlo_acc->prlo_acc_params[page].orig_process_assc = 0;
+		prlo_acc->prlo_acc_params[page].resp_process_assc = 0;
+	}
+
+	return bfa_os_ntohs(prlo_acc->payload_len);
+}
+
+u16
+fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
+		u32 s_id, u16 ox_id, u32 data_format)
+{
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+	bfa_os_memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
+
+	rnid->els_cmd.els_code = FC_ELS_RNID;
+	rnid->node_id_data_format = data_format;
+
+	return sizeof(struct fc_rnid_cmd_s);
+}
+
+u16
+fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
+		  u32 s_id, u16 ox_id, u32 data_format,
+		  struct fc_rnid_common_id_data_s *common_id_data,
+		  struct fc_rnid_general_topology_data_s *gen_topo_data)
+{
+	bfa_os_memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
+
+	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+	rnid_acc->els_cmd.els_code = FC_ELS_ACC;
+	rnid_acc->node_id_data_format = data_format;
+	rnid_acc->common_id_data_length =
+			sizeof(struct fc_rnid_common_id_data_s);
+	rnid_acc->common_id_data = *common_id_data;
+
+	if (data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
+		rnid_acc->specific_id_data_length =
+			sizeof(struct fc_rnid_general_topology_data_s);
+		bfa_os_assign(rnid_acc->gen_topology_data, *gen_topo_data);
+		return sizeof(struct fc_rnid_acc_s);
+	} else {
+		return sizeof(struct fc_rnid_acc_s) -
+			sizeof(struct fc_rnid_general_topology_data_s);
+	}
+
+}
+
+u16
+fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id,
+		u32 s_id, u16 ox_id)
+{
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+	bfa_os_memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
+
+	rpsc->els_cmd.els_code = FC_ELS_RPSC;
+	return sizeof(struct fc_rpsc_cmd_s);
+}
+
+u16
+fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,
+		u32 s_id, u32 *pid_list, u16 npids)
+{
+	u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_os_hton3b(d_id));
+	int i = 0;
+
+	fc_els_req_build(fchs, bfa_os_hton3b(dctlr_id), s_id, 0);
+
+	bfa_os_memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
+
+	rpsc2->els_cmd.els_code = FC_ELS_RPSC;
+	rpsc2->token = bfa_os_htonl(FC_BRCD_TOKEN);
+	rpsc2->num_pids  = bfa_os_htons(npids);
+	for (i = 0; i < npids; i++)
+		rpsc2->pid_list[i].pid = pid_list[i];
+
+	return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * (sizeof(u32)));
+}
+
+u16
+fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
+		u32 d_id, u32 s_id, u16 ox_id,
+		  struct fc_rpsc_speed_info_s *oper_speed)
+{
+	bfa_os_memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
+
+	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+	rpsc_acc->command = FC_ELS_ACC;
+	rpsc_acc->num_entries = bfa_os_htons(1);
+
+	rpsc_acc->speed_info[0].port_speed_cap =
+		bfa_os_htons(oper_speed->port_speed_cap);
+
+	rpsc_acc->speed_info[0].port_op_speed =
+		bfa_os_htons(oper_speed->port_op_speed);
+
+	return sizeof(struct fc_rpsc_acc_s);
+}
+
+/*
+ * TBD -
+ * . get rid of unnecessary memsets
+ */
+
+u16
+fc_logo_rsp_parse(struct fchs_s *fchs, int len)
+{
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+	len = len;
+	if (els_cmd->els_code != FC_ELS_ACC)
+		return FC_PARSE_FAILURE;
+
+	return FC_PARSE_OK;
+}
+
+u16
+fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+	       wwn_t port_name, wwn_t node_name, u16 pdu_size)
+{
+	struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
+
+	bfa_os_memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s));
+
+	pdisc->els_cmd.els_code = FC_ELS_PDISC;
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+	pdisc->csp.rxsz = pdisc->class3.rxsz = bfa_os_htons(pdu_size);
+	pdisc->port_name = port_name;
+	pdisc->node_name = node_name;
+
+	return sizeof(struct fc_logi_s);
+}
+
+u16
+fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
+{
+	struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
+
+	if (len < sizeof(struct fc_logi_s))
+		return FC_PARSE_LEN_INVAL;
+
+	if (pdisc->els_cmd.els_code != FC_ELS_ACC)
+		return FC_PARSE_ACC_INVAL;
+
+	if (!wwn_is_equal(pdisc->port_name, port_name))
+		return FC_PARSE_PWWN_NOT_EQUAL;
+
+	if (!pdisc->class3.class_valid)
+		return FC_PARSE_NWWN_NOT_EQUAL;
+
+	if (bfa_os_ntohs(pdisc->class3.rxsz) < (FC_MIN_PDUSZ))
+		return FC_PARSE_RXSZ_INVAL;
+
+	return FC_PARSE_OK;
+}
+
+u16
+fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+	      int num_pages)
+{
+	struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1);
+	int             page;
+
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+	bfa_os_memset(prlo, 0, (num_pages * 16) + 4);
+	prlo->command = FC_ELS_PRLO;
+	prlo->page_len = 0x10;
+	prlo->payload_len = bfa_os_htons((num_pages * 16) + 4);
+
+	for (page = 0; page < num_pages; page++) {
+		prlo->prlo_params[page].type = FC_TYPE_FCP;
+		prlo->prlo_params[page].opa_valid = 0;
+		prlo->prlo_params[page].rpa_valid = 0;
+		prlo->prlo_params[page].orig_process_assc = 0;
+		prlo->prlo_params[page].resp_process_assc = 0;
+	}
+
+	return bfa_os_ntohs(prlo->payload_len);
+}
+
+u16
+fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
+{
+	struct fc_prlo_acc_s *prlo = (struct fc_prlo_acc_s *) (fchs + 1);
+	int             num_pages = 0;
+	int             page = 0;
+
+	len = len;
+
+	if (prlo->command != FC_ELS_ACC)
+		return FC_PARSE_FAILURE;
+
+	num_pages = ((bfa_os_ntohs(prlo->payload_len)) - 4) / 16;
+
+	for (page = 0; page < num_pages; page++) {
+		if (prlo->prlo_acc_params[page].type != FC_TYPE_FCP)
+			return FC_PARSE_FAILURE;
+
+		if (prlo->prlo_acc_params[page].opa_valid != 0)
+			return FC_PARSE_FAILURE;
+
+		if (prlo->prlo_acc_params[page].rpa_valid != 0)
+			return FC_PARSE_FAILURE;
+
+		if (prlo->prlo_acc_params[page].orig_process_assc != 0)
+			return FC_PARSE_FAILURE;
+
+		if (prlo->prlo_acc_params[page].resp_process_assc != 0)
+			return FC_PARSE_FAILURE;
+	}
+	return FC_PARSE_OK;
+
+}
+
+u16
+fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+	       int num_pages, enum fc_tprlo_type tprlo_type, u32 tpr_id)
+{
+	struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1);
+	int             page;
+
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+	bfa_os_memset(tprlo, 0, (num_pages * 16) + 4);
+	tprlo->command = FC_ELS_TPRLO;
+	tprlo->page_len = 0x10;
+	tprlo->payload_len = bfa_os_htons((num_pages * 16) + 4);
+
+	for (page = 0; page < num_pages; page++) {
+		tprlo->tprlo_params[page].type = FC_TYPE_FCP;
+		tprlo->tprlo_params[page].opa_valid = 0;
+		tprlo->tprlo_params[page].rpa_valid = 0;
+		tprlo->tprlo_params[page].orig_process_assc = 0;
+		tprlo->tprlo_params[page].resp_process_assc = 0;
+		if (tprlo_type == FC_GLOBAL_LOGO) {
+			tprlo->tprlo_params[page].global_process_logout = 1;
+		} else if (tprlo_type == FC_TPR_LOGO) {
+			tprlo->tprlo_params[page].tpo_nport_valid = 1;
+			tprlo->tprlo_params[page].tpo_nport_id = (tpr_id);
+		}
+	}
+
+	return bfa_os_ntohs(tprlo->payload_len);
+}
+
+u16
+fc_tprlo_rsp_parse(struct fchs_s *fchs, int len)
+{
+	struct fc_tprlo_acc_s *tprlo = (struct fc_tprlo_acc_s *) (fchs + 1);
+	int             num_pages = 0;
+	int             page = 0;
+
+	len = len;
+
+	if (tprlo->command != FC_ELS_ACC)
+		return FC_PARSE_ACC_INVAL;
+
+	num_pages = (bfa_os_ntohs(tprlo->payload_len) - 4) / 16;
+
+	for (page = 0; page < num_pages; page++) {
+		if (tprlo->tprlo_acc_params[page].type != FC_TYPE_FCP)
+			return FC_PARSE_NOT_FCP;
+		if (tprlo->tprlo_acc_params[page].opa_valid != 0)
+			return FC_PARSE_OPAFLAG_INVAL;
+		if (tprlo->tprlo_acc_params[page].rpa_valid != 0)
+			return FC_PARSE_RPAFLAG_INVAL;
+		if (tprlo->tprlo_acc_params[page].orig_process_assc != 0)
+			return FC_PARSE_OPA_INVAL;
+		if (tprlo->tprlo_acc_params[page].resp_process_assc != 0)
+			return FC_PARSE_RPA_INVAL;
+	}
+	return FC_PARSE_OK;
+}
+
+enum fc_parse_status
+fc_rrq_rsp_parse(struct fchs_s *fchs, int len)
+{
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+	len = len;
+	if (els_cmd->els_code != FC_ELS_ACC)
+		return FC_PARSE_FAILURE;
+
+	return FC_PARSE_OK;
+}
+
+u16
+fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+		u32 reason_code, u32 reason_expl)
+{
+	struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
+
+	fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
+
+	fchs->cat_info = FC_CAT_BA_RJT;
+	ba_rjt->reason_code = reason_code;
+	ba_rjt->reason_expl = reason_expl;
+	return sizeof(struct fc_ba_rjt_s);
+}
+
+static void
+fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
+{
+	bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s));
+	cthdr->rev_id = CT_GS3_REVISION;
+	cthdr->gs_type = CT_GSTYPE_DIRSERVICE;
+	cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER;
+	cthdr->cmd_rsp_code = bfa_os_htons(cmd_code);
+}
+
+static void
+fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
+{
+	bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s));
+	cthdr->rev_id = CT_GS3_REVISION;
+	cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
+	cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER;
+	cthdr->cmd_rsp_code = bfa_os_htons(cmd_code);
+}
+
+static void
+fc_gs_ms_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code,
+					 u8 sub_type)
+{
+	bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s));
+	cthdr->rev_id = CT_GS3_REVISION;
+	cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
+	cthdr->gs_sub_type = sub_type;
+	cthdr->cmd_rsp_code = bfa_os_htons(cmd_code);
+}
+
+u16
+fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+	       wwn_t port_name)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+	fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN);
+
+	bfa_os_memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s));
+	gidpn->port_name = port_name;
+	return sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+	       u32 port_id)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+	fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID);
+
+	bfa_os_memset(gpnid, 0, sizeof(fcgs_gpnid_req_t));
+	gpnid->dap = port_id;
+	return sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+	       u32 port_id)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+	fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID);
+
+	bfa_os_memset(gnnid, 0, sizeof(fcgs_gnnid_req_t));
+	gnnid->dap = port_id;
+	return sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
+{
+	if (bfa_os_ntohs(cthdr->cmd_rsp_code) != CT_RSP_ACCEPT) {
+		if (cthdr->reason_code == CT_RSN_LOGICAL_BUSY)
+			return FC_PARSE_BUSY;
+		else
+			return FC_PARSE_FAILURE;
+	}
+
+	return FC_PARSE_OK;
+}
+
+u16
+fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
+		u8 set_br_reg, u32 s_id, u16 ox_id)
+{
+	u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
+
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+	bfa_os_memset(scr, 0, sizeof(struct fc_scr_s));
+	scr->command = FC_ELS_SCR;
+	scr->reg_func = FC_SCR_REG_FUNC_FULL;
+	if (set_br_reg)
+		scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE;
+
+	return sizeof(struct fc_scr_s);
+}
+
+u16
+fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
+		u32 s_id, u16 ox_id)
+{
+	u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
+	u16        payldlen;
+
+	fc_els_req_build(fchs, d_id, s_id, ox_id);
+	rscn->command = FC_ELS_RSCN;
+	rscn->pagelen = sizeof(rscn->event[0]);
+
+	payldlen = sizeof(u32) + rscn->pagelen;
+	rscn->payldlen = bfa_os_htons(payldlen);
+
+	rscn->event[0].format = FC_RSCN_FORMAT_PORTID;
+	rscn->event[0].portid = s_id;
+
+	return sizeof(struct fc_rscn_pl_s);
+}
+
+u16
+fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+	       enum bfa_lport_role roles)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
+	u32        type_value, d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u8         index;
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+	fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
+
+	bfa_os_memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
+
+	rftid->dap = s_id;
+
+	/* By default, FCP FC4 Type is registered */
+	index = FC_TYPE_FCP >> 5;
+	type_value = 1 << (FC_TYPE_FCP % 32);
+	rftid->fc4_type[index] = bfa_os_htonl(type_value);
+
+	return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+		   u8 *fc4_bitmap, u32 bitmap_size)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+	fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
+
+	bfa_os_memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
+
+	rftid->dap = s_id;
+	bfa_os_memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap,
+		(bitmap_size < 32 ? bitmap_size : 32));
+
+	return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+	       u8 fc4_type, u8 fc4_ftrs)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1);
+	u32         d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+	fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID);
+
+	bfa_os_memset(rffid, 0, sizeof(struct fcgs_rffid_req_s));
+
+	rffid->dap	    = s_id;
+	rffid->fc4ftr_bits  = fc4_ftrs;
+	rffid->fc4_type	    = fc4_type;
+
+	return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+		u8 *name)
+{
+
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rspnid_req_s *rspnid =
+			(struct fcgs_rspnid_req_s *)(cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+	fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID);
+
+	bfa_os_memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s));
+
+	rspnid->dap = s_id;
+	rspnid->spn_len = (u8) strlen((char *)name);
+	strncpy((char *)rspnid->spn, (char *)name, rspnid->spn_len);
+
+	return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
+{
+
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+
+	fc_gs_cthdr_build(cthdr, s_id, GS_GID_FT);
+
+	bfa_os_memset(gidft, 0, sizeof(struct fcgs_gidft_req_s));
+	gidft->fc4_type = fc4_type;
+	gidft->domain_id = 0;
+	gidft->area_id = 0;
+
+	return sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
+	       wwn_t port_name)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+	fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID);
+
+	bfa_os_memset(rpnid, 0, sizeof(struct fcgs_rpnid_req_s));
+	rpnid->port_id = port_id;
+	rpnid->port_name = port_name;
+
+	return sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
+	       wwn_t node_name)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+	fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID);
+
+	bfa_os_memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s));
+	rnnid->port_id = port_id;
+	rnnid->node_name = node_name;
+
+	return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
+	       u32 cos)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rcsid_req_s *rcsid =
+			(struct fcgs_rcsid_req_s *) (cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+	fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID);
+
+	bfa_os_memset(rcsid, 0, sizeof(struct fcgs_rcsid_req_s));
+	rcsid->port_id = port_id;
+	rcsid->cos = cos;
+
+	return sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
+	       u8 port_type)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+	fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID);
+
+	bfa_os_memset(rptid, 0, sizeof(struct fcgs_rptid_req_s));
+	rptid->port_id = port_id;
+	rptid->port_type = port_type;
+
+	return sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s);
+}
+
+u16
+fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+	fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT);
+
+	bfa_os_memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s));
+	ganxt->port_id = port_id;
+
+	return sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s);
+}
+
+/*
+ * Builds fc hdr and ct hdr for FDMI requests.
+ */
+u16
+fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+		     u16 cmd_code)
+{
+
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+	fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code);
+
+	return sizeof(struct ct_hdr_s);
+}
+
+/*
+ * Given a FC4 Type, this function returns a fc4 type bitmask
+ */
+void
+fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask)
+{
+	u8         index;
+	u32       *ptr = (u32 *) bit_mask;
+	u32        type_value;
+
+	/*
+	 * @todo : Check for bitmask size
+	 */
+
+	index = fc4_type >> 5;
+	type_value = 1 << (fc4_type % 32);
+	ptr[index] = bfa_os_htonl(type_value);
+
+}
+
+/*
+ *	GMAL Request
+ */
+u16
+fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD,
+			CT_GSSUBTYPE_CFGSERVER);
+
+	bfa_os_memset(gmal, 0, sizeof(fcgs_gmal_req_t));
+	gmal->wwn = wwn;
+
+	return sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t);
+}
+
+/*
+ * GFN (Get Fabric Name) Request
+ */
+u16
+fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
+{
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
+	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+
+	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD,
+			CT_GSSUBTYPE_CFGSERVER);
+
+	bfa_os_memset(gfn, 0, sizeof(fcgs_gfn_req_t));
+	gfn->wwn = wwn;
+
+	return sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t);
+}
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
new file mode 100644
index 0000000..73abd02
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * fcbuild.h - FC link service frame building and parsing routines
+ */
+
+#ifndef __FCBUILD_H__
+#define __FCBUILD_H__
+
+#include "bfa_os_inc.h"
+#include "bfa_fc.h"
+#include "bfa_defs_fcs.h"
+
+/*
+ * Utility Macros/functions
+ */
+
+#define wwn_is_equal(_wwn1, _wwn2)		\
+	(memcmp(&(_wwn1), &(_wwn2), sizeof(wwn_t)) == 0)
+
+#define fc_roundup(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1))
+
+/*
+ * Given the fc response length, this routine will return
+ * the length of the actual payload bytes following the CT header.
+ *
+ * Assumes the input response length does not include the crc, eof, etc.
+ */
+static inline   u32
+fc_get_ctresp_pyld_len(u32 resp_len)
+{
+	return resp_len - sizeof(struct ct_hdr_s);
+}
+
+/*
+ * Convert bfa speed to rpsc speed value.
+ */
+static inline  enum bfa_port_speed
+fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed speed)
+{
+	switch (speed) {
+
+	case RPSC_OP_SPEED_1G:
+		return BFA_PORT_SPEED_1GBPS;
+
+	case RPSC_OP_SPEED_2G:
+		return BFA_PORT_SPEED_2GBPS;
+
+	case RPSC_OP_SPEED_4G:
+		return BFA_PORT_SPEED_4GBPS;
+
+	case RPSC_OP_SPEED_8G:
+		return BFA_PORT_SPEED_8GBPS;
+
+	case RPSC_OP_SPEED_10G:
+		return BFA_PORT_SPEED_10GBPS;
+
+	default:
+		return BFA_PORT_SPEED_UNKNOWN;
+	}
+}
+
+/*
+ * Convert RPSC speed to bfa speed value.
+ */
+static inline   enum fc_rpsc_op_speed
+fc_bfa_speed_to_rpsc_operspeed(enum bfa_port_speed op_speed)
+{
+	switch (op_speed) {
+
+	case BFA_PORT_SPEED_1GBPS:
+		return RPSC_OP_SPEED_1G;
+
+	case BFA_PORT_SPEED_2GBPS:
+		return RPSC_OP_SPEED_2G;
+
+	case BFA_PORT_SPEED_4GBPS:
+		return RPSC_OP_SPEED_4G;
+
+	case BFA_PORT_SPEED_8GBPS:
+		return RPSC_OP_SPEED_8G;
+
+	case BFA_PORT_SPEED_10GBPS:
+		return RPSC_OP_SPEED_10G;
+
+	default:
+		return RPSC_OP_SPEED_NOT_EST;
+	}
+}
+
+enum fc_parse_status {
+	FC_PARSE_OK = 0,
+	FC_PARSE_FAILURE = 1,
+	FC_PARSE_BUSY = 2,
+	FC_PARSE_LEN_INVAL,
+	FC_PARSE_ACC_INVAL,
+	FC_PARSE_PWWN_NOT_EQUAL,
+	FC_PARSE_NWWN_NOT_EQUAL,
+	FC_PARSE_RXSZ_INVAL,
+	FC_PARSE_NOT_FCP,
+	FC_PARSE_OPAFLAG_INVAL,
+	FC_PARSE_RPAFLAG_INVAL,
+	FC_PARSE_OPA_INVAL,
+	FC_PARSE_RPA_INVAL,
+
+};
+
+struct fc_templates_s {
+	struct fchs_s fc_els_req;
+	struct fchs_s fc_bls_req;
+	struct fc_logi_s plogi;
+	struct fc_rrq_s rrq;
+};
+
+void            fcbuild_init(void);
+
+u16        fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
+			u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name,
+			       u16 pdu_size, u8 set_npiv, u8 set_auth,
+			       u16 local_bb_credits);
+
+u16        fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi, u32 s_id,
+			       u16 ox_id, wwn_t port_name, wwn_t node_name,
+			       u16 pdu_size);
+
+u16        fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
+				   u32 s_id, u16 ox_id,
+				   wwn_t port_name, wwn_t node_name,
+				   u16 pdu_size,
+				   u16 local_bb_credits);
+
+u16        fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
+			       u32 s_id, u16 ox_id, wwn_t port_name,
+			       wwn_t node_name, u16 pdu_size);
+
+enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
+
+u16        fc_abts_build(struct fchs_s *buf, u32 d_id, u32 s_id,
+			      u16 ox_id);
+
+enum fc_parse_status fc_abts_rsp_parse(struct fchs_s *buf, int len);
+
+u16        fc_rrq_build(struct fchs_s *buf, struct fc_rrq_s *rrq, u32 d_id,
+			     u32 s_id, u16 ox_id, u16 rrq_oxid);
+enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len);
+
+u16        fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+				u16 ox_id, u8 *name);
+
+u16        fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+			       u16 ox_id, enum bfa_lport_role role);
+
+u16       fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
+				   u16 ox_id, u8 *fc4_bitmap,
+				   u32 bitmap_size);
+
+u16	fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			u16 ox_id, u8 fc4_type, u8 fc4_ftrs);
+
+u16        fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u16 ox_id, wwn_t port_name);
+
+u16        fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+			       u16 ox_id, u32 port_id);
+
+u16        fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
+			u8 set_br_reg, u32 s_id, u16 ox_id);
+
+u16        fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+				   u32 s_id, u16 ox_id,
+				   wwn_t port_name, wwn_t node_name,
+				   u16 pdu_size);
+
+u16        fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
+			u32 d_id, u32 s_id, u16 ox_id, wwn_t port_name,
+			       wwn_t node_name);
+
+enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld,
+			u32 host_dap, wwn_t node_name, wwn_t port_name);
+
+enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len,
+				 wwn_t port_name, wwn_t node_name);
+
+u16        fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
+				   u32 d_id, u32 s_id, u16 ox_id,
+				   wwn_t port_name, wwn_t node_name);
+u16        fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt,
+				u32 d_id, u32 s_id, u16 ox_id,
+				u8 reason_code, u8 reason_code_expl);
+u16        fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
+				u32 d_id, u32 s_id, u16 ox_id);
+u16        fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id,
+			      u32 s_id, u16 ox_id);
+
+enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len);
+
+u16        fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+				  u32 s_id, u16 ox_id,
+				  enum bfa_lport_role role);
+
+u16        fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
+			      u32 d_id, u32 s_id, u16 ox_id,
+			      u32 data_format);
+
+u16        fc_rnid_acc_build(struct fchs_s *fchs,
+			struct fc_rnid_acc_s *rnid_acc, u32 d_id, u32 s_id,
+			u16 ox_id, u32 data_format,
+			struct fc_rnid_common_id_data_s *common_id_data,
+			struct fc_rnid_general_topology_data_s *gen_topo_data);
+
+u16	fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rps2c,
+			u32 d_id, u32 s_id, u32 *pid_list, u16 npids);
+u16        fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc,
+			      u32 d_id, u32 s_id, u16 ox_id);
+u16        fc_rpsc_acc_build(struct fchs_s *fchs,
+			struct fc_rpsc_acc_s *rpsc_acc, u32 d_id, u32 s_id,
+			u16 ox_id, struct fc_rpsc_speed_info_s *oper_speed);
+u16        fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,
+				u8 fc4_type);
+
+u16        fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u32 port_id, wwn_t port_name);
+
+u16        fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u32 port_id, wwn_t node_name);
+
+u16        fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u32 port_id, u32 cos);
+
+u16        fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u32 port_id, u8 port_type);
+
+u16        fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u32 port_id);
+
+u16        fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id,
+			      u32 s_id, u16 ox_id, wwn_t port_name);
+
+u16        fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+				  u32 s_id, u16 ox_id);
+
+u16        fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+				     u16 cmd_code);
+u16	fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn);
+u16	fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn);
+
+void		fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);
+
+void		fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+					 u16 ox_id);
+
+enum fc_parse_status	fc_els_rsp_parse(struct fchs_s *fchs, int len);
+
+enum fc_parse_status	fc_plogi_rsp_parse(struct fchs_s *fchs, int len,
+					wwn_t port_name);
+
+enum fc_parse_status	fc_prli_parse(struct fc_prli_s *prli);
+
+enum fc_parse_status	fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name,
+					wwn_t port_name);
+
+u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
+		u32 s_id, u16 ox_id, u16 rx_id);
+
+int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);
+
+u16 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
+		u32 d_id, u32 s_id, u16 ox_id, int num_pages);
+
+u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
+		u32 d_id, u32 s_id, u16 ox_id, int num_pages);
+
+u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len);
+
+u16 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+		u16 ox_id, wwn_t port_name, wwn_t node_name,
+		u16 pdu_size);
+
+u16 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name);
+
+u16 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+		u16 ox_id, int num_pages);
+
+u16 fc_prlo_rsp_parse(struct fchs_s *fchs, int len);
+
+u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+		u16 ox_id, int num_pages, enum fc_tprlo_type tprlo_type,
+		u32 tpr_id);
+
+u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len);
+
+u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+		u16 ox_id, u32 reason_code, u32 reason_expl);
+
+u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+		u32 port_id);
+
+u16 fc_ct_rsp_parse(struct ct_hdr_s *cthdr);
+
+u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id,
+		u16 ox_id);
+#endif
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index 8c703d8..33c8dd5 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,18 +15,291 @@
  * General Public License for more details.
  */
 
-#include <bfa.h>
-#include <log/bfa_log_hal.h>
+#include "bfa_modules.h"
+#include "bfa_cb_ioim.h"
 
 BFA_TRC_FILE(HAL, FCPIM);
 BFA_MODULE(fcpim);
 
+
+#define bfa_fcpim_add_iostats(__l, __r, __stats)	\
+	(__l->__stats += __r->__stats)
+
+
+/**
+ *  BFA ITNIM Related definitions
+ */
+static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
+
+#define BFA_ITNIM_FROM_TAG(_fcpim, _tag)                                \
+	(((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1))))
+
+#define bfa_fcpim_additn(__itnim)					\
+	list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
+#define bfa_fcpim_delitn(__itnim)	do {				\
+	bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));      \
+	bfa_itnim_update_del_itn_stats(__itnim);      \
+	list_del(&(__itnim)->qe);      \
+	bfa_assert(list_empty(&(__itnim)->io_q));      \
+	bfa_assert(list_empty(&(__itnim)->io_cleanup_q));      \
+	bfa_assert(list_empty(&(__itnim)->pending_q));      \
+} while (0)
+
+#define bfa_itnim_online_cb(__itnim) do {				\
+	if ((__itnim)->bfa->fcs)					\
+		bfa_cb_itnim_online((__itnim)->ditn);      \
+	else {								\
+		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
+		__bfa_cb_itnim_online, (__itnim));      \
+	}								\
+} while (0)
+
+#define bfa_itnim_offline_cb(__itnim) do {				\
+	if ((__itnim)->bfa->fcs)					\
+		bfa_cb_itnim_offline((__itnim)->ditn);      \
+	else {								\
+		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
+		__bfa_cb_itnim_offline, (__itnim));      \
+	}								\
+} while (0)
+
+#define bfa_itnim_sler_cb(__itnim) do {					\
+	if ((__itnim)->bfa->fcs)					\
+		bfa_cb_itnim_sler((__itnim)->ditn);      \
+	else {								\
+		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
+		__bfa_cb_itnim_sler, (__itnim));      \
+	}								\
+} while (0)
+
+/**
+ *  bfa_itnim_sm BFA itnim state machine
+ */
+
+
+enum bfa_itnim_event {
+	BFA_ITNIM_SM_CREATE = 1,	/*  itnim is created */
+	BFA_ITNIM_SM_ONLINE = 2,	/*  itnim is online */
+	BFA_ITNIM_SM_OFFLINE = 3,	/*  itnim is offline */
+	BFA_ITNIM_SM_FWRSP = 4,		/*  firmware response */
+	BFA_ITNIM_SM_DELETE = 5,	/*  deleting an existing itnim */
+	BFA_ITNIM_SM_CLEANUP = 6,	/*  IO cleanup completion */
+	BFA_ITNIM_SM_SLER = 7,		/*  second level error recovery */
+	BFA_ITNIM_SM_HWFAIL = 8,	/*  IOC h/w failure event */
+	BFA_ITNIM_SM_QRESUME = 9,	/*  queue space available */
+};
+
+/**
+ *  BFA IOIM related definitions
+ */
+#define bfa_ioim_move_to_comp_q(__ioim) do {				\
+	list_del(&(__ioim)->qe);					\
+	list_add_tail(&(__ioim)->qe, &(__ioim)->fcpim->ioim_comp_q);	\
+} while (0)
+
+
+#define bfa_ioim_cb_profile_comp(__fcpim, __ioim) do {			\
+	if ((__fcpim)->profile_comp)					\
+		(__fcpim)->profile_comp(__ioim);			\
+} while (0)
+
+#define bfa_ioim_cb_profile_start(__fcpim, __ioim) do {			\
+	if ((__fcpim)->profile_start)					\
+		(__fcpim)->profile_start(__ioim);			\
+} while (0)
+/**
+ *  hal_ioim_sm
+ */
+
+/**
+ * IO state machine events
+ */
+enum bfa_ioim_event {
+	BFA_IOIM_SM_START	= 1,	/*  io start request from host */
+	BFA_IOIM_SM_COMP_GOOD	= 2,	/*  io good comp, resource free */
+	BFA_IOIM_SM_COMP	= 3,	/*  io comp, resource is free */
+	BFA_IOIM_SM_COMP_UTAG	= 4,	/*  io comp, resource is free */
+	BFA_IOIM_SM_DONE	= 5,	/*  io comp, resource not free */
+	BFA_IOIM_SM_FREE	= 6,	/*  io resource is freed */
+	BFA_IOIM_SM_ABORT	= 7,	/*  abort request from scsi stack */
+	BFA_IOIM_SM_ABORT_COMP	= 8,	/*  abort from f/w */
+	BFA_IOIM_SM_ABORT_DONE	= 9,	/*  abort completion from f/w */
+	BFA_IOIM_SM_QRESUME	= 10,	/*  CQ space available to queue IO */
+	BFA_IOIM_SM_SGALLOCED	= 11,	/*  SG page allocation successful */
+	BFA_IOIM_SM_SQRETRY	= 12,	/*  sequence recovery retry */
+	BFA_IOIM_SM_HCB		= 13,	/*  bfa callback complete */
+	BFA_IOIM_SM_CLEANUP	= 14,	/*  IO cleanup from itnim */
+	BFA_IOIM_SM_TMSTART	= 15,	/*  IO cleanup from tskim */
+	BFA_IOIM_SM_TMDONE	= 16,	/*  IO cleanup from tskim */
+	BFA_IOIM_SM_HWFAIL	= 17,	/*  IOC h/w failure event */
+	BFA_IOIM_SM_IOTOV	= 18,	/*  ITN offline TOV */
+};
+
+
+/**
+ *  BFA TSKIM related definitions
+ */
+
+/**
+ * task management completion handling
+ */
+#define bfa_tskim_qcomp(__tskim, __cbfn) do {				\
+	bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe, __cbfn, (__tskim));\
+	bfa_tskim_notify_comp(__tskim);      \
+} while (0)
+
+#define bfa_tskim_notify_comp(__tskim) do {				\
+	if ((__tskim)->notify)						\
+		bfa_itnim_tskdone((__tskim)->itnim);      \
+} while (0)
+
+
+enum bfa_tskim_event {
+	BFA_TSKIM_SM_START	= 1,	/*  TM command start		*/
+	BFA_TSKIM_SM_DONE	= 2,	/*  TM completion		*/
+	BFA_TSKIM_SM_QRESUME	= 3,	/*  resume after qfull		*/
+	BFA_TSKIM_SM_HWFAIL	= 5,	/*  IOC h/w failure event	*/
+	BFA_TSKIM_SM_HCB	= 6,	/*  BFA callback completion	*/
+	BFA_TSKIM_SM_IOS_DONE	= 7,	/*  IO and sub TM completions	*/
+	BFA_TSKIM_SM_CLEANUP	= 8,	/*  TM cleanup on ITN offline	*/
+	BFA_TSKIM_SM_CLEANUP_DONE = 9,	/*  TM abort completion	*/
+};
+
+/**
+ * forward declaration for BFA ITNIM functions
+ */
+static void     bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
+static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
+static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_cleanp_comp(void *itnim_cbarg);
+static void     bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
+static void     __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
+static void     __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
+static void     __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
+static void     bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov(void *itnim_arg);
+static void     bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
+
+/**
+ * forward declaration of ITNIM state machine
+ */
+static void     bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+
+/**
+ * forward declaration for BFA IOIM functions
+ */
+static bfa_boolean_t	bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
+static bfa_boolean_t	bfa_ioim_sge_setup(struct bfa_ioim_s *ioim);
+static void		bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim);
+static bfa_boolean_t	bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
+static void		bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
+static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
+static bfa_boolean_t    bfa_ioim_is_abortable(struct bfa_ioim_s *ioim);
+
+
+/**
+ * forward declaration of BFA IO state machine
+ */
+static void     bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_active(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_abort(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void	bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+
+/**
+ * forward declaration for BFA TSKIM functions
+ */
+static void     __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);
+static void     __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);
+static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,
+					lun_t lun);
+static void     bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);
+static void     bfa_tskim_cleanp_comp(void *tskim_cbarg);
+static void     bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);
+static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);
+static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);
+static void     bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);
+
+
+/**
+ * forward declaration of BFA TSKIM state machine
+ */
+static void     bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_active(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+
 /**
  *  hal_fcpim_mod BFA FCP Initiator Mode module
  */
 
 /**
- * 		Compute and return memory needed by FCP(im) module.
+ *	Compute and return memory needed by FCP(im) module.
  */
 static void
 bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
@@ -58,7 +331,7 @@
 
 static void
 bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		     struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
 
@@ -67,12 +340,14 @@
 	bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs);
 	bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs);
 
-	fcpim->bfa            = bfa;
-	fcpim->num_itnims     = cfg->fwcfg.num_rports;
+	fcpim->bfa		= bfa;
+	fcpim->num_itnims	= cfg->fwcfg.num_rports;
 	fcpim->num_ioim_reqs  = cfg->fwcfg.num_ioim_reqs;
 	fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs;
-	fcpim->path_tov       = cfg->drvcfg.path_tov;
-	fcpim->delay_comp	  = cfg->drvcfg.delay_comp;
+	fcpim->path_tov		= cfg->drvcfg.path_tov;
+	fcpim->delay_comp	= cfg->drvcfg.delay_comp;
+	fcpim->profile_comp = NULL;
+	fcpim->profile_start = NULL;
 
 	bfa_itnim_attach(fcpim, meminfo);
 	bfa_tskim_attach(fcpim, meminfo);
@@ -103,7 +378,7 @@
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
 	struct bfa_itnim_s *itnim;
-	struct list_head        *qe, *qen;
+	struct list_head *qe, *qen;
 
 	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
 		itnim = (struct bfa_itnim_s *) qe;
@@ -112,6 +387,56 @@
 }
 
 void
+bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
+		struct bfa_itnim_iostats_s *rstats)
+{
+	bfa_fcpim_add_iostats(lstats, rstats, total_ios);
+	bfa_fcpim_add_iostats(lstats, rstats, qresumes);
+	bfa_fcpim_add_iostats(lstats, rstats, no_iotags);
+	bfa_fcpim_add_iostats(lstats, rstats, io_aborts);
+	bfa_fcpim_add_iostats(lstats, rstats, no_tskims);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_ok);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_underrun);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_overrun);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_aborted);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_timedout);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_nexus_abort);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_proto_err);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_dif_err);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_sqer_needed);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_res_free);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_hostabrts);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_utags);
+	bfa_fcpim_add_iostats(lstats, rstats, io_cleanups);
+	bfa_fcpim_add_iostats(lstats, rstats, io_tmaborts);
+	bfa_fcpim_add_iostats(lstats, rstats, onlines);
+	bfa_fcpim_add_iostats(lstats, rstats, offlines);
+	bfa_fcpim_add_iostats(lstats, rstats, creates);
+	bfa_fcpim_add_iostats(lstats, rstats, deletes);
+	bfa_fcpim_add_iostats(lstats, rstats, create_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, delete_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, sler_events);
+	bfa_fcpim_add_iostats(lstats, rstats, fw_create);
+	bfa_fcpim_add_iostats(lstats, rstats, fw_delete);
+	bfa_fcpim_add_iostats(lstats, rstats, ioc_disabled);
+	bfa_fcpim_add_iostats(lstats, rstats, cleanup_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_cmnds);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_fw_rsps);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_success);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_failures);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_io_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_qresumes);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_iocdowns);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanups);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanup_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, io_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, input_reqs);
+	bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
+	bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
+	bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
+}
+
+void
 bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
@@ -130,21 +455,113 @@
 }
 
 bfa_status_t
-bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_fcpim_stats_s *modstats)
+bfa_fcpim_port_iostats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *stats,
+	u8 lp_tag)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct list_head *qe, *qen;
+	struct bfa_itnim_s *itnim;
+
+	/* accumulate IO stats from itnim */
+	bfa_os_memset(stats, 0, sizeof(struct bfa_itnim_iostats_s));
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		if (itnim->rport->rport_info.lp_tag != lp_tag)
+			continue;
+		bfa_fcpim_add_stats(stats, &(itnim->stats));
+	}
+	return BFA_STATUS_OK;
+}
+bfa_status_t
+bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *modstats)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct list_head *qe, *qen;
+	struct bfa_itnim_s *itnim;
+
+	/* accumulate IO stats from itnim */
+	bfa_os_memset(modstats, 0, sizeof(struct bfa_itnim_iostats_s));
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		bfa_fcpim_add_stats(modstats, &(itnim->stats));
+	}
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa,
+	 struct bfa_fcpim_del_itn_stats_s *modstats)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
 
-	*modstats = fcpim->stats;
+	*modstats = fcpim->del_itn_stats;
 
 	return BFA_STATUS_OK;
 }
 
+
+bfa_status_t
+bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time)
+{
+	struct bfa_itnim_s *itnim;
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct list_head *qe, *qen;
+
+	/* accumulate IO stats from itnim */
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		bfa_itnim_clear_stats(itnim);
+	}
+	fcpim->io_profile = BFA_TRUE;
+	fcpim->io_profile_start_time = time;
+	fcpim->profile_comp = bfa_ioim_profile_comp;
+	fcpim->profile_start = bfa_ioim_profile_start;
+
+	return BFA_STATUS_OK;
+}
+bfa_status_t
+bfa_fcpim_profile_off(struct bfa_s *bfa)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	fcpim->io_profile = BFA_FALSE;
+	fcpim->io_profile_start_time = 0;
+	fcpim->profile_comp = NULL;
+	fcpim->profile_start = NULL;
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct list_head *qe, *qen;
+	struct bfa_itnim_s *itnim;
+
+	/* clear IO stats from all active itnims */
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		if (itnim->rport->rport_info.lp_tag != lp_tag)
+			continue;
+		bfa_itnim_clear_stats(itnim);
+	}
+	return BFA_STATUS_OK;
+
+}
+
 bfa_status_t
 bfa_fcpim_clr_modstats(struct bfa_s *bfa)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct list_head *qe, *qen;
+	struct bfa_itnim_s *itnim;
 
-	memset(&fcpim->stats, 0, sizeof(struct bfa_fcpim_stats_s));
+	/* clear IO stats from all active itnims */
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		bfa_itnim_clear_stats(itnim);
+	}
+	bfa_os_memset(&fcpim->del_itn_stats, 0,
+		sizeof(struct bfa_fcpim_del_itn_stats_s));
 
 	return BFA_STATUS_OK;
 }
@@ -176,14 +593,6 @@
 	 * IO redirection is turned off when QoS is enabled and vice versa
 	 */
 	ioredirect = bfa_fcport_is_qos_enabled(bfa) ? BFA_FALSE : BFA_TRUE;
-
-	/*
-	 * Notify the bfad module of a possible state change in
-	 * IO redirection capability, due to a QoS state change. bfad will
-	 * check on the support for io redirection and update the
-	 * fcpim's ioredirect state accordingly.
-	 */
-	bfa_cb_ioredirect_state_change((void *)(bfa->bfad), ioredirect);
 }
 
 void
@@ -192,3 +601,3012 @@
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
 	fcpim->ioredirect = state;
 }
+
+
+
+/**
+ *  BFA ITNIM module state machine functions
+ */
+
+/**
+ *	Beginning/unallocated state - no events expected.
+ */
+static void
+bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_CREATE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_created);
+		itnim->is_online = BFA_FALSE;
+		bfa_fcpim_additn(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Beginning state, only online event expected.
+ */
+static void
+bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_ONLINE:
+		if (bfa_itnim_send_fwcreate(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Waiting for itnim create response from firmware.
+ */
+static void
+bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_FWRSP:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_online);
+		itnim->is_online = BFA_TRUE;
+		bfa_itnim_iotov_online(itnim);
+		bfa_itnim_online_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending);
+		break;
+
+	case BFA_ITNIM_SM_OFFLINE:
+		if (bfa_itnim_send_fwdelete(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+static void
+bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
+			enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_QRESUME:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+		bfa_itnim_send_fwcreate(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_reqq_wcancel(&itnim->reqq_wait);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	case BFA_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
+		bfa_reqq_wcancel(&itnim->reqq_wait);
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_reqq_wcancel(&itnim->reqq_wait);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Waiting for itnim create response from firmware, a delete is pending.
+ */
+static void
+bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
+				enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_FWRSP:
+		if (bfa_itnim_send_fwdelete(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Online state - normal parking state.
+ */
+static void
+bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
+		itnim->is_online = BFA_FALSE;
+		bfa_itnim_iotov_start(itnim);
+		bfa_itnim_cleanup(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+		itnim->is_online = BFA_FALSE;
+		bfa_itnim_cleanup(itnim);
+		break;
+
+	case BFA_ITNIM_SM_SLER:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_sler);
+		itnim->is_online = BFA_FALSE;
+		bfa_itnim_iotov_start(itnim);
+		bfa_itnim_sler_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		itnim->is_online = BFA_FALSE;
+		bfa_itnim_iotov_start(itnim);
+		bfa_itnim_iocdisable_cleanup(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Second level error recovery need.
+ */
+static void
+bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
+		bfa_itnim_cleanup(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+		bfa_itnim_cleanup(itnim);
+		bfa_itnim_iotov_delete(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_itnim_iocdisable_cleanup(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Going offline. Waiting for active IO cleanup.
+ */
+static void
+bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
+				 enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_CLEANUP:
+		if (bfa_itnim_send_fwdelete(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+		bfa_itnim_iotov_delete(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_itnim_iocdisable_cleanup(itnim);
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_SLER:
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Deleting itnim. Waiting for active IO cleanup.
+ */
+static void
+bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
+				enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_CLEANUP:
+		if (bfa_itnim_send_fwdelete(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_itnim_iocdisable_cleanup(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ * Rport offline. Fimrware itnim is being deleted - awaiting f/w response.
+ */
+static void
+bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_FWRSP:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+static void
+bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
+			enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_QRESUME:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+		bfa_itnim_send_fwdelete(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_reqq_wcancel(&itnim->reqq_wait);
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Offline state.
+ */
+static void
+bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_itnim_iotov_delete(itnim);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	case BFA_ITNIM_SM_ONLINE:
+		if (bfa_itnim_send_fwcreate(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	IOC h/w failed state.
+ */
+static void
+bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
+				enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_itnim_iotov_delete(itnim);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	case BFA_ITNIM_SM_OFFLINE:
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_ONLINE:
+		if (bfa_itnim_send_fwcreate(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Itnim is deleted, waiting for firmware response to delete.
+ */
+static void
+bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_FWRSP:
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+static void
+bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
+		enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_QRESUME:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+		bfa_itnim_send_fwdelete(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_reqq_wcancel(&itnim->reqq_wait);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Initiate cleanup of all IOs on an IOC failure.
+ */
+static void
+bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
+{
+	struct bfa_tskim_s *tskim;
+	struct bfa_ioim_s *ioim;
+	struct list_head	*qe, *qen;
+
+	list_for_each_safe(qe, qen, &itnim->tsk_q) {
+		tskim = (struct bfa_tskim_s *) qe;
+		bfa_tskim_iocdisable(tskim);
+	}
+
+	list_for_each_safe(qe, qen, &itnim->io_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		bfa_ioim_iocdisable(ioim);
+	}
+
+	/**
+	 * For IO request in pending queue, we pretend an early timeout.
+	 */
+	list_for_each_safe(qe, qen, &itnim->pending_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		bfa_ioim_tov(ioim);
+	}
+
+	list_for_each_safe(qe, qen, &itnim->io_cleanup_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		bfa_ioim_iocdisable(ioim);
+	}
+}
+
+/**
+ *	IO cleanup completion
+ */
+static void
+bfa_itnim_cleanp_comp(void *itnim_cbarg)
+{
+	struct bfa_itnim_s *itnim = itnim_cbarg;
+
+	bfa_stats(itnim, cleanup_comps);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP);
+}
+
+/**
+ *	Initiate cleanup of all IOs.
+ */
+static void
+bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
+{
+	struct bfa_ioim_s  *ioim;
+	struct bfa_tskim_s *tskim;
+	struct list_head	*qe, *qen;
+
+	bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim);
+
+	list_for_each_safe(qe, qen, &itnim->io_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+
+		/**
+		 * Move IO to a cleanup queue from active queue so that a later
+		 * TM will not pickup this IO.
+		 */
+		list_del(&ioim->qe);
+		list_add_tail(&ioim->qe, &itnim->io_cleanup_q);
+
+		bfa_wc_up(&itnim->wc);
+		bfa_ioim_cleanup(ioim);
+	}
+
+	list_for_each_safe(qe, qen, &itnim->tsk_q) {
+		tskim = (struct bfa_tskim_s *) qe;
+		bfa_wc_up(&itnim->wc);
+		bfa_tskim_cleanup(tskim);
+	}
+
+	bfa_wc_wait(&itnim->wc);
+}
+
+static void
+__bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_itnim_s *itnim = cbarg;
+
+	if (complete)
+		bfa_cb_itnim_online(itnim->ditn);
+}
+
+static void
+__bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_itnim_s *itnim = cbarg;
+
+	if (complete)
+		bfa_cb_itnim_offline(itnim->ditn);
+}
+
+static void
+__bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_itnim_s *itnim = cbarg;
+
+	if (complete)
+		bfa_cb_itnim_sler(itnim->ditn);
+}
+
+/**
+ * Call to resume any I/O requests waiting for room in request queue.
+ */
+static void
+bfa_itnim_qresume(void *cbarg)
+{
+	struct bfa_itnim_s *itnim = cbarg;
+
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
+}
+
+
+
+
+/**
+ *  bfa_itnim_public
+ */
+
+void
+bfa_itnim_iodone(struct bfa_itnim_s *itnim)
+{
+	bfa_wc_down(&itnim->wc);
+}
+
+void
+bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
+{
+	bfa_wc_down(&itnim->wc);
+}
+
+void
+bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+		u32 *dm_len)
+{
+	/**
+	 * ITN memory
+	 */
+	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s);
+}
+
+void
+bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+	struct bfa_s	*bfa = fcpim->bfa;
+	struct bfa_itnim_s *itnim;
+	int	i, j;
+
+	INIT_LIST_HEAD(&fcpim->itnim_q);
+
+	itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
+	fcpim->itnim_arr = itnim;
+
+	for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
+		bfa_os_memset(itnim, 0, sizeof(struct bfa_itnim_s));
+		itnim->bfa = bfa;
+		itnim->fcpim = fcpim;
+		itnim->reqq = BFA_REQQ_QOS_LO;
+		itnim->rport = BFA_RPORT_FROM_TAG(bfa, i);
+		itnim->iotov_active = BFA_FALSE;
+		bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim);
+
+		INIT_LIST_HEAD(&itnim->io_q);
+		INIT_LIST_HEAD(&itnim->io_cleanup_q);
+		INIT_LIST_HEAD(&itnim->pending_q);
+		INIT_LIST_HEAD(&itnim->tsk_q);
+		INIT_LIST_HEAD(&itnim->delay_comp_q);
+		for (j = 0; j < BFA_IOBUCKET_MAX; j++)
+			itnim->ioprofile.io_latency.min[j] = ~0;
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+	}
+
+	bfa_meminfo_kva(minfo) = (u8 *) itnim;
+}
+
+void
+bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
+{
+	bfa_stats(itnim, ioc_disabled);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL);
+}
+
+static bfa_boolean_t
+bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
+{
+	struct bfi_itnim_create_req_s *m;
+
+	itnim->msg_no++;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
+	if (!m) {
+		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
+			bfa_lpuid(itnim->bfa));
+	m->fw_handle = itnim->rport->fw_handle;
+	m->class = FC_CLASS_3;
+	m->seq_rec = itnim->seq_rec;
+	m->msg_no = itnim->msg_no;
+	bfa_stats(itnim, fw_create);
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(itnim->bfa, itnim->reqq);
+	return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
+{
+	struct bfi_itnim_delete_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
+	if (!m) {
+		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
+			bfa_lpuid(itnim->bfa));
+	m->fw_handle = itnim->rport->fw_handle;
+	bfa_stats(itnim, fw_delete);
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(itnim->bfa, itnim->reqq);
+	return BFA_TRUE;
+}
+
+/**
+ * Cleanup all pending failed inflight requests.
+ */
+static void
+bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov)
+{
+	struct bfa_ioim_s *ioim;
+	struct list_head *qe, *qen;
+
+	list_for_each_safe(qe, qen, &itnim->delay_comp_q) {
+		ioim = (struct bfa_ioim_s *)qe;
+		bfa_ioim_delayed_comp(ioim, iotov);
+	}
+}
+
+/**
+ * Start all pending IO requests.
+ */
+static void
+bfa_itnim_iotov_online(struct bfa_itnim_s *itnim)
+{
+	struct bfa_ioim_s *ioim;
+
+	bfa_itnim_iotov_stop(itnim);
+
+	/**
+	 * Abort all inflight IO requests in the queue
+	 */
+	bfa_itnim_delayed_comp(itnim, BFA_FALSE);
+
+	/**
+	 * Start all pending IO requests.
+	 */
+	while (!list_empty(&itnim->pending_q)) {
+		bfa_q_deq(&itnim->pending_q, &ioim);
+		list_add_tail(&ioim->qe, &itnim->io_q);
+		bfa_ioim_start(ioim);
+	}
+}
+
+/**
+ * Fail all pending IO requests
+ */
+static void
+bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim)
+{
+	struct bfa_ioim_s *ioim;
+
+	/**
+	 * Fail all inflight IO requests in the queue
+	 */
+	bfa_itnim_delayed_comp(itnim, BFA_TRUE);
+
+	/**
+	 * Fail any pending IO requests.
+	 */
+	while (!list_empty(&itnim->pending_q)) {
+		bfa_q_deq(&itnim->pending_q, &ioim);
+		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+		bfa_ioim_tov(ioim);
+	}
+}
+
+/**
+ * IO TOV timer callback. Fail any pending IO requests.
+ */
+static void
+bfa_itnim_iotov(void *itnim_arg)
+{
+	struct bfa_itnim_s *itnim = itnim_arg;
+
+	itnim->iotov_active = BFA_FALSE;
+
+	bfa_cb_itnim_tov_begin(itnim->ditn);
+	bfa_itnim_iotov_cleanup(itnim);
+	bfa_cb_itnim_tov(itnim->ditn);
+}
+
+/**
+ * Start IO TOV timer for failing back pending IO requests in offline state.
+ */
+static void
+bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)
+{
+	if (itnim->fcpim->path_tov > 0) {
+
+		itnim->iotov_active = BFA_TRUE;
+		bfa_assert(bfa_itnim_hold_io(itnim));
+		bfa_timer_start(itnim->bfa, &itnim->timer,
+			bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
+	}
+}
+
+/**
+ * Stop IO TOV timer.
+ */
+static void
+bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim)
+{
+	if (itnim->iotov_active) {
+		itnim->iotov_active = BFA_FALSE;
+		bfa_timer_stop(&itnim->timer);
+	}
+}
+
+/**
+ * Stop IO TOV timer.
+ */
+static void
+bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
+{
+	bfa_boolean_t pathtov_active = BFA_FALSE;
+
+	if (itnim->iotov_active)
+		pathtov_active = BFA_TRUE;
+
+	bfa_itnim_iotov_stop(itnim);
+	if (pathtov_active)
+		bfa_cb_itnim_tov_begin(itnim->ditn);
+	bfa_itnim_iotov_cleanup(itnim);
+	if (pathtov_active)
+		bfa_cb_itnim_tov(itnim->ditn);
+}
+
+static void
+bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa);
+	fcpim->del_itn_stats.del_itn_iocomp_aborted +=
+		itnim->stats.iocomp_aborted;
+	fcpim->del_itn_stats.del_itn_iocomp_timedout +=
+		itnim->stats.iocomp_timedout;
+	fcpim->del_itn_stats.del_itn_iocom_sqer_needed +=
+		itnim->stats.iocom_sqer_needed;
+	fcpim->del_itn_stats.del_itn_iocom_res_free +=
+		itnim->stats.iocom_res_free;
+	fcpim->del_itn_stats.del_itn_iocom_hostabrts +=
+		itnim->stats.iocom_hostabrts;
+	fcpim->del_itn_stats.del_itn_total_ios += itnim->stats.total_ios;
+	fcpim->del_itn_stats.del_io_iocdowns += itnim->stats.io_iocdowns;
+	fcpim->del_itn_stats.del_tm_iocdowns += itnim->stats.tm_iocdowns;
+}
+
+
+
+/**
+ *  bfa_itnim_public
+ */
+
+/**
+ *	Itnim interrupt processing.
+ */
+void
+bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	union bfi_itnim_i2h_msg_u msg;
+	struct bfa_itnim_s *itnim;
+
+	bfa_trc(bfa, m->mhdr.msg_id);
+
+	msg.msg = m;
+
+	switch (m->mhdr.msg_id) {
+	case BFI_ITNIM_I2H_CREATE_RSP:
+		itnim = BFA_ITNIM_FROM_TAG(fcpim,
+						msg.create_rsp->bfa_handle);
+		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+		bfa_stats(itnim, create_comps);
+		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
+		break;
+
+	case BFI_ITNIM_I2H_DELETE_RSP:
+		itnim = BFA_ITNIM_FROM_TAG(fcpim,
+						msg.delete_rsp->bfa_handle);
+		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+		bfa_stats(itnim, delete_comps);
+		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
+		break;
+
+	case BFI_ITNIM_I2H_SLER_EVENT:
+		itnim = BFA_ITNIM_FROM_TAG(fcpim,
+						msg.sler_event->bfa_handle);
+		bfa_stats(itnim, sler_events);
+		bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER);
+		break;
+
+	default:
+		bfa_trc(bfa, m->mhdr.msg_id);
+		bfa_assert(0);
+	}
+}
+
+
+
+/**
+ *  bfa_itnim_api
+ */
+
+struct bfa_itnim_s *
+bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_itnim_s *itnim;
+
+	itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
+	bfa_assert(itnim->rport == rport);
+
+	itnim->ditn = ditn;
+
+	bfa_stats(itnim, creates);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);
+
+	return itnim;
+}
+
+void
+bfa_itnim_delete(struct bfa_itnim_s *itnim)
+{
+	bfa_stats(itnim, deletes);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE);
+}
+
+void
+bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec)
+{
+	itnim->seq_rec = seq_rec;
+	bfa_stats(itnim, onlines);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE);
+}
+
+void
+bfa_itnim_offline(struct bfa_itnim_s *itnim)
+{
+	bfa_stats(itnim, offlines);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE);
+}
+
+/**
+ * Return true if itnim is considered offline for holding off IO request.
+ * IO is not held if itnim is being deleted.
+ */
+bfa_boolean_t
+bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
+{
+	return itnim->fcpim->path_tov && itnim->iotov_active &&
+		(bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||
+		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||
+		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) ||
+		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||
+		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||
+		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable));
+}
+
+bfa_status_t
+bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
+		struct bfa_itnim_ioprofile_s *ioprofile)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa);
+	if (!fcpim->io_profile)
+		return BFA_STATUS_IOPROFILE_OFF;
+
+	itnim->ioprofile.index = BFA_IOBUCKET_MAX;
+	itnim->ioprofile.io_profile_start_time =
+		bfa_io_profile_start_time(itnim->bfa);
+	itnim->ioprofile.clock_res_mul = bfa_io_lat_clock_res_mul;
+	itnim->ioprofile.clock_res_div = bfa_io_lat_clock_res_div;
+	*ioprofile = itnim->ioprofile;
+
+	return BFA_STATUS_OK;
+}
+
+void
+bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
+	struct bfa_itnim_iostats_s *stats)
+{
+	*stats = itnim->stats;
+}
+
+void
+bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
+{
+	int j;
+	bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats));
+	bfa_os_memset(&itnim->ioprofile, 0, sizeof(itnim->ioprofile));
+	for (j = 0; j < BFA_IOBUCKET_MAX; j++)
+		itnim->ioprofile.io_latency.min[j] = ~0;
+}
+
+/**
+ *  BFA IO module state machine functions
+ */
+
+/**
+ *	IO is not started (unallocated).
+ */
+static void
+bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_trc_fp(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_START:
+		if (!bfa_itnim_is_online(ioim->itnim)) {
+			if (!bfa_itnim_hold_io(ioim->itnim)) {
+				bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+				list_del(&ioim->qe);
+				list_add_tail(&ioim->qe,
+					&ioim->fcpim->ioim_comp_q);
+				bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+						__bfa_cb_ioim_pathtov, ioim);
+			} else {
+				list_del(&ioim->qe);
+				list_add_tail(&ioim->qe,
+					&ioim->itnim->pending_q);
+			}
+			break;
+		}
+
+		if (ioim->nsges > BFI_SGE_INLINE) {
+			if (!bfa_ioim_sge_setup(ioim)) {
+				bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);
+				return;
+			}
+		}
+
+		if (!bfa_ioim_send_ioreq(ioim)) {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
+			break;
+		}
+
+		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+		break;
+
+	case BFA_IOIM_SM_IOTOV:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+				__bfa_cb_ioim_pathtov, ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		/**
+		 * IO in pending queue can get abort requests. Complete abort
+		 * requests immediately.
+		 */
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+				__bfa_cb_ioim_abort, ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	IO is waiting for SG pages.
+ */
+static void
+bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_SGALLOCED:
+		if (!bfa_ioim_send_ioreq(ioim)) {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
+			break;
+		}
+		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	IO is active.
+ */
+static void
+bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_trc_fp(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_COMP_GOOD:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+			      __bfa_cb_ioim_good_comp, ioim);
+		break;
+
+	case BFA_IOIM_SM_COMP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_DONE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		ioim->iosp->abort_explicit = BFA_TRUE;
+		ioim->io_cbfn = __bfa_cb_ioim_abort;
+
+		if (bfa_ioim_send_abort(ioim))
+			bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
+		else {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull);
+			bfa_stats(ioim->itnim, qwait);
+			bfa_reqq_wait(ioim->bfa, ioim->reqq,
+					  &ioim->iosp->reqq_wait);
+		}
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		ioim->iosp->abort_explicit = BFA_FALSE;
+		ioim->io_cbfn = __bfa_cb_ioim_failed;
+
+		if (bfa_ioim_send_abort(ioim))
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+		else {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+			bfa_stats(ioim->itnim, qwait);
+			bfa_reqq_wait(ioim->bfa, ioim->reqq,
+					  &ioim->iosp->reqq_wait);
+		}
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_SQRETRY:
+		if (bfa_ioim_get_iotag(ioim) != BFA_TRUE) {
+			/* max retry completed free IO */
+			bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+			bfa_ioim_move_to_comp_q(ioim);
+			bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+					__bfa_cb_ioim_failed, ioim);
+			break;
+		}
+		/* waiting for IO tag resource free */
+		bfa_sm_set_state(ioim, bfa_ioim_sm_cmnd_retry);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+*	IO is retried with new tag.
+*/
+static void
+bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_trc_fp(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_FREE:
+		/* abts and rrq done. Now retry the IO with new tag */
+		if (!bfa_ioim_send_ioreq(ioim)) {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
+			break;
+		}
+		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+	break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		ioim->iosp->abort_explicit = BFA_FALSE;
+		ioim->io_cbfn = __bfa_cb_ioim_failed;
+
+		if (bfa_ioim_send_abort(ioim))
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+		else {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+			bfa_stats(ioim->itnim, qwait);
+			bfa_reqq_wait(ioim->bfa, ioim->reqq,
+					  &ioim->iosp->reqq_wait);
+		}
+	break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+			 __bfa_cb_ioim_failed, ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		/** in this state IO abort is done.
+		 * Waiting for IO tag resource free.
+		 */
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	IO is being aborted, waiting for completion from firmware.
+ */
+static void
+bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_COMP_GOOD:
+	case BFA_IOIM_SM_COMP:
+	case BFA_IOIM_SM_DONE:
+	case BFA_IOIM_SM_FREE:
+		break;
+
+	case BFA_IOIM_SM_ABORT_DONE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT_COMP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_COMP_UTAG:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+		ioim->iosp->abort_explicit = BFA_FALSE;
+
+		if (bfa_ioim_send_abort(ioim))
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+		else {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+			bfa_stats(ioim->itnim, qwait);
+			bfa_reqq_wait(ioim->bfa, ioim->reqq,
+					  &ioim->iosp->reqq_wait);
+		}
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ * IO is being cleaned up (implicit abort), waiting for completion from
+ * firmware.
+ */
+static void
+bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_COMP_GOOD:
+	case BFA_IOIM_SM_COMP:
+	case BFA_IOIM_SM_DONE:
+	case BFA_IOIM_SM_FREE:
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		/**
+		 * IO is already being aborted implicitly
+		 */
+		ioim->io_cbfn = __bfa_cb_ioim_abort;
+		break;
+
+	case BFA_IOIM_SM_ABORT_DONE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT_COMP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_COMP_UTAG:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		/**
+		 * IO can be in cleanup state already due to TM command.
+		 * 2nd cleanup request comes from ITN offline event.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	IO is waiting for room in request CQ
+ */
+static void
+bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_QRESUME:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+		bfa_ioim_send_ioreq(ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	Active IO is being aborted, waiting for room in request CQ.
+ */
+static void
+bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_QRESUME:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
+		bfa_ioim_send_abort(ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+		ioim->iosp->abort_explicit = BFA_FALSE;
+		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+		break;
+
+	case BFA_IOIM_SM_COMP_GOOD:
+	case BFA_IOIM_SM_COMP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_DONE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	Active IO is being cleaned up, waiting for room in request CQ.
+ */
+static void
+bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_QRESUME:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+		bfa_ioim_send_abort(ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		/**
+		 * IO is alraedy being cleaned up implicitly
+		 */
+		ioim->io_cbfn = __bfa_cb_ioim_abort;
+		break;
+
+	case BFA_IOIM_SM_COMP_GOOD:
+	case BFA_IOIM_SM_COMP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_DONE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ * IO bfa callback is pending.
+ */
+static void
+bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_trc_fp(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_HCB:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+		bfa_ioim_free(ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ * IO bfa callback is pending. IO resource cannot be freed.
+ */
+static void
+bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_HCB:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_resfree);
+		list_del(&ioim->qe);
+		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_resfree_q);
+		break;
+
+	case BFA_IOIM_SM_FREE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ * IO is completed, waiting resource free from firmware.
+ */
+static void
+bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_FREE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+		bfa_ioim_free(ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+
+
+/**
+ *  hal_ioim_private
+ */
+
+static void
+__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	if (!complete) {
+		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+		return;
+	}
+
+	bfa_cb_ioim_good_comp(ioim->bfa->bfad, ioim->dio);
+}
+
+static void
+__bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_ioim_s	*ioim = cbarg;
+	struct bfi_ioim_rsp_s *m;
+	u8	*snsinfo = NULL;
+	u8	sns_len = 0;
+	s32	residue = 0;
+
+	if (!complete) {
+		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+		return;
+	}
+
+	m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
+	if (m->io_status == BFI_IOIM_STS_OK) {
+		/**
+		 * setup sense information, if present
+		 */
+		if ((m->scsi_status == SCSI_STATUS_CHECK_CONDITION) &&
+					m->sns_len) {
+			sns_len = m->sns_len;
+			snsinfo = ioim->iosp->snsinfo;
+		}
+
+		/**
+		 * setup residue value correctly for normal completions
+		 */
+		if (m->resid_flags == FCP_RESID_UNDER) {
+			residue = bfa_os_ntohl(m->residue);
+			bfa_stats(ioim->itnim, iocomp_underrun);
+		}
+		if (m->resid_flags == FCP_RESID_OVER) {
+			residue = bfa_os_ntohl(m->residue);
+			residue = -residue;
+			bfa_stats(ioim->itnim, iocomp_overrun);
+		}
+	}
+
+	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, m->io_status,
+			  m->scsi_status, sns_len, snsinfo, residue);
+}
+
+static void
+__bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	if (!complete) {
+		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+		return;
+	}
+
+	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
+			  0, 0, NULL, 0);
+}
+
+static void
+__bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	bfa_stats(ioim->itnim, path_tov_expired);
+	if (!complete) {
+		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+		return;
+	}
+
+	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
+			  0, 0, NULL, 0);
+}
+
+static void
+__bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	if (!complete) {
+		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+		return;
+	}
+
+	bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
+}
+
+static void
+bfa_ioim_sgpg_alloced(void *cbarg)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
+	list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);
+	bfa_ioim_sgpg_setup(ioim);
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);
+}
+
+/**
+ * Send I/O request to firmware.
+ */
+static	bfa_boolean_t
+bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
+{
+	struct bfa_itnim_s *itnim = ioim->itnim;
+	struct bfi_ioim_req_s *m;
+	static struct fcp_cmnd_s cmnd_z0 = { 0 };
+	struct bfi_sge_s      *sge;
+	u32	pgdlen = 0;
+	u32	fcp_dl;
+	u64 addr;
+	struct scatterlist *sg;
+	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
+	if (!m) {
+		bfa_stats(ioim->itnim, qwait);
+		bfa_reqq_wait(ioim->bfa, ioim->reqq,
+				  &ioim->iosp->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	/**
+	 * build i/o request message next
+	 */
+	m->io_tag = bfa_os_htons(ioim->iotag);
+	m->rport_hdl = ioim->itnim->rport->fw_handle;
+	m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio);
+
+	/**
+	 * build inline IO SG element here
+	 */
+	sge = &m->sges[0];
+	if (ioim->nsges) {
+		sg = (struct scatterlist *)scsi_sglist(cmnd);
+		addr = bfa_os_sgaddr(sg_dma_address(sg));
+		sge->sga = *(union bfi_addr_u *) &addr;
+		pgdlen = sg_dma_len(sg);
+		sge->sg_len = pgdlen;
+		sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
+					BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
+		bfa_sge_to_be(sge);
+		sge++;
+	}
+
+	if (ioim->nsges > BFI_SGE_INLINE) {
+		sge->sga = ioim->sgpg->sgpg_pa;
+	} else {
+		sge->sga.a32.addr_lo = 0;
+		sge->sga.a32.addr_hi = 0;
+	}
+	sge->sg_len = pgdlen;
+	sge->flags = BFI_SGE_PGDLEN;
+	bfa_sge_to_be(sge);
+
+	/**
+	 * set up I/O command parameters
+	 */
+	bfa_os_assign(m->cmnd, cmnd_z0);
+	m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio);
+	m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio);
+	bfa_os_assign(m->cmnd.cdb,
+			*(scsi_cdb_t *)bfa_cb_ioim_get_cdb(ioim->dio));
+	fcp_dl = bfa_cb_ioim_get_size(ioim->dio);
+	m->cmnd.fcp_dl = bfa_os_htonl(fcp_dl);
+
+	/**
+	 * set up I/O message header
+	 */
+	switch (m->cmnd.iodir) {
+	case FCP_IODIR_READ:
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa));
+		bfa_stats(itnim, input_reqs);
+		ioim->itnim->stats.rd_throughput += fcp_dl;
+		break;
+	case FCP_IODIR_WRITE:
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa));
+		bfa_stats(itnim, output_reqs);
+		ioim->itnim->stats.wr_throughput += fcp_dl;
+		break;
+	case FCP_IODIR_RW:
+		bfa_stats(itnim, input_reqs);
+		bfa_stats(itnim, output_reqs);
+	default:
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+	}
+	if (itnim->seq_rec ||
+	    (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1)))
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+
+#ifdef IOIM_ADVANCED
+	m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio);
+	m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio);
+	m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio);
+
+	/**
+	 * Handle large CDB (>16 bytes).
+	 */
+	m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) -
+					FCP_CMND_CDB_LEN) / sizeof(u32);
+	if (m->cmnd.addl_cdb_len) {
+		bfa_os_memcpy(&m->cmnd.cdb + 1, (scsi_cdb_t *)
+				bfa_cb_ioim_get_cdb(ioim->dio) + 1,
+				m->cmnd.addl_cdb_len * sizeof(u32));
+		fcp_cmnd_fcpdl(&m->cmnd) =
+				bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
+	}
+#endif
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(ioim->bfa, ioim->reqq);
+	return BFA_TRUE;
+}
+
+/**
+ * Setup any additional SG pages needed.Inline SG element is setup
+ * at queuing time.
+ */
+static bfa_boolean_t
+bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)
+{
+	u16	nsgpgs;
+
+	bfa_assert(ioim->nsges > BFI_SGE_INLINE);
+
+	/**
+	 * allocate SG pages needed
+	 */
+	nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
+	if (!nsgpgs)
+		return BFA_TRUE;
+
+	if (bfa_sgpg_malloc(ioim->bfa, &ioim->sgpg_q, nsgpgs)
+	    != BFA_STATUS_OK) {
+		bfa_sgpg_wait(ioim->bfa, &ioim->iosp->sgpg_wqe, nsgpgs);
+		return BFA_FALSE;
+	}
+
+	ioim->nsgpgs = nsgpgs;
+	bfa_ioim_sgpg_setup(ioim);
+
+	return BFA_TRUE;
+}
+
+static void
+bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
+{
+	int		sgeid, nsges, i;
+	struct bfi_sge_s      *sge;
+	struct bfa_sgpg_s *sgpg;
+	u32	pgcumsz;
+	u64        addr;
+	struct scatterlist *sg;
+	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
+
+	sgeid = BFI_SGE_INLINE;
+	ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q);
+
+	sg = scsi_sglist(cmnd);
+	sg = sg_next(sg);
+
+	do {
+		sge = sgpg->sgpg->sges;
+		nsges = ioim->nsges - sgeid;
+		if (nsges > BFI_SGPG_DATA_SGES)
+			nsges = BFI_SGPG_DATA_SGES;
+
+		pgcumsz = 0;
+		for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) {
+			addr = bfa_os_sgaddr(sg_dma_address(sg));
+			sge->sga = *(union bfi_addr_u *) &addr;
+			sge->sg_len = sg_dma_len(sg);
+			pgcumsz += sge->sg_len;
+
+			/**
+			 * set flags
+			 */
+			if (i < (nsges - 1))
+				sge->flags = BFI_SGE_DATA;
+			else if (sgeid < (ioim->nsges - 1))
+				sge->flags = BFI_SGE_DATA_CPL;
+			else
+				sge->flags = BFI_SGE_DATA_LAST;
+
+			bfa_sge_to_le(sge);
+		}
+
+		sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
+
+		/**
+		 * set the link element of each page
+		 */
+		if (sgeid == ioim->nsges) {
+			sge->flags = BFI_SGE_PGDLEN;
+			sge->sga.a32.addr_lo = 0;
+			sge->sga.a32.addr_hi = 0;
+		} else {
+			sge->flags = BFI_SGE_LINK;
+			sge->sga = sgpg->sgpg_pa;
+		}
+		sge->sg_len = pgcumsz;
+
+		bfa_sge_to_le(sge);
+	} while (sgeid < ioim->nsges);
+}
+
+/**
+ * Send I/O abort request to firmware.
+ */
+static	bfa_boolean_t
+bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
+{
+	struct bfi_ioim_abort_req_s *m;
+	enum bfi_ioim_h2i	msgop;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
+	if (!m)
+		return BFA_FALSE;
+
+	/**
+	 * build i/o request message next
+	 */
+	if (ioim->iosp->abort_explicit)
+		msgop = BFI_IOIM_H2I_IOABORT_REQ;
+	else
+		msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
+
+	bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa));
+	m->io_tag    = bfa_os_htons(ioim->iotag);
+	m->abort_tag = ++ioim->abort_tag;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(ioim->bfa, ioim->reqq);
+	return BFA_TRUE;
+}
+
+/**
+ * Call to resume any I/O requests waiting for room in request queue.
+ */
+static void
+bfa_ioim_qresume(void *cbarg)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	bfa_stats(ioim->itnim, qresumes);
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_QRESUME);
+}
+
+
+static void
+bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)
+{
+	/**
+	 * Move IO from itnim queue to fcpim global queue since itnim will be
+	 * freed.
+	 */
+	list_del(&ioim->qe);
+	list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+
+	if (!ioim->iosp->tskim) {
+		if (ioim->fcpim->delay_comp && ioim->itnim->iotov_active) {
+			bfa_cb_dequeue(&ioim->hcb_qe);
+			list_del(&ioim->qe);
+			list_add_tail(&ioim->qe, &ioim->itnim->delay_comp_q);
+		}
+		bfa_itnim_iodone(ioim->itnim);
+	} else
+		bfa_tskim_iodone(ioim->iosp->tskim);
+}
+
+static bfa_boolean_t
+bfa_ioim_is_abortable(struct bfa_ioim_s *ioim)
+{
+	if ((bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit) &&
+	    (!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim)))	||
+	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_abort))		||
+	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_abort_qfull))	||
+	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_hcb))		||
+	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_hcb_free))	||
+	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_resfree)))
+		return BFA_FALSE;
+
+	return BFA_TRUE;
+}
+
+/**
+ *	or after the link comes back.
+ */
+void
+bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
+{
+	/**
+	 * If path tov timer expired, failback with PATHTOV status - these
+	 * IO requests are not normally retried by IO stack.
+	 *
+	 * Otherwise device cameback online and fail it with normal failed
+	 * status so that IO stack retries these failed IO requests.
+	 */
+	if (iotov)
+		ioim->io_cbfn = __bfa_cb_ioim_pathtov;
+	else {
+		ioim->io_cbfn = __bfa_cb_ioim_failed;
+		bfa_stats(ioim->itnim, iocom_nexus_abort);
+	}
+	bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+
+	/**
+	 * Move IO to fcpim global queue since itnim will be
+	 * freed.
+	 */
+	list_del(&ioim->qe);
+	list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+}
+
+
+
+/**
+ *  hal_ioim_friend
+ */
+
+/**
+ * Memory allocation and initialization.
+ */
+void
+bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+	struct bfa_ioim_s		*ioim;
+	struct bfa_ioim_sp_s	*iosp;
+	u16		i;
+	u8			*snsinfo;
+	u32		snsbufsz;
+
+	/**
+	 * claim memory first
+	 */
+	ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo);
+	fcpim->ioim_arr = ioim;
+	bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs);
+
+	iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo);
+	fcpim->ioim_sp_arr = iosp;
+	bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs);
+
+	/**
+	 * Claim DMA memory for per IO sense data.
+	 */
+	snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN;
+	fcpim->snsbase.pa  = bfa_meminfo_dma_phys(minfo);
+	bfa_meminfo_dma_phys(minfo) += snsbufsz;
+
+	fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo);
+	bfa_meminfo_dma_virt(minfo) += snsbufsz;
+	snsinfo = fcpim->snsbase.kva;
+	bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa);
+
+	/**
+	 * Initialize ioim free queues
+	 */
+	INIT_LIST_HEAD(&fcpim->ioim_free_q);
+	INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
+	INIT_LIST_HEAD(&fcpim->ioim_comp_q);
+
+	for (i = 0; i < fcpim->num_ioim_reqs;
+	     i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) {
+		/*
+		 * initialize IOIM
+		 */
+		bfa_os_memset(ioim, 0, sizeof(struct bfa_ioim_s));
+		ioim->iotag   = i;
+		ioim->bfa     = fcpim->bfa;
+		ioim->fcpim   = fcpim;
+		ioim->iosp    = iosp;
+		iosp->snsinfo = snsinfo;
+		INIT_LIST_HEAD(&ioim->sgpg_q);
+		bfa_reqq_winit(&ioim->iosp->reqq_wait,
+				   bfa_ioim_qresume, ioim);
+		bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
+				   bfa_ioim_sgpg_alloced, ioim);
+		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+
+		list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
+	}
+}
+
+/**
+ * Driver detach time call.
+ */
+void
+bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim)
+{
+}
+
+void
+bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
+	struct bfa_ioim_s *ioim;
+	u16	iotag;
+	enum bfa_ioim_event evt = BFA_IOIM_SM_COMP;
+
+	iotag = bfa_os_ntohs(rsp->io_tag);
+
+	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
+	bfa_assert(ioim->iotag == iotag);
+
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, rsp->io_status);
+	bfa_trc(ioim->bfa, rsp->reuse_io_tag);
+
+	if (bfa_sm_cmp_state(ioim, bfa_ioim_sm_active))
+		bfa_os_assign(ioim->iosp->comp_rspmsg, *m);
+
+	switch (rsp->io_status) {
+	case BFI_IOIM_STS_OK:
+		bfa_stats(ioim->itnim, iocomp_ok);
+		if (rsp->reuse_io_tag == 0)
+			evt = BFA_IOIM_SM_DONE;
+		else
+			evt = BFA_IOIM_SM_COMP;
+		break;
+
+	case BFI_IOIM_STS_TIMEDOUT:
+		bfa_stats(ioim->itnim, iocomp_timedout);
+	case BFI_IOIM_STS_ABORTED:
+		rsp->io_status = BFI_IOIM_STS_ABORTED;
+		bfa_stats(ioim->itnim, iocomp_aborted);
+		if (rsp->reuse_io_tag == 0)
+			evt = BFA_IOIM_SM_DONE;
+		else
+			evt = BFA_IOIM_SM_COMP;
+		break;
+
+	case BFI_IOIM_STS_PROTO_ERR:
+		bfa_stats(ioim->itnim, iocom_proto_err);
+		bfa_assert(rsp->reuse_io_tag);
+		evt = BFA_IOIM_SM_COMP;
+		break;
+
+	case BFI_IOIM_STS_SQER_NEEDED:
+		bfa_stats(ioim->itnim, iocom_sqer_needed);
+		bfa_assert(rsp->reuse_io_tag == 0);
+		evt = BFA_IOIM_SM_SQRETRY;
+		break;
+
+	case BFI_IOIM_STS_RES_FREE:
+		bfa_stats(ioim->itnim, iocom_res_free);
+		evt = BFA_IOIM_SM_FREE;
+		break;
+
+	case BFI_IOIM_STS_HOST_ABORTED:
+		bfa_stats(ioim->itnim, iocom_hostabrts);
+		if (rsp->abort_tag != ioim->abort_tag) {
+			bfa_trc(ioim->bfa, rsp->abort_tag);
+			bfa_trc(ioim->bfa, ioim->abort_tag);
+			return;
+		}
+
+		if (rsp->reuse_io_tag)
+			evt = BFA_IOIM_SM_ABORT_COMP;
+		else
+			evt = BFA_IOIM_SM_ABORT_DONE;
+		break;
+
+	case BFI_IOIM_STS_UTAG:
+		bfa_stats(ioim->itnim, iocom_utags);
+		evt = BFA_IOIM_SM_COMP_UTAG;
+		break;
+
+	default:
+		bfa_assert(0);
+	}
+
+	bfa_sm_send_event(ioim, evt);
+}
+
+void
+bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
+	struct bfa_ioim_s *ioim;
+	u16	iotag;
+
+	iotag = bfa_os_ntohs(rsp->io_tag);
+
+	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
+	bfa_assert(ioim->iotag == iotag);
+
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_ioim_cb_profile_comp(fcpim, ioim);
+
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
+}
+
+void
+bfa_ioim_profile_start(struct bfa_ioim_s *ioim)
+{
+	ioim->start_time = bfa_os_get_clock();
+}
+
+void
+bfa_ioim_profile_comp(struct bfa_ioim_s *ioim)
+{
+	u32 fcp_dl = bfa_cb_ioim_get_size(ioim->dio);
+	u32 index = bfa_ioim_get_index(fcp_dl);
+	u64 end_time = bfa_os_get_clock();
+	struct bfa_itnim_latency_s *io_lat =
+			&(ioim->itnim->ioprofile.io_latency);
+	u32 val = (u32)(end_time - ioim->start_time);
+
+	bfa_itnim_ioprofile_update(ioim->itnim, index);
+
+	io_lat->count[index]++;
+	io_lat->min[index] = (io_lat->min[index] < val) ?
+		io_lat->min[index] : val;
+	io_lat->max[index] = (io_lat->max[index] > val) ?
+		io_lat->max[index] : val;
+	io_lat->avg[index] += val;
+}
+/**
+ * Called by itnim to clean up IO while going offline.
+ */
+void
+bfa_ioim_cleanup(struct bfa_ioim_s *ioim)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_stats(ioim->itnim, io_cleanups);
+
+	ioim->iosp->tskim = NULL;
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
+}
+
+void
+bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, struct bfa_tskim_s *tskim)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_stats(ioim->itnim, io_tmaborts);
+
+	ioim->iosp->tskim = tskim;
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
+}
+
+/**
+ * IOC failure handling.
+ */
+void
+bfa_ioim_iocdisable(struct bfa_ioim_s *ioim)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_stats(ioim->itnim, io_iocdowns);
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_HWFAIL);
+}
+
+/**
+ * IO offline TOV popped. Fail the pending IO.
+ */
+void
+bfa_ioim_tov(struct bfa_ioim_s *ioim)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_IOTOV);
+}
+
+
+
+/**
+ *  hal_ioim_api
+ */
+
+/**
+ * Allocate IOIM resource for initiator mode I/O request.
+ */
+struct bfa_ioim_s *
+bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
+		struct bfa_itnim_s *itnim, u16 nsges)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_ioim_s *ioim;
+
+	/**
+	 * alocate IOIM resource
+	 */
+	bfa_q_deq(&fcpim->ioim_free_q, &ioim);
+	if (!ioim) {
+		bfa_stats(itnim, no_iotags);
+		return NULL;
+	}
+
+	ioim->dio = dio;
+	ioim->itnim = itnim;
+	ioim->nsges = nsges;
+	ioim->nsgpgs = 0;
+
+	bfa_stats(itnim, total_ios);
+	fcpim->ios_active++;
+
+	list_add_tail(&ioim->qe, &itnim->io_q);
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+
+	return ioim;
+}
+
+void
+bfa_ioim_free(struct bfa_ioim_s *ioim)
+{
+	struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
+
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit));
+
+	bfa_assert_fp(list_empty(&ioim->sgpg_q) ||
+			(ioim->nsges > BFI_SGE_INLINE));
+
+	if (ioim->nsgpgs > 0)
+		bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
+
+	bfa_stats(ioim->itnim, io_comps);
+	fcpim->ios_active--;
+
+	list_del(&ioim->qe);
+	list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
+}
+
+void
+bfa_ioim_start(struct bfa_ioim_s *ioim)
+{
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+
+	bfa_ioim_cb_profile_start(ioim->fcpim, ioim);
+
+	/**
+	 * Obtain the queue over which this request has to be issued
+	 */
+	ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ?
+			bfa_cb_ioim_get_reqq(ioim->dio) :
+			bfa_itnim_get_reqq(ioim);
+
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_START);
+}
+
+/**
+ * Driver I/O abort request.
+ */
+bfa_status_t
+bfa_ioim_abort(struct bfa_ioim_s *ioim)
+{
+
+	bfa_trc(ioim->bfa, ioim->iotag);
+
+	if (!bfa_ioim_is_abortable(ioim))
+		return BFA_STATUS_FAILED;
+
+	bfa_stats(ioim->itnim, io_aborts);
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_ABORT);
+
+	return BFA_STATUS_OK;
+}
+
+
+/**
+ *  BFA TSKIM state machine functions
+ */
+
+/**
+ *	Task management command beginning state.
+ */
+static void
+bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_START:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_active);
+		bfa_tskim_gather_ios(tskim);
+
+		/**
+		 * If device is offline, do not send TM on wire. Just cleanup
+		 * any pending IO requests and complete TM request.
+		 */
+		if (!bfa_itnim_is_online(tskim->itnim)) {
+			bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+			tskim->tsk_status = BFI_TSKIM_STS_OK;
+			bfa_tskim_cleanup_ios(tskim);
+			return;
+		}
+
+		if (!bfa_tskim_send(tskim)) {
+			bfa_sm_set_state(tskim, bfa_tskim_sm_qfull);
+			bfa_stats(tskim->itnim, tm_qwait);
+			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
+					  &tskim->reqq_wait);
+		}
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+/**
+ * brief
+ *	TM command is active, awaiting completion from firmware to
+ *	cleanup IO requests in TM scope.
+ */
+static void
+bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_DONE:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+		bfa_tskim_cleanup_ios(tskim);
+		break;
+
+	case BFA_TSKIM_SM_CLEANUP:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
+		if (!bfa_tskim_send_abort(tskim)) {
+			bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup_qfull);
+			bfa_stats(tskim->itnim, tm_qwait);
+			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
+				&tskim->reqq_wait);
+		}
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_tskim_iocdisable_ios(tskim);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+/**
+ *	An active TM is being cleaned up since ITN is offline. Awaiting cleanup
+ *	completion event from firmware.
+ */
+static void
+bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_DONE:
+		/**
+		 * Ignore and wait for ABORT completion from firmware.
+		 */
+		break;
+
+	case BFA_TSKIM_SM_CLEANUP_DONE:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+		bfa_tskim_cleanup_ios(tskim);
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_tskim_iocdisable_ios(tskim);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+static void
+bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_IOS_DONE:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_done);
+		break;
+
+	case BFA_TSKIM_SM_CLEANUP:
+		/**
+		 * Ignore, TM command completed on wire.
+		 * Notify TM conmpletion on IO cleanup completion.
+		 */
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_tskim_iocdisable_ios(tskim);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+/**
+ *	Task management command is waiting for room in request CQ
+ */
+static void
+bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_QRESUME:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_active);
+		bfa_tskim_send(tskim);
+		break;
+
+	case BFA_TSKIM_SM_CLEANUP:
+		/**
+		 * No need to send TM on wire since ITN is offline.
+		 */
+		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+		bfa_reqq_wcancel(&tskim->reqq_wait);
+		bfa_tskim_cleanup_ios(tskim);
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_reqq_wcancel(&tskim->reqq_wait);
+		bfa_tskim_iocdisable_ios(tskim);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+/**
+ *	Task management command is active, awaiting for room in request CQ
+ *	to send clean up request.
+ */
+static void
+bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
+		enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_DONE:
+		bfa_reqq_wcancel(&tskim->reqq_wait);
+		/**
+		 *
+		 * Fall through !!!
+		 */
+
+	case BFA_TSKIM_SM_QRESUME:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
+		bfa_tskim_send_abort(tskim);
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_reqq_wcancel(&tskim->reqq_wait);
+		bfa_tskim_iocdisable_ios(tskim);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+/**
+ *	BFA callback is pending
+ */
+static void
+bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_HCB:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
+		bfa_tskim_free(tskim);
+		break;
+
+	case BFA_TSKIM_SM_CLEANUP:
+		bfa_tskim_notify_comp(tskim);
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+
+
+/**
+ *  hal_tskim_private
+ */
+
+static void
+__bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_tskim_s *tskim = cbarg;
+
+	if (!complete) {
+		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
+		return;
+	}
+
+	bfa_stats(tskim->itnim, tm_success);
+	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, tskim->tsk_status);
+}
+
+static void
+__bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_tskim_s *tskim = cbarg;
+
+	if (!complete) {
+		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
+		return;
+	}
+
+	bfa_stats(tskim->itnim, tm_failures);
+	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk,
+				BFI_TSKIM_STS_FAILED);
+}
+
+static	bfa_boolean_t
+bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)
+{
+	switch (tskim->tm_cmnd) {
+	case FCP_TM_TARGET_RESET:
+		return BFA_TRUE;
+
+	case FCP_TM_ABORT_TASK_SET:
+	case FCP_TM_CLEAR_TASK_SET:
+	case FCP_TM_LUN_RESET:
+	case FCP_TM_CLEAR_ACA:
+		return (tskim->lun == lun);
+
+	default:
+		bfa_assert(0);
+	}
+
+	return BFA_FALSE;
+}
+
+/**
+ *	Gather affected IO requests and task management commands.
+ */
+static void
+bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
+{
+	struct bfa_itnim_s *itnim = tskim->itnim;
+	struct bfa_ioim_s *ioim;
+	struct list_head	*qe, *qen;
+
+	INIT_LIST_HEAD(&tskim->io_q);
+
+	/**
+	 * Gather any active IO requests first.
+	 */
+	list_for_each_safe(qe, qen, &itnim->io_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		if (bfa_tskim_match_scope
+			(tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+			list_del(&ioim->qe);
+			list_add_tail(&ioim->qe, &tskim->io_q);
+		}
+	}
+
+	/**
+	 * Failback any pending IO requests immediately.
+	 */
+	list_for_each_safe(qe, qen, &itnim->pending_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		if (bfa_tskim_match_scope
+			(tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+			list_del(&ioim->qe);
+			list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+			bfa_ioim_tov(ioim);
+		}
+	}
+}
+
+/**
+ *	IO cleanup completion
+ */
+static void
+bfa_tskim_cleanp_comp(void *tskim_cbarg)
+{
+	struct bfa_tskim_s *tskim = tskim_cbarg;
+
+	bfa_stats(tskim->itnim, tm_io_comps);
+	bfa_sm_send_event(tskim, BFA_TSKIM_SM_IOS_DONE);
+}
+
+/**
+ *	Gather affected IO requests and task management commands.
+ */
+static void
+bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
+{
+	struct bfa_ioim_s *ioim;
+	struct list_head	*qe, *qen;
+
+	bfa_wc_init(&tskim->wc, bfa_tskim_cleanp_comp, tskim);
+
+	list_for_each_safe(qe, qen, &tskim->io_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		bfa_wc_up(&tskim->wc);
+		bfa_ioim_cleanup_tm(ioim, tskim);
+	}
+
+	bfa_wc_wait(&tskim->wc);
+}
+
+/**
+ *	Send task management request to firmware.
+ */
+static bfa_boolean_t
+bfa_tskim_send(struct bfa_tskim_s *tskim)
+{
+	struct bfa_itnim_s *itnim = tskim->itnim;
+	struct bfi_tskim_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(tskim->bfa, itnim->reqq);
+	if (!m)
+		return BFA_FALSE;
+
+	/**
+	 * build i/o request message next
+	 */
+	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
+			bfa_lpuid(tskim->bfa));
+
+	m->tsk_tag = bfa_os_htons(tskim->tsk_tag);
+	m->itn_fhdl = tskim->itnim->rport->fw_handle;
+	m->t_secs = tskim->tsecs;
+	m->lun = tskim->lun;
+	m->tm_flags = tskim->tm_cmnd;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(tskim->bfa, itnim->reqq);
+	return BFA_TRUE;
+}
+
+/**
+ *	Send abort request to cleanup an active TM to firmware.
+ */
+static bfa_boolean_t
+bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
+{
+	struct bfa_itnim_s	*itnim = tskim->itnim;
+	struct bfi_tskim_abortreq_s	*m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(tskim->bfa, itnim->reqq);
+	if (!m)
+		return BFA_FALSE;
+
+	/**
+	 * build i/o request message next
+	 */
+	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
+			bfa_lpuid(tskim->bfa));
+
+	m->tsk_tag  = bfa_os_htons(tskim->tsk_tag);
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(tskim->bfa, itnim->reqq);
+	return BFA_TRUE;
+}
+
+/**
+ *	Call to resume task management cmnd waiting for room in request queue.
+ */
+static void
+bfa_tskim_qresume(void *cbarg)
+{
+	struct bfa_tskim_s *tskim = cbarg;
+
+	bfa_stats(tskim->itnim, tm_qresumes);
+	bfa_sm_send_event(tskim, BFA_TSKIM_SM_QRESUME);
+}
+
+/**
+ * Cleanup IOs associated with a task mangement command on IOC failures.
+ */
+static void
+bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)
+{
+	struct bfa_ioim_s *ioim;
+	struct list_head	*qe, *qen;
+
+	list_for_each_safe(qe, qen, &tskim->io_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		bfa_ioim_iocdisable(ioim);
+	}
+}
+
+
+
+/**
+ *  hal_tskim_friend
+ */
+
+/**
+ * Notification on completions from related ioim.
+ */
+void
+bfa_tskim_iodone(struct bfa_tskim_s *tskim)
+{
+	bfa_wc_down(&tskim->wc);
+}
+
+/**
+ * Handle IOC h/w failure notification from itnim.
+ */
+void
+bfa_tskim_iocdisable(struct bfa_tskim_s *tskim)
+{
+	tskim->notify = BFA_FALSE;
+	bfa_stats(tskim->itnim, tm_iocdowns);
+	bfa_sm_send_event(tskim, BFA_TSKIM_SM_HWFAIL);
+}
+
+/**
+ * Cleanup TM command and associated IOs as part of ITNIM offline.
+ */
+void
+bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
+{
+	tskim->notify = BFA_TRUE;
+	bfa_stats(tskim->itnim, tm_cleanups);
+	bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP);
+}
+
+/**
+ *	Memory allocation and initialization.
+ */
+void
+bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+	struct bfa_tskim_s *tskim;
+	u16	i;
+
+	INIT_LIST_HEAD(&fcpim->tskim_free_q);
+
+	tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo);
+	fcpim->tskim_arr = tskim;
+
+	for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
+		/*
+		 * initialize TSKIM
+		 */
+		bfa_os_memset(tskim, 0, sizeof(struct bfa_tskim_s));
+		tskim->tsk_tag = i;
+		tskim->bfa	= fcpim->bfa;
+		tskim->fcpim	= fcpim;
+		tskim->notify  = BFA_FALSE;
+		bfa_reqq_winit(&tskim->reqq_wait, bfa_tskim_qresume,
+					tskim);
+		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
+
+		list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
+	}
+
+	bfa_meminfo_kva(minfo) = (u8 *) tskim;
+}
+
+void
+bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim)
+{
+	/**
+	* @todo
+	*/
+}
+
+void
+bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
+	struct bfa_tskim_s *tskim;
+	u16	tsk_tag = bfa_os_ntohs(rsp->tsk_tag);
+
+	tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);
+	bfa_assert(tskim->tsk_tag == tsk_tag);
+
+	tskim->tsk_status = rsp->tsk_status;
+
+	/**
+	 * Firmware sends BFI_TSKIM_STS_ABORTED status for abort
+	 * requests. All other statuses are for normal completions.
+	 */
+	if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {
+		bfa_stats(tskim->itnim, tm_cleanup_comps);
+		bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);
+	} else {
+		bfa_stats(tskim->itnim, tm_fw_rsps);
+		bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);
+	}
+}
+
+
+
+/**
+ *  hal_tskim_api
+ */
+
+
+struct bfa_tskim_s *
+bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_tskim_s *tskim;
+
+	bfa_q_deq(&fcpim->tskim_free_q, &tskim);
+
+	if (tskim)
+		tskim->dtsk = dtsk;
+
+	return tskim;
+}
+
+void
+bfa_tskim_free(struct bfa_tskim_s *tskim)
+{
+	bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
+	list_del(&tskim->qe);
+	list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);
+}
+
+/**
+ *	Start a task management command.
+ *
+ * @param[in]	tskim	BFA task management command instance
+ * @param[in]	itnim	i-t nexus for the task management command
+ * @param[in]	lun	lun, if applicable
+ * @param[in]	tm_cmnd	Task management command code.
+ * @param[in]	t_secs	Timeout in seconds
+ *
+ * @return None.
+ */
+void
+bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun,
+			enum fcp_tm_cmnd tm_cmnd, u8 tsecs)
+{
+	tskim->itnim	= itnim;
+	tskim->lun	= lun;
+	tskim->tm_cmnd = tm_cmnd;
+	tskim->tsecs	= tsecs;
+	tskim->notify  = BFA_FALSE;
+	bfa_stats(itnim, tm_cmnds);
+
+	list_add_tail(&tskim->qe, &itnim->tsk_q);
+	bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
+}
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
new file mode 100644
index 0000000..3bf3431
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcpim.h
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCPIM_H__
+#define __BFA_FCPIM_H__
+
+#include "bfa.h"
+#include "bfa_svc.h"
+#include "bfi_ms.h"
+#include "bfa_defs_svc.h"
+#include "bfa_cs.h"
+
+
+#define BFA_ITNIM_MIN   32
+#define BFA_ITNIM_MAX   1024
+
+#define BFA_IOIM_MIN	8
+#define BFA_IOIM_MAX	2000
+
+#define BFA_TSKIM_MIN   4
+#define BFA_TSKIM_MAX   512
+#define BFA_FCPIM_PATHTOV_DEF	(30 * 1000)	/* in millisecs */
+#define BFA_FCPIM_PATHTOV_MAX	(90 * 1000)	/* in millisecs */
+
+
+#define bfa_itnim_ioprofile_update(__itnim, __index)			\
+	(__itnim->ioprofile.iocomps[__index]++)
+
+#define BFA_IOIM_RETRY_TAG_OFFSET 11
+#define BFA_IOIM_RETRY_TAG_MASK 0x07ff /* 2K IOs */
+#define BFA_IOIM_RETRY_MAX 7
+
+/* Buckets are are 512 bytes to 2MB */
+static inline u32
+bfa_ioim_get_index(u32 n) {
+	int pos = 0;
+	if (n >= (1UL)<<22)
+		return BFA_IOBUCKET_MAX - 1;
+	n >>= 8;
+	if (n >= (1UL)<<16)
+		n >>= 16; pos += 16;
+	if (n >= 1 << 8)
+		n >>= 8; pos += 8;
+	if (n >= 1 << 4)
+		n >>= 4; pos += 4;
+	if (n >= 1 << 2)
+		n >>= 2; pos += 2;
+	if (n >= 1 << 1)
+		pos += 1;
+
+	return (n == 0) ? (0) : pos;
+}
+
+/*
+ * forward declarations
+ */
+struct bfa_ioim_s;
+struct bfa_tskim_s;
+struct bfad_ioim_s;
+struct bfad_tskim_s;
+
+typedef void    (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim);
+
+struct bfa_fcpim_mod_s {
+	struct bfa_s		*bfa;
+	struct bfa_itnim_s	*itnim_arr;
+	struct bfa_ioim_s	*ioim_arr;
+	struct bfa_ioim_sp_s	*ioim_sp_arr;
+	struct bfa_tskim_s	*tskim_arr;
+	struct bfa_dma_s	snsbase;
+	int			num_itnims;
+	int			num_ioim_reqs;
+	int			num_tskim_reqs;
+	u32			path_tov;
+	u16			q_depth;
+	u8			reqq;		/*  Request queue to be used */
+	u8			rsvd;
+	struct list_head	itnim_q;	/*  queue of active itnim */
+	struct list_head	ioim_free_q;	/*  free IO resources	*/
+	struct list_head	ioim_resfree_q; /*  IOs waiting for f/w */
+	struct list_head	ioim_comp_q;	/*  IO global comp Q	*/
+	struct list_head	tskim_free_q;
+	u32		ios_active;	/*  current active IOs	*/
+	u32		delay_comp;
+	struct bfa_fcpim_del_itn_stats_s del_itn_stats;
+	bfa_boolean_t		ioredirect;
+	bfa_boolean_t		io_profile;
+	u32		io_profile_start_time;
+	bfa_fcpim_profile_t     profile_comp;
+	bfa_fcpim_profile_t     profile_start;
+};
+
+/**
+ * BFA IO (initiator mode)
+ */
+struct bfa_ioim_s {
+	struct list_head	qe;		/*  queue elememt	*/
+	bfa_sm_t		sm;		/*  BFA ioim state machine */
+	struct bfa_s		*bfa;		/*  BFA module	*/
+	struct bfa_fcpim_mod_s	*fcpim;		/*  parent fcpim module */
+	struct bfa_itnim_s	*itnim;		/*  i-t-n nexus for this IO  */
+	struct bfad_ioim_s	*dio;		/*  driver IO handle	*/
+	u16		iotag;		/*  FWI IO tag	*/
+	u16		abort_tag;	/*  unqiue abort request tag */
+	u16		nsges;		/*  number of SG elements */
+	u16		nsgpgs;		/*  number of SG pages	*/
+	struct bfa_sgpg_s	*sgpg;		/*  first SG page	*/
+	struct list_head	sgpg_q;		/*  allocated SG pages	*/
+	struct bfa_cb_qe_s	hcb_qe;		/*  bfa callback qelem	*/
+	bfa_cb_cbfn_t		io_cbfn;	/*  IO completion handler */
+	struct bfa_ioim_sp_s *iosp;		/*  slow-path IO handling */
+	u8		reqq;		/*  Request queue for I/O */
+	u64 start_time;			/*  IO's Profile start val */
+};
+
+
+struct bfa_ioim_sp_s {
+	struct bfi_msg_s	comp_rspmsg;	/*  IO comp f/w response */
+	u8			*snsinfo;	/*  sense info for this IO   */
+	struct bfa_sgpg_wqe_s sgpg_wqe;	/*  waitq elem for sgpg	*/
+	struct bfa_reqq_wait_s reqq_wait;	/*  to wait for room in reqq */
+	bfa_boolean_t		abort_explicit;	/*  aborted by OS	*/
+	struct bfa_tskim_s	*tskim;		/*  Relevant TM cmd	*/
+};
+
+/**
+ * BFA Task management command (initiator mode)
+ */
+struct bfa_tskim_s {
+	struct list_head	qe;
+	bfa_sm_t		sm;
+	struct bfa_s	*bfa;	/*  BFA module  */
+	struct bfa_fcpim_mod_s  *fcpim;	/*  parent fcpim module	*/
+	struct bfa_itnim_s	*itnim;	/*  i-t-n nexus for this IO  */
+	struct bfad_tskim_s	*dtsk;   /*  driver task mgmt cmnd	*/
+	bfa_boolean_t	notify;	/*  notify itnim on TM comp  */
+	lun_t	lun;	/*  lun if applicable	*/
+	enum fcp_tm_cmnd	tm_cmnd;	/*  task management command  */
+	u16	tsk_tag;	/*  FWI IO tag	*/
+	u8	tsecs;	/*  timeout in seconds	*/
+	struct bfa_reqq_wait_s  reqq_wait;   /*  to wait for room in reqq */
+	struct list_head	io_q;	/*  queue of affected IOs	*/
+	struct bfa_wc_s	wc;	/*  waiting counter	*/
+	struct bfa_cb_qe_s	hcb_qe;	/*  bfa callback qelem	*/
+	enum bfi_tskim_status   tsk_status;  /*  TM status	*/
+};
+
+
+/**
+ * BFA i-t-n (initiator mode)
+ */
+struct bfa_itnim_s {
+	struct list_head	qe;		/*  queue element	*/
+	bfa_sm_t	  sm;		/*  i-t-n im BFA state machine  */
+	struct bfa_s	*bfa;		/*  bfa instance	*/
+	struct bfa_rport_s *rport;	/*  bfa rport	*/
+	void	*ditn;		/*  driver i-t-n structure	*/
+	struct bfi_mhdr_s	mhdr;	/*  pre-built mhdr	*/
+	u8	msg_no;		/*  itnim/rport firmware handle */
+	u8	reqq;		/*  CQ for requests	*/
+	struct bfa_cb_qe_s	hcb_qe;	/*  bfa callback qelem	*/
+	struct list_head pending_q;	/*  queue of pending IO requests */
+	struct list_head io_q;		/*  queue of active IO requests */
+	struct list_head io_cleanup_q;	/*  IO being cleaned up	*/
+	struct list_head tsk_q;		/*  queue of active TM commands */
+	struct list_head  delay_comp_q; /*  queue of failed inflight cmds */
+	bfa_boolean_t   seq_rec;	/*  SQER supported	*/
+	bfa_boolean_t   is_online;	/*  itnim is ONLINE for IO	*/
+	bfa_boolean_t   iotov_active;	/*  IO TOV timer is active	 */
+	struct bfa_wc_s	wc;	/*  waiting counter	*/
+	struct bfa_timer_s timer;	/*  pending IO TOV		 */
+	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */
+	struct bfa_fcpim_mod_s *fcpim;	/*  fcpim module	*/
+	struct bfa_itnim_iostats_s	stats;
+	struct bfa_itnim_ioprofile_s  ioprofile;
+};
+
+
+#define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
+#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
+#define BFA_IOIM_FROM_TAG(_fcpim, _iotag)	\
+	(&fcpim->ioim_arr[(_iotag & BFA_IOIM_RETRY_TAG_MASK)])
+#define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag)	\
+	(&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
+
+#define bfa_io_profile_start_time(_bfa)	\
+	(_bfa->modules.fcpim_mod.io_profile_start_time)
+#define bfa_fcpim_get_io_profile(_bfa)	\
+	(_bfa->modules.fcpim_mod.io_profile)
+
+static inline bfa_boolean_t
+bfa_ioim_get_iotag(struct bfa_ioim_s *ioim)
+{
+	u16 k = ioim->iotag;
+
+	k >>= BFA_IOIM_RETRY_TAG_OFFSET; k++;
+
+	if (k > BFA_IOIM_RETRY_MAX)
+		return BFA_FALSE;
+	ioim->iotag &= BFA_IOIM_RETRY_TAG_MASK;
+	ioim->iotag |= k<<BFA_IOIM_RETRY_TAG_OFFSET;
+	return BFA_TRUE;
+}
+/*
+ * function prototypes
+ */
+void	bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
+					struct bfa_meminfo_s *minfo);
+void	bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim);
+void	bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void	bfa_ioim_good_comp_isr(struct bfa_s *bfa,
+					struct bfi_msg_s *msg);
+void	bfa_ioim_cleanup(struct bfa_ioim_s *ioim);
+void	bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
+					struct bfa_tskim_s *tskim);
+void	bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);
+void	bfa_ioim_tov(struct bfa_ioim_s *ioim);
+
+void	bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
+					struct bfa_meminfo_s *minfo);
+void	bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim);
+void	bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void	bfa_tskim_iodone(struct bfa_tskim_s *tskim);
+void	bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
+void	bfa_tskim_cleanup(struct bfa_tskim_s *tskim);
+
+void	bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+					u32 *dm_len);
+void	bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim,
+					struct bfa_meminfo_s *minfo);
+void	bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim);
+void	bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);
+void	bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void	bfa_itnim_iodone(struct bfa_itnim_s *itnim);
+void	bfa_itnim_tskdone(struct bfa_itnim_s *itnim);
+bfa_boolean_t   bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
+void bfa_ioim_profile_comp(struct bfa_ioim_s *ioim);
+void bfa_ioim_profile_start(struct bfa_ioim_s *ioim);
+
+
+/*
+ * bfa fcpim module API functions
+ */
+void		bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
+u16	bfa_fcpim_path_tov_get(struct bfa_s *bfa);
+void		bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth);
+u16	bfa_fcpim_qdepth_get(struct bfa_s *bfa);
+bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa,
+	 struct bfa_itnim_iostats_s *modstats);
+bfa_status_t bfa_fcpim_port_iostats(struct bfa_s *bfa,
+		struct bfa_itnim_iostats_s *stats, u8 lp_tag);
+bfa_status_t bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa,
+	 struct bfa_fcpim_del_itn_stats_s *modstats);
+bfa_status_t bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag);
+void bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *fcpim_stats,
+		struct bfa_itnim_iostats_s *itnim_stats);
+bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa);
+void		bfa_fcpim_set_ioredirect(struct bfa_s *bfa,
+				bfa_boolean_t state);
+void		bfa_fcpim_update_ioredirect(struct bfa_s *bfa);
+bfa_status_t bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time);
+bfa_status_t bfa_fcpim_profile_off(struct bfa_s *bfa);
+#define bfa_fcpim_ioredirect_enabled(__bfa)				\
+	(((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect)
+
+#define bfa_fcpim_get_next_reqq(__bfa, __qid)				\
+{									\
+	struct bfa_fcpim_mod_s *__fcpim = BFA_FCPIM_MOD(__bfa);      \
+	__fcpim->reqq++;						\
+	__fcpim->reqq &= (BFI_IOC_MAX_CQS - 1);      \
+	*(__qid) = __fcpim->reqq;					\
+}
+
+#define bfa_iocfc_map_msg_to_qid(__msg, __qid)				\
+	*(__qid) = (u8)((__msg) & (BFI_IOC_MAX_CQS - 1));
+/*
+ * bfa itnim API functions
+ */
+struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa,
+					struct bfa_rport_s *rport, void *itnim);
+void		bfa_itnim_delete(struct bfa_itnim_s *itnim);
+void		bfa_itnim_online(struct bfa_itnim_s *itnim,
+				 bfa_boolean_t seq_rec);
+void		bfa_itnim_offline(struct bfa_itnim_s *itnim);
+void		bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
+			struct bfa_itnim_iostats_s *stats);
+void		bfa_itnim_clear_stats(struct bfa_itnim_s *itnim);
+bfa_status_t	bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
+		struct bfa_itnim_ioprofile_s *ioprofile);
+#define bfa_itnim_get_reqq(__ioim) (((struct bfa_ioim_s *)__ioim)->itnim->reqq)
+
+/**
+ *	BFA completion callback for bfa_itnim_online().
+ *
+ * @param[in]		itnim		FCS or driver itnim instance
+ *
+ * return None
+ */
+void	bfa_cb_itnim_online(void *itnim);
+
+/**
+ *	BFA completion callback for bfa_itnim_offline().
+ *
+ * @param[in]		itnim		FCS or driver itnim instance
+ *
+ * return None
+ */
+void	bfa_cb_itnim_offline(void *itnim);
+void	bfa_cb_itnim_tov_begin(void *itnim);
+void	bfa_cb_itnim_tov(void *itnim);
+
+/**
+ *	BFA notification to FCS/driver for second level error recovery.
+ *
+ * Atleast one I/O request has timedout and target is unresponsive to
+ * repeated abort requests. Second level error recovery should be initiated
+ * by starting implicit logout and recovery procedures.
+ *
+ * @param[in]		itnim		FCS or driver itnim instance
+ *
+ * return None
+ */
+void	bfa_cb_itnim_sler(void *itnim);
+
+/*
+ * bfa ioim API functions
+ */
+struct bfa_ioim_s	*bfa_ioim_alloc(struct bfa_s *bfa,
+					struct bfad_ioim_s *dio,
+					struct bfa_itnim_s *itnim,
+					u16 nsgles);
+
+void		bfa_ioim_free(struct bfa_ioim_s *ioim);
+void		bfa_ioim_start(struct bfa_ioim_s *ioim);
+bfa_status_t	bfa_ioim_abort(struct bfa_ioim_s *ioim);
+void		bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,
+				      bfa_boolean_t iotov);
+
+
+/**
+ *	I/O completion notification.
+ *
+ * @param[in]		dio			driver IO structure
+ * @param[in]		io_status		IO completion status
+ * @param[in]		scsi_status		SCSI status returned by target
+ * @param[in]		sns_len			SCSI sense length, 0 if none
+ * @param[in]		sns_info		SCSI sense data, if any
+ * @param[in]		residue			Residual length
+ *
+ * @return None
+ */
+void	bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio,
+				  enum bfi_ioim_status io_status,
+				  u8 scsi_status, int sns_len,
+				  u8 *sns_info, s32 residue);
+
+/**
+ *	I/O good completion notification.
+ *
+ * @param[in]		dio			driver IO structure
+ *
+ * @return None
+ */
+void	bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
+
+/**
+ *	I/O abort completion notification
+ *
+ * @param[in]		dio			driver IO that was aborted
+ *
+ * @return None
+ */
+void	bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);
+
+/*
+ * bfa tskim API functions
+ */
+struct bfa_tskim_s	*bfa_tskim_alloc(struct bfa_s *bfa,
+					struct bfad_tskim_s *dtsk);
+void		bfa_tskim_free(struct bfa_tskim_s *tskim);
+void		bfa_tskim_start(struct bfa_tskim_s *tskim,
+				struct bfa_itnim_s *itnim, lun_t lun,
+				enum fcp_tm_cmnd tm, u8 t_secs);
+void		bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
+				  enum bfi_tskim_status tsk_status);
+
+#endif /* __BFA_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/bfa_fcpim_priv.h b/drivers/scsi/bfa/bfa_fcpim_priv.h
deleted file mode 100644
index 762516c..0000000
--- a/drivers/scsi/bfa/bfa_fcpim_priv.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCPIM_PRIV_H__
-#define __BFA_FCPIM_PRIV_H__
-
-#include <bfa_fcpim.h>
-#include <defs/bfa_defs_fcpim.h>
-#include <cs/bfa_wc.h>
-#include "bfa_sgpg_priv.h"
-
-#define BFA_ITNIM_MIN   32
-#define BFA_ITNIM_MAX   1024
-
-#define BFA_IOIM_MIN    8
-#define BFA_IOIM_MAX    2000
-
-#define BFA_TSKIM_MIN   4
-#define BFA_TSKIM_MAX   512
-#define BFA_FCPIM_PATHTOV_DEF	(30 * 1000)	/* in millisecs */
-#define BFA_FCPIM_PATHTOV_MAX	(90 * 1000)	/* in millisecs */
-
-#define bfa_fcpim_stats(__fcpim, __stats)   \
-    ((__fcpim)->stats.__stats++)
-
-struct bfa_fcpim_mod_s {
-	struct bfa_s 	*bfa;
-	struct bfa_itnim_s 	*itnim_arr;
-	struct bfa_ioim_s 	*ioim_arr;
-	struct bfa_ioim_sp_s *ioim_sp_arr;
-	struct bfa_tskim_s 	*tskim_arr;
-	struct bfa_dma_s	snsbase;
-	int			num_itnims;
-	int			num_ioim_reqs;
-	int			num_tskim_reqs;
-	u32		path_tov;
-	u16		q_depth;
-	u8              reqq;           /* Request queue to be used */
-	u8		rsvd;
-	struct list_head 	itnim_q;        /*  queue of active itnim    */
-	struct list_head 	ioim_free_q;    /*  free IO resources        */
-	struct list_head 	ioim_resfree_q; /*  IOs waiting for f/w      */
-	struct list_head 	ioim_comp_q;    /*  IO global comp Q         */
-	struct list_head 	tskim_free_q;
-	u32	ios_active;	/*  current active IOs	      */
-	u32	delay_comp;
-	struct bfa_fcpim_stats_s stats;
-	bfa_boolean_t           ioredirect;
-};
-
-struct bfa_ioim_s;
-struct bfa_tskim_s;
-
-/**
- * BFA IO (initiator mode)
- */
-struct bfa_ioim_s {
-	struct list_head qe;		/*  queue elememt            */
-	bfa_sm_t		sm; 	/*  BFA ioim state machine   */
-	struct bfa_s 	        *bfa;	/*  BFA module               */
-	struct bfa_fcpim_mod_s	*fcpim;	/*  parent fcpim module      */
-	struct bfa_itnim_s 	*itnim;	/*  i-t-n nexus for this IO  */
-	struct bfad_ioim_s 	*dio;	/*  driver IO handle         */
-	u16	iotag;		/*  FWI IO tag               */
-	u16	abort_tag;	/*  unqiue abort request tag */
-	u16	nsges;		/*  number of SG elements    */
-	u16	nsgpgs;		/*  number of SG pages       */
-	struct bfa_sgpg_s *sgpg;	/*  first SG page            */
-	struct list_head sgpg_q;		/*  allocated SG pages       */
-	struct bfa_cb_qe_s hcb_qe;	/*  bfa callback qelem       */
-	bfa_cb_cbfn_t io_cbfn;		/*  IO completion handler    */
-	struct bfa_ioim_sp_s *iosp;	/*  slow-path IO handling    */
-	u8 reqq;           		/* Request queue for I/O    */
-};
-
-struct bfa_ioim_sp_s {
-	struct bfi_msg_s 	comp_rspmsg;	/*  IO comp f/w response     */
-	u8			*snsinfo;	/*  sense info for this IO   */
-	struct bfa_sgpg_wqe_s sgpg_wqe;	/*  waitq elem for sgpg      */
-	struct bfa_reqq_wait_s reqq_wait;	/*  to wait for room in reqq */
-	bfa_boolean_t		abort_explicit;	/*  aborted by OS            */
-	struct bfa_tskim_s	*tskim;		/*  Relevant TM cmd          */
-};
-
-/**
- * BFA Task management command (initiator mode)
- */
-struct bfa_tskim_s {
-	struct list_head          qe;
-	bfa_sm_t		sm;
-	struct bfa_s            *bfa;        /*  BFA module  */
-	struct bfa_fcpim_mod_s  *fcpim;      /*  parent fcpim module      */
-	struct bfa_itnim_s      *itnim;      /*  i-t-n nexus for this IO  */
-	struct bfad_tskim_s         *dtsk;   /*  driver task mgmt cmnd    */
-	bfa_boolean_t        notify;         /*  notify itnim on TM comp  */
-	lun_t                lun;            /*  lun if applicable        */
-	enum fcp_tm_cmnd        tm_cmnd;     /*  task management command  */
-	u16             tsk_tag;        /*  FWI IO tag               */
-	u8              tsecs;          /*  timeout in seconds       */
-	struct bfa_reqq_wait_s  reqq_wait;   /*  to wait for room in reqq */
-	struct list_head              io_q;    /*  queue of affected IOs    */
-	struct bfa_wc_s             wc;      /*  waiting counter          */
-	struct bfa_cb_qe_s	hcb_qe;      /*  bfa callback qelem       */
-	enum bfi_tskim_status   tsk_status;  /*  TM status                */
-};
-
-/**
- * BFA i-t-n (initiator mode)
- */
-struct bfa_itnim_s {
-	struct list_head    qe;		/*  queue element               */
-	bfa_sm_t	  sm;		/*  i-t-n im BFA state machine  */
-	struct bfa_s      *bfa;		/*  bfa instance                */
-	struct bfa_rport_s *rport;	/*  bfa rport                   */
-	void           *ditn;		/*  driver i-t-n structure      */
-	struct bfi_mhdr_s      mhdr;	/*  pre-built mhdr              */
-	u8         msg_no;		/*  itnim/rport firmware handle */
-	u8         reqq;		/*  CQ for requests             */
-	struct bfa_cb_qe_s    hcb_qe;	/*  bfa callback qelem          */
-	struct list_head pending_q;	/*  queue of pending IO requests*/
-	struct list_head io_q;		/*  queue of active IO requests */
-	struct list_head io_cleanup_q;	/*  IO being cleaned up         */
-	struct list_head tsk_q;		/*  queue of active TM commands */
-	struct list_head  delay_comp_q;/*  queue of failed inflight cmds */
-	bfa_boolean_t   seq_rec;	/*  SQER supported              */
-	bfa_boolean_t   is_online;	/*  itnim is ONLINE for IO      */
-	bfa_boolean_t   iotov_active;	/*  IO TOV timer is active	 */
-	struct bfa_wc_s        wc;	/*  waiting counter             */
-	struct bfa_timer_s timer;	/*  pending IO TOV		 */
-	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */
-	struct bfa_fcpim_mod_s *fcpim;	/*  fcpim module                */
-	struct bfa_itnim_hal_stats_s	stats;
-	struct bfa_itnim_latency_s  io_latency;
-};
-
-#define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
-#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
-#define BFA_IOIM_FROM_TAG(_fcpim, _iotag)	\
-	(&fcpim->ioim_arr[_iotag])
-#define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag)                  \
-    (&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
-
-/*
- * function prototypes
- */
-void            bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
-				    struct bfa_meminfo_s *minfo);
-void            bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim);
-void            bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-void            bfa_ioim_good_comp_isr(struct bfa_s *bfa,
-					struct bfi_msg_s *msg);
-void            bfa_ioim_cleanup(struct bfa_ioim_s *ioim);
-void            bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
-					struct bfa_tskim_s *tskim);
-void            bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);
-void            bfa_ioim_tov(struct bfa_ioim_s *ioim);
-
-void            bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
-				     struct bfa_meminfo_s *minfo);
-void            bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim);
-void            bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-void            bfa_tskim_iodone(struct bfa_tskim_s *tskim);
-void            bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
-void            bfa_tskim_cleanup(struct bfa_tskim_s *tskim);
-
-void            bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-				      u32 *dm_len);
-void            bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim,
-				     struct bfa_meminfo_s *minfo);
-void            bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim);
-void            bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);
-void            bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-void            bfa_itnim_iodone(struct bfa_itnim_s *itnim);
-void            bfa_itnim_tskdone(struct bfa_itnim_s *itnim);
-bfa_boolean_t   bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
-
-#endif /* __BFA_FCPIM_PRIV_H__ */
-
diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c
deleted file mode 100644
index 76867b5..0000000
--- a/drivers/scsi/bfa/bfa_fcport.c
+++ /dev/null
@@ -1,1962 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_pport.h>
-#include <bfi/bfi_pbc.h>
-#include <cs/bfa_debug.h>
-#include <aen/bfa_aen.h>
-#include <cs/bfa_plog.h>
-#include <aen/bfa_aen_port.h>
-
-BFA_TRC_FILE(HAL, FCPORT);
-BFA_MODULE(fcport);
-
-/*
- * The port is considered disabled if corresponding physical port or IOC are
- * disabled explicitly
- */
-#define BFA_PORT_IS_DISABLED(bfa) \
-	((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
-	(bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
-
-/*
- * forward declarations
- */
-static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
-static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
-static void     bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
-static void     bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
-static void     bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
-static void     __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
-static void     bfa_fcport_callback(struct bfa_fcport_s *fcport,
-				enum bfa_pport_linkstate event);
-static void     bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
-				enum bfa_pport_linkstate event);
-static void     __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
-static void     bfa_fcport_stats_get_timeout(void *cbarg);
-static void     bfa_fcport_stats_clr_timeout(void *cbarg);
-
-/**
- *  bfa_pport_private
- */
-
-/**
- * BFA port state machine events
- */
-enum bfa_fcport_sm_event {
-	BFA_FCPORT_SM_START = 1,	/*  start port state machine */
-	BFA_FCPORT_SM_STOP = 2,	/*  stop port state machine */
-	BFA_FCPORT_SM_ENABLE = 3,	/*  enable port */
-	BFA_FCPORT_SM_DISABLE = 4,	/*  disable port state machine */
-	BFA_FCPORT_SM_FWRSP = 5,	/*  firmware enable/disable rsp */
-	BFA_FCPORT_SM_LINKUP = 6,	/*  firmware linkup event */
-	BFA_FCPORT_SM_LINKDOWN = 7,	/*  firmware linkup down */
-	BFA_FCPORT_SM_QRESUME = 8,	/*  CQ space available */
-	BFA_FCPORT_SM_HWFAIL = 9,	/*  IOC h/w failure */
-};
-
-/**
- * BFA port link notification state machine events
- */
-
-enum bfa_fcport_ln_sm_event {
-	BFA_FCPORT_LN_SM_LINKUP         = 1,    /*  linkup event */
-	BFA_FCPORT_LN_SM_LINKDOWN       = 2,    /*  linkdown event */
-	BFA_FCPORT_LN_SM_NOTIFICATION   = 3     /*  done notification */
-};
-
-static void     bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
-					enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
-					 enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
-					 enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
-					 enum bfa_fcport_sm_event event);
-
-static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-
-static struct bfa_sm_table_s hal_pport_sm_table[] = {
-	{BFA_SM(bfa_fcport_sm_uninit), BFA_PPORT_ST_UNINIT},
-	{BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PPORT_ST_ENABLING_QWAIT},
-	{BFA_SM(bfa_fcport_sm_enabling), BFA_PPORT_ST_ENABLING},
-	{BFA_SM(bfa_fcport_sm_linkdown), BFA_PPORT_ST_LINKDOWN},
-	{BFA_SM(bfa_fcport_sm_linkup), BFA_PPORT_ST_LINKUP},
-	{BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PPORT_ST_DISABLING_QWAIT},
-	{BFA_SM(bfa_fcport_sm_disabling), BFA_PPORT_ST_DISABLING},
-	{BFA_SM(bfa_fcport_sm_disabled), BFA_PPORT_ST_DISABLED},
-	{BFA_SM(bfa_fcport_sm_stopped), BFA_PPORT_ST_STOPPED},
-	{BFA_SM(bfa_fcport_sm_iocdown), BFA_PPORT_ST_IOCDOWN},
-	{BFA_SM(bfa_fcport_sm_iocfail), BFA_PPORT_ST_IOCDOWN},
-};
-
-static void
-bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = fcport->bfa->logm;
-	wwn_t           pwwn = fcport->pwwn;
-	char            pwwn_ptr[BFA_STRING_32];
-
-	memset(&aen_data, 0, sizeof(aen_data));
-	wwn2str(pwwn_ptr, pwwn);
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, event), pwwn_ptr);
-
-	aen_data.port.ioc_type = bfa_get_type(fcport->bfa);
-	aen_data.port.pwwn = pwwn;
-}
-
-static void
-bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_START:
-		/**
-		 * Start event after IOC is configured and BFA is started.
-		 */
-		if (bfa_fcport_send_enable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		/**
-		 * Port is persistently configured to be in enabled state. Do
-		 * not change state. Port enabling is done when START event is
-		 * received.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		/**
-		 * If a port is persistently configured to be disabled, the
-		 * first event will a port disable request.
-		 */
-		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
-			    enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_QRESUME:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		bfa_fcport_send_enable(fcport);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_reqq_wcancel(&fcport->reqq_wait);
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		/**
-		 * Already enable is in progress.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		/**
-		 * Just send disable request to firmware when room becomes
-		 * available in request queue.
-		 */
-		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
-		bfa_reqq_wcancel(&fcport->reqq_wait);
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
-		break;
-
-	case BFA_FCPORT_SM_LINKUP:
-	case BFA_FCPORT_SM_LINKDOWN:
-		/**
-		 * Possible to get link events when doing back-to-back
-		 * enable/disables.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_reqq_wcancel(&fcport->reqq_wait);
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
-		enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_FWRSP:
-	case BFA_FCPORT_SM_LINKDOWN:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
-		break;
-
-	case BFA_FCPORT_SM_LINKUP:
-		bfa_fcport_update_linkinfo(fcport);
-		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
-
-		bfa_assert(fcport->event_cbfn);
-		bfa_fcport_callback(fcport, BFA_PPORT_LINKUP);
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		/**
-		 * Already being enabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		if (bfa_fcport_send_disable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
-
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_LINKUP:
-		bfa_fcport_update_linkinfo(fcport);
-		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
-		bfa_assert(fcport->event_cbfn);
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
-
-		if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
-
-			bfa_trc(fcport->bfa,
-				pevent->link_state.vc_fcf.fcf.fipenabled);
-			bfa_trc(fcport->bfa,
-				pevent->link_state.vc_fcf.fcf.fipfailed);
-
-			if (pevent->link_state.vc_fcf.fcf.fipfailed)
-				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-					BFA_PL_EID_FIP_FCF_DISC, 0,
-					"FIP FCF Discovery Failed");
-			else
-				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-					BFA_PL_EID_FIP_FCF_DISC, 0,
-					"FIP FCF Discovered");
-		}
-
-		bfa_fcport_callback(fcport, BFA_PPORT_LINKUP);
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE);
-		/**
-		 * If QoS is enabled and it is not online,
-		 * Send a separate event.
-		 */
-		if ((fcport->cfg.qos_enabled)
-		    && (bfa_os_ntohl(fcport->qos_attr.state) != BFA_QOS_ONLINE))
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);
-
-		break;
-
-	case BFA_FCPORT_SM_LINKDOWN:
-		/**
-		 * Possible to get link down event.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		/**
-		 * Already enabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		if (bfa_fcport_send_disable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
-
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_ENABLE:
-		/**
-		 * Already enabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		if (bfa_fcport_send_disable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
-
-		bfa_fcport_reset_linkinfo(fcport);
-		bfa_fcport_callback(fcport, BFA_PPORT_LINKDOWN);
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
-		break;
-
-	case BFA_FCPORT_SM_LINKDOWN:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
-		bfa_fcport_reset_linkinfo(fcport);
-		bfa_fcport_callback(fcport, BFA_PPORT_LINKDOWN);
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
-		if (BFA_PORT_IS_DISABLED(fcport->bfa))
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
-		else
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		bfa_fcport_reset_linkinfo(fcport);
-		if (BFA_PORT_IS_DISABLED(fcport->bfa))
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
-		else
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		bfa_fcport_reset_linkinfo(fcport);
-		bfa_fcport_callback(fcport, BFA_PPORT_LINKDOWN);
-		if (BFA_PORT_IS_DISABLED(fcport->bfa))
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
-		else
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
-			     enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_QRESUME:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
-		bfa_fcport_send_disable(fcport);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		bfa_reqq_wcancel(&fcport->reqq_wait);
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		/**
-		 * Already being disabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_LINKUP:
-	case BFA_FCPORT_SM_LINKDOWN:
-		/**
-		 * Possible to get link events when doing back-to-back
-		 * enable/disables.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
-		bfa_reqq_wcancel(&fcport->reqq_wait);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_FWRSP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		/**
-		 * Already being disabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		if (bfa_fcport_send_enable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		break;
-
-	case BFA_FCPORT_SM_LINKUP:
-	case BFA_FCPORT_SM_LINKDOWN:
-		/**
-		 * Possible to get link events when doing back-to-back
-		 * enable/disables.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_START:
-		/**
-		 * Ignore start event for a port that is disabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		if (bfa_fcport_send_enable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		/**
-		 * Already disabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_START:
-		if (bfa_fcport_send_enable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-		break;
-
-	default:
-		/**
-		 * Ignore all other events.
-		 */
-		;
-	}
-}
-
-/**
- * Port is enabled. IOC is down/failed.
- */
-static void
-bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_START:
-		if (bfa_fcport_send_enable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-		break;
-
-	default:
-		/**
-		 * Ignore all events.
-		 */
-		;
-	}
-}
-
-/**
- * Port is disabled. IOC is down/failed.
- */
-static void
-bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_START:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		break;
-
-	default:
-		/**
-		 * Ignore all events.
-		 */
-		;
-	}
-}
-
-/**
- * Link state is down
- */
-static void
-bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKUP:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
-		bfa_fcport_queue_cb(ln, BFA_PPORT_LINKUP);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is waiting for down notification
- */
-static void
-bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKUP:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
-		break;
-
-	case BFA_FCPORT_LN_SM_NOTIFICATION:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is waiting for down notification and there is a pending up
- */
-static void
-bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKDOWN:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
-		break;
-
-	case BFA_FCPORT_LN_SM_NOTIFICATION:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
-		bfa_fcport_queue_cb(ln, BFA_PPORT_LINKUP);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is up
- */
-static void
-bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKDOWN:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
-		bfa_fcport_queue_cb(ln, BFA_PPORT_LINKDOWN);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is waiting for up notification
- */
-static void
-bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKDOWN:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
-		break;
-
-	case BFA_FCPORT_LN_SM_NOTIFICATION:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is waiting for up notification and there is a pending down
- */
-static void
-bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKUP:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
-		break;
-
-	case BFA_FCPORT_LN_SM_NOTIFICATION:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
-		bfa_fcport_queue_cb(ln, BFA_PPORT_LINKDOWN);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is waiting for up notification and there are pending down and up
- */
-static void
-bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
-			enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKDOWN:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
-		break;
-
-	case BFA_FCPORT_LN_SM_NOTIFICATION:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
-		bfa_fcport_queue_cb(ln, BFA_PPORT_LINKDOWN);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- *  bfa_pport_private
- */
-
-static void
-__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_fcport_ln_s *ln = cbarg;
-
-	if (complete)
-		ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
-	else
-		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
-}
-
-static void
-bfa_fcport_callback(struct bfa_fcport_s *fcport, enum bfa_pport_linkstate event)
-{
-	if (fcport->bfa->fcs) {
-		fcport->event_cbfn(fcport->event_cbarg, event);
-		return;
-	}
-
-	switch (event) {
-	case BFA_PPORT_LINKUP:
-		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
-		break;
-	case BFA_PPORT_LINKDOWN:
-		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
-		break;
-	default:
-		bfa_assert(0);
-	}
-}
-
-static void
-bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_pport_linkstate event)
-{
-	ln->ln_event = event;
-	bfa_cb_queue(ln->fcport->bfa, &ln->ln_qe, __bfa_cb_fcport_event, ln);
-}
-
-#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
-							BFA_CACHELINE_SZ))
-
-static void
-bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
-		  u32 *dm_len)
-{
-	*dm_len += FCPORT_STATS_DMA_SZ;
-}
-
-static void
-bfa_fcport_qresume(void *cbarg)
-{
-	struct bfa_fcport_s *fcport = cbarg;
-
-	bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
-}
-
-static void
-bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
-{
-	u8        *dm_kva;
-	u64        dm_pa;
-
-	dm_kva = bfa_meminfo_dma_virt(meminfo);
-	dm_pa = bfa_meminfo_dma_phys(meminfo);
-
-	fcport->stats_kva = dm_kva;
-	fcport->stats_pa = dm_pa;
-	fcport->stats = (union bfa_fcport_stats_u *)dm_kva;
-
-	dm_kva += FCPORT_STATS_DMA_SZ;
-	dm_pa += FCPORT_STATS_DMA_SZ;
-
-	bfa_meminfo_dma_virt(meminfo) = dm_kva;
-	bfa_meminfo_dma_phys(meminfo) = dm_pa;
-}
-
-/**
- * Memory initialization.
- */
-static void
-bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_pport_cfg_s *port_cfg = &fcport->cfg;
-	struct bfa_fcport_ln_s *ln = &fcport->ln;
-	struct bfa_timeval_s tv;
-
-	bfa_os_memset(fcport, 0, sizeof(struct bfa_fcport_s));
-	fcport->bfa = bfa;
-	ln->fcport = fcport;
-
-	bfa_fcport_mem_claim(fcport, meminfo);
-
-	bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
-	bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
-
-	/**
-	 * initialize time stamp for stats reset
-	 */
-	bfa_os_gettimeofday(&tv);
-	fcport->stats_reset_time = tv.tv_sec;
-
-	/**
-	 * initialize and set default configuration
-	 */
-	port_cfg->topology = BFA_PPORT_TOPOLOGY_P2P;
-	port_cfg->speed = BFA_PPORT_SPEED_AUTO;
-	port_cfg->trunked = BFA_FALSE;
-	port_cfg->maxfrsize = 0;
-
-	port_cfg->trl_def_speed = BFA_PPORT_SPEED_1GBPS;
-
-	bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
-}
-
-static void
-bfa_fcport_detach(struct bfa_s *bfa)
-{
-}
-
-/**
- * Called when IOC is ready.
- */
-static void
-bfa_fcport_start(struct bfa_s *bfa)
-{
-	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
-}
-
-/**
- * Called before IOC is stopped.
- */
-static void
-bfa_fcport_stop(struct bfa_s *bfa)
-{
-	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_STOP);
-}
-
-/**
- * Called when IOC failure is detected.
- */
-static void
-bfa_fcport_iocdisable(struct bfa_s *bfa)
-{
-	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_HWFAIL);
-}
-
-static void
-bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
-{
-	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
-
-	fcport->speed = pevent->link_state.speed;
-	fcport->topology = pevent->link_state.topology;
-
-	if (fcport->topology == BFA_PPORT_TOPOLOGY_LOOP)
-		fcport->myalpa = 0;
-
-	/*
-	 * QoS Details
-	 */
-	bfa_os_assign(fcport->qos_attr, pevent->link_state.qos_attr);
-	bfa_os_assign(fcport->qos_vc_attr,
-		pevent->link_state.vc_fcf.qos_vc_attr);
-
-
-	bfa_trc(fcport->bfa, fcport->speed);
-	bfa_trc(fcport->bfa, fcport->topology);
-}
-
-static void
-bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
-{
-	fcport->speed = BFA_PPORT_SPEED_UNKNOWN;
-	fcport->topology = BFA_PPORT_TOPOLOGY_NONE;
-}
-
-/**
- * Send port enable message to firmware.
- */
-static          bfa_boolean_t
-bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
-{
-	struct bfi_fcport_enable_req_s *m;
-
-	/**
-	 * Increment message tag before queue check, so that responses to old
-	 * requests are discarded.
-	 */
-	fcport->msgtag++;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-	if (!m) {
-		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
-							&fcport->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
-				bfa_lpuid(fcport->bfa));
-	m->nwwn = fcport->nwwn;
-	m->pwwn = fcport->pwwn;
-	m->port_cfg = fcport->cfg;
-	m->msgtag = fcport->msgtag;
-	m->port_cfg.maxfrsize = bfa_os_htons(fcport->cfg.maxfrsize);
-	bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
-	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
-	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-	return BFA_TRUE;
-}
-
-/**
- * Send port disable message to firmware.
- */
-static          bfa_boolean_t
-bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
-{
-	struct bfi_fcport_req_s *m;
-
-	/**
-	 * Increment message tag before queue check, so that responses to old
-	 * requests are discarded.
-	 */
-	fcport->msgtag++;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-	if (!m) {
-		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
-							&fcport->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
-			bfa_lpuid(fcport->bfa));
-	m->msgtag = fcport->msgtag;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-
-	return BFA_TRUE;
-}
-
-static void
-bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
-{
-	fcport->pwwn = bfa_ioc_get_pwwn(&fcport->bfa->ioc);
-	fcport->nwwn = bfa_ioc_get_nwwn(&fcport->bfa->ioc);
-
-	bfa_trc(fcport->bfa, fcport->pwwn);
-	bfa_trc(fcport->bfa, fcport->nwwn);
-}
-
-static void
-bfa_fcport_send_txcredit(void *port_cbarg)
-{
-
-	struct bfa_fcport_s *fcport = port_cbarg;
-	struct bfi_fcport_set_svc_params_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-	if (!m) {
-		bfa_trc(fcport->bfa, fcport->cfg.tx_bbcredit);
-		return;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ,
-			bfa_lpuid(fcport->bfa));
-	m->tx_bbcredit = bfa_os_htons((u16) fcport->cfg.tx_bbcredit);
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-}
-
-static void
-bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
-	struct bfa_qos_stats_s *s)
-{
-	u32     *dip = (u32 *) d;
-	u32     *sip = (u32 *) s;
-	int             i;
-
-	/* Now swap the 32 bit fields */
-	for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
-		dip[i] = bfa_os_ntohl(sip[i]);
-}
-
-static void
-bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
-	struct bfa_fcoe_stats_s *s)
-{
-	u32     *dip = (u32 *) d;
-	u32     *sip = (u32 *) s;
-	int             i;
-
-	for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
-		i = i + 2) {
-#ifdef __BIGENDIAN
-		dip[i] = bfa_os_ntohl(sip[i]);
-		dip[i + 1] = bfa_os_ntohl(sip[i + 1]);
-#else
-		dip[i] = bfa_os_ntohl(sip[i + 1]);
-		dip[i + 1] = bfa_os_ntohl(sip[i]);
-#endif
-	}
-}
-
-static void
-__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_fcport_s *fcport = cbarg;
-
-	if (complete) {
-		if (fcport->stats_status == BFA_STATUS_OK) {
-			struct bfa_timeval_s tv;
-
-			/* Swap FC QoS or FCoE stats */
-			if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
-				bfa_fcport_qos_stats_swap(
-					&fcport->stats_ret->fcqos,
-					&fcport->stats->fcqos);
-			} else {
-				bfa_fcport_fcoe_stats_swap(
-					&fcport->stats_ret->fcoe,
-					&fcport->stats->fcoe);
-
-				bfa_os_gettimeofday(&tv);
-				fcport->stats_ret->fcoe.secs_reset =
-					tv.tv_sec - fcport->stats_reset_time;
-			}
-		}
-		fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
-	} else {
-		fcport->stats_busy = BFA_FALSE;
-		fcport->stats_status = BFA_STATUS_OK;
-	}
-}
-
-static void
-bfa_fcport_stats_get_timeout(void *cbarg)
-{
-	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
-
-	bfa_trc(fcport->bfa, fcport->stats_qfull);
-
-	if (fcport->stats_qfull) {
-		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
-		fcport->stats_qfull = BFA_FALSE;
-	}
-
-	fcport->stats_status = BFA_STATUS_ETIMER;
-	bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get,
-		fcport);
-}
-
-static void
-bfa_fcport_send_stats_get(void *cbarg)
-{
-	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
-	struct bfi_fcport_req_s *msg;
-
-	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-
-	if (!msg) {
-		fcport->stats_qfull = BFA_TRUE;
-		bfa_reqq_winit(&fcport->stats_reqq_wait,
-				bfa_fcport_send_stats_get, fcport);
-		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
-				&fcport->stats_reqq_wait);
-		return;
-	}
-	fcport->stats_qfull = BFA_FALSE;
-
-	bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
-	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
-		bfa_lpuid(fcport->bfa));
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-}
-
-static void
-__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_fcport_s *fcport = cbarg;
-
-	if (complete) {
-		struct bfa_timeval_s tv;
-
-		/**
-		 * re-initialize time stamp for stats reset
-		 */
-		bfa_os_gettimeofday(&tv);
-		fcport->stats_reset_time = tv.tv_sec;
-
-		fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
-	} else {
-		fcport->stats_busy = BFA_FALSE;
-		fcport->stats_status = BFA_STATUS_OK;
-	}
-}
-
-static void
-bfa_fcport_stats_clr_timeout(void *cbarg)
-{
-	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
-
-	bfa_trc(fcport->bfa, fcport->stats_qfull);
-
-	if (fcport->stats_qfull) {
-		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
-		fcport->stats_qfull = BFA_FALSE;
-	}
-
-	fcport->stats_status = BFA_STATUS_ETIMER;
-	bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
-			__bfa_cb_fcport_stats_clr, fcport);
-}
-
-static void
-bfa_fcport_send_stats_clear(void *cbarg)
-{
-	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
-	struct bfi_fcport_req_s *msg;
-
-	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-
-	if (!msg) {
-		fcport->stats_qfull = BFA_TRUE;
-		bfa_reqq_winit(&fcport->stats_reqq_wait,
-				bfa_fcport_send_stats_clear, fcport);
-		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
-				&fcport->stats_reqq_wait);
-		return;
-	}
-	fcport->stats_qfull = BFA_FALSE;
-
-	bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
-	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
-			bfa_lpuid(fcport->bfa));
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-}
-
-/**
- *  bfa_pport_public
- */
-
-/**
- * Called to initialize port attributes
- */
-void
-bfa_fcport_init(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	/**
-	 * Initialize port attributes from IOC hardware data.
-	 */
-	bfa_fcport_set_wwns(fcport);
-	if (fcport->cfg.maxfrsize == 0)
-		fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
-	fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
-	fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
-
-	bfa_assert(fcport->cfg.maxfrsize);
-	bfa_assert(fcport->cfg.rx_bbcredit);
-	bfa_assert(fcport->speed_sup);
-}
-
-
-/**
- * Firmware message handler.
- */
-void
-bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	union bfi_fcport_i2h_msg_u i2hmsg;
-
-	i2hmsg.msg = msg;
-	fcport->event_arg.i2hmsg = i2hmsg;
-
-	switch (msg->mhdr.msg_id) {
-	case BFI_FCPORT_I2H_ENABLE_RSP:
-		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
-			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
-		break;
-
-	case BFI_FCPORT_I2H_DISABLE_RSP:
-		if (fcport->msgtag == i2hmsg.pdisable_rsp->msgtag)
-			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
-		break;
-
-	case BFI_FCPORT_I2H_EVENT:
-		switch (i2hmsg.event->link_state.linkstate) {
-		case BFA_PPORT_LINKUP:
-			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
-			break;
-		case BFA_PPORT_LINKDOWN:
-			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKDOWN);
-			break;
-		case BFA_PPORT_TRUNK_LINKDOWN:
-			/** todo: event notification */
-			break;
-		}
-		break;
-
-	case BFI_FCPORT_I2H_STATS_GET_RSP:
-		/*
-		 * check for timer pop before processing the rsp
-		 */
-		if (fcport->stats_busy == BFA_FALSE ||
-			fcport->stats_status == BFA_STATUS_ETIMER)
-			break;
-
-		bfa_timer_stop(&fcport->timer);
-		fcport->stats_status = i2hmsg.pstatsget_rsp->status;
-		bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
-				__bfa_cb_fcport_stats_get, fcport);
-		break;
-
-	case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
-		/*
-		 * check for timer pop before processing the rsp
-		 */
-		if (fcport->stats_busy == BFA_FALSE ||
-			fcport->stats_status == BFA_STATUS_ETIMER)
-			break;
-
-		bfa_timer_stop(&fcport->timer);
-		fcport->stats_status = BFA_STATUS_OK;
-		bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
-				__bfa_cb_fcport_stats_clr, fcport);
-		break;
-
-	default:
-		bfa_assert(0);
-	break;
-	}
-}
-
-/**
- *  bfa_pport_api
- */
-
-/**
- * Registered callback for port events.
- */
-void
-bfa_fcport_event_register(struct bfa_s *bfa,
-			 void (*cbfn) (void *cbarg, bfa_pport_event_t event),
-			 void *cbarg)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	fcport->event_cbfn = cbfn;
-	fcport->event_cbarg = cbarg;
-}
-
-bfa_status_t
-bfa_fcport_enable(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
-	/* if port is PBC disabled, return error */
-	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
-		bfa_trc(bfa, fcport->pwwn);
-		return BFA_STATUS_PBC;
-	}
-
-	if (bfa_ioc_is_disabled(&bfa->ioc))
-		return BFA_STATUS_IOC_DISABLED;
-
-	if (fcport->diag_busy)
-		return BFA_STATUS_DIAG_BUSY;
-	else if (bfa_sm_cmp_state
-		 (BFA_FCPORT_MOD(bfa), bfa_fcport_sm_disabling_qwait))
-		return BFA_STATUS_DEVBUSY;
-
-	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
-	return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcport_disable(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
-	/* if port is PBC disabled, return error */
-	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
-		bfa_trc(bfa, fcport->pwwn);
-		return BFA_STATUS_PBC;
-	}
-
-	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
-	return BFA_STATUS_OK;
-}
-
-/**
- * Configure port speed.
- */
-bfa_status_t
-bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, speed);
-
-	if ((speed != BFA_PPORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
-		bfa_trc(bfa, fcport->speed_sup);
-		return BFA_STATUS_UNSUPP_SPEED;
-	}
-
-	fcport->cfg.speed = speed;
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * Get current speed.
- */
-enum bfa_pport_speed
-bfa_fcport_get_speed(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->speed;
-}
-
-/**
- * Configure port topology.
- */
-bfa_status_t
-bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_pport_topology topology)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, topology);
-	bfa_trc(bfa, fcport->cfg.topology);
-
-	switch (topology) {
-	case BFA_PPORT_TOPOLOGY_P2P:
-	case BFA_PPORT_TOPOLOGY_LOOP:
-	case BFA_PPORT_TOPOLOGY_AUTO:
-		break;
-
-	default:
-		return BFA_STATUS_EINVAL;
-	}
-
-	fcport->cfg.topology = topology;
-	return BFA_STATUS_OK;
-}
-
-/**
- * Get current topology.
- */
-enum bfa_pport_topology
-bfa_fcport_get_topology(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->topology;
-}
-
-bfa_status_t
-bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, alpa);
-	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
-	bfa_trc(bfa, fcport->cfg.hardalpa);
-
-	fcport->cfg.cfg_hardalpa = BFA_TRUE;
-	fcport->cfg.hardalpa = alpa;
-
-	return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
-	bfa_trc(bfa, fcport->cfg.hardalpa);
-
-	fcport->cfg.cfg_hardalpa = BFA_FALSE;
-	return BFA_STATUS_OK;
-}
-
-bfa_boolean_t
-bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	*alpa = fcport->cfg.hardalpa;
-	return fcport->cfg.cfg_hardalpa;
-}
-
-u8
-bfa_fcport_get_myalpa(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->myalpa;
-}
-
-bfa_status_t
-bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, maxfrsize);
-	bfa_trc(bfa, fcport->cfg.maxfrsize);
-
-	/*
-	 * with in range
-	 */
-	if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
-		return BFA_STATUS_INVLD_DFSZ;
-
-	/*
-	 * power of 2, if not the max frame size of 2112
-	 */
-	if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
-		return BFA_STATUS_INVLD_DFSZ;
-
-	fcport->cfg.maxfrsize = maxfrsize;
-	return BFA_STATUS_OK;
-}
-
-u16
-bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->cfg.maxfrsize;
-}
-
-u32
-bfa_fcport_mypid(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->mypid;
-}
-
-u8
-bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->cfg.rx_bbcredit;
-}
-
-void
-bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	fcport->cfg.tx_bbcredit = (u8) tx_bbcredit;
-	bfa_fcport_send_txcredit(fcport);
-}
-
-/**
- * Get port attributes.
- */
-
-wwn_t
-bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	if (node)
-		return fcport->nwwn;
-	else
-		return fcport->pwwn;
-}
-
-void
-bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
-	bfa_os_memset(attr, 0, sizeof(struct bfa_pport_attr_s));
-
-	attr->nwwn = fcport->nwwn;
-	attr->pwwn = fcport->pwwn;
-
-	attr->factorypwwn =  bfa_ioc_get_mfg_pwwn(&bfa->ioc);
-	attr->factorynwwn =  bfa_ioc_get_mfg_nwwn(&bfa->ioc);
-
-	bfa_os_memcpy(&attr->pport_cfg, &fcport->cfg,
-		      sizeof(struct bfa_pport_cfg_s));
-	/*
-	 * speed attributes
-	 */
-	attr->pport_cfg.speed = fcport->cfg.speed;
-	attr->speed_supported = fcport->speed_sup;
-	attr->speed = fcport->speed;
-	attr->cos_supported = FC_CLASS_3;
-
-	/*
-	 * topology attributes
-	 */
-	attr->pport_cfg.topology = fcport->cfg.topology;
-	attr->topology = fcport->topology;
-
-	/*
-	 * beacon attributes
-	 */
-	attr->beacon = fcport->beacon;
-	attr->link_e2e_beacon = fcport->link_e2e_beacon;
-	attr->plog_enabled = bfa_plog_get_setting(fcport->bfa->plog);
-
-	attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
-	attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
-
-	/* PBC Disabled State */
-	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED)
-		attr->port_state = BFA_PPORT_ST_PREBOOT_DISABLED;
-	else {
-		attr->port_state = bfa_sm_to_state(
-				hal_pport_sm_table, fcport->sm);
-		if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
-			attr->port_state = BFA_PPORT_ST_IOCDIS;
-		else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
-			attr->port_state = BFA_PPORT_ST_FWMISMATCH;
-	}
-}
-
-#define BFA_FCPORT_STATS_TOV	1000
-
-/**
- * Fetch port attributes (FCQoS or FCoE).
- */
-bfa_status_t
-bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
-		    bfa_cb_pport_t cbfn, void *cbarg)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	if (fcport->stats_busy) {
-		bfa_trc(bfa, fcport->stats_busy);
-		return BFA_STATUS_DEVBUSY;
-	}
-
-	fcport->stats_busy  = BFA_TRUE;
-	fcport->stats_ret   = stats;
-	fcport->stats_cbfn  = cbfn;
-	fcport->stats_cbarg = cbarg;
-
-	bfa_fcport_send_stats_get(fcport);
-
-	bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout,
-		fcport, BFA_FCPORT_STATS_TOV);
-	return BFA_STATUS_OK;
-}
-
-/**
- * Reset port statistics (FCQoS or FCoE).
- */
-bfa_status_t
-bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	if (fcport->stats_busy) {
-		bfa_trc(bfa, fcport->stats_busy);
-		return BFA_STATUS_DEVBUSY;
-	}
-
-	fcport->stats_busy = BFA_TRUE;
-	fcport->stats_cbfn = cbfn;
-	fcport->stats_cbarg = cbarg;
-
-	bfa_fcport_send_stats_clear(fcport);
-
-	bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout,
-			fcport, BFA_FCPORT_STATS_TOV);
-	return BFA_STATUS_OK;
-}
-
-/**
- * Fetch FCQoS port statistics
- */
-bfa_status_t
-bfa_fcport_get_qos_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
-	bfa_cb_pport_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FC mode */
-	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
-}
-
-/**
- * Reset FCoE port statistics
- */
-bfa_status_t
-bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FC mode */
-	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
-}
-
-/**
- * Fetch FCQoS port statistics
- */
-bfa_status_t
-bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
-	bfa_cb_pport_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FCoE mode */
-	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
-}
-
-/**
- * Reset FCoE port statistics
- */
-bfa_status_t
-bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FCoE mode */
-	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
-}
-
-bfa_status_t
-bfa_fcport_trunk_enable(struct bfa_s *bfa, u8 bitmap)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, bitmap);
-	bfa_trc(bfa, fcport->cfg.trunked);
-	bfa_trc(bfa, fcport->cfg.trunk_ports);
-
-	if (!bitmap || (bitmap & (bitmap - 1)))
-		return BFA_STATUS_EINVAL;
-
-	fcport->cfg.trunked = BFA_TRUE;
-	fcport->cfg.trunk_ports = bitmap;
-
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_fcport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	qos_attr->state = bfa_os_ntohl(fcport->qos_attr.state);
-	qos_attr->total_bb_cr = bfa_os_ntohl(fcport->qos_attr.total_bb_cr);
-}
-
-void
-bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
-			  struct bfa_qos_vc_attr_s *qos_vc_attr)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr;
-	u32        i = 0;
-
-	qos_vc_attr->total_vc_count = bfa_os_ntohs(bfa_vc_attr->total_vc_count);
-	qos_vc_attr->shared_credit = bfa_os_ntohs(bfa_vc_attr->shared_credit);
-	qos_vc_attr->elp_opmode_flags =
-		bfa_os_ntohl(bfa_vc_attr->elp_opmode_flags);
-
-	/*
-	 * Individual VC info
-	 */
-	while (i < qos_vc_attr->total_vc_count) {
-		qos_vc_attr->vc_info[i].vc_credit =
-			bfa_vc_attr->vc_info[i].vc_credit;
-		qos_vc_attr->vc_info[i].borrow_credit =
-			bfa_vc_attr->vc_info[i].borrow_credit;
-		qos_vc_attr->vc_info[i].priority =
-			bfa_vc_attr->vc_info[i].priority;
-		++i;
-	}
-}
-
-/**
- * Fetch port attributes.
- */
-bfa_status_t
-bfa_fcport_trunk_disable(struct bfa_s *bfa)
-{
-	return BFA_STATUS_OK;
-}
-
-bfa_boolean_t
-bfa_fcport_trunk_query(struct bfa_s *bfa, u32 *bitmap)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	*bitmap = fcport->cfg.trunk_ports;
-	return fcport->cfg.trunked;
-}
-
-bfa_boolean_t
-bfa_fcport_is_disabled(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return bfa_sm_to_state(hal_pport_sm_table, fcport->sm) ==
-		BFA_PPORT_ST_DISABLED;
-
-}
-
-bfa_boolean_t
-bfa_fcport_is_ratelim(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
-
-}
-
-void
-bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
-
-	bfa_trc(bfa, on_off);
-	bfa_trc(bfa, fcport->cfg.qos_enabled);
-
-	bfa_trc(bfa, ioc_type);
-
-	if (ioc_type == BFA_IOC_TYPE_FC) {
-		fcport->cfg.qos_enabled = on_off;
-		/**
-		 * Notify fcpim of the change in QoS state
-		 */
-		bfa_fcpim_update_ioredirect(bfa);
-	}
-}
-
-void
-bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, on_off);
-	bfa_trc(bfa, fcport->cfg.ratelimit);
-
-	fcport->cfg.ratelimit = on_off;
-	if (fcport->cfg.trl_def_speed == BFA_PPORT_SPEED_UNKNOWN)
-		fcport->cfg.trl_def_speed = BFA_PPORT_SPEED_1GBPS;
-}
-
-/**
- * Configure default minimum ratelim speed
- */
-bfa_status_t
-bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, speed);
-
-	/*
-	 * Auto and speeds greater than the supported speed, are invalid
-	 */
-	if ((speed == BFA_PPORT_SPEED_AUTO) || (speed > fcport->speed_sup)) {
-		bfa_trc(bfa, fcport->speed_sup);
-		return BFA_STATUS_UNSUPP_SPEED;
-	}
-
-	fcport->cfg.trl_def_speed = speed;
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * Get default minimum ratelim speed
- */
-enum bfa_pport_speed
-bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, fcport->cfg.trl_def_speed);
-	return fcport->cfg.trl_def_speed;
-
-}
-
-void
-bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, status);
-	bfa_trc(bfa, fcport->diag_busy);
-
-	fcport->diag_busy = status;
-}
-
-void
-bfa_fcport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon,
-		 bfa_boolean_t link_e2e_beacon)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, beacon);
-	bfa_trc(bfa, link_e2e_beacon);
-	bfa_trc(bfa, fcport->beacon);
-	bfa_trc(bfa, fcport->link_e2e_beacon);
-
-	fcport->beacon = beacon;
-	fcport->link_e2e_beacon = link_e2e_beacon;
-}
-
-bfa_boolean_t
-bfa_fcport_is_linkup(struct bfa_s *bfa)
-{
-	return bfa_sm_cmp_state(BFA_FCPORT_MOD(bfa), bfa_fcport_sm_linkup);
-}
-
-bfa_boolean_t
-bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->cfg.qos_enabled;
-}
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index d1a9920..9cebbe3 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -19,35 +19,28 @@
  *  bfa_fcs.c BFA FCS main
  */
 
-#include <fcs/bfa_fcs.h>
-#include "fcs_port.h"
-#include "fcs_uf.h"
-#include "fcs_vport.h"
-#include "fcs_rport.h"
-#include "fcs_fabric.h"
-#include "fcs_fcpim.h"
-#include "fcs_fcptm.h"
-#include "fcbuild.h"
-#include "fcs.h"
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
 #include "bfad_drv.h"
-#include <fcb/bfa_fcb.h>
+
+BFA_TRC_FILE(FCS, FCS);
 
 /**
  * FCS sub-modules
  */
 struct bfa_fcs_mod_s {
 	void		(*attach) (struct bfa_fcs_s *fcs);
-	void            (*modinit) (struct bfa_fcs_s *fcs);
-	void            (*modexit) (struct bfa_fcs_s *fcs);
+	void		(*modinit) (struct bfa_fcs_s *fcs);
+	void		(*modexit) (struct bfa_fcs_s *fcs);
 };
 
 #define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit }
 
 static struct bfa_fcs_mod_s fcs_modules[] = {
-	{ bfa_fcs_pport_attach, NULL, NULL },
+	{ bfa_fcs_port_attach, NULL, NULL },
 	{ bfa_fcs_uf_attach, NULL, NULL },
 	{ bfa_fcs_fabric_attach, bfa_fcs_fabric_modinit,
-	 bfa_fcs_fabric_modexit },
+	  bfa_fcs_fabric_modexit },
 };
 
 /**
@@ -57,8 +50,8 @@
 static void
 bfa_fcs_exit_comp(void *fcs_cbarg)
 {
-	struct bfa_fcs_s *fcs = fcs_cbarg;
-	struct bfad_s *bfad = fcs->bfad;
+	struct bfa_fcs_s      *fcs = fcs_cbarg;
+	struct bfad_s         *bfad = fcs->bfad;
 
 	complete(&bfad->comp);
 }
@@ -74,9 +67,9 @@
  */
 void
 bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
-			bfa_boolean_t min_cfg)
+	       bfa_boolean_t min_cfg)
 {
-	int             i;
+	int		i;
 	struct bfa_fcs_mod_s  *mod;
 
 	fcs->bfa = bfa;
@@ -86,7 +79,7 @@
 	bfa_attach_fcs(bfa);
 	fcbuild_init();
 
-	for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
+	for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
 		mod = &fcs_modules[i];
 		if (mod->attach)
 			mod->attach(fcs);
@@ -99,11 +92,11 @@
 void
 bfa_fcs_init(struct bfa_fcs_s *fcs)
 {
-	int i, npbc_vports;
+	int		i, npbc_vports;
 	struct bfa_fcs_mod_s  *mod;
 	struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
 
-	for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
+	for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
 		mod = &fcs_modules[i];
 		if (mod->modinit)
 			mod->modinit(fcs);
@@ -111,7 +104,7 @@
 	/* Initialize pbc vports */
 	if (!fcs->min_cfg) {
 		npbc_vports =
-			bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
+		    bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
 		for (i = 0; i < npbc_vports; i++)
 			bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);
 	}
@@ -127,12 +120,13 @@
 }
 
 /**
- * 		FCS driver details initialization.
+ *	brief
+ *		FCS driver details initialization.
  *
- * 	param[in]		fcs		FCS instance
- * 	param[in]		driver_info	Driver Details
+ *	param[in]		fcs		FCS instance
+ *	param[in]		driver_info	Driver Details
  *
- * 	return None
+ *	return None
  */
 void
 bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
@@ -145,13 +139,13 @@
 }
 
 /**
- *      @brief
- *              FCS FDMI Driver Parameter Initialization
+ *	brief
+ *		FCS FDMI Driver Parameter Initialization
  *
- *      @param[in]              fcs             FCS instance
- *      @param[in]              fdmi_enable     TRUE/FALSE
+ *	param[in]		fcs		FCS instance
+ *	param[in]		fdmi_enable	TRUE/FALSE
  *
- *      @return None
+ *	return None
  */
 void
 bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable)
@@ -160,22 +154,24 @@
 	fcs->fdmi_enabled = fdmi_enable;
 
 }
-
 /**
- * 		FCS instance cleanup and exit.
+ *	brief
+ *		FCS instance cleanup and exit.
  *
- * 	param[in]		fcs			FCS instance
- * 	return None
+ *	param[in]		fcs			FCS instance
+ *	return None
  */
 void
 bfa_fcs_exit(struct bfa_fcs_s *fcs)
 {
 	struct bfa_fcs_mod_s  *mod;
-	int i;
+	int		nmods, i;
 
 	bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
 
-	for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
+	nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
+
+	for (i = 0; i < nmods; i++) {
 
 		mod = &fcs_modules[i];
 		if (mod->modexit) {
@@ -194,24 +190,1547 @@
 	fcs->trcmod = trcmod;
 }
 
-
-void
-bfa_fcs_log_init(struct bfa_fcs_s *fcs, struct bfa_log_mod_s *logmod)
-{
-	fcs->logm = logmod;
-}
-
-
-void
-bfa_fcs_aen_init(struct bfa_fcs_s *fcs, struct bfa_aen_s *aen)
-{
-	fcs->aen = aen;
-}
-
 void
 bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs)
 {
 	bfa_wc_down(&fcs->wc);
 }
 
+/**
+ * Fabric module implementation.
+ */
 
+#define BFA_FCS_FABRIC_RETRY_DELAY	(2000)	/* Milliseconds */
+#define BFA_FCS_FABRIC_CLEANUP_DELAY	(10000)	/* Milliseconds */
+
+#define bfa_fcs_fabric_set_opertype(__fabric) do {			\
+		if (bfa_fcport_get_topology((__fabric)->fcs->bfa)	\
+		    == BFA_PORT_TOPOLOGY_P2P)				\
+			(__fabric)->oper_type = BFA_PORT_TYPE_NPORT;	\
+		else							\
+			(__fabric)->oper_type = BFA_PORT_TYPE_NLPORT;	\
+} while (0)
+
+/*
+ * forward declarations
+ */
+static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_delay(void *cbarg);
+static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_delete_comp(void *cbarg);
+static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
+				      struct fchs_s *fchs, u16 len);
+static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
+					 struct fchs_s *fchs, u16 len);
+static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
+					 struct bfa_fcxp_s *fcxp, void *cbarg,
+					 bfa_status_t status,
+					 u32 rsp_len,
+					 u32 resid_len,
+					 struct fchs_s *rspfchs);
+/**
+ *  fcs_fabric_sm fabric state machine functions
+ */
+
+/**
+ * Fabric state machine events
+ */
+enum bfa_fcs_fabric_event {
+	BFA_FCS_FABRIC_SM_CREATE	= 1,	/*  create from driver	      */
+	BFA_FCS_FABRIC_SM_DELETE	= 2,	/*  delete from driver	      */
+	BFA_FCS_FABRIC_SM_LINK_DOWN	= 3,	/*  link down from port      */
+	BFA_FCS_FABRIC_SM_LINK_UP	= 4,	/*  link up from port	      */
+	BFA_FCS_FABRIC_SM_CONT_OP	= 5,	/*  flogi/auth continue op   */
+	BFA_FCS_FABRIC_SM_RETRY_OP	= 6,	/*  flogi/auth retry op      */
+	BFA_FCS_FABRIC_SM_NO_FABRIC	= 7,	/*  from flogi/auth	      */
+	BFA_FCS_FABRIC_SM_PERF_EVFP	= 8,	/*  from flogi/auth	      */
+	BFA_FCS_FABRIC_SM_ISOLATE	= 9,	/*  from EVFP processing     */
+	BFA_FCS_FABRIC_SM_NO_TAGGING	= 10,	/*  no VFT tagging from EVFP */
+	BFA_FCS_FABRIC_SM_DELAYED	= 11,	/*  timeout delay event      */
+	BFA_FCS_FABRIC_SM_AUTH_FAILED	= 12,	/*  auth failed	      */
+	BFA_FCS_FABRIC_SM_AUTH_SUCCESS	= 13,	/*  auth successful	      */
+	BFA_FCS_FABRIC_SM_DELCOMP	= 14,	/*  all vports deleted event */
+	BFA_FCS_FABRIC_SM_LOOPBACK	= 15,	/*  Received our own FLOGI   */
+	BFA_FCS_FABRIC_SM_START		= 16,	/*  from driver	      */
+};
+
+static void	bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
+					 enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
+					  enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
+					   enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
+					enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
+					      enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
+				       enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
+					      enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
+					   enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
+					   enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
+					 enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
+				       enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
+					    enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
+					   enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
+					   enum bfa_fcs_fabric_event event);
+/**
+ *   Beginning state before fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
+			 enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_CREATE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
+		bfa_fcs_fabric_init(fabric);
+		bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_UP:
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Beginning state before fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
+			  enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_START:
+		if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
+			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+			bfa_fcs_fabric_login(fabric);
+		} else
+			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_UP:
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+		bfa_fcs_modexit_comp(fabric->fcs);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Link is down, awaiting LINK UP event from port. This is also the
+ *   first state at fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
+			   enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_LINK_UP:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+		bfa_fcs_fabric_login(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_RETRY_OP:
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   FLOGI is in progress, awaiting FLOGI reply.
+ */
+static void
+bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
+			enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_CONT_OP:
+
+		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
+					   fabric->bb_credit);
+		fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
+
+		if (fabric->auth_reqd && fabric->is_auth) {
+			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);
+			bfa_trc(fabric->fcs, event);
+		} else {
+			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
+			bfa_fcs_fabric_notify_online(fabric);
+		}
+		break;
+
+	case BFA_FCS_FABRIC_SM_RETRY_OP:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);
+		bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,
+				bfa_fcs_fabric_delay, fabric,
+				BFA_FCS_FABRIC_RETRY_DELAY);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LOOPBACK:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
+		bfa_lps_discard(fabric->lps);
+		bfa_fcs_fabric_set_opertype(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_NO_FABRIC:
+		fabric->fab_type = BFA_FCS_FABRIC_N2N;
+		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
+					   fabric->bb_credit);
+		bfa_fcs_fabric_notify_online(fabric);
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_lps_discard(fabric->lps);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_lps_discard(fabric->lps);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+
+static void
+bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
+			      enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_DELAYED:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+		bfa_fcs_fabric_login(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_timer_stop(&fabric->delay_timer);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_timer_stop(&fabric->delay_timer);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Authentication is in progress, awaiting authentication results.
+ */
+static void
+bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
+		       enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_AUTH_FAILED:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
+		bfa_lps_discard(fabric->lps);
+		break;
+
+	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
+		bfa_fcs_fabric_notify_online(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_PERF_EVFP:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_lps_discard(fabric->lps);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Authentication failed
+ */
+static void
+bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
+			      enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_fcs_fabric_notify_offline(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Port is in loopback mode.
+ */
+static void
+bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
+			   enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_fcs_fabric_notify_offline(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   There is no attached fabric - private loop or NPort-to-NPort topology.
+ */
+static void
+bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
+			   enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_lps_discard(fabric->lps);
+		bfa_fcs_fabric_notify_offline(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_NO_FABRIC:
+		bfa_trc(fabric->fcs, fabric->bb_credit);
+		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
+					   fabric->bb_credit);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Fabric is online - normal operating state.
+ */
+static void
+bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
+			 enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_lps_discard(fabric->lps);
+		bfa_fcs_fabric_notify_offline(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_AUTH_FAILED:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
+		bfa_lps_discard(fabric->lps);
+		break;
+
+	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Exchanging virtual fabric parameters.
+ */
+static void
+bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
+		       enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_CONT_OP:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);
+		break;
+
+	case BFA_FCS_FABRIC_SM_ISOLATE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   EVFP exchange complete and VFT tagging is enabled.
+ */
+static void
+bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
+			    enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+}
+
+/**
+ *   Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
+ */
+static void
+bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
+			   enum bfa_fcs_fabric_event event)
+{
+	struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
+	char	pwwn_ptr[BFA_STRING_32];
+
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+	wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn);
+
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"Port is isolated due to VF_ID mismatch. "
+		"PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",
+		pwwn_ptr, fabric->fcs->port_vfid,
+		fabric->event_arg.swp_vfid);
+}
+
+/**
+ *   Fabric is being deleted, awaiting vport delete completions.
+ */
+static void
+bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
+			   enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_DELCOMP:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+		bfa_fcs_modexit_comp(fabric->fcs);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_UP:
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_fcs_fabric_notify_offline(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+
+
+/**
+ *  fcs_fabric_private fabric private functions
+ */
+
+static void
+bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
+
+	port_cfg->roles = BFA_LPORT_ROLE_FCP_IM;
+	port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc);
+	port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc);
+}
+
+/**
+ * Port Symbolic Name Creation for base port.
+ */
+void
+bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
+	char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
+	struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
+
+	bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
+
+	/* Model name/number */
+	strncpy((char *)&port_cfg->sym_name, model,
+		BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
+	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+	/* Driver Version */
+	strncat((char *)&port_cfg->sym_name, (char *)driver_info->version,
+		BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
+	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+	/* Host machine name */
+	strncat((char *)&port_cfg->sym_name,
+		(char *)driver_info->host_machine_name,
+		BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
+	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+	/*
+	 * Host OS Info :
+	 * If OS Patch Info is not there, do not truncate any bytes from the
+	 * OS name string and instead copy the entire OS info string (64 bytes).
+	 */
+	if (driver_info->host_os_patch[0] == '\0') {
+		strncat((char *)&port_cfg->sym_name,
+			(char *)driver_info->host_os_name,
+			BFA_FCS_OS_STR_LEN);
+		strncat((char *)&port_cfg->sym_name,
+			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+	} else {
+		strncat((char *)&port_cfg->sym_name,
+			(char *)driver_info->host_os_name,
+			BFA_FCS_PORT_SYMBNAME_OSINFO_SZ);
+		strncat((char *)&port_cfg->sym_name,
+			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+		/* Append host OS Patch Info */
+		strncat((char *)&port_cfg->sym_name,
+			(char *)driver_info->host_os_patch,
+			BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ);
+	}
+
+	/* null terminate */
+	port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
+}
+
+/**
+ * bfa lps login completion callback
+ */
+void
+bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
+{
+	struct bfa_fcs_fabric_s *fabric = uarg;
+
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, status);
+
+	switch (status) {
+	case BFA_STATUS_OK:
+		fabric->stats.flogi_accepts++;
+		break;
+
+	case BFA_STATUS_INVALID_MAC:
+		/* Only for CNA */
+		fabric->stats.flogi_acc_err++;
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+
+		return;
+
+	case BFA_STATUS_EPROTOCOL:
+		switch (bfa_lps_get_extstatus(fabric->lps)) {
+		case BFA_EPROTO_BAD_ACCEPT:
+			fabric->stats.flogi_acc_err++;
+			break;
+
+		case BFA_EPROTO_UNKNOWN_RSP:
+			fabric->stats.flogi_unknown_rsp++;
+			break;
+
+		default:
+			break;
+		}
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+
+		return;
+
+	case BFA_STATUS_FABRIC_RJT:
+		fabric->stats.flogi_rejects++;
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+		return;
+
+	default:
+		fabric->stats.flogi_rsp_err++;
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+		return;
+	}
+
+	fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps);
+	bfa_trc(fabric->fcs, fabric->bb_credit);
+
+	if (!bfa_lps_is_brcd_fabric(fabric->lps))
+		fabric->fabric_name =  bfa_lps_get_peer_nwwn(fabric->lps);
+
+	/*
+	 * Check port type. It should be 1 = F-port.
+	 */
+	if (bfa_lps_is_fport(fabric->lps)) {
+		fabric->bport.pid = bfa_lps_get_pid(fabric->lps);
+		fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps);
+		fabric->is_auth = bfa_lps_is_authreq(fabric->lps);
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
+	} else {
+		/*
+		 * Nport-2-Nport direct attached
+		 */
+		fabric->bport.port_topo.pn2n.rem_port_wwn =
+			bfa_lps_get_peer_pwwn(fabric->lps);
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
+	}
+
+	bfa_trc(fabric->fcs, fabric->bport.pid);
+	bfa_trc(fabric->fcs, fabric->is_npiv);
+	bfa_trc(fabric->fcs, fabric->is_auth);
+}
+/**
+ *		Allocate and send FLOGI.
+ */
+static void
+bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_s		*bfa = fabric->fcs->bfa;
+	struct bfa_lport_cfg_s	*pcfg = &fabric->bport.port_cfg;
+	u8			alpa = 0;
+
+	if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
+		alpa = bfa_fcport_get_myalpa(bfa);
+
+	bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
+		      pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
+
+	fabric->stats.flogi_sent++;
+}
+
+static void
+bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_fcs_vport_s *vport;
+	struct list_head	      *qe, *qen;
+
+	bfa_trc(fabric->fcs, fabric->fabric_name);
+
+	bfa_fcs_fabric_set_opertype(fabric);
+	fabric->stats.fabric_onlines++;
+
+	/**
+	 * notify online event to base and then virtual ports
+	 */
+	bfa_fcs_lport_online(&fabric->bport);
+
+	list_for_each_safe(qe, qen, &fabric->vport_q) {
+		vport = (struct bfa_fcs_vport_s *) qe;
+		bfa_fcs_vport_online(vport);
+	}
+}
+
+static void
+bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_fcs_vport_s *vport;
+	struct list_head	      *qe, *qen;
+
+	bfa_trc(fabric->fcs, fabric->fabric_name);
+	fabric->stats.fabric_offlines++;
+
+	/**
+	 * notify offline event first to vports and then base port.
+	 */
+	list_for_each_safe(qe, qen, &fabric->vport_q) {
+		vport = (struct bfa_fcs_vport_s *) qe;
+		bfa_fcs_vport_offline(vport);
+	}
+
+	bfa_fcs_lport_offline(&fabric->bport);
+
+	fabric->fabric_name = 0;
+	fabric->fabric_ip_addr[0] = 0;
+}
+
+static void
+bfa_fcs_fabric_delay(void *cbarg)
+{
+	struct bfa_fcs_fabric_s *fabric = cbarg;
+
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
+}
+
+/**
+ * Delete all vports and wait for vport delete completions.
+ */
+static void
+bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_fcs_vport_s *vport;
+	struct list_head	      *qe, *qen;
+
+	list_for_each_safe(qe, qen, &fabric->vport_q) {
+		vport = (struct bfa_fcs_vport_s *) qe;
+		bfa_fcs_vport_fcs_delete(vport);
+	}
+
+	bfa_fcs_lport_delete(&fabric->bport);
+	bfa_wc_wait(&fabric->wc);
+}
+
+static void
+bfa_fcs_fabric_delete_comp(void *cbarg)
+{
+	struct bfa_fcs_fabric_s *fabric = cbarg;
+
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
+}
+
+/**
+ *  fcs_fabric_public fabric public functions
+ */
+
+/**
+ * Attach time initialization.
+ */
+void
+bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
+{
+	struct bfa_fcs_fabric_s *fabric;
+
+	fabric = &fcs->fabric;
+	bfa_os_memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
+
+	/**
+	 * Initialize base fabric.
+	 */
+	fabric->fcs = fcs;
+	INIT_LIST_HEAD(&fabric->vport_q);
+	INIT_LIST_HEAD(&fabric->vf_q);
+	fabric->lps = bfa_lps_alloc(fcs->bfa);
+	bfa_assert(fabric->lps);
+
+	/**
+	 * Initialize fabric delete completion handler. Fabric deletion is
+	 * complete when the last vport delete is complete.
+	 */
+	bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
+	bfa_wc_up(&fabric->wc); /* For the base port */
+
+	bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+	bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
+}
+
+void
+bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
+{
+	bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
+	bfa_trc(fcs, 0);
+}
+
+/**
+ *   Module cleanup
+ */
+void
+bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
+{
+	struct bfa_fcs_fabric_s *fabric;
+
+	bfa_trc(fcs, 0);
+
+	/**
+	 * Cleanup base fabric.
+	 */
+	fabric = &fcs->fabric;
+	bfa_lps_delete(fabric->lps);
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
+}
+
+/**
+ * Fabric module start -- kick starts FCS actions
+ */
+void
+bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
+{
+	struct bfa_fcs_fabric_s *fabric;
+
+	bfa_trc(fcs, 0);
+	fabric = &fcs->fabric;
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
+}
+
+/**
+ *   Suspend fabric activity as part of driver suspend.
+ */
+void
+bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs)
+{
+}
+
+bfa_boolean_t
+bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric)
+{
+	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback);
+}
+
+bfa_boolean_t
+bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric)
+{
+	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed);
+}
+
+enum bfa_port_type
+bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric)
+{
+	return fabric->oper_type;
+}
+
+/**
+ *   Link up notification from BFA physical port module.
+ */
+void
+bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);
+}
+
+/**
+ *   Link down notification from BFA physical port module.
+ */
+void
+bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
+}
+
+/**
+ *   A child vport is being created in the fabric.
+ *
+ *   Call from vport module at vport creation. A list of base port and vports
+ *   belonging to a fabric is maintained to propagate link events.
+ *
+ *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ *   param[in] vport  - Vport being created.
+ *
+ *   @return None (always succeeds)
+ */
+void
+bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
+			struct bfa_fcs_vport_s *vport)
+{
+	/**
+	 * - add vport to fabric's vport_q
+	 */
+	bfa_trc(fabric->fcs, fabric->vf_id);
+
+	list_add_tail(&vport->qe, &fabric->vport_q);
+	fabric->num_vports++;
+	bfa_wc_up(&fabric->wc);
+}
+
+/**
+ *   A child vport is being deleted from fabric.
+ *
+ *   Vport is being deleted.
+ */
+void
+bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
+			struct bfa_fcs_vport_s *vport)
+{
+	list_del(&vport->qe);
+	fabric->num_vports--;
+	bfa_wc_down(&fabric->wc);
+}
+
+/**
+ *   Base port is deleted.
+ */
+void
+bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric)
+{
+	bfa_wc_down(&fabric->wc);
+}
+
+
+/**
+ *    Check if fabric is online.
+ *
+ *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ *
+ *   @return  TRUE/FALSE
+ */
+int
+bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric)
+{
+	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online);
+}
+
+/**
+ *	brief
+ *
+ */
+bfa_status_t
+bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs,
+		     struct bfa_lport_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
+{
+	bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Lookup for a vport withing a fabric given its pwwn
+ */
+struct bfa_fcs_vport_s *
+bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
+{
+	struct bfa_fcs_vport_s *vport;
+	struct list_head	      *qe;
+
+	list_for_each(qe, &fabric->vport_q) {
+		vport = (struct bfa_fcs_vport_s *) qe;
+		if (bfa_fcs_lport_get_pwwn(&vport->lport) == pwwn)
+			return vport;
+	}
+
+	return NULL;
+}
+
+/**
+ *    In a given fabric, return the number of lports.
+ *
+ *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ *
+ *   @return : 1 or more.
+ */
+u16
+bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric)
+{
+	return fabric->num_vports;
+}
+
+/*
+ *  Get OUI of the attached switch.
+ *
+ *  Note : Use of this function should be avoided as much as possible.
+ *         This function should be used only if there is any requirement
+*          to check for FOS version below 6.3.
+ *         To check if the attached fabric is a brocade fabric, use
+ *         bfa_lps_is_brcd_fabric() which works for FOS versions 6.3
+ *         or above only.
+ */
+
+u16
+bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)
+{
+	wwn_t fab_nwwn;
+	u8 *tmp;
+	u16 oui;
+
+	fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps);
+
+	tmp = (u8 *)&fab_nwwn;
+	oui = (tmp[3] << 8) | tmp[4];
+
+	return oui;
+}
+/**
+ *		Unsolicited frame receive handling.
+ */
+void
+bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
+		       u16 len)
+{
+	u32	pid = fchs->d_id;
+	struct bfa_fcs_vport_s *vport;
+	struct list_head	      *qe;
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+	struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd;
+
+	bfa_trc(fabric->fcs, len);
+	bfa_trc(fabric->fcs, pid);
+
+	/**
+	 * Look for our own FLOGI frames being looped back. This means an
+	 * external loopback cable is in place. Our own FLOGI frames are
+	 * sometimes looped back when switch port gets temporarily bypassed.
+	 */
+	if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT)) &&
+	    (els_cmd->els_code == FC_ELS_FLOGI) &&
+	    (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) {
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
+		return;
+	}
+
+	/**
+	 * FLOGI/EVFP exchanges should be consumed by base fabric.
+	 */
+	if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) {
+		bfa_trc(fabric->fcs, pid);
+		bfa_fcs_fabric_process_uf(fabric, fchs, len);
+		return;
+	}
+
+	if (fabric->bport.pid == pid) {
+		/**
+		 * All authentication frames should be routed to auth
+		 */
+		bfa_trc(fabric->fcs, els_cmd->els_code);
+		if (els_cmd->els_code == FC_ELS_AUTH) {
+			bfa_trc(fabric->fcs, els_cmd->els_code);
+			return;
+		}
+
+		bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));
+		bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
+		return;
+	}
+
+	/**
+	 * look for a matching local port ID
+	 */
+	list_for_each(qe, &fabric->vport_q) {
+		vport = (struct bfa_fcs_vport_s *) qe;
+		if (vport->lport.pid == pid) {
+			bfa_fcs_lport_uf_recv(&vport->lport, fchs, len);
+			return;
+		}
+	}
+	bfa_trc(fabric->fcs, els_cmd->els_code);
+	bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
+}
+
+/**
+ *		Unsolicited frames to be processed by fabric.
+ */
+static void
+bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
+			  u16 len)
+{
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+	bfa_trc(fabric->fcs, els_cmd->els_code);
+
+	switch (els_cmd->els_code) {
+	case FC_ELS_FLOGI:
+		bfa_fcs_fabric_process_flogi(fabric, fchs, len);
+		break;
+
+	default:
+		/*
+		 * need to generate a LS_RJT
+		 */
+		break;
+	}
+}
+
+/**
+ *	Process	incoming FLOGI
+ */
+static void
+bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
+			struct fchs_s *fchs, u16 len)
+{
+	struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1);
+	struct bfa_fcs_lport_s *bport = &fabric->bport;
+
+	bfa_trc(fabric->fcs, fchs->s_id);
+
+	fabric->stats.flogi_rcvd++;
+	/*
+	 * Check port type. It should be 0 = n-port.
+	 */
+	if (flogi->csp.port_type) {
+		/*
+		 * @todo: may need to send a LS_RJT
+		 */
+		bfa_trc(fabric->fcs, flogi->port_name);
+		fabric->stats.flogi_rejected++;
+		return;
+	}
+
+	fabric->bb_credit = bfa_os_ntohs(flogi->csp.bbcred);
+	bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
+	bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
+
+	/*
+	 * Send a Flogi Acc
+	 */
+	bfa_fcs_fabric_send_flogi_acc(fabric);
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
+}
+
+static void
+bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
+	struct bfa_fcs_lport_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;
+	struct bfa_s	  *bfa = fabric->fcs->bfa;
+	struct bfa_fcxp_s *fcxp;
+	u16	reqlen;
+	struct fchs_s	fchs;
+
+	fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
+	/**
+	 * Do not expect this failure -- expect remote node to retry
+	 */
+	if (!fcxp)
+		return;
+
+	reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				    bfa_os_hton3b(FC_FABRIC_PORT),
+				    n2n_port->reply_oxid, pcfg->pwwn,
+				    pcfg->nwwn,
+				    bfa_fcport_get_maxfrsize(bfa),
+				    bfa_fcport_get_rx_bbcredit(bfa));
+
+	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps),
+		      BFA_FALSE, FC_CLASS_3,
+		      reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
+		      FC_MAX_PDUSZ, 0);
+}
+
+/**
+ *   Flogi Acc completion callback.
+ */
+static void
+bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+			     bfa_status_t status, u32 rsp_len,
+			     u32 resid_len, struct fchs_s *rspfchs)
+{
+	struct bfa_fcs_fabric_s *fabric = cbarg;
+
+	bfa_trc(fabric->fcs, status);
+}
+
+/*
+ *
+ * @param[in] fabric - fabric
+ * @param[in] wwn_t - new fabric name
+ *
+ * @return - none
+ */
+void
+bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
+			       wwn_t fabric_name)
+{
+	struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
+	char	pwwn_ptr[BFA_STRING_32];
+	char	fwwn_ptr[BFA_STRING_32];
+
+	bfa_trc(fabric->fcs, fabric_name);
+
+	if (fabric->fabric_name == 0) {
+		/*
+		 * With BRCD switches, we don't get Fabric Name in FLOGI.
+		 * Don't generate a fabric name change event in this case.
+		 */
+		fabric->fabric_name = fabric_name;
+	} else {
+		fabric->fabric_name = fabric_name;
+		wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport));
+		wwn2str(fwwn_ptr,
+			bfa_fcs_lport_get_fabric_name(&fabric->bport));
+		BFA_LOG(KERN_WARNING, bfad, log_level,
+			"Base port WWN = %s Fabric WWN = %s\n",
+			pwwn_ptr, fwwn_ptr);
+	}
+}
+
+/**
+ *  fcs_vf_api virtual fabrics API
+ */
+
+/**
+ * Enable VF mode.
+ *
+ * @param[in]		fcs		fcs module instance
+ * @param[in]		vf_id		default vf_id of port, FC_VF_ID_NULL
+ *					to use standard default vf_id of 1.
+ *
+ * @retval	BFA_STATUS_OK		vf mode is enabled
+ * @retval	BFA_STATUS_BUSY		Port is active. Port must be disabled
+ *					before VF mode can be enabled.
+ */
+bfa_status_t
+bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id)
+{
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Disable VF mode.
+ *
+ * @param[in]		fcs		fcs module instance
+ *
+ * @retval	BFA_STATUS_OK		vf mode is disabled
+ * @retval	BFA_STATUS_BUSY		VFs are present and being used. All
+ *					VFs must be deleted before disabling
+ *					VF mode.
+ */
+bfa_status_t
+bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs)
+{
+	return BFA_STATUS_OK;
+}
+
+/**
+ *  Create a new VF instance.
+ *
+ *  A new VF is created using the given VF configuration. A VF is identified
+ *  by VF id. No duplicate VF creation is allowed with the same VF id. Once
+ *  a VF is created, VF is automatically started after link initialization
+ *  and EVFP exchange is completed.
+ *
+ *	param[in] vf	 -	FCS vf data structure. Memory is
+ *				allocated by caller (driver)
+ *	param[in] fcs	 -	FCS module
+ *	param[in] vf_cfg -	VF configuration
+ *	param[in] vf_drv -	Opaque handle back to the driver's
+ *				virtual vf structure
+ *
+ *	retval BFA_STATUS_OK VF creation is successful
+ *	retval BFA_STATUS_FAILED VF creation failed
+ *	retval BFA_STATUS_EEXIST A VF exists with the given vf_id
+ */
+bfa_status_t
+bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs, u16 vf_id,
+		  struct bfa_lport_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
+{
+	bfa_trc(fcs, vf_id);
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Use this function to delete a BFA VF object. VF object should
+ *	be stopped before this function call.
+ *
+ *	param[in] vf - pointer to bfa_vf_t.
+ *
+ *	retval BFA_STATUS_OK	On vf deletion success
+ *	retval BFA_STATUS_BUSY VF is not in a stopped state
+ *	retval BFA_STATUS_INPROGRESS VF deletion in in progress
+ */
+bfa_status_t
+bfa_fcs_vf_delete(bfa_fcs_vf_t *vf)
+{
+	bfa_trc(vf->fcs, vf->vf_id);
+	return BFA_STATUS_OK;
+}
+
+
+/**
+ *	Returns attributes of the given VF.
+ *
+ *	param[in]	vf	pointer to bfa_vf_t.
+ *	param[out] vf_attr	vf attributes returned
+ *
+ *	return None
+ */
+void
+bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr)
+{
+	bfa_trc(vf->fcs, vf->vf_id);
+}
+
+/**
+ *	Return statistics associated with the given vf.
+ *
+ *	param[in] vf		pointer to bfa_vf_t.
+ *	param[out] vf_stats	vf statistics returned
+ *
+ *	@return None
+ */
+void
+bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf, struct bfa_vf_stats_s *vf_stats)
+{
+	bfa_os_memcpy(vf_stats, &vf->stats, sizeof(struct bfa_vf_stats_s));
+}
+
+/**
+ *	clear statistics associated with the given vf.
+ *
+ *	param[in]	vf	pointer to bfa_vf_t.
+ *
+ *	@return None
+ */
+void
+bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf)
+{
+	bfa_os_memset(&vf->stats, 0, sizeof(struct bfa_vf_stats_s));
+}
+
+/**
+ *	Returns FCS vf structure for a given vf_id.
+ *
+ *	param[in]	vf_id - VF_ID
+ *
+ *	return
+ *	If lookup succeeds, retuns fcs vf object, otherwise returns NULL
+ */
+bfa_fcs_vf_t   *
+bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
+{
+	bfa_trc(fcs, vf_id);
+	if (vf_id == FC_VF_ID_NULL)
+		return &fcs->fabric;
+
+	return NULL;
+}
+
+/**
+ *	Return the list of VFs configured.
+ *
+ *	param[in]	fcs	fcs module instance
+ *	param[out]	vf_ids	returned list of vf_ids
+ *	param[in,out]	nvfs	in:size of vf_ids array,
+ *				out:total elements present,
+ *				actual elements returned is limited by the size
+ *
+ *	return Driver VF structure
+ */
+void
+bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
+{
+	bfa_trc(fcs, *nvfs);
+}
+
+/**
+ *	Return the list of all VFs visible from fabric.
+ *
+ *	param[in]	fcs	fcs module instance
+ *	param[out]	vf_ids	returned list of vf_ids
+ *	param[in,out]	nvfs	in:size of vf_ids array,
+ *				out:total elements present,
+ *				actual elements returned is limited by the size
+ *
+ *	return Driver VF structure
+ */
+void
+bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
+{
+	bfa_trc(fcs, *nvfs);
+}
+
+/**
+ *	Return the list of local logical ports present in the given VF.
+ *
+ *	param[in]	vf	vf for which logical ports are returned
+ *	param[out]	lpwwn	returned logical port wwn list
+ *	param[in,out]	nlports	in:size of lpwwn list;
+ *				out:total elements present,
+ *				actual elements returned is limited by the size
+ */
+void
+bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
+{
+	struct list_head	*qe;
+	struct bfa_fcs_vport_s *vport;
+	int	i;
+	struct bfa_fcs_s      *fcs;
+
+	if (vf == NULL || lpwwn == NULL || *nlports == 0)
+		return;
+
+	fcs = vf->fcs;
+
+	bfa_trc(fcs, vf->vf_id);
+	bfa_trc(fcs, (u32) *nlports);
+
+	i = 0;
+	lpwwn[i++] = vf->bport.port_cfg.pwwn;
+
+	list_for_each(qe, &vf->vport_q) {
+		if (i >= *nlports)
+			break;
+
+		vport = (struct bfa_fcs_vport_s *) qe;
+		lpwwn[i++] = vport->lport.port_cfg.pwwn;
+	}
+
+	bfa_trc(fcs, i);
+	*nlports = i;
+}
+
+/**
+ * BFA FCS PPORT ( physical port)
+ */
+static void
+bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event)
+{
+	struct bfa_fcs_s      *fcs = cbarg;
+
+	bfa_trc(fcs, event);
+
+	switch (event) {
+	case BFA_PORT_LINKUP:
+		bfa_fcs_fabric_link_up(&fcs->fabric);
+		break;
+
+	case BFA_PORT_LINKDOWN:
+		bfa_fcs_fabric_link_down(&fcs->fabric);
+		break;
+
+	default:
+		bfa_assert(0);
+	}
+}
+
+void
+bfa_fcs_port_attach(struct bfa_fcs_s *fcs)
+{
+	bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs);
+}
+
+/**
+ * BFA FCS UF ( Unsolicited Frames)
+ */
+
+/**
+ *		BFA callback for unsolicited frame receive handler.
+ *
+ * @param[in]		cbarg		callback arg for receive handler
+ * @param[in]		uf		unsolicited frame descriptor
+ *
+ * @return None
+ */
+static void
+bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
+{
+	struct bfa_fcs_s	*fcs = (struct bfa_fcs_s *) cbarg;
+	struct fchs_s	*fchs = bfa_uf_get_frmbuf(uf);
+	u16	len = bfa_uf_get_frmlen(uf);
+	struct fc_vft_s *vft;
+	struct bfa_fcs_fabric_s *fabric;
+
+	/**
+	 * check for VFT header
+	 */
+	if (fchs->routing == FC_RTG_EXT_HDR &&
+	    fchs->cat_info == FC_CAT_VFT_HDR) {
+		bfa_stats(fcs, uf.tagged);
+		vft = bfa_uf_get_frmbuf(uf);
+		if (fcs->port_vfid == vft->vf_id)
+			fabric = &fcs->fabric;
+		else
+			fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
+
+		/**
+		 * drop frame if vfid is unknown
+		 */
+		if (!fabric) {
+			bfa_assert(0);
+			bfa_stats(fcs, uf.vfid_unknown);
+			bfa_uf_free(uf);
+			return;
+		}
+
+		/**
+		 * skip vft header
+		 */
+		fchs = (struct fchs_s *) (vft + 1);
+		len -= sizeof(struct fc_vft_s);
+
+		bfa_trc(fcs, vft->vf_id);
+	} else {
+		bfa_stats(fcs, uf.untagged);
+		fabric = &fcs->fabric;
+	}
+
+	bfa_trc(fcs, ((u32 *) fchs)[0]);
+	bfa_trc(fcs, ((u32 *) fchs)[1]);
+	bfa_trc(fcs, ((u32 *) fchs)[2]);
+	bfa_trc(fcs, ((u32 *) fchs)[3]);
+	bfa_trc(fcs, ((u32 *) fchs)[4]);
+	bfa_trc(fcs, ((u32 *) fchs)[5]);
+	bfa_trc(fcs, len);
+
+	bfa_fcs_fabric_uf_recv(fabric, fchs, len);
+	bfa_uf_free(uf);
+}
+
+void
+bfa_fcs_uf_attach(struct bfa_fcs_s *fcs)
+{
+	bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
+}
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
new file mode 100644
index 0000000..d75045d
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -0,0 +1,779 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCS_H__
+#define __BFA_FCS_H__
+
+#include "bfa_cs.h"
+#include "bfa_defs.h"
+#include "bfa_defs_fcs.h"
+#include "bfa_modules.h"
+#include "bfa_fc.h"
+
+#define BFA_FCS_OS_STR_LEN		64
+
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+	BFA_TRC_FCS_FCS		= 1,
+	BFA_TRC_FCS_PORT	= 2,
+	BFA_TRC_FCS_RPORT	= 3,
+	BFA_TRC_FCS_FCPIM	= 4,
+};
+
+
+struct bfa_fcs_s;
+
+#define __fcs_min_cfg(__fcs)       ((__fcs)->min_cfg)
+void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);
+
+#define BFA_FCS_BRCD_SWITCH_OUI  0x051e
+#define N2N_LOCAL_PID	    0x010000
+#define N2N_REMOTE_PID		0x020000
+#define	BFA_FCS_RETRY_TIMEOUT 2000
+#define BFA_FCS_PID_IS_WKA(pid)  ((bfa_os_ntoh3b(pid) > 0xFFF000) ?  1 : 0)
+
+
+
+struct bfa_fcs_lport_ns_s {
+	bfa_sm_t        sm;		/*  state machine */
+	struct bfa_timer_s timer;
+	struct bfa_fcs_lport_s *port;	/*  parent port */
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_fcxp_wqe_s fcxp_wqe;
+};
+
+
+struct bfa_fcs_lport_scn_s {
+	bfa_sm_t        sm;		/*  state machine */
+	struct bfa_timer_s timer;
+	struct bfa_fcs_lport_s *port;	/*  parent port */
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_fcxp_wqe_s fcxp_wqe;
+};
+
+
+struct bfa_fcs_lport_fdmi_s {
+	bfa_sm_t        sm;		/*  state machine */
+	struct bfa_timer_s timer;
+	struct bfa_fcs_lport_ms_s *ms;	/*  parent ms */
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_fcxp_wqe_s fcxp_wqe;
+	u8	retry_cnt;	/*  retry count */
+	u8	rsvd[3];
+};
+
+
+struct bfa_fcs_lport_ms_s {
+	bfa_sm_t        sm;		/*  state machine */
+	struct bfa_timer_s timer;
+	struct bfa_fcs_lport_s *port;	/*  parent port */
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_fcxp_wqe_s fcxp_wqe;
+	struct bfa_fcs_lport_fdmi_s fdmi;	/*  FDMI component of MS */
+	u8         retry_cnt;	/*  retry count */
+	u8	rsvd[3];
+};
+
+
+struct bfa_fcs_lport_fab_s {
+	struct bfa_fcs_lport_ns_s ns;	/*  NS component of port */
+	struct bfa_fcs_lport_scn_s scn;	/*  scn component of port */
+	struct bfa_fcs_lport_ms_s ms;	/*  MS component of port */
+};
+
+#define	MAX_ALPA_COUNT	127
+
+struct bfa_fcs_lport_loop_s {
+	u8         num_alpa;	/*  Num of ALPA entries in the map */
+	u8         alpa_pos_map[MAX_ALPA_COUNT];	/*  ALPA Positional
+							 *Map */
+	struct bfa_fcs_lport_s *port;	/*  parent port */
+};
+
+struct bfa_fcs_lport_n2n_s {
+	u32        rsvd;
+	u16        reply_oxid;	/*  ox_id from the req flogi to be
+					 *used in flogi acc */
+	wwn_t           rem_port_wwn;	/*  Attached port's wwn */
+};
+
+
+union bfa_fcs_lport_topo_u {
+	struct bfa_fcs_lport_fab_s pfab;
+	struct bfa_fcs_lport_loop_s ploop;
+	struct bfa_fcs_lport_n2n_s pn2n;
+};
+
+
+struct bfa_fcs_lport_s {
+	struct list_head         qe;	/*  used by port/vport */
+	bfa_sm_t               sm;	/*  state machine */
+	struct bfa_fcs_fabric_s *fabric;	/*  parent fabric */
+	struct bfa_lport_cfg_s  port_cfg;	/*  port configuration */
+	struct bfa_timer_s link_timer;	/*  timer for link offline */
+	u32        pid:24;	/*  FC address */
+	u8         lp_tag;		/*  lport tag */
+	u16        num_rports;	/*  Num of r-ports */
+	struct list_head         rport_q; /*  queue of discovered r-ports */
+	struct bfa_fcs_s *fcs;	/*  FCS instance */
+	union bfa_fcs_lport_topo_u port_topo;	/*  fabric/loop/n2n details */
+	struct bfad_port_s *bfad_port;	/*  driver peer instance */
+	struct bfa_fcs_vport_s *vport;	/*  NULL for base ports */
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_fcxp_wqe_s fcxp_wqe;
+	struct bfa_lport_stats_s stats;
+	struct bfa_wc_s        wc;	/*  waiting counter for events */
+};
+#define BFA_FCS_GET_HAL_FROM_PORT(port)  (port->fcs->bfa)
+#define BFA_FCS_GET_NS_FROM_PORT(port)  (&port->port_topo.pfab.ns)
+#define BFA_FCS_GET_SCN_FROM_PORT(port)  (&port->port_topo.pfab.scn)
+#define BFA_FCS_GET_MS_FROM_PORT(port)  (&port->port_topo.pfab.ms)
+#define BFA_FCS_GET_FDMI_FROM_PORT(port)  (&port->port_topo.pfab.ms.fdmi)
+#define	BFA_FCS_VPORT_IS_INITIATOR_MODE(port) \
+		(port->port_cfg.roles & BFA_LPORT_ROLE_FCP_IM)
+
+/*
+ * forward declaration
+ */
+struct bfad_vf_s;
+
+enum bfa_fcs_fabric_type {
+	BFA_FCS_FABRIC_UNKNOWN = 0,
+	BFA_FCS_FABRIC_SWITCHED = 1,
+	BFA_FCS_FABRIC_N2N = 2,
+};
+
+
+struct bfa_fcs_fabric_s {
+	struct list_head   qe;		/*  queue element */
+	bfa_sm_t	 sm;		/*  state machine */
+	struct bfa_fcs_s *fcs;		/*  FCS instance */
+	struct bfa_fcs_lport_s  bport;	/*  base logical port */
+	enum bfa_fcs_fabric_type fab_type; /*  fabric type */
+	enum bfa_port_type oper_type;	/*  current link topology */
+	u8         is_vf;		/*  is virtual fabric? */
+	u8         is_npiv;	/*  is NPIV supported ? */
+	u8         is_auth;	/*  is Security/Auth supported ? */
+	u16        bb_credit;	/*  BB credit from fabric */
+	u16        vf_id;		/*  virtual fabric ID */
+	u16        num_vports;	/*  num vports */
+	u16        rsvd;
+	struct list_head         vport_q;	/*  queue of virtual ports */
+	struct list_head         vf_q;	/*  queue of virtual fabrics */
+	struct bfad_vf_s      *vf_drv;	/*  driver vf structure */
+	struct bfa_timer_s link_timer;	/*  Link Failure timer. Vport */
+	wwn_t           fabric_name;	/*  attached fabric name */
+	bfa_boolean_t   auth_reqd;	/*  authentication required	*/
+	struct bfa_timer_s delay_timer;	/*  delay timer		*/
+	union {
+		u16        swp_vfid;/*  switch port VF id		*/
+	} event_arg;
+	struct bfa_wc_s        wc;	/*  wait counter for delete	*/
+	struct bfa_vf_stats_s	stats;	/*  fabric/vf stats		*/
+	struct bfa_lps_s	*lps;	/*  lport login services	*/
+	u8	fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ];
+					/*  attached fabric's ip addr  */
+};
+
+#define bfa_fcs_fabric_npiv_capable(__f)    ((__f)->is_npiv)
+#define bfa_fcs_fabric_is_switched(__f)			\
+	((__f)->fab_type == BFA_FCS_FABRIC_SWITCHED)
+
+/**
+ *   The design calls for a single implementation of base fabric and vf.
+ */
+#define bfa_fcs_vf_t struct bfa_fcs_fabric_s
+
+struct bfa_vf_event_s {
+	u32        undefined;
+};
+
+struct bfa_fcs_s;
+struct bfa_fcs_fabric_s;
+
+/*
+ * @todo : need to move to a global config file.
+ * Maximum Rports supported per port (physical/logical).
+ */
+#define BFA_FCS_MAX_RPORTS_SUPP  256	/* @todo : tentative value */
+
+#define bfa_fcs_lport_t struct bfa_fcs_lport_s
+
+/**
+ * Symbolic Name related defines
+ *  Total bytes 255.
+ *  Physical Port's symbolic name 128 bytes.
+ *  For Vports, Vport's symbolic name is appended to the Physical port's
+ *  Symbolic Name.
+ *
+ *  Physical Port's symbolic name Format : (Total 128 bytes)
+ *  Adapter Model number/name : 12 bytes
+ *  Driver Version     : 10 bytes
+ *  Host Machine Name  : 30 bytes
+ *  Host OS Info	   : 48 bytes
+ *  Host OS PATCH Info : 16 bytes
+ *  ( remaining 12 bytes reserved to be used for separator)
+ */
+#define BFA_FCS_PORT_SYMBNAME_SEPARATOR			" | "
+
+#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ			12
+#define BFA_FCS_PORT_SYMBNAME_VERSION_SZ		10
+#define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ		30
+#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ			48
+#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ		16
+
+/**
+ * Get FC port ID for a logical port.
+ */
+#define bfa_fcs_lport_get_fcid(_lport)	((_lport)->pid)
+#define bfa_fcs_lport_get_pwwn(_lport)	((_lport)->port_cfg.pwwn)
+#define bfa_fcs_lport_get_nwwn(_lport)	((_lport)->port_cfg.nwwn)
+#define bfa_fcs_lport_get_psym_name(_lport)	((_lport)->port_cfg.sym_name)
+#define bfa_fcs_lport_is_initiator(_lport)			\
+	((_lport)->port_cfg.roles & BFA_LPORT_ROLE_FCP_IM)
+#define bfa_fcs_lport_get_nrports(_lport)	\
+	((_lport) ? (_lport)->num_rports : 0)
+
+static inline struct bfad_port_s *
+bfa_fcs_lport_get_drvport(struct bfa_fcs_lport_s *port)
+{
+	return port->bfad_port;
+}
+
+#define bfa_fcs_lport_get_opertype(_lport)	((_lport)->fabric->oper_type)
+#define bfa_fcs_lport_get_fabric_name(_lport)	((_lport)->fabric->fabric_name)
+#define bfa_fcs_lport_get_fabric_ipaddr(_lport)		\
+		((_lport)->fabric->fabric_ip_addr)
+
+/**
+ * bfa fcs port public functions
+ */
+
+bfa_boolean_t   bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port);
+struct bfa_fcs_lport_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs);
+void bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
+			      wwn_t rport_wwns[], int *nrports);
+
+wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
+			      int index, int nrports, bfa_boolean_t bwwn);
+
+struct bfa_fcs_lport_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,
+					    u16 vf_id, wwn_t lpwwn);
+
+void bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
+			    struct bfa_lport_info_s *port_info);
+void bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s *port,
+			    struct bfa_lport_attr_s *port_attr);
+void bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
+			     struct bfa_lport_stats_s *port_stats);
+void bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port);
+enum bfa_port_speed bfa_fcs_lport_get_rport_max_speed(
+			struct bfa_fcs_lport_s *port);
+
+/* MS FCS routines */
+void bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port);
+
+/* FDMI FCS routines */
+void bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms);
+void bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms);
+void bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms);
+void bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport, struct fchs_s *fchs,
+				     u16 len);
+void bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
+			u16 vf_id, struct bfa_fcs_vport_s *vport);
+void bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
+				struct bfa_lport_cfg_s *port_cfg);
+void            bfa_fcs_lport_online(struct bfa_fcs_lport_s *port);
+void            bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port);
+void            bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port);
+struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid(
+		struct bfa_fcs_lport_s *port, u32 pid);
+struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pwwn(
+		struct bfa_fcs_lport_s *port, wwn_t pwwn);
+struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_nwwn(
+		struct bfa_fcs_lport_s *port, wwn_t nwwn);
+void            bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port,
+				       struct bfa_fcs_rport_s *rport);
+void            bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port,
+				       struct bfa_fcs_rport_s *rport);
+void bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs);
+void            bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port);
+void            bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
+					      struct fchs_s *rx_frame, u32 len);
+
+struct bfa_fcs_vport_s {
+	struct list_head		qe;		/*  queue elem	*/
+	bfa_sm_t		sm;		/*  state machine	*/
+	bfa_fcs_lport_t		lport;		/*  logical port	*/
+	struct bfa_timer_s	timer;
+	struct bfad_vport_s	*vport_drv;	/*  Driver private	*/
+	struct bfa_vport_stats_s vport_stats;	/*  vport statistics	*/
+	struct bfa_lps_s	*lps;		/*  Lport login service*/
+	int			fdisc_retries;
+};
+
+#define bfa_fcs_vport_get_port(vport)			\
+	((struct bfa_fcs_lport_s  *)(&vport->port))
+
+/**
+ * bfa fcs vport public functions
+ */
+bfa_status_t bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport,
+				  struct bfa_fcs_s *fcs, u16 vf_id,
+				  struct bfa_lport_cfg_s *port_cfg,
+				  struct bfad_vport_s *vport_drv);
+bfa_status_t bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport,
+				      struct bfa_fcs_s *fcs, u16 vf_id,
+				      struct bfa_lport_cfg_s *port_cfg,
+				      struct bfad_vport_s *vport_drv);
+bfa_boolean_t bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport);
+bfa_status_t bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport);
+bfa_status_t bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport);
+bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
+			    struct bfa_vport_attr_s *vport_attr);
+void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
+			     struct bfa_vport_stats_s *vport_stats);
+void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport);
+struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs,
+					     u16 vf_id, wwn_t vpwwn);
+void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport);
+
+#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT	90	/* in secs */
+#define BFA_FCS_RPORT_MAX_RETRIES	(5)
+
+/*
+ * forward declarations
+ */
+struct bfad_rport_s;
+
+struct bfa_fcs_itnim_s;
+struct bfa_fcs_tin_s;
+struct bfa_fcs_iprp_s;
+
+/* Rport Features (RPF) */
+struct bfa_fcs_rpf_s {
+	bfa_sm_t	sm;	/*  state machine */
+	struct bfa_fcs_rport_s *rport;	/*  parent rport */
+	struct bfa_timer_s	timer;	/*  general purpose timer */
+	struct bfa_fcxp_s	*fcxp;	/*  FCXP needed for discarding */
+	struct bfa_fcxp_wqe_s	fcxp_wqe; /*  fcxp wait queue element */
+	int	rpsc_retries;	/*  max RPSC retry attempts */
+	enum bfa_port_speed	rpsc_speed;
+	/*  Current Speed from RPSC. O if RPSC fails */
+	enum bfa_port_speed	assigned_speed;
+	/**
+	 * Speed assigned by the user.  will be used if RPSC is
+	 * not supported by the rport.
+	 */
+};
+
+struct bfa_fcs_rport_s {
+	struct list_head	qe;	/*  used by port/vport */
+	struct bfa_fcs_lport_s *port;	/*  parent FCS port */
+	struct bfa_fcs_s	*fcs;	/*  fcs instance */
+	struct bfad_rport_s	*rp_drv;	/*  driver peer instance */
+	u32	pid;	/*  port ID of rport */
+	u16	maxfrsize;	/*  maximum frame size */
+	u16	reply_oxid;	/*  OX_ID of inbound requests */
+	enum fc_cos	fc_cos;	/*  FC classes of service supp */
+	bfa_boolean_t	cisc;	/*  CISC capable device */
+	bfa_boolean_t	prlo;	/*  processing prlo or LOGO */
+	wwn_t	pwwn;	/*  port wwn of rport */
+	wwn_t	nwwn;	/*  node wwn of rport */
+	struct bfa_rport_symname_s psym_name; /*  port symbolic name  */
+	bfa_sm_t	sm;		/*  state machine */
+	struct bfa_timer_s timer;	/*  general purpose timer */
+	struct bfa_fcs_itnim_s *itnim;	/*  ITN initiator mode role */
+	struct bfa_fcs_tin_s *tin;	/*  ITN initiator mode role */
+	struct bfa_fcs_iprp_s *iprp;	/*  IP/FC role */
+	struct bfa_rport_s *bfa_rport;	/*  BFA Rport */
+	struct bfa_fcxp_s *fcxp;	/*  FCXP needed for discarding */
+	int	plogi_retries;	/*  max plogi retry attempts */
+	int	ns_retries;	/*  max NS query retry attempts */
+	struct bfa_fcxp_wqe_s	fcxp_wqe; /*  fcxp wait queue element */
+	struct bfa_rport_stats_s stats;	/*  rport stats */
+	enum bfa_rport_function	scsi_function;  /*  Initiator/Target */
+	struct bfa_fcs_rpf_s rpf;	/* Rport features module */
+};
+
+static inline struct bfa_rport_s *
+bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)
+{
+	return rport->bfa_rport;
+}
+
+/**
+ * bfa fcs rport API functions
+ */
+bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn,
+			       struct bfa_fcs_rport_s *rport,
+			       struct bfad_rport_s *rport_drv);
+bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+			    struct bfa_rport_attr_s *attr);
+void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
+			     struct bfa_rport_stats_s *stats);
+void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport);
+struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port,
+					     wwn_t rpwwn);
+struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
+	struct bfa_fcs_lport_s *port, wwn_t rnwwn);
+void bfa_fcs_rport_set_del_timeout(u8 rport_tmo);
+
+void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
+			     enum bfa_port_speed speed);
+void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
+	 struct fchs_s *fchs, u16 len);
+void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);
+
+struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_lport_s *port,
+	 u32 pid);
+void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
+			 struct fc_logi_s *plogi_rsp);
+void bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port,
+				struct fchs_s *rx_fchs,
+				struct fc_logi_s *plogi);
+void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
+			 struct fc_logi_s *plogi);
+void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id);
+
+void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport);
+int  bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport);
+struct bfa_fcs_rport_s *bfa_fcs_rport_create_by_wwn(
+			struct bfa_fcs_lport_s *port, wwn_t wwn);
+void  bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport);
+void  bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport);
+void  bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport);
+
+/*
+ * forward declarations
+ */
+struct bfad_itnim_s;
+
+struct bfa_fcs_itnim_s {
+	bfa_sm_t		sm;		/*  state machine */
+	struct bfa_fcs_rport_s	*rport;		/*  parent remote rport  */
+	struct bfad_itnim_s	*itnim_drv;	/*  driver peer instance */
+	struct bfa_fcs_s	*fcs;		/*  fcs instance	*/
+	struct bfa_timer_s	timer;		/*  timer functions	*/
+	struct bfa_itnim_s	*bfa_itnim;	/*  BFA itnim struct	*/
+	u32		prli_retries;	/*  max prli retry attempts */
+	bfa_boolean_t		seq_rec;	/*  seq recovery support */
+	bfa_boolean_t		rec_support;	/*  REC supported	*/
+	bfa_boolean_t		conf_comp;	/*  FCP_CONF	support */
+	bfa_boolean_t		task_retry_id;	/*  task retry id supp	*/
+	struct bfa_fcxp_wqe_s	fcxp_wqe;	/*  wait qelem for fcxp  */
+	struct bfa_fcxp_s	*fcxp;		/*  FCXP in use	*/
+	struct bfa_itnim_stats_s	stats;	/*  itn statistics	*/
+};
+#define bfa_fcs_fcxp_alloc(__fcs)	\
+	bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL)
+
+#define bfa_fcs_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg) \
+	bfa_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg, \
+					NULL, 0, 0, NULL, NULL, NULL, NULL)
+
+static inline struct bfad_port_s *
+bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->port->bfad_port;
+}
+
+
+static inline struct bfa_fcs_lport_s *
+bfa_fcs_itnim_get_port(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->port;
+}
+
+
+static inline wwn_t
+bfa_fcs_itnim_get_nwwn(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->nwwn;
+}
+
+
+static inline wwn_t
+bfa_fcs_itnim_get_pwwn(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->pwwn;
+}
+
+
+static inline u32
+bfa_fcs_itnim_get_fcid(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->pid;
+}
+
+
+static inline	u32
+bfa_fcs_itnim_get_maxfrsize(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->maxfrsize;
+}
+
+
+static inline	enum fc_cos
+bfa_fcs_itnim_get_cos(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->fc_cos;
+}
+
+
+static inline struct bfad_itnim_s *
+bfa_fcs_itnim_get_drvitn(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->itnim_drv;
+}
+
+
+static inline struct bfa_itnim_s *
+bfa_fcs_itnim_get_halitn(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->bfa_itnim;
+}
+
+/**
+ * bfa fcs FCP Initiator mode API functions
+ */
+void bfa_fcs_itnim_get_attr(struct bfa_fcs_itnim_s *itnim,
+			    struct bfa_itnim_attr_s *attr);
+void bfa_fcs_itnim_get_stats(struct bfa_fcs_itnim_s *itnim,
+			     struct bfa_itnim_stats_s *stats);
+struct bfa_fcs_itnim_s *bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port,
+					     wwn_t rpwwn);
+bfa_status_t bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
+				    struct bfa_itnim_attr_s *attr);
+bfa_status_t bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
+				     struct bfa_itnim_stats_s *stats);
+bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port,
+				       wwn_t rpwwn);
+struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim);
+bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
+			struct fchs_s *fchs, u16 len);
+
+#define	BFA_FCS_FDMI_SUPORTED_SPEEDS  (FDMI_TRANS_SPEED_1G  |	\
+				       FDMI_TRANS_SPEED_2G |	\
+				       FDMI_TRANS_SPEED_4G |	\
+				       FDMI_TRANS_SPEED_8G)
+
+/*
+ * HBA Attribute Block : BFA internal representation. Note : Some variable
+ * sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based
+ * on this the size has been reduced to 16 bytes from the standard's 64 bytes.
+ */
+struct bfa_fcs_fdmi_hba_attr_s {
+	wwn_t           node_name;
+	u8         manufacturer[64];
+	u8         serial_num[64];
+	u8         model[16];
+	u8         model_desc[256];
+	u8         hw_version[8];
+	u8         driver_version[8];
+	u8         option_rom_ver[BFA_VERSION_LEN];
+	u8         fw_version[8];
+	u8         os_name[256];
+	u32        max_ct_pyld;
+};
+
+/*
+ * Port Attribute Block
+ */
+struct bfa_fcs_fdmi_port_attr_s {
+	u8         supp_fc4_types[32];	/* supported FC4 types */
+	u32        supp_speed;	/* supported speed */
+	u32        curr_speed;	/* current Speed */
+	u32        max_frm_size;	/* max frame size */
+	u8         os_device_name[256];	/* OS device Name */
+	u8         host_name[256];	/* host name */
+};
+
+struct bfa_fcs_stats_s {
+	struct {
+		u32	untagged; /*  untagged receive frames */
+		u32	tagged;	/*  tagged receive frames */
+		u32	vfid_unknown;	/*  VF id is unknown */
+	} uf;
+};
+
+struct bfa_fcs_driver_info_s {
+	u8	 version[BFA_VERSION_LEN];		/* Driver Version */
+	u8	 host_machine_name[BFA_FCS_OS_STR_LEN];
+	u8	 host_os_name[BFA_FCS_OS_STR_LEN]; /* OS name and version */
+	u8	 host_os_patch[BFA_FCS_OS_STR_LEN]; /* patch or service pack */
+	u8	 os_device_name[BFA_FCS_OS_STR_LEN]; /* Driver Device Name */
+};
+
+struct bfa_fcs_s {
+	struct bfa_s	  *bfa;	/*  corresponding BFA bfa instance */
+	struct bfad_s	      *bfad; /*  corresponding BDA driver instance */
+	struct bfa_trc_mod_s  *trcmod;	/*  tracing module */
+	bfa_boolean_t	vf_enabled;	/*  VF mode is enabled */
+	bfa_boolean_t	fdmi_enabled;	/*  FDMI is enabled */
+	bfa_boolean_t min_cfg;		/* min cfg enabled/disabled */
+	u16	port_vfid;	/*  port default VF ID */
+	struct bfa_fcs_driver_info_s driver_info;
+	struct bfa_fcs_fabric_s fabric; /*  base fabric state machine */
+	struct bfa_fcs_stats_s	stats;	/*  FCS statistics */
+	struct bfa_wc_s		wc;	/*  waiting counter */
+};
+
+/*
+ * bfa fcs API functions
+ */
+void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,
+		    struct bfad_s *bfad,
+		    bfa_boolean_t min_cfg);
+void bfa_fcs_init(struct bfa_fcs_s *fcs);
+void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
+			      struct bfa_fcs_driver_info_s *driver_info);
+void bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable);
+void bfa_fcs_exit(struct bfa_fcs_s *fcs);
+void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod);
+void		bfa_fcs_start(struct bfa_fcs_s *fcs);
+
+/**
+ * bfa fcs vf public functions
+ */
+bfa_status_t bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id);
+bfa_status_t bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs);
+bfa_status_t bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs,
+			       u16 vf_id, struct bfa_lport_cfg_s *port_cfg,
+			       struct bfad_vf_s *vf_drv);
+bfa_status_t bfa_fcs_vf_delete(bfa_fcs_vf_t *vf);
+void bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
+void bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
+void bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr);
+void bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf,
+			  struct bfa_vf_stats_s *vf_stats);
+void bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf);
+void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
+bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
+u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);
+
+/*
+ * fabric protected interface functions
+ */
+void bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
+	struct bfa_fcs_vport_s *vport);
+void bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
+	struct bfa_fcs_vport_s *vport);
+int bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric);
+struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup(
+		struct bfa_fcs_fabric_s *fabric, wwn_t pwwn);
+void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
+		struct fchs_s *fchs, u16 len);
+bfa_boolean_t	bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric);
+bfa_boolean_t	bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric);
+enum bfa_port_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric);
+void	bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
+void	bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric);
+bfa_status_t	bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf,
+			struct bfa_fcs_s *fcs, struct bfa_lport_cfg_s *port_cfg,
+			struct bfad_vf_s *vf_drv);
+void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
+	       wwn_t fabric_name);
+u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);
+void bfa_fcs_port_attach(struct bfa_fcs_s *fcs);
+
+/**
+ * BFA FCS callback interfaces
+ */
+
+/**
+ * fcb Main fcs callbacks
+ */
+
+struct bfad_port_s;
+struct bfad_vf_s;
+struct bfad_vport_s;
+struct bfad_rport_s;
+
+/**
+ * lport callbacks
+ */
+struct bfad_port_s *bfa_fcb_lport_new(struct bfad_s *bfad,
+				      struct bfa_fcs_lport_s *port,
+				      enum bfa_lport_role roles,
+				      struct bfad_vf_s *vf_drv,
+				      struct bfad_vport_s *vp_drv);
+void bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles,
+			  struct bfad_vf_s *vf_drv,
+			  struct bfad_vport_s *vp_drv);
+
+/**
+ * vport callbacks
+ */
+void bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s);
+
+/**
+ * rport callbacks
+ */
+bfa_status_t bfa_fcb_rport_alloc(struct bfad_s *bfad,
+				 struct bfa_fcs_rport_s **rport,
+				 struct bfad_rport_s **rport_drv);
+
+/**
+ * itnim callbacks
+ */
+void bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim,
+			 struct bfad_itnim_s **itnim_drv);
+void bfa_fcb_itnim_free(struct bfad_s *bfad,
+			struct bfad_itnim_s *itnim_drv);
+void bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv);
+void bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv);
+
+#endif /* __BFA_FCS_H__ */
diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c
new file mode 100644
index 0000000..569dfef
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c
@@ -0,0 +1,783 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+/**
+ *  fcpim.c - FCP initiator mode i-t nexus state machine
+ */
+
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
+#include "bfad_drv.h"
+#include "bfad_im.h"
+
+BFA_TRC_FILE(FCS, FCPIM);
+
+/*
+ * forward declarations
+ */
+static void	bfa_fcs_itnim_timeout(void *arg);
+static void	bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
+static void	bfa_fcs_itnim_send_prli(void *itnim_cbarg,
+					struct bfa_fcxp_s *fcxp_alloced);
+static void	bfa_fcs_itnim_prli_response(void *fcsarg,
+			 struct bfa_fcxp_s *fcxp, void *cbarg,
+			    bfa_status_t req_status, u32 rsp_len,
+			    u32 resid_len, struct fchs_s *rsp_fchs);
+
+/**
+ *  fcs_itnim_sm FCS itnim state machine events
+ */
+
+enum bfa_fcs_itnim_event {
+	BFA_FCS_ITNIM_SM_ONLINE = 1,	/*  rport online event */
+	BFA_FCS_ITNIM_SM_OFFLINE = 2,	/*  rport offline */
+	BFA_FCS_ITNIM_SM_FRMSENT = 3,	/*  prli frame is sent */
+	BFA_FCS_ITNIM_SM_RSP_OK = 4,	/*  good response */
+	BFA_FCS_ITNIM_SM_RSP_ERROR = 5,	/*  error response */
+	BFA_FCS_ITNIM_SM_TIMEOUT = 6,	/*  delay timeout */
+	BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /*  BFA online callback */
+	BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /*  BFA offline callback */
+	BFA_FCS_ITNIM_SM_INITIATOR = 9,	/*  rport is initiator */
+	BFA_FCS_ITNIM_SM_DELETE = 10,	/*  delete event from rport */
+	BFA_FCS_ITNIM_SM_PRLO = 11,	/*  delete event from rport */
+};
+
+static void	bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
+					 enum bfa_fcs_itnim_event event);
+static void	bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
+					   enum bfa_fcs_itnim_event event);
+static void	bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
+				      enum bfa_fcs_itnim_event event);
+static void	bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
+					    enum bfa_fcs_itnim_event event);
+static void	bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
+					    enum bfa_fcs_itnim_event event);
+static void	bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
+					enum bfa_fcs_itnim_event event);
+static void	bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
+					     enum bfa_fcs_itnim_event event);
+static void	bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
+					   enum bfa_fcs_itnim_event event);
+
+static struct bfa_sm_table_s itnim_sm_table[] = {
+	{BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE},
+	{BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND},
+	{BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT},
+	{BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY},
+	{BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE},
+	{BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE},
+	{BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE},
+	{BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR},
+};
+
+/**
+ *  fcs_itnim_sm FCS itnim state machine
+ */
+
+static void
+bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
+		 enum bfa_fcs_itnim_event event)
+{
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	bfa_trc(itnim->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_ITNIM_SM_ONLINE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
+		itnim->prli_retries = 0;
+		bfa_fcs_itnim_send_prli(itnim, NULL);
+		break;
+
+	case BFA_FCS_ITNIM_SM_OFFLINE:
+		bfa_fcs_rport_itnim_ack(itnim->rport);
+		break;
+
+	case BFA_FCS_ITNIM_SM_INITIATOR:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
+		break;
+
+	case BFA_FCS_ITNIM_SM_DELETE:
+		bfa_fcs_itnim_free(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->fcs, event);
+	}
+
+}
+
+static void
+bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
+		 enum bfa_fcs_itnim_event event)
+{
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	bfa_trc(itnim->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_ITNIM_SM_FRMSENT:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli);
+		break;
+
+	case BFA_FCS_ITNIM_SM_INITIATOR:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
+		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
+		break;
+
+	case BFA_FCS_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
+		bfa_fcs_rport_itnim_ack(itnim->rport);
+		break;
+
+	case BFA_FCS_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
+		bfa_fcs_itnim_free(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
+		 enum bfa_fcs_itnim_event event)
+{
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	bfa_trc(itnim->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_ITNIM_SM_RSP_OK:
+		if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR) {
+			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
+		} else {
+			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
+			bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
+		}
+		break;
+
+	case BFA_FCS_ITNIM_SM_RSP_ERROR:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry);
+		bfa_timer_start(itnim->fcs->bfa, &itnim->timer,
+				bfa_fcs_itnim_timeout, itnim,
+				BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case BFA_FCS_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_fcxp_discard(itnim->fcxp);
+		bfa_fcs_rport_itnim_ack(itnim->rport);
+		break;
+
+	case BFA_FCS_ITNIM_SM_INITIATOR:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
+		bfa_fcxp_discard(itnim->fcxp);
+		break;
+
+	case BFA_FCS_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_fcxp_discard(itnim->fcxp);
+		bfa_fcs_itnim_free(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
+			    enum bfa_fcs_itnim_event event)
+{
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	bfa_trc(itnim->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_ITNIM_SM_TIMEOUT:
+		if (itnim->prli_retries < BFA_FCS_RPORT_MAX_RETRIES) {
+			itnim->prli_retries++;
+			bfa_trc(itnim->fcs, itnim->prli_retries);
+			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
+			bfa_fcs_itnim_send_prli(itnim, NULL);
+		} else {
+			/* invoke target offline */
+			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+			bfa_fcs_rport_logo_imp(itnim->rport);
+		}
+		break;
+
+
+	case BFA_FCS_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_timer_stop(&itnim->timer);
+		bfa_fcs_rport_itnim_ack(itnim->rport);
+		break;
+
+	case BFA_FCS_ITNIM_SM_INITIATOR:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
+		bfa_timer_stop(&itnim->timer);
+		break;
+
+	case BFA_FCS_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_timer_stop(&itnim->timer);
+		bfa_fcs_itnim_free(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
+			    enum bfa_fcs_itnim_event event)
+{
+	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
+	char	lpwwn_buf[BFA_STRING_32];
+	char	rpwwn_buf[BFA_STRING_32];
+
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	bfa_trc(itnim->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_ITNIM_SM_HCB_ONLINE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
+		bfa_fcb_itnim_online(itnim->itnim_drv);
+		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
+		wwn2str(rpwwn_buf, itnim->rport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+		"Target (WWN = %s) is online for initiator (WWN = %s)\n",
+		rpwwn_buf, lpwwn_buf);
+		break;
+
+	case BFA_FCS_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_itnim_offline(itnim->bfa_itnim);
+		bfa_fcs_rport_itnim_ack(itnim->rport);
+		break;
+
+	case BFA_FCS_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_fcs_itnim_free(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
+		 enum bfa_fcs_itnim_event event)
+{
+	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
+	char	lpwwn_buf[BFA_STRING_32];
+	char	rpwwn_buf[BFA_STRING_32];
+
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	bfa_trc(itnim->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
+		bfa_fcb_itnim_offline(itnim->itnim_drv);
+		bfa_itnim_offline(itnim->bfa_itnim);
+		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
+		wwn2str(rpwwn_buf, itnim->rport->pwwn);
+		if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE)
+			BFA_LOG(KERN_ERR, bfad, log_level,
+			"Target (WWN = %s) connectivity lost for "
+			"initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);
+		else
+			BFA_LOG(KERN_INFO, bfad, log_level,
+			"Target (WWN = %s) offlined by initiator (WWN = %s)\n",
+			rpwwn_buf, lpwwn_buf);
+		break;
+
+	case BFA_FCS_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_fcs_itnim_free(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
+			     enum bfa_fcs_itnim_event event)
+{
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	bfa_trc(itnim->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_ITNIM_SM_HCB_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_fcs_rport_itnim_ack(itnim->rport);
+		break;
+
+	case BFA_FCS_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_fcs_itnim_free(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->fcs, event);
+	}
+}
+
+/*
+ * This state is set when a discovered rport is also in intiator mode.
+ * This ITN is marked as no_op and is not active and will not be truned into
+ * online state.
+ */
+static void
+bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
+		 enum bfa_fcs_itnim_event event)
+{
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	bfa_trc(itnim->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_fcs_rport_itnim_ack(itnim->rport);
+		break;
+
+	case BFA_FCS_ITNIM_SM_RSP_ERROR:
+	case BFA_FCS_ITNIM_SM_ONLINE:
+	case BFA_FCS_ITNIM_SM_INITIATOR:
+		break;
+
+	case BFA_FCS_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		bfa_fcs_itnim_free(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_itnim_s *itnim = itnim_cbarg;
+	struct bfa_fcs_rport_s *rport = itnim->rport;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
+	struct bfa_fcxp_s *fcxp;
+	int		len;
+
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		itnim->stats.fcxp_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
+				    bfa_fcs_itnim_send_prli, itnim);
+		return;
+	}
+	itnim->fcxp = fcxp;
+
+	len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			    itnim->rport->pid, bfa_fcs_lport_get_fcid(port), 0);
+
+	bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
+		      BFA_FALSE, FC_CLASS_3, len, &fchs,
+		      bfa_fcs_itnim_prli_response, (void *)itnim,
+		      FC_MAX_PDUSZ, FC_ELS_TOV);
+
+	itnim->stats.prli_sent++;
+	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
+}
+
+static void
+bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+			    bfa_status_t req_status, u32 rsp_len,
+			    u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
+	struct fc_els_cmd_s *els_cmd;
+	struct fc_prli_s *prli_resp;
+	struct fc_ls_rjt_s *ls_rjt;
+	struct fc_prli_params_s *sparams;
+
+	bfa_trc(itnim->fcs, req_status);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		itnim->stats.prli_rsp_err++;
+		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
+		return;
+	}
+
+	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+	if (els_cmd->els_code == FC_ELS_ACC) {
+		prli_resp = (struct fc_prli_s *) els_cmd;
+
+		if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) {
+			bfa_trc(itnim->fcs, rsp_len);
+			/*
+			 * Check if this  r-port is also in Initiator mode.
+			 * If so, we need to set this ITN as a no-op.
+			 */
+			if (prli_resp->parampage.servparams.initiator) {
+				bfa_trc(itnim->fcs, prli_resp->parampage.type);
+				itnim->rport->scsi_function =
+					 BFA_RPORT_INITIATOR;
+				itnim->stats.prli_rsp_acc++;
+				bfa_sm_send_event(itnim,
+						  BFA_FCS_ITNIM_SM_RSP_OK);
+				return;
+			}
+
+			itnim->stats.prli_rsp_parse_err++;
+			return;
+		}
+		itnim->rport->scsi_function = BFA_RPORT_TARGET;
+
+		sparams = &prli_resp->parampage.servparams;
+		itnim->seq_rec	     = sparams->retry;
+		itnim->rec_support   = sparams->rec_support;
+		itnim->task_retry_id = sparams->task_retry_id;
+		itnim->conf_comp     = sparams->confirm;
+
+		itnim->stats.prli_rsp_acc++;
+		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
+	} else {
+		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+		bfa_trc(itnim->fcs, ls_rjt->reason_code);
+		bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
+
+		itnim->stats.prli_rsp_rjt++;
+		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
+	}
+}
+
+static void
+bfa_fcs_itnim_timeout(void *arg)
+{
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) arg;
+
+	itnim->stats.timeout++;
+	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
+}
+
+static void
+bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
+{
+	bfa_itnim_delete(itnim->bfa_itnim);
+	bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
+}
+
+
+
+/**
+ *  itnim_public FCS ITNIM public interfaces
+ */
+
+/**
+ *	Called by rport when a new rport is created.
+ *
+ * @param[in] rport	-  remote port.
+ */
+struct bfa_fcs_itnim_s *
+bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct bfa_fcs_itnim_s *itnim;
+	struct bfad_itnim_s   *itnim_drv;
+	struct bfa_itnim_s *bfa_itnim;
+
+	/*
+	 * call bfad to allocate the itnim
+	 */
+	bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv);
+	if (itnim == NULL) {
+		bfa_trc(port->fcs, rport->pwwn);
+		return NULL;
+	}
+
+	/*
+	 * Initialize itnim
+	 */
+	itnim->rport = rport;
+	itnim->fcs = rport->fcs;
+	itnim->itnim_drv = itnim_drv;
+
+	/*
+	 * call BFA to create the itnim
+	 */
+	bfa_itnim =
+		bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
+
+	if (bfa_itnim == NULL) {
+		bfa_trc(port->fcs, rport->pwwn);
+		bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
+		bfa_assert(0);
+		return NULL;
+	}
+
+	itnim->bfa_itnim     = bfa_itnim;
+	itnim->seq_rec	     = BFA_FALSE;
+	itnim->rec_support   = BFA_FALSE;
+	itnim->conf_comp     = BFA_FALSE;
+	itnim->task_retry_id = BFA_FALSE;
+
+	/*
+	 * Set State machine
+	 */
+	bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+
+	return itnim;
+}
+
+/**
+ *	Called by rport to delete  the instance of FCPIM.
+ *
+ * @param[in] rport	-  remote port.
+ */
+void
+bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
+{
+	bfa_trc(itnim->fcs, itnim->rport->pid);
+	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE);
+}
+
+/**
+ * Notification from rport that PLOGI is complete to initiate FC-4 session.
+ */
+void
+bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim)
+{
+	itnim->stats.onlines++;
+
+	if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) {
+		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE);
+	} else {
+		/*
+		 *  For well known addresses, we set the itnim to initiator
+		 *  state
+		 */
+		itnim->stats.initiator++;
+		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
+	}
+}
+
+/**
+ * Called by rport to handle a remote device offline.
+ */
+void
+bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim)
+{
+	itnim->stats.offlines++;
+	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE);
+}
+
+/**
+ * Called by rport when remote port is known to be an initiator from
+ * PRLI received.
+ */
+void
+bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim)
+{
+	bfa_trc(itnim->fcs, itnim->rport->pid);
+	itnim->stats.initiator++;
+	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
+}
+
+/**
+ * Called by rport to check if the itnim is online.
+ */
+bfa_status_t
+bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
+{
+	bfa_trc(itnim->fcs, itnim->rport->pid);
+	switch (bfa_sm_to_state(itnim_sm_table, itnim->sm)) {
+	case BFA_ITNIM_ONLINE:
+	case BFA_ITNIM_INITIATIOR:
+		return BFA_STATUS_OK;
+
+	default:
+		return BFA_STATUS_NO_FCPIM_NEXUS;
+	}
+}
+
+/**
+ * BFA completion callback for bfa_itnim_online().
+ */
+void
+bfa_cb_itnim_online(void *cbarg)
+{
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
+
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
+}
+
+/**
+ * BFA completion callback for bfa_itnim_offline().
+ */
+void
+bfa_cb_itnim_offline(void *cb_arg)
+{
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
+
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
+}
+
+/**
+ * Mark the beginning of PATH TOV handling. IO completion callbacks
+ * are still pending.
+ */
+void
+bfa_cb_itnim_tov_begin(void *cb_arg)
+{
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
+
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+}
+
+/**
+ * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
+ */
+void
+bfa_cb_itnim_tov(void *cb_arg)
+{
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
+	struct bfad_itnim_s *itnim_drv = itnim->itnim_drv;
+
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	itnim_drv->state = ITNIM_STATE_TIMEOUT;
+}
+
+/**
+ *		BFA notification to FCS/driver for second level error recovery.
+ *
+ * Atleast one I/O request has timedout and target is unresponsive to
+ * repeated abort requests. Second level error recovery should be initiated
+ * by starting implicit logout and recovery procedures.
+ */
+void
+bfa_cb_itnim_sler(void *cb_arg)
+{
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
+
+	itnim->stats.sler++;
+	bfa_trc(itnim->fcs, itnim->rport->pwwn);
+	bfa_fcs_rport_logo_imp(itnim->rport);
+}
+
+struct bfa_fcs_itnim_s *
+bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
+{
+	struct bfa_fcs_rport_s *rport;
+	rport = bfa_fcs_rport_lookup(port, rpwwn);
+
+	if (!rport)
+		return NULL;
+
+	bfa_assert(rport->itnim != NULL);
+	return rport->itnim;
+}
+
+bfa_status_t
+bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
+		       struct bfa_itnim_attr_s *attr)
+{
+	struct bfa_fcs_itnim_s *itnim = NULL;
+
+	itnim = bfa_fcs_itnim_lookup(port, rpwwn);
+
+	if (itnim == NULL)
+		return BFA_STATUS_NO_FCPIM_NEXUS;
+
+	attr->state	    = bfa_sm_to_state(itnim_sm_table, itnim->sm);
+	attr->retry	    = itnim->seq_rec;
+	attr->rec_support   = itnim->rec_support;
+	attr->conf_comp	    = itnim->conf_comp;
+	attr->task_retry_id = itnim->task_retry_id;
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
+			struct bfa_itnim_stats_s *stats)
+{
+	struct bfa_fcs_itnim_s *itnim = NULL;
+
+	bfa_assert(port != NULL);
+
+	itnim = bfa_fcs_itnim_lookup(port, rpwwn);
+
+	if (itnim == NULL)
+		return BFA_STATUS_NO_FCPIM_NEXUS;
+
+	bfa_os_memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s));
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
+{
+	struct bfa_fcs_itnim_s *itnim = NULL;
+
+	bfa_assert(port != NULL);
+
+	itnim = bfa_fcs_itnim_lookup(port, rpwwn);
+
+	if (itnim == NULL)
+		return BFA_STATUS_NO_FCPIM_NEXUS;
+
+	bfa_os_memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s));
+	return BFA_STATUS_OK;
+}
+
+void
+bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
+			struct fchs_s *fchs, u16 len)
+{
+	struct fc_els_cmd_s *els_cmd;
+
+	bfa_trc(itnim->fcs, fchs->type);
+
+	if (fchs->type != FC_TYPE_ELS)
+		return;
+
+	els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+	bfa_trc(itnim->fcs, els_cmd->els_code);
+
+	switch (els_cmd->els_code) {
+	case FC_ELS_PRLO:
+		bfa_fcs_rport_prlo(itnim->rport, fchs->ox_id);
+		break;
+
+	default:
+		bfa_assert(0);
+	}
+}
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 35df20e..b522bf3 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -16,23 +16,13 @@
  */
 
 /**
- *  bfa_fcs_port.c BFA FCS port
+ *  bfa_fcs_lport.c BFA FCS port
  */
 
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <fcb/bfa_fcb_port.h>
-#include <bfa_svc.h>
-#include <log/bfa_log_fcs.h>
-#include "fcs.h"
-#include "fcs_lport.h"
-#include "fcs_vport.h"
-#include "fcs_rport.h"
-#include "fcs_fcxp.h"
-#include "fcs_trcmod.h"
-#include "lport_priv.h"
-#include <aen/bfa_aen_lport.h>
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
+#include "bfa_fc.h"
+#include "bfad_drv.h"
 
 BFA_TRC_FILE(FCS, PORT);
 
@@ -40,49 +30,53 @@
  * Forward declarations
  */
 
-static void     bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
-				      enum bfa_lport_aen_event event);
-static void     bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port,
-			struct fchs_s *rx_fchs, u8 reason_code,
-			u8 reason_code_expl);
-static void     bfa_fcs_port_plogi(struct bfa_fcs_port_s *port,
-			struct fchs_s *rx_fchs,
-			struct fc_logi_s *plogi);
-static void     bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_deleted(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_echo(struct bfa_fcs_port_s *port,
+static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
+					 struct fchs_s *rx_fchs, u8 reason_code,
+					 u8 reason_code_expl);
+static void     bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
+			struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
+static void     bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
 			struct fchs_s *rx_fchs,
 			struct fc_echo_s *echo, u16 len);
-static void     bfa_fcs_port_rnid(struct bfa_fcs_port_s *port,
+static void     bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
 			struct fchs_s *rx_fchs,
 			struct fc_rnid_cmd_s *rnid, u16 len);
-static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
+static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
 			struct fc_rnid_general_topology_data_s *gen_topo_data);
 
+static void	bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
+static void	bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
+static void	bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
+
+static void	bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
+static void	bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
+static void	bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
+
 static struct {
-	void            (*init) (struct bfa_fcs_port_s *port);
-	void            (*online) (struct bfa_fcs_port_s *port);
-	void            (*offline) (struct bfa_fcs_port_s *port);
+	void		(*init) (struct bfa_fcs_lport_s *port);
+	void		(*online) (struct bfa_fcs_lport_s *port);
+	void		(*offline) (struct bfa_fcs_lport_s *port);
 } __port_action[] = {
 	{
-	bfa_fcs_port_unknown_init, bfa_fcs_port_unknown_online,
-			bfa_fcs_port_unknown_offline}, {
-	bfa_fcs_port_fab_init, bfa_fcs_port_fab_online,
-			bfa_fcs_port_fab_offline}, {
-	bfa_fcs_port_loop_init, bfa_fcs_port_loop_online,
-			bfa_fcs_port_loop_offline}, {
-bfa_fcs_port_n2n_init, bfa_fcs_port_n2n_online,
-			bfa_fcs_port_n2n_offline},};
+	bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
+			bfa_fcs_lport_unknown_offline}, {
+	bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
+			bfa_fcs_lport_fab_offline}, {
+	bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
+			bfa_fcs_lport_n2n_offline},
+	};
 
 /**
  *  fcs_port_sm FCS logical port state machine
  */
 
-enum bfa_fcs_port_event {
+enum bfa_fcs_lport_event {
 	BFA_FCS_PORT_SM_CREATE = 1,
 	BFA_FCS_PORT_SM_ONLINE = 2,
 	BFA_FCS_PORT_SM_OFFLINE = 3,
@@ -90,27 +84,28 @@
 	BFA_FCS_PORT_SM_DELRPORT = 5,
 };
 
-static void     bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
-				       enum bfa_fcs_port_event event);
-static void     bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port,
-				     enum bfa_fcs_port_event event);
-static void     bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
-				       enum bfa_fcs_port_event event);
-static void     bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
-					enum bfa_fcs_port_event event);
-static void     bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
-					 enum bfa_fcs_port_event event);
+static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
+static void     bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
+static void     bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
+static void     bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
+static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
 
 static void
-bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
-			enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_uninit(
+	struct bfa_fcs_lport_s *port,
+	enum bfa_fcs_lport_event event)
 {
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 	bfa_trc(port->fcs, event);
 
 	switch (event) {
 	case BFA_FCS_PORT_SM_CREATE:
-		bfa_sm_set_state(port, bfa_fcs_port_sm_init);
+		bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
 		break;
 
 	default:
@@ -119,20 +114,21 @@
 }
 
 static void
-bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
+			enum bfa_fcs_lport_event event)
 {
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 	bfa_trc(port->fcs, event);
 
 	switch (event) {
 	case BFA_FCS_PORT_SM_ONLINE:
-		bfa_sm_set_state(port, bfa_fcs_port_sm_online);
-		bfa_fcs_port_online_actions(port);
+		bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
+		bfa_fcs_lport_online_actions(port);
 		break;
 
 	case BFA_FCS_PORT_SM_DELETE:
-		bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
-		bfa_fcs_port_deleted(port);
+		bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+		bfa_fcs_lport_deleted(port);
 		break;
 
 	case BFA_FCS_PORT_SM_OFFLINE:
@@ -144,19 +140,20 @@
 }
 
 static void
-bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
-			enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_online(
+	struct bfa_fcs_lport_s *port,
+	enum bfa_fcs_lport_event event)
 {
 	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe, *qen;
+	struct list_head		*qe, *qen;
 
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 	bfa_trc(port->fcs, event);
 
 	switch (event) {
 	case BFA_FCS_PORT_SM_OFFLINE:
-		bfa_sm_set_state(port, bfa_fcs_port_sm_offline);
-		bfa_fcs_port_offline_actions(port);
+		bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
+		bfa_fcs_lport_offline_actions(port);
 		break;
 
 	case BFA_FCS_PORT_SM_DELETE:
@@ -164,12 +161,12 @@
 		__port_action[port->fabric->fab_type].offline(port);
 
 		if (port->num_rports == 0) {
-			bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
-			bfa_fcs_port_deleted(port);
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+			bfa_fcs_lport_deleted(port);
 		} else {
-			bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
 			list_for_each_safe(qe, qen, &port->rport_q) {
-				rport = (struct bfa_fcs_rport_s *)qe;
+				rport = (struct bfa_fcs_rport_s *) qe;
 				bfa_fcs_rport_delete(rport);
 			}
 		}
@@ -184,29 +181,30 @@
 }
 
 static void
-bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
-			enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_offline(
+	struct bfa_fcs_lport_s *port,
+	enum bfa_fcs_lport_event event)
 {
 	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe, *qen;
+	struct list_head		*qe, *qen;
 
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 	bfa_trc(port->fcs, event);
 
 	switch (event) {
 	case BFA_FCS_PORT_SM_ONLINE:
-		bfa_sm_set_state(port, bfa_fcs_port_sm_online);
-		bfa_fcs_port_online_actions(port);
+		bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
+		bfa_fcs_lport_online_actions(port);
 		break;
 
 	case BFA_FCS_PORT_SM_DELETE:
 		if (port->num_rports == 0) {
-			bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
-			bfa_fcs_port_deleted(port);
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+			bfa_fcs_lport_deleted(port);
 		} else {
-			bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
 			list_for_each_safe(qe, qen, &port->rport_q) {
-				rport = (struct bfa_fcs_rport_s *)qe;
+				rport = (struct bfa_fcs_rport_s *) qe;
 				bfa_fcs_rport_delete(rport);
 			}
 		}
@@ -222,8 +220,9 @@
 }
 
 static void
-bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
-			 enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_deleting(
+	struct bfa_fcs_lport_s *port,
+	enum bfa_fcs_lport_event event)
 {
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 	bfa_trc(port->fcs, event);
@@ -231,8 +230,8 @@
 	switch (event) {
 	case BFA_FCS_PORT_SM_DELRPORT:
 		if (port->num_rports == 0) {
-			bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
-			bfa_fcs_port_deleted(port);
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+			bfa_fcs_lport_deleted(port);
 		}
 		break;
 
@@ -241,74 +240,44 @@
 	}
 }
 
-
-
 /**
  *  fcs_port_pvt
  */
 
-/**
- * Send AEN notification
- */
-static void
-bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
-		      enum bfa_lport_aen_event event)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = port->fcs->logm;
-	enum bfa_port_role role = port->port_cfg.roles;
-	wwn_t           lpwwn = bfa_fcs_port_get_pwwn(port);
-	char            lpwwn_ptr[BFA_STRING_32];
-	char           *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] =
-		{ "Initiator", "Target", "IPFC" };
-
-	wwn2str(lpwwn_ptr, lpwwn);
-
-	bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX);
-
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, event), lpwwn_ptr,
-		role_str[role/2]);
-
-	aen_data.lport.vf_id = port->fabric->vf_id;
-	aen_data.lport.roles = role;
-	aen_data.lport.ppwwn =
-		bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
-	aen_data.lport.lpwwn = lpwwn;
-}
-
 /*
  * Send a LS reject
  */
 static void
-bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
+bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
 			 u8 reason_code, u8 reason_code_expl)
 {
-	struct fchs_s          fchs;
+	struct fchs_s	fchs;
 	struct bfa_fcxp_s *fcxp;
 	struct bfa_rport_s *bfa_rport = NULL;
-	int             len;
+	int		len;
 
+	bfa_trc(port->fcs, rx_fchs->d_id);
 	bfa_trc(port->fcs, rx_fchs->s_id);
 
 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
 	if (!fcxp)
 		return;
 
-	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-			      bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
-			      reason_code, reason_code_expl);
+	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			      rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+			      rx_fchs->ox_id, reason_code, reason_code_expl);
 
 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
-		      BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
-		      FC_MAX_PDUSZ, 0);
+			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+			  FC_MAX_PDUSZ, 0);
 }
 
 /**
  * Process incoming plogi from a remote port.
  */
 static void
-bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
-			struct fc_logi_s *plogi)
+bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
+		struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
 {
 	struct bfa_fcs_rport_s *rport;
 
@@ -328,46 +297,40 @@
 		/*
 		 * send a LS reject
 		 */
-		bfa_fcs_port_send_ls_rjt(port, rx_fchs,
-					 FC_LS_RJT_RSN_PROTOCOL_ERROR,
-					 FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
+		bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
+					FC_LS_RJT_RSN_PROTOCOL_ERROR,
+					FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
 		return;
 	}
 
 	/**
-* Direct Attach P2P mode : verify address assigned by the r-port.
+	 * Direct Attach P2P mode : verify address assigned by the r-port.
 	 */
-	if ((!bfa_fcs_fabric_is_switched(port->fabric))
-	    &&
-	    (memcmp
-	     ((void *)&bfa_fcs_port_get_pwwn(port), (void *)&plogi->port_name,
-	      sizeof(wwn_t)) < 0)) {
+	if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
+		(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
+			   (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
 		if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
-			/*
-			 * Address assigned to us cannot be a WKA
-			 */
-			bfa_fcs_port_send_ls_rjt(port, rx_fchs,
+			/* Address assigned to us cannot be a WKA */
+			bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
 					FC_LS_RJT_RSN_PROTOCOL_ERROR,
 					FC_LS_RJT_EXP_INVALID_NPORT_ID);
 			return;
 		}
-		port->pid = rx_fchs->d_id;
+		port->pid  = rx_fchs->d_id;
 	}
 
 	/**
 	 * First, check if we know the device by pwwn.
 	 */
-	rport = bfa_fcs_port_get_rport_by_pwwn(port, plogi->port_name);
+	rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
 	if (rport) {
 		/**
-		 * Direct Attach P2P mode: handle address assigned by the rport.
+		 * Direct Attach P2P mode : handle address assigned by r-port.
 		 */
-		if ((!bfa_fcs_fabric_is_switched(port->fabric))
-		    &&
-		    (memcmp
-		     ((void *)&bfa_fcs_port_get_pwwn(port),
-		      (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
-			port->pid = rx_fchs->d_id;
+		if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
+			(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
+			(void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
+			port->pid  = rx_fchs->d_id;
 			rport->pid = rx_fchs->s_id;
 		}
 		bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
@@ -377,7 +340,7 @@
 	/**
 	 * Next, lookup rport by PID.
 	 */
-	rport = bfa_fcs_port_get_rport_by_pid(port, rx_fchs->s_id);
+	rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
 	if (!rport) {
 		/**
 		 * Inbound PLOGI from a new device.
@@ -416,39 +379,40 @@
  * Since it does not require a login, it is processed here.
  */
 static void
-bfa_fcs_port_echo(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
-			struct fc_echo_s *echo, u16 rx_len)
+bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
+		struct fc_echo_s *echo, u16 rx_len)
 {
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_rport_s *bfa_rport = NULL;
-	int             len, pyld_len;
+	struct fchs_s		fchs;
+	struct bfa_fcxp_s	*fcxp;
+	struct bfa_rport_s	*bfa_rport = NULL;
+	int			len, pyld_len;
 
 	bfa_trc(port->fcs, rx_fchs->s_id);
 	bfa_trc(port->fcs, rx_fchs->d_id);
-	bfa_trc(port->fcs, rx_len);
 
 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
 	if (!fcxp)
 		return;
 
-	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-			      bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
+	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+				rx_fchs->ox_id);
 
 	/*
 	 * Copy the payload (if any) from the echo frame
 	 */
 	pyld_len = rx_len - sizeof(struct fchs_s);
+	bfa_trc(port->fcs, rx_len);
 	bfa_trc(port->fcs, pyld_len);
 
 	if (pyld_len > len)
 		memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
-		       sizeof(struct fc_echo_s), (echo + 1),
-		       (pyld_len - sizeof(struct fc_echo_s)));
+			sizeof(struct fc_echo_s), (echo + 1),
+			(pyld_len - sizeof(struct fc_echo_s)));
 
 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
-		      BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
-		      FC_MAX_PDUSZ, 0);
+			BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
+			FC_MAX_PDUSZ, 0);
 }
 
 /*
@@ -456,16 +420,16 @@
  * Since it does not require a login, it is processed here.
  */
 static void
-bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
-			struct fc_rnid_cmd_s *rnid, u16 rx_len)
+bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
+		struct fc_rnid_cmd_s *rnid, u16 rx_len)
 {
 	struct fc_rnid_common_id_data_s common_id_data;
 	struct fc_rnid_general_topology_data_s gen_topo_data;
-	struct fchs_s          fchs;
+	struct fchs_s	fchs;
 	struct bfa_fcxp_s *fcxp;
 	struct bfa_rport_s *bfa_rport = NULL;
-	u16        len;
-	u32        data_format;
+	u16	len;
+	u32	data_format;
 
 	bfa_trc(port->fcs, rx_fchs->s_id);
 	bfa_trc(port->fcs, rx_fchs->d_id);
@@ -495,28 +459,26 @@
 	/*
 	 * Copy the Node Id Info
 	 */
-	common_id_data.port_name = bfa_fcs_port_get_pwwn(port);
-	common_id_data.node_name = bfa_fcs_port_get_nwwn(port);
+	common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
+	common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
 
-	len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-				bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
-				data_format, &common_id_data, &gen_topo_data);
+	len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+				rx_fchs->ox_id, data_format, &common_id_data,
+				&gen_topo_data);
 
 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
-		      BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
-		      FC_MAX_PDUSZ, 0);
-
-	return;
+			BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+			FC_MAX_PDUSZ, 0);
 }
 
 /*
  *  Fill out General Topolpgy Discovery Data for RNID ELS.
  */
 static void
-bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
+bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
 			struct fc_rnid_general_topology_data_s *gen_topo_data)
 {
-
 	bfa_os_memset(gen_topo_data, 0,
 		      sizeof(struct fc_rnid_general_topology_data_s));
 
@@ -526,76 +488,111 @@
 }
 
 static void
-bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
 {
+	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+	char	lpwwn_buf[BFA_STRING_32];
+
 	bfa_trc(port->fcs, port->fabric->oper_type);
 
 	__port_action[port->fabric->fab_type].init(port);
 	__port_action[port->fabric->fab_type].online(port);
 
-	bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_ONLINE);
-	bfa_fcb_port_online(port->fcs->bfad, port->port_cfg.roles,
-			port->fabric->vf_drv, (port->vport == NULL) ?
-			NULL : port->vport->vport_drv);
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"Logical port online: WWN = %s Role = %s\n",
+		lpwwn_buf, "Initiator");
+
+	bfad->bfad_flags |= BFAD_PORT_ONLINE;
 }
 
 static void
-bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
 {
-	struct list_head *qe, *qen;
+	struct list_head	*qe, *qen;
 	struct bfa_fcs_rport_s *rport;
+	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+	char    lpwwn_buf[BFA_STRING_32];
 
 	bfa_trc(port->fcs, port->fabric->oper_type);
 
 	__port_action[port->fabric->fab_type].offline(port);
 
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
 	if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE)
-		bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
+		BFA_LOG(KERN_ERR, bfad, log_level,
+		"Logical port lost fabric connectivity: WWN = %s Role = %s\n",
+		lpwwn_buf, "Initiator");
 	else
-		bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_OFFLINE);
-	bfa_fcb_port_offline(port->fcs->bfad, port->port_cfg.roles,
-			port->fabric->vf_drv,
-			(port->vport == NULL) ? NULL : port->vport->vport_drv);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+		"Logical port taken offline: WWN = %s Role = %s\n",
+		lpwwn_buf, "Initiator");
 
 	list_for_each_safe(qe, qen, &port->rport_q) {
-		rport = (struct bfa_fcs_rport_s *)qe;
+		rport = (struct bfa_fcs_rport_s *) qe;
 		bfa_fcs_rport_offline(rport);
 	}
 }
 
 static void
-bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
 {
 	bfa_assert(0);
 }
 
 static void
-bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
 {
 	bfa_assert(0);
 }
 
 static void
-bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
 {
 	bfa_assert(0);
 }
 
 static void
-bfa_fcs_port_deleted(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
 {
-	bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DELETE);
+	struct fchs_s fchs;
+	struct bfa_fcxp_s *fcxp;
+	int		len;
 
-	/*
-	 * Base port will be deleted by the OS driver
-	 */
+	bfa_trc(port->fcs, rx_fchs->d_id);
+	bfa_trc(port->fcs, rx_fchs->s_id);
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+
+	len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+			rx_fchs->ox_id, 0);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
+			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+			  FC_MAX_PDUSZ, 0);
+}
+static void
+bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
+{
+	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+	char    lpwwn_buf[BFA_STRING_32];
+
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"Logical port deleted: WWN = %s Role = %s\n",
+		lpwwn_buf, "Initiator");
+
+	/* Base port will be deleted by the OS driver */
 	if (port->vport) {
-		bfa_fcb_port_delete(port->fcs->bfad, port->port_cfg.roles,
-			port->fabric->vf_drv,
-			port->vport ? port->vport->vport_drv : NULL);
+		bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
+				port->fabric->vf_drv,
+				port->vport ? port->vport->vport_drv : NULL);
 		bfa_fcs_vport_delete_comp(port->vport);
 	} else {
-		bfa_fcs_fabric_port_delete_comp(port->fabric);
+		 bfa_fcs_fabric_port_delete_comp(port->fabric);
 	}
 }
 
@@ -608,7 +605,7 @@
  *   Module initialization
  */
 void
-bfa_fcs_port_modinit(struct bfa_fcs_s *fcs)
+bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs)
 {
 
 }
@@ -617,25 +614,25 @@
  *   Module cleanup
  */
 void
-bfa_fcs_port_modexit(struct bfa_fcs_s *fcs)
+bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs)
 {
 	bfa_fcs_modexit_comp(fcs);
 }
 
 /**
- * 		Unsolicited frame receive handling.
+ * Unsolicited frame receive handling.
  */
 void
-bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
-			u16 len)
+bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
+			struct fchs_s *fchs, u16 len)
 {
-	u32        pid = fchs->s_id;
+	u32	pid = fchs->s_id;
 	struct bfa_fcs_rport_s *rport = NULL;
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
 
 	bfa_stats(lport, uf_recvs);
 
-	if (!bfa_fcs_port_is_online(lport)) {
+	if (!bfa_fcs_lport_is_online(lport)) {
 		bfa_stats(lport, uf_recv_drops);
 		return;
 	}
@@ -648,7 +645,7 @@
 	 */
 	if ((fchs->type == FC_TYPE_ELS) &&
 		(els_cmd->els_code == FC_ELS_PLOGI)) {
-		bfa_fcs_port_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
+		bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
 		return;
 	}
 
@@ -656,8 +653,8 @@
 	 * Handle ECHO separately.
 	 */
 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
-		bfa_fcs_port_echo(lport, fchs,
-			(struct fc_echo_s *) els_cmd, len);
+		bfa_fcs_lport_echo(lport, fchs,
+				(struct fc_echo_s *)els_cmd, len);
 		return;
 	}
 
@@ -665,15 +662,21 @@
 	 * Handle RNID separately.
 	 */
 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
-		bfa_fcs_port_rnid(lport, fchs,
+		bfa_fcs_lport_rnid(lport, fchs,
 			(struct fc_rnid_cmd_s *) els_cmd, len);
 		return;
 	}
 
+	if (fchs->type == FC_TYPE_BLS) {
+		if ((fchs->routing == FC_RTG_BASIC_LINK) &&
+				(fchs->cat_info == FC_CAT_ABTS))
+			bfa_fcs_lport_abts_acc(lport, fchs);
+		return;
+	}
 	/**
 	 * look for a matching remote port ID
 	 */
-	rport = bfa_fcs_port_get_rport_by_pid(lport, pid);
+	rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
 	if (rport) {
 		bfa_trc(rport->fcs, fchs->s_id);
 		bfa_trc(rport->fcs, fchs->d_id);
@@ -694,7 +697,7 @@
 
 	bfa_trc(lport->fcs, els_cmd->els_code);
 	if (els_cmd->els_code == FC_ELS_RSCN) {
-		bfa_fcs_port_scn_process_rscn(lport, fchs, len);
+		bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
 		return;
 	}
 
@@ -702,7 +705,6 @@
 		/**
 		 * @todo Handle LOGO frames received.
 		 */
-		bfa_trc(lport->fcs, els_cmd->els_code);
 		return;
 	}
 
@@ -710,14 +712,13 @@
 		/**
 		 * @todo Handle PRLI frames received.
 		 */
-		bfa_trc(lport->fcs, els_cmd->els_code);
 		return;
 	}
 
 	/**
 	 * Unhandled ELS frames. Send a LS_RJT.
 	 */
-	bfa_fcs_port_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
+	bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
 				 FC_LS_RJT_EXP_NO_ADDL_INFO);
 
 }
@@ -726,13 +727,13 @@
  *   PID based Lookup for a R-Port in the Port R-Port Queue
  */
 struct bfa_fcs_rport_s *
-bfa_fcs_port_get_rport_by_pid(struct bfa_fcs_port_s *port, u32 pid)
+bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
 {
 	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe;
+	struct list_head	*qe;
 
 	list_for_each(qe, &port->rport_q) {
-		rport = (struct bfa_fcs_rport_s *)qe;
+		rport = (struct bfa_fcs_rport_s *) qe;
 		if (rport->pid == pid)
 			return rport;
 	}
@@ -745,13 +746,13 @@
  *   PWWN based Lookup for a R-Port in the Port R-Port Queue
  */
 struct bfa_fcs_rport_s *
-bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s *port, wwn_t pwwn)
+bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
 {
 	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe;
+	struct list_head	*qe;
 
 	list_for_each(qe, &port->rport_q) {
-		rport = (struct bfa_fcs_rport_s *)qe;
+		rport = (struct bfa_fcs_rport_s *) qe;
 		if (wwn_is_equal(rport->pwwn, pwwn))
 			return rport;
 	}
@@ -764,13 +765,13 @@
  *   NWWN based Lookup for a R-Port in the Port R-Port Queue
  */
 struct bfa_fcs_rport_s *
-bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s *port, wwn_t nwwn)
+bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
 {
 	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe;
+	struct list_head	*qe;
 
 	list_for_each(qe, &port->rport_q) {
-		rport = (struct bfa_fcs_rport_s *)qe;
+		rport = (struct bfa_fcs_rport_s *) qe;
 		if (wwn_is_equal(rport->nwwn, nwwn))
 			return rport;
 	}
@@ -783,8 +784,9 @@
  * Called by rport module when new rports are discovered.
  */
 void
-bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
-		       struct bfa_fcs_rport_s *rport)
+bfa_fcs_lport_add_rport(
+	struct bfa_fcs_lport_s *port,
+	struct bfa_fcs_rport_s *rport)
 {
 	list_add_tail(&rport->qe, &port->rport_q);
 	port->num_rports++;
@@ -794,8 +796,9 @@
  * Called by rport module to when rports are deleted.
  */
 void
-bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
-		       struct bfa_fcs_rport_s *rport)
+bfa_fcs_lport_del_rport(
+	struct bfa_fcs_lport_s *port,
+	struct bfa_fcs_rport_s *rport)
 {
 	bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
 	list_del(&rport->qe);
@@ -809,7 +812,7 @@
  * Called by vport for virtual ports when FDISC is complete.
  */
 void
-bfa_fcs_port_online(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
 {
 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
 }
@@ -819,7 +822,7 @@
  * Called by vport for virtual ports when virtual port becomes offline.
  */
 void
-bfa_fcs_port_offline(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
 {
 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
 }
@@ -831,40 +834,32 @@
  * bfa_fcs_vport_delete_comp() for vports on completion.
  */
 void
-bfa_fcs_port_delete(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
 {
 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
 }
 
 /**
- * Called by fabric in private loop topology to process LIP event.
- */
-void
-bfa_fcs_port_lip(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
  * Return TRUE if port is online, else return FALSE
  */
 bfa_boolean_t
-bfa_fcs_port_is_online(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
 {
-	return bfa_sm_cmp_state(port, bfa_fcs_port_sm_online);
+	return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
 }
 
 /**
- * Attach time initialization of logical ports.
+  * Attach time initialization of logical ports.
  */
 void
-bfa_fcs_lport_attach(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
-		uint16_t vf_id, struct bfa_fcs_vport_s *vport)
+bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
+		   u16 vf_id, struct bfa_fcs_vport_s *vport)
 {
 	lport->fcs = fcs;
 	lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
 	lport->vport = vport;
 	lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) :
-			 bfa_lps_get_tag(lport->fabric->lps);
+				  bfa_lps_get_tag(lport->fabric->lps);
 
 	INIT_LIST_HEAD(&lport->rport_q);
 	lport->num_rports = 0;
@@ -876,21 +871,26 @@
  */
 
 void
-bfa_fcs_lport_init(struct bfa_fcs_port_s *lport,
-		struct bfa_port_cfg_s *port_cfg)
+bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
+	struct bfa_lport_cfg_s *port_cfg)
 {
 	struct bfa_fcs_vport_s *vport = lport->vport;
+	struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
+	char    lpwwn_buf[BFA_STRING_32];
 
 	bfa_os_assign(lport->port_cfg, *port_cfg);
 
-	lport->bfad_port = bfa_fcb_port_new(lport->fcs->bfad, lport,
-				lport->port_cfg.roles,
-				lport->fabric->vf_drv,
-				vport ? vport->vport_drv : NULL);
+	lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
+					lport->port_cfg.roles,
+					lport->fabric->vf_drv,
+					vport ? vport->vport_drv : NULL);
 
-	bfa_fcs_port_aen_post(lport, BFA_LPORT_AEN_NEW);
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"New logical port created: WWN = %s Role = %s\n",
+		lpwwn_buf, "Initiator");
 
-	bfa_sm_set_state(lport, bfa_fcs_port_sm_uninit);
+	bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
 	bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
 }
 
@@ -899,10 +899,11 @@
  */
 
 void
-bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
-		      struct bfa_port_attr_s *port_attr)
+bfa_fcs_lport_get_attr(
+	struct bfa_fcs_lport_s *port,
+	struct bfa_lport_attr_s *port_attr)
 {
-	if (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online))
+	if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
 		port_attr->pid = port->pid;
 	else
 		port_attr->pid = 0;
@@ -913,25 +914,4895 @@
 		port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric);
 		port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric);
 		port_attr->authfail =
-				bfa_fcs_fabric_is_auth_failed(port->fabric);
-		port_attr->fabric_name = bfa_fcs_port_get_fabric_name(port);
+			bfa_fcs_fabric_is_auth_failed(port->fabric);
+		port_attr->fabric_name  = bfa_fcs_lport_get_fabric_name(port);
 		memcpy(port_attr->fabric_ip_addr,
-		       bfa_fcs_port_get_fabric_ipaddr(port),
-		       BFA_FCS_FABRIC_IPADDR_SZ);
+			bfa_fcs_lport_get_fabric_ipaddr(port),
+			BFA_FCS_FABRIC_IPADDR_SZ);
 
 		if (port->vport != NULL) {
-			port_attr->port_type = BFA_PPORT_TYPE_VPORT;
+			port_attr->port_type = BFA_PORT_TYPE_VPORT;
 			port_attr->fpma_mac =
 				bfa_lps_get_lp_mac(port->vport->lps);
-		} else
+		} else {
 			port_attr->fpma_mac =
 				bfa_lps_get_lp_mac(port->fabric->lps);
-
+		}
 	} else {
-		port_attr->port_type = BFA_PPORT_TYPE_UNKNOWN;
-		port_attr->state = BFA_PORT_UNINIT;
+		port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
+		port_attr->state = BFA_LPORT_UNINIT;
 	}
+}
+
+/**
+ *  bfa_fcs_lport_fab port fab functions
+ */
+
+/**
+ *   Called by port to initialize fabric services of the base port.
+ */
+static void
+bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
+{
+	bfa_fcs_lport_ns_init(port);
+	bfa_fcs_lport_scn_init(port);
+	bfa_fcs_lport_ms_init(port);
+}
+
+/**
+ *   Called by port to notify transition to online state.
+ */
+static void
+bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
+{
+	bfa_fcs_lport_ns_online(port);
+	bfa_fcs_lport_scn_online(port);
+}
+
+/**
+ *   Called by port to notify transition to offline state.
+ */
+static void
+bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
+{
+	bfa_fcs_lport_ns_offline(port);
+	bfa_fcs_lport_scn_offline(port);
+	bfa_fcs_lport_ms_offline(port);
+}
+
+/**
+ *  bfa_fcs_lport_n2n  functions
+ */
+
+/**
+ *   Called by fcs/port to initialize N2N topology.
+ */
+static void
+bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
+{
+}
+
+/**
+ *   Called by fcs/port to notify transition to online state.
+ */
+static void
+bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
+	struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
+	struct bfa_fcs_rport_s *rport;
+
+	bfa_trc(port->fcs, pcfg->pwwn);
+
+	/*
+	 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
+	 * and assign an Address. if not, we need to wait for its PLOGI.
+	 *
+	 * If our PWWN is < than that of the remote port, it will send a PLOGI
+	 * with the PIDs assigned. The rport state machine take care of this
+	 * incoming PLOGI.
+	 */
+	if (memcmp
+	    ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
+	     sizeof(wwn_t)) > 0) {
+		port->pid = N2N_LOCAL_PID;
+		/**
+		 * First, check if we know the device by pwwn.
+		 */
+		rport = bfa_fcs_lport_get_rport_by_pwwn(port,
+							n2n_port->rem_port_wwn);
+		if (rport) {
+			bfa_trc(port->fcs, rport->pid);
+			bfa_trc(port->fcs, rport->pwwn);
+			rport->pid = N2N_REMOTE_PID;
+			bfa_fcs_rport_online(rport);
+			return;
+		}
+
+		/*
+		 * In n2n there can be only one rport. Delete the old one
+		 * whose pid should be zero, because it is offline.
+		 */
+		if (port->num_rports > 0) {
+			rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
+			bfa_assert(rport != NULL);
+			if (rport) {
+				bfa_trc(port->fcs, rport->pwwn);
+				bfa_fcs_rport_delete(rport);
+			}
+		}
+		bfa_fcs_rport_create(port, N2N_REMOTE_PID);
+	}
+}
+
+/**
+ *   Called by fcs/port to notify transition to offline state.
+ */
+static void
+bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
+
+	bfa_trc(port->fcs, port->pid);
+	port->pid = 0;
+	n2n_port->rem_port_wwn = 0;
+	n2n_port->reply_oxid = 0;
+}
+
+#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
+					    struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
+					    struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
+					   struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
+						struct bfa_fcxp_s *fcxp,
+						void *cbarg,
+						bfa_status_t req_status,
+						u32 rsp_len,
+						u32 resid_len,
+						struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
+						struct bfa_fcxp_s *fcxp,
+						void *cbarg,
+						bfa_status_t req_status,
+						u32 rsp_len,
+						u32 resid_len,
+						struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
+					       struct bfa_fcxp_s *fcxp,
+					       void *cbarg,
+					       bfa_status_t req_status,
+					       u32 rsp_len,
+					       u32 resid_len,
+					       struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_fdmi_timeout(void *arg);
+static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
+						  u8 *pyld);
+static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
+						  u8 *pyld);
+static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
+						 u8 *pyld);
+static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
+						       fdmi, u8 *pyld);
+static void	bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+				 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
+static void	bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+				  struct bfa_fcs_fdmi_port_attr_s *port_attr);
+/**
+ *  fcs_fdmi_sm FCS FDMI state machine
+ */
+
+/**
+ *  FDMI State Machine events
+ */
+enum port_fdmi_event {
+	FDMISM_EVENT_PORT_ONLINE = 1,
+	FDMISM_EVENT_PORT_OFFLINE = 2,
+	FDMISM_EVENT_RSP_OK = 4,
+	FDMISM_EVENT_RSP_ERROR = 5,
+	FDMISM_EVENT_TIMEOUT = 6,
+	FDMISM_EVENT_RHBA_SENT = 7,
+	FDMISM_EVENT_RPRT_SENT = 8,
+	FDMISM_EVENT_RPA_SENT = 9,
+};
+
+static void     bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
+					     enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_sending_rhba(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
+					  enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rhba_retry(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_sending_rprt(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
+					  enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rprt_retry(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_sending_rpa(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
+					 enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rpa_retry(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
+					    enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_disabled(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+/**
+ *	Start in offline state - awaiting MS to send start.
+ */
+static void
+bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
+			     enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	fdmi->retry_cnt = 0;
+
+	switch (event) {
+	case FDMISM_EVENT_PORT_ONLINE:
+		if (port->vport) {
+			/*
+			 * For Vports, register a new port.
+			 */
+			bfa_sm_set_state(fdmi,
+					 bfa_fcs_lport_fdmi_sm_sending_rprt);
+			bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
+		} else {
+			/*
+			 * For a base port, we should first register the HBA
+			 * atribute. The HBA attribute also contains the base
+			 *  port registration.
+			 */
+			bfa_sm_set_state(fdmi,
+					 bfa_fcs_lport_fdmi_sm_sending_rhba);
+			bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
+		}
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
+				  enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RHBA_SENT:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+					   &fdmi->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
+			enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RSP_ERROR:
+		/*
+		 * if max retries have not been reached, start timer for a
+		 * delayed retry
+		 */
+		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+			bfa_sm_set_state(fdmi,
+					bfa_fcs_lport_fdmi_sm_rhba_retry);
+			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+					    &fdmi->timer,
+					    bfa_fcs_lport_fdmi_timeout, fdmi,
+					    BFA_FCS_RETRY_TIMEOUT);
+		} else {
+			/*
+			 * set state to offline
+			 */
+			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		}
+		break;
+
+	case FDMISM_EVENT_RSP_OK:
+		/*
+		 * Initiate Register Port Attributes
+		 */
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
+		fdmi->retry_cnt = 0;
+		bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_fcxp_discard(fdmi->fcxp);
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
+		bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_timer_stop(&fdmi->timer);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+/*
+* RPRT : Register Port
+ */
+static void
+bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
+				  enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RPRT_SENT:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+					   &fdmi->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
+			enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RSP_ERROR:
+		/*
+		 * if max retries have not been reached, start timer for a
+		 * delayed retry
+		 */
+		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+			bfa_sm_set_state(fdmi,
+					bfa_fcs_lport_fdmi_sm_rprt_retry);
+			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+					    &fdmi->timer,
+					    bfa_fcs_lport_fdmi_timeout, fdmi,
+					    BFA_FCS_RETRY_TIMEOUT);
+
+		} else {
+			/*
+			 * set state to offline
+			 */
+			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+			fdmi->retry_cnt = 0;
+		}
+		break;
+
+	case FDMISM_EVENT_RSP_OK:
+		fdmi->retry_cnt = 0;
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_fcxp_discard(fdmi->fcxp);
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
+		bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_timer_stop(&fdmi->timer);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+/*
+ * Register Port Attributes
+ */
+static void
+bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
+				 enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RPA_SENT:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+					   &fdmi->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
+			enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RSP_ERROR:
+		/*
+		 * if max retries have not been reached, start timer for a
+		 * delayed retry
+		 */
+		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
+			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+					    &fdmi->timer,
+					    bfa_fcs_lport_fdmi_timeout, fdmi,
+					    BFA_FCS_RETRY_TIMEOUT);
+		} else {
+			/*
+			 * set state to offline
+			 */
+			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+			fdmi->retry_cnt = 0;
+		}
+		break;
+
+	case FDMISM_EVENT_RSP_OK:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
+		fdmi->retry_cnt = 0;
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_fcxp_discard(fdmi->fcxp);
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
+			       enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
+		bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_timer_stop(&fdmi->timer);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+/**
+ *  FDMI is disabled state.
+ */
+static void
+bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
+			     enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	/* No op State. It can only be enabled at Driver Init. */
+}
+
+/**
+*  RHBA : Register HBA Attributes.
+ */
+static void
+bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct fchs_s fchs;
+	int             len, attr_len;
+	struct bfa_fcxp_s *fcxp;
+	u8        *pyld;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+					bfa_fcs_lport_fdmi_send_rhba, fdmi);
+		return;
+	}
+	fdmi->fcxp = fcxp;
+
+	pyld = bfa_fcxp_get_reqbuf(fcxp);
+	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
+				   FDMI_RHBA);
+
+	attr_len =
+		bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
+					  (u8 *) ((struct ct_hdr_s *) pyld
+						       + 1));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, (len + attr_len), &fchs,
+			  bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
+}
+
+static          u16
+bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct bfa_fcs_fdmi_hba_attr_s hba_attr;
+	struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
+	struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
+	struct fdmi_attr_s *attr;
+	u8        *curr_ptr;
+	u16        len, count;
+
+	/*
+	 * get hba attributes
+	 */
+	bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
+
+	rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
+	rhba->port_list.num_ports = bfa_os_htonl(1);
+	rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
+
+	len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
+
+	count = 0;
+	len += sizeof(rhba->hba_attr_blk.attr_count);
+
+	/*
+	 * fill out the invididual entries of the HBA attrib Block
+	 */
+	curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
+
+	/*
+	 * Node Name
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_NODENAME);
+	attr->len = sizeof(wwn_t);
+	memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), attr->len);
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Manufacturer
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MANUFACTURER);
+	attr->len = (u16) strlen(fcs_hba_attr->manufacturer);
+	memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+								 *fields need
+								 *to be 4 byte
+								 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Serial Number
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_SERIALNUM);
+	attr->len = (u16) strlen(fcs_hba_attr->serial_num);
+	memcpy(attr->value, fcs_hba_attr->serial_num, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+								 *fields need
+								 *to be 4 byte
+								 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Model
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL);
+	attr->len = (u16) strlen(fcs_hba_attr->model);
+	memcpy(attr->value, fcs_hba_attr->model, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+								 *fields need
+								 *to be 4 byte
+								 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Model Desc
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL_DESC);
+	attr->len = (u16) strlen(fcs_hba_attr->model_desc);
+	memcpy(attr->value, fcs_hba_attr->model_desc, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							 *fields need
+							 *to be 4 byte
+							 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * H/W Version
+	 */
+	if (fcs_hba_attr->hw_version[0] != '\0') {
+		attr = (struct fdmi_attr_s *) curr_ptr;
+		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_HW_VERSION);
+		attr->len = (u16) strlen(fcs_hba_attr->hw_version);
+		memcpy(attr->value, fcs_hba_attr->hw_version, attr->len);
+		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+								 *fields need
+								 *to be 4 byte
+								 *aligned */
+		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+		len += attr->len;
+		count++;
+		attr->len =
+			bfa_os_htons(attr->len + sizeof(attr->type) +
+					 sizeof(attr->len));
+	}
+
+	/*
+	 * Driver Version
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_DRIVER_VERSION);
+	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
+	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							 *fields need
+							 *to be 4 byte
+							 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Option Rom Version
+	 */
+	if (fcs_hba_attr->option_rom_ver[0] != '\0') {
+		attr = (struct fdmi_attr_s *) curr_ptr;
+		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_ROM_VERSION);
+		attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver);
+		memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len);
+		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+								 *fields need
+								 *to be 4 byte
+								 *aligned */
+		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+		len += attr->len;
+		count++;
+		attr->len =
+			bfa_os_htons(attr->len + sizeof(attr->type) +
+					 sizeof(attr->len));
+	}
+
+	/*
+	 * f/w Version = driver version
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_FW_VERSION);
+	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
+	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							 *fields need
+							 *to be 4 byte
+							 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * OS Name
+	 */
+	if (fcs_hba_attr->os_name[0] != '\0') {
+		attr = (struct fdmi_attr_s *) curr_ptr;
+		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_OS_NAME);
+		attr->len = (u16) strlen(fcs_hba_attr->os_name);
+		memcpy(attr->value, fcs_hba_attr->os_name, attr->len);
+		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							     *fields need
+							     *to be 4 byte
+							     *aligned */
+		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+		len += attr->len;
+		count++;
+		attr->len =
+			bfa_os_htons(attr->len + sizeof(attr->type) +
+					sizeof(attr->len));
+	}
+
+	/*
+	 * MAX_CT_PAYLOAD
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MAX_CT);
+	attr->len = sizeof(fcs_hba_attr->max_ct_pyld);
+	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len);
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Update size of payload
+	 */
+	len += ((sizeof(attr->type) +
+		 sizeof(attr->len)) * count);
+
+	rhba->hba_attr_blk.attr_count = bfa_os_htonl(count);
+	return len;
+}
+
+static void
+bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi =
+				(struct bfa_fcs_lport_fdmi_s *) cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+		return;
+	}
+
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+/**
+*  RPRT : Register Port
+ */
+static void
+bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct fchs_s fchs;
+	u16        len, attr_len;
+	struct bfa_fcxp_s *fcxp;
+	u8        *pyld;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+					bfa_fcs_lport_fdmi_send_rprt, fdmi);
+		return;
+	}
+	fdmi->fcxp = fcxp;
+
+	pyld = bfa_fcxp_get_reqbuf(fcxp);
+	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
+				   FDMI_RPRT);
+
+	attr_len =
+		bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
+					  (u8 *) ((struct ct_hdr_s *) pyld
+						       + 1));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len + attr_len, &fchs,
+			  bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
+}
+
+/**
+ * This routine builds Port Attribute Block that used in RPA, RPRT commands.
+ */
+static          u16
+bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
+				       u8 *pyld)
+{
+	struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
+	struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
+	struct fdmi_attr_s *attr;
+	u8        *curr_ptr;
+	u16        len;
+	u8	count = 0;
+
+	/*
+	 * get port attributes
+	 */
+	bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
+
+	len = sizeof(port_attrib->attr_count);
+
+	/*
+	 * fill out the invididual entries
+	 */
+	curr_ptr = (u8 *) &port_attrib->port_attr;
+
+	/*
+	 * FC4 Types
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FC4_TYPES);
+	attr->len = sizeof(fcs_port_attr.supp_fc4_types);
+	memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len);
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	++count;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Supported Speed
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_SUPP_SPEED);
+	attr->len = sizeof(fcs_port_attr.supp_speed);
+	memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len);
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	++count;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * current Port Speed
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_PORT_SPEED);
+	attr->len = sizeof(fcs_port_attr.curr_speed);
+	memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len);
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	++count;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * max frame size
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FRAME_SIZE);
+	attr->len = sizeof(fcs_port_attr.max_frm_size);
+	memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len);
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	++count;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * OS Device Name
+	 */
+	if (fcs_port_attr.os_device_name[0] != '\0') {
+		attr = (struct fdmi_attr_s *) curr_ptr;
+		attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_DEV_NAME);
+		attr->len = (u16) strlen(fcs_port_attr.os_device_name);
+		memcpy(attr->value, fcs_port_attr.os_device_name, attr->len);
+		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							     *fields need
+							     *to be 4 byte
+							     *aligned */
+		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+		len += attr->len;
+		++count;
+		attr->len =
+			bfa_os_htons(attr->len + sizeof(attr->type) +
+					sizeof(attr->len));
+	}
+	/*
+	 * Host Name
+	 */
+	if (fcs_port_attr.host_name[0] != '\0') {
+		attr = (struct fdmi_attr_s *) curr_ptr;
+		attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_HOST_NAME);
+		attr->len = (u16) strlen(fcs_port_attr.host_name);
+		memcpy(attr->value, fcs_port_attr.host_name, attr->len);
+		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							     *fields need
+							     *to be 4 byte
+							     *aligned */
+		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+		len += attr->len;
+		++count;
+		attr->len =
+			bfa_os_htons(attr->len + sizeof(attr->type) +
+				sizeof(attr->len));
+	}
+
+	/*
+	 * Update size of payload
+	 */
+	port_attrib->attr_count = bfa_os_htonl(count);
+	len += ((sizeof(attr->type) +
+		 sizeof(attr->len)) * count);
+	return len;
+}
+
+static          u16
+bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
+	u16        len;
+
+	rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
+	rprt->port_name = bfa_fcs_lport_get_pwwn(port);
+
+	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
+				(u8 *) &rprt->port_attr_blk);
+
+	len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
+
+	return len;
+}
+
+static void
+bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi =
+			(struct bfa_fcs_lport_fdmi_s *) cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+		return;
+	}
+
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+/**
+*  RPA : Register Port Attributes.
+ */
+static void
+bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct fchs_s fchs;
+	u16        len, attr_len;
+	struct bfa_fcxp_s *fcxp;
+	u8        *pyld;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+					bfa_fcs_lport_fdmi_send_rpa, fdmi);
+		return;
+	}
+	fdmi->fcxp = fcxp;
+
+	pyld = bfa_fcxp_get_reqbuf(fcxp);
+	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
+				   FDMI_RPA);
+
+	attr_len =
+		bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
+					 (u8 *) ((struct ct_hdr_s *) pyld
+						      + 1));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len + attr_len, &fchs,
+			  bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
+}
+
+static          u16
+bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
+	u16        len;
+
+	rpa->port_name = bfa_fcs_lport_get_pwwn(port);
+
+	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
+				(u8 *) &rpa->port_attr_blk);
+
+	len += sizeof(rpa->port_name);
+
+	return len;
+}
+
+static void
+bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+			void *cbarg, bfa_status_t req_status, u32 rsp_len,
+			u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi =
+				(struct bfa_fcs_lport_fdmi_s *) cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+		return;
+	}
+
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+static void
+bfa_fcs_lport_fdmi_timeout(void *arg)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
+
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
+}
+
+void
+bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+			 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
+
+	bfa_os_memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
+
+	bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
+					hba_attr->manufacturer);
+	bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
+					hba_attr->serial_num);
+	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
+					hba_attr->model);
+	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
+					hba_attr->model_desc);
+	bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
+					hba_attr->hw_version);
+	bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
+					hba_attr->option_rom_ver);
+	bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
+					hba_attr->fw_version);
+
+	strncpy(hba_attr->driver_version, (char *)driver_info->version,
+		sizeof(hba_attr->driver_version));
+
+	strncpy(hba_attr->os_name, driver_info->host_os_name,
+		sizeof(hba_attr->os_name));
+
+	/*
+	 * If there is a patch level, append it
+	 * to the os name along with a separator
+	 */
+	if (driver_info->host_os_patch[0] != '\0') {
+		strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+		strncat(hba_attr->os_name, driver_info->host_os_patch,
+				sizeof(driver_info->host_os_patch));
+	}
+
+	hba_attr->max_ct_pyld = bfa_os_htonl(FC_MAX_PDUSZ);
+}
+
+void
+bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+			  struct bfa_fcs_fdmi_port_attr_s *port_attr)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
+	struct bfa_port_attr_s pport_attr;
+
+	bfa_os_memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
+
+	/*
+	 * get pport attributes from hal
+	 */
+	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
+
+	/*
+	 * get FC4 type Bitmask
+	 */
+	fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
+
+	/*
+	 * Supported Speeds
+	 */
+	port_attr->supp_speed = bfa_os_htonl(BFA_FCS_FDMI_SUPORTED_SPEEDS);
+
+	/*
+	 * Current Speed
+	 */
+	port_attr->curr_speed = bfa_os_htonl(pport_attr.speed);
+
+	/*
+	 * Max PDU Size.
+	 */
+	port_attr->max_frm_size = bfa_os_htonl(FC_MAX_PDUSZ);
+
+	/*
+	 * OS device Name
+	 */
+	strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
+		sizeof(port_attr->os_device_name));
+
+	/*
+	 * Host name
+	 */
+	strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
+		sizeof(port_attr->host_name));
 
 }
 
 
+void
+bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
+
+	fdmi->ms = ms;
+	if (ms->port->fcs->fdmi_enabled)
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+	else
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
+}
+
+void
+bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
+
+	fdmi->ms = ms;
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
+
+	fdmi->ms = ms;
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
+}
+
+#define BFA_FCS_MS_CMD_MAX_RETRIES  2
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
+					   struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ms_timeout(void *arg);
+static void     bfa_fcs_lport_ms_plogi_response(void *fcsarg,
+					       struct bfa_fcxp_s *fcxp,
+					       void *cbarg,
+					       bfa_status_t req_status,
+					       u32 rsp_len,
+					       u32 resid_len,
+					       struct fchs_s *rsp_fchs);
+
+static void	bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
+					struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ms_gmal_response(void *fcsarg,
+					       struct bfa_fcxp_s *fcxp,
+					       void *cbarg,
+					       bfa_status_t req_status,
+					       u32 rsp_len,
+					       u32 resid_len,
+					       struct fchs_s *rsp_fchs);
+static void	bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
+					struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ms_gfn_response(void *fcsarg,
+					       struct bfa_fcxp_s *fcxp,
+					       void *cbarg,
+					       bfa_status_t req_status,
+					       u32 rsp_len,
+					       u32 resid_len,
+					       struct fchs_s *rsp_fchs);
+/**
+ *  fcs_ms_sm FCS MS state machine
+ */
+
+/**
+ *  MS State Machine events
+ */
+enum port_ms_event {
+	MSSM_EVENT_PORT_ONLINE = 1,
+	MSSM_EVENT_PORT_OFFLINE = 2,
+	MSSM_EVENT_RSP_OK = 3,
+	MSSM_EVENT_RSP_ERROR = 4,
+	MSSM_EVENT_TIMEOUT = 5,
+	MSSM_EVENT_FCXP_SENT = 6,
+	MSSM_EVENT_PORT_FABRIC_RSCN = 7
+};
+
+static void     bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
+					   enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
+						 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
+					 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
+					       enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
+						 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
+					 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
+					       enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
+						 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
+					 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
+					       enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
+					  enum port_ms_event event);
+/**
+ *	Start in offline state - awaiting NS to send start.
+ */
+static void
+bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_PORT_ONLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
+		bfa_fcs_lport_ms_send_plogi(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+					   &ms->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
+			enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
+		ms->port->stats.ms_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+				    &ms->timer, bfa_fcs_lport_ms_timeout, ms,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case MSSM_EVENT_RSP_OK:
+		/*
+		 * since plogi is done, now invoke MS related sub-modules
+		 */
+		bfa_fcs_lport_fdmi_online(ms);
+
+		/**
+		 * if this is a Vport, go to online state.
+		 */
+		if (ms->port->vport) {
+			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
+			break;
+		}
+
+		/*
+		 * For a base port we need to get the
+		 * switch's IP address.
+		 */
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
+		bfa_fcs_lport_ms_send_gmal(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_discard(ms->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
+			enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
+		bfa_fcs_lport_ms_send_plogi(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_timer_stop(&ms->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
+			enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		break;
+
+	case MSSM_EVENT_PORT_FABRIC_RSCN:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+		ms->retry_cnt = 0;
+		bfa_fcs_lport_ms_send_gfn(ms, NULL);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+					   &ms->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
+			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
+			ms->port->stats.ms_retries++;
+			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
+				BFA_FCS_RETRY_TIMEOUT);
+		} else {
+			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+			bfa_fcs_lport_ms_send_gfn(ms, NULL);
+			ms->retry_cnt = 0;
+		}
+		break;
+
+	case MSSM_EVENT_RSP_OK:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+		bfa_fcs_lport_ms_send_gfn(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_discard(ms->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
+		bfa_fcs_lport_ms_send_gmal(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_timer_stop(&ms->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+/**
+ *  ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
+	bfa_fcs_lport_t *port = ms->port;
+	struct fchs_s	fchs;
+	int		len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+					bfa_fcs_lport_ms_send_gmal, ms);
+		return;
+	}
+	ms->fcxp = fcxp;
+
+	len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			     bfa_fcs_lport_get_fcid(port),
+				 bfa_lps_get_peer_nwwn(port->fabric->lps));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ms_gmal_response, (void *)ms,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
+	bfa_fcs_lport_t *port = ms->port;
+	struct ct_hdr_s		*cthdr = NULL;
+	struct fcgs_gmal_resp_s *gmal_resp;
+	struct fcgs_gmal_entry_s *gmal_entry;
+	u32		num_entries;
+	u8			*rsp_str;
+
+	bfa_trc(port->fcs, req_status);
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
+
+		num_entries = bfa_os_ntohl(gmal_resp->ms_len);
+		if (num_entries == 0) {
+			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+			return;
+		}
+		/*
+		* The response could contain multiple Entries.
+		* Entries for SNMP interface, etc.
+		* We look for the entry with a telnet prefix.
+		* First "http://" entry refers to IP addr
+		*/
+
+		gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
+		while (num_entries > 0) {
+			if (strncmp(gmal_entry->prefix,
+				CT_GMAL_RESP_PREFIX_HTTP,
+				sizeof(gmal_entry->prefix)) == 0) {
+
+				/*
+				* if the IP address is terminating with a '/',
+				* remove it.
+				* Byte 0 consists of the length of the string.
+				*/
+				rsp_str = &(gmal_entry->prefix[0]);
+				if (rsp_str[gmal_entry->len-1] == '/')
+					rsp_str[gmal_entry->len-1] = 0;
+
+				/* copy IP Address to fabric */
+				strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
+					gmal_entry->ip_addr,
+					BFA_FCS_FABRIC_IPADDR_SZ);
+				break;
+			} else {
+				--num_entries;
+				++gmal_entry;
+			}
+		}
+
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+		return;
+	}
+
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+}
+
+static void
+bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
+			enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+					   &ms->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
+			enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
+			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
+			ms->port->stats.ms_retries++;
+			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
+				BFA_FCS_RETRY_TIMEOUT);
+		} else {
+			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
+			ms->retry_cnt = 0;
+		}
+		break;
+
+	case MSSM_EVENT_RSP_OK:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_discard(ms->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+		bfa_fcs_lport_ms_send_gfn(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_timer_stop(&ms->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+/**
+ *  ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
+	bfa_fcs_lport_t *port = ms->port;
+	struct fchs_s		fchs;
+	int			len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+					bfa_fcs_lport_ms_send_gfn, ms);
+		return;
+	}
+	ms->fcxp = fcxp;
+
+	len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			     bfa_fcs_lport_get_fcid(port),
+				 bfa_lps_get_peer_nwwn(port->fabric->lps));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ms_gfn_response, (void *)ms,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+			void *cbarg, bfa_status_t req_status, u32 rsp_len,
+			u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
+	bfa_fcs_lport_t *port = ms->port;
+	struct ct_hdr_s	*cthdr = NULL;
+	wwn_t	       *gfn_resp;
+
+	bfa_trc(port->fcs, req_status);
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		gfn_resp = (wwn_t *)(cthdr + 1);
+		/* check if it has actually changed */
+		if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
+				gfn_resp, sizeof(wwn_t)) != 0)) {
+			bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
+		}
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+		return;
+	}
+
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+}
+
+/**
+ *  ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
+	struct bfa_fcs_lport_s *port = ms->port;
+	struct fchs_s	fchs;
+	int	len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ms_plogi_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+					bfa_fcs_lport_ms_send_plogi, ms);
+		return;
+	}
+	ms->fcxp = fcxp;
+
+	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			     bfa_os_hton3b(FC_MGMT_SERVER),
+			     bfa_fcs_lport_get_fcid(port), 0,
+			     port->port_cfg.pwwn, port->port_cfg.nwwn,
+				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ms_plogi_response, (void *)ms,
+			  FC_MAX_PDUSZ, FC_ELS_TOV);
+
+	port->stats.ms_plogi_sent++;
+	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+			void *cbarg, bfa_status_t req_status,
+			u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ms->port;
+	struct fc_els_cmd_s *els_cmd;
+	struct fc_ls_rjt_s *ls_rjt;
+
+	bfa_trc(port->fcs, req_status);
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		port->stats.ms_plogi_rsp_err++;
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+	switch (els_cmd->els_code) {
+
+	case FC_ELS_ACC:
+		if (rsp_len < sizeof(struct fc_logi_s)) {
+			bfa_trc(port->fcs, rsp_len);
+			port->stats.ms_plogi_acc_err++;
+			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+			break;
+		}
+		port->stats.ms_plogi_accepts++;
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+		break;
+
+	case FC_ELS_LS_RJT:
+		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+		bfa_trc(port->fcs, ls_rjt->reason_code);
+		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+		port->stats.ms_rejects++;
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+		break;
+
+	default:
+		port->stats.ms_plogi_unknown_rsp++;
+		bfa_trc(port->fcs, els_cmd->els_code);
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_timeout(void *arg)
+{
+	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
+
+	ms->port->stats.ms_timeouts++;
+	bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
+}
+
+
+void
+bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+	ms->port = port;
+	bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+
+	/*
+	 * Invoke init routines of sub modules.
+	 */
+	bfa_fcs_lport_fdmi_init(ms);
+}
+
+void
+bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+	ms->port = port;
+	bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
+	bfa_fcs_lport_fdmi_offline(ms);
+}
+
+void
+bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+	ms->port = port;
+	bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
+}
+void
+bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+	/* todo.  Handle this only  when in Online state */
+	if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
+		bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
+}
+
+/**
+ * @page ns_sm_info VPORT NS State Machine
+ *
+ * @section ns_sm_interactions VPORT NS State Machine Interactions
+ *
+ * @section ns_sm VPORT NS State Machine
+ * img ns_sm.jpg
+ */
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
+					   struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
+					     struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
+					    struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
+					    struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
+					    struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ns_timeout(void *arg);
+static void     bfa_fcs_lport_ns_plogi_response(void *fcsarg,
+					       struct bfa_fcxp_s *fcxp,
+					       void *cbarg,
+					       bfa_status_t req_status,
+					       u32 rsp_len,
+					       u32 resid_len,
+					       struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
+						 struct bfa_fcxp_s *fcxp,
+						 void *cbarg,
+						 bfa_status_t req_status,
+						 u32 rsp_len,
+						 u32 resid_len,
+						 struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
+						struct bfa_fcxp_s *fcxp,
+						void *cbarg,
+						bfa_status_t req_status,
+						u32 rsp_len,
+						u32 resid_len,
+						struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
+						struct bfa_fcxp_s *fcxp,
+						void *cbarg,
+						bfa_status_t req_status,
+						u32 rsp_len,
+						u32 resid_len,
+						struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
+						struct bfa_fcxp_s *fcxp,
+						void *cbarg,
+						bfa_status_t req_status,
+						u32 rsp_len,
+						u32 resid_len,
+						struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_process_gidft_pids(
+				struct bfa_fcs_lport_s *port,
+				u32 *pid_buf, u32 n_pids);
+
+static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
+/**
+ *  fcs_ns_sm FCS nameserver interface state machine
+ */
+
+/**
+ * VPort NS State Machine events
+ */
+enum vport_ns_event {
+	NSSM_EVENT_PORT_ONLINE = 1,
+	NSSM_EVENT_PORT_OFFLINE = 2,
+	NSSM_EVENT_PLOGI_SENT = 3,
+	NSSM_EVENT_RSP_OK = 4,
+	NSSM_EVENT_RSP_ERROR = 5,
+	NSSM_EVENT_TIMEOUT = 6,
+	NSSM_EVENT_NS_QUERY = 7,
+	NSSM_EVENT_RSPNID_SENT = 8,
+	NSSM_EVENT_RFTID_SENT = 9,
+	NSSM_EVENT_RFFID_SENT = 10,
+	NSSM_EVENT_GIDFT_SENT = 11,
+};
+
+static void     bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
+					   enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
+						 enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
+					 enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
+					       enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_sending_rspn_id(
+					struct bfa_fcs_lport_ns_s *ns,
+					enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
+					   enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
+						 enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_sending_rft_id(
+					struct bfa_fcs_lport_ns_s *ns,
+					enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
+						enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
+					  enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_sending_rff_id(
+					struct bfa_fcs_lport_ns_s *ns,
+					enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
+						enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
+					  enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_sending_gid_ft(
+					struct bfa_fcs_lport_ns_s *ns,
+					enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
+					  enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
+						enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
+					  enum vport_ns_event event);
+/**
+ *	Start in offline state - awaiting linkup
+ */
+static void
+bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_PORT_ONLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
+		bfa_fcs_lport_ns_send_plogi(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_PLOGI_SENT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+					   &ns->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
+		ns->port->stats.ns_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case NSSM_EVENT_RSP_OK:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
+		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_discard(ns->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
+				enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
+		bfa_fcs_lport_ns_send_plogi(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_timer_stop(&ns->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
+				   enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSPNID_SENT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+					   &ns->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
+		ns->port->stats.ns_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case NSSM_EVENT_RSP_OK:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
+		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_fcxp_discard(ns->fcxp);
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
+				enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
+		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_timer_stop(&ns->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
+				  enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RFTID_SENT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+					   &ns->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSP_OK:
+		/* Now move to register FC4 Features */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
+		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
+		ns->port->stats.ns_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_discard(ns->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
+				enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
+		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_timer_stop(&ns->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
+				  enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RFFID_SENT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+					   &ns->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSP_OK:
+
+		/*
+		 * If min cfg mode is enabled, we donot initiate rport
+		 * discovery with the fabric. Instead, we will retrieve the
+		 * boot targets from HAL/FW.
+		 */
+		if (__fcs_min_cfg(ns->port->fcs)) {
+			bfa_fcs_lport_ns_boot_target_disc(ns->port);
+			bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
+			return;
+		}
+
+		/*
+		 * If the port role is Initiator Mode issue NS query.
+		 * If it is Target Mode, skip this and go to online.
+		 */
+		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
+			bfa_sm_set_state(ns,
+				bfa_fcs_lport_ns_sm_sending_gid_ft);
+			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
+		}
+		/*
+		 * kick off mgmt srvr state machine
+		 */
+		bfa_fcs_lport_ms_online(ns->port);
+		break;
+
+	case NSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
+		ns->port->stats.ns_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_discard(ns->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
+				enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
+		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_timer_stop(&ns->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+static void
+bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
+				  enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_GIDFT_SENT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+					   &ns->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSP_OK:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
+		break;
+
+	case NSSM_EVENT_RSP_ERROR:
+		/*
+		 * TBD: for certain reject codes, we don't need to retry
+		 */
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
+		ns->port->stats.ns_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_discard(ns->fcxp);
+		break;
+
+	case  NSSM_EVENT_NS_QUERY:
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
+				enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
+		bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_timer_stop(&ns->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		break;
+
+	case NSSM_EVENT_NS_QUERY:
+		/*
+		 * If the port role is Initiator Mode issue NS query.
+		 * If it is Target Mode, skip this and go to online.
+		 */
+		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
+			bfa_sm_set_state(ns,
+				bfa_fcs_lport_ns_sm_sending_gid_ft);
+			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
+		};
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+
+
+/**
+ *  ns_pvt Nameserver local functions
+ */
+
+static void
+bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+
+fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ns_plogi_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+					bfa_fcs_lport_ns_send_plogi, ns);
+		return;
+	}
+	ns->fcxp = fcxp;
+
+	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			     bfa_os_hton3b(FC_NAME_SERVER),
+			     bfa_fcs_lport_get_fcid(port), 0,
+			     port->port_cfg.pwwn, port->port_cfg.nwwn,
+				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ns_plogi_response, (void *)ns,
+			  FC_MAX_PDUSZ, FC_ELS_TOV);
+	port->stats.ns_plogi_sent++;
+
+	bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+			void *cbarg, bfa_status_t req_status, u32 rsp_len,
+		       u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	/* struct fc_logi_s *plogi_resp; */
+	struct fc_els_cmd_s *els_cmd;
+	struct fc_ls_rjt_s *ls_rjt;
+
+	bfa_trc(port->fcs, req_status);
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		port->stats.ns_plogi_rsp_err++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+	switch (els_cmd->els_code) {
+
+	case FC_ELS_ACC:
+		if (rsp_len < sizeof(struct fc_logi_s)) {
+			bfa_trc(port->fcs, rsp_len);
+			port->stats.ns_plogi_acc_err++;
+			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+			break;
+		}
+		port->stats.ns_plogi_accepts++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		break;
+
+	case FC_ELS_LS_RJT:
+		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+		bfa_trc(port->fcs, ls_rjt->reason_code);
+		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+		port->stats.ns_rejects++;
+
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		break;
+
+	default:
+		port->stats.ns_plogi_unknown_rsp++;
+		bfa_trc(port->fcs, els_cmd->els_code);
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+	}
+}
+
+/**
+ * Register the symbolic port name.
+ */
+static void
+bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+	u8         symbl[256];
+	u8         *psymbl = &symbl[0];
+
+	bfa_os_memset(symbl, 0, sizeof(symbl));
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ns_rspnid_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+					bfa_fcs_lport_ns_send_rspn_id, ns);
+		return;
+	}
+	ns->fcxp = fcxp;
+
+	/*
+	 * for V-Port, form a Port Symbolic Name
+	 */
+	if (port->vport) {
+		/**
+		 * For Vports, we append the vport's port symbolic name
+		 * to that of the base port.
+		 */
+
+		strncpy((char *)psymbl,
+			(char *) &
+			(bfa_fcs_lport_get_psym_name
+			 (bfa_fcs_get_base_port(port->fcs))),
+			strlen((char *) &
+			       bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
+							  (port->fcs))));
+
+		/* Ensure we have a null terminating string. */
+		((char *)psymbl)[strlen((char *) &
+			bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
+						(port->fcs)))] = 0;
+		strncat((char *)psymbl,
+			(char *) &(bfa_fcs_lport_get_psym_name(port)),
+		strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
+	} else {
+		psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
+	}
+
+	len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			      bfa_fcs_lport_get_fcid(port), 0, psymbl);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	port->stats.ns_rspnid_sent++;
+
+	bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				 void *cbarg, bfa_status_t req_status,
+				 u32 rsp_len, u32 resid_len,
+				 struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		port->stats.ns_rspnid_rsp_err++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		port->stats.ns_rspnid_accepts++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		return;
+	}
+
+	port->stats.ns_rspnid_rejects++;
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
+/**
+ * Register FC4-Types
+ */
+static void
+bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ns_rftid_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+					bfa_fcs_lport_ns_send_rft_id, ns);
+		return;
+	}
+	ns->fcxp = fcxp;
+
+	len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+		     bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ns_rft_id_response, (void *)ns,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	port->stats.ns_rftid_sent++;
+	bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		port->stats.ns_rftid_rsp_err++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		port->stats.ns_rftid_accepts++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		return;
+	}
+
+	port->stats.ns_rftid_rejects++;
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
+/**
+ * Register FC4-Features : Should be done after RFT_ID
+ */
+static void
+bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+	u8			fc4_ftrs = 0;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ns_rffid_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+					bfa_fcs_lport_ns_send_rff_id, ns);
+		return;
+	}
+	ns->fcxp = fcxp;
+
+	if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
+		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
+
+	len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			     bfa_fcs_lport_get_fcid(port), 0,
+				 FC_TYPE_FCP, fc4_ftrs);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ns_rff_id_response, (void *)ns,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	port->stats.ns_rffid_sent++;
+	bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		port->stats.ns_rffid_rsp_err++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		port->stats.ns_rffid_accepts++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		return;
+	}
+
+	port->stats.ns_rffid_rejects++;
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+
+	if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
+		/* if this command is not supported, we don't retry */
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+	} else
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+/**
+ * Query Fabric for FC4-Types Devices.
+ *
+* TBD : Need to use a local (FCS private) response buffer, since the response
+ * can be larger than 2K.
+ */
+static void
+bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ns_gidft_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+					bfa_fcs_lport_ns_send_gid_ft, ns);
+		return;
+	}
+	ns->fcxp = fcxp;
+
+	/*
+	 * This query is only initiated for FCP initiator mode.
+	 */
+	len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			      ns->port->pid, FC_TYPE_FCP);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
+			  bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
+
+	port->stats.ns_gidft_sent++;
+
+	bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct ct_hdr_s *cthdr = NULL;
+	u32        n_pids;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		port->stats.ns_gidft_rsp_err++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	if (resid_len != 0) {
+		/*
+		 * TBD : we will need to allocate a larger buffer & retry the
+		 * command
+		 */
+		bfa_trc(port->fcs, rsp_len);
+		bfa_trc(port->fcs, resid_len);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	switch (cthdr->cmd_rsp_code) {
+
+	case CT_RSP_ACCEPT:
+
+		port->stats.ns_gidft_accepts++;
+		n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
+		bfa_trc(port->fcs, n_pids);
+		bfa_fcs_lport_ns_process_gidft_pids(port,
+						   (u32 *) (cthdr + 1),
+						   n_pids);
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		break;
+
+	case CT_RSP_REJECT:
+
+		/*
+		 * Check the reason code  & explanation.
+		 * There may not have been any FC4 devices in the fabric
+		 */
+		port->stats.ns_gidft_rejects++;
+		bfa_trc(port->fcs, cthdr->reason_code);
+		bfa_trc(port->fcs, cthdr->exp_code);
+
+		if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
+		    && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
+
+			bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		} else {
+			/*
+			 * for all other errors, retry
+			 */
+			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		}
+		break;
+
+	default:
+		port->stats.ns_gidft_unknown_rsp++;
+		bfa_trc(port->fcs, cthdr->cmd_rsp_code);
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+	}
+}
+
+/**
+ *     This routine will be called by bfa_timer on timer timeouts.
+ *
+ *	param[in]	port - pointer to bfa_fcs_lport_t.
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+static void
+bfa_fcs_lport_ns_timeout(void *arg)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
+
+	ns->port->stats.ns_timeouts++;
+	bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
+}
+
+/*
+ * Process the PID list in GID_FT response
+ */
+static void
+bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
+				   u32 n_pids)
+{
+	struct fcgs_gidft_resp_s *gidft_entry;
+	struct bfa_fcs_rport_s *rport;
+	u32        ii;
+
+	for (ii = 0; ii < n_pids; ii++) {
+		gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
+
+		if (gidft_entry->pid == port->pid)
+			continue;
+
+		/*
+		 * Check if this rport already exists
+		 */
+		rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
+		if (rport == NULL) {
+			/*
+			 * this is a new device. create rport
+			 */
+			rport = bfa_fcs_rport_create(port, gidft_entry->pid);
+		} else {
+			/*
+			 * this rport already exists
+			 */
+			bfa_fcs_rport_scn(rport);
+		}
+
+		bfa_trc(port->fcs, gidft_entry->pid);
+
+		/*
+		 * if the last entry bit is set, bail out.
+		 */
+		if (gidft_entry->last)
+			return;
+	}
+}
+
+/**
+ *  fcs_ns_public FCS nameserver public interfaces
+ */
+
+/*
+ * Functions called by port/fab.
+ * These will send relevant Events to the ns state machine.
+ */
+void
+bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+	ns->port = port;
+	bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+}
+
+void
+bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+	ns->port = port;
+	bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+	ns->port = port;
+	bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
+}
+
+void
+bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+	bfa_trc(port->fcs, port->pid);
+	bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
+}
+
+void
+bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
+{
+
+	struct bfa_fcs_rport_s *rport;
+	u8 nwwns;
+	wwn_t  wwns[BFA_PREBOOT_BOOTLUN_MAX];
+	int ii;
+
+	bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
+
+	for (ii = 0 ; ii < nwwns; ++ii) {
+		rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
+		bfa_assert(rport);
+	}
+}
+
+/**
+ * FCS SCN
+ */
+
+#define FC_QOS_RSCN_EVENT		0x0c
+#define FC_FABRIC_NAME_RSCN_EVENT	0x0d
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
+					  struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_scn_scr_response(void *fcsarg,
+					      struct bfa_fcxp_s *fcxp,
+					      void *cbarg,
+					      bfa_status_t req_status,
+					      u32 rsp_len,
+					      u32 resid_len,
+					      struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
+					     struct fchs_s *rx_fchs);
+static void     bfa_fcs_lport_scn_timeout(void *arg);
+
+/**
+ *  fcs_scm_sm FCS SCN state machine
+ */
+
+/**
+ * VPort SCN State Machine events
+ */
+enum port_scn_event {
+	SCNSM_EVENT_PORT_ONLINE = 1,
+	SCNSM_EVENT_PORT_OFFLINE = 2,
+	SCNSM_EVENT_RSP_OK = 3,
+	SCNSM_EVENT_RSP_ERROR = 4,
+	SCNSM_EVENT_TIMEOUT = 5,
+	SCNSM_EVENT_SCR_SENT = 6,
+};
+
+static void     bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
+					    enum port_scn_event event);
+static void     bfa_fcs_lport_scn_sm_sending_scr(
+					struct bfa_fcs_lport_scn_s *scn,
+					enum port_scn_event event);
+static void     bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
+					enum port_scn_event event);
+static void     bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
+					      enum port_scn_event event);
+static void     bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
+					   enum port_scn_event event);
+
+/**
+ *	Starting state - awaiting link up.
+ */
+static void
+bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
+			enum port_scn_event event)
+{
+	switch (event) {
+	case SCNSM_EVENT_PORT_ONLINE:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
+		bfa_fcs_lport_scn_send_scr(scn, NULL);
+		break;
+
+	case SCNSM_EVENT_PORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(scn->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
+				enum port_scn_event event)
+{
+	switch (event) {
+	case SCNSM_EVENT_SCR_SENT:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
+		break;
+
+	case SCNSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+		bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(scn->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
+			enum port_scn_event event)
+{
+	struct bfa_fcs_lport_s *port = scn->port;
+
+	switch (event) {
+	case SCNSM_EVENT_RSP_OK:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
+		break;
+
+	case SCNSM_EVENT_RSP_ERROR:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
+		bfa_timer_start(port->fcs->bfa, &scn->timer,
+				    bfa_fcs_lport_scn_timeout, scn,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case SCNSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+		bfa_fcxp_discard(scn->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
+				enum port_scn_event event)
+{
+	switch (event) {
+	case SCNSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
+		bfa_fcs_lport_scn_send_scr(scn, NULL);
+		break;
+
+	case SCNSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+		bfa_timer_stop(&scn->timer);
+		break;
+
+	default:
+		bfa_sm_fault(scn->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
+			enum port_scn_event event)
+{
+	switch (event) {
+	case SCNSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(scn->port->fcs, event);
+	}
+}
+
+
+
+/**
+ *  fcs_scn_private FCS SCN private functions
+ */
+
+/**
+ * This routine will be called to send a SCR command.
+ */
+static void
+bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
+	struct bfa_fcs_lport_s *port = scn->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
+					bfa_fcs_lport_scn_send_scr, scn);
+		return;
+	}
+	scn->fcxp = fcxp;
+
+	/* Handle VU registrations for Base port only */
+	if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
+		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				bfa_lps_is_brcd_fabric(port->fabric->lps),
+							port->pid, 0);
+	} else {
+	    len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				    BFA_FALSE,
+				    port->pid, 0);
+	}
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_scn_scr_response,
+			  (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
+
+	bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
+}
+
+static void
+bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+			void *cbarg, bfa_status_t req_status, u32 rsp_len,
+			      u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
+	struct bfa_fcs_lport_s *port = scn->port;
+	struct fc_els_cmd_s *els_cmd;
+	struct fc_ls_rjt_s *ls_rjt;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+	switch (els_cmd->els_code) {
+
+	case FC_ELS_ACC:
+		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
+		break;
+
+	case FC_ELS_LS_RJT:
+
+		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+		bfa_trc(port->fcs, ls_rjt->reason_code);
+		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+		break;
+
+	default:
+		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+	}
+}
+
+/*
+ * Send a LS Accept
+ */
+static void
+bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
+				struct fchs_s *rx_fchs)
+{
+	struct fchs_s fchs;
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_rport_s *bfa_rport = NULL;
+	int             len;
+
+	bfa_trc(port->fcs, rx_fchs->s_id);
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+
+	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			      rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+			      rx_fchs->ox_id);
+
+	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
+			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+			  FC_MAX_PDUSZ, 0);
+}
+
+/**
+ *     This routine will be called by bfa_timer on timer timeouts.
+ *
+ *	param[in]	vport		- pointer to bfa_fcs_lport_t.
+ *	param[out]	vport_status	- pointer to return vport status in
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+static void
+bfa_fcs_lport_scn_timeout(void *arg)
+{
+	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
+
+	bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
+}
+
+
+
+/**
+ *  fcs_scn_public FCS state change notification public interfaces
+ */
+
+/*
+ * Functions called by port/fab
+ */
+void
+bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+	scn->port = port;
+	bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+}
+
+void
+bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+	scn->port = port;
+	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+	scn->port = port;
+	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
+}
+
+static void
+bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	bfa_trc(port->fcs, rpid);
+
+	/**
+	 * If this is an unknown device, then it just came online.
+	 * Otherwise let rport handle the RSCN event.
+	 */
+	rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
+	if (rport == NULL) {
+		/*
+		 * If min cfg mode is enabled, we donot need to
+		 * discover any new rports.
+		 */
+		if (!__fcs_min_cfg(port->fcs))
+			rport = bfa_fcs_rport_create(port, rpid);
+	} else
+		bfa_fcs_rport_scn(rport);
+}
+
+/**
+ * rscn format based PID comparison
+ */
+#define __fc_pid_match(__c0, __c1, __fmt)		\
+	(((__fmt) == FC_RSCN_FORMAT_FABRIC) ||		\
+	 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) &&		\
+	  ((__c0)[0] == (__c1)[0])) ||				\
+	 (((__fmt) == FC_RSCN_FORMAT_AREA) &&		\
+	  ((__c0)[0] == (__c1)[0]) &&				\
+	  ((__c0)[1] == (__c1)[1])))
+
+static void
+bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
+				enum fc_rscn_format format,
+				u32 rscn_pid)
+{
+	struct bfa_fcs_rport_s *rport;
+	struct list_head        *qe, *qe_next;
+	u8        *c0, *c1;
+
+	bfa_trc(port->fcs, format);
+	bfa_trc(port->fcs, rscn_pid);
+
+	c0 = (u8 *) &rscn_pid;
+
+	list_for_each_safe(qe, qe_next, &port->rport_q) {
+		rport = (struct bfa_fcs_rport_s *) qe;
+		c1 = (u8 *) &rport->pid;
+		if (__fc_pid_match(c0, c1, format))
+			bfa_fcs_rport_scn(rport);
+	}
+}
+
+
+void
+bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
+			struct fchs_s *fchs, u32 len)
+{
+	struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
+	int             num_entries;
+	u32        rscn_pid;
+	bfa_boolean_t   nsquery = BFA_FALSE, found;
+	int             i = 0, j;
+
+	num_entries =
+		(bfa_os_ntohs(rscn->payldlen) -
+		 sizeof(u32)) / sizeof(rscn->event[0]);
+
+	bfa_trc(port->fcs, num_entries);
+
+	port->stats.num_rscn++;
+
+	bfa_fcs_lport_scn_send_ls_acc(port, fchs);
+
+	for (i = 0; i < num_entries; i++) {
+		rscn_pid = rscn->event[i].portid;
+
+		bfa_trc(port->fcs, rscn->event[i].format);
+		bfa_trc(port->fcs, rscn_pid);
+
+		/* check for duplicate entries in the list */
+		found = BFA_FALSE;
+		for (j = 0; j < i; j++) {
+			if (rscn->event[j].portid == rscn_pid) {
+				found = BFA_TRUE;
+				break;
+			}
+		}
+
+		/* if found in down the list, pid has been already processed */
+		if (found) {
+			bfa_trc(port->fcs, rscn_pid);
+			continue;
+		}
+
+		switch (rscn->event[i].format) {
+		case FC_RSCN_FORMAT_PORTID:
+			if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
+				/*
+				 * Ignore this event.
+				 * f/w would have processed it
+				 */
+				bfa_trc(port->fcs, rscn_pid);
+			} else {
+				port->stats.num_portid_rscn++;
+				bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
+			}
+		break;
+
+		case FC_RSCN_FORMAT_FABRIC:
+			if (rscn->event[i].qualifier ==
+					FC_FABRIC_NAME_RSCN_EVENT) {
+				bfa_fcs_lport_ms_fabric_rscn(port);
+				break;
+			}
+			/* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
+
+		case FC_RSCN_FORMAT_AREA:
+		case FC_RSCN_FORMAT_DOMAIN:
+			nsquery = BFA_TRUE;
+			bfa_fcs_lport_scn_multiport_rscn(port,
+							rscn->event[i].format,
+							rscn_pid);
+			break;
+
+
+		default:
+			bfa_assert(0);
+			nsquery = BFA_TRUE;
+		}
+	}
+
+	/**
+	 * If any of area, domain or fabric RSCN is received, do a fresh discovery
+	 * to find new devices.
+	 */
+	if (nsquery)
+		bfa_fcs_lport_ns_query(port);
+}
+
+/**
+ * BFA FCS port
+ */
+/**
+ *  fcs_port_api BFA FCS port API
+ */
+struct bfa_fcs_lport_s *
+bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
+{
+	return &fcs->fabric.bport;
+}
+
+wwn_t
+bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
+		int nrports, bfa_boolean_t bwwn)
+{
+	struct list_head	*qh, *qe;
+	struct bfa_fcs_rport_s *rport = NULL;
+	int	i;
+	struct bfa_fcs_s	*fcs;
+
+	if (port == NULL || nrports == 0)
+		return (wwn_t) 0;
+
+	fcs = port->fcs;
+	bfa_trc(fcs, (u32) nrports);
+
+	i = 0;
+	qh = &port->rport_q;
+	qe = bfa_q_first(qh);
+
+	while ((qe != qh) && (i < nrports)) {
+		rport = (struct bfa_fcs_rport_s *) qe;
+		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+			qe = bfa_q_next(qe);
+			bfa_trc(fcs, (u32) rport->pwwn);
+			bfa_trc(fcs, rport->pid);
+			bfa_trc(fcs, i);
+			continue;
+		}
+
+		if (bwwn) {
+			if (!memcmp(&wwn, &rport->pwwn, 8))
+				break;
+		} else {
+			if (i == index)
+				break;
+		}
+
+		i++;
+		qe = bfa_q_next(qe);
+	}
+
+	bfa_trc(fcs, i);
+	if (rport)
+		return rport->pwwn;
+	else
+		return (wwn_t) 0;
+}
+
+void
+bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
+	 wwn_t rport_wwns[], int *nrports)
+{
+	struct list_head	*qh, *qe;
+	struct bfa_fcs_rport_s *rport = NULL;
+	int	i;
+	struct bfa_fcs_s	*fcs;
+
+	if (port == NULL || rport_wwns == NULL || *nrports == 0)
+		return;
+
+	fcs = port->fcs;
+	bfa_trc(fcs, (u32) *nrports);
+
+	i = 0;
+	qh = &port->rport_q;
+	qe = bfa_q_first(qh);
+
+	while ((qe != qh) && (i < *nrports)) {
+		rport = (struct bfa_fcs_rport_s *) qe;
+		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+			qe = bfa_q_next(qe);
+			bfa_trc(fcs, (u32) rport->pwwn);
+			bfa_trc(fcs, rport->pid);
+			bfa_trc(fcs, i);
+			continue;
+		}
+
+		rport_wwns[i] = rport->pwwn;
+
+		i++;
+		qe = bfa_q_next(qe);
+	}
+
+	bfa_trc(fcs, i);
+	*nrports = i;
+}
+
+/*
+ * Iterate's through all the rport's in the given port to
+ * determine the maximum operating speed.
+ *
+ * !!!! To be used in TRL Functionality only !!!!
+ */
+bfa_port_speed_t
+bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
+{
+	struct list_head *qh, *qe;
+	struct bfa_fcs_rport_s *rport = NULL;
+	struct bfa_fcs_s	*fcs;
+	bfa_port_speed_t max_speed = 0;
+	struct bfa_port_attr_s port_attr;
+	bfa_port_speed_t port_speed, rport_speed;
+	bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
+
+
+	if (port == NULL)
+		return 0;
+
+	fcs = port->fcs;
+
+	/* Get Physical port's current speed */
+	bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
+	port_speed = port_attr.speed;
+	bfa_trc(fcs, port_speed);
+
+	qh = &port->rport_q;
+	qe = bfa_q_first(qh);
+
+	while (qe != qh) {
+		rport = (struct bfa_fcs_rport_s *) qe;
+		if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) ||
+			(bfa_fcs_rport_get_state(rport) ==
+			  BFA_RPORT_OFFLINE)) {
+			qe = bfa_q_next(qe);
+			continue;
+		}
+
+		rport_speed = rport->rpf.rpsc_speed;
+		if ((trl_enabled) && (rport_speed ==
+			BFA_PORT_SPEED_UNKNOWN)) {
+			/* Use default ratelim speed setting */
+			rport_speed =
+				bfa_fcport_get_ratelim_speed(port->fcs->bfa);
+		}
+
+		if	((rport_speed  == BFA_PORT_SPEED_8GBPS) ||
+			(rport_speed > port_speed)) {
+			max_speed = rport_speed;
+			break;
+		} else if (rport_speed > max_speed) {
+			max_speed = rport_speed;
+		}
+
+		qe = bfa_q_next(qe);
+	}
+
+	bfa_trc(fcs, max_speed);
+	return max_speed;
+}
+
+struct bfa_fcs_lport_s *
+bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
+{
+	struct bfa_fcs_vport_s *vport;
+	bfa_fcs_vf_t   *vf;
+
+	bfa_assert(fcs != NULL);
+
+	vf = bfa_fcs_vf_lookup(fcs, vf_id);
+	if (vf == NULL) {
+		bfa_trc(fcs, vf_id);
+		return NULL;
+	}
+
+	if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
+		return &vf->bport;
+
+	vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
+	if (vport)
+		return &vport->lport;
+
+	return NULL;
+}
+
+/*
+ *  API corresponding to NPIV_VPORT_GETINFO.
+ */
+void
+bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
+	 struct bfa_lport_info_s *port_info)
+{
+
+	bfa_trc(port->fcs, port->fabric->fabric_name);
+
+	if (port->vport == NULL) {
+		/*
+		 * This is a Physical port
+		 */
+		port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
+
+		/*
+		 * @todo : need to fix the state & reason
+		 */
+		port_info->port_state = 0;
+		port_info->offline_reason = 0;
+
+		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
+		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
+
+		port_info->max_vports_supp =
+			bfa_lps_get_max_vport(port->fcs->bfa);
+		port_info->num_vports_inuse =
+			bfa_fcs_fabric_vport_count(port->fabric);
+		port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
+		port_info->num_rports_inuse = port->num_rports;
+	} else {
+		/*
+		 * This is a virtual port
+		 */
+		port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
+
+		/*
+		 * @todo : need to fix the state & reason
+		 */
+		port_info->port_state = 0;
+		port_info->offline_reason = 0;
+
+		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
+		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
+	}
+}
+
+void
+bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
+	 struct bfa_lport_stats_s *port_stats)
+{
+	*port_stats = fcs_port->stats;
+}
+
+void
+bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
+{
+	bfa_os_memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
+}
+
+/**
+ * FCS virtual port state machine
+ */
+
+#define __vport_fcs(__vp)       ((__vp)->lport.fcs)
+#define __vport_pwwn(__vp)      ((__vp)->lport.port_cfg.pwwn)
+#define __vport_nwwn(__vp)      ((__vp)->lport.port_cfg.nwwn)
+#define __vport_bfa(__vp)       ((__vp)->lport.fcs->bfa)
+#define __vport_fcid(__vp)      ((__vp)->lport.pid)
+#define __vport_fabric(__vp)    ((__vp)->lport.fabric)
+#define __vport_vfid(__vp)      ((__vp)->lport.fabric->vf_id)
+
+#define BFA_FCS_VPORT_MAX_RETRIES  5
+/*
+ * Forward declarations
+ */
+static void     bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
+static void     bfa_fcs_vport_timeout(void *vport_arg);
+static void     bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
+static void     bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
+
+/**
+ *  fcs_vport_sm FCS virtual port state machine
+ */
+
+/**
+ * VPort State Machine events
+ */
+enum bfa_fcs_vport_event {
+	BFA_FCS_VPORT_SM_CREATE = 1,	/*  vport create event */
+	BFA_FCS_VPORT_SM_DELETE = 2,	/*  vport delete event */
+	BFA_FCS_VPORT_SM_START = 3,	/*  vport start request */
+	BFA_FCS_VPORT_SM_STOP = 4,	/*  stop: unsupported */
+	BFA_FCS_VPORT_SM_ONLINE = 5,	/*  fabric online */
+	BFA_FCS_VPORT_SM_OFFLINE = 6,	/*  fabric offline event */
+	BFA_FCS_VPORT_SM_FRMSENT = 7,	/*  fdisc/logo sent events */
+	BFA_FCS_VPORT_SM_RSP_OK = 8,	/*  good response */
+	BFA_FCS_VPORT_SM_RSP_ERROR = 9,	/*  error/bad response */
+	BFA_FCS_VPORT_SM_TIMEOUT = 10,	/*  delay timer event */
+	BFA_FCS_VPORT_SM_DELCOMP = 11,	/*  lport delete completion */
+	BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,	/*  Dup wnn error*/
+	BFA_FCS_VPORT_SM_RSP_FAILED = 13,	/*  non-retryable failure */
+};
+
+static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
+					enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
+					 enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
+					 enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
+				       enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
+					     enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
+					enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
+					  enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
+					 enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
+				      enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
+				      enum bfa_fcs_vport_event event);
+
+static struct bfa_sm_table_s  vport_sm_table[] = {
+	{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
+	{BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
+	{BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
+	{BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
+	{BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
+	{BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
+	{BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
+	{BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
+	{BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
+	{BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
+};
+
+/**
+ * Beginning state.
+ */
+static void
+bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_CREATE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+		bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Created state - a start event is required to start up the state machine.
+ */
+static void
+bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_START:
+		if (bfa_fcs_fabric_is_online(__vport_fabric(vport))
+		    && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
+			bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+			bfa_fcs_vport_do_fdisc(vport);
+		} else {
+			/**
+			 * Fabric is offline or not NPIV capable, stay in
+			 * offline state.
+			 */
+			vport->vport_stats.fab_no_npiv++;
+			bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+		}
+		break;
+
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_ONLINE:
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		/**
+		 * Ignore ONLINE/OFFLINE events from fabric
+		 * till vport is started.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Offline state - awaiting ONLINE event from fabric SM.
+ */
+static void
+bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_ONLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+		vport->fdisc_retries = 0;
+		bfa_fcs_vport_do_fdisc(vport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		/*
+		 * This can happen if the vport couldn't be initialzied
+		 * due the fact that the npiv was not enabled on the switch.
+		 * In that case we will put the vport in offline state.
+		 * However, the link can go down and cause the this event to
+		 * be sent when we are already offline. Ignore it.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+
+/**
+ * FDISC is sent and awaiting reply from fabric.
+ */
+static void
+bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_lps_discard(vport->lps);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+		bfa_lps_discard(vport->lps);
+		break;
+
+	case BFA_FCS_VPORT_SM_RSP_OK:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
+		bfa_fcs_lport_online(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_RSP_ERROR:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
+		bfa_timer_start(__vport_bfa(vport), &vport->timer,
+				    bfa_fcs_vport_timeout, vport,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case BFA_FCS_VPORT_SM_RSP_FAILED:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+		break;
+
+	case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * FDISC attempt failed - a timer is active to retry FDISC.
+ */
+static void
+bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
+			     enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_timer_stop(&vport->timer);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+		bfa_timer_stop(&vport->timer);
+		break;
+
+	case BFA_FCS_VPORT_SM_TIMEOUT:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+		vport->vport_stats.fdisc_retries++;
+		vport->fdisc_retries++;
+		bfa_fcs_vport_do_fdisc(vport);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Vport is online (FDISC is complete).
+ */
+static void
+bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+		bfa_lps_discard(vport->lps);
+		bfa_fcs_lport_offline(&vport->lport);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Vport is being deleted - awaiting lport delete completion to send
+ * LOGO to fabric.
+ */
+static void
+bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		break;
+
+	case BFA_FCS_VPORT_SM_DELCOMP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
+		bfa_fcs_vport_do_logo(vport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Error State.
+ * This state will be set when the Vport Creation fails due
+ * to errors like Dup WWN. In this state only operation allowed
+ * is a Vport Delete.
+ */
+static void
+bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	default:
+		bfa_trc(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Lport cleanup is in progress since vport is being deleted. Fabric is
+ * offline, so no LOGO is needed to complete vport deletion.
+ */
+static void
+bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELCOMP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+		bfa_fcs_vport_free(vport);
+		break;
+
+	case BFA_FCS_VPORT_SM_DELETE:
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
+ * is done.
+ */
+static void
+bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_lps_discard(vport->lps);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case BFA_FCS_VPORT_SM_RSP_OK:
+	case BFA_FCS_VPORT_SM_RSP_ERROR:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+		bfa_fcs_vport_free(vport);
+		break;
+
+	case BFA_FCS_VPORT_SM_DELETE:
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+
+
+/**
+ *  fcs_vport_private FCS virtual port private functions
+ */
+/**
+ * This routine will be called to send a FDISC command.
+ */
+static void
+bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
+{
+	bfa_lps_fdisc(vport->lps, vport,
+		bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
+		__vport_pwwn(vport), __vport_nwwn(vport));
+	vport->vport_stats.fdisc_sent++;
+}
+
+static void
+bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
+{
+	u8		lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps);
+	u8		lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps);
+
+	bfa_trc(__vport_fcs(vport), lsrjt_rsn);
+	bfa_trc(__vport_fcs(vport), lsrjt_expl);
+
+	/* For certain reason codes, we don't want to retry. */
+	switch (bfa_lps_get_lsrjt_expl(vport->lps)) {
+	case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
+	case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
+		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+		else
+			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
+		break;
+
+	case FC_LS_RJT_EXP_INSUFF_RES:
+		/*
+		 * This means max logins per port/switch setting on the
+		 * switch was exceeded.
+		 */
+		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+		else
+			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
+		break;
+
+	default:
+		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+	}
+}
+
+/**
+ *	Called to send a logout to the fabric. Used when a V-Port is
+ *	deleted/stopped.
+ */
+static void
+bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+
+	vport->vport_stats.logo_sent++;
+	bfa_lps_fdisclogo(vport->lps);
+}
+
+
+/**
+ *     This routine will be called by bfa_timer on timer timeouts.
+ *
+ *	param[in]	vport		- pointer to bfa_fcs_vport_t.
+ *	param[out]	vport_status	- pointer to return vport status in
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+static void
+bfa_fcs_vport_timeout(void *vport_arg)
+{
+	struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
+
+	vport->vport_stats.fdisc_timeouts++;
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
+}
+
+static void
+bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
+{
+	struct bfad_vport_s *vport_drv =
+			(struct bfad_vport_s *)vport->vport_drv;
+
+	bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
+
+	if (vport_drv->comp_del)
+		complete(vport_drv->comp_del);
+
+	bfa_lps_delete(vport->lps);
+}
+
+
+
+/**
+ *  fcs_vport_public FCS virtual port public interfaces
+ */
+
+/**
+ * Online notification from fabric SM.
+ */
+void
+bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
+{
+	vport->vport_stats.fab_online++;
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+}
+
+/**
+ * Offline notification from fabric SM.
+ */
+void
+bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
+{
+	vport->vport_stats.fab_offline++;
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
+}
+
+/**
+ * Cleanup notification from fabric SM on link timer expiry.
+ */
+void
+bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
+{
+	vport->vport_stats.fab_cleanup++;
+}
+/**
+ * delete notification from fabric SM. To be invoked from within FCS.
+ */
+void
+bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
+{
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
+}
+
+/**
+ * Delete completion callback from associated lport
+ */
+void
+bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
+{
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
+}
+
+
+
+/**
+ *  fcs_vport_api Virtual port API
+ */
+
+/**
+ *	Use this function to instantiate a new FCS vport object. This
+ *	function will not trigger any HW initialization process (which will be
+ *	done in vport_start() call)
+ *
+ *	param[in] vport	-		pointer to bfa_fcs_vport_t. This space
+ *					needs to be allocated by the driver.
+ *	param[in] fcs		-	FCS instance
+ *	param[in] vport_cfg	-	vport configuration
+ *	param[in] vf_id		-	VF_ID if vport is created within a VF.
+ *					FC_VF_ID_NULL to specify base fabric.
+ *	param[in] vport_drv	-	Opaque handle back to the driver's vport
+ *					structure
+ *
+ *	retval BFA_STATUS_OK - on success.
+ *	retval BFA_STATUS_FAILED - on failure.
+ */
+bfa_status_t
+bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
+		u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
+		struct bfad_vport_s *vport_drv)
+{
+	if (vport_cfg->pwwn == 0)
+		return BFA_STATUS_INVALID_WWN;
+
+	if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
+		return BFA_STATUS_VPORT_WWN_BP;
+
+	if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
+		return BFA_STATUS_VPORT_EXISTS;
+
+	if (bfa_fcs_fabric_vport_count(&fcs->fabric) ==
+			bfa_lps_get_max_vport(fcs->bfa))
+		return BFA_STATUS_VPORT_MAX;
+
+	vport->lps = bfa_lps_alloc(fcs->bfa);
+	if (!vport->lps)
+		return BFA_STATUS_VPORT_MAX;
+
+	vport->vport_drv = vport_drv;
+	vport_cfg->preboot_vp = BFA_FALSE;
+
+	bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+	bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
+	bfa_fcs_lport_init(&vport->lport, vport_cfg);
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Use this function to instantiate a new FCS PBC vport object. This
+ *	function will not trigger any HW initialization process (which will be
+ *	done in vport_start() call)
+ *
+ *	param[in] vport	-	pointer to bfa_fcs_vport_t. This space
+ *				needs to be allocated by the driver.
+ *	param[in] fcs	-	FCS instance
+ *	param[in] vport_cfg	-	vport configuration
+ *	param[in] vf_id		-	VF_ID if vport is created within a VF.
+ *					FC_VF_ID_NULL to specify base fabric.
+ *	param[in] vport_drv	-	Opaque handle back to the driver's vport
+ *					structure
+ *
+ *	retval BFA_STATUS_OK - on success.
+ *	retval BFA_STATUS_FAILED - on failure.
+ */
+bfa_status_t
+bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
+			u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
+			struct bfad_vport_s *vport_drv)
+{
+	bfa_status_t rc;
+
+	rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
+	vport->lport.port_cfg.preboot_vp = BFA_TRUE;
+
+	return rc;
+}
+
+/**
+ *	Use this function to findout if this is a pbc vport or not.
+ *
+ * @param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ * @returns None
+ */
+bfa_boolean_t
+bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
+{
+
+	if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
+		return BFA_TRUE;
+	else
+		return BFA_FALSE;
+
+}
+
+/**
+ * Use this function initialize the vport.
+ *
+ * @param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ * @returns None
+ */
+bfa_status_t
+bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
+{
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Use this function quiese the vport object. This function will return
+ *	immediately, when the vport is actually stopped, the
+ *	bfa_drv_vport_stop_cb() will be called.
+ *
+ *	param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ *	return None
+ */
+bfa_status_t
+bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
+{
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Use this function to delete a vport object. Fabric object should
+ *	be stopped before this function call.
+ *
+ *	!!!!!!! Donot invoke this from within FCS  !!!!!!!
+ *
+ *	param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ *	return     None
+ */
+bfa_status_t
+bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
+{
+
+	if (vport->lport.port_cfg.preboot_vp)
+		return BFA_STATUS_PBC;
+
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Use this function to get vport's current status info.
+ *
+ *	param[in] vport		pointer to bfa_fcs_vport_t.
+ *	param[out] attr		pointer to return vport attributes
+ *
+ *	return None
+ */
+void
+bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
+			struct bfa_vport_attr_s *attr)
+{
+	if (vport == NULL || attr == NULL)
+		return;
+
+	bfa_os_memset(attr, 0, sizeof(struct bfa_vport_attr_s));
+
+	bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
+	attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
+}
+
+/**
+ *	Use this function to get vport's statistics.
+ *
+ *	param[in]	vport	pointer to bfa_fcs_vport_t.
+ *	param[out]	stats	pointer to return vport statistics in
+ *
+ *	return None
+ */
+void
+bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
+			struct bfa_vport_stats_s *stats)
+{
+	*stats = vport->vport_stats;
+}
+
+/**
+ *	Use this function to clear vport's statistics.
+ *
+ *	param[in]	vport	pointer to bfa_fcs_vport_t.
+ *
+ *	return None
+ */
+void
+bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport)
+{
+	bfa_os_memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
+}
+
+/**
+ *	Lookup a virtual port. Excludes base port from lookup.
+ */
+struct bfa_fcs_vport_s *
+bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
+{
+	struct bfa_fcs_vport_s *vport;
+	struct bfa_fcs_fabric_s *fabric;
+
+	bfa_trc(fcs, vf_id);
+	bfa_trc(fcs, vpwwn);
+
+	fabric = bfa_fcs_vf_lookup(fcs, vf_id);
+	if (!fabric) {
+		bfa_trc(fcs, vf_id);
+		return NULL;
+	}
+
+	vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
+	return vport;
+}
+
+/**
+ * FDISC Response
+ */
+void
+bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
+{
+	struct bfa_fcs_vport_s *vport = uarg;
+
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), status);
+
+	switch (status) {
+	case BFA_STATUS_OK:
+		/*
+		 * Initialiaze the V-Port fields
+		 */
+		__vport_fcid(vport) = bfa_lps_get_pid(vport->lps);
+		vport->vport_stats.fdisc_accepts++;
+		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
+		break;
+
+	case BFA_STATUS_INVALID_MAC:
+		/* Only for CNA */
+		vport->vport_stats.fdisc_acc_bad++;
+		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+
+		break;
+
+	case BFA_STATUS_EPROTOCOL:
+		switch (bfa_lps_get_extstatus(vport->lps)) {
+		case BFA_EPROTO_BAD_ACCEPT:
+			vport->vport_stats.fdisc_acc_bad++;
+			break;
+
+		case BFA_EPROTO_UNKNOWN_RSP:
+			vport->vport_stats.fdisc_unknown_rsp++;
+			break;
+
+		default:
+			break;
+		}
+
+		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+		break;
+
+	case BFA_STATUS_FABRIC_RJT:
+		vport->vport_stats.fdisc_rejects++;
+		bfa_fcs_vport_fdisc_rejected(vport);
+		break;
+
+	default:
+		vport->vport_stats.fdisc_rsp_err++;
+		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+	}
+}
+
+/**
+ * LOGO response
+ */
+void
+bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
+{
+	struct bfa_fcs_vport_s *vport = uarg;
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
+}
+
+/**
+ * Received clear virtual link
+ */
+void
+bfa_cb_lps_cvl_event(void *bfad, void *uarg)
+{
+	struct bfa_fcs_vport_s *vport = uarg;
+
+	/* Send an Offline followed by an ONLINE */
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+}
diff --git a/drivers/scsi/bfa/bfa_fcs_port.c b/drivers/scsi/bfa/bfa_fcs_port.c
deleted file mode 100644
index 3c27788..0000000
--- a/drivers/scsi/bfa/bfa_fcs_port.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcs_pport.c BFA FCS PPORT ( physical port)
- */
-
-#include <fcs/bfa_fcs.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs_fabric.h>
-#include "fcs_trcmod.h"
-#include "fcs.h"
-#include "fcs_fabric.h"
-#include "fcs_port.h"
-
-BFA_TRC_FILE(FCS, PPORT);
-
-static void
-bfa_fcs_pport_event_handler(void *cbarg, bfa_pport_event_t event)
-{
-	struct bfa_fcs_s      *fcs = cbarg;
-
-	bfa_trc(fcs, event);
-
-	switch (event) {
-	case BFA_PPORT_LINKUP:
-		bfa_fcs_fabric_link_up(&fcs->fabric);
-		break;
-
-	case BFA_PPORT_LINKDOWN:
-		bfa_fcs_fabric_link_down(&fcs->fabric);
-		break;
-
-	case BFA_PPORT_TRUNK_LINKDOWN:
-		bfa_assert(0);
-		break;
-
-	default:
-		bfa_assert(0);
-	}
-}
-
-void
-bfa_fcs_pport_attach(struct bfa_fcs_s *fcs)
-{
-	bfa_fcport_event_register(fcs->bfa, bfa_fcs_pport_event_handler, fcs);
-}
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
new file mode 100644
index 0000000..635f0cd
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -0,0 +1,3126 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+/**
+ *  rport.c Remote port implementation.
+ */
+
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
+#include "bfad_drv.h"
+
+BFA_TRC_FILE(FCS, RPORT);
+
+static u32
+bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
+	 /* In millisecs */
+/*
+ * forward declarations
+ */
+static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(
+		struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);
+static void	bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
+static void	bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
+static void	bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
+static void	bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
+static void	bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
+					struct fc_logi_s *plogi);
+static void	bfa_fcs_rport_timeout(void *arg);
+static void	bfa_fcs_rport_send_plogi(void *rport_cbarg,
+					 struct bfa_fcxp_s *fcxp_alloced);
+static void	bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
+					struct bfa_fcxp_s *fcxp_alloced);
+static void	bfa_fcs_rport_plogi_response(void *fcsarg,
+				struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs);
+static void	bfa_fcs_rport_send_adisc(void *rport_cbarg,
+					 struct bfa_fcxp_s *fcxp_alloced);
+static void	bfa_fcs_rport_adisc_response(void *fcsarg,
+				struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs);
+static void	bfa_fcs_rport_send_nsdisc(void *rport_cbarg,
+					 struct bfa_fcxp_s *fcxp_alloced);
+static void	bfa_fcs_rport_gidpn_response(void *fcsarg,
+				struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs);
+static void	bfa_fcs_rport_gpnid_response(void *fcsarg,
+				struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs);
+static void	bfa_fcs_rport_send_logo(void *rport_cbarg,
+					struct bfa_fcxp_s *fcxp_alloced);
+static void	bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
+static void	bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
+					struct fchs_s *rx_fchs, u16 len);
+static void	bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
+				struct fchs_s *rx_fchs, u8 reason_code,
+					  u8 reason_code_expl);
+static void	bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
+				struct fchs_s *rx_fchs, u16 len);
+static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
+/**
+ *  fcs_rport_sm FCS rport state machine events
+ */
+
+enum rport_event {
+	RPSM_EVENT_PLOGI_SEND	= 1,	/*  new rport; start with PLOGI */
+	RPSM_EVENT_PLOGI_RCVD	= 2,	/*  Inbound PLOGI from remote port */
+	RPSM_EVENT_PLOGI_COMP	= 3,	/*  PLOGI completed to rport	*/
+	RPSM_EVENT_LOGO_RCVD	= 4,	/*  LOGO from remote device	*/
+	RPSM_EVENT_LOGO_IMP	= 5,	/*  implicit logo for SLER	*/
+	RPSM_EVENT_FCXP_SENT	= 6,	/*  Frame from has been sent	*/
+	RPSM_EVENT_DELETE	= 7,	/*  RPORT delete request	*/
+	RPSM_EVENT_SCN		= 8,	/*  state change notification	*/
+	RPSM_EVENT_ACCEPTED	= 9,	/*  Good response from remote device */
+	RPSM_EVENT_FAILED	= 10,	/*  Request to rport failed.	*/
+	RPSM_EVENT_TIMEOUT	= 11,	/*  Rport SM timeout event	*/
+	RPSM_EVENT_HCB_ONLINE  = 12,	/*  BFA rport online callback	*/
+	RPSM_EVENT_HCB_OFFLINE = 13,	/*  BFA rport offline callback	*/
+	RPSM_EVENT_FC4_OFFLINE = 14,	/*  FC-4 offline complete	*/
+	RPSM_EVENT_ADDRESS_CHANGE = 15,	/*  Rport's PID has changed	*/
+	RPSM_EVENT_ADDRESS_DISC = 16,	/*  Need to Discover rport's PID */
+	RPSM_EVENT_PRLO_RCVD   = 17,	/*  PRLO from remote device	*/
+	RPSM_EVENT_PLOGI_RETRY = 18,	/*  Retry PLOGI continously */
+};
+
+static void	bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
+					enum rport_event event);
+static void	bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
+						  enum rport_event event);
+static void	bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
+					enum rport_event event);
+static void	bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
+					enum rport_event event);
+static void	bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
+						 enum rport_event event);
+static void	bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
+					 enum rport_event event);
+static void	bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
+					enum rport_event event);
+static void	bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
+					 enum rport_event event);
+static void	bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+
+static struct bfa_sm_table_s rport_sm_table[] = {
+	{BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
+	{BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
+	{BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
+	{BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
+	{BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
+	{BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
+	{BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
+	{BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
+	{BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
+	{BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
+	{BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
+	{BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
+	{BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
+	{BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
+	{BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
+	{BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
+	{BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
+	{BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
+	{BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
+	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
+	{BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
+	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
+};
+
+/**
+ *		Beginning state.
+ */
+static void
+bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_PLOGI_SEND:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+		rport->plogi_retries = 0;
+		bfa_fcs_rport_send_plogi(rport, NULL);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_ADDRESS_DISC:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		PLOGI is being sent.
+ */
+static void
+bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_SCN:
+		/* query the NS */
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		PLOGI is being sent.
+ */
+static void
+bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+	case RPSM_EVENT_SCN:
+		/**
+		 * Ignore, SCN is possibly online notification.
+		 */
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_HCB_OFFLINE:
+		/**
+		 * Ignore BFA callback, on a PLOGI receive we call bfa offline.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		PLOGI is sent.
+ */
+static void
+bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+		bfa_fcs_rport_send_plogi(rport, NULL);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_LOGO_RCVD:
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_SCN:
+		bfa_timer_stop(&rport->timer);
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_timer_stop(&rport->timer);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		PLOGI is sent.
+ */
+static void
+bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_ACCEPTED:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		rport->plogi_retries = 0;
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+		bfa_fcs_rport_send_logo_acc(rport);
+		/*
+		 * !! fall through !!
+		 */
+	case RPSM_EVENT_PRLO_RCVD:
+		if (rport->prlo == BFA_TRUE)
+			bfa_fcs_rport_send_prlo_acc(rport);
+
+		bfa_fcxp_discard(rport->fcxp);
+		/*
+		 * !! fall through !!
+		 */
+	case RPSM_EVENT_FAILED:
+		if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
+			rport->plogi_retries++;
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
+			bfa_timer_start(rport->fcs->bfa, &rport->timer,
+					bfa_fcs_rport_timeout, rport,
+					BFA_FCS_RETRY_TIMEOUT);
+		} else {
+			bfa_stats(rport->port, rport_del_max_plogi_retry);
+			rport->pid = 0;
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+			bfa_timer_start(rport->fcs->bfa, &rport->timer,
+					bfa_fcs_rport_timeout, rport,
+					bfa_fcs_rport_del_timeout);
+		}
+		break;
+
+	case	RPSM_EVENT_PLOGI_RETRY:
+		rport->plogi_retries = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				(FC_RA_TOV * 1000));
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_SCN:
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		PLOGI is complete. Awaiting BFA rport online callback. FC-4s
+ *		are offline.
+ */
+static void
+bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_HCB_ONLINE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
+		bfa_fcs_rport_online_action(rport);
+		break;
+
+	case RPSM_EVENT_PRLO_RCVD:
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_rport_offline(rport->bfa_rport);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+		/**
+		 * @todo
+		 * Ignore SCN - PLOGI just completed, FC-4 login should detect
+		 * device failures.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is ONLINE. FC-4s active.
+ */
+static void
+bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_SCN:
+		if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
+			bfa_sm_set_state(rport,
+					 bfa_fcs_rport_sm_nsquery_sending);
+			rport->ns_retries = 0;
+			bfa_fcs_rport_send_nsdisc(rport, NULL);
+		} else {
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+			bfa_fcs_rport_send_adisc(rport, NULL);
+		}
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+	case RPSM_EVENT_LOGO_IMP:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		An SCN event is received in ONLINE state. NS query is being sent
+ *		prior to ADISC authentication with rport. FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+		/**
+		 * ignore SCN, wait for response to query itself
+		 */
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *	An SCN event is received in ONLINE state. NS query is sent to rport.
+ *	FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_ACCEPTED:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+		bfa_fcs_rport_send_adisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_FAILED:
+		rport->ns_retries++;
+		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
+			bfa_sm_set_state(rport,
+					 bfa_fcs_rport_sm_nsquery_sending);
+			bfa_fcs_rport_send_nsdisc(rport, NULL);
+		} else {
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+			bfa_fcs_rport_offline_action(rport);
+		}
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_PLOGI_RCVD:
+	case RPSM_EVENT_LOGO_IMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *	An SCN event is received in ONLINE state. ADISC is being sent for
+ *	authenticating with rport. FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		An SCN event is received in ONLINE state. ADISC is to rport.
+ *		FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_ACCEPTED:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		/**
+		 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
+		 * At least go offline when a PLOGI is received.
+		 */
+		bfa_fcxp_discard(rport->fcxp);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case RPSM_EVENT_FAILED:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+		/**
+		 * already processing RSCN
+		 */
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport has sent LOGO. Awaiting FC-4 offline completion callback.
+ */
+static void
+bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FC4_OFFLINE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		LOGO needs to be sent to rport. Awaiting FC-4 offline completion
+ *		callback.
+ */
+static void
+bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FC4_OFFLINE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *	Rport is going offline. Awaiting FC-4 offline completion callback.
+ */
+static void
+bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FC4_OFFLINE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_LOGO_IMP:
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		/**
+		 * rport is already going offline.
+		 * SCN - ignore and wait till transitioning to offline state
+		 */
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is offline. FC-4s are offline. Awaiting BFA rport offline
+ *		callback.
+ */
+static void
+bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
+				enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_HCB_OFFLINE:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		if (bfa_fcs_lport_is_online(rport->port)) {
+			if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
+				bfa_sm_set_state(rport,
+					bfa_fcs_rport_sm_nsdisc_sending);
+				rport->ns_retries = 0;
+				bfa_fcs_rport_send_nsdisc(rport, NULL);
+			} else {
+				bfa_sm_set_state(rport,
+					bfa_fcs_rport_sm_plogi_sending);
+				rport->plogi_retries = 0;
+				bfa_fcs_rport_send_plogi(rport, NULL);
+			}
+		} else {
+			rport->pid = 0;
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+			bfa_timer_start(rport->fcs->bfa, &rport->timer,
+					bfa_fcs_rport_timeout, rport,
+					bfa_fcs_rport_del_timeout);
+		}
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		/**
+		 * Ignore, already offline.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is offline. FC-4s are offline. Awaiting BFA rport offline
+ *		callback to send LOGO accept.
+ */
+static void
+bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_HCB_OFFLINE:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		if (rport->pid && (rport->prlo == BFA_TRUE))
+			bfa_fcs_rport_send_prlo_acc(rport);
+		if (rport->pid && (rport->prlo == BFA_FALSE))
+			bfa_fcs_rport_send_logo_acc(rport);
+		/*
+		 * If the lport is online and if the rport is not a well
+		 * known address port,
+		 * we try to re-discover the r-port.
+		 */
+		if (bfa_fcs_lport_is_online(rport->port) &&
+			(!BFA_FCS_PID_IS_WKA(rport->pid))) {
+			bfa_sm_set_state(rport,
+				bfa_fcs_rport_sm_nsdisc_sending);
+			rport->ns_retries = 0;
+			bfa_fcs_rport_send_nsdisc(rport, NULL);
+		} else {
+			/*
+			 * if it is not a well known address, reset the
+			 * pid to 0.
+			 */
+			if (!BFA_FCS_PID_IS_WKA(rport->pid))
+				rport->pid = 0;
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+			bfa_timer_start(rport->fcs->bfa, &rport->timer,
+					bfa_fcs_rport_timeout, rport,
+					bfa_fcs_rport_del_timeout);
+		}
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		/**
+		 * Ignore - already processing a LOGO.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is being deleted. FC-4s are offline.
+ *  Awaiting BFA rport offline
+ *		callback to send LOGO.
+ */
+static void
+bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
+		 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_HCB_OFFLINE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
+		bfa_fcs_rport_send_logo(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is being deleted. FC-4s are offline. LOGO is being sent.
+ */
+static void
+bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		/* Once LOGO is sent, we donot wait for the response */
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is offline. FC-4s are offline. BFA rport is offline.
+ *		Timer active to delete stale rport.
+ */
+static void
+bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		bfa_timer_stop(&rport->timer);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_LOGO_IMP:
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_SEND:
+		bfa_timer_stop(&rport->timer);
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+		rport->plogi_retries = 0;
+		bfa_fcs_rport_send_plogi(rport, NULL);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *	Rport address has changed. Nameserver discovery request is being sent.
+ */
+static void
+bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_PLOGI_SEND:
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		rport->ns_retries = 0; /* reset the retry count */
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Nameserver discovery failed. Waiting for timeout to retry.
+ */
+static void
+bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		bfa_timer_stop(&rport->timer);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_timer_stop(&rport->timer);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+		bfa_fcs_rport_send_logo_acc(rport);
+		break;
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_fcs_rport_send_prlo_acc(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport address has changed. Nameserver discovery request is sent.
+ */
+static void
+bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_ACCEPTED:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		if (rport->pid) {
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+			bfa_fcs_rport_send_plogi(rport, NULL);
+		} else {
+			bfa_sm_set_state(rport,
+				 bfa_fcs_rport_sm_nsdisc_sending);
+			rport->ns_retries = 0;
+			bfa_fcs_rport_send_nsdisc(rport, NULL);
+		}
+		break;
+
+	case RPSM_EVENT_FAILED:
+		rport->ns_retries++;
+		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
+			bfa_sm_set_state(rport,
+				 bfa_fcs_rport_sm_nsdisc_sending);
+			bfa_fcs_rport_send_nsdisc(rport, NULL);
+		} else {
+			rport->pid = 0;
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+			bfa_timer_start(rport->fcs->bfa, &rport->timer,
+					bfa_fcs_rport_timeout, rport,
+					bfa_fcs_rport_del_timeout);
+		};
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_fcs_rport_send_prlo_acc(rport);
+		break;
+	case RPSM_EVENT_SCN:
+		/**
+		 * ignore, wait for NS query response
+		 */
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+		/**
+		 * Not logged-in yet. Accept LOGO.
+		 */
+		bfa_fcs_rport_send_logo_acc(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+
+
+/**
+ *  fcs_rport_private FCS RPORT provate functions
+ */
+
+static void
+bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
+	int		len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+					bfa_fcs_rport_send_plogi, rport);
+		return;
+	}
+	rport->fcxp = fcxp;
+
+	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+				bfa_fcs_lport_get_fcid(port), 0,
+				port->port_cfg.pwwn, port->port_cfg.nwwn,
+				bfa_fcport_get_maxfrsize(port->fcs->bfa));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
+			(void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
+
+	rport->stats.plogis++;
+	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+	struct fc_logi_s	*plogi_rsp;
+	struct fc_ls_rjt_s	*ls_rjt;
+	struct bfa_fcs_rport_s *twin;
+	struct list_head	*qe;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(rport->fcs, req_status);
+		rport->stats.plogi_failed++;
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		return;
+	}
+
+	plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+	/**
+	 * Check for failure first.
+	 */
+	if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
+		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+		bfa_trc(rport->fcs, ls_rjt->reason_code);
+		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
+
+		if ((ls_rjt->reason_code == FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD) &&
+		 (ls_rjt->reason_code_expl == FC_LS_RJT_EXP_INSUFF_RES)) {
+			rport->stats.rjt_insuff_res++;
+			bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RETRY);
+			return;
+		}
+
+		rport->stats.plogi_rejects++;
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		return;
+	}
+
+	/**
+	 * PLOGI is complete. Make sure this device is not one of the known
+	 * device with a new FC port address.
+	 */
+	list_for_each(qe, &rport->port->rport_q) {
+		twin = (struct bfa_fcs_rport_s *) qe;
+		if (twin == rport)
+			continue;
+		if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
+			bfa_trc(rport->fcs, twin->pid);
+			bfa_trc(rport->fcs, rport->pid);
+
+			/* Update plogi stats in twin */
+			twin->stats.plogis  += rport->stats.plogis;
+			twin->stats.plogi_rejects  +=
+				 rport->stats.plogi_rejects;
+			twin->stats.plogi_timeouts  +=
+				 rport->stats.plogi_timeouts;
+			twin->stats.plogi_failed +=
+				 rport->stats.plogi_failed;
+			twin->stats.plogi_rcvd	  += rport->stats.plogi_rcvd;
+			twin->stats.plogi_accs++;
+
+			bfa_fcs_rport_delete(rport);
+
+			bfa_fcs_rport_update(twin, plogi_rsp);
+			twin->pid = rsp_fchs->s_id;
+			bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
+			return;
+		}
+	}
+
+	/**
+	 * Normal login path -- no evil twins.
+	 */
+	rport->stats.plogi_accs++;
+	bfa_fcs_rport_update(rport, plogi_rsp);
+	bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+}
+
+static void
+bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s		fchs;
+	int		len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->reply_oxid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+					bfa_fcs_rport_send_plogiacc, rport);
+		return;
+	}
+	rport->fcxp = fcxp;
+
+	len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				 rport->pid, bfa_fcs_lport_get_fcid(port),
+				 rport->reply_oxid, port->port_cfg.pwwn,
+				 port->port_cfg.nwwn,
+				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+
+	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s		fchs;
+	int		len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+					bfa_fcs_rport_send_adisc, rport);
+		return;
+	}
+	rport->fcxp = fcxp;
+
+	len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+				bfa_fcs_lport_get_fcid(port), 0,
+				port->port_cfg.pwwn, port->port_cfg.nwwn);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
+			rport, FC_MAX_PDUSZ, FC_ELS_TOV);
+
+	rport->stats.adisc_sent++;
+	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+	void		*pld = bfa_fcxp_get_rspbuf(fcxp);
+	struct fc_ls_rjt_s	*ls_rjt;
+
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(rport->fcs, req_status);
+		rport->stats.adisc_failed++;
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		return;
+	}
+
+	if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
+				rport->nwwn)  == FC_PARSE_OK) {
+		rport->stats.adisc_accs++;
+		bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+		return;
+	}
+
+	rport->stats.adisc_rejects++;
+	ls_rjt = pld;
+	bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
+	bfa_trc(rport->fcs, ls_rjt->reason_code);
+	bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
+	bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+}
+
+static void
+bfa_fcs_rport_send_nsdisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
+	struct bfa_fcxp_s *fcxp;
+	int		len;
+	bfa_cb_fcxp_send_t cbfn;
+
+	bfa_trc(rport->fcs, rport->pid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+					bfa_fcs_rport_send_nsdisc, rport);
+		return;
+	}
+	rport->fcxp = fcxp;
+
+	if (rport->pwwn) {
+		len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				bfa_fcs_lport_get_fcid(port), 0, rport->pwwn);
+		cbfn = bfa_fcs_rport_gidpn_response;
+	} else {
+		len = fc_gpnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				bfa_fcs_lport_get_fcid(port), 0, rport->pid);
+		cbfn = bfa_fcs_rport_gpnid_response;
+	}
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, cbfn,
+			(void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+	struct ct_hdr_s	*cthdr;
+	struct fcgs_gidpn_resp_s	*gidpn_rsp;
+	struct bfa_fcs_rport_s	*twin;
+	struct list_head	*qe;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		/* Check if the pid is the same as before. */
+		gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
+
+		if (gidpn_rsp->dap == rport->pid) {
+			/* Device is online  */
+			bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+		} else {
+			/*
+			 * Device's PID has changed. We need to cleanup
+			 * and re-login. If there is another device with
+			 * the the newly discovered pid, send an scn notice
+			 * so that its new pid can be discovered.
+			 */
+			list_for_each(qe, &rport->port->rport_q) {
+				twin = (struct bfa_fcs_rport_s *) qe;
+				if (twin == rport)
+					continue;
+				if (gidpn_rsp->dap == twin->pid) {
+					bfa_trc(rport->fcs, twin->pid);
+					bfa_trc(rport->fcs, rport->pid);
+
+					twin->pid = 0;
+					bfa_sm_send_event(twin,
+					 RPSM_EVENT_ADDRESS_CHANGE);
+				}
+			}
+			rport->pid = gidpn_rsp->dap;
+			bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
+		}
+		return;
+	}
+
+	/*
+	 * Reject Response
+	 */
+	switch (cthdr->reason_code) {
+	case CT_RSN_LOGICAL_BUSY:
+		/*
+		 * Need to retry
+		 */
+		bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
+		break;
+
+	case CT_RSN_UNABLE_TO_PERF:
+		/*
+		 * device doesn't exist : Start timer to cleanup this later.
+		 */
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		break;
+
+	default:
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		break;
+	}
+}
+
+static void
+bfa_fcs_rport_gpnid_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+	struct ct_hdr_s	*cthdr;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+		return;
+	}
+
+	/*
+	 * Reject Response
+	 */
+	switch (cthdr->reason_code) {
+	case CT_RSN_LOGICAL_BUSY:
+		/*
+		 * Need to retry
+		 */
+		bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
+		break;
+
+	case CT_RSN_UNABLE_TO_PERF:
+		/*
+		 * device doesn't exist : Start timer to cleanup this later.
+		 */
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		break;
+
+	default:
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		break;
+	}
+}
+
+/**
+ *	Called to send a logout to the rport.
+ */
+static void
+bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port;
+	struct fchs_s	fchs;
+	struct bfa_fcxp_s *fcxp;
+	u16	len;
+
+	bfa_trc(rport->fcs, rport->pid);
+
+	port = rport->port;
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+					bfa_fcs_rport_send_logo, rport);
+		return;
+	}
+	rport->fcxp = fcxp;
+
+	len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+				bfa_fcs_lport_get_fcid(port), 0,
+				bfa_fcs_lport_get_pwwn(port));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, NULL,
+			rport, FC_MAX_PDUSZ, FC_ELS_TOV);
+
+	rport->stats.logos++;
+	bfa_fcxp_discard(rport->fcxp);
+	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+/**
+ *	Send ACC for a LOGO received.
+ */
+static void
+bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port;
+	struct fchs_s	fchs;
+	struct bfa_fcxp_s *fcxp;
+	u16	len;
+
+	bfa_trc(rport->fcs, rport->pid);
+
+	port = rport->port;
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+
+	rport->stats.logo_rcvd++;
+	len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rport->pid, bfa_fcs_lport_get_fcid(port),
+				rport->reply_oxid);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+/**
+ *	brief
+ *	This routine will be called by bfa_timer on timer timeouts.
+ *
+ *	param[in]	rport			- pointer to bfa_fcs_lport_ns_t.
+ *	param[out]	rport_status	- pointer to return vport status in
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+static void
+bfa_fcs_rport_timeout(void *arg)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) arg;
+
+	rport->stats.plogi_timeouts++;
+	bfa_stats(rport->port, rport_plogi_timeouts);
+	bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
+}
+
+static void
+bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
+			struct fchs_s *rx_fchs, u16 len)
+{
+	struct bfa_fcxp_s *fcxp;
+	struct fchs_s	fchs;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fc_prli_s	*prli;
+
+	bfa_trc(port->fcs, rx_fchs->s_id);
+	bfa_trc(port->fcs, rx_fchs->d_id);
+
+	rport->stats.prli_rcvd++;
+
+	/*
+	 * We are in Initiator Mode
+	 */
+	prli = (struct fc_prli_s *) (rx_fchs + 1);
+
+	if (prli->parampage.servparams.target) {
+		/*
+		 * PRLI from a target ?
+		 * Send the Acc.
+		 * PRLI sent by us will be used to transition the IT nexus,
+		 * once the response is received from the target.
+		 */
+		bfa_trc(port->fcs, rx_fchs->s_id);
+		rport->scsi_function = BFA_RPORT_TARGET;
+	} else {
+		bfa_trc(rport->fcs, prli->parampage.type);
+		rport->scsi_function = BFA_RPORT_INITIATOR;
+		bfa_fcs_itnim_is_initiator(rport->itnim);
+	}
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+
+	len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+				rx_fchs->ox_id, port->port_cfg.roles);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+static void
+bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
+			struct fchs_s *rx_fchs, u16 len)
+{
+	struct bfa_fcxp_s *fcxp;
+	struct fchs_s	fchs;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fc_rpsc_speed_info_s speeds;
+	struct bfa_port_attr_s pport_attr;
+
+	bfa_trc(port->fcs, rx_fchs->s_id);
+	bfa_trc(port->fcs, rx_fchs->d_id);
+
+	rport->stats.rpsc_rcvd++;
+	speeds.port_speed_cap =
+		RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
+		RPSC_SPEED_CAP_8G;
+
+	/*
+	 * get curent speed from pport attributes from BFA
+	 */
+	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
+
+	speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+
+	len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+				rx_fchs->ox_id, &speeds);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+static void
+bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
+			struct fchs_s *rx_fchs, u16 len)
+{
+	struct bfa_fcxp_s *fcxp;
+	struct fchs_s	fchs;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fc_adisc_s	*adisc;
+
+	bfa_trc(port->fcs, rx_fchs->s_id);
+	bfa_trc(port->fcs, rx_fchs->d_id);
+
+	rport->stats.adisc_rcvd++;
+
+	adisc = (struct fc_adisc_s *) (rx_fchs + 1);
+
+	/*
+	 * Accept if the itnim for this rport is online.
+	 * Else reject the ADISC.
+	 */
+	if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
+
+		fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+		if (!fcxp)
+			return;
+
+		len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+			 rx_fchs->ox_id, port->port_cfg.pwwn,
+			 port->port_cfg.nwwn);
+
+		bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
+				BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+				FC_MAX_PDUSZ, 0);
+	} else {
+		rport->stats.adisc_rejected++;
+		bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
+					  FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
+					  FC_LS_RJT_EXP_LOGIN_REQUIRED);
+	}
+}
+
+static void
+bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct bfa_rport_info_s rport_info;
+
+	rport_info.pid = rport->pid;
+	rport_info.local_pid = port->pid;
+	rport_info.lp_tag = port->lp_tag;
+	rport_info.vf_id = port->fabric->vf_id;
+	rport_info.vf_en = port->fabric->is_vf;
+	rport_info.fc_class = rport->fc_cos;
+	rport_info.cisc = rport->cisc;
+	rport_info.max_frmsz = rport->maxfrsize;
+	bfa_rport_online(rport->bfa_rport, &rport_info);
+}
+
+static struct bfa_fcs_rport_s *
+bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
+{
+	struct bfa_fcs_s	*fcs = port->fcs;
+	struct bfa_fcs_rport_s *rport;
+	struct bfad_rport_s	*rport_drv;
+
+	/**
+	 * allocate rport
+	 */
+	if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
+		!= BFA_STATUS_OK) {
+		bfa_trc(fcs, rpid);
+		return NULL;
+	}
+
+	/*
+	 * Initialize r-port
+	 */
+	rport->port = port;
+	rport->fcs = fcs;
+	rport->rp_drv = rport_drv;
+	rport->pid = rpid;
+	rport->pwwn = pwwn;
+
+	/**
+	 * allocate BFA rport
+	 */
+	rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
+	if (!rport->bfa_rport) {
+		bfa_trc(fcs, rpid);
+		kfree(rport_drv);
+		return NULL;
+	}
+
+	/**
+	 * allocate FC-4s
+	 */
+	bfa_assert(bfa_fcs_lport_is_initiator(port));
+
+	if (bfa_fcs_lport_is_initiator(port)) {
+		rport->itnim = bfa_fcs_itnim_create(rport);
+		if (!rport->itnim) {
+			bfa_trc(fcs, rpid);
+			bfa_rport_delete(rport->bfa_rport);
+			kfree(rport_drv);
+			return NULL;
+		}
+	}
+
+	bfa_fcs_lport_add_rport(port, rport);
+
+	bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+
+	/* Initialize the Rport Features(RPF) Sub Module  */
+	if (!BFA_FCS_PID_IS_WKA(rport->pid))
+		bfa_fcs_rpf_init(rport);
+
+	return rport;
+}
+
+
+static void
+bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+
+	/**
+	 * - delete FC-4s
+	 * - delete BFA rport
+	 * - remove from queue of rports
+	 */
+	if (bfa_fcs_lport_is_initiator(port)) {
+		bfa_fcs_itnim_delete(rport->itnim);
+		if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))
+			bfa_fcs_rpf_rport_offline(rport);
+	}
+
+	bfa_rport_delete(rport->bfa_rport);
+	bfa_fcs_lport_del_rport(port, rport);
+	kfree(rport->rp_drv);
+}
+
+static void
+bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+	char	lpwwn_buf[BFA_STRING_32];
+	char	rpwwn_buf[BFA_STRING_32];
+
+	rport->stats.onlines++;
+
+	if (bfa_fcs_lport_is_initiator(port)) {
+		bfa_fcs_itnim_rport_online(rport->itnim);
+		if (!BFA_FCS_PID_IS_WKA(rport->pid))
+			bfa_fcs_rpf_rport_online(rport);
+	};
+
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+	wwn2str(rpwwn_buf, rport->pwwn);
+	if (!BFA_FCS_PID_IS_WKA(rport->pid))
+		BFA_LOG(KERN_INFO, bfad, log_level,
+		"Remote port (WWN = %s) online for logical port (WWN = %s)\n",
+		rpwwn_buf, lpwwn_buf);
+}
+
+static void
+bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+	char	lpwwn_buf[BFA_STRING_32];
+	char	rpwwn_buf[BFA_STRING_32];
+
+	rport->stats.offlines++;
+
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+	wwn2str(rpwwn_buf, rport->pwwn);
+	if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
+		if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE)
+			BFA_LOG(KERN_ERR, bfad, log_level,
+				"Remote port (WWN = %s) connectivity lost for "
+				"logical port (WWN = %s)\n",
+				rpwwn_buf, lpwwn_buf);
+		else
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"Remote port (WWN = %s) offlined by "
+				"logical port (WWN = %s)\n",
+				rpwwn_buf, lpwwn_buf);
+	}
+
+	if (bfa_fcs_lport_is_initiator(port)) {
+		bfa_fcs_itnim_rport_offline(rport->itnim);
+		if (!BFA_FCS_PID_IS_WKA(rport->pid))
+			bfa_fcs_rpf_rport_offline(rport);
+	}
+}
+
+/**
+ * Update rport parameters from PLOGI or PLOGI accept.
+ */
+static void
+bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
+{
+	bfa_fcs_lport_t *port = rport->port;
+
+	/**
+	 * - port name
+	 * - node name
+	 */
+	rport->pwwn = plogi->port_name;
+	rport->nwwn = plogi->node_name;
+
+	/**
+	 * - class of service
+	 */
+	rport->fc_cos = 0;
+	if (plogi->class3.class_valid)
+		rport->fc_cos = FC_CLASS_3;
+
+	if (plogi->class2.class_valid)
+		rport->fc_cos |= FC_CLASS_2;
+
+	/**
+	 * - CISC
+	 * - MAX receive frame size
+	 */
+	rport->cisc = plogi->csp.cisc;
+	rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz);
+
+	bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
+	bfa_trc(port->fcs, port->fabric->bb_credit);
+	/**
+	 * Direct Attach P2P mode :
+	 * This is to handle a bug (233476) in IBM targets in Direct Attach
+	 *  Mode. Basically, in FLOGI Accept the target would have
+	 * erroneously set the BB Credit to the value used in the FLOGI
+	 * sent by the HBA. It uses the correct value (its own BB credit)
+	 * in PLOGI.
+	 */
+	if ((!bfa_fcs_fabric_is_switched(port->fabric))	 &&
+		(bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
+
+		bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
+		bfa_trc(port->fcs, port->fabric->bb_credit);
+
+		port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred);
+		bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
+					  port->fabric->bb_credit);
+	}
+
+}
+
+/**
+ *	Called to handle LOGO received from an existing remote port.
+ */
+static void
+bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
+{
+	rport->reply_oxid = fchs->ox_id;
+	bfa_trc(rport->fcs, rport->reply_oxid);
+
+	rport->prlo = BFA_FALSE;
+	rport->stats.logo_rcvd++;
+	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
+}
+
+
+
+/**
+ *  fcs_rport_public FCS rport public interfaces
+ */
+
+/**
+ *	Called by bport/vport to create a remote port instance for a discovered
+ *	remote device.
+ *
+ * @param[in] port	- base port or vport
+ * @param[in] rpid	- remote port ID
+ *
+ * @return None
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_create(struct bfa_fcs_lport_s *port, u32 rpid)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	bfa_trc(port->fcs, rpid);
+	rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
+	if (!rport)
+		return NULL;
+
+	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
+	return rport;
+}
+
+/**
+ * Called to create a rport for which only the wwn is known.
+ *
+ * @param[in] port	- base port
+ * @param[in] rpwwn	- remote port wwn
+ *
+ * @return None
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_create_by_wwn(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
+{
+	struct bfa_fcs_rport_s *rport;
+	bfa_trc(port->fcs, rpwwn);
+	rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
+	if (!rport)
+		return NULL;
+
+	bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
+	return rport;
+}
+/**
+ * Called by bport in private loop topology to indicate that a
+ * rport has been discovered and plogi has been completed.
+ *
+ * @param[in] port	- base port or vport
+ * @param[in] rpid	- remote port ID
+ */
+void
+bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
+	 struct fc_logi_s *plogi)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
+	if (!rport)
+		return;
+
+	bfa_fcs_rport_update(rport, plogi);
+
+	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
+}
+
+/**
+ *	Called by bport/vport to handle PLOGI received from a new remote port.
+ *	If an existing rport does a plogi, it will be handled separately.
+ */
+void
+bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
+				struct fc_logi_s *plogi)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
+	if (!rport)
+		return;
+
+	bfa_fcs_rport_update(rport, plogi);
+
+	rport->reply_oxid = fchs->ox_id;
+	bfa_trc(rport->fcs, rport->reply_oxid);
+
+	rport->stats.plogi_rcvd++;
+	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
+}
+
+static int
+wwn_compare(wwn_t wwn1, wwn_t wwn2)
+{
+	u8		*b1 = (u8 *) &wwn1;
+	u8		*b2 = (u8 *) &wwn2;
+	int		i;
+
+	for (i = 0; i < sizeof(wwn_t); i++) {
+		if (b1[i] < b2[i])
+			return -1;
+		if (b1[i] > b2[i])
+			return 1;
+	}
+	return 0;
+}
+
+/**
+ *	Called by bport/vport to handle PLOGI received from an existing
+ *	 remote port.
+ */
+void
+bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
+			struct fc_logi_s *plogi)
+{
+	/**
+	 * @todo Handle P2P and initiator-initiator.
+	 */
+
+	bfa_fcs_rport_update(rport, plogi);
+
+	rport->reply_oxid = rx_fchs->ox_id;
+	bfa_trc(rport->fcs, rport->reply_oxid);
+
+	/**
+	 * In Switched fabric topology,
+	 * PLOGI to each other. If our pwwn is smaller, ignore it,
+	 * if it is not a well known address.
+	 * If the link topology is N2N,
+	 * this Plogi should be accepted.
+	 */
+	if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) &&
+		(bfa_fcs_fabric_is_switched(rport->port->fabric)) &&
+		(!BFA_FCS_PID_IS_WKA(rport->pid))) {
+		bfa_trc(rport->fcs, rport->pid);
+		return;
+	}
+
+	rport->stats.plogi_rcvd++;
+	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
+}
+
+/**
+ * Called by bport/vport to delete a remote port instance.
+ *
+ * Rport delete is called under the following conditions:
+ *		- vport is deleted
+ *		- vf is deleted
+ *		- explicit request from OS to delete rport
+ */
+void
+bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
+}
+
+/**
+ * Called by bport/vport to  when a target goes offline.
+ *
+ */
+void
+bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
+}
+
+/**
+ * Called by bport in n2n when a target (attached port) becomes online.
+ *
+ */
+void
+bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
+}
+/**
+ *	Called by bport/vport to notify SCN for the remote port
+ */
+void
+bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
+{
+	rport->stats.rscns++;
+	bfa_sm_send_event(rport, RPSM_EVENT_SCN);
+}
+
+/**
+ *	Called by	fcpim to notify that the ITN cleanup is done.
+ */
+void
+bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
+}
+
+/**
+ *	Called by fcptm to notify that the ITN cleanup is done.
+ */
+void
+bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
+}
+
+/**
+ *	brief
+ *	This routine BFA callback for bfa_rport_online() call.
+ *
+ *	param[in]	cb_arg	-  rport struct.
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+void
+bfa_cb_rport_online(void *cbarg)
+{
+
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
+}
+
+/**
+ *	brief
+ *	This routine BFA callback for bfa_rport_offline() call.
+ *
+ *	param[in]	rport	-
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+void
+bfa_cb_rport_offline(void *cbarg)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
+}
+
+/**
+ *	brief
+ *	This routine is a static BFA callback when there is a QoS flow_id
+ *	change notification
+ *
+ *	param[in]	rport	-
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+void
+bfa_cb_rport_qos_scn_flowid(void *cbarg,
+		struct bfa_rport_qos_attr_s old_qos_attr,
+		struct bfa_rport_qos_attr_s new_qos_attr)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+}
+
+/**
+ *	brief
+ *	This routine is a static BFA callback when there is a QoS priority
+ *	change notification
+ *
+ *	param[in]	rport	-
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+void
+bfa_cb_rport_qos_scn_prio(void *cbarg,
+		struct bfa_rport_qos_attr_s old_qos_attr,
+		struct bfa_rport_qos_attr_s new_qos_attr)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+}
+
+/**
+ *		Called to process any unsolicted frames from this remote port
+ */
+void
+bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
+}
+
+/**
+ *		Called to process any unsolicted frames from this remote port
+ */
+void
+bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
+			struct fchs_s *fchs, u16 len)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fc_els_cmd_s	*els_cmd;
+
+	bfa_trc(rport->fcs, fchs->s_id);
+	bfa_trc(rport->fcs, fchs->d_id);
+	bfa_trc(rport->fcs, fchs->type);
+
+	if (fchs->type != FC_TYPE_ELS)
+		return;
+
+	els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+	bfa_trc(rport->fcs, els_cmd->els_code);
+
+	switch (els_cmd->els_code) {
+	case FC_ELS_LOGO:
+		bfa_stats(port, plogi_rcvd);
+		bfa_fcs_rport_process_logo(rport, fchs);
+		break;
+
+	case FC_ELS_ADISC:
+		bfa_stats(port, adisc_rcvd);
+		bfa_fcs_rport_process_adisc(rport, fchs, len);
+		break;
+
+	case FC_ELS_PRLO:
+		bfa_stats(port, prlo_rcvd);
+		if (bfa_fcs_lport_is_initiator(port))
+			bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
+		break;
+
+	case FC_ELS_PRLI:
+		bfa_stats(port, prli_rcvd);
+		bfa_fcs_rport_process_prli(rport, fchs, len);
+		break;
+
+	case FC_ELS_RPSC:
+		bfa_stats(port, rpsc_rcvd);
+		bfa_fcs_rport_process_rpsc(rport, fchs, len);
+		break;
+
+	default:
+		bfa_stats(port, un_handled_els_rcvd);
+		bfa_fcs_rport_send_ls_rjt(rport, fchs,
+					  FC_LS_RJT_RSN_CMD_NOT_SUPP,
+					  FC_LS_RJT_EXP_NO_ADDL_INFO);
+		break;
+	}
+}
+
+/* send best case  acc to prlo */
+static void
+bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
+	struct bfa_fcxp_s *fcxp;
+	int		len;
+
+	bfa_trc(rport->fcs, rport->pid);
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+	len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			rport->pid, bfa_fcs_lport_get_fcid(port),
+			rport->reply_oxid, 0);
+
+	bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,
+		port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
+		NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+/*
+ * Send a LS reject
+ */
+static void
+bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
+			  u8 reason_code, u8 reason_code_expl)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
+	struct bfa_fcxp_s *fcxp;
+	int		len;
+
+	bfa_trc(rport->fcs, rx_fchs->s_id);
+
+	fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
+	if (!fcxp)
+		return;
+
+	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+				rx_fchs->ox_id, reason_code, reason_code_expl);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
+			BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+			FC_MAX_PDUSZ, 0);
+}
+
+/**
+ * Return state of rport.
+ */
+int
+bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
+{
+	return bfa_sm_to_state(rport_sm_table, rport->sm);
+}
+
+/**
+ *	brief
+ *		 Called by the Driver to set rport delete/ageout timeout
+ *
+ *	param[in]		rport timeout value in seconds.
+ *
+ *	return None
+ */
+void
+bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
+{
+	/* convert to Millisecs */
+	if (rport_tmo > 0)
+		bfa_fcs_rport_del_timeout = rport_tmo * 1000;
+}
+void
+bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id)
+{
+	bfa_trc(rport->fcs, rport->pid);
+
+	rport->prlo = BFA_TRUE;
+	rport->reply_oxid = ox_id;
+	bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
+}
+
+
+
+/**
+ * Remote port implementation.
+ */
+
+/**
+ *  fcs_rport_api FCS rport API.
+ */
+
+/**
+ *	Direct API to add a target by port wwn. This interface is used, for
+ *	example, by bios when target pwwn is known from boot lun configuration.
+ */
+bfa_status_t
+bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn,
+		struct bfa_fcs_rport_s *rport, struct bfad_rport_s *rport_drv)
+{
+	bfa_trc(port->fcs, *pwwn);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Direct API to remove a target and its associated resources. This
+ *	interface is used, for example, by driver to remove target
+ *	ports from the target list for a VM.
+ */
+bfa_status_t
+bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in)
+{
+
+	struct bfa_fcs_rport_s *rport;
+
+	bfa_trc(rport_in->fcs, rport_in->pwwn);
+
+	rport = bfa_fcs_lport_get_rport_by_pwwn(rport_in->port, rport_in->pwwn);
+	if (rport == NULL) {
+		/*
+		 * TBD Error handling
+		 */
+		bfa_trc(rport_in->fcs, rport_in->pid);
+		return BFA_STATUS_UNKNOWN_RWWN;
+	}
+
+	/*
+	 * TBD if this remote port is online, send a logo
+	 */
+	return BFA_STATUS_OK;
+
+}
+
+/**
+ *	Remote device status for display/debug.
+ */
+void
+bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+			struct bfa_rport_attr_s *rport_attr)
+{
+	struct bfa_rport_qos_attr_s qos_attr;
+	bfa_fcs_lport_t *port = rport->port;
+	bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
+
+	bfa_os_memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
+
+	rport_attr->pid = rport->pid;
+	rport_attr->pwwn = rport->pwwn;
+	rport_attr->nwwn = rport->nwwn;
+	rport_attr->cos_supported = rport->fc_cos;
+	rport_attr->df_sz = rport->maxfrsize;
+	rport_attr->state = bfa_fcs_rport_get_state(rport);
+	rport_attr->fc_cos = rport->fc_cos;
+	rport_attr->cisc = rport->cisc;
+	rport_attr->scsi_function = rport->scsi_function;
+	rport_attr->curr_speed  = rport->rpf.rpsc_speed;
+	rport_attr->assigned_speed  = rport->rpf.assigned_speed;
+
+	bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr);
+	rport_attr->qos_attr = qos_attr;
+
+	rport_attr->trl_enforced = BFA_FALSE;
+	if (bfa_fcport_is_ratelim(port->fcs->bfa)) {
+		if (rport_speed == BFA_PORT_SPEED_UNKNOWN) {
+			/* Use default ratelim speed setting */
+			rport_speed =
+				bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
+		}
+
+		if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
+			rport_attr->trl_enforced = BFA_TRUE;
+	}
+}
+
+/**
+ *	Per remote device statistics.
+ */
+void
+bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
+			struct bfa_rport_stats_s *stats)
+{
+	*stats = rport->stats;
+}
+
+void
+bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport)
+{
+	bfa_os_memset((char *)&rport->stats, 0,
+			sizeof(struct bfa_rport_stats_s));
+}
+
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	rport = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
+	if (rport == NULL) {
+		/*
+		 * TBD Error handling
+		 */
+	}
+
+	return rport;
+}
+
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	rport = bfa_fcs_lport_get_rport_by_nwwn(port, rnwwn);
+	if (rport == NULL) {
+		/*
+		 * TBD Error handling
+		 */
+	}
+
+	return rport;
+}
+
+/*
+ * This API is to set the Rport's speed. Should be used when RPSC is not
+ * supported by the rport.
+ */
+void
+bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, bfa_port_speed_t speed)
+{
+	rport->rpf.assigned_speed  = speed;
+
+	/* Set this speed in f/w only if the RPSC speed is not available */
+	if (rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN)
+		bfa_rport_speed(rport->bfa_rport, speed);
+}
+
+
+
+/**
+ * Remote port features (RPF) implementation.
+ */
+
+#define BFA_FCS_RPF_RETRIES	(3)
+#define BFA_FCS_RPF_RETRY_TIMEOUT  (1000) /* 1 sec (In millisecs) */
+
+static void     bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
+				struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_rpf_rpsc2_response(void *fcsarg,
+			struct bfa_fcxp_s *fcxp,
+			void *cbarg,
+			bfa_status_t req_status,
+			u32 rsp_len,
+			u32 resid_len,
+			struct fchs_s *rsp_fchs);
+
+static void     bfa_fcs_rpf_timeout(void *arg);
+
+/**
+ *  fcs_rport_ftrs_sm FCS rport state machine events
+ */
+
+enum rpf_event {
+	RPFSM_EVENT_RPORT_OFFLINE  = 1, /* Rport offline		*/
+	RPFSM_EVENT_RPORT_ONLINE   = 2,	/* Rport online			*/
+	RPFSM_EVENT_FCXP_SENT      = 3,	/* Frame from has been sent	*/
+	RPFSM_EVENT_TIMEOUT	   = 4, /* Rport SM timeout event	*/
+	RPFSM_EVENT_RPSC_COMP      = 5,
+	RPFSM_EVENT_RPSC_FAIL      = 6,
+	RPFSM_EVENT_RPSC_ERROR     = 7,
+};
+
+static void	bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
+					enum rpf_event event);
+static void     bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
+				       enum rpf_event event);
+static void     bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
+				       enum rpf_event event);
+static void	bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
+					enum rpf_event event);
+static void     bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
+					enum rpf_event event);
+static void     bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
+					enum rpf_event event);
+
+static void
+bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+	struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_RPORT_ONLINE:
+		/* Send RPSC2 to a Brocade fabric only. */
+		if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
+			((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) ||
+			(bfa_fcs_fabric_get_switch_oui(fabric) ==
+						BFA_FCS_BRCD_SWITCH_OUI))) {
+			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+			rpf->rpsc_retries = 0;
+			bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+		}
+		break;
+
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
+		break;
+
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
+		rpf->rpsc_retries = 0;
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_RPSC_COMP:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+		/* Update speed info in f/w via BFA */
+		if (rpf->rpsc_speed != BFA_PORT_SPEED_UNKNOWN)
+			bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
+		else if (rpf->assigned_speed != BFA_PORT_SPEED_UNKNOWN)
+			bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
+		break;
+
+	case RPFSM_EVENT_RPSC_FAIL:
+		/* RPSC not supported by rport */
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+		break;
+
+	case RPFSM_EVENT_RPSC_ERROR:
+		/* need to retry...delayed a bit. */
+		if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
+			bfa_timer_start(rport->fcs->bfa, &rpf->timer,
+				    bfa_fcs_rpf_timeout, rpf,
+				    BFA_FCS_RPF_RETRY_TIMEOUT);
+			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
+		} else {
+			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+		}
+		break;
+
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+		bfa_fcxp_discard(rpf->fcxp);
+		rpf->rpsc_retries = 0;
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_TIMEOUT:
+		/* re-send the RPSC */
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+		bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+		break;
+
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		bfa_timer_stop(&rpf->timer);
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+		rpf->rpsc_retries = 0;
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+		rpf->rpsc_retries = 0;
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_RPORT_ONLINE:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+		bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+		break;
+
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+/**
+ * Called when Rport is created.
+ */
+void
+bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_rpf_s *rpf = &rport->rpf;
+
+	bfa_trc(rport->fcs, rport->pid);
+	rpf->rport = rport;
+
+	bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
+}
+
+/**
+ * Called when Rport becomes online
+ */
+void
+bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
+{
+	bfa_trc(rport->fcs, rport->pid);
+
+	if (__fcs_min_cfg(rport->port->fcs))
+		return;
+
+	if (bfa_fcs_fabric_is_switched(rport->port->fabric))
+		bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
+}
+
+/**
+ * Called when Rport becomes offline
+ */
+void
+bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
+{
+	bfa_trc(rport->fcs, rport->pid);
+
+	if (__fcs_min_cfg(rport->port->fcs))
+		return;
+
+	rport->rpf.rpsc_speed = 0;
+	bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
+}
+
+static void
+bfa_fcs_rpf_timeout(void *arg)
+{
+	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
+}
+
+static void
+bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg;
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
+	int		len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
+					bfa_fcs_rpf_send_rpsc2, rpf);
+		return;
+	}
+	rpf->fcxp = fcxp;
+
+	len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+			    bfa_fcs_lport_get_fcid(port), &rport->pid, 1);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
+			  rpf, FC_MAX_PDUSZ, FC_ELS_TOV);
+	rport->stats.rpsc_sent++;
+	bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
+
+}
+
+static void
+bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+			    bfa_status_t req_status, u32 rsp_len,
+			    u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+	struct fc_ls_rjt_s *ls_rjt;
+	struct fc_rpsc2_acc_s *rpsc2_acc;
+	u16	num_ents;
+
+	bfa_trc(rport->fcs, req_status);
+
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(rport->fcs, req_status);
+		if (req_status == BFA_STATUS_ETIMER)
+			rport->stats.rpsc_failed++;
+		bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+		return;
+	}
+
+	rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
+	if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
+		rport->stats.rpsc_accs++;
+		num_ents = bfa_os_ntohs(rpsc2_acc->num_pids);
+		bfa_trc(rport->fcs, num_ents);
+		if (num_ents > 0) {
+			bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
+			bfa_trc(rport->fcs,
+				bfa_os_ntohs(rpsc2_acc->port_info[0].pid));
+			bfa_trc(rport->fcs,
+				bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
+			bfa_trc(rport->fcs,
+				bfa_os_ntohs(rpsc2_acc->port_info[0].index));
+			bfa_trc(rport->fcs,
+				rpsc2_acc->port_info[0].type);
+
+			if (rpsc2_acc->port_info[0].speed == 0) {
+				bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+				return;
+			}
+
+			rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
+				bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
+
+			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
+		}
+	} else {
+		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+		bfa_trc(rport->fcs, ls_rjt->reason_code);
+		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
+		rport->stats.rpsc_rejects++;
+		if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
+			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
+		else
+			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+	}
+}
diff --git a/drivers/scsi/bfa/bfa_fcs_uf.c b/drivers/scsi/bfa/bfa_fcs_uf.c
deleted file mode 100644
index 3d57d48..0000000
--- a/drivers/scsi/bfa/bfa_fcs_uf.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcs_uf.c BFA FCS UF ( Unsolicited Frames)
- */
-
-#include <fcs/bfa_fcs.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs_fabric.h>
-#include "fcs.h"
-#include "fcs_trcmod.h"
-#include "fcs_fabric.h"
-#include "fcs_uf.h"
-
-BFA_TRC_FILE(FCS, UF);
-
-/**
- * 		BFA callback for unsolicited frame receive handler.
- *
- * @param[in]		cbarg		callback arg for receive handler
- * @param[in]		uf		unsolicited frame descriptor
- *
- * @return None
- */
-static void
-bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
-{
-	struct bfa_fcs_s      *fcs = (struct bfa_fcs_s *) cbarg;
-	struct fchs_s         *fchs = bfa_uf_get_frmbuf(uf);
-	u16        len = bfa_uf_get_frmlen(uf);
-	struct fc_vft_s       *vft;
-	struct bfa_fcs_fabric_s *fabric;
-
-	/**
-	 * check for VFT header
-	 */
-	if (fchs->routing == FC_RTG_EXT_HDR &&
-		fchs->cat_info == FC_CAT_VFT_HDR) {
-		bfa_stats(fcs, uf.tagged);
-		vft = bfa_uf_get_frmbuf(uf);
-		if (fcs->port_vfid == vft->vf_id)
-			fabric = &fcs->fabric;
-		else
-			fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
-
-		/**
-		 * drop frame if vfid is unknown
-		 */
-		if (!fabric) {
-			bfa_assert(0);
-			bfa_stats(fcs, uf.vfid_unknown);
-			bfa_uf_free(uf);
-			return;
-		}
-
-		/**
-		 * skip vft header
-		 */
-		fchs = (struct fchs_s *) (vft + 1);
-		len -= sizeof(struct fc_vft_s);
-
-		bfa_trc(fcs, vft->vf_id);
-	} else {
-		bfa_stats(fcs, uf.untagged);
-		fabric = &fcs->fabric;
-	}
-
-	bfa_trc(fcs, ((u32 *) fchs)[0]);
-	bfa_trc(fcs, ((u32 *) fchs)[1]);
-	bfa_trc(fcs, ((u32 *) fchs)[2]);
-	bfa_trc(fcs, ((u32 *) fchs)[3]);
-	bfa_trc(fcs, ((u32 *) fchs)[4]);
-	bfa_trc(fcs, ((u32 *) fchs)[5]);
-	bfa_trc(fcs, len);
-
-	bfa_fcs_fabric_uf_recv(fabric, fchs, len);
-	bfa_uf_free(uf);
-}
-
-void
-bfa_fcs_uf_attach(struct bfa_fcs_s *fcs)
-{
-	bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
-}
diff --git a/drivers/scsi/bfa/bfa_fcxp.c b/drivers/scsi/bfa/bfa_fcxp.c
deleted file mode 100644
index 8258f88..0000000
--- a/drivers/scsi/bfa/bfa_fcxp.c
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfi/bfi_uf.h>
-#include <cs/bfa_debug.h>
-
-BFA_TRC_FILE(HAL, FCXP);
-BFA_MODULE(fcxp);
-
-/**
- * forward declarations
- */
-static void     __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
-static void     hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
-				 struct bfi_fcxp_send_rsp_s *fcxp_rsp);
-static void     hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
-				 struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
-static void	bfa_fcxp_qresume(void *cbarg);
-static void	bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
-			       struct bfi_fcxp_send_req_s *send_req);
-
-/**
- *  fcxp_pvt BFA FCXP private functions
- */
-
-static void
-claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
-{
-	u8        *dm_kva = NULL;
-	u64        dm_pa;
-	u32        buf_pool_sz;
-
-	dm_kva = bfa_meminfo_dma_virt(mi);
-	dm_pa = bfa_meminfo_dma_phys(mi);
-
-	buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
-
-	/*
-	 * Initialize the fcxp req payload list
-	 */
-	mod->req_pld_list_kva = dm_kva;
-	mod->req_pld_list_pa = dm_pa;
-	dm_kva += buf_pool_sz;
-	dm_pa += buf_pool_sz;
-	bfa_os_memset(mod->req_pld_list_kva, 0, buf_pool_sz);
-
-	/*
-	 * Initialize the fcxp rsp payload list
-	 */
-	buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
-	mod->rsp_pld_list_kva = dm_kva;
-	mod->rsp_pld_list_pa = dm_pa;
-	dm_kva += buf_pool_sz;
-	dm_pa += buf_pool_sz;
-	bfa_os_memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
-
-	bfa_meminfo_dma_virt(mi) = dm_kva;
-	bfa_meminfo_dma_phys(mi) = dm_pa;
-}
-
-static void
-claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
-{
-	u16        i;
-	struct bfa_fcxp_s *fcxp;
-
-	fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
-	bfa_os_memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
-
-	INIT_LIST_HEAD(&mod->fcxp_free_q);
-	INIT_LIST_HEAD(&mod->fcxp_active_q);
-
-	mod->fcxp_list = fcxp;
-
-	for (i = 0; i < mod->num_fcxps; i++) {
-		fcxp->fcxp_mod = mod;
-		fcxp->fcxp_tag = i;
-
-		list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
-		bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
-		fcxp->reqq_waiting = BFA_FALSE;
-
-		fcxp = fcxp + 1;
-	}
-
-	bfa_meminfo_kva(mi) = (void *)fcxp;
-}
-
-static void
-bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
-		u32 *dm_len)
-{
-	u16        num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
-
-	if (num_fcxp_reqs == 0)
-		return;
-
-	/*
-	 * Account for req/rsp payload
-	 */
-	*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
-	if (cfg->drvcfg.min_cfg)
-		*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
-	else
-		*dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
-
-	/*
-	 * Account for fcxp structs
-	 */
-	*ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
-}
-
-static void
-bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		    struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
-	bfa_os_memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
-	mod->bfa = bfa;
-	mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
-
-	/**
-	 * Initialize FCXP request and response payload sizes.
-	 */
-	mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
-	if (!cfg->drvcfg.min_cfg)
-		mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
-
-	INIT_LIST_HEAD(&mod->wait_q);
-
-	claim_fcxp_req_rsp_mem(mod, meminfo);
-	claim_fcxps_mem(mod, meminfo);
-}
-
-static void
-bfa_fcxp_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcxp_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcxp_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcxp_iocdisable(struct bfa_s *bfa)
-{
-	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-	struct bfa_fcxp_s *fcxp;
-	struct list_head        *qe, *qen;
-
-	list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
-		fcxp = (struct bfa_fcxp_s *) qe;
-		if (fcxp->caller == NULL) {
-			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
-					BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
-			bfa_fcxp_free(fcxp);
-		} else {
-			fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
-			bfa_cb_queue(bfa, &fcxp->hcb_qe,
-				      __bfa_fcxp_send_cbfn, fcxp);
-		}
-	}
-}
-
-static struct bfa_fcxp_s *
-bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
-{
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_q_deq(&fm->fcxp_free_q, &fcxp);
-
-	if (fcxp)
-		list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
-
-	return fcxp;
-}
-
-static void
-bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
-{
-	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-	struct bfa_fcxp_wqe_s *wqe;
-
-	bfa_q_deq(&mod->wait_q, &wqe);
-	if (wqe) {
-		bfa_trc(mod->bfa, fcxp->fcxp_tag);
-		wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
-		return;
-	}
-
-	bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
-	list_del(&fcxp->qe);
-	list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
-}
-
-static void
-bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
-		       bfa_status_t req_status, u32 rsp_len,
-		       u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	/* discarded fcxp completion */
-}
-
-static void
-__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_fcxp_s *fcxp = cbarg;
-
-	if (complete) {
-		fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
-				fcxp->rsp_status, fcxp->rsp_len,
-				fcxp->residue_len, &fcxp->rsp_fchs);
-	} else {
-		bfa_fcxp_free(fcxp);
-	}
-}
-
-static void
-hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
-{
-	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);
-	struct bfa_fcxp_s 	*fcxp;
-	u16		fcxp_tag = bfa_os_ntohs(fcxp_rsp->fcxp_tag);
-
-	bfa_trc(bfa, fcxp_tag);
-
-	fcxp_rsp->rsp_len = bfa_os_ntohl(fcxp_rsp->rsp_len);
-
-	/**
-	 * @todo f/w should not set residue to non-0 when everything
-	 *       is received.
-	 */
-	if (fcxp_rsp->req_status == BFA_STATUS_OK)
-		fcxp_rsp->residue_len = 0;
-	else
-		fcxp_rsp->residue_len = bfa_os_ntohl(fcxp_rsp->residue_len);
-
-	fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
-
-	bfa_assert(fcxp->send_cbfn != NULL);
-
-	hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
-
-	if (fcxp->send_cbfn != NULL) {
-		if (fcxp->caller == NULL) {
-			bfa_trc(mod->bfa, fcxp->fcxp_tag);
-
-			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
-					fcxp_rsp->req_status, fcxp_rsp->rsp_len,
-					fcxp_rsp->residue_len, &fcxp_rsp->fchs);
-			/*
-			 * fcxp automatically freed on return from the callback
-			 */
-			bfa_fcxp_free(fcxp);
-		} else {
-			bfa_trc(mod->bfa, fcxp->fcxp_tag);
-			fcxp->rsp_status = fcxp_rsp->req_status;
-			fcxp->rsp_len = fcxp_rsp->rsp_len;
-			fcxp->residue_len = fcxp_rsp->residue_len;
-			fcxp->rsp_fchs = fcxp_rsp->fchs;
-
-			bfa_cb_queue(bfa, &fcxp->hcb_qe,
-				      __bfa_fcxp_send_cbfn, fcxp);
-		}
-	} else {
-		bfa_trc(bfa, fcxp_tag);
-	}
-}
-
-static void
-hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
-{
-	union bfi_addr_u      sga_zero = { {0} };
-
-	sge->sg_len = reqlen;
-	sge->flags = BFI_SGE_DATA_LAST;
-	bfa_dma_addr_set(sge[0].sga, req_pa);
-	bfa_sge_to_be(sge);
-	sge++;
-
-	sge->sga = sga_zero;
-	sge->sg_len = reqlen;
-	sge->flags = BFI_SGE_PGDLEN;
-	bfa_sge_to_be(sge);
-}
-
-static void
-hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
-		 struct fchs_s *fchs)
-{
-	/*
-	 * TODO: TX ox_id
-	 */
-	if (reqlen > 0) {
-		if (fcxp->use_ireqbuf) {
-			u32        pld_w0 =
-				*((u32 *) BFA_FCXP_REQ_PLD(fcxp));
-
-			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
-				BFA_PL_EID_TX,
-				reqlen + sizeof(struct fchs_s), fchs, pld_w0);
-		} else {
-			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
-				BFA_PL_EID_TX, reqlen + sizeof(struct fchs_s),
-				fchs);
-		}
-	} else {
-		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
-			       reqlen + sizeof(struct fchs_s), fchs);
-	}
-}
-
-static void
-hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
-		 struct bfi_fcxp_send_rsp_s *fcxp_rsp)
-{
-	if (fcxp_rsp->rsp_len > 0) {
-		if (fcxp->use_irspbuf) {
-			u32        pld_w0 =
-				*((u32 *) BFA_FCXP_RSP_PLD(fcxp));
-
-			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
-					      BFA_PL_EID_RX,
-					      (u16) fcxp_rsp->rsp_len,
-					      &fcxp_rsp->fchs, pld_w0);
-		} else {
-			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
-				       BFA_PL_EID_RX,
-				       (u16) fcxp_rsp->rsp_len,
-				       &fcxp_rsp->fchs);
-		}
-	} else {
-		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
-			       (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
-	}
-}
-
-/**
- * Handler to resume sending fcxp when space in available in cpe queue.
- */
-static void
-bfa_fcxp_qresume(void *cbarg)
-{
-	struct bfa_fcxp_s		*fcxp = cbarg;
-	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;
-	struct bfi_fcxp_send_req_s	*send_req;
-
-	fcxp->reqq_waiting = BFA_FALSE;
-	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
-	bfa_fcxp_queue(fcxp, send_req);
-}
-
-/**
- * Queue fcxp send request to foimrware.
- */
-static void
-bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
-{
-	struct bfa_s      		*bfa = fcxp->fcxp_mod->bfa;
-	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
-	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
-	struct bfa_rport_s		*rport = reqi->bfa_rport;
-
-	bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
-			bfa_lpuid(bfa));
-
-	send_req->fcxp_tag = bfa_os_htons(fcxp->fcxp_tag);
-	if (rport) {
-		send_req->rport_fw_hndl = rport->fw_handle;
-		send_req->max_frmsz = bfa_os_htons(rport->rport_info.max_frmsz);
-		if (send_req->max_frmsz == 0)
-			send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
-	} else {
-		send_req->rport_fw_hndl = 0;
-		send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
-	}
-
-	send_req->vf_id = bfa_os_htons(reqi->vf_id);
-	send_req->lp_tag = reqi->lp_tag;
-	send_req->class = reqi->class;
-	send_req->rsp_timeout = rspi->rsp_timeout;
-	send_req->cts = reqi->cts;
-	send_req->fchs = reqi->fchs;
-
-	send_req->req_len = bfa_os_htonl(reqi->req_tot_len);
-	send_req->rsp_maxlen = bfa_os_htonl(rspi->rsp_maxlen);
-
-	/*
-	 * setup req sgles
-	 */
-	if (fcxp->use_ireqbuf == 1) {
-		hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
-					BFA_FCXP_REQ_PLD_PA(fcxp));
-	} else {
-		if (fcxp->nreq_sgles > 0) {
-			bfa_assert(fcxp->nreq_sgles == 1);
-			hal_fcxp_set_local_sges(send_req->req_sge,
-						reqi->req_tot_len,
-						fcxp->req_sga_cbfn(fcxp->caller,
-								   0));
-		} else {
-			bfa_assert(reqi->req_tot_len == 0);
-			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
-		}
-	}
-
-	/*
-	 * setup rsp sgles
-	 */
-	if (fcxp->use_irspbuf == 1) {
-		bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
-
-		hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
-					BFA_FCXP_RSP_PLD_PA(fcxp));
-
-	} else {
-		if (fcxp->nrsp_sgles > 0) {
-			bfa_assert(fcxp->nrsp_sgles == 1);
-			hal_fcxp_set_local_sges(send_req->rsp_sge,
-						rspi->rsp_maxlen,
-						fcxp->rsp_sga_cbfn(fcxp->caller,
-								   0));
-		} else {
-			bfa_assert(rspi->rsp_maxlen == 0);
-			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
-		}
-	}
-
-	hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
-
-	bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
-
-	bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
-	bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
-}
-
-
-/**
- *  hal_fcxp_api BFA FCXP API
- */
-
-/**
- * Allocate an FCXP instance to send a response or to send a request
- * that has a response. Request/response buffers are allocated by caller.
- *
- * @param[in]	bfa		BFA bfa instance
- * @param[in]	nreq_sgles	Number of SG elements required for request
- * 				buffer. 0, if fcxp internal buffers are	used.
- * 				Use bfa_fcxp_get_reqbuf() to get the
- * 				internal req buffer.
- * @param[in]	req_sgles	SG elements describing request buffer. Will be
- * 				copied in by BFA and hence can be freed on
- * 				return from this function.
- * @param[in]	get_req_sga	function ptr to be called to get a request SG
- * 				Address (given the sge index).
- * @param[in]	get_req_sglen	function ptr to be called to get a request SG
- * 				len (given the sge index).
- * @param[in]	get_rsp_sga	function ptr to be called to get a response SG
- * 				Address (given the sge index).
- * @param[in]	get_rsp_sglen	function ptr to be called to get a response SG
- * 				len (given the sge index).
- *
- * @return FCXP instance. NULL on failure.
- */
-struct bfa_fcxp_s *
-bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
-			int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
-			bfa_fcxp_get_sglen_t req_sglen_cbfn,
-			bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
-			bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
-{
-	struct bfa_fcxp_s *fcxp = NULL;
-	u32        nreq_sgpg, nrsp_sgpg;
-
-	bfa_assert(bfa != NULL);
-
-	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
-	if (fcxp == NULL)
-		return NULL;
-
-	bfa_trc(bfa, fcxp->fcxp_tag);
-
-	fcxp->caller = caller;
-
-	if (nreq_sgles == 0) {
-		fcxp->use_ireqbuf = 1;
-	} else {
-		bfa_assert(req_sga_cbfn != NULL);
-		bfa_assert(req_sglen_cbfn != NULL);
-
-		fcxp->use_ireqbuf = 0;
-		fcxp->req_sga_cbfn = req_sga_cbfn;
-		fcxp->req_sglen_cbfn = req_sglen_cbfn;
-
-		fcxp->nreq_sgles = nreq_sgles;
-
-		/*
-		 * alloc required sgpgs
-		 */
-		if (nreq_sgles > BFI_SGE_INLINE) {
-			nreq_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
-
-			if (bfa_sgpg_malloc(bfa, &fcxp->req_sgpg_q, nreq_sgpg)
-			    != BFA_STATUS_OK) {
-				/*
-				 * TODO
-				 */
-			}
-		}
-	}
-
-	if (nrsp_sgles == 0) {
-		fcxp->use_irspbuf = 1;
-	} else {
-		bfa_assert(rsp_sga_cbfn != NULL);
-		bfa_assert(rsp_sglen_cbfn != NULL);
-
-		fcxp->use_irspbuf = 0;
-		fcxp->rsp_sga_cbfn = rsp_sga_cbfn;
-		fcxp->rsp_sglen_cbfn = rsp_sglen_cbfn;
-
-		fcxp->nrsp_sgles = nrsp_sgles;
-		/*
-		 * alloc required sgpgs
-		 */
-		if (nrsp_sgles > BFI_SGE_INLINE) {
-			nrsp_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
-
-			if (bfa_sgpg_malloc
-			    (bfa, &fcxp->rsp_sgpg_q, nrsp_sgpg)
-			    != BFA_STATUS_OK) {
-				/* bfa_sgpg_wait(bfa, &fcxp->rsp_sgpg_wqe,
-				nrsp_sgpg); */
-				/*
-				 * TODO
-				 */
-			}
-		}
-	}
-
-	return fcxp;
-}
-
-/**
- * Get the internal request buffer pointer
- *
- * @param[in]	fcxp	BFA fcxp pointer
- *
- * @return 		pointer to the internal request buffer
- */
-void *
-bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
-{
-	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-	void	*reqbuf;
-
-	bfa_assert(fcxp->use_ireqbuf == 1);
-	reqbuf = ((u8 *)mod->req_pld_list_kva) +
-			fcxp->fcxp_tag * mod->req_pld_sz;
-	return reqbuf;
-}
-
-u32
-bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
-{
-	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-
-	return mod->req_pld_sz;
-}
-
-/**
- * Get the internal response buffer pointer
- *
- * @param[in]	fcxp	BFA fcxp pointer
- *
- * @return		pointer to the internal request buffer
- */
-void *
-bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
-{
-	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-	void	*rspbuf;
-
-	bfa_assert(fcxp->use_irspbuf == 1);
-
-	rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
-			fcxp->fcxp_tag * mod->rsp_pld_sz;
-	return rspbuf;
-}
-
-/**
- * 		Free the BFA FCXP
- *
- * @param[in]	fcxp			BFA fcxp pointer
- *
- * @return 		void
- */
-void
-bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
-{
-	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-
-	bfa_assert(fcxp != NULL);
-	bfa_trc(mod->bfa, fcxp->fcxp_tag);
-	bfa_fcxp_put(fcxp);
-}
-
-/**
- * Send a FCXP request
- *
- * @param[in]	fcxp	BFA fcxp pointer
- * @param[in]	rport	BFA rport pointer. Could be left NULL for WKA rports
- * @param[in]	vf_id	virtual Fabric ID
- * @param[in]	lp_tag  lport tag
- * @param[in]	cts	use Continous sequence
- * @param[in]	cos	fc Class of Service
- * @param[in]	reqlen	request length, does not include FCHS length
- * @param[in]	fchs	fc Header Pointer. The header content will be copied
- *			in by BFA.
- *
- * @param[in]	cbfn	call back function to be called on receiving
- * 								the response
- * @param[in]	cbarg	arg for cbfn
- * @param[in]	rsp_timeout
- *			response timeout
- *
- * @return		bfa_status_t
- */
-void
-bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
-		u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
-		u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
-		void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
-{
-	struct bfa_s			*bfa  = fcxp->fcxp_mod->bfa;
-	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
-	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
-	struct bfi_fcxp_send_req_s	*send_req;
-
-	bfa_trc(bfa, fcxp->fcxp_tag);
-
-	/**
-	 * setup request/response info
-	 */
-	reqi->bfa_rport = rport;
-	reqi->vf_id = vf_id;
-	reqi->lp_tag = lp_tag;
-	reqi->class = cos;
-	rspi->rsp_timeout = rsp_timeout;
-	reqi->cts = cts;
-	reqi->fchs = *fchs;
-	reqi->req_tot_len = reqlen;
-	rspi->rsp_maxlen = rsp_maxlen;
-	fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
-	fcxp->send_cbarg = cbarg;
-
-	/**
-	 * If no room in CPE queue, wait for space in request queue
-	 */
-	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
-	if (!send_req) {
-		bfa_trc(bfa, fcxp->fcxp_tag);
-		fcxp->reqq_waiting = BFA_TRUE;
-		bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
-		return;
-	}
-
-	bfa_fcxp_queue(fcxp, send_req);
-}
-
-/**
- * Abort a BFA FCXP
- *
- * @param[in]	fcxp	BFA fcxp pointer
- *
- * @return 		void
- */
-bfa_status_t
-bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
-{
-	bfa_assert(0);
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
-			bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg)
-{
-	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
-	bfa_assert(list_empty(&mod->fcxp_free_q));
-
-	wqe->alloc_cbfn = alloc_cbfn;
-	wqe->alloc_cbarg = alloc_cbarg;
-	list_add_tail(&wqe->qe, &mod->wait_q);
-}
-
-void
-bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
-{
-	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
-	bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
-	list_del(&wqe->qe);
-}
-
-void
-bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
-{
-	/**
-	 * If waiting for room in request queue, cancel reqq wait
-	 * and free fcxp.
-	 */
-	if (fcxp->reqq_waiting) {
-		fcxp->reqq_waiting = BFA_FALSE;
-		bfa_reqq_wcancel(&fcxp->reqq_wqe);
-		bfa_fcxp_free(fcxp);
-		return;
-	}
-
-	fcxp->send_cbfn = bfa_fcxp_null_comp;
-}
-
-
-
-/**
- *  hal_fcxp_public BFA FCXP public functions
- */
-
-void
-bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
-{
-	switch (msg->mhdr.msg_id) {
-	case BFI_FCXP_I2H_SEND_RSP:
-		hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
-		break;
-
-	default:
-		bfa_trc(bfa, msg->mhdr.msg_id);
-		bfa_assert(0);
-	}
-}
-
-u32
-bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
-{
-	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
-	return mod->rsp_pld_sz;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_fcxp_priv.h b/drivers/scsi/bfa/bfa_fcxp_priv.h
deleted file mode 100644
index 4cda493..0000000
--- a/drivers/scsi/bfa/bfa_fcxp_priv.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCXP_PRIV_H__
-#define __BFA_FCXP_PRIV_H__
-
-#include <cs/bfa_sm.h>
-#include <protocol/fc.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_fcxp.h>
-
-#define BFA_FCXP_MIN     	(1)
-#define BFA_FCXP_MAX_IBUF_SZ	(2 * 1024 + 256)
-#define BFA_FCXP_MAX_LBUF_SZ	(4 * 1024 + 256)
-
-struct bfa_fcxp_mod_s {
-	struct bfa_s      *bfa;		/*  backpointer to BFA */
-	struct bfa_fcxp_s *fcxp_list;	/*  array of FCXPs */
-	u16        num_fcxps;	/*  max num FCXP requests */
-	struct list_head fcxp_free_q;	/*  free FCXPs */
-	struct list_head fcxp_active_q;	/*  active FCXPs */
-	void	*req_pld_list_kva;	/*  list of FCXP req pld */
-	u64 req_pld_list_pa;	/*  list of FCXP req pld */
-	void *rsp_pld_list_kva;		/*  list of FCXP resp pld */
-	u64 rsp_pld_list_pa;	/*  list of FCXP resp pld */
-	struct list_head  wait_q;		/*  wait queue for free fcxp */
-	u32	req_pld_sz;
-	u32	rsp_pld_sz;
-};
-
-#define BFA_FCXP_MOD(__bfa)		(&(__bfa)->modules.fcxp_mod)
-#define BFA_FCXP_FROM_TAG(__mod, __tag)	(&(__mod)->fcxp_list[__tag])
-
-typedef void    (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp,
-				   void *cb_arg, bfa_status_t req_status,
-				   u32 rsp_len, u32 resid_len,
-				   struct fchs_s *rsp_fchs);
-
-/**
- * Information needed for a FCXP request
- */
-struct bfa_fcxp_req_info_s {
-	struct bfa_rport_s *bfa_rport;	/*  Pointer to the bfa rport that was
-					 *returned from bfa_rport_create().
-					 *This could be left NULL for WKA or for
-					 *FCXP interactions before the rport
-					 *nexus is established
-					 */
-	struct fchs_s   fchs;	/*  request FC header structure */
-	u8 cts;		/*  continous sequence */
-	u8 class;		/*  FC class for the request/response */
-	u16 max_frmsz;	/*  max send frame size */
-	u16 vf_id;		/*  vsan tag if applicable */
-	u8	lp_tag;		/*  lport tag */
-	u32 req_tot_len;	/*  request payload total length */
-};
-
-struct bfa_fcxp_rsp_info_s {
-	struct fchs_s rsp_fchs;		/*  Response frame's FC header will
-					 * be *sent back in this field */
-	u8         rsp_timeout;	/*  timeout in seconds, 0-no response
-					 */
-	u8         rsvd2[3];
-	u32        rsp_maxlen;	/*  max response length expected */
-};
-
-struct bfa_fcxp_s {
-	struct list_head 	qe;		/*  fcxp queue element */
-	bfa_sm_t        sm;             /*  state machine */
-	void           	*caller;	/*  driver or fcs */
-	struct bfa_fcxp_mod_s *fcxp_mod;
-					/*  back pointer to fcxp mod */
-	u16        fcxp_tag;	/*  internal tag */
-	struct bfa_fcxp_req_info_s req_info;
-					/*  request info */
-	struct bfa_fcxp_rsp_info_s rsp_info;
-					/*  response info */
-	u8 	use_ireqbuf;	/*  use internal req buf */
-	u8         use_irspbuf;	/*  use internal rsp buf */
-	u32        nreq_sgles;	/*  num request SGLEs */
-	u32        nrsp_sgles;	/*  num response SGLEs */
-	struct list_head req_sgpg_q;	/*  SG pages for request buf */
-	struct list_head req_sgpg_wqe;	/*  wait queue for req SG page */
-	struct list_head rsp_sgpg_q;	/*  SG pages for response buf */
-	struct list_head rsp_sgpg_wqe;	/*  wait queue for rsp SG page */
-
-	bfa_fcxp_get_sgaddr_t req_sga_cbfn;
-					/*  SG elem addr user function */
-	bfa_fcxp_get_sglen_t req_sglen_cbfn;
-					/*  SG elem len user function */
-	bfa_fcxp_get_sgaddr_t rsp_sga_cbfn;
-					/*  SG elem addr user function */
-	bfa_fcxp_get_sglen_t rsp_sglen_cbfn;
-					/*  SG elem len user function */
-	bfa_cb_fcxp_send_t send_cbfn;   /*  send completion callback */
-	void		*send_cbarg;	/*  callback arg */
-	struct bfa_sge_s   req_sge[BFA_FCXP_MAX_SGES];
-					/*  req SG elems */
-	struct bfa_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];
-					/*  rsp SG elems */
-	u8         rsp_status;	/*  comp: rsp status */
-	u32        rsp_len;	/*  comp: actual response len */
-	u32        residue_len;	/*  comp: residual rsp length */
-	struct fchs_s          rsp_fchs;	/*  comp: response fchs */
-	struct bfa_cb_qe_s    hcb_qe;	/*  comp: callback qelem */
-	struct bfa_reqq_wait_s	reqq_wqe;
-	bfa_boolean_t	reqq_waiting;
-};
-
-#define BFA_FCXP_REQ_PLD(_fcxp) 	(bfa_fcxp_get_reqbuf(_fcxp))
-
-#define BFA_FCXP_RSP_FCHS(_fcxp) 	(&((_fcxp)->rsp_info.fchs))
-#define BFA_FCXP_RSP_PLD(_fcxp) 	(bfa_fcxp_get_rspbuf(_fcxp))
-
-#define BFA_FCXP_REQ_PLD_PA(_fcxp)					\
-	((_fcxp)->fcxp_mod->req_pld_list_pa +				\
-		((_fcxp)->fcxp_mod->req_pld_sz  * (_fcxp)->fcxp_tag))
-
-#define BFA_FCXP_RSP_PLD_PA(_fcxp) 					\
-	((_fcxp)->fcxp_mod->rsp_pld_list_pa +				\
-		((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag))
-
-void	bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-#endif /* __BFA_FCXP_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_fwimg_priv.h b/drivers/scsi/bfa/bfa_fwimg_priv.h
deleted file mode 100644
index d33e19e..0000000
--- a/drivers/scsi/bfa/bfa_fwimg_priv.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FWIMG_PRIV_H__
-#define __BFA_FWIMG_PRIV_H__
-
-#define	BFI_FLASH_CHUNK_SZ		256	/*  Flash chunk size */
-#define	BFI_FLASH_CHUNK_SZ_WORDS	(BFI_FLASH_CHUNK_SZ/sizeof(u32))
-
-/**
- * BFI FW image type
- */
-enum {
-	BFI_IMAGE_CB_FC,
-	BFI_IMAGE_CT_FC,
-	BFI_IMAGE_CT_CNA,
-	BFI_IMAGE_MAX,
-};
-
-extern u32 *bfi_image_get_chunk(int type, uint32_t off);
-extern u32 bfi_image_get_size(int type);
-extern u32 bfi_image_ct_fc_size;
-extern u32 bfi_image_ct_cna_size;
-extern u32 bfi_image_cb_fc_size;
-extern u32 *bfi_image_ct_fc;
-extern u32 *bfi_image_ct_cna;
-extern u32 *bfi_image_cb_fc;
-
-
-#endif /* __BFA_FWIMG_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c
index edfd729..c787d3a 100644
--- a/drivers/scsi/bfa/bfa_hw_cb.c
+++ b/drivers/scsi/bfa/bfa_hw_cb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,15 +15,15 @@
  * General Public License for more details.
  */
 
-#include <bfa_priv.h>
-#include <bfi/bfi_cbreg.h>
+#include "bfa_modules.h"
+#include "bfi_cbreg.h"
 
 void
 bfa_hwcb_reginit(struct bfa_s *bfa)
 {
 	struct bfa_iocfc_regs_s	*bfa_regs = &bfa->iocfc.bfa_regs;
 	bfa_os_addr_t		kva = bfa_ioc_bar0(&bfa->ioc);
-	int             	i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+	int			i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
 
 	if (fn == 0) {
 		bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c
index a357fb3..c97ebaf 100644
--- a/drivers/scsi/bfa/bfa_hw_ct.c
+++ b/drivers/scsi/bfa/bfa_hw_ct.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,9 +15,8 @@
  * General Public License for more details.
  */
 
-#include <bfa_priv.h>
-#include <bfi/bfi_ctreg.h>
-#include <bfa_ioc.h>
+#include "bfa_modules.h"
+#include "bfi_ctreg.h"
 
 BFA_TRC_FILE(HAL, IOCFC_CT);
 
@@ -53,7 +52,7 @@
 {
 	struct bfa_iocfc_regs_s	*bfa_regs = &bfa->iocfc.bfa_regs;
 	bfa_os_addr_t		kva = bfa_ioc_bar0(&bfa->ioc);
-	int             	i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+	int			i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
 
 	if (fn == 0) {
 		bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
@@ -87,7 +86,7 @@
 void
 bfa_hwct_reqq_ack(struct bfa_s *bfa, int reqq)
 {
-	u32 r32;
+	u32	r32;
 
 	r32 = bfa_reg_read(bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq]);
 	bfa_reg_write(bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq], r32);
diff --git a/drivers/scsi/bfa/bfa_intr.c b/drivers/scsi/bfa/bfa_intr.c
deleted file mode 100644
index 4936788..0000000
--- a/drivers/scsi/bfa/bfa_intr.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#include <bfa.h>
-#include <bfi/bfi_ctreg.h>
-#include <bfa_port_priv.h>
-#include <bfa_intr_priv.h>
-#include <cs/bfa_debug.h>
-
-BFA_TRC_FILE(HAL, INTR);
-
-static void
-bfa_msix_errint(struct bfa_s *bfa, u32 intr)
-{
-	bfa_ioc_error_isr(&bfa->ioc);
-}
-
-static void
-bfa_msix_lpu(struct bfa_s *bfa)
-{
-	bfa_ioc_mbox_isr(&bfa->ioc);
-}
-
-static void
-bfa_reqq_resume(struct bfa_s *bfa, int qid)
-{
-	struct list_head *waitq, *qe, *qen;
-	struct bfa_reqq_wait_s *wqe;
-
-	waitq = bfa_reqq(bfa, qid);
-	list_for_each_safe(qe, qen, waitq) {
-		/**
-		 * Callback only as long as there is room in request queue
-		 */
-		if (bfa_reqq_full(bfa, qid))
-			break;
-
-		list_del(qe);
-		wqe = (struct bfa_reqq_wait_s *) qe;
-		wqe->qresume(wqe->cbarg);
-	}
-}
-
-void
-bfa_msix_all(struct bfa_s *bfa, int vec)
-{
-	bfa_intx(bfa);
-}
-
-/**
- *  hal_intr_api
- */
-bfa_boolean_t
-bfa_intx(struct bfa_s *bfa)
-{
-	u32        intr, qintr;
-	int             queue;
-
-	intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
-	if (!intr)
-		return BFA_FALSE;
-
-	/**
-	 * RME completion queue interrupt
-	 */
-	qintr = intr & __HFN_INT_RME_MASK;
-	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
-
-	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
-		if (intr & (__HFN_INT_RME_Q0 << queue))
-			bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
-	}
-	intr &= ~qintr;
-	if (!intr)
-		return BFA_TRUE;
-
-	/**
-	 * CPE completion queue interrupt
-	 */
-	qintr = intr & __HFN_INT_CPE_MASK;
-	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
-
-	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
-		if (intr & (__HFN_INT_CPE_Q0 << queue))
-			bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
-	}
-	intr &= ~qintr;
-	if (!intr)
-		return BFA_TRUE;
-
-	bfa_msix_lpu_err(bfa, intr);
-
-	return BFA_TRUE;
-}
-
-void
-bfa_isr_enable(struct bfa_s *bfa)
-{
-	u32        intr_unmask;
-	int             pci_func = bfa_ioc_pcifn(&bfa->ioc);
-
-	bfa_trc(bfa, pci_func);
-
-	bfa_msix_install(bfa);
-	intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
-		       __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS |
-		       __HFN_INT_LL_HALT);
-
-	if (pci_func == 0)
-		intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
-				__HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
-				__HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
-				__HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
-				__HFN_INT_MBOX_LPU0);
-	else
-		intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
-				__HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
-				__HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
-				__HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
-				__HFN_INT_MBOX_LPU1);
-
-	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr_unmask);
-	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, ~intr_unmask);
-	bfa->iocfc.intr_mask = ~intr_unmask;
-	bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
-}
-
-void
-bfa_isr_disable(struct bfa_s *bfa)
-{
-	bfa_isr_mode_set(bfa, BFA_FALSE);
-	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L);
-	bfa_msix_uninstall(bfa);
-}
-
-void
-bfa_msix_reqq(struct bfa_s *bfa, int qid)
-{
-	struct list_head *waitq;
-
-	qid &= (BFI_IOC_MAX_CQS - 1);
-
-	bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);
-
-	/**
-	 * Resume any pending requests in the corresponding reqq.
-	 */
-	waitq = bfa_reqq(bfa, qid);
-	if (!list_empty(waitq))
-		bfa_reqq_resume(bfa, qid);
-}
-
-void
-bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	bfa_trc(bfa, m->mhdr.msg_class);
-	bfa_trc(bfa, m->mhdr.msg_id);
-	bfa_trc(bfa, m->mhdr.mtag.i2htok);
-	bfa_assert(0);
-	bfa_trc_stop(bfa->trcmod);
-}
-
-void
-bfa_msix_rspq(struct bfa_s *bfa, int qid)
-{
-	struct bfi_msg_s *m;
-	u32 pi, ci;
-	struct list_head *waitq;
-
-	bfa_trc_fp(bfa, qid);
-
-	qid &= (BFI_IOC_MAX_CQS - 1);
-
-	bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
-
-	ci = bfa_rspq_ci(bfa, qid);
-	pi = bfa_rspq_pi(bfa, qid);
-
-	bfa_trc_fp(bfa, ci);
-	bfa_trc_fp(bfa, pi);
-
-	if (bfa->rme_process) {
-		while (ci != pi) {
-			m = bfa_rspq_elem(bfa, qid, ci);
-			bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);
-
-			bfa_isrs[m->mhdr.msg_class] (bfa, m);
-
-			CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
-		}
-	}
-
-	/**
-	 * update CI
-	 */
-	bfa_rspq_ci(bfa, qid) = pi;
-	bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[qid], pi);
-	bfa_os_mmiowb();
-
-	/**
-	 * Resume any pending requests in the corresponding reqq.
-	 */
-	waitq = bfa_reqq(bfa, qid);
-	if (!list_empty(waitq))
-		bfa_reqq_resume(bfa, qid);
-}
-
-void
-bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
-{
-	u32 intr, curr_value;
-
-	intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
-
-	if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
-		bfa_msix_lpu(bfa);
-
-	intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
-		__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
-
-	if (intr) {
-		if (intr & __HFN_INT_LL_HALT) {
-			/**
-			 * If LL_HALT bit is set then FW Init Halt LL Port
-			 * Register needs to be cleared as well so Interrupt
-			 * Status Register will be cleared.
-			 */
-			curr_value = bfa_reg_read(bfa->ioc.ioc_regs.ll_halt);
-			curr_value &= ~__FW_INIT_HALT_P;
-			bfa_reg_write(bfa->ioc.ioc_regs.ll_halt, curr_value);
-		}
-
-		if (intr & __HFN_INT_ERR_PSS) {
-			/**
-			 * ERR_PSS bit needs to be cleared as well in case
-			 * interrups are shared so driver's interrupt handler is
-			 * still called eventhough it is already masked out.
-			 */
-			curr_value = bfa_reg_read(
-				bfa->ioc.ioc_regs.pss_err_status_reg);
-			curr_value &= __PSS_ERR_STATUS_SET;
-			bfa_reg_write(bfa->ioc.ioc_regs.pss_err_status_reg,
-				curr_value);
-		}
-
-		bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr);
-		bfa_msix_errint(bfa, intr);
-	}
-}
-
-void
-bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func)
-{
-	bfa_isrs[mc] = isr_func;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_intr_priv.h b/drivers/scsi/bfa/bfa_intr_priv.h
deleted file mode 100644
index 5fc301c..0000000
--- a/drivers/scsi/bfa/bfa_intr_priv.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_INTR_PRIV_H__
-#define __BFA_INTR_PRIV_H__
-
-/**
- * Message handler
- */
-typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
-void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
-void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
-
-
-#define bfa_reqq_pi(__bfa, __reqq)	((__bfa)->iocfc.req_cq_pi[__reqq])
-#define bfa_reqq_ci(__bfa, __reqq)					\
-	(*(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva))
-
-#define bfa_reqq_full(__bfa, __reqq)				\
-	(((bfa_reqq_pi(__bfa, __reqq) + 1) &			\
-	  ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1)) ==	\
-	 bfa_reqq_ci(__bfa, __reqq))
-
-#define bfa_reqq_next(__bfa, __reqq)				\
-	(bfa_reqq_full(__bfa, __reqq) ? NULL :			\
-	 ((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
-			  + bfa_reqq_pi((__bfa), (__reqq)))))
-
-#define bfa_reqq_produce(__bfa, __reqq)	do {				\
-	(__bfa)->iocfc.req_cq_pi[__reqq]++;				\
-	(__bfa)->iocfc.req_cq_pi[__reqq] &=				\
-		((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1);      \
-	bfa_reg_write((__bfa)->iocfc.bfa_regs.cpe_q_pi[__reqq],		\
-				(__bfa)->iocfc.req_cq_pi[__reqq]);      \
-	bfa_os_mmiowb();      \
-} while (0)
-
-#define bfa_rspq_pi(__bfa, __rspq)					\
-	(*(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva))
-
-#define bfa_rspq_ci(__bfa, __rspq)	((__bfa)->iocfc.rsp_cq_ci[__rspq])
-#define bfa_rspq_elem(__bfa, __rspq, __ci)				\
-	(&((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci])
-
-#define CQ_INCR(__index, __size) do {					\
-			(__index)++;					\
-			(__index) &= ((__size) - 1);      \
-} while (0)
-
-/**
- * Queue element to wait for room in request queue. FIFO order is
- * maintained when fullfilling requests.
- */
-struct bfa_reqq_wait_s {
-	struct list_head 	qe;
-	void		(*qresume) (void *cbarg);
-	void		*cbarg;
-};
-
-/**
- * Circular queue usage assignments
- */
-enum {
-	BFA_REQQ_IOC	= 0,	/*  all low-priority IOC msgs	*/
-	BFA_REQQ_FCXP	= 0,	/*  all FCXP messages		*/
-	BFA_REQQ_LPS	= 0,	/*  all lport service msgs	*/
-	BFA_REQQ_PORT	= 0,	/*  all port messages		*/
-	BFA_REQQ_FLASH	= 0,	/*  for flash module		*/
-	BFA_REQQ_DIAG	= 0,	/*  for diag module		*/
-	BFA_REQQ_RPORT	= 0,	/*  all port messages		*/
-	BFA_REQQ_SBOOT	= 0,	/*  all san boot messages	*/
-	BFA_REQQ_QOS_LO	= 1,	/*  all low priority IO	*/
-	BFA_REQQ_QOS_MD	= 2,	/*  all medium priority IO	*/
-	BFA_REQQ_QOS_HI	= 3,	/*  all high priority IO	*/
-};
-
-static inline void
-bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
-			void *cbarg)
-{
-	wqe->qresume = qresume;
-	wqe->cbarg = cbarg;
-}
-
-#define bfa_reqq(__bfa, __reqq)	(&(__bfa)->reqq_waitq[__reqq])
-
-/**
- * static inline void
- * bfa_reqq_wait(struct bfa_s *bfa, int reqq, struct bfa_reqq_wait_s *wqe)
- */
-#define bfa_reqq_wait(__bfa, __reqq, __wqe) do {			\
-									\
-		struct list_head *waitq = bfa_reqq(__bfa, __reqq);      \
-									\
-		bfa_assert(((__reqq) < BFI_IOC_MAX_CQS));      \
-		bfa_assert((__wqe)->qresume && (__wqe)->cbarg);      \
-									\
-		list_add_tail(&(__wqe)->qe, waitq);      \
-} while (0)
-
-#define bfa_reqq_wcancel(__wqe)	list_del(&(__wqe)->qe)
-
-#endif /* __BFA_INTR_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 8e78f20..6795b24 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,35 +15,33 @@
  * General Public License for more details.
  */
 
-#include <bfa.h>
-#include <bfa_ioc.h>
-#include <bfa_fwimg_priv.h>
-#include <cna/bfa_cna_trcmod.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_ctreg.h>
-#include <aen/bfa_aen_ioc.h>
-#include <aen/bfa_aen.h>
-#include <log/bfa_log_hal.h>
-#include <defs/bfa_defs_pci.h>
+#include "bfa_ioc.h"
+#include "bfi_ctreg.h"
+#include "bfa_defs.h"
+#include "bfa_defs_svc.h"
+#include "bfad_drv.h"
 
 BFA_TRC_FILE(CNA, IOC);
 
 /**
  * IOC local definitions
  */
-#define BFA_IOC_TOV		2000	/* msecs */
-#define BFA_IOC_HWSEM_TOV       500     /* msecs */
-#define BFA_IOC_HB_TOV          500     /* msecs */
-#define BFA_IOC_HWINIT_MAX      2
-#define BFA_IOC_FWIMG_MINSZ     (16 * 1024)
-#define BFA_IOC_TOV_RECOVER      BFA_IOC_HB_TOV
+#define BFA_IOC_TOV		3000	/* msecs */
+#define BFA_IOC_HWSEM_TOV	500	/* msecs */
+#define BFA_IOC_HB_TOV		500	/* msecs */
+#define BFA_IOC_HWINIT_MAX	2
+#define BFA_IOC_TOV_RECOVER	 BFA_IOC_HB_TOV
 
 #define bfa_ioc_timer_start(__ioc)					\
 	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
 			bfa_ioc_timeout, (__ioc), BFA_IOC_TOV)
 #define bfa_ioc_timer_stop(__ioc)   bfa_timer_stop(&(__ioc)->ioc_timer)
 
+#define bfa_hb_timer_start(__ioc)					\
+	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->hb_timer,		\
+			bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV)
+#define bfa_hb_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->hb_timer)
+
 #define BFA_DBG_FWTRC_ENTS	(BFI_IOC_TRC_ENTS)
 #define BFA_DBG_FWTRC_LEN					\
 	(BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) +	\
@@ -55,100 +53,226 @@
  * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
  */
 
-#define bfa_ioc_firmware_lock(__ioc)                    \
+#define bfa_ioc_firmware_lock(__ioc)			\
 			((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
-#define bfa_ioc_firmware_unlock(__ioc)                  \
+#define bfa_ioc_firmware_unlock(__ioc)			\
 			((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
 #define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
 #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
-#define bfa_ioc_notify_hbfail(__ioc)                    \
+#define bfa_ioc_notify_hbfail(__ioc)			\
 			((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc))
-#define bfa_ioc_is_optrom(__ioc)        \
-	(bfi_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
 
-bfa_boolean_t   bfa_auto_recover = BFA_TRUE;
+#ifdef BFA_IOC_IS_UEFI
+#define bfa_ioc_is_bios_optrom(__ioc) (0)
+#define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI
+#else
+#define bfa_ioc_is_bios_optrom(__ioc)	\
+	(bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
+#define bfa_ioc_is_uefi(__ioc) (0)
+#endif
+
+#define bfa_ioc_mbox_cmd_pending(__ioc)		\
+			(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
+			bfa_reg_read((__ioc)->ioc_regs.hfn_mbox_cmd))
+
+bfa_boolean_t bfa_auto_recover = BFA_TRUE;
 
 /*
  * forward declarations
  */
-static void     bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
-static void     bfa_ioc_timeout(void *ioc);
-static void     bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);
-static void     bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_recover(struct bfa_ioc_s *ioc);
-static void	bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
+static void bfa_ioc_timeout(void *ioc);
+static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
+static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
+static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
+static void bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);
+static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
+static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
+static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
+static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
+static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
+static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_failed(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
 
 /**
- *  bfa_ioc_sm
+ *  hal_ioc_sm
  */
 
 /**
- * IOC state machine events
+ * IOC state machine definitions/declarations
  */
 enum ioc_event {
-	IOC_E_ENABLE = 1,	/*  IOC enable request */
-	IOC_E_DISABLE = 2,	/*  IOC disable request */
-	IOC_E_TIMEOUT = 3,	/*  f/w response timeout */
-	IOC_E_FWREADY = 4,	/*  f/w initialization done */
-	IOC_E_FWRSP_GETATTR = 5,	/*  IOC get attribute response */
-	IOC_E_FWRSP_ENABLE = 6,	/*  enable f/w response */
-	IOC_E_FWRSP_DISABLE = 7,	/*  disable f/w response */
-	IOC_E_HBFAIL = 8,	/*  heartbeat failure */
-	IOC_E_HWERROR = 9,	/*  hardware error interrupt */
-	IOC_E_SEMLOCKED = 10,	/*  h/w semaphore is locked */
-	IOC_E_DETACH = 11,	/*  driver detach cleanup */
+	IOC_E_RESET		= 1,	/*  IOC reset request		*/
+	IOC_E_ENABLE		= 2,	/*  IOC enable request		*/
+	IOC_E_DISABLE		= 3,	/*  IOC disable request	*/
+	IOC_E_DETACH		= 4,	/*  driver detach cleanup	*/
+	IOC_E_ENABLED		= 5,	/*  f/w enabled		*/
+	IOC_E_FWRSP_GETATTR	= 6,	/*  IOC get attribute response	*/
+	IOC_E_DISABLED		= 7,	/*  f/w disabled		*/
+	IOC_E_FAILED		= 8,	/*  failure notice by iocpf sm	*/
+	IOC_E_HBFAIL		= 9,	/*  heartbeat failure		*/
+	IOC_E_HWERROR		= 10,	/*  hardware error interrupt	*/
+	IOC_E_TIMEOUT		= 11,	/*  timeout			*/
 };
 
+bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
 
 static struct bfa_sm_table_s ioc_sm_table[] = {
+	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
 	{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
-	{BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH},
-	{BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH},
-	{BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT},
-	{BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT},
-	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT},
+	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
 	{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
 	{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
 	{BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
-	{BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL},
+	{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
 	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
 	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
 };
 
 /**
+ * IOCPF state machine definitions/declarations
+ */
+
+#define bfa_iocpf_timer_start(__ioc)					\
+	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
+			bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
+#define bfa_iocpf_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->ioc_timer)
+
+#define bfa_iocpf_recovery_timer_start(__ioc)				\
+	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
+			bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV_RECOVER)
+
+#define bfa_sem_timer_start(__ioc)					\
+	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer,	\
+			bfa_iocpf_sem_timeout, (__ioc), BFA_IOC_HWSEM_TOV)
+#define bfa_sem_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->sem_timer)
+
+/*
+ * Forward declareations for iocpf state machine
+ */
+static void bfa_iocpf_enable(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_disable(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_fail(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_initfail(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_stop(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_timeout(void *ioc_arg);
+static void bfa_iocpf_sem_timeout(void *ioc_arg);
+
+/**
+ * IOCPF state machine events
+ */
+enum iocpf_event {
+	IOCPF_E_ENABLE		= 1,	/*  IOCPF enable request	*/
+	IOCPF_E_DISABLE		= 2,	/*  IOCPF disable request	*/
+	IOCPF_E_STOP		= 3,	/*  stop on driver detach	*/
+	IOCPF_E_FWREADY		= 4,	/*  f/w initialization done	*/
+	IOCPF_E_FWRSP_ENABLE	= 5,	/*  enable f/w response	*/
+	IOCPF_E_FWRSP_DISABLE	= 6,	/*  disable f/w response	*/
+	IOCPF_E_FAIL		= 7,	/*  failure notice by ioc sm	*/
+	IOCPF_E_INITFAIL	= 8,	/*  init fail notice by ioc sm	*/
+	IOCPF_E_GETATTRFAIL	= 9,	/*  init fail notice by ioc sm	*/
+	IOCPF_E_SEMLOCKED	= 10,	/*  h/w semaphore is locked	*/
+	IOCPF_E_TIMEOUT		= 11,	/*  f/w response timeout	*/
+};
+
+/**
+ * IOCPF states
+ */
+enum bfa_iocpf_state {
+	BFA_IOCPF_RESET		= 1,	/*  IOC is in reset state */
+	BFA_IOCPF_SEMWAIT	= 2,	/*  Waiting for IOC h/w semaphore */
+	BFA_IOCPF_HWINIT	= 3,	/*  IOC h/w is being initialized */
+	BFA_IOCPF_READY		= 4,	/*  IOCPF is initialized */
+	BFA_IOCPF_INITFAIL	= 5,	/*  IOCPF failed */
+	BFA_IOCPF_FAIL		= 6,	/*  IOCPF failed */
+	BFA_IOCPF_DISABLING	= 7,	/*  IOCPF is being disabled */
+	BFA_IOCPF_DISABLED	= 8,	/*  IOCPF is disabled */
+	BFA_IOCPF_FWMISMATCH	= 9,	/*  IOC f/w different from drivers */
+};
+
+bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);
+
+static struct bfa_sm_table_s iocpf_sm_table[] = {
+	{BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
+	{BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
+	{BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
+	{BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
+	{BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
+	{BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
+	{BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
+	{BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
+	{BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
+	{BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
+	{BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
+};
+
+/**
+ * IOC State Machine
+ */
+
+/**
+ * Beginning state. IOC uninit state.
+ */
+
+static void
+bfa_ioc_sm_uninit_entry(struct bfa_ioc_s *ioc)
+{
+}
+
+/**
+ * IOC is in uninit state.
+ */
+static void
+bfa_ioc_sm_uninit(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOC_E_RESET:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+/**
  * Reset entry actions -- initialize state machine
  */
 static void
 bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
 {
-	ioc->retry_count = 0;
-	ioc->auto_recover = bfa_auto_recover;
+	bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
 }
 
 /**
- * Beginning state. IOC is in reset state.
+ * IOC is in reset state.
  */
 static void
 bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
@@ -157,195 +281,15 @@
 
 	switch (event) {
 	case IOC_E_ENABLE:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_ioc_disable_comp(ioc);
-		break;
-
-	case IOC_E_DETACH:
-		break;
-
-	default:
-		bfa_sm_fault(ioc, event);
-	}
-}
-
-/**
- * Semaphore should be acquired for version check.
- */
-static void
-bfa_ioc_sm_fwcheck_entry(struct bfa_ioc_s *ioc)
-{
-	bfa_ioc_hw_sem_get(ioc);
-}
-
-/**
- * Awaiting h/w semaphore to continue with version check.
- */
-static void
-bfa_ioc_sm_fwcheck(struct bfa_ioc_s *ioc, enum ioc_event event)
-{
-	bfa_trc(ioc, event);
-
-	switch (event) {
-	case IOC_E_SEMLOCKED:
-		if (bfa_ioc_firmware_lock(ioc)) {
-			ioc->retry_count = 0;
-			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
-		} else {
-			bfa_ioc_hw_sem_release(ioc);
-			bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch);
-		}
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_ioc_disable_comp(ioc);
-		/*
-		 * fall through
-		 */
-
-	case IOC_E_DETACH:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
-		break;
-
-	case IOC_E_FWREADY:
-		break;
-
-	default:
-		bfa_sm_fault(ioc, event);
-	}
-}
-
-/**
- * Notify enable completion callback and generate mismatch AEN.
- */
-static void
-bfa_ioc_sm_mismatch_entry(struct bfa_ioc_s *ioc)
-{
-	/**
-	 * Provide enable completion callback and AEN notification only once.
-	 */
-	if (ioc->retry_count == 0) {
-		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-		bfa_ioc_aen_post(ioc, BFA_IOC_AEN_FWMISMATCH);
-	}
-	ioc->retry_count++;
-	bfa_ioc_timer_start(ioc);
-}
-
-/**
- * Awaiting firmware version match.
- */
-static void
-bfa_ioc_sm_mismatch(struct bfa_ioc_s *ioc, enum ioc_event event)
-{
-	bfa_trc(ioc, event);
-
-	switch (event) {
-	case IOC_E_TIMEOUT:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_ioc_disable_comp(ioc);
-		/*
-		 * fall through
-		 */
-
-	case IOC_E_DETACH:
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
-		break;
-
-	case IOC_E_FWREADY:
-		break;
-
-	default:
-		bfa_sm_fault(ioc, event);
-	}
-}
-
-/**
- * Request for semaphore.
- */
-static void
-bfa_ioc_sm_semwait_entry(struct bfa_ioc_s *ioc)
-{
-	bfa_ioc_hw_sem_get(ioc);
-}
-
-/**
- * Awaiting semaphore for h/w initialzation.
- */
-static void
-bfa_ioc_sm_semwait(struct bfa_ioc_s *ioc, enum ioc_event event)
-{
-	bfa_trc(ioc, event);
-
-	switch (event) {
-	case IOC_E_SEMLOCKED:
-		ioc->retry_count = 0;
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
-		break;
-
-	default:
-		bfa_sm_fault(ioc, event);
-	}
-}
-
-
-static void
-bfa_ioc_sm_hwinit_entry(struct bfa_ioc_s *ioc)
-{
-	bfa_ioc_timer_start(ioc);
-	bfa_ioc_reset(ioc, BFA_FALSE);
-}
-
-/**
- * Hardware is being initialized. Interrupts are enabled.
- * Holding hardware semaphore lock.
- */
-static void
-bfa_ioc_sm_hwinit(struct bfa_ioc_s *ioc, enum ioc_event event)
-{
-	bfa_trc(ioc, event);
-
-	switch (event) {
-	case IOC_E_FWREADY:
-		bfa_ioc_timer_stop(ioc);
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
 		break;
 
-	case IOC_E_HWERROR:
-		bfa_ioc_timer_stop(ioc);
-		/*
-		 * fall through
-		 */
-
-	case IOC_E_TIMEOUT:
-		ioc->retry_count++;
-		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
-			bfa_ioc_timer_start(ioc);
-			bfa_ioc_reset(ioc, BFA_TRUE);
-			break;
-		}
-
-		bfa_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+	case IOC_E_DISABLE:
+		bfa_ioc_disable_comp(ioc);
 		break;
 
-	case IOC_E_DISABLE:
-		bfa_ioc_hw_sem_release(ioc);
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+	case IOC_E_DETACH:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
 		break;
 
 	default:
@@ -357,8 +301,7 @@
 static void
 bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
 {
-	bfa_ioc_timer_start(ioc);
-	bfa_ioc_send_enable(ioc);
+	bfa_iocpf_enable(ioc);
 }
 
 /**
@@ -371,39 +314,29 @@
 	bfa_trc(ioc, event);
 
 	switch (event) {
-	case IOC_E_FWRSP_ENABLE:
-		bfa_ioc_timer_stop(ioc);
-		bfa_ioc_hw_sem_release(ioc);
+	case IOC_E_ENABLED:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
 		break;
 
-	case IOC_E_HWERROR:
-		bfa_ioc_timer_stop(ioc);
-		/*
-		 * fall through
-		 */
-
-	case IOC_E_TIMEOUT:
-		ioc->retry_count++;
-		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
-			bfa_reg_write(ioc->ioc_regs.ioc_fwstate,
-				      BFI_IOC_UNINIT);
-			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
-			break;
-		}
-
-		bfa_ioc_hw_sem_release(ioc);
+	case IOC_E_FAILED:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
 		break;
 
-	case IOC_E_DISABLE:
-		bfa_ioc_timer_stop(ioc);
-		bfa_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+	case IOC_E_HWERROR:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		bfa_iocpf_initfail(ioc);
 		break;
 
-	case IOC_E_FWREADY:
-		bfa_ioc_send_enable(ioc);
+	case IOC_E_DISABLE:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
+
+	case IOC_E_DETACH:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		bfa_iocpf_stop(ioc);
+		break;
+
+	case IOC_E_ENABLE:
 		break;
 
 	default:
@@ -434,19 +367,26 @@
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
 		break;
 
+	case IOC_E_FAILED:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		break;
+
 	case IOC_E_HWERROR:
 		bfa_ioc_timer_stop(ioc);
-		/*
-		 * fall through
-		 */
+		/* fall through */
 
 	case IOC_E_TIMEOUT:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		bfa_iocpf_getattrfail(ioc);
 		break;
 
 	case IOC_E_DISABLE:
 		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
+
+	case IOC_E_ENABLE:
 		break;
 
 	default:
@@ -458,9 +398,11 @@
 static void
 bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
 {
+	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+
 	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
 	bfa_ioc_hb_monitor(ioc);
-	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_ENABLE);
+	BFA_LOG(KERN_INFO, bfad, log_level, "IOC enabled\n");
 }
 
 static void
@@ -477,19 +419,18 @@
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 		break;
 
-	case IOC_E_HWERROR:
-	case IOC_E_FWREADY:
-		/**
-		 * Hard error or IOC recovery by other function.
-		 * Treat it same as heartbeat failure.
-		 */
+	case IOC_E_FAILED:
 		bfa_ioc_hb_stop(ioc);
-		/*
-		 * !!! fall through !!!
-		 */
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+		break;
+
+	case IOC_E_HWERROR:
+		bfa_ioc_hb_stop(ioc);
+		/* !!! fall through !!! */
 
 	case IOC_E_HBFAIL:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+		bfa_iocpf_fail(ioc);
 		break;
 
 	default:
@@ -501,9 +442,9 @@
 static void
 bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
 {
-	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_DISABLE);
-	bfa_ioc_timer_start(ioc);
-	bfa_ioc_send_disable(ioc);
+	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+	bfa_iocpf_disable(ioc);
+	BFA_LOG(KERN_INFO, bfad, log_level, "IOC disabled\n");
 }
 
 /**
@@ -515,20 +456,17 @@
 	bfa_trc(ioc, event);
 
 	switch (event) {
-	case IOC_E_FWRSP_DISABLE:
-		bfa_ioc_timer_stop(ioc);
+	case IOC_E_DISABLED:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
 		break;
 
 	case IOC_E_HWERROR:
-		bfa_ioc_timer_stop(ioc);
 		/*
-		 * !!! fall through !!!
+		 * No state change.  Will move to disabled state
+		 * after iocpf sm completes failure processing and
+		 * moves to disabled state.
 		 */
-
-	case IOC_E_TIMEOUT:
-		bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		bfa_iocpf_fail(ioc);
 		break;
 
 	default:
@@ -552,19 +490,16 @@
 
 	switch (event) {
 	case IOC_E_ENABLE:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
 		break;
 
 	case IOC_E_DISABLE:
 		ioc->cbfn->disable_cbfn(ioc->bfa);
 		break;
 
-	case IOC_E_FWREADY:
-		break;
-
 	case IOC_E_DETACH:
-		bfa_ioc_firmware_unlock(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		bfa_iocpf_stop(ioc);
 		break;
 
 	default:
@@ -577,7 +512,6 @@
 bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc)
 {
 	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-	bfa_ioc_timer_start(ioc);
 }
 
 /**
@@ -589,19 +523,24 @@
 	bfa_trc(ioc, event);
 
 	switch (event) {
+	case IOC_E_ENABLED:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+		break;
+
+	case IOC_E_FAILED:
+		/**
+		 * Initialization failure during iocpf init retry.
+		 */
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		break;
+
 	case IOC_E_DISABLE:
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 		break;
 
 	case IOC_E_DETACH:
-		bfa_ioc_timer_stop(ioc);
-		bfa_ioc_firmware_unlock(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
-		break;
-
-	case IOC_E_TIMEOUT:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		bfa_iocpf_stop(ioc);
 		break;
 
 	default:
@@ -611,74 +550,50 @@
 
 
 static void
-bfa_ioc_sm_hbfail_entry(struct bfa_ioc_s *ioc)
+bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
 {
-	struct list_head *qe;
-	struct bfa_ioc_hbfail_notify_s *notify;
-
-	/**
-	 * Mark IOC as failed in hardware and stop firmware.
-	 */
-	bfa_ioc_lpu_stop(ioc);
-	bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL);
-
-	/**
-	 * Notify other functions on HB failure.
-	 */
-	bfa_ioc_notify_hbfail(ioc);
+	struct list_head			*qe;
+	struct bfa_ioc_hbfail_notify_s	*notify;
+	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
 
 	/**
 	 * Notify driver and common modules registered for notification.
 	 */
 	ioc->cbfn->hbfail_cbfn(ioc->bfa);
 	list_for_each(qe, &ioc->hb_notify_q) {
-		notify = (struct bfa_ioc_hbfail_notify_s *)qe;
+		notify = (struct bfa_ioc_hbfail_notify_s *) qe;
 		notify->cbfn(notify->cbarg);
 	}
 
-	/**
-	 * Flush any queued up mailbox requests.
-	 */
-	bfa_ioc_mbox_hbfail(ioc);
-	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_HBFAIL);
-
-	/**
-	 * Trigger auto-recovery after a delay.
-	 */
-	if (ioc->auto_recover) {
-		bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer,
-				bfa_ioc_timeout, ioc, BFA_IOC_TOV_RECOVER);
-	}
+	BFA_LOG(KERN_CRIT, bfad, log_level,
+		"Heart Beat of IOC has failed\n");
 }
 
 /**
- * IOC heartbeat failure.
+ * IOC failure.
  */
 static void
-bfa_ioc_sm_hbfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
 {
 	bfa_trc(ioc, event);
 
 	switch (event) {
 
+	case IOC_E_FAILED:
+		/**
+		 * Initialization failure during iocpf recovery.
+		 * !!! Fall through !!!
+		 */
 	case IOC_E_ENABLE:
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 		break;
 
+	case IOC_E_ENABLED:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+		break;
+
 	case IOC_E_DISABLE:
-		if (ioc->auto_recover)
-			bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
-		break;
-
-	case IOC_E_TIMEOUT:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
-		break;
-
-	case IOC_E_FWREADY:
-		/**
-		 * Recovery is already initiated by other function.
-		 */
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 		break;
 
 	case IOC_E_HWERROR:
@@ -686,6 +601,498 @@
 		 * HB failure notification, ignore.
 		 */
 		break;
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+
+/**
+ * IOCPF State Machine
+ */
+
+
+/**
+ * Reset entry actions -- initialize state machine
+ */
+static void
+bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
+{
+	iocpf->retry_count = 0;
+	iocpf->auto_recover = bfa_auto_recover;
+}
+
+/**
+ * Beginning state. IOC is in reset state.
+ */
+static void
+bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_ENABLE:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
+		break;
+
+	case IOCPF_E_STOP:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Semaphore should be acquired for version check.
+ */
+static void
+bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/**
+ * Awaiting h/w semaphore to continue with version check.
+ */
+static void
+bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_SEMLOCKED:
+		if (bfa_ioc_firmware_lock(ioc)) {
+			iocpf->retry_count = 0;
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+		} else {
+			bfa_ioc_hw_sem_release(ioc);
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
+		}
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		bfa_ioc_pf_disabled(ioc);
+		break;
+
+	case IOCPF_E_STOP:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Notify enable completion callback.
+ */
+static void
+bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
+{
+	/*
+	 * Call only the first time sm enters fwmismatch state.
+	 */
+	if (iocpf->retry_count == 0)
+		bfa_ioc_pf_fwmismatch(iocpf->ioc);
+
+	iocpf->retry_count++;
+	bfa_iocpf_timer_start(iocpf->ioc);
+}
+
+/**
+ * Awaiting firmware version match.
+ */
+static void
+bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_TIMEOUT:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		bfa_ioc_pf_disabled(ioc);
+		break;
+
+	case IOCPF_E_STOP:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Request for semaphore.
+ */
+static void
+bfa_iocpf_sm_semwait_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/**
+ * Awaiting semaphore for h/w initialzation.
+ */
+static void
+bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_SEMLOCKED:
+		iocpf->retry_count = 0;
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_iocpf_timer_start(iocpf->ioc);
+	bfa_ioc_reset(iocpf->ioc, BFA_FALSE);
+}
+
+/**
+ * Hardware is being initialized. Interrupts are enabled.
+ * Holding hardware semaphore lock.
+ */
+static void
+bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_FWREADY:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
+		break;
+
+	case IOCPF_E_INITFAIL:
+		bfa_iocpf_timer_stop(ioc);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case IOCPF_E_TIMEOUT:
+		iocpf->retry_count++;
+		if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
+			bfa_iocpf_timer_start(ioc);
+			bfa_ioc_reset(ioc, BFA_TRUE);
+			break;
+		}
+
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+
+		if (event == IOCPF_E_TIMEOUT)
+			bfa_ioc_pf_failed(ioc);
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_iocpf_timer_start(iocpf->ioc);
+	bfa_ioc_send_enable(iocpf->ioc);
+}
+
+/**
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
+ */
+static void
+bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_FWRSP_ENABLE:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
+		break;
+
+	case IOCPF_E_INITFAIL:
+		bfa_iocpf_timer_stop(ioc);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case IOCPF_E_TIMEOUT:
+		iocpf->retry_count++;
+		if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
+			bfa_reg_write(ioc->ioc_regs.ioc_fwstate,
+				      BFI_IOC_UNINIT);
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+			break;
+		}
+
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+
+		if (event == IOCPF_E_TIMEOUT)
+			bfa_ioc_pf_failed(ioc);
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
+		break;
+
+	case IOCPF_E_FWREADY:
+		bfa_ioc_send_enable(ioc);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+
+static void
+bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_ioc_pf_enabled(iocpf->ioc);
+}
+
+static void
+bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_DISABLE:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
+		break;
+
+	case IOCPF_E_GETATTRFAIL:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+		break;
+
+	case IOCPF_E_FAIL:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		break;
+
+	case IOCPF_E_FWREADY:
+		if (bfa_ioc_is_operational(ioc))
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		else
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+
+		bfa_ioc_pf_failed(ioc);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_iocpf_timer_start(iocpf->ioc);
+	bfa_ioc_send_disable(iocpf->ioc);
+}
+
+/**
+ * IOC is being disabled
+ */
+static void
+bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_FWRSP_DISABLE:
+	case IOCPF_E_FWREADY:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	case IOCPF_E_FAIL:
+		bfa_iocpf_timer_stop(ioc);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case IOCPF_E_TIMEOUT:
+		bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	case IOCPF_E_FWRSP_ENABLE:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * IOC disable completion entry.
+ */
+static void
+bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_ioc_pf_disabled(iocpf->ioc);
+}
+
+static void
+bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_ENABLE:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+		break;
+
+	case IOCPF_E_STOP:
+		bfa_ioc_firmware_unlock(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_iocpf_timer_start(iocpf->ioc);
+}
+
+/**
+ * Hardware initialization failed.
+ */
+static void
+bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_DISABLE:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	case IOCPF_E_STOP:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_ioc_firmware_unlock(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	case IOCPF_E_TIMEOUT:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
+{
+	/**
+	 * Mark IOC as failed in hardware and stop firmware.
+	 */
+	bfa_ioc_lpu_stop(iocpf->ioc);
+	bfa_reg_write(iocpf->ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL);
+
+	/**
+	 * Notify other functions on HB failure.
+	 */
+	bfa_ioc_notify_hbfail(iocpf->ioc);
+
+	/**
+	 * Flush any queued up mailbox requests.
+	 */
+	bfa_ioc_mbox_hbfail(iocpf->ioc);
+
+	if (iocpf->auto_recover)
+		bfa_iocpf_recovery_timer_start(iocpf->ioc);
+}
+
+/**
+ * IOC is in failed state.
+ */
+static void
+bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_DISABLE:
+		if (iocpf->auto_recover)
+			bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	case IOCPF_E_TIMEOUT:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+		break;
 
 	default:
 		bfa_sm_fault(ioc, event);
@@ -695,14 +1102,14 @@
 
 
 /**
- *  bfa_ioc_pvt BFA IOC private functions
+ *  hal_ioc_pvt BFA IOC private functions
  */
 
 static void
 bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
 {
-	struct list_head *qe;
-	struct bfa_ioc_hbfail_notify_s *notify;
+	struct list_head			*qe;
+	struct bfa_ioc_hbfail_notify_s	*notify;
 
 	ioc->cbfn->disable_cbfn(ioc->bfa);
 
@@ -710,25 +1117,17 @@
 	 * Notify common modules registered for notification.
 	 */
 	list_for_each(qe, &ioc->hb_notify_q) {
-		notify = (struct bfa_ioc_hbfail_notify_s *)qe;
+		notify = (struct bfa_ioc_hbfail_notify_s *) qe;
 		notify->cbfn(notify->cbarg);
 	}
 }
 
-void
-bfa_ioc_sem_timeout(void *ioc_arg)
-{
-	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
-
-	bfa_ioc_hw_sem_get(ioc);
-}
-
 bfa_boolean_t
 bfa_ioc_sem_get(bfa_os_addr_t sem_reg)
 {
 	u32 r32;
 	int cnt = 0;
-#define BFA_SEM_SPINCNT 3000
+#define BFA_SEM_SPINCNT	3000
 
 	r32 = bfa_reg_read(sem_reg);
 
@@ -754,7 +1153,7 @@
 static void
 bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
 {
-	u32        r32;
+	u32	r32;
 
 	/**
 	 * First read to the semaphore register will return 0, subsequent reads
@@ -762,12 +1161,11 @@
 	 */
 	r32 = bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
 	if (r32 == 0) {
-		bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED);
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
 		return;
 	}
 
-	bfa_timer_begin(ioc->timer_mod, &ioc->sem_timer, bfa_ioc_sem_timeout,
-			ioc, BFA_IOC_HWSEM_TOV);
+	bfa_sem_timer_start(ioc);
 }
 
 void
@@ -779,7 +1177,7 @@
 static void
 bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc)
 {
-	bfa_timer_stop(&ioc->sem_timer);
+	bfa_sem_timer_stop(ioc);
 }
 
 /**
@@ -788,14 +1186,18 @@
 static void
 bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
 {
-	u32        pss_ctl;
-	int             i;
+	u32	pss_ctl;
+	int		i;
 #define PSS_LMEM_INIT_TIME  10000
 
 	pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
 	pss_ctl &= ~__PSS_LMEM_RESET;
 	pss_ctl |= __PSS_LMEM_INIT_EN;
-	pss_ctl |= __PSS_I2C_CLK_DIV(3UL); /* i2c workaround 12.5khz clock */
+
+	/*
+	 * i2c workaround 12.5khz clock
+	 */
+	pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
 	bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
 
 	/**
@@ -821,7 +1223,7 @@
 static void
 bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
 {
-	u32        pss_ctl;
+	u32	pss_ctl;
 
 	/**
 	 * Take processor out of reset.
@@ -835,7 +1237,7 @@
 static void
 bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
 {
-	u32        pss_ctl;
+	u32	pss_ctl;
 
 	/**
 	 * Put processors in reset.
@@ -852,10 +1254,10 @@
 void
 bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
 {
-	u32        pgnum, pgoff;
-	u32        loff = 0;
-	int             i;
-	u32       *fwsig = (u32 *) fwhdr;
+	u32	pgnum, pgoff;
+	u32	loff = 0;
+	int		i;
+	u32	*fwsig = (u32 *) fwhdr;
 
 	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
 	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
@@ -863,7 +1265,8 @@
 
 	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
 	     i++) {
-		fwsig[i] = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+		fwsig[i] =
+			bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
 		loff += sizeof(u32);
 	}
 }
@@ -875,10 +1278,10 @@
 bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
 {
 	struct bfi_ioc_image_hdr_s *drv_fwhdr;
-	int             i;
+	int i;
 
 	drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
-			bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
 
 	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
 		if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
@@ -897,21 +1300,20 @@
  * Return true if current running version is valid. Firmware signature and
  * execution context (driver/bios) must match.
  */
-static          bfa_boolean_t
-bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc)
+static bfa_boolean_t
+bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
 {
 	struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
 
 	/**
 	 * If bios/efi boot (flash based) -- return true
 	 */
-	if (bfa_ioc_is_optrom(ioc))
+	if (bfa_ioc_is_bios_optrom(ioc))
 		return BFA_TRUE;
 
 	bfa_ioc_fwver_get(ioc, &fwhdr);
 	drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
-			bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
-
+		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
 
 	if (fwhdr.signature != drv_fwhdr->signature) {
 		bfa_trc(ioc, fwhdr.signature);
@@ -919,9 +1321,9 @@
 		return BFA_FALSE;
 	}
 
-	if (fwhdr.exec != drv_fwhdr->exec) {
-		bfa_trc(ioc, fwhdr.exec);
-		bfa_trc(ioc, drv_fwhdr->exec);
+	if (bfa_os_swap32(fwhdr.param) != boot_env) {
+		bfa_trc(ioc, fwhdr.param);
+		bfa_trc(ioc, boot_env);
 		return BFA_FALSE;
 	}
 
@@ -934,7 +1336,7 @@
 static void
 bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
 {
-	u32        r32;
+	u32	r32;
 
 	r32 = bfa_reg_read(ioc->ioc_regs.lpu_mbox_cmd);
 	if (r32)
@@ -946,7 +1348,9 @@
 bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
 {
 	enum bfi_ioc_state ioc_fwstate;
-	bfa_boolean_t   fwvalid;
+	bfa_boolean_t fwvalid;
+	u32 boot_type;
+	u32 boot_env;
 
 	ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
 
@@ -955,14 +1359,33 @@
 
 	bfa_trc(ioc, ioc_fwstate);
 
+	boot_type = BFI_BOOT_TYPE_NORMAL;
+	boot_env = BFI_BOOT_LOADER_OS;
+
+	/**
+	 * Flash based firmware boot BIOS env.
+	 */
+	if (bfa_ioc_is_bios_optrom(ioc)) {
+		boot_type = BFI_BOOT_TYPE_FLASH;
+		boot_env = BFI_BOOT_LOADER_BIOS;
+	}
+
+	/**
+	 * Flash based firmware boot UEFI env.
+	 */
+	if (bfa_ioc_is_uefi(ioc)) {
+		boot_type = BFI_BOOT_TYPE_FLASH;
+		boot_env = BFI_BOOT_LOADER_UEFI;
+	}
+
 	/**
 	 * check if firmware is valid
 	 */
 	fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
-			BFA_FALSE : bfa_ioc_fwver_valid(ioc);
+		BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);
 
 	if (!fwvalid) {
-		bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+		bfa_ioc_boot(ioc, boot_type, boot_env);
 		return;
 	}
 
@@ -971,7 +1394,6 @@
 	 * just wait for an initialization completion interrupt.
 	 */
 	if (ioc_fwstate == BFI_IOC_INITING) {
-		bfa_trc(ioc, ioc_fwstate);
 		ioc->cbfn->reset_cbfn(ioc->bfa);
 		return;
 	}
@@ -985,8 +1407,7 @@
 	 * is loaded.
 	 */
 	if (ioc_fwstate == BFI_IOC_DISABLED ||
-		(!bfa_ioc_is_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
-		bfa_trc(ioc, ioc_fwstate);
+	    (!bfa_ioc_is_bios_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
 
 		/**
 		 * When using MSI-X any pending firmware ready event should
@@ -994,20 +1415,20 @@
 		 */
 		bfa_ioc_msgflush(ioc);
 		ioc->cbfn->reset_cbfn(ioc->bfa);
-		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
 		return;
 	}
 
 	/**
 	 * Initialize the h/w for any other states.
 	 */
-	bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+	bfa_ioc_boot(ioc, boot_type, boot_env);
 }
 
 static void
 bfa_ioc_timeout(void *ioc_arg)
 {
-	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
+	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
 
 	bfa_trc(ioc, 0);
 	bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
@@ -1016,8 +1437,8 @@
 void
 bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
 {
-	u32       *msgp = (u32 *) ioc_msg;
-	u32        i;
+	u32 *msgp = (u32 *) ioc_msg;
+	u32 i;
 
 	bfa_trc(ioc, msgp[0]);
 	bfa_trc(ioc, len);
@@ -1038,17 +1459,20 @@
 	 * write 1 to mailbox CMD to trigger LPU event
 	 */
 	bfa_reg_write(ioc->ioc_regs.hfn_mbox_cmd, 1);
-	(void)bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
+	(void) bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
 }
 
 static void
 bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
 {
 	struct bfi_ioc_ctrl_req_s enable_req;
+	struct bfa_timeval_s tv;
 
 	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
 		    bfa_ioc_portid(ioc));
 	enable_req.ioc_class = ioc->ioc_mc;
+	bfa_os_gettimeofday(&tv);
+	enable_req.tv_sec = bfa_os_ntohl(tv.tv_sec);
 	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
 }
 
@@ -1065,7 +1489,7 @@
 static void
 bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
 {
-	struct bfi_ioc_getattr_req_s attr_req;
+	struct bfi_ioc_getattr_req_s	attr_req;
 
 	bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
 		    bfa_ioc_portid(ioc));
@@ -1077,12 +1501,11 @@
 bfa_ioc_hb_check(void *cbarg)
 {
 	struct bfa_ioc_s  *ioc = cbarg;
-	u32     hb_count;
+	u32	hb_count;
 
 	hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
 	if (ioc->hb_count == hb_count) {
-		bfa_log(ioc->logm, BFA_LOG_HAL_HEARTBEAT_FAILURE,
-			hb_count);
+		printk(KERN_CRIT "Firmware heartbeat failure at %d", hb_count);
 		bfa_ioc_recover(ioc);
 		return;
 	} else {
@@ -1090,61 +1513,54 @@
 	}
 
 	bfa_ioc_mbox_poll(ioc);
-	bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check,
-			ioc, BFA_IOC_HB_TOV);
+	bfa_hb_timer_start(ioc);
 }
 
 static void
 bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
 {
 	ioc->hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
-	bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc,
-			BFA_IOC_HB_TOV);
+	bfa_hb_timer_start(ioc);
 }
 
 static void
 bfa_ioc_hb_stop(struct bfa_ioc_s *ioc)
 {
-	bfa_timer_stop(&ioc->ioc_timer);
+	bfa_hb_timer_stop(ioc);
 }
 
+
 /**
- *      Initiate a full firmware download.
+ *	Initiate a full firmware download.
  */
 static void
 bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
-		    u32 boot_param)
+		    u32 boot_env)
 {
-	u32       *fwimg;
-	u32        pgnum, pgoff;
-	u32        loff = 0;
-	u32        chunkno = 0;
-	u32        i;
+	u32 *fwimg;
+	u32 pgnum, pgoff;
+	u32 loff = 0;
+	u32 chunkno = 0;
+	u32 i;
 
 	/**
 	 * Initialize LMEM first before code download
 	 */
 	bfa_ioc_lmem_init(ioc);
 
-	/**
-	 * Flash based firmware boot
-	 */
-	bfa_trc(ioc, bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
-	if (bfa_ioc_is_optrom(ioc))
-		boot_type = BFI_BOOT_TYPE_FLASH;
-	fwimg = bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
-
+	bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
+	fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
 
 	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
 	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
 
 	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
 
-	for (i = 0; i < bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
+	for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
 
 		if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
 			chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
-			fwimg = bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
+			fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
 					BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
 		}
 
@@ -1162,7 +1578,8 @@
 		loff = PSS_SMEM_PGOFF(loff);
 		if (loff == 0) {
 			pgnum++;
-			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+			bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+				      pgnum);
 		}
 	}
 
@@ -1171,11 +1588,11 @@
 
 	/*
 	 * Set boot type and boot param at the end.
-	 */
+	*/
 	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_TYPE_OFF,
 			bfa_os_swap32(boot_type));
-	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_PARAM_OFF,
-			bfa_os_swap32(boot_param));
+	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_LOADER_OFF,
+			bfa_os_swap32(boot_env));
 }
 
 static void
@@ -1190,11 +1607,11 @@
 static void
 bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
 {
-	struct bfi_ioc_attr_s *attr = ioc->attr;
+	struct bfi_ioc_attr_s	*attr = ioc->attr;
 
-	attr->adapter_prop = bfa_os_ntohl(attr->adapter_prop);
+	attr->adapter_prop  = bfa_os_ntohl(attr->adapter_prop);
 	attr->card_type     = bfa_os_ntohl(attr->card_type);
-	attr->maxfrsize = bfa_os_ntohs(attr->maxfrsize);
+	attr->maxfrsize	    = bfa_os_ntohs(attr->maxfrsize);
 
 	bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
 }
@@ -1205,8 +1622,8 @@
 static void
 bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	int             mc;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	int	mc;
 
 	INIT_LIST_HEAD(&mod->cmd_q);
 	for (mc = 0; mc < BFI_MC_MAX; mc++) {
@@ -1221,9 +1638,9 @@
 static void
 bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	struct bfa_mbox_cmd_s *cmd;
-	u32        stat;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	struct bfa_mbox_cmd_s		*cmd;
+	u32			stat;
 
 	/**
 	 * If no command pending, do nothing
@@ -1251,25 +1668,194 @@
 static void
 bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	struct bfa_mbox_cmd_s *cmd;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	struct bfa_mbox_cmd_s		*cmd;
 
 	while (!list_empty(&mod->cmd_q))
 		bfa_q_deq(&mod->cmd_q, &cmd);
 }
 
 /**
- *  bfa_ioc_public
+ * Read data from SMEM to host through PCI memmap
+ *
+ * @param[in]	ioc	memory for IOC
+ * @param[in]	tbuf	app memory to store data from smem
+ * @param[in]	soff	smem offset
+ * @param[in]	sz	size of smem in bytes
  */
+static bfa_status_t
+bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
+{
+	u32 pgnum, loff, r32;
+	int i, len;
+	u32 *buf = tbuf;
+
+	pgnum = bfa_ioc_smem_pgnum(ioc, soff);
+	loff = bfa_ioc_smem_pgoff(ioc, soff);
+	bfa_trc(ioc, pgnum);
+	bfa_trc(ioc, loff);
+	bfa_trc(ioc, sz);
+
+	/*
+	 *  Hold semaphore to serialize pll init and fwtrc.
+	 */
+	if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
+		bfa_trc(ioc, 0);
+		return BFA_STATUS_FAILED;
+	}
+
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+	len = sz/sizeof(u32);
+	bfa_trc(ioc, len);
+	for (i = 0; i < len; i++) {
+		r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+		buf[i] = bfa_os_ntohl(r32);
+		loff += sizeof(u32);
+
+		/**
+		 * handle page offset wrap around
+		 */
+		loff = PSS_SMEM_PGOFF(loff);
+		if (loff == 0) {
+			pgnum++;
+			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+		}
+	}
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+		      bfa_ioc_smem_pgnum(ioc, 0));
+	/*
+	 *  release semaphore.
+	 */
+	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+
+	bfa_trc(ioc, pgnum);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Clear SMEM data from host through PCI memmap
+ *
+ * @param[in]	ioc	memory for IOC
+ * @param[in]	soff	smem offset
+ * @param[in]	sz	size of smem in bytes
+ */
+static bfa_status_t
+bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
+{
+	int i, len;
+	u32 pgnum, loff;
+
+	pgnum = bfa_ioc_smem_pgnum(ioc, soff);
+	loff = bfa_ioc_smem_pgoff(ioc, soff);
+	bfa_trc(ioc, pgnum);
+	bfa_trc(ioc, loff);
+	bfa_trc(ioc, sz);
+
+	/*
+	 *  Hold semaphore to serialize pll init and fwtrc.
+	 */
+	if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
+		bfa_trc(ioc, 0);
+		return BFA_STATUS_FAILED;
+	}
+
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+	len = sz/sizeof(u32); /* len in words */
+	bfa_trc(ioc, len);
+	for (i = 0; i < len; i++) {
+		bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 0);
+		loff += sizeof(u32);
+
+		/**
+		 * handle page offset wrap around
+		 */
+		loff = PSS_SMEM_PGOFF(loff);
+		if (loff == 0) {
+			pgnum++;
+			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+		}
+	}
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+		      bfa_ioc_smem_pgnum(ioc, 0));
+
+	/*
+	 *  release semaphore.
+	 */
+	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+	bfa_trc(ioc, pgnum);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * hal iocpf to ioc interface
+ */
+static void
+bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_ENABLED);
+}
+
+static void
+bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_DISABLED);
+}
+
+static void
+bfa_ioc_pf_failed(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_FAILED);
+}
+
+static void
+bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
+{
+	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+	/**
+	 * Provide enable completion callback.
+	 */
+	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+	BFA_LOG(KERN_WARNING, bfad, log_level,
+		"Running firmware version is incompatible "
+		"with the driver version\n");
+}
+
+
+
+/**
+ *  hal_ioc_public
+ */
+
+bfa_status_t
+bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
+{
+
+	/*
+	 *  Hold semaphore so that nobody can access the chip during init.
+	 */
+	bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
+
+	bfa_ioc_pll_init_asic(ioc);
+
+	ioc->pllinit = BFA_TRUE;
+	/*
+	 *  release semaphore.
+	 */
+	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+
+	return BFA_STATUS_OK;
+}
 
 /**
  * Interface used by diag module to do firmware boot with memory test
  * as the entry vector.
  */
 void
-bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param)
+bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
 {
-	bfa_os_addr_t   rb;
+	bfa_os_addr_t	rb;
 
 	bfa_ioc_stats(ioc, ioc_boots);
 
@@ -1280,7 +1866,7 @@
 	 * Initialize IOC state of all functions on a chip reset.
 	 */
 	rb = ioc->pcidev.pci_bar_kva;
-	if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
+	if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
 		bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_MEMTEST);
 		bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_MEMTEST);
 	} else {
@@ -1289,7 +1875,7 @@
 	}
 
 	bfa_ioc_msgflush(ioc);
-	bfa_ioc_download_fw(ioc, boot_type, boot_param);
+	bfa_ioc_download_fw(ioc, boot_type, boot_env);
 
 	/**
 	 * Enable interrupts just before starting LPU
@@ -1308,18 +1894,29 @@
 }
 
 
+
 bfa_boolean_t
 bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
 {
 	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
 }
 
+bfa_boolean_t
+bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
+{
+	u32 r32 = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
+
+	return ((r32 != BFI_IOC_UNINIT) &&
+		(r32 != BFI_IOC_INITING) &&
+		(r32 != BFI_IOC_MEMTEST));
+}
+
 void
 bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
 {
-	u32       *msgp = mbmsg;
-	u32        r32;
-	int             i;
+	u32	*msgp = mbmsg;
+	u32	r32;
+	int		i;
 
 	/**
 	 * read the MBOX msg
@@ -1341,9 +1938,10 @@
 void
 bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
 {
-	union bfi_ioc_i2h_msg_u *msg;
+	union bfi_ioc_i2h_msg_u	*msg;
+	struct bfa_iocpf_s *iocpf = &ioc->iocpf;
 
-	msg = (union bfi_ioc_i2h_msg_u *)m;
+	msg = (union bfi_ioc_i2h_msg_u *) m;
 
 	bfa_ioc_stats(ioc, ioc_isrs);
 
@@ -1352,15 +1950,15 @@
 		break;
 
 	case BFI_IOC_I2H_READY_EVENT:
-		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+		bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
 		break;
 
 	case BFI_IOC_I2H_ENABLE_REPLY:
-		bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE);
+		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
 		break;
 
 	case BFI_IOC_I2H_DISABLE_REPLY:
-		bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE);
+		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
 		break;
 
 	case BFI_IOC_I2H_GETATTR_REPLY:
@@ -1378,29 +1976,24 @@
  *
  * @param[in]	ioc	memory for IOC
  * @param[in]	bfa	driver instance structure
- * @param[in]	trcmod	kernel trace module
- * @param[in]	aen	kernel aen event module
- * @param[in]	logm	kernel logging module
  */
 void
 bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
-	       struct bfa_timer_mod_s *timer_mod, struct bfa_trc_mod_s *trcmod,
-	       struct bfa_aen_s *aen, struct bfa_log_mod_s *logm)
+	       struct bfa_timer_mod_s *timer_mod)
 {
-	ioc->bfa = bfa;
-	ioc->cbfn = cbfn;
-	ioc->timer_mod = timer_mod;
-	ioc->trcmod = trcmod;
-	ioc->aen = aen;
-	ioc->logm = logm;
-	ioc->fcmode = BFA_FALSE;
-	ioc->pllinit = BFA_FALSE;
+	ioc->bfa	= bfa;
+	ioc->cbfn	= cbfn;
+	ioc->timer_mod	= timer_mod;
+	ioc->fcmode	= BFA_FALSE;
+	ioc->pllinit	= BFA_FALSE;
 	ioc->dbg_fwsave_once = BFA_TRUE;
+	ioc->iocpf.ioc	= ioc;
 
 	bfa_ioc_mbox_attach(ioc);
 	INIT_LIST_HEAD(&ioc->hb_notify_q);
 
-	bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+	bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+	bfa_fsm_send_event(ioc, IOC_E_RESET);
 }
 
 /**
@@ -1421,10 +2014,10 @@
 bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
 		 enum bfi_mclass mc)
 {
-	ioc->ioc_mc = mc;
-	ioc->pcidev = *pcidev;
-	ioc->ctdev  = bfa_asic_id_ct(ioc->pcidev.device_id);
-	ioc->cna = ioc->ctdev && !ioc->fcmode;
+	ioc->ioc_mc	= mc;
+	ioc->pcidev	= *pcidev;
+	ioc->ctdev	= bfa_asic_id_ct(ioc->pcidev.device_id);
+	ioc->cna	= ioc->ctdev && !ioc->fcmode;
 
 	/**
 	 * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c
@@ -1445,14 +2038,14 @@
  * @param[in]	dm_pa	physical address of IOC dma memory
  */
 void
-bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
+bfa_ioc_mem_claim(struct bfa_ioc_s *ioc,  u8 *dm_kva, u64 dm_pa)
 {
 	/**
 	 * dma memory for firmware attribute
 	 */
 	ioc->attr_dma.kva = dm_kva;
 	ioc->attr_dma.pa = dm_pa;
-	ioc->attr = (struct bfi_ioc_attr_s *)dm_kva;
+	ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;
 }
 
 /**
@@ -1490,7 +2083,7 @@
 int
 bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover)
 {
-return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
+	return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
 }
 
 /**
@@ -1500,8 +2093,8 @@
 void
 bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
 {
-	ioc->dbg_fwsave = dbg_fwsave;
-	ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->auto_recover);
+	ioc->dbg_fwsave	    = dbg_fwsave;
+	ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->iocpf.auto_recover);
 }
 
 u32
@@ -1525,8 +2118,8 @@
 void
 bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	int             mc;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	int				mc;
 
 	for (mc = 0; mc < BFI_MC_MAX; mc++)
 		mod->mbhdlr[mc].cbfn = mcfuncs[mc];
@@ -1539,10 +2132,10 @@
 bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
 		    bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
 
-	mod->mbhdlr[mc].cbfn = cbfn;
-	mod->mbhdlr[mc].cbarg = cbarg;
+	mod->mbhdlr[mc].cbfn	= cbfn;
+	mod->mbhdlr[mc].cbarg	= cbarg;
 }
 
 /**
@@ -1555,8 +2148,8 @@
 void
 bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	u32        stat;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	u32			stat;
 
 	/**
 	 * If a previous command is pending, queue new command
@@ -1587,9 +2180,9 @@
 void
 bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	struct bfi_mbmsg_s m;
-	int             mc;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	struct bfi_mbmsg_s		m;
+	int				mc;
 
 	bfa_ioc_msgget(ioc, &m);
 
@@ -1621,16 +2214,14 @@
 	ioc->port_id = bfa_ioc_pcifn(ioc);
 }
 
-#ifndef BFA_BIOS_BUILD
-
 /**
  * return true if IOC is disabled
  */
 bfa_boolean_t
 bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
 {
-	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling)
-		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
+		bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
 }
 
 /**
@@ -1639,9 +2230,9 @@
 bfa_boolean_t
 bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
 {
-	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset)
-		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck)
-		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch);
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) ||
+		bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_fwcheck) ||
+		bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);
 }
 
 #define bfa_ioc_state_disabled(__sm)		\
@@ -1659,8 +2250,8 @@
 bfa_boolean_t
 bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
 {
-	u32        ioc_state;
-	bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
+	u32	ioc_state;
+	bfa_os_addr_t	rb = ioc->pcidev.pci_bar_kva;
 
 	if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
 		return BFA_FALSE;
@@ -1669,16 +2260,18 @@
 	if (!bfa_ioc_state_disabled(ioc_state))
 		return BFA_FALSE;
 
-	ioc_state = bfa_reg_read(rb + BFA_IOC1_STATE_REG);
-	if (!bfa_ioc_state_disabled(ioc_state))
-		return BFA_FALSE;
+	if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
+		ioc_state = bfa_reg_read(rb + BFA_IOC1_STATE_REG);
+		if (!bfa_ioc_state_disabled(ioc_state))
+			return BFA_FALSE;
+	}
 
 	return BFA_TRUE;
 }
 
 /**
  * Add to IOC heartbeat failure notification queue. To be used by common
- * modules such as
+ * modules such as cee, port, diag.
  */
 void
 bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
@@ -1692,7 +2285,7 @@
 bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
 			 struct bfa_adapter_attr_s *ad_attr)
 {
-	struct bfi_ioc_attr_s *ioc_attr;
+	struct bfi_ioc_attr_s	*ioc_attr;
 
 	ioc_attr = ioc->attr;
 
@@ -1719,7 +2312,7 @@
 		ad_attr->prototype = 0;
 
 	ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
-	ad_attr->mac = bfa_ioc_get_mac(ioc);
+	ad_attr->mac  = bfa_ioc_get_mac(ioc);
 
 	ad_attr->pcie_gen = ioc_attr->pcie_gen;
 	ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
@@ -1729,6 +2322,7 @@
 	bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
 
 	ad_attr->cna_capable = ioc->cna;
+	ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
 }
 
 enum bfa_ioc_type_e
@@ -1782,7 +2376,7 @@
 {
 	bfa_os_memset((void *)optrom_ver, 0, BFA_VERSION_LEN);
 	bfa_os_memcpy(optrom_ver, ioc->attr->optrom_version,
-		BFA_VERSION_LEN);
+		      BFA_VERSION_LEN);
 }
 
 void
@@ -1795,7 +2389,7 @@
 void
 bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
 {
-	struct bfi_ioc_attr_s   *ioc_attr;
+	struct bfi_ioc_attr_s	*ioc_attr;
 
 	bfa_assert(model);
 	bfa_os_memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
@@ -1805,14 +2399,48 @@
 	/**
 	 * model name
 	 */
-	snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
-			BFA_MFG_NAME, ioc_attr->card_type);
+	bfa_os_snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
+		BFA_MFG_NAME, ioc_attr->card_type);
 }
 
 enum bfa_ioc_state
 bfa_ioc_get_state(struct bfa_ioc_s *ioc)
 {
-	return bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+	enum bfa_iocpf_state iocpf_st;
+	enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+
+	if (ioc_st == BFA_IOC_ENABLING ||
+		ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
+
+		iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
+
+		switch (iocpf_st) {
+		case BFA_IOCPF_SEMWAIT:
+			ioc_st = BFA_IOC_SEMWAIT;
+			break;
+
+		case BFA_IOCPF_HWINIT:
+			ioc_st = BFA_IOC_HWINIT;
+			break;
+
+		case BFA_IOCPF_FWMISMATCH:
+			ioc_st = BFA_IOC_FWMISMATCH;
+			break;
+
+		case BFA_IOCPF_FAIL:
+			ioc_st = BFA_IOC_FAIL;
+			break;
+
+		case BFA_IOCPF_INITFAIL:
+			ioc_st = BFA_IOC_INITFAIL;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	return ioc_st;
 }
 
 void
@@ -1833,7 +2461,7 @@
 }
 
 /**
- *  bfa_wwn_public
+ *  hal_wwn_public
  */
 wwn_t
 bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc)
@@ -1857,10 +2485,10 @@
 bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
 {
 	/*
-	 * Currently mfg mac is used as FCoE enode mac (not configured by PBC)
+	 * Check the IOC type and return the appropriate MAC
 	 */
 	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
-		return bfa_ioc_get_mfg_mac(ioc);
+		return ioc->attr->fcoe_mac;
 	else
 		return ioc->attr->mac;
 }
@@ -1880,12 +2508,16 @@
 mac_t
 bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
 {
-	mac_t   mac;
+	mac_t	m;
 
-	mac = ioc->attr->mfg_mac;
-	mac.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
+	m = ioc->attr->mfg_mac;
+	if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
+		m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
+	else
+		bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
+			bfa_ioc_pcifn(ioc));
 
-	return mac;
+	return m;
 }
 
 bfa_boolean_t
@@ -1895,46 +2527,12 @@
 }
 
 /**
- * Send AEN notification
- */
-void
-bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = ioc->logm;
-	s32         inst_num = 0;
-	enum bfa_ioc_type_e ioc_type;
-
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, event), inst_num);
-
-	memset(&aen_data.ioc.pwwn, 0, sizeof(aen_data.ioc.pwwn));
-	memset(&aen_data.ioc.mac, 0, sizeof(aen_data.ioc.mac));
-	ioc_type = bfa_ioc_get_type(ioc);
-	switch (ioc_type) {
-	case BFA_IOC_TYPE_FC:
-		aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc);
-		break;
-	case BFA_IOC_TYPE_FCoE:
-		aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc);
-		aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
-		break;
-	case BFA_IOC_TYPE_LL:
-		aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
-		break;
-	default:
-		bfa_assert(ioc_type == BFA_IOC_TYPE_FC);
-		break;
-	}
-	aen_data.ioc.ioc_type = ioc_type;
-}
-
-/**
  * Retrieve saved firmware trace from a prior IOC failure.
  */
 bfa_status_t
 bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
 {
-	int             tlen;
+	int	tlen;
 
 	if (ioc->dbg_fwsave_len == 0)
 		return BFA_STATUS_ENOFSAVE;
@@ -1963,57 +2561,145 @@
 bfa_status_t
 bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
 {
-	u32        pgnum;
-	u32        loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
-	int             i, tlen;
-	u32       *tbuf = trcdata, r32;
+	u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
+	int tlen;
+	bfa_status_t status;
 
 	bfa_trc(ioc, *trclen);
 
-	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
-	loff = bfa_ioc_smem_pgoff(ioc, loff);
-
-	/*
-	 *  Hold semaphore to serialize pll init and fwtrc.
-	 */
-	if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg))
-		return BFA_STATUS_FAILED;
-
-	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
-
 	tlen = *trclen;
 	if (tlen > BFA_DBG_FWTRC_LEN)
 		tlen = BFA_DBG_FWTRC_LEN;
-	tlen /= sizeof(u32);
 
-	bfa_trc(ioc, tlen);
+	status = bfa_ioc_smem_read(ioc, trcdata, loff, tlen);
+	*trclen = tlen;
+	return status;
+}
 
-	for (i = 0; i < tlen; i++) {
-		r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
-		tbuf[i] = bfa_os_ntohl(r32);
-		loff += sizeof(u32);
+static void
+bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)
+{
+	struct bfa_mbox_cmd_s cmd;
+	struct bfi_ioc_ctrl_req_s *req = (struct bfi_ioc_ctrl_req_s *) cmd.msg;
 
-		/**
-		 * handle page offset wrap around
-		 */
-		loff = PSS_SMEM_PGOFF(loff);
-		if (loff == 0) {
-			pgnum++;
-			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
-		}
-	}
-	bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
-		      bfa_ioc_smem_pgnum(ioc, 0));
+	bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,
+		    bfa_ioc_portid(ioc));
+	req->ioc_class = ioc->ioc_mc;
+	bfa_ioc_mbox_queue(ioc, &cmd);
+}
 
-	/*
-	 *  release semaphore.
+static void
+bfa_ioc_fwsync(struct bfa_ioc_s *ioc)
+{
+	u32 fwsync_iter = 1000;
+
+	bfa_ioc_send_fwsync(ioc);
+
+	/**
+	 * After sending a fw sync mbox command wait for it to
+	 * take effect.  We will not wait for a response because
+	 *    1. fw_sync mbox cmd doesn't have a response.
+	 *    2. Even if we implement that,  interrupts might not
+	 *	 be enabled when we call this function.
+	 * So, just keep checking if any mbox cmd is pending, and
+	 * after waiting for a reasonable amount of time, go ahead.
+	 * It is possible that fw has crashed and the mbox command
+	 * is never acknowledged.
 	 */
-	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+	while (bfa_ioc_mbox_cmd_pending(ioc) && fwsync_iter > 0)
+		fwsync_iter--;
+}
 
-	bfa_trc(ioc, pgnum);
+/**
+ * Dump firmware smem
+ */
+bfa_status_t
+bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
+				u32 *offset, int *buflen)
+{
+	u32 loff;
+	int dlen;
+	bfa_status_t status;
+	u32 smem_len = BFA_IOC_FW_SMEM_SIZE(ioc);
 
-	*trclen = tlen * sizeof(u32);
-	return BFA_STATUS_OK;
+	if (*offset >= smem_len) {
+		*offset = *buflen = 0;
+		return BFA_STATUS_EINVAL;
+	}
+
+	loff = *offset;
+	dlen = *buflen;
+
+	/**
+	 * First smem read, sync smem before proceeding
+	 * No need to sync before reading every chunk.
+	 */
+	if (loff == 0)
+		bfa_ioc_fwsync(ioc);
+
+	if ((loff + dlen) >= smem_len)
+		dlen = smem_len - loff;
+
+	status = bfa_ioc_smem_read(ioc, buf, loff, dlen);
+
+	if (status != BFA_STATUS_OK) {
+		*offset = *buflen = 0;
+		return status;
+	}
+
+	*offset += dlen;
+
+	if (*offset >= smem_len)
+		*offset = 0;
+
+	*buflen = dlen;
+
+	return status;
+}
+
+/**
+ * Firmware statistics
+ */
+bfa_status_t
+bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats)
+{
+	u32 loff = BFI_IOC_FWSTATS_OFF + \
+		BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
+	int tlen;
+	bfa_status_t status;
+
+	if (ioc->stats_busy) {
+		bfa_trc(ioc, ioc->stats_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+	ioc->stats_busy = BFA_TRUE;
+
+	tlen = sizeof(struct bfa_fw_stats_s);
+	status = bfa_ioc_smem_read(ioc, stats, loff, tlen);
+
+	ioc->stats_busy = BFA_FALSE;
+	return status;
+}
+
+bfa_status_t
+bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
+{
+	u32 loff = BFI_IOC_FWSTATS_OFF + \
+		BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
+	int tlen;
+	bfa_status_t status;
+
+	if (ioc->stats_busy) {
+		bfa_trc(ioc, ioc->stats_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+	ioc->stats_busy = BFA_TRUE;
+
+	tlen = sizeof(struct bfa_fw_stats_s);
+	status = bfa_ioc_smem_clr(ioc, loff, tlen);
+
+	ioc->stats_busy = BFA_FALSE;
+	return status;
 }
 
 /**
@@ -2022,7 +2708,7 @@
 static void
 bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
 {
-	int             tlen;
+	int		tlen;
 
 	if (ioc->dbg_fwsave_len) {
 		tlen = ioc->dbg_fwsave_len;
@@ -2050,11 +2736,135 @@
 {
 	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
 		return;
-
-	if (ioc->attr->nwwn == 0)
-		bfa_ioc_aen_post(ioc, BFA_IOC_AEN_INVALID_NWWN);
-	if (ioc->attr->pwwn == 0)
-		bfa_ioc_aen_post(ioc, BFA_IOC_AEN_INVALID_PWWN);
 }
 
-#endif
+/**
+ *  hal_iocpf_pvt BFA IOC PF private functions
+ */
+
+static void
+bfa_iocpf_enable(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
+}
+
+static void
+bfa_iocpf_disable(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
+}
+
+static void
+bfa_iocpf_fail(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
+}
+
+static void
+bfa_iocpf_initfail(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
+}
+
+static void
+bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
+}
+
+static void
+bfa_iocpf_stop(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
+}
+
+static void
+bfa_iocpf_timeout(void *ioc_arg)
+{
+	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
+
+	bfa_trc(ioc, 0);
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
+}
+
+static void
+bfa_iocpf_sem_timeout(void *ioc_arg)
+{
+	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
+
+	bfa_ioc_hw_sem_get(ioc);
+}
+
+/**
+ *  bfa timer function
+ */
+void
+bfa_timer_init(struct bfa_timer_mod_s *mod)
+{
+	INIT_LIST_HEAD(&mod->timer_q);
+}
+
+void
+bfa_timer_beat(struct bfa_timer_mod_s *mod)
+{
+	struct list_head *qh = &mod->timer_q;
+	struct list_head *qe, *qe_next;
+	struct bfa_timer_s *elem;
+	struct list_head timedout_q;
+
+	INIT_LIST_HEAD(&timedout_q);
+
+	qe = bfa_q_next(qh);
+
+	while (qe != qh) {
+		qe_next = bfa_q_next(qe);
+
+		elem = (struct bfa_timer_s *) qe;
+		if (elem->timeout <= BFA_TIMER_FREQ) {
+			elem->timeout = 0;
+			list_del(&elem->qe);
+			list_add_tail(&elem->qe, &timedout_q);
+		} else {
+			elem->timeout -= BFA_TIMER_FREQ;
+		}
+
+		qe = qe_next;	/* go to next elem */
+	}
+
+	/*
+	 * Pop all the timeout entries
+	 */
+	while (!list_empty(&timedout_q)) {
+		bfa_q_deq(&timedout_q, &elem);
+		elem->timercb(elem->arg);
+	}
+}
+
+/**
+ * Should be called with lock protection
+ */
+void
+bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
+		    void (*timercb) (void *), void *arg, unsigned int timeout)
+{
+
+	bfa_assert(timercb != NULL);
+	bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
+
+	timer->timeout = timeout;
+	timer->timercb = timercb;
+	timer->arg = arg;
+
+	list_add_tail(&timer->qe, &mod->timer_q);
+}
+
+/**
+ * Should be called with lock protection
+ */
+void
+bfa_timer_stop(struct bfa_timer_s *timer)
+{
+	bfa_assert(!list_empty(&timer->qe));
+
+	list_del(&timer->qe);
+}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index cae05b2..288c580 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -18,18 +18,74 @@
 #ifndef __BFA_IOC_H__
 #define __BFA_IOC_H__
 
-#include <cs/bfa_sm.h>
-#include <bfi/bfi.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_boot.h>
-#include <bfa_timer.h>
+#include "bfa_os_inc.h"
+#include "bfa_cs.h"
+#include "bfi.h"
+
+/**
+ * BFA timer declarations
+ */
+typedef void (*bfa_timer_cbfn_t)(void *);
+
+/**
+ * BFA timer data structure
+ */
+struct bfa_timer_s {
+	struct list_head	qe;
+	bfa_timer_cbfn_t timercb;
+	void		*arg;
+	int		timeout;	/**< in millisecs. */
+};
+
+/**
+ * Timer module structure
+ */
+struct bfa_timer_mod_s {
+	struct list_head timer_q;
+};
+
+#define BFA_TIMER_FREQ 200 /**< specified in millisecs */
+
+void bfa_timer_beat(struct bfa_timer_mod_s *mod);
+void bfa_timer_init(struct bfa_timer_mod_s *mod);
+void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
+			bfa_timer_cbfn_t timercb, void *arg,
+			unsigned int timeout);
+void bfa_timer_stop(struct bfa_timer_s *timer);
+
+/**
+ * Generic Scatter Gather Element used by driver
+ */
+struct bfa_sge_s {
+	u32	sg_len;
+	void		*sg_addr;
+};
+
+#define bfa_sge_word_swap(__sge) do {					     \
+	((u32 *)(__sge))[0] = bfa_os_swap32(((u32 *)(__sge))[0]);      \
+	((u32 *)(__sge))[1] = bfa_os_swap32(((u32 *)(__sge))[1]);      \
+	((u32 *)(__sge))[2] = bfa_os_swap32(((u32 *)(__sge))[2]);      \
+} while (0)
+
+#define bfa_swap_words(_x)  (	\
+	((_x) << 32) | ((_x) >> 32))
+
+#ifdef __BIGENDIAN
+#define bfa_sge_to_be(_x)
+#define bfa_sge_to_le(_x)	bfa_sge_word_swap(_x)
+#define bfa_sgaddr_le(_x)	bfa_swap_words(_x)
+#else
+#define	bfa_sge_to_be(_x)	bfa_sge_word_swap(_x)
+#define bfa_sge_to_le(_x)
+#define bfa_sgaddr_le(_x)	(_x)
+#endif
 
 /**
  * PCI device information required by IOC
  */
 struct bfa_pcidev_s {
-	int             pci_slot;
-	u8         pci_func;
+	int		pci_slot;
+	u8		pci_func;
 	u16	device_id;
 	bfa_os_addr_t   pci_bar_kva;
 };
@@ -39,13 +95,18 @@
  * Address
  */
 struct bfa_dma_s {
-	void		*kva;	/*! Kernel virtual address	*/
-	u64	pa;	/*! Physical address		*/
+	void		*kva;	/* ! Kernel virtual address	*/
+	u64	pa;	/* ! Physical address		*/
 };
 
 #define BFA_DMA_ALIGN_SZ	256
 #define BFA_ROUNDUP(_l, _s)	(((_l) + ((_s) - 1)) & ~((_s) - 1))
 
+/**
+ * smem size for Crossbow and Catapult
+ */
+#define BFI_SMEM_CB_SIZE	0x200000U	/* ! 2MB for crossbow	*/
+#define BFI_SMEM_CT_SIZE	0x280000U	/* ! 2.5MB for catapult	*/
 
 
 #define bfa_dma_addr_set(dma_addr, pa)	\
@@ -101,7 +162,7 @@
  * IOC Mailbox structures
  */
 struct bfa_mbox_cmd_s {
-	struct list_head		qe;
+	struct list_head	qe;
 	u32	msg[BFI_IOC_MSGSZ];
 };
 
@@ -110,8 +171,8 @@
  */
 typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg_s *m);
 struct bfa_ioc_mbox_mod_s {
-	struct list_head	cmd_q;		/*  pending mbox queue	*/
-	int		nmclass;	/*  number of handlers */
+	struct list_head		cmd_q;	/*  pending mbox queue	*/
+	int			nmclass;	/*  number of handlers */
 	struct {
 		bfa_ioc_mbox_mcfunc_t	cbfn;	/*  message handlers	*/
 		void			*cbarg;
@@ -149,49 +210,54 @@
 	(__notify)->cbarg = (__cbarg);      \
 } while (0)
 
+struct bfa_iocpf_s {
+	bfa_fsm_t		fsm;
+	struct bfa_ioc_s	*ioc;
+	u32		retry_count;
+	bfa_boolean_t		auto_recover;
+};
+
 struct bfa_ioc_s {
 	bfa_fsm_t		fsm;
 	struct bfa_s		*bfa;
 	struct bfa_pcidev_s	pcidev;
-	struct bfa_timer_mod_s 	*timer_mod;
-	struct bfa_timer_s 	ioc_timer;
-	struct bfa_timer_s 	sem_timer;
+	struct bfa_timer_mod_s	*timer_mod;
+	struct bfa_timer_s	ioc_timer;
+	struct bfa_timer_s	sem_timer;
+	struct bfa_timer_s	hb_timer;
 	u32		hb_count;
-	u32		retry_count;
 	struct list_head		hb_notify_q;
 	void			*dbg_fwsave;
 	int			dbg_fwsave_len;
 	bfa_boolean_t		dbg_fwsave_once;
 	enum bfi_mclass		ioc_mc;
-	struct bfa_ioc_regs_s 	ioc_regs;
+	struct bfa_ioc_regs_s	ioc_regs;
 	struct bfa_trc_mod_s	*trcmod;
-	struct bfa_aen_s	*aen;
-	struct bfa_log_mod_s	*logm;
 	struct bfa_ioc_drv_stats_s	stats;
-	bfa_boolean_t		auto_recover;
 	bfa_boolean_t		fcmode;
 	bfa_boolean_t		ctdev;
 	bfa_boolean_t		cna;
 	bfa_boolean_t		pllinit;
+	bfa_boolean_t		stats_busy;	/*  outstanding stats */
 	u8			port_id;
-
 	struct bfa_dma_s	attr_dma;
 	struct bfi_ioc_attr_s	*attr;
 	struct bfa_ioc_cbfn_s	*cbfn;
 	struct bfa_ioc_mbox_mod_s mbox_mod;
-	struct bfa_ioc_hwif_s   *ioc_hwif;
+	struct bfa_ioc_hwif_s	*ioc_hwif;
+	struct bfa_iocpf_s	iocpf;
 };
 
 struct bfa_ioc_hwif_s {
-	bfa_status_t    (*ioc_pll_init) (struct bfa_ioc_s *ioc);
-	bfa_boolean_t   (*ioc_firmware_lock)    (struct bfa_ioc_s *ioc);
-	void            (*ioc_firmware_unlock)  (struct bfa_ioc_s *ioc);
-	void		(*ioc_reg_init) (struct bfa_ioc_s *ioc);
-	void		(*ioc_map_port) (struct bfa_ioc_s *ioc);
-	void		(*ioc_isr_mode_set)     (struct bfa_ioc_s *ioc,
-						bfa_boolean_t msix);
-	void            (*ioc_notify_hbfail)    (struct bfa_ioc_s *ioc);
-	void            (*ioc_ownership_reset)  (struct bfa_ioc_s *ioc);
+	bfa_status_t (*ioc_pll_init) (bfa_os_addr_t rb, bfa_boolean_t fcmode);
+	bfa_boolean_t	(*ioc_firmware_lock)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_firmware_unlock)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_reg_init)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_map_port)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_isr_mode_set)	(struct bfa_ioc_s *ioc,
+					bfa_boolean_t msix);
+	void		(*ioc_notify_hbfail)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_ownership_reset)	(struct bfa_ioc_s *ioc);
 };
 
 #define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)
@@ -206,18 +272,19 @@
 #define bfa_ioc_rx_bbcredit(__ioc)	((__ioc)->attr->rx_bbcredit)
 #define bfa_ioc_speed_sup(__ioc)	\
 	BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
-#define bfa_ioc_get_nports(__ioc)       \
+#define bfa_ioc_get_nports(__ioc)	\
 	BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)
 
-#define bfa_ioc_stats(_ioc, _stats)     ((_ioc)->stats._stats++)
-#define BFA_IOC_FWIMG_MINSZ     (16 * 1024)
-#define BFA_IOC_FWIMG_TYPE(__ioc)                                       \
-	(((__ioc)->ctdev) ?                                             \
-	 (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) :     \
+#define bfa_ioc_stats(_ioc, _stats)	((_ioc)->stats._stats++)
+#define BFA_IOC_FWIMG_MINSZ	(16 * 1024)
+#define BFA_IOC_FWIMG_TYPE(__ioc)					\
+	(((__ioc)->ctdev) ?						\
+	 (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) :	\
 	 BFI_IMAGE_CB_FC)
-
-#define BFA_IOC_FLASH_CHUNK_NO(off)             (off / BFI_FLASH_CHUNK_SZ_WORDS)
-#define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off)      (off % BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_IOC_FW_SMEM_SIZE(__ioc)					\
+	(((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE)
+#define BFA_IOC_FLASH_CHUNK_NO(off)		(off / BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off)	(off % BFI_FLASH_CHUNK_SZ_WORDS)
 #define BFA_IOC_FLASH_CHUNK_ADDR(chunkno)  (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
 
 /**
@@ -235,18 +302,28 @@
 /**
  * IOC interfaces
  */
-#define bfa_ioc_pll_init(__ioc) ((__ioc)->ioc_hwif->ioc_pll_init(__ioc))
-#define bfa_ioc_isr_mode_set(__ioc, __msix)                     \
+
+#define bfa_ioc_pll_init_asic(__ioc) \
+	((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \
+			   (__ioc)->fcmode))
+
+bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc);
+bfa_status_t bfa_ioc_cb_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode);
+bfa_boolean_t bfa_ioc_ct_pll_init_complete(bfa_os_addr_t rb);
+bfa_status_t bfa_ioc_ct_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode);
+
+#define	bfa_ioc_isr_mode_set(__ioc, __msix)			\
 			((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix))
-#define bfa_ioc_ownership_reset(__ioc)                          \
+#define	bfa_ioc_ownership_reset(__ioc)				\
 			((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
 
+
 void bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc);
 void bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc);
+
 void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa,
-		struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod,
-		struct bfa_trc_mod_s *trcmod,
-		struct bfa_aen_s *aen, struct bfa_log_mod_s *logm);
+		struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod);
+void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
 void bfa_ioc_detach(struct bfa_ioc_s *ioc);
 void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
 		enum bfi_mclass mc);
@@ -256,21 +333,22 @@
 void bfa_ioc_disable(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc);
 
-void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param);
+void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type,
+		u32 boot_param);
 void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg);
 void bfa_ioc_error_isr(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_is_operational(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_is_initialized(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc);
-void bfa_ioc_cfg_complete(struct bfa_ioc_s *ioc);
 enum bfa_ioc_type_e bfa_ioc_get_type(struct bfa_ioc_s *ioc);
 void bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num);
 void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver);
 void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver);
 void bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model);
 void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc,
-	char *manufacturer);
+		char *manufacturer);
 void bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev);
 enum bfa_ioc_state bfa_ioc_get_state(struct bfa_ioc_s *ioc);
 
@@ -284,6 +362,8 @@
 void bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc);
 bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
 				 int *trclen);
+bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
+	u32 *offset, int *buflen);
 u32 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr);
 u32 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr);
 void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc);
@@ -297,7 +377,8 @@
 			struct bfi_ioc_image_hdr_s *fwhdr);
 bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc,
 			struct bfi_ioc_image_hdr_s *fwhdr);
-void bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event);
+bfa_status_t bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats);
+bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc);
 
 /*
  * bfa mfg wwn API functions
@@ -310,5 +391,68 @@
 mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc);
 u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc);
 
-#endif /* __BFA_IOC_H__ */
+/*
+ * F/W Image Size & Chunk
+ */
+extern u32 bfi_image_ct_fc_size;
+extern u32 bfi_image_ct_cna_size;
+extern u32 bfi_image_cb_fc_size;
+extern u32 *bfi_image_ct_fc;
+extern u32 *bfi_image_ct_cna;
+extern u32 *bfi_image_cb_fc;
 
+static inline u32 *
+bfi_image_ct_fc_get_chunk(u32 off)
+{	return (u32 *)(bfi_image_ct_fc + off); }
+
+static inline u32 *
+bfi_image_ct_cna_get_chunk(u32 off)
+{	return (u32 *)(bfi_image_ct_cna + off); }
+
+static inline u32 *
+bfi_image_cb_fc_get_chunk(u32 off)
+{	return (u32 *)(bfi_image_cb_fc + off); }
+
+static inline u32*
+bfa_cb_image_get_chunk(int type, u32 off)
+{
+	switch (type) {
+	case BFI_IMAGE_CT_FC:
+		return bfi_image_ct_fc_get_chunk(off);	break;
+	case BFI_IMAGE_CT_CNA:
+		return bfi_image_ct_cna_get_chunk(off);	break;
+	case BFI_IMAGE_CB_FC:
+		return bfi_image_cb_fc_get_chunk(off);	break;
+	default: return 0;
+	}
+}
+
+static inline u32
+bfa_cb_image_get_size(int type)
+{
+	switch (type) {
+	case BFI_IMAGE_CT_FC:
+		return bfi_image_ct_fc_size;	break;
+	case BFI_IMAGE_CT_CNA:
+		return bfi_image_ct_cna_size;	break;
+	case BFI_IMAGE_CB_FC:
+		return bfi_image_cb_fc_size;	break;
+	default: return 0;
+	}
+}
+
+/**
+ * CNA TRCMOD declaration
+ */
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+	BFA_TRC_CNA_PORT	= 1,
+	BFA_TRC_CNA_IOC		= 2,
+	BFA_TRC_CNA_IOC_CB	= 3,
+	BFA_TRC_CNA_IOC_CT	= 4,
+};
+
+#endif /* __BFA_IOC_H__ */
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c
index 324bdde..d7ac864 100644
--- a/drivers/scsi/bfa/bfa_ioc_cb.c
+++ b/drivers/scsi/bfa/bfa_ioc_cb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,22 +15,15 @@
  * General Public License for more details.
  */
 
-#include <bfa.h>
-#include <bfa_ioc.h>
-#include <bfa_fwimg_priv.h>
-#include <cna/bfa_cna_trcmod.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_cbreg.h>
-#include <log/bfa_log_hal.h>
-#include <defs/bfa_defs_pci.h>
+#include "bfa_ioc.h"
+#include "bfi_cbreg.h"
+#include "bfa_defs.h"
 
 BFA_TRC_FILE(CNA, IOC_CB);
 
 /*
  * forward declarations
  */
-static bfa_status_t bfa_ioc_cb_pll_init(struct bfa_ioc_s *ioc);
 static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc);
 static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc);
 static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc);
@@ -95,6 +88,7 @@
  * Host <-> LPU mailbox command/status registers
  */
 static struct { u32 hfn, lpu; } iocreg_mbcmd[] = {
+
 	{ HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT },
 	{ HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT }
 };
@@ -154,6 +148,7 @@
 /**
  * Initialize IOC to port mapping.
  */
+
 static void
 bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc)
 {
@@ -161,6 +156,7 @@
 	 * For crossbow, port id is same as pci function.
 	 */
 	ioc->port_id = bfa_ioc_pcifn(ioc);
+
 	bfa_trc(ioc, ioc->port_id);
 }
 
@@ -172,75 +168,6 @@
 {
 }
 
-static bfa_status_t
-bfa_ioc_cb_pll_init(struct bfa_ioc_s *ioc)
-{
-	bfa_os_addr_t	rb = ioc->pcidev.pci_bar_kva;
-	u32	pll_sclk, pll_fclk;
-
-	/*
-	 *  Hold semaphore so that nobody can access the chip during init.
-	 */
-	bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
-
-	pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN |
-			__APP_PLL_212_P0_1(3U) |
-			__APP_PLL_212_JITLMT0_1(3U) |
-			__APP_PLL_212_CNTLMT0_1(3U);
-	pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN |
-			__APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) |
-			__APP_PLL_400_JITLMT0_1(3U) |
-			__APP_PLL_400_CNTLMT0_1(3U);
-
-	bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
-	bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
-
-	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
-
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
-			__APP_PLL_212_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
-			__APP_PLL_212_BYPASS |
-			__APP_PLL_212_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
-			__APP_PLL_400_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
-			__APP_PLL_400_BYPASS |
-			__APP_PLL_400_LOGIC_SOFT_RESET);
-	bfa_os_udelay(2);
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
-			__APP_PLL_212_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
-			__APP_PLL_400_LOGIC_SOFT_RESET);
-
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
-			pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
-			pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET);
-
-	/**
-	 * Wait for PLLs to lock.
-	 */
-	bfa_os_udelay(2000);
-	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
-
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk);
-
-	/*
-	 *  release semaphore.
-	 */
-	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
-
-	return BFA_STATUS_OK;
-}
-
 /**
  * Cleanup hw semaphore and usecnt registers
  */
@@ -256,3 +183,54 @@
 	bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
 	bfa_ioc_hw_sem_release(ioc);
 }
+
+
+
+bfa_status_t
+bfa_ioc_cb_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode)
+{
+	u32	pll_sclk, pll_fclk;
+
+	pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN |
+		__APP_PLL_212_P0_1(3U) |
+		__APP_PLL_212_JITLMT0_1(3U) |
+		__APP_PLL_212_CNTLMT0_1(3U);
+	pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN |
+		__APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) |
+		__APP_PLL_400_JITLMT0_1(3U) |
+		__APP_PLL_400_CNTLMT0_1(3U);
+	bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
+	bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
+	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+	bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+			  __APP_PLL_212_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+			  __APP_PLL_212_BYPASS |
+			  __APP_PLL_212_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+			  __APP_PLL_400_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+			  __APP_PLL_400_BYPASS |
+			  __APP_PLL_400_LOGIC_SOFT_RESET);
+	bfa_os_udelay(2);
+	bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+			  __APP_PLL_212_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+			  __APP_PLL_400_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+			  pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+			  pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET);
+	bfa_os_udelay(2000);
+	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + APP_PLL_212_CTL_REG), pll_sclk);
+	bfa_reg_write((rb + APP_PLL_400_CTL_REG), pll_fclk);
+
+	return BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index 68f027d..f21b82c 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,22 +15,15 @@
  * General Public License for more details.
  */
 
-#include <bfa.h>
-#include <bfa_ioc.h>
-#include <bfa_fwimg_priv.h>
-#include <cna/bfa_cna_trcmod.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_ctreg.h>
-#include <log/bfa_log_hal.h>
-#include <defs/bfa_defs_pci.h>
+#include "bfa_ioc.h"
+#include "bfi_ctreg.h"
+#include "bfa_defs.h"
 
 BFA_TRC_FILE(CNA, IOC_CT);
 
 /*
  * forward declarations
  */
-static bfa_status_t bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc);
 static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc);
 static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc);
 static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc);
@@ -78,7 +71,8 @@
 	/**
 	 * If bios boot (flash based) -- do not increment usage count
 	 */
-	if (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < BFA_IOC_FWIMG_MINSZ)
+	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+						BFA_IOC_FWIMG_MINSZ)
 		return BFA_TRUE;
 
 	bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
@@ -136,7 +130,8 @@
 	/**
 	 * If bios boot (flash based) -- do not decrement usage count
 	 */
-	if (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < BFA_IOC_FWIMG_MINSZ)
+	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+						BFA_IOC_FWIMG_MINSZ)
 		return;
 
 	/**
@@ -308,111 +303,6 @@
 	bfa_reg_write(rb + FNC_PERS_REG, r32);
 }
 
-static bfa_status_t
-bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc)
-{
-	bfa_os_addr_t	rb = ioc->pcidev.pci_bar_kva;
-	u32	pll_sclk, pll_fclk, r32;
-
-	/*
-	 *  Hold semaphore so that nobody can access the chip during init.
-	 */
-	bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
-
-	pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
-		__APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
-		__APP_PLL_312_JITLMT0_1(3U) |
-		__APP_PLL_312_CNTLMT0_1(1U);
-	pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
-		__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
-		__APP_PLL_425_JITLMT0_1(3U) |
-		__APP_PLL_425_CNTLMT0_1(1U);
-
-	/**
-	 *	For catapult, choose operational mode FC/FCoE
-	 */
-	if (ioc->fcmode) {
-		bfa_reg_write((rb + OP_MODE), 0);
-		bfa_reg_write((rb + ETH_MAC_SER_REG),
-				__APP_EMS_CMLCKSEL |
-				__APP_EMS_REFCKBUFEN2 |
-				__APP_EMS_CHANNEL_SEL);
-	} else {
-		ioc->pllinit = BFA_TRUE;
-		bfa_reg_write((rb + OP_MODE), __GLOBAL_FCOE_MODE);
-		bfa_reg_write((rb + ETH_MAC_SER_REG),
-				 __APP_EMS_REFCKBUFEN1);
-	}
-
-	bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
-	bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
-
-	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
-
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk |
-		__APP_PLL_312_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk |
-		__APP_PLL_425_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk |
-		__APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk |
-		__APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE);
-
-	/**
-	 * Wait for PLLs to lock.
-	 */
-	bfa_reg_read(rb + HOSTFN0_INT_MSK);
-	bfa_os_udelay(2000);
-	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
-
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk |
-		__APP_PLL_312_ENABLE);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk |
-		__APP_PLL_425_ENABLE);
-
-	/**
-	 * PSS memory reset is asserted at power-on-reset. Need to clear
-	 * this before running EDRAM BISTR
-	 */
-	if (ioc->cna) {
-		bfa_reg_write((rb + PMM_1T_RESET_REG_P0), __PMM_1T_RESET_P);
-		bfa_reg_write((rb + PMM_1T_RESET_REG_P1), __PMM_1T_RESET_P);
-	}
-
-	r32 = bfa_reg_read((rb + PSS_CTL_REG));
-	r32 &= ~__PSS_LMEM_RESET;
-	bfa_reg_write((rb + PSS_CTL_REG), r32);
-	bfa_os_udelay(1000);
-
-	if (ioc->cna) {
-		bfa_reg_write((rb + PMM_1T_RESET_REG_P0), 0);
-		bfa_reg_write((rb + PMM_1T_RESET_REG_P1), 0);
-	}
-
-	bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START);
-	bfa_os_udelay(1000);
-	r32 = bfa_reg_read((rb + MBIST_STAT_REG));
-	bfa_trc(ioc, r32);
-
-	/**
-	 * Clear BISTR
-	 */
-	bfa_reg_write((rb + MBIST_CTL_REG), 0);
-
-	/*
-	 *  release semaphore.
-	 */
-	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
-
-	return BFA_STATUS_OK;
-}
-
 /**
  * Cleanup hw semaphore and usecnt registers
  */
@@ -434,3 +324,86 @@
 	bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
 	bfa_ioc_hw_sem_release(ioc);
 }
+
+
+
+/*
+ * Check the firmware state to know if pll_init has been completed already
+ */
+bfa_boolean_t
+bfa_ioc_ct_pll_init_complete(bfa_os_addr_t rb)
+{
+	if ((bfa_reg_read(rb + BFA_IOC0_STATE_REG) == BFI_IOC_OP) ||
+	  (bfa_reg_read(rb + BFA_IOC1_STATE_REG) == BFI_IOC_OP))
+		return BFA_TRUE;
+
+	return BFA_FALSE;
+}
+
+bfa_status_t
+bfa_ioc_ct_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode)
+{
+	u32	pll_sclk, pll_fclk, r32;
+
+	pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
+		__APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
+		__APP_PLL_312_JITLMT0_1(3U) |
+		__APP_PLL_312_CNTLMT0_1(1U);
+	pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
+		__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
+		__APP_PLL_425_JITLMT0_1(3U) |
+		__APP_PLL_425_CNTLMT0_1(1U);
+	if (fcmode) {
+		bfa_reg_write((rb + OP_MODE), 0);
+		bfa_reg_write((rb + ETH_MAC_SER_REG),
+				__APP_EMS_CMLCKSEL |
+				__APP_EMS_REFCKBUFEN2 |
+				__APP_EMS_CHANNEL_SEL);
+	} else {
+		bfa_reg_write((rb + OP_MODE), __GLOBAL_FCOE_MODE);
+		bfa_reg_write((rb + ETH_MAC_SER_REG),
+				__APP_EMS_REFCKBUFEN1);
+	}
+	bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
+	bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
+	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+	bfa_reg_write(rb + APP_PLL_312_CTL_REG, pll_sclk |
+		__APP_PLL_312_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_425_CTL_REG, pll_fclk |
+		__APP_PLL_425_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_312_CTL_REG, pll_sclk |
+		__APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE);
+	bfa_reg_write(rb + APP_PLL_425_CTL_REG, pll_fclk |
+		__APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE);
+	bfa_reg_read(rb + HOSTFN0_INT_MSK);
+	bfa_os_udelay(2000);
+	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+	bfa_reg_write(rb + APP_PLL_312_CTL_REG, pll_sclk |
+		__APP_PLL_312_ENABLE);
+	bfa_reg_write(rb + APP_PLL_425_CTL_REG, pll_fclk |
+		__APP_PLL_425_ENABLE);
+	if (!fcmode) {
+		bfa_reg_write((rb + PMM_1T_RESET_REG_P0), __PMM_1T_RESET_P);
+		bfa_reg_write((rb + PMM_1T_RESET_REG_P1), __PMM_1T_RESET_P);
+	}
+	r32 = bfa_reg_read((rb + PSS_CTL_REG));
+	r32 &= ~__PSS_LMEM_RESET;
+	bfa_reg_write((rb + PSS_CTL_REG), r32);
+	bfa_os_udelay(1000);
+	if (!fcmode) {
+		bfa_reg_write((rb + PMM_1T_RESET_REG_P0), 0);
+		bfa_reg_write((rb + PMM_1T_RESET_REG_P1), 0);
+	}
+
+	bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START);
+	bfa_os_udelay(1000);
+	r32 = bfa_reg_read((rb + MBIST_STAT_REG));
+	bfa_reg_write((rb + MBIST_CTL_REG), 0);
+	return BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c
deleted file mode 100644
index 90820be..0000000
--- a/drivers/scsi/bfa/bfa_iocfc.c
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <cs/bfa_debug.h>
-#include <bfa_priv.h>
-#include <log/bfa_log_hal.h>
-#include <bfi/bfi_boot.h>
-#include <bfi/bfi_cbreg.h>
-#include <aen/bfa_aen_ioc.h>
-#include <defs/bfa_defs_iocfc.h>
-#include <defs/bfa_defs_pci.h>
-#include "bfa_callback_priv.h"
-#include "bfad_drv.h"
-
-BFA_TRC_FILE(HAL, IOCFC);
-
-/**
- * IOC local definitions
- */
-#define BFA_IOCFC_TOV		5000	/* msecs */
-
-enum {
-	BFA_IOCFC_ACT_NONE	= 0,
-	BFA_IOCFC_ACT_INIT	= 1,
-	BFA_IOCFC_ACT_STOP	= 2,
-	BFA_IOCFC_ACT_DISABLE	= 3,
-};
-
-/*
- * forward declarations
- */
-static void bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status);
-static void bfa_iocfc_disable_cbfn(void *bfa_arg);
-static void bfa_iocfc_hbfail_cbfn(void *bfa_arg);
-static void bfa_iocfc_reset_cbfn(void *bfa_arg);
-static void bfa_iocfc_stats_clear(void *bfa_arg);
-static void bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d,
-			struct bfa_fw_stats_s *s);
-static void bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete);
-static void bfa_iocfc_stats_clr_timeout(void *bfa_arg);
-static void bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete);
-static void bfa_iocfc_stats_timeout(void *bfa_arg);
-
-static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn;
-
-/**
- *  bfa_ioc_pvt BFA IOC private functions
- */
-
-static void
-bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
-	int             i, per_reqq_sz, per_rspq_sz;
-
-	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
-							BFA_DMA_ALIGN_SZ);
-	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
-							BFA_DMA_ALIGN_SZ);
-
-	/*
-	 * Calculate CQ size
-	 */
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-		*dm_len = *dm_len + per_reqq_sz;
-		*dm_len = *dm_len + per_rspq_sz;
-	}
-
-	/*
-	 * Calculate Shadow CI/PI size
-	 */
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++)
-		*dm_len += (2 * BFA_CACHELINE_SZ);
-}
-
-static void
-bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
-	*dm_len +=
-		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
-	*dm_len +=
-		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-			    BFA_CACHELINE_SZ);
-	*dm_len += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
-}
-
-/**
- * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ
- */
-static void
-bfa_iocfc_send_cfg(void *bfa_arg)
-{
-	struct bfa_s *bfa = bfa_arg;
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfg_req_s cfg_req;
-	struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo;
-	struct bfa_iocfc_cfg_s  *cfg = &iocfc->cfg;
-	int             i;
-
-	bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS);
-	bfa_trc(bfa, cfg->fwcfg.num_cqs);
-
-	bfa_iocfc_reset_queues(bfa);
-
-	/**
-	 * initialize IOC configuration info
-	 */
-	cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
-	cfg_info->num_cqs = cfg->fwcfg.num_cqs;
-
-	bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
-	bfa_dma_be_addr_set(cfg_info->stats_addr, iocfc->stats_pa);
-
-	/**
-	 * dma map REQ and RSP circular queues and shadow pointers
-	 */
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-		bfa_dma_be_addr_set(cfg_info->req_cq_ba[i],
-				       iocfc->req_cq_ba[i].pa);
-		bfa_dma_be_addr_set(cfg_info->req_shadow_ci[i],
-				       iocfc->req_cq_shadow_ci[i].pa);
-		cfg_info->req_cq_elems[i] =
-			bfa_os_htons(cfg->drvcfg.num_reqq_elems);
-
-		bfa_dma_be_addr_set(cfg_info->rsp_cq_ba[i],
-				       iocfc->rsp_cq_ba[i].pa);
-		bfa_dma_be_addr_set(cfg_info->rsp_shadow_pi[i],
-				       iocfc->rsp_cq_shadow_pi[i].pa);
-		cfg_info->rsp_cq_elems[i] =
-			bfa_os_htons(cfg->drvcfg.num_rspq_elems);
-	}
-
-	/**
-	 * Enable interrupt coalescing if it is driver init path
-	 * and not ioc disable/enable path.
-	 */
-	if (!iocfc->cfgdone)
-		cfg_info->intr_attr.coalesce = BFA_TRUE;
-
-	iocfc->cfgdone = BFA_FALSE;
-
-	/**
-	 * dma map IOC configuration itself
-	 */
-	bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ,
-			bfa_lpuid(bfa));
-	bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);
-
-	bfa_ioc_mbox_send(&bfa->ioc, &cfg_req,
-			sizeof(struct bfi_iocfc_cfg_req_s));
-}
-
-static void
-bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		    struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	bfa->bfad = bfad;
-	iocfc->bfa = bfa;
-	iocfc->action = BFA_IOCFC_ACT_NONE;
-
-	bfa_os_assign(iocfc->cfg, *cfg);
-
-	/**
-	 * Initialize chip specific handlers.
-	 */
-	if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) {
-		iocfc->hwif.hw_reginit = bfa_hwct_reginit;
-		iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;
-		iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
-		iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
-		iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
-		iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;
-		iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
-		iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
-		iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range;
-	} else {
-		iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
-		iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack;
-		iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
-		iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
-		iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
-		iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;
-		iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
-		iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
-		iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range;
-	}
-
-	iocfc->hwif.hw_reginit(bfa);
-	bfa->msix.nvecs = 0;
-}
-
-static void
-bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
-		      struct bfa_meminfo_s *meminfo)
-{
-	u8        *dm_kva;
-	u64        dm_pa;
-	int             i, per_reqq_sz, per_rspq_sz;
-	struct bfa_iocfc_s  *iocfc = &bfa->iocfc;
-	int		dbgsz;
-
-	dm_kva = bfa_meminfo_dma_virt(meminfo);
-	dm_pa = bfa_meminfo_dma_phys(meminfo);
-
-	/*
-	 * First allocate dma memory for IOC.
-	 */
-	bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
-	dm_kva += bfa_ioc_meminfo();
-	dm_pa  += bfa_ioc_meminfo();
-
-	/*
-	 * Claim DMA-able memory for the request/response queues and for shadow
-	 * ci/pi registers
-	 */
-	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
-							BFA_DMA_ALIGN_SZ);
-	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
-							BFA_DMA_ALIGN_SZ);
-
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-		iocfc->req_cq_ba[i].kva = dm_kva;
-		iocfc->req_cq_ba[i].pa = dm_pa;
-		bfa_os_memset(dm_kva, 0, per_reqq_sz);
-		dm_kva += per_reqq_sz;
-		dm_pa += per_reqq_sz;
-
-		iocfc->rsp_cq_ba[i].kva = dm_kva;
-		iocfc->rsp_cq_ba[i].pa = dm_pa;
-		bfa_os_memset(dm_kva, 0, per_rspq_sz);
-		dm_kva += per_rspq_sz;
-		dm_pa += per_rspq_sz;
-	}
-
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-		iocfc->req_cq_shadow_ci[i].kva = dm_kva;
-		iocfc->req_cq_shadow_ci[i].pa = dm_pa;
-		dm_kva += BFA_CACHELINE_SZ;
-		dm_pa += BFA_CACHELINE_SZ;
-
-		iocfc->rsp_cq_shadow_pi[i].kva = dm_kva;
-		iocfc->rsp_cq_shadow_pi[i].pa = dm_pa;
-		dm_kva += BFA_CACHELINE_SZ;
-		dm_pa += BFA_CACHELINE_SZ;
-	}
-
-	/*
-	 * Claim DMA-able memory for the config info page
-	 */
-	bfa->iocfc.cfg_info.kva = dm_kva;
-	bfa->iocfc.cfg_info.pa = dm_pa;
-	bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;
-	dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
-	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
-
-	/*
-	 * Claim DMA-able memory for the config response
-	 */
-	bfa->iocfc.cfgrsp_dma.kva = dm_kva;
-	bfa->iocfc.cfgrsp_dma.pa = dm_pa;
-	bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva;
-
-	dm_kva +=
-		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-			    BFA_CACHELINE_SZ);
-	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-			     BFA_CACHELINE_SZ);
-
-	/*
-	 * Claim DMA-able memory for iocfc stats
-	 */
-	bfa->iocfc.stats_kva = dm_kva;
-	bfa->iocfc.stats_pa = dm_pa;
-	bfa->iocfc.fw_stats = (struct bfa_fw_stats_s *) dm_kva;
-	dm_kva += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
-	dm_pa += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
-
-	bfa_meminfo_dma_virt(meminfo) = dm_kva;
-	bfa_meminfo_dma_phys(meminfo) = dm_pa;
-
-	dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover);
-	if (dbgsz > 0) {
-		bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
-		bfa_meminfo_kva(meminfo) += dbgsz;
-	}
-}
-
-/**
- * Start BFA submodules.
- */
-static void
-bfa_iocfc_start_submod(struct bfa_s *bfa)
-{
-	int             i;
-
-	bfa->rme_process = BFA_TRUE;
-
-	for (i = 0; hal_mods[i]; i++)
-		hal_mods[i]->start(bfa);
-}
-
-/**
- * Disable BFA submodules.
- */
-static void
-bfa_iocfc_disable_submod(struct bfa_s *bfa)
-{
-	int             i;
-
-	for (i = 0; hal_mods[i]; i++)
-		hal_mods[i]->iocdisable(bfa);
-}
-
-static void
-bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete)
-{
-	struct bfa_s	*bfa = bfa_arg;
-
-	if (complete) {
-		if (bfa->iocfc.cfgdone)
-			bfa_cb_init(bfa->bfad, BFA_STATUS_OK);
-		else
-			bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED);
-	} else {
-		if (bfa->iocfc.cfgdone)
-			bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
-	}
-}
-
-static void
-bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
-{
-	struct bfa_s  *bfa = bfa_arg;
-	struct bfad_s *bfad = bfa->bfad;
-
-	if (compl)
-		complete(&bfad->comp);
-
-	else
-		bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
-}
-
-static void
-bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
-{
-	struct bfa_s  *bfa = bfa_arg;
-	struct bfad_s *bfad = bfa->bfad;
-
-	if (compl)
-		complete(&bfad->disable_comp);
-}
-
-/**
- * Update BFA configuration from firmware configuration.
- */
-static void
-bfa_iocfc_cfgrsp(struct bfa_s *bfa)
-{
-	struct bfa_iocfc_s		*iocfc	 = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s	*cfgrsp  = iocfc->cfgrsp;
-	struct bfa_iocfc_fwcfg_s	*fwcfg   = &cfgrsp->fwcfg;
-
-	fwcfg->num_cqs        = fwcfg->num_cqs;
-	fwcfg->num_ioim_reqs  = bfa_os_ntohs(fwcfg->num_ioim_reqs);
-	fwcfg->num_tskim_reqs = bfa_os_ntohs(fwcfg->num_tskim_reqs);
-	fwcfg->num_fcxp_reqs  = bfa_os_ntohs(fwcfg->num_fcxp_reqs);
-	fwcfg->num_uf_bufs    = bfa_os_ntohs(fwcfg->num_uf_bufs);
-	fwcfg->num_rports     = bfa_os_ntohs(fwcfg->num_rports);
-
-	iocfc->cfgdone = BFA_TRUE;
-
-	/**
-	 * Configuration is complete - initialize/start submodules
-	 */
-	bfa_fcport_init(bfa);
-
-	if (iocfc->action == BFA_IOCFC_ACT_INIT)
-		bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
-	else
-		bfa_iocfc_start_submod(bfa);
-}
-
-static void
-bfa_iocfc_stats_clear(void *bfa_arg)
-{
-	struct bfa_s		*bfa = bfa_arg;
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-	struct bfi_iocfc_stats_req_s stats_req;
-
-	bfa_timer_start(bfa, &iocfc->stats_timer,
-			    bfa_iocfc_stats_clr_timeout, bfa,
-			    BFA_IOCFC_TOV);
-
-	bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CLEAR_STATS_REQ,
-		bfa_lpuid(bfa));
-	bfa_ioc_mbox_send(&bfa->ioc, &stats_req,
-		sizeof(struct bfi_iocfc_stats_req_s));
-}
-
-static void
-bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d, struct bfa_fw_stats_s *s)
-{
-	u32       *dip = (u32 *) d;
-	u32       *sip = (u32 *) s;
-	int             i;
-
-	for (i = 0; i < (sizeof(struct bfa_fw_stats_s) / sizeof(u32)); i++)
-		dip[i] = bfa_os_ntohl(sip[i]);
-}
-
-static void
-bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete)
-{
-	struct bfa_s *bfa = bfa_arg;
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-
-	if (complete) {
-		bfa_ioc_clr_stats(&bfa->ioc);
-		iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status);
-	} else {
-		iocfc->stats_busy = BFA_FALSE;
-		iocfc->stats_status = BFA_STATUS_OK;
-	}
-}
-
-static void
-bfa_iocfc_stats_clr_timeout(void *bfa_arg)
-{
-	struct bfa_s		*bfa = bfa_arg;
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	bfa_trc(bfa, 0);
-
-	iocfc->stats_status = BFA_STATUS_ETIMER;
-	bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_clr_cb, bfa);
-}
-
-static void
-bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete)
-{
-	struct bfa_s		*bfa = bfa_arg;
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	if (complete) {
-		if (iocfc->stats_status == BFA_STATUS_OK) {
-			bfa_os_memset(iocfc->stats_ret, 0,
-				sizeof(*iocfc->stats_ret));
-			bfa_iocfc_stats_swap(&iocfc->stats_ret->fw_stats,
-				iocfc->fw_stats);
-		}
-		iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status);
-	} else {
-		iocfc->stats_busy = BFA_FALSE;
-		iocfc->stats_status = BFA_STATUS_OK;
-	}
-}
-
-static void
-bfa_iocfc_stats_timeout(void *bfa_arg)
-{
-	struct bfa_s		*bfa = bfa_arg;
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	bfa_trc(bfa, 0);
-
-	iocfc->stats_status = BFA_STATUS_ETIMER;
-	bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb, bfa);
-}
-
-static void
-bfa_iocfc_stats_query(struct bfa_s *bfa)
-{
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-	struct bfi_iocfc_stats_req_s stats_req;
-
-	bfa_timer_start(bfa, &iocfc->stats_timer,
-			    bfa_iocfc_stats_timeout, bfa, BFA_IOCFC_TOV);
-
-	bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_GET_STATS_REQ,
-			bfa_lpuid(bfa));
-	bfa_ioc_mbox_send(&bfa->ioc, &stats_req,
-		sizeof(struct bfi_iocfc_stats_req_s));
-}
-
-void
-bfa_iocfc_reset_queues(struct bfa_s *bfa)
-{
-	int             q;
-
-	for (q = 0; q < BFI_IOC_MAX_CQS; q++) {
-		bfa_reqq_ci(bfa, q) = 0;
-		bfa_reqq_pi(bfa, q) = 0;
-		bfa_rspq_ci(bfa, q) = 0;
-		bfa_rspq_pi(bfa, q) = 0;
-	}
-}
-
-/**
- * IOC enable request is complete
- */
-static void
-bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
-{
-	struct bfa_s	*bfa = bfa_arg;
-
-	if (status != BFA_STATUS_OK) {
-		bfa_isr_disable(bfa);
-		if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
-			bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
-				     bfa_iocfc_init_cb, bfa);
-		return;
-	}
-
-	bfa_iocfc_send_cfg(bfa);
-}
-
-/**
- * IOC disable request is complete
- */
-static void
-bfa_iocfc_disable_cbfn(void *bfa_arg)
-{
-	struct bfa_s	*bfa = bfa_arg;
-
-	bfa_isr_disable(bfa);
-	bfa_iocfc_disable_submod(bfa);
-
-	if (bfa->iocfc.action == BFA_IOCFC_ACT_STOP)
-		bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb,
-			     bfa);
-	else {
-		bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE);
-		bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb,
-			     bfa);
-	}
-}
-
-/**
- * Notify sub-modules of hardware failure.
- */
-static void
-bfa_iocfc_hbfail_cbfn(void *bfa_arg)
-{
-	struct bfa_s	*bfa = bfa_arg;
-
-	bfa->rme_process = BFA_FALSE;
-
-	bfa_isr_disable(bfa);
-	bfa_iocfc_disable_submod(bfa);
-
-	if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
-		bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, bfa_iocfc_init_cb,
-			     bfa);
-}
-
-/**
- * Actions on chip-reset completion.
- */
-static void
-bfa_iocfc_reset_cbfn(void *bfa_arg)
-{
-	struct bfa_s	*bfa = bfa_arg;
-
-	bfa_iocfc_reset_queues(bfa);
-	bfa_isr_enable(bfa);
-}
-
-
-
-/**
- *  bfa_ioc_public
- */
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
-{
-	/* dma memory for IOC */
-	*dm_len += bfa_ioc_meminfo();
-
-	bfa_iocfc_fw_cfg_sz(cfg, dm_len);
-	bfa_iocfc_cqs_sz(cfg, dm_len);
-	*km_len += bfa_ioc_debug_trcsz(bfa_auto_recover);
-}
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		   struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	int             i;
-
-	bfa_iocfc_cbfn.enable_cbfn = bfa_iocfc_enable_cbfn;
-	bfa_iocfc_cbfn.disable_cbfn = bfa_iocfc_disable_cbfn;
-	bfa_iocfc_cbfn.hbfail_cbfn = bfa_iocfc_hbfail_cbfn;
-	bfa_iocfc_cbfn.reset_cbfn = bfa_iocfc_reset_cbfn;
-
-	bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod,
-		bfa->trcmod, bfa->aen, bfa->logm);
-
-	/**
-	 * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC.
-	 */
-	if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC)
-		bfa_ioc_set_fcmode(&bfa->ioc);
-
-	bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC);
-	bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
-
-	bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
-	bfa_iocfc_mem_claim(bfa, cfg, meminfo);
-	bfa_timer_init(&bfa->timer_mod);
-
-	INIT_LIST_HEAD(&bfa->comp_q);
-	for (i = 0; i < BFI_IOC_MAX_CQS; i++)
-		INIT_LIST_HEAD(&bfa->reqq_waitq[i]);
-}
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_detach(struct bfa_s *bfa)
-{
-	bfa_ioc_detach(&bfa->ioc);
-}
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_init(struct bfa_s *bfa)
-{
-	bfa->iocfc.action = BFA_IOCFC_ACT_INIT;
-	bfa_ioc_enable(&bfa->ioc);
-}
-
-/**
- * IOC start called from bfa_start(). Called to start IOC operations
- * at driver instantiation for this instance.
- */
-void
-bfa_iocfc_start(struct bfa_s *bfa)
-{
-	if (bfa->iocfc.cfgdone)
-		bfa_iocfc_start_submod(bfa);
-}
-
-/**
- * IOC stop called from bfa_stop(). Called only when driver is unloaded
- * for this instance.
- */
-void
-bfa_iocfc_stop(struct bfa_s *bfa)
-{
-	bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
-
-	bfa->rme_process = BFA_FALSE;
-	bfa_ioc_disable(&bfa->ioc);
-}
-
-void
-bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
-{
-	struct bfa_s		*bfa = bfaarg;
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-	union bfi_iocfc_i2h_msg_u	*msg;
-
-	msg = (union bfi_iocfc_i2h_msg_u *) m;
-	bfa_trc(bfa, msg->mh.msg_id);
-
-	switch (msg->mh.msg_id) {
-	case BFI_IOCFC_I2H_CFG_REPLY:
-		iocfc->cfg_reply = &msg->cfg_reply;
-		bfa_iocfc_cfgrsp(bfa);
-		break;
-
-	case BFI_IOCFC_I2H_GET_STATS_RSP:
-		if (iocfc->stats_busy == BFA_FALSE
-		    || iocfc->stats_status == BFA_STATUS_ETIMER)
-			break;
-
-		bfa_timer_stop(&iocfc->stats_timer);
-		iocfc->stats_status = BFA_STATUS_OK;
-		bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb,
-			      bfa);
-		break;
-	case BFI_IOCFC_I2H_CLEAR_STATS_RSP:
-		/*
-		 * check for timer pop before processing the rsp
-		 */
-		if (iocfc->stats_busy == BFA_FALSE
-		    || iocfc->stats_status == BFA_STATUS_ETIMER)
-			break;
-
-		bfa_timer_stop(&iocfc->stats_timer);
-		iocfc->stats_status = BFA_STATUS_OK;
-		bfa_cb_queue(bfa, &iocfc->stats_hcb_qe,
-			      bfa_iocfc_stats_clr_cb, bfa);
-		break;
-	case BFI_IOCFC_I2H_UPDATEQ_RSP:
-		iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
-		break;
-	default:
-		bfa_assert(0);
-	}
-}
-
-#ifndef BFA_BIOS_BUILD
-void
-bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr)
-{
-	bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr);
-}
-
-u64
-bfa_adapter_get_id(struct bfa_s *bfa)
-{
-	return bfa_ioc_get_adid(&bfa->ioc);
-}
-
-void
-bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr)
-{
-	struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
-
-	attr->intr_attr.coalesce = iocfc->cfginfo->intr_attr.coalesce;
-
-	attr->intr_attr.delay = iocfc->cfginfo->intr_attr.delay ?
-			bfa_os_ntohs(iocfc->cfginfo->intr_attr.delay) :
-			bfa_os_ntohs(iocfc->cfgrsp->intr_attr.delay);
-
-	attr->intr_attr.latency = iocfc->cfginfo->intr_attr.latency ?
-			bfa_os_ntohs(iocfc->cfginfo->intr_attr.latency) :
-			bfa_os_ntohs(iocfc->cfgrsp->intr_attr.latency);
-
-	attr->config    = iocfc->cfg;
-
-}
-
-bfa_status_t
-bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
-{
-	struct bfa_iocfc_s		*iocfc = &bfa->iocfc;
-	struct bfi_iocfc_set_intr_req_s *m;
-
-	iocfc->cfginfo->intr_attr.coalesce = attr->coalesce;
-	iocfc->cfginfo->intr_attr.delay = bfa_os_htons(attr->delay);
-	iocfc->cfginfo->intr_attr.latency = bfa_os_htons(attr->latency);
-
-	if (!bfa_iocfc_is_operational(bfa))
-		return BFA_STATUS_OK;
-
-	m = bfa_reqq_next(bfa, BFA_REQQ_IOC);
-	if (!m)
-		return BFA_STATUS_DEVBUSY;
-
-	bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ,
-			bfa_lpuid(bfa));
-	m->coalesce = iocfc->cfginfo->intr_attr.coalesce;
-	m->delay    = iocfc->cfginfo->intr_attr.delay;
-	m->latency  = iocfc->cfginfo->intr_attr.latency;
-
-
-	bfa_trc(bfa, attr->delay);
-	bfa_trc(bfa, attr->latency);
-
-	bfa_reqq_produce(bfa, BFA_REQQ_IOC);
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
-{
-	struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
-
-	iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
-	bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
-}
-
-bfa_status_t
-bfa_iocfc_get_stats(struct bfa_s *bfa, struct bfa_iocfc_stats_s *stats,
-		      bfa_cb_ioc_t cbfn, void *cbarg)
-{
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	if (iocfc->stats_busy) {
-		bfa_trc(bfa, iocfc->stats_busy);
-		return BFA_STATUS_DEVBUSY;
-	}
-
-	if (!bfa_iocfc_is_operational(bfa)) {
-		bfa_trc(bfa, 0);
-		return BFA_STATUS_IOC_NON_OP;
-	}
-
-	iocfc->stats_busy = BFA_TRUE;
-	iocfc->stats_ret = stats;
-	iocfc->stats_cbfn = cbfn;
-	iocfc->stats_cbarg = cbarg;
-
-	bfa_iocfc_stats_query(bfa);
-
-	return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_iocfc_clear_stats(struct bfa_s *bfa, bfa_cb_ioc_t cbfn, void *cbarg)
-{
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	if (iocfc->stats_busy) {
-		bfa_trc(bfa, iocfc->stats_busy);
-		return BFA_STATUS_DEVBUSY;
-	}
-
-	if (!bfa_iocfc_is_operational(bfa)) {
-		bfa_trc(bfa, 0);
-		return BFA_STATUS_IOC_NON_OP;
-	}
-
-	iocfc->stats_busy = BFA_TRUE;
-	iocfc->stats_cbfn = cbfn;
-	iocfc->stats_cbarg = cbarg;
-
-	bfa_iocfc_stats_clear(bfa);
-	return BFA_STATUS_OK;
-}
-
-/**
- * Enable IOC after it is disabled.
- */
-void
-bfa_iocfc_enable(struct bfa_s *bfa)
-{
-	bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
-		     "IOC Enable");
-	bfa_ioc_enable(&bfa->ioc);
-}
-
-void
-bfa_iocfc_disable(struct bfa_s *bfa)
-{
-	bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
-		     "IOC Disable");
-	bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE;
-
-	bfa->rme_process = BFA_FALSE;
-	bfa_ioc_disable(&bfa->ioc);
-}
-
-
-bfa_boolean_t
-bfa_iocfc_is_operational(struct bfa_s *bfa)
-{
-	return bfa_ioc_is_operational(&bfa->ioc) && bfa->iocfc.cfgdone;
-}
-
-/**
- * Return boot target port wwns -- read from boot information in flash.
- */
-void
-bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns)
-{
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-	int i;
-
-	if (cfgrsp->pbc_cfg.boot_enabled && cfgrsp->pbc_cfg.nbluns) {
-		bfa_trc(bfa, cfgrsp->pbc_cfg.nbluns);
-		*nwwns = cfgrsp->pbc_cfg.nbluns;
-		for (i = 0; i < cfgrsp->pbc_cfg.nbluns; i++)
-			wwns[i] = cfgrsp->pbc_cfg.blun[i].tgt_pwwn;
-
-		return;
-	}
-
-	*nwwns = cfgrsp->bootwwns.nwwns;
-	memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(cfgrsp->bootwwns.wwn));
-}
-
-void
-bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg)
-{
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
-	pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled;
-	pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns;
-	pbcfg->speed = cfgrsp->pbc_cfg.port_speed;
-	memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun));
-}
-
-int
-bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
-{
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
-	memcpy(pbc_vport, cfgrsp->pbc_cfg.vport, sizeof(cfgrsp->pbc_cfg.vport));
-	return cfgrsp->pbc_cfg.nvports;
-}
-
-
-#endif
-
-
diff --git a/drivers/scsi/bfa/bfa_iocfc.h b/drivers/scsi/bfa/bfa_iocfc.h
deleted file mode 100644
index 74a6a04..0000000
--- a/drivers/scsi/bfa/bfa_iocfc.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_IOCFC_H__
-#define __BFA_IOCFC_H__
-
-#include <bfa_ioc.h>
-#include <bfa.h>
-#include <bfi/bfi_iocfc.h>
-#include <bfi/bfi_pbc.h>
-#include <bfa_callback_priv.h>
-
-#define BFA_REQQ_NELEMS_MIN	(4)
-#define BFA_RSPQ_NELEMS_MIN	(4)
-
-struct bfa_iocfc_regs_s {
-	bfa_os_addr_t   intr_status;
-	bfa_os_addr_t   intr_mask;
-	bfa_os_addr_t   cpe_q_pi[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   cpe_q_ci[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   cpe_q_depth[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   cpe_q_ctrl[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   rme_q_ci[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   rme_q_pi[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   rme_q_depth[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   rme_q_ctrl[BFI_IOC_MAX_CQS];
-};
-
-/**
- * MSIX vector handlers
- */
-#define BFA_MSIX_MAX_VECTORS	22
-typedef void (*bfa_msix_handler_t)(struct bfa_s *bfa, int vec);
-struct bfa_msix_s {
-	int	nvecs;
-	bfa_msix_handler_t handler[BFA_MSIX_MAX_VECTORS];
-};
-
-/**
- * Chip specific interfaces
- */
-struct bfa_hwif_s {
-	void (*hw_reginit)(struct bfa_s *bfa);
-	void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
-	void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
-	void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
-	void (*hw_msix_install)(struct bfa_s *bfa);
-	void (*hw_msix_uninstall)(struct bfa_s *bfa);
-	void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
-	void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
-			u32 *nvecs, u32 *maxvec);
-	void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,
-			u32 *end);
-};
-typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
-
-struct bfa_iocfc_s {
-	struct bfa_s 		*bfa;
-	struct bfa_iocfc_cfg_s 	cfg;
-	int			action;
-
-	u32        	req_cq_pi[BFI_IOC_MAX_CQS];
-	u32        	rsp_cq_ci[BFI_IOC_MAX_CQS];
-
-	struct bfa_cb_qe_s	init_hcb_qe;
-	struct bfa_cb_qe_s	stop_hcb_qe;
-	struct bfa_cb_qe_s	dis_hcb_qe;
-	struct bfa_cb_qe_s	stats_hcb_qe;
-	bfa_boolean_t		cfgdone;
-
-	struct bfa_dma_s	cfg_info;
-	struct bfi_iocfc_cfg_s *cfginfo;
-	struct bfa_dma_s	cfgrsp_dma;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp;
-	struct bfi_iocfc_cfg_reply_s *cfg_reply;
-
-	u8			*stats_kva;
-	u64		stats_pa;
-	struct bfa_fw_stats_s 	*fw_stats;
-	struct bfa_timer_s 	stats_timer;	/*  timer */
-	struct bfa_iocfc_stats_s *stats_ret;	/*  driver stats location */
-	bfa_status_t		stats_status;	/*  stats/statsclr status */
-	bfa_boolean_t   	stats_busy;	/*  outstanding stats */
-	bfa_cb_ioc_t		stats_cbfn;	/*  driver callback function */
-	void           		*stats_cbarg;	/*  user callback arg */
-
-	struct bfa_dma_s   	req_cq_ba[BFI_IOC_MAX_CQS];
-	struct bfa_dma_s   	req_cq_shadow_ci[BFI_IOC_MAX_CQS];
-	struct bfa_dma_s   	rsp_cq_ba[BFI_IOC_MAX_CQS];
-	struct bfa_dma_s   	rsp_cq_shadow_pi[BFI_IOC_MAX_CQS];
-	struct bfa_iocfc_regs_s	bfa_regs;	/*  BFA device registers */
-	struct bfa_hwif_s	hwif;
-
-	bfa_cb_iocfc_t		updateq_cbfn; /*  bios callback function */
-	void			*updateq_cbarg;	/*  bios callback arg */
-	u32			intr_mask;
-};
-
-#define bfa_lpuid(__bfa)		bfa_ioc_portid(&(__bfa)->ioc)
-#define bfa_msix_init(__bfa, __nvecs)	\
-	((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs))
-#define bfa_msix_install(__bfa)	\
-	((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
-#define bfa_msix_uninstall(__bfa)	\
-	((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
-#define bfa_isr_mode_set(__bfa, __msix)	\
-	((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
-#define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec)	\
-	((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap,	\
-		 __nvecs, __maxvec))
-#define bfa_msix_get_rme_range(__bfa, __start, __end)   \
-	((__bfa)->iocfc.hwif.hw_msix_get_rme_range(__bfa, __start, __end))
-
-/*
- * FC specific IOC functions.
- */
-void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len);
-void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
-		struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
-		struct bfa_pcidev_s *pcidev);
-void bfa_iocfc_detach(struct bfa_s *bfa);
-void bfa_iocfc_init(struct bfa_s *bfa);
-void bfa_iocfc_start(struct bfa_s *bfa);
-void bfa_iocfc_stop(struct bfa_s *bfa);
-void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
-void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
-bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
-void bfa_iocfc_reset_queues(struct bfa_s *bfa);
-void bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba,
-			u32 reqq_sci, u32 rspq_spi,
-			bfa_cb_iocfc_t cbfn, void *cbarg);
-
-void bfa_msix_all(struct bfa_s *bfa, int vec);
-void bfa_msix_reqq(struct bfa_s *bfa, int vec);
-void bfa_msix_rspq(struct bfa_s *bfa, int vec);
-void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
-
-void bfa_hwcb_reginit(struct bfa_s *bfa);
-void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwcb_msix_install(struct bfa_s *bfa);
-void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
-void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
-void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap,
-			u32 *nvecs, u32 *maxvec);
-void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end);
-void bfa_hwct_reginit(struct bfa_s *bfa);
-void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwct_msix_install(struct bfa_s *bfa);
-void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
-void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
-void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap,
-			u32 *nvecs, u32 *maxvec);
-void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end);
-
-void bfa_com_meminfo(bfa_boolean_t mincfg, u32 *dm_len);
-void bfa_com_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi,
-		bfa_boolean_t mincfg);
-void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns);
-void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa,
-		struct bfa_boot_pbc_s *pbcfg);
-int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,
-		struct bfi_pbc_vport_s *pbc_vport);
-
-#endif /* __BFA_IOCFC_H__ */
-
diff --git a/drivers/scsi/bfa/bfa_iocfc_q.c b/drivers/scsi/bfa/bfa_iocfc_q.c
deleted file mode 100644
index 500a17d..0000000
--- a/drivers/scsi/bfa/bfa_iocfc_q.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include "bfa_intr_priv.h"
-
-BFA_TRC_FILE(HAL, IOCFC_Q);
-
-void
-bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba,
-				u32 reqq_sci, u32 rspq_spi, bfa_cb_iocfc_t cbfn,
-				void *cbarg)
-{
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_updateq_req_s updateq_req;
-
-	iocfc->updateq_cbfn = cbfn;
-	iocfc->updateq_cbarg = cbarg;
-
-	bfi_h2i_set(updateq_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_UPDATEQ_REQ,
-			bfa_lpuid(bfa));
-
-	updateq_req.reqq_ba = bfa_os_htonl(reqq_ba);
-	updateq_req.rspq_ba = bfa_os_htonl(rspq_ba);
-	updateq_req.reqq_sci = bfa_os_htonl(reqq_sci);
-	updateq_req.rspq_spi = bfa_os_htonl(rspq_spi);
-
-	bfa_ioc_mbox_send(&bfa->ioc, &updateq_req,
-			sizeof(struct bfi_iocfc_updateq_req_s));
-}
diff --git a/drivers/scsi/bfa/bfa_ioim.c b/drivers/scsi/bfa/bfa_ioim.c
deleted file mode 100644
index bdfdc19..0000000
--- a/drivers/scsi/bfa/bfa_ioim.c
+++ /dev/null
@@ -1,1364 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <cs/bfa_debug.h>
-#include <bfa_cb_ioim_macros.h>
-
-BFA_TRC_FILE(HAL, IOIM);
-
-/*
- * forward declarations.
- */
-static bfa_boolean_t	bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
-static bfa_boolean_t	bfa_ioim_sge_setup(struct bfa_ioim_s *ioim);
-static void		bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim);
-static bfa_boolean_t	bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
-static void		bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
-static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
-
-/**
- *  bfa_ioim_sm
- */
-
-/**
- * IO state machine events
- */
-enum bfa_ioim_event {
-	BFA_IOIM_SM_START = 1,		/*  io start request from host */
-	BFA_IOIM_SM_COMP_GOOD = 2,	/*  io good comp, resource free */
-	BFA_IOIM_SM_COMP = 3,		/*  io comp, resource is free */
-	BFA_IOIM_SM_COMP_UTAG = 4,	/*  io comp, resource is free */
-	BFA_IOIM_SM_DONE = 5,		/*  io comp, resource not free */
-	BFA_IOIM_SM_FREE = 6,		/*  io resource is freed */
-	BFA_IOIM_SM_ABORT = 7,		/*  abort request from scsi stack */
-	BFA_IOIM_SM_ABORT_COMP = 8,	/*  abort from f/w */
-	BFA_IOIM_SM_ABORT_DONE = 9,	/*  abort completion from f/w */
-	BFA_IOIM_SM_QRESUME = 10,	/*  CQ space available to queue IO */
-	BFA_IOIM_SM_SGALLOCED = 11,	/*  SG page allocation successful */
-	BFA_IOIM_SM_SQRETRY = 12,	/*  sequence recovery retry */
-	BFA_IOIM_SM_HCB	= 13,		/*  bfa callback complete */
-	BFA_IOIM_SM_CLEANUP = 14,	/*  IO cleanup from itnim */
-	BFA_IOIM_SM_TMSTART = 15,	/*  IO cleanup from tskim */
-	BFA_IOIM_SM_TMDONE = 16,	/*  IO cleanup from tskim */
-	BFA_IOIM_SM_HWFAIL = 17,	/*  IOC h/w failure event */
-	BFA_IOIM_SM_IOTOV = 18,		/*  ITN offline TOV       */
-};
-
-/*
- * forward declaration of IO state machine
- */
-static void     bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim,
-				       enum bfa_ioim_event event);
-static void     bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim,
-					enum bfa_ioim_event event);
-static void     bfa_ioim_sm_active(struct bfa_ioim_s *ioim,
-				       enum bfa_ioim_event event);
-static void     bfa_ioim_sm_abort(struct bfa_ioim_s *ioim,
-				      enum bfa_ioim_event event);
-static void     bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim,
-					enum bfa_ioim_event event);
-static void     bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim,
-				      enum bfa_ioim_event event);
-static void     bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim,
-					    enum bfa_ioim_event event);
-static void     bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim,
-					      enum bfa_ioim_event event);
-static void     bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim,
-				    enum bfa_ioim_event event);
-static void     bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim,
-					 enum bfa_ioim_event event);
-static void     bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,
-					enum bfa_ioim_event event);
-
-/**
- * 		IO is not started (unallocated).
- */
-static void
-bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_trc_fp(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_START:
-		if (!bfa_itnim_is_online(ioim->itnim)) {
-			if (!bfa_itnim_hold_io(ioim->itnim)) {
-				bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-				list_del(&ioim->qe);
-				list_add_tail(&ioim->qe,
-						&ioim->fcpim->ioim_comp_q);
-				bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
-						__bfa_cb_ioim_pathtov, ioim);
-			} else {
-				list_del(&ioim->qe);
-				list_add_tail(&ioim->qe,
-						&ioim->itnim->pending_q);
-			}
-			break;
-		}
-
-		if (ioim->nsges > BFI_SGE_INLINE) {
-			if (!bfa_ioim_sge_setup(ioim)) {
-				bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);
-				return;
-			}
-		}
-
-		if (!bfa_ioim_send_ioreq(ioim)) {
-			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
-			break;
-		}
-
-		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
-		break;
-
-	case BFA_IOIM_SM_IOTOV:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
-				__bfa_cb_ioim_pathtov, ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		/**
-		 * IO in pending queue can get abort requests. Complete abort
-		 * requests immediately.
-		 */
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-				ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		IO is waiting for SG pages.
- */
-static void
-bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_SGALLOCED:
-		if (!bfa_ioim_send_ioreq(ioim)) {
-			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
-			break;
-		}
-		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		IO is active.
- */
-static void
-bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_trc_fp(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_COMP_GOOD:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
-			      __bfa_cb_ioim_good_comp, ioim);
-		break;
-
-	case BFA_IOIM_SM_COMP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_DONE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		ioim->iosp->abort_explicit = BFA_TRUE;
-		ioim->io_cbfn = __bfa_cb_ioim_abort;
-
-		if (bfa_ioim_send_abort(ioim))
-			bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
-		else {
-			bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull);
-			bfa_reqq_wait(ioim->bfa, ioim->reqq,
-					&ioim->iosp->reqq_wait);
-		}
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		ioim->iosp->abort_explicit = BFA_FALSE;
-		ioim->io_cbfn = __bfa_cb_ioim_failed;
-
-		if (bfa_ioim_send_abort(ioim))
-			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
-		else {
-			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
-			bfa_reqq_wait(ioim->bfa, ioim->reqq,
-					&ioim->iosp->reqq_wait);
-		}
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		IO is being aborted, waiting for completion from firmware.
- */
-static void
-bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_COMP_GOOD:
-	case BFA_IOIM_SM_COMP:
-	case BFA_IOIM_SM_DONE:
-	case BFA_IOIM_SM_FREE:
-		break;
-
-	case BFA_IOIM_SM_ABORT_DONE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT_COMP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_COMP_UTAG:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
-		ioim->iosp->abort_explicit = BFA_FALSE;
-
-		if (bfa_ioim_send_abort(ioim))
-			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
-		else {
-			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
-			bfa_reqq_wait(ioim->bfa, ioim->reqq,
-					  &ioim->iosp->reqq_wait);
-		}
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * IO is being cleaned up (implicit abort), waiting for completion from
- * firmware.
- */
-static void
-bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_COMP_GOOD:
-	case BFA_IOIM_SM_COMP:
-	case BFA_IOIM_SM_DONE:
-	case BFA_IOIM_SM_FREE:
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		/**
-		 * IO is already being aborted implicitly
-		 */
-		ioim->io_cbfn = __bfa_cb_ioim_abort;
-		break;
-
-	case BFA_IOIM_SM_ABORT_DONE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT_COMP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_COMP_UTAG:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		/**
-		 * IO can be in cleanup state already due to TM command. 2nd cleanup
-		 * request comes from ITN offline event.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		IO is waiting for room in request CQ
- */
-static void
-bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_QRESUME:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
-		bfa_ioim_send_ioreq(ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		Active IO is being aborted, waiting for room in request CQ.
- */
-static void
-bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_QRESUME:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
-		bfa_ioim_send_abort(ioim);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
-		ioim->iosp->abort_explicit = BFA_FALSE;
-		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
-		break;
-
-	case BFA_IOIM_SM_COMP_GOOD:
-	case BFA_IOIM_SM_COMP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_DONE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		Active IO is being cleaned up, waiting for room in request CQ.
- */
-static void
-bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_QRESUME:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
-		bfa_ioim_send_abort(ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		/**
-		 * IO is already being cleaned up implicitly
-		 */
-		ioim->io_cbfn = __bfa_cb_ioim_abort;
-		break;
-
-	case BFA_IOIM_SM_COMP_GOOD:
-	case BFA_IOIM_SM_COMP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_DONE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * IO bfa callback is pending.
- */
-static void
-bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_trc_fp(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_HCB:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
-		bfa_ioim_free(ioim);
-		bfa_cb_ioim_resfree(ioim->bfa->bfad);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * IO bfa callback is pending. IO resource cannot be freed.
- */
-static void
-bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_HCB:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_resfree);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_resfree_q);
-		break;
-
-	case BFA_IOIM_SM_FREE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * IO is completed, waiting resource free from firmware.
- */
-static void
-bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_FREE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
-		bfa_ioim_free(ioim);
-		bfa_cb_ioim_resfree(ioim->bfa->bfad);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-
-
-/**
- *  bfa_ioim_private
- */
-
-static void
-__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-		return;
-	}
-
-	bfa_cb_ioim_good_comp(ioim->bfa->bfad, ioim->dio);
-}
-
-static void
-__bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_ioim_s	*ioim = cbarg;
-	struct bfi_ioim_rsp_s *m;
-	u8		*snsinfo = NULL;
-	u8         sns_len = 0;
-	s32         residue = 0;
-
-	if (!complete) {
-		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-		return;
-	}
-
-	m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
-	if (m->io_status == BFI_IOIM_STS_OK) {
-		/**
-		 * setup sense information, if present
-		 */
-		if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION
-					&& m->sns_len) {
-			sns_len = m->sns_len;
-			snsinfo = ioim->iosp->snsinfo;
-		}
-
-		/**
-		 * setup residue value correctly for normal completions
-		 */
-		if (m->resid_flags == FCP_RESID_UNDER)
-			residue = bfa_os_ntohl(m->residue);
-		if (m->resid_flags == FCP_RESID_OVER) {
-			residue = bfa_os_ntohl(m->residue);
-			residue = -residue;
-		}
-	}
-
-	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, m->io_status,
-			  m->scsi_status, sns_len, snsinfo, residue);
-}
-
-static void
-__bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-		return;
-	}
-
-	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
-			  0, 0, NULL, 0);
-}
-
-static void
-__bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-		return;
-	}
-
-	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
-			  0, 0, NULL, 0);
-}
-
-static void
-__bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-		return;
-	}
-
-	bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
-}
-
-static void
-bfa_ioim_sgpg_alloced(void *cbarg)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
-	list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);
-	bfa_ioim_sgpg_setup(ioim);
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);
-}
-
-/**
- * Send I/O request to firmware.
- */
-static          bfa_boolean_t
-bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
-{
-	struct bfa_itnim_s *itnim = ioim->itnim;
-	struct bfi_ioim_req_s *m;
-	static struct fcp_cmnd_s cmnd_z0 = { 0 };
-	struct bfi_sge_s      *sge;
-	u32        pgdlen = 0;
-	u64 addr;
-	struct scatterlist *sg;
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
-	if (!m) {
-		bfa_reqq_wait(ioim->bfa, ioim->reqq,
-				  &ioim->iosp->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	/**
-	 * build i/o request message next
-	 */
-	m->io_tag = bfa_os_htons(ioim->iotag);
-	m->rport_hdl = ioim->itnim->rport->fw_handle;
-	m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio);
-
-	/**
-	 * build inline IO SG element here
-	 */
-	sge = &m->sges[0];
-	if (ioim->nsges) {
-		sg = (struct scatterlist *)scsi_sglist(cmnd);
-		addr = bfa_os_sgaddr(sg_dma_address(sg));
-		sge->sga = *(union bfi_addr_u *) &addr;
-		pgdlen = sg_dma_len(sg);
-		sge->sg_len = pgdlen;
-		sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
-					BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
-		bfa_sge_to_be(sge);
-		sge++;
-	}
-
-	if (ioim->nsges > BFI_SGE_INLINE) {
-		sge->sga = ioim->sgpg->sgpg_pa;
-	} else {
-		sge->sga.a32.addr_lo = 0;
-		sge->sga.a32.addr_hi = 0;
-	}
-	sge->sg_len = pgdlen;
-	sge->flags = BFI_SGE_PGDLEN;
-	bfa_sge_to_be(sge);
-
-	/**
-	 * set up I/O command parameters
-	 */
-	bfa_os_assign(m->cmnd, cmnd_z0);
-	m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio);
-	m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio);
-	bfa_os_assign(m->cmnd.cdb,
-			*(struct scsi_cdb_s *)bfa_cb_ioim_get_cdb(ioim->dio));
-	m->cmnd.fcp_dl = bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
-
-	/**
-	 * set up I/O message header
-	 */
-	switch (m->cmnd.iodir) {
-	case FCP_IODIR_READ:
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa));
-		bfa_stats(itnim, input_reqs);
-		break;
-	case FCP_IODIR_WRITE:
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa));
-		bfa_stats(itnim, output_reqs);
-		break;
-	case FCP_IODIR_RW:
-		bfa_stats(itnim, input_reqs);
-		bfa_stats(itnim, output_reqs);
-	default:
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
-	}
-	if (itnim->seq_rec ||
-	    (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1)))
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
-
-#ifdef IOIM_ADVANCED
-	m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio);
-	m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio);
-	m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio);
-
-	/**
-	 * Handle large CDB (>16 bytes).
-	 */
-	m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) -
-					FCP_CMND_CDB_LEN) / sizeof(u32);
-	if (m->cmnd.addl_cdb_len) {
-		bfa_os_memcpy(&m->cmnd.cdb + 1, (struct scsi_cdb_s *)
-				bfa_cb_ioim_get_cdb(ioim->dio) + 1,
-				m->cmnd.addl_cdb_len * sizeof(u32));
-		fcp_cmnd_fcpdl(&m->cmnd) =
-				bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
-	}
-#endif
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(ioim->bfa, ioim->reqq);
-	return BFA_TRUE;
-}
-
-/**
- * Setup any additional SG pages needed.Inline SG element is setup
- * at queuing time.
- */
-static bfa_boolean_t
-bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)
-{
-	u16        nsgpgs;
-
-	bfa_assert(ioim->nsges > BFI_SGE_INLINE);
-
-	/**
-	 * allocate SG pages needed
-	 */
-	nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
-	if (!nsgpgs)
-		return BFA_TRUE;
-
-	if (bfa_sgpg_malloc(ioim->bfa, &ioim->sgpg_q, nsgpgs)
-	    != BFA_STATUS_OK) {
-		bfa_sgpg_wait(ioim->bfa, &ioim->iosp->sgpg_wqe, nsgpgs);
-		return BFA_FALSE;
-	}
-
-	ioim->nsgpgs = nsgpgs;
-	bfa_ioim_sgpg_setup(ioim);
-
-	return BFA_TRUE;
-}
-
-static void
-bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
-{
-	int             sgeid, nsges, i;
-	struct bfi_sge_s      *sge;
-	struct bfa_sgpg_s *sgpg;
-	u32        pgcumsz;
-	u64        addr;
-	struct scatterlist *sg;
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
-
-	sgeid = BFI_SGE_INLINE;
-	ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q);
-
-	sg = scsi_sglist(cmnd);
-	sg = sg_next(sg);
-
-	do {
-		sge = sgpg->sgpg->sges;
-		nsges = ioim->nsges - sgeid;
-		if (nsges > BFI_SGPG_DATA_SGES)
-			nsges = BFI_SGPG_DATA_SGES;
-
-		pgcumsz = 0;
-		for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) {
-			addr = bfa_os_sgaddr(sg_dma_address(sg));
-			sge->sga = *(union bfi_addr_u *) &addr;
-			sge->sg_len = sg_dma_len(sg);
-			pgcumsz += sge->sg_len;
-
-			/**
-			 * set flags
-			 */
-			if (i < (nsges - 1))
-				sge->flags = BFI_SGE_DATA;
-			else if (sgeid < (ioim->nsges - 1))
-				sge->flags = BFI_SGE_DATA_CPL;
-			else
-				sge->flags = BFI_SGE_DATA_LAST;
-		}
-
-		sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
-
-		/**
-		 * set the link element of each page
-		 */
-		if (sgeid == ioim->nsges) {
-			sge->flags = BFI_SGE_PGDLEN;
-			sge->sga.a32.addr_lo = 0;
-			sge->sga.a32.addr_hi = 0;
-		} else {
-			sge->flags = BFI_SGE_LINK;
-			sge->sga = sgpg->sgpg_pa;
-		}
-		sge->sg_len = pgcumsz;
-	} while (sgeid < ioim->nsges);
-}
-
-/**
- * Send I/O abort request to firmware.
- */
-static          bfa_boolean_t
-bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
-{
-	struct bfi_ioim_abort_req_s *m;
-	enum bfi_ioim_h2i       msgop;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
-	if (!m)
-		return BFA_FALSE;
-
-	/**
-	 * build i/o request message next
-	 */
-	if (ioim->iosp->abort_explicit)
-		msgop = BFI_IOIM_H2I_IOABORT_REQ;
-	else
-		msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
-
-	bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa));
-	m->io_tag    = bfa_os_htons(ioim->iotag);
-	m->abort_tag = ++ioim->abort_tag;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(ioim->bfa, ioim->reqq);
-	return BFA_TRUE;
-}
-
-/**
- * Call to resume any I/O requests waiting for room in request queue.
- */
-static void
-bfa_ioim_qresume(void *cbarg)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	bfa_fcpim_stats(ioim->fcpim, qresumes);
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_QRESUME);
-}
-
-
-static void
-bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)
-{
-	/**
-	 * Move IO from itnim queue to fcpim global queue since itnim will be
-	 * freed.
-	 */
-	list_del(&ioim->qe);
-	list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-
-	if (!ioim->iosp->tskim) {
-		if (ioim->fcpim->delay_comp && ioim->itnim->iotov_active) {
-			bfa_cb_dequeue(&ioim->hcb_qe);
-			list_del(&ioim->qe);
-			list_add_tail(&ioim->qe, &ioim->itnim->delay_comp_q);
-		}
-		bfa_itnim_iodone(ioim->itnim);
-	} else
-		bfa_tskim_iodone(ioim->iosp->tskim);
-}
-
-/**
- * 		  or after the link comes back.
- */
-void
-bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
-{
-	/**
-	 * If path tov timer expired, failback with PATHTOV status - these
-	 * IO requests are not normally retried by IO stack.
-	 *
-	 * Otherwise device cameback online and fail it with normal failed
-	 * status so that IO stack retries these failed IO requests.
-	 */
-	if (iotov)
-		ioim->io_cbfn = __bfa_cb_ioim_pathtov;
-	else
-		ioim->io_cbfn = __bfa_cb_ioim_failed;
-
-	bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-
-    /**
-     * Move IO to fcpim global queue since itnim will be
-     * freed.
-     */
-    list_del(&ioim->qe);
-    list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-}
-
-
-
-/**
- *  bfa_ioim_friend
- */
-
-/**
- * Memory allocation and initialization.
- */
-void
-bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
-{
-	struct bfa_ioim_s		*ioim;
-	struct bfa_ioim_sp_s	*iosp;
-	u16		i;
-	u8			*snsinfo;
-	u32		snsbufsz;
-
-	/**
-	 * claim memory first
-	 */
-	ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo);
-	fcpim->ioim_arr = ioim;
-	bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs);
-
-	iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo);
-	fcpim->ioim_sp_arr = iosp;
-	bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs);
-
-	/**
-	 * Claim DMA memory for per IO sense data.
-	 */
-	snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN;
-	fcpim->snsbase.pa  = bfa_meminfo_dma_phys(minfo);
-	bfa_meminfo_dma_phys(minfo) += snsbufsz;
-
-	fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo);
-	bfa_meminfo_dma_virt(minfo) += snsbufsz;
-	snsinfo = fcpim->snsbase.kva;
-	bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa);
-
-	/**
-	 * Initialize ioim free queues
-	 */
-	INIT_LIST_HEAD(&fcpim->ioim_free_q);
-	INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
-	INIT_LIST_HEAD(&fcpim->ioim_comp_q);
-
-	for (i = 0; i < fcpim->num_ioim_reqs;
-	     i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) {
-		/*
-		 * initialize IOIM
-		 */
-		bfa_os_memset(ioim, 0, sizeof(struct bfa_ioim_s));
-		ioim->iotag   = i;
-		ioim->bfa     = fcpim->bfa;
-		ioim->fcpim   = fcpim;
-		ioim->iosp    = iosp;
-		iosp->snsinfo = snsinfo;
-		INIT_LIST_HEAD(&ioim->sgpg_q);
-		bfa_reqq_winit(&ioim->iosp->reqq_wait,
-				   bfa_ioim_qresume, ioim);
-		bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
-				   bfa_ioim_sgpg_alloced, ioim);
-		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
-
-		list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
-	}
-}
-
-/**
- * Driver detach time call.
- */
-void
-bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim)
-{
-}
-
-void
-bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
-	struct bfa_ioim_s *ioim;
-	u16        iotag;
-	enum bfa_ioim_event evt = BFA_IOIM_SM_COMP;
-
-	iotag = bfa_os_ntohs(rsp->io_tag);
-
-	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
-	bfa_assert(ioim->iotag == iotag);
-
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, rsp->io_status);
-	bfa_trc(ioim->bfa, rsp->reuse_io_tag);
-
-	if (bfa_sm_cmp_state(ioim, bfa_ioim_sm_active))
-		bfa_os_assign(ioim->iosp->comp_rspmsg, *m);
-
-	switch (rsp->io_status) {
-	case BFI_IOIM_STS_OK:
-		bfa_fcpim_stats(fcpim, iocomp_ok);
-		if (rsp->reuse_io_tag == 0)
-			evt = BFA_IOIM_SM_DONE;
-		else
-			evt = BFA_IOIM_SM_COMP;
-		break;
-
-	case BFI_IOIM_STS_TIMEDOUT:
-	case BFI_IOIM_STS_ABORTED:
-		rsp->io_status = BFI_IOIM_STS_ABORTED;
-		bfa_fcpim_stats(fcpim, iocomp_aborted);
-		if (rsp->reuse_io_tag == 0)
-			evt = BFA_IOIM_SM_DONE;
-		else
-			evt = BFA_IOIM_SM_COMP;
-		break;
-
-	case BFI_IOIM_STS_PROTO_ERR:
-		bfa_fcpim_stats(fcpim, iocom_proto_err);
-		bfa_assert(rsp->reuse_io_tag);
-		evt = BFA_IOIM_SM_COMP;
-		break;
-
-	case BFI_IOIM_STS_SQER_NEEDED:
-		bfa_fcpim_stats(fcpim, iocom_sqer_needed);
-		bfa_assert(rsp->reuse_io_tag == 0);
-		evt = BFA_IOIM_SM_SQRETRY;
-		break;
-
-	case BFI_IOIM_STS_RES_FREE:
-		bfa_fcpim_stats(fcpim, iocom_res_free);
-		evt = BFA_IOIM_SM_FREE;
-		break;
-
-	case BFI_IOIM_STS_HOST_ABORTED:
-		bfa_fcpim_stats(fcpim, iocom_hostabrts);
-		if (rsp->abort_tag != ioim->abort_tag) {
-			bfa_trc(ioim->bfa, rsp->abort_tag);
-			bfa_trc(ioim->bfa, ioim->abort_tag);
-			return;
-		}
-
-		if (rsp->reuse_io_tag)
-			evt = BFA_IOIM_SM_ABORT_COMP;
-		else
-			evt = BFA_IOIM_SM_ABORT_DONE;
-		break;
-
-	case BFI_IOIM_STS_UTAG:
-		bfa_fcpim_stats(fcpim, iocom_utags);
-		evt = BFA_IOIM_SM_COMP_UTAG;
-		break;
-
-	default:
-		bfa_assert(0);
-	}
-
-	bfa_sm_send_event(ioim, evt);
-}
-
-void
-bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
-	struct bfa_ioim_s *ioim;
-	u16        iotag;
-
-	iotag = bfa_os_ntohs(rsp->io_tag);
-
-	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
-	bfa_assert(ioim->iotag == iotag);
-
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
-}
-
-/**
- * Called by itnim to clean up IO while going offline.
- */
-void
-bfa_ioim_cleanup(struct bfa_ioim_s *ioim)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_fcpim_stats(ioim->fcpim, io_cleanups);
-
-	ioim->iosp->tskim = NULL;
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
-}
-
-void
-bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, struct bfa_tskim_s *tskim)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_fcpim_stats(ioim->fcpim, io_tmaborts);
-
-	ioim->iosp->tskim = tskim;
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
-}
-
-/**
- * IOC failure handling.
- */
-void
-bfa_ioim_iocdisable(struct bfa_ioim_s *ioim)
-{
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_HWFAIL);
-}
-
-/**
- * IO offline TOV popped. Fail the pending IO.
- */
-void
-bfa_ioim_tov(struct bfa_ioim_s *ioim)
-{
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_IOTOV);
-}
-
-
-
-/**
- *  bfa_ioim_api
- */
-
-/**
- * Allocate IOIM resource for initiator mode I/O request.
- */
-struct bfa_ioim_s *
-bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
-		struct bfa_itnim_s *itnim, u16 nsges)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfa_ioim_s *ioim;
-
-	/**
-	 * alocate IOIM resource
-	 */
-	bfa_q_deq(&fcpim->ioim_free_q, &ioim);
-	if (!ioim) {
-		bfa_fcpim_stats(fcpim, no_iotags);
-		return NULL;
-	}
-
-	ioim->dio = dio;
-	ioim->itnim = itnim;
-	ioim->nsges = nsges;
-	ioim->nsgpgs = 0;
-
-	bfa_stats(fcpim, total_ios);
-	bfa_stats(itnim, ios);
-	fcpim->ios_active++;
-
-	list_add_tail(&ioim->qe, &itnim->io_q);
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-
-	return ioim;
-}
-
-void
-bfa_ioim_free(struct bfa_ioim_s *ioim)
-{
-	struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
-
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit));
-
-	bfa_assert_fp(list_empty(&ioim->sgpg_q)
-		   || (ioim->nsges > BFI_SGE_INLINE));
-
-	if (ioim->nsgpgs > 0)
-		bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
-
-	bfa_stats(ioim->itnim, io_comps);
-	fcpim->ios_active--;
-
-	list_del(&ioim->qe);
-	list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
-}
-
-void
-bfa_ioim_start(struct bfa_ioim_s *ioim)
-{
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-
-	/**
-	 * Obtain the queue over which this request has to be issued
-	 */
-	ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ?
-			bfa_cb_ioim_get_reqq(ioim->dio) :
-			bfa_itnim_get_reqq(ioim);
-
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_START);
-}
-
-/**
- * Driver I/O abort request.
- */
-void
-bfa_ioim_abort(struct bfa_ioim_s *ioim)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_fcpim_stats(ioim->fcpim, io_aborts);
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_ABORT);
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_itnim.c b/drivers/scsi/bfa/bfa_itnim.c
deleted file mode 100644
index a914ff2..0000000
--- a/drivers/scsi/bfa/bfa_itnim.c
+++ /dev/null
@@ -1,1088 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_fcpim.h>
-#include "bfa_fcpim_priv.h"
-
-BFA_TRC_FILE(HAL, ITNIM);
-
-#define BFA_ITNIM_FROM_TAG(_fcpim, _tag)				\
-	((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1)))
-
-#define bfa_fcpim_additn(__itnim)					\
-	list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
-#define bfa_fcpim_delitn(__itnim)	do {				\
-	bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));      \
-	list_del(&(__itnim)->qe);      \
-	bfa_assert(list_empty(&(__itnim)->io_q));      \
-	bfa_assert(list_empty(&(__itnim)->io_cleanup_q));      \
-	bfa_assert(list_empty(&(__itnim)->pending_q));      \
-} while (0)
-
-#define bfa_itnim_online_cb(__itnim) do {				\
-	if ((__itnim)->bfa->fcs)					\
-		bfa_cb_itnim_online((__itnim)->ditn);      \
-	else {								\
-		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
-		__bfa_cb_itnim_online, (__itnim));      \
-	}								\
-} while (0)
-
-#define bfa_itnim_offline_cb(__itnim) do {				\
-	if ((__itnim)->bfa->fcs)					\
-		bfa_cb_itnim_offline((__itnim)->ditn);      \
-	else {								\
-		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
-		__bfa_cb_itnim_offline, (__itnim));      \
-	}								\
-} while (0)
-
-#define bfa_itnim_sler_cb(__itnim) do {					\
-	if ((__itnim)->bfa->fcs)					\
-		bfa_cb_itnim_sler((__itnim)->ditn);      \
-	else {								\
-		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
-		__bfa_cb_itnim_sler, (__itnim));      \
-	}								\
-} while (0)
-
-/*
- * forward declarations
- */
-static void     bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
-static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
-static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
-static void     bfa_itnim_cleanp_comp(void *itnim_cbarg);
-static void     bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
-static void     __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
-static void     __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
-static void     __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
-static void     bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
-static void     bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
-static void     bfa_itnim_iotov(void *itnim_arg);
-static void     bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
-static void     bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
-static void     bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
-
-/**
- *  bfa_itnim_sm BFA itnim state machine
- */
-
-
-enum bfa_itnim_event {
-	BFA_ITNIM_SM_CREATE = 1,	/*  itnim is created */
-	BFA_ITNIM_SM_ONLINE = 2,	/*  itnim is online */
-	BFA_ITNIM_SM_OFFLINE = 3,	/*  itnim is offline */
-	BFA_ITNIM_SM_FWRSP = 4,		/*  firmware response */
-	BFA_ITNIM_SM_DELETE = 5,	/*  deleting an existing itnim */
-	BFA_ITNIM_SM_CLEANUP = 6,	/*  IO cleanup completion */
-	BFA_ITNIM_SM_SLER = 7,		/*  second level error recovery */
-	BFA_ITNIM_SM_HWFAIL = 8,	/*  IOC h/w failure event */
-	BFA_ITNIM_SM_QRESUME = 9,	/*  queue space available */
-};
-
-static void     bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
-					enum bfa_itnim_event event);
-static void     bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
-					 enum bfa_itnim_event event);
-static void     bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-static void	bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
-				enum bfa_itnim_event event);
-static void     bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
-					enum bfa_itnim_event event);
-static void     bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
-				      enum bfa_itnim_event event);
-static void     bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
-						 enum bfa_itnim_event event);
-static void     bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
-						enum bfa_itnim_event event);
-static void     bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-static void     bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
-					 enum bfa_itnim_event event);
-static void     bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
-					    enum bfa_itnim_event event);
-static void     bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-static void     bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-static void     bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-static void     bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-
-/**
- * 		Beginning/unallocated state - no events expected.
- */
-static void
-bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_CREATE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_created);
-		itnim->is_online = BFA_FALSE;
-		bfa_fcpim_additn(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Beginning state, only online event expected.
- */
-static void
-bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_ONLINE:
-		if (bfa_itnim_send_fwcreate(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Waiting for itnim create response from firmware.
- */
-static void
-bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_FWRSP:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_online);
-		itnim->is_online = BFA_TRUE;
-		bfa_itnim_iotov_online(itnim);
-		bfa_itnim_online_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending);
-		break;
-
-	case BFA_ITNIM_SM_OFFLINE:
-		if (bfa_itnim_send_fwdelete(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-static void
-bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
-			enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_QRESUME:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
-		bfa_itnim_send_fwcreate(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_reqq_wcancel(&itnim->reqq_wait);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	case BFA_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
-		bfa_reqq_wcancel(&itnim->reqq_wait);
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_reqq_wcancel(&itnim->reqq_wait);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 	Waiting for itnim create response from firmware, a delete is pending.
- */
-static void
-bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
-				enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_FWRSP:
-		if (bfa_itnim_send_fwdelete(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Online state - normal parking state.
- */
-static void
-bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
-		itnim->is_online = BFA_FALSE;
-		bfa_itnim_iotov_start(itnim);
-		bfa_itnim_cleanup(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
-		itnim->is_online = BFA_FALSE;
-		bfa_itnim_cleanup(itnim);
-		break;
-
-	case BFA_ITNIM_SM_SLER:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_sler);
-		itnim->is_online = BFA_FALSE;
-		bfa_itnim_iotov_start(itnim);
-		bfa_itnim_sler_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		itnim->is_online = BFA_FALSE;
-		bfa_itnim_iotov_start(itnim);
-		bfa_itnim_iocdisable_cleanup(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Second level error recovery need.
- */
-static void
-bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
-		bfa_itnim_cleanup(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
-		bfa_itnim_cleanup(itnim);
-		bfa_itnim_iotov_delete(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_itnim_iocdisable_cleanup(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Going offline. Waiting for active IO cleanup.
- */
-static void
-bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
-				 enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_CLEANUP:
-		if (bfa_itnim_send_fwdelete(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
-		bfa_itnim_iotov_delete(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_itnim_iocdisable_cleanup(itnim);
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_SLER:
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Deleting itnim. Waiting for active IO cleanup.
- */
-static void
-bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
-				enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_CLEANUP:
-		if (bfa_itnim_send_fwdelete(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_itnim_iocdisable_cleanup(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * Rport offline. Fimrware itnim is being deleted - awaiting f/w response.
- */
-static void
-bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_FWRSP:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-static void
-bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
-			enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_QRESUME:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
-		bfa_itnim_send_fwdelete(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_reqq_wcancel(&itnim->reqq_wait);
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Offline state.
- */
-static void
-bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_itnim_iotov_delete(itnim);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	case BFA_ITNIM_SM_ONLINE:
-		if (bfa_itnim_send_fwcreate(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		IOC h/w failed state.
- */
-static void
-bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
-			    enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_itnim_iotov_delete(itnim);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	case BFA_ITNIM_SM_OFFLINE:
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_ONLINE:
-		if (bfa_itnim_send_fwcreate(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Itnim is deleted, waiting for firmware response to delete.
- */
-static void
-bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_FWRSP:
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-static void
-bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
-			enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_QRESUME:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
-		bfa_itnim_send_fwdelete(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_reqq_wcancel(&itnim->reqq_wait);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-
-
-/**
- *  bfa_itnim_private
- */
-
-/**
- * 		Initiate cleanup of all IOs on an IOC failure.
- */
-static void
-bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
-{
-	struct bfa_tskim_s *tskim;
-	struct bfa_ioim_s *ioim;
-	struct list_head        *qe, *qen;
-
-	list_for_each_safe(qe, qen, &itnim->tsk_q) {
-		tskim = (struct bfa_tskim_s *) qe;
-		bfa_tskim_iocdisable(tskim);
-	}
-
-	list_for_each_safe(qe, qen, &itnim->io_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		bfa_ioim_iocdisable(ioim);
-	}
-
-	/**
-	 * For IO request in pending queue, we pretend an early timeout.
-	 */
-	list_for_each_safe(qe, qen, &itnim->pending_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		bfa_ioim_tov(ioim);
-	}
-
-	list_for_each_safe(qe, qen, &itnim->io_cleanup_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		bfa_ioim_iocdisable(ioim);
-	}
-}
-
-/**
- * 		IO cleanup completion
- */
-static void
-bfa_itnim_cleanp_comp(void *itnim_cbarg)
-{
-	struct bfa_itnim_s *itnim = itnim_cbarg;
-
-	bfa_stats(itnim, cleanup_comps);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP);
-}
-
-/**
- * 		Initiate cleanup of all IOs.
- */
-static void
-bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
-{
-	struct bfa_ioim_s  *ioim;
-	struct bfa_tskim_s *tskim;
-	struct list_head         *qe, *qen;
-
-	bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim);
-
-	list_for_each_safe(qe, qen, &itnim->io_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-
-		/**
-		 * Move IO to a cleanup queue from active queue so that a later
-		 * TM will not pickup this IO.
-		 */
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &itnim->io_cleanup_q);
-
-		bfa_wc_up(&itnim->wc);
-		bfa_ioim_cleanup(ioim);
-	}
-
-	list_for_each_safe(qe, qen, &itnim->tsk_q) {
-		tskim = (struct bfa_tskim_s *) qe;
-		bfa_wc_up(&itnim->wc);
-		bfa_tskim_cleanup(tskim);
-	}
-
-	bfa_wc_wait(&itnim->wc);
-}
-
-static void
-__bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_itnim_s *itnim = cbarg;
-
-	if (complete)
-		bfa_cb_itnim_online(itnim->ditn);
-}
-
-static void
-__bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_itnim_s *itnim = cbarg;
-
-	if (complete)
-		bfa_cb_itnim_offline(itnim->ditn);
-}
-
-static void
-__bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_itnim_s *itnim = cbarg;
-
-	if (complete)
-		bfa_cb_itnim_sler(itnim->ditn);
-}
-
-/**
- * Call to resume any I/O requests waiting for room in request queue.
- */
-static void
-bfa_itnim_qresume(void *cbarg)
-{
-	struct bfa_itnim_s *itnim = cbarg;
-
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
-}
-
-
-
-
-/**
- *  bfa_itnim_public
- */
-
-void
-bfa_itnim_iodone(struct bfa_itnim_s *itnim)
-{
-	bfa_wc_down(&itnim->wc);
-}
-
-void
-bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
-{
-	bfa_wc_down(&itnim->wc);
-}
-
-void
-bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
-{
-	/**
-	 * ITN memory
-	 */
-	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s);
-}
-
-void
-bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
-{
-	struct bfa_s      *bfa = fcpim->bfa;
-	struct bfa_itnim_s *itnim;
-	int             i;
-
-	INIT_LIST_HEAD(&fcpim->itnim_q);
-
-	itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
-	fcpim->itnim_arr = itnim;
-
-	for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
-		bfa_os_memset(itnim, 0, sizeof(struct bfa_itnim_s));
-		itnim->bfa = bfa;
-		itnim->fcpim = fcpim;
-		itnim->reqq = BFA_REQQ_QOS_LO;
-		itnim->rport = BFA_RPORT_FROM_TAG(bfa, i);
-		itnim->iotov_active = BFA_FALSE;
-		bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim);
-
-		INIT_LIST_HEAD(&itnim->io_q);
-		INIT_LIST_HEAD(&itnim->io_cleanup_q);
-		INIT_LIST_HEAD(&itnim->pending_q);
-		INIT_LIST_HEAD(&itnim->tsk_q);
-		INIT_LIST_HEAD(&itnim->delay_comp_q);
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-	}
-
-	bfa_meminfo_kva(minfo) = (u8 *) itnim;
-}
-
-void
-bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
-{
-	bfa_stats(itnim, ioc_disabled);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL);
-}
-
-static bfa_boolean_t
-bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
-{
-	struct bfi_itnim_create_req_s *m;
-
-	itnim->msg_no++;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
-	if (!m) {
-		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
-			bfa_lpuid(itnim->bfa));
-	m->fw_handle = itnim->rport->fw_handle;
-	m->class = FC_CLASS_3;
-	m->seq_rec = itnim->seq_rec;
-	m->msg_no = itnim->msg_no;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(itnim->bfa, itnim->reqq);
-	return BFA_TRUE;
-}
-
-static bfa_boolean_t
-bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
-{
-	struct bfi_itnim_delete_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
-	if (!m) {
-		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
-			bfa_lpuid(itnim->bfa));
-	m->fw_handle = itnim->rport->fw_handle;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(itnim->bfa, itnim->reqq);
-	return BFA_TRUE;
-}
-
-/**
- * Cleanup all pending failed inflight requests.
- */
-static void
-bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov)
-{
-	struct bfa_ioim_s *ioim;
-	struct list_head *qe, *qen;
-
-	list_for_each_safe(qe, qen, &itnim->delay_comp_q) {
-		ioim = (struct bfa_ioim_s *)qe;
-		bfa_ioim_delayed_comp(ioim, iotov);
-	}
-}
-
-/**
- * Start all pending IO requests.
- */
-static void
-bfa_itnim_iotov_online(struct bfa_itnim_s *itnim)
-{
-	struct bfa_ioim_s *ioim;
-
-	bfa_itnim_iotov_stop(itnim);
-
-	/**
-	 * Abort all inflight IO requests in the queue
-	 */
-	bfa_itnim_delayed_comp(itnim, BFA_FALSE);
-
-	/**
-	 * Start all pending IO requests.
-	 */
-	while (!list_empty(&itnim->pending_q)) {
-		bfa_q_deq(&itnim->pending_q, &ioim);
-		list_add_tail(&ioim->qe, &itnim->io_q);
-		bfa_ioim_start(ioim);
-	}
-}
-
-/**
- * Fail all pending IO requests
- */
-static void
-bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim)
-{
-	struct bfa_ioim_s *ioim;
-
-	/**
-	 * Fail all inflight IO requests in the queue
-	 */
-	bfa_itnim_delayed_comp(itnim, BFA_TRUE);
-
-	/**
-	 * Fail any pending IO requests.
-	 */
-	while (!list_empty(&itnim->pending_q)) {
-		bfa_q_deq(&itnim->pending_q, &ioim);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_ioim_tov(ioim);
-	}
-}
-
-/**
- * IO TOV timer callback. Fail any pending IO requests.
- */
-static void
-bfa_itnim_iotov(void *itnim_arg)
-{
-	struct bfa_itnim_s *itnim = itnim_arg;
-
-	itnim->iotov_active = BFA_FALSE;
-
-	bfa_cb_itnim_tov_begin(itnim->ditn);
-	bfa_itnim_iotov_cleanup(itnim);
-	bfa_cb_itnim_tov(itnim->ditn);
-}
-
-/**
- * Start IO TOV timer for failing back pending IO requests in offline state.
- */
-static void
-bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)
-{
-	if (itnim->fcpim->path_tov > 0) {
-
-		itnim->iotov_active = BFA_TRUE;
-		bfa_assert(bfa_itnim_hold_io(itnim));
-		bfa_timer_start(itnim->bfa, &itnim->timer,
-			bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
-	}
-}
-
-/**
- * Stop IO TOV timer.
- */
-static void
-bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim)
-{
-	if (itnim->iotov_active) {
-		itnim->iotov_active = BFA_FALSE;
-		bfa_timer_stop(&itnim->timer);
-	}
-}
-
-/**
- * Stop IO TOV timer.
- */
-static void
-bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
-{
-    bfa_boolean_t pathtov_active = BFA_FALSE;
-
-    if (itnim->iotov_active)
-		pathtov_active = BFA_TRUE;
-
-	bfa_itnim_iotov_stop(itnim);
-	if (pathtov_active)
-		bfa_cb_itnim_tov_begin(itnim->ditn);
-	bfa_itnim_iotov_cleanup(itnim);
-	if (pathtov_active)
-		bfa_cb_itnim_tov(itnim->ditn);
-}
-
-
-
-/**
- *  bfa_itnim_public
- */
-
-/**
- * 		Itnim interrupt processing.
- */
-void
-bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	union bfi_itnim_i2h_msg_u msg;
-	struct bfa_itnim_s *itnim;
-
-	bfa_trc(bfa, m->mhdr.msg_id);
-
-	msg.msg = m;
-
-	switch (m->mhdr.msg_id) {
-	case BFI_ITNIM_I2H_CREATE_RSP:
-		itnim = BFA_ITNIM_FROM_TAG(fcpim,
-					       msg.create_rsp->bfa_handle);
-		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
-		bfa_stats(itnim, create_comps);
-		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
-		break;
-
-	case BFI_ITNIM_I2H_DELETE_RSP:
-		itnim = BFA_ITNIM_FROM_TAG(fcpim,
-					       msg.delete_rsp->bfa_handle);
-		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
-		bfa_stats(itnim, delete_comps);
-		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
-		break;
-
-	case BFI_ITNIM_I2H_SLER_EVENT:
-		itnim = BFA_ITNIM_FROM_TAG(fcpim,
-					       msg.sler_event->bfa_handle);
-		bfa_stats(itnim, sler_events);
-		bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER);
-		break;
-
-	default:
-		bfa_trc(bfa, m->mhdr.msg_id);
-		bfa_assert(0);
-	}
-}
-
-
-
-/**
- *  bfa_itnim_api
- */
-
-struct bfa_itnim_s *
-bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfa_itnim_s *itnim;
-
-	itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
-	bfa_assert(itnim->rport == rport);
-
-	itnim->ditn = ditn;
-
-	bfa_stats(itnim, creates);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);
-
-	return itnim;
-}
-
-void
-bfa_itnim_delete(struct bfa_itnim_s *itnim)
-{
-	bfa_stats(itnim, deletes);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE);
-}
-
-void
-bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec)
-{
-	itnim->seq_rec = seq_rec;
-	bfa_stats(itnim, onlines);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE);
-}
-
-void
-bfa_itnim_offline(struct bfa_itnim_s *itnim)
-{
-	bfa_stats(itnim, offlines);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE);
-}
-
-/**
- * Return true if itnim is considered offline for holding off IO request.
- * IO is not held if itnim is being deleted.
- */
-bfa_boolean_t
-bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
-{
-	return
-		itnim->fcpim->path_tov && itnim->iotov_active &&
-		(bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||
-		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||
-		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) ||
-		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||
-		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||
-		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable))
-	;
-}
-
-void
-bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
-	struct bfa_itnim_hal_stats_s *stats)
-{
-	*stats = itnim->stats;
-}
-
-void
-bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
-{
-	bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats));
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_log.c b/drivers/scsi/bfa/bfa_log.c
deleted file mode 100644
index e751401..0000000
--- a/drivers/scsi/bfa/bfa_log.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_log.c BFA log library
- */
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_log.h>
-
-/*
- * global log info structure
- */
-struct bfa_log_info_s {
-	u32        start_idx;	/*  start index for a module */
-	u32        total_count;	/*  total count for a module */
-	enum bfa_log_severity level;	/*  global log level */
-	bfa_log_cb_t	cbfn;		/*  callback function */
-};
-
-static struct bfa_log_info_s bfa_log_info[BFA_LOG_MODULE_ID_MAX + 1];
-static u32 bfa_log_msg_total_count;
-static int      bfa_log_initialized;
-
-static char    *bfa_log_severity[] =
-	{ "[none]", "[critical]", "[error]", "[warn]", "[info]", "" };
-
-/**
- * BFA log library initialization
- *
- * The log library initialization includes the following,
- *    - set log instance name and callback function
- *    - read the message array generated from xml files
- *    - calculate start index for each module
- *    - calculate message count for each module
- *    - perform error checking
- *
- * @param[in] log_mod - log module info
- * @param[in] instance_name - instance name
- * @param[in] cbfn - callback function
- *
- * It return 0 on success, or -1 on failure
- */
-int
-bfa_log_init(struct bfa_log_mod_s *log_mod, char *instance_name,
-			bfa_log_cb_t cbfn)
-{
-	struct bfa_log_msgdef_s *msg;
-	u32        pre_mod_id = 0;
-	u32        cur_mod_id = 0;
-	u32        i, pre_idx, idx, msg_id;
-
-	/*
-	 * set instance name
-	 */
-	if (log_mod) {
-		strncpy(log_mod->instance_info, instance_name,
-			sizeof(log_mod->instance_info));
-		log_mod->cbfn = cbfn;
-		for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++)
-			log_mod->log_level[i] = BFA_LOG_WARNING;
-	}
-
-	if (bfa_log_initialized)
-		return 0;
-
-	for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++) {
-		bfa_log_info[i].start_idx = 0;
-		bfa_log_info[i].total_count = 0;
-		bfa_log_info[i].level = BFA_LOG_WARNING;
-		bfa_log_info[i].cbfn = cbfn;
-	}
-
-	pre_idx = 0;
-	idx = 0;
-	msg = bfa_log_msg_array;
-	msg_id = BFA_LOG_GET_MSG_ID(msg);
-	pre_mod_id = BFA_LOG_GET_MOD_ID(msg_id);
-	while (msg_id != 0) {
-		cur_mod_id = BFA_LOG_GET_MOD_ID(msg_id);
-
-		if (cur_mod_id > BFA_LOG_MODULE_ID_MAX) {
-			cbfn(log_mod, msg_id,
-				"%s%s log: module id %u out of range\n",
-				BFA_LOG_CAT_NAME,
-				bfa_log_severity[BFA_LOG_ERROR],
-				cur_mod_id);
-			return -1;
-		}
-
-		if (pre_mod_id > BFA_LOG_MODULE_ID_MAX) {
-			cbfn(log_mod, msg_id,
-				"%s%s log: module id %u out of range\n",
-				BFA_LOG_CAT_NAME,
-				bfa_log_severity[BFA_LOG_ERROR],
-				pre_mod_id);
-			return -1;
-		}
-
-		if (cur_mod_id != pre_mod_id) {
-			bfa_log_info[pre_mod_id].start_idx = pre_idx;
-			bfa_log_info[pre_mod_id].total_count = idx - pre_idx;
-			pre_mod_id = cur_mod_id;
-			pre_idx = idx;
-		}
-
-		idx++;
-		msg++;
-		msg_id = BFA_LOG_GET_MSG_ID(msg);
-	}
-
-	bfa_log_info[cur_mod_id].start_idx = pre_idx;
-	bfa_log_info[cur_mod_id].total_count = idx - pre_idx;
-	bfa_log_msg_total_count = idx;
-
-	cbfn(log_mod, msg_id, "%s%s log: init OK, msg total count %u\n",
-		BFA_LOG_CAT_NAME,
-		bfa_log_severity[BFA_LOG_INFO], bfa_log_msg_total_count);
-
-	bfa_log_initialized = 1;
-
-	return 0;
-}
-
-/**
- * BFA log set log level for a module
- *
- * @param[in] log_mod - log module info
- * @param[in] mod_id - module id
- * @param[in] log_level - log severity level
- *
- * It return BFA_STATUS_OK on success, or > 0 on failure
- */
-bfa_status_t
-bfa_log_set_level(struct bfa_log_mod_s *log_mod, int mod_id,
-		  enum bfa_log_severity log_level)
-{
-	if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX)
-		return BFA_STATUS_EINVAL;
-
-	if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX)
-		return BFA_STATUS_EINVAL;
-
-	if (log_mod)
-		log_mod->log_level[mod_id] = log_level;
-	else
-		bfa_log_info[mod_id].level = log_level;
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * BFA log set log level for all modules
- *
- * @param[in] log_mod - log module info
- * @param[in] log_level - log severity level
- *
- * It return BFA_STATUS_OK on success, or > 0 on failure
- */
-bfa_status_t
-bfa_log_set_level_all(struct bfa_log_mod_s *log_mod,
-		  enum bfa_log_severity log_level)
-{
-	int mod_id = BFA_LOG_UNUSED_ID + 1;
-
-	if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX)
-		return BFA_STATUS_EINVAL;
-
-	if (log_mod) {
-		for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++)
-			log_mod->log_level[mod_id] = log_level;
-	} else {
-		for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++)
-			bfa_log_info[mod_id].level = log_level;
-	}
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * BFA log set log level for all aen sub-modules
- *
- * @param[in] log_mod - log module info
- * @param[in] log_level - log severity level
- *
- * It return BFA_STATUS_OK on success, or > 0 on failure
- */
-bfa_status_t
-bfa_log_set_level_aen(struct bfa_log_mod_s *log_mod,
-		  enum bfa_log_severity log_level)
-{
-	int mod_id = BFA_LOG_AEN_MIN + 1;
-
-	if (log_mod) {
-		for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++)
-			log_mod->log_level[mod_id] = log_level;
-	} else {
-		for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++)
-			bfa_log_info[mod_id].level = log_level;
-	}
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * BFA log get log level for a module
- *
- * @param[in] log_mod - log module info
- * @param[in] mod_id - module id
- *
- * It returns log level or -1 on error
- */
-enum bfa_log_severity
-bfa_log_get_level(struct bfa_log_mod_s *log_mod, int mod_id)
-{
-	if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX)
-		return BFA_LOG_INVALID;
-
-	if (log_mod)
-		return log_mod->log_level[mod_id];
-	else
-		return bfa_log_info[mod_id].level;
-}
-
-enum bfa_log_severity
-bfa_log_get_msg_level(struct bfa_log_mod_s *log_mod, u32 msg_id)
-{
-	struct bfa_log_msgdef_s *msg;
-	u32        mod = BFA_LOG_GET_MOD_ID(msg_id);
-	u32        idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1;
-
-	if (!bfa_log_initialized)
-		return BFA_LOG_INVALID;
-
-	if (mod > BFA_LOG_MODULE_ID_MAX)
-		return BFA_LOG_INVALID;
-
-	if (idx >= bfa_log_info[mod].total_count) {
-		bfa_log_info[mod].cbfn(log_mod, msg_id,
-			"%s%s log: inconsistent idx %u vs. total count %u\n",
-			BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx,
-			bfa_log_info[mod].total_count);
-		return BFA_LOG_INVALID;
-	}
-
-	msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx;
-	if (msg_id != BFA_LOG_GET_MSG_ID(msg)) {
-		bfa_log_info[mod].cbfn(log_mod, msg_id,
-			"%s%s log: inconsistent msg id %u array msg id %u\n",
-			BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR],
-			msg_id, BFA_LOG_GET_MSG_ID(msg));
-		return BFA_LOG_INVALID;
-	}
-
-	return BFA_LOG_GET_SEVERITY(msg);
-}
-
-/**
- * BFA log message handling
- *
- * BFA log message handling finds the message based on message id and prints
- * out the message based on its format and arguments. It also does prefix
- * the severity etc.
- *
- * @param[in] log_mod - log module info
- * @param[in] msg_id - message id
- * @param[in] ... - message arguments
- *
- * It return 0 on success, or -1 on errors
- */
-int
-bfa_log(struct bfa_log_mod_s *log_mod, u32 msg_id, ...)
-{
-	va_list         ap;
-	char            buf[256];
-	struct bfa_log_msgdef_s *msg;
-	int             log_level;
-	u32        mod = BFA_LOG_GET_MOD_ID(msg_id);
-	u32        idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1;
-
-	if (!bfa_log_initialized)
-		return -1;
-
-	if (mod > BFA_LOG_MODULE_ID_MAX)
-		return -1;
-
-	if (idx >= bfa_log_info[mod].total_count) {
-		bfa_log_info[mod].
-			cbfn
-			(log_mod, msg_id,
-			"%s%s log: inconsistent idx %u vs. total count %u\n",
-			BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx,
-			bfa_log_info[mod].total_count);
-		return -1;
-	}
-
-	msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx;
-	if (msg_id != BFA_LOG_GET_MSG_ID(msg)) {
-		bfa_log_info[mod].
-			cbfn
-			(log_mod, msg_id,
-			"%s%s log: inconsistent msg id %u array msg id %u\n",
-			BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR],
-			msg_id, BFA_LOG_GET_MSG_ID(msg));
-		return -1;
-	}
-
-	log_level = log_mod ? log_mod->log_level[mod] : bfa_log_info[mod].level;
-	if ((BFA_LOG_GET_SEVERITY(msg) > log_level) &&
-			(msg->attributes != BFA_LOG_ATTR_NONE))
-		return 0;
-
-	va_start(ap, msg_id);
-	bfa_os_vsprintf(buf, BFA_LOG_GET_MSG_FMT_STRING(msg), ap);
-	va_end(ap);
-
-	if (log_mod)
-		log_mod->cbfn(log_mod, msg_id, "%s[%s]%s%s %s: %s\n",
-				BFA_LOG_CAT_NAME, log_mod->instance_info,
-				bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)],
-				(msg->attributes & BFA_LOG_ATTR_AUDIT)
-				? " (audit) " : "", msg->msg_value, buf);
-	else
-		bfa_log_info[mod].cbfn(log_mod, msg_id, "%s%s%s %s: %s\n",
-				BFA_LOG_CAT_NAME,
-				bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)],
-				(msg->attributes & BFA_LOG_ATTR_AUDIT) ?
-				" (audit) " : "", msg->msg_value, buf);
-
-	return 0;
-}
-
diff --git a/drivers/scsi/bfa/bfa_log_module.c b/drivers/scsi/bfa/bfa_log_module.c
deleted file mode 100644
index cf577ef..0000000
--- a/drivers/scsi/bfa/bfa_log_module.c
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <cs/bfa_log.h>
-#include <aen/bfa_aen_adapter.h>
-#include <aen/bfa_aen_audit.h>
-#include <aen/bfa_aen_ethport.h>
-#include <aen/bfa_aen_ioc.h>
-#include <aen/bfa_aen_itnim.h>
-#include <aen/bfa_aen_lport.h>
-#include <aen/bfa_aen_port.h>
-#include <aen/bfa_aen_rport.h>
-#include <log/bfa_log_fcs.h>
-#include <log/bfa_log_hal.h>
-#include <log/bfa_log_linux.h>
-#include <log/bfa_log_wdrv.h>
-
-struct bfa_log_msgdef_s bfa_log_msg_array[] = {
-
-
-/* messages define for BFA_AEN_CAT_ADAPTER Module */
-{BFA_AEN_ADAPTER_ADD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ADAPTER_ADD",
- "New adapter found: SN = %s, base port WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_ADAPTER_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_ADAPTER_REMOVE",
- "Adapter removed: SN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_AUDIT Module */
-{BFA_AEN_AUDIT_AUTH_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_ENABLE",
- "Authentication enabled for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_AUDIT_AUTH_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_DISABLE",
- "Authentication disabled for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_ETHPORT Module */
-{BFA_AEN_ETHPORT_LINKUP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_LINKUP",
- "Base port ethernet linkup: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_ETHPORT_LINKDOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_LINKDOWN",
- "Base port ethernet linkdown: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_ETHPORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_ENABLE",
- "Base port ethernet interface enabled: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_ETHPORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_DISABLE",
- "Base port ethernet interface disabled: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_IOC Module */
-{BFA_AEN_IOC_HBGOOD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_IOC_HBGOOD",
- "Heart Beat of IOC %d is good.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_HBFAIL, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_CRITICAL,
- "BFA_AEN_IOC_HBFAIL",
- "Heart Beat of IOC %d has failed.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_IOC_ENABLE",
- "IOC %d is enabled.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_IOC_DISABLE",
- "IOC %d is disabled.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_FWMISMATCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_CRITICAL, "BFA_AEN_IOC_FWMISMATCH",
- "Running firmware version is incompatible with the driver version.",
- (0), 0},
-
-{BFA_AEN_IOC_FWCFG_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_CRITICAL, "BFA_AEN_IOC_FWCFG_ERROR",
- "Link initialization failed due to firmware configuration read error:"
- " WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_INVALID_VENDOR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_VENDOR",
- "Unsupported switch vendor. Link initialization failed: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_INVALID_NWWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_NWWN",
- "Invalid NWWN. Link initialization failed: NWWN = 00:00:00:00:00:00:00:00.",
- (0), 0},
-
-{BFA_AEN_IOC_INVALID_PWWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_PWWN",
- "Invalid PWWN. Link initialization failed: PWWN = 00:00:00:00:00:00:00:00.",
- (0), 0},
-
-
-
-
-/* messages define for BFA_AEN_CAT_ITNIM Module */
-{BFA_AEN_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ITNIM_ONLINE",
- "Target (WWN = %s) is online for initiator (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ITNIM_OFFLINE",
- "Target (WWN = %s) offlined by initiator (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_ITNIM_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_ITNIM_DISCONNECT",
- "Target (WWN = %s) connectivity lost for initiator (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-
-
-
-/* messages define for BFA_AEN_CAT_LPORT Module */
-{BFA_AEN_LPORT_NEW, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_NEW",
- "New logical port created: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DELETE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_DELETE",
- "Logical port deleted: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_ONLINE",
- "Logical port online: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_OFFLINE",
- "Logical port taken offline: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_LPORT_DISCONNECT",
- "Logical port lost fabric connectivity: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_NEW_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_NEW_PROP",
- "New virtual port created using proprietary interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DELETE_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_PROP",
- "Virtual port deleted using proprietary interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_NEW_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_LPORT_NEW_STANDARD",
- "New virtual port created using standard interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DELETE_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_STANDARD",
- "Virtual port deleted using standard interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_NPIV_DUP_WWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_DUP_WWN",
- "Virtual port login failed. Duplicate WWN = %s reported by fabric.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_LPORT_NPIV_FABRIC_MAX, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_FABRIC_MAX",
- "Virtual port (WWN = %s) login failed. Max NPIV ports already exist in"
- " fabric/fport.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_LPORT_NPIV_UNKNOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_UNKNOWN",
- "Virtual port (WWN = %s) login failed.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_PORT Module */
-{BFA_AEN_PORT_ONLINE, BFA_LOG_ATTR_NONE, BFA_LOG_INFO, "BFA_AEN_PORT_ONLINE",
- "Base port online: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
- "BFA_AEN_PORT_OFFLINE",
- "Base port offline: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_RLIR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_RLIR",
- "RLIR event not supported.",
- (0), 0},
-
-{BFA_AEN_PORT_SFP_INSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_SFP_INSERT",
- "New SFP found: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_SFP_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_REMOVE",
- "SFP removed: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_SFP_POM, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
- "BFA_AEN_PORT_SFP_POM",
- "SFP POM level to %s: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_PORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_ENABLE",
- "Base port enabled: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_DISABLE",
- "Base port disabled: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_AUTH_ON, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_AUTH_ON",
- "Authentication successful for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_AUTH_OFF, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "BFA_AEN_PORT_AUTH_OFF",
- "Authentication unsuccessful for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "BFA_AEN_PORT_DISCONNECT",
- "Base port (WWN = %s) lost fabric connectivity.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_QOS_NEG, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
- "BFA_AEN_PORT_QOS_NEG",
- "QOS negotiation failed for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_FABRIC_NAME_CHANGE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_FABRIC_NAME_CHANGE",
- "Base port WWN = %s, Fabric WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_PORT_SFP_ACCESS_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_ACCESS_ERROR",
- "SFP access error: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_SFP_UNSUPPORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_UNSUPPORT",
- "Unsupported SFP found: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_RPORT Module */
-{BFA_AEN_RPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_ONLINE",
- "Remote port (WWN = %s) online for logical port (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_RPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_OFFLINE",
- "Remote port (WWN = %s) offlined by logical port (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_RPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_RPORT_DISCONNECT",
- "Remote port (WWN = %s) connectivity lost for logical port (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_RPORT_QOS_PRIO, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_QOS_PRIO",
- "QOS priority changed to %s: RPWWN = %s and LPWWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_AEN_RPORT_QOS_FLOWID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_QOS_FLOWID",
- "QOS flow ID changed to %d: RPWWN = %s and LPWWN = %s.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-
-
-
-/* messages define for FCS Module */
-{BFA_LOG_FCS_FABRIC_NOSWITCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "FCS_FABRIC_NOSWITCH",
- "No switched fabric presence is detected.",
- (0), 0},
-
-{BFA_LOG_FCS_FABRIC_ISOLATED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "FCS_FABRIC_ISOLATED",
- "Port is isolated due to VF_ID mismatch. PWWN: %s, Port VF_ID: %04x and"
- " switch port VF_ID: %04x.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_X << BFA_LOG_ARG1) |
-  (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
-
-
-
-
-/* messages define for HAL Module */
-{BFA_LOG_HAL_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "HAL_ASSERT",
- "Assertion failure: %s:%d: %s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_HAL_HEARTBEAT_FAILURE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_CRITICAL, "HAL_HEARTBEAT_FAILURE",
- "Firmware heartbeat failure at %d",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_HAL_FCPIM_PARM_INVALID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "HAL_FCPIM_PARM_INVALID",
- "Driver configuration %s value %d is invalid. Value should be within"
- " %d and %d.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
-  (BFA_LOG_D << BFA_LOG_ARG2) | (BFA_LOG_D << BFA_LOG_ARG3) | 0), 4},
-
-{BFA_LOG_HAL_SM_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "HAL_SM_ASSERT",
- "SM Assertion failure: %s:%d: event = %d",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
-  (BFA_LOG_D << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_HAL_DRIVER_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "HAL_DRIVER_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_HAL_DRIVER_CONFIG_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "HAL_DRIVER_CONFIG_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_HAL_MBOX_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "HAL_MBOX_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for LINUX Module */
-{BFA_LOG_LINUX_DEVICE_CLAIMED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DEVICE_CLAIMED",
- "bfa device at %s claimed.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_HASH_INIT_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_HASH_INIT_FAILED",
- "Hash table initialization failure for the port %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_SYSFS_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_SYSFS_FAILED",
- "sysfs file creation failure for the port %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_MEM_ALLOC_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_MEM_ALLOC_FAILED",
- "Memory allocation failed: %s.  ",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_REGISTRATION_FAILED,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_DRIVER_REGISTRATION_FAILED",
- "%s.  ",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_ITNIM_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_ITNIM_FREE",
- "scsi%d: FCID: %s WWPN: %s",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_LINUX_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_ITNIM_ONLINE",
- "Target: %d:0:%d FCID: %s WWPN: %s",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4},
-
-{BFA_LOG_LINUX_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_ITNIM_OFFLINE",
- "Target: %d:0:%d FCID: %s WWPN: %s",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4},
-
-{BFA_LOG_LINUX_SCSI_HOST_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_SCSI_HOST_FREE",
- "Free scsi%d",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_SCSI_ABORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_SCSI_ABORT",
- "scsi%d: abort cmnd %p, iotag %x",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) |
-  (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_LINUX_SCSI_ABORT_COMP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_SCSI_ABORT_COMP",
- "scsi%d: complete abort 0x%p, iotag 0x%x",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) |
-  (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_LINUX_DRIVER_CONFIG_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_DRIVER_CONFIG_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_BNA_STATE_MACHINE,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_BNA_STATE_MACHINE",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_IOC_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_IOC_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_RESOURCE_ALLOC_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_RESOURCE_ALLOC_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_RING_BUFFER_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_RING_BUFFER_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "LINUX_DRIVER_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_INFO, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DRIVER_INFO",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_DIAG, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DRIVER_DIAG",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_AEN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DRIVER_AEN",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for WDRV Module */
-{BFA_LOG_WDRV_IOC_INIT_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_INIT_ERROR",
- "IOC initialization has failed.",
- (0), 0},
-
-{BFA_LOG_WDRV_IOC_INTERNAL_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_INTERNAL_ERROR",
- "IOC internal error.  ",
- (0), 0},
-
-{BFA_LOG_WDRV_IOC_START_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_START_ERROR",
- "IOC could not be started.  ",
- (0), 0},
-
-{BFA_LOG_WDRV_IOC_STOP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_STOP_ERROR",
- "IOC could not be stopped.  ",
- (0), 0},
-
-{BFA_LOG_WDRV_INSUFFICIENT_RESOURCES, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_INSUFFICIENT_RESOURCES",
- "Insufficient memory.  ",
- (0), 0},
-
-{BFA_LOG_WDRV_BASE_ADDRESS_MAP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_BASE_ADDRESS_MAP_ERROR",
- "Unable to map the IOC onto the system address space.  ",
- (0), 0},
-
-
-{0, 0, 0, "", "", 0, 0},
-};
diff --git a/drivers/scsi/bfa/bfa_lps.c b/drivers/scsi/bfa/bfa_lps.c
deleted file mode 100644
index acabb44..0000000
--- a/drivers/scsi/bfa/bfa_lps.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfi/bfi_lps.h>
-#include <cs/bfa_debug.h>
-#include <defs/bfa_defs_pci.h>
-
-BFA_TRC_FILE(HAL, LPS);
-BFA_MODULE(lps);
-
-#define BFA_LPS_MIN_LPORTS	(1)
-#define BFA_LPS_MAX_LPORTS	(256)
-
-/*
- * Maximum Vports supported per physical port or vf.
- */
-#define BFA_LPS_MAX_VPORTS_SUPP_CB  255
-#define BFA_LPS_MAX_VPORTS_SUPP_CT  190
-
-/**
- * forward declarations
- */
-static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
-			    u32 *dm_len);
-static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
-			   struct bfa_iocfc_cfg_s *cfg,
-			   struct bfa_meminfo_s *meminfo,
-			   struct bfa_pcidev_s *pcidev);
-static void bfa_lps_detach(struct bfa_s *bfa);
-static void bfa_lps_start(struct bfa_s *bfa);
-static void bfa_lps_stop(struct bfa_s *bfa);
-static void bfa_lps_iocdisable(struct bfa_s *bfa);
-static void bfa_lps_login_rsp(struct bfa_s *bfa,
-			      struct bfi_lps_login_rsp_s *rsp);
-static void bfa_lps_logout_rsp(struct bfa_s *bfa,
-			       struct bfi_lps_logout_rsp_s *rsp);
-static void bfa_lps_reqq_resume(void *lps_arg);
-static void bfa_lps_free(struct bfa_lps_s *lps);
-static void bfa_lps_send_login(struct bfa_lps_s *lps);
-static void bfa_lps_send_logout(struct bfa_lps_s *lps);
-static void bfa_lps_login_comp(struct bfa_lps_s *lps);
-static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
-static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
-
-/**
- *  lps_pvt BFA LPS private functions
- */
-
-enum bfa_lps_event {
-	BFA_LPS_SM_LOGIN	= 1,	/* login request from user	*/
-	BFA_LPS_SM_LOGOUT	= 2,	/* logout request from user	*/
-	BFA_LPS_SM_FWRSP	= 3,	/* f/w response to login/logout	*/
-	BFA_LPS_SM_RESUME	= 4,	/* space present in reqq queue	*/
-	BFA_LPS_SM_DELETE	= 5,	/* lps delete from user		*/
-	BFA_LPS_SM_OFFLINE	= 6,	/* Link is offline		*/
-	BFA_LPS_SM_RX_CVL       = 7,	/* Rx clear virtual link        */
-};
-
-static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps,
-			enum bfa_lps_event event);
-static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_logowait(struct bfa_lps_s *lps,
-			enum bfa_lps_event event);
-
-/**
- * Init state -- no login
- */
-static void
-bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_LOGIN:
-		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
-			bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
-			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
-		} else {
-			bfa_sm_set_state(lps, bfa_lps_sm_login);
-			bfa_lps_send_login(lps);
-		}
-		if (lps->fdisc)
-			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-			BFA_PL_EID_LOGIN, 0, "FDISC Request");
-		else
-			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-			BFA_PL_EID_LOGIN, 0, "FLOGI Request");
-		break;
-
-	case BFA_LPS_SM_LOGOUT:
-		bfa_lps_logout_comp(lps);
-		break;
-
-	case BFA_LPS_SM_DELETE:
-		bfa_lps_free(lps);
-		break;
-
-	case BFA_LPS_SM_RX_CVL:
-	case BFA_LPS_SM_OFFLINE:
-		break;
-
-	case BFA_LPS_SM_FWRSP:
-		/* Could happen when fabric detects loopback and discards
-		 * the lps request. Fw will eventually sent out the timeout
-		 * Just ignore
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-/**
- * login is in progress -- awaiting response from firmware
- */
-static void
-bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_FWRSP:
-		if (lps->status == BFA_STATUS_OK) {
-			bfa_sm_set_state(lps, bfa_lps_sm_online);
-			if (lps->fdisc)
-				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-				BFA_PL_EID_LOGIN, 0, "FDISC Accept");
-			else
-				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-				BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
-		} else {
-			bfa_sm_set_state(lps, bfa_lps_sm_init);
-			if (lps->fdisc)
-				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-				BFA_PL_EID_LOGIN, 0,
-				"FDISC Fail (RJT or timeout)");
-			else
-				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-				BFA_PL_EID_LOGIN, 0,
-				"FLOGI Fail (RJT or timeout)");
-		}
-		bfa_lps_login_comp(lps);
-		break;
-
-	case BFA_LPS_SM_OFFLINE:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-/**
- * login pending - awaiting space in request queue
- */
-static void
-bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_RESUME:
-		bfa_sm_set_state(lps, bfa_lps_sm_login);
-		break;
-
-	case BFA_LPS_SM_OFFLINE:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		bfa_reqq_wcancel(&lps->wqe);
-		break;
-
-	case BFA_LPS_SM_RX_CVL:
-		/*
-		 * Login was not even sent out; so when getting out
-		 * of this state, it will appear like a login retry
-		 * after Clear virtual link
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-/**
- * login complete
- */
-static void
-bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_LOGOUT:
-		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
-			bfa_sm_set_state(lps, bfa_lps_sm_logowait);
-			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
-		} else {
-			bfa_sm_set_state(lps, bfa_lps_sm_logout);
-			bfa_lps_send_logout(lps);
-		}
-		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-			BFA_PL_EID_LOGO, 0, "Logout");
-		break;
-
-	case BFA_LPS_SM_RX_CVL:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-
-		/* Let the vport module know about this event */
-		bfa_lps_cvl_event(lps);
-		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
-		break;
-
-	case BFA_LPS_SM_OFFLINE:
-	case BFA_LPS_SM_DELETE:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-/**
- * logout in progress - awaiting firmware response
- */
-static void
-bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_FWRSP:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		bfa_lps_logout_comp(lps);
-		break;
-
-	case BFA_LPS_SM_OFFLINE:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-/**
- * logout pending -- awaiting space in request queue
- */
-static void
-bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_RESUME:
-		bfa_sm_set_state(lps, bfa_lps_sm_logout);
-		bfa_lps_send_logout(lps);
-		break;
-
-	case BFA_LPS_SM_OFFLINE:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		bfa_reqq_wcancel(&lps->wqe);
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-
-
-/**
- *  lps_pvt BFA LPS private functions
- */
-
-/**
- * return memory requirement
- */
-static void
-bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
-{
-	if (cfg->drvcfg.min_cfg)
-		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
-	else
-		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
-}
-
-/**
- * bfa module attach at initialization time
- */
-static void
-bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps;
-	int			i;
-
-	bfa_os_memset(mod, 0, sizeof(struct bfa_lps_mod_s));
-	mod->num_lps = BFA_LPS_MAX_LPORTS;
-	if (cfg->drvcfg.min_cfg)
-		mod->num_lps = BFA_LPS_MIN_LPORTS;
-	else
-		mod->num_lps = BFA_LPS_MAX_LPORTS;
-	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
-
-	bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
-
-	INIT_LIST_HEAD(&mod->lps_free_q);
-	INIT_LIST_HEAD(&mod->lps_active_q);
-
-	for (i = 0; i < mod->num_lps; i++, lps++) {
-		lps->bfa	= bfa;
-		lps->lp_tag	= (u8) i;
-		lps->reqq	= BFA_REQQ_LPS;
-		bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
-		list_add_tail(&lps->qe, &mod->lps_free_q);
-	}
-}
-
-static void
-bfa_lps_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_lps_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_lps_stop(struct bfa_s *bfa)
-{
-}
-
-/**
- * IOC in disabled state -- consider all lps offline
- */
-static void
-bfa_lps_iocdisable(struct bfa_s *bfa)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps;
-	struct list_head		*qe, *qen;
-
-	list_for_each_safe(qe, qen, &mod->lps_active_q) {
-		lps = (struct bfa_lps_s *) qe;
-		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
-	}
-}
-
-/**
- * Firmware login response
- */
-static void
-bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps;
-
-	bfa_assert(rsp->lp_tag < mod->num_lps);
-	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
-
-	lps->status = rsp->status;
-	switch (rsp->status) {
-	case BFA_STATUS_OK:
-		lps->fport	= rsp->f_port;
-		lps->npiv_en	= rsp->npiv_en;
-		lps->lp_pid	= rsp->lp_pid;
-		lps->pr_bbcred	= bfa_os_ntohs(rsp->bb_credit);
-		lps->pr_pwwn	= rsp->port_name;
-		lps->pr_nwwn	= rsp->node_name;
-		lps->auth_req	= rsp->auth_req;
-		lps->lp_mac	= rsp->lp_mac;
-		lps->brcd_switch = rsp->brcd_switch;
-		lps->fcf_mac	= rsp->fcf_mac;
-
-		break;
-
-	case BFA_STATUS_FABRIC_RJT:
-		lps->lsrjt_rsn = rsp->lsrjt_rsn;
-		lps->lsrjt_expl = rsp->lsrjt_expl;
-
-		break;
-
-	case BFA_STATUS_EPROTOCOL:
-		lps->ext_status = rsp->ext_status;
-
-		break;
-
-	default:
-		/* Nothing to do with other status */
-		break;
-	}
-
-	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
-}
-
-/**
- * Firmware logout response
- */
-static void
-bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps;
-
-	bfa_assert(rsp->lp_tag < mod->num_lps);
-	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
-
-	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
-}
-
-/**
- * Firmware received a Clear virtual link request (for FCoE)
- */
-static void
-bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
-{
-	struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s        *lps;
-
-	lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag);
-
-	bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
-}
-
-/**
- * Space is available in request queue, resume queueing request to firmware.
- */
-static void
-bfa_lps_reqq_resume(void *lps_arg)
-{
-	struct bfa_lps_s	*lps = lps_arg;
-
-	bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
-}
-
-/**
- * lps is freed -- triggered by vport delete
- */
-static void
-bfa_lps_free(struct bfa_lps_s *lps)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);
-
-	list_del(&lps->qe);
-	list_add_tail(&lps->qe, &mod->lps_free_q);
-}
-
-/**
- * send login request to firmware
- */
-static void
-bfa_lps_send_login(struct bfa_lps_s *lps)
-{
-	struct bfi_lps_login_req_s	*m;
-
-	m = bfa_reqq_next(lps->bfa, lps->reqq);
-	bfa_assert(m);
-
-	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
-			bfa_lpuid(lps->bfa));
-
-	m->lp_tag	= lps->lp_tag;
-	m->alpa		= lps->alpa;
-	m->pdu_size	= bfa_os_htons(lps->pdusz);
-	m->pwwn		= lps->pwwn;
-	m->nwwn		= lps->nwwn;
-	m->fdisc	= lps->fdisc;
-	m->auth_en	= lps->auth_en;
-
-	bfa_reqq_produce(lps->bfa, lps->reqq);
-}
-
-/**
- * send logout request to firmware
- */
-static void
-bfa_lps_send_logout(struct bfa_lps_s *lps)
-{
-	struct bfi_lps_logout_req_s *m;
-
-	m = bfa_reqq_next(lps->bfa, lps->reqq);
-	bfa_assert(m);
-
-	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
-			bfa_lpuid(lps->bfa));
-
-	m->lp_tag    = lps->lp_tag;
-	m->port_name = lps->pwwn;
-	bfa_reqq_produce(lps->bfa, lps->reqq);
-}
-
-/**
- * Indirect login completion handler for non-fcs
- */
-static void
-bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
-{
-	struct bfa_lps_s *lps	= arg;
-
-	if (!complete)
-		return;
-
-	if (lps->fdisc)
-		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
-	else
-		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
-}
-
-/**
- * Login completion handler -- direct call for fcs, queue for others
- */
-static void
-bfa_lps_login_comp(struct bfa_lps_s *lps)
-{
-	if (!lps->bfa->fcs) {
-		bfa_cb_queue(lps->bfa, &lps->hcb_qe,
-				bfa_lps_login_comp_cb, lps);
-		return;
-	}
-
-	if (lps->fdisc)
-		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
-	else
-		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
-}
-
-/**
- * Indirect logout completion handler for non-fcs
- */
-static void
-bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
-{
-	struct bfa_lps_s *lps	= arg;
-
-	if (!complete)
-		return;
-
-	if (lps->fdisc)
-		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
-	else
-		bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
-}
-
-/**
- * Logout completion handler -- direct call for fcs, queue for others
- */
-static void
-bfa_lps_logout_comp(struct bfa_lps_s *lps)
-{
-	if (!lps->bfa->fcs) {
-		bfa_cb_queue(lps->bfa, &lps->hcb_qe,
-				bfa_lps_logout_comp_cb, lps);
-		return;
-	}
-	if (lps->fdisc)
-		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
-	else
-		bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
-}
-
-/**
- * Clear virtual link completion handler for non-fcs
- */
-static void
-bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
-{
-	struct bfa_lps_s *lps   = arg;
-
-	if (!complete)
-		return;
-
-	/* Clear virtual link to base port will result in link down */
-	if (lps->fdisc)
-		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
-}
-
-/**
- * Received Clear virtual link event --direct call for fcs,
- * queue for others
- */
-static void
-bfa_lps_cvl_event(struct bfa_lps_s *lps)
-{
-	if (!lps->bfa->fcs) {
-		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
-				lps);
-		return;
-	}
-
-	/* Clear virtual link to base port will result in link down */
-	if (lps->fdisc)
-		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
-}
-
-u32
-bfa_lps_get_max_vport(struct bfa_s *bfa)
-{
-	if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
-		return BFA_LPS_MAX_VPORTS_SUPP_CT;
-	else
-		return BFA_LPS_MAX_VPORTS_SUPP_CB;
-}
-
-/**
- *  lps_public BFA LPS public functions
- */
-
-/**
- * Allocate a lport srvice tag.
- */
-struct bfa_lps_s  *
-bfa_lps_alloc(struct bfa_s *bfa)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps = NULL;
-
-	bfa_q_deq(&mod->lps_free_q, &lps);
-
-	if (lps == NULL)
-		return NULL;
-
-	list_add_tail(&lps->qe, &mod->lps_active_q);
-
-	bfa_sm_set_state(lps, bfa_lps_sm_init);
-	return lps;
-}
-
-/**
- * Free lport service tag. This can be called anytime after an alloc.
- * No need to wait for any pending login/logout completions.
- */
-void
-bfa_lps_delete(struct bfa_lps_s *lps)
-{
-	bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
-}
-
-/**
- * Initiate a lport login.
- */
-void
-bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
-	wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
-{
-	lps->uarg	= uarg;
-	lps->alpa	= alpa;
-	lps->pdusz	= pdusz;
-	lps->pwwn	= pwwn;
-	lps->nwwn	= nwwn;
-	lps->fdisc	= BFA_FALSE;
-	lps->auth_en	= auth_en;
-	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
-}
-
-/**
- * Initiate a lport fdisc login.
- */
-void
-bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
-	wwn_t nwwn)
-{
-	lps->uarg	= uarg;
-	lps->alpa	= 0;
-	lps->pdusz	= pdusz;
-	lps->pwwn	= pwwn;
-	lps->nwwn	= nwwn;
-	lps->fdisc	= BFA_TRUE;
-	lps->auth_en	= BFA_FALSE;
-	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
-}
-
-/**
- * Initiate a lport logout (flogi).
- */
-void
-bfa_lps_flogo(struct bfa_lps_s *lps)
-{
-	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
-}
-
-/**
- * Initiate a lport FDSIC logout.
- */
-void
-bfa_lps_fdisclogo(struct bfa_lps_s *lps)
-{
-	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
-}
-
-/**
- * Discard a pending login request -- should be called only for
- * link down handling.
- */
-void
-bfa_lps_discard(struct bfa_lps_s *lps)
-{
-	bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
-}
-
-/**
- * Return lport services tag
- */
-u8
-bfa_lps_get_tag(struct bfa_lps_s *lps)
-{
-	return lps->lp_tag;
-}
-
-/**
- * Return lport services tag given the pid
- */
-u8
-bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps;
-	int			i;
-
-	for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
-		if (lps->lp_pid == pid)
-			return lps->lp_tag;
-	}
-
-	/* Return base port tag anyway */
-	return 0;
-}
-
-/**
- * return if fabric login indicates support for NPIV
- */
-bfa_boolean_t
-bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
-{
-	return lps->npiv_en;
-}
-
-/**
- * Return TRUE if attached to F-Port, else return FALSE
- */
-bfa_boolean_t
-bfa_lps_is_fport(struct bfa_lps_s *lps)
-{
-	return lps->fport;
-}
-
-/**
- * Return TRUE if attached to a Brocade Fabric
- */
-bfa_boolean_t
-bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
-{
-	return lps->brcd_switch;
-}
-/**
- * return TRUE if authentication is required
- */
-bfa_boolean_t
-bfa_lps_is_authreq(struct bfa_lps_s *lps)
-{
-	return lps->auth_req;
-}
-
-bfa_eproto_status_t
-bfa_lps_get_extstatus(struct bfa_lps_s *lps)
-{
-	return lps->ext_status;
-}
-
-/**
- * return port id assigned to the lport
- */
-u32
-bfa_lps_get_pid(struct bfa_lps_s *lps)
-{
-	return lps->lp_pid;
-}
-
-/**
- * Return bb_credit assigned in FLOGI response
- */
-u16
-bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
-{
-	return lps->pr_bbcred;
-}
-
-/**
- * Return peer port name
- */
-wwn_t
-bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
-{
-	return lps->pr_pwwn;
-}
-
-/**
- * Return peer node name
- */
-wwn_t
-bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
-{
-	return lps->pr_nwwn;
-}
-
-/**
- * return reason code if login request is rejected
- */
-u8
-bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
-{
-	return lps->lsrjt_rsn;
-}
-
-/**
- * return explanation code if login request is rejected
- */
-u8
-bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
-{
-	return lps->lsrjt_expl;
-}
-
-/**
- * Return fpma/spma MAC for lport
- */
-struct mac_s
-bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
-{
-	return lps->lp_mac;
-}
-
-/**
- * LPS firmware message class handler.
- */
-void
-bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	union bfi_lps_i2h_msg_u	msg;
-
-	bfa_trc(bfa, m->mhdr.msg_id);
-	msg.msg = m;
-
-	switch (m->mhdr.msg_id) {
-	case BFI_LPS_H2I_LOGIN_RSP:
-		bfa_lps_login_rsp(bfa, msg.login_rsp);
-		break;
-
-	case BFI_LPS_H2I_LOGOUT_RSP:
-		bfa_lps_logout_rsp(bfa, msg.logout_rsp);
-		break;
-
-	case BFI_LPS_H2I_CVL_EVENT:
-		bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
-		break;
-
-	default:
-		bfa_trc(bfa, m->mhdr.msg_id);
-		bfa_assert(0);
-	}
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_lps_priv.h b/drivers/scsi/bfa/bfa_lps_priv.h
deleted file mode 100644
index d16c6ce..0000000
--- a/drivers/scsi/bfa/bfa_lps_priv.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_LPS_PRIV_H__
-#define __BFA_LPS_PRIV_H__
-
-#include <bfa_svc.h>
-
-struct bfa_lps_mod_s {
-	struct list_head		lps_free_q;
-	struct list_head		lps_active_q;
-	struct bfa_lps_s	*lps_arr;
-	int			num_lps;
-};
-
-#define BFA_LPS_MOD(__bfa)		(&(__bfa)->modules.lps_mod)
-#define BFA_LPS_FROM_TAG(__mod, __tag)	(&(__mod)->lps_arr[__tag])
-
-/*
- * external functions
- */
-void	bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-
-#endif /* __BFA_LPS_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_module.c b/drivers/scsi/bfa/bfa_module.c
deleted file mode 100644
index a7fcc80..0000000
--- a/drivers/scsi/bfa/bfa_module.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#include <bfa.h>
-#include <defs/bfa_defs_pci.h>
-#include <cs/bfa_debug.h>
-#include <bfa_iocfc.h>
-
-/**
- * BFA module list terminated by NULL
- */
-struct bfa_module_s *hal_mods[] = {
-	&hal_mod_sgpg,
-	&hal_mod_fcport,
-	&hal_mod_fcxp,
-	&hal_mod_lps,
-	&hal_mod_uf,
-	&hal_mod_rport,
-	&hal_mod_fcpim,
-#ifdef BFA_CFG_PBIND
-	&hal_mod_pbind,
-#endif
-	NULL
-};
-
-/**
- * Message handlers for various modules.
- */
-bfa_isr_func_t  bfa_isrs[BFI_MC_MAX] = {
-	bfa_isr_unhandled,	/* NONE */
-	bfa_isr_unhandled,	/* BFI_MC_IOC */
-	bfa_isr_unhandled,	/* BFI_MC_DIAG */
-	bfa_isr_unhandled,	/* BFI_MC_FLASH */
-	bfa_isr_unhandled,	/* BFI_MC_CEE */
-	bfa_fcport_isr,		/* BFI_MC_FCPORT */
-	bfa_isr_unhandled,	/* BFI_MC_IOCFC */
-	bfa_isr_unhandled,	/* BFI_MC_LL */
-	bfa_uf_isr,		/* BFI_MC_UF */
-	bfa_fcxp_isr,		/* BFI_MC_FCXP */
-	bfa_lps_isr,		/* BFI_MC_LPS */
-	bfa_rport_isr,		/* BFI_MC_RPORT */
-	bfa_itnim_isr,		/* BFI_MC_ITNIM */
-	bfa_isr_unhandled,	/* BFI_MC_IOIM_READ */
-	bfa_isr_unhandled,	/* BFI_MC_IOIM_WRITE */
-	bfa_isr_unhandled,	/* BFI_MC_IOIM_IO */
-	bfa_ioim_isr,		/* BFI_MC_IOIM */
-	bfa_ioim_good_comp_isr,	/* BFI_MC_IOIM_IOCOM */
-	bfa_tskim_isr,		/* BFI_MC_TSKIM */
-	bfa_isr_unhandled,	/* BFI_MC_SBOOT */
-	bfa_isr_unhandled,	/* BFI_MC_IPFC */
-	bfa_isr_unhandled,	/* BFI_MC_PORT */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-};
-
-/**
- * Message handlers for mailbox command classes
- */
-bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[BFI_MC_MAX] = {
-	NULL,
-	NULL,			/* BFI_MC_IOC	*/
-	NULL,			/* BFI_MC_DIAG	*/
-	NULL,		/* BFI_MC_FLASH */
-	NULL,			/* BFI_MC_CEE	*/
-	NULL,			/* BFI_MC_PORT	*/
-	bfa_iocfc_isr,		/* BFI_MC_IOCFC */
-	NULL,
-};
-
diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h
new file mode 100644
index 0000000..2cd5273
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_modules.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+/**
+ *  bfa_modules.h BFA modules
+ */
+
+#ifndef __BFA_MODULES_H__
+#define __BFA_MODULES_H__
+
+#include "bfa_cs.h"
+#include "bfa.h"
+#include "bfa_svc.h"
+#include "bfa_fcpim.h"
+#include "bfa_port.h"
+
+struct bfa_modules_s {
+	struct bfa_fcport_s	fcport;		/*  fc port module	      */
+	struct bfa_fcxp_mod_s	fcxp_mod;	/*  fcxp module	      */
+	struct bfa_lps_mod_s	lps_mod;	/*  fcxp module	      */
+	struct bfa_uf_mod_s	uf_mod;		/*  unsolicited frame module */
+	struct bfa_rport_mod_s	rport_mod;	/*  remote port module	      */
+	struct bfa_fcpim_mod_s	fcpim_mod;	/*  FCP initiator module     */
+	struct bfa_sgpg_mod_s	sgpg_mod;	/*  SG page module	      */
+	struct bfa_port_s	port;		/*  Physical port module     */
+};
+
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+	BFA_TRC_HAL_CORE	= 1,
+	BFA_TRC_HAL_FCXP	= 2,
+	BFA_TRC_HAL_FCPIM	= 3,
+	BFA_TRC_HAL_IOCFC_CT	= 4,
+	BFA_TRC_HAL_IOCFC_CB	= 5,
+};
+
+
+/**
+ * Macro to define a new BFA module
+ */
+#define BFA_MODULE(__mod)						\
+	static void bfa_ ## __mod ## _meminfo(				\
+			struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,	\
+			u32 *dm_len);      \
+	static void bfa_ ## __mod ## _attach(struct bfa_s *bfa,		\
+			void *bfad, struct bfa_iocfc_cfg_s *cfg,	\
+			struct bfa_meminfo_s *meminfo,			\
+			struct bfa_pcidev_s *pcidev);      \
+	static void bfa_ ## __mod ## _detach(struct bfa_s *bfa);      \
+	static void bfa_ ## __mod ## _start(struct bfa_s *bfa);      \
+	static void bfa_ ## __mod ## _stop(struct bfa_s *bfa);      \
+	static void bfa_ ## __mod ## _iocdisable(struct bfa_s *bfa);      \
+									\
+	extern struct bfa_module_s hal_mod_ ## __mod;			\
+	struct bfa_module_s hal_mod_ ## __mod = {			\
+		bfa_ ## __mod ## _meminfo,				\
+		bfa_ ## __mod ## _attach,				\
+		bfa_ ## __mod ## _detach,				\
+		bfa_ ## __mod ## _start,				\
+		bfa_ ## __mod ## _stop,					\
+		bfa_ ## __mod ## _iocdisable,				\
+	}
+
+#define BFA_CACHELINE_SZ	(256)
+
+/**
+ * Structure used to interact between different BFA sub modules
+ *
+ * Each sub module needs to implement only the entry points relevant to it (and
+ * can leave entry points as NULL)
+ */
+struct bfa_module_s {
+	void (*meminfo) (struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+			u32 *dm_len);
+	void (*attach) (struct bfa_s *bfa, void *bfad,
+			struct bfa_iocfc_cfg_s *cfg,
+			struct bfa_meminfo_s *meminfo,
+			struct bfa_pcidev_s *pcidev);
+	void (*detach) (struct bfa_s *bfa);
+	void (*start) (struct bfa_s *bfa);
+	void (*stop) (struct bfa_s *bfa);
+	void (*iocdisable) (struct bfa_s *bfa);
+};
+
+extern struct bfa_module_s *hal_mods[];
+
+struct bfa_s {
+	void			*bfad;		/*  BFA driver instance    */
+	struct bfa_plog_s	*plog;		/*  portlog buffer	    */
+	struct bfa_trc_mod_s	*trcmod;	/*  driver tracing	    */
+	struct bfa_ioc_s	ioc;		/*  IOC module		    */
+	struct bfa_iocfc_s	iocfc;		/*  IOCFC module	    */
+	struct bfa_timer_mod_s	timer_mod;	/*  timer module	    */
+	struct bfa_modules_s	modules;	/*  BFA modules	    */
+	struct list_head	comp_q;		/*  pending completions     */
+	bfa_boolean_t		rme_process;	/*  RME processing enabled  */
+	struct list_head	reqq_waitq[BFI_IOC_MAX_CQS];
+	bfa_boolean_t		fcs;		/*  FCS is attached to BFA */
+	struct bfa_msix_s	msix;
+};
+
+extern bfa_isr_func_t bfa_isrs[BFI_MC_MAX];
+extern bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[];
+extern bfa_boolean_t bfa_auto_recover;
+extern struct bfa_module_s hal_mod_sgpg;
+extern struct bfa_module_s hal_mod_fcport;
+extern struct bfa_module_s hal_mod_fcxp;
+extern struct bfa_module_s hal_mod_lps;
+extern struct bfa_module_s hal_mod_uf;
+extern struct bfa_module_s hal_mod_rport;
+extern struct bfa_module_s hal_mod_fcpim;
+
+#endif /* __BFA_MODULES_H__ */
diff --git a/drivers/scsi/bfa/bfa_modules_priv.h b/drivers/scsi/bfa/bfa_modules_priv.h
deleted file mode 100644
index f554c2f..0000000
--- a/drivers/scsi/bfa/bfa_modules_priv.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_MODULES_PRIV_H__
-#define __BFA_MODULES_PRIV_H__
-
-#include "bfa_uf_priv.h"
-#include "bfa_port_priv.h"
-#include "bfa_rport_priv.h"
-#include "bfa_fcxp_priv.h"
-#include "bfa_lps_priv.h"
-#include "bfa_fcpim_priv.h"
-#include <cee/bfa_cee.h>
-#include <port/bfa_port.h>
-
-
-struct bfa_modules_s {
-	struct bfa_fcport_s	fcport;	/*  fc port module	*/
-	struct bfa_fcxp_mod_s fcxp_mod; /*  fcxp module		*/
-	struct bfa_lps_mod_s lps_mod;   /*  fcxp module		*/
-	struct bfa_uf_mod_s uf_mod;	/*  unsolicited frame module	*/
-	struct bfa_rport_mod_s rport_mod; /*  remote port module	*/
-	struct bfa_fcpim_mod_s fcpim_mod; /*  FCP initiator module	*/
-	struct bfa_sgpg_mod_s sgpg_mod; /*  SG page module		*/
-	struct bfa_cee_s cee;   	/*  CEE Module                 */
-	struct bfa_port_s port;		/*  Physical port module	*/
-};
-
-#endif /* __BFA_MODULES_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_os_inc.h b/drivers/scsi/bfa/bfa_os_inc.h
index bd1cd3e..788a250 100644
--- a/drivers/scsi/bfa/bfa_os_inc.h
+++ b/drivers/scsi/bfa/bfa_os_inc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -22,30 +22,20 @@
 #ifndef __BFA_OS_INC_H__
 #define __BFA_OS_INC_H__
 
-#ifndef __KERNEL__
-#include <stdint.h>
-#else
 #include <linux/types.h>
-
 #include <linux/version.h>
 #include <linux/pci.h>
-
 #include <linux/dma-mapping.h>
-#define SET_MODULE_VERSION(VER)
-
 #include <linux/idr.h>
-
 #include <linux/interrupt.h>
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
-
 #include <linux/workqueue.h>
-
+#include <linux/bitops.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
-
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_transport_fc.h>
 #include <scsi/scsi_transport.h>
@@ -54,97 +44,75 @@
 #define __BIGENDIAN
 #endif
 
-#define BFA_ERR			KERN_ERR
-#define BFA_WARNING		KERN_WARNING
-#define BFA_NOTICE		KERN_NOTICE
-#define BFA_INFO		KERN_INFO
-#define BFA_DEBUG		KERN_DEBUG
+static inline u64 bfa_os_get_clock(void)
+{
+	return jiffies;
+}
 
-#define LOG_BFAD_INIT		0x00000001
-#define LOG_FCP_IO		0x00000002
+static inline u64 bfa_os_get_log_time(void)
+{
+	u64 system_time = 0;
+	struct timeval tv;
+	do_gettimeofday(&tv);
 
-#ifdef DEBUG
-#define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...)			\
-		BFA_LOG(bfad, level, mask, fmt, ## arg)
-#define BFA_DEV_TRACE(bfad, level, fmt, arg...)				\
-		BFA_DEV_PRINTF(bfad, level, fmt, ## arg)
-#define BFA_TRACE(level, fmt, arg...)					\
-		BFA_PRINTF(level, fmt, ## arg)
-#else
-#define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...)
-#define BFA_DEV_TRACE(bfad, level, fmt, arg...)
-#define BFA_TRACE(level, fmt, arg...)
-#endif
+	/* We are interested in seconds only. */
+	system_time = tv.tv_sec;
+	return system_time;
+}
+
+#define bfa_io_lat_clock_res_div HZ
+#define bfa_io_lat_clock_res_mul 1000
 
 #define BFA_ASSERT(p) do {						\
 	if (!(p)) {      \
 		printk(KERN_ERR "assert(%s) failed at %s:%d\n",		\
 		#p, __FILE__, __LINE__);      \
-		BUG();      \
 	}								\
 } while (0)
 
-
-#define BFA_LOG(bfad, level, mask, fmt, arg...)				\
-do { 									\
-	if (((mask) & (((struct bfad_s *)(bfad))->			\
-		cfg_data[cfg_log_mask])) || (level[1] <= '3'))		\
-		dev_printk(level, &(((struct bfad_s *)			\
-			(bfad))->pcidev->dev), fmt, ##arg);      \
+#define BFA_LOG(level, bfad, mask, fmt, arg...)				\
+do {									\
+	if (((mask) == 4) || (level[1] <= '4'))				\
+		dev_printk(level, &((bfad)->pcidev)->dev, fmt, ##arg);	\
 } while (0)
 
-#ifndef BFA_DEV_PRINTF
-#define BFA_DEV_PRINTF(bfad, level, fmt, arg...)			\
-		dev_printk(level, &(((struct bfad_s *)			\
-			(bfad))->pcidev->dev), fmt, ##arg);
-#endif
-
-#define BFA_PRINTF(level, fmt, arg...)					\
-		printk(level fmt, ##arg);
-
-int bfa_os_MWB(void *);
-
-#define bfa_os_mmiowb()		mmiowb()
-
 #define bfa_swap_3b(_x)				\
 	((((_x) & 0xff) << 16) |		\
 	((_x) & 0x00ff00) |			\
 	(((_x) & 0xff0000) >> 16))
 
-#define bfa_swap_8b(_x) 				\
-     ((((_x) & 0xff00000000000000ull) >> 56)		\
-      | (((_x) & 0x00ff000000000000ull) >> 40)		\
-      | (((_x) & 0x0000ff0000000000ull) >> 24)		\
-      | (((_x) & 0x000000ff00000000ull) >> 8)		\
-      | (((_x) & 0x00000000ff000000ull) << 8)		\
-      | (((_x) & 0x0000000000ff0000ull) << 24)		\
-      | (((_x) & 0x000000000000ff00ull) << 40)		\
-      | (((_x) & 0x00000000000000ffull) << 56))
+#define bfa_swap_8b(_x)					\
+	((((_x) & 0xff00000000000000ull) >> 56)		\
+	 | (((_x) & 0x00ff000000000000ull) >> 40)	\
+	 | (((_x) & 0x0000ff0000000000ull) >> 24)	\
+	 | (((_x) & 0x000000ff00000000ull) >> 8)	\
+	 | (((_x) & 0x00000000ff000000ull) << 8)	\
+	 | (((_x) & 0x0000000000ff0000ull) << 24)	\
+	 | (((_x) & 0x000000000000ff00ull) << 40)	\
+	 | (((_x) & 0x00000000000000ffull) << 56))
 
-#define bfa_os_swap32(_x) 			\
-	((((_x) & 0xff) << 24) 		|	\
+#define bfa_os_swap32(_x)			\
+	((((_x) & 0xff) << 24)		|	\
 	(((_x) & 0x0000ff00) << 8)	|	\
 	(((_x) & 0x00ff0000) >> 8)	|	\
 	(((_x) & 0xff000000) >> 24))
 
-#define bfa_os_swap_sgaddr(_x)	((u64)(					\
-	(((u64)(_x) & (u64)0x00000000000000ffull) << 32)	|	\
-	(((u64)(_x) & (u64)0x000000000000ff00ull) << 32)	|	\
-	(((u64)(_x) & (u64)0x0000000000ff0000ull) << 32)	|	\
-	(((u64)(_x) & (u64)0x00000000ff000000ull) << 32)	|	\
-	(((u64)(_x) & (u64)0x000000ff00000000ull) >> 32)	|	\
-	(((u64)(_x) & (u64)0x0000ff0000000000ull) >> 32)	|	\
-	(((u64)(_x) & (u64)0x00ff000000000000ull) >> 32)	|	\
+#define bfa_os_swap_sgaddr(_x)  ((u64)(                                 \
+	(((u64)(_x) & (u64)0x00000000000000ffull) << 32)        |       \
+	(((u64)(_x) & (u64)0x000000000000ff00ull) << 32)        |       \
+	(((u64)(_x) & (u64)0x0000000000ff0000ull) << 32)        |       \
+	(((u64)(_x) & (u64)0x00000000ff000000ull) << 32)        |       \
+	(((u64)(_x) & (u64)0x000000ff00000000ull) >> 32)        |       \
+	(((u64)(_x) & (u64)0x0000ff0000000000ull) >> 32)        |       \
+	(((u64)(_x) & (u64)0x00ff000000000000ull) >> 32)        |       \
 	(((u64)(_x) & (u64)0xff00000000000000ull) >> 32)))
 
 #ifndef __BIGENDIAN
 #define bfa_os_htons(_x) ((u16)((((_x) & 0xff00) >> 8) | \
 				 (((_x) & 0x00ff) << 8)))
-
 #define bfa_os_htonl(_x)	bfa_os_swap32(_x)
 #define bfa_os_htonll(_x)	bfa_swap_8b(_x)
 #define bfa_os_hton3b(_x)	bfa_swap_3b(_x)
-
 #define bfa_os_wtole(_x)   (_x)
 #define bfa_os_sgaddr(_x)  (_x)
 
@@ -170,17 +138,16 @@
 #define bfa_os_memcpy	memcpy
 #define bfa_os_udelay	udelay
 #define bfa_os_vsprintf vsprintf
+#define bfa_os_snprintf snprintf
 
 #define bfa_os_assign(__t, __s) __t = __s
-
-#define bfa_os_addr_t char __iomem *
-#define bfa_os_panic()
+#define bfa_os_addr_t void __iomem *
 
 #define bfa_os_reg_read(_raddr) readl(_raddr)
 #define bfa_os_reg_write(_raddr, _val) writel((_val), (_raddr))
-#define bfa_os_mem_read(_raddr, _off)                                   \
+#define bfa_os_mem_read(_raddr, _off)					\
 	bfa_os_swap32(readl(((_raddr) + (_off))))
-#define bfa_os_mem_write(_raddr, _off, _val)                            \
+#define bfa_os_mem_write(_raddr, _off, _val)				\
 	writel(bfa_os_swap32((_val)), ((_raddr) + (_off)))
 
 #define BFA_TRC_TS(_trcm)						\
@@ -191,11 +158,6 @@
 				(tv.tv_sec*1000000+tv.tv_usec);      \
 			 })
 
-struct bfa_log_mod_s;
-void bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id,
-			const char *fmt, ...);
-#endif
-
 #define boolean_t int
 
 /**
@@ -206,7 +168,15 @@
 	u32	tv_usec;	/*  microseconds   */
 };
 
-void bfa_os_gettimeofday(struct bfa_timeval_s *tv);
+static inline void
+bfa_os_gettimeofday(struct bfa_timeval_s *tv)
+{
+	struct timeval  tmp_tv;
+
+	do_gettimeofday(&tmp_tv);
+	tv->tv_sec = (u32) tmp_tv.tv_sec;
+	tv->tv_usec = (u32) tmp_tv.tv_usec;
+}
 
 static inline void
 wwn2str(char *wwn_str, u64 wwn)
diff --git a/drivers/scsi/bfa/bfa_plog.h b/drivers/scsi/bfa/bfa_plog.h
new file mode 100644
index 0000000..501f0ed
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_plog.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_PORTLOG_H__
+#define __BFA_PORTLOG_H__
+
+#include "bfa_fc.h"
+#include "bfa_defs.h"
+
+#define BFA_PL_NLOG_ENTS 256
+#define BFA_PL_LOG_REC_INCR(_x) ((_x)++, (_x) %= BFA_PL_NLOG_ENTS)
+
+#define BFA_PL_STRING_LOG_SZ   32   /* number of chars in string log */
+#define BFA_PL_INT_LOG_SZ      8    /* number of integers in the integer log */
+
+enum bfa_plog_log_type {
+	BFA_PL_LOG_TYPE_INVALID	= 0,
+	BFA_PL_LOG_TYPE_INT	= 1,
+	BFA_PL_LOG_TYPE_STRING	= 2,
+};
+
+/*
+ * the (fixed size) record format for each entry in the portlog
+ */
+struct bfa_plog_rec_s {
+	u64	tv;	/* timestamp */
+	u8	 port;	/* Source port that logged this entry */
+	u8	 mid;	/* module id */
+	u8	 eid;	/* indicates Rx, Tx, IOCTL, etc.  bfa_plog_eid */
+	u8	 log_type; /* string/integer log, bfa_plog_log_type_t */
+	u8	 log_num_ints;
+	/*
+	 * interpreted only if log_type is INT_LOG. indicates number of
+	 * integers in the int_log[] (0-PL_INT_LOG_SZ).
+	 */
+	u8	 rsvd;
+	u16	misc;	/* can be used to indicate fc frame length */
+	union {
+		char	    string_log[BFA_PL_STRING_LOG_SZ];
+		u32	int_log[BFA_PL_INT_LOG_SZ];
+	} log_entry;
+
+};
+
+/*
+ * the following #defines will be used by the logging entities to indicate
+ * their module id. BFAL will convert the integer value to string format
+ *
+* process to be used while changing the following #defines:
+ *  - Always add new entries at the end
+ *  - define corresponding string in BFAL
+ *  - Do not remove any entry or rearrange the order.
+ */
+enum bfa_plog_mid {
+	BFA_PL_MID_INVALID	= 0,
+	BFA_PL_MID_DEBUG	= 1,
+	BFA_PL_MID_DRVR		= 2,
+	BFA_PL_MID_HAL		= 3,
+	BFA_PL_MID_HAL_FCXP	= 4,
+	BFA_PL_MID_HAL_UF	= 5,
+	BFA_PL_MID_FCS		= 6,
+	BFA_PL_MID_LPS		= 7,
+	BFA_PL_MID_MAX		= 8
+};
+
+#define BFA_PL_MID_STRLEN    8
+struct bfa_plog_mid_strings_s {
+	char	    m_str[BFA_PL_MID_STRLEN];
+};
+
+/*
+ * the following #defines will be used by the logging entities to indicate
+ * their event type. BFAL will convert the integer value to string format
+ *
+* process to be used while changing the following #defines:
+ *  - Always add new entries at the end
+ *  - define corresponding string in BFAL
+ *  - Do not remove any entry or rearrange the order.
+ */
+enum bfa_plog_eid {
+	BFA_PL_EID_INVALID		= 0,
+	BFA_PL_EID_IOC_DISABLE		= 1,
+	BFA_PL_EID_IOC_ENABLE		= 2,
+	BFA_PL_EID_PORT_DISABLE		= 3,
+	BFA_PL_EID_PORT_ENABLE		= 4,
+	BFA_PL_EID_PORT_ST_CHANGE	= 5,
+	BFA_PL_EID_TX			= 6,
+	BFA_PL_EID_TX_ACK1		= 7,
+	BFA_PL_EID_TX_RJT		= 8,
+	BFA_PL_EID_TX_BSY		= 9,
+	BFA_PL_EID_RX			= 10,
+	BFA_PL_EID_RX_ACK1		= 11,
+	BFA_PL_EID_RX_RJT		= 12,
+	BFA_PL_EID_RX_BSY		= 13,
+	BFA_PL_EID_CT_IN		= 14,
+	BFA_PL_EID_CT_OUT		= 15,
+	BFA_PL_EID_DRIVER_START		= 16,
+	BFA_PL_EID_RSCN			= 17,
+	BFA_PL_EID_DEBUG		= 18,
+	BFA_PL_EID_MISC			= 19,
+	BFA_PL_EID_FIP_FCF_DISC		= 20,
+	BFA_PL_EID_FIP_FCF_CVL		= 21,
+	BFA_PL_EID_LOGIN		= 22,
+	BFA_PL_EID_LOGO			= 23,
+	BFA_PL_EID_TRUNK_SCN		= 24,
+	BFA_PL_EID_MAX
+};
+
+#define BFA_PL_ENAME_STRLEN	8
+struct bfa_plog_eid_strings_s {
+	char	    e_str[BFA_PL_ENAME_STRLEN];
+};
+
+#define BFA_PL_SIG_LEN	8
+#define BFA_PL_SIG_STR  "12pl123"
+
+/*
+ * per port circular log buffer
+ */
+struct bfa_plog_s {
+	char	    plog_sig[BFA_PL_SIG_LEN];	/* Start signature */
+	u8	 plog_enabled;
+	u8	 rsvd[7];
+	u32	ticks;
+	u16	head;
+	u16	tail;
+	struct bfa_plog_rec_s  plog_recs[BFA_PL_NLOG_ENTS];
+};
+
+void bfa_plog_init(struct bfa_plog_s *plog);
+void bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+			enum bfa_plog_eid event, u16 misc, char *log_str);
+void bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+			enum bfa_plog_eid event, u16 misc,
+			u32 *intarr, u32 num_ints);
+void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+		enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr);
+void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+			enum bfa_plog_eid event, u16 misc,
+			struct fchs_s *fchdr, u32 pld_w0);
+void bfa_plog_clear(struct bfa_plog_s *plog);
+void bfa_plog_enable(struct bfa_plog_s *plog);
+void bfa_plog_disable(struct bfa_plog_s *plog);
+bfa_boolean_t	bfa_plog_get_setting(struct bfa_plog_s *plog);
+
+#endif /* __BFA_PORTLOG_H__ */
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c
index c7e69f1..b6d170a 100644
--- a/drivers/scsi/bfa/bfa_port.c
+++ b/drivers/scsi/bfa/bfa_port.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,30 +15,25 @@
  * General Public License for more details.
  */
 
-#include <defs/bfa_defs_port.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-#include <cs/bfa_debug.h>
-#include <port/bfa_port.h>
-#include <bfi/bfi.h>
-#include <bfi/bfi_port.h>
-#include <bfa_ioc.h>
-#include <cna/bfa_cna_trcmod.h>
+#include "bfa_defs_svc.h"
+#include "bfa_port.h"
+#include "bfi.h"
+#include "bfa_ioc.h"
+
 
 BFA_TRC_FILE(CNA, PORT);
 
 #define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
-#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
 
 static void
-bfa_port_stats_swap(struct bfa_port_s *port, union bfa_pport_stats_u *stats)
+bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats)
 {
-	u32       *dip = (u32 *) stats;
-	u32        t0, t1;
-	int             i;
+	u32    *dip = (u32 *) stats;
+	u32    t0, t1;
+	int	    i;
 
-	for (i = 0; i < sizeof(union bfa_pport_stats_u) / sizeof(u32);
-	     i += 2) {
+	for (i = 0; i < sizeof(union bfa_port_stats_u)/sizeof(u32);
+		i += 2) {
 		t0 = dip[i];
 		t1 = dip[i + 1];
 #ifdef __BIGENDIAN
@@ -49,11 +44,6 @@
 		dip[i + 1] = bfa_os_ntohl(t0);
 #endif
 	}
-
-    /** todo
-     * QoS stats r also swapped as 64bit; that structure also
-     * has to use 64 bit counters
-     */
 }
 
 /**
@@ -68,7 +58,9 @@
 static void
 bfa_port_enable_isr(struct bfa_port_s *port, bfa_status_t status)
 {
-	bfa_assert(0);
+	bfa_trc(port, status);
+	port->endis_pending = BFA_FALSE;
+	port->endis_cbfn(port->endis_cbarg, status);
 }
 
 /**
@@ -83,7 +75,9 @@
 static void
 bfa_port_disable_isr(struct bfa_port_s *port, bfa_status_t status)
 {
-	bfa_assert(0);
+	bfa_trc(port, status);
+	port->endis_pending = BFA_FALSE;
+	port->endis_cbfn(port->endis_cbarg, status);
 }
 
 /**
@@ -105,7 +99,7 @@
 		struct bfa_timeval_s tv;
 
 		memcpy(port->stats, port->stats_dma.kva,
-		       sizeof(union bfa_pport_stats_u));
+		       sizeof(union bfa_port_stats_u));
 		bfa_port_stats_swap(port, port->stats);
 
 		bfa_os_gettimeofday(&tv);
@@ -133,11 +127,11 @@
 	struct bfa_timeval_s tv;
 
 	port->stats_status = status;
-	port->stats_busy = BFA_FALSE;
+	port->stats_busy   = BFA_FALSE;
 
 	/**
-	 * re-initialize time stamp for stats reset
-	 */
+	* re-initialize time stamp for stats reset
+	*/
 	bfa_os_gettimeofday(&tv);
 	port->stats_reset_time = tv.tv_sec;
 
@@ -158,10 +152,10 @@
 static void
 bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m)
 {
-	struct bfa_port_s *port = (struct bfa_port_s *)cbarg;
+	struct bfa_port_s *port = (struct bfa_port_s *) cbarg;
 	union bfi_port_i2h_msg_u *i2hmsg;
 
-	i2hmsg = (union bfi_port_i2h_msg_u *)m;
+	i2hmsg = (union bfi_port_i2h_msg_u *) m;
 	bfa_trc(port, m->mh.msg_id);
 
 	switch (m->mh.msg_id) {
@@ -178,9 +172,7 @@
 		break;
 
 	case BFI_PORT_I2H_GET_STATS_RSP:
-		/*
-		 * Stats busy flag is still set? (may be cmd timed out)
-		 */
+		/* Stats busy flag is still set? (may be cmd timed out) */
 		if (port->stats_busy == BFA_FALSE)
 			break;
 		bfa_port_get_stats_isr(port, i2hmsg->getstats_rsp.status);
@@ -208,7 +200,7 @@
 u32
 bfa_port_meminfo(void)
 {
-	return BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), BFA_DMA_ALIGN_SZ);
+	return BFA_ROUNDUP(sizeof(union bfa_port_stats_u), BFA_DMA_ALIGN_SZ);
 }
 
 /**
@@ -216,8 +208,8 @@
  *
  *
  * @param[in] port Port module pointer
- * 	      dma_kva Kernel Virtual Address of Port DMA Memory
- * 	      dma_pa  Physical Address of Port DMA Memory
+ *	      dma_kva Kernel Virtual Address of Port DMA Memory
+ *	      dma_pa  Physical Address of Port DMA Memory
  *
  * @return void
  */
@@ -225,7 +217,7 @@
 bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, u64 dma_pa)
 {
 	port->stats_dma.kva = dma_kva;
-	port->stats_dma.pa = dma_pa;
+	port->stats_dma.pa  = dma_pa;
 }
 
 /**
@@ -239,12 +231,14 @@
  */
 bfa_status_t
 bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
-		void *cbarg)
+		 void *cbarg)
 {
 	struct bfi_port_generic_req_s *m;
 
-	/** todo Not implemented */
-	bfa_assert(0);
+	if (bfa_ioc_is_disabled(port->ioc)) {
+		bfa_trc(port, BFA_STATUS_IOC_DISABLED);
+		return BFA_STATUS_IOC_DISABLED;
+	}
 
 	if (!bfa_ioc_is_operational(port->ioc)) {
 		bfa_trc(port, BFA_STATUS_IOC_FAILURE);
@@ -256,11 +250,11 @@
 		return BFA_STATUS_DEVBUSY;
 	}
 
-	m = (struct bfi_port_generic_req_s *)port->endis_mb.msg;
+	m = (struct bfi_port_generic_req_s *) port->endis_mb.msg;
 
 	port->msgtag++;
-	port->endis_cbfn = cbfn;
-	port->endis_cbarg = cbarg;
+	port->endis_cbfn    = cbfn;
+	port->endis_cbarg   = cbarg;
 	port->endis_pending = BFA_TRUE;
 
 	bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_ENABLE_REQ,
@@ -281,12 +275,14 @@
  */
 bfa_status_t
 bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
-		 void *cbarg)
+		  void *cbarg)
 {
 	struct bfi_port_generic_req_s *m;
 
-	/** todo Not implemented */
-	bfa_assert(0);
+	if (bfa_ioc_is_disabled(port->ioc)) {
+		bfa_trc(port, BFA_STATUS_IOC_DISABLED);
+		return BFA_STATUS_IOC_DISABLED;
+	}
 
 	if (!bfa_ioc_is_operational(port->ioc)) {
 		bfa_trc(port, BFA_STATUS_IOC_FAILURE);
@@ -298,11 +294,11 @@
 		return BFA_STATUS_DEVBUSY;
 	}
 
-	m = (struct bfi_port_generic_req_s *)port->endis_mb.msg;
+	m = (struct bfi_port_generic_req_s *) port->endis_mb.msg;
 
 	port->msgtag++;
-	port->endis_cbfn = cbfn;
-	port->endis_cbarg = cbarg;
+	port->endis_cbfn    = cbfn;
+	port->endis_cbarg   = cbarg;
 	port->endis_pending = BFA_TRUE;
 
 	bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_DISABLE_REQ,
@@ -322,8 +318,8 @@
  * @return Status
  */
 bfa_status_t
-bfa_port_get_stats(struct bfa_port_s *port, union bfa_pport_stats_u *stats,
-		   bfa_port_stats_cbfn_t cbfn, void *cbarg)
+bfa_port_get_stats(struct bfa_port_s *port, union bfa_port_stats_u *stats,
+		    bfa_port_stats_cbfn_t cbfn, void *cbarg)
 {
 	struct bfi_port_get_stats_req_s *m;
 
@@ -337,12 +333,12 @@
 		return BFA_STATUS_DEVBUSY;
 	}
 
-	m = (struct bfi_port_get_stats_req_s *)port->stats_mb.msg;
+	m = (struct bfi_port_get_stats_req_s *) port->stats_mb.msg;
 
-	port->stats = stats;
-	port->stats_cbfn = cbfn;
+	port->stats	  = stats;
+	port->stats_cbfn  = cbfn;
 	port->stats_cbarg = cbarg;
-	port->stats_busy = BFA_TRUE;
+	port->stats_busy  = BFA_TRUE;
 	bfa_dma_be_addr_set(m->dma_addr, port->stats_dma.pa);
 
 	bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_GET_STATS_REQ,
@@ -362,7 +358,7 @@
  */
 bfa_status_t
 bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,
-		     void *cbarg)
+		      void *cbarg)
 {
 	struct bfi_port_generic_req_s *m;
 
@@ -376,11 +372,11 @@
 		return BFA_STATUS_DEVBUSY;
 	}
 
-	m = (struct bfi_port_generic_req_s *)port->stats_mb.msg;
+	m = (struct bfi_port_generic_req_s *) port->stats_mb.msg;
 
-	port->stats_cbfn = cbfn;
+	port->stats_cbfn  = cbfn;
 	port->stats_cbarg = cbarg;
-	port->stats_busy = BFA_TRUE;
+	port->stats_busy  = BFA_TRUE;
 
 	bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_CLEAR_STATS_REQ,
 		    bfa_ioc_portid(port->ioc));
@@ -400,11 +396,9 @@
 void
 bfa_port_hbfail(void *arg)
 {
-	struct bfa_port_s *port = (struct bfa_port_s *)arg;
+	struct bfa_port_s *port = (struct bfa_port_s *) arg;
 
-	/*
-	 * Fail any pending get_stats/clear_stats requests
-	 */
+	/* Fail any pending get_stats/clear_stats requests */
 	if (port->stats_busy) {
 		if (port->stats_cbfn)
 			port->stats_cbfn(port->stats_cbarg, BFA_STATUS_FAILED);
@@ -412,9 +406,7 @@
 		port->stats_busy = BFA_FALSE;
 	}
 
-	/*
-	 * Clear any enable/disable is pending
-	 */
+	/* Clear any enable/disable is pending */
 	if (port->endis_pending) {
 		if (port->endis_cbfn)
 			port->endis_cbfn(port->endis_cbarg, BFA_STATUS_FAILED);
@@ -433,22 +425,20 @@
  *                   The device driver specific mbox ISR functions have
  *                   this pointer as one of the parameters.
  *            trcmod -
- *            logmod -
  *
  * @return void
  */
 void
-bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, void *dev,
-		struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
+bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
+		 void *dev, struct bfa_trc_mod_s *trcmod)
 {
 	struct bfa_timeval_s tv;
 
 	bfa_assert(port);
 
-	port->dev = dev;
-	port->ioc = ioc;
+	port->dev    = dev;
+	port->ioc    = ioc;
 	port->trcmod = trcmod;
-	port->logmod = logmod;
 
 	port->stats_busy = BFA_FALSE;
 	port->endis_pending = BFA_FALSE;
diff --git a/drivers/scsi/bfa/bfa_port.h b/drivers/scsi/bfa/bfa_port.h
new file mode 100644
index 0000000..dbce9df
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_port.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_PORT_H__
+#define __BFA_PORT_H__
+
+#include "bfa_defs_svc.h"
+#include "bfa_ioc.h"
+#include "bfa_cs.h"
+
+typedef void (*bfa_port_stats_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_port_endis_cbfn_t) (void *dev, bfa_status_t status);
+
+struct bfa_port_s {
+	void				*dev;
+	struct bfa_ioc_s		*ioc;
+	struct bfa_trc_mod_s		*trcmod;
+	u32			msgtag;
+	bfa_boolean_t			stats_busy;
+	struct bfa_mbox_cmd_s		stats_mb;
+	bfa_port_stats_cbfn_t		stats_cbfn;
+	void				*stats_cbarg;
+	bfa_status_t			stats_status;
+	u32			stats_reset_time;
+	union bfa_port_stats_u		*stats;
+	struct bfa_dma_s		stats_dma;
+	bfa_boolean_t			endis_pending;
+	struct bfa_mbox_cmd_s		endis_mb;
+	bfa_port_endis_cbfn_t		endis_cbfn;
+	void				*endis_cbarg;
+	bfa_status_t			endis_status;
+	struct bfa_ioc_hbfail_notify_s	hbfail;
+};
+
+void	     bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
+				void *dev, struct bfa_trc_mod_s *trcmod);
+void	     bfa_port_detach(struct bfa_port_s *port);
+void	     bfa_port_hbfail(void *arg);
+
+bfa_status_t bfa_port_get_stats(struct bfa_port_s *port,
+				 union bfa_port_stats_u *stats,
+				 bfa_port_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_port_clear_stats(struct bfa_port_s *port,
+				   bfa_port_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_port_enable(struct bfa_port_s *port,
+			      bfa_port_endis_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_port_disable(struct bfa_port_s *port,
+			       bfa_port_endis_cbfn_t cbfn, void *cbarg);
+u32     bfa_port_meminfo(void);
+void	     bfa_port_mem_claim(struct bfa_port_s *port,
+				 u8 *dma_kva, u64 dma_pa);
+#endif	/* __BFA_PORT_H__ */
diff --git a/drivers/scsi/bfa/bfa_port_priv.h b/drivers/scsi/bfa/bfa_port_priv.h
deleted file mode 100644
index c9ebe04..0000000
--- a/drivers/scsi/bfa/bfa_port_priv.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_PORT_PRIV_H__
-#define __BFA_PORT_PRIV_H__
-
-#include <defs/bfa_defs_pport.h>
-#include <bfi/bfi_pport.h>
-#include "bfa_intr_priv.h"
-
-/**
- * Link notification data structure
- */
-struct bfa_fcport_ln_s {
-	struct bfa_fcport_s     *fcport;
-	bfa_sm_t                sm;
-	struct bfa_cb_qe_s      ln_qe;  /*  BFA callback queue elem for ln */
-	enum bfa_pport_linkstate ln_event; /*  ln event for callback */
-};
-
-/**
- * BFA FC port data structure
- */
-struct bfa_fcport_s {
-	struct bfa_s 		*bfa;	/*  parent BFA instance */
-	bfa_sm_t		sm;	/*  port state machine */
-	wwn_t			nwwn;	/*  node wwn of physical port */
-	wwn_t			pwwn;	/*  port wwn of physical oprt */
-	enum bfa_pport_speed speed_sup;
-					/*  supported speeds */
-	enum bfa_pport_speed speed;	/*  current speed */
-	enum bfa_pport_topology topology;	/*  current topology */
-	u8			myalpa;	/*  my ALPA in LOOP topology */
-	u8			rsvd[3];
-	u32             mypid:24;
-	u32             rsvd_b:8;
-	struct bfa_pport_cfg_s	cfg;	/*  current port configuration */
-	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
-	struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
-	struct bfa_reqq_wait_s	reqq_wait;
-					/*  to wait for room in reqq */
-	struct bfa_reqq_wait_s	svcreq_wait;
-					/*  to wait for room in reqq */
-	struct bfa_reqq_wait_s	stats_reqq_wait;
-					/*  to wait for room in reqq (stats) */
-	void			*event_cbarg;
-	void			(*event_cbfn) (void *cbarg,
-						bfa_pport_event_t event);
-	union {
-		union bfi_fcport_i2h_msg_u i2hmsg;
-	} event_arg;
-	void			*bfad;	/*  BFA driver handle */
-	struct bfa_fcport_ln_s   ln; /* Link Notification */
-	struct bfa_cb_qe_s		hcb_qe;	/*  BFA callback queue elem */
-	struct bfa_timer_s      timer;  /*  timer */
-	u32		msgtag;	/*  fimrware msg tag for reply */
-	u8			*stats_kva;
-	u64		stats_pa;
-	union bfa_fcport_stats_u *stats;
-	union bfa_fcport_stats_u *stats_ret; /*  driver stats location */
-	bfa_status_t            stats_status; /*  stats/statsclr status */
-	bfa_boolean_t           stats_busy; /*  outstanding stats/statsclr */
-	bfa_boolean_t           stats_qfull;
-	u32                	stats_reset_time; /* stats reset time stamp */
-	bfa_cb_pport_t          stats_cbfn; /*  driver callback function */
-	void                    *stats_cbarg; /* user callback arg */
-	bfa_boolean_t           diag_busy; /*  diag busy status */
-	bfa_boolean_t           beacon; /*  port beacon status */
-	bfa_boolean_t           link_e2e_beacon; /*  link beacon status */
-};
-
-#define BFA_FCPORT_MOD(__bfa)	(&(__bfa)->modules.fcport)
-
-/*
- * public functions
- */
-void bfa_fcport_init(struct bfa_s *bfa);
-void bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-
-#endif /* __BFA_PORT_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_priv.h b/drivers/scsi/bfa/bfa_priv.h
deleted file mode 100644
index bf4939b..0000000
--- a/drivers/scsi/bfa/bfa_priv.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_PRIV_H__
-#define __BFA_PRIV_H__
-
-#include "bfa_iocfc.h"
-#include "bfa_intr_priv.h"
-#include "bfa_trcmod_priv.h"
-#include "bfa_modules_priv.h"
-#include "bfa_fwimg_priv.h"
-#include <cs/bfa_log.h>
-#include <bfa_timer.h>
-
-/**
- * Macro to define a new BFA module
- */
-#define BFA_MODULE(__mod) 						\
-	static void bfa_ ## __mod ## _meminfo(				\
-			struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,	\
-			u32 *dm_len);      \
-	static void bfa_ ## __mod ## _attach(struct bfa_s *bfa,		\
-			void *bfad, struct bfa_iocfc_cfg_s *cfg, 	\
-			struct bfa_meminfo_s *meminfo,			\
-			struct bfa_pcidev_s *pcidev);      \
-	static void bfa_ ## __mod ## _detach(struct bfa_s *bfa);      \
-	static void bfa_ ## __mod ## _start(struct bfa_s *bfa);      \
-	static void bfa_ ## __mod ## _stop(struct bfa_s *bfa);      \
-	static void bfa_ ## __mod ## _iocdisable(struct bfa_s *bfa);      \
-									\
-	extern struct bfa_module_s hal_mod_ ## __mod;			\
-	struct bfa_module_s hal_mod_ ## __mod = {			\
-		bfa_ ## __mod ## _meminfo,				\
-		bfa_ ## __mod ## _attach,				\
-		bfa_ ## __mod ## _detach,				\
-		bfa_ ## __mod ## _start,				\
-		bfa_ ## __mod ## _stop,					\
-		bfa_ ## __mod ## _iocdisable,				\
-	}
-
-#define BFA_CACHELINE_SZ	(256)
-
-/**
- * Structure used to interact between different BFA sub modules
- *
- * Each sub module needs to implement only the entry points relevant to it (and
- * can leave entry points as NULL)
- */
-struct bfa_module_s {
-	void (*meminfo) (struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-			u32 *dm_len);
-	void (*attach) (struct bfa_s *bfa, void *bfad,
-			struct bfa_iocfc_cfg_s *cfg,
-			struct bfa_meminfo_s *meminfo,
-			struct bfa_pcidev_s *pcidev);
-	void (*detach) (struct bfa_s *bfa);
-	void (*start) (struct bfa_s *bfa);
-	void (*stop) (struct bfa_s *bfa);
-	void (*iocdisable) (struct bfa_s *bfa);
-};
-
-extern struct bfa_module_s *hal_mods[];
-
-struct bfa_s {
-	void			*bfad;		/*  BFA driver instance    */
-	struct bfa_aen_s	*aen;		/*  AEN module		    */
-	struct bfa_plog_s	*plog;		/*  portlog buffer	    */
-	struct bfa_log_mod_s	*logm;		/*  driver logging modulen */
-	struct bfa_trc_mod_s	*trcmod;	/*  driver tracing	    */
-	struct bfa_ioc_s	ioc;		/*  IOC module		    */
-	struct bfa_iocfc_s	iocfc;		/*  IOCFC module	    */
-	struct bfa_timer_mod_s	timer_mod;	/*  timer module	    */
-	struct bfa_modules_s	modules;	/*  BFA modules	    */
-	struct list_head	comp_q;		/*  pending completions    */
-	bfa_boolean_t		rme_process;	/*  RME processing enabled */
-	struct list_head		reqq_waitq[BFI_IOC_MAX_CQS];
-	bfa_boolean_t		fcs;		/*  FCS is attached to BFA */
-	struct bfa_msix_s	msix;
-};
-
-extern bfa_isr_func_t bfa_isrs[BFI_MC_MAX];
-extern bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[];
-extern bfa_boolean_t bfa_auto_recover;
-extern struct bfa_module_s hal_mod_flash;
-extern struct bfa_module_s hal_mod_fcdiag;
-extern struct bfa_module_s hal_mod_sgpg;
-extern struct bfa_module_s hal_mod_fcport;
-extern struct bfa_module_s hal_mod_fcxp;
-extern struct bfa_module_s hal_mod_lps;
-extern struct bfa_module_s hal_mod_uf;
-extern struct bfa_module_s hal_mod_rport;
-extern struct bfa_module_s hal_mod_fcpim;
-extern struct bfa_module_s hal_mod_pbind;
-
-#endif /* __BFA_PRIV_H__ */
-
diff --git a/drivers/scsi/bfa/bfa_rport.c b/drivers/scsi/bfa/bfa_rport.c
deleted file mode 100644
index ccd0680..0000000
--- a/drivers/scsi/bfa/bfa_rport.c
+++ /dev/null
@@ -1,906 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_rport.h>
-#include "bfa_intr_priv.h"
-
-BFA_TRC_FILE(HAL, RPORT);
-BFA_MODULE(rport);
-
-#define bfa_rport_offline_cb(__rp) do {				\
-	if ((__rp)->bfa->fcs)						\
-		bfa_cb_rport_offline((__rp)->rport_drv);      \
-	else {								\
-		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
-				__bfa_cb_rport_offline, (__rp));      \
-	}								\
-} while (0)
-
-#define bfa_rport_online_cb(__rp) do {				\
-	if ((__rp)->bfa->fcs)						\
-		bfa_cb_rport_online((__rp)->rport_drv);      \
-	else {								\
-		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
-				  __bfa_cb_rport_online, (__rp));      \
-		}							\
-} while (0)
-
-/*
- * forward declarations
- */
-static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
-static void bfa_rport_free(struct bfa_rport_s *rport);
-static bfa_boolean_t bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
-static bfa_boolean_t bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
-static bfa_boolean_t bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
-static void __bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete);
-
-/**
- *  bfa_rport_sm BFA rport state machine
- */
-
-
-enum bfa_rport_event {
-	BFA_RPORT_SM_CREATE	= 1,	/*  rport create event		*/
-	BFA_RPORT_SM_DELETE	= 2,	/*  deleting an existing rport */
-	BFA_RPORT_SM_ONLINE	= 3,	/*  rport is online		*/
-	BFA_RPORT_SM_OFFLINE	= 4,	/*  rport is offline		*/
-	BFA_RPORT_SM_FWRSP	= 5,	/*  firmware response		*/
-	BFA_RPORT_SM_HWFAIL	= 6,	/*  IOC h/w failure		*/
-	BFA_RPORT_SM_QOS_SCN	= 7,	/*  QoS SCN from firmware	*/
-	BFA_RPORT_SM_SET_SPEED	= 8,	/*  Set Rport Speed 		*/
-	BFA_RPORT_SM_QRESUME	= 9,	/*  space in requeue queue	*/
-};
-
-static void	bfa_rport_sm_uninit(struct bfa_rport_s *rp,
-					enum bfa_rport_event event);
-static void	bfa_rport_sm_created(struct bfa_rport_s *rp,
-					 enum bfa_rport_event event);
-static void	bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_online(struct bfa_rport_s *rp,
-					enum bfa_rport_event event);
-static void	bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_offline(struct bfa_rport_s *rp,
-					 enum bfa_rport_event event);
-static void	bfa_rport_sm_deleting(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
-					    enum bfa_rport_event event);
-static void	bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-
-/**
- * Beginning state, only online event expected.
- */
-static void
-bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_CREATE:
-		bfa_stats(rp, sm_un_cr);
-		bfa_sm_set_state(rp, bfa_rport_sm_created);
-		break;
-
-	default:
-		bfa_stats(rp, sm_un_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-static void
-bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_ONLINE:
-		bfa_stats(rp, sm_cr_on);
-		if (bfa_rport_send_fwcreate(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_cr_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_cr_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		break;
-
-	default:
-		bfa_stats(rp, sm_cr_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Waiting for rport create response from firmware.
- */
-static void
-bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_FWRSP:
-		bfa_stats(rp, sm_fwc_rsp);
-		bfa_sm_set_state(rp, bfa_rport_sm_online);
-		bfa_rport_online_cb(rp);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_fwc_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
-		break;
-
-	case BFA_RPORT_SM_OFFLINE:
-		bfa_stats(rp, sm_fwc_off);
-		bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_fwc_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		break;
-
-	default:
-		bfa_stats(rp, sm_fwc_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Request queue is full, awaiting queue resume to send create request.
- */
-static void
-bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_QRESUME:
-		bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
-		bfa_rport_send_fwcreate(rp);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_fwc_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_reqq_wcancel(&rp->reqq_wait);
-		bfa_rport_free(rp);
-		break;
-
-	case BFA_RPORT_SM_OFFLINE:
-		bfa_stats(rp, sm_fwc_off);
-		bfa_sm_set_state(rp, bfa_rport_sm_offline);
-		bfa_reqq_wcancel(&rp->reqq_wait);
-		bfa_rport_offline_cb(rp);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_fwc_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		bfa_reqq_wcancel(&rp->reqq_wait);
-		break;
-
-	default:
-		bfa_stats(rp, sm_fwc_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Online state - normal parking state.
- */
-static void
-bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	struct bfi_rport_qos_scn_s *qos_scn;
-
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_OFFLINE:
-		bfa_stats(rp, sm_on_off);
-		if (bfa_rport_send_fwdelete(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_on_del);
-		if (bfa_rport_send_fwdelete(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_on_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		break;
-
-	case BFA_RPORT_SM_SET_SPEED:
-		bfa_rport_send_fwspeed(rp);
-		break;
-
-	case BFA_RPORT_SM_QOS_SCN:
-		qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
-		rp->qos_attr = qos_scn->new_qos_attr;
-		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
-		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
-		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
-		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
-
-		qos_scn->old_qos_attr.qos_flow_id  =
-			bfa_os_ntohl(qos_scn->old_qos_attr.qos_flow_id);
-		qos_scn->new_qos_attr.qos_flow_id  =
-			bfa_os_ntohl(qos_scn->new_qos_attr.qos_flow_id);
-		qos_scn->old_qos_attr.qos_priority =
-			bfa_os_ntohl(qos_scn->old_qos_attr.qos_priority);
-		qos_scn->new_qos_attr.qos_priority =
-			bfa_os_ntohl(qos_scn->new_qos_attr.qos_priority);
-
-		if (qos_scn->old_qos_attr.qos_flow_id !=
-			qos_scn->new_qos_attr.qos_flow_id)
-			bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
-						    qos_scn->old_qos_attr,
-						    qos_scn->new_qos_attr);
-		if (qos_scn->old_qos_attr.qos_priority !=
-			qos_scn->new_qos_attr.qos_priority)
-			bfa_cb_rport_qos_scn_prio(rp->rport_drv,
-						  qos_scn->old_qos_attr,
-						  qos_scn->new_qos_attr);
-		break;
-
-	default:
-		bfa_stats(rp, sm_on_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Firmware rport is being deleted - awaiting f/w response.
- */
-static void
-bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_FWRSP:
-		bfa_stats(rp, sm_fwd_rsp);
-		bfa_sm_set_state(rp, bfa_rport_sm_offline);
-		bfa_rport_offline_cb(rp);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_fwd_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_fwd_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		bfa_rport_offline_cb(rp);
-		break;
-
-	default:
-		bfa_stats(rp, sm_fwd_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-static void
-bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_QRESUME:
-		bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
-		bfa_rport_send_fwdelete(rp);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_fwd_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_fwd_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		bfa_reqq_wcancel(&rp->reqq_wait);
-		bfa_rport_offline_cb(rp);
-		break;
-
-	default:
-		bfa_stats(rp, sm_fwd_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Offline state.
- */
-static void
-bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_off_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	case BFA_RPORT_SM_ONLINE:
-		bfa_stats(rp, sm_off_on);
-		if (bfa_rport_send_fwcreate(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_off_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		break;
-
-	default:
-		bfa_stats(rp, sm_off_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Rport is deleted, waiting for firmware response to delete.
- */
-static void
-bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_FWRSP:
-		bfa_stats(rp, sm_del_fwrsp);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_del_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	default:
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-static void
-bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_QRESUME:
-		bfa_stats(rp, sm_del_fwrsp);
-		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
-		bfa_rport_send_fwdelete(rp);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_del_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_reqq_wcancel(&rp->reqq_wait);
-		bfa_rport_free(rp);
-		break;
-
-	default:
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Waiting for rport create response from firmware. A delete is pending.
- */
-static void
-bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
-				enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_FWRSP:
-		bfa_stats(rp, sm_delp_fwrsp);
-		if (bfa_rport_send_fwdelete(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_delp_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	default:
-		bfa_stats(rp, sm_delp_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Waiting for rport create response from firmware. Rport offline is pending.
- */
-static void
-bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
-				 enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_FWRSP:
-		bfa_stats(rp, sm_offp_fwrsp);
-		if (bfa_rport_send_fwdelete(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_offp_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_offp_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		break;
-
-	default:
-		bfa_stats(rp, sm_offp_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * IOC h/w failed.
- */
-static void
-bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_OFFLINE:
-		bfa_stats(rp, sm_iocd_off);
-		bfa_rport_offline_cb(rp);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_iocd_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	case BFA_RPORT_SM_ONLINE:
-		bfa_stats(rp, sm_iocd_on);
-		if (bfa_rport_send_fwcreate(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		break;
-
-	default:
-		bfa_stats(rp, sm_iocd_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-
-
-/**
- *  bfa_rport_private BFA rport private functions
- */
-
-static void
-__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_rport_s *rp = cbarg;
-
-	if (complete)
-		bfa_cb_rport_online(rp->rport_drv);
-}
-
-static void
-__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_rport_s *rp = cbarg;
-
-	if (complete)
-		bfa_cb_rport_offline(rp->rport_drv);
-}
-
-static void
-bfa_rport_qresume(void *cbarg)
-{
-	struct bfa_rport_s	*rp = cbarg;
-
-	bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
-}
-
-static void
-bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
-{
-	if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
-		cfg->fwcfg.num_rports = BFA_RPORT_MIN;
-
-	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
-}
-
-static void
-bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		     struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
-	struct bfa_rport_s *rp;
-	u16        i;
-
-	INIT_LIST_HEAD(&mod->rp_free_q);
-	INIT_LIST_HEAD(&mod->rp_active_q);
-
-	rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
-	mod->rps_list = rp;
-	mod->num_rports = cfg->fwcfg.num_rports;
-
-	bfa_assert(mod->num_rports
-		   && !(mod->num_rports & (mod->num_rports - 1)));
-
-	for (i = 0; i < mod->num_rports; i++, rp++) {
-		bfa_os_memset(rp, 0, sizeof(struct bfa_rport_s));
-		rp->bfa = bfa;
-		rp->rport_tag = i;
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-
-		/**
-		 *  - is unused
-		 */
-		if (i)
-			list_add_tail(&rp->qe, &mod->rp_free_q);
-
-		bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
-	}
-
-	/**
-	 * consume memory
-	 */
-	bfa_meminfo_kva(meminfo) = (u8 *) rp;
-}
-
-static void
-bfa_rport_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_rport_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_rport_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_rport_iocdisable(struct bfa_s *bfa)
-{
-	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
-	struct bfa_rport_s *rport;
-	struct list_head        *qe, *qen;
-
-	list_for_each_safe(qe, qen, &mod->rp_active_q) {
-		rport = (struct bfa_rport_s *) qe;
-		bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
-	}
-}
-
-static struct bfa_rport_s *
-bfa_rport_alloc(struct bfa_rport_mod_s *mod)
-{
-	struct bfa_rport_s *rport;
-
-	bfa_q_deq(&mod->rp_free_q, &rport);
-	if (rport)
-		list_add_tail(&rport->qe, &mod->rp_active_q);
-
-	return rport;
-}
-
-static void
-bfa_rport_free(struct bfa_rport_s *rport)
-{
-	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
-
-	bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport));
-	list_del(&rport->qe);
-	list_add_tail(&rport->qe, &mod->rp_free_q);
-}
-
-static bfa_boolean_t
-bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
-{
-	struct bfi_rport_create_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
-	if (!m) {
-		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
-			bfa_lpuid(rp->bfa));
-	m->bfa_handle = rp->rport_tag;
-	m->max_frmsz = bfa_os_htons(rp->rport_info.max_frmsz);
-	m->pid = rp->rport_info.pid;
-	m->lp_tag = rp->rport_info.lp_tag;
-	m->local_pid = rp->rport_info.local_pid;
-	m->fc_class = rp->rport_info.fc_class;
-	m->vf_en = rp->rport_info.vf_en;
-	m->vf_id = rp->rport_info.vf_id;
-	m->cisc = rp->rport_info.cisc;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
-	return BFA_TRUE;
-}
-
-static bfa_boolean_t
-bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
-{
-	struct bfi_rport_delete_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
-	if (!m) {
-		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
-			bfa_lpuid(rp->bfa));
-	m->fw_handle = rp->fw_handle;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
-	return BFA_TRUE;
-}
-
-static bfa_boolean_t
-bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
-{
-	struct bfa_rport_speed_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
-	if (!m) {
-		bfa_trc(rp->bfa, rp->rport_info.speed);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
-			bfa_lpuid(rp->bfa));
-	m->fw_handle = rp->fw_handle;
-	m->speed = (u8)rp->rport_info.speed;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
-	return BFA_TRUE;
-}
-
-
-
-/**
- *  bfa_rport_public
- */
-
-/**
- * 		Rport interrupt processing.
- */
-void
-bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	union bfi_rport_i2h_msg_u msg;
-	struct bfa_rport_s *rp;
-
-	bfa_trc(bfa, m->mhdr.msg_id);
-
-	msg.msg = m;
-
-	switch (m->mhdr.msg_id) {
-	case BFI_RPORT_I2H_CREATE_RSP:
-		rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
-		rp->fw_handle = msg.create_rsp->fw_handle;
-		rp->qos_attr = msg.create_rsp->qos_attr;
-		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
-		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
-		break;
-
-	case BFI_RPORT_I2H_DELETE_RSP:
-		rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
-		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
-		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
-		break;
-
-	case BFI_RPORT_I2H_QOS_SCN:
-		rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
-		rp->event_arg.fw_msg = msg.qos_scn_evt;
-		bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
-		break;
-
-	default:
-		bfa_trc(bfa, m->mhdr.msg_id);
-		bfa_assert(0);
-	}
-}
-
-
-
-/**
- *  bfa_rport_api
- */
-
-struct bfa_rport_s *
-bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
-{
-	struct bfa_rport_s *rp;
-
-	rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
-
-	if (rp == NULL)
-		return NULL;
-
-	rp->bfa = bfa;
-	rp->rport_drv = rport_drv;
-	bfa_rport_clear_stats(rp);
-
-	bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
-	bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
-
-	return rp;
-}
-
-void
-bfa_rport_delete(struct bfa_rport_s *rport)
-{
-	bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE);
-}
-
-void
-bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
-{
-	bfa_assert(rport_info->max_frmsz != 0);
-
-	/**
-	 * Some JBODs are seen to be not setting PDU size correctly in PLOGI
-	 * responses. Default to minimum size.
-	 */
-	if (rport_info->max_frmsz == 0) {
-		bfa_trc(rport->bfa, rport->rport_tag);
-		rport_info->max_frmsz = FC_MIN_PDUSZ;
-	}
-
-	bfa_os_assign(rport->rport_info, *rport_info);
-	bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
-}
-
-void
-bfa_rport_offline(struct bfa_rport_s *rport)
-{
-	bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE);
-}
-
-void
-bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_pport_speed speed)
-{
-	bfa_assert(speed != 0);
-	bfa_assert(speed != BFA_PPORT_SPEED_AUTO);
-
-	rport->rport_info.speed = speed;
-	bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
-}
-
-void
-bfa_rport_get_stats(struct bfa_rport_s *rport,
-	struct bfa_rport_hal_stats_s *stats)
-{
-	*stats = rport->stats;
-}
-
-void
-bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
-					struct bfa_rport_qos_attr_s *qos_attr)
-{
-	qos_attr->qos_priority  = bfa_os_ntohl(rport->qos_attr.qos_priority);
-	qos_attr->qos_flow_id  = bfa_os_ntohl(rport->qos_attr.qos_flow_id);
-
-}
-
-void
-bfa_rport_clear_stats(struct bfa_rport_s *rport)
-{
-	bfa_os_memset(&rport->stats, 0, sizeof(rport->stats));
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_rport_priv.h b/drivers/scsi/bfa/bfa_rport_priv.h
deleted file mode 100644
index 6490ce2..0000000
--- a/drivers/scsi/bfa/bfa_rport_priv.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_RPORT_PRIV_H__
-#define __BFA_RPORT_PRIV_H__
-
-#include <bfa_svc.h>
-
-#define BFA_RPORT_MIN	4
-
-struct bfa_rport_mod_s {
-	struct bfa_rport_s *rps_list;	/*  list of rports	*/
-	struct list_head 	rp_free_q;	/*  free bfa_rports	*/
-	struct list_head 	rp_active_q;	/*  free bfa_rports 	*/
-	u16	num_rports;	/*  number of rports	*/
-};
-
-#define BFA_RPORT_MOD(__bfa)	(&(__bfa)->modules.rport_mod)
-
-/**
- * Convert rport tag to RPORT
- */
-#define BFA_RPORT_FROM_TAG(__bfa, _tag)				\
-	(BFA_RPORT_MOD(__bfa)->rps_list +				\
-	 ((_tag) & (BFA_RPORT_MOD(__bfa)->num_rports - 1)))
-
-/*
- * external functions
- */
-void	bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-#endif /* __BFA_RPORT_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_sgpg.c b/drivers/scsi/bfa/bfa_sgpg.c
deleted file mode 100644
index ae452c4..0000000
--- a/drivers/scsi/bfa/bfa_sgpg.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-
-BFA_TRC_FILE(HAL, SGPG);
-BFA_MODULE(sgpg);
-
-/**
- *  bfa_sgpg_mod BFA SGPG Mode module
- */
-
-/**
- * Compute and return memory needed by FCP(im) module.
- */
-static void
-bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
-{
-	if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
-		cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
-
-	*km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
-	*dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
-}
-
-
-static void
-bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		    struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_sgpg_mod_s	*mod = BFA_SGPG_MOD(bfa);
-	int				i;
-	struct bfa_sgpg_s		*hsgpg;
-	struct bfi_sgpg_s 	*sgpg;
-	u64		align_len;
-
-	union {
-		u64        pa;
-		union bfi_addr_u      addr;
-	} sgpg_pa;
-
-	INIT_LIST_HEAD(&mod->sgpg_q);
-	INIT_LIST_HEAD(&mod->sgpg_wait_q);
-
-	bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
-
-	mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
-	mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
-	align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
-	mod->sgpg_arr_pa += align_len;
-	mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
-						align_len);
-	mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
-						align_len);
-
-	hsgpg = mod->hsgpg_arr;
-	sgpg = mod->sgpg_arr;
-	sgpg_pa.pa = mod->sgpg_arr_pa;
-	mod->free_sgpgs = mod->num_sgpgs;
-
-	bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));
-
-	for (i = 0; i < mod->num_sgpgs; i++) {
-		bfa_os_memset(hsgpg, 0, sizeof(*hsgpg));
-		bfa_os_memset(sgpg, 0, sizeof(*sgpg));
-
-		hsgpg->sgpg = sgpg;
-		hsgpg->sgpg_pa = sgpg_pa.addr;
-		list_add_tail(&hsgpg->qe, &mod->sgpg_q);
-
-		hsgpg++;
-		sgpg++;
-		sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
-	}
-
-	bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
-	bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
-	bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
-}
-
-static void
-bfa_sgpg_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_sgpg_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_sgpg_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_sgpg_iocdisable(struct bfa_s *bfa)
-{
-}
-
-
-
-/**
- *  bfa_sgpg_public BFA SGPG public functions
- */
-
-bfa_status_t
-bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
-{
-	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
-	struct bfa_sgpg_s *hsgpg;
-	int             i;
-
-	bfa_trc_fp(bfa, nsgpgs);
-
-	if (mod->free_sgpgs < nsgpgs)
-		return BFA_STATUS_ENOMEM;
-
-	for (i = 0; i < nsgpgs; i++) {
-		bfa_q_deq(&mod->sgpg_q, &hsgpg);
-		bfa_assert(hsgpg);
-		list_add_tail(&hsgpg->qe, sgpg_q);
-	}
-
-	mod->free_sgpgs -= nsgpgs;
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
-{
-	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
-	struct bfa_sgpg_wqe_s *wqe;
-
-	bfa_trc_fp(bfa, nsgpg);
-
-	mod->free_sgpgs += nsgpg;
-	bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);
-
-	list_splice_tail_init(sgpg_q, &mod->sgpg_q);
-
-	if (list_empty(&mod->sgpg_wait_q))
-		return;
-
-	/**
-	 * satisfy as many waiting requests as possible
-	 */
-	do {
-		wqe = bfa_q_first(&mod->sgpg_wait_q);
-		if (mod->free_sgpgs < wqe->nsgpg)
-			nsgpg = mod->free_sgpgs;
-		else
-			nsgpg = wqe->nsgpg;
-		bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
-		wqe->nsgpg -= nsgpg;
-		if (wqe->nsgpg == 0) {
-			list_del(&wqe->qe);
-			wqe->cbfn(wqe->cbarg);
-		}
-	} while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
-}
-
-void
-bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
-{
-	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
-
-	bfa_assert(nsgpg > 0);
-	bfa_assert(nsgpg > mod->free_sgpgs);
-
-	wqe->nsgpg_total = wqe->nsgpg = nsgpg;
-
-	/**
-	 * allocate any left to this one first
-	 */
-	if (mod->free_sgpgs) {
-		/**
-		 * no one else is waiting for SGPG
-		 */
-		bfa_assert(list_empty(&mod->sgpg_wait_q));
-		list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
-		wqe->nsgpg -= mod->free_sgpgs;
-		mod->free_sgpgs = 0;
-	}
-
-	list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
-}
-
-void
-bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
-{
-	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
-
-	bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
-	list_del(&wqe->qe);
-
-	if (wqe->nsgpg_total != wqe->nsgpg)
-		bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
-				   wqe->nsgpg_total - wqe->nsgpg);
-}
-
-void
-bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
-		   void *cbarg)
-{
-	INIT_LIST_HEAD(&wqe->sgpg_q);
-	wqe->cbfn = cbfn;
-	wqe->cbarg = cbarg;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_sgpg_priv.h b/drivers/scsi/bfa/bfa_sgpg_priv.h
deleted file mode 100644
index 9c2a8cb..0000000
--- a/drivers/scsi/bfa/bfa_sgpg_priv.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  hal_sgpg.h BFA SG page module
- */
-
-#ifndef __BFA_SGPG_PRIV_H__
-#define __BFA_SGPG_PRIV_H__
-
-#include <cs/bfa_q.h>
-
-#define BFA_SGPG_MIN	(16)
-
-/**
- * Alignment macro for SG page allocation
- */
-#define BFA_SGPG_ROUNDUP(_l) (((_l) + (sizeof(struct bfi_sgpg_s) - 1)) \
-			& ~(sizeof(struct bfi_sgpg_s) - 1))
-
-struct bfa_sgpg_wqe_s {
-	struct list_head qe;	/*  queue sg page element	*/
-	int	nsgpg;		/*  pages to be allocated	*/
-	int	nsgpg_total;	/*  total pages required	*/
-	void	(*cbfn) (void *cbarg);
-				/*  callback function		*/
-	void	*cbarg;		/*  callback arg		*/
-	struct list_head sgpg_q;	/*  queue of alloced sgpgs	*/
-};
-
-struct bfa_sgpg_s {
-	struct list_head 	qe;	/*  queue sg page element	*/
-	struct bfi_sgpg_s *sgpg; /*  va of SG page		*/
-	union bfi_addr_u sgpg_pa;/*  pa of SG page		*/
-};
-
-/**
- * Given number of SG elements, BFA_SGPG_NPAGE() returns the number of
- * SG pages required.
- */
-#define BFA_SGPG_NPAGE(_nsges)  (((_nsges) / BFI_SGPG_DATA_SGES) + 1)
-
-struct bfa_sgpg_mod_s {
-	struct bfa_s *bfa;
-	int		num_sgpgs;	/*  number of SG pages		*/
-	int		free_sgpgs;	/*  number of free SG pages	*/
-	struct bfa_sgpg_s *hsgpg_arr;	/*  BFA SG page array	*/
-	struct bfi_sgpg_s *sgpg_arr;	/*  actual SG page array	*/
-	u64	sgpg_arr_pa;	/*  SG page array DMA addr	*/
-	struct list_head sgpg_q;	/*  queue of free SG pages	*/
-	struct list_head sgpg_wait_q; /*  wait queue for SG pages	*/
-};
-#define BFA_SGPG_MOD(__bfa)	(&(__bfa)->modules.sgpg_mod)
-
-bfa_status_t	bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q,
-								int nsgpgs);
-void		bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q,
-								int nsgpgs);
-void		bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe,
-				   void (*cbfn) (void *cbarg), void *cbarg);
-void		bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe,
-								int nsgpgs);
-void		bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe);
-
-#endif /* __BFA_SGPG_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_sm.c b/drivers/scsi/bfa/bfa_sm.c
deleted file mode 100644
index 5420f4f..0000000
--- a/drivers/scsi/bfa/bfa_sm.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfasm.c BFA State machine utility functions
- */
-
-#include <cs/bfa_sm.h>
-
-/**
- *  cs_sm_api
- */
-
-int
-bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm)
-{
-	int             i = 0;
-
-	while (smt[i].sm && smt[i].sm != sm)
-		i++;
-	return smt[i].state;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
new file mode 100644
index 0000000..aa1dc74
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -0,0 +1,5423 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include "bfa_os_inc.h"
+#include "bfa_plog.h"
+#include "bfa_cs.h"
+#include "bfa_modules.h"
+#include "bfad_drv.h"
+
+BFA_TRC_FILE(HAL, FCXP);
+BFA_MODULE(fcxp);
+BFA_MODULE(sgpg);
+BFA_MODULE(lps);
+BFA_MODULE(fcport);
+BFA_MODULE(rport);
+BFA_MODULE(uf);
+
+/**
+ * LPS related definitions
+ */
+#define BFA_LPS_MIN_LPORTS      (1)
+#define BFA_LPS_MAX_LPORTS      (256)
+
+/*
+ * Maximum Vports supported per physical port or vf.
+ */
+#define BFA_LPS_MAX_VPORTS_SUPP_CB  255
+#define BFA_LPS_MAX_VPORTS_SUPP_CT  190
+
+/**
+ *  lps_pvt BFA LPS private functions
+ */
+
+enum bfa_lps_event {
+	BFA_LPS_SM_LOGIN	= 1,	/* login request from user	*/
+	BFA_LPS_SM_LOGOUT	= 2,	/* logout request from user	*/
+	BFA_LPS_SM_FWRSP	= 3,	/* f/w response to login/logout	*/
+	BFA_LPS_SM_RESUME	= 4,	/* space present in reqq queue	*/
+	BFA_LPS_SM_DELETE	= 5,	/* lps delete from user		*/
+	BFA_LPS_SM_OFFLINE	= 6,	/* Link is offline		*/
+	BFA_LPS_SM_RX_CVL	= 7,	/* Rx clear virtual link	*/
+};
+
+/**
+ * FC PORT related definitions
+ */
+/*
+ * The port is considered disabled if corresponding physical port or IOC are
+ * disabled explicitly
+ */
+#define BFA_PORT_IS_DISABLED(bfa) \
+	((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
+	(bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
+
+
+/**
+ * BFA port state machine events
+ */
+enum bfa_fcport_sm_event {
+	BFA_FCPORT_SM_START	= 1,	/*  start port state machine	*/
+	BFA_FCPORT_SM_STOP	= 2,	/*  stop port state machine	*/
+	BFA_FCPORT_SM_ENABLE	= 3,	/*  enable port		*/
+	BFA_FCPORT_SM_DISABLE	= 4,	/*  disable port state machine */
+	BFA_FCPORT_SM_FWRSP	= 5,	/*  firmware enable/disable rsp */
+	BFA_FCPORT_SM_LINKUP	= 6,	/*  firmware linkup event	*/
+	BFA_FCPORT_SM_LINKDOWN	= 7,	/*  firmware linkup down	*/
+	BFA_FCPORT_SM_QRESUME	= 8,	/*  CQ space available	*/
+	BFA_FCPORT_SM_HWFAIL	= 9,	/*  IOC h/w failure		*/
+};
+
+/**
+ * BFA port link notification state machine events
+ */
+
+enum bfa_fcport_ln_sm_event {
+	BFA_FCPORT_LN_SM_LINKUP		= 1,	/*  linkup event	*/
+	BFA_FCPORT_LN_SM_LINKDOWN	= 2,	/*  linkdown event	*/
+	BFA_FCPORT_LN_SM_NOTIFICATION	= 3	/*  done notification	*/
+};
+
+/**
+ * RPORT related definitions
+ */
+#define bfa_rport_offline_cb(__rp) do {					\
+	if ((__rp)->bfa->fcs)						\
+		bfa_cb_rport_offline((__rp)->rport_drv);      \
+	else {								\
+		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
+				__bfa_cb_rport_offline, (__rp));      \
+	}								\
+} while (0)
+
+#define bfa_rport_online_cb(__rp) do {					\
+	if ((__rp)->bfa->fcs)						\
+		bfa_cb_rport_online((__rp)->rport_drv);      \
+	else {								\
+		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
+				  __bfa_cb_rport_online, (__rp));      \
+		}							\
+} while (0)
+
+
+enum bfa_rport_event {
+	BFA_RPORT_SM_CREATE	= 1,	/*  rport create event		*/
+	BFA_RPORT_SM_DELETE	= 2,	/*  deleting an existing rport	*/
+	BFA_RPORT_SM_ONLINE	= 3,	/*  rport is online		*/
+	BFA_RPORT_SM_OFFLINE	= 4,	/*  rport is offline		*/
+	BFA_RPORT_SM_FWRSP	= 5,	/*  firmware response		*/
+	BFA_RPORT_SM_HWFAIL	= 6,	/*  IOC h/w failure		*/
+	BFA_RPORT_SM_QOS_SCN	= 7,	/*  QoS SCN from firmware	*/
+	BFA_RPORT_SM_SET_SPEED	= 8,	/*  Set Rport Speed		*/
+	BFA_RPORT_SM_QRESUME	= 9,	/*  space in requeue queue	*/
+};
+
+/**
+ * forward declarations FCXP related functions
+ */
+static void	__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
+static void	hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
+				struct bfi_fcxp_send_rsp_s *fcxp_rsp);
+static void	hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
+				struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
+static void	bfa_fcxp_qresume(void *cbarg);
+static void	bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
+				struct bfi_fcxp_send_req_s *send_req);
+
+/**
+ * forward declarations for LPS functions
+ */
+static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+				u32 *dm_len);
+static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
+				struct bfa_iocfc_cfg_s *cfg,
+				struct bfa_meminfo_s *meminfo,
+				struct bfa_pcidev_s *pcidev);
+static void bfa_lps_detach(struct bfa_s *bfa);
+static void bfa_lps_start(struct bfa_s *bfa);
+static void bfa_lps_stop(struct bfa_s *bfa);
+static void bfa_lps_iocdisable(struct bfa_s *bfa);
+static void bfa_lps_login_rsp(struct bfa_s *bfa,
+				struct bfi_lps_login_rsp_s *rsp);
+static void bfa_lps_logout_rsp(struct bfa_s *bfa,
+				struct bfi_lps_logout_rsp_s *rsp);
+static void bfa_lps_reqq_resume(void *lps_arg);
+static void bfa_lps_free(struct bfa_lps_s *lps);
+static void bfa_lps_send_login(struct bfa_lps_s *lps);
+static void bfa_lps_send_logout(struct bfa_lps_s *lps);
+static void bfa_lps_login_comp(struct bfa_lps_s *lps);
+static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
+static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
+
+/**
+ * forward declaration for LPS state machine
+ */
+static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
+					event);
+static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
+					event);
+
+/**
+ * forward declaration for FC Port functions
+ */
+static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
+static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
+static void bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
+static void bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
+static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
+static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
+static void bfa_fcport_scn(struct bfa_fcport_s *fcport,
+			enum bfa_port_linkstate event, bfa_boolean_t trunk);
+static void bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
+				enum bfa_port_linkstate event);
+static void __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
+static void bfa_fcport_stats_get_timeout(void *cbarg);
+static void bfa_fcport_stats_clr_timeout(void *cbarg);
+static void bfa_trunk_iocdisable(struct bfa_s *bfa);
+
+/**
+ * forward declaration for FC PORT state machine
+ */
+static void     bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+
+static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+
+static struct bfa_sm_table_s hal_port_sm_table[] = {
+	{BFA_SM(bfa_fcport_sm_uninit), BFA_PORT_ST_UNINIT},
+	{BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PORT_ST_ENABLING_QWAIT},
+	{BFA_SM(bfa_fcport_sm_enabling), BFA_PORT_ST_ENABLING},
+	{BFA_SM(bfa_fcport_sm_linkdown), BFA_PORT_ST_LINKDOWN},
+	{BFA_SM(bfa_fcport_sm_linkup), BFA_PORT_ST_LINKUP},
+	{BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PORT_ST_DISABLING_QWAIT},
+	{BFA_SM(bfa_fcport_sm_toggling_qwait), BFA_PORT_ST_TOGGLING_QWAIT},
+	{BFA_SM(bfa_fcport_sm_disabling), BFA_PORT_ST_DISABLING},
+	{BFA_SM(bfa_fcport_sm_disabled), BFA_PORT_ST_DISABLED},
+	{BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
+	{BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
+	{BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
+};
+
+
+/**
+ * forward declaration for RPORT related functions
+ */
+static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
+static void		bfa_rport_free(struct bfa_rport_s *rport);
+static bfa_boolean_t	bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
+static bfa_boolean_t	bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
+static bfa_boolean_t	bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
+static void		__bfa_cb_rport_online(void *cbarg,
+						bfa_boolean_t complete);
+static void		__bfa_cb_rport_offline(void *cbarg,
+						bfa_boolean_t complete);
+
+/**
+ * forward declaration for RPORT state machine
+ */
+static void     bfa_rport_sm_uninit(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_created(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_online(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_offline(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_deleting(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+
+/**
+ * PLOG related definitions
+ */
+static int
+plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
+{
+	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
+		(pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
+		return 1;
+
+	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
+		(pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
+		return 1;
+
+	return 0;
+}
+
+static void
+bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
+{
+	u16 tail;
+	struct bfa_plog_rec_s *pl_recp;
+
+	if (plog->plog_enabled == 0)
+		return;
+
+	if (plkd_validate_logrec(pl_rec)) {
+		bfa_assert(0);
+		return;
+	}
+
+	tail = plog->tail;
+
+	pl_recp = &(plog->plog_recs[tail]);
+
+	bfa_os_memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
+
+	pl_recp->tv = bfa_os_get_log_time();
+	BFA_PL_LOG_REC_INCR(plog->tail);
+
+	if (plog->head == plog->tail)
+		BFA_PL_LOG_REC_INCR(plog->head);
+}
+
+void
+bfa_plog_init(struct bfa_plog_s *plog)
+{
+	bfa_os_memset((char *)plog, 0, sizeof(struct bfa_plog_s));
+
+	bfa_os_memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
+	plog->head = plog->tail = 0;
+	plog->plog_enabled = 1;
+}
+
+void
+bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+		enum bfa_plog_eid event,
+		u16 misc, char *log_str)
+{
+	struct bfa_plog_rec_s  lp;
+
+	if (plog->plog_enabled) {
+		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+		lp.mid = mid;
+		lp.eid = event;
+		lp.log_type = BFA_PL_LOG_TYPE_STRING;
+		lp.misc = misc;
+		strncpy(lp.log_entry.string_log, log_str,
+			BFA_PL_STRING_LOG_SZ - 1);
+		lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
+		bfa_plog_add(plog, &lp);
+	}
+}
+
+void
+bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+		enum bfa_plog_eid event,
+		u16 misc, u32 *intarr, u32 num_ints)
+{
+	struct bfa_plog_rec_s  lp;
+	u32 i;
+
+	if (num_ints > BFA_PL_INT_LOG_SZ)
+		num_ints = BFA_PL_INT_LOG_SZ;
+
+	if (plog->plog_enabled) {
+		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+		lp.mid = mid;
+		lp.eid = event;
+		lp.log_type = BFA_PL_LOG_TYPE_INT;
+		lp.misc = misc;
+
+		for (i = 0; i < num_ints; i++)
+			bfa_os_assign(lp.log_entry.int_log[i],
+					intarr[i]);
+
+		lp.log_num_ints = (u8) num_ints;
+
+		bfa_plog_add(plog, &lp);
+	}
+}
+
+void
+bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+			enum bfa_plog_eid event,
+			u16 misc, struct fchs_s *fchdr)
+{
+	struct bfa_plog_rec_s  lp;
+	u32	*tmp_int = (u32 *) fchdr;
+	u32	ints[BFA_PL_INT_LOG_SZ];
+
+	if (plog->plog_enabled) {
+		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+
+		ints[0] = tmp_int[0];
+		ints[1] = tmp_int[1];
+		ints[2] = tmp_int[4];
+
+		bfa_plog_intarr(plog, mid, event, misc, ints, 3);
+	}
+}
+
+void
+bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+		      enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
+		      u32 pld_w0)
+{
+	struct bfa_plog_rec_s  lp;
+	u32	*tmp_int = (u32 *) fchdr;
+	u32	ints[BFA_PL_INT_LOG_SZ];
+
+	if (plog->plog_enabled) {
+		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+
+		ints[0] = tmp_int[0];
+		ints[1] = tmp_int[1];
+		ints[2] = tmp_int[4];
+		ints[3] = pld_w0;
+
+		bfa_plog_intarr(plog, mid, event, misc, ints, 4);
+	}
+}
+
+void
+bfa_plog_clear(struct bfa_plog_s *plog)
+{
+	plog->head = plog->tail = 0;
+}
+
+void
+bfa_plog_enable(struct bfa_plog_s *plog)
+{
+	plog->plog_enabled = 1;
+}
+
+void
+bfa_plog_disable(struct bfa_plog_s *plog)
+{
+	plog->plog_enabled = 0;
+}
+
+bfa_boolean_t
+bfa_plog_get_setting(struct bfa_plog_s *plog)
+{
+	return (bfa_boolean_t)plog->plog_enabled;
+}
+
+/**
+ *  fcxp_pvt BFA FCXP private functions
+ */
+
+static void
+claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
+{
+	u8	       *dm_kva = NULL;
+	u64	dm_pa;
+	u32	buf_pool_sz;
+
+	dm_kva = bfa_meminfo_dma_virt(mi);
+	dm_pa = bfa_meminfo_dma_phys(mi);
+
+	buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
+
+	/*
+	 * Initialize the fcxp req payload list
+	 */
+	mod->req_pld_list_kva = dm_kva;
+	mod->req_pld_list_pa = dm_pa;
+	dm_kva += buf_pool_sz;
+	dm_pa += buf_pool_sz;
+	bfa_os_memset(mod->req_pld_list_kva, 0, buf_pool_sz);
+
+	/*
+	 * Initialize the fcxp rsp payload list
+	 */
+	buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
+	mod->rsp_pld_list_kva = dm_kva;
+	mod->rsp_pld_list_pa = dm_pa;
+	dm_kva += buf_pool_sz;
+	dm_pa += buf_pool_sz;
+	bfa_os_memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
+
+	bfa_meminfo_dma_virt(mi) = dm_kva;
+	bfa_meminfo_dma_phys(mi) = dm_pa;
+}
+
+static void
+claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
+{
+	u16	i;
+	struct bfa_fcxp_s *fcxp;
+
+	fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
+	bfa_os_memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
+
+	INIT_LIST_HEAD(&mod->fcxp_free_q);
+	INIT_LIST_HEAD(&mod->fcxp_active_q);
+
+	mod->fcxp_list = fcxp;
+
+	for (i = 0; i < mod->num_fcxps; i++) {
+		fcxp->fcxp_mod = mod;
+		fcxp->fcxp_tag = i;
+
+		list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+		bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
+		fcxp->reqq_waiting = BFA_FALSE;
+
+		fcxp = fcxp + 1;
+	}
+
+	bfa_meminfo_kva(mi) = (void *)fcxp;
+}
+
+static void
+bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+		 u32 *dm_len)
+{
+	u16	num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
+
+	if (num_fcxp_reqs == 0)
+		return;
+
+	/*
+	 * Account for req/rsp payload
+	 */
+	*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
+	if (cfg->drvcfg.min_cfg)
+		*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
+	else
+		*dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
+
+	/*
+	 * Account for fcxp structs
+	 */
+	*ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
+}
+
+static void
+bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+	bfa_os_memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
+	mod->bfa = bfa;
+	mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
+
+	/**
+	 * Initialize FCXP request and response payload sizes.
+	 */
+	mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
+	if (!cfg->drvcfg.min_cfg)
+		mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
+
+	INIT_LIST_HEAD(&mod->wait_q);
+
+	claim_fcxp_req_rsp_mem(mod, meminfo);
+	claim_fcxps_mem(mod, meminfo);
+}
+
+static void
+bfa_fcxp_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+	struct bfa_fcxp_s *fcxp;
+	struct list_head	      *qe, *qen;
+
+	list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
+		fcxp = (struct bfa_fcxp_s *) qe;
+		if (fcxp->caller == NULL) {
+			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+					BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
+			bfa_fcxp_free(fcxp);
+		} else {
+			fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
+			bfa_cb_queue(bfa, &fcxp->hcb_qe,
+				     __bfa_fcxp_send_cbfn, fcxp);
+		}
+	}
+}
+
+static struct bfa_fcxp_s *
+bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
+{
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_q_deq(&fm->fcxp_free_q, &fcxp);
+
+	if (fcxp)
+		list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
+
+	return fcxp;
+}
+
+static void
+bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
+	       struct bfa_s *bfa,
+	       u8 *use_ibuf,
+	       u32 *nr_sgles,
+	       bfa_fcxp_get_sgaddr_t *r_sga_cbfn,
+	       bfa_fcxp_get_sglen_t *r_sglen_cbfn,
+	       struct list_head *r_sgpg_q,
+	       int n_sgles,
+	       bfa_fcxp_get_sgaddr_t sga_cbfn,
+	       bfa_fcxp_get_sglen_t sglen_cbfn)
+{
+
+	bfa_assert(bfa != NULL);
+
+	bfa_trc(bfa, fcxp->fcxp_tag);
+
+	if (n_sgles == 0) {
+		*use_ibuf = 1;
+	} else {
+		bfa_assert(*sga_cbfn != NULL);
+		bfa_assert(*sglen_cbfn != NULL);
+
+		*use_ibuf = 0;
+		*r_sga_cbfn = sga_cbfn;
+		*r_sglen_cbfn = sglen_cbfn;
+
+		*nr_sgles = n_sgles;
+
+		/*
+		 * alloc required sgpgs
+		 */
+		if (n_sgles > BFI_SGE_INLINE)
+			bfa_assert(0);
+	}
+
+}
+
+static void
+bfa_fcxp_init(struct bfa_fcxp_s *fcxp,
+	       void *caller, struct bfa_s *bfa, int nreq_sgles,
+	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
+	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+{
+
+	bfa_assert(bfa != NULL);
+
+	bfa_trc(bfa, fcxp->fcxp_tag);
+
+	fcxp->caller = caller;
+
+	bfa_fcxp_init_reqrsp(fcxp, bfa,
+		&fcxp->use_ireqbuf, &fcxp->nreq_sgles, &fcxp->req_sga_cbfn,
+		&fcxp->req_sglen_cbfn, &fcxp->req_sgpg_q,
+		nreq_sgles, req_sga_cbfn, req_sglen_cbfn);
+
+	bfa_fcxp_init_reqrsp(fcxp, bfa,
+		&fcxp->use_irspbuf, &fcxp->nrsp_sgles, &fcxp->rsp_sga_cbfn,
+		&fcxp->rsp_sglen_cbfn, &fcxp->rsp_sgpg_q,
+		nrsp_sgles, rsp_sga_cbfn, rsp_sglen_cbfn);
+
+}
+
+static void
+bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
+{
+	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+	struct bfa_fcxp_wqe_s *wqe;
+
+	bfa_q_deq(&mod->wait_q, &wqe);
+	if (wqe) {
+		bfa_trc(mod->bfa, fcxp->fcxp_tag);
+
+		bfa_fcxp_init(fcxp, wqe->caller, wqe->bfa, wqe->nreq_sgles,
+			wqe->nrsp_sgles, wqe->req_sga_cbfn,
+			wqe->req_sglen_cbfn, wqe->rsp_sga_cbfn,
+			wqe->rsp_sglen_cbfn);
+
+		wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
+		return;
+	}
+
+	bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
+	list_del(&fcxp->qe);
+	list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+}
+
+static void
+bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
+		   bfa_status_t req_status, u32 rsp_len,
+		   u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	/* discarded fcxp completion */
+}
+
+static void
+__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_fcxp_s *fcxp = cbarg;
+
+	if (complete) {
+		fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+				fcxp->rsp_status, fcxp->rsp_len,
+				fcxp->residue_len, &fcxp->rsp_fchs);
+	} else {
+		bfa_fcxp_free(fcxp);
+	}
+}
+
+static void
+hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
+{
+	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);
+	struct bfa_fcxp_s	*fcxp;
+	u16		fcxp_tag = bfa_os_ntohs(fcxp_rsp->fcxp_tag);
+
+	bfa_trc(bfa, fcxp_tag);
+
+	fcxp_rsp->rsp_len = bfa_os_ntohl(fcxp_rsp->rsp_len);
+
+	/**
+	 * @todo f/w should not set residue to non-0 when everything
+	 *	 is received.
+	 */
+	if (fcxp_rsp->req_status == BFA_STATUS_OK)
+		fcxp_rsp->residue_len = 0;
+	else
+		fcxp_rsp->residue_len = bfa_os_ntohl(fcxp_rsp->residue_len);
+
+	fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
+
+	bfa_assert(fcxp->send_cbfn != NULL);
+
+	hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
+
+	if (fcxp->send_cbfn != NULL) {
+		bfa_trc(mod->bfa, (NULL == fcxp->caller));
+		if (fcxp->caller == NULL) {
+			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+					fcxp_rsp->req_status, fcxp_rsp->rsp_len,
+					fcxp_rsp->residue_len, &fcxp_rsp->fchs);
+			/*
+			 * fcxp automatically freed on return from the callback
+			 */
+			bfa_fcxp_free(fcxp);
+		} else {
+			fcxp->rsp_status = fcxp_rsp->req_status;
+			fcxp->rsp_len = fcxp_rsp->rsp_len;
+			fcxp->residue_len = fcxp_rsp->residue_len;
+			fcxp->rsp_fchs = fcxp_rsp->fchs;
+
+			bfa_cb_queue(bfa, &fcxp->hcb_qe,
+					__bfa_fcxp_send_cbfn, fcxp);
+		}
+	} else {
+		bfa_trc(bfa, (NULL == fcxp->send_cbfn));
+	}
+}
+
+static void
+hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
+{
+	union bfi_addr_u      sga_zero = { {0} };
+
+	sge->sg_len = reqlen;
+	sge->flags = BFI_SGE_DATA_LAST;
+	bfa_dma_addr_set(sge[0].sga, req_pa);
+	bfa_sge_to_be(sge);
+	sge++;
+
+	sge->sga = sga_zero;
+	sge->sg_len = reqlen;
+	sge->flags = BFI_SGE_PGDLEN;
+	bfa_sge_to_be(sge);
+}
+
+static void
+hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
+		 struct fchs_s *fchs)
+{
+	/*
+	 * TODO: TX ox_id
+	 */
+	if (reqlen > 0) {
+		if (fcxp->use_ireqbuf) {
+			u32	pld_w0 =
+				*((u32 *) BFA_FCXP_REQ_PLD(fcxp));
+
+			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
+					BFA_PL_EID_TX,
+					reqlen + sizeof(struct fchs_s), fchs,
+					pld_w0);
+		} else {
+			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
+					BFA_PL_EID_TX,
+					reqlen + sizeof(struct fchs_s),
+					fchs);
+		}
+	} else {
+		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
+			       reqlen + sizeof(struct fchs_s), fchs);
+	}
+}
+
+static void
+hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
+		 struct bfi_fcxp_send_rsp_s *fcxp_rsp)
+{
+	if (fcxp_rsp->rsp_len > 0) {
+		if (fcxp->use_irspbuf) {
+			u32	pld_w0 =
+				*((u32 *) BFA_FCXP_RSP_PLD(fcxp));
+
+			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
+					      BFA_PL_EID_RX,
+					      (u16) fcxp_rsp->rsp_len,
+					      &fcxp_rsp->fchs, pld_w0);
+		} else {
+			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
+				       BFA_PL_EID_RX,
+				       (u16) fcxp_rsp->rsp_len,
+				       &fcxp_rsp->fchs);
+		}
+	} else {
+		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
+			       (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
+	}
+}
+
+/**
+ * Handler to resume sending fcxp when space in available in cpe queue.
+ */
+static void
+bfa_fcxp_qresume(void *cbarg)
+{
+	struct bfa_fcxp_s		*fcxp = cbarg;
+	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;
+	struct bfi_fcxp_send_req_s	*send_req;
+
+	fcxp->reqq_waiting = BFA_FALSE;
+	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
+	bfa_fcxp_queue(fcxp, send_req);
+}
+
+/**
+ * Queue fcxp send request to foimrware.
+ */
+static void
+bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
+{
+	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;
+	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
+	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
+	struct bfa_rport_s		*rport = reqi->bfa_rport;
+
+	bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
+		    bfa_lpuid(bfa));
+
+	send_req->fcxp_tag = bfa_os_htons(fcxp->fcxp_tag);
+	if (rport) {
+		send_req->rport_fw_hndl = rport->fw_handle;
+		send_req->max_frmsz = bfa_os_htons(rport->rport_info.max_frmsz);
+		if (send_req->max_frmsz == 0)
+			send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
+	} else {
+		send_req->rport_fw_hndl = 0;
+		send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
+	}
+
+	send_req->vf_id = bfa_os_htons(reqi->vf_id);
+	send_req->lp_tag = reqi->lp_tag;
+	send_req->class = reqi->class;
+	send_req->rsp_timeout = rspi->rsp_timeout;
+	send_req->cts = reqi->cts;
+	send_req->fchs = reqi->fchs;
+
+	send_req->req_len = bfa_os_htonl(reqi->req_tot_len);
+	send_req->rsp_maxlen = bfa_os_htonl(rspi->rsp_maxlen);
+
+	/*
+	 * setup req sgles
+	 */
+	if (fcxp->use_ireqbuf == 1) {
+		hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
+					BFA_FCXP_REQ_PLD_PA(fcxp));
+	} else {
+		if (fcxp->nreq_sgles > 0) {
+			bfa_assert(fcxp->nreq_sgles == 1);
+			hal_fcxp_set_local_sges(send_req->req_sge,
+						reqi->req_tot_len,
+						fcxp->req_sga_cbfn(fcxp->caller,
+								   0));
+		} else {
+			bfa_assert(reqi->req_tot_len == 0);
+			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+		}
+	}
+
+	/*
+	 * setup rsp sgles
+	 */
+	if (fcxp->use_irspbuf == 1) {
+		bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
+
+		hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
+					BFA_FCXP_RSP_PLD_PA(fcxp));
+
+	} else {
+		if (fcxp->nrsp_sgles > 0) {
+			bfa_assert(fcxp->nrsp_sgles == 1);
+			hal_fcxp_set_local_sges(send_req->rsp_sge,
+						rspi->rsp_maxlen,
+						fcxp->rsp_sga_cbfn(fcxp->caller,
+								   0));
+		} else {
+			bfa_assert(rspi->rsp_maxlen == 0);
+			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+		}
+	}
+
+	hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
+
+	bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
+
+	bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
+	bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
+}
+
+/**
+ *  hal_fcxp_api BFA FCXP API
+ */
+
+/**
+ * Allocate an FCXP instance to send a response or to send a request
+ * that has a response. Request/response buffers are allocated by caller.
+ *
+ * @param[in]	bfa		BFA bfa instance
+ * @param[in]	nreq_sgles	Number of SG elements required for request
+ *				buffer. 0, if fcxp internal buffers are	used.
+ *				Use bfa_fcxp_get_reqbuf() to get the
+ *				internal req buffer.
+ * @param[in]	req_sgles	SG elements describing request buffer. Will be
+ *				copied in by BFA and hence can be freed on
+ *				return from this function.
+ * @param[in]	get_req_sga	function ptr to be called to get a request SG
+ *				Address (given the sge index).
+ * @param[in]	get_req_sglen	function ptr to be called to get a request SG
+ *				len (given the sge index).
+ * @param[in]	get_rsp_sga	function ptr to be called to get a response SG
+ *				Address (given the sge index).
+ * @param[in]	get_rsp_sglen	function ptr to be called to get a response SG
+ *				len (given the sge index).
+ *
+ * @return FCXP instance. NULL on failure.
+ */
+struct bfa_fcxp_s *
+bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
+	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
+	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+{
+	struct bfa_fcxp_s *fcxp = NULL;
+
+	bfa_assert(bfa != NULL);
+
+	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
+	if (fcxp == NULL)
+		return NULL;
+
+	bfa_trc(bfa, fcxp->fcxp_tag);
+
+	bfa_fcxp_init(fcxp, caller, bfa, nreq_sgles, nrsp_sgles, req_sga_cbfn,
+			req_sglen_cbfn, rsp_sga_cbfn, rsp_sglen_cbfn);
+
+	return fcxp;
+}
+
+/**
+ * Get the internal request buffer pointer
+ *
+ * @param[in]	fcxp	BFA fcxp pointer
+ *
+ * @return		pointer to the internal request buffer
+ */
+void *
+bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
+{
+	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+	void	*reqbuf;
+
+	bfa_assert(fcxp->use_ireqbuf == 1);
+	reqbuf = ((u8 *)mod->req_pld_list_kva) +
+		fcxp->fcxp_tag * mod->req_pld_sz;
+	return reqbuf;
+}
+
+u32
+bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
+{
+	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+
+	return mod->req_pld_sz;
+}
+
+/**
+ * Get the internal response buffer pointer
+ *
+ * @param[in]	fcxp	BFA fcxp pointer
+ *
+ * @return		pointer to the internal request buffer
+ */
+void *
+bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
+{
+	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+	void	*rspbuf;
+
+	bfa_assert(fcxp->use_irspbuf == 1);
+
+	rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
+		fcxp->fcxp_tag * mod->rsp_pld_sz;
+	return rspbuf;
+}
+
+/**
+ *		Free the BFA FCXP
+ *
+ * @param[in]	fcxp			BFA fcxp pointer
+ *
+ * @return		void
+ */
+void
+bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
+{
+	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+
+	bfa_assert(fcxp != NULL);
+	bfa_trc(mod->bfa, fcxp->fcxp_tag);
+	bfa_fcxp_put(fcxp);
+}
+
+/**
+ * Send a FCXP request
+ *
+ * @param[in]	fcxp	BFA fcxp pointer
+ * @param[in]	rport	BFA rport pointer. Could be left NULL for WKA rports
+ * @param[in]	vf_id	virtual Fabric ID
+ * @param[in]	lp_tag	lport tag
+ * @param[in]	cts	use Continous sequence
+ * @param[in]	cos	fc Class of Service
+ * @param[in]	reqlen	request length, does not include FCHS length
+ * @param[in]	fchs	fc Header Pointer. The header content will be copied
+ *			in by BFA.
+ *
+ * @param[in]	cbfn	call back function to be called on receiving
+ *								the response
+ * @param[in]	cbarg	arg for cbfn
+ * @param[in]	rsp_timeout
+ *			response timeout
+ *
+ * @return		bfa_status_t
+ */
+void
+bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
+	      u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
+	      u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
+	      void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
+{
+	struct bfa_s			*bfa  = fcxp->fcxp_mod->bfa;
+	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
+	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
+	struct bfi_fcxp_send_req_s	*send_req;
+
+	bfa_trc(bfa, fcxp->fcxp_tag);
+
+	/**
+	 * setup request/response info
+	 */
+	reqi->bfa_rport = rport;
+	reqi->vf_id = vf_id;
+	reqi->lp_tag = lp_tag;
+	reqi->class = cos;
+	rspi->rsp_timeout = rsp_timeout;
+	reqi->cts = cts;
+	reqi->fchs = *fchs;
+	reqi->req_tot_len = reqlen;
+	rspi->rsp_maxlen = rsp_maxlen;
+	fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
+	fcxp->send_cbarg = cbarg;
+
+	/**
+	 * If no room in CPE queue, wait for space in request queue
+	 */
+	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
+	if (!send_req) {
+		bfa_trc(bfa, fcxp->fcxp_tag);
+		fcxp->reqq_waiting = BFA_TRUE;
+		bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
+		return;
+	}
+
+	bfa_fcxp_queue(fcxp, send_req);
+}
+
+/**
+ * Abort a BFA FCXP
+ *
+ * @param[in]	fcxp	BFA fcxp pointer
+ *
+ * @return		void
+ */
+bfa_status_t
+bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
+{
+	bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
+	bfa_assert(0);
+	return BFA_STATUS_OK;
+}
+
+void
+bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+	       bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
+	       void *caller, int nreq_sgles,
+	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
+	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+{
+	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+	bfa_assert(list_empty(&mod->fcxp_free_q));
+
+	wqe->alloc_cbfn = alloc_cbfn;
+	wqe->alloc_cbarg = alloc_cbarg;
+	wqe->caller = caller;
+	wqe->bfa = bfa;
+	wqe->nreq_sgles = nreq_sgles;
+	wqe->nrsp_sgles = nrsp_sgles;
+	wqe->req_sga_cbfn = req_sga_cbfn;
+	wqe->req_sglen_cbfn = req_sglen_cbfn;
+	wqe->rsp_sga_cbfn = rsp_sga_cbfn;
+	wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
+
+	list_add_tail(&wqe->qe, &mod->wait_q);
+}
+
+void
+bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
+{
+	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+	bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
+	list_del(&wqe->qe);
+}
+
+void
+bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
+{
+	/**
+	 * If waiting for room in request queue, cancel reqq wait
+	 * and free fcxp.
+	 */
+	if (fcxp->reqq_waiting) {
+		fcxp->reqq_waiting = BFA_FALSE;
+		bfa_reqq_wcancel(&fcxp->reqq_wqe);
+		bfa_fcxp_free(fcxp);
+		return;
+	}
+
+	fcxp->send_cbfn = bfa_fcxp_null_comp;
+}
+
+
+
+/**
+ *  hal_fcxp_public BFA FCXP public functions
+ */
+
+void
+bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+	switch (msg->mhdr.msg_id) {
+	case BFI_FCXP_I2H_SEND_RSP:
+		hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
+		break;
+
+	default:
+		bfa_trc(bfa, msg->mhdr.msg_id);
+		bfa_assert(0);
+	}
+}
+
+u32
+bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
+{
+	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+	return mod->rsp_pld_sz;
+}
+
+
+/**
+ *  BFA LPS state machine functions
+ */
+
+/**
+ * Init state -- no login
+ */
+static void
+bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_LOGIN:
+		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
+			bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
+			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
+		} else {
+			bfa_sm_set_state(lps, bfa_lps_sm_login);
+			bfa_lps_send_login(lps);
+		}
+
+		if (lps->fdisc)
+			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+				BFA_PL_EID_LOGIN, 0, "FDISC Request");
+		else
+			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+				BFA_PL_EID_LOGIN, 0, "FLOGI Request");
+		break;
+
+	case BFA_LPS_SM_LOGOUT:
+		bfa_lps_logout_comp(lps);
+		break;
+
+	case BFA_LPS_SM_DELETE:
+		bfa_lps_free(lps);
+		break;
+
+	case BFA_LPS_SM_RX_CVL:
+	case BFA_LPS_SM_OFFLINE:
+		break;
+
+	case BFA_LPS_SM_FWRSP:
+		/*
+		 * Could happen when fabric detects loopback and discards
+		 * the lps request. Fw will eventually sent out the timeout
+		 * Just ignore
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+/**
+ * login is in progress -- awaiting response from firmware
+ */
+static void
+bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_FWRSP:
+		if (lps->status == BFA_STATUS_OK) {
+			bfa_sm_set_state(lps, bfa_lps_sm_online);
+			if (lps->fdisc)
+				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+					BFA_PL_EID_LOGIN, 0, "FDISC Accept");
+			else
+				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+					BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
+		} else {
+			bfa_sm_set_state(lps, bfa_lps_sm_init);
+			if (lps->fdisc)
+				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+					BFA_PL_EID_LOGIN, 0,
+					"FDISC Fail (RJT or timeout)");
+			else
+				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+					BFA_PL_EID_LOGIN, 0,
+					"FLOGI Fail (RJT or timeout)");
+		}
+		bfa_lps_login_comp(lps);
+		break;
+
+	case BFA_LPS_SM_OFFLINE:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+/**
+ * login pending - awaiting space in request queue
+ */
+static void
+bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_RESUME:
+		bfa_sm_set_state(lps, bfa_lps_sm_login);
+		break;
+
+	case BFA_LPS_SM_OFFLINE:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		bfa_reqq_wcancel(&lps->wqe);
+		break;
+
+	case BFA_LPS_SM_RX_CVL:
+		/*
+		 * Login was not even sent out; so when getting out
+		 * of this state, it will appear like a login retry
+		 * after Clear virtual link
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+/**
+ * login complete
+ */
+static void
+bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_LOGOUT:
+		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
+			bfa_sm_set_state(lps, bfa_lps_sm_logowait);
+			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
+		} else {
+			bfa_sm_set_state(lps, bfa_lps_sm_logout);
+			bfa_lps_send_logout(lps);
+		}
+		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+			BFA_PL_EID_LOGO, 0, "Logout");
+		break;
+
+	case BFA_LPS_SM_RX_CVL:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+
+		/* Let the vport module know about this event */
+		bfa_lps_cvl_event(lps);
+		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
+		break;
+
+	case BFA_LPS_SM_OFFLINE:
+	case BFA_LPS_SM_DELETE:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+/**
+ * logout in progress - awaiting firmware response
+ */
+static void
+bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_FWRSP:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		bfa_lps_logout_comp(lps);
+		break;
+
+	case BFA_LPS_SM_OFFLINE:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+/**
+ * logout pending -- awaiting space in request queue
+ */
+static void
+bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_RESUME:
+		bfa_sm_set_state(lps, bfa_lps_sm_logout);
+		bfa_lps_send_logout(lps);
+		break;
+
+	case BFA_LPS_SM_OFFLINE:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		bfa_reqq_wcancel(&lps->wqe);
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+
+
+/**
+ *  lps_pvt BFA LPS private functions
+ */
+
+/**
+ * return memory requirement
+ */
+static void
+bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+	u32 *dm_len)
+{
+	if (cfg->drvcfg.min_cfg)
+		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
+	else
+		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
+}
+
+/**
+ * bfa module attach at initialization time
+ */
+static void
+bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+	struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+	int			i;
+
+	bfa_os_memset(mod, 0, sizeof(struct bfa_lps_mod_s));
+	mod->num_lps = BFA_LPS_MAX_LPORTS;
+	if (cfg->drvcfg.min_cfg)
+		mod->num_lps = BFA_LPS_MIN_LPORTS;
+	else
+		mod->num_lps = BFA_LPS_MAX_LPORTS;
+	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
+
+	bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
+
+	INIT_LIST_HEAD(&mod->lps_free_q);
+	INIT_LIST_HEAD(&mod->lps_active_q);
+
+	for (i = 0; i < mod->num_lps; i++, lps++) {
+		lps->bfa	= bfa;
+		lps->lp_tag	= (u8) i;
+		lps->reqq	= BFA_REQQ_LPS;
+		bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
+		list_add_tail(&lps->qe, &mod->lps_free_q);
+	}
+}
+
+static void
+bfa_lps_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_lps_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_lps_stop(struct bfa_s *bfa)
+{
+}
+
+/**
+ * IOC in disabled state -- consider all lps offline
+ */
+static void
+bfa_lps_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+	struct list_head		*qe, *qen;
+
+	list_for_each_safe(qe, qen, &mod->lps_active_q) {
+		lps = (struct bfa_lps_s *) qe;
+		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
+	}
+}
+
+/**
+ * Firmware login response
+ */
+static void
+bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+
+	bfa_assert(rsp->lp_tag < mod->num_lps);
+	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+
+	lps->status = rsp->status;
+	switch (rsp->status) {
+	case BFA_STATUS_OK:
+		lps->fport	= rsp->f_port;
+		lps->npiv_en	= rsp->npiv_en;
+		lps->lp_pid	= rsp->lp_pid;
+		lps->pr_bbcred	= bfa_os_ntohs(rsp->bb_credit);
+		lps->pr_pwwn	= rsp->port_name;
+		lps->pr_nwwn	= rsp->node_name;
+		lps->auth_req	= rsp->auth_req;
+		lps->lp_mac	= rsp->lp_mac;
+		lps->brcd_switch = rsp->brcd_switch;
+		lps->fcf_mac	= rsp->fcf_mac;
+
+		break;
+
+	case BFA_STATUS_FABRIC_RJT:
+		lps->lsrjt_rsn = rsp->lsrjt_rsn;
+		lps->lsrjt_expl = rsp->lsrjt_expl;
+
+		break;
+
+	case BFA_STATUS_EPROTOCOL:
+		lps->ext_status = rsp->ext_status;
+
+		break;
+
+	default:
+		/* Nothing to do with other status */
+		break;
+	}
+
+	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
+}
+
+/**
+ * Firmware logout response
+ */
+static void
+bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+
+	bfa_assert(rsp->lp_tag < mod->num_lps);
+	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+
+	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
+}
+
+/**
+ * Firmware received a Clear virtual link request (for FCoE)
+ */
+static void
+bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+
+	lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag);
+
+	bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
+}
+
+/**
+ * Space is available in request queue, resume queueing request to firmware.
+ */
+static void
+bfa_lps_reqq_resume(void *lps_arg)
+{
+	struct bfa_lps_s	*lps = lps_arg;
+
+	bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
+}
+
+/**
+ * lps is freed -- triggered by vport delete
+ */
+static void
+bfa_lps_free(struct bfa_lps_s *lps)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);
+
+	lps->lp_pid = 0;
+	list_del(&lps->qe);
+	list_add_tail(&lps->qe, &mod->lps_free_q);
+}
+
+/**
+ * send login request to firmware
+ */
+static void
+bfa_lps_send_login(struct bfa_lps_s *lps)
+{
+	struct bfi_lps_login_req_s	*m;
+
+	m = bfa_reqq_next(lps->bfa, lps->reqq);
+	bfa_assert(m);
+
+	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
+		bfa_lpuid(lps->bfa));
+
+	m->lp_tag	= lps->lp_tag;
+	m->alpa		= lps->alpa;
+	m->pdu_size	= bfa_os_htons(lps->pdusz);
+	m->pwwn		= lps->pwwn;
+	m->nwwn		= lps->nwwn;
+	m->fdisc	= lps->fdisc;
+	m->auth_en	= lps->auth_en;
+
+	bfa_reqq_produce(lps->bfa, lps->reqq);
+}
+
+/**
+ * send logout request to firmware
+ */
+static void
+bfa_lps_send_logout(struct bfa_lps_s *lps)
+{
+	struct bfi_lps_logout_req_s *m;
+
+	m = bfa_reqq_next(lps->bfa, lps->reqq);
+	bfa_assert(m);
+
+	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
+		bfa_lpuid(lps->bfa));
+
+	m->lp_tag    = lps->lp_tag;
+	m->port_name = lps->pwwn;
+	bfa_reqq_produce(lps->bfa, lps->reqq);
+}
+
+/**
+ * Indirect login completion handler for non-fcs
+ */
+static void
+bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
+{
+	struct bfa_lps_s *lps	= arg;
+
+	if (!complete)
+		return;
+
+	if (lps->fdisc)
+		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
+	else
+		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
+}
+
+/**
+ * Login completion handler -- direct call for fcs, queue for others
+ */
+static void
+bfa_lps_login_comp(struct bfa_lps_s *lps)
+{
+	if (!lps->bfa->fcs) {
+		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,
+			lps);
+		return;
+	}
+
+	if (lps->fdisc)
+		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
+	else
+		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
+}
+
+/**
+ * Indirect logout completion handler for non-fcs
+ */
+static void
+bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
+{
+	struct bfa_lps_s *lps	= arg;
+
+	if (!complete)
+		return;
+
+	if (lps->fdisc)
+		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
+}
+
+/**
+ * Logout completion handler -- direct call for fcs, queue for others
+ */
+static void
+bfa_lps_logout_comp(struct bfa_lps_s *lps)
+{
+	if (!lps->bfa->fcs) {
+		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,
+			lps);
+		return;
+	}
+	if (lps->fdisc)
+		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
+}
+
+/**
+ * Clear virtual link completion handler for non-fcs
+ */
+static void
+bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
+{
+	struct bfa_lps_s *lps	= arg;
+
+	if (!complete)
+		return;
+
+	/* Clear virtual link to base port will result in link down */
+	if (lps->fdisc)
+		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
+}
+
+/**
+ * Received Clear virtual link event --direct call for fcs,
+ * queue for others
+ */
+static void
+bfa_lps_cvl_event(struct bfa_lps_s *lps)
+{
+	if (!lps->bfa->fcs) {
+		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
+			lps);
+		return;
+	}
+
+	/* Clear virtual link to base port will result in link down */
+	if (lps->fdisc)
+		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
+}
+
+
+
+/**
+ *  lps_public BFA LPS public functions
+ */
+
+u32
+bfa_lps_get_max_vport(struct bfa_s *bfa)
+{
+	if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
+		return BFA_LPS_MAX_VPORTS_SUPP_CT;
+	else
+		return BFA_LPS_MAX_VPORTS_SUPP_CB;
+}
+
+/**
+ * Allocate a lport srvice tag.
+ */
+struct bfa_lps_s  *
+bfa_lps_alloc(struct bfa_s *bfa)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps = NULL;
+
+	bfa_q_deq(&mod->lps_free_q, &lps);
+
+	if (lps == NULL)
+		return NULL;
+
+	list_add_tail(&lps->qe, &mod->lps_active_q);
+
+	bfa_sm_set_state(lps, bfa_lps_sm_init);
+	return lps;
+}
+
+/**
+ * Free lport service tag. This can be called anytime after an alloc.
+ * No need to wait for any pending login/logout completions.
+ */
+void
+bfa_lps_delete(struct bfa_lps_s *lps)
+{
+	bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
+}
+
+/**
+ * Initiate a lport login.
+ */
+void
+bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
+	wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
+{
+	lps->uarg	= uarg;
+	lps->alpa	= alpa;
+	lps->pdusz	= pdusz;
+	lps->pwwn	= pwwn;
+	lps->nwwn	= nwwn;
+	lps->fdisc	= BFA_FALSE;
+	lps->auth_en	= auth_en;
+	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
+}
+
+/**
+ * Initiate a lport fdisc login.
+ */
+void
+bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
+	wwn_t nwwn)
+{
+	lps->uarg	= uarg;
+	lps->alpa	= 0;
+	lps->pdusz	= pdusz;
+	lps->pwwn	= pwwn;
+	lps->nwwn	= nwwn;
+	lps->fdisc	= BFA_TRUE;
+	lps->auth_en	= BFA_FALSE;
+	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
+}
+
+/**
+ * Initiate a lport logout (flogi).
+ */
+void
+bfa_lps_flogo(struct bfa_lps_s *lps)
+{
+	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
+}
+
+/**
+ * Initiate a lport FDSIC logout.
+ */
+void
+bfa_lps_fdisclogo(struct bfa_lps_s *lps)
+{
+	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
+}
+
+/**
+ * Discard a pending login request -- should be called only for
+ * link down handling.
+ */
+void
+bfa_lps_discard(struct bfa_lps_s *lps)
+{
+	bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
+}
+
+/**
+ * Return lport services tag
+ */
+u8
+bfa_lps_get_tag(struct bfa_lps_s *lps)
+{
+	return lps->lp_tag;
+}
+
+/**
+ * Return lport services tag given the pid
+ */
+u8
+bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+	int			i;
+
+	for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
+		if (lps->lp_pid == pid)
+			return lps->lp_tag;
+	}
+
+	/* Return base port tag anyway */
+	return 0;
+}
+
+/**
+ * return if fabric login indicates support for NPIV
+ */
+bfa_boolean_t
+bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
+{
+	return lps->npiv_en;
+}
+
+/**
+ * Return TRUE if attached to F-Port, else return FALSE
+ */
+bfa_boolean_t
+bfa_lps_is_fport(struct bfa_lps_s *lps)
+{
+	return lps->fport;
+}
+
+/**
+ * Return TRUE if attached to a Brocade Fabric
+ */
+bfa_boolean_t
+bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
+{
+	return lps->brcd_switch;
+}
+/**
+ * return TRUE if authentication is required
+ */
+bfa_boolean_t
+bfa_lps_is_authreq(struct bfa_lps_s *lps)
+{
+	return lps->auth_req;
+}
+
+bfa_eproto_status_t
+bfa_lps_get_extstatus(struct bfa_lps_s *lps)
+{
+	return lps->ext_status;
+}
+
+/**
+ * return port id assigned to the lport
+ */
+u32
+bfa_lps_get_pid(struct bfa_lps_s *lps)
+{
+	return lps->lp_pid;
+}
+
+/**
+ * return port id assigned to the base lport
+ */
+u32
+bfa_lps_get_base_pid(struct bfa_s *bfa)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+
+	return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
+}
+
+/**
+ * Return bb_credit assigned in FLOGI response
+ */
+u16
+bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
+{
+	return lps->pr_bbcred;
+}
+
+/**
+ * Return peer port name
+ */
+wwn_t
+bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
+{
+	return lps->pr_pwwn;
+}
+
+/**
+ * Return peer node name
+ */
+wwn_t
+bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
+{
+	return lps->pr_nwwn;
+}
+
+/**
+ * return reason code if login request is rejected
+ */
+u8
+bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
+{
+	return lps->lsrjt_rsn;
+}
+
+/**
+ * return explanation code if login request is rejected
+ */
+u8
+bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
+{
+	return lps->lsrjt_expl;
+}
+
+/**
+ * Return fpma/spma MAC for lport
+ */
+mac_t
+bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
+{
+	return lps->lp_mac;
+}
+
+/**
+ * LPS firmware message class handler.
+ */
+void
+bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	union bfi_lps_i2h_msg_u	msg;
+
+	bfa_trc(bfa, m->mhdr.msg_id);
+	msg.msg = m;
+
+	switch (m->mhdr.msg_id) {
+	case BFI_LPS_H2I_LOGIN_RSP:
+		bfa_lps_login_rsp(bfa, msg.login_rsp);
+		break;
+
+	case BFI_LPS_H2I_LOGOUT_RSP:
+		bfa_lps_logout_rsp(bfa, msg.logout_rsp);
+		break;
+
+	case BFI_LPS_H2I_CVL_EVENT:
+		bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
+		break;
+
+	default:
+		bfa_trc(bfa, m->mhdr.msg_id);
+		bfa_assert(0);
+	}
+}
+
+/**
+ * FC PORT state machine functions
+ */
+static void
+bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
+			enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_START:
+		/**
+		 * Start event after IOC is configured and BFA is started.
+		 */
+		if (bfa_fcport_send_enable(fcport)) {
+			bfa_trc(fcport->bfa, BFA_TRUE);
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		} else {
+			bfa_trc(fcport->bfa, BFA_FALSE);
+			bfa_sm_set_state(fcport,
+					bfa_fcport_sm_enabling_qwait);
+		}
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		/**
+		 * Port is persistently configured to be in enabled state. Do
+		 * not change state. Port enabling is done when START event is
+		 * received.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		/**
+		 * If a port is persistently configured to be disabled, the
+		 * first event will a port disable request.
+		 */
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
+				enum bfa_fcport_sm_event event)
+{
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_QRESUME:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		bfa_fcport_send_enable(fcport);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		/**
+		 * Already enable is in progress.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		/**
+		 * Just send disable request to firmware when room becomes
+		 * available in request queue.
+		 */
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port disabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_LINKUP:
+	case BFA_FCPORT_SM_LINKDOWN:
+		/**
+		 * Possible to get link events when doing back-to-back
+		 * enable/disables.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
+						enum bfa_fcport_sm_event event)
+{
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_FWRSP:
+	case BFA_FCPORT_SM_LINKDOWN:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
+		break;
+
+	case BFA_FCPORT_SM_LINKUP:
+		bfa_fcport_update_linkinfo(fcport);
+		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
+
+		bfa_assert(fcport->event_cbfn);
+		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		/**
+		 * Already being enabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		if (bfa_fcport_send_disable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_disabling_qwait);
+
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port disabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
+						enum bfa_fcport_sm_event event)
+{
+	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_LINKUP:
+		bfa_fcport_update_linkinfo(fcport);
+		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
+		bfa_assert(fcport->event_cbfn);
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
+		if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
+
+			bfa_trc(fcport->bfa,
+				pevent->link_state.vc_fcf.fcf.fipenabled);
+			bfa_trc(fcport->bfa,
+				pevent->link_state.vc_fcf.fcf.fipfailed);
+
+			if (pevent->link_state.vc_fcf.fcf.fipfailed)
+				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+					BFA_PL_EID_FIP_FCF_DISC, 0,
+					"FIP FCF Discovery Failed");
+			else
+				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+					BFA_PL_EID_FIP_FCF_DISC, 0,
+					"FIP FCF Discovered");
+		}
+
+		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port online: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_LINKDOWN:
+		/**
+		 * Possible to get link down event.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		/**
+		 * Already enabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		if (bfa_fcport_send_disable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_disabling_qwait);
+
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port disabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
+	enum bfa_fcport_sm_event event)
+{
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_ENABLE:
+		/**
+		 * Already enabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		if (bfa_fcport_send_disable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_disabling_qwait);
+
+		bfa_fcport_reset_linkinfo(fcport);
+		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port offline: WWN = %s\n", pwwn_buf);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port disabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_LINKDOWN:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
+		bfa_fcport_reset_linkinfo(fcport);
+		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		if (BFA_PORT_IS_DISABLED(fcport->bfa))
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"Base port offline: WWN = %s\n", pwwn_buf);
+		else
+			BFA_LOG(KERN_ERR, bfad, log_level,
+				"Base port (WWN = %s) "
+				"lost fabric connectivity\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		bfa_fcport_reset_linkinfo(fcport);
+		wwn2str(pwwn_buf, fcport->pwwn);
+		if (BFA_PORT_IS_DISABLED(fcport->bfa))
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"Base port offline: WWN = %s\n", pwwn_buf);
+		else
+			BFA_LOG(KERN_ERR, bfad, log_level,
+				"Base port (WWN = %s) "
+				"lost fabric connectivity\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		bfa_fcport_reset_linkinfo(fcport);
+		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+		wwn2str(pwwn_buf, fcport->pwwn);
+		if (BFA_PORT_IS_DISABLED(fcport->bfa))
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"Base port offline: WWN = %s\n", pwwn_buf);
+		else
+			BFA_LOG(KERN_ERR, bfad, log_level,
+				"Base port (WWN = %s) "
+				"lost fabric connectivity\n", pwwn_buf);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
+				 enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_QRESUME:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+		bfa_fcport_send_disable(fcport);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		/**
+		 * Already being disabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_LINKUP:
+	case BFA_FCPORT_SM_LINKDOWN:
+		/**
+		 * Possible to get link events when doing back-to-back
+		 * enable/disables.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
+				 enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_QRESUME:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+		bfa_fcport_send_disable(fcport);
+		if (bfa_fcport_send_enable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_enabling_qwait);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
+		break;
+
+	case BFA_FCPORT_SM_LINKUP:
+	case BFA_FCPORT_SM_LINKDOWN:
+		/**
+		 * Possible to get link events when doing back-to-back
+		 * enable/disables.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
+						enum bfa_fcport_sm_event event)
+{
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_FWRSP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		/**
+		 * Already being disabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		if (bfa_fcport_send_enable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_enabling_qwait);
+
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port enabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		break;
+
+	case BFA_FCPORT_SM_LINKUP:
+	case BFA_FCPORT_SM_LINKDOWN:
+		/**
+		 * Possible to get link events when doing back-to-back
+		 * enable/disables.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
+						enum bfa_fcport_sm_event event)
+{
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_START:
+		/**
+		 * Ignore start event for a port that is disabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		if (bfa_fcport_send_enable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_enabling_qwait);
+
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port enabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		/**
+		 * Already disabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
+			 enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_START:
+		if (bfa_fcport_send_enable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_enabling_qwait);
+		break;
+
+	default:
+		/**
+		 * Ignore all other events.
+		 */
+		;
+	}
+}
+
+/**
+ * Port is enabled. IOC is down/failed.
+ */
+static void
+bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
+			 enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_START:
+		if (bfa_fcport_send_enable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_enabling_qwait);
+		break;
+
+	default:
+		/**
+		 * Ignore all events.
+		 */
+		;
+	}
+}
+
+/**
+ * Port is disabled. IOC is down/failed.
+ */
+static void
+bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
+			 enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_START:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		break;
+
+	default:
+		/**
+		 * Ignore all events.
+		 */
+		;
+	}
+}
+
+/**
+ * Link state is down
+ */
+static void
+bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKUP:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
+		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for down notification
+ */
+static void
+bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKUP:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
+		break;
+
+	case BFA_FCPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for down notification and there is a pending up
+ */
+static void
+bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
+		break;
+
+	case BFA_FCPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
+		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is up
+ */
+static void
+bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
+		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for up notification
+ */
+static void
+bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
+		break;
+
+	case BFA_FCPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for up notification and there is a pending down
+ */
+static void
+bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKUP:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
+		break;
+
+	case BFA_FCPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
+		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for up notification and there are pending down and up
+ */
+static void
+bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
+			enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
+		break;
+
+	case BFA_FCPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
+		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+
+
+/**
+ *  hal_port_private
+ */
+
+static void
+__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_fcport_ln_s *ln = cbarg;
+
+	if (complete)
+		ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
+	else
+		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
+}
+
+/**
+ * Send SCN notification to upper layers.
+ * trunk - false if caller is fcport to ignore fcport event in trunked mode
+ */
+static void
+bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
+	bfa_boolean_t trunk)
+{
+	if (fcport->cfg.trunked && !trunk)
+		return;
+
+	switch (event) {
+	case BFA_PORT_LINKUP:
+		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
+		break;
+	case BFA_PORT_LINKDOWN:
+		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
+		break;
+	default:
+		bfa_assert(0);
+	}
+}
+
+static void
+bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
+{
+	struct bfa_fcport_s *fcport = ln->fcport;
+
+	if (fcport->bfa->fcs) {
+		fcport->event_cbfn(fcport->event_cbarg, event);
+		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
+	} else {
+		ln->ln_event = event;
+		bfa_cb_queue(fcport->bfa, &ln->ln_qe,
+			__bfa_cb_fcport_event, ln);
+	}
+}
+
+#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
+							BFA_CACHELINE_SZ))
+
+static void
+bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+		u32 *dm_len)
+{
+	*dm_len += FCPORT_STATS_DMA_SZ;
+}
+
+static void
+bfa_fcport_qresume(void *cbarg)
+{
+	struct bfa_fcport_s *fcport = cbarg;
+
+	bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
+}
+
+static void
+bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
+{
+	u8		*dm_kva;
+	u64	dm_pa;
+
+	dm_kva = bfa_meminfo_dma_virt(meminfo);
+	dm_pa  = bfa_meminfo_dma_phys(meminfo);
+
+	fcport->stats_kva = dm_kva;
+	fcport->stats_pa  = dm_pa;
+	fcport->stats	  = (union bfa_fcport_stats_u *) dm_kva;
+
+	dm_kva += FCPORT_STATS_DMA_SZ;
+	dm_pa  += FCPORT_STATS_DMA_SZ;
+
+	bfa_meminfo_dma_virt(meminfo) = dm_kva;
+	bfa_meminfo_dma_phys(meminfo) = dm_pa;
+}
+
+/**
+ * Memory initialization.
+ */
+static void
+bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
+	struct bfa_fcport_ln_s *ln = &fcport->ln;
+	struct bfa_timeval_s tv;
+
+	bfa_os_memset(fcport, 0, sizeof(struct bfa_fcport_s));
+	fcport->bfa = bfa;
+	ln->fcport = fcport;
+
+	bfa_fcport_mem_claim(fcport, meminfo);
+
+	bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
+	bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
+
+	/**
+	 * initialize time stamp for stats reset
+	 */
+	bfa_os_gettimeofday(&tv);
+	fcport->stats_reset_time = tv.tv_sec;
+
+	/**
+	 * initialize and set default configuration
+	 */
+	port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;
+	port_cfg->speed = BFA_PORT_SPEED_AUTO;
+	port_cfg->trunked = BFA_FALSE;
+	port_cfg->maxfrsize = 0;
+
+	port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
+
+	bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
+}
+
+static void
+bfa_fcport_detach(struct bfa_s *bfa)
+{
+}
+
+/**
+ * Called when IOC is ready.
+ */
+static void
+bfa_fcport_start(struct bfa_s *bfa)
+{
+	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
+}
+
+/**
+ * Called before IOC is stopped.
+ */
+static void
+bfa_fcport_stop(struct bfa_s *bfa)
+{
+	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_STOP);
+	bfa_trunk_iocdisable(bfa);
+}
+
+/**
+ * Called when IOC failure is detected.
+ */
+static void
+bfa_fcport_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);
+	bfa_trunk_iocdisable(bfa);
+}
+
+static void
+bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
+{
+	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+	fcport->speed = pevent->link_state.speed;
+	fcport->topology = pevent->link_state.topology;
+
+	if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP)
+		fcport->myalpa = 0;
+
+	/* QoS Details */
+	bfa_os_assign(fcport->qos_attr, pevent->link_state.qos_attr);
+	bfa_os_assign(fcport->qos_vc_attr,
+		pevent->link_state.vc_fcf.qos_vc_attr);
+
+	/**
+	 * update trunk state if applicable
+	 */
+	if (!fcport->cfg.trunked)
+		trunk->attr.state = BFA_TRUNK_DISABLED;
+
+	/* update FCoE specific */
+	fcport->fcoe_vlan = bfa_os_ntohs(pevent->link_state.vc_fcf.fcf.vlan);
+
+	bfa_trc(fcport->bfa, fcport->speed);
+	bfa_trc(fcport->bfa, fcport->topology);
+}
+
+static void
+bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
+{
+	fcport->speed = BFA_PORT_SPEED_UNKNOWN;
+	fcport->topology = BFA_PORT_TOPOLOGY_NONE;
+}
+
+/**
+ * Send port enable message to firmware.
+ */
+static bfa_boolean_t
+bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
+{
+	struct bfi_fcport_enable_req_s *m;
+
+	/**
+	 * Increment message tag before queue check, so that responses to old
+	 * requests are discarded.
+	 */
+	fcport->msgtag++;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+	if (!m) {
+		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+							&fcport->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
+			bfa_lpuid(fcport->bfa));
+	m->nwwn = fcport->nwwn;
+	m->pwwn = fcport->pwwn;
+	m->port_cfg = fcport->cfg;
+	m->msgtag = fcport->msgtag;
+	m->port_cfg.maxfrsize = bfa_os_htons(fcport->cfg.maxfrsize);
+	bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
+	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
+	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+	return BFA_TRUE;
+}
+
+/**
+ * Send port disable message to firmware.
+ */
+static	bfa_boolean_t
+bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
+{
+	struct bfi_fcport_req_s *m;
+
+	/**
+	 * Increment message tag before queue check, so that responses to old
+	 * requests are discarded.
+	 */
+	fcport->msgtag++;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+	if (!m) {
+		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+							&fcport->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
+			bfa_lpuid(fcport->bfa));
+	m->msgtag = fcport->msgtag;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+
+	return BFA_TRUE;
+}
+
+static void
+bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
+{
+	fcport->pwwn = bfa_ioc_get_pwwn(&fcport->bfa->ioc);
+	fcport->nwwn = bfa_ioc_get_nwwn(&fcport->bfa->ioc);
+
+	bfa_trc(fcport->bfa, fcport->pwwn);
+	bfa_trc(fcport->bfa, fcport->nwwn);
+}
+
+static void
+bfa_fcport_send_txcredit(void *port_cbarg)
+{
+
+	struct bfa_fcport_s *fcport = port_cbarg;
+	struct bfi_fcport_set_svc_params_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+	if (!m) {
+		bfa_trc(fcport->bfa, fcport->cfg.tx_bbcredit);
+		return;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ,
+			bfa_lpuid(fcport->bfa));
+	m->tx_bbcredit = bfa_os_htons((u16)fcport->cfg.tx_bbcredit);
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+}
+
+static void
+bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
+	struct bfa_qos_stats_s *s)
+{
+	u32	*dip = (u32 *) d;
+	u32	*sip = (u32 *) s;
+	int		i;
+
+	/* Now swap the 32 bit fields */
+	for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
+		dip[i] = bfa_os_ntohl(sip[i]);
+}
+
+static void
+bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
+	struct bfa_fcoe_stats_s *s)
+{
+	u32	*dip = (u32 *) d;
+	u32	*sip = (u32 *) s;
+	int		i;
+
+	for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
+	     i = i + 2) {
+#ifdef __BIGENDIAN
+		dip[i] = bfa_os_ntohl(sip[i]);
+		dip[i + 1] = bfa_os_ntohl(sip[i + 1]);
+#else
+		dip[i] = bfa_os_ntohl(sip[i + 1]);
+		dip[i + 1] = bfa_os_ntohl(sip[i]);
+#endif
+	}
+}
+
+static void
+__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_fcport_s *fcport = cbarg;
+
+	if (complete) {
+		if (fcport->stats_status == BFA_STATUS_OK) {
+			struct bfa_timeval_s tv;
+
+			/* Swap FC QoS or FCoE stats */
+			if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
+				bfa_fcport_qos_stats_swap(
+					&fcport->stats_ret->fcqos,
+					&fcport->stats->fcqos);
+			} else {
+				bfa_fcport_fcoe_stats_swap(
+					&fcport->stats_ret->fcoe,
+					&fcport->stats->fcoe);
+
+				bfa_os_gettimeofday(&tv);
+				fcport->stats_ret->fcoe.secs_reset =
+					tv.tv_sec - fcport->stats_reset_time;
+			}
+		}
+		fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
+	} else {
+		fcport->stats_busy = BFA_FALSE;
+		fcport->stats_status = BFA_STATUS_OK;
+	}
+}
+
+static void
+bfa_fcport_stats_get_timeout(void *cbarg)
+{
+	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+
+	bfa_trc(fcport->bfa, fcport->stats_qfull);
+
+	if (fcport->stats_qfull) {
+		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
+		fcport->stats_qfull = BFA_FALSE;
+	}
+
+	fcport->stats_status = BFA_STATUS_ETIMER;
+	bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get,
+		fcport);
+}
+
+static void
+bfa_fcport_send_stats_get(void *cbarg)
+{
+	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+	struct bfi_fcport_req_s *msg;
+
+	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+
+	if (!msg) {
+		fcport->stats_qfull = BFA_TRUE;
+		bfa_reqq_winit(&fcport->stats_reqq_wait,
+				bfa_fcport_send_stats_get, fcport);
+		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+				&fcport->stats_reqq_wait);
+		return;
+	}
+	fcport->stats_qfull = BFA_FALSE;
+
+	bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
+	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
+			bfa_lpuid(fcport->bfa));
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+}
+
+static void
+__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_fcport_s *fcport = cbarg;
+
+	if (complete) {
+		struct bfa_timeval_s tv;
+
+		/**
+		 * re-initialize time stamp for stats reset
+		 */
+		bfa_os_gettimeofday(&tv);
+		fcport->stats_reset_time = tv.tv_sec;
+
+		fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
+	} else {
+		fcport->stats_busy = BFA_FALSE;
+		fcport->stats_status = BFA_STATUS_OK;
+	}
+}
+
+static void
+bfa_fcport_stats_clr_timeout(void *cbarg)
+{
+	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+
+	bfa_trc(fcport->bfa, fcport->stats_qfull);
+
+	if (fcport->stats_qfull) {
+		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
+		fcport->stats_qfull = BFA_FALSE;
+	}
+
+	fcport->stats_status = BFA_STATUS_ETIMER;
+	bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
+			__bfa_cb_fcport_stats_clr, fcport);
+}
+
+static void
+bfa_fcport_send_stats_clear(void *cbarg)
+{
+	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+	struct bfi_fcport_req_s *msg;
+
+	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+
+	if (!msg) {
+		fcport->stats_qfull = BFA_TRUE;
+		bfa_reqq_winit(&fcport->stats_reqq_wait,
+				bfa_fcport_send_stats_clear, fcport);
+		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+						&fcport->stats_reqq_wait);
+		return;
+	}
+	fcport->stats_qfull = BFA_FALSE;
+
+	bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
+	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
+			bfa_lpuid(fcport->bfa));
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+}
+
+/**
+ * Handle trunk SCN event from firmware.
+ */
+static void
+bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
+{
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+	struct bfi_fcport_trunk_link_s *tlink;
+	struct bfa_trunk_link_attr_s *lattr;
+	enum bfa_trunk_state state_prev;
+	int i;
+	int link_bm = 0;
+
+	bfa_trc(fcport->bfa, fcport->cfg.trunked);
+	bfa_assert(scn->trunk_state == BFA_TRUNK_ONLINE ||
+		   scn->trunk_state == BFA_TRUNK_OFFLINE);
+
+	bfa_trc(fcport->bfa, trunk->attr.state);
+	bfa_trc(fcport->bfa, scn->trunk_state);
+	bfa_trc(fcport->bfa, scn->trunk_speed);
+
+	/**
+	 * Save off new state for trunk attribute query
+	 */
+	state_prev = trunk->attr.state;
+	if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))
+		trunk->attr.state = scn->trunk_state;
+	trunk->attr.speed = scn->trunk_speed;
+	for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
+		lattr = &trunk->attr.link_attr[i];
+		tlink = &scn->tlink[i];
+
+		lattr->link_state = tlink->state;
+		lattr->trunk_wwn  = tlink->trunk_wwn;
+		lattr->fctl	  = tlink->fctl;
+		lattr->speed	  = tlink->speed;
+		lattr->deskew	  = bfa_os_ntohl(tlink->deskew);
+
+		if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {
+			fcport->speed	 = tlink->speed;
+			fcport->topology = BFA_PORT_TOPOLOGY_P2P;
+			link_bm |= 1 << i;
+		}
+
+		bfa_trc(fcport->bfa, lattr->link_state);
+		bfa_trc(fcport->bfa, lattr->trunk_wwn);
+		bfa_trc(fcport->bfa, lattr->fctl);
+		bfa_trc(fcport->bfa, lattr->speed);
+		bfa_trc(fcport->bfa, lattr->deskew);
+	}
+
+	switch (link_bm) {
+	case 3:
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");
+		break;
+	case 2:
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");
+		break;
+	case 1:
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");
+		break;
+	default:
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+			BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");
+	}
+
+	/**
+	 * Notify upper layers if trunk state changed.
+	 */
+	if ((state_prev != trunk->attr.state) ||
+		(scn->trunk_state == BFA_TRUNK_OFFLINE)) {
+		bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?
+			BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);
+	}
+}
+
+static void
+bfa_trunk_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	int i = 0;
+
+	/**
+	 * In trunked mode, notify upper layers that link is down
+	 */
+	if (fcport->cfg.trunked) {
+		if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)
+			bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);
+
+		fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;
+		fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;
+		for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
+			fcport->trunk.attr.link_attr[i].trunk_wwn = 0;
+			fcport->trunk.attr.link_attr[i].fctl =
+						BFA_TRUNK_LINK_FCTL_NORMAL;
+			fcport->trunk.attr.link_attr[i].link_state =
+						BFA_TRUNK_LINK_STATE_DN_LINKDN;
+			fcport->trunk.attr.link_attr[i].speed =
+						BFA_PORT_SPEED_UNKNOWN;
+			fcport->trunk.attr.link_attr[i].deskew = 0;
+		}
+	}
+}
+
+
+
+/**
+ *  hal_port_public
+ */
+
+/**
+ * Called to initialize port attributes
+ */
+void
+bfa_fcport_init(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	/**
+	 * Initialize port attributes from IOC hardware data.
+	 */
+	bfa_fcport_set_wwns(fcport);
+	if (fcport->cfg.maxfrsize == 0)
+		fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
+	fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
+	fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
+
+	bfa_assert(fcport->cfg.maxfrsize);
+	bfa_assert(fcport->cfg.rx_bbcredit);
+	bfa_assert(fcport->speed_sup);
+}
+
+/**
+ * Firmware message handler.
+ */
+void
+bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	union bfi_fcport_i2h_msg_u i2hmsg;
+
+	i2hmsg.msg = msg;
+	fcport->event_arg.i2hmsg = i2hmsg;
+
+	bfa_trc(bfa, msg->mhdr.msg_id);
+	bfa_trc(bfa, bfa_sm_to_state(hal_port_sm_table, fcport->sm));
+
+	switch (msg->mhdr.msg_id) {
+	case BFI_FCPORT_I2H_ENABLE_RSP:
+		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
+			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
+		break;
+
+	case BFI_FCPORT_I2H_DISABLE_RSP:
+		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
+			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
+		break;
+
+	case BFI_FCPORT_I2H_EVENT:
+		if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
+			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
+		else
+			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKDOWN);
+		break;
+
+	case BFI_FCPORT_I2H_TRUNK_SCN:
+		bfa_trunk_scn(fcport, i2hmsg.trunk_scn);
+		break;
+
+	case BFI_FCPORT_I2H_STATS_GET_RSP:
+		/*
+		 * check for timer pop before processing the rsp
+		 */
+		if (fcport->stats_busy == BFA_FALSE ||
+		    fcport->stats_status == BFA_STATUS_ETIMER)
+			break;
+
+		bfa_timer_stop(&fcport->timer);
+		fcport->stats_status = i2hmsg.pstatsget_rsp->status;
+		bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
+				__bfa_cb_fcport_stats_get, fcport);
+		break;
+
+	case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
+		/*
+		 * check for timer pop before processing the rsp
+		 */
+		if (fcport->stats_busy == BFA_FALSE ||
+		    fcport->stats_status == BFA_STATUS_ETIMER)
+			break;
+
+		bfa_timer_stop(&fcport->timer);
+		fcport->stats_status = BFA_STATUS_OK;
+		bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
+				__bfa_cb_fcport_stats_clr, fcport);
+		break;
+
+	case BFI_FCPORT_I2H_ENABLE_AEN:
+		bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);
+		break;
+
+	case BFI_FCPORT_I2H_DISABLE_AEN:
+		bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);
+		break;
+
+	default:
+		bfa_assert(0);
+	break;
+	}
+}
+
+
+
+/**
+ *  hal_port_api
+ */
+
+/**
+ * Registered callback for port events.
+ */
+void
+bfa_fcport_event_register(struct bfa_s *bfa,
+				void (*cbfn) (void *cbarg,
+				enum bfa_port_linkstate event),
+				void *cbarg)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	fcport->event_cbfn = cbfn;
+	fcport->event_cbarg = cbarg;
+}
+
+bfa_status_t
+bfa_fcport_enable(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	if (bfa_ioc_is_disabled(&bfa->ioc))
+		return BFA_STATUS_IOC_DISABLED;
+
+	if (fcport->diag_busy)
+		return BFA_STATUS_DIAG_BUSY;
+
+	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcport_disable(struct bfa_s *bfa)
+{
+
+	if (bfa_ioc_is_disabled(&bfa->ioc))
+		return BFA_STATUS_IOC_DISABLED;
+
+	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Configure port speed.
+ */
+bfa_status_t
+bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, speed);
+
+	if (fcport->cfg.trunked == BFA_TRUE)
+		return BFA_STATUS_TRUNK_ENABLED;
+	if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
+		bfa_trc(bfa, fcport->speed_sup);
+		return BFA_STATUS_UNSUPP_SPEED;
+	}
+
+	fcport->cfg.speed = speed;
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Get current speed.
+ */
+enum bfa_port_speed
+bfa_fcport_get_speed(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->speed;
+}
+
+/**
+ * Configure port topology.
+ */
+bfa_status_t
+bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, topology);
+	bfa_trc(bfa, fcport->cfg.topology);
+
+	switch (topology) {
+	case BFA_PORT_TOPOLOGY_P2P:
+	case BFA_PORT_TOPOLOGY_LOOP:
+	case BFA_PORT_TOPOLOGY_AUTO:
+		break;
+
+	default:
+		return BFA_STATUS_EINVAL;
+	}
+
+	fcport->cfg.topology = topology;
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Get current topology.
+ */
+enum bfa_port_topology
+bfa_fcport_get_topology(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->topology;
+}
+
+bfa_status_t
+bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, alpa);
+	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
+	bfa_trc(bfa, fcport->cfg.hardalpa);
+
+	fcport->cfg.cfg_hardalpa = BFA_TRUE;
+	fcport->cfg.hardalpa = alpa;
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
+	bfa_trc(bfa, fcport->cfg.hardalpa);
+
+	fcport->cfg.cfg_hardalpa = BFA_FALSE;
+	return BFA_STATUS_OK;
+}
+
+bfa_boolean_t
+bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	*alpa = fcport->cfg.hardalpa;
+	return fcport->cfg.cfg_hardalpa;
+}
+
+u8
+bfa_fcport_get_myalpa(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->myalpa;
+}
+
+bfa_status_t
+bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, maxfrsize);
+	bfa_trc(bfa, fcport->cfg.maxfrsize);
+
+	/* with in range */
+	if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
+		return BFA_STATUS_INVLD_DFSZ;
+
+	/* power of 2, if not the max frame size of 2112 */
+	if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
+		return BFA_STATUS_INVLD_DFSZ;
+
+	fcport->cfg.maxfrsize = maxfrsize;
+	return BFA_STATUS_OK;
+}
+
+u16
+bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->cfg.maxfrsize;
+}
+
+u8
+bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->cfg.rx_bbcredit;
+}
+
+void
+bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
+	bfa_fcport_send_txcredit(fcport);
+}
+
+/**
+ * Get port attributes.
+ */
+
+wwn_t
+bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	if (node)
+		return fcport->nwwn;
+	else
+		return fcport->pwwn;
+}
+
+void
+bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_os_memset(attr, 0, sizeof(struct bfa_port_attr_s));
+
+	attr->nwwn = fcport->nwwn;
+	attr->pwwn = fcport->pwwn;
+
+	attr->factorypwwn =  bfa_ioc_get_mfg_pwwn(&bfa->ioc);
+	attr->factorynwwn =  bfa_ioc_get_mfg_nwwn(&bfa->ioc);
+
+	bfa_os_memcpy(&attr->pport_cfg, &fcport->cfg,
+		sizeof(struct bfa_port_cfg_s));
+	/* speed attributes */
+	attr->pport_cfg.speed = fcport->cfg.speed;
+	attr->speed_supported = fcport->speed_sup;
+	attr->speed = fcport->speed;
+	attr->cos_supported = FC_CLASS_3;
+
+	/* topology attributes */
+	attr->pport_cfg.topology = fcport->cfg.topology;
+	attr->topology = fcport->topology;
+	attr->pport_cfg.trunked = fcport->cfg.trunked;
+
+	/* beacon attributes */
+	attr->beacon = fcport->beacon;
+	attr->link_e2e_beacon = fcport->link_e2e_beacon;
+	attr->plog_enabled = bfa_plog_get_setting(fcport->bfa->plog);
+	attr->io_profile = bfa_fcpim_get_io_profile(fcport->bfa);
+
+	attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);
+	attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);
+	attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
+	if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
+		attr->port_state = BFA_PORT_ST_IOCDIS;
+	else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
+		attr->port_state = BFA_PORT_ST_FWMISMATCH;
+
+	/* FCoE vlan */
+	attr->fcoe_vlan = fcport->fcoe_vlan;
+}
+
+#define BFA_FCPORT_STATS_TOV	1000
+
+/**
+ * Fetch port statistics (FCQoS or FCoE).
+ */
+bfa_status_t
+bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
+	bfa_cb_port_t cbfn, void *cbarg)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	if (fcport->stats_busy) {
+		bfa_trc(bfa, fcport->stats_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	fcport->stats_busy  = BFA_TRUE;
+	fcport->stats_ret   = stats;
+	fcport->stats_cbfn  = cbfn;
+	fcport->stats_cbarg = cbarg;
+
+	bfa_fcport_send_stats_get(fcport);
+
+	bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout,
+			fcport, BFA_FCPORT_STATS_TOV);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Reset port statistics (FCQoS or FCoE).
+ */
+bfa_status_t
+bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	if (fcport->stats_busy) {
+		bfa_trc(bfa, fcport->stats_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	fcport->stats_busy  = BFA_TRUE;
+	fcport->stats_cbfn  = cbfn;
+	fcport->stats_cbarg = cbarg;
+
+	bfa_fcport_send_stats_clear(fcport);
+
+	bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout,
+			fcport, BFA_FCPORT_STATS_TOV);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Fetch FCQoS port statistics
+ */
+bfa_status_t
+bfa_fcport_get_qos_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
+	bfa_cb_port_t cbfn, void *cbarg)
+{
+	/* Meaningful only for FC mode */
+	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
+
+	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
+}
+
+/**
+ * Reset FCoE port statistics
+ */
+bfa_status_t
+bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
+{
+	/* Meaningful only for FC mode */
+	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
+
+	return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
+}
+
+/**
+ * Fetch FCQoS port statistics
+ */
+bfa_status_t
+bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
+	bfa_cb_port_t cbfn, void *cbarg)
+{
+	/* Meaningful only for FCoE mode */
+	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
+
+	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
+}
+
+/**
+ * Reset FCoE port statistics
+ */
+bfa_status_t
+bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
+{
+	/* Meaningful only for FCoE mode */
+	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
+
+	return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
+}
+
+void
+bfa_fcport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	qos_attr->state = fcport->qos_attr.state;
+	qos_attr->total_bb_cr = bfa_os_ntohl(fcport->qos_attr.total_bb_cr);
+}
+
+void
+bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
+	struct bfa_qos_vc_attr_s *qos_vc_attr)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr;
+	u32 i = 0;
+
+	qos_vc_attr->total_vc_count = bfa_os_ntohs(bfa_vc_attr->total_vc_count);
+	qos_vc_attr->shared_credit  = bfa_os_ntohs(bfa_vc_attr->shared_credit);
+	qos_vc_attr->elp_opmode_flags  =
+			bfa_os_ntohl(bfa_vc_attr->elp_opmode_flags);
+
+	/* Individual VC info */
+	while (i < qos_vc_attr->total_vc_count) {
+		qos_vc_attr->vc_info[i].vc_credit	=
+				bfa_vc_attr->vc_info[i].vc_credit;
+		qos_vc_attr->vc_info[i].borrow_credit	=
+				bfa_vc_attr->vc_info[i].borrow_credit;
+		qos_vc_attr->vc_info[i].priority	=
+				bfa_vc_attr->vc_info[i].priority;
+		++i;
+	}
+}
+
+/**
+ * Fetch port attributes.
+ */
+bfa_boolean_t
+bfa_fcport_is_disabled(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
+		BFA_PORT_ST_DISABLED;
+
+}
+
+bfa_boolean_t
+bfa_fcport_is_ratelim(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
+
+}
+
+void
+bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
+
+	bfa_trc(bfa, on_off);
+	bfa_trc(bfa, fcport->cfg.qos_enabled);
+
+	bfa_trc(bfa, ioc_type);
+
+	if (ioc_type == BFA_IOC_TYPE_FC) {
+		fcport->cfg.qos_enabled = on_off;
+		/**
+		 * Notify fcpim of the change in QoS state
+		 */
+		bfa_fcpim_update_ioredirect(bfa);
+	}
+}
+
+void
+bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, on_off);
+	bfa_trc(bfa, fcport->cfg.ratelimit);
+
+	fcport->cfg.ratelimit = on_off;
+	if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
+		fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
+}
+
+/**
+ * Configure default minimum ratelim speed
+ */
+bfa_status_t
+bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, speed);
+
+	/* Auto and speeds greater than the supported speed, are invalid */
+	if ((speed == BFA_PORT_SPEED_AUTO) || (speed > fcport->speed_sup)) {
+		bfa_trc(bfa, fcport->speed_sup);
+		return BFA_STATUS_UNSUPP_SPEED;
+	}
+
+	fcport->cfg.trl_def_speed = speed;
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Get default minimum ratelim speed
+ */
+enum bfa_port_speed
+bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, fcport->cfg.trl_def_speed);
+	return fcport->cfg.trl_def_speed;
+
+}
+void
+bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, status);
+	bfa_trc(bfa, fcport->diag_busy);
+
+	fcport->diag_busy = status;
+}
+
+void
+bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
+	bfa_boolean_t link_e2e_beacon)
+{
+	struct bfa_s *bfa = dev;
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, beacon);
+	bfa_trc(bfa, link_e2e_beacon);
+	bfa_trc(bfa, fcport->beacon);
+	bfa_trc(bfa, fcport->link_e2e_beacon);
+
+	fcport->beacon = beacon;
+	fcport->link_e2e_beacon = link_e2e_beacon;
+}
+
+bfa_boolean_t
+bfa_fcport_is_linkup(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return	(!fcport->cfg.trunked &&
+		 bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||
+		(fcport->cfg.trunked &&
+		 fcport->trunk.attr.state == BFA_TRUNK_ONLINE);
+}
+
+bfa_boolean_t
+bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->cfg.qos_enabled;
+}
+
+bfa_status_t
+bfa_trunk_get_attr(struct bfa_s *bfa, struct bfa_trunk_attr_s *attr)
+
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+	bfa_trc(bfa, fcport->cfg.trunked);
+	bfa_trc(bfa, trunk->attr.state);
+	*attr = trunk->attr;
+	attr->port_id = bfa_lps_get_base_pid(bfa);
+
+	return BFA_STATUS_OK;
+}
+
+void
+bfa_trunk_enable_cfg(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+	bfa_trc(bfa, 1);
+	trunk->attr.state = BFA_TRUNK_OFFLINE;
+	fcport->cfg.trunked = BFA_TRUE;
+}
+
+bfa_status_t
+bfa_trunk_enable(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+	bfa_trc(bfa, 1);
+
+	trunk->attr.state   = BFA_TRUNK_OFFLINE;
+	bfa_fcport_disable(bfa);
+	fcport->cfg.trunked = BFA_TRUE;
+	bfa_fcport_enable(bfa);
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_trunk_disable(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+	bfa_trc(bfa, 0);
+	trunk->attr.state   = BFA_TRUNK_DISABLED;
+	bfa_fcport_disable(bfa);
+	fcport->cfg.trunked = BFA_FALSE;
+	bfa_fcport_enable(bfa);
+	return BFA_STATUS_OK;
+}
+
+
+/**
+ * Rport State machine functions
+ */
+/**
+ * Beginning state, only online event expected.
+ */
+static void
+bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_CREATE:
+		bfa_stats(rp, sm_un_cr);
+		bfa_sm_set_state(rp, bfa_rport_sm_created);
+		break;
+
+	default:
+		bfa_stats(rp, sm_un_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+static void
+bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_ONLINE:
+		bfa_stats(rp, sm_cr_on);
+		if (bfa_rport_send_fwcreate(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_cr_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_cr_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		break;
+
+	default:
+		bfa_stats(rp, sm_cr_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Waiting for rport create response from firmware.
+ */
+static void
+bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_FWRSP:
+		bfa_stats(rp, sm_fwc_rsp);
+		bfa_sm_set_state(rp, bfa_rport_sm_online);
+		bfa_rport_online_cb(rp);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_fwc_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
+		break;
+
+	case BFA_RPORT_SM_OFFLINE:
+		bfa_stats(rp, sm_fwc_off);
+		bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_fwc_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		break;
+
+	default:
+		bfa_stats(rp, sm_fwc_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Request queue is full, awaiting queue resume to send create request.
+ */
+static void
+bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_QRESUME:
+		bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+		bfa_rport_send_fwcreate(rp);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_fwc_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_reqq_wcancel(&rp->reqq_wait);
+		bfa_rport_free(rp);
+		break;
+
+	case BFA_RPORT_SM_OFFLINE:
+		bfa_stats(rp, sm_fwc_off);
+		bfa_sm_set_state(rp, bfa_rport_sm_offline);
+		bfa_reqq_wcancel(&rp->reqq_wait);
+		bfa_rport_offline_cb(rp);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_fwc_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		bfa_reqq_wcancel(&rp->reqq_wait);
+		break;
+
+	default:
+		bfa_stats(rp, sm_fwc_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Online state - normal parking state.
+ */
+static void
+bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	struct bfi_rport_qos_scn_s *qos_scn;
+
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_OFFLINE:
+		bfa_stats(rp, sm_on_off);
+		if (bfa_rport_send_fwdelete(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_on_del);
+		if (bfa_rport_send_fwdelete(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_on_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		break;
+
+	case BFA_RPORT_SM_SET_SPEED:
+		bfa_rport_send_fwspeed(rp);
+		break;
+
+	case BFA_RPORT_SM_QOS_SCN:
+		qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
+		rp->qos_attr = qos_scn->new_qos_attr;
+		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
+		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
+		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
+		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
+
+		qos_scn->old_qos_attr.qos_flow_id  =
+			bfa_os_ntohl(qos_scn->old_qos_attr.qos_flow_id);
+		qos_scn->new_qos_attr.qos_flow_id  =
+			bfa_os_ntohl(qos_scn->new_qos_attr.qos_flow_id);
+
+		if (qos_scn->old_qos_attr.qos_flow_id !=
+			qos_scn->new_qos_attr.qos_flow_id)
+			bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
+						    qos_scn->old_qos_attr,
+						    qos_scn->new_qos_attr);
+		if (qos_scn->old_qos_attr.qos_priority !=
+			qos_scn->new_qos_attr.qos_priority)
+			bfa_cb_rport_qos_scn_prio(rp->rport_drv,
+						  qos_scn->old_qos_attr,
+						  qos_scn->new_qos_attr);
+		break;
+
+	default:
+		bfa_stats(rp, sm_on_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Firmware rport is being deleted - awaiting f/w response.
+ */
+static void
+bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_FWRSP:
+		bfa_stats(rp, sm_fwd_rsp);
+		bfa_sm_set_state(rp, bfa_rport_sm_offline);
+		bfa_rport_offline_cb(rp);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_fwd_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_fwd_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		bfa_rport_offline_cb(rp);
+		break;
+
+	default:
+		bfa_stats(rp, sm_fwd_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+static void
+bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_QRESUME:
+		bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+		bfa_rport_send_fwdelete(rp);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_fwd_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_fwd_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		bfa_reqq_wcancel(&rp->reqq_wait);
+		bfa_rport_offline_cb(rp);
+		break;
+
+	default:
+		bfa_stats(rp, sm_fwd_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Offline state.
+ */
+static void
+bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_off_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	case BFA_RPORT_SM_ONLINE:
+		bfa_stats(rp, sm_off_on);
+		if (bfa_rport_send_fwcreate(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_off_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		break;
+
+	default:
+		bfa_stats(rp, sm_off_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Rport is deleted, waiting for firmware response to delete.
+ */
+static void
+bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_FWRSP:
+		bfa_stats(rp, sm_del_fwrsp);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_del_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	default:
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+static void
+bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_QRESUME:
+		bfa_stats(rp, sm_del_fwrsp);
+		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+		bfa_rport_send_fwdelete(rp);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_del_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_reqq_wcancel(&rp->reqq_wait);
+		bfa_rport_free(rp);
+		break;
+
+	default:
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Waiting for rport create response from firmware. A delete is pending.
+ */
+static void
+bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
+				enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_FWRSP:
+		bfa_stats(rp, sm_delp_fwrsp);
+		if (bfa_rport_send_fwdelete(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_delp_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	default:
+		bfa_stats(rp, sm_delp_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Waiting for rport create response from firmware. Rport offline is pending.
+ */
+static void
+bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
+				 enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_FWRSP:
+		bfa_stats(rp, sm_offp_fwrsp);
+		if (bfa_rport_send_fwdelete(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_offp_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_offp_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		break;
+
+	default:
+		bfa_stats(rp, sm_offp_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * IOC h/w failed.
+ */
+static void
+bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_OFFLINE:
+		bfa_stats(rp, sm_iocd_off);
+		bfa_rport_offline_cb(rp);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_iocd_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	case BFA_RPORT_SM_ONLINE:
+		bfa_stats(rp, sm_iocd_on);
+		if (bfa_rport_send_fwcreate(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		break;
+
+	default:
+		bfa_stats(rp, sm_iocd_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+
+
+/**
+ *  bfa_rport_private BFA rport private functions
+ */
+
+static void
+__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_rport_s *rp = cbarg;
+
+	if (complete)
+		bfa_cb_rport_online(rp->rport_drv);
+}
+
+static void
+__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_rport_s *rp = cbarg;
+
+	if (complete)
+		bfa_cb_rport_offline(rp->rport_drv);
+}
+
+static void
+bfa_rport_qresume(void *cbarg)
+{
+	struct bfa_rport_s	*rp = cbarg;
+
+	bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
+}
+
+static void
+bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+		u32 *dm_len)
+{
+	if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
+		cfg->fwcfg.num_rports = BFA_RPORT_MIN;
+
+	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
+}
+
+static void
+bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		     struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
+	struct bfa_rport_s *rp;
+	u16 i;
+
+	INIT_LIST_HEAD(&mod->rp_free_q);
+	INIT_LIST_HEAD(&mod->rp_active_q);
+
+	rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
+	mod->rps_list = rp;
+	mod->num_rports = cfg->fwcfg.num_rports;
+
+	bfa_assert(mod->num_rports &&
+		   !(mod->num_rports & (mod->num_rports - 1)));
+
+	for (i = 0; i < mod->num_rports; i++, rp++) {
+		bfa_os_memset(rp, 0, sizeof(struct bfa_rport_s));
+		rp->bfa = bfa;
+		rp->rport_tag = i;
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+
+		/**
+		 *  - is unused
+		 */
+		if (i)
+			list_add_tail(&rp->qe, &mod->rp_free_q);
+
+		bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
+	}
+
+	/**
+	 * consume memory
+	 */
+	bfa_meminfo_kva(meminfo) = (u8 *) rp;
+}
+
+static void
+bfa_rport_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
+	struct bfa_rport_s *rport;
+	struct list_head *qe, *qen;
+
+	list_for_each_safe(qe, qen, &mod->rp_active_q) {
+		rport = (struct bfa_rport_s *) qe;
+		bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
+	}
+}
+
+static struct bfa_rport_s *
+bfa_rport_alloc(struct bfa_rport_mod_s *mod)
+{
+	struct bfa_rport_s *rport;
+
+	bfa_q_deq(&mod->rp_free_q, &rport);
+	if (rport)
+		list_add_tail(&rport->qe, &mod->rp_active_q);
+
+	return rport;
+}
+
+static void
+bfa_rport_free(struct bfa_rport_s *rport)
+{
+	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
+
+	bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport));
+	list_del(&rport->qe);
+	list_add_tail(&rport->qe, &mod->rp_free_q);
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
+{
+	struct bfi_rport_create_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+	if (!m) {
+		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
+			bfa_lpuid(rp->bfa));
+	m->bfa_handle = rp->rport_tag;
+	m->max_frmsz = bfa_os_htons(rp->rport_info.max_frmsz);
+	m->pid = rp->rport_info.pid;
+	m->lp_tag = rp->rport_info.lp_tag;
+	m->local_pid = rp->rport_info.local_pid;
+	m->fc_class = rp->rport_info.fc_class;
+	m->vf_en = rp->rport_info.vf_en;
+	m->vf_id = rp->rport_info.vf_id;
+	m->cisc = rp->rport_info.cisc;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+	return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
+{
+	struct bfi_rport_delete_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+	if (!m) {
+		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
+			bfa_lpuid(rp->bfa));
+	m->fw_handle = rp->fw_handle;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+	return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
+{
+	struct bfa_rport_speed_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+	if (!m) {
+		bfa_trc(rp->bfa, rp->rport_info.speed);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
+			bfa_lpuid(rp->bfa));
+	m->fw_handle = rp->fw_handle;
+	m->speed = (u8)rp->rport_info.speed;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+	return BFA_TRUE;
+}
+
+
+
+/**
+ *  bfa_rport_public
+ */
+
+/**
+ * Rport interrupt processing.
+ */
+void
+bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	union bfi_rport_i2h_msg_u msg;
+	struct bfa_rport_s *rp;
+
+	bfa_trc(bfa, m->mhdr.msg_id);
+
+	msg.msg = m;
+
+	switch (m->mhdr.msg_id) {
+	case BFI_RPORT_I2H_CREATE_RSP:
+		rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
+		rp->fw_handle = msg.create_rsp->fw_handle;
+		rp->qos_attr = msg.create_rsp->qos_attr;
+		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
+		break;
+
+	case BFI_RPORT_I2H_DELETE_RSP:
+		rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
+		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
+		break;
+
+	case BFI_RPORT_I2H_QOS_SCN:
+		rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
+		rp->event_arg.fw_msg = msg.qos_scn_evt;
+		bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
+		break;
+
+	default:
+		bfa_trc(bfa, m->mhdr.msg_id);
+		bfa_assert(0);
+	}
+}
+
+
+
+/**
+ *  bfa_rport_api
+ */
+
+struct bfa_rport_s *
+bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
+{
+	struct bfa_rport_s *rp;
+
+	rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
+
+	if (rp == NULL)
+		return NULL;
+
+	rp->bfa = bfa;
+	rp->rport_drv = rport_drv;
+	bfa_rport_clear_stats(rp);
+
+	bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
+	bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
+
+	return rp;
+}
+
+void
+bfa_rport_delete(struct bfa_rport_s *rport)
+{
+	bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE);
+}
+
+void
+bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
+{
+	bfa_assert(rport_info->max_frmsz != 0);
+
+	/**
+	 * Some JBODs are seen to be not setting PDU size correctly in PLOGI
+	 * responses. Default to minimum size.
+	 */
+	if (rport_info->max_frmsz == 0) {
+		bfa_trc(rport->bfa, rport->rport_tag);
+		rport_info->max_frmsz = FC_MIN_PDUSZ;
+	}
+
+	bfa_os_assign(rport->rport_info, *rport_info);
+	bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
+}
+
+void
+bfa_rport_offline(struct bfa_rport_s *rport)
+{
+	bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE);
+}
+
+void
+bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
+{
+	bfa_assert(speed != 0);
+	bfa_assert(speed != BFA_PORT_SPEED_AUTO);
+
+	rport->rport_info.speed = speed;
+	bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
+}
+
+void
+bfa_rport_get_stats(struct bfa_rport_s *rport,
+	struct bfa_rport_hal_stats_s *stats)
+{
+	*stats = rport->stats;
+}
+
+void
+bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
+					struct bfa_rport_qos_attr_s *qos_attr)
+{
+	qos_attr->qos_priority  = rport->qos_attr.qos_priority;
+	qos_attr->qos_flow_id  = bfa_os_ntohl(rport->qos_attr.qos_flow_id);
+
+}
+
+void
+bfa_rport_clear_stats(struct bfa_rport_s *rport)
+{
+	bfa_os_memset(&rport->stats, 0, sizeof(rport->stats));
+}
+
+
+/**
+ * SGPG related functions
+ */
+
+/**
+ * Compute and return memory needed by FCP(im) module.
+ */
+static void
+bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+		u32 *dm_len)
+{
+	if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
+		cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
+
+	*km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
+	*dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
+}
+
+
+static void
+bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		    struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+	int i;
+	struct bfa_sgpg_s *hsgpg;
+	struct bfi_sgpg_s *sgpg;
+	u64 align_len;
+
+	union {
+		u64 pa;
+		union bfi_addr_u addr;
+	} sgpg_pa, sgpg_pa_tmp;
+
+	INIT_LIST_HEAD(&mod->sgpg_q);
+	INIT_LIST_HEAD(&mod->sgpg_wait_q);
+
+	bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
+
+	mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
+	mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
+	align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
+	mod->sgpg_arr_pa += align_len;
+	mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
+						align_len);
+	mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
+						align_len);
+
+	hsgpg = mod->hsgpg_arr;
+	sgpg = mod->sgpg_arr;
+	sgpg_pa.pa = mod->sgpg_arr_pa;
+	mod->free_sgpgs = mod->num_sgpgs;
+
+	bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));
+
+	for (i = 0; i < mod->num_sgpgs; i++) {
+		bfa_os_memset(hsgpg, 0, sizeof(*hsgpg));
+		bfa_os_memset(sgpg, 0, sizeof(*sgpg));
+
+		hsgpg->sgpg = sgpg;
+		sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
+		hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
+		list_add_tail(&hsgpg->qe, &mod->sgpg_q);
+
+		hsgpg++;
+		sgpg++;
+		sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
+	}
+
+	bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
+	bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
+	bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
+}
+
+static void
+bfa_sgpg_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_iocdisable(struct bfa_s *bfa)
+{
+}
+
+
+
+/**
+ *  hal_sgpg_public BFA SGPG public functions
+ */
+
+bfa_status_t
+bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
+{
+	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+	struct bfa_sgpg_s *hsgpg;
+	int i;
+
+	bfa_trc_fp(bfa, nsgpgs);
+
+	if (mod->free_sgpgs < nsgpgs)
+		return BFA_STATUS_ENOMEM;
+
+	for (i = 0; i < nsgpgs; i++) {
+		bfa_q_deq(&mod->sgpg_q, &hsgpg);
+		bfa_assert(hsgpg);
+		list_add_tail(&hsgpg->qe, sgpg_q);
+	}
+
+	mod->free_sgpgs -= nsgpgs;
+	return BFA_STATUS_OK;
+}
+
+void
+bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
+{
+	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+	struct bfa_sgpg_wqe_s *wqe;
+
+	bfa_trc_fp(bfa, nsgpg);
+
+	mod->free_sgpgs += nsgpg;
+	bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);
+
+	list_splice_tail_init(sgpg_q, &mod->sgpg_q);
+
+	if (list_empty(&mod->sgpg_wait_q))
+		return;
+
+	/**
+	 * satisfy as many waiting requests as possible
+	 */
+	do {
+		wqe = bfa_q_first(&mod->sgpg_wait_q);
+		if (mod->free_sgpgs < wqe->nsgpg)
+			nsgpg = mod->free_sgpgs;
+		else
+			nsgpg = wqe->nsgpg;
+		bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
+		wqe->nsgpg -= nsgpg;
+		if (wqe->nsgpg == 0) {
+			list_del(&wqe->qe);
+			wqe->cbfn(wqe->cbarg);
+		}
+	} while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
+}
+
+void
+bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
+{
+	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+
+	bfa_assert(nsgpg > 0);
+	bfa_assert(nsgpg > mod->free_sgpgs);
+
+	wqe->nsgpg_total = wqe->nsgpg = nsgpg;
+
+	/**
+	 * allocate any left to this one first
+	 */
+	if (mod->free_sgpgs) {
+		/**
+		 * no one else is waiting for SGPG
+		 */
+		bfa_assert(list_empty(&mod->sgpg_wait_q));
+		list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
+		wqe->nsgpg -= mod->free_sgpgs;
+		mod->free_sgpgs = 0;
+	}
+
+	list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
+}
+
+void
+bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
+{
+	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+
+	bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
+	list_del(&wqe->qe);
+
+	if (wqe->nsgpg_total != wqe->nsgpg)
+		bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
+				   wqe->nsgpg_total - wqe->nsgpg);
+}
+
+void
+bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
+		   void *cbarg)
+{
+	INIT_LIST_HEAD(&wqe->sgpg_q);
+	wqe->cbfn = cbfn;
+	wqe->cbarg = cbarg;
+}
+
+/**
+ *  UF related functions
+ */
+/*
+ *****************************************************************************
+ * Internal functions
+ *****************************************************************************
+ */
+static void
+__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_uf_s   *uf = cbarg;
+	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
+
+	if (complete)
+		ufm->ufrecv(ufm->cbarg, uf);
+}
+
+static void
+claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+	u32 uf_pb_tot_sz;
+
+	ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
+	ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
+	uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
+							BFA_DMA_ALIGN_SZ);
+
+	bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
+	bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
+
+	bfa_os_memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
+}
+
+static void
+claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+	struct bfi_uf_buf_post_s *uf_bp_msg;
+	struct bfi_sge_s      *sge;
+	union bfi_addr_u      sga_zero = { {0} };
+	u16 i;
+	u16 buf_len;
+
+	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
+	uf_bp_msg = ufm->uf_buf_posts;
+
+	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
+	     i++, uf_bp_msg++) {
+		bfa_os_memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
+
+		uf_bp_msg->buf_tag = i;
+		buf_len = sizeof(struct bfa_uf_buf_s);
+		uf_bp_msg->buf_len = bfa_os_htons(buf_len);
+		bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
+			    bfa_lpuid(ufm->bfa));
+
+		sge = uf_bp_msg->sge;
+		sge[0].sg_len = buf_len;
+		sge[0].flags = BFI_SGE_DATA_LAST;
+		bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
+		bfa_sge_to_be(sge);
+
+		sge[1].sg_len = buf_len;
+		sge[1].flags = BFI_SGE_PGDLEN;
+		sge[1].sga = sga_zero;
+		bfa_sge_to_be(&sge[1]);
+	}
+
+	/**
+	 * advance pointer beyond consumed memory
+	 */
+	bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
+}
+
+static void
+claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+	u16 i;
+	struct bfa_uf_s   *uf;
+
+	/*
+	 * Claim block of memory for UF list
+	 */
+	ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
+
+	/*
+	 * Initialize UFs and queue it in UF free queue
+	 */
+	for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
+		bfa_os_memset(uf, 0, sizeof(struct bfa_uf_s));
+		uf->bfa = ufm->bfa;
+		uf->uf_tag = i;
+		uf->pb_len = sizeof(struct bfa_uf_buf_s);
+		uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
+		uf->buf_pa = ufm_pbs_pa(ufm, i);
+		list_add_tail(&uf->qe, &ufm->uf_free_q);
+	}
+
+	/**
+	 * advance memory pointer
+	 */
+	bfa_meminfo_kva(mi) = (u8 *) uf;
+}
+
+static void
+uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+	claim_uf_pbs(ufm, mi);
+	claim_ufs(ufm, mi);
+	claim_uf_post_msgs(ufm, mi);
+}
+
+static void
+bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
+{
+	u32 num_ufs = cfg->fwcfg.num_uf_bufs;
+
+	/*
+	 * dma-able memory for UF posted bufs
+	 */
+	*dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
+							BFA_DMA_ALIGN_SZ);
+
+	/*
+	 * kernel Virtual memory for UFs and UF buf post msg copies
+	 */
+	*ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
+	*ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
+}
+
+static void
+bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		  struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+
+	bfa_os_memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
+	ufm->bfa = bfa;
+	ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
+	INIT_LIST_HEAD(&ufm->uf_free_q);
+	INIT_LIST_HEAD(&ufm->uf_posted_q);
+
+	uf_mem_claim(ufm, meminfo);
+}
+
+static void
+bfa_uf_detach(struct bfa_s *bfa)
+{
+}
+
+static struct bfa_uf_s *
+bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
+{
+	struct bfa_uf_s   *uf;
+
+	bfa_q_deq(&uf_mod->uf_free_q, &uf);
+	return uf;
+}
+
+static void
+bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
+{
+	list_add_tail(&uf->qe, &uf_mod->uf_free_q);
+}
+
+static bfa_status_t
+bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
+{
+	struct bfi_uf_buf_post_s *uf_post_msg;
+
+	uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
+	if (!uf_post_msg)
+		return BFA_STATUS_FAILED;
+
+	bfa_os_memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
+		      sizeof(struct bfi_uf_buf_post_s));
+	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
+
+	bfa_trc(ufm->bfa, uf->uf_tag);
+
+	list_add_tail(&uf->qe, &ufm->uf_posted_q);
+	return BFA_STATUS_OK;
+}
+
+static void
+bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
+{
+	struct bfa_uf_s   *uf;
+
+	while ((uf = bfa_uf_get(uf_mod)) != NULL) {
+		if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
+			break;
+	}
+}
+
+static void
+uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
+{
+	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+	u16 uf_tag = m->buf_tag;
+	struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
+	struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
+	u8 *buf = &uf_buf->d[0];
+	struct fchs_s *fchs;
+
+	m->frm_len = bfa_os_ntohs(m->frm_len);
+	m->xfr_len = bfa_os_ntohs(m->xfr_len);
+
+	fchs = (struct fchs_s *)uf_buf;
+
+	list_del(&uf->qe);	/* dequeue from posted queue */
+
+	uf->data_ptr = buf;
+	uf->data_len = m->xfr_len;
+
+	bfa_assert(uf->data_len >= sizeof(struct fchs_s));
+
+	if (uf->data_len == sizeof(struct fchs_s)) {
+		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
+			       uf->data_len, (struct fchs_s *)buf);
+	} else {
+		u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
+		bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
+				      BFA_PL_EID_RX, uf->data_len,
+				      (struct fchs_s *)buf, pld_w0);
+	}
+
+	if (bfa->fcs)
+		__bfa_cb_uf_recv(uf, BFA_TRUE);
+	else
+		bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
+}
+
+static void
+bfa_uf_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_uf_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+	struct bfa_uf_s *uf;
+	struct list_head *qe, *qen;
+
+	list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
+		uf = (struct bfa_uf_s *) qe;
+		list_del(&uf->qe);
+		bfa_uf_put(ufm, uf);
+	}
+}
+
+static void
+bfa_uf_start(struct bfa_s *bfa)
+{
+	bfa_uf_post_all(BFA_UF_MOD(bfa));
+}
+
+
+
+/**
+ *  hal_uf_api
+ */
+
+/**
+ * Register handler for all unsolicted recieve frames.
+ *
+ * @param[in]	bfa		BFA instance
+ * @param[in]	ufrecv	receive handler function
+ * @param[in]	cbarg	receive handler arg
+ */
+void
+bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
+{
+	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+
+	ufm->ufrecv = ufrecv;
+	ufm->cbarg = cbarg;
+}
+
+/**
+ *	Free an unsolicited frame back to BFA.
+ *
+ * @param[in]		uf		unsolicited frame to be freed
+ *
+ * @return None
+ */
+void
+bfa_uf_free(struct bfa_uf_s *uf)
+{
+	bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
+	bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
+}
+
+
+
+/**
+ *  uf_pub BFA uf module public functions
+ */
+void
+bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+	bfa_trc(bfa, msg->mhdr.msg_id);
+
+	switch (msg->mhdr.msg_id) {
+	case BFI_UF_I2H_FRM_RCVD:
+		uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
+		break;
+
+	default:
+		bfa_trc(bfa, msg->mhdr.msg_id);
+		bfa_assert(0);
+	}
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
new file mode 100644
index 0000000..9921dad
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -0,0 +1,657 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_SVC_H__
+#define __BFA_SVC_H__
+
+#include "bfa_cs.h"
+#include "bfi_ms.h"
+
+
+/**
+ * Scatter-gather DMA related defines
+ */
+#define BFA_SGPG_MIN	(16)
+
+/**
+ * Alignment macro for SG page allocation
+ */
+#define BFA_SGPG_ROUNDUP(_l) (((_l) + (sizeof(struct bfi_sgpg_s) - 1))	\
+			      & ~(sizeof(struct bfi_sgpg_s) - 1))
+
+struct bfa_sgpg_wqe_s {
+	struct list_head qe;	/*  queue sg page element	*/
+	int	nsgpg;		/*  pages to be allocated	*/
+	int	nsgpg_total;	/*  total pages required	*/
+	void	(*cbfn) (void *cbarg);	/*  callback function	*/
+	void	*cbarg;		/*  callback arg		*/
+	struct list_head sgpg_q;	/*  queue of alloced sgpgs	*/
+};
+
+struct bfa_sgpg_s {
+	struct list_head  qe;	/*  queue sg page element	*/
+	struct bfi_sgpg_s *sgpg;	/*  va of SG page		*/
+	union bfi_addr_u sgpg_pa;	/*  pa of SG page		*/
+};
+
+/**
+ * Given number of SG elements, BFA_SGPG_NPAGE() returns the number of
+ * SG pages required.
+ */
+#define BFA_SGPG_NPAGE(_nsges)  (((_nsges) / BFI_SGPG_DATA_SGES) + 1)
+
+struct bfa_sgpg_mod_s {
+	struct bfa_s *bfa;
+	int		num_sgpgs;	/*  number of SG pages		*/
+	int		free_sgpgs;	/*  number of free SG pages	*/
+	struct bfa_sgpg_s	*hsgpg_arr;	/*  BFA SG page array	*/
+	struct bfi_sgpg_s *sgpg_arr;	/*  actual SG page array	*/
+	u64	sgpg_arr_pa;	/*  SG page array DMA addr	*/
+	struct list_head	sgpg_q;		/*  queue of free SG pages */
+	struct list_head	sgpg_wait_q;	/*  wait queue for SG pages */
+};
+#define BFA_SGPG_MOD(__bfa)	(&(__bfa)->modules.sgpg_mod)
+
+bfa_status_t bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q,
+			     int nsgpgs);
+void bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs);
+void bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe,
+		    void (*cbfn) (void *cbarg), void *cbarg);
+void bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpgs);
+void bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe);
+
+
+/**
+ * FCXP related defines
+ */
+#define BFA_FCXP_MIN		(1)
+#define BFA_FCXP_MAX_IBUF_SZ	(2 * 1024 + 256)
+#define BFA_FCXP_MAX_LBUF_SZ	(4 * 1024 + 256)
+
+struct bfa_fcxp_mod_s {
+	struct bfa_s      *bfa;		/* backpointer to BFA */
+	struct bfa_fcxp_s *fcxp_list;	/* array of FCXPs */
+	u16	num_fcxps;	/* max num FCXP requests */
+	struct list_head  fcxp_free_q;	/* free FCXPs */
+	struct list_head  fcxp_active_q;	/* active FCXPs */
+	void		*req_pld_list_kva;	/* list of FCXP req pld */
+	u64	req_pld_list_pa;	/* list of FCXP req pld */
+	void		*rsp_pld_list_kva;	/* list of FCXP resp pld */
+	u64	rsp_pld_list_pa;	/* list of FCXP resp pld */
+	struct list_head  wait_q;		/* wait queue for free fcxp */
+	u32	req_pld_sz;
+	u32	rsp_pld_sz;
+};
+
+#define BFA_FCXP_MOD(__bfa)		(&(__bfa)->modules.fcxp_mod)
+#define BFA_FCXP_FROM_TAG(__mod, __tag)	(&(__mod)->fcxp_list[__tag])
+
+typedef void    (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp,
+				   void *cb_arg, bfa_status_t req_status,
+				   u32 rsp_len, u32 resid_len,
+				   struct fchs_s *rsp_fchs);
+
+typedef u64 (*bfa_fcxp_get_sgaddr_t) (void *bfad_fcxp, int sgeid);
+typedef u32 (*bfa_fcxp_get_sglen_t) (void *bfad_fcxp, int sgeid);
+typedef void (*bfa_cb_fcxp_send_t) (void *bfad_fcxp, struct bfa_fcxp_s *fcxp,
+				    void *cbarg, enum bfa_status req_status,
+				    u32 rsp_len, u32 resid_len,
+				    struct fchs_s *rsp_fchs);
+typedef void (*bfa_fcxp_alloc_cbfn_t) (void *cbarg, struct bfa_fcxp_s *fcxp);
+
+
+
+/**
+ * Information needed for a FCXP request
+ */
+struct bfa_fcxp_req_info_s {
+	struct bfa_rport_s *bfa_rport;
+					/** Pointer to the bfa rport that was
+					 * returned from bfa_rport_create().
+					 * This could be left NULL for WKA or
+					 * for FCXP interactions before the
+					 * rport nexus is established
+					 */
+	struct fchs_s	fchs;	/*  request FC header structure */
+	u8		cts;	/*  continous sequence */
+	u8		class;	/*  FC class for the request/response */
+	u16	max_frmsz;	/*  max send frame size */
+	u16	vf_id;	/*  vsan tag if applicable */
+	u8		lp_tag;	/*  lport tag */
+	u32	req_tot_len;	/*  request payload total length */
+};
+
+struct bfa_fcxp_rsp_info_s {
+	struct fchs_s	rsp_fchs;
+				/** !< Response frame's FC header will
+				 * be sent back in this field */
+	u8		rsp_timeout;
+				/** !< timeout in seconds, 0-no response
+				 */
+	u8		rsvd2[3];
+	u32	rsp_maxlen;	/*  max response length expected */
+};
+
+struct bfa_fcxp_s {
+	struct list_head	qe;		/*  fcxp queue element */
+	bfa_sm_t	sm;		/*  state machine */
+	void		*caller;	/*  driver or fcs */
+	struct bfa_fcxp_mod_s *fcxp_mod;
+	/*  back pointer to fcxp mod */
+	u16	fcxp_tag;	/*  internal tag */
+	struct bfa_fcxp_req_info_s req_info;
+	/*  request info */
+	struct bfa_fcxp_rsp_info_s rsp_info;
+	/*  response info */
+	u8	use_ireqbuf;	/*  use internal req buf */
+	u8		use_irspbuf;	/*  use internal rsp buf */
+	u32	nreq_sgles;	/*  num request SGLEs */
+	u32	nrsp_sgles;	/*  num response SGLEs */
+	struct list_head req_sgpg_q;	/*  SG pages for request buf */
+	struct list_head req_sgpg_wqe;	/*  wait queue for req SG page */
+	struct list_head rsp_sgpg_q;	/*  SG pages for response buf */
+	struct list_head rsp_sgpg_wqe;	/*  wait queue for rsp SG page */
+
+	bfa_fcxp_get_sgaddr_t req_sga_cbfn;
+	/*  SG elem addr user function */
+	bfa_fcxp_get_sglen_t req_sglen_cbfn;
+	/*  SG elem len user function */
+	bfa_fcxp_get_sgaddr_t rsp_sga_cbfn;
+	/*  SG elem addr user function */
+	bfa_fcxp_get_sglen_t rsp_sglen_cbfn;
+	/*  SG elem len user function */
+	bfa_cb_fcxp_send_t send_cbfn;   /*  send completion callback */
+	void		*send_cbarg;	/*  callback arg */
+	struct bfa_sge_s   req_sge[BFA_FCXP_MAX_SGES];
+	/*  req SG elems */
+	struct bfa_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];
+	/*  rsp SG elems */
+	u8		rsp_status;	/*  comp: rsp status */
+	u32	rsp_len;	/*  comp: actual response len */
+	u32	residue_len;	/*  comp: residual rsp length */
+	struct fchs_s	rsp_fchs;	/*  comp: response fchs */
+	struct bfa_cb_qe_s    hcb_qe;	/*  comp: callback qelem */
+	struct bfa_reqq_wait_s	reqq_wqe;
+	bfa_boolean_t	reqq_waiting;
+};
+
+struct bfa_fcxp_wqe_s {
+	struct list_head		qe;
+	bfa_fcxp_alloc_cbfn_t	alloc_cbfn;
+	void		*alloc_cbarg;
+	void		*caller;
+	struct bfa_s	*bfa;
+	int		nreq_sgles;
+	int		nrsp_sgles;
+	bfa_fcxp_get_sgaddr_t	req_sga_cbfn;
+	bfa_fcxp_get_sglen_t	req_sglen_cbfn;
+	bfa_fcxp_get_sgaddr_t	rsp_sga_cbfn;
+	bfa_fcxp_get_sglen_t	rsp_sglen_cbfn;
+};
+
+#define BFA_FCXP_REQ_PLD(_fcxp)		(bfa_fcxp_get_reqbuf(_fcxp))
+#define BFA_FCXP_RSP_FCHS(_fcxp)	(&((_fcxp)->rsp_info.fchs))
+#define BFA_FCXP_RSP_PLD(_fcxp)		(bfa_fcxp_get_rspbuf(_fcxp))
+
+#define BFA_FCXP_REQ_PLD_PA(_fcxp)				\
+	((_fcxp)->fcxp_mod->req_pld_list_pa +			\
+	 ((_fcxp)->fcxp_mod->req_pld_sz  * (_fcxp)->fcxp_tag))
+
+#define BFA_FCXP_RSP_PLD_PA(_fcxp)				\
+	((_fcxp)->fcxp_mod->rsp_pld_list_pa +			\
+	 ((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag))
+
+void	bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+
+/**
+ * RPORT related defines
+ */
+#define BFA_RPORT_MIN	4
+
+struct bfa_rport_mod_s {
+	struct bfa_rport_s *rps_list;	/*  list of rports	*/
+	struct list_head	rp_free_q;	/*  free bfa_rports	*/
+	struct list_head	rp_active_q;	/*  free bfa_rports	*/
+	u16	num_rports;	/*  number of rports	*/
+};
+
+#define BFA_RPORT_MOD(__bfa)	(&(__bfa)->modules.rport_mod)
+
+/**
+ * Convert rport tag to RPORT
+ */
+#define BFA_RPORT_FROM_TAG(__bfa, _tag)				\
+	(BFA_RPORT_MOD(__bfa)->rps_list +			\
+	 ((_tag) & (BFA_RPORT_MOD(__bfa)->num_rports - 1)))
+
+/*
+ * protected functions
+ */
+void	bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+/**
+ *	BFA rport information.
+ */
+struct bfa_rport_info_s {
+	u16	max_frmsz;	/*  max rcv pdu size		    */
+	u32	pid:24,	/*  remote port ID		    */
+		lp_tag:8;	/*  tag			    */
+	u32	local_pid:24,	/*  local port ID		    */
+		cisc:8;	/*  CIRO supported		    */
+	u8	fc_class;	/*  supported FC classes. enum fc_cos */
+	u8	vf_en;		/*  virtual fabric enable	    */
+	u16	vf_id;		/*  virtual fabric ID		    */
+	enum bfa_port_speed speed;	/*  Rport's current speed	    */
+};
+
+/**
+ * BFA rport data structure
+ */
+struct bfa_rport_s {
+	struct list_head	qe;	/*  queue element		    */
+	bfa_sm_t	sm;		/*  state machine		    */
+	struct bfa_s	*bfa;		/*  backpointer to BFA		    */
+	void		*rport_drv;	/*  fcs/driver rport object	    */
+	u16	fw_handle;	/*  firmware rport handle	    */
+	u16	rport_tag;	/*  BFA rport tag		    */
+	struct bfa_rport_info_s rport_info; /*  rport info from fcs/driver */
+	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq     */
+	struct bfa_cb_qe_s hcb_qe;	/*  BFA callback qelem		    */
+	struct bfa_rport_hal_stats_s stats; /*  BFA rport statistics	    */
+	struct bfa_rport_qos_attr_s qos_attr;
+	union a {
+		bfa_status_t	status;	/*  f/w status */
+		void		*fw_msg; /*  QoS scn event		    */
+	} event_arg;
+};
+#define BFA_RPORT_FC_COS(_rport)	((_rport)->rport_info.fc_class)
+
+
+/**
+ * UF - unsolicited receive related defines
+ */
+
+#define BFA_UF_MIN	(4)
+
+
+struct bfa_uf_s {
+	struct list_head	qe;	/*  queue element		*/
+	struct bfa_s		*bfa;	/*  bfa instance		*/
+	u16	uf_tag;		/*  identifying tag fw msgs	*/
+	u16	vf_id;
+	u16	src_rport_handle;
+	u16	rsvd;
+	u8		*data_ptr;
+	u16	data_len;	/*  actual receive length	*/
+	u16	pb_len;		/*  posted buffer length	*/
+	void		*buf_kva;	/*  buffer virtual address	*/
+	u64	buf_pa;		/*  buffer physical address	*/
+	struct bfa_cb_qe_s hcb_qe;	/*  comp: BFA comp qelem	*/
+	struct bfa_sge_s sges[BFI_SGE_INLINE_MAX];
+};
+
+/**
+ *      Callback prototype for unsolicited frame receive handler.
+ *
+ * @param[in]           cbarg           callback arg for receive handler
+ * @param[in]           uf              unsolicited frame descriptor
+ *
+ * @return None
+ */
+typedef void (*bfa_cb_uf_recv_t) (void *cbarg, struct bfa_uf_s *uf);
+
+struct bfa_uf_mod_s {
+	struct bfa_s *bfa;		/*  back pointer to BFA */
+	struct bfa_uf_s *uf_list;	/*  array of UFs */
+	u16	num_ufs;	/*  num unsolicited rx frames */
+	struct list_head	uf_free_q;	/*  free UFs */
+	struct list_head	uf_posted_q;	/*  UFs posted to IOC */
+	struct bfa_uf_buf_s *uf_pbs_kva;	/*  list UF bufs request pld */
+	u64	uf_pbs_pa;	/*  phy addr for UF bufs */
+	struct bfi_uf_buf_post_s *uf_buf_posts;
+	/*  pre-built UF post msgs */
+	bfa_cb_uf_recv_t ufrecv;	/*  uf recv handler function */
+	void		*cbarg;		/*  uf receive handler arg */
+};
+
+#define BFA_UF_MOD(__bfa)	(&(__bfa)->modules.uf_mod)
+
+#define ufm_pbs_pa(_ufmod, _uftag)					\
+	((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag))
+
+void	bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+#define BFA_UF_BUFSZ	(2 * 1024 + 256)
+
+/**
+ * @todo private
+ */
+struct bfa_uf_buf_s {
+	u8		d[BFA_UF_BUFSZ];
+};
+
+
+/**
+ * LPS - bfa lport login/logout service interface
+ */
+struct bfa_lps_s {
+	struct list_head	qe;	/*  queue element		*/
+	struct bfa_s	*bfa;		/*  parent bfa instance	*/
+	bfa_sm_t	sm;		/*  finite state machine	*/
+	u8		lp_tag;		/*  lport tag			*/
+	u8		reqq;		/*  lport request queue	*/
+	u8		alpa;		/*  ALPA for loop topologies	*/
+	u32	lp_pid;		/*  lport port ID		*/
+	bfa_boolean_t	fdisc;		/*  snd FDISC instead of FLOGI	*/
+	bfa_boolean_t	auth_en;	/*  enable authentication	*/
+	bfa_boolean_t	auth_req;	/*  authentication required	*/
+	bfa_boolean_t	npiv_en;	/*  NPIV is allowed by peer	*/
+	bfa_boolean_t	fport;		/*  attached peer is F_PORT	*/
+	bfa_boolean_t	brcd_switch;	/*  attached peer is brcd sw	*/
+	bfa_status_t	status;		/*  login status		*/
+	u16		pdusz;		/*  max receive PDU size	*/
+	u16		pr_bbcred;	/*  BB_CREDIT from peer		*/
+	u8		lsrjt_rsn;	/*  LSRJT reason		*/
+	u8		lsrjt_expl;	/*  LSRJT explanation		*/
+	wwn_t		pwwn;		/*  port wwn of lport		*/
+	wwn_t		nwwn;		/*  node wwn of lport		*/
+	wwn_t		pr_pwwn;	/*  port wwn of lport peer	*/
+	wwn_t		pr_nwwn;	/*  node wwn of lport peer	*/
+	mac_t		lp_mac;		/*  fpma/spma MAC for lport	*/
+	mac_t		fcf_mac;	/*  FCF MAC of lport		*/
+	struct bfa_reqq_wait_s	wqe;	/*  request wait queue element	*/
+	void		*uarg;		/*  user callback arg		*/
+	struct bfa_cb_qe_s hcb_qe;	/*  comp: callback qelem	*/
+	struct bfi_lps_login_rsp_s *loginrsp;
+	bfa_eproto_status_t ext_status;
+};
+
+struct bfa_lps_mod_s {
+	struct list_head		lps_free_q;
+	struct list_head		lps_active_q;
+	struct bfa_lps_s	*lps_arr;
+	int			num_lps;
+};
+
+#define BFA_LPS_MOD(__bfa)		(&(__bfa)->modules.lps_mod)
+#define BFA_LPS_FROM_TAG(__mod, __tag)	(&(__mod)->lps_arr[__tag])
+
+/*
+ * external functions
+ */
+void	bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+
+/**
+ * FCPORT related defines
+ */
+
+#define BFA_FCPORT(_bfa)	(&((_bfa)->modules.port))
+typedef void (*bfa_cb_port_t) (void *cbarg, enum bfa_status status);
+
+/**
+ * Link notification data structure
+ */
+struct bfa_fcport_ln_s {
+	struct bfa_fcport_s	*fcport;
+	bfa_sm_t		sm;
+	struct bfa_cb_qe_s	ln_qe;	/*  BFA callback queue elem for ln */
+	enum bfa_port_linkstate ln_event; /*  ln event for callback */
+};
+
+struct bfa_fcport_trunk_s {
+	struct bfa_trunk_attr_s	attr;
+};
+
+/**
+ * BFA FC port data structure
+ */
+struct bfa_fcport_s {
+	struct bfa_s		*bfa;	/*  parent BFA instance */
+	bfa_sm_t		sm;	/*  port state machine */
+	wwn_t			nwwn;	/*  node wwn of physical port */
+	wwn_t			pwwn;	/*  port wwn of physical oprt */
+	enum bfa_port_speed speed_sup;
+	/*  supported speeds */
+	enum bfa_port_speed speed;	/*  current speed */
+	enum bfa_port_topology topology;	/*  current topology */
+	u8			myalpa;	/*  my ALPA in LOOP topology */
+	u8			rsvd[3];
+	struct bfa_port_cfg_s	cfg;	/*  current port configuration */
+	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
+	struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
+	struct bfa_reqq_wait_s	reqq_wait;
+	/*  to wait for room in reqq */
+	struct bfa_reqq_wait_s	svcreq_wait;
+	/*  to wait for room in reqq */
+	struct bfa_reqq_wait_s	stats_reqq_wait;
+	/*  to wait for room in reqq (stats) */
+	void			*event_cbarg;
+	void			(*event_cbfn) (void *cbarg,
+					       enum bfa_port_linkstate event);
+	union {
+		union bfi_fcport_i2h_msg_u i2hmsg;
+	} event_arg;
+	void			*bfad;	/*  BFA driver handle */
+	struct bfa_fcport_ln_s	ln; /*  Link Notification */
+	struct bfa_cb_qe_s	hcb_qe;	/*  BFA callback queue elem */
+	struct bfa_timer_s	timer;	/*  timer */
+	u32		msgtag;	/*  fimrware msg tag for reply */
+	u8			*stats_kva;
+	u64		stats_pa;
+	union bfa_fcport_stats_u *stats;
+	union bfa_fcport_stats_u *stats_ret; /*  driver stats location */
+	bfa_status_t		stats_status; /*  stats/statsclr status */
+	bfa_boolean_t		stats_busy; /*  outstanding stats/statsclr */
+	bfa_boolean_t		stats_qfull;
+	u32		stats_reset_time; /*  stats reset time stamp */
+	bfa_cb_port_t		stats_cbfn; /*  driver callback function */
+	void			*stats_cbarg; /* *!< user callback arg */
+	bfa_boolean_t		diag_busy; /*  diag busy status */
+	bfa_boolean_t		beacon; /*  port beacon status */
+	bfa_boolean_t		link_e2e_beacon; /*  link beacon status */
+	struct bfa_fcport_trunk_s trunk;
+	u16		fcoe_vlan;
+};
+
+#define BFA_FCPORT_MOD(__bfa)	(&(__bfa)->modules.fcport)
+
+/*
+ * protected functions
+ */
+void bfa_fcport_init(struct bfa_s *bfa);
+void bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+/*
+ * bfa fcport API functions
+ */
+bfa_status_t bfa_fcport_enable(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_disable(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_speed(struct bfa_s *bfa,
+				  enum bfa_port_speed speed);
+enum bfa_port_speed bfa_fcport_get_speed(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_topology(struct bfa_s *bfa,
+				     enum bfa_port_topology topo);
+enum bfa_port_topology bfa_fcport_get_topology(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa);
+bfa_boolean_t bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa);
+u8 bfa_fcport_get_myalpa(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_clr_hardalpa(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxsize);
+u16 bfa_fcport_get_maxfrsize(struct bfa_s *bfa);
+u8 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa);
+void bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr);
+wwn_t bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node);
+void bfa_fcport_event_register(struct bfa_s *bfa,
+			void (*event_cbfn) (void *cbarg,
+			enum bfa_port_linkstate event), void *event_cbarg);
+bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
+void bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off);
+void bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off);
+bfa_status_t bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa,
+					  enum bfa_port_speed speed);
+enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
+
+void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
+void bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status);
+void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
+		       bfa_boolean_t link_e2e_beacon);
+void bfa_fcport_qos_get_attr(struct bfa_s *bfa,
+			     struct bfa_qos_attr_s *qos_attr);
+void bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
+				struct bfa_qos_vc_attr_s *qos_vc_attr);
+bfa_status_t bfa_fcport_get_qos_stats(struct bfa_s *bfa,
+				      union bfa_fcport_stats_u *stats,
+				      bfa_cb_port_t cbfn, void *cbarg);
+bfa_status_t bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
+					void *cbarg);
+bfa_status_t bfa_fcport_get_fcoe_stats(struct bfa_s *bfa,
+				       union bfa_fcport_stats_u *stats,
+				       bfa_cb_port_t cbfn, void *cbarg);
+bfa_status_t bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
+					 void *cbarg);
+bfa_boolean_t     bfa_fcport_is_ratelim(struct bfa_s *bfa);
+bfa_boolean_t	bfa_fcport_is_linkup(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
+				  union bfa_fcport_stats_u *stats,
+				  bfa_cb_port_t cbfn, void *cbarg);
+bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
+				    void *cbarg);
+bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
+
+/*
+ * bfa rport API functions
+ */
+struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv);
+void bfa_rport_delete(struct bfa_rport_s *rport);
+void bfa_rport_online(struct bfa_rport_s *rport,
+		      struct bfa_rport_info_s *rport_info);
+void bfa_rport_offline(struct bfa_rport_s *rport);
+void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed);
+void bfa_rport_get_stats(struct bfa_rport_s *rport,
+			 struct bfa_rport_hal_stats_s *stats);
+void bfa_rport_clear_stats(struct bfa_rport_s *rport);
+void bfa_cb_rport_online(void *rport);
+void bfa_cb_rport_offline(void *rport);
+void bfa_cb_rport_qos_scn_flowid(void *rport,
+				 struct bfa_rport_qos_attr_s old_qos_attr,
+				 struct bfa_rport_qos_attr_s new_qos_attr);
+void bfa_cb_rport_qos_scn_prio(void *rport,
+			       struct bfa_rport_qos_attr_s old_qos_attr,
+			       struct bfa_rport_qos_attr_s new_qos_attr);
+void bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
+			    struct bfa_rport_qos_attr_s *qos_attr);
+
+/*
+ * bfa fcxp API functions
+ */
+struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
+				  int nreq_sgles, int nrsp_sgles,
+				  bfa_fcxp_get_sgaddr_t get_req_sga,
+				  bfa_fcxp_get_sglen_t get_req_sglen,
+				  bfa_fcxp_get_sgaddr_t get_rsp_sga,
+				  bfa_fcxp_get_sglen_t get_rsp_sglen);
+void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+				bfa_fcxp_alloc_cbfn_t alloc_cbfn,
+				void *cbarg, void *bfad_fcxp,
+				int nreq_sgles, int nrsp_sgles,
+				bfa_fcxp_get_sgaddr_t get_req_sga,
+				bfa_fcxp_get_sglen_t get_req_sglen,
+				bfa_fcxp_get_sgaddr_t get_rsp_sga,
+				bfa_fcxp_get_sglen_t get_rsp_sglen);
+void bfa_fcxp_walloc_cancel(struct bfa_s *bfa,
+			    struct bfa_fcxp_wqe_s *wqe);
+void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp);
+
+void *bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp);
+void *bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp);
+
+void bfa_fcxp_free(struct bfa_fcxp_s *fcxp);
+
+void bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
+		   u16 vf_id, u8 lp_tag,
+		   bfa_boolean_t cts, enum fc_cos cos,
+		   u32 reqlen, struct fchs_s *fchs,
+		   bfa_cb_fcxp_send_t cbfn,
+		   void *cbarg,
+		   u32 rsp_maxlen, u8 rsp_timeout);
+bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp);
+u32 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp);
+u32 bfa_fcxp_get_maxrsp(struct bfa_s *bfa);
+
+static inline void *
+bfa_uf_get_frmbuf(struct bfa_uf_s *uf)
+{
+	return uf->data_ptr;
+}
+
+static inline   u16
+bfa_uf_get_frmlen(struct bfa_uf_s *uf)
+{
+	return uf->data_len;
+}
+
+/*
+ * bfa uf API functions
+ */
+void bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv,
+			  void *cbarg);
+void bfa_uf_free(struct bfa_uf_s *uf);
+
+/**
+ * bfa lport service api
+ */
+
+u32 bfa_lps_get_max_vport(struct bfa_s *bfa);
+struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
+void bfa_lps_delete(struct bfa_lps_s *lps);
+void bfa_lps_discard(struct bfa_lps_s *lps);
+void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,
+		   u16 pdusz, wwn_t pwwn, wwn_t nwwn,
+		   bfa_boolean_t auth_en);
+void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,
+		   wwn_t pwwn, wwn_t nwwn);
+void bfa_lps_flogo(struct bfa_lps_s *lps);
+void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
+u8 bfa_lps_get_tag(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps);
+bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps);
+u32 bfa_lps_get_pid(struct bfa_lps_s *lps);
+u32 bfa_lps_get_base_pid(struct bfa_s *bfa);
+u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
+u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps);
+wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps);
+wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps);
+u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps);
+u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps);
+mac_t bfa_lps_get_lp_mac(struct bfa_lps_s *lps);
+void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
+void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
+void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
+void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
+
+void bfa_trunk_enable_cfg(struct bfa_s *bfa);
+bfa_status_t bfa_trunk_enable(struct bfa_s *bfa);
+bfa_status_t bfa_trunk_disable(struct bfa_s *bfa);
+bfa_status_t bfa_trunk_get_attr(struct bfa_s *bfa,
+		struct bfa_trunk_attr_s *attr);
+
+#endif /* __BFA_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfa_timer.c b/drivers/scsi/bfa/bfa_timer.c
deleted file mode 100644
index cb76481..0000000
--- a/drivers/scsi/bfa/bfa_timer.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa_timer.h>
-#include <cs/bfa_debug.h>
-
-void
-bfa_timer_init(struct bfa_timer_mod_s *mod)
-{
-	INIT_LIST_HEAD(&mod->timer_q);
-}
-
-void
-bfa_timer_beat(struct bfa_timer_mod_s *mod)
-{
-	struct list_head        *qh = &mod->timer_q;
-	struct list_head        *qe, *qe_next;
-	struct bfa_timer_s *elem;
-	struct list_head         timedout_q;
-
-	INIT_LIST_HEAD(&timedout_q);
-
-	qe = bfa_q_next(qh);
-
-	while (qe != qh) {
-		qe_next = bfa_q_next(qe);
-
-		elem = (struct bfa_timer_s *) qe;
-		if (elem->timeout <= BFA_TIMER_FREQ) {
-			elem->timeout = 0;
-			list_del(&elem->qe);
-			list_add_tail(&elem->qe, &timedout_q);
-		} else {
-			elem->timeout -= BFA_TIMER_FREQ;
-		}
-
-		qe = qe_next;	/* go to next elem */
-	}
-
-	/*
-	 * Pop all the timeout entries
-	 */
-	while (!list_empty(&timedout_q)) {
-		bfa_q_deq(&timedout_q, &elem);
-		elem->timercb(elem->arg);
-	}
-}
-
-/**
- * Should be called with lock protection
- */
-void
-bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
-		    void (*timercb) (void *), void *arg, unsigned int timeout)
-{
-
-	bfa_assert(timercb != NULL);
-	bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
-
-	timer->timeout = timeout;
-	timer->timercb = timercb;
-	timer->arg = arg;
-
-	list_add_tail(&timer->qe, &mod->timer_q);
-}
-
-/**
- * Should be called with lock protection
- */
-void
-bfa_timer_stop(struct bfa_timer_s *timer)
-{
-	bfa_assert(!list_empty(&timer->qe));
-
-	list_del(&timer->qe);
-}
diff --git a/drivers/scsi/bfa/bfa_trcmod_priv.h b/drivers/scsi/bfa/bfa_trcmod_priv.h
deleted file mode 100644
index a7a8261..0000000
--- a/drivers/scsi/bfa/bfa_trcmod_priv.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  hal_trcmod.h BFA trace modules
- */
-
-#ifndef __BFA_TRCMOD_PRIV_H__
-#define __BFA_TRCMOD_PRIV_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
-	BFA_TRC_HAL_INTR	= 1,
-	BFA_TRC_HAL_FCXP	= 2,
-	BFA_TRC_HAL_UF		= 3,
-	BFA_TRC_HAL_RPORT	= 4,
-	BFA_TRC_HAL_FCPIM	= 5,
-	BFA_TRC_HAL_IOIM	= 6,
-	BFA_TRC_HAL_TSKIM	= 7,
-	BFA_TRC_HAL_ITNIM	= 8,
-	BFA_TRC_HAL_FCPORT	= 9,
-	BFA_TRC_HAL_SGPG	= 10,
-	BFA_TRC_HAL_FLASH	= 11,
-	BFA_TRC_HAL_DEBUG	= 12,
-	BFA_TRC_HAL_WWN		= 13,
-	BFA_TRC_HAL_FLASH_RAW	= 14,
-	BFA_TRC_HAL_SBOOT	= 15,
-	BFA_TRC_HAL_SBOOT_IO	= 16,
-	BFA_TRC_HAL_SBOOT_INTR	= 17,
-	BFA_TRC_HAL_SBTEST	= 18,
-	BFA_TRC_HAL_IPFC	= 19,
-	BFA_TRC_HAL_IOCFC	= 20,
-	BFA_TRC_HAL_FCPTM	= 21,
-	BFA_TRC_HAL_IOTM	= 22,
-	BFA_TRC_HAL_TSKTM	= 23,
-	BFA_TRC_HAL_TIN		= 24,
-	BFA_TRC_HAL_LPS		= 25,
-	BFA_TRC_HAL_FCDIAG	= 26,
-	BFA_TRC_HAL_PBIND	= 27,
-	BFA_TRC_HAL_IOCFC_CT	= 28,
-	BFA_TRC_HAL_IOCFC_CB	= 29,
-	BFA_TRC_HAL_IOCFC_Q	= 30,
-};
-
-#endif /* __BFA_TRCMOD_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_tskim.c b/drivers/scsi/bfa/bfa_tskim.c
deleted file mode 100644
index ad9aaae..0000000
--- a/drivers/scsi/bfa/bfa_tskim.c
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_cb_ioim_macros.h>
-
-BFA_TRC_FILE(HAL, TSKIM);
-
-/**
- * task management completion handling
- */
-#define bfa_tskim_qcomp(__tskim, __cbfn) do {			\
-	bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe,	\
-			 __cbfn, (__tskim));      \
-	bfa_tskim_notify_comp(__tskim);      \
-} while (0)
-
-#define bfa_tskim_notify_comp(__tskim) do {			 \
-	if ((__tskim)->notify)					 \
-		bfa_itnim_tskdone((__tskim)->itnim);      \
-} while (0)
-
-/*
- * forward declarations
- */
-static void     __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);
-static void     __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);
-static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,
-					       lun_t lun);
-static void     bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);
-static void     bfa_tskim_cleanp_comp(void *tskim_cbarg);
-static void     bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);
-static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);
-static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);
-static void     bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);
-
-/**
- *  bfa_tskim_sm
- */
-
-enum bfa_tskim_event {
-	BFA_TSKIM_SM_START        = 1,  /*  TM command start            */
-	BFA_TSKIM_SM_DONE         = 2,  /*  TM completion               */
-	BFA_TSKIM_SM_QRESUME      = 3,  /*  resume after qfull          */
-	BFA_TSKIM_SM_HWFAIL       = 5,  /*  IOC h/w failure event       */
-	BFA_TSKIM_SM_HCB          = 6,  /*  BFA callback completion     */
-	BFA_TSKIM_SM_IOS_DONE     = 7,  /*  IO and sub TM completions   */
-	BFA_TSKIM_SM_CLEANUP      = 8,  /*  TM cleanup on ITN offline   */
-	BFA_TSKIM_SM_CLEANUP_DONE = 9,  /*  TM abort completion         */
-};
-
-static void     bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim,
-					enum bfa_tskim_event event);
-static void     bfa_tskim_sm_active(struct bfa_tskim_s *tskim,
-					enum bfa_tskim_event event);
-static void     bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim,
-					 enum bfa_tskim_event event);
-static void     bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim,
-					 enum bfa_tskim_event event);
-static void     bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim,
-				       enum bfa_tskim_event event);
-static void     bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
-				       enum bfa_tskim_event event);
-static void     bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
-				     enum bfa_tskim_event event);
-
-/**
- *      Task management command beginning state.
- */
-static void
-bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_START:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_active);
-		bfa_tskim_gather_ios(tskim);
-
-		/**
-		 * If device is offline, do not send TM on wire. Just cleanup
-		 * any pending IO requests and complete TM request.
-		 */
-		if (!bfa_itnim_is_online(tskim->itnim)) {
-			bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
-			tskim->tsk_status = BFI_TSKIM_STS_OK;
-			bfa_tskim_cleanup_ios(tskim);
-			return;
-		}
-
-		if (!bfa_tskim_send(tskim)) {
-			bfa_sm_set_state(tskim, bfa_tskim_sm_qfull);
-			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
-					  &tskim->reqq_wait);
-		}
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-/**
- * brief
- *	TM command is active, awaiting completion from firmware to
- *	cleanup IO requests in TM scope.
- */
-static void
-bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_DONE:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
-		bfa_tskim_cleanup_ios(tskim);
-		break;
-
-	case BFA_TSKIM_SM_CLEANUP:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
-		if (!bfa_tskim_send_abort(tskim)) {
-			bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup_qfull);
-			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
-				&tskim->reqq_wait);
-		}
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_tskim_iocdisable_ios(tskim);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-/**
- *	An active TM is being cleaned up since ITN is offline. Awaiting cleanup
- *	completion event from firmware.
- */
-static void
-bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_DONE:
-		/**
-		 * Ignore and wait for ABORT completion from firmware.
-		 */
-		break;
-
-	case BFA_TSKIM_SM_CLEANUP_DONE:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
-		bfa_tskim_cleanup_ios(tskim);
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_tskim_iocdisable_ios(tskim);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-static void
-bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_IOS_DONE:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_done);
-		break;
-
-	case BFA_TSKIM_SM_CLEANUP:
-		/**
-		 * Ignore, TM command completed on wire.
-		 * Notify TM conmpletion on IO cleanup completion.
-		 */
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_tskim_iocdisable_ios(tskim);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-/**
- *      Task management command is waiting for room in request CQ
- */
-static void
-bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_QRESUME:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_active);
-		bfa_tskim_send(tskim);
-		break;
-
-	case BFA_TSKIM_SM_CLEANUP:
-		/**
-		 * No need to send TM on wire since ITN is offline.
-		 */
-		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
-		bfa_reqq_wcancel(&tskim->reqq_wait);
-		bfa_tskim_cleanup_ios(tskim);
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_reqq_wcancel(&tskim->reqq_wait);
-		bfa_tskim_iocdisable_ios(tskim);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-/**
- *      Task management command is active, awaiting for room in request CQ
- *	to send clean up request.
- */
-static void
-bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
-		enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_DONE:
-		bfa_reqq_wcancel(&tskim->reqq_wait);
-		/**
-		 *
-		 * Fall through !!!
-		 */
-
-	case BFA_TSKIM_SM_QRESUME:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
-		bfa_tskim_send_abort(tskim);
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_reqq_wcancel(&tskim->reqq_wait);
-		bfa_tskim_iocdisable_ios(tskim);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-/**
- *      BFA callback is pending
- */
-static void
-bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_HCB:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
-		bfa_tskim_free(tskim);
-		break;
-
-	case BFA_TSKIM_SM_CLEANUP:
-		bfa_tskim_notify_comp(tskim);
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-
-
-/**
- *  bfa_tskim_private
- */
-
-static void
-__bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_tskim_s *tskim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
-		return;
-	}
-
-	bfa_stats(tskim->itnim, tm_success);
-	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, tskim->tsk_status);
-}
-
-static void
-__bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_tskim_s *tskim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
-		return;
-	}
-
-	bfa_stats(tskim->itnim, tm_failures);
-	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk,
-			   BFI_TSKIM_STS_FAILED);
-}
-
-static          bfa_boolean_t
-bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)
-{
-	switch (tskim->tm_cmnd) {
-	case FCP_TM_TARGET_RESET:
-		return BFA_TRUE;
-
-	case FCP_TM_ABORT_TASK_SET:
-	case FCP_TM_CLEAR_TASK_SET:
-	case FCP_TM_LUN_RESET:
-	case FCP_TM_CLEAR_ACA:
-		return (tskim->lun == lun);
-
-	default:
-		bfa_assert(0);
-	}
-
-	return BFA_FALSE;
-}
-
-/**
- *      Gather affected IO requests and task management commands.
- */
-static void
-bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
-{
-	struct bfa_itnim_s *itnim = tskim->itnim;
-	struct bfa_ioim_s *ioim;
-	struct list_head        *qe, *qen;
-
-	INIT_LIST_HEAD(&tskim->io_q);
-
-	/**
-	 * Gather any active IO requests first.
-	 */
-	list_for_each_safe(qe, qen, &itnim->io_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		if (bfa_tskim_match_scope
-		    (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
-			list_del(&ioim->qe);
-			list_add_tail(&ioim->qe, &tskim->io_q);
-		}
-	}
-
-	/**
-	 * Failback any pending IO requests immediately.
-	 */
-	list_for_each_safe(qe, qen, &itnim->pending_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		if (bfa_tskim_match_scope
-		    (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
-			list_del(&ioim->qe);
-			list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-			bfa_ioim_tov(ioim);
-		}
-	}
-}
-
-/**
- * 		IO cleanup completion
- */
-static void
-bfa_tskim_cleanp_comp(void *tskim_cbarg)
-{
-	struct bfa_tskim_s *tskim = tskim_cbarg;
-
-	bfa_stats(tskim->itnim, tm_io_comps);
-	bfa_sm_send_event(tskim, BFA_TSKIM_SM_IOS_DONE);
-}
-
-/**
- *      Gather affected IO requests and task management commands.
- */
-static void
-bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
-{
-	struct bfa_ioim_s *ioim;
-	struct list_head        *qe, *qen;
-
-	bfa_wc_init(&tskim->wc, bfa_tskim_cleanp_comp, tskim);
-
-	list_for_each_safe(qe, qen, &tskim->io_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		bfa_wc_up(&tskim->wc);
-		bfa_ioim_cleanup_tm(ioim, tskim);
-	}
-
-	bfa_wc_wait(&tskim->wc);
-}
-
-/**
- *      Send task management request to firmware.
- */
-static bfa_boolean_t
-bfa_tskim_send(struct bfa_tskim_s *tskim)
-{
-	struct bfa_itnim_s *itnim = tskim->itnim;
-	struct bfi_tskim_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(tskim->bfa, itnim->reqq);
-	if (!m)
-		return BFA_FALSE;
-
-	/**
-	 * build i/o request message next
-	 */
-	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
-			bfa_lpuid(tskim->bfa));
-
-	m->tsk_tag = bfa_os_htons(tskim->tsk_tag);
-	m->itn_fhdl = tskim->itnim->rport->fw_handle;
-	m->t_secs = tskim->tsecs;
-	m->lun = tskim->lun;
-	m->tm_flags = tskim->tm_cmnd;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(tskim->bfa, itnim->reqq);
-	return BFA_TRUE;
-}
-
-/**
- *      Send abort request to cleanup an active TM to firmware.
- */
-static bfa_boolean_t
-bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
-{
-	struct bfa_itnim_s             *itnim = tskim->itnim;
-	struct bfi_tskim_abortreq_s    *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(tskim->bfa, itnim->reqq);
-	if (!m)
-		return BFA_FALSE;
-
-	/**
-	 * build i/o request message next
-	 */
-	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
-			bfa_lpuid(tskim->bfa));
-
-	m->tsk_tag  = bfa_os_htons(tskim->tsk_tag);
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(tskim->bfa, itnim->reqq);
-	return BFA_TRUE;
-}
-
-/**
- *      Call to resume task management cmnd waiting for room in request queue.
- */
-static void
-bfa_tskim_qresume(void *cbarg)
-{
-	struct bfa_tskim_s *tskim = cbarg;
-
-	bfa_fcpim_stats(tskim->fcpim, qresumes);
-	bfa_stats(tskim->itnim, tm_qresumes);
-	bfa_sm_send_event(tskim, BFA_TSKIM_SM_QRESUME);
-}
-
-/**
- * Cleanup IOs associated with a task mangement command on IOC failures.
- */
-static void
-bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)
-{
-	struct bfa_ioim_s *ioim;
-	struct list_head        *qe, *qen;
-
-	list_for_each_safe(qe, qen, &tskim->io_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		bfa_ioim_iocdisable(ioim);
-	}
-}
-
-
-
-/**
- *  bfa_tskim_friend
- */
-
-/**
- * Notification on completions from related ioim.
- */
-void
-bfa_tskim_iodone(struct bfa_tskim_s *tskim)
-{
-	bfa_wc_down(&tskim->wc);
-}
-
-/**
- * Handle IOC h/w failure notification from itnim.
- */
-void
-bfa_tskim_iocdisable(struct bfa_tskim_s *tskim)
-{
-	tskim->notify = BFA_FALSE;
-	bfa_stats(tskim->itnim, tm_iocdowns);
-	bfa_sm_send_event(tskim, BFA_TSKIM_SM_HWFAIL);
-}
-
-/**
- * Cleanup TM command and associated IOs as part of ITNIM offline.
- */
-void
-bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
-{
-	tskim->notify = BFA_TRUE;
-	bfa_stats(tskim->itnim, tm_cleanups);
-	bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP);
-}
-
-/**
- *      Memory allocation and initialization.
- */
-void
-bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
-{
-	struct bfa_tskim_s *tskim;
-	u16        i;
-
-	INIT_LIST_HEAD(&fcpim->tskim_free_q);
-
-	tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo);
-	fcpim->tskim_arr = tskim;
-
-	for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
-		/*
-		 * initialize TSKIM
-		 */
-		bfa_os_memset(tskim, 0, sizeof(struct bfa_tskim_s));
-		tskim->tsk_tag = i;
-		tskim->bfa     = fcpim->bfa;
-		tskim->fcpim   = fcpim;
-		tskim->notify  = BFA_FALSE;
-		bfa_reqq_winit(&tskim->reqq_wait, bfa_tskim_qresume,
-				   tskim);
-		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
-
-		list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
-	}
-
-	bfa_meminfo_kva(minfo) = (u8 *) tskim;
-}
-
-void
-bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim)
-{
-    /**
-     * @todo
-     */
-}
-
-void
-bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
-	struct bfa_tskim_s *tskim;
-	u16        tsk_tag = bfa_os_ntohs(rsp->tsk_tag);
-
-	tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);
-	bfa_assert(tskim->tsk_tag == tsk_tag);
-
-	tskim->tsk_status = rsp->tsk_status;
-
-	/**
-	 * Firmware sends BFI_TSKIM_STS_ABORTED status for abort
-	 * requests. All other statuses are for normal completions.
-	 */
-	if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {
-		bfa_stats(tskim->itnim, tm_cleanup_comps);
-		bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);
-	} else {
-		bfa_stats(tskim->itnim, tm_fw_rsps);
-		bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);
-	}
-}
-
-
-
-/**
- *  bfa_tskim_api
- */
-
-
-struct bfa_tskim_s *
-bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfa_tskim_s *tskim;
-
-	bfa_q_deq(&fcpim->tskim_free_q, &tskim);
-
-	if (!tskim)
-		bfa_fcpim_stats(fcpim, no_tskims);
-	else
-		tskim->dtsk = dtsk;
-
-	return tskim;
-}
-
-void
-bfa_tskim_free(struct bfa_tskim_s *tskim)
-{
-	bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
-	list_del(&tskim->qe);
-	list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);
-}
-
-/**
- *      Start a task management command.
- *
- * @param[in]       tskim       BFA task management command instance
- * @param[in]       itnim       i-t nexus for the task management command
- * @param[in]       lun         lun, if applicable
- * @param[in]       tm_cmnd     Task management command code.
- * @param[in]       t_secs      Timeout in seconds
- *
- * @return None.
- */
-void
-bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun,
-		    enum fcp_tm_cmnd tm_cmnd, u8 tsecs)
-{
-	tskim->itnim   = itnim;
-	tskim->lun     = lun;
-	tskim->tm_cmnd = tm_cmnd;
-	tskim->tsecs   = tsecs;
-	tskim->notify  = BFA_FALSE;
-	bfa_stats(itnim, tm_cmnds);
-
-	list_add_tail(&tskim->qe, &itnim->tsk_q);
-	bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_uf.c b/drivers/scsi/bfa/bfa_uf.c
deleted file mode 100644
index b9a9a68..0000000
--- a/drivers/scsi/bfa/bfa_uf.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_uf.c BFA unsolicited frame receive implementation
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_uf.h>
-#include <cs/bfa_debug.h>
-
-BFA_TRC_FILE(HAL, UF);
-BFA_MODULE(uf);
-
-/*
- *****************************************************************************
- * Internal functions
- *****************************************************************************
- */
-static void
-__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_uf_s   *uf = cbarg;
-	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
-
-	if (complete)
-		ufm->ufrecv(ufm->cbarg, uf);
-}
-
-static void
-claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
-	u32        uf_pb_tot_sz;
-
-	ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
-	ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
-	uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
-							BFA_DMA_ALIGN_SZ);
-
-	bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
-	bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
-
-	bfa_os_memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
-}
-
-static void
-claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
-	struct bfi_uf_buf_post_s *uf_bp_msg;
-	struct bfi_sge_s      *sge;
-	union bfi_addr_u      sga_zero = { {0} };
-	u16        i;
-	u16        buf_len;
-
-	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
-	uf_bp_msg = ufm->uf_buf_posts;
-
-	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
-	     i++, uf_bp_msg++) {
-		bfa_os_memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
-
-		uf_bp_msg->buf_tag = i;
-		buf_len = sizeof(struct bfa_uf_buf_s);
-		uf_bp_msg->buf_len = bfa_os_htons(buf_len);
-		bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
-			    bfa_lpuid(ufm->bfa));
-
-		sge = uf_bp_msg->sge;
-		sge[0].sg_len = buf_len;
-		sge[0].flags = BFI_SGE_DATA_LAST;
-		bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
-		bfa_sge_to_be(sge);
-
-		sge[1].sg_len = buf_len;
-		sge[1].flags = BFI_SGE_PGDLEN;
-		sge[1].sga = sga_zero;
-		bfa_sge_to_be(&sge[1]);
-	}
-
-	/**
-	 * advance pointer beyond consumed memory
-	 */
-	bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
-}
-
-static void
-claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
-	u16        i;
-	struct bfa_uf_s   *uf;
-
-	/*
-	 * Claim block of memory for UF list
-	 */
-	ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
-
-	/*
-	 * Initialize UFs and queue it in UF free queue
-	 */
-	for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
-		bfa_os_memset(uf, 0, sizeof(struct bfa_uf_s));
-		uf->bfa = ufm->bfa;
-		uf->uf_tag = i;
-		uf->pb_len = sizeof(struct bfa_uf_buf_s);
-		uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
-		uf->buf_pa = ufm_pbs_pa(ufm, i);
-		list_add_tail(&uf->qe, &ufm->uf_free_q);
-	}
-
-	/**
-	 * advance memory pointer
-	 */
-	bfa_meminfo_kva(mi) = (u8 *) uf;
-}
-
-static void
-uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
-	claim_uf_pbs(ufm, mi);
-	claim_ufs(ufm, mi);
-	claim_uf_post_msgs(ufm, mi);
-}
-
-static void
-bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
-{
-	u32        num_ufs = cfg->fwcfg.num_uf_bufs;
-
-	/*
-	 * dma-able memory for UF posted bufs
-	 */
-	*dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
-							BFA_DMA_ALIGN_SZ);
-
-	/*
-	 * kernel Virtual memory for UFs and UF buf post msg copies
-	 */
-	*ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
-	*ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
-}
-
-static void
-bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		  struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
-
-	bfa_os_memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
-	ufm->bfa = bfa;
-	ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
-	INIT_LIST_HEAD(&ufm->uf_free_q);
-	INIT_LIST_HEAD(&ufm->uf_posted_q);
-
-	uf_mem_claim(ufm, meminfo);
-}
-
-static void
-bfa_uf_detach(struct bfa_s *bfa)
-{
-}
-
-static struct bfa_uf_s *
-bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
-{
-	struct bfa_uf_s   *uf;
-
-	bfa_q_deq(&uf_mod->uf_free_q, &uf);
-	return uf;
-}
-
-static void
-bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
-{
-	list_add_tail(&uf->qe, &uf_mod->uf_free_q);
-}
-
-static bfa_status_t
-bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
-{
-	struct bfi_uf_buf_post_s *uf_post_msg;
-
-	uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
-	if (!uf_post_msg)
-		return BFA_STATUS_FAILED;
-
-	bfa_os_memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
-		      sizeof(struct bfi_uf_buf_post_s));
-	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
-
-	bfa_trc(ufm->bfa, uf->uf_tag);
-
-	list_add_tail(&uf->qe, &ufm->uf_posted_q);
-	return BFA_STATUS_OK;
-}
-
-static void
-bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
-{
-	struct bfa_uf_s   *uf;
-
-	while ((uf = bfa_uf_get(uf_mod)) != NULL) {
-		if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
-			break;
-	}
-}
-
-static void
-uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
-{
-	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
-	u16        uf_tag = m->buf_tag;
-	struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
-	struct bfa_uf_s   *uf = &ufm->uf_list[uf_tag];
-	u8        *buf = &uf_buf->d[0];
-	struct fchs_s         *fchs;
-
-	m->frm_len = bfa_os_ntohs(m->frm_len);
-	m->xfr_len = bfa_os_ntohs(m->xfr_len);
-
-	fchs = (struct fchs_s *) uf_buf;
-
-	list_del(&uf->qe);	/* dequeue from posted queue */
-
-	uf->data_ptr = buf;
-	uf->data_len = m->xfr_len;
-
-	bfa_assert(uf->data_len >= sizeof(struct fchs_s));
-
-	if (uf->data_len == sizeof(struct fchs_s)) {
-		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
-			       uf->data_len, (struct fchs_s *) buf);
-	} else {
-		u32        pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
-		bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
-				      BFA_PL_EID_RX, uf->data_len,
-				      (struct fchs_s *) buf, pld_w0);
-	}
-
-	if (bfa->fcs)
-		__bfa_cb_uf_recv(uf, BFA_TRUE);
-	else
-		bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
-}
-
-static void
-bfa_uf_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_uf_iocdisable(struct bfa_s *bfa)
-{
-	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
-	struct bfa_uf_s   *uf;
-	struct list_head        *qe, *qen;
-
-	list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
-		uf = (struct bfa_uf_s *) qe;
-		list_del(&uf->qe);
-		bfa_uf_put(ufm, uf);
-	}
-}
-
-static void
-bfa_uf_start(struct bfa_s *bfa)
-{
-	bfa_uf_post_all(BFA_UF_MOD(bfa));
-}
-
-
-
-/**
- *  bfa_uf_api
- */
-
-/**
- * 		Register handler for all unsolicted recieve frames.
- *
- * @param[in]	bfa		BFA instance
- * @param[in]	ufrecv	receive handler function
- * @param[in]	cbarg	receive handler arg
- */
-void
-bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
-{
-	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
-
-	ufm->ufrecv = ufrecv;
-	ufm->cbarg = cbarg;
-}
-
-/**
- * 		Free an unsolicited frame back to BFA.
- *
- * @param[in]		uf		unsolicited frame to be freed
- *
- * @return None
- */
-void
-bfa_uf_free(struct bfa_uf_s *uf)
-{
-	bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
-	bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
-}
-
-
-
-/**
- *  uf_pub BFA uf module public functions
- */
-
-void
-bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
-{
-	bfa_trc(bfa, msg->mhdr.msg_id);
-
-	switch (msg->mhdr.msg_id) {
-	case BFI_UF_I2H_FRM_RCVD:
-		uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
-		break;
-
-	default:
-		bfa_trc(bfa, msg->mhdr.msg_id);
-		bfa_assert(0);
-	}
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_uf_priv.h b/drivers/scsi/bfa/bfa_uf_priv.h
deleted file mode 100644
index bcb490f..0000000
--- a/drivers/scsi/bfa/bfa_uf_priv.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_UF_PRIV_H__
-#define __BFA_UF_PRIV_H__
-
-#include <cs/bfa_sm.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_uf.h>
-
-#define BFA_UF_MIN	(4)
-
-struct bfa_uf_mod_s {
-	struct bfa_s *bfa;		/*  back pointer to BFA */
-	struct bfa_uf_s *uf_list;	/*  array of UFs */
-	u16	num_ufs;	/*  num unsolicited rx frames */
-	struct list_head 	uf_free_q;	/*  free UFs */
-	struct list_head 	uf_posted_q;	/*  UFs posted to IOC */
-	struct bfa_uf_buf_s *uf_pbs_kva;	/*  list UF bufs request pld */
-	u64	uf_pbs_pa;	/*  phy addr for UF bufs */
-	struct bfi_uf_buf_post_s *uf_buf_posts;
-					/*  pre-built UF post msgs */
-	bfa_cb_uf_recv_t ufrecv;	/*  uf recv handler function */
-	void		*cbarg;		/*  uf receive handler arg */
-};
-
-#define BFA_UF_MOD(__bfa)	(&(__bfa)->modules.uf_mod)
-
-#define ufm_pbs_pa(_ufmod, _uftag)	\
-	((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag))
-
-void	bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-
-#endif /* __BFA_UF_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index ca04cc9..4d8784e 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -18,46 +18,62 @@
 /**
  *  bfad.c Linux driver PCI interface module.
  */
-
-#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/kthread.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/firmware.h>
+#include <asm/uaccess.h>
+#include <asm/fcntl.h>
+
 #include "bfad_drv.h"
 #include "bfad_im.h"
-#include "bfad_tm.h"
-#include "bfad_ipfc.h"
-#include "bfad_trcmod.h"
-#include <fcb/bfa_fcb_vf.h>
-#include <fcb/bfa_fcb_rport.h>
-#include <fcb/bfa_fcb_port.h>
-#include <fcb/bfa_fcb.h>
+#include "bfa_fcs.h"
+#include "bfa_os_inc.h"
+#include "bfa_defs.h"
+#include "bfa.h"
 
 BFA_TRC_FILE(LDRV, BFAD);
 DEFINE_MUTEX(bfad_mutex);
 LIST_HEAD(bfad_list);
-static int      bfad_inst;
-int bfad_supported_fc4s;
 
-static char     *host_name;
-static char     *os_name;
-static char     *os_patch;
-static int      num_rports;
-static int      num_ios;
-static int      num_tms;
-static int      num_fcxps;
-static int      num_ufbufs;
-static int      reqq_size;
-static int      rspq_size;
-static int      num_sgpgs;
-static int      rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;
-static int      bfa_io_max_sge = BFAD_IO_MAX_SGE;
-static int      log_level = BFA_LOG_WARNING;
-static int      ioc_auto_recover = BFA_TRUE;
-static int      ipfc_enable = BFA_FALSE;
-static int	fdmi_enable = BFA_TRUE;
-int 		bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
-int      	bfa_linkup_delay = -1;
+static int	bfad_inst;
+static int      num_sgpgs_parm;
+int		supported_fc4s;
+char		*host_name, *os_name, *os_patch;
+int		num_rports, num_ios, num_tms;
+int		num_fcxps, num_ufbufs;
+int		reqq_size, rspq_size, num_sgpgs;
+int		rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;
+int		bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
+int		bfa_io_max_sge = BFAD_IO_MAX_SGE;
+int		log_level = 3; /* WARNING log level */
+int		ioc_auto_recover = BFA_TRUE;
+int		bfa_linkup_delay = -1;
+int		fdmi_enable = BFA_TRUE;
+int		pcie_max_read_reqsz;
 int		bfa_debugfs_enable = 1;
+int		msix_disable_cb = 0, msix_disable_ct = 0;
+
+u32	bfi_image_ct_fc_size, bfi_image_ct_cna_size, bfi_image_cb_fc_size;
+u32     *bfi_image_ct_fc, *bfi_image_ct_cna, *bfi_image_cb_fc;
+
+const char *msix_name_ct[] = {
+	"cpe0", "cpe1", "cpe2", "cpe3",
+	"rme0", "rme1", "rme2", "rme3",
+	"ctrl" };
+
+const char *msix_name_cb[] = {
+	"cpe0", "cpe1", "cpe2", "cpe3",
+	"rme0", "rme1", "rme2", "rme3",
+	"eemc", "elpu0", "elpu1", "epss", "mlpu" };
+
+MODULE_FIRMWARE(BFAD_FW_FILE_CT_FC);
+MODULE_FIRMWARE(BFAD_FW_FILE_CT_CNA);
+MODULE_FIRMWARE(BFAD_FW_FILE_CB_FC);
 
 module_param(os_name, charp, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(os_name, "OS name of the hba host machine");
@@ -66,8 +82,8 @@
 module_param(host_name, charp, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(host_name, "Hostname of the hba host machine");
 module_param(num_rports, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(num_rports, "Max number of rports supported per port"
-		" (physical/logical), default=1024");
+MODULE_PARM_DESC(num_rports, "Max number of rports supported per port "
+				"(physical/logical), default=1024");
 module_param(num_ios, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(num_ios, "Max number of ioim requests, default=2000");
 module_param(num_tms, int, S_IRUGO | S_IWUSR);
@@ -75,120 +91,277 @@
 module_param(num_fcxps, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(num_fcxps, "Max number of fcxp requests, default=64");
 module_param(num_ufbufs, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(num_ufbufs, "Max number of unsolicited frame buffers,"
-		" default=64");
+MODULE_PARM_DESC(num_ufbufs, "Max number of unsolicited frame "
+				"buffers, default=64");
 module_param(reqq_size, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(reqq_size, "Max number of request queue elements,"
-		" default=256");
+MODULE_PARM_DESC(reqq_size, "Max number of request queue elements, "
+				"default=256");
 module_param(rspq_size, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rspq_size, "Max number of response queue elements,"
-		" default=64");
+MODULE_PARM_DESC(rspq_size, "Max number of response queue elements, "
+				"default=64");
 module_param(num_sgpgs, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(num_sgpgs, "Number of scatter/gather pages, default=2048");
 module_param(rport_del_timeout, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rport_del_timeout, "Rport delete timeout, default=90 secs,"
-		" Range[>0]");
+MODULE_PARM_DESC(rport_del_timeout, "Rport delete timeout, default=90 secs, "
+					"Range[>0]");
 module_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32,"
-		" Range[>0]");
+MODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32, Range[>0]");
 module_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(bfa_io_max_sge, "Max io scatter/gather elements, default=255");
 module_param(log_level, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(log_level, "Driver log level, default=3,"
-		" Range[Critical:1|Error:2|Warning:3|Info:4]");
+MODULE_PARM_DESC(log_level, "Driver log level, default=3, "
+				"Range[Critical:1|Error:2|Warning:3|Info:4]");
 module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1,"
-		" Range[off:0|on:1]");
-module_param(ipfc_enable, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ipfc_enable, "Enable IPoFC, default=0, Range[off:0|on:1]");
+MODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1, "
+				"Range[off:0|on:1]");
 module_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(bfa_linkup_delay, "Link up delay, default=30 secs for boot"
-		" port. Otherwise Range[>0]");
+MODULE_PARM_DESC(bfa_linkup_delay, "Link up delay, default=30 secs for "
+			"boot port. Otherwise 10 secs in RHEL4 & 0 for "
+			"[RHEL5, SLES10, ESX40] Range[>0]");
+module_param(msix_disable_cb, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(msix_disable_cb, "Disable Message Signaled Interrupts "
+			"for Brocade-415/425/815/825 cards, default=0, "
+			" Range[false:0|true:1]");
+module_param(msix_disable_ct, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(msix_disable_ct, "Disable Message Signaled Interrupts "
+			"if possible for Brocade-1010/1020/804/1007/902/1741 "
+			"cards, default=0, Range[false:0|true:1]");
 module_param(fdmi_enable, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1,"
-		" Range[false:0|true:1]");
+MODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1, "
+				"Range[false:0|true:1]");
+module_param(pcie_max_read_reqsz, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pcie_max_read_reqsz, "PCIe max read request size, default=0 "
+		"(use system setting), Range[128|256|512|1024|2048|4096]");
 module_param(bfa_debugfs_enable, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(bfa_debugfs_enable, "Enables debugfs feature, default=1,"
 		" Range[false:0|true:1]");
 
-/*
- * Stores the module parm num_sgpgs value;
- * used to reset for bfad next instance.
+static void
+bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_operational(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_stopping(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_failed(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_fcs_exit(struct bfad_s *bfad, enum bfad_sm_event event);
+
+/**
+ * Beginning state for the driver instance, awaiting the pci_probe event
  */
-static int num_sgpgs_parm;
-
-static bfa_status_t
-bfad_fc4_probe(struct bfad_s *bfad)
+static void
+bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event)
 {
-	int             rc;
+	bfa_trc(bfad, event);
 
-	rc = bfad_im_probe(bfad);
-	if (rc != BFA_STATUS_OK)
-		goto ext;
+	switch (event) {
+	case BFAD_E_CREATE:
+		bfa_sm_set_state(bfad, bfad_sm_created);
+		bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad,
+						"%s", "bfad_worker");
+		if (IS_ERR(bfad->bfad_tsk)) {
+			printk(KERN_INFO "bfad[%d]: Kernel thread "
+				"creation failed!\n", bfad->inst_no);
+			bfa_sm_send_event(bfad, BFAD_E_KTHREAD_CREATE_FAILED);
+		}
+		bfa_sm_send_event(bfad, BFAD_E_INIT);
+		break;
 
-	bfad_tm_probe(bfad);
+	case BFAD_E_STOP:
+		/* Ignore stop; already in uninit */
+		break;
 
-	if (ipfc_enable)
-		bfad_ipfc_probe(bfad);
+	default:
+		bfa_sm_fault(bfad, event);
+	}
+}
 
-	bfad->bfad_flags |= BFAD_FC4_PROBE_DONE;
-ext:
-	return rc;
+/**
+ * Driver Instance is created, awaiting event INIT to initialize the bfad
+ */
+static void
+bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)
+{
+	unsigned long flags;
+
+	bfa_trc(bfad, event);
+
+	switch (event) {
+	case BFAD_E_INIT:
+		bfa_sm_set_state(bfad, bfad_sm_initializing);
+
+		init_completion(&bfad->comp);
+
+		/* Enable Interrupt and wait bfa_init completion */
+		if (bfad_setup_intr(bfad)) {
+			printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",
+					bfad->inst_no);
+			bfa_sm_send_event(bfad, BFAD_E_INTR_INIT_FAILED);
+			break;
+		}
+
+		spin_lock_irqsave(&bfad->bfad_lock, flags);
+		bfa_init(&bfad->bfa);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+		/* Set up interrupt handler for each vectors */
+		if ((bfad->bfad_flags & BFAD_MSIX_ON) &&
+			bfad_install_msix_handler(bfad)) {
+			printk(KERN_WARNING "%s: install_msix failed, bfad%d\n",
+				__func__, bfad->inst_no);
+		}
+
+		bfad_init_timer(bfad);
+
+		wait_for_completion(&bfad->comp);
+
+		if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
+			bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);
+		} else {
+			bfad->bfad_flags |= BFAD_HAL_INIT_FAIL;
+			bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);
+		}
+
+		break;
+
+	case BFAD_E_KTHREAD_CREATE_FAILED:
+		bfa_sm_set_state(bfad, bfad_sm_uninit);
+		break;
+
+	default:
+		bfa_sm_fault(bfad, event);
+	}
 }
 
 static void
-bfad_fc4_probe_undo(struct bfad_s *bfad)
+bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event)
 {
-	bfad_im_probe_undo(bfad);
-	bfad_tm_probe_undo(bfad);
-	if (ipfc_enable)
-		bfad_ipfc_probe_undo(bfad);
-	bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+	int	retval;
+	unsigned long	flags;
+
+	bfa_trc(bfad, event);
+
+	switch (event) {
+	case BFAD_E_INIT_SUCCESS:
+		kthread_stop(bfad->bfad_tsk);
+		spin_lock_irqsave(&bfad->bfad_lock, flags);
+		bfad->bfad_tsk = NULL;
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+		retval = bfad_start_ops(bfad);
+		if (retval != BFA_STATUS_OK)
+			break;
+		bfa_sm_set_state(bfad, bfad_sm_operational);
+		break;
+
+	case BFAD_E_INTR_INIT_FAILED:
+		bfa_sm_set_state(bfad, bfad_sm_uninit);
+		kthread_stop(bfad->bfad_tsk);
+		spin_lock_irqsave(&bfad->bfad_lock, flags);
+		bfad->bfad_tsk = NULL;
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		break;
+
+	case BFAD_E_INIT_FAILED:
+		bfa_sm_set_state(bfad, bfad_sm_failed);
+		break;
+	default:
+		bfa_sm_fault(bfad, event);
+	}
 }
 
 static void
-bfad_fc4_probe_post(struct bfad_s *bfad)
+bfad_sm_failed(struct bfad_s *bfad, enum bfad_sm_event event)
 {
-	if (bfad->im)
-		bfad_im_probe_post(bfad->im);
+	int	retval;
 
-	bfad_tm_probe_post(bfad);
-	if (ipfc_enable)
-		bfad_ipfc_probe_post(bfad);
-}
+	bfa_trc(bfad, event);
 
-static bfa_status_t
-bfad_fc4_port_new(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
-{
-	int             rc = BFA_STATUS_FAILED;
+	switch (event) {
+	case BFAD_E_INIT_SUCCESS:
+		retval = bfad_start_ops(bfad);
+		if (retval != BFA_STATUS_OK)
+			break;
+		bfa_sm_set_state(bfad, bfad_sm_operational);
+		break;
 
-	if (roles & BFA_PORT_ROLE_FCP_IM)
-		rc = bfad_im_port_new(bfad, port);
-	if (rc != BFA_STATUS_OK)
-		goto ext;
+	case BFAD_E_STOP:
+		if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
+			bfad_uncfg_pport(bfad);
+		if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE) {
+			bfad_im_probe_undo(bfad);
+			bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+		}
+		bfad_stop(bfad);
+		break;
 
-	if (roles & BFA_PORT_ROLE_FCP_TM)
-		rc = bfad_tm_port_new(bfad, port);
-	if (rc != BFA_STATUS_OK)
-		goto ext;
+	case BFAD_E_EXIT_COMP:
+		bfa_sm_set_state(bfad, bfad_sm_uninit);
+		bfad_remove_intr(bfad);
+		del_timer_sync(&bfad->hal_tmo);
+		break;
 
-	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
-		rc = bfad_ipfc_port_new(bfad, port, port->pvb_type);
-ext:
-	return rc;
+	default:
+		bfa_sm_fault(bfad, event);
+	}
 }
 
 static void
-bfad_fc4_port_delete(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
+bfad_sm_operational(struct bfad_s *bfad, enum bfad_sm_event event)
 {
-	if (roles & BFA_PORT_ROLE_FCP_IM)
-		bfad_im_port_delete(bfad, port);
+	bfa_trc(bfad, event);
 
-	if (roles & BFA_PORT_ROLE_FCP_TM)
-		bfad_tm_port_delete(bfad, port);
+	switch (event) {
+	case BFAD_E_STOP:
+		bfa_sm_set_state(bfad, bfad_sm_fcs_exit);
+		bfad_fcs_stop(bfad);
+		break;
 
-	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
-		bfad_ipfc_port_delete(bfad, port);
+	default:
+		bfa_sm_fault(bfad, event);
+	}
+}
+
+static void
+bfad_sm_fcs_exit(struct bfad_s *bfad, enum bfad_sm_event event)
+{
+	bfa_trc(bfad, event);
+
+	switch (event) {
+	case BFAD_E_FCS_EXIT_COMP:
+		bfa_sm_set_state(bfad, bfad_sm_stopping);
+		bfad_stop(bfad);
+		break;
+
+	default:
+		bfa_sm_fault(bfad, event);
+	}
+}
+
+static void
+bfad_sm_stopping(struct bfad_s *bfad, enum bfad_sm_event event)
+{
+	bfa_trc(bfad, event);
+
+	switch (event) {
+	case BFAD_E_EXIT_COMP:
+		bfa_sm_set_state(bfad, bfad_sm_uninit);
+		bfad_remove_intr(bfad);
+		del_timer_sync(&bfad->hal_tmo);
+		bfad_im_probe_undo(bfad);
+		bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+		bfad_uncfg_pport(bfad);
+		break;
+
+	default:
+		bfa_sm_fault(bfad, event);
+		break;
+	}
 }
 
 /**
@@ -209,12 +382,13 @@
 void
 bfa_cb_init(void *drv, bfa_status_t init_status)
 {
-	struct bfad_s  *bfad = drv;
+	struct bfad_s	      *bfad = drv;
 
 	if (init_status == BFA_STATUS_OK) {
 		bfad->bfad_flags |= BFAD_HAL_INIT_DONE;
 
-		/* If BFAD_HAL_INIT_FAIL flag is set:
+		/*
+		 * If BFAD_HAL_INIT_FAIL flag is set:
 		 * Wake up the kernel thread to start
 		 * the bfad operations after HAL init done
 		 */
@@ -227,26 +401,16 @@
 	complete(&bfad->comp);
 }
 
-
-
 /**
  *  BFA_FCS callbacks
  */
-static struct bfad_port_s *
-bfad_get_drv_port(struct bfad_s *bfad, struct bfad_vf_s *vf_drv,
-		  struct bfad_vport_s *vp_drv)
-{
-	return (vp_drv) ? (&(vp_drv)->drv_port)
-		: ((vf_drv) ? (&(vf_drv)->base_port) : (&(bfad)->pport));
-}
-
 struct bfad_port_s *
-bfa_fcb_port_new(struct bfad_s *bfad, struct bfa_fcs_port_s *port,
-		 enum bfa_port_role roles, struct bfad_vf_s *vf_drv,
+bfa_fcb_lport_new(struct bfad_s *bfad, struct bfa_fcs_lport_s *port,
+		 enum bfa_lport_role roles, struct bfad_vf_s *vf_drv,
 		 struct bfad_vport_s *vp_drv)
 {
-	bfa_status_t    rc;
-	struct bfad_port_s *port_drv;
+	bfa_status_t	rc;
+	struct bfad_port_s    *port_drv;
 
 	if (!vp_drv && !vf_drv) {
 		port_drv = &bfad->pport;
@@ -264,71 +428,32 @@
 
 	port_drv->fcs_port = port;
 	port_drv->roles = roles;
-	rc = bfad_fc4_port_new(bfad, port_drv, roles);
-	if (rc != BFA_STATUS_OK) {
-		bfad_fc4_port_delete(bfad, port_drv, roles);
-		port_drv = NULL;
+
+	if (roles & BFA_LPORT_ROLE_FCP_IM) {
+		rc = bfad_im_port_new(bfad, port_drv);
+		if (rc != BFA_STATUS_OK) {
+			bfad_im_port_delete(bfad, port_drv);
+			port_drv = NULL;
+		}
 	}
 
 	return port_drv;
 }
 
 void
-bfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles,
+bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles,
 		    struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
 {
-	struct bfad_port_s *port_drv;
+	struct bfad_port_s    *port_drv;
 
-	/*
-	 * this will be only called from rmmod context
-	 */
+	/* this will be only called from rmmod context */
 	if (vp_drv && !vp_drv->comp_del) {
-		port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
+		port_drv = (vp_drv) ? (&(vp_drv)->drv_port) :
+				((vf_drv) ? (&(vf_drv)->base_port) :
+				(&(bfad)->pport));
 		bfa_trc(bfad, roles);
-		bfad_fc4_port_delete(bfad, port_drv, roles);
-	}
-}
-
-void
-bfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles,
-		    struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
-{
-	struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
-
-	if (roles & BFA_PORT_ROLE_FCP_IM)
-		bfad_im_port_online(bfad, port_drv);
-
-	if (roles & BFA_PORT_ROLE_FCP_TM)
-		bfad_tm_port_online(bfad, port_drv);
-
-	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
-		bfad_ipfc_port_online(bfad, port_drv);
-
-	bfad->bfad_flags |= BFAD_PORT_ONLINE;
-}
-
-void
-bfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles,
-		     struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
-{
-	struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
-
-	if (roles & BFA_PORT_ROLE_FCP_IM)
-		bfad_im_port_offline(bfad, port_drv);
-
-	if (roles & BFA_PORT_ROLE_FCP_TM)
-		bfad_tm_port_offline(bfad, port_drv);
-
-	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
-		bfad_ipfc_port_offline(bfad, port_drv);
-}
-
-void
-bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv)
-{
-	if (vport_drv->comp_del) {
-		complete(vport_drv->comp_del);
-		return;
+		if (roles & BFA_LPORT_ROLE_FCP_IM)
+			bfad_im_port_delete(bfad, port_drv);
 	}
 }
 
@@ -339,7 +464,7 @@
 bfa_fcb_rport_alloc(struct bfad_s *bfad, struct bfa_fcs_rport_s **rport,
 		    struct bfad_rport_s **rport_drv)
 {
-	bfa_status_t    rc = BFA_STATUS_OK;
+	bfa_status_t	rc = BFA_STATUS_OK;
 
 	*rport_drv = kzalloc(sizeof(struct bfad_rport_s), GFP_ATOMIC);
 	if (*rport_drv == NULL) {
@@ -354,35 +479,43 @@
 }
 
 /**
- * @brief
  * FCS PBC VPORT Create
  */
 void
 bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s pbc_vport)
 {
 
-	struct bfad_pcfg_s *pcfg;
+	struct bfa_lport_cfg_s port_cfg = {0};
+	struct bfad_vport_s   *vport;
+	int rc;
 
-	pcfg = kzalloc(sizeof(struct bfad_pcfg_s), GFP_ATOMIC);
-	if (!pcfg) {
+	vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL);
+	if (!vport) {
 		bfa_trc(bfad, 0);
 		return;
 	}
 
-	pcfg->port_cfg.roles = BFA_PORT_ROLE_FCP_IM;
-	pcfg->port_cfg.pwwn = pbc_vport.vp_pwwn;
-	pcfg->port_cfg.nwwn = pbc_vport.vp_nwwn;
-	pcfg->port_cfg.preboot_vp  = BFA_TRUE;
+	vport->drv_port.bfad = bfad;
+	port_cfg.roles = BFA_LPORT_ROLE_FCP_IM;
+	port_cfg.pwwn = pbc_vport.vp_pwwn;
+	port_cfg.nwwn = pbc_vport.vp_nwwn;
+	port_cfg.preboot_vp  = BFA_TRUE;
 
-	list_add_tail(&pcfg->list_entry, &bfad->pbc_pcfg_list);
+	rc = bfa_fcs_pbc_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, 0,
+				  &port_cfg, vport);
 
-	return;
+	if (rc != BFA_STATUS_OK) {
+		bfa_trc(bfad, 0);
+		return;
+	}
+
+	list_add_tail(&vport->list_entry, &bfad->pbc_vport_list);
 }
 
 void
 bfad_hal_mem_release(struct bfad_s *bfad)
 {
-	int             i;
+	int		i;
 	struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
 	struct bfa_mem_elem_s *meminfo_elem;
 
@@ -395,9 +528,9 @@
 				break;
 			case BFA_MEM_TYPE_DMA:
 				dma_free_coherent(&bfad->pcidev->dev,
-						meminfo_elem->mem_len,
-						meminfo_elem->kva,
-						(dma_addr_t) meminfo_elem->dma);
+					meminfo_elem->mem_len,
+					meminfo_elem->kva,
+					(dma_addr_t) meminfo_elem->dma);
 				break;
 			default:
 				bfa_assert(0);
@@ -434,27 +567,27 @@
 	 * otherwise, the default values will be shown as 0 in sysfs
 	 */
 	num_rports = bfa_cfg->fwcfg.num_rports;
-	num_ios    = bfa_cfg->fwcfg.num_ioim_reqs;
-	num_tms	   = bfa_cfg->fwcfg.num_tskim_reqs;
-	num_fcxps  = bfa_cfg->fwcfg.num_fcxp_reqs;
+	num_ios = bfa_cfg->fwcfg.num_ioim_reqs;
+	num_tms = bfa_cfg->fwcfg.num_tskim_reqs;
+	num_fcxps = bfa_cfg->fwcfg.num_fcxp_reqs;
 	num_ufbufs = bfa_cfg->fwcfg.num_uf_bufs;
-	reqq_size  = bfa_cfg->drvcfg.num_reqq_elems;
-	rspq_size  = bfa_cfg->drvcfg.num_rspq_elems;
-	num_sgpgs  = bfa_cfg->drvcfg.num_sgpgs;
+	reqq_size = bfa_cfg->drvcfg.num_reqq_elems;
+	rspq_size = bfa_cfg->drvcfg.num_rspq_elems;
+	num_sgpgs = bfa_cfg->drvcfg.num_sgpgs;
 }
 
 bfa_status_t
 bfad_hal_mem_alloc(struct bfad_s *bfad)
 {
+	int		i;
 	struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
 	struct bfa_mem_elem_s *meminfo_elem;
-	bfa_status_t    rc = BFA_STATUS_OK;
-	dma_addr_t      phys_addr;
-	int             retry_count = 0;
-	int             reset_value = 1;
-	int             min_num_sgpgs = 512;
-	void           *kva;
-	int             i;
+	dma_addr_t	phys_addr;
+	void	       *kva;
+	bfa_status_t	rc = BFA_STATUS_OK;
+	int retry_count = 0;
+	int reset_value = 1;
+	int min_num_sgpgs = 512;
 
 	bfa_cfg_get_default(&bfad->ioc_cfg);
 
@@ -478,8 +611,7 @@
 			break;
 		case BFA_MEM_TYPE_DMA:
 			kva = dma_alloc_coherent(&bfad->pcidev->dev,
-					meminfo_elem->mem_len,
-					&phys_addr, GFP_KERNEL);
+				meminfo_elem->mem_len, &phys_addr, GFP_KERNEL);
 			if (kva == NULL) {
 				bfad_hal_mem_release(bfad);
 				/*
@@ -487,14 +619,14 @@
 				 * num_sgpages try with half the value.
 				 */
 				if (num_sgpgs > min_num_sgpgs) {
-					printk(KERN_INFO "bfad[%d]: memory"
-						" allocation failed with"
-						" num_sgpgs: %d\n",
+					printk(KERN_INFO
+					"bfad[%d]: memory allocation failed"
+					" with num_sgpgs: %d\n",
 						bfad->inst_no, num_sgpgs);
 					nextLowerInt(&num_sgpgs);
-					printk(KERN_INFO "bfad[%d]: trying to"
-						" allocate memory with"
-						" num_sgpgs: %d\n",
+					printk(KERN_INFO
+					"bfad[%d]: trying to allocate memory"
+					" with num_sgpgs: %d\n",
 						bfad->inst_no, num_sgpgs);
 					retry_count++;
 					goto retry;
@@ -536,11 +668,11 @@
  */
 bfa_status_t
 bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
-			struct bfa_port_cfg_s *port_cfg, struct device *dev)
+		  struct bfa_lport_cfg_s *port_cfg, struct device *dev)
 {
-	struct bfad_vport_s *vport;
-	int rc = BFA_STATUS_OK;
-	unsigned long   flags;
+	struct bfad_vport_s   *vport;
+	int		rc = BFA_STATUS_OK;
+	unsigned long	flags;
 	struct completion fcomp;
 
 	vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL);
@@ -551,18 +683,14 @@
 
 	vport->drv_port.bfad = bfad;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	if (port_cfg->preboot_vp == BFA_TRUE)
-		rc = bfa_fcs_pbc_vport_create(&vport->fcs_vport,
-				&bfad->bfa_fcs, vf_id, port_cfg, vport);
-	else
-		rc = bfa_fcs_vport_create(&vport->fcs_vport,
-				&bfad->bfa_fcs, vf_id, port_cfg, vport);
+	rc = bfa_fcs_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, vf_id,
+				  port_cfg, vport);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	if (rc != BFA_STATUS_OK)
 		goto ext_free_vport;
 
-	if (port_cfg->roles & BFA_PORT_ROLE_FCP_IM) {
+	if (port_cfg->roles & BFA_LPORT_ROLE_FCP_IM) {
 		rc = bfad_im_scsi_host_alloc(bfad, vport->drv_port.im_port,
 							dev);
 		if (rc != BFA_STATUS_OK)
@@ -593,10 +721,10 @@
  */
 bfa_status_t
 bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
-	       struct bfa_port_cfg_s *port_cfg)
+	       struct bfa_lport_cfg_s *port_cfg)
 {
-	struct bfad_vf_s *vf;
-	int             rc = BFA_STATUS_OK;
+	struct bfad_vf_s      *vf;
+	int		rc = BFA_STATUS_OK;
 
 	vf = kzalloc(sizeof(struct bfad_vf_s), GFP_KERNEL);
 	if (!vf) {
@@ -615,9 +743,9 @@
 void
 bfad_bfa_tmo(unsigned long data)
 {
-	struct bfad_s  *bfad = (struct bfad_s *)data;
-	unsigned long   flags;
-	struct list_head  doneq;
+	struct bfad_s	      *bfad = (struct bfad_s *) data;
+	unsigned long	flags;
+	struct list_head	       doneq;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 
@@ -633,7 +761,8 @@
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	}
 
-	mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
+	mod_timer(&bfad->hal_tmo,
+		  jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
 }
 
 void
@@ -643,16 +772,17 @@
 	bfad->hal_tmo.function = bfad_bfa_tmo;
 	bfad->hal_tmo.data = (unsigned long)bfad;
 
-	mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
+	mod_timer(&bfad->hal_tmo,
+		  jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
 }
 
 int
 bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
 {
-	int             rc = -ENODEV;
+	int		rc = -ENODEV;
 
 	if (pci_enable_device(pdev)) {
-		BFA_PRINTF(BFA_ERR, "pci_enable_device fail %p\n", pdev);
+		printk(KERN_ERR "pci_enable_device fail %p\n", pdev);
 		goto out;
 	}
 
@@ -664,14 +794,14 @@
 
 	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
 		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
-			BFA_PRINTF(BFA_ERR, "pci_set_dma_mask fail %p\n", pdev);
+			printk(KERN_ERR "pci_set_dma_mask fail %p\n", pdev);
 			goto out_release_region;
 		}
 
 	bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
 
 	if (bfad->pci_bar0_kva == NULL) {
-		BFA_PRINTF(BFA_ERR, "Fail to map bar0\n");
+		printk(KERN_ERR "Fail to map bar0\n");
 		goto out_release_region;
 	}
 
@@ -688,6 +818,54 @@
 	bfad->pci_attr.pcifn = PCI_FUNC(pdev->devfn);
 
 	bfad->pcidev = pdev;
+
+	/* Adjust PCIe Maximum Read Request Size */
+	if (pcie_max_read_reqsz > 0) {
+		int pcie_cap_reg;
+		u16 pcie_dev_ctl;
+		u16 mask = 0xffff;
+
+		switch (pcie_max_read_reqsz) {
+		case 128:
+			mask = 0x0;
+			break;
+		case 256:
+			mask = 0x1000;
+			break;
+		case 512:
+			mask = 0x2000;
+			break;
+		case 1024:
+			mask = 0x3000;
+			break;
+		case 2048:
+			mask = 0x4000;
+			break;
+		case 4096:
+			mask = 0x5000;
+			break;
+		default:
+			break;
+		}
+
+		pcie_cap_reg = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+		if (mask != 0xffff && pcie_cap_reg) {
+			pcie_cap_reg += 0x08;
+			pci_read_config_word(pdev, pcie_cap_reg, &pcie_dev_ctl);
+			if ((pcie_dev_ctl & 0x7000) != mask) {
+				printk(KERN_WARNING "BFA[%s]: "
+				"pcie_max_read_request_size is %d, "
+				"reset to %d\n", bfad->pci_name,
+				(1 << ((pcie_dev_ctl & 0x7000) >> 12)) << 7,
+				pcie_max_read_reqsz);
+
+				pcie_dev_ctl &= ~0x7000;
+				pci_write_config_word(pdev, pcie_cap_reg,
+						pcie_dev_ctl | mask);
+			}
+		}
+	}
+
 	return 0;
 
 out_release_region:
@@ -710,25 +888,22 @@
 void
 bfad_fcs_port_cfg(struct bfad_s *bfad)
 {
-	struct bfa_port_cfg_s port_cfg;
-	struct bfa_pport_attr_s attr;
-	char            symname[BFA_SYMNAME_MAXLEN];
+	struct bfa_lport_cfg_s  port_cfg;
+	struct bfa_port_attr_s attr;
+	char		symname[BFA_SYMNAME_MAXLEN];
 
 	sprintf(symname, "%s-%d", BFAD_DRIVER_NAME, bfad->inst_no);
 	memcpy(port_cfg.sym_name.symname, symname, strlen(symname));
 	bfa_fcport_get_attr(&bfad->bfa, &attr);
 	port_cfg.nwwn = attr.nwwn;
 	port_cfg.pwwn = attr.pwwn;
-
-	bfa_fcs_cfg_base_port(&bfad->bfa_fcs, &port_cfg);
 }
 
 bfa_status_t
 bfad_drv_init(struct bfad_s *bfad)
 {
-	bfa_status_t    rc;
-	unsigned long   flags;
-	struct bfa_fcs_driver_info_s driver_info;
+	bfa_status_t	rc;
+	unsigned long	flags;
 
 	bfad->cfg_data.rport_del_timeout = rport_del_timeout;
 	bfad->cfg_data.lun_queue_depth = bfa_lun_queue_depth;
@@ -740,15 +915,12 @@
 		printk(KERN_WARNING "bfad%d bfad_hal_mem_alloc failure\n",
 		       bfad->inst_no);
 		printk(KERN_WARNING
-			"Not enough memory to attach all Brocade HBA ports,"
-			" System may need more memory.\n");
+			"Not enough memory to attach all Brocade HBA ports, %s",
+			"System may need more memory.\n");
 		goto out_hal_mem_alloc_failure;
 	}
 
-	bfa_init_log(&bfad->bfa, bfad->logmod);
 	bfa_init_trc(&bfad->bfa, bfad->trcmod);
-	bfa_init_aen(&bfad->bfa, bfad->aen);
-	memset(bfad->file_map, 0, sizeof(bfad->file_map));
 	bfa_init_plog(&bfad->bfa, &bfad->plog_buf);
 	bfa_plog_init(&bfad->plog_buf);
 	bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START,
@@ -757,77 +929,17 @@
 	bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg, &bfad->meminfo,
 		   &bfad->hal_pcidev);
 
-	init_completion(&bfad->comp);
-
-	/*
-	 * Enable Interrupt and wait bfa_init completion
-	 */
-	if (bfad_setup_intr(bfad)) {
-		printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",
-		       bfad->inst_no);
-		goto out_setup_intr_failure;
-	}
-
+	/* FCS INIT */
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	bfa_init(&bfad->bfa);
-	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
-	/*
-	 * Set up interrupt handler for each vectors
-	 */
-	if ((bfad->bfad_flags & BFAD_MSIX_ON)
-	    && bfad_install_msix_handler(bfad)) {
-		printk(KERN_WARNING "%s: install_msix failed, bfad%d\n",
-		       __func__, bfad->inst_no);
-	}
-
-	bfad_init_timer(bfad);
-
-	wait_for_completion(&bfad->comp);
-
-	memset(&driver_info, 0, sizeof(driver_info));
-	strncpy(driver_info.version, BFAD_DRIVER_VERSION,
-		sizeof(driver_info.version) - 1);
-	__kernel_param_lock();
-	if (host_name)
-		strncpy(driver_info.host_machine_name, host_name,
-			sizeof(driver_info.host_machine_name) - 1);
-	if (os_name)
-		strncpy(driver_info.host_os_name, os_name,
-			sizeof(driver_info.host_os_name) - 1);
-	if (os_patch)
-		strncpy(driver_info.host_os_patch, os_patch,
-			sizeof(driver_info.host_os_patch) - 1);
-	__kernel_param_unlock();
-
-	strncpy(driver_info.os_device_name, bfad->pci_name,
-		sizeof(driver_info.os_device_name - 1));
-
-	/*
-	 * FCS INIT
-	 */
-	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	bfa_fcs_log_init(&bfad->bfa_fcs, bfad->logmod);
 	bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod);
-	bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen);
 	bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
-
-	/* Do FCS init only when HAL init is done */
-	if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
-		bfa_fcs_init(&bfad->bfa_fcs);
-		bfad->bfad_flags |= BFAD_FCS_INIT_DONE;
-	}
-
-	bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
 	bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
+
 	return BFA_STATUS_OK;
 
-out_setup_intr_failure:
-	bfa_detach(&bfad->bfa);
-	bfad_hal_mem_release(bfad);
 out_hal_mem_alloc_failure:
 	return BFA_STATUS_FAILED;
 }
@@ -855,7 +967,7 @@
 void
 bfad_drv_start(struct bfad_s *bfad)
 {
-	unsigned long   flags;
+	unsigned long	flags;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	bfa_start(&bfad->bfa);
@@ -863,13 +975,14 @@
 	bfad->bfad_flags |= BFAD_HAL_START_DONE;
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
-	bfad_fc4_probe_post(bfad);
+	if (bfad->im)
+		flush_workqueue(bfad->im->drv_workq);
 }
 
 void
-bfad_drv_stop(struct bfad_s *bfad)
+bfad_fcs_stop(struct bfad_s *bfad)
 {
-	unsigned long   flags;
+	unsigned long	flags;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	init_completion(&bfad->comp);
@@ -878,24 +991,32 @@
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	wait_for_completion(&bfad->comp);
 
+	bfa_sm_send_event(bfad, BFAD_E_FCS_EXIT_COMP);
+}
+
+void
+bfad_stop(struct bfad_s *bfad)
+{
+	unsigned long	flags;
+
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	init_completion(&bfad->comp);
 	bfa_stop(&bfad->bfa);
 	bfad->bfad_flags &= ~BFAD_HAL_START_DONE;
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	wait_for_completion(&bfad->comp);
+
+	bfa_sm_send_event(bfad, BFAD_E_EXIT_COMP);
 }
 
 bfa_status_t
-bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role)
+bfad_cfg_pport(struct bfad_s *bfad, enum bfa_lport_role role)
 {
-	int             rc = BFA_STATUS_OK;
+	int		rc = BFA_STATUS_OK;
 
-	/*
-	 * Allocate scsi_host for the physical port
-	 */
-	if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
-	    && (role & BFA_PORT_ROLE_FCP_IM)) {
+	/* Allocate scsi_host for the physical port */
+	if ((supported_fc4s & BFA_LPORT_ROLE_FCP_IM) &&
+	    (role & BFA_LPORT_ROLE_FCP_IM)) {
 		if (bfad->pport.im_port == NULL) {
 			rc = BFA_STATUS_FAILED;
 			goto out;
@@ -906,7 +1027,7 @@
 		if (rc != BFA_STATUS_OK)
 			goto out;
 
-		bfad->pport.roles |= BFA_PORT_ROLE_FCP_IM;
+		bfad->pport.roles |= BFA_LPORT_ROLE_FCP_IM;
 	}
 
 	/* Setup the debugfs node for this scsi_host */
@@ -922,74 +1043,102 @@
 void
 bfad_uncfg_pport(struct bfad_s *bfad)
 {
-	 /* Remove the debugfs node for this scsi_host */
+	/* Remove the debugfs node for this scsi_host */
 	kfree(bfad->regdata);
 	bfad_debugfs_exit(&bfad->pport);
 
-	if ((bfad->pport.roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) {
-		bfad_ipfc_port_delete(bfad, &bfad->pport);
-		bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IPFC;
-	}
-
-	if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
-	    && (bfad->pport.roles & BFA_PORT_ROLE_FCP_IM)) {
+	if ((supported_fc4s & BFA_LPORT_ROLE_FCP_IM) &&
+	    (bfad->pport.roles & BFA_LPORT_ROLE_FCP_IM)) {
 		bfad_im_scsi_host_free(bfad, bfad->pport.im_port);
 		bfad_im_port_clean(bfad->pport.im_port);
 		kfree(bfad->pport.im_port);
-		bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IM;
+		bfad->pport.roles &= ~BFA_LPORT_ROLE_FCP_IM;
 	}
 
 	bfad->bfad_flags &= ~BFAD_CFG_PPORT_DONE;
 }
 
-void
-bfad_drv_log_level_set(struct bfad_s *bfad)
-{
-	if (log_level > BFA_LOG_INVALID && log_level <= BFA_LOG_LEVEL_MAX)
-		bfa_log_set_level_all(&bfad->log_data, log_level);
-}
-
 bfa_status_t
-bfad_start_ops(struct bfad_s *bfad)
-{
-	int retval;
-	struct bfad_pcfg_s *pcfg, *pcfg_new;
+bfad_start_ops(struct bfad_s *bfad) {
+
+	int	retval;
+	unsigned long	flags;
+	struct bfad_vport_s *vport, *vport_new;
+	struct bfa_fcs_driver_info_s driver_info;
+
+	/* Fill the driver_info info to fcs*/
+	memset(&driver_info, 0, sizeof(driver_info));
+	strncpy(driver_info.version, BFAD_DRIVER_VERSION,
+		sizeof(driver_info.version) - 1);
+	if (host_name)
+		strncpy(driver_info.host_machine_name, host_name,
+			sizeof(driver_info.host_machine_name) - 1);
+	if (os_name)
+		strncpy(driver_info.host_os_name, os_name,
+			sizeof(driver_info.host_os_name) - 1);
+	if (os_patch)
+		strncpy(driver_info.host_os_patch, os_patch,
+			sizeof(driver_info.host_os_patch) - 1);
+
+	strncpy(driver_info.os_device_name, bfad->pci_name,
+		sizeof(driver_info.os_device_name - 1));
+
+	/* FCS INIT */
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
+	bfa_fcs_init(&bfad->bfa_fcs);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	/* PPORT FCS config */
 	bfad_fcs_port_cfg(bfad);
 
-	retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM);
-	if (retval != BFA_STATUS_OK)
-		goto out_cfg_pport_failure;
-
-	/* BFAD level FC4 (IM/TM/IPFC) specific resource allocation */
-	retval = bfad_fc4_probe(bfad);
+	retval = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
 	if (retval != BFA_STATUS_OK) {
-		printk(KERN_WARNING "bfad_fc4_probe failed\n");
-		goto out_fc4_probe_failure;
+		if (bfa_sm_cmp_state(bfad, bfad_sm_initializing))
+			bfa_sm_set_state(bfad, bfad_sm_failed);
+		bfad_stop(bfad);
+		return BFA_STATUS_FAILED;
 	}
 
+	/* BFAD level FC4 IM specific resource allocation */
+	retval = bfad_im_probe(bfad);
+	if (retval != BFA_STATUS_OK) {
+		printk(KERN_WARNING "bfad_im_probe failed\n");
+		if (bfa_sm_cmp_state(bfad, bfad_sm_initializing))
+			bfa_sm_set_state(bfad, bfad_sm_failed);
+		bfad_im_probe_undo(bfad);
+		bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+		bfad_uncfg_pport(bfad);
+		bfad_stop(bfad);
+		return BFA_STATUS_FAILED;
+	} else
+		bfad->bfad_flags |= BFAD_FC4_PROBE_DONE;
+
 	bfad_drv_start(bfad);
 
-	/* pbc vport creation */
-	list_for_each_entry_safe(pcfg, pcfg_new,  &bfad->pbc_pcfg_list,
-					list_entry) {
+	/* Complete pbc vport create */
+	list_for_each_entry_safe(vport, vport_new, &bfad->pbc_vport_list,
+				list_entry) {
 		struct fc_vport_identifiers vid;
 		struct fc_vport *fc_vport;
+		char pwwn_buf[BFA_STRING_32];
 
 		memset(&vid, 0, sizeof(vid));
 		vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
 		vid.vport_type = FC_PORTTYPE_NPIV;
 		vid.disable = false;
-		vid.node_name = wwn_to_u64((u8 *)&pcfg->port_cfg.nwwn);
-		vid.port_name = wwn_to_u64((u8 *)&pcfg->port_cfg.pwwn);
+		vid.node_name = wwn_to_u64((u8 *)
+				(&((vport->fcs_vport).lport.port_cfg.nwwn)));
+		vid.port_name = wwn_to_u64((u8 *)
+				(&((vport->fcs_vport).lport.port_cfg.pwwn)));
 		fc_vport = fc_vport_create(bfad->pport.im_port->shost, 0, &vid);
-		if (!fc_vport)
+		if (!fc_vport) {
+			wwn2str(pwwn_buf, vid.port_name);
 			printk(KERN_WARNING "bfad%d: failed to create pbc vport"
-				" %llx\n", bfad->inst_no, vid.port_name);
-		list_del(&pcfg->list_entry);
-		kfree(pcfg);
-
+				" %s\n", bfad->inst_no, pwwn_buf);
+		}
+		list_del(&vport->list_entry);
+		kfree(vport);
 	}
 
 	/*
@@ -998,24 +1147,15 @@
 	 * passed in module param value as the bfa_linkup_delay.
 	 */
 	if (bfa_linkup_delay < 0) {
-
 		bfa_linkup_delay = bfad_os_get_linkup_delay(bfad);
 		bfad_os_rport_online_wait(bfad);
 		bfa_linkup_delay = -1;
-
-	} else {
+	} else
 		bfad_os_rport_online_wait(bfad);
-	}
 
-	bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name);
+	BFA_LOG(KERN_INFO, bfad, log_level, "bfa device claimed\n");
 
 	return BFA_STATUS_OK;
-
-out_fc4_probe_failure:
-	bfad_fc4_probe_undo(bfad);
-	bfad_uncfg_pport(bfad);
-out_cfg_pport_failure:
-	return BFA_STATUS_FAILED;
 }
 
 int
@@ -1028,18 +1168,8 @@
 
 	while (!kthread_should_stop()) {
 
-		/* Check if the FCS init is done from bfad_drv_init;
-		 * if not done do FCS init and set the flag.
-		 */
-		if (!(bfad->bfad_flags & BFAD_FCS_INIT_DONE)) {
-			spin_lock_irqsave(&bfad->bfad_lock, flags);
-			bfa_fcs_init(&bfad->bfa_fcs);
-			bfad->bfad_flags |= BFAD_FCS_INIT_DONE;
-			spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		}
-
-		/* Start the bfad operations after HAL init done */
-		bfad_start_ops(bfad);
+		/* Send event BFAD_E_INIT_SUCCESS */
+		bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);
 
 		spin_lock_irqsave(&bfad->bfad_lock, flags);
 		bfad->bfad_tsk = NULL;
@@ -1051,9 +1181,198 @@
 	return 0;
 }
 
- /*
-  *  PCI_entry PCI driver entries * {
-  */
+/**
+ *  BFA driver interrupt functions
+ */
+irqreturn_t
+bfad_intx(int irq, void *dev_id)
+{
+	struct bfad_s	*bfad = dev_id;
+	struct list_head	doneq;
+	unsigned long	flags;
+	bfa_boolean_t rc;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	rc = bfa_intx(&bfad->bfa);
+	if (!rc) {
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		return IRQ_NONE;
+	}
+
+	bfa_comp_deq(&bfad->bfa, &doneq);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (!list_empty(&doneq)) {
+		bfa_comp_process(&bfad->bfa, &doneq);
+
+		spin_lock_irqsave(&bfad->bfad_lock, flags);
+		bfa_comp_free(&bfad->bfa, &doneq);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		bfa_trc_fp(bfad, irq);
+	}
+
+	return IRQ_HANDLED;
+
+}
+
+static irqreturn_t
+bfad_msix(int irq, void *dev_id)
+{
+	struct bfad_msix_s *vec = dev_id;
+	struct bfad_s *bfad = vec->bfad;
+	struct list_head doneq;
+	unsigned long   flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+	bfa_msix(&bfad->bfa, vec->msix.entry);
+	bfa_comp_deq(&bfad->bfa, &doneq);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (!list_empty(&doneq)) {
+		bfa_comp_process(&bfad->bfa, &doneq);
+
+		spin_lock_irqsave(&bfad->bfad_lock, flags);
+		bfa_comp_free(&bfad->bfa, &doneq);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * Initialize the MSIX entry table.
+ */
+static void
+bfad_init_msix_entry(struct bfad_s *bfad, struct msix_entry *msix_entries,
+			 int mask, int max_bit)
+{
+	int	i;
+	int	match = 0x00000001;
+
+	for (i = 0, bfad->nvec = 0; i < MAX_MSIX_ENTRY; i++) {
+		if (mask & match) {
+			bfad->msix_tab[bfad->nvec].msix.entry = i;
+			bfad->msix_tab[bfad->nvec].bfad = bfad;
+			msix_entries[bfad->nvec].entry = i;
+			bfad->nvec++;
+		}
+
+		match <<= 1;
+	}
+
+}
+
+int
+bfad_install_msix_handler(struct bfad_s *bfad)
+{
+	int i, error = 0;
+
+	for (i = 0; i < bfad->nvec; i++) {
+		sprintf(bfad->msix_tab[i].name, "bfa-%s-%s",
+				bfad->pci_name,
+				((bfa_asic_id_ct(bfad->hal_pcidev.device_id)) ?
+				msix_name_ct[i] : msix_name_cb[i]));
+
+		error = request_irq(bfad->msix_tab[i].msix.vector,
+				    (irq_handler_t) bfad_msix, 0,
+				    bfad->msix_tab[i].name, &bfad->msix_tab[i]);
+		bfa_trc(bfad, i);
+		bfa_trc(bfad, bfad->msix_tab[i].msix.vector);
+		if (error) {
+			int	j;
+
+			for (j = 0; j < i; j++)
+				free_irq(bfad->msix_tab[j].msix.vector,
+						&bfad->msix_tab[j]);
+
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Setup MSIX based interrupt.
+ */
+int
+bfad_setup_intr(struct bfad_s *bfad)
+{
+	int error = 0;
+	u32 mask = 0, i, num_bit = 0, max_bit = 0;
+	struct msix_entry msix_entries[MAX_MSIX_ENTRY];
+	struct pci_dev *pdev = bfad->pcidev;
+
+	/* Call BFA to get the msix map for this PCI function.  */
+	bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
+
+	/* Set up the msix entry table */
+	bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
+
+	if ((bfa_asic_id_ct(pdev->device) && !msix_disable_ct) ||
+	    (!bfa_asic_id_ct(pdev->device) && !msix_disable_cb)) {
+
+		error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
+		if (error) {
+			/*
+			 * Only error number of vector is available.
+			 * We don't have a mechanism to map multiple
+			 * interrupts into one vector, so even if we
+			 * can try to request less vectors, we don't
+			 * know how to associate interrupt events to
+			 *  vectors. Linux doesn't dupicate vectors
+			 * in the MSIX table for this case.
+			 */
+
+			printk(KERN_WARNING "bfad%d: "
+				"pci_enable_msix failed (%d),"
+				" use line based.\n", bfad->inst_no, error);
+
+			goto line_based;
+		}
+
+		/* Save the vectors */
+		for (i = 0; i < bfad->nvec; i++) {
+			bfa_trc(bfad, msix_entries[i].vector);
+			bfad->msix_tab[i].msix.vector = msix_entries[i].vector;
+		}
+
+		bfa_msix_init(&bfad->bfa, bfad->nvec);
+
+		bfad->bfad_flags |= BFAD_MSIX_ON;
+
+		return error;
+	}
+
+line_based:
+	error = 0;
+	if (request_irq
+	    (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
+	     BFAD_DRIVER_NAME, bfad) != 0) {
+		/* Enable interrupt handler failed */
+		return 1;
+	}
+
+	return error;
+}
+
+void
+bfad_remove_intr(struct bfad_s *bfad)
+{
+	int	i;
+
+	if (bfad->bfad_flags & BFAD_MSIX_ON) {
+		for (i = 0; i < bfad->nvec; i++)
+			free_irq(bfad->msix_tab[i].msix.vector,
+					&bfad->msix_tab[i]);
+
+		pci_disable_msix(bfad->pcidev);
+		bfad->bfad_flags &= ~BFAD_MSIX_ON;
+	} else {
+		free_irq(bfad->pcidev->irq, bfad);
+	}
+}
 
 /**
  * PCI probe entry.
@@ -1061,18 +1380,14 @@
 int
 bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
-	struct bfad_s  *bfad;
-	int             error = -ENODEV, retval;
+	struct bfad_s	*bfad;
+	int		error = -ENODEV, retval;
 
-	/*
-	 * For single port cards - only claim function 0
-	 */
-	if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P)
-	    && (PCI_FUNC(pdev->devfn) != 0))
+	/* For single port cards - only claim function 0 */
+	if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P) &&
+		(PCI_FUNC(pdev->devfn) != 0))
 		return -ENODEV;
 
-	BFA_TRACE(BFA_INFO, "bfad_pci_probe entry");
-
 	bfad = kzalloc(sizeof(struct bfad_s), GFP_KERNEL);
 	if (!bfad) {
 		error = -ENOMEM;
@@ -1086,21 +1401,11 @@
 		goto out_alloc_trace_failure;
 	}
 
-	/*
-	 * LOG/TRACE INIT
-	 */
+	/* TRACE INIT */
 	bfa_trc_init(bfad->trcmod);
 	bfa_trc(bfad, bfad_inst);
 
-	bfad->logmod = &bfad->log_data;
-	bfa_log_init(bfad->logmod, (char *)pci_name(pdev), bfa_os_printf);
-
-	bfad_drv_log_level_set(bfad);
-
-	bfad->aen = &bfad->aen_buf;
-
 	if (!(bfad_load_fwimg(pdev))) {
-		printk(KERN_WARNING "bfad_load_fwimg failure!\n");
 		kfree(bfad->trcmod);
 		goto out_alloc_trace_failure;
 	}
@@ -1117,46 +1422,31 @@
 	list_add_tail(&bfad->list_entry, &bfad_list);
 	mutex_unlock(&bfad_mutex);
 
+	/* Initializing the state machine: State set to uninit */
+	bfa_sm_set_state(bfad, bfad_sm_uninit);
+
 	spin_lock_init(&bfad->bfad_lock);
 	pci_set_drvdata(pdev, bfad);
 
 	bfad->ref_count = 0;
 	bfad->pport.bfad = bfad;
-	INIT_LIST_HEAD(&bfad->pbc_pcfg_list);
-
-	bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad, "%s",
-					"bfad_worker");
-	if (IS_ERR(bfad->bfad_tsk)) {
-		printk(KERN_INFO "bfad[%d]: Kernel thread"
-			" creation failed!\n",
-			bfad->inst_no);
-		goto out_kthread_create_failure;
-	}
+	INIT_LIST_HEAD(&bfad->pbc_vport_list);
 
 	retval = bfad_drv_init(bfad);
 	if (retval != BFA_STATUS_OK)
 		goto out_drv_init_failure;
-	if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
-		bfad->bfad_flags |= BFAD_HAL_INIT_FAIL;
-		printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no);
-		goto ok;
-	}
 
-	retval = bfad_start_ops(bfad);
-	if (retval != BFA_STATUS_OK)
-		goto out_start_ops_failure;
+	bfa_sm_send_event(bfad, BFAD_E_CREATE);
 
-	kthread_stop(bfad->bfad_tsk);
-	bfad->bfad_tsk = NULL;
+	if (bfa_sm_cmp_state(bfad, bfad_sm_uninit))
+		goto out_bfad_sm_failure;
 
-ok:
 	return 0;
 
-out_start_ops_failure:
-	bfad_drv_uninit(bfad);
+out_bfad_sm_failure:
+	bfa_detach(&bfad->bfa);
+	bfad_hal_mem_release(bfad);
 out_drv_init_failure:
-	kthread_stop(bfad->bfad_tsk);
-out_kthread_create_failure:
 	mutex_lock(&bfad_mutex);
 	bfad_inst--;
 	list_del(&bfad->list_entry);
@@ -1176,62 +1466,29 @@
 void
 bfad_pci_remove(struct pci_dev *pdev)
 {
-	struct bfad_s  *bfad = pci_get_drvdata(pdev);
-	unsigned long   flags;
+	struct bfad_s	      *bfad = pci_get_drvdata(pdev);
+	unsigned long	flags;
 
 	bfa_trc(bfad, bfad->inst_no);
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	if (bfad->bfad_tsk != NULL)
+	if (bfad->bfad_tsk != NULL) {
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 		kthread_stop(bfad->bfad_tsk);
-	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
-	if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE)
-	    && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
-
-		spin_lock_irqsave(&bfad->bfad_lock, flags);
-		init_completion(&bfad->comp);
-		bfa_stop(&bfad->bfa);
+	} else {
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		wait_for_completion(&bfad->comp);
-
-		bfad_remove_intr(bfad);
-		del_timer_sync(&bfad->hal_tmo);
-		goto hal_detach;
-	} else if (!(bfad->bfad_flags & BFAD_DRV_INIT_DONE)) {
-		goto remove_sysfs;
 	}
 
-	if (bfad->bfad_flags & BFAD_HAL_START_DONE) {
-		bfad_drv_stop(bfad);
-	} else if (bfad->bfad_flags & BFAD_DRV_INIT_DONE) {
-		/* Invoking bfa_stop() before bfa_detach
-		 * when HAL and DRV init are success
-		 * but HAL start did not occur.
-		 */
-		spin_lock_irqsave(&bfad->bfad_lock, flags);
-		init_completion(&bfad->comp);
-		bfa_stop(&bfad->bfa);
-		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		wait_for_completion(&bfad->comp);
-	}
+	/* Send Event BFAD_E_STOP */
+	bfa_sm_send_event(bfad, BFAD_E_STOP);
 
-	bfad_remove_intr(bfad);
-	del_timer_sync(&bfad->hal_tmo);
-
-	if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE)
-		bfad_fc4_probe_undo(bfad);
-
-	if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
-		bfad_uncfg_pport(bfad);
-
-hal_detach:
+	/* Driver detach and dealloc mem */
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	bfa_detach(&bfad->bfa);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	bfad_hal_mem_release(bfad);
-remove_sysfs:
 
+	/* Cleaning the BFAD instance */
 	mutex_lock(&bfad_mutex);
 	bfad_inst--;
 	list_del(&bfad->list_entry);
@@ -1242,35 +1499,34 @@
 	kfree(bfad);
 }
 
-
-static struct pci_device_id bfad_id_table[] = {
+struct pci_device_id bfad_id_table[] = {
 	{
-	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
-	 .device = BFA_PCI_DEVICE_ID_FC_8G2P,
-	 .subvendor = PCI_ANY_ID,
-	 .subdevice = PCI_ANY_ID,
-	 },
+		.vendor = BFA_PCI_VENDOR_ID_BROCADE,
+		.device = BFA_PCI_DEVICE_ID_FC_8G2P,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+	},
 	{
-	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
-	 .device = BFA_PCI_DEVICE_ID_FC_8G1P,
-	 .subvendor = PCI_ANY_ID,
-	 .subdevice = PCI_ANY_ID,
-	 },
+		.vendor = BFA_PCI_VENDOR_ID_BROCADE,
+		.device = BFA_PCI_DEVICE_ID_FC_8G1P,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+	},
 	{
-	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
-	 .device = BFA_PCI_DEVICE_ID_CT,
-	 .subvendor = PCI_ANY_ID,
-	 .subdevice = PCI_ANY_ID,
-	 .class = (PCI_CLASS_SERIAL_FIBER << 8),
-	 .class_mask = ~0,
-	 },
+		.vendor = BFA_PCI_VENDOR_ID_BROCADE,
+		.device = BFA_PCI_DEVICE_ID_CT,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+		.class = (PCI_CLASS_SERIAL_FIBER << 8),
+		.class_mask = ~0,
+	},
 	{
-	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
-	 .device = BFA_PCI_DEVICE_ID_CT_FC,
-	 .subvendor = PCI_ANY_ID,
-	 .subdevice = PCI_ANY_ID,
-	 .class = (PCI_CLASS_SERIAL_FIBER << 8),
-	 .class_mask = ~0,
+		.vendor = BFA_PCI_VENDOR_ID_BROCADE,
+		.device = BFA_PCI_DEVICE_ID_CT_FC,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+		.class = (PCI_CLASS_SERIAL_FIBER << 8),
+		.class_mask = ~0,
 	},
 
 	{0, 0},
@@ -1286,89 +1542,104 @@
 };
 
 /**
- *  Linux driver module functions
- */
-bfa_status_t
-bfad_fc4_module_init(void)
-{
-	int             rc;
-
-	rc = bfad_im_module_init();
-	if (rc != BFA_STATUS_OK)
-		goto ext;
-
-	bfad_tm_module_init();
-	if (ipfc_enable)
-		bfad_ipfc_module_init();
-ext:
-	return rc;
-}
-
-void
-bfad_fc4_module_exit(void)
-{
-	if (ipfc_enable)
-		bfad_ipfc_module_exit();
-	bfad_tm_module_exit();
-	bfad_im_module_exit();
-}
-
-/**
  * Driver module init.
  */
-static int      __init
+static int __init
 bfad_init(void)
 {
-	int             error = 0;
+	int		error = 0;
 
 	printk(KERN_INFO "Brocade BFA FC/FCOE SCSI driver - version: %s\n",
-	       BFAD_DRIVER_VERSION);
+			BFAD_DRIVER_VERSION);
 
 	if (num_sgpgs > 0)
 		num_sgpgs_parm = num_sgpgs;
 
-	error = bfad_fc4_module_init();
+	error = bfad_im_module_init();
 	if (error) {
 		error = -ENOMEM;
-		printk(KERN_WARNING "bfad_fc4_module_init failure\n");
+		printk(KERN_WARNING "bfad_im_module_init failure\n");
 		goto ext;
 	}
 
-	if (!strcmp(FCPI_NAME, " fcpim"))
-		bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IM;
-	if (!strcmp(FCPT_NAME, " fcptm"))
-		bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_TM;
-	if (!strcmp(IPFC_NAME, " ipfc"))
-		bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IPFC;
+	if (strcmp(FCPI_NAME, " fcpim") == 0)
+		supported_fc4s |= BFA_LPORT_ROLE_FCP_IM;
 
 	bfa_ioc_auto_recover(ioc_auto_recover);
 	bfa_fcs_rport_set_del_timeout(rport_del_timeout);
-	error = pci_register_driver(&bfad_pci_driver);
 
+	error = pci_register_driver(&bfad_pci_driver);
 	if (error) {
-		printk(KERN_WARNING "bfad pci_register_driver failure\n");
+		printk(KERN_WARNING "pci_register_driver failure\n");
 		goto ext;
 	}
 
 	return 0;
 
 ext:
-	bfad_fc4_module_exit();
+	bfad_im_module_exit();
 	return error;
 }
 
 /**
  * Driver module exit.
  */
-static void     __exit
+static void __exit
 bfad_exit(void)
 {
 	pci_unregister_driver(&bfad_pci_driver);
-	bfad_fc4_module_exit();
+	bfad_im_module_exit();
 	bfad_free_fwimg();
 }
 
-#define BFAD_PROTO_NAME FCPI_NAME FCPT_NAME IPFC_NAME
+/* Firmware handling */
+u32 *
+bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
+		u32 *bfi_image_size, char *fw_name)
+{
+	const struct firmware *fw;
+
+	if (request_firmware(&fw, fw_name, &pdev->dev)) {
+		printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
+		goto error;
+	}
+
+	*bfi_image = vmalloc(fw->size);
+	if (NULL == *bfi_image) {
+		printk(KERN_ALERT "Fail to allocate buffer for fw image "
+			"size=%x!\n", (u32) fw->size);
+		goto error;
+	}
+
+	memcpy(*bfi_image, fw->data, fw->size);
+	*bfi_image_size = fw->size/sizeof(u32);
+
+	return *bfi_image;
+
+error:
+	return NULL;
+}
+
+u32 *
+bfad_get_firmware_buf(struct pci_dev *pdev)
+{
+	if (pdev->device == BFA_PCI_DEVICE_ID_CT_FC) {
+		if (bfi_image_ct_fc_size == 0)
+			bfad_read_firmware(pdev, &bfi_image_ct_fc,
+				&bfi_image_ct_fc_size, BFAD_FW_FILE_CT_FC);
+		return bfi_image_ct_fc;
+	} else if (pdev->device == BFA_PCI_DEVICE_ID_CT) {
+		if (bfi_image_ct_cna_size == 0)
+			bfad_read_firmware(pdev, &bfi_image_ct_cna,
+				&bfi_image_ct_cna_size, BFAD_FW_FILE_CT_CNA);
+		return bfi_image_ct_cna;
+	} else {
+		if (bfi_image_cb_fc_size == 0)
+			bfad_read_firmware(pdev, &bfi_image_cb_fc,
+				&bfi_image_cb_fc_size, BFAD_FW_FILE_CB_FC);
+		return bfi_image_cb_fc;
+	}
+}
 
 module_init(bfad_init);
 module_exit(bfad_exit);
@@ -1376,5 +1647,3 @@
 MODULE_DESCRIPTION("Brocade Fibre Channel HBA Driver" BFAD_PROTO_NAME);
 MODULE_AUTHOR("Brocade Communications Systems, Inc.");
 MODULE_VERSION(BFAD_DRIVER_VERSION);
-
-
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index 0818eb0..d884372 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -19,15 +19,8 @@
  *  bfa_attr.c Linux driver configuration interface module.
  */
 
-#include <linux/slab.h>
 #include "bfad_drv.h"
 #include "bfad_im.h"
-#include "bfad_trcmod.h"
-#include "bfad_attr.h"
-
-/**
- *  FC_transport_template FC transport template
- */
 
 /**
  * FC transport template entry, get SCSI target port ID.
@@ -42,7 +35,7 @@
 	u32        fc_id = -1;
 	unsigned long   flags;
 
-	shost = bfad_os_starget_to_shost(starget);
+	shost = dev_to_shost(starget->dev.parent);
 	im_port = (struct bfad_im_port_s *) shost->hostdata[0];
 	bfad = im_port->bfad;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -68,7 +61,7 @@
 	u64             node_name = 0;
 	unsigned long   flags;
 
-	shost = bfad_os_starget_to_shost(starget);
+	shost = dev_to_shost(starget->dev.parent);
 	im_port = (struct bfad_im_port_s *) shost->hostdata[0];
 	bfad = im_port->bfad;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -94,7 +87,7 @@
 	u64             port_name = 0;
 	unsigned long   flags;
 
-	shost = bfad_os_starget_to_shost(starget);
+	shost = dev_to_shost(starget->dev.parent);
 	im_port = (struct bfad_im_port_s *) shost->hostdata[0];
 	bfad = im_port->bfad;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -118,17 +111,7 @@
 	struct bfad_port_s    *port = im_port->port;
 
 	fc_host_port_id(shost) =
-			bfa_os_hton3b(bfa_fcs_port_get_fcid(port->fcs_port));
-}
-
-
-
-
-
-struct Scsi_Host *
-bfad_os_starget_to_shost(struct scsi_target *starget)
-{
-	return dev_to_shost(starget->dev.parent);
+			bfa_os_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port));
 }
 
 /**
@@ -140,21 +123,21 @@
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s         *bfad = im_port->bfad;
-	struct bfa_pport_attr_s attr;
+	struct bfa_lport_attr_s port_attr;
 
-	bfa_fcport_get_attr(&bfad->bfa, &attr);
+	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
 
-	switch (attr.port_type) {
-	case BFA_PPORT_TYPE_NPORT:
+	switch (port_attr.port_type) {
+	case BFA_PORT_TYPE_NPORT:
 		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
 		break;
-	case BFA_PPORT_TYPE_NLPORT:
+	case BFA_PORT_TYPE_NLPORT:
 		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
 		break;
-	case BFA_PPORT_TYPE_P2P:
+	case BFA_PORT_TYPE_P2P:
 		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
 		break;
-	case BFA_PPORT_TYPE_LPORT:
+	case BFA_PORT_TYPE_LPORT:
 		fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
 		break;
 	default:
@@ -172,25 +155,28 @@
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s         *bfad = im_port->bfad;
-	struct bfa_pport_attr_s attr;
+	struct bfa_port_attr_s attr;
 
 	bfa_fcport_get_attr(&bfad->bfa, &attr);
 
 	switch (attr.port_state) {
-	case BFA_PPORT_ST_LINKDOWN:
+	case BFA_PORT_ST_LINKDOWN:
 		fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
 		break;
-	case BFA_PPORT_ST_LINKUP:
+	case BFA_PORT_ST_LINKUP:
 		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
 		break;
-	case BFA_PPORT_ST_UNINIT:
-	case BFA_PPORT_ST_ENABLING_QWAIT:
-	case BFA_PPORT_ST_ENABLING:
-	case BFA_PPORT_ST_DISABLING_QWAIT:
-	case BFA_PPORT_ST_DISABLING:
-	case BFA_PPORT_ST_DISABLED:
-	case BFA_PPORT_ST_STOPPED:
-	case BFA_PPORT_ST_IOCDOWN:
+	case BFA_PORT_ST_DISABLED:
+	case BFA_PORT_ST_STOPPED:
+	case BFA_PORT_ST_IOCDOWN:
+	case BFA_PORT_ST_IOCDIS:
+		fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
+		break;
+	case BFA_PORT_ST_UNINIT:
+	case BFA_PORT_ST_ENABLING_QWAIT:
+	case BFA_PORT_ST_ENABLING:
+	case BFA_PORT_ST_DISABLING_QWAIT:
+	case BFA_PORT_ST_DISABLING:
 	default:
 		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
 		break;
@@ -210,13 +196,9 @@
 	memset(fc_host_active_fc4s(shost), 0,
 	       sizeof(fc_host_active_fc4s(shost)));
 
-	if (port->supported_fc4s &
-		(BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM))
+	if (port->supported_fc4s & BFA_LPORT_ROLE_FCP_IM)
 		fc_host_active_fc4s(shost)[2] = 1;
 
-	if (port->supported_fc4s & BFA_PORT_ROLE_FCP_IPFC)
-		fc_host_active_fc4s(shost)[3] = 0x20;
-
 	fc_host_active_fc4s(shost)[7] = 1;
 }
 
@@ -229,29 +211,29 @@
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s         *bfad = im_port->bfad;
-	struct bfa_pport_attr_s attr;
-	unsigned long   flags;
+	struct bfa_port_attr_s attr;
 
-	spin_lock_irqsave(shost->host_lock, flags);
 	bfa_fcport_get_attr(&bfad->bfa, &attr);
 	switch (attr.speed) {
-	case BFA_PPORT_SPEED_8GBPS:
+	case BFA_PORT_SPEED_10GBPS:
+		fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
+		break;
+	case BFA_PORT_SPEED_8GBPS:
 		fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
 		break;
-	case BFA_PPORT_SPEED_4GBPS:
+	case BFA_PORT_SPEED_4GBPS:
 		fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
 		break;
-	case BFA_PPORT_SPEED_2GBPS:
+	case BFA_PORT_SPEED_2GBPS:
 		fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
 		break;
-	case BFA_PPORT_SPEED_1GBPS:
+	case BFA_PORT_SPEED_1GBPS:
 		fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
 		break;
 	default:
 		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
 		break;
 	}
-	spin_unlock_irqrestore(shost->host_lock, flags);
 }
 
 /**
@@ -265,7 +247,7 @@
 	struct bfad_port_s    *port = im_port->port;
 	wwn_t           fabric_nwwn = 0;
 
-	fabric_nwwn = bfa_fcs_port_get_fabric_name(port->fcs_port);
+	fabric_nwwn = bfa_fcs_lport_get_fabric_name(port->fcs_port);
 
 	fc_host_fabric_name(shost) = bfa_os_htonll(fabric_nwwn);
 
@@ -281,23 +263,44 @@
 			(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s         *bfad = im_port->bfad;
 	struct bfad_hal_comp fcomp;
+	union bfa_port_stats_u *fcstats;
 	struct fc_host_statistics *hstats;
 	bfa_status_t    rc;
 	unsigned long   flags;
 
+	fcstats = kzalloc(sizeof(union bfa_port_stats_u), GFP_KERNEL);
+	if (fcstats == NULL)
+		return NULL;
+
 	hstats = &bfad->link_stats;
 	init_completion(&fcomp.comp);
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	memset(hstats, 0, sizeof(struct fc_host_statistics));
-	rc =  bfa_port_get_stats(BFA_FCPORT(&bfad->bfa),
-				     (union bfa_pport_stats_u *) hstats,
-				     bfad_hcb_comp, &fcomp);
+	rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa),
+				fcstats, bfad_hcb_comp, &fcomp);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	if (rc != BFA_STATUS_OK)
 		return NULL;
 
 	wait_for_completion(&fcomp.comp);
 
+	/* Fill the fc_host_statistics structure */
+	hstats->seconds_since_last_reset = fcstats->fc.secs_reset;
+	hstats->tx_frames = fcstats->fc.tx_frames;
+	hstats->tx_words  = fcstats->fc.tx_words;
+	hstats->rx_frames = fcstats->fc.rx_frames;
+	hstats->rx_words  = fcstats->fc.rx_words;
+	hstats->lip_count = fcstats->fc.lip_count;
+	hstats->nos_count = fcstats->fc.nos_count;
+	hstats->error_frames = fcstats->fc.error_frames;
+	hstats->dumped_frames = fcstats->fc.dropped_frames;
+	hstats->link_failure_count = fcstats->fc.link_failures;
+	hstats->loss_of_sync_count = fcstats->fc.loss_of_syncs;
+	hstats->loss_of_signal_count = fcstats->fc.loss_of_signals;
+	hstats->prim_seq_protocol_err_count = fcstats->fc.primseq_errs;
+	hstats->invalid_crc_count = fcstats->fc.invalid_crcs;
+
+	kfree(fcstats);
 	return hstats;
 }
 
@@ -317,7 +320,7 @@
 	init_completion(&fcomp.comp);
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	rc = bfa_port_clear_stats(BFA_FCPORT(&bfad->bfa), bfad_hcb_comp,
-		&fcomp);
+					&fcomp);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	if (rc != BFA_STATUS_OK)
@@ -372,8 +375,8 @@
 	struct bfad_im_port_s *im_port =
 		(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s *bfad = im_port->bfad;
-	struct bfa_port_cfg_s port_cfg;
-	struct bfad_pcfg_s *pcfg;
+	struct bfa_lport_cfg_s port_cfg;
+	struct bfad_vport_s *vp;
 	int status = 0, rc;
 	unsigned long flags;
 
@@ -382,12 +385,14 @@
 	u64_to_wwn(fc_vport->port_name, (u8 *)&port_cfg.pwwn);
 	if (strlen(vname) > 0)
 		strcpy((char *)&port_cfg.sym_name, vname);
-	port_cfg.roles = BFA_PORT_ROLE_FCP_IM;
+	port_cfg.roles = BFA_LPORT_ROLE_FCP_IM;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	list_for_each_entry(pcfg, &bfad->pbc_pcfg_list, list_entry) {
-		if (port_cfg.pwwn == pcfg->port_cfg.pwwn) {
-			port_cfg.preboot_vp = pcfg->port_cfg.preboot_vp;
+	list_for_each_entry(vp, &bfad->pbc_vport_list, list_entry) {
+		if (port_cfg.pwwn ==
+				vp->fcs_vport.lport.port_cfg.pwwn) {
+			port_cfg.preboot_vp =
+				vp->fcs_vport.lport.port_cfg.preboot_vp;
 			break;
 		}
 	}
@@ -638,7 +643,7 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 	char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
 
 	bfa_get_adapter_serial_num(&bfad->bfa, serial_num);
@@ -652,7 +657,7 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 	char model[BFA_ADAPTER_MODEL_NAME_LEN];
 
 	bfa_get_adapter_model(&bfad->bfa, model);
@@ -666,10 +671,54 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
+	char model[BFA_ADAPTER_MODEL_NAME_LEN];
 	char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
 
-	bfa_get_adapter_model(&bfad->bfa, model_descr);
+	bfa_get_adapter_model(&bfad->bfa, model);
+	if (!strcmp(model, "Brocade-425"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 4Gbps PCIe dual port FC HBA");
+	else if (!strcmp(model, "Brocade-825"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 8Gbps PCIe dual port FC HBA");
+	else if (!strcmp(model, "Brocade-42B"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"HP 4Gbps PCIe dual port FC HBA");
+	else if (!strcmp(model, "Brocade-82B"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"HP 8Gbps PCIe dual port FC HBA");
+	else if (!strcmp(model, "Brocade-1010"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 10Gbps single port CNA");
+	else if (!strcmp(model, "Brocade-1020"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 10Gbps dual port CNA");
+	else if (!strcmp(model, "Brocade-1007"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 10Gbps CNA");
+	else if (!strcmp(model, "Brocade-415"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 4Gbps PCIe single port FC HBA");
+	else if (!strcmp(model, "Brocade-815"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 8Gbps PCIe single port FC HBA");
+	else if (!strcmp(model, "Brocade-41B"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"HP 4Gbps PCIe single port FC HBA");
+	else if (!strcmp(model, "Brocade-81B"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"HP 8Gbps PCIe single port FC HBA");
+	else if (!strcmp(model, "Brocade-804"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"HP Bladesystem C-class 8Gbps FC HBA");
+	else if (!strcmp(model, "Brocade-902"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 10Gbps CNA");
+	else
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Invalid Model");
+
 	return snprintf(buf, PAGE_SIZE, "%s\n", model_descr);
 }
 
@@ -683,7 +732,7 @@
 	struct bfad_port_s    *port = im_port->port;
 	u64        nwwn;
 
-	nwwn = bfa_fcs_port_get_nwwn(port->fcs_port);
+	nwwn = bfa_fcs_lport_get_nwwn(port->fcs_port);
 	return snprintf(buf, PAGE_SIZE, "0x%llx\n", bfa_os_htonll(nwwn));
 }
 
@@ -694,14 +743,14 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
-	char model[BFA_ADAPTER_MODEL_NAME_LEN];
-	char fw_ver[BFA_VERSION_LEN];
+	struct bfad_s *bfad = im_port->bfad;
+	struct bfa_lport_attr_s port_attr;
+	char symname[BFA_SYMNAME_MAXLEN];
 
-	bfa_get_adapter_model(&bfad->bfa, model);
-	bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
-	return snprintf(buf, PAGE_SIZE, "Brocade %s FV%s DV%s\n",
-		model, fw_ver, BFAD_DRIVER_VERSION);
+	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
+	strncpy(symname, port_attr.port_cfg.sym_name.symname,
+			BFA_SYMNAME_MAXLEN);
+	return snprintf(buf, PAGE_SIZE, "%s\n", symname);
 }
 
 static ssize_t
@@ -711,7 +760,7 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 	char hw_ver[BFA_VERSION_LEN];
 
 	bfa_get_pci_chip_rev(&bfad->bfa, hw_ver);
@@ -732,7 +781,7 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 	char optrom_ver[BFA_VERSION_LEN];
 
 	bfa_get_adapter_optrom_ver(&bfad->bfa, optrom_ver);
@@ -746,7 +795,7 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 	char fw_ver[BFA_VERSION_LEN];
 
 	bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
@@ -760,10 +809,10 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
-		bfa_get_nports(&bfad->bfa));
+			bfa_get_nports(&bfad->bfa));
 }
 
 static ssize_t
@@ -788,10 +837,10 @@
 
 	rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC);
 	if (rports == NULL)
-		return -ENOMEM;
+		return snprintf(buf, PAGE_SIZE, "Failed\n");
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	bfa_fcs_port_get_rports(port->fcs_port, rports, &nrports);
+	bfa_fcs_lport_get_rports(port->fcs_port, rports, &nrports);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	kfree(rports);
 
@@ -837,19 +886,19 @@
 };
 
 struct device_attribute *bfad_im_vport_attrs[] = {
-    &dev_attr_serial_number,
-    &dev_attr_model,
-    &dev_attr_model_description,
-    &dev_attr_node_name,
-    &dev_attr_symbolic_name,
-    &dev_attr_hardware_version,
-    &dev_attr_driver_version,
-    &dev_attr_option_rom_version,
-    &dev_attr_firmware_version,
-    &dev_attr_number_of_ports,
-    &dev_attr_driver_name,
-    &dev_attr_number_of_discovered_ports,
-    NULL,
+	&dev_attr_serial_number,
+	&dev_attr_model,
+	&dev_attr_model_description,
+	&dev_attr_node_name,
+	&dev_attr_symbolic_name,
+	&dev_attr_hardware_version,
+	&dev_attr_driver_version,
+	&dev_attr_option_rom_version,
+	&dev_attr_firmware_version,
+	&dev_attr_number_of_ports,
+	&dev_attr_driver_name,
+	&dev_attr_number_of_discovered_ports,
+	NULL,
 };
 
 
diff --git a/drivers/scsi/bfa/bfad_attr.h b/drivers/scsi/bfa/bfad_attr.h
deleted file mode 100644
index bf01020..0000000
--- a/drivers/scsi/bfa/bfad_attr.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFAD_ATTR_H__
-#define __BFAD_ATTR_H__
-
-/**
- *  FC_transport_template FC transport template
- */
-
-struct Scsi_Host*
-bfad_os_dev_to_shost(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI target port ID.
- */
-void
-bfad_im_get_starget_port_id(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI target nwwn.
- */
-void
-bfad_im_get_starget_node_name(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI target pwwn.
- */
-void
-bfad_im_get_starget_port_name(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI host port ID.
- */
-void
-bfad_im_get_host_port_id(struct Scsi_Host *shost);
-
-struct Scsi_Host*
-bfad_os_starget_to_shost(struct scsi_target *starget);
-
-
-#endif /*  __BFAD_ATTR_H__ */
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
index 4b82f12..69ed1c4 100644
--- a/drivers/scsi/bfa/bfad_debugfs.c
+++ b/drivers/scsi/bfa/bfad_debugfs.c
@@ -17,8 +17,8 @@
 
 #include <linux/debugfs.h>
 
-#include <bfad_drv.h>
-#include <bfad_im.h>
+#include "bfad_drv.h"
+#include "bfad_im.h"
 
 /*
  * BFA debufs interface
@@ -28,7 +28,7 @@
  * mount -t debugfs none /sys/kernel/debug
  *
  * BFA Hierarchy:
- * 	- bfa/host#
+ *	- bfa/host#
  * where the host number corresponds to the one under /sys/class/scsi_host/host#
  *
  * Debugging service available per host:
@@ -217,7 +217,7 @@
 #define BFA_REG_ADDRSZ(__bfa)	\
 	((bfa_ioc_devid(&(__bfa)->ioc) == BFA_PCI_DEVICE_ID_CT) ?	\
 		BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ)
-#define BFA_REG_ADDRMSK(__bfa)  ((uint32_t)(BFA_REG_ADDRSZ(__bfa) - 1))
+#define BFA_REG_ADDRMSK(__bfa)  ((u32)(BFA_REG_ADDRSZ(__bfa) - 1))
 
 static bfa_status_t
 bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len)
@@ -359,7 +359,7 @@
 		return -EINVAL;
 	}
 
-	reg_addr = (uint32_t *) ((uint8_t *) bfa_ioc_bar0(ioc) + addr);
+	reg_addr = (u32 *) ((u8 *) bfa_ioc_bar0(ioc) + addr);
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	bfa_reg_write(reg_addr, val);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index 465b8b8..98420bb 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -28,30 +28,27 @@
 
 #include "bfa_os_inc.h"
 
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs.h>
-#include <defs/bfa_defs_pci.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_rport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <defs/bfa_defs_vport.h>
-#include <fcs/bfa_fcs_vport.h>
+#include "bfa_modules.h"
+#include "bfa_fcs.h"
+#include "bfa_defs_fcs.h"
 
-#include <cs/bfa_plog.h>
-#include "aen/bfa_aen.h"
-#include <log/bfa_log_linux.h>
+#include "bfa_plog.h"
+#include "bfa_cs.h"
 
-#define BFAD_DRIVER_NAME        "bfa"
+#define BFAD_DRIVER_NAME	"bfa"
 #ifdef BFA_DRIVER_VERSION
 #define BFAD_DRIVER_VERSION    BFA_DRIVER_VERSION
 #else
-#define BFAD_DRIVER_VERSION    "2.2.2.1"
+#define BFAD_DRIVER_VERSION    "2.3.2.0"
 #endif
 
-
+#define BFAD_PROTO_NAME FCPI_NAME
 #define BFAD_IRQ_FLAGS IRQF_SHARED
 
+#ifndef FC_PORTSPEED_8GBIT
+#define FC_PORTSPEED_8GBIT 0x10
+#endif
+
 /*
  * BFAD flags
  */
@@ -62,9 +59,9 @@
 #define BFAD_HAL_START_DONE			0x00000010
 #define BFAD_PORT_ONLINE			0x00000020
 #define BFAD_RPORT_ONLINE			0x00000040
-#define BFAD_FCS_INIT_DONE                      0x00000080
-#define BFAD_HAL_INIT_FAIL                      0x00000100
-#define BFAD_FC4_PROBE_DONE                     0x00000200
+#define BFAD_FCS_INIT_DONE			0x00000080
+#define BFAD_HAL_INIT_FAIL			0x00000100
+#define BFAD_FC4_PROBE_DONE			0x00000200
 #define BFAD_PORT_DELETE			0x00000001
 
 /*
@@ -77,8 +74,8 @@
 /*
  * BFAD configuration parameter default values
  */
-#define BFAD_LUN_QUEUE_DEPTH 		32
-#define BFAD_IO_MAX_SGE 		SG_ALL
+#define BFAD_LUN_QUEUE_DEPTH	32
+#define BFAD_IO_MAX_SGE		SG_ALL
 
 #define bfad_isr_t irq_handler_t
 
@@ -87,6 +84,16 @@
 struct bfad_msix_s {
 	struct bfad_s *bfad;
 	struct msix_entry msix;
+	char name[32];
+};
+
+/*
+ * Only append to the enums defined here to avoid any versioning
+ * needed between trace utility and driver version
+ */
+enum {
+	BFA_TRC_LDRV_BFAD		= 1,
+	BFA_TRC_LDRV_IM			= 2,
 };
 
 enum bfad_port_pvb_type {
@@ -101,17 +108,13 @@
  */
 struct bfad_port_s {
 	struct list_head list_entry;
-	struct bfad_s         *bfad;
-	struct bfa_fcs_port_s *fcs_port;
-	u32        roles;
-	s32         flags;
-	u32        supported_fc4s;
-	u8		ipfc_flags;
+	struct bfad_s	*bfad;
+	struct bfa_fcs_lport_s *fcs_port;
+	u32	roles;
+	s32		flags;
+	u32	supported_fc4s;
 	enum bfad_port_pvb_type pvb_type;
 	struct bfad_im_port_s *im_port;	/* IM specific data */
-	struct bfad_tm_port_s *tm_port;	/* TM specific data */
-	struct bfad_ipfc_port_s *ipfc_port;	/* IPFC specific data */
-
 	/* port debugfs specific data */
 	struct dentry *port_debugfs_root;
 };
@@ -124,7 +127,6 @@
 	struct bfa_fcs_vport_s fcs_vport;
 	struct completion *comp_del;
 	struct list_head list_entry;
-	struct bfa_port_cfg_s port_cfg;
 };
 
 /*
@@ -137,20 +139,35 @@
 };
 
 struct bfad_cfg_param_s {
-	u32        rport_del_timeout;
-	u32        ioc_queue_depth;
-	u32        lun_queue_depth;
-	u32        io_max_sge;
-	u32        binding_method;
+	u32	rport_del_timeout;
+	u32	ioc_queue_depth;
+	u32	lun_queue_depth;
+	u32	io_max_sge;
+	u32	binding_method;
+};
+
+union bfad_tmp_buf {
+	/* From struct bfa_adapter_attr_s */
+	char		manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
+	char		serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+	char		model[BFA_ADAPTER_MODEL_NAME_LEN];
+	char		fw_ver[BFA_VERSION_LEN];
+	char		optrom_ver[BFA_VERSION_LEN];
+
+	/* From struct bfa_ioc_pci_attr_s */
+	u8		chip_rev[BFA_IOC_CHIP_REV_LEN];  /*  chip revision */
+
+	wwn_t		wwn[BFA_FCS_MAX_LPORTS];
 };
 
 /*
  * BFAD (PCI function) data structure
  */
 struct bfad_s {
+	bfa_sm_t	sm;	/* state machine */
 	struct list_head list_entry;
-	struct bfa_s       bfa;
-	struct bfa_fcs_s       bfa_fcs;
+	struct bfa_s	bfa;
+	struct bfa_fcs_s bfa_fcs;
 	struct pci_dev *pcidev;
 	const char *pci_name;
 	struct bfa_pcidev_s hal_pcidev;
@@ -163,41 +180,41 @@
 	struct bfad_port_s     pport;	/* physical port of the BFAD */
 	struct bfa_meminfo_s meminfo;
 	struct bfa_iocfc_cfg_s   ioc_cfg;
-	u32        inst_no;	/* BFAD instance number */
-	u32        bfad_flags;
+	u32	inst_no;	/* BFAD instance number */
+	u32	bfad_flags;
 	spinlock_t      bfad_lock;
 	struct task_struct *bfad_tsk;
 	struct bfad_cfg_param_s cfg_data;
 	struct bfad_msix_s msix_tab[MAX_MSIX_ENTRY];
-	int             nvec;
-	char            adapter_name[BFA_ADAPTER_SYM_NAME_LEN];
-	char            port_name[BFA_ADAPTER_SYM_NAME_LEN];
+	int		nvec;
+	char	adapter_name[BFA_ADAPTER_SYM_NAME_LEN];
+	char	port_name[BFA_ADAPTER_SYM_NAME_LEN];
 	struct timer_list hal_tmo;
 	unsigned long   hs_start;
 	struct bfad_im_s *im;		/* IM specific data */
-	struct bfad_tm_s *tm;		/* TM specific data */
-	struct bfad_ipfc_s *ipfc;	/* IPFC specific data */
-	struct bfa_log_mod_s   log_data;
 	struct bfa_trc_mod_s  *trcmod;
-	struct bfa_log_mod_s  *logmod;
-	struct bfa_aen_s      *aen;
-	struct bfa_aen_s       aen_buf;
-	void		*file_map[BFA_AEN_MAX_APP];
 	struct bfa_plog_s      plog_buf;
-	int             ref_count;
-	bfa_boolean_t	ipfc_enabled;
+	int		ref_count;
+	union bfad_tmp_buf tmp_buf;
 	struct fc_host_statistics link_stats;
-	struct list_head pbc_pcfg_list;
-	atomic_t wq_reqcnt;
+	struct list_head pbc_vport_list;
 	/* debugfs specific data */
 	char *regdata;
 	u32 reglen;
 	struct dentry *bfad_dentry_files[5];
 };
 
-struct bfad_pcfg_s {
-	struct list_head list_entry;
-	struct bfa_port_cfg_s port_cfg;
+/* BFAD state machine events */
+enum bfad_sm_event {
+	BFAD_E_CREATE			= 1,
+	BFAD_E_KTHREAD_CREATE_FAILED	= 2,
+	BFAD_E_INIT			= 3,
+	BFAD_E_INIT_SUCCESS		= 4,
+	BFAD_E_INIT_FAILED		= 5,
+	BFAD_E_INTR_INIT_FAILED		= 6,
+	BFAD_E_FCS_EXIT_COMP		= 7,
+	BFAD_E_EXIT_COMP		= 8,
+	BFAD_E_STOP			= 9
 };
 
 /*
@@ -208,30 +225,30 @@
 };
 
 struct bfad_buf_info {
-	void           *virt;
+	void		*virt;
 	dma_addr_t      phys;
-	u32        size;
+	u32	size;
 };
 
 struct bfad_fcxp {
 	struct bfad_port_s    *port;
 	struct bfa_rport_s *bfa_rport;
 	bfa_status_t    req_status;
-	u16        tag;
-	u16        rsp_len;
-	u16        rsp_maxlen;
-	u8         use_ireqbuf;
-	u8         use_irspbuf;
-	u32        num_req_sgles;
-	u32        num_rsp_sgles;
-	struct fchs_s          fchs;
-	void           *reqbuf_info;
-	void           *rspbuf_info;
+	u16	tag;
+	u16	rsp_len;
+	u16	rsp_maxlen;
+	u8		use_ireqbuf;
+	u8		use_irspbuf;
+	u32	num_req_sgles;
+	u32	num_rsp_sgles;
+	struct fchs_s	fchs;
+	void		*reqbuf_info;
+	void		*rspbuf_info;
 	struct bfa_sge_s  *req_sge;
 	struct bfa_sge_s  *rsp_sge;
 	fcxp_send_cb_t  send_cbfn;
-	void           *send_cbarg;
-	void           *bfa_fcxp;
+	void		*send_cbarg;
+	void		*bfa_fcxp;
 	struct completion comp;
 };
 
@@ -244,34 +261,48 @@
  * Macro to obtain the immediate lower power
  * of two for the integer.
  */
-#define nextLowerInt(x)                         	\
-do {                                            	\
-	int j;                                  	\
-	(*x)--;    		                	\
-	for (j = 1; j < (sizeof(int) * 8); j <<= 1)     \
-		(*x) = (*x) | (*x) >> j;        	\
-	(*x)++;                  	        	\
-	(*x) = (*x) >> 1;                       	\
+#define nextLowerInt(x)                         \
+do {                                            \
+	int i;                                  \
+	(*x)--;					\
+	for (i = 1; i < (sizeof(int)*8); i <<= 1) \
+		(*x) = (*x) | (*x) >> i;	\
+	(*x)++;					\
+	(*x) = (*x) >> 1;			\
 } while (0)
 
 
-bfa_status_t    bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
-			  struct bfa_port_cfg_s *port_cfg, struct device *dev);
-bfa_status_t    bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
-			       struct bfa_port_cfg_s *port_cfg);
-bfa_status_t    bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role);
-bfa_status_t    bfad_drv_init(struct bfad_s *bfad);
+#define list_remove_head(list, entry, type, member)		\
+do {								\
+	entry = NULL;                                           \
+	if (!list_empty(list)) {                                \
+		entry = list_entry((list)->next, type, member);	\
+		list_del_init(&entry->member);			\
+	}							\
+} while (0)
+
+#define list_get_first(list, type, member)				\
+((list_empty(list)) ? NULL :						\
+	list_entry((list)->next, type, member))
+
+bfa_status_t	bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
+				  struct bfa_lport_cfg_s *port_cfg,
+				  struct device *dev);
+bfa_status_t	bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
+			       struct bfa_lport_cfg_s *port_cfg);
+bfa_status_t	bfad_cfg_pport(struct bfad_s *bfad, enum bfa_lport_role role);
+bfa_status_t	bfad_drv_init(struct bfad_s *bfad);
 bfa_status_t	bfad_start_ops(struct bfad_s *bfad);
-void            bfad_drv_start(struct bfad_s *bfad);
-void            bfad_uncfg_pport(struct bfad_s *bfad);
-void            bfad_drv_stop(struct bfad_s *bfad);
-void            bfad_remove_intr(struct bfad_s *bfad);
-void            bfad_hal_mem_release(struct bfad_s *bfad);
-void            bfad_hcb_comp(void *arg, bfa_status_t status);
+void		bfad_drv_start(struct bfad_s *bfad);
+void		bfad_uncfg_pport(struct bfad_s *bfad);
+void		bfad_stop(struct bfad_s *bfad);
+void		bfad_fcs_stop(struct bfad_s *bfad);
+void		bfad_remove_intr(struct bfad_s *bfad);
+void		bfad_hal_mem_release(struct bfad_s *bfad);
+void		bfad_hcb_comp(void *arg, bfa_status_t status);
 
-int             bfad_setup_intr(struct bfad_s *bfad);
-void            bfad_remove_intr(struct bfad_s *bfad);
-
+int		bfad_setup_intr(struct bfad_s *bfad);
+void		bfad_remove_intr(struct bfad_s *bfad);
 void		bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg);
 bfa_status_t	bfad_hal_mem_alloc(struct bfad_s *bfad);
 void		bfad_bfa_tmo(unsigned long data);
@@ -280,9 +311,6 @@
 void		bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad);
 void		bfad_fcs_port_cfg(struct bfad_s *bfad);
 void		bfad_drv_uninit(struct bfad_s *bfad);
-void		bfad_drv_log_level_set(struct bfad_s *bfad);
-bfa_status_t	bfad_fc4_module_init(void);
-void		bfad_fc4_module_exit(void);
 int		bfad_worker(void *ptr);
 void		bfad_debugfs_init(struct bfad_port_s *port);
 void		bfad_debugfs_exit(struct bfad_port_s *port);
@@ -294,10 +322,30 @@
 int bfad_install_msix_handler(struct bfad_s *bfad);
 
 extern struct idr bfad_im_port_index;
+extern struct pci_device_id bfad_id_table[];
 extern struct list_head bfad_list;
-extern int bfa_lun_queue_depth;
-extern int bfad_supported_fc4s;
-extern int bfa_linkup_delay;
+extern char	*os_name;
+extern char	*os_patch;
+extern char	*host_name;
+extern int	num_rports;
+extern int	num_ios;
+extern int	num_tms;
+extern int	num_fcxps;
+extern int	num_ufbufs;
+extern int	reqq_size;
+extern int	rspq_size;
+extern int	num_sgpgs;
+extern int      rport_del_timeout;
+extern int      bfa_lun_queue_depth;
+extern int      bfa_io_max_sge;
+extern int      log_level;
+extern int      ioc_auto_recover;
+extern int      bfa_linkup_delay;
+extern int      msix_disable_cb;
+extern int      msix_disable_ct;
+extern int      fdmi_enable;
+extern int      supported_fc4s;
+extern int	pcie_max_read_reqsz;
 extern int bfa_debugfs_enable;
 extern struct mutex bfad_mutex;
 
diff --git a/drivers/scsi/bfa/bfad_fwimg.c b/drivers/scsi/bfa/bfad_fwimg.c
deleted file mode 100644
index 1baca1a..0000000
--- a/drivers/scsi/bfa/bfad_fwimg.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfad_fwimg.c Linux driver PCI interface module.
- */
-#include <bfa_os_inc.h>
-#include <bfad_drv.h>
-#include <bfad_im_compat.h>
-#include <defs/bfa_defs_version.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <asm/uaccess.h>
-#include <asm/fcntl.h>
-#include <linux/pci.h>
-#include <linux/firmware.h>
-#include <bfa_fwimg_priv.h>
-#include <bfa.h>
-
-u32 bfi_image_ct_fc_size;
-u32 bfi_image_ct_cna_size;
-u32 bfi_image_cb_fc_size;
-u32 *bfi_image_ct_fc;
-u32 *bfi_image_ct_cna;
-u32 *bfi_image_cb_fc;
-
-
-#define	BFAD_FW_FILE_CT_FC	"ctfw_fc.bin"
-#define	BFAD_FW_FILE_CT_CNA	"ctfw_cna.bin"
-#define	BFAD_FW_FILE_CB_FC	"cbfw_fc.bin"
-MODULE_FIRMWARE(BFAD_FW_FILE_CT_FC);
-MODULE_FIRMWARE(BFAD_FW_FILE_CT_CNA);
-MODULE_FIRMWARE(BFAD_FW_FILE_CB_FC);
-
-u32 *
-bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
-			u32 *bfi_image_size, char *fw_name)
-{
-	const struct firmware *fw;
-
-	if (request_firmware(&fw, fw_name, &pdev->dev)) {
-		printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
-		goto error;
-	}
-
-	*bfi_image = vmalloc(fw->size);
-	if (NULL == *bfi_image) {
-		printk(KERN_ALERT "Fail to allocate buffer for fw image "
-			"size=%x!\n", (u32) fw->size);
-		goto error;
-	}
-
-	memcpy(*bfi_image, fw->data, fw->size);
-	*bfi_image_size = fw->size/sizeof(u32);
-
-	return *bfi_image;
-
-error:
-	return NULL;
-}
-
-u32 *
-bfad_get_firmware_buf(struct pci_dev *pdev)
-{
-	if (pdev->device == BFA_PCI_DEVICE_ID_CT_FC) {
-		if (bfi_image_ct_fc_size == 0)
-			bfad_read_firmware(pdev, &bfi_image_ct_fc,
-				&bfi_image_ct_fc_size, BFAD_FW_FILE_CT_FC);
-		return bfi_image_ct_fc;
-	} else if (pdev->device == BFA_PCI_DEVICE_ID_CT) {
-		if (bfi_image_ct_cna_size == 0)
-			bfad_read_firmware(pdev, &bfi_image_ct_cna,
-				&bfi_image_ct_cna_size, BFAD_FW_FILE_CT_CNA);
-		return bfi_image_ct_cna;
-	} else {
-		if (bfi_image_cb_fc_size == 0)
-			bfad_read_firmware(pdev, &bfi_image_cb_fc,
-				&bfi_image_cb_fc_size, BFAD_FW_FILE_CB_FC);
-		return bfi_image_cb_fc;
-	}
-}
-
-u32 *
-bfi_image_ct_fc_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_ct_fc + off); }
-
-u32 *
-bfi_image_ct_cna_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_ct_cna + off); }
-
-u32 *
-bfi_image_cb_fc_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_cb_fc + off); }
-
-uint32_t *
-bfi_image_get_chunk(int type, uint32_t off)
-{
-	switch (type) {
-	case BFI_IMAGE_CT_FC: return bfi_image_ct_fc_get_chunk(off); break;
-	case BFI_IMAGE_CT_CNA: return bfi_image_ct_cna_get_chunk(off); break;
-	case BFI_IMAGE_CB_FC: return bfi_image_cb_fc_get_chunk(off); break;
-	default: return 0; break;
-	}
-}
-
-uint32_t
-bfi_image_get_size(int type)
-{
-	switch (type) {
-	case BFI_IMAGE_CT_FC: return bfi_image_ct_fc_size; break;
-	case BFI_IMAGE_CT_CNA: return bfi_image_ct_cna_size; break;
-	case BFI_IMAGE_CB_FC: return bfi_image_cb_fc_size; break;
-	default: return 0; break;
-	}
-}
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index 6ef87f6..d950ee4 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -19,12 +19,10 @@
  *  bfad_im.c Linux driver IM module.
  */
 
-#include <linux/slab.h>
 #include "bfad_drv.h"
 #include "bfad_im.h"
-#include "bfad_trcmod.h"
-#include "bfa_cb_ioim_macros.h"
-#include <fcb/bfa_fcb_fcpim.h>
+#include "bfa_cb_ioim.h"
+#include "bfa_fcs.h"
 
 BFA_TRC_FILE(LDRV, IM);
 
@@ -33,8 +31,10 @@
 struct scsi_transport_template *bfad_im_scsi_vport_transport_template;
 static void bfad_im_itnim_work_handler(struct work_struct *work);
 static int bfad_im_queuecommand(struct scsi_cmnd *cmnd,
-		void (*done)(struct scsi_cmnd *));
+				void (*done)(struct scsi_cmnd *));
 static int bfad_im_slave_alloc(struct scsi_device *sdev);
+static void bfad_im_fc_rport_add(struct bfad_im_port_s  *im_port,
+				struct bfad_itnim_s *itnim);
 
 void
 bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio,
@@ -58,6 +58,7 @@
 				sns_len = SCSI_SENSE_BUFFERSIZE;
 			memcpy(cmnd->sense_buffer, sns_info, sns_len);
 		}
+
 		if (residue > 0) {
 			bfa_trc(bfad, residue);
 			scsi_set_resid(cmnd, residue);
@@ -76,7 +77,8 @@
 	case BFI_IOIM_STS_TIMEDOUT:
 	case BFI_IOIM_STS_PATHTOV:
 	default:
-		cmnd->result = ScsiResult(DID_ERROR, 0);
+		host_status = DID_ERROR;
+		cmnd->result = ScsiResult(host_status, 0);
 	}
 
 	/* Unmap DMA, if host is NULL, it means a scsi passthru cmd */
@@ -162,11 +164,6 @@
 		wake_up(wq);
 }
 
-void
-bfa_cb_ioim_resfree(void *drv)
-{
-}
-
 /**
  *  Scsi_Host_template SCSI host template
  */
@@ -179,15 +176,23 @@
 	static char     bfa_buf[256];
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
+	struct bfa_s *bfa = &bfad->bfa;
+	struct bfa_ioc_s *ioc = &bfa->ioc;
 	char model[BFA_ADAPTER_MODEL_NAME_LEN];
 
-	bfa_get_adapter_model(&bfad->bfa, model);
+	bfa_get_adapter_model(bfa, model);
 
 	memset(bfa_buf, 0, sizeof(bfa_buf));
-	snprintf(bfa_buf, sizeof(bfa_buf),
-		"Brocade FC/FCOE Adapter, " "model: %s hwpath: %s driver: %s",
+	if (ioc->ctdev)
+		snprintf(bfa_buf, sizeof(bfa_buf),
+		"Brocade FCOE Adapter, " "model: %s hwpath: %s driver: %s",
+		 model, bfad->pci_name, BFAD_DRIVER_VERSION);
+	else
+		snprintf(bfa_buf, sizeof(bfa_buf),
+		"Brocade FC Adapter, " "model: %s hwpath: %s driver: %s",
 		model, bfad->pci_name, BFAD_DRIVER_VERSION);
+
 	return bfa_buf;
 }
 
@@ -221,9 +226,9 @@
 	}
 
 	bfa_trc(bfad, hal_io->iotag);
-	bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT,
+	BFA_LOG(KERN_INFO, bfad, log_level, "scsi%d: abort cmnd %p iotag %x\n",
 		im_port->shost->host_no, cmnd, hal_io->iotag);
-	bfa_ioim_abort(hal_io);
+	(void) bfa_ioim_abort(hal_io);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	/* Need to wait until the command get aborted */
@@ -237,7 +242,8 @@
 
 	cmnd->scsi_done(cmnd);
 	bfa_trc(bfad, hal_io->iotag);
-	bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT_COMP,
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"scsi%d: complete abort 0x%p iotag 0x%x\n",
 		im_port->shost->host_no, cmnd, hal_io->iotag);
 	return SUCCESS;
 out:
@@ -255,8 +261,8 @@
 
 	tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
 	if (!tskim) {
-		BFA_DEV_PRINTF(bfad, BFA_ERR,
-			       "target reset, fail to allocate tskim\n");
+		BFA_LOG(KERN_ERR, bfad, log_level,
+			"target reset, fail to allocate tskim\n");
 		rc = BFA_STATUS_FAILED;
 		goto out;
 	}
@@ -306,7 +312,7 @@
 
 	tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
 	if (!tskim) {
-		BFA_DEV_PRINTF(bfad, BFA_ERR,
+		BFA_LOG(KERN_ERR, bfad, log_level,
 				"LUN reset, fail to allocate tskim");
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 		rc = FAILED;
@@ -331,8 +337,8 @@
 
 	task_status = cmnd->SCp.Status >> 1;
 	if (task_status != BFI_TSKIM_STS_OK) {
-		BFA_DEV_PRINTF(bfad, BFA_ERR, "LUN reset failure, status: %d\n",
-			       task_status);
+		BFA_LOG(KERN_ERR, bfad, log_level,
+			"LUN reset failure, status: %d\n", task_status);
 		rc = FAILED;
 	}
 
@@ -375,7 +381,7 @@
 
 			task_status = cmnd->SCp.Status >> 1;
 			if (task_status != BFI_TSKIM_STS_OK) {
-				BFA_DEV_PRINTF(bfad, BFA_ERR,
+				BFA_LOG(KERN_ERR, bfad, log_level,
 					"target reset failure,"
 					" status: %d\n", task_status);
 				err_cnt++;
@@ -438,6 +444,7 @@
 	wwn_t wwpn;
 	u32 fcid;
 	char wwpn_str[32], fcid_str[16];
+	struct bfad_im_s	*im = itnim_drv->im;
 
 	/* online to free state transtion should not happen */
 	bfa_assert(itnim_drv->state != ITNIM_STATE_ONLINE);
@@ -454,10 +461,14 @@
 	fcid = bfa_fcs_itnim_get_fcid(&itnim_drv->fcs_itnim);
 	wwn2str(wwpn_str, wwpn);
 	fcid2str(fcid_str, fcid);
-	bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_FREE,
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"ITNIM FREE scsi%d: FCID: %s WWPN: %s\n",
 		port->im_port->shost->host_no,
 		fcid_str, wwpn_str);
-	bfad_os_itnim_process(itnim_drv);
+
+	/* ITNIM processing */
+	if (itnim_drv->queue_work)
+		queue_work(im->drv_workq, &itnim_drv->itnim_work);
 }
 
 /**
@@ -468,13 +479,17 @@
 bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv)
 {
 	struct bfad_port_s    *port;
+	struct bfad_im_s	*im = itnim_drv->im;
 
 	itnim_drv->bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim_drv->fcs_itnim);
 	port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
 	itnim_drv->state = ITNIM_STATE_ONLINE;
 	itnim_drv->queue_work = 1;
 	itnim_drv->im_port = port->im_port;
-	bfad_os_itnim_process(itnim_drv);
+
+	/* ITNIM processing */
+	if (itnim_drv->queue_work)
+		queue_work(im->drv_workq, &itnim_drv->itnim_work);
 }
 
 /**
@@ -486,6 +501,7 @@
 {
 	struct bfad_port_s    *port;
 	struct bfad_s *bfad;
+	struct bfad_im_s	*im = itnim_drv->im;
 
 	port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
 	bfad = port->bfad;
@@ -497,16 +513,10 @@
 	itnim_drv->im_port = port->im_port;
 	itnim_drv->state = ITNIM_STATE_OFFLINE_PENDING;
 	itnim_drv->queue_work = 1;
-	bfad_os_itnim_process(itnim_drv);
-}
 
-/**
- * BFA FCS itnim timeout callback.
- * Context: Interrupt. bfad_lock is held
- */
-void bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim)
-{
-	itnim->state = ITNIM_STATE_TIMEOUT;
+	/* ITNIM processing */
+	if (itnim_drv->queue_work)
+		queue_work(im->drv_workq, &itnim_drv->itnim_work);
 }
 
 /**
@@ -514,7 +524,7 @@
  */
 int
 bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
-				struct device *dev)
+			struct device *dev)
 {
 	int error = 1;
 
@@ -580,7 +590,7 @@
 bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
 {
 	bfa_trc(bfad, bfad->inst_no);
-	bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_HOST_FREE,
+	BFA_LOG(KERN_INFO, bfad, log_level, "Free scsi%d\n",
 			im_port->shost->host_no);
 
 	fc_remove_host(im_port->shost);
@@ -598,14 +608,11 @@
 {
 	struct bfad_im_port_s *im_port =
 		container_of(work, struct bfad_im_port_s, port_delete_work);
-	struct bfad_s *bfad = im_port->bfad;
 
 	if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) {
 		im_port->flags |= BFAD_PORT_DELETE;
 		fc_vport_terminate(im_port->fc_vport);
-		atomic_dec(&bfad->wq_reqcnt);
 	}
-
 }
 
 bfa_status_t
@@ -636,11 +643,8 @@
 {
 	struct bfad_im_port_s *im_port = port->im_port;
 
-	if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) {
-		atomic_inc(&bfad->wq_reqcnt);
-		queue_work(bfad->im->drv_workq,
+	queue_work(bfad->im->drv_workq,
 				&im_port->port_delete_work);
-	}
 }
 
 void
@@ -663,16 +667,6 @@
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 }
 
-void
-bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port)
-{
-}
-
-void
-bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port)
-{
-}
-
 bfa_status_t
 bfad_im_probe(struct bfad_s *bfad)
 {
@@ -701,27 +695,12 @@
 bfad_im_probe_undo(struct bfad_s *bfad)
 {
 	if (bfad->im) {
-		while (atomic_read(&bfad->wq_reqcnt)) {
-			printk(KERN_INFO "bfa %s: waiting workq processing,"
-				" wq_reqcnt:%x\n", bfad->pci_name,
-				atomic_read(&bfad->wq_reqcnt));
-			schedule_timeout_uninterruptible(HZ);
-		}
 		bfad_os_destroy_workq(bfad->im);
 		kfree(bfad->im);
 		bfad->im = NULL;
 	}
 }
 
-/**
- * Call back function to handle IO redirection state change
- */
-void
-bfa_cb_ioredirect_state_change(void *hcb_bfad, bfa_boolean_t ioredirect)
-{
-	/* Do nothing */
-}
-
 struct Scsi_Host *
 bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
 {
@@ -751,6 +730,7 @@
 bfad_os_destroy_workq(struct bfad_im_s *im)
 {
 	if (im && im->drv_workq) {
+		flush_workqueue(im->drv_workq);
 		destroy_workqueue(im->drv_workq);
 		im->drv_workq = NULL;
 	}
@@ -762,7 +742,7 @@
 	struct bfad_im_s      *im = bfad->im;
 
 	bfa_trc(bfad, 0);
-	snprintf(im->drv_workq_name, BFAD_KOBJ_NAME_LEN, "bfad_wq_%d",
+	snprintf(im->drv_workq_name, KOBJ_NAME_LEN, "bfad_wq_%d",
 		 bfad->inst_no);
 	im->drv_workq = create_singlethread_workqueue(im->drv_workq_name);
 	if (!im->drv_workq)
@@ -832,12 +812,6 @@
 	.max_sectors = 0xFFFF,
 };
 
-void
-bfad_im_probe_post(struct bfad_im_s *im)
-{
-	flush_workqueue(im->drv_workq);
-}
-
 bfa_status_t
 bfad_im_module_init(void)
 {
@@ -861,20 +835,12 @@
 {
 	if (bfad_im_scsi_transport_template)
 		fc_release_transport(bfad_im_scsi_transport_template);
+
 	if (bfad_im_scsi_vport_transport_template)
 		fc_release_transport(bfad_im_scsi_vport_transport_template);
 }
 
 void
-bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv)
-{
-	struct bfad_im_s      *im = itnim_drv->im;
-
-	if (itnim_drv->queue_work)
-		queue_work(im->drv_workq, &itnim_drv->itnim_work);
-}
-
-void
 bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
 {
 	struct scsi_device *tmp_sdev;
@@ -916,9 +882,6 @@
 	}
 }
 
-
-
-
 struct bfad_itnim_s *
 bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id)
 {
@@ -949,44 +912,64 @@
 	return 0;
 }
 
+static u32
+bfad_im_supported_speeds(struct bfa_s *bfa)
+{
+	struct bfa_ioc_attr_s ioc_attr;
+	u32 supported_speed = 0;
+
+	bfa_get_attr(bfa, &ioc_attr);
+	if (ioc_attr.adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
+		if (ioc_attr.adapter_attr.is_mezz) {
+			supported_speed |= FC_PORTSPEED_8GBIT |
+				FC_PORTSPEED_4GBIT |
+				FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
+		} else {
+			supported_speed |= FC_PORTSPEED_8GBIT |
+				FC_PORTSPEED_4GBIT |
+				FC_PORTSPEED_2GBIT;
+		}
+	} else if (ioc_attr.adapter_attr.max_speed == BFA_PORT_SPEED_4GBPS) {
+		supported_speed |=  FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
+				FC_PORTSPEED_1GBIT;
+	} else if (ioc_attr.adapter_attr.max_speed == BFA_PORT_SPEED_10GBPS) {
+		supported_speed |= FC_PORTSPEED_10GBIT;
+	}
+	return supported_speed;
+}
+
 void
 bfad_os_fc_host_init(struct bfad_im_port_s *im_port)
 {
 	struct Scsi_Host *host = im_port->shost;
 	struct bfad_s         *bfad = im_port->bfad;
 	struct bfad_port_s    *port = im_port->port;
-	struct bfa_pport_attr_s pattr;
-	char model[BFA_ADAPTER_MODEL_NAME_LEN];
-	char fw_ver[BFA_VERSION_LEN];
+	struct bfa_port_attr_s pattr;
+	struct bfa_lport_attr_s port_attr;
+	char symname[BFA_SYMNAME_MAXLEN];
 
 	fc_host_node_name(host) =
-		bfa_os_htonll((bfa_fcs_port_get_nwwn(port->fcs_port)));
+		bfa_os_htonll((bfa_fcs_lport_get_nwwn(port->fcs_port)));
 	fc_host_port_name(host) =
-		bfa_os_htonll((bfa_fcs_port_get_pwwn(port->fcs_port)));
+		bfa_os_htonll((bfa_fcs_lport_get_pwwn(port->fcs_port)));
 	fc_host_max_npiv_vports(host) = bfa_lps_get_max_vport(&bfad->bfa);
 
 	fc_host_supported_classes(host) = FC_COS_CLASS3;
 
 	memset(fc_host_supported_fc4s(host), 0,
 	       sizeof(fc_host_supported_fc4s(host)));
-	if (bfad_supported_fc4s & (BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM))
+	if (supported_fc4s & BFA_LPORT_ROLE_FCP_IM)
 		/* For FCP type 0x08 */
 		fc_host_supported_fc4s(host)[2] = 1;
-	if (bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IPFC)
-		/* For LLC/SNAP type 0x05 */
-		fc_host_supported_fc4s(host)[3] = 0x20;
 	/* For fibre channel services type 0x20 */
 	fc_host_supported_fc4s(host)[7] = 1;
 
-	bfa_get_adapter_model(&bfad->bfa, model);
-	bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
-	sprintf(fc_host_symbolic_name(host), "Brocade %s FV%s DV%s",
-		model, fw_ver, BFAD_DRIVER_VERSION);
+	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
+	strncpy(symname, port_attr.port_cfg.sym_name.symname,
+		BFA_SYMNAME_MAXLEN);
+	sprintf(fc_host_symbolic_name(host), "%s", symname);
 
-	fc_host_supported_speeds(host) = 0;
-	fc_host_supported_speeds(host) |=
-		FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
-		FC_PORTSPEED_1GBIT;
+	fc_host_supported_speeds(host) = bfad_im_supported_speeds(&bfad->bfa);
 
 	bfa_fcport_get_attr(&bfad->bfa, &pattr);
 	fc_host_maxframe_size(host) = pattr.pport_cfg.maxfrsize;
@@ -1065,7 +1048,9 @@
 			fcid2str(fcid_str, fcid);
 			list_add_tail(&itnim->list_entry,
 				&im_port->itnim_mapped_list);
-			bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_ONLINE,
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"ITNIM ONLINE Target: %d:0:%d "
+				"FCID: %s WWPN: %s\n",
 				im_port->shost->host_no,
 				itnim->scsi_tgt_id,
 				fcid_str, wwpn_str);
@@ -1096,7 +1081,9 @@
 			wwn2str(wwpn_str, wwpn);
 			fcid2str(fcid_str, fcid);
 			list_del(&itnim->list_entry);
-			bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_OFFLINE,
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"ITNIM OFFLINE Target: %d:0:%d "
+				"FCID: %s WWPN: %s\n",
 				im_port->shost->host_no,
 				itnim->scsi_tgt_id,
 				fcid_str, wwpn_str);
@@ -1142,7 +1129,7 @@
 	struct bfa_ioim_s *hal_io;
 	unsigned long   flags;
 	int             rc;
-	s16        sg_cnt = 0;
+	int       sg_cnt = 0;
 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
 
 	rc = fc_remote_port_chkready(rport);
@@ -1153,7 +1140,6 @@
 	}
 
 	sg_cnt = scsi_dma_map(cmnd);
-
 	if (sg_cnt < 0)
 		return SCSI_MLQUEUE_HOST_BUSY;
 
@@ -1168,6 +1154,7 @@
 		goto out_fail_cmd;
 	}
 
+
 	itnim = itnim_data->itnim;
 	if (!itnim) {
 		cmnd->result = ScsiResult(DID_IMM_RETRY, 0);
@@ -1206,47 +1193,49 @@
 	int rport_delay = 10;
 
 	for (i = 0; !(bfad->bfad_flags & BFAD_PORT_ONLINE)
-		 && i < bfa_linkup_delay; i++)
-		schedule_timeout_uninterruptible(HZ);
+		&& i < bfa_linkup_delay; i++) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ);
+	}
 
 	if (bfad->bfad_flags & BFAD_PORT_ONLINE) {
 		rport_delay = rport_delay < bfa_linkup_delay ?
-				 rport_delay : bfa_linkup_delay;
+			rport_delay : bfa_linkup_delay;
 		for (i = 0; !(bfad->bfad_flags & BFAD_RPORT_ONLINE)
-			 && i < rport_delay; i++)
-			schedule_timeout_uninterruptible(HZ);
+			&& i < rport_delay; i++) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(HZ);
+		}
 
-		if (rport_delay > 0 && (bfad->bfad_flags & BFAD_RPORT_ONLINE))
-			schedule_timeout_uninterruptible(rport_delay * HZ);
+		if (rport_delay > 0 && (bfad->bfad_flags & BFAD_RPORT_ONLINE)) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(rport_delay * HZ);
+		}
 	}
 }
 
 int
 bfad_os_get_linkup_delay(struct bfad_s *bfad)
 {
-
-	u8      nwwns = 0;
-	wwn_t	wwns[BFA_PREBOOT_BOOTLUN_MAX];
-	int     ldelay;
+	u8		nwwns = 0;
+	wwn_t		wwns[BFA_PREBOOT_BOOTLUN_MAX];
+	int		linkup_delay;
 
 	/*
 	 * Querying for the boot target port wwns
 	 * -- read from boot information in flash.
-	 * If nwwns > 0 => boot over SAN and set bfa_linkup_delay = 30
-	 * else => local boot machine set bfa_linkup_delay = 10
+	 * If nwwns > 0 => boot over SAN and set linkup_delay = 30
+	 * else => local boot machine set linkup_delay = 0
 	 */
 
 	bfa_iocfc_get_bootwwns(&bfad->bfa, &nwwns, wwns);
 
-	if (nwwns > 0) {
-		/* If boot over SAN; linkup_delay = 30sec */
-		ldelay = 30;
-	} else {
-		/* If local boot; linkup_delay = 10sec */
-		ldelay = 0;
-	}
+	if (nwwns > 0)
+		/* If Boot over SAN set linkup_delay = 30sec */
+		linkup_delay = 30;
+	else
+		/* If local boot; no linkup_delay */
+		linkup_delay = 0;
 
-	return ldelay;
+	return linkup_delay;
 }
-
-
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h
index 973cab4..b038c0e 100644
--- a/drivers/scsi/bfa/bfad_im.h
+++ b/drivers/scsi/bfa/bfad_im.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -18,20 +18,20 @@
 #ifndef __BFAD_IM_H__
 #define __BFAD_IM_H__
 
-#include "fcs/bfa_fcs_fcpim.h"
-#include "bfad_im_compat.h"
+#include "bfa_fcs.h"
 
 #define FCPI_NAME " fcpim"
 
+#ifndef KOBJ_NAME_LEN
+#define KOBJ_NAME_LEN           20
+#endif
+
 bfa_status_t bfad_im_module_init(void);
 void bfad_im_module_exit(void);
 bfa_status_t bfad_im_probe(struct bfad_s *bfad);
 void bfad_im_probe_undo(struct bfad_s *bfad);
-void bfad_im_probe_post(struct bfad_im_s *im);
 bfa_status_t bfad_im_port_new(struct bfad_s *bfad, struct bfad_port_s *port);
 void bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port);
-void bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port);
-void bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port);
 void bfad_im_port_clean(struct bfad_im_port_s *im_port);
 int  bfad_im_scsi_host_alloc(struct bfad_s *bfad,
 		struct bfad_im_port_s *im_port, struct device *dev);
@@ -44,14 +44,10 @@
 #define BFAD_LUN_RESET_TMO 60
 #define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
 #define BFA_QUEUE_FULL_RAMP_UP_TIME 120
-#define BFAD_KOBJ_NAME_LEN 20
 
 /*
  * itnim flags
  */
-#define ITNIM_MAPPED		0x00000001
-
-#define SCSI_TASK_MGMT		0x00000001
 #define IO_DONE_BIT			0
 
 struct bfad_itnim_data_s {
@@ -64,7 +60,7 @@
 	struct work_struct port_delete_work;
 	int             idr_id;
 	u16        cur_scsi_id;
-	u16	   flags;
+	u16	flags;
 	struct list_head binding_list;
 	struct Scsi_Host *shost;
 	struct list_head itnim_mapped_list;
@@ -118,14 +114,13 @@
 struct bfad_im_s {
 	struct bfad_s         *bfad;
 	struct workqueue_struct *drv_workq;
-	char   drv_workq_name[BFAD_KOBJ_NAME_LEN];
+	char            drv_workq_name[KOBJ_NAME_LEN];
 };
 
 struct Scsi_Host *bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port,
 				struct bfad_s *);
 bfa_status_t bfad_os_thread_workq(struct bfad_s *bfad);
 void bfad_os_destroy_workq(struct bfad_im_s *im);
-void bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv);
 void bfad_os_fc_host_init(struct bfad_im_port_s *im_port);
 void bfad_os_scsi_host_free(struct bfad_s *bfad,
 				 struct bfad_im_port_s *im_port);
@@ -133,11 +128,6 @@
 				 struct scsi_device *sdev);
 void bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev);
 struct bfad_itnim_s *bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id);
-int bfad_os_scsi_add_host(struct Scsi_Host *shost,
-		struct bfad_im_port_s *im_port, struct bfad_s *bfad);
-
-void bfad_im_itnim_unmap(struct bfad_im_port_s  *im_port,
-			 struct bfad_itnim_s *itnim);
 
 extern struct scsi_host_template bfad_im_scsi_host_template;
 extern struct scsi_host_template bfad_im_vport_template;
@@ -146,4 +136,34 @@
 extern struct scsi_transport_template *bfad_im_scsi_transport_template;
 extern struct scsi_transport_template *bfad_im_scsi_vport_transport_template;
 
+extern struct device_attribute *bfad_im_host_attrs[];
+extern struct device_attribute *bfad_im_vport_attrs[];
+
+irqreturn_t bfad_intx(int irq, void *dev_id);
+
+/* Firmware releated */
+#define BFAD_FW_FILE_CT_FC      "ctfw_fc.bin"
+#define BFAD_FW_FILE_CT_CNA     "ctfw_cna.bin"
+#define BFAD_FW_FILE_CB_FC      "cbfw_fc.bin"
+
+u32 *bfad_get_firmware_buf(struct pci_dev *pdev);
+u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
+		u32 *bfi_image_size, char *fw_name);
+
+static inline u32 *
+bfad_load_fwimg(struct pci_dev *pdev)
+{
+	return bfad_get_firmware_buf(pdev);
+}
+
+static inline void
+bfad_free_fwimg(void)
+{
+	if (bfi_image_ct_fc_size && bfi_image_ct_fc)
+		vfree(bfi_image_ct_fc);
+	if (bfi_image_ct_cna_size && bfi_image_ct_cna)
+		vfree(bfi_image_ct_cna);
+	if (bfi_image_cb_fc_size && bfi_image_cb_fc)
+		vfree(bfi_image_cb_fc);
+}
 #endif
diff --git a/drivers/scsi/bfa/bfad_im_compat.h b/drivers/scsi/bfa/bfad_im_compat.h
deleted file mode 100644
index 0a122ab..0000000
--- a/drivers/scsi/bfa/bfad_im_compat.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFAD_IM_COMPAT_H__
-#define __BFAD_IM_COMPAT_H__
-
-extern struct device_attribute *bfad_im_host_attrs[];
-extern struct device_attribute *bfad_im_vport_attrs[];
-
-u32 *bfad_get_firmware_buf(struct pci_dev *pdev);
-u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
-			u32 *bfi_image_size, char *fw_name);
-
-static inline u32 *
-bfad_load_fwimg(struct pci_dev *pdev)
-{
-	return bfad_get_firmware_buf(pdev);
-}
-
-static inline void
-bfad_free_fwimg(void)
-{
-	if (bfi_image_ct_fc_size && bfi_image_ct_fc)
-		vfree(bfi_image_ct_fc);
-	if (bfi_image_ct_cna_size && bfi_image_ct_cna)
-		vfree(bfi_image_ct_cna);
-	if (bfi_image_cb_fc_size && bfi_image_cb_fc)
-		vfree(bfi_image_cb_fc);
-}
-
-#endif
diff --git a/drivers/scsi/bfa/bfad_intr.c b/drivers/scsi/bfa/bfad_intr.c
deleted file mode 100644
index 56a3515..0000000
--- a/drivers/scsi/bfa/bfad_intr.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include "bfad_drv.h"
-#include "bfad_trcmod.h"
-
-BFA_TRC_FILE(LDRV, INTR);
-
-/**
- *  bfa_isr BFA driver interrupt functions
- */
-static int msix_disable_cb;
-static int msix_disable_ct;
-module_param(msix_disable_cb, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(msix_disable_cb, "Disable MSIX for Brocade-415/425/815/825"
-		" cards, default=0, Range[false:0|true:1]");
-module_param(msix_disable_ct, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(msix_disable_ct, "Disable MSIX for Brocade-1010/1020/804"
-		" cards, default=0, Range[false:0|true:1]");
-/**
- * Line based interrupt handler.
- */
-static irqreturn_t
-bfad_intx(int irq, void *dev_id)
-{
-	struct bfad_s         *bfad = dev_id;
-	struct list_head         doneq;
-	unsigned long   flags;
-	bfa_boolean_t rc;
-
-	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	rc = bfa_intx(&bfad->bfa);
-	if (!rc) {
-		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		return IRQ_NONE;
-	}
-
-	bfa_comp_deq(&bfad->bfa, &doneq);
-	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
-	if (!list_empty(&doneq)) {
-		bfa_comp_process(&bfad->bfa, &doneq);
-
-		spin_lock_irqsave(&bfad->bfad_lock, flags);
-		bfa_comp_free(&bfad->bfa, &doneq);
-		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		bfa_trc_fp(bfad, irq);
-	}
-
-	return IRQ_HANDLED;
-
-}
-
-static irqreturn_t
-bfad_msix(int irq, void *dev_id)
-{
-	struct bfad_msix_s *vec = dev_id;
-	struct bfad_s *bfad = vec->bfad;
-	struct list_head doneq;
-	unsigned long   flags;
-
-	spin_lock_irqsave(&bfad->bfad_lock, flags);
-
-	bfa_msix(&bfad->bfa, vec->msix.entry);
-	bfa_comp_deq(&bfad->bfa, &doneq);
-	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
-	if (!list_empty(&doneq)) {
-		bfa_comp_process(&bfad->bfa, &doneq);
-
-		spin_lock_irqsave(&bfad->bfad_lock, flags);
-		bfa_comp_free(&bfad->bfa, &doneq);
-		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-	}
-
-	return IRQ_HANDLED;
-}
-
-/**
- * Initialize the MSIX entry table.
- */
-static void
-bfad_init_msix_entry(struct bfad_s *bfad, struct msix_entry *msix_entries,
-			 int mask, int max_bit)
-{
-	int             i;
-	int             match = 0x00000001;
-
-	for (i = 0, bfad->nvec = 0; i < MAX_MSIX_ENTRY; i++) {
-		if (mask & match) {
-			bfad->msix_tab[bfad->nvec].msix.entry = i;
-			bfad->msix_tab[bfad->nvec].bfad = bfad;
-			msix_entries[bfad->nvec].entry = i;
-			bfad->nvec++;
-		}
-
-		match <<= 1;
-	}
-
-}
-
-int
-bfad_install_msix_handler(struct bfad_s *bfad)
-{
-	int             i, error = 0;
-
-	for (i = 0; i < bfad->nvec; i++) {
-		error = request_irq(bfad->msix_tab[i].msix.vector,
-				    (irq_handler_t) bfad_msix, 0,
-				    BFAD_DRIVER_NAME, &bfad->msix_tab[i]);
-		bfa_trc(bfad, i);
-		bfa_trc(bfad, bfad->msix_tab[i].msix.vector);
-		if (error) {
-			int             j;
-
-			for (j = 0; j < i; j++)
-				free_irq(bfad->msix_tab[j].msix.vector,
-						&bfad->msix_tab[j]);
-
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-/**
- * Setup MSIX based interrupt.
- */
-int
-bfad_setup_intr(struct bfad_s *bfad)
-{
-	int error = 0;
-	u32 mask = 0, i, num_bit = 0, max_bit = 0;
-	struct msix_entry msix_entries[MAX_MSIX_ENTRY];
-	struct pci_dev *pdev = bfad->pcidev;
-
-	/* Call BFA to get the msix map for this PCI function.  */
-	bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
-
-	/* Set up the msix entry table */
-	bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
-
-	if ((bfa_asic_id_ct(pdev->device) && !msix_disable_ct) ||
-		(!bfa_asic_id_ct(pdev->device) && !msix_disable_cb)) {
-
-		error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
-		if (error) {
-			/*
-			 * Only error number of vector is available.
-			 * We don't have a mechanism to map multiple
-			 * interrupts into one vector, so even if we
-			 * can try to request less vectors, we don't
-			 * know how to associate interrupt events to
-			 *  vectors. Linux doesn't dupicate vectors
-			 * in the MSIX table for this case.
-			 */
-
-			printk(KERN_WARNING "bfad%d: "
-				"pci_enable_msix failed (%d),"
-				" use line based.\n", bfad->inst_no, error);
-
-			goto line_based;
-		}
-
-		/* Save the vectors */
-		for (i = 0; i < bfad->nvec; i++) {
-			bfa_trc(bfad, msix_entries[i].vector);
-			bfad->msix_tab[i].msix.vector = msix_entries[i].vector;
-		}
-
-		bfa_msix_init(&bfad->bfa, bfad->nvec);
-
-		bfad->bfad_flags |= BFAD_MSIX_ON;
-
-		return error;
-	}
-
-line_based:
-	error = 0;
-	if (request_irq
-	    (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
-	     BFAD_DRIVER_NAME, bfad) != 0) {
-		/* Enable interrupt handler failed */
-		return 1;
-	}
-
-	return error;
-}
-
-void
-bfad_remove_intr(struct bfad_s *bfad)
-{
-	int             i;
-
-	if (bfad->bfad_flags & BFAD_MSIX_ON) {
-		for (i = 0; i < bfad->nvec; i++)
-			free_irq(bfad->msix_tab[i].msix.vector,
-					&bfad->msix_tab[i]);
-
-		pci_disable_msix(bfad->pcidev);
-		bfad->bfad_flags &= ~BFAD_MSIX_ON;
-	} else {
-		free_irq(bfad->pcidev->irq, bfad);
-	}
-}
-
-
diff --git a/drivers/scsi/bfa/bfad_ipfc.h b/drivers/scsi/bfa/bfad_ipfc.h
deleted file mode 100644
index 718bc52..0000000
--- a/drivers/scsi/bfa/bfad_ipfc.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DRV_IPFC_H__
-#define __BFA_DRV_IPFC_H__
-
-
-#define IPFC_NAME ""
-
-#define bfad_ipfc_module_init(x) do {} while (0)
-#define bfad_ipfc_module_exit(x) do {} while (0)
-#define bfad_ipfc_probe(x) do {} while (0)
-#define bfad_ipfc_probe_undo(x) do {} while (0)
-#define bfad_ipfc_port_config(x, y) BFA_STATUS_OK
-#define bfad_ipfc_port_unconfig(x, y) do {} while (0)
-
-#define bfad_ipfc_probe_post(x) do {} while (0)
-#define bfad_ipfc_port_new(x, y, z) BFA_STATUS_OK
-#define bfad_ipfc_port_delete(x, y) do {} while (0)
-#define bfad_ipfc_port_online(x, y) do {} while (0)
-#define bfad_ipfc_port_offline(x, y) do {} while (0)
-
-#define bfad_ip_get_attr(x) BFA_STATUS_FAILED
-#define bfad_ip_reset_drv_stats(x) BFA_STATUS_FAILED
-#define bfad_ip_get_drv_stats(x, y) BFA_STATUS_FAILED
-#define bfad_ip_enable_ipfc(x, y, z) BFA_STATUS_FAILED
-
-
-#endif
diff --git a/drivers/scsi/bfa/bfad_os.c b/drivers/scsi/bfa/bfad_os.c
deleted file mode 100644
index faf47b4..0000000
--- a/drivers/scsi/bfa/bfad_os.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfad_os.c Linux driver OS specific calls.
- */
-
-#include "bfa_os_inc.h"
-#include "bfad_drv.h"
-
-void
-bfa_os_gettimeofday(struct bfa_timeval_s *tv)
-{
-	struct timeval  tmp_tv;
-
-	do_gettimeofday(&tmp_tv);
-	tv->tv_sec = (u32) tmp_tv.tv_sec;
-	tv->tv_usec = (u32) tmp_tv.tv_usec;
-}
-
-void
-bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id,
-			const char *fmt, ...)
-{
-	va_list ap;
-	#define BFA_STRING_256	256
-	char tmp[BFA_STRING_256];
-
-	va_start(ap, fmt);
-	vsprintf(tmp, fmt, ap);
-	va_end(ap);
-
-	printk(tmp);
-}
-
-
diff --git a/drivers/scsi/bfa/bfad_tm.h b/drivers/scsi/bfa/bfad_tm.h
deleted file mode 100644
index 4901b1b..0000000
--- a/drivers/scsi/bfa/bfad_tm.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/*
- * Brocade Fibre Channel HBA Linux Target Mode Driver
- */
-
-/**
- *  tm/dummy/bfad_tm.h BFA callback dummy header file for BFA Linux target mode PCI interface module.
- */
-
-#ifndef __BFAD_TM_H__
-#define __BFAD_TM_H__
-
-#include <defs/bfa_defs_status.h>
-
-#define FCPT_NAME 		""
-
-/*
- * Called from base Linux driver on (De)Init events
- */
-
-/* attach tgt template with scst */
-#define bfad_tm_module_init()	do {} while (0)
-
-/* detach/release tgt template */
-#define bfad_tm_module_exit()	do {} while (0)
-
-#define bfad_tm_probe(x)	do {} while (0)
-#define bfad_tm_probe_undo(x)	do {} while (0)
-#define bfad_tm_probe_post(x)	do {} while (0)
-
-/*
- * Called by base Linux driver but triggered by BFA FCS on config events
- */
-#define bfad_tm_port_new(x, y)		BFA_STATUS_OK
-#define bfad_tm_port_delete(x, y)	do {} while (0)
-
-/*
- * Called by base Linux driver but triggered by BFA FCS on PLOGI/O events
- */
-#define bfad_tm_port_online(x, y)	do {} while (0)
-#define bfad_tm_port_offline(x, y)	do {} while (0)
-
-#endif
diff --git a/drivers/scsi/bfa/bfad_trcmod.h b/drivers/scsi/bfa/bfad_trcmod.h
deleted file mode 100644
index 2827b2a..0000000
--- a/drivers/scsi/bfa/bfad_trcmod.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfad_trcmod.h Linux driver trace modules
- */
-
-
-#ifndef __BFAD_TRCMOD_H__
-#define __BFAD_TRCMOD_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
-	/* 2.6 Driver */
-	BFA_TRC_LDRV_BFAD		= 1,
-	BFA_TRC_LDRV_BFAD_2_6		= 2,
-	BFA_TRC_LDRV_BFAD_2_6_9		= 3,
-	BFA_TRC_LDRV_BFAD_2_6_10	= 4,
-	BFA_TRC_LDRV_INTR		= 5,
-	BFA_TRC_LDRV_IOCTL		= 6,
-	BFA_TRC_LDRV_OS			= 7,
-	BFA_TRC_LDRV_IM			= 8,
-	BFA_TRC_LDRV_IM_2_6		= 9,
-	BFA_TRC_LDRV_IM_2_6_9		= 10,
-	BFA_TRC_LDRV_IM_2_6_10		= 11,
-	BFA_TRC_LDRV_TM			= 12,
-	BFA_TRC_LDRV_IPFC		= 13,
-	BFA_TRC_LDRV_IM_2_4		= 14,
-	BFA_TRC_LDRV_IM_VMW		= 15,
-	BFA_TRC_LDRV_IM_LT_2_6_10	= 16,
-};
-
-#endif /* __BFAD_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
new file mode 100644
index 0000000..85f2224
--- /dev/null
+++ b/drivers/scsi/bfa/bfi.h
@@ -0,0 +1,579 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_H__
+#define __BFI_H__
+
+#include "bfa_defs.h"
+#include "bfa_defs_svc.h"
+
+#pragma pack(1)
+
+/**
+ * BFI FW image type
+ */
+#define	BFI_FLASH_CHUNK_SZ			256	/*  Flash chunk size */
+#define	BFI_FLASH_CHUNK_SZ_WORDS	(BFI_FLASH_CHUNK_SZ/sizeof(u32))
+enum {
+	BFI_IMAGE_CB_FC,
+	BFI_IMAGE_CT_FC,
+	BFI_IMAGE_CT_CNA,
+	BFI_IMAGE_MAX,
+};
+
+/**
+ * Msg header common to all msgs
+ */
+struct bfi_mhdr_s {
+	u8		msg_class;	/*  @ref bfi_mclass_t		    */
+	u8		msg_id;		/*  msg opcode with in the class   */
+	union {
+		struct {
+			u8	rsvd;
+			u8	lpu_id;	/*  msg destination		    */
+		} h2i;
+		u16	i2htok;	/*  token in msgs to host	    */
+	} mtag;
+};
+
+#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {		\
+	(_mh).msg_class		= (_mc);      \
+	(_mh).msg_id		= (_op);      \
+	(_mh).mtag.h2i.lpu_id	= (_lpuid);      \
+} while (0)
+
+#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {		\
+	(_mh).msg_class		= (_mc);      \
+	(_mh).msg_id		= (_op);      \
+	(_mh).mtag.i2htok	= (_i2htok);      \
+} while (0)
+
+/*
+ * Message opcodes: 0-127 to firmware, 128-255 to host
+ */
+#define BFI_I2H_OPCODE_BASE	128
+#define BFA_I2HM(_x)		((_x) + BFI_I2H_OPCODE_BASE)
+
+/**
+ ****************************************************************************
+ *
+ * Scatter Gather Element and Page definition
+ *
+ ****************************************************************************
+ */
+
+#define BFI_SGE_INLINE	1
+#define BFI_SGE_INLINE_MAX	(BFI_SGE_INLINE + 1)
+
+/**
+ * SG Flags
+ */
+enum {
+	BFI_SGE_DATA		= 0,	/*  data address, not last	     */
+	BFI_SGE_DATA_CPL	= 1,	/*  data addr, last in current page */
+	BFI_SGE_DATA_LAST	= 3,	/*  data address, last		     */
+	BFI_SGE_LINK		= 2,	/*  link address		     */
+	BFI_SGE_PGDLEN		= 2,	/*  cumulative data length for page */
+};
+
+/**
+ * DMA addresses
+ */
+union bfi_addr_u {
+	struct {
+		u32	addr_lo;
+		u32	addr_hi;
+	} a32;
+};
+
+/**
+ * Scatter Gather Element
+ */
+struct bfi_sge_s {
+#ifdef __BIGENDIAN
+	u32	flags:2,
+			rsvd:2,
+			sg_len:28;
+#else
+	u32	sg_len:28,
+			rsvd:2,
+			flags:2;
+#endif
+	union bfi_addr_u sga;
+};
+
+/**
+ * Scatter Gather Page
+ */
+#define BFI_SGPG_DATA_SGES		7
+#define BFI_SGPG_SGES_MAX		(BFI_SGPG_DATA_SGES + 1)
+#define BFI_SGPG_RSVD_WD_LEN	8
+struct bfi_sgpg_s {
+	struct bfi_sge_s sges[BFI_SGPG_SGES_MAX];
+	u32	rsvd[BFI_SGPG_RSVD_WD_LEN];
+};
+
+/*
+ * Large Message structure - 128 Bytes size Msgs
+ */
+#define BFI_LMSG_SZ		128
+#define BFI_LMSG_PL_WSZ	\
+			((BFI_LMSG_SZ - sizeof(struct bfi_mhdr_s)) / 4)
+
+struct bfi_msg_s {
+	struct bfi_mhdr_s mhdr;
+	u32	pl[BFI_LMSG_PL_WSZ];
+};
+
+/**
+ * Mailbox message structure
+ */
+#define BFI_MBMSG_SZ		7
+struct bfi_mbmsg_s {
+	struct bfi_mhdr_s	mh;
+	u32		pl[BFI_MBMSG_SZ];
+};
+
+/**
+ * Message Classes
+ */
+enum bfi_mclass {
+	BFI_MC_IOC		= 1,	/*  IO Controller (IOC)	    */
+	BFI_MC_FCPORT		= 5,	/*  FC port			    */
+	BFI_MC_IOCFC		= 6,	/*  FC - IO Controller (IOC)	    */
+	BFI_MC_LL               = 7,    /*  Link Layer                      */
+	BFI_MC_UF		= 8,	/*  Unsolicited frame receive	    */
+	BFI_MC_FCXP		= 9,	/*  FC Transport		    */
+	BFI_MC_LPS		= 10,	/*  lport fc login services	    */
+	BFI_MC_RPORT		= 11,	/*  Remote port		    */
+	BFI_MC_ITNIM		= 12,	/*  I-T nexus (Initiator mode)	    */
+	BFI_MC_IOIM_READ	= 13,	/*  read IO (Initiator mode)	    */
+	BFI_MC_IOIM_WRITE	= 14,	/*  write IO (Initiator mode)	    */
+	BFI_MC_IOIM_IO		= 15,	/*  IO (Initiator mode)	    */
+	BFI_MC_IOIM		= 16,	/*  IO (Initiator mode)	    */
+	BFI_MC_IOIM_IOCOM	= 17,	/*  good IO completion		    */
+	BFI_MC_TSKIM		= 18,	/*  Initiator Task management	    */
+	BFI_MC_PORT		= 21,	/*  Physical port		    */
+	BFI_MC_MAX		= 32
+};
+
+#define BFI_IOC_MAX_CQS		4
+#define BFI_IOC_MAX_CQS_ASIC	8
+#define BFI_IOC_MSGLEN_MAX	32	/* 32 bytes */
+
+#define BFI_BOOT_TYPE_OFF		8
+#define BFI_BOOT_LOADER_OFF		12
+
+#define BFI_BOOT_TYPE_NORMAL		0
+#define	BFI_BOOT_TYPE_FLASH		1
+#define	BFI_BOOT_TYPE_MEMTEST		2
+
+#define BFI_BOOT_LOADER_OS		0
+#define BFI_BOOT_LOADER_BIOS		1
+#define BFI_BOOT_LOADER_UEFI		2
+
+/**
+ *----------------------------------------------------------------------
+ *				IOC
+ *----------------------------------------------------------------------
+ */
+
+enum bfi_ioc_h2i_msgs {
+	BFI_IOC_H2I_ENABLE_REQ		= 1,
+	BFI_IOC_H2I_DISABLE_REQ		= 2,
+	BFI_IOC_H2I_GETATTR_REQ		= 3,
+	BFI_IOC_H2I_DBG_SYNC		= 4,
+	BFI_IOC_H2I_DBG_DUMP		= 5,
+};
+
+enum bfi_ioc_i2h_msgs {
+	BFI_IOC_I2H_ENABLE_REPLY	= BFA_I2HM(1),
+	BFI_IOC_I2H_DISABLE_REPLY	= BFA_I2HM(2),
+	BFI_IOC_I2H_GETATTR_REPLY	= BFA_I2HM(3),
+	BFI_IOC_I2H_READY_EVENT		= BFA_I2HM(4),
+	BFI_IOC_I2H_HBEAT		= BFA_I2HM(5),
+};
+
+/**
+ * BFI_IOC_H2I_GETATTR_REQ message
+ */
+struct bfi_ioc_getattr_req_s {
+	struct bfi_mhdr_s	mh;
+	union bfi_addr_u	attr_addr;
+};
+
+struct bfi_ioc_attr_s {
+	wwn_t		mfg_pwwn;	/*  Mfg port wwn	   */
+	wwn_t		mfg_nwwn;	/*  Mfg node wwn	   */
+	mac_t		mfg_mac;	/*  Mfg mac		   */
+	u16	rsvd_a;
+	wwn_t		pwwn;
+	wwn_t		nwwn;
+	mac_t		mac;		/*  PBC or Mfg mac	   */
+	u16	rsvd_b;
+	mac_t		fcoe_mac;
+	u16	rsvd_c;
+	char		brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+	u8		pcie_gen;
+	u8		pcie_lanes_orig;
+	u8		pcie_lanes;
+	u8		rx_bbcredit;	/*  receive buffer credits */
+	u32	adapter_prop;	/*  adapter properties     */
+	u16	maxfrsize;	/*  max receive frame size */
+	char		asic_rev;
+	u8		rsvd_d;
+	char		fw_version[BFA_VERSION_LEN];
+	char		optrom_version[BFA_VERSION_LEN];
+	struct		bfa_mfg_vpd_s	vpd;
+	u32	card_type;	/*  card type			*/
+};
+
+/**
+ * BFI_IOC_I2H_GETATTR_REPLY message
+ */
+struct bfi_ioc_getattr_reply_s {
+	struct	bfi_mhdr_s	mh;	/*  Common msg header		*/
+	u8			status;	/*  cfg reply status		*/
+	u8			rsvd[3];
+};
+
+/**
+ * Firmware memory page offsets
+ */
+#define BFI_IOC_SMEM_PG0_CB	(0x40)
+#define BFI_IOC_SMEM_PG0_CT	(0x180)
+
+/**
+ * Firmware statistic offset
+ */
+#define BFI_IOC_FWSTATS_OFF	(0x6B40)
+#define BFI_IOC_FWSTATS_SZ	(4096)
+
+/**
+ * Firmware trace offset
+ */
+#define BFI_IOC_TRC_OFF		(0x4b00)
+#define BFI_IOC_TRC_ENTS	256
+
+#define BFI_IOC_FW_SIGNATURE	(0xbfadbfad)
+#define BFI_IOC_MD5SUM_SZ	4
+struct bfi_ioc_image_hdr_s {
+	u32	signature;	/*  constant signature */
+	u32	rsvd_a;
+	u32	exec;		/*  exec vector	*/
+	u32	param;		/*  parameters		*/
+	u32	rsvd_b[4];
+	u32	md5sum[BFI_IOC_MD5SUM_SZ];
+};
+
+/**
+ *  BFI_IOC_I2H_READY_EVENT message
+ */
+struct bfi_ioc_rdy_event_s {
+	struct bfi_mhdr_s	mh;		/*  common msg header */
+	u8			init_status;	/*  init event status */
+	u8			rsvd[3];
+};
+
+struct bfi_ioc_hbeat_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u32	   hb_count;	/*  current heart beat count	*/
+};
+
+/**
+ * IOC hardware/firmware state
+ */
+enum bfi_ioc_state {
+	BFI_IOC_UNINIT		= 0,	/*  not initialized		     */
+	BFI_IOC_INITING		= 1,	/*  h/w is being initialized	     */
+	BFI_IOC_HWINIT		= 2,	/*  h/w is initialized		     */
+	BFI_IOC_CFG		= 3,	/*  IOC configuration in progress   */
+	BFI_IOC_OP		= 4,	/*  IOC is operational		     */
+	BFI_IOC_DISABLING	= 5,	/*  IOC is being disabled	     */
+	BFI_IOC_DISABLED	= 6,	/*  IOC is disabled		     */
+	BFI_IOC_CFG_DISABLED	= 7,	/*  IOC is being disabled;transient */
+	BFI_IOC_FAIL		= 8,	/*  IOC heart-beat failure	     */
+	BFI_IOC_MEMTEST		= 9,	/*  IOC is doing memtest	     */
+};
+
+#define BFI_IOC_ENDIAN_SIG  0x12345678
+
+enum {
+	BFI_ADAPTER_TYPE_FC	= 0x01,		/*  FC adapters	   */
+	BFI_ADAPTER_TYPE_MK	= 0x0f0000,	/*  adapter type mask     */
+	BFI_ADAPTER_TYPE_SH	= 16,	        /*  adapter type shift    */
+	BFI_ADAPTER_NPORTS_MK	= 0xff00,	/*  number of ports mask  */
+	BFI_ADAPTER_NPORTS_SH	= 8,	        /*  number of ports shift */
+	BFI_ADAPTER_SPEED_MK	= 0xff,		/*  adapter speed mask    */
+	BFI_ADAPTER_SPEED_SH	= 0,	        /*  adapter speed shift   */
+	BFI_ADAPTER_PROTO	= 0x100000,	/*  prototype adapaters   */
+	BFI_ADAPTER_TTV		= 0x200000,	/*  TTV debug capable     */
+	BFI_ADAPTER_UNSUPP	= 0x400000,	/*  unknown adapter type  */
+};
+
+#define BFI_ADAPTER_GETP(__prop, __adap_prop)			\
+	(((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >>	\
+		BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_SETP(__prop, __val)				\
+	((__val) << BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_IS_PROTO(__adap_type)			\
+	((__adap_type) & BFI_ADAPTER_PROTO)
+#define BFI_ADAPTER_IS_TTV(__adap_type)				\
+	((__adap_type) & BFI_ADAPTER_TTV)
+#define BFI_ADAPTER_IS_UNSUPP(__adap_type)			\
+	((__adap_type) & BFI_ADAPTER_UNSUPP)
+#define BFI_ADAPTER_IS_SPECIAL(__adap_type)			\
+	((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO |	\
+			BFI_ADAPTER_UNSUPP))
+
+/**
+ * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages
+ */
+struct bfi_ioc_ctrl_req_s {
+	struct bfi_mhdr_s	mh;
+	u8			ioc_class;
+	u8			rsvd[3];
+	u32		tv_sec;
+};
+#define bfi_ioc_enable_req_t struct bfi_ioc_ctrl_req_s;
+#define bfi_ioc_disable_req_t struct bfi_ioc_ctrl_req_s;
+
+/**
+ * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
+ */
+struct bfi_ioc_ctrl_reply_s {
+	struct bfi_mhdr_s	mh;		/*  Common msg header     */
+	u8			status;		/*  enable/disable status */
+	u8			rsvd[3];
+};
+#define bfi_ioc_enable_reply_t struct bfi_ioc_ctrl_reply_s;
+#define bfi_ioc_disable_reply_t struct bfi_ioc_ctrl_reply_s;
+
+#define BFI_IOC_MSGSZ   8
+/**
+ * H2I Messages
+ */
+union bfi_ioc_h2i_msg_u {
+	struct bfi_mhdr_s		mh;
+	struct bfi_ioc_ctrl_req_s	enable_req;
+	struct bfi_ioc_ctrl_req_s	disable_req;
+	struct bfi_ioc_getattr_req_s	getattr_req;
+	u32			mboxmsg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * I2H Messages
+ */
+union bfi_ioc_i2h_msg_u {
+	struct bfi_mhdr_s		mh;
+	struct bfi_ioc_rdy_event_s	rdy_event;
+	u32			mboxmsg[BFI_IOC_MSGSZ];
+};
+
+
+/**
+ *----------------------------------------------------------------------
+ *				PBC
+ *----------------------------------------------------------------------
+ */
+
+#define BFI_PBC_MAX_BLUNS	8
+#define BFI_PBC_MAX_VPORTS	16
+
+/**
+ * PBC boot lun configuration
+ */
+struct bfi_pbc_blun_s {
+	wwn_t		tgt_pwwn;
+	lun_t		tgt_lun;
+};
+
+/**
+ * PBC virtual port configuration
+ */
+struct bfi_pbc_vport_s {
+	wwn_t		vp_pwwn;
+	wwn_t		vp_nwwn;
+};
+
+/**
+ * BFI pre-boot configuration information
+ */
+struct bfi_pbc_s {
+	u8		port_enabled;
+	u8		boot_enabled;
+	u8		nbluns;
+	u8		nvports;
+	u8		port_speed;
+	u8		rsvd_a;
+	u16	hss;
+	wwn_t		pbc_pwwn;
+	wwn_t		pbc_nwwn;
+	struct bfi_pbc_blun_s blun[BFI_PBC_MAX_BLUNS];
+	struct bfi_pbc_vport_s vport[BFI_PBC_MAX_VPORTS];
+};
+
+/**
+ *----------------------------------------------------------------------
+ *				MSGQ
+ *----------------------------------------------------------------------
+ */
+#define BFI_MSGQ_FULL(_q)	(((_q->pi + 1) % _q->q_depth) == _q->ci)
+#define BFI_MSGQ_EMPTY(_q)	(_q->pi == _q->ci)
+#define BFI_MSGQ_UPDATE_CI(_q)	(_q->ci = (_q->ci + 1) % _q->q_depth)
+#define BFI_MSGQ_UPDATE_PI(_q)	(_q->pi = (_q->pi + 1) % _q->q_depth)
+
+/* q_depth must be power of 2 */
+#define BFI_MSGQ_FREE_CNT(_q)	((_q->ci - _q->pi - 1) & (_q->q_depth - 1))
+
+enum bfi_msgq_h2i_msgs_e {
+	BFI_MSGQ_H2I_INIT_REQ	= 1,
+	BFI_MSGQ_H2I_DOORBELL	= 2,
+	BFI_MSGQ_H2I_SHUTDOWN	= 3,
+};
+
+enum bfi_msgq_i2h_msgs_e {
+	BFI_MSGQ_I2H_INIT_RSP	= 1,
+	BFI_MSGQ_I2H_DOORBELL	= 2,
+};
+
+
+/* Messages(commands/responsed/AENS will have the following header */
+struct bfi_msgq_mhdr_s {
+	u8		msg_class;
+	u8		msg_id;
+	u16	msg_token;
+	u16	num_entries;
+	u8		enet_id;
+	u8		rsvd[1];
+};
+
+#define bfi_msgq_mhdr_set(_mh, _mc, _mid, _tok, _enet_id) do {        \
+	(_mh).msg_class		= (_mc);      \
+	(_mh).msg_id		= (_mid);      \
+	(_mh).msg_token		= (_tok);      \
+	(_mh).enet_id		= (_enet_id);      \
+} while (0)
+
+/*
+ * Mailbox  for messaging interface
+ *
+*/
+#define BFI_MSGQ_CMD_ENTRY_SIZE		(64)    /* TBD */
+#define BFI_MSGQ_RSP_ENTRY_SIZE		(64)    /* TBD */
+#define BFI_MSGQ_MSG_SIZE_MAX		(2048)  /* TBD */
+
+struct bfi_msgq_s {
+	union bfi_addr_u addr;
+	u16 q_depth;     /* Total num of entries in the queue */
+	u8 rsvd[2];
+};
+
+/* BFI_ENET_MSGQ_CFG_REQ TBD init or cfg? */
+struct bfi_msgq_cfg_req_s {
+	struct bfi_mhdr_s mh;
+	struct bfi_msgq_s cmdq;
+	struct bfi_msgq_s rspq;
+};
+
+/* BFI_ENET_MSGQ_CFG_RSP */
+struct bfi_msgq_cfg_rsp_s {
+	struct bfi_mhdr_s mh;
+	u8 cmd_status;
+	u8 rsvd[3];
+};
+
+
+/* BFI_MSGQ_H2I_DOORBELL */
+struct bfi_msgq_h2i_db_s {
+	struct bfi_mhdr_s mh;
+	u16 cmdq_pi;
+	u16 rspq_ci;
+};
+
+/* BFI_MSGQ_I2H_DOORBELL */
+struct bfi_msgq_i2h_db_s {
+	struct bfi_mhdr_s mh;
+	u16 rspq_pi;
+	u16 cmdq_ci;
+};
+
+#pragma pack()
+
+/* BFI port specific */
+#pragma pack(1)
+
+enum bfi_port_h2i {
+	BFI_PORT_H2I_ENABLE_REQ         = (1),
+	BFI_PORT_H2I_DISABLE_REQ        = (2),
+	BFI_PORT_H2I_GET_STATS_REQ      = (3),
+	BFI_PORT_H2I_CLEAR_STATS_REQ    = (4),
+};
+
+enum bfi_port_i2h {
+	BFI_PORT_I2H_ENABLE_RSP         = BFA_I2HM(1),
+	BFI_PORT_I2H_DISABLE_RSP        = BFA_I2HM(2),
+	BFI_PORT_I2H_GET_STATS_RSP      = BFA_I2HM(3),
+	BFI_PORT_I2H_CLEAR_STATS_RSP    = BFA_I2HM(4),
+};
+
+/**
+ * Generic REQ type
+ */
+struct bfi_port_generic_req_s {
+	struct bfi_mhdr_s  mh;          /*  msg header		*/
+	u32     msgtag;         /*  msgtag for reply                */
+	u32     rsvd;
+};
+
+/**
+ * Generic RSP type
+ */
+struct bfi_port_generic_rsp_s {
+	struct bfi_mhdr_s  mh;          /*  common msg header               */
+	u8              status;         /*  port enable status              */
+	u8              rsvd[3];
+	u32     msgtag;         /*  msgtag for reply                */
+};
+
+/**
+ * BFI_PORT_H2I_GET_STATS_REQ
+ */
+struct bfi_port_get_stats_req_s {
+	struct bfi_mhdr_s  mh;          /*  common msg header               */
+	union bfi_addr_u   dma_addr;
+};
+
+union bfi_port_h2i_msg_u {
+	struct bfi_mhdr_s               mh;
+	struct bfi_port_generic_req_s   enable_req;
+	struct bfi_port_generic_req_s   disable_req;
+	struct bfi_port_get_stats_req_s getstats_req;
+	struct bfi_port_generic_req_s   clearstats_req;
+};
+
+union bfi_port_i2h_msg_u {
+	struct bfi_mhdr_s               mh;
+	struct bfi_port_generic_rsp_s   enable_rsp;
+	struct bfi_port_generic_rsp_s   disable_rsp;
+	struct bfi_port_generic_rsp_s   getstats_rsp;
+	struct bfi_port_generic_rsp_s   clearstats_rsp;
+};
+
+#pragma pack()
+
+#endif /* __BFI_H__ */
diff --git a/drivers/scsi/bfa/bfi_cbreg.h b/drivers/scsi/bfa/bfi_cbreg.h
new file mode 100644
index 0000000..6f03ed3
--- /dev/null
+++ b/drivers/scsi/bfa/bfi_cbreg.h
@@ -0,0 +1,304 @@
+
+/*
+ * bfi_cbreg.h crossbow host block register definitions
+ *
+ * !!! Do not edit. Auto generated. !!!
+ */
+
+#ifndef __BFI_CBREG_H__
+#define __BFI_CBREG_H__
+
+
+#define HOSTFN0_INT_STATUS               0x00014000
+#define __HOSTFN0_INT_STATUS_LVL_MK      0x00f00000
+#define __HOSTFN0_INT_STATUS_LVL_SH      20
+#define __HOSTFN0_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
+#define __HOSTFN0_INT_STATUS_P           0x000fffff
+#define HOSTFN0_INT_MSK                  0x00014004
+#define HOST_PAGE_NUM_FN0                0x00014008
+#define __HOST_PAGE_NUM_FN               0x000001ff
+#define HOSTFN1_INT_STATUS               0x00014100
+#define __HOSTFN1_INT_STAT_LVL_MK        0x00f00000
+#define __HOSTFN1_INT_STAT_LVL_SH        20
+#define __HOSTFN1_INT_STAT_LVL(_v)       ((_v) << __HOSTFN1_INT_STAT_LVL_SH)
+#define __HOSTFN1_INT_STAT_P             0x000fffff
+#define HOSTFN1_INT_MSK                  0x00014104
+#define HOST_PAGE_NUM_FN1                0x00014108
+#define APP_PLL_400_CTL_REG              0x00014204
+#define __P_400_PLL_LOCK                 0x80000000
+#define __APP_PLL_400_SRAM_USE_100MHZ    0x00100000
+#define __APP_PLL_400_RESET_TIMER_MK     0x000e0000
+#define __APP_PLL_400_RESET_TIMER_SH     17
+#define __APP_PLL_400_RESET_TIMER(_v)    ((_v) << __APP_PLL_400_RESET_TIMER_SH)
+#define __APP_PLL_400_LOGIC_SOFT_RESET   0x00010000
+#define __APP_PLL_400_CNTLMT0_1_MK       0x0000c000
+#define __APP_PLL_400_CNTLMT0_1_SH       14
+#define __APP_PLL_400_CNTLMT0_1(_v)      ((_v) << __APP_PLL_400_CNTLMT0_1_SH)
+#define __APP_PLL_400_JITLMT0_1_MK       0x00003000
+#define __APP_PLL_400_JITLMT0_1_SH       12
+#define __APP_PLL_400_JITLMT0_1(_v)      ((_v) << __APP_PLL_400_JITLMT0_1_SH)
+#define __APP_PLL_400_HREF               0x00000800
+#define __APP_PLL_400_HDIV               0x00000400
+#define __APP_PLL_400_P0_1_MK            0x00000300
+#define __APP_PLL_400_P0_1_SH            8
+#define __APP_PLL_400_P0_1(_v)           ((_v) << __APP_PLL_400_P0_1_SH)
+#define __APP_PLL_400_Z0_2_MK            0x000000e0
+#define __APP_PLL_400_Z0_2_SH            5
+#define __APP_PLL_400_Z0_2(_v)           ((_v) << __APP_PLL_400_Z0_2_SH)
+#define __APP_PLL_400_RSEL200500         0x00000010
+#define __APP_PLL_400_ENARST             0x00000008
+#define __APP_PLL_400_BYPASS             0x00000004
+#define __APP_PLL_400_LRESETN            0x00000002
+#define __APP_PLL_400_ENABLE             0x00000001
+#define APP_PLL_212_CTL_REG              0x00014208
+#define __P_212_PLL_LOCK                 0x80000000
+#define __APP_PLL_212_RESET_TIMER_MK     0x000e0000
+#define __APP_PLL_212_RESET_TIMER_SH     17
+#define __APP_PLL_212_RESET_TIMER(_v)    ((_v) << __APP_PLL_212_RESET_TIMER_SH)
+#define __APP_PLL_212_LOGIC_SOFT_RESET   0x00010000
+#define __APP_PLL_212_CNTLMT0_1_MK       0x0000c000
+#define __APP_PLL_212_CNTLMT0_1_SH       14
+#define __APP_PLL_212_CNTLMT0_1(_v)      ((_v) << __APP_PLL_212_CNTLMT0_1_SH)
+#define __APP_PLL_212_JITLMT0_1_MK       0x00003000
+#define __APP_PLL_212_JITLMT0_1_SH       12
+#define __APP_PLL_212_JITLMT0_1(_v)      ((_v) << __APP_PLL_212_JITLMT0_1_SH)
+#define __APP_PLL_212_HREF               0x00000800
+#define __APP_PLL_212_HDIV               0x00000400
+#define __APP_PLL_212_P0_1_MK            0x00000300
+#define __APP_PLL_212_P0_1_SH            8
+#define __APP_PLL_212_P0_1(_v)           ((_v) << __APP_PLL_212_P0_1_SH)
+#define __APP_PLL_212_Z0_2_MK            0x000000e0
+#define __APP_PLL_212_Z0_2_SH            5
+#define __APP_PLL_212_Z0_2(_v)           ((_v) << __APP_PLL_212_Z0_2_SH)
+#define __APP_PLL_212_RSEL200500         0x00000010
+#define __APP_PLL_212_ENARST             0x00000008
+#define __APP_PLL_212_BYPASS             0x00000004
+#define __APP_PLL_212_LRESETN            0x00000002
+#define __APP_PLL_212_ENABLE             0x00000001
+#define HOST_SEM0_REG                    0x00014230
+#define __HOST_SEMAPHORE                 0x00000001
+#define HOST_SEM1_REG                    0x00014234
+#define HOST_SEM2_REG                    0x00014238
+#define HOST_SEM3_REG                    0x0001423c
+#define HOST_SEM0_INFO_REG               0x00014240
+#define HOST_SEM1_INFO_REG               0x00014244
+#define HOST_SEM2_INFO_REG               0x00014248
+#define HOST_SEM3_INFO_REG               0x0001424c
+#define HOSTFN0_LPU0_CMD_STAT            0x00019000
+#define __HOSTFN0_LPU0_MBOX_INFO_MK      0xfffffffe
+#define __HOSTFN0_LPU0_MBOX_INFO_SH      1
+#define __HOSTFN0_LPU0_MBOX_INFO(_v)     ((_v) << __HOSTFN0_LPU0_MBOX_INFO_SH)
+#define __HOSTFN0_LPU0_MBOX_CMD_STATUS   0x00000001
+#define LPU0_HOSTFN0_CMD_STAT            0x00019008
+#define __LPU0_HOSTFN0_MBOX_INFO_MK      0xfffffffe
+#define __LPU0_HOSTFN0_MBOX_INFO_SH      1
+#define __LPU0_HOSTFN0_MBOX_INFO(_v)     ((_v) << __LPU0_HOSTFN0_MBOX_INFO_SH)
+#define __LPU0_HOSTFN0_MBOX_CMD_STATUS   0x00000001
+#define HOSTFN1_LPU1_CMD_STAT            0x00019014
+#define __HOSTFN1_LPU1_MBOX_INFO_MK      0xfffffffe
+#define __HOSTFN1_LPU1_MBOX_INFO_SH      1
+#define __HOSTFN1_LPU1_MBOX_INFO(_v)     ((_v) << __HOSTFN1_LPU1_MBOX_INFO_SH)
+#define __HOSTFN1_LPU1_MBOX_CMD_STATUS   0x00000001
+#define LPU1_HOSTFN1_CMD_STAT            0x0001901c
+#define __LPU1_HOSTFN1_MBOX_INFO_MK      0xfffffffe
+#define __LPU1_HOSTFN1_MBOX_INFO_SH      1
+#define __LPU1_HOSTFN1_MBOX_INFO(_v)     ((_v) << __LPU1_HOSTFN1_MBOX_INFO_SH)
+#define __LPU1_HOSTFN1_MBOX_CMD_STATUS   0x00000001
+#define CPE_Q0_DEPTH                     0x00010014
+#define CPE_Q0_PI                        0x0001001c
+#define CPE_Q0_CI                        0x00010020
+#define CPE_Q1_DEPTH                     0x00010034
+#define CPE_Q1_PI                        0x0001003c
+#define CPE_Q1_CI                        0x00010040
+#define CPE_Q2_DEPTH                     0x00010054
+#define CPE_Q2_PI                        0x0001005c
+#define CPE_Q2_CI                        0x00010060
+#define CPE_Q3_DEPTH                     0x00010074
+#define CPE_Q3_PI                        0x0001007c
+#define CPE_Q3_CI                        0x00010080
+#define CPE_Q4_DEPTH                     0x00010094
+#define CPE_Q4_PI                        0x0001009c
+#define CPE_Q4_CI                        0x000100a0
+#define CPE_Q5_DEPTH                     0x000100b4
+#define CPE_Q5_PI                        0x000100bc
+#define CPE_Q5_CI                        0x000100c0
+#define CPE_Q6_DEPTH                     0x000100d4
+#define CPE_Q6_PI                        0x000100dc
+#define CPE_Q6_CI                        0x000100e0
+#define CPE_Q7_DEPTH                     0x000100f4
+#define CPE_Q7_PI                        0x000100fc
+#define CPE_Q7_CI                        0x00010100
+#define RME_Q0_DEPTH                     0x00011014
+#define RME_Q0_PI                        0x0001101c
+#define RME_Q0_CI                        0x00011020
+#define RME_Q1_DEPTH                     0x00011034
+#define RME_Q1_PI                        0x0001103c
+#define RME_Q1_CI                        0x00011040
+#define RME_Q2_DEPTH                     0x00011054
+#define RME_Q2_PI                        0x0001105c
+#define RME_Q2_CI                        0x00011060
+#define RME_Q3_DEPTH                     0x00011074
+#define RME_Q3_PI                        0x0001107c
+#define RME_Q3_CI                        0x00011080
+#define RME_Q4_DEPTH                     0x00011094
+#define RME_Q4_PI                        0x0001109c
+#define RME_Q4_CI                        0x000110a0
+#define RME_Q5_DEPTH                     0x000110b4
+#define RME_Q5_PI                        0x000110bc
+#define RME_Q5_CI                        0x000110c0
+#define RME_Q6_DEPTH                     0x000110d4
+#define RME_Q6_PI                        0x000110dc
+#define RME_Q6_CI                        0x000110e0
+#define RME_Q7_DEPTH                     0x000110f4
+#define RME_Q7_PI                        0x000110fc
+#define RME_Q7_CI                        0x00011100
+#define PSS_CTL_REG                      0x00018800
+#define __PSS_I2C_CLK_DIV_MK             0x00030000
+#define __PSS_I2C_CLK_DIV_SH             16
+#define __PSS_I2C_CLK_DIV(_v)            ((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE             0x00001000
+#define __PSS_LMEM_RESET                 0x00000200
+#define __PSS_LMEM_INIT_EN               0x00000100
+#define __PSS_LPU1_RESET                 0x00000002
+#define __PSS_LPU0_RESET                 0x00000001
+#define PSS_ERR_STATUS_REG               0x00018810
+#define __PSS_LMEM1_CORR_ERR             0x00000800
+#define __PSS_LMEM0_CORR_ERR             0x00000400
+#define __PSS_LMEM1_UNCORR_ERR           0x00000200
+#define __PSS_LMEM0_UNCORR_ERR           0x00000100
+#define __PSS_BAL_PERR                   0x00000080
+#define __PSS_DIP_IF_ERR                 0x00000040
+#define __PSS_IOH_IF_ERR                 0x00000020
+#define __PSS_TDS_IF_ERR                 0x00000010
+#define __PSS_RDS_IF_ERR                 0x00000008
+#define __PSS_SGM_IF_ERR                 0x00000004
+#define __PSS_LPU1_RAM_ERR               0x00000002
+#define __PSS_LPU0_RAM_ERR               0x00000001
+#define ERR_SET_REG                      0x00018818
+#define __PSS_ERR_STATUS_SET             0x00000fff
+
+
+/*
+ * These definitions are either in error/missing in spec. Its auto-generated
+ * from hard coded values in regparse.pl.
+ */
+#define __EMPHPOST_AT_4G_MK_FIX          0x0000001c
+#define __EMPHPOST_AT_4G_SH_FIX          0x00000002
+#define __EMPHPRE_AT_4G_FIX              0x00000003
+#define __SFP_TXRATE_EN_FIX              0x00000100
+#define __SFP_RXRATE_EN_FIX              0x00000080
+
+
+/*
+ * These register definitions are auto-generated from hard coded values
+ * in regparse.pl.
+ */
+#define HOSTFN0_LPU_MBOX0_0              0x00019200
+#define HOSTFN1_LPU_MBOX0_8              0x00019260
+#define LPU_HOSTFN0_MBOX0_0              0x00019280
+#define LPU_HOSTFN1_MBOX0_8              0x000192e0
+
+
+/*
+ * These register mapping definitions are auto-generated from mapping tables
+ * in regparse.pl.
+ */
+#define BFA_IOC0_HBEAT_REG               HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG               HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG               HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG               HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT                 HOST_SEM4_INFO_REG
+
+#define CPE_Q_DEPTH(__n) \
+	(CPE_Q0_DEPTH + (__n) * (CPE_Q1_DEPTH - CPE_Q0_DEPTH))
+#define CPE_Q_PI(__n) \
+	(CPE_Q0_PI + (__n) * (CPE_Q1_PI - CPE_Q0_PI))
+#define CPE_Q_CI(__n) \
+	(CPE_Q0_CI + (__n) * (CPE_Q1_CI - CPE_Q0_CI))
+#define RME_Q_DEPTH(__n) \
+	(RME_Q0_DEPTH + (__n) * (RME_Q1_DEPTH - RME_Q0_DEPTH))
+#define RME_Q_PI(__n) \
+	(RME_Q0_PI + (__n) * (RME_Q1_PI - RME_Q0_PI))
+#define RME_Q_CI(__n) \
+	(RME_Q0_CI + (__n) * (RME_Q1_CI - RME_Q0_CI))
+
+#define CPE_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
+#define CPE_Q_MASK(__q)  ((__q) & 0x3)
+#define RME_Q_MASK(__q)  ((__q) & 0x3)
+
+
+/*
+ * PCI MSI-X vector defines
+ */
+enum {
+    BFA_MSIX_CPE_Q0 = 0,
+    BFA_MSIX_CPE_Q1 = 1,
+    BFA_MSIX_CPE_Q2 = 2,
+    BFA_MSIX_CPE_Q3 = 3,
+    BFA_MSIX_CPE_Q4 = 4,
+    BFA_MSIX_CPE_Q5 = 5,
+    BFA_MSIX_CPE_Q6 = 6,
+    BFA_MSIX_CPE_Q7 = 7,
+    BFA_MSIX_RME_Q0 = 8,
+    BFA_MSIX_RME_Q1 = 9,
+    BFA_MSIX_RME_Q2 = 10,
+    BFA_MSIX_RME_Q3 = 11,
+    BFA_MSIX_RME_Q4 = 12,
+    BFA_MSIX_RME_Q5 = 13,
+    BFA_MSIX_RME_Q6 = 14,
+    BFA_MSIX_RME_Q7 = 15,
+    BFA_MSIX_ERR_EMC = 16,
+    BFA_MSIX_ERR_LPU0 = 17,
+    BFA_MSIX_ERR_LPU1 = 18,
+    BFA_MSIX_ERR_PSS = 19,
+    BFA_MSIX_MBOX_LPU0 = 20,
+    BFA_MSIX_MBOX_LPU1 = 21,
+    BFA_MSIX_CB_MAX = 22,
+};
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0                   0x00000001U
+#define __HFN_INT_CPE_Q1                   0x00000002U
+#define __HFN_INT_CPE_Q2                   0x00000004U
+#define __HFN_INT_CPE_Q3                   0x00000008U
+#define __HFN_INT_CPE_Q4                   0x00000010U
+#define __HFN_INT_CPE_Q5                   0x00000020U
+#define __HFN_INT_CPE_Q6                   0x00000040U
+#define __HFN_INT_CPE_Q7                   0x00000080U
+#define __HFN_INT_RME_Q0                   0x00000100U
+#define __HFN_INT_RME_Q1                   0x00000200U
+#define __HFN_INT_RME_Q2                   0x00000400U
+#define __HFN_INT_RME_Q3                   0x00000800U
+#define __HFN_INT_RME_Q4                   0x00001000U
+#define __HFN_INT_RME_Q5                   0x00002000U
+#define __HFN_INT_RME_Q6                   0x00004000U
+#define __HFN_INT_RME_Q7                   0x00008000U
+#define __HFN_INT_ERR_EMC                  0x00010000U
+#define __HFN_INT_ERR_LPU0                 0x00020000U
+#define __HFN_INT_ERR_LPU1                 0x00040000U
+#define __HFN_INT_ERR_PSS                  0x00080000U
+#define __HFN_INT_MBOX_LPU0                0x00100000U
+#define __HFN_INT_MBOX_LPU1                0x00200000U
+#define __HFN_INT_MBOX1_LPU0               0x00400000U
+#define __HFN_INT_MBOX1_LPU1               0x00800000U
+#define __HFN_INT_CPE_MASK                 0x000000ffU
+#define __HFN_INT_RME_MASK                 0x0000ff00U
+
+
+/*
+ * crossbow memory map.
+ */
+#define PSS_SMEM_PAGE_START	0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff)
+
+/*
+ * End of crossbow memory map
+ */
+
+
+#endif /* __BFI_CBREG_H__ */
+
diff --git a/drivers/scsi/bfa/bfi_ctreg.h b/drivers/scsi/bfa/bfi_ctreg.h
new file mode 100644
index 0000000..62b86a4
--- /dev/null
+++ b/drivers/scsi/bfa/bfi_ctreg.h
@@ -0,0 +1,627 @@
+
+/*
+ * bfi_ctreg.h catapult host block register definitions
+ *
+ * !!! Do not edit. Auto generated. !!!
+ */
+
+#ifndef __BFI_CTREG_H__
+#define __BFI_CTREG_H__
+
+
+#define HOSTFN0_LPU_MBOX0_0		0x00019200
+#define HOSTFN1_LPU_MBOX0_8		0x00019260
+#define LPU_HOSTFN0_MBOX0_0		0x00019280
+#define LPU_HOSTFN1_MBOX0_8		0x000192e0
+#define HOSTFN2_LPU_MBOX0_0		0x00019400
+#define HOSTFN3_LPU_MBOX0_8		0x00019460
+#define LPU_HOSTFN2_MBOX0_0		0x00019480
+#define LPU_HOSTFN3_MBOX0_8		0x000194e0
+#define HOSTFN0_INT_STATUS		0x00014000
+#define __HOSTFN0_HALT_OCCURRED		0x01000000
+#define __HOSTFN0_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN0_INT_STATUS_LVL_SH	20
+#define __HOSTFN0_INT_STATUS_LVL(_v)	((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
+#define __HOSTFN0_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN0_INT_STATUS_P_SH	16
+#define __HOSTFN0_INT_STATUS_P(_v)	((_v) << __HOSTFN0_INT_STATUS_P_SH)
+#define __HOSTFN0_INT_STATUS_F		0x0000ffff
+#define HOSTFN0_INT_MSK			0x00014004
+#define HOST_PAGE_NUM_FN0		0x00014008
+#define __HOST_PAGE_NUM_FN		0x000001ff
+#define HOST_MSIX_ERR_INDEX_FN0		0x0001400c
+#define __MSIX_ERR_INDEX_FN		0x000001ff
+#define HOSTFN1_INT_STATUS		0x00014100
+#define __HOSTFN1_HALT_OCCURRED		0x01000000
+#define __HOSTFN1_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN1_INT_STATUS_LVL_SH	20
+#define __HOSTFN1_INT_STATUS_LVL(_v)	((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
+#define __HOSTFN1_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN1_INT_STATUS_P_SH	16
+#define __HOSTFN1_INT_STATUS_P(_v)	((_v) << __HOSTFN1_INT_STATUS_P_SH)
+#define __HOSTFN1_INT_STATUS_F		0x0000ffff
+#define HOSTFN1_INT_MSK			0x00014104
+#define HOST_PAGE_NUM_FN1		0x00014108
+#define HOST_MSIX_ERR_INDEX_FN1		0x0001410c
+#define APP_PLL_425_CTL_REG		0x00014204
+#define __P_425_PLL_LOCK		0x80000000
+#define __APP_PLL_425_SRAM_USE_100MHZ	0x00100000
+#define __APP_PLL_425_RESET_TIMER_MK	0x000e0000
+#define __APP_PLL_425_RESET_TIMER_SH	17
+#define __APP_PLL_425_RESET_TIMER(_v)	((_v) << __APP_PLL_425_RESET_TIMER_SH)
+#define __APP_PLL_425_LOGIC_SOFT_RESET	0x00010000
+#define __APP_PLL_425_CNTLMT0_1_MK	0x0000c000
+#define __APP_PLL_425_CNTLMT0_1_SH	14
+#define __APP_PLL_425_CNTLMT0_1(_v)	((_v) << __APP_PLL_425_CNTLMT0_1_SH)
+#define __APP_PLL_425_JITLMT0_1_MK	0x00003000
+#define __APP_PLL_425_JITLMT0_1_SH	12
+#define __APP_PLL_425_JITLMT0_1(_v)	((_v) << __APP_PLL_425_JITLMT0_1_SH)
+#define __APP_PLL_425_HREF		0x00000800
+#define __APP_PLL_425_HDIV		0x00000400
+#define __APP_PLL_425_P0_1_MK		0x00000300
+#define __APP_PLL_425_P0_1_SH		8
+#define __APP_PLL_425_P0_1(_v)		((_v) << __APP_PLL_425_P0_1_SH)
+#define __APP_PLL_425_Z0_2_MK		0x000000e0
+#define __APP_PLL_425_Z0_2_SH		5
+#define __APP_PLL_425_Z0_2(_v)		((_v) << __APP_PLL_425_Z0_2_SH)
+#define __APP_PLL_425_RSEL200500	0x00000010
+#define __APP_PLL_425_ENARST		0x00000008
+#define __APP_PLL_425_BYPASS		0x00000004
+#define __APP_PLL_425_LRESETN		0x00000002
+#define __APP_PLL_425_ENABLE		0x00000001
+#define APP_PLL_312_CTL_REG		0x00014208
+#define __P_312_PLL_LOCK		0x80000000
+#define __ENABLE_MAC_AHB_1		0x00800000
+#define __ENABLE_MAC_AHB_0		0x00400000
+#define __ENABLE_MAC_1			0x00200000
+#define __ENABLE_MAC_0			0x00100000
+#define __APP_PLL_312_RESET_TIMER_MK	0x000e0000
+#define __APP_PLL_312_RESET_TIMER_SH	17
+#define __APP_PLL_312_RESET_TIMER(_v)	((_v) << __APP_PLL_312_RESET_TIMER_SH)
+#define __APP_PLL_312_LOGIC_SOFT_RESET	0x00010000
+#define __APP_PLL_312_CNTLMT0_1_MK	0x0000c000
+#define __APP_PLL_312_CNTLMT0_1_SH	14
+#define __APP_PLL_312_CNTLMT0_1(_v)	((_v) << __APP_PLL_312_CNTLMT0_1_SH)
+#define __APP_PLL_312_JITLMT0_1_MK	0x00003000
+#define __APP_PLL_312_JITLMT0_1_SH	12
+#define __APP_PLL_312_JITLMT0_1(_v)	((_v) << __APP_PLL_312_JITLMT0_1_SH)
+#define __APP_PLL_312_HREF		0x00000800
+#define __APP_PLL_312_HDIV		0x00000400
+#define __APP_PLL_312_P0_1_MK		0x00000300
+#define __APP_PLL_312_P0_1_SH		8
+#define __APP_PLL_312_P0_1(_v)		((_v) << __APP_PLL_312_P0_1_SH)
+#define __APP_PLL_312_Z0_2_MK		0x000000e0
+#define __APP_PLL_312_Z0_2_SH		5
+#define __APP_PLL_312_Z0_2(_v)		((_v) << __APP_PLL_312_Z0_2_SH)
+#define __APP_PLL_312_RSEL200500	0x00000010
+#define __APP_PLL_312_ENARST		0x00000008
+#define __APP_PLL_312_BYPASS		0x00000004
+#define __APP_PLL_312_LRESETN		0x00000002
+#define __APP_PLL_312_ENABLE		0x00000001
+#define MBIST_CTL_REG			0x00014220
+#define __EDRAM_BISTR_START		0x00000004
+#define __MBIST_RESET			0x00000002
+#define __MBIST_START			0x00000001
+#define MBIST_STAT_REG			0x00014224
+#define __EDRAM_BISTR_STATUS		0x00000008
+#define __EDRAM_BISTR_DONE		0x00000004
+#define __MEM_BIT_STATUS		0x00000002
+#define __MBIST_DONE			0x00000001
+#define HOST_SEM0_REG			0x00014230
+#define __HOST_SEMAPHORE		0x00000001
+#define HOST_SEM1_REG			0x00014234
+#define HOST_SEM2_REG			0x00014238
+#define HOST_SEM3_REG			0x0001423c
+#define HOST_SEM0_INFO_REG		0x00014240
+#define HOST_SEM1_INFO_REG		0x00014244
+#define HOST_SEM2_INFO_REG		0x00014248
+#define HOST_SEM3_INFO_REG		0x0001424c
+#define ETH_MAC_SER_REG			0x00014288
+#define __APP_EMS_CKBUFAMPIN		0x00000020
+#define __APP_EMS_REFCLKSEL		0x00000010
+#define __APP_EMS_CMLCKSEL		0x00000008
+#define __APP_EMS_REFCKBUFEN2		0x00000004
+#define __APP_EMS_REFCKBUFEN1		0x00000002
+#define __APP_EMS_CHANNEL_SEL		0x00000001
+#define HOSTFN2_INT_STATUS		0x00014300
+#define __HOSTFN2_HALT_OCCURRED		0x01000000
+#define __HOSTFN2_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN2_INT_STATUS_LVL_SH	20
+#define __HOSTFN2_INT_STATUS_LVL(_v)	((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
+#define __HOSTFN2_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN2_INT_STATUS_P_SH	16
+#define __HOSTFN2_INT_STATUS_P(_v)	((_v) << __HOSTFN2_INT_STATUS_P_SH)
+#define __HOSTFN2_INT_STATUS_F		0x0000ffff
+#define HOSTFN2_INT_MSK			0x00014304
+#define HOST_PAGE_NUM_FN2		0x00014308
+#define HOST_MSIX_ERR_INDEX_FN2		0x0001430c
+#define HOSTFN3_INT_STATUS		0x00014400
+#define __HALT_OCCURRED			0x01000000
+#define __HOSTFN3_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN3_INT_STATUS_LVL_SH	20
+#define __HOSTFN3_INT_STATUS_LVL(_v)	((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
+#define __HOSTFN3_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN3_INT_STATUS_P_SH	16
+#define __HOSTFN3_INT_STATUS_P(_v)	((_v) << __HOSTFN3_INT_STATUS_P_SH)
+#define __HOSTFN3_INT_STATUS_F		0x0000ffff
+#define HOSTFN3_INT_MSK			0x00014404
+#define HOST_PAGE_NUM_FN3		0x00014408
+#define HOST_MSIX_ERR_INDEX_FN3		0x0001440c
+#define FNC_ID_REG			0x00014600
+#define __FUNCTION_NUMBER		0x00000007
+#define FNC_PERS_REG			0x00014604
+#define __F3_FUNCTION_ACTIVE		0x80000000
+#define __F3_FUNCTION_MODE		0x40000000
+#define __F3_PORT_MAP_MK		0x30000000
+#define __F3_PORT_MAP_SH		28
+#define __F3_PORT_MAP(_v)		((_v) << __F3_PORT_MAP_SH)
+#define __F3_VM_MODE			0x08000000
+#define __F3_INTX_STATUS_MK		0x07000000
+#define __F3_INTX_STATUS_SH		24
+#define __F3_INTX_STATUS(_v)		((_v) << __F3_INTX_STATUS_SH)
+#define __F2_FUNCTION_ACTIVE		0x00800000
+#define __F2_FUNCTION_MODE		0x00400000
+#define __F2_PORT_MAP_MK		0x00300000
+#define __F2_PORT_MAP_SH		20
+#define __F2_PORT_MAP(_v)		((_v) << __F2_PORT_MAP_SH)
+#define __F2_VM_MODE			0x00080000
+#define __F2_INTX_STATUS_MK		0x00070000
+#define __F2_INTX_STATUS_SH		16
+#define __F2_INTX_STATUS(_v)		((_v) << __F2_INTX_STATUS_SH)
+#define __F1_FUNCTION_ACTIVE		0x00008000
+#define __F1_FUNCTION_MODE		0x00004000
+#define __F1_PORT_MAP_MK		0x00003000
+#define __F1_PORT_MAP_SH		12
+#define __F1_PORT_MAP(_v)		((_v) << __F1_PORT_MAP_SH)
+#define __F1_VM_MODE			0x00000800
+#define __F1_INTX_STATUS_MK		0x00000700
+#define __F1_INTX_STATUS_SH		8
+#define __F1_INTX_STATUS(_v)		((_v) << __F1_INTX_STATUS_SH)
+#define __F0_FUNCTION_ACTIVE		0x00000080
+#define __F0_FUNCTION_MODE		0x00000040
+#define __F0_PORT_MAP_MK		0x00000030
+#define __F0_PORT_MAP_SH		4
+#define __F0_PORT_MAP(_v)		((_v) << __F0_PORT_MAP_SH)
+#define __F0_VM_MODE		0x00000008
+#define __F0_INTX_STATUS		0x00000007
+enum {
+	__F0_INTX_STATUS_MSIX		= 0x0,
+	__F0_INTX_STATUS_INTA		= 0x1,
+	__F0_INTX_STATUS_INTB		= 0x2,
+	__F0_INTX_STATUS_INTC		= 0x3,
+	__F0_INTX_STATUS_INTD		= 0x4,
+};
+#define OP_MODE				0x0001460c
+#define __APP_ETH_CLK_LOWSPEED		0x00000004
+#define __GLOBAL_CORECLK_HALFSPEED	0x00000002
+#define __GLOBAL_FCOE_MODE		0x00000001
+#define HOST_SEM4_REG			0x00014610
+#define HOST_SEM5_REG			0x00014614
+#define HOST_SEM6_REG			0x00014618
+#define HOST_SEM7_REG			0x0001461c
+#define HOST_SEM4_INFO_REG		0x00014620
+#define HOST_SEM5_INFO_REG		0x00014624
+#define HOST_SEM6_INFO_REG		0x00014628
+#define HOST_SEM7_INFO_REG		0x0001462c
+#define HOSTFN0_LPU0_MBOX0_CMD_STAT	0x00019000
+#define __HOSTFN0_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN0_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN0_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN0_LPU1_MBOX0_CMD_STAT	0x00019004
+#define __HOSTFN0_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN0_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN0_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN0_MBOX0_CMD_STAT	0x00019008
+#define __LPU0_HOSTFN0_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN0_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN0_MBOX0_CMD_STAT	0x0001900c
+#define __LPU1_HOSTFN0_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN0_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN1_LPU0_MBOX0_CMD_STAT	0x00019010
+#define __HOSTFN1_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN1_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN1_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN1_LPU1_MBOX0_CMD_STAT	0x00019014
+#define __HOSTFN1_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN1_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN1_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN1_MBOX0_CMD_STAT	0x00019018
+#define __LPU0_HOSTFN1_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN1_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN1_MBOX0_CMD_STAT	0x0001901c
+#define __LPU1_HOSTFN1_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN1_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN2_LPU0_MBOX0_CMD_STAT	0x00019150
+#define __HOSTFN2_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN2_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN2_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN2_LPU1_MBOX0_CMD_STAT	0x00019154
+#define __HOSTFN2_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN2_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN2_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN2_MBOX0_CMD_STAT	0x00019158
+#define __LPU0_HOSTFN2_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN2_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN2_MBOX0_CMD_STAT	0x0001915c
+#define __LPU1_HOSTFN2_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN2_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN3_LPU0_MBOX0_CMD_STAT	0x00019160
+#define __HOSTFN3_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN3_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN3_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN3_LPU1_MBOX0_CMD_STAT	0x00019164
+#define __HOSTFN3_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN3_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN3_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN3_MBOX0_CMD_STAT	0x00019168
+#define __LPU0_HOSTFN3_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN3_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN3_MBOX0_CMD_STAT	0x0001916c
+#define __LPU1_HOSTFN3_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN3_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS	0x00000001
+#define FW_INIT_HALT_P0			0x000191ac
+#define __FW_INIT_HALT_P		0x00000001
+#define FW_INIT_HALT_P1			0x000191bc
+#define CPE_PI_PTR_Q0			0x00038000
+#define __CPE_PI_UNUSED_MK		0xffff0000
+#define __CPE_PI_UNUSED_SH		16
+#define __CPE_PI_UNUSED(_v)		((_v) << __CPE_PI_UNUSED_SH)
+#define __CPE_PI_PTR			0x0000ffff
+#define CPE_PI_PTR_Q1			0x00038040
+#define CPE_CI_PTR_Q0			0x00038004
+#define __CPE_CI_UNUSED_MK		0xffff0000
+#define __CPE_CI_UNUSED_SH		16
+#define __CPE_CI_UNUSED(_v)		((_v) << __CPE_CI_UNUSED_SH)
+#define __CPE_CI_PTR			0x0000ffff
+#define CPE_CI_PTR_Q1			0x00038044
+#define CPE_DEPTH_Q0			0x00038008
+#define __CPE_DEPTH_UNUSED_MK		0xf8000000
+#define __CPE_DEPTH_UNUSED_SH		27
+#define __CPE_DEPTH_UNUSED(_v)		((_v) << __CPE_DEPTH_UNUSED_SH)
+#define __CPE_MSIX_VEC_INDEX_MK		0x07ff0000
+#define __CPE_MSIX_VEC_INDEX_SH		16
+#define __CPE_MSIX_VEC_INDEX(_v)	((_v) << __CPE_MSIX_VEC_INDEX_SH)
+#define __CPE_DEPTH			0x0000ffff
+#define CPE_DEPTH_Q1			0x00038048
+#define CPE_QCTRL_Q0			0x0003800c
+#define __CPE_CTRL_UNUSED30_MK		0xfc000000
+#define __CPE_CTRL_UNUSED30_SH		26
+#define __CPE_CTRL_UNUSED30(_v)		((_v) << __CPE_CTRL_UNUSED30_SH)
+#define __CPE_FUNC_INT_CTRL_MK		0x03000000
+#define __CPE_FUNC_INT_CTRL_SH		24
+#define __CPE_FUNC_INT_CTRL(_v)		((_v) << __CPE_FUNC_INT_CTRL_SH)
+enum {
+	__CPE_FUNC_INT_CTRL_DISABLE		= 0x0,
+	__CPE_FUNC_INT_CTRL_F2NF		= 0x1,
+	__CPE_FUNC_INT_CTRL_3QUART		= 0x2,
+	__CPE_FUNC_INT_CTRL_HALF		= 0x3,
+};
+#define __CPE_CTRL_UNUSED20_MK		0x00f00000
+#define __CPE_CTRL_UNUSED20_SH		20
+#define __CPE_CTRL_UNUSED20(_v)		((_v) << __CPE_CTRL_UNUSED20_SH)
+#define __CPE_SCI_TH_MK			0x000f0000
+#define __CPE_SCI_TH_SH			16
+#define __CPE_SCI_TH(_v)		((_v) << __CPE_SCI_TH_SH)
+#define __CPE_CTRL_UNUSED10_MK		0x0000c000
+#define __CPE_CTRL_UNUSED10_SH		14
+#define __CPE_CTRL_UNUSED10(_v)		((_v) << __CPE_CTRL_UNUSED10_SH)
+#define __CPE_ACK_PENDING		0x00002000
+#define __CPE_CTRL_UNUSED40_MK		0x00001c00
+#define __CPE_CTRL_UNUSED40_SH		10
+#define __CPE_CTRL_UNUSED40(_v)		((_v) << __CPE_CTRL_UNUSED40_SH)
+#define __CPE_PCIEID_MK			0x00000300
+#define __CPE_PCIEID_SH			8
+#define __CPE_PCIEID(_v)		((_v) << __CPE_PCIEID_SH)
+#define __CPE_CTRL_UNUSED00_MK		0x000000fe
+#define __CPE_CTRL_UNUSED00_SH		1
+#define __CPE_CTRL_UNUSED00(_v)		((_v) << __CPE_CTRL_UNUSED00_SH)
+#define __CPE_ESIZE			0x00000001
+#define CPE_QCTRL_Q1			0x0003804c
+#define __CPE_CTRL_UNUSED31_MK		0xfc000000
+#define __CPE_CTRL_UNUSED31_SH		26
+#define __CPE_CTRL_UNUSED31(_v)		((_v) << __CPE_CTRL_UNUSED31_SH)
+#define __CPE_CTRL_UNUSED21_MK		0x00f00000
+#define __CPE_CTRL_UNUSED21_SH		20
+#define __CPE_CTRL_UNUSED21(_v)		((_v) << __CPE_CTRL_UNUSED21_SH)
+#define __CPE_CTRL_UNUSED11_MK		0x0000c000
+#define __CPE_CTRL_UNUSED11_SH		14
+#define __CPE_CTRL_UNUSED11(_v)		((_v) << __CPE_CTRL_UNUSED11_SH)
+#define __CPE_CTRL_UNUSED41_MK		0x00001c00
+#define __CPE_CTRL_UNUSED41_SH		10
+#define __CPE_CTRL_UNUSED41(_v)		((_v) << __CPE_CTRL_UNUSED41_SH)
+#define __CPE_CTRL_UNUSED01_MK		0x000000fe
+#define __CPE_CTRL_UNUSED01_SH		1
+#define __CPE_CTRL_UNUSED01(_v)		((_v) << __CPE_CTRL_UNUSED01_SH)
+#define RME_PI_PTR_Q0			0x00038020
+#define __LATENCY_TIME_STAMP_MK		0xffff0000
+#define __LATENCY_TIME_STAMP_SH		16
+#define __LATENCY_TIME_STAMP(_v)	((_v) << __LATENCY_TIME_STAMP_SH)
+#define __RME_PI_PTR			0x0000ffff
+#define RME_PI_PTR_Q1			0x00038060
+#define RME_CI_PTR_Q0			0x00038024
+#define __DELAY_TIME_STAMP_MK		0xffff0000
+#define __DELAY_TIME_STAMP_SH		16
+#define __DELAY_TIME_STAMP(_v)		((_v) << __DELAY_TIME_STAMP_SH)
+#define __RME_CI_PTR			0x0000ffff
+#define RME_CI_PTR_Q1			0x00038064
+#define RME_DEPTH_Q0			0x00038028
+#define __RME_DEPTH_UNUSED_MK		0xf8000000
+#define __RME_DEPTH_UNUSED_SH		27
+#define __RME_DEPTH_UNUSED(_v)		((_v) << __RME_DEPTH_UNUSED_SH)
+#define __RME_MSIX_VEC_INDEX_MK		0x07ff0000
+#define __RME_MSIX_VEC_INDEX_SH		16
+#define __RME_MSIX_VEC_INDEX(_v)	((_v) << __RME_MSIX_VEC_INDEX_SH)
+#define __RME_DEPTH			0x0000ffff
+#define RME_DEPTH_Q1			0x00038068
+#define RME_QCTRL_Q0			0x0003802c
+#define __RME_INT_LATENCY_TIMER_MK	0xff000000
+#define __RME_INT_LATENCY_TIMER_SH	24
+#define __RME_INT_LATENCY_TIMER(_v)	((_v) << __RME_INT_LATENCY_TIMER_SH)
+#define __RME_INT_DELAY_TIMER_MK	0x00ff0000
+#define __RME_INT_DELAY_TIMER_SH	16
+#define __RME_INT_DELAY_TIMER(_v)	((_v) << __RME_INT_DELAY_TIMER_SH)
+#define __RME_INT_DELAY_DISABLE		0x00008000
+#define __RME_DLY_DELAY_DISABLE		0x00004000
+#define __RME_ACK_PENDING		0x00002000
+#define __RME_FULL_INTERRUPT_DISABLE	0x00001000
+#define __RME_CTRL_UNUSED10_MK		0x00000c00
+#define __RME_CTRL_UNUSED10_SH		10
+#define __RME_CTRL_UNUSED10(_v)		((_v) << __RME_CTRL_UNUSED10_SH)
+#define __RME_PCIEID_MK			0x00000300
+#define __RME_PCIEID_SH			8
+#define __RME_PCIEID(_v)		((_v) << __RME_PCIEID_SH)
+#define __RME_CTRL_UNUSED00_MK		0x000000fe
+#define __RME_CTRL_UNUSED00_SH		1
+#define __RME_CTRL_UNUSED00(_v)		((_v) << __RME_CTRL_UNUSED00_SH)
+#define __RME_ESIZE			0x00000001
+#define RME_QCTRL_Q1			0x0003806c
+#define __RME_CTRL_UNUSED11_MK		0x00000c00
+#define __RME_CTRL_UNUSED11_SH		10
+#define __RME_CTRL_UNUSED11(_v)		((_v) << __RME_CTRL_UNUSED11_SH)
+#define __RME_CTRL_UNUSED01_MK		0x000000fe
+#define __RME_CTRL_UNUSED01_SH		1
+#define __RME_CTRL_UNUSED01(_v)		((_v) << __RME_CTRL_UNUSED01_SH)
+#define PSS_CTL_REG			0x00018800
+#define __PSS_I2C_CLK_DIV_MK		0x007f0000
+#define __PSS_I2C_CLK_DIV_SH		16
+#define __PSS_I2C_CLK_DIV(_v)		((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE		0x00001000
+#define __PSS_LMEM_RESET		0x00000200
+#define __PSS_LMEM_INIT_EN		0x00000100
+#define __PSS_LPU1_RESET		0x00000002
+#define __PSS_LPU0_RESET		0x00000001
+#define PSS_ERR_STATUS_REG		0x00018810
+#define __PSS_LPU1_TCM_READ_ERR		0x00200000
+#define __PSS_LPU0_TCM_READ_ERR		0x00100000
+#define __PSS_LMEM5_CORR_ERR		0x00080000
+#define __PSS_LMEM4_CORR_ERR		0x00040000
+#define __PSS_LMEM3_CORR_ERR		0x00020000
+#define __PSS_LMEM2_CORR_ERR		0x00010000
+#define __PSS_LMEM1_CORR_ERR		0x00008000
+#define __PSS_LMEM0_CORR_ERR		0x00004000
+#define __PSS_LMEM5_UNCORR_ERR		0x00002000
+#define __PSS_LMEM4_UNCORR_ERR		0x00001000
+#define __PSS_LMEM3_UNCORR_ERR		0x00000800
+#define __PSS_LMEM2_UNCORR_ERR		0x00000400
+#define __PSS_LMEM1_UNCORR_ERR		0x00000200
+#define __PSS_LMEM0_UNCORR_ERR		0x00000100
+#define __PSS_BAL_PERR			0x00000080
+#define __PSS_DIP_IF_ERR		0x00000040
+#define __PSS_IOH_IF_ERR		0x00000020
+#define __PSS_TDS_IF_ERR		0x00000010
+#define __PSS_RDS_IF_ERR		0x00000008
+#define __PSS_SGM_IF_ERR		0x00000004
+#define __PSS_LPU1_RAM_ERR		0x00000002
+#define __PSS_LPU0_RAM_ERR		0x00000001
+#define ERR_SET_REG			0x00018818
+#define __PSS_ERR_STATUS_SET		0x003fffff
+#define PMM_1T_RESET_REG_P0		0x0002381c
+#define __PMM_1T_RESET_P		0x00000001
+#define PMM_1T_RESET_REG_P1		0x00023c1c
+#define HQM_QSET0_RXQ_DRBL_P0		0x00038000
+#define __RXQ0_ADD_VECTORS_P		0x80000000
+#define __RXQ0_STOP_P			0x40000000
+#define __RXQ0_PRD_PTR_P		0x0000ffff
+#define HQM_QSET1_RXQ_DRBL_P0		0x00038080
+#define __RXQ1_ADD_VECTORS_P		0x80000000
+#define __RXQ1_STOP_P			0x40000000
+#define __RXQ1_PRD_PTR_P		0x0000ffff
+#define HQM_QSET0_RXQ_DRBL_P1		0x0003c000
+#define HQM_QSET1_RXQ_DRBL_P1		0x0003c080
+#define HQM_QSET0_TXQ_DRBL_P0		0x00038020
+#define __TXQ0_ADD_VECTORS_P		0x80000000
+#define __TXQ0_STOP_P			0x40000000
+#define __TXQ0_PRD_PTR_P		0x0000ffff
+#define HQM_QSET1_TXQ_DRBL_P0		0x000380a0
+#define __TXQ1_ADD_VECTORS_P		0x80000000
+#define __TXQ1_STOP_P			0x40000000
+#define __TXQ1_PRD_PTR_P		0x0000ffff
+#define HQM_QSET0_TXQ_DRBL_P1		0x0003c020
+#define HQM_QSET1_TXQ_DRBL_P1		0x0003c0a0
+#define HQM_QSET0_IB_DRBL_1_P0		0x00038040
+#define __IB1_0_ACK_P			0x80000000
+#define __IB1_0_DISABLE_P		0x40000000
+#define __IB1_0_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB1_0_COALESCING_CFG_P_SH	16
+#define __IB1_0_COALESCING_CFG_P(_v)	((_v) << __IB1_0_COALESCING_CFG_P_SH)
+#define __IB1_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET1_IB_DRBL_1_P0		0x000380c0
+#define __IB1_1_ACK_P			0x80000000
+#define __IB1_1_DISABLE_P		0x40000000
+#define __IB1_1_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB1_1_COALESCING_CFG_P_SH	16
+#define __IB1_1_COALESCING_CFG_P(_v)	((_v) << __IB1_1_COALESCING_CFG_P_SH)
+#define __IB1_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET0_IB_DRBL_1_P1		0x0003c040
+#define HQM_QSET1_IB_DRBL_1_P1		0x0003c0c0
+#define HQM_QSET0_IB_DRBL_2_P0		0x00038060
+#define __IB2_0_ACK_P			0x80000000
+#define __IB2_0_DISABLE_P		0x40000000
+#define __IB2_0_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB2_0_COALESCING_CFG_P_SH	16
+#define __IB2_0_COALESCING_CFG_P(_v)	((_v) << __IB2_0_COALESCING_CFG_P_SH)
+#define __IB2_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET1_IB_DRBL_2_P0		0x000380e0
+#define __IB2_1_ACK_P			0x80000000
+#define __IB2_1_DISABLE_P		0x40000000
+#define __IB2_1_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB2_1_COALESCING_CFG_P_SH	16
+#define __IB2_1_COALESCING_CFG_P(_v)	((_v) << __IB2_1_COALESCING_CFG_P_SH)
+#define __IB2_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET0_IB_DRBL_2_P1		0x0003c060
+#define HQM_QSET1_IB_DRBL_2_P1		0x0003c0e0
+
+
+/*
+ * These definitions are either in error/missing in spec. Its auto-generated
+ * from hard coded values in regparse.pl.
+ */
+#define __EMPHPOST_AT_4G_MK_FIX		0x0000001c
+#define __EMPHPOST_AT_4G_SH_FIX		0x00000002
+#define __EMPHPRE_AT_4G_FIX		0x00000003
+#define __SFP_TXRATE_EN_FIX		0x00000100
+#define __SFP_RXRATE_EN_FIX		0x00000080
+
+
+/*
+ * These register definitions are auto-generated from hard coded values
+ * in regparse.pl.
+ */
+
+
+/*
+ * These register mapping definitions are auto-generated from mapping tables
+ * in regparse.pl.
+ */
+#define BFA_IOC0_HBEAT_REG		HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG		HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG		HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG		HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT		 HOST_SEM4_INFO_REG
+
+#define CPE_DEPTH_Q(__n) \
+	(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
+#define CPE_QCTRL_Q(__n) \
+	(CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
+#define CPE_PI_PTR_Q(__n) \
+	(CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
+#define CPE_CI_PTR_Q(__n) \
+	(CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
+#define RME_DEPTH_Q(__n) \
+	(RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
+#define RME_QCTRL_Q(__n) \
+	(RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
+#define RME_PI_PTR_Q(__n) \
+	(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
+#define RME_CI_PTR_Q(__n) \
+	(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
+#define HQM_QSET_RXQ_DRBL_P0(__n) (HQM_QSET0_RXQ_DRBL_P0 + (__n) \
+	* (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
+#define HQM_QSET_TXQ_DRBL_P0(__n) (HQM_QSET0_TXQ_DRBL_P0 + (__n) \
+	* (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
+#define HQM_QSET_IB_DRBL_1_P0(__n) (HQM_QSET0_IB_DRBL_1_P0 + (__n) \
+	* (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
+#define HQM_QSET_IB_DRBL_2_P0(__n) (HQM_QSET0_IB_DRBL_2_P0 + (__n) \
+	* (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
+#define HQM_QSET_RXQ_DRBL_P1(__n) (HQM_QSET0_RXQ_DRBL_P1 + (__n) \
+	* (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
+#define HQM_QSET_TXQ_DRBL_P1(__n) (HQM_QSET0_TXQ_DRBL_P1 + (__n) \
+	* (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
+#define HQM_QSET_IB_DRBL_1_P1(__n) (HQM_QSET0_IB_DRBL_1_P1 + (__n) \
+	* (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
+#define HQM_QSET_IB_DRBL_2_P1(__n) (HQM_QSET0_IB_DRBL_2_P1 + (__n) \
+	* (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
+
+#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+#define CPE_Q_MASK(__q) ((__q) & 0x3)
+#define RME_Q_MASK(__q) ((__q) & 0x3)
+
+
+/*
+ * PCI MSI-X vector defines
+ */
+enum {
+	BFA_MSIX_CPE_Q0 = 0,
+	BFA_MSIX_CPE_Q1 = 1,
+	BFA_MSIX_CPE_Q2 = 2,
+	BFA_MSIX_CPE_Q3 = 3,
+	BFA_MSIX_RME_Q0 = 4,
+	BFA_MSIX_RME_Q1 = 5,
+	BFA_MSIX_RME_Q2 = 6,
+	BFA_MSIX_RME_Q3 = 7,
+	BFA_MSIX_LPU_ERR = 8,
+	BFA_MSIX_CT_MAX = 9,
+};
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0		0x00000001U
+#define __HFN_INT_CPE_Q1		0x00000002U
+#define __HFN_INT_CPE_Q2		0x00000004U
+#define __HFN_INT_CPE_Q3		0x00000008U
+#define __HFN_INT_CPE_Q4		0x00000010U
+#define __HFN_INT_CPE_Q5		0x00000020U
+#define __HFN_INT_CPE_Q6		0x00000040U
+#define __HFN_INT_CPE_Q7		0x00000080U
+#define __HFN_INT_RME_Q0		0x00000100U
+#define __HFN_INT_RME_Q1		0x00000200U
+#define __HFN_INT_RME_Q2		0x00000400U
+#define __HFN_INT_RME_Q3		0x00000800U
+#define __HFN_INT_RME_Q4		0x00001000U
+#define __HFN_INT_RME_Q5		0x00002000U
+#define __HFN_INT_RME_Q6		0x00004000U
+#define __HFN_INT_RME_Q7		0x00008000U
+#define __HFN_INT_ERR_EMC		0x00010000U
+#define __HFN_INT_ERR_LPU0		0x00020000U
+#define __HFN_INT_ERR_LPU1		0x00040000U
+#define __HFN_INT_ERR_PSS		0x00080000U
+#define __HFN_INT_MBOX_LPU0		0x00100000U
+#define __HFN_INT_MBOX_LPU1		0x00200000U
+#define __HFN_INT_MBOX1_LPU0		0x00400000U
+#define __HFN_INT_MBOX1_LPU1		0x00800000U
+#define __HFN_INT_LL_HALT		0x01000000U
+#define __HFN_INT_CPE_MASK		0x000000ffU
+#define __HFN_INT_RME_MASK		0x0000ff00U
+
+
+/*
+ * catapult memory map.
+ */
+#define LL_PGN_HQM0		0x0096
+#define LL_PGN_HQM1		0x0097
+#define PSS_SMEM_PAGE_START	0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff)
+
+/*
+ * End of catapult memory map
+ */
+
+
+#endif /* __BFI_CTREG_H__ */
diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h
new file mode 100644
index 0000000..69ac85f
--- /dev/null
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -0,0 +1,765 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_MS_H__
+#define __BFI_MS_H__
+
+#include "bfi.h"
+#include "bfa_fc.h"
+#include "bfa_defs_svc.h"
+
+#pragma pack(1)
+
+enum bfi_iocfc_h2i_msgs {
+	BFI_IOCFC_H2I_CFG_REQ		= 1,
+	BFI_IOCFC_H2I_SET_INTR_REQ	= 2,
+	BFI_IOCFC_H2I_UPDATEQ_REQ	= 3,
+};
+
+enum bfi_iocfc_i2h_msgs {
+	BFI_IOCFC_I2H_CFG_REPLY		= BFA_I2HM(1),
+	BFI_IOCFC_I2H_UPDATEQ_RSP	= BFA_I2HM(3),
+};
+
+struct bfi_iocfc_cfg_s {
+	u8	num_cqs;	/*  Number of CQs to be used	*/
+	u8	 sense_buf_len;	/*  SCSI sense length	    */
+	u16	rsvd_1;
+	u32	endian_sig;	/*  endian signature of host     */
+
+	/**
+	 * Request and response circular queue base addresses, size and
+	 * shadow index pointers.
+	 */
+	union bfi_addr_u  req_cq_ba[BFI_IOC_MAX_CQS];
+	union bfi_addr_u  req_shadow_ci[BFI_IOC_MAX_CQS];
+	u16    req_cq_elems[BFI_IOC_MAX_CQS];
+	union bfi_addr_u  rsp_cq_ba[BFI_IOC_MAX_CQS];
+	union bfi_addr_u  rsp_shadow_pi[BFI_IOC_MAX_CQS];
+	u16    rsp_cq_elems[BFI_IOC_MAX_CQS];
+
+	union bfi_addr_u  stats_addr;	/*  DMA-able address for stats	  */
+	union bfi_addr_u  cfgrsp_addr;	/*  config response dma address  */
+	union bfi_addr_u  ioim_snsbase;  /*  IO sense buffer base address */
+	struct bfa_iocfc_intr_attr_s intr_attr; /*  IOC interrupt attributes */
+};
+
+/**
+ * Boot target wwn information for this port. This contains either the stored
+ * or discovered boot target port wwns for the port.
+ */
+struct bfi_iocfc_bootwwns {
+	wwn_t		wwn[BFA_BOOT_BOOTLUN_MAX];
+	u8		nwwns;
+	u8		rsvd[7];
+};
+
+struct bfi_iocfc_cfgrsp_s {
+	struct bfa_iocfc_fwcfg_s	fwcfg;
+	struct bfa_iocfc_intr_attr_s	intr_attr;
+	struct bfi_iocfc_bootwwns	bootwwns;
+	struct bfi_pbc_s		pbc_cfg;
+};
+
+/**
+ * BFI_IOCFC_H2I_CFG_REQ message
+ */
+struct bfi_iocfc_cfg_req_s {
+	struct bfi_mhdr_s      mh;
+	union bfi_addr_u      ioc_cfg_dma_addr;
+};
+
+
+/**
+ * BFI_IOCFC_I2H_CFG_REPLY message
+ */
+struct bfi_iocfc_cfg_reply_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header	  */
+	u8	 cfg_success;	/*  cfg reply status	   */
+	u8	 lpu_bm;		/*  LPUs assigned for this IOC */
+	u8	 rsvd[2];
+};
+
+
+/**
+ * BFI_IOCFC_H2I_SET_INTR_REQ message
+ */
+struct bfi_iocfc_set_intr_req_s {
+	struct bfi_mhdr_s mh;		/*  common msg header		*/
+	u8		coalesce;	/*  enable intr coalescing	*/
+	u8		rsvd[3];
+	u16	delay;		/*  delay timer 0..1125us	*/
+	u16	latency;	/*  latency timer 0..225us	*/
+};
+
+
+/**
+ * BFI_IOCFC_H2I_UPDATEQ_REQ message
+ */
+struct bfi_iocfc_updateq_req_s {
+	struct bfi_mhdr_s mh;		/*  common msg header		*/
+	u32 reqq_ba;		/*  reqq base addr		*/
+	u32 rspq_ba;		/*  rspq base addr		*/
+	u32 reqq_sci;		/*  reqq shadow ci		*/
+	u32 rspq_spi;		/*  rspq shadow pi		*/
+};
+
+
+/**
+ * BFI_IOCFC_I2H_UPDATEQ_RSP message
+ */
+struct bfi_iocfc_updateq_rsp_s {
+	struct bfi_mhdr_s mh;		/*  common msg header	*/
+	u8	status;			/*  updateq  status	*/
+	u8	rsvd[3];
+};
+
+
+/**
+ * H2I Messages
+ */
+union bfi_iocfc_h2i_msg_u {
+	struct bfi_mhdr_s		mh;
+	struct bfi_iocfc_cfg_req_s	cfg_req;
+	struct bfi_iocfc_updateq_req_s updateq_req;
+	u32 mboxmsg[BFI_IOC_MSGSZ];
+};
+
+
+/**
+ * I2H Messages
+ */
+union bfi_iocfc_i2h_msg_u {
+	struct bfi_mhdr_s		mh;
+	struct bfi_iocfc_cfg_reply_s	cfg_reply;
+	struct bfi_iocfc_updateq_rsp_s updateq_rsp;
+	u32 mboxmsg[BFI_IOC_MSGSZ];
+};
+
+
+enum bfi_fcport_h2i {
+	BFI_FCPORT_H2I_ENABLE_REQ		= (1),
+	BFI_FCPORT_H2I_DISABLE_REQ		= (2),
+	BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ	= (3),
+	BFI_FCPORT_H2I_STATS_GET_REQ		= (4),
+	BFI_FCPORT_H2I_STATS_CLEAR_REQ		= (5),
+};
+
+
+enum bfi_fcport_i2h {
+	BFI_FCPORT_I2H_ENABLE_RSP		= BFA_I2HM(1),
+	BFI_FCPORT_I2H_DISABLE_RSP		= BFA_I2HM(2),
+	BFI_FCPORT_I2H_SET_SVC_PARAMS_RSP	= BFA_I2HM(3),
+	BFI_FCPORT_I2H_STATS_GET_RSP		= BFA_I2HM(4),
+	BFI_FCPORT_I2H_STATS_CLEAR_RSP		= BFA_I2HM(5),
+	BFI_FCPORT_I2H_EVENT			= BFA_I2HM(6),
+	BFI_FCPORT_I2H_TRUNK_SCN		= BFA_I2HM(7),
+	BFI_FCPORT_I2H_ENABLE_AEN		= BFA_I2HM(8),
+	BFI_FCPORT_I2H_DISABLE_AEN		= BFA_I2HM(9),
+};
+
+
+/**
+ * Generic REQ type
+ */
+struct bfi_fcport_req_s {
+	struct bfi_mhdr_s  mh;		/*  msg header			    */
+	u32	   msgtag;	/*  msgtag for reply		    */
+};
+
+/**
+ * Generic RSP type
+ */
+struct bfi_fcport_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		    */
+	u8		   status;	/*  port enable status		    */
+	u8		   rsvd[3];
+	u32	   msgtag;	/*  msgtag for reply		    */
+};
+
+/**
+ * BFI_FCPORT_H2I_ENABLE_REQ
+ */
+struct bfi_fcport_enable_req_s {
+	struct bfi_mhdr_s  mh;		/*  msg header			    */
+	u32	   rsvd1;
+	wwn_t		   nwwn;	/*  node wwn of physical port	    */
+	wwn_t		   pwwn;	/*  port wwn of physical port	    */
+	struct bfa_port_cfg_s port_cfg; /*  port configuration	    */
+	union bfi_addr_u   stats_dma_addr; /*  DMA address for stats	    */
+	u32	   msgtag;	/*  msgtag for reply		    */
+	u32	   rsvd2;
+};
+
+/**
+ * BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ
+ */
+struct bfi_fcport_set_svc_params_req_s {
+	struct bfi_mhdr_s  mh;		/*  msg header */
+	u16	   tx_bbcredit;	/*  Tx credits */
+	u16	   rsvd;
+};
+
+/**
+ * BFI_FCPORT_I2H_EVENT
+ */
+struct bfi_fcport_event_s {
+	struct bfi_mhdr_s	mh;	/*  common msg header */
+	struct bfa_port_link_s	link_state;
+};
+
+/**
+ * BFI_FCPORT_I2H_TRUNK_SCN
+ */
+struct bfi_fcport_trunk_link_s {
+	wwn_t			trunk_wwn;
+	u8			fctl;		/* bfa_trunk_link_fctl_t */
+	u8			state;		/* bfa_trunk_link_state_t */
+	u8			speed;		/* bfa_port_speed_t */
+	u8			rsvd;
+	u32		deskew;
+};
+
+#define BFI_FCPORT_MAX_LINKS	2
+struct bfi_fcport_trunk_scn_s {
+	struct bfi_mhdr_s	mh;
+	u8			trunk_state;	/* bfa_trunk_state_t */
+	u8			trunk_speed;	/* bfa_port_speed_t */
+	u8			rsvd_a[2];
+	struct bfi_fcport_trunk_link_s tlink[BFI_FCPORT_MAX_LINKS];
+};
+
+/**
+ * fcport H2I message
+ */
+union bfi_fcport_h2i_msg_u {
+	struct bfi_mhdr_s			*mhdr;
+	struct bfi_fcport_enable_req_s		*penable;
+	struct bfi_fcport_req_s			*pdisable;
+	struct bfi_fcport_set_svc_params_req_s	*psetsvcparams;
+	struct bfi_fcport_req_s			*pstatsget;
+	struct bfi_fcport_req_s			*pstatsclear;
+};
+
+/**
+ * fcport I2H message
+ */
+union bfi_fcport_i2h_msg_u {
+	struct bfi_msg_s			*msg;
+	struct bfi_fcport_rsp_s			*penable_rsp;
+	struct bfi_fcport_rsp_s			*pdisable_rsp;
+	struct bfi_fcport_rsp_s			*psetsvcparams_rsp;
+	struct bfi_fcport_rsp_s			*pstatsget_rsp;
+	struct bfi_fcport_rsp_s			*pstatsclear_rsp;
+	struct bfi_fcport_event_s		*event;
+	struct bfi_fcport_trunk_scn_s		*trunk_scn;
+};
+
+enum bfi_fcxp_h2i {
+	BFI_FCXP_H2I_SEND_REQ = 1,
+};
+
+enum bfi_fcxp_i2h {
+	BFI_FCXP_I2H_SEND_RSP = BFA_I2HM(1),
+};
+
+#define BFA_FCXP_MAX_SGES	2
+
+/**
+ * FCXP send request structure
+ */
+struct bfi_fcxp_send_req_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		    */
+	u16	fcxp_tag;	/*  driver request tag		    */
+	u16	max_frmsz;	/*  max send frame size	    */
+	u16	vf_id;		/*  vsan tag if applicable	    */
+	u16	rport_fw_hndl;	/*  FW Handle for the remote port  */
+	u8	 class;		/*  FC class used for req/rsp	    */
+	u8	 rsp_timeout;	/*  timeout in secs, 0-no response */
+	u8	 cts;		/*  continue sequence		    */
+	u8	 lp_tag;	/*  lport tag			    */
+	struct fchs_s	fchs;	/*  request FC header structure    */
+	u32	req_len;	/*  request payload length	    */
+	u32	rsp_maxlen;	/*  max response length expected   */
+	struct bfi_sge_s   req_sge[BFA_FCXP_MAX_SGES];	/*  request buf    */
+	struct bfi_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];	/*  response buf   */
+};
+
+/**
+ * FCXP send response structure
+ */
+struct bfi_fcxp_send_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		    */
+	u16	fcxp_tag;	/*  send request tag		    */
+	u8	 req_status;	/*  request status		    */
+	u8	 rsvd;
+	u32	rsp_len;	/*  actual response length	    */
+	u32	residue_len;	/*  residual response length	    */
+	struct fchs_s	fchs;	/*  response FC header structure   */
+};
+
+enum bfi_uf_h2i {
+	BFI_UF_H2I_BUF_POST = 1,
+};
+
+enum bfi_uf_i2h {
+	BFI_UF_I2H_FRM_RCVD = BFA_I2HM(1),
+};
+
+#define BFA_UF_MAX_SGES	2
+
+struct bfi_uf_buf_post_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		*/
+	u16	buf_tag;	/*  buffer tag			*/
+	u16	buf_len;	/*  total buffer length	*/
+	struct bfi_sge_s   sge[BFA_UF_MAX_SGES]; /*  buffer DMA SGEs	*/
+};
+
+struct bfi_uf_frm_rcvd_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		*/
+	u16	buf_tag;	/*  buffer tag			*/
+	u16	rsvd;
+	u16	frm_len;	/*  received frame length	*/
+	u16	xfr_len;	/*  tranferred length		*/
+};
+
+enum bfi_lps_h2i_msgs {
+	BFI_LPS_H2I_LOGIN_REQ	= 1,
+	BFI_LPS_H2I_LOGOUT_REQ	= 2,
+};
+
+enum bfi_lps_i2h_msgs {
+	BFI_LPS_H2I_LOGIN_RSP	= BFA_I2HM(1),
+	BFI_LPS_H2I_LOGOUT_RSP	= BFA_I2HM(2),
+	BFI_LPS_H2I_CVL_EVENT	= BFA_I2HM(3),
+};
+
+struct bfi_lps_login_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		lp_tag;
+	u8		alpa;
+	u16	pdu_size;
+	wwn_t		pwwn;
+	wwn_t		nwwn;
+	u8		fdisc;
+	u8		auth_en;
+	u8		rsvd[2];
+};
+
+struct bfi_lps_login_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		lp_tag;
+	u8		status;
+	u8		lsrjt_rsn;
+	u8		lsrjt_expl;
+	wwn_t		port_name;
+	wwn_t		node_name;
+	u16	bb_credit;
+	u8		f_port;
+	u8		npiv_en;
+	u32	lp_pid:24;
+	u32	auth_req:8;
+	mac_t		lp_mac;
+	mac_t		fcf_mac;
+	u8		ext_status;
+	u8		brcd_switch;	/*  attached peer is brcd switch */
+};
+
+struct bfi_lps_logout_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		lp_tag;
+	u8		rsvd[3];
+	wwn_t		port_name;
+};
+
+struct bfi_lps_logout_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		lp_tag;
+	u8		status;
+	u8		rsvd[2];
+};
+
+struct bfi_lps_cvl_event_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		lp_tag;
+	u8		rsvd[3];
+};
+
+union bfi_lps_h2i_msg_u {
+	struct bfi_mhdr_s		*msg;
+	struct bfi_lps_login_req_s	*login_req;
+	struct bfi_lps_logout_req_s	*logout_req;
+};
+
+union bfi_lps_i2h_msg_u {
+	struct bfi_msg_s		*msg;
+	struct bfi_lps_login_rsp_s	*login_rsp;
+	struct bfi_lps_logout_rsp_s	*logout_rsp;
+	struct bfi_lps_cvl_event_s	*cvl_event;
+};
+
+enum bfi_rport_h2i_msgs {
+	BFI_RPORT_H2I_CREATE_REQ = 1,
+	BFI_RPORT_H2I_DELETE_REQ = 2,
+	BFI_RPORT_H2I_SET_SPEED_REQ  = 3,
+};
+
+enum bfi_rport_i2h_msgs {
+	BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1),
+	BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2),
+	BFI_RPORT_I2H_QOS_SCN    = BFA_I2HM(3),
+};
+
+struct bfi_rport_create_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u16	bfa_handle;	/*  host rport handle		*/
+	u16	max_frmsz;	/*  max rcv pdu size		*/
+	u32	pid:24,	/*  remote port ID		*/
+		lp_tag:8;	/*  local port tag		*/
+	u32	local_pid:24,	/*  local port ID		*/
+		cisc:8;
+	u8	fc_class;	/*  supported FC classes	*/
+	u8	vf_en;		/*  virtual fabric enable	*/
+	u16	vf_id;		/*  virtual fabric ID		*/
+};
+
+struct bfi_rport_create_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		status;		/*  rport creation status	*/
+	u8		rsvd[3];
+	u16	bfa_handle;	/*  host rport handle		*/
+	u16	fw_handle;	/*  firmware rport handle	*/
+	struct bfa_rport_qos_attr_s qos_attr;  /* QoS Attributes */
+};
+
+struct bfa_rport_speed_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u16	fw_handle;	/*  firmware rport handle	*/
+	u8		speed;		/*  rport's speed via RPSC	*/
+	u8		rsvd;
+};
+
+struct bfi_rport_delete_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u16	fw_handle;	/*  firmware rport handle	*/
+	u16	rsvd;
+};
+
+struct bfi_rport_delete_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u16	bfa_handle;	/*  host rport handle		*/
+	u8		status;		/*  rport deletion status	*/
+	u8		rsvd;
+};
+
+struct bfi_rport_qos_scn_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u16	bfa_handle;	/*  host rport handle		*/
+	u16	rsvd;
+	struct bfa_rport_qos_attr_s old_qos_attr;  /* Old QoS Attributes */
+	struct bfa_rport_qos_attr_s new_qos_attr;  /* New QoS Attributes */
+};
+
+union bfi_rport_h2i_msg_u {
+	struct bfi_msg_s		*msg;
+	struct bfi_rport_create_req_s	*create_req;
+	struct bfi_rport_delete_req_s	*delete_req;
+	struct bfi_rport_speed_req_s	*speed_req;
+};
+
+union bfi_rport_i2h_msg_u {
+	struct bfi_msg_s		*msg;
+	struct bfi_rport_create_rsp_s	*create_rsp;
+	struct bfi_rport_delete_rsp_s	*delete_rsp;
+	struct bfi_rport_qos_scn_s	*qos_scn_evt;
+};
+
+/*
+ * Initiator mode I-T nexus interface defines.
+ */
+
+enum bfi_itnim_h2i {
+	BFI_ITNIM_H2I_CREATE_REQ = 1,	/*  i-t nexus creation */
+	BFI_ITNIM_H2I_DELETE_REQ = 2,	/*  i-t nexus deletion */
+};
+
+enum bfi_itnim_i2h {
+	BFI_ITNIM_I2H_CREATE_RSP = BFA_I2HM(1),
+	BFI_ITNIM_I2H_DELETE_RSP = BFA_I2HM(2),
+	BFI_ITNIM_I2H_SLER_EVENT = BFA_I2HM(3),
+};
+
+struct bfi_itnim_create_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		 */
+	u16	fw_handle;	/*  f/w handle for itnim	 */
+	u8	class;		/*  FC class for IO		 */
+	u8	seq_rec;	/*  sequence recovery support	 */
+	u8	msg_no;		/*  seq id of the msg		 */
+};
+
+struct bfi_itnim_create_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		 */
+	u16	bfa_handle;	/*  bfa handle for itnim	 */
+	u8	status;		/*  fcp request status		 */
+	u8	seq_id;		/*  seq id of the msg		 */
+};
+
+struct bfi_itnim_delete_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		 */
+	u16	fw_handle;	/*  f/w itnim handle		 */
+	u8	seq_id;		/*  seq id of the msg		 */
+	u8	rsvd;
+};
+
+struct bfi_itnim_delete_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		 */
+	u16	bfa_handle;	/*  bfa handle for itnim	 */
+	u8	status;		/*  fcp request status		 */
+	u8	seq_id;		/*  seq id of the msg		 */
+};
+
+struct bfi_itnim_sler_event_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		 */
+	u16	bfa_handle;	/*  bfa handle for itnim	 */
+	u16	rsvd;
+};
+
+union bfi_itnim_h2i_msg_u {
+	struct bfi_itnim_create_req_s *create_req;
+	struct bfi_itnim_delete_req_s *delete_req;
+	struct bfi_msg_s	*msg;
+};
+
+union bfi_itnim_i2h_msg_u {
+	struct bfi_itnim_create_rsp_s *create_rsp;
+	struct bfi_itnim_delete_rsp_s *delete_rsp;
+	struct bfi_itnim_sler_event_s *sler_event;
+	struct bfi_msg_s	*msg;
+};
+
+/*
+ * Initiator mode IO interface defines.
+ */
+
+enum bfi_ioim_h2i {
+	BFI_IOIM_H2I_IOABORT_REQ = 1,	/*  IO abort request	 */
+	BFI_IOIM_H2I_IOCLEANUP_REQ = 2,	/*  IO cleanup request	 */
+};
+
+enum bfi_ioim_i2h {
+	BFI_IOIM_I2H_IO_RSP = BFA_I2HM(1),	/*  non-fp IO response	 */
+	BFI_IOIM_I2H_IOABORT_RSP = BFA_I2HM(2),	/*  ABORT rsp	 */
+};
+
+/**
+ * IO command DIF info
+ */
+struct bfi_ioim_dif_s {
+	u32	dif_info[4];
+};
+
+/**
+ * FCP IO messages overview
+ *
+ * @note
+ * - Max CDB length supported is 64 bytes.
+ * - SCSI Linked commands and SCSI bi-directional Commands not
+ *	supported.
+ *
+ */
+struct bfi_ioim_req_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		 */
+	u16	io_tag;		/*  I/O tag			 */
+	u16	rport_hdl;	/*  itnim/rport firmware handle */
+	struct fcp_cmnd_s	cmnd;	/*  IO request info	*/
+
+	/**
+	 * SG elements array within the IO request must be double word
+	 * aligned. This aligment is required to optimize SGM setup for the IO.
+	 */
+	struct bfi_sge_s	sges[BFI_SGE_INLINE_MAX];
+	u8	io_timeout;
+	u8	dif_en;
+	u8	rsvd_a[2];
+	struct bfi_ioim_dif_s  dif;
+};
+
+/**
+ *	This table shows various IO status codes from firmware and their
+ *	meaning. Host driver can use these status codes to further process
+ *	IO completions.
+ *
+ *	BFI_IOIM_STS_OK		: IO completed with error free SCSI &
+ *					transport status.
+ *					 io-tag can be reused.
+ *
+ *	BFA_IOIM_STS_SCSI_ERR		: IO completed with scsi error.
+ *	- io-tag can be reused.
+ *
+ *	BFI_IOIM_STS_HOST_ABORTED	: IO was aborted successfully due to
+ *						host request.
+ *					- io-tag cannot be reused yet.
+ *
+ *	BFI_IOIM_STS_ABORTED		: IO was aborted successfully
+ *						internally by f/w.
+ *					- io-tag cannot be reused yet.
+ *
+ *	BFI_IOIM_STS_TIMEDOUT	: IO timedout and ABTS/RRQ is happening
+ *					in the firmware and
+ *					- io-tag cannot be reused yet.
+ *
+ *	BFI_IOIM_STS_SQER_NEEDED	: Firmware could not recover the IO
+ *					  with sequence level error
+ *	logic and hence host needs to retry
+ *					  this IO with a different IO tag
+ *					- io-tag cannot be used yet.
+ *
+ *	BFI_IOIM_STS_NEXUS_ABORT	: Second Level Error Recovery from host
+ *					  is required because 2 consecutive ABTS
+ *					  timedout and host needs logout and
+ *					  re-login with the target
+ *					- io-tag cannot be used yet.
+ *
+ *	BFI_IOIM_STS_UNDERRUN	: IO completed with SCSI status good,
+ *					  but the data tranferred is less than
+ *					  the fcp data length in the command.
+ *					  ex. SCSI INQUIRY where transferred
+ *					  data length and residue count in FCP
+ *					  response accounts for total fcp-dl
+ *					  - io-tag can be reused.
+ *
+ *	BFI_IOIM_STS_OVERRUN	: IO completed with SCSI status good,
+ *					  but the data transerred is more than
+ *					  fcp data length in the command. ex.
+ *					  TAPE IOs where blocks can of unequal
+ *					  lengths.
+ *					- io-tag can be reused.
+ *
+ *	BFI_IOIM_STS_RES_FREE	: Firmware has completed using io-tag
+ *					  during abort process
+ *					- io-tag can be reused.
+ *
+ *	BFI_IOIM_STS_PROTO_ERR	: Firmware detected a protocol error.
+ *					  ex target sent more data than
+ *					  requested, or there was data frame
+ *					  loss and other reasons
+ *					- io-tag cannot be used yet.
+ *
+ *	BFI_IOIM_STS_DIF_ERR	: Firwmare detected DIF error. ex: DIF
+ *					CRC err or Ref Tag err or App tag err.
+ *					- io-tag can be reused.
+ *
+ *	BFA_IOIM_STS_TSK_MGT_ABORT	: IO was aborted because of Task
+ *					  Management command from the host
+ *					  - io-tag can be reused.
+ *
+ *	BFI_IOIM_STS_UTAG		: Firmware does not know about this
+ *					  io_tag.
+ *					- io-tag can be reused.
+ */
+enum bfi_ioim_status {
+	BFI_IOIM_STS_OK = 0,
+	BFI_IOIM_STS_HOST_ABORTED = 1,
+	BFI_IOIM_STS_ABORTED = 2,
+	BFI_IOIM_STS_TIMEDOUT = 3,
+	BFI_IOIM_STS_RES_FREE = 4,
+	BFI_IOIM_STS_SQER_NEEDED = 5,
+	BFI_IOIM_STS_PROTO_ERR = 6,
+	BFI_IOIM_STS_UTAG = 7,
+	BFI_IOIM_STS_PATHTOV = 8,
+};
+
+#define BFI_IOIM_SNSLEN	(256)
+/**
+ * I/O response message
+ */
+struct bfi_ioim_rsp_s {
+	struct bfi_mhdr_s	mh;	/*  common msg header		*/
+	u16	io_tag;		/*  completed IO tag		 */
+	u16	bfa_rport_hndl;	/*  releated rport handle	 */
+	u8	io_status;	/*  IO completion status	 */
+	u8	reuse_io_tag;	/*  IO tag can be reused	*/
+	u16	abort_tag;	/*  host abort request tag	*/
+	u8		scsi_status;	/*  scsi status from target	 */
+	u8		sns_len;	/*  scsi sense length		 */
+	u8		resid_flags;	/*  IO residue flags		 */
+	u8		rsvd_a;
+	u32	residue;	/*  IO residual length in bytes */
+	u32	rsvd_b[3];
+};
+
+struct bfi_ioim_abort_req_s {
+	struct bfi_mhdr_s  mh;	/*  Common msg header  */
+	u16	io_tag;	/*  I/O tag	*/
+	u16	abort_tag;	/*  unique request tag */
+};
+
+/*
+ * Initiator mode task management command interface defines.
+ */
+
+enum bfi_tskim_h2i {
+	BFI_TSKIM_H2I_TM_REQ	= 1, /*  task-mgmt command	*/
+	BFI_TSKIM_H2I_ABORT_REQ = 2, /*  task-mgmt command	*/
+};
+
+enum bfi_tskim_i2h {
+	BFI_TSKIM_I2H_TM_RSP = BFA_I2HM(1),
+};
+
+struct bfi_tskim_req_s {
+	struct bfi_mhdr_s  mh;	/*  Common msg header	*/
+	u16	tsk_tag;	/*  task management tag	*/
+	u16	itn_fhdl;	/*  itn firmware handle	*/
+	lun_t	lun;	/*  LU number	*/
+	u8	tm_flags;	/*  see enum fcp_tm_cmnd	*/
+	u8	t_secs;	/*  Timeout value in seconds	*/
+	u8	rsvd[2];
+};
+
+struct bfi_tskim_abortreq_s {
+	struct bfi_mhdr_s  mh;	/*  Common msg header	*/
+	u16	tsk_tag;	/*  task management tag	*/
+	u16	rsvd;
+};
+
+enum bfi_tskim_status {
+	/*
+	 * Following are FCP-4 spec defined status codes,
+	 * **DO NOT CHANGE THEM **
+	 */
+	BFI_TSKIM_STS_OK	= 0,
+	BFI_TSKIM_STS_NOT_SUPP = 4,
+	BFI_TSKIM_STS_FAILED	= 5,
+
+	/**
+	 * Defined by BFA
+	 */
+	BFI_TSKIM_STS_TIMEOUT  = 10,	/*  TM request timedout	*/
+	BFI_TSKIM_STS_ABORTED  = 11,	/*  Aborted on host request */
+};
+
+struct bfi_tskim_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		 */
+	u16	tsk_tag;	/*  task mgmt cmnd tag		 */
+	u8	tsk_status;	/*  @ref bfi_tskim_status */
+	u8	rsvd;
+};
+
+#pragma pack()
+
+#endif /* __BFI_MS_H__ */
diff --git a/drivers/scsi/bfa/fab.c b/drivers/scsi/bfa/fab.c
deleted file mode 100644
index 7e3a4d5..0000000
--- a/drivers/scsi/bfa/fab.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "lport_priv.h"
-
-/**
- *  fab.c port fab implementation.
- */
-
-/**
- *  bfa_fcs_port_fab_public port fab public functions
- */
-
-/**
- *   Called by port to initialize fabric services of the base port.
- */
-void
-bfa_fcs_port_fab_init(struct bfa_fcs_port_s *port)
-{
-	bfa_fcs_port_ns_init(port);
-	bfa_fcs_port_scn_init(port);
-	bfa_fcs_port_ms_init(port);
-}
-
-/**
- *   Called by port to notify transition to online state.
- */
-void
-bfa_fcs_port_fab_online(struct bfa_fcs_port_s *port)
-{
-	bfa_fcs_port_ns_online(port);
-	bfa_fcs_port_scn_online(port);
-}
-
-/**
- *   Called by port to notify transition to offline state.
- */
-void
-bfa_fcs_port_fab_offline(struct bfa_fcs_port_s *port)
-{
-	bfa_fcs_port_ns_offline(port);
-	bfa_fcs_port_scn_offline(port);
-	bfa_fcs_port_ms_offline(port);
-}
diff --git a/drivers/scsi/bfa/fabric.c b/drivers/scsi/bfa/fabric.c
deleted file mode 100644
index ddd4ba9..0000000
--- a/drivers/scsi/bfa/fabric.c
+++ /dev/null
@@ -1,1323 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fabric.c Fabric module implementation.
- */
-
-#include "fcs_fabric.h"
-#include "fcs_lport.h"
-#include "fcs_vport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs_auth.h"
-#include "fcs.h"
-#include "fcbuild.h"
-#include <log/bfa_log_fcs.h>
-#include <aen/bfa_aen_port.h>
-#include <bfa_svc.h>
-
-BFA_TRC_FILE(FCS, FABRIC);
-
-#define BFA_FCS_FABRIC_RETRY_DELAY	(2000)	/* Milliseconds */
-#define BFA_FCS_FABRIC_CLEANUP_DELAY	(10000)	/* Milliseconds */
-
-#define bfa_fcs_fabric_set_opertype(__fabric) do {             \
-	if (bfa_fcport_get_topology((__fabric)->fcs->bfa)       \
-				== BFA_PPORT_TOPOLOGY_P2P)     \
-		(__fabric)->oper_type = BFA_PPORT_TYPE_NPORT;  \
-	else                                                   \
-		(__fabric)->oper_type = BFA_PPORT_TYPE_NLPORT; \
-} while (0)
-
-/*
- * forward declarations
- */
-static void     bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_delay(void *cbarg);
-static void     bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_delete_comp(void *cbarg);
-static void     bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
-					  struct fchs_s *fchs, u16 len);
-static void     bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
-					     struct fchs_s *fchs, u16 len);
-static void     bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
-					     struct bfa_fcxp_s *fcxp,
-					     void *cbarg, bfa_status_t status,
-					     u32 rsp_len,
-					     u32 resid_len,
-					     struct fchs_s *rspfchs);
-/**
- *  fcs_fabric_sm fabric state machine functions
- */
-
-/**
- * Fabric state machine events
- */
-enum bfa_fcs_fabric_event {
-	BFA_FCS_FABRIC_SM_CREATE = 1,	/*  fabric create from driver */
-	BFA_FCS_FABRIC_SM_DELETE = 2,	/*  fabric delete from driver */
-	BFA_FCS_FABRIC_SM_LINK_DOWN = 3,	/*  link down from port */
-	BFA_FCS_FABRIC_SM_LINK_UP = 4,	/*  link up from port */
-	BFA_FCS_FABRIC_SM_CONT_OP = 5,	/*  continue op from flogi/auth */
-	BFA_FCS_FABRIC_SM_RETRY_OP = 6,	/*  continue op from flogi/auth */
-	BFA_FCS_FABRIC_SM_NO_FABRIC = 7,	/*  no fabric from flogi/auth
-						 */
-	BFA_FCS_FABRIC_SM_PERF_EVFP = 8,	/*  perform EVFP from
-						 *flogi/auth */
-	BFA_FCS_FABRIC_SM_ISOLATE = 9,	/*  isolate from EVFP processing */
-	BFA_FCS_FABRIC_SM_NO_TAGGING = 10,/*  no VFT tagging from EVFP */
-	BFA_FCS_FABRIC_SM_DELAYED = 11,	/*  timeout delay event */
-	BFA_FCS_FABRIC_SM_AUTH_FAILED = 12,	/*  authentication failed */
-	BFA_FCS_FABRIC_SM_AUTH_SUCCESS = 13,	/*  authentication successful
-						 */
-	BFA_FCS_FABRIC_SM_DELCOMP = 14,	/*  all vports deleted event */
-	BFA_FCS_FABRIC_SM_LOOPBACK = 15,	/*  Received our own FLOGI */
-	BFA_FCS_FABRIC_SM_START = 16,	/*  fabric delete from driver */
-};
-
-static void     bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
-					 enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
-					  enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
-					   enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
-					enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
-					      enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
-				       enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
-					      enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
-					   enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
-					   enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
-					 enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
-				       enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
-					    enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
-					   enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
-					   enum bfa_fcs_fabric_event event);
-/**
- *   Beginning state before fabric creation.
- */
-static void
-bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
-			 enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_CREATE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
-		bfa_fcs_fabric_init(fabric);
-		bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_UP:
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Beginning state before fabric creation.
- */
-static void
-bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
-			  enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_START:
-		if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
-			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
-			bfa_fcs_fabric_login(fabric);
-		} else
-			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_UP:
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
-		bfa_fcs_modexit_comp(fabric->fcs);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Link is down, awaiting LINK UP event from port. This is also the
- *   first state at fabric creation.
- */
-static void
-bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
-			   enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_LINK_UP:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
-		bfa_fcs_fabric_login(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_RETRY_OP:
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   FLOGI is in progress, awaiting FLOGI reply.
- */
-static void
-bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
-			enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_CONT_OP:
-
-		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
-		fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
-
-		if (fabric->auth_reqd && fabric->is_auth) {
-			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);
-			bfa_trc(fabric->fcs, event);
-		} else {
-			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
-			bfa_fcs_fabric_notify_online(fabric);
-		}
-		break;
-
-	case BFA_FCS_FABRIC_SM_RETRY_OP:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);
-		bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,
-				bfa_fcs_fabric_delay, fabric,
-				BFA_FCS_FABRIC_RETRY_DELAY);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LOOPBACK:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
-		bfa_lps_discard(fabric->lps);
-		bfa_fcs_fabric_set_opertype(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_NO_FABRIC:
-		fabric->fab_type = BFA_FCS_FABRIC_N2N;
-		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
-		bfa_fcs_fabric_notify_online(fabric);
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_lps_discard(fabric->lps);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-
-static void
-bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
-			      enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_DELAYED:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
-		bfa_fcs_fabric_login(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_timer_stop(&fabric->delay_timer);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_timer_stop(&fabric->delay_timer);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Authentication is in progress, awaiting authentication results.
- */
-static void
-bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
-		       enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_AUTH_FAILED:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
-		bfa_lps_discard(fabric->lps);
-		break;
-
-	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
-		bfa_fcs_fabric_notify_online(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_PERF_EVFP:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Authentication failed
- */
-static void
-bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
-			      enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_fcs_fabric_notify_offline(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Port is in loopback mode.
- */
-static void
-bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
-			   enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_fcs_fabric_notify_offline(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   There is no attached fabric - private loop or NPort-to-NPort topology.
- */
-static void
-bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
-			   enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
-		bfa_fcs_fabric_notify_offline(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_NO_FABRIC:
-		bfa_trc(fabric->fcs, fabric->bb_credit);
-		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Fabric is online - normal operating state.
- */
-static void
-bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
-			 enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
-		bfa_fcs_fabric_notify_offline(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_AUTH_FAILED:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
-		bfa_lps_discard(fabric->lps);
-		break;
-
-	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Exchanging virtual fabric parameters.
- */
-static void
-bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
-		       enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_CONT_OP:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);
-		break;
-
-	case BFA_FCS_FABRIC_SM_ISOLATE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   EVFP exchange complete and VFT tagging is enabled.
- */
-static void
-bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
-			    enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-}
-
-/**
- *   Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
- */
-static void
-bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
-			   enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	bfa_log(fabric->fcs->logm, BFA_LOG_FCS_FABRIC_ISOLATED,
-		fabric->bport.port_cfg.pwwn, fabric->fcs->port_vfid,
-		fabric->event_arg.swp_vfid);
-}
-
-/**
- *   Fabric is being deleted, awaiting vport delete completions.
- */
-static void
-bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
-			   enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_DELCOMP:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
-		bfa_fcs_modexit_comp(fabric->fcs);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_UP:
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_fcs_fabric_notify_offline(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-
-
-/**
- *  fcs_fabric_private fabric private functions
- */
-
-static void
-bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg;
-
-	port_cfg->roles = BFA_PORT_ROLE_FCP_IM;
-	port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc);
-	port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc);
-}
-
-/**
- * Port Symbolic Name Creation for base port.
- */
-void
-bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg;
-	char            model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
-	struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
-
-	bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
-
-	/*
-	 * Model name/number
-	 */
-	strncpy((char *)&port_cfg->sym_name, model,
-		BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
-	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
-	/*
-	 * Driver Version
-	 */
-	strncat((char *)&port_cfg->sym_name, (char *)driver_info->version,
-		BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
-	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
-	/*
-	 * Host machine name
-	 */
-	strncat((char *)&port_cfg->sym_name,
-		(char *)driver_info->host_machine_name,
-		BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
-	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
-	/*
-	 * Host OS Info :
-	 * If OS Patch Info is not there, do not truncate any bytes from the
-	 * OS name string and instead copy the entire OS info string (64 bytes).
-	 */
-	if (driver_info->host_os_patch[0] == '\0') {
-		strncat((char *)&port_cfg->sym_name,
-			(char *)driver_info->host_os_name, BFA_FCS_OS_STR_LEN);
-		strncat((char *)&port_cfg->sym_name,
-			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-	} else {
-		strncat((char *)&port_cfg->sym_name,
-			(char *)driver_info->host_os_name,
-			BFA_FCS_PORT_SYMBNAME_OSINFO_SZ);
-		strncat((char *)&port_cfg->sym_name,
-			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
-		/*
-		 * Append host OS Patch Info
-		 */
-		strncat((char *)&port_cfg->sym_name,
-			(char *)driver_info->host_os_patch,
-			BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ);
-	}
-
-	/*
-	 * null terminate
-	 */
-	port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
-}
-
-/**
- * bfa lps login completion callback
- */
-void
-bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
-{
-	struct bfa_fcs_fabric_s *fabric = uarg;
-
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, status);
-
-	switch (status) {
-	case BFA_STATUS_OK:
-		fabric->stats.flogi_accepts++;
-		break;
-
-	case BFA_STATUS_INVALID_MAC:
-		/*
-		 * Only for CNA
-		 */
-		fabric->stats.flogi_acc_err++;
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
-
-		return;
-
-	case BFA_STATUS_EPROTOCOL:
-		switch (bfa_lps_get_extstatus(fabric->lps)) {
-		case BFA_EPROTO_BAD_ACCEPT:
-			fabric->stats.flogi_acc_err++;
-			break;
-
-		case BFA_EPROTO_UNKNOWN_RSP:
-			fabric->stats.flogi_unknown_rsp++;
-			break;
-
-		default:
-			break;
-		}
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
-
-		return;
-
-	case BFA_STATUS_FABRIC_RJT:
-		fabric->stats.flogi_rejects++;
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
-		return;
-
-	default:
-		fabric->stats.flogi_rsp_err++;
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
-		return;
-	}
-
-	fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps);
-	bfa_trc(fabric->fcs, fabric->bb_credit);
-
-	if (!bfa_lps_is_brcd_fabric(fabric->lps))
-		fabric->fabric_name = bfa_lps_get_peer_nwwn(fabric->lps);
-
-	/*
-	 * Check port type. It should be 1 = F-port.
-	 */
-	if (bfa_lps_is_fport(fabric->lps)) {
-		fabric->bport.pid = bfa_lps_get_pid(fabric->lps);
-		fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps);
-		fabric->is_auth = bfa_lps_is_authreq(fabric->lps);
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
-	} else {
-		/*
-		 * Nport-2-Nport direct attached
-		 */
-		fabric->bport.port_topo.pn2n.rem_port_wwn =
-			bfa_lps_get_peer_pwwn(fabric->lps);
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
-	}
-
-	bfa_trc(fabric->fcs, fabric->bport.pid);
-	bfa_trc(fabric->fcs, fabric->is_npiv);
-	bfa_trc(fabric->fcs, fabric->is_auth);
-}
-
-/**
- * 		Allocate and send FLOGI.
- */
-static void
-bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_s   *bfa = fabric->fcs->bfa;
-	struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg;
-	u8         alpa = 0;
-
-	if (bfa_fcport_get_topology(bfa) == BFA_PPORT_TOPOLOGY_LOOP)
-		alpa = bfa_fcport_get_myalpa(bfa);
-
-	bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
-		      pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
-
-	fabric->stats.flogi_sent++;
-}
-
-static void
-bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_fcs_vport_s *vport;
-	struct list_head *qe, *qen;
-
-	bfa_trc(fabric->fcs, fabric->fabric_name);
-
-	bfa_fcs_fabric_set_opertype(fabric);
-	fabric->stats.fabric_onlines++;
-
-	/**
-	 * notify online event to base and then virtual ports
-	 */
-	bfa_fcs_port_online(&fabric->bport);
-
-	list_for_each_safe(qe, qen, &fabric->vport_q) {
-		vport = (struct bfa_fcs_vport_s *)qe;
-		bfa_fcs_vport_online(vport);
-	}
-}
-
-static void
-bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_fcs_vport_s *vport;
-	struct list_head *qe, *qen;
-
-	bfa_trc(fabric->fcs, fabric->fabric_name);
-	fabric->stats.fabric_offlines++;
-
-	/**
-	 * notify offline event first to vports and then base port.
-	 */
-	list_for_each_safe(qe, qen, &fabric->vport_q) {
-		vport = (struct bfa_fcs_vport_s *)qe;
-		bfa_fcs_vport_offline(vport);
-	}
-
-	bfa_fcs_port_offline(&fabric->bport);
-
-	fabric->fabric_name = 0;
-	fabric->fabric_ip_addr[0] = 0;
-}
-
-static void
-bfa_fcs_fabric_delay(void *cbarg)
-{
-	struct bfa_fcs_fabric_s *fabric = cbarg;
-
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
-}
-
-/**
- * Delete all vports and wait for vport delete completions.
- */
-static void
-bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_fcs_vport_s *vport;
-	struct list_head *qe, *qen;
-
-	list_for_each_safe(qe, qen, &fabric->vport_q) {
-		vport = (struct bfa_fcs_vport_s *)qe;
-		bfa_fcs_vport_fcs_delete(vport);
-	}
-
-	bfa_fcs_port_delete(&fabric->bport);
-	bfa_wc_wait(&fabric->wc);
-}
-
-static void
-bfa_fcs_fabric_delete_comp(void *cbarg)
-{
-	struct bfa_fcs_fabric_s *fabric = cbarg;
-
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
-}
-
-
-
-/**
- *  fcs_fabric_public fabric public functions
- */
-
-/**
- *   Attach time initialization
- */
-void
-bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
-{
-	struct bfa_fcs_fabric_s *fabric;
-
-	fabric = &fcs->fabric;
-	bfa_os_memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
-
-	/**
-	 * Initialize base fabric.
-	 */
-	fabric->fcs = fcs;
-	INIT_LIST_HEAD(&fabric->vport_q);
-	INIT_LIST_HEAD(&fabric->vf_q);
-	fabric->lps = bfa_lps_alloc(fcs->bfa);
-	bfa_assert(fabric->lps);
-
-	/**
-	 * Initialize fabric delete completion handler. Fabric deletion is complete
-	 * when the last vport delete is complete.
-	 */
-	bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
-	bfa_wc_up(&fabric->wc);	/* For the base port */
-
-	bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
-	bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
-}
-
-void
-bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
-{
-	bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
-	bfa_trc(fcs, 0);
-}
-
-/**
- *   Module cleanup
- */
-void
-bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
-{
-	struct bfa_fcs_fabric_s *fabric;
-
-	bfa_trc(fcs, 0);
-
-	/**
-	 * Cleanup base fabric.
-	 */
-	fabric = &fcs->fabric;
-	bfa_lps_delete(fabric->lps);
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
-}
-
-/**
- * Fabric module start -- kick starts FCS actions
- */
-void
-bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
-{
-	struct bfa_fcs_fabric_s *fabric;
-
-	bfa_trc(fcs, 0);
-	fabric = &fcs->fabric;
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
-}
-
-/**
- *   Suspend fabric activity as part of driver suspend.
- */
-void
-bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs)
-{
-}
-
-bfa_boolean_t
-bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric)
-{
-	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback);
-}
-
-bfa_boolean_t
-bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric)
-{
-	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed);
-}
-
-enum bfa_pport_type
-bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric)
-{
-	return fabric->oper_type;
-}
-
-/**
- *   Link up notification from BFA physical port module.
- */
-void
-bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);
-}
-
-/**
- *   Link down notification from BFA physical port module.
- */
-void
-bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
-}
-
-/**
- *   A child vport is being created in the fabric.
- *
- *   Call from vport module at vport creation. A list of base port and vports
- *   belonging to a fabric is maintained to propagate link events.
- *
- *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *   param[in] vport  - Vport being created.
- *
- *   @return None (always succeeds)
- */
-void
-bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
-			struct bfa_fcs_vport_s *vport)
-{
-	/**
-	 * - add vport to fabric's vport_q
-	 */
-	bfa_trc(fabric->fcs, fabric->vf_id);
-
-	list_add_tail(&vport->qe, &fabric->vport_q);
-	fabric->num_vports++;
-	bfa_wc_up(&fabric->wc);
-}
-
-/**
- *   A child vport is being deleted from fabric.
- *
- *   Vport is being deleted.
- */
-void
-bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
-			struct bfa_fcs_vport_s *vport)
-{
-	list_del(&vport->qe);
-	fabric->num_vports--;
-	bfa_wc_down(&fabric->wc);
-}
-
-/**
- *   Base port is deleted.
- */
-void
-bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric)
-{
-	bfa_wc_down(&fabric->wc);
-}
-
-/**
- *    Check if fabric is online.
- *
- *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *
- *   @return  TRUE/FALSE
- */
-int
-bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric)
-{
-	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online);
-}
-
-
-bfa_status_t
-bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs,
-		     struct bfa_port_cfg_s *port_cfg,
-		     struct bfad_vf_s *vf_drv)
-{
-	bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit);
-	return BFA_STATUS_OK;
-}
-
-/**
- * Lookup for a vport withing a fabric given its pwwn
- */
-struct bfa_fcs_vport_s *
-bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
-{
-	struct bfa_fcs_vport_s *vport;
-	struct list_head *qe;
-
-	list_for_each(qe, &fabric->vport_q) {
-		vport = (struct bfa_fcs_vport_s *)qe;
-		if (bfa_fcs_port_get_pwwn(&vport->lport) == pwwn)
-			return vport;
-	}
-
-	return NULL;
-}
-
-/**
- *    In a given fabric, return the number of lports.
- *
- *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *
-*    @return : 1 or more.
- */
-u16
-bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric)
-{
-	return fabric->num_vports;
-}
-
-/*
- *  Get OUI of the attached switch.
- *
- *  Note : Use of this function should be avoided as much as possible.
- *         This function should be used only if there is any requirement
- *         to check for FOS version below 6.3.
- *         To check if the attached fabric is a brocade fabric, use
- *         bfa_lps_is_brcd_fabric() which works for FOS versions 6.3
- *         or above only.
- */
-
-u16
-bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)
-{
-	wwn_t fab_nwwn;
-	u8 *tmp;
-	u16 oui;
-
-	fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps);
-
-	tmp = (uint8_t *)&fab_nwwn;
-	oui = (tmp[3] << 8) | tmp[4];
-
-	return oui;
-}
-
-/**
- * 		Unsolicited frame receive handling.
- */
-void
-bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
-		       u16 len)
-{
-	u32        pid = fchs->d_id;
-	struct bfa_fcs_vport_s *vport;
-	struct list_head *qe;
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-	struct fc_logi_s     *flogi = (struct fc_logi_s *) els_cmd;
-
-	bfa_trc(fabric->fcs, len);
-	bfa_trc(fabric->fcs, pid);
-
-	/**
-	 * Look for our own FLOGI frames being looped back. This means an
-	 * external loopback cable is in place. Our own FLOGI frames are
-	 * sometimes looped back when switch port gets temporarily bypassed.
-	 */
-	if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT))
-	    && (els_cmd->els_code == FC_ELS_FLOGI)
-	    && (flogi->port_name == bfa_fcs_port_get_pwwn(&fabric->bport))) {
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
-		return;
-	}
-
-	/**
-	 * FLOGI/EVFP exchanges should be consumed by base fabric.
-	 */
-	if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) {
-		bfa_trc(fabric->fcs, pid);
-		bfa_fcs_fabric_process_uf(fabric, fchs, len);
-		return;
-	}
-
-	if (fabric->bport.pid == pid) {
-		/**
-		 * All authentication frames should be routed to auth
-		 */
-		bfa_trc(fabric->fcs, els_cmd->els_code);
-		if (els_cmd->els_code == FC_ELS_AUTH) {
-			bfa_trc(fabric->fcs, els_cmd->els_code);
-			fabric->auth.response = (u8 *) els_cmd;
-			return;
-		}
-
-		bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));
-		bfa_fcs_port_uf_recv(&fabric->bport, fchs, len);
-		return;
-	}
-
-	/**
-	 * look for a matching local port ID
-	 */
-	list_for_each(qe, &fabric->vport_q) {
-		vport = (struct bfa_fcs_vport_s *)qe;
-		if (vport->lport.pid == pid) {
-			bfa_fcs_port_uf_recv(&vport->lport, fchs, len);
-			return;
-		}
-	}
-	bfa_trc(fabric->fcs, els_cmd->els_code);
-	bfa_fcs_port_uf_recv(&fabric->bport, fchs, len);
-}
-
-/**
- * 		Unsolicited frames to be processed by fabric.
- */
-static void
-bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
-			  u16 len)
-{
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-
-	bfa_trc(fabric->fcs, els_cmd->els_code);
-
-	switch (els_cmd->els_code) {
-	case FC_ELS_FLOGI:
-		bfa_fcs_fabric_process_flogi(fabric, fchs, len);
-		break;
-
-	default:
-		/*
-		 * need to generate a LS_RJT
-		 */
-		break;
-	}
-}
-
-/**
- * 	Process	incoming FLOGI
- */
-static void
-bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
-			struct fchs_s *fchs, u16 len)
-{
-	struct fc_logi_s     *flogi = (struct fc_logi_s *) (fchs + 1);
-	struct bfa_fcs_port_s *bport = &fabric->bport;
-
-	bfa_trc(fabric->fcs, fchs->s_id);
-
-	fabric->stats.flogi_rcvd++;
-	/*
-	 * Check port type. It should be 0 = n-port.
-	 */
-	if (flogi->csp.port_type) {
-		/*
-		 * @todo: may need to send a LS_RJT
-		 */
-		bfa_trc(fabric->fcs, flogi->port_name);
-		fabric->stats.flogi_rejected++;
-		return;
-	}
-
-	fabric->bb_credit = bfa_os_ntohs(flogi->csp.bbcred);
-	bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
-	bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
-
-	/*
-	 * Send a Flogi Acc
-	 */
-	bfa_fcs_fabric_send_flogi_acc(fabric);
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
-}
-
-static void
-bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg;
-	struct bfa_fcs_port_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;
-	struct bfa_s   *bfa = fabric->fcs->bfa;
-	struct bfa_fcxp_s *fcxp;
-	u16        reqlen;
-	struct fchs_s          fchs;
-
-	fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
-	/**
-	 * Do not expect this failure -- expect remote node to retry
-	 */
-	if (!fcxp)
-		return;
-
-	reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-				    bfa_os_hton3b(FC_FABRIC_PORT),
-				    n2n_port->reply_oxid, pcfg->pwwn,
-				    pcfg->nwwn, bfa_fcport_get_maxfrsize(bfa),
-				    bfa_fcport_get_rx_bbcredit(bfa));
-
-	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps),
-			BFA_FALSE, FC_CLASS_3, reqlen, &fchs,
-			bfa_fcs_fabric_flogiacc_comp, fabric,
-			FC_MAX_PDUSZ, 0); /* Timeout 0 indicates no
-					   * response expected
-					   */
-}
-
-/**
- *   Flogi Acc completion callback.
- */
-static void
-bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			     bfa_status_t status, u32 rsp_len,
-			     u32 resid_len, struct fchs_s *rspfchs)
-{
-	struct bfa_fcs_fabric_s *fabric = cbarg;
-
-	bfa_trc(fabric->fcs, status);
-}
-
-/*
- *
- * @param[in] fabric - fabric
- * @param[in] result - 1
- *
- * @return - none
- */
-void
-bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric, enum auth_status status)
-{
-	bfa_trc(fabric->fcs, status);
-
-	if (status == FC_AUTH_STATE_SUCCESS)
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_SUCCESS);
-	else
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_FAILED);
-}
-
-/**
- * Send AEN notification
- */
-static void
-bfa_fcs_fabric_aen_post(struct bfa_fcs_port_s *port,
-			enum bfa_port_aen_event event)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = port->fcs->logm;
-	wwn_t           pwwn = bfa_fcs_port_get_pwwn(port);
-	wwn_t           fwwn = bfa_fcs_port_get_fabric_name(port);
-	char            pwwn_ptr[BFA_STRING_32];
-	char            fwwn_ptr[BFA_STRING_32];
-
-	wwn2str(pwwn_ptr, pwwn);
-	wwn2str(fwwn_ptr, fwwn);
-
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, event),
-		pwwn_ptr, fwwn_ptr);
-
-	aen_data.port.pwwn = pwwn;
-	aen_data.port.fwwn = fwwn;
-}
-
-/*
- *
- * @param[in] fabric - fabric
- * @param[in] wwn_t - new fabric name
- *
- * @return - none
- */
-void
-bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
-			       wwn_t fabric_name)
-{
-	bfa_trc(fabric->fcs, fabric_name);
-
-	if (fabric->fabric_name == 0) {
-		/*
-		 * With BRCD switches, we don't get Fabric Name in FLOGI.
-		 * Don't generate a fabric name change event in this case.
-		 */
-		fabric->fabric_name = fabric_name;
-	} else {
-		fabric->fabric_name = fabric_name;
-		/*
-		 * Generate a Event
-		 */
-		bfa_fcs_fabric_aen_post(&fabric->bport,
-					BFA_PORT_AEN_FABRIC_NAME_CHANGE);
-	}
-
-}
-
-/**
- *
- * @param[in] fabric - fabric
- * @param[in] node_symname -
- *              Caller allocated buffer to receive the symbolic name
- *
- * @return - none
- */
-void
-bfa_fcs_get_sym_name(const struct bfa_fcs_s *fcs, char *node_symname)
-{
-	bfa_os_memcpy(node_symname,
-			fcs->fabric.bport.port_cfg.sym_name.symname,
-			BFA_SYMNAME_MAXLEN);
-}
-
-/**
- * Not used by FCS.
- */
-void
-bfa_cb_lps_flogo_comp(void *bfad, void *uarg)
-{
-}
-
-
diff --git a/drivers/scsi/bfa/fcbuild.c b/drivers/scsi/bfa/fcbuild.c
deleted file mode 100644
index fee5456..0000000
--- a/drivers/scsi/bfa/fcbuild.c
+++ /dev/null
@@ -1,1449 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-/*
- * fcbuild.c - FC link service frame building and parsing routines
- */
-
-#include <bfa_os_inc.h>
-#include "fcbuild.h"
-
-/*
- * static build functions
- */
-static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id);
-static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id);
-static struct fchs_s   fc_els_req_tmpl;
-static struct fchs_s   fc_els_rsp_tmpl;
-static struct fchs_s   fc_bls_req_tmpl;
-static struct fchs_s   fc_bls_rsp_tmpl;
-static struct fc_ba_acc_s ba_acc_tmpl;
-static struct fc_logi_s plogi_tmpl;
-static struct fc_prli_s prli_tmpl;
-static struct fc_rrq_s rrq_tmpl;
-static struct fchs_s   fcp_fchs_tmpl;
-
-void
-fcbuild_init(void)
-{
-	/*
-	 * fc_els_req_tmpl
-	 */
-	fc_els_req_tmpl.routing = FC_RTG_EXT_LINK;
-	fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST;
-	fc_els_req_tmpl.type = FC_TYPE_ELS;
-	fc_els_req_tmpl.f_ctl =
-		bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
-			      FCTL_SI_XFER);
-	fc_els_req_tmpl.rx_id = FC_RXID_ANY;
-
-	/*
-	 * fc_els_rsp_tmpl
-	 */
-	fc_els_rsp_tmpl.routing = FC_RTG_EXT_LINK;
-	fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY;
-	fc_els_rsp_tmpl.type = FC_TYPE_ELS;
-	fc_els_rsp_tmpl.f_ctl =
-		bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
-			      FCTL_END_SEQ | FCTL_SI_XFER);
-	fc_els_rsp_tmpl.rx_id = FC_RXID_ANY;
-
-	/*
-	 * fc_bls_req_tmpl
-	 */
-	fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK;
-	fc_bls_req_tmpl.type = FC_TYPE_BLS;
-	fc_bls_req_tmpl.f_ctl = bfa_os_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
-	fc_bls_req_tmpl.rx_id = FC_RXID_ANY;
-
-	/*
-	 * fc_bls_rsp_tmpl
-	 */
-	fc_bls_rsp_tmpl.routing = FC_RTG_BASIC_LINK;
-	fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC;
-	fc_bls_rsp_tmpl.type = FC_TYPE_BLS;
-	fc_bls_rsp_tmpl.f_ctl =
-		bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
-			      FCTL_END_SEQ | FCTL_SI_XFER);
-	fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY;
-
-	/*
-	 * ba_acc_tmpl
-	 */
-	ba_acc_tmpl.seq_id_valid = 0;
-	ba_acc_tmpl.low_seq_cnt = 0;
-	ba_acc_tmpl.high_seq_cnt = 0xFFFF;
-
-	/*
-	 * plogi_tmpl
-	 */
-	plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
-	plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
-	plogi_tmpl.csp.bbcred = bfa_os_htons(0x0004);
-	plogi_tmpl.csp.ciro = 0x1;
-	plogi_tmpl.csp.cisc = 0x0;
-	plogi_tmpl.csp.altbbcred = 0x0;
-	plogi_tmpl.csp.conseq = bfa_os_htons(0x00FF);
-	plogi_tmpl.csp.ro_bitmap = bfa_os_htons(0x0002);
-	plogi_tmpl.csp.e_d_tov = bfa_os_htonl(2000);
-
-	plogi_tmpl.class3.class_valid = 1;
-	plogi_tmpl.class3.sequential = 1;
-	plogi_tmpl.class3.conseq = 0xFF;
-	plogi_tmpl.class3.ospx = 1;
-
-	/*
-	 * prli_tmpl
-	 */
-	prli_tmpl.command = FC_ELS_PRLI;
-	prli_tmpl.pglen = 0x10;
-	prli_tmpl.pagebytes = bfa_os_htons(0x0014);
-	prli_tmpl.parampage.type = FC_TYPE_FCP;
-	prli_tmpl.parampage.imagepair = 1;
-	prli_tmpl.parampage.servparams.rxrdisab = 1;
-
-	/*
-	 * rrq_tmpl
-	 */
-	rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ;
-
-	/*
-	 * fcp_fchs_tmpl
-	 */
-	fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA;
-	fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
-	fcp_fchs_tmpl.type = FC_TYPE_FCP;
-	fcp_fchs_tmpl.f_ctl =
-		bfa_os_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
-	fcp_fchs_tmpl.seq_id = 1;
-	fcp_fchs_tmpl.rx_id = FC_RXID_ANY;
-}
-
-static void
-fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u32 ox_id)
-{
-	bfa_os_memset(fchs, 0, sizeof(struct fchs_s));
-
-	fchs->routing = FC_RTG_FC4_DEV_DATA;
-	fchs->cat_info = FC_CAT_UNSOLICIT_CTRL;
-	fchs->type = FC_TYPE_SERVICES;
-	fchs->f_ctl =
-		bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
-			      FCTL_SI_XFER);
-	fchs->rx_id = FC_RXID_ANY;
-	fchs->d_id = (d_id);
-	fchs->s_id = (s_id);
-	fchs->ox_id = bfa_os_htons(ox_id);
-
-	/**
-	 * @todo no need to set ox_id for request
-	 *       no need to set rx_id for response
-	 */
-}
-
-void
-fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id)
-{
-	bfa_os_memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
-	fchs->d_id = (d_id);
-	fchs->s_id = (s_id);
-	fchs->ox_id = bfa_os_htons(ox_id);
-}
-
-static void
-fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id)
-{
-	bfa_os_memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
-	fchs->d_id = d_id;
-	fchs->s_id = s_id;
-	fchs->ox_id = ox_id;
-}
-
-enum fc_parse_status
-fc_els_rsp_parse(struct fchs_s *fchs, int len)
-{
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-	struct fc_ls_rjt_s    *ls_rjt = (struct fc_ls_rjt_s *) els_cmd;
-
-	len = len;
-
-	switch (els_cmd->els_code) {
-	case FC_ELS_LS_RJT:
-		if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
-			return FC_PARSE_BUSY;
-		else
-			return FC_PARSE_FAILURE;
-
-	case FC_ELS_ACC:
-		return FC_PARSE_OK;
-	}
-	return FC_PARSE_OK;
-}
-
-static void
-fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id)
-{
-	bfa_os_memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
-	fchs->d_id = d_id;
-	fchs->s_id = s_id;
-	fchs->ox_id = ox_id;
-}
-
-static          u16
-fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
-		 u16 ox_id, wwn_t port_name, wwn_t node_name,
-		 u16 pdu_size, u8 els_code)
-{
-	struct fc_logi_s     *plogi = (struct fc_logi_s *) (pld);
-
-	bfa_os_memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
-
-	plogi->els_cmd.els_code = els_code;
-	if (els_code == FC_ELS_PLOGI)
-		fc_els_req_build(fchs, d_id, s_id, ox_id);
-	else
-		fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-
-	plogi->csp.rxsz = plogi->class3.rxsz = bfa_os_htons(pdu_size);
-
-	bfa_os_memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
-	bfa_os_memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
-
-	return sizeof(struct fc_logi_s);
-}
-
-u16
-fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
-		u16 ox_id, wwn_t port_name, wwn_t node_name,
-		u16 pdu_size, u8 set_npiv, u8 set_auth,
-		u16 local_bb_credits)
-{
-	u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT);
-	u32 	*vvl_info;
-
-	bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
-
-	flogi->els_cmd.els_code = FC_ELS_FLOGI;
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-
-	flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size);
-	flogi->port_name = port_name;
-	flogi->node_name = node_name;
-
-	/*
-	 * Set the NPIV Capability Bit ( word 1, bit 31) of Common
-	 * Service Parameters.
-	 */
-	flogi->csp.ciro = set_npiv;
-
-	/* set AUTH capability */
-	flogi->csp.security = set_auth;
-
-	flogi->csp.bbcred = bfa_os_htons(local_bb_credits);
-
-	/* Set brcd token in VVL */
-	vvl_info = (u32 *)&flogi->vvl[0];
-
-	/* set the flag to indicate the presence of VVL */
-	flogi->csp.npiv_supp    = 1; /* @todo. field name is not correct */
-	vvl_info[0]	= bfa_os_htonl(FLOGI_VVL_BRCD);
-
-	return sizeof(struct fc_logi_s);
-}
-
-u16
-fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
-		   u16 ox_id, wwn_t port_name, wwn_t node_name,
-		   u16 pdu_size, u16 local_bb_credits)
-{
-	u32        d_id = 0;
-
-	bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
-	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-
-	flogi->els_cmd.els_code = FC_ELS_ACC;
-	flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size);
-	flogi->port_name = port_name;
-	flogi->node_name = node_name;
-
-	flogi->csp.bbcred = bfa_os_htons(local_bb_credits);
-
-	return sizeof(struct fc_logi_s);
-}
-
-u16
-fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
-		u16 ox_id, wwn_t port_name, wwn_t node_name,
-		u16 pdu_size)
-{
-	u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT);
-
-	bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
-
-	flogi->els_cmd.els_code = FC_ELS_FDISC;
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-
-	flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size);
-	flogi->port_name = port_name;
-	flogi->node_name = node_name;
-
-	return sizeof(struct fc_logi_s);
-}
-
-u16
-fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
-	       u16 ox_id, wwn_t port_name, wwn_t node_name,
-	       u16 pdu_size)
-{
-	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
-				node_name, pdu_size, FC_ELS_PLOGI);
-}
-
-u16
-fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
-		   u16 ox_id, wwn_t port_name, wwn_t node_name,
-		   u16 pdu_size)
-{
-	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
-				node_name, pdu_size, FC_ELS_ACC);
-}
-
-enum fc_parse_status
-fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
-{
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-	struct fc_logi_s     *plogi;
-	struct fc_ls_rjt_s    *ls_rjt;
-
-	switch (els_cmd->els_code) {
-	case FC_ELS_LS_RJT:
-		ls_rjt = (struct fc_ls_rjt_s *) (fchs + 1);
-		if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
-			return FC_PARSE_BUSY;
-		else
-			return FC_PARSE_FAILURE;
-	case FC_ELS_ACC:
-		plogi = (struct fc_logi_s *) (fchs + 1);
-		if (len < sizeof(struct fc_logi_s))
-			return FC_PARSE_FAILURE;
-
-		if (!wwn_is_equal(plogi->port_name, port_name))
-			return FC_PARSE_FAILURE;
-
-		if (!plogi->class3.class_valid)
-			return FC_PARSE_FAILURE;
-
-		if (bfa_os_ntohs(plogi->class3.rxsz) < (FC_MIN_PDUSZ))
-			return FC_PARSE_FAILURE;
-
-		return FC_PARSE_OK;
-	default:
-		return FC_PARSE_FAILURE;
-	}
-}
-
-enum fc_parse_status
-fc_plogi_parse(struct fchs_s *fchs)
-{
-	struct fc_logi_s     *plogi = (struct fc_logi_s *) (fchs + 1);
-
-	if (plogi->class3.class_valid != 1)
-		return FC_PARSE_FAILURE;
-
-	if ((bfa_os_ntohs(plogi->class3.rxsz) < FC_MIN_PDUSZ)
-	    || (bfa_os_ntohs(plogi->class3.rxsz) > FC_MAX_PDUSZ)
-	    || (plogi->class3.rxsz == 0))
-		return FC_PARSE_FAILURE;
-
-	return FC_PARSE_OK;
-}
-
-u16
-fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
-	      u16 ox_id)
-{
-	struct fc_prli_s      *prli = (struct fc_prli_s *) (pld);
-
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-	bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
-
-	prli->command = FC_ELS_PRLI;
-	prli->parampage.servparams.initiator     = 1;
-	prli->parampage.servparams.retry         = 1;
-	prli->parampage.servparams.rec_support   = 1;
-	prli->parampage.servparams.task_retry_id = 0;
-	prli->parampage.servparams.confirm       = 1;
-
-	return sizeof(struct fc_prli_s);
-}
-
-u16
-fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
-		  u16 ox_id, enum bfa_port_role role)
-{
-	struct fc_prli_s      *prli = (struct fc_prli_s *) (pld);
-
-	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-	bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
-
-	prli->command = FC_ELS_ACC;
-
-	if ((role & BFA_PORT_ROLE_FCP_TM) == BFA_PORT_ROLE_FCP_TM)
-		prli->parampage.servparams.target = 1;
-	else
-		prli->parampage.servparams.initiator = 1;
-
-	prli->parampage.rspcode = FC_PRLI_ACC_XQTD;
-
-	return sizeof(struct fc_prli_s);
-}
-
-enum fc_parse_status
-fc_prli_rsp_parse(struct fc_prli_s *prli, int len)
-{
-	if (len < sizeof(struct fc_prli_s))
-		return FC_PARSE_FAILURE;
-
-	if (prli->command != FC_ELS_ACC)
-		return FC_PARSE_FAILURE;
-
-	if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD)
-	    && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG))
-		return FC_PARSE_FAILURE;
-
-	if (prli->parampage.servparams.target != 1)
-		return FC_PARSE_FAILURE;
-
-	return FC_PARSE_OK;
-}
-
-enum fc_parse_status
-fc_prli_parse(struct fc_prli_s *prli)
-{
-	if (prli->parampage.type != FC_TYPE_FCP)
-		return FC_PARSE_FAILURE;
-
-	if (!prli->parampage.imagepair)
-		return FC_PARSE_FAILURE;
-
-	if (!prli->parampage.servparams.initiator)
-		return FC_PARSE_FAILURE;
-
-	return FC_PARSE_OK;
-}
-
-u16
-fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id,
-			u32 s_id, u16 ox_id, wwn_t port_name)
-{
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-
-	memset(logo, '\0', sizeof(struct fc_logo_s));
-	logo->els_cmd.els_code = FC_ELS_LOGO;
-	logo->nport_id = (s_id);
-	logo->orig_port_name = port_name;
-
-	return sizeof(struct fc_logo_s);
-}
-
-static          u16
-fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
-		 u32 s_id, u16 ox_id, wwn_t port_name,
-		 wwn_t node_name, u8 els_code)
-{
-	memset(adisc, '\0', sizeof(struct fc_adisc_s));
-
-	adisc->els_cmd.els_code = els_code;
-
-	if (els_code == FC_ELS_ADISC)
-		fc_els_req_build(fchs, d_id, s_id, ox_id);
-	else
-		fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-
-	adisc->orig_HA = 0;
-	adisc->orig_port_name = port_name;
-	adisc->orig_node_name = node_name;
-	adisc->nport_id = (s_id);
-
-	return sizeof(struct fc_adisc_s);
-}
-
-u16
-fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
-		u32 s_id, u16 ox_id, wwn_t port_name,
-		wwn_t node_name)
-{
-	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
-				node_name, FC_ELS_ADISC);
-}
-
-u16
-fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
-		   u32 s_id, u16 ox_id, wwn_t port_name,
-		   wwn_t node_name)
-{
-	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
-				node_name, FC_ELS_ACC);
-}
-
-enum fc_parse_status
-fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name,
-				 wwn_t node_name)
-{
-
-	if (len < sizeof(struct fc_adisc_s))
-		return FC_PARSE_FAILURE;
-
-	if (adisc->els_cmd.els_code != FC_ELS_ACC)
-		return FC_PARSE_FAILURE;
-
-	if (!wwn_is_equal(adisc->orig_port_name, port_name))
-		return FC_PARSE_FAILURE;
-
-	return FC_PARSE_OK;
-}
-
-enum fc_parse_status
-fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap,
-		 wwn_t node_name, wwn_t port_name)
-{
-	struct fc_adisc_s     *adisc = (struct fc_adisc_s *) pld;
-
-	if (adisc->els_cmd.els_code != FC_ELS_ACC)
-		return FC_PARSE_FAILURE;
-
-	if ((adisc->nport_id == (host_dap))
-	    && wwn_is_equal(adisc->orig_port_name, port_name)
-	    && wwn_is_equal(adisc->orig_node_name, node_name))
-		return FC_PARSE_OK;
-
-	return FC_PARSE_FAILURE;
-}
-
-enum fc_parse_status
-fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name)
-{
-	struct fc_logi_s     *pdisc = (struct fc_logi_s *) (fchs + 1);
-
-	if (pdisc->class3.class_valid != 1)
-		return FC_PARSE_FAILURE;
-
-	if ((bfa_os_ntohs(pdisc->class3.rxsz) <
-		 (FC_MIN_PDUSZ - sizeof(struct fchs_s)))
-	    || (pdisc->class3.rxsz == 0))
-		return FC_PARSE_FAILURE;
-
-	if (!wwn_is_equal(pdisc->port_name, port_name))
-		return FC_PARSE_FAILURE;
-
-	if (!wwn_is_equal(pdisc->node_name, node_name))
-		return FC_PARSE_FAILURE;
-
-	return FC_PARSE_OK;
-}
-
-u16
-fc_abts_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
-{
-	bfa_os_memcpy(fchs, &fc_bls_req_tmpl, sizeof(struct fchs_s));
-	fchs->cat_info = FC_CAT_ABTS;
-	fchs->d_id = (d_id);
-	fchs->s_id = (s_id);
-	fchs->ox_id = bfa_os_htons(ox_id);
-
-	return sizeof(struct fchs_s);
-}
-
-enum fc_parse_status
-fc_abts_rsp_parse(struct fchs_s *fchs, int len)
-{
-	if ((fchs->cat_info == FC_CAT_BA_ACC)
-	    || (fchs->cat_info == FC_CAT_BA_RJT))
-		return FC_PARSE_OK;
-
-	return FC_PARSE_FAILURE;
-}
-
-u16
-fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id,
-			 u32 s_id, u16 ox_id, u16 rrq_oxid)
-{
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-
-	/*
-	 * build rrq payload
-	 */
-	bfa_os_memcpy(rrq, &rrq_tmpl, sizeof(struct fc_rrq_s));
-	rrq->s_id = (s_id);
-	rrq->ox_id = bfa_os_htons(rrq_oxid);
-	rrq->rx_id = FC_RXID_ANY;
-
-	return sizeof(struct fc_rrq_s);
-}
-
-u16
-fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
-		  u16 ox_id)
-{
-	struct fc_els_cmd_s   *acc = pld;
-
-	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-
-	memset(acc, 0, sizeof(struct fc_els_cmd_s));
-	acc->els_code = FC_ELS_ACC;
-
-	return sizeof(struct fc_els_cmd_s);
-}
-
-u16
-fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
-		u32 s_id, u16 ox_id, u8 reason_code,
-		u8 reason_code_expl)
-{
-	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-	memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
-
-	ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT;
-	ls_rjt->reason_code = reason_code;
-	ls_rjt->reason_code_expl = reason_code_expl;
-	ls_rjt->vendor_unique = 0x00;
-
-	return sizeof(struct fc_ls_rjt_s);
-}
-
-u16
-fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
-		u32 s_id, u16 ox_id, u16 rx_id)
-{
-	fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
-
-	bfa_os_memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s));
-
-	fchs->rx_id = rx_id;
-
-	ba_acc->ox_id = fchs->ox_id;
-	ba_acc->rx_id = fchs->rx_id;
-
-	return sizeof(struct fc_ba_acc_s);
-}
-
-u16
-fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
-			u32 d_id, u32 s_id, u16 ox_id)
-{
-	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-	memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
-	els_cmd->els_code = FC_ELS_ACC;
-
-	return sizeof(struct fc_els_cmd_s);
-}
-
-int
-fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
-{
-	int             num_pages = 0;
-	struct fc_prlo_s      *prlo;
-	struct fc_tprlo_s     *tprlo;
-
-	if (els_code == FC_ELS_PRLO) {
-		prlo = (struct fc_prlo_s *) (fc_frame + 1);
-		num_pages = (bfa_os_ntohs(prlo->payload_len) - 4) / 16;
-	} else {
-		tprlo = (struct fc_tprlo_s *) (fc_frame + 1);
-		num_pages = (bfa_os_ntohs(tprlo->payload_len) - 4) / 16;
-	}
-	return num_pages;
-}
-
-u16
-fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			int num_pages)
-{
-	int             page;
-
-	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-
-	memset(tprlo_acc, 0, (num_pages * 16) + 4);
-	tprlo_acc->command = FC_ELS_ACC;
-
-	tprlo_acc->page_len = 0x10;
-	tprlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4);
-
-	for (page = 0; page < num_pages; page++) {
-		tprlo_acc->tprlo_acc_params[page].opa_valid = 0;
-		tprlo_acc->tprlo_acc_params[page].rpa_valid = 0;
-		tprlo_acc->tprlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
-		tprlo_acc->tprlo_acc_params[page].orig_process_assc = 0;
-		tprlo_acc->tprlo_acc_params[page].resp_process_assc = 0;
-	}
-	return bfa_os_ntohs(tprlo_acc->payload_len);
-}
-
-u16
-fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			int num_pages)
-{
-	int             page;
-
-	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-
-	memset(prlo_acc, 0, (num_pages * 16) + 4);
-	prlo_acc->command = FC_ELS_ACC;
-	prlo_acc->page_len = 0x10;
-	prlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4);
-
-	for (page = 0; page < num_pages; page++) {
-		prlo_acc->prlo_acc_params[page].opa_valid = 0;
-		prlo_acc->prlo_acc_params[page].rpa_valid = 0;
-		prlo_acc->prlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
-		prlo_acc->prlo_acc_params[page].orig_process_assc = 0;
-		prlo_acc->prlo_acc_params[page].resp_process_assc = 0;
-	}
-
-	return bfa_os_ntohs(prlo_acc->payload_len);
-}
-
-u16
-fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
-			u32 s_id, u16 ox_id, u32 data_format)
-{
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-
-	memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
-
-	rnid->els_cmd.els_code = FC_ELS_RNID;
-	rnid->node_id_data_format = data_format;
-
-	return sizeof(struct fc_rnid_cmd_s);
-}
-
-u16
-fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			u32 data_format,
-			struct fc_rnid_common_id_data_s *common_id_data,
-			struct fc_rnid_general_topology_data_s *gen_topo_data)
-{
-	memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
-
-	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-
-	rnid_acc->els_cmd.els_code = FC_ELS_ACC;
-	rnid_acc->node_id_data_format = data_format;
-	rnid_acc->common_id_data_length =
-			sizeof(struct fc_rnid_common_id_data_s);
-	rnid_acc->common_id_data = *common_id_data;
-
-	if (data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
-		rnid_acc->specific_id_data_length =
-			sizeof(struct fc_rnid_general_topology_data_s);
-		bfa_os_assign(rnid_acc->gen_topology_data, *gen_topo_data);
-		return sizeof(struct fc_rnid_acc_s);
-	} else {
-		return sizeof(struct fc_rnid_acc_s) -
-			sizeof(struct fc_rnid_general_topology_data_s);
-	}
-
-}
-
-u16
-fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id,
-			u32 s_id, u16 ox_id)
-{
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-
-	memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
-
-	rpsc->els_cmd.els_code = FC_ELS_RPSC;
-	return sizeof(struct fc_rpsc_cmd_s);
-}
-
-u16
-fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2,
-			u32 d_id, u32 s_id, u32 *pid_list,
-			u16 npids)
-{
-	u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_os_hton3b(d_id));
-	int i = 0;
-
-	fc_els_req_build(fchs, bfa_os_hton3b(dctlr_id), s_id, 0);
-
-	memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
-
-	rpsc2->els_cmd.els_code = FC_ELS_RPSC;
-	rpsc2->token = bfa_os_htonl(FC_BRCD_TOKEN);
-	rpsc2->num_pids  = bfa_os_htons(npids);
-	for (i = 0; i < npids; i++)
-		rpsc2->pid_list[i].pid = pid_list[i];
-
-	return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) *
-			(sizeof(u32)));
-}
-
-u16
-fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			struct fc_rpsc_speed_info_s *oper_speed)
-{
-	memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
-
-	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-
-	rpsc_acc->command = FC_ELS_ACC;
-	rpsc_acc->num_entries = bfa_os_htons(1);
-
-	rpsc_acc->speed_info[0].port_speed_cap =
-		bfa_os_htons(oper_speed->port_speed_cap);
-
-	rpsc_acc->speed_info[0].port_op_speed =
-		bfa_os_htons(oper_speed->port_op_speed);
-
-	return sizeof(struct fc_rpsc_acc_s);
-
-}
-
-/*
- * TBD -
- * . get rid of unnecessary memsets
- */
-
-u16
-fc_logo_rsp_parse(struct fchs_s *fchs, int len)
-{
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-
-	len = len;
-	if (els_cmd->els_code != FC_ELS_ACC)
-		return FC_PARSE_FAILURE;
-
-	return FC_PARSE_OK;
-}
-
-u16
-fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, wwn_t port_name, wwn_t node_name,
-			u16 pdu_size)
-{
-	struct fc_logi_s     *pdisc = (struct fc_logi_s *) (fchs + 1);
-
-	bfa_os_memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s));
-
-	pdisc->els_cmd.els_code = FC_ELS_PDISC;
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-
-	pdisc->csp.rxsz = pdisc->class3.rxsz = bfa_os_htons(pdu_size);
-	pdisc->port_name = port_name;
-	pdisc->node_name = node_name;
-
-	return sizeof(struct fc_logi_s);
-}
-
-u16
-fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
-{
-	struct fc_logi_s     *pdisc = (struct fc_logi_s *) (fchs + 1);
-
-	if (len < sizeof(struct fc_logi_s))
-		return FC_PARSE_LEN_INVAL;
-
-	if (pdisc->els_cmd.els_code != FC_ELS_ACC)
-		return FC_PARSE_ACC_INVAL;
-
-	if (!wwn_is_equal(pdisc->port_name, port_name))
-		return FC_PARSE_PWWN_NOT_EQUAL;
-
-	if (!pdisc->class3.class_valid)
-		return FC_PARSE_NWWN_NOT_EQUAL;
-
-	if (bfa_os_ntohs(pdisc->class3.rxsz) < (FC_MIN_PDUSZ))
-		return FC_PARSE_RXSZ_INVAL;
-
-	return FC_PARSE_OK;
-}
-
-u16
-fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
-	      int num_pages)
-{
-	struct fc_prlo_s      *prlo = (struct fc_prlo_s *) (fchs + 1);
-	int             page;
-
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-	memset(prlo, 0, (num_pages * 16) + 4);
-	prlo->command = FC_ELS_PRLO;
-	prlo->page_len = 0x10;
-	prlo->payload_len = bfa_os_htons((num_pages * 16) + 4);
-
-	for (page = 0; page < num_pages; page++) {
-		prlo->prlo_params[page].type = FC_TYPE_FCP;
-		prlo->prlo_params[page].opa_valid = 0;
-		prlo->prlo_params[page].rpa_valid = 0;
-		prlo->prlo_params[page].orig_process_assc = 0;
-		prlo->prlo_params[page].resp_process_assc = 0;
-	}
-
-	return bfa_os_ntohs(prlo->payload_len);
-}
-
-u16
-fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
-{
-	struct fc_prlo_acc_s  *prlo = (struct fc_prlo_acc_s *) (fchs + 1);
-	int             num_pages = 0;
-	int             page = 0;
-
-	len = len;
-
-	if (prlo->command != FC_ELS_ACC)
-		return FC_PARSE_FAILURE;
-
-	num_pages = ((bfa_os_ntohs(prlo->payload_len)) - 4) / 16;
-
-	for (page = 0; page < num_pages; page++) {
-		if (prlo->prlo_acc_params[page].type != FC_TYPE_FCP)
-			return FC_PARSE_FAILURE;
-
-		if (prlo->prlo_acc_params[page].opa_valid != 0)
-			return FC_PARSE_FAILURE;
-
-		if (prlo->prlo_acc_params[page].rpa_valid != 0)
-			return FC_PARSE_FAILURE;
-
-		if (prlo->prlo_acc_params[page].orig_process_assc != 0)
-			return FC_PARSE_FAILURE;
-
-		if (prlo->prlo_acc_params[page].resp_process_assc != 0)
-			return FC_PARSE_FAILURE;
-	}
-	return FC_PARSE_OK;
-
-}
-
-u16
-fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, int num_pages,
-			enum fc_tprlo_type tprlo_type, u32 tpr_id)
-{
-	struct fc_tprlo_s     *tprlo = (struct fc_tprlo_s *) (fchs + 1);
-	int             page;
-
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-	memset(tprlo, 0, (num_pages * 16) + 4);
-	tprlo->command = FC_ELS_TPRLO;
-	tprlo->page_len = 0x10;
-	tprlo->payload_len = bfa_os_htons((num_pages * 16) + 4);
-
-	for (page = 0; page < num_pages; page++) {
-		tprlo->tprlo_params[page].type = FC_TYPE_FCP;
-		tprlo->tprlo_params[page].opa_valid = 0;
-		tprlo->tprlo_params[page].rpa_valid = 0;
-		tprlo->tprlo_params[page].orig_process_assc = 0;
-		tprlo->tprlo_params[page].resp_process_assc = 0;
-		if (tprlo_type == FC_GLOBAL_LOGO) {
-			tprlo->tprlo_params[page].global_process_logout = 1;
-		} else if (tprlo_type == FC_TPR_LOGO) {
-			tprlo->tprlo_params[page].tpo_nport_valid = 1;
-			tprlo->tprlo_params[page].tpo_nport_id = (tpr_id);
-		}
-	}
-
-	return bfa_os_ntohs(tprlo->payload_len);
-}
-
-u16
-fc_tprlo_rsp_parse(struct fchs_s *fchs, int len)
-{
-	struct fc_tprlo_acc_s *tprlo = (struct fc_tprlo_acc_s *) (fchs + 1);
-	int             num_pages = 0;
-	int             page = 0;
-
-	len = len;
-
-	if (tprlo->command != FC_ELS_ACC)
-		return FC_PARSE_ACC_INVAL;
-
-	num_pages = (bfa_os_ntohs(tprlo->payload_len) - 4) / 16;
-
-	for (page = 0; page < num_pages; page++) {
-		if (tprlo->tprlo_acc_params[page].type != FC_TYPE_FCP)
-			return FC_PARSE_NOT_FCP;
-		if (tprlo->tprlo_acc_params[page].opa_valid != 0)
-			return FC_PARSE_OPAFLAG_INVAL;
-		if (tprlo->tprlo_acc_params[page].rpa_valid != 0)
-			return FC_PARSE_RPAFLAG_INVAL;
-		if (tprlo->tprlo_acc_params[page].orig_process_assc != 0)
-			return FC_PARSE_OPA_INVAL;
-		if (tprlo->tprlo_acc_params[page].resp_process_assc != 0)
-			return FC_PARSE_RPA_INVAL;
-	}
-	return FC_PARSE_OK;
-}
-
-enum fc_parse_status
-fc_rrq_rsp_parse(struct fchs_s *fchs, int len)
-{
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-
-	len = len;
-	if (els_cmd->els_code != FC_ELS_ACC)
-		return FC_PARSE_FAILURE;
-
-	return FC_PARSE_OK;
-}
-
-u16
-fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, u32 reason_code,
-			u32 reason_expl)
-{
-	struct fc_ba_rjt_s    *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
-
-	fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
-
-	fchs->cat_info = FC_CAT_BA_RJT;
-	ba_rjt->reason_code = reason_code;
-	ba_rjt->reason_expl = reason_expl;
-	return sizeof(struct fc_ba_rjt_s);
-}
-
-static void
-fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
-{
-	bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s));
-	cthdr->rev_id = CT_GS3_REVISION;
-	cthdr->gs_type = CT_GSTYPE_DIRSERVICE;
-	cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER;
-	cthdr->cmd_rsp_code = bfa_os_htons(cmd_code);
-}
-
-static void
-fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
-{
-	bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s));
-	cthdr->rev_id = CT_GS3_REVISION;
-	cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
-	cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER;
-	cthdr->cmd_rsp_code = bfa_os_htons(cmd_code);
-}
-
-static void
-fc_gs_ms_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code,
-					 u8 sub_type)
-{
-	bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s));
-	cthdr->rev_id = CT_GS3_REVISION;
-	cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
-	cthdr->gs_sub_type = sub_type;
-	cthdr->cmd_rsp_code = bfa_os_htons(cmd_code);
-}
-
-u16
-fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
-	       wwn_t port_name)
-{
-
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_gidpn_req_s *gidpn =
-			(struct fcgs_gidpn_req_s *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
-	fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN);
-
-	bfa_os_memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s));
-	gidpn->port_name = port_name;
-	return sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
-	       u32 port_id)
-{
-
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
-	fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID);
-
-	bfa_os_memset(gpnid, 0, sizeof(fcgs_gpnid_req_t));
-	gpnid->dap = port_id;
-	return sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
-	       u32 port_id)
-{
-
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
-	fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID);
-
-	bfa_os_memset(gnnid, 0, sizeof(fcgs_gnnid_req_t));
-	gnnid->dap = port_id;
-	return sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
-{
-	if (bfa_os_ntohs(cthdr->cmd_rsp_code) != CT_RSP_ACCEPT) {
-		if (cthdr->reason_code == CT_RSN_LOGICAL_BUSY)
-			return FC_PARSE_BUSY;
-		else
-			return FC_PARSE_FAILURE;
-	}
-
-	return FC_PARSE_OK;
-}
-
-u16
-fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, u8 set_br_reg,
-			u32 s_id, u16 ox_id)
-{
-	u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
-
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-
-	bfa_os_memset(scr, 0, sizeof(struct fc_scr_s));
-	scr->command = FC_ELS_SCR;
-	scr->reg_func = FC_SCR_REG_FUNC_FULL;
-	if (set_br_reg)
-		scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE;
-
-	return sizeof(struct fc_scr_s);
-}
-
-u16
-fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id,
-			u16 ox_id)
-{
-	u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
-	u16        payldlen;
-
-	fc_els_req_build(fchs, d_id, s_id, ox_id);
-	rscn->command = FC_ELS_RSCN;
-	rscn->pagelen = sizeof(rscn->event[0]);
-
-	payldlen = sizeof(u32) + rscn->pagelen;
-	rscn->payldlen = bfa_os_htons(payldlen);
-
-	rscn->event[0].format = FC_RSCN_FORMAT_PORTID;
-	rscn->event[0].portid = s_id;
-
-	return sizeof(struct fc_rscn_pl_s);
-}
-
-u16
-fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
-	       enum bfa_port_role roles)
-{
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rftid_req_s *rftid =
-			(struct fcgs_rftid_req_s *) (cthdr + 1);
-	u32        type_value, d_id = bfa_os_hton3b(FC_NAME_SERVER);
-	u8         index;
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
-	fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
-
-	bfa_os_memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
-
-	rftid->dap = s_id;
-
-	/* By default, FCP FC4 Type is registered */
-	index = FC_TYPE_FCP >> 5;
-	type_value = 1 << (FC_TYPE_FCP % 32);
-	rftid->fc4_type[index] = bfa_os_htonl(type_value);
-
-	if (roles & BFA_PORT_ROLE_FCP_IPFC) {
-		index = FC_TYPE_IP >> 5;
-		type_value = 1 << (FC_TYPE_IP % 32);
-		rftid->fc4_type[index] |= bfa_os_htonl(type_value);
-	}
-
-	return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 ox_id, u8 *fc4_bitmap,
-			u32 bitmap_size)
-{
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rftid_req_s *rftid =
-			(struct fcgs_rftid_req_s *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
-	fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
-
-	bfa_os_memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
-
-	rftid->dap = s_id;
-	bfa_os_memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap,
-			(bitmap_size < 32 ? bitmap_size : 32));
-
-	return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
-	       u8 fc4_type, u8 fc4_ftrs)
-{
-	struct ct_hdr_s         *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rffid_req_s *rffid =
-			(struct fcgs_rffid_req_s *) (cthdr + 1);
-	u32         d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
-	fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID);
-
-	bfa_os_memset(rffid, 0, sizeof(struct fcgs_rffid_req_s));
-
-	rffid->dap 		 	= s_id;
-	rffid->fc4ftr_bits  = fc4_ftrs;
-	rffid->fc4_type		= fc4_type;
-
-	return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
-		u8 *name)
-{
-
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rspnid_req_s *rspnid =
-			(struct fcgs_rspnid_req_s *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
-	fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID);
-
-	bfa_os_memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s));
-
-	rspnid->dap = s_id;
-	rspnid->spn_len = (u8) strlen((char *)name);
-	strncpy((char *)rspnid->spn, (char *)name, rspnid->spn_len);
-
-	return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u8 fc4_type)
-{
-
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_gidft_req_s *gidft =
-			(struct fcgs_gidft_req_s *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
-
-	fc_gs_cthdr_build(cthdr, s_id, GS_GID_FT);
-
-	bfa_os_memset(gidft, 0, sizeof(struct fcgs_gidft_req_s));
-	gidft->fc4_type = fc4_type;
-	gidft->domain_id = 0;
-	gidft->area_id = 0;
-
-	return sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
-	       wwn_t port_name)
-{
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rpnid_req_s *rpnid =
-			(struct fcgs_rpnid_req_s *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
-	fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID);
-
-	bfa_os_memset(rpnid, 0, sizeof(struct fcgs_rpnid_req_s));
-	rpnid->port_id = port_id;
-	rpnid->port_name = port_name;
-
-	return sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
-	       wwn_t node_name)
-{
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rnnid_req_s *rnnid =
-			(struct fcgs_rnnid_req_s *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
-	fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID);
-
-	bfa_os_memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s));
-	rnnid->port_id = port_id;
-	rnnid->node_name = node_name;
-
-	return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
-	       u32 cos)
-{
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rcsid_req_s *rcsid =
-			(struct fcgs_rcsid_req_s *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
-	fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID);
-
-	bfa_os_memset(rcsid, 0, sizeof(struct fcgs_rcsid_req_s));
-	rcsid->port_id = port_id;
-	rcsid->cos = cos;
-
-	return sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
-	       u8 port_type)
-{
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rptid_req_s *rptid =
-			(struct fcgs_rptid_req_s *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
-	fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID);
-
-	bfa_os_memset(rptid, 0, sizeof(struct fcgs_rptid_req_s));
-	rptid->port_id = port_id;
-	rptid->port_type = port_type;
-
-	return sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
-{
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_ganxt_req_s *ganxt =
-			(struct fcgs_ganxt_req_s *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
-	fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT);
-
-	bfa_os_memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s));
-	ganxt->port_id = port_id;
-
-	return sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s);
-}
-
-/*
- * Builds fc hdr and ct hdr for FDMI requests.
- */
-u16
-fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-		     u16 cmd_code)
-{
-
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
-	fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code);
-
-	return sizeof(struct ct_hdr_s);
-}
-
-/*
- * Given a FC4 Type, this function returns a fc4 type bitmask
- */
-void
-fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask)
-{
-	u8         index;
-	u32       *ptr = (u32 *) bit_mask;
-	u32        type_value;
-
-	/*
-	 * @todo : Check for bitmask size
-	 */
-
-	index = fc4_type >> 5;
-	type_value = 1 << (fc4_type % 32);
-	ptr[index] = bfa_os_htonl(type_value);
-
-}
-
-/*
- * GMAL Request
- */
-u16
-fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
-{
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
-	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD,
-			CT_GSSUBTYPE_CFGSERVER);
-
-	bfa_os_memset(gmal, 0, sizeof(fcgs_gmal_req_t));
-	gmal->wwn = wwn;
-
-	return sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t);
-}
-
-/*
- * GFN (Get Fabric Name) Request
- */
-u16
-fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
-{
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
-
-	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
-	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD,
-			CT_GSSUBTYPE_CFGSERVER);
-
-	bfa_os_memset(gfn, 0, sizeof(fcgs_gfn_req_t));
-	gfn->wwn = wwn;
-
-	return sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t);
-}
diff --git a/drivers/scsi/bfa/fcbuild.h b/drivers/scsi/bfa/fcbuild.h
deleted file mode 100644
index 981d98d..0000000
--- a/drivers/scsi/bfa/fcbuild.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-/*
- * fcbuild.h - FC link service frame building and parsing routines
- */
-
-#ifndef __FCBUILD_H__
-#define __FCBUILD_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/fc.h>
-#include <protocol/fcp.h>
-#include <protocol/ct.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_pport.h>
-
-/*
- * Utility Macros/functions
- */
-
-#define fcif_sof_set(_ifhdr, _sof)	((_ifhdr)->sof = FC_ ## _sof)
-#define fcif_eof_set(_ifhdr, _eof)	((_ifhdr)->eof = FC_ ## _eof)
-
-#define wwn_is_equal(_wwn1, _wwn2)		\
-	(memcmp(&(_wwn1), &(_wwn2), sizeof(wwn_t)) == 0)
-
-#define fc_roundup(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1))
-
-/*
- * Given the fc response length, this routine will return
- * the length of the actual payload bytes following the CT header.
- *
- * Assumes the input response length does not include the crc, eof, etc.
- */
-static inline   u32
-fc_get_ctresp_pyld_len(u32 resp_len)
-{
-	return resp_len - sizeof(struct ct_hdr_s);
-}
-
-/*
- * Convert bfa speed to rpsc speed value.
- */
-static inline enum bfa_pport_speed
-fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed_s speed)
-{
-	switch (speed) {
-
-	case RPSC_OP_SPEED_1G:
-		return BFA_PPORT_SPEED_1GBPS;
-
-	case RPSC_OP_SPEED_2G:
-		return BFA_PPORT_SPEED_2GBPS;
-
-	case RPSC_OP_SPEED_4G:
-		return BFA_PPORT_SPEED_4GBPS;
-
-	case RPSC_OP_SPEED_8G:
-		return BFA_PPORT_SPEED_8GBPS;
-
-	case RPSC_OP_SPEED_10G:
-		return BFA_PPORT_SPEED_10GBPS;
-
-	default:
-		return BFA_PPORT_SPEED_UNKNOWN;
-	}
-}
-
-/*
- * Convert RPSC speed to bfa speed value.
- */
-static inline   enum fc_rpsc_op_speed_s
-fc_bfa_speed_to_rpsc_operspeed(enum bfa_pport_speed op_speed)
-{
-	switch (op_speed) {
-
-	case BFA_PPORT_SPEED_1GBPS:
-		return RPSC_OP_SPEED_1G;
-
-	case BFA_PPORT_SPEED_2GBPS:
-		return RPSC_OP_SPEED_2G;
-
-	case BFA_PPORT_SPEED_4GBPS:
-		return RPSC_OP_SPEED_4G;
-
-	case BFA_PPORT_SPEED_8GBPS:
-		return RPSC_OP_SPEED_8G;
-
-	case BFA_PPORT_SPEED_10GBPS:
-		return RPSC_OP_SPEED_10G;
-
-	default:
-		return RPSC_OP_SPEED_NOT_EST;
-	}
-}
-enum fc_parse_status {
-	FC_PARSE_OK = 0,
-	FC_PARSE_FAILURE = 1,
-	FC_PARSE_BUSY = 2,
-	FC_PARSE_LEN_INVAL,
-	FC_PARSE_ACC_INVAL,
-	FC_PARSE_PWWN_NOT_EQUAL,
-	FC_PARSE_NWWN_NOT_EQUAL,
-	FC_PARSE_RXSZ_INVAL,
-	FC_PARSE_NOT_FCP,
-	FC_PARSE_OPAFLAG_INVAL,
-	FC_PARSE_RPAFLAG_INVAL,
-	FC_PARSE_OPA_INVAL,
-	FC_PARSE_RPA_INVAL,
-
-};
-
-struct fc_templates_s {
-	struct fchs_s          fc_els_req;
-	struct fchs_s          fc_bls_req;
-	struct fc_logi_s      plogi;
-	struct fc_rrq_s        rrq;
-};
-
-void fcbuild_init(void);
-
-u16 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
-			u32 s_id, u16 ox_id, wwn_t port_name,
-			wwn_t node_name, u16 pdu_size, u8 set_npiv,
-			u8 set_auth, u16 local_bb_credits);
-u16 fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi,
-			u32 s_id, u16 ox_id, wwn_t port_name,
-			wwn_t node_name, u16 pdu_size);
-u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
-			u32 s_id, u16 ox_id, wwn_t port_name,
-			wwn_t node_name, u16 pdu_size,
-			u16 local_bb_credits);
-u16 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
-			u32 s_id, u16 ox_id, wwn_t port_name,
-			wwn_t node_name, u16 pdu_size);
-enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
-u16 fc_abts_build(struct fchs_s *buf, u32 d_id, u32 s_id,
-			u16 ox_id);
-enum fc_parse_status fc_abts_rsp_parse(struct fchs_s *buf, int len);
-u16 fc_rrq_build(struct fchs_s *buf, struct fc_rrq_s *rrq, u32 d_id,
-			u32 s_id, u16 ox_id, u16 rrq_oxid);
-enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len);
-u16 fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
-			u16 ox_id, u8 *name);
-u16 fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,
-			u16 ox_id, enum bfa_port_role role);
-u16 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 ox_id, u8 *fc4_bitmap,
-			u32 bitmap_size);
-u16 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 ox_id, u8 fc4_type, u8 fc4_ftrs);
-u16 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 ox_id, wwn_t port_name);
-u16 fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
-			u16 ox_id, u32 port_id);
-u16 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
-			u8 set_br_reg, u32 s_id, u16 ox_id);
-u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
-			u32 s_id, u16 ox_id,
-			wwn_t port_name, wwn_t node_name, u16 pdu_size);
-
-u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			wwn_t port_name, wwn_t node_name);
-enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld,
-			u32 host_dap,
-			wwn_t node_name, wwn_t port_name);
-enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len,
-			wwn_t port_name, wwn_t node_name);
-u16 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			wwn_t port_name, wwn_t node_name);
-u16 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt,
-			u32 d_id, u32 s_id, u16 ox_id,
-			u8 reason_code, u8 reason_code_expl);
-u16 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
-			u32 d_id, u32 s_id, u16 ox_id);
-u16 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id,
-			u32 s_id, u16 ox_id);
-enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len);
-
-u16 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
-			u32 s_id, u16 ox_id,
-			enum bfa_port_role role);
-u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
-			u32 d_id, u32 s_id, u16 ox_id,
-			u32 data_format);
-u16 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			u32 data_format,
-			struct fc_rnid_common_id_data_s *common_id_data,
-			struct fc_rnid_general_topology_data_s *
-			gen_topo_data);
-u16 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rps2c,
-			u32 d_id, u32 s_id,
-			u32 *pid_list, u16 npids);
-u16 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc,
-			u32 d_id, u32 s_id, u16 ox_id);
-u16 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			struct fc_rpsc_speed_info_s *oper_speed);
-u16 fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,
-			u8 fc4_type);
-u16 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u32 port_id, wwn_t port_name);
-u16 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u32 port_id, wwn_t node_name);
-u16 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u32 port_id, u32 cos);
-u16 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u32 port_id, u8 port_type);
-u16 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u32 port_id);
-u16 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo,
-			u32 d_id, u32 s_id, u16 ox_id,
-			wwn_t port_name);
-u16 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
-			u32 s_id, u16 ox_id);
-u16 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 cmd_code);
-u16 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			wwn_t wwn);
-u16 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			wwn_t wwn);
-void fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);
-void fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id);
-enum fc_parse_status fc_els_rsp_parse(struct fchs_s *fchs, int len);
-enum fc_parse_status fc_plogi_rsp_parse(struct fchs_s *fchs, int len,
-			 wwn_t port_name);
-enum fc_parse_status fc_prli_parse(struct fc_prli_s *prli);
-enum fc_parse_status fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name,
-			wwn_t port_name);
-u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			u16 rx_id);
-int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);
-u16 fc_tprlo_acc_build(struct fchs_s *fchs,
-			struct fc_tprlo_acc_s *tprlo_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			int num_pages);
-u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			int num_pages);
-u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len);
-u16 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, wwn_t port_name, wwn_t node_name,
-			u16 pdu_size);
-u16 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name);
-u16 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, int num_pages);
-u16 fc_prlo_rsp_parse(struct fchs_s *fchs, int len);
-u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, int num_pages,
-			enum fc_tprlo_type tprlo_type, u32 tpr_id);
-u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len);
-u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, u32 reason_code,
-			u32 reason_expl);
-u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 ox_id, u32 port_id);
-u16 fc_ct_rsp_parse(struct ct_hdr_s *cthdr);
-u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
-			u32 s_id, u16 ox_id);
-#endif
diff --git a/drivers/scsi/bfa/fcpim.c b/drivers/scsi/bfa/fcpim.c
deleted file mode 100644
index 6b8976a..0000000
--- a/drivers/scsi/bfa/fcpim.c
+++ /dev/null
@@ -1,824 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fcpim.c - FCP initiator mode i-t nexus state machine
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_fcpim.h"
-#include "fcs_rport.h"
-#include "fcs_lport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include <fcs/bfa_fcs_fcpim.h>
-#include <fcb/bfa_fcb_fcpim.h>
-#include <aen/bfa_aen_itnim.h>
-
-BFA_TRC_FILE(FCS, FCPIM);
-
-/*
- * forward declarations
- */
-static void     bfa_fcs_itnim_timeout(void *arg);
-static void     bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
-static void     bfa_fcs_itnim_send_prli(void *itnim_cbarg,
-					struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_itnim_prli_response(void *fcsarg,
-					    struct bfa_fcxp_s *fcxp,
-					    void *cbarg,
-					    bfa_status_t req_status,
-					    u32 rsp_len,
-					    u32 resid_len,
-					    struct fchs_s *rsp_fchs);
-static void     bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
-				       enum bfa_itnim_aen_event event);
-
-/**
- *  fcs_itnim_sm FCS itnim state machine events
- */
-
-enum bfa_fcs_itnim_event {
-	BFA_FCS_ITNIM_SM_ONLINE = 1,	/*  rport online event */
-	BFA_FCS_ITNIM_SM_OFFLINE = 2,	/*  rport offline */
-	BFA_FCS_ITNIM_SM_FRMSENT = 3,	/*  prli frame is sent */
-	BFA_FCS_ITNIM_SM_RSP_OK = 4,	/*  good response */
-	BFA_FCS_ITNIM_SM_RSP_ERROR = 5,	/*  error response */
-	BFA_FCS_ITNIM_SM_TIMEOUT = 6,	/*  delay timeout */
-	BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7,	/*  BFA online callback */
-	BFA_FCS_ITNIM_SM_HCB_ONLINE = 8,	/*  BFA offline callback */
-	BFA_FCS_ITNIM_SM_INITIATOR = 9,	/*  rport is initiator */
-	BFA_FCS_ITNIM_SM_DELETE = 10,	/*  delete event from rport */
-	BFA_FCS_ITNIM_SM_PRLO = 11,	/*  delete event from rport */
-};
-
-static void     bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
-					 enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
-					   enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
-				      enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
-					    enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
-					    enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
-					enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
-					     enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
-					   enum bfa_fcs_itnim_event event);
-
-static struct bfa_sm_table_s itnim_sm_table[] = {
-	{BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE},
-	{BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND},
-	{BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT},
-	{BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY},
-	{BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE},
-	{BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE},
-	{BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE},
-	{BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR},
-};
-
-/**
- *  fcs_itnim_sm FCS itnim state machine
- */
-
-static void
-bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
-			 enum bfa_fcs_itnim_event event)
-{
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_trc(itnim->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_ITNIM_SM_ONLINE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
-		itnim->prli_retries = 0;
-		bfa_fcs_itnim_send_prli(itnim, NULL);
-		break;
-
-	case BFA_FCS_ITNIM_SM_OFFLINE:
-		bfa_fcs_rport_itnim_ack(itnim->rport);
-		break;
-
-	case BFA_FCS_ITNIM_SM_INITIATOR:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
-		break;
-
-	case BFA_FCS_ITNIM_SM_DELETE:
-		bfa_fcs_itnim_free(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->fcs, event);
-	}
-
-}
-
-static void
-bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
-			   enum bfa_fcs_itnim_event event)
-{
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_trc(itnim->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_ITNIM_SM_FRMSENT:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli);
-		break;
-
-	case BFA_FCS_ITNIM_SM_INITIATOR:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
-		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
-		break;
-
-	case BFA_FCS_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
-		break;
-
-	case BFA_FCS_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
-		bfa_fcs_itnim_free(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
-		      enum bfa_fcs_itnim_event event)
-{
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_trc(itnim->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_ITNIM_SM_RSP_OK:
-		if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR) {
-			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
-		} else {
-			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
-			bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
-		}
-		break;
-
-	case BFA_FCS_ITNIM_SM_RSP_ERROR:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry);
-		bfa_timer_start(itnim->fcs->bfa, &itnim->timer,
-				bfa_fcs_itnim_timeout, itnim,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case BFA_FCS_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcxp_discard(itnim->fcxp);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
-		break;
-
-	case BFA_FCS_ITNIM_SM_INITIATOR:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
-		bfa_fcxp_discard(itnim->fcxp);
-		break;
-
-	case BFA_FCS_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcxp_discard(itnim->fcxp);
-		bfa_fcs_itnim_free(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
-			    enum bfa_fcs_itnim_event event)
-{
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_trc(itnim->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_ITNIM_SM_TIMEOUT:
-		if (itnim->prli_retries < BFA_FCS_RPORT_MAX_RETRIES) {
-			itnim->prli_retries++;
-			bfa_trc(itnim->fcs, itnim->prli_retries);
-			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
-			bfa_fcs_itnim_send_prli(itnim, NULL);
-		} else {
-			/* invoke target offline */
-			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-			bfa_fcs_rport_logo_imp(itnim->rport);
-		}
-		break;
-
-	case BFA_FCS_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_timer_stop(&itnim->timer);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
-		break;
-
-	case BFA_FCS_ITNIM_SM_INITIATOR:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
-		bfa_timer_stop(&itnim->timer);
-		break;
-
-	case BFA_FCS_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_timer_stop(&itnim->timer);
-		bfa_fcs_itnim_free(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
-			    enum bfa_fcs_itnim_event event)
-{
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_trc(itnim->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_ITNIM_SM_HCB_ONLINE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
-		bfa_fcb_itnim_online(itnim->itnim_drv);
-		bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);
-		break;
-
-	case BFA_FCS_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_itnim_offline(itnim->bfa_itnim);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
-		break;
-
-	case BFA_FCS_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcs_itnim_free(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
-			enum bfa_fcs_itnim_event event)
-{
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_trc(itnim->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
-		bfa_fcb_itnim_offline(itnim->itnim_drv);
-		bfa_itnim_offline(itnim->bfa_itnim);
-		if (bfa_fcs_port_is_online(itnim->rport->port) == BFA_TRUE)
-			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);
-		else
-			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);
-		break;
-
-	case BFA_FCS_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcs_itnim_free(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
-			     enum bfa_fcs_itnim_event event)
-{
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_trc(itnim->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_ITNIM_SM_HCB_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
-		break;
-
-	case BFA_FCS_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcs_itnim_free(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->fcs, event);
-	}
-}
-
-/*
- * This state is set when a discovered rport is also in intiator mode.
- * This ITN is marked as no_op and is not active and will not be truned into
- * online state.
- */
-static void
-bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
-			   enum bfa_fcs_itnim_event event)
-{
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_trc(itnim->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
-		break;
-
-	case BFA_FCS_ITNIM_SM_RSP_ERROR:
-	case BFA_FCS_ITNIM_SM_ONLINE:
-	case BFA_FCS_ITNIM_SM_INITIATOR:
-		break;
-
-	case BFA_FCS_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcs_itnim_free(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->fcs, event);
-	}
-}
-
-
-
-/**
- *  itnim_private FCS ITNIM private interfaces
- */
-
-static void
-bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
-		       enum bfa_itnim_aen_event event)
-{
-	struct bfa_fcs_rport_s *rport = itnim->rport;
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = rport->fcs->logm;
-	wwn_t           lpwwn = bfa_fcs_port_get_pwwn(rport->port);
-	wwn_t           rpwwn = rport->pwwn;
-	char            lpwwn_ptr[BFA_STRING_32];
-	char            rpwwn_ptr[BFA_STRING_32];
-
-	/*
-	 * Don't post events for well known addresses
-	 */
-	if (BFA_FCS_PID_IS_WKA(rport->pid))
-		return;
-
-	wwn2str(lpwwn_ptr, lpwwn);
-	wwn2str(rpwwn_ptr, rpwwn);
-
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, event),
-		rpwwn_ptr, lpwwn_ptr);
-
-	aen_data.itnim.vf_id = rport->port->fabric->vf_id;
-	aen_data.itnim.ppwwn =
-		bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(itnim->fcs));
-	aen_data.itnim.lpwwn = lpwwn;
-	aen_data.itnim.rpwwn = rpwwn;
-}
-
-static void
-bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_itnim_s *itnim = itnim_cbarg;
-	struct bfa_fcs_rport_s *rport = itnim->rport;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	int             len;
-
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		itnim->stats.fcxp_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
-				    bfa_fcs_itnim_send_prli, itnim);
-		return;
-	}
-	itnim->fcxp = fcxp;
-
-	len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), itnim->rport->pid,
-			    bfa_fcs_port_get_fcid(port), 0);
-
-	bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
-		      BFA_FALSE, FC_CLASS_3, len, &fchs,
-		      bfa_fcs_itnim_prli_response, (void *)itnim, FC_MAX_PDUSZ,
-		      FC_ELS_TOV);
-
-	itnim->stats.prli_sent++;
-	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
-}
-
-static void
-bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			    bfa_status_t req_status, u32 rsp_len,
-			    u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
-	struct fc_els_cmd_s   *els_cmd;
-	struct fc_prli_s      *prli_resp;
-	struct fc_ls_rjt_s    *ls_rjt;
-	struct fc_prli_params_s *sparams;
-
-	bfa_trc(itnim->fcs, req_status);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		itnim->stats.prli_rsp_err++;
-		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
-		return;
-	}
-
-	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-	if (els_cmd->els_code == FC_ELS_ACC) {
-		prli_resp = (struct fc_prli_s *) els_cmd;
-
-		if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) {
-			bfa_trc(itnim->fcs, rsp_len);
-			/*
-			 * Check if this  r-port is also in Initiator mode.
-			 * If so, we need to set this ITN as a no-op.
-			 */
-			if (prli_resp->parampage.servparams.initiator) {
-				bfa_trc(itnim->fcs, prli_resp->parampage.type);
-				itnim->rport->scsi_function =
-					BFA_RPORT_INITIATOR;
-				itnim->stats.prli_rsp_acc++;
-				bfa_sm_send_event(itnim,
-						  BFA_FCS_ITNIM_SM_RSP_OK);
-				return;
-			}
-
-			itnim->stats.prli_rsp_parse_err++;
-			return;
-		}
-		itnim->rport->scsi_function = BFA_RPORT_TARGET;
-
-		sparams = &prli_resp->parampage.servparams;
-		itnim->seq_rec = sparams->retry;
-		itnim->rec_support = sparams->rec_support;
-		itnim->task_retry_id = sparams->task_retry_id;
-		itnim->conf_comp = sparams->confirm;
-
-		itnim->stats.prli_rsp_acc++;
-		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
-	} else {
-		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-		bfa_trc(itnim->fcs, ls_rjt->reason_code);
-		bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
-
-		itnim->stats.prli_rsp_rjt++;
-		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
-	}
-}
-
-static void
-bfa_fcs_itnim_timeout(void *arg)
-{
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)arg;
-
-	itnim->stats.timeout++;
-	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
-}
-
-static void
-bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
-{
-	bfa_itnim_delete(itnim->bfa_itnim);
-	bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
-}
-
-
-
-/**
- *  itnim_public FCS ITNIM public interfaces
- */
-
-/**
- * 	Called by rport when a new rport is created.
- *
- * @param[in] rport	-  remote port.
- */
-struct bfa_fcs_itnim_s *
-bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-	struct bfa_fcs_itnim_s *itnim;
-	struct bfad_itnim_s *itnim_drv;
-	struct bfa_itnim_s *bfa_itnim;
-
-	/*
-	 * call bfad to allocate the itnim
-	 */
-	bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv);
-	if (itnim == NULL) {
-		bfa_trc(port->fcs, rport->pwwn);
-		return NULL;
-	}
-
-	/*
-	 * Initialize itnim
-	 */
-	itnim->rport = rport;
-	itnim->fcs = rport->fcs;
-	itnim->itnim_drv = itnim_drv;
-
-	/*
-	 * call BFA to create the itnim
-	 */
-	bfa_itnim = bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
-
-	if (bfa_itnim == NULL) {
-		bfa_trc(port->fcs, rport->pwwn);
-		bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
-		bfa_assert(0);
-		return NULL;
-	}
-
-	itnim->bfa_itnim = bfa_itnim;
-	itnim->seq_rec = BFA_FALSE;
-	itnim->rec_support = BFA_FALSE;
-	itnim->conf_comp = BFA_FALSE;
-	itnim->task_retry_id = BFA_FALSE;
-
-	/*
-	 * Set State machine
-	 */
-	bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-
-	return itnim;
-}
-
-/**
- * 	Called by rport to delete  the instance of FCPIM.
- *
- * @param[in] rport	-  remote port.
- */
-void
-bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
-{
-	bfa_trc(itnim->fcs, itnim->rport->pid);
-	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE);
-}
-
-/**
- * Notification from rport that PLOGI is complete to initiate FC-4 session.
- */
-void
-bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim)
-{
-	itnim->stats.onlines++;
-
-	if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) {
-		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE);
-	} else {
-		/*
-		 * For well known addresses, we set the itnim to initiator
-		 * state
-		 */
-		itnim->stats.initiator++;
-		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
-	}
-}
-
-/**
- * Called by rport to handle a remote device offline.
- */
-void
-bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim)
-{
-	itnim->stats.offlines++;
-	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE);
-}
-
-/**
- * Called by rport when remote port is known to be an initiator from
- * PRLI received.
- */
-void
-bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim)
-{
-	bfa_trc(itnim->fcs, itnim->rport->pid);
-	itnim->stats.initiator++;
-	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
-}
-
-/**
- * Called by rport to check if the itnim is online.
- */
-bfa_status_t
-bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
-{
-	bfa_trc(itnim->fcs, itnim->rport->pid);
-	switch (bfa_sm_to_state(itnim_sm_table, itnim->sm)) {
-	case BFA_ITNIM_ONLINE:
-	case BFA_ITNIM_INITIATIOR:
-		return BFA_STATUS_OK;
-
-	default:
-		return BFA_STATUS_NO_FCPIM_NEXUS;
-
-	}
-}
-
-/**
- * BFA completion callback for bfa_itnim_online().
- */
-void
-bfa_cb_itnim_online(void *cbarg)
-{
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
-
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
-}
-
-/**
- * BFA completion callback for bfa_itnim_offline().
- */
-void
-bfa_cb_itnim_offline(void *cb_arg)
-{
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
-
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
-}
-
-/**
- * Mark the beginning of PATH TOV handling. IO completion callbacks
- * are still pending.
- */
-void
-bfa_cb_itnim_tov_begin(void *cb_arg)
-{
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
-
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-}
-
-/**
- * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
- */
-void
-bfa_cb_itnim_tov(void *cb_arg)
-{
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
-
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_fcb_itnim_tov(itnim->itnim_drv);
-}
-
-/**
- * 		BFA notification to FCS/driver for second level error recovery.
- *
- * Atleast one I/O request has timedout and target is unresponsive to
- * repeated abort requests. Second level error recovery should be initiated
- * by starting implicit logout and recovery procedures.
- */
-void
-bfa_cb_itnim_sler(void *cb_arg)
-{
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
-
-	itnim->stats.sler++;
-	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_fcs_rport_logo_imp(itnim->rport);
-}
-
-struct bfa_fcs_itnim_s *
-bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
-{
-	struct bfa_fcs_rport_s *rport;
-	rport = bfa_fcs_rport_lookup(port, rpwwn);
-
-	if (!rport)
-		return NULL;
-
-	bfa_assert(rport->itnim != NULL);
-	return rport->itnim;
-}
-
-bfa_status_t
-bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
-		       struct bfa_itnim_attr_s *attr)
-{
-	struct bfa_fcs_itnim_s *itnim = NULL;
-
-	itnim = bfa_fcs_itnim_lookup(port, rpwwn);
-
-	if (itnim == NULL)
-		return BFA_STATUS_NO_FCPIM_NEXUS;
-
-	attr->state = bfa_sm_to_state(itnim_sm_table, itnim->sm);
-	attr->retry = itnim->seq_rec;
-	attr->rec_support = itnim->rec_support;
-	attr->conf_comp = itnim->conf_comp;
-	attr->task_retry_id = itnim->task_retry_id;
-	bfa_os_memset(&attr->io_latency, 0, sizeof(struct bfa_itnim_latency_s));
-
-	return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
-			struct bfa_itnim_stats_s *stats)
-{
-	struct bfa_fcs_itnim_s *itnim = NULL;
-
-	bfa_assert(port != NULL);
-
-	itnim = bfa_fcs_itnim_lookup(port, rpwwn);
-
-	if (itnim == NULL)
-		return BFA_STATUS_NO_FCPIM_NEXUS;
-
-	bfa_os_memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s));
-
-	return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port, wwn_t rpwwn)
-{
-	struct bfa_fcs_itnim_s *itnim = NULL;
-
-	bfa_assert(port != NULL);
-
-	itnim = bfa_fcs_itnim_lookup(port, rpwwn);
-
-	if (itnim == NULL)
-		return BFA_STATUS_NO_FCPIM_NEXUS;
-
-	bfa_os_memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s));
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
-		      u16 len)
-{
-	struct fc_els_cmd_s   *els_cmd;
-
-	bfa_trc(itnim->fcs, fchs->type);
-
-	if (fchs->type != FC_TYPE_ELS)
-		return;
-
-	els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-
-	bfa_trc(itnim->fcs, els_cmd->els_code);
-
-	switch (els_cmd->els_code) {
-	case FC_ELS_PRLO:
-		bfa_fcs_rport_prlo(itnim->rport, fchs->ox_id);
-		break;
-
-	default:
-		bfa_assert(0);
-	}
-}
-
-void
-bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim)
-{
-}
-
-void
-bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim)
-{
-}
diff --git a/drivers/scsi/bfa/fcptm.c b/drivers/scsi/bfa/fcptm.c
deleted file mode 100644
index 8c8b08c..0000000
--- a/drivers/scsi/bfa/fcptm.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- * This file contains dummy FCPTM routines to aid in Initiator Mode only
- * compilation of OS driver.
- *
- */
-
-#include "bfa_os_inc.h"
-#include "fcs_rport.h"
-#include "fcs_fcptm.h"
-#include "fcs/bfa_fcs_rport.h"
-
-struct bfa_fcs_tin_s *
-bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport)
-{
-	return NULL;
-}
-
-void
-bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len)
-{
-}
-
-void
-bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len)
-{
-}
-
-void
-bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin)
-{
-}
diff --git a/drivers/scsi/bfa/fcs.h b/drivers/scsi/bfa/fcs.h
deleted file mode 100644
index 8d08230..0000000
--- a/drivers/scsi/bfa/fcs.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fcs.h FCS module functions
- */
-
-
-#ifndef __FCS_H__
-#define __FCS_H__
-
-#define __fcs_min_cfg(__fcs)       ((__fcs)->min_cfg)
-
-void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);
-
-#endif /* __FCS_H__ */
diff --git a/drivers/scsi/bfa/fcs_auth.h b/drivers/scsi/bfa/fcs_auth.h
deleted file mode 100644
index 65d155f..0000000
--- a/drivers/scsi/bfa/fcs_auth.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fcs_uf.h FCS unsolicited frame receive
- */
-
-
-#ifndef __FCS_AUTH_H__
-#define __FCS_AUTH_H__
-
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <fcs/bfa_fcs_lport.h>
-
-/*
- * fcs friend functions: only between fcs modules
- */
-void bfa_fcs_auth_uf_recv(struct bfa_fcs_fabric_s *fabric, int len);
-void bfa_fcs_auth_start(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_auth_stop(struct bfa_fcs_fabric_s *fabric);
-
-#endif /* __FCS_UF_H__ */
diff --git a/drivers/scsi/bfa/fcs_fabric.h b/drivers/scsi/bfa/fcs_fabric.h
deleted file mode 100644
index 432ab8a..0000000
--- a/drivers/scsi/bfa/fcs_fabric.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fcs_lport.h FCS logical port interfaces
- */
-
-#ifndef __FCS_FABRIC_H__
-#define __FCS_FABRIC_H__
-
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <fcs/bfa_fcs_lport.h>
-
-#define BFA_FCS_BRCD_SWITCH_OUI  0x051e
-
-/*
-* fcs friend functions: only between fcs modules
- */
-void		bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs);
-void            bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);
-void            bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs);
-void            bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs);
-void            bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);
-void            bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);
-void            bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
-					struct bfa_fcs_vport_s *vport);
-void            bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
-					struct bfa_fcs_vport_s *vport);
-int             bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric);
-struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup(
-			struct bfa_fcs_fabric_s *fabric, wwn_t pwwn);
-void            bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
-void            bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
-			struct fchs_s *fchs, u16 len);
-u16        bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);
-bfa_boolean_t   bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric);
-bfa_boolean_t	bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric);
-enum bfa_pport_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric);
-void     	bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric);
-
-bfa_status_t bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf,
-			struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg,
-			struct bfad_vf_s *vf_drv);
-void bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric,
-			enum auth_status status);
-
-void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
-			wwn_t fabric_name);
-u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_get_sym_name(const struct bfa_fcs_s *fcs, char *node_symname);
-
-#endif /* __FCS_FABRIC_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcpim.h b/drivers/scsi/bfa/fcs_fcpim.h
deleted file mode 100644
index 11e6e7b..0000000
--- a/drivers/scsi/bfa/fcs_fcpim.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __FCS_FCPIM_H__
-#define __FCS_FCPIM_H__
-
-#include <defs/bfa_defs_port.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-
-/*
- * Following routines are from FCPIM and will be called by rport.
- */
-struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim);
-bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim);
-
-void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim);
-
-void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
-			u16 len);
-#endif /* __FCS_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcptm.h b/drivers/scsi/bfa/fcs_fcptm.h
deleted file mode 100644
index ffff082..0000000
--- a/drivers/scsi/bfa/fcs_fcptm.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __FCS_FCPTM_H__
-#define __FCS_FCPTM_H__
-
-#include <defs/bfa_defs_port.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-
-/*
- * Following routines are from FCPTM and will be called by rport.
- */
-struct bfa_fcs_tin_s *bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs,
-			u16 len);
-void bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin);
-
-/*
- * Modudle init/cleanup routines.
- */
-void bfa_fcs_fcptm_modinit(struct bfa_fcs_s *fcs);
-void bfa_fcs_fcptm_modexit(struct bfa_fcs_s *fcs);
-void bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs,
-			u16 len);
-
-#endif /* __FCS_FCPTM_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcxp.h b/drivers/scsi/bfa/fcs_fcxp.h
deleted file mode 100644
index 8277fe9..0000000
--- a/drivers/scsi/bfa/fcs_fcxp.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fcs_fcxp.h FCXP helper macros for FCS
- */
-
-
-#ifndef __FCS_FCXP_H__
-#define __FCS_FCXP_H__
-
-#define bfa_fcs_fcxp_alloc(__fcs)	\
-	bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL)
-
-#endif /* __FCS_FCXP_H__ */
diff --git a/drivers/scsi/bfa/fcs_lport.h b/drivers/scsi/bfa/fcs_lport.h
deleted file mode 100644
index a6508c8..0000000
--- a/drivers/scsi/bfa/fcs_lport.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fcs_lport.h FCS logical port interfaces
- */
-
-#ifndef __FCS_LPORT_H__
-#define __FCS_LPORT_H__
-
-#define __VPORT_H__
-#include <defs/bfa_defs_port.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <fcs_fabric.h>
-#include <fcs_ms.h>
-#include <cs/bfa_q.h>
-#include <fcbuild.h>
-
-/*
- * PID used in P2P/N2N ( In Big Endian)
- */
-#define N2N_LOCAL_PID	    0x010000
-#define N2N_REMOTE_PID		0x020000
-
-/*
- * Misc Timeouts
- */
-/*
- * To be used when spawning a timer before retrying a failed command. Milli
- * Secs.
- */
-#define	BFA_FCS_RETRY_TIMEOUT 2000
-
-/*
- * Check for Port/Vport Mode/Role
- */
-#define	BFA_FCS_VPORT_IS_INITIATOR_MODE(port) \
-		(port->port_cfg.roles & BFA_PORT_ROLE_FCP_IM)
-
-#define	BFA_FCS_VPORT_IS_TARGET_MODE(port) \
-		(port->port_cfg.roles & BFA_PORT_ROLE_FCP_TM)
-
-#define	BFA_FCS_VPORT_IS_IPFC_MODE(port) \
-		(port->port_cfg.roles & BFA_PORT_ROLE_FCP_IPFC)
-
-/*
- * Is this a Well Known Address
- */
-#define BFA_FCS_PID_IS_WKA(pid)  ((bfa_os_ntoh3b(pid) > 0xFFF000) ?  1 : 0)
-
-/*
- * Pointer to elements within Port
- */
-#define BFA_FCS_GET_HAL_FROM_PORT(port)  (port->fcs->bfa)
-#define BFA_FCS_GET_NS_FROM_PORT(port)  (&port->port_topo.pfab.ns)
-#define BFA_FCS_GET_SCN_FROM_PORT(port)  (&port->port_topo.pfab.scn)
-#define BFA_FCS_GET_MS_FROM_PORT(port)  (&port->port_topo.pfab.ms)
-#define BFA_FCS_GET_FDMI_FROM_PORT(port)  (&port->port_topo.pfab.ms.fdmi)
-
-/*
- * handler for unsolicied frames
- */
-void bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
-			u16 len);
-
-/*
- * Following routines will be called by Fabric to indicate port
- * online/offline to vport.
- */
-void bfa_fcs_lport_attach(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
-			uint16_t vf_id, struct bfa_fcs_vport_s *vport);
-void bfa_fcs_lport_init(struct bfa_fcs_port_s *lport,
-			struct bfa_port_cfg_s *port_cfg);
-void bfa_fcs_port_online(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_offline(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_delete(struct bfa_fcs_port_s *port);
-bfa_boolean_t   bfa_fcs_port_is_online(struct bfa_fcs_port_s *port);
-
-/*
- * Lookup rport based on PID
- */
-struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pid(
-			struct bfa_fcs_port_s *port, u32 pid);
-
-/*
- * Lookup rport based on PWWN
- */
-struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pwwn(
-			struct bfa_fcs_port_s *port, wwn_t pwwn);
-struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_nwwn(
-			struct bfa_fcs_port_s *port, wwn_t nwwn);
-void bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
-			struct bfa_fcs_rport_s *rport);
-void bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
-			struct bfa_fcs_rport_s *rport);
-
-void bfa_fcs_port_modinit(struct bfa_fcs_s *fcs);
-void bfa_fcs_port_modexit(struct bfa_fcs_s *fcs);
-void bfa_fcs_port_lip(struct bfa_fcs_port_s *port);
-
-#endif /* __FCS_LPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_ms.h b/drivers/scsi/bfa/fcs_ms.h
deleted file mode 100644
index b6a8c12..0000000
--- a/drivers/scsi/bfa/fcs_ms.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fcs_ms.h FCS ms interfaces
- */
-#ifndef __FCS_MS_H__
-#define __FCS_MS_H__
-
-/* MS FCS routines */
-void bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port);
-
-/* FDMI FCS routines */
-void bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms);
-void bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms);
-void bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms);
-
-#endif
diff --git a/drivers/scsi/bfa/fcs_port.h b/drivers/scsi/bfa/fcs_port.h
deleted file mode 100644
index 408c06a..0000000
--- a/drivers/scsi/bfa/fcs_port.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fcs_pport.h FCS physical port interfaces
- */
-
-
-#ifndef __FCS_PPORT_H__
-#define __FCS_PPORT_H__
-
-/*
- * fcs friend functions: only between fcs modules
- */
-void bfa_fcs_pport_attach(struct bfa_fcs_s *fcs);
-
-#endif /* __FCS_PPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_rport.h b/drivers/scsi/bfa/fcs_rport.h
deleted file mode 100644
index e634fb7..0000000
--- a/drivers/scsi/bfa/fcs_rport.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fcs_rport.h FCS rport interfaces and defines
- */
-
-#ifndef __FCS_RPORT_H__
-#define __FCS_RPORT_H__
-
-#include <fcs/bfa_fcs_rport.h>
-
-#define BFA_FCS_RPORT_MAX_RETRIES               (5)
-
-void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
-			u16 len);
-void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);
-
-struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_port_s *port,
-			u32 pid);
-void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
-			struct fc_logi_s *plogi_rsp);
-void bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port,
-			struct fchs_s *rx_fchs,
-			struct fc_logi_s *plogi);
-void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
-			struct fc_logi_s *plogi);
-void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id);
-void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport);
-int  bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport);
-struct bfa_fcs_rport_s *bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port,
-			wwn_t wwn);
-
-
-/* Rport Features */
-void  bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport);
-void  bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport);
-void  bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport);
-
-#endif /* __FCS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_trcmod.h b/drivers/scsi/bfa/fcs_trcmod.h
deleted file mode 100644
index 41b5ae8..0000000
--- a/drivers/scsi/bfa/fcs_trcmod.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fcs_trcmod.h BFA FCS trace modules
- */
-
-#ifndef __FCS_TRCMOD_H__
-#define __FCS_TRCMOD_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
-	BFA_TRC_FCS_FABRIC		= 1,
-	BFA_TRC_FCS_VFAPI		= 2,
-	BFA_TRC_FCS_PORT		= 3,
-	BFA_TRC_FCS_VPORT		= 4,
-	BFA_TRC_FCS_VP_API		= 5,
-	BFA_TRC_FCS_VPS			= 6,
-	BFA_TRC_FCS_RPORT		= 7,
-	BFA_TRC_FCS_FCPIM		= 8,
-	BFA_TRC_FCS_FCPTM		= 9,
-	BFA_TRC_FCS_NS			= 10,
-	BFA_TRC_FCS_SCN			= 11,
-	BFA_TRC_FCS_LOOP		= 12,
-	BFA_TRC_FCS_UF			= 13,
-	BFA_TRC_FCS_PPORT		= 14,
-	BFA_TRC_FCS_FCPIP		= 15,
-	BFA_TRC_FCS_PORT_API	= 16,
-	BFA_TRC_FCS_RPORT_API	= 17,
-	BFA_TRC_FCS_AUTH		= 18,
-	BFA_TRC_FCS_N2N			= 19,
-	BFA_TRC_FCS_MS			= 20,
-	BFA_TRC_FCS_FDMI		= 21,
-	BFA_TRC_FCS_RPORT_FTRS	= 22,
-};
-
-#endif /* __FCS_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/fcs_uf.h b/drivers/scsi/bfa/fcs_uf.h
deleted file mode 100644
index f591072..0000000
--- a/drivers/scsi/bfa/fcs_uf.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  fcs_uf.h FCS unsolicited frame receive
- */
-
-
-#ifndef __FCS_UF_H__
-#define __FCS_UF_H__
-
-/*
- * fcs friend functions: only between fcs modules
- */
-void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);
-
-#endif /* __FCS_UF_H__ */
diff --git a/drivers/scsi/bfa/fcs_vport.h b/drivers/scsi/bfa/fcs_vport.h
deleted file mode 100644
index bb647a4..0000000
--- a/drivers/scsi/bfa/fcs_vport.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __FCS_VPORT_H__
-#define __FCS_VPORT_H__
-
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <defs/bfa_defs_pci.h>
-
-void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport);
-
-#endif /* __FCS_VPORT_H__ */
-
diff --git a/drivers/scsi/bfa/fdmi.c b/drivers/scsi/bfa/fdmi.c
deleted file mode 100644
index 2b50eabf..0000000
--- a/drivers/scsi/bfa/fdmi.c
+++ /dev/null
@@ -1,1230 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  port_api.c BFA FCS port
- */
-
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "lport_priv.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include <fcs/bfa_fcs_fdmi.h>
-
-BFA_TRC_FILE(FCS, FDMI);
-
-#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
-
-/*
- * forward declarations
- */
-static void     bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg,
-					   struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_fdmi_rhba_response(void *fcsarg,
-						struct bfa_fcxp_s *fcxp,
-						void *cbarg,
-						bfa_status_t req_status,
-						u32 rsp_len,
-						u32 resid_len,
-						struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_fdmi_rprt_response(void *fcsarg,
-						struct bfa_fcxp_s *fcxp,
-						void *cbarg,
-						bfa_status_t req_status,
-						u32 rsp_len,
-						u32 resid_len,
-						struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_fdmi_rpa_response(void *fcsarg,
-					       struct bfa_fcxp_s *fcxp,
-					       void *cbarg,
-					       bfa_status_t req_status,
-					       u32 rsp_len,
-					       u32 resid_len,
-					       struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_fdmi_timeout(void *arg);
-static u16 bfa_fcs_port_fdmi_build_rhba_pyld(
-			struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static u16 bfa_fcs_port_fdmi_build_rprt_pyld(
-			struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static u16 bfa_fcs_port_fdmi_build_rpa_pyld(
-			struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static u16 bfa_fcs_port_fdmi_build_portattr_block(
-			struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
-			struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
-static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi,
-			struct bfa_fcs_fdmi_port_attr_s *port_attr);
-/**
- *  fcs_fdmi_sm FCS FDMI state machine
- */
-
-/**
- *  FDMI State Machine events
- */
-enum port_fdmi_event {
-	FDMISM_EVENT_PORT_ONLINE = 1,
-	FDMISM_EVENT_PORT_OFFLINE = 2,
-	FDMISM_EVENT_RSP_OK = 4,
-	FDMISM_EVENT_RSP_ERROR = 5,
-	FDMISM_EVENT_TIMEOUT = 6,
-	FDMISM_EVENT_RHBA_SENT = 7,
-	FDMISM_EVENT_RPRT_SENT = 8,
-	FDMISM_EVENT_RPA_SENT = 9,
-};
-
-static void bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void     bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void     bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void     bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void	bfa_fcs_port_fdmi_sm_disabled(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-
-/**
- * 		Start in offline state - awaiting MS to send start.
- */
-static void
-bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi,
-			     enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	fdmi->retry_cnt = 0;
-
-	switch (event) {
-	case FDMISM_EVENT_PORT_ONLINE:
-		if (port->vport) {
-			/*
-			 * For Vports, register a new port.
-			 */
-			bfa_sm_set_state(fdmi,
-					 bfa_fcs_port_fdmi_sm_sending_rprt);
-			bfa_fcs_port_fdmi_send_rprt(fdmi, NULL);
-		} else {
-			/*
-			 * For a base port, we should first register the HBA
-			 * atribute. The HBA attribute also contains the base
-			 *  port registration.
-			 */
-			bfa_sm_set_state(fdmi,
-					 bfa_fcs_port_fdmi_sm_sending_rhba);
-			bfa_fcs_port_fdmi_send_rhba(fdmi, NULL);
-		}
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
-				  enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RHBA_SENT:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
-				       &fdmi->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
-			  enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RSP_ERROR:
-		/*
-		 * if max retries have not been reached, start timer for a
-		 * delayed retry
-		 */
-		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba_retry);
-			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
-					&fdmi->timer, bfa_fcs_port_fdmi_timeout,
-					fdmi, BFA_FCS_RETRY_TIMEOUT);
-		} else {
-			/*
-			 * set state to offline
-			 */
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		}
-		break;
-
-	case FDMISM_EVENT_RSP_OK:
-		/*
-		 * Initiate Register Port Attributes
-		 */
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa);
-		fdmi->retry_cnt = 0;
-		bfa_fcs_port_fdmi_send_rpa(fdmi, NULL);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_fcxp_discard(fdmi->fcxp);
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-				enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rhba);
-		bfa_fcs_port_fdmi_send_rhba(fdmi, NULL);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_timer_stop(&fdmi->timer);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-/*
-* RPRT : Register Port
- */
-static void
-bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
-				  enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RPRT_SENT:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
-				       &fdmi->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
-			  enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RSP_ERROR:
-		/*
-		 * if max retries have not been reached, start timer for a
-		 * delayed retry
-		 */
-		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt_retry);
-			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
-					&fdmi->timer, bfa_fcs_port_fdmi_timeout,
-					fdmi, BFA_FCS_RETRY_TIMEOUT);
-
-		} else {
-			/*
-			 * set state to offline
-			 */
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-			fdmi->retry_cnt = 0;
-		}
-		break;
-
-	case FDMISM_EVENT_RSP_OK:
-		fdmi->retry_cnt = 0;
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_fcxp_discard(fdmi->fcxp);
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-				enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rprt);
-		bfa_fcs_port_fdmi_send_rprt(fdmi, NULL);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_timer_stop(&fdmi->timer);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-/*
- * Register Port Attributes
- */
-static void
-bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
-				 enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RPA_SENT:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
-				       &fdmi->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
-			 enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RSP_ERROR:
-		/*
-		 * if max retries have not been reached, start timer for a
-		 * delayed retry
-		 */
-		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa_retry);
-			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
-					&fdmi->timer, bfa_fcs_port_fdmi_timeout,
-					fdmi, BFA_FCS_RETRY_TIMEOUT);
-		} else {
-			/*
-			 * set state to offline
-			 */
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-			fdmi->retry_cnt = 0;
-		}
-		break;
-
-	case FDMISM_EVENT_RSP_OK:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online);
-		fdmi->retry_cnt = 0;
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_fcxp_discard(fdmi->fcxp);
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-			       enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa);
-		bfa_fcs_port_fdmi_send_rpa(fdmi, NULL);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_timer_stop(&fdmi->timer);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi,
-			    enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-/**
- *  FDMI is disabled state.
- */
-static void
-bfa_fcs_port_fdmi_sm_disabled(struct bfa_fcs_port_fdmi_s *fdmi,
-				enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	/* No op State. It can only be enabled at Driver Init. */
-}
-
-/**
-*   RHBA : Register HBA Attributes.
- */
-static void
-bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct fchs_s          fchs;
-	int             len, attr_len;
-	struct bfa_fcxp_s *fcxp;
-	u8        *pyld;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-				    bfa_fcs_port_fdmi_send_rhba, fdmi);
-		return;
-	}
-	fdmi->fcxp = fcxp;
-
-	pyld = bfa_fcxp_get_reqbuf(fcxp);
-	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
-
-	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
-				   FDMI_RHBA);
-
-	attr_len = bfa_fcs_port_fdmi_build_rhba_pyld(fdmi,
-			(u8 *) ((struct ct_hdr_s *) pyld + 1));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, (len + attr_len), &fchs,
-		      bfa_fcs_port_fdmi_rhba_response, (void *)fdmi,
-		      FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
-}
-
-static          u16
-bfa_fcs_port_fdmi_build_rhba_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
-				  u8 *pyld)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct bfa_fcs_fdmi_hba_attr_s hba_attr;	/* @todo */
-	struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr; /* @todo */
-	struct fdmi_rhba_s    *rhba = (struct fdmi_rhba_s *) pyld;
-	struct fdmi_attr_s    *attr;
-	u8        *curr_ptr;
-	u16        len, count;
-
-	/*
-	 * get hba attributes
-	 */
-	bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
-
-	rhba->hba_id = bfa_fcs_port_get_pwwn(port);
-	rhba->port_list.num_ports = bfa_os_htonl(1);
-	rhba->port_list.port_entry = bfa_fcs_port_get_pwwn(port);
-
-	len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
-
-	count = 0;
-	len += sizeof(rhba->hba_attr_blk.attr_count);
-
-	/*
-	 * fill out the invididual entries of the HBA attrib Block
-	 */
-	curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
-
-	/*
-	 * Node Name
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_NODENAME);
-	attr->len = sizeof(wwn_t);
-	memcpy(attr->value, &bfa_fcs_port_get_nwwn(port), attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Manufacturer
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MANUFACTURER);
-	attr->len = (u16) strlen(fcs_hba_attr->manufacturer);
-	memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Serial Number
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_SERIALNUM);
-	attr->len = (u16) strlen(fcs_hba_attr->serial_num);
-	memcpy(attr->value, fcs_hba_attr->serial_num, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Model
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL);
-	attr->len = (u16) strlen(fcs_hba_attr->model);
-	memcpy(attr->value, fcs_hba_attr->model, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Model Desc
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL_DESC);
-	attr->len = (u16) strlen(fcs_hba_attr->model_desc);
-	memcpy(attr->value, fcs_hba_attr->model_desc, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * H/W Version
-	 */
-	if (fcs_hba_attr->hw_version[0] != '\0') {
-		attr = (struct fdmi_attr_s *) curr_ptr;
-		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_HW_VERSION);
-		attr->len = (u16) strlen(fcs_hba_attr->hw_version);
-		memcpy(attr->value, fcs_hba_attr->hw_version, attr->len);
-		/* variable fields need to be 4 byte aligned */
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
-		count++;
-		attr->len =
-			bfa_os_htons(attr->len + sizeof(attr->type) +
-				     sizeof(attr->len));
-	}
-
-	/*
-	 * Driver Version
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_DRIVER_VERSION);
-	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
-	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Option Rom Version
-	 */
-	if (fcs_hba_attr->option_rom_ver[0] != '\0') {
-		attr = (struct fdmi_attr_s *) curr_ptr;
-		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_ROM_VERSION);
-		attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver);
-		memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len);
-		/* variable fields need to be 4 byte aligned */
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
-		count++;
-		attr->len =
-			bfa_os_htons(attr->len + sizeof(attr->type) +
-				     sizeof(attr->len));
-	}
-
-	/*
-	 * f/w Version = driver version
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_FW_VERSION);
-	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
-	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * OS Name
-	 */
-	if (fcs_hba_attr->os_name[0] != '\0') {
-		attr = (struct fdmi_attr_s *) curr_ptr;
-		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_OS_NAME);
-		attr->len = (u16) strlen(fcs_hba_attr->os_name);
-		memcpy(attr->value, fcs_hba_attr->os_name, attr->len);
-		/* variable fields need to be 4 byte aligned */
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
-		count++;
-		attr->len =
-			bfa_os_htons(attr->len + sizeof(attr->type) +
-				     sizeof(attr->len));
-	}
-
-	/*
-	 * MAX_CT_PAYLOAD
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MAX_CT);
-	attr->len = sizeof(fcs_hba_attr->max_ct_pyld);
-	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len);
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Update size of payload
-	 */
-	len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
-
-	rhba->hba_attr_blk.attr_count = bfa_os_htonl(count);
-	return len;
-}
-
-static void
-bfa_fcs_port_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				void *cbarg, bfa_status_t req_status,
-				u32 rsp_len, u32 resid_len,
-				struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
-		return;
-	}
-
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-}
-
-/**
-*   RPRT : Register Port
- */
-static void
-bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct fchs_s          fchs;
-	u16        len, attr_len;
-	struct bfa_fcxp_s *fcxp;
-	u8        *pyld;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-				    bfa_fcs_port_fdmi_send_rprt, fdmi);
-		return;
-	}
-	fdmi->fcxp = fcxp;
-
-	pyld = bfa_fcxp_get_reqbuf(fcxp);
-	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
-
-	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
-				   FDMI_RPRT);
-
-	attr_len = bfa_fcs_port_fdmi_build_rprt_pyld(fdmi,
-			(u8 *) ((struct ct_hdr_s *) pyld + 1));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len + attr_len, &fchs,
-		      bfa_fcs_port_fdmi_rprt_response, (void *)fdmi,
-		      FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
-}
-
-/**
- * This routine builds Port Attribute Block that used in RPA, RPRT commands.
- */
-static          u16
-bfa_fcs_port_fdmi_build_portattr_block(struct bfa_fcs_port_fdmi_s *fdmi,
-				       u8 *pyld)
-{
-	struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
-	struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
-	struct fdmi_attr_s    *attr;
-	u8        *curr_ptr;
-	u16        len;
-	u8         count = 0;
-
-	/*
-	 * get port attributes
-	 */
-	bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
-
-	len = sizeof(port_attrib->attr_count);
-
-	/*
-	 * fill out the invididual entries
-	 */
-	curr_ptr = (u8 *) &port_attrib->port_attr;
-
-	/*
-	 * FC4 Types
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FC4_TYPES);
-	attr->len = sizeof(fcs_port_attr.supp_fc4_types);
-	memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	++count;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Supported Speed
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_SUPP_SPEED);
-	attr->len = sizeof(fcs_port_attr.supp_speed);
-	memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	++count;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * current Port Speed
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_PORT_SPEED);
-	attr->len = sizeof(fcs_port_attr.curr_speed);
-	memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	++count;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * max frame size
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FRAME_SIZE);
-	attr->len = sizeof(fcs_port_attr.max_frm_size);
-	memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	++count;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * OS Device Name
-	 */
-	if (fcs_port_attr.os_device_name[0] != '\0') {
-		attr = (struct fdmi_attr_s *) curr_ptr;
-		attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_DEV_NAME);
-		attr->len = (u16) strlen(fcs_port_attr.os_device_name);
-		memcpy(attr->value, fcs_port_attr.os_device_name, attr->len);
-		/* variable fields need to be 4 byte aligned */
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
-		++count;
-		attr->len =
-			bfa_os_htons(attr->len + sizeof(attr->type) +
-				     sizeof(attr->len));
-
-	}
-	/*
-	 * Host Name
-	 */
-	if (fcs_port_attr.host_name[0] != '\0') {
-		attr = (struct fdmi_attr_s *) curr_ptr;
-		attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_HOST_NAME);
-		attr->len = (u16) strlen(fcs_port_attr.host_name);
-		memcpy(attr->value, fcs_port_attr.host_name, attr->len);
-		/* variable fields need to be 4 byte aligned */
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
-		++count;
-		attr->len =
-			bfa_os_htons(attr->len + sizeof(attr->type) +
-				     sizeof(attr->len));
-
-	}
-
-	/*
-	 * Update size of payload
-	 */
-	port_attrib->attr_count = bfa_os_htonl(count);
-	len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
-	return len;
-}
-
-static          u16
-bfa_fcs_port_fdmi_build_rprt_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
-				  u8 *pyld)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct fdmi_rprt_s    *rprt = (struct fdmi_rprt_s *) pyld;
-	u16        len;
-
-	rprt->hba_id = bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
-	rprt->port_name = bfa_fcs_port_get_pwwn(port);
-
-	len = bfa_fcs_port_fdmi_build_portattr_block(fdmi,
-			(u8 *) &rprt->port_attr_blk);
-
-	len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
-
-	return len;
-}
-
-static void
-bfa_fcs_port_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				void *cbarg, bfa_status_t req_status,
-				u32 rsp_len, u32 resid_len,
-				struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
-		return;
-	}
-
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-}
-
-/**
-*   RPA : Register Port Attributes.
- */
-static void
-bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct fchs_s          fchs;
-	u16        len, attr_len;
-	struct bfa_fcxp_s *fcxp;
-	u8        *pyld;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-				    bfa_fcs_port_fdmi_send_rpa, fdmi);
-		return;
-	}
-	fdmi->fcxp = fcxp;
-
-	pyld = bfa_fcxp_get_reqbuf(fcxp);
-	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
-
-	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
-				   FDMI_RPA);
-
-	attr_len = bfa_fcs_port_fdmi_build_rpa_pyld(fdmi,
-			(u8 *) ((struct ct_hdr_s *) pyld + 1));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len + attr_len, &fchs,
-		      bfa_fcs_port_fdmi_rpa_response, (void *)fdmi,
-		      FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
-}
-
-static          u16
-bfa_fcs_port_fdmi_build_rpa_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
-				 u8 *pyld)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct fdmi_rpa_s     *rpa = (struct fdmi_rpa_s *) pyld;
-	u16        len;
-
-	rpa->port_name = bfa_fcs_port_get_pwwn(port);
-
-	len = bfa_fcs_port_fdmi_build_portattr_block(fdmi,
-			(u8 *) &rpa->port_attr_blk);
-
-	len += sizeof(rpa->port_name);
-
-	return len;
-}
-
-static void
-bfa_fcs_port_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-			       void *cbarg, bfa_status_t req_status,
-			       u32 rsp_len, u32 resid_len,
-			       struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
-		return;
-	}
-
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-}
-
-static void
-bfa_fcs_port_fdmi_timeout(void *arg)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)arg;
-
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
-}
-
-static void
-bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
-			 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
-
-	bfa_os_memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
-
-	bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
-		hba_attr->manufacturer);
-	bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
-						hba_attr->serial_num);
-	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, hba_attr->model);
-	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, hba_attr->model_desc);
-	bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc, hba_attr->hw_version);
-	bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
-		hba_attr->option_rom_ver);
-	bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc, hba_attr->fw_version);
-
-	strncpy(hba_attr->driver_version, (char *)driver_info->version,
-		sizeof(hba_attr->driver_version));
-
-	strncpy(hba_attr->os_name, driver_info->host_os_name,
-		sizeof(hba_attr->os_name));
-
-	/*
-	 * If there is a patch level, append it to the os name along with a
-	 * separator
-	 */
-	if (driver_info->host_os_patch[0] != '\0') {
-		strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-		strncat(hba_attr->os_name, driver_info->host_os_patch,
-			sizeof(driver_info->host_os_patch));
-	}
-
-	hba_attr->max_ct_pyld = bfa_os_htonl(FC_MAX_PDUSZ);
-
-}
-
-static void
-bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi,
-			  struct bfa_fcs_fdmi_port_attr_s *port_attr)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
-	struct bfa_pport_attr_s pport_attr;
-
-	bfa_os_memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
-
-	/*
-	 * get pport attributes from hal
-	 */
-	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
-
-	/*
-	 * get FC4 type Bitmask
-	 */
-	fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
-
-	/*
-	 * Supported Speeds
-	 */
-	port_attr->supp_speed = bfa_os_htonl(BFA_FCS_FDMI_SUPORTED_SPEEDS);
-
-	/*
-	 * Current Speed
-	 */
-	port_attr->curr_speed = bfa_os_htonl(pport_attr.speed);
-
-	/*
-	 * Max PDU Size.
-	 */
-	port_attr->max_frm_size = bfa_os_htonl(FC_MAX_PDUSZ);
-
-	/*
-	 * OS device Name
-	 */
-	strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
-		sizeof(port_attr->os_device_name));
-
-	/*
-	 * Host name
-	 */
-	strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
-		sizeof(port_attr->host_name));
-
-}
-
-
-void
-bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
-
-	fdmi->ms = ms;
-	if (ms->port->fcs->fdmi_enabled)
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-	else
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_disabled);
-}
-
-void
-bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
-
-	fdmi->ms = ms;
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
-}
-
-void
-bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
-
-	fdmi->ms = ms;
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
-}
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen.h b/drivers/scsi/bfa/include/aen/bfa_aen.h
deleted file mode 100644
index 6abbab0..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_AEN_H__
-#define __BFA_AEN_H__
-
-#include "defs/bfa_defs_aen.h"
-#include "defs/bfa_defs_status.h"
-#include "cs/bfa_debug.h"
-
-#define BFA_AEN_MAX_ENTRY	512
-
-extern int bfa_aen_max_cfg_entry;
-struct bfa_aen_s {
-	void		*bfad;
-	int		max_entry;
-	int		write_index;
-	int		read_index;
-	int		bfad_num;
-	int		seq_num;
-	void		(*aen_cb_notify)(void *bfad);
-	void		(*gettimeofday)(struct bfa_timeval_s *tv);
-	struct bfa_trc_mod_s *trcmod;
-	int		app_ri[BFA_AEN_MAX_APP]; /* For multiclient support */
-	struct bfa_aen_entry_s list[BFA_AEN_MAX_ENTRY]; /* Must be the last */
-};
-
-
-/**
- * Public APIs
- */
-static inline void
-bfa_aen_set_max_cfg_entry(int max_entry)
-{
-	bfa_aen_max_cfg_entry = max_entry;
-}
-
-static inline int
-bfa_aen_get_max_cfg_entry(void)
-{
-	return bfa_aen_max_cfg_entry;
-}
-
-static inline int
-bfa_aen_get_meminfo(void)
-{
-	return sizeof(struct bfa_aen_entry_s) * bfa_aen_get_max_cfg_entry();
-}
-
-static inline int
-bfa_aen_get_wi(struct bfa_aen_s *aen)
-{
-	return aen->write_index;
-}
-
-static inline int
-bfa_aen_get_ri(struct bfa_aen_s *aen)
-{
-	return aen->read_index;
-}
-
-static inline int
-bfa_aen_fetch_count(struct bfa_aen_s *aen, enum bfa_aen_app  app_id)
-{
-	bfa_assert((app_id < BFA_AEN_MAX_APP) && (app_id >= bfa_aen_app_bcu));
-	return ((aen->write_index + aen->max_entry) - aen->app_ri[app_id])
-		% aen->max_entry;
-}
-
-int bfa_aen_init(struct bfa_aen_s *aen, struct bfa_trc_mod_s *trcmod,
-		void *bfad, int bfad_num, void (*aen_cb_notify)(void *),
-		void (*gettimeofday)(struct bfa_timeval_s *));
-
-void bfa_aen_post(struct bfa_aen_s *aen, enum bfa_aen_category aen_category,
-		     int aen_type, union bfa_aen_data_u *aen_data);
-
-bfa_status_t bfa_aen_fetch(struct bfa_aen_s *aen,
-			struct bfa_aen_entry_s *aen_entry,
-			int entry_req, enum bfa_aen_app app_id, int *entry_ret);
-
-int bfa_aen_get_inst(struct bfa_aen_s *aen);
-
-#endif /* __BFA_AEN_H__ */
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h b/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h
deleted file mode 100644
index 260d3ea..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_ADAPTER Module */
-#ifndef	__bfa_aen_adapter_h__
-#define	__bfa_aen_adapter_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_ADAPTER_ADD \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ADAPTER, BFA_ADAPTER_AEN_ADD)
-#define BFA_AEN_ADAPTER_REMOVE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ADAPTER, BFA_ADAPTER_AEN_REMOVE)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_audit.h b/drivers/scsi/bfa/include/aen/bfa_aen_audit.h
deleted file mode 100644
index 12cd7aa..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_audit.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_AUDIT Module */
-#ifndef	__bfa_aen_audit_h__
-#define	__bfa_aen_audit_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_AUDIT_AUTH_ENABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_AUDIT, BFA_AUDIT_AEN_AUTH_ENABLE)
-#define BFA_AEN_AUDIT_AUTH_DISABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_AUDIT, BFA_AUDIT_AEN_AUTH_DISABLE)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h b/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h
deleted file mode 100644
index 507d0b5..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_ETHPORT Module */
-#ifndef	__bfa_aen_ethport_h__
-#define	__bfa_aen_ethport_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_ETHPORT_LINKUP \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_LINKUP)
-#define BFA_AEN_ETHPORT_LINKDOWN \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_LINKDOWN)
-#define BFA_AEN_ETHPORT_ENABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_ENABLE)
-#define BFA_AEN_ETHPORT_DISABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_DISABLE)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h b/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h
deleted file mode 100644
index 4daf96f..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_IOC Module */
-#ifndef	__bfa_aen_ioc_h__
-#define	__bfa_aen_ioc_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_IOC_HBGOOD \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_HBGOOD)
-#define BFA_AEN_IOC_HBFAIL \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_HBFAIL)
-#define BFA_AEN_IOC_ENABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_ENABLE)
-#define BFA_AEN_IOC_DISABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_DISABLE)
-#define BFA_AEN_IOC_FWMISMATCH \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_FWMISMATCH)
-#define BFA_AEN_IOC_FWCFG_ERROR \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_FWCFG_ERROR)
-#define BFA_AEN_IOC_INVALID_VENDOR      \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_VENDOR)
-#define BFA_AEN_IOC_INVALID_NWWN        \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_NWWN)
-#define BFA_AEN_IOC_INVALID_PWWN        \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_PWWN)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h b/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h
deleted file mode 100644
index a7d8ddc..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_ITNIM Module */
-#ifndef	__bfa_aen_itnim_h__
-#define	__bfa_aen_itnim_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_ITNIM_ONLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_ONLINE)
-#define BFA_AEN_ITNIM_OFFLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_OFFLINE)
-#define BFA_AEN_ITNIM_DISCONNECT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_DISCONNECT)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_lport.h b/drivers/scsi/bfa/include/aen/bfa_aen_lport.h
deleted file mode 100644
index 5a8ebb6..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_lport.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_LPORT Module */
-#ifndef	__bfa_aen_lport_h__
-#define	__bfa_aen_lport_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_LPORT_NEW \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW)
-#define BFA_AEN_LPORT_DELETE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE)
-#define BFA_AEN_LPORT_ONLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_ONLINE)
-#define BFA_AEN_LPORT_OFFLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_OFFLINE)
-#define BFA_AEN_LPORT_DISCONNECT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DISCONNECT)
-#define BFA_AEN_LPORT_NEW_PROP \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW_PROP)
-#define BFA_AEN_LPORT_DELETE_PROP \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE_PROP)
-#define BFA_AEN_LPORT_NEW_STANDARD \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW_STANDARD)
-#define BFA_AEN_LPORT_DELETE_STANDARD \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE_STANDARD)
-#define BFA_AEN_LPORT_NPIV_DUP_WWN \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_DUP_WWN)
-#define BFA_AEN_LPORT_NPIV_FABRIC_MAX \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_FABRIC_MAX)
-#define BFA_AEN_LPORT_NPIV_UNKNOWN \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_UNKNOWN)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_port.h b/drivers/scsi/bfa/include/aen/bfa_aen_port.h
deleted file mode 100644
index 9add905..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_port.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_PORT Module */
-#ifndef	__bfa_aen_port_h__
-#define	__bfa_aen_port_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_PORT_ONLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_ONLINE)
-#define BFA_AEN_PORT_OFFLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_OFFLINE)
-#define BFA_AEN_PORT_RLIR \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_RLIR)
-#define BFA_AEN_PORT_SFP_INSERT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_INSERT)
-#define BFA_AEN_PORT_SFP_REMOVE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_REMOVE)
-#define BFA_AEN_PORT_SFP_POM \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_POM)
-#define BFA_AEN_PORT_ENABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_ENABLE)
-#define BFA_AEN_PORT_DISABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_DISABLE)
-#define BFA_AEN_PORT_AUTH_ON \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_AUTH_ON)
-#define BFA_AEN_PORT_AUTH_OFF \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_AUTH_OFF)
-#define BFA_AEN_PORT_DISCONNECT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_DISCONNECT)
-#define BFA_AEN_PORT_QOS_NEG \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_QOS_NEG)
-#define BFA_AEN_PORT_FABRIC_NAME_CHANGE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_FABRIC_NAME_CHANGE)
-#define BFA_AEN_PORT_SFP_ACCESS_ERROR \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_ACCESS_ERROR)
-#define BFA_AEN_PORT_SFP_UNSUPPORT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_UNSUPPORT)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_rport.h b/drivers/scsi/bfa/include/aen/bfa_aen_rport.h
deleted file mode 100644
index 7e4be1f..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_rport.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_RPORT Module */
-#ifndef	__bfa_aen_rport_h__
-#define	__bfa_aen_rport_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_RPORT_ONLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_ONLINE)
-#define BFA_AEN_RPORT_OFFLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_OFFLINE)
-#define BFA_AEN_RPORT_DISCONNECT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_DISCONNECT)
-#define BFA_AEN_RPORT_QOS_PRIO \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_QOS_PRIO)
-#define BFA_AEN_RPORT_QOS_FLOWID \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_QOS_FLOWID)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/bfa.h b/drivers/scsi/bfa/include/bfa.h
deleted file mode 100644
index d52b32f..0000000
--- a/drivers/scsi/bfa/include/bfa.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_H__
-#define __BFA_H__
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_debug.h>
-#include <cs/bfa_q.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-#include <cs/bfa_plog.h>
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_ioc.h>
-#include <defs/bfa_defs_iocfc.h>
-#include <aen/bfa_aen.h>
-#include <bfi/bfi.h>
-
-struct bfa_s;
-#include <bfa_intr_priv.h>
-
-struct bfa_pcidev_s;
-
-/**
- * PCI devices supported by the current BFA
- */
-struct bfa_pciid_s {
-	u16        device_id;
-	u16        vendor_id;
-};
-
-extern char     bfa_version[];
-
-/**
- * BFA Power Mgmt Commands
- */
-enum bfa_pm_cmd {
-	BFA_PM_CTL_D0 = 0,
-	BFA_PM_CTL_D1 = 1,
-	BFA_PM_CTL_D2 = 2,
-	BFA_PM_CTL_D3 = 3,
-};
-
-/**
- * BFA memory resources
- */
-enum bfa_mem_type {
-	BFA_MEM_TYPE_KVA = 1,	/*! Kernel Virtual Memory *(non-dma-able) */
-	BFA_MEM_TYPE_DMA = 2,	/*! DMA-able memory */
-	BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA,
-};
-
-struct bfa_mem_elem_s {
-	enum bfa_mem_type mem_type;	/*  see enum bfa_mem_type 	*/
-	u32        mem_len;	/*  Total Length in Bytes	*/
-	u8       	*kva;		/*  kernel virtual address	*/
-	u64        dma;		/*  dma address if DMA memory	*/
-	u8       	*kva_curp;	/*  kva allocation cursor	*/
-	u64        dma_curp;	/*  dma allocation cursor	*/
-};
-
-struct bfa_meminfo_s {
-	struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
-};
-#define bfa_meminfo_kva(_m)	\
-	((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp)
-#define bfa_meminfo_dma_virt(_m)	\
-	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp)
-#define bfa_meminfo_dma_phys(_m)	\
-	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp)
-
-/**
- * Generic Scatter Gather Element used by driver
- */
-struct bfa_sge_s {
-	u32        sg_len;
-	void           *sg_addr;
-};
-
-#define bfa_sge_to_be(__sge) do {                                          \
-	((u32 *)(__sge))[0] = bfa_os_htonl(((u32 *)(__sge))[0]);      \
-	((u32 *)(__sge))[1] = bfa_os_htonl(((u32 *)(__sge))[1]);      \
-	((u32 *)(__sge))[2] = bfa_os_htonl(((u32 *)(__sge))[2]);      \
-} while (0)
-
-
-/*
- * bfa stats interfaces
- */
-#define bfa_stats(_mod, _stats)	((_mod)->stats._stats++)
-
-#define bfa_ioc_get_stats(__bfa, __ioc_stats)	\
-	bfa_ioc_fetch_stats(&(__bfa)->ioc, __ioc_stats)
-#define bfa_ioc_clear_stats(__bfa)	\
-	bfa_ioc_clr_stats(&(__bfa)->ioc)
-#define bfa_get_nports(__bfa)   \
-	bfa_ioc_get_nports(&(__bfa)->ioc)
-#define bfa_get_adapter_manufacturer(__bfa, __manufacturer) \
-	bfa_ioc_get_adapter_manufacturer(&(__bfa)->ioc, __manufacturer)
-#define bfa_get_adapter_model(__bfa, __model)   \
-	bfa_ioc_get_adapter_model(&(__bfa)->ioc, __model)
-#define bfa_get_adapter_serial_num(__bfa, __serial_num) \
-	bfa_ioc_get_adapter_serial_num(&(__bfa)->ioc, __serial_num)
-#define bfa_get_adapter_fw_ver(__bfa, __fw_ver) \
-	bfa_ioc_get_adapter_fw_ver(&(__bfa)->ioc, __fw_ver)
-#define bfa_get_adapter_optrom_ver(__bfa, __optrom_ver) \
-	bfa_ioc_get_adapter_optrom_ver(&(__bfa)->ioc, __optrom_ver)
-#define bfa_get_pci_chip_rev(__bfa, __chip_rev) \
-	bfa_ioc_get_pci_chip_rev(&(__bfa)->ioc, __chip_rev)
-#define bfa_get_ioc_state(__bfa)    \
-	bfa_ioc_get_state(&(__bfa)->ioc)
-#define bfa_get_type(__bfa) \
-	bfa_ioc_get_type(&(__bfa)->ioc)
-#define bfa_get_mac(__bfa)  \
-	bfa_ioc_get_mac(&(__bfa)->ioc)
-#define bfa_get_mfg_mac(__bfa)  \
-	bfa_ioc_get_mfg_mac(&(__bfa)->ioc)
-#define bfa_get_fw_clock_res(__bfa)    \
-	((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res)
-
-/*
- * bfa API functions
- */
-void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
-void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
-void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
-void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
-			struct bfa_meminfo_s *meminfo);
-void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-			struct bfa_meminfo_s *meminfo,
-			struct bfa_pcidev_s *pcidev);
-void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod);
-void bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod);
-void bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen);
-void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog);
-void bfa_detach(struct bfa_s *bfa);
-void bfa_init(struct bfa_s *bfa);
-void bfa_start(struct bfa_s *bfa);
-void bfa_stop(struct bfa_s *bfa);
-void bfa_attach_fcs(struct bfa_s *bfa);
-void bfa_cb_init(void *bfad, bfa_status_t status);
-void bfa_cb_stop(void *bfad, bfa_status_t status);
-void bfa_cb_updateq(void *bfad, bfa_status_t status);
-
-bfa_boolean_t bfa_intx(struct bfa_s *bfa);
-void bfa_isr_enable(struct bfa_s *bfa);
-void bfa_isr_disable(struct bfa_s *bfa);
-void bfa_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
-			u32 *num_vecs, u32 *max_vec_bit);
-#define bfa_msix(__bfa, __vec) ((__bfa)->msix.handler[__vec](__bfa, __vec))
-
-void bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q);
-void bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q);
-void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q);
-
-typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status);
-void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr);
-bfa_status_t bfa_iocfc_get_stats(struct bfa_s *bfa,
-			struct bfa_iocfc_stats_s *stats,
-			bfa_cb_ioc_t cbfn, void *cbarg);
-bfa_status_t bfa_iocfc_clear_stats(struct bfa_s *bfa,
-			bfa_cb_ioc_t cbfn, void *cbarg);
-void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr);
-
-void bfa_adapter_get_attr(struct bfa_s *bfa,
-			struct bfa_adapter_attr_s *ad_attr);
-u64 bfa_adapter_get_id(struct bfa_s *bfa);
-
-bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,
-			struct bfa_iocfc_intr_attr_s *attr);
-
-void bfa_iocfc_enable(struct bfa_s *bfa);
-void bfa_iocfc_disable(struct bfa_s *bfa);
-void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
-void bfa_chip_reset(struct bfa_s *bfa);
-void bfa_cb_ioc_disable(void *bfad);
-void bfa_timer_tick(struct bfa_s *bfa);
-#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout)	\
-	bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
-
-/*
- * BFA debug API functions
- */
-bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen);
-bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen);
-void bfa_debug_fwsave_clear(struct bfa_s *bfa);
-
-#include "bfa_priv.h"
-
-#endif /* __BFA_H__ */
diff --git a/drivers/scsi/bfa/include/bfa_fcpim.h b/drivers/scsi/bfa/include/bfa_fcpim.h
deleted file mode 100644
index 4bc9453..0000000
--- a/drivers/scsi/bfa/include/bfa_fcpim.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCPIM_H__
-#define __BFA_FCPIM_H__
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_fcpim.h>
-#include <defs/bfa_defs_fcpim.h>
-
-/*
- * forward declarations
- */
-struct bfa_itnim_s;
-struct bfa_ioim_s;
-struct bfa_tskim_s;
-struct bfad_ioim_s;
-struct bfad_tskim_s;
-
-/*
- * bfa fcpim module API functions
- */
-void		bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
-u16	bfa_fcpim_path_tov_get(struct bfa_s *bfa);
-void		bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth);
-u16	bfa_fcpim_qdepth_get(struct bfa_s *bfa);
-bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa,
-			struct bfa_fcpim_stats_s *modstats);
-bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa);
-void bfa_fcpim_set_ioredirect(struct bfa_s *bfa, bfa_boolean_t state);
-void bfa_fcpim_update_ioredirect(struct bfa_s *bfa);
-void bfa_cb_ioredirect_state_change(void *hcb_bfad, bfa_boolean_t ioredirect);
-
-#define bfa_fcpim_ioredirect_enabled(__bfa)                             \
-	(((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect)
-
-#define bfa_fcpim_get_next_reqq(__bfa, __qid)                           \
-{                                                                       \
-	struct bfa_fcpim_mod_s *__fcpim = BFA_FCPIM_MOD(__bfa);         \
-	__fcpim->reqq++;                                                \
-	__fcpim->reqq &= (BFI_IOC_MAX_CQS - 1);                          \
-	*(__qid) = __fcpim->reqq;                                       \
-}
-
-#define bfa_iocfc_map_msg_to_qid(__msg, __qid)                          \
-	*(__qid) = (u8)((__msg) & (BFI_IOC_MAX_CQS - 1));
-
-
-/*
- * bfa itnim API functions
- */
-struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa,
-					struct bfa_rport_s *rport, void *itnim);
-void		bfa_itnim_delete(struct bfa_itnim_s *itnim);
-void		bfa_itnim_online(struct bfa_itnim_s *itnim,
-				 bfa_boolean_t seq_rec);
-void		bfa_itnim_offline(struct bfa_itnim_s *itnim);
-void		bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
-			struct bfa_itnim_hal_stats_s *stats);
-void		bfa_itnim_clear_stats(struct bfa_itnim_s *itnim);
-
-#define bfa_itnim_get_reqq(__ioim) (((struct bfa_ioim_s *)__ioim)->itnim->reqq)
-
-/**
- * 		BFA completion callback for bfa_itnim_online().
- *
- * @param[in]		itnim		FCS or driver itnim instance
- *
- * return None
- */
-void            bfa_cb_itnim_online(void *itnim);
-
-/**
- * 		BFA completion callback for bfa_itnim_offline().
- *
- * @param[in]		itnim		FCS or driver itnim instance
- *
- * return None
- */
-void            bfa_cb_itnim_offline(void *itnim);
-void            bfa_cb_itnim_tov_begin(void *itnim);
-void            bfa_cb_itnim_tov(void *itnim);
-
-/**
- * 		BFA notification to FCS/driver for second level error recovery.
- *
- * Atleast one I/O request has timedout and target is unresponsive to
- * repeated abort requests. Second level error recovery should be initiated
- * by starting implicit logout and recovery procedures.
- *
- * @param[in]		itnim		FCS or driver itnim instance
- *
- * return None
- */
-void            bfa_cb_itnim_sler(void *itnim);
-
-/*
- * bfa ioim API functions
- */
-struct bfa_ioim_s	*bfa_ioim_alloc(struct bfa_s *bfa,
-					struct bfad_ioim_s *dio,
-					struct bfa_itnim_s *itnim,
-					u16 nsgles);
-
-void		bfa_ioim_free(struct bfa_ioim_s *ioim);
-void		bfa_ioim_start(struct bfa_ioim_s *ioim);
-void		bfa_ioim_abort(struct bfa_ioim_s *ioim);
-void 		bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,
-				      bfa_boolean_t iotov);
-
-
-/**
- * 		I/O completion notification.
- *
- * @param[in]		dio			driver IO structure
- * @param[in]		io_status		IO completion status
- * @param[in]		scsi_status		SCSI status returned by target
- * @param[in]		sns_len			SCSI sense length, 0 if none
- * @param[in]		sns_info		SCSI sense data, if any
- * @param[in]		residue			Residual length
- *
- * @return None
- */
-void            bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio,
-				  enum bfi_ioim_status io_status,
-				  u8 scsi_status, int sns_len,
-				  u8 *sns_info, s32 residue);
-
-/**
- * 		I/O good completion notification.
- *
- * @param[in]		dio			driver IO structure
- *
- * @return None
- */
-void            bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
-
-/**
- * 		I/O abort completion notification
- *
- * @param[in]		dio			driver IO that was aborted
- *
- * @return None
- */
-void            bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);
-void		bfa_cb_ioim_resfree(void *hcb_bfad);
-
-void 			bfa_cb_ioim_resfree(void *hcb_bfad);
-
-/*
- * bfa tskim API functions
- */
-struct bfa_tskim_s	*bfa_tskim_alloc(struct bfa_s *bfa,
-					struct bfad_tskim_s *dtsk);
-void		bfa_tskim_free(struct bfa_tskim_s *tskim);
-void		bfa_tskim_start(struct bfa_tskim_s *tskim,
-				struct bfa_itnim_s *itnim, lun_t lun,
-				enum fcp_tm_cmnd tm, u8 t_secs);
-void		bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
-				  enum bfi_tskim_status tsk_status);
-
-#endif /* __BFA_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/include/bfa_fcptm.h b/drivers/scsi/bfa/include/bfa_fcptm.h
deleted file mode 100644
index 5f5ffe0..0000000
--- a/drivers/scsi/bfa/include/bfa_fcptm.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCPTM_H__
-#define __BFA_FCPTM_H__
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_fcptm.h>
-
-/*
- * forward declarations
- */
-struct bfa_tin_s;
-struct bfa_iotm_s;
-struct bfa_tsktm_s;
-
-/*
- * bfa fcptm module API functions
- */
-void bfa_fcptm_path_tov_set(struct bfa_s *bfa, u16 path_tov);
-u16 bfa_fcptm_path_tov_get(struct bfa_s *bfa);
-void bfa_fcptm_qdepth_set(struct bfa_s *bfa, u16 q_depth);
-u16 bfa_fcptm_qdepth_get(struct bfa_s *bfa);
-
-/*
- * bfa tin API functions
- */
-void bfa_tin_get_stats(struct bfa_tin_s *tin, struct bfa_tin_stats_s *stats);
-void bfa_tin_clear_stats(struct bfa_tin_s *tin);
-
-#endif /* __BFA_FCPTM_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfa_svc.h b/drivers/scsi/bfa/include/bfa_svc.h
deleted file mode 100644
index 7840943..0000000
--- a/drivers/scsi/bfa/include/bfa_svc.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_SVC_H__
-#define __BFA_SVC_H__
-
-/*
- * forward declarations
- */
-struct bfa_fcxp_s;
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_rport.h>
-#include <defs/bfa_defs_qos.h>
-#include <defs/bfa_defs_fcport.h>
-#include <cs/bfa_sm.h>
-#include <bfa.h>
-
-/**
- * 		BFA rport information.
- */
-struct bfa_rport_info_s {
-	u16        max_frmsz;	/*  max rcv pdu size               */
-	u32        pid:24,		/*  remote port ID                 */
-			lp_tag:8;	/*  tag                     */
-	u32        local_pid:24,	/*  local port ID		    */
-			cisc:8;		/*  CIRO supported		    */
-	u8         fc_class;	/*  supported FC classes. enum fc_cos */
-	u8         vf_en;		/*  virtual fabric enable          */
-	u16        vf_id;		/*  virtual fabric ID              */
-	enum bfa_pport_speed speed;	/*  Rport's current speed	    */
-};
-
-/**
- * BFA rport data structure
- */
-struct bfa_rport_s {
-	struct list_head        qe;	  /*  queue element */
-	bfa_sm_t	      sm; 	  /*  state machine */
-	struct bfa_s          *bfa;	  /*  backpointer to BFA */
-	void                  *rport_drv; /*  fcs/driver rport object */
-	u16              fw_handle; /*  firmware rport handle */
-	u16              rport_tag; /*  BFA rport tag */
-	struct bfa_rport_info_s rport_info; /*  rport info from fcs/driver */
-	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */
-	struct bfa_cb_qe_s    hcb_qe;	 /*  BFA callback qelem */
-	struct bfa_rport_hal_stats_s stats; /*  BFA rport statistics  */
-	struct bfa_rport_qos_attr_s  qos_attr;
-	union a {
-		bfa_status_t    status;	 /*  f/w status */
-		void            *fw_msg; /*  QoS scn event */
-	} event_arg;
-};
-#define BFA_RPORT_FC_COS(_rport)	((_rport)->rport_info.fc_class)
-
-/**
- * Send completion callback.
- */
-typedef void (*bfa_cb_fcxp_send_t) (void *bfad_fcxp, struct bfa_fcxp_s *fcxp,
-			void *cbarg, enum bfa_status req_status,
-			u32 rsp_len, u32 resid_len,
-			struct fchs_s *rsp_fchs);
-
-/**
- * BFA fcxp allocation (asynchronous)
- */
-typedef void (*bfa_fcxp_alloc_cbfn_t) (void *cbarg, struct bfa_fcxp_s *fcxp);
-
-struct bfa_fcxp_wqe_s {
-	struct list_head         qe;
-	bfa_fcxp_alloc_cbfn_t  alloc_cbfn;
-	void           *alloc_cbarg;
-};
-
-typedef u64 (*bfa_fcxp_get_sgaddr_t) (void *bfad_fcxp, int sgeid);
-typedef u32 (*bfa_fcxp_get_sglen_t) (void *bfad_fcxp, int sgeid);
-
-#define BFA_UF_BUFSZ	(2 * 1024 + 256)
-
-/**
- * @todo private
- */
-struct bfa_uf_buf_s {
-	u8         d[BFA_UF_BUFSZ];
-};
-
-
-struct bfa_uf_s {
-	struct list_head	qe;		/*  queue element	  */
-	struct bfa_s	*bfa;		/*  bfa instance	  */
-	u16        uf_tag;		/*  identifying tag fw msgs     */
-	u16        vf_id;
-	u16        src_rport_handle;
-	u16        rsvd;
-	u8        	*data_ptr;
-	u16        data_len;	/*  actual receive length	  */
-	u16        pb_len;		/*  posted buffer length	  */
-	void           	*buf_kva;	/*  buffer virtual address	  */
-	u64        buf_pa;		/*  buffer physical address	  */
-	struct bfa_cb_qe_s    hcb_qe;	/*  comp: BFA comp qelem	  */
-	struct bfa_sge_s   	sges[BFI_SGE_INLINE_MAX];
-};
-
-typedef void (*bfa_cb_pport_t) (void *cbarg, enum bfa_status status);
-
-/**
- * bfa lport login/logout service interface
- */
-struct bfa_lps_s {
-	struct list_head	qe;		/*  queue element */
-	struct bfa_s	*bfa;		/*  parent bfa instance	*/
-	bfa_sm_t	sm;		/*  finite state machine	*/
-	u8		lp_tag;		/*  lport tag			*/
-	u8		reqq;		/*  lport request queue	*/
-	u8		alpa;		/*  ALPA for loop topologies	*/
-	u32	lp_pid;		/*  lport port ID		*/
-	bfa_boolean_t	fdisc;		/*  send FDISC instead of FLOGI  */
-	bfa_boolean_t	auth_en;	/*  enable authentication	*/
-	bfa_boolean_t	auth_req;	/*  authentication required	*/
-	bfa_boolean_t	npiv_en;	/*  NPIV is allowed by peer	*/
-	bfa_boolean_t	fport;		/*  attached peer is F_PORT	*/
-	bfa_boolean_t	brcd_switch;/*  attached peer is brcd switch	*/
-	bfa_status_t	status;		/*  login status		*/
-	u16	pdusz;		/*  max receive PDU size 	*/
-	u16	pr_bbcred;	/*  BB_CREDIT from peer 	*/
-	u8		lsrjt_rsn;	/*  LSRJT reason		*/
-	u8		lsrjt_expl;	/*  LSRJT explanation		*/
-	wwn_t		pwwn;		/*  port wwn of lport		*/
-	wwn_t		nwwn;		/*  node wwn of lport		*/
-	wwn_t		pr_pwwn;	/*  port wwn of lport peer	*/
-	wwn_t		pr_nwwn;	/*  node wwn of lport peer	*/
-	mac_t		lp_mac;		/*  fpma/spma MAC for lport	*/
-	mac_t		fcf_mac;	/*  FCF MAC of lport		*/
-	struct bfa_reqq_wait_s	wqe;	/*  request wait queue element	*/
-	void		*uarg;		/*  user callback arg		*/
-	struct bfa_cb_qe_s hcb_qe;	/*  comp: callback qelem	*/
-	struct bfi_lps_login_rsp_s *loginrsp;
-	bfa_eproto_status_t	ext_status;
-};
-
-#define BFA_FCPORT(_bfa)        (&((_bfa)->modules.port))
-
-/*
- * bfa pport API functions
- */
-bfa_status_t bfa_fcport_enable(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_disable(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_speed(struct bfa_s *bfa,
-			enum bfa_pport_speed speed);
-enum bfa_pport_speed bfa_fcport_get_speed(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_topology(struct bfa_s *bfa,
-			enum bfa_pport_topology topo);
-enum bfa_pport_topology bfa_fcport_get_topology(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa);
-bfa_boolean_t bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa);
-u8 bfa_fcport_get_myalpa(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_clr_hardalpa(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxsize);
-u16 bfa_fcport_get_maxfrsize(struct bfa_s *bfa);
-u32 bfa_fcport_mypid(struct bfa_s *bfa);
-u8 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_trunk_enable(struct bfa_s *bfa, u8 bitmap);
-bfa_status_t bfa_fcport_trunk_disable(struct bfa_s *bfa);
-bfa_boolean_t bfa_fcport_trunk_query(struct bfa_s *bfa, u32 *bitmap);
-void bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr);
-wwn_t bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node);
-void bfa_fcport_event_register(struct bfa_s *bfa,
-			void (*event_cbfn) (void *cbarg,
-			bfa_pport_event_t event), void *event_cbarg);
-bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
-void bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off);
-void bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off);
-bfa_status_t bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa,
-			enum bfa_pport_speed speed);
-enum bfa_pport_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
-
-void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
-void bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status);
-void bfa_fcport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon,
-			bfa_boolean_t link_e2e_beacon);
-void bfa_cb_pport_event(void *cbarg, bfa_pport_event_t event);
-void bfa_fcport_qos_get_attr(struct bfa_s *bfa,
-			struct bfa_qos_attr_s *qos_attr);
-void bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
-			struct bfa_qos_vc_attr_s *qos_vc_attr);
-bfa_status_t bfa_fcport_get_qos_stats(struct bfa_s *bfa,
-			union bfa_fcport_stats_u *stats,
-			bfa_cb_pport_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn,
-			void *cbarg);
-bfa_status_t bfa_fcport_get_fcoe_stats(struct bfa_s *bfa,
-			union bfa_fcport_stats_u *stats,
-			bfa_cb_pport_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn,
-			void *cbarg);
-
-bfa_boolean_t     bfa_fcport_is_ratelim(struct bfa_s *bfa);
-bfa_boolean_t	bfa_fcport_is_linkup(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
-		union bfa_fcport_stats_u *stats,
-		bfa_cb_pport_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn,
-		void *cbarg);
-bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
-
-/*
- * bfa rport API functions
- */
-struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv);
-void bfa_rport_delete(struct bfa_rport_s *rport);
-void bfa_rport_online(struct bfa_rport_s *rport,
-			struct bfa_rport_info_s *rport_info);
-void bfa_rport_offline(struct bfa_rport_s *rport);
-void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_pport_speed speed);
-void bfa_rport_get_stats(struct bfa_rport_s *rport,
-			struct bfa_rport_hal_stats_s *stats);
-void bfa_rport_clear_stats(struct bfa_rport_s *rport);
-void bfa_cb_rport_online(void *rport);
-void bfa_cb_rport_offline(void *rport);
-void bfa_cb_rport_qos_scn_flowid(void *rport,
-			struct bfa_rport_qos_attr_s old_qos_attr,
-			struct bfa_rport_qos_attr_s new_qos_attr);
-void bfa_cb_rport_qos_scn_prio(void *rport,
-			struct bfa_rport_qos_attr_s old_qos_attr,
-			struct bfa_rport_qos_attr_s new_qos_attr);
-void bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
-			struct bfa_rport_qos_attr_s *qos_attr);
-
-/*
- * bfa fcxp API functions
- */
-struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
-			int nreq_sgles, int nrsp_sgles,
-			bfa_fcxp_get_sgaddr_t get_req_sga,
-			bfa_fcxp_get_sglen_t get_req_sglen,
-			bfa_fcxp_get_sgaddr_t get_rsp_sga,
-			bfa_fcxp_get_sglen_t get_rsp_sglen);
-void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
-			bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *cbarg);
-void bfa_fcxp_walloc_cancel(struct bfa_s *bfa,
-			struct bfa_fcxp_wqe_s *wqe);
-void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp);
-
-void *bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp);
-void *bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp);
-
-void bfa_fcxp_free(struct bfa_fcxp_s *fcxp);
-
-void bfa_fcxp_send(struct bfa_fcxp_s *fcxp,
-			struct bfa_rport_s *rport, u16 vf_id, u8 lp_tag,
-			bfa_boolean_t cts, enum fc_cos cos,
-			u32 reqlen, struct fchs_s *fchs,
-			bfa_cb_fcxp_send_t cbfn,
-			void *cbarg,
-			u32 rsp_maxlen, u8 rsp_timeout);
-bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp);
-u32        bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp);
-u32	bfa_fcxp_get_maxrsp(struct bfa_s *bfa);
-
-static inline void *
-bfa_uf_get_frmbuf(struct bfa_uf_s *uf)
-{
-	return uf->data_ptr;
-}
-
-static inline   u16
-bfa_uf_get_frmlen(struct bfa_uf_s *uf)
-{
-	return uf->data_len;
-}
-
-/**
- *      Callback prototype for unsolicited frame receive handler.
- *
- * @param[in]           cbarg           callback arg for receive handler
- * @param[in]           uf              unsolicited frame descriptor
- *
- * @return None
- */
-typedef void (*bfa_cb_uf_recv_t) (void *cbarg, struct bfa_uf_s *uf);
-
-/*
- * bfa uf API functions
- */
-void bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv,
-			void *cbarg);
-void bfa_uf_free(struct bfa_uf_s *uf);
-
-/**
- * bfa lport service api
- */
-
-u32	bfa_lps_get_max_vport(struct bfa_s *bfa);
-struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
-void bfa_lps_delete(struct bfa_lps_s *lps);
-void bfa_lps_discard(struct bfa_lps_s *lps);
-void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
-		   wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en);
-void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
-		   wwn_t nwwn);
-void bfa_lps_flogo(struct bfa_lps_s *lps);
-void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
-u8 bfa_lps_get_tag(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps);
-bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps);
-u32 bfa_lps_get_pid(struct bfa_lps_s *lps);
-u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
-u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps);
-wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps);
-wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps);
-u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps);
-u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps);
-mac_t bfa_lps_get_lp_mac(struct bfa_lps_s *lps);
-void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
-void bfa_cb_lps_flogo_comp(void *bfad, void *uarg);
-void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
-void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
-void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
-
-#endif /* __BFA_SVC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfa_timer.h b/drivers/scsi/bfa/include/bfa_timer.h
deleted file mode 100644
index f710874..0000000
--- a/drivers/scsi/bfa/include/bfa_timer.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_TIMER_H__
-#define __BFA_TIMER_H__
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_q.h>
-
-struct bfa_s;
-
-typedef void (*bfa_timer_cbfn_t)(void *);
-
-/**
- * BFA timer data structure
- */
-struct bfa_timer_s {
-	struct list_head	qe;
-	bfa_timer_cbfn_t timercb;
-	void            *arg;
-	int             timeout;	/**< in millisecs. */
-};
-
-/**
- * Timer module structure
- */
-struct bfa_timer_mod_s {
-	struct list_head timer_q;
-};
-
-#define BFA_TIMER_FREQ 200 /**< specified in millisecs */
-
-void bfa_timer_beat(struct bfa_timer_mod_s *mod);
-void bfa_timer_init(struct bfa_timer_mod_s *mod);
-void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
-			bfa_timer_cbfn_t timercb, void *arg,
-			unsigned int timeout);
-void bfa_timer_stop(struct bfa_timer_s *timer);
-
-#endif /* __BFA_TIMER_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi.h b/drivers/scsi/bfa/include/bfi/bfi.h
deleted file mode 100644
index a550e80..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_H__
-#define __BFI_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_status.h>
-
-#pragma pack(1)
-
-/**
- * Msg header common to all msgs
- */
-struct bfi_mhdr_s {
-	u8         msg_class;	/*  @ref bfi_mclass_t	    */
-	u8         msg_id;		/*  msg opcode with in the class   */
-	union {
-		struct {
-			u8         rsvd;
-			u8         lpu_id;	/*  msg destination	    */
-		} h2i;
-		u16        i2htok;	/*  token in msgs to host	    */
-	} mtag;
-};
-
-#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {		\
-	(_mh).msg_class 		= (_mc);      \
-	(_mh).msg_id			= (_op);      \
-	(_mh).mtag.h2i.lpu_id	= (_lpuid);      \
-} while (0)
-
-#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {		\
-	(_mh).msg_class 		= (_mc);      \
-	(_mh).msg_id			= (_op);      \
-	(_mh).mtag.i2htok		= (_i2htok);      \
-} while (0)
-
-/*
- * Message opcodes: 0-127 to firmware, 128-255 to host
- */
-#define BFI_I2H_OPCODE_BASE	128
-#define BFA_I2HM(_x) 			((_x) + BFI_I2H_OPCODE_BASE)
-
-/**
- ****************************************************************************
- *
- * Scatter Gather Element and Page definition
- *
- ****************************************************************************
- */
-
-#define BFI_SGE_INLINE	1
-#define BFI_SGE_INLINE_MAX	(BFI_SGE_INLINE + 1)
-
-/**
- * SG Flags
- */
-enum {
-	BFI_SGE_DATA	= 0,	/*  data address, not last	     */
-	BFI_SGE_DATA_CPL	= 1,	/*  data addr, last in current page */
-	BFI_SGE_DATA_LAST	= 3,	/*  data address, last		     */
-	BFI_SGE_LINK	= 2,	/*  link address		     */
-	BFI_SGE_PGDLEN	= 2,	/*  cumulative data length for page */
-};
-
-/**
- * DMA addresses
- */
-union bfi_addr_u {
-	struct {
-		u32        addr_lo;
-		u32        addr_hi;
-	} a32;
-};
-
-/**
- * Scatter Gather Element
- */
-struct bfi_sge_s {
-#ifdef __BIGENDIAN
-	u32        flags:2,
-			rsvd:2,
-			sg_len:28;
-#else
-	u32        sg_len:28,
-			rsvd:2,
-			flags:2;
-#endif
-	union bfi_addr_u sga;
-};
-
-/**
- * Scatter Gather Page
- */
-#define BFI_SGPG_DATA_SGES		7
-#define BFI_SGPG_SGES_MAX		(BFI_SGPG_DATA_SGES + 1)
-#define BFI_SGPG_RSVD_WD_LEN	8
-struct bfi_sgpg_s {
-	struct bfi_sge_s sges[BFI_SGPG_SGES_MAX];
-	u32	rsvd[BFI_SGPG_RSVD_WD_LEN];
-};
-
-/*
- * Large Message structure - 128 Bytes size Msgs
- */
-#define BFI_LMSG_SZ		128
-#define BFI_LMSG_PL_WSZ	\
-			((BFI_LMSG_SZ - sizeof(struct bfi_mhdr_s)) / 4)
-
-struct bfi_msg_s {
-	struct bfi_mhdr_s mhdr;
-	u32	pl[BFI_LMSG_PL_WSZ];
-};
-
-/**
- * Mailbox message structure
- */
-#define BFI_MBMSG_SZ		7
-struct bfi_mbmsg_s {
-	struct bfi_mhdr_s	mh;
-	u32		pl[BFI_MBMSG_SZ];
-};
-
-/**
- * Message Classes
- */
-enum bfi_mclass {
-	BFI_MC_IOC		= 1,	/*  IO Controller (IOC)	    */
-	BFI_MC_DIAG		= 2,	/*  Diagnostic Msgs		    */
-	BFI_MC_FLASH		= 3,	/*  Flash message class	    */
-	BFI_MC_CEE		= 4,	/*  CEE                     */
-	BFI_MC_FCPORT		= 5,	/*  FC port		   	    */
-	BFI_MC_IOCFC		= 6,	/*  FC - IO Controller (IOC)	    */
-	BFI_MC_LL		= 7,	/*  Link Layer		 	    */
-	BFI_MC_UF		= 8,	/*  Unsolicited frame receive	    */
-	BFI_MC_FCXP		= 9,	/*  FC Transport		    */
-	BFI_MC_LPS		= 10,	/*  lport fc login services	    */
-	BFI_MC_RPORT		= 11,	/*  Remote port		    */
-	BFI_MC_ITNIM		= 12,	/*  I-T nexus (Initiator mode)	    */
-	BFI_MC_IOIM_READ	= 13,	/*  read IO (Initiator mode)	    */
-	BFI_MC_IOIM_WRITE	= 14,	/*  write IO (Initiator mode)	    */
-	BFI_MC_IOIM_IO		= 15,	/*  IO (Initiator mode)	    */
-	BFI_MC_IOIM		= 16,	/*  IO (Initiator mode)	    */
-	BFI_MC_IOIM_IOCOM	= 17,	/*  good IO completion		    */
-	BFI_MC_TSKIM		= 18,	/*  Initiator Task management	    */
-	BFI_MC_SBOOT		= 19,	/*  SAN boot services		    */
-	BFI_MC_IPFC		= 20,	/*  IP over FC Msgs		    */
-	BFI_MC_PORT		= 21,	/*  Physical port		    */
-	BFI_MC_MAX		= 32
-};
-
-#define BFI_IOC_MAX_CQS		4
-#define BFI_IOC_MAX_CQS_ASIC	8
-#define BFI_IOC_MSGLEN_MAX	32	/* 32 bytes */
-
-#pragma pack()
-
-#endif /* __BFI_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_boot.h b/drivers/scsi/bfa/include/bfi/bfi_boot.h
deleted file mode 100644
index 5955afe..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_boot.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-/*
- * bfi_boot.h
- */
-
-#ifndef __BFI_BOOT_H__
-#define __BFI_BOOT_H__
-
-#define BFI_BOOT_TYPE_OFF		8
-#define BFI_BOOT_PARAM_OFF		12
-
-#define BFI_BOOT_TYPE_NORMAL 		0	/* param is device id */
-#define	BFI_BOOT_TYPE_FLASH		1
-#define	BFI_BOOT_TYPE_MEMTEST		2
-
-#define BFI_BOOT_MEMTEST_RES_ADDR   0x900
-#define BFI_BOOT_MEMTEST_RES_SIG    0xA0A1A2A3
-
-#endif
diff --git a/drivers/scsi/bfa/include/bfi/bfi_cbreg.h b/drivers/scsi/bfa/include/bfi/bfi_cbreg.h
deleted file mode 100644
index a51ee61..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_cbreg.h
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/*
- * bfi_cbreg.h crossbow host block register definitions
- *
- * !!! Do not edit. Auto generated. !!!
- */
-
-#ifndef __BFI_CBREG_H__
-#define __BFI_CBREG_H__
-
-
-#define HOSTFN0_INT_STATUS               0x00014000
-#define __HOSTFN0_INT_STATUS_LVL_MK      0x00f00000
-#define __HOSTFN0_INT_STATUS_LVL_SH      20
-#define __HOSTFN0_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
-#define __HOSTFN0_INT_STATUS_P           0x000fffff
-#define HOSTFN0_INT_MSK                  0x00014004
-#define HOST_PAGE_NUM_FN0                0x00014008
-#define __HOST_PAGE_NUM_FN               0x000001ff
-#define HOSTFN1_INT_STATUS               0x00014100
-#define __HOSTFN1_INT_STAT_LVL_MK        0x00f00000
-#define __HOSTFN1_INT_STAT_LVL_SH        20
-#define __HOSTFN1_INT_STAT_LVL(_v)       ((_v) << __HOSTFN1_INT_STAT_LVL_SH)
-#define __HOSTFN1_INT_STAT_P             0x000fffff
-#define HOSTFN1_INT_MSK                  0x00014104
-#define HOST_PAGE_NUM_FN1                0x00014108
-#define APP_PLL_400_CTL_REG              0x00014204
-#define __P_400_PLL_LOCK                 0x80000000
-#define __APP_PLL_400_SRAM_USE_100MHZ    0x00100000
-#define __APP_PLL_400_RESET_TIMER_MK     0x000e0000
-#define __APP_PLL_400_RESET_TIMER_SH     17
-#define __APP_PLL_400_RESET_TIMER(_v)    ((_v) << __APP_PLL_400_RESET_TIMER_SH)
-#define __APP_PLL_400_LOGIC_SOFT_RESET   0x00010000
-#define __APP_PLL_400_CNTLMT0_1_MK       0x0000c000
-#define __APP_PLL_400_CNTLMT0_1_SH       14
-#define __APP_PLL_400_CNTLMT0_1(_v)      ((_v) << __APP_PLL_400_CNTLMT0_1_SH)
-#define __APP_PLL_400_JITLMT0_1_MK       0x00003000
-#define __APP_PLL_400_JITLMT0_1_SH       12
-#define __APP_PLL_400_JITLMT0_1(_v)      ((_v) << __APP_PLL_400_JITLMT0_1_SH)
-#define __APP_PLL_400_HREF               0x00000800
-#define __APP_PLL_400_HDIV               0x00000400
-#define __APP_PLL_400_P0_1_MK            0x00000300
-#define __APP_PLL_400_P0_1_SH            8
-#define __APP_PLL_400_P0_1(_v)           ((_v) << __APP_PLL_400_P0_1_SH)
-#define __APP_PLL_400_Z0_2_MK            0x000000e0
-#define __APP_PLL_400_Z0_2_SH            5
-#define __APP_PLL_400_Z0_2(_v)           ((_v) << __APP_PLL_400_Z0_2_SH)
-#define __APP_PLL_400_RSEL200500         0x00000010
-#define __APP_PLL_400_ENARST             0x00000008
-#define __APP_PLL_400_BYPASS             0x00000004
-#define __APP_PLL_400_LRESETN            0x00000002
-#define __APP_PLL_400_ENABLE             0x00000001
-#define APP_PLL_212_CTL_REG              0x00014208
-#define __P_212_PLL_LOCK                 0x80000000
-#define __APP_PLL_212_RESET_TIMER_MK     0x000e0000
-#define __APP_PLL_212_RESET_TIMER_SH     17
-#define __APP_PLL_212_RESET_TIMER(_v)    ((_v) << __APP_PLL_212_RESET_TIMER_SH)
-#define __APP_PLL_212_LOGIC_SOFT_RESET   0x00010000
-#define __APP_PLL_212_CNTLMT0_1_MK       0x0000c000
-#define __APP_PLL_212_CNTLMT0_1_SH       14
-#define __APP_PLL_212_CNTLMT0_1(_v)      ((_v) << __APP_PLL_212_CNTLMT0_1_SH)
-#define __APP_PLL_212_JITLMT0_1_MK       0x00003000
-#define __APP_PLL_212_JITLMT0_1_SH       12
-#define __APP_PLL_212_JITLMT0_1(_v)      ((_v) << __APP_PLL_212_JITLMT0_1_SH)
-#define __APP_PLL_212_HREF               0x00000800
-#define __APP_PLL_212_HDIV               0x00000400
-#define __APP_PLL_212_P0_1_MK            0x00000300
-#define __APP_PLL_212_P0_1_SH            8
-#define __APP_PLL_212_P0_1(_v)           ((_v) << __APP_PLL_212_P0_1_SH)
-#define __APP_PLL_212_Z0_2_MK            0x000000e0
-#define __APP_PLL_212_Z0_2_SH            5
-#define __APP_PLL_212_Z0_2(_v)           ((_v) << __APP_PLL_212_Z0_2_SH)
-#define __APP_PLL_212_RSEL200500         0x00000010
-#define __APP_PLL_212_ENARST             0x00000008
-#define __APP_PLL_212_BYPASS             0x00000004
-#define __APP_PLL_212_LRESETN            0x00000002
-#define __APP_PLL_212_ENABLE             0x00000001
-#define HOST_SEM0_REG                    0x00014230
-#define __HOST_SEMAPHORE                 0x00000001
-#define HOST_SEM1_REG                    0x00014234
-#define HOST_SEM2_REG                    0x00014238
-#define HOST_SEM3_REG                    0x0001423c
-#define HOST_SEM0_INFO_REG               0x00014240
-#define HOST_SEM1_INFO_REG               0x00014244
-#define HOST_SEM2_INFO_REG               0x00014248
-#define HOST_SEM3_INFO_REG               0x0001424c
-#define HOSTFN0_LPU0_CMD_STAT            0x00019000
-#define __HOSTFN0_LPU0_MBOX_INFO_MK      0xfffffffe
-#define __HOSTFN0_LPU0_MBOX_INFO_SH      1
-#define __HOSTFN0_LPU0_MBOX_INFO(_v)     ((_v) << __HOSTFN0_LPU0_MBOX_INFO_SH)
-#define __HOSTFN0_LPU0_MBOX_CMD_STATUS   0x00000001
-#define LPU0_HOSTFN0_CMD_STAT            0x00019008
-#define __LPU0_HOSTFN0_MBOX_INFO_MK      0xfffffffe
-#define __LPU0_HOSTFN0_MBOX_INFO_SH      1
-#define __LPU0_HOSTFN0_MBOX_INFO(_v)     ((_v) << __LPU0_HOSTFN0_MBOX_INFO_SH)
-#define __LPU0_HOSTFN0_MBOX_CMD_STATUS   0x00000001
-#define HOSTFN1_LPU1_CMD_STAT            0x00019014
-#define __HOSTFN1_LPU1_MBOX_INFO_MK      0xfffffffe
-#define __HOSTFN1_LPU1_MBOX_INFO_SH      1
-#define __HOSTFN1_LPU1_MBOX_INFO(_v)     ((_v) << __HOSTFN1_LPU1_MBOX_INFO_SH)
-#define __HOSTFN1_LPU1_MBOX_CMD_STATUS   0x00000001
-#define LPU1_HOSTFN1_CMD_STAT            0x0001901c
-#define __LPU1_HOSTFN1_MBOX_INFO_MK      0xfffffffe
-#define __LPU1_HOSTFN1_MBOX_INFO_SH      1
-#define __LPU1_HOSTFN1_MBOX_INFO(_v)     ((_v) << __LPU1_HOSTFN1_MBOX_INFO_SH)
-#define __LPU1_HOSTFN1_MBOX_CMD_STATUS   0x00000001
-#define CPE_Q0_DEPTH                     0x00010014
-#define CPE_Q0_PI                        0x0001001c
-#define CPE_Q0_CI                        0x00010020
-#define CPE_Q1_DEPTH                     0x00010034
-#define CPE_Q1_PI                        0x0001003c
-#define CPE_Q1_CI                        0x00010040
-#define CPE_Q2_DEPTH                     0x00010054
-#define CPE_Q2_PI                        0x0001005c
-#define CPE_Q2_CI                        0x00010060
-#define CPE_Q3_DEPTH                     0x00010074
-#define CPE_Q3_PI                        0x0001007c
-#define CPE_Q3_CI                        0x00010080
-#define CPE_Q4_DEPTH                     0x00010094
-#define CPE_Q4_PI                        0x0001009c
-#define CPE_Q4_CI                        0x000100a0
-#define CPE_Q5_DEPTH                     0x000100b4
-#define CPE_Q5_PI                        0x000100bc
-#define CPE_Q5_CI                        0x000100c0
-#define CPE_Q6_DEPTH                     0x000100d4
-#define CPE_Q6_PI                        0x000100dc
-#define CPE_Q6_CI                        0x000100e0
-#define CPE_Q7_DEPTH                     0x000100f4
-#define CPE_Q7_PI                        0x000100fc
-#define CPE_Q7_CI                        0x00010100
-#define RME_Q0_DEPTH                     0x00011014
-#define RME_Q0_PI                        0x0001101c
-#define RME_Q0_CI                        0x00011020
-#define RME_Q1_DEPTH                     0x00011034
-#define RME_Q1_PI                        0x0001103c
-#define RME_Q1_CI                        0x00011040
-#define RME_Q2_DEPTH                     0x00011054
-#define RME_Q2_PI                        0x0001105c
-#define RME_Q2_CI                        0x00011060
-#define RME_Q3_DEPTH                     0x00011074
-#define RME_Q3_PI                        0x0001107c
-#define RME_Q3_CI                        0x00011080
-#define RME_Q4_DEPTH                     0x00011094
-#define RME_Q4_PI                        0x0001109c
-#define RME_Q4_CI                        0x000110a0
-#define RME_Q5_DEPTH                     0x000110b4
-#define RME_Q5_PI                        0x000110bc
-#define RME_Q5_CI                        0x000110c0
-#define RME_Q6_DEPTH                     0x000110d4
-#define RME_Q6_PI                        0x000110dc
-#define RME_Q6_CI                        0x000110e0
-#define RME_Q7_DEPTH                     0x000110f4
-#define RME_Q7_PI                        0x000110fc
-#define RME_Q7_CI                        0x00011100
-#define PSS_CTL_REG                      0x00018800
-#define __PSS_I2C_CLK_DIV_MK             0x00030000
-#define __PSS_I2C_CLK_DIV_SH             16
-#define __PSS_I2C_CLK_DIV(_v)            ((_v) << __PSS_I2C_CLK_DIV_SH)
-#define __PSS_LMEM_INIT_DONE             0x00001000
-#define __PSS_LMEM_RESET                 0x00000200
-#define __PSS_LMEM_INIT_EN               0x00000100
-#define __PSS_LPU1_RESET                 0x00000002
-#define __PSS_LPU0_RESET                 0x00000001
-#define PSS_ERR_STATUS_REG		 0x00018810
-#define __PSS_LMEM1_CORR_ERR		 0x00000800
-#define __PSS_LMEM0_CORR_ERR             0x00000400
-#define __PSS_LMEM1_UNCORR_ERR           0x00000200
-#define __PSS_LMEM0_UNCORR_ERR           0x00000100
-#define __PSS_BAL_PERR                   0x00000080
-#define __PSS_DIP_IF_ERR                 0x00000040
-#define __PSS_IOH_IF_ERR                 0x00000020
-#define __PSS_TDS_IF_ERR                 0x00000010
-#define __PSS_RDS_IF_ERR                 0x00000008
-#define __PSS_SGM_IF_ERR                 0x00000004
-#define __PSS_LPU1_RAM_ERR               0x00000002
-#define __PSS_LPU0_RAM_ERR               0x00000001
-#define ERR_SET_REG			 0x00018818
-#define __PSS_ERR_STATUS_SET		 0x00000fff
-
-/*
- * These definitions are either in error/missing in spec. Its auto-generated
- * from hard coded values in regparse.pl.
- */
-#define __EMPHPOST_AT_4G_MK_FIX          0x0000001c
-#define __EMPHPOST_AT_4G_SH_FIX          0x00000002
-#define __EMPHPRE_AT_4G_FIX              0x00000003
-#define __SFP_TXRATE_EN_FIX              0x00000100
-#define __SFP_RXRATE_EN_FIX              0x00000080
-
-
-/*
- * These register definitions are auto-generated from hard coded values
- * in regparse.pl.
- */
-#define HOSTFN0_LPU_MBOX0_0              0x00019200
-#define HOSTFN1_LPU_MBOX0_8              0x00019260
-#define LPU_HOSTFN0_MBOX0_0              0x00019280
-#define LPU_HOSTFN1_MBOX0_8              0x000192e0
-
-
-/*
- * These register mapping definitions are auto-generated from mapping tables
- * in regparse.pl.
- */
-#define BFA_IOC0_HBEAT_REG               HOST_SEM0_INFO_REG
-#define BFA_IOC0_STATE_REG               HOST_SEM1_INFO_REG
-#define BFA_IOC1_HBEAT_REG               HOST_SEM2_INFO_REG
-#define BFA_IOC1_STATE_REG               HOST_SEM3_INFO_REG
-#define BFA_FW_USE_COUNT                 HOST_SEM4_INFO_REG
-
-#define CPE_Q_DEPTH(__n) \
-	(CPE_Q0_DEPTH + (__n) * (CPE_Q1_DEPTH - CPE_Q0_DEPTH))
-#define CPE_Q_PI(__n) \
-	(CPE_Q0_PI + (__n) * (CPE_Q1_PI - CPE_Q0_PI))
-#define CPE_Q_CI(__n) \
-	(CPE_Q0_CI + (__n) * (CPE_Q1_CI - CPE_Q0_CI))
-#define RME_Q_DEPTH(__n) \
-	(RME_Q0_DEPTH + (__n) * (RME_Q1_DEPTH - RME_Q0_DEPTH))
-#define RME_Q_PI(__n) \
-	(RME_Q0_PI + (__n) * (RME_Q1_PI - RME_Q0_PI))
-#define RME_Q_CI(__n) \
-	(RME_Q0_CI + (__n) * (RME_Q1_CI - RME_Q0_CI))
-
-#define CPE_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
-#define RME_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
-#define CPE_Q_MASK(__q)  ((__q) & 0x3)
-#define RME_Q_MASK(__q)  ((__q) & 0x3)
-
-
-/*
- * PCI MSI-X vector defines
- */
-enum {
-    BFA_MSIX_CPE_Q0 = 0,
-    BFA_MSIX_CPE_Q1 = 1,
-    BFA_MSIX_CPE_Q2 = 2,
-    BFA_MSIX_CPE_Q3 = 3,
-    BFA_MSIX_CPE_Q4 = 4,
-    BFA_MSIX_CPE_Q5 = 5,
-    BFA_MSIX_CPE_Q6 = 6,
-    BFA_MSIX_CPE_Q7 = 7,
-    BFA_MSIX_RME_Q0 = 8,
-    BFA_MSIX_RME_Q1 = 9,
-    BFA_MSIX_RME_Q2 = 10,
-    BFA_MSIX_RME_Q3 = 11,
-    BFA_MSIX_RME_Q4 = 12,
-    BFA_MSIX_RME_Q5 = 13,
-    BFA_MSIX_RME_Q6 = 14,
-    BFA_MSIX_RME_Q7 = 15,
-    BFA_MSIX_ERR_EMC = 16,
-    BFA_MSIX_ERR_LPU0 = 17,
-    BFA_MSIX_ERR_LPU1 = 18,
-    BFA_MSIX_ERR_PSS = 19,
-    BFA_MSIX_MBOX_LPU0 = 20,
-    BFA_MSIX_MBOX_LPU1 = 21,
-    BFA_MSIX_CB_MAX = 22,
-};
-
-/*
- * And corresponding host interrupt status bit field defines
- */
-#define __HFN_INT_CPE_Q0                   0x00000001U
-#define __HFN_INT_CPE_Q1                   0x00000002U
-#define __HFN_INT_CPE_Q2                   0x00000004U
-#define __HFN_INT_CPE_Q3                   0x00000008U
-#define __HFN_INT_CPE_Q4                   0x00000010U
-#define __HFN_INT_CPE_Q5                   0x00000020U
-#define __HFN_INT_CPE_Q6                   0x00000040U
-#define __HFN_INT_CPE_Q7                   0x00000080U
-#define __HFN_INT_RME_Q0                   0x00000100U
-#define __HFN_INT_RME_Q1                   0x00000200U
-#define __HFN_INT_RME_Q2                   0x00000400U
-#define __HFN_INT_RME_Q3                   0x00000800U
-#define __HFN_INT_RME_Q4                   0x00001000U
-#define __HFN_INT_RME_Q5                   0x00002000U
-#define __HFN_INT_RME_Q6                   0x00004000U
-#define __HFN_INT_RME_Q7                   0x00008000U
-#define __HFN_INT_ERR_EMC                  0x00010000U
-#define __HFN_INT_ERR_LPU0                 0x00020000U
-#define __HFN_INT_ERR_LPU1                 0x00040000U
-#define __HFN_INT_ERR_PSS                  0x00080000U
-#define __HFN_INT_MBOX_LPU0                0x00100000U
-#define __HFN_INT_MBOX_LPU1                0x00200000U
-#define __HFN_INT_MBOX1_LPU0               0x00400000U
-#define __HFN_INT_MBOX1_LPU1               0x00800000U
-#define __HFN_INT_CPE_MASK                 0x000000ffU
-#define __HFN_INT_RME_MASK                 0x0000ff00U
-
-
-/*
- * crossbow memory map.
- */
-#define PSS_SMEM_PAGE_START	0x8000
-#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
-#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff)
-
-/*
- * End of crossbow memory map
- */
-
-
-#endif /* __BFI_CBREG_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_cee.h b/drivers/scsi/bfa/include/bfi/bfi_cee.h
deleted file mode 100644
index 09705965..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_cee.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-/**
- *  Copyright (c) 2006-2009 Brocade Communications Systems, Inc.
- *  All rights reserved.
- *
- *  bfi_dcbx.h BFI Interface (Mailbox commands and related structures)
- * between host driver and DCBX/LLDP firmware module.
- *
-**/
-
-#ifndef __BFI_CEE_H__
-#define __BFI_CEE_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-
-enum bfi_cee_h2i_msgs_e {
-	BFI_CEE_H2I_GET_CFG_REQ = 1,
-	BFI_CEE_H2I_RESET_STATS = 2,
-	BFI_CEE_H2I_GET_STATS_REQ = 3,
-};
-
-
-enum bfi_cee_i2h_msgs_e {
-	BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1),
-	BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2),
-	BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3),
-};
-
-
-/* Data structures */
-
-/*
- * BFI_CEE_H2I_RESET_STATS
- */
-struct bfi_lldp_reset_stats_s {
-	struct bfi_mhdr_s  mh;
-};
-
-/*
- * BFI_CEE_H2I_RESET_STATS
- */
-struct bfi_cee_reset_stats_s {
-	struct bfi_mhdr_s  mh;
-};
-
-/*
- * BFI_CEE_H2I_GET_CFG_REQ
- */
-struct bfi_cee_get_req_s {
-	struct bfi_mhdr_s  mh;
-	union bfi_addr_u   dma_addr;
-};
-
-
-/*
- * BFI_CEE_I2H_GET_CFG_RSP
- */
-struct bfi_cee_get_rsp_s {
-	struct bfi_mhdr_s  mh;
-	u8            cmd_status;
-	u8            rsvd[3];
-};
-
-/*
- * BFI_CEE_H2I_GET_STATS_REQ
- */
-struct bfi_cee_stats_req_s {
-	struct bfi_mhdr_s  mh;
-	union bfi_addr_u   dma_addr;
-};
-
-
-/*
- * BFI_CEE_I2H_GET_STATS_RSP
- */
-struct bfi_cee_stats_rsp_s {
-	struct bfi_mhdr_s  mh;
-	u8 		   cmd_status;
-	u8 		   rsvd[3];
-};
-
-
-
-union bfi_cee_h2i_msg_u {
-	struct bfi_mhdr_s           mh;
-	struct bfi_cee_get_req_s   get_req;
-	struct bfi_cee_stats_req_s stats_req;
-};
-
-
-union bfi_cee_i2h_msg_u {
-	struct bfi_mhdr_s         mh;
-	struct bfi_cee_get_rsp_s  get_rsp;
-	struct bfi_cee_stats_rsp_s stats_rsp;
-};
-
-#pragma pack()
-
-
-#endif /* __BFI_CEE_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_ctreg.h b/drivers/scsi/bfa/include/bfi/bfi_ctreg.h
deleted file mode 100644
index c0ef5a9..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_ctreg.h
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/*
- * bfi_ctreg.h catapult host block register definitions
- *
- * !!! Do not edit. Auto generated. !!!
- */
-
-#ifndef __BFI_CTREG_H__
-#define __BFI_CTREG_H__
-
-
-#define HOSTFN0_LPU_MBOX0_0              0x00019200
-#define HOSTFN1_LPU_MBOX0_8              0x00019260
-#define LPU_HOSTFN0_MBOX0_0              0x00019280
-#define LPU_HOSTFN1_MBOX0_8              0x000192e0
-#define HOSTFN2_LPU_MBOX0_0              0x00019400
-#define HOSTFN3_LPU_MBOX0_8              0x00019460
-#define LPU_HOSTFN2_MBOX0_0              0x00019480
-#define LPU_HOSTFN3_MBOX0_8              0x000194e0
-#define HOSTFN0_INT_STATUS               0x00014000
-#define __HOSTFN0_HALT_OCCURRED          0x01000000
-#define __HOSTFN0_INT_STATUS_LVL_MK      0x00f00000
-#define __HOSTFN0_INT_STATUS_LVL_SH      20
-#define __HOSTFN0_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
-#define __HOSTFN0_INT_STATUS_P_MK        0x000f0000
-#define __HOSTFN0_INT_STATUS_P_SH        16
-#define __HOSTFN0_INT_STATUS_P(_v)       ((_v) << __HOSTFN0_INT_STATUS_P_SH)
-#define __HOSTFN0_INT_STATUS_F           0x0000ffff
-#define HOSTFN0_INT_MSK                  0x00014004
-#define HOST_PAGE_NUM_FN0                0x00014008
-#define __HOST_PAGE_NUM_FN               0x000001ff
-#define HOST_MSIX_ERR_INDEX_FN0          0x0001400c
-#define __MSIX_ERR_INDEX_FN              0x000001ff
-#define HOSTFN1_INT_STATUS               0x00014100
-#define __HOSTFN1_HALT_OCCURRED          0x01000000
-#define __HOSTFN1_INT_STATUS_LVL_MK      0x00f00000
-#define __HOSTFN1_INT_STATUS_LVL_SH      20
-#define __HOSTFN1_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
-#define __HOSTFN1_INT_STATUS_P_MK        0x000f0000
-#define __HOSTFN1_INT_STATUS_P_SH        16
-#define __HOSTFN1_INT_STATUS_P(_v)       ((_v) << __HOSTFN1_INT_STATUS_P_SH)
-#define __HOSTFN1_INT_STATUS_F           0x0000ffff
-#define HOSTFN1_INT_MSK                  0x00014104
-#define HOST_PAGE_NUM_FN1                0x00014108
-#define HOST_MSIX_ERR_INDEX_FN1          0x0001410c
-#define APP_PLL_425_CTL_REG              0x00014204
-#define __P_425_PLL_LOCK                 0x80000000
-#define __APP_PLL_425_SRAM_USE_100MHZ    0x00100000
-#define __APP_PLL_425_RESET_TIMER_MK     0x000e0000
-#define __APP_PLL_425_RESET_TIMER_SH     17
-#define __APP_PLL_425_RESET_TIMER(_v)    ((_v) << __APP_PLL_425_RESET_TIMER_SH)
-#define __APP_PLL_425_LOGIC_SOFT_RESET   0x00010000
-#define __APP_PLL_425_CNTLMT0_1_MK       0x0000c000
-#define __APP_PLL_425_CNTLMT0_1_SH       14
-#define __APP_PLL_425_CNTLMT0_1(_v)      ((_v) << __APP_PLL_425_CNTLMT0_1_SH)
-#define __APP_PLL_425_JITLMT0_1_MK       0x00003000
-#define __APP_PLL_425_JITLMT0_1_SH       12
-#define __APP_PLL_425_JITLMT0_1(_v)      ((_v) << __APP_PLL_425_JITLMT0_1_SH)
-#define __APP_PLL_425_HREF               0x00000800
-#define __APP_PLL_425_HDIV               0x00000400
-#define __APP_PLL_425_P0_1_MK            0x00000300
-#define __APP_PLL_425_P0_1_SH            8
-#define __APP_PLL_425_P0_1(_v)           ((_v) << __APP_PLL_425_P0_1_SH)
-#define __APP_PLL_425_Z0_2_MK            0x000000e0
-#define __APP_PLL_425_Z0_2_SH            5
-#define __APP_PLL_425_Z0_2(_v)           ((_v) << __APP_PLL_425_Z0_2_SH)
-#define __APP_PLL_425_RSEL200500         0x00000010
-#define __APP_PLL_425_ENARST             0x00000008
-#define __APP_PLL_425_BYPASS             0x00000004
-#define __APP_PLL_425_LRESETN            0x00000002
-#define __APP_PLL_425_ENABLE             0x00000001
-#define APP_PLL_312_CTL_REG              0x00014208
-#define __P_312_PLL_LOCK                 0x80000000
-#define __ENABLE_MAC_AHB_1               0x00800000
-#define __ENABLE_MAC_AHB_0               0x00400000
-#define __ENABLE_MAC_1                   0x00200000
-#define __ENABLE_MAC_0                   0x00100000
-#define __APP_PLL_312_RESET_TIMER_MK     0x000e0000
-#define __APP_PLL_312_RESET_TIMER_SH     17
-#define __APP_PLL_312_RESET_TIMER(_v)    ((_v) << __APP_PLL_312_RESET_TIMER_SH)
-#define __APP_PLL_312_LOGIC_SOFT_RESET   0x00010000
-#define __APP_PLL_312_CNTLMT0_1_MK       0x0000c000
-#define __APP_PLL_312_CNTLMT0_1_SH       14
-#define __APP_PLL_312_CNTLMT0_1(_v)      ((_v) << __APP_PLL_312_CNTLMT0_1_SH)
-#define __APP_PLL_312_JITLMT0_1_MK       0x00003000
-#define __APP_PLL_312_JITLMT0_1_SH       12
-#define __APP_PLL_312_JITLMT0_1(_v)      ((_v) << __APP_PLL_312_JITLMT0_1_SH)
-#define __APP_PLL_312_HREF               0x00000800
-#define __APP_PLL_312_HDIV               0x00000400
-#define __APP_PLL_312_P0_1_MK            0x00000300
-#define __APP_PLL_312_P0_1_SH            8
-#define __APP_PLL_312_P0_1(_v)           ((_v) << __APP_PLL_312_P0_1_SH)
-#define __APP_PLL_312_Z0_2_MK            0x000000e0
-#define __APP_PLL_312_Z0_2_SH            5
-#define __APP_PLL_312_Z0_2(_v)           ((_v) << __APP_PLL_312_Z0_2_SH)
-#define __APP_PLL_312_RSEL200500         0x00000010
-#define __APP_PLL_312_ENARST             0x00000008
-#define __APP_PLL_312_BYPASS             0x00000004
-#define __APP_PLL_312_LRESETN            0x00000002
-#define __APP_PLL_312_ENABLE             0x00000001
-#define MBIST_CTL_REG                    0x00014220
-#define __EDRAM_BISTR_START              0x00000004
-#define __MBIST_RESET                    0x00000002
-#define __MBIST_START                    0x00000001
-#define MBIST_STAT_REG                   0x00014224
-#define __EDRAM_BISTR_STATUS             0x00000008
-#define __EDRAM_BISTR_DONE               0x00000004
-#define __MEM_BIT_STATUS                 0x00000002
-#define __MBIST_DONE                     0x00000001
-#define HOST_SEM0_REG                    0x00014230
-#define __HOST_SEMAPHORE                 0x00000001
-#define HOST_SEM1_REG                    0x00014234
-#define HOST_SEM2_REG                    0x00014238
-#define HOST_SEM3_REG                    0x0001423c
-#define HOST_SEM0_INFO_REG               0x00014240
-#define HOST_SEM1_INFO_REG               0x00014244
-#define HOST_SEM2_INFO_REG               0x00014248
-#define HOST_SEM3_INFO_REG               0x0001424c
-#define ETH_MAC_SER_REG                  0x00014288
-#define __APP_EMS_CKBUFAMPIN             0x00000020
-#define __APP_EMS_REFCLKSEL              0x00000010
-#define __APP_EMS_CMLCKSEL               0x00000008
-#define __APP_EMS_REFCKBUFEN2            0x00000004
-#define __APP_EMS_REFCKBUFEN1            0x00000002
-#define __APP_EMS_CHANNEL_SEL            0x00000001
-#define HOSTFN2_INT_STATUS               0x00014300
-#define __HOSTFN2_HALT_OCCURRED          0x01000000
-#define __HOSTFN2_INT_STATUS_LVL_MK      0x00f00000
-#define __HOSTFN2_INT_STATUS_LVL_SH      20
-#define __HOSTFN2_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
-#define __HOSTFN2_INT_STATUS_P_MK        0x000f0000
-#define __HOSTFN2_INT_STATUS_P_SH        16
-#define __HOSTFN2_INT_STATUS_P(_v)       ((_v) << __HOSTFN2_INT_STATUS_P_SH)
-#define __HOSTFN2_INT_STATUS_F           0x0000ffff
-#define HOSTFN2_INT_MSK                  0x00014304
-#define HOST_PAGE_NUM_FN2                0x00014308
-#define HOST_MSIX_ERR_INDEX_FN2          0x0001430c
-#define HOSTFN3_INT_STATUS               0x00014400
-#define __HALT_OCCURRED                  0x01000000
-#define __HOSTFN3_INT_STATUS_LVL_MK      0x00f00000
-#define __HOSTFN3_INT_STATUS_LVL_SH      20
-#define __HOSTFN3_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
-#define __HOSTFN3_INT_STATUS_P_MK        0x000f0000
-#define __HOSTFN3_INT_STATUS_P_SH        16
-#define __HOSTFN3_INT_STATUS_P(_v)       ((_v) << __HOSTFN3_INT_STATUS_P_SH)
-#define __HOSTFN3_INT_STATUS_F           0x0000ffff
-#define HOSTFN3_INT_MSK                  0x00014404
-#define HOST_PAGE_NUM_FN3                0x00014408
-#define HOST_MSIX_ERR_INDEX_FN3          0x0001440c
-#define FNC_ID_REG                       0x00014600
-#define __FUNCTION_NUMBER                0x00000007
-#define FNC_PERS_REG                     0x00014604
-#define __F3_FUNCTION_ACTIVE             0x80000000
-#define __F3_FUNCTION_MODE               0x40000000
-#define __F3_PORT_MAP_MK                 0x30000000
-#define __F3_PORT_MAP_SH                 28
-#define __F3_PORT_MAP(_v)                ((_v) << __F3_PORT_MAP_SH)
-#define __F3_VM_MODE                     0x08000000
-#define __F3_INTX_STATUS_MK              0x07000000
-#define __F3_INTX_STATUS_SH              24
-#define __F3_INTX_STATUS(_v)             ((_v) << __F3_INTX_STATUS_SH)
-#define __F2_FUNCTION_ACTIVE             0x00800000
-#define __F2_FUNCTION_MODE               0x00400000
-#define __F2_PORT_MAP_MK                 0x00300000
-#define __F2_PORT_MAP_SH                 20
-#define __F2_PORT_MAP(_v)                ((_v) << __F2_PORT_MAP_SH)
-#define __F2_VM_MODE                     0x00080000
-#define __F2_INTX_STATUS_MK              0x00070000
-#define __F2_INTX_STATUS_SH              16
-#define __F2_INTX_STATUS(_v)             ((_v) << __F2_INTX_STATUS_SH)
-#define __F1_FUNCTION_ACTIVE             0x00008000
-#define __F1_FUNCTION_MODE               0x00004000
-#define __F1_PORT_MAP_MK                 0x00003000
-#define __F1_PORT_MAP_SH                 12
-#define __F1_PORT_MAP(_v)                ((_v) << __F1_PORT_MAP_SH)
-#define __F1_VM_MODE                     0x00000800
-#define __F1_INTX_STATUS_MK              0x00000700
-#define __F1_INTX_STATUS_SH              8
-#define __F1_INTX_STATUS(_v)             ((_v) << __F1_INTX_STATUS_SH)
-#define __F0_FUNCTION_ACTIVE             0x00000080
-#define __F0_FUNCTION_MODE               0x00000040
-#define __F0_PORT_MAP_MK                 0x00000030
-#define __F0_PORT_MAP_SH                 4
-#define __F0_PORT_MAP(_v)                ((_v) << __F0_PORT_MAP_SH)
-#define __F0_VM_MODE                     0x00000008
-#define __F0_INTX_STATUS                 0x00000007
-enum {
-    __F0_INTX_STATUS_MSIX            = 0x0,
-    __F0_INTX_STATUS_INTA            = 0x1,
-    __F0_INTX_STATUS_INTB            = 0x2,
-    __F0_INTX_STATUS_INTC            = 0x3,
-    __F0_INTX_STATUS_INTD            = 0x4,
-};
-#define OP_MODE                          0x0001460c
-#define __APP_ETH_CLK_LOWSPEED           0x00000004
-#define __GLOBAL_CORECLK_HALFSPEED       0x00000002
-#define __GLOBAL_FCOE_MODE               0x00000001
-#define HOST_SEM4_REG                    0x00014610
-#define HOST_SEM5_REG                    0x00014614
-#define HOST_SEM6_REG                    0x00014618
-#define HOST_SEM7_REG                    0x0001461c
-#define HOST_SEM4_INFO_REG               0x00014620
-#define HOST_SEM5_INFO_REG               0x00014624
-#define HOST_SEM6_INFO_REG               0x00014628
-#define HOST_SEM7_INFO_REG               0x0001462c
-#define HOSTFN0_LPU0_MBOX0_CMD_STAT      0x00019000
-#define __HOSTFN0_LPU0_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN0_LPU0_MBOX0_INFO_SH     1
-#define __HOSTFN0_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN0_LPU1_MBOX0_CMD_STAT      0x00019004
-#define __HOSTFN0_LPU1_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN0_LPU1_MBOX0_INFO_SH     1
-#define __HOSTFN0_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS  0x00000001
-#define LPU0_HOSTFN0_MBOX0_CMD_STAT      0x00019008
-#define __LPU0_HOSTFN0_MBOX0_INFO_MK     0xfffffffe
-#define __LPU0_HOSTFN0_MBOX0_INFO_SH     1
-#define __LPU0_HOSTFN0_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS  0x00000001
-#define LPU1_HOSTFN0_MBOX0_CMD_STAT      0x0001900c
-#define __LPU1_HOSTFN0_MBOX0_INFO_MK     0xfffffffe
-#define __LPU1_HOSTFN0_MBOX0_INFO_SH     1
-#define __LPU1_HOSTFN0_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN1_LPU0_MBOX0_CMD_STAT      0x00019010
-#define __HOSTFN1_LPU0_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN1_LPU0_MBOX0_INFO_SH     1
-#define __HOSTFN1_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN1_LPU1_MBOX0_CMD_STAT      0x00019014
-#define __HOSTFN1_LPU1_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN1_LPU1_MBOX0_INFO_SH     1
-#define __HOSTFN1_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS  0x00000001
-#define LPU0_HOSTFN1_MBOX0_CMD_STAT      0x00019018
-#define __LPU0_HOSTFN1_MBOX0_INFO_MK     0xfffffffe
-#define __LPU0_HOSTFN1_MBOX0_INFO_SH     1
-#define __LPU0_HOSTFN1_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS  0x00000001
-#define LPU1_HOSTFN1_MBOX0_CMD_STAT      0x0001901c
-#define __LPU1_HOSTFN1_MBOX0_INFO_MK     0xfffffffe
-#define __LPU1_HOSTFN1_MBOX0_INFO_SH     1
-#define __LPU1_HOSTFN1_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN2_LPU0_MBOX0_CMD_STAT      0x00019150
-#define __HOSTFN2_LPU0_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN2_LPU0_MBOX0_INFO_SH     1
-#define __HOSTFN2_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN2_LPU1_MBOX0_CMD_STAT      0x00019154
-#define __HOSTFN2_LPU1_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN2_LPU1_MBOX0_INFO_SH     1
-#define __HOSTFN2_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN2_MBOX0_CMD_STAT      0x00019158
-#define __LPU0_HOSTFN2_MBOX0_INFO_MK     0xfffffffe
-#define __LPU0_HOSTFN2_MBOX0_INFO_SH     1
-#define __LPU0_HOSTFN2_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS  0x00000001
-#define LPU1_HOSTFN2_MBOX0_CMD_STAT      0x0001915c
-#define __LPU1_HOSTFN2_MBOX0_INFO_MK     0xfffffffe
-#define __LPU1_HOSTFN2_MBOX0_INFO_SH     1
-#define __LPU1_HOSTFN2_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN3_LPU0_MBOX0_CMD_STAT      0x00019160
-#define __HOSTFN3_LPU0_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN3_LPU0_MBOX0_INFO_SH     1
-#define __HOSTFN3_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN3_LPU1_MBOX0_CMD_STAT      0x00019164
-#define __HOSTFN3_LPU1_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN3_LPU1_MBOX0_INFO_SH     1
-#define __HOSTFN3_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS  0x00000001
-#define LPU0_HOSTFN3_MBOX0_CMD_STAT      0x00019168
-#define __LPU0_HOSTFN3_MBOX0_INFO_MK     0xfffffffe
-#define __LPU0_HOSTFN3_MBOX0_INFO_SH     1
-#define __LPU0_HOSTFN3_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS  0x00000001
-#define LPU1_HOSTFN3_MBOX0_CMD_STAT      0x0001916c
-#define __LPU1_HOSTFN3_MBOX0_INFO_MK     0xfffffffe
-#define __LPU1_HOSTFN3_MBOX0_INFO_SH     1
-#define __LPU1_HOSTFN3_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS  0x00000001
-#define FW_INIT_HALT_P0                  0x000191ac
-#define __FW_INIT_HALT_P                 0x00000001
-#define FW_INIT_HALT_P1                  0x000191bc
-#define CPE_PI_PTR_Q0                    0x00038000
-#define __CPE_PI_UNUSED_MK               0xffff0000
-#define __CPE_PI_UNUSED_SH               16
-#define __CPE_PI_UNUSED(_v)              ((_v) << __CPE_PI_UNUSED_SH)
-#define __CPE_PI_PTR                     0x0000ffff
-#define CPE_PI_PTR_Q1                    0x00038040
-#define CPE_CI_PTR_Q0                    0x00038004
-#define __CPE_CI_UNUSED_MK               0xffff0000
-#define __CPE_CI_UNUSED_SH               16
-#define __CPE_CI_UNUSED(_v)              ((_v) << __CPE_CI_UNUSED_SH)
-#define __CPE_CI_PTR                     0x0000ffff
-#define CPE_CI_PTR_Q1                    0x00038044
-#define CPE_DEPTH_Q0                     0x00038008
-#define __CPE_DEPTH_UNUSED_MK            0xf8000000
-#define __CPE_DEPTH_UNUSED_SH            27
-#define __CPE_DEPTH_UNUSED(_v)           ((_v) << __CPE_DEPTH_UNUSED_SH)
-#define __CPE_MSIX_VEC_INDEX_MK          0x07ff0000
-#define __CPE_MSIX_VEC_INDEX_SH          16
-#define __CPE_MSIX_VEC_INDEX(_v)         ((_v) << __CPE_MSIX_VEC_INDEX_SH)
-#define __CPE_DEPTH                      0x0000ffff
-#define CPE_DEPTH_Q1                     0x00038048
-#define CPE_QCTRL_Q0                     0x0003800c
-#define __CPE_CTRL_UNUSED30_MK           0xfc000000
-#define __CPE_CTRL_UNUSED30_SH           26
-#define __CPE_CTRL_UNUSED30(_v)          ((_v) << __CPE_CTRL_UNUSED30_SH)
-#define __CPE_FUNC_INT_CTRL_MK           0x03000000
-#define __CPE_FUNC_INT_CTRL_SH           24
-#define __CPE_FUNC_INT_CTRL(_v)          ((_v) << __CPE_FUNC_INT_CTRL_SH)
-enum {
-    __CPE_FUNC_INT_CTRL_DISABLE      = 0x0,
-    __CPE_FUNC_INT_CTRL_F2NF         = 0x1,
-    __CPE_FUNC_INT_CTRL_3QUART       = 0x2,
-    __CPE_FUNC_INT_CTRL_HALF         = 0x3,
-};
-#define __CPE_CTRL_UNUSED20_MK           0x00f00000
-#define __CPE_CTRL_UNUSED20_SH           20
-#define __CPE_CTRL_UNUSED20(_v)          ((_v) << __CPE_CTRL_UNUSED20_SH)
-#define __CPE_SCI_TH_MK                  0x000f0000
-#define __CPE_SCI_TH_SH                  16
-#define __CPE_SCI_TH(_v)                 ((_v) << __CPE_SCI_TH_SH)
-#define __CPE_CTRL_UNUSED10_MK           0x0000c000
-#define __CPE_CTRL_UNUSED10_SH           14
-#define __CPE_CTRL_UNUSED10(_v)          ((_v) << __CPE_CTRL_UNUSED10_SH)
-#define __CPE_ACK_PENDING                0x00002000
-#define __CPE_CTRL_UNUSED40_MK           0x00001c00
-#define __CPE_CTRL_UNUSED40_SH           10
-#define __CPE_CTRL_UNUSED40(_v)          ((_v) << __CPE_CTRL_UNUSED40_SH)
-#define __CPE_PCIEID_MK                  0x00000300
-#define __CPE_PCIEID_SH                  8
-#define __CPE_PCIEID(_v)                 ((_v) << __CPE_PCIEID_SH)
-#define __CPE_CTRL_UNUSED00_MK           0x000000fe
-#define __CPE_CTRL_UNUSED00_SH           1
-#define __CPE_CTRL_UNUSED00(_v)          ((_v) << __CPE_CTRL_UNUSED00_SH)
-#define __CPE_ESIZE                      0x00000001
-#define CPE_QCTRL_Q1                     0x0003804c
-#define __CPE_CTRL_UNUSED31_MK           0xfc000000
-#define __CPE_CTRL_UNUSED31_SH           26
-#define __CPE_CTRL_UNUSED31(_v)          ((_v) << __CPE_CTRL_UNUSED31_SH)
-#define __CPE_CTRL_UNUSED21_MK           0x00f00000
-#define __CPE_CTRL_UNUSED21_SH           20
-#define __CPE_CTRL_UNUSED21(_v)          ((_v) << __CPE_CTRL_UNUSED21_SH)
-#define __CPE_CTRL_UNUSED11_MK           0x0000c000
-#define __CPE_CTRL_UNUSED11_SH           14
-#define __CPE_CTRL_UNUSED11(_v)          ((_v) << __CPE_CTRL_UNUSED11_SH)
-#define __CPE_CTRL_UNUSED41_MK           0x00001c00
-#define __CPE_CTRL_UNUSED41_SH           10
-#define __CPE_CTRL_UNUSED41(_v)          ((_v) << __CPE_CTRL_UNUSED41_SH)
-#define __CPE_CTRL_UNUSED01_MK           0x000000fe
-#define __CPE_CTRL_UNUSED01_SH           1
-#define __CPE_CTRL_UNUSED01(_v)          ((_v) << __CPE_CTRL_UNUSED01_SH)
-#define RME_PI_PTR_Q0                    0x00038020
-#define __LATENCY_TIME_STAMP_MK          0xffff0000
-#define __LATENCY_TIME_STAMP_SH          16
-#define __LATENCY_TIME_STAMP(_v)         ((_v) << __LATENCY_TIME_STAMP_SH)
-#define __RME_PI_PTR                     0x0000ffff
-#define RME_PI_PTR_Q1                    0x00038060
-#define RME_CI_PTR_Q0                    0x00038024
-#define __DELAY_TIME_STAMP_MK            0xffff0000
-#define __DELAY_TIME_STAMP_SH            16
-#define __DELAY_TIME_STAMP(_v)           ((_v) << __DELAY_TIME_STAMP_SH)
-#define __RME_CI_PTR                     0x0000ffff
-#define RME_CI_PTR_Q1                    0x00038064
-#define RME_DEPTH_Q0                     0x00038028
-#define __RME_DEPTH_UNUSED_MK            0xf8000000
-#define __RME_DEPTH_UNUSED_SH            27
-#define __RME_DEPTH_UNUSED(_v)           ((_v) << __RME_DEPTH_UNUSED_SH)
-#define __RME_MSIX_VEC_INDEX_MK          0x07ff0000
-#define __RME_MSIX_VEC_INDEX_SH          16
-#define __RME_MSIX_VEC_INDEX(_v)         ((_v) << __RME_MSIX_VEC_INDEX_SH)
-#define __RME_DEPTH                      0x0000ffff
-#define RME_DEPTH_Q1                     0x00038068
-#define RME_QCTRL_Q0                     0x0003802c
-#define __RME_INT_LATENCY_TIMER_MK       0xff000000
-#define __RME_INT_LATENCY_TIMER_SH       24
-#define __RME_INT_LATENCY_TIMER(_v)      ((_v) << __RME_INT_LATENCY_TIMER_SH)
-#define __RME_INT_DELAY_TIMER_MK         0x00ff0000
-#define __RME_INT_DELAY_TIMER_SH         16
-#define __RME_INT_DELAY_TIMER(_v)        ((_v) << __RME_INT_DELAY_TIMER_SH)
-#define __RME_INT_DELAY_DISABLE          0x00008000
-#define __RME_DLY_DELAY_DISABLE          0x00004000
-#define __RME_ACK_PENDING                0x00002000
-#define __RME_FULL_INTERRUPT_DISABLE     0x00001000
-#define __RME_CTRL_UNUSED10_MK           0x00000c00
-#define __RME_CTRL_UNUSED10_SH           10
-#define __RME_CTRL_UNUSED10(_v)          ((_v) << __RME_CTRL_UNUSED10_SH)
-#define __RME_PCIEID_MK                  0x00000300
-#define __RME_PCIEID_SH                  8
-#define __RME_PCIEID(_v)                 ((_v) << __RME_PCIEID_SH)
-#define __RME_CTRL_UNUSED00_MK           0x000000fe
-#define __RME_CTRL_UNUSED00_SH           1
-#define __RME_CTRL_UNUSED00(_v)          ((_v) << __RME_CTRL_UNUSED00_SH)
-#define __RME_ESIZE                      0x00000001
-#define RME_QCTRL_Q1                     0x0003806c
-#define __RME_CTRL_UNUSED11_MK           0x00000c00
-#define __RME_CTRL_UNUSED11_SH           10
-#define __RME_CTRL_UNUSED11(_v)          ((_v) << __RME_CTRL_UNUSED11_SH)
-#define __RME_CTRL_UNUSED01_MK           0x000000fe
-#define __RME_CTRL_UNUSED01_SH           1
-#define __RME_CTRL_UNUSED01(_v)          ((_v) << __RME_CTRL_UNUSED01_SH)
-#define PSS_CTL_REG                      0x00018800
-#define __PSS_I2C_CLK_DIV_MK             0x007f0000
-#define __PSS_I2C_CLK_DIV_SH             16
-#define __PSS_I2C_CLK_DIV(_v)            ((_v) << __PSS_I2C_CLK_DIV_SH)
-#define __PSS_LMEM_INIT_DONE             0x00001000
-#define __PSS_LMEM_RESET                 0x00000200
-#define __PSS_LMEM_INIT_EN               0x00000100
-#define __PSS_LPU1_RESET                 0x00000002
-#define __PSS_LPU0_RESET                 0x00000001
-#define PSS_ERR_STATUS_REG               0x00018810
-#define __PSS_LPU1_TCM_READ_ERR          0x00200000
-#define __PSS_LPU0_TCM_READ_ERR          0x00100000
-#define __PSS_LMEM5_CORR_ERR             0x00080000
-#define __PSS_LMEM4_CORR_ERR             0x00040000
-#define __PSS_LMEM3_CORR_ERR             0x00020000
-#define __PSS_LMEM2_CORR_ERR             0x00010000
-#define __PSS_LMEM1_CORR_ERR             0x00008000
-#define __PSS_LMEM0_CORR_ERR             0x00004000
-#define __PSS_LMEM5_UNCORR_ERR           0x00002000
-#define __PSS_LMEM4_UNCORR_ERR           0x00001000
-#define __PSS_LMEM3_UNCORR_ERR           0x00000800
-#define __PSS_LMEM2_UNCORR_ERR           0x00000400
-#define __PSS_LMEM1_UNCORR_ERR           0x00000200
-#define __PSS_LMEM0_UNCORR_ERR           0x00000100
-#define __PSS_BAL_PERR                   0x00000080
-#define __PSS_DIP_IF_ERR                 0x00000040
-#define __PSS_IOH_IF_ERR                 0x00000020
-#define __PSS_TDS_IF_ERR                 0x00000010
-#define __PSS_RDS_IF_ERR                 0x00000008
-#define __PSS_SGM_IF_ERR                 0x00000004
-#define __PSS_LPU1_RAM_ERR               0x00000002
-#define __PSS_LPU0_RAM_ERR               0x00000001
-#define ERR_SET_REG			 0x00018818
-#define __PSS_ERR_STATUS_SET		 0x003fffff
-#define PMM_1T_RESET_REG_P0              0x0002381c
-#define __PMM_1T_RESET_P                 0x00000001
-#define PMM_1T_RESET_REG_P1              0x00023c1c
-#define HQM_QSET0_RXQ_DRBL_P0            0x00038000
-#define __RXQ0_ADD_VECTORS_P             0x80000000
-#define __RXQ0_STOP_P                    0x40000000
-#define __RXQ0_PRD_PTR_P                 0x0000ffff
-#define HQM_QSET1_RXQ_DRBL_P0            0x00038080
-#define __RXQ1_ADD_VECTORS_P             0x80000000
-#define __RXQ1_STOP_P                    0x40000000
-#define __RXQ1_PRD_PTR_P                 0x0000ffff
-#define HQM_QSET0_RXQ_DRBL_P1            0x0003c000
-#define HQM_QSET1_RXQ_DRBL_P1            0x0003c080
-#define HQM_QSET0_TXQ_DRBL_P0            0x00038020
-#define __TXQ0_ADD_VECTORS_P             0x80000000
-#define __TXQ0_STOP_P                    0x40000000
-#define __TXQ0_PRD_PTR_P                 0x0000ffff
-#define HQM_QSET1_TXQ_DRBL_P0            0x000380a0
-#define __TXQ1_ADD_VECTORS_P             0x80000000
-#define __TXQ1_STOP_P                    0x40000000
-#define __TXQ1_PRD_PTR_P                 0x0000ffff
-#define HQM_QSET0_TXQ_DRBL_P1            0x0003c020
-#define HQM_QSET1_TXQ_DRBL_P1            0x0003c0a0
-#define HQM_QSET0_IB_DRBL_1_P0           0x00038040
-#define __IB1_0_ACK_P                    0x80000000
-#define __IB1_0_DISABLE_P                0x40000000
-#define __IB1_0_NUM_OF_ACKED_EVENTS_P    0x0000ffff
-#define HQM_QSET1_IB_DRBL_1_P0           0x000380c0
-#define __IB1_1_ACK_P                    0x80000000
-#define __IB1_1_DISABLE_P                0x40000000
-#define __IB1_1_NUM_OF_ACKED_EVENTS_P    0x0000ffff
-#define HQM_QSET0_IB_DRBL_1_P1           0x0003c040
-#define HQM_QSET1_IB_DRBL_1_P1           0x0003c0c0
-#define HQM_QSET0_IB_DRBL_2_P0           0x00038060
-#define __IB2_0_ACK_P                    0x80000000
-#define __IB2_0_DISABLE_P                0x40000000
-#define __IB2_0_NUM_OF_ACKED_EVENTS_P    0x0000ffff
-#define HQM_QSET1_IB_DRBL_2_P0           0x000380e0
-#define __IB2_1_ACK_P                    0x80000000
-#define __IB2_1_DISABLE_P                0x40000000
-#define __IB2_1_NUM_OF_ACKED_EVENTS_P    0x0000ffff
-#define HQM_QSET0_IB_DRBL_2_P1           0x0003c060
-#define HQM_QSET1_IB_DRBL_2_P1           0x0003c0e0
-
-
-/*
- * These definitions are either in error/missing in spec. Its auto-generated
- * from hard coded values in regparse.pl.
- */
-#define __EMPHPOST_AT_4G_MK_FIX          0x0000001c
-#define __EMPHPOST_AT_4G_SH_FIX          0x00000002
-#define __EMPHPRE_AT_4G_FIX              0x00000003
-#define __SFP_TXRATE_EN_FIX              0x00000100
-#define __SFP_RXRATE_EN_FIX              0x00000080
-
-
-/*
- * These register definitions are auto-generated from hard coded values
- * in regparse.pl.
- */
-
-
-/*
- * These register mapping definitions are auto-generated from mapping tables
- * in regparse.pl.
- */
-#define BFA_IOC0_HBEAT_REG               HOST_SEM0_INFO_REG
-#define BFA_IOC0_STATE_REG               HOST_SEM1_INFO_REG
-#define BFA_IOC1_HBEAT_REG               HOST_SEM2_INFO_REG
-#define BFA_IOC1_STATE_REG               HOST_SEM3_INFO_REG
-#define BFA_FW_USE_COUNT                 HOST_SEM4_INFO_REG
-
-#define CPE_DEPTH_Q(__n) \
-	(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
-#define CPE_QCTRL_Q(__n) \
-	(CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
-#define CPE_PI_PTR_Q(__n) \
-	(CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
-#define CPE_CI_PTR_Q(__n) \
-	(CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
-#define RME_DEPTH_Q(__n) \
-	(RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
-#define RME_QCTRL_Q(__n) \
-	(RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
-#define RME_PI_PTR_Q(__n) \
-	(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
-#define RME_CI_PTR_Q(__n) \
-	(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
-#define HQM_QSET_RXQ_DRBL_P0(__n) \
-	(HQM_QSET0_RXQ_DRBL_P0 + (__n) * (HQM_QSET1_RXQ_DRBL_P0 - \
-	HQM_QSET0_RXQ_DRBL_P0))
-#define HQM_QSET_TXQ_DRBL_P0(__n) \
-	(HQM_QSET0_TXQ_DRBL_P0 + (__n) * (HQM_QSET1_TXQ_DRBL_P0 - \
-	HQM_QSET0_TXQ_DRBL_P0))
-#define HQM_QSET_IB_DRBL_1_P0(__n) \
-	(HQM_QSET0_IB_DRBL_1_P0 + (__n) * (HQM_QSET1_IB_DRBL_1_P0 - \
-	HQM_QSET0_IB_DRBL_1_P0))
-#define HQM_QSET_IB_DRBL_2_P0(__n) \
-	(HQM_QSET0_IB_DRBL_2_P0 + (__n) * (HQM_QSET1_IB_DRBL_2_P0 - \
-	HQM_QSET0_IB_DRBL_2_P0))
-#define HQM_QSET_RXQ_DRBL_P1(__n) \
-	(HQM_QSET0_RXQ_DRBL_P1 + (__n) * (HQM_QSET1_RXQ_DRBL_P1 - \
-	HQM_QSET0_RXQ_DRBL_P1))
-#define HQM_QSET_TXQ_DRBL_P1(__n) \
-	(HQM_QSET0_TXQ_DRBL_P1 + (__n) * (HQM_QSET1_TXQ_DRBL_P1 - \
-	HQM_QSET0_TXQ_DRBL_P1))
-#define HQM_QSET_IB_DRBL_1_P1(__n) \
-	(HQM_QSET0_IB_DRBL_1_P1 + (__n) * (HQM_QSET1_IB_DRBL_1_P1 - \
-	HQM_QSET0_IB_DRBL_1_P1))
-#define HQM_QSET_IB_DRBL_2_P1(__n) \
-	(HQM_QSET0_IB_DRBL_2_P1 + (__n) * (HQM_QSET1_IB_DRBL_2_P1 - \
-	HQM_QSET0_IB_DRBL_2_P1))
-
-#define CPE_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
-#define RME_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
-#define CPE_Q_MASK(__q)  ((__q) & 0x3)
-#define RME_Q_MASK(__q)  ((__q) & 0x3)
-
-
-/*
- * PCI MSI-X vector defines
- */
-enum {
-    BFA_MSIX_CPE_Q0 = 0,
-    BFA_MSIX_CPE_Q1 = 1,
-    BFA_MSIX_CPE_Q2 = 2,
-    BFA_MSIX_CPE_Q3 = 3,
-    BFA_MSIX_RME_Q0 = 4,
-    BFA_MSIX_RME_Q1 = 5,
-    BFA_MSIX_RME_Q2 = 6,
-    BFA_MSIX_RME_Q3 = 7,
-    BFA_MSIX_LPU_ERR = 8,
-    BFA_MSIX_CT_MAX = 9,
-};
-
-/*
- * And corresponding host interrupt status bit field defines
- */
-#define __HFN_INT_CPE_Q0                   0x00000001U
-#define __HFN_INT_CPE_Q1                   0x00000002U
-#define __HFN_INT_CPE_Q2                   0x00000004U
-#define __HFN_INT_CPE_Q3                   0x00000008U
-#define __HFN_INT_CPE_Q4                   0x00000010U
-#define __HFN_INT_CPE_Q5                   0x00000020U
-#define __HFN_INT_CPE_Q6                   0x00000040U
-#define __HFN_INT_CPE_Q7                   0x00000080U
-#define __HFN_INT_RME_Q0                   0x00000100U
-#define __HFN_INT_RME_Q1                   0x00000200U
-#define __HFN_INT_RME_Q2                   0x00000400U
-#define __HFN_INT_RME_Q3                   0x00000800U
-#define __HFN_INT_RME_Q4                   0x00001000U
-#define __HFN_INT_RME_Q5                   0x00002000U
-#define __HFN_INT_RME_Q6                   0x00004000U
-#define __HFN_INT_RME_Q7                   0x00008000U
-#define __HFN_INT_ERR_EMC                  0x00010000U
-#define __HFN_INT_ERR_LPU0                 0x00020000U
-#define __HFN_INT_ERR_LPU1                 0x00040000U
-#define __HFN_INT_ERR_PSS                  0x00080000U
-#define __HFN_INT_MBOX_LPU0                0x00100000U
-#define __HFN_INT_MBOX_LPU1                0x00200000U
-#define __HFN_INT_MBOX1_LPU0               0x00400000U
-#define __HFN_INT_MBOX1_LPU1               0x00800000U
-#define __HFN_INT_LL_HALT		   0x01000000U
-#define __HFN_INT_CPE_MASK                 0x000000ffU
-#define __HFN_INT_RME_MASK                 0x0000ff00U
-
-
-/*
- * catapult memory map.
- */
-#define LL_PGN_HQM0                      0x0096
-#define LL_PGN_HQM1                      0x0097
-#define PSS_SMEM_PAGE_START	0x8000
-#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
-#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff)
-
-/*
- * End of catapult memory map
- */
-
-
-#endif /* __BFI_CTREG_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fabric.h b/drivers/scsi/bfa/include/bfi/bfi_fabric.h
deleted file mode 100644
index c0669ed..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_fabric.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_FABRIC_H__
-#define __BFI_FABRIC_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_fabric_h2i_msgs {
-	BFI_FABRIC_H2I_CREATE_REQ	= 1,
-	BFI_FABRIC_H2I_DELETE_REQ	= 2,
-	BFI_FABRIC_H2I_SETAUTH		= 3,
-};
-
-enum bfi_fabric_i2h_msgs {
-	BFI_FABRIC_I2H_CREATE_RSP	= BFA_I2HM(1),
-	BFI_FABRIC_I2H_DELETE_RSP	= BFA_I2HM(2),
-	BFI_FABRIC_I2H_SETAUTH_RSP	= BFA_I2HM(3),
-	BFI_FABRIC_I2H_ONLINE		= BFA_I2HM(4),
-	BFI_FABRIC_I2H_OFFLINE		= BFA_I2HM(5),
-};
-
-struct bfi_fabric_create_req_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u8         vf_en;		/*  virtual fabric enable	*/
-	u8         rsvd;
-	u16        vf_id;		/*  virtual fabric ID		*/
-	wwn_t		pwwn;		/*  port name			*/
-	wwn_t		nwwn;		/*  node name			*/
-};
-
-struct bfi_fabric_create_rsp_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host fabric handle		*/
-	u8         status;		/*  fabric create status	*/
-	u8         rsvd;
-};
-
-struct bfi_fabric_delete_req_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        fw_handle;	/*  firmware fabric handle	*/
-	u16        rsvd;
-};
-
-struct bfi_fabric_delete_rsp_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host fabric handle		*/
-	u8         status;		/*  fabric deletion status	*/
-	u8         rsvd;
-};
-
-#define BFI_FABRIC_AUTHSECRET_LEN	64
-struct bfi_fabric_setauth_req_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        fw_handle;	/*  f/w handle of fabric	*/
-	u8		algorithm;
-	u8		group;
-	u8		secret[BFI_FABRIC_AUTHSECRET_LEN];
-};
-
-union bfi_fabric_h2i_msg_u {
-	bfi_msg_t		*msg;
-	struct bfi_fabric_create_req_s	*create_req;
-	struct bfi_fabric_delete_req_s	*delete_req;
-};
-
-union bfi_fabric_i2h_msg_u {
-	bfi_msg_t		*msg;
-	struct bfi_fabric_create_rsp_s	*create_rsp;
-	struct bfi_fabric_delete_rsp_s	*delete_rsp;
-};
-
-#pragma pack()
-
-#endif /* __BFI_FABRIC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fcpim.h b/drivers/scsi/bfa/include/bfi/bfi_fcpim.h
deleted file mode 100644
index 52c059f..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_fcpim.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_FCPIM_H__
-#define __BFI_FCPIM_H__
-
-#include "bfi.h"
-#include <protocol/fcp.h>
-
-#pragma pack(1)
-
-/*
- * Initiator mode I-T nexus interface defines.
- */
-
-enum bfi_itnim_h2i {
-	BFI_ITNIM_H2I_CREATE_REQ = 1,	/*  i-t nexus creation */
-	BFI_ITNIM_H2I_DELETE_REQ = 2,	/*  i-t nexus deletion */
-};
-
-enum bfi_itnim_i2h {
-	BFI_ITNIM_I2H_CREATE_RSP = BFA_I2HM(1),
-	BFI_ITNIM_I2H_DELETE_RSP = BFA_I2HM(2),
-	BFI_ITNIM_I2H_SLER_EVENT = BFA_I2HM(3),
-};
-
-struct bfi_itnim_create_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		 */
-	u16        fw_handle;	/*  f/w handle for itnim	 */
-	u8         class;		/*  FC class for IO		 */
-	u8         seq_rec;	/*  sequence recovery support	 */
-	u8         msg_no;		/*  seq id of the msg		 */
-};
-
-struct bfi_itnim_create_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		 */
-	u16        bfa_handle;	/*  bfa handle for itnim	 */
-	u8         status;		/*  fcp request status		 */
-	u8         seq_id;		/*  seq id of the msg		 */
-};
-
-struct bfi_itnim_delete_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		 */
-	u16        fw_handle;	/*  f/w itnim handle		 */
-	u8         seq_id;		/*  seq id of the msg		 */
-	u8         rsvd;
-};
-
-struct bfi_itnim_delete_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		 */
-	u16        bfa_handle;	/*  bfa handle for itnim	 */
-	u8         status;		/*  fcp request status		 */
-	u8         seq_id;		/*  seq id of the msg		 */
-};
-
-struct bfi_itnim_sler_event_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		 */
-	u16        bfa_handle;	/*  bfa handle for itnim	 */
-	u16        rsvd;
-};
-
-union bfi_itnim_h2i_msg_u {
-	struct bfi_itnim_create_req_s *create_req;
-	struct bfi_itnim_delete_req_s *delete_req;
-	struct bfi_msg_s      *msg;
-};
-
-union bfi_itnim_i2h_msg_u {
-	struct bfi_itnim_create_rsp_s *create_rsp;
-	struct bfi_itnim_delete_rsp_s *delete_rsp;
-	struct bfi_itnim_sler_event_s *sler_event;
-	struct bfi_msg_s      *msg;
-};
-
-/*
- * Initiator mode IO interface defines.
- */
-
-enum bfi_ioim_h2i {
-	BFI_IOIM_H2I_IOABORT_REQ = 1,	/*  IO abort request	 */
-	BFI_IOIM_H2I_IOCLEANUP_REQ = 2,	/*  IO cleanup request	 */
-};
-
-enum bfi_ioim_i2h {
-	BFI_IOIM_I2H_IO_RSP = BFA_I2HM(1),	/*  non-fp IO response	 */
-	BFI_IOIM_I2H_IOABORT_RSP = BFA_I2HM(2),/*  ABORT rsp	 */
-};
-
-/**
- * IO command DIF info
- */
-struct bfi_ioim_dif_s {
-	u32	dif_info[4];
-};
-
-/**
- * FCP IO messages overview
- *
- * @note
- * - Max CDB length supported is 64 bytes.
- * - SCSI Linked commands and SCSI bi-directional Commands not
- * 	 supported.
- *
- */
-struct bfi_ioim_req_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		 */
-	u16        io_tag;		/*  I/O tag			 */
-	u16        rport_hdl;	/*  itnim/rport firmware handle */
-	struct fcp_cmnd_s cmnd;		/*  IO request info		 */
-
-	/**
-	 * SG elements array within the IO request must be double word
-	 * aligned. This aligment is required to optimize SGM setup for the IO.
-	 */
-	struct bfi_sge_s   sges[BFI_SGE_INLINE_MAX];
-	u8         io_timeout;
-	u8         dif_en;
-	u8         rsvd_a[2];
-	struct bfi_ioim_dif_s  dif;
-};
-
-/**
- * 	This table shows various IO status codes from firmware and their
- *	meaning. Host driver can use these status codes to further process
- *	IO completions.
- *
- * 	BFI_IOIM_STS_OK		: IO completed with error free SCSI &
- *					   transport status.
- * 					   - io-tag can be reused.
- *
- * 	BFA_IOIM_STS_SCSI_ERR		: IO completed with scsi error.
- * 					  - io-tag can be reused.
- *
- * 	BFI_IOIM_STS_HOST_ABORTED	: IO was aborted successfully due to
- *					   host request.
- * 					   - io-tag cannot be reused yet.
- *
- * 	BFI_IOIM_STS_ABORTED		: IO was aborted successfully
- *					   internally by f/w.
- * 					   - io-tag cannot be reused yet.
- *
- * 	BFI_IOIM_STS_TIMEDOUT	: IO timedout and ABTS/RRQ is happening
- *					   in the firmware and
- * 					   - io-tag cannot be reused yet.
- *
- * 	BFI_IOIM_STS_SQER_NEEDED	: Firmware could not recover the IO
- *					  with sequence level error
- * 					  logic and hence host needs to retry
- *					  this IO with a different IO tag
- * 					  - io-tag cannot be used yet.
- *
- * 	BFI_IOIM_STS_NEXUS_ABORT	: Second Level Error Recovery from host
- *					  is required because 2 consecutive ABTS
- *					  timedout and host needs logout and
- *					  re-login with the target
- * 					  - io-tag cannot be used yet.
- *
- * 	BFI_IOIM_STS_UNDERRUN	: IO completed with SCSI status good,
- *					  but the data tranferred is less than
- *					  the fcp data length in the command.
- *					  ex. SCSI INQUIRY where transferred
- *					  data length and residue count in FCP
- *					  response accounts for total fcp-dl
- * 					  - io-tag can be reused.
- *
- * 	BFI_IOIM_STS_OVERRUN	: IO completed with SCSI status good,
- *					  but the data transerred is more than
- *					  fcp data length in the command. ex.
- *					  TAPE IOs where blocks can of unequal
- *					  lengths.
- * 					  - io-tag can be reused.
- *
- * 	BFI_IOIM_STS_RES_FREE	: Firmware has completed using io-tag
- *					  during abort process
- * 					  - io-tag can be reused.
- *
- * 	BFI_IOIM_STS_PROTO_ERR	: Firmware detected a protocol error.
- *					  ex target sent more data than
- *					  requested, or there was data frame
- *					  loss and other reasons
- * 					  - io-tag cannot be used yet.
- *
- * 	BFI_IOIM_STS_DIF_ERR	: Firwmare detected DIF error. ex: DIF
- * 					  CRC err or Ref Tag err or App tag err.
- * 					  - io-tag can be reused.
- *
- * 	BFA_IOIM_STS_TSK_MGT_ABORT	: IO was aborted because of Task
- *					  Management command from the host
- * 					  - io-tag can be reused.
- *
- * 	BFI_IOIM_STS_UTAG		: Firmware does not know about this
- *					  io_tag.
- * 					  - io-tag can be reused.
- */
-enum bfi_ioim_status {
-	BFI_IOIM_STS_OK = 0,
-	BFI_IOIM_STS_HOST_ABORTED = 1,
-	BFI_IOIM_STS_ABORTED = 2,
-	BFI_IOIM_STS_TIMEDOUT = 3,
-	BFI_IOIM_STS_RES_FREE = 4,
-	BFI_IOIM_STS_SQER_NEEDED = 5,
-	BFI_IOIM_STS_PROTO_ERR = 6,
-	BFI_IOIM_STS_UTAG = 7,
-	BFI_IOIM_STS_PATHTOV = 8,
-};
-
-#define BFI_IOIM_SNSLEN	(256)
-/**
- * I/O response message
- */
-struct bfi_ioim_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header	 	 */
-	u16        io_tag;		/*  completed IO tag		 */
-	u16        bfa_rport_hndl;	/*  releated rport handle	 */
-	u8         io_status;	/*  IO completion status	 */
-	u8         reuse_io_tag;	/*  IO tag can be reused        */
-	u16	abort_tag;	/*  host abort request tag      */
-	u8		scsi_status;	/*  scsi status from target	 */
-	u8		sns_len;	/*  scsi sense length		 */
-	u8		resid_flags;	/*  IO residue flags		 */
-	u8		rsvd_a;
-	u32	residue;	/*  IO residual length in bytes */
-	u32	rsvd_b[3];
-};
-
-struct bfi_ioim_abort_req_s {
-	struct bfi_mhdr_s  mh;          /*  Common msg header  */
-	u16        io_tag;         /*  I/O tag            */
-	u16        abort_tag;      /*  unique request tag */
-};
-
-/*
- * Initiator mode task management command interface defines.
- */
-
-enum bfi_tskim_h2i {
-	BFI_TSKIM_H2I_TM_REQ    = 1, /*  task-mgmt command         */
-	BFI_TSKIM_H2I_ABORT_REQ = 2, /*  task-mgmt command         */
-};
-
-enum bfi_tskim_i2h {
-	BFI_TSKIM_I2H_TM_RSP = BFA_I2HM(1),
-};
-
-struct bfi_tskim_req_s {
-	struct bfi_mhdr_s  mh;             /*  Common msg header          */
-	u16        tsk_tag;        /*  task management tag        */
-	u16        itn_fhdl;       /*  itn firmware handle        */
-	lun_t           lun;            /*  LU number                  */
-	u8         tm_flags;       /*  see fcp_tm_cmnd_t          */
-	u8         t_secs;         /*  Timeout value in seconds   */
-	u8         rsvd[2];
-};
-
-struct bfi_tskim_abortreq_s {
-	struct bfi_mhdr_s  mh;             /*  Common msg header          */
-	u16        tsk_tag;        /*  task management tag        */
-	u16        rsvd;
-};
-
-enum bfi_tskim_status {
-	/*
-	 * Following are FCP-4 spec defined status codes,
-	 * **DO NOT CHANGE THEM **
-	 */
-	BFI_TSKIM_STS_OK       = 0,
-	BFI_TSKIM_STS_NOT_SUPP = 4,
-	BFI_TSKIM_STS_FAILED   = 5,
-
-	/**
-	 * Defined by BFA
-	 */
-	BFI_TSKIM_STS_TIMEOUT  = 10,    /*  TM request timedout     */
-	BFI_TSKIM_STS_ABORTED  = 11,    /*  Aborted on host request */
-};
-
-struct bfi_tskim_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		 */
-	u16        tsk_tag;	/*  task mgmt cmnd tag		 */
-	u8         tsk_status;	/*  @ref bfi_tskim_status */
-	u8         rsvd;
-};
-
-#pragma pack()
-
-#endif /* __BFI_FCPIM_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fcxp.h b/drivers/scsi/bfa/include/bfi/bfi_fcxp.h
deleted file mode 100644
index e0e995a..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_fcxp.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_FCXP_H__
-#define __BFI_FCXP_H__
-
-#include "bfi.h"
-
-#pragma pack(1)
-
-enum bfi_fcxp_h2i {
-	BFI_FCXP_H2I_SEND_REQ = 1,
-};
-
-enum bfi_fcxp_i2h {
-	BFI_FCXP_I2H_SEND_RSP = BFA_I2HM(1),
-};
-
-#define BFA_FCXP_MAX_SGES	2
-
-/**
- * FCXP send request structure
- */
-struct bfi_fcxp_send_req_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		    */
-	u16        fcxp_tag;	/*  driver request tag		    */
-	u16        max_frmsz;	/*  max send frame size	    */
-	u16        vf_id;		/*  vsan tag if applicable	    */
-	u16        rport_fw_hndl;	/*  FW Handle for the remote port  */
-	u8         class;		/*  FC class used for req/rsp	    */
-	u8         rsp_timeout;	/*  timeout in secs, 0-no response */
-	u8         cts;		/*  continue sequence		    */
-	u8         lp_tag;		/*  lport tag			    */
-	struct fchs_s   fchs;		/*  request FC header structure    */
-	u32        req_len;	/*  request payload length	    */
-	u32        rsp_maxlen;	/*  max response length expected   */
-	struct bfi_sge_s   req_sge[BFA_FCXP_MAX_SGES];	/*  request buf    */
-	struct bfi_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];	/*  response buf   */
-};
-
-/**
- * FCXP send response structure
- */
-struct bfi_fcxp_send_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		    */
-	u16        fcxp_tag;	/*  send request tag		    */
-	u8         req_status;	/*  request status		    */
-	u8         rsvd;
-	u32        rsp_len;	/*  actual response length	    */
-	u32        residue_len;	/*  residual response length	    */
-	struct fchs_s   fchs;		/*  response FC header structure   */
-};
-
-#pragma pack()
-
-#endif /* __BFI_FCXP_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_ioc.h b/drivers/scsi/bfa/include/bfi/bfi_ioc.h
deleted file mode 100644
index 450ded6..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_ioc.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_IOC_H__
-#define __BFI_IOC_H__
-
-#include "bfi.h"
-#include <defs/bfa_defs_ioc.h>
-
-#pragma pack(1)
-
-enum bfi_ioc_h2i_msgs {
-	BFI_IOC_H2I_ENABLE_REQ 		= 1,
-	BFI_IOC_H2I_DISABLE_REQ 	= 2,
-	BFI_IOC_H2I_GETATTR_REQ 	= 3,
-	BFI_IOC_H2I_DBG_SYNC	 	= 4,
-	BFI_IOC_H2I_DBG_DUMP	 	= 5,
-};
-
-enum bfi_ioc_i2h_msgs {
-	BFI_IOC_I2H_ENABLE_REPLY	= BFA_I2HM(1),
-	BFI_IOC_I2H_DISABLE_REPLY 	= BFA_I2HM(2),
-	BFI_IOC_I2H_GETATTR_REPLY 	= BFA_I2HM(3),
-	BFI_IOC_I2H_READY_EVENT 	= BFA_I2HM(4),
-	BFI_IOC_I2H_HBEAT		= BFA_I2HM(5),
-};
-
-/**
- * BFI_IOC_H2I_GETATTR_REQ message
- */
-struct bfi_ioc_getattr_req_s {
-	struct bfi_mhdr_s	mh;
-	union bfi_addr_u	attr_addr;
-};
-
-struct bfi_ioc_attr_s {
-	wwn_t           mfg_pwwn;       /* Mfg port wwn */
-	wwn_t           mfg_nwwn;       /* Mfg node wwn */
-	mac_t		mfg_mac;	/* Mfg mac      */
-	u16		rsvd_a;
-	wwn_t           pwwn;
-	wwn_t           nwwn;
-	mac_t           mac;            /* PBC or Mfg mac */
-	u16        	rsvd_b;
-	char            brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
-	u8         pcie_gen;
-	u8         pcie_lanes_orig;
-	u8         pcie_lanes;
-	u8         rx_bbcredit;	/*  receive buffer credits */
-	u32        adapter_prop;	/*  adapter properties     */
-	u16        maxfrsize;	/*  max receive frame size */
-	char       asic_rev;
-	u8         rsvd_c;
-	char       fw_version[BFA_VERSION_LEN];
-	char       optrom_version[BFA_VERSION_LEN];
-	struct bfa_mfg_vpd_s	vpd;
-	u32        card_type;	/* card type */
-};
-
-/**
- * BFI_IOC_I2H_GETATTR_REPLY message
- */
-struct bfi_ioc_getattr_reply_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header          */
-	u8		status;	/*  cfg reply status           */
-	u8		rsvd[3];
-};
-
-/**
- * Firmware memory page offsets
- */
-#define BFI_IOC_SMEM_PG0_CB	(0x40)
-#define BFI_IOC_SMEM_PG0_CT	(0x180)
-
-/**
- * Firmware trace offset
- */
-#define BFI_IOC_TRC_OFF		(0x4b00)
-#define BFI_IOC_TRC_ENTS	256
-
-#define BFI_IOC_FW_SIGNATURE	(0xbfadbfad)
-#define BFI_IOC_MD5SUM_SZ	4
-struct bfi_ioc_image_hdr_s {
-	u32        signature;	/*  constant signature */
-	u32        rsvd_a;
-	u32        exec;		/*  exec vector        */
-	u32        param;		/*  parameters         */
-	u32        rsvd_b[4];
-	u32        md5sum[BFI_IOC_MD5SUM_SZ];
-};
-
-/**
- *  BFI_IOC_I2H_READY_EVENT message
- */
-struct bfi_ioc_rdy_event_s {
-	struct bfi_mhdr_s  mh;			/*  common msg header */
-	u8         init_status;	/*  init event status */
-	u8         rsvd[3];
-};
-
-struct bfi_ioc_hbeat_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u32	   hb_count;	/*  current heart beat count	*/
-};
-
-/**
- * IOC hardware/firmware state
- */
-enum bfi_ioc_state {
-	BFI_IOC_UNINIT 	 = 0,		/*  not initialized                 */
-	BFI_IOC_INITING 	 = 1,	/*  h/w is being initialized        */
-	BFI_IOC_HWINIT 	 = 2,		/*  h/w is initialized              */
-	BFI_IOC_CFG 	 = 3,		/*  IOC configuration in progress   */
-	BFI_IOC_OP 		 = 4,	/*  IOC is operational              */
-	BFI_IOC_DISABLING 	 = 5,	/*  IOC is being disabled           */
-	BFI_IOC_DISABLED 	 = 6,	/*  IOC is disabled                 */
-	BFI_IOC_CFG_DISABLED = 7,	/*  IOC is being disabled;transient */
-	BFI_IOC_FAIL       = 8,		/*  IOC heart-beat failure          */
-	BFI_IOC_MEMTEST      = 9,	/*  IOC is doing memtest            */
-};
-
-#define BFI_IOC_ENDIAN_SIG  0x12345678
-
-enum {
-	BFI_ADAPTER_TYPE_FC   = 0x01,		/*  FC adapters           */
-	BFI_ADAPTER_TYPE_MK   = 0x0f0000,	/*  adapter type mask     */
-	BFI_ADAPTER_TYPE_SH   = 16,	        /*  adapter type shift    */
-	BFI_ADAPTER_NPORTS_MK = 0xff00,		/*  number of ports mask  */
-	BFI_ADAPTER_NPORTS_SH = 8,	        /*  number of ports shift */
-	BFI_ADAPTER_SPEED_MK  = 0xff,		/*  adapter speed mask    */
-	BFI_ADAPTER_SPEED_SH  = 0,	        /*  adapter speed shift   */
-	BFI_ADAPTER_PROTO     = 0x100000,	/*  prototype adapaters   */
-	BFI_ADAPTER_TTV       = 0x200000,	/*  TTV debug capable     */
-	BFI_ADAPTER_UNSUPP    = 0x400000,	/*  unknown adapter type  */
-};
-
-#define BFI_ADAPTER_GETP(__prop, __adap_prop)          		\
-    (((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >>         \
-     BFI_ADAPTER_ ## __prop ## _SH)
-#define BFI_ADAPTER_SETP(__prop, __val)         		\
-    ((__val) << BFI_ADAPTER_ ## __prop ## _SH)
-#define BFI_ADAPTER_IS_PROTO(__adap_type)   			\
-    ((__adap_type) & BFI_ADAPTER_PROTO)
-#define BFI_ADAPTER_IS_TTV(__adap_type)     			\
-    ((__adap_type) & BFI_ADAPTER_TTV)
-#define BFI_ADAPTER_IS_UNSUPP(__adap_type)  			\
-    ((__adap_type) & BFI_ADAPTER_UNSUPP)
-#define BFI_ADAPTER_IS_SPECIAL(__adap_type)                     \
-    ((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO |     \
-			BFI_ADAPTER_UNSUPP))
-
-/**
- * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages
- */
-struct bfi_ioc_ctrl_req_s {
-	struct bfi_mhdr_s	mh;
-	u8			ioc_class;
-	u8         	rsvd[3];
-};
-
-/**
- * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
- */
-struct bfi_ioc_ctrl_reply_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header     */
-	u8         status;		/*  enable/disable status */
-	u8         rsvd[3];
-};
-
-#define BFI_IOC_MSGSZ   8
-/**
- * H2I Messages
- */
-union bfi_ioc_h2i_msg_u {
-	struct bfi_mhdr_s 	mh;
-	struct bfi_ioc_ctrl_req_s enable_req;
-	struct bfi_ioc_ctrl_req_s disable_req;
-	struct bfi_ioc_getattr_req_s getattr_req;
-	u32       		mboxmsg[BFI_IOC_MSGSZ];
-};
-
-/**
- * I2H Messages
- */
-union bfi_ioc_i2h_msg_u {
-	struct bfi_mhdr_s      	mh;
-	struct bfi_ioc_rdy_event_s 	rdy_event;
-	u32       		mboxmsg[BFI_IOC_MSGSZ];
-};
-
-#pragma pack()
-
-#endif /* __BFI_IOC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_iocfc.h b/drivers/scsi/bfa/include/bfi/bfi_iocfc.h
deleted file mode 100644
index ccdfcc5..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_iocfc.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_IOCFC_H__
-#define __BFI_IOCFC_H__
-
-#include "bfi.h"
-#include <bfi/bfi_pbc.h>
-#include <defs/bfa_defs_ioc.h>
-#include <defs/bfa_defs_iocfc.h>
-#include <defs/bfa_defs_boot.h>
-
-#pragma pack(1)
-
-enum bfi_iocfc_h2i_msgs {
-	BFI_IOCFC_H2I_CFG_REQ 		= 1,
-	BFI_IOCFC_H2I_GET_STATS_REQ 	= 2,
-	BFI_IOCFC_H2I_CLEAR_STATS_REQ	= 3,
-	BFI_IOCFC_H2I_SET_INTR_REQ 	= 4,
-	BFI_IOCFC_H2I_UPDATEQ_REQ = 5,
-};
-
-enum bfi_iocfc_i2h_msgs {
-	BFI_IOCFC_I2H_CFG_REPLY		= BFA_I2HM(1),
-	BFI_IOCFC_I2H_GET_STATS_RSP 	= BFA_I2HM(2),
-	BFI_IOCFC_I2H_CLEAR_STATS_RSP	= BFA_I2HM(3),
-	BFI_IOCFC_I2H_UPDATEQ_RSP = BFA_I2HM(5),
-};
-
-struct bfi_iocfc_cfg_s {
-	u8         num_cqs; 	/*  Number of CQs to be used     */
-	u8         sense_buf_len;	/*  SCSI sense length            */
-	u8         trunk_enabled;	/*  port trunking enabled        */
-	u8         trunk_ports;	/*  trunk ports bit map          */
-	u32        endian_sig;	/*  endian signature of host     */
-
-	/**
-	 * Request and response circular queue base addresses, size and
-	 * shadow index pointers.
-	 */
-	union bfi_addr_u  req_cq_ba[BFI_IOC_MAX_CQS];
-	union bfi_addr_u  req_shadow_ci[BFI_IOC_MAX_CQS];
-	u16    req_cq_elems[BFI_IOC_MAX_CQS];
-	union bfi_addr_u  rsp_cq_ba[BFI_IOC_MAX_CQS];
-	union bfi_addr_u  rsp_shadow_pi[BFI_IOC_MAX_CQS];
-	u16    rsp_cq_elems[BFI_IOC_MAX_CQS];
-
-	union bfi_addr_u  stats_addr;	/*  DMA-able address for stats	  */
-	union bfi_addr_u  cfgrsp_addr;	/*  config response dma address  */
-	union bfi_addr_u  ioim_snsbase;  /*  IO sense buffer base address */
-	struct bfa_iocfc_intr_attr_s intr_attr; /*  IOC interrupt attributes */
-};
-
-/**
- * Boot target wwn information for this port. This contains either the stored
- * or discovered boot target port wwns for the port.
- */
-struct bfi_iocfc_bootwwns {
-	wwn_t		wwn[BFA_BOOT_BOOTLUN_MAX];
-	u8		nwwns;
-	u8		rsvd[7];
-};
-
-struct bfi_iocfc_cfgrsp_s {
-	struct bfa_iocfc_fwcfg_s	fwcfg;
-	struct bfa_iocfc_intr_attr_s	intr_attr;
-	struct bfi_iocfc_bootwwns	bootwwns;
-	struct bfi_pbc_s                pbc_cfg;
-};
-
-/**
- * BFI_IOCFC_H2I_CFG_REQ message
- */
-struct bfi_iocfc_cfg_req_s {
-	struct bfi_mhdr_s      mh;
-	union bfi_addr_u      ioc_cfg_dma_addr;
-};
-
-/**
- * BFI_IOCFC_I2H_CFG_REPLY message
- */
-struct bfi_iocfc_cfg_reply_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header          */
-	u8         cfg_success;	/*  cfg reply status           */
-	u8         lpu_bm;		/*  LPUs assigned for this IOC */
-	u8         rsvd[2];
-};
-
-/**
- *  BFI_IOCFC_H2I_GET_STATS_REQ & BFI_IOCFC_H2I_CLEAR_STATS_REQ messages
- */
-struct bfi_iocfc_stats_req_s {
-	struct bfi_mhdr_s mh;		/*  msg header            */
-	u32        msgtag;		/*  msgtag for reply      */
-};
-
-/**
- * BFI_IOCFC_I2H_GET_STATS_RSP & BFI_IOCFC_I2H_CLEAR_STATS_RSP messages
- */
-struct bfi_iocfc_stats_rsp_s {
-	struct bfi_mhdr_s mh;		/*  common msg header     */
-	u8         status;		/*  reply status          */
-	u8         rsvd[3];
-	u32        msgtag;		/*  msgtag for reply      */
-};
-
-/**
- * BFI_IOCFC_H2I_SET_INTR_REQ message
- */
-struct bfi_iocfc_set_intr_req_s {
-	struct bfi_mhdr_s mh;		/*  common msg header     */
-	u8		coalesce;	/*  enable intr coalescing*/
-	u8         rsvd[3];
-	u16	delay;		/*  delay timer 0..1125us  */
-	u16	latency;	/*  latency timer 0..225us */
-};
-
-/**
- * BFI_IOCFC_H2I_UPDATEQ_REQ message
- */
-struct bfi_iocfc_updateq_req_s {
-	struct bfi_mhdr_s mh;		/*  common msg header     */
-	u32 reqq_ba;			/*  reqq base addr        */
-	u32 rspq_ba;			/*  rspq base addr        */
-	u32 reqq_sci;			/*  reqq shadow ci        */
-	u32 rspq_spi;			/*  rspq shadow pi        */
-};
-
-/**
- * BFI_IOCFC_I2H_UPDATEQ_RSP message
- */
-struct bfi_iocfc_updateq_rsp_s {
-	struct bfi_mhdr_s mh;		/*  common msg header     */
-	u8         status;		/*  updateq  status       */
-	u8         rsvd[3];
-};
-
-/**
- * H2I Messages
- */
-union bfi_iocfc_h2i_msg_u {
-	struct bfi_mhdr_s 		mh;
-	struct bfi_iocfc_cfg_req_s 	cfg_req;
-	struct bfi_iocfc_stats_req_s stats_get;
-	struct bfi_iocfc_stats_req_s stats_clr;
-	struct bfi_iocfc_updateq_req_s updateq_req;
-	u32       			mboxmsg[BFI_IOC_MSGSZ];
-};
-
-/**
- * I2H Messages
- */
-union bfi_iocfc_i2h_msg_u {
-	struct bfi_mhdr_s      		mh;
-	struct bfi_iocfc_cfg_reply_s 		cfg_reply;
-	struct bfi_iocfc_stats_rsp_s stats_get_rsp;
-	struct bfi_iocfc_stats_rsp_s stats_clr_rsp;
-	struct bfi_iocfc_updateq_rsp_s updateq_rsp;
-	u32       			mboxmsg[BFI_IOC_MSGSZ];
-};
-
-#pragma pack()
-
-#endif /* __BFI_IOCFC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_lport.h b/drivers/scsi/bfa/include/bfi/bfi_lport.h
deleted file mode 100644
index 2901061..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_lport.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_LPORT_H__
-#define __BFI_LPORT_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_lport_h2i_msgs {
-	BFI_LPORT_H2I_CREATE_REQ = 1,
-	BFI_LPORT_H2I_DELETE_REQ = 2,
-};
-
-enum bfi_lport_i2h_msgs {
-	BFI_LPORT_I2H_CREATE_RSP = BFA_I2HM(1),
-	BFI_LPORT_I2H_DELETE_RSP = BFA_I2HM(2),
-	BFI_LPORT_I2H_ONLINE	  = BFA_I2HM(3),
-	BFI_LPORT_I2H_OFFLINE	  = BFA_I2HM(4),
-};
-
-#define BFI_LPORT_MAX_SYNNAME	64
-
-enum bfi_lport_role_e {
-	BFI_LPORT_ROLE_FCPIM	= 1,
-	BFI_LPORT_ROLE_FCPTM	= 2,
-	BFI_LPORT_ROLE_IPFC	= 4,
-};
-
-struct bfi_lport_create_req_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16	fabric_fwhdl;	/*  parent fabric instance	*/
-	u8		roles;		/*  lport FC-4 roles		*/
-	u8		rsvd;
-	wwn_t		pwwn;		/*  port name			*/
-	wwn_t		nwwn;		/*  node name			*/
-	u8		symname[BFI_LPORT_MAX_SYNNAME];
-};
-
-struct bfi_lport_create_rsp_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u8         status;		/*  lport creation status	*/
-	u8         rsvd[3];
-};
-
-struct bfi_lport_delete_req_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        fw_handle;	/*  firmware lport handle	*/
-	u16        rsvd;
-};
-
-struct bfi_lport_delete_rsp_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host lport handle		*/
-	u8         status;		/*  lport deletion status	*/
-	u8         rsvd;
-};
-
-union bfi_lport_h2i_msg_u {
-	bfi_msg_t		*msg;
-	struct bfi_lport_create_req_s	*create_req;
-	struct bfi_lport_delete_req_s	*delete_req;
-};
-
-union bfi_lport_i2h_msg_u {
-	bfi_msg_t		*msg;
-	struct bfi_lport_create_rsp_s	*create_rsp;
-	struct bfi_lport_delete_rsp_s	*delete_rsp;
-};
-
-#pragma pack()
-
-#endif /* __BFI_LPORT_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_lps.h b/drivers/scsi/bfa/include/bfi/bfi_lps.h
deleted file mode 100644
index 7ed31bb..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_lps.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_LPS_H__
-#define __BFI_LPS_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_lps_h2i_msgs {
-	BFI_LPS_H2I_LOGIN_REQ	= 1,
-	BFI_LPS_H2I_LOGOUT_REQ	= 2,
-};
-
-enum bfi_lps_i2h_msgs {
-	BFI_LPS_H2I_LOGIN_RSP	= BFA_I2HM(1),
-	BFI_LPS_H2I_LOGOUT_RSP	= BFA_I2HM(2),
-	BFI_LPS_H2I_CVL_EVENT   = BFA_I2HM(3),
-};
-
-struct bfi_lps_login_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
-	u8		alpa;
-	u16	pdu_size;
-	wwn_t		pwwn;
-	wwn_t		nwwn;
-	u8		fdisc;
-	u8		auth_en;
-	u8		rsvd[2];
-};
-
-struct bfi_lps_login_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
-	u8		status;
-	u8		lsrjt_rsn;
-	u8		lsrjt_expl;
-	wwn_t		port_name;
-	wwn_t		node_name;
-	u16	bb_credit;
-	u8		f_port;
-	u8		npiv_en;
-	u32	lp_pid:24;
-	u32	auth_req:8;
-	mac_t		lp_mac;
-	mac_t		fcf_mac;
-	u8		ext_status;
-	u8  	brcd_switch;/*  attached peer is brcd switch	*/
-};
-
-struct bfi_lps_logout_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
-	u8		rsvd[3];
-	wwn_t		port_name;
-};
-
-struct bfi_lps_logout_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
-	u8		status;
-	u8		rsvd[2];
-};
-
-struct bfi_lps_cvl_event_s {
-	struct bfi_mhdr_s  mh;      /* common msg header      */
-	u8		lp_tag;
-	u8		rsvd[3];
-};
-
-union bfi_lps_h2i_msg_u {
-	struct bfi_mhdr_s		*msg;
-	struct bfi_lps_login_req_s	*login_req;
-	struct bfi_lps_logout_req_s	*logout_req;
-};
-
-union bfi_lps_i2h_msg_u {
-	struct bfi_msg_s		*msg;
-	struct bfi_lps_login_rsp_s	*login_rsp;
-	struct bfi_lps_logout_rsp_s	*logout_rsp;
-	struct bfi_lps_cvl_event_s	*cvl_event;
-};
-
-#pragma pack()
-
-#endif /* __BFI_LPS_H__ */
-
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_pbc.h b/drivers/scsi/bfa/include/bfi/bfi_pbc.h
deleted file mode 100644
index 88a4154..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_pbc.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_PBC_H__
-#define __BFI_PBC_H__
-
-#pragma pack(1)
-
-#define BFI_PBC_MAX_BLUNS	8
-#define BFI_PBC_MAX_VPORTS	16
-
-#define BFI_PBC_PORT_DISABLED	 2
-/**
- * PBC boot lun configuration
- */
-struct bfi_pbc_blun_s {
-	wwn_t		tgt_pwwn;
-	lun_t		tgt_lun;
-};
-
-/**
- * PBC virtual port configuration
- */
-struct bfi_pbc_vport_s {
-	wwn_t		vp_pwwn;
-	wwn_t		vp_nwwn;
-};
-
-/**
- * BFI pre-boot configuration information
- */
-struct bfi_pbc_s {
-	u8		port_enabled;
-	u8		boot_enabled;
-	u8		nbluns;
-	u8		nvports;
-	u8		port_speed;
-	u8		rsvd_a;
-	u16		hss;
-	wwn_t		pbc_pwwn;
-	wwn_t		pbc_nwwn;
-	struct bfi_pbc_blun_s blun[BFI_PBC_MAX_BLUNS];
-	struct bfi_pbc_vport_s vport[BFI_PBC_MAX_VPORTS];
-};
-
-#pragma pack()
-
-#endif /* __BFI_PBC_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi_port.h b/drivers/scsi/bfa/include/bfi/bfi_port.h
deleted file mode 100644
index 3ec3bea..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_port.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFI_PORT_H__
-#define __BFI_PORT_H__
-
-#include <bfi/bfi.h>
-#include <defs/bfa_defs_pport.h>
-
-#pragma pack(1)
-
-enum bfi_port_h2i {
-	BFI_PORT_H2I_ENABLE_REQ		= (1),
-	BFI_PORT_H2I_DISABLE_REQ	= (2),
-	BFI_PORT_H2I_GET_STATS_REQ	= (3),
-	BFI_PORT_H2I_CLEAR_STATS_REQ	= (4),
-};
-
-enum bfi_port_i2h {
-	BFI_PORT_I2H_ENABLE_RSP		= BFA_I2HM(1),
-	BFI_PORT_I2H_DISABLE_RSP	= BFA_I2HM(2),
-	BFI_PORT_I2H_GET_STATS_RSP	= BFA_I2HM(3),
-	BFI_PORT_I2H_CLEAR_STATS_RSP	= BFA_I2HM(4),
-};
-
-/**
- * Generic REQ type
- */
-struct bfi_port_generic_req_s {
-	struct bfi_mhdr_s  mh;		/*  msg header			    */
-	u32        msgtag;		/*  msgtag for reply		    */
-	u32	rsvd;
-};
-
-/**
- * Generic RSP type
- */
-struct bfi_port_generic_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		    */
-	u8         status;		/*  port enable status		    */
-	u8         rsvd[3];
-	u32        msgtag;		/*  msgtag for reply		    */
-};
-
-/**
- * @todo
- * BFI_PORT_H2I_ENABLE_REQ
- */
-
-/**
- * @todo
- * BFI_PORT_I2H_ENABLE_RSP
- */
-
-/**
- * BFI_PORT_H2I_DISABLE_REQ
- */
-
-/**
- * BFI_PORT_I2H_DISABLE_RSP
- */
-
-/**
- * BFI_PORT_H2I_GET_STATS_REQ
- */
-struct bfi_port_get_stats_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		    */
-	union bfi_addr_u   dma_addr;
-};
-
-/**
- * BFI_PORT_I2H_GET_STATS_RSP
- */
-
-/**
- * BFI_PORT_H2I_CLEAR_STATS_REQ
- */
-
-/**
- * BFI_PORT_I2H_CLEAR_STATS_RSP
- */
-
-union bfi_port_h2i_msg_u {
-	struct bfi_mhdr_s		mh;
-	struct bfi_port_generic_req_s	enable_req;
-	struct bfi_port_generic_req_s	disable_req;
-	struct bfi_port_get_stats_req_s	getstats_req;
-	struct bfi_port_generic_req_s	clearstats_req;
-};
-
-union bfi_port_i2h_msg_u {
-	struct bfi_mhdr_s         	mh;
-	struct bfi_port_generic_rsp_s	enable_rsp;
-	struct bfi_port_generic_rsp_s	disable_rsp;
-	struct bfi_port_generic_rsp_s	getstats_rsp;
-	struct bfi_port_generic_rsp_s	clearstats_rsp;
-};
-
-#pragma pack()
-
-#endif /* __BFI_PORT_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_pport.h b/drivers/scsi/bfa/include/bfi/bfi_pport.h
deleted file mode 100644
index 50dcf45..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_pport.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFI_PPORT_H__
-#define __BFI_PPORT_H__
-
-#include <bfi/bfi.h>
-#include <defs/bfa_defs_pport.h>
-
-#pragma pack(1)
-
-enum bfi_fcport_h2i {
-	BFI_FCPORT_H2I_ENABLE_REQ		= (1),
-	BFI_FCPORT_H2I_DISABLE_REQ		= (2),
-	BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ	= (3),
-	BFI_FCPORT_H2I_STATS_GET_REQ		= (4),
-	BFI_FCPORT_H2I_STATS_CLEAR_REQ		= (5),
-};
-
-enum bfi_fcport_i2h {
-	BFI_FCPORT_I2H_ENABLE_RSP		= BFA_I2HM(1),
-	BFI_FCPORT_I2H_DISABLE_RSP		= BFA_I2HM(2),
-	BFI_FCPORT_I2H_SET_SVC_PARAMS_RSP	= BFA_I2HM(3),
-	BFI_FCPORT_I2H_STATS_GET_RSP		= BFA_I2HM(4),
-	BFI_FCPORT_I2H_STATS_CLEAR_RSP		= BFA_I2HM(5),
-	BFI_FCPORT_I2H_EVENT			= BFA_I2HM(6),
-};
-
-/**
- * Generic REQ type
- */
-struct bfi_fcport_req_s {
-	struct bfi_mhdr_s  mh;		/*  msg header			    */
-	u32	   msgtag;	/*  msgtag for reply		    */
-};
-
-/**
- * Generic RSP type
- */
-struct bfi_fcport_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		    */
-	u8		   status;	/*  port enable status		    */
-	u8		   rsvd[3];
-	u32	   msgtag;	/*  msgtag for reply		    */
-};
-
-/**
- * BFI_FCPORT_H2I_ENABLE_REQ
- */
-struct bfi_fcport_enable_req_s {
-	struct bfi_mhdr_s  mh;		/*  msg header			    */
-	u32	   rsvd1;
-	wwn_t		   nwwn;	/*  node wwn of physical port	    */
-	wwn_t		   pwwn;	/*  port wwn of physical port	    */
-	struct bfa_pport_cfg_s port_cfg; /*  port configuration	    */
-	union bfi_addr_u   stats_dma_addr; /*  DMA address for stats	    */
-	u32	   msgtag;	/*  msgtag for reply		    */
-	u32	   rsvd2;
-};
-
-/**
- * BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ
- */
-struct bfi_fcport_set_svc_params_req_s {
-	struct bfi_mhdr_s  mh;		/*  msg header */
-	u16	   tx_bbcredit;	/*  Tx credits */
-	u16	   rsvd;
-};
-
-/**
- * BFI_FCPORT_I2H_EVENT
- */
-struct bfi_fcport_event_s {
-	struct bfi_mhdr_s 	mh;	/*  common msg header */
-	struct bfa_pport_link_s	link_state;
-};
-
-/**
- * fcport H2I message
- */
-union bfi_fcport_h2i_msg_u {
-	struct bfi_mhdr_s			*mhdr;
-	struct bfi_fcport_enable_req_s		*penable;
-	struct bfi_fcport_req_s			*pdisable;
-	struct bfi_fcport_set_svc_params_req_s	*psetsvcparams;
-	struct bfi_fcport_req_s			*pstatsget;
-	struct bfi_fcport_req_s			*pstatsclear;
-};
-
-/**
- * fcport I2H message
- */
-union bfi_fcport_i2h_msg_u {
-	struct bfi_msg_s			*msg;
-	struct bfi_fcport_rsp_s			*penable_rsp;
-	struct bfi_fcport_rsp_s			*pdisable_rsp;
-	struct bfi_fcport_rsp_s			*psetsvcparams_rsp;
-	struct bfi_fcport_rsp_s			*pstatsget_rsp;
-	struct bfi_fcport_rsp_s			*pstatsclear_rsp;
-	struct bfi_fcport_event_s		*event;
-};
-
-#pragma pack()
-
-#endif /* __BFI_PPORT_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi_rport.h b/drivers/scsi/bfa/include/bfi/bfi_rport.h
deleted file mode 100644
index e1cd83b..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_rport.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_RPORT_H__
-#define __BFI_RPORT_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_rport_h2i_msgs {
-	BFI_RPORT_H2I_CREATE_REQ = 1,
-	BFI_RPORT_H2I_DELETE_REQ = 2,
-	BFI_RPORT_H2I_SET_SPEED_REQ  = 3,
-};
-
-enum bfi_rport_i2h_msgs {
-	BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1),
-	BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2),
-	BFI_RPORT_I2H_QOS_SCN    = BFA_I2HM(3),
-};
-
-struct bfi_rport_create_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host rport handle		*/
-	u16        max_frmsz;	/*  max rcv pdu size		*/
-	u32        pid:24,		/*  remote port ID		*/
-			lp_tag:8;	/*  local port tag		*/
-	u32        local_pid:24,	/*  local port ID		*/
-			cisc:8;
-	u8         fc_class;	/*  supported FC classes	*/
-	u8         vf_en;		/*  virtual fabric enable	*/
-	u16        vf_id;		/*  virtual fabric ID		*/
-};
-
-struct bfi_rport_create_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8         status;		/*  rport creation status	*/
-	u8         rsvd[3];
-	u16        bfa_handle;	/*  host rport handle		*/
-	u16        fw_handle;	/*  firmware rport handle	*/
-	struct bfa_rport_qos_attr_s qos_attr;  /* QoS Attributes */
-};
-
-struct bfa_rport_speed_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u16        fw_handle;	/*  firmware rport handle	*/
-	u8		speed;		/*! rport's speed via RPSC  */
-	u8		rsvd;
-};
-
-struct bfi_rport_delete_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u16        fw_handle;	/*  firmware rport handle	*/
-	u16        rsvd;
-};
-
-struct bfi_rport_delete_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host rport handle		*/
-	u8         status;		/*  rport deletion status	*/
-	u8         rsvd;
-};
-
-struct bfi_rport_qos_scn_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host rport handle		*/
-	u16        rsvd;
-	struct bfa_rport_qos_attr_s old_qos_attr;  /* Old QoS Attributes */
-	struct bfa_rport_qos_attr_s new_qos_attr;  /* New QoS Attributes */
-};
-
-union bfi_rport_h2i_msg_u {
-	struct bfi_msg_s 		*msg;
-	struct bfi_rport_create_req_s	*create_req;
-	struct bfi_rport_delete_req_s	*delete_req;
-	struct bfi_rport_speed_req_s	*speed_req;
-};
-
-union bfi_rport_i2h_msg_u {
-	struct bfi_msg_s 		*msg;
-	struct bfi_rport_create_rsp_s	*create_rsp;
-	struct bfi_rport_delete_rsp_s	*delete_rsp;
-	struct bfi_rport_qos_scn_s	*qos_scn_evt;
-};
-
-#pragma pack()
-
-#endif /* __BFI_RPORT_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_uf.h b/drivers/scsi/bfa/include/bfi/bfi_uf.h
deleted file mode 100644
index f328a9e..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_uf.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_UF_H__
-#define __BFI_UF_H__
-
-#include "bfi.h"
-
-#pragma pack(1)
-
-enum bfi_uf_h2i {
-	BFI_UF_H2I_BUF_POST = 1,
-};
-
-enum bfi_uf_i2h {
-	BFI_UF_I2H_FRM_RCVD = BFA_I2HM(1),
-};
-
-#define BFA_UF_MAX_SGES	2
-
-struct bfi_uf_buf_post_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		*/
-	u16        buf_tag;	/*  buffer tag			*/
-	u16        buf_len;	/*  total buffer length	*/
-	struct bfi_sge_s   sge[BFA_UF_MAX_SGES]; /*  buffer DMA SGEs	*/
-};
-
-struct bfi_uf_frm_rcvd_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		*/
-	u16        buf_tag;	/*  buffer tag			*/
-	u16        rsvd;
-	u16        frm_len;	/*  received frame length 	*/
-	u16        xfr_len;	/*  tranferred length		*/
-};
-
-#pragma pack()
-
-#endif /* __BFI_UF_H__ */
diff --git a/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h b/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h
deleted file mode 100644
index a75a1f3..0000000
--- a/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_cna_trcmod.h CNA trace modules
- */
-
-#ifndef __BFA_CNA_TRCMOD_H__
-#define __BFA_CNA_TRCMOD_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
-	BFA_TRC_CNA_CEE		= 1,
-	BFA_TRC_CNA_PORT	= 2,
-	BFA_TRC_CNA_IOC     = 3,
-	BFA_TRC_CNA_DIAG    = 4,
-	BFA_TRC_CNA_IOC_CB  = 5,
-	BFA_TRC_CNA_IOC_CT  = 6,
-};
-
-#endif /* __BFA_CNA_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/include/cna/cee/bfa_cee.h b/drivers/scsi/bfa/include/cna/cee/bfa_cee.h
deleted file mode 100644
index 77f297f..0000000
--- a/drivers/scsi/bfa/include/cna/cee/bfa_cee.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_CEE_H__
-#define __BFA_CEE_H__
-
-#include <defs/bfa_defs_cee.h>
-#include <bfa_ioc.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-
-typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, bfa_status_t status);
-typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, bfa_status_t status);
-typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, bfa_status_t status);
-typedef void (*bfa_cee_hbfail_cbfn_t) (void *dev, bfa_status_t status);
-
-struct bfa_cee_cbfn_s {
-	bfa_cee_get_attr_cbfn_t    get_attr_cbfn;
-	void *get_attr_cbarg;
-	bfa_cee_get_stats_cbfn_t   get_stats_cbfn;
-	void *get_stats_cbarg;
-	bfa_cee_reset_stats_cbfn_t reset_stats_cbfn;
-	void *reset_stats_cbarg;
-};
-
-struct bfa_cee_s {
-	void *dev;
-	bfa_boolean_t get_attr_pending;
-	bfa_boolean_t get_stats_pending;
-	bfa_boolean_t reset_stats_pending;
-	bfa_status_t get_attr_status;
-	bfa_status_t get_stats_status;
-	bfa_status_t reset_stats_status;
-	struct bfa_cee_cbfn_s cbfn;
-	struct bfa_ioc_hbfail_notify_s hbfail;
-	struct bfa_trc_mod_s *trcmod;
-	struct bfa_log_mod_s *logmod;
-	struct bfa_cee_attr_s *attr;
-	struct bfa_cee_stats_s *stats;
-	struct bfa_dma_s attr_dma;
-	struct bfa_dma_s stats_dma;
-	struct bfa_ioc_s *ioc;
-	struct bfa_mbox_cmd_s get_cfg_mb;
-	struct bfa_mbox_cmd_s get_stats_mb;
-	struct bfa_mbox_cmd_s reset_stats_mb;
-};
-
-u32 bfa_cee_meminfo(void);
-void bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva,
-			 u64 dma_pa);
-void bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
-			struct bfa_trc_mod_s *trcmod,
-			struct bfa_log_mod_s *logmod);
-void bfa_cee_detach(struct bfa_cee_s *cee);
-bfa_status_t bfa_cee_get_attr(struct bfa_cee_s *cee,
-			 struct bfa_cee_attr_s *attr,
-			bfa_cee_get_attr_cbfn_t cbfn, void *cbarg);
-bfa_status_t bfa_cee_get_stats(struct bfa_cee_s *cee,
-			struct bfa_cee_stats_s *stats,
-			bfa_cee_get_stats_cbfn_t cbfn, void *cbarg);
-bfa_status_t bfa_cee_reset_stats(struct bfa_cee_s *cee,
-			bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg);
-#endif /* __BFA_CEE_H__ */
diff --git a/drivers/scsi/bfa/include/cna/port/bfa_port.h b/drivers/scsi/bfa/include/cna/port/bfa_port.h
deleted file mode 100644
index d7babaf..0000000
--- a/drivers/scsi/bfa/include/cna/port/bfa_port.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_PORT_H__
-#define __BFA_PORT_H__
-
-#include <defs/bfa_defs_port.h>
-#include <bfa_ioc.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-
-typedef void    (*bfa_port_stats_cbfn_t) (void *dev, bfa_status_t status);
-typedef void    (*bfa_port_endis_cbfn_t) (void *dev, bfa_status_t status);
-
-struct bfa_port_s {
-	void           *dev;
-	struct bfa_ioc_s *ioc;
-	struct bfa_trc_mod_s *trcmod;
-	struct bfa_log_mod_s *logmod;
-	u32        msgtag;
-	bfa_boolean_t   stats_busy;
-	struct bfa_mbox_cmd_s stats_mb;
-	bfa_port_stats_cbfn_t stats_cbfn;
-	void           *stats_cbarg;
-	bfa_status_t    stats_status;
-	u32             stats_reset_time;
-	union bfa_pport_stats_u *stats;
-	struct bfa_dma_s stats_dma;
-	bfa_boolean_t   endis_pending;
-	struct bfa_mbox_cmd_s endis_mb;
-	bfa_port_endis_cbfn_t endis_cbfn;
-	void           *endis_cbarg;
-	bfa_status_t    endis_status;
-	struct bfa_ioc_hbfail_notify_s hbfail;
-};
-
-void            bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
-				void *dev, struct bfa_trc_mod_s *trcmod,
-				struct bfa_log_mod_s *logmod);
-void            bfa_port_detach(struct bfa_port_s *port);
-void            bfa_port_hbfail(void *arg);
-
-bfa_status_t    bfa_port_get_stats(struct bfa_port_s *port,
-				   union bfa_pport_stats_u *stats,
-				   bfa_port_stats_cbfn_t cbfn, void *cbarg);
-bfa_status_t    bfa_port_clear_stats(struct bfa_port_s *port,
-				     bfa_port_stats_cbfn_t cbfn, void *cbarg);
-bfa_status_t    bfa_port_enable(struct bfa_port_s *port,
-				bfa_port_endis_cbfn_t cbfn, void *cbarg);
-bfa_status_t    bfa_port_disable(struct bfa_port_s *port,
-				 bfa_port_endis_cbfn_t cbfn, void *cbarg);
-u32        bfa_port_meminfo(void);
-void            bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva,
-				   u64 dma_pa);
-
-#endif /* __BFA_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h b/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h
deleted file mode 100644
index 1563ee5..0000000
--- a/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved.
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __ETHPORT_DEFS_H__
-#define __ETHPORT_DEFS_H__
-
-struct bnad_drv_stats {
-	u64 netif_queue_stop;
-	u64 netif_queue_wakeup;
-	u64 tso4;
-	u64 tso6;
-	u64 tso_err;
-	u64 tcpcsum_offload;
-	u64 udpcsum_offload;
-	u64 csum_help;
-	u64 csum_help_err;
-
-	u64 hw_stats_updates;
-	u64 netif_rx_schedule;
-	u64 netif_rx_complete;
-	u64 netif_rx_dropped;
-};
-#endif
diff --git a/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h b/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h
deleted file mode 100644
index eb75480..0000000
--- a/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved.
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __PHYPORT_DEFS_H__
-#define __PHYPORT_DEFS_H__
-
-#define BNA_TXF_ID_MAX  	64
-#define BNA_RXF_ID_MAX  	64
-
-/*
- * Statistics
- */
-
-/*
- * TxF Frame Statistics
- */
-struct bna_stats_txf {
-	u64        ucast_octets;
-	u64        ucast;
-	u64        ucast_vlan;
-
-	u64        mcast_octets;
-	u64        mcast;
-	u64        mcast_vlan;
-
-	u64        bcast_octets;
-	u64        bcast;
-	u64        bcast_vlan;
-
-	u64        errors;
-	u64        filter_vlan;	/* frames filtered due to VLAN */
-	u64        filter_mac_sa;	/* frames filtered due to SA check */
-};
-
-/*
- * RxF Frame Statistics
- */
-struct bna_stats_rxf {
-	u64        ucast_octets;
-	u64        ucast;
-	u64        ucast_vlan;
-
-	u64        mcast_octets;
-	u64        mcast;
-	u64        mcast_vlan;
-
-	u64        bcast_octets;
-	u64        bcast;
-	u64        bcast_vlan;
-	u64        frame_drops;
-};
-
-/*
- * FC Tx Frame Statistics
- */
-struct bna_stats_fc_tx {
-	u64        txf_ucast_octets;
-	u64        txf_ucast;
-	u64        txf_ucast_vlan;
-
-	u64        txf_mcast_octets;
-	u64        txf_mcast;
-	u64        txf_mcast_vlan;
-
-	u64        txf_bcast_octets;
-	u64        txf_bcast;
-	u64        txf_bcast_vlan;
-
-	u64        txf_parity_errors;
-	u64        txf_timeout;
-	u64        txf_fid_parity_errors;
-};
-
-/*
- * FC Rx Frame Statistics
- */
-struct bna_stats_fc_rx {
-	u64        rxf_ucast_octets;
-	u64        rxf_ucast;
-	u64        rxf_ucast_vlan;
-
-	u64        rxf_mcast_octets;
-	u64        rxf_mcast;
-	u64        rxf_mcast_vlan;
-
-	u64        rxf_bcast_octets;
-	u64        rxf_bcast;
-	u64        rxf_bcast_vlan;
-};
-
-/*
- * RAD Frame Statistics
- */
-struct cna_stats_rad {
-	u64        rx_frames;
-	u64        rx_octets;
-	u64        rx_vlan_frames;
-
-	u64        rx_ucast;
-	u64        rx_ucast_octets;
-	u64        rx_ucast_vlan;
-
-	u64        rx_mcast;
-	u64        rx_mcast_octets;
-	u64        rx_mcast_vlan;
-
-	u64        rx_bcast;
-	u64        rx_bcast_octets;
-	u64        rx_bcast_vlan;
-
-	u64        rx_drops;
-};
-
-/*
- * BPC Tx Registers
- */
-struct cna_stats_bpc_tx {
-	u64        tx_pause[8];
-	u64        tx_zero_pause[8];	/*  Pause cancellation */
-	u64        tx_first_pause[8];	/*  Pause initiation rather
-						 *than retention */
-};
-
-/*
- * BPC Rx Registers
- */
-struct cna_stats_bpc_rx {
-	u64        rx_pause[8];
-	u64        rx_zero_pause[8];	/*  Pause cancellation */
-	u64        rx_first_pause[8];	/*  Pause initiation rather
-						 *than retention */
-};
-
-/*
- * MAC Rx Statistics
- */
-struct cna_stats_mac_rx {
-	u64        frame_64;	/* both rx and tx counter */
-	u64        frame_65_127;	/* both rx and tx counter */
-	u64        frame_128_255;	/* both rx and tx counter */
-	u64        frame_256_511;	/* both rx and tx counter */
-	u64        frame_512_1023;	/* both rx and tx counter */
-	u64        frame_1024_1518;	/* both rx and tx counter */
-	u64        frame_1518_1522;	/* both rx and tx counter */
-	u64        rx_bytes;
-	u64        rx_packets;
-	u64        rx_fcs_error;
-	u64        rx_multicast;
-	u64        rx_broadcast;
-	u64        rx_control_frames;
-	u64        rx_pause;
-	u64        rx_unknown_opcode;
-	u64        rx_alignment_error;
-	u64        rx_frame_length_error;
-	u64        rx_code_error;
-	u64        rx_carrier_sense_error;
-	u64        rx_undersize;
-	u64        rx_oversize;
-	u64        rx_fragments;
-	u64        rx_jabber;
-	u64        rx_drop;
-};
-
-/*
- * MAC Tx Statistics
- */
-struct cna_stats_mac_tx {
-	u64        tx_bytes;
-	u64        tx_packets;
-	u64        tx_multicast;
-	u64        tx_broadcast;
-	u64        tx_pause;
-	u64        tx_deferral;
-	u64        tx_excessive_deferral;
-	u64        tx_single_collision;
-	u64        tx_muliple_collision;
-	u64        tx_late_collision;
-	u64        tx_excessive_collision;
-	u64        tx_total_collision;
-	u64        tx_pause_honored;
-	u64        tx_drop;
-	u64        tx_jabber;
-	u64        tx_fcs_error;
-	u64        tx_control_frame;
-	u64        tx_oversize;
-	u64        tx_undersize;
-	u64        tx_fragments;
-};
-
-/*
- * Complete statistics
- */
-struct bna_stats {
-	struct cna_stats_mac_rx mac_rx_stats;
-	struct cna_stats_bpc_rx bpc_rx_stats;
-	struct cna_stats_rad rad_stats;
-	struct bna_stats_fc_rx fc_rx_stats;
-	struct cna_stats_mac_tx mac_tx_stats;
-	struct cna_stats_bpc_tx bpc_tx_stats;
-	struct bna_stats_fc_tx fc_tx_stats;
-	struct bna_stats_rxf rxf_stats[BNA_TXF_ID_MAX];
-	struct bna_stats_txf txf_stats[BNA_RXF_ID_MAX];
-};
-
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_checksum.h b/drivers/scsi/bfa/include/cs/bfa_checksum.h
deleted file mode 100644
index 650f8d0..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_checksum.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_checksum.h BFA checksum utilities
- */
-
-#ifndef __BFA_CHECKSUM_H__
-#define __BFA_CHECKSUM_H__
-
-static inline u32
-bfa_checksum_u32(u32 *buf, int sz)
-{
-	int		i, m = sz >> 2;
-	u32	sum = 0;
-
-	for (i = 0; i < m; i++)
-		sum ^= buf[i];
-
-	return sum;
-}
-
-static inline u16
-bfa_checksum_u16(u16 *buf, int sz)
-{
-	int             i, m = sz >> 1;
-	u16        sum = 0;
-
-	for (i = 0; i < m; i++)
-		sum ^= buf[i];
-
-	return sum;
-}
-
-static inline u8
-bfa_checksum_u8(u8 *buf, int sz)
-{
-	int             i;
-	u8         sum = 0;
-
-	for (i = 0; i < sz; i++)
-		sum ^= buf[i];
-
-	return sum;
-}
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_debug.h b/drivers/scsi/bfa/include/cs/bfa_debug.h
deleted file mode 100644
index 75a911e..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_debug.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_debug.h BFA debug interfaces
- */
-
-#ifndef __BFA_DEBUG_H__
-#define __BFA_DEBUG_H__
-
-#define bfa_assert(__cond)	do {					\
-	if (!(__cond)) 							\
-		bfa_panic(__LINE__, __FILE__, #__cond);      \
-} while (0)
-
-#define bfa_sm_fault(__mod, __event)	do {				\
-	bfa_trc(__mod, (((uint32_t)0xDEAD << 16) | __event));		\
-	bfa_sm_panic((__mod)->logm, __LINE__, __FILE__, __event); 	\
-} while (0)
-
-#ifndef BFA_PERF_BUILD
-#define bfa_assert_fp(__cond)	bfa_assert(__cond)
-#else
-#define bfa_assert_fp(__cond)
-#endif
-
-struct bfa_log_mod_s;
-void bfa_panic(int line, char *file, char *panicstr);
-void bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event);
-
-#endif /* __BFA_DEBUG_H__ */
diff --git a/drivers/scsi/bfa/include/cs/bfa_log.h b/drivers/scsi/bfa/include/cs/bfa_log.h
deleted file mode 100644
index bc334e0..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_log.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_log.h BFA log library data structure and function definition
- */
-
-#ifndef __BFA_LOG_H__
-#define __BFA_LOG_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_aen.h>
-
-/*
- * BFA log module definition
- *
- * To create a new module id:
- * Add a #define at the end of the list below. Select a value for your
- * definition so that it is one (1) greater than the previous
- * definition. Modify the definition of BFA_LOG_MODULE_ID_MAX to become
- * your new definition.
- * Should have no gaps in between the values because this is used in arrays.
- * IMPORTANT: AEN_IDs must be at the begining, otherwise update bfa_defs_aen.h
- */
-
-enum bfa_log_module_id {
-	BFA_LOG_UNUSED_ID	= 0,
-
-	/* AEN defs begin */
-	BFA_LOG_AEN_MIN		= BFA_LOG_UNUSED_ID,
-
-	BFA_LOG_AEN_ID_ADAPTER 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_ADAPTER,/* 1 */
-	BFA_LOG_AEN_ID_PORT 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_PORT,	/* 2 */
-	BFA_LOG_AEN_ID_LPORT 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_LPORT,	/* 3 */
-	BFA_LOG_AEN_ID_RPORT 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_RPORT,	/* 4 */
-	BFA_LOG_AEN_ID_ITNIM 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_ITNIM,	/* 5 */
-	BFA_LOG_AEN_ID_TIN 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_TIN,	/* 6 */
-	BFA_LOG_AEN_ID_IPFC 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_IPFC,	/* 7 */
-	BFA_LOG_AEN_ID_AUDIT 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_AUDIT,	/* 8 */
-	BFA_LOG_AEN_ID_IOC	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_IOC,	/* 9 */
-	BFA_LOG_AEN_ID_ETHPORT	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_ETHPORT,/* 10 */
-
-	BFA_LOG_AEN_MAX		= BFA_LOG_AEN_ID_ETHPORT,
-	/* AEN defs end */
-
-	BFA_LOG_MODULE_ID_MIN	= BFA_LOG_AEN_MAX,
-
-	BFA_LOG_FW_ID		= BFA_LOG_MODULE_ID_MIN + 1,
-	BFA_LOG_HAL_ID		= BFA_LOG_MODULE_ID_MIN + 2,
-	BFA_LOG_FCS_ID		= BFA_LOG_MODULE_ID_MIN + 3,
-	BFA_LOG_WDRV_ID		= BFA_LOG_MODULE_ID_MIN + 4,
-	BFA_LOG_LINUX_ID	= BFA_LOG_MODULE_ID_MIN + 5,
-	BFA_LOG_SOLARIS_ID	= BFA_LOG_MODULE_ID_MIN + 6,
-
-	BFA_LOG_MODULE_ID_MAX 	= BFA_LOG_SOLARIS_ID,
-
-	/* Not part of any arrays */
-	BFA_LOG_MODULE_ID_ALL 	= BFA_LOG_MODULE_ID_MAX + 1,
-	BFA_LOG_AEN_ALL 	= BFA_LOG_MODULE_ID_MAX + 2,
-	BFA_LOG_DRV_ALL		= BFA_LOG_MODULE_ID_MAX + 3,
-};
-
-/*
- * BFA log catalog name
- */
-#define BFA_LOG_CAT_NAME	"BFA"
-
-/*
- * bfa log severity values
- */
-enum bfa_log_severity {
-	BFA_LOG_INVALID = 0,
-	BFA_LOG_CRITICAL = 1,
-	BFA_LOG_ERROR = 2,
-	BFA_LOG_WARNING = 3,
-	BFA_LOG_INFO = 4,
-	BFA_LOG_NONE = 5,
-	BFA_LOG_LEVEL_MAX = BFA_LOG_NONE
-};
-
-#define BFA_LOG_MODID_OFFSET		16
-
-
-struct bfa_log_msgdef_s {
-	u32	msg_id;		/*  message id */
-	int		attributes;	/*  attributes */
-	int		severity;	/*  severity level */
-	char		*msg_value;
-					/*  msg string */
-	char		*message;
-					/*  msg format string */
-	int		arg_type;	/*  argument type */
-	int		arg_num;	/*  number of argument */
-};
-
-/*
- * supported argument type
- */
-enum bfa_log_arg_type {
-	BFA_LOG_S = 0,		/*  string */
-	BFA_LOG_D,		/*  decimal */
-	BFA_LOG_I,		/*  integer */
-	BFA_LOG_O,		/*  oct number */
-	BFA_LOG_U,		/*  unsigned integer */
-	BFA_LOG_X,		/*  hex number */
-	BFA_LOG_F,		/*  floating */
-	BFA_LOG_C,		/*  character */
-	BFA_LOG_L,		/*  double */
-	BFA_LOG_P		/*  pointer */
-};
-
-#define BFA_LOG_ARG_TYPE	2
-#define BFA_LOG_ARG0		(0 * BFA_LOG_ARG_TYPE)
-#define BFA_LOG_ARG1		(1 * BFA_LOG_ARG_TYPE)
-#define BFA_LOG_ARG2		(2 * BFA_LOG_ARG_TYPE)
-#define BFA_LOG_ARG3		(3 * BFA_LOG_ARG_TYPE)
-
-#define BFA_LOG_GET_MOD_ID(msgid) ((msgid >> BFA_LOG_MODID_OFFSET) & 0xff)
-#define BFA_LOG_GET_MSG_IDX(msgid) (msgid & 0xffff)
-#define BFA_LOG_GET_MSG_ID(msgdef) ((msgdef)->msg_id)
-#define BFA_LOG_GET_MSG_FMT_STRING(msgdef) ((msgdef)->message)
-#define BFA_LOG_GET_SEVERITY(msgdef) ((msgdef)->severity)
-
-/*
- * Event attributes
- */
-#define BFA_LOG_ATTR_NONE	0
-#define BFA_LOG_ATTR_AUDIT	1
-#define BFA_LOG_ATTR_LOG	2
-#define BFA_LOG_ATTR_FFDC	4
-
-#define BFA_LOG_CREATE_ID(msw, lsw) \
-	(((u32)msw << BFA_LOG_MODID_OFFSET) | lsw)
-
-struct bfa_log_mod_s;
-
-/**
- * callback function
- */
-typedef void (*bfa_log_cb_t)(struct bfa_log_mod_s *log_mod, u32 msg_id,
-			const char *format, ...);
-
-
-struct bfa_log_mod_s {
-	char		instance_info[BFA_STRING_32];	/*  instance info */
-	int		log_level[BFA_LOG_MODULE_ID_MAX + 1];
-						/*  log level for modules */
-	bfa_log_cb_t	cbfn; 			/*  callback function */
-};
-
-extern int bfa_log_init(struct bfa_log_mod_s *log_mod,
-			char *instance_name, bfa_log_cb_t cbfn);
-extern int bfa_log(struct bfa_log_mod_s *log_mod, u32 msg_id, ...);
-extern bfa_status_t bfa_log_set_level(struct bfa_log_mod_s *log_mod,
-			int mod_id, enum bfa_log_severity log_level);
-extern bfa_status_t bfa_log_set_level_all(struct bfa_log_mod_s *log_mod,
-			enum bfa_log_severity log_level);
-extern bfa_status_t bfa_log_set_level_aen(struct bfa_log_mod_s *log_mod,
-			enum bfa_log_severity log_level);
-extern enum bfa_log_severity bfa_log_get_level(struct bfa_log_mod_s *log_mod,
-			int mod_id);
-extern enum bfa_log_severity bfa_log_get_msg_level(
-			struct bfa_log_mod_s *log_mod, u32 msg_id);
-/*
- * array of messages generated from xml files
- */
-extern struct bfa_log_msgdef_s bfa_log_msg_array[];
-
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_perf.h b/drivers/scsi/bfa/include/cs/bfa_perf.h
deleted file mode 100644
index 45aa5f9..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_perf.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFAD_PERF_H__
-#define __BFAD_PERF_H__
-
-#ifdef BFAD_PERF_BUILD
-
-#undef bfa_trc
-#undef bfa_trc32
-#undef bfa_assert
-#undef BFA_TRC_FILE
-
-#define bfa_trc(_trcp, _data)
-#define bfa_trc32(_trcp, _data)
-#define bfa_assert(__cond)
-#define BFA_TRC_FILE(__mod, __submod)
-
-#endif
-
-#endif /* __BFAD_PERF_H__ */
diff --git a/drivers/scsi/bfa/include/cs/bfa_plog.h b/drivers/scsi/bfa/include/cs/bfa_plog.h
deleted file mode 100644
index f5bef63..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_plog.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_PORTLOG_H__
-#define __BFA_PORTLOG_H__
-
-#include "protocol/fc.h"
-#include <defs/bfa_defs_types.h>
-
-#define BFA_PL_NLOG_ENTS 256
-#define BFA_PL_LOG_REC_INCR(_x) ((_x)++, (_x) %= BFA_PL_NLOG_ENTS)
-
-#define BFA_PL_STRING_LOG_SZ   32   /* number of chars in string log */
-#define BFA_PL_INT_LOG_SZ      8    /* number of integers in the integer log */
-
-enum bfa_plog_log_type {
-	BFA_PL_LOG_TYPE_INVALID = 0,
-	BFA_PL_LOG_TYPE_INT 	= 1,
-	BFA_PL_LOG_TYPE_STRING 	= 2,
-};
-
-/*
- * the (fixed size) record format for each entry in the portlog
- */
-struct bfa_plog_rec_s {
-	u32        tv;	/* Filled by the portlog driver when the *
-				 * entry is added to the circular log.   */
-	u8         port;	/* Source port that logged this entry. CM
-				 * entities will use 0xFF */
-	u8         mid;	/* Integer value to be used by all entities *
-				 * while logging. The module id to string   *
-				 * conversion will be done by BFAL. See
-				 * enum bfa_plog_mid */
-	u8         eid;	/* indicates Rx, Tx, IOCTL, etc. See
-				 * enum bfa_plog_eid */
-	u8         log_type; /* indicates string log or integer log.
-				   * see bfa_plog_log_type_t */
-	u8         log_num_ints;
-	/*
-	 * interpreted only if log_type is INT_LOG. indicates number of
-	 * integers in the int_log[] (0-PL_INT_LOG_SZ).
-	 */
-	u8         rsvd;
-	u16        misc;	/* can be used to indicate fc frame length,
-				 *etc.. */
-	union {
-		char            string_log[BFA_PL_STRING_LOG_SZ];
-		u32        int_log[BFA_PL_INT_LOG_SZ];
-	} log_entry;
-
-};
-
-/*
- * the following #defines will be used by the logging entities to indicate
- * their module id. BFAL will convert the integer value to string format
- *
-* process to be used while changing the following #defines:
- *  - Always add new entries at the end
- *  - define corresponding string in BFAL
- *  - Do not remove any entry or rearrange the order.
- */
-enum bfa_plog_mid {
-	BFA_PL_MID_INVALID 	= 0,
-	BFA_PL_MID_DEBUG 	= 1,
-	BFA_PL_MID_DRVR 	= 2,
-	BFA_PL_MID_HAL 		= 3,
-	BFA_PL_MID_HAL_FCXP 	= 4,
-	BFA_PL_MID_HAL_UF 	= 5,
-	BFA_PL_MID_FCS 		= 6,
-	BFA_PL_MID_LPS		= 7,
-	BFA_PL_MID_MAX 		= 8
-};
-
-#define BFA_PL_MID_STRLEN    8
-struct bfa_plog_mid_strings_s {
-	char            m_str[BFA_PL_MID_STRLEN];
-};
-
-/*
- * the following #defines will be used by the logging entities to indicate
- * their event type. BFAL will convert the integer value to string format
- *
-* process to be used while changing the following #defines:
- *  - Always add new entries at the end
- *  - define corresponding string in BFAL
- *  - Do not remove any entry or rearrange the order.
- */
-enum bfa_plog_eid {
-	BFA_PL_EID_INVALID 		= 0,
-	BFA_PL_EID_IOC_DISABLE 		= 1,
-	BFA_PL_EID_IOC_ENABLE 		= 2,
-	BFA_PL_EID_PORT_DISABLE 	= 3,
-	BFA_PL_EID_PORT_ENABLE 		= 4,
-	BFA_PL_EID_PORT_ST_CHANGE 	= 5,
-	BFA_PL_EID_TX 			= 6,
-	BFA_PL_EID_TX_ACK1 		= 7,
-	BFA_PL_EID_TX_RJT 		= 8,
-	BFA_PL_EID_TX_BSY 		= 9,
-	BFA_PL_EID_RX 			= 10,
-	BFA_PL_EID_RX_ACK1 		= 11,
-	BFA_PL_EID_RX_RJT 		= 12,
-	BFA_PL_EID_RX_BSY 		= 13,
-	BFA_PL_EID_CT_IN 		= 14,
-	BFA_PL_EID_CT_OUT 		= 15,
-	BFA_PL_EID_DRIVER_START 	= 16,
-	BFA_PL_EID_RSCN 		= 17,
-	BFA_PL_EID_DEBUG 		= 18,
-	BFA_PL_EID_MISC 		= 19,
-	BFA_PL_EID_FIP_FCF_DISC		= 20,
-	BFA_PL_EID_FIP_FCF_CVL		= 21,
-	BFA_PL_EID_LOGIN		= 22,
-	BFA_PL_EID_LOGO			= 23,
-	BFA_PL_EID_MAX			= 24
-};
-
-#define BFA_PL_ENAME_STRLEN    	8
-struct bfa_plog_eid_strings_s {
-	char            e_str[BFA_PL_ENAME_STRLEN];
-};
-
-#define BFA_PL_SIG_LEN	8
-#define BFA_PL_SIG_STR  "12pl123"
-
-/*
- * per port circular log buffer
- */
-struct bfa_plog_s {
-	char            plog_sig[BFA_PL_SIG_LEN];	/* Start signature */
-	u8         plog_enabled;
-	u8         rsvd[7];
-	u32        ticks;
-	u16        head;
-	u16        tail;
-	struct bfa_plog_rec_s  plog_recs[BFA_PL_NLOG_ENTS];
-};
-
-void bfa_plog_init(struct bfa_plog_s *plog);
-void bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-			enum bfa_plog_eid event, u16 misc, char *log_str);
-void bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-			enum bfa_plog_eid event, u16 misc,
-			u32 *intarr, u32 num_ints);
-void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-			enum bfa_plog_eid event, u16 misc,
-			struct fchs_s *fchdr);
-void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-			enum bfa_plog_eid event, u16 misc,
-			struct fchs_s *fchdr, u32 pld_w0);
-void bfa_plog_clear(struct bfa_plog_s *plog);
-void bfa_plog_enable(struct bfa_plog_s *plog);
-void bfa_plog_disable(struct bfa_plog_s *plog);
-bfa_boolean_t	bfa_plog_get_setting(struct bfa_plog_s *plog);
-
-#endif /* __BFA_PORTLOG_H__ */
diff --git a/drivers/scsi/bfa/include/cs/bfa_q.h b/drivers/scsi/bfa/include/cs/bfa_q.h
deleted file mode 100644
index ea895fa..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_q.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_q.h Circular queue definitions.
- */
-
-#ifndef __BFA_Q_H__
-#define __BFA_Q_H__
-
-#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
-#define bfa_q_next(_qe)	(((struct list_head *) (_qe))->next)
-#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev)
-
-/*
- * bfa_q_qe_init - to initialize a queue element
- */
-#define bfa_q_qe_init(_qe) {						\
-	bfa_q_next(_qe) = (struct list_head *) NULL;			\
-	bfa_q_prev(_qe) = (struct list_head *) NULL;			\
-}
-
-/*
- * bfa_q_deq - dequeue an element from head of the queue
- */
-#define bfa_q_deq(_q, _qe) {						\
-	if (!list_empty(_q)) {					\
-		(*((struct list_head **) (_qe))) = bfa_q_next(_q);	\
-		bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) =	\
-						(struct list_head *) (_q); \
-		bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \
-		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		\
-	} else {							\
-		*((struct list_head **) (_qe)) = (struct list_head *) NULL; \
-	}								\
-}
-
-/*
- * bfa_q_deq_tail - dequeue an element from tail of the queue
- */
-#define bfa_q_deq_tail(_q, _qe) {					    \
-	if (!list_empty(_q)) {					            \
-		*((struct list_head **) (_qe)) = bfa_q_prev(_q);	    \
-		bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) = 	    \
-						(struct list_head *) (_q);  \
-		bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);    \
-		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		    \
-	} else {							    \
-		*((struct list_head **) (_qe)) = (struct list_head *) NULL; \
-	}								    \
-}
-
-/*
- * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not
- * consistent across modules)
- */
-#ifndef BFA_PERF_BUILD
-#define BFA_Q_DBG_INIT(_qe)	bfa_q_qe_init(_qe)
-#else
-#define BFA_Q_DBG_INIT(_qe)
-#endif
-
-#define bfa_q_is_on_q(_q, _qe)		\
-	bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
-extern int bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe);
-
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_sm.h b/drivers/scsi/bfa/include/cs/bfa_sm.h
deleted file mode 100644
index 11fba90..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_sm.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfasm.h State machine defines
- */
-
-#ifndef __BFA_SM_H__
-#define __BFA_SM_H__
-
-typedef void (*bfa_sm_t)(void *sm, int event);
-/**
- * oc - object class eg. bfa_ioc
- * st - state, eg. reset
- * otype - object type, eg. struct bfa_ioc_s
- * etype - object type, eg. enum ioc_event
- */
-#define bfa_sm_state_decl(oc, st, otype, etype)         \
-	static void oc ## _sm_ ## st(otype * fsm, etype event)
-
-#define bfa_sm_set_state(_sm, _state)	((_sm)->sm = (bfa_sm_t)(_state))
-#define bfa_sm_send_event(_sm, _event)	((_sm)->sm((_sm), (_event)))
-#define bfa_sm_get_state(_sm)		((_sm)->sm)
-#define bfa_sm_cmp_state(_sm, _state)	((_sm)->sm == (bfa_sm_t)(_state))
-
-/**
- * For converting from state machine function to state encoding.
- */
-struct bfa_sm_table_s {
-	bfa_sm_t	sm;	/*  state machine function	*/
-	int		state;	/*  state machine encoding	*/
-	char		*name;	/*  state name for display	*/
-};
-#define BFA_SM(_sm)	((bfa_sm_t)(_sm))
-
-int bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm);
-
-/**
- * State machine with entry actions.
- */
-typedef void (*bfa_fsm_t)(void *fsm, int event);
-
-/**
- * oc - object class eg. bfa_ioc
- * st - state, eg. reset
- * otype - object type, eg. struct bfa_ioc_s
- * etype - object type, eg. enum ioc_event
- */
-#define bfa_fsm_state_decl(oc, st, otype, etype)		\
-	static void oc ## _sm_ ## st(otype * fsm, etype event);      \
-	static void oc ## _sm_ ## st ## _entry(otype * fsm)
-
-#define bfa_fsm_set_state(_fsm, _state) do {	\
-	(_fsm)->fsm = (bfa_fsm_t)(_state);      \
-	_state ## _entry(_fsm);      \
-} while (0)
-
-#define bfa_fsm_send_event(_fsm, _event)	\
-	((_fsm)->fsm((_fsm), (_event)))
-#define bfa_fsm_cmp_state(_fsm, _state)		\
-	((_fsm)->fsm == (bfa_fsm_t)(_state))
-
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_trc.h b/drivers/scsi/bfa/include/cs/bfa_trc.h
deleted file mode 100644
index 310771c..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_trc.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_TRC_H__
-#define __BFA_TRC_H__
-
-#include <bfa_os_inc.h>
-
-#ifndef BFA_TRC_MAX
-#define BFA_TRC_MAX	(4 * 1024)
-#endif
-
-#ifndef BFA_TRC_TS
-#define BFA_TRC_TS(_trcm)	((_trcm)->ticks++)
-#endif
-
-struct bfa_trc_s {
-#ifdef __BIGENDIAN
-	u16	fileno;
-	u16	line;
-#else
-	u16	line;
-	u16	fileno;
-#endif
-	u32	timestamp;
-	union {
-		struct {
-			u32	rsvd;
-			u32	u32;
-		} u32;
-		u64	u64;
-	} data;
-};
-
-
-struct bfa_trc_mod_s {
-	u32	head;
-	u32	tail;
-	u32	ntrc;
-	u32	stopped;
-	u32	ticks;
-	u32	rsvd[3];
-	struct bfa_trc_s trc[BFA_TRC_MAX];
-};
-
-
-enum {
-	BFA_TRC_FW   = 1,	/*  firmware modules */
-	BFA_TRC_HAL  = 2,	/*  BFA modules */
-	BFA_TRC_FCS  = 3,	/*  BFA FCS modules */
-	BFA_TRC_LDRV = 4,	/*  Linux driver modules */
-	BFA_TRC_SDRV = 5,	/*  Solaris driver modules */
-	BFA_TRC_VDRV = 6,	/*  vmware driver modules */
-	BFA_TRC_WDRV = 7,	/*  windows driver modules */
-	BFA_TRC_AEN  = 8,	/*  AEN module */
-	BFA_TRC_BIOS = 9,	/*  bios driver modules */
-	BFA_TRC_EFI  = 10,	/*  EFI driver modules */
-	BNA_TRC_WDRV = 11,	/*  BNA windows driver modules */
-	BNA_TRC_VDRV = 12,	/*  BNA vmware driver modules */
-	BNA_TRC_SDRV = 13,	/*  BNA Solaris driver modules */
-	BNA_TRC_LDRV = 14,	/*  BNA Linux driver modules */
-	BNA_TRC_HAL  = 15,	/*  BNA modules */
-	BFA_TRC_CNA  = 16,	/*  Common modules */
-	BNA_TRC_IMDRV = 17	/*  BNA windows intermediate driver modules */
-};
-#define BFA_TRC_MOD_SH	10
-#define BFA_TRC_MOD(__mod)	((BFA_TRC_ ## __mod) << BFA_TRC_MOD_SH)
-
-/**
- * Define a new tracing file (module). Module should match one defined above.
- */
-#define BFA_TRC_FILE(__mod, __submod)					\
-	static int __trc_fileno = ((BFA_TRC_ ## __mod ## _ ## __submod) | \
-						 BFA_TRC_MOD(__mod))
-
-
-#define bfa_trc32(_trcp, _data)	\
-	__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
-
-
-#ifndef BFA_BOOT_BUILD
-#define bfa_trc(_trcp, _data)	\
-	__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u64)_data)
-#else
-void bfa_boot_trc(struct bfa_trc_mod_s *trcmod, u16 fileno,
-			u16 line, u32 data);
-#define bfa_trc(_trcp, _data)	\
-	bfa_boot_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
-#endif
-
-
-static inline void
-bfa_trc_init(struct bfa_trc_mod_s *trcm)
-{
-	trcm->head = trcm->tail = trcm->stopped = 0;
-	trcm->ntrc = BFA_TRC_MAX;
-}
-
-
-static inline void
-bfa_trc_stop(struct bfa_trc_mod_s *trcm)
-{
-	trcm->stopped = 1;
-}
-
-#ifdef FWTRC
-extern void dc_flush(void *data);
-#else
-#define dc_flush(data)
-#endif
-
-
-static inline void
-__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
-{
-	int		tail = trcm->tail;
-	struct bfa_trc_s 	*trc = &trcm->trc[tail];
-
-	if (trcm->stopped)
-		return;
-
-	trc->fileno = (u16) fileno;
-	trc->line = (u16) line;
-	trc->data.u64 = data;
-	trc->timestamp = BFA_TRC_TS(trcm);
-	dc_flush(trc);
-
-	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
-	if (trcm->tail == trcm->head)
-		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
-	dc_flush(trcm);
-}
-
-
-static inline void
-__bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
-{
-	int		tail = trcm->tail;
-	struct bfa_trc_s *trc = &trcm->trc[tail];
-
-	if (trcm->stopped)
-		return;
-
-	trc->fileno = (u16) fileno;
-	trc->line = (u16) line;
-	trc->data.u32.u32 = data;
-	trc->timestamp = BFA_TRC_TS(trcm);
-	dc_flush(trc);
-
-	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
-	if (trcm->tail == trcm->head)
-		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
-	dc_flush(trcm);
-}
-
-#ifndef BFA_PERF_BUILD
-#define bfa_trc_fp(_trcp, _data)	bfa_trc(_trcp, _data)
-#else
-#define bfa_trc_fp(_trcp, _data)
-#endif
-
-#endif /* __BFA_TRC_H__ */
-
diff --git a/drivers/scsi/bfa/include/cs/bfa_wc.h b/drivers/scsi/bfa/include/cs/bfa_wc.h
deleted file mode 100644
index 0460bd4..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_wc.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_wc.h Generic wait counter.
- */
-
-#ifndef __BFA_WC_H__
-#define __BFA_WC_H__
-
-typedef void (*bfa_wc_resume_t) (void *cbarg);
-
-struct bfa_wc_s {
-	bfa_wc_resume_t wc_resume;
-	void		*wc_cbarg;
-	int		wc_count;
-};
-
-static inline void
-bfa_wc_up(struct bfa_wc_s *wc)
-{
-	wc->wc_count++;
-}
-
-static inline void
-bfa_wc_down(struct bfa_wc_s *wc)
-{
-	wc->wc_count--;
-	if (wc->wc_count == 0)
-		wc->wc_resume(wc->wc_cbarg);
-}
-
-/**
- * Initialize a waiting counter.
- */
-static inline void
-bfa_wc_init(struct bfa_wc_s *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
-{
-	wc->wc_resume = wc_resume;
-	wc->wc_cbarg = wc_cbarg;
-	wc->wc_count = 0;
-	bfa_wc_up(wc);
-}
-
-/**
- * Wait for counter to reach zero
- */
-static inline void
-bfa_wc_wait(struct bfa_wc_s *wc)
-{
-	bfa_wc_down(wc);
-}
-
-#endif
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h b/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h
deleted file mode 100644
index aea0360..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_ADAPTER_H__
-#define __BFA_DEFS_ADAPTER_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_version.h>
-#include <defs/bfa_defs_mfg.h>
-
-/**
- * BFA adapter level attributes.
- */
-enum {
-	BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE),
-					/*
-					 *!< adapter serial num length
-					 */
-	BFA_ADAPTER_MODEL_NAME_LEN  = 16,  /*  model name length */
-	BFA_ADAPTER_MODEL_DESCR_LEN = 128, /*  model description length */
-	BFA_ADAPTER_MFG_NAME_LEN    = 8,   /*  manufacturer name length */
-	BFA_ADAPTER_SYM_NAME_LEN    = 64,  /*  adapter symbolic name length */
-	BFA_ADAPTER_OS_TYPE_LEN	    = 64,  /*  adapter os type length */
-};
-
-struct bfa_adapter_attr_s {
-	char            manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
-	char            serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
-	u32		card_type;
-	char            model[BFA_ADAPTER_MODEL_NAME_LEN];
-	char            model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
-	wwn_t           pwwn;
-	char            node_symname[FC_SYMNAME_MAX];
-	char            hw_ver[BFA_VERSION_LEN];
-	char            fw_ver[BFA_VERSION_LEN];
-	char            optrom_ver[BFA_VERSION_LEN];
-	char            os_type[BFA_ADAPTER_OS_TYPE_LEN];
-	struct bfa_mfg_vpd_s	vpd;
-	struct mac_s	mac;
-
-	u8		nports;
-	u8		max_speed;
-	u8		prototype;
-	char	        asic_rev;
-
-	u8         pcie_gen;
-	u8         pcie_lanes_orig;
-	u8         pcie_lanes;
-	u8	        cna_capable;
-	u8         is_mezz;
-};
-
-/**
- * BFA adapter level events
- * Arguments below are in BFAL context from Mgmt
- * BFA_PORT_AEN_ADD:        [in]: None     [out]: serial_num, pwwn, nports
- * BFA_PORT_AEN_REMOVE:     [in]: pwwn     [out]: serial_num, pwwn, nports
- */
-enum bfa_adapter_aen_event {
-	BFA_ADAPTER_AEN_ADD 	= 1,	/*  New Adapter found event */
-	BFA_ADAPTER_AEN_REMOVE 	= 2,	/*  Adapter removed event */
-};
-
-struct bfa_adapter_aen_data_s {
-	char            serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
-	u32        nports;	/*  Number of NPorts */
-	wwn_t           pwwn;	/*  WWN of one of its physical port */
-};
-
-#endif /* __BFA_DEFS_ADAPTER_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_aen.h b/drivers/scsi/bfa/include/defs/bfa_defs_aen.h
deleted file mode 100644
index 3524469..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_aen.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_AEN_H__
-#define __BFA_DEFS_AEN_H__
-
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_ioc.h>
-#include <defs/bfa_defs_adapter.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_lport.h>
-#include <defs/bfa_defs_rport.h>
-#include <defs/bfa_defs_itnim.h>
-#include <defs/bfa_defs_tin.h>
-#include <defs/bfa_defs_ipfc.h>
-#include <defs/bfa_defs_audit.h>
-#include <defs/bfa_defs_ethport.h>
-
-#define BFA_AEN_MAX_APP         5
-
-enum bfa_aen_app {
-	bfa_aen_app_bcu = 0,    /* No thread for bcu */
-	bfa_aen_app_hcm = 1,
-	bfa_aen_app_cim = 2,
-	bfa_aen_app_snia = 3,
-	bfa_aen_app_test = 4,   /* To be removed after unit test */
-};
-
-enum bfa_aen_category {
-	BFA_AEN_CAT_ADAPTER 	= 1,
-	BFA_AEN_CAT_PORT 	= 2,
-	BFA_AEN_CAT_LPORT 	= 3,
-	BFA_AEN_CAT_RPORT 	= 4,
-	BFA_AEN_CAT_ITNIM 	= 5,
-	BFA_AEN_CAT_TIN 	= 6,
-	BFA_AEN_CAT_IPFC 	= 7,
-	BFA_AEN_CAT_AUDIT 	= 8,
-	BFA_AEN_CAT_IOC 	= 9,
-	BFA_AEN_CAT_ETHPORT	= 10,
-	BFA_AEN_MAX_CAT 	= 10
-};
-
-#pragma pack(1)
-union bfa_aen_data_u {
-	struct bfa_adapter_aen_data_s 	adapter;
-	struct bfa_port_aen_data_s 	port;
-	struct bfa_lport_aen_data_s 	lport;
-	struct bfa_rport_aen_data_s 	rport;
-	struct bfa_itnim_aen_data_s 	itnim;
-	struct bfa_audit_aen_data_s 	audit;
-	struct bfa_ioc_aen_data_s 	ioc;
-	struct bfa_ethport_aen_data_s 	ethport;
-};
-
-struct bfa_aen_entry_s {
-	enum bfa_aen_category 	aen_category;
-	int			aen_type;
-	union bfa_aen_data_u  	aen_data;
-	struct bfa_timeval_s   	aen_tv;
-	s32         	seq_num;
-	s32         	bfad_num;
-	s32         	rsvd[1];
-};
-
-#pragma pack()
-
-#define bfa_aen_event_t int
-
-#endif /* __BFA_DEFS_AEN_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_audit.h b/drivers/scsi/bfa/include/defs/bfa_defs_audit.h
deleted file mode 100644
index 8e3a962..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_audit.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_AUDIT_H__
-#define __BFA_DEFS_AUDIT_H__
-
-#include <bfa_os_inc.h>
-
-/**
- * BFA audit events
- */
-enum bfa_audit_aen_event {
-	BFA_AUDIT_AEN_AUTH_ENABLE 	= 1,
-	BFA_AUDIT_AEN_AUTH_DISABLE 	= 2,
-};
-
-/**
- * audit event data
- */
-struct bfa_audit_aen_data_s {
-	wwn_t           pwwn;
-};
-
-#endif /* __BFA_DEFS_AUDIT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_auth.h b/drivers/scsi/bfa/include/defs/bfa_defs_auth.h
deleted file mode 100644
index f56ed87..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_auth.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_AUTH_H__
-#define __BFA_DEFS_AUTH_H__
-
-#include <defs/bfa_defs_types.h>
-
-#define PUBLIC_KEY			15409
-#define PRIVATE_KEY			19009
-#define KEY_LEN				32399
-#define BFA_AUTH_SECRET_STRING_LEN	256
-#define BFA_AUTH_FAIL_NO_PASSWORD	0xFE
-#define BFA_AUTH_FAIL_TIMEOUT		0xFF
-
-/**
- * Authentication status
- */
-enum bfa_auth_status {
-	BFA_AUTH_STATUS_NONE 	= 0,	/*  no authentication */
-	BFA_AUTH_UNINIT 	= 1,	/*  state - uninit */
-	BFA_AUTH_NEG_SEND 	= 2,	/*  state - negotiate send */
-	BFA_AUTH_CHAL_WAIT 	= 3,	/*  state - challenge wait */
-	BFA_AUTH_NEG_RETRY 	= 4,	/*  state - negotiate retry */
-	BFA_AUTH_REPLY_SEND 	= 5,	/*  state - reply send */
-	BFA_AUTH_STATUS_WAIT 	= 6,	/*  state - status wait */
-	BFA_AUTH_SUCCESS 	= 7,	/*  state - success */
-	BFA_AUTH_FAILED 	= 8,	/*  state - failed */
-	BFA_AUTH_STATUS_UNKNOWN = 9,	/*  authentication status unknown */
-};
-
-enum bfa_auth_rej_code {
-	BFA_AUTH_RJT_CODE_AUTH_FAILURE   = 1, /* auth failure */
-	BFA_AUTH_RJT_CODE_LOGICAL_ERR    = 2, /* logical error */
-};
-
-/**
- * Authentication reject codes
- */
-enum bfa_auth_rej_code_exp {
-	BFA_AUTH_MECH_NOT_USABLE        = 1, /* auth. mechanism not usable */
-	BFA_AUTH_DH_GROUP_NOT_USABLE    = 2, /* DH Group not usable */
-	BFA_AUTH_HASH_FUNC_NOT_USABLE   = 3, /* hash Function not usable */
-	BFA_AUTH_AUTH_XACT_STARTED      = 4, /* auth xact started */
-	BFA_AUTH_AUTH_FAILED            = 5, /* auth failed */
-	BFA_AUTH_INCORRECT_PLD          = 6, /* incorrect payload */
-	BFA_AUTH_INCORRECT_PROTO_MSG    = 7, /* incorrect proto msg */
-	BFA_AUTH_RESTART_AUTH_PROTO     = 8, /* restart auth protocol */
-	BFA_AUTH_AUTH_CONCAT_NOT_SUPP   = 9, /* auth concat not supported */
-	BFA_AUTH_PROTO_VER_NOT_SUPP     = 10,/* proto version not supported */
-};
-
-struct auth_proto_stats_s {
-	u32        auth_rjts;
-	u32        auth_negs;
-	u32        auth_dones;
-
-	u32        dhchap_challenges;
-	u32        dhchap_replies;
-	u32        dhchap_successes;
-};
-
-/**
- * Authentication related statistics
- */
-struct bfa_auth_stats_s {
-	u32           auth_failures;	/*  authentication failures */
-	u32           auth_successes;	/*  authentication successes*/
-	struct auth_proto_stats_s auth_rx_stats; /*  Rx protocol stats */
-	struct auth_proto_stats_s auth_tx_stats; /*  Tx protocol stats */
-};
-
-/**
- * Authentication hash function algorithms
- */
-enum bfa_auth_algo {
-	BFA_AUTH_ALGO_MD5 	= 1,	/*  Message-Digest algorithm 5 */
-	BFA_AUTH_ALGO_SHA1 	= 2,	/*  Secure Hash Algorithm 1 */
-	BFA_AUTH_ALGO_MS 	= 3,	/*  MD5, then SHA-1 */
-	BFA_AUTH_ALGO_SM 	= 4,	/*  SHA-1, then MD5 */
-};
-
-/**
- * DH Groups
- *
- * Current value could be combination of one or more of the following values
- */
-enum bfa_auth_group {
-	BFA_AUTH_GROUP_DHNULL 	= 0,	/*  DH NULL (value == 0) */
-	BFA_AUTH_GROUP_DH768 	= 1,	/*  DH group 768 (value == 1) */
-	BFA_AUTH_GROUP_DH1024 	= 2,	/*  DH group 1024 (value == 2) */
-	BFA_AUTH_GROUP_DH1280 	= 4,	/*  DH group 1280 (value == 3) */
-	BFA_AUTH_GROUP_DH1536 	= 8,	/*  DH group 1536 (value == 4) */
-
-	BFA_AUTH_GROUP_ALL 	= 256	/*  Use default DH group order
-					 *    0, 1, 2, 3, 4 */
-};
-
-/**
- * Authentication secret sources
- */
-enum bfa_auth_secretsource {
-	BFA_AUTH_SECSRC_LOCAL 	= 1,	/*  locally configured */
-	BFA_AUTH_SECSRC_RADIUS 	= 2,	/*  use radius server */
-	BFA_AUTH_SECSRC_TACACS 	= 3,	/*  TACACS server */
-};
-
-/**
- * Authentication attributes
- */
-struct bfa_auth_attr_s {
-	enum bfa_auth_status 	status;
-	enum bfa_auth_algo 	algo;
-	enum bfa_auth_group 	dh_grp;
-	enum bfa_auth_rej_code  rjt_code;
-	enum bfa_auth_rej_code_exp rjt_code_exp;
-	u8			secret_set;
-	u8			resv[3];
-};
-
-#endif /* __BFA_DEFS_AUTH_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_boot.h b/drivers/scsi/bfa/include/defs/bfa_defs_boot.h
deleted file mode 100644
index 0fca10b..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_boot.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_BOOT_H__
-#define __BFA_DEFS_BOOT_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_pport.h>
-
-enum {
-	BFA_BOOT_BOOTLUN_MAX = 4,	/*  maximum boot lun per IOC */
-	BFA_PREBOOT_BOOTLUN_MAX = 8,    /*  maximum preboot lun per IOC */
-
-};
-
-#define BOOT_CFG_REV1	1
-
-/**
- *      Boot options setting. Boot options setting determines from where
- *      to get the boot lun information
- */
-enum bfa_boot_bootopt {
-    BFA_BOOT_AUTO_DISCOVER = 0,    /*  Boot from blun provided by fabric */
-    BFA_BOOT_STORED_BLUN   = 1,    /*  Boot from bluns stored in flash   */
-    BFA_BOOT_FIRST_LUN     = 2,    /*  Boot from first discovered blun   */
-};
-
-/**
- * Boot lun information.
- */
-struct bfa_boot_bootlun_s {
-	wwn_t           pwwn;	/*  port wwn of target */
-	lun_t           lun;	/*  64-bit lun */
-};
-
-/**
- * BOOT boot configuraton
- */
-struct bfa_boot_cfg_s {
-	u8         version;
-	u8         rsvd1;
-	u16        chksum;
-
-	u8         enable;		/*  enable/disable SAN boot */
-	u8         speed;		/*  boot speed settings */
-	u8         topology;	/*  boot topology setting */
-	u8         bootopt;	/*  bfa_boot_bootopt_t */
-
-	u32        nbluns;		/*  number of boot luns */
-
-	u32        rsvd2;
-
-	struct bfa_boot_bootlun_s blun[BFA_BOOT_BOOTLUN_MAX];
-	struct bfa_boot_bootlun_s blun_disc[BFA_BOOT_BOOTLUN_MAX];
-};
-
-struct bfa_boot_pbc_s {
-	u8         enable;         /* enable/disable SAN boot */
-	u8         speed;          /* boot speed settings */
-	u8         topology;       /* boot topology setting */
-	u8         rsvd1;
-	u32        nbluns;         /* number of boot luns */
-	struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX];
-};
-
-#endif /* __BFA_DEFS_BOOT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_cee.h b/drivers/scsi/bfa/include/defs/bfa_defs_cee.h
deleted file mode 100644
index 6eaf519..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_cee.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- *  bfa_defs_cee.h Interface declarations between host based
- *	BFAL and DCBX/LLDP module in Firmware
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_CEE_H__
-#define __BFA_DEFS_CEE_H__
-
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_pport.h>
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-#define BFA_CEE_LLDP_MAX_STRING_LEN (128)
-
-#define BFA_CEE_LLDP_SYS_CAP_OTHER       0x0001
-#define BFA_CEE_LLDP_SYS_CAP_REPEATER    0x0002
-#define BFA_CEE_LLDP_SYS_CAP_MAC_BRIDGE  0x0004
-#define BFA_CEE_LLDP_SYS_CAP_WLAN_AP     0x0008
-#define BFA_CEE_LLDP_SYS_CAP_ROUTER      0x0010
-#define BFA_CEE_LLDP_SYS_CAP_TELEPHONE 	 0x0020
-#define BFA_CEE_LLDP_SYS_CAP_DOCSIS_CD   0x0040
-#define BFA_CEE_LLDP_SYS_CAP_STATION     0x0080
-#define BFA_CEE_LLDP_SYS_CAP_CVLAN	     0x0100
-#define BFA_CEE_LLDP_SYS_CAP_SVLAN 	     0x0200
-#define BFA_CEE_LLDP_SYS_CAP_TPMR		 0x0400
-
-
-/* LLDP string type */
-struct bfa_cee_lldp_str_s {
-	u8 sub_type;
-	u8 len;
-	u8 rsvd[2];
-	u8 value[BFA_CEE_LLDP_MAX_STRING_LEN];
-};
-
-
-/* LLDP parameters */
-struct bfa_cee_lldp_cfg_s {
-	struct bfa_cee_lldp_str_s chassis_id;
-	struct bfa_cee_lldp_str_s port_id;
-	struct bfa_cee_lldp_str_s port_desc;
-	struct bfa_cee_lldp_str_s sys_name;
-	struct bfa_cee_lldp_str_s sys_desc;
-	struct bfa_cee_lldp_str_s mgmt_addr;
-	u16    time_to_interval;
-	u16    enabled_system_cap;
-};
-
-enum bfa_cee_dcbx_version_e {
-	DCBX_PROTOCOL_PRECEE = 1,
-	DCBX_PROTOCOL_CEE    = 2,
-};
-
-enum bfa_cee_lls_e {
-	CEE_LLS_DOWN_NO_TLV = 0, /* LLS is down because the TLV not sent by
-				  * the peer */
-	CEE_LLS_DOWN        = 1, /* LLS is down as advertised by the peer */
-	CEE_LLS_UP          = 2,
-};
-
-/* CEE/DCBX parameters */
-struct bfa_cee_dcbx_cfg_s {
-	u8 pgid[8];
-	u8 pg_percentage[8];
-	u8 pfc_enabled;          /* bitmap of priorties with PFC enabled */
-	u8 fcoe_user_priority;   /* bitmap of priorities used for FcoE
-				       * traffic */
-	u8 dcbx_version;	/* operating version:CEE or preCEE */
-	u8 lls_fcoe;	/* FCoE Logical Link Status */
-	u8 lls_lan;	/* LAN Logical Link Status */
-	u8 rsvd[3];
-};
-
-/* CEE status */
-/* Making this to tri-state for the benefit of port list command */
-enum bfa_cee_status_e {
-	CEE_UP = 0,
-	CEE_PHY_UP = 1,
-	CEE_LOOPBACK = 2,
-	CEE_PHY_DOWN = 3,
-};
-
-/* CEE Query */
-struct bfa_cee_attr_s {
-	u8                   cee_status;
-	u8                   error_reason;
-	struct bfa_cee_lldp_cfg_s lldp_remote;
-	struct bfa_cee_dcbx_cfg_s dcbx_remote;
-	mac_t src_mac;
-	u8 link_speed;
-	u8 nw_priority;
-	u8 filler[2];
-};
-
-
-
-
-/* LLDP/DCBX/CEE Statistics */
-
-struct bfa_cee_lldp_stats_s {
-	u32 frames_transmitted;
-	u32 frames_aged_out;
-	u32 frames_discarded;
-	u32 frames_in_error;
-	u32 frames_rcvd;
-	u32 tlvs_discarded;
-	u32 tlvs_unrecognized;
-};
-
-struct bfa_cee_dcbx_stats_s {
-	u32 subtlvs_unrecognized;
-	u32 negotiation_failed;
-	u32 remote_cfg_changed;
-	u32 tlvs_received;
-	u32 tlvs_invalid;
-	u32 seqno;
-	u32 ackno;
-	u32 recvd_seqno;
-	u32 recvd_ackno;
-};
-
-struct bfa_cee_cfg_stats_s {
-	u32 cee_status_down;
-	u32 cee_status_up;
-	u32 cee_hw_cfg_changed;
-	u32 recvd_invalid_cfg;
-};
-
-
-struct bfa_cee_stats_s {
-	struct bfa_cee_lldp_stats_s lldp_stats;
-	struct bfa_cee_dcbx_stats_s dcbx_stats;
-	struct bfa_cee_cfg_stats_s  cfg_stats;
-};
-
-#pragma pack()
-
-
-#endif	/* __BFA_DEFS_CEE_H__ */
-
-
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_driver.h b/drivers/scsi/bfa/include/defs/bfa_defs_driver.h
deleted file mode 100644
index 7d00d00..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_driver.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_DRIVER_H__
-#define __BFA_DEFS_DRIVER_H__
-
-/**
- * Driver statistics
- */
-struct bfa_driver_stats_s {
-	u16    tm_io_abort;
-    u16    tm_io_abort_comp;
-    u16    tm_lun_reset;
-    u16    tm_lun_reset_comp;
-    u16    tm_target_reset;
-    u16    tm_bus_reset;
-    u16    ioc_restart;        /*  IOC restart count */
-    u16    rsvd;
-    u64    control_req;
-    u64    input_req;
-    u64    output_req;
-    u64    input_words;
-    u64    output_words;
-};
-
-
-#endif /* __BFA_DEFS_DRIVER_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h b/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h
deleted file mode 100644
index b4fa092..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_ETHPORT_H__
-#define __BFA_DEFS_ETHPORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_port.h>
-#include <protocol/types.h>
-#include <cna/pstats/phyport_defs.h>
-#include <cna/pstats/ethport_defs.h>
-
-struct bna_tx_info_s {
-	u32    miniport_state;
-	u32    adapter_state;
-	u64    tx_count;
-	u64    tx_wi;
-	u64    tx_sg;
-	u64    tx_tcp_chksum;
-	u64    tx_udp_chksum;
-	u64    tx_ip_chksum;
-	u64    tx_lsov1;
-	u64    tx_lsov2;
-	u64    tx_max_sg_len ;
-};
-
-struct bna_rx_queue_info_s {
-	u16    q_id ;
-	u16    buf_size ;
-	u16    buf_count ;
-	u16    rsvd ;
-	u64    rx_count ;
-	u64    rx_dropped ;
-	u64    rx_unsupported ;
-	u64    rx_internal_err ;
-	u64    rss_count ;
-	u64    vlan_count ;
-	u64    rx_tcp_chksum ;
-	u64    rx_udp_chksum ;
-	u64    rx_ip_chksum ;
-	u64    rx_hds ;
-};
-
-struct bna_rx_q_set_s {
-	u16    q_set_type;
-	u32    miniport_state;
-	u32    adapter_state;
-	struct bna_rx_queue_info_s    rx_queue[2];
-};
-
-struct bna_port_stats_s {
-	struct bna_tx_info_s   tx_stats;
-	u16        qset_count ;
-	struct bna_rx_q_set_s  rx_qset[8];
-};
-
-struct bfa_ethport_stats_s {
-	struct bna_stats_txf	txf_stats[1];
-	struct bna_stats_rxf	rxf_stats[1];
-	struct bnad_drv_stats drv_stats;
-};
-
-/**
- * Ethernet port events
- * Arguments below are in BFAL context from Mgmt
- * BFA_PORT_AEN_ETH_LINKUP:    [in]: mac [out]: mac
- * BFA_PORT_AEN_ETH_LINKDOWN:  [in]: mac [out]: mac
- * BFA_PORT_AEN_ETH_ENABLE:  [in]: mac [out]: mac
- * BFA_PORT_AEN_ETH_DISABLE:  [in]: mac [out]: mac
- *
- */
-enum bfa_ethport_aen_event {
-	BFA_ETHPORT_AEN_LINKUP = 1, /*  Base Port Ethernet link up event */
-	BFA_ETHPORT_AEN_LINKDOWN = 2, /*  Base Port Ethernet link down event */
-	BFA_ETHPORT_AEN_ENABLE = 3, /*  Base Port Ethernet link enable event */
-	BFA_ETHPORT_AEN_DISABLE = 4, /*  Base Port Ethernet link disable
-				      * event */
-};
-
-struct bfa_ethport_aen_data_s {
-	mac_t mac;	/*  MAC address of the physical port */
-};
-
-
-#endif /* __BFA_DEFS_ETHPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h b/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h
deleted file mode 100644
index c08f4f5..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_FCPIM_H__
-#define __BFA_DEFS_FCPIM_H__
-
-struct bfa_fcpim_stats_s {
-	u32        total_ios;	/*  Total IO count */
-	u32        qresumes;	/*  IO waiting for CQ space */
-	u32        no_iotags;	/*  NO IO contexts */
-	u32        io_aborts;	/*  IO abort requests */
-	u32        no_tskims;	/*  NO task management contexts */
-	u32        iocomp_ok;	/*  IO completions with OK status */
-	u32        iocomp_underrun;	/*  IO underrun (good) */
-	u32        iocomp_overrun;	/*  IO overrun (good) */
-	u32        iocomp_aborted;	/*  Aborted IO requests */
-	u32        iocomp_timedout;	/*  IO timeouts */
-	u32        iocom_nexus_abort;	/*  IO selection timeouts */
-	u32        iocom_proto_err;	/*  IO protocol errors */
-	u32        iocom_dif_err;	/*  IO SBC-3 protection errors */
-	u32        iocom_tm_abort;	/*  IO aborted by TM requests */
-	u32        iocom_sqer_needed;	/*  IO retry for SQ error
-						 *recovery */
-	u32        iocom_res_free;	/*  Delayed freeing of IO resources */
-	u32        iocomp_scsierr;	/*  IO with non-good SCSI status */
-	u32        iocom_hostabrts;	/*  Host IO abort requests */
-	u32        iocom_utags;	/*  IO comp with unknown tags */
-	u32        io_cleanups;	/*  IO implicitly aborted */
-	u32        io_tmaborts;	/*  IO aborted due to TM commands */
-	u32        rsvd;
-};
-#endif /*__BFA_DEFS_FCPIM_H__*/
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h b/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h
deleted file mode 100644
index af86a63..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- *  bfa_defs_fcport.h
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_FCPORT_H__
-#define __BFA_DEFS_FCPORT_H__
-
-#include <defs/bfa_defs_types.h>
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-/**
- * FCoE statistics
- */
-struct bfa_fcoe_stats_s {
-	u64	secs_reset;	/*  Seconds since stats reset	     */
-	u64	cee_linkups;	/*  CEE link up		     */
-	u64	cee_linkdns;	/*  CEE link down		     */
-	u64	fip_linkups;	/*  FIP link up		     */
-	u64	fip_linkdns;	/*  FIP link down		     */
-	u64	fip_fails;	/*  FIP failures		     */
-	u64	mac_invalids;	/*  Invalid mac assignments	     */
-	u64	vlan_req;	/*  Vlan requests		     */
-	u64	vlan_notify;	/*  Vlan notifications		     */
-	u64	vlan_err;	/*  Vlan notification errors	     */
-	u64	vlan_timeouts;	/*  Vlan request timeouts	     */
-	u64	vlan_invalids;	/*  Vlan invalids		     */
-	u64	disc_req;	/*  Discovery requests		     */
-	u64	disc_rsp;	/*  Discovery responses	     */
-	u64	disc_err;	/*  Discovery error frames	     */
-	u64	disc_unsol;	/*  Discovery unsolicited	     */
-	u64	disc_timeouts;	/*  Discovery timeouts		     */
-	u64	disc_fcf_unavail; /*  Discovery FCF not avail	     */
-	u64	linksvc_unsupp;	/*  FIP link service req unsupp.    */
-	u64	linksvc_err;	/*  FIP link service req errors     */
-	u64	logo_req;	/*  FIP logos received			     */
-	u64	clrvlink_req;	/*  Clear virtual link requests     */
-	u64	op_unsupp;	/*  FIP operation unsupp.	     */
-	u64	untagged;	/*  FIP untagged frames	     */
-	u64	txf_ucast;	/*  Tx FCoE unicast frames	     */
-	u64	txf_ucast_vlan;	/*  Tx FCoE unicast vlan frames     */
-	u64	txf_ucast_octets; /*  Tx FCoE unicast octets	     */
-	u64	txf_mcast;	/*  Tx FCoE mutlicast frames	     */
-	u64	txf_mcast_vlan;	/*  Tx FCoE mutlicast vlan frames   */
-	u64	txf_mcast_octets; /*  Tx FCoE multicast octets	     */
-	u64	txf_bcast;	/*  Tx FCoE broadcast frames	     */
-	u64	txf_bcast_vlan;	/*  Tx FCoE broadcast vlan frames   */
-	u64	txf_bcast_octets; /*  Tx FCoE broadcast octets	     */
-	u64	txf_timeout;	/*  Tx timeouts		     */
-	u64	txf_parity_errors; /*  Transmit parity err	     */
-	u64	txf_fid_parity_errors; /*  Transmit FID parity err  */
-	u64     rxf_ucast_octets; /* Rx FCoE unicast octets        */
-	u64     rxf_ucast;      /* Rx FCoE unicast frames          */
-	u64     rxf_ucast_vlan; /* Rx FCoE unicast vlan frames     */
-	u64     rxf_mcast_octets; /* Rx FCoE multicast octets      */
-	u64     rxf_mcast;      /* Rx FCoE multicast frames        */
-	u64     rxf_mcast_vlan; /* Rx FCoE multicast vlan frames   */
-	u64     rxf_bcast_octets; /* Rx FCoE broadcast octets      */
-	u64     rxf_bcast;      /* Rx FCoE broadcast frames        */
-	u64     rxf_bcast_vlan; /* Rx FCoE broadcast vlan frames   */
-};
-
-/**
- * QoS or FCoE stats (fcport stats excluding physical FC port stats)
- */
-union bfa_fcport_stats_u {
-	struct bfa_qos_stats_s	fcqos;
-	struct bfa_fcoe_stats_s	fcoe;
-};
-
-#pragma pack()
-
-#endif  /* __BFA_DEFS_FCPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h b/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h
deleted file mode 100644
index add0a05..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_IOC_H__
-#define __BFA_DEFS_IOC_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_version.h>
-#include <defs/bfa_defs_adapter.h>
-#include <defs/bfa_defs_pm.h>
-
-enum {
-	BFA_IOC_DRIVER_LEN	= 16,
-	BFA_IOC_CHIP_REV_LEN 	= 8,
-};
-
-/**
- * Driver and firmware versions.
- */
-struct bfa_ioc_driver_attr_s {
-	char            driver[BFA_IOC_DRIVER_LEN];	/*  driver name */
-	char            driver_ver[BFA_VERSION_LEN];	/*  driver version */
-	char            fw_ver[BFA_VERSION_LEN];	/*  firmware version*/
-	char            bios_ver[BFA_VERSION_LEN];	/*  bios version */
-	char            efi_ver[BFA_VERSION_LEN];	/*  EFI version */
-	char            ob_ver[BFA_VERSION_LEN];	/*  openboot version*/
-};
-
-/**
- * IOC PCI device attributes
- */
-struct bfa_ioc_pci_attr_s {
-	u16        vendor_id;	/*  PCI vendor ID */
-	u16        device_id;	/*  PCI device ID */
-	u16        ssid;		/*  subsystem ID */
-	u16        ssvid;		/*  subsystem vendor ID */
-	u32        pcifn;		/*  PCI device function */
-	u32        rsvd;		/* padding */
-	u8         chip_rev[BFA_IOC_CHIP_REV_LEN];	 /*  chip revision */
-};
-
-/**
- * IOC states
- */
-enum bfa_ioc_state {
-	BFA_IOC_RESET       = 1,  /*  IOC is in reset state */
-	BFA_IOC_SEMWAIT     = 2,  /*  Waiting for IOC hardware semaphore */
-	BFA_IOC_HWINIT 	    = 3,  /*  IOC hardware is being initialized */
-	BFA_IOC_GETATTR     = 4,  /*  IOC is being configured */
-	BFA_IOC_OPERATIONAL = 5,  /*  IOC is operational */
-	BFA_IOC_INITFAIL    = 6,  /*  IOC hardware failure */
-	BFA_IOC_HBFAIL      = 7,  /*  IOC heart-beat failure */
-	BFA_IOC_DISABLING   = 8,  /*  IOC is being disabled */
-	BFA_IOC_DISABLED    = 9,  /*  IOC is disabled */
-	BFA_IOC_FWMISMATCH  = 10, /*  IOC firmware different from drivers */
-};
-
-/**
- * IOC firmware stats
- */
-struct bfa_fw_ioc_stats_s {
-	u32        hb_count;
-	u32        cfg_reqs;
-	u32        enable_reqs;
-	u32        disable_reqs;
-	u32        stats_reqs;
-	u32        clrstats_reqs;
-	u32        unknown_reqs;
-	u32        ic_reqs;		/*  interrupt coalesce reqs */
-};
-
-/**
- * IOC driver stats
- */
-struct bfa_ioc_drv_stats_s {
-	u32	ioc_isrs;
-	u32	ioc_enables;
-	u32	ioc_disables;
-	u32	ioc_hbfails;
-	u32	ioc_boots;
-	u32	stats_tmos;
-	u32        hb_count;
-	u32        disable_reqs;
-	u32        enable_reqs;
-	u32        disable_replies;
-	u32        enable_replies;
-};
-
-/**
- * IOC statistics
- */
-struct bfa_ioc_stats_s {
-	struct bfa_ioc_drv_stats_s	drv_stats; /*  driver IOC stats */
-	struct bfa_fw_ioc_stats_s 	fw_stats;  /*  firmware IOC stats */
-};
-
-
-enum bfa_ioc_type_e {
-	BFA_IOC_TYPE_FC	  = 1,
-	BFA_IOC_TYPE_FCoE = 2,
-	BFA_IOC_TYPE_LL	  = 3,
-};
-
-/**
- * IOC attributes returned in queries
- */
-struct bfa_ioc_attr_s {
-	enum bfa_ioc_type_e		ioc_type;
-	enum bfa_ioc_state 		state;		/*  IOC state      */
-	struct bfa_adapter_attr_s	adapter_attr;	/*  HBA attributes */
-	struct bfa_ioc_driver_attr_s 	driver_attr;	/*  driver attr    */
-	struct bfa_ioc_pci_attr_s	pci_attr;
-	u8				port_id;	/*  port number    */
-	u8				rsvd[7];	/*  64bit align    */
-};
-
-/**
- * BFA IOC level events
- */
-enum bfa_ioc_aen_event {
-	BFA_IOC_AEN_HBGOOD	= 1,	/*  Heart Beat restore event	*/
-	BFA_IOC_AEN_HBFAIL	= 2,	/*  Heart Beat failure event	*/
-	BFA_IOC_AEN_ENABLE	= 3,	/*  IOC enabled event		*/
-	BFA_IOC_AEN_DISABLE	= 4,	/*  IOC disabled event		*/
-	BFA_IOC_AEN_FWMISMATCH	= 5,	/*  IOC firmware mismatch	*/
-	BFA_IOC_AEN_FWCFG_ERROR = 6,    /*  IOC firmware config error   */
-	BFA_IOC_AEN_INVALID_VENDOR = 7,
-	BFA_IOC_AEN_INVALID_NWWN = 8,   /*  Zero NWWN                   */
-	BFA_IOC_AEN_INVALID_PWWN = 9    /*  Zero PWWN                   */
-
-};
-
-/**
- * BFA IOC level event data, now just a place holder
- */
-struct bfa_ioc_aen_data_s {
-	wwn_t	pwwn;
-	s16 ioc_type;
-	mac_t	mac;
-};
-
-#endif /* __BFA_DEFS_IOC_H__ */
-
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h b/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h
deleted file mode 100644
index 31e728a..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_IOCFC_H__
-#define __BFA_DEFS_IOCFC_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_version.h>
-#include <defs/bfa_defs_adapter.h>
-#include <defs/bfa_defs_pm.h>
-
-#define BFA_IOCFC_INTR_DELAY	1125
-#define BFA_IOCFC_INTR_LATENCY	225
-#define BFA_IOCFCOE_INTR_DELAY  25
-#define BFA_IOCFCOE_INTR_LATENCY 5
-
-/**
- * Interrupt coalescing configuration.
- */
-struct bfa_iocfc_intr_attr_s {
-	bfa_boolean_t	coalesce;	/*  enable/disable coalescing */
-	u16	latency;	/*  latency in microseconds   */
-	u16	delay;		/*  delay in microseconds     */
-};
-
-/**
- * IOC firmware configuraton
- */
-struct bfa_iocfc_fwcfg_s {
-	u16        num_fabrics;	/*  number of fabrics		*/
-	u16        num_lports;	/*  number of local lports	*/
-	u16        num_rports;	/*  number of remote ports	*/
-	u16        num_ioim_reqs;	/*  number of IO reqs		*/
-	u16        num_tskim_reqs;	/*  task management requests	*/
-	u16        num_iotm_reqs;	/*  number of TM IO reqs	*/
-	u16        num_tsktm_reqs;	/*  TM task management requests*/
-	u16        num_fcxp_reqs;	/*  unassisted FC exchanges	*/
-	u16        num_uf_bufs;	/*  unsolicited recv buffers	*/
-	u8	   num_cqs;
-	u8         fw_tick_res;    /*!< FW clock resolution in ms */
-	u8         rsvd[4];
-
-};
-
-struct bfa_iocfc_drvcfg_s {
-	u16        num_reqq_elems;	/*  number of req queue elements */
-	u16        num_rspq_elems;	/*  number of rsp queue elements */
-	u16        num_sgpgs;	/*  number of total SG pages	  */
-	u16        num_sboot_tgts;	/*  number of SAN boot targets	  */
-	u16        num_sboot_luns;	/*  number of SAN boot luns	  */
-	u16	    ioc_recover;	/*  IOC recovery mode		  */
-	u16	    min_cfg;	/*  minimum configuration	  */
-	u16        path_tov;	/*  device path timeout	  */
-	bfa_boolean_t   delay_comp; /*  delay completion of
-							failed inflight IOs */
-	u32		rsvd;
-};
-/**
- * IOC configuration
- */
-struct bfa_iocfc_cfg_s {
-	struct bfa_iocfc_fwcfg_s	fwcfg;	/*  firmware side config */
-	struct bfa_iocfc_drvcfg_s	drvcfg;	/*  driver side config	  */
-};
-
-/**
- * IOC firmware IO stats
- */
-struct bfa_fw_io_stats_s {
-	u32	host_abort;		/*  IO aborted by host driver*/
-	u32	host_cleanup;		/*  IO clean up by host driver */
-
-	u32	fw_io_timeout;		/*  IOs timedout */
-	u32	fw_frm_parse;		/*  frame parsed by f/w */
-	u32	fw_frm_data;		/*  fcp_data frame parsed by f/w */
-	u32	fw_frm_rsp;		/*  fcp_rsp frame parsed by f/w */
-	u32	fw_frm_xfer_rdy;	/*  xfer_rdy frame parsed by f/w */
-	u32	fw_frm_bls_acc;		/*  BLS ACC  frame parsed by f/w */
-	u32	fw_frm_tgt_abort;	/*  target ABTS parsed by f/w */
-	u32	fw_frm_unknown;		/*  unknown parsed by f/w */
-	u32	fw_data_dma;		/*  f/w DMA'ed the data frame */
-	u32	fw_frm_drop;		/*  f/w drop the frame */
-
-	u32	rec_timeout;		/*  FW rec timed out */
-	u32	error_rec;			/*  FW sending rec on
-							* an error condition*/
-	u32	wait_for_si;		/*  FW wait for SI */
-	u32	rec_rsp_inval;		/*  REC rsp invalid */
-	u32	seqr_io_abort;		/*  target does not know cmd so abort */
-	u32	seqr_io_retry;		/*  SEQR failed so retry IO */
-
-	u32	itn_cisc_upd_rsp;	/*  ITN cisc updated on fcp_rsp */
-	u32	itn_cisc_upd_data;	/*  ITN cisc updated on fcp_data */
-	u32	itn_cisc_upd_xfer_rdy;	/*  ITN cisc updated on fcp_data */
-
-	u32	fcp_data_lost;		/*  fcp data lost */
-
-	u32	ro_set_in_xfer_rdy;	/*  Target set RO in Xfer_rdy frame */
-	u32	xfer_rdy_ooo_err;	/*  Out of order Xfer_rdy received */
-	u32	xfer_rdy_unknown_err;	/*  unknown error in xfer_rdy frame */
-
-	u32	io_abort_timeout;	/*  ABTS timedout  */
-	u32	sler_initiated;		/*  SLER initiated */
-
-	u32	unexp_fcp_rsp;		/*  fcp response in wrong state */
-
-	u32	fcp_rsp_under_run;	/*  fcp rsp IO underrun */
-	u32        fcp_rsp_under_run_wr;   /*  fcp rsp IO underrun for write */
-	u32	fcp_rsp_under_run_err;	/*  fcp rsp IO underrun error */
-	u32        fcp_rsp_resid_inval;    /*  invalid residue */
-	u32	fcp_rsp_over_run;	/*  fcp rsp IO overrun */
-	u32	fcp_rsp_over_run_err;	/*  fcp rsp IO overrun error */
-	u32	fcp_rsp_proto_err;	/*  protocol error in fcp rsp */
-	u32	fcp_rsp_sense_err;	/*  error in sense info in fcp rsp */
-	u32	fcp_conf_req;		/*  FCP conf requested */
-
-	u32	tgt_aborted_io;		/*  target initiated abort */
-
-	u32	ioh_edtov_timeout_event;/*  IOH edtov timer popped */
-	u32	ioh_fcp_rsp_excp_event;	/*  IOH FCP_RSP exception */
-	u32	ioh_fcp_conf_event;	/*  IOH FCP_CONF */
-	u32	ioh_mult_frm_rsp_event;	/*  IOH multi_frame FCP_RSP */
-	u32	ioh_hit_class2_event;	/*  IOH hit class2 */
-	u32	ioh_miss_other_event;	/*  IOH miss other */
-	u32	ioh_seq_cnt_err_event;	/*  IOH seq cnt error */
-	u32	ioh_len_err_event;		/*  IOH len error - fcp_dl !=
-							* bytes xfered */
-	u32	ioh_seq_len_err_event;	/*  IOH seq len error */
-	u32	ioh_data_oor_event;	/*  Data out of range */
-	u32	ioh_ro_ooo_event;	/*  Relative offset out of range */
-	u32	ioh_cpu_owned_event;	/*  IOH hit -iost owned by f/w */
-	u32	ioh_unexp_frame_event;	/*  unexpected frame recieved
-						 *   count */
-	u32	ioh_err_int;		/*  IOH error int during data-phase
-						 *   for scsi write
-						 */
-};
-
-/**
- * IOC port firmware stats
- */
-
-struct bfa_fw_port_fpg_stats_s {
-    u32    intr_evt;
-    u32    intr;
-    u32    intr_excess;
-    u32    intr_cause0;
-    u32    intr_other;
-    u32    intr_other_ign;
-    u32    sig_lost;
-    u32    sig_regained;
-    u32    sync_lost;
-    u32    sync_to;
-    u32    sync_regained;
-    u32    div2_overflow;
-    u32    div2_underflow;
-    u32    efifo_overflow;
-    u32    efifo_underflow;
-    u32    idle_rx;
-    u32    lrr_rx;
-    u32    lr_rx;
-    u32    ols_rx;
-    u32    nos_rx;
-    u32    lip_rx;
-    u32    arbf0_rx;
-    u32    arb_rx;
-    u32    mrk_rx;
-    u32    const_mrk_rx;
-    u32    prim_unknown;
-};
-
-
-struct bfa_fw_port_lksm_stats_s {
-    u32    hwsm_success;       /*  hwsm state machine success          */
-    u32    hwsm_fails;         /*  hwsm fails                          */
-    u32    hwsm_wdtov;         /*  hwsm timed out                      */
-    u32    swsm_success;       /*  swsm success                        */
-    u32    swsm_fails;         /*  swsm fails                          */
-    u32    swsm_wdtov;         /*  swsm timed out                      */
-    u32    busybufs;           /*  link init failed due to busybuf     */
-    u32    buf_waits;          /*  bufwait state entries               */
-    u32    link_fails;         /*  link failures                       */
-    u32    psp_errors;         /*  primitive sequence protocol errors  */
-    u32    lr_unexp;           /*  No. of times LR rx-ed unexpectedly  */
-    u32    lrr_unexp;          /*  No. of times LRR rx-ed unexpectedly */
-    u32    lr_tx;              /*  No. of times LR tx started          */
-    u32    lrr_tx;             /*  No. of times LRR tx started         */
-    u32    ols_tx;             /*  No. of times OLS tx started         */
-    u32    nos_tx;             /*  No. of times NOS tx started         */
-    u32    hwsm_lrr_rx;        /*  No. of times LRR rx-ed by HWSM      */
-    u32    hwsm_lr_rx;         /* No. of times LR rx-ed by HWSM        */
-};
-
-
-struct bfa_fw_port_snsm_stats_s {
-    u32    hwsm_success;       /*  Successful hwsm terminations        */
-    u32    hwsm_fails;         /*  hwsm fail count                     */
-    u32    hwsm_wdtov;         /*  hwsm timed out                      */
-    u32    swsm_success;       /*  swsm success                        */
-    u32    swsm_wdtov;         /*  swsm timed out                      */
-    u32    error_resets;       /*  error resets initiated by upsm      */
-    u32    sync_lost;          /*  Sync loss count                     */
-    u32    sig_lost;           /*  Signal loss count                   */
-};
-
-
-struct bfa_fw_port_physm_stats_s {
-    u32    module_inserts;     /*  Module insert count                 */
-    u32    module_xtracts;     /*  Module extracts count               */
-    u32    module_invalids;    /*  Invalid module inserted count       */
-    u32    module_read_ign;    /*  Module validation status ignored    */
-    u32    laser_faults;       /*  Laser fault count                   */
-    u32    rsvd;
-};
-
-
-struct bfa_fw_fip_stats_s {
-    u32    vlan_req;           /*  vlan discovery requests             */
-    u32    vlan_notify;        /*  vlan notifications                  */
-    u32    vlan_err;           /*  vlan response error                 */
-    u32    vlan_timeouts;      /*  vlan disvoery timeouts              */
-    u32    vlan_invalids;      /*  invalid vlan in discovery advert.   */
-    u32    disc_req;           /*  Discovery solicit requests          */
-    u32    disc_rsp;           /*  Discovery solicit response          */
-    u32    disc_err;           /*  Discovery advt. parse errors        */
-    u32    disc_unsol;         /*  Discovery unsolicited               */
-    u32    disc_timeouts;      /*  Discovery timeouts                  */
-    u32    disc_fcf_unavail;   /*  Discovery FCF Not Avail.            */
-    u32    linksvc_unsupp;     /*  Unsupported link service req        */
-    u32    linksvc_err;        /*  Parse error in link service req     */
-    u32    logo_req;           /*  FIP logos received	               */
-    u32    clrvlink_req;       /*  Clear virtual link req              */
-    u32    op_unsupp;          /*  Unsupported FIP operation           */
-    u32    untagged;           /*  Untagged frames (ignored)           */
-    u32	   invalid_version;    /*!< Invalid FIP version           */
-};
-
-
-struct bfa_fw_lps_stats_s {
-    u32    mac_invalids;       /*  Invalid mac assigned                */
-    u32    rsvd;
-};
-
-
-struct bfa_fw_fcoe_stats_s {
-    u32    cee_linkups;        /*  CEE link up count                   */
-    u32    cee_linkdns;        /*  CEE link down count                 */
-    u32    fip_linkups;        /*  FIP link up count                   */
-    u32    fip_linkdns;        /*  FIP link up count                   */
-    u32    fip_fails;          /*  FIP fail count                      */
-    u32    mac_invalids;       /*  Invalid mac assigned                */
-};
-
-/**
- * IOC firmware FCoE port stats
- */
-struct bfa_fw_fcoe_port_stats_s {
-    struct bfa_fw_fcoe_stats_s  fcoe_stats;
-    struct bfa_fw_fip_stats_s   fip_stats;
-};
-
-/**
- * IOC firmware FC port stats
- */
-struct bfa_fw_fc_port_stats_s {
-	struct bfa_fw_port_fpg_stats_s		fpg_stats;
-	struct bfa_fw_port_physm_stats_s	physm_stats;
-	struct bfa_fw_port_snsm_stats_s		snsm_stats;
-	struct bfa_fw_port_lksm_stats_s		lksm_stats;
-};
-
-/**
- * IOC firmware FC port stats
- */
-union bfa_fw_port_stats_s {
-	struct bfa_fw_fc_port_stats_s	fc_stats;
-	struct bfa_fw_fcoe_port_stats_s	fcoe_stats;
-};
-
-/**
- * IOC firmware stats
- */
-struct bfa_fw_stats_s {
-	struct bfa_fw_ioc_stats_s	ioc_stats;
-	struct bfa_fw_io_stats_s	io_stats;
-	union  bfa_fw_port_stats_s	port_stats;
-};
-
-/**
- * IOC statistics
- */
-struct bfa_iocfc_stats_s {
-	struct bfa_fw_stats_s 	fw_stats;	/*  firmware IOC stats      */
-};
-
-/**
- * IOC attributes returned in queries
- */
-struct bfa_iocfc_attr_s {
-	struct bfa_iocfc_cfg_s		config;		/*  IOCFC config   */
-	struct bfa_iocfc_intr_attr_s	intr_attr;	/*  interrupt attr */
-};
-
-#define BFA_IOCFC_PATHTOV_MAX	60
-#define BFA_IOCFC_QDEPTH_MAX	2000
-
-#endif /* __BFA_DEFS_IOC_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h b/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h
deleted file mode 100644
index 7cb63ea..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_IPFC_H__
-#define __BFA_DEFS_IPFC_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-
-/**
- * FCS ip remote port states
- */
-enum bfa_iprp_state {
-	BFA_IPRP_UNINIT  = 0,	/*  PORT is not yet initialized */
-	BFA_IPRP_ONLINE  = 1,	/*  process login is complete */
-	BFA_IPRP_OFFLINE = 2,	/*  iprp is offline */
-};
-
-/**
- * FCS remote port statistics
- */
-struct bfa_iprp_stats_s {
-	u32        offlines;
-	u32        onlines;
-	u32        rscns;
-	u32        plogis;
-	u32        logos;
-	u32        plogi_timeouts;
-	u32        plogi_rejects;
-};
-
-/**
- * FCS iprp attribute returned in queries
- */
-struct bfa_iprp_attr_s {
-	enum bfa_iprp_state state;
-};
-
-struct bfa_ipfc_stats_s {
-	u32 arp_sent;
-	u32 arp_recv;
-	u32 arp_reply_sent;
-	u32 arp_reply_recv;
-	u32 farp_sent;
-	u32 farp_recv;
-	u32 farp_reply_sent;
-	u32 farp_reply_recv;
-	u32 farp_reject_sent;
-	u32 farp_reject_recv;
-};
-
-struct bfa_ipfc_attr_s {
-	bfa_boolean_t enabled;
-};
-
-#endif /* __BFA_DEFS_IPFC_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h b/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h
deleted file mode 100644
index d77788b..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_ITNIM_H__
-#define __BFA_DEFS_ITNIM_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-
-/**
- * FCS itnim states
- */
-enum bfa_itnim_state {
-	BFA_ITNIM_OFFLINE 	= 0,	/*  offline */
-	BFA_ITNIM_PRLI_SEND 	= 1,	/*  prli send */
-	BFA_ITNIM_PRLI_SENT 	= 2,	/*  prli sent */
-	BFA_ITNIM_PRLI_RETRY 	= 3,	/*  prli retry */
-	BFA_ITNIM_HCB_ONLINE 	= 4,	/*  online callback */
-	BFA_ITNIM_ONLINE 	= 5,	/*  online */
-	BFA_ITNIM_HCB_OFFLINE 	= 6,	/*  offline callback */
-	BFA_ITNIM_INITIATIOR 	= 7,	/*  initiator */
-};
-
-struct bfa_itnim_latency_s {
-	u32	min;
-	u32	max;
-	u32	count;
-	u32	clock_res;
-	u32	avg;
-	u32	rsvd;
-};
-
-struct bfa_itnim_hal_stats_s {
-	u32	onlines;	/*  ITN nexus onlines (PRLI done) */
-	u32	offlines;	/*  ITN Nexus offlines 	*/
-	u32	creates;	/*  ITN create requests 	*/
-	u32	deletes;	/*  ITN delete requests 	*/
-	u32	create_comps;	/*  ITN create completions 	*/
-	u32	delete_comps;	/*  ITN delete completions 	*/
-	u32	sler_events;	/*  SLER (sequence level error
-					 * recovery) events */
-	u32	ioc_disabled;	/*  Num IOC disables		*/
-	u32	cleanup_comps;	/*  ITN cleanup completions */
-	u32	tm_cmnds;	/*  task management(TM) cmnds sent */
-	u32	tm_fw_rsps;	/*  TM cmds firmware responses */
-	u32	tm_success;	/*  TM successes */
-	u32	tm_failures;	/*  TM failures */
-	u32	tm_io_comps;	/*  TM IO completions */
-	u32	tm_qresumes;	/*  TM queue resumes (after waiting
-					 * for resources)
-					 */
-	u32	tm_iocdowns;	/*  TM cmnds affected by IOC down */
-	u32	tm_cleanups;	/*  TM cleanups */
-	u32	tm_cleanup_comps;
-					/*  TM cleanup completions */
-	u32	ios;		/*  IO requests */
-	u32	io_comps;	/*  IO completions */
-	u64	input_reqs;	/*  INPUT requests */
-	u64	output_reqs;	/*  OUTPUT requests */
-};
-
-/**
- * FCS remote port statistics
- */
-struct bfa_itnim_stats_s {
-	u32        onlines;	/*  num rport online */
-	u32        offlines;	/*  num rport offline */
-	u32        prli_sent;	/*  num prli sent out */
-	u32        fcxp_alloc_wait;/*  num fcxp alloc waits */
-	u32        prli_rsp_err;	/*  num prli rsp errors */
-	u32        prli_rsp_acc;	/*  num prli rsp accepts */
-	u32        initiator;	/*  rport is an initiator */
-	u32        prli_rsp_parse_err;	/*  prli rsp parsing errors */
-	u32        prli_rsp_rjt;	/*  num prli rsp rejects */
-	u32        timeout;	/*  num timeouts detected */
-	u32        sler;		/*  num sler notification from BFA */
-	u32	rsvd;
-	struct bfa_itnim_hal_stats_s	hal_stats;
-};
-
-/**
- * FCS itnim attributes returned in queries
- */
-struct bfa_itnim_attr_s {
-	enum bfa_itnim_state state; /*  FCS itnim state        */
-	u8 retry;		/*  data retransmision support */
-	u8	task_retry_id;  /*  task retry ident support   */
-	u8 rec_support;    /*  REC supported              */
-	u8 conf_comp;      /*  confirmed completion supp  */
-	struct bfa_itnim_latency_s  io_latency; /* IO latency  */
-};
-
-/**
- * BFA ITNIM events.
- * Arguments below are in BFAL context from Mgmt
- * BFA_ITNIM_AEN_NEW:       [in]: None  [out]: vf_id, lpwwn
- * BFA_ITNIM_AEN_DELETE:    [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- *				  [out]: vf_id, ppwwn, lpwwn, rpwwn
- * BFA_ITNIM_AEN_ONLINE:    [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- *				  [out]: vf_id, ppwwn, lpwwn, rpwwn
- * BFA_ITNIM_AEN_OFFLINE:   [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- *				  [out]: vf_id, ppwwn, lpwwn, rpwwn
- * BFA_ITNIM_AEN_DISCONNECT:[in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- *				  [out]: vf_id, ppwwn, lpwwn, rpwwn
- */
-enum bfa_itnim_aen_event {
-	BFA_ITNIM_AEN_ONLINE 	= 1,	/*  Target online */
-	BFA_ITNIM_AEN_OFFLINE 	= 2,	/*  Target offline */
-	BFA_ITNIM_AEN_DISCONNECT = 3,	/*  Target disconnected */
-};
-
-/**
- * BFA ITNIM event data structure.
- */
-struct bfa_itnim_aen_data_s {
-	u16        vf_id;	/*  vf_id of the IT nexus */
-	u16        rsvd[3];
-	wwn_t           ppwwn;	/*  WWN of its physical port */
-	wwn_t           lpwwn;	/*  WWN of logical port */
-	wwn_t           rpwwn;	/*  WWN of remote(target) port */
-};
-
-#endif /* __BFA_DEFS_ITNIM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_led.h b/drivers/scsi/bfa/include/defs/bfa_defs_led.h
deleted file mode 100644
index 6203927..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_led.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_LED_H__
-#define __BFA_DEFS_LED_H__
-
-#define	BFA_LED_MAX_NUM		3
-
-enum bfa_led_op {
-	BFA_LED_OFF   = 0,
-	BFA_LED_ON    = 1,
-	BFA_LED_FLICK = 2,
-	BFA_LED_BLINK = 3,
-};
-
-enum bfa_led_color {
-	BFA_LED_GREEN = 0,
-	BFA_LED_AMBER = 1,
-};
-
-#endif /* __BFA_DEFS_LED_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_lport.h b/drivers/scsi/bfa/include/defs/bfa_defs_lport.h
deleted file mode 100644
index 0952a13..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_lport.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_LPORT_H__
-#define __BFA_DEFS_LPORT_H__
-
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_port.h>
-
-/**
- * BFA AEN logical port events.
- * Arguments below are in BFAL context from Mgmt
- * BFA_LPORT_AEN_NEW:       [in]: None         [out]: vf_id, ppwwn, lpwwn, roles
- * BFA_LPORT_AEN_DELETE:    [in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_ONLINE:    [in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_OFFLINE:   [in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_DISCONNECT:[in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NEW_PROP:  [in]: None         [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_DELETE_PROP:     [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NEW_STANDARD:    [in]: None   [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_DELETE_STANDARD: [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NPIV_DUP_WWN:    [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NPIV_FABRIC_MAX: [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NPIV_UNKNOWN:    [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
- */
-enum bfa_lport_aen_event {
-	BFA_LPORT_AEN_NEW	= 1,	/*  LPort created event */
-	BFA_LPORT_AEN_DELETE	= 2,	/*  LPort deleted event */
-	BFA_LPORT_AEN_ONLINE	= 3,	/*  LPort online event */
-	BFA_LPORT_AEN_OFFLINE	= 4,	/*  LPort offline event */
-	BFA_LPORT_AEN_DISCONNECT = 5,	/*  LPort disconnect event */
-	BFA_LPORT_AEN_NEW_PROP	= 6,	/*  VPort created event */
-	BFA_LPORT_AEN_DELETE_PROP = 7,	/*  VPort deleted event */
-	BFA_LPORT_AEN_NEW_STANDARD = 8,	/*  VPort created event */
-	BFA_LPORT_AEN_DELETE_STANDARD = 9,  /*  VPort deleted event */
-	BFA_LPORT_AEN_NPIV_DUP_WWN = 10,    /*  VPort configured with
-					     *   duplicate WWN event
-						 */
-	BFA_LPORT_AEN_NPIV_FABRIC_MAX = 11, /*  Max NPIV in fabric/fport */
-	BFA_LPORT_AEN_NPIV_UNKNOWN = 12, /*  Unknown NPIV Error code event */
-};
-
-/**
- * BFA AEN event data structure
- */
-struct bfa_lport_aen_data_s {
-	u16        vf_id;	/*  vf_id of this logical port */
-	s16         roles;  /*  Logical port mode,IM/TM/IP etc */
-	u32        rsvd;
-	wwn_t           ppwwn;	/*  WWN of its physical port */
-	wwn_t           lpwwn;	/*  WWN of this logical port */
-};
-
-#endif /* __BFA_DEFS_LPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h b/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h
deleted file mode 100644
index d22fb79..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_MFG_H__
-#define __BFA_DEFS_MFG_H__
-
-#include <bfa_os_inc.h>
-
-/**
- * Manufacturing block version
- */
-#define BFA_MFG_VERSION				2
-
-/**
- * Manufacturing block encrypted version
- */
-#define BFA_MFG_ENC_VER				2
-
-/**
- * Manufacturing block version 1 length
- */
-#define BFA_MFG_VER1_LEN			128
-
-/**
- * Manufacturing block header length
- */
-#define BFA_MFG_HDR_LEN				4
-
-/**
- * Checksum size
- */
-#define BFA_MFG_CHKSUM_SIZE			16
-
-/**
- * Manufacturing block format
- */
-#define BFA_MFG_SERIALNUM_SIZE			11
-#define BFA_MFG_PARTNUM_SIZE			14
-#define BFA_MFG_SUPPLIER_ID_SIZE		10
-#define BFA_MFG_SUPPLIER_PARTNUM_SIZE		20
-#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE		20
-#define BFA_MFG_SUPPLIER_REVISION_SIZE		4
-#define STRSZ(_n)	(((_n) + 4) & ~3)
-
-/**
- * Manufacturing card type
- */
-enum {
-	BFA_MFG_TYPE_CB_MAX  = 825,      /*  Crossbow card type max	*/
-	BFA_MFG_TYPE_FC8P2   = 825,      /*  8G 2port FC card		*/
-	BFA_MFG_TYPE_FC8P1   = 815,      /*  8G 1port FC card		*/
-	BFA_MFG_TYPE_FC4P2   = 425,      /*  4G 2port FC card		*/
-	BFA_MFG_TYPE_FC4P1   = 415,      /*  4G 1port FC card		*/
-	BFA_MFG_TYPE_CNA10P2 = 1020,     /*  10G 2port CNA card	*/
-	BFA_MFG_TYPE_CNA10P1 = 1010,     /*  10G 1port CNA card	*/
-	BFA_MFG_TYPE_JAYHAWK = 804,      /*  Jayhawk mezz card */
-	BFA_MFG_TYPE_WANCHESE = 1007,    /*  Wanchese mezz card */
-	BFA_MFG_TYPE_INVALID = 0,        /*  Invalid card type */
-};
-
-#pragma pack(1)
-
-/**
- * Card type to port number conversion
- */
-#define bfa_mfg_type2port_num(card_type) (((card_type) / 10) % 10)
-
-/**
- * Check if Mezz card
- */
-#define bfa_mfg_is_mezz(type) (( \
-	(type) == BFA_MFG_TYPE_JAYHAWK || \
-	(type) == BFA_MFG_TYPE_WANCHESE))
-
-/**
- * Check if card type valid
- */
-#define bfa_mfg_is_card_type_valid(type) (( \
-	(type) == BFA_MFG_TYPE_FC8P2 || \
-	(type) == BFA_MFG_TYPE_FC8P1 || \
-	(type) == BFA_MFG_TYPE_FC4P2 || \
-	(type) == BFA_MFG_TYPE_FC4P1 || \
-	(type) == BFA_MFG_TYPE_CNA10P2 || \
-	(type) == BFA_MFG_TYPE_CNA10P1 || \
-	bfa_mfg_is_mezz(type)))
-
-/**
- * All numerical fields are in big-endian format.
- */
-struct bfa_mfg_block_s {
-};
-
-/**
- * VPD data length
- */
-#define BFA_MFG_VPD_LEN		512
-
-#define BFA_MFG_VPD_PCI_HDR_OFF		137
-#define BFA_MFG_VPD_PCI_VER_MASK	0x07	/*  version mask 3 bits */
-#define BFA_MFG_VPD_PCI_VDR_MASK	0xf8	/*  vendor mask 5 bits */
-
-/**
- * VPD vendor tag
- */
-enum {
-	BFA_MFG_VPD_UNKNOWN	= 0,     /*  vendor unknown 		*/
-	BFA_MFG_VPD_IBM 	= 1,     /*  vendor IBM 		*/
-	BFA_MFG_VPD_HP  	= 2,     /*  vendor HP  		*/
-	BFA_MFG_VPD_DELL        = 3,	 /*  vendor DELL                */
-	BFA_MFG_VPD_PCI_IBM 	= 0x08,  /*  PCI VPD IBM     		*/
-	BFA_MFG_VPD_PCI_HP  	= 0x10,  /*  PCI VPD HP			*/
-	BFA_MFG_VPD_PCI_DELL    = 0x20,  /*  PCI VPD DELL           	*/
-	BFA_MFG_VPD_PCI_BRCD 	= 0xf8,  /*  PCI VPD Brocade 		*/
-};
-
-/**
- * All numerical fields are in big-endian format.
- */
-struct bfa_mfg_vpd_s {
-	u8		version;	/*  vpd data version */
-	u8		vpd_sig[3];	/*  characters 'V', 'P', 'D' */
-	u8		chksum;		/*  u8 checksum */
-	u8		vendor;		/*  vendor */
-	u8 	len;		/*  vpd data length excluding header */
-	u8 	rsv;
-	u8		data[BFA_MFG_VPD_LEN];	/*  vpd data */
-};
-
-#pragma pack()
-
-#endif /* __BFA_DEFS_MFG_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pci.h b/drivers/scsi/bfa/include/defs/bfa_defs_pci.h
deleted file mode 100644
index ea7d89b..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pci.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_PCI_H__
-#define __BFA_DEFS_PCI_H__
-
-/**
- * PCI device and vendor ID information
- */
-enum {
-	BFA_PCI_VENDOR_ID_BROCADE	= 0x1657,
-	BFA_PCI_DEVICE_ID_FC_8G2P	= 0x13,
-	BFA_PCI_DEVICE_ID_FC_8G1P	= 0x17,
-	BFA_PCI_DEVICE_ID_CT		= 0x14,
-	BFA_PCI_DEVICE_ID_CT_FC         = 0x21,
-};
-
-#define bfa_asic_id_ct(devid)                   \
-	((devid) == BFA_PCI_DEVICE_ID_CT ||     \
-	 (devid) == BFA_PCI_DEVICE_ID_CT_FC)
-
-/**
- * PCI sub-system device and vendor ID information
- */
-enum {
-	BFA_PCI_FCOE_SSDEVICE_ID	= 0x14,
-};
-
-/**
- * Maximum number of device address ranges mapped through different BAR(s)
- */
-#define BFA_PCI_ACCESS_RANGES 1
-
-#endif /* __BFA_DEFS_PCI_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pm.h b/drivers/scsi/bfa/include/defs/bfa_defs_pm.h
deleted file mode 100644
index e8d6d95..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pm.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_PM_H__
-#define __BFA_DEFS_PM_H__
-
-#include <bfa_os_inc.h>
-
-/**
- * BFA power management device states
- */
-enum bfa_pm_ds {
-	BFA_PM_DS_D0 = 0,	/*  full power mode */
-	BFA_PM_DS_D1 = 1,	/*  power save state 1 */
-	BFA_PM_DS_D2 = 2,	/*  power save state 2 */
-	BFA_PM_DS_D3 = 3,	/*  power off state */
-};
-
-#endif /* __BFA_DEFS_PM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pom.h b/drivers/scsi/bfa/include/defs/bfa_defs_pom.h
deleted file mode 100644
index d9fa278..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pom.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_POM_H__
-#define __BFA_DEFS_POM_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_types.h>
-
-/**
- * POM health status levels for each attributes.
- */
-enum bfa_pom_entry_health {
-	BFA_POM_HEALTH_NOINFO  = 1,	/*  no information */
-	BFA_POM_HEALTH_NORMAL  = 2,	/*  health is normal */
-	BFA_POM_HEALTH_WARNING = 3,	/*  warning level */
-	BFA_POM_HEALTH_ALARM   = 4,	/*  alarming level */
-};
-
-/**
- * Reading of temperature/voltage/current/power
- */
-struct bfa_pom_entry_s {
-	enum bfa_pom_entry_health health;	/*  POM entry health */
-	u32        curr_value;	/*  current value */
-	u32        thr_warn_high;	/*  threshold warning high */
-	u32        thr_warn_low;	/*  threshold warning low */
-	u32        thr_alarm_low;	/*  threshold alaram low */
-	u32        thr_alarm_high;	/*  threshold alarm high */
-};
-
-/**
- * POM attributes
- */
-struct bfa_pom_attr_s {
-	struct bfa_pom_entry_s temperature;	/*  centigrade */
-	struct bfa_pom_entry_s voltage;	/*  volts */
-	struct bfa_pom_entry_s curr;	/*  milli amps */
-	struct bfa_pom_entry_s txpower;	/*  micro watts */
-	struct bfa_pom_entry_s rxpower;	/*  micro watts */
-};
-
-#endif /* __BFA_DEFS_POM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_port.h b/drivers/scsi/bfa/include/defs/bfa_defs_port.h
deleted file mode 100644
index ebdf0d1..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_port.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_PORT_H__
-#define __BFA_DEFS_PORT_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_ioc.h>
-
-#define BFA_FCS_FABRIC_IPADDR_SZ  16
-
-/**
- * symbolic names for base port/virtual port
- */
-#define BFA_SYMNAME_MAXLEN	128	/* vmware/windows uses 128 bytes */
-struct bfa_port_symname_s {
-	char            symname[BFA_SYMNAME_MAXLEN];
-};
-
-/**
-* Roles of FCS port:
- *     - FCP IM and FCP TM roles cannot be enabled together for a FCS port
- *     - Create multiple ports if both IM and TM functions required.
- *     - Atleast one role must be specified.
- */
-enum bfa_port_role {
-	BFA_PORT_ROLE_FCP_IM 	= 0x01,	/*  FCP initiator role */
-	BFA_PORT_ROLE_FCP_TM 	= 0x02,	/*  FCP target role */
-	BFA_PORT_ROLE_FCP_IPFC 	= 0x04,	/*  IP over FC role */
-	BFA_PORT_ROLE_FCP_MAX 	= BFA_PORT_ROLE_FCP_IPFC | BFA_PORT_ROLE_FCP_IM
-};
-
-/**
- * FCS port configuration.
- */
-struct bfa_port_cfg_s {
-	wwn_t               pwwn;       /*  port wwn */
-	wwn_t               nwwn;       /*  node wwn */
-	struct bfa_port_symname_s  sym_name;   /*  vm port symbolic name */
-	bfa_boolean_t       preboot_vp;  /* vport created from PBC */
-	enum bfa_port_role     roles;      /*  FCS port roles */
-	u8             tag[16];	/*  opaque tag from application */
-};
-
-/**
- * FCS port states
- */
-enum bfa_port_state {
-	BFA_PORT_UNINIT  = 0,	/*  PORT is not yet initialized */
-	BFA_PORT_FDISC   = 1,	/*  FDISC is in progress */
-	BFA_PORT_ONLINE  = 2,	/*  login to fabric is complete */
-	BFA_PORT_OFFLINE = 3,	/*  No login to fabric */
-};
-
-/**
- * FCS port type. Required for VmWare.
- */
-enum bfa_port_type {
-	BFA_PORT_TYPE_PHYSICAL = 0,
-	BFA_PORT_TYPE_VIRTUAL,
-};
-
-/**
- * FCS port offline reason. Required for VmWare.
- */
-enum bfa_port_offline_reason {
-	BFA_PORT_OFFLINE_UNKNOWN = 0,
-	BFA_PORT_OFFLINE_LINKDOWN,
-	BFA_PORT_OFFLINE_FAB_UNSUPPORTED,	/*  NPIV not supported by the
-						 *    fabric */
-	BFA_PORT_OFFLINE_FAB_NORESOURCES,
-	BFA_PORT_OFFLINE_FAB_LOGOUT,
-};
-
-/**
- * FCS lport info. Required for VmWare.
- */
-struct bfa_port_info_s {
-	u8         port_type;	/* bfa_port_type_t : physical or
-					 * virtual */
-	u8         port_state;	/* one of bfa_port_state values */
-	u8         offline_reason;	/* one of bfa_port_offline_reason_t
-					 * values */
-	wwn_t           port_wwn;
-	wwn_t           node_wwn;
-
-	/*
-	 * following 4 feilds are valid for Physical Ports only
-	 */
-	u32        max_vports_supp;	/* Max supported vports */
-	u32        num_vports_inuse;	/* Num of in use vports */
-	u32        max_rports_supp;	/* Max supported rports */
-	u32        num_rports_inuse;	/* Num of doscovered rports */
-
-};
-
-/**
- * FCS port statistics
- */
-struct bfa_port_stats_s {
-	u32        ns_plogi_sent;
-	u32        ns_plogi_rsp_err;
-	u32        ns_plogi_acc_err;
-	u32        ns_plogi_accepts;
-	u32        ns_rejects;	/* NS command rejects */
-	u32        ns_plogi_unknown_rsp;
-	u32        ns_plogi_alloc_wait;
-
-	u32        ns_retries;	/* NS command retries */
-	u32        ns_timeouts;	/* NS command timeouts */
-
-	u32        ns_rspnid_sent;
-	u32        ns_rspnid_accepts;
-	u32        ns_rspnid_rsp_err;
-	u32        ns_rspnid_rejects;
-	u32        ns_rspnid_alloc_wait;
-
-	u32        ns_rftid_sent;
-	u32        ns_rftid_accepts;
-	u32        ns_rftid_rsp_err;
-	u32        ns_rftid_rejects;
-	u32        ns_rftid_alloc_wait;
-
-	u32	ns_rffid_sent;
-	u32	ns_rffid_accepts;
-	u32	ns_rffid_rsp_err;
-	u32	ns_rffid_rejects;
-	u32	ns_rffid_alloc_wait;
-
-	u32        ns_gidft_sent;
-	u32        ns_gidft_accepts;
-	u32        ns_gidft_rsp_err;
-	u32        ns_gidft_rejects;
-	u32        ns_gidft_unknown_rsp;
-	u32        ns_gidft_alloc_wait;
-
-	/*
-	 * Mgmt Server stats
-	 */
-	u32        ms_retries;	/* MS command retries */
-	u32        ms_timeouts;	/* MS command timeouts */
-	u32        ms_plogi_sent;
-	u32        ms_plogi_rsp_err;
-	u32        ms_plogi_acc_err;
-	u32        ms_plogi_accepts;
-	u32        ms_rejects;	/* MS command rejects */
-	u32        ms_plogi_unknown_rsp;
-	u32        ms_plogi_alloc_wait;
-
-	u32        num_rscn;	/* Num of RSCN received */
-	u32        num_portid_rscn;/* Num portid format RSCN
-								* received */
-
-	u32	uf_recvs; 	/* unsolicited recv frames      */
-	u32	uf_recv_drops; 	/* dropped received frames	*/
-
-	u32	rsvd; 		/* padding for 64 bit alignment */
-};
-
-/**
- * BFA port attribute returned in queries
- */
-struct bfa_port_attr_s {
-	enum bfa_port_state state;		/*  port state */
-	u32         pid;		/*  port ID */
-	struct bfa_port_cfg_s   port_cfg;	/*  port configuration */
-	enum bfa_pport_type port_type;	/*  current topology */
-	u32         loopback;	/*  cable is externally looped back */
-	wwn_t		fabric_name; /*  attached switch's nwwn */
-	u8		fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; /*  attached
-							* fabric's ip addr */
-	struct mac_s    fpma_mac;	/*  Lport's FPMA Mac address */
-	u16     authfail;		/*  auth failed state */
-};
-
-/**
- * BFA physical port Level events
- * Arguments below are in BFAL context from Mgmt
- * BFA_PORT_AEN_ONLINE:     [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_OFFLINE:    [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_RLIR:       [in]: None	[out]: pwwn, rlir_data, rlir_len
- * BFA_PORT_AEN_SFP_INSERT: [in]: pwwn	[out]: port_id, pwwn
- * BFA_PORT_AEN_SFP_REMOVE: [in]: pwwn	[out]: port_id, pwwn
- * BFA_PORT_AEN_SFP_POM:    [in]: pwwn	[out]: level, port_id, pwwn
- * BFA_PORT_AEN_ENABLE:     [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_DISABLE:    [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_AUTH_ON:    [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_AUTH_OFF:   [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_DISCONNECT: [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_QOS_NEG:    [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_FABRIC_NAME_CHANGE: [in]: pwwn, [out]: pwwn, fwwn
- *
- */
-enum bfa_port_aen_event {
-	BFA_PORT_AEN_ONLINE     = 1,	/*  Physical Port online event */
-	BFA_PORT_AEN_OFFLINE    = 2,	/*  Physical Port offline event */
-	BFA_PORT_AEN_RLIR       = 3,	/*  RLIR event, not supported */
-	BFA_PORT_AEN_SFP_INSERT = 4,	/*  SFP inserted event */
-	BFA_PORT_AEN_SFP_REMOVE = 5,	/*  SFP removed event */
-	BFA_PORT_AEN_SFP_POM    = 6,	/*  SFP POM event */
-	BFA_PORT_AEN_ENABLE     = 7,	/*  Physical Port enable event */
-	BFA_PORT_AEN_DISABLE    = 8,	/*  Physical Port disable event */
-	BFA_PORT_AEN_AUTH_ON    = 9,	/*  Physical Port auth success event */
-	BFA_PORT_AEN_AUTH_OFF   = 10,	/*  Physical Port auth fail event */
-	BFA_PORT_AEN_DISCONNECT = 11,	/*  Physical Port disconnect event */
-	BFA_PORT_AEN_QOS_NEG    = 12,  	/*  Base Port QOS negotiation event */
-	BFA_PORT_AEN_FABRIC_NAME_CHANGE = 13, /*  Fabric Name/WWN change
-					       * event */
-	BFA_PORT_AEN_SFP_ACCESS_ERROR = 14, /*  SFP read error event */
-	BFA_PORT_AEN_SFP_UNSUPPORT = 15, /*  Unsupported SFP event */
-};
-
-enum bfa_port_aen_sfp_pom {
-	BFA_PORT_AEN_SFP_POM_GREEN = 1,	/*  Normal */
-	BFA_PORT_AEN_SFP_POM_AMBER = 2,	/*  Warning */
-	BFA_PORT_AEN_SFP_POM_RED   = 3,	/*  Critical */
-	BFA_PORT_AEN_SFP_POM_MAX   = BFA_PORT_AEN_SFP_POM_RED
-};
-
-struct bfa_port_aen_data_s {
-	wwn_t           pwwn;         /*  WWN of the physical port */
-	wwn_t           fwwn;         /*  WWN of the fabric port */
-	s32         phy_port_num; /*! For SFP related events */
-	s16         ioc_type;
-	s16         level;        /*  Only transitions will
-					* be informed */
-	struct mac_s    mac;          /*  MAC address of the ethernet port,
-					* applicable to CNA port only */
-	s16         rsvd;
-};
-
-#endif /* __BFA_DEFS_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h
deleted file mode 100644
index 2de67583..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_PPORT_H__
-#define __BFA_DEFS_PPORT_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/fc.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_qos.h>
-#include <cna/pstats/phyport_defs.h>
-
-/* Modify char* port_stt[] in bfal_port.c if a new state was added */
-enum bfa_pport_states {
-	BFA_PPORT_ST_UNINIT 		= 1,
-	BFA_PPORT_ST_ENABLING_QWAIT 	= 2,
-	BFA_PPORT_ST_ENABLING 		= 3,
-	BFA_PPORT_ST_LINKDOWN 		= 4,
-	BFA_PPORT_ST_LINKUP 		= 5,
-	BFA_PPORT_ST_DISABLING_QWAIT 	= 6,
-	BFA_PPORT_ST_DISABLING		= 7,
-	BFA_PPORT_ST_DISABLED 		= 8,
-	BFA_PPORT_ST_STOPPED 		= 9,
-	BFA_PPORT_ST_IOCDOWN 		= 10,
-	BFA_PPORT_ST_IOCDIS 		= 11,
-	BFA_PPORT_ST_FWMISMATCH		= 12,
-	BFA_PPORT_ST_PREBOOT_DISABLED   = 13,
-	BFA_PPORT_ST_MAX_STATE,
-};
-
-/**
- * 	Port speed settings. Each specific speed is a bit field. Use multiple
- *      bits to specify speeds to be selected for auto-negotiation.
- */
-enum bfa_pport_speed {
-	BFA_PPORT_SPEED_UNKNOWN = 0,
-	BFA_PPORT_SPEED_1GBPS 	= 1,
-	BFA_PPORT_SPEED_2GBPS 	= 2,
-	BFA_PPORT_SPEED_4GBPS 	= 4,
-	BFA_PPORT_SPEED_8GBPS 	= 8,
-	BFA_PPORT_SPEED_10GBPS 	= 10,
-	BFA_PPORT_SPEED_AUTO =
-		(BFA_PPORT_SPEED_1GBPS | BFA_PPORT_SPEED_2GBPS |
-		 BFA_PPORT_SPEED_4GBPS | BFA_PPORT_SPEED_8GBPS),
-};
-
-/**
- * 		Port operational type (in sync with SNIA port type).
- */
-enum bfa_pport_type {
-	BFA_PPORT_TYPE_UNKNOWN = 1,	/*  port type is unknown */
-	BFA_PPORT_TYPE_TRUNKED = 2,	/*  Trunked mode */
-	BFA_PPORT_TYPE_NPORT   = 5,	/*  P2P with switched fabric */
-	BFA_PPORT_TYPE_NLPORT  = 6,	/*  public loop */
-	BFA_PPORT_TYPE_LPORT   = 20,	/*  private loop */
-	BFA_PPORT_TYPE_P2P     = 21,	/*  P2P with no switched fabric */
-	BFA_PPORT_TYPE_VPORT   = 22,	/*  NPIV - virtual port */
-};
-
-/**
- * 		Port topology setting. A port's topology and fabric login status
- * 		determine its operational type.
- */
-enum bfa_pport_topology {
-	BFA_PPORT_TOPOLOGY_NONE = 0,	/*  No valid topology */
-	BFA_PPORT_TOPOLOGY_P2P  = 1,	/*  P2P only */
-	BFA_PPORT_TOPOLOGY_LOOP = 2,	/*  LOOP topology */
-	BFA_PPORT_TOPOLOGY_AUTO = 3,	/*  auto topology selection */
-};
-
-/**
- * 		Physical port loopback types.
- */
-enum bfa_pport_opmode {
-	BFA_PPORT_OPMODE_NORMAL   = 0x00, /*  normal non-loopback mode */
-	BFA_PPORT_OPMODE_LB_INT   = 0x01, /*  internal loop back */
-	BFA_PPORT_OPMODE_LB_SLW   = 0x02, /*  serial link wrapback (serdes) */
-	BFA_PPORT_OPMODE_LB_EXT   = 0x04, /*  external loop back (serdes) */
-	BFA_PPORT_OPMODE_LB_CBL   = 0x08, /*  cabled loop back */
-	BFA_PPORT_OPMODE_LB_NLINT = 0x20, /*  NL_Port internal loopback */
-};
-
-#define BFA_PPORT_OPMODE_LB_HARD(_mode)			\
-	((_mode == BFA_PPORT_OPMODE_LB_INT) ||		\
-     (_mode == BFA_PPORT_OPMODE_LB_SLW) ||		\
-     (_mode == BFA_PPORT_OPMODE_LB_EXT))
-
-/**
-		Port State (in sync with SNIA port state).
- */
-enum bfa_pport_snia_state {
-	BFA_PPORT_STATE_UNKNOWN  = 1,	/*  port is not initialized */
-	BFA_PPORT_STATE_ONLINE   = 2,	/*  port is ONLINE */
-	BFA_PPORT_STATE_DISABLED = 3,	/*  port is disabled by user */
-	BFA_PPORT_STATE_BYPASSED = 4,	/*  port is bypassed (in LOOP) */
-	BFA_PPORT_STATE_DIAG     = 5,	/*  port diagnostics is active */
-	BFA_PPORT_STATE_LINKDOWN = 6,	/*  link is down */
-	BFA_PPORT_STATE_LOOPBACK = 8,	/*  port is looped back */
-};
-
-/**
- * 		Port link state
- */
-enum bfa_pport_linkstate {
-	BFA_PPORT_LINKUP 	 = 1,	/*  Physical port/Trunk link up */
-	BFA_PPORT_LINKDOWN 	 = 2,	/*  Physical port/Trunk link down */
-	BFA_PPORT_TRUNK_LINKDOWN = 3,	/*  Trunk link down (new tmaster) */
-};
-
-/**
- * 		Port link state event
- */
-#define bfa_pport_event_t enum bfa_pport_linkstate
-
-/**
- * 		Port link state reason code
- */
-enum bfa_pport_linkstate_rsn {
-	BFA_PPORT_LINKSTATE_RSN_NONE		= 0,
-	BFA_PPORT_LINKSTATE_RSN_DISABLED 	= 1,
-	BFA_PPORT_LINKSTATE_RSN_RX_NOS 		= 2,
-	BFA_PPORT_LINKSTATE_RSN_RX_OLS 		= 3,
-	BFA_PPORT_LINKSTATE_RSN_RX_LIP 		= 4,
-	BFA_PPORT_LINKSTATE_RSN_RX_LIPF7 	= 5,
-	BFA_PPORT_LINKSTATE_RSN_SFP_REMOVED 	= 6,
-	BFA_PPORT_LINKSTATE_RSN_PORT_FAULT 	= 7,
-	BFA_PPORT_LINKSTATE_RSN_RX_LOS 		= 8,
-	BFA_PPORT_LINKSTATE_RSN_LOCAL_FAULT 	= 9,
-	BFA_PPORT_LINKSTATE_RSN_REMOTE_FAULT 	= 10,
-	BFA_PPORT_LINKSTATE_RSN_TIMEOUT 	= 11,
-
-
-
-	/* CEE related reason codes/errors */
-	CEE_LLDP_INFO_AGED_OUT       = 20,
-	CEE_LLDP_SHUTDOWN_TLV_RCVD   = 21,
-	CEE_PEER_NOT_ADVERTISE_DCBX  = 22,
-	CEE_PEER_NOT_ADVERTISE_PG    = 23,
-	CEE_PEER_NOT_ADVERTISE_PFC   = 24,
-	CEE_PEER_NOT_ADVERTISE_FCOE  = 25,
-	CEE_PG_NOT_COMPATIBLE        = 26,
-	CEE_PFC_NOT_COMPATIBLE       = 27,
-	CEE_FCOE_NOT_COMPATIBLE      = 28,
-	CEE_BAD_PG_RCVD              = 29,
-	CEE_BAD_BW_RCVD              = 30,
-	CEE_BAD_PFC_RCVD             = 31,
-	CEE_BAD_FCOE_PRI_RCVD        = 32,
-	CEE_FCOE_PRI_PFC_OFF         = 33,
-	CEE_DUP_CONTROL_TLV_RCVD     = 34,
-	CEE_DUP_FEAT_TLV_RCVD        = 35,
-	CEE_APPLY_NEW_CFG            = 36,	/* reason, not an error */
-	CEE_PROTOCOL_INIT            = 37,  /* reason, not an error */
-	CEE_PHY_LINK_DOWN            = 38,
-	CEE_LLS_FCOE_ABSENT          = 39,
-	CEE_LLS_FCOE_DOWN            = 40
-};
-
-/**
- *      Default Target Rate Limiting Speed.
- */
-#define BFA_PPORT_DEF_TRL_SPEED  BFA_PPORT_SPEED_1GBPS
-
-/**
- *      Physical port configuration
- */
-struct bfa_pport_cfg_s {
-	u8         topology;	/*  bfa_pport_topology		*/
-	u8         speed;		/*  enum bfa_pport_speed	*/
-	u8         trunked;	/*  trunked or not		*/
-	u8         qos_enabled;	/*  qos enabled or not		*/
-	u8         trunk_ports;	/*  bitmap of trunked ports	*/
-	u8         cfg_hardalpa;	/*  is hard alpa configured	*/
-	u16        maxfrsize;	/*  maximum frame size		*/
-	u8         hardalpa;	/*  configured hard alpa	*/
-	u8         rx_bbcredit;	/*  receive buffer credits	*/
-	u8         tx_bbcredit;	/*  transmit buffer credits	*/
-	u8         ratelimit;	/*  ratelimit enabled or not	*/
-	u8         trl_def_speed;	/*  ratelimit default speed	*/
-	u8		rsvd[3];
-	u16   	path_tov;	/*  device path timeout	*/
-	u16   	q_depth;	/*  SCSI Queue depth		*/
-};
-
-/**
- * 		Port attribute values.
- */
-struct bfa_pport_attr_s {
-	/*
-	 * Static fields
-	 */
-	wwn_t           nwwn;		/*  node wwn */
-	wwn_t           pwwn;		/*  port wwn */
-	wwn_t           factorynwwn;    /*  factory node wwn */
-	wwn_t           factorypwwn;    /*  factory port wwn */
-	enum fc_cos     cos_supported;	/*  supported class of services */
-	u32        rsvd;
-	struct fc_symname_s    port_symname;	/*  port symbolic name */
-	enum bfa_pport_speed speed_supported; /*  supported speeds */
-	bfa_boolean_t   pbind_enabled;	/*  Will be set if Persistent binding
-					 *   enabled. Relevant only in Windows
-					 */
-
-	/*
-	 * Configured values
-	 */
-	struct bfa_pport_cfg_s pport_cfg;	/*  pport cfg */
-
-	/*
-	 * Dynamic field - info from BFA
-	 */
-	enum bfa_pport_states 	port_state;	/*  current port state */
-	enum bfa_pport_speed 	speed;		/*  current speed */
-	enum bfa_pport_topology 	topology;	/*  current topology */
-	bfa_boolean_t		beacon;		/*  current beacon status */
-	bfa_boolean_t		link_e2e_beacon;/*  set if link beacon on */
-	bfa_boolean_t		plog_enabled;	/*  set if portlog is enabled*/
-
-	/*
-	 * Dynamic field - info from FCS
-	 */
-	u32        	pid;		/*  port ID */
-	enum bfa_pport_type 	port_type;	/*  current topology */
-	u32        	loopback;	/*  external loopback */
-	u32		authfail;	/* auth fail state */
-	u32		rsvd2;		/*  padding for 64 bit */
-};
-
-/**
- * 		FC Port statistics.
- */
-struct bfa_pport_fc_stats_s {
-	u64    secs_reset; /* Seconds since stats is reset     */
-	u64    tx_frames;  /* Tx frames                */
-	u64    tx_words;   /* Tx words                 */
-	u64    tx_lip;     /* Tx LIP               */
-	u64    tx_nos;     /* Tx NOS               */
-	u64    tx_ols;     /* Tx OLS               */
-	u64    tx_lr;      /* Tx LR                */
-	u64    tx_lrr;     /* Tx LRR               */
-	u64    rx_frames;  /* Rx frames                */
-	u64    rx_words;   /* Rx words                 */
-	u64    lip_count;  /* Rx LIP                   */
-	u64    nos_count;  /* Rx NOS               */
-	u64    ols_count;  /* Rx OLS               */
-	u64    lr_count;   /* Rx LR                */
-	u64    lrr_count;  /* Rx LRR               */
-	u64    invalid_crcs;   /* Rx CRC err frames            */
-	u64    invalid_crc_gd_eof; /* Rx CRC err good EOF frames   */
-	u64    undersized_frm; /* Rx undersized frames         */
-	u64    oversized_frm;  /* Rx oversized frames          */
-	u64    bad_eof_frm;    /* Rx frames with bad EOF       */
-	u64    error_frames;   /* Errored frames           */
-	u64    dropped_frames; /* Dropped frames           */
-	u64    link_failures;  /* Link Failure (LF) count          */
-	u64    loss_of_syncs;  /* Loss of sync count           */
-	u64    loss_of_signals;/* Loss of signal count         */
-	u64    primseq_errs;   /* Primitive sequence protocol err. */
-	u64    bad_os_count;   /* Invalid ordered sets         */
-	u64    err_enc_out;    /* Encoding err nonframe_8b10b      */
-	u64    err_enc;    /* Encoding err frame_8b10b         */
-};
-
-/**
- * 		Eth Port statistics.
- */
-struct bfa_pport_eth_stats_s {
-	u64    secs_reset;   /* Seconds since stats is reset   */
-	u64    frame_64;     /* Frames 64 bytes            */
-	u64    frame_65_127;     /* Frames 65-127 bytes        */
-	u64    frame_128_255;    /* Frames 128-255 bytes       */
-	u64    frame_256_511;    /* Frames 256-511 bytes       */
-	u64    frame_512_1023;   /* Frames 512-1023 bytes          */
-	u64    frame_1024_1518;  /* Frames 1024-1518 bytes         */
-	u64    frame_1519_1522;  /* Frames 1519-1522 bytes         */
-	u64    tx_bytes;     /* Tx bytes               */
-	u64    tx_packets;   /* Tx packets             */
-	u64    tx_mcast_packets; /* Tx multicast packets       */
-	u64    tx_bcast_packets; /* Tx broadcast packets       */
-	u64    tx_control_frame; /* Tx control frame           */
-	u64    tx_drop;      /* Tx drops               */
-	u64    tx_jabber;    /* Tx jabber              */
-	u64    tx_fcs_error;     /* Tx FCS error           */
-	u64    tx_fragments;     /* Tx fragments           */
-	u64    rx_bytes;     /* Rx bytes               */
-	u64    rx_packets;   /* Rx packets             */
-	u64    rx_mcast_packets; /* Rx multicast packets       */
-	u64    rx_bcast_packets; /* Rx broadcast packets       */
-	u64    rx_control_frames; /* Rx control frames         */
-	u64    rx_unknown_opcode; /* Rx unknown opcode         */
-	u64    rx_drop;      /* Rx drops               */
-	u64    rx_jabber;    /* Rx jabber              */
-	u64    rx_fcs_error;     /* Rx FCS errors              */
-	u64    rx_alignment_error; /* Rx alignment errors          */
-	u64    rx_frame_length_error; /* Rx frame len errors       */
-	u64    rx_code_error;    /* Rx code errors             */
-	u64    rx_fragments;     /* Rx fragments           */
-	u64    rx_pause;     /* Rx pause               */
-	u64    rx_zero_pause;    /* Rx zero pause              */
-	u64    tx_pause;     /* Tx pause               */
-	u64    tx_zero_pause;    /* Tx zero pause              */
-	u64    rx_fcoe_pause;    /* Rx FCoE pause              */
-	u64    rx_fcoe_zero_pause; /* Rx FCoE zero pause       */
-	u64    tx_fcoe_pause;    /* Tx FCoE pause              */
-	u64    tx_fcoe_zero_pause; /* Tx FCoE zero pause       */
-};
-
-/**
- * 		Port statistics.
- */
-union bfa_pport_stats_u {
-	struct bfa_pport_fc_stats_s	fc;
-	struct bfa_pport_eth_stats_s 	eth;
-};
-
-/**
- *              Port FCP mappings.
- */
-struct bfa_pport_fcpmap_s {
-	char		osdevname[256];
-	u32	bus;
-	u32        target;
-	u32        oslun;
-	u32        fcid;
-	wwn_t           nwwn;
-	wwn_t           pwwn;
-	u64        fcplun;
-	char		luid[256];
-};
-
-/**
- *              Port RNI	 */
-struct bfa_pport_rnid_s {
-	wwn_t             wwn;
-	u32          unittype;
-	u32          portid;
-	u32          attached_nodes_num;
-	u16          ip_version;
-	u16          udp_port;
-	u8           ipaddr[16];
-	u16          rsvd;
-	u16          topologydiscoveryflags;
-};
-
-struct bfa_fcport_fcf_s {
-	wwn_t           name;           /* FCF name                 */
-	wwn_t           fabric_name;    /* Fabric Name              */
-	u8		fipenabled;     /* FIP enabled or not       */
-	u8		fipfailed;      /* FIP failed or not        */
-	u8         	resv[2];
-	u8         	pri;            /* FCF priority             */
-	u8         	version;        /* FIP version used         */
-	u8         	available;      /* Available  for  login    */
-	u8         	fka_disabled;   /* FKA is disabled          */
-	u8         	maxsz_verified; /* FCoE max size verified   */
-	u8         	fc_map[3];      /* FC map                   */
-	u16		vlan;           /* FCoE vlan tag/priority   */
-	u32        	fka_adv_per;    /* FIP  ka advert. period   */
-	struct mac_s	mac;            /* FCF mac                  */
-};
-
-/**
- * 		Link state information
- */
-struct bfa_pport_link_s {
-	u8         linkstate;	/*  Link state bfa_pport_linkstate */
-	u8         linkstate_rsn;	/*  bfa_pport_linkstate_rsn_t */
-	u8         topology;	/*  P2P/LOOP bfa_pport_topology */
-	u8         speed;		/*  Link speed (1/2/4/8 G) */
-	u32        linkstate_opt;	/*  Linkstate optional data (debug) */
-	u8         trunked;	/*  Trunked or not (1 or 0) */
-	u8         resvd[3];
-	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
-	union {
-		struct bfa_qos_vc_attr_s qos_vc_attr;  /* VC info from ELP */
-		struct bfa_fcport_fcf_s fcf;    /* FCF information (for FCoE) */
-	} vc_fcf;
-};
-
-#endif /* __BFA_DEFS_PPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_qos.h b/drivers/scsi/bfa/include/defs/bfa_defs_qos.h
deleted file mode 100644
index aadbacd..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_qos.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_QOS_H__
-#define __BFA_DEFS_QOS_H__
-
-/**
- * QoS states
- */
-enum bfa_qos_state {
-	BFA_QOS_ONLINE = 1,		/*  QoS is online */
-	BFA_QOS_OFFLINE = 2,		/*  QoS is offline */
-};
-
-
-/**
- * QoS  Priority levels.
- */
-enum bfa_qos_priority {
-	BFA_QOS_UNKNOWN = 0,
-	BFA_QOS_HIGH  = 1,	/*  QoS Priority Level High */
-	BFA_QOS_MED  =  2,	/*  QoS Priority Level Medium */
-	BFA_QOS_LOW  =  3,	/*  QoS Priority Level Low */
-};
-
-
-/**
- * QoS  bandwidth allocation for each priority level
- */
-enum bfa_qos_bw_alloc {
-	BFA_QOS_BW_HIGH  = 60,	/*  bandwidth allocation for High */
-	BFA_QOS_BW_MED  =  30,	/*  bandwidth allocation for Medium */
-	BFA_QOS_BW_LOW  =  10,	/*  bandwidth allocation for Low */
-};
-
-/**
- * QoS attribute returned in QoS Query
- */
-struct bfa_qos_attr_s {
-	enum bfa_qos_state state;		/*  QoS current state */
-	u32  total_bb_cr;  	 	/*  Total BB Credits */
-};
-
-/**
- * These fields should be displayed only from the CLI.
- * There will be a separate BFAL API (get_qos_vc_attr ?)
- * to retrieve this.
- *
- */
-#define  BFA_QOS_MAX_VC  16
-
-struct bfa_qos_vc_info_s {
-	u8 vc_credit;
-	u8 borrow_credit;
-	u8 priority;
-	u8 resvd;
-};
-
-struct bfa_qos_vc_attr_s {
-	u16  total_vc_count;                    /*  Total VC Count */
-	u16  shared_credit;
-	u32  elp_opmode_flags;
-	struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC];  /*   as many as
-							    * total_vc_count */
-};
-
-/**
- * QoS statistics
- */
-struct bfa_qos_stats_s {
-	u32	flogi_sent; 		/*  QoS Flogi sent */
-	u32	flogi_acc_recvd;	/*  QoS Flogi Acc received */
-	u32	flogi_rjt_recvd; /*  QoS Flogi rejects received */
-	u32	flogi_retries;		/*  QoS Flogi retries */
-
-	u32	elp_recvd; 	   	/*  QoS ELP received */
-	u32	elp_accepted;       /*  QoS ELP Accepted */
-	u32	elp_rejected;       /*  QoS ELP rejected */
-	u32	elp_dropped;        /*  QoS ELP dropped  */
-
-	u32	qos_rscn_recvd;     /*  QoS RSCN received */
-	u32	rsvd; 		/* padding for 64 bit alignment */
-};
-
-#endif /* __BFA_DEFS_QOS_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_rport.h b/drivers/scsi/bfa/include/defs/bfa_defs_rport.h
deleted file mode 100644
index e0af59d..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_rport.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_RPORT_H__
-#define __BFA_DEFS_RPORT_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_qos.h>
-
-/**
- * FCS remote port states
- */
-enum bfa_rport_state {
-	BFA_RPORT_UNINIT 	= 0,	/*  PORT is not yet initialized */
-	BFA_RPORT_OFFLINE 	= 1,	/*  rport is offline */
-	BFA_RPORT_PLOGI 	= 2,	/*  PLOGI to rport is in progress */
-	BFA_RPORT_ONLINE 	= 3,	/*  login to rport is complete */
-	BFA_RPORT_PLOGI_RETRY 	= 4,	/*  retrying login to rport */
-	BFA_RPORT_NSQUERY 	= 5,	/*  nameserver query */
-	BFA_RPORT_ADISC 	= 6,	/*  ADISC authentication */
-	BFA_RPORT_LOGO 		= 7,	/*  logging out with rport */
-	BFA_RPORT_LOGORCV 	= 8,	/*  handling LOGO from rport */
-	BFA_RPORT_NSDISC 	= 9,	/*  re-discover rport */
-};
-
-/**
- *  Rport Scsi Function : Initiator/Target.
- */
-enum bfa_rport_function {
-	BFA_RPORT_INITIATOR 	= 0x01,	/*  SCSI Initiator	*/
-	BFA_RPORT_TARGET 	= 0x02,	/*  SCSI Target	*/
-};
-
-/**
- * port/node symbolic names for rport
- */
-#define BFA_RPORT_SYMNAME_MAXLEN	255
-struct bfa_rport_symname_s {
-	char            symname[BFA_RPORT_SYMNAME_MAXLEN];
-};
-
-struct bfa_rport_hal_stats_s {
-	u32        sm_un_cr;	    /*  uninit: create events      */
-	u32        sm_un_unexp;	    /*  uninit: exception events   */
-	u32        sm_cr_on;	    /*  created: online events     */
-	u32        sm_cr_del;	    /*  created: delete events     */
-	u32        sm_cr_hwf;	    /*  created: IOC down          */
-	u32        sm_cr_unexp;	    /*  created: exception events  */
-	u32        sm_fwc_rsp;	    /*  fw create: f/w responses   */
-	u32        sm_fwc_del;	    /*  fw create: delete events   */
-	u32        sm_fwc_off;	    /*  fw create: offline events  */
-	u32        sm_fwc_hwf;	    /*  fw create: IOC down        */
-	u32        sm_fwc_unexp;	    /*  fw create: exception events*/
-	u32        sm_on_off;	    /*  online: offline events     */
-	u32        sm_on_del;	    /*  online: delete events      */
-	u32        sm_on_hwf;	    /*  online: IOC down events    */
-	u32        sm_on_unexp;	    /*  online: exception events   */
-	u32        sm_fwd_rsp;	    /*  fw delete: fw responses    */
-	u32        sm_fwd_del;	    /*  fw delete: delete events   */
-	u32        sm_fwd_hwf;	    /*  fw delete: IOC down events */
-	u32        sm_fwd_unexp;	    /*  fw delete: exception events*/
-	u32        sm_off_del;	    /*  offline: delete events     */
-	u32        sm_off_on;	    /*  offline: online events     */
-	u32        sm_off_hwf;	    /*  offline: IOC down events   */
-	u32        sm_off_unexp;	    /*  offline: exception events  */
-	u32        sm_del_fwrsp;	    /*  delete: fw responses       */
-	u32        sm_del_hwf;	    /*  delete: IOC down events    */
-	u32        sm_del_unexp;	    /*  delete: exception events   */
-	u32        sm_delp_fwrsp;	    /*  delete pend: fw responses  */
-	u32        sm_delp_hwf;	    /*  delete pend: IOC downs     */
-	u32        sm_delp_unexp;	    /*  delete pend: exceptions    */
-	u32        sm_offp_fwrsp;	    /*  off-pending: fw responses  */
-	u32        sm_offp_del;	    /*  off-pending: deletes       */
-	u32        sm_offp_hwf;	    /*  off-pending: IOC downs     */
-	u32        sm_offp_unexp;	    /*  off-pending: exceptions    */
-	u32        sm_iocd_off;	    /*  IOC down: offline events   */
-	u32        sm_iocd_del;	    /*  IOC down: delete events    */
-	u32        sm_iocd_on;	    /*  IOC down: online events    */
-	u32        sm_iocd_unexp;	    /*  IOC down: exceptions       */
-	u32        rsvd;
-};
-
-/**
- * FCS remote port statistics
- */
-struct bfa_rport_stats_s {
-	u32        offlines;           /*  remote port offline count  */
-	u32        onlines;            /*  remote port online count   */
-	u32        rscns;              /*  RSCN affecting rport       */
-	u32        plogis;		    /*  plogis sent                */
-	u32        plogi_accs;	    /*  plogi accepts              */
-	u32        plogi_timeouts;	    /*  plogi timeouts             */
-	u32        plogi_rejects;	    /*  rcvd plogi rejects         */
-	u32        plogi_failed;	    /*  local failure              */
-	u32        plogi_rcvd;	    /*  plogis rcvd                */
-	u32        prli_rcvd;          /*  inbound PRLIs              */
-	u32        adisc_rcvd;         /*  ADISCs received            */
-	u32        adisc_rejects;      /*  recvd  ADISC rejects       */
-	u32        adisc_sent;         /*  ADISC requests sent        */
-	u32        adisc_accs;         /*  ADISC accepted by rport    */
-	u32        adisc_failed;       /*  ADISC failed (no response) */
-	u32        adisc_rejected;     /*  ADISC rejected by us    */
-	u32        logos;              /*  logos sent                 */
-	u32        logo_accs;          /*  LOGO accepts from rport    */
-	u32        logo_failed;        /*  LOGO failures              */
-	u32        logo_rejected;      /*  LOGO rejects from rport    */
-	u32        logo_rcvd;          /*  LOGO from remote port      */
-
-	u32        rpsc_rcvd;         /*  RPSC received            */
-	u32        rpsc_rejects;      /*  recvd  RPSC rejects       */
-	u32        rpsc_sent;         /*  RPSC requests sent        */
-	u32        rpsc_accs;         /*  RPSC accepted by rport    */
-	u32        rpsc_failed;       /*  RPSC failed (no response) */
-	u32        rpsc_rejected;     /*  RPSC rejected by us    */
-
-	u32        rsvd;
-	struct bfa_rport_hal_stats_s	hal_stats;  /*  BFA rport stats    */
-};
-
-/**
- *  Rport's QoS attributes
- */
-struct bfa_rport_qos_attr_s {
-	enum bfa_qos_priority qos_priority;  /*  rport's QoS priority   */
-	u32	       qos_flow_id;	  /*  QoS flow Id	 */
-};
-
-/**
- * FCS remote port attributes returned in queries
- */
-struct bfa_rport_attr_s {
-	wwn_t           	nwwn;	/*  node wwn */
-	wwn_t           	pwwn;	/*  port wwn */
-	enum fc_cos cos_supported;	/*  supported class of services */
-	u32        	pid;	/*  port ID */
-	u32        	df_sz;	/*  Max payload size */
-	enum bfa_rport_state 	state;	/*  Rport State machine state */
-	enum fc_cos        	fc_cos;	/*  FC classes of services */
-	bfa_boolean_t   	cisc;	/*  CISC capable device */
-	struct bfa_rport_symname_s symname; /*  Symbolic Name */
-	enum bfa_rport_function	scsi_function; /*  Initiator/Target */
-	struct bfa_rport_qos_attr_s qos_attr; /*  qos attributes  */
-	enum bfa_pport_speed curr_speed;   /*  operating speed got from
-					    * RPSC ELS. UNKNOWN, if RPSC
-					    * is not supported */
-	bfa_boolean_t 	trl_enforced;	/*  TRL enforced ? TRUE/FALSE */
-	enum bfa_pport_speed	assigned_speed;	/* Speed assigned by the user.
-						 * will be used if RPSC is not
-						 * supported by the rport */
-};
-
-#define bfa_rport_aen_qos_data_t struct bfa_rport_qos_attr_s
-
-/**
- * BFA remote port events
- * Arguments below are in BFAL context from Mgmt
- * BFA_RPORT_AEN_ONLINE:    [in]: lpwwn	[out]: vf_id, lpwwn, rpwwn
- * BFA_RPORT_AEN_OFFLINE:   [in]: lpwwn [out]: vf_id, lpwwn, rpwwn
- * BFA_RPORT_AEN_DISCONNECT:[in]: lpwwn [out]: vf_id, lpwwn, rpwwn
- * BFA_RPORT_AEN_QOS_PRIO:  [in]: lpwwn [out]: vf_id, lpwwn, rpwwn, prio
- * BFA_RPORT_AEN_QOS_FLOWID:[in]: lpwwn [out]: vf_id, lpwwn, rpwwn, flow_id
- */
-enum bfa_rport_aen_event {
-	BFA_RPORT_AEN_ONLINE      = 1,	/*  RPort online event */
-	BFA_RPORT_AEN_OFFLINE     = 2,	/*  RPort offline event */
-	BFA_RPORT_AEN_DISCONNECT  = 3,	/*  RPort disconnect event */
-	BFA_RPORT_AEN_QOS_PRIO    = 4,	/*  QOS priority change event */
-	BFA_RPORT_AEN_QOS_FLOWID  = 5,	/*  QOS flow Id change event */
-};
-
-struct bfa_rport_aen_data_s {
-	u16        vf_id;	/*  vf_id of this logical port */
-	u16        rsvd[3];
-	wwn_t           ppwwn;	/*  WWN of its physical port */
-	wwn_t           lpwwn;	/*  WWN of this logical port */
-	wwn_t           rpwwn;	/*  WWN of this remote port */
-	union {
-		bfa_rport_aen_qos_data_t qos;
-	} priv;
-};
-
-#endif /* __BFA_DEFS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_status.h b/drivers/scsi/bfa/include/defs/bfa_defs_status.h
deleted file mode 100644
index 6eb4e62..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_status.h
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_STATUS_H__
-#define __BFA_DEFS_STATUS_H__
-
-/**
- * API status return values
- *
- * NOTE: The error msgs are auto generated from the comments. Only singe line
- * comments are supported
- */
-enum bfa_status {
-	BFA_STATUS_OK 		= 0,	/*  Success */
-	BFA_STATUS_FAILED 	= 1,	/*  Operation failed */
-	BFA_STATUS_EINVAL 	= 2,	/*  Invalid params Check input
-					 * parameters */
-	BFA_STATUS_ENOMEM 	= 3,	/*  Out of resources */
-	BFA_STATUS_ENOSYS 	= 4,	/*  Function not implemented */
-	BFA_STATUS_ETIMER 	= 5,	/*  Timer expired - Retry, if
-					 * persists, contact support */
-	BFA_STATUS_EPROTOCOL 	= 6,	/*  Protocol error */
-	BFA_STATUS_ENOFCPORTS 	= 7,	/*  No FC ports resources */
-	BFA_STATUS_NOFLASH 	= 8,	/*  Flash not present */
-	BFA_STATUS_BADFLASH 	= 9,	/*  Flash is corrupted or bad */
-	BFA_STATUS_SFP_UNSUPP 	= 10,	/*  Unsupported SFP - Replace SFP */
-	BFA_STATUS_UNKNOWN_VFID = 11,	/*  VF_ID not found */
-	BFA_STATUS_DATACORRUPTED = 12,	/*  Diag returned data corrupted
-					 * contact support */
-	BFA_STATUS_DEVBUSY 	= 13,	/*  Device busy - Retry operation */
-	BFA_STATUS_ABORTED 	= 14,	/*  Operation aborted */
-	BFA_STATUS_NODEV 	= 15,	/*  Dev is not present */
-	BFA_STATUS_HDMA_FAILED 	= 16,	/*  Host dma failed contact support */
-	BFA_STATUS_FLASH_BAD_LEN = 17,	/*  Flash bad length */
-	BFA_STATUS_UNKNOWN_LWWN = 18,	/*  LPORT PWWN not found */
-	BFA_STATUS_UNKNOWN_RWWN = 19,	/*  RPORT PWWN not found */
-	BFA_STATUS_FCPT_LS_RJT 	= 20,	/*  Got LS_RJT for FC Pass
-					 * through Req */
-	BFA_STATUS_VPORT_EXISTS = 21,	/*  VPORT already exists */
-	BFA_STATUS_VPORT_MAX 	= 22,	/*  Reached max VPORT supported
-					 * limit */
-	BFA_STATUS_UNSUPP_SPEED = 23,	/*  Invalid Speed Check speed
-					 * setting */
-	BFA_STATUS_INVLD_DFSZ 	= 24,	/*  Invalid Max data field size */
-	BFA_STATUS_CNFG_FAILED 	= 25,	/*  Setting can not be persisted */
-	BFA_STATUS_CMD_NOTSUPP 	= 26,	/*  Command/API not supported */
-	BFA_STATUS_NO_ADAPTER 	= 27,	/*  No Brocade Adapter Found */
-	BFA_STATUS_LINKDOWN 	= 28,	/*  Link is down - Check or replace
-					 * SFP/cable */
-	BFA_STATUS_FABRIC_RJT 	= 29,	/*  Reject from attached fabric */
-	BFA_STATUS_UNKNOWN_VWWN = 30,	/*  VPORT PWWN not found */
-	BFA_STATUS_NSLOGIN_FAILED = 31,	/*  Nameserver login failed */
-	BFA_STATUS_NO_RPORTS 	= 32,	/*  No remote ports found */
-	BFA_STATUS_NSQUERY_FAILED = 33,	/*  Nameserver query failed */
-	BFA_STATUS_PORT_OFFLINE = 34,	/*  Port is not online */
-	BFA_STATUS_RPORT_OFFLINE = 35,	/*  RPORT is not online */
-	BFA_STATUS_TGTOPEN_FAILED = 36,	/*  Remote SCSI target open failed */
-	BFA_STATUS_BAD_LUNS 	= 37,	/*  No valid LUNs found */
-	BFA_STATUS_IO_FAILURE 	= 38,	/*  SCSI target IO failure */
-	BFA_STATUS_NO_FABRIC 	= 39,	/*  No switched fabric present */
-	BFA_STATUS_EBADF 	= 40,	/*  Bad file descriptor */
-	BFA_STATUS_EINTR 	= 41,	/*  A signal was caught during ioctl */
-	BFA_STATUS_EIO 		= 42,	/*  I/O error */
-	BFA_STATUS_ENOTTY 	= 43,	/*  Inappropriate I/O control
-					 * operation */
-	BFA_STATUS_ENXIO 	= 44,	/*  No such device or address */
-	BFA_STATUS_EFOPEN 	= 45,	/*  Failed to open file */
-	BFA_STATUS_VPORT_WWN_BP = 46,	/*  WWN is same as base port's WWN */
-	BFA_STATUS_PORT_NOT_DISABLED = 47, /*  Port not disabled disable port
-					    * first */
-	BFA_STATUS_BADFRMHDR 	= 48,	/*  Bad frame header */
-	BFA_STATUS_BADFRMSZ 	= 49,	/*  Bad frame size check and replace
-					 * SFP/cable */
-	BFA_STATUS_MISSINGFRM 	= 50,   /* Missing frame check and replace
-					 * SFP/cable or for Mezz card check and
-					 * replace pass through module */
-	BFA_STATUS_LINKTIMEOUT 	= 51,	/*  Link timeout check and replace
-					 * SFP/cable */
-	BFA_STATUS_NO_FCPIM_NEXUS = 52,	/*  No FCP Nexus exists with the
-					 * rport */
-	BFA_STATUS_CHECKSUM_FAIL = 53,	/*  checksum failure */
-	BFA_STATUS_GZME_FAILED 	= 54,	/*  Get zone member query failed */
-	BFA_STATUS_SCSISTART_REQD = 55,	/*  SCSI disk require START command */
-	BFA_STATUS_IOC_FAILURE 	= 56,	/*  IOC failure - Retry, if persists
-					 * contact support */
-	BFA_STATUS_INVALID_WWN 	= 57,	/*  Invalid WWN */
-	BFA_STATUS_MISMATCH 	= 58,	/*  Version mismatch */
-	BFA_STATUS_IOC_ENABLED 	= 59,	/*  IOC is already enabled */
-	BFA_STATUS_ADAPTER_ENABLED = 60, /*  Adapter is not disabled disable
-					  * adapter first */
-	BFA_STATUS_IOC_NON_OP 	= 61,	/*  IOC is not operational. Enable IOC
-					 * and if it still fails,
-					 * contact support */
-	BFA_STATUS_ADDR_MAP_FAILURE = 62, /*  PCI base address not mapped
-					   * in OS */
-	BFA_STATUS_SAME_NAME 	= 63,	/*  Name exists! use a different
-					 * name */
-	BFA_STATUS_PENDING      = 64,   /*  API completes asynchronously */
-	BFA_STATUS_8G_SPD	= 65,	/*  Speed setting not valid for
-					 * 8G HBA */
-	BFA_STATUS_4G_SPD	= 66,	/*  Speed setting not valid for
-					 * 4G HBA */
-	BFA_STATUS_AD_IS_ENABLE = 67,	/*  Adapter is already enabled */
-	BFA_STATUS_EINVAL_TOV 	= 68,	/*  Invalid path failover TOV */
-	BFA_STATUS_EINVAL_QDEPTH = 69,	/*  Invalid queue depth value */
-	BFA_STATUS_VERSION_FAIL = 70,	/*  Application/Driver version
-					 * mismatch */
-	BFA_STATUS_DIAG_BUSY    = 71,	/*  diag busy */
-	BFA_STATUS_BEACON_ON	= 72,	/*  Port Beacon already on */
-	BFA_STATUS_BEACON_OFF	= 73,	/*  Port Beacon already off */
-	BFA_STATUS_LBEACON_ON   = 74,	/*  Link End-to-End Beacon already
-					 * on */
-	BFA_STATUS_LBEACON_OFF	= 75,	/*  Link End-to-End Beacon already
-					 * off */
-	BFA_STATUS_PORT_NOT_INITED = 76, /*  Port not initialized */
-	BFA_STATUS_RPSC_ENABLED = 77, /*  Target has a valid speed */
-	BFA_STATUS_ENOFSAVE = 78,	/*  No saved firmware trace */
-	BFA_STATUS_BAD_FILE = 79,	/*  Not a valid Brocade Boot Code
-					 * file */
-	BFA_STATUS_RLIM_EN = 80,	/*  Target rate limiting is already
-					 * enabled */
-	BFA_STATUS_RLIM_DIS = 81,  /*  Target rate limiting is already
-				    * disabled */
-	BFA_STATUS_IOC_DISABLED = 82,   /*  IOC is already disabled */
-	BFA_STATUS_ADAPTER_DISABLED = 83,   /*  Adapter is already disabled */
-	BFA_STATUS_BIOS_DISABLED = 84,   /*  Bios is already disabled */
-	BFA_STATUS_AUTH_ENABLED = 85,   /*  Authentication is already
-					 * enabled */
-	BFA_STATUS_AUTH_DISABLED = 86,   /*  Authentication is already
-					 * disabled */
-	BFA_STATUS_ERROR_TRL_ENABLED = 87,   /*  Target rate limiting is
-					      * enabled */
-	BFA_STATUS_ERROR_QOS_ENABLED = 88,   /*  QoS is enabled */
-	BFA_STATUS_NO_SFP_DEV = 89, /*  No SFP device check or replace SFP */
-	BFA_STATUS_MEMTEST_FAILED = 90,	/*  Memory test failed contact
-					 * support */
-	BFA_STATUS_INVALID_DEVID = 91,	/*  Invalid device id provided */
-	BFA_STATUS_QOS_ENABLED = 92, /*  QOS is already enabled */
-	BFA_STATUS_QOS_DISABLED = 93, /*  QOS is already disabled */
-	BFA_STATUS_INCORRECT_DRV_CONFIG = 94, /*  Check configuration
-					       * key/value pair */
-	BFA_STATUS_REG_FAIL = 95, /*  Can't read windows registry */
-	BFA_STATUS_IM_INV_CODE = 96, /*  Invalid IOCTL code */
-	BFA_STATUS_IM_INV_VLAN = 97, /*  Invalid VLAN ID */
-	BFA_STATUS_IM_INV_ADAPT_NAME = 98, /*  Invalid adapter name */
-	BFA_STATUS_IM_LOW_RESOURCES = 99, /*  Memory allocation failure in
-					   * driver */
-	BFA_STATUS_IM_VLANID_IS_PVID = 100, /*  Given VLAN id same as PVID */
-	BFA_STATUS_IM_VLANID_EXISTS = 101, /*  Given VLAN id already exists */
-	BFA_STATUS_IM_FW_UPDATE_FAIL = 102, /*  Updating firmware with new
-					     * VLAN ID failed */
-	BFA_STATUS_PORTLOG_ENABLED = 103, /*  Port Log is already enabled */
-	BFA_STATUS_PORTLOG_DISABLED = 104, /*  Port Log is already disabled */
-	BFA_STATUS_FILE_NOT_FOUND = 105, /*  Specified file could not be
-					  * found */
-	BFA_STATUS_QOS_FC_ONLY = 106, /*  QOS can be enabled for FC mode
-				       * only */
-	BFA_STATUS_RLIM_FC_ONLY = 107, /*  RATELIM can be enabled for FC mode
-					* only */
-	BFA_STATUS_CT_SPD = 108, /*  Invalid speed selection for Catapult. */
-	BFA_STATUS_LEDTEST_OP = 109, /*  LED test is operating */
-	BFA_STATUS_CEE_NOT_DN = 110, /*  eth port is not at down state, please
-				      * bring down first */
-	BFA_STATUS_10G_SPD = 111, /*  Speed setting not valid for 10G CNA */
-	BFA_STATUS_IM_INV_TEAM_NAME = 112, /*  Invalid team name */
-	BFA_STATUS_IM_DUP_TEAM_NAME = 113, /*  Given team name already
-					    * exists */
-	BFA_STATUS_IM_ADAPT_ALREADY_IN_TEAM = 114, /*  Given adapter is part
-						    * of another team */
-	BFA_STATUS_IM_ADAPT_HAS_VLANS = 115, /*  Adapter has VLANs configured.
-					      * Delete all VLANs to become
-					      * part of the team */
-	BFA_STATUS_IM_PVID_MISMATCH = 116, /*  Mismatching PVIDs configured
-					    * for adapters */
-	BFA_STATUS_IM_LINK_SPEED_MISMATCH = 117, /*  Mismatching link speeds
-						  * configured for adapters */
-	BFA_STATUS_IM_MTU_MISMATCH = 118, /*  Mismatching MTUs configured for
-					   * adapters */
-	BFA_STATUS_IM_RSS_MISMATCH = 119, /*  Mismatching RSS parameters
-					   * configured for adapters */
-	BFA_STATUS_IM_HDS_MISMATCH = 120, /*  Mismatching HDS parameters
-					   * configured for adapters */
-	BFA_STATUS_IM_OFFLOAD_MISMATCH = 121, /*  Mismatching offload
-					       * parameters configured for
-					       * adapters */
-	BFA_STATUS_IM_PORT_PARAMS = 122, /*  Error setting port parameters */
-	BFA_STATUS_IM_PORT_NOT_IN_TEAM = 123, /*  Port is not part of team */
-	BFA_STATUS_IM_CANNOT_REM_PRI = 124, /*  Primary adapter cannot be
-					     * removed. Change primary before
-					     * removing */
-	BFA_STATUS_IM_MAX_PORTS_REACHED = 125, /*  Exceeding maximum ports
-						* per team */
-	BFA_STATUS_IM_LAST_PORT_DELETE = 126, /*  Last port in team being
-					       * deleted */
-	BFA_STATUS_IM_NO_DRIVER = 127, /*  IM driver is not installed */
-	BFA_STATUS_IM_MAX_VLANS_REACHED = 128, /*  Exceeding maximum VLANs
-						* per port */
-	BFA_STATUS_TOMCAT_SPD_NOT_ALLOWED = 129, /* Bios speed config not
-						  * allowed for CNA */
-	BFA_STATUS_NO_MINPORT_DRIVER = 130, /*  Miniport driver is not
-					     * loaded */
-	BFA_STATUS_CARD_TYPE_MISMATCH = 131, /*  Card type mismatch */
-	BFA_STATUS_BAD_ASICBLK = 132, /*  Bad ASIC block */
-	BFA_STATUS_NO_DRIVER = 133, /*  Brocade adapter/driver not installed
-				     *  or loaded */
-	BFA_STATUS_INVALID_MAC = 134, /*  Invalid MAC address */
-	BFA_STATUS_IM_NO_VLAN = 135, /*  No VLANs configured on the adapter */
-	BFA_STATUS_IM_ETH_LB_FAILED = 136, /*  Ethernet loopback test failed */
-	BFA_STATUS_IM_PVID_REMOVE = 137, /* Cannot remove port VLAN (PVID) */
-	BFA_STATUS_IM_PVID_EDIT = 138, /* Cannot edit port VLAN (PVID) */
-	BFA_STATUS_CNA_NO_BOOT = 139, /*  Boot upload not allowed for CNA */
-	BFA_STATUS_IM_PVID_NON_ZERO = 140, /*  Port VLAN ID (PVID) is Set to
-					    * Non-Zero Value */
-	BFA_STATUS_IM_INETCFG_LOCK_FAILED = 141, /*  Acquiring Network
-						  * Subsystem Lock Failed.Please
-						  * try after some time */
-	BFA_STATUS_IM_GET_INETCFG_FAILED = 142, /*  Acquiring Network Subsystem
-						 * handle Failed. Please try
-						 * after some time */
-	BFA_STATUS_IM_NOT_BOUND = 143, /*  IM driver is not active */
-	BFA_STATUS_INSUFFICIENT_PERMS = 144, /*  User doesn't have sufficient
-					      * permissions to execute the BCU
-					      * application */
-	BFA_STATUS_IM_INV_VLAN_NAME = 145, /* Invalid/Reserved VLAN name
-					    * string. The name is not allowed
-					    * for the normal VLAN */
-	BFA_STATUS_CMD_NOTSUPP_CNA = 146, /*  Command not supported for CNA */
-	BFA_STATUS_IM_PASSTHRU_EDIT = 147, /* Can not edit passthrough VLAN
-					    * id */
-	BFA_STATUS_IM_BIND_FAILED = 148, /* IM Driver bind operation
-					  * failed */
-	BFA_STATUS_IM_UNBIND_FAILED = 149, /* IM Driver unbind operation
-					    * failed */
-	BFA_STATUS_IM_PORT_IN_TEAM = 150, /*  Port is already part of the
-					   * team */
-	BFA_STATUS_IM_VLAN_NOT_FOUND = 151, /*  VLAN ID doesn't exists */
-	BFA_STATUS_IM_TEAM_NOT_FOUND = 152, /*  Teaming configuration doesn't
-					     * exists */
-	BFA_STATUS_IM_TEAM_CFG_NOT_ALLOWED = 153, /*  Given settings are not
-						* allowed for the current
-						* Teaming mode */
-	BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot
-			       * configuration */
-	BFA_STATUS_DEVID_MISSING = 155, /* Boot image is not for the adapter(s)
-					 * installed */
-	BFA_STATUS_BAD_FWCFG = 156, /* Bad firmware configuration */
-	BFA_STATUS_CREATE_FILE = 157, /* Failed to create temporary file */
-	BFA_STATUS_INVALID_VENDOR = 158, /* Invalid switch vendor */
-	BFA_STATUS_SFP_NOT_READY = 159, /* SFP info is not ready. Retry */
-	BFA_STATUS_NO_TOPOLOGY_FOR_CNA = 160, /* Topology command not
-					       * applicable to CNA */
-	BFA_STATUS_BOOT_CODE_UPDATED = 161, /* reboot -- -r is needed after
-					     * boot code updated */
-	BFA_STATUS_BOOT_VERSION = 162, /* Boot code version not compatible with
-					* the driver installed */
-	BFA_STATUS_CARDTYPE_MISSING = 163, /* Boot image is not for the
-					    * adapter(s) installed */
-	BFA_STATUS_INVALID_CARDTYPE = 164, /* Invalid card type provided */
-	BFA_STATUS_MAX_VAL              /* Unknown error code */
-};
-#define bfa_status_t enum bfa_status
-
-enum bfa_eproto_status {
-	BFA_EPROTO_BAD_ACCEPT = 0,
-	BFA_EPROTO_UNKNOWN_RSP = 1
-};
-#define bfa_eproto_status_t enum bfa_eproto_status
-
-#endif /* __BFA_DEFS_STATUS_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_tin.h b/drivers/scsi/bfa/include/defs/bfa_defs_tin.h
deleted file mode 100644
index e05a2db..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_tin.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_TIN_H__
-#define __BFA_DEFS_TIN_H__
-
-#include <protocol/types.h>
-#include <protocol/fc.h>
-
-/**
- * FCS tin states
- */
-enum bfa_tin_state_e {
-	BFA_TIN_SM_OFFLINE = 0,		/*  tin is offline */
-	BFA_TIN_SM_WOS_LOGIN = 1,	/*  Waiting PRLI ACC/RJT from ULP */
-	BFA_TIN_SM_WFW_ONLINE = 2,	/*  Waiting ACK to PRLI ACC from FW */
-	BFA_TIN_SM_ONLINE = 3,		/*  tin login is complete */
-	BFA_TIN_SM_WIO_RELOGIN = 4,	/*  tin relogin is in progress */
-	BFA_TIN_SM_WIO_LOGOUT = 5,	/*  Processing of PRLO req from
-					 *   Initiator is in progress
-					 */
-	BFA_TIN_SM_WOS_LOGOUT = 6,	/*  Processing of PRLO req from
-					 *   Initiator is in progress
-					 */
-	BFA_TIN_SM_WIO_CLEAN = 7,	/*  Waiting for IO cleanup before tin
-					 *   is offline. This can be triggered
-					 *   by RPORT LOGO (rcvd/sent) or by
-					 *   PRLO (rcvd/sent)
-					 */
-};
-
-struct bfa_prli_req_s {
-	struct fchs_s fchs;
-	struct fc_prli_s prli_payload;
-};
-
-struct bfa_prlo_req_s {
-	struct fchs_s fchs;
-	struct fc_prlo_s prlo_payload;
-};
-
-void bfa_tin_send_login_rsp(void *bfa_tin, u32 login_rsp,
-				struct fc_ls_rjt_s rjt_payload);
-void bfa_tin_send_logout_rsp(void *bfa_tin, u32 logout_rsp,
-				struct fc_ls_rjt_s rjt_payload);
-/**
- * FCS target port statistics
- */
-struct bfa_tin_stats_s {
-	u32 onlines;	/*  ITN nexus onlines (PRLI done) */
-	u32 offlines;	/*  ITN Nexus offlines 	*/
-	u32 prli_req_parse_err;	/*  prli req parsing errors */
-	u32 prli_rsp_rjt;	/*  num prli rsp rejects sent */
-	u32 prli_rsp_acc;	/*  num prli rsp accepts sent */
-	u32 cleanup_comps;	/*  ITN cleanup completions */
-};
-
-/**
- * FCS tin attributes returned in queries
- */
-struct bfa_tin_attr_s {
-	enum bfa_tin_state_e state;
-	u8	seq_retry;    /*  Sequence retry supported      */
-	u8	rsvd[3];
-};
-
-/**
- * BFA TIN async event data structure for BFAL
- */
-enum bfa_tin_aen_event {
-	BFA_TIN_AEN_ONLINE 	= 1,	/*  Target online */
-	BFA_TIN_AEN_OFFLINE 	= 2,	/*  Target offline */
-	BFA_TIN_AEN_DISCONNECT	= 3,	/*  Target disconnected */
-};
-
-/**
- * BFA TIN event data structure.
- */
-struct bfa_tin_aen_data_s {
-	u16 vf_id;	/*  vf_id of the IT nexus */
-	u16 rsvd[3];
-	wwn_t lpwwn;	/*  WWN of logical port */
-	wwn_t rpwwn;	/*  WWN of remote(target) port */
-};
-
-/**
- * Below APIs are needed from BFA driver
- * Move these to BFA driver public header file?
- */
-/*  TIN rcvd new PRLI & gets bfad_tin_t ptr from driver this callback */
-void *bfad_tin_rcvd_login_req(void *bfad_tm_port, void *bfa_tin,
-				wwn_t rp_wwn, u32 rp_fcid,
-				struct bfa_prli_req_s prli_req);
-/*  TIN rcvd new PRLO */
-void bfad_tin_rcvd_logout_req(void *bfad_tin, wwn_t rp_wwn, u32 rp_fcid,
-				struct bfa_prlo_req_s prlo_req);
-/*  TIN is online and ready for IO */
-void bfad_tin_online(void *bfad_tin);
-/*  TIN is offline and BFA driver can shutdown its upper stack */
-void bfad_tin_offline(void *bfad_tin);
-/*  TIN does not need this BFA driver tin tag anymore, so can be freed */
-void bfad_tin_res_free(void *bfad_tin);
-
-#endif /* __BFA_DEFS_TIN_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h b/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h
deleted file mode 100644
index ade763db..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_TSENSOR_H__
-#define __BFA_DEFS_TSENSOR_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_types.h>
-
-/**
- * Temperature sensor status values
- */
-enum bfa_tsensor_status {
-	BFA_TSENSOR_STATUS_UNKNOWN   = 1,   /*  unknown status */
-	BFA_TSENSOR_STATUS_FAULTY    = 2,   /*  sensor is faulty */
-	BFA_TSENSOR_STATUS_BELOW_MIN = 3,   /*  temperature below mininum */
-	BFA_TSENSOR_STATUS_NOMINAL   = 4,   /*  normal temperature */
-	BFA_TSENSOR_STATUS_ABOVE_MAX = 5,   /*  temperature above maximum */
-};
-
-/**
- * Temperature sensor attribute
- */
-struct bfa_tsensor_attr_s {
-	enum bfa_tsensor_status status;	/*  temperature sensor status */
-	u32        	value;	/*  current temperature in celsius */
-};
-
-#endif /* __BFA_DEFS_TSENSOR_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_types.h b/drivers/scsi/bfa/include/defs/bfa_defs_types.h
deleted file mode 100644
index 4348332..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_types.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_TYPES_H__
-#define __BFA_DEFS_TYPES_H__
-
-#include <bfa_os_inc.h>
-
-enum bfa_boolean {
-	BFA_FALSE = 0,
-	BFA_TRUE  = 1
-};
-#define bfa_boolean_t enum bfa_boolean
-
-#define BFA_STRING_32	32
-
-#endif /* __BFA_DEFS_TYPES_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_version.h b/drivers/scsi/bfa/include/defs/bfa_defs_version.h
deleted file mode 100644
index f8902a2..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_version.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_VERSION_H__
-#define __BFA_DEFS_VERSION_H__
-
-#define BFA_VERSION_LEN		64
-
-#endif
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_vf.h b/drivers/scsi/bfa/include/defs/bfa_defs_vf.h
deleted file mode 100644
index 3235be5..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_vf.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_VF_H__
-#define __BFA_DEFS_VF_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_port.h>
-#include <protocol/types.h>
-
-/**
- * VF states
- */
-enum bfa_vf_state {
-	BFA_VF_UNINIT    = 0,	/*  fabric is not yet initialized */
-	BFA_VF_LINK_DOWN = 1,	/*  link is down */
-	BFA_VF_FLOGI     = 2,	/*  flogi is in progress */
-	BFA_VF_AUTH      = 3,	/*  authentication in progress */
-	BFA_VF_NOFABRIC  = 4,	/*  fabric is not present */
-	BFA_VF_ONLINE    = 5,	/*  login to fabric is complete */
-	BFA_VF_EVFP      = 6,	/*  EVFP is in progress */
-	BFA_VF_ISOLATED  = 7,	/*  port isolated due to vf_id mismatch */
-};
-
-/**
- * VF statistics
- */
-struct bfa_vf_stats_s {
-	u32        flogi_sent;	/*  Num FLOGIs sent 		*/
-	u32        flogi_rsp_err;	/*  FLOGI response errors 	*/
-	u32        flogi_acc_err;	/*  FLOGI accept errors 	*/
-	u32        flogi_accepts;	/*  FLOGI accepts received 	*/
-	u32        flogi_rejects;	/*  FLOGI rejects received 	*/
-	u32        flogi_unknown_rsp; /*  Unknown responses for FLOGI */
-	u32        flogi_alloc_wait; /*  Allocation waits prior to
-					   * sending FLOGI
-					   */
-	u32        flogi_rcvd;	/*  FLOGIs received */
-	u32        flogi_rejected;	/*  Incoming FLOGIs rejected */
-	u32        fabric_onlines;	/*  Internal fabric online
-					 * notification sent to other
-					 * modules
-					 */
-	u32        fabric_offlines; /*  Internal fabric offline
-					  * notification sent to other
-					  * modules
-					  */
-	u32        resvd;
-};
-
-/**
- * VF attributes returned in queries
- */
-struct bfa_vf_attr_s {
-	enum bfa_vf_state  state;		/*  VF state */
-	u32        rsvd;
-	wwn_t           fabric_name;	/*  fabric name */
-};
-
-#endif /* __BFA_DEFS_VF_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_vport.h b/drivers/scsi/bfa/include/defs/bfa_defs_vport.h
deleted file mode 100644
index 9f021f4..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_vport.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_VPORT_H__
-#define __BFA_DEFS_VPORT_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_port.h>
-#include <protocol/types.h>
-
-/**
- * VPORT states
- */
-enum bfa_vport_state {
-	BFA_FCS_VPORT_UNINIT 		= 0,
-	BFA_FCS_VPORT_CREATED 		= 1,
-	BFA_FCS_VPORT_OFFLINE 		= 1,
-	BFA_FCS_VPORT_FDISC_SEND 	= 2,
-	BFA_FCS_VPORT_FDISC 		= 3,
-	BFA_FCS_VPORT_FDISC_RETRY 	= 4,
-	BFA_FCS_VPORT_ONLINE 		= 5,
-	BFA_FCS_VPORT_DELETING 		= 6,
-	BFA_FCS_VPORT_CLEANUP 		= 6,
-	BFA_FCS_VPORT_LOGO_SEND 	= 7,
-	BFA_FCS_VPORT_LOGO 			= 8,
-	BFA_FCS_VPORT_ERROR			= 9,
-	BFA_FCS_VPORT_MAX_STATE,
-};
-
-/**
- * vport statistics
- */
-struct bfa_vport_stats_s {
-	struct bfa_port_stats_s port_stats;	/*  base class (port) stats */
-	/*
-	 * TODO - remove
-	 */
-
-	u32        fdisc_sent;	/*  num fdisc sent */
-	u32        fdisc_accepts;	/*  fdisc accepts */
-	u32        fdisc_retries;	/*  fdisc retries */
-	u32        fdisc_timeouts;	/*  fdisc timeouts */
-	u32        fdisc_rsp_err;	/*  fdisc response error */
-	u32        fdisc_acc_bad;	/*  bad fdisc accepts */
-	u32        fdisc_rejects;	/*  fdisc rejects */
-	u32        fdisc_unknown_rsp;
-	/*
-	 *!< fdisc rsp unknown error
-	 */
-	u32        fdisc_alloc_wait;/*  fdisc req (fcxp)alloc wait */
-
-	u32        logo_alloc_wait;/*  logo req (fcxp) alloc wait */
-	u32        logo_sent;	/*  logo sent */
-	u32        logo_accepts;	/*  logo accepts */
-	u32        logo_rejects;	/*  logo rejects */
-	u32        logo_rsp_err;	/*  logo rsp errors */
-	u32        logo_unknown_rsp;
-			/*  logo rsp unknown errors */
-
-	u32        fab_no_npiv;	/*  fabric does not support npiv */
-
-	u32        fab_offline;	/*  offline events from fab SM */
-	u32        fab_online;	/*  online events from fab SM */
-	u32        fab_cleanup;	/*  cleanup request from fab SM */
-	u32        rsvd;
-};
-
-/**
- * BFA vport attribute returned in queries
- */
-struct bfa_vport_attr_s {
-	struct bfa_port_attr_s   port_attr; /*  base class (port) attributes */
-	enum bfa_vport_state vport_state; /*  vport state */
-	u32          rsvd;
-};
-
-#endif /* __BFA_DEFS_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb.h b/drivers/scsi/bfa/include/fcb/bfa_fcb.h
deleted file mode 100644
index 2963b0b..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcb.h BFA FCS callback interfaces
- */
-
-#ifndef __BFA_FCB_H__
-#define __BFA_FCB_H__
-
-/**
- *  fcb Main fcs callbacks
- */
-
-void bfa_fcb_exit(struct bfad_s *bfad);
-
-
-
-#endif /* __BFA_FCB_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h
deleted file mode 100644
index 52585d3..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
-* : bfad_fcpim.h - BFA FCS initiator mode remote port callbacks
- */
-
-#ifndef __BFAD_FCB_FCPIM_H__
-#define __BFAD_FCB_FCPIM_H__
-
-struct bfad_itnim_s;
-
-/*
- * RPIM callbacks
- */
-
-/**
- * 	Memory allocation for remote port instance. Called before PRLI is
- * 	initiated to the remote target port.
- *
- * @param[in] bfad		- driver instance
- * @param[out] itnim		- FCS remote port (IM) instance
- * @param[out] itnim_drv	- driver remote port (IM) instance
- *
- * @return None
- */
-void bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim,
-				    struct bfad_itnim_s **itnim_drv);
-
-/**
- * 		Free remote port (IM) instance.
- *
- * @param[in] bfad	- driver instance
- * @param[in] itnim_drv	- driver remote port instance
- *
- * @return None
- */
-void            bfa_fcb_itnim_free(struct bfad_s *bfad,
-				   struct bfad_itnim_s *itnim_drv);
-
-/**
- * 	Notification of when login with a remote target device is complete.
- *
- * @param[in] itnim_drv	- driver remote port instance
- *
- * @return None
- */
-void            bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv);
-
-/**
- * 	Notification when login with the remote device is severed.
- *
- * @param[in] itnim_drv	- driver remote port instance
- *
- * @return None
- */
-void            bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv);
-
-void            bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim_drv);
-
-#endif /* __BFAD_FCB_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h
deleted file mode 100644
index 5fd7f98..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcb_port.h BFA FCS virtual port driver interfaces
- */
-
-#ifndef __BFA_FCB_PORT_H__
-#define __BFA_FCB_PORT_H__
-
-#include <fcb/bfa_fcb_vport.h>
-/**
- *  fcs_port_fcb FCS port driver interfaces
- */
-
-/*
- * Forward declarations
- */
-struct bfad_port_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * 	Call from FCS to driver module when a port is instantiated. The port
- * 	can be a base port or a virtual port with in the base fabric or
- * 	a virtual fabric.
- *
- *  On this callback, driver is supposed to create scsi_host, scsi_tgt or
- *  network interfaces bases on ports personality/roles.
- *
- *      base port of base fabric:	vf_drv == NULL && vp_drv == NULL
- *      vport of base fabric:		vf_drv == NULL && vp_drv != NULL
- *      base port of VF:		vf_drv != NULL && vp_drv == NULL
- *      vport of VF:			vf_drv != NULL && vp_drv != NULL
- *
- * @param[in] bfad   - driver instance
- * @param[in] port   - FCS port instance
- * @param[in] roles  - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-struct bfad_port_s *bfa_fcb_port_new(struct bfad_s *bfad,
-			struct bfa_fcs_port_s *port,
-			enum bfa_port_role roles, struct bfad_vf_s *vf_drv,
-			struct bfad_vport_s *vp_drv);
-
-/**
- * 	Call from FCS to driver module when a port is deleted. The port
- * 	can be a base port or a virtual port with in the base fabric or
- * 	a virtual fabric.
- *
- * @param[in] bfad   - driver instance
- * @param[in] roles  - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-void bfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles,
-			struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
-
-/**
- * 	Notification when port transitions to ONLINE state.
- *
- * Online notification is a logical link up for the local port. This
- * notification is sent after a successfull FLOGI, or a successful
- * link initialization in proviate-loop or N2N topologies.
- *
- * @param[in] bfad   - driver instance
- * @param[in] roles  - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-void bfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles,
-			struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
-
-/**
- * 	Notification when port transitions to OFFLINE state.
- *
- * Offline notification is a logical link down for the local port.
- *
- * @param[in] bfad   - driver instance
- * @param[in] roles  - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-void bfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles,
-			struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
-
-
-#endif /* __BFA_FCB_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h
deleted file mode 100644
index e0261bb..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcb_rport.h BFA FCS rport driver interfaces
- */
-
-#ifndef __BFA_FCB_RPORT_H__
-#define __BFA_FCB_RPORT_H__
-
-/**
- *  fcs_rport_fcb Remote port driver interfaces
- */
-
-
-struct bfad_rport_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * 	Completion callback for bfa_fcs_rport_add().
- *
- * @param[in] rport_drv - driver instance of rport
- *
- * @return None
- */
-void bfa_fcb_rport_add(struct bfad_rport_s *rport_drv);
-
-/**
- * 	Completion callback for bfa_fcs_rport_remove().
- *
- * @param[in] rport_drv - driver instance of rport
- *
- * @return None
- */
-void bfa_fcb_rport_remove(struct bfad_rport_s *rport_drv);
-
-/**
- * 		Call to allocate a rport instance.
- *
- * @param[in] bfad - driver instance
- * @param[out] rport - BFA FCS instance of rport
- * @param[out] rport_drv - driver instance of rport
- *
- * @retval BFA_STATUS_OK - successfully allocated
- * @retval BFA_STATUS_ENOMEM - cannot allocate
- */
-bfa_status_t bfa_fcb_rport_alloc(struct bfad_s *bfad,
-			struct bfa_fcs_rport_s **rport,
-			struct bfad_rport_s **rport_drv);
-
-/**
- * 	Call to free rport memory resources.
- *
- * @param[in] bfad - driver instance
- * @param[in] rport_drv - driver instance of rport
- *
- * @return None
- */
-void bfa_fcb_rport_free(struct bfad_s *bfad, struct bfad_rport_s **rport_drv);
-
-
-
-#endif /* __BFA_FCB_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h
deleted file mode 100644
index cfd3fac..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcb_vf.h BFA FCS virtual fabric driver interfaces
- */
-
-#ifndef __BFA_FCB_VF_H__
-#define __BFA_FCB_VF_H__
-
-/**
- *  fcs_vf_fcb Virtual fabric driver intrefaces
- */
-
-
-struct bfad_vf_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * 	Completion callback for bfa_fcs_vf_stop().
- *
- * @param[in] vf_drv - driver instance of vf
- *
- * @return None
- */
-void            bfa_fcb_vf_stop(struct bfad_vf_s *vf_drv);
-
-
-
-#endif /* __BFA_FCB_VF_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h
deleted file mode 100644
index cfd6ba7..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcb_vport.h BFA FCS virtual port driver interfaces
- */
-
-#ifndef __BFA_FCB_VPORT_H__
-#define __BFA_FCB_VPORT_H__
-
-/**
- *  fcs_vport_fcb Virtual port driver interfaces
- */
-
-
-struct bfad_vport_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * 	Completion callback for bfa_fcs_vport_delete().
- *
- * @param[in] vport_drv - driver instance of vport
- *
- * @return None
- */
-void bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv);
-void bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s);
-
-
-
-#endif /* __BFA_FCB_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs.h b/drivers/scsi/bfa/include/fcs/bfa_fcs.h
deleted file mode 100644
index 54e5b81..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCS_H__
-#define __BFA_FCS_H__
-
-#include <cs/bfa_debug.h>
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_version.h>
-#include <bfa.h>
-#include <fcs/bfa_fcs_fabric.h>
-
-#define BFA_FCS_OS_STR_LEN  		64
-
-struct bfa_fcs_stats_s {
-	struct {
-		u32        untagged; /*  untagged receive frames */
-		u32        tagged;	/*  tagged receive frames */
-		u32        vfid_unknown;	/*  VF id is unknown */
-	} uf;
-};
-
-struct bfa_fcs_driver_info_s {
-	u8  version[BFA_VERSION_LEN];		/*  Driver Version */
-	u8  host_machine_name[BFA_FCS_OS_STR_LEN];
-	u8  host_os_name[BFA_FCS_OS_STR_LEN]; /*  OS name and version */
-	u8  host_os_patch[BFA_FCS_OS_STR_LEN];/*  patch or service pack */
-	u8  os_device_name[BFA_FCS_OS_STR_LEN]; /*  Driver Device Name */
-};
-
-struct bfa_fcs_s {
-	struct bfa_s      *bfa;	/*  corresponding BFA bfa instance */
-	struct bfad_s         *bfad; /*  corresponding BDA driver instance */
-	struct bfa_log_mod_s  *logm;	/*  driver logging module instance */
-	struct bfa_trc_mod_s  *trcmod;	/*  tracing module */
-	struct bfa_aen_s      *aen;	/*  aen component */
-	bfa_boolean_t   vf_enabled;	/*  VF mode is enabled */
-	bfa_boolean_t   fdmi_enabled;   /*!< FDMI is enabled */
-	bfa_boolean_t min_cfg;		/* min cfg enabled/disabled */
-	u16        port_vfid;	/*  port default VF ID */
-	struct bfa_fcs_driver_info_s driver_info;
-	struct bfa_fcs_fabric_s fabric; /*  base fabric state machine */
-	struct bfa_fcs_stats_s	stats;	/*  FCS statistics */
-	struct bfa_wc_s       	wc;	/*  waiting counter */
-};
-
-/*
- * bfa fcs API functions
- */
-void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,
-			struct bfad_s *bfad, bfa_boolean_t min_cfg);
-void bfa_fcs_init(struct bfa_fcs_s *fcs);
-void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
-			struct bfa_fcs_driver_info_s *driver_info);
-void bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable);
-void bfa_fcs_exit(struct bfa_fcs_s *fcs);
-void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod);
-void bfa_fcs_log_init(struct bfa_fcs_s *fcs, struct bfa_log_mod_s *logmod);
-void bfa_fcs_aen_init(struct bfa_fcs_s *fcs, struct bfa_aen_s *aen);
-void 	  	bfa_fcs_start(struct bfa_fcs_s *fcs);
-
-#endif /* __BFA_FCS_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h
deleted file mode 100644
index 28c4c9f..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCS_AUTH_H__
-#define __BFA_FCS_AUTH_H__
-
-struct bfa_fcs_s;
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_auth.h>
-#include <defs/bfa_defs_vf.h>
-#include <cs/bfa_q.h>
-#include <cs/bfa_sm.h>
-#include <defs/bfa_defs_pport.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <protocol/fc_sp.h>
-
-struct bfa_fcs_fabric_s;
-
-
-
-struct bfa_fcs_auth_s {
-	bfa_sm_t	sm;	/*  state machine */
-	bfa_boolean_t   policy;	/*  authentication enabled/disabled */
-	enum bfa_auth_status status;	/*  authentication status */
-	enum auth_rjt_codes  rjt_code;	/*  auth reject status */
-	enum auth_rjt_code_exps  rjt_code_exp;	/*  auth reject reason */
-	enum bfa_auth_algo algo;	/*  Authentication algorithm */
-	struct bfa_auth_stats_s stats;	/*  Statistics */
-	enum auth_dh_gid   group;	/*  DH(diffie-hellman) Group */
-	enum bfa_auth_secretsource source;	/*  Secret source */
-	char            secret[BFA_AUTH_SECRET_STRING_LEN];
-				/*  secret string */
-	u8         secret_len;
-				/*  secret string length */
-	u8         nretries;
-				/*  number of retries */
-	struct bfa_fcs_fabric_s *fabric;/*  pointer to fabric */
-	u8         sentcode;	/*  pointer to response data */
-	u8        *response;	/*  pointer to response data */
-	struct bfa_timer_s delay_timer; 	/*  delay timer */
-	struct bfa_fcxp_s *fcxp;		/*  pointer to fcxp */
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-};
-
-/**
- * bfa fcs authentication public functions
- */
-bfa_status_t    bfa_fcs_auth_get_attr(struct bfa_fcs_s *port,
-				      struct bfa_auth_attr_s *attr);
-bfa_status_t    bfa_fcs_auth_set_policy(struct bfa_fcs_s *port,
-					bfa_boolean_t policy);
-enum bfa_auth_status bfa_fcs_auth_get_status(struct bfa_fcs_s *port);
-bfa_status_t    bfa_fcs_auth_set_algo(struct bfa_fcs_s *port,
-				      enum bfa_auth_algo algo);
-bfa_status_t    bfa_fcs_auth_get_stats(struct bfa_fcs_s *port,
-				       struct bfa_auth_stats_s *stats);
-bfa_status_t    bfa_fcs_auth_set_dh_group(struct bfa_fcs_s *port, int group);
-bfa_status_t    bfa_fcs_auth_set_secretstring(struct bfa_fcs_s *port,
-					      char *secret);
-bfa_status_t    bfa_fcs_auth_set_secretstring_encrypt(struct bfa_fcs_s *port,
-					      u32 secret[], u32 len);
-bfa_status_t    bfa_fcs_auth_set_secretsource(struct bfa_fcs_s *port,
-					      enum bfa_auth_secretsource src);
-bfa_status_t    bfa_fcs_auth_reset_stats(struct bfa_fcs_s *port);
-bfa_status_t    bfa_fcs_auth_reinit(struct bfa_fcs_s *port);
-
-#endif /* __BFA_FCS_AUTH_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h
deleted file mode 100644
index 08b79d5..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCS_FABRIC_H__
-#define __BFA_FCS_FABRIC_H__
-
-struct bfa_fcs_s;
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_vf.h>
-#include <cs/bfa_q.h>
-#include <cs/bfa_sm.h>
-#include <defs/bfa_defs_pport.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <protocol/fc_sp.h>
-#include <fcs/bfa_fcs_auth.h>
-
-/*
- * forward declaration
- */
-struct bfad_vf_s;
-
-enum bfa_fcs_fabric_type {
-	BFA_FCS_FABRIC_UNKNOWN = 0,
-	BFA_FCS_FABRIC_SWITCHED = 1,
-	BFA_FCS_FABRIC_PLOOP = 2,
-	BFA_FCS_FABRIC_N2N = 3,
-};
-
-
-struct bfa_fcs_fabric_s {
-	struct list_head   qe;		/*  queue element */
-	bfa_sm_t	 sm;		/*  state machine */
-	struct bfa_fcs_s *fcs;		/*  FCS instance */
-	struct bfa_fcs_port_s  bport;	/*  base logical port */
-	enum bfa_fcs_fabric_type fab_type; /*  fabric type */
-	enum bfa_pport_type oper_type;	/*  current link topology */
-	u8         is_vf;		/*  is virtual fabric? */
-	u8         is_npiv;	/*  is NPIV supported ? */
-	u8         is_auth;	/*  is Security/Auth supported ? */
-	u16        bb_credit;	/*  BB credit from fabric */
-	u16        vf_id;		/*  virtual fabric ID */
-	u16        num_vports;	/*  num vports */
-	u16        rsvd;
-	struct list_head         vport_q;	/*  queue of virtual ports */
-	struct list_head         vf_q;	/*  queue of virtual fabrics */
-	struct bfad_vf_s      *vf_drv;	/*  driver vf structure */
-	struct bfa_timer_s link_timer;	/*  Link Failure timer. Vport */
-	wwn_t           fabric_name;	/*  attached fabric name */
-	bfa_boolean_t   auth_reqd;	/*  authentication required	*/
-	struct bfa_timer_s delay_timer;	/*  delay timer		*/
-	union {
-		u16        swp_vfid;/*  switch port VF id		*/
-	} event_arg;
-	struct bfa_fcs_auth_s  auth;	/*  authentication config	*/
-	struct bfa_wc_s        wc;	/*  wait counter for delete	*/
-	struct bfa_vf_stats_s  stats; 	/*  fabric/vf stats		*/
-	struct bfa_lps_s	*lps;	/*  lport login services	*/
-	u8	fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ];  /*  attached
-							    * fabric's ip addr
-							    */
-};
-
-#define bfa_fcs_fabric_npiv_capable(__f)    ((__f)->is_npiv)
-#define bfa_fcs_fabric_is_switched(__f)			\
-	((__f)->fab_type == BFA_FCS_FABRIC_SWITCHED)
-
-/**
- *   The design calls for a single implementation of base fabric and vf.
- */
-#define bfa_fcs_vf_t struct bfa_fcs_fabric_s
-
-struct bfa_vf_event_s {
-	u32        undefined;
-};
-
-/**
- * bfa fcs vf public functions
- */
-bfa_status_t bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id);
-bfa_status_t bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs);
-bfa_status_t bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs,
-			       u16 vf_id, struct bfa_port_cfg_s *port_cfg,
-			       struct bfad_vf_s *vf_drv);
-bfa_status_t bfa_fcs_vf_delete(bfa_fcs_vf_t *vf);
-void bfa_fcs_vf_start(bfa_fcs_vf_t *vf);
-bfa_status_t bfa_fcs_vf_stop(bfa_fcs_vf_t *vf);
-void bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
-void bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
-void bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr);
-void bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf,
-			  struct bfa_vf_stats_s *vf_stats);
-void bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf);
-void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
-bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
-struct bfad_vf_s *bfa_fcs_vf_get_drv_vf(bfa_fcs_vf_t *vf);
-
-#endif /* __BFA_FCS_FABRIC_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h
deleted file mode 100644
index 9a35ecf..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcs_fcpim.h BFA FCS FCP Initiator Mode interfaces/defines.
- */
-
-#ifndef __BFA_FCS_FCPIM_H__
-#define __BFA_FCS_FCPIM_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_itnim.h>
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <bfa_fcpim.h>
-
-/*
- * forward declarations
- */
-struct bfad_itnim_s;
-
-struct bfa_fcs_itnim_s {
-	bfa_sm_t		sm;		/*  state machine */
-	struct bfa_fcs_rport_s 	*rport;		/*  parent remote rport  */
-	struct bfad_itnim_s   	*itnim_drv;	/*  driver peer instance */
-	struct bfa_fcs_s      	*fcs;		/*  fcs instance         */
-	struct bfa_timer_s 	timer;		/*  timer functions      */
-	struct bfa_itnim_s 	*bfa_itnim;	/*  BFA itnim struct     */
-	u32                	prli_retries;   /*  max prli retry attempts */
-	bfa_boolean_t	 	seq_rec;	/*  seq recovery support */
-	bfa_boolean_t	 	rec_support;	/*  REC supported        */
-	bfa_boolean_t	 	conf_comp;	/*  FCP_CONF     support */
-	bfa_boolean_t	 	task_retry_id;	/*  task retry id supp   */
-	struct bfa_fcxp_wqe_s 	fcxp_wqe;	/*  wait qelem for fcxp  */
-	struct bfa_fcxp_s *fcxp;		/*  FCXP in use          */
-	struct bfa_itnim_stats_s 	stats;	/*  itn statistics       */
-};
-
-
-static inline struct bfad_port_s *
-bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->port->bfad_port;
-}
-
-
-static inline struct bfa_fcs_port_s *
-bfa_fcs_itnim_get_port(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->port;
-}
-
-
-static inline wwn_t
-bfa_fcs_itnim_get_nwwn(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->nwwn;
-}
-
-
-static inline wwn_t
-bfa_fcs_itnim_get_pwwn(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->pwwn;
-}
-
-
-static inline u32
-bfa_fcs_itnim_get_fcid(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->pid;
-}
-
-
-static inline   u32
-bfa_fcs_itnim_get_maxfrsize(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->maxfrsize;
-}
-
-
-static inline   enum fc_cos
-bfa_fcs_itnim_get_cos(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->fc_cos;
-}
-
-
-static inline struct bfad_itnim_s *
-bfa_fcs_itnim_get_drvitn(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->itnim_drv;
-}
-
-
-static inline struct bfa_itnim_s *
-bfa_fcs_itnim_get_halitn(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->bfa_itnim;
-}
-
-/**
- * bfa fcs FCP Initiator mode API functions
- */
-void bfa_fcs_itnim_get_attr(struct bfa_fcs_itnim_s *itnim,
-			struct bfa_itnim_attr_s *attr);
-void bfa_fcs_itnim_get_stats(struct bfa_fcs_itnim_s *itnim,
-			struct bfa_itnim_stats_s *stats);
-struct bfa_fcs_itnim_s *bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port,
-			wwn_t rpwwn);
-bfa_status_t bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
-			struct bfa_itnim_attr_s *attr);
-bfa_status_t bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
-			struct bfa_itnim_stats_s *stats);
-bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port,
-			wwn_t rpwwn);
-#endif /* __BFA_FCS_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h
deleted file mode 100644
index 4441fff..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcs_fdmi.h BFA fcs fdmi module public interface
- */
-
-#ifndef __BFA_FCS_FDMI_H__
-#define __BFA_FCS_FDMI_H__
-#include <bfa_os_inc.h>
-#include <protocol/fdmi.h>
-
-#define	BFA_FCS_FDMI_SUPORTED_SPEEDS  (FDMI_TRANS_SPEED_1G  | \
-					FDMI_TRANS_SPEED_2G | \
-					FDMI_TRANS_SPEED_4G | \
-					FDMI_TRANS_SPEED_8G)
-
-/*
-* HBA Attribute Block : BFA internal representation. Note : Some variable
-* sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based
- * on this the size has been reduced to 16 bytes from the standard's 64 bytes.
- */
-struct bfa_fcs_fdmi_hba_attr_s {
-	wwn_t           node_name;
-	u8         manufacturer[64];
-	u8         serial_num[64];
-	u8         model[16];
-	u8         model_desc[256];
-	u8         hw_version[8];
-	u8         driver_version[8];
-	u8         option_rom_ver[BFA_VERSION_LEN];
-	u8         fw_version[8];
-	u8         os_name[256];
-	u32        max_ct_pyld;
-};
-
-/*
- * Port Attribute Block
- */
-struct bfa_fcs_fdmi_port_attr_s {
-	u8         supp_fc4_types[32];	/* supported FC4 types */
-	u32        supp_speed;	/* supported speed */
-	u32        curr_speed;	/* current Speed */
-	u32        max_frm_size;	/* max frame size */
-	u8         os_device_name[256];	/* OS device Name */
-	u8         host_name[256];	/* host name */
-};
-
-#endif /* __BFA_FCS_FDMI_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h
deleted file mode 100644
index ceaefd3..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcs_port.h BFA fcs port module public interface
- */
-
-#ifndef __BFA_FCS_PORT_H__
-#define __BFA_FCS_PORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_rport.h>
-#include <cs/bfa_q.h>
-#include <bfa_svc.h>
-#include <cs/bfa_wc.h>
-
-struct bfa_fcs_s;
-struct bfa_fcs_fabric_s;
-
-/*
- * Maximum Rports supported per port (physical/logical).
- */
-#define BFA_FCS_MAX_RPORTS_SUPP  256	/* @todo : tentative value */
-
-
-struct bfa_fcs_port_ns_s {
-	bfa_sm_t        sm;		/*  state machine */
-	struct bfa_timer_s timer;
-	struct bfa_fcs_port_s *port;	/*  parent port */
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-};
-
-
-struct bfa_fcs_port_scn_s {
-	bfa_sm_t        sm;		/*  state machine */
-	struct bfa_timer_s timer;
-	struct bfa_fcs_port_s *port;	/*  parent port */
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-};
-
-
-struct bfa_fcs_port_fdmi_s {
-	bfa_sm_t        sm;		/*  state machine */
-	struct bfa_timer_s timer;
-	struct bfa_fcs_port_ms_s *ms;	/*  parent ms */
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-	u8         retry_cnt;	/*  retry count */
-	u8	 	   rsvd[3];
-};
-
-
-struct bfa_fcs_port_ms_s {
-	bfa_sm_t        sm;		/*  state machine */
-	struct bfa_timer_s timer;
-	struct bfa_fcs_port_s *port;	/*  parent port */
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-	struct bfa_fcs_port_fdmi_s fdmi;	/*  FDMI component of MS */
-	u8         retry_cnt;	/*  retry count */
-	u8	 	   rsvd[3];
-};
-
-
-struct bfa_fcs_port_fab_s {
-	struct bfa_fcs_port_ns_s ns;	/*  NS component of port */
-	struct bfa_fcs_port_scn_s scn;	/*  scn component of port */
-	struct bfa_fcs_port_ms_s ms;	/*  MS component of port */
-};
-
-
-
-#define 	MAX_ALPA_COUNT 		127
-
-struct bfa_fcs_port_loop_s {
-	u8         num_alpa;	/*  Num of ALPA entries in the map */
-	u8         alpa_pos_map[MAX_ALPA_COUNT];	/*  ALPA Positional
-							 *Map */
-	struct bfa_fcs_port_s *port;	/*  parent port */
-};
-
-
-
-struct bfa_fcs_port_n2n_s {
-	u32        rsvd;
-	u16        reply_oxid;	/*  ox_id from the req flogi to be
-					 *used in flogi acc */
-	wwn_t           rem_port_wwn;	/*  Attached port's wwn */
-};
-
-
-union bfa_fcs_port_topo_u {
-	struct bfa_fcs_port_fab_s pfab;
-	struct bfa_fcs_port_loop_s ploop;
-	struct bfa_fcs_port_n2n_s pn2n;
-};
-
-
-struct bfa_fcs_port_s {
-	struct list_head         qe;	/*  used by port/vport */
-	bfa_sm_t               sm;	/*  state machine */
-	struct bfa_fcs_fabric_s *fabric;/*  parent fabric */
-	struct bfa_port_cfg_s  port_cfg;/*  port configuration */
-	struct bfa_timer_s link_timer;	/*  timer for link offline */
-	u32 pid:24;	/*  FC address */
-	u8  lp_tag;	/*  lport tag */
-	u16 num_rports;	/*  Num of r-ports */
-	struct list_head rport_q;	/*  queue of discovered r-ports */
-	struct bfa_fcs_s *fcs;	/*  FCS instance */
-	union bfa_fcs_port_topo_u port_topo;	/*  fabric/loop/n2n details */
-	struct bfad_port_s *bfad_port;	/*  driver peer instance */
-	struct bfa_fcs_vport_s *vport;	/*  NULL for base ports */
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-	struct bfa_port_stats_s stats;
-	struct bfa_wc_s        wc;	/*  waiting counter for events */
-};
-
-#define bfa_fcs_lport_t struct bfa_fcs_port_s
-
-/**
- * Symbolic Name related defines
- *  Total bytes 255.
- *  Physical Port's symbolic name 128 bytes.
- *  For Vports, Vport's symbolic name is appended to the Physical port's
- *  Symbolic Name.
- *
- *  Physical Port's symbolic name Format : (Total 128 bytes)
- *  Adapter Model number/name : 12 bytes
- *  Driver Version     : 10 bytes
- *  Host Machine Name  : 30 bytes
- * 	Host OS Info	   : 48 bytes
- * 	Host OS PATCH Info : 16 bytes
- *  ( remaining 12 bytes reserved to be used for separator)
- */
-#define BFA_FCS_PORT_SYMBNAME_SEPARATOR 		" | "
-
-#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ			12
-#define BFA_FCS_PORT_SYMBNAME_VERSION_SZ 		10
-#define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ 	30
-#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ			48
-#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ		16
-
-/**
- * Get FC port ID for a logical port.
- */
-#define bfa_fcs_port_get_fcid(_lport)	((_lport)->pid)
-#define bfa_fcs_port_get_pwwn(_lport)	((_lport)->port_cfg.pwwn)
-#define bfa_fcs_port_get_nwwn(_lport)	((_lport)->port_cfg.nwwn)
-#define bfa_fcs_port_get_psym_name(_lport)	((_lport)->port_cfg.sym_name)
-#define bfa_fcs_port_is_initiator(_lport)	\
-			((_lport)->port_cfg.roles & BFA_PORT_ROLE_FCP_IM)
-#define bfa_fcs_port_is_target(_lport)	\
-			((_lport)->port_cfg.roles & BFA_PORT_ROLE_FCP_TM)
-#define bfa_fcs_port_get_nrports(_lport)	\
-			((_lport) ? (_lport)->num_rports : 0)
-
-static inline struct bfad_port_s *
-bfa_fcs_port_get_drvport(struct bfa_fcs_port_s *port)
-{
-	return port->bfad_port;
-}
-
-
-#define bfa_fcs_port_get_opertype(_lport)	((_lport)->fabric->oper_type)
-
-
-#define bfa_fcs_port_get_fabric_name(_lport)	((_lport)->fabric->fabric_name)
-
-
-#define bfa_fcs_port_get_fabric_ipaddr(_lport) \
-		((_lport)->fabric->fabric_ip_addr)
-
-/**
- * bfa fcs port public functions
- */
-void bfa_fcs_cfg_base_port(struct bfa_fcs_s *fcs,
-			struct bfa_port_cfg_s *port_cfg);
-struct bfa_fcs_port_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs);
-void bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port,
-			wwn_t rport_wwns[], int *nrports);
-
-wwn_t bfa_fcs_port_get_rport(struct bfa_fcs_port_s *port, wwn_t wwn,
-			int index, int nrports, bfa_boolean_t bwwn);
-
-struct bfa_fcs_port_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,
-			u16 vf_id, wwn_t lpwwn);
-
-void bfa_fcs_port_get_info(struct bfa_fcs_port_s *port,
-			struct bfa_port_info_s *port_info);
-void bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
-			struct bfa_port_attr_s *port_attr);
-void bfa_fcs_port_get_stats(struct bfa_fcs_port_s *fcs_port,
-			struct bfa_port_stats_s *port_stats);
-void bfa_fcs_port_clear_stats(struct bfa_fcs_port_s *fcs_port);
-enum bfa_pport_speed bfa_fcs_port_get_rport_max_speed(
-			struct bfa_fcs_port_s *port);
-void bfa_fcs_port_enable_ipfc_roles(struct bfa_fcs_port_s *fcs_port);
-void bfa_fcs_port_disable_ipfc_roles(struct bfa_fcs_port_s *fcs_port);
-
-#endif /* __BFA_FCS_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h
deleted file mode 100644
index 3027fc6..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCS_RPORT_H__
-#define __BFA_FCS_RPORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <cs/bfa_q.h>
-#include <fcs/bfa_fcs.h>
-#include <defs/bfa_defs_rport.h>
-
-#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT 	90 	/* in secs */
-/*
- * forward declarations
- */
-struct bfad_rport_s;
-
-struct bfa_fcs_itnim_s;
-struct bfa_fcs_tin_s;
-struct bfa_fcs_iprp_s;
-
-/* Rport Features (RPF) */
-struct bfa_fcs_rpf_s {
-	bfa_sm_t               sm;	/*  state machine */
-	struct bfa_fcs_rport_s *rport;	/*  parent rport */
-	struct bfa_timer_s 	timer;	/*  general purpose timer */
-	struct bfa_fcxp_s 	*fcxp;	/*  FCXP needed for discarding */
-	struct bfa_fcxp_wqe_s 	fcxp_wqe;	/*  fcxp wait queue element */
-	int             	rpsc_retries;	/*  max RPSC retry attempts */
-	enum bfa_pport_speed 	rpsc_speed;	/* Current Speed from RPSC.
-						 * O if RPSC fails */
-	enum bfa_pport_speed	assigned_speed;	/* Speed assigned by the user.
-						 * will be used if RPSC is not
-						 * supported by the rport */
-};
-
-struct bfa_fcs_rport_s {
-	struct list_head         qe;	/*  used by port/vport */
-	struct bfa_fcs_port_s *port;	/*  parent FCS port */
-	struct bfa_fcs_s      *fcs;	/*  fcs instance */
-	struct bfad_rport_s   *rp_drv;	/*  driver peer instance */
-	u32        pid;	/*  port ID of rport */
-	u16        maxfrsize;	/*  maximum frame size */
-	u16        reply_oxid;	/*  OX_ID of inbound requests */
-	enum fc_cos        fc_cos;	/*  FC classes of service supp */
-	bfa_boolean_t   cisc;	/*  CISC capable device */
-	bfa_boolean_t   prlo;   /*  processing prlo or LOGO */
-	wwn_t           pwwn;	/*  port wwn of rport */
-	wwn_t           nwwn;	/*  node wwn of rport */
-	struct bfa_rport_symname_s psym_name; /*  port symbolic name  */
-	bfa_sm_t        sm;		/*  state machine */
-	struct bfa_timer_s timer;	/*  general purpose timer */
-	struct bfa_fcs_itnim_s *itnim;	/*  ITN initiator mode role */
-	struct bfa_fcs_tin_s *tin;	/*  ITN initiator mode role */
-	struct bfa_fcs_iprp_s *iprp;	/*  IP/FC role */
-	struct bfa_rport_s *bfa_rport;	/*  BFA Rport */
-	struct bfa_fcxp_s *fcxp;	/*  FCXP needed for discarding */
-	int             plogi_retries;	/*  max plogi retry attempts */
-	int             ns_retries;	/*  max NS query retry attempts */
-	struct bfa_fcxp_wqe_s 	fcxp_wqe; /*  fcxp wait queue element */
-	struct bfa_rport_stats_s stats;	/*  rport stats */
-	enum bfa_rport_function	scsi_function;  /*  Initiator/Target */
-	struct bfa_fcs_rpf_s rpf; 	/* Rport features module */
-};
-
-static inline struct bfa_rport_s *
-bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)
-{
-	return rport->bfa_rport;
-}
-
-/**
- * bfa fcs rport API functions
- */
-bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_port_s *port, wwn_t *pwwn,
-			struct bfa_fcs_rport_s *rport,
-			struct bfad_rport_s *rport_drv);
-bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
-			struct bfa_rport_attr_s *attr);
-void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
-			struct bfa_rport_stats_s *stats);
-void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport);
-struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_port_s *port,
-			wwn_t rpwwn);
-struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
-			struct bfa_fcs_port_s *port, wwn_t rnwwn);
-void bfa_fcs_rport_set_del_timeout(u8 rport_tmo);
-void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
-			enum bfa_pport_speed speed);
-#endif /* __BFA_FCS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h
deleted file mode 100644
index 0af2624..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcs_vport.h BFA fcs vport module public interface
- */
-
-#ifndef __BFA_FCS_VPORT_H__
-#define __BFA_FCS_VPORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_vport.h>
-#include <fcs/bfa_fcs.h>
-#include <fcb/bfa_fcb_vport.h>
-
-struct bfa_fcs_vport_s {
-	struct list_head		qe;		/*  queue elem	 */
-	bfa_sm_t		sm;		/*  state machine	*/
-	bfa_fcs_lport_t		lport;		/*  logical port	*/
-	struct bfa_timer_s	timer;		/*  general purpose timer */
-	struct bfad_vport_s	*vport_drv;	/*  Driver private	*/
-	struct bfa_vport_stats_s vport_stats;	/*  vport statistics	*/
-	struct bfa_lps_s	*lps;		/*  Lport login service */
-	int			fdisc_retries;
-};
-
-#define bfa_fcs_vport_get_port(vport) \
-			((struct bfa_fcs_port_s  *)(&vport->port))
-
-/**
- * bfa fcs vport public functions
- */
-bfa_status_t bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport,
-			struct bfa_fcs_s *fcs, u16 vf_id,
-			struct bfa_port_cfg_s *port_cfg,
-			struct bfad_vport_s *vport_drv);
-bfa_status_t bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport,
-			struct bfa_fcs_s *fcs, uint16_t vf_id,
-			struct bfa_port_cfg_s *port_cfg,
-			struct bfad_vport_s *vport_drv);
-bfa_status_t bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport);
-bfa_status_t bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport);
-bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
-			struct bfa_vport_attr_s *vport_attr);
-void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
-			struct bfa_vport_stats_s *vport_stats);
-void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport);
-struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs,
-			u16 vf_id, wwn_t vpwwn);
-
-#endif /* __BFA_FCS_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/log/bfa_log_fcs.h b/drivers/scsi/bfa/include/log/bfa_log_fcs.h
deleted file mode 100644
index b6f5df8..0000000
--- a/drivers/scsi/bfa/include/log/bfa_log_fcs.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/*
- * messages define for FCS Module
- */
-#ifndef	__BFA_LOG_FCS_H__
-#define	__BFA_LOG_FCS_H__
-#include  <cs/bfa_log.h>
-#define BFA_LOG_FCS_FABRIC_NOSWITCH 	\
-	(((u32) BFA_LOG_FCS_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_FCS_FABRIC_ISOLATED 	\
-	(((u32) BFA_LOG_FCS_ID << BFA_LOG_MODID_OFFSET) | 2)
-#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_hal.h b/drivers/scsi/bfa/include/log/bfa_log_hal.h
deleted file mode 100644
index 5f8f5e3..0000000
--- a/drivers/scsi/bfa/include/log/bfa_log_hal.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/* messages define for HAL Module */
-#ifndef	__BFA_LOG_HAL_H__
-#define	__BFA_LOG_HAL_H__
-#include  <cs/bfa_log.h>
-#define BFA_LOG_HAL_ASSERT \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_HAL_HEARTBEAT_FAILURE \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 2)
-#define BFA_LOG_HAL_FCPIM_PARM_INVALID \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 3)
-#define BFA_LOG_HAL_SM_ASSERT \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 4)
-#define BFA_LOG_HAL_DRIVER_ERROR \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 5)
-#define BFA_LOG_HAL_DRIVER_CONFIG_ERROR \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 6)
-#define BFA_LOG_HAL_MBOX_ERROR \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 7)
-#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_linux.h b/drivers/scsi/bfa/include/log/bfa_log_linux.h
deleted file mode 100644
index 44bc897..0000000
--- a/drivers/scsi/bfa/include/log/bfa_log_linux.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/* messages define for LINUX Module */
-#ifndef	__BFA_LOG_LINUX_H__
-#define	__BFA_LOG_LINUX_H__
-#include  <cs/bfa_log.h>
-#define BFA_LOG_LINUX_DEVICE_CLAIMED \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_LINUX_HASH_INIT_FAILED \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 2)
-#define BFA_LOG_LINUX_SYSFS_FAILED \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 3)
-#define BFA_LOG_LINUX_MEM_ALLOC_FAILED \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 4)
-#define BFA_LOG_LINUX_DRIVER_REGISTRATION_FAILED \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 5)
-#define BFA_LOG_LINUX_ITNIM_FREE \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 6)
-#define BFA_LOG_LINUX_ITNIM_ONLINE \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 7)
-#define BFA_LOG_LINUX_ITNIM_OFFLINE \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 8)
-#define BFA_LOG_LINUX_SCSI_HOST_FREE \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 9)
-#define BFA_LOG_LINUX_SCSI_ABORT \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 10)
-#define BFA_LOG_LINUX_SCSI_ABORT_COMP \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 11)
-#define BFA_LOG_LINUX_DRIVER_CONFIG_ERROR \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 12)
-#define BFA_LOG_LINUX_BNA_STATE_MACHINE \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 13)
-#define BFA_LOG_LINUX_IOC_ERROR \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 14)
-#define BFA_LOG_LINUX_RESOURCE_ALLOC_ERROR \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 15)
-#define BFA_LOG_LINUX_RING_BUFFER_ERROR \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 16)
-#define BFA_LOG_LINUX_DRIVER_ERROR \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 17)
-#define BFA_LOG_LINUX_DRIVER_INFO \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 18)
-#define BFA_LOG_LINUX_DRIVER_DIAG \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 19)
-#define BFA_LOG_LINUX_DRIVER_AEN \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 20)
-#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_wdrv.h b/drivers/scsi/bfa/include/log/bfa_log_wdrv.h
deleted file mode 100644
index 809a95f..0000000
--- a/drivers/scsi/bfa/include/log/bfa_log_wdrv.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/*
- * messages define for WDRV Module
- */
-#ifndef	__BFA_LOG_WDRV_H__
-#define	__BFA_LOG_WDRV_H__
-#include  <cs/bfa_log.h>
-#define BFA_LOG_WDRV_IOC_INIT_ERROR 	\
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_WDRV_IOC_INTERNAL_ERROR \
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 2)
-#define BFA_LOG_WDRV_IOC_START_ERROR 	\
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 3)
-#define BFA_LOG_WDRV_IOC_STOP_ERROR 	\
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 4)
-#define BFA_LOG_WDRV_INSUFFICIENT_RESOURCES \
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 5)
-#define BFA_LOG_WDRV_BASE_ADDRESS_MAP_ERROR \
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 6)
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/ct.h b/drivers/scsi/bfa/include/protocol/ct.h
deleted file mode 100644
index b82540a..0000000
--- a/drivers/scsi/bfa/include/protocol/ct.h
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __CT_H__
-#define __CT_H__
-
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-struct ct_hdr_s{
-	u32	rev_id:8;	/* Revision of the CT */
-	u32	in_id:24;	/* Initiator Id */
-	u32	gs_type:8;	/* Generic service Type */
-	u32	gs_sub_type:8;	/* Generic service sub type */
-	u32	options:8;	/* options */
-	u32	rsvrd:8;	/* reserved */
-	u32	cmd_rsp_code:16;/* ct command/response code */
-	u32	max_res_size:16;/* maximum/residual size */
-	u32	frag_id:8;	/* fragment ID */
-	u32	reason_code:8;	/* reason code */
-	u32	exp_code:8;	/* explanation code */
-	u32	vendor_unq:8;	/* vendor unique */
-};
-
-/*
- * defines for the Revision
- */
-enum {
-	CT_GS3_REVISION = 0x01,
-};
-
-/*
- * defines for gs_type
- */
-enum {
-	CT_GSTYPE_KEYSERVICE	= 0xF7,
-	CT_GSTYPE_ALIASSERVICE	= 0xF8,
-	CT_GSTYPE_MGMTSERVICE	= 0xFA,
-	CT_GSTYPE_TIMESERVICE	= 0xFB,
-	CT_GSTYPE_DIRSERVICE	= 0xFC,
-};
-
-/*
- * defines for gs_sub_type for gs type directory service
- */
-enum {
-	CT_GSSUBTYPE_NAMESERVER = 0x02,
-};
-
-/*
- * defines for gs_sub_type for gs type management service
- */
-enum {
-	CT_GSSUBTYPE_CFGSERVER	= 0x01,
-	CT_GSSUBTYPE_UNZONED_NS = 0x02,
-	CT_GSSUBTYPE_ZONESERVER = 0x03,
-	CT_GSSUBTYPE_LOCKSERVER = 0x04,
-	CT_GSSUBTYPE_HBA_MGMTSERVER = 0x10,	/* for FDMI */
-};
-
-/*
- * defines for CT response code field
- */
-enum {
-	CT_RSP_REJECT = 0x8001,
-	CT_RSP_ACCEPT = 0x8002,
-};
-
-/*
- * definitions for CT reason code
- */
-enum {
-	CT_RSN_INV_CMD		= 0x01,
-	CT_RSN_INV_VER		= 0x02,
-	CT_RSN_LOGIC_ERR	= 0x03,
-	CT_RSN_INV_SIZE		= 0x04,
-	CT_RSN_LOGICAL_BUSY	= 0x05,
-	CT_RSN_PROTO_ERR	= 0x07,
-	CT_RSN_UNABLE_TO_PERF	= 0x09,
-	CT_RSN_NOT_SUPP			= 0x0B,
-	CT_RSN_SERVER_NOT_AVBL  = 0x0D,
-	CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E,
-	CT_RSN_VENDOR_SPECIFIC  = 0xFF,
-
-};
-
-/*
- * definitions for explanations code for Name server
- */
-enum {
-	CT_NS_EXP_NOADDITIONAL	= 0x00,
-	CT_NS_EXP_ID_NOT_REG	= 0x01,
-	CT_NS_EXP_PN_NOT_REG	= 0x02,
-	CT_NS_EXP_NN_NOT_REG	= 0x03,
-	CT_NS_EXP_CS_NOT_REG	= 0x04,
-	CT_NS_EXP_IPN_NOT_REG	= 0x05,
-	CT_NS_EXP_IPA_NOT_REG	= 0x06,
-	CT_NS_EXP_FT_NOT_REG	= 0x07,
-	CT_NS_EXP_SPN_NOT_REG	= 0x08,
-	CT_NS_EXP_SNN_NOT_REG	= 0x09,
-	CT_NS_EXP_PT_NOT_REG	= 0x0A,
-	CT_NS_EXP_IPP_NOT_REG	= 0x0B,
-	CT_NS_EXP_FPN_NOT_REG	= 0x0C,
-	CT_NS_EXP_HA_NOT_REG	= 0x0D,
-	CT_NS_EXP_FD_NOT_REG	= 0x0E,
-	CT_NS_EXP_FF_NOT_REG	= 0x0F,
-	CT_NS_EXP_ACCESSDENIED	= 0x10,
-	CT_NS_EXP_UNACCEPTABLE_ID = 0x11,
-	CT_NS_EXP_DATABASEEMPTY			= 0x12,
-	CT_NS_EXP_NOT_REG_IN_SCOPE 		= 0x13,
-	CT_NS_EXP_DOM_ID_NOT_PRESENT 	= 0x14,
-	CT_NS_EXP_PORT_NUM_NOT_PRESENT  = 0x15,
-	CT_NS_EXP_NO_DEVICE_ATTACHED 	= 0x16
-};
-
-/*
- * definitions for the explanation code for all servers
- */
-enum {
-	CT_EXP_AUTH_EXCEPTION			= 0xF1,
-	CT_EXP_DB_FULL					= 0xF2,
-	CT_EXP_DB_EMPTY					= 0xF3,
-	CT_EXP_PROCESSING_REQ			= 0xF4,
-	CT_EXP_UNABLE_TO_VERIFY_CONN	= 0xF5,
-	CT_EXP_DEVICES_NOT_IN_CMN_ZONE  = 0xF6
-};
-
-/*
- * Command codes for Name server
- */
-enum {
-	GS_GID_PN	= 0x0121,	/* Get Id on port name */
-	GS_GPN_ID	= 0x0112,	/* Get port name on ID */
-	GS_GNN_ID	= 0x0113,	/* Get node name on ID */
-	GS_GID_FT	= 0x0171,	/* Get Id on FC4 type */
-	GS_GSPN_ID	= 0x0118,	/* Get symbolic PN on ID */
-	GS_RFT_ID	= 0x0217,	/* Register fc4type on ID */
-	GS_RSPN_ID	= 0x0218,	/* Register symbolic PN on ID */
-	GS_RPN_ID	= 0x0212,	/* Register port name */
-	GS_RNN_ID	= 0x0213,	/* Register node name */
-	GS_RCS_ID	= 0x0214,	/* Register class of service */
-	GS_RPT_ID	= 0x021A,	/* Register port type */
-	GS_GA_NXT	= 0x0100,	/* Get all next */
-	GS_RFF_ID	= 0x021F,	/* Register FC4 Feature		*/
-};
-
-struct fcgs_id_req_s{
-	u32	rsvd:8;
-	u32	dap:24;	/* port identifier */
-};
-#define fcgs_gpnid_req_t struct fcgs_id_req_s
-#define fcgs_gnnid_req_t struct fcgs_id_req_s
-#define fcgs_gspnid_req_t struct fcgs_id_req_s
-
-struct fcgs_gidpn_req_s{
-	wwn_t	port_name;	/* port wwn */
-};
-
-struct fcgs_gidpn_resp_s{
-	u32	rsvd:8;
-	u32	dap:24;	/* port identifier */
-};
-
-/**
- * RFT_ID
- */
-struct fcgs_rftid_req_s {
-	u32	rsvd:8;
-	u32	dap:24;		/* port identifier */
-	u32	fc4_type[8];	/* fc4 types */
-};
-
-/**
- * RFF_ID : Register FC4 features.
- */
-
-#define FC_GS_FCP_FC4_FEATURE_INITIATOR  0x02
-#define FC_GS_FCP_FC4_FEATURE_TARGET	 0x01
-
-struct fcgs_rffid_req_s{
-    u32    rsvd:8;
-    u32    dap:24;		/* port identifier	*/
-    u32    rsvd1:16;
-    u32    fc4ftr_bits:8;	/* fc4 feature bits	*/
-    u32    fc4_type:8;	/* corresponding FC4 Type */
-};
-
-/**
- * GID_FT Request
- */
-struct fcgs_gidft_req_s{
-	u8	reserved;
-	u8	domain_id;	/* domain, 0 - all fabric */
-	u8	area_id;	/* area, 0 - whole domain */
-	u8	fc4_type;	/* FC_TYPE_FCP for SCSI devices */
-};				/* GID_FT Request */
-
-/**
- * GID_FT Response
- */
-struct fcgs_gidft_resp_s {
-	u8		last:1;	/* last port identifier flag */
-	u8		reserved:7;
-	u32	pid:24;	/* port identifier */
-};				/* GID_FT Response */
-
-/**
- * RSPN_ID
- */
-struct fcgs_rspnid_req_s{
-	u32	rsvd:8;
-	u32	dap:24;		/* port identifier */
-	u8		spn_len;	/* symbolic port name length */
-	u8		spn[256];	/* symbolic port name */
-};
-
-/**
- * RPN_ID
- */
-struct fcgs_rpnid_req_s{
-	u32	rsvd:8;
-	u32	port_id:24;
-	wwn_t		port_name;
-};
-
-/**
- * RNN_ID
- */
-struct fcgs_rnnid_req_s{
-	u32	rsvd:8;
-	u32	port_id:24;
-	wwn_t		node_name;
-};
-
-/**
- * RCS_ID
- */
-struct fcgs_rcsid_req_s{
-	u32	rsvd:8;
-	u32	port_id:24;
-	u32	cos;
-};
-
-/**
- * RPT_ID
- */
-struct fcgs_rptid_req_s{
-	u32	rsvd:8;
-	u32	port_id:24;
-	u32	port_type:8;
-	u32	rsvd1:24;
-};
-
-/**
- * GA_NXT Request
- */
-struct fcgs_ganxt_req_s{
-	u32	rsvd:8;
-	u32	port_id:24;
-};
-
-/**
- * GA_NXT Response
- */
-struct fcgs_ganxt_rsp_s{
-	u32	port_type:8;	/* Port Type */
-	u32	port_id:24;	/* Port Identifier */
-	wwn_t		port_name;	/* Port Name */
-	u8		spn_len;	/* Length of Symbolic Port Name */
-	char		spn[255];	/* Symbolic Port Name */
-	wwn_t		node_name;	/* Node Name */
-	u8		snn_len;	/* Length of Symbolic Node Name */
-	char		snn[255];	/* Symbolic Node Name */
-	u8		ipa[8];		/* Initial Process Associator */
-	u8		ip[16];		/* IP Address */
-	u32	cos;		/* Class of Service */
-	u32	fc4types[8];	/* FC-4 TYPEs */
-	wwn_t		fabric_port_name;
-					/* Fabric Port Name */
-	u32	rsvd:8;		/* Reserved */
-	u32	hard_addr:24;	/* Hard Address */
-};
-
-/*
- * Fabric Config Server
- */
-
-/*
- * Command codes for Fabric Configuration Server
- */
-enum {
-	GS_FC_GFN_CMD	= 0x0114,	/* GS FC Get Fabric Name  */
-	GS_FC_GMAL_CMD	= 0x0116,	/* GS FC GMAL  */
-	GS_FC_TRACE_CMD	= 0x0400,	/* GS FC Trace Route */
-	GS_FC_PING_CMD	= 0x0401,	/* GS FC Ping */
-};
-
-/*
- * Source or Destination Port Tags.
- */
-enum {
-	GS_FTRACE_TAG_NPORT_ID		= 1,
-	GS_FTRACE_TAG_NPORT_NAME	= 2,
-};
-
-/*
-* Port Value : Could be a Port id or wwn
- */
-union fcgs_port_val_u{
-	u32	nport_id;
-	wwn_t		nport_wwn;
-};
-
-#define GS_FTRACE_MAX_HOP_COUNT	20
-#define GS_FTRACE_REVISION	1
-
-/*
- * Ftrace Related Structures.
- */
-
-/*
- * STR (Switch Trace) Reject Reason Codes. From FC-SW.
- */
-enum {
-	GS_FTRACE_STR_CMD_COMPLETED_SUCC	= 0,
-	GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH,
-	GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH,
-	GS_FTRACE_STR_MAX_HOP_CNT_REACHED,
-	GS_FTRACE_STR_SRC_PORT_NOT_FOUND,
-	GS_FTRACE_STR_DST_PORT_NOT_FOUND,
-	GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE,
-	GS_FTRACE_STR_NO_ROUTE_BW_PORTS,
-	GS_FTRACE_STR_NO_ADDL_EXPLN,
-	GS_FTRACE_STR_FABRIC_BUSY,
-	GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS,
-	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0,
-	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff,
-};
-
-/*
- * Ftrace Request
- */
-struct fcgs_ftrace_req_s{
-	u32	revision;
-	u16	src_port_tag;	/* Source Port tag */
-	u16	src_port_len;	/* Source Port len */
-	union fcgs_port_val_u src_port_val;	/* Source Port value */
-	u16	dst_port_tag;	/* Destination Port tag */
-	u16	dst_port_len;	/* Destination Port len */
-	union fcgs_port_val_u dst_port_val;	/* Destination Port value */
-	u32	token;
-	u8		vendor_id[8];	/* T10 Vendor Identifier */
-	u8		vendor_info[8];	/* Vendor specific Info */
-	u32	max_hop_cnt;	/* Max Hop Count */
-};
-
-/*
- * Path info structure
- */
-struct fcgs_ftrace_path_info_s{
-	wwn_t		switch_name;		/* Switch WWN */
-	u32	domain_id;
-	wwn_t		ingress_port_name;	/* Ingress ports wwn */
-	u32	ingress_phys_port_num;	/* Ingress ports physical port
-						 * number
-						 */
-	wwn_t		egress_port_name;	/* Ingress ports wwn */
-	u32	egress_phys_port_num;	/* Ingress ports physical port
-						 * number
-						 */
-};
-
-/*
- * Ftrace Acc Response
- */
-struct fcgs_ftrace_resp_s{
-	u32	revision;
-	u32	token;
-	u8		vendor_id[8];		/* T10 Vendor Identifier */
-	u8		vendor_info[8];		/* Vendor specific Info */
-	u32	str_rej_reason_code;	/* STR Reject Reason Code */
-	u32	num_path_info_entries;	/* No. of path info entries */
-	/*
-	 * path info entry/entries.
-	 */
-	struct fcgs_ftrace_path_info_s path_info[1];
-
-};
-
-/*
-* Fabric Config Server : FCPing
- */
-
-/*
- * FC Ping Request
- */
-struct fcgs_fcping_req_s{
-	u32	revision;
-	u16	port_tag;
-	u16	port_len;	/* Port len */
-	union fcgs_port_val_u port_val;	/* Port value */
-	u32	token;
-};
-
-/*
- * FC Ping Response
- */
-struct fcgs_fcping_resp_s{
-	u32	token;
-};
-
-/*
- * Command codes for zone server query.
- */
-enum {
-	ZS_GZME = 0x0124,	/* Get zone member extended */
-};
-
-/*
- * ZS GZME request
- */
-#define ZS_GZME_ZNAMELEN	32
-struct zs_gzme_req_s{
-	u8	znamelen;
-	u8	rsvd[3];
-	u8	zname[ZS_GZME_ZNAMELEN];
-};
-
-enum zs_mbr_type{
-	ZS_MBR_TYPE_PWWN	= 1,
-	ZS_MBR_TYPE_DOMPORT	= 2,
-	ZS_MBR_TYPE_PORTID	= 3,
-	ZS_MBR_TYPE_NWWN	= 4,
-};
-
-struct zs_mbr_wwn_s{
-	u8	mbr_type;
-	u8	rsvd[3];
-	wwn_t	wwn;
-};
-
-struct zs_query_resp_s{
-	u32	nmbrs;	/*  number of zone members */
-	struct zs_mbr_wwn_s	mbr[1];
-};
-
-/*
- * GMAL Command ( Get ( interconnect Element) Management Address List)
- * To retrieve the IP Address of a Switch.
- */
-
-#define CT_GMAL_RESP_PREFIX_TELNET	 "telnet://"
-#define CT_GMAL_RESP_PREFIX_HTTP	 "http://"
-
-/*  GMAL/GFN request */
-struct fcgs_req_s {
-	wwn_t    wwn; 	/* PWWN/NWWN */
-};
-
-#define fcgs_gmal_req_t struct fcgs_req_s
-#define fcgs_gfn_req_t struct fcgs_req_s
-
-/* Accept Response to GMAL */
-struct fcgs_gmal_resp_s {
-	u32 		ms_len;   /* Num of entries */
-	u8     	ms_ma[256];
-};
-
-struct fc_gmal_entry_s {
-	u8  len;
-	u8  prefix[7]; /* like "http://" */
-	u8  ip_addr[248];
-};
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/fc.h b/drivers/scsi/bfa/include/protocol/fc.h
deleted file mode 100644
index 436dd7c..0000000
--- a/drivers/scsi/bfa/include/protocol/fc.h
+++ /dev/null
@@ -1,1111 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __FC_H__
-#define __FC_H__
-
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-/*
- * Fibre Channel Header Structure (FCHS) definition
- */
-struct fchs_s {
-#ifdef __BIGENDIAN
-	u32        routing:4;	/* routing bits */
-	u32        cat_info:4;	/* category info */
-#else
-	u32        cat_info:4;	/* category info */
-	u32        routing:4;	/* routing bits */
-#endif
-	u32        d_id:24;	/* destination identifier */
-
-	u32        cs_ctl:8;	/* class specific control */
-	u32        s_id:24;	/* source identifier */
-
-	u32        type:8;		/* data structure type */
-	u32        f_ctl:24;	/* initial frame control */
-
-	u8         seq_id;		/* sequence identifier */
-	u8         df_ctl;		/* data field control */
-	u16        seq_cnt;	/* sequence count */
-
-	u16        ox_id;		/* originator exchange ID */
-	u16        rx_id;		/* responder exchange ID */
-
-	u32        ro;		/* relative offset */
-};
-
-#define FC_SOF_LEN      4
-#define FC_EOF_LEN      4
-#define FC_CRC_LEN      4
-
-/*
- * Fibre Channel BB_E Header Structure
- */
-struct fcbbehs_s {
-	u16	ver_rsvd;
-	u32	rsvd[2];
-	u32	rsvd__sof;
-};
-
-#define FC_SEQ_ID_MAX		256
-
-/*
- * routing bit definitions
- */
-enum {
-	FC_RTG_FC4_DEV_DATA	= 0x0,	/* FC-4 Device Data */
-	FC_RTG_EXT_LINK		= 0x2,	/* Extended Link Data */
-	FC_RTG_FC4_LINK_DATA	= 0x3,	/* FC-4 Link Data */
-	FC_RTG_VIDEO_DATA	= 0x4,	/* Video Data */
-	FC_RTG_EXT_HDR		= 0x5,	/* VFT, IFR or Encapsuled */
-	FC_RTG_BASIC_LINK	= 0x8,	/* Basic Link data */
-	FC_RTG_LINK_CTRL	= 0xC,	/* Link Control */
-};
-
-/*
- * information category for extended link data and FC-4 Link Data
- */
-enum {
-	FC_CAT_LD_REQUEST	= 0x2,	/* Request */
-	FC_CAT_LD_REPLY		= 0x3,	/* Reply */
-	FC_CAT_LD_DIAG		= 0xF,	/* for DIAG use only */
-};
-
-/*
- * information category for extended headers (VFT, IFR or encapsulation)
- */
-enum {
-	FC_CAT_VFT_HDR = 0x0,	/* Virtual fabric tagging header */
-	FC_CAT_IFR_HDR = 0x1,	/* Inter-Fabric routing header */
-	FC_CAT_ENC_HDR = 0x2,	/* Encapsulation header */
-};
-
-/*
- * information category for FC-4 device data
- */
-enum {
-	FC_CAT_UNCATEG_INFO	= 0x0,	/* Uncategorized information */
-	FC_CAT_SOLICIT_DATA	= 0x1,	/* Solicited Data */
-	FC_CAT_UNSOLICIT_CTRL	= 0x2,	/* Unsolicited Control */
-	FC_CAT_SOLICIT_CTRL	= 0x3,	/* Solicited Control */
-	FC_CAT_UNSOLICIT_DATA	= 0x4,	/* Unsolicited Data */
-	FC_CAT_DATA_DESC	= 0x5,	/* Data Descriptor */
-	FC_CAT_UNSOLICIT_CMD	= 0x6,	/* Unsolicited Command */
-	FC_CAT_CMD_STATUS	= 0x7,	/* Command Status */
-};
-
-/*
- * information category for Link Control
- */
-enum {
-	FC_CAT_ACK_1		= 0x00,
-	FC_CAT_ACK_0_N		= 0x01,
-	FC_CAT_P_RJT		= 0x02,
-	FC_CAT_F_RJT		= 0x03,
-	FC_CAT_P_BSY		= 0x04,
-	FC_CAT_F_BSY_DATA	= 0x05,
-	FC_CAT_F_BSY_LINK_CTL	= 0x06,
-	FC_CAT_F_LCR		= 0x07,
-	FC_CAT_NTY		= 0x08,
-	FC_CAT_END		= 0x09,
-};
-
-/*
- * Type Field Definitions. FC-PH Section 18.5 pg. 165
- */
-enum {
-	FC_TYPE_BLS		= 0x0,	/* Basic Link Service */
-	FC_TYPE_ELS		= 0x1,	/* Extended Link Service */
-	FC_TYPE_IP		= 0x5,	/* IP */
-	FC_TYPE_FCP		= 0x8,	/* SCSI-FCP */
-	FC_TYPE_GPP		= 0x9,	/* SCSI_GPP */
-	FC_TYPE_SERVICES	= 0x20,	/* Fibre Channel Services */
-	FC_TYPE_FC_FSS		= 0x22,	/* Fabric Switch Services */
-	FC_TYPE_FC_AL		= 0x23,	/* FC-AL */
-	FC_TYPE_FC_SNMP		= 0x24,	/* FC-SNMP */
-	FC_TYPE_MAX		= 256,	/* 256 FC-4 types */
-};
-
-struct fc_fc4types_s{
-	u8         bits[FC_TYPE_MAX / 8];
-};
-
-/*
- * Frame Control Definitions. FC-PH Table-45. pg. 168
- */
-enum {
-	FCTL_EC_ORIG = 0x000000,	/* exchange originator */
-	FCTL_EC_RESP = 0x800000,	/* exchange responder */
-	FCTL_SEQ_INI = 0x000000,	/* sequence initiator */
-	FCTL_SEQ_REC = 0x400000,	/* sequence recipient */
-	FCTL_FS_EXCH = 0x200000,	/* first sequence of xchg */
-	FCTL_LS_EXCH = 0x100000,	/* last sequence of xchg */
-	FCTL_END_SEQ = 0x080000,	/* last frame of sequence */
-	FCTL_SI_XFER = 0x010000,	/* seq initiative transfer */
-	FCTL_RO_PRESENT = 0x000008,	/* relative offset present */
-	FCTL_FILLBYTE_MASK = 0x000003	/* , fill byte mask */
-};
-
-/*
- * Fabric Well Known Addresses
- */
-enum {
-	FC_MIN_WELL_KNOWN_ADDR		= 0xFFFFF0,
-	FC_DOMAIN_CONTROLLER_MASK 	= 0xFFFC00,
-	FC_ALIAS_SERVER			= 0xFFFFF8,
-	FC_MGMT_SERVER			= 0xFFFFFA,
-	FC_TIME_SERVER			= 0xFFFFFB,
-	FC_NAME_SERVER			= 0xFFFFFC,
-	FC_FABRIC_CONTROLLER		= 0xFFFFFD,
-	FC_FABRIC_PORT			= 0xFFFFFE,
-	FC_BROADCAST_SERVER		= 0xFFFFFF
-};
-
-/*
- * domain/area/port defines
- */
-#define FC_DOMAIN_MASK  0xFF0000
-#define FC_DOMAIN_SHIFT 16
-#define FC_AREA_MASK    0x00FF00
-#define FC_AREA_SHIFT   8
-#define FC_PORT_MASK    0x0000FF
-#define FC_PORT_SHIFT   0
-
-#define FC_GET_DOMAIN(p)	(((p) & FC_DOMAIN_MASK) >> FC_DOMAIN_SHIFT)
-#define FC_GET_AREA(p)		(((p) & FC_AREA_MASK) >> FC_AREA_SHIFT)
-#define FC_GET_PORT(p)		(((p) & FC_PORT_MASK) >> FC_PORT_SHIFT)
-
-#define FC_DOMAIN_CTRLR(p)	(FC_DOMAIN_CONTROLLER_MASK | (FC_GET_DOMAIN(p)))
-
-enum {
-	FC_RXID_ANY = 0xFFFFU,
-};
-
-/*
- * generic ELS command
- */
-struct fc_els_cmd_s{
-	u32        els_code:8;	/* ELS Command Code */
-	u32        reserved:24;
-};
-
-/*
- * ELS Command Codes. FC-PH Table-75. pg. 223
- */
-enum {
-	FC_ELS_LS_RJT = 0x1,	/* Link Service Reject. */
-	FC_ELS_ACC = 0x02,	/* Accept */
-	FC_ELS_PLOGI = 0x03,	/* N_Port Login. */
-	FC_ELS_FLOGI = 0x04,	/* F_Port Login. */
-	FC_ELS_LOGO = 0x05,	/* Logout. */
-	FC_ELS_ABTX = 0x06,	/* Abort Exchange */
-	FC_ELS_RES = 0x08,	/* Read Exchange status */
-	FC_ELS_RSS = 0x09,	/* Read sequence status block */
-	FC_ELS_RSI = 0x0A,	/* Request Sequence Initiative */
-	FC_ELS_ESTC = 0x0C,	/* Estimate Credit. */
-	FC_ELS_RTV = 0x0E,	/* Read Timeout Value. */
-	FC_ELS_RLS = 0x0F,	/* Read Link Status. */
-	FC_ELS_ECHO = 0x10,	/* Echo */
-	FC_ELS_TEST = 0x11,	/* Test */
-	FC_ELS_RRQ = 0x12,	/* Reinstate Recovery Qualifier. */
-	FC_ELS_REC = 0x13,	/* Add this for TAPE support in FCR */
-	FC_ELS_PRLI = 0x20,	/* Process Login */
-	FC_ELS_PRLO = 0x21,	/* Process Logout. */
-	FC_ELS_SCN = 0x22,	/* State Change Notification. */
-	FC_ELS_TPRLO = 0x24,	/* Third Party Process Logout. */
-	FC_ELS_PDISC = 0x50,	/* Discover N_Port Parameters. */
-	FC_ELS_FDISC = 0x51,	/* Discover F_Port Parameters. */
-	FC_ELS_ADISC = 0x52,	/* Discover Address. */
-	FC_ELS_FAN = 0x60,	/* Fabric Address Notification */
-	FC_ELS_RSCN = 0x61,	/* Reg State Change Notification */
-	FC_ELS_SCR = 0x62,	/* State Change Registration. */
-	FC_ELS_RTIN = 0x77,	/* Mangement server request */
-	FC_ELS_RNID = 0x78,	/* Mangement server request */
-	FC_ELS_RLIR = 0x79,	/* Registered Link Incident Record */
-
-	FC_ELS_RPSC = 0x7D,	/* Report Port Speed Capabilities */
-	FC_ELS_QSA = 0x7E,	/* Query Security Attributes. Ref FC-SP */
-	FC_ELS_E2E_LBEACON = 0x81,
-				/* End-to-End Link Beacon */
-	FC_ELS_AUTH = 0x90,	/* Authentication. Ref FC-SP */
-	FC_ELS_RFCN = 0x97,	/* Request Fabric Change Notification. Ref
-				 *FC-SP */
-
-};
-
-/*
- *  Version numbers for FC-PH standards,
- *  used in login to indicate what port
- *  supports. See FC-PH-X table 158.
- */
-enum {
-	FC_PH_VER_4_3 = 0x09,
-	FC_PH_VER_PH_3 = 0x20,
-};
-
-/*
- * PDU size defines
- */
-enum {
-	FC_MIN_PDUSZ = 512,
-	FC_MAX_PDUSZ = 2112,
-};
-
-/*
- * N_Port PLOGI Common Service Parameters.
- * FC-PH-x. Figure-76. pg. 308.
- */
-struct fc_plogi_csp_s{
-	u8         verhi;	/* FC-PH high version */
-	u8         verlo;	/* FC-PH low version */
-	u16        bbcred;	/* BB_Credit */
-
-#ifdef __BIGENDIAN
-	u8         ciro:1,		/* continuously increasing RO */
-			rro:1,		/* random relative offset */
-			npiv_supp:1,	/* NPIV supported */
-			port_type:1,	/* N_Port/F_port */
-			altbbcred:1,	/* alternate BB_Credit */
-			resolution:1,	/* ms/ns ED_TOV resolution */
-			vvl_info:1,	/* VVL Info included */
-			reserved1:1;
-
-	u8         hg_supp:1,
-			query_dbc:1,
-			security:1,
-			sync_cap:1,
-			r_t_tov:1,
-			dh_dup_supp:1,
-			cisc:1,		/* continuously increasing seq count */
-			payload:1;
-#else
-	u8         reserved2:2,
-			resolution:1,	/* ms/ns ED_TOV resolution */
-			altbbcred:1,	/* alternate BB_Credit */
-			port_type:1,	/* N_Port/F_port */
-			npiv_supp:1,	/* NPIV supported */
-			rro:1,		/* random relative offset */
-			ciro:1;		/* continuously increasing RO */
-
-	u8         payload:1,
-			cisc:1,		/* continuously increasing seq count */
-			dh_dup_supp:1,
-			r_t_tov:1,
-			sync_cap:1,
-			security:1,
-			query_dbc:1,
-			hg_supp:1;
-#endif
-
-	u16        rxsz;		/* recieve data_field size */
-
-	u16        conseq;
-	u16        ro_bitmap;
-
-	u32        e_d_tov;
-};
-
-/*
- * N_Port PLOGI Class Specific Parameters.
- * FC-PH-x. Figure 78. pg. 318.
- */
-struct fc_plogi_clp_s{
-#ifdef __BIGENDIAN
-	u32        class_valid:1;
-	u32        intermix:1;	/* class intermix supported if set =1.
-					 * valid only for class1. Reserved for
-					 * class2 & class3
-					 */
-	u32        reserved1:2;
-	u32        sequential:1;
-	u32        reserved2:3;
-#else
-	u32        reserved2:3;
-	u32        sequential:1;
-	u32        reserved1:2;
-	u32        intermix:1;	/* class intermix supported if set =1.
-					 * valid only for class1. Reserved for
-					 * class2 & class3
-					 */
-	u32        class_valid:1;
-#endif
-
-	u32        reserved3:24;
-
-	u32        reserved4:16;
-	u32        rxsz:16;	/* Receive data_field size */
-
-	u32        reserved5:8;
-	u32        conseq:8;
-	u32        e2e_credit:16;	/* end to end credit */
-
-	u32        reserved7:8;
-	u32        ospx:8;
-	u32        reserved8:16;
-};
-
-#define FLOGI_VVL_BRCD    0x42524344 /* ASCII value for each character in
-				      * string "BRCD" */
-
-/*
- * PLOGI els command and reply payload
- */
-struct fc_logi_s{
-	struct fc_els_cmd_s els_cmd;	/* ELS command code */
-	struct fc_plogi_csp_s  csp;		/* common service params */
-	wwn_t           port_name;
-	wwn_t           node_name;
-	struct fc_plogi_clp_s  class1;		/* class 1 service parameters */
-	struct fc_plogi_clp_s  class2;		/* class 2 service parameters */
-	struct fc_plogi_clp_s  class3;		/* class 3 service parameters */
-	struct fc_plogi_clp_s  class4;		/* class 4 service parameters */
-	u8         vvl[16];	/* vendor version level */
-};
-
-/*
- * LOGO els command payload
- */
-struct fc_logo_s{
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        nport_id:24;	/* N_Port identifier of source */
-	wwn_t           orig_port_name;	/* Port name of the LOGO originator */
-};
-
-/*
- * ADISC els command payload
- */
-struct fc_adisc_s {
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        orig_HA:24;	/* originator hard address */
-	wwn_t           orig_port_name;	/* originator port name */
-	wwn_t           orig_node_name;	/* originator node name */
-	u32        res2:8;
-	u32        nport_id:24;	/* originator NPortID */
-};
-
-/*
- * Exchange status block
- */
-struct fc_exch_status_blk_s{
-	u32        oxid:16;
-	u32        rxid:16;
-	u32        res1:8;
-	u32        orig_np:24;	/* originator NPortID */
-	u32        res2:8;
-	u32        resp_np:24;	/* responder NPortID */
-	u32        es_bits;
-	u32        res3;
-	/*
-	 * un modified section of the fields
-	 */
-};
-
-/*
- * RES els command payload
- */
-struct fc_res_s {
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        nport_id:24;	/* N_Port identifier of source */
-	u32        oxid:16;
-	u32        rxid:16;
-	u8         assoc_hdr[32];
-};
-
-/*
- * RES els accept payload
- */
-struct fc_res_acc_s{
-	struct fc_els_cmd_s els_cmd;	/* ELS command code */
-	struct fc_exch_status_blk_s fc_exch_blk; /* Exchange status block */
-};
-
-/*
- * REC els command payload
- */
-struct fc_rec_s {
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        nport_id:24;	/* N_Port identifier of source */
-	u32        oxid:16;
-	u32        rxid:16;
-};
-
-#define FC_REC_ESB_OWN_RSP	0x80000000	/* responder owns */
-#define FC_REC_ESB_SI		0x40000000	/* SI is owned 	*/
-#define FC_REC_ESB_COMP		0x20000000	/* exchange is complete	*/
-#define FC_REC_ESB_ENDCOND_ABN	0x10000000	/* abnormal ending 	*/
-#define FC_REC_ESB_RQACT	0x04000000	/* recovery qual active	*/
-#define FC_REC_ESB_ERRP_MSK	0x03000000
-#define FC_REC_ESB_OXID_INV	0x00800000	/* invalid OXID		*/
-#define FC_REC_ESB_RXID_INV	0x00400000	/* invalid RXID		*/
-#define FC_REC_ESB_PRIO_INUSE	0x00200000
-
-/*
- * REC els accept payload
- */
-struct fc_rec_acc_s {
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        oxid:16;
-	u32        rxid:16;
-	u32        res1:8;
-	u32        orig_id:24;	/* N_Port id of exchange originator */
-	u32        res2:8;
-	u32        resp_id:24;	/* N_Port id of exchange responder */
-	u32        count;		/* data transfer count */
-	u32        e_stat;		/* exchange status */
-};
-
-/*
- * RSI els payload
- */
-struct fc_rsi_s {
-	struct fc_els_cmd_s    els_cmd;
-	u32        res1:8;
-	u32        orig_sid:24;
-	u32        oxid:16;
-	u32        rxid:16;
-};
-
-/*
- * structure for PRLI paramater pages, both request & response
- * see FC-PH-X table 113 & 115 for explanation also FCP table 8
- */
-struct fc_prli_params_s{
-	u32        reserved:16;
-#ifdef __BIGENDIAN
-	u32        reserved1:5;
-	u32        rec_support:1;
-	u32        task_retry_id:1;
-	u32        retry:1;
-
-	u32        confirm:1;
-	u32        doverlay:1;
-	u32        initiator:1;
-	u32        target:1;
-	u32        cdmix:1;
-	u32        drmix:1;
-	u32        rxrdisab:1;
-	u32        wxrdisab:1;
-#else
-	u32        retry:1;
-	u32        task_retry_id:1;
-	u32        rec_support:1;
-	u32        reserved1:5;
-
-	u32        wxrdisab:1;
-	u32        rxrdisab:1;
-	u32        drmix:1;
-	u32        cdmix:1;
-	u32        target:1;
-	u32        initiator:1;
-	u32        doverlay:1;
-	u32        confirm:1;
-#endif
-};
-
-/*
- * valid values for rspcode in PRLI ACC payload
- */
-enum {
-	FC_PRLI_ACC_XQTD = 0x1,		/* request executed */
-	FC_PRLI_ACC_PREDEF_IMG = 0x5,	/* predefined image - no prli needed */
-};
-
-struct fc_prli_params_page_s{
-	u32        type:8;
-	u32        codext:8;
-#ifdef __BIGENDIAN
-	u32        origprocasv:1;
-	u32        rsppav:1;
-	u32        imagepair:1;
-	u32        reserved1:1;
-	u32        rspcode:4;
-#else
-	u32        rspcode:4;
-	u32        reserved1:1;
-	u32        imagepair:1;
-	u32        rsppav:1;
-	u32        origprocasv:1;
-#endif
-	u32        reserved2:8;
-
-	u32        origprocas;
-	u32        rspprocas;
-	struct fc_prli_params_s  servparams;
-};
-
-/*
- * PRLI request and accept payload, FC-PH-X tables 112 & 114
- */
-struct fc_prli_s{
-	u32        command:8;
-	u32        pglen:8;
-	u32        pagebytes:16;
-	struct fc_prli_params_page_s parampage;
-};
-
-/*
- * PRLO logout params page
- */
-struct fc_prlo_params_page_s{
-	u32        type:8;
-	u32        type_ext:8;
-#ifdef __BIGENDIAN
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
-	u32        rpa_valid:1;	/* responder process associator valid */
-	u32        res1:14;
-#else
-	u32        res1:14;
-	u32        rpa_valid:1;	/* responder process associator valid */
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
-#endif
-	u32        orig_process_assc;
-	u32        resp_process_assc;
-
-	u32        res2;
-};
-
-/*
- * PRLO els command payload
- */
-struct fc_prlo_s{
-	u32        	command:8;
-	u32        	page_len:8;
-	u32        	payload_len:16;
-	struct fc_prlo_params_page_s 	prlo_params[1];
-};
-
-/*
- * PRLO Logout response parameter page
- */
-struct fc_prlo_acc_params_page_s{
-	u32        type:8;
-	u32        type_ext:8;
-
-#ifdef __BIGENDIAN
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
-	u32        rpa_valid:1;	/* responder process associator valid */
-	u32        res1:14;
-#else
-	u32        res1:14;
-	u32        rpa_valid:1;	/* responder process associator valid */
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
-#endif
-	u32        orig_process_assc;
-	u32        resp_process_assc;
-
-	u32        fc4type_csp;
-};
-
-/*
- * PRLO els command ACC payload
- */
-struct fc_prlo_acc_s{
-	u32        command:8;
-	u32        page_len:8;
-	u32        payload_len:16;
-	struct fc_prlo_acc_params_page_s prlo_acc_params[1];
-};
-
-/*
- * SCR els command payload
- */
-enum {
-	FC_SCR_REG_FUNC_FABRIC_DETECTED = 0x01,
-	FC_SCR_REG_FUNC_N_PORT_DETECTED = 0x02,
-	FC_SCR_REG_FUNC_FULL = 0x03,
-	FC_SCR_REG_FUNC_CLEAR_REG = 0xFF,
-};
-
-/* SCR VU registrations */
-enum {
-	FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE = 0x01
-};
-
-struct fc_scr_s{
-	u32 command:8;
-	u32 res:24;
-	u32 vu_reg_func:8; /* Vendor Unique Registrations */
-	u32 res1:16;
-	u32 reg_func:8;
-};
-
-/*
- * Information category for Basic link data
- */
-enum {
-	FC_CAT_NOP	= 0x0,
-	FC_CAT_ABTS	= 0x1,
-	FC_CAT_RMC	= 0x2,
-	FC_CAT_BA_ACC	= 0x4,
-	FC_CAT_BA_RJT	= 0x5,
-	FC_CAT_PRMT	= 0x6,
-};
-
-/*
- * LS_RJT els reply payload
- */
-struct fc_ls_rjt_s {
-	struct fc_els_cmd_s    els_cmd;		/* ELS command code */
-	u32        res1:8;
-	u32        reason_code:8;		/* Reason code for reject */
-	u32        reason_code_expl:8;	/* Reason code explanation */
-	u32        vendor_unique:8;	/* Vendor specific */
-};
-
-/*
- * LS_RJT reason codes
- */
-enum {
-	FC_LS_RJT_RSN_INV_CMD_CODE	= 0x01,
-	FC_LS_RJT_RSN_LOGICAL_ERROR	= 0x03,
-	FC_LS_RJT_RSN_LOGICAL_BUSY	= 0x05,
-	FC_LS_RJT_RSN_PROTOCOL_ERROR	= 0x07,
-	FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD = 0x09,
-	FC_LS_RJT_RSN_CMD_NOT_SUPP	= 0x0B,
-};
-
-/*
- * LS_RJT reason code explanation
- */
-enum {
-	FC_LS_RJT_EXP_NO_ADDL_INFO		= 0x00,
-	FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS	= 0x01,
-	FC_LS_RJT_EXP_SPARMS_ERR_INI_CTL	= 0x03,
-	FC_LS_RJT_EXP_SPARMS_ERR_REC_CTL	= 0x05,
-	FC_LS_RJT_EXP_SPARMS_ERR_RXSZ		= 0x07,
-	FC_LS_RJT_EXP_SPARMS_ERR_CONSEQ		= 0x09,
-	FC_LS_RJT_EXP_SPARMS_ERR_CREDIT		= 0x0B,
-	FC_LS_RJT_EXP_INV_PORT_NAME		= 0x0D,
-	FC_LS_RJT_EXP_INV_NODE_FABRIC_NAME	= 0x0E,
-	FC_LS_RJT_EXP_INV_CSP			= 0x0F,
-	FC_LS_RJT_EXP_INV_ASSOC_HDR		= 0x11,
-	FC_LS_RJT_EXP_ASSOC_HDR_REQD		= 0x13,
-	FC_LS_RJT_EXP_INV_ORIG_S_ID		= 0x15,
-	FC_LS_RJT_EXP_INV_OXID_RXID_COMB	= 0x17,
-	FC_LS_RJT_EXP_CMD_ALREADY_IN_PROG	= 0x19,
-	FC_LS_RJT_EXP_LOGIN_REQUIRED		= 0x1E,
-	FC_LS_RJT_EXP_INVALID_NPORT_ID		= 0x1F,
-	FC_LS_RJT_EXP_INSUFF_RES		= 0x29,
-	FC_LS_RJT_EXP_CMD_NOT_SUPP		= 0x2C,
-	FC_LS_RJT_EXP_INV_PAYLOAD_LEN		= 0x2D,
-};
-
-/*
- * RRQ els command payload
- */
-struct fc_rrq_s{
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        s_id:24;	/* exchange originator S_ID */
-
-	u32        ox_id:16;	/* originator exchange ID */
-	u32        rx_id:16;	/* responder exchange ID */
-
-	u32        res2[8];	/* optional association header */
-};
-
-/*
- * ABTS BA_ACC reply payload
- */
-struct fc_ba_acc_s{
-	u32        seq_id_valid:8;	/* set to 0x00 for Abort Exchange */
-	u32        seq_id:8;	/* invalid for Abort Exchange */
-	u32        res2:16;
-	u32        ox_id:16;	/* OX_ID from ABTS frame */
-	u32        rx_id:16;	/* RX_ID from ABTS frame */
-	u32        low_seq_cnt:16;	/* set to 0x0000 for Abort Exchange */
-	u32        high_seq_cnt:16;/* set to 0xFFFF for Abort Exchange */
-};
-
-/*
- * ABTS BA_RJT reject payload
- */
-struct fc_ba_rjt_s{
-	u32        res1:8;		/* Reserved */
-	u32        reason_code:8;	/* reason code for reject */
-	u32        reason_expl:8;	/* reason code explanation */
-	u32        vendor_unique:8;/* vendor unique reason code,set to 0 */
-};
-
-/*
- * TPRLO logout parameter page
- */
-struct fc_tprlo_params_page_s{
-	u32        type:8;
-	u32        type_ext:8;
-
-#ifdef __BIGENDIAN
-	u32        opa_valid:1;
-	u32        rpa_valid:1;
-	u32        tpo_nport_valid:1;
-	u32        global_process_logout:1;
-	u32        res1:12;
-#else
-	u32        res1:12;
-	u32        global_process_logout:1;
-	u32        tpo_nport_valid:1;
-	u32        rpa_valid:1;
-	u32        opa_valid:1;
-#endif
-
-	u32        orig_process_assc;
-	u32        resp_process_assc;
-
-	u32        res2:8;
-	u32        tpo_nport_id;
-};
-
-/*
- * TPRLO ELS command payload
- */
-struct fc_tprlo_s{
-	u32        command:8;
-	u32        page_len:8;
-	u32        payload_len:16;
-
-	struct fc_tprlo_params_page_s tprlo_params[1];
-};
-
-enum fc_tprlo_type{
-	FC_GLOBAL_LOGO = 1,
-	FC_TPR_LOGO
-};
-
-/*
- * TPRLO els command ACC payload
- */
-struct fc_tprlo_acc_s{
-	u32	command:8;
-	u32	page_len:8;
-	u32	payload_len:16;
-	struct fc_prlo_acc_params_page_s tprlo_acc_params[1];
-};
-
-/*
- * RSCN els command req payload
- */
-#define FC_RSCN_PGLEN	0x4
-
-enum fc_rscn_format{
-	FC_RSCN_FORMAT_PORTID	= 0x0,
-	FC_RSCN_FORMAT_AREA	= 0x1,
-	FC_RSCN_FORMAT_DOMAIN	= 0x2,
-	FC_RSCN_FORMAT_FABRIC	= 0x3,
-};
-
-struct fc_rscn_event_s{
-	u32        format:2;
-	u32        qualifier:4;
-	u32        resvd:2;
-	u32        portid:24;
-};
-
-struct fc_rscn_pl_s{
-	u8         command;
-	u8         pagelen;
-	u16        payldlen;
-	struct fc_rscn_event_s event[1];
-};
-
-/*
- * ECHO els command req payload
- */
-struct fc_echo_s {
-	struct fc_els_cmd_s    els_cmd;
-};
-
-/*
- * RNID els command
- */
-
-#define RNID_NODEID_DATA_FORMAT_COMMON    		 0x00
-#define RNID_NODEID_DATA_FORMAT_FCP3        		 0x08
-#define RNID_NODEID_DATA_FORMAT_DISCOVERY     		0xDF
-
-#define RNID_ASSOCIATED_TYPE_UNKNOWN                    0x00000001
-#define RNID_ASSOCIATED_TYPE_OTHER                      0x00000002
-#define RNID_ASSOCIATED_TYPE_HUB                        0x00000003
-#define RNID_ASSOCIATED_TYPE_SWITCH                     0x00000004
-#define RNID_ASSOCIATED_TYPE_GATEWAY                    0x00000005
-#define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE             0x00000009
-#define RNID_ASSOCIATED_TYPE_HOST                       0x0000000A
-#define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM          0x0000000B
-#define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE      0x0000000E
-#define RNID_ASSOCIATED_TYPE_NAS_SERVER                 0x00000011
-#define RNID_ASSOCIATED_TYPE_BRIDGE                     0x00000002
-#define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE      0x00000003
-#define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE      0x000000FF
-
-/*
- * RNID els command payload
- */
-struct fc_rnid_cmd_s{
-	struct fc_els_cmd_s    els_cmd;
-	u32        node_id_data_format:8;
-	u32        reserved:24;
-};
-
-/*
- * RNID els response payload
- */
-
-struct fc_rnid_common_id_data_s{
-	wwn_t           port_name;
-	wwn_t           node_name;
-};
-
-struct fc_rnid_general_topology_data_s{
-	u32        vendor_unique[4];
-	u32        asso_type;
-	u32        phy_port_num;
-	u32        num_attached_nodes;
-	u32        node_mgmt:8;
-	u32        ip_version:8;
-	u32        udp_tcp_port_num:16;
-	u32        ip_address[4];
-	u32        reserved:16;
-	u32        vendor_specific:16;
-};
-
-struct fc_rnid_acc_s{
-	struct fc_els_cmd_s    els_cmd;
-	u32        node_id_data_format:8;
-	u32        common_id_data_length:8;
-	u32        reserved:8;
-	u32        specific_id_data_length:8;
-	struct fc_rnid_common_id_data_s common_id_data;
-	struct fc_rnid_general_topology_data_s gen_topology_data;
-};
-
-#define RNID_ASSOCIATED_TYPE_UNKNOWN                    0x00000001
-#define RNID_ASSOCIATED_TYPE_OTHER                      0x00000002
-#define RNID_ASSOCIATED_TYPE_HUB                        0x00000003
-#define RNID_ASSOCIATED_TYPE_SWITCH                     0x00000004
-#define RNID_ASSOCIATED_TYPE_GATEWAY                    0x00000005
-#define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE             0x00000009
-#define RNID_ASSOCIATED_TYPE_HOST                       0x0000000A
-#define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM          0x0000000B
-#define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE      0x0000000E
-#define RNID_ASSOCIATED_TYPE_NAS_SERVER                 0x00000011
-#define RNID_ASSOCIATED_TYPE_BRIDGE                     0x00000002
-#define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE      0x00000003
-#define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE      0x000000FF
-
-enum fc_rpsc_speed_cap{
-	RPSC_SPEED_CAP_1G = 0x8000,
-	RPSC_SPEED_CAP_2G = 0x4000,
-	RPSC_SPEED_CAP_4G = 0x2000,
-	RPSC_SPEED_CAP_10G = 0x1000,
-	RPSC_SPEED_CAP_8G = 0x0800,
-	RPSC_SPEED_CAP_16G = 0x0400,
-
-	RPSC_SPEED_CAP_UNKNOWN = 0x0001,
-};
-
-enum fc_rpsc_op_speed_s{
-	RPSC_OP_SPEED_1G = 0x8000,
-	RPSC_OP_SPEED_2G = 0x4000,
-	RPSC_OP_SPEED_4G = 0x2000,
-	RPSC_OP_SPEED_10G = 0x1000,
-	RPSC_OP_SPEED_8G = 0x0800,
-	RPSC_OP_SPEED_16G = 0x0400,
-
-	RPSC_OP_SPEED_NOT_EST = 0x0001,	/*! speed not established */
-};
-
-struct fc_rpsc_speed_info_s{
-	u16        port_speed_cap;	/*! see fc_rpsc_speed_cap_t */
-	u16        port_op_speed;	/*! see fc_rpsc_op_speed_t */
-};
-
-enum link_e2e_beacon_subcmd{
-	LINK_E2E_BEACON_ON = 1,
-	LINK_E2E_BEACON_OFF = 2
-};
-
-enum beacon_type{
-	BEACON_TYPE_NORMAL	= 1,	/*! Normal Beaconing. Green */
-	BEACON_TYPE_WARN	= 2,	/*! Warning Beaconing. Yellow/Amber */
-	BEACON_TYPE_CRITICAL	= 3	/*! Critical Beaconing. Red */
-};
-
-struct link_e2e_beacon_param_s {
-	u8         beacon_type;	/* Beacon Type. See beacon_type_t */
-	u8         beacon_frequency;
-					/* Beacon frequency. Number of blinks
-					 * per 10 seconds
-					 */
-	u16        beacon_duration;/* Beacon duration (in Seconds). The
-					 * command operation should be
-					 * terminated at the end of this
-					 * timeout value.
-					 *
-					 * Ignored if diag_sub_cmd is
-					 * LINK_E2E_BEACON_OFF.
-					 *
-					 * If 0, beaconing will continue till a
-					 * BEACON OFF request is received
-					 */
-};
-
-/*
- * Link E2E beacon request/good response format. For LS_RJTs use fc_ls_rjt_t
- */
-struct link_e2e_beacon_req_s{
-	u32        ls_code;	/*! FC_ELS_E2E_LBEACON in requests *
-					 *or FC_ELS_ACC in good replies */
-	u32        ls_sub_cmd;	/*! See link_e2e_beacon_subcmd_t */
-	struct link_e2e_beacon_param_s beacon_parm;
-};
-
-/**
- * If RPSC request is sent to the Domain Controller, the request is for
- * all the ports within that domain (TODO - I don't think FOS implements
- * this...).
- */
-struct fc_rpsc_cmd_s{
-	struct fc_els_cmd_s    els_cmd;
-};
-
-/*
- * RPSC Acc
- */
-struct fc_rpsc_acc_s{
-	u32        command:8;
-	u32        rsvd:8;
-	u32        num_entries:16;
-
-	struct fc_rpsc_speed_info_s speed_info[1];
-};
-
-/**
- * If RPSC2 request is sent to the Domain Controller,
- */
-#define FC_BRCD_TOKEN    0x42524344
-
-struct fc_rpsc2_cmd_s{
-	struct fc_els_cmd_s    els_cmd;
-	u32       	token;
-	u16     	resvd;
-	u16     	num_pids;       /* Number of pids in the request */
-	struct  {
-		u32	rsvd1:8;
-		u32	pid:24;	/* port identifier */
-	} pid_list[1];
-};
-
-enum fc_rpsc2_port_type{
-	RPSC2_PORT_TYPE_UNKNOWN = 0,
-	RPSC2_PORT_TYPE_NPORT   = 1,
-	RPSC2_PORT_TYPE_NLPORT  = 2,
-	RPSC2_PORT_TYPE_NPIV_PORT  = 0x5f,
-	RPSC2_PORT_TYPE_NPORT_TRUNK  = 0x6f,
-};
-
-/*
- * RPSC2 portInfo entry structure
- */
-struct fc_rpsc2_port_info_s{
-    u32    pid;        /* PID */
-    u16    resvd1;
-    u16    index;      /* port number / index */
-    u8     resvd2;
-    u8    	type;        /* port type N/NL/... */
-    u16    speed;      /* port Operating Speed */
-};
-
-/*
- * RPSC2 Accept payload
- */
-struct fc_rpsc2_acc_s{
-	u8        els_cmd;
-	u8        resvd;
-	u16       num_pids;  /* Number of pids in the request */
-	struct fc_rpsc2_port_info_s  port_info[1];    /* port information */
-};
-
-/**
- * bit fields so that multiple classes can be specified
- */
-enum fc_cos{
-	FC_CLASS_2	= 0x04,
-	FC_CLASS_3	= 0x08,
-	FC_CLASS_2_3	= 0x0C,
-};
-
-/*
- * symbolic name
- */
-struct fc_symname_s{
-	u8         symname[FC_SYMNAME_MAX];
-};
-
-struct fc_alpabm_s{
-	u8         alpa_bm[FC_ALPA_MAX / 8];
-};
-
-/*
- * protocol default timeout values
- */
-#define FC_ED_TOV		2
-#define FC_REC_TOV		(FC_ED_TOV + 1)
-#define FC_RA_TOV		10
-#define FC_ELS_TOV		(2 * FC_RA_TOV)
-#define FC_FCCT_TOV		(3 * FC_RA_TOV)
-
-/*
- * virtual fabric related defines
- */
-#define FC_VF_ID_NULL    0	/*  must not be used as VF_ID */
-#define FC_VF_ID_MIN     1
-#define FC_VF_ID_MAX     0xEFF
-#define FC_VF_ID_CTL     0xFEF	/*  control VF_ID */
-
-/**
- * Virtual Fabric Tagging header format
- * @caution This is defined only in BIG ENDIAN format.
- */
-struct fc_vft_s{
-	u32        r_ctl:8;
-	u32        ver:2;
-	u32        type:4;
-	u32        res_a:2;
-	u32        priority:3;
-	u32        vf_id:12;
-	u32        res_b:1;
-	u32        hopct:8;
-	u32        res_c:24;
-};
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/fc_sp.h b/drivers/scsi/bfa/include/protocol/fc_sp.h
deleted file mode 100644
index 55bb0b3..0000000
--- a/drivers/scsi/bfa/include/protocol/fc_sp.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __FC_SP_H__
-#define __FC_SP_H__
-
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-enum auth_els_flags{
-	FC_AUTH_ELS_MORE_FRAGS_FLAG 	= 0x80,	/*! bit-7. More Fragments
-						 * Follow
-						 */
-	FC_AUTH_ELS_CONCAT_FLAG 	= 0x40,	/*! bit-6. Concatenation Flag */
-	FC_AUTH_ELS_SEQ_NUM_FLAG 	= 0x01 	/*! bit-0. Sequence Number */
-};
-
-enum auth_msg_codes{
-	FC_AUTH_MC_AUTH_RJT		= 0x0A,	/*! Auth Reject */
-	FC_AUTH_MC_AUTH_NEG 		= 0x0B, /*! Auth Negotiate */
-	FC_AUTH_MC_AUTH_DONE 		= 0x0C, /*! Auth Done */
-
-	FC_AUTH_MC_DHCHAP_CHAL 		= 0x10, /*! DHCHAP Challenge */
-	FC_AUTH_MC_DHCHAP_REPLY 	= 0x11, /*! DHCHAP Reply */
-	FC_AUTH_MC_DHCHAP_SUCC 		= 0x12, /*! DHCHAP Success */
-
-	FC_AUTH_MC_FCAP_REQ 		= 0x13, /*! FCAP Request */
-	FC_AUTH_MC_FCAP_ACK 		= 0x14, /*! FCAP Acknowledge */
-	FC_AUTH_MC_FCAP_CONF 		= 0x15, /*! FCAP Confirm */
-
-	FC_AUTH_MC_FCPAP_INIT 		= 0x16, /*! FCPAP Init */
-	FC_AUTH_MC_FCPAP_ACC 		= 0x17, /*! FCPAP Accept */
-	FC_AUTH_MC_FCPAP_COMP 		= 0x18, /*! FCPAP Complete */
-
-	FC_AUTH_MC_IKE_SA_INIT 		= 0x22, /*! IKE SA INIT */
-	FC_AUTH_MC_IKE_SA_AUTH 		= 0x23, /*! IKE SA Auth */
-	FC_AUTH_MC_IKE_CREATE_CHILD_SA	= 0x24, /*! IKE Create Child SA */
-	FC_AUTH_MC_IKE_INFO 		= 0x25, /*! IKE informational */
-};
-
-enum auth_proto_version{
-	FC_AUTH_PROTO_VER_1 	= 1,	/*! Protocol Version 1 */
-};
-
-enum {
-	FC_AUTH_ELS_COMMAND_CODE = 0x90,/*! Authentication ELS Command code  */
-	FC_AUTH_PROTO_PARAM_LEN_SZ = 4,	/*! Size of Proto Parameter Len Field */
-	FC_AUTH_PROTO_PARAM_VAL_SZ = 4,	/*! Size of Proto Parameter Val Field */
-	FC_MAX_AUTH_SECRET_LEN     = 256,
-					/*! Maximum secret string length */
-	FC_AUTH_NUM_USABLE_PROTO_LEN_SZ = 4,
-					/*! Size of usable protocols field */
-	FC_AUTH_RESP_VALUE_LEN_SZ	= 4,
-					/*! Size of response value length */
-	FC_MAX_CHAP_KEY_LEN	= 256,	/*! Maximum md5 digest length */
-	FC_MAX_AUTH_RETRIES     = 3,	/*! Maximum number of retries */
-	FC_MD5_DIGEST_LEN       = 16,	/*! MD5 digest length */
-	FC_SHA1_DIGEST_LEN      = 20,	/*! SHA1 digest length */
-	FC_MAX_DHG_SUPPORTED    = 1,	/*! Maximum DH Groups supported */
-	FC_MAX_ALG_SUPPORTED    = 1,	/*! Maximum algorithms supported */
-	FC_MAX_PROTO_SUPPORTED  = 1,	/*! Maximum protocols supported */
-	FC_START_TXN_ID         = 2,	/*! Starting transaction ID */
-};
-
-enum auth_proto_id{
-	FC_AUTH_PROTO_DHCHAP		= 0x00000001,
-	FC_AUTH_PROTO_FCAP 		= 0x00000002,
-	FC_AUTH_PROTO_FCPAP 		= 0x00000003,
-	FC_AUTH_PROTO_IKEv2 		= 0x00000004,
-	FC_AUTH_PROTO_IKEv2_AUTH 	= 0x00000005,
-};
-
-struct auth_name_s{
-	u16	name_tag;	/*! Name Tag = 1 for Authentication */
-	u16	name_len;	/*! Name Length = 8 for Authentication
-					 */
-	wwn_t		name;  		/*! Name. TODO - is this PWWN */
-};
-
-
-enum auth_hash_func{
-	FC_AUTH_HASH_FUNC_MD5 		= 0x00000005,
-	FC_AUTH_HASH_FUNC_SHA_1 	= 0x00000006,
-};
-
-enum auth_dh_gid{
-	FC_AUTH_DH_GID_0_DHG_NULL	= 0x00000000,
-	FC_AUTH_DH_GID_1_DHG_1024	= 0x00000001,
-	FC_AUTH_DH_GID_2_DHG_1280	= 0x00000002,
-	FC_AUTH_DH_GID_3_DHG_1536	= 0x00000003,
-	FC_AUTH_DH_GID_4_DHG_2048	= 0x00000004,
-	FC_AUTH_DH_GID_6_DHG_3072	= 0x00000006,
-	FC_AUTH_DH_GID_7_DHG_4096	= 0x00000007,
-	FC_AUTH_DH_GID_8_DHG_6144	= 0x00000008,
-	FC_AUTH_DH_GID_9_DHG_8192	= 0x00000009,
-};
-
-struct auth_els_msg_s {
-	u8		auth_els_code;	/*  Authentication ELS Code (0x90) */
-	u8 	auth_els_flag; 	/*  Authentication ELS Flags */
-	u8 	auth_msg_code; 	/*  Authentication Message Code */
-	u8 	proto_version; 	/*  Protocol Version */
-	u32	msg_len; 	/*  Message Length */
-	u32	trans_id; 	/*  Transaction Identifier (T_ID) */
-
-	/* Msg payload follows... */
-};
-
-
-enum auth_neg_param_tags {
-	FC_AUTH_NEG_DHCHAP_HASHLIST 	= 0x0001,
-	FC_AUTH_NEG_DHCHAP_DHG_ID_LIST 	= 0x0002,
-};
-
-
-struct dhchap_param_format_s {
-	u16	tag;		/*! Parameter Tag. See
-					 * auth_neg_param_tags_t
-					 */
-	u16	word_cnt;
-
-	/* followed by variable length parameter value... */
-};
-
-struct auth_proto_params_s {
-	u32	proto_param_len;
-	u32	proto_id;
-
-	/*
-	 * Followed by variable length Protocol specific parameters. DH-CHAP
-	 * uses dhchap_param_format_t
-	 */
-};
-
-struct auth_neg_msg_s {
-	struct auth_name_s	auth_ini_name;
-	u32		usable_auth_protos;
-	struct auth_proto_params_s proto_params[1]; /*! (1..usable_auth_proto)
-						     * protocol params
-						     */
-};
-
-struct auth_dh_val_s {
-	u32 dh_val_len;
-	u32 dh_val[1];
-};
-
-struct auth_dhchap_chal_msg_s {
-	struct auth_els_msg_s	hdr;
-	struct auth_name_s auth_responder_name;	/* TODO VRK - is auth_name_t
-						 * type OK?
-						 */
-	u32 	hash_id;
-	u32 	dh_grp_id;
-	u32 	chal_val_len;
-	char		chal_val[1];
-
-	/* ...followed by variable Challenge length/value and DH length/value */
-};
-
-
-enum auth_rjt_codes {
-	FC_AUTH_RJT_CODE_AUTH_FAILURE 	= 0x01,
-	FC_AUTH_RJT_CODE_LOGICAL_ERR	= 0x02,
-};
-
-enum auth_rjt_code_exps {
-	FC_AUTH_CEXP_AUTH_MECH_NOT_USABLE	= 0x01,
-	FC_AUTH_CEXP_DH_GROUP_NOT_USABLE 	= 0x02,
-	FC_AUTH_CEXP_HASH_FUNC_NOT_USABLE 	= 0x03,
-	FC_AUTH_CEXP_AUTH_XACT_STARTED		= 0x04,
-	FC_AUTH_CEXP_AUTH_FAILED 		= 0x05,
-	FC_AUTH_CEXP_INCORRECT_PLD 		= 0x06,
-	FC_AUTH_CEXP_INCORRECT_PROTO_MSG 	= 0x07,
-	FC_AUTH_CEXP_RESTART_AUTH_PROTO 	= 0x08,
-	FC_AUTH_CEXP_AUTH_CONCAT_NOT_SUPP 	= 0x09,
-	FC_AUTH_CEXP_PROTO_VER_NOT_SUPP 	= 0x0A,
-};
-
-enum auth_status {
-	FC_AUTH_STATE_INPROGRESS = 0, 	/*! authentication in progress 	*/
-	FC_AUTH_STATE_FAILED	= 1, 	/*! authentication failed */
-	FC_AUTH_STATE_SUCCESS	= 2 	/*! authentication successful	*/
-};
-
-struct auth_rjt_msg_s {
-	struct auth_els_msg_s	hdr;
-	u8		reason_code;
-	u8		reason_code_exp;
-	u8		rsvd[2];
-};
-
-
-struct auth_dhchap_neg_msg_s {
-	struct auth_els_msg_s hdr;
-	struct auth_neg_msg_s nego;
-};
-
-struct auth_dhchap_reply_msg_s {
-	struct auth_els_msg_s	hdr;
-
-	/*
-	 * followed by response value length & Value + DH Value Length & Value
-	 */
-};
-
-#pragma pack()
-
-#endif /* __FC_SP_H__ */
diff --git a/drivers/scsi/bfa/include/protocol/fcp.h b/drivers/scsi/bfa/include/protocol/fcp.h
deleted file mode 100644
index 74ea63c..0000000
--- a/drivers/scsi/bfa/include/protocol/fcp.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __FCPPROTO_H__
-#define __FCPPROTO_H__
-
-#include <linux/bitops.h>
-#include <protocol/scsi.h>
-
-#pragma pack(1)
-
-enum {
-	FCP_RJT		= 0x01000000,	/* SRR reject */
-	FCP_SRR_ACCEPT	= 0x02000000,	/* SRR accept */
-	FCP_SRR		= 0x14000000,	/* Sequence Retransmission Request */
-};
-
-/*
- * SRR FC-4 LS payload
- */
-struct fc_srr_s{
-	u32	ls_cmd;
-	u32        ox_id:16;	/* ox-id */
-	u32        rx_id:16;	/* rx-id */
-	u32        ro;		/* relative offset */
-	u32        r_ctl:8;		/* R_CTL for I.U. */
-	u32        res:24;
-};
-
-
-/*
- * FCP_CMND definitions
- */
-#define FCP_CMND_CDB_LEN    16
-#define FCP_CMND_LUN_LEN    8
-
-struct fcp_cmnd_s{
-	lun_t           lun;		/* 64-bit LU number */
-	u8         crn;		/* command reference number */
-#ifdef __BIGENDIAN
-	u8         resvd:1,
-			priority:4,	/* FCP-3: SAM-3 priority */
-			taskattr:3;	/* scsi task attribute */
-#else
-	u8         taskattr:3,	/* scsi task attribute */
-			priority:4,	/* FCP-3: SAM-3 priority */
-			resvd:1;
-#endif
-	u8         tm_flags;	/* task management flags */
-#ifdef __BIGENDIAN
-	u8         addl_cdb_len:6,	/* additional CDB length words */
-			iodir:2;	/* read/write FCP_DATA IUs */
-#else
-	u8         iodir:2,	/* read/write FCP_DATA IUs */
-			addl_cdb_len:6;	/* additional CDB length */
-#endif
-	struct scsi_cdb_s      cdb;
-
-	/*
-	 * !!! additional cdb bytes follows here!!!
-	 */
-	u32        fcp_dl;	/* bytes to be transferred */
-};
-
-#define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN)
-#define fcp_cmnd_fcpdl(_cmnd)	((&(_cmnd)->fcp_dl)[(_cmnd)->addl_cdb_len])
-
-/*
- * fcp_cmnd_t.iodir field values
- */
-enum fcp_iodir{
-	FCP_IODIR_NONE	= 0,
-	FCP_IODIR_WRITE = 1,
-	FCP_IODIR_READ	= 2,
-	FCP_IODIR_RW	= 3,
-};
-
-/*
- * Task attribute field
- */
-enum {
-	FCP_TASK_ATTR_SIMPLE	= 0,
-	FCP_TASK_ATTR_HOQ	= 1,
-	FCP_TASK_ATTR_ORDERED	= 2,
-	FCP_TASK_ATTR_ACA	= 4,
-	FCP_TASK_ATTR_UNTAGGED	= 5,	/* obsolete in FCP-3 */
-};
-
-/*
- * Task management flags field - only one bit shall be set
- */
-enum fcp_tm_cmnd{
-	FCP_TM_ABORT_TASK_SET	= BIT(1),
-	FCP_TM_CLEAR_TASK_SET	= BIT(2),
-	FCP_TM_LUN_RESET	= BIT(4),
-	FCP_TM_TARGET_RESET	= BIT(5),	/* obsolete in FCP-3 */
-	FCP_TM_CLEAR_ACA	= BIT(6),
-};
-
-/*
- * FCP_XFER_RDY IU defines
- */
-struct fcp_xfer_rdy_s{
-	u32        data_ro;
-	u32        burst_len;
-	u32        reserved;
-};
-
-/*
- * FCP_RSP residue flags
- */
-enum fcp_residue{
-	FCP_NO_RESIDUE = 0,	/* no residue */
-	FCP_RESID_OVER = 1,	/* more data left that was not sent */
-	FCP_RESID_UNDER = 2,	/* less data than requested */
-};
-
-enum {
-	FCP_RSPINFO_GOOD = 0,
-	FCP_RSPINFO_DATALEN_MISMATCH = 1,
-	FCP_RSPINFO_CMND_INVALID = 2,
-	FCP_RSPINFO_ROLEN_MISMATCH = 3,
-	FCP_RSPINFO_TM_NOT_SUPP = 4,
-	FCP_RSPINFO_TM_FAILED = 5,
-};
-
-struct fcp_rspinfo_s{
-	u32        res0:24;
-	u32        rsp_code:8;	/* response code (as above) */
-	u32        res1;
-};
-
-struct fcp_resp_s{
-	u32        reserved[2];	/* 2 words reserved */
-	u16        reserved2;
-#ifdef __BIGENDIAN
-	u8         reserved3:3;
-	u8         fcp_conf_req:1;	/* FCP_CONF is requested */
-	u8         resid_flags:2;	/* underflow/overflow */
-	u8         sns_len_valid:1;/* sense len is valid */
-	u8         rsp_len_valid:1;/* response len is valid */
-#else
-	u8         rsp_len_valid:1;/* response len is valid */
-	u8         sns_len_valid:1;/* sense len is valid */
-	u8         resid_flags:2;	/* underflow/overflow */
-	u8         fcp_conf_req:1;	/* FCP_CONF is requested */
-	u8         reserved3:3;
-#endif
-	u8         scsi_status;	/* one byte SCSI status */
-	u32        residue;	/* residual data bytes */
-	u32        sns_len;	/* length od sense info */
-	u32        rsp_len;	/* length of response info */
-};
-
-#define fcp_snslen(__fcprsp)	((__fcprsp)->sns_len_valid ? 		\
-					(__fcprsp)->sns_len : 0)
-#define fcp_rsplen(__fcprsp)	((__fcprsp)->rsp_len_valid ? 		\
-					(__fcprsp)->rsp_len : 0)
-#define fcp_rspinfo(__fcprsp)	((struct fcp_rspinfo_s *)((__fcprsp) + 1))
-#define fcp_snsinfo(__fcprsp)	(((u8 *)fcp_rspinfo(__fcprsp)) + 	\
-						fcp_rsplen(__fcprsp))
-
-struct fcp_cmnd_fr_s{
-	struct fchs_s          fchs;
-	struct fcp_cmnd_s      fcp;
-};
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/fdmi.h b/drivers/scsi/bfa/include/protocol/fdmi.h
deleted file mode 100644
index 6c05c26..0000000
--- a/drivers/scsi/bfa/include/protocol/fdmi.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __FDMI_H__
-#define __FDMI_H__
-
-#include <protocol/types.h>
-#include <protocol/fc.h>
-#include <protocol/ct.h>
-
-#pragma pack(1)
-
-/*
- * FDMI Command Codes
- */
-#define	FDMI_GRHL		0x0100
-#define	FDMI_GHAT		0x0101
-#define	FDMI_GRPL		0x0102
-#define	FDMI_GPAT		0x0110
-#define	FDMI_RHBA		0x0200
-#define	FDMI_RHAT		0x0201
-#define	FDMI_RPRT		0x0210
-#define	FDMI_RPA		0x0211
-#define	FDMI_DHBA		0x0300
-#define	FDMI_DPRT		0x0310
-
-/*
- * FDMI reason codes
- */
-#define	FDMI_NO_ADDITIONAL_EXP		0x00
-#define	FDMI_HBA_ALREADY_REG		0x10
-#define	FDMI_HBA_ATTRIB_NOT_REG		0x11
-#define	FDMI_HBA_ATTRIB_MULTIPLE	0x12
-#define	FDMI_HBA_ATTRIB_LENGTH_INVALID	0x13
-#define	FDMI_HBA_ATTRIB_NOT_PRESENT	0x14
-#define	FDMI_PORT_ORIG_NOT_IN_LIST	0x15
-#define	FDMI_PORT_HBA_NOT_IN_LIST	0x16
-#define	FDMI_PORT_ATTRIB_NOT_REG	0x20
-#define	FDMI_PORT_NOT_REG		0x21
-#define	FDMI_PORT_ATTRIB_MULTIPLE	0x22
-#define	FDMI_PORT_ATTRIB_LENGTH_INVALID	0x23
-#define	FDMI_PORT_ALREADY_REGISTEREED	0x24
-
-/*
- * FDMI Transmission Speed Mask values
- */
-#define	FDMI_TRANS_SPEED_1G		0x00000001
-#define	FDMI_TRANS_SPEED_2G		0x00000002
-#define	FDMI_TRANS_SPEED_10G		0x00000004
-#define	FDMI_TRANS_SPEED_4G		0x00000008
-#define	FDMI_TRANS_SPEED_8G		0x00000010
-#define	FDMI_TRANS_SPEED_16G		0x00000020
-#define	FDMI_TRANS_SPEED_UNKNOWN	0x00008000
-
-/*
- * FDMI HBA attribute types
- */
-enum fdmi_hba_attribute_type {
-	FDMI_HBA_ATTRIB_NODENAME = 1,	/* 0x0001 */
-	FDMI_HBA_ATTRIB_MANUFACTURER,	/* 0x0002 */
-	FDMI_HBA_ATTRIB_SERIALNUM,	/* 0x0003 */
-	FDMI_HBA_ATTRIB_MODEL,		/* 0x0004 */
-	FDMI_HBA_ATTRIB_MODEL_DESC,	/* 0x0005 */
-	FDMI_HBA_ATTRIB_HW_VERSION,	/* 0x0006 */
-	FDMI_HBA_ATTRIB_DRIVER_VERSION,	/* 0x0007 */
-	FDMI_HBA_ATTRIB_ROM_VERSION,	/* 0x0008 */
-	FDMI_HBA_ATTRIB_FW_VERSION,	/* 0x0009 */
-	FDMI_HBA_ATTRIB_OS_NAME,	/* 0x000A */
-	FDMI_HBA_ATTRIB_MAX_CT,		/* 0x000B */
-
-	FDMI_HBA_ATTRIB_MAX_TYPE
-};
-
-/*
- * FDMI Port attribute types
- */
-enum fdmi_port_attribute_type {
-	FDMI_PORT_ATTRIB_FC4_TYPES = 1,	/* 0x0001 */
-	FDMI_PORT_ATTRIB_SUPP_SPEED,	/* 0x0002 */
-	FDMI_PORT_ATTRIB_PORT_SPEED,	/* 0x0003 */
-	FDMI_PORT_ATTRIB_FRAME_SIZE,	/* 0x0004 */
-	FDMI_PORT_ATTRIB_DEV_NAME,	/* 0x0005 */
-	FDMI_PORT_ATTRIB_HOST_NAME,	/* 0x0006 */
-
-	FDMI_PORT_ATTR_MAX_TYPE
-};
-
-/*
- * FDMI attribute
- */
-struct fdmi_attr_s {
-	u16        type;
-	u16        len;
-	u8         value[1];
-};
-
-/*
- * HBA Attribute Block
- */
-struct fdmi_hba_attr_s {
-	u32        attr_count;	/* # of attributes */
-	struct fdmi_attr_s     hba_attr;	/* n attributes */
-};
-
-/*
- * Registered Port List
- */
-struct fdmi_port_list_s {
-	u32        num_ports;	/* number Of Port Entries */
-	wwn_t           port_entry;	/* one or more */
-};
-
-/*
- * Port Attribute Block
- */
-struct fdmi_port_attr_s {
-	u32        attr_count;	/* # of attributes */
-	struct fdmi_attr_s     port_attr;	/* n attributes */
-};
-
-/*
- * FDMI Register HBA Attributes
- */
-struct fdmi_rhba_s {
-	wwn_t           hba_id;		/* HBA Identifier */
-	struct fdmi_port_list_s port_list;	/* Registered Port List */
-	struct fdmi_hba_attr_s hba_attr_blk;	/* HBA attribute block */
-};
-
-/*
- * FDMI Register Port
- */
-struct fdmi_rprt_s {
-	wwn_t           hba_id;		/* HBA Identifier */
-	wwn_t           port_name;	/* Port wwn */
-	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */
-};
-
-/*
- * FDMI Register Port Attributes
- */
-struct fdmi_rpa_s {
-	wwn_t           port_name;	/* port wwn */
-	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */
-};
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/scsi.h b/drivers/scsi/bfa/include/protocol/scsi.h
deleted file mode 100644
index b220e6b..0000000
--- a/drivers/scsi/bfa/include/protocol/scsi.h
+++ /dev/null
@@ -1,1648 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __SCSI_H__
-#define __SCSI_H__
-
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-/*
- * generic SCSI cdb definition
- */
-#define SCSI_MAX_CDBLEN     16
-struct scsi_cdb_s{
-	u8         scsi_cdb[SCSI_MAX_CDBLEN];
-};
-
-/*
- * scsi lun serial number definition
- */
-#define SCSI_LUN_SN_LEN     32
-struct scsi_lun_sn_s{
-	u8         lun_sn[SCSI_LUN_SN_LEN];
-};
-
-/*
- * SCSI Direct Access Commands
- */
-enum {
-	SCSI_OP_TEST_UNIT_READY		= 0x00,
-	SCSI_OP_REQUEST_SENSE		= 0x03,
-	SCSI_OP_FORMAT_UNIT		= 0x04,
-	SCSI_OP_READ6			= 0x08,
-	SCSI_OP_WRITE6			= 0x0A,
-	SCSI_OP_WRITE_FILEMARKS		= 0x10,
-	SCSI_OP_INQUIRY			= 0x12,
-	SCSI_OP_MODE_SELECT6		= 0x15,
-	SCSI_OP_RESERVE6		= 0x16,
-	SCSI_OP_RELEASE6		= 0x17,
-	SCSI_OP_MODE_SENSE6		= 0x1A,
-	SCSI_OP_START_STOP_UNIT		= 0x1B,
-	SCSI_OP_SEND_DIAGNOSTIC		= 0x1D,
-	SCSI_OP_READ_CAPACITY		= 0x25,
-	SCSI_OP_READ10			= 0x28,
-	SCSI_OP_WRITE10			= 0x2A,
-	SCSI_OP_VERIFY10		= 0x2F,
-	SCSI_OP_READ_DEFECT_DATA	= 0x37,
-	SCSI_OP_LOG_SELECT		= 0x4C,
-	SCSI_OP_LOG_SENSE		= 0x4D,
-	SCSI_OP_MODE_SELECT10		= 0x55,
-	SCSI_OP_RESERVE10		= 0x56,
-	SCSI_OP_RELEASE10		= 0x57,
-	SCSI_OP_MODE_SENSE10		= 0x5A,
-	SCSI_OP_PER_RESERVE_IN		= 0x5E,
-	SCSI_OP_PER_RESERVE_OUR		= 0x5E,
-	SCSI_OP_READ16			= 0x88,
-	SCSI_OP_WRITE16			= 0x8A,
-	SCSI_OP_VERIFY16		= 0x8F,
-	SCSI_OP_READ_CAPACITY16		= 0x9E,
-	SCSI_OP_REPORT_LUNS		= 0xA0,
-	SCSI_OP_READ12			= 0xA8,
-	SCSI_OP_WRITE12			= 0xAA,
-	SCSI_OP_UNDEF			= 0xFF,
-};
-
-/*
- * SCSI START_STOP_UNIT command
- */
-struct scsi_start_stop_unit_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         reserved1:4;
-	u8         immed:1;
-#else
-	u8         immed:1;
-	u8         reserved1:4;
-	u8         lun:3;
-#endif
-	u8         reserved2;
-	u8         reserved3;
-#ifdef __BIGENDIAN
-	u8         power_conditions:4;
-	u8         reserved4:2;
-	u8         loEj:1;
-	u8         start:1;
-#else
-	u8         start:1;
-	u8         loEj:1;
-	u8         reserved4:2;
-	u8         power_conditions:4;
-#endif
-	u8         control;
-};
-
-/*
- * SCSI SEND_DIAGNOSTIC command
- */
-struct scsi_send_diagnostic_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         self_test_code:3;
-	u8         pf:1;
-	u8         reserved1:1;
-	u8         self_test:1;
-	u8         dev_offl:1;
-	u8         unit_offl:1;
-#else
-	u8         unit_offl:1;
-	u8         dev_offl:1;
-	u8         self_test:1;
-	u8         reserved1:1;
-	u8         pf:1;
-	u8         self_test_code:3;
-#endif
-	u8         reserved2;
-
-	u8         param_list_length[2];	/* MSB first */
-	u8         control;
-
-};
-
-/*
- * SCSI READ10/WRITE10 commands
- */
-struct scsi_rw10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         dpo:1;	/* Disable Page Out */
-	u8         fua:1;	/* Force Unit Access */
-	u8         reserved1:2;
-	u8         rel_adr:1;	/* relative address */
-#else
-	u8         rel_adr:1;
-	u8         reserved1:2;
-	u8         fua:1;
-	u8         dpo:1;
-	u8         lun:3;
-#endif
-	u8         lba0;	/* logical block address - MSB */
-	u8         lba1;
-	u8         lba2;
-	u8         lba3;	/* LSB */
-	u8         reserved3;
-	u8         xfer_length0;	/* transfer length in blocks - MSB */
-	u8         xfer_length1;	/* LSB */
-	u8         control;
-};
-
-#define SCSI_CDB10_GET_LBA(cdb)                     \
-    (((cdb)->lba0 << 24) | ((cdb)->lba1 << 16) |    \
-     ((cdb)->lba2 << 8) | (cdb)->lba3)
-
-#define SCSI_CDB10_SET_LBA(cdb, lba) {      \
-    (cdb)->lba0 = lba >> 24;            \
-    (cdb)->lba1 = (lba >> 16) & 0xFF;   \
-    (cdb)->lba2 = (lba >> 8) & 0xFF;    \
-    (cdb)->lba3 = lba & 0xFF;           \
-}
-
-#define SCSI_CDB10_GET_TL(cdb)  \
-    ((cdb)->xfer_length0 << 8 | (cdb)->xfer_length1)
-#define SCSI_CDB10_SET_TL(cdb, tl) {      \
-    (cdb)->xfer_length0 = tl >> 8;       \
-    (cdb)->xfer_length1 = tl & 0xFF;     \
-}
-
-/*
- * SCSI READ6/WRITE6 commands
- */
-struct scsi_rw6_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         lba0:5;		/* MSb */
-#else
-	u8         lba0:5;		/* MSb */
-	u8         lun:3;
-#endif
-	u8         lba1;
-	u8         lba2;		/* LSB */
-	u8         xfer_length;
-	u8         control;
-};
-
-#define SCSI_TAPE_CDB6_GET_TL(cdb)              \
-    (((cdb)->tl0 << 16) | ((cdb)->tl1 << 8) | (cdb)->tl2)
-
-#define SCSI_TAPE_CDB6_SET_TL(cdb, tl) {      \
-    (cdb)->tl0 = tl >> 16;            \
-    (cdb)->tl1 = (tl >> 8) & 0xFF;    \
-    (cdb)->tl2 = tl & 0xFF;           \
-}
-
-/*
- * SCSI sequential (TAPE) wrtie command
- */
-struct scsi_tape_wr_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         rsvd:7;
-	u8         fixed:1;	/* MSb */
-#else
-	u8         fixed:1;	/* MSb */
-	u8         rsvd:7;
-#endif
-	u8         tl0;		/* Msb */
-	u8         tl1;
-	u8         tl2;		/* Lsb */
-
-	u8         control;
-};
-
-#define SCSI_CDB6_GET_LBA(cdb)              \
-    (((cdb)->lba0 << 16) | ((cdb)->lba1 << 8) | (cdb)->lba2)
-
-#define SCSI_CDB6_SET_LBA(cdb, lba) {      \
-    (cdb)->lba0 = lba >> 16;            \
-    (cdb)->lba1 = (lba >> 8) & 0xFF;    \
-    (cdb)->lba2 = lba & 0xFF;           \
-}
-
-#define SCSI_CDB6_GET_TL(cdb) ((cdb)->xfer_length)
-#define SCSI_CDB6_SET_TL(cdb, tl) {      \
-    (cdb)->xfer_length = tl;         \
-}
-
-/*
- * SCSI sense data format
- */
-struct scsi_sense_s{
-#ifdef __BIGENDIAN
-	u8         valid:1;
-	u8         rsp_code:7;
-#else
-	u8         rsp_code:7;
-	u8         valid:1;
-#endif
-	u8         seg_num;
-#ifdef __BIGENDIAN
-	u8         file_mark:1;
-	u8         eom:1;		/* end of media */
-	u8         ili:1;		/* incorrect length indicator */
-	u8         reserved:1;
-	u8         sense_key:4;
-#else
-	u8         sense_key:4;
-	u8         reserved:1;
-	u8         ili:1;		/* incorrect length indicator */
-	u8         eom:1;		/* end of media */
-	u8         file_mark:1;
-#endif
-	u8         information[4];	/* device-type or command specific info
-					 */
-	u8         add_sense_length;
-					/* additional sense length */
-	u8         command_info[4];/* command specific information
-						 */
-	u8         asc;		/* additional sense code */
-	u8         ascq;		/* additional sense code qualifier */
-	u8         fru_code;	/* field replaceable unit code */
-#ifdef __BIGENDIAN
-	u8         sksv:1;		/* sense key specific valid */
-	u8         c_d:1;		/* command/data bit */
-	u8         res1:2;
-	u8         bpv:1;		/* bit pointer valid */
-	u8         bpointer:3;	/* bit pointer */
-#else
-	u8         bpointer:3;	/* bit pointer */
-	u8         bpv:1;		/* bit pointer valid */
-	u8         res1:2;
-	u8         c_d:1;		/* command/data bit */
-	u8         sksv:1;		/* sense key specific valid */
-#endif
-	u8         fpointer[2];	/* field pointer */
-};
-
-#define SCSI_SENSE_CUR_ERR          0x70
-#define SCSI_SENSE_DEF_ERR          0x71
-
-/*
- * SCSI sense key values
- */
-#define SCSI_SK_NO_SENSE        0x0
-#define SCSI_SK_REC_ERR         0x1	/* recovered error */
-#define SCSI_SK_NOT_READY       0x2
-#define SCSI_SK_MED_ERR         0x3	/* medium error */
-#define SCSI_SK_HW_ERR          0x4	/* hardware error */
-#define SCSI_SK_ILLEGAL_REQ     0x5
-#define SCSI_SK_UNIT_ATT        0x6	/* unit attention */
-#define SCSI_SK_DATA_PROTECT    0x7
-#define SCSI_SK_BLANK_CHECK     0x8
-#define SCSI_SK_VENDOR_SPEC     0x9
-#define SCSI_SK_COPY_ABORTED    0xA
-#define SCSI_SK_ABORTED_CMND    0xB
-#define SCSI_SK_VOL_OVERFLOW    0xD
-#define SCSI_SK_MISCOMPARE      0xE
-
-/*
- * SCSI additional sense codes
- */
-#define SCSI_ASC_NO_ADD_SENSE           0x00
-#define SCSI_ASC_LUN_NOT_READY          0x04
-#define SCSI_ASC_LUN_COMMUNICATION      0x08
-#define SCSI_ASC_WRITE_ERROR            0x0C
-#define SCSI_ASC_INVALID_CMND_CODE      0x20
-#define SCSI_ASC_BAD_LBA                0x21
-#define SCSI_ASC_INVALID_FIELD_IN_CDB   0x24
-#define SCSI_ASC_LUN_NOT_SUPPORTED      0x25
-#define SCSI_ASC_LUN_WRITE_PROTECT      0x27
-#define SCSI_ASC_POWERON_BDR            0x29	/* power on reset, bus reset,
-						 * bus device reset
-						 */
-#define SCSI_ASC_PARAMS_CHANGED         0x2A
-#define SCSI_ASC_CMND_CLEARED_BY_A_I    0x2F
-#define SCSI_ASC_SAVING_PARAM_NOTSUPP   0x39
-#define SCSI_ASC_TOCC                   0x3F	/* target operating condtions
-						 * changed
-						 */
-#define SCSI_ASC_PARITY_ERROR           0x47
-#define SCSI_ASC_CMND_PHASE_ERROR       0x4A
-#define SCSI_ASC_DATA_PHASE_ERROR       0x4B
-#define SCSI_ASC_VENDOR_SPEC            0x7F
-
-/*
- * SCSI additional sense code qualifiers
- */
-#define SCSI_ASCQ_CAUSE_NOT_REPORT      0x00
-#define SCSI_ASCQ_BECOMING_READY        0x01
-#define SCSI_ASCQ_INIT_CMD_REQ          0x02
-#define SCSI_ASCQ_FORMAT_IN_PROGRESS    0x04
-#define SCSI_ASCQ_OPERATION_IN_PROGRESS 0x07
-#define SCSI_ASCQ_SELF_TEST_IN_PROGRESS 0x09
-#define SCSI_ASCQ_WR_UNEXP_UNSOL_DATA   0x0C
-#define SCSI_ASCQ_WR_NOTENG_UNSOL_DATA  0x0D
-
-#define SCSI_ASCQ_LBA_OUT_OF_RANGE      0x00
-#define SCSI_ASCQ_INVALID_ELEMENT_ADDR  0x01
-
-#define SCSI_ASCQ_LUN_WRITE_PROTECTED       0x00
-#define SCSI_ASCQ_LUN_HW_WRITE_PROTECTED    0x01
-#define SCSI_ASCQ_LUN_SW_WRITE_PROTECTED    0x02
-
-#define SCSI_ASCQ_POR   0x01	/* power on reset */
-#define SCSI_ASCQ_SBR   0x02	/* scsi bus reset */
-#define SCSI_ASCQ_BDR   0x03	/* bus device reset */
-#define SCSI_ASCQ_DIR   0x04	/* device internal reset */
-
-#define SCSI_ASCQ_MODE_PARAMS_CHANGED       0x01
-#define SCSI_ASCQ_LOG_PARAMS_CHANGED        0x02
-#define SCSI_ASCQ_RESERVATIONS_PREEMPTED    0x03
-#define SCSI_ASCQ_RESERVATIONS_RELEASED     0x04
-#define SCSI_ASCQ_REGISTRATIONS_PREEMPTED   0x05
-
-#define SCSI_ASCQ_MICROCODE_CHANGED 0x01
-#define SCSI_ASCQ_CHANGED_OPER_COND 0x02
-#define SCSI_ASCQ_INQ_CHANGED       0x03	/* inquiry data changed */
-#define SCSI_ASCQ_DI_CHANGED        0x05	/* device id changed */
-#define SCSI_ASCQ_RL_DATA_CHANGED   0x0E	/* report luns data changed */
-
-#define SCSI_ASCQ_DP_CRC_ERR            0x01	/* data phase crc error */
-#define SCSI_ASCQ_DP_SCSI_PARITY_ERR    0x02	/* data phase scsi parity error
-						 */
-#define SCSI_ASCQ_IU_CRC_ERR            0x03	/* information unit crc error */
-#define SCSI_ASCQ_PROTO_SERV_CRC_ERR    0x05
-
-#define SCSI_ASCQ_LUN_TIME_OUT          0x01
-
-/* ------------------------------------------------------------
- * SCSI INQUIRY
- * ------------------------------------------------------------*/
-
-struct scsi_inquiry_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         reserved1:3;
-	u8         cmd_dt:1;
-	u8         evpd:1;
-#else
-	u8         evpd:1;
-	u8         cmd_dt:1;
-	u8         reserved1:3;
-	u8         lun:3;
-#endif
-	u8         page_code;
-	u8         reserved2;
-	u8         alloc_length;
-	u8         control;
-};
-
-struct scsi_inquiry_vendor_s{
-	u8         vendor_id[8];
-};
-
-struct scsi_inquiry_prodid_s{
-	u8         product_id[16];
-};
-
-struct scsi_inquiry_prodrev_s{
-	u8         product_rev[4];
-};
-
-struct scsi_inquiry_data_s{
-#ifdef __BIGENDIAN
-	u8         peripheral_qual:3;	/* peripheral qualifier */
-	u8         device_type:5;		/* peripheral device type */
-
-	u8         rmb:1;			/* removable medium bit */
-	u8         device_type_mod:7;	/* device type modifier */
-
-	u8         version;
-
-	u8         aenc:1;		/* async event notification capability
-					 */
-	u8         trm_iop:1;	/* terminate I/O process */
-	u8         norm_aca:1;	/* normal ACA supported */
-	u8         hi_support:1;	/* SCSI-3: supports REPORT LUNS */
-	u8         rsp_data_format:4;
-
-	u8         additional_len;
-	u8         sccs:1;
-	u8         reserved1:7;
-
-	u8         reserved2:1;
-	u8         enc_serv:1;	/* enclosure service component */
-	u8         reserved3:1;
-	u8         multi_port:1;	/* multi-port device */
-	u8         m_chngr:1;	/* device in medium transport element */
-	u8         ack_req_q:1;	/* SIP specific bit */
-	u8         addr32:1;	/* SIP specific bit */
-	u8         addr16:1;	/* SIP specific bit */
-
-	u8         rel_adr:1;	/* relative address */
-	u8         w_bus32:1;
-	u8         w_bus16:1;
-	u8         synchronous:1;
-	u8         linked_commands:1;
-	u8         trans_dis:1;
-	u8         cmd_queue:1;	/* command queueing supported */
-	u8         soft_reset:1;	/* soft reset alternative (VS) */
-#else
-	u8         device_type:5;	/* peripheral device type */
-	u8         peripheral_qual:3;
-					/* peripheral qualifier */
-
-	u8         device_type_mod:7;
-					/* device type modifier */
-	u8         rmb:1;		/* removable medium bit */
-
-	u8         version;
-
-	u8         rsp_data_format:4;
-	u8         hi_support:1;	/* SCSI-3: supports REPORT LUNS */
-	u8         norm_aca:1;	/* normal ACA supported */
-	u8         terminate_iop:1;/* terminate I/O process */
-	u8         aenc:1;		/* async event notification capability
-					 */
-
-	u8         additional_len;
-	u8         reserved1:7;
-	u8         sccs:1;
-
-	u8         addr16:1;	/* SIP specific bit */
-	u8         addr32:1;	/* SIP specific bit */
-	u8         ack_req_q:1;	/* SIP specific bit */
-	u8         m_chngr:1;	/* device in medium transport element */
-	u8         multi_port:1;	/* multi-port device */
-	u8         reserved3:1;	/* TBD - Vendor Specific */
-	u8         enc_serv:1;	/* enclosure service component */
-	u8         reserved2:1;
-
-	u8         soft_seset:1;	/* soft reset alternative (VS) */
-	u8         cmd_queue:1;	/* command queueing supported */
-	u8         trans_dis:1;
-	u8         linked_commands:1;
-	u8         synchronous:1;
-	u8         w_bus16:1;
-	u8         w_bus32:1;
-	u8         rel_adr:1;	/* relative address */
-#endif
-	struct scsi_inquiry_vendor_s vendor_id;
-	struct scsi_inquiry_prodid_s product_id;
-	struct scsi_inquiry_prodrev_s product_rev;
-	u8         vendor_specific[20];
-	u8         reserved4[40];
-};
-
-/*
- * inquiry.peripheral_qual field values
- */
-#define SCSI_DEVQUAL_DEFAULT        0
-#define SCSI_DEVQUAL_NOT_CONNECTED  1
-#define SCSI_DEVQUAL_NOT_SUPPORTED  3
-
-/*
- * inquiry.device_type field values
- */
-#define SCSI_DEVICE_DIRECT_ACCESS       0x00
-#define SCSI_DEVICE_SEQ_ACCESS          0x01
-#define SCSI_DEVICE_ARRAY_CONTROLLER    0x0C
-#define SCSI_DEVICE_UNKNOWN             0x1F
-
-/*
- * inquiry.version
- */
-#define SCSI_VERSION_ANSI_X3131     2	/* ANSI X3.131 SCSI-2 */
-#define SCSI_VERSION_SPC            3	/* SPC (SCSI-3), ANSI X3.301:1997 */
-#define SCSI_VERSION_SPC_2          4	/* SPC-2 */
-
-/*
- * response data format
- */
-#define SCSI_RSP_DATA_FORMAT        2	/* SCSI-2 & SPC */
-
-/*
- * SCSI inquiry page codes
- */
-#define SCSI_INQ_PAGE_VPD_PAGES     0x00	/* supported vpd pages */
-#define SCSI_INQ_PAGE_USN_PAGE      0x80	/* unit serial number page */
-#define SCSI_INQ_PAGE_DEV_IDENT     0x83	/* device indentification page
-						 */
-#define SCSI_INQ_PAGES_MAX          3
-
-/*
- * supported vital product data pages
- */
-struct scsi_inq_page_vpd_pages_s{
-#ifdef __BIGENDIAN
-	u8         peripheral_qual:3;
-	u8         device_type:5;
-#else
-	u8         device_type:5;
-	u8         peripheral_qual:3;
-#endif
-	u8         page_code;
-	u8         reserved;
-	u8         page_length;
-	u8         pages[SCSI_INQ_PAGES_MAX];
-};
-
-/*
- * Unit serial number page
- */
-#define SCSI_INQ_USN_LEN 32
-
-struct scsi_inq_usn_s{
-	char            usn[SCSI_INQ_USN_LEN];
-};
-
-struct scsi_inq_page_usn_s{
-#ifdef __BIGENDIAN
-	u8         peripheral_qual:3;
-	u8         device_type:5;
-#else
-	u8         device_type:5;
-	u8         peripheral_qual:3;
-#endif
-	u8         page_code;
-	u8         reserved1;
-	u8         page_length;
-	struct scsi_inq_usn_s  usn;
-};
-
-enum {
-	SCSI_INQ_DIP_CODE_BINARY = 1,	/* identifier has binary value */
-	SCSI_INQ_DIP_CODE_ASCII = 2,	/* identifier has ascii value */
-};
-
-enum {
-	SCSI_INQ_DIP_ASSOC_LUN = 0,	/* id is associated with device */
-	SCSI_INQ_DIP_ASSOC_PORT = 1,	/* id is associated with port that
-					 * received the request
-					 */
-};
-
-enum {
-	SCSI_INQ_ID_TYPE_VENDOR = 1,
-	SCSI_INQ_ID_TYPE_IEEE = 2,
-	SCSI_INQ_ID_TYPE_FC_FS = 3,
-	SCSI_INQ_ID_TYPE_OTHER = 4,
-};
-
-struct scsi_inq_dip_desc_s{
-#ifdef __BIGENDIAN
-	u8         res0:4;
-	u8         code_set:4;
-	u8         res1:2;
-	u8         association:2;
-	u8         id_type:4;
-#else
-	u8         code_set:4;
-	u8         res0:4;
-	u8         id_type:4;
-	u8         association:2;
-	u8         res1:2;
-#endif
-	u8         res2;
-	u8         id_len;
-	struct scsi_lun_sn_s   id;
-};
-
-/*
- * Device indentification page
- */
-struct scsi_inq_page_dev_ident_s{
-#ifdef __BIGENDIAN
-	u8         peripheral_qual:3;
-	u8         device_type:5;
-#else
-	u8         device_type:5;
-	u8         peripheral_qual:3;
-#endif
-	u8         page_code;
-	u8         reserved1;
-	u8         page_length;
-	struct scsi_inq_dip_desc_s desc;
-};
-
-/* ------------------------------------------------------------
- * READ CAPACITY
- * ------------------------------------------------------------
- */
-
-struct scsi_read_capacity_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         reserved1:4;
-	u8         rel_adr:1;
-#else
-	u8         rel_adr:1;
-	u8         reserved1:4;
-	u8         lun:3;
-#endif
-	u8         lba0;	/* MSB */
-	u8         lba1;
-	u8         lba2;
-	u8         lba3;	/* LSB */
-	u8         reserved2;
-	u8         reserved3;
-#ifdef __BIGENDIAN
-	u8         reserved4:7;
-	u8         pmi:1;	/* partial medium indicator */
-#else
-	u8         pmi:1;	/* partial medium indicator */
-	u8         reserved4:7;
-#endif
-	u8         control;
-};
-
-struct scsi_read_capacity_data_s{
-	u32        max_lba;	/* maximum LBA available */
-	u32        block_length;	/* in bytes */
-};
-
-struct scsi_read_capacity16_data_s{
-	u64        lba;	/* maximum LBA available */
-	u32        block_length;	/* in bytes */
-#ifdef __BIGENDIAN
-	u8         reserved1:4,
-			p_type:3,
-			prot_en:1;
-	u8		reserved2:4,
-			lb_pbe:4;	/* logical blocks per physical block
-					 * exponent */
-	u16	reserved3:2,
-			lba_align:14;	/* lowest aligned logical block
-					 * address */
-#else
-	u16	lba_align:14,	/* lowest aligned logical block
-					 * address */
-			reserved3:2;
-	u8		lb_pbe:4,	/* logical blocks per physical block
-					 * exponent */
-			reserved2:4;
-	u8		prot_en:1,
-			p_type:3,
-			reserved1:4;
-#endif
-	u64	reserved4;
-	u64	reserved5;
-};
-
-/* ------------------------------------------------------------
- * REPORT LUNS command
- * ------------------------------------------------------------
- */
-
-struct scsi_report_luns_s{
-	u8         opcode;		/* A0h - REPORT LUNS opCode */
-	u8         reserved1[5];
-	u8         alloc_length[4];/* allocation length MSB first */
-	u8         reserved2;
-	u8         control;
-};
-
-#define SCSI_REPORT_LUN_ALLOC_LENGTH(rl)                		\
-    ((rl->alloc_length[0] << 24) | (rl->alloc_length[1] << 16) | 	\
-     (rl->alloc_length[2] << 8) | (rl->alloc_length[3]))
-
-#define SCSI_REPORT_LUNS_SET_ALLOCLEN(rl, alloc_len) {      \
-    (rl)->alloc_length[0] = (alloc_len) >> 24;      			\
-    (rl)->alloc_length[1] = ((alloc_len) >> 16) & 0xFF; 		\
-    (rl)->alloc_length[2] = ((alloc_len) >> 8) & 0xFF;  		\
-    (rl)->alloc_length[3] = (alloc_len) & 0xFF;     			\
-}
-
-struct scsi_report_luns_data_s{
-	u32        lun_list_length;	/* length of LUN list length */
-	u32        reserved;
-	lun_t           lun[1];			/* first LUN in lun list */
-};
-
-/* -------------------------------------------------------------
- * SCSI mode  parameters
- * -----------------------------------------------------------
- */
-enum {
-	SCSI_DA_MEDIUM_DEF = 0,	/* direct access default medium type */
-	SCSI_DA_MEDIUM_SS = 1,	/* direct access single sided */
-	SCSI_DA_MEDIUM_DS = 2,	/* direct access double sided */
-};
-
-/*
- * SCSI Mode Select(6) cdb
- */
-struct scsi_mode_select6_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         pf:1;		/* page format */
-	u8         reserved2:3;
-	u8         sp:1;		/* save pages if set to 1 */
-#else
-	u8         sp:1;	/* save pages if set to 1 */
-	u8         reserved2:3;
-	u8         pf:1;	/* page format */
-	u8         reserved1:3;
-#endif
-	u8         reserved3[2];
-	u8         alloc_len;
-	u8         control;
-};
-
-/*
- * SCSI Mode Select(10) cdb
- */
-struct scsi_mode_select10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         pf:1;	/* page format */
-	u8         reserved2:3;
-	u8         sp:1;	/* save pages if set to 1 */
-#else
-	u8         sp:1;	/* save pages if set to 1 */
-	u8         reserved2:3;
-	u8         pf:1;	/* page format */
-	u8         reserved1:3;
-#endif
-	u8         reserved3[5];
-	u8         alloc_len_msb;
-	u8         alloc_len_lsb;
-	u8         control;
-};
-
-/*
- * SCSI Mode Sense(6) cdb
- */
-struct scsi_mode_sense6_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:4;
-	u8         dbd:1;	/* disable block discriptors if set to 1 */
-	u8         reserved2:3;
-
-	u8         pc:2;	/* page control */
-	u8         page_code:6;
-#else
-	u8         reserved2:3;
-	u8         dbd:1;	/* disable block descriptors if set to 1 */
-	u8         reserved1:4;
-
-	u8         page_code:6;
-	u8         pc:2;	/* page control */
-#endif
-	u8         reserved3;
-	u8         alloc_len;
-	u8         control;
-};
-
-/*
- * SCSI Mode Sense(10) cdb
- */
-struct scsi_mode_sense10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         LLBAA:1;	/* long LBA accepted if set to 1 */
-	u8         dbd:1;		/* disable block descriptors if set
-					 * to 1
-					 */
-	u8         reserved2:3;
-
-	u8         pc:2;		/* page control */
-	u8         page_code:6;
-#else
-	u8         reserved2:3;
-	u8         dbd:1;		/* disable block descriptors if set to
-					 * 1
-					 */
-	u8         LLBAA:1;	/* long LBA accepted if set to 1 */
-	u8         reserved1:3;
-
-	u8         page_code:6;
-	u8         pc:2;		/* page control */
-#endif
-	u8         reserved3[4];
-	u8         alloc_len_msb;
-	u8         alloc_len_lsb;
-	u8         control;
-};
-
-#define SCSI_CDB10_GET_AL(cdb)  					\
-    ((cdb)->alloc_len_msb << 8 | (cdb)->alloc_len_lsb)
-
-#define SCSI_CDB10_SET_AL(cdb, al) {      \
-    (cdb)->alloc_len_msb = al >> 8;       				\
-    (cdb)->alloc_len_lsb = al & 0xFF;     				\
-}
-
-#define SCSI_CDB6_GET_AL(cdb) ((cdb)->alloc_len)
-
-#define SCSI_CDB6_SET_AL(cdb, al) {      \
-    (cdb)->alloc_len = al;         					\
-}
-
-/*
- * page control field values
- */
-#define SCSI_PC_CURRENT_VALUES       0x0
-#define SCSI_PC_CHANGEABLE_VALUES    0x1
-#define SCSI_PC_DEFAULT_VALUES       0x2
-#define SCSI_PC_SAVED_VALUES         0x3
-
-/*
- * SCSI mode page codes
- */
-#define SCSI_MP_VENDOR_SPEC     0x00
-#define SCSI_MP_DISC_RECN       0x02	/* disconnect-reconnect page */
-#define SCSI_MP_FORMAT_DEVICE   0x03
-#define SCSI_MP_RDG             0x04	/* rigid disk geometry page */
-#define SCSI_MP_FDP             0x05	/* flexible disk page */
-#define SCSI_MP_CACHING         0x08	/* caching page */
-#define SCSI_MP_CONTROL         0x0A	/* control mode page */
-#define SCSI_MP_MED_TYPES_SUP   0x0B	/* medium types supported page */
-#define SCSI_MP_INFO_EXCP_CNTL  0x1C	/* informational exception control */
-#define SCSI_MP_ALL             0x3F	/* return all pages - mode sense only */
-
-/*
- * mode parameter header
- */
-struct scsi_mode_param_header6_s{
-	u8         mode_datalen;
-	u8         medium_type;
-
-	/*
-	 * device specific parameters expanded for direct access devices
-	 */
-#ifdef __BIGENDIAN
-	u32        wp:1;		/* write protected */
-	u32        reserved1:2;
-	u32        dpofua:1;	/* disable page out + force unit access
-					 */
-	u32        reserved2:4;
-#else
-	u32        reserved2:4;
-	u32        dpofua:1;	/* disable page out + force unit access
-					 */
-	u32        reserved1:2;
-	u32        wp:1;		/* write protected */
-#endif
-
-	u8         block_desclen;
-};
-
-struct scsi_mode_param_header10_s{
-	u32        mode_datalen:16;
-	u32        medium_type:8;
-
-	/*
-	 * device specific parameters expanded for direct access devices
-	 */
-#ifdef __BIGENDIAN
-	u32        wp:1;		/* write protected */
-	u32        reserved1:2;
-	u32        dpofua:1;	/* disable page out + force unit access
-					 */
-	u32        reserved2:4;
-#else
-	u32        reserved2:4;
-	u32        dpofua:1;	/* disable page out + force unit access
-					 */
-	u32        reserved1:2;
-	u32        wp:1;		/* write protected */
-#endif
-
-#ifdef __BIGENDIAN
-	u32        reserved3:7;
-	u32        longlba:1;
-#else
-	u32        longlba:1;
-	u32        reserved3:7;
-#endif
-	u32        reserved4:8;
-	u32        block_desclen:16;
-};
-
-/*
- * mode parameter block descriptor
- */
-struct scsi_mode_param_desc_s{
-	u32        nblks;
-	u32        density_code:8;
-	u32        block_length:24;
-};
-
-/*
- * Disconnect-reconnect mode page format
- */
-struct scsi_mp_disc_recn_s{
-#ifdef __BIGENDIAN
-	u8         ps:1;
-	u8         reserved1:1;
-	u8         page_code:6;
-#else
-	u8         page_code:6;
-	u8         reserved1:1;
-	u8         ps:1;
-#endif
-	u8         page_len;
-	u8         buf_full_ratio;
-	u8         buf_empty_ratio;
-
-	u8         bil_msb;	/* bus inactivity limit -MSB */
-	u8         bil_lsb;	/* bus inactivity limit -LSB */
-
-	u8         dtl_msb;	/* disconnect time limit - MSB */
-	u8         dtl_lsb;	/* disconnect time limit - LSB */
-
-	u8         ctl_msb;	/* connect time limit - MSB */
-	u8         ctl_lsb;	/* connect time limit - LSB */
-
-	u8         max_burst_len_msb;
-	u8         max_burst_len_lsb;
-#ifdef __BIGENDIAN
-	u8         emdp:1;	/* enable modify data pointers */
-	u8         fa:3;	/* fair arbitration */
-	u8         dimm:1;	/* disconnect immediate */
-	u8         dtdc:3;	/* data transfer disconnect control */
-#else
-	u8         dtdc:3;	/* data transfer disconnect control */
-	u8         dimm:1;	/* disconnect immediate */
-	u8         fa:3;	/* fair arbitration */
-	u8         emdp:1;	/* enable modify data pointers */
-#endif
-
-	u8         reserved3;
-
-	u8         first_burst_len_msb;
-	u8         first_burst_len_lsb;
-};
-
-/*
- * SCSI format device mode page
- */
-struct scsi_mp_format_device_s{
-#ifdef __BIGENDIAN
-	u32        ps:1;
-	u32        reserved1:1;
-	u32        page_code:6;
-#else
-	u32        page_code:6;
-	u32        reserved1:1;
-	u32        ps:1;
-#endif
-	u32        page_len:8;
-	u32        tracks_per_zone:16;
-
-	u32        a_sec_per_zone:16;
-	u32        a_tracks_per_zone:16;
-
-	u32        a_tracks_per_lun:16;	/* alternate tracks/lun-MSB */
-	u32        sec_per_track:16;	/* sectors/track-MSB */
-
-	u32        bytes_per_sector:16;
-	u32        interleave:16;
-
-	u32        tsf:16;			/* track skew factor-MSB */
-	u32        csf:16;			/* cylinder skew factor-MSB */
-
-#ifdef __BIGENDIAN
-	u32        ssec:1;	/* soft sector formatting */
-	u32        hsec:1;	/* hard sector formatting */
-	u32        rmb:1;	/* removable media */
-	u32        surf:1;	/* surface */
-	u32        reserved2:4;
-#else
-	u32        reserved2:4;
-	u32        surf:1;	/* surface */
-	u32        rmb:1;	/* removable media */
-	u32        hsec:1;	/* hard sector formatting */
-	u32        ssec:1;	/* soft sector formatting */
-#endif
-	u32        reserved3:24;
-};
-
-/*
- * SCSI rigid disk device geometry page
- */
-struct scsi_mp_rigid_device_geometry_s{
-#ifdef __BIGENDIAN
-	u32        ps:1;
-	u32        reserved1:1;
-	u32        page_code:6;
-#else
-	u32        page_code:6;
-	u32        reserved1:1;
-	u32        ps:1;
-#endif
-	u32        page_len:8;
-	u32        num_cylinders0:8;
-	u32        num_cylinders1:8;
-
-	u32        num_cylinders2:8;
-	u32        num_heads:8;
-	u32        scwp0:8;
-	u32        scwp1:8;
-
-	u32        scwp2:8;
-	u32        scrwc0:8;
-	u32        scrwc1:8;
-	u32        scrwc2:8;
-
-	u32        dsr:16;
-	u32        lscyl0:8;
-	u32        lscyl1:8;
-
-	u32        lscyl2:8;
-#ifdef __BIGENDIAN
-	u32        reserved2:6;
-	u32        rpl:2;	/* rotational position locking */
-#else
-	u32        rpl:2;	/* rotational position locking */
-	u32        reserved2:6;
-#endif
-	u32        rot_off:8;
-	u32        reserved3:8;
-
-	u32        med_rot_rate:16;
-	u32        reserved4:16;
-};
-
-/*
- * SCSI caching mode page
- */
-struct scsi_mp_caching_s{
-#ifdef __BIGENDIAN
-	u8         ps:1;
-	u8         res1:1;
-	u8         page_code:6;
-#else
-	u8         page_code:6;
-	u8         res1:1;
-	u8         ps:1;
-#endif
-	u8         page_len;
-#ifdef __BIGENDIAN
-	u8         ic:1;	/* initiator control */
-	u8         abpf:1;	/* abort pre-fetch */
-	u8         cap:1;	/* caching analysis permitted */
-	u8         disc:1;	/* discontinuity */
-	u8         size:1;	/* size enable */
-	u8         wce:1;	/* write cache enable */
-	u8         mf:1;	/* multiplication factor */
-	u8         rcd:1;	/* read cache disable */
-
-	u8         drrp:4;	/* demand read retention priority */
-	u8         wrp:4;	/* write retention priority */
-#else
-	u8         rcd:1;	/* read cache disable */
-	u8         mf:1;	/* multiplication factor */
-	u8         wce:1;	/* write cache enable */
-	u8         size:1;	/* size enable */
-	u8         disc:1;	/* discontinuity */
-	u8         cap:1;	/* caching analysis permitted */
-	u8         abpf:1;	/* abort pre-fetch */
-	u8         ic:1;	/* initiator control */
-
-	u8         wrp:4;	/* write retention priority */
-	u8         drrp:4;	/* demand read retention priority */
-#endif
-	u8         dptl[2];/* disable pre-fetch transfer length */
-	u8         min_prefetch[2];
-	u8         max_prefetch[2];
-	u8         max_prefetch_limit[2];
-#ifdef __BIGENDIAN
-	u8         fsw:1;	/* force sequential write */
-	u8         lbcss:1;/* logical block cache segment size */
-	u8         dra:1;	/* disable read ahead */
-	u8         vs:2;	/* vendor specific */
-	u8         res2:3;
-#else
-	u8         res2:3;
-	u8         vs:2;	/* vendor specific */
-	u8         dra:1;	/* disable read ahead */
-	u8         lbcss:1;/* logical block cache segment size */
-	u8         fsw:1;	/* force sequential write */
-#endif
-	u8         num_cache_segs;
-
-	u8         cache_seg_size[2];
-	u8         res3;
-	u8         non_cache_seg_size[3];
-};
-
-/*
- * SCSI control mode page
- */
-struct scsi_mp_control_page_s{
-#ifdef __BIGENDIAN
-u8         ps:1;
-u8         reserved1:1;
-u8         page_code:6;
-#else
-u8         page_code:6;
-u8         reserved1:1;
-u8         ps:1;
-#endif
-	u8         page_len;
-#ifdef __BIGENDIAN
-	u8         tst:3;		/* task set type */
-	u8         reserved3:3;
-	u8         gltsd:1;	/* global logging target save disable */
-	u8         rlec:1;		/* report log exception condition */
-
-	u8         qalgo_mod:4;	/* queue alogorithm modifier */
-	u8         reserved4:1;
-	u8         qerr:2;		/* queue error management */
-	u8         dque:1;		/* disable queuing */
-
-	u8         reserved5:1;
-	u8         rac:1;		/* report a check */
-	u8         reserved6:2;
-	u8         swp:1;		/* software write protect */
-	u8         raerp:1;	/* ready AER permission */
-	u8         uaaerp:1;	/* unit attenstion AER permission */
-	u8         eaerp:1;	/* error AER permission */
-
-	u8         reserved7:5;
-	u8         autoload_mod:3;
-#else
-	u8         rlec:1;		/* report log exception condition */
-	u8         gltsd:1;	/* global logging target save disable */
-	u8         reserved3:3;
-	u8         tst:3;		/* task set type */
-
-	u8         dque:1;		/* disable queuing */
-	u8         qerr:2;		/* queue error management */
-	u8         reserved4:1;
-	u8         qalgo_mod:4;	/* queue alogorithm modifier */
-
-	u8         eaerp:1;	/* error AER permission */
-	u8         uaaerp:1;	/* unit attenstion AER permission */
-	u8         raerp:1;	/* ready AER permission */
-	u8         swp:1;		/* software write protect */
-	u8         reserved6:2;
-	u8         rac:1;		/* report a check */
-	u8         reserved5:1;
-
-	u8         autoload_mod:3;
-	u8         reserved7:5;
-#endif
-	u8         rahp_msb;	/* ready AER holdoff period - MSB */
-	u8         rahp_lsb;	/* ready AER holdoff period - LSB */
-
-	u8         busy_timeout_period_msb;
-	u8         busy_timeout_period_lsb;
-
-	u8         ext_selftest_compl_time_msb;
-	u8         ext_selftest_compl_time_lsb;
-};
-
-/*
- * SCSI medium types supported mode page
- */
-struct scsi_mp_medium_types_sup_s{
-#ifdef __BIGENDIAN
-	u8         ps:1;
-	u8         reserved1:1;
-	u8         page_code:6;
-#else
-	u8         page_code:6;
-	u8         reserved1:1;
-	u8         ps:1;
-#endif
-	u8         page_len;
-
-	u8         reserved3[2];
-	u8         med_type1_sup;	/* medium type one supported */
-	u8         med_type2_sup;	/* medium type two supported */
-	u8         med_type3_sup;	/* medium type three supported */
-	u8         med_type4_sup;	/* medium type four supported */
-};
-
-/*
- * SCSI informational exception control mode page
- */
-struct scsi_mp_info_excpt_cntl_s{
-#ifdef __BIGENDIAN
-	u8         ps:1;
-	u8         reserved1:1;
-	u8         page_code:6;
-#else
-	u8         page_code:6;
-	u8         reserved1:1;
-	u8         ps:1;
-#endif
-	u8         page_len;
-#ifdef __BIGENDIAN
-	u8         perf:1;		/* performance */
-	u8         reserved3:1;
-	u8         ebf:1;		/* enable background fucntion */
-	u8         ewasc:1;	/* enable warning */
-	u8         dexcpt:1;	/* disable exception control */
-	u8         test:1;		/* enable test device failure
-					 * notification
-					 */
-	u8         reserved4:1;
-	u8         log_error:1;
-
-	u8         reserved5:4;
-	u8         mrie:4;		/* method of reporting info
-					 * exceptions
-					 */
-#else
-	u8         log_error:1;
-	u8         reserved4:1;
-	u8         test:1;		/* enable test device failure
-					 * notification
-					 */
-	u8         dexcpt:1;	/* disable exception control */
-	u8         ewasc:1;	/* enable warning */
-	u8         ebf:1;		/* enable background fucntion */
-	u8         reserved3:1;
-	u8         perf:1;		/* performance */
-
-	u8         mrie:4;		/* method of reporting info
-					 * exceptions
-					 */
-	u8         reserved5:4;
-#endif
-	u8         interval_timer_msb;
-	u8         interval_timer_lsb;
-
-	u8         report_count_msb;
-	u8         report_count_lsb;
-};
-
-/*
- * Methods of reporting informational exceptions
- */
-#define SCSI_MP_IEC_NO_REPORT       0x0	/* no reporting of exceptions */
-#define SCSI_MP_IEC_AER             0x1	/* async event reporting */
-#define SCSI_MP_IEC_UNIT_ATTN       0x2	/* generate unit attenstion */
-#define SCSI_MO_IEC_COND_REC_ERR    0x3	/* conditionally generate recovered
-					 * error
-					 */
-#define SCSI_MP_IEC_UNCOND_REC_ERR  0x4	/* unconditionally generate recovered
-					 * error
-					 */
-#define SCSI_MP_IEC_NO_SENSE        0x5	/* generate no sense */
-#define SCSI_MP_IEC_ON_REQUEST      0x6	/* only report exceptions on request */
-
-/*
- * SCSI flexible disk page
- */
-struct scsi_mp_flexible_disk_s{
-#ifdef __BIGENDIAN
-	u8         ps:1;
-	u8         reserved1:1;
-	u8         page_code:6;
-#else
-	u8         page_code:6;
-	u8         reserved1:1;
-	u8         ps:1;
-#endif
-	u8         page_len;
-
-	u8         transfer_rate_msb;
-	u8         transfer_rate_lsb;
-
-	u8         num_heads;
-	u8         num_sectors;
-
-	u8         bytes_per_sector_msb;
-	u8         bytes_per_sector_lsb;
-
-	u8         num_cylinders_msb;
-	u8         num_cylinders_lsb;
-
-	u8         sc_wpc_msb;	/* starting cylinder-write
-					 * precompensation msb
-					 */
-	u8         sc_wpc_lsb;	/* starting cylinder-write
-					 * precompensation lsb
-					 */
-	u8         sc_rwc_msb;	/* starting cylinder-reduced write
-					 * current msb
-					 */
-	u8         sc_rwc_lsb;	/* starting cylinder-reduced write
-					 * current lsb
-					 */
-
-	u8         dev_step_rate_msb;
-	u8         dev_step_rate_lsb;
-
-	u8         dev_step_pulse_width;
-
-	u8         head_sd_msb;	/* head settle delay msb */
-	u8         head_sd_lsb;	/* head settle delay lsb */
-
-	u8         motor_on_delay;
-	u8         motor_off_delay;
-#ifdef __BIGENDIAN
-	u8         trdy:1;		/* true ready bit */
-	u8         ssn:1;		/* start sector number bit */
-	u8         mo:1;		/* motor on bit */
-	u8         reserved3:5;
-
-	u8         reserved4:4;
-	u8         spc:4;		/* step pulse per cylinder */
-#else
-	u8         reserved3:5;
-	u8         mo:1;		/* motor on bit */
-	u8         ssn:1;		/* start sector number bit */
-	u8         trdy:1;		/* true ready bit */
-
-	u8         spc:4;		/* step pulse per cylinder */
-	u8         reserved4:4;
-#endif
-	u8         write_comp;
-	u8         head_load_delay;
-	u8         head_unload_delay;
-#ifdef __BIGENDIAN
-	u8         pin34:4;	/* pin34 usage */
-	u8         pin2:4;		/* pin2 usage */
-
-	u8         pin4:4;		/* pin4 usage */
-	u8         pin1:4;		/* pin1 usage */
-#else
-	u8         pin2:4;		/* pin2 usage */
-	u8         pin34:4;	/* pin34 usage */
-
-	u8         pin1:4;		/* pin1 usage */
-	u8         pin4:4;		/* pin4 usage */
-#endif
-	u8         med_rot_rate_msb;
-	u8         med_rot_rate_lsb;
-
-	u8         reserved5[2];
-};
-
-struct scsi_mode_page_format_data6_s{
-	struct scsi_mode_param_header6_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_format_device_s format;	/* format device data */
-};
-
-struct scsi_mode_page_format_data10_s{
-	struct scsi_mode_param_header10_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_format_device_s format;	/* format device data */
-};
-
-struct scsi_mode_page_rdg_data6_s{
-	struct scsi_mode_param_header6_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_rigid_device_geometry_s rdg;
-					/* rigid geometry data */
-};
-
-struct scsi_mode_page_rdg_data10_s{
-	struct scsi_mode_param_header10_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_rigid_device_geometry_s rdg;
-					/* rigid geometry data */
-};
-
-struct scsi_mode_page_cache6_s{
-	struct scsi_mode_param_header6_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_caching_s cache;	/* cache page data */
-};
-
-struct scsi_mode_page_cache10_s{
-	struct scsi_mode_param_header10_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_caching_s cache;	/* cache page data */
-};
-
-/* --------------------------------------------------------------
- * Format Unit command
- * ------------------------------------------------------------
- */
-
-/*
- * Format Unit CDB
- */
-struct scsi_format_unit_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         res1:3;
-	u8         fmtdata:1;	/* if set, data out phase has format
-					 * data
-					 */
-	u8         cmplst:1;	/* if set, defect list is complete */
-	u8         def_list:3;	/* format of defect descriptor is
-					 * fmtdata =1
-					 */
-#else
-	u8         def_list:3;	/* format of defect descriptor is
-					 * fmtdata = 1
-					 */
-	u8         cmplst:1;	/* if set, defect list is complete */
-	u8         fmtdata:1;	/* if set, data out phase has format
-					 * data
-					 */
-	u8         res1:3;
-#endif
-	u8         interleave_msb;
-	u8         interleave_lsb;
-	u8         vendor_spec;
-	u8         control;
-};
-
-/*
- * h
- */
-struct scsi_reserve6_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved:3;
-	u8         obsolete:4;
-	u8         extent:1;
-#else
-	u8         extent:1;
-	u8         obsolete:4;
-	u8         reserved:3;
-#endif
-	u8         reservation_id;
-	u16        param_list_len;
-	u8         control;
-};
-
-/*
- * h
- */
-struct scsi_release6_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         obsolete:4;
-	u8         extent:1;
-#else
-	u8         extent:1;
-	u8         obsolete:4;
-	u8         reserved1:3;
-#endif
-	u8         reservation_id;
-	u16        reserved2;
-	u8         control;
-};
-
-/*
- * h
- */
-struct scsi_reserve10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         third_party:1;
-	u8         reserved2:2;
-	u8         long_id:1;
-	u8         extent:1;
-#else
-	u8         extent:1;
-	u8         long_id:1;
-	u8         reserved2:2;
-	u8         third_party:1;
-	u8         reserved1:3;
-#endif
-	u8         reservation_id;
-	u8         third_pty_dev_id;
-	u8         reserved3;
-	u8         reserved4;
-	u8         reserved5;
-	u16        param_list_len;
-	u8         control;
-};
-
-struct scsi_release10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         third_party:1;
-	u8         reserved2:2;
-	u8         long_id:1;
-	u8         extent:1;
-#else
-	u8         extent:1;
-	u8         long_id:1;
-	u8         reserved2:2;
-	u8         third_party:1;
-	u8         reserved1:3;
-#endif
-	u8         reservation_id;
-	u8         third_pty_dev_id;
-	u8         reserved3;
-	u8         reserved4;
-	u8         reserved5;
-	u16        param_list_len;
-	u8         control;
-};
-
-struct scsi_verify10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         dpo:1;
-	u8         reserved:2;
-	u8         bytchk:1;
-	u8         reladdr:1;
-#else
-	u8         reladdr:1;
-	u8         bytchk:1;
-	u8         reserved:2;
-	u8         dpo:1;
-	u8         lun:3;
-#endif
-	u8         lba0;
-	u8         lba1;
-	u8         lba2;
-	u8         lba3;
-	u8         reserved1;
-	u8         verification_len0;
-	u8         verification_len1;
-	u8         control_byte;
-};
-
-struct scsi_request_sense_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         reserved:5;
-#else
-	u8         reserved:5;
-	u8         lun:3;
-#endif
-	u8         reserved0;
-	u8         reserved1;
-	u8         alloc_len;
-	u8         control_byte;
-};
-
-/* ------------------------------------------------------------
- * SCSI status byte values
- * ------------------------------------------------------------
- */
-#define SCSI_STATUS_GOOD                   0x00
-#define SCSI_STATUS_CHECK_CONDITION        0x02
-#define SCSI_STATUS_CONDITION_MET          0x04
-#define SCSI_STATUS_BUSY                   0x08
-#define SCSI_STATUS_INTERMEDIATE           0x10
-#define SCSI_STATUS_ICM                    0x14	/* intermediate condition met */
-#define SCSI_STATUS_RESERVATION_CONFLICT   0x18
-#define SCSI_STATUS_COMMAND_TERMINATED     0x22
-#define SCSI_STATUS_QUEUE_FULL             0x28
-#define SCSI_STATUS_ACA_ACTIVE             0x30
-
-#define SCSI_MAX_ALLOC_LEN		0xFF	/* maximum allocarion length
-						 * in CDBs
-						 */
-
-#define SCSI_OP_WRITE_VERIFY10      0x2E
-#define SCSI_OP_WRITE_VERIFY12      0xAE
-#define SCSI_OP_UNDEF               0xFF
-
-/*
- * SCSI WRITE-VERIFY(10) command
- */
-struct scsi_write_verify10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         dpo:1;		/* Disable Page Out */
-	u8         reserved2:1;
-	u8         ebp:1;		/* erse by-pass */
-	u8         bytchk:1;	/* byte check */
-	u8         rel_adr:1;	/* relative address */
-#else
-	u8         rel_adr:1;	/* relative address */
-	u8         bytchk:1;	/* byte check */
-	u8         ebp:1;		/* erse by-pass */
-	u8         reserved2:1;
-	u8         dpo:1;		/* Disable Page Out */
-	u8         reserved1:3;
-#endif
-	u8         lba0;		/* logical block address - MSB */
-	u8         lba1;
-	u8         lba2;
-	u8         lba3;		/* LSB */
-	u8         reserved3;
-	u8         xfer_length0;	/* transfer length in blocks - MSB */
-	u8         xfer_length1;	/* LSB */
-	u8         control;
-};
-
-#pragma pack()
-
-#endif /* __SCSI_H__ */
diff --git a/drivers/scsi/bfa/include/protocol/types.h b/drivers/scsi/bfa/include/protocol/types.h
deleted file mode 100644
index 2875a6c..0000000
--- a/drivers/scsi/bfa/include/protocol/types.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  types.h Protocol defined base types
- */
-
-#ifndef __TYPES_H__
-#define __TYPES_H__
-
-#include <bfa_os_inc.h>
-
-#define wwn_t u64
-#define lun_t u64
-
-#define WWN_NULL	(0)
-#define FC_SYMNAME_MAX	256	/*  max name server symbolic name size */
-#define FC_ALPA_MAX	128
-
-#pragma pack(1)
-
-#define MAC_ADDRLEN	(6)
-struct mac_s { u8 mac[MAC_ADDRLEN]; };
-#define mac_t struct mac_s
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/loop.c b/drivers/scsi/bfa/loop.c
deleted file mode 100644
index f6342ef..0000000
--- a/drivers/scsi/bfa/loop.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  port_loop.c vport private loop implementation.
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, LOOP);
-
-/**
- *   ALPA to LIXA bitmap mapping
- *
- *   ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31
- * is for L_bit (login required) and is filled as ALPA 0x00 here.
- */
-static const u8   port_loop_alpa_map[] = {
-	0xEF, 0xE8, 0xE4, 0xE2, 0xE1, 0xE0, 0xDC, 0xDA,	/* Word 3 Bits 0..7 */
-	0xD9, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xCE,	/* Word 3 Bits 8..15 */
-	0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC7, 0xC6, 0xC5,	/* Word 3 Bits 16..23 */
-	0xC3, 0xBC, 0xBA, 0xB9, 0xB6, 0xB5, 0xB4, 0xB3,	/* Word 3 Bits 24..31 */
-
-	0xB2, 0xB1, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9,	/* Word 2 Bits 0..7 */
-	0xA7, 0xA6, 0xA5, 0xA3, 0x9F, 0x9E, 0x9D, 0x9B,	/* Word 2 Bits 8..15 */
-	0x98, 0x97, 0x90, 0x8F, 0x88, 0x84, 0x82, 0x81,	/* Word 2 Bits 16..23 */
-	0x80, 0x7C, 0x7A, 0x79, 0x76, 0x75, 0x74, 0x73,	/* Word 2 Bits 24..31 */
-
-	0x72, 0x71, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69,	/* Word 1 Bits 0..7 */
-	0x67, 0x66, 0x65, 0x63, 0x5C, 0x5A, 0x59, 0x56,	/* Word 1 Bits 8..15 */
-	0x55, 0x54, 0x53, 0x52, 0x51, 0x4E, 0x4D, 0x4C,	/* Word 1 Bits 16..23 */
-	0x4B, 0x4A, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3C,	/* Word 1 Bits 24..31 */
-
-	0x3A, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,	/* Word 0 Bits 0..7 */
-	0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x27, 0x26,	/* Word 0 Bits 8..15 */
-	0x25, 0x23, 0x1F, 0x1E, 0x1D, 0x1B, 0x18, 0x17,	/* Word 0 Bits 16..23 */
-	0x10, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00,	/* Word 0 Bits 24..31 */
-};
-
-/*
- * Local Functions
- */
-static bfa_status_t bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port,
-					u8 alpa);
-
-static void bfa_fcs_port_loop_plogi_response(void *fcsarg,
-					struct bfa_fcxp_s *fcxp,
-					void *cbarg,
-					bfa_status_t req_status,
-					u32 rsp_len,
-					u32 resid_len,
-					struct fchs_s *rsp_fchs);
-/**
- *   Called by port to initializar in provate LOOP topology.
- */
-void
-bfa_fcs_port_loop_init(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
- *   Called by port to notify transition to online state.
- */
-void
-bfa_fcs_port_loop_online(struct bfa_fcs_port_s *port)
-{
-
-	u8         num_alpa = port->port_topo.ploop.num_alpa;
-	u8        *alpa_pos_map = port->port_topo.ploop.alpa_pos_map;
-	struct bfa_fcs_rport_s *r_port;
-	int             ii = 0;
-
-	/*
-	 * If the port role is Initiator Mode, create Rports.
-	 */
-	if (port->port_cfg.roles == BFA_PORT_ROLE_FCP_IM) {
-		/*
-		 * Check if the ALPA positional bitmap is available.
-		 * if not, we send PLOGI to all possible ALPAs.
-		 */
-		if (num_alpa > 0) {
-			for (ii = 0; ii < num_alpa; ii++) {
-				/*
-				 * ignore ALPA of bfa port
-				 */
-				if (alpa_pos_map[ii] != port->pid) {
-					r_port = bfa_fcs_rport_create(port,
-						alpa_pos_map[ii]);
-				}
-			}
-		} else {
-			for (ii = 0; ii < MAX_ALPA_COUNT; ii++) {
-				/*
-				 * ignore ALPA of bfa port
-				 */
-				if ((port_loop_alpa_map[ii] > 0)
-				    && (port_loop_alpa_map[ii] != port->pid))
-					bfa_fcs_port_loop_send_plogi(port,
-						port_loop_alpa_map[ii]);
-				/**TBD */
-			}
-		}
-	} else {
-		/*
-		 * TBD Target Mode ??
-		 */
-	}
-
-}
-
-/**
- *   Called by port to notify transition to offline state.
- */
-void
-bfa_fcs_port_loop_offline(struct bfa_fcs_port_s *port)
-{
-
-}
-
-/**
- *   Called by port to notify a LIP on the loop.
- */
-void
-bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
- * Local Functions.
- */
-static bfa_status_t
-bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port, u8 alpa)
-{
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp = NULL;
-	int             len;
-
-	bfa_trc(port->fcs, alpa);
-
-	fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
-				  NULL);
-	bfa_assert(fcxp);
-
-	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.pwwn, port->port_cfg.nwwn,
-				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-			  FC_CLASS_3, len, &fchs,
-			  bfa_fcs_port_loop_plogi_response, (void *)port,
-			  FC_MAX_PDUSZ, FC_RA_TOV);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *   Called by fcxp to notify the Plogi response
- */
-static void
-bfa_fcs_port_loop_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				 void *cbarg, bfa_status_t req_status,
-				 u32 rsp_len, u32 resid_len,
-				 struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
-	struct fc_logi_s     *plogi_resp;
-	struct fc_els_cmd_s   *els_cmd;
-
-	bfa_trc(port->fcs, req_status);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		/*
-		 * @todo
-		 * This could mean that the device with this APLA does not
-		 * exist on the loop.
-		 */
-
-		return;
-	}
-
-	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-	plogi_resp = (struct fc_logi_s *) els_cmd;
-
-	if (els_cmd->els_code == FC_ELS_ACC) {
-		bfa_fcs_rport_start(port, rsp_fchs, plogi_resp);
-	} else {
-		bfa_trc(port->fcs, plogi_resp->els_cmd.els_code);
-		bfa_assert(0);
-	}
-}
diff --git a/drivers/scsi/bfa/lport_api.c b/drivers/scsi/bfa/lport_api.c
deleted file mode 100644
index 72b3f50..0000000
--- a/drivers/scsi/bfa/lport_api.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  port_api.c BFA FCS port
- */
-
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include "fcs_rport.h"
-#include "fcs_fabric.h"
-#include "fcs_trcmod.h"
-#include "fcs_vport.h"
-
-BFA_TRC_FILE(FCS, PORT_API);
-
-
-
-/**
- *  fcs_port_api BFA FCS port API
- */
-
-void
-bfa_fcs_cfg_base_port(struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg)
-{
-}
-
-struct bfa_fcs_port_s *
-bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
-{
-	return &fcs->fabric.bport;
-}
-
-wwn_t
-bfa_fcs_port_get_rport(struct bfa_fcs_port_s *port, wwn_t wwn, int index,
-		       int nrports, bfa_boolean_t bwwn)
-{
-	struct list_head *qh, *qe;
-	struct bfa_fcs_rport_s *rport = NULL;
-	int             i;
-	struct bfa_fcs_s *fcs;
-
-	if (port == NULL || nrports == 0)
-		return (wwn_t) 0;
-
-	fcs = port->fcs;
-	bfa_trc(fcs, (u32) nrports);
-
-	i = 0;
-	qh = &port->rport_q;
-	qe = bfa_q_first(qh);
-
-	while ((qe != qh) && (i < nrports)) {
-		rport = (struct bfa_fcs_rport_s *)qe;
-		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
-			qe = bfa_q_next(qe);
-			bfa_trc(fcs, (u32) rport->pwwn);
-			bfa_trc(fcs, rport->pid);
-			bfa_trc(fcs, i);
-			continue;
-		}
-
-		if (bwwn) {
-			if (!memcmp(&wwn, &rport->pwwn, 8))
-				break;
-		} else {
-			if (i == index)
-				break;
-		}
-
-		i++;
-		qe = bfa_q_next(qe);
-	}
-
-	bfa_trc(fcs, i);
-	if (rport)
-		return rport->pwwn;
-	else
-		return (wwn_t) 0;
-}
-
-void
-bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port, wwn_t rport_wwns[],
-			int *nrports)
-{
-	struct list_head *qh, *qe;
-	struct bfa_fcs_rport_s *rport = NULL;
-	int             i;
-	struct bfa_fcs_s *fcs;
-
-	if (port == NULL || rport_wwns == NULL || *nrports == 0)
-		return;
-
-	fcs = port->fcs;
-	bfa_trc(fcs, (u32) *nrports);
-
-	i = 0;
-	qh = &port->rport_q;
-	qe = bfa_q_first(qh);
-
-	while ((qe != qh) && (i < *nrports)) {
-		rport = (struct bfa_fcs_rport_s *)qe;
-		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
-			qe = bfa_q_next(qe);
-			bfa_trc(fcs, (u32) rport->pwwn);
-			bfa_trc(fcs, rport->pid);
-			bfa_trc(fcs, i);
-			continue;
-		}
-
-		rport_wwns[i] = rport->pwwn;
-
-		i++;
-		qe = bfa_q_next(qe);
-	}
-
-	bfa_trc(fcs, i);
-	*nrports = i;
-	return;
-}
-
-/*
- * Iterate's through all the rport's in the given port to
- * determine the maximum operating speed.
- *
- * To be used in TRL Functionality only
- */
-enum bfa_pport_speed
-bfa_fcs_port_get_rport_max_speed(struct bfa_fcs_port_s *port)
-{
-	struct list_head *qh, *qe;
-	struct bfa_fcs_rport_s *rport = NULL;
-	struct bfa_fcs_s *fcs;
-	enum bfa_pport_speed max_speed = 0;
-	struct bfa_pport_attr_s pport_attr;
-	enum bfa_pport_speed pport_speed, rport_speed;
-	bfa_boolean_t     trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
-
-	if (port == NULL)
-		return 0;
-
-	fcs = port->fcs;
-
-	/*
-	 * Get Physical port's current speed
-	 */
-	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
-	pport_speed = pport_attr.speed;
-	bfa_trc(fcs, pport_speed);
-
-	qh = &port->rport_q;
-	qe = bfa_q_first(qh);
-
-	while (qe != qh) {
-		rport = (struct bfa_fcs_rport_s *) qe;
-		if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) ||
-			(bfa_fcs_rport_get_state(rport) ==
-						BFA_RPORT_OFFLINE)) {
-			qe = bfa_q_next(qe);
-			continue;
-		}
-
-		rport_speed = rport->rpf.rpsc_speed;
-		if ((trl_enabled) &&  (rport_speed ==
-						BFA_PPORT_SPEED_UNKNOWN)) {
-			/* Use default ratelim speed setting */
-			rport_speed =
-				bfa_fcport_get_ratelim_speed(port->fcs->bfa);
-		}
-
-		if ((rport_speed  == BFA_PPORT_SPEED_8GBPS) ||
-			(rport_speed > pport_speed)) {
-			max_speed = rport_speed;
-			break;
-		} else if (rport_speed > max_speed) {
-			max_speed = rport_speed;
-		}
-
-		qe = bfa_q_next(qe);
-	}
-
-	bfa_trc(fcs, max_speed);
-	return max_speed;
-}
-
-struct bfa_fcs_port_s *
-bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
-{
-	struct bfa_fcs_vport_s *vport;
-	bfa_fcs_vf_t   *vf;
-
-	bfa_assert(fcs != NULL);
-
-	vf = bfa_fcs_vf_lookup(fcs, vf_id);
-	if (vf == NULL) {
-		bfa_trc(fcs, vf_id);
-		return NULL;
-	}
-
-	if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
-		return &vf->bport;
-
-	vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
-	if (vport)
-		return &vport->lport;
-
-	return NULL;
-}
-
-/*
- *  API corresponding to VmWare's NPIV_VPORT_GETINFO.
- */
-void
-bfa_fcs_port_get_info(struct bfa_fcs_port_s *port,
-		      struct bfa_port_info_s *port_info)
-{
-
-	bfa_trc(port->fcs, port->fabric->fabric_name);
-
-	if (port->vport == NULL) {
-		/*
-		 * This is a Physical port
-		 */
-		port_info->port_type = BFA_PORT_TYPE_PHYSICAL;
-
-		/*
-		 * @todo : need to fix the state & reason
-		 */
-		port_info->port_state = 0;
-		port_info->offline_reason = 0;
-
-		port_info->port_wwn = bfa_fcs_port_get_pwwn(port);
-		port_info->node_wwn = bfa_fcs_port_get_nwwn(port);
-
-		port_info->max_vports_supp =
-			bfa_lps_get_max_vport(port->fcs->bfa);
-		port_info->num_vports_inuse =
-			bfa_fcs_fabric_vport_count(port->fabric);
-		port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
-		port_info->num_rports_inuse = port->num_rports;
-	} else {
-		/*
-		 * This is a virtual port
-		 */
-		port_info->port_type = BFA_PORT_TYPE_VIRTUAL;
-
-		/*
-		 * @todo : need to fix the state & reason
-		 */
-		port_info->port_state = 0;
-		port_info->offline_reason = 0;
-
-		port_info->port_wwn = bfa_fcs_port_get_pwwn(port);
-		port_info->node_wwn = bfa_fcs_port_get_nwwn(port);
-	}
-}
-
-void
-bfa_fcs_port_get_stats(struct bfa_fcs_port_s *fcs_port,
-		       struct bfa_port_stats_s *port_stats)
-{
-	bfa_os_memcpy(port_stats, &fcs_port->stats,
-		      sizeof(struct bfa_port_stats_s));
-	return;
-}
-
-void
-bfa_fcs_port_clear_stats(struct bfa_fcs_port_s *fcs_port)
-{
-	bfa_os_memset(&fcs_port->stats, 0, sizeof(struct bfa_port_stats_s));
-	return;
-}
-
-void
-bfa_fcs_port_enable_ipfc_roles(struct bfa_fcs_port_s *fcs_port)
-{
-	fcs_port->port_cfg.roles |= BFA_PORT_ROLE_FCP_IPFC;
-	return;
-}
-
-void
-bfa_fcs_port_disable_ipfc_roles(struct bfa_fcs_port_s *fcs_port)
-{
-	fcs_port->port_cfg.roles &= ~BFA_PORT_ROLE_FCP_IPFC;
-	return;
-}
-
-
diff --git a/drivers/scsi/bfa/lport_priv.h b/drivers/scsi/bfa/lport_priv.h
deleted file mode 100644
index dbae370..0000000
--- a/drivers/scsi/bfa/lport_priv.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef __VP_PRIV_H__
-#define __VP_PRIV_H__
-
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_vport.h>
-
-/*
- * Functions exported by vps
- */
-void            bfa_fcs_vport_init(struct bfa_fcs_vport_s *vport);
-
-/*
- * Functions exported by vps
- */
-void            bfa_fcs_vps_online(struct bfa_fcs_port_s *port);
-void            bfa_fcs_vps_offline(struct bfa_fcs_port_s *port);
-void            bfa_fcs_vps_lip(struct bfa_fcs_port_s *port);
-
-/*
- * Functions exported by port_fab
- */
-void            bfa_fcs_port_fab_init(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_fab_online(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_fab_offline(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_fab_rx_frame(struct bfa_fcs_port_s *port,
-					  u8 *rx_frame, u32 len);
-
-/*
- * Functions exported by VP-NS.
- */
-void            bfa_fcs_port_ns_init(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_ns_offline(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_ns_online(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_ns_query(struct bfa_fcs_port_s *port);
-
-/*
- * Functions exported by VP-SCN
- */
-void            bfa_fcs_port_scn_init(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_scn_offline(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_scn_online(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_scn_process_rscn(struct bfa_fcs_port_s *port,
-					      struct fchs_s *rx_frame, u32 len);
-
-/*
- * Functions exported by VP-N2N
- */
-
-void            bfa_fcs_port_n2n_init(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_n2n_online(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_n2n_offline(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_n2n_rx_frame(struct bfa_fcs_port_s *port,
-					  u8 *rx_frame, u32 len);
-
-/*
- * Functions exported by VP-LOOP
- */
-void            bfa_fcs_port_loop_init(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_loop_online(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_loop_offline(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_loop_rx_frame(struct bfa_fcs_port_s *port,
-					   u8 *rx_frame, u32 len);
-
-#endif /* __VP_PRIV_H__ */
diff --git a/drivers/scsi/bfa/ms.c b/drivers/scsi/bfa/ms.c
deleted file mode 100644
index 1d579ef..0000000
--- a/drivers/scsi/bfa/ms.c
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, MS);
-
-#define BFA_FCS_MS_CMD_MAX_RETRIES  2
-/*
- * forward declarations
- */
-static void     bfa_fcs_port_ms_send_plogi(void *ms_cbarg,
-					   struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ms_timeout(void *arg);
-static void     bfa_fcs_port_ms_plogi_response(void *fcsarg,
-					       struct bfa_fcxp_s *fcxp,
-					       void *cbarg,
-					       bfa_status_t req_status,
-					       u32 rsp_len,
-					       u32 resid_len,
-					       struct fchs_s *rsp_fchs);
-
-static void     bfa_fcs_port_ms_send_gmal(void *ms_cbarg,
-					  struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ms_gmal_response(void *fcsarg,
-					      struct bfa_fcxp_s *fcxp,
-					      void *cbarg,
-					      bfa_status_t req_status,
-					      u32 rsp_len,
-					      u32 resid_len,
-					      struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ms_send_gfn(void *ms_cbarg,
-					 struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ms_gfn_response(void *fcsarg,
-					     struct bfa_fcxp_s *fcxp,
-					     void *cbarg,
-					     bfa_status_t req_status,
-					     u32 rsp_len,
-					     u32 resid_len,
-					     struct fchs_s *rsp_fchs);
-/**
- *  fcs_ms_sm FCS MS state machine
- */
-
-/**
- *  MS State Machine events
- */
-enum port_ms_event {
-	MSSM_EVENT_PORT_ONLINE = 1,
-	MSSM_EVENT_PORT_OFFLINE = 2,
-	MSSM_EVENT_RSP_OK = 3,
-	MSSM_EVENT_RSP_ERROR = 4,
-	MSSM_EVENT_TIMEOUT = 5,
-	MSSM_EVENT_FCXP_SENT = 6,
-	MSSM_EVENT_PORT_FABRIC_RSCN = 7
-};
-
-static void     bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
-					   enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
-						 enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms,
-					 enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
-					       enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
-						enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms,
-					enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
-					      enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
-					       enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms,
-				       enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
-					     enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
-					  enum port_ms_event event);
-/**
- * 		Start in offline state - awaiting NS to send start.
- */
-static void
-bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
-			   enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_PORT_ONLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
-		bfa_fcs_port_ms_send_plogi(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
-				 enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
-				       &ms->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_retry);
-		ms->port->stats.ms_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer,
-				bfa_fcs_port_ms_timeout, ms,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case MSSM_EVENT_RSP_OK:
-		/*
-		 * since plogi is done, now invoke MS related sub-modules
-		 */
-		bfa_fcs_port_fdmi_online(ms);
-
-		/**
-		 * if this is a Vport, go to online state.
-		 */
-		if (ms->port->vport) {
-			bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
-			break;
-		}
-
-		/*
-		 * For a base port we need to get the
-		 * switch's IP address.
-		 */
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
-		bfa_fcs_port_ms_send_gmal(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_discard(ms->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
-			       enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
-		bfa_fcs_port_ms_send_plogi(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_timer_stop(&ms->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
-			  enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		break;
-
-	case MSSM_EVENT_PORT_FABRIC_RSCN:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
-		ms->retry_cnt = 0;
-		bfa_fcs_port_ms_send_gfn(ms, NULL);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
-				enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
-				       &ms->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
-			bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_retry);
-			ms->port->stats.ms_retries++;
-			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
-					&ms->timer, bfa_fcs_port_ms_timeout, ms,
-					BFA_FCS_RETRY_TIMEOUT);
-		} else {
-			bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
-			bfa_fcs_port_ms_send_gfn(ms, NULL);
-			ms->retry_cnt = 0;
-		}
-		break;
-
-	case MSSM_EVENT_RSP_OK:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
-		bfa_fcs_port_ms_send_gfn(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_discard(ms->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
-			      enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
-		bfa_fcs_port_ms_send_gmal(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_timer_stop(&ms->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-/**
- *  ms_pvt MS local functions
- */
-
-static void
-bfa_fcs_port_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ms_s *ms = ms_cbarg;
-	struct bfa_fcs_port_s *port = ms->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-				    bfa_fcs_port_ms_send_gmal, ms);
-		return;
-	}
-	ms->fcxp = fcxp;
-
-	len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-				bfa_fcs_port_get_fcid(port),
-				bfa_lps_get_peer_nwwn(port->fabric->lps));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gmal_response,
-		      (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_port_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-			      void *cbarg, bfa_status_t req_status,
-			      u32 rsp_len, u32 resid_len,
-			      struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
-	struct bfa_fcs_port_s *port = ms->port;
-	struct ct_hdr_s       *cthdr = NULL;
-	struct fcgs_gmal_resp_s *gmal_resp;
-	struct fc_gmal_entry_s *gmal_entry;
-	u32        num_entries;
-	u8        *rsp_str;
-
-	bfa_trc(port->fcs, req_status);
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
-		num_entries = bfa_os_ntohl(gmal_resp->ms_len);
-		if (num_entries == 0) {
-			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-			return;
-		}
-		/*
-		 * The response could contain multiple Entries.
-		 * Entries for SNMP interface, etc.
-		 * We look for the entry with a telnet prefix.
-		 * First "http://" entry refers to IP addr
-		 */
-
-		gmal_entry = (struct fc_gmal_entry_s *)gmal_resp->ms_ma;
-		while (num_entries > 0) {
-			if (strncmp
-			    (gmal_entry->prefix, CT_GMAL_RESP_PREFIX_HTTP,
-			     sizeof(gmal_entry->prefix)) == 0) {
-
-				/*
-				 * if the IP address is terminating with a '/',
-				 * remove it. *Byte 0 consists of the length
-				 * of the string.
-				 */
-				rsp_str = &(gmal_entry->prefix[0]);
-				if (rsp_str[gmal_entry->len - 1] == '/')
-					rsp_str[gmal_entry->len - 1] = 0;
-				/*
-				 * copy IP Address to fabric
-				 */
-				strncpy(bfa_fcs_port_get_fabric_ipaddr(port),
-					gmal_entry->ip_addr,
-					BFA_FCS_FABRIC_IPADDR_SZ);
-				break;
-			} else {
-				--num_entries;
-				++gmal_entry;
-			}
-		}
-
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
-		return;
-	}
-
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-}
-
-static void
-bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
-			       enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
-				       &ms->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
-			bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_retry);
-			ms->port->stats.ms_retries++;
-			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
-					&ms->timer, bfa_fcs_port_ms_timeout, ms,
-					BFA_FCS_RETRY_TIMEOUT);
-		} else {
-			bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
-			ms->retry_cnt = 0;
-		}
-		break;
-
-	case MSSM_EVENT_RSP_OK:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_discard(ms->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
-			     enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
-		bfa_fcs_port_ms_send_gfn(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_timer_stop(&ms->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-/**
- *  ms_pvt MS local functions
- */
-
-static void
-bfa_fcs_port_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ms_s *ms = ms_cbarg;
-	struct bfa_fcs_port_s *port = ms->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-				    bfa_fcs_port_ms_send_gfn, ms);
-		return;
-	}
-	ms->fcxp = fcxp;
-
-	len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			       bfa_fcs_port_get_fcid(port),
-			       bfa_lps_get_peer_nwwn(port->fabric->lps));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gfn_response,
-		      (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_port_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			     bfa_status_t req_status, u32 rsp_len,
-			       u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
-	struct bfa_fcs_port_s *port = ms->port;
-	struct ct_hdr_s       *cthdr = NULL;
-	wwn_t          *gfn_resp;
-
-	bfa_trc(port->fcs, req_status);
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		gfn_resp = (wwn_t *) (cthdr + 1);
-		/*
-		 * check if it has actually changed
-		 */
-		if ((memcmp
-		     ((void *)&bfa_fcs_port_get_fabric_name(port), gfn_resp,
-		      sizeof(wwn_t)) != 0))
-			bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
-		return;
-	}
-
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-}
-
-/**
- *  ms_pvt MS local functions
- */
-
-static void
-bfa_fcs_port_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ms_s *ms = ms_cbarg;
-	struct bfa_fcs_port_s *port = ms->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ms_plogi_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-				    bfa_fcs_port_ms_send_plogi, ms);
-		return;
-	}
-	ms->fcxp = fcxp;
-
-	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_os_hton3b(FC_MGMT_SERVER),
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.pwwn, port->port_cfg.nwwn,
-			     bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_plogi_response,
-		      (void *)ms, FC_MAX_PDUSZ, FC_ELS_TOV);
-
-	port->stats.ms_plogi_sent++;
-	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_port_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-			       void *cbarg, bfa_status_t req_status,
-			       u32 rsp_len, u32 resid_len,
-			       struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
-
-	struct bfa_fcs_port_s *port = ms->port;
-	struct fc_els_cmd_s   *els_cmd;
-	struct fc_ls_rjt_s    *ls_rjt;
-
-	bfa_trc(port->fcs, req_status);
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		port->stats.ms_plogi_rsp_err++;
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-	switch (els_cmd->els_code) {
-
-	case FC_ELS_ACC:
-		if (rsp_len < sizeof(struct fc_logi_s)) {
-			bfa_trc(port->fcs, rsp_len);
-			port->stats.ms_plogi_acc_err++;
-			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-			break;
-		}
-		port->stats.ms_plogi_accepts++;
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
-		break;
-
-	case FC_ELS_LS_RJT:
-		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-		bfa_trc(port->fcs, ls_rjt->reason_code);
-		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
-
-		port->stats.ms_rejects++;
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-		break;
-
-	default:
-		port->stats.ms_plogi_unknown_rsp++;
-		bfa_trc(port->fcs, els_cmd->els_code);
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-	}
-}
-
-static void
-bfa_fcs_port_ms_timeout(void *arg)
-{
-	struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)arg;
-
-	ms->port->stats.ms_timeouts++;
-	bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
-}
-
-
-void
-bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
-	ms->port = port;
-	bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-
-	/*
-	 * Invoke init routines of sub modules.
-	 */
-	bfa_fcs_port_fdmi_init(ms);
-}
-
-void
-bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
-	ms->port = port;
-	bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
-	bfa_fcs_port_fdmi_offline(ms);
-}
-
-void
-bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
-	ms->port = port;
-	bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
-}
-
-void
-bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
-	/*
-	 * @todo.  Handle this only when in Online state
-	 */
-	if (bfa_sm_cmp_state(ms, bfa_fcs_port_ms_sm_online))
-		bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
-}
diff --git a/drivers/scsi/bfa/n2n.c b/drivers/scsi/bfa/n2n.c
deleted file mode 100644
index 7354568..0000000
--- a/drivers/scsi/bfa/n2n.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  n2n.c n2n implementation.
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, N2N);
-
-/**
- *   Called by fcs/port to initialize N2N topology.
- */
-void
-bfa_fcs_port_n2n_init(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
- *   Called by fcs/port to notify transition to online state.
- */
-void
-bfa_fcs_port_n2n_online(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_n2n_s *n2n_port = &port->port_topo.pn2n;
-	struct bfa_port_cfg_s *pcfg = &port->port_cfg;
-	struct bfa_fcs_rport_s *rport;
-
-	bfa_trc(port->fcs, pcfg->pwwn);
-
-	/*
-	 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
-	 * and assign an Address. if not, we need to wait for its PLOGI.
-	 *
-	 * If our PWWN is < than that of the remote port, it will send a PLOGI
-	 * with the PIDs assigned. The rport state machine take care of this
-	 * incoming PLOGI.
-	 */
-	if (memcmp
-	    ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
-	     sizeof(wwn_t)) > 0) {
-		port->pid = N2N_LOCAL_PID;
-		/**
-		 * First, check if we know the device by pwwn.
-		 */
-		rport = bfa_fcs_port_get_rport_by_pwwn(port,
-						       n2n_port->rem_port_wwn);
-		if (rport) {
-			bfa_trc(port->fcs, rport->pid);
-			bfa_trc(port->fcs, rport->pwwn);
-			rport->pid = N2N_REMOTE_PID;
-			bfa_fcs_rport_online(rport);
-			return;
-		}
-
-		/*
-		 * In n2n there can be only one rport. Delete the old one whose
-		 * pid should be zero, because it is offline.
-		 */
-		if (port->num_rports > 0) {
-			rport = bfa_fcs_port_get_rport_by_pid(port, 0);
-			bfa_assert(rport != NULL);
-			if (rport) {
-				bfa_trc(port->fcs, rport->pwwn);
-				bfa_fcs_rport_delete(rport);
-			}
-		}
-		bfa_fcs_rport_create(port, N2N_REMOTE_PID);
-	}
-}
-
-/**
- *   Called by fcs/port to notify transition to offline state.
- */
-void
-bfa_fcs_port_n2n_offline(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_n2n_s *n2n_port = &port->port_topo.pn2n;
-
-	bfa_trc(port->fcs, port->pid);
-	port->pid = 0;
-	n2n_port->rem_port_wwn = 0;
-	n2n_port->reply_oxid = 0;
-}
-
-
diff --git a/drivers/scsi/bfa/ns.c b/drivers/scsi/bfa/ns.c
deleted file mode 100644
index ae0edcc..0000000
--- a/drivers/scsi/bfa/ns.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- * @page ns_sm_info VPORT NS State Machine
- *
- * @section ns_sm_interactions VPORT NS State Machine Interactions
- *
- * @section ns_sm VPORT NS State Machine
- * 	img ns_sm.jpg
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfa_iocfc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, NS);
-
-/*
- * forward declarations
- */
-static void     bfa_fcs_port_ns_send_plogi(void *ns_cbarg,
-					   struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ns_send_rspn_id(void *ns_cbarg,
-					     struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ns_send_rft_id(void *ns_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ns_send_rff_id(void *ns_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ns_send_gid_ft(void *ns_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ns_timeout(void *arg);
-static void     bfa_fcs_port_ns_plogi_response(void *fcsarg,
-					       struct bfa_fcxp_s *fcxp,
-					       void *cbarg,
-					       bfa_status_t req_status,
-					       u32 rsp_len,
-					       u32 resid_len,
-					       struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ns_rspn_id_response(void *fcsarg,
-						 struct bfa_fcxp_s *fcxp,
-						 void *cbarg,
-						 bfa_status_t req_status,
-						 u32 rsp_len,
-						 u32 resid_len,
-						 struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ns_rft_id_response(void *fcsarg,
-						struct bfa_fcxp_s *fcxp,
-						void *cbarg,
-						bfa_status_t req_status,
-						u32 rsp_len,
-						u32 resid_len,
-						struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ns_rff_id_response(void *fcsarg,
-						struct bfa_fcxp_s *fcxp,
-						void *cbarg,
-						bfa_status_t req_status,
-						u32 rsp_len,
-						u32 resid_len,
-						struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ns_gid_ft_response(void *fcsarg,
-						struct bfa_fcxp_s *fcxp,
-						void *cbarg,
-						bfa_status_t req_status,
-						u32 rsp_len,
-						u32 resid_len,
-						struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ns_process_gidft_pids(struct bfa_fcs_port_s *port,
-						   u32 *pid_buf,
-						   u32 n_pids);
-
-static void     bfa_fcs_port_ns_boot_target_disc(struct bfa_fcs_port_s *port);
-/**
- *  fcs_ns_sm FCS nameserver interface state machine
- */
-
-/**
- * VPort NS State Machine events
- */
-enum vport_ns_event {
-	NSSM_EVENT_PORT_ONLINE = 1,
-	NSSM_EVENT_PORT_OFFLINE = 2,
-	NSSM_EVENT_PLOGI_SENT = 3,
-	NSSM_EVENT_RSP_OK = 4,
-	NSSM_EVENT_RSP_ERROR = 5,
-	NSSM_EVENT_TIMEOUT = 6,
-	NSSM_EVENT_NS_QUERY = 7,
-	NSSM_EVENT_RSPNID_SENT = 8,
-	NSSM_EVENT_RFTID_SENT = 9,
-	NSSM_EVENT_RFFID_SENT = 10,
-	NSSM_EVENT_GIDFT_SENT = 11,
-};
-
-static void     bfa_fcs_port_ns_sm_offline(struct bfa_fcs_port_ns_s *ns,
-					   enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_plogi_sending(struct bfa_fcs_port_ns_s *ns,
-						 enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_plogi(struct bfa_fcs_port_ns_s *ns,
-					 enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_plogi_retry(struct bfa_fcs_port_ns_s *ns,
-					       enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_sending_rspn_id(struct bfa_fcs_port_ns_s *ns,
-						   enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rspn_id(struct bfa_fcs_port_ns_s *ns,
-					   enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rspn_id_retry(struct bfa_fcs_port_ns_s *ns,
-						 enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_sending_rft_id(struct bfa_fcs_port_ns_s *ns,
-						  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rft_id_retry(struct bfa_fcs_port_ns_s *ns,
-						enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rft_id(struct bfa_fcs_port_ns_s *ns,
-					  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_sending_rff_id(struct bfa_fcs_port_ns_s *ns,
-						  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rff_id_retry(struct bfa_fcs_port_ns_s *ns,
-						enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rff_id(struct bfa_fcs_port_ns_s *ns,
-					  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_sending_gid_ft(struct bfa_fcs_port_ns_s *ns,
-						  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_gid_ft(struct bfa_fcs_port_ns_s *ns,
-					  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_gid_ft_retry(struct bfa_fcs_port_ns_s *ns,
-						enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_online(struct bfa_fcs_port_ns_s *ns,
-					  enum vport_ns_event event);
-/**
- * 		Start in offline state - awaiting linkup
- */
-static void
-bfa_fcs_port_ns_sm_offline(struct bfa_fcs_port_ns_s *ns,
-			   enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_PORT_ONLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_sending);
-		bfa_fcs_port_ns_send_plogi(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_plogi_sending(struct bfa_fcs_port_ns_s *ns,
-				 enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_PLOGI_SENT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
-				       &ns->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_plogi(struct bfa_fcs_port_ns_s *ns,
-			 enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_retry);
-		ns->port->stats.ns_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
-				bfa_fcs_port_ns_timeout, ns,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case NSSM_EVENT_RSP_OK:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rspn_id);
-		bfa_fcs_port_ns_send_rspn_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_discard(ns->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_plogi_retry(struct bfa_fcs_port_ns_s *ns,
-			       enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_sending);
-		bfa_fcs_port_ns_send_plogi(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_timer_stop(&ns->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_sending_rspn_id(struct bfa_fcs_port_ns_s *ns,
-				   enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSPNID_SENT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rspn_id);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
-				       &ns->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rspn_id(struct bfa_fcs_port_ns_s *ns,
-			   enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rspn_id_retry);
-		ns->port->stats.ns_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
-				bfa_fcs_port_ns_timeout, ns,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case NSSM_EVENT_RSP_OK:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rft_id);
-		bfa_fcs_port_ns_send_rft_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_fcxp_discard(ns->fcxp);
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rspn_id_retry(struct bfa_fcs_port_ns_s *ns,
-				 enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rspn_id);
-		bfa_fcs_port_ns_send_rspn_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_timer_stop(&ns->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_sending_rft_id(struct bfa_fcs_port_ns_s *ns,
-				  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RFTID_SENT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rft_id);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
-				       &ns->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rft_id(struct bfa_fcs_port_ns_s *ns,
-			  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSP_OK:
-		/*
-		 * Now move to register FC4 Features
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rff_id);
-		bfa_fcs_port_ns_send_rff_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rft_id_retry);
-		ns->port->stats.ns_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
-				bfa_fcs_port_ns_timeout, ns,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_discard(ns->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rft_id_retry(struct bfa_fcs_port_ns_s *ns,
-				enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rft_id);
-		bfa_fcs_port_ns_send_rft_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_timer_stop(&ns->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_sending_rff_id(struct bfa_fcs_port_ns_s *ns,
-				  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RFFID_SENT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rff_id);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
-				       &ns->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rff_id(struct bfa_fcs_port_ns_s *ns,
-			  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSP_OK:
-
-		/*
-		 * If min cfg mode is enabled, we donot initiate rport
-		 * discovery with the fabric. Instead, we will retrieve the
-		 * boot targets from HAL/FW.
-		 */
-		if (__fcs_min_cfg(ns->port->fcs)) {
-			bfa_fcs_port_ns_boot_target_disc(ns->port);
-			bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
-			return;
-		}
-
-		/*
-		 * If the port role is Initiator Mode issue NS query.
-		 * If it is Target Mode, skip this and go to online.
-		 */
-		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
-			bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
-			bfa_fcs_port_ns_send_gid_ft(ns, NULL);
-		} else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port)) {
-			bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
-		}
-		/*
-		 * kick off mgmt srvr state machine
-		 */
-		bfa_fcs_port_ms_online(ns->port);
-		break;
-
-	case NSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rff_id_retry);
-		ns->port->stats.ns_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
-				bfa_fcs_port_ns_timeout, ns,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_discard(ns->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rff_id_retry(struct bfa_fcs_port_ns_s *ns,
-				enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rff_id);
-		bfa_fcs_port_ns_send_rff_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_timer_stop(&ns->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-static void
-bfa_fcs_port_ns_sm_sending_gid_ft(struct bfa_fcs_port_ns_s *ns,
-				  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_GIDFT_SENT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_gid_ft);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
-				       &ns->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_gid_ft(struct bfa_fcs_port_ns_s *ns,
-			  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSP_OK:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
-		break;
-
-	case NSSM_EVENT_RSP_ERROR:
-		/*
-		 * TBD: for certain reject codes, we don't need to retry
-		 */
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_gid_ft_retry);
-		ns->port->stats.ns_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
-				bfa_fcs_port_ns_timeout, ns,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_discard(ns->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_gid_ft_retry(struct bfa_fcs_port_ns_s *ns,
-				enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
-		bfa_fcs_port_ns_send_gid_ft(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_timer_stop(&ns->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_online(struct bfa_fcs_port_ns_s *ns,
-			  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		break;
-
-	case NSSM_EVENT_NS_QUERY:
-		/*
-		 * If the port role is Initiator Mode issue NS query.
-		 * If it is Target Mode, skip this and go to online.
-		 */
-		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
-			bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
-			bfa_fcs_port_ns_send_gid_ft(ns, NULL);
-		};
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-
-
-/**
- *  ns_pvt Nameserver local functions
- */
-
-static void
-bfa_fcs_port_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ns_s *ns = ns_cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ns_plogi_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-				    bfa_fcs_port_ns_send_plogi, ns);
-		return;
-	}
-	ns->fcxp = fcxp;
-
-	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_os_hton3b(FC_NAME_SERVER),
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.pwwn, port->port_cfg.nwwn,
-			     bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_plogi_response,
-		      (void *)ns, FC_MAX_PDUSZ, FC_ELS_TOV);
-	port->stats.ns_plogi_sent++;
-
-	bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
-}
-
-static void
-bfa_fcs_port_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-			       void *cbarg, bfa_status_t req_status,
-			       u32 rsp_len, u32 resid_len,
-			       struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	/* struct fc_logi_s *plogi_resp; */
-	struct fc_els_cmd_s   *els_cmd;
-	struct fc_ls_rjt_s    *ls_rjt;
-
-	bfa_trc(port->fcs, req_status);
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		port->stats.ns_plogi_rsp_err++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-	switch (els_cmd->els_code) {
-
-	case FC_ELS_ACC:
-		if (rsp_len < sizeof(struct fc_logi_s)) {
-			bfa_trc(port->fcs, rsp_len);
-			port->stats.ns_plogi_acc_err++;
-			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-			break;
-		}
-		port->stats.ns_plogi_accepts++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		break;
-
-	case FC_ELS_LS_RJT:
-		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-		bfa_trc(port->fcs, ls_rjt->reason_code);
-		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
-
-		port->stats.ns_rejects++;
-
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		break;
-
-	default:
-		port->stats.ns_plogi_unknown_rsp++;
-		bfa_trc(port->fcs, els_cmd->els_code);
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-	}
-}
-
-/**
- * Register the symbolic port name.
- */
-static void
-bfa_fcs_port_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ns_s *ns = ns_cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-	u8         symbl[256];
-	u8        *psymbl = &symbl[0];
-
-	bfa_os_memset(symbl, 0, sizeof(symbl));
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ns_rspnid_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-				    bfa_fcs_port_ns_send_rspn_id, ns);
-		return;
-	}
-	ns->fcxp = fcxp;
-
-	/*
-	 * for V-Port, form a Port Symbolic Name
-	 */
-	if (port->vport) {
-		/**For Vports,
-		 *  we append the vport's port symbolic name to that of the base port.
-		 */
-
-		strncpy((char *)psymbl,
-			(char *)
-			&(bfa_fcs_port_get_psym_name
-			  (bfa_fcs_get_base_port(port->fcs))),
-			strlen((char *)
-			       &bfa_fcs_port_get_psym_name(bfa_fcs_get_base_port
-							   (port->fcs))));
-
-		/*
-		 * Ensure we have a null terminating string.
-		 */
-		((char *)
-		 psymbl)[strlen((char *)
-				&bfa_fcs_port_get_psym_name
-				(bfa_fcs_get_base_port(port->fcs)))] = 0;
-
-		strncat((char *)psymbl,
-			(char *)&(bfa_fcs_port_get_psym_name(port)),
-			strlen((char *)&bfa_fcs_port_get_psym_name(port)));
-	} else {
-		psymbl = (u8 *) &(bfa_fcs_port_get_psym_name(port));
-	}
-
-	len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			      bfa_fcs_port_get_fcid(port), 0, psymbl);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rspn_id_response,
-		      (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	port->stats.ns_rspnid_sent++;
-
-	bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
-}
-
-static void
-bfa_fcs_port_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				 void *cbarg, bfa_status_t req_status,
-				 u32 rsp_len, u32 resid_len,
-				 struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		port->stats.ns_rspnid_rsp_err++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		port->stats.ns_rspnid_accepts++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		return;
-	}
-
-	port->stats.ns_rspnid_rejects++;
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-}
-
-/**
- * Register FC4-Types
- * TBD, Need to retrieve this from the OS driver, in case IPFC is enabled ?
- */
-static void
-bfa_fcs_port_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ns_s *ns = ns_cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ns_rftid_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-				    bfa_fcs_port_ns_send_rft_id, ns);
-		return;
-	}
-	ns->fcxp = fcxp;
-
-	len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.roles);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rft_id_response,
-		      (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	port->stats.ns_rftid_sent++;
-	bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
-}
-
-static void
-bfa_fcs_port_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				void *cbarg, bfa_status_t req_status,
-				u32 rsp_len, u32 resid_len,
-				struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		port->stats.ns_rftid_rsp_err++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		port->stats.ns_rftid_accepts++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		return;
-	}
-
-	port->stats.ns_rftid_rejects++;
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-}
-
-/**
-* Register FC4-Features : Should be done after RFT_ID
- */
-static void
-bfa_fcs_port_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ns_s *ns = ns_cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-	u8         fc4_ftrs = 0;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ns_rffid_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-				    bfa_fcs_port_ns_send_rff_id, ns);
-		return;
-	}
-	ns->fcxp = fcxp;
-
-	if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
-		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
-	else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port))
-		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_TARGET;
-
-	len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_fcs_port_get_fcid(port), 0, FC_TYPE_FCP,
-			     fc4_ftrs);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rff_id_response,
-		      (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	port->stats.ns_rffid_sent++;
-	bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
-}
-
-static void
-bfa_fcs_port_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				void *cbarg, bfa_status_t req_status,
-				u32 rsp_len, u32 resid_len,
-				struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		port->stats.ns_rffid_rsp_err++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		port->stats.ns_rffid_accepts++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		return;
-	}
-
-	port->stats.ns_rffid_rejects++;
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-
-	if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
-		/*
-		 * if this command is not supported, we don't retry
-		 */
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-	} else {
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-	}
-}
-
-/**
- * Query Fabric for FC4-Types Devices.
- *
-*  TBD : Need to use a local (FCS private) response buffer, since the response
- * can be larger than 2K.
- */
-static void
-bfa_fcs_port_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ns_s *ns = ns_cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ns_gidft_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-				    bfa_fcs_port_ns_send_gid_ft, ns);
-		return;
-	}
-	ns->fcxp = fcxp;
-
-	/*
-	 * This query is only initiated for FCP initiator mode.
-	 */
-	len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), ns->port->pid,
-			      FC_TYPE_FCP);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_gid_ft_response,
-		      (void *)ns, bfa_fcxp_get_maxrsp(port->fcs->bfa),
-		      FC_FCCT_TOV);
-
-	port->stats.ns_gidft_sent++;
-
-	bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
-}
-
-static void
-bfa_fcs_port_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				void *cbarg, bfa_status_t req_status,
-				u32 rsp_len, u32 resid_len,
-				struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct ct_hdr_s       *cthdr = NULL;
-	u32        n_pids;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		port->stats.ns_gidft_rsp_err++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	if (resid_len != 0) {
-		/*
-		 * TBD : we will need to allocate a larger buffer & retry the
-		 * command
-		 */
-		bfa_trc(port->fcs, rsp_len);
-		bfa_trc(port->fcs, resid_len);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	switch (cthdr->cmd_rsp_code) {
-
-	case CT_RSP_ACCEPT:
-
-		port->stats.ns_gidft_accepts++;
-		n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
-		bfa_trc(port->fcs, n_pids);
-		bfa_fcs_port_ns_process_gidft_pids(port,
-						   (u32 *) (cthdr + 1),
-						   n_pids);
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		break;
-
-	case CT_RSP_REJECT:
-
-		/*
-		 * Check the reason code  & explanation.
-		 * There may not have been any FC4 devices in the fabric
-		 */
-		port->stats.ns_gidft_rejects++;
-		bfa_trc(port->fcs, cthdr->reason_code);
-		bfa_trc(port->fcs, cthdr->exp_code);
-
-		if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
-		    && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
-
-			bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		} else {
-			/*
-			 * for all other errors, retry
-			 */
-			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		}
-		break;
-
-	default:
-		port->stats.ns_gidft_unknown_rsp++;
-		bfa_trc(port->fcs, cthdr->cmd_rsp_code);
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-	}
-}
-
-/**
- *     This routine will be called by bfa_timer on timer timeouts.
- *
- * 	param[in] 	port 	- pointer to bfa_fcs_port_t.
- *
- * 	return
- * 		void
- *
-* 	Special Considerations:
- *
- * 	note
- */
-static void
-bfa_fcs_port_ns_timeout(void *arg)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)arg;
-
-	ns->port->stats.ns_timeouts++;
-	bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
-}
-
-/*
- * Process the PID list in GID_FT response
- */
-static void
-bfa_fcs_port_ns_process_gidft_pids(struct bfa_fcs_port_s *port,
-				   u32 *pid_buf, u32 n_pids)
-{
-	struct fcgs_gidft_resp_s *gidft_entry;
-	struct bfa_fcs_rport_s *rport;
-	u32        ii;
-
-	for (ii = 0; ii < n_pids; ii++) {
-		gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
-
-		if (gidft_entry->pid == port->pid)
-			continue;
-
-		/*
-		 * Check if this rport already exists
-		 */
-		rport = bfa_fcs_port_get_rport_by_pid(port, gidft_entry->pid);
-		if (rport == NULL) {
-			/*
-			 * this is a new device. create rport
-			 */
-			rport = bfa_fcs_rport_create(port, gidft_entry->pid);
-		} else {
-			/*
-			 * this rport already exists
-			 */
-			bfa_fcs_rport_scn(rport);
-		}
-
-		bfa_trc(port->fcs, gidft_entry->pid);
-
-		/*
-		 * if the last entry bit is set, bail out.
-		 */
-		if (gidft_entry->last)
-			return;
-	}
-}
-
-/**
- *  fcs_ns_public FCS nameserver public interfaces
- */
-
-/*
- * Functions called by port/fab.
- * These will send relevant Events to the ns state machine.
- */
-void
-bfa_fcs_port_ns_init(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
-	ns->port = port;
-	bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-}
-
-void
-bfa_fcs_port_ns_offline(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
-	ns->port = port;
-	bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
-}
-
-void
-bfa_fcs_port_ns_online(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
-	ns->port = port;
-	bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
-}
-
-void
-bfa_fcs_port_ns_query(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
-	bfa_trc(port->fcs, port->pid);
-	bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
-}
-
-static void
-bfa_fcs_port_ns_boot_target_disc(struct bfa_fcs_port_s *port)
-{
-
-	struct bfa_fcs_rport_s *rport;
-	u8         nwwns;
-	wwn_t  wwns[BFA_PREBOOT_BOOTLUN_MAX];
-	int             ii;
-
-	bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
-
-	for (ii = 0; ii < nwwns; ++ii) {
-		rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
-		bfa_assert(rport);
-	}
-}
-
-
diff --git a/drivers/scsi/bfa/plog.c b/drivers/scsi/bfa/plog.c
deleted file mode 100644
index fcb8864..0000000
--- a/drivers/scsi/bfa/plog.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_plog.h>
-#include <cs/bfa_debug.h>
-
-static int
-plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
-{
-	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT)
-	    && (pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
-		return 1;
-
-	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT)
-	    && (pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
-		return 1;
-
-	return 0;
-}
-
-static void
-bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
-{
-	u16        tail;
-	struct bfa_plog_rec_s *pl_recp;
-
-	if (plog->plog_enabled == 0)
-		return;
-
-	if (plkd_validate_logrec(pl_rec)) {
-		bfa_assert(0);
-		return;
-	}
-
-	tail = plog->tail;
-
-	pl_recp = &(plog->plog_recs[tail]);
-
-	bfa_os_memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
-
-	pl_recp->tv = BFA_TRC_TS(plog);
-	BFA_PL_LOG_REC_INCR(plog->tail);
-
-	if (plog->head == plog->tail)
-		BFA_PL_LOG_REC_INCR(plog->head);
-}
-
-void
-bfa_plog_init(struct bfa_plog_s *plog)
-{
-	bfa_os_memset((char *)plog, 0, sizeof(struct bfa_plog_s));
-
-	bfa_os_memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
-	plog->head = plog->tail = 0;
-	plog->plog_enabled = 1;
-}
-
-void
-bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-		enum bfa_plog_eid event,
-		u16 misc, char *log_str)
-{
-	struct bfa_plog_rec_s  lp;
-
-	if (plog->plog_enabled) {
-		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
-		lp.mid = mid;
-		lp.eid = event;
-		lp.log_type = BFA_PL_LOG_TYPE_STRING;
-		lp.misc = misc;
-		strncpy(lp.log_entry.string_log, log_str,
-			BFA_PL_STRING_LOG_SZ - 1);
-		lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
-		bfa_plog_add(plog, &lp);
-	}
-}
-
-void
-bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-		enum bfa_plog_eid event,
-		u16 misc, u32 *intarr, u32 num_ints)
-{
-	struct bfa_plog_rec_s  lp;
-	u32        i;
-
-	if (num_ints > BFA_PL_INT_LOG_SZ)
-		num_ints = BFA_PL_INT_LOG_SZ;
-
-	if (plog->plog_enabled) {
-		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
-		lp.mid = mid;
-		lp.eid = event;
-		lp.log_type = BFA_PL_LOG_TYPE_INT;
-		lp.misc = misc;
-
-		for (i = 0; i < num_ints; i++)
-			bfa_os_assign(lp.log_entry.int_log[i],
-					intarr[i]);
-
-		lp.log_num_ints = (u8) num_ints;
-
-		bfa_plog_add(plog, &lp);
-	}
-}
-
-void
-bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-			enum bfa_plog_eid event,
-			u16 misc, struct fchs_s *fchdr)
-{
-	struct bfa_plog_rec_s  lp;
-	u32       *tmp_int = (u32 *) fchdr;
-	u32        ints[BFA_PL_INT_LOG_SZ];
-
-	if (plog->plog_enabled) {
-		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
-
-		ints[0] = tmp_int[0];
-		ints[1] = tmp_int[1];
-		ints[2] = tmp_int[4];
-
-		bfa_plog_intarr(plog, mid, event, misc, ints, 3);
-	}
-}
-
-void
-bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-		      enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
-		      u32 pld_w0)
-{
-	struct bfa_plog_rec_s  lp;
-	u32       *tmp_int = (u32 *) fchdr;
-	u32        ints[BFA_PL_INT_LOG_SZ];
-
-	if (plog->plog_enabled) {
-		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
-
-		ints[0] = tmp_int[0];
-		ints[1] = tmp_int[1];
-		ints[2] = tmp_int[4];
-		ints[3] = pld_w0;
-
-		bfa_plog_intarr(plog, mid, event, misc, ints, 4);
-	}
-}
-
-void
-bfa_plog_clear(struct bfa_plog_s *plog)
-{
-	plog->head = plog->tail = 0;
-}
-
-void
-bfa_plog_enable(struct bfa_plog_s *plog)
-{
-	plog->plog_enabled = 1;
-}
-
-void
-bfa_plog_disable(struct bfa_plog_s *plog)
-{
-	plog->plog_enabled = 0;
-}
-
-bfa_boolean_t
-bfa_plog_get_setting(struct bfa_plog_s *plog)
-{
-	return (bfa_boolean_t)plog->plog_enabled;
-}
diff --git a/drivers/scsi/bfa/rport.c b/drivers/scsi/bfa/rport.c
deleted file mode 100644
index 9b4c2c9..0000000
--- a/drivers/scsi/bfa/rport.c
+++ /dev/null
@@ -1,2676 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  rport.c Remote port implementation.
- */
-
-#include <linux/slab.h>
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcbuild.h"
-#include "fcs_vport.h"
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_fcpim.h"
-#include "fcs_fcptm.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include <fcb/bfa_fcb_rport.h>
-#include <aen/bfa_aen_rport.h>
-
-BFA_TRC_FILE(FCS, RPORT);
-
-/* In millisecs */
-static u32 bfa_fcs_rport_del_timeout =
-			BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
-
-/*
- * forward declarations
- */
-static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port,
-						   wwn_t pwwn, u32 rpid);
-static void     bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
-				     struct fc_logi_s *plogi);
-static void     bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_timeout(void *arg);
-static void     bfa_fcs_rport_send_plogi(void *rport_cbarg,
-					 struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rport_plogi_response(void *fcsarg,
-					     struct bfa_fcxp_s *fcxp,
-					     void *cbarg,
-					     bfa_status_t req_status,
-					     u32 rsp_len,
-					     u32 resid_len,
-					     struct fchs_s *rsp_fchs);
-static void     bfa_fcs_rport_send_adisc(void *rport_cbarg,
-					 struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rport_adisc_response(void *fcsarg,
-					     struct bfa_fcxp_s *fcxp,
-					     void *cbarg,
-					     bfa_status_t req_status,
-					     u32 rsp_len,
-					     u32 resid_len,
-					     struct fchs_s *rsp_fchs);
-static void     bfa_fcs_rport_send_gidpn(void *rport_cbarg,
-					 struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rport_gidpn_response(void *fcsarg,
-					     struct bfa_fcxp_s *fcxp,
-					     void *cbarg,
-					     bfa_status_t req_status,
-					     u32 rsp_len,
-					     u32 resid_len,
-					     struct fchs_s *rsp_fchs);
-static void     bfa_fcs_rport_send_logo(void *rport_cbarg,
-					struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
-static void     bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u16 len);
-static void     bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u8 reason_code,
-			u8 reason_code_expl);
-static void     bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u16 len);
-static void	bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
-/**
- *  fcs_rport_sm FCS rport state machine events
- */
-
-enum rport_event {
-	RPSM_EVENT_PLOGI_SEND = 1,	/*  new rport; start with PLOGI */
-	RPSM_EVENT_PLOGI_RCVD = 2,	/*  Inbound PLOGI from remote port */
-	RPSM_EVENT_PLOGI_COMP = 3,	/*  PLOGI completed to rport */
-	RPSM_EVENT_LOGO_RCVD = 4,	/*  LOGO from remote device */
-	RPSM_EVENT_LOGO_IMP = 5,	/*  implicit logo for SLER */
-	RPSM_EVENT_FCXP_SENT = 6,	/*  Frame from has been sent */
-	RPSM_EVENT_DELETE = 7,	/*  RPORT delete request */
-	RPSM_EVENT_SCN = 8,	/*  state change notification */
-	RPSM_EVENT_ACCEPTED = 9,/*  Good response from remote device */
-	RPSM_EVENT_FAILED = 10,	/*  Request to rport failed.  */
-	RPSM_EVENT_TIMEOUT = 11,	/*  Rport SM timeout event */
-	RPSM_EVENT_HCB_ONLINE = 12,	/*  BFA rport online callback */
-	RPSM_EVENT_HCB_OFFLINE = 13,	/*  BFA rport offline callback */
-	RPSM_EVENT_FC4_OFFLINE = 14,	/*  FC-4 offline complete */
-	RPSM_EVENT_ADDRESS_CHANGE = 15,	/*  Rport's PID has changed */
-	RPSM_EVENT_ADDRESS_DISC = 16,	/*  Need to Discover rport's PID */
-	RPSM_EVENT_PRLO_RCVD = 17,      /*  PRLO from remote device      */
-};
-
-static void     bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
-					enum rport_event event);
-static void     bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
-					       enum rport_event event);
-static void     bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
-						  enum rport_event event);
-static void     bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
-				       enum rport_event event);
-static void     bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
-					    enum rport_event event);
-static void     bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
-					enum rport_event event);
-static void     bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
-						 enum rport_event event);
-static void     bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
-					 enum rport_event event);
-static void     bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
-					       enum rport_event event);
-static void     bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
-				       enum rport_event event);
-static void     bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
-					      enum rport_event event);
-static void     bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
-					      enum rport_event event);
-static void     bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
-					      enum rport_event event);
-static void     bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
-					 enum rport_event event);
-static void     bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
-						enum rport_event event);
-static void     bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
-					      enum rport_event event);
-static void     bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-
-static struct bfa_sm_table_s rport_sm_table[] = {
-	{BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
-	{BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
-	{BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
-	{BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
-	{BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
-	{BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
-	{BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
-	{BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
-	{BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
-	{BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
-	{BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
-	{BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
-	{BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
-	{BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
-	{BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
-	{BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
-	{BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
-	{BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
-	{BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
-	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
-	{BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
-	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
-};
-
-/**
- * 		Beginning state.
- */
-static void
-bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_PLOGI_SEND:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
-		rport->plogi_retries = 0;
-		bfa_fcs_rport_send_plogi(rport, NULL);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-	case RPSM_EVENT_ADDRESS_DISC:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		PLOGI is being sent.
- */
-static void
-bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
-			       enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_SCN:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		PLOGI is being sent.
- */
-static void
-bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
-				  enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * Ignore, SCN is possibly online notification.
-		 */
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_HCB_OFFLINE:
-		/**
-		 * Ignore BFA callback, on a PLOGI receive we call bfa offline.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		PLOGI is sent.
- */
-static void
-bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_SCN:
-		bfa_timer_stop(&rport->timer);
-		/*
-		 * !! fall through !!
-		 */
-
-	case RPSM_EVENT_TIMEOUT:
-		if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
-			rport->plogi_retries++;
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
-			bfa_fcs_rport_send_plogi(rport, NULL);
-		} else {
-			rport->pid = 0;
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-			bfa_timer_start(rport->fcs->bfa, &rport->timer,
-					bfa_fcs_rport_timeout, rport,
-					bfa_fcs_rport_del_timeout);
-		}
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_LOGO_RCVD:
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_timer_stop(&rport->timer);
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_timer_stop(&rport->timer);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		PLOGI is sent.
- */
-static void
-bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_ACCEPTED:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		rport->plogi_retries = 0;
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-		bfa_fcs_rport_send_logo_acc(rport);
-		/*
-		 * !! fall through !!
-		 */
-	case RPSM_EVENT_PRLO_RCVD:
-		if (rport->prlo == BFA_TRUE)
-			bfa_fcs_rport_send_prlo_acc(rport);
-
-		bfa_fcxp_discard(rport->fcxp);
-		/*
-		 * !! fall through !!
-		 */
-	case RPSM_EVENT_FAILED:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * Ignore SCN - wait for PLOGI response.
-		 */
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		PLOGI is complete. Awaiting BFA rport online callback. FC-4s
- * 		are offline.
- */
-static void
-bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_HCB_ONLINE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
-		bfa_fcs_rport_online_action(rport);
-		break;
-
-	case RPSM_EVENT_PRLO_RCVD:
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_rport_offline(rport->bfa_rport);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * @todo
-		 * Ignore SCN - PLOGI just completed, FC-4 login should detect
-		 * device failures.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport is ONLINE. FC-4s active.
- */
-static void
-bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_SCN:
-		/**
-		 * Pause FC-4 activity till rport is authenticated.
-		 * In switched fabrics, check presence of device in nameserver
-		 * first.
-		 */
-		bfa_fcs_rport_fc4_pause(rport);
-
-		if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
-			bfa_sm_set_state(rport,
-					 bfa_fcs_rport_sm_nsquery_sending);
-			rport->ns_retries = 0;
-			bfa_fcs_rport_send_gidpn(rport, NULL);
-		} else {
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
-			bfa_fcs_rport_send_adisc(rport, NULL);
-		}
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-	case RPSM_EVENT_LOGO_IMP:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		An SCN event is received in ONLINE state. NS query is being sent
- * 		prior to ADISC authentication with rport. FC-4s are paused.
- */
-static void
-bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
-				 enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * ignore SCN, wait for response to query itself
-		 */
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 	An SCN event is received in ONLINE state. NS query is sent to rport.
- * 	FC-4s are paused.
- */
-static void
-bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_ACCEPTED:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
-		bfa_fcs_rport_send_adisc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_FAILED:
-		rport->ns_retries++;
-		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
-			bfa_sm_set_state(rport,
-					 bfa_fcs_rport_sm_nsquery_sending);
-			bfa_fcs_rport_send_gidpn(rport, NULL);
-		} else {
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-			bfa_fcs_rport_offline_action(rport);
-		}
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-	case RPSM_EVENT_PLOGI_RCVD:
-	case RPSM_EVENT_LOGO_IMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 	An SCN event is received in ONLINE state. ADISC is being sent for
- * 	authenticating with rport. FC-4s are paused.
- */
-static void
-bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
-			       enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		An SCN event is received in ONLINE state. ADISC is to rport.
- * 		FC-4s are paused.
- */
-static void
-bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_ACCEPTED:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
-		bfa_fcs_rport_fc4_resume(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		/**
-		 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
-		 * At least go offline when a PLOGI is received.
-		 */
-		bfa_fcxp_discard(rport->fcxp);
-		/*
-		 * !!! fall through !!!
-		 */
-
-	case RPSM_EVENT_FAILED:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * already processing RSCN
-		 */
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport has sent LOGO. Awaiting FC-4 offline completion callback.
- */
-static void
-bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FC4_OFFLINE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		LOGO needs to be sent to rport. Awaiting FC-4 offline completion
- * 		callback.
- */
-static void
-bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
-			      enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FC4_OFFLINE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 	Rport is going offline. Awaiting FC-4 offline completion callback.
- */
-static void
-bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FC4_OFFLINE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_LOGO_IMP:
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		/**
-		 * rport is already going offline.
-		 * SCN - ignore and wait till transitioning to offline state
-		 */
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport is offline. FC-4s are offline. Awaiting BFA rport offline
- * 		callback.
- */
-static void
-bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_HCB_OFFLINE:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		if (bfa_fcs_port_is_online(rport->port)) {
-			if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
-				bfa_sm_set_state(rport,
-					bfa_fcs_rport_sm_nsdisc_sending);
-				rport->ns_retries = 0;
-				bfa_fcs_rport_send_gidpn(rport, NULL);
-			} else {
-				bfa_sm_set_state(rport,
-					bfa_fcs_rport_sm_plogi_sending);
-				rport->plogi_retries = 0;
-				bfa_fcs_rport_send_plogi(rport, NULL);
-			}
-		} else {
-			rport->pid = 0;
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-			bfa_timer_start(rport->fcs->bfa, &rport->timer,
-					bfa_fcs_rport_timeout, rport,
-					bfa_fcs_rport_del_timeout);
-		}
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		/**
-		 * Ignore, already offline.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport is offline. FC-4s are offline. Awaiting BFA rport offline
- * 		callback to send LOGO accept.
- */
-static void
-bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_HCB_OFFLINE:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		if (rport->pid && (rport->prlo == BFA_TRUE))
-			bfa_fcs_rport_send_prlo_acc(rport);
-		if (rport->pid && (rport->prlo == BFA_FALSE))
-			bfa_fcs_rport_send_logo_acc(rport);
-
-		/*
-		 * If the lport is online and if the rport is not a well known
-		 * address port, we try to re-discover the r-port.
-		 */
-		if (bfa_fcs_port_is_online(rport->port)
-		    && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
-			bfa_sm_set_state(rport,
-					 bfa_fcs_rport_sm_nsdisc_sending);
-			rport->ns_retries = 0;
-			bfa_fcs_rport_send_gidpn(rport, NULL);
-		} else {
-			/*
-			 * if it is not a well known address, reset the pid to
-			 *
-			 */
-			if (!BFA_FCS_PID_IS_WKA(rport->pid))
-				rport->pid = 0;
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-			bfa_timer_start(rport->fcs->bfa, &rport->timer,
-					bfa_fcs_rport_timeout, rport,
-					bfa_fcs_rport_del_timeout);
-		}
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		/**
-		 * Ignore - already processing a LOGO.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * Rport is being deleted. FC-4s are offline. Awaiting BFA rport offline
- * callback to send LOGO.
- */
-static void
-bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
-			      enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_HCB_OFFLINE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
-		bfa_fcs_rport_send_logo(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport is being deleted. FC-4s are offline. LOGO is being sent.
- */
-static void
-bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
-			      enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		/*
-		 * Once LOGO is sent, we donot wait for the response
-		 */
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport is offline. FC-4s are offline. BFA rport is offline.
- * 		Timer active to delete stale rport.
- */
-static void
-bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		bfa_timer_stop(&rport->timer);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_LOGO_IMP:
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_SEND:
-		bfa_timer_stop(&rport->timer);
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
-		rport->plogi_retries = 0;
-		bfa_fcs_rport_send_plogi(rport, NULL);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 	Rport address has changed. Nameserver discovery request is being sent.
- */
-static void
-bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
-				enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_PLOGI_SEND:
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		rport->ns_retries = 0;	/* reset the retry count */
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Nameserver discovery failed. Waiting for timeout to retry.
- */
-static void
-bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
-			      enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		bfa_timer_stop(&rport->timer);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_timer_stop(&rport->timer);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-		bfa_fcs_rport_send_logo_acc(rport);
-		break;
-
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_fcs_rport_send_prlo_acc(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * Rport address has changed. Nameserver discovery request is sent.
- */
-static void
-bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_ACCEPTED:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		if (rport->pid) {
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
-			bfa_fcs_rport_send_plogi(rport, NULL);
-		} else {
-			bfa_sm_set_state(rport,
-					 bfa_fcs_rport_sm_nsdisc_sending);
-			rport->ns_retries = 0;
-			bfa_fcs_rport_send_gidpn(rport, NULL);
-		}
-		break;
-
-	case RPSM_EVENT_FAILED:
-		rport->ns_retries++;
-		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
-			bfa_sm_set_state(rport,
-					 bfa_fcs_rport_sm_nsdisc_sending);
-			bfa_fcs_rport_send_gidpn(rport, NULL);
-		} else {
-			rport->pid = 0;
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-			bfa_timer_start(rport->fcs->bfa, &rport->timer,
-					bfa_fcs_rport_timeout, rport,
-					bfa_fcs_rport_del_timeout);
-		};
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_fcs_rport_send_prlo_acc(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * ignore, wait for NS query response
-		 */
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-		/**
-		 * Not logged-in yet. Accept LOGO.
-		 */
-		bfa_fcs_rport_send_logo_acc(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-
-
-/**
- *  fcs_rport_private FCS RPORT provate functions
- */
-
-static void
-bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-				    bfa_fcs_rport_send_plogi, rport);
-		return;
-	}
-	rport->fcxp = fcxp;
-
-	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.pwwn, port->port_cfg.nwwn,
-			     bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
-		      (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
-
-	rport->stats.plogis++;
-	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			     bfa_status_t req_status, u32 rsp_len,
-			     u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-	struct fc_logi_s	*plogi_rsp;
-	struct fc_ls_rjt_s	*ls_rjt;
-	struct bfa_fcs_rport_s *twin;
-	struct list_head *qe;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(rport->fcs, req_status);
-		rport->stats.plogi_failed++;
-		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-		return;
-	}
-
-	plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-	/**
-	 * Check for failure first.
-	 */
-	if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
-		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-		bfa_trc(rport->fcs, ls_rjt->reason_code);
-		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
-
-		rport->stats.plogi_rejects++;
-		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-		return;
-	}
-
-	/**
-	 * PLOGI is complete. Make sure this device is not one of the known
-	 * device with a new FC port address.
-	 */
-	list_for_each(qe, &rport->port->rport_q) {
-		twin = (struct bfa_fcs_rport_s *)qe;
-		if (twin == rport)
-			continue;
-		if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
-			bfa_trc(rport->fcs, twin->pid);
-			bfa_trc(rport->fcs, rport->pid);
-
-			/*
-			 * Update plogi stats in twin
-			 */
-			twin->stats.plogis += rport->stats.plogis;
-			twin->stats.plogi_rejects += rport->stats.plogi_rejects;
-			twin->stats.plogi_timeouts +=
-				rport->stats.plogi_timeouts;
-			twin->stats.plogi_failed += rport->stats.plogi_failed;
-			twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
-			twin->stats.plogi_accs++;
-
-			bfa_fcs_rport_delete(rport);
-
-			bfa_fcs_rport_update(twin, plogi_rsp);
-			twin->pid = rsp_fchs->s_id;
-			bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
-			return;
-		}
-	}
-
-	/**
-	 * Normal login path -- no evil twins.
-	 */
-	rport->stats.plogi_accs++;
-	bfa_fcs_rport_update(rport, plogi_rsp);
-	bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
-}
-
-static void
-bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->reply_oxid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-				    bfa_fcs_rport_send_plogiacc, rport);
-		return;
-	}
-	rport->fcxp = fcxp;
-
-	len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-				 bfa_fcs_port_get_fcid(port), rport->reply_oxid,
-				 port->port_cfg.pwwn, port->port_cfg.nwwn,
-				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
-
-	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-				    bfa_fcs_rport_send_adisc, rport);
-		return;
-	}
-	rport->fcxp = fcxp;
-
-	len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.pwwn, port->port_cfg.nwwn);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
-		      rport, FC_MAX_PDUSZ, FC_ELS_TOV);
-
-	rport->stats.adisc_sent++;
-	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			     bfa_status_t req_status, u32 rsp_len,
-			     u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-	void           *pld = bfa_fcxp_get_rspbuf(fcxp);
-	struct fc_ls_rjt_s    *ls_rjt;
-
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(rport->fcs, req_status);
-		rport->stats.adisc_failed++;
-		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-		return;
-	}
-
-	if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
-		rport->nwwn)  == FC_PARSE_OK) {
-		rport->stats.adisc_accs++;
-		bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
-		return;
-	}
-
-	rport->stats.adisc_rejects++;
-	ls_rjt = pld;
-	bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
-	bfa_trc(rport->fcs, ls_rjt->reason_code);
-	bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
-	bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-}
-
-static void
-bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	int             len;
-
-	bfa_trc(rport->fcs, rport->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-				    bfa_fcs_rport_send_gidpn, rport);
-		return;
-	}
-	rport->fcxp = fcxp;
-
-	len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_fcs_port_get_fcid(port), 0, rport->pwwn);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response,
-		      (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			     bfa_status_t req_status, u32 rsp_len,
-			     u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-	struct bfa_fcs_rport_s *twin;
-	struct list_head *qe;
-	struct ct_hdr_s       	*cthdr;
-	struct fcgs_gidpn_resp_s	*gidpn_rsp;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		/*
-		 * Check if the pid is the same as before.
-		 */
-		gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
-
-		if (gidpn_rsp->dap == rport->pid) {
-			/*
-			 * Device is online
-			 */
-			bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
-		} else {
-			/*
-			 * Device's PID has changed. We need to cleanup and
-			 * re-login. If there is another device with the the
-			 * newly discovered pid, send an scn notice so that its
-			 * new pid can be discovered.
-			 */
-			list_for_each(qe, &rport->port->rport_q) {
-				twin = (struct bfa_fcs_rport_s *)qe;
-				if (twin == rport)
-					continue;
-				if (gidpn_rsp->dap == twin->pid) {
-					bfa_trc(rport->fcs, twin->pid);
-					bfa_trc(rport->fcs, rport->pid);
-
-					twin->pid = 0;
-					bfa_sm_send_event(twin,
-						RPSM_EVENT_ADDRESS_CHANGE);
-				}
-			}
-			rport->pid = gidpn_rsp->dap;
-			bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
-		}
-		return;
-	}
-
-	/*
-	 * Reject Response
-	 */
-	switch (cthdr->reason_code) {
-	case CT_RSN_LOGICAL_BUSY:
-		/*
-		 * Need to retry
-		 */
-		bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
-		break;
-
-	case CT_RSN_UNABLE_TO_PERF:
-		/*
-		 * device doesn't exist : Start timer to cleanup this later.
-		 */
-		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-		break;
-
-	default:
-		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-		break;
-	}
-}
-
-/**
- *    Called to send a logout to the rport.
- */
-static void
-bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port;
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	u16        len;
-
-	bfa_trc(rport->fcs, rport->pid);
-
-	port = rport->port;
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-				    bfa_fcs_rport_send_logo, rport);
-		return;
-	}
-	rport->fcxp = fcxp;
-
-	len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-			    bfa_fcs_port_get_fcid(port), 0,
-			    bfa_fcs_port_get_pwwn(port));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ,
-		      FC_ELS_TOV);
-
-	rport->stats.logos++;
-	bfa_fcxp_discard(rport->fcxp);
-	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
-}
-
-/**
- *    Send ACC for a LOGO received.
- */
-static void
-bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port;
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	u16        len;
-
-	bfa_trc(rport->fcs, rport->pid);
-
-	port = rport->port;
-
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp)
-		return;
-
-	rport->stats.logo_rcvd++;
-	len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-				bfa_fcs_port_get_fcid(port), rport->reply_oxid);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
-}
-
-/**
- *     This routine will be called by bfa_timer on timer timeouts.
- *
- * 	param[in] 	rport 			- pointer to bfa_fcs_port_ns_t.
- * 	param[out]	rport_status 	- pointer to return vport status in
- *
- * 	return
- * 		void
- *
-*  	Special Considerations:
- *
- * 	note
- */
-static void
-bfa_fcs_rport_timeout(void *arg)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)arg;
-
-	rport->stats.plogi_timeouts++;
-	bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
-}
-
-static void
-bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u16 len)
-{
-	struct bfa_fcxp_s *fcxp;
-	struct fchs_s          fchs;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fc_prli_s      *prli;
-
-	bfa_trc(port->fcs, rx_fchs->s_id);
-	bfa_trc(port->fcs, rx_fchs->d_id);
-
-	rport->stats.prli_rcvd++;
-
-	if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
-		/*
-		 * Target Mode : Let the fcptm handle it
-		 */
-		bfa_fcs_tin_rx_prli(rport->tin, rx_fchs, len);
-		return;
-	}
-
-	/*
-	 * We are either in Initiator or ipfc Mode
-	 */
-	prli = (struct fc_prli_s *) (rx_fchs + 1);
-
-	if (prli->parampage.servparams.initiator) {
-		bfa_trc(rport->fcs, prli->parampage.type);
-		rport->scsi_function = BFA_RPORT_INITIATOR;
-		bfa_fcs_itnim_is_initiator(rport->itnim);
-	} else {
-		/*
-		 * @todo: PRLI from a target ?
-		 */
-		bfa_trc(port->fcs, rx_fchs->s_id);
-		rport->scsi_function = BFA_RPORT_TARGET;
-	}
-
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp)
-		return;
-
-	len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-				bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
-				port->port_cfg.roles);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
-}
-
-static void
-bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u16 len)
-{
-	struct bfa_fcxp_s *fcxp;
-	struct fchs_s          fchs;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fc_rpsc_speed_info_s speeds;
-	struct bfa_pport_attr_s pport_attr;
-
-	bfa_trc(port->fcs, rx_fchs->s_id);
-	bfa_trc(port->fcs, rx_fchs->d_id);
-
-	rport->stats.rpsc_rcvd++;
-	speeds.port_speed_cap =
-		RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
-		RPSC_SPEED_CAP_8G;
-
-	/*
-	 * get curent speed from pport attributes from BFA
-	 */
-	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
-
-	speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
-
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp)
-		return;
-
-	len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-				bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
-				&speeds);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
-}
-
-static void
-bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u16 len)
-{
-	struct bfa_fcxp_s *fcxp;
-	struct fchs_s          fchs;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fc_adisc_s      *adisc;
-
-	bfa_trc(port->fcs, rx_fchs->s_id);
-	bfa_trc(port->fcs, rx_fchs->d_id);
-
-	rport->stats.adisc_rcvd++;
-
-	if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
-		/*
-		 * @todo : Target Mode handling
-		 */
-		bfa_trc(port->fcs, rx_fchs->d_id);
-		bfa_assert(0);
-		return;
-	}
-
-	adisc = (struct fc_adisc_s *) (rx_fchs + 1);
-
-	/*
-	 * Accept if the itnim for this rport is online. Else reject the ADISC
-	 */
-	if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
-
-		fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-		if (!fcxp)
-			return;
-
-		len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-					 rx_fchs->s_id,
-					 bfa_fcs_port_get_fcid(port),
-					 rx_fchs->ox_id, port->port_cfg.pwwn,
-					 port->port_cfg.nwwn);
-
-		bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
-			      BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
-			      FC_MAX_PDUSZ, 0);
-	} else {
-		rport->stats.adisc_rejected++;
-		bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
-					  FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
-					  FC_LS_RJT_EXP_LOGIN_REQUIRED);
-	}
-
-}
-
-static void
-bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-	struct bfa_rport_info_s rport_info;
-
-	rport_info.pid = rport->pid;
-	rport_info.local_pid = port->pid;
-	rport_info.lp_tag = port->lp_tag;
-	rport_info.vf_id = port->fabric->vf_id;
-	rport_info.vf_en = port->fabric->is_vf;
-	rport_info.fc_class = rport->fc_cos;
-	rport_info.cisc = rport->cisc;
-	rport_info.max_frmsz = rport->maxfrsize;
-	bfa_rport_online(rport->bfa_rport, &rport_info);
-}
-
-static void
-bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport)
-{
-	if (bfa_fcs_port_is_initiator(rport->port))
-		bfa_fcs_itnim_pause(rport->itnim);
-
-	if (bfa_fcs_port_is_target(rport->port))
-		bfa_fcs_tin_pause(rport->tin);
-}
-
-static void
-bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport)
-{
-	if (bfa_fcs_port_is_initiator(rport->port))
-		bfa_fcs_itnim_resume(rport->itnim);
-
-	if (bfa_fcs_port_is_target(rport->port))
-		bfa_fcs_tin_resume(rport->tin);
-}
-
-static struct bfa_fcs_rport_s *
-bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
-{
-	struct bfa_fcs_s *fcs = port->fcs;
-	struct bfa_fcs_rport_s *rport;
-	struct bfad_rport_s *rport_drv;
-
-	/**
-	 * allocate rport
-	 */
-	if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
-	    != BFA_STATUS_OK) {
-		bfa_trc(fcs, rpid);
-		return NULL;
-	}
-
-	/*
-	 * Initialize r-port
-	 */
-	rport->port = port;
-	rport->fcs = fcs;
-	rport->rp_drv = rport_drv;
-	rport->pid = rpid;
-	rport->pwwn = pwwn;
-
-	/**
-	 * allocate BFA rport
-	 */
-	rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
-	if (!rport->bfa_rport) {
-		bfa_trc(fcs, rpid);
-		kfree(rport_drv);
-		return NULL;
-	}
-
-	/**
-	 * allocate FC-4s
-	 */
-	bfa_assert(bfa_fcs_port_is_initiator(port) ^
-		   bfa_fcs_port_is_target(port));
-
-	if (bfa_fcs_port_is_initiator(port)) {
-		rport->itnim = bfa_fcs_itnim_create(rport);
-		if (!rport->itnim) {
-			bfa_trc(fcs, rpid);
-			bfa_rport_delete(rport->bfa_rport);
-			kfree(rport_drv);
-			return NULL;
-		}
-	}
-
-	if (bfa_fcs_port_is_target(port)) {
-		rport->tin = bfa_fcs_tin_create(rport);
-		if (!rport->tin) {
-			bfa_trc(fcs, rpid);
-			bfa_rport_delete(rport->bfa_rport);
-			kfree(rport_drv);
-			return NULL;
-		}
-	}
-
-	bfa_fcs_port_add_rport(port, rport);
-
-	bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-
-	/*
-	 * Initialize the Rport Features(RPF) Sub Module
-	 */
-	if (!BFA_FCS_PID_IS_WKA(rport->pid))
-		bfa_fcs_rpf_init(rport);
-
-	return rport;
-}
-
-
-static void
-bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-
-	/**
-	 * - delete FC-4s
-	 * - delete BFA rport
-	 * - remove from queue of rports
-	 */
-	if (bfa_fcs_port_is_initiator(port))
-		bfa_fcs_itnim_delete(rport->itnim);
-
-	if (bfa_fcs_port_is_target(port))
-		bfa_fcs_tin_delete(rport->tin);
-
-	bfa_rport_delete(rport->bfa_rport);
-	bfa_fcs_port_del_rport(port, rport);
-	kfree(rport->rp_drv);
-}
-
-static void
-bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
-		       enum bfa_rport_aen_event event,
-		       struct bfa_rport_aen_data_s *data)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = rport->fcs->logm;
-	wwn_t           lpwwn = bfa_fcs_port_get_pwwn(rport->port);
-	wwn_t           rpwwn = rport->pwwn;
-	char            lpwwn_ptr[BFA_STRING_32];
-	char            rpwwn_ptr[BFA_STRING_32];
-	char           *prio_str[] = { "unknown", "high", "medium", "low" };
-
-	wwn2str(lpwwn_ptr, lpwwn);
-	wwn2str(rpwwn_ptr, rpwwn);
-
-	switch (event) {
-	case BFA_RPORT_AEN_ONLINE:
-	case BFA_RPORT_AEN_OFFLINE:
-	case BFA_RPORT_AEN_DISCONNECT:
-		bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, event),
-			rpwwn_ptr, lpwwn_ptr);
-		break;
-	case BFA_RPORT_AEN_QOS_PRIO:
-		aen_data.rport.priv.qos = data->priv.qos;
-		bfa_log(logmod, BFA_AEN_RPORT_QOS_PRIO,
-			prio_str[aen_data.rport.priv.qos.qos_priority],
-			rpwwn_ptr, lpwwn_ptr);
-		break;
-	case BFA_RPORT_AEN_QOS_FLOWID:
-		aen_data.rport.priv.qos = data->priv.qos;
-		bfa_log(logmod, BFA_AEN_RPORT_QOS_FLOWID,
-			aen_data.rport.priv.qos.qos_flow_id, rpwwn_ptr,
-			lpwwn_ptr);
-		break;
-	default:
-		break;
-	}
-
-	aen_data.rport.vf_id = rport->port->fabric->vf_id;
-	aen_data.rport.ppwwn =
-		bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(rport->fcs));
-	aen_data.rport.lpwwn = lpwwn;
-	aen_data.rport.rpwwn = rpwwn;
-}
-
-static void
-bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-
-	rport->stats.onlines++;
-
-	if (bfa_fcs_port_is_initiator(port)) {
-		bfa_fcs_itnim_rport_online(rport->itnim);
-		if (!BFA_FCS_PID_IS_WKA(rport->pid))
-			bfa_fcs_rpf_rport_online(rport);
-	};
-
-	if (bfa_fcs_port_is_target(port))
-		bfa_fcs_tin_rport_online(rport->tin);
-
-	/*
-	 * Don't post events for well known addresses
-	 */
-	if (!BFA_FCS_PID_IS_WKA(rport->pid))
-		bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
-}
-
-static void
-bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-
-	rport->stats.offlines++;
-
-	/*
-	 * Don't post events for well known addresses
-	 */
-	if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
-		if (bfa_fcs_port_is_online(rport->port) == BFA_TRUE) {
-			bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_DISCONNECT,
-					       NULL);
-		} else {
-			bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_OFFLINE,
-					       NULL);
-		}
-	}
-
-	if (bfa_fcs_port_is_initiator(port)) {
-		bfa_fcs_itnim_rport_offline(rport->itnim);
-		if (!BFA_FCS_PID_IS_WKA(rport->pid))
-			bfa_fcs_rpf_rport_offline(rport);
-	}
-
-	if (bfa_fcs_port_is_target(port))
-		bfa_fcs_tin_rport_offline(rport->tin);
-}
-
-/**
- * Update rport parameters from PLOGI or PLOGI accept.
- */
-static void
-bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-
-	/**
-	 * - port name
-	 * - node name
-	 */
-	rport->pwwn = plogi->port_name;
-	rport->nwwn = plogi->node_name;
-
-	/**
-	 * - class of service
-	 */
-	rport->fc_cos = 0;
-	if (plogi->class3.class_valid)
-		rport->fc_cos = FC_CLASS_3;
-
-	if (plogi->class2.class_valid)
-		rport->fc_cos |= FC_CLASS_2;
-
-	/**
-	 * - CISC
-	 * - MAX receive frame size
-	 */
-	rport->cisc = plogi->csp.cisc;
-	rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz);
-
-	bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
-	bfa_trc(port->fcs, port->fabric->bb_credit);
-	/**
-	 * Direct Attach P2P mode :
-	 * This is to handle a bug (233476) in IBM targets in Direct Attach
-	 * Mode. Basically, in FLOGI Accept the target would have erroneously
-	 * set the BB Credit to the value used in the FLOGI sent by the HBA.
-	 * It uses the correct value (its own BB credit) in PLOGI.
-	 */
-	if ((!bfa_fcs_fabric_is_switched(port->fabric))
-	    && (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
-
-		bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
-		bfa_trc(port->fcs, port->fabric->bb_credit);
-
-		port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred);
-		bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
-					  port->fabric->bb_credit);
-	}
-
-}
-
-/**
- *   Called to handle LOGO received from an existing remote port.
- */
-static void
-bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
-{
-	rport->reply_oxid = fchs->ox_id;
-	bfa_trc(rport->fcs, rport->reply_oxid);
-
-	rport->prlo = BFA_FALSE;
-	rport->stats.logo_rcvd++;
-	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
-}
-
-
-
-/**
- *  fcs_rport_public FCS rport public interfaces
- */
-
-/**
- * 	Called by bport/vport to create a remote port instance for a discovered
- * 	remote device.
- *
- * @param[in] port	- base port or vport
- * @param[in] rpid	- remote port ID
- *
- * @return None
- */
-struct bfa_fcs_rport_s *
-bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	bfa_trc(port->fcs, rpid);
-	rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
-	if (!rport)
-		return NULL;
-
-	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
-	return rport;
-}
-
-/**
- * Called to create a rport for which only the wwn is known.
- *
- * @param[in] port	- base port
- * @param[in] rpwwn	- remote port wwn
- *
- * @return None
- */
-struct bfa_fcs_rport_s *
-bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	bfa_trc(port->fcs, rpwwn);
-	rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
-	if (!rport)
-		return NULL;
-
-	bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
-	return rport;
-}
-
-/**
- * Called by bport in private loop topology to indicate that a
- * rport has been discovered and plogi has been completed.
- *
- * @param[in] port	- base port or vport
- * @param[in] rpid	- remote port ID
- */
-void
-bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
-			struct fc_logi_s *plogi)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
-	if (!rport)
-		return;
-
-	bfa_fcs_rport_update(rport, plogi);
-
-	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
-}
-
-/**
- *   Called by bport/vport to handle PLOGI received from a new remote port.
- *   If an existing rport does a plogi, it will be handled separately.
- */
-void
-bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
-			   struct fc_logi_s *plogi)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
-	if (!rport)
-		return;
-
-	bfa_fcs_rport_update(rport, plogi);
-
-	rport->reply_oxid = fchs->ox_id;
-	bfa_trc(rport->fcs, rport->reply_oxid);
-
-	rport->stats.plogi_rcvd++;
-	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
-}
-
-static int
-wwn_compare(wwn_t wwn1, wwn_t wwn2)
-{
-	u8        *b1 = (u8 *) &wwn1;
-	u8        *b2 = (u8 *) &wwn2;
-	int             i;
-
-	for (i = 0; i < sizeof(wwn_t); i++) {
-		if (b1[i] < b2[i])
-			return -1;
-		if (b1[i] > b2[i])
-			return 1;
-	}
-	return 0;
-}
-
-/**
- *   Called by bport/vport to handle PLOGI received from an existing
- * 	 remote port.
- */
-void
-bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
-		    struct fc_logi_s *plogi)
-{
-	/**
-	 * @todo Handle P2P and initiator-initiator.
-	 */
-
-	bfa_fcs_rport_update(rport, plogi);
-
-	rport->reply_oxid = rx_fchs->ox_id;
-	bfa_trc(rport->fcs, rport->reply_oxid);
-
-	/**
-	 * In Switched fabric topology,
-	 * PLOGI to each other. If our pwwn is smaller, ignore it,
-	 * if it is not a well known address.
-	 * If the link topology is N2N,
-	 * this Plogi should be accepted.
-	 */
-	if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1)
-	    && (bfa_fcs_fabric_is_switched(rport->port->fabric))
-	    && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
-		bfa_trc(rport->fcs, rport->pid);
-		return;
-	}
-
-	rport->stats.plogi_rcvd++;
-	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
-}
-
-/**
- * Called by bport/vport to delete a remote port instance.
- *
-* Rport delete is called under the following conditions:
- * 		- vport is deleted
- * 		- vf is deleted
- * 		- explicit request from OS to delete rport (vmware)
- */
-void
-bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
-}
-
-/**
- * Called by bport/vport to  when a target goes offline.
- *
- */
-void
-bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
-}
-
-/**
- * Called by bport in n2n when a target (attached port) becomes online.
- *
- */
-void
-bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
-}
-
-/**
- *   Called by bport/vport to notify SCN for the remote port
- */
-void
-bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
-{
-
-	rport->stats.rscns++;
-	bfa_sm_send_event(rport, RPSM_EVENT_SCN);
-}
-
-/**
- *   Called by  fcpim to notify that the ITN cleanup is done.
- */
-void
-bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
-}
-
-/**
- *   Called by fcptm to notify that the ITN cleanup is done.
- */
-void
-bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
-}
-
-/**
- *     This routine BFA callback for bfa_rport_online() call.
- *
- * 	param[in] 	cb_arg	-  rport struct.
- *
- * 	return
- * 		void
- *
-* 	Special Considerations:
- *
- * 	note
- */
-void
-bfa_cb_rport_online(void *cbarg)
-{
-
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
-}
-
-/**
- *     This routine BFA callback for bfa_rport_offline() call.
- *
- * 	param[in] 	rport 	-
- *
- * 	return
- * 		void
- *
- * 	Special Considerations:
- *
- * 	note
- */
-void
-bfa_cb_rport_offline(void *cbarg)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
-}
-
-/**
- * This routine is a static BFA callback when there is a QoS flow_id
- * change notification
- *
- * @param[in] 	rport 	-
- *
- * @return  	void
- *
- * Special Considerations:
- *
- * @note
- */
-void
-bfa_cb_rport_qos_scn_flowid(void *cbarg,
-			    struct bfa_rport_qos_attr_s old_qos_attr,
-			    struct bfa_rport_qos_attr_s new_qos_attr)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-	struct bfa_rport_aen_data_s aen_data;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	aen_data.priv.qos = new_qos_attr;
-	bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
-}
-
-/**
- * This routine is a static BFA callback when there is a QoS priority
- * change notification
- *
- * @param[in] 	rport 	-
- *
- * @return 	void
- *
- * Special Considerations:
- *
- * @note
- */
-void
-bfa_cb_rport_qos_scn_prio(void *cbarg, struct bfa_rport_qos_attr_s old_qos_attr,
-			  struct bfa_rport_qos_attr_s new_qos_attr)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-	struct bfa_rport_aen_data_s aen_data;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	aen_data.priv.qos = new_qos_attr;
-	bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
-}
-
-/**
- * 		Called to process any unsolicted frames from this remote port
- */
-void
-bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
-}
-
-/**
- * 		Called to process any unsolicted frames from this remote port
- */
-void
-bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
-			u16 len)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fc_els_cmd_s   *els_cmd;
-
-	bfa_trc(rport->fcs, fchs->s_id);
-	bfa_trc(rport->fcs, fchs->d_id);
-	bfa_trc(rport->fcs, fchs->type);
-
-	if (fchs->type != FC_TYPE_ELS)
-		return;
-
-	els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-
-	bfa_trc(rport->fcs, els_cmd->els_code);
-
-	switch (els_cmd->els_code) {
-	case FC_ELS_LOGO:
-		bfa_fcs_rport_process_logo(rport, fchs);
-		break;
-
-	case FC_ELS_ADISC:
-		bfa_fcs_rport_process_adisc(rport, fchs, len);
-		break;
-
-	case FC_ELS_PRLO:
-		if (bfa_fcs_port_is_initiator(port))
-			bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
-
-		if (bfa_fcs_port_is_target(port))
-			bfa_fcs_fcptm_uf_recv(rport->tin, fchs, len);
-		break;
-
-	case FC_ELS_PRLI:
-		bfa_fcs_rport_process_prli(rport, fchs, len);
-		break;
-
-	case FC_ELS_RPSC:
-		bfa_fcs_rport_process_rpsc(rport, fchs, len);
-		break;
-
-	default:
-		bfa_fcs_rport_send_ls_rjt(rport, fchs,
-					  FC_LS_RJT_RSN_CMD_NOT_SUPP,
-					  FC_LS_RJT_EXP_NO_ADDL_INFO);
-		break;
-	}
-}
-
-/* Send best case acc to prlo */
-static void
-bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s fchs;
-	struct bfa_fcxp_s *fcxp;
-	int len;
-
-	bfa_trc(rport->fcs, rport->pid);
-
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp)
-		return;
-
-	len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			rport->pid, bfa_fcs_port_get_fcid(port),
-			rport->reply_oxid, 0);
-
-	bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,
-			port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
-			NULL, NULL, FC_MAX_PDUSZ, 0);
-}
-
-/*
- * Send a LS reject
- */
-static void
-bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
-			  u8 reason_code, u8 reason_code_expl)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	int             len;
-
-	bfa_trc(rport->fcs, rx_fchs->s_id);
-
-	fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
-	if (!fcxp)
-		return;
-
-	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-			      bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
-			      reason_code, reason_code_expl);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
-}
-
-/**
- * Return state of rport.
- */
-int
-bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
-{
-	return bfa_sm_to_state(rport_sm_table, rport->sm);
-}
-
-/**
- * 		 Called by the Driver to set rport delete/ageout timeout
- *
- * 	param[in]		rport timeout value in seconds.
- *
- * 	return None
- */
-void
-bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
-{
-	/*
-	 * convert to Millisecs
-	 */
-	if (rport_tmo > 0)
-		bfa_fcs_rport_del_timeout = rport_tmo * 1000;
-}
-
-void
-bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id)
-{
-	bfa_trc(rport->fcs, rport->pid);
-
-	rport->prlo = BFA_TRUE;
-	rport->reply_oxid = ox_id;
-	bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
-}
diff --git a/drivers/scsi/bfa/rport_api.c b/drivers/scsi/bfa/rport_api.c
deleted file mode 100644
index 15e0c47..0000000
--- a/drivers/scsi/bfa/rport_api.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_vport.h"
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-
-BFA_TRC_FILE(FCS, RPORT_API);
-
-/**
- *  rport_api.c Remote port implementation.
- */
-
-/**
- *  fcs_rport_api FCS rport API.
- */
-
-/**
- * 	Direct API to add a target by port wwn. This interface is used, for
- *	example, by bios when target pwwn is known from boot lun configuration.
- */
-bfa_status_t
-bfa_fcs_rport_add(struct bfa_fcs_port_s *port, wwn_t *pwwn,
-			struct bfa_fcs_rport_s *rport,
-			struct bfad_rport_s *rport_drv)
-{
-	bfa_trc(port->fcs, *pwwn);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *	Direct API to remove a target and its associated resources. This
- *	interface is used, for example, by vmware driver to remove target
- *	ports from the target list for a VM.
- */
-bfa_status_t
-bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in)
-{
-
-	struct bfa_fcs_rport_s *rport;
-
-	bfa_trc(rport_in->fcs, rport_in->pwwn);
-
-	rport = bfa_fcs_port_get_rport_by_pwwn(rport_in->port, rport_in->pwwn);
-	if (rport == NULL) {
-		/*
-		 * TBD Error handling
-		 */
-		bfa_trc(rport_in->fcs, rport_in->pid);
-		return BFA_STATUS_UNKNOWN_RWWN;
-	}
-
-	/*
-	 * TBD if this remote port is online, send a logo
-	 */
-	return BFA_STATUS_OK;
-
-}
-
-/**
- *	Remote device status for display/debug.
- */
-void
-bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
-			struct bfa_rport_attr_s *rport_attr)
-{
-	struct bfa_rport_qos_attr_s qos_attr;
-	struct bfa_fcs_port_s *port = rport->port;
-	enum bfa_pport_speed rport_speed = rport->rpf.rpsc_speed;
-
-	bfa_os_memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
-
-	rport_attr->pid = rport->pid;
-	rport_attr->pwwn = rport->pwwn;
-	rport_attr->nwwn = rport->nwwn;
-	rport_attr->cos_supported = rport->fc_cos;
-	rport_attr->df_sz = rport->maxfrsize;
-	rport_attr->state = bfa_fcs_rport_get_state(rport);
-	rport_attr->fc_cos = rport->fc_cos;
-	rport_attr->cisc = rport->cisc;
-	rport_attr->scsi_function = rport->scsi_function;
-	rport_attr->curr_speed  = rport->rpf.rpsc_speed;
-	rport_attr->assigned_speed  = rport->rpf.assigned_speed;
-
-	bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr);
-	rport_attr->qos_attr = qos_attr;
-
-	rport_attr->trl_enforced = BFA_FALSE;
-
-	if (bfa_fcport_is_ratelim(port->fcs->bfa)) {
-		if (rport_speed == BFA_PPORT_SPEED_UNKNOWN) {
-			/* Use default ratelim speed setting */
-			rport_speed =
-				bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
-		}
-		if (rport_speed < bfa_fcs_port_get_rport_max_speed(port))
-			rport_attr->trl_enforced = BFA_TRUE;
-	}
-
-	/*
-	 * TODO
-	 * rport->symname
-	 */
-}
-
-/**
- * 	Per remote device statistics.
- */
-void
-bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
-			struct bfa_rport_stats_s *stats)
-{
-	*stats = rport->stats;
-}
-
-void
-bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport)
-{
-	bfa_os_memset((char *)&rport->stats, 0,
-			sizeof(struct bfa_rport_stats_s));
-}
-
-struct bfa_fcs_rport_s *
-bfa_fcs_rport_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	rport = bfa_fcs_port_get_rport_by_pwwn(port, rpwwn);
-	if (rport == NULL) {
-		/*
-		 * TBD Error handling
-		 */
-	}
-
-	return rport;
-}
-
-struct bfa_fcs_rport_s *
-bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_port_s *port, wwn_t rnwwn)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	rport = bfa_fcs_port_get_rport_by_nwwn(port, rnwwn);
-	if (rport == NULL) {
-		/*
-		 * TBD Error handling
-		 */
-	}
-
-	return rport;
-}
-
-/*
- * This API is to set the Rport's speed. Should be used when RPSC is not
- * supported by the rport.
- */
-void
-bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
-			enum bfa_pport_speed speed)
-{
-	rport->rpf.assigned_speed  = speed;
-
-	/* Set this speed in f/w only if the RPSC speed is not available */
-	if (rport->rpf.rpsc_speed == BFA_PPORT_SPEED_UNKNOWN)
-		bfa_rport_speed(rport->bfa_rport, speed);
-}
-
-
diff --git a/drivers/scsi/bfa/rport_ftrs.c b/drivers/scsi/bfa/rport_ftrs.c
deleted file mode 100644
index f2a9361..0000000
--- a/drivers/scsi/bfa/rport_ftrs.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  rport_ftrs.c Remote port features (RPF) implementation.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcbuild.h"
-#include "fcs_rport.h"
-#include "fcs_lport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-
-BFA_TRC_FILE(FCS, RPORT_FTRS);
-
-#define BFA_FCS_RPF_RETRIES	(3)
-#define BFA_FCS_RPF_RETRY_TIMEOUT  (1000) /* 1 sec (In millisecs) */
-
-static void     bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
-			struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rpf_rpsc2_response(void *fcsarg,
-			struct bfa_fcxp_s *fcxp, void *cbarg,
-			bfa_status_t req_status, u32 rsp_len,
-			u32 resid_len,
-			struct fchs_s *rsp_fchs);
-static void     bfa_fcs_rpf_timeout(void *arg);
-
-/**
- *  fcs_rport_ftrs_sm FCS rport state machine events
- */
-
-enum rpf_event {
-	RPFSM_EVENT_RPORT_OFFLINE  = 1,     /*  Rport offline            */
-	RPFSM_EVENT_RPORT_ONLINE   = 2,     /*  Rport online            */
-	RPFSM_EVENT_FCXP_SENT      = 3,    /*  Frame from has been sent */
-	RPFSM_EVENT_TIMEOUT  	   = 4,    /*  Rport SM timeout event   */
-	RPFSM_EVENT_RPSC_COMP      = 5,
-	RPFSM_EVENT_RPSC_FAIL      = 6,
-	RPFSM_EVENT_RPSC_ERROR     = 7,
-};
-
-static void	bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
-					enum rpf_event event);
-static void     bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
-					       enum rpf_event event);
-static void     bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
-					       enum rpf_event event);
-static void 	bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
-							enum rpf_event event);
-static void     bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
-							enum rpf_event event);
-static void     bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
-							enum rpf_event event);
-
-static void
-bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-	struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_RPORT_ONLINE:
-		/* Send RPSC2 to a Brocade fabric only. */
-		if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
-			((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) ||
-			(bfa_fcs_fabric_get_switch_oui(fabric) ==
-						BFA_FCS_BRCD_SWITCH_OUI))) {
-			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
-			rpf->rpsc_retries = 0;
-			bfa_fcs_rpf_send_rpsc2(rpf, NULL);
-		}
-		break;
-
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
-		break;
-
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
-		rpf->rpsc_retries = 0;
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_RPSC_COMP:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
-		/* Update speed info in f/w via BFA */
-		if (rpf->rpsc_speed != BFA_PPORT_SPEED_UNKNOWN)
-			bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
-		else if (rpf->assigned_speed != BFA_PPORT_SPEED_UNKNOWN)
-			bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
-		break;
-
-	case RPFSM_EVENT_RPSC_FAIL:
-		/* RPSC not supported by rport */
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
-		break;
-
-	case RPFSM_EVENT_RPSC_ERROR:
-		/* need to retry...delayed a bit. */
-		if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
-			bfa_timer_start(rport->fcs->bfa, &rpf->timer,
-				    bfa_fcs_rpf_timeout, rpf,
-				    BFA_FCS_RPF_RETRY_TIMEOUT);
-			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
-		} else {
-			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
-		}
-		break;
-
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
-		bfa_fcxp_discard(rpf->fcxp);
-		rpf->rpsc_retries = 0;
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_TIMEOUT:
-		/* re-send the RPSC */
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
-		bfa_fcs_rpf_send_rpsc2(rpf, NULL);
-		break;
-
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		bfa_timer_stop(&rpf->timer);
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
-		rpf->rpsc_retries = 0;
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
-		rpf->rpsc_retries = 0;
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_RPORT_ONLINE:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
-		bfa_fcs_rpf_send_rpsc2(rpf, NULL);
-		break;
-
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-/**
- * Called when Rport is created.
- */
-void  bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_rpf_s *rpf = &rport->rpf;
-
-	bfa_trc(rport->fcs, rport->pid);
-	rpf->rport = rport;
-
-	bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
-}
-
-/**
- * Called when Rport becomes online
- */
-void  bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
-{
-	bfa_trc(rport->fcs, rport->pid);
-
-	if (__fcs_min_cfg(rport->port->fcs))
-		return;
-
-	if (bfa_fcs_fabric_is_switched(rport->port->fabric))
-		bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
-}
-
-/**
- * Called when Rport becomes offline
- */
-void  bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
-{
-	bfa_trc(rport->fcs, rport->pid);
-
-	if (__fcs_min_cfg(rport->port->fcs))
-		return;
-
-	rport->rpf.rpsc_speed = 0;
-	bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
-}
-
-static void
-bfa_fcs_rpf_timeout(void *arg)
-{
-	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
-}
-
-static void
-bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rpf_s *rpf 	= (struct bfa_fcs_rpf_s *)rpf_cbarg;
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
-					bfa_fcs_rpf_send_rpsc2, rpf);
-		return;
-	}
-	rpf->fcxp = fcxp;
-
-	len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-			    bfa_fcs_port_get_fcid(port), &rport->pid, 1);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-			  FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
-			  rpf, FC_MAX_PDUSZ, FC_ELS_TOV);
-	rport->stats.rpsc_sent++;
-	bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
-
-}
-
-static void
-bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			    bfa_status_t req_status, u32 rsp_len,
-			    u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-	struct fc_ls_rjt_s    *ls_rjt;
-	struct fc_rpsc2_acc_s  *rpsc2_acc;
-	u16        num_ents;
-
-	bfa_trc(rport->fcs, req_status);
-
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(rport->fcs, req_status);
-		if (req_status == BFA_STATUS_ETIMER)
-			rport->stats.rpsc_failed++;
-		bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
-		return;
-	}
-
-	rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
-	if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
-		rport->stats.rpsc_accs++;
-		num_ents = bfa_os_ntohs(rpsc2_acc->num_pids);
-		bfa_trc(rport->fcs, num_ents);
-		if (num_ents > 0) {
-			bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
-			bfa_trc(rport->fcs,
-				bfa_os_ntohs(rpsc2_acc->port_info[0].pid));
-			bfa_trc(rport->fcs,
-				bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
-			bfa_trc(rport->fcs,
-				bfa_os_ntohs(rpsc2_acc->port_info[0].index));
-			bfa_trc(rport->fcs,
-				rpsc2_acc->port_info[0].type);
-
-			if (rpsc2_acc->port_info[0].speed == 0) {
-				bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
-				return;
-			}
-
-			rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
-				bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
-
-			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
-		}
-	} else {
-		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-		bfa_trc(rport->fcs, ls_rjt->reason_code);
-		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
-		rport->stats.rpsc_rejects++;
-		if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
-			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
-		else
-			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
-	}
-}
diff --git a/drivers/scsi/bfa/scn.c b/drivers/scsi/bfa/scn.c
deleted file mode 100644
index 8a60129..0000000
--- a/drivers/scsi/bfa/scn.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_ms.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, SCN);
-
-#define FC_QOS_RSCN_EVENT		0x0c
-#define FC_FABRIC_NAME_RSCN_EVENT	0x0d
-
-/*
- * forward declarations
- */
-static void     bfa_fcs_port_scn_send_scr(void *scn_cbarg,
-					  struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_scn_scr_response(void *fcsarg,
-					      struct bfa_fcxp_s *fcxp,
-					      void *cbarg,
-					      bfa_status_t req_status,
-					      u32 rsp_len,
-					      u32 resid_len,
-					      struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port,
-					     struct fchs_s *rx_fchs);
-static void     bfa_fcs_port_scn_timeout(void *arg);
-
-/**
- *  fcs_scm_sm FCS SCN state machine
- */
-
-/**
- * VPort SCN State Machine events
- */
-enum port_scn_event {
-	SCNSM_EVENT_PORT_ONLINE = 1,
-	SCNSM_EVENT_PORT_OFFLINE = 2,
-	SCNSM_EVENT_RSP_OK = 3,
-	SCNSM_EVENT_RSP_ERROR = 4,
-	SCNSM_EVENT_TIMEOUT = 5,
-	SCNSM_EVENT_SCR_SENT = 6,
-};
-
-static void     bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn,
-					    enum port_scn_event event);
-static void     bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn,
-						enum port_scn_event event);
-static void     bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn,
-					enum port_scn_event event);
-static void     bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn,
-					      enum port_scn_event event);
-static void     bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn,
-					   enum port_scn_event event);
-
-/**
- * 		Starting state - awaiting link up.
- */
-static void
-bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn,
-			    enum port_scn_event event)
-{
-	switch (event) {
-	case SCNSM_EVENT_PORT_ONLINE:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr);
-		bfa_fcs_port_scn_send_scr(scn, NULL);
-		break;
-
-	case SCNSM_EVENT_PORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(scn->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn,
-				enum port_scn_event event)
-{
-	switch (event) {
-	case SCNSM_EVENT_SCR_SENT:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr);
-		break;
-
-	case SCNSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
-		bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(scn->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn,
-			enum port_scn_event event)
-{
-	struct bfa_fcs_port_s *port = scn->port;
-
-	switch (event) {
-	case SCNSM_EVENT_RSP_OK:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_online);
-		break;
-
-	case SCNSM_EVENT_RSP_ERROR:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr_retry);
-		bfa_timer_start(port->fcs->bfa, &scn->timer,
-				bfa_fcs_port_scn_timeout, scn,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case SCNSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
-		bfa_fcxp_discard(scn->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(scn->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn,
-			      enum port_scn_event event)
-{
-	switch (event) {
-	case SCNSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr);
-		bfa_fcs_port_scn_send_scr(scn, NULL);
-		break;
-
-	case SCNSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
-		bfa_timer_stop(&scn->timer);
-		break;
-
-	default:
-		bfa_sm_fault(scn->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn,
-			   enum port_scn_event event)
-{
-	switch (event) {
-	case SCNSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(scn->port->fcs, event);
-	}
-}
-
-
-
-/**
- *  fcs_scn_private FCS SCN private functions
- */
-
-/**
- * This routine will be called to send a SCR command.
- */
-static void
-bfa_fcs_port_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_scn_s *scn = scn_cbarg;
-	struct bfa_fcs_port_s *port = scn->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
-				    bfa_fcs_port_scn_send_scr, scn);
-		return;
-	}
-	scn->fcxp = fcxp;
-
-	/*
-	 * Handle VU registrations for Base port only
-	 */
-	if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
-		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-				   bfa_lps_is_brcd_fabric(port->fabric->lps),
-				   port->pid, 0);
-	} else {
-		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), BFA_FALSE,
-				   port->pid, 0);
-	}
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_scn_scr_response,
-		      (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
-
-	bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
-}
-
-static void
-bfa_fcs_port_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-			      void *cbarg, bfa_status_t req_status,
-			      u32 rsp_len, u32 resid_len,
-			      struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)cbarg;
-	struct bfa_fcs_port_s *port = scn->port;
-	struct fc_els_cmd_s   *els_cmd;
-	struct fc_ls_rjt_s    *ls_rjt;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-	switch (els_cmd->els_code) {
-
-	case FC_ELS_ACC:
-		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
-		break;
-
-	case FC_ELS_LS_RJT:
-
-		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-		bfa_trc(port->fcs, ls_rjt->reason_code);
-		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
-
-		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
-		break;
-
-	default:
-		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
-	}
-}
-
-/*
- * Send a LS Accept
- */
-static void
-bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port,
-			struct fchs_s *rx_fchs)
-{
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_rport_s *bfa_rport = NULL;
-	int             len;
-
-	bfa_trc(port->fcs, rx_fchs->s_id);
-
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp)
-		return;
-
-	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-			      bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
-
-	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
-		      BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
-		      FC_MAX_PDUSZ, 0);
-}
-
-/**
- *     This routine will be called by bfa_timer on timer timeouts.
- *
- * 	param[in] 	vport 			- pointer to bfa_fcs_port_t.
- * 	param[out]	vport_status 	- pointer to return vport status in
- *
- * 	return
- * 		void
- *
-*  	Special Considerations:
- *
- * 	note
- */
-static void
-bfa_fcs_port_scn_timeout(void *arg)
-{
-	struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)arg;
-
-	bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
-}
-
-
-
-/**
- *  fcs_scn_public FCS state change notification public interfaces
- */
-
-/*
- * Functions called by port/fab
- */
-void
-bfa_fcs_port_scn_init(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
-
-	scn->port = port;
-	bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
-}
-
-void
-bfa_fcs_port_scn_offline(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
-
-	scn->port = port;
-	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
-}
-
-void
-bfa_fcs_port_scn_online(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
-
-	scn->port = port;
-	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
-}
-
-static void
-bfa_fcs_port_scn_portid_rscn(struct bfa_fcs_port_s *port, u32 rpid)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	bfa_trc(port->fcs, rpid);
-
-	/**
-	 * If this is an unknown device, then it just came online.
-	 * Otherwise let rport handle the RSCN event.
-	 */
-	rport = bfa_fcs_port_get_rport_by_pid(port, rpid);
-	if (rport == NULL) {
-		/*
-		 * If min cfg mode is enabled, we donot need to
-		 * discover any new rports.
-		 */
-		if (!__fcs_min_cfg(port->fcs))
-			rport = bfa_fcs_rport_create(port, rpid);
-	} else {
-		bfa_fcs_rport_scn(rport);
-	}
-}
-
-/**
- * rscn format based PID comparison
- */
-#define __fc_pid_match(__c0, __c1, __fmt)		\
-	(((__fmt) == FC_RSCN_FORMAT_FABRIC) ||		\
-	 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) &&		\
-	  ((__c0)[0] == (__c1)[0])) ||			\
-	 (((__fmt) == FC_RSCN_FORMAT_AREA) &&		\
-	  ((__c0)[0] == (__c1)[0]) &&			\
-	  ((__c0)[1] == (__c1)[1])))
-
-static void
-bfa_fcs_port_scn_multiport_rscn(struct bfa_fcs_port_s *port,
-			enum fc_rscn_format format, u32 rscn_pid)
-{
-	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe, *qe_next;
-	u8        *c0, *c1;
-
-	bfa_trc(port->fcs, format);
-	bfa_trc(port->fcs, rscn_pid);
-
-	c0 = (u8 *) &rscn_pid;
-
-	list_for_each_safe(qe, qe_next, &port->rport_q) {
-		rport = (struct bfa_fcs_rport_s *)qe;
-		c1 = (u8 *) &rport->pid;
-		if (__fc_pid_match(c0, c1, format))
-			bfa_fcs_rport_scn(rport);
-	}
-}
-
-void
-bfa_fcs_port_scn_process_rscn(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
-			      u32 len)
-{
-	struct fc_rscn_pl_s   *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
-	int             num_entries;
-	u32        rscn_pid;
-	bfa_boolean_t   nsquery = BFA_FALSE;
-	int             i = 0;
-
-	num_entries =
-		(bfa_os_ntohs(rscn->payldlen) -
-		 sizeof(u32)) / sizeof(rscn->event[0]);
-
-	bfa_trc(port->fcs, num_entries);
-
-	port->stats.num_rscn++;
-
-	bfa_fcs_port_scn_send_ls_acc(port, fchs);
-
-	for (i = 0; i < num_entries; i++) {
-		rscn_pid = rscn->event[i].portid;
-
-		bfa_trc(port->fcs, rscn->event[i].format);
-		bfa_trc(port->fcs, rscn_pid);
-
-		switch (rscn->event[i].format) {
-		case FC_RSCN_FORMAT_PORTID:
-			if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
-				/*
-				 * Ignore this event. f/w would have processed
-				 * it
-				 */
-				bfa_trc(port->fcs, rscn_pid);
-			} else {
-				port->stats.num_portid_rscn++;
-				bfa_fcs_port_scn_portid_rscn(port, rscn_pid);
-			}
-			break;
-
-		case FC_RSCN_FORMAT_FABRIC:
-			if (rscn->event[i].qualifier ==
-			    FC_FABRIC_NAME_RSCN_EVENT) {
-				bfa_fcs_port_ms_fabric_rscn(port);
-				break;
-			}
-			/*
-			 * !!!!!!!!! Fall Through !!!!!!!!!!!!!
-			 */
-
-		case FC_RSCN_FORMAT_AREA:
-		case FC_RSCN_FORMAT_DOMAIN:
-			nsquery = BFA_TRUE;
-			bfa_fcs_port_scn_multiport_rscn(port,
-							rscn->event[i].format,
-							rscn_pid);
-			break;
-
-		default:
-			bfa_assert(0);
-			nsquery = BFA_TRUE;
-		}
-	}
-
-	/**
-	 * If any of area, domain or fabric RSCN is received, do a fresh discovery
-	 * to find new devices.
-	 */
-	if (nsquery)
-		bfa_fcs_port_ns_query(port);
-}
-
-
diff --git a/drivers/scsi/bfa/vfapi.c b/drivers/scsi/bfa/vfapi.c
deleted file mode 100644
index 391a479..0000000
--- a/drivers/scsi/bfa/vfapi.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  vfapi.c Fabric module implementation.
- */
-
-#include "fcs_fabric.h"
-#include "fcs_trcmod.h"
-
-BFA_TRC_FILE(FCS, VFAPI);
-
-/**
- *  fcs_vf_api virtual fabrics API
- */
-
-/**
- * 		Enable VF mode.
- *
- * @param[in]		fcs		fcs module instance
- * @param[in]		vf_id		default vf_id of port, FC_VF_ID_NULL
- * 					to use standard default vf_id of 1.
- *
- * @retval	BFA_STATUS_OK		vf mode is enabled
- * @retval	BFA_STATUS_BUSY		Port is active. Port must be disabled
- *					before VF mode can be enabled.
- */
-bfa_status_t
-bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id)
-{
-	return BFA_STATUS_OK;
-}
-
-/**
- * 		Disable VF mode.
- *
- * @param[in]		fcs		fcs module instance
- *
- * @retval	BFA_STATUS_OK		vf mode is disabled
- * @retval	BFA_STATUS_BUSY		VFs are present and being used. All
- * 					VFs must be deleted before disabling
- *					VF mode.
- */
-bfa_status_t
-bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs)
-{
-	return BFA_STATUS_OK;
-}
-
-/**
- * 		Create a new VF instance.
- *
- *  A new VF is created using the given VF configuration. A VF is identified
- *  by VF id. No duplicate VF creation is allowed with the same VF id. Once
- *  a VF is created, VF is automatically started after link initialization
- *  and EVFP exchange is completed.
- *
- * 	param[in] vf		- 	FCS vf data structure. Memory is
- *					allocated by caller (driver)
- * 	param[in] fcs 		- 	FCS module
- * 	param[in] vf_cfg	- 	VF configuration
- * 	param[in] vf_drv 	- 	Opaque handle back to the driver's
- *					virtual vf structure
- *
- * 	retval BFA_STATUS_OK VF creation is successful
- * 	retval BFA_STATUS_FAILED VF creation failed
- * 	retval BFA_STATUS_EEXIST A VF exists with the given vf_id
- */
-bfa_status_t
-bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs, u16 vf_id,
-		  struct bfa_port_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
-{
-	bfa_trc(fcs, vf_id);
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Use this function to delete a BFA VF object. VF object should
- * 		be stopped before this function call.
- *
- * 	param[in] vf - pointer to bfa_vf_t.
- *
- * 	retval BFA_STATUS_OK	On vf deletion success
- * 	retval BFA_STATUS_BUSY VF is not in a stopped state
- * 	retval BFA_STATUS_INPROGRESS VF deletion in in progress
- */
-bfa_status_t
-bfa_fcs_vf_delete(bfa_fcs_vf_t *vf)
-{
-	bfa_trc(vf->fcs, vf->vf_id);
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Start participation in VF. This triggers login to the virtual fabric.
- *
- * 	param[in] vf - pointer to bfa_vf_t.
- *
- * 	return None
- */
-void
-bfa_fcs_vf_start(bfa_fcs_vf_t *vf)
-{
-	bfa_trc(vf->fcs, vf->vf_id);
-}
-
-/**
- *  	Logout with the virtual fabric.
- *
- * 	param[in] vf - pointer to bfa_vf_t.
- *
- * 	retval BFA_STATUS_OK 	On success.
- * 	retval BFA_STATUS_INPROGRESS VF is being stopped.
- */
-bfa_status_t
-bfa_fcs_vf_stop(bfa_fcs_vf_t *vf)
-{
-	bfa_trc(vf->fcs, vf->vf_id);
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Returns attributes of the given VF.
- *
- * 	param[in] 	vf			pointer to bfa_vf_t.
- * 	param[out] vf_attr 	vf attributes returned
- *
- * 	return None
- */
-void
-bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr)
-{
-	bfa_trc(vf->fcs, vf->vf_id);
-}
-
-/**
- * 		Return statistics associated with the given vf.
- *
- * 	param[in] 	vf			pointer to bfa_vf_t.
- * 	param[out] vf_stats 	vf statistics returned
- *
- *  @return None
- */
-void
-bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf, struct bfa_vf_stats_s *vf_stats)
-{
-	bfa_os_memcpy(vf_stats, &vf->stats, sizeof(struct bfa_vf_stats_s));
-	return;
-}
-
-void
-/**
- * 		clear statistics associated with the given vf.
- *
- * 	param[in] 	vf			pointer to bfa_vf_t.
- *
- *  @return None
- */
-bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf)
-{
-	bfa_os_memset(&vf->stats, 0, sizeof(struct bfa_vf_stats_s));
-	return;
-}
-
-/**
- *  	Returns FCS vf structure for a given vf_id.
- *
- * 	param[in] 	vf_id		- VF_ID
- *
- * 	return
- * 		If lookup succeeds, retuns fcs vf object, otherwise returns NULL
- */
-bfa_fcs_vf_t   *
-bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
-{
-	bfa_trc(fcs, vf_id);
-	if (vf_id == FC_VF_ID_NULL)
-		return &fcs->fabric;
-
-	/**
-	 * @todo vf support
-	 */
-
-	return NULL;
-}
-
-/**
- *  	Returns driver VF structure for a given FCS vf.
- *
- * 	param[in] 	vf		- pointer to bfa_vf_t
- *
- * 	return Driver VF structure
- */
-struct bfad_vf_s      *
-bfa_fcs_vf_get_drv_vf(bfa_fcs_vf_t *vf)
-{
-	bfa_assert(vf);
-	bfa_trc(vf->fcs, vf->vf_id);
-	return vf->vf_drv;
-}
-
-/**
- *  	Return the list of VFs configured.
- *
- * 	param[in]	fcs	fcs module instance
- * 	param[out] 	vf_ids	returned list of vf_ids
- * 	param[in,out] 	nvfs	in:size of vf_ids array,
- * 				out:total elements present,
- * 				actual elements returned is limited by the size
- *
- * 	return Driver VF structure
- */
-void
-bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
-{
-	bfa_trc(fcs, *nvfs);
-}
-
-/**
- *  	Return the list of all VFs visible from fabric.
- *
- * 	param[in]	fcs	fcs module instance
- * 	param[out] 	vf_ids	returned list of vf_ids
- * 	param[in,out] 	nvfs	in:size of vf_ids array,
- *				out:total elements present,
- * 				actual elements returned is limited by the size
- *
- * 	return Driver VF structure
- */
-void
-bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
-{
-	bfa_trc(fcs, *nvfs);
-}
-
-/**
- * 		Return the list of local logical ports present in the given VF.
- *
- * 	param[in]	vf	vf for which logical ports are returned
- * 	param[out] 	lpwwn	returned logical port wwn list
- * 	param[in,out] 	nlports	in:size of lpwwn list;
- *				out:total elements present,
- * 				actual elements returned is limited by the size
- *
- */
-void
-bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
-{
-	struct list_head        *qe;
-	struct bfa_fcs_vport_s *vport;
-	int             i;
-	struct bfa_fcs_s      *fcs;
-
-	if (vf == NULL || lpwwn == NULL || *nlports == 0)
-		return;
-
-	fcs = vf->fcs;
-
-	bfa_trc(fcs, vf->vf_id);
-	bfa_trc(fcs, (u32) *nlports);
-
-	i = 0;
-	lpwwn[i++] = vf->bport.port_cfg.pwwn;
-
-	list_for_each(qe, &vf->vport_q) {
-		if (i >= *nlports)
-			break;
-
-		vport = (struct bfa_fcs_vport_s *) qe;
-		lpwwn[i++] = vport->lport.port_cfg.pwwn;
-	}
-
-	bfa_trc(fcs, i);
-	*nlports = i;
-	return;
-}
-
-
diff --git a/drivers/scsi/bfa/vport.c b/drivers/scsi/bfa/vport.c
deleted file mode 100644
index b378ec7..0000000
--- a/drivers/scsi/bfa/vport.c
+++ /dev/null
@@ -1,903 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/**
- *  bfa_fcs_vport.c FCS virtual port state machine
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <fcbuild.h>
-#include "fcs_fabric.h"
-#include "fcs_lport.h"
-#include "fcs_vport.h"
-#include "fcs_trcmod.h"
-#include "fcs.h"
-#include <aen/bfa_aen_lport.h>
-
-BFA_TRC_FILE(FCS, VPORT);
-
-#define __vport_fcs(__vp)       ((__vp)->lport.fcs)
-#define __vport_pwwn(__vp)      ((__vp)->lport.port_cfg.pwwn)
-#define __vport_nwwn(__vp)      ((__vp)->lport.port_cfg.nwwn)
-#define __vport_bfa(__vp)       ((__vp)->lport.fcs->bfa)
-#define __vport_fcid(__vp)      ((__vp)->lport.pid)
-#define __vport_fabric(__vp)    ((__vp)->lport.fabric)
-#define __vport_vfid(__vp)      ((__vp)->lport.fabric->vf_id)
-
-#define BFA_FCS_VPORT_MAX_RETRIES  5
-/*
- * Forward declarations
- */
-static void     bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
-static void     bfa_fcs_vport_timeout(void *vport_arg);
-static void     bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
-static void     bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
-
-/**
- *  fcs_vport_sm FCS virtual port state machine
- */
-
-/**
- * VPort State Machine events
- */
-enum bfa_fcs_vport_event {
-	BFA_FCS_VPORT_SM_CREATE = 1,	/*  vport create event */
-	BFA_FCS_VPORT_SM_DELETE = 2,	/*  vport delete event */
-	BFA_FCS_VPORT_SM_START = 3,	/*  vport start request */
-	BFA_FCS_VPORT_SM_STOP = 4,	/*  stop: unsupported */
-	BFA_FCS_VPORT_SM_ONLINE = 5,	/*  fabric online */
-	BFA_FCS_VPORT_SM_OFFLINE = 6,	/*  fabric offline event */
-	BFA_FCS_VPORT_SM_FRMSENT = 7,	/*  fdisc/logo sent events */
-	BFA_FCS_VPORT_SM_RSP_OK = 8,	/*  good response */
-	BFA_FCS_VPORT_SM_RSP_ERROR = 9,	/*  error/bad response */
-	BFA_FCS_VPORT_SM_TIMEOUT = 10,	/*  delay timer event */
-	BFA_FCS_VPORT_SM_DELCOMP = 11,	/*  lport delete completion */
-	BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,	/*  Dup wnn error */
-	BFA_FCS_VPORT_SM_RSP_FAILED = 13,	/*  non-retryable failure */
-};
-
-static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
-					enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
-					 enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
-					 enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
-				       enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
-					     enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
-					enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
-					  enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
-					 enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
-				      enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
-				       enum bfa_fcs_vport_event event);
-
-static struct bfa_sm_table_s vport_sm_table[] = {
-	{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
-	{BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
-	{BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
-	{BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
-	{BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
-	{BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
-	{BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
-	{BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
-	{BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
-	{BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
-};
-
-/**
- * Beginning state.
- */
-static void
-bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
-			enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_CREATE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
-		bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Created state - a start event is required to start up the state machine.
- */
-static void
-bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
-			 enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_START:
-		if (bfa_fcs_fabric_is_online(__vport_fabric(vport))
-		    && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
-			bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
-			bfa_fcs_vport_do_fdisc(vport);
-		} else {
-			/**
-			 * Fabric is offline or not NPIV capable, stay in
-			 * offline state.
-			 */
-			vport->vport_stats.fab_no_npiv++;
-			bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		}
-		break;
-
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_fcs_port_delete(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_ONLINE:
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		/**
-		 * Ignore ONLINE/OFFLINE events from fabric till vport is started.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Offline state - awaiting ONLINE event from fabric SM.
- */
-static void
-bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
-			 enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_fcs_port_delete(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_ONLINE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
-		vport->fdisc_retries = 0;
-		bfa_fcs_vport_do_fdisc(vport);
-		break;
-
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		/*
-		 * This can happen if the vport couldn't be initialzied due
-		 * the fact that the npiv was not enabled on the switch. In
-		 * that case we will put the vport in offline state. However,
-		 * the link can go down and cause the this event to be sent when
-		 * we are already offline. Ignore it.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * FDISC is sent and awaiting reply from fabric.
- */
-static void
-bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
-		       enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_lps_discard(vport->lps);
-		bfa_fcs_port_delete(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		bfa_lps_discard(vport->lps);
-		break;
-
-	case BFA_FCS_VPORT_SM_RSP_OK:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
-		bfa_fcs_port_online(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_RSP_ERROR:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
-		bfa_timer_start(__vport_bfa(vport), &vport->timer,
-				bfa_fcs_vport_timeout, vport,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case BFA_FCS_VPORT_SM_RSP_FAILED:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		break;
-
-	case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * FDISC attempt failed - a timer is active to retry FDISC.
- */
-static void
-bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
-			     enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_timer_stop(&vport->timer);
-		bfa_fcs_port_delete(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		bfa_timer_stop(&vport->timer);
-		break;
-
-	case BFA_FCS_VPORT_SM_TIMEOUT:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
-		vport->vport_stats.fdisc_retries++;
-		vport->fdisc_retries++;
-		bfa_fcs_vport_do_fdisc(vport);
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Vport is online (FDISC is complete).
- */
-static void
-bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
-			enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
-		bfa_fcs_port_delete(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		bfa_lps_discard(vport->lps);
-		bfa_fcs_port_offline(&vport->lport);
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Vport is being deleted - awaiting lport delete completion to send
- * LOGO to fabric.
- */
-static void
-bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
-			  enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		break;
-
-	case BFA_FCS_VPORT_SM_DELCOMP:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
-		bfa_fcs_vport_do_logo(vport);
-		break;
-
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Error State.
- * This state will be set when the Vport Creation fails due to errors like
- * Dup WWN. In this state only operation allowed is a Vport Delete.
- */
-static void
-bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
-		       enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_fcs_port_delete(&vport->lport);
-
-		break;
-
-	default:
-		bfa_trc(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Lport cleanup is in progress since vport is being deleted. Fabric is
- * offline, so no LOGO is needed to complete vport deletion.
- */
-static void
-bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
-			 enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELCOMP:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
-		bfa_fcs_vport_free(vport);
-		break;
-
-	case BFA_FCS_VPORT_SM_DELETE:
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
- * is done.
- */
-static void
-bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
-		      enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		bfa_lps_discard(vport->lps);
-		/*
-		 * !!! fall through !!!
-		 */
-
-	case BFA_FCS_VPORT_SM_RSP_OK:
-	case BFA_FCS_VPORT_SM_RSP_ERROR:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
-		bfa_fcs_vport_free(vport);
-		break;
-
-	case BFA_FCS_VPORT_SM_DELETE:
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-
-
-/**
- *  fcs_vport_private FCS virtual port private functions
- */
-
-/**
- * Send AEN notification
- */
-static void
-bfa_fcs_vport_aen_post(bfa_fcs_lport_t *port, enum bfa_lport_aen_event event)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = port->fcs->logm;
-	enum bfa_port_role role = port->port_cfg.roles;
-	wwn_t           lpwwn = bfa_fcs_port_get_pwwn(port);
-	char            lpwwn_ptr[BFA_STRING_32];
-	char           *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] =
-		{ "Initiator", "Target", "IPFC" };
-
-	wwn2str(lpwwn_ptr, lpwwn);
-
-	bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX);
-
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, event), lpwwn_ptr,
-			role_str[role/2]);
-
-	aen_data.lport.vf_id = port->fabric->vf_id;
-	aen_data.lport.roles = role;
-	aen_data.lport.ppwwn =
-		bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
-	aen_data.lport.lpwwn = lpwwn;
-}
-
-/**
- * This routine will be called to send a FDISC command.
- */
-static void
-bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
-{
-	bfa_lps_fdisc(vport->lps, vport,
-		      bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
-		      __vport_pwwn(vport), __vport_nwwn(vport));
-	vport->vport_stats.fdisc_sent++;
-}
-
-static void
-bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
-{
-	u8         lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps);
-	u8         lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps);
-
-	bfa_trc(__vport_fcs(vport), lsrjt_rsn);
-	bfa_trc(__vport_fcs(vport), lsrjt_expl);
-
-	/*
-	 * For certain reason codes, we don't want to retry.
-	 */
-	switch (bfa_lps_get_lsrjt_expl(vport->lps)) {
-	case FC_LS_RJT_EXP_INV_PORT_NAME:	/* by brocade */
-	case FC_LS_RJT_EXP_INVALID_NPORT_ID:	/* by Cisco */
-		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
-			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-		else {
-			bfa_fcs_vport_aen_post(&vport->lport,
-					       BFA_LPORT_AEN_NPIV_DUP_WWN);
-			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
-		}
-		break;
-
-	case FC_LS_RJT_EXP_INSUFF_RES:
-		/*
-		 * This means max logins per port/switch setting on the
-		 * switch was exceeded.
-		 */
-		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
-			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-		else {
-			bfa_fcs_vport_aen_post(&vport->lport,
-					       BFA_LPORT_AEN_NPIV_FABRIC_MAX);
-			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
-		}
-		break;
-
-	default:
-		if (vport->fdisc_retries == 0)	/* Print only once */
-			bfa_fcs_vport_aen_post(&vport->lport,
-					       BFA_LPORT_AEN_NPIV_UNKNOWN);
-		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-	}
-}
-
-/**
- * 	Called to send a logout to the fabric. Used when a V-Port is
- * 	deleted/stopped.
- */
-static void
-bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-
-	vport->vport_stats.logo_sent++;
-	bfa_lps_fdisclogo(vport->lps);
-}
-
-/**
- *     This routine will be called by bfa_timer on timer timeouts.
- *
- * 	param[in] 	vport 		- pointer to bfa_fcs_vport_t.
- * 	param[out]	vport_status 	- pointer to return vport status in
- *
- * 	return
- * 		void
- *
-* 	Special Considerations:
- *
- * 	note
- */
-static void
-bfa_fcs_vport_timeout(void *vport_arg)
-{
-	struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *)vport_arg;
-
-	vport->vport_stats.fdisc_timeouts++;
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
-}
-
-static void
-bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
-{
-	bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
-	bfa_fcb_vport_delete(vport->vport_drv);
-	bfa_lps_delete(vport->lps);
-}
-
-
-
-/**
- *  fcs_vport_public FCS virtual port public interfaces
- */
-
-/**
- * Online notification from fabric SM.
- */
-void
-bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
-{
-	vport->vport_stats.fab_online++;
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
-}
-
-/**
- * Offline notification from fabric SM.
- */
-void
-bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
-{
-	vport->vport_stats.fab_offline++;
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
-}
-
-/**
- * Cleanup notification from fabric SM on link timer expiry.
- */
-void
-bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
-{
-	vport->vport_stats.fab_cleanup++;
-}
-
-/**
- * delete notification from fabric SM. To be invoked from within FCS.
- */
-void
-bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
-{
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
-}
-
-/**
- * Delete completion callback from associated lport
- */
-void
-bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
-{
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
-}
-
-/**
- *  fcs_vport_api Virtual port API
- */
-
-/**
- *  	Use this function to instantiate a new FCS vport object. This
- * 	function will not trigger any HW initialization process (which will be
- * 	done in vport_start() call)
- *
- * 	param[in] vport	- 	pointer to bfa_fcs_vport_t. This space
- * 					needs to be allocated by the driver.
- * 	param[in] fcs 		- 	FCS instance
- * 	param[in] vport_cfg	- 	vport configuration
- * 	param[in] vf_id    	- 	VF_ID if vport is created within a VF.
- *                          		FC_VF_ID_NULL to specify base fabric.
- * 	param[in] vport_drv 	- 	Opaque handle back to the driver's vport
- * 					structure
- *
- * 	retval BFA_STATUS_OK - on success.
- * 	retval BFA_STATUS_FAILED - on failure.
- */
-bfa_status_t
-bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
-		     u16 vf_id, struct bfa_port_cfg_s *vport_cfg,
-		     struct bfad_vport_s *vport_drv)
-{
-	if (vport_cfg->pwwn == 0)
-		return BFA_STATUS_INVALID_WWN;
-
-	if (bfa_fcs_port_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
-		return BFA_STATUS_VPORT_WWN_BP;
-
-	if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
-		return BFA_STATUS_VPORT_EXISTS;
-
-	if (bfa_fcs_fabric_vport_count(&fcs->fabric) ==
-		bfa_lps_get_max_vport(fcs->bfa))
-		return BFA_STATUS_VPORT_MAX;
-
-	vport->lps = bfa_lps_alloc(fcs->bfa);
-	if (!vport->lps)
-		return BFA_STATUS_VPORT_MAX;
-
-	vport->vport_drv = vport_drv;
-	vport_cfg->preboot_vp = BFA_FALSE;
-	bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
-
-	bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
-	bfa_fcs_lport_init(&vport->lport, vport_cfg);
-
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *      Use this function to instantiate a new FCS PBC vport object. This
- *      function will not trigger any HW initialization process (which will be
- *      done in vport_start() call)
- *
- *      param[in] vport        -       pointer to bfa_fcs_vport_t. This space
- *                                      needs to be allocated by the driver.
- *      param[in] fcs          -       FCS instance
- *      param[in] vport_cfg    -       vport configuration
- *      param[in] vf_id        -       VF_ID if vport is created within a VF.
- *                                      FC_VF_ID_NULL to specify base fabric.
- *      param[in] vport_drv    -       Opaque handle back to the driver's vport
- *                                      structure
- *
- *      retval BFA_STATUS_OK - on success.
- *      retval BFA_STATUS_FAILED - on failure.
- */
-bfa_status_t
-bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
-			uint16_t vf_id, struct bfa_port_cfg_s *vport_cfg,
-			struct bfad_vport_s *vport_drv)
-{
-	bfa_status_t rc;
-
-	rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
-	vport->lport.port_cfg.preboot_vp = BFA_TRUE;
-
-	return rc;
-}
-
-/**
- *  	Use this function initialize the vport.
- *
- *  @param[in] vport - pointer to bfa_fcs_vport_t.
- *
- *  @returns None
- */
-bfa_status_t
-bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
-{
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Use this function quiese the vport object. This function will return
- * 	immediately, when the vport is actually stopped, the
- * 	bfa_drv_vport_stop_cb() will be called.
- *
- * 	param[in] vport - pointer to bfa_fcs_vport_t.
- *
- * 	return None
- */
-bfa_status_t
-bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
-{
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Use this function to delete a vport object. Fabric object should
- * 		be stopped before this function call.
- *
- *	Donot invoke this from within FCS
- *
- * 	param[in] vport - pointer to bfa_fcs_vport_t.
- *
- * 	return     None
- */
-bfa_status_t
-bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
-{
-	if (vport->lport.port_cfg.preboot_vp)
-		return BFA_STATUS_PBC;
-
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Use this function to get vport's current status info.
- *
- * 	param[in] 	vport 		pointer to bfa_fcs_vport_t.
- * 	param[out]	attr 		pointer to return vport attributes
- *
- * 	return None
- */
-void
-bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
-		       struct bfa_vport_attr_s *attr)
-{
-	if (vport == NULL || attr == NULL)
-		return;
-
-	bfa_os_memset(attr, 0, sizeof(struct bfa_vport_attr_s));
-
-	bfa_fcs_port_get_attr(&vport->lport, &attr->port_attr);
-	attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
-}
-
-/**
- *  	Use this function to get vport's statistics.
- *
- * 	param[in] 	vport 		pointer to bfa_fcs_vport_t.
- * 	param[out]	stats		pointer to return vport statistics in
- *
- * 	return None
- */
-void
-bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
-			struct bfa_vport_stats_s *stats)
-{
-	*stats = vport->vport_stats;
-}
-
-/**
- *  	Use this function to clear vport's statistics.
- *
- * 	param[in] 	vport 		pointer to bfa_fcs_vport_t.
- *
- * 	return None
- */
-void
-bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport)
-{
-	bfa_os_memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
-}
-
-/**
- *      Lookup a virtual port. Excludes base port from lookup.
- */
-struct bfa_fcs_vport_s *
-bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
-{
-	struct bfa_fcs_vport_s *vport;
-	struct bfa_fcs_fabric_s *fabric;
-
-	bfa_trc(fcs, vf_id);
-	bfa_trc(fcs, vpwwn);
-
-	fabric = bfa_fcs_vf_lookup(fcs, vf_id);
-	if (!fabric) {
-		bfa_trc(fcs, vf_id);
-		return NULL;
-	}
-
-	vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
-	return vport;
-}
-
-/**
- * FDISC Response
- */
-void
-bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
-{
-	struct bfa_fcs_vport_s *vport = uarg;
-
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), status);
-
-	switch (status) {
-	case BFA_STATUS_OK:
-		/*
-		 * Initialize the V-Port fields
-		 */
-		__vport_fcid(vport) = bfa_lps_get_pid(vport->lps);
-		vport->vport_stats.fdisc_accepts++;
-		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
-		break;
-
-	case BFA_STATUS_INVALID_MAC:
-		/*
-		 * Only for CNA
-		 */
-		vport->vport_stats.fdisc_acc_bad++;
-		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-
-		break;
-
-	case BFA_STATUS_EPROTOCOL:
-		switch (bfa_lps_get_extstatus(vport->lps)) {
-		case BFA_EPROTO_BAD_ACCEPT:
-			vport->vport_stats.fdisc_acc_bad++;
-			break;
-
-		case BFA_EPROTO_UNKNOWN_RSP:
-			vport->vport_stats.fdisc_unknown_rsp++;
-			break;
-
-		default:
-			break;
-		}
-
-		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-		break;
-
-	case BFA_STATUS_FABRIC_RJT:
-		vport->vport_stats.fdisc_rejects++;
-		bfa_fcs_vport_fdisc_rejected(vport);
-		break;
-
-	default:
-		vport->vport_stats.fdisc_rsp_err++;
-		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-	}
-}
-
-/**
- * LOGO response
- */
-void
-bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
-{
-	struct bfa_fcs_vport_s *vport = uarg;
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
-}
-
-/**
- * Received clear virtual link
- */
-void
-bfa_cb_lps_cvl_event(void *bfad, void *uarg)
-{
-	struct bfa_fcs_vport_s *vport = uarg;
-
-	/* Send an Offline followed by an ONLINE */
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
-}
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 2fceb19..1b6f86b 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -120,6 +120,8 @@
 /* additional LOM specific iSCSI license not installed */
 #define ISCSI_KCQE_COMPLETION_STATUS_LOM_ISCSI_NOT_ENABLED              (0x51)
 
+#define ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY				(0x80)
+
 /* SQ/RQ/CQ DB structure sizes */
 #define ISCSI_SQ_DB_SIZE    (16)
 #define ISCSI_RQ_DB_SIZE    (16)
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 00c0335..a44b1b3 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -58,6 +58,8 @@
 #define MAX_PAGES_PER_CTRL_STRUCT_POOL	8
 #define BNX2I_RESERVED_SLOW_PATH_CMD_SLOTS	4
 
+#define BNX2I_5771X_DBELL_PAGE_SIZE	128
+
 /* 5706/08 hardware has limit on maximum buffer size per BD it can handle */
 #define MAX_BD_LENGTH			65535
 #define BD_SPLIT_SIZE			32768
@@ -753,7 +755,7 @@
 extern int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *conn,
 				    struct bnx2i_cmd *cmnd);
 extern int bnx2i_send_iscsi_nopout(struct bnx2i_conn *conn,
-				   struct iscsi_task *mtask, u32 ttt,
+				   struct iscsi_task *mtask,
 				   char *datap, int data_len, int unsol);
 extern int bnx2i_send_iscsi_logout(struct bnx2i_conn *conn,
 				   struct iscsi_task *mtask);
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index d23fc25..8d9dbb3 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -385,7 +385,6 @@
 	struct bnx2i_cmd *bnx2i_cmd;
 	struct bnx2i_tmf_request *tmfabort_wqe;
 	u32 dword;
-	u32 scsi_lun[2];
 
 	bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data;
 	tmfabort_hdr = (struct iscsi_tm *)mtask->hdr;
@@ -393,38 +392,41 @@
 						bnx2i_conn->ep->qp.sq_prod_qe;
 
 	tmfabort_wqe->op_code = tmfabort_hdr->opcode;
-	tmfabort_wqe->op_attr = 0;
-	tmfabort_wqe->op_attr =
-		ISCSI_TMF_REQUEST_ALWAYS_ONE | ISCSI_TM_FUNC_ABORT_TASK;
+	tmfabort_wqe->op_attr = tmfabort_hdr->flags;
 
 	tmfabort_wqe->itt = (mtask->itt | (ISCSI_TASK_TYPE_MPATH << 14));
 	tmfabort_wqe->reserved2 = 0;
 	tmfabort_wqe->cmd_sn = be32_to_cpu(tmfabort_hdr->cmdsn);
 
-	ctask = iscsi_itt_to_task(conn, tmfabort_hdr->rtt);
-	if (!ctask || !ctask->sc)
-		/*
-		 * the iscsi layer must have completed the cmd while this
-		 * was starting up.
-		 *
-		 * Note: In the case of a SCSI cmd timeout, the task's sc
-		 *       is still active; hence ctask->sc != 0
-		 *       In this case, the task must be aborted
-		 */
-		return 0;
+	switch (tmfabort_hdr->flags & ISCSI_FLAG_TM_FUNC_MASK) {
+	case ISCSI_TM_FUNC_ABORT_TASK:
+	case ISCSI_TM_FUNC_TASK_REASSIGN:
+		ctask = iscsi_itt_to_task(conn, tmfabort_hdr->rtt);
+		if (!ctask || !ctask->sc)
+			/*
+			 * the iscsi layer must have completed the cmd while
+			 * was starting up.
+			 *
+			 * Note: In the case of a SCSI cmd timeout, the task's
+			 *       sc is still active; hence ctask->sc != 0
+			 *       In this case, the task must be aborted
+			 */
+			return 0;
 
-	ref_sc = ctask->sc;
-
-	/* Retrieve LUN directly from the ref_sc */
-	int_to_scsilun(ref_sc->device->lun, (struct scsi_lun *) scsi_lun);
-	tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]);
-	tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]);
-
-	if (ref_sc->sc_data_direction == DMA_TO_DEVICE)
-		dword = (ISCSI_TASK_TYPE_WRITE << ISCSI_CMD_REQUEST_TYPE_SHIFT);
-	else
-		dword = (ISCSI_TASK_TYPE_READ << ISCSI_CMD_REQUEST_TYPE_SHIFT);
-	tmfabort_wqe->ref_itt = (dword | (tmfabort_hdr->rtt & ISCSI_ITT_MASK));
+		ref_sc = ctask->sc;
+		if (ref_sc->sc_data_direction == DMA_TO_DEVICE)
+			dword = (ISCSI_TASK_TYPE_WRITE <<
+				 ISCSI_CMD_REQUEST_TYPE_SHIFT);
+		else
+			dword = (ISCSI_TASK_TYPE_READ <<
+				 ISCSI_CMD_REQUEST_TYPE_SHIFT);
+		tmfabort_wqe->ref_itt = (dword |
+					(tmfabort_hdr->rtt & ISCSI_ITT_MASK));
+		break;
+	default:
+		tmfabort_wqe->ref_itt = RESERVED_ITT;
+	}
+	memcpy(tmfabort_wqe->lun, tmfabort_hdr->lun, sizeof(struct scsi_lun));
 	tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn);
 
 	tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma;
@@ -464,7 +466,6 @@
  * @conn:		iscsi connection
  * @cmd:		driver command structure which is requesting
  *			a WQE to sent to chip for further processing
- * @ttt:		TTT to be used when building pdu header
  * @datap:		payload buffer pointer
  * @data_len:		payload data length
  * @unsol:		indicated whether nopout pdu is unsolicited pdu or
@@ -473,7 +474,7 @@
  * prepare and post a nopout request WQE to CNIC firmware
  */
 int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
-			    struct iscsi_task *task, u32 ttt,
+			    struct iscsi_task *task,
 			    char *datap, int data_len, int unsol)
 {
 	struct bnx2i_endpoint *ep = bnx2i_conn->ep;
@@ -498,7 +499,7 @@
 	nopout_wqe->itt = ((u16)task->itt |
 			   (ISCSI_TASK_TYPE_MPATH <<
 			    ISCSI_TMF_REQUEST_TYPE_SHIFT));
-	nopout_wqe->ttt = ttt;
+	nopout_wqe->ttt = nopout_hdr->ttt;
 	nopout_wqe->flags = 0;
 	if (!unsol)
 		nopout_wqe->flags = ISCSI_NOP_OUT_REQUEST_LOCAL_COMPLETION;
@@ -2405,7 +2406,8 @@
 	if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
 		reg_base = pci_resource_start(ep->hba->pcidev,
 					      BNX2X_DOORBELL_PCI_BAR);
-		reg_off = PAGE_SIZE * (cid_num & 0x1FFFF) + DPM_TRIGER_TYPE;
+		reg_off = BNX2I_5771X_DBELL_PAGE_SIZE * (cid_num & 0x1FFFF) +
+			  DPM_TRIGER_TYPE;
 		ep->qp.ctx_base = ioremap_nocache(reg_base + reg_off, 4);
 		goto arm_cq;
 	}
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index a796f56..50c2aa3b 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -17,15 +17,17 @@
 static u32 adapter_count;
 
 #define DRV_MODULE_NAME		"bnx2i"
-#define DRV_MODULE_VERSION	"2.1.2"
-#define DRV_MODULE_RELDATE	"Jun 28, 2010"
+#define DRV_MODULE_VERSION	"2.1.3"
+#define DRV_MODULE_RELDATE	"Aug 10, 2010"
 
 static char version[] __devinitdata =
 		"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
 		" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 
-MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com>");
+MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and "
+	      "Eddie Wai <eddie.wai@broadcom.com>");
+
 MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711"
 		   " iSCSI Driver");
 MODULE_LICENSE("GPL");
@@ -167,6 +169,38 @@
 
 
 /**
+ * bnx2i_chip_cleanup - local routine to handle chip cleanup
+ * @hba:	Adapter instance to register
+ *
+ * Driver checks if adapter still has any active connections before
+ *	executing the cleanup process
+ */
+static void bnx2i_chip_cleanup(struct bnx2i_hba *hba)
+{
+	struct bnx2i_endpoint *bnx2i_ep;
+	struct list_head *pos, *tmp;
+
+	if (hba->ofld_conns_active) {
+		/* Stage to force the disconnection
+		 * This is the case where the daemon is either slow or
+		 * not present
+		 */
+		printk(KERN_ALERT "bnx2i: (%s) chip cleanup for %d active "
+			"connections\n", hba->netdev->name,
+			hba->ofld_conns_active);
+		mutex_lock(&hba->net_dev_lock);
+		list_for_each_safe(pos, tmp, &hba->ep_active_list) {
+			bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link);
+			/* Clean up the chip only */
+			bnx2i_hw_ep_disconnect(bnx2i_ep);
+			bnx2i_ep->cm_sk = NULL;
+		}
+		mutex_unlock(&hba->net_dev_lock);
+	}
+}
+
+
+/**
  * bnx2i_stop - cnic callback to shutdown adapter instance
  * @handle:	transparent handle pointing to adapter structure
  *
@@ -176,8 +210,6 @@
 void bnx2i_stop(void *handle)
 {
 	struct bnx2i_hba *hba = handle;
-	struct list_head *pos, *tmp;
-	struct bnx2i_endpoint *bnx2i_ep;
 	int conns_active;
 
 	/* check if cleanup happened in GOING_DOWN context */
@@ -198,24 +230,7 @@
 		if (hba->ofld_conns_active == conns_active)
 			break;
 	}
-	if (hba->ofld_conns_active) {
-		/* Stage to force the disconnection
-		 * This is the case where the daemon is either slow or
-		 * not present
-		 */
-		printk(KERN_ALERT "bnx2i: Wait timeout, force all eps "
-			"to disconnect (%d)\n", hba->ofld_conns_active);
-		mutex_lock(&hba->net_dev_lock);
-		list_for_each_safe(pos, tmp, &hba->ep_active_list) {
-			bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link);
-			/* Clean up the chip only */
-			bnx2i_hw_ep_disconnect(bnx2i_ep);
-		}
-		mutex_unlock(&hba->net_dev_lock);
-		if (hba->ofld_conns_active)
-			printk(KERN_ERR "bnx2i: EP disconnect timeout (%d)!\n",
-				hba->ofld_conns_active);
-	}
+	bnx2i_chip_cleanup(hba);
 
 	/* This flag should be cleared last so that ep_disconnect() gracefully
 	 * cleans up connection context
@@ -457,6 +472,7 @@
 		adapter_count--;
 
 		if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
+			bnx2i_chip_cleanup(hba);
 			hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
 			clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
 		}
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index a46ccc3..fb50efb 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1078,11 +1078,9 @@
 		buf = bnx2i_conn->gen_pdu.req_buf;
 		if (data_len)
 			rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task,
-						     RESERVED_ITT,
 						     buf, data_len, 1);
 		else
 			rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task,
-						     RESERVED_ITT,
 						     NULL, 0, 1);
 		break;
 	case ISCSI_OP_LOGOUT:
@@ -1955,6 +1953,9 @@
 	if (!cnic)
 		return 0;
 
+	if (bnx2i_ep->state == EP_STATE_IDLE)
+		return 0;
+
 	if (!bnx2i_ep_tcp_conn_active(bnx2i_ep))
 		goto destroy_conn;
 
@@ -1998,11 +1999,13 @@
 	else
 		close_ret = cnic->cm_abort(bnx2i_ep->cm_sk);
 
+	/* No longer allow CFC delete if cm_close/abort fails the request */
 	if (close_ret)
-		bnx2i_ep->state = EP_STATE_DISCONN_COMPL;
-
-	/* wait for option-2 conn teardown */
-	wait_event_interruptible(bnx2i_ep->ofld_wait,
+		printk(KERN_ALERT "bnx2i: %s close/abort(%d) returned %d\n",
+			bnx2i_ep->hba->netdev->name, close, close_ret);
+	else
+		/* wait for option-2 conn teardown */
+		wait_event_interruptible(bnx2i_ep->ofld_wait,
 				 bnx2i_ep->state != EP_STATE_DISCONN_START);
 
 	if (signal_pending(current))
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index d653218..a15474e 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -22,7 +22,6 @@
 #include <linux/chio.h>			/* here are all the ioctls */
 #include <linux/mutex.h>
 #include <linux/idr.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 
 #include <scsi/scsi.h>
@@ -44,6 +43,7 @@
 MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR);
 MODULE_ALIAS_SCSI_DEVICE(TYPE_MEDIUM_CHANGER);
 
+static DEFINE_MUTEX(ch_mutex);
 static int init = 1;
 module_param(init, int, 0444);
 MODULE_PARM_DESC(init, \
@@ -581,19 +581,19 @@
 	scsi_changer *ch;
 	int minor = iminor(inode);
 
-	lock_kernel();
+	mutex_lock(&ch_mutex);
 	spin_lock(&ch_index_lock);
 	ch = idr_find(&ch_index_idr, minor);
 
 	if (NULL == ch || scsi_device_get(ch->device)) {
 		spin_unlock(&ch_index_lock);
-		unlock_kernel();
+		mutex_unlock(&ch_mutex);
 		return -ENXIO;
 	}
 	spin_unlock(&ch_index_lock);
 
 	file->private_data = ch;
-	unlock_kernel();
+	mutex_unlock(&ch_mutex);
 	return 0;
 }
 
@@ -981,6 +981,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= ch_ioctl_compat,
 #endif
+	.llseek		= noop_llseek,
 };
 
 static int __init init_ch_module(void)
diff --git a/drivers/scsi/cxgb3i/Kbuild b/drivers/scsi/cxgb3i/Kbuild
deleted file mode 100644
index 70d060b..0000000
--- a/drivers/scsi/cxgb3i/Kbuild
+++ /dev/null
@@ -1,4 +0,0 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3
-
-cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o
-obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
diff --git a/drivers/scsi/cxgb3i/Kconfig b/drivers/scsi/cxgb3i/Kconfig
deleted file mode 100644
index bfdcaf5..0000000
--- a/drivers/scsi/cxgb3i/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-config SCSI_CXGB3_ISCSI
-	tristate "Chelsio S3xx iSCSI support"
-	depends on CHELSIO_T3_DEPENDS
-	select CHELSIO_T3
-	select SCSI_ISCSI_ATTRS
-	---help---
-	This driver supports iSCSI offload for the Chelsio S3 series devices.
diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h
deleted file mode 100644
index e3133b5..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * cxgb3i.h: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef __CXGB3I_H__
-#define __CXGB3I_H__
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/netdevice.h>
-#include <linux/scatterlist.h>
-#include <linux/skbuff.h>
-#include <scsi/libiscsi_tcp.h>
-
-/* from cxgb3 LLD */
-#include "common.h"
-#include "t3_cpl.h"
-#include "t3cdev.h"
-#include "cxgb3_ctl_defs.h"
-#include "cxgb3_offload.h"
-#include "firmware_exports.h"
-
-#include "cxgb3i_offload.h"
-#include "cxgb3i_ddp.h"
-
-#define CXGB3I_SCSI_HOST_QDEPTH 1024
-#define CXGB3I_MAX_TARGET	CXGB3I_MAX_CONN
-#define CXGB3I_MAX_LUN		512
-#define ISCSI_PDU_NONPAYLOAD_MAX \
-	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + 2*ISCSI_DIGEST_SIZE)
-
-struct cxgb3i_adapter;
-struct cxgb3i_hba;
-struct cxgb3i_endpoint;
-
-/**
- * struct cxgb3i_hba - cxgb3i iscsi structure (per port)
- *
- * @snic:	cxgb3i adapter containing this port
- * @ndev:	pointer to netdev structure
- * @shost:	pointer to scsi host structure
- */
-struct cxgb3i_hba {
-	struct cxgb3i_adapter *snic;
-	struct net_device *ndev;
-	struct Scsi_Host *shost;
-};
-
-/**
- * struct cxgb3i_adapter - cxgb3i adapter structure (per pci)
- *
- * @listhead:	list head to link elements
- * @lock:	lock for this structure
- * @tdev:	pointer to t3cdev used by cxgb3 driver
- * @pdev:	pointer to pci dev
- * @hba_cnt:	# of hbas (the same as # of ports)
- * @hba:	all the hbas on this adapter
- * @flags:	bit flag for adapter event/status
- * @tx_max_size: max. tx packet size supported
- * @rx_max_size: max. rx packet size supported
- * @tag_format: ddp tag format settings
- */
-#define CXGB3I_ADAPTER_FLAG_RESET	0x1
-struct cxgb3i_adapter {
-	struct list_head list_head;
-	spinlock_t lock;
-	struct t3cdev *tdev;
-	struct pci_dev *pdev;
-	unsigned char hba_cnt;
-	struct cxgb3i_hba *hba[MAX_NPORTS];
-
-	unsigned int flags;
-	unsigned int tx_max_size;
-	unsigned int rx_max_size;
-
-	struct cxgb3i_tag_format tag_format;
-};
-
-/**
- * struct cxgb3i_conn - cxgb3i iscsi connection
- *
- * @listhead:	list head to link elements
- * @cep:	pointer to iscsi_endpoint structure
- * @conn:	pointer to iscsi_conn structure
- * @hba:	pointer to the hba this conn. is going through
- * @task_idx_bits: # of bits needed for session->cmds_max
- */
-struct cxgb3i_conn {
-	struct list_head list_head;
-	struct cxgb3i_endpoint *cep;
-	struct iscsi_conn *conn;
-	struct cxgb3i_hba *hba;
-	unsigned int task_idx_bits;
-};
-
-/**
- * struct cxgb3i_endpoint - iscsi tcp endpoint
- *
- * @c3cn:	the h/w tcp connection representation
- * @hba:	pointer to the hba this conn. is going through
- * @cconn:	pointer to the associated cxgb3i iscsi connection
- */
-struct cxgb3i_endpoint {
-	struct s3_conn *c3cn;
-	struct cxgb3i_hba *hba;
-	struct cxgb3i_conn *cconn;
-};
-
-/**
- * struct cxgb3i_task_data - private iscsi task data
- *
- * @nr_frags:	# of coalesced page frags (from scsi sgl)
- * @frags:	coalesced page frags (from scsi sgl)
- * @skb:	tx pdu skb
- * @offset:	data offset for the next pdu
- * @count:	max. possible pdu payload
- * @sgoffset:	offset to the first sg entry for a given offset
- */
-#define MAX_PDU_FRAGS	((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
-struct cxgb3i_task_data {
-	unsigned short nr_frags;
-	skb_frag_t frags[MAX_PDU_FRAGS];
-	struct sk_buff *skb;
-	unsigned int offset;
-	unsigned int count;
-	unsigned int sgoffset;
-};
-
-int cxgb3i_iscsi_init(void);
-void cxgb3i_iscsi_cleanup(void);
-
-struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *);
-void cxgb3i_adapter_open(struct t3cdev *);
-void cxgb3i_adapter_close(struct t3cdev *);
-
-struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *,
-				       struct net_device *);
-void cxgb3i_hba_host_remove(struct cxgb3i_hba *);
-
-int cxgb3i_pdu_init(void);
-void cxgb3i_pdu_cleanup(void);
-void cxgb3i_conn_cleanup_task(struct iscsi_task *);
-int cxgb3i_conn_alloc_pdu(struct iscsi_task *, u8);
-int cxgb3i_conn_init_pdu(struct iscsi_task *, unsigned int, unsigned int);
-int cxgb3i_conn_xmit_pdu(struct iscsi_task *);
-
-void cxgb3i_release_itt(struct iscsi_task *task, itt_t hdr_itt);
-int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt);
-
-#endif
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
deleted file mode 100644
index be0e230..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- * cxgb3i_ddp.c: Chelsio S3xx iSCSI DDP Manager.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/scatterlist.h>
-
-/* from cxgb3 LLD */
-#include "common.h"
-#include "t3_cpl.h"
-#include "t3cdev.h"
-#include "cxgb3_ctl_defs.h"
-#include "cxgb3_offload.h"
-#include "firmware_exports.h"
-
-#include "cxgb3i_ddp.h"
-
-#define ddp_log_error(fmt...) printk(KERN_ERR "cxgb3i_ddp: ERR! " fmt)
-#define ddp_log_warn(fmt...)  printk(KERN_WARNING "cxgb3i_ddp: WARN! " fmt)
-#define ddp_log_info(fmt...)  printk(KERN_INFO "cxgb3i_ddp: " fmt)
-
-#ifdef __DEBUG_CXGB3I_DDP__
-#define ddp_log_debug(fmt, args...) \
-	printk(KERN_INFO "cxgb3i_ddp: %s - " fmt, __func__ , ## args)
-#else
-#define ddp_log_debug(fmt...)
-#endif
-
-/*
- * iSCSI Direct Data Placement
- *
- * T3 h/w can directly place the iSCSI Data-In or Data-Out PDU's payload into
- * pre-posted final destination host-memory buffers based on the Initiator
- * Task Tag (ITT) in Data-In or Target Task Tag (TTT) in Data-Out PDUs.
- *
- * The host memory address is programmed into h/w in the format of pagepod
- * entries.
- * The location of the pagepod entry is encoded into ddp tag which is used or
- * is the base for ITT/TTT.
- */
-
-#define DDP_PGIDX_MAX		4
-#define DDP_THRESHOLD	2048
-static unsigned char ddp_page_order[DDP_PGIDX_MAX] = {0, 1, 2, 4};
-static unsigned char ddp_page_shift[DDP_PGIDX_MAX] = {12, 13, 14, 16};
-static unsigned char page_idx = DDP_PGIDX_MAX;
-
-/*
- * functions to program the pagepod in h/w
- */
-static inline void ulp_mem_io_set_hdr(struct sk_buff *skb, unsigned int addr)
-{
-	struct ulp_mem_io *req = (struct ulp_mem_io *)skb->head;
-
-	req->wr.wr_lo = 0;
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS));
-	req->cmd_lock_addr = htonl(V_ULP_MEMIO_ADDR(addr >> 5) |
-				   V_ULPTX_CMD(ULP_MEM_WRITE));
-	req->len = htonl(V_ULP_MEMIO_DATA_LEN(PPOD_SIZE >> 5) |
-			 V_ULPTX_NFLITS((PPOD_SIZE >> 3) + 1));
-}
-
-static int set_ddp_map(struct cxgb3i_ddp_info *ddp, struct pagepod_hdr *hdr,
-		       unsigned int idx, unsigned int npods,
-		       struct cxgb3i_gather_list *gl)
-{
-	unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
-	int i;
-
-	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
-		struct sk_buff *skb = ddp->gl_skb[idx];
-		struct pagepod *ppod;
-		int j, pidx;
-
-		/* hold on to the skb until we clear the ddp mapping */
-		skb_get(skb);
-
-		ulp_mem_io_set_hdr(skb, pm_addr);
-		ppod = (struct pagepod *)
-		       (skb->head + sizeof(struct ulp_mem_io));
-		memcpy(&(ppod->hdr), hdr, sizeof(struct pagepod));
-		for (pidx = 4 * i, j = 0; j < 5; ++j, ++pidx)
-			ppod->addr[j] = pidx < gl->nelem ?
-				     cpu_to_be64(gl->phys_addr[pidx]) : 0UL;
-
-		skb->priority = CPL_PRIORITY_CONTROL;
-		cxgb3_ofld_send(ddp->tdev, skb);
-	}
-	return 0;
-}
-
-static void clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int tag,
-			 unsigned int idx, unsigned int npods)
-{
-	unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
-	int i;
-
-	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
-		struct sk_buff *skb = ddp->gl_skb[idx];
-
-		if (!skb) {
-			ddp_log_error("ddp tag 0x%x, 0x%x, %d/%u, skb NULL.\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(ddp->tdev, skb);
-	}
-}
-
-static inline int ddp_find_unused_entries(struct cxgb3i_ddp_info *ddp,
-					  unsigned int start, unsigned int max,
-					  unsigned int count,
-					  struct cxgb3i_gather_list *gl)
-{
-	unsigned int i, j, k;
-
-	/* not enough entries */
-	if ((max - start) < count)
-		return -EBUSY;
-
-	max -= count;
-	spin_lock(&ddp->map_lock);
-	for (i = start; i < max;) {
-		for (j = 0, k = i; j < count; j++, k++) {
-			if (ddp->gl_map[k])
-				break;
-		}
-		if (j == count) {
-			for (j = 0, k = i; j < count; j++, k++)
-				ddp->gl_map[k] = gl;
-			spin_unlock(&ddp->map_lock);
-			return i;
-		}
-		i += j + 1;
-	}
-	spin_unlock(&ddp->map_lock);
-	return -EBUSY;
-}
-
-static inline void ddp_unmark_entries(struct cxgb3i_ddp_info *ddp,
-				      int start, int count)
-{
-	spin_lock(&ddp->map_lock);
-	memset(&ddp->gl_map[start], 0,
-	       count * sizeof(struct cxgb3i_gather_list *));
-	spin_unlock(&ddp->map_lock);
-}
-
-static inline void ddp_free_gl_skb(struct cxgb3i_ddp_info *ddp,
-				   int idx, int count)
-{
-	int i;
-
-	for (i = 0; i < count; i++, idx++)
-		if (ddp->gl_skb[idx]) {
-			kfree_skb(ddp->gl_skb[idx]);
-			ddp->gl_skb[idx] = NULL;
-		}
-}
-
-static inline int ddp_alloc_gl_skb(struct cxgb3i_ddp_info *ddp, int idx,
-				   int count, gfp_t gfp)
-{
-	int i;
-
-	for (i = 0; i < count; i++) {
-		struct sk_buff *skb = alloc_skb(sizeof(struct ulp_mem_io) +
-						PPOD_SIZE, gfp);
-		if (skb) {
-			ddp->gl_skb[idx + i] = skb;
-			skb_put(skb, sizeof(struct ulp_mem_io) + PPOD_SIZE);
-		} else {
-			ddp_free_gl_skb(ddp, idx, i);
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-/**
- * cxgb3i_ddp_find_page_index - return ddp page index for a given page size
- * @pgsz: page size
- * return the ddp page index, if no match is found return DDP_PGIDX_MAX.
- */
-int cxgb3i_ddp_find_page_index(unsigned long pgsz)
-{
-	int i;
-
-	for (i = 0; i < DDP_PGIDX_MAX; i++) {
-		if (pgsz == (1UL << ddp_page_shift[i]))
-			return i;
-	}
-	ddp_log_debug("ddp page size 0x%lx not supported.\n", pgsz);
-	return DDP_PGIDX_MAX;
-}
-
-/**
- * cxgb3i_ddp_adjust_page_table - adjust page table with PAGE_SIZE
- * return the ddp page index, if no match is found return DDP_PGIDX_MAX.
- */
-int cxgb3i_ddp_adjust_page_table(void)
-{
-	int i;
-	unsigned int base_order, order;
-
-	if (PAGE_SIZE < (1UL << ddp_page_shift[0])) {
-		ddp_log_info("PAGE_SIZE 0x%lx too small, min. 0x%lx.\n",
-				PAGE_SIZE, 1UL << ddp_page_shift[0]);
-		return -EINVAL;
-	}
-
-	base_order = get_order(1UL << ddp_page_shift[0]);
-	order = get_order(1 << PAGE_SHIFT);
-	for (i = 0; i < DDP_PGIDX_MAX; i++) {
-		/* first is the kernel page size, then just doubling the size */
-		ddp_page_order[i] = order - base_order + i;
-		ddp_page_shift[i] = PAGE_SHIFT + i;
-	}
-	return 0;
-}
-
-static inline void ddp_gl_unmap(struct pci_dev *pdev,
-				struct cxgb3i_gather_list *gl)
-{
-	int i;
-
-	for (i = 0; i < gl->nelem; i++)
-		pci_unmap_page(pdev, gl->phys_addr[i], PAGE_SIZE,
-			       PCI_DMA_FROMDEVICE);
-}
-
-static inline int ddp_gl_map(struct pci_dev *pdev,
-			     struct cxgb3i_gather_list *gl)
-{
-	int i;
-
-	for (i = 0; i < gl->nelem; i++) {
-		gl->phys_addr[i] = pci_map_page(pdev, gl->pages[i], 0,
-						PAGE_SIZE,
-						PCI_DMA_FROMDEVICE);
-		if (unlikely(pci_dma_mapping_error(pdev, gl->phys_addr[i])))
-			goto unmap;
-	}
-
-	return i;
-
-unmap:
-	if (i) {
-		unsigned int nelem = gl->nelem;
-
-		gl->nelem = i;
-		ddp_gl_unmap(pdev, gl);
-		gl->nelem = nelem;
-	}
-	return -ENOMEM;
-}
-
-/**
- * cxgb3i_ddp_make_gl - build ddp page buffer list
- * @xferlen: total buffer length
- * @sgl: page buffer scatter-gather list
- * @sgcnt: # of page buffers
- * @pdev: pci_dev, used for pci map
- * @gfp: allocation mode
- *
- * construct a ddp page buffer list from the scsi scattergather list.
- * coalesce buffers as much as possible, and obtain dma addresses for
- * each page.
- *
- * Return the cxgb3i_gather_list constructed from the page buffers if the
- * memory can be used for ddp. Return NULL otherwise.
- */
-struct cxgb3i_gather_list *cxgb3i_ddp_make_gl(unsigned int xferlen,
-					      struct scatterlist *sgl,
-					      unsigned int sgcnt,
-					      struct pci_dev *pdev,
-					      gfp_t gfp)
-{
-	struct cxgb3i_gather_list *gl;
-	struct scatterlist *sg = sgl;
-	struct page *sgpage = sg_page(sg);
-	unsigned int sglen = sg->length;
-	unsigned int sgoffset = sg->offset;
-	unsigned int npages = (xferlen + sgoffset + PAGE_SIZE - 1) >>
-			      PAGE_SHIFT;
-	int i = 1, j = 0;
-
-	if (xferlen < DDP_THRESHOLD) {
-		ddp_log_debug("xfer %u < threshold %u, no ddp.\n",
-			      xferlen, DDP_THRESHOLD);
-		return NULL;
-	}
-
-	gl = kzalloc(sizeof(struct cxgb3i_gather_list) +
-		     npages * (sizeof(dma_addr_t) + sizeof(struct page *)),
-		     gfp);
-	if (!gl)
-		return NULL;
-
-	gl->pages = (struct page **)&gl->phys_addr[npages];
-	gl->length = xferlen;
-	gl->offset = sgoffset;
-	gl->pages[0] = sgpage;
-
-	sg = sg_next(sg);
-	while (sg) {
-		struct page *page = sg_page(sg);
-
-		if (sgpage == page && sg->offset == sgoffset + sglen)
-			sglen += sg->length;
-		else {
-			/* make sure the sgl is fit for ddp:
-			 * each has the same page size, and
-			 * all of the middle pages are used completely
-			 */
-			if ((j && sgoffset) ||
-			    ((i != sgcnt - 1) &&
-			     ((sglen + sgoffset) & ~PAGE_MASK)))
-				goto error_out;
-
-			j++;
-			if (j == gl->nelem || sg->offset)
-				goto error_out;
-			gl->pages[j] = page;
-			sglen = sg->length;
-			sgoffset = sg->offset;
-			sgpage = page;
-		}
-		i++;
-		sg = sg_next(sg);
-	}
-	gl->nelem = ++j;
-
-	if (ddp_gl_map(pdev, gl) < 0)
-		goto error_out;
-
-	return gl;
-
-error_out:
-	kfree(gl);
-	return NULL;
-}
-
-/**
- * cxgb3i_ddp_release_gl - release a page buffer list
- * @gl: a ddp page buffer list
- * @pdev: pci_dev used for pci_unmap
- * free a ddp page buffer list resulted from cxgb3i_ddp_make_gl().
- */
-void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
-			   struct pci_dev *pdev)
-{
-	ddp_gl_unmap(pdev, gl);
-	kfree(gl);
-}
-
-/**
- * cxgb3i_ddp_tag_reserve - set up ddp for a data transfer
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @tformat: tag format
- * @tagp: contains s/w tag initially, will be updated with ddp/hw tag
- * @gl: the page momory list
- * @gfp: allocation mode
- *
- * ddp setup for a given page buffer list and construct the ddp tag.
- * return 0 if success, < 0 otherwise.
- */
-int cxgb3i_ddp_tag_reserve(struct t3cdev *tdev, unsigned int tid,
-			   struct cxgb3i_tag_format *tformat, u32 *tagp,
-			   struct cxgb3i_gather_list *gl, gfp_t gfp)
-{
-	struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
-	struct pagepod_hdr hdr;
-	unsigned int npods;
-	int idx = -1;
-	int err = -ENOMEM;
-	u32 sw_tag = *tagp;
-	u32 tag;
-
-	if (page_idx >= DDP_PGIDX_MAX || !ddp || !gl || !gl->nelem ||
-		gl->length < DDP_THRESHOLD) {
-		ddp_log_debug("pgidx %u, xfer %u/%u, NO ddp.\n",
-			      page_idx, gl->length, DDP_THRESHOLD);
-		return -EINVAL;
-	}
-
-	npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
-
-	if (ddp->idx_last == ddp->nppods)
-		idx = ddp_find_unused_entries(ddp, 0, ddp->nppods, npods, gl);
-	else {
-		idx = ddp_find_unused_entries(ddp, ddp->idx_last + 1,
-					      ddp->nppods, npods, gl);
-		if (idx < 0 && ddp->idx_last >= npods) {
-			idx = ddp_find_unused_entries(ddp, 0,
-				min(ddp->idx_last + npods, ddp->nppods),
-						      npods, gl);
-		}
-	}
-	if (idx < 0) {
-		ddp_log_debug("xferlen %u, gl %u, npods %u NO DDP.\n",
-			      gl->length, gl->nelem, npods);
-		return idx;
-	}
-
-	err = ddp_alloc_gl_skb(ddp, idx, npods, gfp);
-	if (err < 0)
-		goto unmark_entries;
-
-	tag = cxgb3i_ddp_tag_base(tformat, sw_tag);
-	tag |= idx << PPOD_IDX_SHIFT;
-
-	hdr.rsvd = 0;
-	hdr.vld_tid = htonl(F_PPOD_VALID | V_PPOD_TID(tid));
-	hdr.pgsz_tag_clr = htonl(tag & ddp->rsvd_tag_mask);
-	hdr.maxoffset = htonl(gl->length);
-	hdr.pgoffset = htonl(gl->offset);
-
-	err = set_ddp_map(ddp, &hdr, idx, npods, gl);
-	if (err < 0)
-		goto free_gl_skb;
-
-	ddp->idx_last = idx;
-	ddp_log_debug("xfer %u, gl %u,%u, tid 0x%x, 0x%x -> 0x%x(%u,%u).\n",
-		      gl->length, gl->nelem, gl->offset, tid, sw_tag, tag,
-		      idx, npods);
-	*tagp = tag;
-	return 0;
-
-free_gl_skb:
-	ddp_free_gl_skb(ddp, idx, npods);
-unmark_entries:
-	ddp_unmark_entries(ddp, idx, npods);
-	return err;
-}
-
-/**
- * cxgb3i_ddp_tag_release - release a ddp tag
- * @tdev: t3cdev adapter
- * @tag: ddp tag
- * ddp cleanup for a given ddp tag and release all the resources held
- */
-void cxgb3i_ddp_tag_release(struct t3cdev *tdev, u32 tag)
-{
-	struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
-	u32 idx;
-
-	if (!ddp) {
-		ddp_log_error("release ddp tag 0x%x, ddp NULL.\n", tag);
-		return;
-	}
-
-	idx = (tag >> PPOD_IDX_SHIFT) & ddp->idx_mask;
-	if (idx < ddp->nppods) {
-		struct cxgb3i_gather_list *gl = ddp->gl_map[idx];
-		unsigned int npods;
-
-		if (!gl || !gl->nelem) {
-			ddp_log_error("release 0x%x, idx 0x%x, gl 0x%p, %u.\n",
-				      tag, idx, gl, gl ? gl->nelem : 0);
-			return;
-		}
-		npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
-		ddp_log_debug("ddp tag 0x%x, release idx 0x%x, npods %u.\n",
-			      tag, idx, npods);
-		clear_ddp_map(ddp, tag, idx, npods);
-		ddp_unmark_entries(ddp, idx, npods);
-		cxgb3i_ddp_release_gl(gl, ddp->pdev);
-	} else
-		ddp_log_error("ddp tag 0x%x, idx 0x%x > max 0x%x.\n",
-			      tag, idx, ddp->nppods);
-}
-
-static int setup_conn_pgidx(struct t3cdev *tdev, unsigned int tid, int pg_idx,
-			    int reply)
-{
-	struct sk_buff *skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
-					GFP_KERNEL);
-	struct cpl_set_tcb_field *req;
-	u64 val = pg_idx < DDP_PGIDX_MAX ? pg_idx : 0;
-
-	if (!skb)
-		return -ENOMEM;
-
-	/* set up ulp submode and page size */
-	req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	req->wr.wr_lo = 0;
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-	req->reply = V_NO_REPLY(reply ? 0 : 1);
-	req->cpu_idx = 0;
-	req->word = htons(31);
-	req->mask = cpu_to_be64(0xF0000000);
-	req->val = cpu_to_be64(val << 28);
-	skb->priority = CPL_PRIORITY_CONTROL;
-
-	cxgb3_ofld_send(tdev, skb);
-	return 0;
-}
-
-/**
- * cxgb3i_setup_conn_host_pagesize - setup the conn.'s ddp page size
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @reply: request reply from h/w
- * set up the ddp page size based on the host PAGE_SIZE for a connection
- * identified by tid
- */
-int cxgb3i_setup_conn_host_pagesize(struct t3cdev *tdev, unsigned int tid,
-				    int reply)
-{
-	return setup_conn_pgidx(tdev, tid, page_idx, reply);
-}
-
-/**
- * cxgb3i_setup_conn_pagesize - setup the conn.'s ddp page size
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @reply: request reply from h/w
- * @pgsz: ddp page size
- * set up the ddp page size for a connection identified by tid
- */
-int cxgb3i_setup_conn_pagesize(struct t3cdev *tdev, unsigned int tid,
-				int reply, unsigned long pgsz)
-{
-	int pgidx = cxgb3i_ddp_find_page_index(pgsz);
-
-	return setup_conn_pgidx(tdev, tid, pgidx, reply);
-}
-
-/**
- * cxgb3i_setup_conn_digest - setup conn. digest setting
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @hcrc: header digest enabled
- * @dcrc: data digest enabled
- * @reply: request reply from h/w
- * set up the iscsi digest settings for a connection identified by tid
- */
-int cxgb3i_setup_conn_digest(struct t3cdev *tdev, unsigned int tid,
-			     int hcrc, int dcrc, int reply)
-{
-	struct sk_buff *skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
-					GFP_KERNEL);
-	struct cpl_set_tcb_field *req;
-	u64 val = (hcrc ? 1 : 0) | (dcrc ? 2 : 0);
-
-	if (!skb)
-		return -ENOMEM;
-
-	/* set up ulp submode and page size */
-	req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	req->wr.wr_lo = 0;
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-	req->reply = V_NO_REPLY(reply ? 0 : 1);
-	req->cpu_idx = 0;
-	req->word = htons(31);
-	req->mask = cpu_to_be64(0x0F000000);
-	req->val = cpu_to_be64(val << 24);
-	skb->priority = CPL_PRIORITY_CONTROL;
-
-	cxgb3_ofld_send(tdev, skb);
-	return 0;
-}
-
-
-/**
- * cxgb3i_adapter_ddp_info - read the adapter's ddp information
- * @tdev: t3cdev adapter
- * @tformat: tag format
- * @txsz: max tx pdu payload size, filled in by this func.
- * @rxsz: max rx pdu payload size, filled in by this func.
- * setup the tag format for a given iscsi entity
- */
-int cxgb3i_adapter_ddp_info(struct t3cdev *tdev,
-			    struct cxgb3i_tag_format *tformat,
-			    unsigned int *txsz, unsigned int *rxsz)
-{
-	struct cxgb3i_ddp_info *ddp;
-	unsigned char idx_bits;
-
-	if (!tformat)
-		return -EINVAL;
-
-	if (!tdev->ulp_iscsi)
-		return -EINVAL;
-
-	ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
-
-	idx_bits = 32 - tformat->sw_bits;
-	tformat->rsvd_bits = ddp->idx_bits;
-	tformat->rsvd_shift = PPOD_IDX_SHIFT;
-	tformat->rsvd_mask = (1 << tformat->rsvd_bits) - 1;
-
-	ddp_log_info("tag format: sw %u, rsvd %u,%u, mask 0x%x.\n",
-		      tformat->sw_bits, tformat->rsvd_bits,
-		      tformat->rsvd_shift, tformat->rsvd_mask);
-
-	*txsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
-			ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
-	*rxsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
-			ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
-	ddp_log_info("max payload size: %u/%u, %u/%u.\n",
-		     *txsz, ddp->max_txsz, *rxsz, ddp->max_rxsz);
-	return 0;
-}
-
-/**
- * cxgb3i_ddp_cleanup - release the cxgb3 adapter's ddp resource
- * @tdev: t3cdev adapter
- * release all the resource held by the ddp pagepod manager for a given
- * adapter if needed
- */
-
-static void ddp_cleanup(struct kref *kref)
-{
-	struct cxgb3i_ddp_info *ddp = container_of(kref,
-						struct cxgb3i_ddp_info,
-						refcnt);
-	int i = 0;
-
-	ddp_log_info("kref release ddp 0x%p, t3dev 0x%p.\n", ddp, ddp->tdev);
-
-	ddp->tdev->ulp_iscsi = NULL;
-	while (i < ddp->nppods) {
-		struct cxgb3i_gather_list *gl = ddp->gl_map[i];
-		if (gl) {
-			int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
-					>> PPOD_PAGES_SHIFT;
-			ddp_log_info("t3dev 0x%p, ddp %d + %d.\n",
-					ddp->tdev, i, npods);
-			kfree(gl);
-			ddp_free_gl_skb(ddp, i, npods);
-			i += npods;
-		} else
-			i++;
-	}
-	cxgb3i_free_big_mem(ddp);
-}
-
-void cxgb3i_ddp_cleanup(struct t3cdev *tdev)
-{
-	struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
-
-	ddp_log_info("t3dev 0x%p, release ddp 0x%p.\n", tdev, ddp);
-	if (ddp)
-		kref_put(&ddp->refcnt, ddp_cleanup);
-}
-
-/**
- * ddp_init - initialize the cxgb3 adapter's ddp resource
- * @tdev: t3cdev adapter
- * initialize the ddp pagepod manager for a given adapter
- */
-static void ddp_init(struct t3cdev *tdev)
-{
-	struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
-	struct ulp_iscsi_info uinfo;
-	unsigned int ppmax, bits;
-	int i, err;
-
-	if (ddp) {
-		kref_get(&ddp->refcnt);
-		ddp_log_warn("t3dev 0x%p, ddp 0x%p already set up.\n",
-				tdev, tdev->ulp_iscsi);
-		return;
-	}
-
-	err = tdev->ctl(tdev, ULP_ISCSI_GET_PARAMS, &uinfo);
-	if (err < 0) {
-		ddp_log_error("%s, failed to get iscsi param err=%d.\n",
-				 tdev->name, err);
-		return;
-	}
-
-	ppmax = (uinfo.ulimit - uinfo.llimit + 1) >> PPOD_SIZE_SHIFT;
-	bits = __ilog2_u32(ppmax) + 1;
-	if (bits > PPOD_IDX_MAX_SIZE)
-		bits = PPOD_IDX_MAX_SIZE;
-	ppmax = (1 << (bits - 1)) - 1;
-
-	ddp = cxgb3i_alloc_big_mem(sizeof(struct cxgb3i_ddp_info) +
-				   ppmax *
-					(sizeof(struct cxgb3i_gather_list *) +
-					sizeof(struct sk_buff *)),
-				   GFP_KERNEL);
-	if (!ddp) {
-		ddp_log_warn("%s unable to alloc ddp 0x%d, ddp disabled.\n",
-			     tdev->name, ppmax);
-		return;
-	}
-	ddp->gl_map = (struct cxgb3i_gather_list **)(ddp + 1);
-	ddp->gl_skb = (struct sk_buff **)(((char *)ddp->gl_map) +
-					  ppmax *
-					  sizeof(struct cxgb3i_gather_list *));
-	spin_lock_init(&ddp->map_lock);
-	kref_init(&ddp->refcnt);
-
-	ddp->tdev = tdev;
-	ddp->pdev = uinfo.pdev;
-	ddp->max_txsz = min_t(unsigned int, uinfo.max_txsz, ULP2_MAX_PKT_SIZE);
-	ddp->max_rxsz = min_t(unsigned int, uinfo.max_rxsz, ULP2_MAX_PKT_SIZE);
-	ddp->llimit = uinfo.llimit;
-	ddp->ulimit = uinfo.ulimit;
-	ddp->nppods = ppmax;
-	ddp->idx_last = ppmax;
-	ddp->idx_bits = bits;
-	ddp->idx_mask = (1 << bits) - 1;
-	ddp->rsvd_tag_mask = (1 << (bits + PPOD_IDX_SHIFT)) - 1;
-
-	uinfo.tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
-	for (i = 0; i < DDP_PGIDX_MAX; i++)
-		uinfo.pgsz_factor[i] = ddp_page_order[i];
-	uinfo.ulimit = uinfo.llimit + (ppmax << PPOD_SIZE_SHIFT);
-
-	err = tdev->ctl(tdev, ULP_ISCSI_SET_PARAMS, &uinfo);
-	if (err < 0) {
-		ddp_log_warn("%s unable to set iscsi param err=%d, "
-			      "ddp disabled.\n", tdev->name, err);
-		goto free_ddp_map;
-	}
-
-	tdev->ulp_iscsi = ddp;
-
-	ddp_log_info("tdev 0x%p, nppods %u, bits %u, mask 0x%x,0x%x pkt %u/%u,"
-			" %u/%u.\n",
-			tdev, ppmax, ddp->idx_bits, ddp->idx_mask,
-			ddp->rsvd_tag_mask, ddp->max_txsz, uinfo.max_txsz,
-			ddp->max_rxsz, uinfo.max_rxsz);
-	return;
-
-free_ddp_map:
-	cxgb3i_free_big_mem(ddp);
-}
-
-/**
- * cxgb3i_ddp_init - initialize ddp functions
- */
-void cxgb3i_ddp_init(struct t3cdev *tdev)
-{
-	if (page_idx == DDP_PGIDX_MAX) {
-		page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
-
-		if (page_idx == DDP_PGIDX_MAX) {
-			ddp_log_info("system PAGE_SIZE %lu, update hw.\n",
-					PAGE_SIZE);
-			if (cxgb3i_ddp_adjust_page_table() < 0) {
-				ddp_log_info("PAGE_SIZE %lu, ddp disabled.\n",
-						PAGE_SIZE);
-				return;
-			}
-			page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
-		}
-		ddp_log_info("system PAGE_SIZE %lu, ddp idx %u.\n",
-				PAGE_SIZE, page_idx);
-	}
-	ddp_init(tdev);
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h
deleted file mode 100644
index 6761b32..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * cxgb3i_ddp.h: Chelsio S3xx iSCSI DDP Manager.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef __CXGB3I_ULP2_DDP_H__
-#define __CXGB3I_ULP2_DDP_H__
-
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-/**
- * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity
- *
- * @sw_bits:	# of bits used by iscsi software layer
- * @rsvd_bits:	# of bits used by h/w
- * @rsvd_shift:	h/w bits shift left
- * @rsvd_mask:	reserved bit mask
- */
-struct cxgb3i_tag_format {
-	unsigned char sw_bits;
-	unsigned char rsvd_bits;
-	unsigned char rsvd_shift;
-	unsigned char filler[1];
-	u32 rsvd_mask;
-};
-
-/**
- * struct cxgb3i_gather_list - cxgb3i direct data placement memory
- *
- * @tag:	ddp tag
- * @length:	total data buffer length
- * @offset:	initial offset to the 1st page
- * @nelem:	# of pages
- * @pages:	page pointers
- * @phys_addr:	physical address
- */
-struct cxgb3i_gather_list {
-	u32 tag;
-	unsigned int length;
-	unsigned int offset;
-	unsigned int nelem;
-	struct page **pages;
-	dma_addr_t phys_addr[0];
-};
-
-/**
- * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload
- *
- * @list:	list head to link elements
- * @refcnt:	ref. count
- * @tdev:	pointer to t3cdev used by cxgb3 driver
- * @max_txsz:	max tx packet size for ddp
- * @max_rxsz:	max rx packet size for ddp
- * @llimit:	lower bound of the page pod memory
- * @ulimit:	upper bound of the page pod memory
- * @nppods:	# of page pod entries
- * @idx_last:	page pod entry last used
- * @idx_bits:	# of bits the pagepod index would take
- * @idx_mask:	pagepod index mask
- * @rsvd_tag_mask: tag mask
- * @map_lock:	lock to synchonize access to the page pod map
- * @gl_map:	ddp memory gather list
- * @gl_skb:	skb used to program the pagepod
- */
-struct cxgb3i_ddp_info {
-	struct list_head list;
-	struct kref refcnt;
-	struct t3cdev *tdev;
-	struct pci_dev *pdev;
-	unsigned int max_txsz;
-	unsigned int max_rxsz;
-	unsigned int llimit;
-	unsigned int ulimit;
-	unsigned int nppods;
-	unsigned int idx_last;
-	unsigned char idx_bits;
-	unsigned char filler[3];
-	u32 idx_mask;
-	u32 rsvd_tag_mask;
-	spinlock_t map_lock;
-	struct cxgb3i_gather_list **gl_map;
-	struct sk_buff **gl_skb;
-};
-
-#define ISCSI_PDU_NONPAYLOAD_LEN	312 /* bhs(48) + ahs(256) + digest(8) */
-#define ULP2_MAX_PKT_SIZE	16224
-#define ULP2_MAX_PDU_PAYLOAD	(ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
-#define PPOD_PAGES_MAX		4
-#define PPOD_PAGES_SHIFT	2	/* 4 pages per pod */
-
-/*
- * struct pagepod_hdr, pagepod - pagepod format
- */
-struct pagepod_hdr {
-	u32 vld_tid;
-	u32 pgsz_tag_clr;
-	u32 maxoffset;
-	u32 pgoffset;
-	u64 rsvd;
-};
-
-struct pagepod {
-	struct pagepod_hdr hdr;
-	u64 addr[PPOD_PAGES_MAX + 1];
-};
-
-#define PPOD_SIZE		sizeof(struct pagepod)	/* 64 */
-#define PPOD_SIZE_SHIFT		6
-
-#define PPOD_COLOR_SHIFT	0
-#define PPOD_COLOR_SIZE		6
-#define PPOD_COLOR_MASK		((1 << PPOD_COLOR_SIZE) - 1)
-
-#define PPOD_IDX_SHIFT		PPOD_COLOR_SIZE
-#define PPOD_IDX_MAX_SIZE	24
-
-#define S_PPOD_TID    0
-#define M_PPOD_TID    0xFFFFFF
-#define V_PPOD_TID(x) ((x) << S_PPOD_TID)
-
-#define S_PPOD_VALID    24
-#define V_PPOD_VALID(x) ((x) << S_PPOD_VALID)
-#define F_PPOD_VALID    V_PPOD_VALID(1U)
-
-#define S_PPOD_COLOR    0
-#define M_PPOD_COLOR    0x3F
-#define V_PPOD_COLOR(x) ((x) << S_PPOD_COLOR)
-
-#define S_PPOD_TAG    6
-#define M_PPOD_TAG    0xFFFFFF
-#define V_PPOD_TAG(x) ((x) << S_PPOD_TAG)
-
-#define S_PPOD_PGSZ    30
-#define M_PPOD_PGSZ    0x3
-#define V_PPOD_PGSZ(x) ((x) << S_PPOD_PGSZ)
-
-/*
- * large memory chunk allocation/release
- * use vmalloc() if kmalloc() fails
- */
-static inline void *cxgb3i_alloc_big_mem(unsigned int size,
-					 gfp_t gfp)
-{
-	void *p = kmalloc(size, gfp);
-	if (!p)
-		p = vmalloc(size);
-	if (p)
-		memset(p, 0, size);
-	return p;
-}
-
-static inline void cxgb3i_free_big_mem(void *addr)
-{
-	if (is_vmalloc_addr(addr))
-		vfree(addr);
-	else
-		kfree(addr);
-}
-
-/*
- * cxgb3i ddp tag are 32 bits, it consists of reserved bits used by h/w and
- * non-reserved bits that can be used by the iscsi s/w.
- * The reserved bits are identified by the rsvd_bits and rsvd_shift fields
- * in struct cxgb3i_tag_format.
- *
- * The upper most reserved bit can be used to check if a tag is ddp tag or not:
- * 	if the bit is 0, the tag is a valid ddp tag
- */
-
-/**
- * cxgb3i_is_ddp_tag - check if a given tag is a hw/ddp tag
- * @tformat: tag format information
- * @tag: tag to be checked
- *
- * return true if the tag is a ddp tag, false otherwise.
- */
-static inline int cxgb3i_is_ddp_tag(struct cxgb3i_tag_format *tformat, u32 tag)
-{
-	return !(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1)));
-}
-
-/**
- * cxgb3i_sw_tag_usable - check if s/w tag has enough bits left for hw bits
- * @tformat: tag format information
- * @sw_tag: s/w tag to be checked
- *
- * return true if the tag can be used for hw ddp tag, false otherwise.
- */
-static inline int cxgb3i_sw_tag_usable(struct cxgb3i_tag_format *tformat,
-					u32 sw_tag)
-{
-	sw_tag >>= (32 - tformat->rsvd_bits);
-	return !sw_tag;
-}
-
-/**
- * cxgb3i_set_non_ddp_tag - mark a given s/w tag as an invalid ddp tag
- * @tformat: tag format information
- * @sw_tag: s/w tag to be checked
- *
- * insert 1 at the upper most reserved bit to mark it as an invalid ddp tag.
- */
-static inline u32 cxgb3i_set_non_ddp_tag(struct cxgb3i_tag_format *tformat,
-					 u32 sw_tag)
-{
-	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
-	u32 mask = (1 << shift) - 1;
-
-	if (sw_tag && (sw_tag & ~mask)) {
-		u32 v1 = sw_tag & ((1 << shift) - 1);
-		u32 v2 = (sw_tag >> (shift - 1)) << shift;
-
-		return v2 | v1 | 1 << shift;
-	}
-	return sw_tag | 1 << shift;
-}
-
-/**
- * cxgb3i_ddp_tag_base - shift s/w tag bits so that reserved bits are not used
- * @tformat: tag format information
- * @sw_tag: s/w tag to be checked
- */
-static inline u32 cxgb3i_ddp_tag_base(struct cxgb3i_tag_format *tformat,
-				      u32 sw_tag)
-{
-	u32 mask = (1 << tformat->rsvd_shift) - 1;
-
-	if (sw_tag && (sw_tag & ~mask)) {
-		u32 v1 = sw_tag & mask;
-		u32 v2 = sw_tag >> tformat->rsvd_shift;
-
-		v2 <<= tformat->rsvd_shift + tformat->rsvd_bits;
-		return v2 | v1;
-	}
-	return sw_tag;
-}
-
-/**
- * cxgb3i_tag_rsvd_bits - get the reserved bits used by the h/w
- * @tformat: tag format information
- * @tag: tag to be checked
- *
- * return the reserved bits in the tag
- */
-static inline u32 cxgb3i_tag_rsvd_bits(struct cxgb3i_tag_format *tformat,
-				       u32 tag)
-{
-	if (cxgb3i_is_ddp_tag(tformat, tag))
-		return (tag >> tformat->rsvd_shift) & tformat->rsvd_mask;
-	return 0;
-}
-
-/**
- * cxgb3i_tag_nonrsvd_bits - get the non-reserved bits used by the s/w
- * @tformat: tag format information
- * @tag: tag to be checked
- *
- * return the non-reserved bits in the tag.
- */
-static inline u32 cxgb3i_tag_nonrsvd_bits(struct cxgb3i_tag_format *tformat,
-					  u32 tag)
-{
-	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
-	u32 v1, v2;
-
-	if (cxgb3i_is_ddp_tag(tformat, tag)) {
-		v1 = tag & ((1 << tformat->rsvd_shift) - 1);
-		v2 = (tag >> (shift + 1)) << tformat->rsvd_shift;
-	} else {
-		u32 mask = (1 << shift) - 1;
-
-		tag &= ~(1 << shift);
-		v1 = tag & mask;
-		v2 = (tag >> 1) & ~mask;
-	}
-	return v1 | v2;
-}
-
-int cxgb3i_ddp_tag_reserve(struct t3cdev *, unsigned int tid,
-			   struct cxgb3i_tag_format *, u32 *tag,
-			   struct cxgb3i_gather_list *, gfp_t gfp);
-void cxgb3i_ddp_tag_release(struct t3cdev *, u32 tag);
-
-struct cxgb3i_gather_list *cxgb3i_ddp_make_gl(unsigned int xferlen,
-				struct scatterlist *sgl,
-				unsigned int sgcnt,
-				struct pci_dev *pdev,
-				gfp_t gfp);
-void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
-				struct pci_dev *pdev);
-
-int cxgb3i_setup_conn_host_pagesize(struct t3cdev *, unsigned int tid,
-				    int reply);
-int cxgb3i_setup_conn_pagesize(struct t3cdev *, unsigned int tid, int reply,
-			       unsigned long pgsz);
-int cxgb3i_setup_conn_digest(struct t3cdev *, unsigned int tid,
-				int hcrc, int dcrc, int reply);
-int cxgb3i_ddp_find_page_index(unsigned long pgsz);
-int cxgb3i_adapter_ddp_info(struct t3cdev *, struct cxgb3i_tag_format *,
-			    unsigned int *txsz, unsigned int *rxsz);
-
-void cxgb3i_ddp_init(struct t3cdev *);
-void cxgb3i_ddp_cleanup(struct t3cdev *);
-#endif
diff --git a/drivers/scsi/cxgb3i/cxgb3i_init.c b/drivers/scsi/cxgb3i/cxgb3i_init.c
deleted file mode 100644
index 685af36..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_init.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/* cxgb3i_init.c: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include "cxgb3i.h"
-
-#define DRV_MODULE_NAME         "cxgb3i"
-#define DRV_MODULE_VERSION	"1.0.2"
-#define DRV_MODULE_RELDATE	"Mar. 2009"
-
-static char version[] =
-	"Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME
-	" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
-
-MODULE_AUTHOR("Karen Xie <kxie@chelsio.com>");
-MODULE_DESCRIPTION("Chelsio S3xx iSCSI Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_MODULE_VERSION);
-
-static void open_s3_dev(struct t3cdev *);
-static void close_s3_dev(struct t3cdev *);
-static void s3_event_handler(struct t3cdev *tdev, u32 event, u32 port);
-
-static cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS];
-static struct cxgb3_client t3c_client = {
-	.name = "iscsi_cxgb3",
-	.handlers = cxgb3i_cpl_handlers,
-	.add = open_s3_dev,
-	.remove = close_s3_dev,
-	.event_handler = s3_event_handler,
-};
-
-/**
- * open_s3_dev - register with cxgb3 LLD
- * @t3dev:	cxgb3 adapter instance
- */
-static void open_s3_dev(struct t3cdev *t3dev)
-{
-	static int vers_printed;
-
-	if (!vers_printed) {
-		printk(KERN_INFO "%s", version);
-		vers_printed = 1;
-	}
-
-	cxgb3i_ddp_init(t3dev);
-	cxgb3i_sdev_add(t3dev, &t3c_client);
-	cxgb3i_adapter_open(t3dev);
-}
-
-/**
- * close_s3_dev - de-register with cxgb3 LLD
- * @t3dev:	cxgb3 adapter instance
- */
-static void close_s3_dev(struct t3cdev *t3dev)
-{
-	cxgb3i_adapter_close(t3dev);
-	cxgb3i_sdev_remove(t3dev);
-	cxgb3i_ddp_cleanup(t3dev);
-}
-
-static void s3_event_handler(struct t3cdev *tdev, u32 event, u32 port)
-{
-	struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(tdev);
-
-	cxgb3i_log_info("snic 0x%p, tdev 0x%p, event 0x%x, port 0x%x.\n",
-			snic, tdev, event, port);
-	if (!snic)
-		return;
-
-	switch (event) {
-	case OFFLOAD_STATUS_DOWN:
-		snic->flags |= CXGB3I_ADAPTER_FLAG_RESET;
-		break;
-	case OFFLOAD_STATUS_UP:
-		snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
-		break;
-	}
-}
-
-/**
- * cxgb3i_init_module - module init entry point
- *
- * initialize any driver wide global data structures and register itself
- *	with the cxgb3 module
- */
-static int __init cxgb3i_init_module(void)
-{
-	int err;
-
-	err = cxgb3i_sdev_init(cxgb3i_cpl_handlers);
-	if (err < 0)
-		return err;
-
-	err = cxgb3i_iscsi_init();
-	if (err < 0)
-		return err;
-
-	err = cxgb3i_pdu_init();
-	if (err < 0) {
-		cxgb3i_iscsi_cleanup();
-		return err;
-	}
-
-	cxgb3_register_client(&t3c_client);
-
-	return 0;
-}
-
-/**
- * cxgb3i_exit_module - module cleanup/exit entry point
- *
- * go through the driver hba list and for each hba, release any resource held.
- *	and unregisters iscsi transport and the cxgb3 module
- */
-static void __exit cxgb3i_exit_module(void)
-{
-	cxgb3_unregister_client(&t3c_client);
-	cxgb3i_pdu_cleanup();
-	cxgb3i_iscsi_cleanup();
-	cxgb3i_sdev_cleanup();
-}
-
-module_init(cxgb3i_init_module);
-module_exit(cxgb3i_exit_module);
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
deleted file mode 100644
index 7b686ab..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+++ /dev/null
@@ -1,1018 +0,0 @@
-/* cxgb3i_iscsi.c: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, Inc.
- * Copyright (c) 2008 Mike Christie
- * Copyright (c) 2008 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/inet.h>
-#include <linux/slab.h>
-#include <linux/crypto.h>
-#include <linux/if_vlan.h>
-#include <net/dst.h>
-#include <net/tcp.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi.h>
-#include <scsi/iscsi_proto.h>
-#include <scsi/libiscsi.h>
-#include <scsi/scsi_transport_iscsi.h>
-
-#include "cxgb3i.h"
-#include "cxgb3i_pdu.h"
-
-#ifdef __DEBUG_CXGB3I_TAG__
-#define cxgb3i_tag_debug	cxgb3i_log_debug
-#else
-#define cxgb3i_tag_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_CXGB3I_API__
-#define cxgb3i_api_debug	cxgb3i_log_debug
-#else
-#define cxgb3i_api_debug(fmt...)
-#endif
-
-/*
- * align pdu size to multiple of 512 for better performance
- */
-#define align_pdu_size(n) do { n = (n) & (~511); } while (0)
-
-static struct scsi_transport_template *cxgb3i_scsi_transport;
-static struct scsi_host_template cxgb3i_host_template;
-static struct iscsi_transport cxgb3i_iscsi_transport;
-static unsigned char sw_tag_idx_bits;
-static unsigned char sw_tag_age_bits;
-
-static LIST_HEAD(cxgb3i_snic_list);
-static DEFINE_RWLOCK(cxgb3i_snic_rwlock);
-
-/**
- * cxgb3i_adpater_find_by_tdev - find the cxgb3i_adapter structure via t3cdev
- * @tdev: t3cdev pointer
- */
-struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *tdev)
-{
-	struct cxgb3i_adapter *snic;
-
-	read_lock(&cxgb3i_snic_rwlock);
-	list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
-		if (snic->tdev == tdev) {
-			read_unlock(&cxgb3i_snic_rwlock);
-			return snic;
-		}
-	}
-	read_unlock(&cxgb3i_snic_rwlock);
-	return NULL;
-}
-
-static inline int adapter_update(struct cxgb3i_adapter *snic)
-{
-	cxgb3i_log_info("snic 0x%p, t3dev 0x%p, updating.\n",
-			snic, snic->tdev);
-	return cxgb3i_adapter_ddp_info(snic->tdev, &snic->tag_format,
-					&snic->tx_max_size,
-					&snic->rx_max_size);
-}
-
-static int adapter_add(struct cxgb3i_adapter *snic)
-{
-	struct t3cdev *t3dev = snic->tdev;
-	struct adapter *adapter = tdev2adap(t3dev);
-	int i, err;
-
-	snic->pdev = adapter->pdev;
-	snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
-
-	err = cxgb3i_adapter_ddp_info(t3dev, &snic->tag_format,
-				    &snic->tx_max_size,
-				    &snic->rx_max_size);
-	if (err < 0)
-		return err;
-
-	for_each_port(adapter, i) {
-		snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]);
-		if (!snic->hba[i])
-			return -EINVAL;
-	}
-	snic->hba_cnt = adapter->params.nports;
-
-	/* add to the list */
-	write_lock(&cxgb3i_snic_rwlock);
-	list_add_tail(&snic->list_head, &cxgb3i_snic_list);
-	write_unlock(&cxgb3i_snic_rwlock);
-
-	cxgb3i_log_info("t3dev 0x%p open, snic 0x%p, %u scsi hosts added.\n",
-			t3dev, snic, snic->hba_cnt);
-	return 0;
-}
-
-/**
- * cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings
- * @t3dev: t3cdev adapter
- */
-void cxgb3i_adapter_open(struct t3cdev *t3dev)
-{
-	struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
-	int err;
-
-	if (snic)
-		err = adapter_update(snic);
-	else {
-		snic = kzalloc(sizeof(*snic), GFP_KERNEL);
-		if (snic) {
-			spin_lock_init(&snic->lock);
-			snic->tdev = t3dev;
-			err = adapter_add(snic);
-		} else
-			err = -ENOMEM;
-	}
-
-	if (err < 0) {
-		cxgb3i_log_info("snic 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
-				snic, snic ? snic->flags : 0, t3dev, err);
-		if (snic) {
-			snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
-			cxgb3i_adapter_close(t3dev);
-		}
-	}
-}
-
-/**
- * cxgb3i_adapter_close - release the resources held and cleanup h/w settings
- * @t3dev: t3cdev adapter
- */
-void cxgb3i_adapter_close(struct t3cdev *t3dev)
-{
-	struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
-	int i;
-
-	if (!snic || snic->flags & CXGB3I_ADAPTER_FLAG_RESET) {
-		cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, f 0x%x.\n",
-				t3dev, snic, snic ? snic->flags : 0);
-		return;
-	}
-
-	/* remove from the list */
-	write_lock(&cxgb3i_snic_rwlock);
-	list_del(&snic->list_head);
-	write_unlock(&cxgb3i_snic_rwlock);
-
-	for (i = 0; i < snic->hba_cnt; i++) {
-		if (snic->hba[i]) {
-			cxgb3i_hba_host_remove(snic->hba[i]);
-			snic->hba[i] = NULL;
-		}
-	}
-	cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, %u scsi hosts removed.\n",
-			t3dev, snic, snic->hba_cnt);
-	kfree(snic);
-}
-
-/**
- * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device
- * @t3dev: t3cdev adapter
- */
-static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
-{
-	struct cxgb3i_adapter *snic;
-	int i;
-
-	if (ndev->priv_flags & IFF_802_1Q_VLAN)
-		ndev = vlan_dev_real_dev(ndev);
-
-	read_lock(&cxgb3i_snic_rwlock);
-	list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
-		for (i = 0; i < snic->hba_cnt; i++) {
-			if (snic->hba[i]->ndev == ndev) {
-				read_unlock(&cxgb3i_snic_rwlock);
-				return snic->hba[i];
-			}
-		}
-	}
-	read_unlock(&cxgb3i_snic_rwlock);
-	return NULL;
-}
-
-/**
- * cxgb3i_hba_host_add - register a new host with scsi/iscsi
- * @snic: the cxgb3i adapter
- * @ndev: associated net_device
- */
-struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
-				       struct net_device *ndev)
-{
-	struct cxgb3i_hba *hba;
-	struct Scsi_Host *shost;
-	int err;
-
-	shost = iscsi_host_alloc(&cxgb3i_host_template,
-				 sizeof(struct cxgb3i_hba), 1);
-	if (!shost) {
-		cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_alloc failed.\n",
-				snic, ndev);
-		return NULL;
-	}
-
-	shost->transportt = cxgb3i_scsi_transport;
-	shost->max_lun = CXGB3I_MAX_LUN;
-	shost->max_id = CXGB3I_MAX_TARGET;
-	shost->max_channel = 0;
-	shost->max_cmd_len = 16;
-
-	hba = iscsi_host_priv(shost);
-	hba->snic = snic;
-	hba->ndev = ndev;
-	hba->shost = shost;
-
-	pci_dev_get(snic->pdev);
-	err = iscsi_host_add(shost, &snic->pdev->dev);
-	if (err) {
-		cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_add failed.\n",
-				snic, ndev);
-		goto pci_dev_put;
-	}
-
-	cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
-			 shost, hba, shost->host_no);
-
-	return hba;
-
-pci_dev_put:
-	pci_dev_put(snic->pdev);
-	scsi_host_put(shost);
-	return NULL;
-}
-
-/**
- * cxgb3i_hba_host_remove - de-register the host with scsi/iscsi
- * @hba: the cxgb3i hba
- */
-void cxgb3i_hba_host_remove(struct cxgb3i_hba *hba)
-{
-	cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
-			 hba->shost, hba, hba->shost->host_no);
-	iscsi_host_remove(hba->shost);
-	pci_dev_put(hba->snic->pdev);
-	iscsi_host_free(hba->shost);
-}
-
-/**
- * cxgb3i_ep_connect - establish TCP connection to target portal
- * @shost:		scsi host to use
- * @dst_addr:		target IP address
- * @non_blocking:	blocking or non-blocking call
- *
- * Initiates a TCP/IP connection to the dst_addr
- */
-static struct iscsi_endpoint *cxgb3i_ep_connect(struct Scsi_Host *shost,
-						struct sockaddr *dst_addr,
-						int non_blocking)
-{
-	struct iscsi_endpoint *ep;
-	struct cxgb3i_endpoint *cep;
-	struct cxgb3i_hba *hba = NULL;
-	struct s3_conn *c3cn = NULL;
-	int err = 0;
-
-	if (shost)
-		hba = iscsi_host_priv(shost);
-
-	cxgb3i_api_debug("shost 0x%p, hba 0x%p.\n", shost, hba);
-
-	c3cn = cxgb3i_c3cn_create();
-	if (!c3cn) {
-		cxgb3i_log_info("ep connect OOM.\n");
-		err = -ENOMEM;
-		goto release_conn;
-	}
-
-	err = cxgb3i_c3cn_connect(hba ? hba->ndev : NULL, c3cn,
-				 (struct sockaddr_in *)dst_addr);
-	if (err < 0) {
-		cxgb3i_log_info("ep connect failed.\n");
-		goto release_conn;
-	}
-
-	hba = cxgb3i_hba_find_by_netdev(c3cn->dst_cache->dev);
-	if (!hba) {
-		err = -ENOSPC;
-		cxgb3i_log_info("NOT going through cxgbi device.\n");
-		goto release_conn;
-	}
-
-	if (shost && hba != iscsi_host_priv(shost)) {
-		err = -ENOSPC;
-		cxgb3i_log_info("Could not connect through request host%u\n",
-				shost->host_no);
-		goto release_conn;
-	}
-
-	if (c3cn_is_closing(c3cn)) {
-		err = -ENOSPC;
-		cxgb3i_log_info("ep connect unable to connect.\n");
-		goto release_conn;
-	}
-
-	ep = iscsi_create_endpoint(sizeof(*cep));
-	if (!ep) {
-		err = -ENOMEM;
-		cxgb3i_log_info("iscsi alloc ep, OOM.\n");
-		goto release_conn;
-	}
-	cep = ep->dd_data;
-	cep->c3cn = c3cn;
-	cep->hba = hba;
-
-	cxgb3i_api_debug("ep 0x%p, 0x%p, c3cn 0x%p, hba 0x%p.\n",
-			  ep, cep, c3cn, hba);
-	return ep;
-
-release_conn:
-	cxgb3i_api_debug("conn 0x%p failed, release.\n", c3cn);
-	if (c3cn)
-		cxgb3i_c3cn_release(c3cn);
-	return ERR_PTR(err);
-}
-
-/**
- * cxgb3i_ep_poll - polls for TCP connection establishement
- * @ep:		TCP connection (endpoint) handle
- * @timeout_ms:	timeout value in milli secs
- *
- * polls for TCP connect request to complete
- */
-static int cxgb3i_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
-{
-	struct cxgb3i_endpoint *cep = ep->dd_data;
-	struct s3_conn *c3cn = cep->c3cn;
-
-	if (!c3cn_is_established(c3cn))
-		return 0;
-	cxgb3i_api_debug("ep 0x%p, c3cn 0x%p established.\n", ep, c3cn);
-	return 1;
-}
-
-/**
- * cxgb3i_ep_disconnect - teardown TCP connection
- * @ep:		TCP connection (endpoint) handle
- *
- * teardown TCP connection
- */
-static void cxgb3i_ep_disconnect(struct iscsi_endpoint *ep)
-{
-	struct cxgb3i_endpoint *cep = ep->dd_data;
-	struct cxgb3i_conn *cconn = cep->cconn;
-
-	cxgb3i_api_debug("ep 0x%p, cep 0x%p.\n", ep, cep);
-
-	if (cconn && cconn->conn) {
-		/*
-		 * stop the xmit path so the xmit_pdu function is
-		 * not being called
-		 */
-		iscsi_suspend_tx(cconn->conn);
-
-		write_lock_bh(&cep->c3cn->callback_lock);
-		cep->c3cn->user_data = NULL;
-		cconn->cep = NULL;
-		write_unlock_bh(&cep->c3cn->callback_lock);
-	}
-
-	cxgb3i_api_debug("ep 0x%p, cep 0x%p, release c3cn 0x%p.\n",
-			 ep, cep, cep->c3cn);
-	cxgb3i_c3cn_release(cep->c3cn);
-	iscsi_destroy_endpoint(ep);
-}
-
-/**
- * cxgb3i_session_create - create a new iscsi session
- * @cmds_max:		max # of commands
- * @qdepth:		scsi queue depth
- * @initial_cmdsn:	initial iscsi CMDSN for this session
- *
- * Creates a new iSCSI session
- */
-static struct iscsi_cls_session *
-cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
-		      u32 initial_cmdsn)
-{
-	struct cxgb3i_endpoint *cep;
-	struct cxgb3i_hba *hba;
-	struct Scsi_Host *shost;
-	struct iscsi_cls_session *cls_session;
-	struct iscsi_session *session;
-
-	if (!ep) {
-		cxgb3i_log_error("%s, missing endpoint.\n", __func__);
-		return NULL;
-	}
-
-	cep = ep->dd_data;
-	hba = cep->hba;
-	shost = hba->shost;
-	cxgb3i_api_debug("ep 0x%p, cep 0x%p, hba 0x%p.\n", ep, cep, hba);
-	BUG_ON(hba != iscsi_host_priv(shost));
-
-	cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost,
-					  cmds_max, 0,
-					  sizeof(struct iscsi_tcp_task) +
-					  sizeof(struct cxgb3i_task_data),
-					  initial_cmdsn, ISCSI_MAX_TARGET);
-	if (!cls_session)
-		return NULL;
-	session = cls_session->dd_data;
-	if (iscsi_tcp_r2tpool_alloc(session))
-		goto remove_session;
-
-	return cls_session;
-
-remove_session:
-	iscsi_session_teardown(cls_session);
-	return NULL;
-}
-
-/**
- * cxgb3i_session_destroy - destroys iscsi session
- * @cls_session:	pointer to iscsi cls session
- *
- * Destroys an iSCSI session instance and releases its all resources held
- */
-static void cxgb3i_session_destroy(struct iscsi_cls_session *cls_session)
-{
-	cxgb3i_api_debug("sess 0x%p.\n", cls_session);
-	iscsi_tcp_r2tpool_free(cls_session->dd_data);
-	iscsi_session_teardown(cls_session);
-}
-
-/**
- * cxgb3i_conn_max_xmit_dlength -- calc the max. xmit pdu segment size
- * @conn: iscsi connection
- * check the max. xmit pdu payload, reduce it if needed
- */
-static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn)
-
-{
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM);
-
-	max = min(cconn->hba->snic->tx_max_size, max);
-	if (conn->max_xmit_dlength)
-		conn->max_xmit_dlength = min(conn->max_xmit_dlength, max);
-	else
-		conn->max_xmit_dlength = max;
-	align_pdu_size(conn->max_xmit_dlength);
-	cxgb3i_api_debug("conn 0x%p, max xmit %u.\n",
-			 conn, conn->max_xmit_dlength);
-	return 0;
-}
-
-/**
- * cxgb3i_conn_max_recv_dlength -- check the max. recv pdu segment size
- * @conn: iscsi connection
- * return 0 if the value is valid, < 0 otherwise.
- */
-static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn)
-{
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	unsigned int max = cconn->hba->snic->rx_max_size;
-
-	align_pdu_size(max);
-	if (conn->max_recv_dlength) {
-		if (conn->max_recv_dlength > max) {
-			cxgb3i_log_error("MaxRecvDataSegmentLength %u too big."
-					 " Need to be <= %u.\n",
-					 conn->max_recv_dlength, max);
-			return -EINVAL;
-		}
-		conn->max_recv_dlength = min(conn->max_recv_dlength, max);
-		align_pdu_size(conn->max_recv_dlength);
-	} else
-		conn->max_recv_dlength = max;
-	cxgb3i_api_debug("conn 0x%p, max recv %u.\n",
-			 conn, conn->max_recv_dlength);
-	return 0;
-}
-
-/**
- * cxgb3i_conn_create - create iscsi connection instance
- * @cls_session:	pointer to iscsi cls session
- * @cid:		iscsi cid
- *
- * Creates a new iSCSI connection instance for a given session
- */
-static struct iscsi_cls_conn *cxgb3i_conn_create(struct iscsi_cls_session
-						 *cls_session, u32 cid)
-{
-	struct iscsi_cls_conn *cls_conn;
-	struct iscsi_conn *conn;
-	struct iscsi_tcp_conn *tcp_conn;
-	struct cxgb3i_conn *cconn;
-
-	cxgb3i_api_debug("sess 0x%p, cid %u.\n", cls_session, cid);
-
-	cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*cconn), cid);
-	if (!cls_conn)
-		return NULL;
-	conn = cls_conn->dd_data;
-	tcp_conn = conn->dd_data;
-	cconn = tcp_conn->dd_data;
-
-	cconn->conn = conn;
-	return cls_conn;
-}
-
-/**
- * cxgb3i_conn_bind - binds iscsi sess, conn and endpoint together
- * @cls_session:	pointer to iscsi cls session
- * @cls_conn:		pointer to iscsi cls conn
- * @transport_eph:	64-bit EP handle
- * @is_leading:		leading connection on this session?
- *
- * Binds together an iSCSI session, an iSCSI connection and a
- *	TCP connection. This routine returns error code if the TCP
- *	connection does not belong on the device iSCSI sess/conn is bound
- */
-
-static int cxgb3i_conn_bind(struct iscsi_cls_session *cls_session,
-			    struct iscsi_cls_conn *cls_conn,
-			    u64 transport_eph, int is_leading)
-{
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct cxgb3i_adapter *snic;
-	struct iscsi_endpoint *ep;
-	struct cxgb3i_endpoint *cep;
-	struct s3_conn *c3cn;
-	int err;
-
-	ep = iscsi_lookup_endpoint(transport_eph);
-	if (!ep)
-		return -EINVAL;
-
-	/* setup ddp pagesize */
-	cep = ep->dd_data;
-	c3cn = cep->c3cn;
-	snic = cep->hba->snic;
-	err = cxgb3i_setup_conn_host_pagesize(snic->tdev, c3cn->tid, 0);
-	if (err < 0)
-		return err;
-
-	cxgb3i_api_debug("ep 0x%p, cls sess 0x%p, cls conn 0x%p.\n",
-			 ep, cls_session, cls_conn);
-
-	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
-	if (err)
-		return -EINVAL;
-
-	/* calculate the tag idx bits needed for this conn based on cmds_max */
-	cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1;
-	cxgb3i_api_debug("session cmds_max 0x%x, bits %u.\n",
-			 conn->session->cmds_max, cconn->task_idx_bits);
-
-	read_lock(&c3cn->callback_lock);
-	c3cn->user_data = conn;
-	cconn->hba = cep->hba;
-	cconn->cep = cep;
-	cep->cconn = cconn;
-	read_unlock(&c3cn->callback_lock);
-
-	cxgb3i_conn_max_xmit_dlength(conn);
-	cxgb3i_conn_max_recv_dlength(conn);
-
-	spin_lock_bh(&conn->session->lock);
-	sprintf(conn->portal_address, "%pI4", &c3cn->daddr.sin_addr.s_addr);
-	conn->portal_port = ntohs(c3cn->daddr.sin_port);
-	spin_unlock_bh(&conn->session->lock);
-
-	/* init recv engine */
-	iscsi_tcp_hdr_recv_prep(tcp_conn);
-
-	return 0;
-}
-
-/**
- * cxgb3i_conn_get_param - return iscsi connection parameter to caller
- * @cls_conn:	pointer to iscsi cls conn
- * @param:	parameter type identifier
- * @buf:	buffer pointer
- *
- * returns iSCSI connection parameters
- */
-static int cxgb3i_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;
-
-	cxgb3i_api_debug("cls_conn 0x%p, param %d.\n", cls_conn, param);
-
-	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);
-		spin_unlock_bh(&conn->session->lock);
-		break;
-	default:
-		return iscsi_conn_get_param(cls_conn, param, buf);
-	}
-
-	return len;
-}
-
-/**
- * cxgb3i_conn_set_param - set iscsi connection parameter
- * @cls_conn:	pointer to iscsi cls conn
- * @param:	parameter type identifier
- * @buf:	buffer pointer
- * @buflen:	buffer length
- *
- * set iSCSI connection parameters
- */
-static int cxgb3i_conn_set_param(struct iscsi_cls_conn *cls_conn,
-				 enum iscsi_param param, char *buf, int buflen)
-{
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct iscsi_session *session = conn->session;
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct cxgb3i_adapter *snic = cconn->hba->snic;
-	struct s3_conn *c3cn = cconn->cep->c3cn;
-	int value, err = 0;
-
-	switch (param) {
-	case ISCSI_PARAM_HDRDGST_EN:
-		err = iscsi_set_param(cls_conn, param, buf, buflen);
-		if (!err && conn->hdrdgst_en)
-			err = cxgb3i_setup_conn_digest(snic->tdev, c3cn->tid,
-							conn->hdrdgst_en,
-							conn->datadgst_en, 0);
-		break;
-	case ISCSI_PARAM_DATADGST_EN:
-		err = iscsi_set_param(cls_conn, param, buf, buflen);
-		if (!err && conn->datadgst_en)
-			err = cxgb3i_setup_conn_digest(snic->tdev, c3cn->tid,
-							conn->hdrdgst_en,
-							conn->datadgst_en, 0);
-		break;
-	case ISCSI_PARAM_MAX_R2T:
-		sscanf(buf, "%d", &value);
-		if (value <= 0 || !is_power_of_2(value))
-			return -EINVAL;
-		if (session->max_r2t == value)
-			break;
-		iscsi_tcp_r2tpool_free(session);
-		err = iscsi_set_param(cls_conn, param, buf, buflen);
-		if (!err && iscsi_tcp_r2tpool_alloc(session))
-			return -ENOMEM;
-	case ISCSI_PARAM_MAX_RECV_DLENGTH:
-		err = iscsi_set_param(cls_conn, param, buf, buflen);
-		if (!err)
-			err = cxgb3i_conn_max_recv_dlength(conn);
-		break;
-	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
-		err = iscsi_set_param(cls_conn, param, buf, buflen);
-		if (!err)
-			err = cxgb3i_conn_max_xmit_dlength(conn);
-		break;
-	default:
-		return iscsi_set_param(cls_conn, param, buf, buflen);
-	}
-	return err;
-}
-
-/**
- * cxgb3i_host_set_param - configure host (adapter) related parameters
- * @shost:	scsi host pointer
- * @param:	parameter type identifier
- * @buf:	buffer pointer
- */
-static int cxgb3i_host_set_param(struct Scsi_Host *shost,
-				 enum iscsi_host_param param,
-				 char *buf, int buflen)
-{
-	struct cxgb3i_hba *hba = iscsi_host_priv(shost);
-
-	if (!hba->ndev) {
-		shost_printk(KERN_ERR, shost, "Could not set host param. "
-			     "Netdev for host not set.\n");
-		return -ENODEV;
-	}
-
-	cxgb3i_api_debug("param %d, buf %s.\n", param, buf);
-
-	switch (param) {
-	case ISCSI_HOST_PARAM_IPADDRESS:
-	{
-		__be32 addr = in_aton(buf);
-		cxgb3i_set_private_ipv4addr(hba->ndev, addr);
-		return 0;
-	}
-	case ISCSI_HOST_PARAM_HWADDRESS:
-	case ISCSI_HOST_PARAM_NETDEV_NAME:
-		/* ignore */
-		return 0;
-	default:
-		return iscsi_host_set_param(shost, param, buf, buflen);
-	}
-}
-
-/**
- * cxgb3i_host_get_param - returns host (adapter) related parameters
- * @shost:	scsi host pointer
- * @param:	parameter type identifier
- * @buf:	buffer pointer
- */
-static int cxgb3i_host_get_param(struct Scsi_Host *shost,
-				 enum iscsi_host_param param, char *buf)
-{
-	struct cxgb3i_hba *hba = iscsi_host_priv(shost);
-	int len = 0;
-
-	if (!hba->ndev) {
-		shost_printk(KERN_ERR, shost, "Could not set host param. "
-			     "Netdev for host not set.\n");
-		return -ENODEV;
-	}
-
-	cxgb3i_api_debug("hba %s, param %d.\n", hba->ndev->name, param);
-
-	switch (param) {
-	case ISCSI_HOST_PARAM_HWADDRESS:
-		len = sysfs_format_mac(buf, hba->ndev->dev_addr, 6);
-		break;
-	case ISCSI_HOST_PARAM_NETDEV_NAME:
-		len = sprintf(buf, "%s\n", hba->ndev->name);
-		break;
-	case ISCSI_HOST_PARAM_IPADDRESS:
-	{
-		__be32 addr;
-
-		addr = cxgb3i_get_private_ipv4addr(hba->ndev);
-		len = sprintf(buf, "%pI4", &addr);
-		break;
-	}
-	default:
-		return iscsi_host_get_param(shost, param, buf);
-	}
-	return len;
-}
-
-/**
- * cxgb3i_conn_get_stats - returns iSCSI stats
- * @cls_conn:	pointer to iscsi cls conn
- * @stats:	pointer to iscsi statistic struct
- */
-static void cxgb3i_conn_get_stats(struct iscsi_cls_conn *cls_conn,
-				  struct iscsi_stats *stats)
-{
-	struct iscsi_conn *conn = cls_conn->dd_data;
-
-	stats->txdata_octets = conn->txdata_octets;
-	stats->rxdata_octets = conn->rxdata_octets;
-	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
-	stats->dataout_pdus = conn->dataout_pdus_cnt;
-	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
-	stats->datain_pdus = conn->datain_pdus_cnt;
-	stats->r2t_pdus = conn->r2t_pdus_cnt;
-	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
-	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
-	stats->digest_err = 0;
-	stats->timeout_err = 0;
-	stats->custom_length = 1;
-	strcpy(stats->custom[0].desc, "eh_abort_cnt");
-	stats->custom[0].value = conn->eh_abort_cnt;
-}
-
-/**
- * cxgb3i_parse_itt - get the idx and age bits from a given tag
- * @conn:	iscsi connection
- * @itt:	itt tag
- * @idx:	task index, filled in by this function
- * @age:	session age, filled in by this function
- */
-static void cxgb3i_parse_itt(struct iscsi_conn *conn, itt_t itt,
-			     int *idx, int *age)
-{
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct cxgb3i_adapter *snic = cconn->hba->snic;
-	u32 tag = ntohl((__force u32) itt);
-	u32 sw_bits;
-
-	sw_bits = cxgb3i_tag_nonrsvd_bits(&snic->tag_format, tag);
-	if (idx)
-		*idx = sw_bits & ((1 << cconn->task_idx_bits) - 1);
-	if (age)
-		*age = (sw_bits >> cconn->task_idx_bits) & ISCSI_AGE_MASK;
-
-	cxgb3i_tag_debug("parse tag 0x%x/0x%x, sw 0x%x, itt 0x%x, age 0x%x.\n",
-			 tag, itt, sw_bits, idx ? *idx : 0xFFFFF,
-			 age ? *age : 0xFF);
-}
-
-/**
- * cxgb3i_reserve_itt - generate tag for a give task
- * @task: iscsi task
- * @hdr_itt: tag, filled in by this function
- * Set up ddp for scsi read tasks if possible.
- */
-int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt)
-{
-	struct scsi_cmnd *sc = task->sc;
-	struct iscsi_conn *conn = task->conn;
-	struct iscsi_session *sess = conn->session;
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct cxgb3i_adapter *snic = cconn->hba->snic;
-	struct cxgb3i_tag_format *tformat = &snic->tag_format;
-	u32 sw_tag = (sess->age << cconn->task_idx_bits) | task->itt;
-	u32 tag;
-	int err = -EINVAL;
-
-	if (sc &&
-	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) &&
-	    cxgb3i_sw_tag_usable(tformat, sw_tag)) {
-		struct s3_conn *c3cn = cconn->cep->c3cn;
-		struct cxgb3i_gather_list *gl;
-
-		gl = cxgb3i_ddp_make_gl(scsi_in(sc)->length,
-					scsi_in(sc)->table.sgl,
-					scsi_in(sc)->table.nents,
-					snic->pdev,
-					GFP_ATOMIC);
-		if (gl) {
-			tag = sw_tag;
-			err = cxgb3i_ddp_tag_reserve(snic->tdev, c3cn->tid,
-						     tformat, &tag,
-						     gl, GFP_ATOMIC);
-			if (err < 0)
-				cxgb3i_ddp_release_gl(gl, snic->pdev);
-		}
-	}
-
-	if (err < 0)
-		tag = cxgb3i_set_non_ddp_tag(tformat, sw_tag);
-	/* the itt need to sent in big-endian order */
-	*hdr_itt = (__force itt_t)htonl(tag);
-
-	cxgb3i_tag_debug("new tag 0x%x/0x%x (itt 0x%x, age 0x%x).\n",
-			 tag, *hdr_itt, task->itt, sess->age);
-	return 0;
-}
-
-/**
- * cxgb3i_release_itt - release the tag for a given task
- * @task:	iscsi task
- * @hdr_itt:	tag
- * If the tag is a ddp tag, release the ddp setup
- */
-void cxgb3i_release_itt(struct iscsi_task *task, itt_t hdr_itt)
-{
-	struct scsi_cmnd *sc = task->sc;
-	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct cxgb3i_adapter *snic = cconn->hba->snic;
-	struct cxgb3i_tag_format *tformat = &snic->tag_format;
-	u32 tag = ntohl((__force u32)hdr_itt);
-
-	cxgb3i_tag_debug("release tag 0x%x.\n", tag);
-
-	if (sc &&
-	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) &&
-	    cxgb3i_is_ddp_tag(tformat, tag))
-		cxgb3i_ddp_tag_release(snic->tdev, tag);
-}
-
-/**
- * cxgb3i_host_template -- Scsi_Host_Template structure
- *	used when registering with the scsi mid layer
- */
-static struct scsi_host_template cxgb3i_host_template = {
-	.module			= THIS_MODULE,
-	.name			= "Chelsio S3xx iSCSI Initiator",
-	.proc_name		= "cxgb3i",
-	.queuecommand		= iscsi_queuecommand,
-	.change_queue_depth	= iscsi_change_queue_depth,
-	.can_queue		= CXGB3I_SCSI_HOST_QDEPTH,
-	.sg_tablesize		= SG_ALL,
-	.max_sectors		= 0xFFFF,
-	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
-	.eh_abort_handler	= iscsi_eh_abort,
-	.eh_device_reset_handler = iscsi_eh_device_reset,
-	.eh_target_reset_handler = iscsi_eh_recover_target,
-	.target_alloc		= iscsi_target_alloc,
-	.use_clustering		= DISABLE_CLUSTERING,
-	.this_id		= -1,
-};
-
-static struct iscsi_transport cxgb3i_iscsi_transport = {
-	.owner			= THIS_MODULE,
-	.name			= "cxgb3i",
-	.caps			= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
-				| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
-				CAP_PADDING_OFFLOAD,
-	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
-				ISCSI_MAX_XMIT_DLENGTH |
-				ISCSI_HDRDGST_EN |
-				ISCSI_DATADGST_EN |
-				ISCSI_INITIAL_R2T_EN |
-				ISCSI_MAX_R2T |
-				ISCSI_IMM_DATA_EN |
-				ISCSI_FIRST_BURST |
-				ISCSI_MAX_BURST |
-				ISCSI_PDU_INORDER_EN |
-				ISCSI_DATASEQ_INORDER_EN |
-				ISCSI_ERL |
-				ISCSI_CONN_PORT |
-				ISCSI_CONN_ADDRESS |
-				ISCSI_EXP_STATSN |
-				ISCSI_PERSISTENT_PORT |
-				ISCSI_PERSISTENT_ADDRESS |
-				ISCSI_TARGET_NAME | ISCSI_TPGT |
-				ISCSI_USERNAME | ISCSI_PASSWORD |
-				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
-				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
-				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
-				ISCSI_PING_TMO | ISCSI_RECV_TMO |
-				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
-	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
-			ISCSI_HOST_INITIATOR_NAME | ISCSI_HOST_NETDEV_NAME,
-	.get_host_param		= cxgb3i_host_get_param,
-	.set_host_param		= cxgb3i_host_set_param,
-	/* session management */
-	.create_session		= cxgb3i_session_create,
-	.destroy_session	= cxgb3i_session_destroy,
-	.get_session_param	= iscsi_session_get_param,
-	/* connection management */
-	.create_conn		= cxgb3i_conn_create,
-	.bind_conn		= cxgb3i_conn_bind,
-	.destroy_conn		= iscsi_tcp_conn_teardown,
-	.start_conn		= iscsi_conn_start,
-	.stop_conn		= iscsi_conn_stop,
-	.get_conn_param		= cxgb3i_conn_get_param,
-	.set_param		= cxgb3i_conn_set_param,
-	.get_stats		= cxgb3i_conn_get_stats,
-	/* pdu xmit req. from user space */
-	.send_pdu		= iscsi_conn_send_pdu,
-	/* task */
-	.init_task		= iscsi_tcp_task_init,
-	.xmit_task		= iscsi_tcp_task_xmit,
-	.cleanup_task		= cxgb3i_conn_cleanup_task,
-
-	/* pdu */
-	.alloc_pdu		= cxgb3i_conn_alloc_pdu,
-	.init_pdu		= cxgb3i_conn_init_pdu,
-	.xmit_pdu		= cxgb3i_conn_xmit_pdu,
-	.parse_pdu_itt		= cxgb3i_parse_itt,
-
-	/* TCP connect/disconnect */
-	.ep_connect		= cxgb3i_ep_connect,
-	.ep_poll		= cxgb3i_ep_poll,
-	.ep_disconnect		= cxgb3i_ep_disconnect,
-	/* Error recovery timeout call */
-	.session_recovery_timedout = iscsi_session_recovery_timedout,
-};
-
-int cxgb3i_iscsi_init(void)
-{
-	sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
-	sw_tag_age_bits = (__ilog2_u32(ISCSI_AGE_MASK)) + 1;
-	cxgb3i_log_info("tag itt 0x%x, %u bits, age 0x%x, %u bits.\n",
-			ISCSI_ITT_MASK, sw_tag_idx_bits,
-			ISCSI_AGE_MASK, sw_tag_age_bits);
-
-	cxgb3i_scsi_transport =
-	    iscsi_register_transport(&cxgb3i_iscsi_transport);
-	if (!cxgb3i_scsi_transport) {
-		cxgb3i_log_error("Could not register cxgb3i transport.\n");
-		return -ENODEV;
-	}
-	cxgb3i_api_debug("cxgb3i transport 0x%p.\n", cxgb3i_scsi_transport);
-	return 0;
-}
-
-void cxgb3i_iscsi_cleanup(void)
-{
-	if (cxgb3i_scsi_transport) {
-		cxgb3i_api_debug("cxgb3i transport 0x%p.\n",
-				 cxgb3i_scsi_transport);
-		iscsi_unregister_transport(&cxgb3i_iscsi_transport);
-	}
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c
deleted file mode 100644
index 3ee13cf..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.c
+++ /dev/null
@@ -1,1944 +0,0 @@
-/*
- * cxgb3i_offload.c: Chelsio S3xx iscsi offloaded tcp connection management
- *
- * Copyright (C) 2003-2008 Chelsio Communications.  All rights reserved.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
- * release for licensing terms and conditions.
- *
- * Written by:	Dimitris Michailidis (dm@chelsio.com)
- *		Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/if_vlan.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-
-#include "cxgb3_defs.h"
-#include "cxgb3_ctl_defs.h"
-#include "firmware_exports.h"
-#include "cxgb3i_offload.h"
-#include "cxgb3i_pdu.h"
-#include "cxgb3i_ddp.h"
-
-#ifdef __DEBUG_C3CN_CONN__
-#define c3cn_conn_debug		cxgb3i_log_debug
-#else
-#define c3cn_conn_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_C3CN_TX__
-#define c3cn_tx_debug		cxgb3i_log_debug
-#else
-#define c3cn_tx_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_C3CN_RX__
-#define c3cn_rx_debug		cxgb3i_log_debug
-#else
-#define c3cn_rx_debug(fmt...)
-#endif
-
-/*
- * module parameters releated to offloaded iscsi connection
- */
-static int cxgb3_rcv_win = 256 * 1024;
-module_param(cxgb3_rcv_win, int, 0644);
-MODULE_PARM_DESC(cxgb3_rcv_win, "TCP receive window in bytes (default=256KB)");
-
-static int cxgb3_snd_win = 128 * 1024;
-module_param(cxgb3_snd_win, int, 0644);
-MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=128KB)");
-
-static int cxgb3_rx_credit_thres = 10 * 1024;
-module_param(cxgb3_rx_credit_thres, int, 0644);
-MODULE_PARM_DESC(rx_credit_thres,
-		 "RX credits return threshold in bytes (default=10KB)");
-
-static unsigned int cxgb3_max_connect = 8 * 1024;
-module_param(cxgb3_max_connect, uint, 0644);
-MODULE_PARM_DESC(cxgb3_max_connect, "Max. # of connections (default=8092)");
-
-static unsigned int cxgb3_sport_base = 20000;
-module_param(cxgb3_sport_base, uint, 0644);
-MODULE_PARM_DESC(cxgb3_sport_base, "starting port number (default=20000)");
-
-/*
- * cxgb3i tcp connection data(per adapter) list
- */
-static LIST_HEAD(cdata_list);
-static DEFINE_RWLOCK(cdata_rwlock);
-
-static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion);
-static void c3cn_release_offload_resources(struct s3_conn *c3cn);
-
-/*
- * iscsi source port management
- *
- * Find a free source port in the port allocation map. We use a very simple
- * rotor scheme to look for the next free port.
- *
- * If a source port has been specified make sure that it doesn't collide with
- * our normal source port allocation map.  If it's outside the range of our
- * allocation/deallocation scheme just let them use it.
- *
- * If the source port is outside our allocation range, the caller is
- * responsible for keeping track of their port usage.
- */
-static int c3cn_get_port(struct s3_conn *c3cn, struct cxgb3i_sdev_data *cdata)
-{
-	unsigned int start;
-	int idx;
-
-	if (!cdata)
-		goto error_out;
-
-	if (c3cn->saddr.sin_port) {
-		cxgb3i_log_error("connect, sin_port NON-ZERO %u.\n",
-				 c3cn->saddr.sin_port);
-		return -EADDRINUSE;
-	}
-
-	spin_lock_bh(&cdata->lock);
-	start = idx = cdata->sport_next;
-	do {
-		if (++idx >= cxgb3_max_connect)
-			idx = 0;
-		if (!cdata->sport_conn[idx]) {
-			c3cn->saddr.sin_port = htons(cxgb3_sport_base + idx);
-			cdata->sport_next = idx;
-			cdata->sport_conn[idx] = c3cn;
-			spin_unlock_bh(&cdata->lock);
-
-			c3cn_conn_debug("%s reserve port %u.\n",
-					cdata->cdev->name,
-					cxgb3_sport_base + idx);
-			return 0;
-		}
-	} while (idx != start);
-	spin_unlock_bh(&cdata->lock);
-
-error_out:
-	return -EADDRNOTAVAIL;
-}
-
-static void c3cn_put_port(struct s3_conn *c3cn)
-{
-	if (!c3cn->cdev)
-		return;
-
-	if (c3cn->saddr.sin_port) {
-		struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(c3cn->cdev);
-		int idx = ntohs(c3cn->saddr.sin_port) - cxgb3_sport_base;
-
-		c3cn->saddr.sin_port = 0;
-		if (idx < 0 || idx >= cxgb3_max_connect)
-			return;
-		spin_lock_bh(&cdata->lock);
-		cdata->sport_conn[idx] = NULL;
-		spin_unlock_bh(&cdata->lock);
-		c3cn_conn_debug("%s, release port %u.\n",
-				cdata->cdev->name, cxgb3_sport_base + idx);
-	}
-}
-
-static inline void c3cn_set_flag(struct s3_conn *c3cn, enum c3cn_flags flag)
-{
-	__set_bit(flag, &c3cn->flags);
-	c3cn_conn_debug("c3cn 0x%p, set %d, s %u, f 0x%lx.\n",
-			c3cn, flag, c3cn->state, c3cn->flags);
-}
-
-static inline void c3cn_clear_flag(struct s3_conn *c3cn, enum c3cn_flags flag)
-{
-	__clear_bit(flag, &c3cn->flags);
-	c3cn_conn_debug("c3cn 0x%p, clear %d, s %u, f 0x%lx.\n",
-			c3cn, flag, c3cn->state, c3cn->flags);
-}
-
-static inline int c3cn_flag(struct s3_conn *c3cn, enum c3cn_flags flag)
-{
-	if (c3cn == NULL)
-		return 0;
-	return test_bit(flag, &c3cn->flags);
-}
-
-static void c3cn_set_state(struct s3_conn *c3cn, int state)
-{
-	c3cn_conn_debug("c3cn 0x%p state -> %u.\n", c3cn, state);
-	c3cn->state = state;
-}
-
-static inline void c3cn_hold(struct s3_conn *c3cn)
-{
-	atomic_inc(&c3cn->refcnt);
-}
-
-static inline void c3cn_put(struct s3_conn *c3cn)
-{
-	if (atomic_dec_and_test(&c3cn->refcnt)) {
-		c3cn_conn_debug("free c3cn 0x%p, s %u, f 0x%lx.\n",
-				c3cn, c3cn->state, c3cn->flags);
-		kfree(c3cn);
-	}
-}
-
-static void c3cn_closed(struct s3_conn *c3cn)
-{
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			 c3cn, c3cn->state, c3cn->flags);
-
-	c3cn_put_port(c3cn);
-	c3cn_release_offload_resources(c3cn);
-	c3cn_set_state(c3cn, C3CN_STATE_CLOSED);
-	cxgb3i_conn_closing(c3cn);
-}
-
-/*
- * CPL (Chelsio Protocol Language) defines a message passing interface between
- * the host driver and T3 asic.
- * The section below implments CPLs that related to iscsi tcp connection
- * open/close/abort and data send/receive.
- */
-
-/*
- * CPL connection active open request: host ->
- */
-static unsigned int find_best_mtu(const struct t3c_data *d, unsigned short mtu)
-{
-	int i = 0;
-
-	while (i < d->nmtus - 1 && d->mtus[i + 1] <= mtu)
-		++i;
-	return i;
-}
-
-static unsigned int select_mss(struct s3_conn *c3cn, unsigned int pmtu)
-{
-	unsigned int idx;
-	struct dst_entry *dst = c3cn->dst_cache;
-	struct t3cdev *cdev = c3cn->cdev;
-	const struct t3c_data *td = T3C_DATA(cdev);
-	u16 advmss = dst_metric(dst, RTAX_ADVMSS);
-
-	if (advmss > pmtu - 40)
-		advmss = pmtu - 40;
-	if (advmss < td->mtus[0] - 40)
-		advmss = td->mtus[0] - 40;
-	idx = find_best_mtu(td, advmss + 40);
-	return idx;
-}
-
-static inline int compute_wscale(int win)
-{
-	int wscale = 0;
-	while (wscale < 14 && (65535<<wscale) < win)
-		wscale++;
-	return wscale;
-}
-
-static inline unsigned int calc_opt0h(struct s3_conn *c3cn)
-{
-	int wscale = compute_wscale(cxgb3_rcv_win);
-	return  V_KEEP_ALIVE(1) |
-		F_TCAM_BYPASS |
-		V_WND_SCALE(wscale) |
-		V_MSS_IDX(c3cn->mss_idx);
-}
-
-static inline unsigned int calc_opt0l(struct s3_conn *c3cn)
-{
-	return  V_ULP_MODE(ULP_MODE_ISCSI) |
-		V_RCV_BUFSIZ(cxgb3_rcv_win>>10);
-}
-
-static void make_act_open_req(struct s3_conn *c3cn, struct sk_buff *skb,
-			      unsigned int atid, const struct l2t_entry *e)
-{
-	struct cpl_act_open_req *req;
-
-	c3cn_conn_debug("c3cn 0x%p, atid 0x%x.\n", c3cn, atid);
-
-	skb->priority = CPL_PRIORITY_SETUP;
-	req = (struct cpl_act_open_req *)__skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	req->wr.wr_lo = 0;
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, atid));
-	req->local_port = c3cn->saddr.sin_port;
-	req->peer_port = c3cn->daddr.sin_port;
-	req->local_ip = c3cn->saddr.sin_addr.s_addr;
-	req->peer_ip = c3cn->daddr.sin_addr.s_addr;
-	req->opt0h = htonl(calc_opt0h(c3cn) | V_L2T_IDX(e->idx) |
-			   V_TX_CHANNEL(e->smt_idx));
-	req->opt0l = htonl(calc_opt0l(c3cn));
-	req->params = 0;
-	req->opt2 = 0;
-}
-
-static void fail_act_open(struct s3_conn *c3cn, int errno)
-{
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-	c3cn->err = errno;
-	c3cn_closed(c3cn);
-}
-
-static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
-{
-	struct s3_conn *c3cn = (struct s3_conn *)skb->sk;
-
-	c3cn_conn_debug("c3cn 0x%p, state %u.\n", c3cn, c3cn->state);
-
-	c3cn_hold(c3cn);
-	spin_lock_bh(&c3cn->lock);
-	if (c3cn->state == C3CN_STATE_CONNECTING)
-		fail_act_open(c3cn, -EHOSTUNREACH);
-	spin_unlock_bh(&c3cn->lock);
-	c3cn_put(c3cn);
-	__kfree_skb(skb);
-}
-
-/*
- * CPL connection close request: host ->
- *
- * Close a connection by sending a CPL_CLOSE_CON_REQ message and queue it to
- * the write queue (i.e., after any unsent txt data).
- */
-static void skb_entail(struct s3_conn *c3cn, struct sk_buff *skb,
-		       int flags)
-{
-	skb_tcp_seq(skb) = c3cn->write_seq;
-	skb_flags(skb) = flags;
-	__skb_queue_tail(&c3cn->write_queue, skb);
-}
-
-static void send_close_req(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb = c3cn->cpl_close;
-	struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->head;
-	unsigned int tid = c3cn->tid;
-
-	c3cn_conn_debug("c3cn 0x%p, state 0x%x, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	c3cn->cpl_close = NULL;
-
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_CLOSE_CON));
-	req->wr.wr_lo = htonl(V_WR_TID(tid));
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
-	req->rsvd = htonl(c3cn->write_seq);
-
-	skb_entail(c3cn, skb, C3CB_FLAG_NO_APPEND);
-	if (c3cn->state != C3CN_STATE_CONNECTING)
-		c3cn_push_tx_frames(c3cn, 1);
-}
-
-/*
- * CPL connection abort request: host ->
- *
- * Send an ABORT_REQ message. Makes sure we do not send multiple ABORT_REQs
- * for the same connection and also that we do not try to send a message
- * after the connection has closed.
- */
-static void abort_arp_failure(struct t3cdev *cdev, struct sk_buff *skb)
-{
-	struct cpl_abort_req *req = cplhdr(skb);
-
-	c3cn_conn_debug("tdev 0x%p.\n", cdev);
-
-	req->cmd = CPL_ABORT_NO_RST;
-	cxgb3_ofld_send(cdev, skb);
-}
-
-static inline void c3cn_purge_write_queue(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb;
-
-	while ((skb = __skb_dequeue(&c3cn->write_queue)))
-		__kfree_skb(skb);
-}
-
-static void send_abort_req(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb = c3cn->cpl_abort_req;
-	struct cpl_abort_req *req;
-	unsigned int tid = c3cn->tid;
-
-	if (unlikely(c3cn->state == C3CN_STATE_ABORTING) || !skb ||
-		     !c3cn->cdev)
-		return;
-
-	c3cn_set_state(c3cn, C3CN_STATE_ABORTING);
-
-	c3cn_conn_debug("c3cn 0x%p, flag ABORT_RPL + ABORT_SHUT.\n", c3cn);
-
-	c3cn_set_flag(c3cn, C3CN_ABORT_RPL_PENDING);
-
-	/* Purge the send queue so we don't send anything after an abort. */
-	c3cn_purge_write_queue(c3cn);
-
-	c3cn->cpl_abort_req = NULL;
-	req = (struct cpl_abort_req *)skb->head;
-	memset(req, 0, sizeof(*req));
-
-	skb->priority = CPL_PRIORITY_DATA;
-	set_arp_failure_handler(skb, abort_arp_failure);
-
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_REQ));
-	req->wr.wr_lo = htonl(V_WR_TID(tid));
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ABORT_REQ, tid));
-	req->rsvd0 = htonl(c3cn->snd_nxt);
-	req->rsvd1 = !c3cn_flag(c3cn, C3CN_TX_DATA_SENT);
-	req->cmd = CPL_ABORT_SEND_RST;
-
-	l2t_send(c3cn->cdev, skb, c3cn->l2t);
-}
-
-/*
- * CPL connection abort reply: host ->
- *
- * Send an ABORT_RPL message in response of the ABORT_REQ received.
- */
-static void send_abort_rpl(struct s3_conn *c3cn, int rst_status)
-{
-	struct sk_buff *skb = c3cn->cpl_abort_rpl;
-	struct cpl_abort_rpl *rpl = (struct cpl_abort_rpl *)skb->head;
-
-	c3cn->cpl_abort_rpl = NULL;
-
-	skb->priority = CPL_PRIORITY_DATA;
-	memset(rpl, 0, sizeof(*rpl));
-	rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL));
-	rpl->wr.wr_lo = htonl(V_WR_TID(c3cn->tid));
-	OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, c3cn->tid));
-	rpl->cmd = rst_status;
-
-	cxgb3_ofld_send(c3cn->cdev, skb);
-}
-
-/*
- * CPL connection rx data ack: host ->
- * Send RX credits through an RX_DATA_ACK CPL message. Returns the number of
- * credits sent.
- */
-static u32 send_rx_credits(struct s3_conn *c3cn, u32 credits, u32 dack)
-{
-	struct sk_buff *skb;
-	struct cpl_rx_data_ack *req;
-
-	skb = alloc_skb(sizeof(*req), GFP_ATOMIC);
-	if (!skb)
-		return 0;
-
-	req = (struct cpl_rx_data_ack *)__skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	req->wr.wr_lo = 0;
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, c3cn->tid));
-	req->credit_dack = htonl(dack | V_RX_CREDITS(credits));
-	skb->priority = CPL_PRIORITY_ACK;
-	cxgb3_ofld_send(c3cn->cdev, skb);
-	return credits;
-}
-
-/*
- * CPL connection tx data: host ->
- *
- * Send iscsi PDU via TX_DATA CPL message. Returns the number of
- * credits sent.
- * Each TX_DATA consumes work request credit (wrs), so we need to keep track of
- * how many we've used so far and how many are pending (i.e., yet ack'ed by T3).
- */
-
-/*
- * For ULP connections HW may inserts digest bytes into the pdu. Those digest
- * bytes are not sent by the host but are part of the TCP payload and therefore
- * consume TCP sequence space.
- */
-static const unsigned int cxgb3_ulp_extra_len[] = { 0, 4, 4, 8 };
-static inline unsigned int ulp_extra_len(const struct sk_buff *skb)
-{
-	return cxgb3_ulp_extra_len[skb_ulp_mode(skb) & 3];
-}
-
-static unsigned int wrlen __read_mostly;
-
-/*
- * The number of WRs needed for an skb depends on the number of fragments
- * in the skb and whether it has any payload in its main body.  This maps the
- * length of the gather list represented by an skb into the # of necessary WRs.
- * The extra two fragments are for iscsi bhs and payload padding.
- */
-#define SKB_WR_LIST_SIZE	(MAX_SKB_FRAGS + 2)
-static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly;
-
-static void s3_init_wr_tab(unsigned int wr_len)
-{
-	int i;
-
-	if (skb_wrs[1])		/* already initialized */
-		return;
-
-	for (i = 1; i < SKB_WR_LIST_SIZE; i++) {
-		int sgl_len = (3 * i) / 2 + (i & 1);
-
-		sgl_len += 3;
-		skb_wrs[i] = (sgl_len <= wr_len
-			      ? 1 : 1 + (sgl_len - 2) / (wr_len - 1));
-	}
-
-	wrlen = wr_len * 8;
-}
-
-static inline void reset_wr_list(struct s3_conn *c3cn)
-{
-	c3cn->wr_pending_head = c3cn->wr_pending_tail = NULL;
-}
-
-/*
- * Add a WR to a connections's list of pending WRs.  This is a singly-linked
- * list of sk_buffs operating as a FIFO.  The head is kept in wr_pending_head
- * and the tail in wr_pending_tail.
- */
-static inline void enqueue_wr(struct s3_conn *c3cn,
-			      struct sk_buff *skb)
-{
-	skb_tx_wr_next(skb) = NULL;
-
-	/*
-	 * We want to take an extra reference since both us and the driver
-	 * need to free the packet before it's really freed. We know there's
-	 * just one user currently so we use atomic_set rather than skb_get
-	 * to avoid the atomic op.
-	 */
-	atomic_set(&skb->users, 2);
-
-	if (!c3cn->wr_pending_head)
-		c3cn->wr_pending_head = skb;
-	else
-		skb_tx_wr_next(c3cn->wr_pending_tail) = skb;
-	c3cn->wr_pending_tail = skb;
-}
-
-static int count_pending_wrs(struct s3_conn *c3cn)
-{
-	int n = 0;
-	const struct sk_buff *skb = c3cn->wr_pending_head;
-
-	while (skb) {
-		n += skb->csum;
-		skb = skb_tx_wr_next(skb);
-	}
-	return n;
-}
-
-static inline struct sk_buff *peek_wr(const struct s3_conn *c3cn)
-{
-	return c3cn->wr_pending_head;
-}
-
-static inline void free_wr_skb(struct sk_buff *skb)
-{
-	kfree_skb(skb);
-}
-
-static inline struct sk_buff *dequeue_wr(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb = c3cn->wr_pending_head;
-
-	if (likely(skb)) {
-		/* Don't bother clearing the tail */
-		c3cn->wr_pending_head = skb_tx_wr_next(skb);
-		skb_tx_wr_next(skb) = NULL;
-	}
-	return skb;
-}
-
-static void purge_wr_queue(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb;
-	while ((skb = dequeue_wr(c3cn)) != NULL)
-		free_wr_skb(skb);
-}
-
-static inline void make_tx_data_wr(struct s3_conn *c3cn, struct sk_buff *skb,
-				   int len, int req_completion)
-{
-	struct tx_data_wr *req;
-
-	skb_reset_transport_header(skb);
-	req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req));
-	req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA) |
-			(req_completion ? F_WR_COMPL : 0));
-	req->wr_lo = htonl(V_WR_TID(c3cn->tid));
-	req->sndseq = htonl(c3cn->snd_nxt);
-	/* len includes the length of any HW ULP additions */
-	req->len = htonl(len);
-	req->param = htonl(V_TX_PORT(c3cn->l2t->smt_idx));
-	/* V_TX_ULP_SUBMODE sets both the mode and submode */
-	req->flags = htonl(V_TX_ULP_SUBMODE(skb_ulp_mode(skb)) |
-			   V_TX_SHOVE((skb_peek(&c3cn->write_queue) ? 0 : 1)));
-
-	if (!c3cn_flag(c3cn, C3CN_TX_DATA_SENT)) {
-		req->flags |= htonl(V_TX_ACK_PAGES(2) | F_TX_INIT |
-				    V_TX_CPU_IDX(c3cn->qset));
-		/* Sendbuffer is in units of 32KB. */
-		req->param |= htonl(V_TX_SNDBUF(cxgb3_snd_win >> 15));
-		c3cn_set_flag(c3cn, C3CN_TX_DATA_SENT);
-	}
-}
-
-/**
- * c3cn_push_tx_frames -- start transmit
- * @c3cn: the offloaded connection
- * @req_completion: request wr_ack or not
- *
- * Prepends TX_DATA_WR or CPL_CLOSE_CON_REQ headers to buffers waiting in a
- * connection's send queue and sends them on to T3.  Must be called with the
- * connection's lock held.  Returns the amount of send buffer space that was
- * freed as a result of sending queued data to T3.
- */
-static void arp_failure_discard(struct t3cdev *cdev, struct sk_buff *skb)
-{
-	kfree_skb(skb);
-}
-
-static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion)
-{
-	int total_size = 0;
-	struct sk_buff *skb;
-	struct t3cdev *cdev;
-	struct cxgb3i_sdev_data *cdata;
-
-	if (unlikely(c3cn->state == C3CN_STATE_CONNECTING ||
-		     c3cn->state == C3CN_STATE_CLOSE_WAIT_1 ||
-		     c3cn->state >= C3CN_STATE_ABORTING)) {
-		c3cn_tx_debug("c3cn 0x%p, in closing state %u.\n",
-			      c3cn, c3cn->state);
-		return 0;
-	}
-
-	cdev = c3cn->cdev;
-	cdata = CXGB3_SDEV_DATA(cdev);
-
-	while (c3cn->wr_avail
-	       && (skb = skb_peek(&c3cn->write_queue)) != NULL) {
-		int len = skb->len;	/* length before skb_push */
-		int frags = skb_shinfo(skb)->nr_frags + (len != skb->data_len);
-		int wrs_needed = skb_wrs[frags];
-
-		if (wrs_needed > 1 && len + sizeof(struct tx_data_wr) <= wrlen)
-			wrs_needed = 1;
-
-		WARN_ON(frags >= SKB_WR_LIST_SIZE || wrs_needed < 1);
-
-		if (c3cn->wr_avail < wrs_needed) {
-			c3cn_tx_debug("c3cn 0x%p, skb len %u/%u, frag %u, "
-				      "wr %d < %u.\n",
-				      c3cn, skb->len, skb->data_len, frags,
-				      wrs_needed, c3cn->wr_avail);
-			break;
-		}
-
-		__skb_unlink(skb, &c3cn->write_queue);
-		skb->priority = CPL_PRIORITY_DATA;
-		skb->csum = wrs_needed;	/* remember this until the WR_ACK */
-		c3cn->wr_avail -= wrs_needed;
-		c3cn->wr_unacked += wrs_needed;
-		enqueue_wr(c3cn, skb);
-
-		c3cn_tx_debug("c3cn 0x%p, enqueue, skb len %u/%u, frag %u, "
-				"wr %d, left %u, unack %u.\n",
-				c3cn, skb->len, skb->data_len, frags,
-				wrs_needed, c3cn->wr_avail, c3cn->wr_unacked);
-
-
-		if (likely(skb_flags(skb) & C3CB_FLAG_NEED_HDR)) {
-			if ((req_completion &&
-				c3cn->wr_unacked == wrs_needed) ||
-			    (skb_flags(skb) & C3CB_FLAG_COMPL) ||
-			    c3cn->wr_unacked >= c3cn->wr_max / 2) {
-				req_completion = 1;
-				c3cn->wr_unacked = 0;
-			}
-			len += ulp_extra_len(skb);
-			make_tx_data_wr(c3cn, skb, len, req_completion);
-			c3cn->snd_nxt += len;
-			skb_flags(skb) &= ~C3CB_FLAG_NEED_HDR;
-		}
-
-		total_size += skb->truesize;
-		set_arp_failure_handler(skb, arp_failure_discard);
-		l2t_send(cdev, skb, c3cn->l2t);
-	}
-	return total_size;
-}
-
-/*
- * process_cpl_msg: -> host
- * Top-level CPL message processing used by most CPL messages that
- * pertain to connections.
- */
-static inline void process_cpl_msg(void (*fn)(struct s3_conn *,
-					      struct sk_buff *),
-				   struct s3_conn *c3cn,
-				   struct sk_buff *skb)
-{
-	spin_lock_bh(&c3cn->lock);
-	fn(c3cn, skb);
-	spin_unlock_bh(&c3cn->lock);
-}
-
-/*
- * process_cpl_msg_ref: -> host
- * Similar to process_cpl_msg() but takes an extra connection reference around
- * the call to the handler.  Should be used if the handler may drop a
- * connection reference.
- */
-static inline void process_cpl_msg_ref(void (*fn) (struct s3_conn *,
-						   struct sk_buff *),
-				       struct s3_conn *c3cn,
-				       struct sk_buff *skb)
-{
-	c3cn_hold(c3cn);
-	process_cpl_msg(fn, c3cn, skb);
-	c3cn_put(c3cn);
-}
-
-/*
- * Process a CPL_ACT_ESTABLISH message: -> host
- * Updates connection state from an active establish CPL message.  Runs with
- * the connection lock held.
- */
-
-static inline void s3_free_atid(struct t3cdev *cdev, unsigned int tid)
-{
-	struct s3_conn *c3cn = cxgb3_free_atid(cdev, tid);
-	if (c3cn)
-		c3cn_put(c3cn);
-}
-
-static void c3cn_established(struct s3_conn *c3cn, u32 snd_isn,
-			     unsigned int opt)
-{
-	c3cn_conn_debug("c3cn 0x%p, state %u.\n", c3cn, c3cn->state);
-
-	c3cn->write_seq = c3cn->snd_nxt = c3cn->snd_una = snd_isn;
-
-	/*
-	 * Causes the first RX_DATA_ACK to supply any Rx credits we couldn't
-	 * pass through opt0.
-	 */
-	if (cxgb3_rcv_win > (M_RCV_BUFSIZ << 10))
-		c3cn->rcv_wup -= cxgb3_rcv_win - (M_RCV_BUFSIZ << 10);
-
-	dst_confirm(c3cn->dst_cache);
-
-	smp_mb();
-
-	c3cn_set_state(c3cn, C3CN_STATE_ESTABLISHED);
-}
-
-static void process_act_establish(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct cpl_act_establish *req = cplhdr(skb);
-	u32 rcv_isn = ntohl(req->rcv_isn);	/* real RCV_ISN + 1 */
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (unlikely(c3cn->state != C3CN_STATE_CONNECTING))
-		cxgb3i_log_error("TID %u expected SYN_SENT, got EST., s %u\n",
-				 c3cn->tid, c3cn->state);
-
-	c3cn->copied_seq = c3cn->rcv_wup = c3cn->rcv_nxt = rcv_isn;
-	c3cn_established(c3cn, ntohl(req->snd_isn), ntohs(req->tcp_opt));
-
-	__kfree_skb(skb);
-
-	if (unlikely(c3cn_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED)))
-		/* upper layer has requested closing */
-		send_abort_req(c3cn);
-	else {
-		if (skb_queue_len(&c3cn->write_queue))
-			c3cn_push_tx_frames(c3cn, 1);
-		cxgb3i_conn_tx_open(c3cn);
-	}
-}
-
-static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb,
-			    void *ctx)
-{
-	struct cpl_act_establish *req = cplhdr(skb);
-	unsigned int tid = GET_TID(req);
-	unsigned int atid = G_PASS_OPEN_TID(ntohl(req->tos_tid));
-	struct s3_conn *c3cn = ctx;
-	struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(cdev);
-
-	c3cn_conn_debug("rcv, tid 0x%x, c3cn 0x%p, s %u, f 0x%lx.\n",
-			tid, c3cn, c3cn->state, c3cn->flags);
-
-	c3cn->tid = tid;
-	c3cn_hold(c3cn);
-	cxgb3_insert_tid(cdata->cdev, cdata->client, c3cn, tid);
-	s3_free_atid(cdev, atid);
-
-	c3cn->qset = G_QNUM(ntohl(skb->csum));
-
-	process_cpl_msg(process_act_establish, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process a CPL_ACT_OPEN_RPL message: -> host
- * Handle active open failures.
- */
-static int act_open_rpl_status_to_errno(int status)
-{
-	switch (status) {
-	case CPL_ERR_CONN_RESET:
-		return -ECONNREFUSED;
-	case CPL_ERR_ARP_MISS:
-		return -EHOSTUNREACH;
-	case CPL_ERR_CONN_TIMEDOUT:
-		return -ETIMEDOUT;
-	case CPL_ERR_TCAM_FULL:
-		return -ENOMEM;
-	case CPL_ERR_CONN_EXIST:
-		cxgb3i_log_error("ACTIVE_OPEN_RPL: 4-tuple in use\n");
-		return -EADDRINUSE;
-	default:
-		return -EIO;
-	}
-}
-
-static void act_open_retry_timer(unsigned long data)
-{
-	struct sk_buff *skb;
-	struct s3_conn *c3cn = (struct s3_conn *)data;
-
-	c3cn_conn_debug("c3cn 0x%p, state %u.\n", c3cn, c3cn->state);
-
-	spin_lock_bh(&c3cn->lock);
-	skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_ATOMIC);
-	if (!skb)
-		fail_act_open(c3cn, -ENOMEM);
-	else {
-		skb->sk = (struct sock *)c3cn;
-		set_arp_failure_handler(skb, act_open_req_arp_failure);
-		make_act_open_req(c3cn, skb, c3cn->tid, c3cn->l2t);
-		l2t_send(c3cn->cdev, skb, c3cn->l2t);
-	}
-	spin_unlock_bh(&c3cn->lock);
-	c3cn_put(c3cn);
-}
-
-static void process_act_open_rpl(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct cpl_act_open_rpl *rpl = cplhdr(skb);
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (rpl->status == CPL_ERR_CONN_EXIST &&
-	    c3cn->retry_timer.function != act_open_retry_timer) {
-		c3cn->retry_timer.function = act_open_retry_timer;
-		if (!mod_timer(&c3cn->retry_timer, jiffies + HZ / 2))
-			c3cn_hold(c3cn);
-	} else
-		fail_act_open(c3cn, act_open_rpl_status_to_errno(rpl->status));
-	__kfree_skb(skb);
-}
-
-static int do_act_open_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
-	struct s3_conn *c3cn = ctx;
-	struct cpl_act_open_rpl *rpl = cplhdr(skb);
-
-	c3cn_conn_debug("rcv, status 0x%x, c3cn 0x%p, s %u, f 0x%lx.\n",
-			rpl->status, c3cn, c3cn->state, c3cn->flags);
-
-	if (rpl->status != CPL_ERR_TCAM_FULL &&
-	    rpl->status != CPL_ERR_CONN_EXIST &&
-	    rpl->status != CPL_ERR_ARP_MISS)
-		cxgb3_queue_tid_release(cdev, GET_TID(rpl));
-
-	process_cpl_msg_ref(process_act_open_rpl, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process PEER_CLOSE CPL messages: -> host
- * Handle peer FIN.
- */
-static void process_peer_close(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING))
-		goto out;
-
-	switch (c3cn->state) {
-	case C3CN_STATE_ESTABLISHED:
-		c3cn_set_state(c3cn, C3CN_STATE_PASSIVE_CLOSE);
-		break;
-	case C3CN_STATE_ACTIVE_CLOSE:
-		c3cn_set_state(c3cn, C3CN_STATE_CLOSE_WAIT_2);
-		break;
-	case C3CN_STATE_CLOSE_WAIT_1:
-		c3cn_closed(c3cn);
-		break;
-	case C3CN_STATE_ABORTING:
-		break;
-	default:
-		cxgb3i_log_error("%s: peer close, TID %u in bad state %u\n",
-				 c3cn->cdev->name, c3cn->tid, c3cn->state);
-	}
-
-	cxgb3i_conn_closing(c3cn);
-out:
-	__kfree_skb(skb);
-}
-
-static int do_peer_close(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
-	struct s3_conn *c3cn = ctx;
-
-	c3cn_conn_debug("rcv, c3cn 0x%p, s %u, f 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-	process_cpl_msg_ref(process_peer_close, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process CLOSE_CONN_RPL CPL message: -> host
- * Process a peer ACK to our FIN.
- */
-static void process_close_con_rpl(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct cpl_close_con_rpl *rpl = cplhdr(skb);
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	c3cn->snd_una = ntohl(rpl->snd_nxt) - 1;	/* exclude FIN */
-
-	if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING))
-		goto out;
-
-	switch (c3cn->state) {
-	case C3CN_STATE_ACTIVE_CLOSE:
-		c3cn_set_state(c3cn, C3CN_STATE_CLOSE_WAIT_1);
-		break;
-	case C3CN_STATE_CLOSE_WAIT_1:
-	case C3CN_STATE_CLOSE_WAIT_2:
-		c3cn_closed(c3cn);
-		break;
-	case C3CN_STATE_ABORTING:
-		break;
-	default:
-		cxgb3i_log_error("%s: close_rpl, TID %u in bad state %u\n",
-				 c3cn->cdev->name, c3cn->tid, c3cn->state);
-	}
-
-out:
-	kfree_skb(skb);
-}
-
-static int do_close_con_rpl(struct t3cdev *cdev, struct sk_buff *skb,
-			    void *ctx)
-{
-	struct s3_conn *c3cn = ctx;
-
-	c3cn_conn_debug("rcv, c3cn 0x%p, s %u, f 0x%lx.\n",
-			 c3cn, c3cn->state, c3cn->flags);
-
-	process_cpl_msg_ref(process_close_con_rpl, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process ABORT_REQ_RSS CPL message: -> host
- * Process abort requests.  If we are waiting for an ABORT_RPL we ignore this
- * request except that we need to reply to it.
- */
-
-static int abort_status_to_errno(struct s3_conn *c3cn, int abort_reason,
-				 int *need_rst)
-{
-	switch (abort_reason) {
-	case CPL_ERR_BAD_SYN: /* fall through */
-	case CPL_ERR_CONN_RESET:
-		return c3cn->state > C3CN_STATE_ESTABLISHED ?
-			-EPIPE : -ECONNRESET;
-	case CPL_ERR_XMIT_TIMEDOUT:
-	case CPL_ERR_PERSIST_TIMEDOUT:
-	case CPL_ERR_FINWAIT2_TIMEDOUT:
-	case CPL_ERR_KEEPALIVE_TIMEDOUT:
-		return -ETIMEDOUT;
-	default:
-		return -EIO;
-	}
-}
-
-static void process_abort_req(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	int rst_status = CPL_ABORT_NO_RST;
-	const struct cpl_abort_req_rss *req = cplhdr(skb);
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (!c3cn_flag(c3cn, C3CN_ABORT_REQ_RCVD)) {
-		c3cn_set_flag(c3cn, C3CN_ABORT_REQ_RCVD);
-		c3cn_set_state(c3cn, C3CN_STATE_ABORTING);
-		__kfree_skb(skb);
-		return;
-	}
-
-	c3cn_clear_flag(c3cn, C3CN_ABORT_REQ_RCVD);
-	send_abort_rpl(c3cn, rst_status);
-
-	if (!c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING)) {
-		c3cn->err =
-		    abort_status_to_errno(c3cn, req->status, &rst_status);
-		c3cn_closed(c3cn);
-	}
-}
-
-static int do_abort_req(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
-	const struct cpl_abort_req_rss *req = cplhdr(skb);
-	struct s3_conn *c3cn = ctx;
-
-	c3cn_conn_debug("rcv, c3cn 0x%p, s 0x%x, f 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
-	    req->status == CPL_ERR_PERSIST_NEG_ADVICE) {
-		__kfree_skb(skb);
-		return 0;
-	}
-
-	process_cpl_msg_ref(process_abort_req, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process ABORT_RPL_RSS CPL message: -> host
- * Process abort replies.  We only process these messages if we anticipate
- * them as the coordination between SW and HW in this area is somewhat lacking
- * and sometimes we get ABORT_RPLs after we are done with the connection that
- * originated the ABORT_REQ.
- */
-static void process_abort_rpl(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING)) {
-		if (!c3cn_flag(c3cn, C3CN_ABORT_RPL_RCVD))
-			c3cn_set_flag(c3cn, C3CN_ABORT_RPL_RCVD);
-		else {
-			c3cn_clear_flag(c3cn, C3CN_ABORT_RPL_RCVD);
-			c3cn_clear_flag(c3cn, C3CN_ABORT_RPL_PENDING);
-			if (c3cn_flag(c3cn, C3CN_ABORT_REQ_RCVD))
-				cxgb3i_log_error("%s tid %u, ABORT_RPL_RSS\n",
-						 c3cn->cdev->name, c3cn->tid);
-			c3cn_closed(c3cn);
-		}
-	}
-	__kfree_skb(skb);
-}
-
-static int do_abort_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
-	struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
-	struct s3_conn *c3cn = ctx;
-
-	c3cn_conn_debug("rcv, status 0x%x, c3cn 0x%p, s %u, 0x%lx.\n",
-			rpl->status, c3cn, c3cn ? c3cn->state : 0,
-			c3cn ? c3cn->flags : 0UL);
-
-	/*
-	 * Ignore replies to post-close aborts indicating that the abort was
-	 * requested too late.  These connections are terminated when we get
-	 * PEER_CLOSE or CLOSE_CON_RPL and by the time the abort_rpl_rss
-	 * arrives the TID is either no longer used or it has been recycled.
-	 */
-	if (rpl->status == CPL_ERR_ABORT_FAILED)
-		goto discard;
-
-	/*
-	 * Sometimes we've already closed the connection, e.g., a post-close
-	 * abort races with ABORT_REQ_RSS, the latter frees the connection
-	 * expecting the ABORT_REQ will fail with CPL_ERR_ABORT_FAILED,
-	 * but FW turns the ABORT_REQ into a regular one and so we get
-	 * ABORT_RPL_RSS with status 0 and no connection.
-	 */
-	if (!c3cn)
-		goto discard;
-
-	process_cpl_msg_ref(process_abort_rpl, c3cn, skb);
-	return 0;
-
-discard:
-	__kfree_skb(skb);
-	return 0;
-}
-
-/*
- * Process RX_ISCSI_HDR CPL message: -> host
- * Handle received PDUs, the payload could be DDP'ed. If not, the payload
- * follow after the bhs.
- */
-static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct cpl_iscsi_hdr *hdr_cpl = cplhdr(skb);
-	struct cpl_iscsi_hdr_norss data_cpl;
-	struct cpl_rx_data_ddp_norss ddp_cpl;
-	unsigned int hdr_len, data_len, status;
-	unsigned int len;
-	int err;
-
-	if (unlikely(c3cn->state >= C3CN_STATE_PASSIVE_CLOSE)) {
-		if (c3cn->state != C3CN_STATE_ABORTING)
-			send_abort_req(c3cn);
-		__kfree_skb(skb);
-		return;
-	}
-
-	skb_tcp_seq(skb) = ntohl(hdr_cpl->seq);
-	skb_flags(skb) = 0;
-
-	skb_reset_transport_header(skb);
-	__skb_pull(skb, sizeof(struct cpl_iscsi_hdr));
-
-	len = hdr_len = ntohs(hdr_cpl->len);
-	/* msg coalesce is off or not enough data received */
-	if (skb->len <= hdr_len) {
-		cxgb3i_log_error("%s: TID %u, ISCSI_HDR, skb len %u < %u.\n",
-				 c3cn->cdev->name, c3cn->tid,
-				 skb->len, hdr_len);
-		goto abort_conn;
-	}
-
-	err = skb_copy_bits(skb, skb->len - sizeof(ddp_cpl), &ddp_cpl,
-			    sizeof(ddp_cpl));
-	if (err < 0)
-		goto abort_conn;
-
-	skb_ulp_mode(skb) = ULP2_FLAG_DATA_READY;
-	skb_rx_pdulen(skb) = ntohs(ddp_cpl.len);
-	skb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc);
-	status = ntohl(ddp_cpl.ddp_status);
-
-	c3cn_rx_debug("rx skb 0x%p, len %u, pdulen %u, ddp status 0x%x.\n",
-		      skb, skb->len, skb_rx_pdulen(skb), status);
-
-	if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT))
-		skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR;
-	if (status & (1 << RX_DDP_STATUS_DCRC_SHIFT))
-		skb_ulp_mode(skb) |= ULP2_FLAG_DCRC_ERROR;
-	if (status & (1 << RX_DDP_STATUS_PAD_SHIFT))
-		skb_ulp_mode(skb) |= ULP2_FLAG_PAD_ERROR;
-
-	if (skb->len > (hdr_len + sizeof(ddp_cpl))) {
-		err = skb_copy_bits(skb, hdr_len, &data_cpl, sizeof(data_cpl));
-		if (err < 0)
-			goto abort_conn;
-		data_len = ntohs(data_cpl.len);
-		len += sizeof(data_cpl) + data_len;
-	} else if (status & (1 << RX_DDP_STATUS_DDP_SHIFT))
-		skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED;
-
-	c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_rx_pdulen(skb);
-	__pskb_trim(skb, len);
-	__skb_queue_tail(&c3cn->receive_queue, skb);
-	cxgb3i_conn_pdu_ready(c3cn);
-
-	return;
-
-abort_conn:
-	send_abort_req(c3cn);
-	__kfree_skb(skb);
-}
-
-static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx)
-{
-	struct s3_conn *c3cn = ctx;
-
-	process_cpl_msg(process_rx_iscsi_hdr, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process TX_DATA_ACK CPL messages: -> host
- * Process an acknowledgment of WR completion.  Advance snd_una and send the
- * next batch of work requests from the write queue.
- */
-static void check_wr_invariants(struct s3_conn *c3cn)
-{
-	int pending = count_pending_wrs(c3cn);
-
-	if (unlikely(c3cn->wr_avail + pending != c3cn->wr_max))
-		cxgb3i_log_error("TID %u: credit imbalance: avail %u, "
-				"pending %u, total should be %u\n",
-				c3cn->tid, c3cn->wr_avail, pending,
-				c3cn->wr_max);
-}
-
-static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct cpl_wr_ack *hdr = cplhdr(skb);
-	unsigned int credits = ntohs(hdr->credits);
-	u32 snd_una = ntohl(hdr->snd_una);
-
-	c3cn_tx_debug("%u WR credits, avail %u, unack %u, TID %u, state %u.\n",
-			credits, c3cn->wr_avail, c3cn->wr_unacked,
-			c3cn->tid, c3cn->state);
-
-	c3cn->wr_avail += credits;
-	if (c3cn->wr_unacked > c3cn->wr_max - c3cn->wr_avail)
-		c3cn->wr_unacked = c3cn->wr_max - c3cn->wr_avail;
-
-	while (credits) {
-		struct sk_buff *p = peek_wr(c3cn);
-
-		if (unlikely(!p)) {
-			cxgb3i_log_error("%u WR_ACK credits for TID %u with "
-					 "nothing pending, state %u\n",
-					 credits, c3cn->tid, c3cn->state);
-			break;
-		}
-		if (unlikely(credits < p->csum)) {
-			struct tx_data_wr *w = cplhdr(p);
-			cxgb3i_log_error("TID %u got %u WR credits need %u, "
-					 "len %u, main body %u, frags %u, "
-					 "seq # %u, ACK una %u, ACK nxt %u, "
-					 "WR_AVAIL %u, WRs pending %u\n",
-					 c3cn->tid, credits, p->csum, p->len,
-					 p->len - p->data_len,
-					 skb_shinfo(p)->nr_frags,
-					 ntohl(w->sndseq), snd_una,
-					 ntohl(hdr->snd_nxt), c3cn->wr_avail,
-					 count_pending_wrs(c3cn) - credits);
-			p->csum -= credits;
-			break;
-		} else {
-			dequeue_wr(c3cn);
-			credits -= p->csum;
-			free_wr_skb(p);
-		}
-	}
-
-	check_wr_invariants(c3cn);
-
-	if (unlikely(before(snd_una, c3cn->snd_una))) {
-		cxgb3i_log_error("TID %u, unexpected sequence # %u in WR_ACK "
-				 "snd_una %u\n",
-				 c3cn->tid, snd_una, c3cn->snd_una);
-		goto out_free;
-	}
-
-	if (c3cn->snd_una != snd_una) {
-		c3cn->snd_una = snd_una;
-		dst_confirm(c3cn->dst_cache);
-	}
-
-	if (skb_queue_len(&c3cn->write_queue)) {
-		if (c3cn_push_tx_frames(c3cn, 0))
-			cxgb3i_conn_tx_open(c3cn);
-	} else
-		cxgb3i_conn_tx_open(c3cn);
-out_free:
-	__kfree_skb(skb);
-}
-
-static int do_wr_ack(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
-	struct s3_conn *c3cn = ctx;
-
-	process_cpl_msg(process_wr_ack, c3cn, skb);
-	return 0;
-}
-
-/*
- * for each connection, pre-allocate skbs needed for close/abort requests. So
- * that we can service the request right away.
- */
-static void c3cn_free_cpl_skbs(struct s3_conn *c3cn)
-{
-	if (c3cn->cpl_close)
-		kfree_skb(c3cn->cpl_close);
-	if (c3cn->cpl_abort_req)
-		kfree_skb(c3cn->cpl_abort_req);
-	if (c3cn->cpl_abort_rpl)
-		kfree_skb(c3cn->cpl_abort_rpl);
-}
-
-static int c3cn_alloc_cpl_skbs(struct s3_conn *c3cn)
-{
-	c3cn->cpl_close = alloc_skb(sizeof(struct cpl_close_con_req),
-				   GFP_KERNEL);
-	if (!c3cn->cpl_close)
-		return -ENOMEM;
-	skb_put(c3cn->cpl_close, sizeof(struct cpl_close_con_req));
-
-	c3cn->cpl_abort_req = alloc_skb(sizeof(struct cpl_abort_req),
-					GFP_KERNEL);
-	if (!c3cn->cpl_abort_req)
-		goto free_cpl_skbs;
-	skb_put(c3cn->cpl_abort_req, sizeof(struct cpl_abort_req));
-
-	c3cn->cpl_abort_rpl = alloc_skb(sizeof(struct cpl_abort_rpl),
-					GFP_KERNEL);
-	if (!c3cn->cpl_abort_rpl)
-		goto free_cpl_skbs;
-	skb_put(c3cn->cpl_abort_rpl, sizeof(struct cpl_abort_rpl));
-
-	return 0;
-
-free_cpl_skbs:
-	c3cn_free_cpl_skbs(c3cn);
-	return -ENOMEM;
-}
-
-/**
- * c3cn_release_offload_resources - release offload resource
- * @c3cn: the offloaded iscsi tcp connection.
- * Release resources held by an offload connection (TID, L2T entry, etc.)
- */
-static void c3cn_release_offload_resources(struct s3_conn *c3cn)
-{
-	struct t3cdev *cdev = c3cn->cdev;
-	unsigned int tid = c3cn->tid;
-
-	c3cn->qset = 0;
-	c3cn_free_cpl_skbs(c3cn);
-
-	if (c3cn->wr_avail != c3cn->wr_max) {
-		purge_wr_queue(c3cn);
-		reset_wr_list(c3cn);
-	}
-
-	if (cdev) {
-		if (c3cn->l2t) {
-			l2t_release(L2DATA(cdev), c3cn->l2t);
-			c3cn->l2t = NULL;
-		}
-		if (c3cn->state == C3CN_STATE_CONNECTING)
-			/* we have ATID */
-			s3_free_atid(cdev, tid);
-		else {
-			/* we have TID */
-			cxgb3_remove_tid(cdev, (void *)c3cn, tid);
-			c3cn_put(c3cn);
-		}
-	}
-
-	c3cn->dst_cache = NULL;
-	c3cn->cdev = NULL;
-}
-
-/**
- * cxgb3i_c3cn_create - allocate and initialize an s3_conn structure
- * returns the s3_conn structure allocated.
- */
-struct s3_conn *cxgb3i_c3cn_create(void)
-{
-	struct s3_conn *c3cn;
-
-	c3cn = kzalloc(sizeof(*c3cn), GFP_KERNEL);
-	if (!c3cn)
-		return NULL;
-
-	/* pre-allocate close/abort cpl, so we don't need to wait for memory
-	   when close/abort is requested. */
-	if (c3cn_alloc_cpl_skbs(c3cn) < 0)
-		goto free_c3cn;
-
-	c3cn_conn_debug("alloc c3cn 0x%p.\n", c3cn);
-
-	c3cn->flags = 0;
-	spin_lock_init(&c3cn->lock);
-	atomic_set(&c3cn->refcnt, 1);
-	skb_queue_head_init(&c3cn->receive_queue);
-	skb_queue_head_init(&c3cn->write_queue);
-	setup_timer(&c3cn->retry_timer, NULL, (unsigned long)c3cn);
-	rwlock_init(&c3cn->callback_lock);
-
-	return c3cn;
-
-free_c3cn:
-	kfree(c3cn);
-	return NULL;
-}
-
-static void c3cn_active_close(struct s3_conn *c3cn)
-{
-	int data_lost;
-	int close_req = 0;
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			 c3cn, c3cn->state, c3cn->flags);
-
-	dst_confirm(c3cn->dst_cache);
-
-	c3cn_hold(c3cn);
-	spin_lock_bh(&c3cn->lock);
-
-	data_lost = skb_queue_len(&c3cn->receive_queue);
-	__skb_queue_purge(&c3cn->receive_queue);
-
-	switch (c3cn->state) {
-	case C3CN_STATE_CLOSED:
-	case C3CN_STATE_ACTIVE_CLOSE:
-	case C3CN_STATE_CLOSE_WAIT_1:
-	case C3CN_STATE_CLOSE_WAIT_2:
-	case C3CN_STATE_ABORTING:
-		/* nothing need to be done */
-		break;
-	case C3CN_STATE_CONNECTING:
-		/* defer until cpl_act_open_rpl or cpl_act_establish */
-		c3cn_set_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED);
-		break;
-	case C3CN_STATE_ESTABLISHED:
-		close_req = 1;
-		c3cn_set_state(c3cn, C3CN_STATE_ACTIVE_CLOSE);
-		break;
-	case C3CN_STATE_PASSIVE_CLOSE:
-		close_req = 1;
-		c3cn_set_state(c3cn, C3CN_STATE_CLOSE_WAIT_2);
-		break;
-	}
-
-	if (close_req) {
-		if (data_lost)
-			/* Unread data was tossed, zap the connection. */
-			send_abort_req(c3cn);
-		else
-			send_close_req(c3cn);
-	}
-
-	spin_unlock_bh(&c3cn->lock);
-	c3cn_put(c3cn);
-}
-
-/**
- * cxgb3i_c3cn_release - close and release an iscsi tcp connection and any
- * 	resource held
- * @c3cn: the iscsi tcp connection
- */
-void cxgb3i_c3cn_release(struct s3_conn *c3cn)
-{
-	c3cn_conn_debug("c3cn 0x%p, s %u, f 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-	if (unlikely(c3cn->state == C3CN_STATE_CONNECTING))
-		c3cn_set_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED);
-	else if (likely(c3cn->state != C3CN_STATE_CLOSED))
-		c3cn_active_close(c3cn);
-	c3cn_put(c3cn);
-}
-
-static int is_cxgb3_dev(struct net_device *dev)
-{
-	struct cxgb3i_sdev_data *cdata;
-	struct net_device *ndev = dev;
-
-	if (dev->priv_flags & IFF_802_1Q_VLAN)
-		ndev = vlan_dev_real_dev(dev);
-
-	write_lock(&cdata_rwlock);
-	list_for_each_entry(cdata, &cdata_list, list) {
-		struct adap_ports *ports = &cdata->ports;
-		int i;
-
-		for (i = 0; i < ports->nports; i++)
-			if (ndev == ports->lldevs[i]) {
-				write_unlock(&cdata_rwlock);
-				return 1;
-			}
-	}
-	write_unlock(&cdata_rwlock);
-	return 0;
-}
-
-/**
- * cxgb3_egress_dev - return the cxgb3 egress device
- * @root_dev: the root device anchoring the search
- * @c3cn: the connection used to determine egress port in bonding mode
- * @context: in bonding mode, indicates a connection set up or failover
- *
- * Return egress device or NULL if the egress device isn't one of our ports.
- */
-static struct net_device *cxgb3_egress_dev(struct net_device *root_dev,
-					   struct s3_conn *c3cn,
-					   int context)
-{
-	while (root_dev) {
-		if (root_dev->priv_flags & IFF_802_1Q_VLAN)
-			root_dev = vlan_dev_real_dev(root_dev);
-		else if (is_cxgb3_dev(root_dev))
-			return root_dev;
-		else
-			return NULL;
-	}
-	return NULL;
-}
-
-static struct rtable *find_route(struct net_device *dev,
-				 __be32 saddr, __be32 daddr,
-				 __be16 sport, __be16 dport)
-{
-	struct rtable *rt;
-	struct flowi fl = {
-		.oif = dev ? dev->ifindex : 0,
-		.nl_u = {
-			 .ip4_u = {
-				   .daddr = daddr,
-				   .saddr = saddr,
-				   .tos = 0 } },
-		.proto = IPPROTO_TCP,
-		.uli_u = {
-			  .ports = {
-				    .sport = sport,
-				    .dport = dport } } };
-
-	if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
-		return NULL;
-	return rt;
-}
-
-/*
- * Assign offload parameters to some connection fields.
- */
-static void init_offload_conn(struct s3_conn *c3cn,
-			      struct t3cdev *cdev,
-			      struct dst_entry *dst)
-{
-	BUG_ON(c3cn->cdev != cdev);
-	c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs - 1;
-	c3cn->wr_unacked = 0;
-	c3cn->mss_idx = select_mss(c3cn, dst_mtu(dst));
-
-	reset_wr_list(c3cn);
-}
-
-static int initiate_act_open(struct s3_conn *c3cn, struct net_device *dev)
-{
-	struct cxgb3i_sdev_data *cdata = NDEV2CDATA(dev);
-	struct t3cdev *cdev = cdata->cdev;
-	struct dst_entry *dst = c3cn->dst_cache;
-	struct sk_buff *skb;
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-	/*
-	 * Initialize connection data.  Note that the flags and ULP mode are
-	 * initialized higher up ...
-	 */
-	c3cn->dev = dev;
-	c3cn->cdev = cdev;
-	c3cn->tid = cxgb3_alloc_atid(cdev, cdata->client, c3cn);
-	if (c3cn->tid < 0)
-		goto out_err;
-
-	c3cn->qset = 0;
-	c3cn->l2t = t3_l2t_get(cdev, dst->neighbour, dev);
-	if (!c3cn->l2t)
-		goto free_tid;
-
-	skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_KERNEL);
-	if (!skb)
-		goto free_l2t;
-
-	skb->sk = (struct sock *)c3cn;
-	set_arp_failure_handler(skb, act_open_req_arp_failure);
-
-	c3cn_hold(c3cn);
-
-	init_offload_conn(c3cn, cdev, dst);
-	c3cn->err = 0;
-
-	make_act_open_req(c3cn, skb, c3cn->tid, c3cn->l2t);
-	l2t_send(cdev, skb, c3cn->l2t);
-	return 0;
-
-free_l2t:
-	l2t_release(L2DATA(cdev), c3cn->l2t);
-free_tid:
-	s3_free_atid(cdev, c3cn->tid);
-	c3cn->tid = 0;
-out_err:
-	return -EINVAL;
-}
-
-/**
- * cxgb3i_find_dev - find the interface associated with the given address
- * @ipaddr: ip address
- */
-static struct net_device *
-cxgb3i_find_dev(struct net_device *dev, __be32 ipaddr)
-{
-	struct flowi fl;
-	int err;
-	struct rtable *rt;
-
-	memset(&fl, 0, sizeof(fl));
-	fl.nl_u.ip4_u.daddr = ipaddr;
-
-	err = ip_route_output_key(dev ? dev_net(dev) : &init_net, &rt, &fl);
-	if (!err)
-		return (&rt->dst)->dev;
-
-	return NULL;
-}
-
-/**
- * cxgb3i_c3cn_connect - initiates an iscsi tcp connection to a given address
- * @c3cn: the iscsi tcp connection
- * @usin: destination address
- *
- * return 0 if active open request is sent, < 0 otherwise.
- */
-int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn,
-			struct sockaddr_in *usin)
-{
-	struct rtable *rt;
-	struct cxgb3i_sdev_data *cdata;
-	struct t3cdev *cdev;
-	__be32 sipv4;
-	struct net_device *dstdev;
-	int err;
-
-	c3cn_conn_debug("c3cn 0x%p, dev 0x%p.\n", c3cn, dev);
-
-	if (usin->sin_family != AF_INET)
-		return -EAFNOSUPPORT;
-
-	c3cn->daddr.sin_port = usin->sin_port;
-	c3cn->daddr.sin_addr.s_addr = usin->sin_addr.s_addr;
-
-	dstdev = cxgb3i_find_dev(dev, usin->sin_addr.s_addr);
-	if (!dstdev || !is_cxgb3_dev(dstdev))
-		return -ENETUNREACH;
-
-	if (dstdev->priv_flags & IFF_802_1Q_VLAN)
-		dev = dstdev;
-
-	rt = find_route(dev, c3cn->saddr.sin_addr.s_addr,
-			c3cn->daddr.sin_addr.s_addr,
-			c3cn->saddr.sin_port,
-			c3cn->daddr.sin_port);
-	if (rt == NULL) {
-		c3cn_conn_debug("NO route to 0x%x, port %u, dev %s.\n",
-				c3cn->daddr.sin_addr.s_addr,
-				ntohs(c3cn->daddr.sin_port),
-				dev ? dev->name : "any");
-		return -ENETUNREACH;
-	}
-
-	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
-		c3cn_conn_debug("multi-cast route to 0x%x, port %u, dev %s.\n",
-				c3cn->daddr.sin_addr.s_addr,
-				ntohs(c3cn->daddr.sin_port),
-				dev ? dev->name : "any");
-		ip_rt_put(rt);
-		return -ENETUNREACH;
-	}
-
-	if (!c3cn->saddr.sin_addr.s_addr)
-		c3cn->saddr.sin_addr.s_addr = rt->rt_src;
-
-	/* now commit destination to connection */
-	c3cn->dst_cache = &rt->dst;
-
-	/* try to establish an offloaded connection */
-	dev = cxgb3_egress_dev(c3cn->dst_cache->dev, c3cn, 0);
-	if (dev == NULL) {
-		c3cn_conn_debug("c3cn 0x%p, egress dev NULL.\n", c3cn);
-		return -ENETUNREACH;
-	}
-	cdata = NDEV2CDATA(dev);
-	cdev = cdata->cdev;
-
-	/* get a source port if one hasn't been provided */
-	err = c3cn_get_port(c3cn, cdata);
-	if (err)
-		return err;
-
-	c3cn_conn_debug("c3cn 0x%p get port %u.\n",
-			c3cn, ntohs(c3cn->saddr.sin_port));
-
-	sipv4 = cxgb3i_get_private_ipv4addr(dev);
-	if (!sipv4) {
-		c3cn_conn_debug("c3cn 0x%p, iscsi ip not configured.\n", c3cn);
-		sipv4 = c3cn->saddr.sin_addr.s_addr;
-		cxgb3i_set_private_ipv4addr(dev, sipv4);
-	} else
-		c3cn->saddr.sin_addr.s_addr = sipv4;
-
-	c3cn_conn_debug("c3cn 0x%p, %pI4,%u-%pI4,%u SYN_SENT.\n",
-			c3cn,
-			&c3cn->saddr.sin_addr.s_addr,
-			ntohs(c3cn->saddr.sin_port),
-			&c3cn->daddr.sin_addr.s_addr,
-			ntohs(c3cn->daddr.sin_port));
-
-	c3cn_set_state(c3cn, C3CN_STATE_CONNECTING);
-	if (!initiate_act_open(c3cn, dev))
-		return 0;
-
-	/*
-	 * If we get here, we don't have an offload connection so simply
-	 * return a failure.
-	 */
-	err = -ENOTSUPP;
-
-	/*
-	 * This trashes the connection and releases the local port,
-	 * if necessary.
-	 */
-	c3cn_conn_debug("c3cn 0x%p -> CLOSED.\n", c3cn);
-	c3cn_set_state(c3cn, C3CN_STATE_CLOSED);
-	ip_rt_put(rt);
-	c3cn_put_port(c3cn);
-	return err;
-}
-
-/**
- * cxgb3i_c3cn_rx_credits - ack received tcp data.
- * @c3cn: iscsi tcp connection
- * @copied: # of bytes processed
- *
- * Called after some received data has been read.  It returns RX credits
- * to the HW for the amount of data processed.
- */
-void cxgb3i_c3cn_rx_credits(struct s3_conn *c3cn, int copied)
-{
-	struct t3cdev *cdev;
-	int must_send;
-	u32 credits, dack = 0;
-
-	if (c3cn->state != C3CN_STATE_ESTABLISHED)
-		return;
-
-	credits = c3cn->copied_seq - c3cn->rcv_wup;
-	if (unlikely(!credits))
-		return;
-
-	cdev = c3cn->cdev;
-
-	if (unlikely(cxgb3_rx_credit_thres == 0))
-		return;
-
-	dack = F_RX_DACK_CHANGE | V_RX_DACK_MODE(1);
-
-	/*
-	 * For coalescing to work effectively ensure the receive window has
-	 * at least 16KB left.
-	 */
-	must_send = credits + 16384 >= cxgb3_rcv_win;
-
-	if (must_send || credits >= cxgb3_rx_credit_thres)
-		c3cn->rcv_wup += send_rx_credits(c3cn, credits, dack);
-}
-
-/**
- * cxgb3i_c3cn_send_pdus - send the skbs containing iscsi pdus
- * @c3cn: iscsi tcp connection
- * @skb: skb contains the iscsi pdu
- *
- * Add a list of skbs to a connection send queue. The skbs must comply with
- * the max size limit of the device and have a headroom of at least
- * TX_HEADER_LEN bytes.
- * Return # of bytes queued.
- */
-int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct sk_buff *next;
-	int err, copied = 0;
-
-	spin_lock_bh(&c3cn->lock);
-
-	if (c3cn->state != C3CN_STATE_ESTABLISHED) {
-		c3cn_tx_debug("c3cn 0x%p, not in est. state %u.\n",
-			      c3cn, c3cn->state);
-		err = -EAGAIN;
-		goto out_err;
-	}
-
-	if (c3cn->err) {
-		c3cn_tx_debug("c3cn 0x%p, err %d.\n", c3cn, c3cn->err);
-		err = -EPIPE;
-		goto out_err;
-	}
-
-	if (c3cn->write_seq - c3cn->snd_una >= cxgb3_snd_win) {
-		c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n",
-				c3cn, c3cn->write_seq, c3cn->snd_una,
-				cxgb3_snd_win);
-		err = -ENOBUFS;
-		goto out_err;
-	}
-
-	while (skb) {
-		int frags = skb_shinfo(skb)->nr_frags +
-				(skb->len != skb->data_len);
-
-		if (unlikely(skb_headroom(skb) < TX_HEADER_LEN)) {
-			c3cn_tx_debug("c3cn 0x%p, skb head.\n", c3cn);
-			err = -EINVAL;
-			goto out_err;
-		}
-
-		if (frags >= SKB_WR_LIST_SIZE) {
-			cxgb3i_log_error("c3cn 0x%p, tx frags %d, len %u,%u.\n",
-					 c3cn, skb_shinfo(skb)->nr_frags,
-					 skb->len, skb->data_len);
-			err = -EINVAL;
-			goto out_err;
-		}
-
-		next = skb->next;
-		skb->next = NULL;
-		skb_entail(c3cn, skb, C3CB_FLAG_NO_APPEND | C3CB_FLAG_NEED_HDR);
-		copied += skb->len;
-		c3cn->write_seq += skb->len + ulp_extra_len(skb);
-		skb = next;
-	}
-done:
-	if (likely(skb_queue_len(&c3cn->write_queue)))
-		c3cn_push_tx_frames(c3cn, 1);
-	spin_unlock_bh(&c3cn->lock);
-	return copied;
-
-out_err:
-	if (copied == 0 && err == -EPIPE)
-		copied = c3cn->err ? c3cn->err : -EPIPE;
-	else
-		copied = err;
-	goto done;
-}
-
-static void sdev_data_cleanup(struct cxgb3i_sdev_data *cdata)
-{
-	struct adap_ports *ports = &cdata->ports;
-	struct s3_conn *c3cn;
-	int i;
-
-	for (i = 0; i < cxgb3_max_connect; i++) {
-		if (cdata->sport_conn[i]) {
-			c3cn = cdata->sport_conn[i];
-			cdata->sport_conn[i] = NULL;
-
-			spin_lock_bh(&c3cn->lock);
-			c3cn->cdev = NULL;
-			c3cn_set_flag(c3cn, C3CN_OFFLOAD_DOWN);
-			c3cn_closed(c3cn);
-			spin_unlock_bh(&c3cn->lock);
-		}
-	}
-
-	for (i = 0; i < ports->nports; i++)
-		NDEV2CDATA(ports->lldevs[i]) = NULL;
-
-	cxgb3i_free_big_mem(cdata);
-}
-
-void cxgb3i_sdev_cleanup(void)
-{
-	struct cxgb3i_sdev_data *cdata;
-
-	write_lock(&cdata_rwlock);
-	list_for_each_entry(cdata, &cdata_list, list) {
-		list_del(&cdata->list);
-		sdev_data_cleanup(cdata);
-	}
-	write_unlock(&cdata_rwlock);
-}
-
-int cxgb3i_sdev_init(cxgb3_cpl_handler_func *cpl_handlers)
-{
-	cpl_handlers[CPL_ACT_ESTABLISH] = do_act_establish;
-	cpl_handlers[CPL_ACT_OPEN_RPL] = do_act_open_rpl;
-	cpl_handlers[CPL_PEER_CLOSE] = do_peer_close;
-	cpl_handlers[CPL_ABORT_REQ_RSS] = do_abort_req;
-	cpl_handlers[CPL_ABORT_RPL_RSS] = do_abort_rpl;
-	cpl_handlers[CPL_CLOSE_CON_RPL] = do_close_con_rpl;
-	cpl_handlers[CPL_TX_DMA_ACK] = do_wr_ack;
-	cpl_handlers[CPL_ISCSI_HDR] = do_iscsi_hdr;
-
-	if (cxgb3_max_connect > CXGB3I_MAX_CONN)
-		cxgb3_max_connect = CXGB3I_MAX_CONN;
-	return 0;
-}
-
-/**
- * cxgb3i_sdev_add - allocate and initialize resources for each adapter found
- * @cdev:	t3cdev adapter
- * @client:	cxgb3 driver client
- */
-void cxgb3i_sdev_add(struct t3cdev *cdev, struct cxgb3_client *client)
-{
-	struct cxgb3i_sdev_data *cdata;
-	struct ofld_page_info rx_page_info;
-	unsigned int wr_len;
-	int mapsize = cxgb3_max_connect * sizeof(struct s3_conn *);
-	int i;
-
-	cdata =  cxgb3i_alloc_big_mem(sizeof(*cdata) + mapsize, GFP_KERNEL);
-	if (!cdata) {
-		cxgb3i_log_warn("t3dev 0x%p, offload up, OOM %d.\n",
-				cdev, mapsize);
-		return;
-	}
-
-	if (cdev->ctl(cdev, GET_WR_LEN, &wr_len) < 0 ||
-	    cdev->ctl(cdev, GET_PORTS, &cdata->ports) < 0 ||
-	    cdev->ctl(cdev, GET_RX_PAGE_INFO, &rx_page_info) < 0) {
-		cxgb3i_log_warn("t3dev 0x%p, offload up, ioctl failed.\n",
-				cdev);
-		goto free_cdata;
-	}
-
-	s3_init_wr_tab(wr_len);
-
-	spin_lock_init(&cdata->lock);
-	INIT_LIST_HEAD(&cdata->list);
-	cdata->cdev = cdev;
-	cdata->client = client;
-
-	for (i = 0; i < cdata->ports.nports; i++)
-		NDEV2CDATA(cdata->ports.lldevs[i]) = cdata;
-
-	write_lock(&cdata_rwlock);
-	list_add_tail(&cdata->list, &cdata_list);
-	write_unlock(&cdata_rwlock);
-
-	cxgb3i_log_info("t3dev 0x%p, offload up, added.\n", cdev);
-	return;
-
-free_cdata:
-	cxgb3i_free_big_mem(cdata);
-}
-
-/**
- * cxgb3i_sdev_remove - free the allocated resources for the adapter
- * @cdev:	t3cdev adapter
- */
-void cxgb3i_sdev_remove(struct t3cdev *cdev)
-{
-	struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(cdev);
-
-	cxgb3i_log_info("t3dev 0x%p, offload down, remove.\n", cdev);
-
-	write_lock(&cdata_rwlock);
-	list_del(&cdata->list);
-	write_unlock(&cdata_rwlock);
-
-	sdev_data_cleanup(cdata);
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h
deleted file mode 100644
index 6a1d86b..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * cxgb3i_offload.h: Chelsio S3xx iscsi offloaded tcp connection management
- *
- * Copyright (C) 2003-2008 Chelsio Communications.  All rights reserved.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
- * release for licensing terms and conditions.
- *
- * Written by:	Dimitris Michailidis (dm@chelsio.com)
- *		Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef _CXGB3I_OFFLOAD_H
-#define _CXGB3I_OFFLOAD_H
-
-#include <linux/skbuff.h>
-#include <linux/in.h>
-
-#include "common.h"
-#include "adapter.h"
-#include "t3cdev.h"
-#include "cxgb3_offload.h"
-
-#define cxgb3i_log_error(fmt...) printk(KERN_ERR "cxgb3i: ERR! " fmt)
-#define cxgb3i_log_warn(fmt...)	 printk(KERN_WARNING "cxgb3i: WARN! " fmt)
-#define cxgb3i_log_info(fmt...)  printk(KERN_INFO "cxgb3i: " fmt)
-#define cxgb3i_log_debug(fmt, args...) \
-	printk(KERN_INFO "cxgb3i: %s - " fmt, __func__ , ## args)
-
-/**
- * struct s3_conn - an iscsi tcp connection structure
- *
- * @dev:	net device of with connection
- * @cdev:	adapter t3cdev for net device
- * @flags:	see c3cn_flags below
- * @tid:	connection id assigned by the h/w
- * @qset:	queue set used by connection
- * @mss_idx:	Maximum Segment Size table index
- * @l2t:	ARP resolution entry for offload packets
- * @wr_max:	maximum in-flight writes
- * @wr_avail:	number of writes available
- * @wr_unacked:	writes since last request for completion notification
- * @wr_pending_head: head of pending write queue
- * @wr_pending_tail: tail of pending write queue
- * @cpl_close:	skb for cpl_close_req
- * @cpl_abort_req: skb for cpl_abort_req
- * @cpl_abort_rpl: skb for cpl_abort_rpl
- * @lock:	connection status lock
- * @refcnt:	reference count on connection
- * @state:	connection state
- * @saddr:	source ip/port address
- * @daddr:	destination ip/port address
- * @dst_cache:	reference to destination route
- * @receive_queue: received PDUs
- * @write_queue: un-pushed pending writes
- * @retry_timer: retry timer for various operations
- * @err:	connection error status
- * @callback_lock: lock for opaque user context
- * @user_data:	opaque user context
- * @rcv_nxt:	next receive seq. #
- * @copied_seq:	head of yet unread data
- * @rcv_wup:	rcv_nxt on last window update sent
- * @snd_nxt:	next sequence we send
- * @snd_una:	first byte we want an ack for
- * @write_seq:	tail+1 of data held in send buffer
- */
-struct s3_conn {
-	struct net_device *dev;
-	struct t3cdev *cdev;
-	unsigned long flags;
-	int tid;
-	int qset;
-	int mss_idx;
-	struct l2t_entry *l2t;
-	int wr_max;
-	int wr_avail;
-	int wr_unacked;
-	struct sk_buff *wr_pending_head;
-	struct sk_buff *wr_pending_tail;
-	struct sk_buff *cpl_close;
-	struct sk_buff *cpl_abort_req;
-	struct sk_buff *cpl_abort_rpl;
-	spinlock_t lock;
-	atomic_t refcnt;
-	volatile unsigned int state;
-	struct sockaddr_in saddr;
-	struct sockaddr_in daddr;
-	struct dst_entry *dst_cache;
-	struct sk_buff_head receive_queue;
-	struct sk_buff_head write_queue;
-	struct timer_list retry_timer;
-	int err;
-	rwlock_t callback_lock;
-	void *user_data;
-
-	u32 rcv_nxt;
-	u32 copied_seq;
-	u32 rcv_wup;
-	u32 snd_nxt;
-	u32 snd_una;
-	u32 write_seq;
-};
-
-/*
- * connection state
- */
-enum conn_states {
-	C3CN_STATE_CONNECTING = 1,
-	C3CN_STATE_ESTABLISHED,
-	C3CN_STATE_ACTIVE_CLOSE,
-	C3CN_STATE_PASSIVE_CLOSE,
-	C3CN_STATE_CLOSE_WAIT_1,
-	C3CN_STATE_CLOSE_WAIT_2,
-	C3CN_STATE_ABORTING,
-	C3CN_STATE_CLOSED,
-};
-
-static inline unsigned int c3cn_is_closing(const struct s3_conn *c3cn)
-{
-	return c3cn->state >= C3CN_STATE_ACTIVE_CLOSE;
-}
-static inline unsigned int c3cn_is_established(const struct s3_conn *c3cn)
-{
-	return c3cn->state == C3CN_STATE_ESTABLISHED;
-}
-
-/*
- * Connection flags -- many to track some close related events.
- */
-enum c3cn_flags {
-	C3CN_ABORT_RPL_RCVD,	/* received one ABORT_RPL_RSS message */
-	C3CN_ABORT_REQ_RCVD,	/* received one ABORT_REQ_RSS message */
-	C3CN_ABORT_RPL_PENDING,	/* expecting an abort reply */
-	C3CN_TX_DATA_SENT,	/* already sent a TX_DATA WR */
-	C3CN_ACTIVE_CLOSE_NEEDED,	/* need to be closed */
-	C3CN_OFFLOAD_DOWN	/* offload function off */
-};
-
-/**
- * cxgb3i_sdev_data - Per adapter data.
- * Linked off of each Ethernet device port on the adapter.
- * Also available via the t3cdev structure since we have pointers to our port
- * net_device's there ...
- *
- * @list:	list head to link elements
- * @cdev:	t3cdev adapter
- * @client:	CPL client pointer
- * @ports:	array of adapter ports
- * @sport_next: next port
- * @sport_conn:	source port connection
- */
-struct cxgb3i_sdev_data {
-	struct list_head list;
-	struct t3cdev *cdev;
-	struct cxgb3_client *client;
-	struct adap_ports ports;
-	spinlock_t lock;
-	unsigned int sport_next;
-	struct s3_conn *sport_conn[0];
-};
-#define NDEV2CDATA(ndev) (*(struct cxgb3i_sdev_data **)&(ndev)->ec_ptr)
-#define CXGB3_SDEV_DATA(cdev) NDEV2CDATA((cdev)->lldev)
-
-void cxgb3i_sdev_cleanup(void);
-int cxgb3i_sdev_init(cxgb3_cpl_handler_func *);
-void cxgb3i_sdev_add(struct t3cdev *, struct cxgb3_client *);
-void cxgb3i_sdev_remove(struct t3cdev *);
-
-struct s3_conn *cxgb3i_c3cn_create(void);
-int cxgb3i_c3cn_connect(struct net_device *, struct s3_conn *,
-			struct sockaddr_in *);
-void cxgb3i_c3cn_rx_credits(struct s3_conn *, int);
-int cxgb3i_c3cn_send_pdus(struct s3_conn *, struct sk_buff *);
-void cxgb3i_c3cn_release(struct s3_conn *);
-
-/**
- * cxgb3_skb_cb - control block for received pdu state and ULP mode management.
- *
- * @flag:	see C3CB_FLAG_* below
- * @ulp_mode:	ULP mode/submode of sk_buff
- * @seq:	tcp sequence number
- */
-struct cxgb3_skb_rx_cb {
-	__u32 ddigest;			/* data digest */
-	__u32 pdulen;			/* recovered pdu length */
-};
-
-struct cxgb3_skb_tx_cb {
-	struct sk_buff *wr_next;	/* next wr */
-};
-
-struct cxgb3_skb_cb {
-	__u8 flags;
-	__u8 ulp_mode;
-	__u32 seq;
-	union {
-		struct cxgb3_skb_rx_cb rx;
-		struct cxgb3_skb_tx_cb tx;
-	};
-};
-
-#define CXGB3_SKB_CB(skb)	((struct cxgb3_skb_cb *)&((skb)->cb[0]))
-#define skb_flags(skb)		(CXGB3_SKB_CB(skb)->flags)
-#define skb_ulp_mode(skb)	(CXGB3_SKB_CB(skb)->ulp_mode)
-#define skb_tcp_seq(skb)	(CXGB3_SKB_CB(skb)->seq)
-#define skb_rx_ddigest(skb)	(CXGB3_SKB_CB(skb)->rx.ddigest)
-#define skb_rx_pdulen(skb)	(CXGB3_SKB_CB(skb)->rx.pdulen)
-#define skb_tx_wr_next(skb)	(CXGB3_SKB_CB(skb)->tx.wr_next)
-
-enum c3cb_flags {
-	C3CB_FLAG_NEED_HDR = 1 << 0,	/* packet needs a TX_DATA_WR header */
-	C3CB_FLAG_NO_APPEND = 1 << 1,	/* don't grow this skb */
-	C3CB_FLAG_COMPL = 1 << 2,	/* request WR completion */
-};
-
-/**
- * sge_opaque_hdr -
- * Opaque version of structure the SGE stores at skb->head of TX_DATA packets
- * and for which we must reserve space.
- */
-struct sge_opaque_hdr {
-	void *dev;
-	dma_addr_t addr[MAX_SKB_FRAGS + 1];
-};
-
-/* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
-#define TX_HEADER_LEN \
-		(sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr))
-#define SKB_TX_HEADROOM		SKB_MAX_HEAD(TX_HEADER_LEN)
-
-/*
- * get and set private ip for iscsi traffic
- */
-#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
-
-/* max. connections per adapter */
-#define CXGB3I_MAX_CONN		16384
-#endif /* _CXGB3_OFFLOAD_H */
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
deleted file mode 100644
index dc5e3e7..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * cxgb3i_pdu.c: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, Inc.
- * Copyright (c) 2008 Mike Christie
- * Copyright (c) 2008 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/crypto.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_host.h>
-
-#include "cxgb3i.h"
-#include "cxgb3i_pdu.h"
-
-#ifdef __DEBUG_CXGB3I_RX__
-#define cxgb3i_rx_debug		cxgb3i_log_debug
-#else
-#define cxgb3i_rx_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_CXGB3I_TX__
-#define cxgb3i_tx_debug		cxgb3i_log_debug
-#else
-#define cxgb3i_tx_debug(fmt...)
-#endif
-
-/* always allocate rooms for AHS */
-#define SKB_TX_PDU_HEADER_LEN	\
-	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE)
-static unsigned int skb_extra_headroom;
-static struct page *pad_page;
-
-/*
- * pdu receive, interact with libiscsi_tcp
- */
-static inline int read_pdu_skb(struct iscsi_conn *conn, struct sk_buff *skb,
-			       unsigned int offset, int offloaded)
-{
-	int status = 0;
-	int bytes_read;
-
-	bytes_read = iscsi_tcp_recv_skb(conn, skb, offset, offloaded, &status);
-	switch (status) {
-	case ISCSI_TCP_CONN_ERR:
-		return -EIO;
-	case ISCSI_TCP_SUSPENDED:
-		/* no transfer - just have caller flush queue */
-		return bytes_read;
-	case ISCSI_TCP_SKB_DONE:
-		/*
-		 * pdus should always fit in the skb and we should get
-		 * segment done notifcation.
-		 */
-		iscsi_conn_printk(KERN_ERR, conn, "Invalid pdu or skb.");
-		return -EFAULT;
-	case ISCSI_TCP_SEGMENT_DONE:
-		return bytes_read;
-	default:
-		iscsi_conn_printk(KERN_ERR, conn, "Invalid iscsi_tcp_recv_skb "
-				  "status %d\n", status);
-		return -EINVAL;
-	}
-}
-
-static int cxgb3i_conn_read_pdu_skb(struct iscsi_conn *conn,
-				    struct sk_buff *skb)
-{
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	bool offloaded = 0;
-	unsigned int offset;
-	int rc;
-
-	cxgb3i_rx_debug("conn 0x%p, skb 0x%p, len %u, flag 0x%x.\n",
-			conn, skb, skb->len, skb_ulp_mode(skb));
-
-	if (!iscsi_tcp_recv_segment_is_hdr(tcp_conn)) {
-		iscsi_conn_failure(conn, ISCSI_ERR_PROTO);
-		return -EIO;
-	}
-
-	if (conn->hdrdgst_en && (skb_ulp_mode(skb) & ULP2_FLAG_HCRC_ERROR)) {
-		iscsi_conn_failure(conn, ISCSI_ERR_HDR_DGST);
-		return -EIO;
-	}
-
-	if (conn->datadgst_en && (skb_ulp_mode(skb) & ULP2_FLAG_DCRC_ERROR)) {
-		iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
-		return -EIO;
-	}
-
-	/* iscsi hdr */
-	rc = read_pdu_skb(conn, skb, 0, 0);
-	if (rc <= 0)
-		return rc;
-
-	if (iscsi_tcp_recv_segment_is_hdr(tcp_conn))
-		return 0;
-
-	offset = rc;
-	if (conn->hdrdgst_en)
-		offset += ISCSI_DIGEST_SIZE;
-
-	/* iscsi data */
-	if (skb_ulp_mode(skb) & ULP2_FLAG_DATA_DDPED) {
-		cxgb3i_rx_debug("skb 0x%p, opcode 0x%x, data %u, ddp'ed, "
-				"itt 0x%x.\n",
-				skb,
-				tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
-				tcp_conn->in.datalen,
-				ntohl(tcp_conn->in.hdr->itt));
-		offloaded = 1;
-	} else {
-		cxgb3i_rx_debug("skb 0x%p, opcode 0x%x, data %u, NOT ddp'ed, "
-				"itt 0x%x.\n",
-				skb,
-				tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
-				tcp_conn->in.datalen,
-				ntohl(tcp_conn->in.hdr->itt));
-		offset += sizeof(struct cpl_iscsi_hdr_norss);
-	}
-
-	rc = read_pdu_skb(conn, skb, offset, offloaded);
-	if (rc < 0)
-		return rc;
-	else
-		return 0;
-}
-
-/*
- * pdu transmit, interact with libiscsi_tcp
- */
-static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
-{
-	u8 submode = 0;
-
-	if (hcrc)
-		submode |= 1;
-	if (dcrc)
-		submode |= 2;
-	skb_ulp_mode(skb) = (ULP_MODE_ISCSI << 4) | submode;
-}
-
-void cxgb3i_conn_cleanup_task(struct iscsi_task *task)
-{
-	struct cxgb3i_task_data *tdata = task->dd_data +
-					sizeof(struct iscsi_tcp_task);
-
-	/* never reached the xmit task callout */
-	if (tdata->skb)
-		__kfree_skb(tdata->skb);
-	memset(tdata, 0, sizeof(struct cxgb3i_task_data));
-
-	/* MNC - Do we need a check in case this is called but
-	 * cxgb3i_conn_alloc_pdu has never been called on the task */
-	cxgb3i_release_itt(task, task->hdr_itt);
-	iscsi_tcp_cleanup_task(task);
-}
-
-static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
-				unsigned int offset, unsigned int *off,
-				struct scatterlist **sgp)
-{
-	int i;
-	struct scatterlist *sg;
-
-	for_each_sg(sgl, sg, sgcnt, i) {
-		if (offset < sg->length) {
-			*off = offset;
-			*sgp = sg;
-			return 0;
-		}
-		offset -= sg->length;
-	}
-	return -EFAULT;
-}
-
-static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
-				unsigned int dlen, skb_frag_t *frags,
-				int frag_max)
-{
-	unsigned int datalen = dlen;
-	unsigned int sglen = sg->length - sgoffset;
-	struct page *page = sg_page(sg);
-	int i;
-
-	i = 0;
-	do {
-		unsigned int copy;
-
-		if (!sglen) {
-			sg = sg_next(sg);
-			if (!sg) {
-				cxgb3i_log_error("%s, sg NULL, len %u/%u.\n",
-						 __func__, datalen, dlen);
-				return -EINVAL;
-			}
-			sgoffset = 0;
-			sglen = sg->length;
-			page = sg_page(sg);
-
-		}
-		copy = min(datalen, sglen);
-		if (i && page == frags[i - 1].page &&
-		    sgoffset + sg->offset ==
-			frags[i - 1].page_offset + frags[i - 1].size) {
-			frags[i - 1].size += copy;
-		} else {
-			if (i >= frag_max) {
-				cxgb3i_log_error("%s, too many pages %u, "
-						 "dlen %u.\n", __func__,
-						 frag_max, dlen);
-				return -EINVAL;
-			}
-
-			frags[i].page = page;
-			frags[i].page_offset = sg->offset + sgoffset;
-			frags[i].size = copy;
-			i++;
-		}
-		datalen -= copy;
-		sgoffset += copy;
-		sglen -= copy;
-	} while (datalen);
-
-	return i;
-}
-
-int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
-{
-	struct iscsi_conn *conn = task->conn;
-	struct iscsi_tcp_task *tcp_task = task->dd_data;
-	struct cxgb3i_task_data *tdata = task->dd_data + sizeof(*tcp_task);
-	struct scsi_cmnd *sc = task->sc;
-	int headroom = SKB_TX_PDU_HEADER_LEN;
-
-	tcp_task->dd_data = tdata;
-	task->hdr = NULL;
-
-	/* write command, need to send data pdus */
-	if (skb_extra_headroom && (opcode == ISCSI_OP_SCSI_DATA_OUT ||
-	    (opcode == ISCSI_OP_SCSI_CMD &&
-	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE))))
-		headroom += min(skb_extra_headroom, conn->max_xmit_dlength);
-
-	tdata->skb = alloc_skb(TX_HEADER_LEN + headroom, GFP_ATOMIC);
-	if (!tdata->skb)
-		return -ENOMEM;
-	skb_reserve(tdata->skb, TX_HEADER_LEN);
-
-	cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n",
-			task, opcode, tdata->skb);
-
-	task->hdr = (struct iscsi_hdr *)tdata->skb->data;
-	task->hdr_max = SKB_TX_PDU_HEADER_LEN;
-
-	/* data_out uses scsi_cmd's itt */
-	if (opcode != ISCSI_OP_SCSI_DATA_OUT)
-		cxgb3i_reserve_itt(task, &task->hdr->itt);
-
-	return 0;
-}
-
-int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
-			      unsigned int count)
-{
-	struct iscsi_conn *conn = task->conn;
-	struct iscsi_tcp_task *tcp_task = task->dd_data;
-	struct cxgb3i_task_data *tdata = tcp_task->dd_data;
-	struct sk_buff *skb = tdata->skb;
-	unsigned int datalen = count;
-	int i, padlen = iscsi_padding(count);
-	struct page *pg;
-
-	cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n",
-			task, task->sc, offset, count, skb);
-
-	skb_put(skb, task->hdr_len);
-	tx_skb_setmode(skb, conn->hdrdgst_en, datalen ? conn->datadgst_en : 0);
-	if (!count)
-		return 0;
-
-	if (task->sc) {
-		struct scsi_data_buffer *sdb = scsi_out(task->sc);
-		struct scatterlist *sg = NULL;
-		int err;
-
-		tdata->offset = offset;
-		tdata->count = count;
-		err = sgl_seek_offset(sdb->table.sgl, sdb->table.nents,
-					tdata->offset, &tdata->sgoffset, &sg);
-		if (err < 0) {
-			cxgb3i_log_warn("tpdu, sgl %u, bad offset %u/%u.\n",
-					sdb->table.nents, tdata->offset,
-					sdb->length);
-			return err;
-		}
-		err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count,
-					tdata->frags, MAX_PDU_FRAGS);
-		if (err < 0) {
-			cxgb3i_log_warn("tpdu, sgl %u, bad offset %u + %u.\n",
-					sdb->table.nents, tdata->offset,
-					tdata->count);
-			return err;
-		}
-		tdata->nr_frags = err;
-
-		if (tdata->nr_frags > MAX_SKB_FRAGS ||
-		    (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
-			char *dst = skb->data + task->hdr_len;
-			skb_frag_t *frag = tdata->frags;
-
-			/* data fits in the skb's headroom */
-			for (i = 0; i < tdata->nr_frags; i++, frag++) {
-				char *src = kmap_atomic(frag->page,
-							KM_SOFTIRQ0);
-
-				memcpy(dst, src+frag->page_offset, frag->size);
-				dst += frag->size;
-				kunmap_atomic(src, KM_SOFTIRQ0);
-			}
-			if (padlen) {
-				memset(dst, 0, padlen);
-				padlen = 0;
-			}
-			skb_put(skb, count + padlen);
-		} else {
-			/* data fit into frag_list */
-			for (i = 0; i < tdata->nr_frags; i++)
-				get_page(tdata->frags[i].page);
-
-			memcpy(skb_shinfo(skb)->frags, tdata->frags,
-				sizeof(skb_frag_t) * tdata->nr_frags);
-			skb_shinfo(skb)->nr_frags = tdata->nr_frags;
-			skb->len += count;
-			skb->data_len += count;
-			skb->truesize += count;
-		}
-
-	} else {
-		pg = virt_to_page(task->data);
-
-		get_page(pg);
-		skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data),
-					count);
-		skb->len += count;
-		skb->data_len += count;
-		skb->truesize += count;
-	}
-
-	if (padlen) {
-		i = skb_shinfo(skb)->nr_frags;
-		get_page(pad_page);
-		skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, pad_page, 0,
-				 padlen);
-
-		skb->data_len += padlen;
-		skb->truesize += padlen;
-		skb->len += padlen;
-	}
-
-	return 0;
-}
-
-int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
-{
-	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct iscsi_tcp_task *tcp_task = task->dd_data;
-	struct cxgb3i_task_data *tdata = tcp_task->dd_data;
-	struct sk_buff *skb = tdata->skb;
-	unsigned int datalen;
-	int err;
-
-	if (!skb)
-		return 0;
-
-	datalen = skb->data_len;
-	tdata->skb = NULL;
-	err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb);
-	if (err > 0) {
-		int pdulen = err;
-
-		cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
-				task, skb, skb->len, skb->data_len, err);
-
-		if (task->conn->hdrdgst_en)
-			pdulen += ISCSI_DIGEST_SIZE;
-		if (datalen && task->conn->datadgst_en)
-			pdulen += ISCSI_DIGEST_SIZE;
-
-		task->conn->txdata_octets += pdulen;
-		return 0;
-	}
-
-	if (err == -EAGAIN || err == -ENOBUFS) {
-		/* reset skb to send when we are called again */
-		tdata->skb = skb;
-		return err;
-	}
-
-	kfree_skb(skb);
-	cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
-			task->itt, skb, skb->len, skb->data_len, err);
-	iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
-	iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
-	return err;
-}
-
-int cxgb3i_pdu_init(void)
-{
-	if (SKB_TX_HEADROOM > (512 * MAX_SKB_FRAGS))
-		skb_extra_headroom = SKB_TX_HEADROOM;
-	pad_page = alloc_page(GFP_KERNEL);
-	if (!pad_page)
-		return -ENOMEM;
-	memset(page_address(pad_page), 0, PAGE_SIZE);
-	return 0;
-}
-
-void cxgb3i_pdu_cleanup(void)
-{
-	if (pad_page) {
-		__free_page(pad_page);
-		pad_page = NULL;
-	}
-}
-
-void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb;
-	unsigned int read = 0;
-	struct iscsi_conn *conn = c3cn->user_data;
-	int err = 0;
-
-	cxgb3i_rx_debug("cn 0x%p.\n", c3cn);
-
-	read_lock(&c3cn->callback_lock);
-	if (unlikely(!conn || conn->suspend_rx)) {
-		cxgb3i_rx_debug("conn 0x%p, id %d, suspend_rx %lu!\n",
-				conn, conn ? conn->id : 0xFF,
-				conn ? conn->suspend_rx : 0xFF);
-		read_unlock(&c3cn->callback_lock);
-		return;
-	}
-	skb = skb_peek(&c3cn->receive_queue);
-	while (!err && skb) {
-		__skb_unlink(skb, &c3cn->receive_queue);
-		read += skb_rx_pdulen(skb);
-		cxgb3i_rx_debug("conn 0x%p, cn 0x%p, rx skb 0x%p, pdulen %u.\n",
-				conn, c3cn, skb, skb_rx_pdulen(skb));
-		err = cxgb3i_conn_read_pdu_skb(conn, skb);
-		__kfree_skb(skb);
-		skb = skb_peek(&c3cn->receive_queue);
-	}
-	read_unlock(&c3cn->callback_lock);
-	c3cn->copied_seq += read;
-	cxgb3i_c3cn_rx_credits(c3cn, read);
-	conn->rxdata_octets += read;
-
-	if (err) {
-		cxgb3i_log_info("conn 0x%p rx failed err %d.\n", conn, err);
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-	}
-}
-
-void cxgb3i_conn_tx_open(struct s3_conn *c3cn)
-{
-	struct iscsi_conn *conn = c3cn->user_data;
-
-	cxgb3i_tx_debug("cn 0x%p.\n", c3cn);
-	if (conn) {
-		cxgb3i_tx_debug("cn 0x%p, cid %d.\n", c3cn, conn->id);
-		iscsi_conn_queue_work(conn);
-	}
-}
-
-void cxgb3i_conn_closing(struct s3_conn *c3cn)
-{
-	struct iscsi_conn *conn;
-
-	read_lock(&c3cn->callback_lock);
-	conn = c3cn->user_data;
-	if (conn && c3cn->state != C3CN_STATE_ESTABLISHED)
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-	read_unlock(&c3cn->callback_lock);
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.h b/drivers/scsi/cxgb3i/cxgb3i_pdu.h
deleted file mode 100644
index 0770b23..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * cxgb3i_ulp2.h: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef __CXGB3I_ULP2_PDU_H__
-#define __CXGB3I_ULP2_PDU_H__
-
-struct cpl_iscsi_hdr_norss {
-	union opcode_tid ot;
-	u16 pdu_len_ddp;
-	u16 len;
-	u32 seq;
-	u16 urg;
-	u8 rsvd;
-	u8 status;
-};
-
-struct cpl_rx_data_ddp_norss {
-	union opcode_tid ot;
-	u16 urg;
-	u16 len;
-	u32 seq;
-	u32 nxt_seq;
-	u32 ulp_crc;
-	u32 ddp_status;
-};
-
-#define RX_DDP_STATUS_IPP_SHIFT		27	/* invalid pagepod */
-#define RX_DDP_STATUS_TID_SHIFT		26	/* tid mismatch */
-#define RX_DDP_STATUS_COLOR_SHIFT	25	/* color mismatch */
-#define RX_DDP_STATUS_OFFSET_SHIFT	24	/* offset mismatch */
-#define RX_DDP_STATUS_ULIMIT_SHIFT	23	/* ulimit error */
-#define RX_DDP_STATUS_TAG_SHIFT		22	/* tag mismatch */
-#define RX_DDP_STATUS_DCRC_SHIFT	21	/* dcrc error */
-#define RX_DDP_STATUS_HCRC_SHIFT	20	/* hcrc error */
-#define RX_DDP_STATUS_PAD_SHIFT		19	/* pad error */
-#define RX_DDP_STATUS_PPP_SHIFT		18	/* pagepod parity error */
-#define RX_DDP_STATUS_LLIMIT_SHIFT	17	/* llimit error */
-#define RX_DDP_STATUS_DDP_SHIFT		16	/* ddp'able */
-#define RX_DDP_STATUS_PMM_SHIFT		15	/* pagepod mismatch */
-
-#define ULP2_FLAG_DATA_READY		0x1
-#define ULP2_FLAG_DATA_DDPED		0x2
-#define ULP2_FLAG_HCRC_ERROR		0x10
-#define ULP2_FLAG_DCRC_ERROR		0x20
-#define ULP2_FLAG_PAD_ERROR		0x40
-
-void cxgb3i_conn_closing(struct s3_conn *c3cn);
-void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn);
-void cxgb3i_conn_tx_open(struct s3_conn *c3cn);
-#endif
diff --git a/drivers/scsi/cxgbi/Kconfig b/drivers/scsi/cxgbi/Kconfig
new file mode 100644
index 0000000..17eb5d52
--- /dev/null
+++ b/drivers/scsi/cxgbi/Kconfig
@@ -0,0 +1,2 @@
+source "drivers/scsi/cxgbi/cxgb3i/Kconfig"
+source "drivers/scsi/cxgbi/cxgb4i/Kconfig"
diff --git a/drivers/scsi/cxgbi/Makefile b/drivers/scsi/cxgbi/Makefile
new file mode 100644
index 0000000..86007e3
--- /dev/null
+++ b/drivers/scsi/cxgbi/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_SCSI_CXGB3_ISCSI)	+= libcxgbi.o cxgb3i/
+obj-$(CONFIG_SCSI_CXGB4_ISCSI)	+= libcxgbi.o cxgb4i/
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kbuild b/drivers/scsi/cxgbi/cxgb3i/Kbuild
new file mode 100644
index 0000000..09dbf9e
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb3i/Kbuild
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3
+
+obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kconfig b/drivers/scsi/cxgbi/cxgb3i/Kconfig
new file mode 100644
index 0000000..5cf4e98
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb3i/Kconfig
@@ -0,0 +1,7 @@
+config SCSI_CXGB3_ISCSI
+	tristate "Chelsio T3 iSCSI support"
+	depends on CHELSIO_T3_DEPENDS
+	select CHELSIO_T3
+	select SCSI_ISCSI_ATTRS
+	---help---
+	  This driver supports iSCSI offload for the Chelsio T3 devices.
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
new file mode 100644
index 0000000..a129a17
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -0,0 +1,1465 @@
+/*
+ * cxgb3i_offload.c: Chelsio S3xx iscsi offloaded tcp connection management
+ *
+ * Copyright (C) 2003-2008 Chelsio Communications.  All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
+ * release for licensing terms and conditions.
+ *
+ * Written by:	Dimitris Michailidis (dm@chelsio.com)
+ *		Karen Xie (kxie@chelsio.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <scsi/scsi_host.h>
+
+#include "common.h"
+#include "t3_cpl.h"
+#include "t3cdev.h"
+#include "cxgb3_defs.h"
+#include "cxgb3_ctl_defs.h"
+#include "cxgb3_offload.h"
+#include "firmware_exports.h"
+#include "cxgb3i.h"
+
+static unsigned int dbg_level;
+#include "../libcxgbi.h"
+
+#define DRV_MODULE_NAME         "cxgb3i"
+#define DRV_MODULE_DESC         "Chelsio T3 iSCSI Driver"
+#define DRV_MODULE_VERSION	"2.0.0"
+#define DRV_MODULE_RELDATE	"Jun. 2010"
+
+static char version[] =
+	DRV_MODULE_DESC " " DRV_MODULE_NAME
+	" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Chelsio Communications, Inc.");
+MODULE_DESCRIPTION(DRV_MODULE_DESC);
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(dbg_level, uint, 0644);
+MODULE_PARM_DESC(dbg_level, "debug flag (default=0)");
+
+static int cxgb3i_rcv_win = 256 * 1024;
+module_param(cxgb3i_rcv_win, int, 0644);
+MODULE_PARM_DESC(cxgb3i_rcv_win, "TCP receive window in bytes (default=256KB)");
+
+static int cxgb3i_snd_win = 128 * 1024;
+module_param(cxgb3i_snd_win, int, 0644);
+MODULE_PARM_DESC(cxgb3i_snd_win, "TCP send window in bytes (default=128KB)");
+
+static int cxgb3i_rx_credit_thres = 10 * 1024;
+module_param(cxgb3i_rx_credit_thres, int, 0644);
+MODULE_PARM_DESC(rx_credit_thres,
+		 "RX credits return threshold in bytes (default=10KB)");
+
+static unsigned int cxgb3i_max_connect = 8 * 1024;
+module_param(cxgb3i_max_connect, uint, 0644);
+MODULE_PARM_DESC(cxgb3i_max_connect, "Max. # of connections (default=8092)");
+
+static unsigned int cxgb3i_sport_base = 20000;
+module_param(cxgb3i_sport_base, uint, 0644);
+MODULE_PARM_DESC(cxgb3i_sport_base, "starting port number (default=20000)");
+
+static void cxgb3i_dev_open(struct t3cdev *);
+static void cxgb3i_dev_close(struct t3cdev *);
+static void cxgb3i_dev_event_handler(struct t3cdev *, u32, u32);
+
+static struct cxgb3_client t3_client = {
+	.name = DRV_MODULE_NAME,
+	.handlers = cxgb3i_cpl_handlers,
+	.add = cxgb3i_dev_open,
+	.remove = cxgb3i_dev_close,
+	.event_handler = cxgb3i_dev_event_handler,
+};
+
+static struct scsi_host_template cxgb3i_host_template = {
+	.module		= THIS_MODULE,
+	.name		= DRV_MODULE_NAME,
+	.proc_name	= DRV_MODULE_NAME,
+	.can_queue	= CXGB3I_SCSI_HOST_QDEPTH,
+	.queuecommand	= iscsi_queuecommand,
+	.change_queue_depth = iscsi_change_queue_depth,
+	.sg_tablesize	= SG_ALL,
+	.max_sectors	= 0xFFFF,
+	.cmd_per_lun	= ISCSI_DEF_CMD_PER_LUN,
+	.eh_abort_handler = iscsi_eh_abort,
+	.eh_device_reset_handler = iscsi_eh_device_reset,
+	.eh_target_reset_handler = iscsi_eh_recover_target,
+	.target_alloc	= iscsi_target_alloc,
+	.use_clustering	= DISABLE_CLUSTERING,
+	.this_id	= -1,
+};
+
+static struct iscsi_transport cxgb3i_iscsi_transport = {
+	.owner		= THIS_MODULE,
+	.name		= DRV_MODULE_NAME,
+	/* owner and name should be set already */
+	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+				| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+				CAP_PADDING_OFFLOAD,
+	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
+				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
+				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
+				ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
+				ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
+				ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
+				ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+				ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
+				ISCSI_PERSISTENT_ADDRESS |
+				ISCSI_TARGET_NAME | ISCSI_TPGT |
+				ISCSI_USERNAME | ISCSI_PASSWORD |
+				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+				ISCSI_PING_TMO | ISCSI_RECV_TMO |
+				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+				ISCSI_HOST_INITIATOR_NAME |
+				ISCSI_HOST_NETDEV_NAME,
+	.get_host_param	= cxgbi_get_host_param,
+	.set_host_param	= cxgbi_set_host_param,
+	/* session management */
+	.create_session	= cxgbi_create_session,
+	.destroy_session	= cxgbi_destroy_session,
+	.get_session_param = iscsi_session_get_param,
+	/* connection management */
+	.create_conn	= cxgbi_create_conn,
+	.bind_conn	= cxgbi_bind_conn,
+	.destroy_conn	= iscsi_tcp_conn_teardown,
+	.start_conn	= iscsi_conn_start,
+	.stop_conn	= iscsi_conn_stop,
+	.get_conn_param	= cxgbi_get_conn_param,
+	.set_param	= cxgbi_set_conn_param,
+	.get_stats	= cxgbi_get_conn_stats,
+	/* pdu xmit req from user space */
+	.send_pdu	= iscsi_conn_send_pdu,
+	/* task */
+	.init_task	= iscsi_tcp_task_init,
+	.xmit_task	= iscsi_tcp_task_xmit,
+	.cleanup_task	= cxgbi_cleanup_task,
+	/* pdu */
+	.alloc_pdu	= cxgbi_conn_alloc_pdu,
+	.init_pdu	= cxgbi_conn_init_pdu,
+	.xmit_pdu	= cxgbi_conn_xmit_pdu,
+	.parse_pdu_itt	= cxgbi_parse_pdu_itt,
+	/* TCP connect/disconnect */
+	.ep_connect	= cxgbi_ep_connect,
+	.ep_poll	= cxgbi_ep_poll,
+	.ep_disconnect	= cxgbi_ep_disconnect,
+	/* Error recovery timeout call */
+	.session_recovery_timedout = iscsi_session_recovery_timedout,
+};
+
+static struct scsi_transport_template *cxgb3i_stt;
+
+/*
+ * CPL (Chelsio Protocol Language) defines a message passing interface between
+ * the host driver and Chelsio asic.
+ * The section below implments CPLs that related to iscsi tcp connection
+ * open/close/abort and data send/receive.
+ */
+
+static int push_tx_frames(struct cxgbi_sock *csk, int req_completion);
+
+static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
+			      const struct l2t_entry *e)
+{
+	unsigned int wscale = cxgbi_sock_compute_wscale(cxgb3i_rcv_win);
+	struct cpl_act_open_req *req = (struct cpl_act_open_req *)skb->head;
+
+	skb->priority = CPL_PRIORITY_SETUP;
+
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, csk->atid));
+	req->local_port = csk->saddr.sin_port;
+	req->peer_port = csk->daddr.sin_port;
+	req->local_ip = csk->saddr.sin_addr.s_addr;
+	req->peer_ip = csk->daddr.sin_addr.s_addr;
+
+	req->opt0h = htonl(V_KEEP_ALIVE(1) | F_TCAM_BYPASS |
+			V_WND_SCALE(wscale) | V_MSS_IDX(csk->mss_idx) |
+			V_L2T_IDX(e->idx) | V_TX_CHANNEL(e->smt_idx));
+	req->opt0l = htonl(V_ULP_MODE(ULP2_MODE_ISCSI) |
+			V_RCV_BUFSIZ(cxgb3i_rcv_win>>10));
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, %pI4:%u-%pI4:%u, %u,%u,%u.\n",
+		csk, csk->state, csk->flags, csk->atid,
+		&req->local_ip, ntohs(req->local_port),
+		&req->peer_ip, ntohs(req->peer_port),
+		csk->mss_idx, e->idx, e->smt_idx);
+
+	l2t_send(csk->cdev->lldev, skb, csk->l2t);
+}
+
+static inline void act_open_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
+{
+	cxgbi_sock_act_open_req_arp_failure(NULL, skb);
+}
+
+/*
+ * CPL connection close request: host ->
+ *
+ * Close a connection by sending a CPL_CLOSE_CON_REQ message and queue it to
+ * the write queue (i.e., after any unsent txt data).
+ */
+static void send_close_req(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->cpl_close;
+	struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->head;
+	unsigned int tid = csk->tid;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	csk->cpl_close = NULL;
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_CLOSE_CON));
+	req->wr.wr_lo = htonl(V_WR_TID(tid));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
+	req->rsvd = htonl(csk->write_seq);
+
+	cxgbi_sock_skb_entail(csk, skb);
+	if (csk->state >= CTP_ESTABLISHED)
+		push_tx_frames(csk, 1);
+}
+
+/*
+ * CPL connection abort request: host ->
+ *
+ * Send an ABORT_REQ message. Makes sure we do not send multiple ABORT_REQs
+ * for the same connection and also that we do not try to send a message
+ * after the connection has closed.
+ */
+static void abort_arp_failure(struct t3cdev *tdev, struct sk_buff *skb)
+{
+	struct cpl_abort_req *req = cplhdr(skb);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"t3dev 0x%p, tid %u, skb 0x%p.\n",
+		tdev, GET_TID(req), skb);
+	req->cmd = CPL_ABORT_NO_RST;
+	cxgb3_ofld_send(tdev, skb);
+}
+
+static void send_abort_req(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->cpl_abort_req;
+	struct cpl_abort_req *req;
+
+	if (unlikely(csk->state == CTP_ABORTING || !skb))
+		return;
+	cxgbi_sock_set_state(csk, CTP_ABORTING);
+	cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_PENDING);
+	/* Purge the send queue so we don't send anything after an abort. */
+	cxgbi_sock_purge_write_queue(csk);
+
+	csk->cpl_abort_req = NULL;
+	req = (struct cpl_abort_req *)skb->head;
+	skb->priority = CPL_PRIORITY_DATA;
+	set_arp_failure_handler(skb, abort_arp_failure);
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_REQ));
+	req->wr.wr_lo = htonl(V_WR_TID(csk->tid));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ABORT_REQ, csk->tid));
+	req->rsvd0 = htonl(csk->snd_nxt);
+	req->rsvd1 = !cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT);
+	req->cmd = CPL_ABORT_SEND_RST;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, snd_nxt %u, 0x%x.\n",
+		csk, csk->state, csk->flags, csk->tid, csk->snd_nxt,
+		req->rsvd1);
+
+	l2t_send(csk->cdev->lldev, skb, csk->l2t);
+}
+
+/*
+ * CPL connection abort reply: host ->
+ *
+ * Send an ABORT_RPL message in response of the ABORT_REQ received.
+ */
+static void send_abort_rpl(struct cxgbi_sock *csk, int rst_status)
+{
+	struct sk_buff *skb = csk->cpl_abort_rpl;
+	struct cpl_abort_rpl *rpl = (struct cpl_abort_rpl *)skb->head;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, status %d.\n",
+		csk, csk->state, csk->flags, csk->tid, rst_status);
+
+	csk->cpl_abort_rpl = NULL;
+	skb->priority = CPL_PRIORITY_DATA;
+	rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL));
+	rpl->wr.wr_lo = htonl(V_WR_TID(csk->tid));
+	OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, csk->tid));
+	rpl->cmd = rst_status;
+	cxgb3_ofld_send(csk->cdev->lldev, skb);
+}
+
+/*
+ * CPL connection rx data ack: host ->
+ * Send RX credits through an RX_DATA_ACK CPL message. Returns the number of
+ * credits sent.
+ */
+static u32 send_rx_credits(struct cxgbi_sock *csk, u32 credits)
+{
+	struct sk_buff *skb;
+	struct cpl_rx_data_ack *req;
+	u32 dack = F_RX_DACK_CHANGE | V_RX_DACK_MODE(1);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx,%u, credit %u, dack %u.\n",
+		csk, csk->state, csk->flags, csk->tid, credits, dack);
+
+	skb = alloc_wr(sizeof(*req), 0, GFP_ATOMIC);
+	if (!skb) {
+		pr_info("csk 0x%p, credit %u, OOM.\n", csk, credits);
+		return 0;
+	}
+	req = (struct cpl_rx_data_ack *)skb->head;
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, csk->tid));
+	req->credit_dack = htonl(F_RX_DACK_CHANGE | V_RX_DACK_MODE(1) |
+				V_RX_CREDITS(credits));
+	skb->priority = CPL_PRIORITY_ACK;
+	cxgb3_ofld_send(csk->cdev->lldev, skb);
+	return credits;
+}
+
+/*
+ * CPL connection tx data: host ->
+ *
+ * Send iscsi PDU via TX_DATA CPL message. Returns the number of
+ * credits sent.
+ * Each TX_DATA consumes work request credit (wrs), so we need to keep track of
+ * how many we've used so far and how many are pending (i.e., yet ack'ed by T3).
+ */
+
+static unsigned int wrlen __read_mostly;
+static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly;
+
+static void init_wr_tab(unsigned int wr_len)
+{
+	int i;
+
+	if (skb_wrs[1])		/* already initialized */
+		return;
+	for (i = 1; i < SKB_WR_LIST_SIZE; i++) {
+		int sgl_len = (3 * i) / 2 + (i & 1);
+
+		sgl_len += 3;
+		skb_wrs[i] = (sgl_len <= wr_len
+			      ? 1 : 1 + (sgl_len - 2) / (wr_len - 1));
+	}
+	wrlen = wr_len * 8;
+}
+
+static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb,
+				   int len, int req_completion)
+{
+	struct tx_data_wr *req;
+	struct l2t_entry *l2t = csk->l2t;
+
+	skb_reset_transport_header(skb);
+	req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req));
+	req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA) |
+			(req_completion ? F_WR_COMPL : 0));
+	req->wr_lo = htonl(V_WR_TID(csk->tid));
+	/* len includes the length of any HW ULP additions */
+	req->len = htonl(len);
+	/* V_TX_ULP_SUBMODE sets both the mode and submode */
+	req->flags = htonl(V_TX_ULP_SUBMODE(cxgbi_skcb_ulp_mode(skb)) |
+			   V_TX_SHOVE((skb_peek(&csk->write_queue) ? 0 : 1)));
+	req->sndseq = htonl(csk->snd_nxt);
+	req->param = htonl(V_TX_PORT(l2t->smt_idx));
+
+	if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT)) {
+		req->flags |= htonl(V_TX_ACK_PAGES(2) | F_TX_INIT |
+				    V_TX_CPU_IDX(csk->rss_qid));
+		/* sendbuffer is in units of 32KB. */
+		req->param |= htonl(V_TX_SNDBUF(cxgb3i_snd_win >> 15));
+		cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT);
+	}
+}
+
+/**
+ * push_tx_frames -- start transmit
+ * @c3cn: the offloaded connection
+ * @req_completion: request wr_ack or not
+ *
+ * Prepends TX_DATA_WR or CPL_CLOSE_CON_REQ headers to buffers waiting in a
+ * connection's send queue and sends them on to T3.  Must be called with the
+ * connection's lock held.  Returns the amount of send buffer space that was
+ * freed as a result of sending queued data to T3.
+ */
+
+static void arp_failure_skb_discard(struct t3cdev *dev, struct sk_buff *skb)
+{
+	kfree_skb(skb);
+}
+
+static int push_tx_frames(struct cxgbi_sock *csk, int req_completion)
+{
+	int total_size = 0;
+	struct sk_buff *skb;
+
+	if (unlikely(csk->state < CTP_ESTABLISHED ||
+		csk->state == CTP_CLOSE_WAIT_1 || csk->state >= CTP_ABORTING)) {
+			log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+				"csk 0x%p,%u,0x%lx,%u, in closing state.\n",
+				csk, csk->state, csk->flags, csk->tid);
+		return 0;
+	}
+
+	while (csk->wr_cred && (skb = skb_peek(&csk->write_queue)) != NULL) {
+		int len = skb->len;	/* length before skb_push */
+		int frags = skb_shinfo(skb)->nr_frags + (len != skb->data_len);
+		int wrs_needed = skb_wrs[frags];
+
+		if (wrs_needed > 1 && len + sizeof(struct tx_data_wr) <= wrlen)
+			wrs_needed = 1;
+
+		WARN_ON(frags >= SKB_WR_LIST_SIZE || wrs_needed < 1);
+
+		if (csk->wr_cred < wrs_needed) {
+			log_debug(1 << CXGBI_DBG_PDU_TX,
+				"csk 0x%p, skb len %u/%u, frag %u, wr %d<%u.\n",
+				csk, skb->len, skb->data_len, frags,
+				wrs_needed, csk->wr_cred);
+			break;
+		}
+
+		__skb_unlink(skb, &csk->write_queue);
+		skb->priority = CPL_PRIORITY_DATA;
+		skb->csum = wrs_needed;	/* remember this until the WR_ACK */
+		csk->wr_cred -= wrs_needed;
+		csk->wr_una_cred += wrs_needed;
+		cxgbi_sock_enqueue_wr(csk, skb);
+
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p, enqueue, skb len %u/%u, frag %u, wr %d, "
+			"left %u, unack %u.\n",
+			csk, skb->len, skb->data_len, frags, skb->csum,
+			csk->wr_cred, csk->wr_una_cred);
+
+		if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) {
+			if ((req_completion &&
+				csk->wr_una_cred == wrs_needed) ||
+			     csk->wr_una_cred >= csk->wr_max_cred / 2) {
+				req_completion = 1;
+				csk->wr_una_cred = 0;
+			}
+			len += cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
+			make_tx_data_wr(csk, skb, len, req_completion);
+			csk->snd_nxt += len;
+			cxgbi_skcb_clear_flag(skb, SKCBF_TX_NEED_HDR);
+		}
+		total_size += skb->truesize;
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p, tid 0x%x, send skb 0x%p.\n",
+			csk, csk->tid, skb);
+		set_arp_failure_handler(skb, arp_failure_skb_discard);
+		l2t_send(csk->cdev->lldev, skb, csk->l2t);
+	}
+	return total_size;
+}
+
+/*
+ * Process a CPL_ACT_ESTABLISH message: -> host
+ * Updates connection state from an active establish CPL message.  Runs with
+ * the connection lock held.
+ */
+
+static inline void free_atid(struct cxgbi_sock *csk)
+{
+	if (cxgbi_sock_flag(csk, CTPF_HAS_ATID)) {
+		cxgb3_free_atid(csk->cdev->lldev, csk->atid);
+		cxgbi_sock_clear_flag(csk, CTPF_HAS_ATID);
+		cxgbi_sock_put(csk);
+	}
+}
+
+static int do_act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+	struct cpl_act_establish *req = cplhdr(skb);
+	unsigned int tid = GET_TID(req);
+	unsigned int atid = G_PASS_OPEN_TID(ntohl(req->tos_tid));
+	u32 rcv_isn = ntohl(req->rcv_isn);	/* real RCV_ISN + 1 */
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"atid 0x%x,tid 0x%x, csk 0x%p,%u,0x%lx, isn %u.\n",
+		atid, atid, csk, csk->state, csk->flags, rcv_isn);
+
+	cxgbi_sock_get(csk);
+	cxgbi_sock_set_flag(csk, CTPF_HAS_TID);
+	csk->tid = tid;
+	cxgb3_insert_tid(csk->cdev->lldev, &t3_client, csk, tid);
+
+	free_atid(csk);
+
+	csk->rss_qid = G_QNUM(ntohs(skb->csum));
+
+	spin_lock_bh(&csk->lock);
+	if (csk->retry_timer.function) {
+		del_timer(&csk->retry_timer);
+		csk->retry_timer.function = NULL;
+	}
+
+	if (unlikely(csk->state != CTP_ACTIVE_OPEN))
+		pr_info("csk 0x%p,%u,0x%lx,%u, got EST.\n",
+			csk, csk->state, csk->flags, csk->tid);
+
+	csk->copied_seq = csk->rcv_wup = csk->rcv_nxt = rcv_isn;
+	if (cxgb3i_rcv_win > (M_RCV_BUFSIZ << 10))
+		csk->rcv_wup -= cxgb3i_rcv_win - (M_RCV_BUFSIZ << 10);
+
+	cxgbi_sock_established(csk, ntohl(req->snd_isn), ntohs(req->tcp_opt));
+
+	if (unlikely(cxgbi_sock_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED)))
+		/* upper layer has requested closing */
+		send_abort_req(csk);
+	else {
+		if (skb_queue_len(&csk->write_queue))
+			push_tx_frames(csk, 1);
+		cxgbi_conn_tx_open(csk);
+	}
+
+	spin_unlock_bh(&csk->lock);
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process a CPL_ACT_OPEN_RPL message: -> host
+ * Handle active open failures.
+ */
+static int act_open_rpl_status_to_errno(int status)
+{
+	switch (status) {
+	case CPL_ERR_CONN_RESET:
+		return -ECONNREFUSED;
+	case CPL_ERR_ARP_MISS:
+		return -EHOSTUNREACH;
+	case CPL_ERR_CONN_TIMEDOUT:
+		return -ETIMEDOUT;
+	case CPL_ERR_TCAM_FULL:
+		return -ENOMEM;
+	case CPL_ERR_CONN_EXIST:
+		return -EADDRINUSE;
+	default:
+		return -EIO;
+	}
+}
+
+static void act_open_retry_timer(unsigned long data)
+{
+	struct sk_buff *skb;
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+	skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_ATOMIC);
+	if (!skb)
+		cxgbi_sock_fail_act_open(csk, -ENOMEM);
+	else {
+		skb->sk = (struct sock *)csk;
+		set_arp_failure_handler(skb, act_open_arp_failure);
+		send_act_open_req(csk, skb, csk->l2t);
+	}
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+
+static int do_act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+	struct cpl_act_open_rpl *rpl = cplhdr(skb);
+
+	pr_info("csk 0x%p,%u,0x%lx,%u, status %u, %pI4:%u-%pI4:%u.\n",
+		csk, csk->state, csk->flags, csk->atid, rpl->status,
+		&csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
+		&csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port));
+
+	if (rpl->status != CPL_ERR_TCAM_FULL &&
+	    rpl->status != CPL_ERR_CONN_EXIST &&
+	    rpl->status != CPL_ERR_ARP_MISS)
+		cxgb3_queue_tid_release(tdev, GET_TID(rpl));
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+	if (rpl->status == CPL_ERR_CONN_EXIST &&
+	    csk->retry_timer.function != act_open_retry_timer) {
+		csk->retry_timer.function = act_open_retry_timer;
+		mod_timer(&csk->retry_timer, jiffies + HZ / 2);
+	} else
+		cxgbi_sock_fail_act_open(csk,
+				act_open_rpl_status_to_errno(rpl->status));
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process PEER_CLOSE CPL messages: -> host
+ * Handle peer FIN.
+ */
+static int do_peer_close(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	cxgbi_sock_rcv_peer_close(csk);
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process CLOSE_CONN_RPL CPL message: -> host
+ * Process a peer ACK to our FIN.
+ */
+static int do_close_con_rpl(struct t3cdev *cdev, struct sk_buff *skb,
+			    void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+	struct cpl_close_con_rpl *rpl = cplhdr(skb);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, snxt %u.\n",
+		csk, csk->state, csk->flags, csk->tid, ntohl(rpl->snd_nxt));
+
+	cxgbi_sock_rcv_close_conn_rpl(csk, ntohl(rpl->snd_nxt));
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process ABORT_REQ_RSS CPL message: -> host
+ * Process abort requests.  If we are waiting for an ABORT_RPL we ignore this
+ * request except that we need to reply to it.
+ */
+
+static int abort_status_to_errno(struct cxgbi_sock *csk, int abort_reason,
+				 int *need_rst)
+{
+	switch (abort_reason) {
+	case CPL_ERR_BAD_SYN: /* fall through */
+	case CPL_ERR_CONN_RESET:
+		return csk->state > CTP_ESTABLISHED ? -EPIPE : -ECONNRESET;
+	case CPL_ERR_XMIT_TIMEDOUT:
+	case CPL_ERR_PERSIST_TIMEDOUT:
+	case CPL_ERR_FINWAIT2_TIMEDOUT:
+	case CPL_ERR_KEEPALIVE_TIMEDOUT:
+		return -ETIMEDOUT;
+	default:
+		return -EIO;
+	}
+}
+
+static int do_abort_req(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+	const struct cpl_abort_req_rss *req = cplhdr(skb);
+	struct cxgbi_sock *csk = ctx;
+	int rst_status = CPL_ABORT_NO_RST;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
+	    req->status == CPL_ERR_PERSIST_NEG_ADVICE) {
+		goto done;
+	}
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (!cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD)) {
+		cxgbi_sock_set_flag(csk, CTPF_ABORT_REQ_RCVD);
+		cxgbi_sock_set_state(csk, CTP_ABORTING);
+		goto out;
+	}
+
+	cxgbi_sock_clear_flag(csk, CTPF_ABORT_REQ_RCVD);
+	send_abort_rpl(csk, rst_status);
+
+	if (!cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING)) {
+		csk->err = abort_status_to_errno(csk, req->status, &rst_status);
+		cxgbi_sock_closed(csk);
+	}
+
+out:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+done:
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process ABORT_RPL_RSS CPL message: -> host
+ * Process abort replies.  We only process these messages if we anticipate
+ * them as the coordination between SW and HW in this area is somewhat lacking
+ * and sometimes we get ABORT_RPLs after we are done with the connection that
+ * originated the ABORT_REQ.
+ */
+static int do_abort_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+	struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
+	struct cxgbi_sock *csk = ctx;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"status 0x%x, csk 0x%p, s %u, 0x%lx.\n",
+		rpl->status, csk, csk ? csk->state : 0,
+		csk ? csk->flags : 0UL);
+	/*
+	 * Ignore replies to post-close aborts indicating that the abort was
+	 * requested too late.  These connections are terminated when we get
+	 * PEER_CLOSE or CLOSE_CON_RPL and by the time the abort_rpl_rss
+	 * arrives the TID is either no longer used or it has been recycled.
+	 */
+	if (rpl->status == CPL_ERR_ABORT_FAILED)
+		goto rel_skb;
+	/*
+	 * Sometimes we've already closed the connection, e.g., a post-close
+	 * abort races with ABORT_REQ_RSS, the latter frees the connection
+	 * expecting the ABORT_REQ will fail with CPL_ERR_ABORT_FAILED,
+	 * but FW turns the ABORT_REQ into a regular one and so we get
+	 * ABORT_RPL_RSS with status 0 and no connection.
+	 */
+	if (csk)
+		cxgbi_sock_rcv_abort_rpl(csk);
+rel_skb:
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process RX_ISCSI_HDR CPL message: -> host
+ * Handle received PDUs, the payload could be DDP'ed. If not, the payload
+ * follow after the bhs.
+ */
+static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+	struct cpl_iscsi_hdr *hdr_cpl = cplhdr(skb);
+	struct cpl_iscsi_hdr_norss data_cpl;
+	struct cpl_rx_data_ddp_norss ddp_cpl;
+	unsigned int hdr_len, data_len, status;
+	unsigned int len;
+	int err;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx,%u, skb 0x%p,%u.\n",
+		csk, csk->state, csk->flags, csk->tid, skb, skb->len);
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state >= CTP_PASSIVE_CLOSE)) {
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+			"csk 0x%p,%u,0x%lx,%u, bad state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		if (csk->state != CTP_ABORTING)
+			goto abort_conn;
+		else
+			goto discard;
+	}
+
+	cxgbi_skcb_tcp_seq(skb) = ntohl(hdr_cpl->seq);
+	cxgbi_skcb_flags(skb) = 0;
+
+	skb_reset_transport_header(skb);
+	__skb_pull(skb, sizeof(struct cpl_iscsi_hdr));
+
+	len = hdr_len = ntohs(hdr_cpl->len);
+	/* msg coalesce is off or not enough data received */
+	if (skb->len <= hdr_len) {
+		pr_err("%s: tid %u, CPL_ISCSI_HDR, skb len %u < %u.\n",
+			csk->cdev->ports[csk->port_id]->name, csk->tid,
+			skb->len, hdr_len);
+		goto abort_conn;
+	}
+	cxgbi_skcb_set_flag(skb, SKCBF_RX_COALESCED);
+
+	err = skb_copy_bits(skb, skb->len - sizeof(ddp_cpl), &ddp_cpl,
+			    sizeof(ddp_cpl));
+	if (err < 0) {
+		pr_err("%s: tid %u, copy cpl_ddp %u-%zu failed %d.\n",
+			csk->cdev->ports[csk->port_id]->name, csk->tid,
+			skb->len, sizeof(ddp_cpl), err);
+		goto abort_conn;
+	}
+
+	cxgbi_skcb_set_flag(skb, SKCBF_RX_STATUS);
+	cxgbi_skcb_rx_pdulen(skb) = ntohs(ddp_cpl.len);
+	cxgbi_skcb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc);
+	status = ntohl(ddp_cpl.ddp_status);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p, skb 0x%p,%u, pdulen %u, status 0x%x.\n",
+		csk, skb, skb->len, cxgbi_skcb_rx_pdulen(skb), status);
+
+	if (status & (1 << CPL_RX_DDP_STATUS_HCRC_SHIFT))
+		cxgbi_skcb_set_flag(skb, SKCBF_RX_HCRC_ERR);
+	if (status & (1 << CPL_RX_DDP_STATUS_DCRC_SHIFT))
+		cxgbi_skcb_set_flag(skb, SKCBF_RX_DCRC_ERR);
+	if (status & (1 << CPL_RX_DDP_STATUS_PAD_SHIFT))
+		cxgbi_skcb_set_flag(skb, SKCBF_RX_PAD_ERR);
+
+	if (skb->len > (hdr_len + sizeof(ddp_cpl))) {
+		err = skb_copy_bits(skb, hdr_len, &data_cpl, sizeof(data_cpl));
+		if (err < 0) {
+			pr_err("%s: tid %u, cp %zu/%u failed %d.\n",
+				csk->cdev->ports[csk->port_id]->name,
+				csk->tid, sizeof(data_cpl), skb->len, err);
+			goto abort_conn;
+		}
+		data_len = ntohs(data_cpl.len);
+		log_debug(1 << CXGBI_DBG_DDP | 1 << CXGBI_DBG_PDU_RX,
+			"skb 0x%p, pdu not ddp'ed %u/%u, status 0x%x.\n",
+			skb, data_len, cxgbi_skcb_rx_pdulen(skb), status);
+		len += sizeof(data_cpl) + data_len;
+	} else if (status & (1 << CPL_RX_DDP_STATUS_DDP_SHIFT))
+		cxgbi_skcb_set_flag(skb, SKCBF_RX_DATA_DDPD);
+
+	csk->rcv_nxt = ntohl(ddp_cpl.seq) + cxgbi_skcb_rx_pdulen(skb);
+	__pskb_trim(skb, len);
+	__skb_queue_tail(&csk->receive_queue, skb);
+	cxgbi_conn_pdu_ready(csk);
+
+	spin_unlock_bh(&csk->lock);
+	return 0;
+
+abort_conn:
+	send_abort_req(csk);
+discard:
+	spin_unlock_bh(&csk->lock);
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process TX_DATA_ACK CPL messages: -> host
+ * Process an acknowledgment of WR completion.  Advance snd_una and send the
+ * next batch of work requests from the write queue.
+ */
+static int do_wr_ack(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+	struct cpl_wr_ack *hdr = cplhdr(skb);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx,%u, cr %u.\n",
+		csk, csk->state, csk->flags, csk->tid, ntohs(hdr->credits));
+
+	cxgbi_sock_rcv_wr_ack(csk, ntohs(hdr->credits), ntohl(hdr->snd_una), 1);
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * for each connection, pre-allocate skbs needed for close/abort requests. So
+ * that we can service the request right away.
+ */
+static int alloc_cpls(struct cxgbi_sock *csk)
+{
+	csk->cpl_close = alloc_wr(sizeof(struct cpl_close_con_req), 0,
+					GFP_KERNEL);
+	if (!csk->cpl_close)
+		return -ENOMEM;
+	csk->cpl_abort_req = alloc_wr(sizeof(struct cpl_abort_req), 0,
+					GFP_KERNEL);
+	if (!csk->cpl_abort_req)
+		goto free_cpl_skbs;
+
+	csk->cpl_abort_rpl = alloc_wr(sizeof(struct cpl_abort_rpl), 0,
+					GFP_KERNEL);
+	if (!csk->cpl_abort_rpl)
+		goto free_cpl_skbs;
+
+	return 0;
+
+free_cpl_skbs:
+	cxgbi_sock_free_cpl_skbs(csk);
+	return -ENOMEM;
+}
+
+/**
+ * release_offload_resources - release offload resource
+ * @c3cn: the offloaded iscsi tcp connection.
+ * Release resources held by an offload connection (TID, L2T entry, etc.)
+ */
+static void l2t_put(struct cxgbi_sock *csk)
+{
+	struct t3cdev *t3dev = (struct t3cdev *)csk->cdev->lldev;
+
+	if (csk->l2t) {
+		l2t_release(L2DATA(t3dev), csk->l2t);
+		csk->l2t = NULL;
+		cxgbi_sock_put(csk);
+	}
+}
+
+static void release_offload_resources(struct cxgbi_sock *csk)
+{
+	struct t3cdev *t3dev = (struct t3cdev *)csk->cdev->lldev;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	csk->rss_qid = 0;
+	cxgbi_sock_free_cpl_skbs(csk);
+
+	if (csk->wr_cred != csk->wr_max_cred) {
+		cxgbi_sock_purge_wr_queue(csk);
+		cxgbi_sock_reset_wr_list(csk);
+	}
+	l2t_put(csk);
+	if (cxgbi_sock_flag(csk, CTPF_HAS_ATID))
+		free_atid(csk);
+	else if (cxgbi_sock_flag(csk, CTPF_HAS_TID)) {
+		cxgb3_remove_tid(t3dev, (void *)csk, csk->tid);
+		cxgbi_sock_clear_flag(csk, CTPF_HAS_TID);
+		cxgbi_sock_put(csk);
+	}
+	csk->dst = NULL;
+	csk->cdev = NULL;
+}
+
+static void update_address(struct cxgbi_hba *chba)
+{
+	if (chba->ipv4addr) {
+		if (chba->vdev &&
+		    chba->ipv4addr != cxgb3i_get_private_ipv4addr(chba->vdev)) {
+			cxgb3i_set_private_ipv4addr(chba->vdev, chba->ipv4addr);
+			cxgb3i_set_private_ipv4addr(chba->ndev, 0);
+			pr_info("%s set %pI4.\n",
+				chba->vdev->name, &chba->ipv4addr);
+		} else if (chba->ipv4addr !=
+				cxgb3i_get_private_ipv4addr(chba->ndev)) {
+			cxgb3i_set_private_ipv4addr(chba->ndev, chba->ipv4addr);
+			pr_info("%s set %pI4.\n",
+				chba->ndev->name, &chba->ipv4addr);
+		}
+	} else if (cxgb3i_get_private_ipv4addr(chba->ndev)) {
+		if (chba->vdev)
+			cxgb3i_set_private_ipv4addr(chba->vdev, 0);
+		cxgb3i_set_private_ipv4addr(chba->ndev, 0);
+	}
+}
+
+static int init_act_open(struct cxgbi_sock *csk)
+{
+	struct dst_entry *dst = csk->dst;
+	struct cxgbi_device *cdev = csk->cdev;
+	struct t3cdev *t3dev = (struct t3cdev *)cdev->lldev;
+	struct net_device *ndev = cdev->ports[csk->port_id];
+	struct cxgbi_hba *chba = cdev->hbas[csk->port_id];
+	struct sk_buff *skb = NULL;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx.\n", csk, csk->state, csk->flags);
+
+	update_address(chba);
+	if (chba->ipv4addr)
+		csk->saddr.sin_addr.s_addr = chba->ipv4addr;
+
+	csk->rss_qid = 0;
+	csk->l2t = t3_l2t_get(t3dev, dst->neighbour, ndev);
+	if (!csk->l2t) {
+		pr_err("NO l2t available.\n");
+		return -EINVAL;
+	}
+	cxgbi_sock_get(csk);
+
+	csk->atid = cxgb3_alloc_atid(t3dev, &t3_client, csk);
+	if (csk->atid < 0) {
+		pr_err("NO atid available.\n");
+		goto rel_resource;
+	}
+	cxgbi_sock_set_flag(csk, CTPF_HAS_ATID);
+	cxgbi_sock_get(csk);
+
+	skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_KERNEL);
+	if (!skb)
+		goto rel_resource;
+	skb->sk = (struct sock *)csk;
+	set_arp_failure_handler(skb, act_open_arp_failure);
+
+	csk->wr_max_cred = csk->wr_cred = T3C_DATA(t3dev)->max_wrs - 1;
+	csk->wr_una_cred = 0;
+	csk->mss_idx = cxgbi_sock_select_mss(csk, dst_mtu(dst));
+	cxgbi_sock_reset_wr_list(csk);
+	csk->err = 0;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, %pI4:%u-%pI4:%u.\n",
+		csk, csk->state, csk->flags,
+		&csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
+		&csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port));
+
+	cxgbi_sock_set_state(csk, CTP_ACTIVE_OPEN);
+	send_act_open_req(csk, skb, csk->l2t);
+	return 0;
+
+rel_resource:
+	if (skb)
+		__kfree_skb(skb);
+	return -EINVAL;
+}
+
+cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS] = {
+	[CPL_ACT_ESTABLISH] = do_act_establish,
+	[CPL_ACT_OPEN_RPL] = do_act_open_rpl,
+	[CPL_PEER_CLOSE] = do_peer_close,
+	[CPL_ABORT_REQ_RSS] = do_abort_req,
+	[CPL_ABORT_RPL_RSS] = do_abort_rpl,
+	[CPL_CLOSE_CON_RPL] = do_close_con_rpl,
+	[CPL_TX_DMA_ACK] = do_wr_ack,
+	[CPL_ISCSI_HDR] = do_iscsi_hdr,
+};
+
+/**
+ * cxgb3i_ofld_init - allocate and initialize resources for each adapter found
+ * @cdev:	cxgbi adapter
+ */
+int cxgb3i_ofld_init(struct cxgbi_device *cdev)
+{
+	struct t3cdev *t3dev = (struct t3cdev *)cdev->lldev;
+	struct adap_ports port;
+	struct ofld_page_info rx_page_info;
+	unsigned int wr_len;
+	int rc;
+
+	if (t3dev->ctl(t3dev, GET_WR_LEN, &wr_len) < 0 ||
+	    t3dev->ctl(t3dev, GET_PORTS, &port) < 0 ||
+	    t3dev->ctl(t3dev, GET_RX_PAGE_INFO, &rx_page_info) < 0) {
+		pr_warn("t3 0x%p, offload up, ioctl failed.\n", t3dev);
+		return -EINVAL;
+	}
+
+	if (cxgb3i_max_connect > CXGBI_MAX_CONN)
+		cxgb3i_max_connect = CXGBI_MAX_CONN;
+
+	rc = cxgbi_device_portmap_create(cdev, cxgb3i_sport_base,
+					cxgb3i_max_connect);
+	if (rc < 0)
+		return rc;
+
+	init_wr_tab(wr_len);
+	cdev->csk_release_offload_resources = release_offload_resources;
+	cdev->csk_push_tx_frames = push_tx_frames;
+	cdev->csk_send_abort_req = send_abort_req;
+	cdev->csk_send_close_req = send_close_req;
+	cdev->csk_send_rx_credits = send_rx_credits;
+	cdev->csk_alloc_cpls = alloc_cpls;
+	cdev->csk_init_act_open = init_act_open;
+
+	pr_info("cdev 0x%p, offload up, added.\n", cdev);
+	return 0;
+}
+
+/*
+ * functions to program the pagepod in h/w
+ */
+static inline void ulp_mem_io_set_hdr(struct sk_buff *skb, unsigned int addr)
+{
+	struct ulp_mem_io *req = (struct ulp_mem_io *)skb->head;
+
+	memset(req, 0, sizeof(*req));
+
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS));
+	req->cmd_lock_addr = htonl(V_ULP_MEMIO_ADDR(addr >> 5) |
+				   V_ULPTX_CMD(ULP_MEM_WRITE));
+	req->len = htonl(V_ULP_MEMIO_DATA_LEN(PPOD_SIZE >> 5) |
+			 V_ULPTX_NFLITS((PPOD_SIZE >> 3) + 1));
+}
+
+static int ddp_set_map(struct cxgbi_sock *csk, struct cxgbi_pagepod_hdr *hdr,
+			unsigned int idx, unsigned int npods,
+				struct cxgbi_gather_list *gl)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
+	int i;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"csk 0x%p, idx %u, npods %u, gl 0x%p.\n",
+		csk, idx, npods, gl);
+
+	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
+		struct sk_buff *skb = ddp->gl_skb[idx];
+
+		/* hold on to the skb until we clear the ddp mapping */
+		skb_get(skb);
+
+		ulp_mem_io_set_hdr(skb, pm_addr);
+		cxgbi_ddp_ppod_set((struct cxgbi_pagepod *)(skb->head +
+					sizeof(struct ulp_mem_io)),
+				   hdr, gl, i * PPOD_PAGES_MAX);
+		skb->priority = CPL_PRIORITY_CONTROL;
+		cxgb3_ofld_send(cdev->lldev, skb);
+	}
+	return 0;
+}
+
+static void ddp_clear_map(struct cxgbi_hba *chba, unsigned int tag,
+			  unsigned int idx, unsigned int npods)
+{
+	struct cxgbi_device *cdev = chba->cdev;
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
+	int i;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"cdev 0x%p, idx %u, npods %u, tag 0x%x.\n",
+		cdev, idx, npods, tag);
+
+	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
+		struct sk_buff *skb = ddp->gl_skb[idx];
+
+		if (!skb) {
+			pr_err("tag 0x%x, 0x%x, %d/%u, skb NULL.\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)
+{
+	struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
+					GFP_KERNEL);
+	struct cpl_set_tcb_field *req;
+	u64 val = pg_idx < DDP_PGIDX_MAX ? pg_idx : 0;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"csk 0x%p, tid %u, pg_idx %d.\n", csk, tid, pg_idx);
+	if (!skb)
+		return -ENOMEM;
+
+	/* set up ulp submode and page size */
+	req = (struct cpl_set_tcb_field *)skb->head;
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+	req->reply = V_NO_REPLY(reply ? 0 : 1);
+	req->cpu_idx = 0;
+	req->word = htons(31);
+	req->mask = cpu_to_be64(0xF0000000);
+	req->val = cpu_to_be64(val << 28);
+	skb->priority = CPL_PRIORITY_CONTROL;
+
+	cxgb3_ofld_send(csk->cdev->lldev, skb);
+	return 0;
+}
+
+/**
+ * cxgb3i_setup_conn_digest - setup conn. digest setting
+ * @csk: cxgb tcp socket
+ * @tid: connection id
+ * @hcrc: header digest enabled
+ * @dcrc: data digest enabled
+ * @reply: request reply from h/w
+ * set up the iscsi digest settings for a connection identified by tid
+ */
+static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
+			     int hcrc, int dcrc, int reply)
+{
+	struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
+					GFP_KERNEL);
+	struct cpl_set_tcb_field *req;
+	u64 val = (hcrc ? 1 : 0) | (dcrc ? 2 : 0);
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"csk 0x%p, tid %u, crc %d,%d.\n", csk, tid, hcrc, dcrc);
+	if (!skb)
+		return -ENOMEM;
+
+	/* set up ulp submode and page size */
+	req = (struct cpl_set_tcb_field *)skb->head;
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+	req->reply = V_NO_REPLY(reply ? 0 : 1);
+	req->cpu_idx = 0;
+	req->word = htons(31);
+	req->mask = cpu_to_be64(0x0F000000);
+	req->val = cpu_to_be64(val << 24);
+	skb->priority = CPL_PRIORITY_CONTROL;
+
+	cxgb3_ofld_send(csk->cdev->lldev, skb);
+	return 0;
+}
+
+/**
+ * t3_ddp_cleanup - release the cxgb3 adapter's ddp resource
+ * @cdev: cxgb3i adapter
+ * release all the resource held by the ddp pagepod manager for a given
+ * adapter if needed
+ */
+
+static void t3_ddp_cleanup(struct cxgbi_device *cdev)
+{
+	struct t3cdev *tdev = (struct t3cdev *)cdev->lldev;
+
+	if (cxgbi_ddp_cleanup(cdev)) {
+		pr_info("t3dev 0x%p, ulp_iscsi no more user.\n", tdev);
+		tdev->ulp_iscsi = NULL;
+	}
+}
+
+/**
+ * ddp_init - initialize the cxgb3 adapter's ddp resource
+ * @cdev: cxgb3i adapter
+ * initialize the ddp pagepod manager for a given adapter
+ */
+static int cxgb3i_ddp_init(struct cxgbi_device *cdev)
+{
+	struct t3cdev *tdev = (struct t3cdev *)cdev->lldev;
+	struct cxgbi_ddp_info *ddp = tdev->ulp_iscsi;
+	struct ulp_iscsi_info uinfo;
+	unsigned int pgsz_factor[4];
+	int err;
+
+	if (ddp) {
+		kref_get(&ddp->refcnt);
+		pr_warn("t3dev 0x%p, ddp 0x%p already set up.\n",
+			tdev, tdev->ulp_iscsi);
+		cdev->ddp = ddp;
+		return -EALREADY;
+	}
+
+	err = tdev->ctl(tdev, ULP_ISCSI_GET_PARAMS, &uinfo);
+	if (err < 0) {
+		pr_err("%s, failed to get iscsi param err=%d.\n",
+			 tdev->name, err);
+		return err;
+	}
+
+	err = cxgbi_ddp_init(cdev, uinfo.llimit, uinfo.ulimit,
+			uinfo.max_txsz, uinfo.max_rxsz);
+	if (err < 0)
+		return err;
+
+	ddp = cdev->ddp;
+
+	uinfo.tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
+	cxgbi_ddp_page_size_factor(pgsz_factor);
+	uinfo.ulimit = uinfo.llimit + (ddp->nppods << PPOD_SIZE_SHIFT);
+
+	err = tdev->ctl(tdev, ULP_ISCSI_SET_PARAMS, &uinfo);
+	if (err < 0) {
+		pr_warn("%s unable to set iscsi param err=%d, ddp disabled.\n",
+			tdev->name, err);
+		cxgbi_ddp_cleanup(cdev);
+		return err;
+	}
+	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;
+	cdev->csk_ddp_clear = ddp_clear_map;
+
+	pr_info("tdev 0x%p, nppods %u, bits %u, mask 0x%x,0x%x pkt %u/%u, "
+		"%u/%u.\n",
+		tdev, ddp->nppods, ddp->idx_bits, ddp->idx_mask,
+		ddp->rsvd_tag_mask, ddp->max_txsz, uinfo.max_txsz,
+		ddp->max_rxsz, uinfo.max_rxsz);
+	return 0;
+}
+
+static void cxgb3i_dev_close(struct t3cdev *t3dev)
+{
+	struct cxgbi_device *cdev = cxgbi_device_find_by_lldev(t3dev);
+
+	if (!cdev || cdev->flags & CXGBI_FLAG_ADAPTER_RESET) {
+		pr_info("0x%p close, f 0x%x.\n", cdev, cdev ? cdev->flags : 0);
+		return;
+	}
+
+	cxgbi_device_unregister(cdev);
+}
+
+/**
+ * cxgb3i_dev_open - init a t3 adapter structure and any h/w settings
+ * @t3dev: t3cdev adapter
+ */
+static void cxgb3i_dev_open(struct t3cdev *t3dev)
+{
+	struct cxgbi_device *cdev = cxgbi_device_find_by_lldev(t3dev);
+	struct adapter *adapter = tdev2adap(t3dev);
+	int i, err;
+
+	if (cdev) {
+		pr_info("0x%p, updating.\n", cdev);
+		return;
+	}
+
+	cdev = cxgbi_device_register(0, adapter->params.nports);
+	if (!cdev) {
+		pr_warn("device 0x%p register failed.\n", t3dev);
+		return;
+	}
+
+	cdev->flags = CXGBI_FLAG_DEV_T3 | CXGBI_FLAG_IPV4_SET;
+	cdev->lldev = t3dev;
+	cdev->pdev = adapter->pdev;
+	cdev->ports = adapter->port;
+	cdev->nports = adapter->params.nports;
+	cdev->mtus = adapter->params.mtus;
+	cdev->nmtus = NMTUS;
+	cdev->snd_win = cxgb3i_snd_win;
+	cdev->rcv_win = cxgb3i_rcv_win;
+	cdev->rx_credit_thres = cxgb3i_rx_credit_thres;
+	cdev->skb_tx_rsvd = CXGB3I_TX_HEADER_LEN;
+	cdev->skb_rx_extra = sizeof(struct cpl_iscsi_hdr_norss);
+	cdev->dev_ddp_cleanup = t3_ddp_cleanup;
+	cdev->itp = &cxgb3i_iscsi_transport;
+
+	err = cxgb3i_ddp_init(cdev);
+	if (err) {
+		pr_info("0x%p ddp init failed\n", cdev);
+		goto err_out;
+	}
+
+	err = cxgb3i_ofld_init(cdev);
+	if (err) {
+		pr_info("0x%p offload init failed\n", cdev);
+		goto err_out;
+	}
+
+	err = cxgbi_hbas_add(cdev, CXGB3I_MAX_LUN, CXGBI_MAX_CONN,
+				&cxgb3i_host_template, cxgb3i_stt);
+	if (err)
+		goto err_out;
+
+	for (i = 0; i < cdev->nports; i++)
+		cdev->hbas[i]->ipv4addr =
+			cxgb3i_get_private_ipv4addr(cdev->ports[i]);
+
+	pr_info("cdev 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
+		cdev, cdev ? cdev->flags : 0, t3dev, err);
+	return;
+
+err_out:
+	cxgbi_device_unregister(cdev);
+}
+
+static void cxgb3i_dev_event_handler(struct t3cdev *t3dev, u32 event, u32 port)
+{
+	struct cxgbi_device *cdev = cxgbi_device_find_by_lldev(t3dev);
+
+	log_debug(1 << CXGBI_DBG_TOE,
+		"0x%p, cdev 0x%p, event 0x%x, port 0x%x.\n",
+		t3dev, cdev, event, port);
+	if (!cdev)
+		return;
+
+	switch (event) {
+	case OFFLOAD_STATUS_DOWN:
+		cdev->flags |= CXGBI_FLAG_ADAPTER_RESET;
+		break;
+	case OFFLOAD_STATUS_UP:
+		cdev->flags &= ~CXGBI_FLAG_ADAPTER_RESET;
+		break;
+	}
+}
+
+/**
+ * cxgb3i_init_module - module init entry point
+ *
+ * initialize any driver wide global data structures and register itself
+ *	with the cxgb3 module
+ */
+static int __init cxgb3i_init_module(void)
+{
+	int rc;
+
+	printk(KERN_INFO "%s", version);
+
+	rc = cxgbi_iscsi_init(&cxgb3i_iscsi_transport, &cxgb3i_stt);
+	if (rc < 0)
+		return rc;
+
+	cxgb3_register_client(&t3_client);
+	return 0;
+}
+
+/**
+ * cxgb3i_exit_module - module cleanup/exit entry point
+ *
+ * go through the driver hba list and for each hba, release any resource held.
+ *	and unregisters iscsi transport and the cxgb3 module
+ */
+static void __exit cxgb3i_exit_module(void)
+{
+	cxgb3_unregister_client(&t3_client);
+	cxgbi_device_unregister_all(CXGBI_FLAG_DEV_T3);
+	cxgbi_iscsi_cleanup(&cxgb3i_iscsi_transport, &cxgb3i_stt);
+}
+
+module_init(cxgb3i_init_module);
+module_exit(cxgb3i_exit_module);
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
new file mode 100644
index 0000000..5f5e339
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
@@ -0,0 +1,51 @@
+/*
+ * cxgb3i.h: Chelsio S3xx iSCSI driver.
+ *
+ * Copyright (c) 2008 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ */
+
+#ifndef __CXGB3I_H__
+#define __CXGB3I_H__
+
+#define CXGB3I_SCSI_HOST_QDEPTH 1024
+#define CXGB3I_MAX_LUN		512
+#define ISCSI_PDU_NONPAYLOAD_MAX \
+	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + 2*ISCSI_DIGEST_SIZE)
+
+/*for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
+#define CXGB3I_TX_HEADER_LEN \
+	(sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr))
+
+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
+
+struct cpl_iscsi_hdr_norss {
+	union opcode_tid ot;
+	u16 pdu_len_ddp;
+	u16 len;
+	u32 seq;
+	u16 urg;
+	u8 rsvd;
+	u8 status;
+};
+
+struct cpl_rx_data_ddp_norss {
+	union opcode_tid ot;
+	u16 urg;
+	u16 len;
+	u32 seq;
+	u32 nxt_seq;
+	u32 ulp_crc;
+	u32 ddp_status;
+};
+#endif
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kbuild b/drivers/scsi/cxgbi/cxgb4i/Kbuild
new file mode 100644
index 0000000..b9f4af7
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/Kbuild
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb4
+
+obj-$(CONFIG_SCSI_CXGB4_ISCSI) += cxgb4i.o
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kconfig b/drivers/scsi/cxgbi/cxgb4i/Kconfig
new file mode 100644
index 0000000..bb94b39
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/Kconfig
@@ -0,0 +1,7 @@
+config SCSI_CXGB4_ISCSI
+	tristate "Chelsio T4 iSCSI support"
+	depends on CHELSIO_T4_DEPENDS
+	select CHELSIO_T4
+	select SCSI_ISCSI_ATTRS
+	---help---
+	  This driver supports iSCSI offload for the Chelsio T4 devices.
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
new file mode 100644
index 0000000..99f2b8c
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -0,0 +1,1604 @@
+/*
+ * cxgb4i.c: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by:	Karen Xie (kxie@chelsio.com)
+ *		Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <scsi/scsi_host.h>
+#include <net/tcp.h>
+#include <net/dst.h>
+#include <linux/netdevice.h>
+
+#include "t4_msg.h"
+#include "cxgb4.h"
+#include "cxgb4_uld.h"
+#include "t4fw_api.h"
+#include "l2t.h"
+#include "cxgb4i.h"
+
+static unsigned int dbg_level;
+
+#include "../libcxgbi.h"
+
+#define	DRV_MODULE_NAME		"cxgb4i"
+#define DRV_MODULE_DESC		"Chelsio T4 iSCSI Driver"
+#define	DRV_MODULE_VERSION	"0.9.1"
+#define	DRV_MODULE_RELDATE	"Aug. 2010"
+
+static char version[] =
+	DRV_MODULE_DESC " " DRV_MODULE_NAME
+	" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Chelsio Communications, Inc.");
+MODULE_DESCRIPTION(DRV_MODULE_DESC);
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(dbg_level, uint, 0644);
+MODULE_PARM_DESC(dbg_level, "Debug flag (default=0)");
+
+static int cxgb4i_rcv_win = 256 * 1024;
+module_param(cxgb4i_rcv_win, int, 0644);
+MODULE_PARM_DESC(cxgb4i_rcv_win, "TCP reveive window in bytes");
+
+static int cxgb4i_snd_win = 128 * 1024;
+module_param(cxgb4i_snd_win, int, 0644);
+MODULE_PARM_DESC(cxgb4i_snd_win, "TCP send window in bytes");
+
+static int cxgb4i_rx_credit_thres = 10 * 1024;
+module_param(cxgb4i_rx_credit_thres, int, 0644);
+MODULE_PARM_DESC(cxgb4i_rx_credit_thres,
+		"RX credits return threshold in bytes (default=10KB)");
+
+static unsigned int cxgb4i_max_connect = (8 * 1024);
+module_param(cxgb4i_max_connect, uint, 0644);
+MODULE_PARM_DESC(cxgb4i_max_connect, "Maximum number of connections");
+
+static unsigned short cxgb4i_sport_base = 20000;
+module_param(cxgb4i_sport_base, ushort, 0644);
+MODULE_PARM_DESC(cxgb4i_sport_base, "Starting port number (default 20000)");
+
+typedef void (*cxgb4i_cplhandler_func)(struct cxgbi_device *, struct sk_buff *);
+
+static void *t4_uld_add(const struct cxgb4_lld_info *);
+static int t4_uld_rx_handler(void *, const __be64 *, const struct pkt_gl *);
+static int t4_uld_state_change(void *, enum cxgb4_state state);
+
+static const struct cxgb4_uld_info cxgb4i_uld_info = {
+	.name = DRV_MODULE_NAME,
+	.add = t4_uld_add,
+	.rx_handler = t4_uld_rx_handler,
+	.state_change = t4_uld_state_change,
+};
+
+static struct scsi_host_template cxgb4i_host_template = {
+	.module		= THIS_MODULE,
+	.name		= DRV_MODULE_NAME,
+	.proc_name	= DRV_MODULE_NAME,
+	.can_queue	= CXGB4I_SCSI_HOST_QDEPTH,
+	.queuecommand	= iscsi_queuecommand,
+	.change_queue_depth = iscsi_change_queue_depth,
+	.sg_tablesize	= SG_ALL,
+	.max_sectors	= 0xFFFF,
+	.cmd_per_lun	= ISCSI_DEF_CMD_PER_LUN,
+	.eh_abort_handler = iscsi_eh_abort,
+	.eh_device_reset_handler = iscsi_eh_device_reset,
+	.eh_target_reset_handler = iscsi_eh_recover_target,
+	.target_alloc	= iscsi_target_alloc,
+	.use_clustering	= DISABLE_CLUSTERING,
+	.this_id	= -1,
+};
+
+static struct iscsi_transport cxgb4i_iscsi_transport = {
+	.owner		= THIS_MODULE,
+	.name		= DRV_MODULE_NAME,
+	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
+				CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+				CAP_PADDING_OFFLOAD,
+	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
+				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
+				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
+				ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
+				ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
+				ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
+				ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+				ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
+				ISCSI_PERSISTENT_ADDRESS |
+				ISCSI_TARGET_NAME | ISCSI_TPGT |
+				ISCSI_USERNAME | ISCSI_PASSWORD |
+				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+				ISCSI_PING_TMO | ISCSI_RECV_TMO |
+				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+				ISCSI_HOST_INITIATOR_NAME |
+				ISCSI_HOST_NETDEV_NAME,
+	.get_host_param	= cxgbi_get_host_param,
+	.set_host_param	= cxgbi_set_host_param,
+	/* session management */
+	.create_session	= cxgbi_create_session,
+	.destroy_session	= cxgbi_destroy_session,
+	.get_session_param = iscsi_session_get_param,
+	/* connection management */
+	.create_conn	= cxgbi_create_conn,
+	.bind_conn		= cxgbi_bind_conn,
+	.destroy_conn	= iscsi_tcp_conn_teardown,
+	.start_conn		= iscsi_conn_start,
+	.stop_conn		= iscsi_conn_stop,
+	.get_conn_param	= cxgbi_get_conn_param,
+	.set_param	= cxgbi_set_conn_param,
+	.get_stats	= cxgbi_get_conn_stats,
+	/* pdu xmit req from user space */
+	.send_pdu	= iscsi_conn_send_pdu,
+	/* task */
+	.init_task	= iscsi_tcp_task_init,
+	.xmit_task	= iscsi_tcp_task_xmit,
+	.cleanup_task	= cxgbi_cleanup_task,
+	/* pdu */
+	.alloc_pdu	= cxgbi_conn_alloc_pdu,
+	.init_pdu	= cxgbi_conn_init_pdu,
+	.xmit_pdu	= cxgbi_conn_xmit_pdu,
+	.parse_pdu_itt	= cxgbi_parse_pdu_itt,
+	/* TCP connect/disconnect */
+	.ep_connect	= cxgbi_ep_connect,
+	.ep_poll	= cxgbi_ep_poll,
+	.ep_disconnect	= cxgbi_ep_disconnect,
+	/* Error recovery timeout call */
+	.session_recovery_timedout = iscsi_session_recovery_timedout,
+};
+
+static struct scsi_transport_template *cxgb4i_stt;
+
+/*
+ * CPL (Chelsio Protocol Language) defines a message passing interface between
+ * the host driver and Chelsio asic.
+ * The section below implments CPLs that related to iscsi tcp connection
+ * open/close/abort and data send/receive.
+ */
+#define DIV_ROUND_UP(n, d)	(((n) + (d) - 1) / (d))
+#define RCV_BUFSIZ_MASK		0x3FFU
+#define MAX_IMM_TX_PKT_LEN	128
+
+static inline void set_queue(struct sk_buff *skb, unsigned int queue,
+				const struct cxgbi_sock *csk)
+{
+	skb->queue_mapping = queue;
+}
+
+static int push_tx_frames(struct cxgbi_sock *, int);
+
+/*
+ * is_ofld_imm - check whether a packet can be sent as immediate data
+ * @skb: the packet
+ *
+ * Returns true if a packet can be sent as an offload WR with immediate
+ * data.  We currently use the same limit as for Ethernet packets.
+ */
+static inline int is_ofld_imm(const struct sk_buff *skb)
+{
+	return skb->len <= (MAX_IMM_TX_PKT_LEN -
+			sizeof(struct fw_ofld_tx_data_wr));
+}
+
+static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
+				struct l2t_entry *e)
+{
+	struct cpl_act_open_req *req;
+	int wscale = cxgbi_sock_compute_wscale(csk->mss_idx);
+	unsigned long long opt0;
+	unsigned int opt2;
+	unsigned int qid_atid = ((unsigned int)csk->atid) |
+				 (((unsigned int)csk->rss_qid) << 14);
+
+	opt0 = KEEP_ALIVE(1) |
+		WND_SCALE(wscale) |
+		MSS_IDX(csk->mss_idx) |
+		L2T_IDX(((struct l2t_entry *)csk->l2t)->idx) |
+		TX_CHAN(csk->tx_chan) |
+		SMAC_SEL(csk->smac_idx) |
+		ULP_MODE(ULP_MODE_ISCSI) |
+		RCV_BUFSIZ(cxgb4i_rcv_win >> 10);
+	opt2 = RX_CHANNEL(0) |
+		RSS_QUEUE_VALID |
+		(1 << 20) | (1 << 22) |
+		RSS_QUEUE(csk->rss_qid);
+
+	set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id);
+	req = (struct cpl_act_open_req *)skb->head;
+
+	INIT_TP_WR(req, 0);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+					qid_atid));
+	req->local_port = csk->saddr.sin_port;
+	req->peer_port = csk->daddr.sin_port;
+	req->local_ip = csk->saddr.sin_addr.s_addr;
+	req->peer_ip = csk->daddr.sin_addr.s_addr;
+	req->opt0 = cpu_to_be64(opt0);
+	req->params = 0;
+	req->opt2 = cpu_to_be32(opt2);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, %pI4:%u-%pI4:%u, atid %d, qid %u.\n",
+		csk, &req->local_ip, ntohs(req->local_port),
+		&req->peer_ip, ntohs(req->peer_port),
+		csk->atid, csk->rss_qid);
+
+	cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+}
+
+static void send_close_req(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->cpl_close;
+	struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->head;
+	unsigned int tid = csk->tid;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, tid %u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+	csk->cpl_close = NULL;
+	set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id);
+	INIT_TP_WR(req, tid);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
+	req->rsvd = 0;
+
+	cxgbi_sock_skb_entail(csk, skb);
+	if (csk->state >= CTP_ESTABLISHED)
+		push_tx_frames(csk, 1);
+}
+
+static void abort_arp_failure(void *handle, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)handle;
+	struct cpl_abort_req *req;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, tid %u, abort.\n",
+		csk, csk->state, csk->flags, csk->tid);
+	req = (struct cpl_abort_req *)skb->data;
+	req->cmd = CPL_ABORT_NO_RST;
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+}
+
+static void send_abort_req(struct cxgbi_sock *csk)
+{
+	struct cpl_abort_req *req;
+	struct sk_buff *skb = csk->cpl_abort_req;
+
+	if (unlikely(csk->state == CTP_ABORTING) || !skb || !csk->cdev)
+		return;
+	cxgbi_sock_set_state(csk, CTP_ABORTING);
+	cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_PENDING);
+	cxgbi_sock_purge_write_queue(csk);
+
+	csk->cpl_abort_req = NULL;
+	req = (struct cpl_abort_req *)skb->head;
+	set_queue(skb, CPL_PRIORITY_DATA, csk);
+	req->cmd = CPL_ABORT_SEND_RST;
+	t4_set_arp_err_handler(skb, csk, abort_arp_failure);
+	INIT_TP_WR(req, csk->tid);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, csk->tid));
+	req->rsvd0 = htonl(csk->snd_nxt);
+	req->rsvd1 = !cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, snd_nxt %u, 0x%x.\n",
+		csk, csk->state, csk->flags, csk->tid, csk->snd_nxt,
+		req->rsvd1);
+
+	cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+}
+
+static void send_abort_rpl(struct cxgbi_sock *csk, int rst_status)
+{
+	struct sk_buff *skb = csk->cpl_abort_rpl;
+	struct cpl_abort_rpl *rpl = (struct cpl_abort_rpl *)skb->head;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, status %d.\n",
+		csk, csk->state, csk->flags, csk->tid, rst_status);
+
+	csk->cpl_abort_rpl = NULL;
+	set_queue(skb, CPL_PRIORITY_DATA, csk);
+	INIT_TP_WR(rpl, csk->tid);
+	OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, csk->tid));
+	rpl->cmd = rst_status;
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+}
+
+/*
+ * CPL connection rx data ack: host ->
+ * Send RX credits through an RX_DATA_ACK CPL message. Returns the number of
+ * credits sent.
+ */
+static u32 send_rx_credits(struct cxgbi_sock *csk, u32 credits)
+{
+	struct sk_buff *skb;
+	struct cpl_rx_data_ack *req;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx,%u, credit %u.\n",
+		csk, csk->state, csk->flags, csk->tid, credits);
+
+	skb = alloc_wr(sizeof(*req), 0, GFP_ATOMIC);
+	if (!skb) {
+		pr_info("csk 0x%p, credit %u, OOM.\n", csk, credits);
+		return 0;
+	}
+	req = (struct cpl_rx_data_ack *)skb->head;
+
+	set_wr_txq(skb, CPL_PRIORITY_ACK, csk->port_id);
+	INIT_TP_WR(req, csk->tid);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK,
+				      csk->tid));
+	req->credit_dack = cpu_to_be32(RX_CREDITS(credits) | RX_FORCE_ACK(1));
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+	return credits;
+}
+
+/*
+ * sgl_len - calculates the size of an SGL of the given capacity
+ * @n: the number of SGL entries
+ * Calculates the number of flits needed for a scatter/gather list that
+ * can hold the given number of entries.
+ */
+static inline unsigned int sgl_len(unsigned int n)
+{
+	n--;
+	return (3 * n) / 2 + (n & 1) + 2;
+}
+
+/*
+ * calc_tx_flits_ofld - calculate # of flits for an offload packet
+ * @skb: the packet
+ *
+ * Returns the number of flits needed for the given offload packet.
+ * These packets are already fully constructed and no additional headers
+ * will be added.
+ */
+static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
+{
+	unsigned int flits, cnt;
+
+	if (is_ofld_imm(skb))
+		return DIV_ROUND_UP(skb->len, 8);
+	flits = skb_transport_offset(skb) / 8;
+	cnt = skb_shinfo(skb)->nr_frags;
+	if (skb->tail != skb->transport_header)
+		cnt++;
+	return flits + sgl_len(cnt);
+}
+
+static inline void send_tx_flowc_wr(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+	struct fw_flowc_wr *flowc;
+	int flowclen, i;
+
+	flowclen = 80;
+	skb = alloc_wr(flowclen, 0, GFP_ATOMIC);
+	flowc = (struct fw_flowc_wr *)skb->head;
+	flowc->op_to_nparams =
+		htonl(FW_WR_OP(FW_FLOWC_WR) | FW_FLOWC_WR_NPARAMS(8));
+	flowc->flowid_len16 =
+		htonl(FW_WR_LEN16(DIV_ROUND_UP(72, 16)) |
+				FW_WR_FLOWID(csk->tid));
+	flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
+	flowc->mnemval[0].val = htonl(csk->cdev->pfvf);
+	flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
+	flowc->mnemval[1].val = htonl(csk->tx_chan);
+	flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
+	flowc->mnemval[2].val = htonl(csk->tx_chan);
+	flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID;
+	flowc->mnemval[3].val = htonl(csk->rss_qid);
+	flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SNDNXT;
+	flowc->mnemval[4].val = htonl(csk->snd_nxt);
+	flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT;
+	flowc->mnemval[5].val = htonl(csk->rcv_nxt);
+	flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF;
+	flowc->mnemval[6].val = htonl(cxgb4i_snd_win);
+	flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS;
+	flowc->mnemval[7].val = htonl(csk->advmss);
+	flowc->mnemval[8].mnemonic = 0;
+	flowc->mnemval[8].val = 0;
+	for (i = 0; i < 9; i++) {
+		flowc->mnemval[i].r4[0] = 0;
+		flowc->mnemval[i].r4[1] = 0;
+		flowc->mnemval[i].r4[2] = 0;
+	}
+	set_queue(skb, CPL_PRIORITY_DATA, csk);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, tid 0x%x, %u,%u,%u,%u,%u,%u,%u.\n",
+		csk, csk->tid, 0, csk->tx_chan, csk->rss_qid,
+		csk->snd_nxt, csk->rcv_nxt, cxgb4i_snd_win,
+		csk->advmss);
+
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+}
+
+static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb,
+				   int dlen, int len, u32 credits, int compl)
+{
+	struct fw_ofld_tx_data_wr *req;
+	unsigned int submode = cxgbi_skcb_ulp_mode(skb) & 3;
+	unsigned int wr_ulp_mode = 0;
+
+	req = (struct fw_ofld_tx_data_wr *)__skb_push(skb, sizeof(*req));
+
+	if (is_ofld_imm(skb)) {
+		req->op_to_immdlen = htonl(FW_WR_OP(FW_OFLD_TX_DATA_WR) |
+					FW_WR_COMPL(1) |
+					FW_WR_IMMDLEN(dlen));
+		req->flowid_len16 = htonl(FW_WR_FLOWID(csk->tid) |
+						FW_WR_LEN16(credits));
+	} else {
+		req->op_to_immdlen =
+			cpu_to_be32(FW_WR_OP(FW_OFLD_TX_DATA_WR) |
+					FW_WR_COMPL(1) |
+					FW_WR_IMMDLEN(0));
+		req->flowid_len16 =
+			cpu_to_be32(FW_WR_FLOWID(csk->tid) |
+					FW_WR_LEN16(credits));
+	}
+	if (submode)
+		wr_ulp_mode = FW_OFLD_TX_DATA_WR_ULPMODE(ULP2_MODE_ISCSI) |
+				FW_OFLD_TX_DATA_WR_ULPSUBMODE(submode);
+	req->tunnel_to_proxy = htonl(wr_ulp_mode) |
+		 FW_OFLD_TX_DATA_WR_SHOVE(skb_peek(&csk->write_queue) ? 0 : 1);
+	req->plen = htonl(len);
+	if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT))
+		cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT);
+}
+
+static void arp_failure_skb_discard(void *handle, struct sk_buff *skb)
+{
+	kfree_skb(skb);
+}
+
+static int push_tx_frames(struct cxgbi_sock *csk, int req_completion)
+{
+	int total_size = 0;
+	struct sk_buff *skb;
+
+	if (unlikely(csk->state < CTP_ESTABLISHED ||
+		csk->state == CTP_CLOSE_WAIT_1 || csk->state >= CTP_ABORTING)) {
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK |
+			 1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p,%u,0x%lx,%u, in closing state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		return 0;
+	}
+
+	while (csk->wr_cred && (skb = skb_peek(&csk->write_queue)) != NULL) {
+		int dlen = skb->len;
+		int len = skb->len;
+		unsigned int credits_needed;
+
+		skb_reset_transport_header(skb);
+		if (is_ofld_imm(skb))
+			credits_needed = DIV_ROUND_UP(dlen +
+					sizeof(struct fw_ofld_tx_data_wr), 16);
+		else
+			credits_needed = DIV_ROUND_UP(8*calc_tx_flits_ofld(skb)
+					+ sizeof(struct fw_ofld_tx_data_wr),
+					16);
+
+		if (csk->wr_cred < credits_needed) {
+			log_debug(1 << CXGBI_DBG_PDU_TX,
+				"csk 0x%p, skb %u/%u, wr %d < %u.\n",
+				csk, skb->len, skb->data_len,
+				credits_needed, csk->wr_cred);
+			break;
+		}
+		__skb_unlink(skb, &csk->write_queue);
+		set_queue(skb, CPL_PRIORITY_DATA, csk);
+		skb->csum = credits_needed;
+		csk->wr_cred -= credits_needed;
+		csk->wr_una_cred += credits_needed;
+		cxgbi_sock_enqueue_wr(csk, skb);
+
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p, skb %u/%u, wr %d, left %u, unack %u.\n",
+			csk, skb->len, skb->data_len, credits_needed,
+			csk->wr_cred, csk->wr_una_cred);
+
+		if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) {
+			if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT)) {
+				send_tx_flowc_wr(csk);
+				skb->csum += 5;
+				csk->wr_cred -= 5;
+				csk->wr_una_cred += 5;
+			}
+			len += cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
+			make_tx_data_wr(csk, skb, dlen, len, credits_needed,
+					req_completion);
+			csk->snd_nxt += len;
+			cxgbi_skcb_clear_flag(skb, SKCBF_TX_NEED_HDR);
+		}
+		total_size += skb->truesize;
+		t4_set_arp_err_handler(skb, csk, arp_failure_skb_discard);
+
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p,%u,0x%lx,%u, skb 0x%p, %u.\n",
+			csk, csk->state, csk->flags, csk->tid, skb, len);
+
+		cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+	}
+	return total_size;
+}
+
+static inline void free_atid(struct cxgbi_sock *csk)
+{
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+
+	if (cxgbi_sock_flag(csk, CTPF_HAS_ATID)) {
+		cxgb4_free_atid(lldi->tids, csk->atid);
+		cxgbi_sock_clear_flag(csk, CTPF_HAS_ATID);
+		cxgbi_sock_put(csk);
+	}
+}
+
+static void do_act_establish(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_act_establish *req = (struct cpl_act_establish *)skb->data;
+	unsigned short tcp_opt = ntohs(req->tcp_opt);
+	unsigned int tid = GET_TID(req);
+	unsigned int atid = GET_TID_TID(ntohl(req->tos_atid));
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+	u32 rcv_isn = be32_to_cpu(req->rcv_isn);
+
+	csk = lookup_atid(t, atid);
+	if (unlikely(!csk)) {
+		pr_err("NO conn. for atid %u, cdev 0x%p.\n", atid, cdev);
+		goto rel_skb;
+	}
+
+	if (csk->atid != atid) {
+		pr_err("bad conn atid %u, csk 0x%p,%u,0x%lx,tid %u, atid %u.\n",
+			atid, csk, csk->state, csk->flags, csk->tid, csk->atid);
+		goto rel_skb;
+	}
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, tid %u, atid %u, rseq %u.\n",
+		csk, csk->state, csk->flags, tid, atid, rcv_isn);
+
+	cxgbi_sock_get(csk);
+	csk->tid = tid;
+	cxgb4_insert_tid(lldi->tids, csk, tid);
+	cxgbi_sock_set_flag(csk, CTPF_HAS_TID);
+
+	free_atid(csk);
+
+	spin_lock_bh(&csk->lock);
+	if (unlikely(csk->state != CTP_ACTIVE_OPEN))
+		pr_info("csk 0x%p,%u,0x%lx,%u, got EST.\n",
+			csk, csk->state, csk->flags, csk->tid);
+
+	if (csk->retry_timer.function) {
+		del_timer(&csk->retry_timer);
+		csk->retry_timer.function = NULL;
+	}
+
+	csk->copied_seq = csk->rcv_wup = csk->rcv_nxt = rcv_isn;
+	/*
+	 * Causes the first RX_DATA_ACK to supply any Rx credits we couldn't
+	 * pass through opt0.
+	 */
+	if (cxgb4i_rcv_win > (RCV_BUFSIZ_MASK << 10))
+		csk->rcv_wup -= cxgb4i_rcv_win - (RCV_BUFSIZ_MASK << 10);
+
+	csk->advmss = lldi->mtus[GET_TCPOPT_MSS(tcp_opt)] - 40;
+	if (GET_TCPOPT_TSTAMP(tcp_opt))
+		csk->advmss -= 12;
+	if (csk->advmss < 128)
+		csk->advmss = 128;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, mss_idx %u, advmss %u.\n",
+			csk, GET_TCPOPT_MSS(tcp_opt), csk->advmss);
+
+	cxgbi_sock_established(csk, ntohl(req->snd_isn), ntohs(req->tcp_opt));
+
+	if (unlikely(cxgbi_sock_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED)))
+		send_abort_req(csk);
+	else {
+		if (skb_queue_len(&csk->write_queue))
+			push_tx_frames(csk, 0);
+		cxgbi_conn_tx_open(csk);
+	}
+	spin_unlock_bh(&csk->lock);
+
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static int act_open_rpl_status_to_errno(int status)
+{
+	switch (status) {
+	case CPL_ERR_CONN_RESET:
+		return -ECONNREFUSED;
+	case CPL_ERR_ARP_MISS:
+		return -EHOSTUNREACH;
+	case CPL_ERR_CONN_TIMEDOUT:
+		return -ETIMEDOUT;
+	case CPL_ERR_TCAM_FULL:
+		return -ENOMEM;
+	case CPL_ERR_CONN_EXIST:
+		return -EADDRINUSE;
+	default:
+		return -EIO;
+	}
+}
+
+static void csk_act_open_retry_timer(unsigned long data)
+{
+	struct sk_buff *skb;
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+	skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_ATOMIC);
+	if (!skb)
+		cxgbi_sock_fail_act_open(csk, -ENOMEM);
+	else {
+		skb->sk = (struct sock *)csk;
+		t4_set_arp_err_handler(skb, csk,
+					cxgbi_sock_act_open_req_arp_failure);
+		send_act_open_req(csk, skb, csk->l2t);
+	}
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+
+static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_act_open_rpl *rpl = (struct cpl_act_open_rpl *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	unsigned int atid =
+		GET_TID_TID(GET_AOPEN_ATID(be32_to_cpu(rpl->atid_status)));
+	unsigned int status = GET_AOPEN_STATUS(be32_to_cpu(rpl->atid_status));
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_atid(t, atid);
+	if (unlikely(!csk)) {
+		pr_err("NO matching conn. atid %u, tid %u.\n", atid, tid);
+		goto rel_skb;
+	}
+
+	pr_info("%pI4:%u-%pI4:%u, atid %u,%u, status %u, csk 0x%p,%u,0x%lx.\n",
+		&csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
+		&csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port),
+		atid, tid, status, csk, csk->state, csk->flags);
+
+	if (status && status != CPL_ERR_TCAM_FULL &&
+	    status != CPL_ERR_CONN_EXIST &&
+	    status != CPL_ERR_ARP_MISS)
+		cxgb4_remove_tid(lldi->tids, csk->port_id, GET_TID(rpl));
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (status == CPL_ERR_CONN_EXIST &&
+	    csk->retry_timer.function != csk_act_open_retry_timer) {
+		csk->retry_timer.function = csk_act_open_retry_timer;
+		mod_timer(&csk->retry_timer, jiffies + HZ / 2);
+	} else
+		cxgbi_sock_fail_act_open(csk,
+					act_open_rpl_status_to_errno(status));
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_peer_close(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_peer_close *req = (struct cpl_peer_close *)skb->data;
+	unsigned int tid = GET_TID(req);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk)) {
+		pr_err("can't find connection for tid %u.\n", tid);
+		goto rel_skb;
+	}
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+	cxgbi_sock_rcv_peer_close(csk);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_close_con_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_close_con_rpl *rpl = (struct cpl_close_con_rpl *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk)) {
+		pr_err("can't find connection for tid %u.\n", tid);
+		goto rel_skb;
+	}
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+	cxgbi_sock_rcv_close_conn_rpl(csk, ntohl(rpl->snd_nxt));
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static int abort_status_to_errno(struct cxgbi_sock *csk, int abort_reason,
+								int *need_rst)
+{
+	switch (abort_reason) {
+	case CPL_ERR_BAD_SYN: /* fall through */
+	case CPL_ERR_CONN_RESET:
+		return csk->state > CTP_ESTABLISHED ?
+			-EPIPE : -ECONNRESET;
+	case CPL_ERR_XMIT_TIMEDOUT:
+	case CPL_ERR_PERSIST_TIMEDOUT:
+	case CPL_ERR_FINWAIT2_TIMEDOUT:
+	case CPL_ERR_KEEPALIVE_TIMEDOUT:
+		return -ETIMEDOUT;
+	default:
+		return -EIO;
+	}
+}
+
+static void do_abort_req_rss(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_abort_req_rss *req = (struct cpl_abort_req_rss *)skb->data;
+	unsigned int tid = GET_TID(req);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+	int rst_status = CPL_ABORT_NO_RST;
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk)) {
+		pr_err("can't find connection for tid %u.\n", tid);
+		goto rel_skb;
+	}
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, tid %u, status 0x%x.\n",
+		csk, csk->state, csk->flags, csk->tid, req->status);
+
+	if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
+	    req->status == CPL_ERR_PERSIST_NEG_ADVICE)
+		goto rel_skb;
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (!cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD)) {
+		cxgbi_sock_set_flag(csk, CTPF_ABORT_REQ_RCVD);
+		cxgbi_sock_set_state(csk, CTP_ABORTING);
+		goto done;
+	}
+
+	cxgbi_sock_clear_flag(csk, CTPF_ABORT_REQ_RCVD);
+	send_abort_rpl(csk, rst_status);
+
+	if (!cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING)) {
+		csk->err = abort_status_to_errno(csk, req->status, &rst_status);
+		cxgbi_sock_closed(csk);
+	}
+done:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_abort_rpl_rss(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_abort_rpl_rss *rpl = (struct cpl_abort_rpl_rss *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_tid(t, tid);
+	if (!csk)
+		goto rel_skb;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"status 0x%x, csk 0x%p, s %u, 0x%lx.\n",
+		rpl->status, csk, csk ? csk->state : 0,
+		csk ? csk->flags : 0UL);
+
+	if (rpl->status == CPL_ERR_ABORT_FAILED)
+		goto rel_skb;
+
+	cxgbi_sock_rcv_abort_rpl(csk);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_rx_iscsi_hdr(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_iscsi_hdr *cpl = (struct cpl_iscsi_hdr *)skb->data;
+	unsigned short pdu_len_ddp = be16_to_cpu(cpl->pdu_len_ddp);
+	unsigned int tid = GET_TID(cpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk)) {
+		pr_err("can't find conn. for tid %u.\n", tid);
+		goto rel_skb;
+	}
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx, tid %u, skb 0x%p,%u, 0x%x.\n",
+		csk, csk->state, csk->flags, csk->tid, skb, skb->len,
+		pdu_len_ddp);
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state >= CTP_PASSIVE_CLOSE)) {
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+			"csk 0x%p,%u,0x%lx,%u, bad state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		if (csk->state != CTP_ABORTING)
+			goto abort_conn;
+		else
+			goto discard;
+	}
+
+	cxgbi_skcb_tcp_seq(skb) = ntohl(cpl->seq);
+	cxgbi_skcb_flags(skb) = 0;
+
+	skb_reset_transport_header(skb);
+	__skb_pull(skb, sizeof(*cpl));
+	__pskb_trim(skb, ntohs(cpl->len));
+
+	if (!csk->skb_ulp_lhdr) {
+		unsigned char *bhs;
+		unsigned int hlen, dlen;
+
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p,%u,0x%lx, tid %u, skb 0x%p header.\n",
+			csk, csk->state, csk->flags, csk->tid, skb);
+		csk->skb_ulp_lhdr = skb;
+		cxgbi_skcb_set_flag(skb, SKCBF_RX_HDR);
+
+		if (cxgbi_skcb_tcp_seq(skb) != csk->rcv_nxt) {
+			pr_info("tid %u, CPL_ISCSI_HDR, bad seq, 0x%x/0x%x.\n",
+				csk->tid, cxgbi_skcb_tcp_seq(skb),
+				csk->rcv_nxt);
+			goto abort_conn;
+		}
+
+		bhs = skb->data;
+		hlen = ntohs(cpl->len);
+		dlen = ntohl(*(unsigned int *)(bhs + 4)) & 0xFFFFFF;
+
+		if ((hlen + dlen) != ISCSI_PDU_LEN(pdu_len_ddp) - 40) {
+			pr_info("tid 0x%x, CPL_ISCSI_HDR, pdu len "
+				"mismatch %u != %u + %u, seq 0x%x.\n",
+				csk->tid, ISCSI_PDU_LEN(pdu_len_ddp) - 40,
+				hlen, dlen, cxgbi_skcb_tcp_seq(skb));
+			goto abort_conn;
+		}
+
+		cxgbi_skcb_rx_pdulen(skb) = (hlen + dlen + 3) & (~0x3);
+		if (dlen)
+			cxgbi_skcb_rx_pdulen(skb) += csk->dcrc_len;
+		csk->rcv_nxt += cxgbi_skcb_rx_pdulen(skb);
+
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p, skb 0x%p, 0x%x,%u+%u,0x%x,0x%x.\n",
+			csk, skb, *bhs, hlen, dlen,
+			ntohl(*((unsigned int *)(bhs + 16))),
+			ntohl(*((unsigned int *)(bhs + 24))));
+
+	} else {
+		struct sk_buff *lskb = csk->skb_ulp_lhdr;
+
+		cxgbi_skcb_set_flag(lskb, SKCBF_RX_DATA);
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p,%u,0x%lx, skb 0x%p data, 0x%p.\n",
+			csk, csk->state, csk->flags, skb, lskb);
+	}
+
+	__skb_queue_tail(&csk->receive_queue, skb);
+	spin_unlock_bh(&csk->lock);
+	return;
+
+abort_conn:
+	send_abort_req(csk);
+discard:
+	spin_unlock_bh(&csk->lock);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_rx_data_ddp(struct cxgbi_device *cdev,
+				  struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct sk_buff *lskb;
+	struct cpl_rx_data_ddp *rpl = (struct cpl_rx_data_ddp *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+	unsigned int status = ntohl(rpl->ddpvld);
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk)) {
+		pr_err("can't find connection for tid %u.\n", tid);
+		goto rel_skb;
+	}
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx, skb 0x%p,0x%x, lhdr 0x%p.\n",
+		csk, csk->state, csk->flags, skb, status, csk->skb_ulp_lhdr);
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state >= CTP_PASSIVE_CLOSE)) {
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+			"csk 0x%p,%u,0x%lx,%u, bad state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		if (csk->state != CTP_ABORTING)
+			goto abort_conn;
+		else
+			goto discard;
+	}
+
+	if (!csk->skb_ulp_lhdr) {
+		pr_err("tid 0x%x, rcv RX_DATA_DDP w/o pdu bhs.\n", csk->tid);
+		goto abort_conn;
+	}
+
+	lskb = csk->skb_ulp_lhdr;
+	csk->skb_ulp_lhdr = NULL;
+
+	cxgbi_skcb_rx_ddigest(lskb) = ntohl(rpl->ulp_crc);
+
+	if (ntohs(rpl->len) != cxgbi_skcb_rx_pdulen(lskb))
+		pr_info("tid 0x%x, RX_DATA_DDP pdulen %u != %u.\n",
+			csk->tid, ntohs(rpl->len), cxgbi_skcb_rx_pdulen(lskb));
+
+	if (status & (1 << CPL_RX_DDP_STATUS_HCRC_SHIFT)) {
+		pr_info("csk 0x%p, lhdr 0x%p, status 0x%x, hcrc bad 0x%lx.\n",
+			csk, lskb, status, cxgbi_skcb_flags(lskb));
+		cxgbi_skcb_set_flag(lskb, SKCBF_RX_HCRC_ERR);
+	}
+	if (status & (1 << CPL_RX_DDP_STATUS_DCRC_SHIFT)) {
+		pr_info("csk 0x%p, lhdr 0x%p, status 0x%x, dcrc bad 0x%lx.\n",
+			csk, lskb, status, cxgbi_skcb_flags(lskb));
+		cxgbi_skcb_set_flag(lskb, SKCBF_RX_DCRC_ERR);
+	}
+	if (status & (1 << CPL_RX_DDP_STATUS_PAD_SHIFT)) {
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p, lhdr 0x%p, status 0x%x, pad bad.\n",
+			csk, lskb, status);
+		cxgbi_skcb_set_flag(lskb, SKCBF_RX_PAD_ERR);
+	}
+	if ((status & (1 << CPL_RX_DDP_STATUS_DDP_SHIFT)) &&
+		!cxgbi_skcb_test_flag(lskb, SKCBF_RX_DATA)) {
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p, lhdr 0x%p, 0x%x, data ddp'ed.\n",
+			csk, lskb, status);
+		cxgbi_skcb_set_flag(lskb, SKCBF_RX_DATA_DDPD);
+	}
+	log_debug(1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p, lskb 0x%p, f 0x%lx.\n",
+		csk, lskb, cxgbi_skcb_flags(lskb));
+
+	cxgbi_skcb_set_flag(lskb, SKCBF_RX_STATUS);
+	cxgbi_conn_pdu_ready(csk);
+	spin_unlock_bh(&csk->lock);
+	goto rel_skb;
+
+abort_conn:
+	send_abort_req(csk);
+discard:
+	spin_unlock_bh(&csk->lock);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_fw4_ack(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_fw4_ack *rpl = (struct cpl_fw4_ack *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk))
+		pr_err("can't find connection for tid %u.\n", tid);
+	else {
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+			"csk 0x%p,%u,0x%lx,%u.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		cxgbi_sock_rcv_wr_ack(csk, rpl->credits, ntohl(rpl->snd_una),
+					rpl->seq_vld);
+	}
+	__kfree_skb(skb);
+}
+
+static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cpl_set_tcb_rpl *rpl = (struct cpl_set_tcb_rpl *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+	struct cxgbi_sock *csk;
+
+	csk = lookup_tid(t, tid);
+	if (!csk)
+		pr_err("can't find conn. for tid %u.\n", tid);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,%lx,%u, status 0x%x.\n",
+		csk, csk->state, csk->flags, csk->tid, rpl->status);
+
+	if (rpl->status != CPL_ERR_NONE)
+		pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n",
+			csk, tid, rpl->status);
+
+	__kfree_skb(skb);
+}
+
+static int alloc_cpls(struct cxgbi_sock *csk)
+{
+	csk->cpl_close = alloc_wr(sizeof(struct cpl_close_con_req),
+					0, GFP_KERNEL);
+	if (!csk->cpl_close)
+		return -ENOMEM;
+
+	csk->cpl_abort_req = alloc_wr(sizeof(struct cpl_abort_req),
+					0, GFP_KERNEL);
+	if (!csk->cpl_abort_req)
+		goto free_cpls;
+
+	csk->cpl_abort_rpl = alloc_wr(sizeof(struct cpl_abort_rpl),
+					0, GFP_KERNEL);
+	if (!csk->cpl_abort_rpl)
+		goto free_cpls;
+	return 0;
+
+free_cpls:
+	cxgbi_sock_free_cpl_skbs(csk);
+	return -ENOMEM;
+}
+
+static inline void l2t_put(struct cxgbi_sock *csk)
+{
+	if (csk->l2t) {
+		cxgb4_l2t_release(csk->l2t);
+		csk->l2t = NULL;
+		cxgbi_sock_put(csk);
+	}
+}
+
+static void release_offload_resources(struct cxgbi_sock *csk)
+{
+	struct cxgb4_lld_info *lldi;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	cxgbi_sock_free_cpl_skbs(csk);
+	if (csk->wr_cred != csk->wr_max_cred) {
+		cxgbi_sock_purge_wr_queue(csk);
+		cxgbi_sock_reset_wr_list(csk);
+	}
+
+	l2t_put(csk);
+	if (cxgbi_sock_flag(csk, CTPF_HAS_ATID))
+		free_atid(csk);
+	else if (cxgbi_sock_flag(csk, CTPF_HAS_TID)) {
+		lldi = cxgbi_cdev_priv(csk->cdev);
+		cxgb4_remove_tid(lldi->tids, 0, csk->tid);
+		cxgbi_sock_clear_flag(csk, CTPF_HAS_TID);
+		cxgbi_sock_put(csk);
+	}
+	csk->dst = NULL;
+	csk->cdev = NULL;
+}
+
+static int init_act_open(struct cxgbi_sock *csk)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct net_device *ndev = cdev->ports[csk->port_id];
+	struct port_info *pi = netdev_priv(ndev);
+	struct sk_buff *skb = NULL;
+	unsigned int step;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	csk->atid = cxgb4_alloc_atid(lldi->tids, csk);
+	if (csk->atid < 0) {
+		pr_err("%s, NO atid available.\n", ndev->name);
+		return -EINVAL;
+	}
+	cxgbi_sock_set_flag(csk, CTPF_HAS_ATID);
+	cxgbi_sock_get(csk);
+
+	csk->l2t = cxgb4_l2t_get(lldi->l2t, csk->dst->neighbour, ndev, 0);
+	if (!csk->l2t) {
+		pr_err("%s, cannot alloc l2t.\n", ndev->name);
+		goto rel_resource;
+	}
+	cxgbi_sock_get(csk);
+
+	skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_KERNEL);
+	if (!skb)
+		goto rel_resource;
+	skb->sk = (struct sock *)csk;
+	t4_set_arp_err_handler(skb, csk, cxgbi_sock_act_open_req_arp_failure);
+
+	if (!csk->mtu)
+		csk->mtu = dst_mtu(csk->dst);
+	cxgb4_best_mtu(lldi->mtus, csk->mtu, &csk->mss_idx);
+	csk->tx_chan = cxgb4_port_chan(ndev);
+	/* SMT two entries per row */
+	csk->smac_idx = ((cxgb4_port_viid(ndev) & 0x7F)) << 1;
+	step = lldi->ntxq / lldi->nchan;
+	csk->txq_idx = cxgb4_port_idx(ndev) * step;
+	step = lldi->nrxq / lldi->nchan;
+	csk->rss_qid = lldi->rxq_ids[cxgb4_port_idx(ndev) * step];
+	csk->wr_max_cred = csk->wr_cred = lldi->wr_cred;
+	csk->wr_una_cred = 0;
+	cxgbi_sock_reset_wr_list(csk);
+	csk->err = 0;
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,p%d,%s, %u,%u,%u, mss %u,%u, smac %u.\n",
+		csk, pi->port_id, ndev->name, csk->tx_chan,
+		csk->txq_idx, csk->rss_qid, csk->mtu, csk->mss_idx,
+		csk->smac_idx);
+
+	cxgbi_sock_set_state(csk, CTP_ACTIVE_OPEN);
+	send_act_open_req(csk, skb, csk->l2t);
+	return 0;
+
+rel_resource:
+	if (skb)
+		__kfree_skb(skb);
+	return -EINVAL;
+}
+
+cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = {
+	[CPL_ACT_ESTABLISH] = do_act_establish,
+	[CPL_ACT_OPEN_RPL] = do_act_open_rpl,
+	[CPL_PEER_CLOSE] = do_peer_close,
+	[CPL_ABORT_REQ_RSS] = do_abort_req_rss,
+	[CPL_ABORT_RPL_RSS] = do_abort_rpl_rss,
+	[CPL_CLOSE_CON_RPL] = do_close_con_rpl,
+	[CPL_FW4_ACK] = do_fw4_ack,
+	[CPL_ISCSI_HDR] = do_rx_iscsi_hdr,
+	[CPL_SET_TCB_RPL] = do_set_tcb_rpl,
+	[CPL_RX_DATA_DDP] = do_rx_data_ddp,
+};
+
+int cxgb4i_ofld_init(struct cxgbi_device *cdev)
+{
+	int rc;
+
+	if (cxgb4i_max_connect > CXGB4I_MAX_CONN)
+		cxgb4i_max_connect = CXGB4I_MAX_CONN;
+
+	rc = cxgbi_device_portmap_create(cdev, cxgb4i_sport_base,
+					cxgb4i_max_connect);
+	if (rc < 0)
+		return rc;
+
+	cdev->csk_release_offload_resources = release_offload_resources;
+	cdev->csk_push_tx_frames = push_tx_frames;
+	cdev->csk_send_abort_req = send_abort_req;
+	cdev->csk_send_close_req = send_close_req;
+	cdev->csk_send_rx_credits = send_rx_credits;
+	cdev->csk_alloc_cpls = alloc_cpls;
+	cdev->csk_init_act_open = init_act_open;
+
+	pr_info("cdev 0x%p, offload up, added.\n", cdev);
+	return 0;
+}
+
+/*
+ * functions to program the pagepod in h/w
+ */
+#define ULPMEM_IDATA_MAX_NPPODS	4 /* 256/PPOD_SIZE */
+static inline void ulp_mem_io_set_hdr(struct ulp_mem_io *req,
+				unsigned int wr_len, unsigned int dlen,
+				unsigned int pm_addr)
+{
+	struct ulptx_idata *idata = (struct ulptx_idata *)(req + 1);
+
+	INIT_ULPTX_WR(req, wr_len, 0, 0);
+	req->cmd = htonl(ULPTX_CMD(ULP_TX_MEM_WRITE) | (1 << 23));
+	req->dlen = htonl(ULP_MEMIO_DATA_LEN(dlen >> 5));
+	req->lock_addr = htonl(ULP_MEMIO_ADDR(pm_addr >> 5));
+	req->len16 = htonl(DIV_ROUND_UP(wr_len - sizeof(req->wr), 16));
+
+	idata->cmd_more = htonl(ULPTX_CMD(ULP_TX_SC_IMM));
+	idata->len = htonl(dlen);
+}
+
+static int ddp_ppod_write_idata(struct cxgbi_device *cdev, unsigned int port_id,
+				struct cxgbi_pagepod_hdr *hdr, unsigned int idx,
+				unsigned int npods,
+				struct cxgbi_gather_list *gl,
+				unsigned int gl_pidx)
+{
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	struct sk_buff *skb;
+	struct ulp_mem_io *req;
+	struct ulptx_idata *idata;
+	struct cxgbi_pagepod *ppod;
+	unsigned int pm_addr = idx * PPOD_SIZE + ddp->llimit;
+	unsigned int dlen = PPOD_SIZE * npods;
+	unsigned int wr_len = roundup(sizeof(struct ulp_mem_io) +
+				sizeof(struct ulptx_idata) + dlen, 16);
+	unsigned int i;
+
+	skb = alloc_wr(wr_len, 0, GFP_ATOMIC);
+	if (!skb) {
+		pr_err("cdev 0x%p, idx %u, npods %u, OOM.\n",
+			cdev, idx, npods);
+		return -ENOMEM;
+	}
+	req = (struct ulp_mem_io *)skb->head;
+	set_queue(skb, CPL_PRIORITY_CONTROL, NULL);
+
+	ulp_mem_io_set_hdr(req, wr_len, dlen, pm_addr);
+	idata = (struct ulptx_idata *)(req + 1);
+	ppod = (struct cxgbi_pagepod *)(idata + 1);
+
+	for (i = 0; i < npods; i++, ppod++, gl_pidx += PPOD_PAGES_MAX) {
+		if (!hdr && !gl)
+			cxgbi_ddp_ppod_clear(ppod);
+		else
+			cxgbi_ddp_ppod_set(ppod, hdr, gl, gl_pidx);
+	}
+
+	cxgb4_ofld_send(cdev->ports[port_id], skb);
+	return 0;
+}
+
+static int ddp_set_map(struct cxgbi_sock *csk, struct cxgbi_pagepod_hdr *hdr,
+			unsigned int idx, unsigned int npods,
+			struct cxgbi_gather_list *gl)
+{
+	unsigned int i, cnt;
+	int err = 0;
+
+	for (i = 0; i < npods; i += cnt, idx += cnt) {
+		cnt = npods - i;
+		if (cnt > ULPMEM_IDATA_MAX_NPPODS)
+			cnt = ULPMEM_IDATA_MAX_NPPODS;
+		err = ddp_ppod_write_idata(csk->cdev, csk->port_id, hdr,
+					idx, cnt, gl, 4 * i);
+		if (err < 0)
+			break;
+	}
+	return err;
+}
+
+static void ddp_clear_map(struct cxgbi_hba *chba, unsigned int tag,
+			  unsigned int idx, unsigned int npods)
+{
+	unsigned int i, cnt;
+	int err;
+
+	for (i = 0; i < npods; i += cnt, idx += cnt) {
+		cnt = npods - i;
+		if (cnt > ULPMEM_IDATA_MAX_NPPODS)
+			cnt = ULPMEM_IDATA_MAX_NPPODS;
+		err = ddp_ppod_write_idata(chba->cdev, chba->port_id, NULL,
+					idx, cnt, NULL, 0);
+		if (err < 0)
+			break;
+	}
+}
+
+static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
+				int pg_idx, bool reply)
+{
+	struct sk_buff *skb;
+	struct cpl_set_tcb_field *req;
+
+	if (!pg_idx || pg_idx >= DDP_PGIDX_MAX)
+		return 0;
+
+	skb = alloc_wr(sizeof(*req), 0, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	/*  set up ulp page size */
+	req = (struct cpl_set_tcb_field *)skb->head;
+	INIT_TP_WR(req, csk->tid);
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid));
+	req->reply_ctrl = htons(NO_REPLY(reply) | QUEUENO(csk->rss_qid));
+	req->word_cookie = htons(0);
+	req->mask = cpu_to_be64(0x3 << 8);
+	req->val = cpu_to_be64(pg_idx << 8);
+	set_wr_txq(skb, CPL_PRIORITY_CONTROL, csk->port_id);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx);
+
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+	return 0;
+}
+
+static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
+				 int hcrc, int dcrc, int reply)
+{
+	struct sk_buff *skb;
+	struct cpl_set_tcb_field *req;
+
+	if (!hcrc && !dcrc)
+		return 0;
+
+	skb = alloc_wr(sizeof(*req), 0, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	csk->hcrc_len = (hcrc ? 4 : 0);
+	csk->dcrc_len = (dcrc ? 4 : 0);
+	/*  set up ulp submode */
+	req = (struct cpl_set_tcb_field *)skb->head;
+	INIT_TP_WR(req, tid);
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+	req->reply_ctrl = htons(NO_REPLY(reply) | QUEUENO(csk->rss_qid));
+	req->word_cookie = htons(0);
+	req->mask = cpu_to_be64(0x3 << 4);
+	req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) |
+				(dcrc ? ULP_CRC_DATA : 0)) << 4);
+	set_wr_txq(skb, CPL_PRIORITY_CONTROL, csk->port_id);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc);
+
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+	return 0;
+}
+
+static int cxgb4i_ddp_init(struct cxgbi_device *cdev)
+{
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	unsigned int tagmask, pgsz_factor[4];
+	int err;
+
+	if (ddp) {
+		kref_get(&ddp->refcnt);
+		pr_warn("cdev 0x%p, ddp 0x%p already set up.\n",
+			cdev, cdev->ddp);
+		return -EALREADY;
+	}
+
+	err = cxgbi_ddp_init(cdev, lldi->vr->iscsi.start,
+			lldi->vr->iscsi.start + lldi->vr->iscsi.size - 1,
+			lldi->iscsi_iolen, lldi->iscsi_iolen);
+	if (err < 0)
+		return err;
+
+	ddp = cdev->ddp;
+
+	tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
+	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;
+	cdev->csk_ddp_clear = ddp_clear_map;
+
+	pr_info("cxgb4i 0x%p tag: sw %u, rsvd %u,%u, mask 0x%x.\n",
+		cdev, cdev->tag_format.sw_bits, cdev->tag_format.rsvd_bits,
+		cdev->tag_format.rsvd_shift, cdev->tag_format.rsvd_mask);
+	pr_info("cxgb4i 0x%p, nppods %u, bits %u, mask 0x%x,0x%x pkt %u/%u, "
+		" %u/%u.\n",
+		cdev, ddp->nppods, ddp->idx_bits, ddp->idx_mask,
+		ddp->rsvd_tag_mask, ddp->max_txsz, lldi->iscsi_iolen,
+		ddp->max_rxsz, lldi->iscsi_iolen);
+	pr_info("cxgb4i 0x%p max payload size: %u/%u, %u/%u.\n",
+		cdev, cdev->tx_max_size, ddp->max_txsz, cdev->rx_max_size,
+		ddp->max_rxsz);
+	return 0;
+}
+
+static void *t4_uld_add(const struct cxgb4_lld_info *lldi)
+{
+	struct cxgbi_device *cdev;
+	struct port_info *pi;
+	int i, rc;
+
+	cdev = cxgbi_device_register(sizeof(*lldi), lldi->nports);
+	if (!cdev) {
+		pr_info("t4 device 0x%p, register failed.\n", lldi);
+		return NULL;
+	}
+	pr_info("0x%p,0x%x, ports %u,%s, chan %u, q %u,%u, wr %u.\n",
+		cdev, lldi->adapter_type, lldi->nports,
+		lldi->ports[0]->name, lldi->nchan, lldi->ntxq,
+		lldi->nrxq, lldi->wr_cred);
+	for (i = 0; i < lldi->nrxq; i++)
+		log_debug(1 << CXGBI_DBG_DEV,
+			"t4 0x%p, rxq id #%d: %u.\n",
+			cdev, i, lldi->rxq_ids[i]);
+
+	memcpy(cxgbi_cdev_priv(cdev), lldi, sizeof(*lldi));
+	cdev->flags = CXGBI_FLAG_DEV_T4;
+	cdev->pdev = lldi->pdev;
+	cdev->ports = lldi->ports;
+	cdev->nports = lldi->nports;
+	cdev->mtus = lldi->mtus;
+	cdev->nmtus = NMTUS;
+	cdev->snd_win = cxgb4i_snd_win;
+	cdev->rcv_win = cxgb4i_rcv_win;
+	cdev->rx_credit_thres = cxgb4i_rx_credit_thres;
+	cdev->skb_tx_rsvd = CXGB4I_TX_HEADER_LEN;
+	cdev->skb_rx_extra = sizeof(struct cpl_iscsi_hdr);
+	cdev->itp = &cxgb4i_iscsi_transport;
+
+	cdev->pfvf = FW_VIID_PFN_GET(cxgb4_port_viid(lldi->ports[0])) << 8;
+	pr_info("cdev 0x%p,%s, pfvf %u.\n",
+		cdev, lldi->ports[0]->name, cdev->pfvf);
+
+	rc = cxgb4i_ddp_init(cdev);
+	if (rc) {
+		pr_info("t4 0x%p ddp init failed.\n", cdev);
+		goto err_out;
+	}
+	rc = cxgb4i_ofld_init(cdev);
+	if (rc) {
+		pr_info("t4 0x%p ofld init failed.\n", cdev);
+		goto err_out;
+	}
+
+	rc = cxgbi_hbas_add(cdev, CXGB4I_MAX_LUN, CXGBI_MAX_CONN,
+				&cxgb4i_host_template, cxgb4i_stt);
+	if (rc)
+		goto err_out;
+
+	for (i = 0; i < cdev->nports; i++) {
+		pi = netdev_priv(lldi->ports[i]);
+		cdev->hbas[i]->port_id = pi->port_id;
+	}
+	return cdev;
+
+err_out:
+	cxgbi_device_unregister(cdev);
+	return ERR_PTR(-ENOMEM);
+}
+
+#define RX_PULL_LEN	128
+static int t4_uld_rx_handler(void *handle, const __be64 *rsp,
+				const struct pkt_gl *pgl)
+{
+	const struct cpl_act_establish *rpl;
+	struct sk_buff *skb;
+	unsigned int opc;
+	struct cxgbi_device *cdev = handle;
+
+	if (pgl == NULL) {
+		unsigned int len = 64 - sizeof(struct rsp_ctrl) - 8;
+
+		skb = alloc_wr(len, 0, GFP_ATOMIC);
+		if (!skb)
+			goto nomem;
+		skb_copy_to_linear_data(skb, &rsp[1], len);
+	} else {
+		if (unlikely(*(u8 *)rsp != *(u8 *)pgl->va)) {
+			pr_info("? FL 0x%p,RSS%#llx,FL %#llx,len %u.\n",
+				pgl->va, be64_to_cpu(*rsp),
+				be64_to_cpu(*(u64 *)pgl->va),
+				pgl->tot_len);
+			return 0;
+		}
+		skb = cxgb4_pktgl_to_skb(pgl, RX_PULL_LEN, RX_PULL_LEN);
+		if (unlikely(!skb))
+			goto nomem;
+	}
+
+	rpl = (struct cpl_act_establish *)skb->data;
+	opc = rpl->ot.opcode;
+	log_debug(1 << CXGBI_DBG_TOE,
+		"cdev %p, opcode 0x%x(0x%x,0x%x), skb %p.\n",
+		 cdev, opc, rpl->ot.opcode_tid, ntohl(rpl->ot.opcode_tid), skb);
+	if (cxgb4i_cplhandlers[opc])
+		cxgb4i_cplhandlers[opc](cdev, skb);
+	else {
+		pr_err("No handler for opcode 0x%x.\n", opc);
+		__kfree_skb(skb);
+	}
+	return 0;
+nomem:
+	log_debug(1 << CXGBI_DBG_TOE, "OOM bailing out.\n");
+	return 1;
+}
+
+static int t4_uld_state_change(void *handle, enum cxgb4_state state)
+{
+	struct cxgbi_device *cdev = handle;
+
+	switch (state) {
+	case CXGB4_STATE_UP:
+		pr_info("cdev 0x%p, UP.\n", cdev);
+		/* re-initialize */
+		break;
+	case CXGB4_STATE_START_RECOVERY:
+		pr_info("cdev 0x%p, RECOVERY.\n", cdev);
+		/* close all connections */
+		break;
+	case CXGB4_STATE_DOWN:
+		pr_info("cdev 0x%p, DOWN.\n", cdev);
+		break;
+	case CXGB4_STATE_DETACH:
+		pr_info("cdev 0x%p, DETACH.\n", cdev);
+		break;
+	default:
+		pr_info("cdev 0x%p, unknown state %d.\n", cdev, state);
+		break;
+	}
+	return 0;
+}
+
+static int __init cxgb4i_init_module(void)
+{
+	int rc;
+
+	printk(KERN_INFO "%s", version);
+
+	rc = cxgbi_iscsi_init(&cxgb4i_iscsi_transport, &cxgb4i_stt);
+	if (rc < 0)
+		return rc;
+	cxgb4_register_uld(CXGB4_ULD_ISCSI, &cxgb4i_uld_info);
+	return 0;
+}
+
+static void __exit cxgb4i_exit_module(void)
+{
+	cxgb4_unregister_uld(CXGB4_ULD_ISCSI);
+	cxgbi_device_unregister_all(CXGBI_FLAG_DEV_T4);
+	cxgbi_iscsi_cleanup(&cxgb4i_iscsi_transport, &cxgb4i_stt);
+}
+
+module_init(cxgb4i_init_module);
+module_exit(cxgb4i_exit_module);
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.h b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.h
new file mode 100644
index 0000000..1096026
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.h
@@ -0,0 +1,43 @@
+/*
+ * cxgb4i.h: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ * Written by: Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#ifndef	__CXGB4I_H__
+#define	__CXGB4I_H__
+
+#define	CXGB4I_SCSI_HOST_QDEPTH	1024
+#define	CXGB4I_MAX_CONN		16384
+#define	CXGB4I_MAX_TARGET	CXGB4I_MAX_CONN
+#define	CXGB4I_MAX_LUN		0x1000
+
+/* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
+#define CXGB4I_TX_HEADER_LEN \
+	(sizeof(struct fw_ofld_tx_data_wr) + sizeof(struct sge_opaque_hdr))
+
+struct ulptx_idata {
+	__be32 cmd_more;
+	__be32 len;
+};
+
+struct cpl_rx_data_ddp {
+	union opcode_tid ot;
+	__be16 urg;
+	__be16 len;
+	__be32 seq;
+	union {
+		__be32 nxt_seq;
+		__be32 ddp_report;
+	};
+	__be32 ulp_crc;
+	__be32 ddpvld;
+};
+#endif	/* __CXGB4I_H__ */
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
new file mode 100644
index 0000000..be56617
--- /dev/null
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -0,0 +1,2612 @@
+/*
+ * libcxgbi.c: Chelsio common library for T3/T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ * Written by: Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/skbuff.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <linux/pci.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <linux/if_vlan.h>
+#include <linux/inet.h>
+#include <net/dst.h>
+#include <net/route.h>
+#include <linux/inetdevice.h>	/* ip_dev_find */
+#include <net/tcp.h>
+
+static unsigned int dbg_level;
+
+#include "libcxgbi.h"
+
+#define DRV_MODULE_NAME		"libcxgbi"
+#define DRV_MODULE_DESC		"Chelsio iSCSI driver library"
+#define DRV_MODULE_VERSION	"0.9.0"
+#define DRV_MODULE_RELDATE	"Jun. 2010"
+
+MODULE_AUTHOR("Chelsio Communications, Inc.");
+MODULE_DESCRIPTION(DRV_MODULE_DESC);
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(dbg_level, uint, 0644);
+MODULE_PARM_DESC(dbg_level, "libiscsi debug level (default=0)");
+
+
+/*
+ * cxgbi device management
+ * maintains a list of the cxgbi devices
+ */
+static LIST_HEAD(cdev_list);
+static DEFINE_MUTEX(cdev_mutex);
+
+int cxgbi_device_portmap_create(struct cxgbi_device *cdev, unsigned int base,
+				unsigned int max_conn)
+{
+	struct cxgbi_ports_map *pmap = &cdev->pmap;
+
+	pmap->port_csk = cxgbi_alloc_big_mem(max_conn *
+					     sizeof(struct cxgbi_sock *),
+					     GFP_KERNEL);
+	if (!pmap->port_csk) {
+		pr_warn("cdev 0x%p, portmap OOM %u.\n", cdev, max_conn);
+		return -ENOMEM;
+	}
+
+	pmap->max_connect = max_conn;
+	pmap->sport_base = base;
+	spin_lock_init(&pmap->lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_portmap_create);
+
+void cxgbi_device_portmap_cleanup(struct cxgbi_device *cdev)
+{
+	struct cxgbi_ports_map *pmap = &cdev->pmap;
+	struct cxgbi_sock *csk;
+	int i;
+
+	for (i = 0; i < pmap->max_connect; i++) {
+		if (pmap->port_csk[i]) {
+			csk = pmap->port_csk[i];
+			pmap->port_csk[i] = NULL;
+			log_debug(1 << CXGBI_DBG_SOCK,
+				"csk 0x%p, cdev 0x%p, offload down.\n",
+				csk, cdev);
+			spin_lock_bh(&csk->lock);
+			cxgbi_sock_set_flag(csk, CTPF_OFFLOAD_DOWN);
+			cxgbi_sock_closed(csk);
+			spin_unlock_bh(&csk->lock);
+			cxgbi_sock_put(csk);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_portmap_cleanup);
+
+static inline void cxgbi_device_destroy(struct cxgbi_device *cdev)
+{
+	log_debug(1 << CXGBI_DBG_DEV,
+		"cdev 0x%p, p# %u.\n", cdev, cdev->nports);
+	cxgbi_hbas_remove(cdev);
+	cxgbi_device_portmap_cleanup(cdev);
+	if (cdev->dev_ddp_cleanup)
+		cdev->dev_ddp_cleanup(cdev);
+	else
+		cxgbi_ddp_cleanup(cdev);
+	if (cdev->ddp)
+		cxgbi_ddp_cleanup(cdev);
+	if (cdev->pmap.max_connect)
+		cxgbi_free_big_mem(cdev->pmap.port_csk);
+	kfree(cdev);
+}
+
+struct cxgbi_device *cxgbi_device_register(unsigned int extra,
+					   unsigned int nports)
+{
+	struct cxgbi_device *cdev;
+
+	cdev = kzalloc(sizeof(*cdev) + extra + nports *
+			(sizeof(struct cxgbi_hba *) +
+			 sizeof(struct net_device *)),
+			GFP_KERNEL);
+	if (!cdev) {
+		pr_warn("nport %d, OOM.\n", nports);
+		return NULL;
+	}
+	cdev->ports = (struct net_device **)(cdev + 1);
+	cdev->hbas = (struct cxgbi_hba **)(((char*)cdev->ports) + nports *
+						sizeof(struct net_device *));
+	if (extra)
+		cdev->dd_data = ((char *)cdev->hbas) +
+				nports * sizeof(struct cxgbi_hba *);
+	spin_lock_init(&cdev->pmap.lock);
+
+	mutex_lock(&cdev_mutex);
+	list_add_tail(&cdev->list_head, &cdev_list);
+	mutex_unlock(&cdev_mutex);
+
+	log_debug(1 << CXGBI_DBG_DEV,
+		"cdev 0x%p, p# %u.\n", cdev, nports);
+	return cdev;
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_register);
+
+void cxgbi_device_unregister(struct cxgbi_device *cdev)
+{
+	log_debug(1 << CXGBI_DBG_DEV,
+		"cdev 0x%p, p# %u,%s.\n",
+		cdev, cdev->nports, cdev->nports ? cdev->ports[0]->name : "");
+	mutex_lock(&cdev_mutex);
+	list_del(&cdev->list_head);
+	mutex_unlock(&cdev_mutex);
+	cxgbi_device_destroy(cdev);
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_unregister);
+
+void cxgbi_device_unregister_all(unsigned int flag)
+{
+	struct cxgbi_device *cdev, *tmp;
+
+	mutex_lock(&cdev_mutex);
+	list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+		if ((cdev->flags & flag) == flag) {
+			log_debug(1 << CXGBI_DBG_DEV,
+				"cdev 0x%p, p# %u,%s.\n",
+				cdev, cdev->nports, cdev->nports ?
+				 cdev->ports[0]->name : "");
+			list_del(&cdev->list_head);
+			cxgbi_device_destroy(cdev);
+		}
+	}
+	mutex_unlock(&cdev_mutex);
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_unregister_all);
+
+struct cxgbi_device *cxgbi_device_find_by_lldev(void *lldev)
+{
+	struct cxgbi_device *cdev, *tmp;
+
+	mutex_lock(&cdev_mutex);
+	list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+		if (cdev->lldev == lldev) {
+			mutex_unlock(&cdev_mutex);
+			return cdev;
+		}
+	}
+	mutex_unlock(&cdev_mutex);
+	log_debug(1 << CXGBI_DBG_DEV,
+		"lldev 0x%p, NO match found.\n", lldev);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_find_by_lldev);
+
+static struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev,
+							int *port)
+{
+	struct net_device *vdev = NULL;
+	struct cxgbi_device *cdev, *tmp;
+	int i;
+
+	if (ndev->priv_flags & IFF_802_1Q_VLAN) {
+		vdev = ndev;
+		ndev = vlan_dev_real_dev(ndev);
+		log_debug(1 << CXGBI_DBG_DEV,
+			"vlan dev %s -> %s.\n", vdev->name, ndev->name);
+	}
+
+	mutex_lock(&cdev_mutex);
+	list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+		for (i = 0; i < cdev->nports; i++) {
+			if (ndev == cdev->ports[i]) {
+				cdev->hbas[i]->vdev = vdev;
+				mutex_unlock(&cdev_mutex);
+				if (port)
+					*port = i;
+				return cdev;
+			}
+		}
+	}
+	mutex_unlock(&cdev_mutex);
+	log_debug(1 << CXGBI_DBG_DEV,
+		"ndev 0x%p, %s, NO match found.\n", ndev, ndev->name);
+	return NULL;
+}
+
+void cxgbi_hbas_remove(struct cxgbi_device *cdev)
+{
+	int i;
+	struct cxgbi_hba *chba;
+
+	log_debug(1 << CXGBI_DBG_DEV,
+		"cdev 0x%p, p#%u.\n", cdev, cdev->nports);
+
+	for (i = 0; i < cdev->nports; i++) {
+		chba = cdev->hbas[i];
+		if (chba) {
+			cdev->hbas[i] = NULL;
+			iscsi_host_remove(chba->shost);
+			pci_dev_put(cdev->pdev);
+			iscsi_host_free(chba->shost);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_hbas_remove);
+
+int cxgbi_hbas_add(struct cxgbi_device *cdev, unsigned int max_lun,
+		unsigned int max_id, struct scsi_host_template *sht,
+		struct scsi_transport_template *stt)
+{
+	struct cxgbi_hba *chba;
+	struct Scsi_Host *shost;
+	int i, err;
+
+	log_debug(1 << CXGBI_DBG_DEV, "cdev 0x%p, p#%u.\n", cdev, cdev->nports);
+
+	for (i = 0; i < cdev->nports; i++) {
+		shost = iscsi_host_alloc(sht, sizeof(*chba), 1);
+		if (!shost) {
+			pr_info("0x%p, p%d, %s, host alloc failed.\n",
+				cdev, i, cdev->ports[i]->name);
+			err = -ENOMEM;
+			goto err_out;
+		}
+
+		shost->transportt = stt;
+		shost->max_lun = max_lun;
+		shost->max_id = max_id;
+		shost->max_channel = 0;
+		shost->max_cmd_len = 16;
+
+		chba = iscsi_host_priv(shost);
+		chba->cdev = cdev;
+		chba->ndev = cdev->ports[i];
+		chba->shost = shost;
+
+		log_debug(1 << CXGBI_DBG_DEV,
+			"cdev 0x%p, p#%d %s: chba 0x%p.\n",
+			cdev, i, cdev->ports[i]->name, chba);
+
+		pci_dev_get(cdev->pdev);
+		err = iscsi_host_add(shost, &cdev->pdev->dev);
+		if (err) {
+			pr_info("cdev 0x%p, p#%d %s, host add failed.\n",
+				cdev, i, cdev->ports[i]->name);
+			pci_dev_put(cdev->pdev);
+			scsi_host_put(shost);
+			goto  err_out;
+		}
+
+		cdev->hbas[i] = chba;
+	}
+
+	return 0;
+
+err_out:
+	cxgbi_hbas_remove(cdev);
+	return err;
+}
+EXPORT_SYMBOL_GPL(cxgbi_hbas_add);
+
+/*
+ * iSCSI offload
+ *
+ * - source port management
+ *   To find a free source port in the port allocation map we use a very simple
+ *   rotor scheme to look for the next free port.
+ *
+ *   If a source port has been specified make sure that it doesn't collide with
+ *   our normal source port allocation map.  If it's outside the range of our
+ *   allocation/deallocation scheme just let them use it.
+ *
+ *   If the source port is outside our allocation range, the caller is
+ *   responsible for keeping track of their port usage.
+ */
+static int sock_get_port(struct cxgbi_sock *csk)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgbi_ports_map *pmap = &cdev->pmap;
+	unsigned int start;
+	int idx;
+
+	if (!pmap->max_connect) {
+		pr_err("cdev 0x%p, p#%u %s, NO port map.\n",
+			   cdev, csk->port_id, cdev->ports[csk->port_id]->name);
+		return -EADDRNOTAVAIL;
+	}
+
+	if (csk->saddr.sin_port) {
+		pr_err("source port NON-ZERO %u.\n",
+			ntohs(csk->saddr.sin_port));
+		return -EADDRINUSE;
+	}
+
+	spin_lock_bh(&pmap->lock);
+	if (pmap->used >= pmap->max_connect) {
+		spin_unlock_bh(&pmap->lock);
+		pr_info("cdev 0x%p, p#%u %s, ALL ports used.\n",
+			cdev, csk->port_id, cdev->ports[csk->port_id]->name);
+		return -EADDRNOTAVAIL;
+	}
+
+	start = idx = pmap->next;
+	do {
+		if (++idx >= pmap->max_connect)
+			idx = 0;
+		if (!pmap->port_csk[idx]) {
+			pmap->used++;
+			csk->saddr.sin_port =
+				htons(pmap->sport_base + idx);
+			pmap->next = idx;
+			pmap->port_csk[idx] = csk;
+			spin_unlock_bh(&pmap->lock);
+			cxgbi_sock_get(csk);
+			log_debug(1 << CXGBI_DBG_SOCK,
+				"cdev 0x%p, p#%u %s, p %u, %u.\n",
+				cdev, csk->port_id,
+				cdev->ports[csk->port_id]->name,
+				pmap->sport_base + idx, pmap->next);
+			return 0;
+		}
+	} while (idx != start);
+	spin_unlock_bh(&pmap->lock);
+
+	/* should not happen */
+	pr_warn("cdev 0x%p, p#%u %s, next %u?\n",
+		cdev, csk->port_id, cdev->ports[csk->port_id]->name,
+		pmap->next);
+	return -EADDRNOTAVAIL;
+}
+
+static void sock_put_port(struct cxgbi_sock *csk)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgbi_ports_map *pmap = &cdev->pmap;
+
+	if (csk->saddr.sin_port) {
+		int idx = ntohs(csk->saddr.sin_port) - pmap->sport_base;
+
+		csk->saddr.sin_port = 0;
+		if (idx < 0 || idx >= pmap->max_connect) {
+			pr_err("cdev 0x%p, p#%u %s, port %u OOR.\n",
+				cdev, csk->port_id,
+				cdev->ports[csk->port_id]->name,
+				ntohs(csk->saddr.sin_port));
+			return;
+		}
+
+		spin_lock_bh(&pmap->lock);
+		pmap->port_csk[idx] = NULL;
+		pmap->used--;
+		spin_unlock_bh(&pmap->lock);
+
+		log_debug(1 << CXGBI_DBG_SOCK,
+			"cdev 0x%p, p#%u %s, release %u.\n",
+			cdev, csk->port_id, cdev->ports[csk->port_id]->name,
+			pmap->sport_base + idx);
+
+		cxgbi_sock_put(csk);
+	}
+}
+
+/*
+ * iscsi tcp connection
+ */
+void cxgbi_sock_free_cpl_skbs(struct cxgbi_sock *csk)
+{
+	if (csk->cpl_close) {
+		kfree_skb(csk->cpl_close);
+		csk->cpl_close = NULL;
+	}
+	if (csk->cpl_abort_req) {
+		kfree_skb(csk->cpl_abort_req);
+		csk->cpl_abort_req = NULL;
+	}
+	if (csk->cpl_abort_rpl) {
+		kfree_skb(csk->cpl_abort_rpl);
+		csk->cpl_abort_rpl = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_free_cpl_skbs);
+
+static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev)
+{
+	struct cxgbi_sock *csk = kzalloc(sizeof(*csk), GFP_NOIO);
+
+	if (!csk) {
+		pr_info("alloc csk %zu failed.\n", sizeof(*csk));
+		return NULL;
+	}
+
+	if (cdev->csk_alloc_cpls(csk) < 0) {
+		pr_info("csk 0x%p, alloc cpls failed.\n", csk);
+		kfree(csk);
+		return NULL;
+	}
+
+	spin_lock_init(&csk->lock);
+	kref_init(&csk->refcnt);
+	skb_queue_head_init(&csk->receive_queue);
+	skb_queue_head_init(&csk->write_queue);
+	setup_timer(&csk->retry_timer, NULL, (unsigned long)csk);
+	rwlock_init(&csk->callback_lock);
+	csk->cdev = cdev;
+	csk->flags = 0;
+	cxgbi_sock_set_state(csk, CTP_CLOSED);
+
+	log_debug(1 << CXGBI_DBG_SOCK, "cdev 0x%p, new csk 0x%p.\n", cdev, csk);
+
+	return csk;
+}
+
+static struct rtable *find_route_ipv4(__be32 saddr, __be32 daddr,
+					__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))
+		return NULL;
+
+	return rt;
+}
+
+static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
+{
+	struct sockaddr_in *daddr = (struct sockaddr_in *)dst_addr;
+	struct dst_entry *dst;
+	struct net_device *ndev;
+	struct cxgbi_device *cdev;
+	struct rtable *rt = NULL;
+	struct cxgbi_sock *csk = NULL;
+	unsigned int mtu = 0;
+	int port = 0xFFFF;
+	int err = 0;
+
+	if (daddr->sin_family != AF_INET) {
+		pr_info("address family 0x%x NOT supported.\n",
+			daddr->sin_family);
+		err = -EAFNOSUPPORT;
+		goto err_out;
+	}
+
+	rt = find_route_ipv4(0, daddr->sin_addr.s_addr, 0, daddr->sin_port, 0);
+	if (!rt) {
+		pr_info("no route to ipv4 0x%x, port %u.\n",
+			daddr->sin_addr.s_addr, daddr->sin_port);
+		err = -ENETUNREACH;
+		goto err_out;
+	}
+	dst = &rt->dst;
+	ndev = dst->neighbour->dev;
+
+	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
+		pr_info("multi-cast route %pI4, port %u, dev %s.\n",
+			&daddr->sin_addr.s_addr, ntohs(daddr->sin_port),
+			ndev->name);
+		err = -ENETUNREACH;
+		goto rel_rt;
+	}
+
+	if (ndev->flags & IFF_LOOPBACK) {
+		ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr);
+		mtu = ndev->mtu;
+		pr_info("rt dev %s, loopback -> %s, mtu %u.\n",
+			dst->neighbour->dev->name, ndev->name, mtu);
+	}
+
+	cdev = cxgbi_device_find_by_netdev(ndev, &port);
+	if (!cdev) {
+		pr_info("dst %pI4, %s, NOT cxgbi device.\n",
+			&daddr->sin_addr.s_addr, ndev->name);
+		err = -ENETUNREACH;
+		goto rel_rt;
+	}
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"route to %pI4 :%u, ndev p#%d,%s, cdev 0x%p.\n",
+		&daddr->sin_addr.s_addr, ntohs(daddr->sin_port),
+			   port, ndev->name, cdev);
+
+	csk = cxgbi_sock_create(cdev);
+	if (!csk) {
+		err = -ENOMEM;
+		goto rel_rt;
+	}
+	csk->cdev = cdev;
+	csk->port_id = port;
+	csk->mtu = mtu;
+	csk->dst = dst;
+	csk->daddr.sin_addr.s_addr = daddr->sin_addr.s_addr;
+	csk->daddr.sin_port = daddr->sin_port;
+	csk->saddr.sin_addr.s_addr = rt->rt_src;
+
+	return csk;
+
+rel_rt:
+	ip_rt_put(rt);
+	if (csk)
+		cxgbi_sock_closed(csk);
+err_out:
+	return ERR_PTR(err);
+}
+
+void cxgbi_sock_established(struct cxgbi_sock *csk, unsigned int snd_isn,
+			unsigned int opt)
+{
+	csk->write_seq = csk->snd_nxt = csk->snd_una = snd_isn;
+	dst_confirm(csk->dst);
+	smp_mb();
+	cxgbi_sock_set_state(csk, CTP_ESTABLISHED);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_established);
+
+static void cxgbi_inform_iscsi_conn_closing(struct cxgbi_sock *csk)
+{
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, state %u, flags 0x%lx, conn 0x%p.\n",
+		csk, csk->state, csk->flags, csk->user_data);
+
+	if (csk->state != CTP_ESTABLISHED) {
+		read_lock_bh(&csk->callback_lock);
+		if (csk->user_data)
+			iscsi_conn_failure(csk->user_data,
+					ISCSI_ERR_CONN_FAILED);
+		read_unlock_bh(&csk->callback_lock);
+	}
+}
+
+void cxgbi_sock_closed(struct cxgbi_sock *csk)
+{
+	log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+		csk, (csk)->state, (csk)->flags, (csk)->tid);
+	cxgbi_sock_set_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED);
+	if (csk->state == CTP_ACTIVE_OPEN || csk->state == CTP_CLOSED)
+		return;
+	if (csk->saddr.sin_port)
+		sock_put_port(csk);
+	if (csk->dst)
+		dst_release(csk->dst);
+	csk->cdev->csk_release_offload_resources(csk);
+	cxgbi_sock_set_state(csk, CTP_CLOSED);
+	cxgbi_inform_iscsi_conn_closing(csk);
+	cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_closed);
+
+static void need_active_close(struct cxgbi_sock *csk)
+{
+	int data_lost;
+	int close_req = 0;
+
+	log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+		csk, (csk)->state, (csk)->flags, (csk)->tid);
+	spin_lock_bh(&csk->lock);
+	dst_confirm(csk->dst);
+	data_lost = skb_queue_len(&csk->receive_queue);
+	__skb_queue_purge(&csk->receive_queue);
+
+	if (csk->state == CTP_ACTIVE_OPEN)
+		cxgbi_sock_set_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED);
+	else if (csk->state == CTP_ESTABLISHED) {
+		close_req = 1;
+		cxgbi_sock_set_state(csk, CTP_ACTIVE_CLOSE);
+	} else if (csk->state == CTP_PASSIVE_CLOSE) {
+		close_req = 1;
+		cxgbi_sock_set_state(csk, CTP_CLOSE_WAIT_2);
+	}
+
+	if (close_req) {
+		if (data_lost)
+			csk->cdev->csk_send_abort_req(csk);
+		else
+			csk->cdev->csk_send_close_req(csk);
+	}
+
+	spin_unlock_bh(&csk->lock);
+}
+
+void cxgbi_sock_fail_act_open(struct cxgbi_sock *csk, int errno)
+{
+	pr_info("csk 0x%p,%u,%lx, %pI4:%u-%pI4:%u, err %d.\n",
+			csk, csk->state, csk->flags,
+			&csk->saddr.sin_addr.s_addr, csk->saddr.sin_port,
+			&csk->daddr.sin_addr.s_addr, csk->daddr.sin_port,
+			errno);
+
+	cxgbi_sock_set_state(csk, CTP_CONNECTING);
+	csk->err = errno;
+	cxgbi_sock_closed(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_fail_act_open);
+
+void cxgbi_sock_act_open_req_arp_failure(void *handle, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)skb->sk;
+
+	log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+		csk, (csk)->state, (csk)->flags, (csk)->tid);
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+	if (csk->state == CTP_ACTIVE_OPEN)
+		cxgbi_sock_fail_act_open(csk, -EHOSTUNREACH);
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+	__kfree_skb(skb);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_act_open_req_arp_failure);
+
+void cxgbi_sock_rcv_abort_rpl(struct cxgbi_sock *csk)
+{
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+	if (cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING)) {
+		if (!cxgbi_sock_flag(csk, CTPF_ABORT_RPL_RCVD))
+			cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_RCVD);
+		else {
+			cxgbi_sock_clear_flag(csk, CTPF_ABORT_RPL_RCVD);
+			cxgbi_sock_clear_flag(csk, CTPF_ABORT_RPL_PENDING);
+			if (cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD))
+				pr_err("csk 0x%p,%u,0x%lx,%u,ABT_RPL_RSS.\n",
+					csk, csk->state, csk->flags, csk->tid);
+			cxgbi_sock_closed(csk);
+		}
+	}
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_abort_rpl);
+
+void cxgbi_sock_rcv_peer_close(struct cxgbi_sock *csk)
+{
+	log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+		csk, (csk)->state, (csk)->flags, (csk)->tid);
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING))
+		goto done;
+
+	switch (csk->state) {
+	case CTP_ESTABLISHED:
+		cxgbi_sock_set_state(csk, CTP_PASSIVE_CLOSE);
+		break;
+	case CTP_ACTIVE_CLOSE:
+		cxgbi_sock_set_state(csk, CTP_CLOSE_WAIT_2);
+		break;
+	case CTP_CLOSE_WAIT_1:
+		cxgbi_sock_closed(csk);
+		break;
+	case CTP_ABORTING:
+		break;
+	default:
+		pr_err("csk 0x%p,%u,0x%lx,%u, bad state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+	}
+	cxgbi_inform_iscsi_conn_closing(csk);
+done:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_peer_close);
+
+void cxgbi_sock_rcv_close_conn_rpl(struct cxgbi_sock *csk, u32 snd_nxt)
+{
+	log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+		csk, (csk)->state, (csk)->flags, (csk)->tid);
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+
+	csk->snd_una = snd_nxt - 1;
+	if (cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING))
+		goto done;
+
+	switch (csk->state) {
+	case CTP_ACTIVE_CLOSE:
+		cxgbi_sock_set_state(csk, CTP_CLOSE_WAIT_1);
+		break;
+	case CTP_CLOSE_WAIT_1:
+	case CTP_CLOSE_WAIT_2:
+		cxgbi_sock_closed(csk);
+		break;
+	case CTP_ABORTING:
+		break;
+	default:
+		pr_err("csk 0x%p,%u,0x%lx,%u, bad state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+	}
+done:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_close_conn_rpl);
+
+void cxgbi_sock_rcv_wr_ack(struct cxgbi_sock *csk, unsigned int credits,
+			   unsigned int snd_una, int seq_chk)
+{
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+			"csk 0x%p,%u,0x%lx,%u, cr %u,%u+%u, snd_una %u,%d.\n",
+			csk, csk->state, csk->flags, csk->tid, credits,
+			csk->wr_cred, csk->wr_una_cred, snd_una, seq_chk);
+
+	spin_lock_bh(&csk->lock);
+
+	csk->wr_cred += credits;
+	if (csk->wr_una_cred > csk->wr_max_cred - csk->wr_cred)
+		csk->wr_una_cred = csk->wr_max_cred - csk->wr_cred;
+
+	while (credits) {
+		struct sk_buff *p = cxgbi_sock_peek_wr(csk);
+
+		if (unlikely(!p)) {
+			pr_err("csk 0x%p,%u,0x%lx,%u, cr %u,%u+%u, empty.\n",
+				csk, csk->state, csk->flags, csk->tid, credits,
+				csk->wr_cred, csk->wr_una_cred);
+			break;
+		}
+
+		if (unlikely(credits < p->csum)) {
+			pr_warn("csk 0x%p,%u,0x%lx,%u, cr %u,%u+%u, < %u.\n",
+				csk, csk->state, csk->flags, csk->tid,
+				credits, csk->wr_cred, csk->wr_una_cred,
+				p->csum);
+			p->csum -= credits;
+			break;
+		} else {
+			cxgbi_sock_dequeue_wr(csk);
+			credits -= p->csum;
+			kfree_skb(p);
+		}
+	}
+
+	cxgbi_sock_check_wr_invariants(csk);
+
+	if (seq_chk) {
+		if (unlikely(before(snd_una, csk->snd_una))) {
+			pr_warn("csk 0x%p,%u,0x%lx,%u, snd_una %u/%u.",
+				csk, csk->state, csk->flags, csk->tid, snd_una,
+				csk->snd_una);
+			goto done;
+		}
+
+		if (csk->snd_una != snd_una) {
+			csk->snd_una = snd_una;
+			dst_confirm(csk->dst);
+		}
+	}
+
+	if (skb_queue_len(&csk->write_queue)) {
+		if (csk->cdev->csk_push_tx_frames(csk, 0))
+			cxgbi_conn_tx_open(csk);
+	} else
+		cxgbi_conn_tx_open(csk);
+done:
+	spin_unlock_bh(&csk->lock);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_wr_ack);
+
+static unsigned int cxgbi_sock_find_best_mtu(struct cxgbi_sock *csk,
+					     unsigned short mtu)
+{
+	int i = 0;
+
+	while (i < csk->cdev->nmtus - 1 && csk->cdev->mtus[i + 1] <= mtu)
+		++i;
+
+	return i;
+}
+
+unsigned int cxgbi_sock_select_mss(struct cxgbi_sock *csk, unsigned int pmtu)
+{
+	unsigned int idx;
+	struct dst_entry *dst = csk->dst;
+
+	csk->advmss = dst_metric(dst, RTAX_ADVMSS);
+
+	if (csk->advmss > pmtu - 40)
+		csk->advmss = pmtu - 40;
+	if (csk->advmss < csk->cdev->mtus[0] - 40)
+		csk->advmss = csk->cdev->mtus[0] - 40;
+	idx = cxgbi_sock_find_best_mtu(csk, csk->advmss + 40);
+
+	return idx;
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_select_mss);
+
+void cxgbi_sock_skb_entail(struct cxgbi_sock *csk, struct sk_buff *skb)
+{
+	cxgbi_skcb_tcp_seq(skb) = csk->write_seq;
+	__skb_queue_tail(&csk->write_queue, skb);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_skb_entail);
+
+void cxgbi_sock_purge_wr_queue(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+
+	while ((skb = cxgbi_sock_dequeue_wr(csk)) != NULL)
+		kfree_skb(skb);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_purge_wr_queue);
+
+void cxgbi_sock_check_wr_invariants(const struct cxgbi_sock *csk)
+{
+	int pending = cxgbi_sock_count_pending_wrs(csk);
+
+	if (unlikely(csk->wr_cred + pending != csk->wr_max_cred))
+		pr_err("csk 0x%p, tid %u, credit %u + %u != %u.\n",
+			csk, csk->tid, csk->wr_cred, pending, csk->wr_max_cred);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_check_wr_invariants);
+
+static int cxgbi_sock_send_pdus(struct cxgbi_sock *csk, struct sk_buff *skb)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct sk_buff *next;
+	int err, copied = 0;
+
+	spin_lock_bh(&csk->lock);
+
+	if (csk->state != CTP_ESTABLISHED) {
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p,%u,0x%lx,%u, EAGAIN.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		err = -EAGAIN;
+		goto out_err;
+	}
+
+	if (csk->err) {
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p,%u,0x%lx,%u, EPIPE %d.\n",
+			csk, csk->state, csk->flags, csk->tid, csk->err);
+		err = -EPIPE;
+		goto out_err;
+	}
+
+	if (csk->write_seq - csk->snd_una >= cdev->snd_win) {
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p,%u,0x%lx,%u, FULL %u-%u >= %u.\n",
+			csk, csk->state, csk->flags, csk->tid, csk->write_seq,
+			csk->snd_una, cdev->snd_win);
+		err = -ENOBUFS;
+		goto out_err;
+	}
+
+	while (skb) {
+		int frags = skb_shinfo(skb)->nr_frags +
+				(skb->len != skb->data_len);
+
+		if (unlikely(skb_headroom(skb) < cdev->skb_tx_rsvd)) {
+			pr_err("csk 0x%p, skb head %u < %u.\n",
+				csk, skb_headroom(skb), cdev->skb_tx_rsvd);
+			err = -EINVAL;
+			goto out_err;
+		}
+
+		if (frags >= SKB_WR_LIST_SIZE) {
+			pr_err("csk 0x%p, frags %d, %u,%u >%u.\n",
+				csk, skb_shinfo(skb)->nr_frags, skb->len,
+				skb->data_len, (uint)(SKB_WR_LIST_SIZE));
+			err = -EINVAL;
+			goto out_err;
+		}
+
+		next = skb->next;
+		skb->next = NULL;
+		cxgbi_skcb_set_flag(skb, SKCBF_TX_NEED_HDR);
+		cxgbi_sock_skb_entail(csk, skb);
+		copied += skb->len;
+		csk->write_seq += skb->len +
+				cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
+		skb = next;
+	}
+done:
+	if (likely(skb_queue_len(&csk->write_queue)))
+		cdev->csk_push_tx_frames(csk, 1);
+	spin_unlock_bh(&csk->lock);
+	return copied;
+
+out_err:
+	if (copied == 0 && err == -EPIPE)
+		copied = csk->err ? csk->err : -EPIPE;
+	else
+		copied = err;
+	goto done;
+}
+
+/*
+ * Direct Data Placement -
+ * Directly place the iSCSI Data-In or Data-Out PDU's payload into pre-posted
+ * final destination host-memory buffers based on the Initiator Task Tag (ITT)
+ * in Data-In or Target Task Tag (TTT) in Data-Out PDUs.
+ * The host memory address is programmed into h/w in the format of pagepod
+ * entries.
+ * The location of the pagepod entry is encoded into ddp tag which is used as
+ * the base for ITT/TTT.
+ */
+
+static unsigned char ddp_page_order[DDP_PGIDX_MAX] = {0, 1, 2, 4};
+static unsigned char ddp_page_shift[DDP_PGIDX_MAX] = {12, 13, 14, 16};
+static unsigned char page_idx = DDP_PGIDX_MAX;
+
+static unsigned char sw_tag_idx_bits;
+static unsigned char sw_tag_age_bits;
+
+/*
+ * Direct-Data Placement page size adjustment
+ */
+static int ddp_adjust_page_table(void)
+{
+	int i;
+	unsigned int base_order, order;
+
+	if (PAGE_SIZE < (1UL << ddp_page_shift[0])) {
+		pr_info("PAGE_SIZE 0x%lx too small, min 0x%lx\n",
+			PAGE_SIZE, 1UL << ddp_page_shift[0]);
+		return -EINVAL;
+	}
+
+	base_order = get_order(1UL << ddp_page_shift[0]);
+	order = get_order(1UL << PAGE_SHIFT);
+
+	for (i = 0; i < DDP_PGIDX_MAX; i++) {
+		/* first is the kernel page size, then just doubling */
+		ddp_page_order[i] = order - base_order + i;
+		ddp_page_shift[i] = PAGE_SHIFT + i;
+	}
+	return 0;
+}
+
+static int ddp_find_page_index(unsigned long pgsz)
+{
+	int i;
+
+	for (i = 0; i < DDP_PGIDX_MAX; i++) {
+		if (pgsz == (1UL << ddp_page_shift[i]))
+			return i;
+	}
+	pr_info("ddp page size %lu not supported.\n", pgsz);
+	return DDP_PGIDX_MAX;
+}
+
+static void ddp_setup_host_page_size(void)
+{
+	if (page_idx == DDP_PGIDX_MAX) {
+		page_idx = ddp_find_page_index(PAGE_SIZE);
+
+		if (page_idx == DDP_PGIDX_MAX) {
+			pr_info("system PAGE %lu, update hw.\n", PAGE_SIZE);
+			if (ddp_adjust_page_table() < 0) {
+				pr_info("PAGE %lu, disable ddp.\n", PAGE_SIZE);
+				return;
+			}
+			page_idx = ddp_find_page_index(PAGE_SIZE);
+		}
+		pr_info("system PAGE %lu, ddp idx %u.\n", PAGE_SIZE, page_idx);
+	}
+}
+
+void cxgbi_ddp_page_size_factor(int *pgsz_factor)
+{
+	int i;
+
+	for (i = 0; i < DDP_PGIDX_MAX; i++)
+		pgsz_factor[i] = ddp_page_order[i];
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_page_size_factor);
+
+/*
+ * DDP setup & teardown
+ */
+
+void cxgbi_ddp_ppod_set(struct cxgbi_pagepod *ppod,
+			struct cxgbi_pagepod_hdr *hdr,
+			struct cxgbi_gather_list *gl, unsigned int gidx)
+{
+	int i;
+
+	memcpy(ppod, hdr, sizeof(*hdr));
+	for (i = 0; i < (PPOD_PAGES_MAX + 1); i++, gidx++) {
+		ppod->addr[i] = gidx < gl->nelem ?
+				cpu_to_be64(gl->phys_addr[gidx]) : 0ULL;
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_ppod_set);
+
+void cxgbi_ddp_ppod_clear(struct cxgbi_pagepod *ppod)
+{
+	memset(ppod, 0, sizeof(*ppod));
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_ppod_clear);
+
+static inline int ddp_find_unused_entries(struct cxgbi_ddp_info *ddp,
+					unsigned int start, unsigned int max,
+					unsigned int count,
+					struct cxgbi_gather_list *gl)
+{
+	unsigned int i, j, k;
+
+	/*  not enough entries */
+	if ((max - start) < count) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"NOT enough entries %u+%u < %u.\n", start, count, max);
+		return -EBUSY;
+	}
+
+	max -= count;
+	spin_lock(&ddp->map_lock);
+	for (i = start; i < max;) {
+		for (j = 0, k = i; j < count; j++, k++) {
+			if (ddp->gl_map[k])
+				break;
+		}
+		if (j == count) {
+			for (j = 0, k = i; j < count; j++, k++)
+				ddp->gl_map[k] = gl;
+			spin_unlock(&ddp->map_lock);
+			return i;
+		}
+		i += j + 1;
+	}
+	spin_unlock(&ddp->map_lock);
+	log_debug(1 << CXGBI_DBG_DDP,
+		"NO suitable entries %u available.\n", count);
+	return -EBUSY;
+}
+
+static inline void ddp_unmark_entries(struct cxgbi_ddp_info *ddp,
+						int start, int count)
+{
+	spin_lock(&ddp->map_lock);
+	memset(&ddp->gl_map[start], 0,
+		count * sizeof(struct cxgbi_gather_list *));
+	spin_unlock(&ddp->map_lock);
+}
+
+static inline void ddp_gl_unmap(struct pci_dev *pdev,
+					struct cxgbi_gather_list *gl)
+{
+	int i;
+
+	for (i = 0; i < gl->nelem; i++)
+		dma_unmap_page(&pdev->dev, gl->phys_addr[i], PAGE_SIZE,
+				PCI_DMA_FROMDEVICE);
+}
+
+static inline int ddp_gl_map(struct pci_dev *pdev,
+				    struct cxgbi_gather_list *gl)
+{
+	int i;
+
+	for (i = 0; i < gl->nelem; i++) {
+		gl->phys_addr[i] = dma_map_page(&pdev->dev, gl->pages[i], 0,
+						PAGE_SIZE,
+						PCI_DMA_FROMDEVICE);
+		if (unlikely(dma_mapping_error(&pdev->dev, gl->phys_addr[i]))) {
+			log_debug(1 << CXGBI_DBG_DDP,
+				"page %d 0x%p, 0x%p dma mapping err.\n",
+				i, gl->pages[i], pdev);
+			goto unmap;
+		}
+	}
+	return i;
+unmap:
+	if (i) {
+		unsigned int nelem = gl->nelem;
+
+		gl->nelem = i;
+		ddp_gl_unmap(pdev, gl);
+		gl->nelem = nelem;
+	}
+	return -EINVAL;
+}
+
+static void ddp_release_gl(struct cxgbi_gather_list *gl,
+				  struct pci_dev *pdev)
+{
+	ddp_gl_unmap(pdev, gl);
+	kfree(gl);
+}
+
+static struct cxgbi_gather_list *ddp_make_gl(unsigned int xferlen,
+						    struct scatterlist *sgl,
+						    unsigned int sgcnt,
+						    struct pci_dev *pdev,
+						    gfp_t gfp)
+{
+	struct cxgbi_gather_list *gl;
+	struct scatterlist *sg = sgl;
+	struct page *sgpage = sg_page(sg);
+	unsigned int sglen = sg->length;
+	unsigned int sgoffset = sg->offset;
+	unsigned int npages = (xferlen + sgoffset + PAGE_SIZE - 1) >>
+				PAGE_SHIFT;
+	int i = 1, j = 0;
+
+	if (xferlen < DDP_THRESHOLD) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"xfer %u < threshold %u, no ddp.\n",
+			xferlen, DDP_THRESHOLD);
+		return NULL;
+	}
+
+	gl = kzalloc(sizeof(struct cxgbi_gather_list) +
+		     npages * (sizeof(dma_addr_t) +
+		     sizeof(struct page *)), gfp);
+	if (!gl) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"xfer %u, %u pages, OOM.\n", xferlen, npages);
+		return NULL;
+	}
+
+	 log_debug(1 << CXGBI_DBG_DDP,
+		"xfer %u, sgl %u, gl max %u.\n", xferlen, sgcnt, npages);
+
+	gl->pages = (struct page **)&gl->phys_addr[npages];
+	gl->nelem = npages;
+	gl->length = xferlen;
+	gl->offset = sgoffset;
+	gl->pages[0] = sgpage;
+
+	for (i = 1, sg = sg_next(sgl), j = 0; i < sgcnt;
+		i++, sg = sg_next(sg)) {
+		struct page *page = sg_page(sg);
+
+		if (sgpage == page && sg->offset == sgoffset + sglen)
+			sglen += sg->length;
+		else {
+			/*  make sure the sgl is fit for ddp:
+			 *  each has the same page size, and
+			 *  all of the middle pages are used completely
+			 */
+			if ((j && sgoffset) || ((i != sgcnt - 1) &&
+			    ((sglen + sgoffset) & ~PAGE_MASK))) {
+				log_debug(1 << CXGBI_DBG_DDP,
+					"page %d/%u, %u + %u.\n",
+					i, sgcnt, sgoffset, sglen);
+				goto error_out;
+			}
+
+			j++;
+			if (j == gl->nelem || sg->offset) {
+				log_debug(1 << CXGBI_DBG_DDP,
+					"page %d/%u, offset %u.\n",
+					j, gl->nelem, sg->offset);
+				goto error_out;
+			}
+			gl->pages[j] = page;
+			sglen = sg->length;
+			sgoffset = sg->offset;
+			sgpage = page;
+		}
+	}
+	gl->nelem = ++j;
+
+	if (ddp_gl_map(pdev, gl) < 0)
+		goto error_out;
+
+	return gl;
+
+error_out:
+	kfree(gl);
+	return NULL;
+}
+
+static void ddp_tag_release(struct cxgbi_hba *chba, u32 tag)
+{
+	struct cxgbi_device *cdev = chba->cdev;
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	u32 idx;
+
+	idx = (tag >> PPOD_IDX_SHIFT) & ddp->idx_mask;
+	if (idx < ddp->nppods) {
+		struct cxgbi_gather_list *gl = ddp->gl_map[idx];
+		unsigned int npods;
+
+		if (!gl || !gl->nelem) {
+			pr_warn("tag 0x%x, idx %u, gl 0x%p, %u.\n",
+				tag, idx, gl, gl ? gl->nelem : 0);
+			return;
+		}
+		npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
+		log_debug(1 << CXGBI_DBG_DDP,
+			"tag 0x%x, release idx %u, npods %u.\n",
+			tag, idx, npods);
+		cdev->csk_ddp_clear(chba, tag, idx, npods);
+		ddp_unmark_entries(ddp, idx, npods);
+		ddp_release_gl(gl, ddp->pdev);
+	} else
+		pr_warn("tag 0x%x, idx %u > max %u.\n", tag, idx, ddp->nppods);
+}
+
+static int ddp_tag_reserve(struct cxgbi_sock *csk, unsigned int tid,
+			   u32 sw_tag, u32 *tagp, struct cxgbi_gather_list *gl,
+			   gfp_t gfp)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	struct cxgbi_tag_format *tformat = &cdev->tag_format;
+	struct cxgbi_pagepod_hdr hdr;
+	unsigned int npods;
+	int idx = -1;
+	int err = -ENOMEM;
+	u32 tag;
+
+	npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
+	if (ddp->idx_last == ddp->nppods)
+		idx = ddp_find_unused_entries(ddp, 0, ddp->nppods,
+							npods, gl);
+	else {
+		idx = ddp_find_unused_entries(ddp, ddp->idx_last + 1,
+							ddp->nppods, npods,
+							gl);
+		if (idx < 0 && ddp->idx_last >= npods) {
+			idx = ddp_find_unused_entries(ddp, 0,
+				min(ddp->idx_last + npods, ddp->nppods),
+							npods, gl);
+		}
+	}
+	if (idx < 0) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"xferlen %u, gl %u, npods %u NO DDP.\n",
+			gl->length, gl->nelem, npods);
+		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;
+
+	hdr.rsvd = 0;
+	hdr.vld_tid = htonl(PPOD_VALID_FLAG | PPOD_TID(tid));
+	hdr.pgsz_tag_clr = htonl(tag & ddp->rsvd_tag_mask);
+	hdr.max_offset = htonl(gl->length);
+	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);
+		goto unmark_entries;
+	}
+
+	ddp->idx_last = idx;
+	log_debug(1 << CXGBI_DBG_DDP,
+		"xfer %u, gl %u,%u, tid 0x%x, tag 0x%x->0x%x(%u,%u).\n",
+		gl->length, gl->nelem, gl->offset, tid, sw_tag, tag, idx,
+		npods);
+	*tagp = tag;
+	return 0;
+
+unmark_entries:
+	ddp_unmark_entries(ddp, idx, npods);
+	return err;
+}
+
+int cxgbi_ddp_reserve(struct cxgbi_sock *csk, unsigned int *tagp,
+			unsigned int sw_tag, unsigned int xferlen,
+			struct scatterlist *sgl, unsigned int sgcnt, gfp_t gfp)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgbi_tag_format *tformat = &cdev->tag_format;
+	struct cxgbi_gather_list *gl;
+	int err;
+
+	if (page_idx >= DDP_PGIDX_MAX || !cdev->ddp ||
+	    xferlen < DDP_THRESHOLD) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"pgidx %u, xfer %u, NO ddp.\n", page_idx, xferlen);
+		return -EINVAL;
+	}
+
+	if (!cxgbi_sw_tag_usable(tformat, sw_tag)) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"sw_tag 0x%x NOT usable.\n", sw_tag);
+		return -EINVAL;
+	}
+
+	gl = ddp_make_gl(xferlen, sgl, sgcnt, cdev->pdev, gfp);
+	if (!gl)
+		return -ENOMEM;
+
+	err = ddp_tag_reserve(csk, csk->tid, sw_tag, tagp, gl, gfp);
+	if (err < 0)
+		ddp_release_gl(gl, cdev->pdev);
+
+	return err;
+}
+
+static void ddp_destroy(struct kref *kref)
+{
+	struct cxgbi_ddp_info *ddp = container_of(kref,
+						struct cxgbi_ddp_info,
+						refcnt);
+	struct cxgbi_device *cdev = ddp->cdev;
+	int i = 0;
+
+	pr_info("kref 0, destroy ddp 0x%p, cdev 0x%p.\n", ddp, cdev);
+
+	while (i < ddp->nppods) {
+		struct cxgbi_gather_list *gl = ddp->gl_map[i];
+
+		if (gl) {
+			int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
+					>> 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++;
+	}
+	cxgbi_free_big_mem(ddp);
+}
+
+int cxgbi_ddp_cleanup(struct cxgbi_device *cdev)
+{
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"cdev 0x%p, release ddp 0x%p.\n", cdev, ddp);
+	cdev->ddp = NULL;
+	if (ddp)
+		return kref_put(&ddp->refcnt, ddp_destroy);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_cleanup);
+
+int cxgbi_ddp_init(struct cxgbi_device *cdev,
+		   unsigned int llimit, unsigned int ulimit,
+		   unsigned int max_txsz, unsigned int max_rxsz)
+{
+	struct cxgbi_ddp_info *ddp;
+	unsigned int ppmax, bits;
+
+	ppmax = (ulimit - llimit + 1) >> PPOD_SIZE_SHIFT;
+	bits = __ilog2_u32(ppmax) + 1;
+	if (bits > PPOD_IDX_MAX_SIZE)
+		bits = PPOD_IDX_MAX_SIZE;
+	ppmax = (1 << (bits - 1)) - 1;
+
+	ddp = cxgbi_alloc_big_mem(sizeof(struct cxgbi_ddp_info) +
+				ppmax * (sizeof(struct cxgbi_gather_list *) +
+					 sizeof(struct sk_buff *)),
+				GFP_KERNEL);
+	if (!ddp) {
+		pr_warn("cdev 0x%p, ddp ppmax %u OOM.\n", cdev, ppmax);
+		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);
+	kref_init(&ddp->refcnt);
+
+	ddp->cdev = cdev;
+	ddp->pdev = cdev->pdev;
+	ddp->llimit = llimit;
+	ddp->ulimit = ulimit;
+	ddp->max_txsz = min_t(unsigned int, max_txsz, ULP2_MAX_PKT_SIZE);
+	ddp->max_rxsz = min_t(unsigned int, max_rxsz, ULP2_MAX_PKT_SIZE);
+	ddp->nppods = ppmax;
+	ddp->idx_last = ppmax;
+	ddp->idx_bits = bits;
+	ddp->idx_mask = (1 << bits) - 1;
+	ddp->rsvd_tag_mask = (1 << (bits + PPOD_IDX_SHIFT)) - 1;
+
+	cdev->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
+	cdev->tag_format.rsvd_bits = ddp->idx_bits;
+	cdev->tag_format.rsvd_shift = PPOD_IDX_SHIFT;
+	cdev->tag_format.rsvd_mask = (1 << cdev->tag_format.rsvd_bits) - 1;
+
+	pr_info("%s tag format, sw %u, rsvd %u,%u, mask 0x%x.\n",
+		cdev->ports[0]->name, cdev->tag_format.sw_bits,
+		cdev->tag_format.rsvd_bits, cdev->tag_format.rsvd_shift,
+		cdev->tag_format.rsvd_mask);
+
+	cdev->tx_max_size = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+				ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
+	cdev->rx_max_size = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+				ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"%s max payload size: %u/%u, %u/%u.\n",
+		cdev->ports[0]->name, cdev->tx_max_size, ddp->max_txsz,
+		cdev->rx_max_size, ddp->max_rxsz);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_init);
+
+/*
+ * APIs interacting with open-iscsi libraries
+ */
+
+static unsigned char padding[4];
+
+static void task_release_itt(struct iscsi_task *task, itt_t hdr_itt)
+{
+	struct scsi_cmnd *sc = task->sc;
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_hba *chba = cconn->chba;
+	struct cxgbi_tag_format *tformat = &chba->cdev->tag_format;
+	u32 tag = ntohl((__force u32)hdr_itt);
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		   "cdev 0x%p, release tag 0x%x.\n", chba->cdev, tag);
+	if (sc &&
+	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) &&
+	    cxgbi_is_ddp_tag(tformat, tag))
+		ddp_tag_release(chba, tag);
+}
+
+static int task_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt)
+{
+	struct scsi_cmnd *sc = task->sc;
+	struct iscsi_conn *conn = task->conn;
+	struct iscsi_session *sess = conn->session;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_hba *chba = cconn->chba;
+	struct cxgbi_tag_format *tformat = &chba->cdev->tag_format;
+	u32 sw_tag = (sess->age << cconn->task_idx_bits) | task->itt;
+	u32 tag = 0;
+	int err = -EINVAL;
+
+	if (sc &&
+	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE)) {
+		err = cxgbi_ddp_reserve(cconn->cep->csk, &tag, sw_tag,
+					scsi_in(sc)->length,
+					scsi_in(sc)->table.sgl,
+					scsi_in(sc)->table.nents,
+					GFP_ATOMIC);
+		if (err < 0)
+			log_debug(1 << CXGBI_DBG_DDP,
+				"csk 0x%p, R task 0x%p, %u,%u, no ddp.\n",
+				cconn->cep->csk, task, scsi_in(sc)->length,
+				scsi_in(sc)->table.nents);
+	}
+
+	if (err < 0)
+		tag = cxgbi_set_non_ddp_tag(tformat, sw_tag);
+	/*  the itt need to sent in big-endian order */
+	*hdr_itt = (__force itt_t)htonl(tag);
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"cdev 0x%p, task 0x%p, 0x%x(0x%x,0x%x)->0x%x/0x%x.\n",
+		chba->cdev, task, sw_tag, task->itt, sess->age, tag, *hdr_itt);
+	return 0;
+}
+
+void cxgbi_parse_pdu_itt(struct iscsi_conn *conn, itt_t itt, int *idx, int *age)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	u32 tag = ntohl((__force u32) itt);
+	u32 sw_bits;
+
+	sw_bits = cxgbi_tag_nonrsvd_bits(&cdev->tag_format, tag);
+	if (idx)
+		*idx = sw_bits & ((1 << cconn->task_idx_bits) - 1);
+	if (age)
+		*age = (sw_bits >> cconn->task_idx_bits) & ISCSI_AGE_MASK;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"cdev 0x%p, tag 0x%x/0x%x, -> 0x%x(0x%x,0x%x).\n",
+		cdev, tag, itt, sw_bits, idx ? *idx : 0xFFFFF,
+		age ? *age : 0xFF);
+}
+EXPORT_SYMBOL_GPL(cxgbi_parse_pdu_itt);
+
+void cxgbi_conn_tx_open(struct cxgbi_sock *csk)
+{
+	struct iscsi_conn *conn = csk->user_data;
+
+	if (conn) {
+		log_debug(1 << CXGBI_DBG_SOCK,
+			"csk 0x%p, cid %d.\n", csk, conn->id);
+		iscsi_conn_queue_work(conn);
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_tx_open);
+
+/*
+ * pdu receive, interact with libiscsi_tcp
+ */
+static inline int read_pdu_skb(struct iscsi_conn *conn,
+			       struct sk_buff *skb,
+			       unsigned int offset,
+			       int offloaded)
+{
+	int status = 0;
+	int bytes_read;
+
+	bytes_read = iscsi_tcp_recv_skb(conn, skb, offset, offloaded, &status);
+	switch (status) {
+	case ISCSI_TCP_CONN_ERR:
+		pr_info("skb 0x%p, off %u, %d, TCP_ERR.\n",
+			  skb, offset, offloaded);
+		return -EIO;
+	case ISCSI_TCP_SUSPENDED:
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"skb 0x%p, off %u, %d, TCP_SUSPEND, rc %d.\n",
+			skb, offset, offloaded, bytes_read);
+		/* no transfer - just have caller flush queue */
+		return bytes_read;
+	case ISCSI_TCP_SKB_DONE:
+		pr_info("skb 0x%p, off %u, %d, TCP_SKB_DONE.\n",
+			skb, offset, offloaded);
+		/*
+		 * pdus should always fit in the skb and we should get
+		 * segment done notifcation.
+		 */
+		iscsi_conn_printk(KERN_ERR, conn, "Invalid pdu or skb.");
+		return -EFAULT;
+	case ISCSI_TCP_SEGMENT_DONE:
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"skb 0x%p, off %u, %d, TCP_SEG_DONE, rc %d.\n",
+			skb, offset, offloaded, bytes_read);
+		return bytes_read;
+	default:
+		pr_info("skb 0x%p, off %u, %d, invalid status %d.\n",
+			skb, offset, offloaded, status);
+		return -EINVAL;
+	}
+}
+
+static int skb_read_pdu_bhs(struct iscsi_conn *conn, struct sk_buff *skb)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+
+	log_debug(1 << CXGBI_DBG_PDU_RX,
+		"conn 0x%p, skb 0x%p, len %u, flag 0x%lx.\n",
+		conn, skb, skb->len, cxgbi_skcb_flags(skb));
+
+	if (!iscsi_tcp_recv_segment_is_hdr(tcp_conn)) {
+		pr_info("conn 0x%p, skb 0x%p, not hdr.\n", conn, skb);
+		iscsi_conn_failure(conn, ISCSI_ERR_PROTO);
+		return -EIO;
+	}
+
+	if (conn->hdrdgst_en &&
+	    cxgbi_skcb_test_flag(skb, SKCBF_RX_HCRC_ERR)) {
+		pr_info("conn 0x%p, skb 0x%p, hcrc.\n", conn, skb);
+		iscsi_conn_failure(conn, ISCSI_ERR_HDR_DGST);
+		return -EIO;
+	}
+
+	return read_pdu_skb(conn, skb, 0, 0);
+}
+
+static int skb_read_pdu_data(struct iscsi_conn *conn, struct sk_buff *lskb,
+			     struct sk_buff *skb, unsigned int offset)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	bool offloaded = 0;
+	int opcode = tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK;
+
+	log_debug(1 << CXGBI_DBG_PDU_RX,
+		"conn 0x%p, skb 0x%p, len %u, flag 0x%lx.\n",
+		conn, skb, skb->len, cxgbi_skcb_flags(skb));
+
+	if (conn->datadgst_en &&
+	    cxgbi_skcb_test_flag(lskb, SKCBF_RX_DCRC_ERR)) {
+		pr_info("conn 0x%p, skb 0x%p, dcrc 0x%lx.\n",
+			conn, lskb, cxgbi_skcb_flags(lskb));
+		iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
+		return -EIO;
+	}
+
+	if (iscsi_tcp_recv_segment_is_hdr(tcp_conn))
+		return 0;
+
+	/* coalesced, add header digest length */
+	if (lskb == skb && conn->hdrdgst_en)
+		offset += ISCSI_DIGEST_SIZE;
+
+	if (cxgbi_skcb_test_flag(lskb, SKCBF_RX_DATA_DDPD))
+		offloaded = 1;
+
+	if (opcode == ISCSI_OP_SCSI_DATA_IN)
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"skb 0x%p, op 0x%x, itt 0x%x, %u %s ddp'ed.\n",
+			skb, opcode, ntohl(tcp_conn->in.hdr->itt),
+			tcp_conn->in.datalen, offloaded ? "is" : "not");
+
+	return read_pdu_skb(conn, skb, offset, offloaded);
+}
+
+static void csk_return_rx_credits(struct cxgbi_sock *csk, int copied)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	int must_send;
+	u32 credits;
+
+	log_debug(1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lu,%u, seq %u, wup %u, thre %u, %u.\n",
+		csk, csk->state, csk->flags, csk->tid, csk->copied_seq,
+		csk->rcv_wup, cdev->rx_credit_thres,
+		cdev->rcv_win);
+
+	if (csk->state != CTP_ESTABLISHED)
+		return;
+
+	credits = csk->copied_seq - csk->rcv_wup;
+	if (unlikely(!credits))
+		return;
+	if (unlikely(cdev->rx_credit_thres == 0))
+		return;
+
+	must_send = credits + 16384 >= cdev->rcv_win;
+	if (must_send || credits >= cdev->rx_credit_thres)
+		csk->rcv_wup += cdev->csk_send_rx_credits(csk, credits);
+}
+
+void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct iscsi_conn *conn = csk->user_data;
+	struct sk_buff *skb;
+	unsigned int read = 0;
+	int err = 0;
+
+	log_debug(1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p, conn 0x%p.\n", csk, conn);
+
+	if (unlikely(!conn || conn->suspend_rx)) {
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p, conn 0x%p, id %d, suspend_rx %lu!\n",
+			csk, conn, conn ? conn->id : 0xFF,
+			conn ? conn->suspend_rx : 0xFF);
+		return;
+	}
+
+	while (!err) {
+		skb = skb_peek(&csk->receive_queue);
+		if (!skb ||
+		    !(cxgbi_skcb_test_flag(skb, SKCBF_RX_STATUS))) {
+			if (skb)
+				log_debug(1 << CXGBI_DBG_PDU_RX,
+					"skb 0x%p, NOT ready 0x%lx.\n",
+					skb, cxgbi_skcb_flags(skb));
+			break;
+		}
+		__skb_unlink(skb, &csk->receive_queue);
+
+		read += cxgbi_skcb_rx_pdulen(skb);
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p, skb 0x%p,%u,f 0x%lx, pdu len %u.\n",
+			csk, skb, skb->len, cxgbi_skcb_flags(skb),
+			cxgbi_skcb_rx_pdulen(skb));
+
+		if (cxgbi_skcb_test_flag(skb, SKCBF_RX_COALESCED)) {
+			err = skb_read_pdu_bhs(conn, skb);
+			if (err < 0) {
+				pr_err("coalesced bhs, csk 0x%p, skb 0x%p,%u, "
+					"f 0x%lx, plen %u.\n",
+					csk, skb, skb->len,
+					cxgbi_skcb_flags(skb),
+					cxgbi_skcb_rx_pdulen(skb));
+				goto skb_done;
+			}
+			err = skb_read_pdu_data(conn, skb, skb,
+						err + cdev->skb_rx_extra);
+			if (err < 0)
+				pr_err("coalesced data, csk 0x%p, skb 0x%p,%u, "
+					"f 0x%lx, plen %u.\n",
+					csk, skb, skb->len,
+					cxgbi_skcb_flags(skb),
+					cxgbi_skcb_rx_pdulen(skb));
+		} else {
+			err = skb_read_pdu_bhs(conn, skb);
+			if (err < 0) {
+				pr_err("bhs, csk 0x%p, skb 0x%p,%u, "
+					"f 0x%lx, plen %u.\n",
+					csk, skb, skb->len,
+					cxgbi_skcb_flags(skb),
+					cxgbi_skcb_rx_pdulen(skb));
+				goto skb_done;
+			}
+
+			if (cxgbi_skcb_test_flag(skb, SKCBF_RX_DATA)) {
+				struct sk_buff *dskb;
+
+				dskb = skb_peek(&csk->receive_queue);
+				if (!dskb) {
+					pr_err("csk 0x%p, skb 0x%p,%u, f 0x%lx,"
+						" plen %u, NO data.\n",
+						csk, skb, skb->len,
+						cxgbi_skcb_flags(skb),
+						cxgbi_skcb_rx_pdulen(skb));
+					err = -EIO;
+					goto skb_done;
+				}
+				__skb_unlink(dskb, &csk->receive_queue);
+
+				err = skb_read_pdu_data(conn, skb, dskb, 0);
+				if (err < 0)
+					pr_err("data, csk 0x%p, skb 0x%p,%u, "
+						"f 0x%lx, plen %u, dskb 0x%p,"
+						"%u.\n",
+						csk, skb, skb->len,
+						cxgbi_skcb_flags(skb),
+						cxgbi_skcb_rx_pdulen(skb),
+						dskb, dskb->len);
+				__kfree_skb(dskb);
+			} else
+				err = skb_read_pdu_data(conn, skb, skb, 0);
+		}
+skb_done:
+		__kfree_skb(skb);
+
+		if (err < 0)
+			break;
+	}
+
+	log_debug(1 << CXGBI_DBG_PDU_RX, "csk 0x%p, read %u.\n", csk, read);
+	if (read) {
+		csk->copied_seq += read;
+		csk_return_rx_credits(csk, read);
+		conn->rxdata_octets += read;
+	}
+
+	if (err < 0) {
+		pr_info("csk 0x%p, 0x%p, rx failed %d, read %u.\n",
+			csk, conn, err, read);
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_pdu_ready);
+
+static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
+				unsigned int offset, unsigned int *off,
+				struct scatterlist **sgp)
+{
+	int i;
+	struct scatterlist *sg;
+
+	for_each_sg(sgl, sg, sgcnt, i) {
+		if (offset < sg->length) {
+			*off = offset;
+			*sgp = sg;
+			return 0;
+		}
+		offset -= sg->length;
+	}
+	return -EFAULT;
+}
+
+static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
+				unsigned int dlen, skb_frag_t *frags,
+				int frag_max)
+{
+	unsigned int datalen = dlen;
+	unsigned int sglen = sg->length - sgoffset;
+	struct page *page = sg_page(sg);
+	int i;
+
+	i = 0;
+	do {
+		unsigned int copy;
+
+		if (!sglen) {
+			sg = sg_next(sg);
+			if (!sg) {
+				pr_warn("sg %d NULL, len %u/%u.\n",
+					i, datalen, dlen);
+				return -EINVAL;
+			}
+			sgoffset = 0;
+			sglen = sg->length;
+			page = sg_page(sg);
+
+		}
+		copy = min(datalen, sglen);
+		if (i && page == frags[i - 1].page &&
+		    sgoffset + sg->offset ==
+			frags[i - 1].page_offset + frags[i - 1].size) {
+			frags[i - 1].size += copy;
+		} else {
+			if (i >= frag_max) {
+				pr_warn("too many pages %u, dlen %u.\n",
+					frag_max, dlen);
+				return -EINVAL;
+			}
+
+			frags[i].page = page;
+			frags[i].page_offset = sg->offset + sgoffset;
+			frags[i].size = copy;
+			i++;
+		}
+		datalen -= copy;
+		sgoffset += copy;
+		sglen -= copy;
+	} while (datalen);
+
+	return i;
+}
+
+int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
+{
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct iscsi_conn *conn = task->conn;
+	struct iscsi_tcp_task *tcp_task = task->dd_data;
+	struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+	struct scsi_cmnd *sc = task->sc;
+	int headroom = SKB_TX_ISCSI_PDU_HEADER_MAX;
+
+	tcp_task->dd_data = tdata;
+	task->hdr = NULL;
+
+	if (SKB_MAX_HEAD(cdev->skb_tx_rsvd) > (512 * MAX_SKB_FRAGS) &&
+	    (opcode == ISCSI_OP_SCSI_DATA_OUT ||
+	     (opcode == ISCSI_OP_SCSI_CMD &&
+	      (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE))))
+		/* data could goes into skb head */
+		headroom += min_t(unsigned int,
+				SKB_MAX_HEAD(cdev->skb_tx_rsvd),
+				conn->max_xmit_dlength);
+
+	tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC);
+	if (!tdata->skb) {
+		pr_warn("alloc skb %u+%u, opcode 0x%x failed.\n",
+			cdev->skb_tx_rsvd, headroom, opcode);
+		return -ENOMEM;
+	}
+
+	skb_reserve(tdata->skb, cdev->skb_tx_rsvd);
+	task->hdr = (struct iscsi_hdr *)tdata->skb->data;
+	task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; /* BHS + AHS */
+
+	/* data_out uses scsi_cmd's itt */
+	if (opcode != ISCSI_OP_SCSI_DATA_OUT)
+		task_reserve_itt(task, &task->hdr->itt);
+
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+		"task 0x%p, op 0x%x, skb 0x%p,%u+%u/%u, itt 0x%x.\n",
+		task, opcode, tdata->skb, cdev->skb_tx_rsvd, headroom,
+		conn->max_xmit_dlength, ntohl(task->hdr->itt));
+
+	return 0;
+}
+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)
+		submode |= 1;
+	if (dcrc)
+		submode |= 2;
+	cxgbi_skcb_ulp_mode(skb) = (ULP2_MODE_ISCSI << 4) | submode;
+}
+
+int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
+			      unsigned int count)
+{
+	struct iscsi_conn *conn = task->conn;
+	struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+	struct sk_buff *skb = tdata->skb;
+	unsigned int datalen = count;
+	int i, padlen = iscsi_padding(count);
+	struct page *pg;
+
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+		"task 0x%p,0x%p, skb 0x%p, 0x%x,0x%x,0x%x, %u+%u.\n",
+		task, task->sc, skb, (*skb->data) & ISCSI_OPCODE_MASK,
+		ntohl(task->cmdsn), ntohl(task->hdr->itt), offset, count);
+
+	skb_put(skb, task->hdr_len);
+	tx_skb_setmode(skb, conn->hdrdgst_en, datalen ? conn->datadgst_en : 0);
+	if (!count)
+		return 0;
+
+	if (task->sc) {
+		struct scsi_data_buffer *sdb = scsi_out(task->sc);
+		struct scatterlist *sg = NULL;
+		int err;
+
+		tdata->offset = offset;
+		tdata->count = count;
+		err = sgl_seek_offset(
+					sdb->table.sgl, sdb->table.nents,
+					tdata->offset, &tdata->sgoffset, &sg);
+		if (err < 0) {
+			pr_warn("tpdu, sgl %u, bad offset %u/%u.\n",
+				sdb->table.nents, tdata->offset, sdb->length);
+			return err;
+		}
+		err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count,
+					tdata->frags, MAX_PDU_FRAGS);
+		if (err < 0) {
+			pr_warn("tpdu, sgl %u, bad offset %u + %u.\n",
+				sdb->table.nents, tdata->offset, tdata->count);
+			return err;
+		}
+		tdata->nr_frags = err;
+
+		if (tdata->nr_frags > MAX_SKB_FRAGS ||
+		    (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
+			char *dst = skb->data + task->hdr_len;
+			skb_frag_t *frag = tdata->frags;
+
+			/* data fits in the skb's headroom */
+			for (i = 0; i < tdata->nr_frags; i++, frag++) {
+				char *src = kmap_atomic(frag->page,
+							KM_SOFTIRQ0);
+
+				memcpy(dst, src+frag->page_offset, frag->size);
+				dst += frag->size;
+				kunmap_atomic(src, KM_SOFTIRQ0);
+			}
+			if (padlen) {
+				memset(dst, 0, padlen);
+				padlen = 0;
+			}
+			skb_put(skb, count + padlen);
+		} else {
+			/* data fit into frag_list */
+			for (i = 0; i < tdata->nr_frags; i++)
+				get_page(tdata->frags[i].page);
+
+			memcpy(skb_shinfo(skb)->frags, tdata->frags,
+				sizeof(skb_frag_t) * tdata->nr_frags);
+			skb_shinfo(skb)->nr_frags = tdata->nr_frags;
+			skb->len += count;
+			skb->data_len += count;
+			skb->truesize += count;
+		}
+
+	} else {
+		pg = virt_to_page(task->data);
+
+		get_page(pg);
+		skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data),
+					count);
+		skb->len += count;
+		skb->data_len += count;
+		skb->truesize += count;
+	}
+
+	if (padlen) {
+		i = skb_shinfo(skb)->nr_frags;
+		skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+				virt_to_page(padding), offset_in_page(padding),
+				padlen);
+
+		skb->data_len += padlen;
+		skb->truesize += padlen;
+		skb->len += padlen;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_init_pdu);
+
+int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
+{
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+	struct sk_buff *skb = tdata->skb;
+	unsigned int datalen;
+	int err;
+
+	if (!skb) {
+		log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+			"task 0x%p, skb NULL.\n", task);
+		return 0;
+	}
+
+	datalen = skb->data_len;
+	tdata->skb = NULL;
+	err = cxgbi_sock_send_pdus(cconn->cep->csk, skb);
+	if (err > 0) {
+		int pdulen = err;
+
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"task 0x%p,0x%p, skb 0x%p, len %u/%u, rv %d.\n",
+			task, task->sc, skb, skb->len, skb->data_len, err);
+
+		if (task->conn->hdrdgst_en)
+			pdulen += ISCSI_DIGEST_SIZE;
+
+		if (datalen && task->conn->datadgst_en)
+			pdulen += ISCSI_DIGEST_SIZE;
+
+		task->conn->txdata_octets += pdulen;
+		return 0;
+	}
+
+	if (err == -EAGAIN || err == -ENOBUFS) {
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n",
+			task, skb, skb->len, skb->data_len, err);
+		/* reset skb to send when we are called again */
+		tdata->skb = skb;
+		return err;
+	}
+
+	kfree_skb(skb);
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+		"itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
+		task->itt, skb, skb->len, skb->data_len, err);
+	iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
+	iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
+	return err;
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_xmit_pdu);
+
+void cxgbi_cleanup_task(struct iscsi_task *task)
+{
+	struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"task 0x%p, skb 0x%p, itt 0x%x.\n",
+		task, tdata->skb, task->hdr_itt);
+
+	/*  never reached the xmit task callout */
+	if (tdata->skb)
+		__kfree_skb(tdata->skb);
+	memset(tdata, 0, sizeof(*tdata));
+
+	task_release_itt(task, task->hdr_itt);
+	iscsi_tcp_cleanup_task(task);
+}
+EXPORT_SYMBOL_GPL(cxgbi_cleanup_task);
+
+void cxgbi_get_conn_stats(struct iscsi_cls_conn *cls_conn,
+				struct iscsi_stats *stats)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+
+	stats->txdata_octets = conn->txdata_octets;
+	stats->rxdata_octets = conn->rxdata_octets;
+	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
+	stats->dataout_pdus = conn->dataout_pdus_cnt;
+	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
+	stats->datain_pdus = conn->datain_pdus_cnt;
+	stats->r2t_pdus = conn->r2t_pdus_cnt;
+	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
+	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+	stats->digest_err = 0;
+	stats->timeout_err = 0;
+	stats->custom_length = 1;
+	strcpy(stats->custom[0].desc, "eh_abort_cnt");
+	stats->custom[0].value = conn->eh_abort_cnt;
+}
+EXPORT_SYMBOL_GPL(cxgbi_get_conn_stats);
+
+static int cxgbi_conn_max_xmit_dlength(struct iscsi_conn *conn)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	unsigned int headroom = SKB_MAX_HEAD(cdev->skb_tx_rsvd);
+	unsigned int max_def = 512 * MAX_SKB_FRAGS;
+	unsigned int max = max(max_def, headroom);
+
+	max = min(cconn->chba->cdev->tx_max_size, max);
+	if (conn->max_xmit_dlength)
+		conn->max_xmit_dlength = min(conn->max_xmit_dlength, max);
+	else
+		conn->max_xmit_dlength = max;
+	cxgbi_align_pdu_size(conn->max_xmit_dlength);
+
+	return 0;
+}
+
+static int cxgbi_conn_max_recv_dlength(struct iscsi_conn *conn)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	unsigned int max = cconn->chba->cdev->rx_max_size;
+
+	cxgbi_align_pdu_size(max);
+
+	if (conn->max_recv_dlength) {
+		if (conn->max_recv_dlength > max) {
+			pr_err("MaxRecvDataSegmentLength %u > %u.\n",
+				conn->max_recv_dlength, max);
+			return -EINVAL;
+		}
+		conn->max_recv_dlength = min(conn->max_recv_dlength, max);
+		cxgbi_align_pdu_size(conn->max_recv_dlength);
+	} else
+		conn->max_recv_dlength = max;
+
+	return 0;
+}
+
+int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
+			enum iscsi_param param, char *buf, int buflen)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_session *session = conn->session;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_sock *csk = cconn->cep->csk;
+	int value, err = 0;
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"cls_conn 0x%p, param %d, buf(%d) %s.\n",
+		cls_conn, param, buflen, buf);
+
+	switch (param) {
+	case ISCSI_PARAM_HDRDGST_EN:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && conn->hdrdgst_en)
+			err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
+							conn->hdrdgst_en,
+							conn->datadgst_en, 0);
+		break;
+	case ISCSI_PARAM_DATADGST_EN:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && conn->datadgst_en)
+			err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
+							conn->hdrdgst_en,
+							conn->datadgst_en, 0);
+		break;
+	case ISCSI_PARAM_MAX_R2T:
+		sscanf(buf, "%d", &value);
+		if (value <= 0 || !is_power_of_2(value))
+			return -EINVAL;
+		if (session->max_r2t == value)
+			break;
+		iscsi_tcp_r2tpool_free(session);
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && iscsi_tcp_r2tpool_alloc(session))
+			return -ENOMEM;
+	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err)
+			err = cxgbi_conn_max_recv_dlength(conn);
+		break;
+	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err)
+			err = cxgbi_conn_max_xmit_dlength(conn);
+		break;
+	default:
+		return iscsi_set_param(cls_conn, param, buf, buflen);
+	}
+	return err;
+}
+EXPORT_SYMBOL_GPL(cxgbi_set_conn_param);
+
+int cxgbi_get_conn_param(struct iscsi_cls_conn *cls_conn,
+			enum iscsi_param param, char *buf)
+{
+	struct iscsi_conn *iconn = cls_conn->dd_data;
+	int len;
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"cls_conn 0x%p, param %d.\n", cls_conn, 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;
+	default:
+		return iscsi_conn_get_param(cls_conn, param, buf);
+	}
+	return len;
+}
+EXPORT_SYMBOL_GPL(cxgbi_get_conn_param);
+
+struct iscsi_cls_conn *
+cxgbi_create_conn(struct iscsi_cls_session *cls_session, u32 cid)
+{
+	struct iscsi_cls_conn *cls_conn;
+	struct iscsi_conn *conn;
+	struct iscsi_tcp_conn *tcp_conn;
+	struct cxgbi_conn *cconn;
+
+	cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*cconn), cid);
+	if (!cls_conn)
+		return NULL;
+
+	conn = cls_conn->dd_data;
+	tcp_conn = conn->dd_data;
+	cconn = tcp_conn->dd_data;
+	cconn->iconn = conn;
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"cid %u(0x%x), cls 0x%p,0x%p, conn 0x%p,0x%p,0x%p.\n",
+		cid, cid, cls_session, cls_conn, conn, tcp_conn, cconn);
+
+	return cls_conn;
+}
+EXPORT_SYMBOL_GPL(cxgbi_create_conn);
+
+int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
+				struct iscsi_cls_conn *cls_conn,
+				u64 transport_eph, int is_leading)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct iscsi_endpoint *ep;
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_sock *csk;
+	int err;
+
+	ep = iscsi_lookup_endpoint(transport_eph);
+	if (!ep)
+		return -EINVAL;
+
+	/*  setup ddp pagesize */
+	cep = ep->dd_data;
+	csk = cep->csk;
+	err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid, page_idx, 0);
+	if (err < 0)
+		return err;
+
+	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+	if (err)
+		return -EINVAL;
+
+	/*  calculate the tag idx bits needed for this conn based on cmds_max */
+	cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1;
+
+	write_lock_bh(&csk->callback_lock);
+	csk->user_data = conn;
+	cconn->chba = cep->chba;
+	cconn->cep = cep;
+	cep->cconn = cconn;
+	write_unlock_bh(&csk->callback_lock);
+
+	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);
+	/*  init recv engine */
+	iscsi_tcp_hdr_recv_prep(tcp_conn);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_bind_conn);
+
+struct iscsi_cls_session *cxgbi_create_session(struct iscsi_endpoint *ep,
+						u16 cmds_max, u16 qdepth,
+						u32 initial_cmdsn)
+{
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_hba *chba;
+	struct Scsi_Host *shost;
+	struct iscsi_cls_session *cls_session;
+	struct iscsi_session *session;
+
+	if (!ep) {
+		pr_err("missing endpoint.\n");
+		return NULL;
+	}
+
+	cep = ep->dd_data;
+	chba = cep->chba;
+	shost = chba->shost;
+
+	BUG_ON(chba != iscsi_host_priv(shost));
+
+	cls_session = iscsi_session_setup(chba->cdev->itp, shost,
+					cmds_max, 0,
+					sizeof(struct iscsi_tcp_task) +
+					sizeof(struct cxgbi_task_data),
+					initial_cmdsn, ISCSI_MAX_TARGET);
+	if (!cls_session)
+		return NULL;
+
+	session = cls_session->dd_data;
+	if (iscsi_tcp_r2tpool_alloc(session))
+		goto remove_session;
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"ep 0x%p, cls sess 0x%p.\n", ep, cls_session);
+	return cls_session;
+
+remove_session:
+	iscsi_session_teardown(cls_session);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(cxgbi_create_session);
+
+void cxgbi_destroy_session(struct iscsi_cls_session *cls_session)
+{
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"cls sess 0x%p.\n", cls_session);
+
+	iscsi_tcp_r2tpool_free(cls_session->dd_data);
+	iscsi_session_teardown(cls_session);
+}
+EXPORT_SYMBOL_GPL(cxgbi_destroy_session);
+
+int cxgbi_set_host_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+			char *buf, int buflen)
+{
+	struct cxgbi_hba *chba = iscsi_host_priv(shost);
+
+	if (!chba->ndev) {
+		shost_printk(KERN_ERR, shost, "Could not get host param. "
+				"netdev for host not set.\n");
+		return -ENODEV;
+	}
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"shost 0x%p, hba 0x%p,%s, param %d, buf(%d) %s.\n",
+		shost, chba, chba->ndev->name, param, buflen, buf);
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_IPADDRESS:
+	{
+		__be32 addr = in_aton(buf);
+		log_debug(1 << CXGBI_DBG_ISCSI,
+			"hba %s, req. ipv4 %pI4.\n", chba->ndev->name, &addr);
+		cxgbi_set_iscsi_ipv4(chba, addr);
+		return 0;
+	}
+	case ISCSI_HOST_PARAM_HWADDRESS:
+	case ISCSI_HOST_PARAM_NETDEV_NAME:
+		return 0;
+	default:
+		return iscsi_host_set_param(shost, param, buf, buflen);
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_set_host_param);
+
+int cxgbi_get_host_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+			char *buf)
+{
+	struct cxgbi_hba *chba = iscsi_host_priv(shost);
+	int len = 0;
+
+	if (!chba->ndev) {
+		shost_printk(KERN_ERR, shost, "Could not get host param. "
+				"netdev for host not set.\n");
+		return -ENODEV;
+	}
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"shost 0x%p, hba 0x%p,%s, param %d.\n",
+		shost, chba, chba->ndev->name, param);
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_HWADDRESS:
+		len = sysfs_format_mac(buf, chba->ndev->dev_addr, 6);
+		break;
+	case ISCSI_HOST_PARAM_NETDEV_NAME:
+		len = sprintf(buf, "%s\n", chba->ndev->name);
+		break;
+	case ISCSI_HOST_PARAM_IPADDRESS:
+	{
+		__be32 addr;
+
+		addr = cxgbi_get_iscsi_ipv4(chba);
+		len = sprintf(buf, "%pI4", &addr);
+		log_debug(1 << CXGBI_DBG_ISCSI,
+			"hba %s, ipv4 %pI4.\n", chba->ndev->name, &addr);
+		break;
+	}
+	default:
+		return iscsi_host_get_param(shost, param, buf);
+	}
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(cxgbi_get_host_param);
+
+struct iscsi_endpoint *cxgbi_ep_connect(struct Scsi_Host *shost,
+					struct sockaddr *dst_addr,
+					int non_blocking)
+{
+	struct iscsi_endpoint *ep;
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_hba *hba = NULL;
+	struct cxgbi_sock *csk;
+	int err = -EINVAL;
+
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_SOCK,
+		"shost 0x%p, non_blocking %d, dst_addr 0x%p.\n",
+		shost, non_blocking, dst_addr);
+
+	if (shost) {
+		hba = iscsi_host_priv(shost);
+		if (!hba) {
+			pr_info("shost 0x%p, priv NULL.\n", shost);
+			goto err_out;
+		}
+	}
+
+	csk = cxgbi_check_route(dst_addr);
+	if (IS_ERR(csk))
+		return (struct iscsi_endpoint *)csk;
+	cxgbi_sock_get(csk);
+
+	if (!hba)
+		hba = csk->cdev->hbas[csk->port_id];
+	else if (hba != csk->cdev->hbas[csk->port_id]) {
+		pr_info("Could not connect through requested host %u"
+			"hba 0x%p != 0x%p (%u).\n",
+			shost->host_no, hba,
+			csk->cdev->hbas[csk->port_id], csk->port_id);
+		err = -ENOSPC;
+		goto release_conn;
+	}
+
+	err = sock_get_port(csk);
+	if (err)
+		goto release_conn;
+
+	cxgbi_sock_set_state(csk, CTP_CONNECTING);
+	err = csk->cdev->csk_init_act_open(csk);
+	if (err)
+		goto release_conn;
+
+	if (cxgbi_sock_is_closing(csk)) {
+		err = -ENOSPC;
+		pr_info("csk 0x%p is closing.\n", csk);
+		goto release_conn;
+	}
+
+	ep = iscsi_create_endpoint(sizeof(*cep));
+	if (!ep) {
+		err = -ENOMEM;
+		pr_info("iscsi alloc ep, OOM.\n");
+		goto release_conn;
+	}
+
+	cep = ep->dd_data;
+	cep->csk = csk;
+	cep->chba = hba;
+
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_SOCK,
+		"ep 0x%p, cep 0x%p, csk 0x%p, hba 0x%p,%s.\n",
+		ep, cep, csk, hba, hba->ndev->name);
+	return ep;
+
+release_conn:
+	cxgbi_sock_put(csk);
+	cxgbi_sock_closed(csk);
+err_out:
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(cxgbi_ep_connect);
+
+int cxgbi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
+{
+	struct cxgbi_endpoint *cep = ep->dd_data;
+	struct cxgbi_sock *csk = cep->csk;
+
+	if (!cxgbi_sock_is_established(csk))
+		return 0;
+	return 1;
+}
+EXPORT_SYMBOL_GPL(cxgbi_ep_poll);
+
+void cxgbi_ep_disconnect(struct iscsi_endpoint *ep)
+{
+	struct cxgbi_endpoint *cep = ep->dd_data;
+	struct cxgbi_conn *cconn = cep->cconn;
+	struct cxgbi_sock *csk = cep->csk;
+
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_SOCK,
+		"ep 0x%p, cep 0x%p, cconn 0x%p, csk 0x%p,%u,0x%lx.\n",
+		ep, cep, cconn, csk, csk->state, csk->flags);
+
+	if (cconn && cconn->iconn) {
+		iscsi_suspend_tx(cconn->iconn);
+		write_lock_bh(&csk->callback_lock);
+		cep->csk->user_data = NULL;
+		cconn->cep = NULL;
+		write_unlock_bh(&csk->callback_lock);
+	}
+	iscsi_destroy_endpoint(ep);
+
+	if (likely(csk->state >= CTP_ESTABLISHED))
+		need_active_close(csk);
+	else
+		cxgbi_sock_closed(csk);
+
+	cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_ep_disconnect);
+
+int cxgbi_iscsi_init(struct iscsi_transport *itp,
+			struct scsi_transport_template **stt)
+{
+	*stt = iscsi_register_transport(itp);
+	if (*stt == NULL) {
+		pr_err("unable to register %s transport 0x%p.\n",
+			itp->name, itp);
+		return -ENODEV;
+	}
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"%s, registered iscsi transport 0x%p.\n",
+		itp->name, stt);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_iscsi_init);
+
+void cxgbi_iscsi_cleanup(struct iscsi_transport *itp,
+			struct scsi_transport_template **stt)
+{
+	if (*stt) {
+		log_debug(1 << CXGBI_DBG_ISCSI,
+			"de-register transport 0x%p, %s, stt 0x%p.\n",
+			itp, itp->name, *stt);
+		*stt = NULL;
+		iscsi_unregister_transport(itp);
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_iscsi_cleanup);
+
+static int __init libcxgbi_init_module(void)
+{
+	sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
+	sw_tag_age_bits = (__ilog2_u32(ISCSI_AGE_MASK)) + 1;
+
+	pr_info("tag itt 0x%x, %u bits, age 0x%x, %u bits.\n",
+		ISCSI_ITT_MASK, sw_tag_idx_bits,
+		ISCSI_AGE_MASK, sw_tag_age_bits);
+
+	ddp_setup_host_page_size();
+	return 0;
+}
+
+static void __exit libcxgbi_exit_module(void)
+{
+	cxgbi_device_unregister_all(0xFF);
+	return;
+}
+
+module_init(libcxgbi_init_module);
+module_exit(libcxgbi_exit_module);
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
new file mode 100644
index 0000000..c57d59d
--- /dev/null
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -0,0 +1,745 @@
+/*
+ * libcxgbi.h: Chelsio common library for T3/T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ * Written by: Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#ifndef	__LIBCXGBI_H__
+#define	__LIBCXGBI_H__
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <scsi/scsi_device.h>
+#include <scsi/libiscsi_tcp.h>
+
+enum cxgbi_dbg_flag {
+	CXGBI_DBG_ISCSI,
+	CXGBI_DBG_DDP,
+	CXGBI_DBG_TOE,
+	CXGBI_DBG_SOCK,
+
+	CXGBI_DBG_PDU_TX,
+	CXGBI_DBG_PDU_RX,
+	CXGBI_DBG_DEV,
+};
+
+#define log_debug(level, fmt, ...)	\
+	do {	\
+		if (dbg_level & (level)) \
+			pr_info(fmt, ##__VA_ARGS__); \
+	} while (0)
+
+/* max. connections per adapter */
+#define CXGBI_MAX_CONN		16384
+
+/* always allocate rooms for AHS */
+#define SKB_TX_ISCSI_PDU_HEADER_MAX	\
+	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE)
+
+#define	ISCSI_PDU_NONPAYLOAD_LEN	312 /* bhs(48) + ahs(256) + digest(8)*/
+
+/*
+ * align pdu size to multiple of 512 for better performance
+ */
+#define cxgbi_align_pdu_size(n) do { n = (n) & (~511); } while (0)
+
+#define ULP2_MODE_ISCSI		2
+
+#define ULP2_MAX_PKT_SIZE	16224
+#define ULP2_MAX_PDU_PAYLOAD	\
+	(ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
+
+/*
+ * For iscsi connections HW may inserts digest bytes into the pdu. Those digest
+ * bytes are not sent by the host but are part of the TCP payload and therefore
+ * consume TCP sequence space.
+ */
+static const unsigned int ulp2_extra_len[] = { 0, 4, 4, 8 };
+static inline unsigned int cxgbi_ulp_extra_len(int submode)
+{
+	return ulp2_extra_len[submode & 3];
+}
+
+/*
+ * struct pagepod_hdr, pagepod - pagepod format
+ */
+
+#define CPL_RX_DDP_STATUS_DDP_SHIFT	16 /* ddp'able */
+#define CPL_RX_DDP_STATUS_PAD_SHIFT	19 /* pad error */
+#define CPL_RX_DDP_STATUS_HCRC_SHIFT	20 /* hcrc error */
+#define CPL_RX_DDP_STATUS_DCRC_SHIFT	21 /* dcrc error */
+
+struct cxgbi_pagepod_hdr {
+	u32 vld_tid;
+	u32 pgsz_tag_clr;
+	u32 max_offset;
+	u32 page_offset;
+	u64 rsvd;
+};
+
+#define PPOD_PAGES_MAX			4
+struct cxgbi_pagepod {
+	struct cxgbi_pagepod_hdr hdr;
+	u64 addr[PPOD_PAGES_MAX + 1];
+};
+
+struct cxgbi_tag_format {
+	unsigned char sw_bits;
+	unsigned char rsvd_bits;
+	unsigned char rsvd_shift;
+	unsigned char filler[1];
+	u32 rsvd_mask;
+};
+
+struct cxgbi_gather_list {
+	unsigned int tag;
+	unsigned int length;
+	unsigned int offset;
+	unsigned int nelem;
+	struct page **pages;
+	dma_addr_t phys_addr[0];
+};
+
+struct cxgbi_ddp_info {
+	struct kref refcnt;
+	struct cxgbi_device *cdev;
+	struct pci_dev *pdev;
+	unsigned int max_txsz;
+	unsigned int max_rxsz;
+	unsigned int llimit;
+	unsigned int ulimit;
+	unsigned int nppods;
+	unsigned int idx_last;
+	unsigned char idx_bits;
+	unsigned char filler[3];
+	unsigned int idx_mask;
+	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
+#define DDP_THRESHOLD		2048
+
+#define PPOD_PAGES_SHIFT	2       /*  4 pages per pod */
+
+#define PPOD_SIZE               sizeof(struct cxgbi_pagepod)  /*  64 */
+#define PPOD_SIZE_SHIFT         6
+
+#define ULPMEM_DSGL_MAX_NPPODS	16	/*  1024/PPOD_SIZE */
+#define ULPMEM_IDATA_MAX_NPPODS	4	/*  256/PPOD_SIZE */
+#define PCIE_MEMWIN_MAX_NPPODS	16	/*  1024/PPOD_SIZE */
+
+#define PPOD_COLOR_SHIFT	0
+#define PPOD_COLOR(x)		((x) << PPOD_COLOR_SHIFT)
+
+#define PPOD_IDX_SHIFT          6
+#define PPOD_IDX_MAX_SIZE       24
+
+#define PPOD_TID_SHIFT		0
+#define PPOD_TID(x)		((x) << PPOD_TID_SHIFT)
+
+#define PPOD_TAG_SHIFT		6
+#define PPOD_TAG(x)		((x) << PPOD_TAG_SHIFT)
+
+#define PPOD_VALID_SHIFT	24
+#define PPOD_VALID(x)		((x) << PPOD_VALID_SHIFT)
+#define PPOD_VALID_FLAG		PPOD_VALID(1U)
+
+/*
+ * sge_opaque_hdr -
+ * Opaque version of structure the SGE stores at skb->head of TX_DATA packets
+ * and for which we must reserve space.
+ */
+struct sge_opaque_hdr {
+	void *dev;
+	dma_addr_t addr[MAX_SKB_FRAGS + 1];
+};
+
+struct cxgbi_sock {
+	struct cxgbi_device *cdev;
+
+	int tid;
+	int atid;
+	unsigned long flags;
+	unsigned int mtu;
+	unsigned short rss_qid;
+	unsigned short txq_idx;
+	unsigned short advmss;
+	unsigned int tx_chan;
+	unsigned int rx_chan;
+	unsigned int mss_idx;
+	unsigned int smac_idx;
+	unsigned char port_id;
+	int wr_max_cred;
+	int wr_cred;
+	int wr_una_cred;
+	unsigned char hcrc_len;
+	unsigned char dcrc_len;
+
+	void *l2t;
+	struct sk_buff *wr_pending_head;
+	struct sk_buff *wr_pending_tail;
+	struct sk_buff *cpl_close;
+	struct sk_buff *cpl_abort_req;
+	struct sk_buff *cpl_abort_rpl;
+	struct sk_buff *skb_ulp_lhdr;
+	spinlock_t lock;
+	struct kref refcnt;
+	unsigned int state;
+	struct sockaddr_in saddr;
+	struct sockaddr_in daddr;
+	struct dst_entry *dst;
+	struct sk_buff_head receive_queue;
+	struct sk_buff_head write_queue;
+	struct timer_list retry_timer;
+	int err;
+	rwlock_t callback_lock;
+	void *user_data;
+
+	u32 rcv_nxt;
+	u32 copied_seq;
+	u32 rcv_wup;
+	u32 snd_nxt;
+	u32 snd_una;
+	u32 write_seq;
+};
+
+/*
+ * connection states
+ */
+enum cxgbi_sock_states{
+	CTP_CLOSED,
+	CTP_CONNECTING,
+	CTP_ACTIVE_OPEN,
+	CTP_ESTABLISHED,
+	CTP_ACTIVE_CLOSE,
+	CTP_PASSIVE_CLOSE,
+	CTP_CLOSE_WAIT_1,
+	CTP_CLOSE_WAIT_2,
+	CTP_ABORTING,
+};
+
+/*
+ * Connection flags -- many to track some close related events.
+ */
+enum cxgbi_sock_flags {
+	CTPF_ABORT_RPL_RCVD,	/*received one ABORT_RPL_RSS message */
+	CTPF_ABORT_REQ_RCVD,	/*received one ABORT_REQ_RSS message */
+	CTPF_ABORT_RPL_PENDING,	/* expecting an abort reply */
+	CTPF_TX_DATA_SENT,	/* already sent a TX_DATA WR */
+	CTPF_ACTIVE_CLOSE_NEEDED,/* need to be closed */
+	CTPF_HAS_ATID,		/* reserved atid */
+	CTPF_HAS_TID,		/* reserved hw tid */
+	CTPF_OFFLOAD_DOWN,	/* offload function off */
+};
+
+struct cxgbi_skb_rx_cb {
+	__u32 ddigest;
+	__u32 pdulen;
+};
+
+struct cxgbi_skb_tx_cb {
+	void *l2t;
+	struct sk_buff *wr_next;
+};
+
+enum cxgbi_skcb_flags {
+	SKCBF_TX_NEED_HDR,	/* packet needs a header */
+	SKCBF_RX_COALESCED,	/* received whole pdu */
+	SKCBF_RX_HDR,		/* recieved pdu header */
+	SKCBF_RX_DATA,		/* recieved pdu payload */
+	SKCBF_RX_STATUS,	/* recieved ddp status */
+	SKCBF_RX_DATA_DDPD,	/* pdu payload ddp'd */
+	SKCBF_RX_HCRC_ERR,	/* header digest error */
+	SKCBF_RX_DCRC_ERR,	/* data digest error */
+	SKCBF_RX_PAD_ERR,	/* padding byte error */
+};
+
+struct cxgbi_skb_cb {
+	unsigned char ulp_mode;
+	unsigned long flags;
+	unsigned int seq;
+	union {
+		struct cxgbi_skb_rx_cb rx;
+		struct cxgbi_skb_tx_cb tx;
+	};
+};
+
+#define CXGBI_SKB_CB(skb)	((struct cxgbi_skb_cb *)&((skb)->cb[0]))
+#define cxgbi_skcb_flags(skb)		(CXGBI_SKB_CB(skb)->flags)
+#define cxgbi_skcb_ulp_mode(skb)	(CXGBI_SKB_CB(skb)->ulp_mode)
+#define cxgbi_skcb_tcp_seq(skb)		(CXGBI_SKB_CB(skb)->seq)
+#define cxgbi_skcb_rx_ddigest(skb)	(CXGBI_SKB_CB(skb)->rx.ddigest)
+#define cxgbi_skcb_rx_pdulen(skb)	(CXGBI_SKB_CB(skb)->rx.pdulen)
+#define cxgbi_skcb_tx_wr_next(skb)	(CXGBI_SKB_CB(skb)->tx.wr_next)
+
+static inline void cxgbi_skcb_set_flag(struct sk_buff *skb,
+					enum cxgbi_skcb_flags flag)
+{
+	__set_bit(flag, &(cxgbi_skcb_flags(skb)));
+}
+
+static inline void cxgbi_skcb_clear_flag(struct sk_buff *skb,
+					enum cxgbi_skcb_flags flag)
+{
+	__clear_bit(flag, &(cxgbi_skcb_flags(skb)));
+}
+
+static inline int cxgbi_skcb_test_flag(struct sk_buff *skb,
+					enum cxgbi_skcb_flags flag)
+{
+	return test_bit(flag, &(cxgbi_skcb_flags(skb)));
+}
+
+static inline void cxgbi_sock_set_flag(struct cxgbi_sock *csk,
+					enum cxgbi_sock_flags flag)
+{
+	__set_bit(flag, &csk->flags);
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, bit %d.\n",
+		csk, csk->state, csk->flags, flag);
+}
+
+static inline void cxgbi_sock_clear_flag(struct cxgbi_sock *csk,
+					enum cxgbi_sock_flags flag)
+{
+	__clear_bit(flag, &csk->flags);
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, bit %d.\n",
+		csk, csk->state, csk->flags, flag);
+}
+
+static inline int cxgbi_sock_flag(struct cxgbi_sock *csk,
+				enum cxgbi_sock_flags flag)
+{
+	if (csk == NULL)
+		return 0;
+	return test_bit(flag, &csk->flags);
+}
+
+static inline void cxgbi_sock_set_state(struct cxgbi_sock *csk, int state)
+{
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, state -> %u.\n",
+		csk, csk->state, csk->flags, state);
+	csk->state = state;
+}
+
+static inline void cxgbi_sock_free(struct kref *kref)
+{
+	struct cxgbi_sock *csk = container_of(kref,
+						struct cxgbi_sock,
+						refcnt);
+	if (csk) {
+		log_debug(1 << CXGBI_DBG_SOCK,
+			"free csk 0x%p, state %u, flags 0x%lx\n",
+			csk, csk->state, csk->flags);
+		kfree(csk);
+	}
+}
+
+static inline void __cxgbi_sock_put(const char *fn, struct cxgbi_sock *csk)
+{
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"%s, put csk 0x%p, ref %u-1.\n",
+		fn, csk, atomic_read(&csk->refcnt.refcount));
+	kref_put(&csk->refcnt, cxgbi_sock_free);
+}
+#define cxgbi_sock_put(csk)	__cxgbi_sock_put(__func__, csk)
+
+static inline void __cxgbi_sock_get(const char *fn, struct cxgbi_sock *csk)
+{
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"%s, get csk 0x%p, ref %u+1.\n",
+		fn, csk, atomic_read(&csk->refcnt.refcount));
+	kref_get(&csk->refcnt);
+}
+#define cxgbi_sock_get(csk)	__cxgbi_sock_get(__func__, csk)
+
+static inline int cxgbi_sock_is_closing(struct cxgbi_sock *csk)
+{
+	return csk->state >= CTP_ACTIVE_CLOSE;
+}
+
+static inline int cxgbi_sock_is_established(struct cxgbi_sock *csk)
+{
+	return csk->state == CTP_ESTABLISHED;
+}
+
+static inline void cxgbi_sock_purge_write_queue(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+
+	while ((skb = __skb_dequeue(&csk->write_queue)))
+		__kfree_skb(skb);
+}
+
+static inline unsigned int cxgbi_sock_compute_wscale(unsigned int win)
+{
+	unsigned int wscale = 0;
+
+	while (wscale < 14 && (65535 << wscale) < win)
+		wscale++;
+	return wscale;
+}
+
+static inline struct sk_buff *alloc_wr(int wrlen, int dlen, gfp_t gfp)
+{
+	struct sk_buff *skb = alloc_skb(wrlen + dlen, gfp);
+
+	if (skb) {
+		__skb_put(skb, wrlen);
+		memset(skb->head, 0, wrlen + dlen);
+	} else
+		pr_info("alloc cpl wr skb %u+%u, OOM.\n", wrlen, dlen);
+	return skb;
+}
+
+
+/*
+ * The number of WRs needed for an skb depends on the number of fragments
+ * in the skb and whether it has any payload in its main body.  This maps the
+ * length of the gather list represented by an skb into the # of necessary WRs.
+ * The extra two fragments are for iscsi bhs and payload padding.
+ */
+#define SKB_WR_LIST_SIZE	 (MAX_SKB_FRAGS + 2)
+
+static inline void cxgbi_sock_reset_wr_list(struct cxgbi_sock *csk)
+{
+	csk->wr_pending_head = csk->wr_pending_tail = NULL;
+}
+
+static inline void cxgbi_sock_enqueue_wr(struct cxgbi_sock *csk,
+					  struct sk_buff *skb)
+{
+	cxgbi_skcb_tx_wr_next(skb) = NULL;
+	/*
+	 * We want to take an extra reference since both us and the driver
+	 * need to free the packet before it's really freed. We know there's
+	 * just one user currently so we use atomic_set rather than skb_get
+	 * to avoid the atomic op.
+	 */
+	atomic_set(&skb->users, 2);
+
+	if (!csk->wr_pending_head)
+		csk->wr_pending_head = skb;
+	else
+		cxgbi_skcb_tx_wr_next(csk->wr_pending_tail) = skb;
+	csk->wr_pending_tail = skb;
+}
+
+static inline int cxgbi_sock_count_pending_wrs(const struct cxgbi_sock *csk)
+{
+	int n = 0;
+	const struct sk_buff *skb = csk->wr_pending_head;
+
+	while (skb) {
+		n += skb->csum;
+		skb = cxgbi_skcb_tx_wr_next(skb);
+	}
+	return n;
+}
+
+static inline struct sk_buff *cxgbi_sock_peek_wr(const struct cxgbi_sock *csk)
+{
+	return csk->wr_pending_head;
+}
+
+static inline struct sk_buff *cxgbi_sock_dequeue_wr(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->wr_pending_head;
+
+	if (likely(skb)) {
+		csk->wr_pending_head = cxgbi_skcb_tx_wr_next(skb);
+		cxgbi_skcb_tx_wr_next(skb) = NULL;
+	}
+	return skb;
+}
+
+void cxgbi_sock_check_wr_invariants(const struct cxgbi_sock *);
+void cxgbi_sock_purge_wr_queue(struct cxgbi_sock *);
+void cxgbi_sock_skb_entail(struct cxgbi_sock *, struct sk_buff *);
+void cxgbi_sock_fail_act_open(struct cxgbi_sock *, int);
+void cxgbi_sock_act_open_req_arp_failure(void *, struct sk_buff *);
+void cxgbi_sock_closed(struct cxgbi_sock *);
+void cxgbi_sock_established(struct cxgbi_sock *, unsigned int, unsigned int);
+void cxgbi_sock_rcv_abort_rpl(struct cxgbi_sock *);
+void cxgbi_sock_rcv_peer_close(struct cxgbi_sock *);
+void cxgbi_sock_rcv_close_conn_rpl(struct cxgbi_sock *, u32);
+void cxgbi_sock_rcv_wr_ack(struct cxgbi_sock *, unsigned int, unsigned int,
+				int);
+unsigned int cxgbi_sock_select_mss(struct cxgbi_sock *, unsigned int);
+void cxgbi_sock_free_cpl_skbs(struct cxgbi_sock *);
+
+struct cxgbi_hba {
+	struct net_device *ndev;
+	struct net_device *vdev;	/* vlan dev */
+	struct Scsi_Host *shost;
+	struct cxgbi_device *cdev;
+	__be32 ipv4addr;
+	unsigned char port_id;
+};
+
+struct cxgbi_ports_map {
+	unsigned int max_connect;
+	unsigned int used;
+	unsigned short sport_base;
+	spinlock_t lock;
+	unsigned int next;
+	struct cxgbi_sock **port_csk;
+};
+
+#define CXGBI_FLAG_DEV_T3		0x1
+#define CXGBI_FLAG_DEV_T4		0x2
+#define CXGBI_FLAG_ADAPTER_RESET	0x4
+#define CXGBI_FLAG_IPV4_SET		0x10
+struct cxgbi_device {
+	struct list_head list_head;
+	unsigned int flags;
+	struct net_device **ports;
+	void *lldev;
+	struct cxgbi_hba **hbas;
+	const unsigned short *mtus;
+	unsigned char nmtus;
+	unsigned char nports;
+	struct pci_dev *pdev;
+	struct dentry *debugfs_root;
+	struct iscsi_transport *itp;
+
+	unsigned int pfvf;
+	unsigned int snd_win;
+	unsigned int rcv_win;
+	unsigned int rx_credit_thres;
+	unsigned int skb_tx_rsvd;
+	unsigned int skb_rx_extra;	/* for msg coalesced mode */
+	unsigned int tx_max_size;
+	unsigned int rx_max_size;
+	struct cxgbi_ports_map pmap;
+	struct cxgbi_tag_format tag_format;
+	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 *);
+	void (*csk_ddp_clear)(struct cxgbi_hba *,
+				unsigned int, unsigned int, unsigned int);
+	int (*csk_ddp_setup_digest)(struct cxgbi_sock *,
+				unsigned int, int, int, int);
+	int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *,
+				unsigned int, int, bool);
+
+	void (*csk_release_offload_resources)(struct cxgbi_sock *);
+	int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *);
+	u32 (*csk_send_rx_credits)(struct cxgbi_sock *, u32);
+	int (*csk_push_tx_frames)(struct cxgbi_sock *, int);
+	void (*csk_send_abort_req)(struct cxgbi_sock *);
+	void (*csk_send_close_req)(struct cxgbi_sock *);
+	int (*csk_alloc_cpls)(struct cxgbi_sock *);
+	int (*csk_init_act_open)(struct cxgbi_sock *);
+
+	void *dd_data;
+};
+#define cxgbi_cdev_priv(cdev)	((cdev)->dd_data)
+
+struct cxgbi_conn {
+	struct cxgbi_endpoint *cep;
+	struct iscsi_conn *iconn;
+	struct cxgbi_hba *chba;
+	u32 task_idx_bits;
+};
+
+struct cxgbi_endpoint {
+	struct cxgbi_conn *cconn;
+	struct cxgbi_hba *chba;
+	struct cxgbi_sock *csk;
+};
+
+#define MAX_PDU_FRAGS	((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
+struct cxgbi_task_data {
+	unsigned short nr_frags;
+	skb_frag_t frags[MAX_PDU_FRAGS];
+	struct sk_buff *skb;
+	unsigned int offset;
+	unsigned int count;
+	unsigned int sgoffset;
+};
+#define iscsi_task_cxgbi_data(task) \
+	((task)->dd_data + sizeof(struct iscsi_tcp_task))
+
+static inline int cxgbi_is_ddp_tag(struct cxgbi_tag_format *tformat, u32 tag)
+{
+	return !(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1)));
+}
+
+static inline int cxgbi_sw_tag_usable(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	sw_tag >>= (32 - tformat->rsvd_bits);
+	return !sw_tag;
+}
+
+static inline u32 cxgbi_set_non_ddp_tag(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
+	u32 mask = (1 << shift) - 1;
+
+	if (sw_tag && (sw_tag & ~mask)) {
+		u32 v1 = sw_tag & ((1 << shift) - 1);
+		u32 v2 = (sw_tag >> (shift - 1)) << shift;
+
+		return v2 | v1 | 1 << shift;
+	}
+
+	return sw_tag | 1 << shift;
+}
+
+static inline u32 cxgbi_ddp_tag_base(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	u32 mask = (1 << tformat->rsvd_shift) - 1;
+
+	if (sw_tag && (sw_tag & ~mask)) {
+		u32 v1 = sw_tag & mask;
+		u32 v2 = sw_tag >> tformat->rsvd_shift;
+
+		v2 <<= tformat->rsvd_bits + tformat->rsvd_shift;
+
+		return v2 | v1;
+	}
+
+	return sw_tag;
+}
+
+static inline u32 cxgbi_tag_rsvd_bits(struct cxgbi_tag_format *tformat,
+					u32 tag)
+{
+	if (cxgbi_is_ddp_tag(tformat, tag))
+		return (tag >> tformat->rsvd_shift) & tformat->rsvd_mask;
+
+	return 0;
+}
+
+static inline u32 cxgbi_tag_nonrsvd_bits(struct cxgbi_tag_format *tformat,
+					u32 tag)
+{
+	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
+	u32 v1, v2;
+
+	if (cxgbi_is_ddp_tag(tformat, tag)) {
+		v1 = tag & ((1 << tformat->rsvd_shift) - 1);
+		v2 = (tag >> (shift + 1)) << tformat->rsvd_shift;
+	} else {
+		u32 mask = (1 << shift) - 1;
+		tag &= ~(1 << shift);
+		v1 = tag & mask;
+		v2 = (tag >> 1) & ~mask;
+	}
+	return v1 | v2;
+}
+
+static inline void *cxgbi_alloc_big_mem(unsigned int size,
+					gfp_t gfp)
+{
+	void *p = kmalloc(size, gfp);
+	if (!p)
+		p = vmalloc(size);
+	if (p)
+		memset(p, 0, size);
+	return p;
+}
+
+static inline void cxgbi_free_big_mem(void *addr)
+{
+	if (is_vmalloc_addr(addr))
+		vfree(addr);
+	else
+		kfree(addr);
+}
+
+static inline void cxgbi_set_iscsi_ipv4(struct cxgbi_hba *chba, __be32 ipaddr)
+{
+	if (chba->cdev->flags & CXGBI_FLAG_IPV4_SET)
+		chba->ipv4addr = ipaddr;
+	else
+		pr_info("set iscsi ipv4 NOT supported, using %s ipv4.\n",
+			chba->ndev->name);
+}
+
+static inline __be32 cxgbi_get_iscsi_ipv4(struct cxgbi_hba *chba)
+{
+	return chba->ipv4addr;
+}
+
+struct cxgbi_device *cxgbi_device_register(unsigned int, unsigned int);
+void cxgbi_device_unregister(struct cxgbi_device *);
+void cxgbi_device_unregister_all(unsigned int flag);
+struct cxgbi_device *cxgbi_device_find_by_lldev(void *);
+int cxgbi_hbas_add(struct cxgbi_device *, unsigned int, unsigned int,
+			struct scsi_host_template *,
+			struct scsi_transport_template *);
+void cxgbi_hbas_remove(struct cxgbi_device *);
+
+int cxgbi_device_portmap_create(struct cxgbi_device *cdev, unsigned int base,
+			unsigned int max_conn);
+void cxgbi_device_portmap_cleanup(struct cxgbi_device *cdev);
+
+void cxgbi_conn_tx_open(struct cxgbi_sock *);
+void cxgbi_conn_pdu_ready(struct cxgbi_sock *);
+int cxgbi_conn_alloc_pdu(struct iscsi_task *, u8);
+int cxgbi_conn_init_pdu(struct iscsi_task *, unsigned int , unsigned int);
+int cxgbi_conn_xmit_pdu(struct iscsi_task *);
+
+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 *);
+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);
+void cxgbi_destroy_session(struct iscsi_cls_session *);
+struct iscsi_cls_session *cxgbi_create_session(struct iscsi_endpoint *,
+			u16, u16, u32);
+int cxgbi_set_host_param(struct Scsi_Host *,
+			enum iscsi_host_param, char *, int);
+int cxgbi_get_host_param(struct Scsi_Host *, enum iscsi_host_param, char *);
+struct iscsi_endpoint *cxgbi_ep_connect(struct Scsi_Host *,
+			struct sockaddr *, int);
+int cxgbi_ep_poll(struct iscsi_endpoint *, int);
+void cxgbi_ep_disconnect(struct iscsi_endpoint *);
+
+int cxgbi_iscsi_init(struct iscsi_transport *,
+			struct scsi_transport_template **);
+void cxgbi_iscsi_cleanup(struct iscsi_transport *,
+			struct scsi_transport_template **);
+void cxgbi_parse_pdu_itt(struct iscsi_conn *, itt_t, int *, int *);
+int cxgbi_ddp_init(struct cxgbi_device *, unsigned int, unsigned int,
+			unsigned int, unsigned int);
+int cxgbi_ddp_cleanup(struct cxgbi_device *);
+void cxgbi_ddp_page_size_factor(int *);
+void cxgbi_ddp_ppod_clear(struct cxgbi_pagepod *);
+void cxgbi_ddp_ppod_set(struct cxgbi_pagepod *, struct cxgbi_pagepod_hdr *,
+			struct cxgbi_gather_list *, unsigned int);
+#endif	/*__LIBCXGBI_H__*/
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 1a970a7..6b72932 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -1,7 +1,7 @@
 /*
  * Generic SCSI-3 ALUA SCSI Device Handler
  *
- * Copyright (C) 2007, 2008 Hannes Reinecke, SUSE Linux Products GmbH.
+ * Copyright (C) 2007-2010 Hannes Reinecke, SUSE Linux Products GmbH.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -20,17 +20,19 @@
  *
  */
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_dh.h>
 
 #define ALUA_DH_NAME "alua"
-#define ALUA_DH_VER "1.2"
+#define ALUA_DH_VER "1.3"
 
 #define TPGS_STATE_OPTIMIZED		0x0
 #define TPGS_STATE_NONOPTIMIZED		0x1
 #define TPGS_STATE_STANDBY		0x2
 #define TPGS_STATE_UNAVAILABLE		0x3
+#define TPGS_STATE_LBA_DEPENDENT	0x4
 #define TPGS_STATE_OFFLINE		0xe
 #define TPGS_STATE_TRANSITIONING	0xf
 
@@ -39,6 +41,7 @@
 #define TPGS_SUPPORT_NONOPTIMIZED	0x02
 #define TPGS_SUPPORT_STANDBY		0x04
 #define TPGS_SUPPORT_UNAVAILABLE	0x08
+#define TPGS_SUPPORT_LBA_DEPENDENT	0x10
 #define TPGS_SUPPORT_OFFLINE		0x40
 #define TPGS_SUPPORT_TRANSITION		0x80
 
@@ -460,6 +463,8 @@
 		return 'S';
 	case TPGS_STATE_UNAVAILABLE:
 		return 'U';
+	case TPGS_STATE_LBA_DEPENDENT:
+		return 'L';
 	case TPGS_STATE_OFFLINE:
 		return 'O';
 	case TPGS_STATE_TRANSITIONING:
@@ -542,7 +547,9 @@
 	int len, k, off, valid_states = 0;
 	char *ucp;
 	unsigned err;
+	unsigned long expiry, interval = 10;
 
+	expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT);
  retry:
 	err = submit_rtpg(sdev, h);
 
@@ -553,7 +560,7 @@
 			return SCSI_DH_IO;
 
 		err = alua_check_sense(sdev, &sense_hdr);
-		if (err == ADD_TO_MLQUEUE)
+		if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry))
 			goto retry;
 		sdev_printk(KERN_INFO, sdev,
 			    "%s: rtpg sense code %02x/%02x/%02x\n",
@@ -587,38 +594,37 @@
 	}
 
 	sdev_printk(KERN_INFO, sdev,
-		    "%s: port group %02x state %c supports %c%c%c%c%c%c\n",
+		    "%s: port group %02x state %c supports %c%c%c%c%c%c%c\n",
 		    ALUA_DH_NAME, h->group_id, print_alua_state(h->state),
 		    valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
 		    valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
+		    valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l',
 		    valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u',
 		    valid_states&TPGS_SUPPORT_STANDBY?'S':'s',
 		    valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n',
 		    valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a');
 
-	if (h->tpgs & TPGS_MODE_EXPLICIT) {
-		switch (h->state) {
-		case TPGS_STATE_TRANSITIONING:
+	switch (h->state) {
+	case TPGS_STATE_TRANSITIONING:
+		if (time_before(jiffies, expiry)) {
 			/* State transition, retry */
+			interval *= 10;
+			msleep(interval);
 			goto retry;
-			break;
-		case TPGS_STATE_OFFLINE:
-			/* Path is offline, fail */
-			err = SCSI_DH_DEV_OFFLINED;
-			break;
-		default:
-			break;
 		}
-	} else {
-		/* Only Implicit ALUA support */
-		if (h->state == TPGS_STATE_OPTIMIZED ||
-		    h->state == TPGS_STATE_NONOPTIMIZED ||
-		    h->state == TPGS_STATE_STANDBY)
-			/* Useable path if active */
-			err = SCSI_DH_OK;
-		else
-			/* Path unuseable for unavailable/offline */
-			err = SCSI_DH_DEV_OFFLINED;
+		/* Transitioning time exceeded, set port to standby */
+		err = SCSI_DH_RETRY;
+		h->state = TPGS_STATE_STANDBY;
+		break;
+	case TPGS_STATE_OFFLINE:
+	case TPGS_STATE_UNAVAILABLE:
+		/* Path unuseable for unavailable/offline */
+		err = SCSI_DH_DEV_OFFLINED;
+		break;
+	default:
+		/* Useable path if active */
+		err = SCSI_DH_OK;
+		break;
 	}
 	return err;
 }
@@ -672,7 +678,9 @@
 			goto out;
 	}
 
-	if (h->tpgs & TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED) {
+	if (h->tpgs & TPGS_MODE_EXPLICIT &&
+	    h->state != TPGS_STATE_OPTIMIZED &&
+	    h->state != TPGS_STATE_LBA_DEPENDENT) {
 		h->callback_fn = fn;
 		h->callback_data = data;
 		err = submit_stpg(h);
@@ -698,8 +706,11 @@
 	struct alua_dh_data *h = get_alua_data(sdev);
 	int ret = BLKPREP_OK;
 
-	if (h->state != TPGS_STATE_OPTIMIZED &&
-	    h->state != TPGS_STATE_NONOPTIMIZED) {
+	if (h->state == TPGS_STATE_TRANSITIONING)
+		ret = BLKPREP_DEFER;
+	else if (h->state != TPGS_STATE_OPTIMIZED &&
+		 h->state != TPGS_STATE_NONOPTIMIZED &&
+		 h->state != TPGS_STATE_LBA_DEPENDENT) {
 		ret = BLKPREP_KILL;
 		req->cmd_flags |= REQ_QUIET;
 	}
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index ffc1edf..23dec00 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -49,7 +49,6 @@
 #include <linux/kernel.h>	/* for printk */
 #include <linux/sched.h>
 #include <linux/reboot.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/dma-mapping.h>
 
@@ -76,6 +75,7 @@
  * Needed for our management apps
  *============================================================================
  */
+static DEFINE_MUTEX(adpt_mutex);
 static dpt_sig_S DPTI_sig = {
 	{'d', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION,
 #ifdef __i386__
@@ -126,6 +126,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= compat_adpt_ioctl,
 #endif
+	.llseek		= noop_llseek,
 };
 
 /* Structures and definitions for synchronous message posting.
@@ -1732,12 +1733,12 @@
 	int minor;
 	adpt_hba* pHba;
 
-	lock_kernel();
+	mutex_lock(&adpt_mutex);
 	//TODO check for root access
 	//
 	minor = iminor(inode);
 	if (minor >= hba_count) {
-		unlock_kernel();
+		mutex_unlock(&adpt_mutex);
 		return -ENXIO;
 	}
 	mutex_lock(&adpt_configuration_lock);
@@ -1748,7 +1749,7 @@
 	}
 	if (pHba == NULL) {
 		mutex_unlock(&adpt_configuration_lock);
-		unlock_kernel();
+		mutex_unlock(&adpt_mutex);
 		return -ENXIO;
 	}
 
@@ -1759,7 +1760,7 @@
 
 	pHba->in_use = 1;
 	mutex_unlock(&adpt_configuration_lock);
-	unlock_kernel();
+	mutex_unlock(&adpt_mutex);
 
 	return 0;
 }
@@ -2160,9 +2161,9 @@
  
 	inode = file->f_dentry->d_inode;
  
-	lock_kernel();
+	mutex_lock(&adpt_mutex);
 	ret = adpt_ioctl(inode, file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&adpt_mutex);
 
 	return ret;
 }
@@ -2176,7 +2177,7 @@
  
 	inode = file->f_dentry->d_inode;
  
-	lock_kernel();
+	mutex_lock(&adpt_mutex);
  
 	switch(cmd) {
 		case DPT_SIGNATURE:
@@ -2194,7 +2195,7 @@
 			ret =  -ENOIOCTLCMD;
 	}
  
-	unlock_kernel();
+	mutex_unlock(&adpt_mutex);
  
 	return ret;
 }
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 9eb7a9e..bb63f1a 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -80,8 +80,6 @@
 static int fnic_slave_alloc(struct scsi_device *sdev)
 {
 	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
-	struct fc_lport *lp = shost_priv(sdev->host);
-	struct fnic *fnic = lport_priv(lp);
 
 	sdev->tagged_supported = 1;
 
@@ -89,8 +87,6 @@
 		return -ENXIO;
 
 	scsi_activate_tcq(sdev, FNIC_DFLT_QUEUE_DEPTH);
-	rport->dev_loss_tmo = fnic->config.port_down_timeout / 1000;
-
 	return 0;
 }
 
@@ -113,6 +109,15 @@
 	.shost_attrs = fnic_attrs,
 };
 
+static void
+fnic_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
+{
+	if (timeout)
+		rport->dev_loss_tmo = timeout;
+	else
+		rport->dev_loss_tmo = 1;
+}
+
 static void fnic_get_host_speed(struct Scsi_Host *shost);
 static struct scsi_transport_template *fnic_fc_transport;
 static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *);
@@ -140,6 +145,7 @@
 	.show_starget_port_name = 1,
 	.show_starget_port_id = 1,
 	.show_rport_dev_loss_tmo = 1,
+	.set_rport_dev_loss_tmo = fnic_set_rport_dev_loss_tmo,
 	.issue_fc_host_lip = fnic_reset,
 	.get_fc_host_stats = fnic_get_stats,
 	.dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
@@ -706,6 +712,7 @@
 		goto err_out_free_exch_mgr;
 	}
 	fc_host_maxframe_size(lp->host) = lp->mfs;
+	fc_host_dev_loss_tmo(lp->host) = fnic->config.port_down_timeout / 1000;
 
 	sprintf(fc_host_symbolic_name(lp->host),
 		DRV_NAME " v" DRV_VERSION " over %s", fnic->name);
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index b860d65..5a3f931 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -120,7 +120,7 @@
 #include <linux/timer.h>
 #include <linux/dma-mapping.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #ifdef GDTH_RTC
@@ -140,6 +140,7 @@
 #include <scsi/scsi_host.h>
 #include "gdth.h"
 
+static DEFINE_MUTEX(gdth_mutex);
 static void gdth_delay(int milliseconds);
 static void gdth_eval_mapping(u32 size, u32 *cyls, int *heads, int *secs);
 static irqreturn_t gdth_interrupt(int irq, void *dev_id);
@@ -372,6 +373,7 @@
     .unlocked_ioctl   = gdth_unlocked_ioctl,
     .open    = gdth_open,
     .release = gdth_close,
+    .llseek = noop_llseek,
 };
 
 #include "gdth_proc.h"
@@ -4042,12 +4044,12 @@
 {
     gdth_ha_str *ha;
 
-    lock_kernel();
+    mutex_lock(&gdth_mutex);
     list_for_each_entry(ha, &gdth_instances, list) {
         if (!ha->sdev)
             ha->sdev = scsi_get_host_dev(ha->shost);
     }
-    unlock_kernel();
+    mutex_unlock(&gdth_mutex);
 
     TRACE(("gdth_open()\n"));
     return 0;
@@ -4615,9 +4617,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&gdth_mutex);
 	ret = gdth_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&gdth_mutex);
 
 	return ret;
 }
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 8a8f803..4f7a582 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -376,6 +376,7 @@
 	shost->this_id = sht->this_id;
 	shost->can_queue = sht->can_queue;
 	shost->sg_tablesize = sht->sg_tablesize;
+	shost->sg_prot_tablesize = sht->sg_prot_tablesize;
 	shost->cmd_per_lun = sht->cmd_per_lun;
 	shost->unchecked_isa_dma = sht->unchecked_isa_dma;
 	shost->use_clustering = sht->use_clustering;
@@ -411,9 +412,7 @@
 
 	device_initialize(&shost->shost_gendev);
 	dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
-#ifndef CONFIG_SYSFS_DEPRECATED
 	shost->shost_gendev.bus = &scsi_bus_type;
-#endif
 	shost->shost_gendev.type = &scsi_host_type;
 
 	device_initialize(&shost->shost_dev);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 9f75a6d..00d08b2 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -50,7 +50,6 @@
 static unsigned int max_targets = IBMVFC_MAX_TARGETS;
 static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT;
 static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS;
-static unsigned int dev_loss_tmo = IBMVFC_DEV_LOSS_TMO;
 static unsigned int ibmvfc_debug = IBMVFC_DEBUG;
 static unsigned int log_level = IBMVFC_DEFAULT_LOG_LEVEL;
 static LIST_HEAD(ibmvfc_head);
@@ -84,11 +83,6 @@
 module_param_named(debug, ibmvfc_debug, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Enable driver debug information. "
 		 "[Default=" __stringify(IBMVFC_DEBUG) "]");
-module_param_named(dev_loss_tmo, dev_loss_tmo, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(dev_loss_tmo, "Maximum number of seconds that the FC "
-		 "transport should insulate the loss of a remote port. Once this "
-		 "value is exceeded, the scsi target is removed. "
-		 "[Default=" __stringify(IBMVFC_DEV_LOSS_TMO) "]");
 module_param_named(log_level, log_level, uint, 0);
 MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver. "
 		 "[Default=" __stringify(IBMVFC_DEFAULT_LOG_LEVEL) "]");
@@ -2496,41 +2490,66 @@
 	LEAVE;
 }
 
-static const struct {
-	enum ibmvfc_async_event ae;
-	const char *desc;
-} ae_desc [] = {
-	{ IBMVFC_AE_ELS_PLOGI,		"PLOGI" },
-	{ IBMVFC_AE_ELS_LOGO,		"LOGO" },
-	{ IBMVFC_AE_ELS_PRLO,		"PRLO" },
-	{ IBMVFC_AE_SCN_NPORT,		"N-Port SCN" },
-	{ IBMVFC_AE_SCN_GROUP,		"Group SCN" },
-	{ IBMVFC_AE_SCN_DOMAIN,		"Domain SCN" },
-	{ IBMVFC_AE_SCN_FABRIC,		"Fabric SCN" },
-	{ IBMVFC_AE_LINK_UP,		"Link Up" },
-	{ IBMVFC_AE_LINK_DOWN,		"Link Down" },
-	{ IBMVFC_AE_LINK_DEAD,		"Link Dead" },
-	{ IBMVFC_AE_HALT,			"Halt" },
-	{ IBMVFC_AE_RESUME,		"Resume" },
-	{ IBMVFC_AE_ADAPTER_FAILED,	"Adapter Failed" },
+static const struct ibmvfc_async_desc ae_desc [] = {
+	{ IBMVFC_AE_ELS_PLOGI,		"PLOGI",		IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ IBMVFC_AE_ELS_LOGO,		"LOGO",		IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ IBMVFC_AE_ELS_PRLO,		"PRLO",		IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ IBMVFC_AE_SCN_NPORT,		"N-Port SCN",	IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ IBMVFC_AE_SCN_GROUP,		"Group SCN",	IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ IBMVFC_AE_SCN_DOMAIN,		"Domain SCN",	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_SCN_FABRIC,		"Fabric SCN",	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_LINK_UP,		"Link Up",		IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_LINK_DOWN,		"Link Down",	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_LINK_DEAD,		"Link Dead",	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_HALT,			"Halt",		IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_RESUME,		"Resume",		IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_ADAPTER_FAILED,	"Adapter Failed",	IBMVFC_DEFAULT_LOG_LEVEL },
 };
 
-static const char *unknown_ae = "Unknown async";
+static const struct ibmvfc_async_desc unknown_ae = {
+	0, "Unknown async", IBMVFC_DEFAULT_LOG_LEVEL
+};
 
 /**
  * ibmvfc_get_ae_desc - Get text description for async event
  * @ae:	async event
  *
  **/
-static const char *ibmvfc_get_ae_desc(u64 ae)
+static const struct ibmvfc_async_desc *ibmvfc_get_ae_desc(u64 ae)
 {
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(ae_desc); i++)
 		if (ae_desc[i].ae == ae)
-			return ae_desc[i].desc;
+			return &ae_desc[i];
 
-	return unknown_ae;
+	return &unknown_ae;
+}
+
+static const struct {
+	enum ibmvfc_ae_link_state state;
+	const char *desc;
+} link_desc [] = {
+	{ IBMVFC_AE_LS_LINK_UP,		" link up" },
+	{ IBMVFC_AE_LS_LINK_BOUNCED,	" link bounced" },
+	{ IBMVFC_AE_LS_LINK_DOWN,	" link down" },
+	{ IBMVFC_AE_LS_LINK_DEAD,	" link dead" },
+};
+
+/**
+ * ibmvfc_get_link_state - Get text description for link state
+ * @state:	link state
+ *
+ **/
+static const char *ibmvfc_get_link_state(enum ibmvfc_ae_link_state state)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(link_desc); i++)
+		if (link_desc[i].state == state)
+			return link_desc[i].desc;
+
+	return "";
 }
 
 /**
@@ -2542,11 +2561,12 @@
 static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
 				struct ibmvfc_host *vhost)
 {
-	const char *desc = ibmvfc_get_ae_desc(crq->event);
+	const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(crq->event);
 	struct ibmvfc_target *tgt;
 
-	ibmvfc_log(vhost, 3, "%s event received. scsi_id: %llx, wwpn: %llx,"
-		   " node_name: %llx\n", desc, crq->scsi_id, crq->wwpn, crq->node_name);
+	ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwpn: %llx,"
+		   " node_name: %llx%s\n", desc->desc, crq->scsi_id, crq->wwpn, crq->node_name,
+		   ibmvfc_get_link_state(crq->link_state));
 
 	switch (crq->event) {
 	case IBMVFC_AE_RESUME:
@@ -2788,7 +2808,6 @@
 static int ibmvfc_slave_configure(struct scsi_device *sdev)
 {
 	struct Scsi_Host *shost = sdev->host;
-	struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
 	unsigned long flags = 0;
 
 	spin_lock_irqsave(shost->host_lock, flags);
@@ -2800,8 +2819,6 @@
 		scsi_activate_tcq(sdev, sdev->queue_depth);
 	} else
 		scsi_deactivate_tcq(sdev, sdev->queue_depth);
-
-	rport->dev_loss_tmo = dev_loss_tmo;
 	spin_unlock_irqrestore(shost->host_lock, flags);
 	return 0;
 }
@@ -4285,8 +4302,10 @@
 		spin_unlock_irqrestore(vhost->host->host_lock, flags);
 		rc = ibmvfc_reset_crq(vhost);
 		spin_lock_irqsave(vhost->host->host_lock, flags);
-		if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
-		    (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
+		if (rc == H_CLOSED)
+			vio_enable_interrupts(to_vio_dev(vhost->dev));
+		else if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
+			 (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
 			ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
 			dev_err(vhost->dev, "Error after reset (rc=%d)\n", rc);
 		}
@@ -4744,6 +4763,8 @@
 	if ((rc = scsi_add_host(shost, dev)))
 		goto release_event_pool;
 
+	fc_host_dev_loss_tmo(shost) = IBMVFC_DEV_LOSS_TMO;
+
 	if ((rc = ibmvfc_create_trace_file(&shost->shost_dev.kobj,
 					   &ibmvfc_trace_attr))) {
 		dev_err(dev, "Failed to create trace file. rc=%d\n", rc);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 608af39..ef663e7 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -541,6 +541,12 @@
 	IBMVFC_AE_ADAPTER_FAILED	= 0x1000,
 };
 
+struct ibmvfc_async_desc {
+	enum ibmvfc_async_event ae;
+	const char *desc;
+	int log_level;
+};
+
 struct ibmvfc_crq {
 	volatile u8 valid;
 	volatile u8 format;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 5256858..df9a12c 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -1096,6 +1096,7 @@
 		res->bus = cfgtew->u.cfgte->res_addr.bus;
 		res->target = cfgtew->u.cfgte->res_addr.target;
 		res->lun = cfgtew->u.cfgte->res_addr.lun;
+		res->lun_wwn = get_unaligned_be64(cfgtew->u.cfgte->lun_wwn);
 	}
 
 	ipr_update_ata_class(res, proto);
@@ -1142,7 +1143,7 @@
 	int i;
 	char *p = buffer;
 
-	res_path[0] = '\0';
+	*p = '\0';
 	p += snprintf(p, buffer + len - p, "%02X", res_path[0]);
 	for (i = 1; res_path[i] != 0xff && ((i * 3) < len); i++)
 		p += snprintf(p, buffer + len - p, "-%02X", res_path[i]);
@@ -1670,7 +1671,7 @@
 
 	array_entry = error->array_member;
 	num_entries = min_t(u32, be32_to_cpu(error->num_entries),
-			    sizeof(error->array_member));
+			    ARRAY_SIZE(error->array_member));
 
 	for (i = 0; i < num_entries; i++, array_entry++) {
 		if (!memcmp(array_entry->vpd.vpd.sn, zero_sn, IPR_SERIAL_NUM_LEN))
@@ -2151,8 +2152,8 @@
 	ipr_err_separator;
 
 	array_entry = error->array_member;
-	num_entries = min_t(u32, be32_to_cpu(error->num_entries),
-			    sizeof(error->array_member));
+	num_entries = min_t(u32, error->num_entries,
+			    ARRAY_SIZE(error->array_member));
 
 	for (i = 0; i < num_entries; i++, array_entry++) {
 
@@ -2166,10 +2167,10 @@
 
 		ipr_err("Array Member %d:\n", i);
 		ipr_log_ext_vpd(&array_entry->vpd);
-		ipr_err("Current Location: %s",
+		ipr_err("Current Location: %s\n",
 			 ipr_format_res_path(array_entry->res_path, buffer,
 					     sizeof(buffer)));
-		ipr_err("Expected Location: %s",
+		ipr_err("Expected Location: %s\n",
 			 ipr_format_res_path(array_entry->expected_res_path,
 					     buffer, sizeof(buffer)));
 
@@ -4089,6 +4090,7 @@
 /**
  * ipr_show_adapter_handle - Show the adapter's resource handle for this device
  * @dev:	device struct
+ * @attr:	device attribute structure
  * @buf:	buffer
  *
  * Return value:
@@ -4122,6 +4124,7 @@
  * ipr_show_resource_path - Show the resource path or the resource address for
  *			    this device.
  * @dev:	device struct
+ * @attr:	device attribute structure
  * @buf:	buffer
  *
  * Return value:
@@ -4159,8 +4162,45 @@
 };
 
 /**
+ * ipr_show_device_id - Show the device_id for this device.
+ * @dev:	device struct
+ * @attr:	device attribute structure
+ * @buf:	buffer
+ *
+ * Return value:
+ *	number of bytes printed to buffer
+ **/
+static ssize_t ipr_show_device_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
+	struct ipr_resource_entry *res;
+	unsigned long lock_flags = 0;
+	ssize_t len = -ENXIO;
+
+	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+	res = (struct ipr_resource_entry *)sdev->hostdata;
+	if (res && ioa_cfg->sis64)
+		len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->dev_id);
+	else if (res)
+		len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->lun_wwn);
+
+	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+	return len;
+}
+
+static struct device_attribute ipr_device_id_attr = {
+	.attr = {
+		.name =		"device_id",
+		.mode =		S_IRUGO,
+	},
+	.show = ipr_show_device_id
+};
+
+/**
  * ipr_show_resource_type - Show the resource type for this device.
  * @dev:	device struct
+ * @attr:	device attribute structure
  * @buf:	buffer
  *
  * Return value:
@@ -4195,6 +4235,7 @@
 static struct device_attribute *ipr_dev_attrs[] = {
 	&ipr_adapter_handle_attr,
 	&ipr_resource_path_attr,
+	&ipr_device_id_attr,
 	&ipr_resource_type_attr,
 	NULL,
 };
@@ -4898,39 +4939,15 @@
 /**
  * ipr_handle_other_interrupt - Handle "other" interrupts
  * @ioa_cfg:	ioa config struct
+ * @int_reg:	interrupt register
  *
  * Return value:
  * 	IRQ_NONE / IRQ_HANDLED
  **/
-static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg)
+static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg,
+					      volatile u32 int_reg)
 {
 	irqreturn_t rc = IRQ_HANDLED;
-	volatile u32 int_reg, int_mask_reg;
-
-	int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
-	int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
-
-	/* If an interrupt on the adapter did not occur, ignore it.
-	 * Or in the case of SIS 64, check for a stage change interrupt.
-	 */
-	if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) {
-		if (ioa_cfg->sis64) {
-			int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
-			int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
-			if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
-
-				/* clear stage change */
-				writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
-				int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
-				list_del(&ioa_cfg->reset_cmd->queue);
-				del_timer(&ioa_cfg->reset_cmd->timer);
-				ipr_reset_ioa_job(ioa_cfg->reset_cmd);
-				return IRQ_HANDLED;
-			}
-		}
-
-		return IRQ_NONE;
-	}
 
 	if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) {
 		/* Mask the interrupt */
@@ -4991,7 +5008,7 @@
 {
 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
 	unsigned long lock_flags = 0;
-	volatile u32 int_reg;
+	volatile u32 int_reg, int_mask_reg;
 	u32 ioasc;
 	u16 cmd_index;
 	int num_hrrq = 0;
@@ -5006,6 +5023,33 @@
 		return IRQ_NONE;
 	}
 
+	int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
+	int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
+
+	/* If an interrupt on the adapter did not occur, ignore it.
+	 * Or in the case of SIS 64, check for a stage change interrupt.
+	 */
+	if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) {
+		if (ioa_cfg->sis64) {
+			int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
+			int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
+			if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
+
+				/* clear stage change */
+				writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
+				int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
+				list_del(&ioa_cfg->reset_cmd->queue);
+				del_timer(&ioa_cfg->reset_cmd->timer);
+				ipr_reset_ioa_job(ioa_cfg->reset_cmd);
+				spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+				return IRQ_HANDLED;
+			}
+		}
+
+		spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+		return IRQ_NONE;
+	}
+
 	while (1) {
 		ipr_cmd = NULL;
 
@@ -5045,7 +5089,7 @@
 			/* Clear the PCI interrupt */
 			do {
 				writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
-				int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
+				int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
 			} while (int_reg & IPR_PCII_HRRQ_UPDATED &&
 					num_hrrq++ < IPR_MAX_HRRQ_RETRIES);
 
@@ -5060,7 +5104,7 @@
 	}
 
 	if (unlikely(rc == IRQ_NONE))
-		rc = ipr_handle_other_interrupt(ioa_cfg);
+		rc = ipr_handle_other_interrupt(ioa_cfg, int_reg);
 
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 	return rc;
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 4d31625..aa8bb2f 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -26,6 +26,7 @@
 #ifndef _IPR_H
 #define _IPR_H
 
+#include <asm/unaligned.h>
 #include <linux/types.h>
 #include <linux/completion.h>
 #include <linux/libata.h>
@@ -37,8 +38,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.5.0"
-#define IPR_DRIVER_DATE "(February 11, 2010)"
+#define IPR_DRIVER_VERSION "2.5.1"
+#define IPR_DRIVER_DATE "(August 10, 2010)"
 
 /*
  * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -318,6 +319,11 @@
 	__be32 wwid[2];
 }__attribute__((packed));
 
+struct ipr_ext_vpd64 {
+	struct ipr_vpd vpd;
+	__be32 wwid[4];
+}__attribute__((packed));
+
 struct ipr_std_inq_data {
 	u8 peri_qual_dev_type;
 #define IPR_STD_INQ_PERI_QUAL(peri) ((peri) >> 5)
@@ -372,7 +378,7 @@
 
 	struct ipr_res_addr res_addr;
 	__be32 res_handle;
-	__be32 reserved4[2];
+	__be32 lun_wwn[2];
 	struct ipr_std_inq_data std_inq_data;
 }__attribute__ ((packed, aligned (4)));
 
@@ -394,7 +400,7 @@
 	__be64 res_path;
 	struct ipr_std_inq_data std_inq_data;
 	u8 reserved2[4];
-	__be64 reserved3[2]; // description text
+	__be64 reserved3[2];
 	u8 reserved4[8];
 }__attribute__ ((packed, aligned (8)));
 
@@ -913,7 +919,7 @@
 	u8 array_id;
 	u8 last_res_path[8];
 	u8 protection_level[8];
-	struct ipr_ext_vpd array_vpd;
+	struct ipr_ext_vpd64 array_vpd;
 	u8 description[16];
 	u8 reserved2[3];
 	u8 num_entries;
@@ -1210,6 +1216,7 @@
 
 	__be32 res_handle;
 	__be64 dev_id;
+	__be64 lun_wwn;
 	struct scsi_lun dev_lun;
 	u8 res_path[8];
 
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 042153c..e1a395b 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -162,6 +162,10 @@
 	unsigned int xfer = 0;
 	unsigned int si;
 
+	/* If the device fell off, no sense in issuing commands */
+	if (dev->gone)
+		return AC_ERR_SYSTEM;
+
 	task = sas_alloc_task(GFP_ATOMIC);
 	if (!task)
 		return AC_ERR_SYSTEM;
@@ -347,6 +351,7 @@
 static struct ata_port_operations sas_sata_ops = {
 	.phy_reset		= sas_ata_phy_reset,
 	.post_internal_cmd	= sas_ata_post_internal,
+	.qc_defer               = ata_std_qc_defer,
 	.qc_prep		= ata_noop_qc_prep,
 	.qc_issue		= sas_ata_qc_issue,
 	.qc_fill_rtf		= sas_ata_qc_fill_rtf,
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 83dd507..505ffe3 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -175,10 +175,10 @@
 	switch (resp->result) {
 	case SMP_RESP_PHY_VACANT:
 		phy->phy_state = PHY_VACANT;
-		return;
+		break;
 	default:
 		phy->phy_state = PHY_NOT_PRESENT;
-		return;
+		break;
 	case SMP_RESP_FUNC_ACC:
 		phy->phy_state = PHY_EMPTY; /* do not know yet */
 		break;
@@ -209,7 +209,10 @@
 	phy->phy->negotiated_linkrate = phy->linkrate;
 
 	if (!rediscover)
-		sas_phy_add(phy->phy);
+		if (sas_phy_add(phy->phy)) {
+			sas_phy_free(phy->phy);
+			return;
+		}
 
 	SAS_DPRINTK("ex %016llx phy%02d:%c attached: %016llx\n",
 		    SAS_ADDR(dev->sas_addr), phy->phy_id,
@@ -1724,6 +1727,7 @@
 	struct domain_device *child, *n;
 
 	list_for_each_entry_safe(child, n, &ex->children, siblings) {
+		child->gone = 1;
 		if (child->dev_type == EDGE_DEV ||
 		    child->dev_type == FANOUT_DEV)
 			sas_unregister_ex_tree(child);
@@ -1744,6 +1748,7 @@
 			&ex_dev->children, siblings) {
 			if (SAS_ADDR(child->sas_addr) ==
 			    SAS_ADDR(phy->attached_sas_addr)) {
+				child->gone = 1;
 				if (child->dev_type == EDGE_DEV ||
 				    child->dev_type == FANOUT_DEV)
 					sas_unregister_ex_tree(child);
@@ -1752,6 +1757,7 @@
 				break;
 			}
 		}
+		parent->gone = 1;
 		sas_disable_routing(parent, phy->attached_sas_addr);
 	}
 	memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index f0cfba9..55f09e9 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -130,17 +130,6 @@
 	sc->scsi_done(sc);
 }
 
-static enum task_attribute sas_scsi_get_task_attr(struct scsi_cmnd *cmd)
-{
-	enum task_attribute ta = TASK_ATTR_SIMPLE;
-	if (cmd->request && blk_rq_tagged(cmd->request)) {
-		if (cmd->device->ordered_tags &&
-		    (cmd->request->cmd_flags & REQ_HARDBARRIER))
-			ta = TASK_ATTR_ORDERED;
-	}
-	return ta;
-}
-
 static struct sas_task *sas_create_task(struct scsi_cmnd *cmd,
 					       struct domain_device *dev,
 					       gfp_t gfp_flags)
@@ -160,7 +149,7 @@
 	task->ssp_task.retry_count = 1;
 	int_to_scsilun(cmd->device->lun, &lun);
 	memcpy(task->ssp_task.LUN, &lun.scsi_lun, 8);
-	task->ssp_task.task_attr = sas_scsi_get_task_attr(cmd);
+	task->ssp_task.task_attr = TASK_ATTR_SIMPLE;
 	memcpy(task->ssp_task.cdb, cmd->cmnd, 16);
 
 	task->scatter = scsi_sglist(cmd);
@@ -228,6 +217,13 @@
 			goto out;
 		}
 
+		/* If the device fell off, no sense in issuing commands */
+		if (dev->gone) {
+			cmd->result = DID_BAD_TARGET << 16;
+			scsi_done(cmd);
+			goto out;
+		}
+
 		res = -ENOMEM;
 		task = sas_create_task(cmd, dev, GFP_ATOMIC);
 		if (!task)
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 23ce457..f681eea 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -586,6 +586,11 @@
 			       phba->cfg_link_speed);
 		mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq,
 						     phba->fc_ratov * 2);
+		if ((mbxstatus == MBX_SUCCESS) &&
+		    (pmboxq->u.mb.mbxStatus == MBXERR_SEC_NO_PERMISSION))
+			lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+					"2859 SLI authentication is required "
+					"for INIT_LINK but has not done yet\n");
 	}
 
 	lpfc_set_loopback_flag(phba);
@@ -2159,6 +2164,11 @@
 	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
 		vport->cfg_nodev_tmo = val;
 		vport->cfg_devloss_tmo = val;
+		/*
+		 * For compat: set the fc_host dev loss so new rports
+		 * will get the value.
+		 */
+		fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
 		lpfc_update_rport_devloss_tmo(vport);
 		return 0;
 	}
@@ -2208,6 +2218,7 @@
 		vport->cfg_nodev_tmo = val;
 		vport->cfg_devloss_tmo = val;
 		vport->dev_loss_tmo_changed = 1;
+		fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
 		lpfc_update_rport_devloss_tmo(vport);
 		return 0;
 	}
@@ -3776,6 +3787,11 @@
 		case MBX_PORT_CAPABILITIES:
 		case MBX_PORT_IOV_CONTROL:
 			break;
+		case MBX_SECURITY_MGMT:
+		case MBX_AUTH_PORT:
+			if (phba->pci_dev_grp == LPFC_PCI_DEV_OC)
+				return -EPERM;
+			break;
 		case MBX_READ_SPARM64:
 		case MBX_READ_LA:
 		case MBX_READ_LA64:
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 49d0cf9..f5d60b5 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -259,6 +259,7 @@
 	struct bsg_job_data *dd_data;
 	uint32_t creg_val;
 	int rc = 0;
+	int iocb_stat;
 
 	/* in case no data is transferred */
 	job->reply->reply_payload_rcv_len = 0;
@@ -373,14 +374,13 @@
 		readl(phba->HCregaddr); /* flush */
 	}
 
-	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
-
-	if (rc == IOCB_SUCCESS)
+	iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
+	if (iocb_stat == IOCB_SUCCESS)
 		return 0; /* done for now */
-	else if (rc == IOCB_BUSY)
-		rc = EAGAIN;
+	else if (iocb_stat == IOCB_BUSY)
+		rc = -EAGAIN;
 	else
-		rc = EIO;
+		rc = -EIO;
 
 
 	/* iocb failed so cleanup */
@@ -631,9 +631,9 @@
 	if (rc == IOCB_SUCCESS)
 		return 0; /* done for now */
 	else if (rc == IOCB_BUSY)
-		rc = EAGAIN;
+		rc = -EAGAIN;
 	else
-		rc = EIO;
+		rc = -EIO;
 
 	pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
 		     job->request_payload.sg_cnt, DMA_TO_DEVICE);
@@ -1299,7 +1299,7 @@
 	/* Allocate buffer for  command iocb */
 	ctiocb = lpfc_sli_get_iocbq(phba);
 	if (!ctiocb) {
-		rc = ENOMEM;
+		rc = -ENOMEM;
 		goto no_ctiocb;
 	}
 
@@ -1518,7 +1518,7 @@
 	loopback_mode = (struct diag_mode_set *)
 		job->request->rqst_data.h_vendor.vendor_cmd;
 	link_flags = loopback_mode->type;
-	timeout = loopback_mode->timeout;
+	timeout = loopback_mode->timeout * 100;
 
 	if ((phba->link_state == LPFC_HBA_ERROR) ||
 	    (psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||
@@ -1649,17 +1649,18 @@
 
 	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (!mbox)
-		return ENOMEM;
+		return -ENOMEM;
 
 	status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID,
 				(uint8_t *)&phba->pport->fc_sparam, mbox, 0);
 	if (status) {
 		mempool_free(mbox, phba->mbox_mem_pool);
-		return ENOMEM;
+		return -ENOMEM;
 	}
 
 	dmabuff = (struct lpfc_dmabuf *) mbox->context1;
 	mbox->context1 = NULL;
+	mbox->context2 = NULL;
 	status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
 
 	if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {
@@ -1667,7 +1668,7 @@
 		kfree(dmabuff);
 		if (status != MBX_TIMEOUT)
 			mempool_free(mbox, phba->mbox_mem_pool);
-		return ENODEV;
+		return -ENODEV;
 	}
 
 	*rpi = mbox->u.mb.un.varWords[0];
@@ -1693,7 +1694,7 @@
 	/* Allocate mboxq structure */
 	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (mbox == NULL)
-		return ENOMEM;
+		return -ENOMEM;
 
 	lpfc_unreg_login(phba, 0, rpi, mbox);
 	status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
@@ -1701,7 +1702,7 @@
 	if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {
 		if (status != MBX_TIMEOUT)
 			mempool_free(mbox, phba->mbox_mem_pool);
-		return EIO;
+		return -EIO;
 	}
 
 	mempool_free(mbox, phba->mbox_mem_pool);
@@ -1730,6 +1731,8 @@
 	struct ulp_bde64 *bpl = NULL;
 	struct lpfc_sli_ct_request *ctreq = NULL;
 	int ret_val = 0;
+	int time_left;
+	int iocb_stat = 0;
 	unsigned long flags;
 
 	*txxri = 0;
@@ -1737,7 +1740,7 @@
 	evt = lpfc_bsg_event_new(FC_REG_CT_EVENT, current->pid,
 				SLI_CT_ELX_LOOPBACK);
 	if (!evt)
-		return ENOMEM;
+		return -ENOMEM;
 
 	spin_lock_irqsave(&phba->ct_ev_lock, flags);
 	list_add(&evt->node, &phba->ct_ev_waiters);
@@ -1770,7 +1773,7 @@
 	if (cmdiocbq == NULL || rspiocbq == NULL ||
 	    dmabuf == NULL || bpl == NULL || ctreq == NULL ||
 		dmabuf->virt == NULL) {
-		ret_val = ENOMEM;
+		ret_val = -ENOMEM;
 		goto err_get_xri_exit;
 	}
 
@@ -1806,24 +1809,24 @@
 	cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
 	cmdiocbq->vport = phba->pport;
 
-	ret_val = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
+	iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
 				rspiocbq,
 				(phba->fc_ratov * 2)
 				+ LPFC_DRVR_TIMEOUT);
-	if (ret_val)
+	if (iocb_stat) {
+		ret_val = -EIO;
 		goto err_get_xri_exit;
-
+	}
 	*txxri =  rsp->ulpContext;
 
 	evt->waiting = 1;
 	evt->wait_time_stamp = jiffies;
-	ret_val = wait_event_interruptible_timeout(
+	time_left = wait_event_interruptible_timeout(
 		evt->wq, !list_empty(&evt->events_to_see),
 		((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ);
 	if (list_empty(&evt->events_to_see))
-		ret_val = (ret_val) ? EINTR : ETIMEDOUT;
+		ret_val = (time_left) ? -EINTR : -ETIMEDOUT;
 	else {
-		ret_val = IOCB_SUCCESS;
 		spin_lock_irqsave(&phba->ct_ev_lock, flags);
 		list_move(evt->events_to_see.prev, &evt->events_to_get);
 		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
@@ -1845,7 +1848,7 @@
 		kfree(dmabuf);
 	}
 
-	if (cmdiocbq && (ret_val != IOCB_TIMEDOUT))
+	if (cmdiocbq && (iocb_stat != IOCB_TIMEDOUT))
 		lpfc_sli_release_iocbq(phba, cmdiocbq);
 	if (rspiocbq)
 		lpfc_sli_release_iocbq(phba, rspiocbq);
@@ -1959,6 +1962,7 @@
 	uint32_t num_bde;
 	struct lpfc_dmabufext *rxbuffer = NULL;
 	int ret_val = 0;
+	int iocb_stat;
 	int i = 0;
 
 	cmdiocbq = lpfc_sli_get_iocbq(phba);
@@ -1973,7 +1977,7 @@
 	}
 
 	if (!cmdiocbq || !rxbmp || !rxbpl || !rxbuffer) {
-		ret_val = ENOMEM;
+		ret_val = -ENOMEM;
 		goto err_post_rxbufs_exit;
 	}
 
@@ -2022,16 +2026,16 @@
 		cmd->ulpClass = CLASS3;
 		cmd->ulpContext = rxxri;
 
-		ret_val = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
-
-		if (ret_val == IOCB_ERROR) {
+		iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq,
+						0);
+		if (iocb_stat == IOCB_ERROR) {
 			diag_cmd_data_free(phba,
 				(struct lpfc_dmabufext *)mp[0]);
 			if (mp[1])
 				diag_cmd_data_free(phba,
 					  (struct lpfc_dmabufext *)mp[1]);
 			dmp = list_entry(next, struct lpfc_dmabuf, list);
-			ret_val = EIO;
+			ret_val = -EIO;
 			goto err_post_rxbufs_exit;
 		}
 
@@ -2045,7 +2049,7 @@
 		cmdiocbq = lpfc_sli_get_iocbq(phba);
 		if (!cmdiocbq) {
 			dmp = list_entry(next, struct lpfc_dmabuf, list);
-			ret_val = EIO;
+			ret_val = -EIO;
 			goto err_post_rxbufs_exit;
 		}
 
@@ -2111,6 +2115,8 @@
 	uint32_t num_bde;
 	uint8_t *ptr = NULL, *rx_databuf = NULL;
 	int rc = 0;
+	int time_left;
+	int iocb_stat;
 	unsigned long flags;
 	void *dataout = NULL;
 	uint32_t total_mem;
@@ -2185,22 +2191,18 @@
 				ptr, size);
 
 	rc = lpfcdiag_loop_self_reg(phba, &rpi);
-	if (rc) {
-		rc = -ENOMEM;
+	if (rc)
 		goto loopback_test_exit;
-	}
 
 	rc = lpfcdiag_loop_get_xri(phba, rpi, &txxri, &rxxri);
 	if (rc) {
 		lpfcdiag_loop_self_unreg(phba, rpi);
-		rc = -ENOMEM;
 		goto loopback_test_exit;
 	}
 
 	rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size);
 	if (rc) {
 		lpfcdiag_loop_self_unreg(phba, rpi);
-		rc = -ENOMEM;
 		goto loopback_test_exit;
 	}
 
@@ -2290,21 +2292,22 @@
 	cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
 	cmdiocbq->vport = phba->pport;
 
-	rc = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, rspiocbq,
-				      (phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT);
+	iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
+					     rspiocbq, (phba->fc_ratov * 2) +
+					     LPFC_DRVR_TIMEOUT);
 
-	if ((rc != IOCB_SUCCESS) || (rsp->ulpStatus != IOCB_SUCCESS)) {
+	if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOCB_SUCCESS)) {
 		rc = -EIO;
 		goto err_loopback_test_exit;
 	}
 
 	evt->waiting = 1;
-	rc = wait_event_interruptible_timeout(
+	time_left = wait_event_interruptible_timeout(
 		evt->wq, !list_empty(&evt->events_to_see),
 		((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ);
 	evt->waiting = 0;
 	if (list_empty(&evt->events_to_see))
-		rc = (rc) ? -EINTR : -ETIMEDOUT;
+		rc = (time_left) ? -EINTR : -ETIMEDOUT;
 	else {
 		spin_lock_irqsave(&phba->ct_ev_lock, flags);
 		list_move(evt->events_to_see.prev, &evt->events_to_get);
@@ -2470,6 +2473,17 @@
 			to += sizeof(MAILBOX_t);
 			size = pmboxq->u.mb.un.varWords[5];
 			memcpy(to, from, size);
+		} else if ((phba->sli_rev == LPFC_SLI_REV4) &&
+			(pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) {
+			struct lpfc_mbx_nembed_cmd *nembed_sge =
+				(struct lpfc_mbx_nembed_cmd *)
+				&pmboxq->u.mb.un.varWords[0];
+
+			from = (uint8_t *)dd_data->context_un.mbox.dmp->dma.
+						virt;
+			to += sizeof(MAILBOX_t);
+			size = nembed_sge->sge[0].length;
+			memcpy(to, from, size);
 		} else if (pmboxq->u.mb.mbxCommand == MBX_READ_EVENT_LOG) {
 			from = (uint8_t *)dd_data->context_un.
 						mbox.dmp->dma.virt;
@@ -2911,6 +2925,59 @@
 			from += sizeof(MAILBOX_t);
 			memcpy((uint8_t *)dmp->dma.virt, from,
 				bde->tus.f.bdeSize);
+		} else if (pmb->mbxCommand == MBX_SLI4_CONFIG) {
+			struct lpfc_mbx_nembed_cmd *nembed_sge;
+			struct mbox_header *header;
+			uint32_t receive_length;
+
+			/* rebuild the command for sli4 using our own buffers
+			* like we do for biu diags
+			*/
+			header = (struct mbox_header *)&pmb->un.varWords[0];
+			nembed_sge = (struct lpfc_mbx_nembed_cmd *)
+				&pmb->un.varWords[0];
+			receive_length = nembed_sge->sge[0].length;
+
+			/* receive length cannot be greater than mailbox
+			 * extension size
+			 */
+			if ((receive_length == 0) ||
+				(receive_length > MAILBOX_EXT_SIZE)) {
+				rc = -ERANGE;
+				goto job_done;
+			}
+
+			rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
+			if (!rxbmp) {
+				rc = -ENOMEM;
+				goto job_done;
+			}
+
+			rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);
+			if (!rxbmp->virt) {
+				rc = -ENOMEM;
+				goto job_done;
+			}
+
+			INIT_LIST_HEAD(&rxbmp->list);
+			rxbpl = (struct ulp_bde64 *) rxbmp->virt;
+			dmp = diag_cmd_data_alloc(phba, rxbpl, receive_length,
+						0);
+			if (!dmp) {
+				rc = -ENOMEM;
+				goto job_done;
+			}
+
+			INIT_LIST_HEAD(&dmp->dma.list);
+			nembed_sge->sge[0].pa_hi = putPaddrHigh(dmp->dma.phys);
+			nembed_sge->sge[0].pa_lo = putPaddrLow(dmp->dma.phys);
+			/* copy the transmit data found in the mailbox
+			 * extension area
+			 */
+			from = (uint8_t *)mb;
+			from += sizeof(MAILBOX_t);
+			memcpy((uint8_t *)dmp->dma.virt, from,
+				header->cfg_mhdr.payload_length);
 		}
 	}
 
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 8d09191..e6ca12f 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3250,6 +3250,8 @@
 		lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi);
 
 	pmb->context1 = NULL;
+	pmb->context2 = NULL;
+
 	lpfc_mbuf_free(phba, mp->virt, mp->phys);
 	kfree(mp);
 	mempool_free(pmb, phba->mbox_mem_pool);
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 1f62ea8..c3d7174 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1015,7 +1015,6 @@
 lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 {
 	struct lpfc_vport *vport = mboxq->vport;
-	unsigned long flags;
 
 	if (mboxq->u.mb.mbxStatus) {
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
@@ -1029,18 +1028,18 @@
 	/* Start FCoE discovery by sending a FLOGI. */
 	phba->fcf.fcfi = bf_get(lpfc_reg_fcfi_fcfi, &mboxq->u.mqe.un.reg_fcfi);
 	/* Set the FCFI registered flag */
-	spin_lock_irqsave(&phba->hbalock, flags);
+	spin_lock_irq(&phba->hbalock);
 	phba->fcf.fcf_flag |= FCF_REGISTERED;
-	spin_unlock_irqrestore(&phba->hbalock, flags);
+	spin_unlock_irq(&phba->hbalock);
 	/* If there is a pending FCoE event, restart FCF table scan. */
 	if (lpfc_check_pending_fcoe_event(phba, 1)) {
 		mempool_free(mboxq, phba->mbox_mem_pool);
 		return;
 	}
-	spin_lock_irqsave(&phba->hbalock, flags);
+	spin_lock_irq(&phba->hbalock);
 	phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE);
 	phba->hba_flag &= ~FCF_DISC_INPROGRESS;
-	spin_unlock_irqrestore(&phba->hbalock, flags);
+	spin_unlock_irq(&phba->hbalock);
 	if (vport->port_state != LPFC_FLOGI)
 		lpfc_initial_flogi(vport);
 
@@ -1240,14 +1239,13 @@
 {
 	LPFC_MBOXQ_t *fcf_mbxq;
 	int rc;
-	unsigned long flags;
 
-	spin_lock_irqsave(&phba->hbalock, flags);
+	spin_lock_irq(&phba->hbalock);
 
 	/* If the FCF is not availabe do nothing. */
 	if (!(phba->fcf.fcf_flag & FCF_AVAILABLE)) {
 		phba->hba_flag &= ~FCF_DISC_INPROGRESS;
-		spin_unlock_irqrestore(&phba->hbalock, flags);
+		spin_unlock_irq(&phba->hbalock);
 		return;
 	}
 
@@ -1255,19 +1253,19 @@
 	if (phba->fcf.fcf_flag & FCF_REGISTERED) {
 		phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE);
 		phba->hba_flag &= ~FCF_DISC_INPROGRESS;
-		spin_unlock_irqrestore(&phba->hbalock, flags);
+		spin_unlock_irq(&phba->hbalock);
 		if (phba->pport->port_state != LPFC_FLOGI)
 			lpfc_initial_flogi(phba->pport);
 		return;
 	}
-	spin_unlock_irqrestore(&phba->hbalock, flags);
+	spin_unlock_irq(&phba->hbalock);
 
 	fcf_mbxq = mempool_alloc(phba->mbox_mem_pool,
 		GFP_KERNEL);
 	if (!fcf_mbxq) {
-		spin_lock_irqsave(&phba->hbalock, flags);
+		spin_lock_irq(&phba->hbalock);
 		phba->hba_flag &= ~FCF_DISC_INPROGRESS;
-		spin_unlock_irqrestore(&phba->hbalock, flags);
+		spin_unlock_irq(&phba->hbalock);
 		return;
 	}
 
@@ -1276,9 +1274,9 @@
 	fcf_mbxq->mbox_cmpl = lpfc_mbx_cmpl_reg_fcfi;
 	rc = lpfc_sli_issue_mbox(phba, fcf_mbxq, MBX_NOWAIT);
 	if (rc == MBX_NOT_FINISHED) {
-		spin_lock_irqsave(&phba->hbalock, flags);
+		spin_lock_irq(&phba->hbalock);
 		phba->hba_flag &= ~FCF_DISC_INPROGRESS;
-		spin_unlock_irqrestore(&phba->hbalock, flags);
+		spin_unlock_irq(&phba->hbalock);
 		mempool_free(fcf_mbxq, phba->mbox_mem_pool);
 	}
 
@@ -2851,6 +2849,7 @@
 	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 
 	pmb->context1 = NULL;
+	pmb->context2 = NULL;
 
 	if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
 		ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
@@ -3149,6 +3148,7 @@
 	ndlp = (struct lpfc_nodelist *) pmb->context2;
 	pmb->context1 = NULL;
 	pmb->context2 = NULL;
+
 	if (mb->mbxStatus) {
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
 				 "0258 Register Fabric login error: 0x%x\n",
@@ -3218,6 +3218,9 @@
 	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
 	struct lpfc_vport *vport = pmb->vport;
 
+	pmb->context1 = NULL;
+	pmb->context2 = NULL;
+
 	if (mb->mbxStatus) {
 out:
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
@@ -3249,8 +3252,6 @@
 		return;
 	}
 
-	pmb->context1 = NULL;
-
 	ndlp->nlp_rpi = mb->un.varWords[0];
 	ndlp->nlp_flag |= NLP_RPI_VALID;
 	ndlp->nlp_type |= NLP_FABRIC;
@@ -4784,6 +4785,7 @@
 	struct lpfc_vport    *vport = pmb->vport;
 
 	pmb->context1 = NULL;
+	pmb->context2 = NULL;
 
 	ndlp->nlp_rpi = mb->un.varWords[0];
 	ndlp->nlp_flag |= NLP_RPI_VALID;
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 1676f61..a631647 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1380,6 +1380,9 @@
 #define MBX_INIT_VFI        0xA3
 #define MBX_INIT_VPI        0xA4
 
+#define MBX_AUTH_PORT       0xF8
+#define MBX_SECURITY_MGMT   0xF9
+
 /* IOCB Commands */
 
 #define CMD_RCV_SEQUENCE_CX     0x01
@@ -1502,7 +1505,8 @@
 #define MBXERR_DMA_ERROR            15
 #define MBXERR_ERROR                16
 #define MBXERR_LINK_DOWN            0x33
-#define MBX_NOT_FINISHED           255
+#define MBXERR_SEC_NO_PERMISSION    0xF02
+#define MBX_NOT_FINISHED            255
 
 #define MBX_BUSY                   0xffffff /* Attempted cmd to busy Mailbox */
 #define MBX_TIMEOUT                0xfffffe /* time-out expired waiting for */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index da9ba06..295c7dd 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1076,21 +1076,16 @@
 		} else {
 			/*
 			* If heart beat timeout called with hb_outstanding set
-			* we need to take the HBA offline.
+			* we need to give the hb mailbox cmd a chance to
+			* complete or TMO.
 			*/
-			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-					"0459 Adapter heartbeat failure, "
-					"taking this port offline.\n");
-
-			spin_lock_irq(&phba->hbalock);
-			psli->sli_flag &= ~LPFC_SLI_ACTIVE;
-			spin_unlock_irq(&phba->hbalock);
-
-			lpfc_offline_prep(phba);
-			lpfc_offline(phba);
-			lpfc_unblock_mgmt_io(phba);
-			phba->link_state = LPFC_HBA_ERROR;
-			lpfc_hba_down_post(phba);
+			lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
+					"0459 Adapter heartbeat still out"
+					"standing:last compl time was %d ms.\n",
+					jiffies_to_msecs(jiffies
+						 - phba->last_completion_time));
+			mod_timer(&phba->hb_tmofunc,
+				  jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
 		}
 	}
 }
@@ -1277,13 +1272,21 @@
 	if (phba->hba_flag & DEFER_ERATT)
 		lpfc_handle_deferred_eratt(phba);
 
-	if (phba->work_hs & HS_FFER6) {
-		/* Re-establishing Link */
-		lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
-				"1301 Re-establishing Link "
-				"Data: x%x x%x x%x\n",
-				phba->work_hs,
-				phba->work_status[0], phba->work_status[1]);
+	if ((phba->work_hs & HS_FFER6) || (phba->work_hs & HS_FFER8)) {
+		if (phba->work_hs & HS_FFER6)
+			/* Re-establishing Link */
+			lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
+					"1301 Re-establishing Link "
+					"Data: x%x x%x x%x\n",
+					phba->work_hs, phba->work_status[0],
+					phba->work_status[1]);
+		if (phba->work_hs & HS_FFER8)
+			/* Device Zeroization */
+			lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
+					"2861 Host Authentication device "
+					"zeroization Data:x%x x%x x%x\n",
+					phba->work_hs, phba->work_status[0],
+					phba->work_status[1]);
 
 		spin_lock_irq(&phba->hbalock);
 		psli->sli_flag &= ~LPFC_SLI_ACTIVE;
@@ -2817,6 +2820,8 @@
 		(((uint32_t) vport->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
 		(uint32_t) vport->fc_sparam.cmn.bbRcvSizeLsb;
 
+	fc_host_dev_loss_tmo(shost) = vport->cfg_devloss_tmo;
+
 	/* This value is also unchanging */
 	memset(fc_host_active_fc4s(shost), 0,
 	       sizeof(fc_host_active_fc4s(shost)));
@@ -2883,65 +2888,6 @@
 }
 
 /**
- * lpfc_sli4_remove_dflt_fcf - Remove the driver default fcf record from the port.
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine is invoked to remove the driver default fcf record from
- * the port.  This routine currently acts on FCF Index 0.
- *
- **/
-void
-lpfc_sli_remove_dflt_fcf(struct lpfc_hba *phba)
-{
-	int rc = 0;
-	LPFC_MBOXQ_t *mboxq;
-	struct lpfc_mbx_del_fcf_tbl_entry *del_fcf_record;
-	uint32_t mbox_tmo, req_len;
-	uint32_t shdr_status, shdr_add_status;
-
-	mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-	if (!mboxq) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-			"2020 Failed to allocate mbox for ADD_FCF cmd\n");
-		return;
-	}
-
-	req_len = sizeof(struct lpfc_mbx_del_fcf_tbl_entry) -
-		  sizeof(struct lpfc_sli4_cfg_mhdr);
-	rc = lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
-			      LPFC_MBOX_OPCODE_FCOE_DELETE_FCF,
-			      req_len, LPFC_SLI4_MBX_EMBED);
-	/*
-	 * In phase 1, there is a single FCF index, 0.  In phase2, the driver
-	 * supports multiple FCF indices.
-	 */
-	del_fcf_record = &mboxq->u.mqe.un.del_fcf_entry;
-	bf_set(lpfc_mbx_del_fcf_tbl_count, del_fcf_record, 1);
-	bf_set(lpfc_mbx_del_fcf_tbl_index, del_fcf_record,
-	       phba->fcf.current_rec.fcf_indx);
-
-	if (!phba->sli4_hba.intr_enable)
-		rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
-	else {
-		mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
-		rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
-	}
-	/* The IOCTL status is embedded in the mailbox subheader. */
-	shdr_status = bf_get(lpfc_mbox_hdr_status,
-			     &del_fcf_record->header.cfg_shdr.response);
-	shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
-				 &del_fcf_record->header.cfg_shdr.response);
-	if (shdr_status || shdr_add_status || rc != MBX_SUCCESS) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-				"2516 DEL FCF of default FCF Index failed "
-				"mbx status x%x, status x%x add_status x%x\n",
-				rc, shdr_status, shdr_add_status);
-	}
-	if (rc != MBX_TIMEOUT)
-		mempool_free(mboxq, phba->mbox_mem_pool);
-}
-
-/**
  * lpfc_fcf_redisc_wait_start_timer - Start fcf rediscover wait timer
  * @phba: Pointer to hba for which this call is being executed.
  *
@@ -4283,12 +4229,6 @@
 {
 	struct lpfc_fcf_conn_entry *conn_entry, *next_conn_entry;
 
-	/* unregister default FCFI from the HBA */
-	lpfc_sli4_fcfi_unreg(phba, phba->fcf.fcfi);
-
-	/* Free the default FCR table */
-	lpfc_sli_remove_dflt_fcf(phba);
-
 	/* Free memory allocated for msi-x interrupt vector entries */
 	kfree(phba->sli4_hba.msix_entries);
 
@@ -4316,9 +4256,6 @@
 	lpfc_sli4_cq_event_release_all(phba);
 	lpfc_sli4_cq_event_pool_destroy(phba);
 
-	/* Reset SLI4 HBA FCoE function */
-	lpfc_pci_function_reset(phba);
-
 	/* Free the bsmbx region. */
 	lpfc_destroy_bootstrap_mbox(phba);
 
@@ -4545,7 +4482,6 @@
 {
 	struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
 	LIST_HEAD(sglq_list);
-	int rc = 0;
 
 	spin_lock_irq(&phba->hbalock);
 	list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &sglq_list);
@@ -4558,11 +4494,6 @@
 		kfree(sglq_entry);
 		phba->sli4_hba.total_sglq_bufs--;
 	}
-	rc = lpfc_sli4_remove_all_sgl_pages(phba);
-	if (rc) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-			"2005 Unable to deregister pages from HBA: %x\n", rc);
-	}
 	kfree(phba->sli4_hba.lpfc_els_sgl_array);
 }
 
@@ -4725,8 +4656,8 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ * 	-ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 int
 lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *phba)
@@ -5419,7 +5350,7 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - could not allocated memory.
+ * 	-ENOMEM - could not allocated memory.
  **/
 static int
 lpfc_create_bootstrap_mbox(struct lpfc_hba *phba)
@@ -5518,8 +5449,8 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ * 	-ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 static int
 lpfc_sli4_read_config(struct lpfc_hba *phba)
@@ -5622,8 +5553,8 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ * 	-ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 static int
 lpfc_setup_endian_order(struct lpfc_hba *phba)
@@ -5671,8 +5602,8 @@
  *
  * Return codes
  *      0 - successful
- *      ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ *      -ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 static int
 lpfc_sli4_queue_create(struct lpfc_hba *phba)
@@ -5966,8 +5897,8 @@
  *
  * Return codes
  *      0 - successful
- *      ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ *      -ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 static void
 lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
@@ -6030,8 +5961,8 @@
  *
  * Return codes
  *      0 - successful
- *      ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ *      -ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 int
 lpfc_sli4_queue_setup(struct lpfc_hba *phba)
@@ -6275,8 +6206,8 @@
  *
  * Return codes
  *      0 - successful
- *      ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ *      -ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 void
 lpfc_sli4_queue_unset(struct lpfc_hba *phba)
@@ -6481,8 +6412,8 @@
  *
  * Return codes
  *      0 - successful
- *      ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ *      -ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 int
 lpfc_pci_function_reset(struct lpfc_hba *phba)
@@ -6592,50 +6523,6 @@
 }
 
 /**
- * lpfc_sli4_fcfi_unreg - Unregister fcfi to device
- * @phba: pointer to lpfc hba data structure.
- * @fcfi: fcf index.
- *
- * This routine is invoked to unregister a FCFI from device.
- **/
-void
-lpfc_sli4_fcfi_unreg(struct lpfc_hba *phba, uint16_t fcfi)
-{
-	LPFC_MBOXQ_t *mbox;
-	uint32_t mbox_tmo;
-	int rc;
-	unsigned long flags;
-
-	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-
-	if (!mbox)
-		return;
-
-	lpfc_unreg_fcfi(mbox, fcfi);
-
-	if (!phba->sli4_hba.intr_enable)
-		rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
-	else {
-		mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
-		rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
-	}
-	if (rc != MBX_TIMEOUT)
-		mempool_free(mbox, phba->mbox_mem_pool);
-	if (rc != MBX_SUCCESS)
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-				"2517 Unregister FCFI command failed "
-				"status %d, mbxStatus x%x\n", rc,
-				bf_get(lpfc_mqe_status, &mbox->u.mqe));
-	else {
-		spin_lock_irqsave(&phba->hbalock, flags);
-		/* Mark the FCFI is no longer registered */
-		phba->fcf.fcf_flag &=
-			~(FCF_AVAILABLE | FCF_REGISTERED | FCF_SCAN_DONE);
-		spin_unlock_irqrestore(&phba->hbalock, flags);
-	}
-}
-
-/**
  * lpfc_sli4_pci_mem_setup - Setup SLI4 HBA PCI memory space.
  * @phba: pointer to lpfc hba data structure.
  *
@@ -7372,10 +7259,14 @@
 
 	phba->pport->work_port_events = 0;
 
-	lpfc_sli4_hba_down(phba);
+	/* Stop the SLI4 device port */
+	lpfc_stop_port(phba);
 
 	lpfc_sli4_disable_intr(phba);
 
+	/* Reset SLI4 HBA FCoE function */
+	lpfc_pci_function_reset(phba);
+
 	return;
 }
 
@@ -7424,15 +7315,15 @@
 		spin_unlock_irq(&phba->hbalock);
 	}
 
-	/* Tear down the queues in the HBA */
-	lpfc_sli4_queue_unset(phba);
-
 	/* Disable PCI subsystem interrupt */
 	lpfc_sli4_disable_intr(phba);
 
 	/* Stop kthread signal shall trigger work_done one more time */
 	kthread_stop(phba->worker_thread);
 
+	/* Reset SLI4 HBA FCoE function */
+	lpfc_pci_function_reset(phba);
+
 	/* Stop the SLI4 device port */
 	phba->pport->work_port_events = 0;
 }
@@ -8368,7 +8259,7 @@
 	list_del_init(&vport->listentry);
 	spin_unlock_irq(&phba->hbalock);
 
-	/* Call scsi_free before lpfc_sli4_driver_resource_unset since scsi
+	/* Perform scsi free before driver resource_unset since scsi
 	 * buffers are released to their corresponding pools here.
 	 */
 	lpfc_scsi_free(phba);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 2e51aa6..3a65895 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -599,6 +599,7 @@
 		iocb->ulpClass = CLASS3;
 		psb->status = IOSTAT_SUCCESS;
 		/* Put it back into the SCSI buffer list */
+		psb->cur_iocbq.context1  = psb;
 		lpfc_release_scsi_buf_s3(phba, psb);
 
 	}
@@ -849,6 +850,7 @@
 		iocb->ulpBdeCount = 1;
 		iocb->ulpLe = 1;
 		iocb->ulpClass = CLASS3;
+		psb->cur_iocbq.context1  = psb;
 		if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
 			pdma_phys_bpl1 = pdma_phys_bpl + SGL_PAGE_SIZE;
 		else
@@ -2276,15 +2278,24 @@
 	 * Check SLI validation that all the transfer was actually done
 	 * (fcpi_parm should be zero). Apply check only to reads.
 	 */
-	} else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm &&
-			(cmnd->sc_data_direction == DMA_FROM_DEVICE)) {
+	} else if (fcpi_parm && (cmnd->sc_data_direction == DMA_FROM_DEVICE)) {
 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR,
 				 "9029 FCP Read Check Error Data: "
-				 "x%x x%x x%x x%x\n",
+				 "x%x x%x x%x x%x x%x\n",
 				 be32_to_cpu(fcpcmd->fcpDl),
 				 be32_to_cpu(fcprsp->rspResId),
-				 fcpi_parm, cmnd->cmnd[0]);
-		host_status = DID_ERROR;
+				 fcpi_parm, cmnd->cmnd[0], scsi_status);
+		switch (scsi_status) {
+		case SAM_STAT_GOOD:
+		case SAM_STAT_CHECK_CONDITION:
+			/* Fabric dropped a data frame. Fail any successful
+			 * command in which we detected dropped frames.
+			 * A status of good or some check conditions could
+			 * be considered a successful command.
+			 */
+			host_status = DID_ERROR;
+			break;
+		}
 		scsi_set_resid(cmnd, scsi_bufflen(cmnd));
 	}
 
@@ -3072,7 +3083,14 @@
 	if (ret)
 		return ret;
 	lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
-	BUG_ON(!lpfc_cmd);
+	if (!lpfc_cmd) {
+		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
+			 "2873 SCSI Layer I/O Abort Request IO CMPL Status "
+			 "x%x ID %d "
+			 "LUN %d snum %#lx\n", ret, cmnd->device->id,
+			 cmnd->device->lun, cmnd->serial_number);
+		return SUCCESS;
+	}
 
 	/*
 	 * If pCmd field of the corresponding lpfc_scsi_buf structure
@@ -3656,7 +3674,6 @@
  *
  * This routine configures following items
  *   - Tag command queuing support for @sdev if supported.
- *   - Dev loss time out value of fc_rport.
  *   - Enable SLI polling for fcp ring if ENABLE_FCP_RING_POLLING flag is set.
  *
  * Return codes:
@@ -3667,21 +3684,12 @@
 {
 	struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
 	struct lpfc_hba   *phba = vport->phba;
-	struct fc_rport   *rport = starget_to_rport(sdev->sdev_target);
 
 	if (sdev->tagged_supported)
 		scsi_activate_tcq(sdev, vport->cfg_lun_queue_depth);
 	else
 		scsi_deactivate_tcq(sdev, vport->cfg_lun_queue_depth);
 
-	/*
-	 * Initialize the fc transport attributes for the target
-	 * containing this scsi device.  Also note that the driver's
-	 * target pointer is stored in the starget_data for the
-	 * driver's sysfs entry point functions.
-	 */
-	rport->dev_loss_tmo = vport->cfg_devloss_tmo;
-
 	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
 		lpfc_sli_handle_fast_ring_event(phba,
 			&phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index fb8905f..0d1e187 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1677,6 +1677,8 @@
 	case MBX_RESUME_RPI:
 	case MBX_READ_EVENT_LOG_STATUS:
 	case MBX_READ_EVENT_LOG:
+	case MBX_SECURITY_MGMT:
+	case MBX_AUTH_PORT:
 		ret = mbxCommand;
 		break;
 	default:
@@ -1730,10 +1732,11 @@
 void
 lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
+	struct lpfc_vport  *vport = pmb->vport;
 	struct lpfc_dmabuf *mp;
+	struct lpfc_nodelist *ndlp;
 	uint16_t rpi, vpi;
 	int rc;
-	struct lpfc_vport  *vport = pmb->vport;
 
 	mp = (struct lpfc_dmabuf *) (pmb->context1);
 
@@ -1774,6 +1777,19 @@
 			return;
 	}
 
+	if (pmb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
+		ndlp = (struct lpfc_nodelist *)pmb->context2;
+		lpfc_nlp_put(ndlp);
+		pmb->context2 = NULL;
+	}
+
+	/* Check security permission status on INIT_LINK mailbox command */
+	if ((pmb->u.mb.mbxCommand == MBX_INIT_LINK) &&
+	    (pmb->u.mb.mbxStatus == MBXERR_SEC_NO_PERMISSION))
+		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+				"2860 SLI authentication is required "
+				"for INIT_LINK but has not done yet\n");
+
 	if (bf_get(lpfc_mqe_command, &pmb->u.mqe) == MBX_SLI4_CONFIG)
 		lpfc_sli4_mbox_cmd_free(phba, pmb);
 	else
@@ -3651,11 +3667,15 @@
 	i = 0;
 	while ((status & (HS_FFRDY | HS_MBRDY)) != (HS_FFRDY | HS_MBRDY)) {
 
-		/* Check every 100ms for 5 retries, then every 500ms for 5, then
-		 * every 2.5 sec for 5, then reset board and every 2.5 sec for
-		 * 4.
+		/* Check every 10ms for 10 retries, then every 100ms for 90
+		 * retries, then every 1 sec for 50 retires for a total of
+		 * ~60 seconds before reset the board again and check every
+		 * 1 sec for 50 retries. The up to 60 seconds before the
+		 * board ready is required by the Falcon FIPS zeroization
+		 * complete, and any reset the board in between shall cause
+		 * restart of zeroization, further delay the board ready.
 		 */
-		if (i++ >= 20) {
+		if (i++ >= 200) {
 			/* Adapter failed to init, timeout, status reg
 			   <status> */
 			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -3683,16 +3703,15 @@
 			return -EIO;
 		}
 
-		if (i <= 5) {
+		if (i <= 10)
 			msleep(10);
-		} else if (i <= 10) {
-			msleep(500);
-		} else {
-			msleep(2500);
-		}
+		else if (i <= 100)
+			msleep(100);
+		else
+			msleep(1000);
 
-		if (i == 15) {
-				/* Do post */
+		if (i == 150) {
+			/* Do post */
 			phba->pport->port_state = LPFC_VPORT_UNKNOWN;
 			lpfc_sli_brdrestart(phba);
 		}
@@ -4186,7 +4205,7 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - could not allocated memory.
+ * 	-ENOMEM - could not allocated memory.
  **/
 static int
 lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
@@ -5943,6 +5962,8 @@
 	uint8_t command_type = ELS_COMMAND_NON_FIP;
 	uint8_t cmnd;
 	uint16_t xritag;
+	uint16_t abrt_iotag;
+	struct lpfc_iocbq *abrtiocbq;
 	struct ulp_bde64 *bpl = NULL;
 	uint32_t els_id = ELS_ID_DEFAULT;
 	int numBdes, i;
@@ -6155,9 +6176,17 @@
 	case CMD_ABORT_XRI_CX:
 		/* words 0-2 memcpy should be 0 rserved */
 		/* port will send abts */
-		if (iocbq->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
+		abrt_iotag = iocbq->iocb.un.acxri.abortContextTag;
+		if (abrt_iotag != 0 && abrt_iotag <= phba->sli.last_iotag) {
+			abrtiocbq = phba->sli.iocbq_lookup[abrt_iotag];
+			fip = abrtiocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK;
+		} else
+			fip = 0;
+
+		if ((iocbq->iocb.ulpCommand == CMD_CLOSE_XRI_CN) || fip)
 			/*
-			 * The link is down so the fw does not need to send abts
+			 * The link is down, or the command was ELS_FIP
+			 * so the fw does not need to send abts
 			 * on the wire.
 			 */
 			bf_set(abort_cmd_ia, &wqe->abort_cmd, 1);
@@ -6901,37 +6930,6 @@
 }
 
 /**
- * lpfc_sli4_hba_down - PCI function resource cleanup for the SLI4 HBA
- * @phba: Pointer to HBA context object.
- *
- * This function cleans up all queues, iocb, buffers, mailbox commands while
- * shutting down the SLI4 HBA FCoE function. This function is called with no
- * lock held and always returns 1.
- *
- * This function does the following to cleanup driver FCoE function resources:
- * - Free discovery resources for each virtual port
- * - Cleanup any pending fabric iocbs
- * - Iterate through the iocb txq and free each entry in the list.
- * - Free up any buffer posted to the HBA.
- * - Clean up all the queue entries: WQ, RQ, MQ, EQ, CQ, etc.
- * - Free mailbox commands in the mailbox queue.
- **/
-int
-lpfc_sli4_hba_down(struct lpfc_hba *phba)
-{
-	/* Stop the SLI4 device port */
-	lpfc_stop_port(phba);
-
-	/* Tear down the queues in the HBA */
-	lpfc_sli4_queue_unset(phba);
-
-	/* unregister default FCFI from the HBA */
-	lpfc_sli4_fcfi_unreg(phba, phba->fcf.fcfi);
-
-	return 1;
-}
-
-/**
  * lpfc_sli_pcimem_bcopy - SLI memory copy function
  * @srcp: Source memory pointer.
  * @destp: Destination memory pointer.
@@ -7888,7 +7886,7 @@
 		/* Check if there is a deferred error condition is active */
 		if ((HS_FFER1 & phba->work_hs) &&
 		    ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
-		     HS_FFER6 | HS_FFER7) & phba->work_hs)) {
+		      HS_FFER6 | HS_FFER7 | HS_FFER8) & phba->work_hs)) {
 			phba->hba_flag |= DEFER_ERATT;
 			/* Clear all interrupt enable conditions */
 			writel(0, phba->HCregaddr);
@@ -8204,7 +8202,8 @@
 			 */
 			if ((HS_FFER1 & phba->work_hs) &&
 				((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
-				HS_FFER6 | HS_FFER7) & phba->work_hs)) {
+				  HS_FFER6 | HS_FFER7 | HS_FFER8) &
+				  phba->work_hs)) {
 				phba->hba_flag |= DEFER_ERATT;
 				/* Clear all interrupt enable conditions */
 				writel(0, phba->HCregaddr);
@@ -8476,7 +8475,7 @@
 	 * If there is deferred error attention, do not check for any interrupt.
 	 */
 	if (unlikely(phba->hba_flag & DEFER_ERATT)) {
-		spin_unlock_irq(&phba->hbalock);
+		spin_unlock(&phba->hbalock);
 		return IRQ_NONE;
 	}
 
@@ -9724,8 +9723,8 @@
  * command to finish before continuing.
  *
  * On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint16_t imax)
@@ -9840,8 +9839,8 @@
  * command to finish before continuing.
  *
  * On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
@@ -10011,8 +10010,8 @@
  * command to finish before continuing.
  *
  * On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
  **/
 int32_t
 lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
@@ -10146,8 +10145,8 @@
  * command to finish before continuing.
  *
  * On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
@@ -10234,8 +10233,8 @@
  * mailbox command to finish before continuing.
  *
  * On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
@@ -10403,7 +10402,7 @@
  * The @eq struct is used to get the queue ID of the queue to destroy.
  *
  * On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq)
@@ -10458,7 +10457,7 @@
  * The @cq struct is used to get the queue ID of the queue to destroy.
  *
  * On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq)
@@ -10511,7 +10510,7 @@
  * The @mq struct is used to get the queue ID of the queue to destroy.
  *
  * On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq)
@@ -10564,7 +10563,7 @@
  * The @wq struct is used to get the queue ID of the queue to destroy.
  *
  * On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq)
@@ -10616,7 +10615,7 @@
  * The @rq struct is used to get the queue ID of the queue to destroy.
  *
  * On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq,
@@ -10758,51 +10757,6 @@
 	}
 	return 0;
 }
-/**
- * lpfc_sli4_remove_all_sgl_pages - Post scatter gather list for an XRI to HBA
- * @phba: The virtual port for which this call being executed.
- *
- * This routine will remove all of the sgl pages registered with the hba.
- *
- * Return codes:
- * 	0 - Success
- * 	-ENXIO, -ENOMEM - Failure
- **/
-int
-lpfc_sli4_remove_all_sgl_pages(struct lpfc_hba *phba)
-{
-	LPFC_MBOXQ_t *mbox;
-	int rc;
-	uint32_t shdr_status, shdr_add_status;
-	union lpfc_sli4_cfg_shdr *shdr;
-
-	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-	if (!mbox)
-		return -ENOMEM;
-
-	lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
-			LPFC_MBOX_OPCODE_FCOE_REMOVE_SGL_PAGES, 0,
-			LPFC_SLI4_MBX_EMBED);
-	if (!phba->sli4_hba.intr_enable)
-		rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
-	else
-		rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
-	/* The IOCTL status is embedded in the mailbox subheader. */
-	shdr = (union lpfc_sli4_cfg_shdr *)
-		&mbox->u.mqe.un.sli4_config.header.cfg_shdr;
-	shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
-	shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
-	if (rc != MBX_TIMEOUT)
-		mempool_free(mbox, phba->mbox_mem_pool);
-	if (shdr_status || shdr_add_status || rc) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-				"2512 REMOVE_ALL_SGL_PAGES mailbox failed with "
-				"status x%x add_status x%x, mbx status x%x\n",
-				shdr_status, shdr_add_status, rc);
-		rc = -ENXIO;
-	}
-	return rc;
-}
 
 /**
  * lpfc_sli4_next_xritag - Get an xritag for the io
@@ -11819,7 +11773,7 @@
  *
  * Return codes
  * 	0 - successful
- *      EIO - The mailbox failed to complete successfully.
+ *      -EIO - The mailbox failed to complete successfully.
  * 	When this error occurs, the driver is not guaranteed
  *	to have any rpi regions posted to the device and
  *	must either attempt to repost the regions or take a
@@ -11857,8 +11811,8 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - No available memory
- *      EIO - The mailbox failed to complete successfully.
+ * 	-ENOMEM - No available memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 int
 lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page)
@@ -12805,8 +12759,11 @@
 	LPFC_MBOXQ_t *mb, *nextmb;
 	struct lpfc_dmabuf *mp;
 	struct lpfc_nodelist *ndlp;
+	struct lpfc_nodelist *act_mbx_ndlp = NULL;
 	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	LIST_HEAD(mbox_cmd_list);
 
+	/* Clean up internally queued mailbox commands with the vport */
 	spin_lock_irq(&phba->hbalock);
 	list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
 		if (mb->vport != vport)
@@ -12816,6 +12773,28 @@
 			(mb->u.mb.mbxCommand != MBX_REG_VPI))
 			continue;
 
+		list_del(&mb->list);
+		list_add_tail(&mb->list, &mbox_cmd_list);
+	}
+	/* Clean up active mailbox command with the vport */
+	mb = phba->sli.mbox_active;
+	if (mb && (mb->vport == vport)) {
+		if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) ||
+			(mb->u.mb.mbxCommand == MBX_REG_VPI))
+			mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
+			act_mbx_ndlp = (struct lpfc_nodelist *)mb->context2;
+			/* Put reference count for delayed processing */
+			act_mbx_ndlp = lpfc_nlp_get(act_mbx_ndlp);
+			/* Unregister the RPI when mailbox complete */
+			mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
+		}
+	}
+	spin_unlock_irq(&phba->hbalock);
+
+	/* Release the cleaned-up mailbox commands */
+	while (!list_empty(&mbox_cmd_list)) {
+		list_remove_head(&mbox_cmd_list, mb, LPFC_MBOXQ_t, list);
 		if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
 			if (phba->sli_rev == LPFC_SLI_REV4)
 				__lpfc_sli4_free_rpi(phba,
@@ -12826,36 +12805,24 @@
 				kfree(mp);
 			}
 			ndlp = (struct lpfc_nodelist *) mb->context2;
+			mb->context2 = NULL;
 			if (ndlp) {
-				spin_lock_irq(shost->host_lock);
+				spin_lock(shost->host_lock);
 				ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
-				spin_unlock_irq(shost->host_lock);
+				spin_unlock(shost->host_lock);
 				lpfc_nlp_put(ndlp);
-				mb->context2 = NULL;
 			}
 		}
-		list_del(&mb->list);
 		mempool_free(mb, phba->mbox_mem_pool);
 	}
-	mb = phba->sli.mbox_active;
-	if (mb && (mb->vport == vport)) {
-		if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) ||
-			(mb->u.mb.mbxCommand == MBX_REG_VPI))
-			mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-		if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
-			ndlp = (struct lpfc_nodelist *) mb->context2;
-			if (ndlp) {
-				spin_lock_irq(shost->host_lock);
-				ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
-				spin_unlock_irq(shost->host_lock);
-				lpfc_nlp_put(ndlp);
-				mb->context2 = NULL;
-			}
-			/* Unregister the RPI when mailbox complete */
-			mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
-		}
+
+	/* Release the ndlp with the cleaned-up active mailbox command */
+	if (act_mbx_ndlp) {
+		spin_lock(shost->host_lock);
+		act_mbx_ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
+		spin_unlock(shost->host_lock);
+		lpfc_nlp_put(act_mbx_ndlp);
 	}
-	spin_unlock_irq(&phba->hbalock);
 }
 
 /**
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index a3b24d9..a0ca572 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -481,7 +481,6 @@
  */
 int lpfc_pci_function_reset(struct lpfc_hba *);
 int lpfc_sli4_hba_setup(struct lpfc_hba *);
-int lpfc_sli4_hba_down(struct lpfc_hba *);
 int lpfc_sli4_config(struct lpfc_hba *, struct lpfcMboxq *, uint8_t,
 		     uint8_t, uint32_t, bool);
 void lpfc_sli4_mbox_cmd_free(struct lpfc_hba *, struct lpfcMboxq *);
@@ -514,7 +513,6 @@
 void lpfc_sli4_queue_unset(struct lpfc_hba *);
 int lpfc_sli4_post_sgl(struct lpfc_hba *, dma_addr_t, dma_addr_t, uint16_t);
 int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *);
-int lpfc_sli4_remove_all_sgl_pages(struct lpfc_hba *);
 uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *);
 int lpfc_sli4_post_async_mbox(struct lpfc_hba *);
 int lpfc_sli4_post_sgl_list(struct lpfc_hba *phba);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 61afb34..f93120e 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.3.16"
+#define LPFC_DRIVER_VERSION "8.3.17"
 #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 1655507..a5281ce 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -580,7 +580,9 @@
 				 "static vport.\n");
 		return VPORT_ERROR;
 	}
-
+	spin_lock_irq(&phba->hbalock);
+	vport->load_flag |= FC_UNLOADING;
+	spin_unlock_irq(&phba->hbalock);
 	/*
 	 * If we are not unloading the driver then prevent the vport_delete
 	 * from happening until after this vport's discovery is finished.
@@ -618,10 +620,6 @@
 		scsi_host_put(shost);
 		return VPORT_INVAL;
 	}
-	spin_lock_irq(&phba->hbalock);
-	vport->load_flag |= FC_UNLOADING;
-	spin_unlock_irq(&phba->hbalock);
-
 	lpfc_free_sysfs_attr(vport);
 
 	lpfc_debugfs_terminate(vport);
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 0b6e322..7ceb5cf 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -46,7 +46,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <scsi/scsicam.h>
 
@@ -62,6 +62,7 @@
 MODULE_LICENSE ("GPL");
 MODULE_VERSION(MEGARAID_MODULE_VERSION);
 
+static DEFINE_MUTEX(megadev_mutex);
 static unsigned int max_cmd_per_lun = DEF_CMD_PER_LUN;
 module_param(max_cmd_per_lun, uint, 0);
 MODULE_PARM_DESC(max_cmd_per_lun, "Maximum number of commands which can be issued to a single LUN (default=DEF_CMD_PER_LUN=63)");
@@ -101,6 +102,7 @@
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= megadev_unlocked_ioctl,
 	.open		= megadev_open,
+	.llseek		= noop_llseek,
 };
 
 /*
@@ -3282,7 +3284,6 @@
 static int
 megadev_open (struct inode *inode, struct file *filep)
 {
-	cycle_kernel_lock();
 	/*
 	 * Only allow superuser to access private ioctl interface
 	 */
@@ -3701,9 +3702,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&megadev_mutex);
 	ret = megadev_ioctl(filep, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&megadev_mutex);
 
 	return ret;
 }
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index 41f82f7..a7008c0 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -16,11 +16,12 @@
  */
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include "megaraid_mm.h"
 
 
 // Entry points for char node driver
+static DEFINE_MUTEX(mraid_mm_mutex);
 static int mraid_mm_open(struct inode *, struct file *);
 static long mraid_mm_unlocked_ioctl(struct file *, uint, unsigned long);
 
@@ -75,6 +76,7 @@
 	.compat_ioctl = mraid_mm_compat_ioctl,
 #endif
 	.owner	= THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice megaraid_mm_dev = {
@@ -98,7 +100,6 @@
 	 */
 	if (!capable(CAP_SYS_ADMIN)) return (-EACCES);
 
-	cycle_kernel_lock();
 	return 0;
 }
 
@@ -224,9 +225,9 @@
 	int err;
 
 	/* inconsistant: mraid_mm_compat_ioctl doesn't take the BKL */
-	lock_kernel();
+	mutex_lock(&mraid_mm_mutex);
 	err = mraid_mm_ioctl(filep, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&mraid_mm_mutex);
 
 	return err;
 }
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 99e4478..d3c9cde 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -33,7 +33,6 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
@@ -62,6 +61,11 @@
 MODULE_AUTHOR("megaraidlinux@lsi.com");
 MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
 
+static int megasas_transition_to_ready(struct megasas_instance *instance);
+static int megasas_get_pd_list(struct megasas_instance *instance);
+static int megasas_issue_init_mfi(struct megasas_instance *instance);
+static int megasas_register_aen(struct megasas_instance *instance,
+				u32 seq_num, u32 class_locale_word);
 /*
  * PCI ID table for all supported controllers
  */
@@ -164,7 +168,7 @@
 static inline void
 megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
 {
-	writel(1, &(regs)->outbound_intr_mask);
+	writel(0, &(regs)->outbound_intr_mask);
 
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_intr_mask);
@@ -200,24 +204,27 @@
 megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
 {
 	u32 status;
+	u32 mfiStatus = 0;
 	/*
 	 * Check if it is our interrupt
 	 */
 	status = readl(&regs->outbound_intr_status);
 
-	if (!(status & MFI_OB_INTR_STATUS_MASK)) {
-		return 1;
-	}
+	if (status & MFI_OB_INTR_STATUS_MASK)
+		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+	if (status & MFI_XSCALE_OMR0_CHANGE_INTERRUPT)
+		mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
 
 	/*
 	 * Clear the interrupt by writing back the same value
 	 */
-	writel(status, &regs->outbound_intr_status);
+	if (mfiStatus)
+		writel(status, &regs->outbound_intr_status);
 
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_intr_status);
 
-	return 0;
+	return mfiStatus;
 }
 
 /**
@@ -232,8 +239,69 @@
 		u32 frame_count,
 		struct megasas_register_set __iomem *regs)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel((frame_phys_addr >> 3)|(frame_count),
 	       &(regs)->inbound_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_xscale -  For controller reset
+ * @regs:                              MFI register set
+ */
+static int
+megasas_adp_reset_xscale(struct megasas_instance *instance,
+	struct megasas_register_set __iomem *regs)
+{
+	u32 i;
+	u32 pcidata;
+	writel(MFI_ADP_RESET, &regs->inbound_doorbell);
+
+	for (i = 0; i < 3; i++)
+		msleep(1000); /* sleep for 3 secs */
+	pcidata  = 0;
+	pci_read_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, &pcidata);
+	printk(KERN_NOTICE "pcidata = %x\n", pcidata);
+	if (pcidata & 0x2) {
+		printk(KERN_NOTICE "mfi 1068 offset read=%x\n", pcidata);
+		pcidata &= ~0x2;
+		pci_write_config_dword(instance->pdev,
+				MFI_1068_PCSR_OFFSET, pcidata);
+
+		for (i = 0; i < 2; i++)
+			msleep(1000); /* need to wait 2 secs again */
+
+		pcidata  = 0;
+		pci_read_config_dword(instance->pdev,
+				MFI_1068_FW_HANDSHAKE_OFFSET, &pcidata);
+		printk(KERN_NOTICE "1068 offset handshake read=%x\n", pcidata);
+		if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) {
+			printk(KERN_NOTICE "1068 offset pcidt=%x\n", pcidata);
+			pcidata = 0;
+			pci_write_config_dword(instance->pdev,
+				MFI_1068_FW_HANDSHAKE_OFFSET, pcidata);
+		}
+	}
+	return 0;
+}
+
+/**
+ * megasas_check_reset_xscale -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_xscale(struct megasas_instance *instance,
+		struct megasas_register_set __iomem *regs)
+{
+	u32 consumer;
+	consumer = *instance->consumer;
+
+	if ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) &&
+		(*instance->consumer == MEGASAS_ADPRESET_INPROG_SIGN)) {
+		return 1;
+	}
+	return 0;
 }
 
 static struct megasas_instance_template megasas_instance_template_xscale = {
@@ -243,6 +311,8 @@
 	.disable_intr = megasas_disable_intr_xscale,
 	.clear_intr = megasas_clear_intr_xscale,
 	.read_fw_status_reg = megasas_read_fw_status_reg_xscale,
+	.adp_reset = megasas_adp_reset_xscale,
+	.check_reset = megasas_check_reset_xscale,
 };
 
 /**
@@ -264,7 +334,7 @@
 {
 	writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
     
-	writel(~0x80000004, &(regs)->outbound_intr_mask);
+	writel(~0x80000000, &(regs)->outbound_intr_mask);
 
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_intr_mask);
@@ -307,7 +377,7 @@
 	status = readl(&regs->outbound_intr_status);
 
 	if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
-		return 1;
+		return 0;
 	}
 
 	/*
@@ -318,7 +388,7 @@
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_doorbell_clear);
 
-	return 0;
+	return 1;
 }
 /**
  * megasas_fire_cmd_ppc -	Sends command to the FW
@@ -332,10 +402,34 @@
 		u32 frame_count,
 		struct megasas_register_set __iomem *regs)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel((frame_phys_addr | (frame_count<<1))|1, 
 			&(regs)->inbound_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
 }
 
+/**
+ * megasas_adp_reset_ppc -	For controller reset
+ * @regs:				MFI register set
+ */
+static int
+megasas_adp_reset_ppc(struct megasas_instance *instance,
+			struct megasas_register_set __iomem *regs)
+{
+	return 0;
+}
+
+/**
+ * megasas_check_reset_ppc -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_ppc(struct megasas_instance *instance,
+			struct megasas_register_set __iomem *regs)
+{
+	return 0;
+}
 static struct megasas_instance_template megasas_instance_template_ppc = {
 	
 	.fire_cmd = megasas_fire_cmd_ppc,
@@ -343,6 +437,8 @@
 	.disable_intr = megasas_disable_intr_ppc,
 	.clear_intr = megasas_clear_intr_ppc,
 	.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
+	.adp_reset = megasas_adp_reset_ppc,
+	.check_reset = megasas_check_reset_ppc,
 };
 
 /**
@@ -397,7 +493,7 @@
 	status = readl(&regs->outbound_intr_status);
 
 	if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) {
-		return 1;
+		return 0;
 	}
 
 	/*
@@ -410,7 +506,7 @@
 	*/
 	readl(&regs->outbound_intr_status);
 
-	return 0;
+	return 1;
 }
 
 /**
@@ -426,11 +522,33 @@
 			struct megasas_register_set __iomem *regs)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&instance->fire_lock, flags);
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel(0, &(regs)->inbound_high_queue_port);
 	writel((frame_phys_addr | (frame_count<<1))|1,
 		&(regs)->inbound_low_queue_port);
-	spin_unlock_irqrestore(&instance->fire_lock, flags);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * 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
+ */
+static int
+megasas_check_reset_skinny(struct megasas_instance *instance,
+				struct megasas_register_set __iomem *regs)
+{
+	return 0;
 }
 
 static struct megasas_instance_template megasas_instance_template_skinny = {
@@ -440,6 +558,8 @@
 	.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,
+	.check_reset = megasas_check_reset_skinny,
 };
 
 
@@ -495,23 +615,29 @@
 megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
 {
 	u32 status;
+	u32 mfiStatus = 0;
 	/*
 	 * Check if it is our interrupt
 	 */
 	status = readl(&regs->outbound_intr_status);
 
-	if (!(status & MFI_GEN2_ENABLE_INTERRUPT_MASK))
-		return 1;
+	if (status & MFI_GEN2_ENABLE_INTERRUPT_MASK) {
+		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+	}
+	if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT) {
+		mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
+	}
 
 	/*
 	 * Clear the interrupt by writing back the same value
 	 */
-	writel(status, &regs->outbound_doorbell_clear);
+	if (mfiStatus)
+		writel(status, &regs->outbound_doorbell_clear);
 
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_intr_status);
 
-	return 0;
+	return mfiStatus;
 }
 /**
  * megasas_fire_cmd_gen2 -     Sends command to the FW
@@ -525,8 +651,74 @@
 			u32 frame_count,
 			struct megasas_register_set __iomem *regs)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel((frame_phys_addr | (frame_count<<1))|1,
 			&(regs)->inbound_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_gen2 -	For controller reset
+ * @regs:				MFI register set
+ */
+static int
+megasas_adp_reset_gen2(struct megasas_instance *instance,
+			struct megasas_register_set __iomem *reg_set)
+{
+	u32			retry = 0 ;
+	u32			HostDiag;
+
+	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);
+
+	while ( !( HostDiag & DIAG_WRITE_ENABLE) ) {
+		msleep(100);
+		HostDiag = (u32)readl(&reg_set->host_diag);
+		printk(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n",
+					retry, HostDiag);
+
+		if (retry++ >= 100)
+			return 1;
+
+	}
+
+	printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
+
+	writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
+
+	ssleep(10);
+
+	HostDiag = (u32)readl(&reg_set->host_diag);
+	while ( ( HostDiag & DIAG_RESET_ADAPTER) ) {
+		msleep(100);
+		HostDiag = (u32)readl(&reg_set->host_diag);
+		printk(KERN_NOTICE "RESET_GEN2: retry=%x, hostdiag=%x\n",
+				retry, HostDiag);
+
+		if (retry++ >= 1000)
+			return 1;
+
+	}
+	return 0;
+}
+
+/**
+ * megasas_check_reset_gen2 -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_gen2(struct megasas_instance *instance,
+		struct megasas_register_set __iomem *regs)
+{
+	return 0;
 }
 
 static struct megasas_instance_template megasas_instance_template_gen2 = {
@@ -536,11 +728,13 @@
 	.disable_intr = megasas_disable_intr_gen2,
 	.clear_intr = megasas_clear_intr_gen2,
 	.read_fw_status_reg = megasas_read_fw_status_reg_gen2,
+	.adp_reset = megasas_adp_reset_gen2,
+	.check_reset = megasas_check_reset_gen2,
 };
 
 /**
 *	This is the end of set of functions & definitions
-* 	specific to ppc (deviceid : 0x60) controllers
+*       specific to gen2 (deviceid : 0x78, 0x79) controllers
 */
 
 /**
@@ -599,8 +793,7 @@
 	instance->instancet->fire_cmd(instance,
 			cmd->frame_phys_addr, 0, instance->reg_set);
 
-	wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA),
-		MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
+	wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA);
 
 	return 0;
 }
@@ -648,8 +841,8 @@
 	/*
 	 * Wait for this cmd to complete
 	 */
-	wait_event_timeout(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF),
-		MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
+	wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF);
+	cmd->sync_cmd = 0;
 
 	megasas_return_cmd(instance, cmd);
 	return 0;
@@ -1131,14 +1324,22 @@
 	u32 frame_count;
 	struct megasas_cmd *cmd;
 	struct megasas_instance *instance;
+	unsigned long flags;
 
 	instance = (struct megasas_instance *)
 	    scmd->device->host->hostdata;
 
-	/* Don't process if we have already declared adapter dead */
-	if (instance->hw_crit_error)
+	if (instance->issuepend_done == 0)
 		return SCSI_MLQUEUE_HOST_BUSY;
 
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
 	scmd->scsi_done = done;
 	scmd->result = 0;
 
@@ -1274,6 +1475,18 @@
 	return 0;
 }
 
+static void megaraid_sas_kill_hba(struct megasas_instance *instance)
+{
+	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+		writel(MFI_STOP_ADP,
+			&instance->reg_set->reserved_0[0]);
+	} else {
+		writel(MFI_STOP_ADP,
+			&instance->reg_set->inbound_doorbell);
+	}
+}
+
 /**
  * megasas_complete_cmd_dpc	 -	Returns FW's controller structure
  * @instance_addr:			Address of adapter soft state
@@ -1291,7 +1504,7 @@
 	unsigned long flags;
 
 	/* If we have already declared adapter dead, donot complete cmds */
-	if (instance->hw_crit_error)
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR )
 		return;
 
 	spin_lock_irqsave(&instance->completion_lock, flags);
@@ -1301,6 +1514,11 @@
 
 	while (consumer != producer) {
 		context = instance->reply_queue[consumer];
+		if (context >= instance->max_fw_cmds) {
+			printk(KERN_ERR "Unexpected context value %x\n",
+				context);
+			BUG();
+		}
 
 		cmd = instance->cmd_list[context];
 
@@ -1350,7 +1568,76 @@
 static int megasas_wait_for_outstanding(struct megasas_instance *instance)
 {
 	int i;
+	u32 reset_index;
 	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
+	u8 adprecovery;
+	unsigned long flags;
+	struct list_head clist_local;
+	struct megasas_cmd *reset_cmd;
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	adprecovery = instance->adprecovery;
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+
+		INIT_LIST_HEAD(&clist_local);
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		list_splice_init(&instance->internal_reset_pending_q,
+				&clist_local);
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		printk(KERN_NOTICE "megasas: HBA reset wait ...\n");
+		for (i = 0; i < wait_time; i++) {
+			msleep(1000);
+			spin_lock_irqsave(&instance->hba_lock, flags);
+			adprecovery = instance->adprecovery;
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			if (adprecovery == MEGASAS_HBA_OPERATIONAL)
+				break;
+		}
+
+		if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+			printk(KERN_NOTICE "megasas: reset: Stopping HBA.\n");
+			spin_lock_irqsave(&instance->hba_lock, flags);
+			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			return FAILED;
+		}
+
+		reset_index	= 0;
+		while (!list_empty(&clist_local)) {
+			reset_cmd	= list_entry((&clist_local)->next,
+						struct megasas_cmd, list);
+			list_del_init(&reset_cmd->list);
+			if (reset_cmd->scmd) {
+				reset_cmd->scmd->result = DID_RESET << 16;
+				printk(KERN_NOTICE "%d:%p reset [%02x], %#lx\n",
+					reset_index, reset_cmd,
+					reset_cmd->scmd->cmnd[0],
+					reset_cmd->scmd->serial_number);
+
+				reset_cmd->scmd->scsi_done(reset_cmd->scmd);
+				megasas_return_cmd(instance, reset_cmd);
+			} else if (reset_cmd->sync_cmd) {
+				printk(KERN_NOTICE "megasas:%p synch cmds"
+						"reset queue\n",
+						reset_cmd);
+
+				reset_cmd->cmd_status = ENODATA;
+				instance->instancet->fire_cmd(instance,
+						reset_cmd->frame_phys_addr,
+						0, instance->reg_set);
+			} else {
+				printk(KERN_NOTICE "megasas: %p unexpected"
+					"cmds lst\n",
+					reset_cmd);
+			}
+			reset_index++;
+		}
+
+		return SUCCESS;
+	}
 
 	for (i = 0; i < wait_time; i++) {
 
@@ -1373,6 +1660,7 @@
 	}
 
 	if (atomic_read(&instance->fw_outstanding)) {
+		printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n");
 		/*
 		* Send signal to FW to stop processing any pending cmds.
 		* The controller will be taken offline by the OS now.
@@ -1388,10 +1676,14 @@
 				&instance->reg_set->inbound_doorbell);
 		}
 		megasas_dump_pending_frames(instance);
-		instance->hw_crit_error = 1;
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
 		return FAILED;
 	}
 
+	printk(KERN_NOTICE "megaraid_sas: no pending cmds after reset\n");
+
 	return SUCCESS;
 }
 
@@ -1413,7 +1705,7 @@
 	scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
 		 scmd->serial_number, scmd->cmnd[0], scmd->retries);
 
-	if (instance->hw_crit_error) {
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
 		printk(KERN_ERR "megasas: cannot recover from previous reset "
 		       "failures\n");
 		return FAILED;
@@ -1568,7 +1860,8 @@
 	instance->aen_cmd = NULL;
 	megasas_return_cmd(instance, cmd);
 
-	if (instance->unload == 0) {
+	if ((instance->unload == 0) &&
+		((instance->issuepend_done == 1))) {
 		struct megasas_aen_event *ev;
 		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 		if (!ev) {
@@ -1663,6 +1956,9 @@
 	struct megasas_header *hdr = &cmd->frame->hdr;
 	unsigned long flags;
 
+	/* flag for the retry reset */
+	cmd->retry_for_fw_reset = 0;
+
 	if (cmd->scmd)
 		cmd->scmd->SCp.ptr = NULL;
 
@@ -1783,39 +2079,301 @@
 }
 
 /**
+ * megasas_issue_pending_cmds_again -	issue all pending cmds
+ *                              	in FW again because of the fw reset
+ * @instance:				Adapter soft state
+ */
+static inline void
+megasas_issue_pending_cmds_again(struct megasas_instance *instance)
+{
+	struct megasas_cmd *cmd;
+	struct list_head clist_local;
+	union megasas_evt_class_locale class_locale;
+	unsigned long flags;
+	u32 seq_num;
+
+	INIT_LIST_HEAD(&clist_local);
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	list_splice_init(&instance->internal_reset_pending_q, &clist_local);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	while (!list_empty(&clist_local)) {
+		cmd	= list_entry((&clist_local)->next,
+					struct megasas_cmd, list);
+		list_del_init(&cmd->list);
+
+		if (cmd->sync_cmd || cmd->scmd) {
+			printk(KERN_NOTICE "megaraid_sas: command %p, %p:%d"
+				"detected to be pending while HBA reset.\n",
+					cmd, cmd->scmd, cmd->sync_cmd);
+
+			cmd->retry_for_fw_reset++;
+
+			if (cmd->retry_for_fw_reset == 3) {
+				printk(KERN_NOTICE "megaraid_sas: cmd %p, %p:%d"
+					"was tried multiple times during reset."
+					"Shutting down the HBA\n",
+					cmd, cmd->scmd, cmd->sync_cmd);
+				megaraid_sas_kill_hba(instance);
+
+				instance->adprecovery =
+						MEGASAS_HW_CRITICAL_ERROR;
+				return;
+			}
+		}
+
+		if (cmd->sync_cmd == 1) {
+			if (cmd->scmd) {
+				printk(KERN_NOTICE "megaraid_sas: unexpected"
+					"cmd attached to internal command!\n");
+			}
+			printk(KERN_NOTICE "megasas: %p synchronous cmd"
+						"on the internal reset queue,"
+						"issue it again.\n", cmd);
+			cmd->cmd_status = ENODATA;
+			instance->instancet->fire_cmd(instance,
+							cmd->frame_phys_addr ,
+							0, instance->reg_set);
+		} else if (cmd->scmd) {
+			printk(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx"
+			"detected on the internal queue, issue again.\n",
+			cmd, cmd->scmd->cmnd[0], cmd->scmd->serial_number);
+
+			atomic_inc(&instance->fw_outstanding);
+			instance->instancet->fire_cmd(instance,
+					cmd->frame_phys_addr,
+					cmd->frame_count-1, instance->reg_set);
+		} else {
+			printk(KERN_NOTICE "megasas: %p unexpected cmd on the"
+				"internal reset defer list while re-issue!!\n",
+				cmd);
+		}
+	}
+
+	if (instance->aen_cmd) {
+		printk(KERN_NOTICE "megaraid_sas: aen_cmd in def process\n");
+		megasas_return_cmd(instance, instance->aen_cmd);
+
+		instance->aen_cmd	= NULL;
+	}
+
+	/*
+	* Initiate AEN (Asynchronous Event Notification)
+	*/
+	seq_num = instance->last_seq_num;
+	class_locale.members.reserved = 0;
+	class_locale.members.locale = MR_EVT_LOCALE_ALL;
+	class_locale.members.class = MR_EVT_CLASS_DEBUG;
+
+	megasas_register_aen(instance, seq_num, class_locale.word);
+}
+
+/**
+ * Move the internal reset pending commands to a deferred queue.
+ *
+ * We move the commands pending at internal reset time to a
+ * pending queue. This queue would be flushed after successful
+ * completion of the internal reset sequence. if the internal reset
+ * did not complete in time, the kernel reset handler would flush
+ * these commands.
+ **/
+static void
+megasas_internal_reset_defer_cmds(struct megasas_instance *instance)
+{
+	struct megasas_cmd *cmd;
+	int i;
+	u32 max_cmd = instance->max_fw_cmds;
+	u32 defer_index;
+	unsigned long flags;
+
+	defer_index     = 0;
+	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+	for (i = 0; i < max_cmd; i++) {
+		cmd = instance->cmd_list[i];
+		if (cmd->sync_cmd == 1 || cmd->scmd) {
+			printk(KERN_NOTICE "megasas: moving cmd[%d]:%p:%d:%p"
+					"on the defer queue as internal\n",
+				defer_index, cmd, cmd->sync_cmd, cmd->scmd);
+
+			if (!list_empty(&cmd->list)) {
+				printk(KERN_NOTICE "megaraid_sas: ERROR while"
+					" moving this cmd:%p, %d %p, it was"
+					"discovered on some list?\n",
+					cmd, cmd->sync_cmd, cmd->scmd);
+
+				list_del_init(&cmd->list);
+			}
+			defer_index++;
+			list_add_tail(&cmd->list,
+				&instance->internal_reset_pending_q);
+		}
+	}
+	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+}
+
+
+static void
+process_fw_state_change_wq(struct work_struct *work)
+{
+	struct megasas_instance *instance =
+		container_of(work, struct megasas_instance, work_init);
+	u32 wait;
+	unsigned long flags;
+
+	if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
+		printk(KERN_NOTICE "megaraid_sas: error, recovery st %x \n",
+				instance->adprecovery);
+		return ;
+	}
+
+	if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
+		printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault"
+					"state, restarting it...\n");
+
+		instance->instancet->disable_intr(instance->reg_set);
+		atomic_set(&instance->fw_outstanding, 0);
+
+		atomic_set(&instance->fw_reset_no_pci_access, 1);
+		instance->instancet->adp_reset(instance, instance->reg_set);
+		atomic_set(&instance->fw_reset_no_pci_access, 0 );
+
+		printk(KERN_NOTICE "megaraid_sas: FW restarted successfully,"
+					"initiating next stage...\n");
+
+		printk(KERN_NOTICE "megaraid_sas: HBA recovery state machine,"
+					"state 2 starting...\n");
+
+		/*waitting for about 20 second before start the second init*/
+		for (wait = 0; wait < 30; wait++) {
+			msleep(1000);
+		}
+
+		if (megasas_transition_to_ready(instance)) {
+			printk(KERN_NOTICE "megaraid_sas:adapter not ready\n");
+
+			megaraid_sas_kill_hba(instance);
+			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+			return ;
+		}
+
+		if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
+			(instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
+			(instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)
+			) {
+			*instance->consumer = *instance->producer;
+		} else {
+			*instance->consumer = 0;
+			*instance->producer = 0;
+		}
+
+		megasas_issue_init_mfi(instance);
+
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		instance->adprecovery	= MEGASAS_HBA_OPERATIONAL;
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		instance->instancet->enable_intr(instance->reg_set);
+
+		megasas_issue_pending_cmds_again(instance);
+		instance->issuepend_done = 1;
+	}
+	return ;
+}
+
+/**
  * megasas_deplete_reply_queue -	Processes all completed commands
  * @instance:				Adapter soft state
  * @alt_status:				Alternate status to be returned to
  * 					SCSI mid-layer instead of the status
  * 					returned by the FW
+ * Note: this must be called with hba lock held
  */
 static int
-megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
+megasas_deplete_reply_queue(struct megasas_instance *instance,
+					u8 alt_status)
 {
-	/*
-	 * Check if it is our interrupt
-	 * Clear the interrupt 
-	 */
-	if(instance->instancet->clear_intr(instance->reg_set))
-		return IRQ_NONE;
+	u32 mfiStatus;
+	u32 fw_state;
 
-	if (instance->hw_crit_error)
-		goto out_done;
-        /*
-	 * Schedule the tasklet for cmd completion
-	 */
+	if ((mfiStatus = instance->instancet->check_reset(instance,
+					instance->reg_set)) == 1) {
+		return IRQ_HANDLED;
+	}
+
+	if ((mfiStatus = instance->instancet->clear_intr(
+						instance->reg_set)
+						) == 0) {
+		return IRQ_NONE;
+	}
+
+	instance->mfiStatus = mfiStatus;
+
+	if ((mfiStatus & MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE)) {
+		fw_state = instance->instancet->read_fw_status_reg(
+				instance->reg_set) & MFI_STATE_MASK;
+
+		if (fw_state != MFI_STATE_FAULT) {
+			printk(KERN_NOTICE "megaraid_sas: fw state:%x\n",
+						fw_state);
+		}
+
+		if ((fw_state == MFI_STATE_FAULT) &&
+				(instance->disableOnlineCtrlReset == 0)) {
+			printk(KERN_NOTICE "megaraid_sas: wait adp restart\n");
+
+			if ((instance->pdev->device ==
+					PCI_DEVICE_ID_LSI_SAS1064R) ||
+				(instance->pdev->device ==
+					PCI_DEVICE_ID_DELL_PERC5) ||
+				(instance->pdev->device ==
+					PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
+
+				*instance->consumer =
+					MEGASAS_ADPRESET_INPROG_SIGN;
+			}
+
+
+			instance->instancet->disable_intr(instance->reg_set);
+			instance->adprecovery	= MEGASAS_ADPRESET_SM_INFAULT;
+			instance->issuepend_done = 0;
+
+			atomic_set(&instance->fw_outstanding, 0);
+			megasas_internal_reset_defer_cmds(instance);
+
+			printk(KERN_NOTICE "megasas: fwState=%x, stage:%d\n",
+					fw_state, instance->adprecovery);
+
+			schedule_work(&instance->work_init);
+			return IRQ_HANDLED;
+
+		} else {
+			printk(KERN_NOTICE "megasas: fwstate:%x, dis_OCR=%x\n",
+				fw_state, instance->disableOnlineCtrlReset);
+		}
+	}
+
 	tasklet_schedule(&instance->isr_tasklet);
-out_done:
 	return IRQ_HANDLED;
 }
-
 /**
  * megasas_isr - isr entry point
  */
 static irqreturn_t megasas_isr(int irq, void *devp)
 {
-	return megasas_deplete_reply_queue((struct megasas_instance *)devp,
-					   DID_OK);
+	struct megasas_instance *instance;
+	unsigned long flags;
+	irqreturn_t	rc;
+
+	if (atomic_read(
+		&(((struct megasas_instance *)devp)->fw_reset_no_pci_access)))
+		return IRQ_HANDLED;
+
+	instance = (struct megasas_instance *)devp;
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	rc =  megasas_deplete_reply_queue(instance, DID_OK);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	return rc;
 }
 
 /**
@@ -1972,7 +2530,7 @@
 			       "in %d secs\n", fw_state, max_wait);
 			return -ENODEV;
 		}
-	};
+	}
  	printk(KERN_INFO "megasas: FW now in Ready state\n");
 
 	return 0;
@@ -2054,6 +2612,7 @@
 	 */
 	sgl_sz = sge_sz * instance->max_num_sge;
 	frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;
+	frame_count = 15;
 
 	/*
 	 * We need one extra frame for the MFI command
@@ -2201,6 +2760,7 @@
 		cmd = instance->cmd_list[i];
 		memset(cmd, 0, sizeof(struct megasas_cmd));
 		cmd->index = i;
+		cmd->scmd = NULL;
 		cmd->instance = instance;
 
 		list_add_tail(&cmd->list, &instance->cmd_pool);
@@ -2368,7 +2928,7 @@
 
 	/* the following function will get the instance PD LIST */
 
-	if ((ret == 0) && (ci->ldCount < MAX_LOGICAL_DRIVES)) {
+	if ((ret == 0) && (ci->ldCount <= MAX_LOGICAL_DRIVES)) {
 		memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
 
 		for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
@@ -2682,6 +3242,21 @@
 	if (megasas_issue_init_mfi(instance))
 		goto fail_fw_init;
 
+	instance->fw_support_ieee = 0;
+	instance->fw_support_ieee =
+		(instance->instancet->read_fw_status_reg(reg_set) &
+		0x04000000);
+
+	printk(KERN_NOTICE "megasas_init_mfi: fw_support_ieee=%d",
+			instance->fw_support_ieee);
+
+	if (instance->fw_support_ieee)
+		instance->flag_ieee = 1;
+
+	/** for passthrough
+	* the following function will get the PD LIST.
+	*/
+
 	memset(instance->pd_list, 0 ,
 		(MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
 	megasas_get_pd_list(instance);
@@ -2708,6 +3283,8 @@
 		max_sectors_2 = ctrl_info->max_request_size;
 
 		tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
+		instance->disableOnlineCtrlReset =
+		ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
 	}
 
 	instance->max_sectors_per_req = instance->max_num_sge *
@@ -2929,6 +3506,7 @@
 	dcmd->flags = MFI_FRAME_DIR_READ;
 	dcmd->timeout = 0;
 	dcmd->pad_0 = 0;
+	instance->last_seq_num = seq_num;
 	dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
 	dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
 	dcmd->mbox.w[0] = seq_num;
@@ -3097,6 +3675,7 @@
 
 	instance = (struct megasas_instance *)host->hostdata;
 	memset(instance, 0, sizeof(*instance));
+	atomic_set( &instance->fw_reset_no_pci_access, 0 );
 
 	instance->producer = pci_alloc_consistent(pdev, sizeof(u32),
 						  &instance->producer_h);
@@ -3114,6 +3693,9 @@
 	megasas_poll_wait_aen = 0;
 	instance->flag_ieee = 0;
 	instance->ev = NULL;
+	instance->issuepend_done = 1;
+	instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+	megasas_poll_wait_aen = 0;
 
 	instance->evt_detail = pci_alloc_consistent(pdev,
 						    sizeof(struct
@@ -3130,6 +3712,7 @@
 	 * Initialize locks and queues
 	 */
 	INIT_LIST_HEAD(&instance->cmd_pool);
+	INIT_LIST_HEAD(&instance->internal_reset_pending_q);
 
 	atomic_set(&instance->fw_outstanding,0);
 
@@ -3137,7 +3720,7 @@
 	init_waitqueue_head(&instance->abort_cmd_wait_q);
 
 	spin_lock_init(&instance->cmd_pool_lock);
-	spin_lock_init(&instance->fire_lock);
+	spin_lock_init(&instance->hba_lock);
 	spin_lock_init(&instance->completion_lock);
 	spin_lock_init(&poll_aen_lock);
 
@@ -3162,6 +3745,9 @@
 	instance->flag = 0;
 	instance->unload = 1;
 	instance->last_time = 0;
+	instance->disableOnlineCtrlReset = 1;
+
+	INIT_WORK(&instance->work_init, process_fw_state_change_wq);
 
 	/*
 	 * Initialize MFI Firmware
@@ -3253,6 +3839,9 @@
 	struct megasas_cmd *cmd;
 	struct megasas_dcmd_frame *dcmd;
 
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+		return;
+
 	cmd = megasas_get_cmd(instance);
 
 	if (!cmd)
@@ -3290,6 +3879,9 @@
 	struct megasas_cmd *cmd;
 	struct megasas_dcmd_frame *dcmd;
 
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+		return;
+
 	cmd = megasas_get_cmd(instance);
 
 	if (!cmd)
@@ -3557,7 +4149,6 @@
  */
 static int megasas_mgmt_open(struct inode *inode, struct file *filep)
 {
-	cycle_kernel_lock();
 	/*
 	 * Allow only those users with admin rights
 	 */
@@ -3781,6 +4372,9 @@
 	struct megasas_iocpacket *ioc;
 	struct megasas_instance *instance;
 	int error;
+	int i;
+	unsigned long flags;
+	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
 
 	ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
 	if (!ioc)
@@ -3797,8 +4391,8 @@
 		goto out_kfree_ioc;
 	}
 
-	if (instance->hw_crit_error == 1) {
-		printk(KERN_DEBUG "Controller in Crit ERROR\n");
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+		printk(KERN_ERR "Controller in crit error\n");
 		error = -ENODEV;
 		goto out_kfree_ioc;
 	}
@@ -3815,6 +4409,35 @@
 		error = -ERESTARTSYS;
 		goto out_kfree_ioc;
 	}
+
+	for (i = 0; i < wait_time; i++) {
+
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+			printk(KERN_NOTICE "megasas: waiting"
+				"for controller reset to finish\n");
+		}
+
+		msleep(1000);
+	}
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		printk(KERN_ERR "megaraid_sas: timed out while"
+			"waiting for HBA to recover\n");
+		error = -ENODEV;
+		goto out_kfree_ioc;
+	}
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
 	error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
 	up(&instance->ioctl_sem);
 
@@ -3828,6 +4451,9 @@
 	struct megasas_instance *instance;
 	struct megasas_aen aen;
 	int error;
+	int i;
+	unsigned long flags;
+	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
 
 	if (file->private_data != file) {
 		printk(KERN_DEBUG "megasas: fasync_helper was not "
@@ -3843,14 +4469,42 @@
 	if (!instance)
 		return -ENODEV;
 
-	if (instance->hw_crit_error == 1) {
-		error = -ENODEV;
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+		return -ENODEV;
 	}
 
 	if (instance->unload == 1) {
 		return -ENODEV;
 	}
 
+	for (i = 0; i < wait_time; i++) {
+
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
+			spin_unlock_irqrestore(&instance->hba_lock,
+						flags);
+			break;
+		}
+
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+			printk(KERN_NOTICE "megasas: waiting for"
+				"controller reset to finish\n");
+		}
+
+		msleep(1000);
+	}
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		printk(KERN_ERR "megaraid_sas: timed out while waiting"
+				"for HBA to recover.\n");
+		return -ENODEV;
+	}
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
 	mutex_lock(&instance->aen_mutex);
 	error = megasas_register_aen(instance, aen.seq_num,
 				     aen.class_locale_word);
@@ -3957,6 +4611,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = megasas_mgmt_compat_ioctl,
 #endif
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 9d8b6bf..16a4f68 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -60,6 +60,7 @@
 #define MFI_STATE_READY				0xB0000000
 #define MFI_STATE_OPERATIONAL			0xC0000000
 #define MFI_STATE_FAULT				0xF0000000
+#define  MFI_RESET_REQUIRED			0x00000001
 
 #define MEGAMFI_FRAME_SIZE			64
 
@@ -73,6 +74,12 @@
  * HOTPLUG	: Resume from Hotplug
  * MFI_STOP_ADP	: Send signal to FW to stop processing
  */
+#define WRITE_SEQUENCE_OFFSET		(0x0000000FC) /* I20 */
+#define HOST_DIAGNOSTIC_OFFSET		(0x000000F8)  /* I20 */
+#define DIAG_WRITE_ENABLE			(0x00000080)
+#define DIAG_RESET_ADAPTER			(0x00000004)
+
+#define MFI_ADP_RESET				0x00000040
 #define MFI_INIT_ABORT				0x00000001
 #define MFI_INIT_READY				0x00000002
 #define MFI_INIT_MFIMODE			0x00000004
@@ -402,8 +409,40 @@
 	u16 ecc_bucket_leak_rate;
 	u8 restore_hotspare_on_insertion;
 	u8 expose_encl_devices;
-	u8 reserved[38];
+	u8 maintainPdFailHistory;
+	u8 disallowHostRequestReordering;
+	u8 abortCCOnError;
+	u8 loadBalanceMode;
+	u8 disableAutoDetectBackplane;
 
+	u8 snapVDSpace;
+
+	/*
+	* Add properties that can be controlled by
+	* a bit in the following structure.
+	*/
+
+	struct {
+		u32     copyBackDisabled            : 1;
+		u32     SMARTerEnabled              : 1;
+		u32     prCorrectUnconfiguredAreas  : 1;
+		u32     useFdeOnly                  : 1;
+		u32     disableNCQ                  : 1;
+		u32     SSDSMARTerEnabled           : 1;
+		u32     SSDPatrolReadEnabled        : 1;
+		u32     enableSpinDownUnconfigured  : 1;
+		u32     autoEnhancedImport          : 1;
+		u32     enableSecretKeyControl      : 1;
+		u32     disableOnlineCtrlReset      : 1;
+		u32     allowBootWithPinnedCache    : 1;
+		u32     disableSpinDownHS           : 1;
+		u32     enableJBOD                  : 1;
+		u32     reserved                    :18;
+	} OnOffProperties;
+	u8 autoSnapVDSpace;
+	u8 viewSpace;
+	u16 spinDownTime;
+	u8  reserved[24];
 } __packed;
 
 /*
@@ -704,6 +743,12 @@
  */
 #define IS_DMA64				(sizeof(dma_addr_t) == 8)
 
+#define MFI_XSCALE_OMR0_CHANGE_INTERRUPT		0x00000001
+
+#define MFI_INTR_FLAG_REPLY_MESSAGE			0x00000001
+#define MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE		0x00000002
+#define MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT	0x00000004
+
 #define MFI_OB_INTR_STATUS_MASK			0x00000002
 #define MFI_POLL_TIMEOUT_SECS			60
 #define MEGASAS_COMPLETION_TIMER_INTERVAL      (HZ/10)
@@ -714,6 +759,9 @@
 #define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT	0x40000000
 #define MFI_SKINNY_ENABLE_INTERRUPT_MASK	(0x00000001)
 
+#define MFI_1068_PCSR_OFFSET			0x84
+#define MFI_1068_FW_HANDSHAKE_OFFSET		0x64
+#define MFI_1068_FW_READY			0xDDDD0000
 /*
 * register set for both 1068 and 1078 controllers
 * structure extended for 1078 registers
@@ -755,8 +803,10 @@
 	u32 	inbound_high_queue_port ;	/*00C4h*/
 
 	u32 	reserved_5;			/*00C8h*/
-	u32 	index_registers[820];		/*00CCh*/
-
+	u32	res_6[11];			/*CCh*/
+	u32	host_diag;
+	u32	seq_offset;
+	u32 	index_registers[807];		/*00CCh*/
 } __attribute__ ((packed));
 
 struct megasas_sge32 {
@@ -1226,11 +1276,12 @@
 
 	struct megasas_cmd **cmd_list;
 	struct list_head cmd_pool;
+	/* used to sync fire the cmd to fw */
 	spinlock_t cmd_pool_lock;
+	/* used to sync fire the cmd to fw */
+	spinlock_t hba_lock;
 	/* used to synch producer, consumer ptrs in dpc */
 	spinlock_t completion_lock;
-	/* used to sync fire the cmd to fw */
-	spinlock_t fire_lock;
 	struct dma_pool *frame_dma_pool;
 	struct dma_pool *sense_dma_pool;
 
@@ -1247,19 +1298,36 @@
 
 	struct pci_dev *pdev;
 	u32 unique_id;
+	u32 fw_support_ieee;
 
 	atomic_t fw_outstanding;
-	u32 hw_crit_error;
+	atomic_t fw_reset_no_pci_access;
 
 	struct megasas_instance_template *instancet;
 	struct tasklet_struct isr_tasklet;
+	struct work_struct work_init;
 
 	u8 flag;
 	u8 unload;
 	u8 flag_ieee;
+	u8 issuepend_done;
+	u8 disableOnlineCtrlReset;
+	u8 adprecovery;
 	unsigned long last_time;
+	u32 mfiStatus;
+	u32 last_seq_num;
 
 	struct timer_list io_completion_timer;
+	struct list_head internal_reset_pending_q;
+};
+
+enum {
+	MEGASAS_HBA_OPERATIONAL			= 0,
+	MEGASAS_ADPRESET_SM_INFAULT		= 1,
+	MEGASAS_ADPRESET_SM_FW_RESET_SUCCESS	= 2,
+	MEGASAS_ADPRESET_SM_OPERATIONAL		= 3,
+	MEGASAS_HW_CRITICAL_ERROR		= 4,
+	MEGASAS_ADPRESET_INPROG_SIGN		= 0xDEADDEAD,
 };
 
 struct megasas_instance_template {
@@ -1272,6 +1340,10 @@
 	int (*clear_intr)(struct megasas_register_set __iomem *);
 
 	u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
+	int (*adp_reset)(struct megasas_instance *, \
+		struct megasas_register_set __iomem *);
+	int (*check_reset)(struct megasas_instance *, \
+		struct megasas_register_set __iomem *);
 };
 
 #define MEGASAS_IS_LOGICAL(scp)						\
@@ -1291,7 +1363,9 @@
 	u32 index;
 	u8 sync_cmd;
 	u8 cmd_status;
-	u16 abort_aen;
+	u8 abort_aen;
+	u8 retry_for_fw_reset;
+
 
 	struct list_head list;
 	struct scsi_cmnd *scmd;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 57bcd5c..12faf64 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -534,7 +534,7 @@
 		if (event_data->DiscoveryStatus)
 			printk("discovery_status(0x%08x)",
 			    le32_to_cpu(event_data->DiscoveryStatus));
-			printk("\n");
+		printk("\n");
 		return;
 	}
 	case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index b774973..40cb8ae 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -51,7 +51,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 #include <linux/poll.h>
 
@@ -61,6 +61,7 @@
 #include "mpt2sas_base.h"
 #include "mpt2sas_ctl.h"
 
+static DEFINE_MUTEX(_ctl_mutex);
 static struct fasync_struct *async_queue;
 static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
 
@@ -2238,9 +2239,9 @@
 {
 	long ret;
 
-	lock_kernel();
+	mutex_lock(&_ctl_mutex);
 	ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
-	unlock_kernel();
+	mutex_unlock(&_ctl_mutex);
 	return ret;
 }
 
@@ -2309,12 +2310,12 @@
 {
 	long ret;
 
-	lock_kernel();
+	mutex_lock(&_ctl_mutex);
 	if (cmd == MPT2COMMAND32)
 		ret = _ctl_compat_mpt_command(file, cmd, arg);
 	else
 		ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
-	unlock_kernel();
+	mutex_unlock(&_ctl_mutex);
 	return ret;
 }
 #endif
@@ -2952,6 +2953,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = _ctl_ioctl_compat,
 #endif
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice ctl_dev = {
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index ffdd9fd..b31a8e3 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -182,6 +182,7 @@
 	.open           = osd_uld_open,
 	.release        = osd_uld_release,
 	.unlocked_ioctl = osd_uld_ioctl,
+	.llseek		= noop_llseek,
 };
 
 struct osd_dev *osduld_path_lookup(const char *name)
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 278b352..54de1d1 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -51,7 +51,7 @@
 #include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/jiffies.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/dma.h>
 #include <asm/system.h>
@@ -80,6 +80,7 @@
 #include "osst_options.h"
 #include "osst_detect.h"
 
+static DEFINE_MUTEX(osst_int_mutex);
 static int max_dev = 0;
 static int write_threshold_kbs = 0;
 static int max_sg_segs = 0;
@@ -4807,9 +4808,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&osst_int_mutex);
 	ret = __os_scsi_tape_open(inode, filp);
-	unlock_kernel();
+	mutex_unlock(&osst_int_mutex);
 	return ret;
 }
 
@@ -4943,9 +4944,9 @@
 	char		    * name  = tape_name(STp);
 	void	    __user  * p     = (void __user *)arg;
 
-	lock_kernel();
+	mutex_lock(&osst_int_mutex);
 	if (mutex_lock_interruptible(&STp->lock)) {
-		unlock_kernel();
+		mutex_unlock(&osst_int_mutex);
 		return -ERESTARTSYS;
 	}
 
@@ -5260,14 +5261,14 @@
 	mutex_unlock(&STp->lock);
 
 	retval = scsi_ioctl(STp->device, cmd_in, p);
-	unlock_kernel();
+	mutex_unlock(&osst_int_mutex);
 	return retval;
 
 out:
 	if (SRpnt) osst_release_request(SRpnt);
 
 	mutex_unlock(&STp->lock);
-	unlock_kernel();
+	mutex_unlock(&osst_int_mutex);
 
 	return retval;
 }
diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
index 53857c6..ecc855c 100644
--- a/drivers/scsi/pcmcia/Kconfig
+++ b/drivers/scsi/pcmcia/Kconfig
@@ -11,7 +11,6 @@
 
 config PCMCIA_AHA152X
 	tristate "Adaptec AHA152X PCMCIA support"
-	depends on !64BIT
 	select SCSI_SPI_ATTRS
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 61f49bd..e77dd02 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -49,7 +49,6 @@
 #include <scsi/scsi_host.h>
 #include "aha152x.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -86,8 +85,6 @@
 static void aha152x_detach(struct pcmcia_device *p_dev);
 static int aha152x_config_cs(struct pcmcia_device *link);
 
-static struct pcmcia_device *dev_list;
-
 static int aha152x_probe(struct pcmcia_device *link)
 {
     scsi_info_t *info;
@@ -100,11 +97,8 @@
     info->p_dev = link;
     link->priv = info;
 
-    link->resource[0]->end = 0x20;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+    link->config_regs = PRESENT_OPTION;
 
     return aha152x_config_cs(link);
 } /* aha152x_attach */
@@ -123,25 +117,24 @@
 
 /*====================================================================*/
 
-static int aha152x_config_check(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
-				void *priv_data)
+static int aha152x_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	p_dev->io_lines = 10;
+
 	/* For New Media T&J, look for a SCSI window */
-	if (cfg->io.win[0].len >= 0x20)
-		p_dev->resource[0]->start = cfg->io.win[0].base;
-	else if ((cfg->io.nwin > 1) &&
-		 (cfg->io.win[1].len >= 0x20))
-		p_dev->resource[0]->start = cfg->io.win[1].base;
-	if ((cfg->io.nwin > 0) &&
-	    (p_dev->resource[0]->start < 0xffff)) {
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -EINVAL;
+	if ((p_dev->resource[0]->end < 0x20) &&
+		(p_dev->resource[1]->end >= 0x20))
+		p_dev->resource[0]->start = p_dev->resource[1]->start;
+
+	if (p_dev->resource[0]->start >= 0xffff)
+		return -EINVAL;
+
+	p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
+	p_dev->resource[0]->end = 0x20;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int aha152x_config_cs(struct pcmcia_device *link)
@@ -160,7 +153,7 @@
     if (!link->irq)
 	    goto failed;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
     
@@ -221,9 +214,7 @@
 
 static struct pcmcia_driver aha152x_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "aha152x_cs",
-	},
+	.name		= "aha152x_cs",
 	.probe		= aha152x_probe,
 	.remove		= aha152x_detach,
 	.id_table       = aha152x_ids,
@@ -238,7 +229,6 @@
 static void __exit exit_aha152x_cs(void)
 {
 	pcmcia_unregister_driver(&aha152x_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_aha152x_cs);
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 13dbe5c..cd69c26 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -46,7 +46,6 @@
 #include <scsi/scsi_host.h>
 #include "fdomain.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -83,11 +82,8 @@
 
 	info->p_dev = link;
 	link->priv = info;
-	link->resource[0]->end = 0x10;
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-	link->conf.Present = PRESENT_OPTION;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+	link->config_regs = PRESENT_OPTION;
 
 	return fdomain_config(link);
 } /* fdomain_attach */
@@ -105,14 +101,12 @@
 
 /*====================================================================*/
 
-static int fdomain_config_check(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
-				void *priv_data)
+static int fdomain_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	p_dev->io_lines = 10;
-	p_dev->resource[0]->start = cfg->io.win[0].base;
+	p_dev->resource[0]->end = 0x10;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	return pcmcia_request_io(p_dev);
 }
 
@@ -132,7 +126,7 @@
 
     if (!link->irq)
 	    goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
@@ -194,9 +188,7 @@
 
 static struct pcmcia_driver fdomain_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "fdomain_cs",
-	},
+	.name		= "fdomain_cs",
 	.probe		= fdomain_probe,
 	.remove		= fdomain_detach,
 	.id_table       = fdomain_ids,
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index dd9b403..9326c2c 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -47,7 +47,6 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -1531,15 +1530,6 @@
   PCMCIA functions
 **********************************************************************/
 
-/*======================================================================
-    nsp_cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link 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 nsp_cs_probe(struct pcmcia_device *link)
 {
 	scsi_info_t  *info;
@@ -1557,14 +1547,6 @@
 
 	nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info);
 
-	/* The io structure describes IO port mapping */
-	link->resource[0]->end	 = 0x10;
-	link->resource[0]->flags = IO_DATA_PATH_WIDTH_AUTO;
-
-	/* General socket configuration */
-	link->conf.Attributes	 = CONF_ENABLE_IRQ;
-	link->conf.IntType	 = INT_MEMORY_AND_IO;
-
 	ret = nsp_cs_config(link);
 
 	nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
@@ -1572,12 +1554,6 @@
 } /* nsp_cs_attach */
 
 
-/*======================================================================
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.	 If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-======================================================================*/
 static void nsp_cs_detach(struct pcmcia_device *link)
 {
 	nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
@@ -1590,98 +1566,36 @@
 } /* nsp_cs_detach */
 
 
-/*======================================================================
-    nsp_cs_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    ethernet device available to the system.
-======================================================================*/
-
-struct nsp_cs_configdata {
-	nsp_hw_data		*data;
-	win_req_t		req;
-};
-
-static int nsp_cs_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cfg,
-			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
-			       void *priv_data)
+static int nsp_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	struct nsp_cs_configdata *cfg_mem = priv_data;
+	nsp_hw_data		*data = priv_data;
 
-	if (cfg->index == 0)
+	if (p_dev->config_index == 0)
 		return -ENODEV;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-		p_dev->conf.Status = CCSR_AUDIO_ENA;
+	/* This reserves IO space but doesn't actually enable it */
+	if (pcmcia_request_io(p_dev) != 0)
+		goto next_entry;
+
+	if (resource_size(p_dev->resource[2])) {
+		p_dev->resource[2]->flags |= (WIN_DATA_WIDTH_16 |
+					WIN_MEMORY_TYPE_CM |
+					WIN_ENABLE);
+		if (p_dev->resource[2]->end < 0x1000)
+			p_dev->resource[2]->end = 0x1000;
+		if (pcmcia_request_window(p_dev, p_dev->resource[2], 0) != 0)
+			goto next_entry;
+		if (pcmcia_map_mem_page(p_dev, p_dev->resource[2],
+						p_dev->card_addr) != 0)
+			goto next_entry;
+
+		data->MmioAddress = (unsigned long)
+			ioremap_nocache(p_dev->resource[2]->start,
+					resource_size(p_dev->resource[2]));
+		data->MmioLength  = resource_size(p_dev->resource[2]);
 	}
-
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-		if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
-			return -ENODEV;
-		else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-			if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
-				return -ENODEV;
-		}
-
-		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-			p_dev->conf.Vpp =
-				cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-		} else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-			p_dev->conf.Vpp =
-				dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-		}
-
-		/* Do we need to allocate an interrupt? */
-		p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-		/* IO window settings */
-		p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-		if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-			p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-			p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-			p_dev->resource[0]->flags |=
-				pcmcia_io_cfg_data_width(io->flags);
-			p_dev->resource[0]->start = io->win[0].base;
-			p_dev->resource[0]->end = io->win[0].len;
-			if (io->nwin > 1) {
-				p_dev->resource[1]->flags =
-					p_dev->resource[0]->flags;
-				p_dev->resource[1]->start = io->win[1].base;
-				p_dev->resource[1]->end = io->win[1].len;
-			}
-			/* This reserves IO space but doesn't actually enable it */
-			if (pcmcia_request_io(p_dev) != 0)
-				goto next_entry;
-		}
-
-		if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
-			cistpl_mem_t	*mem =
-				(cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
-			cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
-			cfg_mem->req.Attributes |= WIN_ENABLE;
-			cfg_mem->req.Base = mem->win[0].host_addr;
-			cfg_mem->req.Size = mem->win[0].len;
-			if (cfg_mem->req.Size < 0x1000)
-				cfg_mem->req.Size = 0x1000;
-			cfg_mem->req.AccessSpeed = 0;
-			if (pcmcia_request_window(p_dev, &cfg_mem->req, &p_dev->win) != 0)
-				goto next_entry;
-			if (pcmcia_map_mem_page(p_dev, p_dev->win,
-					mem->win[0].card_addr) != 0)
-				goto next_entry;
-
-			cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size);
-			cfg_mem->data->MmioLength  = cfg_mem->req.Size;
-		}
-		/* If we got this far, we're cool! */
-		return 0;
-	}
+	/* If we got this far, we're cool! */
+	return 0;
 
 next_entry:
 	nsp_dbg(NSP_DEBUG_INIT, "next");
@@ -1693,25 +1607,23 @@
 {
 	int		  ret;
 	scsi_info_t	 *info	 = link->priv;
-	struct nsp_cs_configdata *cfg_mem;
 	struct Scsi_Host *host;
 	nsp_hw_data      *data = &nsp_data_base;
 
 	nsp_dbg(NSP_DEBUG_INIT, "in");
 
-	cfg_mem = kzalloc(sizeof(*cfg_mem), GFP_KERNEL);
-	if (!cfg_mem)
-		return -ENOMEM;
-	cfg_mem->data = data;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
+		CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IOMEM |
+		CONF_AUTO_SET_IO;
 
-	ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem);
+	ret = pcmcia_loop_config(link, nsp_cs_config_check, data);
 	if (ret)
 		goto cs_failed;
 
 	if (pcmcia_request_irq(link, nspintr))
 		goto cs_failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto cs_failed;
 
@@ -1754,41 +1666,16 @@
 
 	info->host = host;
 
-	/* Finally, report what we've done */
-	printk(KERN_INFO "nsp_cs: index 0x%02x: ",
-	       link->conf.ConfigIndex);
-	if (link->conf.Vpp) {
-		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
-	}
-	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
-		printk(", irq %d", link->irq);
-	}
-	if (link->resource[0])
-		printk(", io %pR", link->resource[0]);
-	if (link->resource[1])
-		printk(" & %pR", link->resource[1]);
-	if (link->win)
-		printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
-		       cfg_mem->req.Base+cfg_mem->req.Size-1);
-	printk("\n");
-
-	kfree(cfg_mem);
 	return 0;
 
  cs_failed:
 	nsp_dbg(NSP_DEBUG_INIT, "config fail");
 	nsp_cs_release(link);
-	kfree(cfg_mem);
 
 	return -ENODEV;
 } /* nsp_cs_config */
 
 
-/*======================================================================
-    After a card is removed, nsp_cs_release() will unregister the net
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-======================================================================*/
 static void nsp_cs_release(struct pcmcia_device *link)
 {
 	scsi_info_t *info = link->priv;
@@ -1807,7 +1694,7 @@
 		scsi_remove_host(info->host);
 	}
 
-	if (link->win) {
+	if (resource_size(link->resource[2])) {
 		if (data != NULL) {
 			iounmap((void *)(data->MmioAddress));
 		}
@@ -1877,9 +1764,7 @@
 
 static struct pcmcia_driver nsp_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "nsp_cs",
-	},
+	.name		= "nsp_cs",
 	.probe		= nsp_cs_probe,
 	.remove		= nsp_cs_detach,
 	.id_table	= nsp_cs_ids,
@@ -1889,14 +1774,11 @@
 
 static int __init nsp_cs_init(void)
 {
-	nsp_msg(KERN_INFO, "loading...");
-
 	return pcmcia_register_driver(&nsp_driver);
 }
 
 static void __exit nsp_cs_exit(void)
 {
-	nsp_msg(KERN_INFO, "unloading...");
 	pcmcia_unregister_driver(&nsp_driver);
 }
 
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index eb775f1..9c96ca8 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -48,7 +48,6 @@
 #include <scsi/scsi_host.h>
 #include "../qlogicfas408.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ciscode.h>
@@ -156,11 +155,8 @@
 		return -ENOMEM;
 	info->p_dev = link;
 	link->priv = info;
-	link->resource[0]->end = 16;
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-	link->conf.Present = PRESENT_OPTION;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+	link->config_regs = PRESENT_OPTION;
 
 	return qlogic_config(link);
 }				/* qlogic_attach */
@@ -178,15 +174,11 @@
 
 /*====================================================================*/
 
-static int qlogic_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cfg,
-			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
-			       void *priv_data)
+static int qlogic_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	p_dev->io_lines = 10;
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
 	if (p_dev->resource[0]->start == 0)
 		return -ENODEV;
@@ -209,7 +201,7 @@
 	if (!link->irq)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -264,7 +256,7 @@
 {
 	scsi_info_t *info = link->priv;
 
-	pcmcia_request_configuration(link, &link->conf);
+	pcmcia_enable_device(link);
 	if ((info->manf_id == MANFID_MACNICA) ||
 	    (info->manf_id == MANFID_PIONEER) ||
 	    (info->manf_id == 0x0098)) {
@@ -302,9 +294,7 @@
 
 static struct pcmcia_driver qlogic_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
 	.name		= "qlogic_cs",
-	},
 	.probe		= qlogic_probe,
 	.remove		= qlogic_detach,
 	.id_table       = qlogic_ids,
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 321e390..0ae27cb 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -71,7 +71,6 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ciscode.h>
@@ -684,15 +683,11 @@
      .shost_attrs		= SYM53C500_shost_attrs
 };
 
-static int SYM53C500_config_check(struct pcmcia_device *p_dev,
-				  cistpl_cftable_entry_t *cfg,
-				  cistpl_cftable_entry_t *dflt,
-				  unsigned int vcc,
-				  void *priv_data)
+static int SYM53C500_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	p_dev->io_lines = 10;
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
 	if (p_dev->resource[0]->start == 0)
 		return -ENODEV;
@@ -721,7 +716,7 @@
 	if (!link->irq)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -859,10 +854,7 @@
 		return -ENOMEM;
 	info->p_dev = link;
 	link->priv = info;
-	link->resource[0]->end = 16;
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
 	return SYM53C500_config(link);
 } /* SYM53C500_attach */
@@ -881,9 +873,7 @@
 
 static struct pcmcia_driver sym53c500_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "sym53c500_cs",
-	},
+	.name		= "sym53c500_cs",
 	.probe		= SYM53C500_probe,
 	.remove		= SYM53C500_detach,
 	.id_table       = sym53c500_ids,
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 9793aa6..d8db013 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -4194,6 +4194,8 @@
 
 	nvmd_type = ioctl_payload->minor_function;
 	fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
+	if (!fw_control_context)
+		return -ENOMEM;
 	fw_control_context->usrAddr = (u8 *)&ioctl_payload->func_specific[0];
 	fw_control_context->len = ioctl_payload->length;
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
@@ -4272,6 +4274,8 @@
 
 	nvmd_type = ioctl_payload->minor_function;
 	fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
+	if (!fw_control_context)
+		return -ENOMEM;
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
 		ioctl_payload->func_specific,
@@ -4381,6 +4385,8 @@
 	struct pm8001_ioctl_payload *ioctl_payload = payload;
 
 	fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
+	if (!fw_control_context)
+		return -ENOMEM;
 	fw_control = (struct fw_control_info *)&ioctl_payload->func_specific[0];
 	if (fw_control->len != 0) {
 		if (pm8001_mem_alloc(pm8001_ha->pdev,
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index ecc45c8..4b87657 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -4165,6 +4165,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = pmcraid_chr_ioctl,
 #endif
+	.llseek = noop_llseek,
 };
 
 
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 114bc5a..2ff4342 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1538,6 +1538,15 @@
 	if (!fcport)
 		return;
 
+	/*
+	 * Transport has effectively 'deleted' the rport, clear
+	 * all local references.
+	 */
+	spin_lock_irq(host->host_lock);
+	fcport->rport = fcport->drport = NULL;
+	*((fc_port_t **)rport->dd_data) = NULL;
+	spin_unlock_irq(host->host_lock);
+
 	if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
 		return;
 
@@ -1545,15 +1554,6 @@
 		qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
 		return;
 	}
-
-	/*
-	 * Transport has effectively 'deleted' the rport, clear
-	 * all local references.
-	 */
-	spin_lock_irq(host->host_lock);
-	fcport->rport = NULL;
-	*((fc_port_t **)rport->dd_data) = NULL;
-	spin_unlock_irq(host->host_lock);
 }
 
 static void
@@ -1676,14 +1676,14 @@
 qla2x00_get_host_fabric_name(struct Scsi_Host *shost)
 {
 	scsi_qla_host_t *vha = shost_priv(shost);
-	u64 node_name;
+	uint8_t node_name[WWN_SIZE] = { 0xFF, 0xFF, 0xFF, 0xFF, \
+		0xFF, 0xFF, 0xFF, 0xFF};
+	u64 fabric_name = wwn_to_u64(node_name);
 
 	if (vha->device_flags & SWITCH_FOUND)
-		node_name = wwn_to_u64(vha->fabric_node_name);
-	else
-		node_name = wwn_to_u64(vha->node_name);
+		fabric_name = wwn_to_u64(vha->fabric_node_name);
 
-	fc_host_fabric_name(shost) = node_name;
+	fc_host_fabric_name(shost) = fabric_name;
 }
 
 static void
@@ -1776,6 +1776,7 @@
 	}
 
 	/* initialize attributes */
+	fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
 	fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
 	fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
 	fc_host_supported_classes(vha->host) =
@@ -1984,6 +1985,7 @@
 	struct qla_hw_data *ha = vha->hw;
 	u32 speed = FC_PORTSPEED_UNKNOWN;
 
+	fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
 	fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
 	fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
 	fc_host_supported_classes(vha->host) = FC_COS_CLASS3;
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 9067629..fdfbf83 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -1254,10 +1254,9 @@
 		return -EINVAL;
 	}
 
-	if (fcport->loop_id == FC_NO_LOOP_ID) {
-		DEBUG2(printk(KERN_ERR "%s(%ld): Invalid port loop id, "
-			"loop_id = 0x%x\n",
-			__func__, vha->host_no, fcport->loop_id));
+	if (atomic_read(&fcport->state) != FCS_ONLINE) {
+		DEBUG2(printk(KERN_ERR "%s(%ld): Port not online\n",
+			__func__, vha->host_no));
 		return -EINVAL;
 	}
 
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index d2a4e15..e1d3ad40 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -706,6 +706,11 @@
 #define MBC_SET_PORT_CONFIG		0x122	/* Set port configuration */
 #define MBC_GET_PORT_CONFIG		0x123	/* Get port configuration */
 
+/*
+ * ISP81xx mailbox commands
+ */
+#define MBC_WRITE_MPI_REGISTER		0x01    /* Write MPI Register. */
+
 /* Firmware return data sizes */
 #define FCAL_MAP_SIZE	128
 
@@ -2860,6 +2865,7 @@
 #define NPIV_CONFIG_NEEDED	16
 #define ISP_UNRECOVERABLE	17
 #define FCOE_CTX_RESET_NEEDED	18	/* Initiate FCoE context reset */
+#define MPI_RESET_NEEDED	19	/* Initiate MPI FW reset */
 
 	uint32_t	device_flags;
 #define SWITCH_FOUND		BIT_0
@@ -3003,6 +3009,8 @@
 
 #define CMD_SP(Cmnd)		((Cmnd)->SCp.ptr)
 
+#define QLA_SG_ALL	1024
+
 enum nexus_wait_type {
 	WAIT_HOST = 0,
 	WAIT_TARGET,
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 1a1b281..c33dec8 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -352,6 +352,8 @@
 extern int
 qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t);
 
+extern int
+qla81xx_write_mpi_register(scsi_qla_host_t *, uint16_t *);
 extern int qla2x00_get_data_rate(scsi_qla_host_t *);
 extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
 	uint16_t *);
@@ -501,7 +503,6 @@
 /* PCI related functions */
 extern int qla82xx_pci_config(struct scsi_qla_host *);
 extern int qla82xx_pci_mem_read_2M(struct qla_hw_data *, u64, void *, int);
-extern int qla82xx_pci_mem_write_2M(struct qla_hw_data *, u64, void *, int);
 extern char *qla82xx_pci_info_str(struct scsi_qla_host *, char *);
 extern int qla82xx_pci_region_offset(struct pci_dev *, int);
 extern int qla82xx_iospace_config(struct qla_hw_data *);
@@ -509,8 +510,8 @@
 /* Initialization related functions */
 extern void qla82xx_reset_chip(struct scsi_qla_host *);
 extern void qla82xx_config_rings(struct scsi_qla_host *);
-extern int qla82xx_pinit_from_rom(scsi_qla_host_t *);
 extern void qla82xx_watchdog(scsi_qla_host_t *);
+extern int qla82xx_start_firmware(scsi_qla_host_t *);
 
 /* Firmware and flash related functions */
 extern int qla82xx_load_risc(scsi_qla_host_t *, uint32_t *);
@@ -533,25 +534,17 @@
 extern irqreturn_t qla82xx_msix_rsp_q(int, void *);
 extern void qla82xx_enable_intrs(struct qla_hw_data *);
 extern void qla82xx_disable_intrs(struct qla_hw_data *);
-extern void qla82xx_mbx_completion(scsi_qla_host_t *, uint16_t);
 extern void qla82xx_poll(int, void *);
 extern void qla82xx_init_flags(struct qla_hw_data *);
 
 /* ISP 8021 hardware related */
-extern int qla82xx_crb_win_lock(struct qla_hw_data *);
+extern void qla82xx_set_drv_active(scsi_qla_host_t *);
 extern void qla82xx_crb_win_unlock(struct qla_hw_data *);
-extern int qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *, ulong *);
 extern int qla82xx_wr_32(struct qla_hw_data *, ulong, u32);
 extern int qla82xx_rd_32(struct qla_hw_data *, ulong);
 extern int qla82xx_rdmem(struct qla_hw_data *, u64, void *, int);
 extern int qla82xx_wrmem(struct qla_hw_data *, u64, void *, int);
-extern int qla82xx_check_for_bad_spd(struct qla_hw_data *);
-extern int qla82xx_load_fw(scsi_qla_host_t *);
-extern int qla82xx_rom_lock(struct qla_hw_data *);
 extern void qla82xx_rom_unlock(struct qla_hw_data *);
-extern int qla82xx_rom_fast_read(struct qla_hw_data *, int , int *);
-extern int qla82xx_do_rom_fast_read(struct qla_hw_data *, int, int *);
-extern unsigned long qla82xx_decode_crb_addr(unsigned long);
 
 /* ISP 8021 IDC */
 extern void qla82xx_clear_drv_active(struct qla_hw_data *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 9c383ba..3cafbef 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -954,6 +954,19 @@
 }
 
 /**
+ * qla81xx_reset_mpi() - Reset's MPI FW via Write MPI Register MBC.
+ *
+ * Returns 0 on success.
+ */
+int
+qla81xx_reset_mpi(scsi_qla_host_t *vha)
+{
+	uint16_t mb[4] = {0x1010, 0, 1, 0};
+
+	return qla81xx_write_mpi_register(vha, mb);
+}
+
+/**
  * qla24xx_reset_risc() - Perform full reset of ISP24xx RISC.
  * @ha: HA context
  *
@@ -967,6 +980,7 @@
 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 	uint32_t cnt, d2;
 	uint16_t wd;
+	static int abts_cnt; /* ISP abort retry counts */
 
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 
@@ -1000,6 +1014,23 @@
 		barrier();
 	}
 
+	/* If required, do an MPI FW reset now */
+	if (test_and_clear_bit(MPI_RESET_NEEDED, &vha->dpc_flags)) {
+		if (qla81xx_reset_mpi(vha) != QLA_SUCCESS) {
+			if (++abts_cnt < 5) {
+				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+				set_bit(MPI_RESET_NEEDED, &vha->dpc_flags);
+			} else {
+				/*
+				 * We exhausted the ISP abort retries. We have to
+				 * set the board offline.
+				 */
+				abts_cnt = 0;
+				vha->flags.online = 0;
+			}
+		}
+	}
+
 	WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
 	RD_REG_DWORD(&reg->hccr);
 
@@ -2799,6 +2830,9 @@
 	if (!IS_IIDMA_CAPABLE(ha))
 		return;
 
+	if (atomic_read(&fcport->state) != FCS_ONLINE)
+		return;
+
 	if (fcport->fp_speed == PORT_SPEED_UNKNOWN ||
 	    fcport->fp_speed > ha->link_data_rate)
 		return;
@@ -3878,17 +3912,19 @@
 			    LOOP_DOWN_TIME);
 	}
 
-	/* 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"));
+	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"));
+			}
 		}
-	}
 
-	/* Requeue all commands in outstanding command list. */
-	qla2x00_abort_all_cmds(vha, DID_RESET << 16);
+		/* Requeue all commands in outstanding command list. */
+		qla2x00_abort_all_cmds(vha, DID_RESET << 16);
+	}
 }
 
 /*
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 28f65be..e0e43d9 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -412,8 +412,14 @@
 				    "Unrecoverable Hardware Error: adapter "
 				    "marked OFFLINE!\n");
 				vha->flags.online = 0;
-			} else
+			} else {
+				/* Check to see if MPI timeout occured */
+				if ((mbx & MBX_3) && (ha->flags.port0))
+					set_bit(MPI_RESET_NEEDED,
+					    &vha->dpc_flags);
+
 				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+			}
 		} else if (mb[1] == 0) {
 			qla_printk(KERN_INFO, ha,
 			    "Unrecoverable Hardware Error: adapter marked "
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index a595ec8..effd8a1 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3828,8 +3828,6 @@
 
 	/* Copy mailbox information */
 	memcpy( mresp, mcp->mb, 64);
-	mresp[3] = mcp->mb[18];
-	mresp[4] = mcp->mb[19];
 	return rval;
 }
 
@@ -3890,9 +3888,10 @@
 	}
 
 	/* Copy mailbox information */
-	memcpy( mresp, mcp->mb, 32);
+	memcpy(mresp, mcp->mb, 64);
 	return rval;
 }
+
 int
 qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic)
 {
@@ -3953,6 +3952,67 @@
 }
 
 int
+qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb)
+{
+	int rval;
+	uint32_t stat, timer;
+	uint16_t mb0 = 0;
+	struct qla_hw_data *ha = vha->hw;
+	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+	rval = QLA_SUCCESS;
+
+	DEBUG11(qla_printk(KERN_INFO, ha,
+	    "%s(%ld): entered.\n", __func__, vha->host_no));
+
+	clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+
+	/* Write the MBC data to the registers */
+	WRT_REG_WORD(&reg->mailbox0, MBC_WRITE_MPI_REGISTER);
+	WRT_REG_WORD(&reg->mailbox1, mb[0]);
+	WRT_REG_WORD(&reg->mailbox2, mb[1]);
+	WRT_REG_WORD(&reg->mailbox3, mb[2]);
+	WRT_REG_WORD(&reg->mailbox4, mb[3]);
+
+	WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
+
+	/* Poll for MBC interrupt */
+	for (timer = 6000000; timer; timer--) {
+		/* Check for pending interrupts. */
+		stat = RD_REG_DWORD(&reg->host_status);
+		if (stat & HSRX_RISC_INT) {
+			stat &= 0xff;
+
+			if (stat == 0x1 || stat == 0x2 ||
+			    stat == 0x10 || stat == 0x11) {
+				set_bit(MBX_INTERRUPT,
+				    &ha->mbx_cmd_flags);
+				mb0 = RD_REG_WORD(&reg->mailbox0);
+				WRT_REG_DWORD(&reg->hccr,
+				    HCCRX_CLR_RISC_INT);
+				RD_REG_DWORD(&reg->hccr);
+				break;
+			}
+		}
+		udelay(5);
+	}
+
+	if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags))
+		rval = mb0 & MBS_MASK;
+	else
+		rval = QLA_FUNCTION_FAILED;
+
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk(KERN_INFO "%s(%ld): failed=%x mb[0]=%x.\n",
+		    __func__, vha->host_no, rval, mb[0]));
+	} else {
+		DEBUG11(printk(KERN_INFO
+		    "%s(%ld): done.\n", __func__, vha->host_no));
+	}
+
+	return rval;
+}
+int
 qla2x00_get_data_rate(scsi_qla_host_t *vha)
 {
 	int rval;
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 0a71cc7..8d9edfb3 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -403,6 +403,54 @@
 	return off;
 }
 
+static int
+qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong *off)
+{
+	struct crb_128M_2M_sub_block_map *m;
+
+	if (*off >= QLA82XX_CRB_MAX)
+		return -1;
+
+	if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) {
+		*off = (*off - QLA82XX_PCI_CAMQM) +
+		    QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase;
+		return 0;
+	}
+
+	if (*off < QLA82XX_PCI_CRBSPACE)
+		return -1;
+
+	*off -= QLA82XX_PCI_CRBSPACE;
+
+	/* Try direct map */
+	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
+
+	if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) {
+		*off = *off + m->start_2M - m->start_128M + ha->nx_pcibase;
+		return 0;
+	}
+	/* Not in direct map, use crb window */
+	return 1;
+}
+
+#define CRB_WIN_LOCK_TIMEOUT 100000000
+static int qla82xx_crb_win_lock(struct qla_hw_data *ha)
+{
+	int done = 0, timeout = 0;
+
+	while (!done) {
+		/* acquire semaphore3 from PCI HW block */
+		done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK));
+		if (done == 1)
+			break;
+		if (timeout >= CRB_WIN_LOCK_TIMEOUT)
+			return -1;
+		timeout++;
+	}
+	qla82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->portnum);
+	return 0;
+}
+
 int
 qla82xx_wr_32(struct qla_hw_data *ha, ulong off, u32 data)
 {
@@ -453,24 +501,6 @@
 	return data;
 }
 
-#define CRB_WIN_LOCK_TIMEOUT 100000000
-int qla82xx_crb_win_lock(struct qla_hw_data *ha)
-{
-	int done = 0, timeout = 0;
-
-	while (!done) {
-		/* acquire semaphore3 from PCI HW block */
-		done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK));
-		if (done == 1)
-			break;
-		if (timeout >= CRB_WIN_LOCK_TIMEOUT)
-			return -1;
-		timeout++;
-	}
-	qla82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->portnum);
-	return 0;
-}
-
 #define IDC_LOCK_TIMEOUT 100000000
 int qla82xx_idc_lock(struct qla_hw_data *ha)
 {
@@ -504,36 +534,6 @@
 	qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_UNLOCK));
 }
 
-int
-qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong *off)
-{
-	struct crb_128M_2M_sub_block_map *m;
-
-	if (*off >= QLA82XX_CRB_MAX)
-		return -1;
-
-	if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) {
-		*off = (*off - QLA82XX_PCI_CAMQM) +
-		    QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase;
-		return 0;
-	}
-
-	if (*off < QLA82XX_PCI_CRBSPACE)
-		return -1;
-
-	*off -= QLA82XX_PCI_CRBSPACE;
-
-	/* Try direct map */
-	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
-
-	if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) {
-		*off = *off + m->start_2M - m->start_128M + ha->nx_pcibase;
-		return 0;
-	}
-	/* Not in direct map, use crb window */
-	return 1;
-}
-
 /*  PCI Windowing for DDR regions.  */
 #define QLA82XX_ADDR_IN_RANGE(addr, low, high) \
 	(((addr) <= (high)) && ((addr) >= (low)))
@@ -557,7 +557,7 @@
 
 int qla82xx_pci_set_window_warning_count;
 
-unsigned long
+static unsigned long
 qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
 {
 	int window;
@@ -798,7 +798,8 @@
 }
 
 #define MTU_FUDGE_FACTOR 100
-unsigned long qla82xx_decode_crb_addr(unsigned long addr)
+static unsigned long
+qla82xx_decode_crb_addr(unsigned long addr)
 {
 	int i;
 	unsigned long base_addr, offset, pci_base;
@@ -824,7 +825,7 @@
 static long rom_max_timeout = 100;
 static long qla82xx_rom_lock_timeout = 100;
 
-int
+static int
 qla82xx_rom_lock(struct qla_hw_data *ha)
 {
 	int done = 0, timeout = 0;
@@ -842,7 +843,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_wait_rom_busy(struct qla_hw_data *ha)
 {
 	long timeout = 0;
@@ -862,7 +863,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_wait_rom_done(struct qla_hw_data *ha)
 {
 	long timeout = 0;
@@ -882,7 +883,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_do_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
 {
 	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr);
@@ -905,7 +906,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
 {
 	int ret, loops = 0;
@@ -926,7 +927,7 @@
 	return ret;
 }
 
-int
+static int
 qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val)
 {
 	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_RDSR);
@@ -940,7 +941,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_flash_wait_write_finish(struct qla_hw_data *ha)
 {
 	long timeout = 0;
@@ -964,7 +965,7 @@
 	return ret;
 }
 
-int
+static int
 qla82xx_flash_set_write_enable(struct qla_hw_data *ha)
 {
 	uint32_t val;
@@ -981,7 +982,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val)
 {
 	if (qla82xx_flash_set_write_enable(ha))
@@ -996,7 +997,7 @@
 	return qla82xx_flash_wait_write_finish(ha);
 }
 
-int
+static int
 qla82xx_write_disable_flash(struct qla_hw_data *ha)
 {
 	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WRDI);
@@ -1008,7 +1009,7 @@
 	return 0;
 }
 
-int
+static int
 ql82xx_rom_lock_d(struct qla_hw_data *ha)
 {
 	int loops = 0;
@@ -1024,7 +1025,7 @@
 	return 0;;
 }
 
-int
+static int
 qla82xx_write_flash_dword(struct qla_hw_data *ha, uint32_t flashaddr,
 	uint32_t data)
 {
@@ -1061,7 +1062,8 @@
 /* This routine does CRB initialize sequence
  *  to put the ISP into operational state
  */
-int qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
+static int
+qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
 {
 	int addr, val;
 	int i ;
@@ -1207,7 +1209,8 @@
 	return 0;
 }
 
-int qla82xx_check_for_bad_spd(struct qla_hw_data *ha)
+static int
+qla82xx_check_for_bad_spd(struct qla_hw_data *ha)
 {
 	u32 val = 0;
 	val = qla82xx_rd_32(ha, BOOT_LOADER_DIMM_STATUS);
@@ -1225,7 +1228,116 @@
 	return 0;
 }
 
-int
+static int
+qla82xx_pci_mem_write_2M(struct qla_hw_data *ha,
+		u64 off, void *data, int size)
+{
+	int i, j, ret = 0, loop, sz[2], off0;
+	int scale, shift_amount, startword;
+	uint32_t temp;
+	uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
+
+	/*
+	 * If not MN, go check for MS or invalid.
+	 */
+	if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX)
+		mem_crb = QLA82XX_CRB_QDR_NET;
+	else {
+		mem_crb = QLA82XX_CRB_DDR_NET;
+		if (qla82xx_pci_mem_bound_check(ha, off, size) == 0)
+			return qla82xx_pci_mem_write_direct(ha,
+			    off, data, size);
+	}
+
+	off0 = off & 0x7;
+	sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+	sz[1] = size - sz[0];
+
+	off8 = off & 0xfffffff0;
+	loop = (((off & 0xf) + size - 1) >> 4) + 1;
+	shift_amount = 4;
+	scale = 2;
+	startword = (off & 0xf)/8;
+
+	for (i = 0; i < loop; i++) {
+		if (qla82xx_pci_mem_read_2M(ha, off8 +
+		    (i << shift_amount), &word[i * scale], 8))
+			return -1;
+	}
+
+	switch (size) {
+	case 1:
+		tmpw = *((uint8_t *)data);
+		break;
+	case 2:
+		tmpw = *((uint16_t *)data);
+		break;
+	case 4:
+		tmpw = *((uint32_t *)data);
+		break;
+	case 8:
+	default:
+		tmpw = *((uint64_t *)data);
+		break;
+	}
+
+	if (sz[0] == 8) {
+		word[startword] = tmpw;
+	} else {
+		word[startword] &=
+			~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+		word[startword] |= tmpw << (off0 * 8);
+	}
+	if (sz[1] != 0) {
+		word[startword+1] &= ~(~0ULL << (sz[1] * 8));
+		word[startword+1] |= tmpw >> (sz[0] * 8);
+	}
+
+	/*
+	 * don't lock here - write_wx gets the lock if each time
+	 * write_lock_irqsave(&adapter->adapter_lock, flags);
+	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+	 */
+	for (i = 0; i < loop; i++) {
+		temp = off8 + (i << shift_amount);
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp);
+		temp = 0;
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp);
+		temp = word[i * scale] & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp);
+		temp = (word[i * scale] >> 32) & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp);
+		temp = word[i*scale + 1] & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb +
+		    MIU_TEST_AGT_WRDATA_UPPER_LO, temp);
+		temp = (word[i*scale + 1] >> 32) & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb +
+		    MIU_TEST_AGT_WRDATA_UPPER_HI, temp);
+
+		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
+		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
+
+		for (j = 0; j < MAX_CTL_CHECK; j++) {
+			temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL);
+			if ((temp & MIU_TA_CTL_BUSY) == 0)
+				break;
+		}
+
+		if (j >= MAX_CTL_CHECK) {
+			if (printk_ratelimit())
+				dev_err(&ha->pdev->dev,
+				    "failed to write through agent\n");
+			ret = -1;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int
 qla82xx_fw_load_from_flash(struct qla_hw_data *ha)
 {
 	int  i;
@@ -1357,114 +1469,6 @@
 	return 0;
 }
 
-int
-qla82xx_pci_mem_write_2M(struct qla_hw_data *ha,
-		u64 off, void *data, int size)
-{
-	int i, j, ret = 0, loop, sz[2], off0;
-	int scale, shift_amount, startword;
-	uint32_t temp;
-	uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
-
-	/*
-	 * If not MN, go check for MS or invalid.
-	 */
-	if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX)
-		mem_crb = QLA82XX_CRB_QDR_NET;
-	else {
-		mem_crb = QLA82XX_CRB_DDR_NET;
-		if (qla82xx_pci_mem_bound_check(ha, off, size) == 0)
-			return qla82xx_pci_mem_write_direct(ha,
-			    off, data, size);
-	}
-
-	off0 = off & 0x7;
-	sz[0] = (size < (8 - off0)) ? size : (8 - off0);
-	sz[1] = size - sz[0];
-
-	off8 = off & 0xfffffff0;
-	loop = (((off & 0xf) + size - 1) >> 4) + 1;
-	shift_amount = 4;
-	scale = 2;
-	startword = (off & 0xf)/8;
-
-	for (i = 0; i < loop; i++) {
-		if (qla82xx_pci_mem_read_2M(ha, off8 +
-		    (i << shift_amount), &word[i * scale], 8))
-			return -1;
-	}
-
-	switch (size) {
-	case 1:
-		tmpw = *((uint8_t *)data);
-		break;
-	case 2:
-		tmpw = *((uint16_t *)data);
-		break;
-	case 4:
-		tmpw = *((uint32_t *)data);
-		break;
-	case 8:
-	default:
-		tmpw = *((uint64_t *)data);
-		break;
-	}
-
-	if (sz[0] == 8) {
-		word[startword] = tmpw;
-	} else {
-		word[startword] &=
-			~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
-		word[startword] |= tmpw << (off0 * 8);
-	}
-	if (sz[1] != 0) {
-		word[startword+1] &= ~(~0ULL << (sz[1] * 8));
-		word[startword+1] |= tmpw >> (sz[0] * 8);
-	}
-
-	/*
-	 * don't lock here - write_wx gets the lock if each time
-	 * write_lock_irqsave(&adapter->adapter_lock, flags);
-	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
-	 */
-	for (i = 0; i < loop; i++) {
-		temp = off8 + (i << shift_amount);
-		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp);
-		temp = 0;
-		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp);
-		temp = word[i * scale] & 0xffffffff;
-		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp);
-		temp = (word[i * scale] >> 32) & 0xffffffff;
-		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp);
-		temp = word[i*scale + 1] & 0xffffffff;
-		qla82xx_wr_32(ha, mem_crb +
-		    MIU_TEST_AGT_WRDATA_UPPER_LO, temp);
-		temp = (word[i*scale + 1] >> 32) & 0xffffffff;
-		qla82xx_wr_32(ha, mem_crb +
-		    MIU_TEST_AGT_WRDATA_UPPER_HI, temp);
-
-		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
-		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
-		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
-		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
-
-		for (j = 0; j < MAX_CTL_CHECK; j++) {
-			temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL);
-			if ((temp & MIU_TA_CTL_BUSY) == 0)
-				break;
-		}
-
-		if (j >= MAX_CTL_CHECK) {
-			if (printk_ratelimit())
-				dev_err(&ha->pdev->dev,
-				    "failed to write through agent\n");
-			ret = -1;
-			break;
-		}
-	}
-
-	return ret;
-}
 
 static struct qla82xx_uri_table_desc *
 qla82xx_get_table_desc(const u8 *unirom, int section)
@@ -1725,7 +1729,8 @@
 	ha->isp_ops->disable_intrs(ha);
 }
 
-int qla82xx_fw_load_from_blob(struct qla_hw_data *ha)
+static int
+qla82xx_fw_load_from_blob(struct qla_hw_data *ha)
 {
 	u64 *ptr64;
 	u32 i, flashaddr, size;
@@ -1836,7 +1841,8 @@
 	return 0;
 }
 
-int qla82xx_check_cmdpeg_state(struct qla_hw_data *ha)
+static int
+qla82xx_check_cmdpeg_state(struct qla_hw_data *ha)
 {
 	u32 val = 0;
 	int retries = 60;
@@ -1874,7 +1880,8 @@
 	return QLA_FUNCTION_FAILED;
 }
 
-int qla82xx_check_rcvpeg_state(struct qla_hw_data *ha)
+static int
+qla82xx_check_rcvpeg_state(struct qla_hw_data *ha)
 {
 	u32 val = 0;
 	int retries = 60;
@@ -1933,7 +1940,7 @@
  * @ha: SCSI driver HA context
  * @mb0: Mailbox0 register
  */
-void
+static void
 qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
 {
 	uint16_t	cnt;
@@ -2257,7 +2264,7 @@
 	ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
 }
 
-static inline void
+inline void
 qla82xx_set_drv_active(scsi_qla_host_t *vha)
 {
 	uint32_t drv_active;
@@ -2267,10 +2274,11 @@
 
 	/* If reset value is all FF's, initialize DRV_ACTIVE */
 	if (drv_active == 0xffffffff) {
-		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, 0);
+		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE,
+			QLA82XX_DRV_NOT_ACTIVE);
 		drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
 	}
-	drv_active |= (1 << (ha->portnum * 4));
+	drv_active |= (QLA82XX_DRV_ACTIVE << (ha->portnum * 4));
 	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active);
 }
 
@@ -2280,7 +2288,7 @@
 	uint32_t drv_active;
 
 	drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
-	drv_active &= ~(1 << (ha->portnum * 4));
+	drv_active &= ~(QLA82XX_DRV_ACTIVE << (ha->portnum * 4));
 	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active);
 }
 
@@ -2291,7 +2299,7 @@
 	int rval;
 
 	drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
-	rval = drv_state & (1 << (ha->portnum * 4));
+	rval = drv_state & (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
 	return rval;
 }
 
@@ -2305,7 +2313,7 @@
 
 	/* If reset value is all FF's, initialize DRV_STATE */
 	if (drv_state == 0xffffffff) {
-		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0);
+		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, QLA82XX_DRVST_NOT_RDY);
 		drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
 	}
 	drv_state |= (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
@@ -2335,7 +2343,8 @@
 	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state);
 }
 
-int qla82xx_load_fw(scsi_qla_host_t *vha)
+static int
+qla82xx_load_fw(scsi_qla_host_t *vha)
 {
 	int rst;
 	struct fw_blob *blob;
@@ -2411,7 +2420,7 @@
 	return QLA_FUNCTION_FAILED;
 }
 
-static int
+int
 qla82xx_start_firmware(scsi_qla_host_t *vha)
 {
 	int           pcie_cap;
@@ -2419,7 +2428,7 @@
 	struct qla_hw_data *ha = vha->hw;
 
 	/* scrub dma mask expansion register */
-	qla82xx_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
+	qla82xx_wr_32(ha, CRB_DMA_SHIFT, QLA82XX_DMA_SHIFT_VALUE);
 
 	/* Put both the PEG CMD and RCV PEG to default state
 	 * of 0 before resetting the hardware
@@ -2882,7 +2891,7 @@
 	return QLA_FUNCTION_FAILED;
 }
 
-uint32_t *
+static uint32_t *
 qla82xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
 	uint32_t length)
 {
@@ -2903,7 +2912,7 @@
 	return dwptr;
 }
 
-int
+static int
 qla82xx_unprotect_flash(struct qla_hw_data *ha)
 {
 	int ret;
@@ -2934,7 +2943,7 @@
 	return ret;
 }
 
-int
+static int
 qla82xx_protect_flash(struct qla_hw_data *ha)
 {
 	int ret;
@@ -2963,7 +2972,7 @@
 	return ret;
 }
 
-int
+static int
 qla82xx_erase_sector(struct qla_hw_data *ha, int addr)
 {
 	int ret = 0;
@@ -3156,6 +3165,20 @@
 	}
 }
 
+void qla82xx_rom_lock_recovery(struct qla_hw_data *ha)
+{
+	if (qla82xx_rom_lock(ha))
+		/* Someone else is holding the lock. */
+		qla_printk(KERN_INFO, ha, "Resetting rom_lock\n");
+
+	/*
+	 * Either we got the lock, or someone
+	 * else died while holding it.
+	 * In either case, unlock.
+	 */
+	qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
+}
+
 /*
  * qla82xx_device_bootstrap
  *    Initialize device, set DEV_READY, start fw
@@ -3170,12 +3193,13 @@
 static int
 qla82xx_device_bootstrap(scsi_qla_host_t *vha)
 {
-	int rval, i, timeout;
+	int rval = QLA_SUCCESS;
+	int i, timeout;
 	uint32_t old_count, count;
 	struct qla_hw_data *ha = vha->hw;
+	int need_reset = 0, peg_stuck = 1;
 
-	if (qla82xx_need_reset(ha))
-		goto dev_initialize;
+	need_reset = qla82xx_need_reset(ha);
 
 	old_count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
 
@@ -3189,9 +3213,27 @@
 
 		count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
 		if (count != old_count)
+			peg_stuck = 0;
+	}
+
+	if (need_reset) {
+		/* We are trying to perform a recovery here. */
+		if (peg_stuck)
+			qla82xx_rom_lock_recovery(ha);
+		goto dev_initialize;
+	} else  {
+		/* Start of day for this ha context. */
+		if (peg_stuck) {
+			/* Either we are the first or recovery in progress. */
+			qla82xx_rom_lock_recovery(ha);
+			goto dev_initialize;
+		} else
+			/* Firmware already running. */
 			goto dev_ready;
 	}
 
+	return rval;
+
 dev_initialize:
 	/* set to DEV_INITIALIZING */
 	qla_printk(KERN_INFO, ha, "HW State: INITIALIZING\n");
@@ -3304,6 +3346,9 @@
 	struct qla_hw_data *ha = vha->hw;
 
 	fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
+	/* all 0xff, assume AER/EEH in progress, ignore */
+	if (fw_heartbeat_counter == 0xffffffff)
+		return;
 	if (vha->fw_heartbeat_counter == fw_heartbeat_counter) {
 		vha->seconds_since_last_heartbeat++;
 		/* FW not alive after 2 seconds */
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 15559ca..51ec0c5 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -26,6 +26,7 @@
 #define CRB_RCVPEG_STATE		QLA82XX_REG(0x13c)
 #define BOOT_LOADER_DIMM_STATUS		QLA82XX_REG(0x54)
 #define CRB_DMA_SHIFT			QLA82XX_REG(0xcc)
+#define QLA82XX_DMA_SHIFT_VALUE		0x55555555
 
 #define QLA82XX_HW_H0_CH_HUB_ADR    0x05
 #define QLA82XX_HW_H1_CH_HUB_ADR    0x0E
@@ -583,6 +584,10 @@
 #define	QLA82XX_DRVST_RST_RDY		1
 #define QLA82XX_DRVST_QSNT_RDY		2
 
+/* Different drive active state */
+#define QLA82XX_DRV_NOT_ACTIVE		0
+#define QLA82XX_DRV_ACTIVE		1
+
 /*
  * The PCI VendorID and DeviceID for our board.
  */
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 1e4bff6..800ea92 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1295,17 +1295,12 @@
 qla2xxx_slave_configure(struct scsi_device *sdev)
 {
 	scsi_qla_host_t *vha = shost_priv(sdev->host);
-	struct qla_hw_data *ha = vha->hw;
-	struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
 	struct req_que *req = vha->req;
 
 	if (sdev->tagged_supported)
 		scsi_activate_tcq(sdev, req->max_q_depth);
 	else
 		scsi_deactivate_tcq(sdev, req->max_q_depth);
-
-	rport->dev_loss_tmo = ha->port_down_retry_count;
-
 	return 0;
 }
 
@@ -2141,8 +2136,16 @@
 	else
 		base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER +
 						base_vha->vp_idx;
-	if (IS_QLA2100(ha))
-		host->sg_tablesize = 32;
+
+	/* Set the SG table size based on ISP type */
+	if (!IS_FWI2_CAPABLE(ha)) {
+		if (IS_QLA2100(ha))
+			host->sg_tablesize = 32;
+	} else {
+		if (!IS_QLA82XX(ha))
+			host->sg_tablesize = QLA_SG_ALL;
+	}
+
 	host->max_id = max_id;
 	host->this_id = 255;
 	host->cmd_per_lun = 3;
@@ -3553,6 +3556,11 @@
 	struct qla_hw_data *ha = vha->hw;
 	struct req_que *req;
 
+	if (ha->flags.eeh_busy) {
+		qla2x00_restart_timer(vha, WATCH_INTERVAL);
+		return;
+	}
+
 	if (IS_QLA82XX(ha))
 		qla82xx_watchdog(vha);
 
@@ -3782,8 +3790,21 @@
 		return PCI_ERS_RESULT_CAN_RECOVER;
 	case pci_channel_io_frozen:
 		ha->flags.eeh_busy = 1;
+		/* For ISP82XX complete any pending mailbox cmd */
+		if (IS_QLA82XX(ha)) {
+			ha->flags.fw_hung = 1;
+			if (ha->flags.mbox_busy) {
+				ha->flags.mbox_int = 1;
+				DEBUG2(qla_printk(KERN_ERR, ha,
+					"Due to pci channel io frozen, doing premature "
+					"completion of mbx command\n"));
+				complete(&ha->mbx_intr_comp);
+			}
+		}
 		qla2x00_free_irqs(vha);
 		pci_disable_device(pdev);
+		/* Return back all IOs */
+		qla2x00_abort_all_cmds(vha, DID_RESET << 16);
 		return PCI_ERS_RESULT_NEED_RESET;
 	case pci_channel_io_perm_failure:
 		ha->flags.pci_channel_io_perm_failure = 1;
@@ -3804,6 +3825,9 @@
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 	struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
 
+	if (IS_QLA82XX(ha))
+		return PCI_ERS_RESULT_RECOVERED;
+
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	if (IS_QLA2100(ha) || IS_QLA2200(ha)){
 		stat = RD_REG_DWORD(&reg->hccr);
@@ -3830,6 +3854,109 @@
 		return PCI_ERS_RESULT_RECOVERED;
 }
 
+uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
+{
+	uint32_t rval = QLA_FUNCTION_FAILED;
+	uint32_t drv_active = 0;
+	struct qla_hw_data *ha = base_vha->hw;
+	int fn;
+	struct pci_dev *other_pdev = NULL;
+
+	DEBUG17(qla_printk(KERN_INFO, ha,
+	    "scsi(%ld): In qla82xx_error_recovery\n", base_vha->host_no));
+
+	set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
+
+	if (base_vha->flags.online) {
+		/* Abort all outstanding commands,
+		 * so as to be requeued later */
+		qla2x00_abort_isp_cleanup(base_vha);
+	}
+
+
+	fn = PCI_FUNC(ha->pdev->devfn);
+	while (fn > 0) {
+		fn--;
+		DEBUG17(qla_printk(KERN_INFO, ha,
+		    "Finding pci device at function = 0x%x\n", fn));
+		other_pdev =
+		    pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
+		    ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
+		    fn));
+
+		if (!other_pdev)
+			continue;
+		if (atomic_read(&other_pdev->enable_cnt)) {
+			DEBUG17(qla_printk(KERN_INFO, ha,
+			    "Found PCI func availabe and enabled at 0x%x\n",
+			    fn));
+			pci_dev_put(other_pdev);
+			break;
+		}
+		pci_dev_put(other_pdev);
+	}
+
+	if (!fn) {
+		/* Reset owner */
+		DEBUG17(qla_printk(KERN_INFO, ha,
+		    "This devfn is reset owner = 0x%x\n", ha->pdev->devfn));
+		qla82xx_idc_lock(ha);
+
+		qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+		    QLA82XX_DEV_INITIALIZING);
+
+		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION,
+		    QLA82XX_IDC_VERSION);
+
+		drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+		DEBUG17(qla_printk(KERN_INFO, ha,
+		    "drv_active = 0x%x\n", drv_active));
+
+		qla82xx_idc_unlock(ha);
+		/* Reset if device is not already reset
+		 * drv_active would be 0 if a reset has already been done
+		 */
+		if (drv_active)
+			rval = qla82xx_start_firmware(base_vha);
+		else
+			rval = QLA_SUCCESS;
+		qla82xx_idc_lock(ha);
+
+		if (rval != QLA_SUCCESS) {
+			qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
+			qla82xx_clear_drv_active(ha);
+			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+			    QLA82XX_DEV_FAILED);
+		} else {
+			qla_printk(KERN_INFO, ha, "HW State: READY\n");
+			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+			    QLA82XX_DEV_READY);
+			qla82xx_idc_unlock(ha);
+			ha->flags.fw_hung = 0;
+			rval = qla82xx_restart_isp(base_vha);
+			qla82xx_idc_lock(ha);
+			/* Clear driver state register */
+			qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0);
+			qla82xx_set_drv_active(base_vha);
+		}
+		qla82xx_idc_unlock(ha);
+	} else {
+		DEBUG17(qla_printk(KERN_INFO, ha,
+		    "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;
+			rval = qla82xx_restart_isp(base_vha);
+			qla82xx_idc_lock(ha);
+			qla82xx_set_drv_active(base_vha);
+			qla82xx_idc_unlock(ha);
+		}
+	}
+	clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
+
+	return rval;
+}
+
 static pci_ers_result_t
 qla2xxx_pci_slot_reset(struct pci_dev *pdev)
 {
@@ -3862,15 +3989,23 @@
 	if (rc) {
 		qla_printk(KERN_WARNING, ha,
 		    "Can't re-enable PCI device after reset.\n");
-		return ret;
+		goto exit_slot_reset;
 	}
 
 	rsp = ha->rsp_q_map[0];
 	if (qla2x00_request_irqs(ha, rsp))
-		return ret;
+		goto exit_slot_reset;
 
 	if (ha->isp_ops->pci_config(base_vha))
-		return ret;
+		goto exit_slot_reset;
+
+	if (IS_QLA82XX(ha)) {
+		if (qla82xx_error_recovery(base_vha) == QLA_SUCCESS) {
+			ret = PCI_ERS_RESULT_RECOVERED;
+			goto exit_slot_reset;
+		} else
+			goto exit_slot_reset;
+	}
 
 	while (ha->flags.mbox_busy && retries--)
 		msleep(1000);
@@ -3881,6 +4016,7 @@
 	clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
 
 
+exit_slot_reset:
 	DEBUG17(qla_printk(KERN_WARNING, ha,
 	    "slot_reset-return:ret=%x\n", ret));
 
@@ -3948,6 +4084,7 @@
 
 static struct file_operations apidev_fops = {
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 /**
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 5d4a382..449256f 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -5,6 +5,7 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/pci.h>
 #include "ql4_def.h"
 #include "ql4_glbl.h"
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index ad0ed21..348fba0 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1046,13 +1046,13 @@
 
 	/* If the user actually wanted this page, we can skip the rest */
 	if (page == 0)
-		return -EINVAL;
+		return 0;
 
 	for (i = 0; i < min((int)buf[3], buf_len - 4); i++)
 		if (buf[i + 4] == page)
 			goto found;
 
-	if (i < buf[3] && i > buf_len)
+	if (i < buf[3] && i >= buf_len - 4)
 		/* ran off the end of the buffer, give us benefit of doubt */
 		goto found;
 	/* The device claims it doesn't support the requested page */
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index b02bdc6..2c36bae 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -109,10 +109,12 @@
 #define DEF_PHYSBLK_EXP 0
 #define DEF_LOWEST_ALIGNED 0
 #define DEF_OPT_BLKS 64
-#define DEF_UNMAP_MAX_BLOCKS 0
-#define DEF_UNMAP_MAX_DESC 0
-#define DEF_UNMAP_GRANULARITY 0
+#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
 
 /* bit mask values for scsi_debug_opts */
 #define SCSI_DEBUG_OPT_NOISE   1
@@ -177,10 +179,12 @@
 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 int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
-static int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
-static int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
-static int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
+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_unmap_alignment = DEF_UNMAP_ALIGNMENT;
+static unsigned int scsi_debug_tpws = DEF_TPWS;
+static unsigned int scsi_debug_tpu = DEF_TPU;
 
 static int scsi_debug_cmnd_count = 0;
 
@@ -723,16 +727,9 @@
 	/* Optimal Transfer Length */
 	put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
 
-	if (scsi_debug_unmap_max_desc) {
-		unsigned int blocks;
-
-		if (scsi_debug_unmap_max_blocks)
-			blocks = scsi_debug_unmap_max_blocks;
-		else
-			blocks = 0xffffffff;
-
+	if (scsi_debug_tpu) {
 		/* Maximum Unmap LBA Count */
-		put_unaligned_be32(blocks, &arr[16]);
+		put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
 
 		/* Maximum Unmap Block Descriptor Count */
 		put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
@@ -745,10 +742,9 @@
 	}
 
 	/* Optimal Unmap Granularity */
-	if (scsi_debug_unmap_granularity) {
-		put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
-		return 0x3c; /* Mandatory page length for thin provisioning */
-	}
+	put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
+
+	return 0x3c; /* Mandatory page length for thin provisioning */
 
 	return sizeof(vpdb0_data);
 }
@@ -765,6 +761,21 @@
 	return 0x3c;
 }
 
+/* Thin provisioning VPD page (SBC-3) */
+static int inquiry_evpd_b2(unsigned char *arr)
+{
+	memset(arr, 0, 0x8);
+	arr[0] = 0;			/* threshold exponent */
+
+	if (scsi_debug_tpu)
+		arr[1] = 1 << 7;
+
+	if (scsi_debug_tpws)
+		arr[1] |= 1 << 6;
+
+	return 0x8;
+}
+
 #define SDEBUG_LONG_INQ_SZ 96
 #define SDEBUG_MAX_INQ_ARR_SZ 584
 
@@ -820,6 +831,7 @@
 			arr[n++] = 0x89;  /* ATA information */
 			arr[n++] = 0xb0;  /* Block limits (SBC) */
 			arr[n++] = 0xb1;  /* Block characteristics (SBC) */
+			arr[n++] = 0xb2;  /* Thin provisioning (SBC) */
 			arr[3] = n - 4;	  /* number of supported VPD pages */
 		} else if (0x80 == cmd[2]) { /* unit serial number */
 			arr[1] = cmd[2];	/*sanity */
@@ -867,6 +879,9 @@
 		} 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) */
+			arr[1] = cmd[2];        /*sanity */
+			arr[3] = inquiry_evpd_b2(&arr[4]);
 		} else {
 			/* Illegal request, invalid field in cdb */
 			mk_sense_buffer(devip, ILLEGAL_REQUEST,
@@ -1038,7 +1053,7 @@
 	arr[13] = scsi_debug_physblk_exp & 0xf;
 	arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
 
-	if (scsi_debug_unmap_granularity)
+	if (scsi_debug_tpu || scsi_debug_tpws)
 		arr[14] |= 0x80; /* TPE */
 
 	arr[15] = scsi_debug_lowest_aligned & 0xff;
@@ -2708,6 +2723,8 @@
 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_AUTHOR("Eric Youngdale + Douglas Gilbert");
 MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -2739,10 +2756,12 @@
 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_max_blocks, "max # of blocks can be unmapped in one cmd (def=0)");
-MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=0)");
-MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=0)");
+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)");
 
 static char sdebug_info[256];
 
@@ -3130,7 +3149,7 @@
 {
 	ssize_t count;
 
-	if (scsi_debug_unmap_granularity == 0)
+	if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0)
 		return scnprintf(buf, PAGE_SIZE, "0-%u\n",
 				 sdebug_store_sectors);
 
@@ -3207,16 +3226,7 @@
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host);
 }
 
-static void pseudo_0_release(struct device *dev)
-{
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n");
-}
-
-static struct device pseudo_primary = {
-	.init_name	= "pseudo_0",
-	.release	= pseudo_0_release,
-};
+struct device *pseudo_primary;
 
 static int __init scsi_debug_init(void)
 {
@@ -3322,10 +3332,21 @@
 		memset(dif_storep, 0xff, dif_size);
 	}
 
-	if (scsi_debug_unmap_granularity) {
+	/* Thin Provisioning */
+	if (scsi_debug_tpu || scsi_debug_tpws) {
 		unsigned int map_bytes;
 
-		if (scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) {
+		scsi_debug_unmap_max_blocks =
+			clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
+
+		scsi_debug_unmap_max_desc =
+			clamp(scsi_debug_unmap_max_desc, 0U, 256U);
+
+		scsi_debug_unmap_granularity =
+			clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
+
+		if (scsi_debug_unmap_alignment &&
+		    scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) {
 			printk(KERN_ERR
 			       "%s: ERR: unmap_granularity < unmap_alignment\n",
 			       __func__);
@@ -3352,10 +3373,10 @@
 			map_region(0, 2);
 	}
 
-	ret = device_register(&pseudo_primary);
-	if (ret < 0) {
-		printk(KERN_WARNING "scsi_debug: device_register error: %d\n",
-			ret);
+	pseudo_primary = root_device_register("pseudo_0");
+	if (IS_ERR(pseudo_primary)) {
+		printk(KERN_WARNING "scsi_debug: root_device_register() error\n");
+		ret = PTR_ERR(pseudo_primary);
 		goto free_vm;
 	}
 	ret = bus_register(&pseudo_lld_bus);
@@ -3402,7 +3423,7 @@
 bus_unreg:
 	bus_unregister(&pseudo_lld_bus);
 dev_unreg:
-	device_unregister(&pseudo_primary);
+	root_device_unregister(pseudo_primary);
 free_vm:
 	if (map_storep)
 		vfree(map_storep);
@@ -3423,7 +3444,7 @@
 	do_remove_driverfs_files();
 	driver_unregister(&sdebug_driverfs_driver);
 	bus_unregister(&pseudo_lld_bus);
-	device_unregister(&pseudo_primary);
+	root_device_unregister(pseudo_primary);
 
 	if (dif_storep)
 		vfree(dif_storep);
@@ -3474,7 +3495,7 @@
         spin_unlock(&sdebug_host_list_lock);
 
         sdbg_host->dev.bus = &pseudo_lld_bus;
-        sdbg_host->dev.parent = &pseudo_primary;
+        sdbg_host->dev.parent = pseudo_primary;
         sdbg_host->dev.release = &sdebug_release_adapter;
         dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host);
 
@@ -3642,7 +3663,7 @@
 			errsts = resp_readcap16(SCpnt, devip);
 		else if (cmd[1] == SAI_GET_LBA_STATUS) {
 
-			if (scsi_debug_unmap_max_desc == 0) {
+			if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0) {
 				mk_sense_buffer(devip, ILLEGAL_REQUEST,
 						INVALID_COMMAND_OPCODE, 0);
 				errsts = check_condition_result;
@@ -3753,8 +3774,16 @@
 		}
 		break;
 	case WRITE_SAME_16:
-		if (cmd[1] & 0x8)
-			unmap = 1;
+		if (cmd[1] & 0x8) {
+			if (scsi_debug_tpws == 0) {
+				mk_sense_buffer(devip, ILLEGAL_REQUEST,
+						INVALID_FIELD_IN_CDB, 0);
+				errsts = check_condition_result;
+			} else
+				unmap = 1;
+		}
+		if (errsts)
+			break;
 		/* fall through */
 	case WRITE_SAME:
 		errsts = check_readiness(SCpnt, 0, devip);
@@ -3768,7 +3797,7 @@
 		if (errsts)
 			break;
 
-		if (scsi_debug_unmap_max_desc == 0) {
+		if (scsi_debug_unmap_max_desc == 0 || scsi_debug_tpu == 0) {
 			mk_sense_buffer(devip, ILLEGAL_REQUEST,
 					INVALID_COMMAND_OPCODE, 0);
 			errsts = check_condition_result;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ee02d38..8041fe1 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -968,11 +968,13 @@
  */
 int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 {
-	int error = scsi_init_sgtable(cmd->request, &cmd->sdb, gfp_mask);
+	struct request *rq = cmd->request;
+
+	int error = scsi_init_sgtable(rq, &cmd->sdb, gfp_mask);
 	if (error)
 		goto err_exit;
 
-	if (blk_bidi_rq(cmd->request)) {
+	if (blk_bidi_rq(rq)) {
 		struct scsi_data_buffer *bidi_sdb = kmem_cache_zalloc(
 			scsi_sdb_cache, GFP_ATOMIC);
 		if (!bidi_sdb) {
@@ -980,28 +982,28 @@
 			goto err_exit;
 		}
 
-		cmd->request->next_rq->special = bidi_sdb;
-		error = scsi_init_sgtable(cmd->request->next_rq, bidi_sdb,
-								    GFP_ATOMIC);
+		rq->next_rq->special = bidi_sdb;
+		error = scsi_init_sgtable(rq->next_rq, bidi_sdb, GFP_ATOMIC);
 		if (error)
 			goto err_exit;
 	}
 
-	if (blk_integrity_rq(cmd->request)) {
+	if (blk_integrity_rq(rq)) {
 		struct scsi_data_buffer *prot_sdb = cmd->prot_sdb;
 		int ivecs, count;
 
 		BUG_ON(prot_sdb == NULL);
-		ivecs = blk_rq_count_integrity_sg(cmd->request);
+		ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio);
 
 		if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask)) {
 			error = BLKPREP_DEFER;
 			goto err_exit;
 		}
 
-		count = blk_rq_map_integrity_sg(cmd->request,
+		count = blk_rq_map_integrity_sg(rq->q, rq->bio,
 						prot_sdb->table.sgl);
 		BUG_ON(unlikely(count > ivecs));
+		BUG_ON(unlikely(count > queue_max_integrity_segments(rq->q)));
 
 		cmd->prot_sdb = prot_sdb;
 		cmd->prot_sdb->table.nents = count;
@@ -1625,6 +1627,14 @@
 	blk_queue_max_segments(q, min_t(unsigned short, shost->sg_tablesize,
 					SCSI_MAX_SG_CHAIN_SEGMENTS));
 
+	if (scsi_host_prot_dma(shost)) {
+		shost->sg_prot_tablesize =
+			min_not_zero(shost->sg_prot_tablesize,
+				     (unsigned short)SCSI_MAX_PROT_SG_SEGMENTS);
+		BUG_ON(shost->sg_prot_tablesize < shost->sg_tablesize);
+		blk_queue_max_integrity_segments(q, shost->sg_prot_tablesize);
+	}
+
 	blk_queue_max_hw_sectors(q, shost->max_sectors);
 	blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
 	blk_queue_segment_boundary(q, shost->dma_boundary);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 3d0a1e6..087821f 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -417,9 +417,7 @@
 	starget->reap_ref = 1;
 	dev->parent = get_device(parent);
 	dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id);
-#ifndef CONFIG_SYSFS_DEPRECATED
 	dev->bus = &scsi_bus_type;
-#endif
 	dev->type = &scsi_target_type;
 	starget->id = id;
 	starget->channel = channel;
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index c3f6737..20ad59d 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -251,6 +251,7 @@
 shost_rd_attr(cmd_per_lun, "%hd\n");
 shost_rd_attr(can_queue, "%hd\n");
 shost_rd_attr(sg_tablesize, "%hu\n");
+shost_rd_attr(sg_prot_tablesize, "%hu\n");
 shost_rd_attr(unchecked_isa_dma, "%d\n");
 shost_rd_attr(prot_capabilities, "%u\n");
 shost_rd_attr(prot_guard_type, "%hd\n");
@@ -262,6 +263,7 @@
 	&dev_attr_cmd_per_lun.attr,
 	&dev_attr_can_queue.attr,
 	&dev_attr_sg_tablesize.attr,
+	&dev_attr_sg_prot_tablesize.attr,
 	&dev_attr_unchecked_isa_dma.attr,
 	&dev_attr_proc_name.attr,
 	&dev_attr_scan.attr,
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c
index a87e21c..0172de1 100644
--- a/drivers/scsi/scsi_tgt_if.c
+++ b/drivers/scsi/scsi_tgt_if.c
@@ -22,7 +22,6 @@
 #include <linux/miscdevice.h>
 #include <linux/gfp.h>
 #include <linux/file.h>
-#include <linux/smp_lock.h>
 #include <net/tcp.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -323,7 +322,6 @@
 {
 	tx_ring.tr_idx = rx_ring.tr_idx = 0;
 
-	cycle_kernel_lock();
 	return 0;
 }
 
@@ -333,6 +331,7 @@
 	.poll		= tgt_poll,
 	.write		= tgt_write,
 	.mmap		= tgt_mmap,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice tgt_miscdev = {
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index d7e470a..998c01b 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -53,6 +53,25 @@
 static void fc_bsg_goose_queue(struct fc_rport *);
 
 /*
+ * Module Parameters
+ */
+
+/*
+ * dev_loss_tmo: the default number of seconds that the FC transport
+ *   should insulate the loss of a remote port.
+ *   The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
+ */
+static unsigned int fc_dev_loss_tmo = 60;		/* seconds */
+
+module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(dev_loss_tmo,
+		 "Maximum number of seconds that the FC transport should"
+		 " insulate the loss of a remote port. Once this value is"
+		 " exceeded, the scsi target is removed. Value should be"
+		 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT if"
+		 " fast_io_fail_tmo is not set.");
+
+/*
  * Redefine so that we can have same named attributes in the
  * sdev/starget/host objects.
  */
@@ -408,6 +427,7 @@
 	if (!fc_host->work_q)
 		return -ENOMEM;
 
+	fc_host->dev_loss_tmo = fc_dev_loss_tmo;
 	snprintf(fc_host->devloss_work_q_name,
 		 sizeof(fc_host->devloss_work_q_name),
 		 "fc_dl_%d", shost->host_no);
@@ -462,25 +482,6 @@
 			       NULL);
 
 /*
- * Module Parameters
- */
-
-/*
- * dev_loss_tmo: the default number of seconds that the FC transport
- *   should insulate the loss of a remote port.
- *   The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
- */
-static unsigned int fc_dev_loss_tmo = 60;		/* seconds */
-
-module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(dev_loss_tmo,
-		 "Maximum number of seconds that the FC transport should"
-		 " insulate the loss of a remote port. Once this value is"
-		 " exceeded, the scsi target is removed. Value should be"
-		 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT if"
-		 " fast_io_fail_tmo is not set.");
-
-/*
  * Netlink Infrastructure
  */
 
@@ -830,24 +831,32 @@
 /*
  * dev_loss_tmo attribute
  */
-fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
-static ssize_t
-store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count)
+static int fc_str_to_dev_loss(const char *buf, unsigned long *val)
 {
-	unsigned long val;
-	struct fc_rport *rport = transport_class_to_rport(dev);
+	char *cp;
+
+	*val = simple_strtoul(buf, &cp, 0);
+	if ((*cp && (*cp != '\n')) || (*val < 0))
+		return -EINVAL;
+	/*
+	 * Check for overflow; dev_loss_tmo is u32
+	 */
+	if (*val > UINT_MAX)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int fc_rport_set_dev_loss_tmo(struct fc_rport *rport,
+				     unsigned long val)
+{
 	struct Scsi_Host *shost = rport_to_shost(rport);
 	struct fc_internal *i = to_fc_internal(shost->transportt);
-	char *cp;
+
 	if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
 	    (rport->port_state == FC_PORTSTATE_DELETED) ||
 	    (rport->port_state == FC_PORTSTATE_NOTPRESENT))
 		return -EBUSY;
-	val = simple_strtoul(buf, &cp, 0);
-	if ((*cp && (*cp != '\n')) || (val < 0))
-		return -EINVAL;
-
 	/*
 	 * Check for overflow; dev_loss_tmo is u32
 	 */
@@ -863,6 +872,25 @@
 		return -EINVAL;
 
 	i->f->set_rport_dev_loss_tmo(rport, val);
+	return 0;
+}
+
+fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
+static ssize_t
+store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct fc_rport *rport = transport_class_to_rport(dev);
+	unsigned long val;
+	int rc;
+
+	rc = fc_str_to_dev_loss(buf, &val);
+	if (rc)
+		return rc;
+
+	rc = fc_rport_set_dev_loss_tmo(rport, val);
+	if (rc)
+		return rc;
 	return count;
 }
 static FC_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,
@@ -1608,8 +1636,35 @@
 static FC_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
 			store_fc_private_host_issue_lip);
 
-fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
+static ssize_t
+store_fc_private_host_dev_loss_tmo(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct Scsi_Host *shost = transport_class_to_shost(dev);
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	struct fc_rport *rport;
+	unsigned long val, flags;
+	int rc;
 
+	rc = fc_str_to_dev_loss(buf, &val);
+	if (rc)
+		return rc;
+
+	fc_host_dev_loss_tmo(shost) = val;
+	spin_lock_irqsave(shost->host_lock, flags);
+	list_for_each_entry(rport, &fc_host->rports, peers)
+		fc_rport_set_dev_loss_tmo(rport, val);
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	return count;
+}
+
+fc_private_host_show_function(dev_loss_tmo, "%d\n", 20, );
+static FC_DEVICE_ATTR(host, dev_loss_tmo, S_IRUGO | S_IWUSR,
+		      show_fc_host_dev_loss_tmo,
+		      store_fc_private_host_dev_loss_tmo);
+
+fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
 
 /*
  * Host Statistics Management
@@ -2165,6 +2220,7 @@
 	SETUP_HOST_ATTRIBUTE_RW(system_hostname);
 
 	/* Transport-managed attributes */
+	SETUP_PRIVATE_HOST_ATTRIBUTE_RW(dev_loss_tmo);
 	SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
 	if (ft->issue_fc_host_lip)
 		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip);
@@ -2525,7 +2581,7 @@
 
 	rport->maxframe_size = -1;
 	rport->supported_classes = FC_COS_UNSPECIFIED;
-	rport->dev_loss_tmo = fc_dev_loss_tmo;
+	rport->dev_loss_tmo = fc_host->dev_loss_tmo;
 	memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name));
 	memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name));
 	rport->port_id = ids->port_id;
@@ -4044,11 +4100,54 @@
 /**
  * fc_bsg_remove - Deletes the bsg hooks on fchosts/rports
  * @q:	the request_queue that is to be torn down.
+ *
+ * Notes:
+ *   Before unregistering the queue empty any requests that are blocked
+ *
+ *
  */
 static void
 fc_bsg_remove(struct request_queue *q)
 {
+	struct request *req; /* block request */
+	int counts; /* totals for request_list count and starved */
+
 	if (q) {
+		/* Stop taking in new requests */
+		spin_lock_irq(q->queue_lock);
+		blk_stop_queue(q);
+
+		/* drain all requests in the queue */
+		while (1) {
+			/* need the lock to fetch a request
+			 * this may fetch the same reqeust as the previous pass
+			 */
+			req = blk_fetch_request(q);
+			/* save requests in use and starved */
+			counts = q->rq.count[0] + q->rq.count[1] +
+				q->rq.starved[0] + q->rq.starved[1];
+			spin_unlock_irq(q->queue_lock);
+			/* any requests still outstanding? */
+			if (counts == 0)
+				break;
+
+			/* This may be the same req as the previous iteration,
+			 * always send the blk_end_request_all after a prefetch.
+			 * It is not okay to not end the request because the
+			 * prefetch started the request.
+			 */
+			if (req) {
+				/* return -ENXIO to indicate that this queue is
+				 * going away
+				 */
+				req->errors = -ENXIO;
+				blk_end_request_all(req, -ENXIO);
+			}
+
+			msleep(200); /* allow bsg to possibly finish */
+			spin_lock_irq(q->queue_lock);
+		}
+
 		bsg_unregister_queue(q);
 		blk_cleanup_queue(q);
 	}
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index e84026d..332387a 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -537,7 +537,7 @@
 
 /**
  * iscsi_block_scsi_eh - block scsi eh until session state has transistioned
- * cmd: scsi cmd passed to scsi eh handler
+ * @cmd: scsi cmd passed to scsi eh handler
  *
  * If the session is down this function will wait for the recovery
  * timer to fire or for the session to be logged back in. If the
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index ffa0689..57d1e3e 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -477,7 +477,7 @@
 
 static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
 {
-	rq->timeout = SD_TIMEOUT;
+	rq->timeout = SD_FLUSH_TIMEOUT;
 	rq->retries = SD_MAX_RETRIES;
 	rq->cmd[0] = SYNCHRONIZE_CACHE;
 	rq->cmd_len = 10;
@@ -1072,7 +1072,7 @@
 		 * flush everything.
 		 */
 		res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-				       SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+				       SD_FLUSH_TIMEOUT, SD_MAX_RETRIES, NULL);
 		if (res == 0)
 			break;
 	}
@@ -1498,6 +1498,9 @@
 	unsigned long long lba;
 	unsigned sector_size;
 
+	if (sdp->no_read_capacity_16)
+		return -EINVAL;
+
 	do {
 		memset(cmd, 0, 16);
 		cmd[0] = SERVICE_ACTION_IN;
@@ -1554,7 +1557,7 @@
 	}
 
 	/* Logical blocks per physical block exponent */
-	sdkp->hw_sector_size = (1 << (buffer[13] & 0xf)) * sector_size;
+	sdkp->physical_block_size = (1 << (buffer[13] & 0xf)) * sector_size;
 
 	/* Lowest aligned logical block */
 	alignment = ((buffer[14] & 0x3f) << 8 | buffer[15]) * sector_size;
@@ -1567,7 +1570,7 @@
 		struct request_queue *q = sdp->request_queue;
 
 		sdkp->thin_provisioning = 1;
-		q->limits.discard_granularity = sdkp->hw_sector_size;
+		q->limits.discard_granularity = sdkp->physical_block_size;
 		q->limits.max_discard_sectors = 0xffffffff;
 
 		if (buffer[14] & 0x40) /* TPRZ */
@@ -1626,6 +1629,15 @@
 	sector_size = get_unaligned_be32(&buffer[4]);
 	lba = get_unaligned_be32(&buffer[0]);
 
+	if (sdp->no_read_capacity_16 && (lba == 0xffffffff)) {
+		/* Some buggy (usb cardreader) devices return an lba of
+		   0xffffffff when the want to report a size of 0 (with
+		   which they really mean no media is present) */
+		sdkp->capacity = 0;
+		sdkp->physical_block_size = sector_size;
+		return sector_size;
+	}
+
 	if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) {
 		sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
 			"kernel compiled with support for large block "
@@ -1635,7 +1647,7 @@
 	}
 
 	sdkp->capacity = lba + 1;
-	sdkp->hw_sector_size = sector_size;
+	sdkp->physical_block_size = sector_size;
 	return sector_size;
 }
 
@@ -1756,10 +1768,10 @@
 				  (unsigned long long)sdkp->capacity,
 				  sector_size, cap_str_10, cap_str_2);
 
-			if (sdkp->hw_sector_size != sector_size)
+			if (sdkp->physical_block_size != sector_size)
 				sd_printk(KERN_NOTICE, sdkp,
 					  "%u-byte physical blocks\n",
-					  sdkp->hw_sector_size);
+					  sdkp->physical_block_size);
 		}
 	}
 
@@ -1773,7 +1785,8 @@
 	else if (sector_size == 256)
 		sdkp->capacity >>= 1;
 
-	blk_queue_physical_block_size(sdp->request_queue, sdkp->hw_sector_size);
+	blk_queue_physical_block_size(sdp->request_queue,
+				      sdkp->physical_block_size);
 	sdkp->device->sector_size = sector_size;
 }
 
@@ -2039,14 +2052,24 @@
 		lba_count = get_unaligned_be32(&buffer[20]);
 		desc_count = get_unaligned_be32(&buffer[24]);
 
-		if (lba_count) {
-			q->limits.max_discard_sectors =
-				lba_count * sector_sz >> 9;
-
-			if (desc_count)
+		if (lba_count && desc_count) {
+			if (sdkp->tpvpd && !sdkp->tpu)
+				sdkp->unmap = 0;
+			else
 				sdkp->unmap = 1;
 		}
 
+		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");
+			goto out;
+		}
+
+		if (lba_count)
+			q->limits.max_discard_sectors =
+				lba_count * sector_sz >> 9;
+
 		granularity = get_unaligned_be32(&buffer[28]);
 
 		if (granularity)
@@ -2087,6 +2110,31 @@
 	kfree(buffer);
 }
 
+/**
+ * sd_read_thin_provisioning - Query thin provisioning VPD page
+ * @disk: disk to query
+ */
+static void sd_read_thin_provisioning(struct scsi_disk *sdkp)
+{
+	unsigned char *buffer;
+	const int vpd_len = 8;
+
+	if (sdkp->thin_provisioning == 0)
+		return;
+
+	buffer = kmalloc(vpd_len, GFP_KERNEL);
+
+	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 */
+
+ out:
+	kfree(buffer);
+}
+
 static int sd_try_extended_inquiry(struct scsi_device *sdp)
 {
 	/*
@@ -2109,7 +2157,7 @@
 	struct scsi_disk *sdkp = scsi_disk(disk);
 	struct scsi_device *sdp = sdkp->device;
 	unsigned char *buffer;
-	unsigned ordered;
+	unsigned flush = 0;
 
 	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
 				      "sd_revalidate_disk\n"));
@@ -2138,6 +2186,7 @@
 		sd_read_capacity(sdkp, buffer);
 
 		if (sd_try_extended_inquiry(sdp)) {
+			sd_read_thin_provisioning(sdkp);
 			sd_read_block_limits(sdkp);
 			sd_read_block_characteristics(sdkp);
 		}
@@ -2151,17 +2200,15 @@
 
 	/*
 	 * We now have all cache related info, determine how we deal
-	 * with ordered requests.  Note that as the current SCSI
-	 * dispatch function can alter request order, we cannot use
-	 * QUEUE_ORDERED_TAG_* even when ordered tag is supported.
+	 * with flush requests.
 	 */
-	if (sdkp->WCE)
-		ordered = sdkp->DPOFUA
-			? QUEUE_ORDERED_DRAIN_FUA : QUEUE_ORDERED_DRAIN_FLUSH;
-	else
-		ordered = QUEUE_ORDERED_DRAIN;
+	if (sdkp->WCE) {
+		flush |= REQ_FLUSH;
+		if (sdkp->DPOFUA)
+			flush |= REQ_FUA;
+	}
 
-	blk_queue_ordered(sdkp->disk->queue, ordered);
+	blk_queue_flush(sdkp->disk->queue, flush);
 
 	set_capacity(disk, sdkp->capacity);
 	kfree(buffer);
@@ -2252,11 +2299,10 @@
 	index = sdkp->index;
 	dev = &sdp->sdev_gendev;
 
-	if (index < SD_MAX_DISKS) {
-		gd->major = sd_major((index & 0xf0) >> 4);
-		gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
-		gd->minors = SD_MINORS;
-	}
+	gd->major = sd_major((index & 0xf0) >> 4);
+	gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
+	gd->minors = SD_MINORS;
+
 	gd->fops = &sd_fops;
 	gd->private_data = &sdkp->driver;
 	gd->queue = sdkp->device->request_queue;
@@ -2346,6 +2392,12 @@
 	if (error)
 		goto out_put;
 
+	if (index >= SD_MAX_DISKS) {
+		error = -ENODEV;
+		sdev_printk(KERN_WARNING, sdp, "SCSI disk (sd) name space exhausted.\n");
+		goto out_free_index;
+	}
+
 	error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN);
 	if (error)
 		goto out_free_index;
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index f81a930..55488fa 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -19,6 +19,7 @@
  */
 #define SD_TIMEOUT		(30 * HZ)
 #define SD_MOD_TIMEOUT		(75 * HZ)
+#define SD_FLUSH_TIMEOUT	(60 * HZ)
 
 /*
  * Number of allowed retries
@@ -50,7 +51,7 @@
 	atomic_t	openers;
 	sector_t	capacity;	/* size in 512-byte sectors */
 	u32		index;
-	unsigned short	hw_sector_size;
+	unsigned int	physical_block_size;
 	u8		media_present;
 	u8		write_prot;
 	u8		protection_type;/* Data Integrity Field */
@@ -62,6 +63,9 @@
 	unsigned	first_scan : 1;
 	unsigned	thin_provisioning : 1;
 	unsigned	unmap : 1;
+	unsigned	tpws : 1;
+	unsigned	tpu : 1;
+	unsigned	tpvpd : 1;
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index 84be621..0cb39ff 100644
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -375,21 +375,20 @@
 	unsigned int i, j;
 	u32 phys, virt;
 
-	/* Already remapped? */
-	if (rq->cmd_flags & REQ_INTEGRITY)
-		return 0;
-
 	sdkp = rq->bio->bi_bdev->bd_disk->private_data;
 
 	if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION)
 		return 0;
 
-	rq->cmd_flags |= REQ_INTEGRITY;
 	phys = hw_sector & 0xffffffff;
 
 	__rq_for_each_bio(bio, rq) {
 		struct bio_vec *iv;
 
+		/* Already remapped? */
+		if (bio_flagged(bio, BIO_MAPPED_INTEGRITY))
+			break;
+
 		virt = bio->bi_integrity->bip_sector & 0xffffffff;
 
 		bip_for_each_vec(iv, bio->bi_integrity, i) {
@@ -408,6 +407,8 @@
 
 			kunmap_atomic(sdt, KM_USER0);
 		}
+
+		bio->bi_flags |= BIO_MAPPED_INTEGRITY;
 	}
 
 	return 0;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 78d6163..5428d53 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -49,7 +49,7 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/blktrace_api.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include "scsi.h"
 #include <scsi/scsi_dbg.h>
@@ -103,6 +103,8 @@
 static int sg_add(struct device *, struct class_interface *);
 static void sg_remove(struct device *, struct class_interface *);
 
+static DEFINE_MUTEX(sg_mutex);
+
 static DEFINE_IDR(sg_index_idr);
 static DEFINE_RWLOCK(sg_index_lock);	/* Also used to lock
 							   file descriptor list for device */
@@ -229,7 +231,7 @@
 	int res;
 	int retval;
 
-	lock_kernel();
+	mutex_lock(&sg_mutex);
 	nonseekable_open(inode, filp);
 	SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
 	sdp = sg_get_dev(dev);
@@ -314,7 +316,7 @@
 sg_put:
 	if (sdp)
 		sg_put_dev(sdp);
-	unlock_kernel();
+	mutex_unlock(&sg_mutex);
 	return retval;
 }
 
@@ -1092,9 +1094,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&sg_mutex);
 	ret = sg_ioctl(filp, cmd_in, arg);
-	unlock_kernel();
+	mutex_unlock(&sg_mutex);
 
 	return ret;
 }
@@ -1351,6 +1353,7 @@
 	.mmap = sg_mmap,
 	.release = sg_release,
 	.fasync = sg_fasync,
+	.llseek = no_llseek,
 };
 
 static struct class *sg_sysfs_class;
@@ -1657,7 +1660,7 @@
 	if (sg_allow_dio && hp->flags & SG_FLAG_DIRECT_IO &&
 	    dxfer_dir != SG_DXFER_UNKNOWN && !iov_count &&
 	    !sfp->parentdp->device->host->unchecked_isa_dma &&
-	    blk_rq_aligned(q, hp->dxferp, dxfer_len))
+	    blk_rq_aligned(q, (unsigned long)hp->dxferp, dxfer_len))
 		md = NULL;
 	else
 		md = &map_data;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index ba9c3e0..d7b383c 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -44,7 +44,6 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
 
@@ -76,6 +75,7 @@
 	 CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \
 	 CDC_MRW|CDC_MRW_W|CDC_RAM)
 
+static DEFINE_MUTEX(sr_mutex);
 static int sr_probe(struct device *);
 static int sr_remove(struct device *);
 static int sr_done(struct scsi_cmnd *);
@@ -470,24 +470,24 @@
 	struct scsi_cd *cd;
 	int ret = -ENXIO;
 
-	lock_kernel();
+	mutex_lock(&sr_mutex);
 	cd = scsi_cd_get(bdev->bd_disk);
 	if (cd) {
 		ret = cdrom_open(&cd->cdi, bdev, mode);
 		if (ret)
 			scsi_cd_put(cd);
 	}
-	unlock_kernel();
+	mutex_unlock(&sr_mutex);
 	return ret;
 }
 
 static int sr_block_release(struct gendisk *disk, fmode_t mode)
 {
 	struct scsi_cd *cd = scsi_cd(disk);
-	lock_kernel();
+	mutex_lock(&sr_mutex);
 	cdrom_release(&cd->cdi, mode);
 	scsi_cd_put(cd);
-	unlock_kernel();
+	mutex_unlock(&sr_mutex);
 	return 0;
 }
 
@@ -499,7 +499,7 @@
 	void __user *argp = (void __user *)arg;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&sr_mutex);
 
 	/*
 	 * Send SCSI addressing ioctls directly to mid level, send other
@@ -529,7 +529,7 @@
 	ret = scsi_ioctl(sdev, cmd, argp);
 
 out:
-	unlock_kernel();
+	mutex_unlock(&sr_mutex);
 	return ret;
 }
 
@@ -862,10 +862,16 @@
 static int sr_packet(struct cdrom_device_info *cdi,
 		struct packet_command *cgc)
 {
+	struct scsi_cd *cd = cdi->handle;
+	struct scsi_device *sdev = cd->device;
+
+	if (cgc->cmd[0] == GPCMD_READ_DISC_INFO && sdev->no_read_disc_info)
+		return -EDRIVE_CANT_DO_THIS;
+
 	if (cgc->timeout <= 0)
 		cgc->timeout = IOCTL_TIMEOUT;
 
-	sr_do_ioctl(cdi->handle, cgc);
+	sr_do_ioctl(cd, cgc);
 
 	return cgc->stat;
 }
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 24211d0..5b7388f 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -9,7 +9,7 @@
    Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
    Michael Schaefer, J"org Weule, and Eric Youngdale.
 
-   Copyright 1992 - 2008 Kai Makisara
+   Copyright 1992 - 2010 Kai Makisara
    email Kai.Makisara@kolumbus.fi
 
    Some small formal changes - aeb, 950809
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static const char *verstr = "20081215";
+static const char *verstr = "20100829";
 
 #include <linux/module.h>
 
@@ -39,7 +39,6 @@
 #include <linux/cdev.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/dma.h>
@@ -76,6 +75,7 @@
 #include "st_options.h"
 #include "st.h"
 
+static DEFINE_MUTEX(st_mutex);
 static int buffer_kbs;
 static int max_sg_segs;
 static int try_direct_io = TRY_DIRECT_IO;
@@ -1180,7 +1180,7 @@
 	int dev = TAPE_NR(inode);
 	char *name;
 
-	lock_kernel();
+	mutex_lock(&st_mutex);
 	/*
 	 * We really want to do nonseekable_open(inode, filp); here, but some
 	 * versions of tar incorrectly call lseek on tapes and bail out if that
@@ -1189,7 +1189,7 @@
 	filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
 
 	if (!(STp = scsi_tape_get(dev))) {
-		unlock_kernel();
+		mutex_unlock(&st_mutex);
 		return -ENXIO;
 	}
 
@@ -1200,7 +1200,7 @@
 	if (STp->in_use) {
 		write_unlock(&st_dev_arr_lock);
 		scsi_tape_put(STp);
-		unlock_kernel();
+		mutex_unlock(&st_mutex);
 		DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
 		return (-EBUSY);
 	}
@@ -1249,14 +1249,14 @@
 			retval = (-EIO);
 		goto err_out;
 	}
-	unlock_kernel();
+	mutex_unlock(&st_mutex);
 	return 0;
 
  err_out:
 	normalize_buffer(STp->buffer);
 	STp->in_use = 0;
 	scsi_tape_put(STp);
-	unlock_kernel();
+	mutex_unlock(&st_mutex);
 	return retval;
 
 }
@@ -2696,18 +2696,21 @@
 		}
 		break;
 	case MTWEOF:
+	case MTWEOFI:
 	case MTWSM:
 		if (STp->write_prot)
 			return (-EACCES);
 		cmd[0] = WRITE_FILEMARKS;
 		if (cmd_in == MTWSM)
 			cmd[1] = 2;
+		if (cmd_in == MTWEOFI)
+			cmd[1] |= 1;
 		cmd[2] = (arg >> 16);
 		cmd[3] = (arg >> 8);
 		cmd[4] = arg;
 		timeout = STp->device->request_queue->rq_timeout;
                 DEBC(
-                     if (cmd_in == MTWEOF)
+		     if (cmd_in != MTWSM)
                                printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name,
 				 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
                      else
@@ -2883,8 +2886,8 @@
 		else if (chg_eof)
 			STps->eof = ST_NOEOF;
 
-		if (cmd_in == MTWEOF)
-			STps->rw = ST_IDLE;
+		if (cmd_in == MTWEOF || cmd_in == MTWEOFI)
+			STps->rw = ST_IDLE;  /* prevent automatic WEOF at close */
 	} else { /* SCSI command was not completely successful. Don't return
                     from this block without releasing the SCSI command block! */
 		struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
@@ -2901,7 +2904,7 @@
 		else
 			undone = 0;
 
-		if (cmd_in == MTWEOF &&
+		if ((cmd_in == MTWEOF || cmd_in == MTWEOFI) &&
 		    cmdstatp->have_sense &&
 		    (cmdstatp->flags & SENSE_EOM)) {
 			if (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 0dff3bb..88b1335 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -1381,6 +1381,30 @@
 }
 
 
+/*
+ * 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_360_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	struct async_icount cnow;
+
+	local_irq_disable();
+	cnow = info->state->icount;
+	local_irq_enable();
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+
+	return 0;
+}
+
 static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
@@ -1394,7 +1418,7 @@
 	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
 		return -ENODEV;
 
-	if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	if (cmd != TIOCMIWAIT) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -1477,31 +1501,6 @@
 			return 0;
 #endif
 
-		/* 
-		 * 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.
-		 */
-		case TIOCGICOUNT:
-			local_irq_disable();
-			cnow = info->state->icount;
-			local_irq_enable();
-			p_cuser = (struct serial_icounter_struct *) arg;
-/* 			error = put_user(cnow.cts, &p_cuser->cts); */
-/* 			if (error) return error; */
-/* 			error = put_user(cnow.dsr, &p_cuser->dsr); */
-/* 			if (error) return error; */
-/* 			error = put_user(cnow.rng, &p_cuser->rng); */
-/* 			if (error) return error; */
-/* 			error = put_user(cnow.dcd, &p_cuser->dcd); */
-/* 			if (error) return error; */
-
-			put_user(cnow.cts, &p_cuser->cts);
-			put_user(cnow.dsr, &p_cuser->dsr);
-			put_user(cnow.rng, &p_cuser->rng);
-			put_user(cnow.dcd, &p_cuser->dcd);
-			return 0;
 
 		default:
 			return -ENOIOCTLCMD;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 24110f6..167c4a6 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -31,6 +31,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/tty.h>
+#include <linux/ratelimit.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_reg.h>
 #include <linux/serial_core.h>
@@ -154,12 +155,6 @@
 	unsigned char		lsr_saved_flags;
 #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
 	unsigned char		msr_saved_flags;
-
-	/*
-	 * We provide a per-port pm hook.
-	 */
-	void			(*pm)(struct uart_port *port,
-				      unsigned int state, unsigned int old);
 };
 
 struct irq_info {
@@ -1606,8 +1601,8 @@
 
 		if (l == i->head && pass_counter++ > PASS_LIMIT) {
 			/* If we hit this, we're dead. */
-			printk(KERN_ERR "serial8250: too much work for "
-				"irq%d\n", irq);
+			printk_ratelimited(KERN_ERR
+				"serial8250: too much work for irq%d\n", irq);
 			break;
 		}
 	} while (l != end);
@@ -1722,12 +1717,6 @@
 	mutex_unlock(&hash_mutex);
 }
 
-/* Base timer interval for polling */
-static inline int poll_timeout(int timeout)
-{
-	return timeout > 6 ? (timeout / 2 - 2) : 1;
-}
-
 /*
  * This function is used to handle ports that do not have an
  * interrupt.  This doesn't work very well for 16450's, but gives
@@ -1742,7 +1731,7 @@
 	iir = serial_in(up, UART_IIR);
 	if (!(iir & UART_IIR_NO_INT))
 		serial8250_handle_port(up);
-	mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+	mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
 }
 
 static void serial8250_backup_timeout(unsigned long data)
@@ -1787,7 +1776,7 @@
 
 	/* Standard timer interval plus 0.2s to keep the port running */
 	mod_timer(&up->timer,
-		jiffies + poll_timeout(up->port.timeout) + HZ / 5);
+		jiffies + uart_poll_timeout(&up->port) + HZ / 5);
 }
 
 static unsigned int serial8250_tx_empty(struct uart_port *port)
@@ -1867,15 +1856,17 @@
 	unsigned int status, tmout = 10000;
 
 	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
+	for (;;) {
 		status = serial_in(up, UART_LSR);
 
 		up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
 
+		if ((status & bits) == bits)
+			break;
 		if (--tmout == 0)
 			break;
 		udelay(1);
-	} while ((status & bits) != bits);
+	}
 
 	/* Wait up to 1s for flow control if necessary */
 	if (up->port.flags & UPF_CONS_FLOW) {
@@ -2069,7 +2060,7 @@
 		up->timer.function = serial8250_backup_timeout;
 		up->timer.data = (unsigned long)up;
 		mod_timer(&up->timer, jiffies +
-			  poll_timeout(up->port.timeout) + HZ / 5);
+			uart_poll_timeout(port) + HZ / 5);
 	}
 
 	/*
@@ -2079,7 +2070,7 @@
 	 */
 	if (!is_real_interrupt(up->port.irq)) {
 		up->timer.data = (unsigned long)up;
-		mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+		mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
 	} else {
 		retval = serial_link_irq_chain(up);
 		if (retval)
@@ -2440,16 +2431,24 @@
 		port->flags &= ~UPF_HARDPPS_CD;
 }
 
-static void
-serial8250_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
+
+void serial8250_do_pm(struct uart_port *port, unsigned int state,
+		      unsigned int oldstate)
 {
 	struct uart_8250_port *p = (struct uart_8250_port *)port;
 
 	serial8250_set_sleep(p, state != 0);
+}
+EXPORT_SYMBOL(serial8250_do_pm);
 
-	if (p->pm)
-		p->pm(port, state, oldstate);
+static void
+serial8250_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	if (port->pm)
+		port->pm(port, state, oldstate);
+	else
+		serial8250_do_pm(port, state, oldstate);
 }
 
 static unsigned int serial8250_port_size(struct uart_8250_port *pt)
@@ -2674,6 +2673,16 @@
 
 static struct uart_8250_port serial8250_ports[UART_NR];
 
+static void (*serial8250_isa_config)(int port, struct uart_port *up,
+	unsigned short *capabilities);
+
+void serial8250_set_isa_configurator(
+	void (*v)(int port, struct uart_port *up, unsigned short *capabilities))
+{
+	serial8250_isa_config = v;
+}
+EXPORT_SYMBOL(serial8250_set_isa_configurator);
+
 static void __init serial8250_isa_init_ports(void)
 {
 	struct uart_8250_port *up;
@@ -2719,6 +2728,9 @@
 		up->port.regshift = old_serial_port[i].iomem_reg_shift;
 		set_io_from_upio(&up->port);
 		up->port.irqflags |= irqflag;
+		if (serial8250_isa_config != NULL)
+			serial8250_isa_config(i, &up->port, &up->capabilities);
+
 	}
 }
 
@@ -3010,6 +3022,7 @@
 		port.serial_in		= p->serial_in;
 		port.serial_out		= p->serial_out;
 		port.set_termios	= p->set_termios;
+		port.pm			= p->pm;
 		port.dev		= &dev->dev;
 		port.irqflags		|= irqflag;
 		ret = serial8250_register_port(&port);
@@ -3176,6 +3189,12 @@
 		/*  Possibly override set_termios call */
 		if (port->set_termios)
 			uart->port.set_termios = port->set_termios;
+		if (port->pm)
+			uart->port.pm = port->pm;
+
+		if (serial8250_isa_config != NULL)
+			serial8250_isa_config(0, &uart->port,
+					&uart->capabilities);
 
 		ret = uart_add_one_port(&serial8250_reg, &uart->port);
 		if (ret == 0)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 12900f7..9278164 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -458,6 +458,7 @@
 	int
 	depends on ARM && PLAT_SAMSUNG
 	default 2 if ARCH_S3C2400
+	default 6 if ARCH_S5P6450
 	default 4 if SERIAL_SAMSUNG_UARTS_4
 	default 3
 	help
@@ -526,12 +527,12 @@
 	  Serial port support for the Samsung S3C24A0 SoC
 
 config SERIAL_S3C6400
-	tristate "Samsung S3C6400/S3C6410/S5P6440/S5PC100 Serial port support"
-	depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5PC100)
+	tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support"
+	depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100)
 	select SERIAL_SAMSUNG_UARTS_4
 	default y
 	help
-	  Serial port support for the Samsung S3C6400, S3C6410, S5P6440
+	  Serial port support for the Samsung S3C6400, S3C6410, S5P6440, S5P6450
 	  and S5PC100 SoCs
 
 config SERIAL_S5PV210
@@ -717,13 +718,6 @@
 	  the Intel Moorestown platform. On other systems use the max3100
 	  driver.
 
-config MRST_MAX3110_IRQ
-	boolean "Enable GPIO IRQ for Max3110 over Moorestown"
-	default n
-	depends on SERIAL_MRST_MAX3110 && GPIO_LANGWELL
-	help
-	  This has to be enabled after Moorestown GPIO driver is loaded
-
 config SERIAL_MFD_HSU
 	tristate "Medfield High Speed UART support"
 	depends on PCI
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c
index f8d8a00..7212162 100644
--- a/drivers/serial/altera_uart.c
+++ b/drivers/serial/altera_uart.c
@@ -15,6 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/console.h>
@@ -27,6 +28,8 @@
 #include <linux/altera_uart.h>
 
 #define DRV_NAME "altera_uart"
+#define SERIAL_ALTERA_MAJOR 204
+#define SERIAL_ALTERA_MINOR 213
 
 /*
  * Altera UART register definitions according to the Nios UART datasheet:
@@ -76,13 +79,28 @@
  */
 struct altera_uart {
 	struct uart_port port;
+	struct timer_list tmr;
 	unsigned int sigs;	/* Local copy of line sigs */
 	unsigned short imr;	/* Local IMR mirror */
 };
 
+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));
+}
+
+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));
+}
+
 static unsigned int altera_uart_tx_empty(struct uart_port *port)
 {
-	return (readl(port->membase + ALTERA_UART_STATUS_REG) &
+	return (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
 		ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0;
 }
 
@@ -91,8 +109,7 @@
 	struct altera_uart *pp = container_of(port, struct altera_uart, port);
 	unsigned int sigs;
 
-	sigs =
-	    (readl(port->membase + ALTERA_UART_STATUS_REG) &
+	sigs = (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
 	     ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
 	sigs |= (pp->sigs & TIOCM_RTS);
 
@@ -108,7 +125,7 @@
 		pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
 	else
 		pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
-	writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_start_tx(struct uart_port *port)
@@ -116,7 +133,7 @@
 	struct altera_uart *pp = container_of(port, struct altera_uart, port);
 
 	pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
-	writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_stop_tx(struct uart_port *port)
@@ -124,7 +141,7 @@
 	struct altera_uart *pp = container_of(port, struct altera_uart, port);
 
 	pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
-	writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_stop_rx(struct uart_port *port)
@@ -132,7 +149,7 @@
 	struct altera_uart *pp = container_of(port, struct altera_uart, port);
 
 	pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
-	writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_break_ctl(struct uart_port *port, int break_state)
@@ -145,7 +162,7 @@
 		pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK;
 	else
 		pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK;
-	writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
@@ -168,7 +185,8 @@
 	tty_termios_encode_baud_rate(termios, baud, baud);
 
 	spin_lock_irqsave(&port->lock, flags);
-	writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG);
+	uart_update_timeout(port, termios->c_cflag, baud);
+	altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
@@ -178,14 +196,15 @@
 	unsigned char ch, flag;
 	unsigned short status;
 
-	while ((status = readl(port->membase + ALTERA_UART_STATUS_REG)) &
+	while ((status = altera_uart_readl(port, ALTERA_UART_STATUS_REG)) &
 	       ALTERA_UART_STATUS_RRDY_MSK) {
-		ch = readl(port->membase + ALTERA_UART_RXDATA_REG);
+		ch = altera_uart_readl(port, ALTERA_UART_RXDATA_REG);
 		flag = TTY_NORMAL;
 		port->icount.rx++;
 
 		if (status & ALTERA_UART_STATUS_E_MSK) {
-			writel(status, port->membase + ALTERA_UART_STATUS_REG);
+			altera_uart_writel(port, status,
+					   ALTERA_UART_STATUS_REG);
 
 			if (status & ALTERA_UART_STATUS_BRK_MSK) {
 				port->icount.brk++;
@@ -225,18 +244,18 @@
 
 	if (port->x_char) {
 		/* Send special char - probably flow control */
-		writel(port->x_char, port->membase + ALTERA_UART_TXDATA_REG);
+		altera_uart_writel(port, port->x_char, ALTERA_UART_TXDATA_REG);
 		port->x_char = 0;
 		port->icount.tx++;
 		return;
 	}
 
-	while (readl(port->membase + ALTERA_UART_STATUS_REG) &
+	while (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
 	       ALTERA_UART_STATUS_TRDY_MSK) {
 		if (xmit->head == xmit->tail)
 			break;
-		writel(xmit->buf[xmit->tail],
-		       port->membase + ALTERA_UART_TXDATA_REG);
+		altera_uart_writel(port, xmit->buf[xmit->tail],
+		       ALTERA_UART_TXDATA_REG);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		port->icount.tx++;
 	}
@@ -246,7 +265,7 @@
 
 	if (xmit->head == xmit->tail) {
 		pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
-		writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+		altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 	}
 }
 
@@ -256,7 +275,7 @@
 	struct altera_uart *pp = container_of(port, struct altera_uart, port);
 	unsigned int isr;
 
-	isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr;
+	isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr;
 
 	spin_lock(&port->lock);
 	if (isr & ALTERA_UART_STATUS_RRDY_MSK)
@@ -268,14 +287,23 @@
 	return IRQ_RETVAL(isr);
 }
 
+static void altera_uart_timer(unsigned long data)
+{
+	struct uart_port *port = (void *)data;
+	struct altera_uart *pp = container_of(port, struct altera_uart, port);
+
+	altera_uart_interrupt(0, port);
+	mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
+}
+
 static void altera_uart_config_port(struct uart_port *port, int flags)
 {
 	port->type = PORT_ALTERA_UART;
 
 	/* Clear mask, so no surprise interrupts. */
-	writel(0, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, 0, ALTERA_UART_CONTROL_REG);
 	/* Clear status register */
-	writel(0, port->membase + ALTERA_UART_STATUS_REG);
+	altera_uart_writel(port, 0, ALTERA_UART_STATUS_REG);
 }
 
 static int altera_uart_startup(struct uart_port *port)
@@ -284,6 +312,12 @@
 	unsigned long flags;
 	int ret;
 
+	if (!port->irq) {
+		setup_timer(&pp->tmr, altera_uart_timer, (unsigned long)port);
+		mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
+		return 0;
+	}
+
 	ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED,
 			DRV_NAME, port);
 	if (ret) {
@@ -316,7 +350,10 @@
 
 	spin_unlock_irqrestore(&port->lock, flags);
 
-	free_irq(port->irq, port);
+	if (port->irq)
+		free_irq(port->irq, port);
+	else
+		del_timer_sync(&pp->tmr);
 }
 
 static const char *altera_uart_type(struct uart_port *port)
@@ -384,8 +421,9 @@
 		port->iotype = SERIAL_IO_MEM;
 		port->irq = platp[i].irq;
 		port->uartclk = platp[i].uartclk;
-		port->flags = ASYNC_BOOT_AUTOCONF;
+		port->flags = UPF_BOOT_AUTOCONF;
 		port->ops = &altera_uart_ops;
+		port->private_data = platp;
 	}
 
 	return 0;
@@ -393,7 +431,7 @@
 
 static void altera_uart_console_putc(struct uart_port *port, const char c)
 {
-	while (!(readl(port->membase + ALTERA_UART_STATUS_REG) &
+	while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
 		 ALTERA_UART_STATUS_TRDY_MSK))
 		cpu_relax();
 
@@ -423,7 +461,7 @@
 	if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
 		return -EINVAL;
 	port = &altera_uart_ports[co->index].port;
-	if (port->membase == 0)
+	if (!port->membase)
 		return -ENODEV;
 
 	if (options)
@@ -435,7 +473,7 @@
 static struct uart_driver altera_uart_driver;
 
 static struct console altera_uart_console = {
-	.name	= "ttyS",
+	.name	= "ttyAL",
 	.write	= altera_uart_console_write,
 	.device	= uart_console_device,
 	.setup	= altera_uart_console_setup,
@@ -466,9 +504,9 @@
 static struct uart_driver altera_uart_driver = {
 	.owner		= THIS_MODULE,
 	.driver_name	= DRV_NAME,
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
+	.dev_name	= "ttyAL",
+	.major		= SERIAL_ALTERA_MAJOR,
+	.minor		= SERIAL_ALTERA_MINOR,
 	.nr		= CONFIG_SERIAL_ALTERA_UART_MAXPORTS,
 	.cons		= ALTERA_UART_CONSOLE,
 };
@@ -477,38 +515,55 @@
 {
 	struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
 	struct uart_port *port;
-	int i;
+	struct resource *res_mem;
+	struct resource *res_irq;
+	int i = pdev->id;
 
-	for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) {
-		port = &altera_uart_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_UART;
-		port->mapbase = platp[i].mapbase;
-		port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
-		port->iotype = SERIAL_IO_MEM;
-		port->irq = platp[i].irq;
-		port->uartclk = platp[i].uartclk;
-		port->ops = &altera_uart_ops;
-		port->flags = ASYNC_BOOT_AUTOCONF;
+	if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
+		return -EINVAL;
 
-		uart_add_one_port(&altera_uart_driver, port);
-	}
+	port = &altera_uart_ports[i].port;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res_mem)
+		port->mapbase = res_mem->start;
+	else if (platp->mapbase)
+		port->mapbase = platp->mapbase;
+	else
+		return -EINVAL;
+
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res_irq)
+		port->irq = res_irq->start;
+	else if (platp->irq)
+		port->irq = platp->irq;
+
+	port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
+	if (!port->membase)
+		return -ENOMEM;
+
+	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);
 
 	return 0;
 }
 
 static int __devexit altera_uart_remove(struct platform_device *pdev)
 {
-	struct uart_port *port;
-	int i;
+	struct uart_port *port = &altera_uart_ports[pdev->id].port;
 
-	for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) {
-		port = &altera_uart_ports[i].port;
-		if (port)
-			uart_remove_one_port(&altera_uart_driver, port);
-	}
-
+	uart_remove_one_port(&altera_uart_driver, port);
 	return 0;
 }
 
@@ -550,3 +605,4 @@
 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_ALTERA_MAJOR);
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c
index 5318dd3..6f1b51e2 100644
--- a/drivers/serial/bfin_sport_uart.c
+++ b/drivers/serial/bfin_sport_uart.c
@@ -131,7 +131,12 @@
 	pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
 
 	tclkdiv = sclk / (2 * baud_rate) - 1;
-	rclkdiv = sclk / (2 * baud_rate * 2) - 1;
+	/* The actual uart baud rate of devices vary between +/-2%. The sport
+	 * RX sample rate should be faster than the double of the worst case,
+	 * otherwise, wrong data are received. So, set sport RX clock to be
+	 * 3% faster.
+	 */
+	rclkdiv = sclk / (2 * baud_rate * 2 * 97 / 100) - 1;
 	SPORT_PUT_TCLKDIV(up, tclkdiv);
 	SPORT_PUT_RCLKDIV(up, rclkdiv);
 	SSYNC();
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 66ecc7a..dfcf4b1 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -327,14 +327,13 @@
 {
 	struct circ_buf *xmit = &sport->port.state->xmit;
 
-	while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
+	while (!uart_circ_empty(xmit) &&
+			!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
 		/* send xmit->buf[xmit->tail]
 		 * out the port here */
 		writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		sport->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
 	}
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c
index 93de907..ee43efc 100644
--- a/drivers/serial/ioc3_serial.c
+++ b/drivers/serial/ioc3_serial.c
@@ -2017,6 +2017,7 @@
 	struct ioc3_port *port;
 	struct ioc3_port *ports[PORTS_PER_CARD];
 	int phys_port;
+	int cnt;
 
 	DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, is, idd));
 
@@ -2044,6 +2045,7 @@
 		if (!port) {
 			printk(KERN_WARNING
 			       "IOC3 serial memory not available for port\n");
+			ret = -ENOMEM;
 			goto out4;
 		}
 		spin_lock_init(&port->ip_lock);
@@ -2146,6 +2148,9 @@
 
 	/* error exits that give back resources */
 out4:
+	for (cnt = 0; cnt < phys_port; cnt++)
+		kfree(ports[cnt]);
+
 	kfree(card_ptr);
 	return ret;
 }
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index eaf5450..18f5484 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -172,13 +172,15 @@
 		 	jsm_uart_port_init here! */
 		dev_err(&pdev->dev, "memory allocation for flipbuf failed\n");
 		rc = -ENOMEM;
-		goto out_free_irq;
+		goto out_free_uart;
 	}
 
 	pci_set_drvdata(pdev, brd);
 	pci_save_state(pdev);
 
 	return 0;
+ out_free_uart:
+	jsm_remove_uart_port(brd);
  out_free_irq:
 	jsm_remove_uart_port(brd);
 	free_irq(brd->irq, brd);
diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c
index 39f9a1a..d4b711c 100644
--- a/drivers/serial/kgdboc.c
+++ b/drivers/serial/kgdboc.c
@@ -243,7 +243,7 @@
 
 #ifdef CONFIG_KGDB_SERIAL_CONSOLE
 /* This is only available if kgdboc is a built in for early debugging */
-int __init kgdboc_early_init(char *opt)
+static int __init kgdboc_early_init(char *opt)
 {
 	/* save the first character of the config string because the
 	 * init routine can destroy it.
diff --git a/drivers/serial/max3107.c b/drivers/serial/max3107.c
index 67283c1..910870e 100644
--- a/drivers/serial/max3107.c
+++ b/drivers/serial/max3107.c
@@ -986,12 +986,14 @@
 	s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL);
 	if (!s->rxbuf) {
 		pr_err("Allocating RX buffer failed\n");
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err_free4;
 	}
 	s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL);
 	if (!s->rxstr) {
 		pr_err("Allocating RX buffer failed\n");
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err_free3;
 	}
 	/* SPI Tx buffer
 	 * SPI transfer buffer
@@ -1002,7 +1004,8 @@
 	s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL);
 	if (!s->txbuf) {
 		pr_err("Allocating TX buffer failed\n");
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err_free2;
 	}
 	/* Initialize shared data lock */
 	spin_lock_init(&s->data_lock);
@@ -1021,13 +1024,15 @@
 	buf[0] = MAX3107_REVID_REG;
 	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
 		dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n");
-		return -EIO;
+		retval = -EIO;
+		goto err_free1;
 	}
 	if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 &&
 		(buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) {
 		dev_err(&s->spi->dev, "REVID %x does not match\n",
 				(buf[0] & MAX3107_SPI_RX_DATA_MASK));
-		return -ENODEV;
+		retval = -ENODEV;
+		goto err_free1;
 	}
 
 	/* Disable all interrupts */
@@ -1047,7 +1052,8 @@
 	/* Perform SPI transfer */
 	if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
 		dev_err(&s->spi->dev, "SPI transfer for init failed\n");
-		return -EIO;
+		retval = -EIO;
+		goto err_free1;
 	}
 
 	/* Register UART driver */
@@ -1055,7 +1061,7 @@
 		retval = uart_register_driver(&max3107_uart_driver);
 		if (retval) {
 			dev_err(&s->spi->dev, "Registering UART driver failed\n");
-			return retval;
+			goto err_free1;
 		}
 		driver_registered = 1;
 	}
@@ -1074,13 +1080,13 @@
 	retval = uart_add_one_port(&max3107_uart_driver, &s->port);
 	if (retval < 0) {
 		dev_err(&s->spi->dev, "Adding UART port failed\n");
-		return retval;
+		goto err_free1;
 	}
 
 	if (pdata->configure) {
 		retval = pdata->configure(s);
 		if (retval < 0)
-			return retval;
+			goto err_free1;
 	}
 
 	/* Go to suspend mode */
@@ -1088,6 +1094,16 @@
 		pdata->hw_suspend(s, 1);
 
 	return 0;
+
+err_free1:
+	kfree(s->txbuf);
+err_free2:
+	kfree(s->rxstr);
+err_free3:
+	kfree(s->rxbuf);
+err_free4:
+	kfree(s);
+	return retval;
 }
 EXPORT_SYMBOL_GPL(max3107_probe);
 
diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c
index 324c385..5fc699e 100644
--- a/drivers/serial/mfd.c
+++ b/drivers/serial/mfd.c
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
+#include <linux/slab.h>
 #include <linux/serial_reg.h>
 #include <linux/circ_buf.h>
 #include <linux/delay.h>
@@ -171,6 +172,9 @@
 	len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
 			"DIV: \t\t0x%08x\n", serial_in(up, UART_DIV));
 
+	if (len > HSU_REGS_BUFSIZE)
+		len = HSU_REGS_BUFSIZE;
+
 	ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
 	kfree(buf);
 	return ret;
@@ -218,6 +222,9 @@
 	len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
 			"D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR));
 
+	if (len > HSU_REGS_BUFSIZE)
+		len = HSU_REGS_BUFSIZE;
+
 	ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
 	kfree(buf);
 	return ret;
@@ -227,12 +234,14 @@
 	.owner		= THIS_MODULE,
 	.open		= hsu_show_regs_open,
 	.read		= port_show_regs,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations dma_regs_ops = {
 	.owner		= THIS_MODULE,
 	.open		= hsu_show_regs_open,
 	.read		= dma_show_regs,
+	.llseek		= default_llseek,
 };
 
 static int hsu_debugfs_init(struct hsu_port *hsu)
@@ -922,39 +931,52 @@
 		cval |= UART_LCR_EPAR;
 
 	/*
+	 * The base clk is 50Mhz, and the baud rate come from:
+	 *	baud = 50M * MUL / (DIV * PS * DLAB)
+	 *
 	 * For those basic low baud rate we can get the direct
-	 * scalar from 2746800, like 115200 = 2746800/24, for those
-	 * higher baud rate, we have to handle them case by case,
-	 * but DIV reg is never touched as its default value 0x3d09
+	 * scalar from 2746800, like 115200 = 2746800/24. For those
+	 * higher baud rate, we handle them case by case, mainly by
+	 * adjusting the MUL/PS registers, and DIV register is kept
+	 * as default value 0x3d09 to make things simple
 	 */
 	baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
-	quot = uart_get_divisor(port, baud);
 
+	quot = 1;
 	switch (baud) {
 	case 3500000:
 		mul = 0x3345;
 		ps = 0xC;
-		quot = 1;
+		break;
+	case 3000000:
+		mul = 0x2EE0;
 		break;
 	case 2500000:
 		mul = 0x2710;
-		ps = 0x10;
-		quot = 1;
 		break;
-	case 18432000:
+	case 2000000:
+		mul = 0x1F40;
+		break;
+	case 1843200:
 		mul = 0x2400;
-		ps = 0x10;
-		quot = 1;
 		break;
 	case 1500000:
-		mul = 0x1D4C;
-		ps = 0xc;
-		quot = 1;
+		mul = 0x1770;
+		break;
+	case 1000000:
+		mul = 0xFA0;
+		break;
+	case 500000:
+		mul = 0x7D0;
 		break;
 	default:
-		;
+		/* Use uart_get_divisor to get quot for other baud rates */
+		quot = 0;
 	}
 
+	if (!quot)
+		quot = uart_get_divisor(port, baud);
+
 	if ((up->port.uartclk / quot) < (2400 * 16))
 		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
 	else if ((up->port.uartclk / quot) < (230400 * 16))
diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c
index f6ad1ec..b62857b 100644
--- a/drivers/serial/mrst_max3110.c
+++ b/drivers/serial/mrst_max3110.c
@@ -1,7 +1,7 @@
 /*
- *  max3110.c - spi uart protocol driver for Maxim 3110 on Moorestown
+ *  mrst_max3110.c - spi uart protocol driver for Maxim 3110
  *
- *  Copyright (C) Intel 2008 Feng Tang <feng.tang@intel.com>
+ * Copyright (c) 2008-2010, 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,20 +29,16 @@
 
 #include <linux/module.h>
 #include <linux/ioport.h>
+#include <linux/irq.h>
 #include <linux/init.h>
 #include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/platform_device.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 
 #include <linux/kthread.h>
-#include <linux/delay.h>
-#include <asm/atomic.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/dw_spi.h>
 
 #include "mrst_max3110.h"
 
@@ -55,7 +51,7 @@
 struct uart_max3110 {
 	struct uart_port port;
 	struct spi_device *spi;
-	char *name;
+	char name[24];
 
 	wait_queue_head_t wq;
 	struct task_struct *main_thread;
@@ -66,35 +62,30 @@
 	u16 cur_conf;
 	u8 clock;
 	u8 parity, word_7bits;
+	u16 irq;
 
 	unsigned long uart_flags;
 
 	/* console related */
 	struct circ_buf con_xmit;
-
-	/* irq related */
-	u16 irq;
 };
 
 /* global data structure, may need be removed */
-struct uart_max3110 *pmax;
-static inline void receive_char(struct uart_max3110 *max, u8 ch);
+static struct uart_max3110 *pmax;
+
 static void receive_chars(struct uart_max3110 *max,
 				unsigned char *str, int len);
-static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf);
-static void max3110_console_receive(struct uart_max3110 *max);
+static int max3110_read_multi(struct uart_max3110 *max, u8 *buf);
+static void max3110_con_receive(struct uart_max3110 *max);
 
-int max3110_write_then_read(struct uart_max3110 *max,
-		const u8 *txbuf, u8 *rxbuf, unsigned len, int always_fast)
+static int max3110_write_then_read(struct uart_max3110 *max,
+		const void *txbuf, void *rxbuf, unsigned len, int always_fast)
 {
 	struct spi_device *spi = max->spi;
 	struct spi_message	message;
 	struct spi_transfer	x;
 	int ret;
 
-	if (!txbuf || !rxbuf)
-		return -EINVAL;
-
 	spi_message_init(&message);
 	memset(&x, 0, sizeof x);
 	x.len = len;
@@ -103,7 +94,7 @@
 	spi_message_add_tail(&x, &message);
 
 	if (always_fast)
-		x.speed_hz = 3125000;
+		x.speed_hz = spi->max_speed_hz;
 	else if (max->baud)
 		x.speed_hz = max->baud;
 
@@ -112,58 +103,80 @@
 	return ret;
 }
 
-/* Write a u16 to the device, and return one u16 read back */
-int max3110_out(struct uart_max3110 *max, const u16 out)
+/* Write a 16b word to the device */
+static int max3110_out(struct uart_max3110 *max, const u16 out)
 {
-	u16 tmp;
+	void *buf;
+	u16 *obuf, *ibuf;
+	u8  ch;
 	int ret;
 
-	ret = max3110_write_then_read(max, (u8 *)&out, (u8 *)&tmp, 2, 1);
-	if (ret)
-		return ret;
+	buf = kzalloc(8, GFP_KERNEL | GFP_DMA);
+	if (!buf)
+		return -ENOMEM;
+
+	obuf = buf;
+	ibuf = buf + 4;
+	*obuf = out;
+	ret = max3110_write_then_read(max, obuf, ibuf, 2, 1);
+	if (ret) {
+		pr_warning(PR_FMT "%s(): get err msg %d when sending 0x%x\n",
+				__func__, ret, out);
+		goto exit;
+	}
 
 	/* If some valid data is read back */
-	if (tmp & MAX3110_READ_DATA_AVAILABLE)
-		receive_char(max, (tmp & 0xff));
+	if (*ibuf & MAX3110_READ_DATA_AVAILABLE) {
+		ch = *ibuf & 0xff;
+		receive_chars(max, &ch, 1);
+	}
 
+exit:
+	kfree(buf);
 	return ret;
 }
 
-#define MAX_READ_LEN	20
 /*
  * This is usually used to read data from SPIC RX FIFO, which doesn't
- * need any delay like flushing character out. It returns how many
- * valide bytes are read back
+ * need any delay like flushing character out.
+ *
+ * Return how many valide bytes are read back
  */
-static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf)
+static int max3110_read_multi(struct uart_max3110 *max, u8 *rxbuf)
 {
-	u16 out[MAX_READ_LEN], in[MAX_READ_LEN];
-	u8 *pbuf, valid_str[MAX_READ_LEN];
-	int i, j, bytelen;
+	void *buf;
+	u16 *obuf, *ibuf;
+	u8 *pbuf, valid_str[M3110_RX_FIFO_DEPTH];
+	int i, j, blen;
 
-	if (len > MAX_READ_LEN) {
-		pr_err(PR_FMT "read len %d is too large\n", len);
+	blen = M3110_RX_FIFO_DEPTH * sizeof(u16);
+	buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA);
+	if (!buf) {
+		pr_warning(PR_FMT "%s(): fail to alloc dma buffer\n", __func__);
 		return 0;
 	}
 
-	bytelen = len * 2;
-	memset(out, 0, bytelen);
-	memset(in, 0, bytelen);
+	/* tx/rx always have the same length */
+	obuf = buf;
+	ibuf = buf + blen;
 
-	if (max3110_write_then_read(max, (u8 *)out, (u8 *)in, bytelen, 1))
+	if (max3110_write_then_read(max, obuf, ibuf, blen, 1)) {
+		kfree(buf);
 		return 0;
+	}
 
-	/* If caller don't provide a buffer, then handle received char */
-	pbuf = buf ? buf : valid_str;
+	/* If caller doesn't provide a buffer, then handle received char */
+	pbuf = rxbuf ? rxbuf : valid_str;
 
-	for (i = 0, j = 0; i < len; i++) {
-		if (in[i] & MAX3110_READ_DATA_AVAILABLE)
-			pbuf[j++] = (u8)(in[i] & 0xff);
+	for (i = 0, j = 0; i < M3110_RX_FIFO_DEPTH; i++) {
+		if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
+			pbuf[j++] = ibuf[i] & 0xff;
 	}
 
 	if (j && (pbuf == valid_str))
 		receive_chars(max, valid_str, j);
 
+	kfree(buf);
 	return j;
 }
 
@@ -177,10 +190,6 @@
 		xmit->buf[xmit->head] = (char)ch;
 		xmit->head = (xmit->head + 1) & (PAGE_SIZE - 1);
 	}
-
-
-	if (!test_and_set_bit(CON_TX_NEEDED, &max->uart_flags))
-		wake_up_process(max->main_thread);
 }
 
 /*
@@ -196,6 +205,9 @@
 		return;
 
 	uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar);
+
+	if (!test_and_set_bit(CON_TX_NEEDED, &pmax->uart_flags))
+		wake_up_process(pmax->main_thread);
 }
 
 static int __init
@@ -209,6 +221,9 @@
 
 	pr_info(PR_FMT "setting up console\n");
 
+	if (co->index == -1)
+		co->index = 0;
+
 	if (!max) {
 		pr_err(PR_FMT "pmax is NULL, return");
 		return -ENODEV;
@@ -239,8 +254,6 @@
 	.data		= &serial_m3110_reg,
 };
 
-#define MRST_CONSOLE	(&serial_m3110_console)
-
 static unsigned int serial_m3110_tx_empty(struct uart_port *port)
 {
 	return 1;
@@ -258,32 +271,44 @@
 }
 
 #define WORDS_PER_XFER	128
-static inline void send_circ_buf(struct uart_max3110 *max,
+static void send_circ_buf(struct uart_max3110 *max,
 				struct circ_buf *xmit)
 {
-	int len, left = 0;
-	u16 obuf[WORDS_PER_XFER], ibuf[WORDS_PER_XFER];
+	void *buf;
+	u16 *obuf, *ibuf;
 	u8 valid_str[WORDS_PER_XFER];
-	int i, j;
+	int i, j, len, blen, dma_size, left, ret = 0;
+
+
+	dma_size = WORDS_PER_XFER * sizeof(u16) * 2;
+	buf = kzalloc(dma_size, GFP_KERNEL | GFP_DMA);
+	if (!buf)
+		return;
+	obuf = buf;
+	ibuf = buf + dma_size/2;
 
 	while (!uart_circ_empty(xmit)) {
 		left = uart_circ_chars_pending(xmit);
 		while (left) {
-			len = (left >= WORDS_PER_XFER) ? WORDS_PER_XFER : left;
+			len = min(left, WORDS_PER_XFER);
+			blen = len * sizeof(u16);
+			memset(ibuf, 0, blen);
 
-			memset(obuf, 0, len * 2);
-			memset(ibuf, 0, len * 2);
 			for (i = 0; i < len; i++) {
 				obuf[i] = (u8)xmit->buf[xmit->tail] | WD_TAG;
 				xmit->tail = (xmit->tail + 1) &
 						(UART_XMIT_SIZE - 1);
 			}
-			max3110_write_then_read(max, (u8 *)obuf,
-						(u8 *)ibuf, len * 2, 0);
+
+			/* Fail to send msg to console is not very critical */
+			ret = max3110_write_then_read(max, obuf, ibuf, blen, 0);
+			if (ret)
+				pr_warning(PR_FMT "%s(): get err msg %d\n",
+						__func__, ret);
 
 			for (i = 0, j = 0; i < len; i++) {
 				if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
-					valid_str[j++] = (u8)(ibuf[i] & 0xff);
+					valid_str[j++] = ibuf[i] & 0xff;
 			}
 
 			if (j)
@@ -293,6 +318,8 @@
 			left -= len;
 		}
 	}
+
+	kfree(buf);
 }
 
 static void transmit_char(struct uart_max3110 *max)
@@ -312,8 +339,10 @@
 		serial_m3110_stop_tx(port);
 }
 
-/* This will be called by uart_write() and tty_write, can't
- * go to sleep */
+/*
+ * This will be called by uart_write() and tty_write, can't
+ * go to sleep
+ */
 static void serial_m3110_start_tx(struct uart_port *port)
 {
 	struct uart_max3110 *max =
@@ -335,7 +364,7 @@
 
 	tty = port->state->port.tty;
 	if (!tty)
-		return;	/* receive some char before the tty is opened */
+		return;
 
 	while (len) {
 		usable = tty_buffer_request_room(tty, len);
@@ -343,32 +372,37 @@
 			tty_insert_flip_string(tty, str, usable);
 			str += usable;
 			port->icount.rx += usable;
-			tty_flip_buffer_push(tty);
 		}
 		len -= usable;
 	}
+	tty_flip_buffer_push(tty);
 }
 
-static inline void receive_char(struct uart_max3110 *max, u8 ch)
-{
-	receive_chars(max, &ch, 1);
-}
-
-static void max3110_console_receive(struct uart_max3110 *max)
+/*
+ * This routine will be used in read_thread or RX IRQ handling,
+ * it will first do one round buffer read(8 words), if there is some
+ * valid RX data, will try to read 5 more rounds till all data
+ * is read out.
+ *
+ * Use stack space as data buffer to save some system load, and chose
+ * 504 Btyes as a threadhold to do a bulk push to upper tty layer when
+ * receiving bulk data, a much bigger buffer may cause stack overflow
+ */
+static void max3110_con_receive(struct uart_max3110 *max)
 {
 	int loop = 1, num, total = 0;
 	u8 recv_buf[512], *pbuf;
 
 	pbuf = recv_buf;
 	do {
-		num = max3110_read_multi(max, 8, pbuf);
+		num = max3110_read_multi(max, pbuf);
 
 		if (num) {
-			loop = 10;
+			loop = 5;
 			pbuf += num;
 			total += num;
 
-			if (total >= 500) {
+			if (total >= 504) {
 				receive_chars(max, recv_buf, total);
 				pbuf = recv_buf;
 				total = 0;
@@ -396,7 +430,7 @@
 		mutex_lock(&max->thread_mutex);
 
 		if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags))
-			max3110_console_receive(max);
+			max3110_con_receive(max);
 
 		/* first handle console output */
 		if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags))
@@ -413,7 +447,6 @@
 	return ret;
 }
 
-#ifdef CONFIG_MRST_MAX3110_IRQ
 static irqreturn_t serial_m3110_irq(int irq, void *dev_id)
 {
 	struct uart_max3110 *max = dev_id;
@@ -425,7 +458,7 @@
 
 	return IRQ_HANDLED;
 }
-#else
+
 /* if don't use RX IRQ, then need a thread to polling read */
 static int max3110_read_thread(void *_max)
 {
@@ -433,9 +466,14 @@
 
 	pr_info(PR_FMT "start read thread\n");
 	do {
-		mutex_lock(&max->thread_mutex);
-		max3110_console_receive(max);
-		mutex_unlock(&max->thread_mutex);
+		/*
+		 * If can't acquire the mutex, it means the main thread
+		 * is running which will also perform the rx job
+		 */
+		if (mutex_trylock(&max->thread_mutex)) {
+			max3110_con_receive(max);
+			mutex_unlock(&max->thread_mutex);
+		}
 
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ / 20);
@@ -443,7 +481,6 @@
 
 	return 0;
 }
-#endif
 
 static int serial_m3110_startup(struct uart_port *port)
 {
@@ -452,33 +489,54 @@
 	u16 config = 0;
 	int ret = 0;
 
-	if (port->line != 0)
+	if (port->line != 0) {
 		pr_err(PR_FMT "uart port startup failed\n");
+		return -1;
+	}
 
-	/* firstly disable all IRQ and config it to 115200, 8n1 */
+	/* Disable all IRQ and config it to 115200, 8n1 */
 	config = WC_TAG | WC_FIFO_ENABLE
 			| WC_1_STOPBITS
 			| WC_8BIT_WORD
 			| WC_BAUD_DR2;
-	ret = max3110_out(max, config);
 
 	/* as we use thread to handle tx/rx, need set low latency */
 	port->state->port.tty->low_latency = 1;
 
-#ifdef CONFIG_MRST_MAX3110_IRQ
-	ret = request_irq(max->irq, serial_m3110_irq,
+	if (max->irq) {
+		max->read_thread = NULL;
+		ret = request_irq(max->irq, serial_m3110_irq,
 				IRQ_TYPE_EDGE_FALLING, "max3110", max);
-	if (ret)
-		return ret;
+		if (ret) {
+			max->irq = 0;
+			pr_err(PR_FMT "unable to allocate IRQ, polling\n");
+		}  else {
+			/* Enable RX IRQ only */
+			config |= WC_RXA_IRQ_ENABLE;
+		}
+	}
 
-	/* enable RX IRQ only */
-	config |= WC_RXA_IRQ_ENABLE;
-	max3110_out(max, config);
-#else
-	/* if IRQ is disabled, start a read thread for input data */
-	max->read_thread =
-		kthread_run(max3110_read_thread, max, "max3110_read");
-#endif
+	if (max->irq == 0) {
+		/* If IRQ is disabled, start a read thread for input data */
+		max->read_thread =
+			kthread_run(max3110_read_thread, max, "max3110_read");
+		if (IS_ERR(max->read_thread)) {
+			ret = PTR_ERR(max->read_thread);
+			max->read_thread = NULL;
+			pr_err(PR_FMT "Can't create read thread!\n");
+			return ret;
+		}
+	}
+
+	ret = max3110_out(max, config);
+	if (ret) {
+		if (max->irq)
+			free_irq(max->irq, max);
+		if (max->read_thread)
+			kthread_stop(max->read_thread);
+		max->read_thread = NULL;
+		return ret;
+	}
 
 	max->cur_conf = config;
 	return 0;
@@ -495,9 +553,8 @@
 		max->read_thread = NULL;
 	}
 
-#ifdef CONFIG_MRST_MAX3110_IRQ
-	free_irq(max->irq, max);
-#endif
+	if (max->irq)
+		free_irq(max->irq, max);
 
 	/* Disable interrupts from this port */
 	config = WC_TAG | WC_SW_SHDI;
@@ -515,8 +572,7 @@
 
 static void serial_m3110_config_port(struct uart_port *port, int flags)
 {
-	/* give it fake type */
-	port->type = PORT_PXA;
+	port->type = PORT_MAX3100;
 }
 
 static int
@@ -551,6 +607,9 @@
 		new_conf |= WC_7BIT_WORD;
 		break;
 	default:
+		/* We only support CS7 & CS8 */
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= CS8;
 	case CS8:
 		cval = UART_LCR_WLEN8;
 		new_conf |= WC_8BIT_WORD;
@@ -559,7 +618,7 @@
 
 	baud = uart_get_baud_rate(port, termios, old, 0, 230400);
 
-	/* first calc the div for 1.8MHZ clock case */
+	/* First calc the div for 1.8MHZ clock case */
 	switch (baud) {
 	case 300:
 		clk_div = WC_BAUD_DR384;
@@ -595,7 +654,7 @@
 		if (max->clock & MAX3110_HIGH_CLK)
 			break;
 	default:
-		/* pick the previous baud rate */
+		/* Pick the previous baud rate */
 		baud = max->baud;
 		clk_div = max->cur_conf & WC_BAUD_DIV_MASK;
 		tty_termios_encode_baud_rate(termios, baud, baud);
@@ -603,15 +662,21 @@
 
 	if (max->clock & MAX3110_HIGH_CLK) {
 		clk_div += 1;
-		/* high clk version max3110 doesn't support B300 */
-		if (baud == 300)
+		/* High clk version max3110 doesn't support B300 */
+		if (baud == 300) {
 			baud = 600;
+			clk_div = WC_BAUD_DR384;
+		}
 		if (baud == 230400)
 			clk_div = WC_BAUD_DR1;
 		tty_termios_encode_baud_rate(termios, baud, baud);
 	}
 
 	new_conf = (new_conf & ~WC_BAUD_DIV_MASK) | clk_div;
+
+	if (unlikely(termios->c_cflag & CMSPAR))
+		termios->c_cflag &= ~CMSPAR;
+
 	if (termios->c_cflag & CSTOPB)
 		new_conf |= WC_2_STOPBITS;
 	else
@@ -631,13 +696,14 @@
 
 	new_conf |= WC_TAG;
 	if (new_conf != max->cur_conf) {
-		max3110_out(max, new_conf);
-		max->cur_conf = new_conf;
-		max->baud = baud;
+		if (!max3110_out(max, new_conf)) {
+			max->cur_conf = new_conf;
+			max->baud = baud;
+		}
 	}
 }
 
-/* don't handle hw handshaking */
+/* Don't handle hw handshaking */
 static unsigned int serial_m3110_get_mctrl(struct uart_port *port)
 {
 	return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR;
@@ -671,7 +737,7 @@
 	.break_ctl	= serial_m3110_break_ctl,
 	.startup	= serial_m3110_startup,
 	.shutdown	= serial_m3110_shutdown,
-	.set_termios	= serial_m3110_set_termios,	/* must have */
+	.set_termios	= serial_m3110_set_termios,
 	.pm		= serial_m3110_pm,
 	.type		= serial_m3110_type,
 	.release_port	= serial_m3110_release_port,
@@ -687,52 +753,60 @@
 	.major		= TTY_MAJOR,
 	.minor		= 64,
 	.nr		= 1,
-	.cons		= MRST_CONSOLE,
+	.cons		= &serial_m3110_console,
 };
 
+#ifdef CONFIG_PM
 static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
 {
+	struct uart_max3110 *max = spi_get_drvdata(spi);
+
+	disable_irq(max->irq);
+	uart_suspend_port(&serial_m3110_reg, &max->port);
+	max3110_out(max, max->cur_conf | WC_SW_SHDI);
 	return 0;
 }
 
 static int serial_m3110_resume(struct spi_device *spi)
 {
+	struct uart_max3110 *max = spi_get_drvdata(spi);
+
+	max3110_out(max, max->cur_conf);
+	uart_resume_port(&serial_m3110_reg, &max->port);
+	enable_irq(max->irq);
 	return 0;
 }
+#else
+#define serial_m3110_suspend	NULL
+#define serial_m3110_resume	NULL
+#endif
 
-static struct dw_spi_chip spi0_uart = {
-	.poll_mode = 1,
-	.enable_dma = 0,
-	.type = SPI_FRF_SPI,
-};
-
-static int serial_m3110_probe(struct spi_device *spi)
+static int __devinit serial_m3110_probe(struct spi_device *spi)
 {
 	struct uart_max3110 *max;
-	int ret;
-	unsigned char *buffer;
+	void *buffer;
 	u16 res;
+	int ret = 0;
+
 	max = kzalloc(sizeof(*max), GFP_KERNEL);
 	if (!max)
 		return -ENOMEM;
 
-	/* set spi info */
-	spi->mode = SPI_MODE_0;
+	/* Set spi info */
 	spi->bits_per_word = 16;
 	max->clock = MAX3110_HIGH_CLK;
-	spi->controller_data = &spi0_uart;
 
 	spi_setup(spi);
 
-	max->port.type = PORT_PXA;	/* need apply for a max3110 type */
-	max->port.fifosize = 2;		/* only have 16b buffer */
+	max->port.type = PORT_MAX3100;
+	max->port.fifosize = 2;		/* Only have 16b buffer */
 	max->port.ops = &serial_m3110_ops;
 	max->port.line = 0;
 	max->port.dev = &spi->dev;
 	max->port.uartclk = 115200;
 
 	max->spi = spi;
-	max->name = spi->modalias;	/* use spi name as the name */
+	strcpy(max->name, spi->modalias);
 	max->irq = (u16)spi->irq;
 
 	mutex_init(&max->thread_mutex);
@@ -754,13 +828,15 @@
 		ret = -ENODEV;
 		goto err_get_page;
 	}
-	buffer = (unsigned char *)__get_free_page(GFP_KERNEL);
+
+	buffer = (void *)__get_free_page(GFP_KERNEL);
 	if (!buffer) {
 		ret = -ENOMEM;
 		goto err_get_page;
 	}
-	max->con_xmit.buf = (unsigned char *)buffer;
-	max->con_xmit.head = max->con_xmit.tail = 0;
+	max->con_xmit.buf = buffer;
+	max->con_xmit.head = 0;
+	max->con_xmit.tail = 0;
 
 	max->main_thread = kthread_run(max3110_main_thread,
 					max, "max3110_main");
@@ -769,8 +845,10 @@
 		goto err_kthread;
 	}
 
+	spi_set_drvdata(spi, max);
 	pmax = max;
-	/* give membase a psudo value to pass serial_core's check */
+
+	/* Give membase a psudo value to pass serial_core's check */
 	max->port.membase = (void *)0xff110000;
 	uart_add_one_port(&serial_m3110_reg, &max->port);
 
@@ -779,19 +857,17 @@
 err_kthread:
 	free_page((unsigned long)buffer);
 err_get_page:
-	pmax = NULL;
 	kfree(max);
 	return ret;
 }
 
-static int max3110_remove(struct spi_device *dev)
+static int __devexit serial_m3110_remove(struct spi_device *dev)
 {
-	struct uart_max3110 *max = pmax;
+	struct uart_max3110 *max = spi_get_drvdata(dev);
 
-	if (!pmax)
+	if (!max)
 		return 0;
 
-	pmax = NULL;
 	uart_remove_one_port(&serial_m3110_reg, &max->port);
 
 	free_page((unsigned long)max->con_xmit.buf);
@@ -810,13 +886,12 @@
 			.owner	= THIS_MODULE,
 	},
 	.probe		= serial_m3110_probe,
-	.remove		= __devexit_p(max3110_remove),
+	.remove		= __devexit_p(serial_m3110_remove),
 	.suspend	= serial_m3110_suspend,
 	.resume		= serial_m3110_resume,
 };
 
-
-int __init serial_m3110_init(void)
+static int __init serial_m3110_init(void)
 {
 	int ret = 0;
 
@@ -831,7 +906,7 @@
 	return ret;
 }
 
-void __exit serial_m3110_exit(void)
+static void __exit serial_m3110_exit(void)
 {
 	spi_unregister_driver(&uart_max3110_driver);
 	uart_unregister_driver(&serial_m3110_reg);
@@ -840,5 +915,5 @@
 module_init(serial_m3110_init);
 module_exit(serial_m3110_exit);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("max3110-uart");
diff --git a/drivers/serial/mrst_max3110.h b/drivers/serial/mrst_max3110.h
index 363478a..d1ef43a 100644
--- a/drivers/serial/mrst_max3110.h
+++ b/drivers/serial/mrst_max3110.h
@@ -56,4 +56,5 @@
 #define WC_BAUD_DR192		(0xE)
 #define WC_BAUD_DR384		(0xF)
 
+#define M3110_RX_FIFO_DEPTH	8
 #endif
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c
index b1156ba..7ac2bf5 100644
--- a/drivers/serial/samsung.c
+++ b/drivers/serial/samsung.c
@@ -1101,7 +1101,7 @@
 	dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);
 
 	port->mapbase = res->start;
-	port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000);
+	port->membase = S3C_VA_UART + (res->start & 0xfffff);
 	ret = platform_get_irq(platdev, 0);
 	if (ret < 0)
 		port->irq = 0;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index cd85112..c4ea146 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1074,10 +1074,10 @@
  * NB: both 1->0 and 0->1 transitions are counted except for
  *     RI where only 0->1 is counted.
  */
-static int uart_get_count(struct uart_state *state,
-			  struct serial_icounter_struct __user *icnt)
+static int uart_get_icount(struct tty_struct *tty,
+			  struct serial_icounter_struct *icount)
 {
-	struct serial_icounter_struct icount;
+	struct uart_state *state = tty->driver_data;
 	struct uart_icount cnow;
 	struct uart_port *uport = state->uart_port;
 
@@ -1085,19 +1085,19 @@
 	memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
 	spin_unlock_irq(&uport->lock);
 
-	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;
+	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 copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+	return 0;
 }
 
 /*
@@ -1150,10 +1150,6 @@
 	case TIOCMIWAIT:
 		ret = uart_wait_modem_status(state, arg);
 		break;
-
-	case TIOCGICOUNT:
-		ret = uart_get_count(state, uarg);
-		break;
 	}
 
 	if (ret != -ENOIOCTLCMD)
@@ -2065,7 +2061,19 @@
 	/*
 	 * Re-enable the console device after suspending.
 	 */
-	if (uart_console(uport)) {
+	if (console_suspend_enabled && uart_console(uport)) {
+		/*
+		 * First try to use the console cflag setting.
+		 */
+		memset(&termios, 0, sizeof(struct ktermios));
+		termios.c_cflag = uport->cons->cflag;
+
+		/*
+		 * If that's unset, use the tty termios setting.
+		 */
+		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);
@@ -2283,6 +2291,7 @@
 #endif
 	.tiocmget	= uart_tiocmget,
 	.tiocmset	= uart_tiocmset,
+	.get_icount	= uart_get_icount,
 #ifdef CONFIG_CONSOLE_POLL
 	.poll_init	= uart_poll_init,
 	.poll_get_char	= uart_poll_get_char,
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 7d475b2..93760b2 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -45,7 +45,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -183,10 +182,8 @@
 {
 	struct serial_info *info = link->priv;
 
-	if (info->multi) {
-		link->conf.Present |= PRESENT_EXT_STATUS;
-		link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
-	}
+	if (info->multi)
+		link->config_flags |= CONF_ENABLE_ESR;
 }
 
 static const struct serial_quirk quirks[] = {
@@ -265,13 +262,6 @@
 static int serial_config(struct pcmcia_device * link);
 
 
-/*======================================================================
-
-    After a card is removed, serial_remove() will unregister
-    the serial device(s), and release the PCMCIA configuration.
-    
-======================================================================*/
-
 static void serial_remove(struct pcmcia_device *link)
 {
 	struct serial_info *info = link->priv;
@@ -314,14 +304,6 @@
 	return 0;
 }
 
-/*======================================================================
-
-    serial_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-======================================================================*/
-
 static int serial_probe(struct pcmcia_device *link)
 {
 	struct serial_info *info;
@@ -335,25 +317,13 @@
 	info->p_dev = link;
 	link->priv = info;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	if (do_sound) {
-		link->conf.Attributes |= CONF_ENABLE_SPKR;
-		link->conf.Status = CCSR_AUDIO_ENA;
-	}
-	link->conf.IntType = INT_MEMORY_AND_IO;
+	link->config_flags |= CONF_ENABLE_IRQ;
+	if (do_sound)
+		link->config_flags |= CONF_ENABLE_SPKR;
 
 	return serial_config(link);
 }
 
-/*======================================================================
-
-    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 serial_detach(struct pcmcia_device *link)
 {
 	struct serial_info *info = link->priv;
@@ -361,11 +331,6 @@
 	dev_dbg(&link->dev, "serial_detach\n");
 
 	/*
-	 * Ensure any outstanding scheduled tasks are completed.
-	 */
-	flush_scheduled_work();
-
-	/*
 	 * Ensure that the ports have been released.
 	 */
 	serial_remove(link);
@@ -430,47 +395,45 @@
 	return -ENODEV;
 }
 
-static int simple_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cf,
-			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
-			       void *priv_data)
+static int simple_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	static const int size_table[2] = { 8, 16 };
 	int *try = priv_data;
 
-	if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
-			cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+	if (p_dev->resource[0]->start == 0)
+		return -ENODEV;
 
-	p_dev->io_lines = ((*try & 0x1) == 0) ?
-			16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+	if ((*try & 0x1) == 0)
+		p_dev->io_lines = 16;
 
-	if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)])
-	    && (cf->io.win[0].base != 0)) {
-		p_dev->resource[0]->start = cf->io.win[0].base;
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -EINVAL;
+	if (p_dev->resource[0]->end != size_table[(*try >> 1)])
+		return -ENODEV;
+
+	p_dev->resource[0]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
-					cistpl_cftable_entry_t *cf,
-					cistpl_cftable_entry_t *dflt,
-					unsigned int vcc,
 					void *priv_data)
 {
 	static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
 	int j;
 
-	if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-		for (j = 0; j < 5; j++) {
-			p_dev->resource[0]->start = base[j];
-			p_dev->io_lines = base[j] ? 16 : 3;
-			if (!pcmcia_request_io(p_dev))
-				return 0;
-		}
+	if (p_dev->io_lines > 3)
+		return -ENODEV;
+
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[0]->end = 8;
+
+	for (j = 0; j < 5; j++) {
+		p_dev->resource[0]->start = base[j];
+		p_dev->io_lines = base[j] ? 16 : 3;
+		if (!pcmcia_request_io(p_dev))
+			return 0;
 	}
 	return -ENODEV;
 }
@@ -480,11 +443,9 @@
 	struct serial_info *info = link->priv;
 	int i = -ENODEV, try;
 
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	link->resource[0]->end = 8;
-
 	/* First pass: look for a config entry that looks normal.
 	 * Two tries: without IO aliases, then with aliases */
+	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_SET_IO;
 	for (try = 0; try < 4; try++)
 		if (!pcmcia_loop_config(link, simple_config_check, &try))
 			goto found_port;
@@ -500,7 +461,7 @@
 
 found_port:
 	if (info->multi && (info->manfid == MANFID_3COM))
-		link->conf.ConfigIndex &= ~(0x08);
+		link->config_index &= ~(0x08);
 
 	/*
 	 * Apply any configuration quirks.
@@ -508,51 +469,50 @@
 	if (info->quirk && info->quirk->config)
 		info->quirk->config(link);
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		return -1;
 	return setup_serial(link, info, link->resource[0]->start, link->irq);
 }
 
-static int multi_config_check(struct pcmcia_device *p_dev,
-			      cistpl_cftable_entry_t *cf,
-			      cistpl_cftable_entry_t *dflt,
-			      unsigned int vcc,
-			      void *priv_data)
+static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	int *base2 = priv_data;
+	int *multi = priv_data;
+
+	if (p_dev->resource[1]->end)
+		return -EINVAL;
 
 	/* The quad port cards have bad CIS's, so just look for a
 	   window larger than 8 ports and assume it will be right */
-	if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
-		p_dev->resource[0]->start = cf->io.win[0].base;
-		p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
-		if (!pcmcia_request_io(p_dev)) {
-			*base2 = p_dev->resource[0]->start + 8;
-			return 0;
-		}
-	}
-	return -ENODEV;
+	if (p_dev->resource[0]->end <= 8)
+		return -EINVAL;
+
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[0]->end = *multi * 8;
+
+	if (pcmcia_request_io(p_dev))
+		return -ENODEV;
+	return 0;
 }
 
 static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
-				       cistpl_cftable_entry_t *cf,
-				       cistpl_cftable_entry_t *dflt,
-				       unsigned int vcc,
 				       void *priv_data)
 {
 	int *base2 = priv_data;
 
-	if (cf->io.nwin == 2) {
-		p_dev->resource[0]->start = cf->io.win[0].base;
-		p_dev->resource[1]->start = cf->io.win[1].base;
-		p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
-		if (!pcmcia_request_io(p_dev)) {
-			*base2 = p_dev->resource[1]->start;
-			return 0;
-		}
-	}
-	return -ENODEV;
+	if (!p_dev->resource[0]->end || !p_dev->resource[1]->end)
+		return -ENODEV;
+
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	if (pcmcia_request_io(p_dev))
+		return -ENODEV;
+
+	*base2 = p_dev->resource[0]->start + 8;
+	return 0;
 }
 
 static int multi_config(struct pcmcia_device *link)
@@ -560,12 +520,12 @@
 	struct serial_info *info = link->priv;
 	int i, base2 = 0;
 
+	link->config_flags |= CONF_AUTO_SET_IO;
 	/* First, look for a generic full-sized window */
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	link->resource[0]->end = info->multi * 8;
-	if (pcmcia_loop_config(link, multi_config_check, &base2)) {
+	if (!pcmcia_loop_config(link, multi_config_check, &info->multi))
+		base2 = link->resource[0]->start + 8;
+	else {
 		/* If that didn't work, look for two windows */
-		link->resource[0]->end = link->resource[1]->end = 8;
 		info->multi = 2;
 		if (pcmcia_loop_config(link, multi_config_check_notpicky,
 				       &base2)) {
@@ -584,7 +544,7 @@
 	if (info->quirk && info->quirk->config)
 		info->quirk->config(link);
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		return -ENODEV;
 
@@ -596,11 +556,11 @@
 				info->prodid == PRODID_POSSIO_GCC)) {
 		int err;
 
-		if (link->conf.ConfigIndex == 1 ||
-		    link->conf.ConfigIndex == 3) {
+		if (link->config_index == 1 ||
+		    link->config_index == 3) {
 			err = setup_serial(link, info, base2,
 					link->irq);
-			base2 = link->resource[0]->start;;
+			base2 = link->resource[0]->start;
 		} else {
 			err = setup_serial(link, info, link->resource[0]->start,
 					link->irq);
@@ -624,33 +584,24 @@
 	return 0;
 }
 
-static int serial_check_for_multi(struct pcmcia_device *p_dev,
-				  cistpl_cftable_entry_t *cf,
-				  cistpl_cftable_entry_t *dflt,
-				  unsigned int vcc,
-				  void *priv_data)
+static int serial_check_for_multi(struct pcmcia_device *p_dev,  void *priv_data)
 {
 	struct serial_info *info = p_dev->priv;
 
-	if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
-		info->multi = cf->io.win[0].len >> 3;
+	if (!p_dev->resource[0]->end)
+		return -EINVAL;
 
-	if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
-		(cf->io.win[1].len == 8))
+	if ((!p_dev->resource[1]->end) && (p_dev->resource[0]->end % 8 == 0))
+		info->multi = p_dev->resource[0]->end >> 3;
+
+	if ((p_dev->resource[1]->end) && (p_dev->resource[0]->end == 8)
+		&& (p_dev->resource[1]->end == 8))
 		info->multi = 2;
 
 	return 0; /* break */
 }
 
 
-/*======================================================================
-
-    serial_config() is scheduled to run after a CARD_INSERTION event
-    is received, to configure the PCMCIA socket, and to make the
-    serial device available to the system.
-
-======================================================================*/
-
 static int serial_config(struct pcmcia_device * link)
 {
 	struct serial_info *info = link->priv;
@@ -894,9 +845,7 @@
 
 static struct pcmcia_driver serial_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "serial_cs",
-	},
+	.name		= "serial_cs",
 	.probe		= serial_probe,
 	.remove		= serial_detach,
 	.id_table	= serial_ids,
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index 9b03d7b..c4bf54b 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -322,6 +322,26 @@
 	return -EINVAL;
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+static int ulite_get_poll_char(struct uart_port *port)
+{
+	if (!(ioread32be(port->membase + ULITE_STATUS)
+						& ULITE_STATUS_RXVALID))
+		return NO_POLL_CHAR;
+
+	return ioread32be(port->membase + ULITE_RX);
+}
+
+static void ulite_put_poll_char(struct uart_port *port, unsigned char ch)
+{
+	while (ioread32be(port->membase + ULITE_STATUS) & ULITE_STATUS_TXFULL)
+		cpu_relax();
+
+	/* write char to device */
+	iowrite32be(ch, port->membase + ULITE_TX);
+}
+#endif
+
 static struct uart_ops ulite_ops = {
 	.tx_empty	= ulite_tx_empty,
 	.set_mctrl	= ulite_set_mctrl,
@@ -338,7 +358,11 @@
 	.release_port	= ulite_release_port,
 	.request_port	= ulite_request_port,
 	.config_port	= ulite_config_port,
-	.verify_port	= ulite_verify_port
+	.verify_port	= ulite_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char	= ulite_get_poll_char,
+	.poll_put_char	= ulite_put_poll_char,
+#endif
 };
 
 /* ---------------------------------------------------------------------
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 91c2f4f..4b9eec6 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -143,10 +143,26 @@
 	  GPIO operations, you should be able to leverage that for better
 	  speed with a custom version of this driver; see the source code.
 
+config SPI_IMX_VER_IMX1
+	def_bool y if SOC_IMX1
+
+config SPI_IMX_VER_0_0
+	def_bool y if SOC_IMX21 || SOC_IMX27
+
+config SPI_IMX_VER_0_4
+	def_bool y if ARCH_MX31
+
+config SPI_IMX_VER_0_7
+	def_bool y if ARCH_MX25 || ARCH_MX35 || ARCH_MX51
+
+config SPI_IMX_VER_2_3
+	def_bool y if ARCH_MX51
+
 config SPI_IMX
 	tristate "Freescale i.MX SPI controllers"
 	depends on ARCH_MXC
 	select SPI_BITBANG
+	default m if IMX_HAVE_PLATFORM_SPI_IMX
 	help
 	  This enables using the Freescale i.MX SPI controllers in master
 	  mode.
@@ -182,12 +198,27 @@
 	  This enables using the Freescale MPC5121 Programmable Serial
 	  Controller in SPI master mode.
 
-config SPI_MPC8xxx
-	tristate "Freescale MPC8xxx SPI controller"
+config SPI_FSL_LIB
+	tristate
 	depends on FSL_SOC
+
+config SPI_FSL_SPI
+	tristate "Freescale SPI controller"
+	depends on FSL_SOC
+	select SPI_FSL_LIB
 	help
-	  This enables using the Freescale MPC8xxx SPI controllers in master
-	  mode.
+	  This enables using the Freescale SPI controllers in master mode.
+	  MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
+	  MPC8569 uses the controller in QE mode, MPC8610 in cpu mode.
+
+config SPI_FSL_ESPI
+	tristate "Freescale eSPI controller"
+	depends on FSL_SOC
+	select SPI_FSL_LIB
+	help
+	  This enables using the Freescale eSPI controllers in master mode.
+	  From MPC8536, 85xx platform uses the controller, and all P10xx,
+	  P20xx, P30xx,P40xx, P50xx uses this controller.
 
 config SPI_OMAP_UWIRE
 	tristate "OMAP1 MicroWire"
@@ -298,6 +329,13 @@
 	help
 	  SPI driver for Freescale STMP37xx/378x SoC SSP interface
 
+config SPI_TOPCLIFF_PCH
+	tristate "Topcliff PCH SPI Controller"
+	depends on PCI
+	help
+	  SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus
+	  used in some x86 embedded processors.
+
 config SPI_TXX9
 	tristate "Toshiba TXx9 SPI controller"
 	depends on GENERIC_GPIO && CPU_TX49XX
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e9cbd18..557aaad 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -2,9 +2,7 @@
 # Makefile for kernel SPI drivers.
 #
 
-ifeq ($(CONFIG_SPI_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG
 
 # small core, mostly translating board-specific
 # config declarations into driver model code
@@ -34,11 +32,14 @@
 obj-$(CONFIG_SPI_MPC512x_PSC)		+= mpc512x_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
-obj-$(CONFIG_SPI_MPC8xxx)		+= spi_mpc8xxx.o
+obj-$(CONFIG_SPI_FSL_LIB)		+= spi_fsl_lib.o
+obj-$(CONFIG_SPI_FSL_ESPI)		+= spi_fsl_espi.o
+obj-$(CONFIG_SPI_FSL_SPI)		+= spi_fsl_spi.o
 obj-$(CONFIG_SPI_PPC4xx)		+= spi_ppc4xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx_hw.o
 obj-$(CONFIG_SPI_S3C64XX)		+= spi_s3c64xx.o
+obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi_topcliff_pch.o
 obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
 obj-$(CONFIG_SPI_XILINX_OF)		+= xilinx_spi_of.o
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c
index 4c37c4e2..fb3d1b3 100644
--- a/drivers/spi/amba-pl022.c
+++ b/drivers/spi/amba-pl022.c
@@ -27,7 +27,6 @@
 /*
  * TODO:
  * - add timeout on polled transfers
- * - add generic DMA framework support
  */
 
 #include <linux/init.h>
@@ -45,6 +44,9 @@
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
 
 /*
  * This macro is used to define some register default values.
@@ -381,6 +383,14 @@
 	enum ssp_reading		read;
 	enum ssp_writing		write;
 	u32				exp_fifo_level;
+	/* DMA settings */
+#ifdef CONFIG_DMA_ENGINE
+	struct dma_chan			*dma_rx_channel;
+	struct dma_chan			*dma_tx_channel;
+	struct sg_table			sgt_rx;
+	struct sg_table			sgt_tx;
+	char				*dummypage;
+#endif
 };
 
 /**
@@ -406,7 +416,7 @@
 	u16 dmacr;
 	u16 cpsr;
 	u8 n_bytes;
-	u8 enable_dma:1;
+	bool enable_dma;
 	enum ssp_reading read;
 	enum ssp_writing write;
 	void (*cs_control) (u32 command);
@@ -763,6 +773,371 @@
 	}
 	return STATE_DONE;
 }
+
+/*
+ * This DMA functionality is only compiled in if we have
+ * access to the generic DMA devices/DMA engine.
+ */
+#ifdef CONFIG_DMA_ENGINE
+static void unmap_free_dma_scatter(struct pl022 *pl022)
+{
+	/* Unmap and free the SG tables */
+	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
+	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+		     pl022->sgt_rx.nents, DMA_FROM_DEVICE);
+	sg_free_table(&pl022->sgt_rx);
+	sg_free_table(&pl022->sgt_tx);
+}
+
+static void dma_callback(void *data)
+{
+	struct pl022 *pl022 = data;
+	struct spi_message *msg = pl022->cur_msg;
+
+	BUG_ON(!pl022->sgt_rx.sgl);
+
+#ifdef VERBOSE_DEBUG
+	/*
+	 * Optionally dump out buffers to inspect contents, this is
+	 * good if you want to convince yourself that the loopback
+	 * read/write contents are the same, when adopting to a new
+	 * DMA engine.
+	 */
+	{
+		struct scatterlist *sg;
+		unsigned int i;
+
+		dma_sync_sg_for_cpu(&pl022->adev->dev,
+				    pl022->sgt_rx.sgl,
+				    pl022->sgt_rx.nents,
+				    DMA_FROM_DEVICE);
+
+		for_each_sg(pl022->sgt_rx.sgl, sg, pl022->sgt_rx.nents, i) {
+			dev_dbg(&pl022->adev->dev, "SPI RX SG ENTRY: %d", i);
+			print_hex_dump(KERN_ERR, "SPI RX: ",
+				       DUMP_PREFIX_OFFSET,
+				       16,
+				       1,
+				       sg_virt(sg),
+				       sg_dma_len(sg),
+				       1);
+		}
+		for_each_sg(pl022->sgt_tx.sgl, sg, pl022->sgt_tx.nents, i) {
+			dev_dbg(&pl022->adev->dev, "SPI TX SG ENTRY: %d", i);
+			print_hex_dump(KERN_ERR, "SPI TX: ",
+				       DUMP_PREFIX_OFFSET,
+				       16,
+				       1,
+				       sg_virt(sg),
+				       sg_dma_len(sg),
+				       1);
+		}
+	}
+#endif
+
+	unmap_free_dma_scatter(pl022);
+
+	/* Update total bytes transfered */
+	msg->actual_length += pl022->cur_transfer->len;
+	if (pl022->cur_transfer->cs_change)
+		pl022->cur_chip->
+			cs_control(SSP_CHIP_DESELECT);
+
+	/* Move to next transfer */
+	msg->state = next_transfer(pl022);
+	tasklet_schedule(&pl022->pump_transfers);
+}
+
+static void setup_dma_scatter(struct pl022 *pl022,
+			      void *buffer,
+			      unsigned int length,
+			      struct sg_table *sgtab)
+{
+	struct scatterlist *sg;
+	int bytesleft = length;
+	void *bufp = buffer;
+	int mapbytes;
+	int i;
+
+	if (buffer) {
+		for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
+			/*
+			 * If there are less bytes left than what fits
+			 * in the current page (plus page alignment offset)
+			 * we just feed in this, else we stuff in as much
+			 * as we can.
+			 */
+			if (bytesleft < (PAGE_SIZE - offset_in_page(bufp)))
+				mapbytes = bytesleft;
+			else
+				mapbytes = PAGE_SIZE - offset_in_page(bufp);
+			sg_set_page(sg, virt_to_page(bufp),
+				    mapbytes, offset_in_page(bufp));
+			bufp += mapbytes;
+			bytesleft -= mapbytes;
+			dev_dbg(&pl022->adev->dev,
+				"set RX/TX target page @ %p, %d bytes, %d left\n",
+				bufp, mapbytes, bytesleft);
+		}
+	} else {
+		/* Map the dummy buffer on every page */
+		for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
+			if (bytesleft < PAGE_SIZE)
+				mapbytes = bytesleft;
+			else
+				mapbytes = PAGE_SIZE;
+			sg_set_page(sg, virt_to_page(pl022->dummypage),
+				    mapbytes, 0);
+			bytesleft -= mapbytes;
+			dev_dbg(&pl022->adev->dev,
+				"set RX/TX to dummy page %d bytes, %d left\n",
+				mapbytes, bytesleft);
+
+		}
+	}
+	BUG_ON(bytesleft);
+}
+
+/**
+ * configure_dma - configures the channels for the next transfer
+ * @pl022: SSP driver's private data structure
+ */
+static int configure_dma(struct pl022 *pl022)
+{
+	struct dma_slave_config rx_conf = {
+		.src_addr = SSP_DR(pl022->phybase),
+		.direction = DMA_FROM_DEVICE,
+		.src_maxburst = pl022->vendor->fifodepth >> 1,
+	};
+	struct dma_slave_config tx_conf = {
+		.dst_addr = SSP_DR(pl022->phybase),
+		.direction = DMA_TO_DEVICE,
+		.dst_maxburst = pl022->vendor->fifodepth >> 1,
+	};
+	unsigned int pages;
+	int ret;
+	int sglen;
+	struct dma_chan *rxchan = pl022->dma_rx_channel;
+	struct dma_chan *txchan = pl022->dma_tx_channel;
+	struct dma_async_tx_descriptor *rxdesc;
+	struct dma_async_tx_descriptor *txdesc;
+	dma_cookie_t cookie;
+
+	/* Check that the channels are available */
+	if (!rxchan || !txchan)
+		return -ENODEV;
+
+	switch (pl022->read) {
+	case READING_NULL:
+		/* Use the same as for writing */
+		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
+		break;
+	case READING_U8:
+		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+		break;
+	case READING_U16:
+		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+		break;
+	case READING_U32:
+		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		break;
+	}
+
+	switch (pl022->write) {
+	case WRITING_NULL:
+		/* Use the same as for reading */
+		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
+		break;
+	case WRITING_U8:
+		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+		break;
+	case WRITING_U16:
+		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+		break;
+	case WRITING_U32:
+		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;;
+		break;
+	}
+
+	/* SPI pecularity: we need to read and write the same width */
+	if (rx_conf.src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+		rx_conf.src_addr_width = tx_conf.dst_addr_width;
+	if (tx_conf.dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+		tx_conf.dst_addr_width = rx_conf.src_addr_width;
+	BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width);
+
+	rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
+				       (unsigned long) &rx_conf);
+	txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
+				       (unsigned long) &tx_conf);
+
+	/* Create sglists for the transfers */
+	pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1;
+	dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages);
+
+	ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_KERNEL);
+	if (ret)
+		goto err_alloc_rx_sg;
+
+	ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_KERNEL);
+	if (ret)
+		goto err_alloc_tx_sg;
+
+	/* Fill in the scatterlists for the RX+TX buffers */
+	setup_dma_scatter(pl022, pl022->rx,
+			  pl022->cur_transfer->len, &pl022->sgt_rx);
+	setup_dma_scatter(pl022, pl022->tx,
+			  pl022->cur_transfer->len, &pl022->sgt_tx);
+
+	/* Map DMA buffers */
+	sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+			   pl022->sgt_rx.nents, DMA_FROM_DEVICE);
+	if (!sglen)
+		goto err_rx_sgmap;
+
+	sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+			   pl022->sgt_tx.nents, DMA_TO_DEVICE);
+	if (!sglen)
+		goto err_tx_sgmap;
+
+	/* Send both scatterlists */
+	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
+				      pl022->sgt_rx.sgl,
+				      pl022->sgt_rx.nents,
+				      DMA_FROM_DEVICE,
+				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!rxdesc)
+		goto err_rxdesc;
+
+	txdesc = txchan->device->device_prep_slave_sg(txchan,
+				      pl022->sgt_tx.sgl,
+				      pl022->sgt_tx.nents,
+				      DMA_TO_DEVICE,
+				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!txdesc)
+		goto err_txdesc;
+
+	/* Put the callback on the RX transfer only, that should finish last */
+	rxdesc->callback = dma_callback;
+	rxdesc->callback_param = pl022;
+
+	/* Submit and fire RX and TX with TX last so we're ready to read! */
+	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);
+
+	return 0;
+
+err_submit_tx:
+err_submit_rx:
+err_txdesc:
+	txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
+err_rxdesc:
+	rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
+	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
+err_tx_sgmap:
+	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+		     pl022->sgt_tx.nents, DMA_FROM_DEVICE);
+err_rx_sgmap:
+	sg_free_table(&pl022->sgt_tx);
+err_alloc_tx_sg:
+	sg_free_table(&pl022->sgt_rx);
+err_alloc_rx_sg:
+	return -ENOMEM;
+}
+
+static int __init pl022_dma_probe(struct pl022 *pl022)
+{
+	dma_cap_mask_t mask;
+
+	/* Try to acquire a generic DMA engine slave channel */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	/*
+	 * We need both RX and TX channels to do DMA, else do none
+	 * of them.
+	 */
+	pl022->dma_rx_channel = dma_request_channel(mask,
+					    pl022->master_info->dma_filter,
+					    pl022->master_info->dma_rx_param);
+	if (!pl022->dma_rx_channel) {
+		dev_err(&pl022->adev->dev, "no RX DMA channel!\n");
+		goto err_no_rxchan;
+	}
+
+	pl022->dma_tx_channel = dma_request_channel(mask,
+					    pl022->master_info->dma_filter,
+					    pl022->master_info->dma_tx_param);
+	if (!pl022->dma_tx_channel) {
+		dev_err(&pl022->adev->dev, "no TX DMA channel!\n");
+		goto err_no_txchan;
+	}
+
+	pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!pl022->dummypage) {
+		dev_err(&pl022->adev->dev, "no DMA dummypage!\n");
+		goto err_no_dummypage;
+	}
+
+	dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n",
+		 dma_chan_name(pl022->dma_rx_channel),
+		 dma_chan_name(pl022->dma_tx_channel));
+
+	return 0;
+
+err_no_dummypage:
+	dma_release_channel(pl022->dma_tx_channel);
+err_no_txchan:
+	dma_release_channel(pl022->dma_rx_channel);
+	pl022->dma_rx_channel = NULL;
+err_no_rxchan:
+	return -ENODEV;
+}
+
+static void terminate_dma(struct pl022 *pl022)
+{
+	struct dma_chan *rxchan = pl022->dma_rx_channel;
+	struct dma_chan *txchan = pl022->dma_tx_channel;
+
+	rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
+	txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
+	unmap_free_dma_scatter(pl022);
+}
+
+static void pl022_dma_remove(struct pl022 *pl022)
+{
+	if (pl022->busy)
+		terminate_dma(pl022);
+	if (pl022->dma_tx_channel)
+		dma_release_channel(pl022->dma_tx_channel);
+	if (pl022->dma_rx_channel)
+		dma_release_channel(pl022->dma_rx_channel);
+	kfree(pl022->dummypage);
+}
+
+#else
+static inline int configure_dma(struct pl022 *pl022)
+{
+	return -ENODEV;
+}
+
+static inline int pl022_dma_probe(struct pl022 *pl022)
+{
+	return 0;
+}
+
+static inline void pl022_dma_remove(struct pl022 *pl022)
+{
+}
+#endif
+
 /**
  * pl022_interrupt_handler - Interrupt handler for SSP controller
  *
@@ -794,14 +1169,17 @@
 	if (unlikely(!irq_status))
 		return IRQ_NONE;
 
-	/* This handles the error code interrupts */
+	/*
+	 * This handles the FIFO interrupts, the timeout
+	 * interrupts are flatly ignored, they cannot be
+	 * trusted.
+	 */
 	if (unlikely(irq_status & SSP_MIS_MASK_RORMIS)) {
 		/*
 		 * Overrun interrupt - bail out since our Data has been
 		 * corrupted
 		 */
-		dev_err(&pl022->adev->dev,
-			"FIFO overrun\n");
+		dev_err(&pl022->adev->dev, "FIFO overrun\n");
 		if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF)
 			dev_err(&pl022->adev->dev,
 				"RXFIFO is full\n");
@@ -896,8 +1274,8 @@
 }
 
 /**
- * pump_transfers - Tasklet function which schedules next interrupt transfer
- * when running in interrupt transfer mode.
+ * pump_transfers - Tasklet function which schedules next transfer
+ * when running in interrupt or DMA transfer mode.
  * @data: SSP driver private data structure
  *
  */
@@ -954,65 +1332,23 @@
 	}
 	/* Flush the FIFOs and let's go! */
 	flush(pl022);
+
+	if (pl022->cur_chip->enable_dma) {
+		if (configure_dma(pl022)) {
+			dev_dbg(&pl022->adev->dev,
+				"configuration of DMA failed, fall back to interrupt mode\n");
+			goto err_config_dma;
+		}
+		return;
+	}
+
+err_config_dma:
 	writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
 }
 
-/**
- * NOT IMPLEMENTED
- * configure_dma - It configures the DMA pipes for DMA transfers
- * @data: SSP driver's private data structure
- *
- */
-static int configure_dma(void *data)
+static void do_interrupt_dma_transfer(struct pl022 *pl022)
 {
-	struct pl022 *pl022 = data;
-	dev_dbg(&pl022->adev->dev, "configure DMA\n");
-	return -ENOTSUPP;
-}
-
-/**
- * do_dma_transfer - It handles transfers of the current message
- * if it is DMA xfer.
- * NOT FULLY IMPLEMENTED
- * @data: SSP driver's private data structure
- */
-static void do_dma_transfer(void *data)
-{
-	struct pl022 *pl022 = data;
-
-	if (configure_dma(data)) {
-		dev_dbg(&pl022->adev->dev, "configuration of DMA Failed!\n");
-		goto err_config_dma;
-	}
-
-	/* TODO: Implememt DMA setup of pipes here */
-
-	/* Enable target chip, set up transfer */
-	pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
-	if (set_up_next_transfer(pl022, pl022->cur_transfer)) {
-		/* Error path */
-		pl022->cur_msg->state = STATE_ERROR;
-		pl022->cur_msg->status = -EIO;
-		giveback(pl022);
-		return;
-	}
-	/* Enable SSP */
-	writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
-	       SSP_CR1(pl022->virtbase));
-
-	/* TODO: Enable the DMA transfer here */
-	return;
-
- err_config_dma:
-	pl022->cur_msg->state = STATE_ERROR;
-	pl022->cur_msg->status = -EIO;
-	giveback(pl022);
-	return;
-}
-
-static void do_interrupt_transfer(void *data)
-{
-	struct pl022 *pl022 = data;
+	u32 irqflags = ENABLE_ALL_INTERRUPTS;
 
 	/* Enable target chip */
 	pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
@@ -1023,15 +1359,26 @@
 		giveback(pl022);
 		return;
 	}
+	/* If we're using DMA, set up DMA here */
+	if (pl022->cur_chip->enable_dma) {
+		/* Configure DMA transfer */
+		if (configure_dma(pl022)) {
+			dev_dbg(&pl022->adev->dev,
+				"configuration of DMA failed, fall back to interrupt mode\n");
+			goto err_config_dma;
+		}
+		/* Disable interrupts in DMA mode, IRQ from DMA controller */
+		irqflags = DISABLE_ALL_INTERRUPTS;
+	}
+err_config_dma:
 	/* Enable SSP, turn on interrupts */
 	writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
 	       SSP_CR1(pl022->virtbase));
-	writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
+	writew(irqflags, SSP_IMSC(pl022->virtbase));
 }
 
-static void do_polling_transfer(void *data)
+static void do_polling_transfer(struct pl022 *pl022)
 {
-	struct pl022 *pl022 = data;
 	struct spi_message *message = NULL;
 	struct spi_transfer *transfer = NULL;
 	struct spi_transfer *previous = NULL;
@@ -1101,7 +1448,7 @@
  *
  * This function checks if there is any spi message in the queue that
  * needs processing and delegate control to appropriate function
- * do_polling_transfer()/do_interrupt_transfer()/do_dma_transfer()
+ * do_polling_transfer()/do_interrupt_dma_transfer()
  * based on the kind of the transfer
  *
  */
@@ -1150,10 +1497,8 @@
 
 	if (pl022->cur_chip->xfer_type == POLLING_TRANSFER)
 		do_polling_transfer(pl022);
-	else if (pl022->cur_chip->xfer_type == INTERRUPT_TRANSFER)
-		do_interrupt_transfer(pl022);
 	else
-		do_dma_transfer(pl022);
+		do_interrupt_dma_transfer(pl022);
 }
 
 
@@ -1248,100 +1593,56 @@
 }
 
 static int verify_controller_parameters(struct pl022 *pl022,
-					struct pl022_config_chip *chip_info)
+				struct pl022_config_chip const *chip_info)
 {
-	if ((chip_info->lbm != LOOPBACK_ENABLED)
-	    && (chip_info->lbm != LOOPBACK_DISABLED)) {
-		dev_err(chip_info->dev,
-			"loopback Mode is configured incorrectly\n");
-		return -EINVAL;
-	}
 	if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI)
 	    || (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) {
-		dev_err(chip_info->dev,
+		dev_err(&pl022->adev->dev,
 			"interface is configured incorrectly\n");
 		return -EINVAL;
 	}
 	if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) &&
 	    (!pl022->vendor->unidir)) {
-		dev_err(chip_info->dev,
+		dev_err(&pl022->adev->dev,
 			"unidirectional mode not supported in this "
 			"hardware version\n");
 		return -EINVAL;
 	}
 	if ((chip_info->hierarchy != SSP_MASTER)
 	    && (chip_info->hierarchy != SSP_SLAVE)) {
-		dev_err(chip_info->dev,
+		dev_err(&pl022->adev->dev,
 			"hierarchy is configured incorrectly\n");
 		return -EINVAL;
 	}
-	if (((chip_info->clk_freq).cpsdvsr < CPSDVR_MIN)
-	    || ((chip_info->clk_freq).cpsdvsr > CPSDVR_MAX)) {
-		dev_err(chip_info->dev,
-			"cpsdvsr is configured incorrectly\n");
-		return -EINVAL;
-	}
-	if ((chip_info->endian_rx != SSP_RX_MSB)
-	    && (chip_info->endian_rx != SSP_RX_LSB)) {
-		dev_err(chip_info->dev,
-			"RX FIFO endianess is configured incorrectly\n");
-		return -EINVAL;
-	}
-	if ((chip_info->endian_tx != SSP_TX_MSB)
-	    && (chip_info->endian_tx != SSP_TX_LSB)) {
-		dev_err(chip_info->dev,
-			"TX FIFO endianess is configured incorrectly\n");
-		return -EINVAL;
-	}
-	if ((chip_info->data_size < SSP_DATA_BITS_4)
-	    || (chip_info->data_size > SSP_DATA_BITS_32)) {
-		dev_err(chip_info->dev,
-			"DATA Size is configured incorrectly\n");
-		return -EINVAL;
-	}
 	if ((chip_info->com_mode != INTERRUPT_TRANSFER)
 	    && (chip_info->com_mode != DMA_TRANSFER)
 	    && (chip_info->com_mode != POLLING_TRANSFER)) {
-		dev_err(chip_info->dev,
+		dev_err(&pl022->adev->dev,
 			"Communication mode is configured incorrectly\n");
 		return -EINVAL;
 	}
 	if ((chip_info->rx_lev_trig < SSP_RX_1_OR_MORE_ELEM)
 	    || (chip_info->rx_lev_trig > SSP_RX_32_OR_MORE_ELEM)) {
-		dev_err(chip_info->dev,
+		dev_err(&pl022->adev->dev,
 			"RX FIFO Trigger Level is configured incorrectly\n");
 		return -EINVAL;
 	}
 	if ((chip_info->tx_lev_trig < SSP_TX_1_OR_MORE_EMPTY_LOC)
 	    || (chip_info->tx_lev_trig > SSP_TX_32_OR_MORE_EMPTY_LOC)) {
-		dev_err(chip_info->dev,
+		dev_err(&pl022->adev->dev,
 			"TX FIFO Trigger Level is configured incorrectly\n");
 		return -EINVAL;
 	}
-	if (chip_info->iface == SSP_INTERFACE_MOTOROLA_SPI) {
-		if ((chip_info->clk_phase != SSP_CLK_FIRST_EDGE)
-		    && (chip_info->clk_phase != SSP_CLK_SECOND_EDGE)) {
-			dev_err(chip_info->dev,
-				"Clock Phase is configured incorrectly\n");
-			return -EINVAL;
-		}
-		if ((chip_info->clk_pol != SSP_CLK_POL_IDLE_LOW)
-		    && (chip_info->clk_pol != SSP_CLK_POL_IDLE_HIGH)) {
-			dev_err(chip_info->dev,
-				"Clock Polarity is configured incorrectly\n");
-			return -EINVAL;
-		}
-	}
 	if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {
 		if ((chip_info->ctrl_len < SSP_BITS_4)
 		    || (chip_info->ctrl_len > SSP_BITS_32)) {
-			dev_err(chip_info->dev,
+			dev_err(&pl022->adev->dev,
 				"CTRL LEN is configured incorrectly\n");
 			return -EINVAL;
 		}
 		if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO)
 		    && (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) {
-			dev_err(chip_info->dev,
+			dev_err(&pl022->adev->dev,
 				"Wait State is configured incorrectly\n");
 			return -EINVAL;
 		}
@@ -1350,24 +1651,20 @@
 			if ((chip_info->duplex !=
 			     SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
 			    && (chip_info->duplex !=
-				SSP_MICROWIRE_CHANNEL_HALF_DUPLEX))
-				dev_err(chip_info->dev,
+				SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) {
+				dev_err(&pl022->adev->dev,
 					"Microwire duplex mode is configured incorrectly\n");
 				return -EINVAL;
+			}
 		} else {
 			if (chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
-				dev_err(chip_info->dev,
+				dev_err(&pl022->adev->dev,
 					"Microwire half duplex mode requested,"
 					" but this is only available in the"
 					" ST version of PL022\n");
 			return -EINVAL;
 		}
 	}
-	if (chip_info->cs_control == NULL) {
-		dev_warn(chip_info->dev,
-			"Chip Select Function is NULL for this chip\n");
-		chip_info->cs_control = null_cs_control;
-	}
 	return 0;
 }
 
@@ -1467,22 +1764,24 @@
 	return 0;
 }
 
-/**
- * NOT IMPLEMENTED
- * process_dma_info - Processes the DMA info provided by client drivers
- * @chip_info: chip info provided by client device
- * @chip: Runtime state maintained by the SSP controller for each spi device
- *
- * This function processes and stores DMA config provided by client driver
- * into the runtime state maintained by the SSP controller driver
+
+/*
+ * A piece of default chip info unless the platform
+ * supplies it.
  */
-static int process_dma_info(struct pl022_config_chip *chip_info,
-			    struct chip_data *chip)
-{
-	dev_err(chip_info->dev,
-		"cannot process DMA info, DMA not implemented!\n");
-	return -ENOTSUPP;
-}
+static const struct pl022_config_chip pl022_default_chip_info = {
+	.com_mode = POLLING_TRANSFER,
+	.iface = SSP_INTERFACE_MOTOROLA_SPI,
+	.hierarchy = SSP_SLAVE,
+	.slave_tx_disable = DO_NOT_DRIVE_TX,
+	.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
+	.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
+	.ctrl_len = SSP_BITS_8,
+	.wait_state = SSP_MWIRE_WAIT_ZERO,
+	.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
+	.cs_control = null_cs_control,
+};
+
 
 /**
  * pl022_setup - setup function registered to SPI master framework
@@ -1496,23 +1795,15 @@
  * controller hardware here, that is not done until the actual transfer
  * commence.
  */
-
-/* FIXME: JUST GUESSING the spi->mode bits understood by this driver */
-#define MODEBITS	(SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
-			| SPI_LSB_FIRST | SPI_LOOP)
-
 static int pl022_setup(struct spi_device *spi)
 {
-	struct pl022_config_chip *chip_info;
+	struct pl022_config_chip const *chip_info;
 	struct chip_data *chip;
+	struct ssp_clock_params clk_freq;
 	int status = 0;
 	struct pl022 *pl022 = spi_master_get_devdata(spi->master);
-
-	if (spi->mode & ~MODEBITS) {
-		dev_dbg(&spi->dev, "unsupported mode bits %x\n",
-			spi->mode & ~MODEBITS);
-		return -EINVAL;
-	}
+	unsigned int bits = spi->bits_per_word;
+	u32 tmp;
 
 	if (!spi->max_speed_hz)
 		return -EINVAL;
@@ -1535,48 +1826,13 @@
 	chip_info = spi->controller_data;
 
 	if (chip_info == NULL) {
+		chip_info = &pl022_default_chip_info;
 		/* spi_board_info.controller_data not is supplied */
 		dev_dbg(&spi->dev,
 			"using default controller_data settings\n");
-
-		chip_info =
-			kzalloc(sizeof(struct pl022_config_chip), GFP_KERNEL);
-
-		if (!chip_info) {
-			dev_err(&spi->dev,
-				"cannot allocate controller data\n");
-			status = -ENOMEM;
-			goto err_first_setup;
-		}
-
-		dev_dbg(&spi->dev, "allocated memory for controller data\n");
-
-		/* Pointer back to the SPI device */
-		chip_info->dev = &spi->dev;
-		/*
-		 * Set controller data default values:
-		 * Polling is supported by default
-		 */
-		chip_info->lbm = LOOPBACK_DISABLED;
-		chip_info->com_mode = POLLING_TRANSFER;
-		chip_info->iface = SSP_INTERFACE_MOTOROLA_SPI;
-		chip_info->hierarchy = SSP_SLAVE;
-		chip_info->slave_tx_disable = DO_NOT_DRIVE_TX;
-		chip_info->endian_tx = SSP_TX_LSB;
-		chip_info->endian_rx = SSP_RX_LSB;
-		chip_info->data_size = SSP_DATA_BITS_12;
-		chip_info->rx_lev_trig = SSP_RX_1_OR_MORE_ELEM;
-		chip_info->tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC;
-		chip_info->clk_phase = SSP_CLK_SECOND_EDGE;
-		chip_info->clk_pol = SSP_CLK_POL_IDLE_LOW;
-		chip_info->ctrl_len = SSP_BITS_8;
-		chip_info->wait_state = SSP_MWIRE_WAIT_ZERO;
-		chip_info->duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX;
-		chip_info->cs_control = null_cs_control;
-	} else {
+	} else
 		dev_dbg(&spi->dev,
 			"using user supplied controller_data settings\n");
-	}
 
 	/*
 	 * We can override with custom divisors, else we use the board
@@ -1586,29 +1842,48 @@
 	    && (0 == chip_info->clk_freq.scr)) {
 		status = calculate_effective_freq(pl022,
 						  spi->max_speed_hz,
-						  &chip_info->clk_freq);
+						  &clk_freq);
 		if (status < 0)
 			goto err_config_params;
 	} else {
-		if ((chip_info->clk_freq.cpsdvsr % 2) != 0)
-			chip_info->clk_freq.cpsdvsr =
-				chip_info->clk_freq.cpsdvsr - 1;
+		memcpy(&clk_freq, &chip_info->clk_freq, sizeof(clk_freq));
+		if ((clk_freq.cpsdvsr % 2) != 0)
+			clk_freq.cpsdvsr =
+				clk_freq.cpsdvsr - 1;
 	}
+	if ((clk_freq.cpsdvsr < CPSDVR_MIN)
+	    || (clk_freq.cpsdvsr > CPSDVR_MAX)) {
+		dev_err(&spi->dev,
+			"cpsdvsr is configured incorrectly\n");
+		goto err_config_params;
+	}
+
+
 	status = verify_controller_parameters(pl022, chip_info);
 	if (status) {
 		dev_err(&spi->dev, "controller data is incorrect");
 		goto err_config_params;
 	}
+
 	/* Now set controller state based on controller data */
 	chip->xfer_type = chip_info->com_mode;
-	chip->cs_control = chip_info->cs_control;
+	if (!chip_info->cs_control) {
+		chip->cs_control = null_cs_control;
+		dev_warn(&spi->dev,
+			 "chip select function is NULL for this chip\n");
+	} else
+		chip->cs_control = chip_info->cs_control;
 
-	if (chip_info->data_size <= 8) {
-		dev_dbg(&spi->dev, "1 <= n <=8 bits per word\n");
+	if (bits <= 3) {
+		/* PL022 doesn't support less than 4-bits */
+		status = -ENOTSUPP;
+		goto err_config_params;
+	} else if (bits <= 8) {
+		dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n");
 		chip->n_bytes = 1;
 		chip->read = READING_U8;
 		chip->write = WRITING_U8;
-	} else if (chip_info->data_size <= 16) {
+	} else if (bits <= 16) {
 		dev_dbg(&spi->dev, "9 <= n <= 16 bits per word\n");
 		chip->n_bytes = 2;
 		chip->read = READING_U16;
@@ -1625,6 +1900,7 @@
 			dev_err(&spi->dev,
 				"a standard pl022 can only handle "
 				"1 <= n <= 16 bit words\n");
+			status = -ENOTSUPP;
 			goto err_config_params;
 		}
 	}
@@ -1636,9 +1912,8 @@
 	chip->cpsr = 0;
 	if ((chip_info->com_mode == DMA_TRANSFER)
 	    && ((pl022->master_info)->enable_dma)) {
-		chip->enable_dma = 1;
+		chip->enable_dma = true;
 		dev_dbg(&spi->dev, "DMA mode set in controller state\n");
-		status = process_dma_info(chip_info, chip);
 		if (status < 0)
 			goto err_config_params;
 		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
@@ -1646,7 +1921,7 @@
 		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
 			       SSP_DMACR_MASK_TXDMAE, 1);
 	} else {
-		chip->enable_dma = 0;
+		chip->enable_dma = false;
 		dev_dbg(&spi->dev, "DMA mode NOT set in controller state\n");
 		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED,
 			       SSP_DMACR_MASK_RXDMAE, 0);
@@ -1654,10 +1929,12 @@
 			       SSP_DMACR_MASK_TXDMAE, 1);
 	}
 
-	chip->cpsr = chip_info->clk_freq.cpsdvsr;
+	chip->cpsr = clk_freq.cpsdvsr;
 
 	/* Special setup for the ST micro extended control registers */
 	if (pl022->vendor->extended_cr) {
+		u32 etx;
+
 		if (pl022->vendor->pl023) {
 			/* These bits are only in the PL023 */
 			SSP_WRITE_BITS(chip->cr1, chip_info->clkdelay,
@@ -1673,29 +1950,51 @@
 			SSP_WRITE_BITS(chip->cr1, chip_info->wait_state,
 				       SSP_CR1_MASK_MWAIT_ST, 6);
 		}
-		SSP_WRITE_BITS(chip->cr0, chip_info->data_size,
+		SSP_WRITE_BITS(chip->cr0, bits - 1,
 			       SSP_CR0_MASK_DSS_ST, 0);
-		SSP_WRITE_BITS(chip->cr1, chip_info->endian_rx,
-			       SSP_CR1_MASK_RENDN_ST, 4);
-		SSP_WRITE_BITS(chip->cr1, chip_info->endian_tx,
-			       SSP_CR1_MASK_TENDN_ST, 5);
+
+		if (spi->mode & SPI_LSB_FIRST) {
+			tmp = SSP_RX_LSB;
+			etx = SSP_TX_LSB;
+		} else {
+			tmp = SSP_RX_MSB;
+			etx = SSP_TX_MSB;
+		}
+		SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_RENDN_ST, 4);
+		SSP_WRITE_BITS(chip->cr1, etx, SSP_CR1_MASK_TENDN_ST, 5);
 		SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig,
 			       SSP_CR1_MASK_RXIFLSEL_ST, 7);
 		SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig,
 			       SSP_CR1_MASK_TXIFLSEL_ST, 10);
 	} else {
-		SSP_WRITE_BITS(chip->cr0, chip_info->data_size,
+		SSP_WRITE_BITS(chip->cr0, bits - 1,
 			       SSP_CR0_MASK_DSS, 0);
 		SSP_WRITE_BITS(chip->cr0, chip_info->iface,
 			       SSP_CR0_MASK_FRF, 4);
 	}
+
 	/* Stuff that is common for all versions */
-	SSP_WRITE_BITS(chip->cr0, chip_info->clk_pol, SSP_CR0_MASK_SPO, 6);
-	SSP_WRITE_BITS(chip->cr0, chip_info->clk_phase, SSP_CR0_MASK_SPH, 7);
-	SSP_WRITE_BITS(chip->cr0, chip_info->clk_freq.scr, SSP_CR0_MASK_SCR, 8);
+	if (spi->mode & SPI_CPOL)
+		tmp = SSP_CLK_POL_IDLE_HIGH;
+	else
+		tmp = SSP_CLK_POL_IDLE_LOW;
+	SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPO, 6);
+
+	if (spi->mode & SPI_CPHA)
+		tmp = SSP_CLK_SECOND_EDGE;
+	else
+		tmp = SSP_CLK_FIRST_EDGE;
+	SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPH, 7);
+
+	SSP_WRITE_BITS(chip->cr0, clk_freq.scr, SSP_CR0_MASK_SCR, 8);
 	/* Loopback is available on all versions except PL023 */
-	if (!pl022->vendor->pl023)
-		SSP_WRITE_BITS(chip->cr1, chip_info->lbm, SSP_CR1_MASK_LBM, 0);
+	if (!pl022->vendor->pl023) {
+		if (spi->mode & SPI_LOOP)
+			tmp = LOOPBACK_ENABLED;
+		else
+			tmp = LOOPBACK_DISABLED;
+		SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_LBM, 0);
+	}
 	SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1);
 	SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2);
 	SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3);
@@ -1704,7 +2003,7 @@
 	spi_set_ctldata(spi, chip);
 	return status;
  err_config_params:
- err_first_setup:
+	spi_set_ctldata(spi, NULL);
 	kfree(chip);
 	return status;
 }
@@ -1766,12 +2065,21 @@
 	master->setup = pl022_setup;
 	master->transfer = pl022_transfer;
 
+	/*
+	 * Supports mode 0-3, loopback, and active low CS. Transfers are
+	 * always MS bit first on the original pl022.
+	 */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
+	if (pl022->vendor->extended_cr)
+		master->mode_bits |= SPI_LSB_FIRST;
+
 	dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num);
 
 	status = amba_request_regions(adev, NULL);
 	if (status)
 		goto err_no_ioregion;
 
+	pl022->phybase = adev->res.start;
 	pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res));
 	if (pl022->virtbase == NULL) {
 		status = -ENOMEM;
@@ -1798,6 +2106,14 @@
 		dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
 		goto err_no_irq;
 	}
+
+	/* Get DMA channels */
+	if (platform_info->enable_dma) {
+		status = pl022_dma_probe(pl022);
+		if (status != 0)
+			goto err_no_dma;
+	}
+
 	/* Initialize and start queue */
 	status = init_queue(pl022);
 	if (status != 0) {
@@ -1826,6 +2142,8 @@
  err_start_queue:
  err_init_queue:
 	destroy_queue(pl022);
+	pl022_dma_remove(pl022);
+ err_no_dma:
 	free_irq(adev->irq[0], pl022);
  err_no_irq:
 	clk_put(pl022->clk);
@@ -1856,6 +2174,7 @@
 		return status;
 	}
 	load_ssp_default_config(pl022);
+	pl022_dma_remove(pl022);
 	free_irq(adev->irq[0], pl022);
 	clk_disable(pl022->clk);
 	clk_put(pl022->clk);
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index c4e0442..154529a 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -654,6 +654,8 @@
 	struct spi_transfer	*xfer;
 	unsigned long		flags;
 	struct device		*controller = spi->master->dev.parent;
+	u8			bits;
+	struct atmel_spi_device	*asd;
 
 	as = spi_master_get_devdata(spi->master);
 
@@ -672,8 +674,18 @@
 			return -EINVAL;
 		}
 
+		if (xfer->bits_per_word) {
+			asd = spi->controller_state;
+			bits = (asd->csr >> 4) & 0xf;
+			if (bits != xfer->bits_per_word - 8) {
+				dev_dbg(&spi->dev, "you can't yet change "
+					 "bits_per_word in transfers\n");
+				return -ENOPROTOOPT;
+			}
+		}
+
 		/* FIXME implement these protocol options!! */
-		if (xfer->bits_per_word || xfer->speed_hz) {
+		if (xfer->speed_hz) {
 			dev_dbg(&spi->dev, "no protocol options yet\n");
 			return -ENOPROTOOPT;
 		}
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 5624785..9043931 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -131,6 +131,7 @@
 	.owner		= THIS_MODULE,
 	.open		= spi_show_regs_open,
 	.read		= spi_show_regs,
+	.llseek		= default_llseek,
 };
 
 static int mrst_spi_debugfs_init(struct dw_spi *dws)
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index b3a94ca..2a651e6 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -296,6 +296,19 @@
 	return 0;
 }
 
+static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(1000);
+	while (!(__raw_readl(reg) & bit)) {
+		if (time_after(jiffies, timeout))
+			return -1;
+		cpu_relax();
+	}
+	return 0;
+}
+
 static unsigned
 omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 {
@@ -309,11 +322,14 @@
 	u32			l;
 	u8			* rx;
 	const u8		* tx;
+	void __iomem		*chstat_reg;
 
 	mcspi = spi_master_get_devdata(spi->master);
 	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
 	l = mcspi_cached_chconf0(spi);
 
+	chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
+
 	count = xfer->len;
 	c = count;
 	word_len = cs->word_len;
@@ -382,6 +398,16 @@
 	if (tx != NULL) {
 		wait_for_completion(&mcspi_dma->dma_tx_completion);
 		dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
+
+		/* for TX_ONLY mode, be sure all words have shifted out */
+		if (rx == NULL) {
+			if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0)
+				dev_err(&spi->dev, "TXS timed out\n");
+			else if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_EOT) < 0)
+				dev_err(&spi->dev, "EOT timed out\n");
+		}
 	}
 
 	if (rx != NULL) {
@@ -435,19 +461,6 @@
 	return count;
 }
 
-static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
-{
-	unsigned long timeout;
-
-	timeout = jiffies + msecs_to_jiffies(1000);
-	while (!(__raw_readl(reg) & bit)) {
-		if (time_after(jiffies, timeout))
-			return -1;
-		cpu_relax();
-	}
-	return 0;
-}
-
 static unsigned
 omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 {
@@ -489,10 +502,8 @@
 					dev_err(&spi->dev, "TXS timed out\n");
 					goto out;
 				}
-#ifdef VERBOSE
-				dev_dbg(&spi->dev, "write-%d %02x\n",
+				dev_vdbg(&spi->dev, "write-%d %02x\n",
 						word_len, *tx);
-#endif
 				__raw_writel(*tx++, tx_reg);
 			}
 			if (rx != NULL) {
@@ -506,10 +517,8 @@
 				    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
 					omap2_mcspi_set_enable(spi, 0);
 					*rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-					dev_dbg(&spi->dev, "read-%d %02x\n",
+					dev_vdbg(&spi->dev, "read-%d %02x\n",
 						    word_len, *(rx - 1));
-#endif
 					if (mcspi_wait_for_reg_bit(chstat_reg,
 						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
 						dev_err(&spi->dev,
@@ -522,10 +531,8 @@
 				}
 
 				*rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-				dev_dbg(&spi->dev, "read-%d %02x\n",
+				dev_vdbg(&spi->dev, "read-%d %02x\n",
 						word_len, *(rx - 1));
-#endif
 			}
 		} while (c);
 	} else if (word_len <= 16) {
@@ -542,10 +549,8 @@
 					dev_err(&spi->dev, "TXS timed out\n");
 					goto out;
 				}
-#ifdef VERBOSE
-				dev_dbg(&spi->dev, "write-%d %04x\n",
+				dev_vdbg(&spi->dev, "write-%d %04x\n",
 						word_len, *tx);
-#endif
 				__raw_writel(*tx++, tx_reg);
 			}
 			if (rx != NULL) {
@@ -559,10 +564,8 @@
 				    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
 					omap2_mcspi_set_enable(spi, 0);
 					*rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-					dev_dbg(&spi->dev, "read-%d %04x\n",
+					dev_vdbg(&spi->dev, "read-%d %04x\n",
 						    word_len, *(rx - 1));
-#endif
 					if (mcspi_wait_for_reg_bit(chstat_reg,
 						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
 						dev_err(&spi->dev,
@@ -575,10 +578,8 @@
 				}
 
 				*rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-				dev_dbg(&spi->dev, "read-%d %04x\n",
+				dev_vdbg(&spi->dev, "read-%d %04x\n",
 						word_len, *(rx - 1));
-#endif
 			}
 		} while (c);
 	} else if (word_len <= 32) {
@@ -595,10 +596,8 @@
 					dev_err(&spi->dev, "TXS timed out\n");
 					goto out;
 				}
-#ifdef VERBOSE
-				dev_dbg(&spi->dev, "write-%d %08x\n",
+				dev_vdbg(&spi->dev, "write-%d %08x\n",
 						word_len, *tx);
-#endif
 				__raw_writel(*tx++, tx_reg);
 			}
 			if (rx != NULL) {
@@ -612,10 +611,8 @@
 				    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
 					omap2_mcspi_set_enable(spi, 0);
 					*rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-					dev_dbg(&spi->dev, "read-%d %08x\n",
+					dev_vdbg(&spi->dev, "read-%d %08x\n",
 						    word_len, *(rx - 1));
-#endif
 					if (mcspi_wait_for_reg_bit(chstat_reg,
 						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
 						dev_err(&spi->dev,
@@ -628,10 +625,8 @@
 				}
 
 				*rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-				dev_dbg(&spi->dev, "read-%d %08x\n",
+				dev_vdbg(&spi->dev, "read-%d %08x\n",
 						word_len, *(rx - 1));
-#endif
 			}
 		} while (c);
 	}
@@ -644,6 +639,12 @@
 		} else if (mcspi_wait_for_reg_bit(chstat_reg,
 				OMAP2_MCSPI_CHSTAT_EOT) < 0)
 			dev_err(&spi->dev, "EOT timed out\n");
+
+		/* disable chan to purge rx datas received in TX_ONLY transfer,
+		 * otherwise these rx datas will affect the direct following
+		 * RX_ONLY transfer.
+		 */
+		omap2_mcspi_set_enable(spi, 0);
 	}
 out:
 	omap2_mcspi_set_enable(spi, 1);
diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c
index 3aea50d..0b677dc 100644
--- a/drivers/spi/orion_spi.c
+++ b/drivers/spi/orion_spi.c
@@ -404,7 +404,7 @@
 			goto msg_rejected;
 		}
 
-		if ((t != NULL) && t->bits_per_word)
+		if (t->bits_per_word)
 			bits_per_word = t->bits_per_word;
 
 		if ((bits_per_word != 8) && (bits_per_word != 16)) {
@@ -415,7 +415,7 @@
 			goto msg_rejected;
 		}
 		/*make sure buffer length is even when working in 16 bit mode*/
-		if ((t != NULL) && (t->bits_per_word == 16) && (t->len & 1)) {
+		if ((t->bits_per_word == 16) && (t->len & 1)) {
 			dev_err(&spi->dev,
 				"message rejected : "
 				"odd data length (%d) while in 16 bit mode\n",
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 0bcf4c1..b5a78a1 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/cache.h>
 #include <linux/mutex.h>
+#include <linux/of_device.h>
 #include <linux/slab.h>
 #include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
@@ -86,6 +87,10 @@
 	const struct spi_device	*spi = to_spi_device(dev);
 	const struct spi_driver	*sdrv = to_spi_driver(drv);
 
+	/* Attempt an OF style match */
+	if (of_driver_match_device(dev, drv))
+		return 1;
+
 	if (sdrv->id_table)
 		return !!spi_match_id(sdrv->id_table, spi);
 
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 10a6dc3..ab483a0 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -1,7 +1,7 @@
 /*
  * Blackfin On-Chip SPI Driver
  *
- * Copyright 2004-2007 Analog Devices Inc.
+ * Copyright 2004-2010 Analog Devices Inc.
  *
  * Enter bugs at http://blackfin.uclinux.org/
  *
@@ -41,13 +41,16 @@
 #define RUNNING_STATE	((void *)1)
 #define DONE_STATE	((void *)2)
 #define ERROR_STATE	((void *)-1)
-#define QUEUE_RUNNING	0
-#define QUEUE_STOPPED	1
 
-/* Value to send if no TX value is supplied */
-#define SPI_IDLE_TXVAL 0x0000
+struct bfin_spi_master_data;
 
-struct driver_data {
+struct bfin_spi_transfer_ops {
+	void (*write) (struct bfin_spi_master_data *);
+	void (*read) (struct bfin_spi_master_data *);
+	void (*duplex) (struct bfin_spi_master_data *);
+};
+
+struct bfin_spi_master_data {
 	/* Driver model hookup */
 	struct platform_device *pdev;
 
@@ -69,7 +72,7 @@
 	spinlock_t lock;
 	struct list_head queue;
 	int busy;
-	int run;
+	bool running;
 
 	/* Message Transfer pump */
 	struct tasklet_struct pump_transfers;
@@ -77,7 +80,7 @@
 	/* Current message transfer state info */
 	struct spi_message *cur_msg;
 	struct spi_transfer *cur_transfer;
-	struct chip_data *cur_chip;
+	struct bfin_spi_slave_data *cur_chip;
 	size_t len_in_bytes;
 	size_t len;
 	void *tx;
@@ -92,38 +95,37 @@
 	dma_addr_t rx_dma;
 	dma_addr_t tx_dma;
 
+	int irq_requested;
+	int spi_irq;
+
 	size_t rx_map_len;
 	size_t tx_map_len;
 	u8 n_bytes;
+	u16 ctrl_reg;
+	u16 flag_reg;
+
 	int cs_change;
-	void (*write) (struct driver_data *);
-	void (*read) (struct driver_data *);
-	void (*duplex) (struct driver_data *);
+	const struct bfin_spi_transfer_ops *ops;
 };
 
-struct chip_data {
+struct bfin_spi_slave_data {
 	u16 ctl_reg;
 	u16 baud;
 	u16 flag;
 
 	u8 chip_select_num;
-	u8 n_bytes;
-	u8 width;		/* 0 or 1 */
 	u8 enable_dma;
-	u8 bits_per_word;	/* 8 or 16 */
-	u8 cs_change_per_word;
 	u16 cs_chg_udelay;	/* Some devices require > 255usec delay */
 	u32 cs_gpio;
 	u16 idle_tx_val;
-	void (*write) (struct driver_data *);
-	void (*read) (struct driver_data *);
-	void (*duplex) (struct driver_data *);
+	u8 pio_interrupt;	/* use spi data irq */
+	const struct bfin_spi_transfer_ops *ops;
 };
 
 #define DEFINE_SPI_REG(reg, off) \
-static inline u16 read_##reg(struct driver_data *drv_data) \
+static inline u16 read_##reg(struct bfin_spi_master_data *drv_data) \
 	{ return bfin_read16(drv_data->regs_base + off); } \
-static inline void write_##reg(struct driver_data *drv_data, u16 v) \
+static inline void write_##reg(struct bfin_spi_master_data *drv_data, u16 v) \
 	{ bfin_write16(drv_data->regs_base + off, v); }
 
 DEFINE_SPI_REG(CTRL, 0x00)
@@ -134,7 +136,7 @@
 DEFINE_SPI_REG(BAUD, 0x14)
 DEFINE_SPI_REG(SHAW, 0x18)
 
-static void bfin_spi_enable(struct driver_data *drv_data)
+static void bfin_spi_enable(struct bfin_spi_master_data *drv_data)
 {
 	u16 cr;
 
@@ -142,7 +144,7 @@
 	write_CTRL(drv_data, (cr | BIT_CTL_ENABLE));
 }
 
-static void bfin_spi_disable(struct driver_data *drv_data)
+static void bfin_spi_disable(struct bfin_spi_master_data *drv_data)
 {
 	u16 cr;
 
@@ -165,7 +167,7 @@
 	return spi_baud;
 }
 
-static int bfin_spi_flush(struct driver_data *drv_data)
+static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)
 {
 	unsigned long limit = loops_per_jiffy << 1;
 
@@ -179,13 +181,12 @@
 }
 
 /* Chip select operation functions for cs_change flag */
-static void bfin_spi_cs_active(struct driver_data *drv_data, struct chip_data *chip)
+static void bfin_spi_cs_active(struct bfin_spi_master_data *drv_data, struct bfin_spi_slave_data *chip)
 {
-	if (likely(chip->chip_select_num)) {
+	if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
 		u16 flag = read_FLAG(drv_data);
 
-		flag |= chip->flag;
-		flag &= ~(chip->flag << 8);
+		flag &= ~chip->flag;
 
 		write_FLAG(drv_data, flag);
 	} else {
@@ -193,13 +194,13 @@
 	}
 }
 
-static void bfin_spi_cs_deactive(struct driver_data *drv_data, struct chip_data *chip)
+static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,
+                                 struct bfin_spi_slave_data *chip)
 {
-	if (likely(chip->chip_select_num)) {
+	if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
 		u16 flag = read_FLAG(drv_data);
 
-		flag &= ~chip->flag;
-		flag |= (chip->flag << 8);
+		flag |= chip->flag;
 
 		write_FLAG(drv_data, flag);
 	} else {
@@ -211,16 +212,43 @@
 		udelay(chip->cs_chg_udelay);
 }
 
-/* stop controller and re-config current chip*/
-static void bfin_spi_restore_state(struct driver_data *drv_data)
+/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
+static inline void bfin_spi_cs_enable(struct bfin_spi_master_data *drv_data,
+                                      struct bfin_spi_slave_data *chip)
 {
-	struct chip_data *chip = drv_data->cur_chip;
+	if (chip->chip_select_num < MAX_CTRL_CS) {
+		u16 flag = read_FLAG(drv_data);
+
+		flag |= (chip->flag >> 8);
+
+		write_FLAG(drv_data, flag);
+	}
+}
+
+static inline void bfin_spi_cs_disable(struct bfin_spi_master_data *drv_data,
+                                       struct bfin_spi_slave_data *chip)
+{
+	if (chip->chip_select_num < MAX_CTRL_CS) {
+		u16 flag = read_FLAG(drv_data);
+
+		flag &= ~(chip->flag >> 8);
+
+		write_FLAG(drv_data, flag);
+	}
+}
+
+/* stop controller and re-config current chip*/
+static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)
+{
+	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
 
 	/* Clear status and disable clock */
 	write_STAT(drv_data, BIT_STAT_CLR);
 	bfin_spi_disable(drv_data);
 	dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
 
+	SSYNC();
+
 	/* Load the registers */
 	write_CTRL(drv_data, chip->ctl_reg);
 	write_BAUD(drv_data, chip->baud);
@@ -230,49 +258,12 @@
 }
 
 /* used to kick off transfer in rx mode and read unwanted RX data */
-static inline void bfin_spi_dummy_read(struct driver_data *drv_data)
+static inline void bfin_spi_dummy_read(struct bfin_spi_master_data *drv_data)
 {
 	(void) read_RDBR(drv_data);
 }
 
-static void bfin_spi_null_writer(struct driver_data *drv_data)
-{
-	u8 n_bytes = drv_data->n_bytes;
-	u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
-	/* clear RXS (we check for RXS inside the loop) */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->tx < drv_data->tx_end) {
-		write_TDBR(drv_data, tx_val);
-		drv_data->tx += n_bytes;
-		/* wait until transfer finished.
-		   checking SPIF or TXS may not guarantee transfer completion */
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		/* discard RX data and clear RXS */
-		bfin_spi_dummy_read(drv_data);
-	}
-}
-
-static void bfin_spi_null_reader(struct driver_data *drv_data)
-{
-	u8 n_bytes = drv_data->n_bytes;
-	u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
-	/* discard old RX data and clear RXS */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->rx < drv_data->rx_end) {
-		write_TDBR(drv_data, tx_val);
-		drv_data->rx += n_bytes;
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		bfin_spi_dummy_read(drv_data);
-	}
-}
-
-static void bfin_spi_u8_writer(struct driver_data *drv_data)
+static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)
 {
 	/* clear RXS (we check for RXS inside the loop) */
 	bfin_spi_dummy_read(drv_data);
@@ -288,25 +279,7 @@
 	}
 }
 
-static void bfin_spi_u8_cs_chg_writer(struct driver_data *drv_data)
-{
-	struct chip_data *chip = drv_data->cur_chip;
-
-	/* clear RXS (we check for RXS inside the loop) */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->tx < drv_data->tx_end) {
-		bfin_spi_cs_active(drv_data, chip);
-		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
-		/* make sure transfer finished before deactiving CS */
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		bfin_spi_dummy_read(drv_data);
-		bfin_spi_cs_deactive(drv_data, chip);
-	}
-}
-
-static void bfin_spi_u8_reader(struct driver_data *drv_data)
+static void bfin_spi_u8_reader(struct bfin_spi_master_data *drv_data)
 {
 	u16 tx_val = drv_data->cur_chip->idle_tx_val;
 
@@ -321,25 +294,7 @@
 	}
 }
 
-static void bfin_spi_u8_cs_chg_reader(struct driver_data *drv_data)
-{
-	struct chip_data *chip = drv_data->cur_chip;
-	u16 tx_val = chip->idle_tx_val;
-
-	/* discard old RX data and clear RXS */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_spi_cs_active(drv_data, chip);
-		write_TDBR(drv_data, tx_val);
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
-		bfin_spi_cs_deactive(drv_data, chip);
-	}
-}
-
-static void bfin_spi_u8_duplex(struct driver_data *drv_data)
+static void bfin_spi_u8_duplex(struct bfin_spi_master_data *drv_data)
 {
 	/* discard old RX data and clear RXS */
 	bfin_spi_dummy_read(drv_data);
@@ -352,24 +307,13 @@
 	}
 }
 
-static void bfin_spi_u8_cs_chg_duplex(struct driver_data *drv_data)
-{
-	struct chip_data *chip = drv_data->cur_chip;
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = {
+	.write  = bfin_spi_u8_writer,
+	.read   = bfin_spi_u8_reader,
+	.duplex = bfin_spi_u8_duplex,
+};
 
-	/* discard old RX data and clear RXS */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_spi_cs_active(drv_data, chip);
-		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
-		bfin_spi_cs_deactive(drv_data, chip);
-	}
-}
-
-static void bfin_spi_u16_writer(struct driver_data *drv_data)
+static void bfin_spi_u16_writer(struct bfin_spi_master_data *drv_data)
 {
 	/* clear RXS (we check for RXS inside the loop) */
 	bfin_spi_dummy_read(drv_data);
@@ -386,26 +330,7 @@
 	}
 }
 
-static void bfin_spi_u16_cs_chg_writer(struct driver_data *drv_data)
-{
-	struct chip_data *chip = drv_data->cur_chip;
-
-	/* clear RXS (we check for RXS inside the loop) */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->tx < drv_data->tx_end) {
-		bfin_spi_cs_active(drv_data, chip);
-		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		drv_data->tx += 2;
-		/* make sure transfer finished before deactiving CS */
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		bfin_spi_dummy_read(drv_data);
-		bfin_spi_cs_deactive(drv_data, chip);
-	}
-}
-
-static void bfin_spi_u16_reader(struct driver_data *drv_data)
+static void bfin_spi_u16_reader(struct bfin_spi_master_data *drv_data)
 {
 	u16 tx_val = drv_data->cur_chip->idle_tx_val;
 
@@ -421,26 +346,7 @@
 	}
 }
 
-static void bfin_spi_u16_cs_chg_reader(struct driver_data *drv_data)
-{
-	struct chip_data *chip = drv_data->cur_chip;
-	u16 tx_val = chip->idle_tx_val;
-
-	/* discard old RX data and clear RXS */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_spi_cs_active(drv_data, chip);
-		write_TDBR(drv_data, tx_val);
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-		drv_data->rx += 2;
-		bfin_spi_cs_deactive(drv_data, chip);
-	}
-}
-
-static void bfin_spi_u16_duplex(struct driver_data *drv_data)
+static void bfin_spi_u16_duplex(struct bfin_spi_master_data *drv_data)
 {
 	/* discard old RX data and clear RXS */
 	bfin_spi_dummy_read(drv_data);
@@ -455,27 +361,14 @@
 	}
 }
 
-static void bfin_spi_u16_cs_chg_duplex(struct driver_data *drv_data)
-{
-	struct chip_data *chip = drv_data->cur_chip;
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = {
+	.write  = bfin_spi_u16_writer,
+	.read   = bfin_spi_u16_reader,
+	.duplex = bfin_spi_u16_duplex,
+};
 
-	/* discard old RX data and clear RXS */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_spi_cs_active(drv_data, chip);
-		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		drv_data->tx += 2;
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-		drv_data->rx += 2;
-		bfin_spi_cs_deactive(drv_data, chip);
-	}
-}
-
-/* test if ther is more transfer to be done */
-static void *bfin_spi_next_transfer(struct driver_data *drv_data)
+/* test if there is more transfer to be done */
+static void *bfin_spi_next_transfer(struct bfin_spi_master_data *drv_data)
 {
 	struct spi_message *msg = drv_data->cur_msg;
 	struct spi_transfer *trans = drv_data->cur_transfer;
@@ -494,9 +387,9 @@
  * caller already set message->status;
  * dma and pio irqs are blocked give finished message back
  */
-static void bfin_spi_giveback(struct driver_data *drv_data)
+static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data)
 {
-	struct chip_data *chip = drv_data->cur_chip;
+	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
 	struct spi_transfer *last_transfer;
 	unsigned long flags;
 	struct spi_message *msg;
@@ -525,10 +418,83 @@
 		msg->complete(msg->context);
 }
 
+/* spi data irq handler */
+static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
+{
+	struct bfin_spi_master_data *drv_data = dev_id;
+	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
+	struct spi_message *msg = drv_data->cur_msg;
+	int n_bytes = drv_data->n_bytes;
+
+	/* wait until transfer finished. */
+	while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+		cpu_relax();
+
+	if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) ||
+		(drv_data->rx && drv_data->rx >= (drv_data->rx_end - n_bytes))) {
+		/* last read */
+		if (drv_data->rx) {
+			dev_dbg(&drv_data->pdev->dev, "last read\n");
+			if (n_bytes == 2)
+				*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
+			else if (n_bytes == 1)
+				*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
+			drv_data->rx += n_bytes;
+		}
+
+		msg->actual_length += drv_data->len_in_bytes;
+		if (drv_data->cs_change)
+			bfin_spi_cs_deactive(drv_data, chip);
+		/* Move to next transfer */
+		msg->state = bfin_spi_next_transfer(drv_data);
+
+		disable_irq_nosync(drv_data->spi_irq);
+
+		/* Schedule transfer tasklet */
+		tasklet_schedule(&drv_data->pump_transfers);
+		return IRQ_HANDLED;
+	}
+
+	if (drv_data->rx && drv_data->tx) {
+		/* duplex */
+		dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
+		if (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)));
+		}
+	} 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);
+	} 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 (drv_data->tx)
+		drv_data->tx += n_bytes;
+	if (drv_data->rx)
+		drv_data->rx += n_bytes;
+
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
 {
-	struct driver_data *drv_data = dev_id;
-	struct chip_data *chip = drv_data->cur_chip;
+	struct bfin_spi_master_data *drv_data = dev_id;
+	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
 	struct spi_message *msg = drv_data->cur_msg;
 	unsigned long timeout;
 	unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel);
@@ -540,10 +506,6 @@
 
 	clear_dma_irqstat(drv_data->dma_channel);
 
-	/* Wait for DMA to complete */
-	while (get_dma_curr_irqstat(drv_data->dma_channel) & DMA_RUN)
-		cpu_relax();
-
 	/*
 	 * wait for the last transaction shifted out.  HRM states:
 	 * at this point there may still be data in the SPI DMA FIFO waiting
@@ -551,8 +513,8 @@
 	 * register until it goes low for 2 successive reads
 	 */
 	if (drv_data->tx != NULL) {
-		while ((read_STAT(drv_data) & TXS) ||
-		       (read_STAT(drv_data) & TXS))
+		while ((read_STAT(drv_data) & BIT_STAT_TXS) ||
+		       (read_STAT(drv_data) & BIT_STAT_TXS))
 			cpu_relax();
 	}
 
@@ -561,14 +523,14 @@
 		dmastat, read_STAT(drv_data));
 
 	timeout = jiffies + HZ;
-	while (!(read_STAT(drv_data) & SPIF))
+	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
 		if (!time_before(jiffies, timeout)) {
 			dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF");
 			break;
 		} else
 			cpu_relax();
 
-	if ((dmastat & DMA_ERR) && (spistat & RBSY)) {
+	if ((dmastat & DMA_ERR) && (spistat & BIT_STAT_RBSY)) {
 		msg->state = ERROR_STATE;
 		dev_err(&drv_data->pdev->dev, "dma receive: fifo/buffer overflow\n");
 	} else {
@@ -588,20 +550,20 @@
 	dev_dbg(&drv_data->pdev->dev,
 		"disable dma channel irq%d\n",
 		drv_data->dma_channel);
-	dma_disable_irq(drv_data->dma_channel);
+	dma_disable_irq_nosync(drv_data->dma_channel);
 
 	return IRQ_HANDLED;
 }
 
 static void bfin_spi_pump_transfers(unsigned long data)
 {
-	struct driver_data *drv_data = (struct driver_data *)data;
+	struct bfin_spi_master_data *drv_data = (struct bfin_spi_master_data *)data;
 	struct spi_message *message = NULL;
 	struct spi_transfer *transfer = NULL;
 	struct spi_transfer *previous = NULL;
-	struct chip_data *chip = NULL;
-	u8 width;
-	u16 cr, dma_width, dma_config;
+	struct bfin_spi_slave_data *chip = NULL;
+	unsigned int bits_per_word;
+	u16 cr, cr_width, dma_width, dma_config;
 	u32 tranf_success = 1;
 	u8 full_duplex = 0;
 
@@ -639,7 +601,7 @@
 			udelay(previous->delay_usecs);
 	}
 
-	/* Setup the transfer state based on the type of transfer */
+	/* Flush any existing transfers that may be sitting in the hardware */
 	if (bfin_spi_flush(drv_data) == 0) {
 		dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
 		message->status = -EIO;
@@ -679,52 +641,31 @@
 	drv_data->cs_change = transfer->cs_change;
 
 	/* Bits per word setup */
-	switch (transfer->bits_per_word) {
-	case 8:
+	bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word;
+	if (bits_per_word == 8) {
 		drv_data->n_bytes = 1;
-		width = CFG_SPI_WORDSIZE8;
-		drv_data->read = chip->cs_change_per_word ?
-			bfin_spi_u8_cs_chg_reader : bfin_spi_u8_reader;
-		drv_data->write = chip->cs_change_per_word ?
-			bfin_spi_u8_cs_chg_writer : bfin_spi_u8_writer;
-		drv_data->duplex = chip->cs_change_per_word ?
-			bfin_spi_u8_cs_chg_duplex : bfin_spi_u8_duplex;
-		break;
-
-	case 16:
+		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;
-		width = CFG_SPI_WORDSIZE16;
-		drv_data->read = chip->cs_change_per_word ?
-			bfin_spi_u16_cs_chg_reader : bfin_spi_u16_reader;
-		drv_data->write = chip->cs_change_per_word ?
-			bfin_spi_u16_cs_chg_writer : bfin_spi_u16_writer;
-		drv_data->duplex = chip->cs_change_per_word ?
-			bfin_spi_u16_cs_chg_duplex : bfin_spi_u16_duplex;
-		break;
-
-	default:
-		/* No change, the same as default setting */
-		drv_data->n_bytes = chip->n_bytes;
-		width = chip->width;
-		drv_data->write = drv_data->tx ? chip->write : bfin_spi_null_writer;
-		drv_data->read = drv_data->rx ? chip->read : bfin_spi_null_reader;
-		drv_data->duplex = chip->duplex ? chip->duplex : bfin_spi_null_writer;
-		break;
+		drv_data->len = (transfer->len) >> 1;
+		cr_width = BIT_CTL_WORDSIZE;
+		drv_data->ops = &bfin_bfin_spi_transfer_ops_u16;
+	} else {
+		dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n");
+		message->status = -EINVAL;
+		bfin_spi_giveback(drv_data);
+		return;
 	}
-	cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD));
-	cr |= (width << 8);
+	cr = read_CTRL(drv_data) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
+	cr |= cr_width;
 	write_CTRL(drv_data, cr);
 
-	if (width == CFG_SPI_WORDSIZE16) {
-		drv_data->len = (transfer->len) >> 1;
-	} else {
-		drv_data->len = transfer->len;
-	}
 	dev_dbg(&drv_data->pdev->dev,
-		"transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n",
-		drv_data->write, chip->write, bfin_spi_null_writer);
+		"transfer: drv_data->ops is %p, chip->ops is %p, u8_ops is %p\n",
+		drv_data->ops, chip->ops, &bfin_bfin_spi_transfer_ops_u8);
 
-	/* speed and width has been set on per message */
 	message->state = RUNNING_STATE;
 	dma_config = 0;
 
@@ -735,13 +676,11 @@
 		write_BAUD(drv_data, chip->baud);
 
 	write_STAT(drv_data, BIT_STAT_CLR);
-	cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD));
-	if (drv_data->cs_change)
-		bfin_spi_cs_active(drv_data, chip);
+	bfin_spi_cs_active(drv_data, chip);
 
 	dev_dbg(&drv_data->pdev->dev,
 		"now pumping a transfer: width is %d, len is %d\n",
-		width, transfer->len);
+		cr_width, transfer->len);
 
 	/*
 	 * Try to map dma buffer and do a dma transfer.  If successful use,
@@ -760,7 +699,7 @@
 		/* config dma channel */
 		dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
 		set_dma_x_count(drv_data->dma_channel, drv_data->len);
-		if (width == CFG_SPI_WORDSIZE16) {
+		if (cr_width == BIT_CTL_WORDSIZE) {
 			set_dma_x_modify(drv_data->dma_channel, 2);
 			dma_width = WDSIZE_16;
 		} else {
@@ -846,73 +785,100 @@
 		dma_enable_irq(drv_data->dma_channel);
 		local_irq_restore(flags);
 
-	} else {
-		/* IO mode write then read */
-		dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
-
-		/* we always use SPI_WRITE mode. SPI_READ mode
-		   seems to have problems with setting up the
-		   output value in TDBR prior to the transfer. */
-		write_CTRL(drv_data, (cr | CFG_SPI_WRITE));
-
-		if (full_duplex) {
-			/* full duplex mode */
-			BUG_ON((drv_data->tx_end - drv_data->tx) !=
-			       (drv_data->rx_end - drv_data->rx));
-			dev_dbg(&drv_data->pdev->dev,
-				"IO duplex: cr is 0x%x\n", cr);
-
-			drv_data->duplex(drv_data);
-
-			if (drv_data->tx != drv_data->tx_end)
-				tranf_success = 0;
-		} else if (drv_data->tx != NULL) {
-			/* write only half duplex */
-			dev_dbg(&drv_data->pdev->dev,
-				"IO write: cr is 0x%x\n", cr);
-
-			drv_data->write(drv_data);
-
-			if (drv_data->tx != drv_data->tx_end)
-				tranf_success = 0;
-		} else if (drv_data->rx != NULL) {
-			/* read only half duplex */
-			dev_dbg(&drv_data->pdev->dev,
-				"IO read: cr is 0x%x\n", cr);
-
-			drv_data->read(drv_data);
-			if (drv_data->rx != drv_data->rx_end)
-				tranf_success = 0;
-		}
-
-		if (!tranf_success) {
-			dev_dbg(&drv_data->pdev->dev,
-				"IO write error!\n");
-			message->state = ERROR_STATE;
-		} else {
-			/* Update total byte transfered */
-			message->actual_length += drv_data->len_in_bytes;
-			/* Move to next transfer of this msg */
-			message->state = bfin_spi_next_transfer(drv_data);
-			if (drv_data->cs_change)
-				bfin_spi_cs_deactive(drv_data, chip);
-		}
-		/* Schedule next transfer tasklet */
-		tasklet_schedule(&drv_data->pump_transfers);
+		return;
 	}
+
+	/*
+	 * We always use SPI_WRITE mode (transfer starts with TDBR write).
+	 * SPI_READ mode (transfer starts with RDBR read) seems to have
+	 * problems with setting up the output value in TDBR prior to the
+	 * start of the transfer.
+	 */
+	write_CTRL(drv_data, cr | BIT_CTL_TXMOD);
+
+	if (chip->pio_interrupt) {
+		/* SPI irq should have been disabled by now */
+
+		/* discard old RX data and clear RXS */
+		bfin_spi_dummy_read(drv_data);
+
+		/* start transfer */
+		if (drv_data->tx == NULL)
+			write_TDBR(drv_data, chip->idle_tx_val);
+		else {
+			if (bits_per_word == 8)
+				write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+			else
+				write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+			drv_data->tx += drv_data->n_bytes;
+		}
+
+		/* once TDBR is empty, interrupt is triggered */
+		enable_irq(drv_data->spi_irq);
+		return;
+	}
+
+	/* IO mode */
+	dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
+
+	if (full_duplex) {
+		/* full duplex mode */
+		BUG_ON((drv_data->tx_end - drv_data->tx) !=
+		       (drv_data->rx_end - drv_data->rx));
+		dev_dbg(&drv_data->pdev->dev,
+			"IO duplex: cr is 0x%x\n", cr);
+
+		drv_data->ops->duplex(drv_data);
+
+		if (drv_data->tx != drv_data->tx_end)
+			tranf_success = 0;
+	} else if (drv_data->tx != NULL) {
+		/* write only half duplex */
+		dev_dbg(&drv_data->pdev->dev,
+			"IO write: cr is 0x%x\n", cr);
+
+		drv_data->ops->write(drv_data);
+
+		if (drv_data->tx != drv_data->tx_end)
+			tranf_success = 0;
+	} else if (drv_data->rx != NULL) {
+		/* read only half duplex */
+		dev_dbg(&drv_data->pdev->dev,
+			"IO read: cr is 0x%x\n", cr);
+
+		drv_data->ops->read(drv_data);
+		if (drv_data->rx != drv_data->rx_end)
+			tranf_success = 0;
+	}
+
+	if (!tranf_success) {
+		dev_dbg(&drv_data->pdev->dev,
+			"IO write error!\n");
+		message->state = ERROR_STATE;
+	} else {
+		/* Update total byte transfered */
+		message->actual_length += drv_data->len_in_bytes;
+		/* Move to next transfer of this msg */
+		message->state = bfin_spi_next_transfer(drv_data);
+		if (drv_data->cs_change)
+			bfin_spi_cs_deactive(drv_data, chip);
+	}
+
+	/* Schedule next transfer tasklet */
+	tasklet_schedule(&drv_data->pump_transfers);
 }
 
 /* pop a msg from queue and kick off real transfer */
 static void bfin_spi_pump_messages(struct work_struct *work)
 {
-	struct driver_data *drv_data;
+	struct bfin_spi_master_data *drv_data;
 	unsigned long flags;
 
-	drv_data = container_of(work, struct driver_data, pump_messages);
+	drv_data = container_of(work, struct bfin_spi_master_data, pump_messages);
 
 	/* Lock queue and check for queue work */
 	spin_lock_irqsave(&drv_data->lock, flags);
-	if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
+	if (list_empty(&drv_data->queue) || !drv_data->running) {
 		/* pumper kicked off but no work to do */
 		drv_data->busy = 0;
 		spin_unlock_irqrestore(&drv_data->lock, flags);
@@ -962,12 +928,12 @@
  */
 static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
 {
-	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
 	unsigned long flags;
 
 	spin_lock_irqsave(&drv_data->lock, flags);
 
-	if (drv_data->run == QUEUE_STOPPED) {
+	if (!drv_data->running) {
 		spin_unlock_irqrestore(&drv_data->lock, flags);
 		return -ESHUTDOWN;
 	}
@@ -979,7 +945,7 @@
 	dev_dbg(&spi->dev, "adding an msg in transfer() \n");
 	list_add_tail(&msg->queue, &drv_data->queue);
 
-	if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
+	if (drv_data->running && !drv_data->busy)
 		queue_work(drv_data->workqueue, &drv_data->pump_messages);
 
 	spin_unlock_irqrestore(&drv_data->lock, flags);
@@ -1003,147 +969,184 @@
 	P_SPI2_SSEL6, P_SPI2_SSEL7},
 };
 
-/* first setup for new devices */
+/* setup for devices (may be called multiple times -- not just first setup) */
 static int bfin_spi_setup(struct spi_device *spi)
 {
-	struct bfin5xx_spi_chip *chip_info = NULL;
-	struct chip_data *chip;
-	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
-	int ret;
-
-	if (spi->bits_per_word != 8 && spi->bits_per_word != 16)
-		return -EINVAL;
+	struct bfin5xx_spi_chip *chip_info;
+	struct bfin_spi_slave_data *chip = NULL;
+	struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
+	u16 bfin_ctl_reg;
+	int ret = -EINVAL;
 
 	/* Only alloc (or use chip_info) on first setup */
+	chip_info = NULL;
 	chip = spi_get_ctldata(spi);
 	if (chip == NULL) {
-		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
-		if (!chip)
-			return -ENOMEM;
+		chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+		if (!chip) {
+			dev_err(&spi->dev, "cannot allocate chip data\n");
+			ret = -ENOMEM;
+			goto error;
+		}
 
 		chip->enable_dma = 0;
 		chip_info = spi->controller_data;
 	}
 
+	/* Let people set non-standard bits directly */
+	bfin_ctl_reg = BIT_CTL_OPENDRAIN | BIT_CTL_EMISO |
+		BIT_CTL_PSSE | BIT_CTL_GM | BIT_CTL_SZ;
+
 	/* chip_info isn't always needed */
 	if (chip_info) {
 		/* Make sure people stop trying to set fields via ctl_reg
 		 * when they should actually be using common SPI framework.
-		 * Currently we let through: WOM EMISO PSSE GM SZ TIMOD.
+		 * Currently we let through: WOM EMISO PSSE GM SZ.
 		 * Not sure if a user actually needs/uses any of these,
 		 * but let's assume (for now) they do.
 		 */
-		if (chip_info->ctl_reg & (SPE|MSTR|CPOL|CPHA|LSBF|SIZE)) {
+		if (chip_info->ctl_reg & ~bfin_ctl_reg) {
 			dev_err(&spi->dev, "do not set bits in ctl_reg "
 				"that the SPI framework manages\n");
-			return -EINVAL;
+			goto error;
 		}
-
 		chip->enable_dma = chip_info->enable_dma != 0
 		    && drv_data->master_info->enable_dma;
 		chip->ctl_reg = chip_info->ctl_reg;
-		chip->bits_per_word = chip_info->bits_per_word;
-		chip->cs_change_per_word = chip_info->cs_change_per_word;
 		chip->cs_chg_udelay = chip_info->cs_chg_udelay;
-		chip->cs_gpio = chip_info->cs_gpio;
 		chip->idle_tx_val = chip_info->idle_tx_val;
+		chip->pio_interrupt = chip_info->pio_interrupt;
+		spi->bits_per_word = chip_info->bits_per_word;
+	} else {
+		/* force a default base state */
+		chip->ctl_reg &= bfin_ctl_reg;
+	}
+
+	if (spi->bits_per_word != 8 && spi->bits_per_word != 16) {
+		dev_err(&spi->dev, "%d bits_per_word is not supported\n",
+				spi->bits_per_word);
+		goto error;
 	}
 
 	/* translate common spi framework into our register */
-	if (spi->mode & SPI_CPOL)
-		chip->ctl_reg |= CPOL;
-	if (spi->mode & SPI_CPHA)
-		chip->ctl_reg |= CPHA;
-	if (spi->mode & SPI_LSB_FIRST)
-		chip->ctl_reg |= LSBF;
-	/* we dont support running in slave mode (yet?) */
-	chip->ctl_reg |= MSTR;
-
-	/*
-	 * if any one SPI chip is registered and wants DMA, request the
-	 * DMA channel for it
-	 */
-	if (chip->enable_dma && !drv_data->dma_requested) {
-		/* register dma irq handler */
-		if (request_dma(drv_data->dma_channel, "BFIN_SPI_DMA") < 0) {
-			dev_dbg(&spi->dev,
-				"Unable to request BlackFin SPI DMA channel\n");
-			return -ENODEV;
-		}
-		if (set_dma_callback(drv_data->dma_channel,
-		    bfin_spi_dma_irq_handler, drv_data) < 0) {
-			dev_dbg(&spi->dev, "Unable to set dma callback\n");
-			return -EPERM;
-		}
-		dma_disable_irq(drv_data->dma_channel);
-		drv_data->dma_requested = 1;
+	if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) {
+		dev_err(&spi->dev, "unsupported spi modes detected\n");
+		goto error;
 	}
+	if (spi->mode & SPI_CPOL)
+		chip->ctl_reg |= BIT_CTL_CPOL;
+	if (spi->mode & SPI_CPHA)
+		chip->ctl_reg |= BIT_CTL_CPHA;
+	if (spi->mode & SPI_LSB_FIRST)
+		chip->ctl_reg |= BIT_CTL_LSBF;
+	/* we dont support running in slave mode (yet?) */
+	chip->ctl_reg |= BIT_CTL_MASTER;
 
 	/*
 	 * Notice: for blackfin, the speed_hz is the value of register
 	 * SPI_BAUD, not the real baudrate
 	 */
 	chip->baud = hz_to_spi_baud(spi->max_speed_hz);
-	chip->flag = 1 << (spi->chip_select);
 	chip->chip_select_num = spi->chip_select;
+	if (chip->chip_select_num < MAX_CTRL_CS) {
+		if (!(spi->mode & SPI_CPHA))
+			dev_warn(&spi->dev, "Warning: SPI CPHA not set:"
+				" Slave Select not under software control!\n"
+				" See Documentation/blackfin/bfin-spi-notes.txt");
 
-	if (chip->chip_select_num == 0) {
+		chip->flag = (1 << spi->chip_select) << 8;
+	} else
+		chip->cs_gpio = chip->chip_select_num - MAX_CTRL_CS;
+
+	if (chip->enable_dma && chip->pio_interrupt) {
+		dev_err(&spi->dev, "enable_dma is set, "
+				"do not set pio_interrupt\n");
+		goto error;
+	}
+	/*
+	 * if any one SPI chip is registered and wants DMA, request the
+	 * DMA channel for it
+	 */
+	if (chip->enable_dma && !drv_data->dma_requested) {
+		/* register dma irq handler */
+		ret = request_dma(drv_data->dma_channel, "BFIN_SPI_DMA");
+		if (ret) {
+			dev_err(&spi->dev,
+				"Unable to request BlackFin SPI DMA channel\n");
+			goto error;
+		}
+		drv_data->dma_requested = 1;
+
+		ret = set_dma_callback(drv_data->dma_channel,
+			bfin_spi_dma_irq_handler, drv_data);
+		if (ret) {
+			dev_err(&spi->dev, "Unable to set dma callback\n");
+			goto error;
+		}
+		dma_disable_irq(drv_data->dma_channel);
+	}
+
+	if (chip->pio_interrupt && !drv_data->irq_requested) {
+		ret = request_irq(drv_data->spi_irq, bfin_spi_pio_irq_handler,
+			IRQF_DISABLED, "BFIN_SPI", drv_data);
+		if (ret) {
+			dev_err(&spi->dev, "Unable to register spi IRQ\n");
+			goto error;
+		}
+		drv_data->irq_requested = 1;
+		/* we use write mode, spi irq has to be disabled here */
+		disable_irq(drv_data->spi_irq);
+	}
+
+	if (chip->chip_select_num >= MAX_CTRL_CS) {
 		ret = gpio_request(chip->cs_gpio, spi->modalias);
 		if (ret) {
-			if (drv_data->dma_requested)
-				free_dma(drv_data->dma_channel);
-			return ret;
+			dev_err(&spi->dev, "gpio_request() error\n");
+			goto pin_error;
 		}
 		gpio_direction_output(chip->cs_gpio, 1);
 	}
 
-	switch (chip->bits_per_word) {
-	case 8:
-		chip->n_bytes = 1;
-		chip->width = CFG_SPI_WORDSIZE8;
-		chip->read = chip->cs_change_per_word ?
-			bfin_spi_u8_cs_chg_reader : bfin_spi_u8_reader;
-		chip->write = chip->cs_change_per_word ?
-			bfin_spi_u8_cs_chg_writer : bfin_spi_u8_writer;
-		chip->duplex = chip->cs_change_per_word ?
-			bfin_spi_u8_cs_chg_duplex : bfin_spi_u8_duplex;
-		break;
-
-	case 16:
-		chip->n_bytes = 2;
-		chip->width = CFG_SPI_WORDSIZE16;
-		chip->read = chip->cs_change_per_word ?
-			bfin_spi_u16_cs_chg_reader : bfin_spi_u16_reader;
-		chip->write = chip->cs_change_per_word ?
-			bfin_spi_u16_cs_chg_writer : bfin_spi_u16_writer;
-		chip->duplex = chip->cs_change_per_word ?
-			bfin_spi_u16_cs_chg_duplex : bfin_spi_u16_duplex;
-		break;
-
-	default:
-		dev_err(&spi->dev, "%d bits_per_word is not supported\n",
-				chip->bits_per_word);
-		if (chip_info)
-			kfree(chip);
-		return -ENODEV;
-	}
-
 	dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n",
-			spi->modalias, chip->width, chip->enable_dma);
+			spi->modalias, spi->bits_per_word, chip->enable_dma);
 	dev_dbg(&spi->dev, "ctl_reg is 0x%x, flag_reg is 0x%x\n",
 			chip->ctl_reg, chip->flag);
 
 	spi_set_ctldata(spi, chip);
 
 	dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num);
-	if ((chip->chip_select_num > 0)
-		&& (chip->chip_select_num <= spi->master->num_chipselect))
-		peripheral_request(ssel[spi->master->bus_num]
-			[chip->chip_select_num-1], spi->modalias);
+	if (chip->chip_select_num < MAX_CTRL_CS) {
+		ret = peripheral_request(ssel[spi->master->bus_num]
+		                         [chip->chip_select_num-1], spi->modalias);
+		if (ret) {
+			dev_err(&spi->dev, "peripheral_request() error\n");
+			goto pin_error;
+		}
+	}
 
+	bfin_spi_cs_enable(drv_data, chip);
 	bfin_spi_cs_deactive(drv_data, chip);
 
 	return 0;
+
+ pin_error:
+	if (chip->chip_select_num >= MAX_CTRL_CS)
+		gpio_free(chip->cs_gpio);
+	else
+		peripheral_free(ssel[spi->master->bus_num]
+			[chip->chip_select_num - 1]);
+ error:
+	if (chip) {
+		if (drv_data->dma_requested)
+			free_dma(drv_data->dma_channel);
+		drv_data->dma_requested = 0;
+
+		kfree(chip);
+		/* prevent free 'chip' twice */
+		spi_set_ctldata(spi, NULL);
+	}
+
+	return ret;
 }
 
 /*
@@ -1152,28 +1155,30 @@
  */
 static void bfin_spi_cleanup(struct spi_device *spi)
 {
-	struct chip_data *chip = spi_get_ctldata(spi);
+	struct bfin_spi_slave_data *chip = spi_get_ctldata(spi);
+	struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
 
 	if (!chip)
 		return;
 
-	if ((chip->chip_select_num > 0)
-		&& (chip->chip_select_num <= spi->master->num_chipselect))
+	if (chip->chip_select_num < MAX_CTRL_CS) {
 		peripheral_free(ssel[spi->master->bus_num]
 					[chip->chip_select_num-1]);
-
-	if (chip->chip_select_num == 0)
+		bfin_spi_cs_disable(drv_data, chip);
+	} else
 		gpio_free(chip->cs_gpio);
 
 	kfree(chip);
+	/* prevent free 'chip' twice */
+	spi_set_ctldata(spi, NULL);
 }
 
-static inline int bfin_spi_init_queue(struct driver_data *drv_data)
+static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
 {
 	INIT_LIST_HEAD(&drv_data->queue);
 	spin_lock_init(&drv_data->lock);
 
-	drv_data->run = QUEUE_STOPPED;
+	drv_data->running = false;
 	drv_data->busy = 0;
 
 	/* init transfer tasklet */
@@ -1190,18 +1195,18 @@
 	return 0;
 }
 
-static inline int bfin_spi_start_queue(struct driver_data *drv_data)
+static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&drv_data->lock, flags);
 
-	if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
+	if (drv_data->running || drv_data->busy) {
 		spin_unlock_irqrestore(&drv_data->lock, flags);
 		return -EBUSY;
 	}
 
-	drv_data->run = QUEUE_RUNNING;
+	drv_data->running = true;
 	drv_data->cur_msg = NULL;
 	drv_data->cur_transfer = NULL;
 	drv_data->cur_chip = NULL;
@@ -1212,7 +1217,7 @@
 	return 0;
 }
 
-static inline int bfin_spi_stop_queue(struct driver_data *drv_data)
+static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
 {
 	unsigned long flags;
 	unsigned limit = 500;
@@ -1226,7 +1231,7 @@
 	 * execution path (pump_messages) would be required to call wake_up or
 	 * friends on every SPI message. Do this instead
 	 */
-	drv_data->run = QUEUE_STOPPED;
+	drv_data->running = false;
 	while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
 		spin_unlock_irqrestore(&drv_data->lock, flags);
 		msleep(10);
@@ -1241,7 +1246,7 @@
 	return status;
 }
 
-static inline int bfin_spi_destroy_queue(struct driver_data *drv_data)
+static inline int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
 {
 	int status;
 
@@ -1259,14 +1264,14 @@
 	struct device *dev = &pdev->dev;
 	struct bfin5xx_spi_master *platform_info;
 	struct spi_master *master;
-	struct driver_data *drv_data = 0;
+	struct bfin_spi_master_data *drv_data;
 	struct resource *res;
 	int status = 0;
 
 	platform_info = dev->platform_data;
 
 	/* Allocate master with space for drv_data */
-	master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
+	master = spi_alloc_master(dev, sizeof(*drv_data));
 	if (!master) {
 		dev_err(&pdev->dev, "can not alloc spi_master\n");
 		return -ENOMEM;
@@ -1302,11 +1307,19 @@
 		goto out_error_ioremap;
 	}
 
-	drv_data->dma_channel = platform_get_irq(pdev, 0);
-	if (drv_data->dma_channel < 0) {
+	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (res == NULL) {
 		dev_err(dev, "No DMA channel specified\n");
 		status = -ENOENT;
-		goto out_error_no_dma_ch;
+		goto out_error_free_io;
+	}
+	drv_data->dma_channel = res->start;
+
+	drv_data->spi_irq = platform_get_irq(pdev, 0);
+	if (drv_data->spi_irq < 0) {
+		dev_err(dev, "No spi pio irq specified\n");
+		status = -ENOENT;
+		goto out_error_free_io;
 	}
 
 	/* Initial and start queue */
@@ -1328,6 +1341,12 @@
 		goto out_error_queue_alloc;
 	}
 
+	/* Reset SPI registers. If these registers were used by the boot loader,
+	 * the sky may fall on your head if you enable the dma controller.
+	 */
+	write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
+	write_FLAG(drv_data, 0xFF00);
+
 	/* Register with the SPI framework */
 	platform_set_drvdata(pdev, drv_data);
 	status = spi_register_master(master);
@@ -1343,7 +1362,7 @@
 
 out_error_queue_alloc:
 	bfin_spi_destroy_queue(drv_data);
-out_error_no_dma_ch:
+out_error_free_io:
 	iounmap((void *) drv_data->regs_base);
 out_error_ioremap:
 out_error_get_res:
@@ -1355,7 +1374,7 @@
 /* stop hardware and remove the driver */
 static int __devexit bfin_spi_remove(struct platform_device *pdev)
 {
-	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
 	int status = 0;
 
 	if (!drv_data)
@@ -1375,6 +1394,11 @@
 			free_dma(drv_data->dma_channel);
 	}
 
+	if (drv_data->irq_requested) {
+		free_irq(drv_data->spi_irq, drv_data);
+		drv_data->irq_requested = 0;
+	}
+
 	/* Disconnect from the SPI framework */
 	spi_unregister_master(drv_data->master);
 
@@ -1389,26 +1413,32 @@
 #ifdef CONFIG_PM
 static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
 	int status = 0;
 
 	status = bfin_spi_stop_queue(drv_data);
 	if (status != 0)
 		return status;
 
-	/* stop hardware */
-	bfin_spi_disable(drv_data);
+	drv_data->ctrl_reg = read_CTRL(drv_data);
+	drv_data->flag_reg = read_FLAG(drv_data);
+
+	/*
+	 * reset SPI_CTL and SPI_FLG registers
+	 */
+	write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
+	write_FLAG(drv_data, 0xFF00);
 
 	return 0;
 }
 
 static int bfin_spi_resume(struct platform_device *pdev)
 {
-	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
 	int status = 0;
 
-	/* Enable the SPI interface */
-	bfin_spi_enable(drv_data);
+	write_CTRL(drv_data, drv_data->ctrl_reg);
+	write_FLAG(drv_data, drv_data->flag_reg);
 
 	/* Start the queue running */
 	status = bfin_spi_start_queue(drv_data);
@@ -1439,7 +1469,7 @@
 {
 	return platform_driver_probe(&bfin_spi_driver, bfin_spi_probe);
 }
-module_init(bfin_spi_init);
+subsys_initcall(bfin_spi_init);
 
 static void __exit bfin_spi_exit(void)
 {
diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi_fsl_espi.c
new file mode 100644
index 0000000..e3b4f64
--- /dev/null
+++ b/drivers/spi/spi_fsl_espi.c
@@ -0,0 +1,748 @@
+/*
+ * Freescale eSPI controller driver.
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/mm.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_spi.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <sysdev/fsl_soc.h>
+
+#include "spi_fsl_lib.h"
+
+/* eSPI Controller registers */
+struct fsl_espi_reg {
+	__be32 mode;		/* 0x000 - eSPI mode register */
+	__be32 event;		/* 0x004 - eSPI event register */
+	__be32 mask;		/* 0x008 - eSPI mask register */
+	__be32 command;		/* 0x00c - eSPI command register */
+	__be32 transmit;	/* 0x010 - eSPI transmit FIFO access register*/
+	__be32 receive;		/* 0x014 - eSPI receive FIFO access register*/
+	u8 res[8];		/* 0x018 - 0x01c reserved */
+	__be32 csmode[4];	/* 0x020 - 0x02c eSPI cs mode register */
+};
+
+struct fsl_espi_transfer {
+	const void *tx_buf;
+	void *rx_buf;
+	unsigned len;
+	unsigned n_tx;
+	unsigned n_rx;
+	unsigned actual_length;
+	int status;
+};
+
+/* eSPI Controller mode register definitions */
+#define SPMODE_ENABLE		(1 << 31)
+#define SPMODE_LOOP		(1 << 30)
+#define SPMODE_TXTHR(x)		((x) << 8)
+#define SPMODE_RXTHR(x)		((x) << 0)
+
+/* eSPI Controller CS mode register definitions */
+#define CSMODE_CI_INACTIVEHIGH	(1 << 31)
+#define CSMODE_CP_BEGIN_EDGECLK	(1 << 30)
+#define CSMODE_REV		(1 << 29)
+#define CSMODE_DIV16		(1 << 28)
+#define CSMODE_PM(x)		((x) << 24)
+#define CSMODE_POL_1		(1 << 20)
+#define CSMODE_LEN(x)		((x) << 16)
+#define CSMODE_BEF(x)		((x) << 12)
+#define CSMODE_AFT(x)		((x) << 8)
+#define CSMODE_CG(x)		((x) << 3)
+
+/* Default mode/csmode for eSPI controller */
+#define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(3))
+#define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \
+		| CSMODE_AFT(0) | CSMODE_CG(1))
+
+/* SPIE register values */
+#define	SPIE_NE		0x00000200	/* Not empty */
+#define	SPIE_NF		0x00000100	/* Not full */
+
+/* SPIM register values */
+#define	SPIM_NE		0x00000200	/* Not empty */
+#define	SPIM_NF		0x00000100	/* Not full */
+#define SPIE_RXCNT(reg)     ((reg >> 24) & 0x3F)
+#define SPIE_TXCNT(reg)     ((reg >> 16) & 0x3F)
+
+/* SPCOM register values */
+#define SPCOM_CS(x)		((x) << 30)
+#define SPCOM_TRANLEN(x)	((x) << 0)
+#define	SPCOM_TRANLEN_MAX	0xFFFF	/* Max transaction length */
+
+static void fsl_espi_change_mode(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+	__be32 __iomem *mode = &reg_base->csmode[spi->chip_select];
+	__be32 __iomem *espi_mode = &reg_base->mode;
+	u32 tmp;
+	unsigned long flags;
+
+	/* Turn off IRQs locally to minimize time that SPI is disabled. */
+	local_irq_save(flags);
+
+	/* Turn off SPI unit prior changing mode */
+	tmp = mpc8xxx_spi_read_reg(espi_mode);
+	mpc8xxx_spi_write_reg(espi_mode, tmp & ~SPMODE_ENABLE);
+	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
+	mpc8xxx_spi_write_reg(espi_mode, tmp);
+
+	local_irq_restore(flags);
+}
+
+static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi)
+{
+	u32 data;
+	u16 data_h;
+	u16 data_l;
+	const u32 *tx = mpc8xxx_spi->tx;
+
+	if (!tx)
+		return 0;
+
+	data = *tx++ << mpc8xxx_spi->tx_shift;
+	data_l = data & 0xffff;
+	data_h = (data >> 16) & 0xffff;
+	swab16s(&data_l);
+	swab16s(&data_h);
+	data = data_h | data_l;
+
+	mpc8xxx_spi->tx = tx;
+	return data;
+}
+
+static int fsl_espi_setup_transfer(struct spi_device *spi,
+					struct spi_transfer *t)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	int bits_per_word = 0;
+	u8 pm;
+	u32 hz = 0;
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+
+	if (t) {
+		bits_per_word = t->bits_per_word;
+		hz = t->speed_hz;
+	}
+
+	/* spi_transfer level calls that work per-word */
+	if (!bits_per_word)
+		bits_per_word = spi->bits_per_word;
+
+	/* Make sure its a bit width we support [4..16] */
+	if ((bits_per_word < 4) || (bits_per_word > 16))
+		return -EINVAL;
+
+	if (!hz)
+		hz = spi->max_speed_hz;
+
+	cs->rx_shift = 0;
+	cs->tx_shift = 0;
+	cs->get_rx = mpc8xxx_spi_rx_buf_u32;
+	cs->get_tx = mpc8xxx_spi_tx_buf_u32;
+	if (bits_per_word <= 8) {
+		cs->rx_shift = 8 - bits_per_word;
+	} else if (bits_per_word <= 16) {
+		cs->rx_shift = 16 - bits_per_word;
+		if (spi->mode & SPI_LSB_FIRST)
+			cs->get_tx = fsl_espi_tx_buf_lsb;
+	} else {
+		return -EINVAL;
+	}
+
+	mpc8xxx_spi->rx_shift = cs->rx_shift;
+	mpc8xxx_spi->tx_shift = cs->tx_shift;
+	mpc8xxx_spi->get_rx = cs->get_rx;
+	mpc8xxx_spi->get_tx = cs->get_tx;
+
+	bits_per_word = bits_per_word - 1;
+
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF));
+
+	cs->hw_mode |= CSMODE_LEN(bits_per_word);
+
+	if ((mpc8xxx_spi->spibrg / hz) > 64) {
+		cs->hw_mode |= CSMODE_DIV16;
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
+
+		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
+			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
+			  hz, mpc8xxx_spi->spibrg / 1024);
+		if (pm > 16)
+			pm = 16;
+	} else {
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
+	}
+	if (pm)
+		pm--;
+
+	cs->hw_mode |= CSMODE_PM(pm);
+
+	fsl_espi_change_mode(spi);
+	return 0;
+}
+
+static int fsl_espi_cpu_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t,
+		unsigned int len)
+{
+	u32 word;
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+
+	mspi->count = len;
+
+	/* enable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
+
+	/* transmit word */
+	word = mspi->get_tx(mspi);
+	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+
+	return 0;
+}
+
+static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
+	unsigned int len = t->len;
+	u8 bits_per_word;
+	int ret;
+
+	bits_per_word = spi->bits_per_word;
+	if (t->bits_per_word)
+		bits_per_word = t->bits_per_word;
+
+	mpc8xxx_spi->len = t->len;
+	len = roundup(len, 4) / 4;
+
+	mpc8xxx_spi->tx = t->tx_buf;
+	mpc8xxx_spi->rx = t->rx_buf;
+
+	INIT_COMPLETION(mpc8xxx_spi->done);
+
+	/* Set SPCOM[CS] and SPCOM[TRANLEN] field */
+	if ((t->len - 1) > SPCOM_TRANLEN_MAX) {
+		dev_err(mpc8xxx_spi->dev, "Transaction length (%d)"
+				" beyond the SPCOM[TRANLEN] field\n", t->len);
+		return -EINVAL;
+	}
+	mpc8xxx_spi_write_reg(&reg_base->command,
+		(SPCOM_CS(spi->chip_select) | SPCOM_TRANLEN(t->len - 1)));
+
+	ret = fsl_espi_cpu_bufs(mpc8xxx_spi, t, len);
+	if (ret)
+		return ret;
+
+	wait_for_completion(&mpc8xxx_spi->done);
+
+	/* disable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+
+	return mpc8xxx_spi->count;
+}
+
+static void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd)
+{
+	if (cmd[1] && cmd[2] && cmd[3]) {
+		cmd[1] = (u8)(addr >> 16);
+		cmd[2] = (u8)(addr >> 8);
+		cmd[3] = (u8)(addr >> 0);
+	}
+}
+
+static unsigned int fsl_espi_cmd2addr(u8 *cmd)
+{
+	if (cmd[1] && cmd[2] && cmd[3])
+		return cmd[1] << 16 | cmd[2] << 8 | cmd[3] << 0;
+
+	return 0;
+}
+
+static void fsl_espi_do_trans(struct spi_message *m,
+				struct fsl_espi_transfer *tr)
+{
+	struct spi_device *spi = m->spi;
+	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+	struct fsl_espi_transfer *espi_trans = tr;
+	struct spi_message message;
+	struct spi_transfer *t, *first, trans;
+	int status = 0;
+
+	spi_message_init(&message);
+	memset(&trans, 0, sizeof(trans));
+
+	first = list_first_entry(&m->transfers, struct spi_transfer,
+			transfer_list);
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if ((first->bits_per_word != t->bits_per_word) ||
+			(first->speed_hz != t->speed_hz)) {
+			espi_trans->status = -EINVAL;
+			dev_err(mspi->dev, "bits_per_word/speed_hz should be"
+					" same for the same SPI transfer\n");
+			return;
+		}
+
+		trans.speed_hz = t->speed_hz;
+		trans.bits_per_word = t->bits_per_word;
+		trans.delay_usecs = max(first->delay_usecs, t->delay_usecs);
+	}
+
+	trans.len = espi_trans->len;
+	trans.tx_buf = espi_trans->tx_buf;
+	trans.rx_buf = espi_trans->rx_buf;
+	spi_message_add_tail(&trans, &message);
+
+	list_for_each_entry(t, &message.transfers, transfer_list) {
+		if (t->bits_per_word || t->speed_hz) {
+			status = -EINVAL;
+
+			status = fsl_espi_setup_transfer(spi, t);
+			if (status < 0)
+				break;
+		}
+
+		if (t->len)
+			status = fsl_espi_bufs(spi, t);
+
+		if (status) {
+			status = -EMSGSIZE;
+			break;
+		}
+
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+	}
+
+	espi_trans->status = status;
+	fsl_espi_setup_transfer(spi, NULL);
+}
+
+static void fsl_espi_cmd_trans(struct spi_message *m,
+				struct fsl_espi_transfer *trans, u8 *rx_buff)
+{
+	struct spi_transfer *t;
+	u8 *local_buf;
+	int i = 0;
+	struct fsl_espi_transfer *espi_trans = trans;
+
+	local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
+	if (!local_buf) {
+		espi_trans->status = -ENOMEM;
+		return;
+	}
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->tx_buf) {
+			memcpy(local_buf + i, t->tx_buf, t->len);
+			i += t->len;
+		}
+	}
+
+	espi_trans->tx_buf = local_buf;
+	espi_trans->rx_buf = local_buf + espi_trans->n_tx;
+	fsl_espi_do_trans(m, espi_trans);
+
+	espi_trans->actual_length = espi_trans->len;
+	kfree(local_buf);
+}
+
+static void fsl_espi_rw_trans(struct spi_message *m,
+				struct fsl_espi_transfer *trans, u8 *rx_buff)
+{
+	struct fsl_espi_transfer *espi_trans = trans;
+	unsigned int n_tx = espi_trans->n_tx;
+	unsigned int n_rx = espi_trans->n_rx;
+	struct spi_transfer *t;
+	u8 *local_buf;
+	u8 *rx_buf = rx_buff;
+	unsigned int trans_len;
+	unsigned int addr;
+	int i, pos, loop;
+
+	local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
+	if (!local_buf) {
+		espi_trans->status = -ENOMEM;
+		return;
+	}
+
+	for (pos = 0, loop = 0; pos < n_rx; pos += trans_len, loop++) {
+		trans_len = n_rx - pos;
+		if (trans_len > SPCOM_TRANLEN_MAX - n_tx)
+			trans_len = SPCOM_TRANLEN_MAX - n_tx;
+
+		i = 0;
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			if (t->tx_buf) {
+				memcpy(local_buf + i, t->tx_buf, t->len);
+				i += t->len;
+			}
+		}
+
+		addr = fsl_espi_cmd2addr(local_buf);
+		addr += pos;
+		fsl_espi_addr2cmd(addr, local_buf);
+
+		espi_trans->n_tx = n_tx;
+		espi_trans->n_rx = trans_len;
+		espi_trans->len = trans_len + n_tx;
+		espi_trans->tx_buf = local_buf;
+		espi_trans->rx_buf = local_buf + n_tx;
+		fsl_espi_do_trans(m, espi_trans);
+
+		memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len);
+
+		if (loop > 0)
+			espi_trans->actual_length += espi_trans->len - n_tx;
+		else
+			espi_trans->actual_length += espi_trans->len;
+	}
+
+	kfree(local_buf);
+}
+
+static void fsl_espi_do_one_msg(struct spi_message *m)
+{
+	struct spi_transfer *t;
+	u8 *rx_buf = NULL;
+	unsigned int n_tx = 0;
+	unsigned int n_rx = 0;
+	struct fsl_espi_transfer espi_trans;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->tx_buf)
+			n_tx += t->len;
+		if (t->rx_buf) {
+			n_rx += t->len;
+			rx_buf = t->rx_buf;
+		}
+	}
+
+	espi_trans.n_tx = n_tx;
+	espi_trans.n_rx = n_rx;
+	espi_trans.len = n_tx + n_rx;
+	espi_trans.actual_length = 0;
+	espi_trans.status = 0;
+
+	if (!rx_buf)
+		fsl_espi_cmd_trans(m, &espi_trans, NULL);
+	else
+		fsl_espi_rw_trans(m, &espi_trans, rx_buf);
+
+	m->actual_length = espi_trans.actual_length;
+	m->status = espi_trans.status;
+	m->complete(m->context);
+}
+
+static int fsl_espi_setup(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_espi_reg *reg_base;
+	int retval;
+	u32 hw_mode;
+	u32 loop_mode;
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+
+	if (!spi->max_speed_hz)
+		return -EINVAL;
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+
+	mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	reg_base = mpc8xxx_spi->reg_base;
+
+	hw_mode = cs->hw_mode; /* Save orginal settings */
+	cs->hw_mode = mpc8xxx_spi_read_reg(
+			&reg_base->csmode[spi->chip_select]);
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(CSMODE_CP_BEGIN_EDGECLK | CSMODE_CI_INACTIVEHIGH
+			 | CSMODE_REV);
+
+	if (spi->mode & SPI_CPHA)
+		cs->hw_mode |= CSMODE_CP_BEGIN_EDGECLK;
+	if (spi->mode & SPI_CPOL)
+		cs->hw_mode |= CSMODE_CI_INACTIVEHIGH;
+	if (!(spi->mode & SPI_LSB_FIRST))
+		cs->hw_mode |= CSMODE_REV;
+
+	/* Handle the loop mode */
+	loop_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
+	loop_mode &= ~SPMODE_LOOP;
+	if (spi->mode & SPI_LOOP)
+		loop_mode |= SPMODE_LOOP;
+	mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
+
+	retval = fsl_espi_setup_transfer(spi, NULL);
+	if (retval < 0) {
+		cs->hw_mode = hw_mode; /* Restore settings */
+		return retval;
+	}
+	return 0;
+}
+
+void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
+{
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+
+	/* We need handle RX first */
+	if (events & SPIE_NE) {
+		u32 rx_data;
+
+		/* Spin until RX is done */
+		while (SPIE_RXCNT(events) < min(4, mspi->len)) {
+			cpu_relax();
+			events = mpc8xxx_spi_read_reg(&reg_base->event);
+		}
+		mspi->len -= 4;
+
+		rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
+
+		if (mspi->rx)
+			mspi->get_rx(rx_data, mspi);
+	}
+
+	if (!(events & SPIE_NF)) {
+		int ret;
+
+		/* spin until TX is done */
+		ret = spin_event_timeout(((events = mpc8xxx_spi_read_reg(
+				&reg_base->event)) & SPIE_NF) == 0, 1000, 0);
+		if (!ret) {
+			dev_err(mspi->dev, "tired waiting for SPIE_NF\n");
+			return;
+		}
+	}
+
+	/* Clear the events */
+	mpc8xxx_spi_write_reg(&reg_base->event, events);
+
+	mspi->count -= 1;
+	if (mspi->count) {
+		u32 word = mspi->get_tx(mspi);
+
+		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+	} else {
+		complete(&mspi->done);
+	}
+}
+
+static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
+{
+	struct mpc8xxx_spi *mspi = context_data;
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+	irqreturn_t ret = IRQ_NONE;
+	u32 events;
+
+	/* Get interrupt events(tx/rx) */
+	events = mpc8xxx_spi_read_reg(&reg_base->event);
+	if (events)
+		ret = IRQ_HANDLED;
+
+	dev_vdbg(mspi->dev, "%s: events %x\n", __func__, events);
+
+	fsl_espi_cpu_irq(mspi, events);
+
+	return ret;
+}
+
+static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
+{
+	iounmap(mspi->reg_base);
+}
+
+static struct spi_master * __devinit fsl_espi_probe(struct device *dev,
+		struct resource *mem, unsigned int irq)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct spi_master *master;
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_espi_reg *reg_base;
+	u32 regval;
+	int i, ret = 0;
+
+	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
+	if (!master) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	dev_set_drvdata(dev, master);
+
+	ret = mpc8xxx_spi_probe(dev, mem, irq);
+	if (ret)
+		goto err_probe;
+
+	master->setup = fsl_espi_setup;
+
+	mpc8xxx_spi = spi_master_get_devdata(master);
+	mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
+	mpc8xxx_spi->spi_remove = fsl_espi_remove;
+
+	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
+	if (!mpc8xxx_spi->reg_base) {
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+
+	reg_base = mpc8xxx_spi->reg_base;
+
+	/* Register for SPI Interrupt */
+	ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
+			  0, "fsl_espi", mpc8xxx_spi);
+	if (ret)
+		goto free_irq;
+
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+		mpc8xxx_spi->rx_shift = 16;
+		mpc8xxx_spi->tx_shift = 24;
+	}
+
+	/* SPI controller initializations */
+	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+	mpc8xxx_spi_write_reg(&reg_base->command, 0);
+	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
+
+	/* Init eSPI CS mode register */
+	for (i = 0; i < pdata->max_chipselect; i++)
+		mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
+
+	/* Enable SPI interface */
+	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+
+	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+	ret = spi_register_master(master);
+	if (ret < 0)
+		goto unreg_master;
+
+	dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
+
+	return master;
+
+unreg_master:
+	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+free_irq:
+	iounmap(mpc8xxx_spi->reg_base);
+err_probe:
+	spi_master_put(master);
+err:
+	return ERR_PTR(ret);
+}
+
+static int of_fsl_espi_get_chipselects(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	const u32 *prop;
+	int len;
+
+	prop = of_get_property(np, "fsl,espi-num-chipselects", &len);
+	if (!prop || len < sizeof(*prop)) {
+		dev_err(dev, "No 'fsl,espi-num-chipselects' property\n");
+		return -EINVAL;
+	}
+
+	pdata->max_chipselect = *prop;
+	pdata->cs_control = NULL;
+
+	return 0;
+}
+
+static int __devinit of_fsl_espi_probe(struct platform_device *ofdev,
+					const struct of_device_id *ofid)
+{
+	struct device *dev = &ofdev->dev;
+	struct device_node *np = ofdev->dev.of_node;
+	struct spi_master *master;
+	struct resource mem;
+	struct resource irq;
+	int ret = -ENOMEM;
+
+	ret = of_mpc8xxx_spi_probe(ofdev, ofid);
+	if (ret)
+		return ret;
+
+	ret = of_fsl_espi_get_chipselects(dev);
+	if (ret)
+		goto err;
+
+	ret = of_address_to_resource(np, 0, &mem);
+	if (ret)
+		goto err;
+
+	ret = of_irq_to_resource(np, 0, &irq);
+	if (!ret) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	master = fsl_espi_probe(dev, &mem, irq.start);
+	if (IS_ERR(master)) {
+		ret = PTR_ERR(master);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static int __devexit of_fsl_espi_remove(struct platform_device *dev)
+{
+	return mpc8xxx_spi_remove(&dev->dev);
+}
+
+static const struct of_device_id of_fsl_espi_match[] = {
+	{ .compatible = "fsl,mpc8536-espi" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
+
+static struct of_platform_driver fsl_espi_driver = {
+	.driver = {
+		.name = "fsl_espi",
+		.owner = THIS_MODULE,
+		.of_match_table = of_fsl_espi_match,
+	},
+	.probe		= of_fsl_espi_probe,
+	.remove		= __devexit_p(of_fsl_espi_remove),
+};
+
+static int __init fsl_espi_init(void)
+{
+	return of_register_platform_driver(&fsl_espi_driver);
+}
+module_init(fsl_espi_init);
+
+static void __exit fsl_espi_exit(void)
+{
+	of_unregister_platform_driver(&fsl_espi_driver);
+}
+module_exit(fsl_espi_exit);
+
+MODULE_AUTHOR("Mingkai Hu");
+MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_fsl_lib.c b/drivers/spi/spi_fsl_lib.c
new file mode 100644
index 0000000..5cd741f
--- /dev/null
+++ b/drivers/spi/spi_fsl_lib.c
@@ -0,0 +1,237 @@
+/*
+ * Freescale SPI/eSPI controller driver library.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright (C) 2006 Polycom, Inc.
+ *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/fsl_devices.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/of_platform.h>
+#include <linux/of_spi.h>
+#include <sysdev/fsl_soc.h>
+
+#include "spi_fsl_lib.h"
+
+#define MPC8XXX_SPI_RX_BUF(type) 					  \
+void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
+{									  \
+	type *rx = mpc8xxx_spi->rx;					  \
+	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
+	mpc8xxx_spi->rx = rx;						  \
+}
+
+#define MPC8XXX_SPI_TX_BUF(type)				\
+u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
+{								\
+	u32 data;						\
+	const type *tx = mpc8xxx_spi->tx;			\
+	if (!tx)						\
+		return 0;					\
+	data = *tx++ << mpc8xxx_spi->tx_shift;			\
+	mpc8xxx_spi->tx = tx;					\
+	return data;						\
+}
+
+MPC8XXX_SPI_RX_BUF(u8)
+MPC8XXX_SPI_RX_BUF(u16)
+MPC8XXX_SPI_RX_BUF(u32)
+MPC8XXX_SPI_TX_BUF(u8)
+MPC8XXX_SPI_TX_BUF(u16)
+MPC8XXX_SPI_TX_BUF(u32)
+
+struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata)
+{
+	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
+}
+
+void mpc8xxx_spi_work(struct work_struct *work)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
+						       work);
+
+	spin_lock_irq(&mpc8xxx_spi->lock);
+	while (!list_empty(&mpc8xxx_spi->queue)) {
+		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
+						   struct spi_message, queue);
+
+		list_del_init(&m->queue);
+		spin_unlock_irq(&mpc8xxx_spi->lock);
+
+		if (mpc8xxx_spi->spi_do_one_msg)
+			mpc8xxx_spi->spi_do_one_msg(m);
+
+		spin_lock_irq(&mpc8xxx_spi->lock);
+	}
+	spin_unlock_irq(&mpc8xxx_spi->lock);
+}
+
+int mpc8xxx_spi_transfer(struct spi_device *spi,
+				struct spi_message *m)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
+	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
+	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
+	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
+
+	return 0;
+}
+
+void mpc8xxx_spi_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+const char *mpc8xxx_spi_strmode(unsigned int flags)
+{
+	if (flags & SPI_QE_CPU_MODE) {
+		return "QE CPU";
+	} else if (flags & SPI_CPM_MODE) {
+		if (flags & SPI_QE)
+			return "QE";
+		else if (flags & SPI_CPM2)
+			return "CPM2";
+		else
+			return "CPM1";
+	}
+	return "CPU";
+}
+
+int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
+			unsigned int irq)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct spi_master *master;
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	int ret = 0;
+
+	master = dev_get_drvdata(dev);
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
+			| SPI_LSB_FIRST | SPI_LOOP;
+
+	master->transfer = mpc8xxx_spi_transfer;
+	master->cleanup = mpc8xxx_spi_cleanup;
+	master->dev.of_node = dev->of_node;
+
+	mpc8xxx_spi = spi_master_get_devdata(master);
+	mpc8xxx_spi->dev = dev;
+	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
+	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
+	mpc8xxx_spi->flags = pdata->flags;
+	mpc8xxx_spi->spibrg = pdata->sysclk;
+	mpc8xxx_spi->irq = irq;
+
+	mpc8xxx_spi->rx_shift = 0;
+	mpc8xxx_spi->tx_shift = 0;
+
+	init_completion(&mpc8xxx_spi->done);
+
+	master->bus_num = pdata->bus_num;
+	master->num_chipselect = pdata->max_chipselect;
+
+	spin_lock_init(&mpc8xxx_spi->lock);
+	init_completion(&mpc8xxx_spi->done);
+	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
+	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
+
+	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
+		dev_name(master->dev.parent));
+	if (mpc8xxx_spi->workqueue == NULL) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	return 0;
+
+err:
+	return ret;
+}
+
+int __devexit mpc8xxx_spi_remove(struct device *dev)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct spi_master *master;
+
+	master = dev_get_drvdata(dev);
+	mpc8xxx_spi = spi_master_get_devdata(master);
+
+	flush_workqueue(mpc8xxx_spi->workqueue);
+	destroy_workqueue(mpc8xxx_spi->workqueue);
+	spi_unregister_master(master);
+
+	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+
+	if (mpc8xxx_spi->spi_remove)
+		mpc8xxx_spi->spi_remove(mpc8xxx_spi);
+
+	return 0;
+}
+
+int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
+					const struct of_device_id *ofid)
+{
+	struct device *dev = &ofdev->dev;
+	struct device_node *np = ofdev->dev.of_node;
+	struct mpc8xxx_spi_probe_info *pinfo;
+	struct fsl_spi_platform_data *pdata;
+	const void *prop;
+	int ret = -ENOMEM;
+
+	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
+	if (!pinfo)
+		return -ENOMEM;
+
+	pdata = &pinfo->pdata;
+	dev->platform_data = pdata;
+
+	/* Allocate bus num dynamically. */
+	pdata->bus_num = -1;
+
+	/* SPI controller is either clocked from QE or SoC clock. */
+	pdata->sysclk = get_brgfreq();
+	if (pdata->sysclk == -1) {
+		pdata->sysclk = fsl_get_sys_freq();
+		if (pdata->sysclk == -1) {
+			ret = -ENODEV;
+			goto err;
+		}
+	}
+
+	prop = of_get_property(np, "mode", NULL);
+	if (prop && !strcmp(prop, "cpu-qe"))
+		pdata->flags = SPI_QE_CPU_MODE;
+	else if (prop && !strcmp(prop, "qe"))
+		pdata->flags = SPI_CPM_MODE | SPI_QE;
+	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
+		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
+	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
+		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
+
+	return 0;
+
+err:
+	kfree(pinfo);
+	return ret;
+}
diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h
new file mode 100644
index 0000000..281e060
--- /dev/null
+++ b/drivers/spi/spi_fsl_lib.h
@@ -0,0 +1,124 @@
+/*
+ * Freescale SPI/eSPI controller driver library.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2006 Polycom, Inc.
+ *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef __SPI_FSL_LIB_H__
+#define __SPI_FSL_LIB_H__
+
+#include <asm/io.h>
+
+/* SPI/eSPI Controller driver's private data. */
+struct mpc8xxx_spi {
+	struct device *dev;
+	void *reg_base;
+
+	/* rx & tx bufs from the spi_transfer */
+	const void *tx;
+	void *rx;
+#ifdef CONFIG_SPI_FSL_ESPI
+	int len;
+#endif
+
+	int subblock;
+	struct spi_pram __iomem *pram;
+	struct cpm_buf_desc __iomem *tx_bd;
+	struct cpm_buf_desc __iomem *rx_bd;
+
+	struct spi_transfer *xfer_in_progress;
+
+	/* dma addresses for CPM transfers */
+	dma_addr_t tx_dma;
+	dma_addr_t rx_dma;
+	bool map_tx_dma;
+	bool map_rx_dma;
+
+	dma_addr_t dma_dummy_tx;
+	dma_addr_t dma_dummy_rx;
+
+	/* functions to deal with different sized buffers */
+	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
+	u32(*get_tx) (struct mpc8xxx_spi *);
+
+	/* hooks for different controller driver */
+	void (*spi_do_one_msg) (struct spi_message *m);
+	void (*spi_remove) (struct mpc8xxx_spi *mspi);
+
+	unsigned int count;
+	unsigned int irq;
+
+	unsigned nsecs;		/* (clock cycle time)/2 */
+
+	u32 spibrg;		/* SPIBRG input clock */
+	u32 rx_shift;		/* RX data reg shift when in qe mode */
+	u32 tx_shift;		/* TX data reg shift when in qe mode */
+
+	unsigned int flags;
+
+	struct workqueue_struct *workqueue;
+	struct work_struct work;
+
+	struct list_head queue;
+	spinlock_t lock;
+
+	struct completion done;
+};
+
+struct spi_mpc8xxx_cs {
+	/* functions to deal with different sized buffers */
+	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
+	u32 (*get_tx) (struct mpc8xxx_spi *);
+	u32 rx_shift;		/* RX data reg shift when in qe mode */
+	u32 tx_shift;		/* TX data reg shift when in qe mode */
+	u32 hw_mode;		/* Holds HW mode register settings */
+};
+
+static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
+{
+	out_be32(reg, val);
+}
+
+static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
+{
+	return in_be32(reg);
+}
+
+struct mpc8xxx_spi_probe_info {
+	struct fsl_spi_platform_data pdata;
+	int *gpios;
+	bool *alow_flags;
+};
+
+extern u32 mpc8xxx_spi_tx_buf_u8(struct mpc8xxx_spi *mpc8xxx_spi);
+extern u32 mpc8xxx_spi_tx_buf_u16(struct mpc8xxx_spi *mpc8xxx_spi);
+extern u32 mpc8xxx_spi_tx_buf_u32(struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u8(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u16(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u32(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+
+extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
+		struct fsl_spi_platform_data *pdata);
+extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
+		struct spi_transfer *t, unsigned int len);
+extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m);
+extern void mpc8xxx_spi_cleanup(struct spi_device *spi);
+extern const char *mpc8xxx_spi_strmode(unsigned int flags);
+extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
+		unsigned int irq);
+extern int mpc8xxx_spi_remove(struct device *dev);
+extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev,
+				const struct of_device_id *ofid);
+
+#endif /* __SPI_FSL_LIB_H__ */
diff --git a/drivers/spi/spi_fsl_spi.c b/drivers/spi/spi_fsl_spi.c
new file mode 100644
index 0000000..7ca52d3
--- /dev/null
+++ b/drivers/spi/spi_fsl_spi.c
@@ -0,0 +1,1193 @@
+/*
+ * Freescale SPI controller driver.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright (C) 2006 Polycom, Inc.
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include <sysdev/fsl_soc.h>
+#include <asm/cpm.h>
+#include <asm/qe.h>
+
+#include "spi_fsl_lib.h"
+
+/* CPM1 and CPM2 are mutually exclusive. */
+#ifdef CONFIG_CPM1
+#include <asm/cpm1.h>
+#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
+#else
+#include <asm/cpm2.h>
+#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
+#endif
+
+/* SPI Controller registers */
+struct fsl_spi_reg {
+	u8 res1[0x20];
+	__be32 mode;
+	__be32 event;
+	__be32 mask;
+	__be32 command;
+	__be32 transmit;
+	__be32 receive;
+};
+
+/* SPI Controller mode register definitions */
+#define	SPMODE_LOOP		(1 << 30)
+#define	SPMODE_CI_INACTIVEHIGH	(1 << 29)
+#define	SPMODE_CP_BEGIN_EDGECLK	(1 << 28)
+#define	SPMODE_DIV16		(1 << 27)
+#define	SPMODE_REV		(1 << 26)
+#define	SPMODE_MS		(1 << 25)
+#define	SPMODE_ENABLE		(1 << 24)
+#define	SPMODE_LEN(x)		((x) << 20)
+#define	SPMODE_PM(x)		((x) << 16)
+#define	SPMODE_OP		(1 << 14)
+#define	SPMODE_CG(x)		((x) << 7)
+
+/*
+ * Default for SPI Mode:
+ *	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
+ */
+#define	SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
+			 SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
+
+/* SPIE register values */
+#define	SPIE_NE		0x00000200	/* Not empty */
+#define	SPIE_NF		0x00000100	/* Not full */
+
+/* SPIM register values */
+#define	SPIM_NE		0x00000200	/* Not empty */
+#define	SPIM_NF		0x00000100	/* Not full */
+
+#define	SPIE_TXB	0x00000200	/* Last char is written to tx fifo */
+#define	SPIE_RXB	0x00000100	/* Last char is written to rx buf */
+
+/* SPCOM register values */
+#define	SPCOM_STR	(1 << 23)	/* Start transmit */
+
+#define	SPI_PRAM_SIZE	0x100
+#define	SPI_MRBLR	((unsigned int)PAGE_SIZE)
+
+static void *fsl_dummy_rx;
+static DEFINE_MUTEX(fsl_dummy_rx_lock);
+static int fsl_dummy_rx_refcnt;
+
+static void fsl_spi_change_mode(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+	__be32 __iomem *mode = &reg_base->mode;
+	unsigned long flags;
+
+	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
+		return;
+
+	/* Turn off IRQs locally to minimize time that SPI is disabled. */
+	local_irq_save(flags);
+
+	/* Turn off SPI unit prior changing mode */
+	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
+
+	/* When in CPM mode, we need to reinit tx and rx. */
+	if (mspi->flags & SPI_CPM_MODE) {
+		if (mspi->flags & SPI_QE) {
+			qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
+				     QE_CR_PROTOCOL_UNSPECIFIED, 0);
+		} else {
+			cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
+			if (mspi->flags & SPI_CPM1) {
+				out_be16(&mspi->pram->rbptr,
+					 in_be16(&mspi->pram->rbase));
+				out_be16(&mspi->pram->tbptr,
+					 in_be16(&mspi->pram->tbase));
+			}
+		}
+	}
+	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
+	local_irq_restore(flags);
+}
+
+static void fsl_spi_chipselect(struct spi_device *spi, int value)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
+	bool pol = spi->mode & SPI_CS_HIGH;
+	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
+
+	if (value == BITBANG_CS_INACTIVE) {
+		if (pdata->cs_control)
+			pdata->cs_control(spi, !pol);
+	}
+
+	if (value == BITBANG_CS_ACTIVE) {
+		mpc8xxx_spi->rx_shift = cs->rx_shift;
+		mpc8xxx_spi->tx_shift = cs->tx_shift;
+		mpc8xxx_spi->get_rx = cs->get_rx;
+		mpc8xxx_spi->get_tx = cs->get_tx;
+
+		fsl_spi_change_mode(spi);
+
+		if (pdata->cs_control)
+			pdata->cs_control(spi, pol);
+	}
+}
+
+static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
+				struct spi_device *spi,
+				struct mpc8xxx_spi *mpc8xxx_spi,
+				int bits_per_word)
+{
+	cs->rx_shift = 0;
+	cs->tx_shift = 0;
+	if (bits_per_word <= 8) {
+		cs->get_rx = mpc8xxx_spi_rx_buf_u8;
+		cs->get_tx = mpc8xxx_spi_tx_buf_u8;
+		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+			cs->rx_shift = 16;
+			cs->tx_shift = 24;
+		}
+	} else if (bits_per_word <= 16) {
+		cs->get_rx = mpc8xxx_spi_rx_buf_u16;
+		cs->get_tx = mpc8xxx_spi_tx_buf_u16;
+		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+			cs->rx_shift = 16;
+			cs->tx_shift = 16;
+		}
+	} else if (bits_per_word <= 32) {
+		cs->get_rx = mpc8xxx_spi_rx_buf_u32;
+		cs->get_tx = mpc8xxx_spi_tx_buf_u32;
+	} else
+		return -EINVAL;
+
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
+	    spi->mode & SPI_LSB_FIRST) {
+		cs->tx_shift = 0;
+		if (bits_per_word <= 8)
+			cs->rx_shift = 8;
+		else
+			cs->rx_shift = 0;
+	}
+	mpc8xxx_spi->rx_shift = cs->rx_shift;
+	mpc8xxx_spi->tx_shift = cs->tx_shift;
+	mpc8xxx_spi->get_rx = cs->get_rx;
+	mpc8xxx_spi->get_tx = cs->get_tx;
+
+	return bits_per_word;
+}
+
+static int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
+				struct spi_device *spi,
+				int bits_per_word)
+{
+	/* QE uses Little Endian for words > 8
+	 * so transform all words > 8 into 8 bits
+	 * Unfortnatly that doesn't work for LSB so
+	 * reject these for now */
+	/* Note: 32 bits word, LSB works iff
+	 * tfcr/rfcr is set to CPMFCR_GBL */
+	if (spi->mode & SPI_LSB_FIRST &&
+	    bits_per_word > 8)
+		return -EINVAL;
+	if (bits_per_word > 8)
+		return 8; /* pretend its 8 bits */
+	return bits_per_word;
+}
+
+static int fsl_spi_setup_transfer(struct spi_device *spi,
+					struct spi_transfer *t)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	int bits_per_word = 0;
+	u8 pm;
+	u32 hz = 0;
+	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
+
+	mpc8xxx_spi = spi_master_get_devdata(spi->master);
+
+	if (t) {
+		bits_per_word = t->bits_per_word;
+		hz = t->speed_hz;
+	}
+
+	/* spi_transfer level calls that work per-word */
+	if (!bits_per_word)
+		bits_per_word = spi->bits_per_word;
+
+	/* Make sure its a bit width we support [4..16, 32] */
+	if ((bits_per_word < 4)
+	    || ((bits_per_word > 16) && (bits_per_word != 32)))
+		return -EINVAL;
+
+	if (!hz)
+		hz = spi->max_speed_hz;
+
+	if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
+		bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
+							   mpc8xxx_spi,
+							   bits_per_word);
+	else if (mpc8xxx_spi->flags & SPI_QE)
+		bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
+							  bits_per_word);
+
+	if (bits_per_word < 0)
+		return bits_per_word;
+
+	if (bits_per_word == 32)
+		bits_per_word = 0;
+	else
+		bits_per_word = bits_per_word - 1;
+
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16
+				  | SPMODE_PM(0xF));
+
+	cs->hw_mode |= SPMODE_LEN(bits_per_word);
+
+	if ((mpc8xxx_spi->spibrg / hz) > 64) {
+		cs->hw_mode |= SPMODE_DIV16;
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
+
+		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
+			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
+			  hz, mpc8xxx_spi->spibrg / 1024);
+		if (pm > 16)
+			pm = 16;
+	} else {
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
+	}
+	if (pm)
+		pm--;
+
+	cs->hw_mode |= SPMODE_PM(pm);
+
+	fsl_spi_change_mode(spi);
+	return 0;
+}
+
+static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
+{
+	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
+	struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
+	unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
+	unsigned int xfer_ofs;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
+
+	if (mspi->rx_dma == mspi->dma_dummy_rx)
+		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
+	else
+		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
+	out_be16(&rx_bd->cbd_datlen, 0);
+	out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
+
+	if (mspi->tx_dma == mspi->dma_dummy_tx)
+		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
+	else
+		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
+	out_be16(&tx_bd->cbd_datlen, xfer_len);
+	out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
+				 BD_SC_LAST);
+
+	/* start transfer */
+	mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
+}
+
+static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
+				struct spi_transfer *t, bool is_dma_mapped)
+{
+	struct device *dev = mspi->dev;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	if (is_dma_mapped) {
+		mspi->map_tx_dma = 0;
+		mspi->map_rx_dma = 0;
+	} else {
+		mspi->map_tx_dma = 1;
+		mspi->map_rx_dma = 1;
+	}
+
+	if (!t->tx_buf) {
+		mspi->tx_dma = mspi->dma_dummy_tx;
+		mspi->map_tx_dma = 0;
+	}
+
+	if (!t->rx_buf) {
+		mspi->rx_dma = mspi->dma_dummy_rx;
+		mspi->map_rx_dma = 0;
+	}
+
+	if (mspi->map_tx_dma) {
+		void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
+
+		mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
+					      DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, mspi->tx_dma)) {
+			dev_err(dev, "unable to map tx dma\n");
+			return -ENOMEM;
+		}
+	} else if (t->tx_buf) {
+		mspi->tx_dma = t->tx_dma;
+	}
+
+	if (mspi->map_rx_dma) {
+		mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
+					      DMA_FROM_DEVICE);
+		if (dma_mapping_error(dev, mspi->rx_dma)) {
+			dev_err(dev, "unable to map rx dma\n");
+			goto err_rx_dma;
+		}
+	} else if (t->rx_buf) {
+		mspi->rx_dma = t->rx_dma;
+	}
+
+	/* enable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB);
+
+	mspi->xfer_in_progress = t;
+	mspi->count = t->len;
+
+	/* start CPM transfers */
+	fsl_spi_cpm_bufs_start(mspi);
+
+	return 0;
+
+err_rx_dma:
+	if (mspi->map_tx_dma)
+		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
+	return -ENOMEM;
+}
+
+static void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+	struct spi_transfer *t = mspi->xfer_in_progress;
+
+	if (mspi->map_tx_dma)
+		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
+	if (mspi->map_rx_dma)
+		dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
+	mspi->xfer_in_progress = NULL;
+}
+
+static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
+				struct spi_transfer *t, unsigned int len)
+{
+	u32 word;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	mspi->count = len;
+
+	/* enable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
+
+	/* transmit word */
+	word = mspi->get_tx(mspi);
+	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+
+	return 0;
+}
+
+static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
+			    bool is_dma_mapped)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	struct fsl_spi_reg *reg_base;
+	unsigned int len = t->len;
+	u8 bits_per_word;
+	int ret;
+
+	reg_base = mpc8xxx_spi->reg_base;
+	bits_per_word = spi->bits_per_word;
+	if (t->bits_per_word)
+		bits_per_word = t->bits_per_word;
+
+	if (bits_per_word > 8) {
+		/* invalid length? */
+		if (len & 1)
+			return -EINVAL;
+		len /= 2;
+	}
+	if (bits_per_word > 16) {
+		/* invalid length? */
+		if (len & 1)
+			return -EINVAL;
+		len /= 2;
+	}
+
+	mpc8xxx_spi->tx = t->tx_buf;
+	mpc8xxx_spi->rx = t->rx_buf;
+
+	INIT_COMPLETION(mpc8xxx_spi->done);
+
+	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
+		ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
+	else
+		ret = fsl_spi_cpu_bufs(mpc8xxx_spi, t, len);
+	if (ret)
+		return ret;
+
+	wait_for_completion(&mpc8xxx_spi->done);
+
+	/* disable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+
+	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
+		fsl_spi_cpm_bufs_complete(mpc8xxx_spi);
+
+	return mpc8xxx_spi->count;
+}
+
+static void fsl_spi_do_one_msg(struct spi_message *m)
+{
+	struct spi_device *spi = m->spi;
+	struct spi_transfer *t;
+	unsigned int cs_change;
+	const int nsecs = 50;
+	int status;
+
+	cs_change = 1;
+	status = 0;
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->bits_per_word || t->speed_hz) {
+			/* Don't allow changes if CS is active */
+			status = -EINVAL;
+
+			if (cs_change)
+				status = fsl_spi_setup_transfer(spi, t);
+			if (status < 0)
+				break;
+		}
+
+		if (cs_change) {
+			fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
+			ndelay(nsecs);
+		}
+		cs_change = t->cs_change;
+		if (t->len)
+			status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
+		if (status) {
+			status = -EMSGSIZE;
+			break;
+		}
+		m->actual_length += t->len;
+
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+
+		if (cs_change) {
+			ndelay(nsecs);
+			fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+			ndelay(nsecs);
+		}
+	}
+
+	m->status = status;
+	m->complete(m->context);
+
+	if (status || !cs_change) {
+		ndelay(nsecs);
+		fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+	}
+
+	fsl_spi_setup_transfer(spi, NULL);
+}
+
+static int fsl_spi_setup(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_spi_reg *reg_base;
+	int retval;
+	u32 hw_mode;
+	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
+
+	if (!spi->max_speed_hz)
+		return -EINVAL;
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+	mpc8xxx_spi = spi_master_get_devdata(spi->master);
+
+	reg_base = mpc8xxx_spi->reg_base;
+
+	hw_mode = cs->hw_mode; /* Save original settings */
+	cs->hw_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
+			 | SPMODE_REV | SPMODE_LOOP);
+
+	if (spi->mode & SPI_CPHA)
+		cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
+	if (spi->mode & SPI_CPOL)
+		cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
+	if (!(spi->mode & SPI_LSB_FIRST))
+		cs->hw_mode |= SPMODE_REV;
+	if (spi->mode & SPI_LOOP)
+		cs->hw_mode |= SPMODE_LOOP;
+
+	retval = fsl_spi_setup_transfer(spi, NULL);
+	if (retval < 0) {
+		cs->hw_mode = hw_mode; /* Restore settings */
+		return retval;
+	}
+	return 0;
+}
+
+static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
+{
+	u16 len;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
+		in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
+
+	len = in_be16(&mspi->rx_bd->cbd_datlen);
+	if (len > mspi->count) {
+		WARN_ON(1);
+		len = mspi->count;
+	}
+
+	/* Clear the events */
+	mpc8xxx_spi_write_reg(&reg_base->event, events);
+
+	mspi->count -= len;
+	if (mspi->count)
+		fsl_spi_cpm_bufs_start(mspi);
+	else
+		complete(&mspi->done);
+}
+
+static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
+{
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	/* We need handle RX first */
+	if (events & SPIE_NE) {
+		u32 rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
+
+		if (mspi->rx)
+			mspi->get_rx(rx_data, mspi);
+	}
+
+	if ((events & SPIE_NF) == 0)
+		/* spin until TX is done */
+		while (((events =
+			mpc8xxx_spi_read_reg(&reg_base->event)) &
+						SPIE_NF) == 0)
+			cpu_relax();
+
+	/* Clear the events */
+	mpc8xxx_spi_write_reg(&reg_base->event, events);
+
+	mspi->count -= 1;
+	if (mspi->count) {
+		u32 word = mspi->get_tx(mspi);
+
+		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+	} else {
+		complete(&mspi->done);
+	}
+}
+
+static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
+{
+	struct mpc8xxx_spi *mspi = context_data;
+	irqreturn_t ret = IRQ_NONE;
+	u32 events;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	/* Get interrupt events(tx/rx) */
+	events = mpc8xxx_spi_read_reg(&reg_base->event);
+	if (events)
+		ret = IRQ_HANDLED;
+
+	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
+
+	if (mspi->flags & SPI_CPM_MODE)
+		fsl_spi_cpm_irq(mspi, events);
+	else
+		fsl_spi_cpu_irq(mspi, events);
+
+	return ret;
+}
+
+static void *fsl_spi_alloc_dummy_rx(void)
+{
+	mutex_lock(&fsl_dummy_rx_lock);
+
+	if (!fsl_dummy_rx)
+		fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
+	if (fsl_dummy_rx)
+		fsl_dummy_rx_refcnt++;
+
+	mutex_unlock(&fsl_dummy_rx_lock);
+
+	return fsl_dummy_rx;
+}
+
+static void fsl_spi_free_dummy_rx(void)
+{
+	mutex_lock(&fsl_dummy_rx_lock);
+
+	switch (fsl_dummy_rx_refcnt) {
+	case 0:
+		WARN_ON(1);
+		break;
+	case 1:
+		kfree(fsl_dummy_rx);
+		fsl_dummy_rx = NULL;
+		/* fall through */
+	default:
+		fsl_dummy_rx_refcnt--;
+		break;
+	}
+
+	mutex_unlock(&fsl_dummy_rx_lock);
+}
+
+static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+	struct device_node *np = dev->of_node;
+	const u32 *iprop;
+	int size;
+	unsigned long spi_base_ofs;
+	unsigned long pram_ofs = -ENOMEM;
+
+	/* Can't use of_address_to_resource(), QE muram isn't at 0. */
+	iprop = of_get_property(np, "reg", &size);
+
+	/* QE with a fixed pram location? */
+	if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
+		return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
+
+	/* QE but with a dynamic pram location? */
+	if (mspi->flags & SPI_QE) {
+		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
+		qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
+				QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
+		return pram_ofs;
+	}
+
+	/* CPM1 and CPM2 pram must be at a fixed addr. */
+	if (!iprop || size != sizeof(*iprop) * 4)
+		return -ENOMEM;
+
+	spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
+	if (IS_ERR_VALUE(spi_base_ofs))
+		return -ENOMEM;
+
+	if (mspi->flags & SPI_CPM2) {
+		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
+		if (!IS_ERR_VALUE(pram_ofs)) {
+			u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs);
+
+			out_be16(spi_base, pram_ofs);
+		}
+	} else {
+		struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs);
+		u16 rpbase = in_be16(&pram->rpbase);
+
+		/* Microcode relocation patch applied? */
+		if (rpbase)
+			pram_ofs = rpbase;
+		else
+			return spi_base_ofs;
+	}
+
+	cpm_muram_free(spi_base_ofs);
+	return pram_ofs;
+}
+
+static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+	struct device_node *np = dev->of_node;
+	const u32 *iprop;
+	int size;
+	unsigned long pram_ofs;
+	unsigned long bds_ofs;
+
+	if (!(mspi->flags & SPI_CPM_MODE))
+		return 0;
+
+	if (!fsl_spi_alloc_dummy_rx())
+		return -ENOMEM;
+
+	if (mspi->flags & SPI_QE) {
+		iprop = of_get_property(np, "cell-index", &size);
+		if (iprop && size == sizeof(*iprop))
+			mspi->subblock = *iprop;
+
+		switch (mspi->subblock) {
+		default:
+			dev_warn(dev, "cell-index unspecified, assuming SPI1");
+			/* fall through */
+		case 0:
+			mspi->subblock = QE_CR_SUBBLOCK_SPI1;
+			break;
+		case 1:
+			mspi->subblock = QE_CR_SUBBLOCK_SPI2;
+			break;
+		}
+	}
+
+	pram_ofs = fsl_spi_cpm_get_pram(mspi);
+	if (IS_ERR_VALUE(pram_ofs)) {
+		dev_err(dev, "can't allocate spi parameter ram\n");
+		goto err_pram;
+	}
+
+	bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
+				  sizeof(*mspi->rx_bd), 8);
+	if (IS_ERR_VALUE(bds_ofs)) {
+		dev_err(dev, "can't allocate bds\n");
+		goto err_bds;
+	}
+
+	mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
+					    DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
+		dev_err(dev, "unable to map dummy tx buffer\n");
+		goto err_dummy_tx;
+	}
+
+	mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR,
+					    DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
+		dev_err(dev, "unable to map dummy rx buffer\n");
+		goto err_dummy_rx;
+	}
+
+	mspi->pram = cpm_muram_addr(pram_ofs);
+
+	mspi->tx_bd = cpm_muram_addr(bds_ofs);
+	mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
+
+	/* Initialize parameter ram. */
+	out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
+	out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
+	out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
+	out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
+	out_be16(&mspi->pram->mrblr, SPI_MRBLR);
+	out_be32(&mspi->pram->rstate, 0);
+	out_be32(&mspi->pram->rdp, 0);
+	out_be16(&mspi->pram->rbptr, 0);
+	out_be16(&mspi->pram->rbc, 0);
+	out_be32(&mspi->pram->rxtmp, 0);
+	out_be32(&mspi->pram->tstate, 0);
+	out_be32(&mspi->pram->tdp, 0);
+	out_be16(&mspi->pram->tbptr, 0);
+	out_be16(&mspi->pram->tbc, 0);
+	out_be32(&mspi->pram->txtmp, 0);
+
+	return 0;
+
+err_dummy_rx:
+	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
+err_dummy_tx:
+	cpm_muram_free(bds_ofs);
+err_bds:
+	cpm_muram_free(pram_ofs);
+err_pram:
+	fsl_spi_free_dummy_rx();
+	return -ENOMEM;
+}
+
+static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+
+	dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
+	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
+	cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
+	cpm_muram_free(cpm_muram_offset(mspi->pram));
+	fsl_spi_free_dummy_rx();
+}
+
+static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
+{
+	iounmap(mspi->reg_base);
+	fsl_spi_cpm_free(mspi);
+}
+
+static struct spi_master * __devinit fsl_spi_probe(struct device *dev,
+		struct resource *mem, unsigned int irq)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct spi_master *master;
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_spi_reg *reg_base;
+	u32 regval;
+	int ret = 0;
+
+	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
+	if (master == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	dev_set_drvdata(dev, master);
+
+	ret = mpc8xxx_spi_probe(dev, mem, irq);
+	if (ret)
+		goto err_probe;
+
+	master->setup = fsl_spi_setup;
+
+	mpc8xxx_spi = spi_master_get_devdata(master);
+	mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg;
+	mpc8xxx_spi->spi_remove = fsl_spi_remove;
+
+
+	ret = fsl_spi_cpm_init(mpc8xxx_spi);
+	if (ret)
+		goto err_cpm_init;
+
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+		mpc8xxx_spi->rx_shift = 16;
+		mpc8xxx_spi->tx_shift = 24;
+	}
+
+	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
+	if (mpc8xxx_spi->reg_base == NULL) {
+		ret = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	/* Register for SPI Interrupt */
+	ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq,
+			  0, "fsl_spi", mpc8xxx_spi);
+
+	if (ret != 0)
+		goto free_irq;
+
+	reg_base = mpc8xxx_spi->reg_base;
+
+	/* SPI controller initializations */
+	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+	mpc8xxx_spi_write_reg(&reg_base->command, 0);
+	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
+
+	/* Enable SPI interface */
+	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
+		regval |= SPMODE_OP;
+
+	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+	ret = spi_register_master(master);
+	if (ret < 0)
+		goto unreg_master;
+
+	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
+		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
+
+	return master;
+
+unreg_master:
+	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+free_irq:
+	iounmap(mpc8xxx_spi->reg_base);
+err_ioremap:
+	fsl_spi_cpm_free(mpc8xxx_spi);
+err_cpm_init:
+err_probe:
+	spi_master_put(master);
+err:
+	return ERR_PTR(ret);
+}
+
+static void fsl_spi_cs_control(struct spi_device *spi, bool on)
+{
+	struct device *dev = spi->dev.parent;
+	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
+	u16 cs = spi->chip_select;
+	int gpio = pinfo->gpios[cs];
+	bool alow = pinfo->alow_flags[cs];
+
+	gpio_set_value(gpio, on ^ alow);
+}
+
+static int of_fsl_spi_get_chipselects(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
+	unsigned int ngpios;
+	int i = 0;
+	int ret;
+
+	ngpios = of_gpio_count(np);
+	if (!ngpios) {
+		/*
+		 * SPI w/o chip-select line. One SPI device is still permitted
+		 * though.
+		 */
+		pdata->max_chipselect = 1;
+		return 0;
+	}
+
+	pinfo->gpios = kmalloc(ngpios * sizeof(*pinfo->gpios), GFP_KERNEL);
+	if (!pinfo->gpios)
+		return -ENOMEM;
+	memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
+
+	pinfo->alow_flags = kzalloc(ngpios * sizeof(*pinfo->alow_flags),
+				    GFP_KERNEL);
+	if (!pinfo->alow_flags) {
+		ret = -ENOMEM;
+		goto err_alloc_flags;
+	}
+
+	for (; i < ngpios; i++) {
+		int gpio;
+		enum of_gpio_flags flags;
+
+		gpio = of_get_gpio_flags(np, i, &flags);
+		if (!gpio_is_valid(gpio)) {
+			dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
+			ret = gpio;
+			goto err_loop;
+		}
+
+		ret = gpio_request(gpio, dev_name(dev));
+		if (ret) {
+			dev_err(dev, "can't request gpio #%d: %d\n", i, ret);
+			goto err_loop;
+		}
+
+		pinfo->gpios[i] = gpio;
+		pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
+
+		ret = gpio_direction_output(pinfo->gpios[i],
+					    pinfo->alow_flags[i]);
+		if (ret) {
+			dev_err(dev, "can't set output direction for gpio "
+				"#%d: %d\n", i, ret);
+			goto err_loop;
+		}
+	}
+
+	pdata->max_chipselect = ngpios;
+	pdata->cs_control = fsl_spi_cs_control;
+
+	return 0;
+
+err_loop:
+	while (i >= 0) {
+		if (gpio_is_valid(pinfo->gpios[i]))
+			gpio_free(pinfo->gpios[i]);
+		i--;
+	}
+
+	kfree(pinfo->alow_flags);
+	pinfo->alow_flags = NULL;
+err_alloc_flags:
+	kfree(pinfo->gpios);
+	pinfo->gpios = NULL;
+	return ret;
+}
+
+static int of_fsl_spi_free_chipselects(struct device *dev)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
+	int i;
+
+	if (!pinfo->gpios)
+		return 0;
+
+	for (i = 0; i < pdata->max_chipselect; i++) {
+		if (gpio_is_valid(pinfo->gpios[i]))
+			gpio_free(pinfo->gpios[i]);
+	}
+
+	kfree(pinfo->gpios);
+	kfree(pinfo->alow_flags);
+	return 0;
+}
+
+static int __devinit of_fsl_spi_probe(struct platform_device *ofdev,
+					const struct of_device_id *ofid)
+{
+	struct device *dev = &ofdev->dev;
+	struct device_node *np = ofdev->dev.of_node;
+	struct spi_master *master;
+	struct resource mem;
+	struct resource irq;
+	int ret = -ENOMEM;
+
+	ret = of_mpc8xxx_spi_probe(ofdev, ofid);
+	if (ret)
+		return ret;
+
+	ret = of_fsl_spi_get_chipselects(dev);
+	if (ret)
+		goto err;
+
+	ret = of_address_to_resource(np, 0, &mem);
+	if (ret)
+		goto err;
+
+	ret = of_irq_to_resource(np, 0, &irq);
+	if (!ret) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	master = fsl_spi_probe(dev, &mem, irq.start);
+	if (IS_ERR(master)) {
+		ret = PTR_ERR(master);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	of_fsl_spi_free_chipselects(dev);
+	return ret;
+}
+
+static int __devexit of_fsl_spi_remove(struct platform_device *ofdev)
+{
+	int ret;
+
+	ret = mpc8xxx_spi_remove(&ofdev->dev);
+	if (ret)
+		return ret;
+	of_fsl_spi_free_chipselects(&ofdev->dev);
+	return 0;
+}
+
+static const struct of_device_id of_fsl_spi_match[] = {
+	{ .compatible = "fsl,spi" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, of_fsl_spi_match);
+
+static struct of_platform_driver of_fsl_spi_driver = {
+	.driver = {
+		.name = "fsl_spi",
+		.owner = THIS_MODULE,
+		.of_match_table = of_fsl_spi_match,
+	},
+	.probe		= of_fsl_spi_probe,
+	.remove		= __devexit_p(of_fsl_spi_remove),
+};
+
+#ifdef CONFIG_MPC832x_RDB
+/*
+ * XXX XXX XXX
+ * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
+ * only. The driver should go away soon, since newer MPC8323E-RDB's device
+ * tree can work with OpenFirmware driver. But for now we support old trees
+ * as well.
+ */
+static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int irq;
+	struct spi_master *master;
+
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -EINVAL;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0)
+		return -EINVAL;
+
+	master = fsl_spi_probe(&pdev->dev, mem, irq);
+	if (IS_ERR(master))
+		return PTR_ERR(master);
+	return 0;
+}
+
+static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev)
+{
+	return mpc8xxx_spi_remove(&pdev->dev);
+}
+
+MODULE_ALIAS("platform:mpc8xxx_spi");
+static struct platform_driver mpc8xxx_spi_driver = {
+	.probe = plat_mpc8xxx_spi_probe,
+	.remove = __devexit_p(plat_mpc8xxx_spi_remove),
+	.driver = {
+		.name = "mpc8xxx_spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static bool legacy_driver_failed;
+
+static void __init legacy_driver_register(void)
+{
+	legacy_driver_failed = platform_driver_register(&mpc8xxx_spi_driver);
+}
+
+static void __exit legacy_driver_unregister(void)
+{
+	if (legacy_driver_failed)
+		return;
+	platform_driver_unregister(&mpc8xxx_spi_driver);
+}
+#else
+static void __init legacy_driver_register(void) {}
+static void __exit legacy_driver_unregister(void) {}
+#endif /* CONFIG_MPC832x_RDB */
+
+static int __init fsl_spi_init(void)
+{
+	legacy_driver_register();
+	return of_register_platform_driver(&of_fsl_spi_driver);
+}
+module_init(fsl_spi_init);
+
+static void __exit fsl_spi_exit(void)
+{
+	of_unregister_platform_driver(&of_fsl_spi_driver);
+	legacy_driver_unregister();
+}
+module_exit(fsl_spi_exit);
+
+MODULE_AUTHOR("Kumar Gala");
+MODULE_DESCRIPTION("Simple Freescale SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c
index e24a634..63e51b0 100644
--- a/drivers/spi/spi_gpio.c
+++ b/drivers/spi/spi_gpio.c
@@ -350,7 +350,7 @@
 	spi_gpio->bitbang.master = spi_master_get(master);
 	spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
 
-	if ((master_flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_RX)) == 0) {
+	if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
 		spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
 		spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
 		spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 7972e90..55a38e2 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -56,7 +56,28 @@
 	unsigned int speed_hz;
 	unsigned int bpw;
 	unsigned int mode;
-	int cs;
+	u8 cs;
+};
+
+enum spi_imx_devtype {
+	SPI_IMX_VER_IMX1,
+	SPI_IMX_VER_0_0,
+	SPI_IMX_VER_0_4,
+	SPI_IMX_VER_0_5,
+	SPI_IMX_VER_0_7,
+	SPI_IMX_VER_2_3,
+	SPI_IMX_VER_AUTODETECT,
+};
+
+struct spi_imx_data;
+
+struct spi_imx_devtype_data {
+	void (*intctrl)(struct spi_imx_data *, int);
+	int (*config)(struct spi_imx_data *, struct spi_imx_config *);
+	void (*trigger)(struct spi_imx_data *);
+	int (*rx_available)(struct spi_imx_data *);
+	void (*reset)(struct spi_imx_data *);
+	unsigned int fifosize;
 };
 
 struct spi_imx_data {
@@ -76,11 +97,7 @@
 	const void *tx_buf;
 	unsigned int txfifo; /* number of words pushed in tx FIFO */
 
-	/* SoC specific functions */
-	void (*intctrl)(struct spi_imx_data *, int);
-	int (*config)(struct spi_imx_data *, struct spi_imx_config *);
-	void (*trigger)(struct spi_imx_data *);
-	int (*rx_available)(struct spi_imx_data *);
+	struct spi_imx_devtype_data devtype_data;
 };
 
 #define MXC_SPI_BUF_RX(type)						\
@@ -140,7 +157,7 @@
 	return max;
 }
 
-/* MX1, MX31, MX35 */
+/* MX1, MX31, MX35, MX51 CSPI */
 static unsigned int spi_imx_clkdiv_2(unsigned int fin,
 		unsigned int fspi)
 {
@@ -155,6 +172,128 @@
 	return 7;
 }
 
+#define SPI_IMX2_3_CTRL		0x08
+#define SPI_IMX2_3_CTRL_ENABLE		(1 <<  0)
+#define SPI_IMX2_3_CTRL_XCH		(1 <<  2)
+#define SPI_IMX2_3_CTRL_MODE(cs)	(1 << ((cs) +  4))
+#define SPI_IMX2_3_CTRL_POSTDIV_OFFSET	8
+#define SPI_IMX2_3_CTRL_PREDIV_OFFSET	12
+#define SPI_IMX2_3_CTRL_CS(cs)		((cs) << 18)
+#define SPI_IMX2_3_CTRL_BL_OFFSET	20
+
+#define SPI_IMX2_3_CONFIG	0x0c
+#define SPI_IMX2_3_CONFIG_SCLKPHA(cs)	(1 << ((cs) +  0))
+#define SPI_IMX2_3_CONFIG_SCLKPOL(cs)	(1 << ((cs) +  4))
+#define SPI_IMX2_3_CONFIG_SBBCTRL(cs)	(1 << ((cs) +  8))
+#define SPI_IMX2_3_CONFIG_SSBPOL(cs)	(1 << ((cs) + 12))
+
+#define SPI_IMX2_3_INT		0x10
+#define SPI_IMX2_3_INT_TEEN		(1 <<  0)
+#define SPI_IMX2_3_INT_RREN		(1 <<  3)
+
+#define SPI_IMX2_3_STAT		0x18
+#define SPI_IMX2_3_STAT_RR		(1 <<  3)
+
+/* MX51 eCSPI */
+static unsigned int spi_imx2_3_clkdiv(unsigned int fin, unsigned int fspi)
+{
+	/*
+	 * there are two 4-bit dividers, the pre-divider divides by
+	 * $pre, the post-divider by 2^$post
+	 */
+	unsigned int pre, post;
+
+	if (unlikely(fspi > fin))
+		return 0;
+
+	post = fls(fin) - fls(fspi);
+	if (fin > fspi << post)
+		post++;
+
+	/* now we have: (fin <= fspi << post) with post being minimal */
+
+	post = max(4U, post) - 4;
+	if (unlikely(post > 0xf)) {
+		pr_err("%s: cannot set clock freq: %u (base freq: %u)\n",
+				__func__, fspi, fin);
+		return 0xff;
+	}
+
+	pre = DIV_ROUND_UP(fin, fspi << post) - 1;
+
+	pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
+			__func__, fin, fspi, post, pre);
+	return (pre << SPI_IMX2_3_CTRL_PREDIV_OFFSET) |
+		(post << SPI_IMX2_3_CTRL_POSTDIV_OFFSET);
+}
+
+static void __maybe_unused spi_imx2_3_intctrl(struct spi_imx_data *spi_imx, int enable)
+{
+	unsigned val = 0;
+
+	if (enable & MXC_INT_TE)
+		val |= SPI_IMX2_3_INT_TEEN;
+
+	if (enable & MXC_INT_RR)
+		val |= SPI_IMX2_3_INT_RREN;
+
+	writel(val, spi_imx->base + SPI_IMX2_3_INT);
+}
+
+static void __maybe_unused spi_imx2_3_trigger(struct spi_imx_data *spi_imx)
+{
+	u32 reg;
+
+	reg = readl(spi_imx->base + SPI_IMX2_3_CTRL);
+	reg |= SPI_IMX2_3_CTRL_XCH;
+	writel(reg, spi_imx->base + SPI_IMX2_3_CTRL);
+}
+
+static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx,
+		struct spi_imx_config *config)
+{
+	u32 ctrl = SPI_IMX2_3_CTRL_ENABLE, cfg = 0;
+
+	/* set master mode */
+	ctrl |= SPI_IMX2_3_CTRL_MODE(config->cs);
+
+	/* set clock speed */
+	ctrl |= spi_imx2_3_clkdiv(spi_imx->spi_clk, config->speed_hz);
+
+	/* set chip select to use */
+	ctrl |= SPI_IMX2_3_CTRL_CS(config->cs);
+
+	ctrl |= (config->bpw - 1) << SPI_IMX2_3_CTRL_BL_OFFSET;
+
+	cfg |= SPI_IMX2_3_CONFIG_SBBCTRL(config->cs);
+
+	if (config->mode & SPI_CPHA)
+		cfg |= SPI_IMX2_3_CONFIG_SCLKPHA(config->cs);
+
+	if (config->mode & SPI_CPOL)
+		cfg |= SPI_IMX2_3_CONFIG_SCLKPOL(config->cs);
+
+	if (config->mode & SPI_CS_HIGH)
+		cfg |= SPI_IMX2_3_CONFIG_SSBPOL(config->cs);
+
+	writel(ctrl, spi_imx->base + SPI_IMX2_3_CTRL);
+	writel(cfg, spi_imx->base + SPI_IMX2_3_CONFIG);
+
+	return 0;
+}
+
+static int __maybe_unused spi_imx2_3_rx_available(struct spi_imx_data *spi_imx)
+{
+	return readl(spi_imx->base + SPI_IMX2_3_STAT) & SPI_IMX2_3_STAT_RR;
+}
+
+static void __maybe_unused spi_imx2_3_reset(struct spi_imx_data *spi_imx)
+{
+	/* drain receive buffer */
+	while (spi_imx2_3_rx_available(spi_imx))
+		readl(spi_imx->base + MXC_CSPIRXDATA);
+}
+
 #define MX31_INTREG_TEEN	(1 << 0)
 #define MX31_INTREG_RREN	(1 << 3)
 
@@ -178,7 +317,7 @@
  * the i.MX35 has a slightly different register layout for bits
  * we do not use here.
  */
-static void mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void __maybe_unused mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
 	unsigned int val = 0;
 
@@ -190,7 +329,7 @@
 	writel(val, spi_imx->base + MXC_CSPIINT);
 }
 
-static void mx31_trigger(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx)
 {
 	unsigned int reg;
 
@@ -199,20 +338,16 @@
 	writel(reg, spi_imx->base + MXC_CSPICTRL);
 }
 
-static int mx31_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused spi_imx0_4_config(struct spi_imx_data *spi_imx,
 		struct spi_imx_config *config)
 {
 	unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
+	int cs = spi_imx->chipselect[config->cs];
 
 	reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
 		MX31_CSPICTRL_DR_SHIFT;
 
-	if (cpu_is_mx31())
-		reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
-	else if (cpu_is_mx25() || cpu_is_mx35()) {
-		reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT;
-		reg |= MX31_CSPICTRL_SSCTL;
-	}
+	reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
 
 	if (config->mode & SPI_CPHA)
 		reg |= MX31_CSPICTRL_PHA;
@@ -220,23 +355,52 @@
 		reg |= MX31_CSPICTRL_POL;
 	if (config->mode & SPI_CS_HIGH)
 		reg |= MX31_CSPICTRL_SSPOL;
-	if (config->cs < 0) {
-		if (cpu_is_mx31())
-			reg |= (config->cs + 32) << MX31_CSPICTRL_CS_SHIFT;
-		else if (cpu_is_mx25() || cpu_is_mx35())
-			reg |= (config->cs + 32) << MX35_CSPICTRL_CS_SHIFT;
-	}
+	if (cs < 0)
+		reg |= (cs + 32) << MX31_CSPICTRL_CS_SHIFT;
 
 	writel(reg, spi_imx->base + MXC_CSPICTRL);
 
 	return 0;
 }
 
-static int mx31_rx_available(struct spi_imx_data *spi_imx)
+static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx,
+		struct spi_imx_config *config)
+{
+	unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
+	int cs = spi_imx->chipselect[config->cs];
+
+	reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
+		MX31_CSPICTRL_DR_SHIFT;
+
+	reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT;
+	reg |= MX31_CSPICTRL_SSCTL;
+
+	if (config->mode & SPI_CPHA)
+		reg |= MX31_CSPICTRL_PHA;
+	if (config->mode & SPI_CPOL)
+		reg |= MX31_CSPICTRL_POL;
+	if (config->mode & SPI_CS_HIGH)
+		reg |= MX31_CSPICTRL_SSPOL;
+	if (cs < 0)
+		reg |= (cs + 32) << MX35_CSPICTRL_CS_SHIFT;
+
+	writel(reg, spi_imx->base + MXC_CSPICTRL);
+
+	return 0;
+}
+
+static int __maybe_unused mx31_rx_available(struct spi_imx_data *spi_imx)
 {
 	return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
 }
 
+static void __maybe_unused spi_imx0_4_reset(struct spi_imx_data *spi_imx)
+{
+	/* drain receive buffer */
+	while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR)
+		readl(spi_imx->base + MXC_CSPIRXDATA);
+}
+
 #define MX27_INTREG_RR		(1 << 4)
 #define MX27_INTREG_TEEN	(1 << 9)
 #define MX27_INTREG_RREN	(1 << 13)
@@ -250,7 +414,7 @@
 #define MX27_CSPICTRL_DR_SHIFT	14
 #define MX27_CSPICTRL_CS_SHIFT	19
 
-static void mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void __maybe_unused mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
 	unsigned int val = 0;
 
@@ -262,7 +426,7 @@
 	writel(val, spi_imx->base + MXC_CSPIINT);
 }
 
-static void mx27_trigger(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx27_trigger(struct spi_imx_data *spi_imx)
 {
 	unsigned int reg;
 
@@ -271,10 +435,11 @@
 	writel(reg, spi_imx->base + MXC_CSPICTRL);
 }
 
-static int mx27_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused mx27_config(struct spi_imx_data *spi_imx,
 		struct spi_imx_config *config)
 {
 	unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER;
+	int cs = spi_imx->chipselect[config->cs];
 
 	reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz) <<
 		MX27_CSPICTRL_DR_SHIFT;
@@ -286,19 +451,24 @@
 		reg |= MX27_CSPICTRL_POL;
 	if (config->mode & SPI_CS_HIGH)
 		reg |= MX27_CSPICTRL_SSPOL;
-	if (config->cs < 0)
-		reg |= (config->cs + 32) << MX27_CSPICTRL_CS_SHIFT;
+	if (cs < 0)
+		reg |= (cs + 32) << MX27_CSPICTRL_CS_SHIFT;
 
 	writel(reg, spi_imx->base + MXC_CSPICTRL);
 
 	return 0;
 }
 
-static int mx27_rx_available(struct spi_imx_data *spi_imx)
+static int __maybe_unused mx27_rx_available(struct spi_imx_data *spi_imx)
 {
 	return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR;
 }
 
+static void __maybe_unused spi_imx0_0_reset(struct spi_imx_data *spi_imx)
+{
+	writel(1, spi_imx->base + MXC_RESET);
+}
+
 #define MX1_INTREG_RR		(1 << 3)
 #define MX1_INTREG_TEEN		(1 << 8)
 #define MX1_INTREG_RREN		(1 << 11)
@@ -310,7 +480,7 @@
 #define MX1_CSPICTRL_MASTER	(1 << 10)
 #define MX1_CSPICTRL_DR_SHIFT	13
 
-static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
+static void __maybe_unused mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
 	unsigned int val = 0;
 
@@ -322,7 +492,7 @@
 	writel(val, spi_imx->base + MXC_CSPIINT);
 }
 
-static void mx1_trigger(struct spi_imx_data *spi_imx)
+static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx)
 {
 	unsigned int reg;
 
@@ -331,7 +501,7 @@
 	writel(reg, spi_imx->base + MXC_CSPICTRL);
 }
 
-static int mx1_config(struct spi_imx_data *spi_imx,
+static int __maybe_unused mx1_config(struct spi_imx_data *spi_imx,
 		struct spi_imx_config *config)
 {
 	unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER;
@@ -350,11 +520,73 @@
 	return 0;
 }
 
-static int mx1_rx_available(struct spi_imx_data *spi_imx)
+static int __maybe_unused mx1_rx_available(struct spi_imx_data *spi_imx)
 {
 	return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR;
 }
 
+static void __maybe_unused mx1_reset(struct spi_imx_data *spi_imx)
+{
+	writel(1, spi_imx->base + MXC_RESET);
+}
+
+/*
+ * These version numbers are taken from the Freescale driver.  Unfortunately it
+ * doesn't support i.MX1, so this entry doesn't match the scheme. :-(
+ */
+static struct spi_imx_devtype_data spi_imx_devtype_data[] __devinitdata = {
+#ifdef CONFIG_SPI_IMX_VER_IMX1
+	[SPI_IMX_VER_IMX1] = {
+		.intctrl = mx1_intctrl,
+		.config = mx1_config,
+		.trigger = mx1_trigger,
+		.rx_available = mx1_rx_available,
+		.reset = mx1_reset,
+		.fifosize = 8,
+	},
+#endif
+#ifdef CONFIG_SPI_IMX_VER_0_0
+	[SPI_IMX_VER_0_0] = {
+		.intctrl = mx27_intctrl,
+		.config = mx27_config,
+		.trigger = mx27_trigger,
+		.rx_available = mx27_rx_available,
+		.reset = spi_imx0_0_reset,
+		.fifosize = 8,
+	},
+#endif
+#ifdef CONFIG_SPI_IMX_VER_0_4
+	[SPI_IMX_VER_0_4] = {
+		.intctrl = mx31_intctrl,
+		.config = spi_imx0_4_config,
+		.trigger = mx31_trigger,
+		.rx_available = mx31_rx_available,
+		.reset = spi_imx0_4_reset,
+		.fifosize = 8,
+	},
+#endif
+#ifdef CONFIG_SPI_IMX_VER_0_7
+	[SPI_IMX_VER_0_7] = {
+		.intctrl = mx31_intctrl,
+		.config = spi_imx0_7_config,
+		.trigger = mx31_trigger,
+		.rx_available = mx31_rx_available,
+		.reset = spi_imx0_4_reset,
+		.fifosize = 8,
+	},
+#endif
+#ifdef CONFIG_SPI_IMX_VER_2_3
+	[SPI_IMX_VER_2_3] = {
+		.intctrl = spi_imx2_3_intctrl,
+		.config = spi_imx2_3_config,
+		.trigger = spi_imx2_3_trigger,
+		.rx_available = spi_imx2_3_rx_available,
+		.reset = spi_imx2_3_reset,
+		.fifosize = 64,
+	},
+#endif
+};
+
 static void spi_imx_chipselect(struct spi_device *spi, int is_active)
 {
 	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
@@ -370,21 +602,21 @@
 
 static void spi_imx_push(struct spi_imx_data *spi_imx)
 {
-	while (spi_imx->txfifo < 8) {
+	while (spi_imx->txfifo < spi_imx->devtype_data.fifosize) {
 		if (!spi_imx->count)
 			break;
 		spi_imx->tx(spi_imx);
 		spi_imx->txfifo++;
 	}
 
-	spi_imx->trigger(spi_imx);
+	spi_imx->devtype_data.trigger(spi_imx);
 }
 
 static irqreturn_t spi_imx_isr(int irq, void *dev_id)
 {
 	struct spi_imx_data *spi_imx = dev_id;
 
-	while (spi_imx->rx_available(spi_imx)) {
+	while (spi_imx->devtype_data.rx_available(spi_imx)) {
 		spi_imx->rx(spi_imx);
 		spi_imx->txfifo--;
 	}
@@ -398,11 +630,12 @@
 		/* No data left to push, but still waiting for rx data,
 		 * enable receive data available interrupt.
 		 */
-		spi_imx->intctrl(spi_imx, MXC_INT_RR);
+		spi_imx->devtype_data.intctrl(
+				spi_imx, MXC_INT_RR);
 		return IRQ_HANDLED;
 	}
 
-	spi_imx->intctrl(spi_imx, 0);
+	spi_imx->devtype_data.intctrl(spi_imx, 0);
 	complete(&spi_imx->xfer_done);
 
 	return IRQ_HANDLED;
@@ -417,7 +650,7 @@
 	config.bpw = t ? t->bits_per_word : spi->bits_per_word;
 	config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
 	config.mode = spi->mode;
-	config.cs = spi_imx->chipselect[spi->chip_select];
+	config.cs = spi->chip_select;
 
 	if (!config.speed_hz)
 		config.speed_hz = spi->max_speed_hz;
@@ -439,7 +672,7 @@
 	} else
 		BUG();
 
-	spi_imx->config(spi_imx, &config);
+	spi_imx->devtype_data.config(spi_imx, &config);
 
 	return 0;
 }
@@ -458,7 +691,7 @@
 
 	spi_imx_push(spi_imx);
 
-	spi_imx->intctrl(spi_imx, MXC_INT_TE);
+	spi_imx->devtype_data.intctrl(spi_imx, MXC_INT_TE);
 
 	wait_for_completion(&spi_imx->xfer_done);
 
@@ -485,6 +718,39 @@
 {
 }
 
+static struct platform_device_id spi_imx_devtype[] = {
+	{
+		.name = DRIVER_NAME,
+		.driver_data = SPI_IMX_VER_AUTODETECT,
+	}, {
+		.name = "imx1-cspi",
+		.driver_data = SPI_IMX_VER_IMX1,
+	}, {
+		.name = "imx21-cspi",
+		.driver_data = SPI_IMX_VER_0_0,
+	}, {
+		.name = "imx25-cspi",
+		.driver_data = SPI_IMX_VER_0_7,
+	}, {
+		.name = "imx27-cspi",
+		.driver_data = SPI_IMX_VER_0_0,
+	}, {
+		.name = "imx31-cspi",
+		.driver_data = SPI_IMX_VER_0_4,
+	}, {
+		.name = "imx35-cspi",
+		.driver_data = SPI_IMX_VER_0_7,
+	}, {
+		.name = "imx51-cspi",
+		.driver_data = SPI_IMX_VER_0_7,
+	}, {
+		.name = "imx51-ecspi",
+		.driver_data = SPI_IMX_VER_2_3,
+	}, {
+		/* sentinel */
+	}
+};
+
 static int __devinit spi_imx_probe(struct platform_device *pdev)
 {
 	struct spi_imx_master *mxc_platform_info;
@@ -536,6 +802,31 @@
 
 	init_completion(&spi_imx->xfer_done);
 
+	if (pdev->id_entry->driver_data == SPI_IMX_VER_AUTODETECT) {
+		if (cpu_is_mx25() || cpu_is_mx35())
+			spi_imx->devtype_data =
+				spi_imx_devtype_data[SPI_IMX_VER_0_7];
+		else if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35())
+			spi_imx->devtype_data =
+				spi_imx_devtype_data[SPI_IMX_VER_0_4];
+		else if (cpu_is_mx27() || cpu_is_mx21())
+			spi_imx->devtype_data =
+				spi_imx_devtype_data[SPI_IMX_VER_0_0];
+		else if (cpu_is_mx1())
+			spi_imx->devtype_data =
+				spi_imx_devtype_data[SPI_IMX_VER_IMX1];
+		else
+			BUG();
+	} else
+		spi_imx->devtype_data =
+			spi_imx_devtype_data[pdev->id_entry->driver_data];
+
+	if (!spi_imx->devtype_data.intctrl) {
+		dev_err(&pdev->dev, "no support for this device compiled in\n");
+		ret = -ENODEV;
+		goto out_gpio_free;
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "can't get platform resource\n");
@@ -567,24 +858,6 @@
 		goto out_iounmap;
 	}
 
-	if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) {
-		spi_imx->intctrl = mx31_intctrl;
-		spi_imx->config = mx31_config;
-		spi_imx->trigger = mx31_trigger;
-		spi_imx->rx_available = mx31_rx_available;
-	} else  if (cpu_is_mx27() || cpu_is_mx21()) {
-		spi_imx->intctrl = mx27_intctrl;
-		spi_imx->config = mx27_config;
-		spi_imx->trigger = mx27_trigger;
-		spi_imx->rx_available = mx27_rx_available;
-	} else if (cpu_is_mx1()) {
-		spi_imx->intctrl = mx1_intctrl;
-		spi_imx->config = mx1_config;
-		spi_imx->trigger = mx1_trigger;
-		spi_imx->rx_available = mx1_rx_available;
-	} else
-		BUG();
-
 	spi_imx->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(spi_imx->clk)) {
 		dev_err(&pdev->dev, "unable to get clock\n");
@@ -595,15 +868,9 @@
 	clk_enable(spi_imx->clk);
 	spi_imx->spi_clk = clk_get_rate(spi_imx->clk);
 
-	if (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
-		writel(1, spi_imx->base + MXC_RESET);
+	spi_imx->devtype_data.reset(spi_imx);
 
-	/* drain receive buffer */
-	if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35())
-		while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR)
-			readl(spi_imx->base + MXC_CSPIRXDATA);
-
-	spi_imx->intctrl(spi_imx, 0);
+	spi_imx->devtype_data.intctrl(spi_imx, 0);
 
 	ret = spi_bitbang_start(&spi_imx->bitbang);
 	if (ret) {
@@ -668,6 +935,7 @@
 		   .name = DRIVER_NAME,
 		   .owner = THIS_MODULE,
 		   },
+	.id_table = spi_imx_devtype,
 	.probe = spi_imx_probe,
 	.remove = __devexit_p(spi_imx_remove),
 };
diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c
deleted file mode 100644
index d31b57f..0000000
--- a/drivers/spi/spi_mpc8xxx.c
+++ /dev/null
@@ -1,1419 +0,0 @@
-/*
- * MPC8xxx SPI controller driver.
- *
- * Maintainer: Kumar Gala
- *
- * Copyright (C) 2006 Polycom, Inc.
- *
- * CPM SPI and QE buffer descriptors mode support:
- * Copyright (c) 2009  MontaVista Software, Inc.
- * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/bug.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/completion.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/platform_device.h>
-#include <linux/fsl_devices.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-#include <linux/slab.h>
-
-#include <sysdev/fsl_soc.h>
-#include <asm/cpm.h>
-#include <asm/qe.h>
-#include <asm/irq.h>
-
-/* CPM1 and CPM2 are mutually exclusive. */
-#ifdef CONFIG_CPM1
-#include <asm/cpm1.h>
-#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
-#else
-#include <asm/cpm2.h>
-#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
-#endif
-
-/* SPI Controller registers */
-struct mpc8xxx_spi_reg {
-	u8 res1[0x20];
-	__be32 mode;
-	__be32 event;
-	__be32 mask;
-	__be32 command;
-	__be32 transmit;
-	__be32 receive;
-};
-
-/* SPI Controller mode register definitions */
-#define	SPMODE_LOOP		(1 << 30)
-#define	SPMODE_CI_INACTIVEHIGH	(1 << 29)
-#define	SPMODE_CP_BEGIN_EDGECLK	(1 << 28)
-#define	SPMODE_DIV16		(1 << 27)
-#define	SPMODE_REV		(1 << 26)
-#define	SPMODE_MS		(1 << 25)
-#define	SPMODE_ENABLE		(1 << 24)
-#define	SPMODE_LEN(x)		((x) << 20)
-#define	SPMODE_PM(x)		((x) << 16)
-#define	SPMODE_OP		(1 << 14)
-#define	SPMODE_CG(x)		((x) << 7)
-
-/*
- * Default for SPI Mode:
- * 	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
- */
-#define	SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
-			 SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
-
-/* SPIE register values */
-#define	SPIE_NE		0x00000200	/* Not empty */
-#define	SPIE_NF		0x00000100	/* Not full */
-
-/* SPIM register values */
-#define	SPIM_NE		0x00000200	/* Not empty */
-#define	SPIM_NF		0x00000100	/* Not full */
-
-#define	SPIE_TXB	0x00000200	/* Last char is written to tx fifo */
-#define	SPIE_RXB	0x00000100	/* Last char is written to rx buf */
-
-/* SPCOM register values */
-#define	SPCOM_STR	(1 << 23)	/* Start transmit */
-
-#define	SPI_PRAM_SIZE	0x100
-#define	SPI_MRBLR	((unsigned int)PAGE_SIZE)
-
-/* SPI Controller driver's private data. */
-struct mpc8xxx_spi {
-	struct device *dev;
-	struct mpc8xxx_spi_reg __iomem *base;
-
-	/* rx & tx bufs from the spi_transfer */
-	const void *tx;
-	void *rx;
-
-	int subblock;
-	struct spi_pram __iomem *pram;
-	struct cpm_buf_desc __iomem *tx_bd;
-	struct cpm_buf_desc __iomem *rx_bd;
-
-	struct spi_transfer *xfer_in_progress;
-
-	/* dma addresses for CPM transfers */
-	dma_addr_t tx_dma;
-	dma_addr_t rx_dma;
-	bool map_tx_dma;
-	bool map_rx_dma;
-
-	dma_addr_t dma_dummy_tx;
-	dma_addr_t dma_dummy_rx;
-
-	/* functions to deal with different sized buffers */
-	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
-	u32(*get_tx) (struct mpc8xxx_spi *);
-
-	unsigned int count;
-	unsigned int irq;
-
-	unsigned nsecs;		/* (clock cycle time)/2 */
-
-	u32 spibrg;		/* SPIBRG input clock */
-	u32 rx_shift;		/* RX data reg shift when in qe mode */
-	u32 tx_shift;		/* TX data reg shift when in qe mode */
-
-	unsigned int flags;
-
-	struct workqueue_struct *workqueue;
-	struct work_struct work;
-
-	struct list_head queue;
-	spinlock_t lock;
-
-	struct completion done;
-};
-
-static void *mpc8xxx_dummy_rx;
-static DEFINE_MUTEX(mpc8xxx_dummy_rx_lock);
-static int mpc8xxx_dummy_rx_refcnt;
-
-struct spi_mpc8xxx_cs {
-	/* functions to deal with different sized buffers */
-	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
-	u32 (*get_tx) (struct mpc8xxx_spi *);
-	u32 rx_shift;		/* RX data reg shift when in qe mode */
-	u32 tx_shift;		/* TX data reg shift when in qe mode */
-	u32 hw_mode;		/* Holds HW mode register settings */
-};
-
-static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
-{
-	out_be32(reg, val);
-}
-
-static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
-{
-	return in_be32(reg);
-}
-
-#define MPC83XX_SPI_RX_BUF(type) 					  \
-static									  \
-void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
-{									  \
-	type *rx = mpc8xxx_spi->rx;					  \
-	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
-	mpc8xxx_spi->rx = rx;						  \
-}
-
-#define MPC83XX_SPI_TX_BUF(type)				\
-static								\
-u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
-{								\
-	u32 data;						\
-	const type *tx = mpc8xxx_spi->tx;			\
-	if (!tx)						\
-		return 0;					\
-	data = *tx++ << mpc8xxx_spi->tx_shift;			\
-	mpc8xxx_spi->tx = tx;					\
-	return data;						\
-}
-
-MPC83XX_SPI_RX_BUF(u8)
-MPC83XX_SPI_RX_BUF(u16)
-MPC83XX_SPI_RX_BUF(u32)
-MPC83XX_SPI_TX_BUF(u8)
-MPC83XX_SPI_TX_BUF(u16)
-MPC83XX_SPI_TX_BUF(u32)
-
-static void mpc8xxx_spi_change_mode(struct spi_device *spi)
-{
-	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
-	struct spi_mpc8xxx_cs *cs = spi->controller_state;
-	__be32 __iomem *mode = &mspi->base->mode;
-	unsigned long flags;
-
-	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
-		return;
-
-	/* Turn off IRQs locally to minimize time that SPI is disabled. */
-	local_irq_save(flags);
-
-	/* Turn off SPI unit prior changing mode */
-	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
-
-	/* When in CPM mode, we need to reinit tx and rx. */
-	if (mspi->flags & SPI_CPM_MODE) {
-		if (mspi->flags & SPI_QE) {
-			qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
-				     QE_CR_PROTOCOL_UNSPECIFIED, 0);
-		} else {
-			cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
-			if (mspi->flags & SPI_CPM1) {
-				out_be16(&mspi->pram->rbptr,
-					 in_be16(&mspi->pram->rbase));
-				out_be16(&mspi->pram->tbptr,
-					 in_be16(&mspi->pram->tbase));
-			}
-		}
-	}
-	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
-	local_irq_restore(flags);
-}
-
-static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
-	bool pol = spi->mode & SPI_CS_HIGH;
-	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
-
-	if (value == BITBANG_CS_INACTIVE) {
-		if (pdata->cs_control)
-			pdata->cs_control(spi, !pol);
-	}
-
-	if (value == BITBANG_CS_ACTIVE) {
-		mpc8xxx_spi->rx_shift = cs->rx_shift;
-		mpc8xxx_spi->tx_shift = cs->tx_shift;
-		mpc8xxx_spi->get_rx = cs->get_rx;
-		mpc8xxx_spi->get_tx = cs->get_tx;
-
-		mpc8xxx_spi_change_mode(spi);
-
-		if (pdata->cs_control)
-			pdata->cs_control(spi, pol);
-	}
-}
-
-static int
-mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
-			   struct spi_device *spi,
-			   struct mpc8xxx_spi *mpc8xxx_spi,
-			   int bits_per_word)
-{
-	cs->rx_shift = 0;
-	cs->tx_shift = 0;
-	if (bits_per_word <= 8) {
-		cs->get_rx = mpc8xxx_spi_rx_buf_u8;
-		cs->get_tx = mpc8xxx_spi_tx_buf_u8;
-		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
-			cs->rx_shift = 16;
-			cs->tx_shift = 24;
-		}
-	} else if (bits_per_word <= 16) {
-		cs->get_rx = mpc8xxx_spi_rx_buf_u16;
-		cs->get_tx = mpc8xxx_spi_tx_buf_u16;
-		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
-			cs->rx_shift = 16;
-			cs->tx_shift = 16;
-		}
-	} else if (bits_per_word <= 32) {
-		cs->get_rx = mpc8xxx_spi_rx_buf_u32;
-		cs->get_tx = mpc8xxx_spi_tx_buf_u32;
-	} else
-		return -EINVAL;
-
-	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
-	    spi->mode & SPI_LSB_FIRST) {
-		cs->tx_shift = 0;
-		if (bits_per_word <= 8)
-			cs->rx_shift = 8;
-		else
-			cs->rx_shift = 0;
-	}
-	mpc8xxx_spi->rx_shift = cs->rx_shift;
-	mpc8xxx_spi->tx_shift = cs->tx_shift;
-	mpc8xxx_spi->get_rx = cs->get_rx;
-	mpc8xxx_spi->get_tx = cs->get_tx;
-
-	return bits_per_word;
-}
-
-static int
-mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
-			  struct spi_device *spi,
-			  int bits_per_word)
-{
-	/* QE uses Little Endian for words > 8
-	 * so transform all words > 8 into 8 bits
-	 * Unfortnatly that doesn't work for LSB so
-	 * reject these for now */
-	/* Note: 32 bits word, LSB works iff
-	 * tfcr/rfcr is set to CPMFCR_GBL */
-	if (spi->mode & SPI_LSB_FIRST &&
-	    bits_per_word > 8)
-		return -EINVAL;
-	if (bits_per_word > 8)
-		return 8; /* pretend its 8 bits */
-	return bits_per_word;
-}
-
-static
-int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	int bits_per_word;
-	u8 pm;
-	u32 hz;
-	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
-
-	mpc8xxx_spi = spi_master_get_devdata(spi->master);
-
-	if (t) {
-		bits_per_word = t->bits_per_word;
-		hz = t->speed_hz;
-	} else {
-		bits_per_word = 0;
-		hz = 0;
-	}
-
-	/* spi_transfer level calls that work per-word */
-	if (!bits_per_word)
-		bits_per_word = spi->bits_per_word;
-
-	/* Make sure its a bit width we support [4..16, 32] */
-	if ((bits_per_word < 4)
-	    || ((bits_per_word > 16) && (bits_per_word != 32)))
-		return -EINVAL;
-
-	if (!hz)
-		hz = spi->max_speed_hz;
-
-	if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
-		bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
-							   mpc8xxx_spi,
-							   bits_per_word);
-	else if (mpc8xxx_spi->flags & SPI_QE)
-		bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
-							  bits_per_word);
-
-	if (bits_per_word < 0)
-		return bits_per_word;
-
-	if (bits_per_word == 32)
-		bits_per_word = 0;
-	else
-		bits_per_word = bits_per_word - 1;
-
-	/* mask out bits we are going to set */
-	cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16
-				  | SPMODE_PM(0xF));
-
-	cs->hw_mode |= SPMODE_LEN(bits_per_word);
-
-	if ((mpc8xxx_spi->spibrg / hz) > 64) {
-		cs->hw_mode |= SPMODE_DIV16;
-		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
-
-		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
-			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
-			  hz, mpc8xxx_spi->spibrg / 1024);
-		if (pm > 16)
-			pm = 16;
-	} else
-		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
-	if (pm)
-		pm--;
-
-	cs->hw_mode |= SPMODE_PM(pm);
-
-	mpc8xxx_spi_change_mode(spi);
-	return 0;
-}
-
-static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
-{
-	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
-	struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
-	unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
-	unsigned int xfer_ofs;
-
-	xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
-
-	out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
-	out_be16(&rx_bd->cbd_datlen, 0);
-	out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
-
-	out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
-	out_be16(&tx_bd->cbd_datlen, xfer_len);
-	out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
-				 BD_SC_LAST);
-
-	/* start transfer */
-	mpc8xxx_spi_write_reg(&mspi->base->command, SPCOM_STR);
-}
-
-static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
-				struct spi_transfer *t, bool is_dma_mapped)
-{
-	struct device *dev = mspi->dev;
-
-	if (is_dma_mapped) {
-		mspi->map_tx_dma = 0;
-		mspi->map_rx_dma = 0;
-	} else {
-		mspi->map_tx_dma = 1;
-		mspi->map_rx_dma = 1;
-	}
-
-	if (!t->tx_buf) {
-		mspi->tx_dma = mspi->dma_dummy_tx;
-		mspi->map_tx_dma = 0;
-	}
-
-	if (!t->rx_buf) {
-		mspi->rx_dma = mspi->dma_dummy_rx;
-		mspi->map_rx_dma = 0;
-	}
-
-	if (mspi->map_tx_dma) {
-		void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
-
-		mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
-					      DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, mspi->tx_dma)) {
-			dev_err(dev, "unable to map tx dma\n");
-			return -ENOMEM;
-		}
-	} else if (t->tx_buf) {
-		mspi->tx_dma = t->tx_dma;
-	}
-
-	if (mspi->map_rx_dma) {
-		mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
-					      DMA_FROM_DEVICE);
-		if (dma_mapping_error(dev, mspi->rx_dma)) {
-			dev_err(dev, "unable to map rx dma\n");
-			goto err_rx_dma;
-		}
-	} else if (t->rx_buf) {
-		mspi->rx_dma = t->rx_dma;
-	}
-
-	/* enable rx ints */
-	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIE_RXB);
-
-	mspi->xfer_in_progress = t;
-	mspi->count = t->len;
-
-	/* start CPM transfers */
-	mpc8xxx_spi_cpm_bufs_start(mspi);
-
-	return 0;
-
-err_rx_dma:
-	if (mspi->map_tx_dma)
-		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
-	return -ENOMEM;
-}
-
-static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-	struct spi_transfer *t = mspi->xfer_in_progress;
-
-	if (mspi->map_tx_dma)
-		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
-	if (mspi->map_rx_dma)
-		dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
-	mspi->xfer_in_progress = NULL;
-}
-
-static int mpc8xxx_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
-				struct spi_transfer *t, unsigned int len)
-{
-	u32 word;
-
-	mspi->count = len;
-
-	/* enable rx ints */
-	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIM_NE);
-
-	/* transmit word */
-	word = mspi->get_tx(mspi);
-	mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
-
-	return 0;
-}
-
-static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
-			    bool is_dma_mapped)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	unsigned int len = t->len;
-	u8 bits_per_word;
-	int ret;
-
-	bits_per_word = spi->bits_per_word;
-	if (t->bits_per_word)
-		bits_per_word = t->bits_per_word;
-
-	if (bits_per_word > 8) {
-		/* invalid length? */
-		if (len & 1)
-			return -EINVAL;
-		len /= 2;
-	}
-	if (bits_per_word > 16) {
-		/* invalid length? */
-		if (len & 1)
-			return -EINVAL;
-		len /= 2;
-	}
-
-	mpc8xxx_spi->tx = t->tx_buf;
-	mpc8xxx_spi->rx = t->rx_buf;
-
-	INIT_COMPLETION(mpc8xxx_spi->done);
-
-	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
-		ret = mpc8xxx_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
-	else
-		ret = mpc8xxx_spi_cpu_bufs(mpc8xxx_spi, t, len);
-	if (ret)
-		return ret;
-
-	wait_for_completion(&mpc8xxx_spi->done);
-
-	/* disable rx ints */
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
-
-	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
-		mpc8xxx_spi_cpm_bufs_complete(mpc8xxx_spi);
-
-	return mpc8xxx_spi->count;
-}
-
-static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
-{
-	struct spi_device *spi = m->spi;
-	struct spi_transfer *t;
-	unsigned int cs_change;
-	const int nsecs = 50;
-	int status;
-
-	cs_change = 1;
-	status = 0;
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->bits_per_word || t->speed_hz) {
-			/* Don't allow changes if CS is active */
-			status = -EINVAL;
-
-			if (cs_change)
-				status = mpc8xxx_spi_setup_transfer(spi, t);
-			if (status < 0)
-				break;
-		}
-
-		if (cs_change) {
-			mpc8xxx_spi_chipselect(spi, BITBANG_CS_ACTIVE);
-			ndelay(nsecs);
-		}
-		cs_change = t->cs_change;
-		if (t->len)
-			status = mpc8xxx_spi_bufs(spi, t, m->is_dma_mapped);
-		if (status) {
-			status = -EMSGSIZE;
-			break;
-		}
-		m->actual_length += t->len;
-
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
-
-		if (cs_change) {
-			ndelay(nsecs);
-			mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
-			ndelay(nsecs);
-		}
-	}
-
-	m->status = status;
-	m->complete(m->context);
-
-	if (status || !cs_change) {
-		ndelay(nsecs);
-		mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
-	}
-
-	mpc8xxx_spi_setup_transfer(spi, NULL);
-}
-
-static void mpc8xxx_spi_work(struct work_struct *work)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
-						       work);
-
-	spin_lock_irq(&mpc8xxx_spi->lock);
-	while (!list_empty(&mpc8xxx_spi->queue)) {
-		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
-						   struct spi_message, queue);
-
-		list_del_init(&m->queue);
-		spin_unlock_irq(&mpc8xxx_spi->lock);
-
-		mpc8xxx_spi_do_one_msg(m);
-
-		spin_lock_irq(&mpc8xxx_spi->lock);
-	}
-	spin_unlock_irq(&mpc8xxx_spi->lock);
-}
-
-static int mpc8xxx_spi_setup(struct spi_device *spi)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	int retval;
-	u32 hw_mode;
-	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
-
-	if (!spi->max_speed_hz)
-		return -EINVAL;
-
-	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
-		if (!cs)
-			return -ENOMEM;
-		spi->controller_state = cs;
-	}
-	mpc8xxx_spi = spi_master_get_devdata(spi->master);
-
-	hw_mode = cs->hw_mode; /* Save original settings */
-	cs->hw_mode = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
-	/* mask out bits we are going to set */
-	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
-			 | SPMODE_REV | SPMODE_LOOP);
-
-	if (spi->mode & SPI_CPHA)
-		cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
-	if (spi->mode & SPI_CPOL)
-		cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
-	if (!(spi->mode & SPI_LSB_FIRST))
-		cs->hw_mode |= SPMODE_REV;
-	if (spi->mode & SPI_LOOP)
-		cs->hw_mode |= SPMODE_LOOP;
-
-	retval = mpc8xxx_spi_setup_transfer(spi, NULL);
-	if (retval < 0) {
-		cs->hw_mode = hw_mode; /* Restore settings */
-		return retval;
-	}
-	return 0;
-}
-
-static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
-{
-	u16 len;
-
-	dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
-		in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
-
-	len = in_be16(&mspi->rx_bd->cbd_datlen);
-	if (len > mspi->count) {
-		WARN_ON(1);
-		len = mspi->count;
-	}
-
-	/* Clear the events */
-	mpc8xxx_spi_write_reg(&mspi->base->event, events);
-
-	mspi->count -= len;
-	if (mspi->count)
-		mpc8xxx_spi_cpm_bufs_start(mspi);
-	else
-		complete(&mspi->done);
-}
-
-static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
-{
-	/* We need handle RX first */
-	if (events & SPIE_NE) {
-		u32 rx_data = mpc8xxx_spi_read_reg(&mspi->base->receive);
-
-		if (mspi->rx)
-			mspi->get_rx(rx_data, mspi);
-	}
-
-	if ((events & SPIE_NF) == 0)
-		/* spin until TX is done */
-		while (((events =
-			mpc8xxx_spi_read_reg(&mspi->base->event)) &
-						SPIE_NF) == 0)
-			cpu_relax();
-
-	/* Clear the events */
-	mpc8xxx_spi_write_reg(&mspi->base->event, events);
-
-	mspi->count -= 1;
-	if (mspi->count) {
-		u32 word = mspi->get_tx(mspi);
-
-		mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
-	} else {
-		complete(&mspi->done);
-	}
-}
-
-static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data)
-{
-	struct mpc8xxx_spi *mspi = context_data;
-	irqreturn_t ret = IRQ_NONE;
-	u32 events;
-
-	/* Get interrupt events(tx/rx) */
-	events = mpc8xxx_spi_read_reg(&mspi->base->event);
-	if (events)
-		ret = IRQ_HANDLED;
-
-	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
-
-	if (mspi->flags & SPI_CPM_MODE)
-		mpc8xxx_spi_cpm_irq(mspi, events);
-	else
-		mpc8xxx_spi_cpu_irq(mspi, events);
-
-	return ret;
-}
-
-static int mpc8xxx_spi_transfer(struct spi_device *spi,
-				struct spi_message *m)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
-
-	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
-	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
-	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
-	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
-
-	return 0;
-}
-
-
-static void mpc8xxx_spi_cleanup(struct spi_device *spi)
-{
-	kfree(spi->controller_state);
-}
-
-static void *mpc8xxx_spi_alloc_dummy_rx(void)
-{
-	mutex_lock(&mpc8xxx_dummy_rx_lock);
-
-	if (!mpc8xxx_dummy_rx)
-		mpc8xxx_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
-	if (mpc8xxx_dummy_rx)
-		mpc8xxx_dummy_rx_refcnt++;
-
-	mutex_unlock(&mpc8xxx_dummy_rx_lock);
-
-	return mpc8xxx_dummy_rx;
-}
-
-static void mpc8xxx_spi_free_dummy_rx(void)
-{
-	mutex_lock(&mpc8xxx_dummy_rx_lock);
-
-	switch (mpc8xxx_dummy_rx_refcnt) {
-	case 0:
-		WARN_ON(1);
-		break;
-	case 1:
-		kfree(mpc8xxx_dummy_rx);
-		mpc8xxx_dummy_rx = NULL;
-		/* fall through */
-	default:
-		mpc8xxx_dummy_rx_refcnt--;
-		break;
-	}
-
-	mutex_unlock(&mpc8xxx_dummy_rx_lock);
-}
-
-static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-	struct device_node *np = dev->of_node;
-	const u32 *iprop;
-	int size;
-	unsigned long spi_base_ofs;
-	unsigned long pram_ofs = -ENOMEM;
-
-	/* Can't use of_address_to_resource(), QE muram isn't at 0. */
-	iprop = of_get_property(np, "reg", &size);
-
-	/* QE with a fixed pram location? */
-	if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
-		return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
-
-	/* QE but with a dynamic pram location? */
-	if (mspi->flags & SPI_QE) {
-		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
-		qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
-				QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
-		return pram_ofs;
-	}
-
-	/* CPM1 and CPM2 pram must be at a fixed addr. */
-	if (!iprop || size != sizeof(*iprop) * 4)
-		return -ENOMEM;
-
-	spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
-	if (IS_ERR_VALUE(spi_base_ofs))
-		return -ENOMEM;
-
-	if (mspi->flags & SPI_CPM2) {
-		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
-		if (!IS_ERR_VALUE(pram_ofs)) {
-			u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs);
-
-			out_be16(spi_base, pram_ofs);
-		}
-	} else {
-		struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs);
-		u16 rpbase = in_be16(&pram->rpbase);
-
-		/* Microcode relocation patch applied? */
-		if (rpbase)
-			pram_ofs = rpbase;
-		else
-			return spi_base_ofs;
-	}
-
-	cpm_muram_free(spi_base_ofs);
-	return pram_ofs;
-}
-
-static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-	struct device_node *np = dev->of_node;
-	const u32 *iprop;
-	int size;
-	unsigned long pram_ofs;
-	unsigned long bds_ofs;
-
-	if (!(mspi->flags & SPI_CPM_MODE))
-		return 0;
-
-	if (!mpc8xxx_spi_alloc_dummy_rx())
-		return -ENOMEM;
-
-	if (mspi->flags & SPI_QE) {
-		iprop = of_get_property(np, "cell-index", &size);
-		if (iprop && size == sizeof(*iprop))
-			mspi->subblock = *iprop;
-
-		switch (mspi->subblock) {
-		default:
-			dev_warn(dev, "cell-index unspecified, assuming SPI1");
-			/* fall through */
-		case 0:
-			mspi->subblock = QE_CR_SUBBLOCK_SPI1;
-			break;
-		case 1:
-			mspi->subblock = QE_CR_SUBBLOCK_SPI2;
-			break;
-		}
-	}
-
-	pram_ofs = mpc8xxx_spi_cpm_get_pram(mspi);
-	if (IS_ERR_VALUE(pram_ofs)) {
-		dev_err(dev, "can't allocate spi parameter ram\n");
-		goto err_pram;
-	}
-
-	bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
-				  sizeof(*mspi->rx_bd), 8);
-	if (IS_ERR_VALUE(bds_ofs)) {
-		dev_err(dev, "can't allocate bds\n");
-		goto err_bds;
-	}
-
-	mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
-					    DMA_TO_DEVICE);
-	if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
-		dev_err(dev, "unable to map dummy tx buffer\n");
-		goto err_dummy_tx;
-	}
-
-	mspi->dma_dummy_rx = dma_map_single(dev, mpc8xxx_dummy_rx, SPI_MRBLR,
-					    DMA_FROM_DEVICE);
-	if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
-		dev_err(dev, "unable to map dummy rx buffer\n");
-		goto err_dummy_rx;
-	}
-
-	mspi->pram = cpm_muram_addr(pram_ofs);
-
-	mspi->tx_bd = cpm_muram_addr(bds_ofs);
-	mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
-
-	/* Initialize parameter ram. */
-	out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
-	out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
-	out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
-	out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
-	out_be16(&mspi->pram->mrblr, SPI_MRBLR);
-	out_be32(&mspi->pram->rstate, 0);
-	out_be32(&mspi->pram->rdp, 0);
-	out_be16(&mspi->pram->rbptr, 0);
-	out_be16(&mspi->pram->rbc, 0);
-	out_be32(&mspi->pram->rxtmp, 0);
-	out_be32(&mspi->pram->tstate, 0);
-	out_be32(&mspi->pram->tdp, 0);
-	out_be16(&mspi->pram->tbptr, 0);
-	out_be16(&mspi->pram->tbc, 0);
-	out_be32(&mspi->pram->txtmp, 0);
-
-	return 0;
-
-err_dummy_rx:
-	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
-err_dummy_tx:
-	cpm_muram_free(bds_ofs);
-err_bds:
-	cpm_muram_free(pram_ofs);
-err_pram:
-	mpc8xxx_spi_free_dummy_rx();
-	return -ENOMEM;
-}
-
-static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-
-	dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
-	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
-	cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
-	cpm_muram_free(cpm_muram_offset(mspi->pram));
-	mpc8xxx_spi_free_dummy_rx();
-}
-
-static const char *mpc8xxx_spi_strmode(unsigned int flags)
-{
-	if (flags & SPI_QE_CPU_MODE) {
-		return "QE CPU";
-	} else if (flags & SPI_CPM_MODE) {
-		if (flags & SPI_QE)
-			return "QE";
-		else if (flags & SPI_CPM2)
-			return "CPM2";
-		else
-			return "CPM1";
-	}
-	return "CPU";
-}
-
-static struct spi_master * __devinit
-mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
-{
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct spi_master *master;
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	u32 regval;
-	int ret = 0;
-
-	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
-	if (master == NULL) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	dev_set_drvdata(dev, master);
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
-			| SPI_LSB_FIRST | SPI_LOOP;
-
-	master->setup = mpc8xxx_spi_setup;
-	master->transfer = mpc8xxx_spi_transfer;
-	master->cleanup = mpc8xxx_spi_cleanup;
-	master->dev.of_node = dev->of_node;
-
-	mpc8xxx_spi = spi_master_get_devdata(master);
-	mpc8xxx_spi->dev = dev;
-	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
-	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
-	mpc8xxx_spi->flags = pdata->flags;
-	mpc8xxx_spi->spibrg = pdata->sysclk;
-
-	ret = mpc8xxx_spi_cpm_init(mpc8xxx_spi);
-	if (ret)
-		goto err_cpm_init;
-
-	mpc8xxx_spi->rx_shift = 0;
-	mpc8xxx_spi->tx_shift = 0;
-	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
-		mpc8xxx_spi->rx_shift = 16;
-		mpc8xxx_spi->tx_shift = 24;
-	}
-
-	init_completion(&mpc8xxx_spi->done);
-
-	mpc8xxx_spi->base = ioremap(mem->start, resource_size(mem));
-	if (mpc8xxx_spi->base == NULL) {
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
-
-	mpc8xxx_spi->irq = irq;
-
-	/* Register for SPI Interrupt */
-	ret = request_irq(mpc8xxx_spi->irq, mpc8xxx_spi_irq,
-			  0, "mpc8xxx_spi", mpc8xxx_spi);
-
-	if (ret != 0)
-		goto unmap_io;
-
-	master->bus_num = pdata->bus_num;
-	master->num_chipselect = pdata->max_chipselect;
-
-	/* SPI controller initializations */
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, 0);
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->command, 0);
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->event, 0xffffffff);
-
-	/* Enable SPI interface */
-	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
-	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
-		regval |= SPMODE_OP;
-
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval);
-	spin_lock_init(&mpc8xxx_spi->lock);
-	init_completion(&mpc8xxx_spi->done);
-	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
-	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
-
-	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
-		dev_name(master->dev.parent));
-	if (mpc8xxx_spi->workqueue == NULL) {
-		ret = -EBUSY;
-		goto free_irq;
-	}
-
-	ret = spi_register_master(master);
-	if (ret < 0)
-		goto unreg_master;
-
-	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base,
-		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
-
-	return master;
-
-unreg_master:
-	destroy_workqueue(mpc8xxx_spi->workqueue);
-free_irq:
-	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-unmap_io:
-	iounmap(mpc8xxx_spi->base);
-err_ioremap:
-	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
-err_cpm_init:
-	spi_master_put(master);
-err:
-	return ERR_PTR(ret);
-}
-
-static int __devexit mpc8xxx_spi_remove(struct device *dev)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	struct spi_master *master;
-
-	master = dev_get_drvdata(dev);
-	mpc8xxx_spi = spi_master_get_devdata(master);
-
-	flush_workqueue(mpc8xxx_spi->workqueue);
-	destroy_workqueue(mpc8xxx_spi->workqueue);
-	spi_unregister_master(master);
-
-	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-	iounmap(mpc8xxx_spi->base);
-	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
-
-	return 0;
-}
-
-struct mpc8xxx_spi_probe_info {
-	struct fsl_spi_platform_data pdata;
-	int *gpios;
-	bool *alow_flags;
-};
-
-static struct mpc8xxx_spi_probe_info *
-to_of_pinfo(struct fsl_spi_platform_data *pdata)
-{
-	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
-}
-
-static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on)
-{
-	struct device *dev = spi->dev.parent;
-	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
-	u16 cs = spi->chip_select;
-	int gpio = pinfo->gpios[cs];
-	bool alow = pinfo->alow_flags[cs];
-
-	gpio_set_value(gpio, on ^ alow);
-}
-
-static int of_mpc8xxx_spi_get_chipselects(struct device *dev)
-{
-	struct device_node *np = dev->of_node;
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
-	unsigned int ngpios;
-	int i = 0;
-	int ret;
-
-	ngpios = of_gpio_count(np);
-	if (!ngpios) {
-		/*
-		 * SPI w/o chip-select line. One SPI device is still permitted
-		 * though.
-		 */
-		pdata->max_chipselect = 1;
-		return 0;
-	}
-
-	pinfo->gpios = kmalloc(ngpios * sizeof(*pinfo->gpios), GFP_KERNEL);
-	if (!pinfo->gpios)
-		return -ENOMEM;
-	memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
-
-	pinfo->alow_flags = kzalloc(ngpios * sizeof(*pinfo->alow_flags),
-				    GFP_KERNEL);
-	if (!pinfo->alow_flags) {
-		ret = -ENOMEM;
-		goto err_alloc_flags;
-	}
-
-	for (; i < ngpios; i++) {
-		int gpio;
-		enum of_gpio_flags flags;
-
-		gpio = of_get_gpio_flags(np, i, &flags);
-		if (!gpio_is_valid(gpio)) {
-			dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
-			ret = gpio;
-			goto err_loop;
-		}
-
-		ret = gpio_request(gpio, dev_name(dev));
-		if (ret) {
-			dev_err(dev, "can't request gpio #%d: %d\n", i, ret);
-			goto err_loop;
-		}
-
-		pinfo->gpios[i] = gpio;
-		pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
-
-		ret = gpio_direction_output(pinfo->gpios[i],
-					    pinfo->alow_flags[i]);
-		if (ret) {
-			dev_err(dev, "can't set output direction for gpio "
-				"#%d: %d\n", i, ret);
-			goto err_loop;
-		}
-	}
-
-	pdata->max_chipselect = ngpios;
-	pdata->cs_control = mpc8xxx_spi_cs_control;
-
-	return 0;
-
-err_loop:
-	while (i >= 0) {
-		if (gpio_is_valid(pinfo->gpios[i]))
-			gpio_free(pinfo->gpios[i]);
-		i--;
-	}
-
-	kfree(pinfo->alow_flags);
-	pinfo->alow_flags = NULL;
-err_alloc_flags:
-	kfree(pinfo->gpios);
-	pinfo->gpios = NULL;
-	return ret;
-}
-
-static int of_mpc8xxx_spi_free_chipselects(struct device *dev)
-{
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
-	int i;
-
-	if (!pinfo->gpios)
-		return 0;
-
-	for (i = 0; i < pdata->max_chipselect; i++) {
-		if (gpio_is_valid(pinfo->gpios[i]))
-			gpio_free(pinfo->gpios[i]);
-	}
-
-	kfree(pinfo->gpios);
-	kfree(pinfo->alow_flags);
-	return 0;
-}
-
-static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
-					  const struct of_device_id *ofid)
-{
-	struct device *dev = &ofdev->dev;
-	struct device_node *np = ofdev->dev.of_node;
-	struct mpc8xxx_spi_probe_info *pinfo;
-	struct fsl_spi_platform_data *pdata;
-	struct spi_master *master;
-	struct resource mem;
-	struct resource irq;
-	const void *prop;
-	int ret = -ENOMEM;
-
-	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
-	if (!pinfo)
-		return -ENOMEM;
-
-	pdata = &pinfo->pdata;
-	dev->platform_data = pdata;
-
-	/* Allocate bus num dynamically. */
-	pdata->bus_num = -1;
-
-	/* SPI controller is either clocked from QE or SoC clock. */
-	pdata->sysclk = get_brgfreq();
-	if (pdata->sysclk == -1) {
-		pdata->sysclk = fsl_get_sys_freq();
-		if (pdata->sysclk == -1) {
-			ret = -ENODEV;
-			goto err_clk;
-		}
-	}
-
-	prop = of_get_property(np, "mode", NULL);
-	if (prop && !strcmp(prop, "cpu-qe"))
-		pdata->flags = SPI_QE_CPU_MODE;
-	else if (prop && !strcmp(prop, "qe"))
-		pdata->flags = SPI_CPM_MODE | SPI_QE;
-	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
-		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
-	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
-		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
-
-	ret = of_mpc8xxx_spi_get_chipselects(dev);
-	if (ret)
-		goto err;
-
-	ret = of_address_to_resource(np, 0, &mem);
-	if (ret)
-		goto err;
-
-	ret = of_irq_to_resource(np, 0, &irq);
-	if (!ret) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	master = mpc8xxx_spi_probe(dev, &mem, irq.start);
-	if (IS_ERR(master)) {
-		ret = PTR_ERR(master);
-		goto err;
-	}
-
-	return 0;
-
-err:
-	of_mpc8xxx_spi_free_chipselects(dev);
-err_clk:
-	kfree(pinfo);
-	return ret;
-}
-
-static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev)
-{
-	int ret;
-
-	ret = mpc8xxx_spi_remove(&ofdev->dev);
-	if (ret)
-		return ret;
-	of_mpc8xxx_spi_free_chipselects(&ofdev->dev);
-	return 0;
-}
-
-static const struct of_device_id of_mpc8xxx_spi_match[] = {
-	{ .compatible = "fsl,spi" },
-	{},
-};
-MODULE_DEVICE_TABLE(of, of_mpc8xxx_spi_match);
-
-static struct of_platform_driver of_mpc8xxx_spi_driver = {
-	.driver = {
-		.name = "mpc8xxx_spi",
-		.owner = THIS_MODULE,
-		.of_match_table = of_mpc8xxx_spi_match,
-	},
-	.probe		= of_mpc8xxx_spi_probe,
-	.remove		= __devexit_p(of_mpc8xxx_spi_remove),
-};
-
-#ifdef CONFIG_MPC832x_RDB
-/*
- * 				XXX XXX XXX
- * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
- * only. The driver should go away soon, since newer MPC8323E-RDB's device
- * tree can work with OpenFirmware driver. But for now we support old trees
- * as well.
- */
-static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
-{
-	struct resource *mem;
-	int irq;
-	struct spi_master *master;
-
-	if (!pdev->dev.platform_data)
-		return -EINVAL;
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem)
-		return -EINVAL;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0)
-		return -EINVAL;
-
-	master = mpc8xxx_spi_probe(&pdev->dev, mem, irq);
-	if (IS_ERR(master))
-		return PTR_ERR(master);
-	return 0;
-}
-
-static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev)
-{
-	return mpc8xxx_spi_remove(&pdev->dev);
-}
-
-MODULE_ALIAS("platform:mpc8xxx_spi");
-static struct platform_driver mpc8xxx_spi_driver = {
-	.probe = plat_mpc8xxx_spi_probe,
-	.remove = __devexit_p(plat_mpc8xxx_spi_remove),
-	.driver = {
-		.name = "mpc8xxx_spi",
-		.owner = THIS_MODULE,
-	},
-};
-
-static bool legacy_driver_failed;
-
-static void __init legacy_driver_register(void)
-{
-	legacy_driver_failed = platform_driver_register(&mpc8xxx_spi_driver);
-}
-
-static void __exit legacy_driver_unregister(void)
-{
-	if (legacy_driver_failed)
-		return;
-	platform_driver_unregister(&mpc8xxx_spi_driver);
-}
-#else
-static void __init legacy_driver_register(void) {}
-static void __exit legacy_driver_unregister(void) {}
-#endif /* CONFIG_MPC832x_RDB */
-
-static int __init mpc8xxx_spi_init(void)
-{
-	legacy_driver_register();
-	return of_register_platform_driver(&of_mpc8xxx_spi_driver);
-}
-
-static void __exit mpc8xxx_spi_exit(void)
-{
-	of_unregister_platform_driver(&of_mpc8xxx_spi_driver);
-	legacy_driver_unregister();
-}
-
-module_init(mpc8xxx_spi_init);
-module_exit(mpc8xxx_spi_exit);
-
-MODULE_AUTHOR("Kumar Gala");
-MODULE_DESCRIPTION("Simple MPC8xxx SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
index c3038da..795828b 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi_s3c64xx.c
@@ -261,15 +261,25 @@
 		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
 		if (dma_mode) {
 			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
-			s3c2410_dma_config(sdd->tx_dmach, 1);
+			s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
 			s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
 						xfer->tx_dma, xfer->len);
 			s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
 		} else {
-			unsigned char *buf = (unsigned char *) xfer->tx_buf;
-			int i = 0;
-			while (i < xfer->len)
-				writeb(buf[i++], regs + S3C64XX_SPI_TX_DATA);
+			switch (sdd->cur_bpw) {
+			case 32:
+				iowrite32_rep(regs + S3C64XX_SPI_TX_DATA,
+					xfer->tx_buf, xfer->len / 4);
+				break;
+			case 16:
+				iowrite16_rep(regs + S3C64XX_SPI_TX_DATA,
+					xfer->tx_buf, xfer->len / 2);
+				break;
+			default:
+				iowrite8_rep(regs + S3C64XX_SPI_TX_DATA,
+					xfer->tx_buf, xfer->len);
+				break;
+			}
 		}
 	}
 
@@ -286,7 +296,7 @@
 			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
 					| S3C64XX_SPI_PACKET_CNT_EN,
 					regs + S3C64XX_SPI_PACKET_CNT);
-			s3c2410_dma_config(sdd->rx_dmach, 1);
+			s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
 			s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
 						xfer->rx_dma, xfer->len);
 			s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
@@ -366,20 +376,26 @@
 				return -EIO;
 		}
 	} else {
-		unsigned char *buf;
-		int i;
-
 		/* If it was only Tx */
 		if (xfer->rx_buf == NULL) {
 			sdd->state &= ~TXBUSY;
 			return 0;
 		}
 
-		i = 0;
-		buf = xfer->rx_buf;
-		while (i < xfer->len)
-			buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA);
-
+		switch (sdd->cur_bpw) {
+		case 32:
+			ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
+				xfer->rx_buf, xfer->len / 4);
+			break;
+		case 16:
+			ioread16_rep(regs + S3C64XX_SPI_RX_DATA,
+				xfer->rx_buf, xfer->len / 2);
+			break;
+		default:
+			ioread8_rep(regs + S3C64XX_SPI_RX_DATA,
+				xfer->rx_buf, xfer->len);
+			break;
+		}
 		sdd->state &= ~RXBUSY;
 	}
 
@@ -399,13 +415,18 @@
 
 static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 {
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
 	void __iomem *regs = sdd->regs;
 	u32 val;
 
 	/* Disable Clock */
-	val = readl(regs + S3C64XX_SPI_CLK_CFG);
-	val &= ~S3C64XX_SPI_ENCLK_ENABLE;
-	writel(val, regs + S3C64XX_SPI_CLK_CFG);
+	if (sci->clk_from_cmu) {
+		clk_disable(sdd->src_clk);
+	} else {
+		val = readl(regs + S3C64XX_SPI_CLK_CFG);
+		val &= ~S3C64XX_SPI_ENCLK_ENABLE;
+		writel(val, regs + S3C64XX_SPI_CLK_CFG);
+	}
 
 	/* Set Polarity and Phase */
 	val = readl(regs + S3C64XX_SPI_CH_CFG);
@@ -429,29 +450,39 @@
 	switch (sdd->cur_bpw) {
 	case 32:
 		val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
+		val |= S3C64XX_SPI_MODE_CH_TSZ_WORD;
 		break;
 	case 16:
 		val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
+		val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD;
 		break;
 	default:
 		val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
+		val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE;
 		break;
 	}
-	val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */
 
 	writel(val, regs + S3C64XX_SPI_MODE_CFG);
 
-	/* Configure Clock */
-	val = readl(regs + S3C64XX_SPI_CLK_CFG);
-	val &= ~S3C64XX_SPI_PSR_MASK;
-	val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
-			& S3C64XX_SPI_PSR_MASK);
-	writel(val, regs + S3C64XX_SPI_CLK_CFG);
+	if (sci->clk_from_cmu) {
+		/* Configure Clock */
+		/* There is half-multiplier before the SPI */
+		clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
+		/* Enable Clock */
+		clk_enable(sdd->src_clk);
+	} else {
+		/* Configure Clock */
+		val = readl(regs + S3C64XX_SPI_CLK_CFG);
+		val &= ~S3C64XX_SPI_PSR_MASK;
+		val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
+				& S3C64XX_SPI_PSR_MASK);
+		writel(val, regs + S3C64XX_SPI_CLK_CFG);
 
-	/* Enable Clock */
-	val = readl(regs + S3C64XX_SPI_CLK_CFG);
-	val |= S3C64XX_SPI_ENCLK_ENABLE;
-	writel(val, regs + S3C64XX_SPI_CLK_CFG);
+		/* Enable Clock */
+		val = readl(regs + S3C64XX_SPI_CLK_CFG);
+		val |= S3C64XX_SPI_ENCLK_ENABLE;
+		writel(val, regs + S3C64XX_SPI_CLK_CFG);
+	}
 }
 
 static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
@@ -499,6 +530,7 @@
 static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
 						struct spi_message *msg)
 {
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
 	struct device *dev = &sdd->pdev->dev;
 	struct spi_transfer *xfer;
 
@@ -514,6 +546,9 @@
 	/* Map until end or first fail */
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 
+		if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+			continue;
+
 		if (xfer->tx_buf != NULL) {
 			xfer->tx_dma = dma_map_single(dev,
 					(void *)xfer->tx_buf, xfer->len,
@@ -545,6 +580,7 @@
 static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
 						struct spi_message *msg)
 {
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
 	struct device *dev = &sdd->pdev->dev;
 	struct spi_transfer *xfer;
 
@@ -553,6 +589,9 @@
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 
+		if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+			continue;
+
 		if (xfer->rx_buf != NULL
 				&& xfer->rx_dma != XFER_DMAADDR_INVALID)
 			dma_unmap_single(dev, xfer->rx_dma,
@@ -608,6 +647,14 @@
 		bpw = xfer->bits_per_word ? : spi->bits_per_word;
 		speed = xfer->speed_hz ? : spi->max_speed_hz;
 
+		if (xfer->len % (bpw / 8)) {
+			dev_err(&spi->dev,
+				"Xfer length(%u) not a multiple of word size(%u)\n",
+				xfer->len, bpw / 8);
+			status = -EIO;
+			goto out;
+		}
+
 		if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
 			sdd->cur_bpw = bpw;
 			sdd->cur_speed = speed;
@@ -798,7 +845,6 @@
 	struct s3c64xx_spi_driver_data *sdd;
 	struct s3c64xx_spi_info *sci;
 	struct spi_message *msg;
-	u32 psr, speed;
 	unsigned long flags;
 	int err = 0;
 
@@ -841,31 +887,36 @@
 	}
 
 	/* Check if we can provide the requested rate */
-	speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1); /* Max possible */
+	if (!sci->clk_from_cmu) {
+		u32 psr, speed;
 
-	if (spi->max_speed_hz > speed)
-		spi->max_speed_hz = speed;
+		/* Max possible */
+		speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1);
 
-	psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
-	psr &= S3C64XX_SPI_PSR_MASK;
-	if (psr == S3C64XX_SPI_PSR_MASK)
-		psr--;
+		if (spi->max_speed_hz > speed)
+			spi->max_speed_hz = speed;
 
-	speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
-	if (spi->max_speed_hz < speed) {
-		if (psr+1 < S3C64XX_SPI_PSR_MASK) {
-			psr++;
-		} else {
-			err = -EINVAL;
-			goto setup_exit;
+		psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
+		psr &= S3C64XX_SPI_PSR_MASK;
+		if (psr == S3C64XX_SPI_PSR_MASK)
+			psr--;
+
+		speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
+		if (spi->max_speed_hz < speed) {
+			if (psr+1 < S3C64XX_SPI_PSR_MASK) {
+				psr++;
+			} else {
+				err = -EINVAL;
+				goto setup_exit;
+			}
 		}
-	}
 
-	speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
-	if (spi->max_speed_hz >= speed)
-		spi->max_speed_hz = speed;
-	else
-		err = -EINVAL;
+		speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
+		if (spi->max_speed_hz >= speed)
+			spi->max_speed_hz = speed;
+		else
+			err = -EINVAL;
+	}
 
 setup_exit:
 
@@ -888,7 +939,8 @@
 	/* Disable Interrupts - we use Polling if not DMA mode */
 	writel(0, regs + S3C64XX_SPI_INT_EN);
 
-	writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
+	if (!sci->clk_from_cmu)
+		writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
 				regs + S3C64XX_SPI_CLK_CFG);
 	writel(0, regs + S3C64XX_SPI_MODE_CFG);
 	writel(0, regs + S3C64XX_SPI_PACKET_CNT);
diff --git a/drivers/spi/spi_topcliff_pch.c b/drivers/spi/spi_topcliff_pch.c
new file mode 100644
index 0000000..58e187f
--- /dev/null
+++ b/drivers/spi/spi_topcliff_pch.c
@@ -0,0 +1,1303 @@
+/*
+ * SPI bus driver for the Topcliff PCH used by Intel SoCs
+ *
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/wait.h>
+#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spi/spidev.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+/* Register offsets */
+#define PCH_SPCR		0x00	/* SPI control register */
+#define PCH_SPBRR		0x04	/* SPI baud rate register */
+#define PCH_SPSR		0x08	/* SPI status register */
+#define PCH_SPDWR		0x0C	/* SPI write data register */
+#define PCH_SPDRR		0x10	/* SPI read data register */
+#define PCH_SSNXCR		0x18	/* SSN Expand Control Register */
+#define PCH_SRST		0x1C	/* SPI reset register */
+
+#define PCH_SPSR_TFD		0x000007C0
+#define PCH_SPSR_RFD		0x0000F800
+
+#define PCH_READABLE(x)		(((x) & PCH_SPSR_RFD)>>11)
+#define PCH_WRITABLE(x)		(((x) & PCH_SPSR_TFD)>>6)
+
+#define PCH_RX_THOLD		7
+#define PCH_RX_THOLD_MAX	15
+
+#define PCH_MAX_BAUDRATE	5000000
+#define PCH_MAX_FIFO_DEPTH	16
+
+#define STATUS_RUNNING		1
+#define STATUS_EXITING		2
+#define PCH_SLEEP_TIME		10
+
+#define PCH_ADDRESS_SIZE	0x20
+
+#define SSN_LOW			0x02U
+#define SSN_NO_CONTROL		0x00U
+#define PCH_MAX_CS		0xFF
+#define PCI_DEVICE_ID_GE_SPI	0x8816
+
+#define SPCR_SPE_BIT		(1 << 0)
+#define SPCR_MSTR_BIT		(1 << 1)
+#define SPCR_LSBF_BIT		(1 << 4)
+#define SPCR_CPHA_BIT		(1 << 5)
+#define SPCR_CPOL_BIT		(1 << 6)
+#define SPCR_TFIE_BIT		(1 << 8)
+#define SPCR_RFIE_BIT		(1 << 9)
+#define SPCR_FIE_BIT		(1 << 10)
+#define SPCR_ORIE_BIT		(1 << 11)
+#define SPCR_MDFIE_BIT		(1 << 12)
+#define SPCR_FICLR_BIT		(1 << 24)
+#define SPSR_TFI_BIT		(1 << 0)
+#define SPSR_RFI_BIT		(1 << 1)
+#define SPSR_FI_BIT		(1 << 2)
+#define SPBRR_SIZE_BIT		(1 << 10)
+
+#define PCH_ALL			(SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|SPCR_ORIE_BIT|SPCR_MDFIE_BIT)
+
+#define SPCR_RFIC_FIELD		20
+#define SPCR_TFIC_FIELD		16
+
+#define SPSR_INT_BITS		0x1F
+#define MASK_SPBRR_SPBR_BITS	(~((1 << 10) - 1))
+#define MASK_RFIC_SPCR_BITS	(~(0xf << 20))
+#define MASK_TFIC_SPCR_BITS	(~(0xf000f << 12))
+
+#define PCH_CLOCK_HZ		50000000
+#define PCH_MAX_SPBR		1023
+
+
+/**
+ * struct pch_spi_data - Holds the SPI channel specific details
+ * @io_remap_addr:		The remapped PCI base address
+ * @master:			Pointer to the SPI master structure
+ * @work:			Reference to work queue handler
+ * @wk:				Workqueue for carrying out execution of the
+ *				requests
+ * @wait:			Wait queue for waking up upon receiving an
+ *				interrupt.
+ * @transfer_complete:		Status of SPI Transfer
+ * @bcurrent_msg_processing:	Status flag for message processing
+ * @lock:			Lock for protecting this structure
+ * @queue:			SPI Message queue
+ * @status:			Status of the SPI driver
+ * @bpw_len:			Length of data to be transferred in bits per
+ *				word
+ * @transfer_active:		Flag showing active transfer
+ * @tx_index:			Transmit data count; for bookkeeping during
+ *				transfer
+ * @rx_index:			Receive data count; for bookkeeping during
+ *				transfer
+ * @tx_buff:			Buffer for data to be transmitted
+ * @rx_index:			Buffer for Received data
+ * @n_curnt_chip:		The chip number that this SPI driver currently
+ *				operates on
+ * @current_chip:		Reference to the current chip that this SPI
+ *				driver currently operates on
+ * @current_msg:		The current message that this SPI driver is
+ *				handling
+ * @cur_trans:			The current transfer that this SPI driver is
+ *				handling
+ * @board_dat:			Reference to the SPI device data structure
+ */
+struct pch_spi_data {
+	void __iomem *io_remap_addr;
+	struct spi_master *master;
+	struct work_struct work;
+	struct workqueue_struct *wk;
+	wait_queue_head_t wait;
+	u8 transfer_complete;
+	u8 bcurrent_msg_processing;
+	spinlock_t lock;
+	struct list_head queue;
+	u8 status;
+	u32 bpw_len;
+	u8 transfer_active;
+	u32 tx_index;
+	u32 rx_index;
+	u16 *pkt_tx_buff;
+	u16 *pkt_rx_buff;
+	u8 n_curnt_chip;
+	struct spi_device *current_chip;
+	struct spi_message *current_msg;
+	struct spi_transfer *cur_trans;
+	struct pch_spi_board_data *board_dat;
+};
+
+/**
+ * struct pch_spi_board_data - Holds the SPI device specific details
+ * @pdev:		Pointer to the PCI device
+ * @irq_reg_sts:	Status of IRQ registration
+ * @pci_req_sts:	Status of pci_request_regions
+ * @suspend_sts:	Status of suspend
+ * @data:		Pointer to SPI channel data structure
+ */
+struct pch_spi_board_data {
+	struct pci_dev *pdev;
+	u8 irq_reg_sts;
+	u8 pci_req_sts;
+	u8 suspend_sts;
+	struct pch_spi_data *data;
+};
+
+static struct pci_device_id pch_spi_pcidev_id[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_GE_SPI)},
+	{0,}
+};
+
+/**
+ * pch_spi_writereg() - Performs  register writes
+ * @master:	Pointer to struct spi_master.
+ * @idx:	Register offset.
+ * @val:	Value to be written to register.
+ */
+static inline void pch_spi_writereg(struct spi_master *master, int idx, u32 val)
+{
+	struct pch_spi_data *data = spi_master_get_devdata(master);
+	iowrite32(val, (data->io_remap_addr + idx));
+}
+
+/**
+ * pch_spi_readreg() - Performs register reads
+ * @master:	Pointer to struct spi_master.
+ * @idx:	Register offset.
+ */
+static inline u32 pch_spi_readreg(struct spi_master *master, int idx)
+{
+	struct pch_spi_data *data = spi_master_get_devdata(master);
+	return ioread32(data->io_remap_addr + idx);
+}
+
+static inline void pch_spi_setclr_reg(struct spi_master *master, int idx,
+				      u32 set, u32 clr)
+{
+	u32 tmp = pch_spi_readreg(master, idx);
+	tmp = (tmp & ~clr) | set;
+	pch_spi_writereg(master, idx, tmp);
+}
+
+static void pch_spi_set_master_mode(struct spi_master *master)
+{
+	pch_spi_setclr_reg(master, PCH_SPCR, SPCR_MSTR_BIT, 0);
+}
+
+/**
+ * pch_spi_clear_fifo() - Clears the Transmit and Receive FIFOs
+ * @master:	Pointer to struct spi_master.
+ */
+static void pch_spi_clear_fifo(struct spi_master *master)
+{
+	pch_spi_setclr_reg(master, PCH_SPCR, SPCR_FICLR_BIT, 0);
+	pch_spi_setclr_reg(master, PCH_SPCR, 0, SPCR_FICLR_BIT);
+}
+
+static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
+				void __iomem *io_remap_addr)
+{
+	u32 n_read, tx_index, rx_index, bpw_len;
+	u16 *pkt_rx_buffer, *pkt_tx_buff;
+	int read_cnt;
+	u32 reg_spcr_val;
+	void __iomem *spsr;
+	void __iomem *spdrr;
+	void __iomem *spdwr;
+
+	spsr = io_remap_addr + PCH_SPSR;
+	iowrite32(reg_spsr_val, spsr);
+
+	if (data->transfer_active) {
+		rx_index = data->rx_index;
+		tx_index = data->tx_index;
+		bpw_len = data->bpw_len;
+		pkt_rx_buffer = data->pkt_rx_buff;
+		pkt_tx_buff = data->pkt_tx_buff;
+
+		spdrr = io_remap_addr + PCH_SPDRR;
+		spdwr = io_remap_addr + PCH_SPDWR;
+
+		n_read = PCH_READABLE(reg_spsr_val);
+
+		for (read_cnt = 0; (read_cnt < n_read); read_cnt++) {
+			pkt_rx_buffer[rx_index++] = ioread32(spdrr);
+			if (tx_index < bpw_len)
+				iowrite32(pkt_tx_buff[tx_index++], spdwr);
+		}
+
+		/* disable RFI if not needed */
+		if ((bpw_len - rx_index) <= PCH_MAX_FIFO_DEPTH) {
+			reg_spcr_val = ioread32(io_remap_addr + PCH_SPCR);
+			reg_spcr_val &= ~SPCR_RFIE_BIT; /* disable RFI */
+
+			/* reset rx threshold */
+			reg_spcr_val &= MASK_RFIC_SPCR_BITS;
+			reg_spcr_val |= (PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD);
+			iowrite32(((reg_spcr_val) &= (~(SPCR_RFIE_BIT))),
+				 (io_remap_addr + PCH_SPCR));
+		}
+
+		/* update counts */
+		data->tx_index = tx_index;
+		data->rx_index = rx_index;
+
+	}
+
+	/* if transfer complete interrupt */
+	if (reg_spsr_val & SPSR_FI_BIT) {
+		/* disable FI & RFI interrupts */
+		pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
+				   SPCR_FIE_BIT | SPCR_TFIE_BIT);
+
+		/* transfer is completed;inform pch_spi_process_messages */
+		data->transfer_complete = true;
+		wake_up(&data->wait);
+	}
+}
+
+/**
+ * pch_spi_handler() - Interrupt handler
+ * @irq:	The interrupt number.
+ * @dev_id:	Pointer to struct pch_spi_board_data.
+ */
+static irqreturn_t pch_spi_handler(int irq, void *dev_id)
+{
+	u32 reg_spsr_val;
+	struct pch_spi_data *data;
+	void __iomem *spsr;
+	void __iomem *io_remap_addr;
+	irqreturn_t ret = IRQ_NONE;
+	struct pch_spi_board_data *board_dat = dev_id;
+
+	if (board_dat->suspend_sts) {
+		dev_dbg(&board_dat->pdev->dev,
+			"%s returning due to suspend\n", __func__);
+		return IRQ_NONE;
+	}
+
+	data = board_dat->data;
+	io_remap_addr = data->io_remap_addr;
+	spsr = io_remap_addr + PCH_SPSR;
+
+	reg_spsr_val = ioread32(spsr);
+
+	/* Check if the interrupt is for SPI device */
+	if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) {
+		pch_spi_handler_sub(data, reg_spsr_val, io_remap_addr);
+		ret = IRQ_HANDLED;
+	}
+
+	dev_dbg(&board_dat->pdev->dev, "%s EXIT return value=%d\n",
+		__func__, ret);
+
+	return ret;
+}
+
+/**
+ * pch_spi_set_baud_rate() - Sets SPBR field in SPBRR
+ * @master:	Pointer to struct spi_master.
+ * @speed_hz:	Baud rate.
+ */
+static void pch_spi_set_baud_rate(struct spi_master *master, u32 speed_hz)
+{
+	u32 n_spbr = PCH_CLOCK_HZ / (speed_hz * 2);
+
+	/* if baud rate is less than we can support limit it */
+	if (n_spbr > PCH_MAX_SPBR)
+		n_spbr = PCH_MAX_SPBR;
+
+	pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, ~MASK_SPBRR_SPBR_BITS);
+}
+
+/**
+ * pch_spi_set_bits_per_word() - Sets SIZE field in SPBRR
+ * @master:		Pointer to struct spi_master.
+ * @bits_per_word:	Bits per word for SPI transfer.
+ */
+static void pch_spi_set_bits_per_word(struct spi_master *master,
+				      u8 bits_per_word)
+{
+	if (bits_per_word == 8)
+		pch_spi_setclr_reg(master, PCH_SPBRR, 0, SPBRR_SIZE_BIT);
+	else
+		pch_spi_setclr_reg(master, PCH_SPBRR, SPBRR_SIZE_BIT, 0);
+}
+
+/**
+ * pch_spi_setup_transfer() - Configures the PCH SPI hardware for transfer
+ * @spi:	Pointer to struct spi_device.
+ */
+static void pch_spi_setup_transfer(struct spi_device *spi)
+{
+	u32 flags = 0;
+
+	dev_dbg(&spi->dev, "%s SPBRR content =%x setting baud rate=%d\n",
+		__func__, pch_spi_readreg(spi->master, PCH_SPBRR),
+		spi->max_speed_hz);
+	pch_spi_set_baud_rate(spi->master, spi->max_speed_hz);
+
+	/* set bits per word */
+	pch_spi_set_bits_per_word(spi->master, spi->bits_per_word);
+
+	if (!(spi->mode & SPI_LSB_FIRST))
+		flags |= SPCR_LSBF_BIT;
+	if (spi->mode & SPI_CPOL)
+		flags |= SPCR_CPOL_BIT;
+	if (spi->mode & SPI_CPHA)
+		flags |= SPCR_CPHA_BIT;
+	pch_spi_setclr_reg(spi->master, PCH_SPCR, flags,
+			   (SPCR_LSBF_BIT | SPCR_CPOL_BIT | SPCR_CPHA_BIT));
+
+	/* Clear the FIFO by toggling  FICLR to 1 and back to 0 */
+	pch_spi_clear_fifo(spi->master);
+}
+
+/**
+ * pch_spi_reset() - Clears SPI registers
+ * @master:	Pointer to struct spi_master.
+ */
+static void pch_spi_reset(struct spi_master *master)
+{
+	/* write 1 to reset SPI */
+	pch_spi_writereg(master, PCH_SRST, 0x1);
+
+	/* clear reset */
+	pch_spi_writereg(master, PCH_SRST, 0x0);
+}
+
+static int pch_spi_setup(struct spi_device *pspi)
+{
+	/* check bits per word */
+	if (pspi->bits_per_word == 0) {
+		pspi->bits_per_word = 8;
+		dev_dbg(&pspi->dev, "%s 8 bits per word\n", __func__);
+	}
+
+	if ((pspi->bits_per_word != 8) && (pspi->bits_per_word != 16)) {
+		dev_err(&pspi->dev, "%s Invalid bits per word\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Check baud rate setting */
+	/* if baud rate of chip is greater than
+	   max we can support,return error */
+	if ((pspi->max_speed_hz) > PCH_MAX_BAUDRATE)
+		pspi->max_speed_hz = PCH_MAX_BAUDRATE;
+
+	dev_dbg(&pspi->dev, "%s MODE = %x\n", __func__,
+		(pspi->mode) & (SPI_CPOL | SPI_CPHA));
+
+	return 0;
+}
+
+static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
+{
+
+	struct spi_transfer *transfer;
+	struct pch_spi_data *data = spi_master_get_devdata(pspi->master);
+	int retval;
+	unsigned long flags;
+
+	/* validate spi message and baud rate */
+	if (unlikely(list_empty(&pmsg->transfers) == 1)) {
+		dev_err(&pspi->dev, "%s list empty\n", __func__);
+		retval = -EINVAL;
+		goto err_out;
+	}
+
+	if (unlikely(pspi->max_speed_hz == 0)) {
+		dev_err(&pspi->dev, "%s pch_spi_tranfer maxspeed=%d\n",
+			__func__, pspi->max_speed_hz);
+		retval = -EINVAL;
+		goto err_out;
+	}
+
+	dev_dbg(&pspi->dev, "%s Transfer List not empty. "
+		"Transfer Speed is set.\n", __func__);
+
+	/* validate Tx/Rx buffers and Transfer length */
+	list_for_each_entry(transfer, &pmsg->transfers, transfer_list) {
+		if (!transfer->tx_buf && !transfer->rx_buf) {
+			dev_err(&pspi->dev,
+				"%s Tx and Rx buffer NULL\n", __func__);
+			retval = -EINVAL;
+			goto err_out;
+		}
+
+		if (!transfer->len) {
+			dev_err(&pspi->dev, "%s Transfer length invalid\n",
+				__func__);
+			retval = -EINVAL;
+			goto err_out;
+		}
+
+		dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length"
+			" valid\n", __func__);
+
+		/* if baud rate hs been specified validate the same */
+		if (transfer->speed_hz > PCH_MAX_BAUDRATE)
+			transfer->speed_hz = PCH_MAX_BAUDRATE;
+
+		/* if bits per word has been specified validate the same */
+		if (transfer->bits_per_word) {
+			if ((transfer->bits_per_word != 8)
+			    && (transfer->bits_per_word != 16)) {
+				retval = -EINVAL;
+				dev_err(&pspi->dev,
+					"%s Invalid bits per word\n", __func__);
+				goto err_out;
+			}
+		}
+	}
+
+	spin_lock_irqsave(&data->lock, flags);
+
+	/* We won't process any messages if we have been asked to terminate */
+	if (data->status == STATUS_EXITING) {
+		dev_err(&pspi->dev, "%s status = STATUS_EXITING.\n", __func__);
+		retval = -ESHUTDOWN;
+		goto err_return_spinlock;
+	}
+
+	/* If suspended ,return -EINVAL */
+	if (data->board_dat->suspend_sts) {
+		dev_err(&pspi->dev, "%s suspend; returning EINVAL\n", __func__);
+		retval = -EINVAL;
+		goto err_return_spinlock;
+	}
+
+	/* set status of message */
+	pmsg->actual_length = 0;
+	dev_dbg(&pspi->dev, "%s - pmsg->status =%d\n", __func__, pmsg->status);
+
+	pmsg->status = -EINPROGRESS;
+
+	/* add message to queue */
+	list_add_tail(&pmsg->queue, &data->queue);
+	dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__);
+
+	/* schedule work queue to run */
+	queue_work(data->wk, &data->work);
+	dev_dbg(&pspi->dev, "%s - Invoked queue work\n", __func__);
+
+	retval = 0;
+
+err_return_spinlock:
+	spin_unlock_irqrestore(&data->lock, flags);
+err_out:
+	dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval);
+	return retval;
+}
+
+static inline void pch_spi_select_chip(struct pch_spi_data *data,
+				       struct spi_device *pspi)
+{
+	if (data->current_chip != NULL) {
+		if (pspi->chip_select != data->n_curnt_chip) {
+			dev_dbg(&pspi->dev, "%s : different slave\n", __func__);
+			data->current_chip = NULL;
+		}
+	}
+
+	data->current_chip = pspi;
+
+	data->n_curnt_chip = data->current_chip->chip_select;
+
+	dev_dbg(&pspi->dev, "%s :Invoking pch_spi_setup_transfer\n", __func__);
+	pch_spi_setup_transfer(pspi);
+}
+
+static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,
+			   struct spi_message **ppmsg)
+{
+	int size;
+	u32 n_writes;
+	int j;
+	struct spi_message *pmsg;
+	const u8 *tx_buf;
+	const u16 *tx_sbuf;
+
+	pmsg = *ppmsg;
+
+	/* set baud rate if needed */
+	if (data->cur_trans->speed_hz) {
+		dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__);
+		pch_spi_set_baud_rate(data->master, data->cur_trans->speed_hz);
+	}
+
+	/* set bits per word if needed */
+	if (data->cur_trans->bits_per_word &&
+	    (data->current_msg->spi->bits_per_word != data->cur_trans->bits_per_word)) {
+		dev_dbg(&data->master->dev, "%s:set bits per word\n", __func__);
+		pch_spi_set_bits_per_word(data->master,
+					  data->cur_trans->bits_per_word);
+		*bpw = data->cur_trans->bits_per_word;
+	} else {
+		*bpw = data->current_msg->spi->bits_per_word;
+	}
+
+	/* reset Tx/Rx index */
+	data->tx_index = 0;
+	data->rx_index = 0;
+
+	data->bpw_len = data->cur_trans->len / (*bpw / 8);
+
+	/* find alloc size */
+	size = data->cur_trans->len * sizeof(*data->pkt_tx_buff);
+
+	/* allocate memory for pkt_tx_buff & pkt_rx_buffer */
+	data->pkt_tx_buff = kzalloc(size, GFP_KERNEL);
+	if (data->pkt_tx_buff != NULL) {
+		data->pkt_rx_buff = kzalloc(size, GFP_KERNEL);
+		if (!data->pkt_rx_buff)
+			kfree(data->pkt_tx_buff);
+	}
+
+	if (!data->pkt_rx_buff) {
+		/* flush queue and set status of all transfers to -ENOMEM */
+		dev_err(&data->master->dev, "%s :kzalloc failed\n", __func__);
+		list_for_each_entry(pmsg, data->queue.next, queue) {
+			pmsg->status = -ENOMEM;
+
+			if (pmsg->complete != 0)
+				pmsg->complete(pmsg->context);
+
+			/* delete from queue */
+			list_del_init(&pmsg->queue);
+		}
+		return;
+	}
+
+	/* copy Tx Data */
+	if (data->cur_trans->tx_buf != NULL) {
+		if (*bpw == 8) {
+			tx_buf = data->cur_trans->tx_buf;
+			for (j = 0; j < data->bpw_len; j++)
+				data->pkt_tx_buff[j] = *tx_buf++;
+		} else {
+			tx_sbuf = data->cur_trans->tx_buf;
+			for (j = 0; j < data->bpw_len; j++)
+				data->pkt_tx_buff[j] = *tx_sbuf++;
+		}
+	}
+
+	/* if len greater than PCH_MAX_FIFO_DEPTH, write 16,else len bytes */
+	n_writes = data->bpw_len;
+	if (n_writes > PCH_MAX_FIFO_DEPTH)
+		n_writes = PCH_MAX_FIFO_DEPTH;
+
+	dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing "
+		"0x2 to SSNXCR\n", __func__);
+	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
+
+	for (j = 0; j < n_writes; j++)
+		pch_spi_writereg(data->master, PCH_SPDWR, data->pkt_tx_buff[j]);
+
+	/* update tx_index */
+	data->tx_index = j;
+
+	/* reset transfer complete flag */
+	data->transfer_complete = false;
+	data->transfer_active = true;
+}
+
+
+static void pch_spi_nomore_transfer(struct pch_spi_data *data,
+						struct spi_message *pmsg)
+{
+	dev_dbg(&data->master->dev, "%s called\n", __func__);
+	/* Invoke complete callback
+	 * [To the spi core..indicating end of transfer] */
+	data->current_msg->status = 0;
+
+	if (data->current_msg->complete != 0) {
+		dev_dbg(&data->master->dev,
+			"%s:Invoking callback of SPI core\n", __func__);
+		data->current_msg->complete(data->current_msg->context);
+	}
+
+	/* update status in global variable */
+	data->bcurrent_msg_processing = false;
+
+	dev_dbg(&data->master->dev,
+		"%s:data->bcurrent_msg_processing = false\n", __func__);
+
+	data->current_msg = NULL;
+	data->cur_trans = NULL;
+
+	/* check if we have items in list and not suspending
+	 * return 1 if list empty */
+	if ((list_empty(&data->queue) == 0) &&
+	    (!data->board_dat->suspend_sts) &&
+	    (data->status != STATUS_EXITING)) {
+		/* We have some more work to do (either there is more tranint
+		 * bpw;sfer requests in the current message or there are
+		 *more messages)
+		 */
+		dev_dbg(&data->master->dev, "%s:Invoke queue_work\n", __func__);
+		queue_work(data->wk, &data->work);
+	} else if (data->board_dat->suspend_sts ||
+		   data->status == STATUS_EXITING) {
+		dev_dbg(&data->master->dev,
+			"%s suspend/remove initiated, flushing queue\n",
+			__func__);
+		list_for_each_entry(pmsg, data->queue.next, queue) {
+			pmsg->status = -EIO;
+
+			if (pmsg->complete)
+				pmsg->complete(pmsg->context);
+
+			/* delete from queue */
+			list_del_init(&pmsg->queue);
+		}
+	}
+}
+
+static void pch_spi_set_ir(struct pch_spi_data *data)
+{
+	/* enable interrupts */
+	if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH) {
+		/* set receive threhold to PCH_RX_THOLD */
+		pch_spi_setclr_reg(data->master, PCH_SPCR,
+				   PCH_RX_THOLD << SPCR_TFIC_FIELD,
+				   ~MASK_TFIC_SPCR_BITS);
+		/* enable FI and RFI interrupts */
+		pch_spi_setclr_reg(data->master, PCH_SPCR,
+				   SPCR_RFIE_BIT | SPCR_TFIE_BIT, 0);
+	} else {
+		/* set receive threhold to maximum */
+		pch_spi_setclr_reg(data->master, PCH_SPCR,
+				   PCH_RX_THOLD_MAX << SPCR_TFIC_FIELD,
+				   ~MASK_TFIC_SPCR_BITS);
+		/* enable FI interrupt */
+		pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_FIE_BIT, 0);
+	}
+
+	dev_dbg(&data->master->dev,
+		"%s:invoking pch_spi_set_enable to enable SPI\n", __func__);
+
+	/* SPI set enable */
+	pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, SPCR_SPE_BIT, 0);
+
+	/* Wait until the transfer completes; go to sleep after
+				 initiating the transfer. */
+	dev_dbg(&data->master->dev,
+		"%s:waiting for transfer to get over\n", __func__);
+
+	wait_event_interruptible(data->wait, data->transfer_complete);
+
+	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL);
+	dev_dbg(&data->master->dev,
+		"%s:no more control over SSN-writing 0 to SSNXCR.", __func__);
+
+	data->transfer_active = false;
+	dev_dbg(&data->master->dev,
+		"%s set data->transfer_active = false\n", __func__);
+
+	/* clear all interrupts */
+	pch_spi_writereg(data->master, PCH_SPSR,
+			 pch_spi_readreg(data->master, PCH_SPSR));
+	/* disable interrupts */
+	pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
+}
+
+static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw)
+{
+	int j;
+	u8 *rx_buf;
+	u16 *rx_sbuf;
+
+	/* copy Rx Data */
+	if (!data->cur_trans->rx_buf)
+		return;
+
+	if (bpw == 8) {
+		rx_buf = data->cur_trans->rx_buf;
+		for (j = 0; j < data->bpw_len; j++)
+			*rx_buf++ = data->pkt_rx_buff[j] & 0xFF;
+	} else {
+		rx_sbuf = data->cur_trans->rx_buf;
+		for (j = 0; j < data->bpw_len; j++)
+			*rx_sbuf++ = data->pkt_rx_buff[j];
+	}
+}
+
+
+static void pch_spi_process_messages(struct work_struct *pwork)
+{
+	struct spi_message *pmsg;
+	struct pch_spi_data *data;
+	int bpw;
+
+	data = container_of(pwork, struct pch_spi_data, work);
+	dev_dbg(&data->master->dev, "%s data initialized\n", __func__);
+
+	spin_lock(&data->lock);
+
+	/* check if suspend has been initiated;if yes flush queue */
+	if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) {
+		dev_dbg(&data->master->dev,
+			"%s suspend/remove initiated,flushing queue\n",
+			__func__);
+
+		list_for_each_entry(pmsg, data->queue.next, queue) {
+			pmsg->status = -EIO;
+
+			if (pmsg->complete != 0) {
+				spin_unlock(&data->lock);
+				pmsg->complete(pmsg->context);
+				spin_lock(&data->lock);
+			}
+
+			/* delete from queue */
+			list_del_init(&pmsg->queue);
+		}
+
+		spin_unlock(&data->lock);
+		return;
+	}
+
+	data->bcurrent_msg_processing = true;
+	dev_dbg(&data->master->dev,
+		"%s Set data->bcurrent_msg_processing= true\n", __func__);
+
+	/* Get the message from the queue and delete it from there. */
+	data->current_msg = list_entry(data->queue.next, struct spi_message,
+					queue);
+
+	list_del_init(&data->current_msg->queue);
+
+	data->current_msg->status = 0;
+
+	pch_spi_select_chip(data, data->current_msg->spi);
+
+	spin_unlock(&data->lock);
+
+	do {
+		/* If we are already processing a message get the next
+		transfer structure from the message otherwise retrieve
+		the 1st transfer request from the message. */
+		spin_lock(&data->lock);
+
+		if (data->cur_trans == NULL) {
+			data->cur_trans =
+			    list_entry(data->current_msg->transfers.
+				       next, struct spi_transfer,
+				       transfer_list);
+			dev_dbg(&data->master->dev,
+				"%s :Getting 1st transfer message\n", __func__);
+		} else {
+			data->cur_trans =
+			    list_entry(data->cur_trans->transfer_list.next,
+				       struct spi_transfer,
+				       transfer_list);
+			dev_dbg(&data->master->dev,
+				"%s :Getting next transfer message\n",
+				__func__);
+		}
+
+		spin_unlock(&data->lock);
+
+		pch_spi_set_tx(data, &bpw, &pmsg);
+
+		/* Control interrupt*/
+		pch_spi_set_ir(data);
+
+		/* Disable SPI transfer */
+		pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, 0,
+				   SPCR_SPE_BIT);
+
+		/* clear FIFO */
+		pch_spi_clear_fifo(data->master);
+
+		/* copy Rx Data */
+		pch_spi_copy_rx_data(data, bpw);
+
+		/* free memory */
+		kfree(data->pkt_rx_buff);
+		data->pkt_rx_buff = NULL;
+
+		kfree(data->pkt_tx_buff);
+		data->pkt_tx_buff = NULL;
+
+		/* increment message count */
+		data->current_msg->actual_length += data->cur_trans->len;
+
+		dev_dbg(&data->master->dev,
+			"%s:data->current_msg->actual_length=%d\n",
+			__func__, data->current_msg->actual_length);
+
+		/* check for delay */
+		if (data->cur_trans->delay_usecs) {
+			dev_dbg(&data->master->dev, "%s:"
+				"delay in usec=%d\n", __func__,
+				data->cur_trans->delay_usecs);
+			udelay(data->cur_trans->delay_usecs);
+		}
+
+		spin_lock(&data->lock);
+
+		/* No more transfer in this message. */
+		if ((data->cur_trans->transfer_list.next) ==
+		    &(data->current_msg->transfers)) {
+			pch_spi_nomore_transfer(data, pmsg);
+		}
+
+		spin_unlock(&data->lock);
+
+	} while (data->cur_trans != NULL);
+}
+
+static void pch_spi_free_resources(struct pch_spi_board_data *board_dat)
+{
+	dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
+
+	/* free workqueue */
+	if (board_dat->data->wk != NULL) {
+		destroy_workqueue(board_dat->data->wk);
+		board_dat->data->wk = NULL;
+		dev_dbg(&board_dat->pdev->dev,
+			"%s destroy_workqueue invoked successfully\n",
+			__func__);
+	}
+
+	/* disable interrupts & free IRQ */
+	if (board_dat->irq_reg_sts) {
+		/* disable interrupts */
+		pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0,
+				   PCH_ALL);
+
+		/* free IRQ */
+		free_irq(board_dat->pdev->irq, board_dat);
+
+		dev_dbg(&board_dat->pdev->dev,
+			"%s free_irq invoked successfully\n", __func__);
+
+		board_dat->irq_reg_sts = false;
+	}
+
+	/* unmap PCI base address */
+	if (board_dat->data->io_remap_addr != 0) {
+		pci_iounmap(board_dat->pdev, board_dat->data->io_remap_addr);
+
+		board_dat->data->io_remap_addr = 0;
+
+		dev_dbg(&board_dat->pdev->dev,
+			"%s pci_iounmap invoked successfully\n", __func__);
+	}
+
+	/* release PCI region */
+	if (board_dat->pci_req_sts) {
+		pci_release_regions(board_dat->pdev);
+		dev_dbg(&board_dat->pdev->dev,
+			"%s pci_release_regions invoked successfully\n",
+			__func__);
+		board_dat->pci_req_sts = false;
+	}
+}
+
+static int pch_spi_get_resources(struct pch_spi_board_data *board_dat)
+{
+	void __iomem *io_remap_addr;
+	int retval;
+	dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
+
+	/* create workqueue */
+	board_dat->data->wk = create_singlethread_workqueue(KBUILD_MODNAME);
+	if (!board_dat->data->wk) {
+		dev_err(&board_dat->pdev->dev,
+			"%s create_singlet hread_workqueue failed\n", __func__);
+		retval = -EBUSY;
+		goto err_return;
+	}
+
+	dev_dbg(&board_dat->pdev->dev,
+		"%s create_singlethread_workqueue success\n", __func__);
+
+	retval = pci_request_regions(board_dat->pdev, KBUILD_MODNAME);
+	if (retval != 0) {
+		dev_err(&board_dat->pdev->dev,
+			"%s request_region failed\n", __func__);
+		goto err_return;
+	}
+
+	board_dat->pci_req_sts = true;
+
+	io_remap_addr = pci_iomap(board_dat->pdev, 1, 0);
+	if (io_remap_addr == 0) {
+		dev_err(&board_dat->pdev->dev,
+			"%s pci_iomap failed\n", __func__);
+		retval = -ENOMEM;
+		goto err_return;
+	}
+
+	/* calculate base address for all channels */
+	board_dat->data->io_remap_addr = io_remap_addr;
+
+	/* reset PCH SPI h/w */
+	pch_spi_reset(board_dat->data->master);
+	dev_dbg(&board_dat->pdev->dev,
+		"%s pch_spi_reset invoked successfully\n", __func__);
+
+	/* register IRQ */
+	retval = request_irq(board_dat->pdev->irq, pch_spi_handler,
+			     IRQF_SHARED, KBUILD_MODNAME, board_dat);
+	if (retval != 0) {
+		dev_err(&board_dat->pdev->dev,
+			"%s request_irq failed\n", __func__);
+		goto err_return;
+	}
+
+	dev_dbg(&board_dat->pdev->dev, "%s request_irq returned=%d\n",
+		__func__, retval);
+
+	board_dat->irq_reg_sts = true;
+	dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);
+
+err_return:
+	if (retval != 0) {
+		dev_err(&board_dat->pdev->dev,
+			"%s FAIL:invoking pch_spi_free_resources\n", __func__);
+		pch_spi_free_resources(board_dat);
+	}
+
+	dev_dbg(&board_dat->pdev->dev, "%s Return=%d\n", __func__, retval);
+
+	return retval;
+}
+
+static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+
+	struct spi_master *master;
+
+	struct pch_spi_board_data *board_dat;
+	int retval;
+
+	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+	/* allocate memory for private data */
+	board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL);
+	if (board_dat == NULL) {
+		dev_err(&pdev->dev,
+			" %s memory allocation for private data failed\n",
+			__func__);
+		retval = -ENOMEM;
+		goto err_kmalloc;
+	}
+
+	dev_dbg(&pdev->dev,
+		"%s memory allocation for private data success\n", __func__);
+
+	/* enable PCI device */
+	retval = pci_enable_device(pdev);
+	if (retval != 0) {
+		dev_err(&pdev->dev, "%s pci_enable_device FAILED\n", __func__);
+
+		goto err_pci_en_device;
+	}
+
+	dev_dbg(&pdev->dev, "%s pci_enable_device returned=%d\n",
+		__func__, retval);
+
+	board_dat->pdev = pdev;
+
+	/* alllocate memory for SPI master */
+	master = spi_alloc_master(&pdev->dev, sizeof(struct pch_spi_data));
+	if (master == NULL) {
+		retval = -ENOMEM;
+		dev_err(&pdev->dev, "%s Fail.\n", __func__);
+		goto err_spi_alloc_master;
+	}
+
+	dev_dbg(&pdev->dev,
+		"%s spi_alloc_master returned non NULL\n", __func__);
+
+	/* initialize members of SPI master */
+	master->bus_num = -1;
+	master->num_chipselect = PCH_MAX_CS;
+	master->setup = pch_spi_setup;
+	master->transfer = pch_spi_transfer;
+	dev_dbg(&pdev->dev,
+		"%s transfer member of SPI master initialized\n", __func__);
+
+	board_dat->data = spi_master_get_devdata(master);
+
+	board_dat->data->master = master;
+	board_dat->data->n_curnt_chip = 255;
+	board_dat->data->board_dat = board_dat;
+	board_dat->data->status = STATUS_RUNNING;
+
+	INIT_LIST_HEAD(&board_dat->data->queue);
+	spin_lock_init(&board_dat->data->lock);
+	INIT_WORK(&board_dat->data->work, pch_spi_process_messages);
+	init_waitqueue_head(&board_dat->data->wait);
+
+	/* allocate resources for PCH SPI */
+	retval = pch_spi_get_resources(board_dat);
+	if (retval) {
+		dev_err(&pdev->dev, "%s fail(retval=%d)\n", __func__, retval);
+		goto err_spi_get_resources;
+	}
+
+	dev_dbg(&pdev->dev, "%s pch_spi_get_resources returned=%d\n",
+		__func__, retval);
+
+	/* save private data in dev */
+	pci_set_drvdata(pdev, board_dat);
+	dev_dbg(&pdev->dev, "%s invoked pci_set_drvdata\n", __func__);
+
+	/* set master mode */
+	pch_spi_set_master_mode(master);
+	dev_dbg(&pdev->dev,
+		"%s invoked pch_spi_set_master_mode\n", __func__);
+
+	/* Register the controller with the SPI core. */
+	retval = spi_register_master(master);
+	if (retval != 0) {
+		dev_err(&pdev->dev,
+			"%s spi_register_master FAILED\n", __func__);
+		goto err_spi_reg_master;
+	}
+
+	dev_dbg(&pdev->dev, "%s spi_register_master returned=%d\n",
+		__func__, retval);
+
+
+	return 0;
+
+err_spi_reg_master:
+	spi_unregister_master(master);
+err_spi_get_resources:
+err_spi_alloc_master:
+	spi_master_put(master);
+	pci_disable_device(pdev);
+err_pci_en_device:
+	kfree(board_dat);
+err_kmalloc:
+	return retval;
+}
+
+static void pch_spi_remove(struct pci_dev *pdev)
+{
+	struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev);
+	int count;
+
+	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+	if (!board_dat) {
+		dev_err(&pdev->dev,
+			"%s pci_get_drvdata returned NULL\n", __func__);
+		return;
+	}
+
+	/* check for any pending messages; no action is taken if the queue
+	 * is still full; but at least we tried.  Unload anyway */
+	count = 500;
+	spin_lock(&board_dat->data->lock);
+	board_dat->data->status = STATUS_EXITING;
+	while ((list_empty(&board_dat->data->queue) == 0) && --count) {
+		dev_dbg(&board_dat->pdev->dev, "%s :queue not empty\n",
+			__func__);
+		spin_unlock(&board_dat->data->lock);
+		msleep(PCH_SLEEP_TIME);
+		spin_lock(&board_dat->data->lock);
+	}
+	spin_unlock(&board_dat->data->lock);
+
+	/* Free resources allocated for PCH SPI */
+	pch_spi_free_resources(board_dat);
+
+	spi_unregister_master(board_dat->data->master);
+
+	/* free memory for private data */
+	kfree(board_dat);
+
+	pci_set_drvdata(pdev, NULL);
+
+	/* disable PCI device */
+	pci_disable_device(pdev);
+
+	dev_dbg(&pdev->dev, "%s invoked pci_disable_device\n", __func__);
+}
+
+#ifdef CONFIG_PM
+static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	u8 count;
+	int retval;
+
+	struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev);
+
+	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+	if (!board_dat) {
+		dev_err(&pdev->dev,
+			"%s pci_get_drvdata returned NULL\n", __func__);
+		return -EFAULT;
+	}
+
+	retval = 0;
+	board_dat->suspend_sts = true;
+
+	/* check if the current message is processed:
+	   Only after thats done the transfer will be suspended */
+	count = 255;
+	while ((--count) > 0) {
+		if (!(board_dat->data->bcurrent_msg_processing)) {
+			dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_"
+				"msg_processing = false\n", __func__);
+			break;
+		} else {
+			dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_msg_"
+				"processing = true\n", __func__);
+		}
+		msleep(PCH_SLEEP_TIME);
+	}
+
+	/* Free IRQ */
+	if (board_dat->irq_reg_sts) {
+		/* disable all interrupts */
+		pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0,
+				   PCH_ALL);
+		pch_spi_reset(board_dat->data->master);
+
+		free_irq(board_dat->pdev->irq, board_dat);
+
+		board_dat->irq_reg_sts = false;
+		dev_dbg(&pdev->dev,
+			"%s free_irq invoked successfully.\n", __func__);
+	}
+
+	/* save config space */
+	retval = pci_save_state(pdev);
+
+	if (retval == 0) {
+		dev_dbg(&pdev->dev, "%s pci_save_state returned=%d\n",
+			__func__, retval);
+		/* disable PM notifications */
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+		dev_dbg(&pdev->dev,
+			"%s pci_enable_wake invoked successfully\n", __func__);
+		/* disable PCI device */
+		pci_disable_device(pdev);
+		dev_dbg(&pdev->dev,
+			"%s pci_disable_device invoked successfully\n",
+			__func__);
+		/* move device to D3hot  state */
+		pci_set_power_state(pdev, PCI_D3hot);
+		dev_dbg(&pdev->dev,
+			"%s pci_set_power_state invoked successfully\n",
+			__func__);
+	} else {
+		dev_err(&pdev->dev, "%s pci_save_state failed\n", __func__);
+	}
+
+	dev_dbg(&pdev->dev, "%s return=%d\n", __func__, retval);
+
+	return retval;
+}
+
+static int pch_spi_resume(struct pci_dev *pdev)
+{
+	int retval;
+
+	struct pch_spi_board_data *board = pci_get_drvdata(pdev);
+	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+	if (!board) {
+		dev_err(&pdev->dev,
+			"%s pci_get_drvdata returned NULL\n", __func__);
+		return -EFAULT;
+	}
+
+	/* move device to DO power state */
+	pci_set_power_state(pdev, PCI_D0);
+
+	/* restore state */
+	pci_restore_state(pdev);
+
+	retval = pci_enable_device(pdev);
+	if (retval < 0) {
+		dev_err(&pdev->dev,
+			"%s pci_enable_device failed\n", __func__);
+	} else {
+		/* disable PM notifications */
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+
+		/* register IRQ handler */
+		if (!board->irq_reg_sts) {
+			/* register IRQ */
+			retval = request_irq(board->pdev->irq, pch_spi_handler,
+					     IRQF_SHARED, KBUILD_MODNAME,
+					     board);
+			if (retval < 0) {
+				dev_err(&pdev->dev,
+					"%s request_irq failed\n", __func__);
+				return retval;
+			}
+			board->irq_reg_sts = true;
+
+			/* reset PCH SPI h/w */
+			pch_spi_reset(board->data->master);
+			pch_spi_set_master_mode(board->data->master);
+
+			/* set suspend status to false */
+			board->suspend_sts = false;
+
+		}
+	}
+
+	dev_dbg(&pdev->dev, "%s returning=%d\n", __func__, retval);
+
+	return retval;
+}
+#else
+#define pch_spi_suspend NULL
+#define pch_spi_resume NULL
+
+#endif
+
+static struct pci_driver pch_spi_pcidev = {
+	.name = "pch_spi",
+	.id_table = pch_spi_pcidev_id,
+	.probe = pch_spi_probe,
+	.remove = pch_spi_remove,
+	.suspend = pch_spi_suspend,
+	.resume = pch_spi_resume,
+};
+
+static int __init pch_spi_init(void)
+{
+	return pci_register_driver(&pch_spi_pcidev);
+}
+module_init(pch_spi_init);
+
+static void __exit pch_spi_exit(void)
+{
+	pci_unregister_driver(&pch_spi_pcidev);
+}
+module_exit(pch_spi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Topcliff PCH SPI PCI Driver");
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index ea1bec3..4e6245e 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -545,6 +545,7 @@
 	.unlocked_ioctl = spidev_ioctl,
 	.open =		spidev_open,
 	.release =	spidev_release,
+	.llseek =	no_llseek,
 };
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 7892ac1..c68b3dc 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -20,7 +20,6 @@
 #include <linux/mmc/sdio_func.h>
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index 526682d..c7345db 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -13,7 +13,6 @@
 #include <linux/io.h>
 #include <linux/etherdevice.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
index 9738cad..ee079ab 100644
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -17,7 +17,6 @@
 #include <linux/pci.h>
 #include <linux/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 1409131..fecb89e 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1922,6 +1922,7 @@
 	.mmap = comedi_mmap,
 	.poll = comedi_poll,
 	.fasync = comedi_fasync,
+	.llseek = noop_llseek,
 };
 
 struct class *comedi_class;
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index f8ede11..0345b4c 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -37,7 +37,6 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -692,10 +691,6 @@
 	local->link = link;
 	link->priv = local;
 
-	/* Initialize the pcmcia_device structure */
-	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	cur_dev = link;
 
 	das16cs_pcmcia_config(link);
@@ -715,37 +710,12 @@
 
 
 static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
-	if (cfg->index == 0)
+	if (p_dev->config_index == 0)
 		return -EINVAL;
 
-	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		return pcmcia_request_io(p_dev);
-	}
-
-	return 0;
+	return pcmcia_request_io(p_dev);
 }
 
 static void das16cs_pcmcia_config(struct pcmcia_device *link)
@@ -754,6 +724,9 @@
 
 	dev_dbg(&link->dev, "das16cs_pcmcia_config\n");
 
+	/* Do we need to allocate an interrupt? */
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
 	ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
@@ -763,25 +736,10 @@
 	if (!link->irq)
 		goto failed;
 
-	/*
-	   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.
-	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
-	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %u", link->irq);
-	if (link->resource[0])
-		printk(", io %pR", link->resource[0]);
-	if (link->resource[1])
-		printk(", io %pR", link->resource[1]);
-	printk("\n");
-
 	return;
 
 failed:
@@ -832,9 +790,7 @@
 	.resume = das16cs_pcmcia_resume,
 	.id_table = das16cs_id_table,
 	.owner = THIS_MODULE,
-	.drv = {
-		.name = "cb_das16_cs",
-		},
+	.name = "cb_das16_cs",
 };
 
 static int __init init_das16cs_pcmcia_cs(void)
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index 48d9fb1..0b32a2d 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -48,7 +48,6 @@
 #include "das08.h"
 
 /* pcmcia includes */
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -115,40 +114,15 @@
 static int das08_pcmcia_suspend(struct pcmcia_device *p_dev);
 static int das08_pcmcia_resume(struct pcmcia_device *p_dev);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static int das08_pcmcia_attach(struct pcmcia_device *);
 static void das08_pcmcia_detach(struct pcmcia_device *);
 
-/*
-   You'll also need to prototype all the functions that will actually
-   be used to talk to your device.  See 'memory_cs' for a good example
-   of a fully self-sufficient driver; the other drivers rely more or
-   less on other parts of the kernel.
-*/
-
 struct local_info_t {
 	struct pcmcia_device *link;
 	int stop;
 	struct bus_operations *bus;
 };
 
-/*======================================================================
-
-    das08_pcmcia_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link 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 das08_pcmcia_attach(struct pcmcia_device *link)
 {
 	struct local_info_t *local;
@@ -162,16 +136,6 @@
 	local->link = link;
 	link->priv = local;
 
-	/*
-	   General socket configuration defaults can go here.  In this
-	   client, we assume very little, and rely on the CIS for almost
-	   everything.  In most clients, many details (i.e., number, sizes,
-	   and attributes of IO windows) are fixed by the nature of the
-	   device, and can be hard-wired here.
-	 */
-	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	cur_dev = link;
 
 	das08_pcmcia_config(link);
@@ -179,15 +143,6 @@
 	return 0;
 }				/* das08_pcmcia_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void das08_pcmcia_detach(struct pcmcia_device *link)
 {
 
@@ -203,53 +158,22 @@
 
 
 static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		return pcmcia_request_io(p_dev);
-	}
-	return 0;
+	return pcmcia_request_io(p_dev);
 }
 
-
-/*======================================================================
-
-    das08_pcmcia_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.
-
-======================================================================*/
-
 static void das08_pcmcia_config(struct pcmcia_device *link)
 {
 	int ret;
 
 	dev_dbg(&link->dev, "das08_pcmcia_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
 	ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
@@ -259,25 +183,10 @@
 	if (!link->irq)
 		goto failed;
 
-	/*
-	   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.
-	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
-	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %u", link->irq);
-	if (link->resource[0])
-		printk(", io %pR", link->resource[0]);
-	if (link->resource[1])
-		printk(" & %pR", link->resource[1]);
-	printk("\n");
-
 	return;
 
 failed:
@@ -285,32 +194,12 @@
 
 }				/* das08_pcmcia_config */
 
-/*======================================================================
-
-    After a card is removed, das08_pcmcia_release() will unregister the
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
 static void das08_pcmcia_release(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "das08_pcmcia_release\n");
 	pcmcia_disable_device(link);
 }				/* das08_pcmcia_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-
-======================================================================*/
-
 static int das08_pcmcia_suspend(struct pcmcia_device *link)
 {
 	struct local_info_t *local = link->priv;
@@ -348,9 +237,7 @@
 	.resume = das08_pcmcia_resume,
 	.id_table = das08_cs_id_table,
 	.owner = THIS_MODULE,
-	.drv = {
-		.name = "pcm-das08",
-		},
+	.name = "pcm-das08",
 };
 
 static int __init init_das08_pcmcia_cs(void)
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index cc15666..6b7372e 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -47,7 +47,6 @@
 
 #include <linux/ioport.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -435,47 +434,20 @@
 	return 0;
 };
 
-/* PCMCIA crap -- watch your words, please! */
-
 static void dio700_config(struct pcmcia_device *link);
 static void dio700_release(struct pcmcia_device *link);
 static int dio700_cs_suspend(struct pcmcia_device *p_dev);
 static int dio700_cs_resume(struct pcmcia_device *p_dev);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static int dio700_cs_attach(struct pcmcia_device *);
 static void dio700_cs_detach(struct pcmcia_device *);
 
-/*
-   You'll also need to prototype all the functions that will actually
-   be used to talk to your device.  See 'memory_cs' for a good example
-   of a fully self-sufficient driver; the other drivers rely more or
-   less on other parts of the kernel.
-*/
-
 struct local_info_t {
 	struct pcmcia_device *link;
 	int stop;
 	struct bus_operations *bus;
 };
 
-/*======================================================================
-
-    dio700_cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link 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 dio700_cs_attach(struct pcmcia_device *link)
 {
 	struct local_info_t *local;
@@ -491,16 +463,6 @@
 	local->link = link;
 	link->priv = local;
 
-	/*
-	   General socket configuration defaults can go here.  In this
-	   client, we assume very little, and rely on the CIS for almost
-	   everything.  In most clients, many details (i.e., number, sizes,
-	   and attributes of IO windows) are fixed by the nature of the
-	   device, and can be hard-wired here.
-	 */
-	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	pcmcia_cur_dev = link;
 
 	dio700_config(link);
@@ -508,15 +470,6 @@
 	return 0;
 }				/* dio700_cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void dio700_cs_detach(struct pcmcia_device *link)
 {
 
@@ -532,65 +485,26 @@
 
 }				/* dio700_cs_detach */
 
-/*======================================================================
-
-    dio700_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.
-
-======================================================================*/
-
 static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-		p_dev->conf.Status = CCSR_AUDIO_ENA;
-	}
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev) != 0)
-			return -ENODEV;
-	}
-
-	/* If we got this far, we're cool! */
-	return 0;
+	return pcmcia_request_io(p_dev);
 }
 
 static void dio700_config(struct pcmcia_device *link)
 {
-	win_req_t req;
 	int ret;
 
 	printk(KERN_INFO "ni_daq_700:  cs-config\n");
 
 	dev_dbg(&link->dev, "dio700_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
+		CONF_AUTO_SET_IO;
+
 	ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
@@ -600,25 +514,10 @@
 	if (!link->irq)
 		goto failed;
 
-	/*
-	   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.
-	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret != 0)
 		goto failed;
 
-	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %d", link->irq);
-	if (link->resource[0])
-		printk(", io %pR", link->resource[0]);
-	if (link->resource[1])
-		printk(" & %pR", link->resource[1]);
-	printk("\n");
-
 	return;
 
 failed:
@@ -634,18 +533,6 @@
 	pcmcia_disable_device(link);
 }				/* dio700_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-
-======================================================================*/
-
 static int dio700_cs_suspend(struct pcmcia_device *link)
 {
 	struct local_info_t *local = link->priv;
@@ -685,9 +572,7 @@
 	.resume = dio700_cs_resume,
 	.id_table = dio700_cs_ids,
 	.owner = THIS_MODULE,
-	.drv = {
-		.name = "ni_daq_700",
-		},
+	.name = "ni_daq_700",
 };
 
 static int __init init_dio700_cs(void)
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index 773ae20..c9c2858 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -48,7 +48,6 @@
 
 #include "8255.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -187,47 +186,20 @@
 	return 0;
 };
 
-/* PCMCIA crap -- watch your words! */
-
 static void dio24_config(struct pcmcia_device *link);
 static void dio24_release(struct pcmcia_device *link);
 static int dio24_cs_suspend(struct pcmcia_device *p_dev);
 static int dio24_cs_resume(struct pcmcia_device *p_dev);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static int dio24_cs_attach(struct pcmcia_device *);
 static void dio24_cs_detach(struct pcmcia_device *);
 
-/*
-   You'll also need to prototype all the functions that will actually
-   be used to talk to your device.  See 'memory_cs' for a good example
-   of a fully self-sufficient driver; the other drivers rely more or
-   less on other parts of the kernel.
-*/
-
 struct local_info_t {
 	struct pcmcia_device *link;
 	int stop;
 	struct bus_operations *bus;
 };
 
-/*======================================================================
-
-    dio24_cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link 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 dio24_cs_attach(struct pcmcia_device *link)
 {
 	struct local_info_t *local;
@@ -243,16 +215,6 @@
 	local->link = link;
 	link->priv = local;
 
-	/*
-	   General socket configuration defaults can go here.  In this
-	   client, we assume very little, and rely on the CIS for almost
-	   everything.  In most clients, many details (i.e., number, sizes,
-	   and attributes of IO windows) are fixed by the nature of the
-	   device, and can be hard-wired here.
-	 */
-	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	pcmcia_cur_dev = link;
 
 	dio24_config(link);
@@ -260,15 +222,6 @@
 	return 0;
 }				/* dio24_cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void dio24_cs_detach(struct pcmcia_device *link)
 {
 
@@ -284,54 +237,13 @@
 
 }				/* dio24_cs_detach */
 
-/*======================================================================
-
-    dio24_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.
-
-======================================================================*/
-
 static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-		p_dev->conf.Status = CCSR_AUDIO_ENA;
-	}
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev) != 0)
-			return -ENODEV;
-	}
-
-	/* If we got this far, we're cool! */
-	return 0;
+	return pcmcia_request_io(p_dev);
 }
 
 static void dio24_config(struct pcmcia_device *link)
@@ -342,6 +254,9 @@
 
 	dev_dbg(&link->dev, "dio24_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
+		CONF_AUTO_SET_IO;
+
 	ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
@@ -351,25 +266,10 @@
 	if (!link->irq)
 		goto failed;
 
-	/*
-	   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.
-	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
-	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %d", link->irq);
-	if (link->resource[0])
-		printk(" & %pR", link->resource[0]);
-	if (link->resource[1])
-		printk(" & %pR", link->resource[1]);
-	printk("\n");
-
 	return;
 
 failed:
@@ -385,18 +285,6 @@
 	pcmcia_disable_device(link);
 }				/* dio24_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-
-======================================================================*/
-
 static int dio24_cs_suspend(struct pcmcia_device *link)
 {
 	struct local_info_t *local = link->priv;
@@ -435,9 +323,7 @@
 	.resume = dio24_cs_resume,
 	.id_table = dio24_cs_ids,
 	.owner = THIS_MODULE,
-	.drv = {
-		.name = "ni_daq_dio24",
-		},
+	.name = "ni_daq_dio24",
 };
 
 static int __init init_dio24_cs(void)
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index 68c4ecb..6facbc8 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -71,7 +71,6 @@
 #include "comedi_fc.h"
 #include "ni_labpc.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -153,59 +152,20 @@
 	return labpc_common_attach(dev, iobase, irq, 0);
 }
 
-/*====================================================================*/
-
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card
-   insertion and ejection events.  They are invoked from the dummy
-   event handler.
-
-   Kernel version 2.6.16 upwards uses suspend() and resume() functions
-   instead of an event() function.
-*/
-
 static void labpc_config(struct pcmcia_device *link);
 static void labpc_release(struct pcmcia_device *link);
 static int labpc_cs_suspend(struct pcmcia_device *p_dev);
 static int labpc_cs_resume(struct pcmcia_device *p_dev);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static int labpc_cs_attach(struct pcmcia_device *);
 static void labpc_cs_detach(struct pcmcia_device *);
 
-/*
-   You'll also need to prototype all the functions that will actually
-   be used to talk to your device.  See 'memory_cs' for a good example
-   of a fully self-sufficient driver; the other drivers rely more or
-   less on other parts of the kernel.
-*/
-
 struct local_info_t {
 	struct pcmcia_device *link;
 	int stop;
 	struct bus_operations *bus;
 };
 
-/*======================================================================
-
-    labpc_cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link 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 labpc_cs_attach(struct pcmcia_device *link)
 {
 	struct local_info_t *local;
@@ -219,16 +179,6 @@
 	local->link = link;
 	link->priv = local;
 
-	/*
-	   General socket configuration defaults can go here.  In this
-	   client, we assume very little, and rely on the CIS for almost
-	   everything.  In most clients, many details (i.e., number, sizes,
-	   and attributes of IO windows) are fixed by the nature of the
-	   device, and can be hard-wired here.
-	 */
-	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	pcmcia_cur_dev = link;
 
 	labpc_config(link);
@@ -236,15 +186,6 @@
 	return 0;
 }				/* labpc_cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void labpc_cs_detach(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "labpc_cs_detach\n");
@@ -263,54 +204,13 @@
 
 }				/* labpc_cs_detach */
 
-/*======================================================================
-
-    labpc_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.
-
-======================================================================*/
-
 static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
-		p_dev->conf.Status = CCSR_AUDIO_ENA;
-	}
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev) != 0)
-			return -ENODEV;
-	}
-
-	/* If we got this far, we're cool! */
-	return 0;
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -320,6 +220,9 @@
 
 	dev_dbg(&link->dev, "labpc_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ |
+		CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
+
 	ret = pcmcia_loop_config(link, labpc_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
@@ -329,25 +232,10 @@
 	if (!link->irq)
 		goto failed;
 
-	/*
-	   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.
-	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
-	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %d", link->irq);
-	if (link->resource[0])
-		printk(" & %pR", link->resource[0]);
-	if (link->resource[1])
-		printk(" & %pR", link->resource[1]);
-	printk("\n");
-
 	return;
 
 failed:
@@ -362,18 +250,6 @@
 	pcmcia_disable_device(link);
 }				/* labpc_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-
-======================================================================*/
-
 static int labpc_cs_suspend(struct pcmcia_device *link)
 {
 	struct local_info_t *local = link->priv;
@@ -391,8 +267,6 @@
 	return 0;
 }				/* labpc_cs_resume */
 
-/*====================================================================*/
-
 static struct pcmcia_device_id labpc_cs_ids[] = {
 	/* N.B. These IDs should match those in labpc_cs_boards (ni_labpc.c) */
 	PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0103),	/* daqcard-1200 */
@@ -411,9 +285,7 @@
 	.resume = labpc_cs_resume,
 	.id_table = labpc_cs_ids,
 	.owner = THIS_MODULE,
-	.drv = {
-		.name = "daqcard-1200",
-		},
+	.name = "daqcard-1200",
 };
 
 static int __init init_labpc_cs(void)
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index 1f24263..4956327 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -48,7 +48,6 @@
 #include "ni_stc.h"
 #include "8255.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -263,11 +262,6 @@
 
 static int cs_attach(struct pcmcia_device *link)
 {
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
-	link->resource[0]->end = 16;
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	cur_dev = link;
 
 	mio_cs_config(link);
@@ -301,16 +295,12 @@
 }
 
 
-static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
-				void *priv_data)
+static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int base, ret;
 
-	p_dev->resource[0]->end = cfg->io.win[0].len;
-	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 
 	for (base = 0x000; base < 0x400; base += 0x20) {
 		p_dev->resource[0]->start = base;
@@ -327,6 +317,7 @@
 	int ret;
 
 	DPRINTK("mio_cs_config(link=%p)\n", link);
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
 	ret = pcmcia_loop_config(link, mio_pcmcia_config_loop, NULL);
 	if (ret) {
@@ -337,7 +328,7 @@
 	if (!link->irq)
 		dev_info(&link->dev, "no IRQ available\n");
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 }
 
 static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
@@ -446,9 +437,7 @@
 	.resume = &mio_cs_resume,
 	.id_table = ni_mio_cs_ids,
 	.owner = THIS_MODULE,
-	.drv = {
-		.name = "ni_mio_cs",
-		},
+	.name = "ni_mio_cs",
 };
 
 int init_module(void)
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index bf489d7..ebba9bb 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -50,7 +50,6 @@
 #include "../comedidev.h"
 #include <linux/semaphore.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -969,43 +968,14 @@
 
 ======================================================================*/
 
-/*
-   The event() function is this driver's Card Services event handler.
-   It will be called by Card Services when an appropriate card status
-   event is received.  The config() and release() entry points are
-   used to configure or release a socket, in response to card
-   insertion and ejection events.
-
-   Kernel version 2.6.16 upwards uses suspend() and resume() functions
-   instead of an event() function.
-*/
-
 static void daqp_cs_config(struct pcmcia_device *link);
 static void daqp_cs_release(struct pcmcia_device *link);
 static int daqp_cs_suspend(struct pcmcia_device *p_dev);
 static int daqp_cs_resume(struct pcmcia_device *p_dev);
 
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static int daqp_cs_attach(struct pcmcia_device *);
 static void daqp_cs_detach(struct pcmcia_device *);
 
-/*======================================================================
-
-    daqp_cs_attach() creates an "instance" of the driver, allocating
-    local data structures for one device.  The device is registered
-    with Card Services.
-
-    The dev_link 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 daqp_cs_attach(struct pcmcia_device *link)
 {
 	struct local_info_t *local;
@@ -1031,30 +1001,11 @@
 	local->link = link;
 	link->priv = local;
 
-	/*
-	   General socket configuration defaults can go here.  In this
-	   client, we assume very little, and rely on the CIS for almost
-	   everything.  In most clients, many details (i.e., number, sizes,
-	   and attributes of IO windows) are fixed by the nature of the
-	   device, and can be hard-wired here.
-	 */
-	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	daqp_cs_config(link);
 
 	return 0;
 }				/* daqp_cs_attach */
 
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
-
 static void daqp_cs_detach(struct pcmcia_device *link)
 {
 	struct local_info_t *dev = link->priv;
@@ -1070,45 +1021,11 @@
 
 }				/* daqp_cs_detach */
 
-/*======================================================================
-
-    daqp_cs_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.
-
-======================================================================*/
-
-
-static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
-				void *priv_data)
+static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-	}
-
-	/* This reserves IO space but doesn't actually enable it */
 	return pcmcia_request_io(p_dev);
 }
 
@@ -1118,6 +1035,8 @@
 
 	dev_dbg(&link->dev, "daqp_cs_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
 	ret = pcmcia_loop_config(link, daqp_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
@@ -1128,25 +1047,10 @@
 	if (ret)
 		goto failed;
 
-	/*
-	   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.
-	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
-	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %u", link->irq);
-	if (link->resource[0])
-		printk(" & %pR", link->resource[0]);
-	if (link->resource[1])
-		printk(" & %pR", link->resource[1]);
-	printk("\n");
-
 	return;
 
 failed:
@@ -1161,18 +1065,6 @@
 	pcmcia_disable_device(link);
 }				/* daqp_cs_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-
-======================================================================*/
-
 static int daqp_cs_suspend(struct pcmcia_device *link)
 {
 	struct local_info_t *local = link->priv;
@@ -1212,9 +1104,7 @@
 	.resume = daqp_cs_resume,
 	.id_table = daqp_cs_id_table,
 	.owner = THIS_MODULE,
-	.drv = {
-		.name = "quatech_daqp_cs",
-		},
+	.name = "quatech_daqp_cs",
 };
 
 int __init init_module(void)
diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c
index fbb80f0..af25899 100644
--- a/drivers/staging/crystalhd/crystalhd_lnx.c
+++ b/drivers/staging/crystalhd/crystalhd_lnx.c
@@ -351,6 +351,7 @@
 	.unlocked_ioctl = chd_dec_ioctl,
 	.open    = chd_dec_open,
 	.release = chd_dec_close,
+	.llseek = noop_llseek,
 };
 
 static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp)
diff --git a/drivers/staging/cx25821/Kconfig b/drivers/staging/cx25821/Kconfig
index df7756a..813cb35 100644
--- a/drivers/staging/cx25821/Kconfig
+++ b/drivers/staging/cx25821/Kconfig
@@ -1,6 +1,7 @@
 config VIDEO_CX25821
 	tristate "Conexant cx25821 support"
 	depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
+	depends on BKL # please fix
 	select I2C_ALGOBIT
 	select VIDEO_BTCX
 	select VIDEO_TVEEPROM
diff --git a/drivers/staging/dream/camera/msm_camera.c b/drivers/staging/dream/camera/msm_camera.c
index 81bd71f..de4ab61 100644
--- a/drivers/staging/dream/camera/msm_camera.c
+++ b/drivers/staging/dream/camera/msm_camera.c
@@ -1941,6 +1941,7 @@
 	.open = msm_open,
 	.unlocked_ioctl = msm_ioctl_config,
 	.release = msm_release_config,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations msm_fops_control = {
@@ -1948,6 +1949,7 @@
 	.open = msm_open_control,
 	.unlocked_ioctl = msm_ioctl_control,
 	.release = msm_release_control,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations msm_fops_frame = {
@@ -1956,6 +1958,7 @@
 	.unlocked_ioctl = msm_ioctl_frame,
 	.release = msm_release_frame,
 	.poll = msm_poll_frame,
+	.llseek = no_llseek,
 };
 
 static int msm_setup_cdev(struct msm_device *msm,
diff --git a/drivers/staging/dream/pmem.c b/drivers/staging/dream/pmem.c
index 7d6bbad..3640d1f 100644
--- a/drivers/staging/dream/pmem.c
+++ b/drivers/staging/dream/pmem.c
@@ -180,6 +180,7 @@
 	.mmap = pmem_mmap,
 	.open = pmem_open,
 	.unlocked_ioctl = pmem_ioctl,
+	.llseek = noop_llseek,
 };
 
 static int get_id(struct file *file)
@@ -1204,6 +1205,7 @@
 static struct file_operations debug_fops = {
 	.read = debug_read,
 	.open = debug_open,
+	.llseek = default_llseek,
 };
 #endif
 
diff --git a/drivers/staging/dream/qdsp5/adsp_driver.c b/drivers/staging/dream/qdsp5/adsp_driver.c
index 8197765..28a6f8d 100644
--- a/drivers/staging/dream/qdsp5/adsp_driver.c
+++ b/drivers/staging/dream/qdsp5/adsp_driver.c
@@ -582,6 +582,7 @@
 	.open = adsp_open,
 	.unlocked_ioctl = adsp_ioctl,
 	.release = adsp_release,
+	.llseek = no_llseek,
 };
 
 static void adsp_create(struct adsp_device *adev, const char *name,
diff --git a/drivers/staging/dream/qdsp5/audio_aac.c b/drivers/staging/dream/qdsp5/audio_aac.c
index a373f35..45f4c78 100644
--- a/drivers/staging/dream/qdsp5/audio_aac.c
+++ b/drivers/staging/dream/qdsp5/audio_aac.c
@@ -1030,6 +1030,7 @@
 	.read = audio_read,
 	.write = audio_write,
 	.unlocked_ioctl = audio_ioctl,
+	.llseek = noop_llseek,
 };
 
 struct miscdevice audio_aac_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_amrnb.c b/drivers/staging/dream/qdsp5/audio_amrnb.c
index 07b79d5..402bbc1 100644
--- a/drivers/staging/dream/qdsp5/audio_amrnb.c
+++ b/drivers/staging/dream/qdsp5/audio_amrnb.c
@@ -841,6 +841,7 @@
 	.read = audamrnb_read,
 	.write = audamrnb_write,
 	.unlocked_ioctl = audamrnb_ioctl,
+	.llseek = noop_llseek,
 };
 
 struct miscdevice audio_amrnb_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_evrc.c b/drivers/staging/dream/qdsp5/audio_evrc.c
index ad989ee..24a8926 100644
--- a/drivers/staging/dream/qdsp5/audio_evrc.c
+++ b/drivers/staging/dream/qdsp5/audio_evrc.c
@@ -813,6 +813,7 @@
 	.read = audevrc_read,
 	.write = audevrc_write,
 	.unlocked_ioctl = audevrc_ioctl,
+	.llseek = noop_llseek,
 };
 
 struct miscdevice audio_evrc_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_in.c b/drivers/staging/dream/qdsp5/audio_in.c
index 6ae48e7..b51fa09 100644
--- a/drivers/staging/dream/qdsp5/audio_in.c
+++ b/drivers/staging/dream/qdsp5/audio_in.c
@@ -921,12 +921,14 @@
 	.read		= audio_in_read,
 	.write		= audio_in_write,
 	.unlocked_ioctl	= audio_in_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct file_operations audpre_fops = {
 	.owner          = THIS_MODULE,
 	.open           = audpre_open,
 	.unlocked_ioctl = audpre_ioctl,
+	.llseek		= noop_llseek,
 };
 
 struct miscdevice audio_in_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_mp3.c b/drivers/staging/dream/qdsp5/audio_mp3.c
index 530e1f3..409a19c 100644
--- a/drivers/staging/dream/qdsp5/audio_mp3.c
+++ b/drivers/staging/dream/qdsp5/audio_mp3.c
@@ -948,6 +948,7 @@
 	.read		= audio_read,
 	.write		= audio_write,
 	.unlocked_ioctl	= audio_ioctl,
+	.llseek		= noop_llseek,
 };
 
 struct miscdevice audio_mp3_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_out.c b/drivers/staging/dream/qdsp5/audio_out.c
index 76d7fa5..d20e895 100644
--- a/drivers/staging/dream/qdsp5/audio_out.c
+++ b/drivers/staging/dream/qdsp5/audio_out.c
@@ -807,12 +807,14 @@
 	.read		= audio_read,
 	.write		= audio_write,
 	.unlocked_ioctl	= audio_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct file_operations audpp_fops = {
 	.owner		= THIS_MODULE,
 	.open		= audpp_open,
 	.unlocked_ioctl	= audpp_ioctl,
+	.llseek		= noop_llseek,
 };
 
 struct miscdevice audio_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_qcelp.c b/drivers/staging/dream/qdsp5/audio_qcelp.c
index effa96f3..911bab4 100644
--- a/drivers/staging/dream/qdsp5/audio_qcelp.c
+++ b/drivers/staging/dream/qdsp5/audio_qcelp.c
@@ -824,6 +824,7 @@
 	.read = audqcelp_read,
 	.write = audqcelp_write,
 	.unlocked_ioctl = audqcelp_ioctl,
+	.llseek = noop_llseek,
 };
 
 struct miscdevice audio_qcelp_misc = {
diff --git a/drivers/staging/dream/qdsp5/evlog.h b/drivers/staging/dream/qdsp5/evlog.h
index 922ce67..e5ab86b 100644
--- a/drivers/staging/dream/qdsp5/evlog.h
+++ b/drivers/staging/dream/qdsp5/evlog.h
@@ -123,6 +123,7 @@
 static const struct file_operations ev_log_ops = {
 	.read = ev_log_read,
 	.open = ev_log_open,
+	.llseek = default_llseek,
 };
 
 static int ev_log_init(struct ev_log *log)
diff --git a/drivers/staging/dream/qdsp5/snd.c b/drivers/staging/dream/qdsp5/snd.c
index 037d7ff..e0f2f7b 100644
--- a/drivers/staging/dream/qdsp5/snd.c
+++ b/drivers/staging/dream/qdsp5/snd.c
@@ -247,6 +247,7 @@
 	.open		= snd_open,
 	.release	= snd_release,
 	.unlocked_ioctl	= snd_ioctl,
+	.llseek		= noop_llseek,
 };
 
 struct miscdevice snd_misc = {
diff --git a/drivers/staging/easycap/Kconfig b/drivers/staging/easycap/Kconfig
index bd96f39..9d5fe4d 100644
--- a/drivers/staging/easycap/Kconfig
+++ b/drivers/staging/easycap/Kconfig
@@ -1,6 +1,7 @@
 config EASYCAP
 	tristate "EasyCAP USB ID 05e1:0408 support"
 	depends on USB && VIDEO_DEV
+	depends on BKL # please fix
 
 	---help---
 	  This is an integrated audio/video driver for EasyCAP cards with
diff --git a/drivers/staging/frontier/alphatrack.c b/drivers/staging/frontier/alphatrack.c
index 4e52105..689099b 100644
--- a/drivers/staging/frontier/alphatrack.c
+++ b/drivers/staging/frontier/alphatrack.c
@@ -641,6 +641,7 @@
 	.open = usb_alphatrack_open,
 	.release = usb_alphatrack_release,
 	.poll = usb_alphatrack_poll,
+	.llseek = no_llseek,
 };
 
 /*
diff --git a/drivers/staging/frontier/tranzport.c b/drivers/staging/frontier/tranzport.c
index eed74f0..3d12c17 100644
--- a/drivers/staging/frontier/tranzport.c
+++ b/drivers/staging/frontier/tranzport.c
@@ -767,6 +767,7 @@
 	.open = usb_tranzport_open,
 	.release = usb_tranzport_release,
 	.poll = usb_tranzport_poll,
+	.llseek = no_llseek,
 };
 
 /*
diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig
index e47f683..75fa468 100644
--- a/drivers/staging/go7007/Kconfig
+++ b/drivers/staging/go7007/Kconfig
@@ -1,6 +1,7 @@
 config VIDEO_GO7007
 	tristate "WIS GO7007 MPEG encoder support"
 	depends on VIDEO_DEV && PCI && I2C && INPUT
+	depends on BKL # please fix
 	depends on SND
 	select VIDEOBUF_DMA_SG
 	select VIDEO_IR
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index ff1d247..8284297 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -25,7 +25,7 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <linux/hdreg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -124,6 +124,7 @@
 };
 
 /* Static decl */
+static DEFINE_MUTEX(blkvsc_mutex);
 static int blkvsc_probe(struct device *dev);
 static int blkvsc_remove(struct device *device);
 static void blkvsc_shutdown(struct device *device);
@@ -1309,7 +1310,7 @@
 	DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users,
 		   blkdev->gd->disk_name);
 
-	lock_kernel();
+	mutex_lock(&blkvsc_mutex);
 	spin_lock(&blkdev->lock);
 
 	if (!blkdev->users && blkdev->device_type == DVD_TYPE) {
@@ -1321,7 +1322,7 @@
 	blkdev->users++;
 
 	spin_unlock(&blkdev->lock);
-	unlock_kernel();
+	mutex_unlock(&blkvsc_mutex);
 	return 0;
 }
 
@@ -1332,7 +1333,7 @@
 	DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users,
 		   blkdev->gd->disk_name);
 
-	lock_kernel();
+	mutex_lock(&blkvsc_mutex);
 	spin_lock(&blkdev->lock);
 	if (blkdev->users == 1) {
 		spin_unlock(&blkdev->lock);
@@ -1343,7 +1344,7 @@
 	blkdev->users--;
 
 	spin_unlock(&blkdev->lock);
-	unlock_kernel();
+	mutex_unlock(&blkvsc_mutex);
 	return 0;
 }
 
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index dd4d87a..92a212f 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -349,6 +349,7 @@
 	.release = iio_event_chrdev_release,
 	.open = iio_event_chrdev_open,
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static void iio_event_dev_release(struct device *dev)
diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c
index 6ab578e..1c5f672 100644
--- a/drivers/staging/iio/industrialio-ring.c
+++ b/drivers/staging/iio/industrialio-ring.c
@@ -133,6 +133,7 @@
 	.release = iio_ring_release,
 	.open = iio_ring_open,
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 /**
diff --git a/drivers/staging/lirc/lirc_imon.c b/drivers/staging/lirc/lirc_imon.c
index 6649325..ed5c5fe 100644
--- a/drivers/staging/lirc/lirc_imon.c
+++ b/drivers/staging/lirc/lirc_imon.c
@@ -115,7 +115,8 @@
 	.owner		= THIS_MODULE,
 	.open		= &display_open,
 	.write		= &vfd_write,
-	.release	= &display_close
+	.release	= &display_close,
+	.llseek		= noop_llseek,
 };
 
 /*
diff --git a/drivers/staging/lirc/lirc_it87.c b/drivers/staging/lirc/lirc_it87.c
index ec11c0e..543c5c3b 100644
--- a/drivers/staging/lirc/lirc_it87.c
+++ b/drivers/staging/lirc/lirc_it87.c
@@ -342,6 +342,7 @@
 	.unlocked_ioctl	= lirc_ioctl,
 	.open		= lirc_open,
 	.release	= lirc_close,
+	.llseek		= noop_llseek,
 };
 
 static int set_use_inc(void *data)
diff --git a/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c
index 73166c3..8f72a84 100644
--- a/drivers/staging/lirc/lirc_sasem.c
+++ b/drivers/staging/lirc/lirc_sasem.c
@@ -125,6 +125,7 @@
 	.write		= &vfd_write,
 	.unlocked_ioctl	= &vfd_ioctl,
 	.release	= &vfd_close,
+	.llseek		= noop_llseek,
 };
 
 /* USB Device ID for Sasem USB Control Board */
diff --git a/drivers/staging/lirc/lirc_serial.c b/drivers/staging/lirc/lirc_serial.c
index 9456f8e..8da3824 100644
--- a/drivers/staging/lirc/lirc_serial.c
+++ b/drivers/staging/lirc/lirc_serial.c
@@ -1058,6 +1058,7 @@
 	.poll		= lirc_dev_fop_poll,
 	.open		= lirc_dev_fop_open,
 	.release	= lirc_dev_fop_close,
+	.llseek		= no_llseek,
 };
 
 static struct lirc_driver driver = {
diff --git a/drivers/staging/lirc/lirc_sir.c b/drivers/staging/lirc/lirc_sir.c
index eb08fa7..2478871 100644
--- a/drivers/staging/lirc/lirc_sir.c
+++ b/drivers/staging/lirc/lirc_sir.c
@@ -459,6 +459,7 @@
 	.unlocked_ioctl	= lirc_ioctl,
 	.open		= lirc_dev_fop_open,
 	.release	= lirc_dev_fop_close,
+	.llseek		= no_llseek,
 };
 
 static int set_use_inc(void *data)
diff --git a/drivers/staging/memrar/memrar_handler.c b/drivers/staging/memrar/memrar_handler.c
index a98b3f1..cfcaa8e 100644
--- a/drivers/staging/memrar/memrar_handler.c
+++ b/drivers/staging/memrar/memrar_handler.c
@@ -890,6 +890,7 @@
 	.mmap           = memrar_mmap,
 	.open           = memrar_open,
 	.release        = memrar_release,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice memrar_miscdev = {
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index 3221814..6885f9a 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -1631,6 +1631,7 @@
 	.read    = keypad_read,		/* read */
 	.open    = keypad_open,		/* open */
 	.release = keypad_release,	/* close */
+	.llseek  = default_llseek,
 };
 
 static struct miscdevice keypad_dev = {
diff --git a/drivers/staging/spectra/ffsport.c b/drivers/staging/spectra/ffsport.c
index fa21a0f..c7932da 100644
--- a/drivers/staging/spectra/ffsport.c
+++ b/drivers/staging/spectra/ffsport.c
@@ -27,7 +27,6 @@
 #include <linux/kthread.h>
 #include <linux/log2.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 
 /**** Helper functions used for Div, Remainder operation on u64 ****/
@@ -590,14 +589,16 @@
 	return -ENOTTY;
 }
 
+static DEFINE_MUTEX(ffsport_mutex);
+
 int GLOB_SBD_unlocked_ioctl(struct block_device *bdev, fmode_t mode,
 		unsigned int cmd, unsigned long arg)
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ffsport_mutex);
 	ret = GLOB_SBD_ioctl(bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ffsport_mutex);
 
 	return ret;
 }
diff --git a/drivers/staging/ti-st/st.h b/drivers/staging/ti-st/st.h
index 9952579..1b3060e 100644
--- a/drivers/staging/ti-st/st.h
+++ b/drivers/staging/ti-st/st.h
@@ -80,5 +80,4 @@
 extern long st_register(struct st_proto_s *);
 extern long st_unregister(enum proto_type);
 
-extern struct platform_device *st_get_plat_device(void);
 #endif /* ST_H */
diff --git a/drivers/staging/ti-st/st_core.c b/drivers/staging/ti-st/st_core.c
index 063c9b1..b85d8bf 100644
--- a/drivers/staging/ti-st/st_core.c
+++ b/drivers/staging/ti-st/st_core.c
@@ -38,7 +38,6 @@
 #include "st_ll.h"
 #include "st.h"
 
-#define VERBOSE
 /* strings to be used for rfkill entries and by
  * ST Core to be used for sysfs debug entry
  */
@@ -581,7 +580,7 @@
 	long err = 0;
 	unsigned long flags = 0;
 
-	st_kim_ref(&st_gdata);
+	st_kim_ref(&st_gdata, 0);
 	pr_info("%s(%d) ", __func__, new_proto->type);
 	if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL
 	    || new_proto->reg_complete_cb == NULL) {
@@ -713,7 +712,7 @@
 
 	pr_debug("%s: %d ", __func__, type);
 
-	st_kim_ref(&st_gdata);
+	st_kim_ref(&st_gdata, 0);
 	if (type < ST_BT || type >= ST_MAX) {
 		pr_err(" protocol %d not supported", type);
 		return -EPROTONOSUPPORT;
@@ -767,7 +766,7 @@
 #endif
 	long len;
 
-	st_kim_ref(&st_gdata);
+	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");
@@ -818,7 +817,7 @@
 	struct st_data_s *st_gdata;
 	pr_info("%s ", __func__);
 
-	st_kim_ref(&st_gdata);
+	st_kim_ref(&st_gdata, 0);
 	st_gdata->tty = tty;
 	tty->disc_data = st_gdata;
 
diff --git a/drivers/staging/ti-st/st_core.h b/drivers/staging/ti-st/st_core.h
index e0c32d1..8601320 100644
--- a/drivers/staging/ti-st/st_core.h
+++ b/drivers/staging/ti-st/st_core.h
@@ -117,7 +117,7 @@
 void st_core_exit(struct st_data_s *);
 
 /* ask for reference from KIM */
-void st_kim_ref(struct st_data_s **);
+void st_kim_ref(struct st_data_s **, int);
 
 #define GPS_STUB_TEST
 #ifdef GPS_STUB_TEST
diff --git a/drivers/staging/ti-st/st_kim.c b/drivers/staging/ti-st/st_kim.c
index b4a6c7f..9e99463 100644
--- a/drivers/staging/ti-st/st_kim.c
+++ b/drivers/staging/ti-st/st_kim.c
@@ -72,11 +72,26 @@
 	PROTO_ENTRY(ST_GPS, "GPS"),
 };
 
+#define MAX_ST_DEVICES	3	/* Imagine 1 on each UART for now */
+struct platform_device *st_kim_devices[MAX_ST_DEVICES];
 
 /**********************************************************************/
 /* internal functions */
 
 /**
+ * st_get_plat_device -
+ *	function which returns the reference to the platform device
+ *	requested by id. As of now only 1 such device exists (id=0)
+ *	the context requesting for reference can get the id to be
+ *	requested by a. The protocol driver which is registering or
+ *	b. the tty device which is opened.
+ */
+static struct platform_device *st_get_plat_device(int id)
+{
+	return st_kim_devices[id];
+}
+
+/**
  * validate_firmware_response -
  *	function to return whether the firmware response was proper
  *	in case of error don't complete so that waiting for proper
@@ -353,7 +368,7 @@
 	struct kim_data_s	*kim_gdata;
 	pr_info(" %s ", __func__);
 
-	kim_pdev = st_get_plat_device();
+	kim_pdev = st_get_plat_device(0);
 	kim_gdata = dev_get_drvdata(&kim_pdev->dev);
 
 	if (kim_gdata->gpios[type] == -1) {
@@ -574,12 +589,12 @@
  *	This would enable multiple such platform devices to exist
  *	on a given platform
  */
-void st_kim_ref(struct st_data_s **core_data)
+void st_kim_ref(struct st_data_s **core_data, int id)
 {
 	struct platform_device	*pdev;
 	struct kim_data_s	*kim_gdata;
 	/* get kim_gdata reference from platform device */
-	pdev = st_get_plat_device();
+	pdev = st_get_plat_device(id);
 	kim_gdata = dev_get_drvdata(&pdev->dev);
 	*core_data = kim_gdata->core_data;
 }
@@ -623,6 +638,7 @@
 	long *gpios = pdev->dev.platform_data;
 	struct kim_data_s	*kim_gdata;
 
+	st_kim_devices[pdev->id] = pdev;
 	kim_gdata = kzalloc(sizeof(struct kim_data_s), GFP_ATOMIC);
 	if (!kim_gdata) {
 		pr_err("no mem to allocate");
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
index 7ee8949..7b3a7d0 100644
--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
+++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
@@ -144,6 +144,7 @@
 	.release = bridge_release,
 	.unlocked_ioctl = bridge_ioctl,
 	.mmap = bridge_mmap,
+	.llseek = noop_llseek,
 };
 
 #ifdef CONFIG_PM
diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig
index c725356..de7ebb9 100644
--- a/drivers/staging/tm6000/Kconfig
+++ b/drivers/staging/tm6000/Kconfig
@@ -1,6 +1,6 @@
 config VIDEO_TM6000
 	tristate "TV Master TM5600/6000/6010 driver"
-	depends on VIDEO_DEV && I2C && INPUT && USB && EXPERIMENTAL
+	depends on VIDEO_DEV && I2C && INPUT && IR_CORE && USB && EXPERIMENTAL
 	select VIDEO_TUNER
 	select MEDIA_TUNER_XC2028
 	select MEDIA_TUNER_XC5000
diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c
index 32f7a0a..54f7667 100644
--- a/drivers/staging/tm6000/tm6000-input.c
+++ b/drivers/staging/tm6000/tm6000-input.c
@@ -46,7 +46,7 @@
 	}
 
 struct tm6000_ir_poll_result {
-	u8 rc_data[4];
+	u16 rc_data;
 };
 
 struct tm6000_IR {
@@ -60,9 +60,9 @@
 	int			polling;
 	struct delayed_work	work;
 	u8			wait:1;
+	u8			key:1;
 	struct urb		*int_urb;
 	u8			*urb_data;
-	u8			key:1;
 
 	int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *);
 
@@ -122,13 +122,14 @@
 
 	if (urb->status != 0)
 		printk(KERN_INFO "not ready\n");
-	else if (urb->actual_length > 0)
+	else if (urb->actual_length > 0) {
 		memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length);
 
-	dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0],
-	ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]);
+		dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0],
+			ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]);
 
-	ir->key = 1;
+		ir->key = 1;
+	}
 
 	rc = usb_submit_urb(urb, GFP_ATOMIC);
 }
@@ -140,30 +141,47 @@
 	int rc;
 	u8 buf[2];
 
-	if (ir->wait && !&dev->int_in) {
-		poll_result->rc_data[0] = 0xff;
+	if (ir->wait && !&dev->int_in)
 		return 0;
-	}
 
 	if (&dev->int_in) {
-		poll_result->rc_data[0] = ir->urb_data[0];
-		poll_result->rc_data[1] = ir->urb_data[1];
+		if (ir->ir.ir_type == IR_TYPE_RC5)
+			poll_result->rc_data = ir->urb_data[0];
+		else
+			poll_result->rc_data = ir->urb_data[0] | ir->urb_data[1] << 8;
 	} else {
 		tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
 		msleep(10);
 		tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
 		msleep(10);
 
-		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
-		 USB_RECIP_DEVICE, REQ_02_GET_IR_CODE, 0, 0, buf, 1);
+		if (ir->ir.ir_type == IR_TYPE_RC5) {
+			rc = tm6000_read_write_usb(dev, USB_DIR_IN |
+				USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				REQ_02_GET_IR_CODE, 0, 0, buf, 1);
 
-		msleep(10);
+			msleep(10);
 
-		dprintk("read data=%02x\n", buf[0]);
-		if (rc < 0)
-			return rc;
+			dprintk("read data=%02x\n", buf[0]);
+			if (rc < 0)
+				return rc;
 
-		poll_result->rc_data[0] = buf[0];
+			poll_result->rc_data = buf[0];
+		} else {
+			rc = tm6000_read_write_usb(dev, USB_DIR_IN |
+				USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				REQ_02_GET_IR_CODE, 0, 0, buf, 2);
+
+			msleep(10);
+
+			dprintk("read data=%04x\n", buf[0] | buf[1] << 8);
+			if (rc < 0)
+				return rc;
+
+			poll_result->rc_data = buf[0] | buf[1] << 8;
+		}
+		if ((poll_result->rc_data & 0x00ff) != 0xff)
+			ir->key = 1;
 	}
 	return 0;
 }
@@ -180,12 +198,11 @@
 		return;
 	}
 
-	dprintk("ir->get_key result data=%02x %02x\n",
-		poll_result.rc_data[0], poll_result.rc_data[1]);
+	dprintk("ir->get_key result data=%04x\n", poll_result.rc_data);
 
-	if (poll_result.rc_data[0] != 0xff && ir->key == 1) {
+	if (ir->key) {
 		ir_input_keydown(ir->input->input_dev, &ir->ir,
-			poll_result.rc_data[0] | poll_result.rc_data[1] << 8);
+				(u32)poll_result.rc_data);
 
 		ir_input_nokey(ir->input->input_dev, &ir->ir);
 		ir->key = 0;
diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig
index 2c1d10a..b11ec37 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
+	depends on USB && NET && EXPERIMENTAL && BKL
 	default N
 	---help---
 	  This enables pushing USB packets over IP to allow remote
diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c
index 19c3354..6555891 100644
--- a/drivers/staging/wlags49_h2/wl_cs.c
+++ b/drivers/staging/wlags49_h2/wl_cs.c
@@ -83,7 +83,6 @@
 #include <linux/if_arp.h>
 #include <linux/ioport.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -147,10 +146,9 @@
 
 	link->resource[0]->end  = HCF_NUM_IO_PORTS;
 	link->resource[0]->flags= IO_DATA_PATH_WIDTH_16;
-	link->conf.Attributes   = CONF_ENABLE_IRQ;
-	link->conf.IntType      = INT_MEMORY_AND_IO;
-	link->conf.ConfigIndex  = 5;
-	link->conf.Present      = PRESENT_OPTION;
+	link->config_flags     |= CONF_ENABLE_IRQ;
+	link->config_index      = 5;
+	link->config_regs       = PRESENT_OPTION;
 
 	link->priv = dev;
 	lp = wl_priv(dev);
@@ -165,27 +163,6 @@
 
 
 
-/*******************************************************************************
- *	wl_adapter_detach()
- *******************************************************************************
- *
- *  DESCRIPTION:
- *
- *      This deletes a driver "instance". The device is de-registered with Card
- *  Services. If it has been released, then the net device is unregistered, and
- *  all local data structures are freed. Otherwise, the structures will be
- *  freed when the device is released.
- *
- *  PARAMETERS:
- *
- *      link    - pointer to the dev_link_t structure representing the device to
- *                detach
- *
- *  RETURNS:
- *
- *      N/A
- *
- ******************************************************************************/
 static void wl_adapter_detach(struct pcmcia_device *link)
 {
 	struct net_device   *dev = link->priv;
@@ -209,26 +186,6 @@
 /*============================================================================*/
 
 
-/*******************************************************************************
- *	wl_adapter_release()
- *******************************************************************************
- *
- *  DESCRIPTION:
- *
- *      After a card is removed, this routine will release the PCMCIA
- *  configuration. If the device is still open, this will be postponed until it
- *  is closed.
- *
- *  PARAMETERS:
- *
- *      arg - a u_long representing a pointer to a dev_link_t structure for the
- *            device to be released.
- *
- *  RETURNS:
- *
- *      N/A
- *
- ******************************************************************************/
 void wl_adapter_release(struct pcmcia_device *link)
 {
 	DBG_FUNC("wl_adapter_release");
@@ -268,26 +225,6 @@
 	return 0;
 } /* wl_adapter_resume */
 
-/*******************************************************************************
- *	wl_adapter_insert()
- *******************************************************************************
- *
- *  DESCRIPTION:
- *
- *      wl_adapter_insert() is scheduled to run after a CARD_INSERTION event is
- *  received, to configure the PCMCIA socket, and to make the ethernet device
- *  available to the system.
- *
- *  PARAMETERS:
- *
- *      link    - pointer to the dev_link_t structure representing the device to
- *                insert
- *
- *  RETURNS:
- *
- *      N/A
- *
- ******************************************************************************/
 void wl_adapter_insert(struct pcmcia_device *link)
 {
 	struct net_device *dev;
@@ -302,7 +239,7 @@
 	dev     = link->priv;
 
 	/* Do we need to allocate an interrupt? */
-	link->conf.Attributes |= CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 	link->io_lines = 6;
 
 	ret = pcmcia_request_io(link);
@@ -313,7 +250,7 @@
 	if (ret != 0)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret != 0)
 		goto failed;
 
@@ -457,9 +394,7 @@
 
 static struct pcmcia_driver wlags49_driver = {
 	.owner	    = THIS_MODULE,
-	.drv	    = {
-		.name = DRIVER_NAME,
-	},
+	.name	    = DRIVER_NAME,
 	.probe	    = wl_adapter_attach,
 	.remove	    = wl_adapter_detach,
 	.id_table   = wl_adapter_ids,
diff --git a/drivers/staging/wlags49_h2/wl_internal.h b/drivers/staging/wlags49_h2/wl_internal.h
index 02f0a20..cd129b3 100644
--- a/drivers/staging/wlags49_h2/wl_internal.h
+++ b/drivers/staging/wlags49_h2/wl_internal.h
@@ -69,7 +69,6 @@
  ******************************************************************************/
 #include <linux/version.h>
 #ifdef BUS_PCMCIA
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
diff --git a/drivers/staging/wlags49_h2/wl_main.c b/drivers/staging/wlags49_h2/wl_main.c
index 88d0d47..8e3536a 100644
--- a/drivers/staging/wlags49_h2/wl_main.c
+++ b/drivers/staging/wlags49_h2/wl_main.c
@@ -414,25 +414,6 @@
 #endif /* HCF_STA */
 
 
-/*******************************************************************************
- *	wl_insert()
- *******************************************************************************
- *
- *  DESCRIPTION:
- *
- *      wl_insert() is scheduled to run after a CARD_INSERTION event is
- *  received, to configure the PCMCIA socket, and to make the ethernet device
- *  available to the system.
- *
- *  PARAMETERS:
- *
- *      dev - a pointer to the net_device struct of the wireless device
- *
- *  RETURNS:
- *
- *      TRUE or FALSE
- *
- ******************************************************************************/
 int wl_insert( struct net_device *dev )
 {
 	int                     result = 0;
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index b53deee..0d236f4 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -257,7 +257,7 @@
 #include <linux/fs.h>		/* everything... */
 #include <linux/errno.h>	/* error codes */
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
@@ -277,6 +277,7 @@
 #define TYPE(inode) (iminor(inode) >> 4)
 #define NUM(inode) (iminor(inode) & 0xf)
 
+static DEFINE_MUTEX(ixj_mutex);
 static int ixjdebug;
 static int hertz = HZ;
 static int samplerate = 100;
@@ -6655,9 +6656,9 @@
 static long ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&ixj_mutex);
 	ret = do_ixj_ioctl(file_p, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ixj_mutex);
 	return ret;
 }
 
@@ -6676,7 +6677,8 @@
         .poll           = ixj_poll,
         .unlocked_ioctl = ixj_ioctl,
         .release        = ixj_release,
-        .fasync         = ixj_fasync
+        .fasync         = ixj_fasync,
+        .llseek	 = default_llseek,
 };
 
 static int ixj_linetest(IXJ *j)
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index a1900e5..d005b9e 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -8,7 +8,6 @@
 #include <linux/errno.h>	/* error codes */
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -32,9 +31,6 @@
 {
 	dev_dbg(&p_dev->dev, "ixj_attach()\n");
 	/* Create new ixj device */
-	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 	p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
 	if (!p_dev->priv) {
 		return -ENOMEM;
@@ -111,40 +107,31 @@
 	return;
 }
 
-static int ixj_config_check(struct pcmcia_device *p_dev,
-			    cistpl_cftable_entry_t *cfg,
-			    cistpl_cftable_entry_t *dflt,
-			    unsigned int vcc,
-			    void *priv_data)
+static int ixj_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		p_dev->io_lines = 3;
-		if (io->nwin == 2) {
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -ENODEV;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->io_lines = 3;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int ixj_config(struct pcmcia_device * link)
 {
 	IXJ *j;
 	ixj_info_t *info;
-	cistpl_cftable_entry_t dflt = { 0 };
 
 	info = link->priv;
 	dev_dbg(&link->dev, "ixj_config\n");
 
-	if (pcmcia_loop_config(link, ixj_config_check, &dflt))
+	link->config_flags = CONF_AUTO_SET_IO;
+
+	if (pcmcia_loop_config(link, ixj_config_check, NULL))
 		goto failed;
 
-	if (pcmcia_request_configuration(link, &link->conf))
+	if (pcmcia_enable_device(link))
 		goto failed;
 
 	/*
@@ -178,9 +165,7 @@
 
 static struct pcmcia_driver ixj_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "ixj_cs",
-	},
+	.name		= "ixj_cs",
 	.probe		= ixj_probe,
 	.remove		= ixj_detach,
 	.id_table	= ixj_ids,
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c
index f3873f6..1915af2 100644
--- a/drivers/telephony/phonedev.c
+++ b/drivers/telephony/phonedev.c
@@ -130,6 +130,7 @@
 {
 	.owner		= THIS_MODULE,
 	.open		= phone_open,
+	.llseek		= noop_llseek,
 };
 
 /*
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index bff1afb..a858d2b 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -23,9 +23,10 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kobject.h>
+#include <linux/cdev.h>
 #include <linux/uio_driver.h>
 
-#define UIO_MAX_DEVICES 255
+#define UIO_MAX_DEVICES		(1U << MINORBITS)
 
 struct uio_device {
 	struct module		*owner;
@@ -41,15 +42,10 @@
 };
 
 static int uio_major;
+static struct cdev *uio_cdev;
 static DEFINE_IDR(uio_idr);
 static const struct file_operations uio_fops;
 
-/* UIO class infrastructure */
-static struct uio_class {
-	struct kref kref;
-	struct class *class;
-} *uio_class;
-
 /* Protect idr accesses */
 static DEFINE_MUTEX(minor_lock);
 
@@ -232,45 +228,34 @@
 			 struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
-	if (idev)
-		return sprintf(buf, "%s\n", idev->info->name);
-	else
-		return -ENODEV;
+	return sprintf(buf, "%s\n", idev->info->name);
 }
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
 static ssize_t show_version(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
-	if (idev)
-		return sprintf(buf, "%s\n", idev->info->version);
-	else
-		return -ENODEV;
+	return sprintf(buf, "%s\n", idev->info->version);
 }
-static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
 
 static ssize_t show_event(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
-	if (idev)
-		return sprintf(buf, "%u\n",
-				(unsigned int)atomic_read(&idev->event));
-	else
-		return -ENODEV;
+	return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event));
 }
-static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
 
-static struct attribute *uio_attrs[] = {
-	&dev_attr_name.attr,
-	&dev_attr_version.attr,
-	&dev_attr_event.attr,
-	NULL,
+static struct device_attribute uio_class_attributes[] = {
+	__ATTR(name, S_IRUGO, show_name, NULL),
+	__ATTR(version, S_IRUGO, show_version, NULL),
+	__ATTR(event, S_IRUGO, show_event, NULL),
+	{}
 };
 
-static struct attribute_group uio_attr_grp = {
-	.attrs = uio_attrs,
+/* UIO class infrastructure */
+static struct class uio_class = {
+	.name = "uio",
+	.dev_attrs = uio_class_attributes,
 };
 
 /*
@@ -287,10 +272,6 @@
 	struct uio_port *port;
 	struct uio_portio *portio;
 
-	ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp);
-	if (ret)
-		goto err_group;
-
 	for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
 		mem = &idev->info->mem[mi];
 		if (mem->size == 0)
@@ -358,8 +339,6 @@
 		kobject_put(&map->kobj);
 	}
 	kobject_put(idev->map_dir);
-	sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
-err_group:
 	dev_err(idev->dev, "error creating sysfs files (%d)\n", ret);
 	return ret;
 }
@@ -385,8 +364,6 @@
 		kobject_put(&port->portio->kobj);
 	}
 	kobject_put(idev->portio_dir);
-
-	sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
 }
 
 static int uio_get_minor(struct uio_device *idev)
@@ -525,7 +502,7 @@
 	struct uio_listener *listener = filep->private_data;
 	struct uio_device *idev = listener->dev;
 
-	if (idev->info->irq == UIO_IRQ_NONE)
+	if (!idev->info->irq)
 		return -EIO;
 
 	poll_wait(filep, &idev->wait, wait);
@@ -543,7 +520,7 @@
 	ssize_t retval;
 	s32 event_count;
 
-	if (idev->info->irq == UIO_IRQ_NONE)
+	if (!idev->info->irq)
 		return -EIO;
 
 	if (count != sizeof(s32))
@@ -591,7 +568,7 @@
 	ssize_t retval;
 	s32 irq_on;
 
-	if (idev->info->irq == UIO_IRQ_NONE)
+	if (!idev->info->irq)
 		return -EIO;
 
 	if (count != sizeof(s32))
@@ -740,72 +717,77 @@
 	.mmap		= uio_mmap,
 	.poll		= uio_poll,
 	.fasync		= uio_fasync,
+	.llseek		= noop_llseek,
 };
 
 static int uio_major_init(void)
 {
-	uio_major = register_chrdev(0, "uio", &uio_fops);
-	if (uio_major < 0)
-		return uio_major;
-	return 0;
+	static const char name[] = "uio";
+	struct cdev *cdev = NULL;
+	dev_t uio_dev = 0;
+	int result;
+
+	result = alloc_chrdev_region(&uio_dev, 0, UIO_MAX_DEVICES, name);
+	if (result)
+		goto out;
+
+	result = -ENOMEM;
+	cdev = cdev_alloc();
+	if (!cdev)
+		goto out_unregister;
+
+	cdev->owner = THIS_MODULE;
+	cdev->ops = &uio_fops;
+	kobject_set_name(&cdev->kobj, "%s", name);
+
+	result = cdev_add(cdev, uio_dev, UIO_MAX_DEVICES);
+	if (result)
+		goto out_put;
+
+	uio_major = MAJOR(uio_dev);
+	uio_cdev = cdev;
+	result = 0;
+out:
+	return result;
+out_put:
+	kobject_put(&cdev->kobj);
+out_unregister:
+	unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES);
+	goto out;
 }
 
 static void uio_major_cleanup(void)
 {
-	unregister_chrdev(uio_major, "uio");
+	unregister_chrdev_region(MKDEV(uio_major, 0), UIO_MAX_DEVICES);
+	cdev_del(uio_cdev);
 }
 
 static int init_uio_class(void)
 {
-	int ret = 0;
-
-	if (uio_class != NULL) {
-		kref_get(&uio_class->kref);
-		goto exit;
-	}
+	int ret;
 
 	/* This is the first time in here, set everything up properly */
 	ret = uio_major_init();
 	if (ret)
 		goto exit;
 
-	uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL);
-	if (!uio_class) {
-		ret = -ENOMEM;
-		goto err_kzalloc;
-	}
-
-	kref_init(&uio_class->kref);
-	uio_class->class = class_create(THIS_MODULE, "uio");
-	if (IS_ERR(uio_class->class)) {
-		ret = IS_ERR(uio_class->class);
-		printk(KERN_ERR "class_create failed for uio\n");
-		goto err_class_create;
+	ret = class_register(&uio_class);
+	if (ret) {
+		printk(KERN_ERR "class_register failed for uio\n");
+		goto err_class_register;
 	}
 	return 0;
 
-err_class_create:
-	kfree(uio_class);
-	uio_class = NULL;
-err_kzalloc:
+err_class_register:
 	uio_major_cleanup();
 exit:
 	return ret;
 }
 
-static void release_uio_class(struct kref *kref)
+static void release_uio_class(void)
 {
-	/* Ok, we cheat as we know we only have one uio_class */
-	class_destroy(uio_class->class);
-	kfree(uio_class);
+	class_unregister(&uio_class);
 	uio_major_cleanup();
-	uio_class = NULL;
-}
-
-static void uio_class_destroy(void)
-{
-	if (uio_class)
-		kref_put(&uio_class->kref, release_uio_class);
 }
 
 /**
@@ -828,10 +810,6 @@
 
 	info->uio_dev = NULL;
 
-	ret = init_uio_class();
-	if (ret)
-		return ret;
-
 	idev = kzalloc(sizeof(*idev), GFP_KERNEL);
 	if (!idev) {
 		ret = -ENOMEM;
@@ -847,7 +825,7 @@
 	if (ret)
 		goto err_get_minor;
 
-	idev->dev = device_create(uio_class->class, parent,
+	idev->dev = device_create(&uio_class, parent,
 				  MKDEV(uio_major, idev->minor), idev,
 				  "uio%d", idev->minor);
 	if (IS_ERR(idev->dev)) {
@@ -862,9 +840,9 @@
 
 	info->uio_dev = idev;
 
-	if (idev->info->irq >= 0) {
-		ret = request_irq(idev->info->irq, uio_interrupt,
-				  idev->info->irq_flags, idev->info->name, idev);
+	if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
+		ret = request_irq(info->irq, uio_interrupt,
+				  info->irq_flags, info->name, idev);
 		if (ret)
 			goto err_request_irq;
 	}
@@ -874,13 +852,12 @@
 err_request_irq:
 	uio_dev_del_attributes(idev);
 err_uio_dev_add_attributes:
-	device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
+	device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
 err_device_create:
 	uio_free_minor(idev);
 err_get_minor:
 	kfree(idev);
 err_kzalloc:
-	uio_class_destroy();
 	return ret;
 }
 EXPORT_SYMBOL_GPL(__uio_register_device);
@@ -901,15 +878,13 @@
 
 	uio_free_minor(idev);
 
-	if (info->irq >= 0)
+	if (info->irq && (info->irq != UIO_IRQ_CUSTOM))
 		free_irq(info->irq, idev);
 
 	uio_dev_del_attributes(idev);
 
-	dev_set_drvdata(idev->dev, NULL);
-	device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
+	device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
 	kfree(idev);
-	uio_class_destroy();
 
 	return;
 }
@@ -917,11 +892,12 @@
 
 static int __init uio_init(void)
 {
-	return 0;
+	return init_uio_class();
 }
 
 static void __exit uio_exit(void)
 {
+	release_uio_class();
 }
 
 module_init(uio_init)
diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c
index 85c9884..fc22e1e 100644
--- a/drivers/uio/uio_pci_generic.c
+++ b/drivers/uio/uio_pci_generic.c
@@ -128,12 +128,6 @@
 	struct uio_pci_generic_dev *gdev;
 	int err;
 
-	if (!pdev->irq) {
-		dev_warn(&pdev->dev, "No IRQ assigned to device: "
-			 "no support for interrupts?\n");
-		return -ENODEV;
-	}
-
 	err = pci_enable_device(pdev);
 	if (err) {
 		dev_err(&pdev->dev, "%s: pci_enable_device failed: %d\n",
@@ -141,6 +135,13 @@
 		return err;
 	}
 
+	if (!pdev->irq) {
+		dev_warn(&pdev->dev, "No IRQ assigned to device: "
+			 "no support for interrupts?\n");
+		pci_disable_device(pdev);
+		return -ENODEV;
+	}
+
 	err = verify_pci_2_3(pdev);
 	if (err)
 		goto err_verify;
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 4aa00e6..67eb377 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -59,6 +59,7 @@
 config USB_ARCH_HAS_EHCI
 	boolean
 	default y if PPC_83xx
+	default y if PPC_MPC512x
 	default y if SOC_AU1200
 	default y if ARCH_IXP4XX
 	default y if ARCH_W90X900
diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile
index 4c4a776..a5d792e 100644
--- a/drivers/usb/atm/Makefile
+++ b/drivers/usb/atm/Makefile
@@ -2,12 +2,10 @@
 # Makefile for USB ATM/xDSL drivers
 #
 
+ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
+
 obj-$(CONFIG_USB_CXACRU)	+= cxacru.o
 obj-$(CONFIG_USB_SPEEDTOUCH)	+= speedtch.o
 obj-$(CONFIG_USB_UEAGLEATM)	+= ueagle-atm.o
 obj-$(CONFIG_USB_ATM)		+= usbatm.o
 obj-$(CONFIG_USB_XUSBATM)	+= xusbatm.o
-
-ifeq ($(CONFIG_USB_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 5af23cc..f383cb4 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -1344,8 +1344,24 @@
 	.tx_padding	= 11,
 };
 
-static int cxacru_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static int cxacru_usb_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
 {
+	struct usb_device *usb_dev = interface_to_usbdev(intf);
+	char buf[15];
+
+	/* Avoid ADSL routers (cx82310_eth).
+	 * Abort if bDeviceClass is 0xff and iProduct is "USB NET CARD".
+	 */
+	if (usb_dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC
+			&& usb_string(usb_dev, usb_dev->descriptor.iProduct,
+				buf, sizeof(buf)) > 0) {
+		if (!strcmp(buf, "USB NET CARD")) {
+			dev_info(&intf->dev, "ignoring cx82310_eth device\n");
+			return -ENODEV;
+		}
+	}
+
 	return usbatm_usb_probe(intf, id, &cxacru_driver);
 }
 
diff --git a/drivers/usb/c67x00/Makefile b/drivers/usb/c67x00/Makefile
index 868bc41..b121868 100644
--- a/drivers/usb/c67x00/Makefile
+++ b/drivers/usb/c67x00/Makefile
@@ -2,8 +2,8 @@
 # Makefile for Cypress C67X00 USB Controller
 #
 
-ccflags-$(CONFIG_USB_DEBUG)		+= -DDEBUG
+ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 
-obj-$(CONFIG_USB_C67X00_HCD)		+= c67x00.o
+obj-$(CONFIG_USB_C67X00_HCD)	+= c67x00.o
 
-c67x00-objs := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o
+c67x00-y := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index bc62fae..d6ede98 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1614,7 +1614,7 @@
 	/* Support Lego NXT using pbLua firmware */
 	{ USB_DEVICE(0x0694, 0xff00),
 	.driver_info = NOT_A_MODEM,
-       	},
+	},
 
 	/* control interfaces without any protocol set */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 094c76b..6ee4451 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -584,7 +584,8 @@
 	.open =		wdm_open,
 	.flush =	wdm_flush,
 	.release =	wdm_release,
-	.poll =		wdm_poll
+	.poll =		wdm_poll,
+	.llseek =	noop_llseek,
 };
 
 static struct usb_class_driver wdm_class = {
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index e325162..9eca405 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -1043,6 +1043,7 @@
 	.compat_ioctl =		usblp_ioctl,
 	.open =		usblp_open,
 	.release =	usblp_release,
+	.llseek =	noop_llseek,
 };
 
 static char *usblp_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 3e7c1b8..6a54634 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -987,6 +987,7 @@
 	.open		= usbtmc_open,
 	.release	= usbtmc_release,
 	.unlocked_ioctl	= usbtmc_ioctl,
+	.llseek		= default_llseek,
 };
 
 static struct usb_class_driver usbtmc_class = {
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 7e594449..9eed5b5 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -91,12 +91,12 @@
 	  If you are unsure about this, say N here.
 
 config USB_SUSPEND
-	bool "USB runtime power management (suspend/resume and wakeup)"
+	bool "USB runtime power management (autosuspend) and wakeup"
 	depends on USB && PM_RUNTIME
 	help
 	  If you say Y here, you can use driver calls or the sysfs
-	  "power/level" file to suspend or resume individual USB
-	  peripherals and to enable or disable autosuspend (see
+	  "power/control" file to enable or disable autosuspend for
+	  individual USB peripherals (see
 	  Documentation/usb/power-management.txt for more details).
 
 	  Also, USB "remote wakeup" signaling is supported, whereby some
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index ec16e602..507a4e1 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -2,20 +2,13 @@
 # Makefile for USB Core files and filesystem
 #
 
-usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o driver.o \
-			config.o file.o buffer.o sysfs.o endpoint.o \
-			devio.o notify.o generic.o quirks.o devices.o
+ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 
-ifeq ($(CONFIG_PCI),y)
-	usbcore-objs	+= hcd-pci.o
-endif
+usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
+usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
+usbcore-y += devio.o notify.o generic.o quirks.o devices.o
 
-ifeq ($(CONFIG_USB_DEVICEFS),y)
-	usbcore-objs	+= inode.o
-endif
+usbcore-$(CONFIG_PCI)		+= hcd-pci.o
+usbcore-$(CONFIG_USB_DEVICEFS)	+= inode.o
 
-obj-$(CONFIG_USB)	+= usbcore.o
-
-ifeq ($(CONFIG_USB_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+obj-$(CONFIG_USB)		+= usbcore.o
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 3449742..ddb4dc9 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -66,8 +66,8 @@
 #define ALLOW_SERIAL_NUMBER
 
 static const char *format_topo =
-/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
-"\nT:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
+/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd */
+"\nT:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%-4s MxCh=%2d\n";
 
 static const char *format_string_manufacturer =
 /* S:  Manufacturer=xxxx */
@@ -520,11 +520,14 @@
 		speed = "1.5"; break;
 	case USB_SPEED_UNKNOWN:		/* usb 1.1 root hub code */
 	case USB_SPEED_FULL:
-		speed = "12 "; break;
+		speed = "12"; break;
+	case USB_SPEED_WIRELESS:	/* Wireless has no real fixed speed */
 	case USB_SPEED_HIGH:
 		speed = "480"; break;
+	case USB_SPEED_SUPER:
+		speed = "5000"; break;
 	default:
-		speed = "?? ";
+		speed = "??";
 	}
 	data_end = pages_start + sprintf(pages_start, format_topo,
 			bus->busnum, level, parent_devnum,
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index d7a4401..c0e60fb 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1337,7 +1337,7 @@
 	/* Avoid PM error messages for devices disconnected while suspended
 	 * as we'll display regular disconnect messages just a bit later.
 	 */
-	if (status == -ENODEV)
+	if (status == -ENODEV || status == -ESHUTDOWN)
 		status = 0;
 	return status;
 }
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 3788e73..9da2505 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -202,7 +202,7 @@
 	return retval;
 
 error_register:
-	kfree(ep_dev);
+	put_device(&ep_dev->dev);
 exit:
 	return retval;
 }
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index f06f5db..9fe34fb 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -59,6 +59,7 @@
 static const struct file_operations usb_fops = {
 	.owner =	THIS_MODULE,
 	.open =		usb_open,
+	.llseek =	noop_llseek,
 };
 
 static struct usb_class {
@@ -159,9 +160,9 @@
 int usb_register_dev(struct usb_interface *intf,
 		     struct usb_class_driver *class_driver)
 {
-	int retval = -EINVAL;
+	int retval;
 	int minor_base = class_driver->minor_base;
-	int minor = 0;
+	int minor;
 	char name[20];
 	char *temp;
 
@@ -173,12 +174,17 @@
 	 */
 	minor_base = 0;
 #endif
-	intf->minor = -1;
-
-	dbg ("looking for a minor, starting at %d", minor_base);
 
 	if (class_driver->fops == NULL)
-		goto exit;
+		return -EINVAL;
+	if (intf->minor >= 0)
+		return -EADDRINUSE;
+
+	retval = init_usb_class();
+	if (retval)
+		return retval;
+
+	dev_dbg(&intf->dev, "looking for a minor, starting at %d", minor_base);
 
 	down_write(&minor_rwsem);
 	for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
@@ -186,20 +192,12 @@
 			continue;
 
 		usb_minors[minor] = class_driver->fops;
-
-		retval = 0;
+		intf->minor = minor;
 		break;
 	}
 	up_write(&minor_rwsem);
-
-	if (retval)
-		goto exit;
-
-	retval = init_usb_class();
-	if (retval)
-		goto exit;
-
-	intf->minor = minor;
+	if (intf->minor < 0)
+		return -EXFULL;
 
 	/* create a usb class device for this usb interface */
 	snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
@@ -213,11 +211,11 @@
 				      "%s", temp);
 	if (IS_ERR(intf->usb_dev)) {
 		down_write(&minor_rwsem);
-		usb_minors[intf->minor] = NULL;
+		usb_minors[minor] = NULL;
+		intf->minor = -1;
 		up_write(&minor_rwsem);
 		retval = PTR_ERR(intf->usb_dev);
 	}
-exit:
 	return retval;
 }
 EXPORT_SYMBOL_GPL(usb_register_dev);
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index c3f9854..3799573 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -329,8 +329,10 @@
 		return;
 
 	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) &&
-			hcd->driver->shutdown)
+			hcd->driver->shutdown) {
 		hcd->driver->shutdown(hcd);
+		pci_disable_device(dev);
+	}
 }
 EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 5cca00a..61800f7 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1263,10 +1263,8 @@
 	*dma_handle = 0;
 }
 
-static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+void unmap_urb_setup_for_dma(struct usb_hcd *hcd, struct urb *urb)
 {
-	enum dma_data_direction dir;
-
 	if (urb->transfer_flags & URB_SETUP_MAP_SINGLE)
 		dma_unmap_single(hcd->self.controller,
 				urb->setup_dma,
@@ -1279,6 +1277,17 @@
 				sizeof(struct usb_ctrlrequest),
 				DMA_TO_DEVICE);
 
+	/* 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);
+
+void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+	enum dma_data_direction dir;
+
+	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)
 		dma_unmap_sg(hcd->self.controller,
@@ -1303,10 +1312,10 @@
 				dir);
 
 	/* Make it safe to call this routine more than once */
-	urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
-			URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
+	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);
 
 static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
 			   gfp_t mem_flags)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 84c18971..27115b4 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -758,6 +758,9 @@
 				clear_port_feature(hdev, port1,
 						   USB_PORT_FEAT_ENABLE);
 				portstatus &= ~USB_PORT_STAT_ENABLE;
+			} else {
+				/* Pretend that power was lost for USB3 devs */
+				portstatus &= ~USB_PORT_STAT_ENABLE;
 			}
 		}
 
@@ -2594,16 +2597,14 @@
 		return 0;
 	if (udev->state != USB_STATE_DEFAULT)
 		return -EINVAL;
-	if (hcd->driver->address_device) {
+	if (hcd->driver->address_device)
 		retval = hcd->driver->address_device(hcd, udev);
-	} else {
+	else
 		retval = usb_control_msg(udev, usb_sndaddr0pipe(),
 				USB_REQ_SET_ADDRESS, 0, devnum, 0,
 				NULL, 0, USB_CTRL_SET_TIMEOUT);
-		if (retval == 0)
-			update_address(udev, devnum);
-	}
 	if (retval == 0) {
+		update_address(udev, devnum);
 		/* Device now using proper address. */
 		usb_set_device_state(udev, USB_STATE_ADDRESS);
 		usb_ep0_reinit(udev);
@@ -2860,13 +2861,16 @@
 	else
 		i = udev->descriptor.bMaxPacketSize0;
 	if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
-		if (udev->speed != USB_SPEED_FULL ||
+		if (udev->speed == USB_SPEED_LOW ||
 				!(i == 8 || i == 16 || i == 32 || i == 64)) {
-			dev_err(&udev->dev, "ep0 maxpacket = %d\n", i);
+			dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i);
 			retval = -EMSGSIZE;
 			goto fail;
 		}
-		dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+		if (udev->speed == USB_SPEED_FULL)
+			dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+		else
+			dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i);
 		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
 		usb_ep0_reinit(udev);
 	}
@@ -3097,16 +3101,17 @@
 			udev->speed = USB_SPEED_UNKNOWN;
 
 		/*
-		 * xHCI needs to issue an address device command later
-		 * in the hub_port_init sequence for SS/HS/FS/LS devices.
+		 * 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.
 		 */
-		if (!(hcd->driver->flags & HCD_USB3)) {
-			/* set the address */
-			choose_address(udev);
-			if (udev->devnum <= 0) {
-				status = -ENOTCONN;	/* Don't retry */
-				goto loop;
-			}
+		choose_address(udev);
+		if (udev->devnum <= 0) {
+			status = -ENOTCONN;	/* Don't retry */
+			goto loop;
 		}
 
 		/* reset (non-USB 3.0 devices) and get descriptor */
@@ -3629,7 +3634,7 @@
 	}
 
 	if (!parent_hdev) {
-		/* this requires hcd-specific logic; see OHCI hc_restart() */
+		/* this requires hcd-specific logic; see ohci_restart() */
 		dev_dbg(&udev->dev, "%s for root hub!\n", __func__);
 		return -EISDIR;
 	}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 844683e..d6e3e41 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1140,13 +1140,6 @@
 {
 	int i;
 
-	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
-		skip_ep0 ? "non-ep0" : "all");
-	for (i = skip_ep0; i < 16; ++i) {
-		usb_disable_endpoint(dev, i, true);
-		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
-	}
-
 	/* getting rid of interfaces will disconnect
 	 * any drivers bound to them (a key side effect)
 	 */
@@ -1176,6 +1169,13 @@
 		if (dev->state == USB_STATE_CONFIGURED)
 			usb_set_device_state(dev, USB_STATE_ADDRESS);
 	}
+
+	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
+		skip_ep0 ? "non-ep0" : "all");
+	for (i = skip_ep0; i < 16; ++i) {
+		usb_disable_endpoint(dev, i, true);
+		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
+	}
 }
 
 /**
@@ -1802,6 +1802,7 @@
 		intf->dev.groups = usb_interface_groups;
 		intf->dev.dma_mask = dev->dev.dma_mask;
 		INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
+		intf->minor = -1;
 		device_initialize(&intf->dev);
 		dev_set_name(&intf->dev, "%d-%s:%d.%d",
 			dev->bus->busnum, dev->devpath,
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 419e6b3..c14fc082 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -401,8 +401,11 @@
 	};
 
 	/* Check that the pipe's type matches the endpoint's type */
-	if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+	if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) {
+		dev_err(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
+			usb_pipetype(urb->pipe), pipetypes[xfertype]);
 		return -EPIPE;		/* The most suitable error code :-) */
+	}
 
 	/* enforce simple/standard policy */
 	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK |
diff --git a/drivers/usb/early/Makefile b/drivers/usb/early/Makefile
index dfedee8..24bbe51 100644
--- a/drivers/usb/early/Makefile
+++ b/drivers/usb/early/Makefile
@@ -2,4 +2,4 @@
 # Makefile for early USB devices
 #
 
-obj-$(CONFIG_EARLY_PRINTK_DBGP)        += ehci-dbgp.o
+obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index cd27f9b..b739ca8 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -158,6 +158,7 @@
 	boolean "Freescale Highspeed USB DR Peripheral Controller"
 	depends on FSL_SOC || ARCH_MXC
 	select USB_GADGET_DUALSPEED
+	select USB_FSL_MPH_DR_OF
 	help
 	   Some of Freescale PowerPC processors have a High Speed
 	   Dual-Role(DR) USB controller, which supports device mode.
@@ -209,17 +210,6 @@
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
-config USB_OTG
-	boolean "OTG Support"
-	depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD
-	help
-	   The most notable feature of USB OTG is support for a
-	   "Dual-Role" device, which can act as either a device
-	   or a host.  The initial role choice can be changed
-	   later, when two dual-role devices talk to each other.
-
-	   Select this only if your OMAP board has a Mini-AB connector.
-
 config USB_GADGET_PXA25X
 	boolean "PXA 25x or IXP 4xx"
 	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
@@ -716,8 +706,8 @@
 	depends on EXPERIMENTAL
 	select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
 	help
-	  The Function Filesystem (FunctioFS) lets one create USB
-	  composite functions in user space in the same way as GadgetFS
+	  The Function Filesystem (FunctionFS) lets one create USB
+	  composite functions in user space in the same way GadgetFS
 	  lets one create USB gadgets in user space.  This allows creation
 	  of composite gadgets such that some of the functions are
 	  implemented in kernel space (for instance Ethernet, serial or
@@ -733,14 +723,14 @@
 	bool "Include configuration with CDC ECM (Ethernet)"
 	depends on USB_FUNCTIONFS && NET
 	help
-	  Include a configuration with CDC ECM funcion (Ethernet) and the
-	  Funcion Filesystem.
+	  Include a configuration with CDC ECM function (Ethernet) and the
+	  Function Filesystem.
 
 config USB_FUNCTIONFS_RNDIS
 	bool "Include configuration with RNDIS (Ethernet)"
 	depends on USB_FUNCTIONFS && NET
 	help
-	  Include a configuration with RNDIS funcion (Ethernet) and the Filesystem.
+	  Include a configuration with RNDIS function (Ethernet) and the Filesystem.
 
 config USB_FUNCTIONFS_GENERIC
 	bool "Include 'pure' configuration"
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 27283df..5780db4 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -1,9 +1,7 @@
 #
 # USB peripheral controller drivers
 #
-ifeq ($(CONFIG_USB_GADGET_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
+ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
 
 obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
@@ -18,10 +16,8 @@
 obj-$(CONFIG_USB_AT91)		+= at91_udc.o
 obj-$(CONFIG_USB_ATMEL_USBA)	+= atmel_usba_udc.o
 obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
-fsl_usb2_udc-objs		:= fsl_udc_core.o
-ifeq ($(CONFIG_ARCH_MXC),y)
-fsl_usb2_udc-objs		+= fsl_mxc_udc.o
-endif
+fsl_usb2_udc-y			:= fsl_udc_core.o
+fsl_usb2_udc-$(CONFIG_ARCH_MXC)	+= fsl_mxc_udc.o
 obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
 obj-$(CONFIG_USB_R8A66597)	+= r8a66597-udc.o
 obj-$(CONFIG_USB_FSL_QE)	+= fsl_qe_udc.o
@@ -32,21 +28,21 @@
 #
 # USB gadget drivers
 #
-g_zero-objs			:= zero.o
-g_audio-objs			:= audio.o
-g_ether-objs			:= ether.o
-g_serial-objs			:= serial.o
-g_midi-objs			:= gmidi.o
-gadgetfs-objs			:= inode.o
-g_file_storage-objs		:= file_storage.o
-g_mass_storage-objs		:= mass_storage.o
-g_printer-objs			:= printer.o
-g_cdc-objs			:= cdc2.o
-g_multi-objs			:= multi.o
-g_hid-objs			:= hid.o
-g_dbgp-objs			:= dbgp.o
-g_nokia-objs			:= nokia.o
-g_webcam-objs			:= webcam.o
+g_zero-y			:= zero.o
+g_audio-y			:= audio.o
+g_ether-y			:= ether.o
+g_serial-y			:= serial.o
+g_midi-y			:= gmidi.o
+gadgetfs-y			:= inode.o
+g_file_storage-y		:= file_storage.o
+g_mass_storage-y		:= mass_storage.o
+g_printer-y			:= printer.o
+g_cdc-y				:= cdc2.o
+g_multi-y			:= multi.o
+g_hid-y				:= hid.o
+g_dbgp-y			:= dbgp.o
+g_nokia-y			:= nokia.o
+g_webcam-y			:= webcam.o
 
 obj-$(CONFIG_USB_ZERO)		+= g_zero.o
 obj-$(CONFIG_USB_AUDIO)		+= g_audio.o
@@ -64,4 +60,3 @@
 obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
 obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
 obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
-
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 731150d4..9034e034 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -203,7 +203,7 @@
 		DBG(dev, "DMA mode       = PPBNDU (packet per buffer "
 			"WITHOUT desc. update)\n");
 		dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBNDU");
-	} else if (use_dma && use_dma_ppb_du && use_dma_ppb_du) {
+	} else if (use_dma && use_dma_ppb && use_dma_ppb_du) {
 		DBG(dev, "DMA mode       = PPBDU (packet per buffer "
 			"WITH desc. update)\n");
 		dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBDU");
@@ -1954,13 +1954,14 @@
 }
 
 /* Called by gadget driver to register itself */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct udc		*dev = udc;
 	int			retval;
 	u32 tmp;
 
-	if (!driver || !driver->bind || !driver->setup
+	if (!driver || !bind || !driver->setup
 			|| driver->speed != USB_SPEED_HIGH)
 		return -EINVAL;
 	if (!dev)
@@ -1972,7 +1973,7 @@
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
 
-	retval = driver->bind(&dev->gadget);
+	retval = bind(&dev->gadget);
 
 	/* Some gadget drivers use both ep0 directions.
 	 * NOTE: to gadget driver, ep0 is just one endpoint...
@@ -2000,7 +2001,7 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /* shutdown requests and disconnect from gadget */
 static void
@@ -3382,8 +3383,10 @@
 	udc = dev;
 
 	retval = device_register(&dev->gadget.dev);
-	if (retval)
+	if (retval) {
+		put_device(&dev->gadget.dev);
 		goto finished;
+	}
 
 	/* timer init */
 	init_timer(&udc_timer);
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 93ead19..387e503 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1628,7 +1628,8 @@
 		schedule_work(&udc->vbus_timer_work);
 }
 
-int usb_gadget_register_driver (struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct at91_udc	*udc = &controller;
 	int		retval;
@@ -1636,7 +1637,7 @@
 
 	if (!driver
 			|| driver->speed < USB_SPEED_FULL
-			|| !driver->bind
+			|| !bind
 			|| !driver->setup) {
 		DBG("bad parameter.\n");
 		return -EINVAL;
@@ -1653,9 +1654,9 @@
 	udc->enabled = 1;
 	udc->selfpowered = 1;
 
-	retval = driver->bind(&udc->gadget);
+	retval = bind(&udc->gadget);
 	if (retval) {
-		DBG("driver->bind() returned %d\n", retval);
+		DBG("bind() returned %d\n", retval);
 		udc->driver = NULL;
 		udc->gadget.dev.driver = NULL;
 		dev_set_drvdata(&udc->gadget.dev, NULL);
@@ -1671,7 +1672,7 @@
 	DBG("bound to %s\n", driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL (usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index d623c7b..b5e20e8 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -1789,7 +1789,8 @@
 	return IRQ_HANDLED;
 }
 
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct usba_udc *udc = &the_udc;
 	unsigned long flags;
@@ -1812,7 +1813,7 @@
 	clk_enable(udc->pclk);
 	clk_enable(udc->hclk);
 
-	ret = driver->bind(&udc->gadget);
+	ret = bind(&udc->gadget);
 	if (ret) {
 		DBG(DBG_ERR, "Could not bind to driver %s: error %d\n",
 			driver->driver.name, ret);
@@ -1841,7 +1842,7 @@
 	udc->gadget.dev.driver = NULL;
 	return ret;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
@@ -2014,6 +2015,9 @@
 			} else {
 				disable_irq(gpio_to_irq(udc->vbus_pin));
 			}
+		} else {
+			/* gpio_request fail so use -EINVAL for gpio_is_valid */
+			ubc->vbus_pin = -EINVAL;
 		}
 	}
 
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c
index b744ccd..93b999e 100644
--- a/drivers/usb/gadget/audio.c
+++ b/drivers/usb/gadget/audio.c
@@ -89,7 +89,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref audio_do_config(struct usb_configuration *c)
+static int __init audio_do_config(struct usb_configuration *c)
 {
 	/* FIXME alloc iConfiguration string, set it in c->strings */
 
@@ -105,7 +105,6 @@
 
 static struct usb_configuration audio_config_driver = {
 	.label			= DRIVER_DESC,
-	.bind			= audio_do_config,
 	.bConfigurationValue	= 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -113,7 +112,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref audio_bind(struct usb_composite_dev *cdev)
+static int __init audio_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	int			status;
@@ -145,7 +144,7 @@
 	strings_dev[STRING_PRODUCT_IDX].id = status;
 	device_desc.iProduct = status;
 
-	status = usb_add_config(cdev, &audio_config_driver);
+	status = usb_add_config(cdev, &audio_config_driver, audio_do_config);
 	if (status < 0)
 		goto fail;
 
@@ -166,13 +165,12 @@
 	.name		= "g_audio",
 	.dev		= &device_desc,
 	.strings	= audio_strings,
-	.bind		= audio_bind,
 	.unbind		= __exit_p(audio_unbind),
 };
 
 static int __init init(void)
 {
-	return usb_composite_register(&audio_driver);
+	return usb_composite_probe(&audio_driver, audio_bind);
 }
 module_init(init);
 
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
index 1f5ba2f..2720ab0 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/cdc2.c
@@ -129,7 +129,7 @@
 /*
  * We _always_ have both CDC ECM and CDC ACM functions.
  */
-static int __ref cdc_do_config(struct usb_configuration *c)
+static int __init cdc_do_config(struct usb_configuration *c)
 {
 	int	status;
 
@@ -151,7 +151,6 @@
 
 static struct usb_configuration cdc_config_driver = {
 	.label			= "CDC Composite (ECM + ACM)",
-	.bind			= cdc_do_config,
 	.bConfigurationValue	= 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -159,7 +158,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref cdc_bind(struct usb_composite_dev *cdev)
+static int __init cdc_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
@@ -218,7 +217,7 @@
 	device_desc.iProduct = status;
 
 	/* register our configuration */
-	status = usb_add_config(cdev, &cdc_config_driver);
+	status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config);
 	if (status < 0)
 		goto fail1;
 
@@ -245,7 +244,6 @@
 	.name		= "g_cdc",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= cdc_bind,
 	.unbind		= __exit_p(cdc_unbind),
 };
 
@@ -255,7 +253,7 @@
 
 static int __init init(void)
 {
-	return usb_composite_register(&cdc_driver);
+	return usb_composite_probe(&cdc_driver, cdc_bind);
 }
 module_init(init);
 
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 6996951..98b36fc 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2340,12 +2340,15 @@
 static const struct usb_gadget_ops usb_gadget_ops;
 
 /**
- * usb_gadget_register_driver: register a gadget driver
+ * usb_gadget_probe_driver: register a gadget driver
+ * @driver: the driver being registered
+ * @bind: the driver's bind callback
  *
- * Check usb_gadget_register_driver() at "usb_gadget.h" for details
- * Interrupts are enabled here
+ * Check usb_gadget_probe_driver() at <linux/usb/gadget.h> for details.
+ * Interrupts are enabled here.
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct ci13xxx *udc = _udc;
 	unsigned long i, k, flags;
@@ -2354,7 +2357,7 @@
 	trace("%p", driver);
 
 	if (driver             == NULL ||
-	    driver->bind       == NULL ||
+	    bind               == NULL ||
 	    driver->unbind     == NULL ||
 	    driver->setup      == NULL ||
 	    driver->disconnect == NULL ||
@@ -2430,7 +2433,7 @@
 	udc->gadget.dev.driver = &driver->driver;
 
 	spin_unlock_irqrestore(udc->lock, flags);
-	retval = driver->bind(&udc->gadget);                /* MAY SLEEP */
+	retval = bind(&udc->gadget);                /* MAY SLEEP */
 	spin_lock_irqsave(udc->lock, flags);
 
 	if (retval) {
@@ -2447,7 +2450,7 @@
 		usb_gadget_unregister_driver(driver);
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /**
  * usb_gadget_unregister_driver: unregister a gadget driver
@@ -2462,7 +2465,6 @@
 	trace("%p", driver);
 
 	if (driver             == NULL ||
-	    driver->bind       == NULL ||
 	    driver->unbind     == NULL ||
 	    driver->setup      == NULL ||
 	    driver->disconnect == NULL ||
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 1160c55..7b5cc16 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/device.h>
+#include <linux/utsname.h>
 
 #include <linux/usb/composite.h>
 
@@ -39,6 +40,7 @@
 #define USB_BUFSIZ	1024
 
 static struct usb_composite_driver *composite;
+static int (*composite_gadget_bind)(struct usb_composite_dev *cdev);
 
 /* Some systems will need runtime overrides for the  product identifers
  * published in the device descriptor, either numbers or strings or both.
@@ -69,6 +71,8 @@
 module_param(iSerialNumber, charp, 0);
 MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
 
+static char composite_manufacturer[50];
+
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -470,18 +474,20 @@
  * usb_add_config() - add a configuration to a device.
  * @cdev: wraps the USB gadget
  * @config: the configuration, with bConfigurationValue assigned
+ * @bind: the configuration's bind function
  * Context: single threaded during gadget setup
  *
- * One of the main tasks of a composite driver's bind() routine is to
+ * One of the main tasks of a composite @bind() routine is to
  * add each of the configurations it supports, using this routine.
  *
- * This function returns the value of the configuration's bind(), which
+ * This function returns the value of the configuration's @bind(), which
  * is zero for success else a negative errno value.  Binding configurations
  * assigns global resources including string IDs, and per-configuration
  * resources such as interface IDs and endpoints.
  */
 int usb_add_config(struct usb_composite_dev *cdev,
-		struct usb_configuration *config)
+		struct usb_configuration *config,
+		int (*bind)(struct usb_configuration *))
 {
 	int				status = -EINVAL;
 	struct usb_configuration	*c;
@@ -490,7 +496,7 @@
 			config->bConfigurationValue,
 			config->label, config);
 
-	if (!config->bConfigurationValue || !config->bind)
+	if (!config->bConfigurationValue || !bind)
 		goto done;
 
 	/* Prevent duplicate configuration identifiers */
@@ -507,7 +513,7 @@
 	INIT_LIST_HEAD(&config->functions);
 	config->next_interface_id = 0;
 
-	status = config->bind(config);
+	status = bind(config);
 	if (status < 0) {
 		list_del(&config->list);
 		config->cdev = NULL;
@@ -533,7 +539,7 @@
 		}
 	}
 
-	/* set_alt(), or next config->bind(), sets up
+	/* set_alt(), or next bind(), sets up
 	 * ep->driver_data as needed.
 	 */
 	usb_ep_autoconfig_reset(cdev->gadget);
@@ -599,6 +605,7 @@
 	struct usb_configuration	*c;
 	struct usb_function		*f;
 	int				len;
+	const char			*str;
 
 	/* Yes, not only is USB's I18N support probably more than most
 	 * folk will ever care about ... also, it's all supported here.
@@ -638,9 +645,29 @@
 		return s->bLength;
 	}
 
-	/* Otherwise, look up and return a specified string.  String IDs
-	 * are device-scoped, so we look up each string table we're told
-	 * about.  These lookups are infrequent; simpler-is-better here.
+	/* Otherwise, look up and return a specified string.  First
+	 * check if the string has not been overridden.
+	 */
+	if (cdev->manufacturer_override == id)
+		str = iManufacturer ?: composite->iManufacturer ?:
+			composite_manufacturer;
+	else if (cdev->product_override == id)
+		str = iProduct ?: composite->iProduct;
+	else if (cdev->serial_override == id)
+		str = iSerialNumber;
+	else
+		str = NULL;
+	if (str) {
+		struct usb_gadget_strings strings = {
+			.language = language,
+			.strings  = &(struct usb_string) { 0xff, str }
+		};
+		return usb_gadget_get_string(&strings, 0xff, buf);
+	}
+
+	/* String IDs are device-scoped, so we look up each string
+	 * table we're told about.  These lookups are infrequent;
+	 * simpler-is-better here.
 	 */
 	if (composite->strings) {
 		len = lookup_string(composite->strings, buf, language, id);
@@ -901,7 +928,8 @@
 		 */
 		switch (ctrl->bRequestType & USB_RECIP_MASK) {
 		case USB_RECIP_INTERFACE:
-			f = cdev->config->interface[intf];
+			if (cdev->config)
+				f = cdev->config->interface[intf];
 			break;
 
 		case USB_RECIP_ENDPOINT:
@@ -1025,26 +1053,17 @@
 	composite = NULL;
 }
 
-static void
-string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
+static u8 override_id(struct usb_composite_dev *cdev, u8 *desc)
 {
-	struct usb_string		*str = tab->strings;
-
-	for (str = tab->strings; str->s; str++) {
-		if (str->id == id) {
-			str->s = s;
-			return;
-		}
+	if (!*desc) {
+		int ret = usb_string_id(cdev);
+		if (unlikely(ret < 0))
+			WARNING(cdev, "failed to override string ID\n");
+		else
+			*desc = ret;
 	}
-}
 
-static void
-string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
-{
-	while (*tab) {
-		string_override_one(*tab, id, s);
-		tab++;
-	}
+	return *desc;
 }
 
 static int composite_bind(struct usb_gadget *gadget)
@@ -1074,7 +1093,13 @@
 	cdev->bufsiz = USB_BUFSIZ;
 	cdev->driver = composite;
 
-	usb_gadget_set_selfpowered(gadget);
+	/*
+	 * As per USB compliance update, a device that is actively drawing
+	 * more than 100mA from USB must report itself as bus-powered in
+	 * the GetStatus(DEVICE) call.
+	 */
+	if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW)
+		usb_gadget_set_selfpowered(gadget);
 
 	/* interface and string IDs start at zero via kzalloc.
 	 * we force endpoints to start unassigned; few controller
@@ -1094,26 +1119,41 @@
 	 * serial number), register function drivers, potentially update
 	 * power state and consumption, etc
 	 */
-	status = composite->bind(cdev);
+	status = composite_gadget_bind(cdev);
 	if (status < 0)
 		goto fail;
 
 	cdev->desc = *composite->dev;
 	cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 
-	/* strings can't be assigned before bind() allocates the
-	 * releavnt identifiers
-	 */
-	if (cdev->desc.iManufacturer && iManufacturer)
-		string_override(composite->strings,
-			cdev->desc.iManufacturer, iManufacturer);
-	if (cdev->desc.iProduct && iProduct)
-		string_override(composite->strings,
-			cdev->desc.iProduct, iProduct);
-	if (cdev->desc.iSerialNumber && iSerialNumber)
-		string_override(composite->strings,
-			cdev->desc.iSerialNumber, iSerialNumber);
+	/* stirng overrides */
+	if (iManufacturer || !cdev->desc.iManufacturer) {
+		if (!iManufacturer && !composite->iManufacturer &&
+		    !*composite_manufacturer)
+			snprintf(composite_manufacturer,
+				 sizeof composite_manufacturer,
+				 "%s %s with %s",
+				 init_utsname()->sysname,
+				 init_utsname()->release,
+				 gadget->name);
 
+		cdev->manufacturer_override =
+			override_id(cdev, &cdev->desc.iManufacturer);
+	}
+
+	if (iProduct || (!cdev->desc.iProduct && composite->iProduct))
+		cdev->product_override =
+			override_id(cdev, &cdev->desc.iProduct);
+
+	if (iSerialNumber)
+		cdev->serial_override =
+			override_id(cdev, &cdev->desc.iSerialNumber);
+
+	/* has userspace failed to provide a serial number? */
+	if (composite->needs_serial && !cdev->desc.iSerialNumber)
+		WARNING(cdev, "userspace failed to provide iSerialNumber\n");
+
+	/* finish up */
 	status = device_create_file(&gadget->dev, &dev_attr_suspended);
 	if (status)
 		goto fail;
@@ -1177,7 +1217,6 @@
 static struct usb_gadget_driver composite_driver = {
 	.speed		= USB_SPEED_HIGH,
 
-	.bind		= composite_bind,
 	.unbind		= composite_unbind,
 
 	.setup		= composite_setup,
@@ -1192,8 +1231,12 @@
 };
 
 /**
- * usb_composite_register() - register a composite driver
+ * usb_composite_probe() - register a composite driver
  * @driver: the driver to register
+ * @bind: the callback used to allocate resources that are shared across the
+ *	whole device, such as string IDs, and add its configurations using
+ *	@usb_add_config().  This may fail by returning a negative errno
+ *	value; it should return zero on successful initialization.
  * Context: single threaded during gadget setup
  *
  * This function is used to register drivers using the composite driver
@@ -1206,18 +1249,22 @@
  * while it was binding.  That would usually be done in order to wait for
  * some userspace participation.
  */
-int usb_composite_register(struct usb_composite_driver *driver)
+extern int usb_composite_probe(struct usb_composite_driver *driver,
+			       int (*bind)(struct usb_composite_dev *cdev))
 {
-	if (!driver || !driver->dev || !driver->bind || composite)
+	if (!driver || !driver->dev || !bind || composite)
 		return -EINVAL;
 
+	if (!driver->iProduct)
+		driver->iProduct = driver->name;
 	if (!driver->name)
 		driver->name = "composite";
 	composite_driver.function =  (char *) driver->name;
 	composite_driver.driver.name = driver->name;
 	composite = driver;
+	composite_gadget_bind = bind;
 
-	return usb_gadget_register_driver(&composite_driver);
+	return usb_gadget_probe_driver(&composite_driver, composite_bind);
 }
 
 /**
diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c
index 0ed50a2..e5ac8a3 100644
--- a/drivers/usb/gadget/dbgp.c
+++ b/drivers/usb/gadget/dbgp.c
@@ -386,15 +386,13 @@
 	} else
 		goto fail;
 
-	if (len >= 0) {
-		req->length = min(length, len);
-		req->zero = len < req->length;
-		if (data && req->length)
-			memcpy(req->buf, data, req->length);
+	req->length = min(length, len);
+	req->zero = len < req->length;
+	if (data && req->length)
+		memcpy(req->buf, data, req->length);
 
-		req->complete = dbgp_setup_complete;
-		return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
-	}
+	req->complete = dbgp_setup_complete;
+	return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
 
 fail:
 	dev_dbg(&dbgp.gadget->dev,
@@ -405,7 +403,6 @@
 static struct usb_gadget_driver dbgp_driver = {
 	.function = "dbgp",
 	.speed = USB_SPEED_HIGH,
-	.bind = dbgp_bind,
 	.unbind = dbgp_unbind,
 	.setup = dbgp_setup,
 	.disconnect = dbgp_disconnect,
@@ -417,7 +414,7 @@
 
 static int __init dbgp_init(void)
 {
-	return usb_gadget_register_driver(&dbgp_driver);
+	return usb_gadget_probe_driver(&dbgp_driver, dbgp_bind);
 }
 
 static void __exit dbgp_exit(void)
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index dc65462..1d2a2ab 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -748,7 +748,8 @@
  */
 
 int
-usb_gadget_register_driver (struct usb_gadget_driver *driver)
+usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct dummy	*dum = the_controller;
 	int		retval, i;
@@ -757,8 +758,7 @@
 		return -EINVAL;
 	if (dum->driver)
 		return -EBUSY;
-	if (!driver->bind || !driver->setup
-			|| driver->speed == USB_SPEED_UNKNOWN)
+	if (!bind || !driver->setup || driver->speed == USB_SPEED_UNKNOWN)
 		return -EINVAL;
 
 	/*
@@ -796,7 +796,7 @@
 	dum->gadget.dev.driver = &driver->driver;
 	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
 			driver->driver.name);
-	retval = driver->bind(&dum->gadget);
+	retval = bind(&dum->gadget);
 	if (retval) {
 		dum->driver = NULL;
 		dum->gadget.dev.driver = NULL;
@@ -812,7 +812,7 @@
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	return 0;
 }
-EXPORT_SYMBOL (usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int
 usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
@@ -874,6 +874,8 @@
 	struct dummy	*dum = the_controller;
 	int		rc;
 
+	usb_get_hcd(dummy_to_hcd(dum));
+
 	dum->gadget.name = gadget_name;
 	dum->gadget.ops = &dummy_ops;
 	dum->gadget.is_dualspeed = 1;
@@ -885,10 +887,10 @@
 	dum->gadget.dev.parent = &pdev->dev;
 	dum->gadget.dev.release = dummy_gadget_release;
 	rc = device_register (&dum->gadget.dev);
-	if (rc < 0)
+	if (rc < 0) {
+		put_device(&dum->gadget.dev);
 		return rc;
-
-	usb_get_hcd (dummy_to_hcd (dum));
+	}
 
 	platform_set_drvdata (pdev, dum);
 	rc = device_create_file (&dum->gadget.dev, &dev_attr_function);
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 114fa02..1690c9d 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -237,7 +237,7 @@
  * the first one present.  That's to make Microsoft's drivers happy,
  * and to follow DOCSIS 1.0 (cable modem standard).
  */
-static int __ref rndis_do_config(struct usb_configuration *c)
+static int __init rndis_do_config(struct usb_configuration *c)
 {
 	/* FIXME alloc iConfiguration string, set it in c->strings */
 
@@ -251,7 +251,6 @@
 
 static struct usb_configuration rndis_config_driver = {
 	.label			= "RNDIS",
-	.bind			= rndis_do_config,
 	.bConfigurationValue	= 2,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -270,7 +269,7 @@
 /*
  * We _always_ have an ECM, CDC Subset, or EEM configuration.
  */
-static int __ref eth_do_config(struct usb_configuration *c)
+static int __init eth_do_config(struct usb_configuration *c)
 {
 	/* FIXME alloc iConfiguration string, set it in c->strings */
 
@@ -289,7 +288,6 @@
 
 static struct usb_configuration eth_config_driver = {
 	/* .label = f(hardware) */
-	.bind			= eth_do_config,
 	.bConfigurationValue	= 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -297,7 +295,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref eth_bind(struct usb_composite_dev *cdev)
+static int __init eth_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
@@ -373,12 +371,13 @@
 
 	/* register our configuration(s); RNDIS first, if it's used */
 	if (has_rndis()) {
-		status = usb_add_config(cdev, &rndis_config_driver);
+		status = usb_add_config(cdev, &rndis_config_driver,
+				rndis_do_config);
 		if (status < 0)
 			goto fail;
 	}
 
-	status = usb_add_config(cdev, &eth_config_driver);
+	status = usb_add_config(cdev, &eth_config_driver, eth_do_config);
 	if (status < 0)
 		goto fail;
 
@@ -402,7 +401,6 @@
 	.name		= "g_ether",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= eth_bind,
 	.unbind		= __exit_p(eth_unbind),
 };
 
@@ -412,7 +410,7 @@
 
 static int __init init(void)
 {
-	return usb_composite_register(&eth_driver);
+	return usb_composite_probe(&eth_driver, eth_bind);
 }
 module_init(init);
 
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index d47a123..bd6226c 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -111,7 +111,7 @@
 	.bInterfaceCount = 	2,	// control + data
 	.bFunctionClass =	USB_CLASS_COMM,
 	.bFunctionSubClass =	USB_CDC_SUBCLASS_ACM,
-	.bFunctionProtocol =	USB_CDC_PROTO_NONE,
+	.bFunctionProtocol =	USB_CDC_ACM_PROTO_AT_V25TER,
 	/* .iFunction =		DYNAMIC */
 };
 
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c
index 53e1202..2b98bd2 100644
--- a/drivers/usb/gadget/f_hid.c
+++ b/drivers/usb/gadget/f_hid.c
@@ -451,6 +451,7 @@
 	.write		= f_hidg_write,
 	.read		= f_hidg_read,
 	.poll		= f_hidg_poll,
+	.llseek		= noop_llseek,
 };
 
 static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index 4322587..b37960f 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -324,7 +324,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref loopback_bind_config(struct usb_configuration *c)
+static int __init loopback_bind_config(struct usb_configuration *c)
 {
 	struct f_loopback	*loop;
 	int			status;
@@ -346,10 +346,9 @@
 	return status;
 }
 
-static  struct usb_configuration loopback_driver = {
+static struct usb_configuration loopback_driver = {
 	.label		= "loopback",
 	.strings	= loopback_strings,
-	.bind		= loopback_bind_config,
 	.bConfigurationValue = 2,
 	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
 	/* .iConfiguration = DYNAMIC */
@@ -382,5 +381,5 @@
 		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	return usb_add_config(cdev, &loopback_driver);
+	return usb_add_config(cdev, &loopback_driver, loopback_bind_config);
 }
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 32cce02..838286b 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -73,6 +73,8 @@
  *				being removable.
  *	->cdrom		Flag specifying that LUN shall be reported as
  *				being a CD-ROM.
+ *	->nofua		Flag specifying that FUA flag in SCSI WRITE(10,12)
+ *				commands for this LUN shall be ignored.
  *
  *	lun_name_format	A printf-like format for names of the LUN
  *				devices.  This determines how the
@@ -127,6 +129,8 @@
  *			Default true, boolean for removable media.
  *	cdrom=b[,b...]	Default false, boolean for whether to emulate
  *				a CD-ROM drive.
+ *	nofua=b[,b...]	Default false, booleans for ignore FUA flag
+ *				in SCSI WRITE(10,12) commands
  *	luns=N		Default N = number of filenames, number of
  *				LUNs to support.
  *	stall		Default determined according to the type of
@@ -409,6 +413,7 @@
 		char ro;
 		char removable;
 		char cdrom;
+		char nofua;
 	} luns[FSG_MAX_LUNS];
 
 	const char		*lun_name_format;
@@ -736,7 +741,7 @@
 
 	/* Get the starting Logical Block Address and check that it's
 	 * not too big */
-	if (common->cmnd[0] == SC_READ_6)
+	if (common->cmnd[0] == READ_6)
 		lba = get_unaligned_be24(&common->cmnd[1]);
 	else {
 		lba = get_unaligned_be32(&common->cmnd[2]);
@@ -874,7 +879,7 @@
 
 	/* Get the starting Logical Block Address and check that it's
 	 * not too big */
-	if (common->cmnd[0] == SC_WRITE_6)
+	if (common->cmnd[0] == WRITE_6)
 		lba = get_unaligned_be24(&common->cmnd[1]);
 	else {
 		lba = get_unaligned_be32(&common->cmnd[2]);
@@ -887,7 +892,7 @@
 			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 			return -EINVAL;
 		}
-		if (common->cmnd[1] & 0x08) {	/* FUA */
+		if (!curlun->nofua && (common->cmnd[1] & 0x08)) { /* FUA */
 			spin_lock(&curlun->filp->f_lock);
 			curlun->filp->f_flags |= O_SYNC;
 			spin_unlock(&curlun->filp->f_lock);
@@ -1181,7 +1186,7 @@
 		return 36;
 	}
 
-	buf[0] = curlun->cdrom ? TYPE_CDROM : TYPE_DISK;
+	buf[0] = curlun->cdrom ? TYPE_ROM : TYPE_DISK;
 	buf[1] = curlun->removable ? 0x80 : 0;
 	buf[2] = 2;		/* ANSI SCSI level 2 */
 	buf[3] = 2;		/* SCSI-2 INQUIRY data format */
@@ -1348,11 +1353,11 @@
 	 * The only variable value is the WriteProtect bit.  We will fill in
 	 * the mode data length later. */
 	memset(buf, 0, 8);
-	if (mscmnd == SC_MODE_SENSE_6) {
+	if (mscmnd == MODE_SENSE) {
 		buf[2] = (curlun->ro ? 0x80 : 0x00);		/* WP, DPOFUA */
 		buf += 4;
 		limit = 255;
-	} else {			/* SC_MODE_SENSE_10 */
+	} else {			/* MODE_SENSE_10 */
 		buf[3] = (curlun->ro ? 0x80 : 0x00);		/* WP, DPOFUA */
 		buf += 8;
 		limit = 65535;		/* Should really be FSG_BUFLEN */
@@ -1392,7 +1397,7 @@
 	}
 
 	/*  Store the mode data length */
-	if (mscmnd == SC_MODE_SENSE_6)
+	if (mscmnd == MODE_SENSE)
 		buf0[0] = len - 1;
 	else
 		put_unaligned_be16(len - 2, buf0);
@@ -1881,7 +1886,7 @@
 	if (common->lun >= 0 && common->lun < common->nluns) {
 		curlun = &common->luns[common->lun];
 		common->curlun = curlun;
-		if (common->cmnd[0] != SC_REQUEST_SENSE) {
+		if (common->cmnd[0] != REQUEST_SENSE) {
 			curlun->sense_data = SS_NO_SENSE;
 			curlun->sense_data_info = 0;
 			curlun->info_valid = 0;
@@ -1893,8 +1898,8 @@
 
 		/* INQUIRY and REQUEST SENSE commands are explicitly allowed
 		 * to use unsupported LUNs; all others may not. */
-		if (common->cmnd[0] != SC_INQUIRY &&
-		    common->cmnd[0] != SC_REQUEST_SENSE) {
+		if (common->cmnd[0] != INQUIRY &&
+		    common->cmnd[0] != REQUEST_SENSE) {
 			DBG(common, "unsupported LUN %d\n", common->lun);
 			return -EINVAL;
 		}
@@ -1903,8 +1908,8 @@
 	/* If a unit attention condition exists, only INQUIRY and
 	 * REQUEST SENSE commands are allowed; anything else must fail. */
 	if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
-			common->cmnd[0] != SC_INQUIRY &&
-			common->cmnd[0] != SC_REQUEST_SENSE) {
+			common->cmnd[0] != INQUIRY &&
+			common->cmnd[0] != REQUEST_SENSE) {
 		curlun->sense_data = curlun->unit_attention_data;
 		curlun->unit_attention_data = SS_NO_SENSE;
 		return -EINVAL;
@@ -1955,7 +1960,7 @@
 	down_read(&common->filesem);	/* We're using the backing file */
 	switch (common->cmnd[0]) {
 
-	case SC_INQUIRY:
+	case INQUIRY:
 		common->data_size_from_cmnd = common->cmnd[4];
 		reply = check_command(common, 6, DATA_DIR_TO_HOST,
 				      (1<<4), 0,
@@ -1964,7 +1969,7 @@
 			reply = do_inquiry(common, bh);
 		break;
 
-	case SC_MODE_SELECT_6:
+	case MODE_SELECT:
 		common->data_size_from_cmnd = common->cmnd[4];
 		reply = check_command(common, 6, DATA_DIR_FROM_HOST,
 				      (1<<1) | (1<<4), 0,
@@ -1973,7 +1978,7 @@
 			reply = do_mode_select(common, bh);
 		break;
 
-	case SC_MODE_SELECT_10:
+	case MODE_SELECT_10:
 		common->data_size_from_cmnd =
 			get_unaligned_be16(&common->cmnd[7]);
 		reply = check_command(common, 10, DATA_DIR_FROM_HOST,
@@ -1983,7 +1988,7 @@
 			reply = do_mode_select(common, bh);
 		break;
 
-	case SC_MODE_SENSE_6:
+	case MODE_SENSE:
 		common->data_size_from_cmnd = common->cmnd[4];
 		reply = check_command(common, 6, DATA_DIR_TO_HOST,
 				      (1<<1) | (1<<2) | (1<<4), 0,
@@ -1992,7 +1997,7 @@
 			reply = do_mode_sense(common, bh);
 		break;
 
-	case SC_MODE_SENSE_10:
+	case MODE_SENSE_10:
 		common->data_size_from_cmnd =
 			get_unaligned_be16(&common->cmnd[7]);
 		reply = check_command(common, 10, DATA_DIR_TO_HOST,
@@ -2002,7 +2007,7 @@
 			reply = do_mode_sense(common, bh);
 		break;
 
-	case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
+	case ALLOW_MEDIUM_REMOVAL:
 		common->data_size_from_cmnd = 0;
 		reply = check_command(common, 6, DATA_DIR_NONE,
 				      (1<<4), 0,
@@ -2011,7 +2016,7 @@
 			reply = do_prevent_allow(common);
 		break;
 
-	case SC_READ_6:
+	case READ_6:
 		i = common->cmnd[4];
 		common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
 		reply = check_command(common, 6, DATA_DIR_TO_HOST,
@@ -2021,7 +2026,7 @@
 			reply = do_read(common);
 		break;
 
-	case SC_READ_10:
+	case READ_10:
 		common->data_size_from_cmnd =
 				get_unaligned_be16(&common->cmnd[7]) << 9;
 		reply = check_command(common, 10, DATA_DIR_TO_HOST,
@@ -2031,7 +2036,7 @@
 			reply = do_read(common);
 		break;
 
-	case SC_READ_12:
+	case READ_12:
 		common->data_size_from_cmnd =
 				get_unaligned_be32(&common->cmnd[6]) << 9;
 		reply = check_command(common, 12, DATA_DIR_TO_HOST,
@@ -2041,7 +2046,7 @@
 			reply = do_read(common);
 		break;
 
-	case SC_READ_CAPACITY:
+	case READ_CAPACITY:
 		common->data_size_from_cmnd = 8;
 		reply = check_command(common, 10, DATA_DIR_TO_HOST,
 				      (0xf<<2) | (1<<8), 1,
@@ -2050,7 +2055,7 @@
 			reply = do_read_capacity(common, bh);
 		break;
 
-	case SC_READ_HEADER:
+	case READ_HEADER:
 		if (!common->curlun || !common->curlun->cdrom)
 			goto unknown_cmnd;
 		common->data_size_from_cmnd =
@@ -2062,7 +2067,7 @@
 			reply = do_read_header(common, bh);
 		break;
 
-	case SC_READ_TOC:
+	case READ_TOC:
 		if (!common->curlun || !common->curlun->cdrom)
 			goto unknown_cmnd;
 		common->data_size_from_cmnd =
@@ -2074,7 +2079,7 @@
 			reply = do_read_toc(common, bh);
 		break;
 
-	case SC_READ_FORMAT_CAPACITIES:
+	case READ_FORMAT_CAPACITIES:
 		common->data_size_from_cmnd =
 			get_unaligned_be16(&common->cmnd[7]);
 		reply = check_command(common, 10, DATA_DIR_TO_HOST,
@@ -2084,7 +2089,7 @@
 			reply = do_read_format_capacities(common, bh);
 		break;
 
-	case SC_REQUEST_SENSE:
+	case REQUEST_SENSE:
 		common->data_size_from_cmnd = common->cmnd[4];
 		reply = check_command(common, 6, DATA_DIR_TO_HOST,
 				      (1<<4), 0,
@@ -2093,7 +2098,7 @@
 			reply = do_request_sense(common, bh);
 		break;
 
-	case SC_START_STOP_UNIT:
+	case START_STOP:
 		common->data_size_from_cmnd = 0;
 		reply = check_command(common, 6, DATA_DIR_NONE,
 				      (1<<1) | (1<<4), 0,
@@ -2102,7 +2107,7 @@
 			reply = do_start_stop(common);
 		break;
 
-	case SC_SYNCHRONIZE_CACHE:
+	case SYNCHRONIZE_CACHE:
 		common->data_size_from_cmnd = 0;
 		reply = check_command(common, 10, DATA_DIR_NONE,
 				      (0xf<<2) | (3<<7), 1,
@@ -2111,7 +2116,7 @@
 			reply = do_synchronize_cache(common);
 		break;
 
-	case SC_TEST_UNIT_READY:
+	case TEST_UNIT_READY:
 		common->data_size_from_cmnd = 0;
 		reply = check_command(common, 6, DATA_DIR_NONE,
 				0, 1,
@@ -2120,7 +2125,7 @@
 
 	/* Although optional, this command is used by MS-Windows.  We
 	 * support a minimal version: BytChk must be 0. */
-	case SC_VERIFY:
+	case VERIFY:
 		common->data_size_from_cmnd = 0;
 		reply = check_command(common, 10, DATA_DIR_NONE,
 				      (1<<1) | (0xf<<2) | (3<<7), 1,
@@ -2129,7 +2134,7 @@
 			reply = do_verify(common);
 		break;
 
-	case SC_WRITE_6:
+	case WRITE_6:
 		i = common->cmnd[4];
 		common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
 		reply = check_command(common, 6, DATA_DIR_FROM_HOST,
@@ -2139,7 +2144,7 @@
 			reply = do_write(common);
 		break;
 
-	case SC_WRITE_10:
+	case WRITE_10:
 		common->data_size_from_cmnd =
 				get_unaligned_be16(&common->cmnd[7]) << 9;
 		reply = check_command(common, 10, DATA_DIR_FROM_HOST,
@@ -2149,7 +2154,7 @@
 			reply = do_write(common);
 		break;
 
-	case SC_WRITE_12:
+	case WRITE_12:
 		common->data_size_from_cmnd =
 				get_unaligned_be32(&common->cmnd[6]) << 9;
 		reply = check_command(common, 12, DATA_DIR_FROM_HOST,
@@ -2163,10 +2168,10 @@
 	 * They don't mean much in this setting.  It's left as an exercise
 	 * for anyone interested to implement RESERVE and RELEASE in terms
 	 * of Posix locks. */
-	case SC_FORMAT_UNIT:
-	case SC_RELEASE:
-	case SC_RESERVE:
-	case SC_SEND_DIAGNOSTIC:
+	case FORMAT_UNIT:
+	case RELEASE:
+	case RESERVE:
+	case SEND_DIAGNOSTIC:
 		/* Fall through */
 
 	default:
@@ -2662,6 +2667,7 @@
 
 /* Write permission is checked per LUN in store_*() functions. */
 static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro);
+static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, fsg_store_nofua);
 static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file);
 
 
@@ -2768,6 +2774,9 @@
 		rc = device_create_file(&curlun->dev, &dev_attr_file);
 		if (rc)
 			goto error_luns;
+		rc = device_create_file(&curlun->dev, &dev_attr_nofua);
+		if (rc)
+			goto error_luns;
 
 		if (lcfg->filename) {
 			rc = fsg_lun_open(curlun, lcfg->filename);
@@ -2911,6 +2920,7 @@
 
 		/* In error recovery common->nluns may be zero. */
 		for (; i; --i, ++lun) {
+			device_remove_file(&lun->dev, &dev_attr_nofua);
 			device_remove_file(&lun->dev, &dev_attr_ro);
 			device_remove_file(&lun->dev, &dev_attr_file);
 			fsg_lun_close(lun);
@@ -3069,8 +3079,10 @@
 	int		ro[FSG_MAX_LUNS];
 	int		removable[FSG_MAX_LUNS];
 	int		cdrom[FSG_MAX_LUNS];
+	int		nofua[FSG_MAX_LUNS];
 
 	unsigned int	file_count, ro_count, removable_count, cdrom_count;
+	unsigned int	nofua_count;
 	unsigned int	luns;	/* nluns */
 	int		stall;	/* can_stall */
 };
@@ -3096,6 +3108,8 @@
 				"true to simulate removable media");	\
 	_FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool,		\
 				"true to simulate CD-ROM instead of disk"); \
+	_FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool,		\
+				"true to ignore SCSI WRITE(10,12) FUA bit"); \
 	_FSG_MODULE_PARAM(prefix, params, luns, uint,			\
 			  "number of LUNs");				\
 	_FSG_MODULE_PARAM(prefix, params, stall, bool,			\
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index 685d768..e403a53 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -404,7 +404,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref sourcesink_bind_config(struct usb_configuration *c)
+static int __init sourcesink_bind_config(struct usb_configuration *c)
 {
 	struct f_sourcesink	*ss;
 	int			status;
@@ -498,7 +498,6 @@
 static struct usb_configuration sourcesink_driver = {
 	.label		= "source/sink",
 	.strings	= sourcesink_strings,
-	.bind		= sourcesink_bind_config,
 	.setup		= sourcesink_setup,
 	.bConfigurationValue = 3,
 	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
@@ -532,5 +531,5 @@
 		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	return usb_add_config(cdev, &sourcesink_driver);
+	return usb_add_config(cdev, &sourcesink_driver, sourcesink_bind_config);
 }
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index a857b7a..d4fdf65 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -89,6 +89,7 @@
  *				Required if "removable" is not set, names of
  *					the files or block devices used for
  *					backing storage
+ *	serial=HHHH...		Required serial number (string of hex chars)
  *	ro=b[,b...]		Default false, booleans for read-only access
  *	removable		Default false, boolean for removable media
  *	luns=N			Default N = number of filenames, number of
@@ -108,12 +109,11 @@
  *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID
  *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID
  *	release=0xRRRR		Override the USB release number (bcdDevice)
- *	serial=HHHH...		Override serial number (string of hex chars)
  *	buflen=N		Default N=16384, buffer size used (will be
  *					rounded down to a multiple of
  *					PAGE_CACHE_SIZE)
  *
- * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
+ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
  * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
  * default values are used for everything else.
  *
@@ -273,13 +273,10 @@
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
-/* DRIVER_VERSION must be at least 6 characters long, as it is used
- * to generate a fallback serial number. */
-#define DRIVER_VERSION		"20 November 2008"
+#define DRIVER_VERSION		"1 September 2010"
 
 static       char fsg_string_manufacturer[64];
 static const char fsg_string_product[] = DRIVER_DESC;
-static       char fsg_string_serial[13];
 static const char fsg_string_config[] = "Self-powered";
 static const char fsg_string_interface[] = "Mass Storage";
 
@@ -305,6 +302,7 @@
 
 static struct {
 	char		*file[FSG_MAX_LUNS];
+	char		*serial;
 	int		ro[FSG_MAX_LUNS];
 	int		nofua[FSG_MAX_LUNS];
 	unsigned int	num_filenames;
@@ -321,7 +319,6 @@
 	unsigned short	vendor;
 	unsigned short	product;
 	unsigned short	release;
-	char		*serial;
 	unsigned int	buflen;
 
 	int		transport_type;
@@ -346,6 +343,9 @@
 		S_IRUGO);
 MODULE_PARM_DESC(file, "names of backing files or devices");
 
+module_param_named(serial, mod_data.serial, charp, S_IRUGO);
+MODULE_PARM_DESC(serial, "USB serial number");
+
 module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
 MODULE_PARM_DESC(ro, "true to force read-only");
 
@@ -365,9 +365,6 @@
 module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
 MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
 
-module_param_named(serial, mod_data.serial, charp, S_IRUGO);
-MODULE_PARM_DESC(serial, "USB serial number");
-
 /* In the non-TEST version, only the module parameters listed above
  * are available. */
 #ifdef CONFIG_USB_FILE_STORAGE_TEST
@@ -786,7 +783,7 @@
 {
 	struct usb_request	*req = fsg->ep0req;
 	static u8		cbi_reset_cmnd[6] = {
-			SC_SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
+			SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
 
 	/* Error in command transfer? */
 	if (req->status || req->length != req->actual ||
@@ -1138,7 +1135,7 @@
 
 	/* Get the starting Logical Block Address and check that it's
 	 * not too big */
-	if (fsg->cmnd[0] == SC_READ_6)
+	if (fsg->cmnd[0] == READ_6)
 		lba = get_unaligned_be24(&fsg->cmnd[1]);
 	else {
 		lba = get_unaligned_be32(&fsg->cmnd[2]);
@@ -1273,7 +1270,7 @@
 
 	/* Get the starting Logical Block Address and check that it's
 	 * not too big */
-	if (fsg->cmnd[0] == SC_WRITE_6)
+	if (fsg->cmnd[0] == WRITE_6)
 		lba = get_unaligned_be24(&fsg->cmnd[1]);
 	else {
 		lba = get_unaligned_be32(&fsg->cmnd[2]);
@@ -1581,7 +1578,7 @@
 	}
 
 	memset(buf, 0, 8);
-	buf[0] = (mod_data.cdrom ? TYPE_CDROM : TYPE_DISK);
+	buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
 	if (mod_data.removable)
 		buf[1] = 0x80;
 	buf[2] = 2;		// ANSI SCSI level 2
@@ -1750,11 +1747,11 @@
 	 * The only variable value is the WriteProtect bit.  We will fill in
 	 * the mode data length later. */
 	memset(buf, 0, 8);
-	if (mscmnd == SC_MODE_SENSE_6) {
+	if (mscmnd == MODE_SENSE) {
 		buf[2] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA
 		buf += 4;
 		limit = 255;
-	} else {			// SC_MODE_SENSE_10
+	} else {			// MODE_SENSE_10
 		buf[3] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA
 		buf += 8;
 		limit = 65535;		// Should really be mod_data.buflen
@@ -1794,7 +1791,7 @@
 	}
 
 	/*  Store the mode data length */
-	if (mscmnd == SC_MODE_SENSE_6)
+	if (mscmnd == MODE_SENSE)
 		buf0[0] = len - 1;
 	else
 		put_unaligned_be16(len - 2, buf0);
@@ -2319,7 +2316,7 @@
 	/* Check the LUN */
 	if (fsg->lun >= 0 && fsg->lun < fsg->nluns) {
 		fsg->curlun = curlun = &fsg->luns[fsg->lun];
-		if (fsg->cmnd[0] != SC_REQUEST_SENSE) {
+		if (fsg->cmnd[0] != REQUEST_SENSE) {
 			curlun->sense_data = SS_NO_SENSE;
 			curlun->sense_data_info = 0;
 			curlun->info_valid = 0;
@@ -2330,8 +2327,8 @@
 
 		/* INQUIRY and REQUEST SENSE commands are explicitly allowed
 		 * to use unsupported LUNs; all others may not. */
-		if (fsg->cmnd[0] != SC_INQUIRY &&
-				fsg->cmnd[0] != SC_REQUEST_SENSE) {
+		if (fsg->cmnd[0] != INQUIRY &&
+				fsg->cmnd[0] != REQUEST_SENSE) {
 			DBG(fsg, "unsupported LUN %d\n", fsg->lun);
 			return -EINVAL;
 		}
@@ -2340,8 +2337,8 @@
 	/* If a unit attention condition exists, only INQUIRY and
 	 * REQUEST SENSE commands are allowed; anything else must fail. */
 	if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
-			fsg->cmnd[0] != SC_INQUIRY &&
-			fsg->cmnd[0] != SC_REQUEST_SENSE) {
+			fsg->cmnd[0] != INQUIRY &&
+			fsg->cmnd[0] != REQUEST_SENSE) {
 		curlun->sense_data = curlun->unit_attention_data;
 		curlun->unit_attention_data = SS_NO_SENSE;
 		return -EINVAL;
@@ -2391,7 +2388,7 @@
 	down_read(&fsg->filesem);	// We're using the backing file
 	switch (fsg->cmnd[0]) {
 
-	case SC_INQUIRY:
+	case INQUIRY:
 		fsg->data_size_from_cmnd = fsg->cmnd[4];
 		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
 				(1<<4), 0,
@@ -2399,7 +2396,7 @@
 			reply = do_inquiry(fsg, bh);
 		break;
 
-	case SC_MODE_SELECT_6:
+	case MODE_SELECT:
 		fsg->data_size_from_cmnd = fsg->cmnd[4];
 		if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
 				(1<<1) | (1<<4), 0,
@@ -2407,7 +2404,7 @@
 			reply = do_mode_select(fsg, bh);
 		break;
 
-	case SC_MODE_SELECT_10:
+	case MODE_SELECT_10:
 		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
 		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
 				(1<<1) | (3<<7), 0,
@@ -2415,7 +2412,7 @@
 			reply = do_mode_select(fsg, bh);
 		break;
 
-	case SC_MODE_SENSE_6:
+	case MODE_SENSE:
 		fsg->data_size_from_cmnd = fsg->cmnd[4];
 		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
 				(1<<1) | (1<<2) | (1<<4), 0,
@@ -2423,7 +2420,7 @@
 			reply = do_mode_sense(fsg, bh);
 		break;
 
-	case SC_MODE_SENSE_10:
+	case MODE_SENSE_10:
 		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
 				(1<<1) | (1<<2) | (3<<7), 0,
@@ -2431,7 +2428,7 @@
 			reply = do_mode_sense(fsg, bh);
 		break;
 
-	case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
+	case ALLOW_MEDIUM_REMOVAL:
 		fsg->data_size_from_cmnd = 0;
 		if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
 				(1<<4), 0,
@@ -2439,7 +2436,7 @@
 			reply = do_prevent_allow(fsg);
 		break;
 
-	case SC_READ_6:
+	case READ_6:
 		i = fsg->cmnd[4];
 		fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
 		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
@@ -2448,7 +2445,7 @@
 			reply = do_read(fsg);
 		break;
 
-	case SC_READ_10:
+	case READ_10:
 		fsg->data_size_from_cmnd =
 				get_unaligned_be16(&fsg->cmnd[7]) << 9;
 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
@@ -2457,7 +2454,7 @@
 			reply = do_read(fsg);
 		break;
 
-	case SC_READ_12:
+	case READ_12:
 		fsg->data_size_from_cmnd =
 				get_unaligned_be32(&fsg->cmnd[6]) << 9;
 		if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST,
@@ -2466,7 +2463,7 @@
 			reply = do_read(fsg);
 		break;
 
-	case SC_READ_CAPACITY:
+	case READ_CAPACITY:
 		fsg->data_size_from_cmnd = 8;
 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
 				(0xf<<2) | (1<<8), 1,
@@ -2474,7 +2471,7 @@
 			reply = do_read_capacity(fsg, bh);
 		break;
 
-	case SC_READ_HEADER:
+	case READ_HEADER:
 		if (!mod_data.cdrom)
 			goto unknown_cmnd;
 		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
@@ -2484,7 +2481,7 @@
 			reply = do_read_header(fsg, bh);
 		break;
 
-	case SC_READ_TOC:
+	case READ_TOC:
 		if (!mod_data.cdrom)
 			goto unknown_cmnd;
 		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
@@ -2494,7 +2491,7 @@
 			reply = do_read_toc(fsg, bh);
 		break;
 
-	case SC_READ_FORMAT_CAPACITIES:
+	case READ_FORMAT_CAPACITIES:
 		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
 				(3<<7), 1,
@@ -2502,7 +2499,7 @@
 			reply = do_read_format_capacities(fsg, bh);
 		break;
 
-	case SC_REQUEST_SENSE:
+	case REQUEST_SENSE:
 		fsg->data_size_from_cmnd = fsg->cmnd[4];
 		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
 				(1<<4), 0,
@@ -2510,7 +2507,7 @@
 			reply = do_request_sense(fsg, bh);
 		break;
 
-	case SC_START_STOP_UNIT:
+	case START_STOP:
 		fsg->data_size_from_cmnd = 0;
 		if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
 				(1<<1) | (1<<4), 0,
@@ -2518,7 +2515,7 @@
 			reply = do_start_stop(fsg);
 		break;
 
-	case SC_SYNCHRONIZE_CACHE:
+	case SYNCHRONIZE_CACHE:
 		fsg->data_size_from_cmnd = 0;
 		if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
 				(0xf<<2) | (3<<7), 1,
@@ -2526,7 +2523,7 @@
 			reply = do_synchronize_cache(fsg);
 		break;
 
-	case SC_TEST_UNIT_READY:
+	case TEST_UNIT_READY:
 		fsg->data_size_from_cmnd = 0;
 		reply = check_command(fsg, 6, DATA_DIR_NONE,
 				0, 1,
@@ -2535,7 +2532,7 @@
 
 	/* Although optional, this command is used by MS-Windows.  We
 	 * support a minimal version: BytChk must be 0. */
-	case SC_VERIFY:
+	case VERIFY:
 		fsg->data_size_from_cmnd = 0;
 		if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
 				(1<<1) | (0xf<<2) | (3<<7), 1,
@@ -2543,7 +2540,7 @@
 			reply = do_verify(fsg);
 		break;
 
-	case SC_WRITE_6:
+	case WRITE_6:
 		i = fsg->cmnd[4];
 		fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
 		if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
@@ -2552,7 +2549,7 @@
 			reply = do_write(fsg);
 		break;
 
-	case SC_WRITE_10:
+	case WRITE_10:
 		fsg->data_size_from_cmnd =
 				get_unaligned_be16(&fsg->cmnd[7]) << 9;
 		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
@@ -2561,7 +2558,7 @@
 			reply = do_write(fsg);
 		break;
 
-	case SC_WRITE_12:
+	case WRITE_12:
 		fsg->data_size_from_cmnd =
 				get_unaligned_be32(&fsg->cmnd[6]) << 9;
 		if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST,
@@ -2574,10 +2571,10 @@
 	 * They don't mean much in this setting.  It's left as an exercise
 	 * for anyone interested to implement RESERVE and RELEASE in terms
 	 * of Posix locks. */
-	case SC_FORMAT_UNIT:
-	case SC_RELEASE:
-	case SC_RESERVE:
-	case SC_SEND_DIAGNOSTIC:
+	case FORMAT_UNIT:
+	case RELEASE:
+	case RESERVE:
+	case SEND_DIAGNOSTIC:
 		// Fall through
 
 	default:
@@ -3178,6 +3175,7 @@
 	for (i = 0; i < fsg->nluns; ++i) {
 		curlun = &fsg->luns[i];
 		if (curlun->registered) {
+			device_remove_file(&curlun->dev, &dev_attr_nofua);
 			device_remove_file(&curlun->dev, &dev_attr_ro);
 			device_remove_file(&curlun->dev, &dev_attr_file);
 			fsg_lun_close(curlun);
@@ -3213,7 +3211,6 @@
 {
 	int	prot;
 	int	gcnum;
-	int	i;
 
 	/* Store the default values */
 	mod_data.transport_type = USB_PR_BULK;
@@ -3309,45 +3306,29 @@
 			if ((*ch < '0' || *ch > '9') &&
 			    (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
 				WARNING(fsg,
-					"Invalid serial string character: %c; "
-					"Failing back to default\n",
+					"Invalid serial string character: %c\n",
 					*ch);
-				goto fill_serial;
+				goto no_serial;
 			}
 		}
 		if (len > 126 ||
 		    (mod_data.transport_type == USB_PR_BULK && len < 12) ||
 		    (mod_data.transport_type != USB_PR_BULK && len > 12)) {
-			WARNING(fsg,
-				"Invalid serial string length; "
-				"Failing back to default\n");
-			goto fill_serial;
+			WARNING(fsg, "Invalid serial string length!\n");
+			goto no_serial;
 		}
 		fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
 	} else {
-		WARNING(fsg,
-			"Userspace failed to provide serial number; "
-			"Failing back to default\n");
-fill_serial:
-		/* Serial number not specified or invalid, make our own.
-		 * We just encode it from the driver version string,
-		 * 12 characters to comply with both CB[I] and BBB spec.
-		 * Warning : Two devices running the same kernel will have
-		 * the same fallback serial number. */
-		for (i = 0; i < 12; i += 2) {
-			unsigned char	c = DRIVER_VERSION[i / 2];
-
-			if (!c)
-				break;
-			sprintf(&fsg_string_serial[i], "%02X", c);
-		}
+		WARNING(fsg, "No serial-number string provided!\n");
+ no_serial:
+		device_desc.iSerialNumber = 0;
 	}
 
 	return 0;
 }
 
 
-static int __ref fsg_bind(struct usb_gadget *gadget)
+static int __init fsg_bind(struct usb_gadget *gadget)
 {
 	struct fsg_dev		*fsg = the_fsg;
 	int			rc;
@@ -3607,7 +3588,6 @@
 	.speed		= USB_SPEED_FULL,
 #endif
 	.function	= (char *) fsg_string_product,
-	.bind		= fsg_bind,
 	.unbind		= fsg_unbind,
 	.disconnect	= fsg_disconnect,
 	.setup		= fsg_setup,
@@ -3649,7 +3629,7 @@
 	if ((rc = fsg_alloc()) != 0)
 		return rc;
 	fsg = the_fsg;
-	if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
+	if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0)
 		kref_put(&fsg->ref, fsg_release);
 	return rc;
 }
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c
index eafa6d2..5bdbfe6 100644
--- a/drivers/usb/gadget/fsl_mxc_udc.c
+++ b/drivers/usb/gadget/fsl_mxc_udc.c
@@ -22,6 +22,10 @@
 static struct clk *mxc_ahb_clk;
 static struct clk *mxc_usb_clk;
 
+/* workaround ENGcm09152 for i.MX35 */
+#define USBPHYCTRL_OTGBASE_OFFSET	0x608
+#define USBPHYCTRL_EVDO			(1 << 23)
+
 int fsl_udc_clk_init(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata;
@@ -84,6 +88,17 @@
 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_OTG_BASE_ADDR +
+				USBPHYCTRL_OTGBASE_OFFSET));
+		writel(v | USBPHYCTRL_EVDO, MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
+				USBPHYCTRL_OTGBASE_OFFSET));
+	}
+#endif
 
 	/* ULPI transceivers don't need usbpll */
 	if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index a5ea2c1..792d5ef 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2302,9 +2302,10 @@
 }
 
 /*-------------------------------------------------------------------------
-	Gadget driver register and unregister.
+	Gadget driver probe and unregister.
  --------------------------------------------------------------------------*/
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	int retval;
 	unsigned long flags = 0;
@@ -2315,8 +2316,7 @@
 
 	if (!driver || (driver->speed != USB_SPEED_FULL
 			&& driver->speed != USB_SPEED_HIGH)
-			|| !driver->bind || !driver->disconnect
-			|| !driver->setup)
+			|| !bind || !driver->disconnect || !driver->setup)
 		return -EINVAL;
 
 	if (udc_controller->driver)
@@ -2332,7 +2332,7 @@
 	udc_controller->gadget.speed = (enum usb_device_speed)(driver->speed);
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 
-	retval = driver->bind(&udc_controller->gadget);
+	retval = bind(&udc_controller->gadget);
 	if (retval) {
 		dev_err(udc_controller->dev, "bind to %s --> %d",
 				driver->driver.name, retval);
@@ -2353,7 +2353,7 @@
 		udc_controller->gadget.name, driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 08a9a62..c16b402 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -1765,7 +1765,8 @@
  * Hook to gadget drivers
  * Called by initialization code of gadget drivers
 *----------------------------------------------------------------*/
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	int retval = -ENODEV;
 	unsigned long flags = 0;
@@ -1775,8 +1776,7 @@
 
 	if (!driver || (driver->speed != USB_SPEED_FULL
 				&& driver->speed != USB_SPEED_HIGH)
-			|| !driver->bind || !driver->disconnect
-			|| !driver->setup)
+			|| !bind || !driver->disconnect || !driver->setup)
 		return -EINVAL;
 
 	if (udc_controller->driver)
@@ -1792,7 +1792,7 @@
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 
 	/* bind udc driver to gadget driver */
-	retval = driver->bind(&udc_controller->gadget);
+	retval = bind(&udc_controller->gadget);
 	if (retval) {
 		VDBG("bind to %s --> %d", driver->driver.name, retval);
 		udc_controller->gadget.dev.driver = NULL;
@@ -1814,7 +1814,7 @@
 		       retval);
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /* Disconnect from gadget driver */
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index a9474f8..af75e36 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -52,9 +52,8 @@
 MODULE_AUTHOR("Michal Nazarewicz");
 MODULE_LICENSE("GPL");
 
-
-static unsigned short gfs_vendor_id    = 0x0525;	/* XXX NetChip */
-static unsigned short gfs_product_id   = 0xa4ac;	/* XXX */
+#define GFS_VENDOR_ID	0x1d6b	/* Linux Foundation */
+#define GFS_PRODUCT_ID	0x0105	/* FunctionFS Gadget */
 
 static struct usb_device_descriptor gfs_dev_desc = {
 	.bLength		= sizeof gfs_dev_desc,
@@ -63,29 +62,16 @@
 	.bcdUSB			= cpu_to_le16(0x0200),
 	.bDeviceClass		= USB_CLASS_PER_INTERFACE,
 
-	/* Vendor and product id can be overridden by module parameters.  */
-	/* .idVendor		= cpu_to_le16(gfs_vendor_id), */
-	/* .idProduct		= cpu_to_le16(gfs_product_id), */
-	/* .bcdDevice		= f(hardware) */
-	/* .iManufacturer	= DYNAMIC */
-	/* .iProduct		= DYNAMIC */
-	/* NO SERIAL NUMBER */
-	.bNumConfigurations	= 1,
+	.idVendor		= cpu_to_le16(GFS_VENDOR_ID),
+	.idProduct		= cpu_to_le16(GFS_PRODUCT_ID),
 };
 
-#define GFS_MODULE_PARAM_DESC(name, field) \
-	MODULE_PARM_DESC(name, "Value of the " #field " field of the device descriptor sent to the host.  Takes effect only prior to the user-space driver registering to the FunctionFS.")
-
-module_param_named(usb_class,    gfs_dev_desc.bDeviceClass,    byte,   0644);
-GFS_MODULE_PARAM_DESC(usb_class, bDeviceClass);
-module_param_named(usb_subclass, gfs_dev_desc.bDeviceSubClass, byte,   0644);
-GFS_MODULE_PARAM_DESC(usb_subclass, bDeviceSubClass);
-module_param_named(usb_protocol, gfs_dev_desc.bDeviceProtocol, byte,   0644);
-GFS_MODULE_PARAM_DESC(usb_protocol, bDeviceProtocol);
-module_param_named(usb_vendor,   gfs_vendor_id,                ushort, 0644);
-GFS_MODULE_PARAM_DESC(usb_vendor, idVendor);
-module_param_named(usb_product,  gfs_product_id,               ushort, 0644);
-GFS_MODULE_PARAM_DESC(usb_product, idProduct);
+module_param_named(bDeviceClass,    gfs_dev_desc.bDeviceClass,    byte,   0644);
+MODULE_PARM_DESC(bDeviceClass, "USB Device class");
+module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte,   0644);
+MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass");
+module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte,   0644);
+MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
 
 
 
@@ -95,8 +81,10 @@
 		.bLength		= sizeof(struct usb_otg_descriptor),
 		.bDescriptorType	= USB_DT_OTG,
 
-		/* REVISIT SRP-only hardware is possible, although
-		 * it would not be called "OTG" ... */
+		/*
+		 * REVISIT SRP-only hardware is possible, although
+		 * it would not be called "OTG" ...
+		 */
 		.bmAttributes		= USB_OTG_SRP | USB_OTG_HNP,
 	},
 
@@ -105,19 +93,7 @@
 
 /* string IDs are assigned dynamically */
 
-enum {
-	GFS_STRING_MANUFACTURER_IDX,
-	GFS_STRING_PRODUCT_IDX,
-	GFS_STRING_FIRST_CONFIG_IDX,
-};
-
-static       char gfs_manufacturer[50];
-static const char gfs_driver_desc[] = DRIVER_DESC;
-static const char gfs_short_name[]  = DRIVER_NAME;
-
 static struct usb_string gfs_strings[] = {
-	[GFS_STRING_MANUFACTURER_IDX].s = gfs_manufacturer,
-	[GFS_STRING_PRODUCT_IDX].s = gfs_driver_desc,
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 	{ .s = "FunctionFS + RNDIS" },
 #endif
@@ -168,11 +144,11 @@
 static int gfs_do_config(struct usb_configuration *c);
 
 static struct usb_composite_driver gfs_driver = {
-	.name		= gfs_short_name,
+	.name		= DRIVER_NAME,
 	.dev		= &gfs_dev_desc,
 	.strings	= gfs_dev_strings,
-	.bind		= gfs_bind,
 	.unbind		= gfs_unbind,
+	.iProduct	= DRIVER_DESC,
 };
 
 
@@ -210,7 +186,7 @@
 		return -EBUSY;
 
 	gfs_ffs_data = ffs;
-	ret = usb_composite_register(&gfs_driver);
+	ret = usb_composite_probe(&gfs_driver, gfs_bind);
 	if (unlikely(ret < 0))
 		clear_bit(0, &gfs_registered);
 	return ret;
@@ -245,20 +221,10 @@
 	if (unlikely(ret < 0))
 		goto error_quick;
 
-	gfs_dev_desc.idVendor  = cpu_to_le16(gfs_vendor_id);
-	gfs_dev_desc.idProduct = cpu_to_le16(gfs_product_id);
-
-	snprintf(gfs_manufacturer, sizeof gfs_manufacturer, "%s %s with %s",
-		 init_utsname()->sysname, init_utsname()->release,
-		 cdev->gadget->name);
-
 	ret = usb_string_ids_tab(cdev, gfs_strings);
 	if (unlikely(ret < 0))
 		goto error;
 
-	gfs_dev_desc.iManufacturer = gfs_strings[GFS_STRING_MANUFACTURER_IDX].id;
-	gfs_dev_desc.iProduct      = gfs_strings[GFS_STRING_PRODUCT_IDX].id;
-
 	ret = functionfs_bind(gfs_ffs_data, cdev);
 	if (unlikely(ret < 0))
 		goto error;
@@ -266,14 +232,12 @@
 	for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
 		struct gfs_configuration *c = gfs_configurations + i;
 
-		ret = GFS_STRING_FIRST_CONFIG_IDX + i;
-		c->c.label			= gfs_strings[ret].s;
-		c->c.iConfiguration		= gfs_strings[ret].id;
-		c->c.bind			= gfs_do_config;
+		c->c.label			= gfs_strings[i].s;
+		c->c.iConfiguration		= gfs_strings[i].id;
 		c->c.bConfigurationValue	= 1 + i;
 		c->c.bmAttributes		= USB_CONFIG_ATT_SELFPOWER;
 
-		ret = usb_add_config(cdev, &c->c);
+		ret = usb_add_config(cdev, &c->c, gfs_do_config);
 		if (unlikely(ret < 0))
 			goto error_unbind;
 	}
@@ -293,13 +257,14 @@
 {
 	ENTER();
 
-	/* We may have been called in an error recovery frem
+	/*
+	 * We may have been called in an error recovery from
 	 * composite_bind() after gfs_unbind() failure so we need to
 	 * check if gfs_ffs_data is not NULL since gfs_bind() handles
 	 * all error recovery itself.  I'd rather we werent called
 	 * from composite on orror recovery, but what you're gonna
-	 * do...? */
-
+	 * do...?
+	 */
 	if (gfs_ffs_data) {
 		gether_cleanup();
 		functionfs_unbind(gfs_ffs_data);
@@ -334,14 +299,16 @@
 	if (unlikely(ret < 0))
 		return ret;
 
-	/* After previous do_configs there may be some invalid
+	/*
+	 * After previous do_configs there may be some invalid
 	 * pointers in c->interface array.  This happens every time
 	 * a user space function with fewer interfaces than a user
 	 * space function that was run before the new one is run.  The
 	 * compasit's set_config() assumes that if there is no more
 	 * then MAX_CONFIG_INTERFACES interfaces in a configuration
 	 * then there is a NULL pointer after the last interface in
-	 * c->interface array.  We need to make sure this is true. */
+	 * c->interface array.  We need to make sure this is true.
+	 */
 	if (c->next_interface_id < ARRAY_SIZE(c->interface))
 		c->interface[c->next_interface_id] = NULL;
 
@@ -350,10 +317,12 @@
 
 
 #ifdef CONFIG_USB_FUNCTIONFS_ETH
+
 static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 {
 	return can_support_ecm(c->cdev->gadget)
 		? ecm_bind_config(c, ethaddr)
 		: geth_bind_config(c, ethaddr);
 }
+
 #endif
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 1b413a5c..0ab7e14 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -1157,7 +1157,7 @@
 /*
  * Creates an output endpoint, and initializes output ports.
  */
-static int __ref gmidi_bind(struct usb_gadget *gadget)
+static int __init gmidi_bind(struct usb_gadget *gadget)
 {
 	struct gmidi_device *dev;
 	struct usb_ep *in_ep, *out_ep;
@@ -1292,7 +1292,6 @@
 static struct usb_gadget_driver gmidi_driver = {
 	.speed		= USB_SPEED_FULL,
 	.function	= (char *)longname,
-	.bind		= gmidi_bind,
 	.unbind		= gmidi_unbind,
 
 	.setup		= gmidi_setup,
@@ -1309,7 +1308,7 @@
 
 static int __init gmidi_init(void)
 {
-	return usb_gadget_register_driver(&gmidi_driver);
+	return usb_gadget_probe_driver(&gmidi_driver, gmidi_bind);
 }
 module_init(gmidi_init);
 
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 1088d08..48a76022 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1343,14 +1343,15 @@
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct goku_udc	*dev = the_controller;
 	int			retval;
 
 	if (!driver
 			|| driver->speed < USB_SPEED_FULL
-			|| !driver->bind
+			|| !bind
 			|| !driver->disconnect
 			|| !driver->setup)
 		return -EINVAL;
@@ -1363,7 +1364,7 @@
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
-	retval = driver->bind(&dev->gadget);
+	retval = bind(&dev->gadget);
 	if (retval) {
 		DBG(dev, "bind to driver %s --> error %d\n",
 				driver->driver.name, retval);
@@ -1380,7 +1381,7 @@
 	DBG(dev, "registered gadget driver '%s'\n", driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void
 stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
@@ -1744,7 +1745,8 @@
 				pci_resource_len (pdev, 0));
 	if (dev->enabled)
 		pci_disable_device(pdev);
-	device_unregister(&dev->gadget.dev);
+	if (dev->registered)
+		device_unregister(&dev->gadget.dev);
 
 	pci_set_drvdata(pdev, NULL);
 	dev->regs = NULL;
@@ -1774,7 +1776,7 @@
 	if (!pdev->irq) {
 		printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev));
 		retval = -ENODEV;
-		goto done;
+		goto err;
 	}
 
 	/* alloc, and start init */
@@ -1782,7 +1784,7 @@
 	if (dev == NULL){
 		pr_debug("enomem %s\n", pci_name(pdev));
 		retval = -ENOMEM;
-		goto done;
+		goto err;
 	}
 
 	spin_lock_init(&dev->lock);
@@ -1800,7 +1802,7 @@
 	retval = pci_enable_device(pdev);
 	if (retval < 0) {
 		DBG(dev, "can't enable, %d\n", retval);
-		goto done;
+		goto err;
 	}
 	dev->enabled = 1;
 
@@ -1809,7 +1811,7 @@
 	if (!request_mem_region(resource, len, driver_name)) {
 		DBG(dev, "controller already in use\n");
 		retval = -EBUSY;
-		goto done;
+		goto err;
 	}
 	dev->got_region = 1;
 
@@ -1817,7 +1819,7 @@
 	if (base == NULL) {
 		DBG(dev, "can't map memory\n");
 		retval = -EFAULT;
-		goto done;
+		goto err;
 	}
 	dev->regs = (struct goku_udc_regs __iomem *) base;
 
@@ -1833,7 +1835,7 @@
 			driver_name, dev) != 0) {
 		DBG(dev, "request interrupt %d failed\n", pdev->irq);
 		retval = -EBUSY;
-		goto done;
+		goto err;
 	}
 	dev->got_irq = 1;
 	if (use_dma)
@@ -1844,13 +1846,16 @@
 	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
 #endif
 
-	/* done */
 	the_controller = dev;
 	retval = device_register(&dev->gadget.dev);
-	if (retval == 0)
-		return 0;
+	if (retval) {
+		put_device(&dev->gadget.dev);
+		goto err;
+	}
+	dev->registered = 1;
+	return 0;
 
-done:
+err:
 	if (dev)
 		goku_remove (pdev);
 	return retval;
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
index 735495b..2523e54 100644
--- a/drivers/usb/gadget/hid.c
+++ b/drivers/usb/gadget/hid.c
@@ -127,7 +127,7 @@
 
 /****************************** Configurations ******************************/
 
-static int __ref do_config(struct usb_configuration *c)
+static int __init do_config(struct usb_configuration *c)
 {
 	struct hidg_func_node *e;
 	int func = 0, status = 0;
@@ -148,7 +148,6 @@
 
 static struct usb_configuration config_driver = {
 	.label			= "HID Gadget",
-	.bind			= do_config,
 	.bConfigurationValue	= 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -156,7 +155,7 @@
 
 /****************************** Gadget Bind ******************************/
 
-static int __ref hid_bind(struct usb_composite_dev *cdev)
+static int __init hid_bind(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget *gadget = cdev->gadget;
 	struct list_head *tmp;
@@ -201,7 +200,7 @@
 	device_desc.iProduct = status;
 
 	/* register our configuration */
-	status = usb_add_config(cdev, &config_driver);
+	status = usb_add_config(cdev, &config_driver, do_config);
 	if (status < 0)
 		return status;
 
@@ -256,7 +255,6 @@
 	.name		= "g_hid",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= hid_bind,
 	.unbind		= __exit_p(hid_unbind),
 };
 
@@ -282,7 +280,7 @@
 	if (status < 0)
 		return status;
 
-	status = usb_composite_register(&hidg_driver);
+	status = usb_composite_probe(&hidg_driver, hid_bind);
 	if (status < 0)
 		platform_driver_unregister(&hidg_plat_driver);
 
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
index e743122..ed02664 100644
--- a/drivers/usb/gadget/imx_udc.c
+++ b/drivers/usb/gadget/imx_udc.c
@@ -1319,14 +1319,15 @@
  * USB gadged driver functions
  *******************************************************************************
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct imx_udc_struct *imx_usb = &controller;
 	int retval;
 
 	if (!driver
 		|| driver->speed < USB_SPEED_FULL
-		|| !driver->bind
+		|| !bind
 		|| !driver->disconnect
 		|| !driver->setup)
 			return -EINVAL;
@@ -1342,7 +1343,7 @@
 	retval = device_add(&imx_usb->gadget.dev);
 	if (retval)
 		goto fail;
-	retval = driver->bind(&imx_usb->gadget);
+	retval = bind(&imx_usb->gadget);
 	if (retval) {
 		D_ERR(imx_usb->dev, "<%s> bind to driver %s --> error %d\n",
 			__func__, driver->driver.name, retval);
@@ -1362,7 +1363,7 @@
 	imx_usb->gadget.dev.driver = NULL;
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index fc35406..d1d72d9 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -33,7 +33,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -1775,7 +1774,6 @@
 	.speed		= USB_SPEED_FULL,
 #endif
 	.function	= (char *) driver_desc,
-	.bind		= gadgetfs_bind,
 	.unbind		= gadgetfs_unbind,
 	.setup		= gadgetfs_setup,
 	.disconnect	= gadgetfs_disconnect,
@@ -1798,7 +1796,6 @@
 
 static struct usb_gadget_driver probe_driver = {
 	.speed		= USB_SPEED_HIGH,
-	.bind		= gadgetfs_probe,
 	.unbind		= gadgetfs_nop,
 	.setup		= (void *)gadgetfs_nop,
 	.disconnect	= gadgetfs_nop,
@@ -1908,7 +1905,7 @@
 
 	/* triggers gadgetfs_bind(); then we can enumerate. */
 	spin_unlock_irq (&dev->lock);
-	value = usb_gadget_register_driver (&gadgetfs_driver);
+	value = usb_gadget_probe_driver(&gadgetfs_driver, gadgetfs_bind);
 	if (value != 0) {
 		kfree (dev->buf);
 		dev->buf = NULL;
@@ -2047,7 +2044,7 @@
 		return -ESRCH;
 
 	/* fake probe to determine $CHIP */
-	(void) usb_gadget_register_driver (&probe_driver);
+	(void) usb_gadget_probe_driver(&probe_driver, gadgetfs_probe);
 	if (!CHIP)
 		return -ENODEV;
 
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index c2d2a20..b8ec954 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -19,7 +19,7 @@
 
 
 /* #undef	DEBUG */
-/* #undef	VERBOSE */
+/* #undef	VERBOSE_DEBUG */
 
 #if defined(CONFIG_USB_LANGWELL_OTG)
 #define	OTG_TRANSCEIVER
@@ -77,141 +77,110 @@
 /*-------------------------------------------------------------------------*/
 /* debugging */
 
-#ifdef	DEBUG
-#define	DBG(dev, fmt, args...) \
-	pr_debug("%s %s: " fmt , driver_name, \
-			pci_name(dev->pdev), ## args)
-#else
-#define	DBG(dev, fmt, args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-
-#ifdef	VERBOSE
-#define	VDBG DBG
-#else
-#define	VDBG(dev, fmt, args...) \
-	do { } while (0)
-#endif	/* VERBOSE */
-
-
-#define	ERROR(dev, fmt, args...) \
-	pr_err("%s %s: " fmt , driver_name, \
-			pci_name(dev->pdev), ## args)
-
-#define	WARNING(dev, fmt, args...) \
-	pr_warning("%s %s: " fmt , driver_name, \
-			pci_name(dev->pdev), ## args)
-
-#define	INFO(dev, fmt, args...) \
-	pr_info("%s %s: " fmt , driver_name, \
-			pci_name(dev->pdev), ## args)
-
-
-#ifdef	VERBOSE
+#ifdef	VERBOSE_DEBUG
 static inline void print_all_registers(struct langwell_udc *dev)
 {
 	int	i;
 
 	/* Capability Registers */
-	printk(KERN_DEBUG "Capability Registers (offset: "
-			"0x%04x, length: 0x%08x)\n",
-			CAP_REG_OFFSET,
-			(u32)sizeof(struct langwell_cap_regs));
-	printk(KERN_DEBUG "caplength=0x%02x\n",
+	dev_dbg(&dev->pdev->dev,
+		"Capability Registers (offset: 0x%04x, length: 0x%08x)\n",
+		CAP_REG_OFFSET, (u32)sizeof(struct langwell_cap_regs));
+	dev_dbg(&dev->pdev->dev, "caplength=0x%02x\n",
 			readb(&dev->cap_regs->caplength));
-	printk(KERN_DEBUG "hciversion=0x%04x\n",
+	dev_dbg(&dev->pdev->dev, "hciversion=0x%04x\n",
 			readw(&dev->cap_regs->hciversion));
-	printk(KERN_DEBUG "hcsparams=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "hcsparams=0x%08x\n",
 			readl(&dev->cap_regs->hcsparams));
-	printk(KERN_DEBUG "hccparams=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "hccparams=0x%08x\n",
 			readl(&dev->cap_regs->hccparams));
-	printk(KERN_DEBUG "dciversion=0x%04x\n",
+	dev_dbg(&dev->pdev->dev, "dciversion=0x%04x\n",
 			readw(&dev->cap_regs->dciversion));
-	printk(KERN_DEBUG "dccparams=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "dccparams=0x%08x\n",
 			readl(&dev->cap_regs->dccparams));
 
 	/* Operational Registers */
-	printk(KERN_DEBUG "Operational Registers (offset: "
-			"0x%04x, length: 0x%08x)\n",
-			OP_REG_OFFSET,
-			(u32)sizeof(struct langwell_op_regs));
-	printk(KERN_DEBUG "extsts=0x%08x\n",
+	dev_dbg(&dev->pdev->dev,
+		"Operational Registers (offset: 0x%04x, length: 0x%08x)\n",
+		OP_REG_OFFSET, (u32)sizeof(struct langwell_op_regs));
+	dev_dbg(&dev->pdev->dev, "extsts=0x%08x\n",
 			readl(&dev->op_regs->extsts));
-	printk(KERN_DEBUG "extintr=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "extintr=0x%08x\n",
 			readl(&dev->op_regs->extintr));
-	printk(KERN_DEBUG "usbcmd=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "usbcmd=0x%08x\n",
 			readl(&dev->op_regs->usbcmd));
-	printk(KERN_DEBUG "usbsts=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "usbsts=0x%08x\n",
 			readl(&dev->op_regs->usbsts));
-	printk(KERN_DEBUG "usbintr=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "usbintr=0x%08x\n",
 			readl(&dev->op_regs->usbintr));
-	printk(KERN_DEBUG "frindex=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "frindex=0x%08x\n",
 			readl(&dev->op_regs->frindex));
-	printk(KERN_DEBUG "ctrldssegment=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "ctrldssegment=0x%08x\n",
 			readl(&dev->op_regs->ctrldssegment));
-	printk(KERN_DEBUG "deviceaddr=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "deviceaddr=0x%08x\n",
 			readl(&dev->op_regs->deviceaddr));
-	printk(KERN_DEBUG "endpointlistaddr=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endpointlistaddr=0x%08x\n",
 			readl(&dev->op_regs->endpointlistaddr));
-	printk(KERN_DEBUG "ttctrl=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "ttctrl=0x%08x\n",
 			readl(&dev->op_regs->ttctrl));
-	printk(KERN_DEBUG "burstsize=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "burstsize=0x%08x\n",
 			readl(&dev->op_regs->burstsize));
-	printk(KERN_DEBUG "txfilltuning=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "txfilltuning=0x%08x\n",
 			readl(&dev->op_regs->txfilltuning));
-	printk(KERN_DEBUG "txttfilltuning=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "txttfilltuning=0x%08x\n",
 			readl(&dev->op_regs->txttfilltuning));
-	printk(KERN_DEBUG "ic_usb=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "ic_usb=0x%08x\n",
 			readl(&dev->op_regs->ic_usb));
-	printk(KERN_DEBUG "ulpi_viewport=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "ulpi_viewport=0x%08x\n",
 			readl(&dev->op_regs->ulpi_viewport));
-	printk(KERN_DEBUG "configflag=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "configflag=0x%08x\n",
 			readl(&dev->op_regs->configflag));
-	printk(KERN_DEBUG "portsc1=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "portsc1=0x%08x\n",
 			readl(&dev->op_regs->portsc1));
-	printk(KERN_DEBUG "devlc=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "devlc=0x%08x\n",
 			readl(&dev->op_regs->devlc));
-	printk(KERN_DEBUG "otgsc=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "otgsc=0x%08x\n",
 			readl(&dev->op_regs->otgsc));
-	printk(KERN_DEBUG "usbmode=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "usbmode=0x%08x\n",
 			readl(&dev->op_regs->usbmode));
-	printk(KERN_DEBUG "endptnak=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptnak=0x%08x\n",
 			readl(&dev->op_regs->endptnak));
-	printk(KERN_DEBUG "endptnaken=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptnaken=0x%08x\n",
 			readl(&dev->op_regs->endptnaken));
-	printk(KERN_DEBUG "endptsetupstat=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptsetupstat=0x%08x\n",
 			readl(&dev->op_regs->endptsetupstat));
-	printk(KERN_DEBUG "endptprime=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptprime=0x%08x\n",
 			readl(&dev->op_regs->endptprime));
-	printk(KERN_DEBUG "endptflush=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptflush=0x%08x\n",
 			readl(&dev->op_regs->endptflush));
-	printk(KERN_DEBUG "endptstat=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptstat=0x%08x\n",
 			readl(&dev->op_regs->endptstat));
-	printk(KERN_DEBUG "endptcomplete=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptcomplete=0x%08x\n",
 			readl(&dev->op_regs->endptcomplete));
 
 	for (i = 0; i < dev->ep_max / 2; i++) {
-		printk(KERN_DEBUG "endptctrl[%d]=0x%08x\n",
+		dev_dbg(&dev->pdev->dev, "endptctrl[%d]=0x%08x\n",
 				i, readl(&dev->op_regs->endptctrl[i]));
 	}
 }
-#endif /* VERBOSE */
+#else
+
+#define	print_all_registers(dev)	do { } while (0)
+
+#endif /* VERBOSE_DEBUG */
 
 
 /*-------------------------------------------------------------------------*/
 
-#define	DIR_STRING(bAddress)	(((bAddress) & USB_DIR_IN) ? "in" : "out")
+#define	is_in(ep)	(((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir ==	\
+			USB_DIR_IN) : (usb_endpoint_dir_in((ep)->desc)))
 
-#define is_in(ep)	(((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir == \
-			USB_DIR_IN) : ((ep)->desc->bEndpointAddress \
-			& USB_DIR_IN) == USB_DIR_IN)
+#define	DIR_STRING(ep)	(is_in(ep) ? "in" : "out")
 
 
-#ifdef	DEBUG
-static char *type_string(u8 bmAttributes)
+static char *type_string(const struct usb_endpoint_descriptor *desc)
 {
-	switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) {
+	switch (usb_endpoint_type(desc)) {
 	case USB_ENDPOINT_XFER_BULK:
 		return "bulk";
 	case USB_ENDPOINT_XFER_ISOC:
@@ -222,7 +191,6 @@
 
 	return "control";
 }
-#endif
 
 
 /* configure endpoint control registers */
@@ -233,7 +201,7 @@
 	u32			endptctrl;
 
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
 	if (is_in) {	/* TX */
@@ -250,7 +218,7 @@
 
 	writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -260,7 +228,7 @@
 	struct langwell_ep	*ep;
 	int			i;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* ep0 in and out */
 	for (i = 0; i < 2; i++) {
@@ -274,17 +242,18 @@
 		ep->dqh->dqh_ios = 1;
 		ep->dqh->dqh_mpl = EP0_MAX_PKT_SIZE;
 
-		/* FIXME: enable ep0-in HW zero length termination select */
+		/* enable ep0-in HW zero length termination select */
 		if (is_in(ep))
 			ep->dqh->dqh_zlt = 0;
 		ep->dqh->dqh_mult = 0;
 
+		ep->dqh->dtd_next = DTD_TERM;
+
 		/* configure ep0 control registers */
 		ep_reset(&dev->ep[0], 0, i, USB_ENDPOINT_XFER_CONTROL);
 	}
 
-	VDBG(dev, "<--- %s()\n", __func__);
-	return;
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -300,12 +269,12 @@
 	struct langwell_ep	*ep;
 	u16			max = 0;
 	unsigned long		flags;
-	int			retval = 0;
+	int			i, retval = 0;
 	unsigned char		zlt, ios = 0, mult = 0;
 
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !desc || ep->desc
 			|| desc->bDescriptorType != USB_DT_ENDPOINT)
@@ -326,7 +295,7 @@
 	 * sanity check type, direction, address, and then
 	 * initialize the endpoint capabilities fields in dQH
 	 */
-	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	switch (usb_endpoint_type(desc)) {
 	case USB_ENDPOINT_XFER_CONTROL:
 		ios = 1;
 		break;
@@ -386,33 +355,36 @@
 
 	spin_lock_irqsave(&dev->lock, flags);
 
-	/* configure endpoint capabilities in dQH */
-	ep->dqh->dqh_ios = ios;
-	ep->dqh->dqh_mpl = cpu_to_le16(max);
-	ep->dqh->dqh_zlt = zlt;
-	ep->dqh->dqh_mult = mult;
-
 	ep->ep.maxpacket = max;
 	ep->desc = desc;
 	ep->stopped = 0;
-	ep->ep_num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	ep->ep_num = usb_endpoint_num(desc);
 
 	/* ep_type */
-	ep->ep_type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+	ep->ep_type = usb_endpoint_type(desc);
 
 	/* configure endpoint control registers */
 	ep_reset(ep, ep->ep_num, is_in(ep), ep->ep_type);
 
-	DBG(dev, "enabled %s (ep%d%s-%s), max %04x\n",
+	/* configure endpoint capabilities in dQH */
+	i = ep->ep_num * 2 + is_in(ep);
+	ep->dqh = &dev->ep_dqh[i];
+	ep->dqh->dqh_ios = ios;
+	ep->dqh->dqh_mpl = cpu_to_le16(max);
+	ep->dqh->dqh_zlt = zlt;
+	ep->dqh->dqh_mult = mult;
+	ep->dqh->dtd_next = DTD_TERM;
+
+	dev_dbg(&dev->pdev->dev, "enabled %s (ep%d%s-%s), max %04x\n",
 			_ep->name,
 			ep->ep_num,
-			DIR_STRING(desc->bEndpointAddress),
-			type_string(desc->bmAttributes),
+			DIR_STRING(ep),
+			type_string(desc),
 			max);
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 done:
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
 
@@ -428,7 +400,7 @@
 	struct langwell_dtd	*curr_dtd, *next_dtd;
 	int			i;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* remove the req from ep->queue */
 	list_del_init(&req->queue);
@@ -448,7 +420,8 @@
 	}
 
 	if (req->mapped) {
-		dma_unmap_single(&dev->pdev->dev, req->req.dma, req->req.length,
+		dma_unmap_single(&dev->pdev->dev,
+			req->req.dma, req->req.length,
 			is_in(ep) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
 		req->req.dma = DMA_ADDR_INVALID;
 		req->mapped = 0;
@@ -458,9 +431,10 @@
 				is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 
 	if (status != -ESHUTDOWN)
-		DBG(dev, "complete %s, req %p, stat %d, len %u/%u\n",
-			ep->ep.name, &req->req, status,
-			req->req.actual, req->req.length);
+		dev_dbg(&dev->pdev->dev,
+				"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;
@@ -473,7 +447,7 @@
 	spin_lock(&dev->lock);
 	ep->stopped = stopped;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -511,7 +485,7 @@
 
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !ep->desc)
 		return -EINVAL;
@@ -535,8 +509,8 @@
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	DBG(dev, "disabled %s\n", _ep->name);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "disabled %s\n", _ep->name);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 
 	return 0;
 }
@@ -555,7 +529,7 @@
 
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	req = kzalloc(sizeof(*req), gfp_flags);
 	if (!req)
@@ -564,8 +538,8 @@
 	req->req.dma = DMA_ADDR_INVALID;
 	INIT_LIST_HEAD(&req->queue);
 
-	VDBG(dev, "alloc request for %s\n", _ep->name);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "alloc request for %s\n", _ep->name);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return &req->req;
 }
 
@@ -580,7 +554,7 @@
 
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !_req)
 		return;
@@ -591,8 +565,8 @@
 	if (_req)
 		kfree(req);
 
-	VDBG(dev, "free request for %s\n", _ep->name);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "free request for %s\n", _ep->name);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -608,23 +582,24 @@
 	struct langwell_udc	*dev;
 
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	i = ep->ep_num * 2 + is_in(ep);
 	dqh = &dev->ep_dqh[i];
 
 	if (ep->ep_num)
-		VDBG(dev, "%s\n", ep->name);
+		dev_vdbg(&dev->pdev->dev, "%s\n", ep->name);
 	else
 		/* ep0 */
-		VDBG(dev, "%s-%s\n", ep->name, is_in(ep) ? "in" : "out");
+		dev_vdbg(&dev->pdev->dev, "%s-%s\n", ep->name, DIR_STRING(ep));
 
-	VDBG(dev, "ep_dqh[%d] addr: 0x%08x\n", i, (u32)&(dev->ep_dqh[i]));
+	dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%08x\n",
+			i, (u32)&(dev->ep_dqh[i]));
 
 	bit_mask = is_in(ep) ?
 		(1 << (ep->ep_num + 16)) : (1 << (ep->ep_num));
 
-	VDBG(dev, "bit_mask = 0x%08x\n", bit_mask);
+	dev_vdbg(&dev->pdev->dev, "bit_mask = 0x%08x\n", bit_mask);
 
 	/* check if the pipe is empty */
 	if (!(list_empty(&ep->queue))) {
@@ -665,14 +640,17 @@
 	/* clear active and halt bit */
 	dtd_status = (u8) ~(DTD_STS_ACTIVE | DTD_STS_HALTED);
 	dqh->dtd_status &= dtd_status;
-	VDBG(dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status);
+	dev_vdbg(&dev->pdev->dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status);
+
+	/* ensure that updates to the dQH will occure before priming */
+	wmb();
 
 	/* write 1 to endptprime register to PRIME endpoint */
 	bit_mask = is_in(ep) ? (1 << (ep->ep_num + 16)) : (1 << ep->ep_num);
-	VDBG(dev, "endprime bit_mask = 0x%08x\n", bit_mask);
+	dev_vdbg(&dev->pdev->dev, "endprime bit_mask = 0x%08x\n", bit_mask);
 	writel(bit_mask, &dev->op_regs->endptprime);
 out:
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -687,7 +665,7 @@
 	int			i;
 
 	dev = req->ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* the maximum transfer length, up to 16k bytes */
 	*length = min(req->req.length - req->req.actual,
@@ -708,7 +686,7 @@
 
 	/* fill in total bytes with transfer size */
 	dtd->dtd_total = cpu_to_le16(*length);
-	VDBG(dev, "dtd->dtd_total = %d\n", dtd->dtd_total);
+	dev_vdbg(&dev->pdev->dev, "dtd->dtd_total = %d\n", dtd->dtd_total);
 
 	/* set is_last flag if req->req.zero is set or not */
 	if (req->req.zero) {
@@ -722,7 +700,7 @@
 		*is_last = 0;
 
 	if (*is_last == 0)
-		VDBG(dev, "multi-dtd request!\n");
+		dev_vdbg(&dev->pdev->dev, "multi-dtd request!\n");
 
 	/* set interrupt on complete bit for the last dTD */
 	if (*is_last && !req->req.no_interrupt)
@@ -733,10 +711,12 @@
 
 	/* set the active bit of status field to 1 */
 	dtd->dtd_status = DTD_STS_ACTIVE;
-	VDBG(dev, "dtd->dtd_status = 0x%02x\n", dtd->dtd_status);
+	dev_vdbg(&dev->pdev->dev, "dtd->dtd_status = 0x%02x\n",
+			dtd->dtd_status);
 
-	VDBG(dev, "length = %d, dma addr= 0x%08x\n", *length, (int)*dma);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "length = %d, dma addr= 0x%08x\n",
+			*length, (int)*dma);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return dtd;
 }
 
@@ -751,7 +731,7 @@
 	dma_addr_t		dma;
 
 	dev = req->ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 	do {
 		dtd = build_dtd(req, &count, &dma, &is_last);
 		if (dtd == NULL)
@@ -773,7 +753,7 @@
 
 	req->tail = dtd;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -803,9 +783,9 @@
 
 	dev = ep->dev;
 	req->ep = ep;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+	if (usb_endpoint_xfer_isoc(ep->desc)) {
 		if (req->req.length > ep->ep.maxpacket)
 			return -EMSGSIZE;
 		is_iso = 1;
@@ -818,7 +798,7 @@
 	if (_req->dma == DMA_ADDR_INVALID) {
 		/* WORKAROUND: WARN_ON(size == 0) */
 		if (_req->length == 0) {
-			VDBG(dev, "req->length: 0->1\n");
+			dev_vdbg(&dev->pdev->dev, "req->length: 0->1\n");
 			zlflag = 1;
 			_req->length++;
 		}
@@ -827,24 +807,25 @@
 				_req->buf, _req->length,
 				is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 		if (zlflag && (_req->length == 1)) {
-			VDBG(dev, "req->length: 1->0\n");
+			dev_vdbg(&dev->pdev->dev, "req->length: 1->0\n");
 			zlflag = 0;
 			_req->length = 0;
 		}
 
 		req->mapped = 1;
-		VDBG(dev, "req->mapped = 1\n");
+		dev_vdbg(&dev->pdev->dev, "req->mapped = 1\n");
 	} else {
 		dma_sync_single_for_device(&dev->pdev->dev,
 				_req->dma, _req->length,
 				is_in(ep) ?  DMA_TO_DEVICE : DMA_FROM_DEVICE);
 		req->mapped = 0;
-		VDBG(dev, "req->mapped = 0\n");
+		dev_vdbg(&dev->pdev->dev, "req->mapped = 0\n");
 	}
 
-	DBG(dev, "%s queue req %p, len %u, buf %p, dma 0x%08llx\n",
-	    _ep->name,
-	    _req, _req->length, _req->buf, (unsigned long long)_req->dma);
+	dev_dbg(&dev->pdev->dev,
+			"%s queue req %p, len %u, buf %p, dma 0x%08x\n",
+			_ep->name,
+			_req, _req->length, _req->buf, (int)_req->dma);
 
 	_req->status = -EINPROGRESS;
 	_req->actual = 0;
@@ -866,12 +847,12 @@
 
 	if (likely(req != NULL)) {
 		list_add_tail(&req->queue, &ep->queue);
-		VDBG(dev, "list_add_tail() \n");
+		dev_vdbg(&dev->pdev->dev, "list_add_tail()\n");
 	}
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -888,7 +869,7 @@
 
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !ep->desc || !_req)
 		return -EINVAL;
@@ -924,7 +905,7 @@
 
 	/* queue head may be partially complete. */
 	if (ep->queue.next == &req->queue) {
-		DBG(dev, "unlink (%s) dma\n", _ep->name);
+		dev_dbg(&dev->pdev->dev, "unlink (%s) dma\n", _ep->name);
 		_req->status = -ECONNRESET;
 		langwell_ep_fifo_flush(&ep->ep);
 
@@ -963,7 +944,7 @@
 	ep->stopped = stopped;
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
 
@@ -976,7 +957,7 @@
 	u32			endptctrl = 0;
 	int			ep_num;
 	struct langwell_udc	*dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	ep_num = ep->ep_num;
 	endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
@@ -1001,7 +982,7 @@
 
 	writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1016,7 +997,7 @@
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !ep->desc)
 		return -EINVAL;
@@ -1024,8 +1005,7 @@
 	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
 		return -ESHUTDOWN;
 
-	if (ep->desc && (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-			== USB_ENDPOINT_XFER_ISOC)
+	if (usb_endpoint_xfer_isoc(ep->desc))
 		return  -EOPNOTSUPP;
 
 	spin_lock_irqsave(&dev->lock, flags);
@@ -1036,7 +1016,7 @@
 	 */
 	if (!list_empty(&ep->queue) && is_in(ep) && value) {
 		/* IN endpoint FIFO holds bytes */
-		DBG(dev, "%s FIFO holds bytes\n", _ep->name);
+		dev_dbg(&dev->pdev->dev, "%s FIFO holds bytes\n", _ep->name);
 		retval = -EAGAIN;
 		goto done;
 	}
@@ -1050,8 +1030,9 @@
 	}
 done:
 	spin_unlock_irqrestore(&dev->lock, flags);
-	DBG(dev, "%s %s halt\n", _ep->name, value ? "set" : "clear");
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "%s %s halt\n",
+			_ep->name, value ? "set" : "clear");
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
 
@@ -1065,12 +1046,12 @@
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !ep->desc)
 		return -EINVAL;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return usb_ep_set_halt(_ep);
 }
 
@@ -1086,15 +1067,16 @@
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !ep->desc) {
-		VDBG(dev, "ep or ep->desc is NULL\n");
-		VDBG(dev, "<--- %s()\n", __func__);
+		dev_vdbg(&dev->pdev->dev, "ep or ep->desc is NULL\n");
+		dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 		return;
 	}
 
-	VDBG(dev, "%s-%s fifo flush\n", _ep->name, is_in(ep) ? "in" : "out");
+	dev_vdbg(&dev->pdev->dev, "%s-%s fifo flush\n",
+			_ep->name, DIR_STRING(ep));
 
 	/* flush endpoint buffer */
 	if (ep->ep_num == 0)
@@ -1110,14 +1092,14 @@
 		writel(flush_bit, &dev->op_regs->endptflush);
 		while (readl(&dev->op_regs->endptflush)) {
 			if (time_after(jiffies, timeout)) {
-				ERROR(dev, "ep flush timeout\n");
+				dev_err(&dev->pdev->dev, "ep flush timeout\n");
 				goto done;
 			}
 			cpu_relax();
 		}
 	} while (readl(&dev->op_regs->endptstat) & flush_bit);
 done:
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1167,31 +1149,59 @@
 		return -ENODEV;
 
 	dev = container_of(_gadget, struct langwell_udc, gadget);
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	retval = readl(&dev->op_regs->frindex) & FRINDEX_MASK;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
 
 
+/* enter or exit PHY low power state */
+static void langwell_phy_low_power(struct langwell_udc *dev, bool flag)
+{
+	u32		devlc;
+	u8		devlc_byte2;
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
+
+	devlc = readl(&dev->op_regs->devlc);
+	dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc);
+
+	if (flag)
+		devlc |= LPM_PHCD;
+	else
+		devlc &= ~LPM_PHCD;
+
+	/* FIXME: workaround for Langwell A1/A2/A3 sighting */
+	devlc_byte2 = (devlc >> 16) & 0xff;
+	writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2);
+
+	devlc = readl(&dev->op_regs->devlc);
+	dev_vdbg(&dev->pdev->dev,
+			"%s PHY low power suspend, devlc = 0x%08x\n",
+			flag ? "enter" : "exit", devlc);
+}
+
+
 /* tries to wake up the host connected to this gadget */
 static int langwell_wakeup(struct usb_gadget *_gadget)
 {
 	struct langwell_udc	*dev;
-	u32 			portsc1, devlc;
-	unsigned long   	flags;
+	u32			portsc1;
+	unsigned long		flags;
 
 	if (!_gadget)
 		return 0;
 
 	dev = container_of(_gadget, struct langwell_udc, gadget);
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	/* Remote Wakeup feature not enabled by host */
-	if (!dev->remote_wakeup)
+	/* remote wakeup feature not enabled by host */
+	if (!dev->remote_wakeup) {
+		dev_info(&dev->pdev->dev, "remote wakeup is disabled\n");
 		return -ENOTSUPP;
+	}
 
 	spin_lock_irqsave(&dev->lock, flags);
 
@@ -1201,27 +1211,23 @@
 		return 0;
 	}
 
-	/* LPM L1 to L0, remote wakeup */
-	if (dev->lpm && dev->lpm_state == LPM_L1) {
-		portsc1 |= PORTS_SLP;
-		writel(portsc1, &dev->op_regs->portsc1);
-	}
-
-	/* force port resume */
-	if (dev->usb_state == USB_STATE_SUSPENDED) {
-		portsc1 |= PORTS_FPR;
-		writel(portsc1, &dev->op_regs->portsc1);
-	}
+	/* LPM L1 to L0 or legacy remote wakeup */
+	if (dev->lpm && dev->lpm_state == LPM_L1)
+		dev_info(&dev->pdev->dev, "LPM L1 to L0 remote wakeup\n");
+	else
+		dev_info(&dev->pdev->dev, "device remote wakeup\n");
 
 	/* exit PHY low power suspend */
-	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "devlc = 0x%08x\n", devlc);
-	devlc &= ~LPM_PHCD;
-	writel(devlc, &dev->op_regs->devlc);
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 0);
+
+	/* force port resume */
+	portsc1 |= PORTS_FPR;
+	writel(portsc1, &dev->op_regs->portsc1);
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -1231,16 +1237,17 @@
 {
 	struct langwell_udc	*dev;
 	unsigned long		flags;
-	u32             	usbcmd;
+	u32			usbcmd;
 
 	if (!_gadget)
 		return -ENODEV;
 
 	dev = container_of(_gadget, struct langwell_udc, gadget);
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	spin_lock_irqsave(&dev->lock, flags);
-	VDBG(dev, "VBUS status: %s\n", is_active ? "on" : "off");
+	dev_vdbg(&dev->pdev->dev, "VBUS status: %s\n",
+			is_active ? "on" : "off");
 
 	dev->vbus_active = (is_active != 0);
 	if (dev->driver && dev->softconnected && dev->vbus_active) {
@@ -1255,7 +1262,7 @@
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -1269,15 +1276,15 @@
 		return -ENODEV;
 
 	dev = container_of(_gadget, struct langwell_udc, gadget);
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dev->transceiver) {
-		VDBG(dev, "otg_set_power\n");
-		VDBG(dev, "<--- %s()\n", __func__);
+		dev_vdbg(&dev->pdev->dev, "otg_set_power\n");
+		dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 		return otg_set_power(dev->transceiver, mA);
 	}
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return -ENOTSUPP;
 }
 
@@ -1286,15 +1293,15 @@
 static int langwell_pullup(struct usb_gadget *_gadget, int is_on)
 {
 	struct langwell_udc	*dev;
-	u32             	usbcmd;
-	unsigned long   	flags;
+	u32			usbcmd;
+	unsigned long		flags;
 
 	if (!_gadget)
 		return -ENODEV;
 
 	dev = container_of(_gadget, struct langwell_udc, gadget);
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	spin_lock_irqsave(&dev->lock, flags);
 	dev->softconnected = (is_on != 0);
@@ -1310,7 +1317,7 @@
 	}
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -1346,12 +1353,13 @@
 static int langwell_udc_reset(struct langwell_udc *dev)
 {
 	u32		usbcmd, usbmode, devlc, endpointlistaddr;
+	u8		devlc_byte0, devlc_byte2;
 	unsigned long	timeout;
 
 	if (!dev)
 		return -EINVAL;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* set controller to stop state */
 	usbcmd = readl(&dev->op_regs->usbcmd);
@@ -1367,7 +1375,7 @@
 	timeout = jiffies + RESET_TIMEOUT;
 	while (readl(&dev->op_regs->usbcmd) & CMD_RST) {
 		if (time_after(jiffies, timeout)) {
-			ERROR(dev, "device reset timeout\n");
+			dev_err(&dev->pdev->dev, "device reset timeout\n");
 			return -ETIMEDOUT;
 		}
 		cpu_relax();
@@ -1382,7 +1390,7 @@
 
 	writel(usbmode, &dev->op_regs->usbmode);
 	usbmode = readl(&dev->op_regs->usbmode);
-	VDBG(dev, "usbmode=0x%08x\n", usbmode);
+	dev_vdbg(&dev->pdev->dev, "usbmode=0x%08x\n", usbmode);
 
 	/* Write-Clear setup status */
 	writel(0, &dev->op_regs->usbsts);
@@ -1390,9 +1398,17 @@
 	/* if support USB LPM, ACK all LPM token */
 	if (dev->lpm) {
 		devlc = readl(&dev->op_regs->devlc);
+		dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc);
+		/* FIXME: workaround for Langwell A1/A2/A3 sighting */
 		devlc &= ~LPM_STL;	/* don't STALL LPM token */
 		devlc &= ~LPM_NYT_ACK;	/* ACK LPM token */
-		writel(devlc, &dev->op_regs->devlc);
+		devlc_byte0 = devlc & 0xff;
+		devlc_byte2 = (devlc >> 16) & 0xff;
+		writeb(devlc_byte0, (u8 *)&dev->op_regs->devlc);
+		writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2);
+		devlc = readl(&dev->op_regs->devlc);
+		dev_vdbg(&dev->pdev->dev,
+				"ACK LPM token, devlc = 0x%08x\n", devlc);
 	}
 
 	/* fill endpointlistaddr register */
@@ -1400,10 +1416,11 @@
 	endpointlistaddr &= ENDPOINTLISTADDR_MASK;
 	writel(endpointlistaddr, &dev->op_regs->endpointlistaddr);
 
-	VDBG(dev, "dQH base (vir: %p, phy: 0x%08x), endpointlistaddr=0x%08x\n",
-			dev->ep_dqh, endpointlistaddr,
-			readl(&dev->op_regs->endpointlistaddr));
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev,
+		"dQH base (vir: %p, phy: 0x%08x), endpointlistaddr=0x%08x\n",
+		dev->ep_dqh, endpointlistaddr,
+		readl(&dev->op_regs->endpointlistaddr));
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -1415,7 +1432,7 @@
 	char			name[14];
 	int			i;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* initialize ep0 */
 	ep = &dev->ep[0];
@@ -1449,11 +1466,9 @@
 
 		INIT_LIST_HEAD(&ep->queue);
 		list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
-
-		ep->dqh = &dev->ep_dqh[i];
 	}
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -1462,7 +1477,7 @@
 static void langwell_udc_start(struct langwell_udc *dev)
 {
 	u32	usbintr, usbcmd;
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* enable interrupts */
 	usbintr = INTR_ULPIE	/* ULPI */
@@ -1485,8 +1500,7 @@
 	usbcmd |= CMD_RUNSTOP;
 	writel(usbcmd, &dev->op_regs->usbcmd);
 
-	DBG(dev, "<--- %s()\n", __func__);
-	return;
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1495,7 +1509,7 @@
 {
 	u32	usbcmd;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* disable all interrupts */
 	writel(0, &dev->op_regs->usbintr);
@@ -1508,8 +1522,7 @@
 	usbcmd &= ~CMD_RUNSTOP;
 	writel(usbcmd, &dev->op_regs->usbcmd);
 
-	DBG(dev, "<--- %s()\n", __func__);
-	return;
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1518,7 +1531,7 @@
 		struct usb_gadget_driver *driver)
 {
 	struct langwell_ep	*ep;
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	nuke(&dev->ep[0], -ESHUTDOWN);
 
@@ -1533,7 +1546,7 @@
 		spin_lock(&dev->lock);
 	}
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1659,13 +1672,15 @@
 		"Over-current Change: %s\n"
 		"Port Enable/Disable Change: %s\n"
 		"Port Enabled/Disabled: %s\n"
-		"Current Connect Status: %s\n\n",
+		"Current Connect Status: %s\n"
+		"LPM Suspend Status: %s\n\n",
 		(tmp_reg & PORTS_PR) ? "Reset" : "Not Reset",
 		(tmp_reg & PORTS_SUSP) ? "Suspend " : "Not Suspend",
 		(tmp_reg & PORTS_OCC) ? "Detected" : "No",
 		(tmp_reg & PORTS_PEC) ? "Changed" : "Not Changed",
 		(tmp_reg & PORTS_PE) ? "Enable" : "Not Correct",
-		(tmp_reg & PORTS_CCS) ?  "Attached" : "Not Attached");
+		(tmp_reg & PORTS_CCS) ?  "Attached" : "Not Attached",
+		(tmp_reg & PORTS_SLP) ? "LPM L1" : "LPM L0");
 	size -= t;
 	next += t;
 
@@ -1676,7 +1691,7 @@
 		"Serial Transceiver : %d\n"
 		"Port Speed: %s\n"
 		"Port Force Full Speed Connenct: %s\n"
-		"PHY Low Power Suspend Clock Disable: %s\n"
+		"PHY Low Power Suspend Clock: %s\n"
 		"BmAttributes: %d\n\n",
 		LPM_PTS(tmp_reg),
 		(tmp_reg & LPM_STS) ? 1 : 0,
@@ -1797,6 +1812,36 @@
 static DEVICE_ATTR(langwell_udc, S_IRUGO, show_langwell_udc, NULL);
 
 
+/* device "remote_wakeup" sysfs attribute file */
+static ssize_t store_remote_wakeup(struct device *_dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct langwell_udc	*dev = the_controller;
+	unsigned long		flags;
+	ssize_t			rc = count;
+
+	if (count > 2)
+		return -EINVAL;
+
+	if (count > 0 && buf[count-1] == '\n')
+		((char *) buf)[count-1] = 0;
+
+	if (buf[0] != '1')
+		return -EINVAL;
+
+	/* force remote wakeup enabled in case gadget driver doesn't support */
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->remote_wakeup = 1;
+	dev->dev_status |= (1 << USB_DEVICE_REMOTE_WAKEUP);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	langwell_wakeup(&dev->gadget);
+
+	return rc;
+}
+static DEVICE_ATTR(remote_wakeup, S_IWUSR, NULL, store_remote_wakeup);
+
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -1807,7 +1852,8 @@
  * the driver might get unbound.
  */
 
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct langwell_udc	*dev = the_controller;
 	unsigned long		flags;
@@ -1816,7 +1862,7 @@
 	if (!dev)
 		return -ENODEV;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dev->driver)
 		return -EBUSY;
@@ -1830,9 +1876,9 @@
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	retval = driver->bind(&dev->gadget);
+	retval = bind(&dev->gadget);
 	if (retval) {
-		DBG(dev, "bind to driver %s --> %d\n",
+		dev_dbg(&dev->pdev->dev, "bind to driver %s --> %d\n",
 				driver->driver.name, retval);
 		dev->driver = NULL;
 		dev->gadget.dev.driver = NULL;
@@ -1851,13 +1897,13 @@
 	if (dev->got_irq)
 		langwell_udc_start(dev);
 
-	VDBG(dev, "After langwell_udc_start(), print all registers:\n");
-#ifdef	VERBOSE
+	dev_vdbg(&dev->pdev->dev,
+			"After langwell_udc_start(), print all registers:\n");
 	print_all_registers(dev);
-#endif
 
-	INFO(dev, "register driver: %s\n", driver->driver.name);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_info(&dev->pdev->dev, "register driver: %s\n",
+			driver->driver.name);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 
 err_unbind:
@@ -1865,10 +1911,10 @@
 	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 
 /* unregister gadget driver */
@@ -1880,11 +1926,15 @@
 	if (!dev)
 		return -ENODEV;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	if (unlikely(!driver || !driver->bind || !driver->unbind))
+	if (unlikely(!driver || !driver->unbind))
 		return -EINVAL;
 
+	/* exit PHY low power suspend */
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 0);
+
 	/* unbind OTG transceiver */
 	if (dev->transceiver)
 		(void)otg_set_peripheral(dev->transceiver, 0);
@@ -1910,8 +1960,9 @@
 
 	device_remove_file(&dev->pdev->dev, &dev_attr_function);
 
-	INFO(dev, "unregistered driver '%s'\n", driver->driver.name);
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_info(&dev->pdev->dev, "unregistered driver '%s'\n",
+			driver->driver.name);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 EXPORT_SYMBOL(usb_gadget_unregister_driver);
@@ -1930,7 +1981,7 @@
 	unsigned long		timeout;
 	struct langwell_dqh	*dqh;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* ep0 OUT dQH */
 	dqh = &dev->ep_dqh[EP_DIR_OUT];
@@ -1943,7 +1994,7 @@
 	timeout = jiffies + SETUPSTAT_TIMEOUT;
 	while (readl(&dev->op_regs->endptsetupstat)) {
 		if (time_after(jiffies, timeout)) {
-			ERROR(dev, "setup_tripwire timeout\n");
+			dev_err(&dev->pdev->dev, "setup_tripwire timeout\n");
 			break;
 		}
 		cpu_relax();
@@ -1963,7 +2014,7 @@
 	usbcmd = readl(&dev->op_regs->usbcmd);
 	writel(usbcmd & ~CMD_SUTW, &dev->op_regs->usbcmd);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1972,7 +2023,7 @@
 {
 	u32	endptctrl;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* set TX and RX to stall */
 	endptctrl = readl(&dev->op_regs->endptctrl[0]);
@@ -1983,7 +2034,7 @@
 	dev->ep0_state = WAIT_FOR_SETUP;
 	dev->ep0_dir = USB_DIR_OUT;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1994,7 +2045,7 @@
 	struct langwell_ep	*ep;
 	int			status = 0;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dir == EP_DIR_IN)
 		dev->ep0_dir = USB_DIR_IN;
@@ -2019,11 +2070,11 @@
 		return -ENOMEM;
 
 	if (status)
-		ERROR(dev, "can't queue ep0 status request\n");
+		dev_err(&dev->pdev->dev, "can't queue ep0 status request\n");
 
 	list_add_tail(&req->queue, &ep->queue);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return status;
 }
 
@@ -2032,11 +2083,11 @@
 static void set_address(struct langwell_udc *dev, u16 value,
 		u16 index, u16 length)
 {
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* save the new address to device struct */
 	dev->dev_addr = (u8) value;
-	VDBG(dev, "dev->dev_addr = %d\n", dev->dev_addr);
+	dev_vdbg(&dev->pdev->dev, "dev->dev_addr = %d\n", dev->dev_addr);
 
 	/* update usb state */
 	dev->usb_state = USB_STATE_ADDRESS;
@@ -2045,7 +2096,7 @@
 	if (prime_status_phase(dev, EP_DIR_IN))
 		ep0_stall(dev);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2054,7 +2105,7 @@
 		u16 wIndex)
 {
 	struct langwell_ep		*ep;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
 		return &dev->ep[0];
@@ -2073,7 +2124,7 @@
 			return ep;
 	}
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return NULL;
 }
 
@@ -2085,7 +2136,7 @@
 	u32			endptctrl;
 	int			retval;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	endptctrl = readl(&dev->op_regs->endptctrl[ep->ep_num]);
 	if (is_in(ep))
@@ -2093,7 +2144,7 @@
 	else
 		retval = endptctrl & EPCTRL_RXS ? 1 : 0;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
 
@@ -2107,14 +2158,13 @@
 	u16	status_data = 0;	/* 16 bits cpu view status data */
 	int	status = 0;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	ep = &dev->ep[0];
 
 	if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
 		/* get device status */
-		status_data = 1 << USB_DEVICE_SELF_POWERED;
-		status_data |= dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP;
+		status_data = dev->dev_status;
 	} else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) {
 		/* get interface status */
 		status_data = 0;
@@ -2129,6 +2179,8 @@
 		status_data = ep_is_stall(epn) << USB_ENDPOINT_HALT;
 	}
 
+	dev_dbg(&dev->pdev->dev, "get status data: 0x%04x\n", status_data);
+
 	dev->ep0_dir = USB_DIR_IN;
 
 	/* borrow the per device status_req */
@@ -2150,18 +2202,19 @@
 		goto stall;
 
 	if (status) {
-		ERROR(dev, "response error on GET_STATUS request\n");
+		dev_err(&dev->pdev->dev,
+				"response error on GET_STATUS request\n");
 		goto stall;
 	}
 
 	list_add_tail(&req->queue, &ep->queue);
 	dev->ep0_state = DATA_STATE_XMIT;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return;
 stall:
 	ep0_stall(dev);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2173,12 +2226,12 @@
 	u16	wIndex = le16_to_cpu(setup->wIndex);
 	u16	wLength = le16_to_cpu(setup->wLength);
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* ep0 fifo flush */
 	nuke(&dev->ep[0], -ESHUTDOWN);
 
-	DBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+	dev_dbg(&dev->pdev->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
 			setup->bRequestType, setup->bRequest,
 			wValue, wIndex, wLength);
 
@@ -2197,7 +2250,7 @@
 	/* We process some stardard setup requests here */
 	switch (setup->bRequest) {
 	case USB_REQ_GET_STATUS:
-		DBG(dev, "SETUP: USB_REQ_GET_STATUS\n");
+		dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_GET_STATUS\n");
 		/* get status, DATA and STATUS phase */
 		if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
 					!= (USB_DIR_IN | USB_TYPE_STANDARD))
@@ -2206,7 +2259,7 @@
 		goto end;
 
 	case USB_REQ_SET_ADDRESS:
-		DBG(dev, "SETUP: USB_REQ_SET_ADDRESS\n");
+		dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_SET_ADDRESS\n");
 		/* STATUS phase */
 		if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
 						| USB_RECIP_DEVICE))
@@ -2220,9 +2273,11 @@
 	{
 		int rc = -EOPNOTSUPP;
 		if (setup->bRequest == USB_REQ_SET_FEATURE)
-			DBG(dev, "SETUP: USB_REQ_SET_FEATURE\n");
+			dev_dbg(&dev->pdev->dev,
+					"SETUP: USB_REQ_SET_FEATURE\n");
 		else if (setup->bRequest == USB_REQ_CLEAR_FEATURE)
-			DBG(dev, "SETUP: USB_REQ_CLEAR_FEATURE\n");
+			dev_dbg(&dev->pdev->dev,
+					"SETUP: USB_REQ_CLEAR_FEATURE\n");
 
 		if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
 				== (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
@@ -2240,13 +2295,29 @@
 
 			spin_unlock(&dev->lock);
 			rc = langwell_ep_set_halt(&epn->ep,
-					(setup->bRequest == USB_REQ_SET_FEATURE)
-						? 1 : 0);
+				(setup->bRequest == USB_REQ_SET_FEATURE)
+				? 1 : 0);
 			spin_lock(&dev->lock);
 
 		} else if ((setup->bRequestType & (USB_RECIP_MASK
 				| USB_TYPE_MASK)) == (USB_RECIP_DEVICE
 				| USB_TYPE_STANDARD)) {
+			rc = 0;
+			switch (wValue) {
+			case USB_DEVICE_REMOTE_WAKEUP:
+				if (setup->bRequest == USB_REQ_SET_FEATURE) {
+					dev->remote_wakeup = 1;
+					dev->dev_status |= (1 << wValue);
+				} else {
+					dev->remote_wakeup = 0;
+					dev->dev_status &= ~(1 << wValue);
+				}
+				break;
+			default:
+				rc = -EOPNOTSUPP;
+				break;
+			}
+
 			if (!gadget_is_otg(&dev->gadget))
 				break;
 			else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) {
@@ -2262,7 +2333,6 @@
 				dev->gadget.a_alt_hnp_support = 1;
 			else
 				break;
-			rc = 0;
 		} else
 			break;
 
@@ -2274,31 +2344,38 @@
 	}
 
 	case USB_REQ_GET_DESCRIPTOR:
-		DBG(dev, "SETUP: USB_REQ_GET_DESCRIPTOR\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_GET_DESCRIPTOR\n");
 		goto delegate;
 
 	case USB_REQ_SET_DESCRIPTOR:
-		DBG(dev, "SETUP: USB_REQ_SET_DESCRIPTOR unsupported\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_SET_DESCRIPTOR unsupported\n");
 		goto delegate;
 
 	case USB_REQ_GET_CONFIGURATION:
-		DBG(dev, "SETUP: USB_REQ_GET_CONFIGURATION\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_GET_CONFIGURATION\n");
 		goto delegate;
 
 	case USB_REQ_SET_CONFIGURATION:
-		DBG(dev, "SETUP: USB_REQ_SET_CONFIGURATION\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_SET_CONFIGURATION\n");
 		goto delegate;
 
 	case USB_REQ_GET_INTERFACE:
-		DBG(dev, "SETUP: USB_REQ_GET_INTERFACE\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_GET_INTERFACE\n");
 		goto delegate;
 
 	case USB_REQ_SET_INTERFACE:
-		DBG(dev, "SETUP: USB_REQ_SET_INTERFACE\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_SET_INTERFACE\n");
 		goto delegate;
 
 	case USB_REQ_SYNCH_FRAME:
-		DBG(dev, "SETUP: USB_REQ_SYNCH_FRAME unsupported\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_SYNCH_FRAME unsupported\n");
 		goto delegate;
 
 	default:
@@ -2310,7 +2387,8 @@
 			/* DATA phase from gadget, STATUS phase from udc */
 			dev->ep0_dir = (setup->bRequestType & USB_DIR_IN)
 					?  USB_DIR_IN : USB_DIR_OUT;
-			VDBG(dev, "dev->ep0_dir = 0x%x, wLength = %d\n",
+			dev_vdbg(&dev->pdev->dev,
+					"dev->ep0_dir = 0x%x, wLength = %d\n",
 					dev->ep0_dir, wLength);
 			spin_unlock(&dev->lock);
 			if (dev->driver->setup(&dev->gadget,
@@ -2322,7 +2400,8 @@
 		} else {
 			/* no DATA phase, IN STATUS phase from gadget */
 			dev->ep0_dir = USB_DIR_IN;
-			VDBG(dev, "dev->ep0_dir = 0x%x, wLength = %d\n",
+			dev_vdbg(&dev->pdev->dev,
+					"dev->ep0_dir = 0x%x, wLength = %d\n",
 					dev->ep0_dir, wLength);
 			spin_unlock(&dev->lock);
 			if (dev->driver->setup(&dev->gadget,
@@ -2334,8 +2413,7 @@
 		break;
 	}
 end:
-	VDBG(dev, "<--- %s()\n", __func__);
-	return;
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2359,23 +2437,27 @@
 	td_complete = 0;
 	actual = curr_req->req.length;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	for (i = 0; i < curr_req->dtd_count; i++) {
-		remaining_length = le16_to_cpu(curr_dtd->dtd_total);
-		actual -= remaining_length;
 
 		/* command execution states by dTD */
 		dtd_status = curr_dtd->dtd_status;
 
+		barrier();
+		remaining_length = le16_to_cpu(curr_dtd->dtd_total);
+		actual -= remaining_length;
+
 		if (!dtd_status) {
 			/* transfers completed successfully */
 			if (!remaining_length) {
 				td_complete++;
-				VDBG(dev, "dTD transmitted successfully\n");
+				dev_vdbg(&dev->pdev->dev,
+					"dTD transmitted successfully\n");
 			} else {
 				if (dir) {
-					VDBG(dev, "TX dTD remains data\n");
+					dev_vdbg(&dev->pdev->dev,
+						"TX dTD remains data\n");
 					retval = -EPROTO;
 					break;
 
@@ -2387,27 +2469,32 @@
 		} else {
 			/* transfers completed with errors */
 			if (dtd_status & DTD_STS_ACTIVE) {
-				DBG(dev, "request not completed\n");
+				dev_dbg(&dev->pdev->dev,
+					"dTD status ACTIVE dQH[%d]\n", index);
 				retval = 1;
 				return retval;
 			} else if (dtd_status & DTD_STS_HALTED) {
-				ERROR(dev, "dTD error %08x dQH[%d]\n",
-						dtd_status, index);
+				dev_err(&dev->pdev->dev,
+					"dTD error %08x dQH[%d]\n",
+					dtd_status, index);
 				/* clear the errors and halt condition */
 				curr_dqh->dtd_status = 0;
 				retval = -EPIPE;
 				break;
 			} else if (dtd_status & DTD_STS_DBE) {
-				DBG(dev, "data buffer (overflow) error\n");
+				dev_dbg(&dev->pdev->dev,
+					"data buffer (overflow) error\n");
 				retval = -EPROTO;
 				break;
 			} else if (dtd_status & DTD_STS_TRE) {
-				DBG(dev, "transaction(ISO) error\n");
+				dev_dbg(&dev->pdev->dev,
+					"transaction(ISO) error\n");
 				retval = -EILSEQ;
 				break;
 			} else
-				ERROR(dev, "unknown error (0x%x)!\n",
-						dtd_status);
+				dev_err(&dev->pdev->dev,
+					"unknown error (0x%x)!\n",
+					dtd_status);
 		}
 
 		if (i != curr_req->dtd_count - 1)
@@ -2420,7 +2507,7 @@
 
 	curr_req->req.actual = actual;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -2430,7 +2517,7 @@
 		struct langwell_ep *ep0, struct langwell_request *req)
 {
 	u32	new_addr;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dev->usb_state == USB_STATE_ADDRESS) {
 		/* set the new address */
@@ -2438,7 +2525,7 @@
 		writel(new_addr << USBADR_SHIFT, &dev->op_regs->deviceaddr);
 
 		new_addr = USBADR(readl(&dev->op_regs->deviceaddr));
-		VDBG(dev, "new_addr = %d\n", new_addr);
+		dev_vdbg(&dev->pdev->dev, "new_addr = %d\n", new_addr);
 	}
 
 	done(ep0, req, 0);
@@ -2458,14 +2545,14 @@
 		dev->ep0_state = WAIT_FOR_SETUP;
 		break;
 	case WAIT_FOR_SETUP:
-		ERROR(dev, "unexpect ep0 packets\n");
+		dev_err(&dev->pdev->dev, "unexpect ep0 packets\n");
 		break;
 	default:
 		ep0_stall(dev);
 		break;
 	}
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2477,16 +2564,17 @@
 	struct langwell_ep	*epn;
 	struct langwell_request	*curr_req, *temp_req;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	complete_bits = readl(&dev->op_regs->endptcomplete);
-	VDBG(dev, "endptcomplete register: 0x%08x\n", complete_bits);
+	dev_vdbg(&dev->pdev->dev, "endptcomplete register: 0x%08x\n",
+			complete_bits);
 
 	/* Write-Clear the bits in endptcomplete register */
 	writel(complete_bits, &dev->op_regs->endptcomplete);
 
 	if (!complete_bits) {
-		DBG(dev, "complete_bits = 0\n");
+		dev_dbg(&dev->pdev->dev, "complete_bits = 0\n");
 		goto done;
 	}
 
@@ -2506,23 +2594,25 @@
 			epn = &dev->ep[i];
 
 		if (epn->name == NULL) {
-			WARNING(dev, "invalid endpoint\n");
+			dev_warn(&dev->pdev->dev, "invalid endpoint\n");
 			continue;
 		}
 
 		if (i < 2)
 			/* ep0 in and out */
-			DBG(dev, "%s-%s transfer completed\n",
+			dev_dbg(&dev->pdev->dev, "%s-%s transfer completed\n",
 					epn->name,
 					is_in(epn) ? "in" : "out");
 		else
-			DBG(dev, "%s transfer completed\n", epn->name);
+			dev_dbg(&dev->pdev->dev, "%s transfer completed\n",
+					epn->name);
 
 		/* process the req queue until an uncomplete request */
 		list_for_each_entry_safe(curr_req, temp_req,
 				&epn->queue, queue) {
 			status = process_ep_req(dev, i, curr_req);
-			VDBG(dev, "%s req status: %d\n", epn->name, status);
+			dev_vdbg(&dev->pdev->dev, "%s req status: %d\n",
+					epn->name, status);
 
 			if (status)
 				break;
@@ -2540,8 +2630,7 @@
 		}
 	}
 done:
-	VDBG(dev, "<--- %s()\n", __func__);
-	return;
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2551,14 +2640,14 @@
 	u32	portsc1, devlc;
 	u32	speed;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dev->bus_reset)
 		dev->bus_reset = 0;
 
 	portsc1 = readl(&dev->op_regs->portsc1);
 	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "portsc1 = 0x%08x, devlc = 0x%08x\n",
+	dev_vdbg(&dev->pdev->dev, "portsc1 = 0x%08x, devlc = 0x%08x\n",
 			portsc1, devlc);
 
 	/* bus reset is finished */
@@ -2579,25 +2668,22 @@
 			dev->gadget.speed = USB_SPEED_UNKNOWN;
 			break;
 		}
-		VDBG(dev, "speed = %d, dev->gadget.speed = %d\n",
+		dev_vdbg(&dev->pdev->dev,
+				"speed = %d, dev->gadget.speed = %d\n",
 				speed, dev->gadget.speed);
 	}
 
 	/* LPM L0 to L1 */
 	if (dev->lpm && dev->lpm_state == LPM_L0)
 		if (portsc1 & PORTS_SUSP && portsc1 & PORTS_SLP) {
-				INFO(dev, "LPM L0 to L1\n");
-				dev->lpm_state = LPM_L1;
+			dev_info(&dev->pdev->dev, "LPM L0 to L1\n");
+			dev->lpm_state = LPM_L1;
 		}
 
 	/* LPM L1 to L0, force resume or remote wakeup finished */
 	if (dev->lpm && dev->lpm_state == LPM_L1)
 		if (!(portsc1 & PORTS_SUSP)) {
-			if (portsc1 & PORTS_SLP)
-				INFO(dev, "LPM L1 to L0, force resume\n");
-			else
-				INFO(dev, "LPM L1 to L0, remote wakeup\n");
-
+			dev_info(&dev->pdev->dev, "LPM L1 to L0\n");
 			dev->lpm_state = LPM_L0;
 		}
 
@@ -2605,7 +2691,7 @@
 	if (!dev->resume_state)
 		dev->usb_state = USB_STATE_DEFAULT;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2617,7 +2703,7 @@
 			endptcomplete;
 	unsigned long	timeout;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* Write-Clear the device address */
 	deviceaddr = readl(&dev->op_regs->deviceaddr);
@@ -2634,7 +2720,10 @@
 
 	dev->ep0_dir = USB_DIR_OUT;
 	dev->ep0_state = WAIT_FOR_SETUP;
-	dev->remote_wakeup = 0;		/* default to 0 on reset */
+
+	/* remote wakeup reset to 0 when the device is reset */
+	dev->remote_wakeup = 0;
+	dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
 	dev->gadget.b_hnp_enable = 0;
 	dev->gadget.a_hnp_support = 0;
 	dev->gadget.a_alt_hnp_support = 0;
@@ -2651,7 +2740,7 @@
 	timeout = jiffies + PRIME_TIMEOUT;
 	while (readl(&dev->op_regs->endptprime)) {
 		if (time_after(jiffies, timeout)) {
-			ERROR(dev, "USB reset timeout\n");
+			dev_err(&dev->pdev->dev, "USB reset timeout\n");
 			break;
 		}
 		cpu_relax();
@@ -2661,7 +2750,7 @@
 	writel((u32) ~0, &dev->op_regs->endptflush);
 
 	if (readl(&dev->op_regs->portsc1) & PORTS_PR) {
-		VDBG(dev, "USB bus reset\n");
+		dev_vdbg(&dev->pdev->dev, "USB bus reset\n");
 		/* bus is reseting */
 		dev->bus_reset = 1;
 
@@ -2669,7 +2758,7 @@
 		stop_activity(dev, dev->driver);
 		dev->usb_state = USB_STATE_DEFAULT;
 	} else {
-		VDBG(dev, "device controller reset\n");
+		dev_vdbg(&dev->pdev->dev, "device controller reset\n");
 		/* controller reset */
 		langwell_udc_reset(dev);
 
@@ -2691,15 +2780,14 @@
 		dev->lotg->hsm.b_hnp_enable = 0;
 #endif
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
 /* USB bus suspend/resume interrupt */
 static void handle_bus_suspend(struct langwell_udc *dev)
 {
-	u32		devlc;
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	dev->resume_state = dev->usb_state;
 	dev->usb_state = USB_STATE_SUSPENDED;
@@ -2733,33 +2821,29 @@
 			spin_unlock(&dev->lock);
 			dev->driver->suspend(&dev->gadget);
 			spin_lock(&dev->lock);
-			DBG(dev, "suspend %s\n", dev->driver->driver.name);
+			dev_dbg(&dev->pdev->dev, "suspend %s\n",
+					dev->driver->driver.name);
 		}
 	}
 
 	/* enter PHY low power suspend */
-	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "devlc = 0x%08x\n", devlc);
-	devlc |= LPM_PHCD;
-	writel(devlc, &dev->op_regs->devlc);
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 0);
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
 static void handle_bus_resume(struct langwell_udc *dev)
 {
-	u32		devlc;
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	dev->usb_state = dev->resume_state;
 	dev->resume_state = 0;
 
 	/* exit PHY low power suspend */
-	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "devlc = 0x%08x\n", devlc);
-	devlc &= ~LPM_PHCD;
-	writel(devlc, &dev->op_regs->devlc);
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 0);
 
 #ifdef	OTG_TRANSCEIVER
 	if (dev->lotg->otg.default_a == 0)
@@ -2772,11 +2856,12 @@
 			spin_unlock(&dev->lock);
 			dev->driver->resume(&dev->gadget);
 			spin_lock(&dev->lock);
-			DBG(dev, "resume %s\n", dev->driver->driver.name);
+			dev_dbg(&dev->pdev->dev, "resume %s\n",
+					dev->driver->driver.name);
 		}
 	}
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2789,11 +2874,11 @@
 				irq_sts,
 				portsc1;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dev->stopped) {
-		VDBG(dev, "handle IRQ_NONE\n");
-		VDBG(dev, "<--- %s()\n", __func__);
+		dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n");
+		dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 		return IRQ_NONE;
 	}
 
@@ -2806,12 +2891,13 @@
 	usbintr = readl(&dev->op_regs->usbintr);
 
 	irq_sts = usbsts & usbintr;
-	VDBG(dev, "usbsts = 0x%08x, usbintr = 0x%08x, irq_sts = 0x%08x\n",
+	dev_vdbg(&dev->pdev->dev,
+			"usbsts = 0x%08x, usbintr = 0x%08x, irq_sts = 0x%08x\n",
 			usbsts, usbintr, irq_sts);
 
 	if (!irq_sts) {
-		VDBG(dev, "handle IRQ_NONE\n");
-		VDBG(dev, "<--- %s()\n", __func__);
+		dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n");
+		dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 		spin_unlock(&dev->lock);
 		return IRQ_NONE;
 	}
@@ -2827,12 +2913,13 @@
 
 	/* USB interrupt */
 	if (irq_sts & STS_UI) {
-		VDBG(dev, "USB interrupt\n");
+		dev_vdbg(&dev->pdev->dev, "USB interrupt\n");
 
 		/* setup packet received from ep0 */
 		if (readl(&dev->op_regs->endptsetupstat)
 				& EP0SETUPSTAT_MASK) {
-			VDBG(dev, "USB SETUP packet received interrupt\n");
+			dev_vdbg(&dev->pdev->dev,
+				"USB SETUP packet received interrupt\n");
 			/* setup tripwire semaphone */
 			setup_tripwire(dev);
 			handle_setup_packet(dev, &dev->local_setup_buff);
@@ -2840,7 +2927,8 @@
 
 		/* USB transfer completion */
 		if (readl(&dev->op_regs->endptcomplete)) {
-			VDBG(dev, "USB transfer completion interrupt\n");
+			dev_vdbg(&dev->pdev->dev,
+				"USB transfer completion interrupt\n");
 			handle_trans_complete(dev);
 		}
 	}
@@ -2848,36 +2936,36 @@
 	/* SOF received interrupt (for ISO transfer) */
 	if (irq_sts & STS_SRI) {
 		/* FIXME */
-		/* VDBG(dev, "SOF received interrupt\n"); */
+		/* dev_vdbg(&dev->pdev->dev, "SOF received interrupt\n"); */
 	}
 
 	/* port change detect interrupt */
 	if (irq_sts & STS_PCI) {
-		VDBG(dev, "port change detect interrupt\n");
+		dev_vdbg(&dev->pdev->dev, "port change detect interrupt\n");
 		handle_port_change(dev);
 	}
 
 	/* suspend interrrupt */
 	if (irq_sts & STS_SLI) {
-		VDBG(dev, "suspend interrupt\n");
+		dev_vdbg(&dev->pdev->dev, "suspend interrupt\n");
 		handle_bus_suspend(dev);
 	}
 
 	/* USB reset interrupt */
 	if (irq_sts & STS_URI) {
-		VDBG(dev, "USB reset interrupt\n");
+		dev_vdbg(&dev->pdev->dev, "USB reset interrupt\n");
 		handle_usb_reset(dev);
 	}
 
 	/* USB error or system error interrupt */
 	if (irq_sts & (STS_UEI | STS_SEI)) {
 		/* FIXME */
-		WARNING(dev, "error IRQ, irq_sts: %x\n", irq_sts);
+		dev_warn(&dev->pdev->dev, "error IRQ, irq_sts: %x\n", irq_sts);
 	}
 
 	spin_unlock(&dev->lock);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return IRQ_HANDLED;
 }
 
@@ -2889,15 +2977,59 @@
 {
 	struct langwell_udc	*dev = the_controller;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	complete(dev->done);
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	kfree(dev);
 }
 
 
+/* enable SRAM caching if SRAM detected */
+static void sram_init(struct langwell_udc *dev)
+{
+	struct pci_dev		*pdev = dev->pdev;
+
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
+
+	dev->sram_addr = pci_resource_start(pdev, 1);
+	dev->sram_size = pci_resource_len(pdev, 1);
+	dev_info(&dev->pdev->dev, "Found private SRAM at %x size:%x\n",
+			dev->sram_addr, dev->sram_size);
+	dev->got_sram = 1;
+
+	if (pci_request_region(pdev, 1, kobject_name(&pdev->dev.kobj))) {
+		dev_warn(&dev->pdev->dev, "SRAM request failed\n");
+		dev->got_sram = 0;
+	} else if (!dma_declare_coherent_memory(&pdev->dev, dev->sram_addr,
+			dev->sram_addr, dev->sram_size, DMA_MEMORY_MAP)) {
+		dev_warn(&dev->pdev->dev, "SRAM DMA declare failed\n");
+		pci_release_region(pdev, 1);
+		dev->got_sram = 0;
+	}
+
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
+}
+
+
+/* release SRAM caching */
+static void sram_deinit(struct langwell_udc *dev)
+{
+	struct pci_dev *pdev = dev->pdev;
+
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
+
+	dma_release_declared_memory(&pdev->dev);
+	pci_release_region(pdev, 1);
+
+	dev->got_sram = 0;
+
+	dev_info(&dev->pdev->dev, "release SRAM caching\n");
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
+}
+
+
 /* tear down the binding between this driver and the pci device */
 static void langwell_udc_remove(struct pci_dev *pdev)
 {
@@ -2906,23 +3038,29 @@
 	DECLARE_COMPLETION(done);
 
 	BUG_ON(dev->driver);
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	dev->done = &done;
 
-	/* free memory allocated in probe */
+#ifndef	OTG_TRANSCEIVER
+	/* free dTD dma_pool and dQH */
 	if (dev->dtd_pool)
 		dma_pool_destroy(dev->dtd_pool);
 
+	if (dev->ep_dqh)
+		dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
+			dev->ep_dqh, dev->ep_dqh_dma);
+
+	/* release SRAM caching */
+	if (dev->has_sram && dev->got_sram)
+		sram_deinit(dev);
+#endif
+
 	if (dev->status_req) {
 		kfree(dev->status_req->req.buf);
 		kfree(dev->status_req);
 	}
 
-	if (dev->ep_dqh)
-		dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
-			dev->ep_dqh, dev->ep_dqh_dma);
-
 	kfree(dev->ep);
 
 	/* diable IRQ handler */
@@ -2949,11 +3087,12 @@
 
 	dev->cap_regs = NULL;
 
-	INFO(dev, "unbind\n");
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_info(&dev->pdev->dev, "unbind\n");
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 
 	device_unregister(&dev->gadget.dev);
 	device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
+	device_remove_file(&pdev->dev, &dev_attr_remote_wakeup);
 
 #ifndef	OTG_TRANSCEIVER
 	pci_set_drvdata(pdev, NULL);
@@ -2997,7 +3136,7 @@
 	spin_lock_init(&dev->lock);
 
 	dev->pdev = pdev;
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 #ifdef	OTG_TRANSCEIVER
 	/* PCI device is already enabled by otg_transceiver driver */
@@ -3022,7 +3161,7 @@
 	resource = pci_resource_start(pdev, 0);
 	len = pci_resource_len(pdev, 0);
 	if (!request_mem_region(resource, len, driver_name)) {
-		ERROR(dev, "controller already in use\n");
+		dev_err(&dev->pdev->dev, "controller already in use\n");
 		retval = -EBUSY;
 		goto error;
 	}
@@ -3031,33 +3170,43 @@
 	base = ioremap_nocache(resource, len);
 #endif
 	if (base == NULL) {
-		ERROR(dev, "can't map memory\n");
+		dev_err(&dev->pdev->dev, "can't map memory\n");
 		retval = -EFAULT;
 		goto error;
 	}
 
 	dev->cap_regs = (struct langwell_cap_regs __iomem *) base;
-	VDBG(dev, "dev->cap_regs: %p\n", dev->cap_regs);
+	dev_vdbg(&dev->pdev->dev, "dev->cap_regs: %p\n", dev->cap_regs);
 	dev->op_regs = (struct langwell_op_regs __iomem *)
 		(base + OP_REG_OFFSET);
-	VDBG(dev, "dev->op_regs: %p\n", dev->op_regs);
+	dev_vdbg(&dev->pdev->dev, "dev->op_regs: %p\n", dev->op_regs);
 
 	/* irq setup after old hardware is cleaned up */
 	if (!pdev->irq) {
-		ERROR(dev, "No IRQ. Check PCI setup!\n");
+		dev_err(&dev->pdev->dev, "No IRQ. Check PCI setup!\n");
 		retval = -ENODEV;
 		goto error;
 	}
 
+	dev->has_sram = 1;
+	dev->got_sram = 0;
+	dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram);
+
 #ifndef	OTG_TRANSCEIVER
-	INFO(dev, "irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n",
+	/* enable SRAM caching if detected */
+	if (dev->has_sram && !dev->got_sram)
+		sram_init(dev);
+
+	dev_info(&dev->pdev->dev,
+			"irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n",
 			pdev->irq, resource, len, base);
 	/* enables bus-mastering for device dev */
 	pci_set_master(pdev);
 
 	if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED,
 				driver_name, dev) != 0) {
-		ERROR(dev, "request interrupt %d failed\n", pdev->irq);
+		dev_err(&dev->pdev->dev,
+				"request interrupt %d failed\n", pdev->irq);
 		retval = -EBUSY;
 		goto error;
 	}
@@ -3071,32 +3220,34 @@
 	dev->lpm = (readl(&dev->cap_regs->hccparams) & HCC_LEN) ? 1 : 0;
 	dev->dciversion = readw(&dev->cap_regs->dciversion);
 	dev->devcap = (readl(&dev->cap_regs->dccparams) & DEVCAP) ? 1 : 0;
-	VDBG(dev, "dev->lpm: %d\n", dev->lpm);
-	VDBG(dev, "dev->dciversion: 0x%04x\n", dev->dciversion);
-	VDBG(dev, "dccparams: 0x%08x\n", readl(&dev->cap_regs->dccparams));
-	VDBG(dev, "dev->devcap: %d\n", dev->devcap);
+	dev_vdbg(&dev->pdev->dev, "dev->lpm: %d\n", dev->lpm);
+	dev_vdbg(&dev->pdev->dev, "dev->dciversion: 0x%04x\n",
+			dev->dciversion);
+	dev_vdbg(&dev->pdev->dev, "dccparams: 0x%08x\n",
+			readl(&dev->cap_regs->dccparams));
+	dev_vdbg(&dev->pdev->dev, "dev->devcap: %d\n", dev->devcap);
 	if (!dev->devcap) {
-		ERROR(dev, "can't support device mode\n");
+		dev_err(&dev->pdev->dev, "can't support device mode\n");
 		retval = -ENODEV;
 		goto error;
 	}
 
 	/* a pair of endpoints (out/in) for each address */
 	dev->ep_max = DEN(readl(&dev->cap_regs->dccparams)) * 2;
-	VDBG(dev, "dev->ep_max: %d\n", dev->ep_max);
+	dev_vdbg(&dev->pdev->dev, "dev->ep_max: %d\n", dev->ep_max);
 
 	/* allocate endpoints memory */
 	dev->ep = kzalloc(sizeof(struct langwell_ep) * dev->ep_max,
 			GFP_KERNEL);
 	if (!dev->ep) {
-		ERROR(dev, "allocate endpoints memory failed\n");
+		dev_err(&dev->pdev->dev, "allocate endpoints memory failed\n");
 		retval = -ENOMEM;
 		goto error;
 	}
 
 	/* allocate device dQH memory */
 	size = dev->ep_max * sizeof(struct langwell_dqh);
-	VDBG(dev, "orig size = %d\n", size);
+	dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size);
 	if (size < DQH_ALIGNMENT)
 		size = DQH_ALIGNMENT;
 	else if ((size % DQH_ALIGNMENT) != 0) {
@@ -3106,17 +3257,18 @@
 	dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
 					&dev->ep_dqh_dma, GFP_KERNEL);
 	if (!dev->ep_dqh) {
-		ERROR(dev, "allocate dQH memory failed\n");
+		dev_err(&dev->pdev->dev, "allocate dQH memory failed\n");
 		retval = -ENOMEM;
 		goto error;
 	}
 	dev->ep_dqh_size = size;
-	VDBG(dev, "ep_dqh_size = %d\n", dev->ep_dqh_size);
+	dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size);
 
 	/* initialize ep0 status request structure */
 	dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL);
 	if (!dev->status_req) {
-		ERROR(dev, "allocate status_req memory failed\n");
+		dev_err(&dev->pdev->dev,
+				"allocate status_req memory failed\n");
 		retval = -ENOMEM;
 		goto error;
 	}
@@ -3129,7 +3281,10 @@
 	dev->resume_state = USB_STATE_NOTATTACHED;
 	dev->usb_state = USB_STATE_POWERED;
 	dev->ep0_dir = USB_DIR_OUT;
-	dev->remote_wakeup = 0;	/* default to 0 on reset */
+
+	/* remote wakeup reset to 0 when the device is reset */
+	dev->remote_wakeup = 0;
+	dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
 
 #ifndef	OTG_TRANSCEIVER
 	/* reset device controller */
@@ -3174,18 +3329,20 @@
 	}
 
 	/* done */
-	INFO(dev, "%s\n", driver_desc);
-	INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base);
-	INFO(dev, "Driver version: " DRIVER_VERSION "\n");
-	INFO(dev, "Support (max) %d endpoints\n", dev->ep_max);
-	INFO(dev, "Device interface version: 0x%04x\n", dev->dciversion);
-	INFO(dev, "Controller mode: %s\n", dev->devcap ? "Device" : "Host");
-	INFO(dev, "Support USB LPM: %s\n", dev->lpm ? "Yes" : "No");
+	dev_info(&dev->pdev->dev, "%s\n", driver_desc);
+	dev_info(&dev->pdev->dev, "irq %d, pci mem %p\n", pdev->irq, base);
+	dev_info(&dev->pdev->dev, "Driver version: " DRIVER_VERSION "\n");
+	dev_info(&dev->pdev->dev, "Support (max) %d endpoints\n", dev->ep_max);
+	dev_info(&dev->pdev->dev, "Device interface version: 0x%04x\n",
+			dev->dciversion);
+	dev_info(&dev->pdev->dev, "Controller mode: %s\n",
+			dev->devcap ? "Device" : "Host");
+	dev_info(&dev->pdev->dev, "Support USB LPM: %s\n",
+			dev->lpm ? "Yes" : "No");
 
-	VDBG(dev, "After langwell_udc_probe(), print all registers:\n");
-#ifdef	VERBOSE
+	dev_vdbg(&dev->pdev->dev,
+			"After langwell_udc_probe(), print all registers:\n");
 	print_all_registers(dev);
-#endif
 
 	the_controller = dev;
 
@@ -3197,12 +3354,18 @@
 	if (retval)
 		goto error;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	retval = device_create_file(&pdev->dev, &dev_attr_remote_wakeup);
+	if (retval)
+		goto error_attr1;
+
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 
+error_attr1:
+	device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
 error:
 	if (dev) {
-		DBG(dev, "<--- %s()\n", __func__);
+		dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 		langwell_udc_remove(pdev);
 	}
 
@@ -3214,9 +3377,8 @@
 static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct langwell_udc	*dev = the_controller;
-	u32			devlc;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* disable interrupt and set controller to stop state */
 	langwell_udc_stop(dev);
@@ -3226,20 +3388,34 @@
 		free_irq(pdev->irq, dev);
 	dev->got_irq = 0;
 
-
 	/* save PCI state */
 	pci_save_state(pdev);
 
+	spin_lock_irq(&dev->lock);
+	/* stop all usb activities */
+	stop_activity(dev, dev->driver);
+	spin_unlock_irq(&dev->lock);
+
+	/* free dTD dma_pool and dQH */
+	if (dev->dtd_pool)
+		dma_pool_destroy(dev->dtd_pool);
+
+	if (dev->ep_dqh)
+		dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
+			dev->ep_dqh, dev->ep_dqh_dma);
+
+	/* release SRAM caching */
+	if (dev->has_sram && dev->got_sram)
+		sram_deinit(dev);
+
 	/* set device power state */
 	pci_set_power_state(pdev, PCI_D3hot);
 
 	/* enter PHY low power suspend */
-	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "devlc = 0x%08x\n", devlc);
-	devlc |= LPM_PHCD;
-	writel(devlc, &dev->op_regs->devlc);
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 1);
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -3248,27 +3424,58 @@
 static int langwell_udc_resume(struct pci_dev *pdev)
 {
 	struct langwell_udc	*dev = the_controller;
-	u32			devlc;
+	size_t			size;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* exit PHY low power suspend */
-	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "devlc = 0x%08x\n", devlc);
-	devlc &= ~LPM_PHCD;
-	writel(devlc, &dev->op_regs->devlc);
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 0);
 
 	/* set device D0 power state */
 	pci_set_power_state(pdev, PCI_D0);
 
+	/* enable SRAM caching if detected */
+	if (dev->has_sram && !dev->got_sram)
+		sram_init(dev);
+
+	/* allocate device dQH memory */
+	size = dev->ep_max * sizeof(struct langwell_dqh);
+	dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size);
+	if (size < DQH_ALIGNMENT)
+		size = DQH_ALIGNMENT;
+	else if ((size % DQH_ALIGNMENT) != 0) {
+		size += DQH_ALIGNMENT + 1;
+		size &= ~(DQH_ALIGNMENT - 1);
+	}
+	dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
+					&dev->ep_dqh_dma, GFP_KERNEL);
+	if (!dev->ep_dqh) {
+		dev_err(&dev->pdev->dev, "allocate dQH memory failed\n");
+		return -ENOMEM;
+	}
+	dev->ep_dqh_size = size;
+	dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size);
+
+	/* create dTD dma_pool resource */
+	dev->dtd_pool = dma_pool_create("langwell_dtd",
+			&dev->pdev->dev,
+			sizeof(struct langwell_dtd),
+			DTD_ALIGNMENT,
+			DMA_BOUNDARY);
+
+	if (!dev->dtd_pool)
+		return -ENOMEM;
+
 	/* restore PCI state */
 	pci_restore_state(pdev);
 
 	/* enable IRQ handler */
-	if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED, driver_name, dev)
-			!= 0) {
-		ERROR(dev, "request interrupt %d failed\n", pdev->irq);
-		return -1;
+	if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED,
+				driver_name, dev) != 0) {
+		dev_err(&dev->pdev->dev, "request interrupt %d failed\n",
+				pdev->irq);
+		return -EBUSY;
 	}
 	dev->got_irq = 1;
 
@@ -3290,7 +3497,7 @@
 	dev->ep0_state = WAIT_FOR_SETUP;
 	dev->ep0_dir = USB_DIR_OUT;
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -3301,15 +3508,15 @@
 	struct langwell_udc	*dev = the_controller;
 	u32			usbmode;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* reset controller mode to IDLE */
 	usbmode = readl(&dev->op_regs->usbmode);
-	DBG(dev, "usbmode = 0x%08x\n", usbmode);
+	dev_dbg(&dev->pdev->dev, "usbmode = 0x%08x\n", usbmode);
 	usbmode &= (~3 | MODE_IDLE);
 	writel(usbmode, &dev->op_regs->usbmode);
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -3324,7 +3531,6 @@
 }, { /* end: all zeroes */ }
 };
 
-
 MODULE_DEVICE_TABLE(pci, pci_ids);
 
 
@@ -3343,12 +3549,6 @@
 };
 
 
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-
 static int __init init(void)
 {
 #ifdef	OTG_TRANSCEIVER
@@ -3370,3 +3570,9 @@
 }
 module_exit(cleanup);
 
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h
index 9719934..f1d9c1b 100644
--- a/drivers/usb/gadget/langwell_udc.h
+++ b/drivers/usb/gadget/langwell_udc.h
@@ -18,11 +18,7 @@
  */
 
 #include <linux/usb/langwell_udc.h>
-
-#if defined(CONFIG_USB_LANGWELL_OTG)
 #include <linux/usb/langwell_otg.h>
-#endif
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -199,7 +195,9 @@
 				vbus_active:1,
 				suspended:1,
 				stopped:1,
-				lpm:1;	/* LPM capability */
+				lpm:1,		/* LPM capability */
+				has_sram:1,	/* SRAM caching */
+				got_sram:1;
 
 	/* pci state used to access those endpoints */
 	struct pci_dev		*pdev;
@@ -224,5 +222,12 @@
 
 	/* make sure release() is done */
 	struct completion	*done;
+
+	/* for private SRAM caching */
+	unsigned int		sram_addr;
+	unsigned int		sram_size;
+
+	/* device status data for get_status request */
+	u16			dev_status;
 };
 
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index fded3fc..6b58bd8 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -408,7 +408,8 @@
 /*
   Register entry point for the peripheral controller driver.
 */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct lh7a40x_udc *dev = the_controller;
 	int retval;
@@ -417,7 +418,7 @@
 
 	if (!driver
 			|| driver->speed != USB_SPEED_FULL
-			|| !driver->bind
+			|| !bind
 			|| !driver->disconnect
 			|| !driver->setup)
 		return -EINVAL;
@@ -431,7 +432,7 @@
 	dev->gadget.dev.driver = &driver->driver;
 
 	device_add(&dev->gadget.dev);
-	retval = driver->bind(&dev->gadget);
+	retval = bind(&dev->gadget);
 	if (retval) {
 		printk(KERN_WARNING "%s: bind to driver %s --> error %d\n",
 		       dev->gadget.name, driver->driver.name, retval);
@@ -453,8 +454,7 @@
 
 	return 0;
 }
-
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /*
   Unregister entry point for the peripheral controller driver.
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index e03058f..51b19f3 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -1454,14 +1454,15 @@
 /*-------------------------------------------------------------------------*/
 static struct m66592 *the_controller;
 
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct m66592 *m66592 = the_controller;
 	int retval;
 
 	if (!driver
 			|| driver->speed != USB_SPEED_HIGH
-			|| !driver->bind
+			|| !bind
 			|| !driver->setup)
 		return -EINVAL;
 	if (!m66592)
@@ -1480,7 +1481,7 @@
 		goto error;
 	}
 
-	retval = driver->bind (&m66592->gadget);
+	retval = bind(&m66592->gadget);
 	if (retval) {
 		pr_err("bind to driver error (%d)\n", retval);
 		device_del(&m66592->gadget.dev);
@@ -1505,7 +1506,7 @@
 
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index 585f255..0769179 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -75,10 +75,6 @@
 	/* Vendor and product id can be overridden by module parameters.  */
 	.idVendor =		cpu_to_le16(FSG_VENDOR_ID),
 	.idProduct =		cpu_to_le16(FSG_PRODUCT_ID),
-	/* .bcdDevice = f(hardware) */
-	/* .iManufacturer = DYNAMIC */
-	/* .iProduct = DYNAMIC */
-	/* NO SERIAL NUMBER */
 	.bNumConfigurations =	1,
 };
 
@@ -86,7 +82,8 @@
 	.bLength =		sizeof otg_descriptor,
 	.bDescriptorType =	USB_DT_OTG,
 
-	/* REVISIT SRP-only hardware is possible, although
+	/*
+	 * REVISIT SRP-only hardware is possible, although
 	 * it would not be called "OTG" ...
 	 */
 	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
@@ -98,33 +95,6 @@
 };
 
 
-/* string IDs are assigned dynamically */
-
-#define STRING_MANUFACTURER_IDX		0
-#define STRING_PRODUCT_IDX		1
-#define STRING_CONFIGURATION_IDX	2
-
-static char manufacturer[50];
-
-static struct usb_string strings_dev[] = {
-	[STRING_MANUFACTURER_IDX].s = manufacturer,
-	[STRING_PRODUCT_IDX].s = DRIVER_DESC,
-	[STRING_CONFIGURATION_IDX].s = "Self Powered",
-	{  } /* end of list */
-};
-
-static struct usb_gadget_strings stringtab_dev = {
-	.language	= 0x0409,	/* en-us */
-	.strings	= strings_dev,
-};
-
-static struct usb_gadget_strings *dev_strings[] = {
-	&stringtab_dev,
-	NULL,
-};
-
-
-
 /****************************** Configurations ******************************/
 
 static struct fsg_module_parameters mod_data = {
@@ -141,7 +111,7 @@
 	return 0;
 }
 
-static int __ref msg_do_config(struct usb_configuration *c)
+static int __init msg_do_config(struct usb_configuration *c)
 {
 	static const struct fsg_operations ops = {
 		.thread_exits = msg_thread_exits,
@@ -171,54 +141,23 @@
 
 static struct usb_configuration msg_config_driver = {
 	.label			= "Linux File-Backed Storage",
-	.bind			= msg_do_config,
 	.bConfigurationValue	= 1,
-	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
 };
 
 
-
 /****************************** Gadget Bind ******************************/
 
-
-static int __ref msg_bind(struct usb_composite_dev *cdev)
+static int __init msg_bind(struct usb_composite_dev *cdev)
 {
-	struct usb_gadget *gadget = cdev->gadget;
 	int status;
 
-	/* Allocate string descriptor numbers ... note that string
-	 * contents can be overridden by the composite_dev glue.
-	 */
-
-	/* device descriptor strings: manufacturer, product */
-	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
-	         init_utsname()->sysname, init_utsname()->release,
-	         gadget->name);
-	status = usb_string_id(cdev);
-	if (status < 0)
-		return status;
-	strings_dev[STRING_MANUFACTURER_IDX].id = status;
-	msg_device_desc.iManufacturer = status;
-
-	status = usb_string_id(cdev);
-	if (status < 0)
-		return status;
-	strings_dev[STRING_PRODUCT_IDX].id = status;
-	msg_device_desc.iProduct = status;
-
-	status = usb_string_id(cdev);
-	if (status < 0)
-		return status;
-	strings_dev[STRING_CONFIGURATION_IDX].id = status;
-	msg_config_driver.iConfiguration = status;
-
-	/* register our second configuration */
-	status = usb_add_config(cdev, &msg_config_driver);
+	status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
 	if (status < 0)
 		return status;
 
-	dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
+	dev_info(&cdev->gadget->dev,
+		 DRIVER_DESC ", version: " DRIVER_VERSION "\n");
 	set_bit(0, &msg_registered);
 	return 0;
 }
@@ -226,12 +165,11 @@
 
 /****************************** Some noise ******************************/
 
-
 static struct usb_composite_driver msg_driver = {
 	.name		= "g_mass_storage",
 	.dev		= &msg_device_desc,
-	.strings	= dev_strings,
-	.bind		= msg_bind,
+	.iProduct	= DRIVER_DESC,
+	.needs_serial	= 1,
 };
 
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -240,7 +178,7 @@
 
 static int __init msg_init(void)
 {
-	return usb_composite_register(&msg_driver);
+	return usb_composite_probe(&msg_driver, msg_bind);
 }
 module_init(msg_init);
 
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 795d762..d9feced 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -74,8 +74,8 @@
 
 /***************************** Device Descriptor ****************************/
 
-#define MULTI_VENDOR_NUM	0x0525	/* XXX NetChip */
-#define MULTI_PRODUCT_NUM	0xa4ab	/* XXX */
+#define MULTI_VENDOR_NUM	0x1d6b	/* Linux Foundation */
+#define MULTI_PRODUCT_NUM	0x0104	/* Multifunction Composite Gadget */
 
 
 enum {
@@ -121,8 +121,6 @@
 
 
 enum {
-	MULTI_STRING_MANUFACTURER_IDX,
-	MULTI_STRING_PRODUCT_IDX,
 #ifdef CONFIG_USB_G_MULTI_RNDIS
 	MULTI_STRING_RNDIS_CONFIG_IDX,
 #endif
@@ -131,11 +129,7 @@
 #endif
 };
 
-static char manufacturer[50];
-
 static struct usb_string strings_dev[] = {
-	[MULTI_STRING_MANUFACTURER_IDX].s = manufacturer,
-	[MULTI_STRING_PRODUCT_IDX].s      = DRIVER_DESC,
 #ifdef CONFIG_USB_G_MULTI_RNDIS
 	[MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS",
 #endif
@@ -170,7 +164,7 @@
 
 #ifdef USB_ETH_RNDIS
 
-static __ref int rndis_do_config(struct usb_configuration *c)
+static __init int rndis_do_config(struct usb_configuration *c)
 {
 	int ret;
 
@@ -197,7 +191,6 @@
 static int rndis_config_register(struct usb_composite_dev *cdev)
 {
 	static struct usb_configuration config = {
-		.bind			= rndis_do_config,
 		.bConfigurationValue	= MULTI_RNDIS_CONFIG_NUM,
 		.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
 	};
@@ -205,7 +198,7 @@
 	config.label          = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].s;
 	config.iConfiguration = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].id;
 
-	return usb_add_config(cdev, &config);
+	return usb_add_config(cdev, &config, rndis_do_config);
 }
 
 #else
@@ -222,7 +215,7 @@
 
 #ifdef CONFIG_USB_G_MULTI_CDC
 
-static __ref int cdc_do_config(struct usb_configuration *c)
+static __init int cdc_do_config(struct usb_configuration *c)
 {
 	int ret;
 
@@ -249,7 +242,6 @@
 static int cdc_config_register(struct usb_composite_dev *cdev)
 {
 	static struct usb_configuration config = {
-		.bind			= cdc_do_config,
 		.bConfigurationValue	= MULTI_CDC_CONFIG_NUM,
 		.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
 	};
@@ -257,7 +249,7 @@
 	config.label          = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].s;
 	config.iConfiguration = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].id;
 
-	return usb_add_config(cdev, &config);
+	return usb_add_config(cdev, &config, cdc_do_config);
 }
 
 #else
@@ -314,20 +306,11 @@
 		device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);
 	}
 
-	/* allocate string descriptor numbers */
-	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
-	         init_utsname()->sysname, init_utsname()->release,
-	         gadget->name);
-
+	/* allocate string IDs */
 	status = usb_string_ids_tab(cdev, strings_dev);
 	if (unlikely(status < 0))
 		goto fail2;
 
-	device_desc.iManufacturer =
-		strings_dev[MULTI_STRING_MANUFACTURER_IDX].id;
-	device_desc.iProduct      =
-		strings_dev[MULTI_STRING_PRODUCT_IDX].id;
-
 	/* register configurations */
 	status = rndis_config_register(cdev);
 	if (unlikely(status < 0))
@@ -368,14 +351,15 @@
 	.name		= "g_multi",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= multi_bind,
 	.unbind		= __exit_p(multi_unbind),
+	.iProduct	= DRIVER_DESC,
+	.needs_serial	= 1,
 };
 
 
 static int __init multi_init(void)
 {
-	return usb_composite_register(&multi_driver);
+	return usb_composite_probe(&multi_driver, multi_bind);
 }
 module_init(multi_init);
 
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 9498be8..d09155b 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1929,7 +1929,8 @@
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  */
-int usb_gadget_register_driver (struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct net2280		*dev = the_controller;
 	int			retval;
@@ -1941,8 +1942,7 @@
 	 */
 	if (!driver
 			|| driver->speed != USB_SPEED_HIGH
-			|| !driver->bind
-			|| !driver->setup)
+			|| !bind || !driver->setup)
 		return -EINVAL;
 	if (!dev)
 		return -ENODEV;
@@ -1957,7 +1957,7 @@
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
-	retval = driver->bind (&dev->gadget);
+	retval = bind(&dev->gadget);
 	if (retval) {
 		DEBUG (dev, "bind to driver %s --> %d\n",
 				driver->driver.name, retval);
@@ -1993,7 +1993,7 @@
 	dev->driver = NULL;
 	return retval;
 }
-EXPORT_SYMBOL (usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void
 stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c
index 7d6b66a..b5364f9d 100644
--- a/drivers/usb/gadget/nokia.c
+++ b/drivers/usb/gadget/nokia.c
@@ -135,7 +135,6 @@
 
 static struct usb_configuration nokia_config_500ma_driver = {
 	.label		= "Bus Powered",
-	.bind		= nokia_bind_config,
 	.bConfigurationValue = 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes	= USB_CONFIG_ATT_ONE,
@@ -144,7 +143,6 @@
 
 static struct usb_configuration nokia_config_100ma_driver = {
 	.label		= "Self Powered",
-	.bind		= nokia_bind_config,
 	.bConfigurationValue = 2,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
@@ -206,11 +204,13 @@
 	}
 
 	/* finaly register the configuration */
-	status = usb_add_config(cdev, &nokia_config_500ma_driver);
+	status = usb_add_config(cdev, &nokia_config_500ma_driver,
+			nokia_bind_config);
 	if (status < 0)
 		goto err_usb;
 
-	status = usb_add_config(cdev, &nokia_config_100ma_driver);
+	status = usb_add_config(cdev, &nokia_config_100ma_driver,
+			nokia_bind_config);
 	if (status < 0)
 		goto err_usb;
 
@@ -241,13 +241,12 @@
 	.name		= "g_nokia",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= nokia_bind,
 	.unbind		= __exit_p(nokia_unbind),
 };
 
 static int __init nokia_init(void)
 {
-	return usb_composite_register(&nokia_driver);
+	return usb_composite_probe(&nokia_driver, nokia_bind);
 }
 module_init(nokia_init);
 
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index f81e4f0..61d3ca6 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2102,7 +2102,8 @@
 		);
 }
 
-int usb_gadget_register_driver (struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	int		status = -ENODEV;
 	struct omap_ep	*ep;
@@ -2114,8 +2115,7 @@
 	if (!driver
 			// FIXME if otg, check:  driver->is_otg
 			|| driver->speed < USB_SPEED_FULL
-			|| !driver->bind
-			|| !driver->setup)
+			|| !bind || !driver->setup)
 		return -EINVAL;
 
 	spin_lock_irqsave(&udc->lock, flags);
@@ -2145,7 +2145,7 @@
 	if (udc->dc_clk != NULL)
 		omap_udc_enable_clock(1);
 
-	status = driver->bind (&udc->gadget);
+	status = bind(&udc->gadget);
 	if (status) {
 		DBG("bind to %s --> %d\n", driver->driver.name, status);
 		udc->gadget.dev.driver = NULL;
@@ -2186,7 +2186,7 @@
 		omap_udc_enable_clock(0);
 	return status;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index cf241c3..2fc8636 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -884,7 +884,8 @@
 	.fsync =	printer_fsync,
 	.poll =		printer_poll,
 	.unlocked_ioctl = printer_ioctl,
-	.release =	printer_close
+	.release =	printer_close,
+	.llseek =	noop_llseek,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1347,7 +1348,7 @@
 	set_gadget_data(gadget, NULL);
 }
 
-static int __ref
+static int __init
 printer_bind(struct usb_gadget *gadget)
 {
 	struct printer_dev	*dev;
@@ -1543,7 +1544,6 @@
 	.speed		= DEVSPEED,
 
 	.function	= (char *) driver_desc,
-	.bind		= printer_bind,
 	.unbind		= printer_unbind,
 
 	.setup		= printer_setup,
@@ -1579,11 +1579,11 @@
 		return status;
 	}
 
-	status = usb_gadget_register_driver(&printer_driver);
+	status = usb_gadget_probe_driver(&printer_driver, printer_bind);
 	if (status) {
 		class_destroy(usb_gadget_class);
 		unregister_chrdev_region(g_printer_devno, 1);
-		DBG(dev, "usb_gadget_register_driver %x\n", status);
+		DBG(dev, "usb_gadget_probe_driver %x\n", status);
 	}
 
 	return status;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index be5fb34..b37f92c 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -1280,14 +1280,15 @@
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct pxa25x_udc	*dev = the_controller;
 	int			retval;
 
 	if (!driver
 			|| driver->speed < USB_SPEED_FULL
-			|| !driver->bind
+			|| !bind
 			|| !driver->disconnect
 			|| !driver->setup)
 		return -EINVAL;
@@ -1308,7 +1309,7 @@
 		dev->gadget.dev.driver = NULL;
 		return retval;
 	}
-	retval = driver->bind(&dev->gadget);
+	retval = bind(&dev->gadget);
 	if (retval) {
 		DMSG("bind to driver %s --> error %d\n",
 				driver->driver.name, retval);
@@ -1338,7 +1339,7 @@
 bind_fail:
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void
 stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 9807624..027d66f 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -1792,8 +1792,9 @@
 }
 
 /**
- * usb_gadget_register_driver - Register gadget driver
+ * usb_gadget_probe_driver - Register gadget driver
  * @driver: gadget driver
+ * @bind: bind function
  *
  * When a driver is successfully registered, it will receive control requests
  * including set_configuration(), which enables non-control requests.  Then
@@ -1805,12 +1806,13 @@
  *
  * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct pxa_udc *udc = the_controller;
 	int retval;
 
-	if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind
+	if (!driver || driver->speed < USB_SPEED_FULL || !bind
 			|| !driver->disconnect || !driver->setup)
 		return -EINVAL;
 	if (!udc)
@@ -1828,7 +1830,7 @@
 		dev_err(udc->dev, "device_add error %d\n", retval);
 		goto add_fail;
 	}
-	retval = driver->bind(&udc->gadget);
+	retval = bind(&udc->gadget);
 	if (retval) {
 		dev_err(udc->dev, "bind to driver %s --> error %d\n",
 			driver->driver.name, retval);
@@ -1859,7 +1861,7 @@
 	udc->gadget.dev.driver = NULL;
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 
 /**
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index 2456ccd..20d43da 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -42,6 +42,7 @@
 	"ep8", "ep9",
 };
 
+static void init_controller(struct r8a66597 *r8a66597);
 static void disable_controller(struct r8a66597 *r8a66597);
 static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req);
 static void irq_packet_write(struct r8a66597_ep *ep,
@@ -104,6 +105,8 @@
 	spin_lock(&r8a66597->lock);
 
 	disable_controller(r8a66597);
+	init_controller(r8a66597);
+	r8a66597_bset(r8a66597, VBSE, INTENB0);
 	INIT_LIST_HEAD(&r8a66597->ep[0].queue);
 }
 
@@ -274,7 +277,7 @@
 	}
 
 	if (buf_bsize && ((bufnum + 16) >= R8A66597_MAX_BUFNUM)) {
-		pr_err(KERN_ERR "r8a66597 pipe memory is insufficient\n");
+		pr_err("r8a66597 pipe memory is insufficient\n");
 		return -ENOMEM;
 	}
 
@@ -1405,14 +1408,15 @@
 /*-------------------------------------------------------------------------*/
 static struct r8a66597 *the_controller;
 
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct r8a66597 *r8a66597 = the_controller;
 	int retval;
 
 	if (!driver
 			|| driver->speed != USB_SPEED_HIGH
-			|| !driver->bind
+			|| !bind
 			|| !driver->setup)
 		return -EINVAL;
 	if (!r8a66597)
@@ -1431,7 +1435,7 @@
 		goto error;
 	}
 
-	retval = driver->bind(&r8a66597->gadget);
+	retval = bind(&r8a66597->gadget);
 	if (retval) {
 		printk(KERN_ERR "bind to driver error (%d)\n", retval);
 		device_del(&r8a66597->gadget.dev);
@@ -1456,7 +1460,7 @@
 
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h
index f763b51..5fc22e0 100644
--- a/drivers/usb/gadget/r8a66597-udc.h
+++ b/drivers/usb/gadget/r8a66597-udc.h
@@ -136,7 +136,7 @@
 				      int len)
 {
 	void __iomem *fifoaddr = r8a66597->reg + offset;
-	unsigned int data;
+	unsigned int data = 0;
 	int i;
 
 	if (r8a66597->pdata->on_chip) {
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 972d5dd..5b31404 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -61,17 +61,17 @@
 #define RNDIS_MAX_CONFIGS	1
 
 
-static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
+static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
 
 /* Driver Version */
-static const __le32 rndis_driver_version = cpu_to_le32 (1);
+static const __le32 rndis_driver_version = cpu_to_le32(1);
 
 /* Function Prototypes */
-static rndis_resp_t *rndis_add_response (int configNr, u32 length);
+static rndis_resp_t *rndis_add_response(int configNr, u32 length);
 
 
 /* supported OIDs */
-static const u32 oid_supported_list [] =
+static const u32 oid_supported_list[] =
 {
 	/* the general stuff */
 	OID_GEN_SUPPORTED_LIST,
@@ -161,21 +161,20 @@
 
 
 /* NDIS Functions */
-static int
-gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
-		rndis_resp_t *r)
+static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
+			       unsigned buf_len, rndis_resp_t *r)
 {
-	int			retval = -ENOTSUPP;
-	u32			length = 4;	/* usually */
-	__le32			*outbuf;
-	int			i, count;
-	rndis_query_cmplt_type	*resp;
-	struct net_device	*net;
+	int retval = -ENOTSUPP;
+	u32 length = 4;	/* usually */
+	__le32 *outbuf;
+	int i, count;
+	rndis_query_cmplt_type *resp;
+	struct net_device *net;
 	struct rtnl_link_stats64 temp;
 	const struct rtnl_link_stats64 *stats;
 
 	if (!r) return -ENOMEM;
-	resp = (rndis_query_cmplt_type *) r->buf;
+	resp = (rndis_query_cmplt_type *)r->buf;
 
 	if (!resp) return -ENOMEM;
 
@@ -191,8 +190,8 @@
 	}
 
 	/* response goes here, right after the header */
-	outbuf = (__le32 *) &resp[1];
-	resp->InformationBufferOffset = cpu_to_le32 (16);
+	outbuf = (__le32 *)&resp[1];
+	resp->InformationBufferOffset = cpu_to_le32(16);
 
 	net = rndis_per_dev_params[configNr].dev;
 	stats = dev_get_stats(net, &temp);
@@ -204,10 +203,10 @@
 	/* mandatory */
 	case OID_GEN_SUPPORTED_LIST:
 		pr_debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
-		length = sizeof (oid_supported_list);
-		count  = length / sizeof (u32);
+		length = sizeof(oid_supported_list);
+		count  = length / sizeof(u32);
 		for (i = 0; i < count; i++)
-			outbuf[i] = cpu_to_le32 (oid_supported_list[i]);
+			outbuf[i] = cpu_to_le32(oid_supported_list[i]);
 		retval = 0;
 		break;
 
@@ -220,14 +219,14 @@
 		 * reddite ergo quae sunt Caesaris Caesari
 		 * et quae sunt Dei Deo!
 		 */
-		*outbuf = cpu_to_le32 (0);
+		*outbuf = cpu_to_le32(0);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_MEDIA_SUPPORTED:
 		pr_debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
-		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
+		*outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
 		retval = 0;
 		break;
 
@@ -235,16 +234,16 @@
 	case OID_GEN_MEDIA_IN_USE:
 		pr_debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
 		/* one medium, one transport... (maybe you do it better) */
-		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
+		*outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_MAXIMUM_FRAME_SIZE:
 		pr_debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
-		if (rndis_per_dev_params [configNr].dev) {
-			*outbuf = cpu_to_le32 (
-				rndis_per_dev_params [configNr].dev->mtu);
+		if (rndis_per_dev_params[configNr].dev) {
+			*outbuf = cpu_to_le32(
+				rndis_per_dev_params[configNr].dev->mtu);
 			retval = 0;
 		}
 		break;
@@ -253,21 +252,21 @@
 	case OID_GEN_LINK_SPEED:
 		if (rndis_debug > 1)
 			pr_debug("%s: OID_GEN_LINK_SPEED\n", __func__);
-		if (rndis_per_dev_params [configNr].media_state
+		if (rndis_per_dev_params[configNr].media_state
 				== NDIS_MEDIA_STATE_DISCONNECTED)
-			*outbuf = cpu_to_le32 (0);
+			*outbuf = cpu_to_le32(0);
 		else
-			*outbuf = cpu_to_le32 (
-				rndis_per_dev_params [configNr].speed);
+			*outbuf = cpu_to_le32(
+				rndis_per_dev_params[configNr].speed);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_TRANSMIT_BLOCK_SIZE:
 		pr_debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
-		if (rndis_per_dev_params [configNr].dev) {
-			*outbuf = cpu_to_le32 (
-				rndis_per_dev_params [configNr].dev->mtu);
+		if (rndis_per_dev_params[configNr].dev) {
+			*outbuf = cpu_to_le32(
+				rndis_per_dev_params[configNr].dev->mtu);
 			retval = 0;
 		}
 		break;
@@ -275,9 +274,9 @@
 	/* mandatory */
 	case OID_GEN_RECEIVE_BLOCK_SIZE:
 		pr_debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
-		if (rndis_per_dev_params [configNr].dev) {
-			*outbuf = cpu_to_le32 (
-				rndis_per_dev_params [configNr].dev->mtu);
+		if (rndis_per_dev_params[configNr].dev) {
+			*outbuf = cpu_to_le32(
+				rndis_per_dev_params[configNr].dev->mtu);
 			retval = 0;
 		}
 		break;
@@ -285,18 +284,20 @@
 	/* mandatory */
 	case OID_GEN_VENDOR_ID:
 		pr_debug("%s: OID_GEN_VENDOR_ID\n", __func__);
-		*outbuf = cpu_to_le32 (
-			rndis_per_dev_params [configNr].vendorID);
+		*outbuf = cpu_to_le32(
+			rndis_per_dev_params[configNr].vendorID);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_VENDOR_DESCRIPTION:
 		pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
-		if ( rndis_per_dev_params [configNr].vendorDescr ) {
-			length = strlen (rndis_per_dev_params [configNr].vendorDescr);
-			memcpy (outbuf,
-				rndis_per_dev_params [configNr].vendorDescr, length);
+		if (rndis_per_dev_params[configNr].vendorDescr) {
+			length = strlen(rndis_per_dev_params[configNr].
+					vendorDescr);
+			memcpy(outbuf,
+				rndis_per_dev_params[configNr].vendorDescr,
+				length);
 		} else {
 			outbuf[0] = 0;
 		}
@@ -313,7 +314,7 @@
 	/* mandatory */
 	case OID_GEN_CURRENT_PACKET_FILTER:
 		pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
-		*outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
+		*outbuf = cpu_to_le32(*rndis_per_dev_params[configNr].filter);
 		retval = 0;
 		break;
 
@@ -328,14 +329,14 @@
 	case OID_GEN_MEDIA_CONNECT_STATUS:
 		if (rndis_debug > 1)
 			pr_debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
-		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+		*outbuf = cpu_to_le32(rndis_per_dev_params[configNr]
 						.media_state);
 		retval = 0;
 		break;
 
 	case OID_GEN_PHYSICAL_MEDIUM:
 		pr_debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
-		*outbuf = cpu_to_le32 (0);
+		*outbuf = cpu_to_le32(0);
 		retval = 0;
 		break;
 
@@ -409,10 +410,10 @@
 	/* mandatory */
 	case OID_802_3_PERMANENT_ADDRESS:
 		pr_debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
-		if (rndis_per_dev_params [configNr].dev) {
+		if (rndis_per_dev_params[configNr].dev) {
 			length = ETH_ALEN;
-			memcpy (outbuf,
-				rndis_per_dev_params [configNr].host_mac,
+			memcpy(outbuf,
+				rndis_per_dev_params[configNr].host_mac,
 				length);
 			retval = 0;
 		}
@@ -421,9 +422,9 @@
 	/* mandatory */
 	case OID_802_3_CURRENT_ADDRESS:
 		pr_debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
-		if (rndis_per_dev_params [configNr].dev) {
+		if (rndis_per_dev_params[configNr].dev) {
 			length = ETH_ALEN;
-			memcpy (outbuf,
+			memcpy(outbuf,
 				rndis_per_dev_params [configNr].host_mac,
 				length);
 			retval = 0;
@@ -434,7 +435,7 @@
 	case OID_802_3_MULTICAST_LIST:
 		pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
 		/* Multicast base address only */
-		*outbuf = cpu_to_le32 (0xE0000000);
+		*outbuf = cpu_to_le32(0xE0000000);
 		retval = 0;
 		break;
 
@@ -442,7 +443,7 @@
 	case OID_802_3_MAXIMUM_LIST_SIZE:
 		pr_debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
 		/* Multicast base address only */
-		*outbuf = cpu_to_le32 (1);
+		*outbuf = cpu_to_le32(1);
 		retval = 0;
 		break;
 
@@ -466,14 +467,14 @@
 	/* mandatory */
 	case OID_802_3_XMIT_ONE_COLLISION:
 		pr_debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
-		*outbuf = cpu_to_le32 (0);
+		*outbuf = cpu_to_le32(0);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_802_3_XMIT_MORE_COLLISIONS:
 		pr_debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
-		*outbuf = cpu_to_le32 (0);
+		*outbuf = cpu_to_le32(0);
 		retval = 0;
 		break;
 
@@ -484,22 +485,22 @@
 	if (retval < 0)
 		length = 0;
 
-	resp->InformationBufferLength = cpu_to_le32 (length);
-	r->length = length + sizeof *resp;
-	resp->MessageLength = cpu_to_le32 (r->length);
+	resp->InformationBufferLength = cpu_to_le32(length);
+	r->length = length + sizeof(*resp);
+	resp->MessageLength = cpu_to_le32(r->length);
 	return retval;
 }
 
-static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
-			rndis_resp_t *r)
+static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
+			     rndis_resp_t *r)
 {
-	rndis_set_cmplt_type		*resp;
-	int				i, retval = -ENOTSUPP;
-	struct rndis_params		*params;
+	rndis_set_cmplt_type *resp;
+	int i, retval = -ENOTSUPP;
+	struct rndis_params *params;
 
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_set_cmplt_type *) r->buf;
+	resp = (rndis_set_cmplt_type *)r->buf;
 	if (!resp)
 		return -ENOMEM;
 
@@ -514,7 +515,7 @@
 		}
 	}
 
-	params = &rndis_per_dev_params [configNr];
+	params = &rndis_per_dev_params[configNr];
 	switch (OID) {
 	case OID_GEN_CURRENT_PACKET_FILTER:
 
@@ -537,11 +538,11 @@
 			params->state = RNDIS_DATA_INITIALIZED;
 			netif_carrier_on(params->dev);
 			if (netif_running(params->dev))
-				netif_wake_queue (params->dev);
+				netif_wake_queue(params->dev);
 		} else {
 			params->state = RNDIS_INITIALIZED;
-			netif_carrier_off (params->dev);
-			netif_stop_queue (params->dev);
+			netif_carrier_off(params->dev);
+			netif_stop_queue(params->dev);
 		}
 		break;
 
@@ -563,48 +564,47 @@
  * Response Functions
  */
 
-static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
+static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
 {
-	rndis_init_cmplt_type	*resp;
-	rndis_resp_t            *r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	rndis_init_cmplt_type *resp;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
 	if (!params->dev)
 		return -ENOTSUPP;
 
-	r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
+	r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_init_cmplt_type *) r->buf;
+	resp = (rndis_init_cmplt_type *)r->buf;
 
-	resp->MessageType = cpu_to_le32 (
-			REMOTE_NDIS_INITIALIZE_CMPLT);
-	resp->MessageLength = cpu_to_le32 (52);
+	resp->MessageType = cpu_to_le32(REMOTE_NDIS_INITIALIZE_CMPLT);
+	resp->MessageLength = cpu_to_le32(52);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-	resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
-	resp->MajorVersion = cpu_to_le32 (RNDIS_MAJOR_VERSION);
-	resp->MinorVersion = cpu_to_le32 (RNDIS_MINOR_VERSION);
-	resp->DeviceFlags = cpu_to_le32 (RNDIS_DF_CONNECTIONLESS);
-	resp->Medium = cpu_to_le32 (RNDIS_MEDIUM_802_3);
-	resp->MaxPacketsPerTransfer = cpu_to_le32 (1);
-	resp->MaxTransferSize = cpu_to_le32 (
+	resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
+	resp->MajorVersion = cpu_to_le32(RNDIS_MAJOR_VERSION);
+	resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION);
+	resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
+	resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3);
+	resp->MaxPacketsPerTransfer = cpu_to_le32(1);
+	resp->MaxTransferSize = cpu_to_le32(
 		  params->dev->mtu
-		+ sizeof (struct ethhdr)
-		+ sizeof (struct rndis_packet_msg_type)
+		+ sizeof(struct ethhdr)
+		+ sizeof(struct rndis_packet_msg_type)
 		+ 22);
-	resp->PacketAlignmentFactor = cpu_to_le32 (0);
-	resp->AFListOffset = cpu_to_le32 (0);
-	resp->AFListSize = cpu_to_le32 (0);
+	resp->PacketAlignmentFactor = cpu_to_le32(0);
+	resp->AFListOffset = cpu_to_le32(0);
+	resp->AFListSize = cpu_to_le32(0);
 
 	params->resp_avail(params->v);
 	return 0;
 }
 
-static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
+static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
 {
 	rndis_query_cmplt_type *resp;
-	rndis_resp_t            *r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
 	/* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */
 	if (!params->dev)
@@ -616,47 +616,46 @@
 	 * rndis_query_cmplt_type followed by data.
 	 * oid_supported_list is the largest data reply
 	 */
-	r = rndis_add_response (configNr,
-		sizeof (oid_supported_list) + sizeof(rndis_query_cmplt_type));
+	r = rndis_add_response(configNr,
+		sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_query_cmplt_type *) r->buf;
+	resp = (rndis_query_cmplt_type *)r->buf;
 
-	resp->MessageType = cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);
+	resp->MessageType = cpu_to_le32(REMOTE_NDIS_QUERY_CMPLT);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
 
-	if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID),
+	if (gen_ndis_query_resp(configNr, le32_to_cpu(buf->OID),
 			le32_to_cpu(buf->InformationBufferOffset)
-					+ 8 + (u8 *) buf,
+					+ 8 + (u8 *)buf,
 			le32_to_cpu(buf->InformationBufferLength),
 			r)) {
 		/* OID not supported */
-		resp->Status = cpu_to_le32 (
-				RNDIS_STATUS_NOT_SUPPORTED);
-		resp->MessageLength = cpu_to_le32 (sizeof *resp);
-		resp->InformationBufferLength = cpu_to_le32 (0);
-		resp->InformationBufferOffset = cpu_to_le32 (0);
+		resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
+		resp->MessageLength = cpu_to_le32(sizeof *resp);
+		resp->InformationBufferLength = cpu_to_le32(0);
+		resp->InformationBufferOffset = cpu_to_le32(0);
 	} else
-		resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+		resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
 
 	params->resp_avail(params->v);
 	return 0;
 }
 
-static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
+static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
 {
-	u32			BufLength, BufOffset;
-	rndis_set_cmplt_type	*resp;
-	rndis_resp_t		*r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	u32 BufLength, BufOffset;
+	rndis_set_cmplt_type *resp;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
-	r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
+	r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_set_cmplt_type *) r->buf;
+	resp = (rndis_set_cmplt_type *)r->buf;
 
-	BufLength = le32_to_cpu (buf->InformationBufferLength);
-	BufOffset = le32_to_cpu (buf->InformationBufferOffset);
+	BufLength = le32_to_cpu(buf->InformationBufferLength);
+	BufOffset = le32_to_cpu(buf->InformationBufferOffset);
 
 #ifdef	VERBOSE_DEBUG
 	pr_debug("%s: Length: %d\n", __func__, BufLength);
@@ -670,59 +669,59 @@
 	pr_debug("\n");
 #endif
 
-	resp->MessageType = cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
-	resp->MessageLength = cpu_to_le32 (16);
+	resp->MessageType = cpu_to_le32(REMOTE_NDIS_SET_CMPLT);
+	resp->MessageLength = cpu_to_le32(16);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-	if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID),
-			((u8 *) buf) + 8 + BufOffset, BufLength, r))
-		resp->Status = cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
+	if (gen_ndis_set_resp(configNr, le32_to_cpu(buf->OID),
+			((u8 *)buf) + 8 + BufOffset, BufLength, r))
+		resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
 	else
-		resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+		resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
 
 	params->resp_avail(params->v);
 	return 0;
 }
 
-static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
+static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf)
 {
-	rndis_reset_cmplt_type	*resp;
-	rndis_resp_t		*r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	rndis_reset_cmplt_type *resp;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
-	r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
+	r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_reset_cmplt_type *) r->buf;
+	resp = (rndis_reset_cmplt_type *)r->buf;
 
-	resp->MessageType = cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT);
-	resp->MessageLength = cpu_to_le32 (16);
-	resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+	resp->MessageType = cpu_to_le32(REMOTE_NDIS_RESET_CMPLT);
+	resp->MessageLength = cpu_to_le32(16);
+	resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
 	/* resent information */
-	resp->AddressingReset = cpu_to_le32 (1);
+	resp->AddressingReset = cpu_to_le32(1);
 
 	params->resp_avail(params->v);
 	return 0;
 }
 
-static int rndis_keepalive_response (int configNr,
-				rndis_keepalive_msg_type *buf)
+static int rndis_keepalive_response(int configNr,
+				    rndis_keepalive_msg_type *buf)
 {
-	rndis_keepalive_cmplt_type	*resp;
-	rndis_resp_t			*r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	rndis_keepalive_cmplt_type *resp;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
 	/* host "should" check only in RNDIS_DATA_INITIALIZED state */
 
-	r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));
+	r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_keepalive_cmplt_type *) r->buf;
+	resp = (rndis_keepalive_cmplt_type *)r->buf;
 
-	resp->MessageType = cpu_to_le32 (
+	resp->MessageType = cpu_to_le32(
 			REMOTE_NDIS_KEEPALIVE_CMPLT);
-	resp->MessageLength = cpu_to_le32 (16);
+	resp->MessageLength = cpu_to_le32(16);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-	resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+	resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
 
 	params->resp_avail(params->v);
 	return 0;
@@ -732,86 +731,85 @@
 /*
  * Device to Host Comunication
  */
-static int rndis_indicate_status_msg (int configNr, u32 status)
+static int rndis_indicate_status_msg(int configNr, u32 status)
 {
-	rndis_indicate_status_msg_type	*resp;
-	rndis_resp_t			*r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	rndis_indicate_status_msg_type *resp;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
 	if (params->state == RNDIS_UNINITIALIZED)
 		return -ENOTSUPP;
 
-	r = rndis_add_response (configNr,
-				sizeof (rndis_indicate_status_msg_type));
+	r = rndis_add_response(configNr,
+				sizeof(rndis_indicate_status_msg_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_indicate_status_msg_type *) r->buf;
+	resp = (rndis_indicate_status_msg_type *)r->buf;
 
-	resp->MessageType = cpu_to_le32 (
-			REMOTE_NDIS_INDICATE_STATUS_MSG);
-	resp->MessageLength = cpu_to_le32 (20);
-	resp->Status = cpu_to_le32 (status);
-	resp->StatusBufferLength = cpu_to_le32 (0);
-	resp->StatusBufferOffset = cpu_to_le32 (0);
+	resp->MessageType = cpu_to_le32(REMOTE_NDIS_INDICATE_STATUS_MSG);
+	resp->MessageLength = cpu_to_le32(20);
+	resp->Status = cpu_to_le32(status);
+	resp->StatusBufferLength = cpu_to_le32(0);
+	resp->StatusBufferOffset = cpu_to_le32(0);
 
 	params->resp_avail(params->v);
 	return 0;
 }
 
-int rndis_signal_connect (int configNr)
+int rndis_signal_connect(int configNr)
 {
-	rndis_per_dev_params [configNr].media_state
+	rndis_per_dev_params[configNr].media_state
 			= NDIS_MEDIA_STATE_CONNECTED;
-	return rndis_indicate_status_msg (configNr,
+	return rndis_indicate_status_msg(configNr,
 					  RNDIS_STATUS_MEDIA_CONNECT);
 }
 
-int rndis_signal_disconnect (int configNr)
+int rndis_signal_disconnect(int configNr)
 {
-	rndis_per_dev_params [configNr].media_state
+	rndis_per_dev_params[configNr].media_state
 			= NDIS_MEDIA_STATE_DISCONNECTED;
-	return rndis_indicate_status_msg (configNr,
+	return rndis_indicate_status_msg(configNr,
 					  RNDIS_STATUS_MEDIA_DISCONNECT);
 }
 
-void rndis_uninit (int configNr)
+void rndis_uninit(int configNr)
 {
 	u8 *buf;
 	u32 length;
 
 	if (configNr >= RNDIS_MAX_CONFIGS)
 		return;
-	rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED;
+	rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED;
 
 	/* drain the response queue */
 	while ((buf = rndis_get_next_response(configNr, &length)))
 		rndis_free_response(configNr, buf);
 }
 
-void rndis_set_host_mac (int configNr, const u8 *addr)
+void rndis_set_host_mac(int configNr, const u8 *addr)
 {
-	rndis_per_dev_params [configNr].host_mac = addr;
+	rndis_per_dev_params[configNr].host_mac = addr;
 }
 
 /*
  * Message Parser
  */
-int rndis_msg_parser (u8 configNr, u8 *buf)
+int rndis_msg_parser(u8 configNr, u8 *buf)
 {
 	u32 MsgType, MsgLength;
 	__le32 *tmp;
-	struct rndis_params		*params;
+	struct rndis_params *params;
 
 	if (!buf)
 		return -ENOMEM;
 
-	tmp = (__le32 *) buf;
+	tmp = (__le32 *)buf;
 	MsgType   = get_unaligned_le32(tmp++);
 	MsgLength = get_unaligned_le32(tmp++);
 
 	if (configNr >= RNDIS_MAX_CONFIGS)
 		return -ENOTSUPP;
-	params = &rndis_per_dev_params [configNr];
+	params = &rndis_per_dev_params[configNr];
 
 	/* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
 	 * rx/tx statistics and link status, in addition to KEEPALIVE traffic
@@ -822,41 +820,41 @@
 	switch (MsgType) {
 	case REMOTE_NDIS_INITIALIZE_MSG:
 		pr_debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
-			__func__ );
+			__func__);
 		params->state = RNDIS_INITIALIZED;
-		return  rndis_init_response (configNr,
-					(rndis_init_msg_type *) buf);
+		return rndis_init_response(configNr,
+					(rndis_init_msg_type *)buf);
 
 	case REMOTE_NDIS_HALT_MSG:
 		pr_debug("%s: REMOTE_NDIS_HALT_MSG\n",
-			__func__ );
+			__func__);
 		params->state = RNDIS_UNINITIALIZED;
 		if (params->dev) {
-			netif_carrier_off (params->dev);
-			netif_stop_queue (params->dev);
+			netif_carrier_off(params->dev);
+			netif_stop_queue(params->dev);
 		}
 		return 0;
 
 	case REMOTE_NDIS_QUERY_MSG:
-		return rndis_query_response (configNr,
-					(rndis_query_msg_type *) buf);
+		return rndis_query_response(configNr,
+					(rndis_query_msg_type *)buf);
 
 	case REMOTE_NDIS_SET_MSG:
-		return rndis_set_response (configNr,
-					(rndis_set_msg_type *) buf);
+		return rndis_set_response(configNr,
+					(rndis_set_msg_type *)buf);
 
 	case REMOTE_NDIS_RESET_MSG:
 		pr_debug("%s: REMOTE_NDIS_RESET_MSG\n",
-			__func__ );
-		return rndis_reset_response (configNr,
-					(rndis_reset_msg_type *) buf);
+			__func__);
+		return rndis_reset_response(configNr,
+					(rndis_reset_msg_type *)buf);
 
 	case REMOTE_NDIS_KEEPALIVE_MSG:
 		/* For USB: host does this every 5 seconds */
 		if (rndis_debug > 1)
 			pr_debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
-				__func__ );
-		return rndis_keepalive_response (configNr,
+				__func__);
+		return rndis_keepalive_response(configNr,
 						 (rndis_keepalive_msg_type *)
 						 buf);
 
@@ -866,7 +864,7 @@
 		 * suspending itself.
 		 */
 		pr_warning("%s: unknown RNDIS message 0x%08X len %d\n",
-			__func__ , MsgType, MsgLength);
+			__func__, MsgType, MsgLength);
 		{
 			unsigned i;
 			for (i = 0; i < MsgLength; i += 16) {
@@ -901,10 +899,10 @@
 		return -EINVAL;
 
 	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
-		if (!rndis_per_dev_params [i].used) {
-			rndis_per_dev_params [i].used = 1;
-			rndis_per_dev_params [i].resp_avail = resp_avail;
-			rndis_per_dev_params [i].v = v;
+		if (!rndis_per_dev_params[i].used) {
+			rndis_per_dev_params[i].used = 1;
+			rndis_per_dev_params[i].resp_avail = resp_avail;
+			rndis_per_dev_params[i].v = v;
 			pr_debug("%s: configNr = %d\n", __func__, i);
 			return i;
 		}
@@ -914,12 +912,12 @@
 	return -ENODEV;
 }
 
-void rndis_deregister (int configNr)
+void rndis_deregister(int configNr)
 {
-	pr_debug("%s: \n", __func__);
+	pr_debug("%s:\n", __func__);
 
 	if (configNr >= RNDIS_MAX_CONFIGS) return;
-	rndis_per_dev_params [configNr].used = 0;
+	rndis_per_dev_params[configNr].used = 0;
 
 	return;
 }
@@ -931,76 +929,76 @@
 		return -EINVAL;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
-	rndis_per_dev_params [configNr].dev = dev;
-	rndis_per_dev_params [configNr].filter = cdc_filter;
+	rndis_per_dev_params[configNr].dev = dev;
+	rndis_per_dev_params[configNr].filter = cdc_filter;
 
 	return 0;
 }
 
-int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
+int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
 {
 	pr_debug("%s:\n", __func__);
 	if (!vendorDescr) return -1;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
-	rndis_per_dev_params [configNr].vendorID = vendorID;
-	rndis_per_dev_params [configNr].vendorDescr = vendorDescr;
+	rndis_per_dev_params[configNr].vendorID = vendorID;
+	rndis_per_dev_params[configNr].vendorDescr = vendorDescr;
 
 	return 0;
 }
 
-int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
+int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
 {
 	pr_debug("%s: %u %u\n", __func__, medium, speed);
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
-	rndis_per_dev_params [configNr].medium = medium;
-	rndis_per_dev_params [configNr].speed = speed;
+	rndis_per_dev_params[configNr].medium = medium;
+	rndis_per_dev_params[configNr].speed = speed;
 
 	return 0;
 }
 
-void rndis_add_hdr (struct sk_buff *skb)
+void rndis_add_hdr(struct sk_buff *skb)
 {
-	struct rndis_packet_msg_type	*header;
+	struct rndis_packet_msg_type *header;
 
 	if (!skb)
 		return;
-	header = (void *) skb_push (skb, sizeof *header);
-	memset (header, 0, sizeof *header);
+	header = (void *)skb_push(skb, sizeof(*header));
+	memset(header, 0, sizeof *header);
 	header->MessageType = cpu_to_le32(REMOTE_NDIS_PACKET_MSG);
 	header->MessageLength = cpu_to_le32(skb->len);
-	header->DataOffset = cpu_to_le32 (36);
-	header->DataLength = cpu_to_le32(skb->len - sizeof *header);
+	header->DataOffset = cpu_to_le32(36);
+	header->DataLength = cpu_to_le32(skb->len - sizeof(*header));
 }
 
-void rndis_free_response (int configNr, u8 *buf)
+void rndis_free_response(int configNr, u8 *buf)
 {
-	rndis_resp_t		*r;
-	struct list_head	*act, *tmp;
+	rndis_resp_t *r;
+	struct list_head *act, *tmp;
 
-	list_for_each_safe (act, tmp,
-			&(rndis_per_dev_params [configNr].resp_queue))
+	list_for_each_safe(act, tmp,
+			&(rndis_per_dev_params[configNr].resp_queue))
 	{
-		r = list_entry (act, rndis_resp_t, list);
+		r = list_entry(act, rndis_resp_t, list);
 		if (r && r->buf == buf) {
-			list_del (&r->list);
-			kfree (r);
+			list_del(&r->list);
+			kfree(r);
 		}
 	}
 }
 
-u8 *rndis_get_next_response (int configNr, u32 *length)
+u8 *rndis_get_next_response(int configNr, u32 *length)
 {
-	rndis_resp_t		*r;
-	struct list_head	*act, *tmp;
+	rndis_resp_t *r;
+	struct list_head *act, *tmp;
 
 	if (!length) return NULL;
 
-	list_for_each_safe (act, tmp,
-			&(rndis_per_dev_params [configNr].resp_queue))
+	list_for_each_safe(act, tmp,
+			&(rndis_per_dev_params[configNr].resp_queue))
 	{
-		r = list_entry (act, rndis_resp_t, list);
+		r = list_entry(act, rndis_resp_t, list);
 		if (!r->send) {
 			r->send = 1;
 			*length = r->length;
@@ -1011,20 +1009,20 @@
 	return NULL;
 }
 
-static rndis_resp_t *rndis_add_response (int configNr, u32 length)
+static rndis_resp_t *rndis_add_response(int configNr, u32 length)
 {
-	rndis_resp_t	*r;
+	rndis_resp_t *r;
 
-	/* NOTE:  this gets copied into ether.c USB_BUFSIZ bytes ... */
-	r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);
+	/* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */
+	r = kmalloc(sizeof(rndis_resp_t) + length, GFP_ATOMIC);
 	if (!r) return NULL;
 
-	r->buf = (u8 *) (r + 1);
+	r->buf = (u8 *)(r + 1);
 	r->length = length;
 	r->send = 0;
 
-	list_add_tail (&r->list,
-		&(rndis_per_dev_params [configNr].resp_queue));
+	list_add_tail(&r->list,
+		&(rndis_per_dev_params[configNr].resp_queue));
 	return r;
 }
 
@@ -1033,7 +1031,7 @@
 			struct sk_buff_head *list)
 {
 	/* tmp points to a struct rndis_packet_msg_type */
-	__le32		*tmp = (void *) skb->data;
+	__le32 *tmp = (void *)skb->data;
 
 	/* MessageType, MessageLength */
 	if (cpu_to_le32(REMOTE_NDIS_PACKET_MSG)
@@ -1054,7 +1052,7 @@
 	return 0;
 }
 
-#ifdef	CONFIG_USB_GADGET_DEBUG_FILES
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
 
 static int rndis_proc_show(struct seq_file *m, void *v)
 {
@@ -1087,7 +1085,7 @@
 }
 
 static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
-		size_t count, loff_t *ppos)
+				size_t count, loff_t *ppos)
 {
 	rndis_params *p = PDE(file->f_path.dentry->d_inode)->data;
 	u32 speed = 0;
@@ -1109,11 +1107,11 @@
 		case '8':
 		case '9':
 			fl_speed = 1;
-			speed = speed*10 + c - '0';
+			speed = speed * 10 + c - '0';
 			break;
 		case 'C':
 		case 'c':
-			rndis_signal_connect (p->confignr);
+			rndis_signal_connect(p->confignr);
 			break;
 		case 'D':
 		case 'd':
@@ -1145,11 +1143,11 @@
 	.write		= rndis_proc_write,
 };
 
-#define	NAME_TEMPLATE	"driver/rndis-%03d"
+#define	NAME_TEMPLATE "driver/rndis-%03d"
 
 static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
 
-#endif	/* CONFIG_USB_GADGET_DEBUG_FILES */
+#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
 
 
 int rndis_init(void)
@@ -1160,42 +1158,40 @@
 #ifdef	CONFIG_USB_GADGET_DEBUG_FILES
 		char name [20];
 
-		sprintf (name, NAME_TEMPLATE, i);
-		if (!(rndis_connect_state [i]
-				= proc_create_data(name, 0660, NULL,
+		sprintf(name, NAME_TEMPLATE, i);
+		rndis_connect_state[i] = proc_create_data(name, 0660, NULL,
 					&rndis_proc_fops,
-					(void *)(rndis_per_dev_params + i))))
-		{
-			pr_debug("%s :remove entries", __func__);
+					(void *)(rndis_per_dev_params + i));
+		if (!rndis_connect_state[i]) {
+			pr_debug("%s: remove entries", __func__);
 			while (i) {
-				sprintf (name, NAME_TEMPLATE, --i);
-				remove_proc_entry (name, NULL);
+				sprintf(name, NAME_TEMPLATE, --i);
+				remove_proc_entry(name, NULL);
 			}
 			pr_debug("\n");
 			return -EIO;
 		}
 #endif
-		rndis_per_dev_params [i].confignr = i;
-		rndis_per_dev_params [i].used = 0;
-		rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED;
-		rndis_per_dev_params [i].media_state
+		rndis_per_dev_params[i].confignr = i;
+		rndis_per_dev_params[i].used = 0;
+		rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED;
+		rndis_per_dev_params[i].media_state
 				= NDIS_MEDIA_STATE_DISCONNECTED;
-		INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue));
+		INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue));
 	}
 
 	return 0;
 }
 
-void rndis_exit (void)
+void rndis_exit(void)
 {
-#ifdef	CONFIG_USB_GADGET_DEBUG_FILES
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
 	u8 i;
-	char name [20];
+	char name[20];
 
 	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
-		sprintf (name, NAME_TEMPLATE, i);
-		remove_proc_entry (name, NULL);
+		sprintf(name, NAME_TEMPLATE, i);
+		remove_proc_entry(name, NULL);
 	}
 #endif
 }
-
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index a229744..ef825c3 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -2523,7 +2523,8 @@
 	return 0;
 }
 
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct s3c_hsotg *hsotg = our_hsotg;
 	int ret;
@@ -2543,7 +2544,7 @@
 		dev_err(hsotg->dev, "%s: bad speed\n", __func__);
 	}
 
-	if (!driver->bind || !driver->setup) {
+	if (!bind || !driver->setup) {
 		dev_err(hsotg->dev, "%s: missing entry points\n", __func__);
 		return -EINVAL;
 	}
@@ -2562,7 +2563,7 @@
 		goto err;
 	}
 
-	ret = driver->bind(&hsotg->gadget);
+	ret = bind(&hsotg->gadget);
 	if (ret) {
 		dev_err(hsotg->dev, "failed bind %s\n", driver->driver.name);
 
@@ -2687,7 +2688,7 @@
 	hsotg->gadget.dev.driver = NULL;
 	return ret;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index ea2b3c7..c244895 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1632,15 +1632,15 @@
 }
 
 /*
- *	usb_gadget_register_driver
+ *	usb_gadget_probe_driver
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct s3c2410_udc *udc = the_controller;
 	int		retval;
 
-	dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n",
-		driver->driver.name);
+	dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name);
 
 	/* Sanity checks */
 	if (!udc)
@@ -1649,10 +1649,9 @@
 	if (udc->driver)
 		return -EBUSY;
 
-	if (!driver->bind || !driver->setup
-			|| driver->speed < USB_SPEED_FULL) {
+	if (!bind || !driver->setup || driver->speed < USB_SPEED_FULL) {
 		printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
-			driver->bind, driver->setup, driver->speed);
+			bind, driver->setup, driver->speed);
 		return -EINVAL;
 	}
 #if defined(MODULE)
@@ -1675,7 +1674,7 @@
 	dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",
 		driver->driver.name);
 
-	if ((retval = driver->bind (&udc->gadget)) != 0) {
+	if ((retval = bind(&udc->gadget)) != 0) {
 		device_del(&udc->gadget.dev);
 		goto register_error;
 	}
@@ -1690,6 +1689,7 @@
 	udc->gadget.dev.driver = NULL;
 	return retval;
 }
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /*
  *	usb_gadget_unregister_driver
@@ -2049,7 +2049,6 @@
 }
 
 EXPORT_SYMBOL(usb_gadget_unregister_driver);
-EXPORT_SYMBOL(usb_gadget_register_driver);
 
 module_init(udc_init);
 module_exit(udc_exit);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index b22eedb..1ac57a9 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -137,7 +137,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref serial_bind_config(struct usb_configuration *c)
+static int __init serial_bind_config(struct usb_configuration *c)
 {
 	unsigned i;
 	int status = 0;
@@ -155,13 +155,12 @@
 
 static struct usb_configuration serial_config_driver = {
 	/* .label = f(use_acm) */
-	.bind		= serial_bind_config,
 	/* .bConfigurationValue = f(use_acm) */
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
 };
 
-static int __ref gs_bind(struct usb_composite_dev *cdev)
+static int __init gs_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
@@ -225,7 +224,8 @@
 	}
 
 	/* register our configuration */
-	status = usb_add_config(cdev, &serial_config_driver);
+	status = usb_add_config(cdev, &serial_config_driver,
+			serial_bind_config);
 	if (status < 0)
 		goto fail;
 
@@ -242,7 +242,6 @@
 	.name		= "g_serial",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= gs_bind,
 };
 
 static int __init init(void)
@@ -271,7 +270,7 @@
 	}
 	strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
 
-	return usb_composite_register(&gserial_driver);
+	return usb_composite_probe(&gserial_driver, gs_bind);
 }
 module_init(init);
 
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 484acfb..3b513ba 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -26,7 +26,6 @@
  * be defined (each of type pointer to char):
  *  - fsg_string_manufacturer -- name of the manufacturer
  *  - fsg_string_product      -- name of the product
- *  - fsg_string_serial       -- product's serial
  *  - fsg_string_config       -- name of the configuration
  *  - fsg_string_interface    -- name of the interface
  * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
@@ -54,6 +53,8 @@
  */
 
 
+#include <linux/usb/storage.h>
+#include <scsi/scsi.h>
 #include <asm/unaligned.h>
 
 
@@ -153,23 +154,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* SCSI device types */
-#define TYPE_DISK	0x00
-#define TYPE_CDROM	0x05
-
-/* USB protocol value = the transport method */
-#define USB_PR_CBI	0x00		/* Control/Bulk/Interrupt */
-#define USB_PR_CB	0x01		/* Control/Bulk w/o interrupt */
-#define USB_PR_BULK	0x50		/* Bulk-only */
-
-/* USB subclass value = the protocol encapsulation */
-#define USB_SC_RBC	0x01		/* Reduced Block Commands (flash) */
-#define USB_SC_8020	0x02		/* SFF-8020i, MMC-2, ATAPI (CD-ROM) */
-#define USB_SC_QIC	0x03		/* QIC-157 (tape) */
-#define USB_SC_UFI	0x04		/* UFI (floppy) */
-#define USB_SC_8070	0x05		/* SFF-8070i (removable) */
-#define USB_SC_SCSI	0x06		/* Transparent SCSI */
-
 /* Bulk-only data structures */
 
 /* Command Block Wrapper */
@@ -221,33 +205,6 @@
 /* Length of a SCSI Command Data Block */
 #define MAX_COMMAND_SIZE	16
 
-/* SCSI commands that we recognize */
-#define SC_FORMAT_UNIT			0x04
-#define SC_INQUIRY			0x12
-#define SC_MODE_SELECT_6		0x15
-#define SC_MODE_SELECT_10		0x55
-#define SC_MODE_SENSE_6			0x1a
-#define SC_MODE_SENSE_10		0x5a
-#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL	0x1e
-#define SC_READ_6			0x08
-#define SC_READ_10			0x28
-#define SC_READ_12			0xa8
-#define SC_READ_CAPACITY		0x25
-#define SC_READ_FORMAT_CAPACITIES	0x23
-#define SC_READ_HEADER			0x44
-#define SC_READ_TOC			0x43
-#define SC_RELEASE			0x17
-#define SC_REQUEST_SENSE		0x03
-#define SC_RESERVE			0x16
-#define SC_SEND_DIAGNOSTIC		0x1d
-#define SC_START_STOP_UNIT		0x1b
-#define SC_SYNCHRONIZE_CACHE		0x35
-#define SC_TEST_UNIT_READY		0x00
-#define SC_VERIFY			0x2f
-#define SC_WRITE_6			0x0a
-#define SC_WRITE_10			0x2a
-#define SC_WRITE_12			0xaa
-
 /* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
 #define SS_NO_SENSE				0
 #define SS_COMMUNICATION_FAILURE		0x040800
@@ -552,7 +509,7 @@
 #ifndef FSG_NO_DEVICE_STRINGS
 	{FSG_STRING_MANUFACTURER,	fsg_string_manufacturer},
 	{FSG_STRING_PRODUCT,		fsg_string_product},
-	{FSG_STRING_SERIAL,		fsg_string_serial},
+	{FSG_STRING_SERIAL,		""},
 	{FSG_STRING_CONFIG,		fsg_string_config},
 #endif
 	{FSG_STRING_INTERFACE,		fsg_string_interface},
diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c
index de1deb7..a5a0fdb 100644
--- a/drivers/usb/gadget/webcam.c
+++ b/drivers/usb/gadget/webcam.c
@@ -308,7 +308,7 @@
  * USB configuration
  */
 
-static int __ref
+static int __init
 webcam_config_bind(struct usb_configuration *c)
 {
 	return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls,
@@ -317,7 +317,6 @@
 
 static struct usb_configuration webcam_config_driver = {
 	.label			= webcam_config_label,
-	.bind			= webcam_config_bind,
 	.bConfigurationValue	= 1,
 	.iConfiguration		= 0, /* dynamic */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -330,7 +329,7 @@
 	return 0;
 }
 
-static int __ref
+static int __init
 webcam_bind(struct usb_composite_dev *cdev)
 {
 	int ret;
@@ -354,7 +353,8 @@
 	webcam_config_driver.iConfiguration = ret;
 
 	/* Register our configuration. */
-	if ((ret = usb_add_config(cdev, &webcam_config_driver)) < 0)
+	if ((ret = usb_add_config(cdev, &webcam_config_driver,
+					webcam_config_bind)) < 0)
 		goto error;
 
 	INFO(cdev, "Webcam Video Gadget\n");
@@ -373,14 +373,13 @@
 	.name		= "g_webcam",
 	.dev		= &webcam_device_descriptor,
 	.strings	= webcam_device_strings,
-	.bind		= webcam_bind,
 	.unbind		= webcam_unbind,
 };
 
 static int __init
 webcam_init(void)
 {
-	return usb_composite_register(&webcam_driver);
+	return usb_composite_probe(&webcam_driver, webcam_bind);
 }
 
 static void __exit
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index cf353920..6d16db9 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -264,7 +264,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref zero_bind(struct usb_composite_dev *cdev)
+static int __init zero_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
@@ -340,7 +340,6 @@
 	.name		= "zero",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= zero_bind,
 	.unbind		= zero_unbind,
 	.suspend	= zero_suspend,
 	.resume		= zero_resume,
@@ -351,7 +350,7 @@
 
 static int __init init(void)
 {
-	return usb_composite_register(&zero_driver);
+	return usb_composite_probe(&zero_driver, zero_bind);
 }
 module_init(init);
 
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 2d926ce..bf2e7d2 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -93,12 +93,14 @@
 
 config USB_EHCI_BIG_ENDIAN_MMIO
 	bool
-	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
+	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || \
+				    XPS_USB_HCD_XILINX || PPC_MPC512x)
 	default y
 
 config USB_EHCI_BIG_ENDIAN_DESC
 	bool
-	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
+	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
+				    PPC_MPC512x)
 	default y
 
 config XPS_USB_HCD_XILINX
@@ -112,10 +114,14 @@
 		support both high speed and full speed devices, or high speed
 		devices only.
 
+config USB_FSL_MPH_DR_OF
+	tristate
+
 config USB_EHCI_FSL
 	bool "Support for Freescale on-chip EHCI USB controller"
 	depends on USB_EHCI_HCD && FSL_SOC
 	select USB_EHCI_ROOT_HUB_TT
+	select USB_FSL_MPH_DR_OF
 	---help---
 	  Variation of ARC USB block used in some Freescale chips.
 
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index b6315aa..91c5a1b 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -2,17 +2,17 @@
 # Makefile for USB Host Controller Drivers
 #
 
-ifeq ($(CONFIG_USB_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
+ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 
-isp1760-objs := isp1760-hcd.o isp1760-if.o
-fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \
-	     fhci-tds.o fhci-sched.o
-ifeq ($(CONFIG_FHCI_DEBUG),y)
-fhci-objs += fhci-dbg.o
-endif
-xhci-hcd-objs := xhci.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o
+isp1760-y := isp1760-hcd.o isp1760-if.o
+
+fhci-y := fhci-hcd.o fhci-hub.o fhci-q.o
+fhci-y += fhci-mem.o fhci-tds.o fhci-sched.o
+
+fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o
+
+xhci-hcd-y := xhci.o xhci-mem.o xhci-pci.o
+xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
 
 obj-$(CONFIG_USB_WHCI_HCD)	+= whci/
 
@@ -33,4 +33,4 @@
 obj-$(CONFIG_USB_ISP1760_HCD)	+= isp1760.o
 obj-$(CONFIG_USB_HWA_HCD)	+= hwa-hc.o
 obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd.o
-
+obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-mph-dr-of.o
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 76b7fd2..86afdc7 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -369,18 +369,21 @@
 	.open		= debug_async_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 static const struct file_operations debug_periodic_fops = {
 	.owner		= THIS_MODULE,
 	.open		= debug_periodic_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 static const struct file_operations debug_registers_fops = {
 	.owner		= THIS_MODULE,
 	.open		= debug_registers_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 static const struct file_operations debug_lpm_fops = {
 	.owner		= THIS_MODULE,
@@ -388,6 +391,7 @@
 	.read		= debug_lpm_read,
 	.write		= debug_lpm_write,
 	.release	= debug_lpm_close,
+	.llseek		= noop_llseek,
 };
 
 static struct dentry *ehci_debug_root;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index a416421..86e4289 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -116,13 +116,33 @@
 		goto err3;
 	}
 
-	/* Enable USB controller */
-	temp = in_be32(hcd->regs + 0x500);
-	out_be32(hcd->regs + 0x500, temp | 0x4);
+	pdata->regs = hcd->regs;
 
-	/* Set to Host mode */
-	temp = in_le32(hcd->regs + 0x1a8);
-	out_le32(hcd->regs + 0x1a8, temp | 0x3);
+	/*
+	 * do platform specific init: check the clock, grab/config pins, etc.
+	 */
+	if (pdata->init && pdata->init(pdev)) {
+		retval = -ENODEV;
+		goto err3;
+	}
+
+	/*
+	 * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs
+	 * flag for 83xx or 8536 system interface registers.
+	 */
+	if (pdata->big_endian_mmio)
+		temp = in_be32(hcd->regs + FSL_SOC_USB_ID);
+	else
+		temp = in_le32(hcd->regs + FSL_SOC_USB_ID);
+
+	if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK))
+		pdata->have_sysif_regs = 1;
+
+	/* Enable USB controller, 83xx or 8536 */
+	if (pdata->have_sysif_regs)
+		setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
+
+	/* Don't need to set host mode here. It will be done by tdi_reset() */
 
 	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
 	if (retval != 0)
@@ -137,6 +157,8 @@
 	usb_put_hcd(hcd);
       err1:
 	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
+	if (pdata->exit)
+		pdata->exit(pdev);
 	return retval;
 }
 
@@ -154,17 +176,30 @@
 static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
 			       struct platform_device *pdev)
 {
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
 	usb_remove_hcd(hcd);
+
+	/*
+	 * do platform specific un-initialization:
+	 * release iomux pins, disable clock, etc.
+	 */
+	if (pdata->exit)
+		pdata->exit(pdev);
 	iounmap(hcd->regs);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 }
 
-static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
-			      enum fsl_usb2_phy_modes phy_mode,
-			      unsigned int port_offset)
+static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
+			       enum fsl_usb2_phy_modes phy_mode,
+			       unsigned int port_offset)
 {
-	u32 portsc = 0;
+	u32 portsc;
+
+	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
+	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
+
 	switch (phy_mode) {
 	case FSL_USB2_PHY_ULPI:
 		portsc |= PORT_PTS_ULPI;
@@ -184,20 +219,21 @@
 	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
 }
 
-static void mpc83xx_usb_setup(struct usb_hcd *hcd)
+static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 {
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct usb_hcd *hcd = ehci_to_hcd(ehci);
 	struct fsl_usb2_platform_data *pdata;
 	void __iomem *non_ehci = hcd->regs;
 	u32 temp;
 
-	pdata =
-	    (struct fsl_usb2_platform_data *)hcd->self.controller->
-	    platform_data;
+	pdata = hcd->self.controller->platform_data;
+
 	/* Enable PHY interface in the control reg. */
-	temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
-	out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
-	out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
+	if (pdata->have_sysif_regs) {
+		temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+		out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
+		out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
+	}
 
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
 	/*
@@ -214,7 +250,7 @@
 
 	if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
 			(pdata->operating_mode == FSL_USB2_DR_OTG))
-		mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
+		ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
 
 	if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
 		unsigned int chip, rev, svr;
@@ -228,27 +264,27 @@
 			ehci->has_fsl_port_bug = 1;
 
 		if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
-			mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
+			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
 		if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
-			mpc83xx_setup_phy(ehci, pdata->phy_mode, 1);
+			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1);
 	}
 
-	/* put controller in host mode. */
-	ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
+	if (pdata->have_sysif_regs) {
 #ifdef CONFIG_PPC_85xx
-	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
-	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
+		out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
+		out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
 #else
-	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
-	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
+		out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
+		out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
 #endif
-	out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
+		out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
+	}
 }
 
 /* called after powerup, by probe or system-pm "wakeup" */
 static int ehci_fsl_reinit(struct ehci_hcd *ehci)
 {
-	mpc83xx_usb_setup(ehci_to_hcd(ehci));
+	ehci_fsl_usb_setup(ehci);
 	ehci_port_power(ehci, 0);
 
 	return 0;
@@ -259,6 +295,11 @@
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
+	struct fsl_usb2_platform_data *pdata;
+
+	pdata = hcd->self.controller->platform_data;
+	ehci->big_endian_desc = pdata->big_endian_desc;
+	ehci->big_endian_mmio = pdata->big_endian_mmio;
 
 	/* EHCI registers start at offset 0x100 */
 	ehci->caps = hcd->regs + 0x100;
@@ -270,6 +311,8 @@
 	/* 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;
@@ -279,8 +322,6 @@
 	if (retval)
 		return retval;
 
-	hcd->has_tt = 1;
-
 	ehci->sbrn = 0x20;
 
 	ehci_reset(ehci);
@@ -372,7 +413,7 @@
 	 * generic hardware linkage
 	 */
 	.irq = ehci_irq,
-	.flags = HCD_USB2,
+	.flags = HCD_USB2 | HCD_MEMORY,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index b5e59db..2c83537 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2005 freescale semiconductor
+/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc.
  * Copyright (c) 2005 MontaVista Software
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -19,6 +19,9 @@
 #define _EHCI_FSL_H
 
 /* offsets for the non-ehci registers in the FSL SOC USB controller */
+#define FSL_SOC_USB_ID		0x0
+#define ID_MSK			0x3f
+#define NID_MSK			0x3f00
 #define FSL_SOC_USB_ULPIVP	0x170
 #define FSL_SOC_USB_PORTSC1	0x184
 #define PORT_PTS_MSK		(3<<30)
@@ -27,7 +30,14 @@
 #define	PORT_PTS_SERIAL		(3<<30)
 #define PORT_PTS_PTW		(1<<28)
 #define FSL_SOC_USB_PORTSC2	0x188
-#define FSL_SOC_USB_USBMODE	0x1a8
+
+#define FSL_SOC_USB_USBGENCTRL	0x200
+#define USBGENCTRL_PPP		(1 << 3)
+#define USBGENCTRL_PFP		(1 << 2)
+#define FSL_SOC_USB_ISIPHYCTRL	0x204
+#define ISIPHYCTRL_PXE		(1)
+#define ISIPHYCTRL_PHYE		(1 << 4)
+
 #define FSL_SOC_USB_SNOOP1	0x400	/* NOTE: big-endian */
 #define FSL_SOC_USB_SNOOP2	0x404	/* NOTE: big-endian */
 #define FSL_SOC_USB_AGECNTTHRSH	0x408	/* NOTE: big-endian */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 34a928d..15fe3ec 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -194,6 +194,17 @@
 	return -ETIMEDOUT;
 }
 
+/* check TDI/ARC silicon is in host mode */
+static int tdi_in_host_mode (struct ehci_hcd *ehci)
+{
+	u32 __iomem	*reg_ptr;
+	u32		tmp;
+
+	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
+	tmp = ehci_readl(ehci, reg_ptr);
+	return (tmp & 3) == USBMODE_CM_HC;
+}
+
 /* force HC to halt state from unknown (EHCI spec section 2.3) */
 static int ehci_halt (struct ehci_hcd *ehci)
 {
@@ -202,6 +213,10 @@
 	/* disable any irqs left enabled by previous code */
 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
 
+	if (ehci_is_TDI(ehci) && tdi_in_host_mode(ehci) == 0) {
+		return 0;
+	}
+
 	if ((temp & STS_HALT) != 0)
 		return 0;
 
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 1f3f01e..d36e4e7 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -40,7 +40,7 @@
 {
 	memset (qtd, 0, sizeof *qtd);
 	qtd->qtd_dma = dma;
-	qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
+	qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
 	qtd->hw_next = EHCI_LIST_END(ehci);
 	qtd->hw_alt_next = EHCI_LIST_END(ehci);
 	INIT_LIST_HEAD (&qtd->qtd_list);
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index a8ad8ac..ac9c4d7 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -26,9 +26,6 @@
 #include <mach/mxc_ehci.h>
 
 #define ULPI_VIEWPORT_OFFSET	0x170
-#define PORTSC_OFFSET		0x184
-#define USBMODE_OFFSET		0x1a8
-#define USBMODE_CM_HOST		3
 
 struct ehci_mxc_priv {
 	struct clk *usbclk, *ahbclk;
@@ -51,6 +48,8 @@
 	/* 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;
@@ -60,8 +59,6 @@
 	if (retval)
 		return retval;
 
-	hcd->has_tt = 1;
-
 	ehci->sbrn = 0x20;
 
 	ehci_reset(ehci);
@@ -191,12 +188,8 @@
 		clk_enable(priv->ahbclk);
 	}
 
-	/* set USBMODE to host mode */
-	temp = readl(hcd->regs + USBMODE_OFFSET);
-	writel(temp | USBMODE_CM_HOST, hcd->regs + USBMODE_OFFSET);
-
 	/* set up the PORTSCx register */
-	writel(pdata->portsc, hcd->regs + PORTSC_OFFSET);
+	ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]);
 	mdelay(10);
 
 	/* setup specific usb hw */
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
new file mode 100644
index 0000000..574b99e
--- /dev/null
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -0,0 +1,308 @@
+/*
+ * Setup platform devices needed by the Freescale multi-port host
+ * and/or dual-role USB controller modules based on the description
+ * in flat device tree.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+
+struct fsl_usb2_dev_data {
+	char *dr_mode;		/* controller mode */
+	char *drivers[3];	/* drivers to instantiate for this mode */
+	enum fsl_usb2_operating_modes op_mode;	/* operating mode */
+};
+
+struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {
+	{
+		.dr_mode = "host",
+		.drivers = { "fsl-ehci", NULL, NULL, },
+		.op_mode = FSL_USB2_DR_HOST,
+	},
+	{
+		.dr_mode = "otg",
+		.drivers = { "fsl-usb2-otg", "fsl-ehci", "fsl-usb2-udc", },
+		.op_mode = FSL_USB2_DR_OTG,
+	},
+	{
+		.dr_mode = "peripheral",
+		.drivers = { "fsl-usb2-udc", NULL, NULL, },
+		.op_mode = FSL_USB2_DR_DEVICE,
+	},
+};
+
+struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)
+{
+	const unsigned char *prop;
+	int i;
+
+	prop = of_get_property(np, "dr_mode", NULL);
+	if (prop) {
+		for (i = 0; i < ARRAY_SIZE(dr_mode_data); i++) {
+			if (!strcmp(prop, dr_mode_data[i].dr_mode))
+				return &dr_mode_data[i];
+		}
+	}
+	pr_warn("%s: Invalid 'dr_mode' property, fallback to host mode\n",
+		np->full_name);
+	return &dr_mode_data[0]; /* mode not specified, use host */
+}
+
+static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)
+{
+	if (!phy_type)
+		return FSL_USB2_PHY_NONE;
+	if (!strcasecmp(phy_type, "ulpi"))
+		return FSL_USB2_PHY_ULPI;
+	if (!strcasecmp(phy_type, "utmi"))
+		return FSL_USB2_PHY_UTMI;
+	if (!strcasecmp(phy_type, "utmi_wide"))
+		return FSL_USB2_PHY_UTMI_WIDE;
+	if (!strcasecmp(phy_type, "serial"))
+		return FSL_USB2_PHY_SERIAL;
+
+	return FSL_USB2_PHY_NONE;
+}
+
+struct platform_device * __devinit fsl_usb2_device_register(
+					struct platform_device *ofdev,
+					struct fsl_usb2_platform_data *pdata,
+					const char *name, int id)
+{
+	struct platform_device *pdev;
+	const struct resource *res = ofdev->resource;
+	unsigned int num = ofdev->num_resources;
+	int retval;
+
+	pdev = platform_device_alloc(name, id);
+	if (!pdev) {
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	pdev->dev.parent = &ofdev->dev;
+
+	pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
+	pdev->dev.dma_mask = &pdev->archdata.dma_mask;
+	*pdev->dev.dma_mask = *ofdev->dev.dma_mask;
+
+	retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+	if (retval)
+		goto error;
+
+	if (num) {
+		retval = platform_device_add_resources(pdev, res, num);
+		if (retval)
+			goto error;
+	}
+
+	retval = platform_device_add(pdev);
+	if (retval)
+		goto error;
+
+	return pdev;
+
+error:
+	platform_device_put(pdev);
+	return ERR_PTR(retval);
+}
+
+static const struct of_device_id fsl_usb2_mph_dr_of_match[];
+
+static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
+{
+	struct device_node *np = ofdev->dev.of_node;
+	struct platform_device *usb_dev;
+	struct fsl_usb2_platform_data data, *pdata;
+	struct fsl_usb2_dev_data *dev_data;
+	const struct of_device_id *match;
+	const unsigned char *prop;
+	static unsigned int idx;
+	int i;
+
+	if (!of_device_is_available(np))
+		return -ENODEV;
+
+	match = of_match_device(fsl_usb2_mph_dr_of_match, &ofdev->dev);
+	if (!match)
+		return -ENODEV;
+
+	pdata = &data;
+	if (match->data)
+		memcpy(pdata, match->data, sizeof(data));
+	else
+		memset(pdata, 0, sizeof(data));
+
+	dev_data = get_dr_mode_data(np);
+
+	if (of_device_is_compatible(np, "fsl-usb2-mph")) {
+		if (of_get_property(np, "port0", NULL))
+			pdata->port_enables |= FSL_USB2_PORT0_ENABLED;
+
+		if (of_get_property(np, "port1", NULL))
+			pdata->port_enables |= FSL_USB2_PORT1_ENABLED;
+
+		pdata->operating_mode = FSL_USB2_MPH_HOST;
+	} else {
+		if (of_get_property(np, "fsl,invert-drvvbus", NULL))
+			pdata->invert_drvvbus = 1;
+
+		if (of_get_property(np, "fsl,invert-pwr-fault", NULL))
+			pdata->invert_pwr_fault = 1;
+
+		/* setup mode selected in the device tree */
+		pdata->operating_mode = dev_data->op_mode;
+	}
+
+	prop = of_get_property(np, "phy_type", NULL);
+	pdata->phy_mode = determine_usb_phy(prop);
+
+	for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) {
+		if (!dev_data->drivers[i])
+			continue;
+		usb_dev = fsl_usb2_device_register(ofdev, pdata,
+					dev_data->drivers[i], idx);
+		if (IS_ERR(usb_dev)) {
+			dev_err(&ofdev->dev, "Can't register usb device\n");
+			return PTR_ERR(usb_dev);
+		}
+	}
+	idx++;
+	return 0;
+}
+
+static int __devexit __unregister_subdev(struct device *dev, void *d)
+{
+	platform_device_unregister(to_platform_device(dev));
+	return 0;
+}
+
+static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
+{
+	device_for_each_child(&ofdev->dev, NULL, __unregister_subdev);
+	return 0;
+}
+
+#ifdef CONFIG_PPC_MPC512x
+
+#define USBGENCTRL		0x200		/* NOTE: big endian */
+#define GC_WU_INT_CLR		(1 << 5)	/* Wakeup int clear */
+#define GC_ULPI_SEL		(1 << 4)	/* ULPI i/f select (usb0 only)*/
+#define GC_PPP			(1 << 3)	/* Inv. Port Power Polarity */
+#define GC_PFP			(1 << 2)	/* Inv. Power Fault Polarity */
+#define GC_WU_ULPI_EN		(1 << 1)	/* Wakeup on ULPI event */
+#define GC_WU_IE		(1 << 1)	/* Wakeup interrupt enable */
+
+#define ISIPHYCTRL		0x204		/* NOTE: big endian */
+#define PHYCTRL_PHYE		(1 << 4)	/* On-chip UTMI PHY enable */
+#define PHYCTRL_BSENH		(1 << 3)	/* Bit Stuff Enable High */
+#define PHYCTRL_BSEN		(1 << 2)	/* Bit Stuff Enable */
+#define PHYCTRL_LSFE		(1 << 1)	/* Line State Filter Enable */
+#define PHYCTRL_PXE		(1 << 0)	/* PHY oscillator enable */
+
+int fsl_usb2_mpc5121_init(struct platform_device *pdev)
+{
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct clk *clk;
+	char clk_name[10];
+	int base, clk_num;
+
+	base = pdev->resource->start & 0xf000;
+	if (base == 0x3000)
+		clk_num = 1;
+	else if (base == 0x4000)
+		clk_num = 2;
+	else
+		return -ENODEV;
+
+	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
+	clk = clk_get(&pdev->dev, clk_name);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clk\n");
+		return PTR_ERR(clk);
+	}
+
+	clk_enable(clk);
+	pdata->clk = clk;
+
+	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
+		u32 reg = 0;
+
+		if (pdata->invert_drvvbus)
+			reg |= GC_PPP;
+
+		if (pdata->invert_pwr_fault)
+			reg |= GC_PFP;
+
+		out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_PHYE | PHYCTRL_PXE);
+		out_be32(pdata->regs + USBGENCTRL, reg);
+	}
+	return 0;
+}
+
+static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
+{
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
+	pdata->regs = NULL;
+
+	if (pdata->clk) {
+		clk_disable(pdata->clk);
+		clk_put(pdata->clk);
+	}
+}
+
+struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = {
+	.big_endian_desc = 1,
+	.big_endian_mmio = 1,
+	.es = 1,
+	.le_setup_buf = 1,
+	.init = fsl_usb2_mpc5121_init,
+	.exit = fsl_usb2_mpc5121_exit,
+};
+#endif /* CONFIG_PPC_MPC512x */
+
+static const struct of_device_id fsl_usb2_mph_dr_of_match[] = {
+	{ .compatible = "fsl-usb2-mph", },
+	{ .compatible = "fsl-usb2-dr", },
+#ifdef CONFIG_PPC_MPC512x
+	{ .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, },
+#endif
+	{},
+};
+
+static struct platform_driver fsl_usb2_mph_dr_driver = {
+	.driver = {
+		.name = "fsl-usb2-mph-dr",
+		.owner = THIS_MODULE,
+		.of_match_table = fsl_usb2_mph_dr_of_match,
+	},
+	.probe	= fsl_usb2_mph_dr_of_probe,
+	.remove	= __devexit_p(fsl_usb2_mph_dr_of_remove),
+};
+
+static int __init fsl_usb2_mph_dr_init(void)
+{
+	return platform_driver_register(&fsl_usb2_mph_dr_driver);
+}
+module_init(fsl_usb2_mph_dr_init);
+
+static void __exit fsl_usb2_mph_dr_exit(void)
+{
+	platform_driver_unregister(&fsl_usb2_mph_dr_driver);
+}
+module_exit(fsl_usb2_mph_dr_exit);
+
+MODULE_DESCRIPTION("FSL MPH DR OF devices driver");
+MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index 3e56303..1dfb2c8 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -57,6 +57,7 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
+#include <linux/dma-mapping.h>
 
 #include "imx21-hcd.h"
 
@@ -136,9 +137,18 @@
 	return wrap_frame(readl(imx21->regs + USBH_FRMNUB));
 }
 
+static inline bool unsuitable_for_dma(dma_addr_t addr)
+{
+	return (addr & 3) != 0;
+}
 
 #include "imx21-dbg.c"
 
+static void nonisoc_urb_completed_for_etd(
+	struct imx21 *imx21, struct etd_priv *etd, int status);
+static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb);
+static void free_dmem(struct imx21 *imx21, struct etd_priv *etd);
+
 /* =========================================== */
 /* ETD management				*/
 /* ===========================================	*/
@@ -185,7 +195,8 @@
 		etd_writel(imx21, num, i, 0);
 	etd->urb = NULL;
 	etd->ep = NULL;
-	etd->td = NULL;;
+	etd->td = NULL;
+	etd->bounce_buffer = NULL;
 }
 
 static void free_etd(struct imx21 *imx21, int num)
@@ -221,26 +232,94 @@
 		((u32) maxpacket << DW0_MAXPKTSIZ));
 }
 
-static void activate_etd(struct imx21 *imx21,
-	int etd_num, dma_addr_t dma, u8 dir)
+/**
+ * Copy buffer to data controller data memory.
+ * We cannot use memcpy_toio() because the hardware requires 32bit writes
+ */
+static void copy_to_dmem(
+	struct imx21 *imx21, int dmem_offset, void *src, int count)
+{
+	void __iomem *dmem = imx21->regs + USBOTG_DMEM + dmem_offset;
+	u32 word = 0;
+	u8 *p = src;
+	int byte = 0;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		byte = i % 4;
+		word += (*p++ << (byte * 8));
+		if (byte == 3) {
+			writel(word, dmem);
+			dmem += 4;
+			word = 0;
+		}
+	}
+
+	if (count && byte != 3)
+		writel(word, dmem);
+}
+
+static void activate_etd(struct imx21 *imx21, int etd_num, u8 dir)
 {
 	u32 etd_mask = 1 << etd_num;
 	struct etd_priv *etd = &imx21->etd[etd_num];
 
+	if (etd->dma_handle && unsuitable_for_dma(etd->dma_handle)) {
+		/* For non aligned isoc the condition below is always true */
+		if (etd->len <= etd->dmem_size) {
+			/* Fits into data memory, use PIO */
+			if (dir != TD_DIR_IN) {
+				copy_to_dmem(imx21,
+						etd->dmem_offset,
+						etd->cpu_buffer, etd->len);
+			}
+			etd->dma_handle = 0;
+
+		} else {
+			/* Too big for data memory, use bounce buffer */
+			enum dma_data_direction dmadir;
+
+			if (dir == TD_DIR_IN) {
+				dmadir = DMA_FROM_DEVICE;
+				etd->bounce_buffer = kmalloc(etd->len,
+								GFP_ATOMIC);
+			} else {
+				dmadir = DMA_TO_DEVICE;
+				etd->bounce_buffer = kmemdup(etd->cpu_buffer,
+								etd->len,
+								GFP_ATOMIC);
+			}
+			if (!etd->bounce_buffer) {
+				dev_err(imx21->dev, "failed bounce alloc\n");
+				goto err_bounce_alloc;
+			}
+
+			etd->dma_handle =
+				dma_map_single(imx21->dev,
+						etd->bounce_buffer,
+						etd->len,
+						dmadir);
+			if (dma_mapping_error(imx21->dev, etd->dma_handle)) {
+				dev_err(imx21->dev, "failed bounce map\n");
+				goto err_bounce_map;
+			}
+		}
+	}
+
 	clear_toggle_bit(imx21, USBH_ETDDONESTAT, etd_mask);
 	set_register_bits(imx21, USBH_ETDDONEEN, etd_mask);
 	clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
 	clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
 
-	if (dma) {
+	if (etd->dma_handle) {
 		set_register_bits(imx21, USB_ETDDMACHANLCLR, etd_mask);
 		clear_toggle_bit(imx21, USBH_XBUFSTAT, etd_mask);
 		clear_toggle_bit(imx21, USBH_YBUFSTAT, etd_mask);
-		writel(dma, imx21->regs + USB_ETDSMSA(etd_num));
+		writel(etd->dma_handle, imx21->regs + USB_ETDSMSA(etd_num));
 		set_register_bits(imx21, USB_ETDDMAEN, etd_mask);
 	} else {
 		if (dir != TD_DIR_IN) {
-			/* need to set for ZLP */
+			/* need to set for ZLP and PIO */
 			set_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
 			set_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
 		}
@@ -263,6 +342,14 @@
 
 	etd->active_count = 1;
 	writel(etd_mask, imx21->regs + USBH_ETDENSET);
+	return;
+
+err_bounce_map:
+	kfree(etd->bounce_buffer);
+
+err_bounce_alloc:
+	free_dmem(imx21, etd);
+	nonisoc_urb_completed_for_etd(imx21, etd, -ENOMEM);
 }
 
 /* ===========================================	*/
@@ -323,16 +410,23 @@
 	etd_writel(imx21, etd_num, 1,
 	    ((dmem_offset + maxpacket) << DW1_YBUFSRTAD) | dmem_offset);
 
+	etd->dmem_offset = dmem_offset;
 	urb_priv->active = 1;
-	activate_etd(imx21, etd_num, etd->dma_handle, dir);
+	activate_etd(imx21, etd_num, dir);
 }
 
-static void free_dmem(struct imx21 *imx21, int offset)
+static void free_dmem(struct imx21 *imx21, struct etd_priv *etd)
 {
 	struct imx21_dmem_area *area;
-	struct etd_priv *etd, *tmp;
+	struct etd_priv *tmp;
 	int found = 0;
+	int offset;
 
+	if (!etd->dmem_size)
+		return;
+	etd->dmem_size = 0;
+
+	offset = etd->dmem_offset;
 	list_for_each_entry(area, &imx21->dmem_list, list) {
 		if (area->offset == offset) {
 			debug_dmem_freed(imx21, area->size);
@@ -378,20 +472,23 @@
 /* ===========================================	*/
 /* End handling 				*/
 /* ===========================================	*/
-static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb);
 
 /* Endpoint now idle - release it's ETD(s) or asssign to queued request */
 static void ep_idle(struct imx21 *imx21, struct ep_priv *ep_priv)
 {
-	int etd_num;
 	int i;
 
 	for (i = 0; i < NUM_ISO_ETDS; i++) {
-		etd_num = ep_priv->etd[i];
+		int etd_num = ep_priv->etd[i];
+		struct etd_priv *etd;
 		if (etd_num < 0)
 			continue;
 
+		etd = &imx21->etd[etd_num];
 		ep_priv->etd[i] = -1;
+
+		free_dmem(imx21, etd); /* for isoc */
+
 		if (list_empty(&imx21->queue_for_etd)) {
 			free_etd(imx21, etd_num);
 			continue;
@@ -437,6 +534,24 @@
 		ep_idle(imx21, ep_priv);
 }
 
+static void nonisoc_urb_completed_for_etd(
+	struct imx21 *imx21, struct etd_priv *etd, int status)
+{
+	struct usb_host_endpoint *ep = etd->ep;
+
+	urb_done(imx21->hcd, etd->urb, status);
+	etd->urb = NULL;
+
+	if (!list_empty(&ep->urb_list)) {
+		struct urb *urb = list_first_entry(
+					&ep->urb_list, struct urb, urb_list);
+
+		dev_vdbg(imx21->dev, "next URB %p\n", urb);
+		schedule_nonisoc_etd(imx21, urb);
+	}
+}
+
+
 /* ===========================================	*/
 /* ISOC Handling ... 				*/
 /* ===========================================	*/
@@ -489,6 +604,8 @@
 		etd->ep = td->ep;
 		etd->urb = td->urb;
 		etd->len = td->len;
+		etd->dma_handle = td->dma_handle;
+		etd->cpu_buffer = td->cpu_buffer;
 
 		debug_isoc_submitted(imx21, cur_frame, td);
 
@@ -502,16 +619,17 @@
 			(TD_NOTACCESSED << DW3_COMPCODE0) |
 			(td->len << DW3_PKTLEN0));
 
-		activate_etd(imx21, etd_num, td->data, dir);
+		activate_etd(imx21, etd_num, dir);
 	}
 }
 
-static void isoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
+static void isoc_etd_done(struct usb_hcd *hcd, int etd_num)
 {
 	struct imx21 *imx21 = hcd_to_imx21(hcd);
 	int etd_mask = 1 << etd_num;
-	struct urb_priv *urb_priv = urb->hcpriv;
 	struct etd_priv *etd = imx21->etd + etd_num;
+	struct urb *urb = etd->urb;
+	struct urb_priv *urb_priv = urb->hcpriv;
 	struct td *td = etd->td;
 	struct usb_host_endpoint *ep = etd->ep;
 	int isoc_index = td->isoc_index;
@@ -545,8 +663,13 @@
 			bytes_xfrd, td->len, urb, etd_num, isoc_index);
 	}
 
-	if (dir_in)
+	if (dir_in) {
 		clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
+		if (!etd->dma_handle)
+			memcpy_fromio(etd->cpu_buffer,
+				imx21->regs + USBOTG_DMEM + etd->dmem_offset,
+				bytes_xfrd);
+	}
 
 	urb->actual_length += bytes_xfrd;
 	urb->iso_frame_desc[isoc_index].actual_length = bytes_xfrd;
@@ -569,30 +692,43 @@
 	int i;
 
 	ep_priv = kzalloc(sizeof(struct ep_priv), GFP_ATOMIC);
-	if (ep_priv == NULL)
+	if (!ep_priv)
 		return NULL;
 
-	/* Allocate the ETDs */
-	for (i = 0; i < NUM_ISO_ETDS; i++) {
-		ep_priv->etd[i] = alloc_etd(imx21);
-		if (ep_priv->etd[i] < 0) {
-			int j;
-			dev_err(imx21->dev, "isoc: Couldn't allocate etd\n");
-			for (j = 0; j < i; j++)
-				free_etd(imx21, ep_priv->etd[j]);
-			goto alloc_etd_failed;
-		}
-		imx21->etd[ep_priv->etd[i]].ep = ep;
-	}
+	for (i = 0; i < NUM_ISO_ETDS; i++)
+		ep_priv->etd[i] = -1;
 
 	INIT_LIST_HEAD(&ep_priv->td_list);
 	ep_priv->ep = ep;
 	ep->hcpriv = ep_priv;
 	return ep_priv;
+}
+
+static int alloc_isoc_etds(struct imx21 *imx21, struct ep_priv *ep_priv)
+{
+	int i, j;
+	int etd_num;
+
+	/* Allocate the ETDs if required */
+	for (i = 0; i < NUM_ISO_ETDS; i++) {
+		if (ep_priv->etd[i] < 0) {
+			etd_num = alloc_etd(imx21);
+			if (etd_num < 0)
+				goto alloc_etd_failed;
+
+			ep_priv->etd[i] = etd_num;
+			imx21->etd[etd_num].ep = ep_priv->ep;
+		}
+	}
+	return 0;
 
 alloc_etd_failed:
-	kfree(ep_priv);
-	return NULL;
+	dev_err(imx21->dev, "isoc: Couldn't allocate etd\n");
+	for (j = 0; j < i; j++) {
+		free_etd(imx21, ep_priv->etd[j]);
+		ep_priv->etd[j] = -1;
+	}
+	return -ENOMEM;
 }
 
 static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
@@ -632,6 +768,10 @@
 		ep_priv = ep->hcpriv;
 	}
 
+	ret = alloc_isoc_etds(imx21, ep_priv);
+	if (ret)
+		goto alloc_etd_failed;
+
 	ret = usb_hcd_link_urb_to_ep(hcd, urb);
 	if (ret)
 		goto link_failed;
@@ -688,12 +828,14 @@
 	/* set up transfers */
 	td = urb_priv->isoc_td;
 	for (i = 0; i < urb->number_of_packets; i++, td++) {
+		unsigned int offset = urb->iso_frame_desc[i].offset;
 		td->ep = ep;
 		td->urb = urb;
 		td->len = urb->iso_frame_desc[i].length;
 		td->isoc_index = i;
 		td->frame = wrap_frame(urb->start_frame + urb->interval * i);
-		td->data = urb->transfer_dma + urb->iso_frame_desc[i].offset;
+		td->dma_handle = urb->transfer_dma + offset;
+		td->cpu_buffer = urb->transfer_buffer + offset;
 		list_add_tail(&td->list, &ep_priv->td_list);
 	}
 
@@ -711,6 +853,7 @@
 	usb_hcd_unlink_urb_from_ep(hcd, urb);
 
 link_failed:
+alloc_etd_failed:
 alloc_ep_failed:
 	spin_unlock_irqrestore(&imx21->lock, flags);
 	kfree(urb_priv->isoc_td);
@@ -734,9 +877,7 @@
 				struct etd_priv *etd = imx21->etd + etd_num;
 
 				reset_etd(imx21, etd_num);
-				if (etd->dmem_size)
-					free_dmem(imx21, etd->dmem_offset);
-				etd->dmem_size = 0;
+				free_dmem(imx21, etd);
 			}
 		}
 	}
@@ -761,7 +902,6 @@
 	int state = urb_priv->state;
 	int etd_num = ep_priv->etd[0];
 	struct etd_priv *etd;
-	int dmem_offset;
 	u32 count;
 	u16 etd_buf_size;
 	u16 maxpacket;
@@ -786,13 +926,15 @@
 	if (usb_pipecontrol(pipe) && (state != US_CTRL_DATA)) {
 		if (state == US_CTRL_SETUP) {
 			dir = TD_DIR_SETUP;
+			if (unsuitable_for_dma(urb->setup_dma))
+				unmap_urb_setup_for_dma(imx21->hcd, urb);
 			etd->dma_handle = urb->setup_dma;
+			etd->cpu_buffer = urb->setup_packet;
 			bufround = 0;
 			count = 8;
 			datatoggle = TD_TOGGLE_DATA0;
 		} else {	/* US_CTRL_ACK */
 			dir = usb_pipeout(pipe) ? TD_DIR_IN : TD_DIR_OUT;
-			etd->dma_handle = urb->transfer_dma;
 			bufround = 0;
 			count = 0;
 			datatoggle = TD_TOGGLE_DATA1;
@@ -800,7 +942,11 @@
 	} else {
 		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);
+
 		etd->dma_handle = urb->transfer_dma;
+		etd->cpu_buffer = urb->transfer_buffer;
 		if (usb_pipebulk(pipe) && (state == US_BULK0))
 			count = 0;
 		else
@@ -855,8 +1001,8 @@
 
 	/* allocate x and y buffer space at once */
 	etd->dmem_size = (count > maxpacket) ? maxpacket * 2 : maxpacket;
-	dmem_offset = alloc_dmem(imx21, etd->dmem_size, urb_priv->ep);
-	if (dmem_offset < 0) {
+	etd->dmem_offset = alloc_dmem(imx21, etd->dmem_size, urb_priv->ep);
+	if (etd->dmem_offset < 0) {
 		/* Setup everything we can in HW and update when we get DMEM */
 		etd_writel(imx21, etd_num, 1, (u32)maxpacket << 16);
 
@@ -867,26 +1013,26 @@
 	}
 
 	etd_writel(imx21, etd_num, 1,
-		(((u32) dmem_offset + (u32) maxpacket) << DW1_YBUFSRTAD) |
-		(u32) dmem_offset);
+		(((u32) etd->dmem_offset + (u32) maxpacket) << DW1_YBUFSRTAD) |
+		(u32) etd->dmem_offset);
 
 	urb_priv->active = 1;
 
 	/* enable the ETD to kick off transfer */
 	dev_vdbg(imx21->dev, "Activating etd %d for %d bytes %s\n",
 		etd_num, count, dir != TD_DIR_IN ? "out" : "in");
-	activate_etd(imx21, etd_num, etd->dma_handle, dir);
+	activate_etd(imx21, etd_num, dir);
 
 }
 
-static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
+static void nonisoc_etd_done(struct usb_hcd *hcd, int etd_num)
 {
 	struct imx21 *imx21 = hcd_to_imx21(hcd);
 	struct etd_priv *etd = &imx21->etd[etd_num];
+	struct urb *urb = etd->urb;
 	u32 etd_mask = 1 << etd_num;
 	struct urb_priv *urb_priv = urb->hcpriv;
 	int dir;
-	u16 xbufaddr;
 	int cc;
 	u32 bytes_xfrd;
 	int etd_done;
@@ -894,7 +1040,6 @@
 	disactivate_etd(imx21, etd_num);
 
 	dir = (etd_readl(imx21, etd_num, 0) >> DW0_DIRECT) & 0x3;
-	xbufaddr = etd_readl(imx21, etd_num, 1) & 0xffff;
 	cc = (etd_readl(imx21, etd_num, 2) >> DW2_COMPCODE) & 0xf;
 	bytes_xfrd = etd->len - (etd_readl(imx21, etd_num, 3) & 0x1fffff);
 
@@ -906,8 +1051,21 @@
 	if (dir == TD_DIR_IN) {
 		clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
 		clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
+
+		if (etd->bounce_buffer) {
+			memcpy(etd->cpu_buffer, etd->bounce_buffer, bytes_xfrd);
+			dma_unmap_single(imx21->dev,
+				etd->dma_handle, etd->len, DMA_FROM_DEVICE);
+		} else if (!etd->dma_handle && bytes_xfrd) {/* PIO */
+			memcpy_fromio(etd->cpu_buffer,
+				imx21->regs + USBOTG_DMEM + etd->dmem_offset,
+				bytes_xfrd);
+		}
 	}
-	free_dmem(imx21, xbufaddr);
+
+	kfree(etd->bounce_buffer);
+	etd->bounce_buffer = NULL;
+	free_dmem(imx21, etd);
 
 	urb->error_count = 0;
 	if (!(urb->transfer_flags & URB_SHORT_NOT_OK)
@@ -964,24 +1122,15 @@
 		break;
 	}
 
-	if (!etd_done) {
+	if (etd_done)
+		nonisoc_urb_completed_for_etd(imx21, etd, cc_to_error[cc]);
+	else {
 		dev_vdbg(imx21->dev, "next state=%d\n", urb_priv->state);
 		schedule_nonisoc_etd(imx21, urb);
-	} else {
-		struct usb_host_endpoint *ep = urb->ep;
-
-		urb_done(hcd, urb, cc_to_error[cc]);
-		etd->urb = NULL;
-
-		if (!list_empty(&ep->urb_list)) {
-			urb = list_first_entry(&ep->urb_list,
-				struct urb, urb_list);
-			dev_vdbg(imx21->dev, "next URB %p\n", urb);
-			schedule_nonisoc_etd(imx21, urb);
-		}
 	}
 }
 
+
 static struct ep_priv *alloc_ep(void)
 {
 	int i;
@@ -1007,7 +1156,6 @@
 	struct etd_priv *etd;
 	int ret;
 	unsigned long flags;
-	int new_ep = 0;
 
 	dev_vdbg(imx21->dev,
 		"enqueue urb=%p ep=%p len=%d "
@@ -1035,7 +1183,6 @@
 		}
 		ep->hcpriv = ep_priv;
 		ep_priv->ep = ep;
-		new_ep = 1;
 	}
 
 	ret = usb_hcd_link_urb_to_ep(hcd, urb);
@@ -1124,9 +1271,13 @@
 	} else if (urb_priv->active) {
 		int etd_num = ep_priv->etd[0];
 		if (etd_num != -1) {
+			struct etd_priv *etd = &imx21->etd[etd_num];
+
 			disactivate_etd(imx21, etd_num);
-			free_dmem(imx21, etd_readl(imx21, etd_num, 1) & 0xffff);
-			imx21->etd[etd_num].urb = NULL;
+			free_dmem(imx21, etd);
+			etd->urb = NULL;
+			kfree(etd->bounce_buffer);
+			etd->bounce_buffer = NULL;
 		}
 	}
 
@@ -1226,9 +1377,9 @@
 		}
 
 		if (usb_pipeisoc(etd->urb->pipe))
-			isoc_etd_done(hcd, etd->urb, etd_num);
+			isoc_etd_done(hcd, etd_num);
 		else
-			nonisoc_etd_done(hcd, etd->urb, etd_num);
+			nonisoc_etd_done(hcd, etd_num);
 	}
 
 	/* only enable SOF interrupt if it may be needed for the kludge */
@@ -1696,6 +1847,7 @@
 	}
 
 	imx21 = hcd_to_imx21(hcd);
+	imx21->hcd = hcd;
 	imx21->dev = &pdev->dev;
 	imx21->pdata = pdev->dev.platform_data;
 	if (!imx21->pdata)
@@ -1754,7 +1906,7 @@
 failed_clock_get:
 	iounmap(imx21->regs);
 failed_ioremap:
-	release_mem_region(res->start, res->end - res->start);
+	release_mem_region(res->start, resource_size(res));
 failed_request_mem:
 	remove_debug_files(imx21);
 	usb_put_hcd(hcd);
diff --git a/drivers/usb/host/imx21-hcd.h b/drivers/usb/host/imx21-hcd.h
index 1b0d913..87b29fd 100644
--- a/drivers/usb/host/imx21-hcd.h
+++ b/drivers/usb/host/imx21-hcd.h
@@ -250,6 +250,7 @@
 #define USBCTRL_USB_BYP			(1 << 2)
 #define USBCTRL_HOST1_TXEN_OE		(1 << 1)
 
+#define USBOTG_DMEM		0x1000
 
 /* Values in TD blocks */
 #define TD_DIR_SETUP	    0
@@ -346,8 +347,8 @@
 	struct list_head list;
 	struct urb *urb;
 	struct usb_host_endpoint *ep;
-	dma_addr_t data;
-	unsigned long buf_addr;
+	dma_addr_t dma_handle;
+	void *cpu_buffer;
 	int len;
 	int frame;
 	int isoc_index;
@@ -360,6 +361,8 @@
 	struct td *td;
 	struct list_head queue;
 	dma_addr_t dma_handle;
+	void *cpu_buffer;
+	void *bounce_buffer;
 	int alloc;
 	int len;
 	int dmem_size;
@@ -412,6 +415,7 @@
 struct imx21 {
 	spinlock_t lock;
 	struct device *dev;
+	struct usb_hcd *hcd;
 	struct mx21_usbh_platform_data *pdata;
 	struct list_head dmem_list;
 	struct list_head queue_for_etd; /* eps queued due to etd shortage */
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index d9e8212..0da7fc0 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1557,8 +1557,6 @@
 	return 0;
 }
 
-#define resource_len(r) (((r)->end - (r)->start) + 1)
-
 static int __devinit isp116x_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
@@ -1597,7 +1595,7 @@
 		ret = -EBUSY;
 		goto err1;
 	}
-	addr_reg = ioremap(addr->start, resource_len(addr));
+	addr_reg = ioremap(addr->start, resource_size(addr));
 	if (addr_reg == NULL) {
 		ret = -ENOMEM;
 		goto err2;
@@ -1606,7 +1604,7 @@
 		ret = -EBUSY;
 		goto err3;
 	}
-	data_reg = ioremap(data->start, resource_len(data));
+	data_reg = ioremap(data->start, resource_size(data));
 	if (data_reg == NULL) {
 		ret = -ENOMEM;
 		goto err4;
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 0587ad4..8196fa1 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -1676,13 +1676,6 @@
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
 			_DBG(0, "USB_PORT_FEAT_SUSPEND\n");
-#ifdef	CONFIG_USB_OTG
-			if (ohci->hcd.self.otg_port == (wIndex + 1) &&
-			    ohci->hcd.self.b_hnp_enable) {
-				start_hnp(ohci);
-				break;
-			}
-#endif
 			spin_lock_irqsave(&isp1362_hcd->lock, flags);
 			isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, RH_PS_PSS);
 			isp1362_hcd->rhport[wIndex] =
@@ -2656,8 +2649,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define resource_len(r) (((r)->end - (r)->start) + 1)
-
 static int __devexit isp1362_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -2679,12 +2670,12 @@
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	DBG(0, "%s: release mem_region: %08lx\n", __func__, (long unsigned int)res->start);
 	if (res)
-		release_mem_region(res->start, resource_len(res));
+		release_mem_region(res->start, resource_size(res));
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	DBG(0, "%s: release mem_region: %08lx\n", __func__, (long unsigned int)res->start);
 	if (res)
-		release_mem_region(res->start, resource_len(res));
+		release_mem_region(res->start, resource_size(res));
 
 	DBG(0, "%s: put_hcd\n", __func__);
 	usb_put_hcd(hcd);
@@ -2730,21 +2721,21 @@
 		goto err1;
 	}
 
-	if (!request_mem_region(addr->start, resource_len(addr), hcd_name)) {
+	if (!request_mem_region(addr->start, resource_size(addr), hcd_name)) {
 		retval = -EBUSY;
 		goto err1;
 	}
-	addr_reg = ioremap(addr->start, resource_len(addr));
+	addr_reg = ioremap(addr->start, resource_size(addr));
 	if (addr_reg == NULL) {
 		retval = -ENOMEM;
 		goto err2;
 	}
 
-	if (!request_mem_region(data->start, resource_len(data), hcd_name)) {
+	if (!request_mem_region(data->start, resource_size(data), hcd_name)) {
 		retval = -EBUSY;
 		goto err3;
 	}
-	data_reg = ioremap(data->start, resource_len(data));
+	data_reg = ioremap(data->start, resource_size(data));
 	if (data_reg == NULL) {
 		retval = -ENOMEM;
 		goto err4;
@@ -2802,13 +2793,13 @@
 	iounmap(data_reg);
  err4:
 	DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)data->start);
-	release_mem_region(data->start, resource_len(data));
+	release_mem_region(data->start, resource_size(data));
  err3:
 	DBG(0, "%s: Unmapping addr_reg @ %p\n", __func__, addr_reg);
 	iounmap(addr_reg);
  err2:
 	DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)addr->start);
-	release_mem_region(addr->start, resource_len(addr));
+	release_mem_region(addr->start, resource_size(addr));
  err1:
 	pr_err("%s: init error, %d\n", __func__, retval);
 
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 36abd2b..d7d3449 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -413,18 +413,21 @@
 	.open		= debug_async_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 static const struct file_operations debug_periodic_fops = {
 	.owner		= THIS_MODULE,
 	.open		= debug_periodic_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 static const struct file_operations debug_registers_fops = {
 	.owner		= THIS_MODULE,
 	.open		= debug_registers_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 
 static struct dentry *ohci_debug_root;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index c3b4ccc..3b57850 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -398,7 +398,14 @@
 
 	ohci = hcd_to_ohci (hcd);
 	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-	ohci_usb_reset (ohci);
+	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+
+	/* If the SHUTDOWN quirk is set, don't put the controller in RESET */
+	ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ?
+			OHCI_CTRL_RWC | OHCI_CTRL_HCFS :
+			OHCI_CTRL_RWC);
+	ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
+
 	/* flush the writes */
 	(void) ohci_readl (ohci, &ohci->regs->control);
 }
@@ -1270,6 +1277,9 @@
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
+#ifdef OMAP3_PLATFORM_DRIVER
+	platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
+#endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 6bdc8b2..36ee9a6 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -201,6 +201,20 @@
 	return 0;
 }
 
+/* nVidia controllers continue to drive Reset signalling on the bus
+ * even after system shutdown, wasting power.  This flag tells the
+ * shutdown routine to leave the controller OPERATIONAL instead of RESET.
+ */
+static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+
+	ohci->flags |= OHCI_QUIRK_SHUTDOWN;
+	ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
+
+	return 0;
+}
+
 /*
  * The hardware normally enables the A-link power management feature, which
  * lets the system lower the power consumption in idle states.
@@ -332,6 +346,10 @@
 		PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
 		.driver_data = (unsigned long)ohci_quirk_amd700,
 	},
+	{
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
+		.driver_data = (unsigned long) ohci_quirk_nvidia_shutdown,
+	},
 
 	/* FIXME for some of the early AMD 760 southbridges, OHCI
 	 * won't work at all.  blacklist them.
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 4181638..afef7b0 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <mach/ohci.h>
+#include <mach/pxa3xx-u2d.h>
 
 /*
  * UHC: USB Host Controller (OHCI-like) register definitions
@@ -235,6 +236,9 @@
 	if (retval < 0)
 		return retval;
 
+	if (cpu_is_pxa3xx())
+		pxa3xx_u2d_start_hc(&ohci_to_hcd(&ohci->ohci)->self);
+
 	uhchr = __raw_readl(ohci->mmio_base + UHCHR) & ~UHCHR_SSE;
 	__raw_writel(uhchr, ohci->mmio_base + UHCHR);
 	__raw_writel(UHCHIE_UPRIE | UHCHIE_RWIE, ohci->mmio_base + UHCHIE);
@@ -251,6 +255,9 @@
 
 	inf = dev->platform_data;
 
+	if (cpu_is_pxa3xx())
+		pxa3xx_u2d_stop_hc(&ohci_to_hcd(&ohci->ohci)->self);
+
 	if (inf->exit)
 		inf->exit(dev);
 
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
index 60f03cc..0b35d22 100644
--- a/drivers/usb/host/ohci-sh.c
+++ b/drivers/usb/host/ohci-sh.c
@@ -77,7 +77,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define resource_len(r) (((r)->end - (r)->start) + 1)
 static int ohci_hcd_sh_probe(struct platform_device *pdev)
 {
 	struct resource *res = NULL;
@@ -109,7 +108,7 @@
 
 	hcd->regs = (void __iomem *)res->start;
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_len(res);
+	hcd->rsrc_len = resource_size(res);
 	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
 	if (ret != 0) {
 		err("Failed to add hcd");
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index cff2363..041d30f30 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -168,7 +168,7 @@
 
 	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
 	if (retval)
-		goto err4;
+		goto err5;
 
 	/* enable power and unmask interrupts */
 
@@ -176,6 +176,8 @@
 	sm501_modify_reg(dev->parent, SM501_IRQ_MASK, 1 << 6, 0);
 
 	return 0;
+err5:
+	iounmap(hcd->regs);
 err4:
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err3:
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 5bf15fe..51facb9 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -403,6 +403,7 @@
 #define	OHCI_QUIRK_HUB_POWER	0x100			/* distrust firmware power/oc setup */
 #define	OHCI_QUIRK_AMD_ISO	0x200			/* ISO transfers*/
 #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
 
 	struct work_struct	nec_work;	/* Worker for NEC quirk */
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index d9c85a2..d32c3ea 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -3696,7 +3696,7 @@
 static int oxu_verify_id(struct platform_device *pdev, void *base)
 {
 	u32 id;
-	char *bo[] = {
+	static const char * const bo[] = {
 		"reserved",
 		"128-pin LQFP",
 		"84-pin TFBGA",
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 83b5f9c..464ed97 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -169,6 +169,7 @@
 static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
 {
 	void __iomem *base;
+	u32 control;
 
 	if (!mmio_resource_enabled(pdev, 0))
 		return;
@@ -177,10 +178,14 @@
 	if (base == NULL)
 		return;
 
+	control = readl(base + OHCI_CONTROL);
+
 /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
-#ifndef __hppa__
-{
-	u32 control = readl(base + OHCI_CONTROL);
+#ifdef __hppa__
+#define	OHCI_CTRL_MASK		(OHCI_CTRL_RWC | OHCI_CTRL_IR)
+#else
+#define	OHCI_CTRL_MASK		OHCI_CTRL_RWC
+
 	if (control & OHCI_CTRL_IR) {
 		int wait_time = 500; /* arbitrary; 5 seconds */
 		writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
@@ -194,13 +199,12 @@
 			dev_warn(&pdev->dev, "OHCI: BIOS handoff failed"
 					" (BIOS bug?) %08x\n",
 					readl(base + OHCI_CONTROL));
-
-		/* reset controller, preserving RWC */
-		writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
 	}
-}
 #endif
 
+	/* reset controller, preserving RWC (and possibly IR) */
+	writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
+
 	/*
 	 * disable interrupts
 	 */
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
index 95d0f5a..25563e9 100644
--- a/drivers/usb/host/r8a66597.h
+++ b/drivers/usb/host/r8a66597.h
@@ -227,7 +227,7 @@
 		int odd = len & 0x0001;
 
 		len = len / 2;
-		ioread16_rep(fifoaddr, buf, len);
+		iowrite16_rep(fifoaddr, buf, len);
 		if (unlikely(odd)) {
 			buf = &buf[len];
 			iowrite8((unsigned char)*buf, fifoaddr);
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 0e13a00..3775c03 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -20,7 +20,6 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -132,49 +131,12 @@
 	platform_device_unregister(&platform_dev);
 }
 
-static int sl811_cs_config_check(struct pcmcia_device *p_dev,
-				 cistpl_cftable_entry_t *cfg,
-				 cistpl_cftable_entry_t *dflt,
-				 unsigned int vcc,
-				 void *priv_data)
+static int sl811_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-		if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
-			return -ENODEV;
-	} else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-		if (dflt->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
-			return -ENODEV;
-		}
-
-	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
-			cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
-			dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-	/* we need an interrupt */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-
-		p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-
-		return pcmcia_request_io(p_dev);
-	}
-	pcmcia_disable_device(p_dev);
-	return -ENODEV;
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -185,6 +147,9 @@
 
 	dev_dbg(&link->dev, "sl811_cs_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ |	CONF_AUTO_SET_VPP |
+		CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO;
+
 	if (pcmcia_loop_config(link, sl811_cs_config_check, NULL))
 		goto failed;
 
@@ -195,18 +160,10 @@
 	if (!link->irq)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
-	dev_info(&link->dev, "index 0x%02x: ",
-		link->conf.ConfigIndex);
-	if (link->conf.Vpp)
-		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
-	printk(", irq %d", link->irq);
-	printk(", io %pR", link->resource[0]);
-	printk("\n");
-
 	if (sl811_hc_init(parent, link->resource[0]->start, link->irq)
 			< 0) {
 failed:
@@ -227,9 +184,6 @@
 	local->p_dev = link;
 	link->priv = local;
 
-	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	return sl811_cs_config(link);
 }
 
@@ -241,9 +195,7 @@
 
 static struct pcmcia_driver sl811_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "sl811_cs",
-	},
+	.name		= "sl811_cs",
 	.probe		= sl811_cs_probe,
 	.remove		= sl811_cs_detach,
 	.id_table	= sl811_ids,
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index d3ade40..2090b45 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -917,10 +917,13 @@
 	unsigned long destination, status;
 	int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
 	int len = urb->transfer_buffer_length;
-	dma_addr_t data = urb->transfer_dma;
+	int this_sg_len;
+	dma_addr_t data;
 	__le32 *plink;
 	struct urb_priv *urbp = urb->hcpriv;
 	unsigned int toggle;
+	struct scatterlist  *sg;
+	int i;
 
 	if (len < 0)
 		return -EINVAL;
@@ -937,12 +940,26 @@
 	if (usb_pipein(urb->pipe))
 		status |= TD_CTRL_SPD;
 
+	i = urb->num_sgs;
+	if (len > 0 && i > 0) {
+		sg = urb->sg;
+		data = sg_dma_address(sg);
+
+		/* urb->transfer_buffer_length may be smaller than the
+		 * size of the scatterlist (or vice versa)
+		 */
+		this_sg_len = min_t(int, sg_dma_len(sg), len);
+	} else {
+		sg = NULL;
+		data = urb->transfer_dma;
+		this_sg_len = len;
+	}
 	/*
 	 * Build the DATA TDs
 	 */
 	plink = NULL;
 	td = qh->dummy_td;
-	do {	/* Allow zero length packets */
+	for (;;) {	/* Allow zero length packets */
 		int pktsze = maxsze;
 
 		if (len <= pktsze) {		/* The last packet */
@@ -965,10 +982,18 @@
 		plink = &td->link;
 		status |= TD_CTRL_ACTIVE;
 
-		data += pktsze;
-		len -= maxsze;
 		toggle ^= 1;
-	} while (len > 0);
+		data += pktsze;
+		this_sg_len -= pktsze;
+		len -= maxsze;
+		if (this_sg_len <= 0) {
+			if (--i <= 0 || len <= 0)
+				break;
+			sg = sg_next(sg);
+			data = sg_dma_address(sg);
+			this_sg_len = min_t(int, sg_dma_len(sg), len);
+		}
+	}
 
 	/*
 	 * URB_ZERO_PACKET means adding a 0-length packet, if direction
diff --git a/drivers/usb/host/whci/Kbuild b/drivers/usb/host/whci/Kbuild
index 11e5040..26df013 100644
--- a/drivers/usb/host/whci/Kbuild
+++ b/drivers/usb/host/whci/Kbuild
@@ -3,7 +3,7 @@
 whci-hcd-y := \
 	asl.o	\
 	debug.o \
-	hcd.o 	\
+	hcd.o	\
 	hw.o	\
 	init.o	\
 	int.o	\
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index a1a7a97..fef5a1f 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -24,6 +24,10 @@
 
 #include "xhci.h"
 
+#define	PORT_WAKE_BITS	(PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E)
+#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)
 {
@@ -123,12 +127,105 @@
  * writing a 0 clears the bit and writing a 1 sets the bit (RWS).
  * For all other types (RW1S, RW1CS, RW, and RZ), writing a '0' has no effect.
  */
-static u32 xhci_port_state_to_neutral(u32 state)
+u32 xhci_port_state_to_neutral(u32 state)
 {
 	/* Save read-only status and port state */
 	return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS);
 }
 
+/*
+ * find slot id based on port number.
+ */
+int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port)
+{
+	int slot_id;
+	int i;
+
+	slot_id = 0;
+	for (i = 0; i < MAX_HC_SLOTS; i++) {
+		if (!xhci->devs[i])
+			continue;
+		if (xhci->devs[i]->port == port) {
+			slot_id = i;
+			break;
+		}
+	}
+
+	return slot_id;
+}
+
+/*
+ * Stop device
+ * It issues stop endpoint command for EP 0 to 30. And wait the last command
+ * to complete.
+ * suspend will set to 1, if suspend bit need to set in command.
+ */
+static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
+{
+	struct xhci_virt_device *virt_dev;
+	struct xhci_command *cmd;
+	unsigned long flags;
+	int timeleft;
+	int ret;
+	int i;
+
+	ret = 0;
+	virt_dev = xhci->devs[slot_id];
+	cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO);
+	if (!cmd) {
+		xhci_dbg(xhci, "Couldn't allocate command structure.\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_irqsave(&xhci->lock, flags);
+	for (i = LAST_EP_INDEX; i > 0; i--) {
+		if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
+			xhci_queue_stop_endpoint(xhci, slot_id, i, suspend);
+	}
+	cmd->command_trb = xhci->cmd_ring->enqueue;
+	list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
+	xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
+	xhci_ring_cmd_db(xhci);
+	spin_unlock_irqrestore(&xhci->lock, flags);
+
+	/* Wait for last stop endpoint command to finish */
+	timeleft = wait_for_completion_interruptible_timeout(
+			cmd->completion,
+			USB_CTRL_SET_TIMEOUT);
+	if (timeleft <= 0) {
+		xhci_warn(xhci, "%s while waiting for stop endpoint command\n",
+				timeleft == 0 ? "Timeout" : "Signal");
+		spin_lock_irqsave(&xhci->lock, flags);
+		/* The timeout might have raced with the event ring handler, so
+		 * only delete from the list if the item isn't poisoned.
+		 */
+		if (cmd->cmd_list.next != LIST_POISON1)
+			list_del(&cmd->cmd_list);
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		ret = -ETIME;
+		goto command_cleanup;
+	}
+
+command_cleanup:
+	xhci_free_command(xhci, cmd);
+	return ret;
+}
+
+/*
+ * Ring device, it rings the all doorbells unconditionally.
+ */
+void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
+{
+	int i;
+
+	for (i = 0; i < LAST_EP_INDEX + 1; i++)
+		if (xhci->devs[slot_id]->eps[i].ring &&
+		    xhci->devs[slot_id]->eps[i].ring->dequeue)
+			xhci_ring_ep_doorbell(xhci, slot_id, i, 0);
+
+	return;
+}
+
 static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex,
 		u32 __iomem *addr, u32 port_status)
 {
@@ -162,6 +259,10 @@
 		status = PORT_PEC;
 		port_change_bit = "enable/disable";
 		break;
+	case USB_PORT_FEAT_C_SUSPEND:
+		status = PORT_PLC;
+		port_change_bit = "suspend/resume";
+		break;
 	default:
 		/* Should never happen */
 		return;
@@ -179,9 +280,10 @@
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	int ports;
 	unsigned long flags;
-	u32 temp, status;
+	u32 temp, temp1, status;
 	int retval = 0;
 	u32 __iomem *addr;
+	int slot_id;
 
 	ports = HCS_MAX_PORTS(xhci->hcs_params1);
 
@@ -211,9 +313,49 @@
 		if ((temp & PORT_OCC))
 			status |= USB_PORT_STAT_C_OVERCURRENT << 16;
 		/*
-		 * FIXME ignoring suspend, reset, and USB 2.1/3.0 specific
+		 * FIXME ignoring reset and USB 2.1/3.0 specific
 		 * changes
 		 */
+		if ((temp & PORT_PLS_MASK) == XDEV_U3
+			&& (temp & PORT_POWER))
+			status |= 1 << USB_PORT_FEAT_SUSPEND;
+		if ((temp & PORT_PLS_MASK) == XDEV_RESUME) {
+			if ((temp & PORT_RESET) || !(temp & PORT_PE))
+				goto error;
+			if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies,
+						xhci->resume_done[wIndex])) {
+				xhci_dbg(xhci, "Resume USB2 port %d\n",
+					wIndex + 1);
+				xhci->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_dbg(xhci, "set port %d resume\n",
+					wIndex + 1);
+				slot_id = xhci_find_slot_id_by_port(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));
+			}
+		}
+		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);
+		}
 		if (temp & PORT_CONNECT) {
 			status |= USB_PORT_STAT_CONNECTION;
 			status |= xhci_port_speed(temp);
@@ -226,6 +368,8 @@
 			status |= USB_PORT_STAT_RESET;
 		if (temp & PORT_POWER)
 			status |= USB_PORT_STAT_POWER;
+		if (xhci->port_c_suspend[wIndex >> 5] & (1 << (wIndex & 31)))
+			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);
 		break;
@@ -238,6 +382,42 @@
 		temp = xhci_readl(xhci, addr);
 		temp = xhci_port_state_to_neutral(temp);
 		switch (wValue) {
+		case USB_PORT_FEAT_SUSPEND:
+			temp = xhci_readl(xhci, addr);
+			/* 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.
+			 */
+			if ((temp & PORT_PE) == 0 || (temp & PORT_RESET)
+				|| (temp & PORT_PLS_MASK) >= XDEV_U3) {
+				xhci_warn(xhci, "USB core suspending device "
+					  "not in U0/U1/U2.\n");
+				goto error;
+			}
+
+			slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
+			if (!slot_id) {
+				xhci_warn(xhci, "slot_id is zero\n");
+				goto error;
+			}
+			/* unlock to execute stop endpoint commands */
+			spin_unlock_irqrestore(&xhci->lock, flags);
+			xhci_stop_device(xhci, slot_id, 1);
+			spin_lock_irqsave(&xhci->lock, flags);
+
+			temp = xhci_port_state_to_neutral(temp);
+			temp &= ~PORT_PLS_MASK;
+			temp |= PORT_LINK_STROBE | XDEV_U3;
+			xhci_writel(xhci, temp, addr);
+
+			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));
+			break;
 		case USB_PORT_FEAT_POWER:
 			/*
 			 * Turn on ports, even if there isn't per-port switching.
@@ -271,6 +451,52 @@
 		temp = xhci_readl(xhci, addr);
 		temp = xhci_port_state_to_neutral(temp);
 		switch (wValue) {
+		case USB_PORT_FEAT_SUSPEND:
+			temp = xhci_readl(xhci, addr);
+			xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n");
+			xhci_dbg(xhci, "PORTSC %04x\n", temp);
+			if (temp & PORT_RESET)
+				goto error;
+			if (temp & XDEV_U3) {
+				if ((temp & PORT_PE) == 0)
+					goto error;
+				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_readl(xhci, addr);
+				} else {
+					temp = xhci_port_state_to_neutral(temp);
+					temp &= ~PORT_PLS_MASK;
+					temp |= PORT_LINK_STROBE | XDEV_RESUME;
+					xhci_writel(xhci, temp, addr);
+
+					spin_unlock_irqrestore(&xhci->lock,
+							       flags);
+					msleep(20);
+					spin_lock_irqsave(&xhci->lock, flags);
+
+					temp = xhci_readl(xhci, addr);
+					temp = xhci_port_state_to_neutral(temp);
+					temp &= ~PORT_PLS_MASK;
+					temp |= PORT_LINK_STROBE | XDEV_U0;
+					xhci_writel(xhci, temp, addr);
+				}
+				xhci->port_c_suspend[wIndex >> 5] |=
+						1 << (wIndex & 31);
+			}
+
+			slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
+			if (!slot_id) {
+				xhci_dbg(xhci, "slot_id is zero\n");
+				goto error;
+			}
+			xhci_ring_device(xhci, slot_id);
+			break;
+		case USB_PORT_FEAT_C_SUSPEND:
+			xhci->port_c_suspend[wIndex >> 5] &=
+					~(1 << (wIndex & 31));
 		case USB_PORT_FEAT_C_RESET:
 		case USB_PORT_FEAT_C_CONNECTION:
 		case USB_PORT_FEAT_C_OVER_CURRENT:
@@ -306,6 +532,7 @@
 {
 	unsigned long flags;
 	u32 temp, status;
+	u32 mask;
 	int i, retval;
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	int ports;
@@ -318,13 +545,18 @@
 	memset(buf, 0, retval);
 	status = 0;
 
+	mask = PORT_CSC | PORT_PEC | PORT_OCC;
+
 	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);
-		if (temp & (PORT_CSC | PORT_PEC | PORT_OCC)) {
+		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]))) {
 			buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
 			status = 1;
 		}
@@ -332,3 +564,182 @@
 	spin_unlock_irqrestore(&xhci->lock, flags);
 	return status ? retval : 0;
 }
+
+#ifdef CONFIG_PM
+
+int xhci_bus_suspend(struct usb_hcd *hcd)
+{
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	int port;
+	unsigned long flags;
+
+	xhci_dbg(xhci, "suspend root hub\n");
+
+	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) {
+				spin_unlock_irqrestore(&xhci->lock, flags);
+				xhci_dbg(xhci, "suspend failed because "
+						"port %d is resuming\n",
+						port + 1);
+				return -EBUSY;
+			}
+		}
+	}
+
+	port = HCS_MAX_PORTS(xhci->hcs_params1);
+	xhci->bus_suspended = 0;
+	while (port--) {
+		/* 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);
+		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);
+			if (slot_id) {
+				spin_unlock_irqrestore(&xhci->lock, flags);
+				xhci_stop_device(xhci, slot_id, 1);
+				spin_lock_irqsave(&xhci->lock, flags);
+			}
+			t2 &= ~PORT_PLS_MASK;
+			t2 |= PORT_LINK_STROBE | XDEV_U3;
+			set_bit(port, &xhci->bus_suspended);
+		}
+		if (hcd->self.root_hub->do_remote_wakeup) {
+			if (t1 & PORT_CONNECT) {
+				t2 |= PORT_WKOC_E | PORT_WKDISC_E;
+				t2 &= ~PORT_WKCONN_E;
+			} else {
+				t2 |= PORT_WKOC_E | PORT_WKCONN_E;
+				t2 &= ~PORT_WKDISC_E;
+			}
+		} else
+			t2 &= ~PORT_WAKE_BITS;
+
+		t1 = xhci_port_state_to_neutral(t1);
+		if (t1 != t2)
+			xhci_writel(xhci, t2, addr);
+
+		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);
+			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);
+	spin_unlock_irqrestore(&xhci->lock, flags);
+	return 0;
+}
+
+int xhci_bus_resume(struct usb_hcd *hcd)
+{
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	int port;
+	u32 temp;
+	unsigned long flags;
+
+	xhci_dbg(xhci, "resume root hub\n");
+
+	if (time_before(jiffies, xhci->next_statechange))
+		msleep(5);
+
+	spin_lock_irqsave(&xhci->lock, flags);
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	/* delay the irqs */
+	temp = xhci_readl(xhci, &xhci->op_regs->command);
+	temp &= ~CMD_EIE;
+	xhci_writel(xhci, temp, &xhci->op_regs->command);
+
+	port = HCS_MAX_PORTS(xhci->hcs_params1);
+	while (port--) {
+		/* 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);
+		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) &&
+		    (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);
+			} else {
+				temp = xhci_port_state_to_neutral(temp);
+				temp &= ~PORT_PLS_MASK;
+				temp |= PORT_LINK_STROBE | XDEV_RESUME;
+				xhci_writel(xhci, temp, addr);
+
+				spin_unlock_irqrestore(&xhci->lock, flags);
+				msleep(20);
+				spin_lock_irqsave(&xhci->lock, flags);
+
+				temp = xhci_readl(xhci, addr);
+				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 + 1);
+			if (slot_id)
+				xhci_ring_device(xhci, slot_id);
+		} else
+			xhci_writel(xhci, temp, addr);
+
+		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);
+			tmp = xhci_readl(xhci, addr);
+			tmp &= ~PORT_RWE;
+			xhci_writel(xhci, tmp, addr);
+		}
+	}
+
+	(void) xhci_readl(xhci, &xhci->op_regs->command);
+
+	xhci->next_statechange = jiffies + msecs_to_jiffies(5);
+	hcd->state = HC_STATE_RUNNING;
+	/* re-enable irqs */
+	temp = xhci_readl(xhci, &xhci->op_regs->command);
+	temp |= CMD_EIE;
+	xhci_writel(xhci, temp, &xhci->op_regs->command);
+	temp = xhci_readl(xhci, &xhci->op_regs->command);
+
+	spin_unlock_irqrestore(&xhci->lock, flags);
+	return 0;
+}
+
+#endif	/* CONFIG_PM */
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 4e51343..2027706 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -778,6 +778,7 @@
 
 	init_completion(&dev->cmd_completion);
 	INIT_LIST_HEAD(&dev->cmd_list);
+	dev->udev = udev;
 
 	/* Point to output device context in dcbaa. */
 	xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
@@ -866,6 +867,7 @@
 			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);
 
 	/* Is this a LS/FS device under a HS hub? */
@@ -1443,6 +1445,7 @@
 	scratchpad_free(xhci);
 	xhci->page_size = 0;
 	xhci->page_shift = 0;
+	xhci->bus_suspended = 0;
 }
 
 static int xhci_test_trb_in_td(struct xhci_hcd *xhci,
@@ -1801,6 +1804,8 @@
 	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;
 
 	if (scratchpad_alloc(xhci, flags))
 		goto fail;
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index f7efe02..bb668a8 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -116,6 +116,30 @@
 	return xhci_pci_reinit(xhci, pdev);
 }
 
+#ifdef CONFIG_PM
+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)
+		return -EINVAL;
+
+	retval = xhci_suspend(xhci);
+
+	return retval;
+}
+
+static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+{
+	struct xhci_hcd		*xhci = hcd_to_xhci(hcd);
+	int			retval = 0;
+
+	retval = xhci_resume(xhci, hibernated);
+	return retval;
+}
+#endif /* CONFIG_PM */
+
 static const struct hc_driver xhci_pci_hc_driver = {
 	.description =		hcd_name,
 	.product_desc =		"xHCI Host Controller",
@@ -132,7 +156,10 @@
 	 */
 	.reset =		xhci_pci_setup,
 	.start =		xhci_run,
-	/* suspend and resume implemented later */
+#ifdef CONFIG_PM
+	.pci_suspend =          xhci_pci_suspend,
+	.pci_resume =           xhci_pci_resume,
+#endif
 	.stop =			xhci_stop,
 	.shutdown =		xhci_shutdown,
 
@@ -152,7 +179,7 @@
 	.reset_bandwidth =	xhci_reset_bandwidth,
 	.address_device =	xhci_address_device,
 	.update_hub_device =	xhci_update_hub_device,
-	.reset_device =		xhci_reset_device,
+	.reset_device =		xhci_discover_or_reset_device,
 
 	/*
 	 * scheduling support
@@ -162,6 +189,8 @@
 	/* Root hub support */
 	.hub_control =		xhci_hub_control,
 	.hub_status_data =	xhci_hub_status_data,
+	.bus_suspend =		xhci_bus_suspend,
+	.bus_resume =		xhci_bus_resume,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -186,6 +215,11 @@
 	/* suspend and resume implemented later */
 
 	.shutdown = 	usb_hcd_pci_shutdown,
+#ifdef CONFIG_PM_SLEEP
+	.driver = {
+		.pm = &usb_hcd_pci_pm_ops
+	},
+#endif
 };
 
 int xhci_register_pci(void)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 48e60d1..9f3115e 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -68,6 +68,10 @@
 #include <linux/slab.h>
 #include "xhci.h"
 
+static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
+		struct xhci_virt_device *virt_dev,
+		struct xhci_event_cmd *event);
+
 /*
  * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA
  * address of the TRB.
@@ -313,7 +317,7 @@
 	xhci_readl(xhci, &xhci->dba->doorbell[0]);
 }
 
-static void ring_ep_doorbell(struct xhci_hcd *xhci,
+void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
 		unsigned int slot_id,
 		unsigned int ep_index,
 		unsigned int stream_id)
@@ -353,7 +357,7 @@
 	/* A ring has pending URBs if its TD list is not empty */
 	if (!(ep->ep_state & EP_HAS_STREAMS)) {
 		if (!(list_empty(&ep->ring->td_list)))
-			ring_ep_doorbell(xhci, slot_id, ep_index, 0);
+			xhci_ring_ep_doorbell(xhci, slot_id, ep_index, 0);
 		return;
 	}
 
@@ -361,7 +365,8 @@
 			stream_id++) {
 		struct xhci_stream_info *stream_info = ep->stream_info;
 		if (!list_empty(&stream_info->stream_rings[stream_id]->td_list))
-			ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
+			xhci_ring_ep_doorbell(xhci, slot_id, ep_index,
+						stream_id);
 	}
 }
 
@@ -626,10 +631,11 @@
  *     bit cleared) so that the HW will skip over them.
  */
 static void handle_stopped_endpoint(struct xhci_hcd *xhci,
-		union xhci_trb *trb)
+		union xhci_trb *trb, struct xhci_event_cmd *event)
 {
 	unsigned int slot_id;
 	unsigned int ep_index;
+	struct xhci_virt_device *virt_dev;
 	struct xhci_ring *ep_ring;
 	struct xhci_virt_ep *ep;
 	struct list_head *entry;
@@ -638,6 +644,21 @@
 
 	struct xhci_dequeue_state deq_state;
 
+	if (unlikely(TRB_TO_SUSPEND_PORT(
+			xhci->cmd_ring->dequeue->generic.field[3]))) {
+		slot_id = TRB_TO_SLOT_ID(
+			xhci->cmd_ring->dequeue->generic.field[3]);
+		virt_dev = xhci->devs[slot_id];
+		if (virt_dev)
+			handle_cmd_in_cmd_wait_list(xhci, virt_dev,
+				event);
+		else
+			xhci_warn(xhci, "Stop endpoint command "
+				"completion for disabled slot %u\n",
+				slot_id);
+		return;
+	}
+
 	memset(&deq_state, 0, sizeof(deq_state));
 	slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
 	ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
@@ -1091,7 +1112,7 @@
 		complete(&xhci->addr_dev);
 		break;
 	case TRB_TYPE(TRB_STOP_RING):
-		handle_stopped_endpoint(xhci, xhci->cmd_ring->dequeue);
+		handle_stopped_endpoint(xhci, xhci->cmd_ring->dequeue, event);
 		break;
 	case TRB_TYPE(TRB_SET_DEQ):
 		handle_set_deq_completion(xhci, event, xhci->cmd_ring->dequeue);
@@ -1144,17 +1165,72 @@
 static void handle_port_status(struct xhci_hcd *xhci,
 		union xhci_trb *event)
 {
+	struct usb_hcd *hcd = xhci_to_hcd(xhci);
 	u32 port_id;
+	u32 temp, temp1;
+	u32 __iomem *addr;
+	int ports;
+	int slot_id;
 
 	/* Port status change events always have a successful completion code */
 	if (GET_COMP_CODE(event->generic.field[2]) != COMP_SUCCESS) {
 		xhci_warn(xhci, "WARN: xHC returned failed port status event\n");
 		xhci->error_bitmask |= 1 << 8;
 	}
-	/* FIXME: core doesn't care about all port link state changes yet */
 	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)) {
+		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);
+	if ((temp & PORT_CONNECT) && (hcd->state == HC_STATE_SUSPENDED)) {
+		xhci_dbg(xhci, "resume root hub\n");
+		usb_hcd_resume_root_hub(hcd);
+	}
+
+	if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) {
+		xhci_dbg(xhci, "port resume event for port %d\n", port_id);
+
+		temp1 = xhci_readl(xhci, &xhci->op_regs->command);
+		if (!(temp1 & CMD_RUN)) {
+			xhci_warn(xhci, "xHC is not running.\n");
+			goto cleanup;
+		}
+
+		if (DEV_SUPERSPEED(temp)) {
+			xhci_dbg(xhci, "resume SS port %d\n", port_id);
+			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);
+			if (!slot_id) {
+				xhci_dbg(xhci, "slot_id is zero\n");
+				goto cleanup;
+			}
+			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_port_state_to_neutral(temp);
+			temp |= PORT_PLC;
+			xhci_writel(xhci, temp, addr);
+		} else {
+			xhci_dbg(xhci, "resume HS port %d\n", port_id);
+			xhci->resume_done[port_id - 1] = jiffies +
+				msecs_to_jiffies(20);
+			mod_timer(&hcd->rh_timer,
+				  xhci->resume_done[port_id - 1]);
+			/* Do the rest in GetPortStatus */
+		}
+	}
+
+cleanup:
 	/* Update event ring dequeue pointer before dropping the lock */
 	inc_deq(xhci, xhci->event_ring, true);
 
@@ -2347,7 +2423,7 @@
 	 */
 	wmb();
 	start_trb->field[3] |= start_cycle;
-	ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
+	xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
 }
 
 /*
@@ -2931,7 +3007,7 @@
 	wmb();
 	start_trb->field[3] |= start_cycle;
 
-	ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id);
+	xhci_ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id);
 	return 0;
 }
 
@@ -3108,15 +3184,20 @@
 			false);
 }
 
+/*
+ * Suspend is set to indicate "Stop Endpoint Command" is being issued to stop
+ * activity on an endpoint that is about to be suspended.
+ */
 int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
-		unsigned int ep_index)
+		unsigned int ep_index, int suspend)
 {
 	u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
 	u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
 	u32 type = TRB_TYPE(TRB_STOP_RING);
+	u32 trb_suspend = SUSPEND_PORT_FOR_TRB(suspend);
 
 	return queue_command(xhci, 0, 0, 0,
-			trb_slot_id | trb_ep_index | type, false);
+			trb_slot_id | trb_ep_index | type | trb_suspend, false);
 }
 
 /* Set Transfer Ring Dequeue Pointer command.
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index d5c550e..5d7d4e9 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -551,6 +551,218 @@
 		    xhci_readl(xhci, &xhci->op_regs->status));
 }
 
+#ifdef CONFIG_PM
+static void xhci_save_registers(struct xhci_hcd *xhci)
+{
+	xhci->s3.command = xhci_readl(xhci, &xhci->op_regs->command);
+	xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification);
+	xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
+	xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg);
+	xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+	xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
+	xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size);
+	xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);
+	xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+}
+
+static void xhci_restore_registers(struct xhci_hcd *xhci)
+{
+	xhci_writel(xhci, xhci->s3.command, &xhci->op_regs->command);
+	xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
+	xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
+	xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg);
+	xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
+	xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
+	xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size);
+	xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
+}
+
+/*
+ * Stop HC (not bus-specific)
+ *
+ * This is called when the machine transition into S3/S4 mode.
+ *
+ */
+int xhci_suspend(struct xhci_hcd *xhci)
+{
+	int			rc = 0;
+	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
+	u32			command;
+
+	spin_lock_irq(&xhci->lock);
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	/* step 1: stop endpoint */
+	/* skipped assuming that port suspend has done */
+
+	/* step 2: clear Run/Stop bit */
+	command = xhci_readl(xhci, &xhci->op_regs->command);
+	command &= ~CMD_RUN;
+	xhci_writel(xhci, command, &xhci->op_regs->command);
+	if (handshake(xhci, &xhci->op_regs->status,
+		      STS_HALT, STS_HALT, 100*100)) {
+		xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
+		spin_unlock_irq(&xhci->lock);
+		return -ETIMEDOUT;
+	}
+
+	/* step 3: save registers */
+	xhci_save_registers(xhci);
+
+	/* step 4: set CSS flag */
+	command = xhci_readl(xhci, &xhci->op_regs->command);
+	command |= CMD_CSS;
+	xhci_writel(xhci, command, &xhci->op_regs->command);
+	if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10*100)) {
+		xhci_warn(xhci, "WARN: xHC CMD_CSS timeout\n");
+		spin_unlock_irq(&xhci->lock);
+		return -ETIMEDOUT;
+	}
+	/* step 5: remove core well power */
+	xhci_cleanup_msix(xhci);
+	spin_unlock_irq(&xhci->lock);
+
+	return rc;
+}
+
+/*
+ * start xHC (not bus-specific)
+ *
+ * This is called when the machine transition from S3/S4 mode.
+ *
+ */
+int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+{
+	u32			command, temp = 0;
+	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
+	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
+	u64	val_64;
+	int	old_state, retval;
+
+	old_state = hcd->state;
+	if (time_before(jiffies, xhci->next_statechange))
+		msleep(100);
+
+	spin_lock_irq(&xhci->lock);
+
+	if (!hibernated) {
+		/* step 1: restore register */
+		xhci_restore_registers(xhci);
+		/* step 2: initialize command ring buffer */
+		val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+		val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
+			 (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+					       xhci->cmd_ring->dequeue) &
+			 (u64) ~CMD_RING_RSVD_BITS) |
+			 xhci->cmd_ring->cycle_state;
+		xhci_dbg(xhci, "// Setting command ring address to 0x%llx\n",
+				(long unsigned long) val_64);
+		xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
+		/* step 3: restore state and start state*/
+		/* step 3: set CRS flag */
+		command = xhci_readl(xhci, &xhci->op_regs->command);
+		command |= CMD_CRS;
+		xhci_writel(xhci, command, &xhci->op_regs->command);
+		if (handshake(xhci, &xhci->op_regs->status,
+			      STS_RESTORE, 0, 10*100)) {
+			xhci_dbg(xhci, "WARN: xHC CMD_CSS timeout\n");
+			spin_unlock_irq(&xhci->lock);
+			return -ETIMEDOUT;
+		}
+		temp = xhci_readl(xhci, &xhci->op_regs->status);
+	}
+
+	/* If restore operation fails, re-initialize the HC during resume */
+	if ((temp & STS_SRE) || hibernated) {
+		usb_root_hub_lost_power(hcd->self.root_hub);
+
+		xhci_dbg(xhci, "Stop HCD\n");
+		xhci_halt(xhci);
+		xhci_reset(xhci);
+		if (hibernated)
+			xhci_cleanup_msix(xhci);
+		spin_unlock_irq(&xhci->lock);
+
+#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
+		/* Tell the event ring poll function not to reschedule */
+		xhci->zombie = 1;
+		del_timer_sync(&xhci->event_ring_timer);
+#endif
+
+		xhci_dbg(xhci, "// Disabling event ring interrupts\n");
+		temp = xhci_readl(xhci, &xhci->op_regs->status);
+		xhci_writel(xhci, temp & ~STS_EINT, &xhci->op_regs->status);
+		temp = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+		xhci_writel(xhci, ER_IRQ_DISABLE(temp),
+				&xhci->ir_set->irq_pending);
+		xhci_print_ir_set(xhci, xhci->ir_set, 0);
+
+		xhci_dbg(xhci, "cleaning up memory\n");
+		xhci_mem_cleanup(xhci);
+		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);
+		if (retval)
+			return retval;
+
+		xhci_dbg(xhci, "Start the HCD\n");
+		retval = xhci_run(hcd);
+		if (!retval)
+			set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+		hcd->state = HC_STATE_SUSPENDED;
+		return retval;
+	}
+
+	/* Re-setup MSI-X */
+	if (hcd->irq)
+		free_irq(hcd->irq, hcd);
+	hcd->irq = -1;
+
+	retval = xhci_setup_msix(xhci);
+	if (retval)
+		/* fall back to msi*/
+		retval = xhci_setup_msi(xhci);
+
+	if (retval) {
+		/* fall back to legacy interrupt*/
+		retval = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
+					hcd->irq_descr, hcd);
+		if (retval) {
+			xhci_err(xhci, "request interrupt %d failed\n",
+					pdev->irq);
+			return retval;
+		}
+		hcd->irq = pdev->irq;
+	}
+
+	/* step 4: set Run/Stop bit */
+	command = xhci_readl(xhci, &xhci->op_regs->command);
+	command |= CMD_RUN;
+	xhci_writel(xhci, command, &xhci->op_regs->command);
+	handshake(xhci, &xhci->op_regs->status, STS_HALT,
+		  0, 250 * 1000);
+
+	/* step 5: walk topology and initialize portsc,
+	 * portpmsc and portli
+	 */
+	/* this is done in bus_resume */
+
+	/* step 6: restart each of the previously
+	 * Running endpoints by ringing their doorbells
+	 */
+
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	if (!hibernated)
+		hcd->state = old_state;
+	else
+		hcd->state = HC_STATE_SUSPENDED;
+
+	spin_unlock_irq(&xhci->lock);
+	return 0;
+}
+#endif	/* CONFIG_PM */
+
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -607,7 +819,11 @@
  * returns 0 this is a root hub; returns -EINVAL for NULL pointers.
  */
 int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
-		struct usb_host_endpoint *ep, int check_ep, const char *func) {
+		struct usb_host_endpoint *ep, int check_ep, bool check_virt_dev,
+		const char *func) {
+	struct xhci_hcd	*xhci;
+	struct xhci_virt_device	*virt_dev;
+
 	if (!hcd || (check_ep && !ep) || !udev) {
 		printk(KERN_DEBUG "xHCI %s called with invalid args\n",
 				func);
@@ -618,11 +834,24 @@
 				func);
 		return 0;
 	}
-	if (!udev->slot_id) {
-		printk(KERN_DEBUG "xHCI %s called with unaddressed device\n",
-				func);
-		return -EINVAL;
+
+	if (check_virt_dev) {
+		xhci = hcd_to_xhci(hcd);
+		if (!udev->slot_id || !xhci->devs
+			|| !xhci->devs[udev->slot_id]) {
+			printk(KERN_DEBUG "xHCI %s called with unaddressed "
+						"device\n", func);
+			return -EINVAL;
+		}
+
+		virt_dev = xhci->devs[udev->slot_id];
+		if (virt_dev->udev != udev) {
+			printk(KERN_DEBUG "xHCI %s called with udev and "
+					  "virt_dev does not match\n", func);
+			return -EINVAL;
+		}
 	}
+
 	return 1;
 }
 
@@ -704,18 +933,13 @@
 	struct urb_priv	*urb_priv;
 	int size, i;
 
-	if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0)
+	if (!urb || xhci_check_args(hcd, urb->dev, urb->ep,
+					true, true, __func__) <= 0)
 		return -EINVAL;
 
 	slot_id = urb->dev->slot_id;
 	ep_index = xhci_get_endpoint_index(&urb->ep->desc);
 
-	if (!xhci->devs || !xhci->devs[slot_id]) {
-		if (!in_interrupt())
-			dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n");
-		ret = -EINVAL;
-		goto exit;
-	}
 	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		if (!in_interrupt())
 			xhci_dbg(xhci, "urb submitted during PCI suspend\n");
@@ -956,7 +1180,7 @@
 		ep->stop_cmd_timer.expires = jiffies +
 			XHCI_STOP_EP_CMD_TIMEOUT * HZ;
 		add_timer(&ep->stop_cmd_timer);
-		xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index);
+		xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index, 0);
 		xhci_ring_cmd_db(xhci);
 	}
 done:
@@ -991,7 +1215,7 @@
 	u32 new_add_flags, new_drop_flags, new_slot_info;
 	int ret;
 
-	ret = xhci_check_args(hcd, udev, ep, 1, __func__);
+	ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
 	if (ret <= 0)
 		return ret;
 	xhci = hcd_to_xhci(hcd);
@@ -1004,12 +1228,6 @@
 		return 0;
 	}
 
-	if (!xhci->devs || !xhci->devs[udev->slot_id]) {
-		xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-				__func__);
-		return -EINVAL;
-	}
-
 	in_ctx = xhci->devs[udev->slot_id]->in_ctx;
 	out_ctx = xhci->devs[udev->slot_id]->out_ctx;
 	ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
@@ -1078,7 +1296,7 @@
 	u32 new_add_flags, new_drop_flags, new_slot_info;
 	int ret = 0;
 
-	ret = xhci_check_args(hcd, udev, ep, 1, __func__);
+	ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
 	if (ret <= 0) {
 		/* So we won't queue a reset ep command for a root hub */
 		ep->hcpriv = NULL;
@@ -1098,12 +1316,6 @@
 		return 0;
 	}
 
-	if (!xhci->devs || !xhci->devs[udev->slot_id]) {
-		xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-				__func__);
-		return -EINVAL;
-	}
-
 	in_ctx = xhci->devs[udev->slot_id]->in_ctx;
 	out_ctx = xhci->devs[udev->slot_id]->out_ctx;
 	ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
@@ -1346,16 +1558,11 @@
 	struct xhci_input_control_ctx *ctrl_ctx;
 	struct xhci_slot_ctx *slot_ctx;
 
-	ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+	ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
 	if (ret <= 0)
 		return ret;
 	xhci = hcd_to_xhci(hcd);
 
-	if (!udev->slot_id || !xhci->devs || !xhci->devs[udev->slot_id]) {
-		xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-				__func__);
-		return -EINVAL;
-	}
 	xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
 	virt_dev = xhci->devs[udev->slot_id];
 
@@ -1405,16 +1612,11 @@
 	struct xhci_virt_device	*virt_dev;
 	int i, ret;
 
-	ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+	ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
 	if (ret <= 0)
 		return;
 	xhci = hcd_to_xhci(hcd);
 
-	if (!xhci->devs || !xhci->devs[udev->slot_id]) {
-		xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-				__func__);
-		return;
-	}
 	xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
 	virt_dev = xhci->devs[udev->slot_id];
 	/* Free any rings allocated for added endpoints */
@@ -1575,7 +1777,7 @@
 
 	if (!ep)
 		return -EINVAL;
-	ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, __func__);
+	ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, true, __func__);
 	if (ret <= 0)
 		return -EINVAL;
 	if (ep->ss_ep_comp.bmAttributes == 0) {
@@ -1953,8 +2155,13 @@
  * Wait for the Reset Device command to finish.  Remove all structures
  * associated with the endpoints that were disabled.  Clear the input device
  * structure?  Cache the rings?  Reset the control endpoint 0 max packet size?
+ *
+ * If the virt_dev to be reset does not exist or does not match the udev,
+ * it means the device is lost, possibly due to the xHC restore error and
+ * re-initialization during S3/S4. In this case, call xhci_alloc_dev() to
+ * re-allocate the device.
  */
-int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
+int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
 {
 	int ret, i;
 	unsigned long flags;
@@ -1965,16 +2172,35 @@
 	int timeleft;
 	int last_freed_endpoint;
 
-	ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+	ret = xhci_check_args(hcd, udev, NULL, 0, false, __func__);
 	if (ret <= 0)
 		return ret;
 	xhci = hcd_to_xhci(hcd);
 	slot_id = udev->slot_id;
 	virt_dev = xhci->devs[slot_id];
 	if (!virt_dev) {
-		xhci_dbg(xhci, "%s called with invalid slot ID %u\n",
-				__func__, slot_id);
-		return -EINVAL;
+		xhci_dbg(xhci, "The device to be reset with slot ID %u does "
+				"not exist. Re-allocate the device\n", slot_id);
+		ret = xhci_alloc_dev(hcd, udev);
+		if (ret == 1)
+			return 0;
+		else
+			return -EINVAL;
+	}
+
+	if (virt_dev->udev != udev) {
+		/* If the virt_dev and the udev does not match, this virt_dev
+		 * may belong to another udev.
+		 * Re-allocate the device.
+		 */
+		xhci_dbg(xhci, "The device to be reset with slot ID %u does "
+				"not match the udev. Re-allocate the device\n",
+				slot_id);
+		ret = xhci_alloc_dev(hcd, udev);
+		if (ret == 1)
+			return 0;
+		else
+			return -EINVAL;
 	}
 
 	xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
@@ -2077,13 +2303,13 @@
 	struct xhci_virt_device *virt_dev;
 	unsigned long flags;
 	u32 state;
-	int i;
+	int i, ret;
 
-	if (udev->slot_id == 0)
+	ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
+	if (ret <= 0)
 		return;
+
 	virt_dev = xhci->devs[udev->slot_id];
-	if (!virt_dev)
-		return;
 
 	/* Stop any wayward timer functions (which may grab the lock) */
 	for (i = 0; i < 31; ++i) {
@@ -2191,12 +2417,17 @@
 
 	virt_dev = xhci->devs[udev->slot_id];
 
-	/* If this is a Set Address to an unconfigured device, setup ep 0 */
-	if (!udev->config)
+	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
+	/*
+	 * If this is the first Set Address since device plug-in or
+	 * virt_device realloaction after a resume with an xHCI power loss,
+	 * then set up the slot context.
+	 */
+	if (!slot_ctx->dev_info)
 		xhci_setup_addressable_virt_dev(xhci, udev);
+	/* Otherwise, update the control endpoint ring enqueue pointer. */
 	else
 		xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev);
-	/* Otherwise, assume the core has the device configured how it wants */
 	xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
 	xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
 
@@ -2268,15 +2499,15 @@
 	 * address given back to us by the HC.
 	 */
 	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
-	udev->devnum = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
+	/* Use kernel assigned address for devices; store xHC assigned
+	 * address locally. */
+	virt_dev->address = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
 	/* Zero the input context control for later use */
 	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
 	ctrl_ctx->add_flags = 0;
 	ctrl_ctx->drop_flags = 0;
 
-	xhci_dbg(xhci, "Device address = %d\n", udev->devnum);
-	/* XXX Meh, not sure if anyone else but choose_address uses this. */
-	set_bit(udev->devnum, udev->bus->devmap.devicemap);
+	xhci_dbg(xhci, "Internal device address = %d\n", virt_dev->address);
 
 	return 0;
 }
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 34a60d9..93d3bf4 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -191,7 +191,7 @@
 /* bits 4:6 are reserved (and should be preserved on writes). */
 /* light reset (port status stays unchanged) - reset completed when this is 0 */
 #define CMD_LRESET	(1 << 7)
-/* FIXME: ignoring host controller save/restore state for now. */
+/* host controller save/restore state. */
 #define CMD_CSS		(1 << 8)
 #define CMD_CRS		(1 << 9)
 /* Enable Wrap Event - '1' means xHC generates an event when MFINDEX wraps. */
@@ -269,6 +269,10 @@
  * A read gives the current link PM state of the port,
  * a write with Link State Write Strobe set sets the link state.
  */
+#define PORT_PLS_MASK	(0xf << 5)
+#define XDEV_U0		(0x0 << 5)
+#define XDEV_U3		(0x3 << 5)
+#define XDEV_RESUME	(0xf << 5)
 /* true: port has power (see HCC_PPC) */
 #define PORT_POWER	(1 << 9)
 /* bits 10:13 indicate device speed:
@@ -353,6 +357,8 @@
 #define PORT_U2_TIMEOUT(p)	(((p) & 0xff) << 8)
 /* Bits 24:31 for port testing */
 
+/* USB2 Protocol PORTSPMSC */
+#define PORT_RWE	(1 << 0x3)
 
 /**
  * struct xhci_intr_reg - Interrupt Register Set
@@ -510,6 +516,7 @@
 #define MAX_EXIT	(0xffff)
 /* Root hub port number that is needed to access the USB device */
 #define ROOT_HUB_PORT(p)	(((p) & 0xff) << 16)
+#define DEVINFO_TO_ROOT_HUB_PORT(p)	(((p) >> 16) & 0xff)
 /* Maximum number of ports under a hub device */
 #define XHCI_MAX_PORTS(p)	(((p) & 0xff) << 24)
 
@@ -731,6 +738,7 @@
 };
 
 struct xhci_virt_device {
+	struct usb_device		*udev;
 	/*
 	 * Commands to the hardware are passed an "input context" that
 	 * tells the hardware what to change in its data structures.
@@ -745,12 +753,15 @@
 	/* Rings saved to ensure old alt settings can be re-instated */
 	struct xhci_ring		**ring_cache;
 	int				num_rings_cached;
+	/* Store xHC assigned device address */
+	int				address;
 #define	XHCI_MAX_RINGS_CACHED	31
 	struct xhci_virt_ep		eps[31];
 	struct completion		cmd_completion;
 	/* Status of the last command issued for this device */
 	u32				cmd_status;
 	struct list_head		cmd_list;
+	u8				port;
 };
 
 
@@ -881,6 +892,10 @@
 #define TRB_TO_EP_INDEX(p)		((((p) & (0x1f << 16)) >> 16) - 1)
 #define	EP_ID_FOR_TRB(p)		((((p) + 1) & 0x1f) << 16)
 
+#define SUSPEND_PORT_FOR_TRB(p)		(((p) & 1) << 23)
+#define TRB_TO_SUSPEND_PORT(p)		(((p) & (1 << 23)) >> 23)
+#define LAST_EP_INDEX			30
+
 /* Set TR Dequeue Pointer command TRB fields */
 #define TRB_TO_STREAM_ID(p)		((((p) & (0xffff << 16)) >> 16))
 #define STREAM_ID_FOR_TRB(p)		((((p)) & 0xffff) << 16)
@@ -1115,6 +1130,17 @@
 #define XHCI_STOP_EP_CMD_TIMEOUT	5
 /* XXX: Make these module parameters */
 
+struct s3_save {
+	u32	command;
+	u32	dev_nt;
+	u64	dcbaa_ptr;
+	u32	config_reg;
+	u32	irq_pending;
+	u32	irq_control;
+	u32	erst_size;
+	u64	erst_base;
+	u64	erst_dequeue;
+};
 
 /* There is one ehci_hci structure per controller */
 struct xhci_hcd {
@@ -1178,6 +1204,12 @@
 #endif
 	/* 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!"
  *
  * xHC interrupts have been disabled and a watchdog timer will (or has already)
@@ -1199,6 +1231,10 @@
 #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];
 };
 
 /* For testing purposes */
@@ -1369,6 +1405,15 @@
 int xhci_run(struct usb_hcd *hcd);
 void xhci_stop(struct usb_hcd *hcd);
 void xhci_shutdown(struct usb_hcd *hcd);
+
+#ifdef	CONFIG_PM
+int xhci_suspend(struct xhci_hcd *xhci);
+int xhci_resume(struct xhci_hcd *xhci, bool hibernated);
+#else
+#define	xhci_suspend	NULL
+#define	xhci_resume	NULL
+#endif
+
 int xhci_get_frame(struct usb_hcd *hcd);
 irqreturn_t xhci_irq(struct usb_hcd *hcd);
 irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd);
@@ -1388,7 +1433,7 @@
 int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
 int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
 void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
-int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev);
+int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev);
 int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 
@@ -1406,7 +1451,7 @@
 int xhci_queue_vendor_command(struct xhci_hcd *xhci,
 		u32 field1, u32 field2, u32 field3, u32 field4);
 int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
-		unsigned int ep_index);
+		unsigned int ep_index, int suspend);
 int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
 		int slot_id, unsigned int ep_index);
 int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
@@ -1436,12 +1481,26 @@
 		unsigned int slot_id, unsigned int ep_index,
 		struct xhci_dequeue_state *deq_state);
 void xhci_stop_endpoint_command_watchdog(unsigned long arg);
+void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
+		unsigned int ep_index, unsigned int stream_id);
 
 /* xHCI roothub code */
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
 		char *buf, u16 wLength);
 int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
 
+#ifdef CONFIG_PM
+int xhci_bus_suspend(struct usb_hcd *hcd);
+int xhci_bus_resume(struct usb_hcd *hcd);
+#else
+#define	xhci_bus_suspend	NULL
+#define	xhci_bus_resume		NULL
+#endif	/* CONFIG_PM */
+
+u32 xhci_port_state_to_neutral(u32 state);
+int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port);
+void xhci_ring_device(struct xhci_hcd *xhci, int slot_id);
+
 /* xHCI contexts */
 struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
 struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index e192e8f..575b56c 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -963,6 +963,7 @@
 	.write =	mdc800_device_write,
 	.open =		mdc800_device_open,
 	.release =	mdc800_device_release,
+	.llseek =	noop_llseek,
 };
 
 
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 55660ea..1bfcd02 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -231,3 +231,16 @@
 	  driver beforehand. Tools for doing so are available at
 	  http://bersace03.free.fr
 
+config USB_YUREX
+	tristate "USB YUREX driver support"
+	depends on USB
+	help
+	  Say Y here if you want to connect a YUREX to your computer's
+	  USB port. The YUREX is a leg-shakes sensor. See
+	  <http://bbu.kayac.com/en/> for further information.
+	  This driver supports read/write of leg-shakes counter and
+	  fasync for the counter update via a device file /dev/yurex*.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called yurex.
+
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 717703e..796ce7eb 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -3,28 +3,27 @@
 # (the ones that don't fit into any other categories)
 #
 
-obj-$(CONFIG_USB_ADUTUX)	+= adutux.o
-obj-$(CONFIG_USB_APPLEDISPLAY)	+= appledisplay.o
-obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
-obj-$(CONFIG_USB_CYTHERM)	+= cytherm.o
-obj-$(CONFIG_USB_EMI26)		+= emi26.o
-obj-$(CONFIG_USB_EMI62)		+= emi62.o
-obj-$(CONFIG_USB_FTDI_ELAN)	+= ftdi-elan.o
-obj-$(CONFIG_USB_IDMOUSE)	+= idmouse.o
-obj-$(CONFIG_USB_IOWARRIOR)	+= iowarrior.o
-obj-$(CONFIG_USB_ISIGHTFW)	+= isight_firmware.o
-obj-$(CONFIG_USB_LCD)		+= usblcd.o
-obj-$(CONFIG_USB_LD)		+= ldusb.o
-obj-$(CONFIG_USB_LED)		+= usbled.o
-obj-$(CONFIG_USB_LEGOTOWER)	+= legousbtower.o
-obj-$(CONFIG_USB_RIO500)	+= rio500.o
-obj-$(CONFIG_USB_TEST)		+= usbtest.o
+ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
+
+obj-$(CONFIG_USB_ADUTUX)		+= adutux.o
+obj-$(CONFIG_USB_APPLEDISPLAY)		+= appledisplay.o
+obj-$(CONFIG_USB_CYPRESS_CY7C63)	+= cypress_cy7c63.o
+obj-$(CONFIG_USB_CYTHERM)		+= cytherm.o
+obj-$(CONFIG_USB_EMI26)			+= emi26.o
+obj-$(CONFIG_USB_EMI62)			+= emi62.o
+obj-$(CONFIG_USB_FTDI_ELAN)		+= ftdi-elan.o
+obj-$(CONFIG_USB_IDMOUSE)		+= idmouse.o
+obj-$(CONFIG_USB_IOWARRIOR)		+= iowarrior.o
+obj-$(CONFIG_USB_ISIGHTFW)		+= isight_firmware.o
+obj-$(CONFIG_USB_LCD)			+= usblcd.o
+obj-$(CONFIG_USB_LD)			+= ldusb.o
+obj-$(CONFIG_USB_LED)			+= usbled.o
+obj-$(CONFIG_USB_LEGOTOWER)		+= legousbtower.o
+obj-$(CONFIG_USB_RIO500)		+= rio500.o
+obj-$(CONFIG_USB_TEST)			+= usbtest.o
 obj-$(CONFIG_USB_TRANCEVIBRATOR)	+= trancevibrator.o
-obj-$(CONFIG_USB_USS720)	+= uss720.o
-obj-$(CONFIG_USB_SEVSEG)	+= usbsevseg.o
+obj-$(CONFIG_USB_USS720)		+= uss720.o
+obj-$(CONFIG_USB_SEVSEG)		+= usbsevseg.o
+obj-$(CONFIG_USB_YUREX)			+= yurex.o
 
-obj-$(CONFIG_USB_SISUSBVGA)	+= sisusbvga/
-
-ifeq ($(CONFIG_USB_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+obj-$(CONFIG_USB_SISUSBVGA)		+= sisusbvga/
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 801324a..44f8b922 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -679,6 +679,7 @@
 	.write = adu_write,
 	.open = adu_open,
 	.release = adu_release,
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index aecf380..c8eec9c 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -2769,7 +2769,7 @@
         ftdi->sequence_num = ++ftdi_instances;
         mutex_unlock(&ftdi_module_lock);
         ftdi_elan_init_kref(ftdi);
-        init_MUTEX(&ftdi->sw_lock);
+	sema_init(&ftdi->sw_lock, 1);
         ftdi->udev = usb_get_dev(interface_to_usbdev(interface));
         ftdi->interface = interface;
         mutex_init(&ftdi->u132_lock);
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index a54c3cb..c6184b4 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -105,6 +105,7 @@
 	.read = idmouse_read,
 	.open = idmouse_open,
 	.release = idmouse_release,
+	.llseek = default_llseek,
 };
 
 /* class driver information */
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index bc88c79..3756641 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -374,7 +374,7 @@
 	case USB_DEVICE_ID_CODEMERCS_IOWPV2:
 	case USB_DEVICE_ID_CODEMERCS_IOW40:
 		/* IOW24 and IOW40 use a synchronous call */
-		buf = kmalloc(8, GFP_KERNEL);	/* 8 bytes are enough for both products */
+		buf = kmalloc(count, GFP_KERNEL);
 		if (!buf) {
 			retval = -ENOMEM;
 			goto exit;
@@ -730,6 +730,7 @@
 	.open = iowarrior_open,
 	.release = iowarrior_release,
 	.poll = iowarrior_poll,
+	.llseek = noop_llseek,
 };
 
 static char *iowarrior_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index dd41d87..edffef6 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -613,6 +613,7 @@
 	.open =		ld_usb_open,
 	.release =	ld_usb_release,
 	.poll =		ld_usb_poll,
+	.llseek =	no_llseek,
 };
 
 /*
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index cc13ae6..4e23d38 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -439,6 +439,7 @@
 	.unlocked_ioctl = ioctl_rio,
 	.open =		open_rio,
 	.release =	close_rio,
+	.llseek =	noop_llseek,
 };
 
 static struct usb_class_driver usb_rio_class = {
diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
index 7f934cf..3142476 100644
--- a/drivers/usb/misc/sisusbvga/Makefile
+++ b/drivers/usb/misc/sisusbvga/Makefile
@@ -4,5 +4,4 @@
 
 obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o
 
-sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o
-
+sisusbvga-y := sisusb.o sisusb_init.o sisusb_con.o
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index d00dde1..5164815 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -282,6 +282,7 @@
         .open =         lcd_open,
 	.unlocked_ioctl = lcd_ioctl,
         .release =      lcd_release,
+        .llseek =	 noop_llseek,
 };
 
 /*
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index eef370e..a35b427 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -13,17 +13,16 @@
 
 /*-------------------------------------------------------------------------*/
 
-// FIXME make these public somewhere; usbdevfs.h?
-//
+/* FIXME make these public somewhere; usbdevfs.h? */
 struct usbtest_param {
-	// inputs
+	/* inputs */
 	unsigned		test_num;	/* 0..(TEST_CASES-1) */
 	unsigned		iterations;
 	unsigned		length;
 	unsigned		vary;
 	unsigned		sglen;
 
-	// outputs
+	/* outputs */
 	struct timeval		duration;
 };
 #define USBTEST_REQUEST	_IOWR('U', 100, struct usbtest_param)
@@ -45,9 +44,9 @@
 	const char		*name;
 	u8			ep_in;		/* bulk/intr source */
 	u8			ep_out;		/* bulk/intr sink */
-	unsigned		autoconf : 1;
-	unsigned		ctrl_out : 1;
-	unsigned		iso : 1;	/* try iso in/out */
+	unsigned		autoconf:1;
+	unsigned		ctrl_out:1;
+	unsigned		iso:1;		/* try iso in/out */
 	int			alt;
 };
 
@@ -71,9 +70,9 @@
 	u8			*buf;
 };
 
-static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test)
+static struct usb_device *testdev_to_usbdev(struct usbtest_dev *test)
 {
-	return interface_to_usbdev (test->intf);
+	return interface_to_usbdev(test->intf);
 }
 
 /* set up all urbs so they can be used with either bulk or interrupt */
@@ -87,7 +86,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int
-get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
+get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf)
 {
 	int				tmp;
 	struct usb_host_interface	*alt;
@@ -115,7 +114,7 @@
 			case USB_ENDPOINT_XFER_ISOC:
 				if (dev->info->iso)
 					goto try_iso;
-				// FALLTHROUGH
+				/* FALLTHROUGH */
 			default:
 				continue;
 			}
@@ -142,9 +141,9 @@
 	return -EINVAL;
 
 found:
-	udev = testdev_to_usbdev (dev);
+	udev = testdev_to_usbdev(dev);
 	if (alt->desc.bAlternateSetting != 0) {
-		tmp = usb_set_interface (udev,
+		tmp = usb_set_interface(udev,
 				alt->desc.bInterfaceNumber,
 				alt->desc.bAlternateSetting);
 		if (tmp < 0)
@@ -152,21 +151,21 @@
 	}
 
 	if (in) {
-		dev->in_pipe = usb_rcvbulkpipe (udev,
+		dev->in_pipe = usb_rcvbulkpipe(udev,
 			in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-		dev->out_pipe = usb_sndbulkpipe (udev,
+		dev->out_pipe = usb_sndbulkpipe(udev,
 			out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
 	}
 	if (iso_in) {
 		dev->iso_in = &iso_in->desc;
-		dev->in_iso_pipe = usb_rcvisocpipe (udev,
+		dev->in_iso_pipe = usb_rcvisocpipe(udev,
 				iso_in->desc.bEndpointAddress
 					& USB_ENDPOINT_NUMBER_MASK);
 	}
 
 	if (iso_out) {
 		dev->iso_out = &iso_out->desc;
-		dev->out_iso_pipe = usb_sndisocpipe (udev,
+		dev->out_iso_pipe = usb_sndisocpipe(udev,
 				iso_out->desc.bEndpointAddress
 					& USB_ENDPOINT_NUMBER_MASK);
 	}
@@ -182,12 +181,12 @@
  * them with non-zero test data (or test for it) when appropriate.
  */
 
-static void simple_callback (struct urb *urb)
+static void simple_callback(struct urb *urb)
 {
 	complete(urb->context);
 }
 
-static struct urb *simple_alloc_urb (
+static struct urb *simple_alloc_urb(
 	struct usb_device	*udev,
 	int			pipe,
 	unsigned long		bytes
@@ -195,32 +194,32 @@
 {
 	struct urb		*urb;
 
-	urb = usb_alloc_urb (0, GFP_KERNEL);
+	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb)
 		return urb;
-	usb_fill_bulk_urb (urb, udev, pipe, NULL, bytes, simple_callback, NULL);
+	usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback, NULL);
 	urb->interval = (udev->speed == USB_SPEED_HIGH)
 			? (INTERRUPT_RATE << 3)
 			: INTERRUPT_RATE;
 	urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-	if (usb_pipein (pipe))
+	if (usb_pipein(pipe))
 		urb->transfer_flags |= URB_SHORT_NOT_OK;
-	urb->transfer_buffer = usb_alloc_coherent (udev, bytes, GFP_KERNEL,
+	urb->transfer_buffer = usb_alloc_coherent(udev, bytes, GFP_KERNEL,
 			&urb->transfer_dma);
 	if (!urb->transfer_buffer) {
-		usb_free_urb (urb);
+		usb_free_urb(urb);
 		urb = NULL;
 	} else
-		memset (urb->transfer_buffer, 0, bytes);
+		memset(urb->transfer_buffer, 0, bytes);
 	return urb;
 }
 
-static unsigned pattern = 0;
+static unsigned pattern;
 static unsigned mod_pattern;
 module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(mod_pattern, "i/o pattern (0 == zeroes)");
 
-static inline void simple_fill_buf (struct urb *urb)
+static inline void simple_fill_buf(struct urb *urb)
 {
 	unsigned	i;
 	u8		*buf = urb->transfer_buffer;
@@ -228,9 +227,9 @@
 
 	switch (pattern) {
 	default:
-		// FALLTHROUGH
+		/* FALLTHROUGH */
 	case 0:
-		memset (buf, 0, len);
+		memset(buf, 0, len);
 		break;
 	case 1:			/* mod63 */
 		for (i = 0; i < len; i++)
@@ -273,14 +272,14 @@
 	return 0;
 }
 
-static void simple_free_urb (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);
-	usb_free_urb (urb);
+	usb_free_urb(urb);
 }
 
-static int simple_io (
+static int simple_io(
 	struct usbtest_dev	*tdev,
 	struct urb		*urb,
 	int			iterations,
@@ -296,17 +295,18 @@
 
 	urb->context = &completion;
 	while (retval == 0 && iterations-- > 0) {
-		init_completion (&completion);
-		if (usb_pipeout (urb->pipe))
-			simple_fill_buf (urb);
-		if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0)
+		init_completion(&completion);
+		if (usb_pipeout(urb->pipe))
+			simple_fill_buf(urb);
+		retval = usb_submit_urb(urb, GFP_KERNEL);
+		if (retval != 0)
 			break;
 
 		/* NOTE:  no timeouts; can't be broken out of by interrupt */
-		wait_for_completion (&completion);
+		wait_for_completion(&completion);
 		retval = urb->status;
 		urb->dev = udev;
-		if (retval == 0 && usb_pipein (urb->pipe))
+		if (retval == 0 && usb_pipein(urb->pipe))
 			retval = simple_check_buf(tdev, urb);
 
 		if (vary) {
@@ -337,7 +337,7 @@
  * Yes, this also tests the scatterlist primitives.
  */
 
-static void free_sglist (struct scatterlist *sg, int nents)
+static void free_sglist(struct scatterlist *sg, int nents)
 {
 	unsigned		i;
 
@@ -346,19 +346,19 @@
 	for (i = 0; i < nents; i++) {
 		if (!sg_page(&sg[i]))
 			continue;
-		kfree (sg_virt(&sg[i]));
+		kfree(sg_virt(&sg[i]));
 	}
-	kfree (sg);
+	kfree(sg);
 }
 
 static struct scatterlist *
-alloc_sglist (int nents, int max, int vary)
+alloc_sglist(int nents, int max, int vary)
 {
 	struct scatterlist	*sg;
 	unsigned		i;
 	unsigned		size = max;
 
-	sg = kmalloc (nents * sizeof *sg, GFP_KERNEL);
+	sg = kmalloc(nents * sizeof *sg, GFP_KERNEL);
 	if (!sg)
 		return NULL;
 	sg_init_table(sg, nents);
@@ -367,9 +367,9 @@
 		char		*buf;
 		unsigned	j;
 
-		buf = kzalloc (size, GFP_KERNEL);
+		buf = kzalloc(size, GFP_KERNEL);
 		if (!buf) {
-			free_sglist (sg, i);
+			free_sglist(sg, i);
 			return NULL;
 		}
 
@@ -397,7 +397,7 @@
 	return sg;
 }
 
-static int perform_sglist (
+static int perform_sglist(
 	struct usbtest_dev	*tdev,
 	unsigned		iterations,
 	int			pipe,
@@ -410,7 +410,7 @@
 	int			retval = 0;
 
 	while (retval == 0 && iterations-- > 0) {
-		retval = usb_sg_init (req, udev, pipe,
+		retval = usb_sg_init(req, udev, pipe,
 				(udev->speed == USB_SPEED_HIGH)
 					? (INTERRUPT_RATE << 3)
 					: INTERRUPT_RATE,
@@ -418,7 +418,7 @@
 
 		if (retval)
 			break;
-		usb_sg_wait (req);
+		usb_sg_wait(req);
 		retval = req->status;
 
 		/* FIXME check resulting data pattern */
@@ -426,9 +426,9 @@
 		/* FIXME if endpoint halted, clear halt (and log) */
 	}
 
-	// FIXME for unlink or fault handling tests, don't report
-	// failure if retval is as we expected ...
-
+	/* FIXME for unlink or fault handling tests, don't report
+	 * failure if retval is as we expected ...
+	 */
 	if (retval)
 		ERROR(tdev, "perform_sglist failed, "
 				"iterations left %d, status %d\n",
@@ -452,31 +452,31 @@
  */
 
 static unsigned realworld = 1;
-module_param (realworld, uint, 0);
-MODULE_PARM_DESC (realworld, "clear to demand stricter spec compliance");
+module_param(realworld, uint, 0);
+MODULE_PARM_DESC(realworld, "clear to demand stricter spec compliance");
 
-static int get_altsetting (struct usbtest_dev *dev)
+static int get_altsetting(struct usbtest_dev *dev)
 {
 	struct usb_interface	*iface = dev->intf;
-	struct usb_device	*udev = interface_to_usbdev (iface);
+	struct usb_device	*udev = interface_to_usbdev(iface);
 	int			retval;
 
-	retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0),
+	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 			USB_REQ_GET_INTERFACE, USB_DIR_IN|USB_RECIP_INTERFACE,
-			0, iface->altsetting [0].desc.bInterfaceNumber,
+			0, iface->altsetting[0].desc.bInterfaceNumber,
 			dev->buf, 1, USB_CTRL_GET_TIMEOUT);
 	switch (retval) {
 	case 1:
-		return dev->buf [0];
+		return dev->buf[0];
 	case 0:
 		retval = -ERANGE;
-		// FALLTHROUGH
+		/* FALLTHROUGH */
 	default:
 		return retval;
 	}
 }
 
-static int set_altsetting (struct usbtest_dev *dev, int alternate)
+static int set_altsetting(struct usbtest_dev *dev, int alternate)
 {
 	struct usb_interface		*iface = dev->intf;
 	struct usb_device		*udev;
@@ -484,9 +484,9 @@
 	if (alternate < 0 || alternate >= 256)
 		return -EINVAL;
 
-	udev = interface_to_usbdev (iface);
-	return usb_set_interface (udev,
-			iface->altsetting [0].desc.bInterfaceNumber,
+	udev = interface_to_usbdev(iface);
+	return usb_set_interface(udev,
+			iface->altsetting[0].desc.bInterfaceNumber,
 			alternate);
 }
 
@@ -519,9 +519,9 @@
 		return 0;
 	}
 
-	if (le16_to_cpu(config->wTotalLength) == len)		/* read it all */
+	if (le16_to_cpu(config->wTotalLength) == len)	/* read it all */
 		return 1;
-	if (le16_to_cpu(config->wTotalLength) >= TBUF_SIZE)		/* max partial read */
+	if (le16_to_cpu(config->wTotalLength) >= TBUF_SIZE)	/* max partial read */
 		return 1;
 	ERROR(tdev, "bogus config descriptor read size\n");
 	return 0;
@@ -542,10 +542,10 @@
  * to see if usbcore, hcd, and device all behave right.  such testing would
  * involve varied read sizes and other operation sequences.
  */
-static int ch9_postconfig (struct usbtest_dev *dev)
+static int ch9_postconfig(struct usbtest_dev *dev)
 {
 	struct usb_interface	*iface = dev->intf;
-	struct usb_device	*udev = interface_to_usbdev (iface);
+	struct usb_device	*udev = interface_to_usbdev(iface);
 	int			i, alt, retval;
 
 	/* [9.2.3] if there's more than one altsetting, we need to be able to
@@ -554,7 +554,7 @@
 	for (i = 0; i < iface->num_altsetting; i++) {
 
 		/* 9.2.3 constrains the range here */
-		alt = iface->altsetting [i].desc.bAlternateSetting;
+		alt = iface->altsetting[i].desc.bAlternateSetting;
 		if (alt < 0 || alt >= iface->num_altsetting) {
 			dev_err(&iface->dev,
 					"invalid alt [%d].bAltSetting = %d\n",
@@ -566,7 +566,7 @@
 			continue;
 
 		/* [9.4.10] set_interface */
-		retval = set_altsetting (dev, alt);
+		retval = set_altsetting(dev, alt);
 		if (retval) {
 			dev_err(&iface->dev, "can't set_interface = %d, %d\n",
 					alt, retval);
@@ -574,7 +574,7 @@
 		}
 
 		/* [9.4.4] get_interface always works */
-		retval = get_altsetting (dev);
+		retval = get_altsetting(dev);
 		if (retval != alt) {
 			dev_err(&iface->dev, "get alt should be %d, was %d\n",
 					alt, retval);
@@ -591,11 +591,11 @@
 		 * ... although some cheap devices (like one TI Hub I've got)
 		 * won't return config descriptors except before set_config.
 		 */
-		retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0),
+		retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 				USB_REQ_GET_CONFIGURATION,
 				USB_DIR_IN | USB_RECIP_DEVICE,
 				0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT);
-		if (retval != 1 || dev->buf [0] != expected) {
+		if (retval != 1 || dev->buf[0] != expected) {
 			dev_err(&iface->dev, "get config --> %d %d (1 %d)\n",
 				retval, dev->buf[0], expected);
 			return (retval < 0) ? retval : -EDOM;
@@ -603,7 +603,7 @@
 	}
 
 	/* there's always [9.4.3] a device descriptor [9.6.1] */
-	retval = usb_get_descriptor (udev, USB_DT_DEVICE, 0,
+	retval = usb_get_descriptor(udev, USB_DT_DEVICE, 0,
 			dev->buf, sizeof udev->descriptor);
 	if (retval != sizeof udev->descriptor) {
 		dev_err(&iface->dev, "dev descriptor --> %d\n", retval);
@@ -612,7 +612,7 @@
 
 	/* there's always [9.4.3] at least one config descriptor [9.6.3] */
 	for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
-		retval = usb_get_descriptor (udev, USB_DT_CONFIG, i,
+		retval = usb_get_descriptor(udev, USB_DT_CONFIG, i,
 				dev->buf, TBUF_SIZE);
 		if (!is_good_config(dev, retval)) {
 			dev_err(&iface->dev,
@@ -621,18 +621,19 @@
 			return (retval < 0) ? retval : -EDOM;
 		}
 
-		// FIXME cross-checking udev->config[i] to make sure usbcore
-		// parsed it right (etc) would be good testing paranoia
+		/* FIXME cross-checking udev->config[i] to make sure usbcore
+		 * parsed it right (etc) would be good testing paranoia
+		 */
 	}
 
 	/* and sometimes [9.2.6.6] speed dependent descriptors */
 	if (le16_to_cpu(udev->descriptor.bcdUSB) == 0x0200) {
-		struct usb_qualifier_descriptor		*d = NULL;
+		struct usb_qualifier_descriptor *d = NULL;
 
 		/* device qualifier [9.6.2] */
-		retval = usb_get_descriptor (udev,
+		retval = usb_get_descriptor(udev,
 				USB_DT_DEVICE_QUALIFIER, 0, dev->buf,
-				sizeof (struct usb_qualifier_descriptor));
+				sizeof(struct usb_qualifier_descriptor));
 		if (retval == -EPIPE) {
 			if (udev->speed == USB_SPEED_HIGH) {
 				dev_err(&iface->dev,
@@ -641,7 +642,7 @@
 				return (retval < 0) ? retval : -EDOM;
 			}
 			/* usb2.0 but not high-speed capable; fine */
-		} else if (retval != sizeof (struct usb_qualifier_descriptor)) {
+		} else if (retval != sizeof(struct usb_qualifier_descriptor)) {
 			dev_err(&iface->dev, "dev qualifier --> %d\n", retval);
 			return (retval < 0) ? retval : -EDOM;
 		} else
@@ -651,7 +652,7 @@
 		if (d) {
 			unsigned max = d->bNumConfigurations;
 			for (i = 0; i < max; i++) {
-				retval = usb_get_descriptor (udev,
+				retval = usb_get_descriptor(udev,
 					USB_DT_OTHER_SPEED_CONFIG, i,
 					dev->buf, TBUF_SIZE);
 				if (!is_good_config(dev, retval)) {
@@ -663,25 +664,26 @@
 			}
 		}
 	}
-	// FIXME fetch strings from at least the device descriptor
+	/* FIXME fetch strings from at least the device descriptor */
 
 	/* [9.4.5] get_status always works */
-	retval = usb_get_status (udev, USB_RECIP_DEVICE, 0, dev->buf);
+	retval = usb_get_status(udev, USB_RECIP_DEVICE, 0, dev->buf);
 	if (retval != 2) {
 		dev_err(&iface->dev, "get dev status --> %d\n", retval);
 		return (retval < 0) ? retval : -EDOM;
 	}
 
-	// FIXME configuration.bmAttributes says if we could try to set/clear
-	// the device's remote wakeup feature ... if we can, test that here
+	/* FIXME configuration.bmAttributes says if we could try to set/clear
+	 * the device's remote wakeup feature ... if we can, test that here
+	 */
 
-	retval = usb_get_status (udev, USB_RECIP_INTERFACE,
-			iface->altsetting [0].desc.bInterfaceNumber, dev->buf);
+	retval = usb_get_status(udev, USB_RECIP_INTERFACE,
+			iface->altsetting[0].desc.bInterfaceNumber, dev->buf);
 	if (retval != 2) {
 		dev_err(&iface->dev, "get interface status --> %d\n", retval);
 		return (retval < 0) ? retval : -EDOM;
 	}
-	// FIXME get status for each endpoint in the interface
+	/* FIXME get status for each endpoint in the interface */
 
 	return 0;
 }
@@ -717,7 +719,7 @@
 	int			expected;
 };
 
-static void ctrl_complete (struct urb *urb)
+static void ctrl_complete(struct urb *urb)
 {
 	struct ctrl_ctx		*ctx = urb->context;
 	struct usb_ctrlrequest	*reqp;
@@ -725,9 +727,9 @@
 	int			status = urb->status;
 
 	reqp = (struct usb_ctrlrequest *)urb->setup_packet;
-	subcase = container_of (reqp, struct subcase, setup);
+	subcase = container_of(reqp, struct subcase, setup);
 
-	spin_lock (&ctx->lock);
+	spin_lock(&ctx->lock);
 	ctx->count--;
 	ctx->pending--;
 
@@ -787,14 +789,14 @@
 
 			/* unlink whatever's still pending */
 			for (i = 1; i < ctx->param->sglen; i++) {
-				struct urb	*u = ctx->urb [
-						(i + subcase->number)
-						% ctx->param->sglen];
+				struct urb *u = ctx->urb[
+							(i + subcase->number)
+							% ctx->param->sglen];
 
 				if (u == urb || !u->dev)
 					continue;
 				spin_unlock(&ctx->lock);
-				status = usb_unlink_urb (u);
+				status = usb_unlink_urb(u);
 				spin_lock(&ctx->lock);
 				switch (status) {
 				case -EINPROGRESS:
@@ -812,7 +814,8 @@
 
 	/* resubmit if we need to, else mark this as done */
 	if ((status == 0) && (ctx->pending < ctx->count)) {
-		if ((status = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
+		status = usb_submit_urb(urb, GFP_ATOMIC);
+		if (status != 0) {
 			ERROR(ctx->dev,
 				"can't resubmit ctrl %02x.%02x, err %d\n",
 				reqp->bRequestType, reqp->bRequest, status);
@@ -824,21 +827,21 @@
 
 	/* signal completion when nothing's queued */
 	if (ctx->pending == 0)
-		complete (&ctx->complete);
-	spin_unlock (&ctx->lock);
+		complete(&ctx->complete);
+	spin_unlock(&ctx->lock);
 }
 
 static int
-test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
+test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param)
 {
-	struct usb_device	*udev = testdev_to_usbdev (dev);
+	struct usb_device	*udev = testdev_to_usbdev(dev);
 	struct urb		**urb;
 	struct ctrl_ctx		context;
 	int			i;
 
-	spin_lock_init (&context.lock);
+	spin_lock_init(&context.lock);
 	context.dev = dev;
-	init_completion (&context.complete);
+	init_completion(&context.complete);
 	context.count = param->sglen * param->iterations;
 	context.pending = 0;
 	context.status = -ENOMEM;
@@ -853,7 +856,7 @@
 	if (!urb)
 		return -ENOMEM;
 	for (i = 0; i < param->sglen; i++) {
-		int			pipe = usb_rcvctrlpipe (udev, 0);
+		int			pipe = usb_rcvctrlpipe(udev, 0);
 		unsigned		len;
 		struct urb		*u;
 		struct usb_ctrlrequest	req;
@@ -869,104 +872,108 @@
 		 * device, but some are chosen to trigger protocol stalls
 		 * or short reads.
 		 */
-		memset (&req, 0, sizeof req);
+		memset(&req, 0, sizeof req);
 		req.bRequest = USB_REQ_GET_DESCRIPTOR;
 		req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE;
 
 		switch (i % NUM_SUBCASES) {
-		case 0:		// get device descriptor
-			req.wValue = cpu_to_le16 (USB_DT_DEVICE << 8);
-			len = sizeof (struct usb_device_descriptor);
+		case 0:		/* get device descriptor */
+			req.wValue = cpu_to_le16(USB_DT_DEVICE << 8);
+			len = sizeof(struct usb_device_descriptor);
 			break;
-		case 1:		// get first config descriptor (only)
-			req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
-			len = sizeof (struct usb_config_descriptor);
+		case 1:		/* get first config descriptor (only) */
+			req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
+			len = sizeof(struct usb_config_descriptor);
 			break;
-		case 2:		// get altsetting (OFTEN STALLS)
+		case 2:		/* get altsetting (OFTEN STALLS) */
 			req.bRequest = USB_REQ_GET_INTERFACE;
 			req.bRequestType = USB_DIR_IN|USB_RECIP_INTERFACE;
-			// index = 0 means first interface
+			/* index = 0 means first interface */
 			len = 1;
 			expected = EPIPE;
 			break;
-		case 3:		// get interface status
+		case 3:		/* get interface status */
 			req.bRequest = USB_REQ_GET_STATUS;
 			req.bRequestType = USB_DIR_IN|USB_RECIP_INTERFACE;
-			// interface 0
+			/* interface 0 */
 			len = 2;
 			break;
-		case 4:		// get device status
+		case 4:		/* get device status */
 			req.bRequest = USB_REQ_GET_STATUS;
 			req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE;
 			len = 2;
 			break;
-		case 5:		// get device qualifier (MAY STALL)
+		case 5:		/* get device qualifier (MAY STALL) */
 			req.wValue = cpu_to_le16 (USB_DT_DEVICE_QUALIFIER << 8);
-			len = sizeof (struct usb_qualifier_descriptor);
+			len = sizeof(struct usb_qualifier_descriptor);
 			if (udev->speed != USB_SPEED_HIGH)
 				expected = EPIPE;
 			break;
-		case 6:		// get first config descriptor, plus interface
-			req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
-			len = sizeof (struct usb_config_descriptor);
-			len += sizeof (struct usb_interface_descriptor);
+		case 6:		/* get first config descriptor, plus interface */
+			req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
+			len = sizeof(struct usb_config_descriptor);
+			len += sizeof(struct usb_interface_descriptor);
 			break;
-		case 7:		// get interface descriptor (ALWAYS STALLS)
+		case 7:		/* get interface descriptor (ALWAYS STALLS) */
 			req.wValue = cpu_to_le16 (USB_DT_INTERFACE << 8);
-			// interface == 0
-			len = sizeof (struct usb_interface_descriptor);
+			/* interface == 0 */
+			len = sizeof(struct usb_interface_descriptor);
 			expected = -EPIPE;
 			break;
-		// NOTE: two consecutive stalls in the queue here.
-		// that tests fault recovery a bit more aggressively.
-		case 8:		// clear endpoint halt (MAY STALL)
+		/* NOTE: two consecutive stalls in the queue here.
+		 *  that tests fault recovery a bit more aggressively. */
+		case 8:		/* clear endpoint halt (MAY STALL) */
 			req.bRequest = USB_REQ_CLEAR_FEATURE;
 			req.bRequestType = USB_RECIP_ENDPOINT;
-			// wValue 0 == ep halt
-			// wIndex 0 == ep0 (shouldn't halt!)
+			/* wValue 0 == ep halt */
+			/* wIndex 0 == ep0 (shouldn't halt!) */
 			len = 0;
-			pipe = usb_sndctrlpipe (udev, 0);
+			pipe = usb_sndctrlpipe(udev, 0);
 			expected = EPIPE;
 			break;
-		case 9:		// get endpoint status
+		case 9:		/* get endpoint status */
 			req.bRequest = USB_REQ_GET_STATUS;
 			req.bRequestType = USB_DIR_IN|USB_RECIP_ENDPOINT;
-			// endpoint 0
+			/* endpoint 0 */
 			len = 2;
 			break;
-		case 10:	// trigger short read (EREMOTEIO)
-			req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
+		case 10:	/* trigger short read (EREMOTEIO) */
+			req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
 			len = 1024;
 			expected = -EREMOTEIO;
 			break;
-		// NOTE: two consecutive _different_ faults in the queue.
-		case 11:	// get endpoint descriptor (ALWAYS STALLS)
-			req.wValue = cpu_to_le16 (USB_DT_ENDPOINT << 8);
-			// endpoint == 0
-			len = sizeof (struct usb_interface_descriptor);
+		/* NOTE: two consecutive _different_ faults in the queue. */
+		case 11:	/* get endpoint descriptor (ALWAYS STALLS) */
+			req.wValue = cpu_to_le16(USB_DT_ENDPOINT << 8);
+			/* endpoint == 0 */
+			len = sizeof(struct usb_interface_descriptor);
 			expected = EPIPE;
 			break;
-		// NOTE: sometimes even a third fault in the queue!
-		case 12:	// get string 0 descriptor (MAY STALL)
-			req.wValue = cpu_to_le16 (USB_DT_STRING << 8);
-			// string == 0, for language IDs
-			len = sizeof (struct usb_interface_descriptor);
-			// may succeed when > 4 languages
-			expected = EREMOTEIO;	// or EPIPE, if no strings
+		/* NOTE: sometimes even a third fault in the queue! */
+		case 12:	/* get string 0 descriptor (MAY STALL) */
+			req.wValue = cpu_to_le16(USB_DT_STRING << 8);
+			/* string == 0, for language IDs */
+			len = sizeof(struct usb_interface_descriptor);
+			/* may succeed when > 4 languages */
+			expected = EREMOTEIO;	/* or EPIPE, if no strings */
 			break;
-		case 13:	// short read, resembling case 10
-			req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
-			// last data packet "should" be DATA1, not DATA0
+		case 13:	/* short read, resembling case 10 */
+			req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
+			/* last data packet "should" be DATA1, not DATA0 */
 			len = 1024 - udev->descriptor.bMaxPacketSize0;
 			expected = -EREMOTEIO;
 			break;
-		case 14:	// short read; try to fill the last packet
-			req.wValue = cpu_to_le16 ((USB_DT_DEVICE << 8) | 0);
+		case 14:	/* short read; try to fill the last packet */
+			req.wValue = cpu_to_le16((USB_DT_DEVICE << 8) | 0);
 			/* device descriptor size == 18 bytes */
 			len = udev->descriptor.bMaxPacketSize0;
 			switch (len) {
-			case 8:		len = 24; break;
-			case 16:	len = 32; break;
+			case 8:
+				len = 24;
+				break;
+			case 16:
+				len = 32;
+				break;
 			}
 			expected = -EREMOTEIO;
 			break;
@@ -975,8 +982,8 @@
 			context.status = -EINVAL;
 			goto cleanup;
 		}
-		req.wLength = cpu_to_le16 (len);
-		urb [i] = u = simple_alloc_urb (udev, pipe, len);
+		req.wLength = cpu_to_le16(len);
+		urb[i] = u = simple_alloc_urb(udev, pipe, len);
 		if (!u)
 			goto cleanup;
 
@@ -994,9 +1001,9 @@
 
 	/* queue the urbs */
 	context.urb = urb;
-	spin_lock_irq (&context.lock);
+	spin_lock_irq(&context.lock);
 	for (i = 0; i < param->sglen; i++) {
-		context.status = usb_submit_urb (urb [i], GFP_ATOMIC);
+		context.status = usb_submit_urb(urb[i], GFP_ATOMIC);
 		if (context.status != 0) {
 			ERROR(dev, "can't submit urb[%d], status %d\n",
 					i, context.status);
@@ -1005,23 +1012,23 @@
 		}
 		context.pending++;
 	}
-	spin_unlock_irq (&context.lock);
+	spin_unlock_irq(&context.lock);
 
 	/* FIXME  set timer and time out; provide a disconnect hook */
 
 	/* wait for the last one to complete */
 	if (context.pending > 0)
-		wait_for_completion (&context.complete);
+		wait_for_completion(&context.complete);
 
 cleanup:
 	for (i = 0; i < param->sglen; i++) {
-		if (!urb [i])
+		if (!urb[i])
 			continue;
-		urb [i]->dev = udev;
+		urb[i]->dev = udev;
 		kfree(urb[i]->setup_packet);
-		simple_free_urb (urb [i]);
+		simple_free_urb(urb[i]);
 	}
-	kfree (urb);
+	kfree(urb);
 	return context.status;
 }
 #undef NUM_SUBCASES
@@ -1029,27 +1036,27 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void unlink1_callback (struct urb *urb)
+static void unlink1_callback(struct urb *urb)
 {
 	int	status = urb->status;
 
-	// we "know" -EPIPE (stall) never happens
+	/* we "know" -EPIPE (stall) never happens */
 	if (!status)
-		status = usb_submit_urb (urb, GFP_ATOMIC);
+		status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
 		urb->status = status;
 		complete(urb->context);
 	}
 }
 
-static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
+static int unlink1(struct usbtest_dev *dev, int pipe, int size, int async)
 {
 	struct urb		*urb;
 	struct completion	completion;
 	int			retval = 0;
 
-	init_completion (&completion);
-	urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
+	init_completion(&completion);
+	urb = simple_alloc_urb(testdev_to_usbdev(dev), pipe, size);
 	if (!urb)
 		return -ENOMEM;
 	urb->context = &completion;
@@ -1061,7 +1068,8 @@
 	 * FIXME want additional tests for when endpoint is STALLing
 	 * due to errors, or is just NAKing requests.
 	 */
-	if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) {
+	retval = usb_submit_urb(urb, GFP_KERNEL);
+	if (retval != 0) {
 		dev_err(&dev->intf->dev, "submit fail %d\n", retval);
 		return retval;
 	}
@@ -1069,7 +1077,7 @@
 	/* unlinking that should always work.  variable delay tests more
 	 * hcd states and code paths, even with little other system load.
 	 */
-	msleep (jiffies % (2 * INTERRUPT_RATE));
+	msleep(jiffies % (2 * INTERRUPT_RATE));
 	if (async) {
 		while (!completion_done(&completion)) {
 			retval = usb_unlink_urb(urb);
@@ -1098,11 +1106,11 @@
 			break;
 		}
 	} else
-		usb_kill_urb (urb);
+		usb_kill_urb(urb);
 
-	wait_for_completion (&completion);
+	wait_for_completion(&completion);
 	retval = urb->status;
-	simple_free_urb (urb);
+	simple_free_urb(urb);
 
 	if (async)
 		return (retval == -ECONNRESET) ? 0 : retval - 1000;
@@ -1111,14 +1119,14 @@
 				0 : retval - 2000;
 }
 
-static int unlink_simple (struct usbtest_dev *dev, int pipe, int len)
+static int unlink_simple(struct usbtest_dev *dev, int pipe, int len)
 {
 	int			retval = 0;
 
 	/* test sync and async paths */
-	retval = unlink1 (dev, pipe, len, 1);
+	retval = unlink1(dev, pipe, len, 1);
 	if (!retval)
-		retval = unlink1 (dev, pipe, len, 0);
+		retval = unlink1(dev, pipe, len, 0);
 	return retval;
 }
 
@@ -1130,7 +1138,7 @@
 	u16	status;
 
 	/* shouldn't look or act halted */
-	retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status);
+	retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, ep, &status);
 	if (retval < 0) {
 		ERROR(tdev, "ep %02x couldn't get no-halt status, %d\n",
 				ep, retval);
@@ -1152,7 +1160,7 @@
 	u16	status;
 
 	/* should look and act halted */
-	retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status);
+	retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, ep, &status);
 	if (retval < 0) {
 		ERROR(tdev, "ep %02x couldn't get halt status, %d\n",
 				ep, retval);
@@ -1182,7 +1190,7 @@
 		return retval;
 
 	/* set halt (protocol test only), verify it worked */
-	retval = usb_control_msg (urb->dev, usb_sndctrlpipe (urb->dev, 0),
+	retval = usb_control_msg(urb->dev, usb_sndctrlpipe(urb->dev, 0),
 			USB_REQ_SET_FEATURE, USB_RECIP_ENDPOINT,
 			USB_ENDPOINT_HALT, ep,
 			NULL, 0, USB_CTRL_SET_TIMEOUT);
@@ -1195,7 +1203,7 @@
 		return retval;
 
 	/* clear halt (tests API + protocol), verify it worked */
-	retval = usb_clear_halt (urb->dev, urb->pipe);
+	retval = usb_clear_halt(urb->dev, urb->pipe);
 	if (retval < 0) {
 		ERROR(tdev, "ep %02x couldn't clear halt, %d\n", ep, retval);
 		return retval;
@@ -1209,18 +1217,18 @@
 	return 0;
 }
 
-static int halt_simple (struct usbtest_dev *dev)
+static int halt_simple(struct usbtest_dev *dev)
 {
 	int		ep;
 	int		retval = 0;
 	struct urb	*urb;
 
-	urb = simple_alloc_urb (testdev_to_usbdev (dev), 0, 512);
+	urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512);
 	if (urb == NULL)
 		return -ENOMEM;
 
 	if (dev->in_pipe) {
-		ep = usb_pipeendpoint (dev->in_pipe) | USB_DIR_IN;
+		ep = usb_pipeendpoint(dev->in_pipe) | USB_DIR_IN;
 		urb->pipe = dev->in_pipe;
 		retval = test_halt(dev, ep, urb);
 		if (retval < 0)
@@ -1228,12 +1236,12 @@
 	}
 
 	if (dev->out_pipe) {
-		ep = usb_pipeendpoint (dev->out_pipe);
+		ep = usb_pipeendpoint(dev->out_pipe);
 		urb->pipe = dev->out_pipe;
 		retval = test_halt(dev, ep, urb);
 	}
 done:
-	simple_free_urb (urb);
+	simple_free_urb(urb);
 	return retval;
 }
 
@@ -1247,7 +1255,7 @@
  * need to be able to handle more than one OUT data packet.  We'll
  * try whatever we're told to try.
  */
-static int ctrl_out (struct usbtest_dev *dev,
+static int ctrl_out(struct usbtest_dev *dev,
 		unsigned count, unsigned length, unsigned vary)
 {
 	unsigned		i, j, len;
@@ -1263,7 +1271,7 @@
 	if (!buf)
 		return -ENOMEM;
 
-	udev = testdev_to_usbdev (dev);
+	udev = testdev_to_usbdev(dev);
 	len = length;
 	retval = 0;
 
@@ -1273,8 +1281,8 @@
 	for (i = 0; i < count; i++) {
 		/* write patterned data */
 		for (j = 0; j < len; j++)
-			buf [j] = i + j;
-		retval = usb_control_msg (udev, usb_sndctrlpipe (udev,0),
+			buf[j] = i + j;
+		retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 				0x5b, USB_DIR_OUT|USB_TYPE_VENDOR,
 				0, 0, buf, len, USB_CTRL_SET_TIMEOUT);
 		if (retval != len) {
@@ -1288,7 +1296,7 @@
 		}
 
 		/* read it back -- assuming nothing intervened!!  */
-		retval = usb_control_msg (udev, usb_rcvctrlpipe (udev,0),
+		retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 				0x5c, USB_DIR_IN|USB_TYPE_VENDOR,
 				0, 0, buf, len, USB_CTRL_GET_TIMEOUT);
 		if (retval != len) {
@@ -1303,9 +1311,9 @@
 
 		/* fail if we can't verify */
 		for (j = 0; j < len; j++) {
-			if (buf [j] != (u8) (i + j)) {
+			if (buf[j] != (u8) (i + j)) {
 				ERROR(dev, "ctrl_out, byte %d is %d not %d\n",
-					j, buf [j], (u8) i + j);
+					j, buf[j], (u8) i + j);
 				retval = -EBADMSG;
 				break;
 			}
@@ -1326,10 +1334,10 @@
 	}
 
 	if (retval < 0)
-		ERROR (dev, "ctrl_out %s failed, code %d, count %d\n",
+		ERROR(dev, "ctrl_out %s failed, code %d, count %d\n",
 			what, retval, i);
 
-	kfree (buf);
+	kfree(buf);
 	return retval;
 }
 
@@ -1351,7 +1359,7 @@
 	struct usbtest_dev	*dev;
 };
 
-static void iso_callback (struct urb *urb)
+static void iso_callback(struct urb *urb)
 {
 	struct iso_context	*ctx = urb->context;
 
@@ -1363,10 +1371,12 @@
 		ctx->errors += urb->error_count;
 	else if (urb->status != 0)
 		ctx->errors += urb->number_of_packets;
+	else if (urb->actual_length != urb->transfer_buffer_length)
+		ctx->errors++;
 
 	if (urb->status == 0 && ctx->count > (ctx->pending - 1)
 			&& !ctx->submit_error) {
-		int status = usb_submit_urb (urb, GFP_ATOMIC);
+		int status = usb_submit_urb(urb, GFP_ATOMIC);
 		switch (status) {
 		case 0:
 			goto done;
@@ -1388,13 +1398,13 @@
 			dev_err(&ctx->dev->intf->dev,
 				"iso test, %lu errors out of %lu\n",
 				ctx->errors, ctx->packet_count);
-		complete (&ctx->done);
+		complete(&ctx->done);
 	}
 done:
 	spin_unlock(&ctx->lock);
 }
 
-static struct urb *iso_alloc_urb (
+static struct urb *iso_alloc_urb(
 	struct usb_device	*udev,
 	int			pipe,
 	struct usb_endpoint_descriptor	*desc,
@@ -1410,7 +1420,7 @@
 	maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11));
 	packets = DIV_ROUND_UP(bytes, maxp);
 
-	urb = usb_alloc_urb (packets, GFP_KERNEL);
+	urb = usb_alloc_urb(packets, GFP_KERNEL);
 	if (!urb)
 		return urb;
 	urb->dev = udev;
@@ -1418,30 +1428,30 @@
 
 	urb->number_of_packets = packets;
 	urb->transfer_buffer_length = bytes;
-	urb->transfer_buffer = usb_alloc_coherent (udev, bytes, GFP_KERNEL,
+	urb->transfer_buffer = usb_alloc_coherent(udev, bytes, GFP_KERNEL,
 			&urb->transfer_dma);
 	if (!urb->transfer_buffer) {
-		usb_free_urb (urb);
+		usb_free_urb(urb);
 		return NULL;
 	}
-	memset (urb->transfer_buffer, 0, bytes);
+	memset(urb->transfer_buffer, 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);
+		urb->iso_frame_desc[i].length = min((unsigned) bytes, maxp);
 		bytes -= urb->iso_frame_desc[i].length;
 
 		urb->iso_frame_desc[i].offset = maxp * i;
 	}
 
 	urb->complete = iso_callback;
-	// urb->context = SET BY CALLER
+	/* urb->context = SET BY CALLER */
 	urb->interval = 1 << (desc->bInterval - 1);
 	urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
 	return urb;
 }
 
 static int
-test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
+test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
 		int pipe, struct usb_endpoint_descriptor *desc)
 {
 	struct iso_context	context;
@@ -1457,11 +1467,11 @@
 	memset(&context, 0, sizeof context);
 	context.count = param->iterations * param->sglen;
 	context.dev = dev;
-	init_completion (&context.done);
-	spin_lock_init (&context.lock);
+	init_completion(&context.done);
+	spin_lock_init(&context.lock);
 
-	memset (urbs, 0, sizeof urbs);
-	udev = testdev_to_usbdev (dev);
+	memset(urbs, 0, sizeof urbs);
+	udev = testdev_to_usbdev(dev);
 	dev_info(&dev->intf->dev,
 		"... iso period %d %sframes, wMaxPacket %04x\n",
 		1 << (desc->bInterval - 1),
@@ -1469,14 +1479,14 @@
 		le16_to_cpu(desc->wMaxPacketSize));
 
 	for (i = 0; i < param->sglen; i++) {
-		urbs [i] = iso_alloc_urb (udev, pipe, desc,
+		urbs[i] = iso_alloc_urb(udev, pipe, desc,
 				param->length);
-		if (!urbs [i]) {
+		if (!urbs[i]) {
 			status = -ENOMEM;
 			goto fail;
 		}
 		packets += urbs[i]->number_of_packets;
-		urbs [i]->context = &context;
+		urbs[i]->context = &context;
 	}
 	packets *= param->iterations;
 	dev_info(&dev->intf->dev,
@@ -1485,27 +1495,27 @@
 			/ ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
 		packets);
 
-	spin_lock_irq (&context.lock);
+	spin_lock_irq(&context.lock);
 	for (i = 0; i < param->sglen; i++) {
 		++context.pending;
-		status = usb_submit_urb (urbs [i], GFP_ATOMIC);
+		status = usb_submit_urb(urbs[i], GFP_ATOMIC);
 		if (status < 0) {
-			ERROR (dev, "submit iso[%d], error %d\n", i, status);
+			ERROR(dev, "submit iso[%d], error %d\n", i, status);
 			if (i == 0) {
-				spin_unlock_irq (&context.lock);
+				spin_unlock_irq(&context.lock);
 				goto fail;
 			}
 
-			simple_free_urb (urbs [i]);
+			simple_free_urb(urbs[i]);
 			urbs[i] = NULL;
 			context.pending--;
 			context.submit_error = 1;
 			break;
 		}
 	}
-	spin_unlock_irq (&context.lock);
+	spin_unlock_irq(&context.lock);
 
-	wait_for_completion (&context.done);
+	wait_for_completion(&context.done);
 
 	for (i = 0; i < param->sglen; i++) {
 		if (urbs[i])
@@ -1526,8 +1536,8 @@
 
 fail:
 	for (i = 0; i < param->sglen; i++) {
-		if (urbs [i])
-			simple_free_urb (urbs [i]);
+		if (urbs[i])
+			simple_free_urb(urbs[i]);
 	}
 	return status;
 }
@@ -1557,10 +1567,10 @@
 
 /* No BKL needed */
 static int
-usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
+usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
 {
-	struct usbtest_dev	*dev = usb_get_intfdata (intf);
-	struct usb_device	*udev = testdev_to_usbdev (dev);
+	struct usbtest_dev	*dev = usb_get_intfdata(intf);
+	struct usb_device	*udev = testdev_to_usbdev(dev);
 	struct usbtest_param	*param = buf;
 	int			retval = -EOPNOTSUPP;
 	struct urb		*urb;
@@ -1569,7 +1579,7 @@
 	struct timeval		start;
 	unsigned		i;
 
-	// FIXME USBDEVFS_CONNECTINFO doesn't say how fast the device is.
+	/* FIXME USBDEVFS_CONNECTINFO doesn't say how fast the device is. */
 
 	pattern = mod_pattern;
 
@@ -1595,9 +1605,9 @@
 			mutex_unlock(&dev->lock);
 			return -ENODEV;
 		}
-		res = set_altsetting (dev, dev->info->alt);
+		res = set_altsetting(dev, dev->info->alt);
 		if (res) {
-			dev_err (&intf->dev,
+			dev_err(&intf->dev,
 					"set altsetting to %d failed, %d\n",
 					dev->info->alt, res);
 			mutex_unlock(&dev->lock);
@@ -1614,7 +1624,7 @@
 	 * FIXME add more tests!  cancel requests, verify the data, control
 	 * queueing, concurrent read+write threads, and so on.
 	 */
-	do_gettimeofday (&start);
+	do_gettimeofday(&start);
 	switch (param->test_num) {
 
 	case 0:
@@ -1629,14 +1639,14 @@
 		dev_info(&intf->dev,
 				"TEST 1:  write %d bytes %u times\n",
 				param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
+		urb = simple_alloc_urb(udev, dev->out_pipe, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk sink (maybe accepts short writes)
+		/* FIRMWARE:  bulk sink (maybe accepts short writes) */
 		retval = simple_io(dev, urb, param->iterations, 0, 0, "test1");
-		simple_free_urb (urb);
+		simple_free_urb(urb);
 		break;
 	case 2:
 		if (dev->in_pipe == 0)
@@ -1644,14 +1654,14 @@
 		dev_info(&intf->dev,
 				"TEST 2:  read %d bytes %u times\n",
 				param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
+		urb = simple_alloc_urb(udev, dev->in_pipe, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk source (maybe generates short writes)
+		/* FIRMWARE:  bulk source (maybe generates short writes) */
 		retval = simple_io(dev, urb, param->iterations, 0, 0, "test2");
-		simple_free_urb (urb);
+		simple_free_urb(urb);
 		break;
 	case 3:
 		if (dev->out_pipe == 0 || param->vary == 0)
@@ -1659,15 +1669,15 @@
 		dev_info(&intf->dev,
 				"TEST 3:  write/%d 0..%d bytes %u times\n",
 				param->vary, param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
+		urb = simple_alloc_urb(udev, dev->out_pipe, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk sink (maybe accepts short writes)
+		/* FIRMWARE:  bulk sink (maybe accepts short writes) */
 		retval = simple_io(dev, urb, param->iterations, param->vary,
 					0, "test3");
-		simple_free_urb (urb);
+		simple_free_urb(urb);
 		break;
 	case 4:
 		if (dev->in_pipe == 0 || param->vary == 0)
@@ -1675,15 +1685,15 @@
 		dev_info(&intf->dev,
 				"TEST 4:  read/%d 0..%d bytes %u times\n",
 				param->vary, param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
+		urb = simple_alloc_urb(udev, dev->in_pipe, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk source (maybe generates short writes)
+		/* FIRMWARE:  bulk source (maybe generates short writes) */
 		retval = simple_io(dev, urb, param->iterations, param->vary,
 					0, "test4");
-		simple_free_urb (urb);
+		simple_free_urb(urb);
 		break;
 
 	/* Queued bulk I/O tests */
@@ -1694,15 +1704,15 @@
 			"TEST 5:  write %d sglists %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
-		sg = alloc_sglist (param->sglen, param->length, 0);
+		sg = alloc_sglist(param->sglen, param->length, 0);
 		if (!sg) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk sink (maybe accepts short writes)
+		/* FIRMWARE:  bulk sink (maybe accepts short writes) */
 		retval = perform_sglist(dev, param->iterations, dev->out_pipe,
 				&req, sg, param->sglen);
-		free_sglist (sg, param->sglen);
+		free_sglist(sg, param->sglen);
 		break;
 
 	case 6:
@@ -1712,15 +1722,15 @@
 			"TEST 6:  read %d sglists %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
-		sg = alloc_sglist (param->sglen, param->length, 0);
+		sg = alloc_sglist(param->sglen, param->length, 0);
 		if (!sg) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk source (maybe generates short writes)
+		/* FIRMWARE:  bulk source (maybe generates short writes) */
 		retval = perform_sglist(dev, param->iterations, dev->in_pipe,
 				&req, sg, param->sglen);
-		free_sglist (sg, param->sglen);
+		free_sglist(sg, param->sglen);
 		break;
 	case 7:
 		if (dev->out_pipe == 0 || param->sglen == 0 || param->vary == 0)
@@ -1729,15 +1739,15 @@
 			"TEST 7:  write/%d %d sglists %d entries 0..%d bytes\n",
 				param->vary, param->iterations,
 				param->sglen, param->length);
-		sg = alloc_sglist (param->sglen, param->length, param->vary);
+		sg = alloc_sglist(param->sglen, param->length, param->vary);
 		if (!sg) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk sink (maybe accepts short writes)
+		/* FIRMWARE:  bulk sink (maybe accepts short writes) */
 		retval = perform_sglist(dev, param->iterations, dev->out_pipe,
 				&req, sg, param->sglen);
-		free_sglist (sg, param->sglen);
+		free_sglist(sg, param->sglen);
 		break;
 	case 8:
 		if (dev->in_pipe == 0 || param->sglen == 0 || param->vary == 0)
@@ -1746,15 +1756,15 @@
 			"TEST 8:  read/%d %d sglists %d entries 0..%d bytes\n",
 				param->vary, param->iterations,
 				param->sglen, param->length);
-		sg = alloc_sglist (param->sglen, param->length, param->vary);
+		sg = alloc_sglist(param->sglen, param->length, param->vary);
 		if (!sg) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk source (maybe generates short writes)
+		/* FIRMWARE:  bulk source (maybe generates short writes) */
 		retval = perform_sglist(dev, param->iterations, dev->in_pipe,
 				&req, sg, param->sglen);
-		free_sglist (sg, param->sglen);
+		free_sglist(sg, param->sglen);
 		break;
 
 	/* non-queued sanity tests for control (chapter 9 subset) */
@@ -1764,7 +1774,7 @@
 			"TEST 9:  ch9 (subset) control tests, %d times\n",
 				param->iterations);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = ch9_postconfig (dev);
+			retval = ch9_postconfig(dev);
 		if (retval)
 			dev_err(&intf->dev, "ch9 subset failed, "
 					"iterations left %d\n", i);
@@ -1779,7 +1789,7 @@
 				"TEST 10:  queue %d control calls, %d times\n",
 				param->sglen,
 				param->iterations);
-		retval = test_ctrl_queue (dev, param);
+		retval = test_ctrl_queue(dev, param);
 		break;
 
 	/* simple non-queued unlinks (ring with one urb) */
@@ -1790,7 +1800,7 @@
 		dev_info(&intf->dev, "TEST 11:  unlink %d reads of %d\n",
 				param->iterations, param->length);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = unlink_simple (dev, dev->in_pipe,
+			retval = unlink_simple(dev, dev->in_pipe,
 						param->length);
 		if (retval)
 			dev_err(&intf->dev, "unlink reads failed %d, "
@@ -1803,7 +1813,7 @@
 		dev_info(&intf->dev, "TEST 12:  unlink %d writes of %d\n",
 				param->iterations, param->length);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = unlink_simple (dev, dev->out_pipe,
+			retval = unlink_simple(dev, dev->out_pipe,
 						param->length);
 		if (retval)
 			dev_err(&intf->dev, "unlink writes failed %d, "
@@ -1818,7 +1828,7 @@
 		dev_info(&intf->dev, "TEST 13:  set/clear %d halts\n",
 				param->iterations);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = halt_simple (dev);
+			retval = halt_simple(dev);
 
 		if (retval)
 			ERROR(dev, "halts failed, iterations left %d\n", i);
@@ -1844,8 +1854,8 @@
 			"TEST 15:  write %d iso, %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
-		// FIRMWARE:  iso sink
-		retval = test_iso_queue (dev, param,
+		/* FIRMWARE:  iso sink */
+		retval = test_iso_queue(dev, param,
 				dev->out_iso_pipe, dev->iso_out);
 		break;
 
@@ -1857,17 +1867,17 @@
 			"TEST 16:  read %d iso, %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
-		// FIRMWARE:  iso source
-		retval = test_iso_queue (dev, param,
+		/* FIRMWARE:  iso source */
+		retval = test_iso_queue(dev, param,
 				dev->in_iso_pipe, dev->iso_in);
 		break;
 
-	// FIXME unlink from queue (ring with N urbs)
+	/* FIXME unlink from queue (ring with N urbs) */
 
-	// FIXME scatterlist cancel (needs helper thread)
+	/* FIXME scatterlist cancel (needs helper thread) */
 
 	}
-	do_gettimeofday (&param->duration);
+	do_gettimeofday(&param->duration);
 	param->duration.tv_sec -= start.tv_sec;
 	param->duration.tv_usec -= start.tv_usec;
 	if (param->duration.tv_usec < 0) {
@@ -1880,22 +1890,22 @@
 
 /*-------------------------------------------------------------------------*/
 
-static unsigned force_interrupt = 0;
-module_param (force_interrupt, uint, 0);
-MODULE_PARM_DESC (force_interrupt, "0 = test default; else interrupt");
+static unsigned force_interrupt;
+module_param(force_interrupt, uint, 0);
+MODULE_PARM_DESC(force_interrupt, "0 = test default; else interrupt");
 
 #ifdef	GENERIC
 static unsigned short vendor;
 module_param(vendor, ushort, 0);
-MODULE_PARM_DESC (vendor, "vendor code (from usb-if)");
+MODULE_PARM_DESC(vendor, "vendor code (from usb-if)");
 
 static unsigned short product;
 module_param(product, ushort, 0);
-MODULE_PARM_DESC (product, "product code (from vendor)");
+MODULE_PARM_DESC(product, "product code (from vendor)");
 #endif
 
 static int
-usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
+usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device	*udev;
 	struct usbtest_dev	*dev;
@@ -1903,7 +1913,7 @@
 	char			*rtest, *wtest;
 	char			*irtest, *iwtest;
 
-	udev = interface_to_usbdev (intf);
+	udev = interface_to_usbdev(intf);
 
 #ifdef	GENERIC
 	/* specify devices by module parameters? */
@@ -1930,8 +1940,9 @@
 	dev->intf = intf;
 
 	/* cacheline-aligned scratch for i/o */
-	if ((dev->buf = kmalloc (TBUF_SIZE, GFP_KERNEL)) == NULL) {
-		kfree (dev);
+	dev->buf = kmalloc(TBUF_SIZE, GFP_KERNEL);
+	if (dev->buf == NULL) {
+		kfree(dev);
 		return -ENOMEM;
 	}
 
@@ -1943,18 +1954,18 @@
 	irtest = iwtest = "";
 	if (force_interrupt || udev->speed == USB_SPEED_LOW) {
 		if (info->ep_in) {
-			dev->in_pipe = usb_rcvintpipe (udev, info->ep_in);
+			dev->in_pipe = usb_rcvintpipe(udev, info->ep_in);
 			rtest = " intr-in";
 		}
 		if (info->ep_out) {
-			dev->out_pipe = usb_sndintpipe (udev, info->ep_out);
+			dev->out_pipe = usb_sndintpipe(udev, info->ep_out);
 			wtest = " intr-out";
 		}
 	} else {
 		if (info->autoconf) {
 			int status;
 
-			status = get_endpoints (dev, intf);
+			status = get_endpoints(dev, intf);
 			if (status < 0) {
 				WARNING(dev, "couldn't get endpoints, %d\n",
 						status);
@@ -1963,10 +1974,10 @@
 			/* may find bulk or ISO pipes */
 		} else {
 			if (info->ep_in)
-				dev->in_pipe = usb_rcvbulkpipe (udev,
+				dev->in_pipe = usb_rcvbulkpipe(udev,
 							info->ep_in);
 			if (info->ep_out)
-				dev->out_pipe = usb_sndbulkpipe (udev,
+				dev->out_pipe = usb_sndbulkpipe(udev,
 							info->ep_out);
 		}
 		if (dev->in_pipe)
@@ -1979,15 +1990,23 @@
 			iwtest = " iso-out";
 	}
 
-	usb_set_intfdata (intf, dev);
-	dev_info (&intf->dev, "%s\n", info->name);
-	dev_info (&intf->dev, "%s speed {control%s%s%s%s%s} tests%s\n",
+	usb_set_intfdata(intf, dev);
+	dev_info(&intf->dev, "%s\n", info->name);
+	dev_info(&intf->dev, "%s speed {control%s%s%s%s%s} tests%s\n",
 			({ char *tmp;
 			switch (udev->speed) {
-			case USB_SPEED_LOW: tmp = "low"; break;
-			case USB_SPEED_FULL: tmp = "full"; break;
-			case USB_SPEED_HIGH: tmp = "high"; break;
-			default: tmp = "unknown"; break;
+			case USB_SPEED_LOW:
+				tmp = "low";
+				break;
+			case USB_SPEED_FULL:
+				tmp = "full";
+				break;
+			case USB_SPEED_HIGH:
+				tmp = "high";
+				break;
+			default:
+				tmp = "unknown";
+				break;
 			}; tmp; }),
 			info->ctrl_out ? " in/out" : "",
 			rtest, wtest,
@@ -1996,24 +2015,24 @@
 	return 0;
 }
 
-static int usbtest_suspend (struct usb_interface *intf, pm_message_t message)
+static int usbtest_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	return 0;
 }
 
-static int usbtest_resume (struct usb_interface *intf)
+static int usbtest_resume(struct usb_interface *intf)
 {
 	return 0;
 }
 
 
-static void usbtest_disconnect (struct usb_interface *intf)
+static void usbtest_disconnect(struct usb_interface *intf)
 {
-	struct usbtest_dev	*dev = usb_get_intfdata (intf);
+	struct usbtest_dev	*dev = usb_get_intfdata(intf);
 
-	usb_set_intfdata (intf, NULL);
-	dev_dbg (&intf->dev, "disconnect\n");
-	kfree (dev);
+	usb_set_intfdata(intf, NULL);
+	dev_dbg(&intf->dev, "disconnect\n");
+	kfree(dev);
 }
 
 /* Basic testing only needs a device that can source or sink bulk traffic.
@@ -2050,9 +2069,9 @@
 	.ep_in		= 2,
 	.ep_out		= 2,
 	.alt		= 1,
-	.autoconf	= 1,		// iso and ctrl_out need autoconf
+	.autoconf	= 1,		/* iso and ctrl_out need autoconf */
 	.ctrl_out	= 1,
-	.iso		= 1,		// iso_ep's are #8 in/out
+	.iso		= 1,		/* iso_ep's are #8 in/out */
 };
 
 /* peripheral running Linux and 'zero.c' test firmware, or
@@ -2109,56 +2128,56 @@
 	 */
 
 	/* generic EZ-USB FX controller */
-	{ USB_DEVICE (0x0547, 0x2235),
+	{ USB_DEVICE(0x0547, 0x2235),
 		.driver_info = (unsigned long) &ez1_info,
-		},
+	},
 
 	/* CY3671 development board with EZ-USB FX */
-	{ USB_DEVICE (0x0547, 0x0080),
+	{ USB_DEVICE(0x0547, 0x0080),
 		.driver_info = (unsigned long) &ez1_info,
-		},
+	},
 
 	/* generic EZ-USB FX2 controller (or development board) */
-	{ USB_DEVICE (0x04b4, 0x8613),
+	{ USB_DEVICE(0x04b4, 0x8613),
 		.driver_info = (unsigned long) &ez2_info,
-		},
+	},
 
 	/* re-enumerated usb test device firmware */
-	{ USB_DEVICE (0xfff0, 0xfff0),
+	{ USB_DEVICE(0xfff0, 0xfff0),
 		.driver_info = (unsigned long) &fw_info,
-		},
+	},
 
 	/* "Gadget Zero" firmware runs under Linux */
-	{ USB_DEVICE (0x0525, 0xa4a0),
+	{ USB_DEVICE(0x0525, 0xa4a0),
 		.driver_info = (unsigned long) &gz_info,
-		},
+	},
 
 	/* so does a user-mode variant */
-	{ USB_DEVICE (0x0525, 0xa4a4),
+	{ USB_DEVICE(0x0525, 0xa4a4),
 		.driver_info = (unsigned long) &um_info,
-		},
+	},
 
 	/* ... and a user-mode variant that talks iso */
-	{ USB_DEVICE (0x0525, 0xa4a3),
+	{ USB_DEVICE(0x0525, 0xa4a3),
 		.driver_info = (unsigned long) &um2_info,
-		},
+	},
 
 #ifdef KEYSPAN_19Qi
 	/* Keyspan 19qi uses an21xx (original EZ-USB) */
-	// this does not coexist with the real Keyspan 19qi driver!
-	{ USB_DEVICE (0x06cd, 0x010b),
+	/* this does not coexist with the real Keyspan 19qi driver! */
+	{ USB_DEVICE(0x06cd, 0x010b),
 		.driver_info = (unsigned long) &ez1_info,
-		},
+	},
 #endif
 
 	/*-------------------------------------------------------------*/
 
 #ifdef IBOT2
 	/* iBOT2 makes a nice source of high speed bulk-in data */
-	// this does not coexist with a real iBOT2 driver!
-	{ USB_DEVICE (0x0b62, 0x0059),
+	/* this does not coexist with a real iBOT2 driver! */
+	{ USB_DEVICE(0x0b62, 0x0059),
 		.driver_info = (unsigned long) &ibot2_info,
-		},
+	},
 #endif
 
 	/*-------------------------------------------------------------*/
@@ -2172,7 +2191,7 @@
 
 	{ }
 };
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver usbtest_driver = {
 	.name =		"usbtest",
@@ -2186,22 +2205,22 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __init usbtest_init (void)
+static int __init usbtest_init(void)
 {
 #ifdef GENERIC
 	if (vendor)
 		pr_debug("params: vend=0x%04x prod=0x%04x\n", vendor, product);
 #endif
-	return usb_register (&usbtest_driver);
+	return usb_register(&usbtest_driver);
 }
-module_init (usbtest_init);
+module_init(usbtest_init);
 
-static void __exit usbtest_exit (void)
+static void __exit usbtest_exit(void)
 {
-	usb_deregister (&usbtest_driver);
+	usb_deregister(&usbtest_driver);
 }
-module_exit (usbtest_exit);
+module_exit(usbtest_exit);
 
-MODULE_DESCRIPTION ("USB Core/HCD Testing Driver");
-MODULE_LICENSE ("GPL");
+MODULE_DESCRIPTION("USB Core/HCD Testing Driver");
+MODULE_LICENSE("GPL");
 
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
new file mode 100644
index 0000000..719c618
--- /dev/null
+++ b/drivers/usb/misc/yurex.c
@@ -0,0 +1,563 @@
+/*
+ * Driver for Meywa-Denki & KAYAC YUREX
+ *
+ * Copyright (C) 2010 Tomoki Sekiyama (tomoki.sekiyama@gmail.com)
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+
+#define DRIVER_AUTHOR "Tomoki Sekiyama"
+#define DRIVER_DESC "Driver for Meywa-Denki & KAYAC YUREX"
+
+#define YUREX_VENDOR_ID		0x0c45
+#define YUREX_PRODUCT_ID	0x1010
+
+#define CMD_ACK		'!'
+#define CMD_ANIMATE	'A'
+#define CMD_COUNT	'C'
+#define CMD_LED		'L'
+#define CMD_READ	'R'
+#define CMD_SET		'S'
+#define CMD_VERSION	'V'
+#define CMD_EOF		0x0d
+#define CMD_PADDING	0xff
+
+#define YUREX_BUF_SIZE		8
+#define YUREX_WRITE_TIMEOUT	(HZ*2)
+
+/* table of devices that work with this driver */
+static struct usb_device_id yurex_table[] = {
+	{ USB_DEVICE(YUREX_VENDOR_ID, YUREX_PRODUCT_ID) },
+	{ }					/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, yurex_table);
+
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define YUREX_MINOR_BASE	0
+#else
+#define YUREX_MINOR_BASE	192
+#endif
+
+/* Structure to hold all of our device specific stuff */
+struct usb_yurex {
+	struct usb_device	*udev;
+	struct usb_interface	*interface;
+	__u8			int_in_endpointAddr;
+	struct urb		*urb;		/* URB for interrupt in */
+	unsigned char           *int_buffer;	/* buffer for intterupt in */
+	struct urb		*cntl_urb;	/* URB for control msg */
+	struct usb_ctrlrequest	*cntl_req;	/* req for control msg */
+	unsigned char		*cntl_buffer;	/* buffer for control msg */
+
+	struct kref		kref;
+	struct mutex		io_mutex;
+	struct fasync_struct	*async_queue;
+	wait_queue_head_t	waitq;
+
+	spinlock_t		lock;
+	__s64			bbu;		/* BBU from device */
+};
+#define to_yurex_dev(d) container_of(d, struct usb_yurex, kref)
+
+static struct usb_driver yurex_driver;
+static const struct file_operations yurex_fops;
+
+
+static void yurex_control_callback(struct urb *urb)
+{
+	struct usb_yurex *dev = urb->context;
+	int status = urb->status;
+
+	if (status) {
+		err("%s - control failed: %d\n", __func__, status);
+		wake_up_interruptible(&dev->waitq);
+		return;
+	}
+	/* on success, sender woken up by CMD_ACK int in, or timeout */
+}
+
+static void yurex_delete(struct kref *kref)
+{
+	struct usb_yurex *dev = to_yurex_dev(kref);
+
+	dbg("yurex_delete");
+
+	usb_put_dev(dev->udev);
+	if (dev->cntl_urb) {
+		usb_kill_urb(dev->cntl_urb);
+		if (dev->cntl_req)
+			usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
+				dev->cntl_req, dev->cntl_urb->setup_dma);
+		if (dev->cntl_buffer)
+			usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
+				dev->cntl_buffer, dev->cntl_urb->transfer_dma);
+		usb_free_urb(dev->cntl_urb);
+	}
+	if (dev->urb) {
+		usb_kill_urb(dev->urb);
+		if (dev->int_buffer)
+			usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
+				dev->int_buffer, dev->urb->transfer_dma);
+		usb_free_urb(dev->urb);
+	}
+	kfree(dev);
+}
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
+static struct usb_class_driver yurex_class = {
+	.name =		"yurex%d",
+	.fops =		&yurex_fops,
+	.minor_base =	YUREX_MINOR_BASE,
+};
+
+static void yurex_interrupt(struct urb *urb)
+{
+	struct usb_yurex *dev = urb->context;
+	unsigned char *buf = dev->int_buffer;
+	int status = urb->status;
+	unsigned long flags;
+	int retval, i;
+
+	switch (status) {
+	case 0: /*success*/
+		break;
+	case -EOVERFLOW:
+		err("%s - overflow with length %d, actual length is %d",
+		    __func__, YUREX_BUF_SIZE, dev->urb->actual_length);
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+	case -EILSEQ:
+		/* The device is terminated, clean up */
+		return;
+	default:
+		err("%s - unknown status received: %d", __func__, status);
+		goto exit;
+	}
+
+	/* handle received message */
+	switch (buf[0]) {
+	case CMD_COUNT:
+	case CMD_READ:
+		if (buf[6] == CMD_EOF) {
+			spin_lock_irqsave(&dev->lock, flags);
+			dev->bbu = 0;
+			for (i = 1; i < 6; i++) {
+				dev->bbu += buf[i];
+				if (i != 5)
+					dev->bbu <<= 8;
+			}
+			dbg("%s count: %lld", __func__, dev->bbu);
+			spin_unlock_irqrestore(&dev->lock, flags);
+
+			kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
+		}
+		else
+			dbg("data format error - no EOF");
+		break;
+	case CMD_ACK:
+		dbg("%s ack: %c", __func__, buf[1]);
+		wake_up_interruptible(&dev->waitq);
+		break;
+	}
+
+exit:
+	retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+	if (retval) {
+		err("%s - usb_submit_urb failed: %d",
+			__func__, retval);
+	}
+}
+
+static int yurex_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+	struct usb_yurex *dev;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	int retval = -ENOMEM;
+	int i;
+	DEFINE_WAIT(wait);
+
+	/* allocate memory for our device state and initialize it */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		err("Out of memory");
+		goto error;
+	}
+	kref_init(&dev->kref);
+	mutex_init(&dev->io_mutex);
+	spin_lock_init(&dev->lock);
+	init_waitqueue_head(&dev->waitq);
+
+	dev->udev = usb_get_dev(interface_to_usbdev(interface));
+	dev->interface = interface;
+
+	/* set up the endpoint information */
+	iface_desc = interface->cur_altsetting;
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (usb_endpoint_is_int_in(endpoint)) {
+			dev->int_in_endpointAddr = endpoint->bEndpointAddress;
+			break;
+		}
+	}
+	if (!dev->int_in_endpointAddr) {
+		retval = -ENODEV;
+		err("Could not find endpoints");
+		goto error;
+	}
+
+
+	/* allocate control URB */
+	dev->cntl_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->cntl_urb) {
+		err("Could not allocate control URB");
+		goto error;
+	}
+
+	/* allocate buffer for control req */
+	dev->cntl_req = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE,
+					   GFP_KERNEL,
+					   &dev->cntl_urb->setup_dma);
+	if (!dev->cntl_req) {
+		err("Could not allocate cntl_req");
+		goto error;
+	}
+
+	/* allocate buffer for control msg */
+	dev->cntl_buffer = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE,
+					      GFP_KERNEL,
+					      &dev->cntl_urb->transfer_dma);
+	if (!dev->cntl_buffer) {
+		err("Could not allocate cntl_buffer");
+		goto error;
+	}
+
+	/* configure control URB */
+	dev->cntl_req->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS |
+				      USB_RECIP_INTERFACE;
+	dev->cntl_req->bRequest	= HID_REQ_SET_REPORT;
+	dev->cntl_req->wValue	= cpu_to_le16((HID_OUTPUT_REPORT + 1) << 8);
+	dev->cntl_req->wIndex	= cpu_to_le16(iface_desc->desc.bInterfaceNumber);
+	dev->cntl_req->wLength	= cpu_to_le16(YUREX_BUF_SIZE);
+
+	usb_fill_control_urb(dev->cntl_urb, dev->udev,
+			     usb_sndctrlpipe(dev->udev, 0),
+			     (void *)dev->cntl_req, dev->cntl_buffer,
+			     YUREX_BUF_SIZE, yurex_control_callback, dev);
+	dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+
+	/* allocate interrupt URB */
+	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->urb) {
+		err("Could not allocate URB");
+		goto error;
+	}
+
+	/* allocate buffer for interrupt in */
+	dev->int_buffer = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE,
+					GFP_KERNEL, &dev->urb->transfer_dma);
+	if (!dev->int_buffer) {
+		err("Could not allocate int_buffer");
+		goto error;
+	}
+
+	/* configure interrupt URB */
+	usb_fill_int_urb(dev->urb, dev->udev,
+			 usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr),
+			 dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt,
+			 dev, 1);
+	dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	if (usb_submit_urb(dev->urb, GFP_KERNEL)) {
+		retval = -EIO;
+		err("Could not submitting URB");
+		goto error;
+	}
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, dev);
+
+	/* we can register the device now, as it is ready */
+	retval = usb_register_dev(interface, &yurex_class);
+	if (retval) {
+		err("Not able to get a minor for this device.");
+		usb_set_intfdata(interface, NULL);
+		goto error;
+	}
+
+	dev->bbu = -1;
+
+	dev_info(&interface->dev,
+		 "USB YUREX device now attached to Yurex #%d\n",
+		 interface->minor);
+
+	return 0;
+
+error:
+	if (dev)
+		/* this frees allocated memory */
+		kref_put(&dev->kref, yurex_delete);
+	return retval;
+}
+
+static void yurex_disconnect(struct usb_interface *interface)
+{
+	struct usb_yurex *dev;
+	int minor = interface->minor;
+
+	dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	/* give back our minor */
+	usb_deregister_dev(interface, &yurex_class);
+
+	/* prevent more I/O from starting */
+	mutex_lock(&dev->io_mutex);
+	dev->interface = NULL;
+	mutex_unlock(&dev->io_mutex);
+
+	/* wakeup waiters */
+	kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
+	wake_up_interruptible(&dev->waitq);
+
+	/* decrement our usage count */
+	kref_put(&dev->kref, yurex_delete);
+
+	dev_info(&interface->dev, "USB YUREX #%d now disconnected\n", minor);
+}
+
+static struct usb_driver yurex_driver = {
+	.name =		"yurex",
+	.probe =	yurex_probe,
+	.disconnect =	yurex_disconnect,
+	.id_table =	yurex_table,
+};
+
+
+static int yurex_fasync(int fd, struct file *file, int on)
+{
+	struct usb_yurex *dev;
+
+	dev = (struct usb_yurex *)file->private_data;
+	return fasync_helper(fd, file, on, &dev->async_queue);
+}
+
+static int yurex_open(struct inode *inode, struct file *file)
+{
+	struct usb_yurex *dev;
+	struct usb_interface *interface;
+	int subminor;
+	int retval = 0;
+
+	subminor = iminor(inode);
+
+	interface = usb_find_interface(&yurex_driver, subminor);
+	if (!interface) {
+		err("%s - error, can't find device for minor %d",
+		    __func__, subminor);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	dev = usb_get_intfdata(interface);
+	if (!dev) {
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	/* increment our usage count for the device */
+	kref_get(&dev->kref);
+
+	/* save our object in the file's private structure */
+	mutex_lock(&dev->io_mutex);
+	file->private_data = dev;
+	mutex_unlock(&dev->io_mutex);
+
+exit:
+	return retval;
+}
+
+static int yurex_release(struct inode *inode, struct file *file)
+{
+	struct usb_yurex *dev;
+
+	dev = (struct usb_yurex *)file->private_data;
+	if (dev == NULL)
+		return -ENODEV;
+
+	yurex_fasync(-1, file, 0);
+
+	/* decrement the count on our device */
+	kref_put(&dev->kref, yurex_delete);
+	return 0;
+}
+
+static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct usb_yurex *dev;
+	int retval = 0;
+	int bytes_read = 0;
+	char in_buffer[20];
+	unsigned long flags;
+
+	dev = (struct usb_yurex *)file->private_data;
+
+	mutex_lock(&dev->io_mutex);
+	if (!dev->interface) {		/* already disconnected */
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	spin_lock_irqsave(&dev->lock, flags);
+	bytes_read = snprintf(in_buffer, 20, "%lld\n", dev->bbu);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	if (*ppos < bytes_read) {
+		if (copy_to_user(buffer, in_buffer + *ppos, bytes_read - *ppos))
+			retval = -EFAULT;
+		else {
+			retval = bytes_read - *ppos;
+			*ppos += bytes_read;
+		}
+	}
+
+exit:
+	mutex_unlock(&dev->io_mutex);
+	return retval;
+}
+
+static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
+{
+	struct usb_yurex *dev;
+	int i, set = 0, retval = 0;
+	char buffer[16];
+	char *data = buffer;
+	unsigned long long c, c2 = 0;
+	signed long timeout = 0;
+	DEFINE_WAIT(wait);
+
+	count = min(sizeof(buffer), count);
+	dev = (struct usb_yurex *)file->private_data;
+
+	/* verify that we actually have some data to write */
+	if (count == 0)
+		goto error;
+
+	mutex_lock(&dev->io_mutex);
+	if (!dev->interface) {		/* alreaday disconnected */
+		mutex_unlock(&dev->io_mutex);
+		retval = -ENODEV;
+		goto error;
+	}
+
+	if (copy_from_user(buffer, user_buffer, count)) {
+		mutex_unlock(&dev->io_mutex);
+		retval = -EFAULT;
+		goto error;
+	}
+	memset(dev->cntl_buffer, CMD_PADDING, YUREX_BUF_SIZE);
+
+	switch (buffer[0]) {
+	case CMD_ANIMATE:
+	case CMD_LED:
+		dev->cntl_buffer[0] = buffer[0];
+		dev->cntl_buffer[1] = buffer[1];
+		dev->cntl_buffer[2] = CMD_EOF;
+		break;
+	case CMD_READ:
+	case CMD_VERSION:
+		dev->cntl_buffer[0] = buffer[0];
+		dev->cntl_buffer[1] = 0x00;
+		dev->cntl_buffer[2] = CMD_EOF;
+		break;
+	case CMD_SET:
+		data++;
+		/* FALL THROUGH */
+	case '0' ... '9':
+		set = 1;
+		c = c2 = simple_strtoull(data, NULL, 0);
+		dev->cntl_buffer[0] = CMD_SET;
+		for (i = 1; i < 6; i++) {
+			dev->cntl_buffer[i] = (c>>32) & 0xff;
+			c <<= 8;
+		}
+		buffer[6] = CMD_EOF;
+		break;
+	default:
+		mutex_unlock(&dev->io_mutex);
+		return -EINVAL;
+	}
+
+	/* send the data as the control msg */
+	prepare_to_wait(&dev->waitq, &wait, TASK_INTERRUPTIBLE);
+	dbg("%s - submit %c", __func__, dev->cntl_buffer[0]);
+	retval = usb_submit_urb(dev->cntl_urb, GFP_KERNEL);
+	if (retval >= 0)
+		timeout = schedule_timeout(YUREX_WRITE_TIMEOUT);
+	finish_wait(&dev->waitq, &wait);
+
+	mutex_unlock(&dev->io_mutex);
+
+	if (retval < 0) {
+		err("%s - failed to send bulk msg, error %d", __func__, retval);
+		goto error;
+	}
+	if (set && timeout)
+		dev->bbu = c2;
+	return timeout ? count : -EIO;
+
+error:
+	return retval;
+}
+
+static const struct file_operations yurex_fops = {
+	.owner =	THIS_MODULE,
+	.read =		yurex_read,
+	.write =	yurex_write,
+	.open =		yurex_open,
+	.release =	yurex_release,
+	.fasync	=	yurex_fasync,
+};
+
+
+static int __init usb_yurex_init(void)
+{
+	int result;
+
+	/* register this driver with the USB subsystem */
+	result = usb_register(&yurex_driver);
+	if (result)
+		err("usb_register failed. Error number %d", result);
+
+	return result;
+}
+
+static void __exit usb_yurex_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&yurex_driver);
+}
+
+module_init(usb_yurex_init);
+module_exit(usb_yurex_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
index 384b198..8ed24ab 100644
--- a/drivers/usb/mon/Makefile
+++ b/drivers/usb/mon/Makefile
@@ -2,6 +2,6 @@
 # Makefile for USB monitor
 #
 
-usbmon-objs	:= mon_main.o mon_stat.o mon_text.o mon_bin.o
+usbmon-y := mon_main.o mon_stat.o mon_text.o mon_bin.o
 
 obj-$(CONFIG_USB_MON)	+= usbmon.o
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index cfd38ed..341a37a 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -45,6 +45,9 @@
 comment "DaVinci 35x and 644x USB support"
 	depends on USB_MUSB_HDRC && ARCH_DAVINCI_DMx
 
+comment "DA8xx/OMAP-L1x USB support"
+	depends on USB_MUSB_HDRC && ARCH_DAVINCI_DA8XX
+
 comment "OMAP 243x high speed USB support"
 	depends on USB_MUSB_HDRC && ARCH_OMAP2430
 
@@ -57,6 +60,17 @@
 comment "Blackfin high speed USB Support"
 	depends on USB_MUSB_HDRC && ((BF54x && !BF544) || (BF52x && !BF522 && !BF523))
 
+config USB_MUSB_AM35X
+	bool
+	depends on USB_MUSB_HDRC && !ARCH_OMAP2430 && !ARCH_OMAP4
+	select NOP_USB_XCEIV
+	default MACH_OMAP3517EVM
+	help
+	  Select this option if your platform is based on AM35x. As
+	  AM35x has an updated MUSB with CPPI4.1 DMA so this config
+	  is introduced to differentiate musb ip between OMAP3x and
+	  AM35x platforms.
+
 config USB_TUSB6010
 	boolean "TUSB 6010 support"
 	depends on USB_MUSB_HDRC && !USB_MUSB_SOC
@@ -144,7 +158,7 @@
 config MUSB_PIO_ONLY
 	bool 'Disable DMA (always use PIO)'
 	depends on USB_MUSB_HDRC
-	default y if USB_TUSB6010
+	default USB_TUSB6010 || ARCH_DAVINCI_DA8XX || USB_MUSB_AM35X
 	help
 	  All data is copied between memory and FIFO by the CPU.
 	  DMA controllers are ignored.
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 9705f71..ce164e8 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -2,49 +2,27 @@
 # for USB OTG silicon based on Mentor Graphics INVENTRA designs
 #
 
-musb_hdrc-objs := musb_core.o
+ccflags-$(CONFIG_USB_MUSB_DEBUG) := -DDEBUG
 
-obj-$(CONFIG_USB_MUSB_HDRC)	+= musb_hdrc.o
+obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o
 
-ifeq ($(CONFIG_ARCH_DAVINCI_DMx),y)
-	musb_hdrc-objs	+= davinci.o
+musb_hdrc-y := musb_core.o
+
+musb_hdrc-$(CONFIG_ARCH_DAVINCI_DMx)		+= davinci.o
+musb_hdrc-$(CONFIG_ARCH_DAVINCI_DA8XX)		+= da8xx.o
+musb_hdrc-$(CONFIG_USB_TUSB6010)		+= tusb6010.o
+musb_hdrc-$(CONFIG_ARCH_OMAP2430)		+= omap2430.o
+ifeq ($(CONFIG_USB_MUSB_AM35X),y)
+	musb_hdrc-$(CONFIG_ARCH_OMAP3430)	+= am35x.o
+else
+	musb_hdrc-$(CONFIG_ARCH_OMAP3430)	+= omap2430.o
 endif
-
-ifeq ($(CONFIG_USB_TUSB6010),y)
-	musb_hdrc-objs	+= tusb6010.o
-endif
-
-ifeq ($(CONFIG_ARCH_OMAP2430),y)
-	musb_hdrc-objs	+= omap2430.o
-endif
-
-ifeq ($(CONFIG_ARCH_OMAP3430),y)
-	musb_hdrc-objs	+= omap2430.o
-endif
-
-ifeq ($(CONFIG_ARCH_OMAP4),y)
-	musb_hdrc-objs  += omap2430.o
-endif
-
-ifeq ($(CONFIG_BF54x),y)
-	musb_hdrc-objs	+= blackfin.o
-endif
-
-ifeq ($(CONFIG_BF52x),y)
-	musb_hdrc-objs	+= blackfin.o
-endif
-
-ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y)
-	musb_hdrc-objs		+= musb_gadget_ep0.o musb_gadget.o
-endif
-
-ifeq ($(CONFIG_USB_MUSB_HDRC_HCD),y)
-	musb_hdrc-objs		+= musb_virthub.o musb_host.o
-endif
-
-ifeq ($(CONFIG_DEBUG_FS),y)
-	musb_hdrc-objs		+= musb_debugfs.o
-endif
+musb_hdrc-$(CONFIG_ARCH_OMAP4)			+= omap2430.o
+musb_hdrc-$(CONFIG_BF54x)			+= blackfin.o
+musb_hdrc-$(CONFIG_BF52x)			+= blackfin.o
+musb_hdrc-$(CONFIG_USB_GADGET_MUSB_HDRC)	+= musb_gadget_ep0.o musb_gadget.o
+musb_hdrc-$(CONFIG_USB_MUSB_HDRC_HCD)		+= musb_virthub.o musb_host.o
+musb_hdrc-$(CONFIG_DEBUG_FS)			+= musb_debugfs.o
 
 # the kconfig must guarantee that only one of the
 # possible I/O schemes will be enabled at a time ...
@@ -54,26 +32,17 @@
 ifneq ($(CONFIG_MUSB_PIO_ONLY),y)
 
   ifeq ($(CONFIG_USB_INVENTRA_DMA),y)
-    musb_hdrc-objs		+= musbhsdma.o
+    musb_hdrc-y			+= musbhsdma.o
 
   else
     ifeq ($(CONFIG_USB_TI_CPPI_DMA),y)
-      musb_hdrc-objs		+= cppi_dma.o
+      musb_hdrc-y		+= cppi_dma.o
 
     else
       ifeq ($(CONFIG_USB_TUSB_OMAP_DMA),y)
-        musb_hdrc-objs		+= tusb6010_omap.o
+	musb_hdrc-y		+= tusb6010_omap.o
 
       endif
     endif
   endif
 endif
-
-
-################################################################################
-
-# Debugging
-
-ifeq ($(CONFIG_USB_MUSB_DEBUG),y)
-	EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
new file mode 100644
index 0000000..b0aabf3
--- /dev/null
+++ b/drivers/usb/musb/am35x.c
@@ -0,0 +1,524 @@
+/*
+ * Texas Instruments AM35x "glue layer"
+ *
+ * Copyright (c) 2010, by Texas Instruments
+ *
+ * Based on the DA8xx "glue layer" code.
+ * Copyright (c) 2008-2009, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can 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 Inventra Controller Driver for Linux is distributed in
+ * the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Inventra Controller Driver for Linux ; 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/clk.h>
+#include <linux/io.h>
+
+#include <plat/control.h>
+#include <plat/usb.h>
+
+#include "musb_core.h"
+
+/*
+ * AM35x specific definitions
+ */
+/* USB 2.0 OTG module registers */
+#define USB_REVISION_REG	0x00
+#define USB_CTRL_REG		0x04
+#define USB_STAT_REG		0x08
+#define USB_EMULATION_REG	0x0c
+/* 0x10 Reserved */
+#define USB_AUTOREQ_REG		0x14
+#define USB_SRP_FIX_TIME_REG	0x18
+#define USB_TEARDOWN_REG	0x1c
+#define EP_INTR_SRC_REG		0x20
+#define EP_INTR_SRC_SET_REG	0x24
+#define EP_INTR_SRC_CLEAR_REG	0x28
+#define EP_INTR_MASK_REG	0x2c
+#define EP_INTR_MASK_SET_REG	0x30
+#define EP_INTR_MASK_CLEAR_REG	0x34
+#define EP_INTR_SRC_MASKED_REG	0x38
+#define CORE_INTR_SRC_REG	0x40
+#define CORE_INTR_SRC_SET_REG	0x44
+#define CORE_INTR_SRC_CLEAR_REG	0x48
+#define CORE_INTR_MASK_REG	0x4c
+#define CORE_INTR_MASK_SET_REG	0x50
+#define CORE_INTR_MASK_CLEAR_REG 0x54
+#define CORE_INTR_SRC_MASKED_REG 0x58
+/* 0x5c Reserved */
+#define USB_END_OF_INTR_REG	0x60
+
+/* Control register bits */
+#define AM35X_SOFT_RESET_MASK	1
+
+/* USB interrupt register bits */
+#define AM35X_INTR_USB_SHIFT	16
+#define AM35X_INTR_USB_MASK	(0x1ff << AM35X_INTR_USB_SHIFT)
+#define AM35X_INTR_DRVVBUS	0x100
+#define AM35X_INTR_RX_SHIFT	16
+#define AM35X_INTR_TX_SHIFT	0
+#define AM35X_TX_EP_MASK	0xffff		/* EP0 + 15 Tx EPs */
+#define AM35X_RX_EP_MASK	0xfffe		/* 15 Rx EPs */
+#define AM35X_TX_INTR_MASK	(AM35X_TX_EP_MASK << AM35X_INTR_TX_SHIFT)
+#define AM35X_RX_INTR_MASK	(AM35X_RX_EP_MASK << AM35X_INTR_RX_SHIFT)
+
+#define USB_MENTOR_CORE_OFFSET	0x400
+
+static inline void phy_on(void)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(100);
+	u32 devconf2;
+
+	/*
+	 * 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);
+
+	DBG(1, "Waiting for PHY clock good...\n");
+	while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
+			& CONF2_PHYCLKGD)) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout)) {
+			DBG(1, "musb PHY clock good timed out\n");
+			break;
+		}
+	}
+}
+
+static inline void phy_off(void)
+{
+	u32 devconf2;
+
+	/*
+	 * 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);
+}
+
+/*
+ * musb_platform_enable - enable interrupts
+ */
+void musb_platform_enable(struct musb *musb)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+	u32 epmask;
+
+	/* Workaround: setup IRQs through both register sets. */
+	epmask = ((musb->epmask & AM35X_TX_EP_MASK) << AM35X_INTR_TX_SHIFT) |
+	       ((musb->epmask & AM35X_RX_EP_MASK) << AM35X_INTR_RX_SHIFT);
+
+	musb_writel(reg_base, EP_INTR_MASK_SET_REG, epmask);
+	musb_writel(reg_base, CORE_INTR_MASK_SET_REG, AM35X_INTR_USB_MASK);
+
+	/* Force the DRVVBUS IRQ so we can start polling for ID change. */
+	if (is_otg_enabled(musb))
+		musb_writel(reg_base, CORE_INTR_SRC_SET_REG,
+			    AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT);
+}
+
+/*
+ * musb_platform_disable - disable HDRC and flush interrupts
+ */
+void musb_platform_disable(struct musb *musb)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+
+	musb_writel(reg_base, CORE_INTR_MASK_CLEAR_REG, AM35X_INTR_USB_MASK);
+	musb_writel(reg_base, EP_INTR_MASK_CLEAR_REG,
+			 AM35X_TX_INTR_MASK | AM35X_RX_INTR_MASK);
+	musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+	musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
+}
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+#define portstate(stmt)		stmt
+#else
+#define portstate(stmt)
+#endif
+
+static void am35x_set_vbus(struct musb *musb, int is_on)
+{
+	WARN_ON(is_on && is_peripheral_active(musb));
+}
+
+#define	POLL_SECONDS	2
+
+static struct timer_list otg_workaround;
+
+static void otg_timer(unsigned long _musb)
+{
+	struct musb		*musb = (void *)_musb;
+	void __iomem		*mregs = musb->mregs;
+	u8			devctl;
+	unsigned long		flags;
+
+	/*
+	 * We poll because AM35x's won't expose several OTG-critical
+	 * status change events (from the transceiver) otherwise.
+	 */
+	devctl = musb_readb(mregs, MUSB_DEVCTL);
+	DBG(7, "Poll devctl %02x (%s)\n", devctl, otg_state_string(musb));
+
+	spin_lock_irqsave(&musb->lock, flags);
+	switch (musb->xceiv->state) {
+	case OTG_STATE_A_WAIT_BCON:
+		devctl &= ~MUSB_DEVCTL_SESSION;
+		musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+		if (devctl & MUSB_DEVCTL_BDEVICE) {
+			musb->xceiv->state = OTG_STATE_B_IDLE;
+			MUSB_DEV_MODE(musb);
+		} else {
+			musb->xceiv->state = OTG_STATE_A_IDLE;
+			MUSB_HST_MODE(musb);
+		}
+		break;
+	case OTG_STATE_A_WAIT_VFALL:
+		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+		musb_writel(musb->ctrl_base, CORE_INTR_SRC_SET_REG,
+			    MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT);
+		break;
+	case OTG_STATE_B_IDLE:
+		if (!is_peripheral_enabled(musb))
+			break;
+
+		devctl = musb_readb(mregs, MUSB_DEVCTL);
+		if (devctl & MUSB_DEVCTL_BDEVICE)
+			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+		else
+			musb->xceiv->state = OTG_STATE_A_IDLE;
+		break;
+	default:
+		break;
+	}
+	spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+{
+	static unsigned long last_timer;
+
+	if (!is_otg_enabled(musb))
+		return;
+
+	if (timeout == 0)
+		timeout = jiffies + msecs_to_jiffies(3);
+
+	/* Never idle if active, or when VBUS timeout is not set as host */
+	if (musb->is_active || (musb->a_wait_bcon == 0 &&
+				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+		DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
+		del_timer(&otg_workaround);
+		last_timer = jiffies;
+		return;
+	}
+
+	if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) {
+		DBG(4, "Longer idle timer already pending, ignoring...\n");
+		return;
+	}
+	last_timer = timeout;
+
+	DBG(4, "%s inactive, starting idle timer for %u ms\n",
+	    otg_state_string(musb), jiffies_to_msecs(timeout - jiffies));
+	mod_timer(&otg_workaround, timeout);
+}
+
+static irqreturn_t am35x_interrupt(int irq, void *hci)
+{
+	struct musb  *musb = hci;
+	void __iomem *reg_base = musb->ctrl_base;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+	u32 epintr, usbintr, lvl_intr;
+
+	spin_lock_irqsave(&musb->lock, flags);
+
+	/* Get endpoint interrupts */
+	epintr = musb_readl(reg_base, EP_INTR_SRC_MASKED_REG);
+
+	if (epintr) {
+		musb_writel(reg_base, EP_INTR_SRC_CLEAR_REG, epintr);
+
+		musb->int_rx =
+			(epintr & AM35X_RX_INTR_MASK) >> AM35X_INTR_RX_SHIFT;
+		musb->int_tx =
+			(epintr & AM35X_TX_INTR_MASK) >> AM35X_INTR_TX_SHIFT;
+	}
+
+	/* Get usb core interrupts */
+	usbintr = musb_readl(reg_base, CORE_INTR_SRC_MASKED_REG);
+	if (!usbintr && !epintr)
+		goto eoi;
+
+	if (usbintr) {
+		musb_writel(reg_base, CORE_INTR_SRC_CLEAR_REG, usbintr);
+
+		musb->int_usb =
+			(usbintr & AM35X_INTR_USB_MASK) >> AM35X_INTR_USB_SHIFT;
+	}
+	/*
+	 * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
+	 * AM35x's missing ID change IRQ.  We need an ID change IRQ to
+	 * switch appropriately between halves of the OTG state machine.
+	 * Managing DEVCTL.SESSION per Mentor docs requires that we know its
+	 * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
+	 * Also, DRVVBUS pulses for SRP (but not at 5V) ...
+	 */
+	if (usbintr & (AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT)) {
+		int drvvbus = musb_readl(reg_base, USB_STAT_REG);
+		void __iomem *mregs = musb->mregs;
+		u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
+		int err;
+
+		err = is_host_enabled(musb) && (musb->int_usb &
+						MUSB_INTR_VBUSERROR);
+		if (err) {
+			/*
+			 * The Mentor core doesn't debounce VBUS as needed
+			 * to cope with device connect current spikes. This
+			 * means it's not uncommon for bus-powered devices
+			 * to get VBUS errors during enumeration.
+			 *
+			 * This is a workaround, but newer RTL from Mentor
+			 * seems to allow a better one: "re"-starting sessions
+			 * without waiting for VBUS to stop registering in
+			 * devctl.
+			 */
+			musb->int_usb &= ~MUSB_INTR_VBUSERROR;
+			musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+			WARNING("VBUS error workaround (delay coming)\n");
+		} else if (is_host_enabled(musb) && drvvbus) {
+			MUSB_HST_MODE(musb);
+			musb->xceiv->default_a = 1;
+			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+			portstate(musb->port1_status |= USB_PORT_STAT_POWER);
+			del_timer(&otg_workaround);
+		} else {
+			musb->is_active = 0;
+			MUSB_DEV_MODE(musb);
+			musb->xceiv->default_a = 0;
+			musb->xceiv->state = OTG_STATE_B_IDLE;
+			portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
+		}
+
+		/* NOTE: this must complete power-on within 100 ms. */
+		DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
+				drvvbus ? "on" : "off",
+				otg_state_string(musb),
+				err ? " ERROR" : "",
+				devctl);
+		ret = IRQ_HANDLED;
+	}
+
+	if (musb->int_tx || musb->int_rx || musb->int_usb)
+		ret |= musb_interrupt(musb);
+
+eoi:
+	/* EOI needs to be written for the IRQ to be re-asserted. */
+	if (ret == IRQ_HANDLED || epintr || usbintr) {
+		/* clear level interrupt */
+		lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+		lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
+		omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
+		/* write EOI */
+		musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
+	}
+
+	/* Poll for ID change */
+	if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
+		mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+
+	spin_unlock_irqrestore(&musb->lock, flags);
+
+	return ret;
+}
+
+int musb_platform_set_mode(struct musb *musb, 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:
+		DBG(2, "Trying to set unsupported mode %u\n", musb_mode);
+	}
+
+	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+	return 0;
+}
+
+int __init musb_platform_init(struct musb *musb, void *board_data)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+	u32 rev, lvl_intr, sw_reset;
+	int status;
+
+	musb->mregs += USB_MENTOR_CORE_OFFSET;
+
+	clk_enable(musb->clock);
+	DBG(2, "musb->clock=%lud\n", clk_get_rate(musb->clock));
+
+	musb->phy_clock = clk_get(musb->controller, "fck");
+	if (IS_ERR(musb->phy_clock)) {
+		status = PTR_ERR(musb->phy_clock);
+		goto exit0;
+	}
+	clk_enable(musb->phy_clock);
+	DBG(2, "musb->phy_clock=%lud\n", clk_get_rate(musb->phy_clock));
+
+	/* Returns zero if e.g. not clocked */
+	rev = musb_readl(reg_base, USB_REVISION_REG);
+	if (!rev) {
+		status = -ENODEV;
+		goto exit1;
+	}
+
+	usb_nop_xceiv_register();
+	musb->xceiv = otg_get_transceiver();
+	if (!musb->xceiv) {
+		status = -ENODEV;
+		goto exit1;
+	}
+
+	if (is_host_enabled(musb))
+		setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
+
+	musb->board_set_vbus = am35x_set_vbus;
+
+	/* Global reset */
+	sw_reset = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+
+	sw_reset |= AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
+
+	sw_reset &= ~AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
+
+	/* Reset the controller */
+	musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK);
+
+	/* Start the on-chip PHY and its PLL. */
+	phy_on();
+
+	msleep(5);
+
+	musb->isr = am35x_interrupt;
+
+	/* clear level interrupt */
+	lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+	lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
+	omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
+	return 0;
+exit1:
+	clk_disable(musb->phy_clock);
+	clk_put(musb->phy_clock);
+exit0:
+	clk_disable(musb->clock);
+	return status;
+}
+
+int musb_platform_exit(struct musb *musb)
+{
+	if (is_host_enabled(musb))
+		del_timer_sync(&otg_workaround);
+
+	phy_off();
+
+	otg_put_transceiver(musb->xceiv);
+	usb_nop_xceiv_unregister();
+
+	clk_disable(musb->clock);
+
+	clk_disable(musb->phy_clock);
+	clk_put(musb->phy_clock);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+void musb_platform_save_context(struct musb *musb,
+	struct musb_context_registers *musb_context)
+{
+	phy_off();
+}
+
+void musb_platform_restore_context(struct musb *musb,
+	struct musb_context_registers *musb_context)
+{
+	phy_on();
+}
+#endif
+
+/* AM35x supports only 32bit read operation */
+void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
+{
+	void __iomem *fifo = hw_ep->fifo;
+	u32		val;
+	int		i;
+
+	/* Read for 32bit-aligned destination address */
+	if (likely((0x03 & (unsigned long) dst) == 0) && len >= 4) {
+		readsl(fifo, dst, len >> 2);
+		dst += len & ~0x03;
+		len &= 0x03;
+	}
+	/*
+	 * Now read the remaining 1 to 3 byte or complete length if
+	 * unaligned address.
+	 */
+	if (len > 4) {
+		for (i = 0; i < (len >> 2); i++) {
+			*(u32 *) dst = musb_readl(fifo, 0);
+			dst += 4;
+		}
+		len &= 0x03;
+	}
+	if (len > 0) {
+		val = musb_readl(fifo, 0);
+		memcpy(dst, &val, len);
+	}
+}
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index b611420..611a9d2 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -342,8 +342,10 @@
 
 	usb_nop_xceiv_register();
 	musb->xceiv = otg_get_transceiver();
-	if (!musb->xceiv)
+	if (!musb->xceiv) {
+		gpio_free(musb->config->gpio_vrsel);
 		return -ENODEV;
+	}
 
 	if (ANOMALY_05000346) {
 		bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
@@ -394,8 +396,9 @@
 
 int musb_platform_exit(struct musb *musb)
 {
-
 	gpio_free(musb->config->gpio_vrsel);
 
+	otg_put_transceiver(musb->xceiv);
+	usb_nop_xceiv_unregister();
 	return 0;
 }
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index 59dc3d3..f5a65ff 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -322,6 +322,7 @@
 				index, transmit ? 'T' : 'R', cppi_ch);
 	cppi_ch->hw_ep = ep;
 	cppi_ch->channel.status = MUSB_DMA_STATUS_FREE;
+	cppi_ch->channel.max_len = 0x7fffffff;
 
 	DBG(4, "Allocate CPPI%d %cX\n", index, transmit ? 'T' : 'R');
 	return &cppi_ch->channel;
@@ -1155,7 +1156,7 @@
 	struct musb_hw_ep	*hw_ep = NULL;
 	u32			rx, tx;
 	int			i, index;
-	unsigned long		flags;
+	unsigned long		uninitialized_var(flags);
 
 	cppi = container_of(musb->dma_controller, struct cppi, controller);
 	if (cppi->irq)
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
new file mode 100644
index 0000000..84427be
--- /dev/null
+++ b/drivers/usb/musb/da8xx.c
@@ -0,0 +1,469 @@
+/*
+ * Texas Instruments DA8xx/OMAP-L1x "glue layer"
+ *
+ * Copyright (c) 2008-2009 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * Based on the DaVinci "glue layer" code.
+ * Copyright (C) 2005-2006 by Texas Instruments
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can 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 Inventra Controller Driver for Linux is distributed in
+ * the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Inventra Controller Driver for Linux ; 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/clk.h>
+#include <linux/io.h>
+
+#include <mach/da8xx.h>
+#include <mach/usb.h>
+
+#include "musb_core.h"
+
+/*
+ * DA8XX specific definitions
+ */
+
+/* USB 2.0 OTG module registers */
+#define DA8XX_USB_REVISION_REG	0x00
+#define DA8XX_USB_CTRL_REG	0x04
+#define DA8XX_USB_STAT_REG	0x08
+#define DA8XX_USB_EMULATION_REG 0x0c
+#define DA8XX_USB_MODE_REG	0x10	/* Transparent, CDC, [Generic] RNDIS */
+#define DA8XX_USB_AUTOREQ_REG	0x14
+#define DA8XX_USB_SRP_FIX_TIME_REG 0x18
+#define DA8XX_USB_TEARDOWN_REG	0x1c
+#define DA8XX_USB_INTR_SRC_REG	0x20
+#define DA8XX_USB_INTR_SRC_SET_REG 0x24
+#define DA8XX_USB_INTR_SRC_CLEAR_REG 0x28
+#define DA8XX_USB_INTR_MASK_REG 0x2c
+#define DA8XX_USB_INTR_MASK_SET_REG 0x30
+#define DA8XX_USB_INTR_MASK_CLEAR_REG 0x34
+#define DA8XX_USB_INTR_SRC_MASKED_REG 0x38
+#define DA8XX_USB_END_OF_INTR_REG 0x3c
+#define DA8XX_USB_GENERIC_RNDIS_EP_SIZE_REG(n) (0x50 + (((n) - 1) << 2))
+
+/* Control register bits */
+#define DA8XX_SOFT_RESET_MASK	1
+
+#define DA8XX_USB_TX_EP_MASK	0x1f		/* EP0 + 4 Tx EPs */
+#define DA8XX_USB_RX_EP_MASK	0x1e		/* 4 Rx EPs */
+
+/* USB interrupt register bits */
+#define DA8XX_INTR_USB_SHIFT	16
+#define DA8XX_INTR_USB_MASK	(0x1ff << DA8XX_INTR_USB_SHIFT) /* 8 Mentor */
+					/* interrupts and DRVVBUS interrupt */
+#define DA8XX_INTR_DRVVBUS	0x100
+#define DA8XX_INTR_RX_SHIFT	8
+#define DA8XX_INTR_RX_MASK	(DA8XX_USB_RX_EP_MASK << DA8XX_INTR_RX_SHIFT)
+#define DA8XX_INTR_TX_SHIFT	0
+#define DA8XX_INTR_TX_MASK	(DA8XX_USB_TX_EP_MASK << DA8XX_INTR_TX_SHIFT)
+
+#define DA8XX_MENTOR_CORE_OFFSET 0x400
+
+#define CFGCHIP2	IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG)
+
+/*
+ * REVISIT (PM): we should be able to keep the PHY in low power mode most
+ * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0
+ * and, when in host mode, autosuspending idle root ports... PHY_PLLON
+ * (overriding SUSPENDM?) then likely needs to stay off.
+ */
+
+static inline void phy_on(void)
+{
+	u32 cfgchip2 = __raw_readl(CFGCHIP2);
+
+	/*
+	 * Start the on-chip PHY and its PLL.
+	 */
+	cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN);
+	cfgchip2 |= CFGCHIP2_PHY_PLLON;
+	__raw_writel(cfgchip2, CFGCHIP2);
+
+	pr_info("Waiting for USB PHY clock good...\n");
+	while (!(__raw_readl(CFGCHIP2) & CFGCHIP2_PHYCLKGD))
+		cpu_relax();
+}
+
+static inline void phy_off(void)
+{
+	u32 cfgchip2 = __raw_readl(CFGCHIP2);
+
+	/*
+	 * Ensure that USB 1.1 reference clock is not being sourced from
+	 * USB 2.0 PHY.  Otherwise do not power down the PHY.
+	 */
+	if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX) &&
+	     (cfgchip2 & CFGCHIP2_USB1SUSPENDM)) {
+		pr_warning("USB 1.1 clocked from USB 2.0 PHY -- "
+			   "can't power it down\n");
+		return;
+	}
+
+	/*
+	 * Power down the on-chip PHY.
+	 */
+	cfgchip2 |= CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN;
+	__raw_writel(cfgchip2, CFGCHIP2);
+}
+
+/*
+ * Because we don't set CTRL.UINT, it's "important" to:
+ *	- not read/write INTRUSB/INTRUSBE (except during
+ *	  initial setup, as a workaround);
+ *	- use INTSET/INTCLR instead.
+ */
+
+/**
+ * musb_platform_enable - enable interrupts
+ */
+void musb_platform_enable(struct musb *musb)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+	u32 mask;
+
+	/* Workaround: setup IRQs through both register sets. */
+	mask = ((musb->epmask & DA8XX_USB_TX_EP_MASK) << DA8XX_INTR_TX_SHIFT) |
+	       ((musb->epmask & DA8XX_USB_RX_EP_MASK) << DA8XX_INTR_RX_SHIFT) |
+	       DA8XX_INTR_USB_MASK;
+	musb_writel(reg_base, DA8XX_USB_INTR_MASK_SET_REG, mask);
+
+	/* Force the DRVVBUS IRQ so we can start polling for ID change. */
+	if (is_otg_enabled(musb))
+		musb_writel(reg_base, DA8XX_USB_INTR_SRC_SET_REG,
+			    DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT);
+}
+
+/**
+ * musb_platform_disable - disable HDRC and flush interrupts
+ */
+void musb_platform_disable(struct musb *musb)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+
+	musb_writel(reg_base, DA8XX_USB_INTR_MASK_CLEAR_REG,
+		    DA8XX_INTR_USB_MASK |
+		    DA8XX_INTR_TX_MASK | DA8XX_INTR_RX_MASK);
+	musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+	musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0);
+}
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+#define portstate(stmt) 	stmt
+#else
+#define portstate(stmt)
+#endif
+
+static void da8xx_set_vbus(struct musb *musb, int is_on)
+{
+	WARN_ON(is_on && is_peripheral_active(musb));
+}
+
+#define	POLL_SECONDS	2
+
+static struct timer_list otg_workaround;
+
+static void otg_timer(unsigned long _musb)
+{
+	struct musb		*musb = (void *)_musb;
+	void __iomem		*mregs = musb->mregs;
+	u8			devctl;
+	unsigned long		flags;
+
+	/*
+	 * We poll because DaVinci's won't expose several OTG-critical
+	 * status change events (from the transceiver) otherwise.
+	 */
+	devctl = musb_readb(mregs, MUSB_DEVCTL);
+	DBG(7, "Poll devctl %02x (%s)\n", devctl, otg_state_string(musb));
+
+	spin_lock_irqsave(&musb->lock, flags);
+	switch (musb->xceiv->state) {
+	case OTG_STATE_A_WAIT_BCON:
+		devctl &= ~MUSB_DEVCTL_SESSION;
+		musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+		if (devctl & MUSB_DEVCTL_BDEVICE) {
+			musb->xceiv->state = OTG_STATE_B_IDLE;
+			MUSB_DEV_MODE(musb);
+		} else {
+			musb->xceiv->state = OTG_STATE_A_IDLE;
+			MUSB_HST_MODE(musb);
+		}
+		break;
+	case OTG_STATE_A_WAIT_VFALL:
+		/*
+		 * Wait till VBUS falls below SessionEnd (~0.2 V); the 1.3
+		 * RTL seems to mis-handle session "start" otherwise (or in
+		 * our case "recover"), in routine "VBUS was valid by the time
+		 * VBUSERR got reported during enumeration" cases.
+		 */
+		if (devctl & MUSB_DEVCTL_VBUS) {
+			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+			break;
+		}
+		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+		musb_writel(musb->ctrl_base, DA8XX_USB_INTR_SRC_SET_REG,
+			    MUSB_INTR_VBUSERROR << DA8XX_INTR_USB_SHIFT);
+		break;
+	case OTG_STATE_B_IDLE:
+		if (!is_peripheral_enabled(musb))
+			break;
+
+		/*
+		 * There's no ID-changed IRQ, so we have no good way to tell
+		 * when to switch to the A-Default state machine (by setting
+		 * the DEVCTL.Session bit).
+		 *
+		 * Workaround:  whenever we're in B_IDLE, try setting the
+		 * session flag every few seconds.  If it works, ID was
+		 * grounded and we're now in the A-Default state machine.
+		 *
+		 * NOTE: setting the session flag is _supposed_ to trigger
+		 * SRP but clearly it doesn't.
+		 */
+		musb_writeb(mregs, MUSB_DEVCTL, devctl | MUSB_DEVCTL_SESSION);
+		devctl = musb_readb(mregs, MUSB_DEVCTL);
+		if (devctl & MUSB_DEVCTL_BDEVICE)
+			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+		else
+			musb->xceiv->state = OTG_STATE_A_IDLE;
+		break;
+	default:
+		break;
+	}
+	spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+{
+	static unsigned long last_timer;
+
+	if (!is_otg_enabled(musb))
+		return;
+
+	if (timeout == 0)
+		timeout = jiffies + msecs_to_jiffies(3);
+
+	/* Never idle if active, or when VBUS timeout is not set as host */
+	if (musb->is_active || (musb->a_wait_bcon == 0 &&
+				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+		DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
+		del_timer(&otg_workaround);
+		last_timer = jiffies;
+		return;
+	}
+
+	if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) {
+		DBG(4, "Longer idle timer already pending, ignoring...\n");
+		return;
+	}
+	last_timer = timeout;
+
+	DBG(4, "%s inactive, starting idle timer for %u ms\n",
+	    otg_state_string(musb), jiffies_to_msecs(timeout - jiffies));
+	mod_timer(&otg_workaround, timeout);
+}
+
+static irqreturn_t da8xx_interrupt(int irq, void *hci)
+{
+	struct musb		*musb = hci;
+	void __iomem		*reg_base = musb->ctrl_base;
+	unsigned long		flags;
+	irqreturn_t		ret = IRQ_NONE;
+	u32			status;
+
+	spin_lock_irqsave(&musb->lock, flags);
+
+	/*
+	 * NOTE: DA8XX shadows the Mentor IRQs.  Don't manage them through
+	 * the Mentor registers (except for setup), use the TI ones and EOI.
+	 */
+
+	/* Acknowledge and handle non-CPPI interrupts */
+	status = musb_readl(reg_base, DA8XX_USB_INTR_SRC_MASKED_REG);
+	if (!status)
+		goto eoi;
+
+	musb_writel(reg_base, DA8XX_USB_INTR_SRC_CLEAR_REG, status);
+	DBG(4, "USB IRQ %08x\n", status);
+
+	musb->int_rx = (status & DA8XX_INTR_RX_MASK) >> DA8XX_INTR_RX_SHIFT;
+	musb->int_tx = (status & DA8XX_INTR_TX_MASK) >> DA8XX_INTR_TX_SHIFT;
+	musb->int_usb = (status & DA8XX_INTR_USB_MASK) >> DA8XX_INTR_USB_SHIFT;
+
+	/*
+	 * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
+	 * DA8xx's missing ID change IRQ.  We need an ID change IRQ to
+	 * switch appropriately between halves of the OTG state machine.
+	 * Managing DEVCTL.Session per Mentor docs requires that we know its
+	 * value but DEVCTL.BDevice is invalid without DEVCTL.Session set.
+	 * Also, DRVVBUS pulses for SRP (but not at 5 V)...
+	 */
+	if (status & (DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT)) {
+		int drvvbus = musb_readl(reg_base, DA8XX_USB_STAT_REG);
+		void __iomem *mregs = musb->mregs;
+		u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
+		int err;
+
+		err = is_host_enabled(musb) && (musb->int_usb &
+						MUSB_INTR_VBUSERROR);
+		if (err) {
+			/*
+			 * The Mentor core doesn't debounce VBUS as needed
+			 * to cope with device connect current spikes. This
+			 * means it's not uncommon for bus-powered devices
+			 * to get VBUS errors during enumeration.
+			 *
+			 * This is a workaround, but newer RTL from Mentor
+			 * seems to allow a better one: "re"-starting sessions
+			 * without waiting for VBUS to stop registering in
+			 * devctl.
+			 */
+			musb->int_usb &= ~MUSB_INTR_VBUSERROR;
+			musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+			WARNING("VBUS error workaround (delay coming)\n");
+		} else if (is_host_enabled(musb) && drvvbus) {
+			MUSB_HST_MODE(musb);
+			musb->xceiv->default_a = 1;
+			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+			portstate(musb->port1_status |= USB_PORT_STAT_POWER);
+			del_timer(&otg_workaround);
+		} else {
+			musb->is_active = 0;
+			MUSB_DEV_MODE(musb);
+			musb->xceiv->default_a = 0;
+			musb->xceiv->state = OTG_STATE_B_IDLE;
+			portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
+		}
+
+		DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
+				drvvbus ? "on" : "off",
+				otg_state_string(musb),
+				err ? " ERROR" : "",
+				devctl);
+		ret = IRQ_HANDLED;
+	}
+
+	if (musb->int_tx || musb->int_rx || musb->int_usb)
+		ret |= musb_interrupt(musb);
+
+ eoi:
+	/* EOI needs to be written for the IRQ to be re-asserted. */
+	if (ret == IRQ_HANDLED || status)
+		musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0);
+
+	/* Poll for ID change */
+	if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
+		mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+
+	spin_unlock_irqrestore(&musb->lock, flags);
+
+	return ret;
+}
+
+int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+{
+	u32 cfgchip2 = __raw_readl(CFGCHIP2);
+
+	cfgchip2 &= ~CFGCHIP2_OTGMODE;
+	switch (musb_mode) {
+#ifdef	CONFIG_USB_MUSB_HDRC_HCD
+	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
+		cfgchip2 |= CFGCHIP2_FORCE_HOST;
+		break;
+#endif
+#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
+	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
+		cfgchip2 |= CFGCHIP2_FORCE_DEVICE;
+		break;
+#endif
+#ifdef	CONFIG_USB_MUSB_OTG
+	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
+		cfgchip2 |= CFGCHIP2_NO_OVERRIDE;
+		break;
+#endif
+	default:
+		DBG(2, "Trying to set unsupported mode %u\n", musb_mode);
+	}
+
+	__raw_writel(cfgchip2, CFGCHIP2);
+	return 0;
+}
+
+int __init musb_platform_init(struct musb *musb, void *board_data)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+	u32 rev;
+
+	musb->mregs += DA8XX_MENTOR_CORE_OFFSET;
+
+	clk_enable(musb->clock);
+
+	/* Returns zero if e.g. not clocked */
+	rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG);
+	if (!rev)
+		goto fail;
+
+	usb_nop_xceiv_register();
+	musb->xceiv = otg_get_transceiver();
+	if (!musb->xceiv)
+		goto fail;
+
+	if (is_host_enabled(musb))
+		setup_timer(&otg_workaround, otg_timer, (unsigned long)musb);
+
+	musb->board_set_vbus = da8xx_set_vbus;
+
+	/* Reset the controller */
+	musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK);
+
+	/* Start the on-chip PHY and its PLL. */
+	phy_on();
+
+	msleep(5);
+
+	/* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */
+	pr_debug("DA8xx OTG revision %08x, PHY %03x, control %02x\n",
+		 rev, __raw_readl(CFGCHIP2),
+		 musb_readb(reg_base, DA8XX_USB_CTRL_REG));
+
+	musb->isr = da8xx_interrupt;
+	return 0;
+fail:
+	clk_disable(musb->clock);
+	return -ENODEV;
+}
+
+int musb_platform_exit(struct musb *musb)
+{
+	if (is_host_enabled(musb))
+		del_timer_sync(&otg_workaround);
+
+	phy_off();
+
+	otg_put_transceiver(musb->xceiv);
+	usb_nop_xceiv_unregister();
+
+	clk_disable(musb->clock);
+
+	return 0;
+}
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 57624361..6e67629 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -446,6 +446,7 @@
 fail:
 	clk_disable(musb->clock);
 
+	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 	return -ENODEV;
 }
@@ -496,6 +497,7 @@
 
 	clk_disable(musb->clock);
 
+	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 
 	return 0;
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 540c766..c9f9024 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -272,6 +272,7 @@
 	}
 }
 
+#if !defined(CONFIG_USB_MUSB_AM35X)
 /*
  * Unload an endpoint's FIFO
  */
@@ -309,6 +310,7 @@
 		readsb(fifo, dst, len);
 	}
 }
+#endif
 
 #endif	/* normal PIO */
 
@@ -550,6 +552,11 @@
 	if (int_usb & MUSB_INTR_SESSREQ) {
 		void __iomem *mbase = musb->mregs;
 
+		if (devctl & MUSB_DEVCTL_BDEVICE) {
+			DBG(3, "SessReq while on B state\n");
+			return IRQ_HANDLED;
+		}
+
 		DBG(1, "SESSION_REQUEST (%s)\n", otg_state_string(musb));
 
 		/* IRQ arrives from ID pin sense or (later, if VBUS power
@@ -1921,10 +1928,6 @@
 		dma_controller_destroy(c);
 	}
 
-#ifdef CONFIG_USB_MUSB_OTG
-	put_device(musb->xceiv->dev);
-#endif
-
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
 	usb_put_hcd(musb_to_hcd(musb));
 #else
@@ -2266,6 +2269,7 @@
 {
 	int i;
 	void __iomem *musb_base = musb->mregs;
+	void __iomem *epio;
 
 	if (is_host_enabled(musb)) {
 		musb_context.frame = musb_readw(musb_base, MUSB_FRAME);
@@ -2279,16 +2283,16 @@
 	musb_context.index = musb_readb(musb_base, MUSB_INDEX);
 	musb_context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
 
-	for (i = 0; i < MUSB_C_NUM_EPS; ++i) {
-		musb_writeb(musb_base, MUSB_INDEX, i);
+	for (i = 0; i < musb->config->num_eps; ++i) {
+		epio = musb->endpoints[i].regs;
 		musb_context.index_regs[i].txmaxp =
-			musb_readw(musb_base, 0x10 + MUSB_TXMAXP);
+			musb_readw(epio, MUSB_TXMAXP);
 		musb_context.index_regs[i].txcsr =
-			musb_readw(musb_base, 0x10 + MUSB_TXCSR);
+			musb_readw(epio, MUSB_TXCSR);
 		musb_context.index_regs[i].rxmaxp =
-			musb_readw(musb_base, 0x10 + MUSB_RXMAXP);
+			musb_readw(epio, MUSB_RXMAXP);
 		musb_context.index_regs[i].rxcsr =
-			musb_readw(musb_base, 0x10 + MUSB_RXCSR);
+			musb_readw(epio, MUSB_RXCSR);
 
 		if (musb->dyn_fifo) {
 			musb_context.index_regs[i].txfifoadd =
@@ -2302,13 +2306,13 @@
 		}
 		if (is_host_enabled(musb)) {
 			musb_context.index_regs[i].txtype =
-				musb_readb(musb_base, 0x10 + MUSB_TXTYPE);
+				musb_readb(epio, MUSB_TXTYPE);
 			musb_context.index_regs[i].txinterval =
-				musb_readb(musb_base, 0x10 + MUSB_TXINTERVAL);
+				musb_readb(epio, MUSB_TXINTERVAL);
 			musb_context.index_regs[i].rxtype =
-				musb_readb(musb_base, 0x10 + MUSB_RXTYPE);
+				musb_readb(epio, MUSB_RXTYPE);
 			musb_context.index_regs[i].rxinterval =
-				musb_readb(musb_base, 0x10 + MUSB_RXINTERVAL);
+				musb_readb(epio, MUSB_RXINTERVAL);
 
 			musb_context.index_regs[i].txfunaddr =
 				musb_read_txfunaddr(musb_base, i);
@@ -2326,8 +2330,6 @@
 		}
 	}
 
-	musb_writeb(musb_base, MUSB_INDEX, musb_context.index);
-
 	musb_platform_save_context(musb, &musb_context);
 }
 
@@ -2336,6 +2338,7 @@
 	int i;
 	void __iomem *musb_base = musb->mregs;
 	void __iomem *ep_target_regs;
+	void __iomem *epio;
 
 	musb_platform_restore_context(musb, &musb_context);
 
@@ -2350,15 +2353,15 @@
 	musb_writeb(musb_base, MUSB_INTRUSBE, musb_context.intrusbe);
 	musb_writeb(musb_base, MUSB_DEVCTL, musb_context.devctl);
 
-	for (i = 0; i < MUSB_C_NUM_EPS; ++i) {
-		musb_writeb(musb_base, MUSB_INDEX, i);
-		musb_writew(musb_base, 0x10 + MUSB_TXMAXP,
+	for (i = 0; i < musb->config->num_eps; ++i) {
+		epio = musb->endpoints[i].regs;
+		musb_writew(epio, MUSB_TXMAXP,
 			musb_context.index_regs[i].txmaxp);
-		musb_writew(musb_base, 0x10 + MUSB_TXCSR,
+		musb_writew(epio, MUSB_TXCSR,
 			musb_context.index_regs[i].txcsr);
-		musb_writew(musb_base, 0x10 + MUSB_RXMAXP,
+		musb_writew(epio, MUSB_RXMAXP,
 			musb_context.index_regs[i].rxmaxp);
-		musb_writew(musb_base, 0x10 + MUSB_RXCSR,
+		musb_writew(epio, MUSB_RXCSR,
 			musb_context.index_regs[i].rxcsr);
 
 		if (musb->dyn_fifo) {
@@ -2373,13 +2376,13 @@
 		}
 
 		if (is_host_enabled(musb)) {
-			musb_writeb(musb_base, 0x10 + MUSB_TXTYPE,
+			musb_writeb(epio, MUSB_TXTYPE,
 				musb_context.index_regs[i].txtype);
-			musb_writeb(musb_base, 0x10 + MUSB_TXINTERVAL,
+			musb_writeb(epio, MUSB_TXINTERVAL,
 				musb_context.index_regs[i].txinterval);
-			musb_writeb(musb_base, 0x10 + MUSB_RXTYPE,
+			musb_writeb(epio, MUSB_RXTYPE,
 				musb_context.index_regs[i].rxtype);
-			musb_writeb(musb_base, 0x10 + MUSB_RXINTERVAL,
+			musb_writeb(epio, MUSB_RXINTERVAL,
 
 			musb_context.index_regs[i].rxinterval);
 			musb_write_txfunaddr(musb_base, i,
@@ -2400,8 +2403,6 @@
 				musb_context.index_regs[i].rxhubport);
 		}
 	}
-
-	musb_writeb(musb_base, MUSB_INDEX, musb_context.index);
 }
 
 static int musb_suspend(struct device *dev)
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 91d6779..69797e5 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -330,6 +330,7 @@
 	/* device lock */
 	spinlock_t		lock;
 	struct clk		*clock;
+	struct clk		*phy_clock;
 	irqreturn_t		(*isr)(int, void *);
 	struct work_struct	irq_work;
 	u16			hwvers;
@@ -599,6 +600,7 @@
 extern int musb_platform_set_mode(struct musb *musb, u8 musb_mode);
 
 #if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) || \
+	defined(CONFIG_ARCH_DAVINCI_DA8XX) || \
 	defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
 	defined(CONFIG_ARCH_OMAP4)
 extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout);
diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h
index d73afdb..94f6973 100644
--- a/drivers/usb/musb/musb_debug.h
+++ b/drivers/usb/musb/musb_debug.h
@@ -42,11 +42,10 @@
 #define INFO(fmt, args...) yprintk(KERN_INFO, fmt, ## args)
 #define ERR(fmt, args...) yprintk(KERN_ERR, fmt, ## args)
 
-#define xprintk(level, facility, format, args...) do { \
-	if (_dbg_level(level)) { \
-		printk(facility "%s %d: " format , \
-				__func__, __LINE__ , ## args); \
-	} } while (0)
+#define DBG(level, format, args...) do { \
+	if (_dbg_level(level)) \
+		pr_debug("%s %d: " format, __func__, __LINE__, ## args); \
+	} while (0)
 
 extern unsigned musb_debug;
 
@@ -55,8 +54,6 @@
 	return musb_debug >= l;
 }
 
-#define DBG(level, fmt, args...) xprintk(level, KERN_DEBUG, fmt, ## args)
-
 extern const char *otg_state_string(struct musb *);
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 6fca870..5d81504 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -300,6 +300,11 @@
 #ifndef	CONFIG_MUSB_PIO_ONLY
 	if (is_dma_capable() && musb_ep->dma) {
 		struct dma_controller	*c = musb->dma_controller;
+		size_t request_size;
+
+		/* setup DMA, then program endpoint CSR */
+		request_size = min_t(size_t, request->length - request->actual,
+					musb_ep->dma->max_len);
 
 		use_dma = (request->dma != DMA_ADDR_INVALID);
 
@@ -307,11 +312,6 @@
 
 #ifdef CONFIG_USB_INVENTRA_DMA
 		{
-			size_t request_size;
-
-			/* setup DMA, then program endpoint CSR */
-			request_size = min_t(size_t, request->length,
-						musb_ep->dma->max_len);
 			if (request_size < musb_ep->packet_sz)
 				musb_ep->dma->desired_mode = 0;
 			else
@@ -337,13 +337,15 @@
 					csr |= (MUSB_TXCSR_DMAENAB |
 							MUSB_TXCSR_MODE);
 					/* against programming guide */
-				} else
-					csr |= (MUSB_TXCSR_AUTOSET
-							| MUSB_TXCSR_DMAENAB
+				} else {
+					csr |= (MUSB_TXCSR_DMAENAB
 							| MUSB_TXCSR_DMAMODE
 							| MUSB_TXCSR_MODE);
-
+					if (!musb_ep->hb_mult)
+						csr |= MUSB_TXCSR_AUTOSET;
+				}
 				csr &= ~MUSB_TXCSR_P_UNDERRUN;
+
 				musb_writew(epio, MUSB_TXCSR, csr);
 			}
 		}
@@ -373,8 +375,8 @@
 		use_dma = use_dma && c->channel_program(
 				musb_ep->dma, musb_ep->packet_sz,
 				0,
-				request->dma,
-				request->length);
+				request->dma + request->actual,
+				request_size);
 		if (!use_dma) {
 			c->channel_release(musb_ep->dma);
 			musb_ep->dma = NULL;
@@ -386,8 +388,8 @@
 		use_dma = use_dma && c->channel_program(
 				musb_ep->dma, musb_ep->packet_sz,
 				request->zero,
-				request->dma,
-				request->length);
+				request->dma + request->actual,
+				request_size);
 #endif
 	}
 #endif
@@ -475,47 +477,34 @@
 				epnum, csr, musb_ep->dma->actual_len, request);
 		}
 
-		if (is_dma || request->actual == request->length) {
-			/*
-			 * First, maybe a terminating short packet. Some DMA
-			 * engines might handle this by themselves.
-			 */
-			if ((request->zero && request->length
-				&& request->length % musb_ep->packet_sz == 0)
+		/*
+		 * First, maybe a terminating short packet. Some DMA
+		 * engines might handle this by themselves.
+		 */
+		if ((request->zero && request->length
+			&& (request->length % musb_ep->packet_sz == 0)
+			&& (request->actual == request->length))
 #ifdef CONFIG_USB_INVENTRA_DMA
-				|| (is_dma && (!dma->desired_mode ||
-					(request->actual &
-						(musb_ep->packet_sz - 1))))
+			|| (is_dma && (!dma->desired_mode ||
+				(request->actual &
+					(musb_ep->packet_sz - 1))))
 #endif
-			) {
-				/*
-				 * On DMA completion, FIFO may not be
-				 * available yet...
-				 */
-				if (csr & MUSB_TXCSR_TXPKTRDY)
-					return;
-
-				DBG(4, "sending zero pkt\n");
-				musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE
-						| MUSB_TXCSR_TXPKTRDY);
-				request->zero = 0;
-			}
-
-			/* ... or if not, then complete it. */
-			musb_g_giveback(musb_ep, request, 0);
-
+		) {
 			/*
-			 * Kickstart next transfer if appropriate;
-			 * the packet that just completed might not
-			 * be transmitted for hours or days.
-			 * REVISIT for double buffering...
-			 * FIXME revisit for stalls too...
+			 * On DMA completion, FIFO may not be
+			 * available yet...
 			 */
-			musb_ep_select(mbase, epnum);
-			csr = musb_readw(epio, MUSB_TXCSR);
-			if (csr & MUSB_TXCSR_FIFONOTEMPTY)
+			if (csr & MUSB_TXCSR_TXPKTRDY)
 				return;
 
+			DBG(4, "sending zero pkt\n");
+			musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE
+					| MUSB_TXCSR_TXPKTRDY);
+			request->zero = 0;
+		}
+
+		if (request->actual == request->length) {
+			musb_g_giveback(musb_ep, request, 0);
 			request = musb_ep->desc ? next_request(musb_ep) : NULL;
 			if (!request) {
 				DBG(4, "%s idle now\n",
@@ -568,11 +557,19 @@
 {
 	const u8		epnum = req->epnum;
 	struct usb_request	*request = &req->request;
-	struct musb_ep		*musb_ep = &musb->endpoints[epnum].ep_out;
+	struct musb_ep		*musb_ep;
 	void __iomem		*epio = musb->endpoints[epnum].regs;
 	unsigned		fifo_count = 0;
-	u16			len = musb_ep->packet_sz;
+	u16			len;
 	u16			csr = musb_readw(epio, MUSB_RXCSR);
+	struct musb_hw_ep	*hw_ep = &musb->endpoints[epnum];
+
+	if (hw_ep->is_shared_fifo)
+		musb_ep = &hw_ep->ep_in;
+	else
+		musb_ep = &hw_ep->ep_out;
+
+	len = musb_ep->packet_sz;
 
 	/* We shouldn't get here while DMA is active, but we do... */
 	if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) {
@@ -647,8 +644,10 @@
 	 */
 
 				csr |= MUSB_RXCSR_DMAENAB;
+				if (!musb_ep->hb_mult &&
+					musb_ep->hw_ep->rx_double_buffered)
+					csr |= MUSB_RXCSR_AUTOCLEAR;
 #ifdef USE_MODE1
-				csr |= MUSB_RXCSR_AUTOCLEAR;
 				/* csr |= MUSB_RXCSR_DMAMODE; */
 
 				/* this special sequence (enabling and then
@@ -663,10 +662,11 @@
 				if (request->actual < request->length) {
 					int transfer_size = 0;
 #ifdef USE_MODE1
-					transfer_size = min(request->length,
+					transfer_size = min(request->length - request->actual,
 							channel->max_len);
 #else
-					transfer_size = len;
+					transfer_size = min(request->length - request->actual,
+							(unsigned)len);
 #endif
 					if (transfer_size <= musb_ep->packet_sz)
 						musb_ep->dma->desired_mode = 0;
@@ -740,9 +740,15 @@
 	u16			csr;
 	struct usb_request	*request;
 	void __iomem		*mbase = musb->mregs;
-	struct musb_ep		*musb_ep = &musb->endpoints[epnum].ep_out;
+	struct musb_ep		*musb_ep;
 	void __iomem		*epio = musb->endpoints[epnum].regs;
 	struct dma_channel	*dma;
+	struct musb_hw_ep	*hw_ep = &musb->endpoints[epnum];
+
+	if (hw_ep->is_shared_fifo)
+		musb_ep = &hw_ep->ep_in;
+	else
+		musb_ep = &hw_ep->ep_out;
 
 	musb_ep_select(mbase, epnum);
 
@@ -769,7 +775,7 @@
 		musb_writew(epio, MUSB_RXCSR, csr);
 
 		DBG(3, "%s iso overrun on %p\n", musb_ep->name, request);
-		if (request && request->status == -EINPROGRESS)
+		if (request->status == -EINPROGRESS)
 			request->status = -EOVERFLOW;
 	}
 	if (csr & MUSB_RXCSR_INCOMPRX) {
@@ -822,14 +828,8 @@
 			return;
 	}
 
-	/* analyze request if the ep is hot */
-	if (request)
-		rxstate(musb, to_musb_request(request));
-	else
-		DBG(3, "packet waiting for %s%s request\n",
-				musb_ep->desc ? "" : "inactive ",
-				musb_ep->end_point.name);
-	return;
+	/* Analyze request */
+	rxstate(musb, to_musb_request(request));
 }
 
 /* ------------------------------------------------------------ */
@@ -872,9 +872,25 @@
 
 	/* REVISIT this rules out high bandwidth periodic transfers */
 	tmp = le16_to_cpu(desc->wMaxPacketSize);
-	if (tmp & ~0x07ff)
-		goto fail;
-	musb_ep->packet_sz = tmp;
+	if (tmp & ~0x07ff) {
+		int ok;
+
+		if (usb_endpoint_dir_in(desc))
+			ok = musb->hb_iso_tx;
+		else
+			ok = musb->hb_iso_rx;
+
+		if (!ok) {
+			DBG(4, "%s: not support ISO high bandwidth\n", __func__);
+			goto fail;
+		}
+		musb_ep->hb_mult = (tmp >> 11) & 3;
+	} else {
+		musb_ep->hb_mult = 0;
+	}
+
+	musb_ep->packet_sz = tmp & 0x7ff;
+	tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1);
 
 	/* enable the interrupts for the endpoint, set the endpoint
 	 * packet size (or fail), set the mode, clear the fifo
@@ -887,8 +903,11 @@
 			musb_ep->is_in = 1;
 		if (!musb_ep->is_in)
 			goto fail;
-		if (tmp > hw_ep->max_packet_sz_tx)
+
+		if (tmp > hw_ep->max_packet_sz_tx) {
+			DBG(4, "%s: packet size beyond hw fifo size\n", __func__);
 			goto fail;
+		}
 
 		int_txe |= (1 << epnum);
 		musb_writew(mbase, MUSB_INTRTXE, int_txe);
@@ -903,7 +922,7 @@
 		if (musb->hwvers < MUSB_HWVERS_2000)
 			musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx);
 		else
-			musb_writew(regs, MUSB_TXMAXP, tmp);
+			musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11));
 
 		csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG;
 		if (musb_readw(regs, MUSB_TXCSR)
@@ -924,8 +943,11 @@
 			musb_ep->is_in = 0;
 		if (musb_ep->is_in)
 			goto fail;
-		if (tmp > hw_ep->max_packet_sz_rx)
+
+		if (tmp > hw_ep->max_packet_sz_rx) {
+			DBG(4, "%s: packet size beyond hw fifo size\n", __func__);
 			goto fail;
+		}
 
 		int_rxe |= (1 << epnum);
 		musb_writew(mbase, MUSB_INTRRXE, int_rxe);
@@ -939,7 +961,7 @@
 		if (musb->hwvers < MUSB_HWVERS_2000)
 			musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx);
 		else
-			musb_writew(regs, MUSB_RXMAXP, tmp);
+			musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11));
 
 		/* force shared fifo to OUT-only mode */
 		if (hw_ep->is_shared_fifo) {
@@ -1081,7 +1103,7 @@
 /*
  * Context: controller locked, IRQs blocked.
  */
-static void musb_ep_restart(struct musb *musb, struct musb_request *req)
+void musb_ep_restart(struct musb *musb, struct musb_request *req)
 {
 	DBG(3, "<== %s request %p len %u on hw_ep%d\n",
 		req->tx ? "TX/IN" : "RX/OUT",
@@ -1696,9 +1718,11 @@
  * -ENOMEM no memeory to perform the operation
  *
  * @param driver the gadget driver
+ * @param bind the driver's bind function
  * @return <0 if error, 0 if everything is fine
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	int retval;
 	unsigned long flags;
@@ -1706,8 +1730,7 @@
 
 	if (!driver
 			|| driver->speed != USB_SPEED_HIGH
-			|| !driver->bind
-			|| !driver->setup)
+			|| !bind || !driver->setup)
 		return -EINVAL;
 
 	/* driver must be initialized to support peripheral mode */
@@ -1735,7 +1758,7 @@
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 	if (retval == 0) {
-		retval = driver->bind(&musb->g);
+		retval = bind(&musb->g);
 		if (retval != 0) {
 			DBG(3, "bind to driver %s failed --> %d\n",
 					driver->driver.name, retval);
@@ -1783,7 +1806,7 @@
 
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h
index c8b1403..dec8dc0 100644
--- a/drivers/usb/musb/musb_gadget.h
+++ b/drivers/usb/musb/musb_gadget.h
@@ -79,6 +79,8 @@
 
 	/* true if lock must be dropped but req_list may not be advanced */
 	u8				busy;
+
+	u8				hb_mult;
 };
 
 static inline struct musb_ep *to_musb_ep(struct usb_ep *ep)
@@ -105,4 +107,6 @@
 
 extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int);
 
+extern void musb_ep_restart(struct musb *, struct musb_request *);
+
 #endif		/* __MUSB_GADGET_H */
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index 59bef8f..6dd03f4 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -261,6 +261,7 @@
 					ctrlrequest->wIndex & 0x0f;
 				struct musb_ep		*musb_ep;
 				struct musb_hw_ep	*ep;
+				struct musb_request	*request;
 				void __iomem		*regs;
 				int			is_in;
 				u16			csr;
@@ -302,6 +303,14 @@
 					musb_writew(regs, MUSB_RXCSR, csr);
 				}
 
+				/* Maybe start the first request in the queue */
+				request = to_musb_request(
+						next_request(musb_ep));
+				if (!musb_ep->busy && request) {
+					DBG(3, "restarting the request\n");
+					musb_ep_restart(musb, request);
+				}
+
 				/* select ep0 again */
 				musb_ep_select(mbase, 0);
 				} break;
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 877d20b..4d5bcb4 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -41,6 +41,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/list.h>
+#include <linux/dma-mapping.h>
 
 #include "musb_core.h"
 #include "musb_host.h"
@@ -660,6 +661,12 @@
 
 	qh->segsize = length;
 
+	/*
+	 * Ensure the data reaches to main memory before starting
+	 * DMA transfer
+	 */
+	wmb();
+
 	if (!dma->channel_program(channel, pkt_size, mode,
 			urb->transfer_dma + offset, length)) {
 		dma->channel_release(channel);
@@ -1113,6 +1120,7 @@
 	u32			status = 0;
 	void __iomem		*mbase = musb->mregs;
 	struct dma_channel	*dma;
+	bool			transfer_pending = false;
 
 	musb_ep_select(mbase, epnum);
 	tx_csr = musb_readw(epio, MUSB_TXCSR);
@@ -1273,7 +1281,7 @@
 				offset = d->offset;
 				length = d->length;
 			}
-		} else if (dma) {
+		} else if (dma && urb->transfer_buffer_length == qh->offset) {
 			done = true;
 		} else {
 			/* see if we need to send more data, or ZLP */
@@ -1286,6 +1294,7 @@
 			if (!done) {
 				offset = qh->offset;
 				length = urb->transfer_buffer_length - offset;
+				transfer_pending = true;
 			}
 		}
 	}
@@ -1305,7 +1314,7 @@
 		urb->actual_length = qh->offset;
 		musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT);
 		return;
-	} else	if (usb_pipeisoc(pipe) && dma) {
+	} else if ((usb_pipeisoc(pipe) || transfer_pending) && dma) {
 		if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb,
 				offset, length)) {
 			if (is_cppi_enabled() || tusb_dma_omap())
@@ -1326,6 +1335,8 @@
 	 */
 	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);
 	musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
 	qh->segsize = length;
 
@@ -1746,6 +1757,8 @@
 #endif	/* Mentor DMA */
 
 		if (!dma) {
+			/* Unmap the buffer so that CPU can use it */
+			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/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 6dc107f..6f771af 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -91,7 +91,7 @@
 			channel = &(musb_channel->channel);
 			channel->private_data = musb_channel;
 			channel->status = MUSB_DMA_STATUS_FREE;
-			channel->max_len = 0x10000;
+			channel->max_len = 0x100000;
 			/* Tx => mode 1; Rx => mode 0 */
 			channel->desired_mode = transmit;
 			channel->actual_len = 0;
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 2111a24..ed618bd 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -320,5 +320,6 @@
 
 	musb_platform_suspend(musb);
 
+	otg_put_transceiver(musb->xceiv);
 	return 0;
 }
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 3c48e77..bde40ef 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1152,6 +1152,8 @@
 	if (ret < 0) {
 		if (sync)
 			iounmap(sync);
+
+		otg_put_transceiver(musb->xceiv);
 		usb_nop_xceiv_unregister();
 	}
 	return ret;
@@ -1166,6 +1168,8 @@
 		musb->board_set_power(0);
 
 	iounmap(musb->sync_va);
+
+	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 	return 0;
 }
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 3b12895..5ce0752 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -67,4 +67,18 @@
 	 built-in with usb ip or which are autonomous and doesn't require any
 	 phy programming such as ISP1x04 etc.
 
+config USB_LANGWELL_OTG
+	tristate "Intel Langwell USB OTG dual-role support"
+	depends on USB && PCI && INTEL_SCU_IPC
+	select USB_OTG
+	select USB_OTG_UTILS
+	help
+	  Say Y here if you want to build Intel Langwell USB OTG
+	  transciever driver in kernel. This driver implements role
+	  switch between EHCI host driver and Langwell USB OTG
+	  client driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called langwell_otg.
+
 endif # USB || OTG
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index aeb49a8..66f1b83 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -2,6 +2,9 @@
 # OTG infrastructure and transceiver drivers
 #
 
+ccflags-$(CONFIG_USB_DEBUG)		:= -DDEBUG
+ccflags-$(CONFIG_USB_GADGET_DEBUG)	+= -DDEBUG
+
 # infrastructure
 obj-$(CONFIG_USB_OTG_UTILS)	+= otg.o
 
@@ -9,9 +12,6 @@
 obj-$(CONFIG_USB_GPIO_VBUS)	+= gpio_vbus.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-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
-
-ccflags-$(CONFIG_USB_DEBUG)	+= -DDEBUG
-ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG
-
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c
new file mode 100644
index 0000000..bdc3ea6
--- /dev/null
+++ b/drivers/usb/otg/langwell_otg.c
@@ -0,0 +1,2408 @@
+/*
+ * Intel Langwell USB OTG transceiver driver
+ * Copyright (C) 2008 - 2010, 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.
+ *
+ */
+/* This driver helps to switch Langwell OTG controller function between host
+ * and peripheral. It works with EHCI driver and Langwell client controller
+ * driver together.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/hcd.h>
+#include <linux/notifier.h>
+#include <linux/delay.h>
+#include <asm/intel_scu_ipc.h>
+
+#include <linux/usb/langwell_otg.h>
+
+#define	DRIVER_DESC		"Intel Langwell USB OTG transceiver driver"
+#define	DRIVER_VERSION		"July 10, 2010"
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+static const char driver_name[] = "langwell_otg";
+
+static int langwell_otg_probe(struct pci_dev *pdev,
+			const struct pci_device_id *id);
+static void langwell_otg_remove(struct pci_dev *pdev);
+static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message);
+static int langwell_otg_resume(struct pci_dev *pdev);
+
+static int langwell_otg_set_host(struct otg_transceiver *otg,
+				struct usb_bus *host);
+static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
+				struct usb_gadget *gadget);
+static int langwell_otg_start_srp(struct otg_transceiver *otg);
+
+static const struct pci_device_id pci_ids[] = {{
+	.class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+	.class_mask =   ~0,
+	.vendor =	0x8086,
+	.device =	0x0811,
+	.subvendor =	PCI_ANY_ID,
+	.subdevice =	PCI_ANY_ID,
+}, { /* end: all zeroes */ }
+};
+
+static struct pci_driver otg_pci_driver = {
+	.name =		(char *) driver_name,
+	.id_table =	pci_ids,
+
+	.probe =	langwell_otg_probe,
+	.remove =	langwell_otg_remove,
+
+	.suspend =	langwell_otg_suspend,
+	.resume =	langwell_otg_resume,
+};
+
+static const char *state_string(enum usb_otg_state state)
+{
+	switch (state) {
+	case OTG_STATE_A_IDLE:
+		return "a_idle";
+	case OTG_STATE_A_WAIT_VRISE:
+		return "a_wait_vrise";
+	case OTG_STATE_A_WAIT_BCON:
+		return "a_wait_bcon";
+	case OTG_STATE_A_HOST:
+		return "a_host";
+	case OTG_STATE_A_SUSPEND:
+		return "a_suspend";
+	case OTG_STATE_A_PERIPHERAL:
+		return "a_peripheral";
+	case OTG_STATE_A_WAIT_VFALL:
+		return "a_wait_vfall";
+	case OTG_STATE_A_VBUS_ERR:
+		return "a_vbus_err";
+	case OTG_STATE_B_IDLE:
+		return "b_idle";
+	case OTG_STATE_B_SRP_INIT:
+		return "b_srp_init";
+	case OTG_STATE_B_PERIPHERAL:
+		return "b_peripheral";
+	case OTG_STATE_B_WAIT_ACON:
+		return "b_wait_acon";
+	case OTG_STATE_B_HOST:
+		return "b_host";
+	default:
+		return "UNDEFINED";
+	}
+}
+
+/* HSM timers */
+static inline struct langwell_otg_timer *otg_timer_initializer
+(void (*function)(unsigned long), unsigned long expires, unsigned long data)
+{
+	struct langwell_otg_timer *timer;
+	timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL);
+	if (timer == NULL)
+		return timer;
+
+	timer->function = function;
+	timer->expires = expires;
+	timer->data = data;
+	return timer;
+}
+
+static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr,
+	*b_se0_srp_tmr, *b_srp_init_tmr;
+
+static struct list_head active_timers;
+
+static struct langwell_otg *the_transceiver;
+
+/* host/client notify transceiver when event affects HNP state */
+void langwell_update_transceiver(void)
+{
+	struct langwell_otg *lnw = the_transceiver;
+
+	dev_dbg(lnw->dev, "transceiver is updated\n");
+
+	if (!lnw->qwork)
+		return ;
+
+	queue_work(lnw->qwork, &lnw->work);
+}
+EXPORT_SYMBOL(langwell_update_transceiver);
+
+static int langwell_otg_set_host(struct otg_transceiver *otg,
+					struct usb_bus *host)
+{
+	otg->host = host;
+
+	return 0;
+}
+
+static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
+					struct usb_gadget *gadget)
+{
+	otg->gadget = gadget;
+
+	return 0;
+}
+
+static int langwell_otg_set_power(struct otg_transceiver *otg,
+				unsigned mA)
+{
+	return 0;
+}
+
+/* A-device drives vbus, controlled through PMIC CHRGCNTL register*/
+static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	u8 r;
+
+	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;
+	}
+
+	/* Workaround for battery attachment issue */
+	if (r == 0x34) {
+		dev_dbg(lnw->dev, "no battery attached on SH\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;
+}
+
+/* charge vbus or discharge vbus through a resistor to ground */
+static void langwell_otg_chrg_vbus(int on)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	u32	val;
+
+	val = readl(lnw->iotg.base + CI_OTGSC);
+
+	if (on)
+		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC,
+				lnw->iotg.base + CI_OTGSC);
+	else
+		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD,
+				lnw->iotg.base + CI_OTGSC);
+}
+
+/* Start SRP */
+static int langwell_otg_start_srp(struct otg_transceiver *otg)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val;
+
+	dev_dbg(lnw->dev, "%s --->\n", __func__);
+
+	val = readl(iotg->base + CI_OTGSC);
+
+	writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP,
+				iotg->base + CI_OTGSC);
+
+	/* Check if the data plus is finished or not */
+	msleep(8);
+	val = readl(iotg->base + CI_OTGSC);
+	if (val & (OTGSC_HADP | OTGSC_DP))
+		dev_dbg(lnw->dev, "DataLine SRP Error\n");
+
+	/* Disable interrupt - b_sess_vld */
+	val = readl(iotg->base + CI_OTGSC);
+	val &= (~(OTGSC_BSVIE | OTGSC_BSEIE));
+	writel(val, iotg->base + CI_OTGSC);
+
+	/* Start VBus SRP, drive vbus to generate VBus pulse */
+	iotg->otg.set_vbus(&iotg->otg, true);
+	msleep(15);
+	iotg->otg.set_vbus(&iotg->otg, false);
+
+	/* Enable interrupt - b_sess_vld*/
+	val = readl(iotg->base + CI_OTGSC);
+	dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val);
+
+	val |= (OTGSC_BSVIE | OTGSC_BSEIE);
+	writel(val, iotg->base + CI_OTGSC);
+
+	/* If Vbus is valid, then update the hsm */
+	if (val & OTGSC_BSV) {
+		dev_dbg(lnw->dev, "no b_sess_vld interrupt\n");
+
+		lnw->iotg.hsm.b_sess_vld = 1;
+		langwell_update_transceiver();
+	}
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+	return 0;
+}
+
+/* stop SOF via bus_suspend */
+static void langwell_otg_loc_sof(int on)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	struct usb_hcd		*hcd;
+	int			err;
+
+	dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume");
+
+	hcd = bus_to_hcd(lnw->iotg.otg.host);
+	if (on)
+		err = hcd->driver->bus_resume(hcd);
+	else
+		err = hcd->driver->bus_suspend(hcd);
+
+	if (err)
+		dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err);
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+}
+
+static int langwell_otg_check_otgsc(void)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	u32				otgsc, usbcfg;
+
+	dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n");
+
+	otgsc = readl(lnw->iotg.base + CI_OTGSC);
+	usbcfg = readl(lnw->usbcfg);
+
+	dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n",
+					otgsc, usbcfg);
+	dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV));
+	dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n",
+					!!(usbcfg & USBCFG_VBUSVAL));
+	dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV));
+	dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n",
+					!!(usbcfg & USBCFG_AVALID));
+	dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV));
+	dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n",
+					!!(usbcfg & USBCFG_BVALID));
+	dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE));
+	dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n",
+					!!(usbcfg & USBCFG_SESEND));
+
+	/* Check USBCFG VBusValid/AValid/BValid/SessEnd */
+	if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) {
+		dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n");
+		goto err;
+	}
+	if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) {
+		dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n");
+		goto err;
+	}
+	if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) {
+		dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n");
+		goto err;
+	}
+	if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) {
+		dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n");
+		goto err;
+	}
+
+	dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n");
+
+	return 0;
+
+err:
+	dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n");
+	return -EPIPE;
+}
+
+
+static void langwell_otg_phy_low_power(int on)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u8				val, phcd;
+	int				retval;
+
+	dev_dbg(lnw->dev, "%s ---> %s mode\n",
+			__func__, on ? "Low power" : "Normal");
+
+	phcd = 0x40;
+
+	val = readb(iotg->base + CI_HOSTPC1 + 2);
+
+	if (on) {
+		/* Due to hardware issue, after set PHCD, sync will failed
+		 * between USBCFG and OTGSC, so before set PHCD, check if
+		 * sync is in process now. If the answer is "yes", then do
+		 * not touch PHCD bit */
+		retval = langwell_otg_check_otgsc();
+		if (retval) {
+			dev_dbg(lnw->dev, "Skip PHCD programming..\n");
+			return ;
+		}
+
+		writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2);
+	} else
+		writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2);
+
+	dev_dbg(lnw->dev, "%s <--- done\n", __func__);
+}
+
+/* After drv vbus, add 2 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");
+
+	mdelay(2);
+	langwell_otg_phy_low_power(on);
+}
+
+/* Enable/Disable OTG interrupt */
+static void langwell_otg_intr(int on)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val;
+
+	dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
+
+	val = readl(iotg->base + CI_OTGSC);
+
+	/* OTGSC_INT_MASK doesn't contains 1msInt */
+	if (on) {
+		val = val | (OTGSC_INT_MASK);
+		writel(val, iotg->base + CI_OTGSC);
+	} else {
+		val = val & ~(OTGSC_INT_MASK);
+		writel(val, iotg->base + CI_OTGSC);
+	}
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+}
+
+/* set HAAR: Hardware Assist Auto-Reset */
+static void langwell_otg_HAAR(int on)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val;
+
+	dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
+
+	val = readl(iotg->base + CI_OTGSC);
+	if (on)
+		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR,
+					iotg->base + CI_OTGSC);
+	else
+		writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR,
+					iotg->base + CI_OTGSC);
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+}
+
+/* set HABA: Hardware Assist B-Disconnect to A-Connect */
+static void langwell_otg_HABA(int on)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val;
+
+	dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
+
+	val = readl(iotg->base + CI_OTGSC);
+	if (on)
+		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA,
+					iotg->base + CI_OTGSC);
+	else
+		writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA,
+					iotg->base + CI_OTGSC);
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+}
+
+static int langwell_otg_check_se0_srp(int on)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	int			delay_time = TB_SE0_SRP * 10;
+	u32			val;
+
+	dev_dbg(lnw->dev, "%s --->\n", __func__);
+
+	do {
+		udelay(100);
+		if (!delay_time--)
+			break;
+		val = readl(lnw->iotg.base + CI_PORTSC1);
+		val &= PORTSC_LS;
+	} while (!val);
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+	return val;
+}
+
+/* The timeout callback function to set time out bit */
+static void set_tmout(unsigned long indicator)
+{
+	*(int *)indicator = 1;
+}
+
+void langwell_otg_nsf_msg(unsigned long indicator)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+
+	switch (indicator) {
+	case 2:
+	case 4:
+	case 6:
+	case 7:
+		dev_warn(lnw->dev,
+			"OTG:NSF-%lu - deivce not responding\n", indicator);
+		break;
+	case 3:
+		dev_warn(lnw->dev,
+			"OTG:NSF-%lu - deivce not supported\n", indicator);
+		break;
+	default:
+		dev_warn(lnw->dev, "Do not have this kind of NSF\n");
+		break;
+	}
+}
+
+/* Initialize timers */
+static int langwell_otg_init_timers(struct otg_hsm *hsm)
+{
+	/* HSM used timers */
+	a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
+				(unsigned long)&hsm->a_wait_vrise_tmout);
+	if (a_wait_vrise_tmr == NULL)
+		return -ENOMEM;
+	a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS,
+				(unsigned long)&hsm->a_aidl_bdis_tmout);
+	if (a_aidl_bdis_tmr == NULL)
+		return -ENOMEM;
+	b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP,
+				(unsigned long)&hsm->b_se0_srp);
+	if (b_se0_srp_tmr == NULL)
+		return -ENOMEM;
+	b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT,
+				(unsigned long)&hsm->b_srp_init_tmout);
+	if (b_srp_init_tmr == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/* Free timers */
+static void langwell_otg_free_timers(void)
+{
+	kfree(a_wait_vrise_tmr);
+	kfree(a_aidl_bdis_tmr);
+	kfree(b_se0_srp_tmr);
+	kfree(b_srp_init_tmr);
+}
+
+/* The timeout callback function to set time out bit */
+static void langwell_otg_timer_fn(unsigned long indicator)
+{
+	struct langwell_otg *lnw = the_transceiver;
+
+	*(int *)indicator = 1;
+
+	dev_dbg(lnw->dev, "kernel timer - timeout\n");
+
+	langwell_update_transceiver();
+}
+
+/* kernel timer used instead of HW based interrupt */
+static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	unsigned long		j = jiffies;
+	unsigned long		data, time;
+
+	switch (timers) {
+	case TA_WAIT_VRISE_TMR:
+		iotg->hsm.a_wait_vrise_tmout = 0;
+		data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout;
+		time = TA_WAIT_VRISE;
+		break;
+	case TA_WAIT_BCON_TMR:
+		iotg->hsm.a_wait_bcon_tmout = 0;
+		data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout;
+		time = TA_WAIT_BCON;
+		break;
+	case TA_AIDL_BDIS_TMR:
+		iotg->hsm.a_aidl_bdis_tmout = 0;
+		data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout;
+		time = TA_AIDL_BDIS;
+		break;
+	case TB_ASE0_BRST_TMR:
+		iotg->hsm.b_ase0_brst_tmout = 0;
+		data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout;
+		time = TB_ASE0_BRST;
+		break;
+	case TB_SRP_INIT_TMR:
+		iotg->hsm.b_srp_init_tmout = 0;
+		data = (unsigned long)&iotg->hsm.b_srp_init_tmout;
+		time = TB_SRP_INIT;
+		break;
+	case TB_SRP_FAIL_TMR:
+		iotg->hsm.b_srp_fail_tmout = 0;
+		data = (unsigned long)&iotg->hsm.b_srp_fail_tmout;
+		time = TB_SRP_FAIL;
+		break;
+	case TB_BUS_SUSPEND_TMR:
+		iotg->hsm.b_bus_suspend_tmout = 0;
+		data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout;
+		time = TB_BUS_SUSPEND;
+		break;
+	default:
+		dev_dbg(lnw->dev, "unkown timer, cannot enable it\n");
+		return;
+	}
+
+	lnw->hsm_timer.data = data;
+	lnw->hsm_timer.function = langwell_otg_timer_fn;
+	lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */
+
+	add_timer(&lnw->hsm_timer);
+
+	dev_dbg(lnw->dev, "add timer successfully\n");
+}
+
+/* Add timer to timer list */
+static void langwell_otg_add_timer(void *gtimer)
+{
+	struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
+	struct langwell_otg_timer *tmp_timer;
+	struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg;
+	u32	val32;
+
+	/* Check if the timer is already in the active list,
+	 * if so update timer count
+	 */
+	list_for_each_entry(tmp_timer, &active_timers, list)
+		if (tmp_timer == timer) {
+			timer->count = timer->expires;
+			return;
+		}
+	timer->count = timer->expires;
+
+	if (list_empty(&active_timers)) {
+		val32 = readl(iotg->base + CI_OTGSC);
+		writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC);
+	}
+
+	list_add_tail(&timer->list, &active_timers);
+}
+
+/* Remove timer from the timer list; clear timeout status */
+static void langwell_otg_del_timer(void *gtimer)
+{
+	struct langwell_otg *lnw = the_transceiver;
+	struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
+	struct langwell_otg_timer *tmp_timer, *del_tmp;
+	u32 val32;
+
+	list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list)
+		if (tmp_timer == timer)
+			list_del(&timer->list);
+
+	if (list_empty(&active_timers)) {
+		val32 = readl(lnw->iotg.base + CI_OTGSC);
+		writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC);
+	}
+}
+
+/* Reduce timer count by 1, and find timeout conditions.*/
+static int langwell_otg_tick_timer(u32 *int_sts)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	struct langwell_otg_timer *tmp_timer, *del_tmp;
+	int expired = 0;
+
+	list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) {
+		tmp_timer->count--;
+		/* check if timer expires */
+		if (!tmp_timer->count) {
+			list_del(&tmp_timer->list);
+			tmp_timer->function(tmp_timer->data);
+			expired = 1;
+		}
+	}
+
+	if (list_empty(&active_timers)) {
+		dev_dbg(lnw->dev, "tick timer: disable 1ms int\n");
+		*int_sts = *int_sts & ~OTGSC_1MSE;
+	}
+	return expired;
+}
+
+static void reset_otg(void)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	int			delay_time = 1000;
+	u32			val;
+
+	dev_dbg(lnw->dev, "reseting OTG controller ...\n");
+	val = readl(lnw->iotg.base + CI_USBCMD);
+	writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD);
+	do {
+		udelay(100);
+		if (!delay_time--)
+			dev_dbg(lnw->dev, "reset timeout\n");
+		val = readl(lnw->iotg.base + CI_USBCMD);
+		val &= USBCMD_RST;
+	} while (val != 0);
+	dev_dbg(lnw->dev, "reset done.\n");
+}
+
+static void set_host_mode(void)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	u32			val;
+
+	reset_otg();
+	val = readl(lnw->iotg.base + CI_USBMODE);
+	val = (val & (~USBMODE_CM)) | USBMODE_HOST;
+	writel(val, lnw->iotg.base + CI_USBMODE);
+}
+
+static void set_client_mode(void)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	u32			val;
+
+	reset_otg();
+	val = readl(lnw->iotg.base + CI_USBMODE);
+	val = (val & (~USBMODE_CM)) | USBMODE_DEVICE;
+	writel(val, lnw->iotg.base + CI_USBMODE);
+}
+
+static void init_hsm(void)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val32;
+
+	/* read OTGSC after reset */
+	val32 = readl(lnw->iotg.base + CI_OTGSC);
+	dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32);
+
+	/* set init state */
+	if (val32 & OTGSC_ID) {
+		iotg->hsm.id = 1;
+		iotg->otg.default_a = 0;
+		set_client_mode();
+		iotg->otg.state = OTG_STATE_B_IDLE;
+	} else {
+		iotg->hsm.id = 0;
+		iotg->otg.default_a = 1;
+		set_host_mode();
+		iotg->otg.state = OTG_STATE_A_IDLE;
+	}
+
+	/* set session indicator */
+	if (val32 & OTGSC_BSE)
+		iotg->hsm.b_sess_end = 1;
+	if (val32 & OTGSC_BSV)
+		iotg->hsm.b_sess_vld = 1;
+	if (val32 & OTGSC_ASV)
+		iotg->hsm.a_sess_vld = 1;
+	if (val32 & OTGSC_AVV)
+		iotg->hsm.a_vbus_vld = 1;
+
+	/* defautly power the bus */
+	iotg->hsm.a_bus_req = 1;
+	iotg->hsm.a_bus_drop = 0;
+	/* defautly don't request bus as B device */
+	iotg->hsm.b_bus_req = 0;
+	/* no system error */
+	iotg->hsm.a_clr_err = 0;
+
+	langwell_otg_phy_low_power_wait(1);
+}
+
+static void update_hsm(void)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val32;
+
+	/* read OTGSC */
+	val32 = readl(lnw->iotg.base + CI_OTGSC);
+	dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32);
+
+	iotg->hsm.id = !!(val32 & OTGSC_ID);
+	iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE);
+	iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV);
+	iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV);
+	iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV);
+}
+
+static irqreturn_t otg_dummy_irq(int irq, void *_dev)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	void __iomem		*reg_base = _dev;
+	u32			val;
+	u32			int_mask = 0;
+
+	val = readl(reg_base + CI_USBMODE);
+	if ((val & USBMODE_CM) != USBMODE_DEVICE)
+		return IRQ_NONE;
+
+	val = readl(reg_base + CI_USBSTS);
+	int_mask = val & INTR_DUMMY_MASK;
+
+	if (int_mask == 0)
+		return IRQ_NONE;
+
+	/* clear hsm.b_conn here since host driver can't detect it
+	*  otg_dummy_irq called means B-disconnect happened.
+	*/
+	if (lnw->iotg.hsm.b_conn) {
+		lnw->iotg.hsm.b_conn = 0;
+		if (spin_trylock(&lnw->wq_lock)) {
+			langwell_update_transceiver();
+			spin_unlock(&lnw->wq_lock);
+		}
+	}
+
+	/* Clear interrupts */
+	writel(int_mask, reg_base + CI_USBSTS);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t otg_irq(int irq, void *_dev)
+{
+	struct langwell_otg		*lnw = _dev;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				int_sts, int_en;
+	u32				int_mask = 0;
+	int				flag = 0;
+
+	int_sts = readl(lnw->iotg.base + CI_OTGSC);
+	int_en = (int_sts & OTGSC_INTEN_MASK) >> 8;
+	int_mask = int_sts & int_en;
+	if (int_mask == 0)
+		return IRQ_NONE;
+
+	if (int_mask & OTGSC_IDIS) {
+		dev_dbg(lnw->dev, "%s: id change int\n", __func__);
+		iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0;
+		dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id);
+		flag = 1;
+	}
+	if (int_mask & OTGSC_DPIS) {
+		dev_dbg(lnw->dev, "%s: data pulse int\n", __func__);
+		iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0;
+		dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det);
+		flag = 1;
+	}
+	if (int_mask & OTGSC_BSEIS) {
+		dev_dbg(lnw->dev, "%s: b session end int\n", __func__);
+		iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0;
+		dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end);
+		flag = 1;
+	}
+	if (int_mask & OTGSC_BSVIS) {
+		dev_dbg(lnw->dev, "%s: b session valid int\n", __func__);
+		iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0;
+		dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end);
+		flag = 1;
+	}
+	if (int_mask & OTGSC_ASVIS) {
+		dev_dbg(lnw->dev, "%s: a session valid int\n", __func__);
+		iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0;
+		dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld);
+		flag = 1;
+	}
+	if (int_mask & OTGSC_AVVIS) {
+		dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__);
+		iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0;
+		dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld);
+		flag = 1;
+	}
+
+	if (int_mask & OTGSC_1MSS) {
+		/* need to schedule otg_work if any timer is expired */
+		if (langwell_otg_tick_timer(&int_sts))
+			flag = 1;
+	}
+
+	writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask,
+					lnw->iotg.base + CI_OTGSC);
+	if (flag)
+		langwell_update_transceiver();
+
+	return IRQ_HANDLED;
+}
+
+static int langwell_otg_iotg_notify(struct notifier_block *nb,
+				unsigned long action, void *data)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = data;
+	int				flag = 0;
+
+	if (iotg == NULL)
+		return NOTIFY_BAD;
+
+	if (lnw == NULL)
+		return NOTIFY_BAD;
+
+	switch (action) {
+	case MID_OTG_NOTIFY_CONNECT:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n");
+		if (iotg->otg.default_a == 1)
+			iotg->hsm.b_conn = 1;
+		else
+			iotg->hsm.a_conn = 1;
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_DISCONN:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n");
+		if (iotg->otg.default_a == 1)
+			iotg->hsm.b_conn = 0;
+		else
+			iotg->hsm.a_conn = 0;
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_HSUSPEND:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n");
+		if (iotg->otg.default_a == 1)
+			iotg->hsm.a_suspend_req = 1;
+		else
+			iotg->hsm.b_bus_req = 0;
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_HRESUME:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n");
+		if (iotg->otg.default_a == 1)
+			iotg->hsm.b_bus_resume = 1;
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_CSUSPEND:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n");
+		if (iotg->otg.default_a == 1) {
+			if (iotg->hsm.b_bus_suspend_vld == 2) {
+				iotg->hsm.b_bus_suspend = 1;
+				iotg->hsm.b_bus_suspend_vld = 0;
+				flag = 1;
+			} else {
+				iotg->hsm.b_bus_suspend_vld++;
+				flag = 0;
+			}
+		} else {
+			if (iotg->hsm.a_bus_suspend == 0) {
+				iotg->hsm.a_bus_suspend = 1;
+				flag = 1;
+			}
+		}
+		break;
+	case MID_OTG_NOTIFY_CRESUME:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n");
+		if (iotg->otg.default_a == 0)
+			iotg->hsm.a_bus_suspend = 0;
+		flag = 0;
+		break;
+	case MID_OTG_NOTIFY_HOSTADD:
+		dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n");
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_HOSTREMOVE:
+		dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n");
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_CLIENTADD:
+		dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n");
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_CLIENTREMOVE:
+		dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n");
+		flag = 1;
+		break;
+	default:
+		dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n");
+		return NOTIFY_DONE;
+	}
+
+	if (flag)
+		langwell_update_transceiver();
+
+	return NOTIFY_OK;
+}
+
+static void langwell_otg_work(struct work_struct *work)
+{
+	struct langwell_otg		*lnw;
+	struct intel_mid_otg_xceiv	*iotg;
+	int				retval;
+	struct pci_dev			*pdev;
+
+	lnw = container_of(work, struct langwell_otg, work);
+	iotg = &lnw->iotg;
+	pdev = to_pci_dev(lnw->dev);
+
+	dev_dbg(lnw->dev, "%s: old state = %s\n", __func__,
+			state_string(iotg->otg.state));
+
+	switch (iotg->otg.state) {
+	case OTG_STATE_UNDEFINED:
+	case OTG_STATE_B_IDLE:
+		if (!iotg->hsm.id) {
+			langwell_otg_del_timer(b_srp_init_tmr);
+			del_timer_sync(&lnw->hsm_timer);
+
+			iotg->otg.default_a = 1;
+			iotg->hsm.a_srp_det = 0;
+
+			langwell_otg_chrg_vbus(0);
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+
+			iotg->otg.state = OTG_STATE_A_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.b_sess_vld) {
+			langwell_otg_del_timer(b_srp_init_tmr);
+			del_timer_sync(&lnw->hsm_timer);
+			iotg->hsm.b_sess_end = 0;
+			iotg->hsm.a_bus_suspend = 0;
+			langwell_otg_chrg_vbus(0);
+
+			if (lnw->iotg.start_peripheral) {
+				lnw->iotg.start_peripheral(&lnw->iotg);
+				iotg->otg.state = OTG_STATE_B_PERIPHERAL;
+			} else
+				dev_dbg(lnw->dev, "client driver not loaded\n");
+
+		} else if (iotg->hsm.b_srp_init_tmout) {
+			iotg->hsm.b_srp_init_tmout = 0;
+			dev_warn(lnw->dev, "SRP init timeout\n");
+		} else if (iotg->hsm.b_srp_fail_tmout) {
+			iotg->hsm.b_srp_fail_tmout = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			/* No silence failure */
+			langwell_otg_nsf_msg(6);
+		} else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) {
+			del_timer_sync(&lnw->hsm_timer);
+			/* workaround for b_se0_srp detection */
+			retval = langwell_otg_check_se0_srp(0);
+			if (retval) {
+				iotg->hsm.b_bus_req = 0;
+				dev_dbg(lnw->dev, "LS isn't SE0, try later\n");
+			} else {
+				/* clear the PHCD before start srp */
+				langwell_otg_phy_low_power(0);
+
+				/* Start SRP */
+				langwell_otg_add_timer(b_srp_init_tmr);
+				iotg->otg.start_srp(&iotg->otg);
+				langwell_otg_del_timer(b_srp_init_tmr);
+				langwell_otg_add_ktimer(TB_SRP_FAIL_TMR);
+
+				/* reset PHY low power mode here */
+				langwell_otg_phy_low_power_wait(1);
+			}
+		}
+		break;
+	case OTG_STATE_B_SRP_INIT:
+		if (!iotg->hsm.id) {
+			iotg->otg.default_a = 1;
+			iotg->hsm.a_srp_det = 0;
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			langwell_otg_chrg_vbus(0);
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_A_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.b_sess_vld) {
+			langwell_otg_chrg_vbus(0);
+			if (lnw->iotg.start_peripheral) {
+				lnw->iotg.start_peripheral(&lnw->iotg);
+				iotg->otg.state = OTG_STATE_B_PERIPHERAL;
+			} else
+				dev_dbg(lnw->dev, "client driver not loaded\n");
+		}
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		if (!iotg->hsm.id) {
+			iotg->otg.default_a = 1;
+			iotg->hsm.a_srp_det = 0;
+
+			langwell_otg_chrg_vbus(0);
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_A_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.b_sess_vld) {
+			iotg->hsm.b_hnp_enable = 0;
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			iotg->otg.state = OTG_STATE_B_IDLE;
+		} else if (iotg->hsm.b_bus_req && iotg->otg.gadget &&
+					iotg->otg.gadget->b_hnp_enable &&
+					iotg->hsm.a_bus_suspend) {
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			langwell_otg_HAAR(1);
+			iotg->hsm.a_conn = 0;
+
+			if (lnw->iotg.start_host) {
+				lnw->iotg.start_host(&lnw->iotg);
+				iotg->otg.state = OTG_STATE_B_WAIT_ACON;
+			} else
+				dev_dbg(lnw->dev,
+						"host driver not loaded.\n");
+
+			iotg->hsm.a_bus_resume = 0;
+			langwell_otg_add_ktimer(TB_ASE0_BRST_TMR);
+		}
+		break;
+
+	case OTG_STATE_B_WAIT_ACON:
+		if (!iotg->hsm.id) {
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			iotg->otg.default_a = 1;
+			iotg->hsm.a_srp_det = 0;
+
+			langwell_otg_chrg_vbus(0);
+
+			langwell_otg_HAAR(0);
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_A_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.b_sess_vld) {
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			iotg->hsm.b_hnp_enable = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			langwell_otg_chrg_vbus(0);
+			langwell_otg_HAAR(0);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+		} else if (iotg->hsm.a_conn) {
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			langwell_otg_HAAR(0);
+			iotg->otg.state = OTG_STATE_B_HOST;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.a_bus_resume ||
+				iotg->hsm.b_ase0_brst_tmout) {
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			langwell_otg_HAAR(0);
+			langwell_otg_nsf_msg(7);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			iotg->hsm.a_bus_suspend = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			if (lnw->iotg.start_peripheral)
+				lnw->iotg.start_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver not loaded.\n");
+
+			iotg->otg.state = OTG_STATE_B_PERIPHERAL;
+		}
+		break;
+
+	case OTG_STATE_B_HOST:
+		if (!iotg->hsm.id) {
+			iotg->otg.default_a = 1;
+			iotg->hsm.a_srp_det = 0;
+
+			langwell_otg_chrg_vbus(0);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_A_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.b_sess_vld) {
+			iotg->hsm.b_hnp_enable = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			langwell_otg_chrg_vbus(0);
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+		} else if ((!iotg->hsm.b_bus_req) ||
+				(!iotg->hsm.a_conn)) {
+			iotg->hsm.b_bus_req = 0;
+			langwell_otg_loc_sof(0);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			iotg->hsm.a_bus_suspend = 0;
+
+			if (lnw->iotg.start_peripheral)
+				lnw->iotg.start_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+						"client driver not loaded.\n");
+
+			iotg->otg.state = OTG_STATE_B_PERIPHERAL;
+		}
+		break;
+
+	case OTG_STATE_A_IDLE:
+		iotg->otg.default_a = 1;
+		if (iotg->hsm.id) {
+			iotg->otg.default_a = 0;
+			iotg->hsm.b_bus_req = 0;
+			iotg->hsm.vbus_srp_up = 0;
+
+			langwell_otg_chrg_vbus(0);
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.a_bus_drop &&
+			(iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) {
+			langwell_otg_phy_low_power(0);
+
+			/* Turn on VBus */
+			iotg->otg.set_vbus(&iotg->otg, true);
+
+			iotg->hsm.vbus_srp_up = 0;
+			iotg->hsm.a_wait_vrise_tmout = 0;
+			langwell_otg_add_timer(a_wait_vrise_tmr);
+			iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) {
+			iotg->hsm.vbus_srp_up = 1;
+		} else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) {
+			msleep(10);
+			langwell_otg_phy_low_power(0);
+
+			/* Turn on VBus */
+			iotg->otg.set_vbus(&iotg->otg, true);
+			iotg->hsm.a_srp_det = 1;
+			iotg->hsm.vbus_srp_up = 0;
+			iotg->hsm.a_wait_vrise_tmout = 0;
+			langwell_otg_add_timer(a_wait_vrise_tmr);
+			iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.a_sess_vld &&
+				!iotg->hsm.vbus_srp_up) {
+			langwell_otg_phy_low_power(1);
+		}
+		break;
+	case OTG_STATE_A_WAIT_VRISE:
+		if (iotg->hsm.id) {
+			langwell_otg_del_timer(a_wait_vrise_tmr);
+			iotg->hsm.b_bus_req = 0;
+			iotg->otg.default_a = 0;
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			set_client_mode();
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+		} else if (iotg->hsm.a_vbus_vld) {
+			langwell_otg_del_timer(a_wait_vrise_tmr);
+			iotg->hsm.b_conn = 0;
+			if (lnw->iotg.start_host)
+				lnw->iotg.start_host(&lnw->iotg);
+			else {
+				dev_dbg(lnw->dev, "host driver not loaded.\n");
+				break;
+			}
+
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
+			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
+		} else if (iotg->hsm.a_wait_vrise_tmout) {
+			iotg->hsm.b_conn = 0;
+			if (iotg->hsm.a_vbus_vld) {
+				if (lnw->iotg.start_host)
+					lnw->iotg.start_host(&lnw->iotg);
+				else {
+					dev_dbg(lnw->dev,
+						"host driver not loaded.\n");
+					break;
+				}
+				langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
+				iotg->otg.state = OTG_STATE_A_WAIT_BCON;
+			} else {
+
+				/* Turn off VBus */
+				iotg->otg.set_vbus(&iotg->otg, false);
+				langwell_otg_phy_low_power_wait(1);
+				iotg->otg.state = OTG_STATE_A_VBUS_ERR;
+			}
+		}
+		break;
+	case OTG_STATE_A_WAIT_BCON:
+		if (iotg->hsm.id) {
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			iotg->otg.default_a = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			set_client_mode();
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.a_vbus_vld) {
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
+		} else if (iotg->hsm.a_bus_drop ||
+				(iotg->hsm.a_wait_bcon_tmout &&
+				!iotg->hsm.a_bus_req)) {
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
+		} else if (iotg->hsm.b_conn) {
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			iotg->hsm.a_suspend_req = 0;
+			iotg->otg.state = OTG_STATE_A_HOST;
+			if (iotg->hsm.a_srp_det && iotg->otg.host &&
+					!iotg->otg.host->b_hnp_enable) {
+				/* SRP capable peripheral-only device */
+				iotg->hsm.a_bus_req = 1;
+				iotg->hsm.a_srp_det = 0;
+			} else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
+					iotg->otg.host->b_hnp_enable) {
+				/* It is not safe enough to do a fast
+				 * transistion from A_WAIT_BCON to
+				 * A_SUSPEND */
+				msleep(10000);
+				if (iotg->hsm.a_bus_req)
+					break;
+
+				if (request_irq(pdev->irq,
+					otg_dummy_irq, IRQF_SHARED,
+					driver_name, iotg->base) != 0) {
+					dev_dbg(lnw->dev,
+						"request interrupt %d fail\n",
+						pdev->irq);
+				}
+
+				langwell_otg_HABA(1);
+				iotg->hsm.b_bus_resume = 0;
+				iotg->hsm.a_aidl_bdis_tmout = 0;
+
+				langwell_otg_loc_sof(0);
+				/* clear PHCD to enable HW timer */
+				langwell_otg_phy_low_power(0);
+				langwell_otg_add_timer(a_aidl_bdis_tmr);
+				iotg->otg.state = OTG_STATE_A_SUSPEND;
+			} else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
+				!iotg->otg.host->b_hnp_enable) {
+				if (lnw->iotg.stop_host)
+					lnw->iotg.stop_host(&lnw->iotg);
+				else
+					dev_dbg(lnw->dev,
+						"host driver removed.\n");
+
+				/* Turn off VBus */
+				iotg->otg.set_vbus(&iotg->otg, false);
+				iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
+			}
+		}
+		break;
+	case OTG_STATE_A_HOST:
+		if (iotg->hsm.id) {
+			iotg->otg.default_a = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			set_client_mode();
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.a_bus_drop ||
+				(iotg->otg.host &&
+				!iotg->otg.host->b_hnp_enable &&
+					!iotg->hsm.a_bus_req)) {
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
+		} else if (!iotg->hsm.a_vbus_vld) {
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
+		} else if (iotg->otg.host &&
+				iotg->otg.host->b_hnp_enable &&
+				!iotg->hsm.a_bus_req) {
+			/* Set HABA to enable hardware assistance to signal
+			 *  A-connect after receiver B-disconnect. Hardware
+			 *  will then set client mode and enable URE, SLE and
+			 *  PCE after the assistance. otg_dummy_irq is used to
+			 *  clean these ints when client driver is not resumed.
+			 */
+			if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED,
+					driver_name, iotg->base) != 0) {
+				dev_dbg(lnw->dev,
+					"request interrupt %d failed\n",
+						pdev->irq);
+			}
+
+			/* set HABA */
+			langwell_otg_HABA(1);
+			iotg->hsm.b_bus_resume = 0;
+			iotg->hsm.a_aidl_bdis_tmout = 0;
+			langwell_otg_loc_sof(0);
+			/* clear PHCD to enable HW timer */
+			langwell_otg_phy_low_power(0);
+			langwell_otg_add_timer(a_aidl_bdis_tmr);
+			iotg->otg.state = OTG_STATE_A_SUSPEND;
+		} else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) {
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
+			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
+		}
+		break;
+	case OTG_STATE_A_SUSPEND:
+		if (iotg->hsm.id) {
+			langwell_otg_del_timer(a_aidl_bdis_tmr);
+			langwell_otg_HABA(0);
+			free_irq(pdev->irq, iotg->base);
+			iotg->otg.default_a = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.a_bus_req ||
+				iotg->hsm.b_bus_resume) {
+			langwell_otg_del_timer(a_aidl_bdis_tmr);
+			langwell_otg_HABA(0);
+			free_irq(pdev->irq, iotg->base);
+			iotg->hsm.a_suspend_req = 0;
+			langwell_otg_loc_sof(1);
+			iotg->otg.state = OTG_STATE_A_HOST;
+		} else if (iotg->hsm.a_aidl_bdis_tmout ||
+				iotg->hsm.a_bus_drop) {
+			langwell_otg_del_timer(a_aidl_bdis_tmr);
+			langwell_otg_HABA(0);
+			free_irq(pdev->irq, iotg->base);
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
+		} else if (!iotg->hsm.b_conn && iotg->otg.host &&
+				iotg->otg.host->b_hnp_enable) {
+			langwell_otg_del_timer(a_aidl_bdis_tmr);
+			langwell_otg_HABA(0);
+			free_irq(pdev->irq, iotg->base);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			iotg->hsm.b_bus_suspend = 0;
+			iotg->hsm.b_bus_suspend_vld = 0;
+
+			/* msleep(200); */
+			if (lnw->iotg.start_peripheral)
+				lnw->iotg.start_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver not loaded.\n");
+
+			langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR);
+			iotg->otg.state = OTG_STATE_A_PERIPHERAL;
+			break;
+		} else if (!iotg->hsm.a_vbus_vld) {
+			langwell_otg_del_timer(a_aidl_bdis_tmr);
+			langwell_otg_HABA(0);
+			free_irq(pdev->irq, iotg->base);
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
+		}
+		break;
+	case OTG_STATE_A_PERIPHERAL:
+		if (iotg->hsm.id) {
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+			iotg->otg.default_a = 0;
+			iotg->hsm.b_bus_req = 0;
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			set_client_mode();
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.a_vbus_vld) {
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
+		} else if (iotg->hsm.a_bus_drop) {
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
+		} else if (iotg->hsm.b_bus_suspend) {
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			if (lnw->iotg.start_host)
+				lnw->iotg.start_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+						"host driver not loaded.\n");
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
+			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
+		} else if (iotg->hsm.b_bus_suspend_tmout) {
+			u32	val;
+			val = readl(lnw->iotg.base + CI_PORTSC1);
+			if (!(val & PORTSC_SUSP))
+				break;
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			if (lnw->iotg.start_host)
+				lnw->iotg.start_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+						"host driver not loaded.\n");
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
+			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
+		}
+		break;
+	case OTG_STATE_A_VBUS_ERR:
+		if (iotg->hsm.id) {
+			iotg->otg.default_a = 0;
+			iotg->hsm.a_clr_err = 0;
+			iotg->hsm.a_srp_det = 0;
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.a_clr_err) {
+			iotg->hsm.a_clr_err = 0;
+			iotg->hsm.a_srp_det = 0;
+			reset_otg();
+			init_hsm();
+			if (iotg->otg.state == OTG_STATE_A_IDLE)
+				langwell_update_transceiver();
+		} else {
+			/* FW will clear PHCD bit when any VBus
+			 * event detected. Reset PHCD to 1 again */
+			langwell_otg_phy_low_power(1);
+		}
+		break;
+	case OTG_STATE_A_WAIT_VFALL:
+		if (iotg->hsm.id) {
+			iotg->otg.default_a = 0;
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.a_bus_req) {
+
+			/* Turn on VBus */
+			iotg->otg.set_vbus(&iotg->otg, true);
+			iotg->hsm.a_wait_vrise_tmout = 0;
+			langwell_otg_add_timer(a_wait_vrise_tmr);
+			iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
+		} else if (!iotg->hsm.a_sess_vld) {
+			iotg->hsm.a_srp_det = 0;
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_A_IDLE;
+		}
+		break;
+	default:
+		;
+	}
+
+	dev_dbg(lnw->dev, "%s: new state = %s\n", __func__,
+			state_string(iotg->otg.state));
+}
+
+static ssize_t
+show_registers(struct device *_dev, struct device_attribute *attr, char *buf)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	char			*next;
+	unsigned		size, t;
+
+	next = buf;
+	size = PAGE_SIZE;
+
+	t = scnprintf(next, size,
+		"\n"
+		"USBCMD = 0x%08x\n"
+		"USBSTS = 0x%08x\n"
+		"USBINTR = 0x%08x\n"
+		"ASYNCLISTADDR = 0x%08x\n"
+		"PORTSC1 = 0x%08x\n"
+		"HOSTPC1 = 0x%08x\n"
+		"OTGSC = 0x%08x\n"
+		"USBMODE = 0x%08x\n",
+		readl(lnw->iotg.base + 0x30),
+		readl(lnw->iotg.base + 0x34),
+		readl(lnw->iotg.base + 0x38),
+		readl(lnw->iotg.base + 0x48),
+		readl(lnw->iotg.base + 0x74),
+		readl(lnw->iotg.base + 0xb4),
+		readl(lnw->iotg.base + 0xf4),
+		readl(lnw->iotg.base + 0xf8)
+	     );
+	size -= t;
+	next += t;
+
+	return PAGE_SIZE - size;
+}
+static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
+
+static ssize_t
+show_hsm(struct device *_dev, struct device_attribute *attr, char *buf)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	char				*next;
+	unsigned			size, t;
+
+	next = buf;
+	size = PAGE_SIZE;
+
+	if (iotg->otg.host)
+		iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable;
+
+	if (iotg->otg.gadget)
+		iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable;
+
+	t = scnprintf(next, size,
+		"\n"
+		"current state = %s\n"
+		"a_bus_resume = \t%d\n"
+		"a_bus_suspend = \t%d\n"
+		"a_conn = \t%d\n"
+		"a_sess_vld = \t%d\n"
+		"a_srp_det = \t%d\n"
+		"a_vbus_vld = \t%d\n"
+		"b_bus_resume = \t%d\n"
+		"b_bus_suspend = \t%d\n"
+		"b_conn = \t%d\n"
+		"b_se0_srp = \t%d\n"
+		"b_sess_end = \t%d\n"
+		"b_sess_vld = \t%d\n"
+		"id = \t%d\n"
+		"a_set_b_hnp_en = \t%d\n"
+		"b_srp_done = \t%d\n"
+		"b_hnp_enable = \t%d\n"
+		"a_wait_vrise_tmout = \t%d\n"
+		"a_wait_bcon_tmout = \t%d\n"
+		"a_aidl_bdis_tmout = \t%d\n"
+		"b_ase0_brst_tmout = \t%d\n"
+		"a_bus_drop = \t%d\n"
+		"a_bus_req = \t%d\n"
+		"a_clr_err = \t%d\n"
+		"a_suspend_req = \t%d\n"
+		"b_bus_req = \t%d\n"
+		"b_bus_suspend_tmout = \t%d\n"
+		"b_bus_suspend_vld = \t%d\n",
+		state_string(iotg->otg.state),
+		iotg->hsm.a_bus_resume,
+		iotg->hsm.a_bus_suspend,
+		iotg->hsm.a_conn,
+		iotg->hsm.a_sess_vld,
+		iotg->hsm.a_srp_det,
+		iotg->hsm.a_vbus_vld,
+		iotg->hsm.b_bus_resume,
+		iotg->hsm.b_bus_suspend,
+		iotg->hsm.b_conn,
+		iotg->hsm.b_se0_srp,
+		iotg->hsm.b_sess_end,
+		iotg->hsm.b_sess_vld,
+		iotg->hsm.id,
+		iotg->hsm.a_set_b_hnp_en,
+		iotg->hsm.b_srp_done,
+		iotg->hsm.b_hnp_enable,
+		iotg->hsm.a_wait_vrise_tmout,
+		iotg->hsm.a_wait_bcon_tmout,
+		iotg->hsm.a_aidl_bdis_tmout,
+		iotg->hsm.b_ase0_brst_tmout,
+		iotg->hsm.a_bus_drop,
+		iotg->hsm.a_bus_req,
+		iotg->hsm.a_clr_err,
+		iotg->hsm.a_suspend_req,
+		iotg->hsm.b_bus_req,
+		iotg->hsm.b_bus_suspend_tmout,
+		iotg->hsm.b_bus_suspend_vld
+		);
+	size -= t;
+	next += t;
+
+	return PAGE_SIZE - size;
+}
+static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL);
+
+static ssize_t
+get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	char			*next;
+	unsigned		size, t;
+
+	next = buf;
+	size = PAGE_SIZE;
+
+	t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req);
+	size -= t;
+	next += t;
+
+	return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_a_bus_req(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+
+	if (!iotg->otg.default_a)
+		return -1;
+	if (count > 2)
+		return -1;
+
+	if (buf[0] == '0') {
+		iotg->hsm.a_bus_req = 0;
+		dev_dbg(lnw->dev, "User request: a_bus_req = 0\n");
+	} else if (buf[0] == '1') {
+		/* If a_bus_drop is TRUE, a_bus_req can't be set */
+		if (iotg->hsm.a_bus_drop)
+			return -1;
+		iotg->hsm.a_bus_req = 1;
+		dev_dbg(lnw->dev, "User request: a_bus_req = 1\n");
+	}
+	if (spin_trylock(&lnw->wq_lock)) {
+		langwell_update_transceiver();
+		spin_unlock(&lnw->wq_lock);
+	}
+	return count;
+}
+static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUGO, get_a_bus_req, set_a_bus_req);
+
+static ssize_t
+get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	char			*next;
+	unsigned		size, t;
+
+	next = buf;
+	size = PAGE_SIZE;
+
+	t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop);
+	size -= t;
+	next += t;
+
+	return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_a_bus_drop(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+
+	if (!iotg->otg.default_a)
+		return -1;
+	if (count > 2)
+		return -1;
+
+	if (buf[0] == '0') {
+		iotg->hsm.a_bus_drop = 0;
+		dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n");
+	} else if (buf[0] == '1') {
+		iotg->hsm.a_bus_drop = 1;
+		iotg->hsm.a_bus_req = 0;
+		dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n");
+		dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n");
+	}
+	if (spin_trylock(&lnw->wq_lock)) {
+		langwell_update_transceiver();
+		spin_unlock(&lnw->wq_lock);
+	}
+	return count;
+}
+static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUGO,
+	get_a_bus_drop, set_a_bus_drop);
+
+static ssize_t
+get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	char			*next;
+	unsigned		size, t;
+
+	next = buf;
+	size = PAGE_SIZE;
+
+	t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req);
+	size -= t;
+	next += t;
+
+	return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_b_bus_req(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+
+	if (iotg->otg.default_a)
+		return -1;
+
+	if (count > 2)
+		return -1;
+
+	if (buf[0] == '0') {
+		iotg->hsm.b_bus_req = 0;
+		dev_dbg(lnw->dev, "User request: b_bus_req = 0\n");
+	} else if (buf[0] == '1') {
+		iotg->hsm.b_bus_req = 1;
+		dev_dbg(lnw->dev, "User request: b_bus_req = 1\n");
+	}
+	if (spin_trylock(&lnw->wq_lock)) {
+		langwell_update_transceiver();
+		spin_unlock(&lnw->wq_lock);
+	}
+	return count;
+}
+static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUGO, get_b_bus_req, set_b_bus_req);
+
+static ssize_t
+set_a_clr_err(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+
+	if (!iotg->otg.default_a)
+		return -1;
+	if (count > 2)
+		return -1;
+
+	if (buf[0] == '1') {
+		iotg->hsm.a_clr_err = 1;
+		dev_dbg(lnw->dev, "User request: a_clr_err = 1\n");
+	}
+	if (spin_trylock(&lnw->wq_lock)) {
+		langwell_update_transceiver();
+		spin_unlock(&lnw->wq_lock);
+	}
+	return count;
+}
+static DEVICE_ATTR(a_clr_err, S_IWUGO, NULL, set_a_clr_err);
+
+static struct attribute *inputs_attrs[] = {
+	&dev_attr_a_bus_req.attr,
+	&dev_attr_a_bus_drop.attr,
+	&dev_attr_b_bus_req.attr,
+	&dev_attr_a_clr_err.attr,
+	NULL,
+};
+
+static struct attribute_group debug_dev_attr_group = {
+	.name = "inputs",
+	.attrs = inputs_attrs,
+};
+
+static int langwell_otg_probe(struct pci_dev *pdev,
+		const struct pci_device_id *id)
+{
+	unsigned long		resource, len;
+	void __iomem		*base = NULL;
+	int			retval;
+	u32			val32;
+	struct langwell_otg	*lnw;
+	char			qname[] = "langwell_otg_queue";
+
+	retval = 0;
+	dev_dbg(&pdev->dev, "\notg controller is detected.\n");
+	if (pci_enable_device(pdev) < 0) {
+		retval = -ENODEV;
+		goto done;
+	}
+
+	lnw = kzalloc(sizeof *lnw, GFP_KERNEL);
+	if (lnw == NULL) {
+		retval = -ENOMEM;
+		goto done;
+	}
+	the_transceiver = lnw;
+
+	/* control register: BAR 0 */
+	resource = pci_resource_start(pdev, 0);
+	len = pci_resource_len(pdev, 0);
+	if (!request_mem_region(resource, len, driver_name)) {
+		retval = -EBUSY;
+		goto err;
+	}
+	lnw->region = 1;
+
+	base = ioremap_nocache(resource, len);
+	if (base == NULL) {
+		retval = -EFAULT;
+		goto err;
+	}
+	lnw->iotg.base = base;
+
+	if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) {
+		retval = -EBUSY;
+		goto err;
+	}
+	lnw->cfg_region = 1;
+
+	/* For the SCCB.USBCFG register */
+	base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN);
+	if (base == NULL) {
+		retval = -EFAULT;
+		goto err;
+	}
+	lnw->usbcfg = base;
+
+	if (!pdev->irq) {
+		dev_dbg(&pdev->dev, "No IRQ.\n");
+		retval = -ENODEV;
+		goto err;
+	}
+
+	lnw->qwork = create_singlethread_workqueue(qname);
+	if (!lnw->qwork) {
+		dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname);
+		retval = -ENOMEM;
+		goto err;
+	}
+	INIT_WORK(&lnw->work, langwell_otg_work);
+
+	/* OTG common part */
+	lnw->dev = &pdev->dev;
+	lnw->iotg.otg.dev = lnw->dev;
+	lnw->iotg.otg.label = driver_name;
+	lnw->iotg.otg.set_host = langwell_otg_set_host;
+	lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral;
+	lnw->iotg.otg.set_power = langwell_otg_set_power;
+	lnw->iotg.otg.set_vbus = langwell_otg_set_vbus;
+	lnw->iotg.otg.start_srp = langwell_otg_start_srp;
+	lnw->iotg.otg.state = OTG_STATE_UNDEFINED;
+
+	if (otg_set_transceiver(&lnw->iotg.otg)) {
+		dev_dbg(lnw->dev, "can't set transceiver\n");
+		retval = -EBUSY;
+		goto err;
+	}
+
+	reset_otg();
+	init_hsm();
+
+	spin_lock_init(&lnw->lock);
+	spin_lock_init(&lnw->wq_lock);
+	INIT_LIST_HEAD(&active_timers);
+	retval = langwell_otg_init_timers(&lnw->iotg.hsm);
+	if (retval) {
+		dev_dbg(&pdev->dev, "Failed to init timers\n");
+		goto err;
+	}
+
+	init_timer(&lnw->hsm_timer);
+	ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier);
+
+	lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify;
+
+	retval = intel_mid_otg_register_notifier(&lnw->iotg,
+						&lnw->iotg_notifier);
+	if (retval) {
+		dev_dbg(lnw->dev, "Failed to register notifier\n");
+		goto err;
+	}
+
+	if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
+				driver_name, lnw) != 0) {
+		dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq);
+		retval = -EBUSY;
+		goto err;
+	}
+
+	/* enable OTGSC int */
+	val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE |
+		OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU;
+	writel(val32, lnw->iotg.base + CI_OTGSC);
+
+	retval = device_create_file(&pdev->dev, &dev_attr_registers);
+	if (retval < 0) {
+		dev_dbg(lnw->dev,
+			"Can't register sysfs attribute: %d\n", retval);
+		goto err;
+	}
+
+	retval = device_create_file(&pdev->dev, &dev_attr_hsm);
+	if (retval < 0) {
+		dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval);
+		goto err;
+	}
+
+	retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group);
+	if (retval < 0) {
+		dev_dbg(lnw->dev,
+			"Can't register sysfs attr group: %d\n", retval);
+		goto err;
+	}
+
+	if (lnw->iotg.otg.state == OTG_STATE_A_IDLE)
+		langwell_update_transceiver();
+
+	return 0;
+
+err:
+	if (the_transceiver)
+		langwell_otg_remove(pdev);
+done:
+	return retval;
+}
+
+static void langwell_otg_remove(struct pci_dev *pdev)
+{
+	struct langwell_otg *lnw = the_transceiver;
+
+	if (lnw->qwork) {
+		flush_workqueue(lnw->qwork);
+		destroy_workqueue(lnw->qwork);
+	}
+	intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier);
+	langwell_otg_free_timers();
+
+	/* disable OTGSC interrupt as OTGSC doesn't change in reset */
+	writel(0, lnw->iotg.base + CI_OTGSC);
+
+	if (pdev->irq)
+		free_irq(pdev->irq, lnw);
+	if (lnw->usbcfg)
+		iounmap(lnw->usbcfg);
+	if (lnw->cfg_region)
+		release_mem_region(USBCFG_ADDR, USBCFG_LEN);
+	if (lnw->iotg.base)
+		iounmap(lnw->iotg.base);
+	if (lnw->region)
+		release_mem_region(pci_resource_start(pdev, 0),
+				pci_resource_len(pdev, 0));
+
+	otg_set_transceiver(NULL);
+	pci_disable_device(pdev);
+	sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group);
+	device_remove_file(&pdev->dev, &dev_attr_hsm);
+	device_remove_file(&pdev->dev, &dev_attr_registers);
+	kfree(lnw);
+	lnw = NULL;
+}
+
+static void transceiver_suspend(struct pci_dev *pdev)
+{
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+	langwell_otg_phy_low_power(1);
+}
+
+static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	int				ret = 0;
+
+	/* Disbale OTG interrupts */
+	langwell_otg_intr(0);
+
+	if (pdev->irq)
+		free_irq(pdev->irq, lnw);
+
+	/* Prevent more otg_work */
+	flush_workqueue(lnw->qwork);
+	destroy_workqueue(lnw->qwork);
+	lnw->qwork = NULL;
+
+	/* start actions */
+	switch (iotg->otg.state) {
+	case OTG_STATE_A_WAIT_VFALL:
+		iotg->otg.state = OTG_STATE_A_IDLE;
+	case OTG_STATE_A_IDLE:
+	case OTG_STATE_B_IDLE:
+	case OTG_STATE_A_VBUS_ERR:
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_A_WAIT_VRISE:
+		langwell_otg_del_timer(a_wait_vrise_tmr);
+		iotg->hsm.a_srp_det = 0;
+
+		/* Turn off VBus */
+		iotg->otg.set_vbus(&iotg->otg, false);
+		iotg->otg.state = OTG_STATE_A_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_A_WAIT_BCON:
+		del_timer_sync(&lnw->hsm_timer);
+		if (lnw->iotg.stop_host)
+			lnw->iotg.stop_host(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev, "host driver has been removed.\n");
+
+		iotg->hsm.a_srp_det = 0;
+
+		/* Turn off VBus */
+		iotg->otg.set_vbus(&iotg->otg, false);
+		iotg->otg.state = OTG_STATE_A_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_A_HOST:
+		if (lnw->iotg.stop_host)
+			lnw->iotg.stop_host(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev, "host driver has been removed.\n");
+
+		iotg->hsm.a_srp_det = 0;
+
+		/* Turn off VBus */
+		iotg->otg.set_vbus(&iotg->otg, false);
+
+		iotg->otg.state = OTG_STATE_A_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_A_SUSPEND:
+		langwell_otg_del_timer(a_aidl_bdis_tmr);
+		langwell_otg_HABA(0);
+		if (lnw->iotg.stop_host)
+			lnw->iotg.stop_host(&lnw->iotg);
+		else
+			dev_dbg(lnw->dev, "host driver has been removed.\n");
+		iotg->hsm.a_srp_det = 0;
+
+		/* Turn off VBus */
+		iotg->otg.set_vbus(&iotg->otg, false);
+		iotg->otg.state = OTG_STATE_A_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_A_PERIPHERAL:
+		del_timer_sync(&lnw->hsm_timer);
+
+		if (lnw->iotg.stop_peripheral)
+			lnw->iotg.stop_peripheral(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev,
+				"client driver has been removed.\n");
+		iotg->hsm.a_srp_det = 0;
+
+		/* Turn off VBus */
+		iotg->otg.set_vbus(&iotg->otg, false);
+		iotg->otg.state = OTG_STATE_A_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_B_HOST:
+		if (lnw->iotg.stop_host)
+			lnw->iotg.stop_host(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev, "host driver has been removed.\n");
+		iotg->hsm.b_bus_req = 0;
+		iotg->otg.state = OTG_STATE_B_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		if (lnw->iotg.stop_peripheral)
+			lnw->iotg.stop_peripheral(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev,
+				"client driver has been removed.\n");
+		iotg->otg.state = OTG_STATE_B_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_B_WAIT_ACON:
+		/* delete hsm timer for b_ase0_brst_tmr */
+		del_timer_sync(&lnw->hsm_timer);
+
+		langwell_otg_HAAR(0);
+
+		if (lnw->iotg.stop_host)
+			lnw->iotg.stop_host(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev, "host driver has been removed.\n");
+		iotg->hsm.b_bus_req = 0;
+		iotg->otg.state = OTG_STATE_B_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	default:
+		dev_dbg(lnw->dev, "error state before suspend\n");
+		break;
+	}
+
+	return ret;
+}
+
+static void transceiver_resume(struct pci_dev *pdev)
+{
+	pci_restore_state(pdev);
+	pci_set_power_state(pdev, PCI_D0);
+}
+
+static int langwell_otg_resume(struct pci_dev *pdev)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	int			ret = 0;
+
+	transceiver_resume(pdev);
+
+	lnw->qwork = create_singlethread_workqueue("langwell_otg_queue");
+	if (!lnw->qwork) {
+		dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen");
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
+				driver_name, lnw) != 0) {
+		dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq);
+		ret = -EBUSY;
+		goto error;
+	}
+
+	/* enable OTG interrupts */
+	langwell_otg_intr(1);
+
+	update_hsm();
+
+	langwell_update_transceiver();
+
+	return ret;
+error:
+	langwell_otg_intr(0);
+	transceiver_suspend(pdev);
+	return ret;
+}
+
+static int __init langwell_otg_init(void)
+{
+	return pci_register_driver(&otg_pci_driver);
+}
+module_init(langwell_otg_init);
+
+static void __exit langwell_otg_cleanup(void)
+{
+	pci_unregister_driver(&otg_pci_driver);
+}
+module_exit(langwell_otg_cleanup);
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
index ccc8195..059d9ac 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/otg/ulpi.c
@@ -29,12 +29,23 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 
+
+struct ulpi_info {
+	unsigned int	id;
+	char		*name;
+};
+
 #define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
+#define ULPI_INFO(_id, _name)		\
+	{				\
+		.id	= (_id),	\
+		.name	= (_name),	\
+	}
 
 /* ULPI hardcoded IDs, used for probing */
-static unsigned int ulpi_ids[] = {
-	ULPI_ID(0x04cc, 0x1504),	/* NXP ISP1504 */
-	ULPI_ID(0x0424, 0x0006),        /* SMSC USB3319 */
+static struct ulpi_info ulpi_ids[] = {
+	ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
+	ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB3319"),
 };
 
 static int ulpi_set_otg_flags(struct otg_transceiver *otg)
@@ -137,6 +148,32 @@
 	return ulpi_set_fc_flags(otg);
 }
 
+static int ulpi_check_integrity(struct otg_transceiver *otg)
+{
+	int ret, i;
+	unsigned int val = 0x55;
+
+	for (i = 0; i < 2; i++) {
+		ret = otg_io_write(otg, val, ULPI_SCRATCH);
+		if (ret < 0)
+			return ret;
+
+		ret = otg_io_read(otg, ULPI_SCRATCH);
+		if (ret < 0)
+			return ret;
+
+		if (ret != val) {
+			pr_err("ULPI integrity check: failed!");
+			return -ENODEV;
+		}
+		val = val << 1;
+	}
+
+	pr_info("ULPI integrity check: passed.\n");
+
+	return 0;
+}
+
 static int ulpi_init(struct otg_transceiver *otg)
 {
 	int i, vid, pid, ret;
@@ -153,12 +190,19 @@
 
 	pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
 
-	for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++)
-		if (ulpi_ids[i] == ULPI_ID(vid, pid))
-			return ulpi_set_flags(otg);
+	for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) {
+		if (ulpi_ids[i].id == ULPI_ID(vid, pid)) {
+			pr_info("Found %s ULPI transceiver.\n",
+				ulpi_ids[i].name);
+			break;
+		}
+	}
 
-	pr_err("ULPI ID does not match any known transceiver.\n");
-	return -ENODEV;
+	ret = ulpi_check_integrity(otg);
+	if (ret)
+		return ret;
+
+	return ulpi_set_flags(otg);
 }
 
 static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host)
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 916b2b6..9505810 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -527,6 +527,15 @@
 	bool "USB Secure Encapsulated Driver - Padded"
 	depends on USB_SERIAL_SAFE
 
+config USB_SERIAL_SAMBA
+	tristate "USB Atmel SAM Boot Assistant (SAM-BA) driver"
+	help
+	  Say Y here if you want to access the SAM-BA boot application of an
+	  Atmel AT91SAM device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sam-ba.
+
 config USB_SERIAL_SIEMENS_MPI
 	tristate "USB Siemens MPI driver"
 	help
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 40ebe17..9a2117f 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -6,10 +6,10 @@
 
 obj-$(CONFIG_USB_SERIAL)			+= usbserial.o
 
-usbserial-obj-$(CONFIG_USB_SERIAL_CONSOLE)	+= console.o
-usbserial-obj-$(CONFIG_USB_EZUSB)		+= ezusb.o
+usbserial-y := usb-serial.o generic.o bus.o
 
-usbserial-objs	:= usb-serial.o generic.o bus.o $(usbserial-obj-y)
+usbserial-$(CONFIG_USB_SERIAL_CONSOLE)	+= console.o
+usbserial-$(CONFIG_USB_EZUSB)		+= ezusb.o
 
 obj-$(CONFIG_USB_SERIAL_AIRCABLE)		+= aircable.o
 obj-$(CONFIG_USB_SERIAL_ARK3116)		+= ark3116.o
@@ -48,6 +48,7 @@
 obj-$(CONFIG_USB_SERIAL_QCAUX)			+= qcaux.o
 obj-$(CONFIG_USB_SERIAL_QUALCOMM)		+= qcserial.o
 obj-$(CONFIG_USB_SERIAL_SAFE)			+= safe_serial.o
+obj-$(CONFIG_USB_SERIAL_SAMBA)			+= sam-ba.o
 obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI)		+= siemens_mpi.o
 obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS)		+= sierra.o
 obj-$(CONFIG_USB_SERIAL_SPCP8X5)		+= spcp8x5.o
@@ -58,6 +59,5 @@
 obj-$(CONFIG_USB_SERIAL_VISOR)			+= visor.o
 obj-$(CONFIG_USB_SERIAL_WHITEHEAT)		+= whiteheat.o
 obj-$(CONFIG_USB_SERIAL_XIRCOM)			+= keyspan_pda.o
-obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL)	+= vivopay-serial.o
+obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL)		+= vivopay-serial.o
 obj-$(CONFIG_USB_SERIAL_ZIO)			+= zio.o
-
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 4e41a2a..8f1d4fb 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -411,6 +411,26 @@
 	return result;
 }
 
+static int ark3116_get_icount(struct tty_struct *tty,
+					struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct ark3116_private *priv = usb_get_serial_port_data(port);
+	struct async_icount cnow = priv->icount;
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+	return 0;
+}
+
 static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
@@ -460,25 +480,6 @@
 				return 0;
 		}
 		break;
-	case TIOCGICOUNT: {
-		struct serial_icounter_struct icount;
-		struct async_icount cnow = priv->icount;
-		memset(&icount, 0, sizeof(icount));
-		icount.cts = cnow.cts;
-		icount.dsr = cnow.dsr;
-		icount.rng = cnow.rng;
-		icount.dcd = cnow.dcd;
-		icount.rx = cnow.rx;
-		icount.tx = cnow.tx;
-		icount.frame = cnow.frame;
-		icount.overrun = cnow.overrun;
-		icount.parity = cnow.parity;
-		icount.brk = cnow.brk;
-		icount.buf_overrun = cnow.buf_overrun;
-		if (copy_to_user(user_arg, &icount, sizeof(icount)))
-			return -EFAULT;
-		return 0;
-	}
 	}
 
 	return -ENOIOCTLCMD;
@@ -736,6 +737,7 @@
 	.ioctl =		ark3116_ioctl,
 	.tiocmget =		ark3116_tiocmget,
 	.tiocmset =		ark3116_tiocmset,
+	.get_icount =		ark3116_get_icount,
 	.open =			ark3116_open,
 	.close =		ark3116_close,
 	.break_ctl = 		ark3116_break_ctl,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 4f1744c..8d7731d 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -54,6 +54,7 @@
 static int debug;
 
 static const struct usb_device_id id_table[] = {
+	{ USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */
 	{ USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */
 	{ USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
 	{ USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
@@ -132,6 +133,7 @@
 	{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
 	{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
 	{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+	{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
 	{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
 	{ } /* Terminating Entry */
 };
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 97cc87d..37b57c7 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -177,6 +177,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_SNIFFER_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
@@ -674,7 +675,6 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
 	{ USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) },
-	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
@@ -715,8 +715,37 @@
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
 	{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
+
+	/* Papouch devices based on FTDI chip */
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485S_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485C_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_LEC_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB232_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_IRAMP_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK5_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO8x8_PID) },
 	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO10x1_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO30x3_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO60x3_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x16_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO3x32_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK6_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_UPSUSB_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_MU_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SIMUKEY_PID) },
 	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AD4USB_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMUX_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMSR_PID) },
+
 	{ USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) },
 	{ USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) },
@@ -751,6 +780,7 @@
 	{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) },
+	{ USB_DEVICE(FTDI_VID, ACCESIO_COM4SM_PID) },
 	{ USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) },
@@ -761,6 +791,9 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -1559,6 +1592,7 @@
 	ftdi_set_max_packet_size(port);
 	if (read_latency_timer(port) < 0)
 		priv->latency = 16;
+	write_latency_timer(port);
 	create_sysfs_attrs(port);
 	return 0;
 }
@@ -1687,8 +1721,6 @@
 
 	dbg("%s", __func__);
 
-	write_latency_timer(port);
-
 	/* No error checking for this (will get errors later anyway) */
 	/* See ftdi_sio.h for description of what is reset */
 	usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -2028,8 +2060,6 @@
 				"urb failed to set to rts/cts flow control\n");
 		}
 
-		/* raise DTR/RTS */
-		set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 	} else {
 		/*
 		 * Xon/Xoff code
@@ -2077,8 +2107,6 @@
 			}
 		}
 
-		/* lower DTR/RTS */
-		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 	}
 	return;
 }
@@ -2168,6 +2196,7 @@
 	 * - 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.
+	 * (except that the driver doesn't support it !)
 	 *
 	 * This code is borrowed from linux/drivers/char/serial.c
 	 */
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 15a4583..cf1aea1b 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -61,6 +61,7 @@
 #define FTDI_OPENDCC_SNIFFER_PID	0xBFD9
 #define FTDI_OPENDCC_THROTTLE_PID	0xBFDA
 #define FTDI_OPENDCC_GATEWAY_PID	0xBFDB
+#define FTDI_OPENDCC_GBM_PID	0xBFDC
 
 /*
  * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
@@ -1022,9 +1023,34 @@
  */
 
 #define PAPOUCH_VID			0x5050	/* Vendor ID */
+#define PAPOUCH_SB485_PID		0x0100	/* Papouch SB485 USB-485/422 Converter */
+#define PAPOUCH_AP485_PID		0x0101	/* AP485 USB-RS485 Converter */
+#define PAPOUCH_SB422_PID		0x0102	/* Papouch SB422 USB-RS422 Converter  */
+#define PAPOUCH_SB485_2_PID		0x0103	/* Papouch SB485 USB-485/422 Converter */
+#define PAPOUCH_AP485_2_PID		0x0104	/* AP485 USB-RS485 Converter */
+#define PAPOUCH_SB422_2_PID		0x0105	/* Papouch SB422 USB-RS422 Converter  */
+#define PAPOUCH_SB485S_PID		0x0106	/* Papouch SB485S USB-485/422 Converter */
+#define PAPOUCH_SB485C_PID		0x0107	/* Papouch SB485C USB-485/422 Converter */
+#define PAPOUCH_LEC_PID			0x0300	/* LEC USB Converter */
+#define PAPOUCH_SB232_PID		0x0301	/* Papouch SB232 USB-RS232 Converter */
 #define PAPOUCH_TMU_PID			0x0400	/* TMU USB Thermometer */
-#define PAPOUCH_QUIDO4x4_PID		0x0900	/* Quido 4/4 Module */
+#define PAPOUCH_IRAMP_PID		0x0500	/* Papouch IRAmp Duplex */
+#define PAPOUCH_DRAK5_PID		0x0700	/* Papouch DRAK5 */
+#define PAPOUCH_QUIDO8x8_PID		0x0800	/* Papouch Quido 8/8 Module */
+#define PAPOUCH_QUIDO4x4_PID		0x0900	/* Papouch Quido 4/4 Module */
+#define PAPOUCH_QUIDO2x2_PID		0x0a00	/* Papouch Quido 2/2 Module */
+#define PAPOUCH_QUIDO10x1_PID		0x0b00	/* Papouch Quido 10/1 Module */
+#define PAPOUCH_QUIDO30x3_PID		0x0c00	/* Papouch Quido 30/3 Module */
+#define PAPOUCH_QUIDO60x3_PID		0x0d00	/* Papouch Quido 60(100)/3 Module */
+#define PAPOUCH_QUIDO2x16_PID		0x0e00	/* Papouch Quido 2/16 Module */
+#define PAPOUCH_QUIDO3x32_PID		0x0f00	/* Papouch Quido 3/32 Module */
+#define PAPOUCH_DRAK6_PID		0x1000	/* Papouch DRAK6 */
+#define PAPOUCH_UPSUSB_PID		0x8000	/* Papouch UPS-USB adapter */
+#define PAPOUCH_MU_PID			0x8001	/* MU controller */
+#define PAPOUCH_SIMUKEY_PID		0x8002	/* Papouch SimuKey */
 #define PAPOUCH_AD4USB_PID		0x8003	/* AD4USB Measurement Module */
+#define PAPOUCH_GMUX_PID		0x8004	/* Papouch GOLIATH MUX */
+#define PAPOUCH_GMSR_PID		0x8005	/* Papouch GOLIATH MSR */
 
 /*
  * Marvell SheevaPlug
@@ -1063,3 +1089,14 @@
  * Submitted by John G. Rogers
  */
 #define SEGWAY_RMP200_PID	0xe729
+
+
+/*
+ * Accesio USB Data Acquisition products (http://www.accesio.com/)
+ */
+#define ACCESIO_COM4SM_PID 	0xD578
+
+/* www.sciencescope.co.uk educational dataloggers */
+#define FTDI_SCIENCESCOPE_LOGBOOKML_PID		0xFF18
+#define FTDI_SCIENCESCOPE_LS_LOGBOOK_PID	0xFF1C
+#define FTDI_SCIENCESCOPE_HS_LOGBOOK_PID	0xFF1D
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 76e6fb3..a0ab78a 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -222,6 +222,8 @@
 static int  edge_tiocmget(struct tty_struct *tty, struct file *file);
 static int  edge_tiocmset(struct tty_struct *tty, struct file *file,
 					unsigned int set, unsigned int clear);
+static int  edge_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount);
 static int  edge_startup(struct usb_serial *serial);
 static void edge_disconnect(struct usb_serial *serial);
 static void edge_release(struct usb_serial *serial);
@@ -1624,6 +1626,31 @@
 	return result;
 }
 
+static int edge_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+	struct async_icount cnow;
+	cnow = edge_port->icount;
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
+			__func__,  port->number, icount->rx, icount->tx);
+	return 0;
+}
+
 static int get_serial_info(struct edgeport_port *edge_port,
 				struct serial_struct __user *retinfo)
 {
@@ -1650,7 +1677,6 @@
 }
 
 
-
 /*****************************************************************************
  * SerialIoctl
  *	this function handles any ioctl calls to the driver
@@ -1663,7 +1689,6 @@
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	struct async_icount cnow;
 	struct async_icount cprev;
-	struct serial_icounter_struct icount;
 
 	dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
 
@@ -1702,26 +1727,6 @@
 		/* NOTREACHED */
 		break;
 
-	case TIOCGICOUNT:
-		cnow = edge_port->icount;
-		memset(&icount, 0, sizeof(icount));
-		icount.cts = cnow.cts;
-		icount.dsr = cnow.dsr;
-		icount.rng = cnow.rng;
-		icount.dcd = cnow.dcd;
-		icount.rx = cnow.rx;
-		icount.tx = cnow.tx;
-		icount.frame = cnow.frame;
-		icount.overrun = cnow.overrun;
-		icount.parity = cnow.parity;
-		icount.brk = cnow.brk;
-		icount.buf_overrun = cnow.buf_overrun;
-
-		dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
-				__func__,  port->number, icount.rx, icount.tx);
-		if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
-			return -EFAULT;
-		return 0;
 	}
 	return -ENOIOCTLCMD;
 }
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index feb56a4..6ab2a3f 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -123,6 +123,7 @@
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
+	.get_icount		= edge_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
@@ -152,6 +153,7 @@
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
+	.get_icount		= edge_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
@@ -181,6 +183,7 @@
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
+	.get_icount		= edge_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
@@ -209,6 +212,7 @@
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
+	.get_icount		= edge_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index a7cfc59..4dad27a 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2510,6 +2510,27 @@
 	return result;
 }
 
+static int edge_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+	struct async_icount *ic = &edge_port->icount;
+
+	icount->cts = ic->cts;
+	icount->dsr = ic->dsr;
+	icount->rng = ic->rng;
+	icount->dcd = ic->dcd;
+	icount->tx = ic->tx;
+        icount->rx = ic->rx;
+        icount->frame = ic->frame;
+        icount->parity = ic->parity;
+        icount->overrun = ic->overrun;
+        icount->brk = ic->brk;
+        icount->buf_overrun = ic->buf_overrun;
+	return 0;
+}
+
 static int get_serial_info(struct edgeport_port *edge_port,
 				struct serial_struct __user *retinfo)
 {
@@ -2572,13 +2593,6 @@
 		}
 		/* not reached */
 		break;
-	case TIOCGICOUNT:
-		dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
-		     port->number, edge_port->icount.rx, edge_port->icount.tx);
-		if (copy_to_user((void __user *)arg, &edge_port->icount,
-				sizeof(edge_port->icount)))
-			return -EFAULT;
-		return 0;
 	}
 	return -ENOIOCTLCMD;
 }
@@ -2758,6 +2772,7 @@
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
+	.get_icount		= edge_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 7aa01b9..2849f8c 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -549,9 +549,12 @@
 {
 	dbg("%s port %d", __func__, port->number);
 
-	usb_serial_generic_close(port);
-	if (port->serial->dev)
+	if (port->serial->dev) {
+		/* shutdown our urbs */
+		usb_kill_urb(port->write_urb);
+		usb_kill_urb(port->read_urb);
 		usb_kill_urb(port->interrupt_in_urb);
+	}
 } /* mct_u232_close */
 
 
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index aa66581..fd0b641 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1896,10 +1896,37 @@
 	return 0;
 }
 
+static int mos7720_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct moschip_port *mos7720_port;
+	struct async_icount cnow;
+
+	mos7720_port = usb_get_serial_port_data(port);
+	cnow = mos7720_port->icount;
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
+		port->number, icount->rx, icount->tx);
+	return 0;
+}
+
 static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
 			  unsigned int __user *value)
 {
-	unsigned int mcr ;
+	unsigned int mcr;
 	unsigned int arg;
 
 	struct usb_serial_port *port;
@@ -1973,7 +2000,6 @@
 	struct moschip_port *mos7720_port;
 	struct async_icount cnow;
 	struct async_icount cprev;
-	struct serial_icounter_struct icount;
 
 	mos7720_port = usb_get_serial_port_data(port);
 	if (mos7720_port == NULL)
@@ -2021,29 +2047,6 @@
 		}
 		/* NOTREACHED */
 		break;
-
-	case TIOCGICOUNT:
-		cnow = mos7720_port->icount;
-
-		memset(&icount, 0, sizeof(struct serial_icounter_struct));
-
-		icount.cts = cnow.cts;
-		icount.dsr = cnow.dsr;
-		icount.rng = cnow.rng;
-		icount.dcd = cnow.dcd;
-		icount.rx = cnow.rx;
-		icount.tx = cnow.tx;
-		icount.frame = cnow.frame;
-		icount.overrun = cnow.overrun;
-		icount.parity = cnow.parity;
-		icount.brk = cnow.brk;
-		icount.buf_overrun = cnow.buf_overrun;
-
-		dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
-		    port->number, icount.rx, icount.tx);
-		if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
-			return -EFAULT;
-		return 0;
 	}
 
 	return -ENOIOCTLCMD;
@@ -2212,6 +2215,7 @@
 	.ioctl			= mos7720_ioctl,
 	.tiocmget		= mos7720_tiocmget,
 	.tiocmset		= mos7720_tiocmset,
+	.get_icount		= mos7720_get_icount,
 	.set_termios		= mos7720_set_termios,
 	.write			= mos7720_write,
 	.write_room		= mos7720_write_room,
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 1a42bc2..93dad58 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -2209,6 +2209,34 @@
 	return 0;
 }
 
+static int mos7840_get_icount(struct tty_struct *tty,
+			struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct moschip_port *mos7840_port;
+	struct async_icount cnow;
+
+	mos7840_port = mos7840_get_port_private(port);
+	cnow = mos7840_port->icount;
+
+	smp_rmb();
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
+		port->number, icount->rx, icount->tx);
+	return 0;
+}
+
 /*****************************************************************************
  * SerialIoctl
  *	this function handles any ioctl calls to the driver
@@ -2223,7 +2251,6 @@
 
 	struct async_icount cnow;
 	struct async_icount cprev;
-	struct serial_icounter_struct icount;
 
 	if (mos7840_port_paranoia_check(port, __func__)) {
 		dbg("%s", "Invalid port");
@@ -2282,29 +2309,6 @@
 		/* NOTREACHED */
 		break;
 
-	case TIOCGICOUNT:
-		cnow = mos7840_port->icount;
-		smp_rmb();
-
-		memset(&icount, 0, sizeof(struct serial_icounter_struct));
-
-		icount.cts = cnow.cts;
-		icount.dsr = cnow.dsr;
-		icount.rng = cnow.rng;
-		icount.dcd = cnow.dcd;
-		icount.rx = cnow.rx;
-		icount.tx = cnow.tx;
-		icount.frame = cnow.frame;
-		icount.overrun = cnow.overrun;
-		icount.parity = cnow.parity;
-		icount.brk = cnow.brk;
-		icount.buf_overrun = cnow.buf_overrun;
-
-		dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
-		    port->number, icount.rx, icount.tx);
-		if (copy_to_user(argp, &icount, sizeof(icount)))
-			return -EFAULT;
-		return 0;
 	default:
 		break;
 	}
@@ -2674,6 +2678,7 @@
 	.break_ctl = mos7840_break,
 	.tiocmget = mos7840_tiocmget,
 	.tiocmset = mos7840_tiocmset,
+	.get_icount = mos7840_get_icount,
 	.attach = mos7840_startup,
 	.disconnect = mos7840_disconnect,
 	.release = mos7840_release,
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index ed01f3b..eda1f92 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -96,8 +96,8 @@
 			/* real data, send it to the tty layer */
 			tty = tty_port_tty_get(&port->port);
 			if (tty) {
-				tty_insert_flip_string(tty, data,
-							       data_length);
+				tty_insert_flip_string(tty, data + 2,
+						       data_length);
 				tty_flip_buffer_push(tty);
 				tty_kref_put(tty);
 			}
@@ -108,10 +108,10 @@
 				else
 					priv->rts = true;
 			} else {
-			dev_dbg(&priv->udev->dev,
-				"Unknown data packet received from the device:"
-				" %2x %2x\n",
-				data[0], data[1]);
+				dev_dbg(&priv->udev->dev,
+					"Unknown data packet received from the device:"
+					" %2x %2x\n",
+					data[0], data[1]);
 			}
 		}
 	} else {
@@ -130,7 +130,7 @@
 						  priv->bulk_address),
 				  priv->bulk_in_buffer, priv->buffer_size,
 				  opticon_bulk_callback, priv);
-		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
 		if (result)
 			dev_err(&port->dev,
 			    "%s - failed resubmitting read urb, error %d\n",
@@ -187,6 +187,9 @@
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
 	kfree(urb->transfer_buffer);
 
+	/* setup packet may be set if we're using it for writing */
+	kfree(urb->setup_packet);
+
 	if (status)
 		dbg("%s - nonzero write bulk status received: %d",
 		    __func__, status);
@@ -237,10 +240,29 @@
 
 	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
 
-	usb_fill_bulk_urb(urb, serial->dev,
-			  usb_sndbulkpipe(serial->dev,
-					  port->bulk_out_endpointAddress),
-			  buffer, count, opticon_write_bulk_callback, priv);
+	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);
+	}
 
 	/* send it down the pipe */
 	status = usb_submit_urb(urb, GFP_ATOMIC);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index c46911a..2297fb1 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -392,6 +392,12 @@
 #define CELOT_VENDOR_ID				0x211f
 #define CELOT_PRODUCT_CT680M			0x6801
 
+/* ONDA Communication vendor id */
+#define ONDA_VENDOR_ID       0x1ee8
+
+/* ONDA MT825UP HSDPA 14.2 modem */
+#define ONDA_MT825UP         0x000b
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
 		OPTION_BLACKLIST_NONE = 0,
@@ -622,6 +628,7 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0011, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff) },
@@ -633,38 +640,52 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0023, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) },
+	/* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, */
 	{ 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, 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) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0037, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0038, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0039, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0040, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0042, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0043, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0044, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0048, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0049, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0050, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff) },
+	/* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0053, 0xff, 0xff, 0xff) }, */
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0056, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0064, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0065, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0067, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0077, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0079, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0082, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0106, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0108, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff) },
@@ -880,6 +901,8 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
@@ -925,6 +948,7 @@
 	{ USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) },
 	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
 	{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
+	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index cde67ca..8858201 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -118,6 +118,8 @@
 
 	spin_lock_init(&data->susp_lock);
 
+	usb_enable_autosuspend(serial->dev);
+
 	switch (nintf) {
 	case 1:
 		/* QDL mode */
@@ -150,7 +152,22 @@
 	case 3:
 	case 4:
 		/* Composite mode */
-		if (ifnum == 2) {
+		/* ifnum == 0 is a broadband network adapter */
+		if (ifnum == 1) {
+			/*
+			 * Diagnostics Monitor (serial line 9600 8N1)
+			 * Qualcomm DM protocol
+			 * use "libqcdm" (ModemManager) for communication
+			 */
+			dbg("Diagnostics Monitor found");
+			retval = usb_set_interface(serial->dev, ifnum, 0);
+			if (retval < 0) {
+				dev_err(&serial->dev->dev,
+					"Could not set interface, error %d\n",
+					retval);
+				retval = -ENODEV;
+			}
+		} else if (ifnum == 2) {
 			dbg("Modem port found");
 			retval = usb_set_interface(serial->dev, ifnum, 0);
 			if (retval < 0) {
@@ -161,6 +178,20 @@
 				kfree(data);
 			}
 			return retval;
+		} else if (ifnum==3) {
+			/*
+			 * NMEA (serial line 9600 8N1)
+			 * # echo "\$GPS_START" > /dev/ttyUSBx
+			 * # echo "\$GPS_STOP"  > /dev/ttyUSBx
+			 */
+			dbg("NMEA GPS interface found");
+			retval = usb_set_interface(serial->dev, ifnum, 0);
+			if (retval < 0) {
+				dev_err(&serial->dev->dev,
+					"Could not set interface, error %d\n",
+					retval);
+				retval = -ENODEV;
+			}
 		}
 		break;
 
diff --git a/drivers/usb/serial/sam-ba.c b/drivers/usb/serial/sam-ba.c
new file mode 100644
index 0000000..e3bba64
--- /dev/null
+++ b/drivers/usb/serial/sam-ba.c
@@ -0,0 +1,206 @@
+/*
+ * Atmel SAM Boot Assistant (SAM-BA) driver
+ *
+ * Copyright (C) 2010 Johan Hovold <jhovold@gmail.com>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+
+#define DRIVER_VERSION	"v1.0"
+#define DRIVER_AUTHOR	"Johan Hovold <jhovold@gmail.com>"
+#define DRIVER_DESC	"Atmel SAM Boot Assistant (SAM-BA) driver"
+
+#define SAMBA_VENDOR_ID		0x3eb
+#define SAMBA_PRODUCT_ID	0x6124
+
+
+static int debug;
+
+static const struct usb_device_id id_table[] = {
+	/*
+	 * NOTE: Only match the CDC Data interface.
+	 */
+	{ USB_DEVICE_AND_INTERFACE_INFO(SAMBA_VENDOR_ID, SAMBA_PRODUCT_ID,
+					USB_CLASS_CDC_DATA, 0, 0) },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver samba_driver = {
+	.name		= "sam-ba",
+	.probe		= usb_serial_probe,
+	.disconnect	= usb_serial_disconnect,
+	.id_table	= id_table,
+	.no_dynamic_id	= 1,
+};
+
+
+/*
+ * NOTE: The SAM-BA firmware cannot handle merged write requests so we cannot
+ *       use the generic write implementation (which uses the port write fifo).
+ */
+static int samba_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count)
+{
+	struct urb *urb;
+	unsigned long flags;
+	int result;
+	int i;
+
+	if (!count)
+		return 0;
+
+	count = min_t(int, count, port->bulk_out_size);
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (!port->write_urbs_free) {
+		spin_unlock_irqrestore(&port->lock, flags);
+		return 0;
+	}
+	i = find_first_bit(&port->write_urbs_free,
+						ARRAY_SIZE(port->write_urbs));
+	__clear_bit(i, &port->write_urbs_free);
+	port->tx_bytes += count;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	urb = port->write_urbs[i];
+	memcpy(urb->transfer_buffer, buf, count);
+	urb->transfer_buffer_length = count;
+	usb_serial_debug_data(debug, &port->dev, __func__, count,
+						urb->transfer_buffer);
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result) {
+		dev_err(&port->dev, "%s - error submitting urb: %d\n",
+						__func__, result);
+		spin_lock_irqsave(&port->lock, flags);
+		__set_bit(i, &port->write_urbs_free);
+		port->tx_bytes -= count;
+		spin_unlock_irqrestore(&port->lock, flags);
+
+		return result;
+	}
+
+	return count;
+}
+
+static int samba_write_room(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	unsigned long flags;
+	unsigned long free;
+	int count;
+	int room;
+
+	spin_lock_irqsave(&port->lock, flags);
+	free = port->write_urbs_free;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	count = hweight_long(free);
+	room = count * port->bulk_out_size;
+
+	dbg("%s - returns %d", __func__, room);
+
+	return room;
+}
+
+static int samba_chars_in_buffer(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	unsigned long flags;
+	int chars;
+
+	spin_lock_irqsave(&port->lock, flags);
+	chars = port->tx_bytes;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	dbg("%s - returns %d", __func__, chars);
+
+	return chars;
+}
+
+static void samba_write_bulk_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = urb->context;
+	unsigned long flags;
+	int i;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) {
+		if (port->write_urbs[i] == urb)
+			break;
+	}
+	spin_lock_irqsave(&port->lock, flags);
+	__set_bit(i, &port->write_urbs_free);
+	port->tx_bytes -= urb->transfer_buffer_length;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (urb->status)
+		dbg("%s - non-zero urb status: %d", __func__, urb->status);
+
+	usb_serial_port_softint(port);
+}
+
+static struct usb_serial_driver samba_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "sam-ba",
+	},
+	.usb_driver		= &samba_driver,
+	.id_table		= id_table,
+	.num_ports		= 1,
+	.bulk_in_size		= 512,
+	.bulk_out_size		= 2048,
+	.write			= samba_write,
+	.write_room		= samba_write_room,
+	.chars_in_buffer	= samba_chars_in_buffer,
+	.write_bulk_callback	= samba_write_bulk_callback,
+	.throttle		= usb_serial_generic_throttle,
+	.unthrottle		= usb_serial_generic_unthrottle,
+};
+
+static int __init samba_init(void)
+{
+	int retval;
+
+	retval = usb_serial_register(&samba_device);
+	if (retval)
+		return retval;
+
+	retval = usb_register(&samba_driver);
+	if (retval) {
+		usb_serial_deregister(&samba_device);
+		return retval;
+	}
+
+	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": "
+							DRIVER_DESC "\n");
+	return 0;
+}
+
+static void __exit samba_exit(void)
+{
+	usb_deregister(&samba_driver);
+	usb_serial_deregister(&samba_device);
+}
+
+module_init(samba_init);
+module_exit(samba_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable verbose debugging messages");
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index e986002..f5312dd333 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -416,12 +416,34 @@
 	return 0;
 }
 
+static int ssu100_get_icount(struct tty_struct *tty,
+			struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+	struct async_icount cnow = priv->icount;
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
+
+
+
 static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
 		    unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
-	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
-	void __user *user_arg = (void __user *)arg;
 
 	dbg("%s cmd 0x%04x", __func__, cmd);
 
@@ -433,27 +455,6 @@
 	case TIOCMIWAIT:
 		return wait_modem_info(port, arg);
 
-	case TIOCGICOUNT:
-	{
-		struct serial_icounter_struct icount;
-		struct async_icount cnow = priv->icount;
-		memset(&icount, 0, sizeof(icount));
-		icount.cts = cnow.cts;
-		icount.dsr = cnow.dsr;
-		icount.rng = cnow.rng;
-		icount.dcd = cnow.dcd;
-		icount.rx = cnow.rx;
-		icount.tx = cnow.tx;
-		icount.frame = cnow.frame;
-		icount.overrun = cnow.overrun;
-		icount.parity = cnow.parity;
-		icount.brk = cnow.brk;
-		icount.buf_overrun = cnow.buf_overrun;
-		if (copy_to_user(user_arg, &icount, sizeof(icount)))
-			return -EFAULT;
-		return 0;
-	}
-
 	default:
 		break;
 	}
@@ -726,6 +727,7 @@
 	.process_read_urb    = ssu100_process_read_urb,
 	.tiocmget            = ssu100_tiocmget,
 	.tiocmset            = ssu100_tiocmset,
+	.get_icount	     = ssu100_get_icount,
 	.ioctl               = ssu100_ioctl,
 	.set_termios         = ssu100_set_termios,
 	.disconnect          = usb_serial_generic_disconnect,
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 90979a1..b2902f3 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -108,6 +108,8 @@
 static void ti_unthrottle(struct tty_struct *tty);
 static int ti_ioctl(struct tty_struct *tty, struct file *file,
 		unsigned int cmd, unsigned long arg);
+static 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);
@@ -237,6 +239,7 @@
 	.set_termios		= ti_set_termios,
 	.tiocmget		= ti_tiocmget,
 	.tiocmset		= ti_tiocmset,
+	.get_icount		= ti_get_icount,
 	.break_ctl		= ti_break,
 	.read_int_callback	= ti_interrupt_callback,
 	.read_bulk_callback	= ti_bulk_in_callback,
@@ -265,6 +268,7 @@
 	.set_termios		= ti_set_termios,
 	.tiocmget		= ti_tiocmget,
 	.tiocmset		= ti_tiocmset,
+	.get_icount		= ti_get_icount,
 	.break_ctl		= ti_break,
 	.read_int_callback	= ti_interrupt_callback,
 	.read_bulk_callback	= ti_bulk_in_callback,
@@ -788,6 +792,31 @@
 	}
 }
 
+static int ti_get_icount(struct tty_struct *tty,
+		struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct ti_port *tport = usb_get_serial_port_data(port);
+	struct async_icount cnow = tport->tp_icount;
+
+	dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d",
+		__func__, port->number,
+		cnow.rx, cnow.tx);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
 
 static int ti_ioctl(struct tty_struct *tty, struct file *file,
 	unsigned int cmd, unsigned long arg)
@@ -830,14 +859,6 @@
 			cprev = cnow;
 		}
 		break;
-	case TIOCGICOUNT:
-		dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d",
-				__func__, port->number,
-				tport->tp_icount.rx, tport->tp_icount.tx);
-		if (copy_to_user((void __user *)arg, &tport->tp_icount,
-					sizeof(tport->tp_icount)))
-			return -EFAULT;
-		return 0;
 	}
 	return -ENOIOCTLCMD;
 }
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 7a2177c..e64da74 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -519,6 +519,18 @@
 	return -EINVAL;
 }
 
+static int serial_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	if (port->serial->type->get_icount)
+		return port->serial->type->get_icount(tty, icount);
+	return -EINVAL;
+}
+
 /*
  * We would be calling tty_wakeup here, but unfortunately some line
  * disciplines have an annoying habit of calling tty->write from
@@ -1195,6 +1207,7 @@
 	.chars_in_buffer =	serial_chars_in_buffer,
 	.tiocmget =		serial_tiocmget,
 	.tiocmset =		serial_tiocmset,
+	.get_icount = 		serial_get_icount,
 	.cleanup = 		serial_cleanup,
 	.install = 		serial_install,
 	.proc_fops =		&serial_proc_fops,
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index eb76aae..15a5d89 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -606,6 +606,10 @@
 
 static int clie_5_attach(struct usb_serial *serial)
 {
+	struct usb_serial_port *port;
+	unsigned int pipe;
+	int j;
+
 	dbg("%s", __func__);
 
 	/* TH55 registers 2 ports.
@@ -621,9 +625,14 @@
 		return -1;
 
 	/* port 0 now uses the modified endpoint Address */
-	serial->port[0]->bulk_out_endpointAddress =
+	port = serial->port[0];
+	port->bulk_out_endpointAddress =
 				serial->port[1]->bulk_out_endpointAddress;
 
+	pipe = usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress);
+	for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j)
+		port->write_urbs[j]->pipe = pipe;
+
 	return 0;
 }
 
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 8a372ba..f2767cf 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -172,6 +172,19 @@
 
 	  If this driver is compiled as a module, it will be named ums-cypress.
 
+config USB_UAS
+	tristate "USB Attached SCSI"
+	depends on USB && SCSI
+	help
+	  The USB Attached SCSI protocol is supported by some USB
+	  storage devices.  It permits higher performance by supporting
+	  multiple outstanding commands.
+
+	  If you don't know whether you have a UAS device, it is safe to
+	  say 'Y' or 'M' here and the kernel will use the right driver.
+
+	  If you compile this driver as a module, it will be named uas.
+
 config USB_LIBUSUAL
 	bool "The shared table of common (or usual) storage devices"
 	depends on USB
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index ef7e5a8..fcf14cd 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -5,20 +5,21 @@
 # Rewritten to use lists instead of if-statements.
 #
 
-EXTRA_CFLAGS	:= -Idrivers/scsi
+ccflags-y := -Idrivers/scsi
 
+obj-$(CONFIG_USB_UAS)		+= uas.o
 obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
 
-usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+usb-storage-y := scsiglue.o protocol.o transport.o usb.o
+usb-storage-y += initializers.o sierra_ms.o option_ms.o
 
-usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
-			initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y)
+usb-storage-$(CONFIG_USB_STORAGE_DEBUG) += debug.o
 
 ifeq ($(CONFIG_USB_LIBUSUAL),)
-	usb-storage-objs	+= usual-tables.o
+	usb-storage-y		+= usual-tables.o
 else
 	obj-$(CONFIG_USB)	+= usb-libusual.o
-	usb-libusual-objs	:= libusual.o usual-tables.o
+	usb-libusual-y		:= libusual.o usual-tables.o
 endif
 
 obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= ums-alauda.o
@@ -33,14 +34,14 @@
 obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
 obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
 
-ums-alauda-objs		:= alauda.o
-ums-cypress-objs	:= cypress_atacb.o
-ums-datafab-objs	:= datafab.o
-ums-freecom-objs	:= freecom.o
-ums-isd200-objs		:= isd200.o
-ums-jumpshot-objs	:= jumpshot.o
-ums-karma-objs		:= karma.o
-ums-onetouch-objs	:= onetouch.o
-ums-sddr09-objs		:= sddr09.o
-ums-sddr55-objs		:= sddr55.o
-ums-usbat-objs		:= shuttle_usbat.o
+ums-alauda-y		:= alauda.o
+ums-cypress-y		:= cypress_atacb.o
+ums-datafab-y		:= datafab.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-sddr09-y		:= sddr09.o
+ums-sddr55-y		:= sddr55.o
+ums-usbat-y		:= shuttle_usbat.o
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index d8d98cf..a688b1e 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -113,7 +113,7 @@
 	 * Let the scanning code know if this target merely sets
 	 * Peripheral Device Type to 0x1f to indicate no LUN.
 	 */
-	if (us->subclass == US_SC_UFI)
+	if (us->subclass == USB_SC_UFI)
 		sdev->sdev_target->pdt_1f_for_no_lun = 1;
 
 	return 0;
@@ -176,7 +176,7 @@
 		/* Disk-type devices use MODE SENSE(6) if the protocol
 		 * (SubClass) is Transparent SCSI, otherwise they use
 		 * MODE SENSE(10). */
-		if (us->subclass != US_SC_SCSI && us->subclass != US_SC_CYP_ATACB)
+		if (us->subclass != USB_SC_SCSI && us->subclass != USB_SC_CYP_ATACB)
 			sdev->use_10_for_ms = 1;
 
 		/* Many disks only accept MODE SENSE transfer lengths of
@@ -209,6 +209,10 @@
 		if (us->fflags & US_FL_CAPACITY_HEURISTICS)
 			sdev->guess_capacity = 1;
 
+		/* Some devices cannot handle READ_CAPACITY_16 */
+		if (us->fflags & US_FL_NO_READ_CAPACITY_16)
+			sdev->no_read_capacity_16 = 1;
+
 		/* assume SPC3 or latter devices support sense size > 18 */
 		if (sdev->scsi_level > SCSI_SPC_2)
 			us->fflags |= US_FL_SANE_SENSE;
@@ -245,7 +249,7 @@
 		 * capacity will be decremented or is correct. */
 		if (!(us->fflags & (US_FL_FIX_CAPACITY | US_FL_CAPACITY_OK |
 					US_FL_SCM_MULT_TARG)) &&
-				us->protocol == US_PR_BULK)
+				us->protocol == USB_PR_BULK)
 			us->use_last_sector_hacks = 1;
 	} else {
 
@@ -253,6 +257,10 @@
 		 * or to force 192-byte transfer lengths for MODE SENSE.
 		 * But they do need to use MODE SENSE(10). */
 		sdev->use_10_for_ms = 1;
+
+		/* Some (fake) usb cdrom devices don't like READ_DISC_INFO */
+		if (us->fflags & US_FL_NO_READ_DISC_INFO)
+			sdev->no_read_disc_info = 1;
 	}
 
 	/* The CB and CBI transports have no way to pass LUN values
@@ -261,7 +269,7 @@
 	 * scsi_level == 0 (UNKNOWN).  Hence such devices must necessarily
 	 * be single-LUN.
 	 */
-	if ((us->protocol == US_PR_CB || us->protocol == US_PR_CBI) &&
+	if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_CBI) &&
 			sdev->scsi_level == SCSI_UNKNOWN)
 		us->max_lun = 0;
 
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index ab5f9f3..bcb9a70 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -1760,7 +1760,7 @@
 	if (result)
 		return result;
 
-	if (us->protocol == US_PR_DPCM_USB) {
+	if (us->protocol == USB_PR_DPCM_USB) {
 		us->transport_name = "Control/Bulk-EUSB/SDDR09";
 		us->transport = dpcm_transport;
 		us->transport_reset = usb_stor_CB_reset;
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 64ec073..0041899 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -642,7 +642,7 @@
 	 * unless the operation involved a data-in transfer.  Devices
 	 * can signal most data-in errors by stalling the bulk-in pipe.
 	 */
-	if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) &&
+	if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) &&
 			srb->sc_data_direction != DMA_FROM_DEVICE) {
 		US_DEBUGP("-- CB transport device requiring auto-sense\n");
 		need_auto_sense = 1;
@@ -701,8 +701,8 @@
 		scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size);
 
 		/* FIXME: we must do the protocol translation here */
-		if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI ||
-				us->subclass == US_SC_CYP_ATACB)
+		if (us->subclass == USB_SC_RBC || us->subclass == USB_SC_SCSI ||
+				us->subclass == USB_SC_CYP_ATACB)
 			srb->cmd_len = 6;
 		else
 			srb->cmd_len = 12;
@@ -926,7 +926,7 @@
 	/* NOTE: CB does not have a status stage.  Silly, I know.  So
 	 * we have to catch this at a higher level.
 	 */
-	if (us->protocol != US_PR_CBI)
+	if (us->protocol != USB_PR_CBI)
 		return USB_STOR_TRANSPORT_GOOD;
 
 	result = usb_stor_intr_transfer(us, us->iobuf, 2);
@@ -942,7 +942,7 @@
 	 * that this means we could be ignoring a real error on these
 	 * commands, but that can't be helped.
 	 */
-	if (us->subclass == US_SC_UFI) {
+	if (us->subclass == USB_SC_UFI) {
 		if (srb->cmnd[0] == REQUEST_SENSE ||
 		    srb->cmnd[0] == INQUIRY)
 			return USB_STOR_TRANSPORT_GOOD;
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
new file mode 100644
index 0000000..2054b1e
--- /dev/null
+++ b/drivers/usb/storage/uas.c
@@ -0,0 +1,751 @@
+/*
+ * USB Attached SCSI
+ * Note that this is not the same as the USB Mass Storage driver
+ *
+ * Copyright Matthew Wilcox for Intel Corp, 2010
+ * Copyright Sarah Sharp for Intel Corp, 2010
+ *
+ * Distributed under the terms of the GNU GPL, version two.
+ */
+
+#include <linux/blkdev.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/usb.h>
+#include <linux/usb/storage.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+/* Common header for all IUs */
+struct iu {
+	__u8 iu_id;
+	__u8 rsvd1;
+	__be16 tag;
+};
+
+enum {
+	IU_ID_COMMAND		= 0x01,
+	IU_ID_STATUS		= 0x03,
+	IU_ID_RESPONSE		= 0x04,
+	IU_ID_TASK_MGMT		= 0x05,
+	IU_ID_READ_READY	= 0x06,
+	IU_ID_WRITE_READY	= 0x07,
+};
+
+struct command_iu {
+	__u8 iu_id;
+	__u8 rsvd1;
+	__be16 tag;
+	__u8 prio_attr;
+	__u8 rsvd5;
+	__u8 len;
+	__u8 rsvd7;
+	struct scsi_lun lun;
+	__u8 cdb[16];	/* XXX: Overflow-checking tools may misunderstand */
+};
+
+struct sense_iu {
+	__u8 iu_id;
+	__u8 rsvd1;
+	__be16 tag;
+	__be16 status_qual;
+	__u8 status;
+	__u8 service_response;
+	__u8 rsvd8[6];
+	__be16 len;
+	__u8 sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+/*
+ * The r00-r01c specs define this version of the SENSE IU data structure.
+ * It's still in use by several different firmware releases.
+ */
+struct sense_iu_old {
+	__u8 iu_id;
+	__u8 rsvd1;
+	__be16 tag;
+	__be16 len;
+	__u8 status;
+	__u8 service_response;
+	__u8 sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+enum {
+	CMD_PIPE_ID		= 1,
+	STATUS_PIPE_ID		= 2,
+	DATA_IN_PIPE_ID		= 3,
+	DATA_OUT_PIPE_ID	= 4,
+
+	UAS_SIMPLE_TAG		= 0,
+	UAS_HEAD_TAG		= 1,
+	UAS_ORDERED_TAG		= 2,
+	UAS_ACA			= 4,
+};
+
+struct uas_dev_info {
+	struct usb_interface *intf;
+	struct usb_device *udev;
+	int qdepth;
+	unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
+	unsigned use_streams:1;
+	unsigned uas_sense_old:1;
+};
+
+enum {
+	ALLOC_SENSE_URB		= (1 << 0),
+	SUBMIT_SENSE_URB	= (1 << 1),
+	ALLOC_DATA_IN_URB	= (1 << 2),
+	SUBMIT_DATA_IN_URB	= (1 << 3),
+	ALLOC_DATA_OUT_URB	= (1 << 4),
+	SUBMIT_DATA_OUT_URB	= (1 << 5),
+	ALLOC_CMD_URB		= (1 << 6),
+	SUBMIT_CMD_URB		= (1 << 7),
+};
+
+/* Overrides scsi_pointer */
+struct uas_cmd_info {
+	unsigned int state;
+	unsigned int stream;
+	struct urb *cmd_urb;
+	struct urb *sense_urb;
+	struct urb *data_in_urb;
+	struct urb *data_out_urb;
+	struct list_head list;
+};
+
+/* I hate forward declarations, but I actually have a loop */
+static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+				struct uas_dev_info *devinfo, gfp_t gfp);
+
+static DEFINE_SPINLOCK(uas_work_lock);
+static LIST_HEAD(uas_work_list);
+
+static void uas_do_work(struct work_struct *work)
+{
+	struct uas_cmd_info *cmdinfo;
+	struct list_head list;
+
+	spin_lock_irq(&uas_work_lock);
+	list_replace_init(&uas_work_list, &list);
+	spin_unlock_irq(&uas_work_lock);
+
+	list_for_each_entry(cmdinfo, &list, list) {
+		struct scsi_pointer *scp = (void *)cmdinfo;
+		struct scsi_cmnd *cmnd = container_of(scp,
+							struct scsi_cmnd, SCp);
+		uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_KERNEL);
+	}
+}
+
+static DECLARE_WORK(uas_work, uas_do_work);
+
+static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
+{
+	struct sense_iu *sense_iu = urb->transfer_buffer;
+	struct scsi_device *sdev = cmnd->device;
+
+	if (urb->actual_length > 16) {
+		unsigned len = be16_to_cpup(&sense_iu->len);
+		if (len + 16 != urb->actual_length) {
+			int newlen = min(len + 16, urb->actual_length) - 16;
+			if (newlen < 0)
+				newlen = 0;
+			sdev_printk(KERN_INFO, sdev, "%s: urb length %d "
+				"disagrees with IU sense data length %d, "
+				"using %d bytes of sense data\n", __func__,
+					urb->actual_length, len, newlen);
+			len = newlen;
+		}
+		memcpy(cmnd->sense_buffer, sense_iu->sense, len);
+	}
+
+	cmnd->result = sense_iu->status;
+	if (sdev->current_cmnd)
+		sdev->current_cmnd = NULL;
+	cmnd->scsi_done(cmnd);
+	usb_free_urb(urb);
+}
+
+static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
+{
+	struct sense_iu_old *sense_iu = urb->transfer_buffer;
+	struct scsi_device *sdev = cmnd->device;
+
+	if (urb->actual_length > 8) {
+		unsigned len = be16_to_cpup(&sense_iu->len) - 2;
+		if (len + 8 != urb->actual_length) {
+			int newlen = min(len + 8, urb->actual_length) - 8;
+			if (newlen < 0)
+				newlen = 0;
+			sdev_printk(KERN_INFO, sdev, "%s: urb length %d "
+				"disagrees with IU sense data length %d, "
+				"using %d bytes of sense data\n", __func__,
+					urb->actual_length, len, newlen);
+			len = newlen;
+		}
+		memcpy(cmnd->sense_buffer, sense_iu->sense, len);
+	}
+
+	cmnd->result = sense_iu->status;
+	if (sdev->current_cmnd)
+		sdev->current_cmnd = NULL;
+	cmnd->scsi_done(cmnd);
+	usb_free_urb(urb);
+}
+
+static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
+							unsigned direction)
+{
+	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+	int err;
+
+	cmdinfo->state = direction | SUBMIT_SENSE_URB;
+	err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
+	if (err) {
+		spin_lock(&uas_work_lock);
+		list_add_tail(&cmdinfo->list, &uas_work_list);
+		spin_unlock(&uas_work_lock);
+		schedule_work(&uas_work);
+	}
+}
+
+static void uas_stat_cmplt(struct urb *urb)
+{
+	struct iu *iu = urb->transfer_buffer;
+	struct scsi_device *sdev = urb->context;
+	struct uas_dev_info *devinfo = sdev->hostdata;
+	struct scsi_cmnd *cmnd;
+	u16 tag;
+
+	if (urb->status) {
+		dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
+		usb_free_urb(urb);
+		return;
+	}
+
+	tag = be16_to_cpup(&iu->tag) - 1;
+	if (sdev->current_cmnd)
+		cmnd = sdev->current_cmnd;
+	else
+		cmnd = scsi_find_tag(sdev, tag);
+	if (!cmnd)
+		return;
+
+	switch (iu->iu_id) {
+	case IU_ID_STATUS:
+		if (urb->actual_length < 16)
+			devinfo->uas_sense_old = 1;
+		if (devinfo->uas_sense_old)
+			uas_sense_old(urb, cmnd);
+		else
+			uas_sense(urb, cmnd);
+		break;
+	case IU_ID_READ_READY:
+		uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB);
+		break;
+	case IU_ID_WRITE_READY:
+		uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB);
+		break;
+	default:
+		scmd_printk(KERN_ERR, cmnd,
+			"Bogus IU (%d) received on status pipe\n", iu->iu_id);
+	}
+}
+
+static void uas_data_cmplt(struct urb *urb)
+{
+	struct scsi_data_buffer *sdb = urb->context;
+	sdb->resid = sdb->length - urb->actual_length;
+	usb_free_urb(urb);
+}
+
+static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
+				unsigned int pipe, u16 stream_id,
+				struct scsi_data_buffer *sdb,
+				enum dma_data_direction dir)
+{
+	struct usb_device *udev = devinfo->udev;
+	struct urb *urb = usb_alloc_urb(0, gfp);
+
+	if (!urb)
+		goto out;
+	usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt,
+									sdb);
+	if (devinfo->use_streams)
+		urb->stream_id = stream_id;
+	urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
+	urb->sg = sdb->table.sgl;
+ out:
+	return urb;
+}
+
+static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
+					struct scsi_cmnd *cmnd, u16 stream_id)
+{
+	struct usb_device *udev = devinfo->udev;
+	struct urb *urb = usb_alloc_urb(0, gfp);
+	struct sense_iu *iu;
+
+	if (!urb)
+		goto out;
+
+	iu = kmalloc(sizeof(*iu), gfp);
+	if (!iu)
+		goto free;
+
+	usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
+						uas_stat_cmplt, cmnd->device);
+	urb->stream_id = stream_id;
+	urb->transfer_flags |= URB_FREE_BUFFER;
+ out:
+	return urb;
+ free:
+	usb_free_urb(urb);
+	return NULL;
+}
+
+static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
+					struct scsi_cmnd *cmnd, u16 stream_id)
+{
+	struct usb_device *udev = devinfo->udev;
+	struct scsi_device *sdev = cmnd->device;
+	struct urb *urb = usb_alloc_urb(0, gfp);
+	struct command_iu *iu;
+	int len;
+
+	if (!urb)
+		goto out;
+
+	len = cmnd->cmd_len - 16;
+	if (len < 0)
+		len = 0;
+	len = ALIGN(len, 4);
+	iu = kmalloc(sizeof(*iu) + len, gfp);
+	if (!iu)
+		goto free;
+
+	iu->iu_id = IU_ID_COMMAND;
+	iu->tag = cpu_to_be16(stream_id);
+	if (sdev->ordered_tags && (cmnd->request->cmd_flags & REQ_HARDBARRIER))
+		iu->prio_attr = UAS_ORDERED_TAG;
+	else
+		iu->prio_attr = UAS_SIMPLE_TAG;
+	iu->len = len;
+	int_to_scsilun(sdev->lun, &iu->lun);
+	memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len);
+
+	usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu) + len,
+							usb_free_urb, NULL);
+	urb->transfer_flags |= URB_FREE_BUFFER;
+ out:
+	return urb;
+ free:
+	usb_free_urb(urb);
+	return NULL;
+}
+
+/*
+ * Why should I request the Status IU before sending the Command IU?  Spec
+ * says to, but also says the device may receive them in any order.  Seems
+ * daft to me.
+ */
+
+static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+					struct uas_dev_info *devinfo, gfp_t gfp)
+{
+	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+
+	if (cmdinfo->state & ALLOC_SENSE_URB) {
+		cmdinfo->sense_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd,
+							cmdinfo->stream);
+		if (!cmdinfo->sense_urb)
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		cmdinfo->state &= ~ALLOC_SENSE_URB;
+	}
+
+	if (cmdinfo->state & SUBMIT_SENSE_URB) {
+		if (usb_submit_urb(cmdinfo->sense_urb, gfp)) {
+			scmd_printk(KERN_INFO, cmnd,
+					"sense urb submission failure\n");
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		}
+		cmdinfo->state &= ~SUBMIT_SENSE_URB;
+	}
+
+	if (cmdinfo->state & ALLOC_DATA_IN_URB) {
+		cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp,
+					devinfo->data_in_pipe, cmdinfo->stream,
+					scsi_in(cmnd), DMA_FROM_DEVICE);
+		if (!cmdinfo->data_in_urb)
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		cmdinfo->state &= ~ALLOC_DATA_IN_URB;
+	}
+
+	if (cmdinfo->state & SUBMIT_DATA_IN_URB) {
+		if (usb_submit_urb(cmdinfo->data_in_urb, gfp)) {
+			scmd_printk(KERN_INFO, cmnd,
+					"data in urb submission failure\n");
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		}
+		cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
+	}
+
+	if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
+		cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp,
+					devinfo->data_out_pipe, cmdinfo->stream,
+					scsi_out(cmnd), DMA_TO_DEVICE);
+		if (!cmdinfo->data_out_urb)
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
+	}
+
+	if (cmdinfo->state & SUBMIT_DATA_OUT_URB) {
+		if (usb_submit_urb(cmdinfo->data_out_urb, gfp)) {
+			scmd_printk(KERN_INFO, cmnd,
+					"data out urb submission failure\n");
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		}
+		cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
+	}
+
+	if (cmdinfo->state & ALLOC_CMD_URB) {
+		cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd,
+							cmdinfo->stream);
+		if (!cmdinfo->cmd_urb)
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		cmdinfo->state &= ~ALLOC_CMD_URB;
+	}
+
+	if (cmdinfo->state & SUBMIT_CMD_URB) {
+		if (usb_submit_urb(cmdinfo->cmd_urb, gfp)) {
+			scmd_printk(KERN_INFO, cmnd,
+					"cmd urb submission failure\n");
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		}
+		cmdinfo->state &= ~SUBMIT_CMD_URB;
+	}
+
+	return 0;
+}
+
+static int uas_queuecommand(struct scsi_cmnd *cmnd,
+					void (*done)(struct scsi_cmnd *))
+{
+	struct scsi_device *sdev = cmnd->device;
+	struct uas_dev_info *devinfo = sdev->hostdata;
+	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+	int err;
+
+	BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
+
+	if (!cmdinfo->sense_urb && sdev->current_cmnd)
+		return SCSI_MLQUEUE_DEVICE_BUSY;
+
+	if (blk_rq_tagged(cmnd->request)) {
+		cmdinfo->stream = cmnd->request->tag + 1;
+	} else {
+		sdev->current_cmnd = cmnd;
+		cmdinfo->stream = 1;
+	}
+
+	cmnd->scsi_done = done;
+
+	cmdinfo->state = ALLOC_SENSE_URB | SUBMIT_SENSE_URB |
+			ALLOC_CMD_URB | SUBMIT_CMD_URB;
+
+	switch (cmnd->sc_data_direction) {
+	case DMA_FROM_DEVICE:
+		cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB;
+		break;
+	case DMA_BIDIRECTIONAL:
+		cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB;
+	case DMA_TO_DEVICE:
+		cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB;
+	case DMA_NONE:
+		break;
+	}
+
+	if (!devinfo->use_streams) {
+		cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
+		cmdinfo->stream = 0;
+	}
+
+	err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC);
+	if (err) {
+		/* If we did nothing, give up now */
+		if (cmdinfo->state & SUBMIT_SENSE_URB) {
+			usb_free_urb(cmdinfo->sense_urb);
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		}
+		spin_lock(&uas_work_lock);
+		list_add_tail(&cmdinfo->list, &uas_work_list);
+		spin_unlock(&uas_work_lock);
+		schedule_work(&uas_work);
+	}
+
+	return 0;
+}
+
+static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
+{
+	struct scsi_device *sdev = cmnd->device;
+	sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
+							cmnd->request->tag);
+
+/* XXX: Send ABORT TASK Task Management command */
+	return FAILED;
+}
+
+static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd)
+{
+	struct scsi_device *sdev = cmnd->device;
+	sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
+							cmnd->request->tag);
+
+/* XXX: Send LOGICAL UNIT RESET Task Management command */
+	return FAILED;
+}
+
+static int uas_eh_target_reset_handler(struct scsi_cmnd *cmnd)
+{
+	struct scsi_device *sdev = cmnd->device;
+	sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
+							cmnd->request->tag);
+
+/* XXX: Can we reset just the one USB interface?
+ * Would calling usb_set_interface() have the right effect?
+ */
+	return FAILED;
+}
+
+static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
+{
+	struct scsi_device *sdev = cmnd->device;
+	struct uas_dev_info *devinfo = sdev->hostdata;
+	struct usb_device *udev = devinfo->udev;
+
+	sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
+							cmnd->request->tag);
+
+	if (usb_reset_device(udev))
+		return SUCCESS;
+
+	return FAILED;
+}
+
+static int uas_slave_alloc(struct scsi_device *sdev)
+{
+	sdev->hostdata = (void *)sdev->host->hostdata[0];
+	return 0;
+}
+
+static int uas_slave_configure(struct scsi_device *sdev)
+{
+	struct uas_dev_info *devinfo = sdev->hostdata;
+	scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
+	scsi_activate_tcq(sdev, devinfo->qdepth - 1);
+	return 0;
+}
+
+static struct scsi_host_template uas_host_template = {
+	.module = THIS_MODULE,
+	.name = "uas",
+	.queuecommand = uas_queuecommand,
+	.slave_alloc = uas_slave_alloc,
+	.slave_configure = uas_slave_configure,
+	.eh_abort_handler = uas_eh_abort_handler,
+	.eh_device_reset_handler = uas_eh_device_reset_handler,
+	.eh_target_reset_handler = uas_eh_target_reset_handler,
+	.eh_bus_reset_handler = uas_eh_bus_reset_handler,
+	.can_queue = 65536,	/* Is there a limit on the _host_ ? */
+	.this_id = -1,
+	.sg_tablesize = SG_NONE,
+	.cmd_per_lun = 1,	/* until we override it */
+	.skip_settle_delay = 1,
+	.ordered_tag = 1,
+};
+
+static struct usb_device_id uas_usb_ids[] = {
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_UAS) },
+	/* 0xaa is a prototype device I happen to have access to */
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, 0xaa) },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, uas_usb_ids);
+
+static void uas_configure_endpoints(struct uas_dev_info *devinfo)
+{
+	struct usb_host_endpoint *eps[4] = { };
+	struct usb_interface *intf = devinfo->intf;
+	struct usb_device *udev = devinfo->udev;
+	struct usb_host_endpoint *endpoint = intf->cur_altsetting->endpoint;
+	unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints;
+
+	devinfo->uas_sense_old = 0;
+
+	for (i = 0; i < n_endpoints; i++) {
+		unsigned char *extra = endpoint[i].extra;
+		int len = endpoint[i].extralen;
+		while (len > 1) {
+			if (extra[1] == USB_DT_PIPE_USAGE) {
+				unsigned pipe_id = extra[2];
+				if (pipe_id > 0 && pipe_id < 5)
+					eps[pipe_id - 1] = &endpoint[i];
+				break;
+			}
+			len -= extra[0];
+			extra += extra[0];
+		}
+	}
+
+	/*
+	 * Assume that if we didn't find a control pipe descriptor, we're
+	 * using a device with old firmware that happens to be set up like
+	 * this.
+	 */
+	if (!eps[0]) {
+		devinfo->cmd_pipe = usb_sndbulkpipe(udev, 1);
+		devinfo->status_pipe = usb_rcvbulkpipe(udev, 1);
+		devinfo->data_in_pipe = usb_rcvbulkpipe(udev, 2);
+		devinfo->data_out_pipe = usb_sndbulkpipe(udev, 2);
+
+		eps[1] = usb_pipe_endpoint(udev, devinfo->status_pipe);
+		eps[2] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
+		eps[3] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
+	} else {
+		devinfo->cmd_pipe = usb_sndbulkpipe(udev,
+						eps[0]->desc.bEndpointAddress);
+		devinfo->status_pipe = usb_rcvbulkpipe(udev,
+						eps[1]->desc.bEndpointAddress);
+		devinfo->data_in_pipe = usb_rcvbulkpipe(udev,
+						eps[2]->desc.bEndpointAddress);
+		devinfo->data_out_pipe = usb_sndbulkpipe(udev,
+						eps[3]->desc.bEndpointAddress);
+	}
+
+	devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, 3, 256,
+								GFP_KERNEL);
+	if (devinfo->qdepth < 0) {
+		devinfo->qdepth = 256;
+		devinfo->use_streams = 0;
+	} else {
+		devinfo->use_streams = 1;
+	}
+}
+
+/*
+ * XXX: What I'd like to do here is register a SCSI host for each USB host in
+ * the system.  Follow usb-storage's design of registering a SCSI host for
+ * each USB device for the moment.  Can implement this by walking up the
+ * USB hierarchy until we find a USB host.
+ */
+static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	int result;
+	struct Scsi_Host *shost;
+	struct uas_dev_info *devinfo;
+	struct usb_device *udev = interface_to_usbdev(intf);
+
+	if (id->bInterfaceProtocol == 0x50) {
+		int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+/* XXX: Shouldn't assume that 1 is the alternative we want */
+		int ret = usb_set_interface(udev, ifnum, 1);
+		if (ret)
+			return -ENODEV;
+	}
+
+	devinfo = kmalloc(sizeof(struct uas_dev_info), GFP_KERNEL);
+	if (!devinfo)
+		return -ENOMEM;
+
+	result = -ENOMEM;
+	shost = scsi_host_alloc(&uas_host_template, sizeof(void *));
+	if (!shost)
+		goto free;
+
+	shost->max_cmd_len = 16 + 252;
+	shost->max_id = 1;
+	shost->sg_tablesize = udev->bus->sg_tablesize;
+
+	result = scsi_add_host(shost, &intf->dev);
+	if (result)
+		goto free;
+	shost->hostdata[0] = (unsigned long)devinfo;
+
+	devinfo->intf = intf;
+	devinfo->udev = udev;
+	uas_configure_endpoints(devinfo);
+
+	scsi_scan_host(shost);
+	usb_set_intfdata(intf, shost);
+	return result;
+ free:
+	kfree(devinfo);
+	if (shost)
+		scsi_host_put(shost);
+	return result;
+}
+
+static int uas_pre_reset(struct usb_interface *intf)
+{
+/* XXX: Need to return 1 if it's not our device in error handling */
+	return 0;
+}
+
+static int uas_post_reset(struct usb_interface *intf)
+{
+/* XXX: Need to return 1 if it's not our device in error handling */
+	return 0;
+}
+
+static void uas_disconnect(struct usb_interface *intf)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct usb_host_endpoint *eps[3];
+	struct Scsi_Host *shost = usb_get_intfdata(intf);
+	struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+
+	scsi_remove_host(shost);
+
+	eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
+	eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
+	eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
+	usb_free_streams(intf, eps, 3, GFP_KERNEL);
+
+	kfree(devinfo);
+}
+
+/*
+ * XXX: Should this plug into libusual so we can auto-upgrade devices from
+ * Bulk-Only to UAS?
+ */
+static struct usb_driver uas_driver = {
+	.name = "uas",
+	.probe = uas_probe,
+	.disconnect = uas_disconnect,
+	.pre_reset = uas_pre_reset,
+	.post_reset = uas_post_reset,
+	.id_table = uas_usb_ids,
+};
+
+static int uas_init(void)
+{
+	return usb_register(&uas_driver);
+}
+
+static void uas_exit(void)
+{
+	usb_deregister(&uas_driver);
+}
+
+module_init(uas_init);
+module_exit(uas_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matthew Wilcox and Sarah Sharp");
diff --git a/drivers/usb/storage/unusual_alauda.h b/drivers/usb/storage/unusual_alauda.h
index 8c412f8..fa3e9ed 100644
--- a/drivers/usb/storage/unusual_alauda.h
+++ b/drivers/usb/storage/unusual_alauda.h
@@ -21,11 +21,11 @@
 UNUSUAL_DEV(  0x0584, 0x0008, 0x0102, 0x0102,
 		"Fujifilm",
 		"DPC-R1 (Alauda)",
-		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0),
+		USB_SC_SCSI, USB_PR_ALAUDA, init_alauda, 0),
 
 UNUSUAL_DEV(  0x07b4, 0x010a, 0x0102, 0x0102,
 		"Olympus",
 		"MAUSB-10 (Alauda)",
-		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0),
+		USB_SC_SCSI, USB_PR_ALAUDA, init_alauda, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_ALAUDA) || ... */
diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h
index 44be6d7..c854fde 100644
--- a/drivers/usb/storage/unusual_cypress.h
+++ b/drivers/usb/storage/unusual_cypress.h
@@ -23,12 +23,12 @@
 UNUSUAL_DEV(  0x04b4, 0x6830, 0x0000, 0x9999,
 		"Cypress",
 		"Cypress AT2LP",
-		US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0),
+		USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
 
 /* CY7C68310 : support atacb and atacb2 */
 UNUSUAL_DEV(  0x04b4, 0x6831, 0x0000, 0x9999,
 		"Cypress",
 		"Cypress ISD-300LP",
-		US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0),
+		USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */
diff --git a/drivers/usb/storage/unusual_datafab.h b/drivers/usb/storage/unusual_datafab.h
index c9298ce..582a603 100644
--- a/drivers/usb/storage/unusual_datafab.h
+++ b/drivers/usb/storage/unusual_datafab.h
@@ -21,7 +21,7 @@
 UNUSUAL_DEV(  0x07c4, 0xa000, 0x0000, 0x0015,
 		"Datafab",
 		"MDCFE-B USB CF Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 /*
@@ -38,45 +38,45 @@
 UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
 		"SIIG/Datafab",
 		"SIIG/Datafab Memory Stick+CF Reader/Writer",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 /* Reported by Josef Reisinger <josef.reisinger@netcologne.de> */
 UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff,
 		"Datafab/Unknown",
 		"MD2/MD3 Disk enclosure",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		US_FL_SINGLE_LUN),
 
 UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
 		"Datafab/Unknown",
 		"Datafab-based Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff,
 		"Datafab/Unknown",
 		"Datafab-based Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff,
 		"PNY/Datafab",
 		"PNY/Datafab CF+SM Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
 		"Simple Tech/Datafab",
 		"Simple Tech/Datafab CF+SM Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 /* Submitted by Olaf Hering <olh@suse.de> */
 UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
 		"Datafab Systems, Inc.",
 		"USB to CF + SM Combo (LC1)",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 /* Reported by Felix Moeller <felix@derklecks.de>
@@ -86,13 +86,13 @@
 UNUSUAL_DEV(  0x07c4, 0xa10b, 0x0000, 0xffff,
 		"DataFab Systems Inc.",
 		"USB CF+MS",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
 		"Acomdata",
 		"CF",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		US_FL_SINGLE_LUN),
 
 #endif /* defined(CONFIG_USB_STORAGE_DATAFAB) || ... */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 2c897ee..6ccdd3d 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -63,26 +63,26 @@
 UNUSUAL_DEV(  0x03eb, 0x2002, 0x0100, 0x0100,
 		"ATMEL",
 		"SND1 Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE),
 
 /* Reported by Rodolfo Quesada <rquesada@roqz.net> */
 UNUSUAL_DEV(  0x03ee, 0x6906, 0x0003, 0x0003,
 		"VIA Technologies Inc.",
 		"Mitsumi multi cardreader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 UNUSUAL_DEV(  0x03f0, 0x0107, 0x0200, 0x0200,
 		"HP",
 		"CD-Writer+",
-		US_SC_8070, US_PR_CB, NULL, 0),
+		USB_SC_8070, USB_PR_CB, NULL, 0),
 
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV(  0x03f0, 0x070c, 0x0000, 0x0000,
 		"HP",
 		"Personal Media Drive",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SANE_SENSE ),
 
 /* Reported by Grant Grundler <grundler@parisc-linux.org>
@@ -91,7 +91,7 @@
 UNUSUAL_DEV(  0x03f0, 0x4002, 0x0001, 0x0001,
 		"HP",
 		"PhotoSmart R707",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY),
 
 /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
  * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
@@ -100,14 +100,14 @@
 UNUSUAL_DEV(  0x0409, 0x0040, 0x0000, 0x9999,
 		"NEC",
 		"NEC USB UF000x",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */
 UNUSUAL_DEV(  0x040d, 0x6205, 0x0003, 0x0003,
 		"VIA Technologies Inc.",
 		"USB 2.0 Card Reader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
@@ -117,40 +117,40 @@
 UNUSUAL_DEV(  0x0411, 0x001c, 0x0113, 0x0113,
 		"Buffalo",
 		"DUB-P40G HDD",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Submitted by Ernestas Vaiciukevicius <ernisv@gmail.com> */
 UNUSUAL_DEV(  0x0419, 0x0100, 0x0100, 0x0100,
 		"Samsung Info. Systems America, Inc.",
 		"MP3 Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Orgad Shaneh <orgads@gmail.com> */
 UNUSUAL_DEV(  0x0419, 0xaace, 0x0100, 0x0100,
 		"Samsung", "MP3 Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Christian Leber <christian@leber.de> */
 UNUSUAL_DEV(  0x0419, 0xaaf5, 0x0100, 0x0100,
 		"TrekStor",
 		"i.Beat 115 2.0",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_NOT_LOCKABLE ),
 
 /* Reported by Stefan Werner <dustbln@gmx.de> */
 UNUSUAL_DEV(  0x0419, 0xaaf6, 0x0100, 0x0100,
 		"TrekStor",
 		"i.Beat Joy 2.0",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Pete Zaitcev <zaitcev@redhat.com>, bz#176584 */
 UNUSUAL_DEV(  0x0420, 0x0001, 0x0100, 0x0100,
 		"GENERIC", "MP3 PLAYER", /* MyMusix PD-205 on the outside. */
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Andrew Nayenko <relan@bk.ru>
@@ -158,28 +158,28 @@
 UNUSUAL_DEV(  0x0421, 0x0019, 0x0592, 0x0610,
 		"Nokia",
 		"Nokia 6288",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /* Reported by Mario Rettig <mariorettig@web.de> */
 UNUSUAL_DEV(  0x0421, 0x042e, 0x0100, 0x0100,
 		"Nokia",
 		"Nokia 3250",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by <honkkis@gmail.com> */
 UNUSUAL_DEV(  0x0421, 0x0433, 0x0100, 0x0100,
 		"Nokia",
 		"E70",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by Jon Hart <Jon.Hart@web.de> */
 UNUSUAL_DEV(  0x0421, 0x0434, 0x0100, 0x0100,
 		"Nokia",
 		"E60",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Sumedha Swamy <sumedhaswamy@gmail.com> and
@@ -187,7 +187,7 @@
 UNUSUAL_DEV(  0x0421, 0x0444, 0x0100, 0x0100,
 		"Nokia",
 		"N91",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by Jiri Slaby <jirislaby@gmail.com> and
@@ -195,42 +195,42 @@
 UNUSUAL_DEV(  0x0421, 0x0446, 0x0100, 0x0100,
 		"Nokia",
 		"N80",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by Matthew Bloch <matthew@bytemark.co.uk> */
 UNUSUAL_DEV(  0x0421, 0x044e, 0x0100, 0x0100,
 		"Nokia",
 		"E61",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by Bardur Arantsson <bardur@scientician.net> */
 UNUSUAL_DEV(  0x0421, 0x047c, 0x0370, 0x0610,
 		"Nokia",
 		"6131",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /* Reported by Manuel Osdoba <manuel.osdoba@tu-ilmenau.de> */
 UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x9999,
 		"Nokia",
 		"Nokia 6233",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /* Reported by Alex Corcoles <alex@corcoles.net> */
 UNUSUAL_DEV(  0x0421, 0x0495, 0x0370, 0x0370,
 		"Nokia",
 		"6234",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 #ifdef NO_SDDR09
 UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
 		"Microtech",
 		"CameraMate",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 #endif
 
@@ -239,7 +239,7 @@
 UNUSUAL_DEV(  0x0451, 0x5416, 0x0100, 0x0100,
 		"Neuros Audio",
 		"USB 2.0 HD 2.5",
-		US_SC_DEVICE, US_PR_BULK, NULL,
+		USB_SC_DEVICE, USB_PR_BULK, NULL,
 		US_FL_NEED_OVERRIDE ),
 
 /*
@@ -250,7 +250,7 @@
 UNUSUAL_DEV(  0x0457, 0x0150, 0x0100, 0x0100,
 		"USBest Technology",	/* sold by Transcend */
 		"USB Mass Storage Device",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
 
 /*
 * Bohdan Linda <bohdan.linda@gmail.com>
@@ -260,7 +260,7 @@
 UNUSUAL_DEV(  0x0457, 0x0151, 0x0100, 0x0100,
 		"USB 2.0",
 		"Flash Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NOT_LOCKABLE ),
 
 /* Reported by Tamas Kerecsen <kerecsen@bigfoot.com>
@@ -272,7 +272,7 @@
 UNUSUAL_DEV(  0x045e, 0xffff, 0x0000, 0x0000,
 		"Mitac",
 		"GPS",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /*
@@ -284,32 +284,32 @@
 UNUSUAL_DEV(  0x046b, 0xff40, 0x0100, 0x0100,
 		"AMI",
 		"Virtual Floppy",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NO_WP_DETECT),
 
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
 		"Kyocera",
 		"Finecam S3x",
-		US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY),
+		USB_SC_8070, USB_PR_CB, NULL, US_FL_FIX_INQUIRY),
 
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0101, 0x0100, 0x0100,
 		"Kyocera",
 		"Finecam S4",
-		US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY),
+		USB_SC_8070, USB_PR_CB, NULL, US_FL_FIX_INQUIRY),
 
 /* Patch submitted by Stephane Galles <stephane.galles@free.fr> */
 UNUSUAL_DEV(  0x0482, 0x0103, 0x0100, 0x0100,
 		"Kyocera",
 		"Finecam S5",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
 
 /* Patch submitted by Jens Taprogge <jens.taprogge@taprogge.org> */
 UNUSUAL_DEV(  0x0482, 0x0107, 0x0100, 0x0100,
 		"Kyocera",
 		"CONTAX SL300R T*",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE),
 
 /* Reported by Paul Stewart <stewart@wetlogic.net>
@@ -317,7 +317,7 @@
 UNUSUAL_DEV(  0x04a4, 0x0004, 0x0001, 0x0001,
 		"Hitachi",
 		"DVD-CAM DZ-MV100A Camcorder",
-		US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN),
+		USB_SC_SCSI, USB_PR_CB, NULL, US_FL_SINGLE_LUN),
 
 /* BENQ DC5330
  * Reported by Manuel Fombuena <mfombuena@ya.com> and
@@ -325,7 +325,7 @@
 UNUSUAL_DEV(  0x04a5, 0x3010, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"300_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Patch for Nikon coolpix 2000
@@ -333,14 +333,14 @@
 UNUSUAL_DEV(  0x04b0, 0x0301, 0x0010, 0x0010,
 		"NIKON",
 		"NIKON DSC E2000",
-		US_SC_DEVICE, US_PR_DEVICE,NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE,NULL,
 		US_FL_NOT_LOCKABLE ),
 
 /* Reported by Doug Maxey (dwm@austin.ibm.com) */
 UNUSUAL_DEV(  0x04b3, 0x4001, 0x0110, 0x0110,
 		"IBM",
 		"IBM RSA2",
-		US_SC_DEVICE, US_PR_CB, NULL,
+		USB_SC_DEVICE, USB_PR_CB, NULL,
 		US_FL_MAX_SECTORS_MIN),
 
 /* Reported by Simon Levitt <simon@whattf.com>
@@ -348,14 +348,14 @@
 UNUSUAL_DEV(  0x04b8, 0x0601, 0x0100, 0x0100,
 		"Epson",
 		"875DC Storage",
-		US_SC_SCSI, US_PR_CB, NULL, US_FL_FIX_INQUIRY),
+		USB_SC_SCSI, USB_PR_CB, NULL, US_FL_FIX_INQUIRY),
 
 /* Reported by Khalid Aziz <khalid@gonehiking.org>
  * This entry is needed because the device reports Sub=ff */
 UNUSUAL_DEV(  0x04b8, 0x0602, 0x0110, 0x0110,
 		"Epson",
 		"785EPX Storage",
-		US_SC_SCSI, US_PR_BULK, NULL, US_FL_SINGLE_LUN),
+		USB_SC_SCSI, USB_PR_BULK, NULL, US_FL_SINGLE_LUN),
 
 /* Not sure who reported this originally but
  * Pavel Machek <pavel@ucw.cz> reported that the extra US_FL_SINGLE_LUN
@@ -363,7 +363,7 @@
 UNUSUAL_DEV(  0x04cb, 0x0100, 0x0000, 0x2210,
 		"Fujifilm",
 		"FinePix 1400Zoom",
-		US_SC_UFI, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN),
+		USB_SC_UFI, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN),
 
 /* Reported by Ondrej Zary <linux@rainbow-software.org>
  * The device reports one sector more and breaks when that sector is accessed
@@ -371,7 +371,7 @@
 UNUSUAL_DEV(  0x04ce, 0x0002, 0x026c, 0x026c,
 		"ScanLogic",
 		"SL11R-IDE",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* Reported by Kriston Fincher <kriston@airmail.net>
@@ -382,27 +382,27 @@
 UNUSUAL_DEV(  0x04da, 0x0901, 0x0100, 0x0200,
 		"Panasonic",
 		"LS-120 Camera",
-		US_SC_UFI, US_PR_DEVICE, NULL, 0),
+		USB_SC_UFI, USB_PR_DEVICE, NULL, 0),
 
 /* From Yukihiro Nakai, via zaitcev@yahoo.com.
  * This is needed for CB instead of CBI */
 UNUSUAL_DEV(  0x04da, 0x0d05, 0x0000, 0x0000,
 		"Sharp CE-CW05",
 		"CD-R/RW Drive",
-		US_SC_8070, US_PR_CB, NULL, 0),
+		USB_SC_8070, USB_PR_CB, NULL, 0),
 
 /* Reported by Adriaan Penning <a.penning@luon.net> */
 UNUSUAL_DEV(  0x04da, 0x2372, 0x0000, 0x9999,
 		"Panasonic",
 		"DMC-LCx Camera",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
 
 /* Reported by Simeon Simeonov <simeonov_2000@yahoo.com> */
 UNUSUAL_DEV(  0x04da, 0x2373, 0x0000, 0x9999,
 		"LEICA",
 		"D-LUX Camera",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
 
 /* Most of the following entries were developed with the help of
@@ -411,19 +411,19 @@
 UNUSUAL_DEV(  0x04e6, 0x0001, 0x0200, 0x0200,
 		"Matshita",
 		"LS-120",
-		US_SC_8020, US_PR_CB, NULL, 0),
+		USB_SC_8020, USB_PR_CB, NULL, 0),
 
 UNUSUAL_DEV(  0x04e6, 0x0002, 0x0100, 0x0100,
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, 
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ),
 
 #ifdef NO_SDDR09
 UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
 		"SCM Microsystems",
 		"eUSB CompactFlash Adapter",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN),
 #endif
 
@@ -431,54 +431,54 @@
 UNUSUAL_DEV(  0x04e6, 0x0006, 0x0100, 0x0100,
 		"SCM Microsystems Inc.",
 		"eUSB MMC Adapter",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN),
 
 /* Reported by Daniel Nouri <dpunktnpunkt@web.de> */
 UNUSUAL_DEV(  0x04e6, 0x0006, 0x0205, 0x0205,
 		"Shuttle",
 		"eUSB MMC Adapter",
-		US_SC_SCSI, US_PR_DEVICE, NULL,
+		USB_SC_SCSI, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
 UNUSUAL_DEV(  0x04e6, 0x0007, 0x0100, 0x0200,
 		"Sony",
 		"Hifd",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN),
 
 UNUSUAL_DEV(  0x04e6, 0x0009, 0x0200, 0x0200,
 		"Shuttle",
 		"eUSB ATA/ATAPI Adapter",
-		US_SC_8020, US_PR_CB, NULL, 0),
+		USB_SC_8020, USB_PR_CB, NULL, 0),
 
 UNUSUAL_DEV(  0x04e6, 0x000a, 0x0200, 0x0200,
 		"Shuttle",
 		"eUSB CompactFlash Adapter",
-		US_SC_8020, US_PR_CB, NULL, 0),
+		USB_SC_8020, USB_PR_CB, NULL, 0),
 
 UNUSUAL_DEV(  0x04e6, 0x000B, 0x0100, 0x0100,
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+		USB_SC_SCSI, USB_PR_BULK, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ), 
 
 UNUSUAL_DEV(  0x04e6, 0x000C, 0x0100, 0x0100,
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+		USB_SC_SCSI, USB_PR_BULK, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ),
 
 UNUSUAL_DEV(  0x04e6, 0x0101, 0x0200, 0x0200,
 		"Shuttle",
 		"CD-RW Device",
-		US_SC_8020, US_PR_CB, NULL, 0),
+		USB_SC_8020, USB_PR_CB, NULL, 0),
 
 /* Reported by Dmitry Khlystov <adminimus@gmail.com> */
 UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,
 		"Samsung",
 		"YP-U3",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64),
 
 /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
@@ -488,14 +488,14 @@
 UNUSUAL_DEV(  0x04fc, 0x80c2, 0x0100, 0x0100,
 		"Kobian Mercury",
 		"Binocam DCB-132",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_BULK32),
 
 /* Reported by Bob Sass <rls@vectordb.com> -- only rev 1.33 tested */
 UNUSUAL_DEV(  0x050d, 0x0115, 0x0133, 0x0133,
 		"Belkin",
 		"USB SCSI Adaptor",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+		USB_SC_SCSI, USB_PR_BULK, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ),
 
 /* Iomega Clik! Drive 
@@ -505,14 +505,14 @@
 UNUSUAL_DEV(  0x0525, 0xa140, 0x0100, 0x0100,
 		"Iomega",
 		"USB Clik! 40",
-		US_SC_8070, US_PR_DEVICE, NULL,
+		USB_SC_8070, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Added by Alan Stern <stern@rowland.harvard.edu> */
 COMPLIANT_DEV(0x0525, 0xa4a5, 0x0000, 0x9999,
 		"Linux",
 		"File-backed Storage Gadget",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_CAPACITY_OK ),
 
 /* Yakumo Mega Image 37
@@ -520,7 +520,7 @@
 UNUSUAL_DEV(  0x052b, 0x1801, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"300_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Another Yakumo camera.
@@ -528,14 +528,14 @@
 UNUSUAL_DEV(  0x052b, 0x1804, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"300_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Iacopo Spalletti <avvisi@spalletti.it> */
 UNUSUAL_DEV(  0x052b, 0x1807, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"300_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Yakumo Mega Image 47
@@ -543,7 +543,7 @@
 UNUSUAL_DEV(  0x052b, 0x1905, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"400_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Paul Ortyl <ortylp@3miasto.net>
@@ -551,13 +551,13 @@
 UNUSUAL_DEV(  0x052b, 0x1911, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"400_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0450,
 		"Sony",
 		"DSC-S30/S70/S75/505V/F505/F707/F717/P8",
-		US_SC_SCSI, US_PR_DEVICE, NULL,
+		USB_SC_SCSI, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
 
 /* Submitted by Lars Jacob <jacob.lars@googlemail.com>
@@ -565,7 +565,7 @@
 UNUSUAL_DEV(  0x054c, 0x0010, 0x0500, 0x0610,
 		"Sony",
 		"DSC-T1/T5/H5",
-		US_SC_8070, US_PR_DEVICE, NULL,
+		USB_SC_8070, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 
@@ -573,88 +573,88 @@
 UNUSUAL_DEV(  0x054c, 0x0025, 0x0100, 0x0100,
 		"Sony",
 		"Memorystick NW-MS7",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Olaf Hering, <olh@suse.de> SuSE Bugzilla #49049 */
 UNUSUAL_DEV(  0x054c, 0x002c, 0x0501, 0x2000,
 		"Sony",
 		"USB Floppy Drive",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 UNUSUAL_DEV(  0x054c, 0x002d, 0x0100, 0x0100,
 		"Sony",
 		"Memorystick MSAC-US1",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Klaus Mueller <k.mueller@intershop.de> */
 UNUSUAL_DEV(  0x054c, 0x002e, 0x0106, 0x0310,
 		"Sony",
 		"Handycam",
-		US_SC_SCSI, US_PR_DEVICE, NULL,
+		USB_SC_SCSI, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Rajesh Kumble Nayak <nayak@obs-nice.fr> */
 UNUSUAL_DEV(  0x054c, 0x002e, 0x0500, 0x0500,
 		"Sony",
 		"Handycam HC-85",
-		US_SC_UFI, US_PR_DEVICE, NULL,
+		USB_SC_UFI, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 UNUSUAL_DEV(  0x054c, 0x0032, 0x0000, 0x9999,
 		"Sony",
 		"Memorystick MSC-U01N",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Michal Mlotek <mlotek@foobar.pl> */
 UNUSUAL_DEV(  0x054c, 0x0058, 0x0000, 0x9999,
 		"Sony",
 		"PEG N760c Memorystick",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 		
 UNUSUAL_DEV(  0x054c, 0x0069, 0x0000, 0x9999,
 		"Sony",
 		"Memorystick MSC-U03",
-		US_SC_UFI, US_PR_CB, NULL,
+		USB_SC_UFI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Nathan Babb <nathan@lexi.com> */
 UNUSUAL_DEV(  0x054c, 0x006d, 0x0000, 0x9999,
 		"Sony",
 		"PEG Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Submitted by Frank Engel <frankie@cse.unsw.edu.au> */
 UNUSUAL_DEV(  0x054c, 0x0099, 0x0000, 0x9999,
 		"Sony",
 		"PEG Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Submitted by Mike Alborn <malborn@deandra.homeip.net> */
 UNUSUAL_DEV(  0x054c, 0x016a, 0x0000, 0x9999,
 		"Sony",
 		"PEG Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* floppy reports multiple luns */
 UNUSUAL_DEV(  0x055d, 0x2020, 0x0000, 0x0210,
 		"SAMSUNG",
 		"SFD-321U [FW 0C]",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* We keep this entry to force the transport; firmware 3.00 and later is ok. */
 UNUSUAL_DEV(  0x057b, 0x0000, 0x0000, 0x0299,
 		"Y-E Data",
 		"Flashbuster-U",
-		US_SC_DEVICE,  US_PR_CB, NULL,
+		USB_SC_DEVICE,  USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN),
 
 /* Reported by Johann Cardon <johann.cardon@free.fr>
@@ -664,20 +664,20 @@
 UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999,
 		"Y-E Data",
 		"Silicon Media R/W",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0),
 
 /* Reported by RTE <raszilki@yandex.ru> */
 UNUSUAL_DEV(  0x058f, 0x6387, 0x0141, 0x0141,
 		"JetFlash",
 		"TS1GJF2A/120",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /* Fabrizio Fellini <fello@libero.it> */
 UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
 		"Fujifilm",
 		"Digital Camera EX-20 DSC",
-		US_SC_8070, US_PR_DEVICE, NULL, 0 ),
+		USB_SC_8070, USB_PR_DEVICE, NULL, 0 ),
 
 /* Reported by Andre Welter <a.r.welter@gmx.de>
  * This antique device predates the release of the Bulk-only Transport
@@ -688,14 +688,14 @@
 UNUSUAL_DEV(  0x059b, 0x0001, 0x0100, 0x0100,
 		"Iomega",
 		"ZIP 100",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Reported by <Hendryk.Pfeiffer@gmx.de> */
 UNUSUAL_DEV(  0x059f, 0x0643, 0x0000, 0x0000,
 		"LaCie",
 		"DVD+-RW",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_GO_SLOW ),
 
 /* Submitted by Joel Bourquard <numlock@freesurf.ch>
@@ -705,7 +705,7 @@
 UNUSUAL_DEV(  0x05ab, 0x0060, 0x1104, 0x1110,
 		"In-System",
 		"PyroGate External CD-ROM Enclosure (FCD-523)",
-		US_SC_SCSI, US_PR_BULK, NULL,
+		USB_SC_SCSI, USB_PR_BULK, NULL,
 		US_FL_NEED_OVERRIDE ),
 
 /* Submitted by Sven Anderson <sven-linux@anderson.de>
@@ -717,26 +717,26 @@
 UNUSUAL_DEV( 0x05ac, 0x1202, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /* Reported by Avi Kivity <avi@argo.co.il> */
 UNUSUAL_DEV( 0x05ac, 0x1203, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 UNUSUAL_DEV( 0x05ac, 0x1204, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
 
 UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /*
@@ -746,7 +746,7 @@
 UNUSUAL_DEV( 0x05ac, 0x120a, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /* Reported by Dan Williams <dcbw@redhat.com>
@@ -758,14 +758,14 @@
 UNUSUAL_DEV(  0x05c6, 0x1000, 0x0000, 0x9999,
 		"Option N.V.",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, option_ms_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init,
 		0),
 
 /* Reported by Blake Matheny <bmatheny@purdue.edu> */
 UNUSUAL_DEV(  0x05dc, 0xb002, 0x0000, 0x0113,
 		"Lexar",
 		"USB CF Reader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* The following two entries are for a Genesys USB to IDE
@@ -782,20 +782,20 @@
 UNUSUAL_DEV(  0x05e3, 0x0701, 0x0000, 0xffff,
 		"Genesys Logic",
 		"USB to IDE Optical",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
 
 UNUSUAL_DEV(  0x05e3, 0x0702, 0x0000, 0xffff,
 		"Genesys Logic",
 		"USB to IDE Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV(  0x05e3, 0x0723, 0x9451, 0x9451,
 		"Genesys Logic",
 		"USB to SATA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SANE_SENSE ),
 
 /* Reported by Hanno Boeck <hanno@gmx.de>
@@ -803,33 +803,33 @@
 UNUSUAL_DEV(  0x0636, 0x0003, 0x0000, 0x9999,
 		"Vivitar",
 		"Vivicam 35Xx",
-		US_SC_SCSI, US_PR_BULK, NULL,
+		USB_SC_SCSI, USB_PR_BULK, NULL,
 		US_FL_FIX_INQUIRY ),
 
 UNUSUAL_DEV(  0x0644, 0x0000, 0x0100, 0x0100,
 		"TEAC",
 		"Floppy Drive",
-		US_SC_UFI, US_PR_CB, NULL, 0 ),
+		USB_SC_UFI, USB_PR_CB, NULL, 0 ),
 
 /* Reported by Darsen Lu <darsen@micro.ee.nthu.edu.tw> */
 UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
 		"SigmaTel",
 		"USBMSC Audio Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /* Reported by Daniel Kukula <daniel.kuku@gmail.com> */
 UNUSUAL_DEV( 0x067b, 0x1063, 0x0100, 0x0100,
 		"Prolific Technology, Inc.",
 		"Prolific Storage Gadget",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_BAD_SENSE ),
 
 /* Reported by Rogerio Brito <rbrito@ime.usp.br> */
 UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001,
 		"Prolific Technology, Inc.",
 		"Mass Storage Device",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NOT_LOCKABLE ),
 
 /* Reported by Richard -=[]=- <micro_flyer@hotmail.com> */
@@ -838,46 +838,47 @@
 UNUSUAL_DEV( 0x067b, 0x2507, 0x0001, 0x0100,
 		"Prolific Technology Inc.",
 		"Mass Storage Device",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_GO_SLOW ),
 
 /* Reported by Alex Butcher <alex.butcher@assursys.co.uk> */
 UNUSUAL_DEV( 0x067b, 0x3507, 0x0001, 0x0101,
 		"Prolific Technology Inc.",
 		"ATAPI-6 Bridge Controller",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_GO_SLOW ),
 
 /* Submitted by Benny Sjostrand <benny@hostmobility.com> */
 UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
 		"Minolta",
 		"Dimage F300",
-		US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+		USB_SC_SCSI, USB_PR_BULK, NULL, 0 ),
 
 /* Reported by Miguel A. Fosas <amn3s1a@ono.com> */
 UNUSUAL_DEV(  0x0686, 0x4017, 0x0001, 0x0001,
 		"Minolta",
 		"DIMAGE E223",
-		US_SC_SCSI, US_PR_DEVICE, NULL, 0 ),
+		USB_SC_SCSI, USB_PR_DEVICE, NULL, 0 ),
 
 UNUSUAL_DEV(  0x0693, 0x0005, 0x0100, 0x0100,
 		"Hagiwara",
 		"Flashgate",
-		US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+		USB_SC_SCSI, USB_PR_BULK, NULL, 0 ),
 
 /* Reported by David Hamilton <niftimusmaximus@lycos.com> */
 UNUSUAL_DEV(  0x069b, 0x3004, 0x0001, 0x0001,
 		"Thomson Multimedia Inc.",
 		"RCA RD1080 MP3 Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /* Reported by Adrian Pilchowiec <adi1981@epf.pl> */
 UNUSUAL_DEV(  0x071b, 0x3203, 0x0000, 0x0000,
 		"RockChip",
 		"MP3",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+		US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64 |
+		US_FL_NO_READ_CAPACITY_16),
 
 /* Reported by Jean-Baptiste Onofre <jb@nanthrax.net>
  * Support the following product :
@@ -886,7 +887,7 @@
 UNUSUAL_DEV(  0x071b, 0x32bb, 0x0000, 0x0000,
 		"RockChip",
 		"MTP",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64),
 
 /* Reported by Massimiliano Ghilardi <massimiliano.ghilardi@gmail.com>
@@ -902,59 +903,59 @@
 UNUSUAL_DEV(  0x071b, 0x3203, 0x0100, 0x0100,
 		"RockChip",
 		"ROCK MP3",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64),
 
 /* Reported by Olivier Blondeau <zeitoun@gmail.com> */
 UNUSUAL_DEV(  0x0727, 0x0306, 0x0100, 0x0100,
 		"ATMEL",
 		"SND1 Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE),
 
 /* Submitted by Roman Hodek <roman@hodek.net> */
 UNUSUAL_DEV(  0x0781, 0x0001, 0x0200, 0x0200,
 		"Sandisk",
 		"ImageMate SDDR-05a",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
 UNUSUAL_DEV(  0x0781, 0x0002, 0x0009, 0x0009,
 		"SanDisk Corporation",
 		"ImageMate CompactFlash USB",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
 		"Sandisk",
 		"ImageMate SDDR-12",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Reported by Eero Volotinen <eero@ping-viini.org> */
 UNUSUAL_DEV(  0x07ab, 0xfccd, 0x0000, 0x9999,
 		"Freecom Technologies",
 		"FHD-Classic",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 UNUSUAL_DEV(  0x07af, 0x0004, 0x0100, 0x0133,
 		"Microtech",
 		"USB-SCSI-DB25",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ), 
 
 UNUSUAL_DEV(  0x07af, 0x0005, 0x0100, 0x0100,
 		"Microtech",
 		"USB-SCSI-HD50",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ),
 
 #ifdef NO_SDDR09
 UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
 		"Microtech",
 		"CameraMate",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 #endif
 
@@ -967,7 +968,7 @@
 UNUSUAL_DEV(  0x07c4, 0xa400, 0x0000, 0xffff,
 		"Datafab",
 		"KECF-USB",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY ),
 
 /* Reported by Rauch Wolke <rauchwolke@gmx.net>
@@ -976,7 +977,7 @@
 UNUSUAL_DEV(  0x07c4, 0xa4a5, 0x0000, 0xffff,
 		"Simple Tech/Datafab",
 		"CF+SM Reader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_MAX_SECTORS_64 ),
 
 /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
@@ -986,42 +987,42 @@
  * - They don't like the INQUIRY command. So we must handle this command
  *   of the SCSI layer ourselves.
  * - Some cameras with idProduct=0x1001 and bcdDevice=0x1000 have
- *   bInterfaceProtocol=0x00 (US_PR_CBI) while others have 0x01 (US_PR_CB).
- *   So don't remove the US_PR_CB override!
- * - Cameras with bcdDevice=0x9009 require the US_SC_8070 override.
+ *   bInterfaceProtocol=0x00 (USB_PR_CBI) while others have 0x01 (USB_PR_CB).
+ *   So don't remove the USB_PR_CB override!
+ * - Cameras with bcdDevice=0x9009 require the USB_SC_8070 override.
  */
 UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
 		"Casio",
 		"QV DigitalCamera",
-		US_SC_8070, US_PR_CB, NULL,
+		USB_SC_8070, USB_PR_CB, NULL,
 		US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),
 
 /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
 UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
 		"Samsung",
 		"Digimax 410",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY),
 
 /* Reported by Luciano Rocha <luciano@eurotux.com> */
 UNUSUAL_DEV( 0x0840, 0x0082, 0x0001, 0x0001,
 		"Argosy",
 		"Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* Reported and patched by Nguyen Anh Quynh <aquynh@gmail.com> */
 UNUSUAL_DEV( 0x0840, 0x0084, 0x0001, 0x0001,
 		"Argosy",
 		"Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* Reported by Martijn Hijdra <martijn.hijdra@gmail.com> */
 UNUSUAL_DEV( 0x0840, 0x0085, 0x0001, 0x0001,
 		"Argosy",
 		"Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
@@ -1033,7 +1034,7 @@
 UNUSUAL_DEV(  0x084d, 0x0011, 0x0110, 0x0110,
 		"Grandtech",
 		"DC2MEGA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_BULK32),
 
 /* Andrew Lunn <andrew@lunn.ch>
@@ -1044,14 +1045,14 @@
 UNUSUAL_DEV(  0x0851, 0x1543, 0x0200, 0x0200,
 		"PanDigital",
 		"Photo Frame",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NOT_LOCKABLE),
 
 /* Submitted by Jan De Luyck <lkml@kcore.org> */
 UNUSUAL_DEV(  0x08bd, 0x1100, 0x0000, 0x0000,
 		"CITIZEN",
 		"X1DE-USB",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
 /* Submitted by Dylan Taft <d13f00l@gmail.com>
@@ -1060,7 +1061,7 @@
 UNUSUAL_DEV(  0x08ca, 0x3103, 0x0100, 0x0100,
 		"AIPTEK",
 		"Aiptek USB Keychain MP3 Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE),
 
 /* Entry needed for flags. Moreover, all devices with this ID use
@@ -1071,7 +1072,7 @@
 UNUSUAL_DEV(  0x090a, 0x1001, 0x0100, 0x0100,
 		"Trumpion",
 		"t33520 USB Flash Card Controller",
-		US_SC_DEVICE, US_PR_BULK, NULL,
+		USB_SC_DEVICE, USB_PR_BULK, NULL,
 		US_FL_NEED_OVERRIDE ),
 
 /* Reported by Filippo Bardelli <filibard@libero.it>
@@ -1080,21 +1081,21 @@
 UNUSUAL_DEV(  0x090a, 0x1050, 0x0100, 0x0100,
 		"Trumpion Microelectronics, Inc.",
 		"33520 USB Digital Voice Recorder",
-		US_SC_UFI, US_PR_DEVICE, NULL,
+		USB_SC_UFI, USB_PR_DEVICE, NULL,
 		0),
 
 /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
 UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
 		"Trumpion",
 		"MP3 player",
-		US_SC_RBC, US_PR_BULK, NULL,
+		USB_SC_RBC, USB_PR_BULK, NULL,
 		0 ),
 
 /* aeb */
 UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
 		"Feiya",
 		"5-in-1 Card Reader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /* This Pentax still camera is not conformant
@@ -1107,7 +1108,7 @@
 UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
 		"Pentax",
 		"Optio 2/3/400",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* These are virtual windows driver CDs, which the zd1211rw driver
@@ -1115,13 +1116,13 @@
 UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101,
 		"ZyXEL",
 		"G-220F USB-WLAN Install",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_DEVICE ),
 
 UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101,
 		"SiteCom",
 		"WL-117 USB-WLAN Install",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_DEVICE ),
 
 /* Reported by Dan Williams <dcbw@redhat.com>
@@ -1133,7 +1134,7 @@
 UNUSUAL_DEV(  0x0af0, 0x6971, 0x0000, 0x9999,
 		"Option N.V.",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, option_ms_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init,
 		0),
 
 /* Reported by F. Aben <f.aben@option.com>
@@ -1143,7 +1144,7 @@
 UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000,
 		"Option",
 		"GI 0401 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 /* Reported by Jan Dumon <j.dumon@option.com>
@@ -1153,104 +1154,104 @@
 UNUSUAL_DEV( 0x0af0, 0x7501, 0x0000, 0x0000,
 		"Option",
 		"GI 0431 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x7701, 0x0000, 0x0000,
 		"Option",
 		"GI 0451 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x7706, 0x0000, 0x0000,
 		"Option",
 		"GI 0451 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x7901, 0x0000, 0x0000,
 		"Option",
 		"GI 0452 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x7A01, 0x0000, 0x0000,
 		"Option",
 		"GI 0461 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x7A05, 0x0000, 0x0000,
 		"Option",
 		"GI 0461 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x8300, 0x0000, 0x0000,
 		"Option",
 		"GI 033x SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x8302, 0x0000, 0x0000,
 		"Option",
 		"GI 033x SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x8304, 0x0000, 0x0000,
 		"Option",
 		"GI 033x SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xc100, 0x0000, 0x0000,
 		"Option",
 		"GI 070x SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xd057, 0x0000, 0x0000,
 		"Option",
 		"GI 1505 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xd058, 0x0000, 0x0000,
 		"Option",
 		"GI 1509 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xd157, 0x0000, 0x0000,
 		"Option",
 		"GI 1515 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xd257, 0x0000, 0x0000,
 		"Option",
 		"GI 1215 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xd357, 0x0000, 0x0000,
 		"Option",
 		"GI 1505 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000,
 		"Seagate",
 		"FreeAgent Pro",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SANE_SENSE ),
 
 UNUSUAL_DEV(  0x0d49, 0x7310, 0x0000, 0x9999,
 		"Maxtor",
 		"USB to SATA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SANE_SENSE),
 
 /*
@@ -1260,14 +1261,14 @@
 UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100,
 		"Unknown",
 		"Unknown",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Joris Struyve <joris@struyve.be> */
 UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
 		"Medion",
 		"MD 7425",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY),
 
 /*
@@ -1278,13 +1279,13 @@
 UNUSUAL_DEV(  0x0d96, 0x5200, 0x0001, 0x0200,
 		"Jenoptik",
 		"JD 5200 z3",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
 
 /* Reported by  Jason Johnston <killean@shaw.ca> */
 UNUSUAL_DEV(  0x0dc4, 0x0073, 0x0000, 0x0000,
 		"Macpower Technology Co.LTD.",
 		"USB 2.0 3.5\" DEVICE",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* Reported by Lubomir Blaha <tritol@trilogic.cz>
@@ -1295,7 +1296,7 @@
 UNUSUAL_DEV( 0x0dd8, 0x1060, 0x0000, 0xffff,
 		"Netac",
 		"USB-CF-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Reported by Edward Chapman (taken from linux-usb mailing list)
@@ -1303,7 +1304,7 @@
 UNUSUAL_DEV( 0x0dd8, 0xd202, 0x0000, 0x9999,
 		"Netac",
 		"USB Flash Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 
@@ -1312,28 +1313,28 @@
 UNUSUAL_DEV( 0x0dda, 0x0001, 0x0012, 0x0012,
 		"WINWARD",
 		"Music Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Ian McConnell <ian at emit.demon.co.uk> */
 UNUSUAL_DEV(  0x0dda, 0x0301, 0x0012, 0x0012,
 		"PNP_MP3",
 		"PNP_MP3 PLAYER",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Jim McCloskey <mcclosk@ucsc.edu> */
 UNUSUAL_DEV( 0x0e21, 0x0520, 0x0100, 0x0100,
 		"Cowon Systems",
 		"iAUDIO M5",
-		US_SC_DEVICE, US_PR_BULK, NULL,
+		USB_SC_DEVICE, USB_PR_BULK, NULL,
 		US_FL_NEED_OVERRIDE ),
 
 /* Submitted by Antoine Mairesse <antoine.mairesse@free.fr> */
 UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300,
 		"USB",
 		"Solid state disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Submitted by Daniel Drake <dsd@gentoo.org>
@@ -1341,14 +1342,14 @@
 UNUSUAL_DEV(  0x0ea0, 0x2168, 0x0110, 0x0110,
 		"Ours Technology",
 		"Flash Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Rastislav Stanik <rs_kernel@yahoo.com> */
 UNUSUAL_DEV(  0x0ea0, 0x6828, 0x0110, 0x0110,
 		"USB",
 		"Flash Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Benjamin Schiller <sbenni@gmx.de>
@@ -1356,7 +1357,7 @@
 UNUSUAL_DEV(  0x0ed1, 0x7636, 0x0103, 0x0103,
 		"Typhoon",
 		"My DJ 1820",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64),
 
 /* Patch by Leonid Petrov mail at lpetrov.net
@@ -1367,7 +1368,7 @@
 UNUSUAL_DEV(  0x0f19, 0x0103, 0x0100, 0x0100,
 		"Oracom Co., Ltd",
 		"ORC-200M",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* David Kuehling <dvdkhlng@gmx.de>:
@@ -1377,21 +1378,21 @@
 UNUSUAL_DEV(  0x0f19, 0x0105, 0x0100, 0x0100,
 		"C-MEX",
 		"A-VOX",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Michael Stattmann <michael@stattmann.com> */
 UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"V800-Vodafone 802",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NO_WP_DETECT ),
 
 /* Reported by The Solutor <thesolutor@gmail.com> */
 UNUSUAL_DEV(  0x0fce, 0xd0e1, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"MD400",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_DEVICE),
 
 /* Reported by Jan Mate <mate@fiit.stuba.sk>
@@ -1399,21 +1400,21 @@
 UNUSUAL_DEV(  0x0fce, 0xe030, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"P990i",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */
 UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"M600i",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by Ricardo Barberis <ricardo@dattatec.com> */
 UNUSUAL_DEV(  0x0fce, 0xe092, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"P1i",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
@@ -1425,13 +1426,13 @@
 UNUSUAL_DEV(  0x1019, 0x0c55, 0x0000, 0x0110,
 		"Desknote",
 		"UCR-61S2B",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_ucr61s2b_init,
 		0 ),
 
 UNUSUAL_DEV(  0x1058, 0x0704, 0x0000, 0x9999,
 		"Western Digital",
 		"External HDD",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SANE_SENSE),
 
 /* Reported by Fabio Venturi <f.venturi@tdnet.it>
@@ -1440,7 +1441,7 @@
 UNUSUAL_DEV(  0x10d6, 0x2200, 0x0100, 0x0100,
 		"Actions Semiconductor",
 		"Mtp device",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0),
 
 /* Reported by Pascal Terjan <pterjan@mandriva.com>
@@ -1449,7 +1450,7 @@
 UNUSUAL_DEV(  0x1186, 0x3e04, 0x0000, 0x0000,
            "D-Link",
            "USB Mass Storage",
-           US_SC_DEVICE, US_PR_DEVICE, option_ms_init, US_FL_IGNORE_DEVICE),
+           USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init, US_FL_IGNORE_DEVICE),
 
 /* Reported by Kevin Lloyd <linux@sierrawireless.com>
  * Entry is needed for the initializer function override,
@@ -1459,7 +1460,7 @@
 UNUSUAL_DEV(  0x1199, 0x0fff, 0x0000, 0x9999,
 		"Sierra Wireless",
 		"USB MMC Storage",
-		US_SC_DEVICE, US_PR_DEVICE, sierra_ms_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, sierra_ms_init,
 		0),
 
 /* Reported by Jaco Kroon <jaco@kroon.co.za>
@@ -1469,7 +1470,7 @@
 UNUSUAL_DEV(  0x1210, 0x0003, 0x0100, 0x0100,
 		"Digitech HMG",
 		"DigiTech Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by fangxiaozhi <huananhu@huawei.com>
@@ -1478,353 +1479,353 @@
 UNUSUAL_DEV(  0x12d1, 0x1001, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1003, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1004, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1401, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1402, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1403, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1404, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1405, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1406, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1407, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1408, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1409, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140A, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140B, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140C, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140D, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140E, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140F, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1410, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1411, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1412, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1413, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1414, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1415, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1416, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1417, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1418, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1419, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141A, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141B, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141C, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141D, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141E, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141F, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1420, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1421, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1422, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1423, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1424, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1425, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1426, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1427, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1428, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1429, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142A, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142B, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142C, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142D, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142E, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142F, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1430, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1431, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1432, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1433, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1434, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1435, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1436, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1437, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1438, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1439, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143A, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143B, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143C, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143D, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143E, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143F, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 
 /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
 UNUSUAL_DEV(  0x132b, 0x000b, 0x0001, 0x0001,
 		"Minolta",
 		"Dimage Z10",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 /* Reported by Kotrla Vitezslav <kotrla@ceb.cz> */
 UNUSUAL_DEV(  0x1370, 0x6828, 0x0110, 0x0110,
 		"SWISSBIT",
 		"Black Silver",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Francesco Foresti <frafore@tiscali.it> */
 UNUSUAL_DEV(  0x14cd, 0x6600, 0x0201, 0x0201,
 		"Super Top",
 		"IDE DEVICE",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Alexandre Oliva <oliva@lsd.ic.unicamp.br>
@@ -1833,7 +1834,7 @@
 UNUSUAL_DEV(  0x152d, 0x2329, 0x0100, 0x0100,
 		"JMicron",
 		"USB to ATA/ATAPI Bridge",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ),
 
 /* Reported by Robert Schedel <r.schedel@yahoo.de>
@@ -1841,7 +1842,7 @@
 UNUSUAL_DEV(  0x1652, 0x6600, 0x0201, 0x0201,
 		"Teac",
 		"HD-35PUK-B",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Hans de Goede <hdegoede@redhat.com>
@@ -1851,18 +1852,23 @@
 UNUSUAL_DEV( 0x1908, 0x1315, 0x0000, 0x0000,
 		"BUILDWIN",
 		"Photo Frame",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_BAD_SENSE ),
 UNUSUAL_DEV( 0x1908, 0x1320, 0x0000, 0x0000,
 		"BUILDWIN",
 		"Photo Frame",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_BAD_SENSE ),
+UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
+		"BUILDWIN",
+		"Photo Frame",
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+		US_FL_NO_READ_DISC_INFO ),
 
 UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001,
 		"ST",
 		"2A",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
@@ -1871,7 +1877,7 @@
 UNUSUAL_DEV(  0x22b8, 0x3010, 0x0001, 0x0001,
 		"Motorola",
 		"RAZR V3x",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
 
 /*
@@ -1882,14 +1888,14 @@
 UNUSUAL_DEV(  0x22b8, 0x6426, 0x0101, 0x0101,
 		"Motorola",
 		"MSnc.",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY | US_FL_BULK_IGNORE_TAG),
 
 /* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */
 UNUSUAL_DEV(  0x2735, 0x100b, 0x0000, 0x9999,
 		"MPIO",
 		"HS200",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_GO_SLOW ),
 
 /* Reported by Frederic Marchal <frederic.marchal@wowcompany.com>
@@ -1898,21 +1904,21 @@
 UNUSUAL_DEV(  0x3340, 0xffff, 0x0000, 0x0000,
 		"Mitac",
 		"Mio DigiWalker USB Sync",
-		US_SC_DEVICE,US_PR_DEVICE,NULL,
+		USB_SC_DEVICE,USB_PR_DEVICE,NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /* Reported by Andrey Rahmatullin <wrar@altlinux.org> */
 UNUSUAL_DEV(  0x4102, 0x1020, 0x0100,  0x0100,
 		"iRiver",
 		"MP3 T10",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Sergey Pinaev <dfo@antex.ru> */
 UNUSUAL_DEV(  0x4102, 0x1059, 0x0000,  0x0000,
                "iRiver",
                "P7K",
-               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_MAX_SECTORS_64 ),
 
 /*
@@ -1922,41 +1928,41 @@
 UNUSUAL_DEV(  0x4146, 0xba01, 0x0100, 0x0100,
 		"Iomega",
 		"Micro Mini 1GB",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
 
 /* Reported by Andrew Simmons <andrew.simmons@gmail.com> */
 UNUSUAL_DEV(  0xed06, 0x4500, 0x0001, 0x0001,
 		"DataStor",
 		"USB4500 FW1.04",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_CAPACITY_HEURISTICS),
 
 /* Reported by Alessio Treglia <quadrispro@ubuntu.com> */
 UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001,
 		"TGE",
 		"Digital MP3 Audio Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
 
 /* Control/Bulk transport for all SubClass values */
-USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_QIC, US_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_UFI, US_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_8070, US_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_SCSI, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_RBC, USB_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8020, USB_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_QIC, USB_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_UFI, USB_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8070, USB_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_SCSI, USB_PR_CB, USB_US_TYPE_STOR),
 
 /* Control/Bulk/Interrupt transport for all SubClass values */
-USUAL_DEV(US_SC_RBC, US_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_8020, US_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_QIC, US_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_UFI, US_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_8070, US_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_SCSI, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_RBC, USB_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8020, USB_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_QIC, USB_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_UFI, USB_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8070, USB_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_SCSI, USB_PR_CBI, USB_US_TYPE_STOR),
 
 /* Bulk-only transport for all SubClass values */
-USUAL_DEV(US_SC_RBC, US_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_8020, US_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_QIC, US_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_UFI, US_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_8070, US_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0),
+USUAL_DEV(USB_SC_RBC, USB_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8020, USB_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_QIC, USB_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_UFI, USB_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8070, USB_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0),
diff --git a/drivers/usb/storage/unusual_freecom.h b/drivers/usb/storage/unusual_freecom.h
index 3758679..59a2611 100644
--- a/drivers/usb/storage/unusual_freecom.h
+++ b/drivers/usb/storage/unusual_freecom.h
@@ -21,6 +21,6 @@
 UNUSUAL_DEV(  0x07ab, 0xfc01, 0x0000, 0x9999,
 		"Freecom",
 		"USB-IDE",
-		US_SC_QIC, US_PR_FREECOM, init_freecom, 0),
+		USB_SC_QIC, USB_PR_FREECOM, init_freecom, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_FREECOM) || ... */
diff --git a/drivers/usb/storage/unusual_isd200.h b/drivers/usb/storage/unusual_isd200.h
index 0d99dde..14cca0c 100644
--- a/drivers/usb/storage/unusual_isd200.h
+++ b/drivers/usb/storage/unusual_isd200.h
@@ -21,37 +21,37 @@
 UNUSUAL_DEV(  0x054c, 0x002b, 0x0100, 0x0110,
 		"Sony",
 		"Portable USB Harddrive V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0110,
 		"In-System",
 		"USB/IDE Bridge (ATA/ATAPI)",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 UNUSUAL_DEV(  0x05ab, 0x0301, 0x0100, 0x0110,
 		"In-System",
 		"Portable USB Harddrive V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 UNUSUAL_DEV(  0x05ab, 0x0351, 0x0100, 0x0110,
 		"In-System",
 		"Portable USB Harddrive V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 UNUSUAL_DEV(  0x05ab, 0x5701, 0x0100, 0x0110,
 		"In-System",
 		"USB Storage Adapter V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x0110,
 		"ATI",
 		"USB Cable 205",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 #endif /* defined(CONFIG_USB_STORAGE_ISD200) || ... */
diff --git a/drivers/usb/storage/unusual_jumpshot.h b/drivers/usb/storage/unusual_jumpshot.h
index 2e549b1..54be78b 100644
--- a/drivers/usb/storage/unusual_jumpshot.h
+++ b/drivers/usb/storage/unusual_jumpshot.h
@@ -21,7 +21,7 @@
 UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x0001,
 		"Lexar",
 		"Jumpshot USB CF Reader",
-		US_SC_SCSI, US_PR_JUMPSHOT, NULL,
+		USB_SC_SCSI, USB_PR_JUMPSHOT, NULL,
 		US_FL_NEED_OVERRIDE),
 
 #endif /* defined(CONFIG_USB_STORAGE_JUMPSHOT) || ... */
diff --git a/drivers/usb/storage/unusual_karma.h b/drivers/usb/storage/unusual_karma.h
index 12ae3a0..6df0397 100644
--- a/drivers/usb/storage/unusual_karma.h
+++ b/drivers/usb/storage/unusual_karma.h
@@ -21,6 +21,6 @@
 UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
 		"Rio",
 		"Rio Karma",
-		US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
+		USB_SC_SCSI, USB_PR_KARMA, rio_karma_init, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_KARMA) || ... */
diff --git a/drivers/usb/storage/unusual_onetouch.h b/drivers/usb/storage/unusual_onetouch.h
index bd9306b..0abb819 100644
--- a/drivers/usb/storage/unusual_onetouch.h
+++ b/drivers/usb/storage/unusual_onetouch.h
@@ -24,13 +24,13 @@
 UNUSUAL_DEV(  0x0d49, 0x7000, 0x0000, 0x9999,
 		"Maxtor",
 		"OneTouch External Harddrive",
-		US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
+		USB_SC_DEVICE, USB_PR_DEVICE, onetouch_connect_input,
 		0),
 
 UNUSUAL_DEV(  0x0d49, 0x7010, 0x0000, 0x9999,
 		"Maxtor",
 		"OneTouch External Harddrive",
-		US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
+		USB_SC_DEVICE, USB_PR_DEVICE, onetouch_connect_input,
 		0),
 
 #endif /* defined(CONFIG_USB_STORAGE_ONETOUCH) || ... */
diff --git a/drivers/usb/storage/unusual_sddr09.h b/drivers/usb/storage/unusual_sddr09.h
index 50cab51..59a7e37 100644
--- a/drivers/usb/storage/unusual_sddr09.h
+++ b/drivers/usb/storage/unusual_sddr09.h
@@ -21,36 +21,36 @@
 UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
 		"Microtech",
 		"CameraMate (DPCM_USB)",
-		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0),
+		USB_SC_SCSI, USB_PR_DPCM_USB, NULL, 0),
 
 UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999,
 		"Sandisk",
 		"ImageMate SDDR09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		USB_SC_SCSI, USB_PR_EUSB_SDDR09, usb_stor_sddr09_init,
 		0),
 
 /* This entry is from Andries.Brouwer@cwi.nl */
 UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
 		"SCM Microsystems",
 		"eUSB SmartMedia / CompactFlash Adapter",
-		US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
+		USB_SC_SCSI, USB_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
 		0),
 
 UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100,
 		"Olympus",
 		"Camedia MAUSB-2",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		USB_SC_SCSI, USB_PR_EUSB_SDDR09, usb_stor_sddr09_init,
 		0),
 
 UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999,
 		"Sandisk",
 		"ImageMate SDDR-09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		USB_SC_SCSI, USB_PR_EUSB_SDDR09, usb_stor_sddr09_init,
 		0),
 
 UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
 		"Microtech",
 		"CameraMate (DPCM_USB)",
-		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0),
+		USB_SC_SCSI, USB_PR_DPCM_USB, NULL, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_SDDR09) || ... */
diff --git a/drivers/usb/storage/unusual_sddr55.h b/drivers/usb/storage/unusual_sddr55.h
index ae81ef7..fcb7e12 100644
--- a/drivers/usb/storage/unusual_sddr55.h
+++ b/drivers/usb/storage/unusual_sddr55.h
@@ -22,23 +22,23 @@
 UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999,
 		"Datafab",
 		"MDSM-B reader",
-		US_SC_SCSI, US_PR_SDDR55, NULL,
+		USB_SC_SCSI, USB_PR_SDDR55, NULL,
 		US_FL_FIX_INQUIRY),
 
 /* SM part - aeb <Andries.Brouwer@cwi.nl> */
 UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
 		"Datafab Systems, Inc.",
 		"USB to CF + SM Combo (LC1)",
-		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
+		USB_SC_SCSI, USB_PR_SDDR55, NULL, 0),
 
 UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
 		"Acomdata",
 		"SM",
-		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
+		USB_SC_SCSI, USB_PR_SDDR55, NULL, 0),
 
 UNUSUAL_DEV(  0x55aa, 0xa103, 0x0000, 0x9999,
 		"Sandisk",
 		"ImageMate SDDR55",
-		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
+		USB_SC_SCSI, USB_PR_SDDR55, NULL, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_SDDR55) || ... */
diff --git a/drivers/usb/storage/unusual_usbat.h b/drivers/usb/storage/unusual_usbat.h
index 80e869f..38e79c4 100644
--- a/drivers/usb/storage/unusual_usbat.h
+++ b/drivers/usb/storage/unusual_usbat.h
@@ -21,23 +21,23 @@
 UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001,
 		"HP",
 		"CD-Writer+ 8200e",
-		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+		USB_SC_8070, USB_PR_USBAT, init_usbat_cd, 0),
 
 UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001,
 		"HP",
 		"CD-Writer+ CD-4e",
-		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+		USB_SC_8070, USB_PR_USBAT, init_usbat_cd, 0),
 
 UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
 		"Shuttle/SCM",
 		"USBAT-02",
-		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
+		USB_SC_SCSI, USB_PR_USBAT, init_usbat_flash,
 		US_FL_SINGLE_LUN),
 
 UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
 		"Sandisk",
 		"ImageMate SDDR-05b",
-		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
+		USB_SC_SCSI, USB_PR_USBAT, init_usbat_flash,
 		US_FL_SINGLE_LUN),
 
 #endif /* defined(CONFIG_USB_STORAGE_USBAT) || ... */
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 90bb017..4219c19 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -512,10 +512,10 @@
 
 	/* Store the entries */
 	us->unusual_dev = unusual_dev;
-	us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ?
+	us->subclass = (unusual_dev->useProtocol == USB_SC_DEVICE) ?
 			idesc->bInterfaceSubClass :
 			unusual_dev->useProtocol;
-	us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
+	us->protocol = (unusual_dev->useTransport == USB_PR_DEVICE) ?
 			idesc->bInterfaceProtocol :
 			unusual_dev->useTransport;
 	us->fflags = USB_US_ORIG_FLAGS(id->driver_info);
@@ -552,10 +552,10 @@
 		struct usb_device_descriptor *ddesc = &dev->descriptor;
 		int msg = -1;
 
-		if (unusual_dev->useProtocol != US_SC_DEVICE &&
+		if (unusual_dev->useProtocol != USB_SC_DEVICE &&
 			us->subclass == idesc->bInterfaceSubClass)
 			msg += 1;
-		if (unusual_dev->useTransport != US_PR_DEVICE &&
+		if (unusual_dev->useTransport != USB_PR_DEVICE &&
 			us->protocol == idesc->bInterfaceProtocol)
 			msg += 2;
 		if (msg >= 0 && !(us->fflags & US_FL_NEED_OVERRIDE))
@@ -582,21 +582,21 @@
 static void get_transport(struct us_data *us)
 {
 	switch (us->protocol) {
-	case US_PR_CB:
+	case USB_PR_CB:
 		us->transport_name = "Control/Bulk";
 		us->transport = usb_stor_CB_transport;
 		us->transport_reset = usb_stor_CB_reset;
 		us->max_lun = 7;
 		break;
 
-	case US_PR_CBI:
+	case USB_PR_CBI:
 		us->transport_name = "Control/Bulk/Interrupt";
 		us->transport = usb_stor_CB_transport;
 		us->transport_reset = usb_stor_CB_reset;
 		us->max_lun = 7;
 		break;
 
-	case US_PR_BULK:
+	case USB_PR_BULK:
 		us->transport_name = "Bulk";
 		us->transport = usb_stor_Bulk_transport;
 		us->transport_reset = usb_stor_Bulk_reset;
@@ -608,35 +608,35 @@
 static void get_protocol(struct us_data *us)
 {
 	switch (us->subclass) {
-	case US_SC_RBC:
+	case USB_SC_RBC:
 		us->protocol_name = "Reduced Block Commands (RBC)";
 		us->proto_handler = usb_stor_transparent_scsi_command;
 		break;
 
-	case US_SC_8020:
+	case USB_SC_8020:
 		us->protocol_name = "8020i";
 		us->proto_handler = usb_stor_pad12_command;
 		us->max_lun = 0;
 		break;
 
-	case US_SC_QIC:
+	case USB_SC_QIC:
 		us->protocol_name = "QIC-157";
 		us->proto_handler = usb_stor_pad12_command;
 		us->max_lun = 0;
 		break;
 
-	case US_SC_8070:
+	case USB_SC_8070:
 		us->protocol_name = "8070i";
 		us->proto_handler = usb_stor_pad12_command;
 		us->max_lun = 0;
 		break;
 
-	case US_SC_SCSI:
+	case USB_SC_SCSI:
 		us->protocol_name = "Transparent SCSI";
 		us->proto_handler = usb_stor_transparent_scsi_command;
 		break;
 
-	case US_SC_UFI:
+	case USB_SC_UFI:
 		us->protocol_name = "Uniform Floppy Interface (UFI)";
 		us->proto_handler = usb_stor_ufi_command;
 		break;
@@ -679,7 +679,7 @@
 		}
 	}
 
-	if (!ep_in || !ep_out || (us->protocol == US_PR_CBI && !ep_int)) {
+	if (!ep_in || !ep_out || (us->protocol == USB_PR_CBI && !ep_int)) {
 		US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
 		return -EIO;
 	}
@@ -834,7 +834,7 @@
 	if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
 
 		/* For bulk-only devices, determine the max LUN value */
-		if (us->protocol == US_PR_BULK &&
+		if (us->protocol == USB_PR_BULK &&
 				!(us->fflags & US_FL_SINGLE_LUN)) {
 			mutex_lock(&us->dev_mutex);
 			us->max_lun = usb_stor_Bulk_max_lun(us);
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 552679b..e24ce31 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -507,6 +507,7 @@
 	.open =		skel_open,
 	.release =	skel_release,
 	.flush =	skel_flush,
+	.llseek =	noop_llseek,
 };
 
 /*
diff --git a/drivers/usb/wusbcore/Makefile b/drivers/usb/wusbcore/Makefile
index 75f1ade..b3bd3130 100644
--- a/drivers/usb/wusbcore/Makefile
+++ b/drivers/usb/wusbcore/Makefile
@@ -1,9 +1,11 @@
+ccflags-$(CONFIG_USB_WUSB_CBAF_DEBUG) := -DDEBUG
+
 obj-$(CONFIG_USB_WUSB)		+= wusbcore.o
 obj-$(CONFIG_USB_HWA_HCD)	+= wusb-wa.o
 obj-$(CONFIG_USB_WUSB_CBAF)	+= wusb-cbaf.o
 
 
-wusbcore-objs := 	\
+wusbcore-y :=		\
 	crypto.o	\
 	devconnect.o	\
 	dev-sysfs.o	\
@@ -14,13 +16,10 @@
 	security.o	\
 	wusbhc.o
 
-wusb-cbaf-objs := cbaf.o
+wusb-cbaf-y := cbaf.o
 
-wusb-wa-objs :=	wa-hc.o		\
-		wa-nep.o	\
-		wa-rpipe.o	\
-		wa-xfer.o
-
-ifeq ($(CONFIG_USB_WUSB_CBAF_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+wusb-wa-y :=		\
+	wa-hc.o		\
+	wa-nep.o	\
+	wa-rpipe.o	\
+	wa-xfer.o
diff --git a/drivers/uwb/address.c b/drivers/uwb/address.c
index 9733213..8739c4f 100644
--- a/drivers/uwb/address.c
+++ b/drivers/uwb/address.c
@@ -363,10 +363,7 @@
 {
 	size_t result;
 	if (type)
-		result = scnprintf(buf, buf_size,
-				  "%02x:%02x:%02x:%02x:%02x:%02x",
-				  addr[0], addr[1], addr[2],
-				  addr[3], addr[4], addr[5]);
+		result = scnprintf(buf, buf_size, "%pM", addr);
 	else
 		result = scnprintf(buf, buf_size, "%02x:%02x",
 				  addr[1], addr[0]);
diff --git a/drivers/uwb/wlp/wss-lc.c b/drivers/uwb/wlp/wss-lc.c
index a005d2a..67872c8 100644
--- a/drivers/uwb/wlp/wss-lc.c
+++ b/drivers/uwb/wlp/wss-lc.c
@@ -791,11 +791,8 @@
 	} else {
 		if (printk_ratelimit())
 			dev_err(dev, "WLP: Destination neighbor (Ethernet: "
-				"%02x:%02x:%02x:%02x:%02x:%02x, Dev: "
-				"%02x:%02x) is not connected. \n", eth_addr[0],
-				eth_addr[1], eth_addr[2], eth_addr[3],
-				eth_addr[4], eth_addr[5], dev_addr->data[1],
-				dev_addr->data[0]);
+				"%pM, Dev: %02x:%02x) is not connected.\n",
+				eth_addr, dev_addr->data[1], dev_addr->data[0]);
 		result = -EINVAL;
 	}
 	return result;
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 29e850a..4b4da5b 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -127,7 +127,10 @@
 	size_t len, total_len = 0;
 	int err, wmem;
 	size_t hdr_size;
-	struct socket *sock = rcu_dereference(vq->private_data);
+	struct socket *sock;
+
+	sock = rcu_dereference_check(vq->private_data,
+				     lockdep_is_held(&vq->mutex));
 	if (!sock)
 		return;
 
@@ -243,7 +246,7 @@
 	int r, nlogs = 0;
 
 	while (datalen > 0) {
-		if (unlikely(headcount >= VHOST_NET_MAX_SG)) {
+		if (unlikely(seg >= UIO_MAXIOV)) {
 			r = -ENOBUFS;
 			goto err;
 		}
@@ -582,7 +585,10 @@
 static void vhost_net_enable_vq(struct vhost_net *n,
 				struct vhost_virtqueue *vq)
 {
-	struct socket *sock = vq->private_data;
+	struct socket *sock;
+
+	sock = rcu_dereference_protected(vq->private_data,
+					 lockdep_is_held(&vq->mutex));
 	if (!sock)
 		return;
 	if (vq == n->vqs + VHOST_NET_VQ_TX) {
@@ -598,7 +604,8 @@
 	struct socket *sock;
 
 	mutex_lock(&vq->mutex);
-	sock = vq->private_data;
+	sock = rcu_dereference_protected(vq->private_data,
+					 lockdep_is_held(&vq->mutex));
 	vhost_net_disable_vq(n, vq);
 	rcu_assign_pointer(vq->private_data, NULL);
 	mutex_unlock(&vq->mutex);
@@ -736,7 +743,8 @@
 	}
 
 	/* start polling new socket */
-	oldsock = vq->private_data;
+	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);
@@ -869,6 +877,7 @@
 	.compat_ioctl   = vhost_net_compat_ioctl,
 #endif
 	.open           = vhost_net_open,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice vhost_net_misc = {
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index c579dcc..94701ff 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -212,6 +212,45 @@
 	}
 }
 
+/* Helper to allocate iovec buffers for all vqs. */
+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);
+		dev->vqs[i].log = kmalloc(sizeof *dev->vqs[i].log * UIO_MAXIOV,
+					  GFP_KERNEL);
+		dev->vqs[i].heads = kmalloc(sizeof *dev->vqs[i].heads *
+					    UIO_MAXIOV, GFP_KERNEL);
+
+		if (!dev->vqs[i].indirect || !dev->vqs[i].log ||
+			!dev->vqs[i].heads)
+			goto err_nomem;
+	}
+	return 0;
+err_nomem:
+	for (; i >= 0; --i) {
+		kfree(dev->vqs[i].indirect);
+		kfree(dev->vqs[i].log);
+		kfree(dev->vqs[i].heads);
+	}
+	return -ENOMEM;
+}
+
+static void vhost_dev_free_iovecs(struct vhost_dev *dev)
+{
+	int i;
+	for (i = 0; i < dev->nvqs; ++i) {
+		kfree(dev->vqs[i].indirect);
+		dev->vqs[i].indirect = NULL;
+		kfree(dev->vqs[i].log);
+		dev->vqs[i].log = NULL;
+		kfree(dev->vqs[i].heads);
+		dev->vqs[i].heads = NULL;
+	}
+}
+
 long vhost_dev_init(struct vhost_dev *dev,
 		    struct vhost_virtqueue *vqs, int nvqs)
 {
@@ -229,6 +268,9 @@
 	dev->worker = NULL;
 
 	for (i = 0; i < dev->nvqs; ++i) {
+		dev->vqs[i].log = NULL;
+		dev->vqs[i].indirect = NULL;
+		dev->vqs[i].heads = NULL;
 		dev->vqs[i].dev = dev;
 		mutex_init(&dev->vqs[i].mutex);
 		vhost_vq_reset(dev, dev->vqs + i);
@@ -295,6 +337,10 @@
 	if (err)
 		goto err_cgroup;
 
+	err = vhost_dev_alloc_iovecs(dev);
+	if (err)
+		goto err_cgroup;
+
 	return 0;
 err_cgroup:
 	kthread_stop(worker);
@@ -320,7 +366,7 @@
 	vhost_dev_cleanup(dev);
 
 	memory->nregions = 0;
-	dev->memory = memory;
+	RCU_INIT_POINTER(dev->memory, memory);
 	return 0;
 }
 
@@ -345,6 +391,7 @@
 			fput(dev->vqs[i].call);
 		vhost_vq_reset(dev, dev->vqs + i);
 	}
+	vhost_dev_free_iovecs(dev);
 	if (dev->log_ctx)
 		eventfd_ctx_put(dev->log_ctx);
 	dev->log_ctx = NULL;
@@ -352,8 +399,9 @@
 		fput(dev->log_file);
 	dev->log_file = NULL;
 	/* No one will access memory at this point */
-	kfree(dev->memory);
-	dev->memory = NULL;
+	kfree(rcu_dereference_protected(dev->memory,
+					lockdep_is_held(&dev->mutex)));
+	RCU_INIT_POINTER(dev->memory, NULL);
 	if (dev->mm)
 		mmput(dev->mm);
 	dev->mm = NULL;
@@ -371,7 +419,7 @@
 	/* Make sure 64 bit math will not overflow. */
 	if (a > ULONG_MAX - (unsigned long)log_base ||
 	    a + (unsigned long)log_base > ULONG_MAX)
-		return -EFAULT;
+		return 0;
 
 	return access_ok(VERIFY_WRITE, log_base + a,
 			 (sz + VHOST_PAGE_SIZE * 8 - 1) / VHOST_PAGE_SIZE / 8);
@@ -440,14 +488,22 @@
 /* Caller should have device mutex but not vq mutex */
 int vhost_log_access_ok(struct vhost_dev *dev)
 {
-	return memory_access_ok(dev, dev->memory, 1);
+	struct vhost_memory *mp;
+
+	mp = rcu_dereference_protected(dev->memory,
+				       lockdep_is_held(&dev->mutex));
+	return memory_access_ok(dev, mp, 1);
 }
 
 /* Verify access for write logging. */
 /* Caller should have vq mutex and device mutex */
 static int vq_log_access_ok(struct vhost_virtqueue *vq, void __user *log_base)
 {
-	return vq_memory_access_ok(log_base, vq->dev->memory,
+	struct vhost_memory *mp;
+
+	mp = rcu_dereference_protected(vq->dev->memory,
+				       lockdep_is_held(&vq->mutex));
+	return vq_memory_access_ok(log_base, mp,
 			    vhost_has_feature(vq->dev, VHOST_F_LOG_ALL)) &&
 		(!vq->log_used || log_access_ok(log_base, vq->log_addr,
 					sizeof *vq->used +
@@ -487,7 +543,8 @@
 		kfree(newmem);
 		return -EFAULT;
 	}
-	oldmem = d->memory;
+	oldmem = rcu_dereference_protected(d->memory,
+					   lockdep_is_held(&d->mutex));
 	rcu_assign_pointer(d->memory, newmem);
 	synchronize_rcu();
 	kfree(oldmem);
@@ -858,11 +915,12 @@
 		if (r < 0)
 			return r;
 		len -= l;
-		if (!len)
+		if (!len) {
+			if (vq->log_ctx)
+				eventfd_signal(vq->log_ctx, 1);
 			return 0;
+		}
 	}
-	if (vq->log_ctx)
-		eventfd_signal(vq->log_ctx, 1);
 	/* Length written exceeds what we have stored. This is a bug. */
 	BUG();
 	return 0;
@@ -946,7 +1004,7 @@
 	}
 
 	ret = translate_desc(dev, indirect->addr, indirect->len, vq->indirect,
-			     ARRAY_SIZE(vq->indirect));
+			     UIO_MAXIOV);
 	if (unlikely(ret < 0)) {
 		vq_err(vq, "Translation failure %d in indirect.\n", ret);
 		return ret;
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index afd7729..073d06a 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -15,11 +15,6 @@
 
 struct vhost_device;
 
-enum {
-	/* Enough place for all fragments, head, and virtio net header. */
-	VHOST_NET_MAX_SG = MAX_SKB_FRAGS + 2,
-};
-
 struct vhost_work;
 typedef void (*vhost_work_fn_t)(struct vhost_work *work);
 
@@ -93,12 +88,15 @@
 	bool log_used;
 	u64 log_addr;
 
-	struct iovec indirect[VHOST_NET_MAX_SG];
-	struct iovec iov[VHOST_NET_MAX_SG];
-	struct iovec hdr[VHOST_NET_MAX_SG];
+	struct iovec iov[UIO_MAXIOV];
+	/* hdr is used to store the virtio header.
+	 * Since each iovec has >= 1 byte length, we never need more than
+	 * header length entries to store the header. */
+	struct iovec hdr[sizeof(struct virtio_net_hdr_mrg_rxbuf)];
+	struct iovec *indirect;
 	size_t vhost_hlen;
 	size_t sock_hlen;
-	struct vring_used_elem heads[VHOST_NET_MAX_SG];
+	struct vring_used_elem *heads;
 	/* We use a kind of RCU to access private pointer.
 	 * All readers access it from worker, which makes it possible to
 	 * flush the vhost_work instead of synchronize_rcu. Therefore readers do
@@ -106,17 +104,17 @@
 	 * vhost_work execution acts instead of rcu_read_lock() and the end of
 	 * vhost_work execution acts instead of rcu_read_lock().
 	 * Writers use virtqueue mutex. */
-	void *private_data;
+	void __rcu *private_data;
 	/* Log write descriptors */
 	void __user *log_base;
-	struct vhost_log log[VHOST_NET_MAX_SG];
+	struct vhost_log *log;
 };
 
 struct vhost_dev {
 	/* Readers use RCU to access memory table pointer
 	 * log base pointer and features.
 	 * Writers use mutex below.*/
-	struct vhost_memory *memory;
+	struct vhost_memory __rcu *memory;
 	struct mm_struct *mm;
 	struct mutex mutex;
 	unsigned acked_features;
@@ -173,7 +171,11 @@
 
 static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
 {
-	unsigned acked_features = rcu_dereference(dev->acked_features);
+	unsigned acked_features;
+
+	acked_features =
+		rcu_dereference_index_check(dev->acked_features,
+					    lockdep_is_held(&dev->mutex));
 	return acked_features & (1 << bit);
 }
 
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index f3aada2..5b2b5ef 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -1718,11 +1718,9 @@
 			(((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
 			(((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
 			((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
-#ifdef ATAFB_FALCON
 		((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
 						       ((green & 0xfc00) >> 5) |
 						       ((blue & 0xf800) >> 11));
-#endif
 	}
 	return 0;
 }
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index b066475..42e303f 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1439,6 +1439,7 @@
 #ifdef CONFIG_FB_DEFERRED_IO
 	.fsync =	fb_deferred_io_fsync,
 #endif
+	.llseek =	default_llseek,
 };
 
 struct class *fb_class;
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c
index ecad965..12dec76 100644
--- a/drivers/video/mbx/mbxdebugfs.c
+++ b/drivers/video/mbx/mbxdebugfs.c
@@ -175,36 +175,42 @@
 	.read = sysconf_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations clock_fops = {
 	.read = clock_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations display_fops = {
 	.read = display_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations gsctl_fops = {
 	.read = gsctl_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations sdram_fops = {
 	.read = sdram_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations misc_fops = {
 	.read = misc_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
index f6fdc20..fed2a72 100644
--- a/drivers/video/omap2/vram.c
+++ b/drivers/video/omap2/vram.c
@@ -554,12 +554,8 @@
 	size = PAGE_ALIGN(size);
 
 	if (paddr) {
-		struct memblock_property res;
-
-		res.base = paddr;
-		res.size = size;
-		if ((paddr & ~PAGE_MASK) || memblock_find(&res) ||
-		    res.base != paddr || res.size != size) {
+		if ((paddr & ~PAGE_MASK) ||
+		    !memblock_is_region_memory(paddr, size)) {
 			pr_err("Illegal SDRAM region for VRAM\n");
 			return;
 		}
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 5d786bd..cea6403 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -298,8 +298,8 @@
 	 * Set bit to enable graphics DMA.
 	 */
 	x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
-	x |= fbi->active ? 0x00000100 : 0;
-	fbi->active = 0;
+	x &= ~CFG_GRA_ENA_MASK;
+	x |= fbi->active ? CFG_GRA_ENA(1) : CFG_GRA_ENA(0);
 
 	/*
 	 * If we are in a pseudo-color mode, we need to enable
@@ -784,12 +784,53 @@
 	return ret;
 }
 
+static int __devexit pxa168fb_remove(struct platform_device *pdev)
+{
+	struct pxa168fb_info *fbi = platform_get_drvdata(pdev);
+	struct fb_info *info;
+	int irq;
+	unsigned int data;
+
+	if (!fbi)
+		return 0;
+
+	/* disable DMA transfer */
+	data = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
+	data &= ~CFG_GRA_ENA_MASK;
+	writel(data, fbi->reg_base + LCD_SPU_DMA_CTRL0);
+
+	info = fbi->info;
+
+	unregister_framebuffer(info);
+
+	writel(GRA_FRAME_IRQ0_ENA(0x0), fbi->reg_base + SPU_IRQ_ENA);
+
+	if (info->cmap.len)
+		fb_dealloc_cmap(&info->cmap);
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, fbi);
+
+	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+				info->screen_base, info->fix.smem_start);
+
+	iounmap(fbi->reg_base);
+
+	clk_disable(fbi->clk);
+	clk_put(fbi->clk);
+
+	framebuffer_release(info);
+
+	return 0;
+}
+
 static struct platform_driver pxa168fb_driver = {
 	.driver		= {
 		.name	= "pxa168-fb",
 		.owner	= THIS_MODULE,
 	},
 	.probe		= pxa168fb_probe,
+	.remove		= __devexit_p(pxa168fb_remove),
 };
 
 static int __init pxa168fb_init(void)
@@ -798,6 +839,12 @@
 }
 module_init(pxa168fb_init);
 
+static void __exit pxa168fb_exit(void)
+{
+	platform_driver_unregister(&pxa168fb_driver);
+}
+module_exit(pxa168fb_exit);
+
 MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
 	      "Green Wan <gwan@marvell.com>");
 MODULE_DESCRIPTION("Framebuffer driver for PXA168/910");
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index fc32c32..f5a39f5 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -28,7 +28,7 @@
 
 #define Q40_PHYS_SCREEN_ADDR 0xFE800000
 
-static struct fb_fix_screeninfo q40fb_fix __initdata = {
+static struct fb_fix_screeninfo q40fb_fix __devinitdata = {
 	.id		= "Q40",
 	.smem_len	= 1024*1024,
 	.type		= FB_TYPE_PACKED_PIXELS,
@@ -37,7 +37,7 @@
 	.accel		= FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo q40fb_var __initdata = {
+static struct fb_var_screeninfo q40fb_var __devinitdata = {
 	.xres		= 1024,
 	.yres		= 512,
 	.xres_virtual	= 1024,
diff --git a/drivers/vlynq/vlynq.c b/drivers/vlynq/vlynq.c
index f2d9e66..f885c86 100644
--- a/drivers/vlynq/vlynq.c
+++ b/drivers/vlynq/vlynq.c
@@ -31,6 +31,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 
 #include <linux/vlynq.h>
 
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 24efd8e..c356146 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -957,12 +957,32 @@
 	  the Warp platform.
 
 config BOOKE_WDT
-	bool "PowerPC Book-E Watchdog Timer"
+	tristate "PowerPC Book-E Watchdog Timer"
 	depends on BOOKE || 4xx
 	---help---
+	  Watchdog driver for PowerPC Book-E chips, such as the Freescale
+	  MPC85xx SOCs and the IBM PowerPC 440.
+
 	  Please see Documentation/watchdog/watchdog-api.txt for
 	  more information.
 
+config BOOKE_WDT_DEFAULT_TIMEOUT
+	int "PowerPC Book-E Watchdog Timer Default Timeout"
+	depends on BOOKE_WDT
+	default 38 if FSL_BOOKE
+	range 0 63 if FSL_BOOKE
+	default 3 if !FSL_BOOKE
+	range 0 3 if !FSL_BOOKE
+	help
+	  Select the default watchdog timer period to be used by the PowerPC
+	  Book-E watchdog driver.  A watchdog "event" occurs when the bit
+	  position represented by this number transitions from zero to one.
+
+	  For Freescale Book-E processors, this is a number between 0 and 63.
+	  For other Book-E processors, this is a number between 0 and 3.
+
+	  The value can be overidden by the wdt_period command-line parameter.
+
 # PPC64 Architecture
 
 config WATCHDOG_RTAS
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index c764c52..b292217 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -267,6 +267,7 @@
 	.unlocked_ioctl	= ar7_wdt_ioctl,
 	.open		= ar7_wdt_open,
 	.release	= ar7_wdt_release,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice ar7_wdt_miscdev = {
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index 3d49671..d11ffb0 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 Freescale Semiconductor Inc.
+ * Copyright 2005, 2008, 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
@@ -33,14 +33,8 @@
  * occur, and the final time the board will reset.
  */
 
-#ifdef	CONFIG_FSL_BOOKE
-#define WDT_PERIOD_DEFAULT 38	/* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */
-#else
-#define WDT_PERIOD_DEFAULT 3	/* Refer to the PPC40x and PPC4xx manuals */
-#endif				/* for timing information */
-
 u32 booke_wdt_enabled;
-u32 booke_wdt_period = WDT_PERIOD_DEFAULT;
+u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT;
 
 #ifdef	CONFIG_FSL_BOOKE
 #define WDTP(x)		((((x)&0x3)<<30)|(((x)&0x3c)<<15))
@@ -114,6 +108,27 @@
 	mtspr(SPRN_TCR, val);
 }
 
+/**
+ * booke_wdt_disable - disable the watchdog on the given CPU
+ *
+ * This function is called on each CPU.  It disables the watchdog on that CPU.
+ *
+ * TCR[WRC] cannot be changed once it has been set to non-zero, but we can
+ * effectively disable the watchdog by setting its period to the maximum value.
+ */
+static void __booke_wdt_disable(void *data)
+{
+	u32 val;
+
+	val = mfspr(SPRN_TCR);
+	val &= ~(TCR_WIE | WDTP_MASK);
+	mtspr(SPRN_TCR, val);
+
+	/* clear status to make sure nothing is pending */
+	__booke_wdt_ping(NULL);
+
+}
+
 static ssize_t booke_wdt_write(struct file *file, const char __user *buf,
 				size_t count, loff_t *ppos)
 {
@@ -193,12 +208,21 @@
 	return nonseekable_open(inode, file);
 }
 
+static int booke_wdt_release(struct inode *inode, struct file *file)
+{
+	on_each_cpu(__booke_wdt_disable, NULL, 0);
+	booke_wdt_enabled = 0;
+
+	return 0;
+}
+
 static const struct file_operations booke_wdt_fops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
 	.write = booke_wdt_write,
 	.unlocked_ioctl = booke_wdt_ioctl,
 	.open = booke_wdt_open,
+	.release = booke_wdt_release,
 };
 
 static struct miscdevice booke_wdt_miscdev = {
@@ -237,4 +261,9 @@
 
 	return ret;
 }
-device_initcall(booke_wdt_init);
+
+module_init(booke_wdt_init);
+module_exit(booke_wdt_exit);
+
+MODULE_DESCRIPTION("PowerPC Book-E watchdog driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 566343b..eca855a 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -25,7 +25,7 @@
 #include <linux/ioport.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -89,6 +89,7 @@
 	} devs[WD_NUMDEVS];
 };
 
+static DEFINE_MUTEX(cpwd_mutex);
 static struct cpwd *cpwd_device;
 
 /* Sun uses Altera PLD EPF8820ATC144-4
@@ -368,7 +369,7 @@
 {
 	struct cpwd *p = cpwd_device;
 
-	lock_kernel();
+	mutex_lock(&cpwd_mutex);
 	switch (iminor(inode)) {
 	case WD0_MINOR:
 	case WD1_MINOR:
@@ -376,7 +377,7 @@
 		break;
 
 	default:
-		unlock_kernel();
+		mutex_unlock(&cpwd_mutex);
 		return -ENODEV;
 	}
 
@@ -386,13 +387,13 @@
 				IRQF_SHARED, DRIVER_NAME, p)) {
 			printk(KERN_ERR PFX "Cannot register IRQ %d\n",
 				p->irq);
-			unlock_kernel();
+			mutex_unlock(&cpwd_mutex);
 			return -EBUSY;
 		}
 		p->initialized = true;
 	}
 
-	unlock_kernel();
+	mutex_unlock(&cpwd_mutex);
 
 	return nonseekable_open(inode, f);
 }
@@ -482,9 +483,9 @@
 	case WIOCSTART:
 	case WIOCSTOP:
 	case WIOCGSTAT:
-		lock_kernel();
+		mutex_lock(&cpwd_mutex);
 		rval = cpwd_ioctl(file, cmd, arg);
-		unlock_kernel();
+		mutex_unlock(&cpwd_mutex);
 		break;
 
 	/* everything else is handled by the generic compat layer */
@@ -524,6 +525,7 @@
 	.write =		cpwd_write,
 	.read =			cpwd_read,
 	.release =		cpwd_release,
+	.llseek =		no_llseek,
 };
 
 static int __devinit cpwd_probe(struct platform_device *op,
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
index 59359c9..726b7df 100644
--- a/drivers/watchdog/ep93xx_wdt.c
+++ b/drivers/watchdog/ep93xx_wdt.c
@@ -188,6 +188,7 @@
 	.unlocked_ioctl	= ep93xx_wdt_ioctl,
 	.open		= ep93xx_wdt_open,
 	.release	= ep93xx_wdt_release,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice ep93xx_wdt_miscdev = {
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
index 2a41017..9099238 100644
--- a/drivers/watchdog/octeon-wdt-main.c
+++ b/drivers/watchdog/octeon-wdt-main.c
@@ -64,6 +64,7 @@
 #include <linux/cpu.h>
 #include <linux/smp.h>
 #include <linux/fs.h>
+#include <linux/irq.h>
 
 #include <asm/mipsregs.h>
 #include <asm/uasm.h>
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 76b58ab..81e3d61 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -258,6 +258,7 @@
 	.unlocked_ioctl = omap_wdt_ioctl,
 	.open = omap_wdt_open,
 	.release = omap_wdt_release,
+	.llseek = no_llseek,
 };
 
 static int __devinit omap_wdt_probe(struct platform_device *pdev)
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 13365ba..7d24b0d 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -338,30 +338,29 @@
 
 static int find_unbound_irq(void)
 {
-	int irq;
-	struct irq_desc *desc;
+	struct irq_data *data;
+	int irq, res;
 
 	for (irq = 0; irq < nr_irqs; irq++) {
-		desc = irq_to_desc(irq);
+		data = irq_get_irq_data(irq);
 		/* only 0->15 have init'd desc; handle irq > 16 */
-		if (desc == NULL)
+		if (!data)
 			break;
-		if (desc->chip == &no_irq_chip)
+		if (data->chip == &no_irq_chip)
 			break;
-		if (desc->chip != &xen_dynamic_chip)
+		if (data->chip != &xen_dynamic_chip)
 			continue;
 		if (irq_info[irq].type == IRQT_UNBOUND)
-			break;
+			return irq;
 	}
 
 	if (irq == nr_irqs)
 		panic("No available IRQ to bind to: increase nr_irqs!\n");
 
-	desc = irq_to_desc_alloc_node(irq, 0);
-	if (WARN_ON(desc == NULL))
-		return -1;
+	res = irq_alloc_desc_at(irq, 0);
 
-	dynamic_irq_init_keep_chip_data(irq);
+	if (WARN_ON(res != irq))
+		return -1;
 
 	return irq;
 }
@@ -495,7 +494,7 @@
 	if (irq_info[irq].type != IRQT_UNBOUND) {
 		irq_info[irq] = mk_unbound_info();
 
-		dynamic_irq_cleanup(irq);
+		irq_free_desc(irq);
 	}
 
 	spin_unlock(&irq_mapping_update_lock);
diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c
index 66e185c..fec6ba3 100644
--- a/drivers/xen/evtchn.c
+++ b/drivers/xen/evtchn.c
@@ -467,6 +467,7 @@
 	.fasync  = evtchn_fasync,
 	.open    = evtchn_open,
 	.release = evtchn_release,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice evtchn_miscdev = {
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 29bac51..d409495 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -755,7 +755,10 @@
 {
 	int ret = 0;
 
-	blocking_notifier_chain_register(&xenstore_chain, nb);
+	if (xenstored_ready > 0)
+		ret = nb->notifier_call(nb, 0, NULL);
+	else
+		blocking_notifier_chain_register(&xenstore_chain, nb);
 
 	return ret;
 }
@@ -769,7 +772,7 @@
 
 void xenbus_probe(struct work_struct *unused)
 {
-	BUG_ON((xenstored_ready <= 0));
+	xenstored_ready = 1;
 
 	/* Enumerate devices in xenstore and watch for changes. */
 	xenbus_probe_devices(&xenbus_frontend);
@@ -835,8 +838,8 @@
 			xen_store_evtchn = xen_start_info->store_evtchn;
 			xen_store_mfn = xen_start_info->store_mfn;
 			xen_store_interface = mfn_to_virt(xen_store_mfn);
+			xenstored_ready = 1;
 		}
-		xenstored_ready = 1;
 	}
 
 	/* Initialize the interface to xenstore. */
diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c
index 78bfab0..bd96340 100644
--- a/drivers/xen/xenfs/super.c
+++ b/drivers/xen/xenfs/super.c
@@ -35,6 +35,7 @@
 
 static const struct file_operations capabilities_file_ops = {
 	.read = capabilities_read,
+	.llseek = default_llseek,
 };
 
 static int xenfs_fill_super(struct super_block *sb, void *data, int silent)
diff --git a/drivers/xen/xenfs/xenbus.c b/drivers/xen/xenfs/xenbus.c
index 3b39c37..1c12360 100644
--- a/drivers/xen/xenfs/xenbus.c
+++ b/drivers/xen/xenfs/xenbus.c
@@ -594,4 +594,5 @@
 	.open = xenbus_file_open,
 	.release = xenbus_file_release,
 	.poll = xenbus_file_poll,
+	.llseek = no_llseek,
 };
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index 6455f3a..e0c2807 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -142,6 +142,7 @@
 	error = device_register(&bus->dev);
 	if (error) {
 		pr_err("Zorro: Error registering zorro_bus\n");
+		put_device(&bus->dev);
 		kfree(bus);
 		return error;
 	}
@@ -175,6 +176,7 @@
 		if (error) {
 			dev_err(&bus->dev, "Error registering device %s\n",
 				z->name);
+			put_device(&z->dev);
 			continue;
 		}
 		error = zorro_create_sysfs_dev_files(z);
diff --git a/firmware/Makefile b/firmware/Makefile
index 9c2d194..74d47cd 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -32,12 +32,14 @@
 					 adaptec/starfire_tx.bin
 fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin
 fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw
-fw-shipped-$(CONFIG_BNX2X) += bnx2x-e1-5.2.13.0.fw bnx2x-e1h-5.2.13.0.fw
-fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-5.0.0.j15.fw \
-			     bnx2/bnx2-rv2p-09-5.0.0.j10.fw \
-			     bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw \
-			     bnx2/bnx2-mips-06-5.0.0.j6.fw \
-			     bnx2/bnx2-rv2p-06-5.0.0.j3.fw
+fw-shipped-$(CONFIG_BNX2X) += bnx2x/bnx2x-e1-6.0.34.0.fw \
+			      bnx2x/bnx2x-e1h-6.0.34.0.fw \
+			      bnx2x/bnx2x-e2-6.0.34.0.fw
+fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-6.0.17.fw \
+			     bnx2/bnx2-rv2p-09-6.0.17.fw \
+			     bnx2/bnx2-rv2p-09ax-6.0.17.fw \
+			     bnx2/bnx2-mips-06-6.0.15.fw \
+			     bnx2/bnx2-rv2p-06-6.0.15.fw
 fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin
 fw-shipped-$(CONFIG_COMPUTONE) += intelliport2.bin
 fw-shipped-$(CONFIG_CHELSIO_T3) += cxgb3/t3b_psram-1.1.0.bin \
diff --git a/firmware/WHENCE b/firmware/WHENCE
index ae5f8a4..f22c4df 100644
--- a/firmware/WHENCE
+++ b/firmware/WHENCE
@@ -679,8 +679,8 @@
 
 Driver: bnx2x: Broadcom Everest
 
-File: bnx2x-e1-5.2.13.0.fw
-File: bnx2x-e1h-5.2.13.0.fw
+File: bnx2x/bnx2x-e1-5.2.13.0.fw
+File: bnx2x/bnx2x-e1h-5.2.13.0.fw
 
 License:
   Copyright (c) 2007-2010 Broadcom Corporation
@@ -699,15 +699,16 @@
 
 Driver: BNX2 - Broadcom NetXtremeII
 
-File: bnx2/bnx2-mips-06-4.6.16.fw
-File: bnx2/bnx2-rv2p-06-4.6.16.fw
-File: bnx2/bnx2-mips-09-4.6.17.fw
-File: bnx2/bnx2-rv2p-09-4.6.15.fw
+File: bnx2/bnx2-mips-06-6.0.15.fw
+File: bnx2/bnx2-rv2p-06-6.0.15.fw
+File: bnx2/bnx2-mips-09-6.0.17.fw
+File: bnx2/bnx2-rv2p-09-6.0.17.fw
+File: bnx2/bnx2-rv2p-09ax-6.0.17.fw
 
 Licence:
 
  This file contains firmware data derived from proprietary unpublished
- source code, Copyright (c) 2004 - 2009 Broadcom Corporation.
+ source code, Copyright (c) 2004 - 2010 Broadcom Corporation.
 
  Permission is hereby granted for the distribution of this firmware data
  in hexadecimal or equivalent format, provided this copyright notice is
diff --git a/firmware/bnx2/bnx2-mips-06-5.0.0.j6.fw.ihex b/firmware/bnx2/bnx2-mips-06-5.0.0.j6.fw.ihex
deleted file mode 100644
index 8d379bf..0000000
--- a/firmware/bnx2/bnx2-mips-06-5.0.0.j6.fw.ihex
+++ /dev/null
@@ -1,5908 +0,0 @@
-:10000000080001100800000000004CC8000000C8F3
-:1000100000000000000000000000000008004CC8C4
-:100020000000001400004D90080000880800000047
-:10003000000058C400004DA408005A40000000848D
-:100040000000A668080058C4000001540000A6EC97
-:10005000080031D808000000000075340000A840F6
-:1000600000000000000000000000000008007534DF
-:100070000000002400011D7408000488080004002A
-:100080000000175C00011D98000000000000000047
-:100090000000000000000000000000000000000060
-:1000A000080000A80800000000003B38000134F4FC
-:1000B0000000000000000000000000000000000040
-:0800C000000000000000000038
-:0800C8000A00004400000000E2
-:1000D000000000000000000D636F6D352E302E30E3
-:1000E0006A36000005000002000000000000000366
-:1000F00000000014000000320000000300000000B7
-:1001000000000000000000000000000000000000EF
-:1001100000000010000001360000EA600000000549
-:1001200000000000000000000000000000000008C7
-:1001300000000000000000000000000000000000BF
-:1001400000000000000000000000000000000000AF
-:10015000000000000000000000000000000000009F
-:10016000000000020000000000000000000000008D
-:10017000000000000000000000000000000000007F
-:10018000000000000000000000000010000000005F
-:10019000000000000000000000000000000000005F
-:1001A000000000000000000000000000000000004F
-:1001B000000000000000000000000000000000003F
-:1001C000000000000000000000000000000000002F
-:1001D000000000000000000000000000100000030C
-:1001E000000000000000000D0000000D3C020800AF
-:1001F00024424D003C03080024634DFCAC40000049
-:100200000043202B1480FFFD244200043C1D080005
-:1002100037BD7FFC03A0F0213C1008002610011020
-:100220003C1C0800279C4D000E000214000000003A
-:100230000000000D27BDFFE8AFBF0014AFB00010F5
-:100240009742010830437000240220001062000B26
-:10025000286220011440002F0000102124024000D9
-:1002600010620025000000002402600010620026D9
-:10027000000010210A0000948FBF001427500100D5
-:10028000920200091040001A240300013C020800F9
-:100290008C42002010400016000018210E00052B93
-:1002A00000000000960300083C06080094C64DBEFE
-:1002B0008E0400188F8200209605000C00031C009D
-:1002C00000661825AC440000AC450004240400017D
-:1002D000AC400008AC40000CAC400010AC40001436
-:1002E000AC4000180E000550AC43001C0000182163
-:1002F0000A000093006010210E0003BD0000000002
-:100300000A000093000010210E000F810000000081
-:10031000000010218FBF00148FB0001003E0000810
-:1003200027BD001827BDFFE0AFB00010AFBF001819
-:10033000AFB10014275001009203000B2402001AF1
-:10034000961100081462005B00002821322200018F
-:1003500010400008000000008E0200009603001408
-:10036000000211C200021040005A10210A0000DBF6
-:10037000A44300803C0208008C420020104000286A
-:10038000000000000E00052B00000000974201084D
-:100390009743010C8F8500203042003E3063FFFF01
-:1003A0000002140000431025ACA200008F4201009F
-:1003B0003C06080094C64DBEACA20004974301164B
-:1003C0009744010E3C02200000031C003084FFFF14
-:1003D00000641825ACA3000800C230259742011024
-:1003E0009743011224040001000214003063FFFF50
-:1003F00000431025ACA2000C974201143042FFFFCD
-:10040000ACA200108F420118ACA200149342010B61
-:10041000304200FFACA200180E000550ACA6001C34
-:100420003C0208008C420040244200013C010800CC
-:10043000AC2200403C0308008C63004432220002DE
-:1004400032240004246300013C010800AC23004472
-:10045000108000180002282B8F4202B804430008C5
-:100460008E0200203C0208008C4200602442000101
-:100470003C010800AC2200600A0000FB24050001DA
-:100480009603001600002821AF4202808E0200046D
-:10049000A7430284AF4202883C021000AF4202B878
-:1004A0003C0208008C42005C244200013C01080030
-:1004B000AC22005C8FBF00188FB100148FB0001009
-:1004C00000A0102103E0000827BD002027BDFFE0A9
-:1004D000AFB00010AFBF0018AFB10014275001003B
-:1004E0009203000B24020003961100081462006DB1
-:1004F000000020213222000110400008000000000E
-:100500008E02000096030014000211C20002104087
-:10051000005A10210A000142A44300803C02080056
-:100520008C42002010400025000000000E00052B2A
-:1005300000000000974201089743010C8F850020BE
-:100540003042003E3063FFFF0002140000431025DC
-:10055000ACA200008F4201003C06080094C64DBECC
-:10056000ACA20004974301169744010E3C02200000
-:1005700000031C003084FFFF00641825ACA30008B2
-:1005800000C2302597420110974301122404000154
-:10059000000214003063FFFF00431025ACA2000CE2
-:1005A000974201143042FFFFACA20010ACA000142F
-:1005B000ACA000180E000550ACA6001C3C020800C0
-:1005C0008C420040244200013C010800AC22004063
-:1005D0003C0208008C420044322300042442000103
-:1005E0003C010800AC2200441060001A32220002D4
-:1005F0008F4202B8044300088E0200203C0208002B
-:100600008C420060244200013C010800AC220060E2
-:100610000A0001772404000196030016000020213F
-:10062000AF4202808E020004A7430284AF420288D8
-:100630003C021000AF4202B83C0208008C42005C51
-:10064000244200013C010800AC22005C0A00017851
-:100650008FBF001810400013000020218F430104B9
-:100660003C026020AC4300148C420004240301FED1
-:10067000304203FF1443000B000020218F42010091
-:10068000000211C02442FFFC2C420008104000026E
-:100690002403000200031F403C026000AC436914C5
-:1006A000000020218FBF00188FB100148FB0001000
-:1006B0000080102103E0000827BD00208F430100C7
-:1006C0002402010050620003000311C20000000D6B
-:1006D000000311C200021040005A1021A440008003
-:1006E00003E00008000010219362000003E000080E
-:1006F000AF80000003E000080000102103E00008C4
-:1007000000001021240201001482000800000000F3
-:100710003C0208008C4200FC244200013C0108001D
-:10072000AC2200FC0A00019F30A200203C0208001D
-:100730008C420084244200013C010800AC22008469
-:1007400030A200201040000830A300103C02080036
-:100750008C420108244200013C010800AC2201083F
-:1007600003E0000800000000106000080000000026
-:100770003C0208008C420104244200013C010800B4
-:10078000AC22010403E00008000000003C02080065
-:100790008C420100244200013C010800AC2201000F
-:1007A00003E000080000000027BDFFE8AFBF001015
-:1007B0002744010094830008306200041040001BAD
-:1007C000306600028F4202B804410008240500018F
-:1007D0003C0208008C420060244200013C010800F9
-:1007E000AC2200600A0001EB8FBF00108C82002059
-:1007F0009483001600002821AF4202808C820004FE
-:10080000A7430284AF4202883C021000AF4202B804
-:100810003C0208008C42005C244200013C010800BC
-:10082000AC22005C0A0001EB8FBF001010C0000674
-:10083000006028218F4401000E00018F000000009D
-:100840000A0001EA240500018F8200088F43010499
-:1008500050430007000028218F4401000E00018F43
-:10086000000000008F420104AF8200080000282130
-:100870008FBF001000A0102103E0000827BD001862
-:100880003C0208008C420088274301009465000C5C
-:10089000244200013C010800AC2200888C6400184E
-:1008A0000345102190454000AF4400388C62001C85
-:1008B0002403FFF800052E000043102434420004F6
-:1008C000AF42003C3C020005AF4200300000000097
-:1008D0000000000000000000AF450404000000001C
-:1008E00000000000000000003C020006344200014D
-:1008F000AF420030000000000000000000000000D7
-:100900008F420000304200101040FFFD0000102117
-:1009100003E000080000000027BDFFE0AFB20018B0
-:100920003C036010AFBF001CAFB10014AFB00010AB
-:100930008C6450002402FF7F3C1A80000082202437
-:100940003484380C24020037AC6450003C12080098
-:1009500026524D38AF42000824020C80AF420024DA
-:100960003C1B80083C06080024C6062C02401021CF
-:100970002404001C2484FFFFAC4600000481FFFD1A
-:10098000244200043C0208002442016C3C0108009F
-:10099000AC224D403C020800244204043C01080003
-:1009A000AC224D443C020800244207B83C01080038
-:1009B000AC224D883C0208002442025C3C03080043
-:1009C000246306343C040800248406E03C05080047
-:1009D00024A53B503C010800AC224DA03C0208007D
-:1009E000244205F43C010800AC264D843C0108007B
-:1009F000AC254D943C010800AC234D9C3C01080003
-:100A0000AC244DA43C010800AC224DA83C010800D8
-:100A1000AC234D3C3C010800AC204D483C01080093
-:100A2000AC204D4C3C010800AC204D503C0108006E
-:100A3000AC204D543C010800AC204D583C0108004E
-:100A4000AC204D5C3C010800AC204D603C0108002E
-:100A5000AC244D643C010800AC204D683C0108000A
-:100A6000AC204D6C3C010800AC204D703C010800EE
-:100A7000AC204D743C010800AC204D783C010800CE
-:100A8000AC264D7C3C010800AC264D803C010800A2
-:100A9000AC204D8C3C010800AC254D903C01080079
-:100AA000AC234D980E0006BB000000003C02800005
-:100AB000344200708C420000AF8200143C030800F6
-:100AC0008C6300208F820004104300043C028000ED
-:100AD0000E0004F3AF8300043C0280003446007033
-:100AE0003C0308008C6300A03C0208008C4200A478
-:100AF000104300048F8400143C010800AC2300A4C0
-:100B0000A743009E8CCA00003C0308008C6300BC15
-:100B10003C0208008C4200B80144202300641821E4
-:100B2000000040210064202B0048102100441021C7
-:100B30003C010800AC2300BC3C010800AC2200B81A
-:100B40008F510000322200071040FFDCAF8A0014F2
-:100B50008CC600003C0508008CA500BC3C040800C5
-:100B60008C8400B800CA302300A628210000102180
-:100B700000A6302B00822021008620213227000190
-:100B80003C010800AC2500BC3C010800AC2400B8C6
-:100B900010E0001F322200028F420100AF4200200D
-:100BA0008F420104AF4200A89342010B0E0001885E
-:100BB000305000FF2E02001D544000040010108031
-:100BC0000E00018B0A0002C5000000000052102137
-:100BD0008C4200000040F8090000000010400005B1
-:100BE0003C0240008F4301043C026020AC430014EF
-:100BF0003C024000AF4201383C0208008C42003405
-:100C0000244200013C010800AC22003432220002E0
-:100C10001040000E322200048F4201400E00018875
-:100C2000AF4200200E00034B000000003C024000D9
-:100C3000AF4201783C0208008C4200382442000197
-:100C40003C010800AC220038322200041040FF981A
-:100C50003C0280008F4201800E000188AF420020DC
-:100C60008F43018024020F00146200050000000081
-:100C70008F420188A742009C0A0002FA3C02400011
-:100C80009362000024030050304200FF1443000828
-:100C90003C0240000E00032D000000005440000400
-:100CA0003C0240000E000E0D000000003C0240001F
-:100CB000AF4201B83C0208008C42003C24420001D3
-:100CC0003C010800AC22003C0A00027A3C02800091
-:100CD0003C0290003442000100822025AF440020F5
-:100CE0008F4200200440FFFE0000000003E00008E7
-:100CF000000000003C0280003442000100822025F8
-:100D000003E00008AF44002027BDFFE0AFB10014AE
-:100D1000AFB0001000808821AFBF00180E000302A2
-:100D200030B000FF9362007D022020210202802566
-:100D3000A370007D8F7000743C0280000E00030BD6
-:100D400002028024160000098FBF00188F4201F8AC
-:100D50000440FFFE24020002AF5101C0A34201C4BF
-:100D60003C021000AF4201F88FBF00188FB1001491
-:100D70008FB0001003E0000827BD002027BDFFE86A
-:100D8000AFBF0010974201843042020010400005BE
-:100D9000000020210E001042000000000A00034164
-:100DA000240400018F420188044000098FBF001015
-:100DB0008F4201883C03FF00004310243C030400E1
-:100DC00014430003240400019362003E8FBF00100F
-:100DD0000080102103E0000827BD00182402000154
-:100DE000A3600022A76200168F4401400A0003108E
-:100DF0002405000127BDFFE8AFBF0014AFB000100D
-:100E000093620000304400FF3883002038820030B5
-:100E10000003182B0002102B00621824106000033E
-:100E200024020050148200628FBF001493420148D4
-:100E3000304200FF2443FFFF2C6200051040005C9D
-:100E40008FBF0014000310803C03080024634CC8CB
-:100E5000004310218C420000004000080000000008
-:100E60000E0003028F4401408F70000C8F4201443A
-:100E70001602000224020001AF62000C0E00030BF8
-:100E80008F4401408F420144145000048FBF00146E
-:100E90008FB000100A000FB827BD00188F62000C39
-:100EA0000A0003B300000000976200108F43014462
-:100EB0003042FFFF1462000900000000240200011C
-:100EC000A76200108F420140AF4202003C021000B6
-:100ED000AF4202380A0003BA8FBF001497620010B5
-:100EE0000A0003B3000000000E0003028F4401401B
-:100EF000976200128F4301443050FFFF1603000237
-:100F000024020001A76200120E00030B8F4401406F
-:100F10008F420144160200048FBF00148FB00010EE
-:100F20000A00034527BD0018976200120A0003B3A8
-:100F300000000000976200148F4301443042FFFF1D
-:100F4000146200068FBF0014240200018FB000104D
-:100F5000A76200140A0012E227BD0018976200146D
-:100F60000A0003B300000000976200168F4301449B
-:100F70003042FFFF14620006240200018FBF0014FC
-:100F80008FB00010A76200160A000BAA27BD001838
-:100F900097620016144000068FBF00143C02080040
-:100FA0008C420070244200013C010800AC22007019
-:100FB0008FB0001003E0000827BD001827BDFFE830
-:100FC000AFBF0014AFB000108F500100936200005B
-:100FD00093430109304400FF2402001F106200A562
-:100FE0002862002010400018240200382862000AFD
-:100FF0001040000C2402000B286200081040002C56
-:1010000000000000046000E528620002144000288F
-:1010100024020006106200268FBF00140A0004B7E5
-:101020008FB000101062005E2862000B144000DCDC
-:101030008FBF00142402000E106200738FB00010E6
-:101040000A0004B700000000106200C028620039E6
-:101050001040000A2402008024020036106200CAF8
-:1010600028620037104000B424020035106200C12D
-:101070008FBF00140A0004B78FB000101062002B5D
-:101080002862008110400006240200C824020039B2
-:10109000106200B48FBF00140A0004B78FB00010B4
-:1010A000106200998FBF00140A0004B78FB00010BF
-:1010B0003C0208008C420020104000B98FBF001491
-:1010C0000E00052B000000008F4201008F830020DE
-:1010D0009745010C97460108AC6200008F4201045D
-:1010E0003C04080094844DBE00052C00AC62000452
-:1010F0008F4201180006340000C43025AC6200089D
-:101100008F42011C24040001AC62000C9342010ACE
-:1011100000A22825AC650010AC600014AC6000187B
-:10112000AC66001C0A00048D8FBF00143C0208004E
-:101130008C4200201040009A8FBF00140E00052B37
-:1011400000000000974401083C03080094634DBE72
-:101150009745010C000422029746010E8F82002061
-:10116000000426000083202500052C003C0300809D
-:1011700000A6282500832025AC400000AC400004D8
-:10118000AC400008AC40000CAC450010AC40001472
-:10119000AC400018AC44001C0A00048C240400017C
-:1011A0009742010C144000150000000093620005F6
-:1011B0003042001014400011000000000E00030235
-:1011C0000200202193620005020020213442001019
-:1011D0000E00030BA36200059362000024030020AD
-:1011E000304200FF1043006D020020218FBF001429
-:1011F0008FB000100A00105827BD00180000000D25
-:101200000A0004B68FBF00143C0208008C42002084
-:10121000104000638FBF00140E00052B000000007B
-:101220008F4201048F8300209744010C3C05080085
-:1012300094A54DBEAC6200009762002C000424000F
-:101240003042FFFF008220253C02400E00A22825EC
-:10125000AC640004AC600008AC60000CAC60001032
-:10126000AC600014AC600018AC65001C0A00048C73
-:10127000240400010E00030202002021A7600008E0
-:101280000E00030B02002021020020210E0003109B
-:10129000240500013C0208008C4200201040004060
-:1012A0008FBF00140E00052B000000009742010CB8
-:1012B0008F8300203C05080094A54DBE0002140059
-:1012C000AC700000AC620004AC6000088F64004C9D
-:1012D0003C02401F00A22825AC64000C8F62005025
-:1012E00024040001AC6200108F620054AC62001450
-:1012F000AC600018AC65001C8FBF00148FB00010EC
-:101300000A00055027BD0018240200205082002545
-:101310008FB000100E000FA202002021104000200C
-:101320008FBF0014020020218FB000100000282180
-:101330000A00031027BD0018020020218FBF0014EF
-:101340008FB000100A00061827BD00189745010C41
-:10135000020020218FBF00148FB000100A00063851
-:1013600027BD0018020020218FB000100A00065D82
-:1013700027BD00189345010D020020218FB00010F9
-:101380000A0006A727BD0018020020218FBF001405
-:101390008FB000100A00068327BD00188FBF00140D
-:1013A0008FB0001003E0000827BD00188F420278BC
-:1013B0000440FFFE2402000234840080AF44024057
-:1013C000A34202443C02100003E00008AF4202784E
-:1013D0003C04080094844DCA3C0208008C424DD461
-:1013E0003083FFFF000318C000431021AF42003CD0
-:1013F0003C0208008C424DD0AF4200383C02005005
-:1014000034420008AF42003000000000000000003D
-:10141000000000008F420000304200201040FFFD1D
-:10142000000000008F4204003C010800AC224DC0C7
-:101430008F4204043C010800AC224DC43C02002051
-:10144000AF420030000000003C02080094424DC84A
-:101450003C03080094634DCC3C05080094A54DCE98
-:1014600024840001004310213083FFFF3C01080069
-:10147000A4224DC83C010800A4244DCA14650003F1
-:10148000000000003C010800A4204DCA03E0000851
-:10149000000000003C05000A27BDFFE803452821A5
-:1014A0003C04080024844DB0AFBF00100E0005B509
-:1014B0002406000A3C02080094424DB23C03080096
-:1014C00094634DCE3042000F2442000300431804C1
-:1014D00024027FFF0043102B10400002AF83001C4A
-:1014E0000000000D0E0004C2000000003C020800D5
-:1014F00094424DBA8FBF001027BD001803E00008CA
-:10150000A74200A23C02000A0342102194430006B5
-:101510003C02080094424DBA3C010800A4234DB699
-:10152000004310238F83001C0002140000021403E8
-:101530000043102B03E000083842000127BDFFE8FC
-:10154000AFBF00103C02000A034210219442000683
-:101550003C010800A4224DB60E00050F000000005B
-:101560005440FFF93C02000A8FBF001003E000085E
-:1015700027BD001827BDFFE8AFBF00100E00050F04
-:101580000000000010400003000000000E00051DD8
-:10159000000000003C0208008C424DC08FBF0010CC
-:1015A00027430400AF4200383C0208008C424DC47F
-:1015B00027BD0018AF830020AF42003C3C0200056D
-:1015C000AF42003003E00008AF8000188F8200189F
-:1015D0003C0300060002114000431025AF420030DA
-:1015E0000000000000000000000000008F4200002A
-:1015F000304200101040FFFD27420400AF8200205F
-:1016000003E00008AF8000183C0608008CC64DC4FB
-:101610008F8500188F8300203C02080094424DBA49
-:1016200027BDFFE024A5000124630020244200011F
-:1016300024C70020AFB10014AFB00010AFBF001836
-:10164000AF850018AF8300203C010800A4224DBAEA
-:10165000309000FF3C010800AC274DC404C10008D5
-:101660000000882104E00006000000003C020800A1
-:101670008C424DC0244200013C010800AC224DC008
-:101680003C02080094424DBA3C03080094634DC8E4
-:101690000010202B004310262C420001004410258E
-:1016A000144000048F830018240200101462000FFD
-:1016B000000000000E000541241100013C03080059
-:1016C00094634DBA3C02080094424DC81462000372
-:1016D000000000000E0004C200000000160000031D
-:1016E000000000000E00052B000000003C03080075
-:1016F00094634DBE3C02080094424DBC246300013B
-:101700003064FFFF3C010800A4234DBE1482000397
-:10171000000000003C010800A4204DBE120000069D
-:10172000000000003C02080094424DBAA74200A20B
-:101730000A0005A3022010210E00050F0000000082
-:1017400010400004022010210E00051D00000000C2
-:10175000022010218FBF00188FB100148FB000102D
-:1017600003E0000827BD00203084FFFF30A5FFFF05
-:1017700000001821108000070000000030820001E6
-:101780001040000200042042006518210A0005AB49
-:101790000005284003E000080060102110C000068A
-:1017A00024C6FFFF8CA2000024A50004AC82000028
-:1017B0000A0005B52484000403E0000800000000CE
-:1017C00010A0000824A3FFFFAC860000000000006A
-:1017D000000000002402FFFF2463FFFF1462FFFAF1
-:1017E0002484000403E0000800000000240200013B
-:1017F000AF62000CA7620010A7620012A76200147B
-:1018000003E00008A76200163082007F0342102127
-:101810003C08000E004818213C0208008C420020C1
-:1018200027BDFFD82407FF80AFB3001CAFB200185C
-:10183000AFB10014AFB00010AFBF00200080802116
-:1018400030B100FF0087202430D200FF1040002F6D
-:1018500000009821AF44002C906200002403005047
-:10186000304200FF1443000E000000003C0208005C
-:101870008C4200E00202102100471024AF42002CED
-:101880003C0208008C4200E0020210213042007F3E
-:101890000342102100481021944200D43053FFFF2E
-:1018A0000E00052B000000003C02080094424DBED3
-:1018B0008F8300200011340000C2302500122C005C
-:1018C0003C02400000C2302534A50001AC7000008D
-:1018D0008FBF0020AC6000048FB20018AC7300080A
-:1018E0008FB10014AC60000C8FB3001CAC6500100D
-:1018F0008FB00010AC60001424040001AC6000182C
-:1019000027BD00280A000550AC66001C8FBF0020D0
-:101910008FB3001C8FB200188FB100148FB000106D
-:1019200003E0000827BD00289343010F24020010A4
-:101930001062000E2865001110A00007240200129A
-:10194000240200082405003A10620006000030213D
-:1019500003E0000800000000240500351462FFFCCD
-:10196000000030210A0005D0000000008F42007402
-:1019700024420FA003E00008AF62000C27BDFFE87F
-:10198000AFBF00100E000310240500018FBF001030
-:1019900024020001A762001227BD001824020001E2
-:1019A00003E00008A360002227BDFFE0AFB10014F0
-:1019B000AFB00010AFBF001830B1FFFF0E00030240
-:1019C000008080219362003F24030004304200FF26
-:1019D0001443000C02002021122000082402000AF7
-:1019E0000E0005C900000000936200052403FFFEFD
-:1019F00000431024A362000524020012A362003FEA
-:101A0000020020210E00030BA360008116200003BA
-:101A1000020020210E00062D0000000002002021FF
-:101A2000322600FF8FBF00188FB100148FB0001056
-:101A3000240500380A0005D027BD002027BDFFE09F
-:101A4000AFBF001CAFB20018AFB10014AFB00010B0
-:101A50000E000302008080210E0005C90000000076
-:101A60009362003F24120018305100FF123200032D
-:101A70000200202124020012A362003F93620005AD
-:101A80002403FFFE004310240E00030BA362000595
-:101A9000020020212405002016320007000030211A
-:101AA0008FBF001C8FB200188FB100148FB00010D0
-:101AB0000A00031027BD00208FBF001C8FB2001842
-:101AC0008FB100148FB00010240500390A0005D032
-:101AD00027BD002027BDFFE8AFB00010AFBF001446
-:101AE0009742010C2405003600808021144000102C
-:101AF000304600FF0E000302000000002402001226
-:101B0000A362003F93620005344200100E0005C935
-:101B1000A36200050E00030B020020210200202119
-:101B20000E000310240500200A00069C000000009F
-:101B30000E0005D0000000000E000302020020216C
-:101B4000936200232403FF9F0200202100431024FE
-:101B50008FBF00148FB00010A36200230A00030B94
-:101B600027BD001827BDFFE0AFBF0018AFB10014BC
-:101B7000AFB0001030B100FF0E00030200808021E2
-:101B8000240200120E0005C9A362003F0E00030BE1
-:101B90000200202102002021022030218FBF0018E6
-:101BA0008FB100148FB00010240500350A0005D055
-:101BB00027BD0020A380002C03E00008A380002D97
-:101BC0008F4202780440FFFE8F820034AF42024011
-:101BD00024020002A34202443C02100003E0000879
-:101BE000AF4202783C0360008C625400304200082F
-:101BF0001440FFFD000000008C625408AF82000C0E
-:101C000024020052AC605408AC645430AC625434CA
-:101C10002402000803E00008AC6254003C026000AB
-:101C20008C42540030420008104000053C03600024
-:101C30008C625400304200081440FFFD0000000098
-:101C40008F83000C3C02600003E00008AC435408A2
-:101C500090A3000024020005008040213063003F73
-:101C600000004821146200050000502190A2001CD1
-:101C700094A3001E304900FF306AFFFFAD00000C46
-:101C8000AD000010AD000024950200148D05001C6D
-:101C90008D0400183042FFFF00491023000211009C
-:101CA000000237C3004038210086202300A2102BF9
-:101CB0000082202300A72823AD05001CAD040018D6
-:101CC000A5090014A5090020A50A001603E00008D4
-:101CD000A50A00228F4201F80440FFFE2402000200
-:101CE000AF4401C0A34201C43C02100003E000085D
-:101CF000AF4201F83C0208008C4200B427BDFFE867
-:101D0000AFBF001424420001AFB000103C01080036
-:101D1000AC2200B48F4300243C02001F30AA00FF15
-:101D20003442FF8030D800FF006280240080F82118
-:101D300030EF00FF1158003B01405821240CFF8078
-:101D40003C19000A3163007F000310C000031940F2
-:101D5000006218213C0208008C4200DC256800016A
-:101D6000310D007F03E21021004310213043007F3A
-:101D700003431821004C102400794821AF4200246D
-:101D80008D220024016C1824006C7026AD22000CFA
-:101D90008D220024310800FFAD220010952200148E
-:101DA000952300208D27001C3042FFFF3063FFFF8A
-:101DB0008D2600180043102300021100000227C3E3
-:101DC0000040282100C4302300E2102B00C2302341
-:101DD00000E53823AD27001CAD2600189522002011
-:101DE000A522001495220022154B000AA5220016F8
-:101DF0008D2300248D2200082546000131450080F6
-:101E00001462000430C4007F108F000238AA0080E2
-:101E100000C0502151AF000131C800FF1518FFC9A3
-:101E2000010058218F8400343082007F0342182142
-:101E30003C02000A006218212402FF800082202454
-:101E4000AF440024A06A0079A06A00838C6200502D
-:101E50008F840034AC6200708C6500743C027FFF9C
-:101E60003442FFFF00A228240E000703AC65007473
-:101E7000AF5000248FBF00148FB0001003E00008A3
-:101E800027BD001827BDFFC0AFBE0038AFB7003474
-:101E9000AFB5002CAFB20020AFB1001CAFB000183E
-:101EA000AFBF003CAFB60030AFB40028AFB30024E2
-:101EB0008F4500248F4600288F43002C3C02001FD2
-:101EC0003442FF800062182400C230240080A82120
-:101ED000AFA3001400A2F0240E0006C7AFA60010A6
-:101EE0003C0208008C4200E02410FF80036088213F
-:101EF00002A2102100501024AF4200243C0208002E
-:101F00008C4200E002A210213042007F03421821DF
-:101F10003C02000A00629021924200D29363008446
-:101F2000305700FF306300FF2402000110620034CC
-:101F30000360202124020002146200360000000029
-:101F40000E0012AE024028219223008392220083C9
-:101F50003063007F3042007F000210C00003194050
-:101F6000006218213C0208008C4200DC02A2102111
-:101F70000043382100F01024AF4200289225007859
-:101F80009224008330E2007F034218213C02000CBF
-:101F900014850007006280212402FFFFA24200F1A5
-:101FA0002402FFFFA64200F20A0007BF2402FFFF3F
-:101FB00096020020A24200F196020022A64200F200
-:101FC0008E020024AE4200F492220083A24200F06E
-:101FD0008E4200C8AE4200FC8E4200C4AE4200F801
-:101FE0008E220050AE4201008E4200CCAE4201046F
-:101FF000922200853042003F0A00081A3442004015
-:102000000E0012D102402821922200850A00081AEF
-:102010003042003F936200852403FFDF3042003FDF
-:10202000A36200859362008500431024A3620085AB
-:102030009363008393620078307400FF304200FFA6
-:1020400010540036240AFF803C0C000C3283007FC1
-:10205000000310C000031940006218213C02080070
-:102060008C4200DC268800013109007F02A2102189
-:102070000043382130E2007F0342182100EA102497
-:10208000AF420028006C80218E020024028A1824AE
-:10209000006A5826AE02000C8E020024310800FFB0
-:1020A000AE02001096020014960300208E07001C5A
-:1020B0003042FFFF3063FFFF8E06001800431023FD
-:1020C00000021100000227C30040282100C4302371
-:1020D00000E2102B00C2302300E53823AE07001CBD
-:1020E000AE06001896020020A602001496020022F6
-:1020F000A602001692220079304200FF1054000719
-:102100000000000051370001316800FF9222007882
-:10211000304200FF1448FFCD0100A021922200832D
-:10212000A22200798E2200500A00087AAE220070A6
-:10213000A22200858E22004C2405FF80AE42010CB5
-:102140009222008534420020A2220085924200D1D2
-:102150003C0308008C6300DC305400FF3C020800A4
-:102160008C4200E400143140001420C002A3182166
-:1021700000C4202102A21021006438210046102151
-:102180000045182400E52824AF450028AF43002C63
-:102190003042007F924400D030E3007F0342282188
-:1021A000034318213C02000C006280213C02000E17
-:1021B000309600FF00A298211296002A000000002D
-:1021C0008E02000C02002021026028211040002510
-:1021D000261000280E0006E2000000009262000DAA
-:1021E00026830001307400FF3042007FA262000DA0
-:1021F0002404FF801697FFF0267300203C0208009D
-:102200008C4200DC0000A02102A210210044102416
-:10221000AF4200283C0208008C4200E43C03080066
-:102220008C6300DC02A2102100441024AF42002C79
-:102230003C0208008C4200E402A318213063007FB6
-:1022400002A210213042007F0342202103431821C3
-:102250003C02000C006280213C02000E0A00083C97
-:10226000008298218E4200D8AE2200508E4200D8C3
-:10227000AE22007092250083924600D19223008303
-:10228000924400D12402FF8000A228243063007F02
-:10229000308400FF00A628250064182A1060000280
-:1022A00030A500FF38A50080A2250083A225007973
-:1022B0000E0006D5000000009222007E02A0202120
-:1022C000A222007A8E2300743C027FFF3442FFFF7B
-:1022D000006218240E000703AE2300748FA20010C2
-:1022E000AF5E00248FBF003CAF4200288FBE003895
-:1022F0008FA200148FB700348FB600308FB5002C3A
-:102300008FB400288FB300248FB200208FB1001C3F
-:102310008FB0001827BD004003E00008AF42002C3A
-:1023200090A2000024420001A0A200003C0308008B
-:102330008C6300F4304200FF1443000F0080302112
-:10234000A0A000003C0208008C4200E48F8400340E
-:10235000008220213082007F034218213C02000CC1
-:10236000006218212402FF8000822024ACC30000F8
-:1023700003E00008AF4400288C82000024420020C3
-:1023800003E00008AC82000094C200003C08080092
-:10239000950800CA30E7FFFF0080482101021021A4
-:1023A000A4C2000094C200003042FFFF00E2102BE4
-:1023B00054400001A4C7000094A200003C030800A0
-:1023C0008C6300CC24420001A4A2000094A200006F
-:1023D0003042FFFF544300078F8600280107102B6F
-:1023E000A4A000005440000101003821A4C700004F
-:1023F0008F8600288CC4001CAF44003C94A20000CF
-:102400008F43003C3042FFFF000210C000621821E1
-:10241000AF43003C8F42003C008220231880000420
-:10242000000000008CC200180A0008DB24420001F2
-:102430008CC20018AF4200383C02005034420010F9
-:10244000AF4200300000000000000000000000006B
-:102450008F420000304200201040FFFD00000000CD
-:102460008F420404AD2200048F420400AD2200001C
-:102470003C020020AF42003003E0000800000000F2
-:1024800027BDFFE0AFB20018AFB10014AFB000102D
-:10249000AFBF001C94C2000000C080213C120800A5
-:1024A000965200C624420001A602000096030000D6
-:1024B00094E2000000E03021144300058FB10030A9
-:1024C0000E0008B0024038210A00090D000000008B
-:1024D0008C8300048C8200042442004004610007C5
-:1024E000AC8200048C820004044000040000000060
-:1024F0008C82000024420001AC82000096020000A1
-:102500003042FFFF50520001A6000000962200005A
-:1025100024420001A62200008F820028962300009A
-:1025200094420016144300048FBF001C24020001D3
-:10253000A62200008FBF001C8FB200188FB10014BC
-:102540008FB0001003E0000827BD00208F8900280D
-:1025500027BDFFE0AFBF00188D22002827480400E8
-:1025600030E700FFAF4200388D22002CAF880030EA
-:10257000AF42003C3C020005AF42003000000000CA
-:10258000000000000000000000000000000000004B
-:10259000000000008C82000C8C82000CAD02000058
-:1025A0008C820010AD0200048C820018AD0200087D
-:1025B0008C82001CAD02000C8CA20014AD02001035
-:1025C0008C820020AD02001490820005304200FF92
-:1025D00000021200AD0200188CA20018AD02001C0F
-:1025E0008CA2000CAD0200208CA20010AD020024D1
-:1025F0008CA2001CAD0200288CA20020AD02002C91
-:10260000AD060030AD000034978300263402FFFF92
-:1026100014620002006020213404FFFF10E000116A
-:10262000AD040038952300369524003624020001BD
-:102630003063FFFF000318C2006918219065004055
-:10264000308400070082100400451025A06200407D
-:102650008F820028944200563042FFFF0A0009741E
-:10266000AD02003C9523003695240036240200017B
-:102670003063FFFF000318C2006918219065004015
-:102680003084000700821004000210270045102447
-:10269000A0620040AD00003C00000000000000000F
-:1026A000000000003C02000634420040AF4200300F
-:1026B0000000000000000000000000008F42000049
-:1026C000304200101040FFFD8F860028AF88003098
-:1026D00024C2005624C7003C24C4002824C500326C
-:1026E00024C600360E0008EEAFA200108FBF0018FF
-:1026F00003E0000827BD00208F8300243C0608006B
-:102700008CC600E88F82003430633FFF00031980DD
-:1027100000461021004310212403FF803046007F33
-:1027200000431024AF420028034618213C02000C4D
-:102730000062302190C2000D30A500FF000038215A
-:1027400034420010A0C2000D8F8900288F8A002417
-:1027500095230036000A138230480003240200014A
-:10276000A4C3000E1102000B290200021040000554
-:10277000240200021100000C240300010A0009B821
-:102780000000182111020006000000000A0009B82C
-:10279000000018218CC2002C0A0009B82443000153
-:1027A0008CC20014244300018CC200180043102B7B
-:1027B00050400009240700012402002714A200034E
-:1027C000000000000A0009C4240700019522003E11
-:1027D00024420001A522003E000A13823043000378
-:1027E0002C620002104000090080282114600004BF
-:1027F0000000000094C200360A0009D43046FFFFF2
-:102800008CC600380A0009D400802821000030213D
-:102810003C04080024844DD80A000921000000006F
-:10282000274901008D22000C95230006012020215C
-:10283000000216023046003F3063FFFF24020027EB
-:1028400000C0282128C7002810C2000EAF83002432
-:1028500010E00008240200312402002110C2000907
-:102860002402002510C200079382002D0A0009F3FC
-:102870000000000010C200059382002D0A0009F339
-:10288000000000000A00098C000000000A0006BEDB
-:102890000000000095230006912400058D25000C02
-:1028A0008D2600108D2700188D28001C8D290020F2
-:1028B000244200013C010800A4234DDE3C01080035
-:1028C000A0244DDD3C010800AC254DE43C0108008E
-:1028D000AC264DE83C010800AC274DF03C01080057
-:1028E000AC284DF43C010800AC294DF803E0000889
-:1028F000A382002D8F87002827BDFFC0AFB300340F
-:10290000AFB20030AFB1002CAFB00028AFBF00387D
-:102910003C0208008C4200D094E3003030B0FFFF4E
-:10292000005010073045FFFF3063FFFF00C09821C3
-:10293000A7A200103C110800963100C614A300069F
-:102940003092FFFF8CE2002424420030AF42003C72
-:102950000A000A2C8CE2002094E200323042FFFF91
-:1029600054A2000827A400188CE2002C2442003056
-:10297000AF42003C8CE20028AF4200380A000A3A1D
-:102980008F84002827A5001027A6002002203821C8
-:102990000E0008B0A7A000208FA20018244200302B
-:1029A000AF4200388FA2001CAF42003C8F84002849
-:1029B0003C020005AF4200309482003427430400FB
-:1029C0003042FFFF0202102B14400007AF8300309B
-:1029D0009482005494830034020210210043102397
-:1029E0000A000A4E3043FFFF94830054948200345F
-:1029F0000223182100501023006218233063FFFFC8
-:102A0000948200163042FFFF1443000300000000D0
-:102A10000A000A5C24030001948200163042FFFF82
-:102A20000043102B104000058F8200309482001666
-:102A3000006210233043FFFF8F820030AC53000050
-:102A4000AC400004AC520008AC43000C3C02000651
-:102A500034420010AF4200300000000000000000CF
-:102A6000000000008F420000304200101040FFFDC7
-:102A7000001018C20064182190650040320400075D
-:102A8000240200018FBF00388FB300348FB20030B2
-:102A90008FB1002C8FB00028008210040045102553
-:102AA00027BD004003E00008A062004027BDFFA84A
-:102AB000AFB60050AFB5004CAFB40048AFB3004460
-:102AC000AFB1003CAFBF0054AFB20040AFB0003870
-:102AD0008C9000003C0208008C4200E88F86003495
-:102AE000960300022413FF8000C2302130633FFFB1
-:102AF0000003198000C3382100F3102490B20000B5
-:102B0000AF42002C9203000230E2007F03423021EA
-:102B10003C02000E00C28821306300C02402004045
-:102B20000080A82100A0B021146200260000A0218E
-:102B30008E3400388E220018144000022402000156
-:102B4000AE2200189202000D304200201440001501
-:102B50008F8200343C0308008C6300DC001238C014
-:102B6000001231400043102100C7302100463821B7
-:102B700030E300073C02008030E6007800C23025D8
-:102B80000343182100F31024AF4208002463090016
-:102B9000AF4608108E2200188C63000800431021F5
-:102BA000AE2200188E22002C8E2300182442000131
-:102BB0000062182B1060003D000000000A000B109E
-:102BC00000000000920300022402FFC00043102412
-:102BD000304200FF1440000524020001AE2200181C
-:102BE000962200360A000AF93054FFFF8E220014A4
-:102BF00024420001AE2200189202000000021600DA
-:102C000000021603044100290000000096020002A1
-:102C100027A4001000802821A7A200169602000217
-:102C200024070001000030213042FFFFAF82002462
-:102C30000E000921AFA0001C960300023C0408000E
-:102C40008C8400E88F82003430633FFF00031980DA
-:102C500000441021004310213043007F3C05000C4C
-:102C60000053102403431821AF42002800651821A7
-:102C70009062000D001221403042007FA062000DE2
-:102C80003C0308008C6300E48F8200340043102171
-:102C90000044382130E2007F03421021004510211A
-:102CA00000F31824AF430028AEA200009222000DCA
-:102CB000304200101040001302A020218F83002812
-:102CC0008EA40000028030219462003E2442FFFF67
-:102CD000A462003E948400029625000E3084FFFF1B
-:102CE0000E000A0B30A5FFFF8F82002894430034AA
-:102CF0009622000E1443000302A0202124020001AA
-:102D0000A382002C02C028210E00089600000000BB
-:102D10008FBF00548FB600508FB5004C8FB4004861
-:102D20008FB300448FB200408FB1003C8FB00038A9
-:102D300003E0000827BD00588F82002827BDFFD080
-:102D4000AFB40028AFB20020AFBF002CAFB3002457
-:102D5000AFB1001CAFB00018904400D0904300D138
-:102D60000000A021309200FFA3A30010306300FFF9
-:102D70008C5100D88C5300DC1072002B240200010F
-:102D80003C0308008C6300E493A400108F8200349D
-:102D90002406FF800004214000431021004410213C
-:102DA0003043007F00461024AF420028034318211F
-:102DB0003C02000C006218218C62000427A400145D
-:102DC00027A5001002228021027010230440001564
-:102DD000AFA300149062000D00C21024304200FF27
-:102DE00014400007020088219062000D3442004028
-:102DF0000E000896A062000D0A000B5593A2001069
-:102E00000E000A79241400018F830028AC7000D8CA
-:102E100093A20010A06200D193A200101452FFD818
-:102E20000000000024020001168200048FBF002C65
-:102E30000E0006BE000000008FBF002C8FB40028DB
-:102E40008FB300248FB200208FB1001C8FB0001808
-:102E500003E0000827BD003027BDFFD8AFB3001C3A
-:102E6000AFB20018AFB10014AFB00010AFBF002078
-:102E70000080982100E0802130B1FFFF0E00052B7B
-:102E800030D200FF00000000000000000000000041
-:102E90008F820020AC510000AC520004AC530008FB
-:102EA000AC40000CAC400010AC400014AC4000182A
-:102EB0003C03080094634DBE02038025AC50001C07
-:102EC00000000000000000000000000024040001D9
-:102ED0008FBF00208FB3001C8FB200188FB1001479
-:102EE0008FB000100A00055027BD002827BDFFE85D
-:102EF000AFB00010AFBF001430A5FFFF30C600FF19
-:102F00000080802124020C80AF42002400000000D9
-:102F100000000000000000000000000000000000B1
-:102F20000E000B64000000003C040800248400E054
-:102F30008C8200002403FF808FBF00140202102146
-:102F400000431024AF4200248C8200003C03000A9E
-:102F5000020280213210007F035010218FB0001038
-:102F60000043102127BD001803E00008AF820028AD
-:102F700027BDFFE8AFBF00108F4401403C030800AD
-:102F80008C6300E02402FF80AF84003400831821AA
-:102F900000621024AF4200243C020008034240219A
-:102FA000950500023063007F3C02000A03431821AC
-:102FB0000062182130A5FFFF3402FFFF000030211E
-:102FC0003C07602010A20006AF8300282402FFFF08
-:102FD000A5020002946500D40E000B8930A5FFFF06
-:102FE0008FBF001024020C8027BD001803E00008EA
-:102FF000AF4200243C020008034240219502000237
-:103000003C0A0800954A00C63046FFFF14C000077E
-:103010003402FFFF8F8200288F8400343C07602039
-:10302000944500D40A000BF230A5FFFF10C2002423
-:103030008F87002894E2005494E400163045FFFF87
-:1030400000A6102300A6182B3089FFFF1060000493
-:103050003044FFFF00C51023012210233044FFFF3E
-:10306000008A102B1040000C012A102324020001BA
-:10307000A50200162402FFFFA502000294E500D479
-:103080008F8400340000302130A5FFFF3C07602012
-:103090000A000B89000000000044102A10400008BC
-:1030A00000000000950200163042000110400004AC
-:1030B000000000009742007E24420014A502001682
-:1030C00003E00008000000008F84002827BDFFE017
-:1030D000AFBF0018948200349483003E1060001A41
-:1030E0003048FFFF9383002C240200011462002764
-:1030F0008FBF00188F820028000818C2310800070F
-:10310000006218212447003A244900542444002036
-:10311000244500302446003490620040304200FFD5
-:103120000102100730420001104000168FBF001846
-:103130000E0008EEAFA900108F82002894420034E0
-:103140000A000C0B3048FFFF948300369482003451
-:103150001043000E8FBF001894820036A482003402
-:1031600094820056A48200548C82002CAC820024ED
-:1031700094820032A48200309482003CA482003AFF
-:103180008FBF00180A000BCB27BD002003E000080A
-:1031900027BD002027BDFFE8AFBF00108F4A010008
-:1031A0003C0508008CA500E03C02080090424DE47C
-:1031B0003C0C0800958C4DDE01452821304B003F2A
-:1031C00030A2007F03424021396900323C02000AEC
-:1031D0003963003F2C630001010240212D290001C9
-:1031E0002402FF8000A2282401234825AF8A00344E
-:1031F00000801821AF4500240000302100802821E4
-:1032000024070001AF8800283C04080024844DD81E
-:10321000AF8C002415200007A380002D240200207D
-:103220005562000F006020213402FFFF5582000C20
-:10323000006020212402002015620005000000002B
-:103240008C6300142402FFFF1062000700000000DE
-:103250000E000921000000000A000C6800000000B8
-:103260000E00098C016028210E000C0000000000F7
-:103270008FBF001024020C8027BD001803E0000857
-:10328000AF4200243C0208008C4200E027BDFFA0B2
-:10329000AFB1003C008210212411FF80AFBE005866
-:1032A000AFB70054AFB20040AFB00038AFBF005C62
-:1032B000AFB60050AFB5004CAFB40048AFB3004458
-:1032C000005110248F4800248F4900288F47002880
-:1032D000AF4200243C0208008C4200E000809021B4
-:1032E00024060006008210213042007F034218218C
-:1032F0003C02000A006280213C02001F3442FF8031
-:1033000000E2382427A40010260500F00122F02452
-:103310000102B8240E0005B5AFA700308FA2001837
-:10332000AE0200C48FA2001CAE0200C88FA200240F
-:10333000AE0200CC93A40010920300D12402FF80BF
-:103340000082102400431025304900FF3083007FA5
-:103350003122007F0062102A10400004000310C0D8
-:1033600001311026304900FF000310C0000319404E
-:10337000006218213C0208008C4200DC920400D25A
-:10338000024210210043102100511024AF420028B6
-:1033900093A300103063007F000310C000031940A6
-:1033A000006218213C0208008C4200DC024210211D
-:1033B000004310213042007F034218213C02000CE0
-:1033C000006240218FA300142402FFFF106200302E
-:1033D000309500FF93A2001195030014304400FFC4
-:1033E0003063FFFF0064182B1060000D0000000028
-:1033F000950400148D07001C8D0600183084FFFF13
-:1034000000442023000421000000102100E43821A2
-:1034100000E4202B00C230210A000CE200C430215D
-:10342000950400148D07001C8D0600183084FFFFE2
-:1034300000822023000421000000102100801821B8
-:1034400000C2302300E4202B00C4302300E33823E3
-:10345000AD07001CAD06001893A20011A5020014D0
-:1034600097A20012A50200168FA20014AD02001050
-:103470008FA20014AD02000C93A20011A50200203F
-:1034800097A20012A50200228FA20014AD02002410
-:103490002406FF80024610243256007FAF420024EB
-:1034A000035618213C02000A006280218E02004C63
-:1034B0008FA200203124007F000428C0AE020050FB
-:1034C0008FA200200004214000852821AE02007058
-:1034D00093A2001001208821A202008393A2001071
-:1034E000A2020079920200853042003FA2020085CC
-:1034F0003C0208008C4200DC0242102100451021F1
-:1035000000461024AF42002C3C0208008C4200E42C
-:103510003C0308008C6300DC0242102100441021AF
-:1035200000461024AF4200283C0208008C4200E410
-:103530000243182100651821024210210044102185
-:103540003042007F3063007F93A5001003422021AA
-:10355000034318213C02000E006240213C02000C93
-:1035600010B1008C008248213233007F16600019B0
-:103570002404FF803C0208008C4200DC024210213F
-:1035800000441024AF42002C3C0208008C4200E4AE
-:103590003C0308008C6300DC02421021004410242C
-:1035A000AF4200283C0208008C4200E4024318218C
-:1035B0003063007F024210213042007F034220210D
-:1035C000034318213C02000E006240213C02000C23
-:1035D000008248219124000D2414FF800000102156
-:1035E00000942025A124000D9504000295050014E7
-:1035F0008D07001C3084FFFF30A5FFFF8D060018EB
-:10360000008520230004210000E4382100C230217D
-:1036100000E4202B00C43021AD07001CAD060018CB
-:1036200095020002A5020014A50000168D020008F4
-:10363000AD0200108D020008AD02000C95020002E0
-:10364000A5020020A50000228D020008AD02002482
-:103650009122000D3042004010400042262200011D
-:103660003C0208008C4200E0A3B300283C10000A92
-:103670000242102100541024AF4200243C020800F2
-:103680008C4200E0A380002C27A4002C02421021D1
-:103690003042007F03421821007018218C6200D84C
-:1036A0008D26000427A50028AFA9002C0046102174
-:1036B000AC6200D80E000A79AF83002893A30028DB
-:1036C0008F8200280E0006BEA04300D10E000C0021
-:1036D0000000000002541024AF4200243C02080005
-:1036E0008C4200DC00132940001320C000A42021DC
-:1036F000024210210044102100541024AF42002C3B
-:103700003C0208008C4200E43C0308008C6300DCAF
-:10371000035630210242102100451021005410248C
-:10372000AF4200283C0208008C4200E4024318210A
-:103730000064182102421021004510213042007F10
-:103740003063007F03422021034318213C02000E16
-:10375000006240213C02000C00D080210082482100
-:10376000262200013043007F14750005304400FF1D
-:103770002403FF800223102400431026304400FF5E
-:1037800093A2001000808821250800281444FF76A9
-:103790002529002093A400108FA300142402FFFF0A
-:1037A0001062000A308900FF248200012483000196
-:1037B0003042007F14550005306900FF2403FF806C
-:1037C0000083102400431026304900FF9202007845
-:1037D000305300FF11330032012088213C020800E1
-:1037E0008C4200DC3225007F000520C00005294006
-:1037F00000A42021024210212406FF800044102151
-:1038000000461024AF42002C3C0308008C6300DC0F
-:103810003C0208008C4200E40243182102421021BD
-:103820000045102100641821004610243063007FF9
-:10383000AF420028034318213C02000E00624021E1
-:103840003C0208008C4200E48D06000C010020219F
-:1038500002421021004510213042007F034218210E
-:103860003C02000C0062482110C0000D01202821FC
-:103870000E0006E2000000002402FF80022218244D
-:1038800026240001006228263082007F14550002A1
-:10389000308300FF30A300FF1473FFD00060882145
-:1038A0008E0300743C027FFF3442FFFF0062182445
-:1038B000AE0300740E00070302402021AF5700241E
-:1038C0008FA20030AF5E00288FBF005C8FBE005813
-:1038D0008FB700548FB600508FB5004C8FB400489E
-:1038E0008FB300448FB200408FB1003C8FB00038DE
-:1038F00027BD006003E00008AF42002C27BDFFD8C1
-:10390000AFB1001CAFBF0020AFB000182751018835
-:10391000922200032408FF803C03000A3047007F06
-:10392000A3A700108F4601803C0208008C4200E0F3
-:10393000AF86003400C2282100A81024AF42002422
-:103940009224000030A2007F034210210043102186
-:10395000AF8200283084007F2402000214820025F8
-:10396000000719403C0208008C4200E400C210210C
-:103970000043282130A2007F0342182100A8102410
-:10398000AF4200283C02000C006218219062000D3A
-:10399000AFA3001400481025A062000D8FA30014EF
-:1039A0009062000D304200405040006A8FBF0020FE
-:1039B0008F860028A380002C27A400148CC200D876
-:1039C0008C63000427A50010004310210E000A7923
-:1039D000ACC200D893A300108F8200280E0006BE50
-:1039E000A04300D10E000C00000000000A000EA34E
-:1039F0008FBF00200E0006C700C020210E0006D594
-:103A0000000000003C0200080342802192230001D4
-:103A10009202007B1443004F8FBF002092220000CF
-:103A20003044007F24020004108200172882000521
-:103A30001040000624020005240200031082000743
-:103A40008FB1001C0A000EA40000000010820012BA
-:103A50008FBF00200A000EA48FB1001C92050083C6
-:103A6000920600788E0700748F84003430A500FF22
-:103A700000073E0230C600FF0E00070B30E7007F54
-:103A80000A000EA38FBF00200E000C6F8F8400343D
-:103A90000A000EA38FBF002024020C80AF42002436
-:103AA0009202003E30420040104000200000000022
-:103AB0009202003E000216000002160304410006B6
-:103AC000000000008F8400340E00063824050093A7
-:103AD0000A000EA38FBF00209202003F24030018AB
-:103AE000304200FF1443000C8F8400342405003959
-:103AF0000E0005D0000030210E0003028F84003438
-:103B000024020012A202003F0E00030B8F84003437
-:103B10000A000EA38FBF0020240500360E0005D03A
-:103B2000000030210A000EA38FBF00200E00030208
-:103B30008F8400349202000534420020A202000566
-:103B40000E00030B8F8400340E0010588F84003455
-:103B50008FBF00208FB1001C8FB0001824020C8092
-:103B600027BD002803E00008AF42002427BDFFE87E
-:103B7000AFB00010AFBF00142743010094620008EB
-:103B8000000214000002140304410002000080211E
-:103B90002410000194620008304200801040001A96
-:103BA00002001021946200083042200010400016EC
-:103BB000020010218C6300183C021C2D344219EDC8
-:103BC000240600061062000F3C0760213C0208003A
-:103BD0008C4200D4104000078F8200288F83002879
-:103BE000906200623042000F34420040A0620062E6
-:103BF0008F8200288F840034944500D40E000B89F6
-:103C000030A5FFFF020010218FBF00148FB00010FD
-:103C100003E0000827BD001827BDFFE0AFB1001486
-:103C2000AFB00010A380002CAFBF00188F4501007B
-:103C30003C0308008C6300E02402FF80AF85003461
-:103C400000A318213064007F03442021006218245F
-:103C50003C02000A00822021AF43002427500100CB
-:103C60008E0200148C8300DCAF84002800431023F4
-:103C700018400004000088218E0200140E000B1C66
-:103C8000AC8200DC9202000B24030002304200FFF1
-:103C90001443002F0000000096020008304300FF8C
-:103CA0002402008214620005240200840E0009D65A
-:103CB000000000000A000F2F00000000146200093D
-:103CC000240200818F8200288F8400343C07602109
-:103CD000944500D49206000530A5FFFF0A000F1E90
-:103CE00030C600FF14620027000000009202000AA4
-:103CF000304300FF3062002010400004306200407A
-:103D00008F8400340A000F1A24060040104000047B
-:103D1000000316008F8400340A000F1A24060041A5
-:103D200000021603044100178F8400342406004269
-:103D30008F8200283C076019944500D430A5FFFF0E
-:103D40000E000B89000000000A000F2F0000000089
-:103D50009202000B24030016304200FF10430006BD
-:103D6000000000009202000B24030017304200FF05
-:103D700014430004000000000E000EA90000000023
-:103D8000004088210E000C00000000009202000A92
-:103D9000304200081040000624020C808F85002865
-:103DA0003C0400080E0012860344202124020C80EB
-:103DB000AF4200248FBF0018022010218FB00010E6
-:103DC0008FB1001403E0000827BD002027BDFFE8E5
-:103DD000AFBF0014AFB000108F5000243C030800A8
-:103DE0008C6300E08F4501002402FF8000A31821AE
-:103DF0003064007F03442021006218243C02000A42
-:103E000000822021AF850034AF43002490820062FD
-:103E1000AF8400283042000F34420050A08200627C
-:103E20003C02001F3442FF800E0006BE02028024C6
-:103E3000AF5000248FBF00148FB0001003E00008C3
-:103E400027BD00183C0208008C4200201040001DD5
-:103E50002745010090A300093C02000803422021ED
-:103E600024020018546200033C0200080A000F708C
-:103E700024020008034220212402001614620005D7
-:103E80002402001724020012A082003F0A000F7AC9
-:103E900094A700085462000694A7000893620005E6
-:103EA0002403FFFE00431024A362000594A700082A
-:103EB00090A6001B8CA4000094A500060A000B64C9
-:103EC00000073C0003E00008000000002744010058
-:103ED00094820008304500FF38A3008238A2008495
-:103EE0002C6300012C4200010062182510600006BE
-:103EF000240200839382002D1040000D000000007A
-:103F00000A000C330000000014A2000524A2FF8068
-:103F10008F4301043C02602003E00008AC4300141E
-:103F2000304200FF2C420002104000032402002215
-:103F30000A000ED40000000014A2000300000000DC
-:103F40000A000F41000000000A000F5F000000009F
-:103F50009363007E9362007A1443000900002021DD
-:103F60009362000024030050304200FF1443000419
-:103F7000240400019362007E24420001A362007EBB
-:103F800003E00008008010218F4201F80440FFFE8A
-:103F900024020002AF4401C0A34201C43C0210004D
-:103FA00003E00008AF4201F827BDFFE8AFBF0010F3
-:103FB0009362003F2403000A304200FF144300468E
-:103FC000000000008F6300548F62004C1062007D7F
-:103FD000036030219362000024030050304200FF50
-:103FE0001443002F000000008F4401403C020800F1
-:103FF0008C4200E02403FF80008210210043102443
-:10400000AF4200243C0208008C4200E08F6500545F
-:104010003C03000A008220213084007F03441021E9
-:1040200000431021AC4501089762003C8F63004CAF
-:104030003042FFFF0002104000621821AF63005CB5
-:104040008F6300548F64004C9762003C0064182317
-:104050003042FFFF00031843000210400043102AC3
-:1040600010400006000000008F6200548F63004C77
-:10407000004310230A000FF0000210439762003C37
-:104080003042FFFF00021040ACC200642402000175
-:10409000A0C0007CA0C2008424020C80AF42002497
-:1040A0000E000FA28F440140104000478FBF001048
-:1040B0008F4301408F4201F80440FFFE24020002BA
-:1040C000AF4301C0A34201C43C021000AF4201F85B
-:1040D0000A0010408FBF00109362003F24030010BD
-:1040E000304200FF14430004000000008F440140F0
-:1040F0000A00102C000028219362003F24030016C0
-:10410000304200FF1443000424020014A362003F65
-:104110000A00103A000000008F62004C8F630050CC
-:1041200000431023044100288FBF001093620081D8
-:1041300024420001A3620081936200812C420004AA
-:1041400014400010000000009362003F24030004AC
-:10415000304200FF14430006000000008F4401407D
-:104160008FBF0010240500930A00063827BD0018F1
-:104170008F440140240500938FBF00100A0006A75A
-:1041800027BD00188F4401400E000302000000000C
-:104190008F6200542442FFFFAF6200548F620050D0
-:1041A0002442FFFFAF6200500E00030B8F4401401A
-:1041B0008F4401408FBF0010240500040A00031043
-:1041C00027BD00188FBF001003E0000827BD0018AE
-:1041D0008F4201889363007E00021402304400FF86
-:1041E000306300FF1464000D000000009362008043
-:1041F000304200FF1044000900000000A36400806A
-:104200009362000024030050304200FF1443000476
-:10421000000000000A00076F8F440180A364008043
-:1042200003E000080000000027BDFFE8AFB0001069
-:10423000AFBF001493620005240300303042003009
-:1042400014430089008080213C0208008C42002039
-:1042500010400080020020210E00052B000000000D
-:104260008F850020ACB000009362003E9363003F56
-:10427000304200FF00021200306300FF00431025AF
-:10428000ACA2000493620082000216000002160332
-:1042900004410005000000003C0308008C63004856
-:1042A0000A00107E000000009362003E3042004091
-:1042B000144000030000182193620081304300FF86
-:1042C0009362008200031E00304200FF00021400CF
-:1042D00000621825ACA300088F620040ACA2000C5D
-:1042E0008F620048ACA200108F62004CACA2001498
-:1042F0008F6200508F63004C004310230441000381
-:10430000000000000A0010928F62004C8F62005083
-:10431000ACA200183C02080094424DBE3C03C00B06
-:1043200000002021004310250E000550ACA2001C07
-:104330008F6200548F840020AC8200008F6200588E
-:10434000AC8200048F62005CAC8200088F62006067
-:104350008F43007400431021AC82000C8F62006414
-:10436000AC820010976300689762006A00031C002B
-:104370003042FFFF00621825AC8300149362008274
-:1043800024030080304200FF1443000300000000BB
-:104390000A0010C6AC8000188F63000C24020001D4
-:1043A0001062000E2402FFFF9362003E3042004084
-:1043B0001440000A2402FFFF8F63000C8F42007438
-:1043C000006218233C02080000621024144000021E
-:1043D000000028210060282100051043AC8200184D
-:1043E0003C02080094424DBE3C03C00C000020215A
-:1043F000004310258F8300200E000550AC62001C86
-:104400008F6200188F8300203C05080094A54DBEE4
-:1044100024040001AC620000AC6000048F66006CF4
-:104420003C02400D00A22825AC6600088F6200DC2B
-:10443000AC62000CAC600010936200050002160034
-:10444000AC620014AC6000180E000550AC65001C96
-:10445000020020218FBF00148FB00010A360000560
-:104460000A0004B927BD00188FBF00148FB00010D8
-:1044700003E0000827BD00189742007C30C600FF0B
-:10448000A08600843047FFFF2402000514C2000B01
-:1044900024E3465090A201122C420007104000076E
-:1044A00024E30A0090A30112240200140062100405
-:1044B00000E210210A0010FE3047FFFF3067FFFFC7
-:1044C00003E00008A4870014AC87004C8CA201080C
-:1044D0000080402100A0482100E2102330C600FFE8
-:1044E0001840000393AA001324E2FFFCACA20108C9
-:1044F00030C2000110400008000000008D02005092
-:1045000000E2102304410013240600058D0200542C
-:1045100010E20010000000008D02005414E2001AA6
-:10452000000000003C0208008C4200D8304200200D
-:104530001040000A240200019103007891020083D8
-:10454000144300062402000101002021012028213B
-:10455000240600040A0010EC00000000A100008402
-:1045600011400009A50200148F4301008F4201F899
-:104570000440FFFE24020002AF4301C0A34201C475
-:104580003C021000AF4201F803E000080000000008
-:1045900027BDFFE88FA90028AFBF00100080402191
-:1045A00000E918231860007330C600FFA080007C6B
-:1045B000A08000818CA2010800E210230440004D7D
-:1045C000000000008C8200509483003C8C840064C6
-:1045D000004748233063FFFF012318210083202B6D
-:1045E00010800004000000008D0200640A00114FDA
-:1045F00000E210219502003C3042FFFF0122102111
-:1046000000E21021AD02005C9502003C8D03005CCD
-:104610003042FFFF0002104000E210210043102B47
-:1046200010400003000000000A00115E8D02005CD3
-:104630009502003C3042FFFF0002104000E21021D2
-:10464000AD02005CA1000084AD07004C8CA2010803
-:1046500000E210231840000224E2FFFCACA2010893
-:1046600030C200011040000A000000008D0200501E
-:1046700000E2102304410004010020218D020054B7
-:1046800014E20003000000000A0011802406000567
-:104690008D02005414E200478FBF00103C02080056
-:1046A0008C4200D8304200201040000A2402000151
-:1046B0009103007891020083144300062402000154
-:1046C00001002021240600048FBF00100A0010EC16
-:1046D00027BD0018A1000084A50200148F4301002B
-:1046E0008F4201F80440FFFE240200020A0011A5D7
-:1046F000000000008C82005C004910230043102B56
-:1047000054400001AC87005C9502003C3042FFFF42
-:104710000062102B14400007240200029502003CA6
-:104720008D03005C3042FFFF00621821AD03005C86
-:1047300024020002AD07004CA10200840E000FA26B
-:104740008F4401001040001B8FBF00108F430100F9
-:104750008F4201F80440FFFE24020002AF4301C073
-:10476000A34201C43C021000AF4201F80A0011BB91
-:104770008FBF001030C200101040000E8FBF00101D
-:104780008C83005C9482003C006918233042FFFF58
-:10479000006218213C023FFF3444FFFF0083102BCE
-:1047A000544000010080182101231021AD02005C5B
-:1047B0008FBF001003E0000827BD001827BDFFE8E9
-:1047C0008FAA0028AFBF00100080402100EA4823D4
-:1047D0001920002130C600FF8C83005C8C820064AD
-:1047E000006A18230043102B504000100069182164
-:1047F00094A2011001221021A4A2011094A2011080
-:104800003042FFFF0043102B1440000A3C023FFFE0
-:1048100094A2011000431023A4A201109482003C32
-:104820003042FFFF0A0011DA00621821A4A0011033
-:104830003C023FFF3444FFFF0083102B5440000133
-:104840000080182100671021AD02005CA100007CEF
-:104850000A001222A100008130C200101040003C6A
-:10486000000000008C820050004A102318400038DD
-:10487000000000009082007C24420001A082007CA5
-:104880009082007C3C0308008C630024304200FFCF
-:104890000043102B1440005C8FBF00108CA2010855
-:1048A00000E2102318400058000000008C830054E0
-:1048B0009482003C006A18233042FFFF0003184333
-:1048C000000210400043102A1040000500000000C4
-:1048D0008C820054004A10230A001209000210437F
-:1048E0009482003C3042FFFF00021040AD020064A1
-:1048F0009502003C8D0400649503003C3042FFFFAC
-:1049000000021040008220213063FFFF0083182145
-:1049100001431021AD02005C8D020054ACA20108DD
-:1049200024020002A10200840E000FA28F440100A5
-:10493000104000358FBF00108F4301008F4201F8F7
-:104940000440FFFE240200020A00124B0000000097
-:10495000AD07004C8CA2010800E2102318400002B1
-:1049600024E2FFFCACA2010830C200011040000AA2
-:10497000000000008D02005000E2102304410004FA
-:10498000010020218D02005414E200030000000009
-:104990000A001242240600058D02005414E2001A97
-:1049A0008FBF00103C0208008C4200D8304200202B
-:1049B0001040000A24020001910300789102008354
-:1049C00014430006240200010100202124060004F3
-:1049D0008FBF00100A0010EC27BD0018A100008452
-:1049E000A50200148F4301008F4201F80440FFFE2E
-:1049F00024020002AF4301C0A34201C43C021000E4
-:104A0000AF4201F88FBF001003E0000827BD001877
-:104A10008FAA00108C8200500080402130C600FF19
-:104A2000004A102300A048211840000700E0182188
-:104A300024020001A0800084A0A00112A48200141E
-:104A40000A0011BDAFAA0010A0800081AD07004C84
-:104A50008CA2010800E210231840000224E2FFFCAF
-:104A6000ACA2010830C200011040000800000000A4
-:104A70008D0200500062102304410013240600053B
-:104A80008D02005410620010000000008D020054DE
-:104A900014620011000000003C0208008C4200D8A3
-:104AA000304200201040000A2402000191030078E7
-:104AB000910200831443000624020001010020211A
-:104AC00001202821240600040A0010EC0000000048
-:104AD000A1000084A502001403E00008000000000B
-:104AE00027BDFFE0AFBF0018274201009046000A33
-:104AF0008C4800148C8B004C9082008430C900FFDD
-:104B000001681823304A00FF1C60001A2D46000679
-:104B1000240200010142100410C0001630430003BB
-:104B2000012030210100382114600007304C000CB6
-:104B300015800009304200301440000B8FBF001870
-:104B40000A0012AC000000000E0011BDAFAB001057
-:104B50000A0012AC8FBF00180E001132AFAB00106C
-:104B60000A0012AC8FBF0018AFAB00100E0012523B
-:104B7000AFAA00148FBF001803E0000827BD002073
-:104B800024020003A08200848C82005403E0000809
-:104B9000ACA201083C020008034218219062008187
-:104BA000240600433C07601924420001A0620081F2
-:104BB000906300813C0208008C4200C0306300FF1B
-:104BC000146200102403FF803C0208008C4200E0C5
-:104BD0000082102100431024AF4200243C02080050
-:104BE0008C4200E03C03000A008210213042007F2A
-:104BF0000342102100431021944500D40A000B8980
-:104C000030A5FFFF03E000080000000027BDFFE023
-:104C1000AFBF0018AFB10014AFB000108F420180D9
-:104C20000080802100A088210E0012B300402021C6
-:104C3000A20000848E0200548FBF00188FB00010B5
-:104C4000AE2201088FB1001403E0000827BD002048
-:104C500027BDFFE03C020008AFB00010AFBF001856
-:104C6000AFB10014034280218F51014092030084B0
-:104C70008E0400508E02004C14820040306600FF0B
-:104C80003C0208008C4200E02403FF800222102135
-:104C900000431024AF4200243C0208008C4200E094
-:104CA0009744007C92050081022210213042007F4F
-:104CB000034218213C02000A0062182114A0000BD4
-:104CC0003084FFFF2402000554C20014248205DC56
-:104CD0009062011224420001A062011224020C80A1
-:104CE000AF4200240A00130B24020005A060011249
-:104CF0002402000514C20009248205DC920200810E
-:104D00002C4200075040000524820A0092030081D3
-:104D10002402001400621004008210213044FFFFBE
-:104D2000A60400140E0012B3022020219602003CBB
-:104D30008E03004C022020213042FFFF0002104071
-:104D4000006218210E000302AE03005C9202007D97
-:104D500002202021344200400E00030BA202007DFD
-:104D60008F4201F80440FFFE24020002AF5101C04F
-:104D7000A34201C43C021000AF4201F88FBF0018EB
-:104D80008FB100148FB0001003E0000827BD002091
-:104D900008000D9808000DE008000E2008000E6CB9
-:044DA00008000EA059
-:0C4DA4000A0000220000000000000000D7
-:104DB0000000000D6370352E302E306A3600000082
-:104DC00005000004000000000000000000000000DA
-:104DD00000000000000000000000000000000000D3
-:104DE00000000000000000000000000000000020A3
-:104DF00000000000000000000000000000000000B3
-:104E000000000000000000000000000000000000A2
-:104E10000000000000000000000000000000000191
-:104E20000000002B00000000000000000000000057
-:104E300010000003000000000000000D0000000D45
-:104E40003C02080024425AC43C03080024636190D9
-:104E5000AC4000000043202B1480FFFD24420004DE
-:104E60003C1D080037BD7FFC03A0F0213C1008006A
-:104E7000261000883C1C0800279C5AC40E0001A67E
-:104E8000000000000000000D27BDFFE83C0960188D
-:104E9000AFBF00108D2C5000240DFF7F240800317F
-:104EA000018D5824356A380C24070C003C1A800008
-:104EB000AD2A50003C04800AAF4800083C1B800823
-:104EC000AF4700240E000935AF8400100E0008F82B
-:104ED000000000000E000845000000000E0012DC7B
-:104EE000000000003C0460168C8500003C06FFFFBB
-:104EF0003C02535300A618241062004734867C00FD
-:104F000094C201F2A780002C10400003A78000CCBF
-:104F100038581E1EA798002C94C201F810400004B7
-:104F2000978300CC38591E1EA79900CC978300CCDC
-:104F30002C7F006753E00001240300669784002C57
-:104F40002C82040114400002006028212404040083
-:104F50003C0760008CE904382403103C3128FFFF33
-:104F60001103001F30B9FFFF57200010A38000CEAF
-:104F700024020050A38200CE939F00CE53E0000F86
-:104F8000A78500CCA78000CC978500CC8FBF0010F0
-:104F9000A780002CA7800034A78000E63C01080011
-:104FA000AC25008003E0000827BD0018939F00CEC9
-:104FB00057E0FFF5A78000CCA78500CC978500CCF3
-:104FC0008FBF0010A784002CA7800034A78000E6C4
-:104FD0003C010800AC25008003E0000827BD001854
-:104FE000A38000CE8CCB003C316A00011140000E42
-:104FF0000000000030A7FFFF10E0FFDE2402005099
-:105000008CCC00C83186000114C0FFDC939F00CE19
-:105010000A000074240200518C8F00043C0E6000D2
-:105020000A00005701EE30218CEF0808240D5708C4
-:10503000000F740211CD000430B8FFFF2405006694
-:105040000A000075240404001700FFCC939F00CED3
-:105050000A000074240200508F8600103089FFFF80
-:10506000000939408CC300103C08005000E820259E
-:10507000AF4300388CC5001427420400AF82001CE7
-:10508000AF45003CAF4400300000000000000000CD
-:105090000000000000000000000000000000000010
-:1050A00000000000000000008F4B0000316A00206B
-:1050B0001140FFFD0000000003E0000800000000B8
-:1050C0008F840010948A001A8C8700243149FFFFD6
-:1050D000000940C000E83021AF46003C8C85002428
-:1050E0008F43003C00A3102318400029000000005B
-:1050F0008C8B0020256200013C0D005035AC00086F
-:10510000AF420038AF4C003000000000000000004B
-:10511000000000000000000000000000000000008F
-:1051200000000000000000008F4F000031EE002062
-:1051300011C0FFFD000000008F4A04003C08002061
-:10514000AC8A00108F490404AC890014AF480030C9
-:1051500000000000948600189487001C00C71821E6
-:10516000A48300189485001A24A20001A482001AC6
-:105170009498001A9499001E133800030000000050
-:1051800003E000080000000003E00008A480001A0B
-:105190008C8200200A0000D63C0D00500A0000C797
-:1051A000000000003C0308008C6300208F82001880
-:1051B00027BDFFE810620008AFBF00100E0000FE20
-:1051C000AF8300183C0308008C6300202404000116
-:1051D000106400048F8900108FBF001003E00008E6
-:1051E00027BD00188FBF00103C076012A520000AE1
-:1051F0009528000A34E5001027BD00183106FFFF8E
-:1052000003E00008ACA600903C0208008C4200209D
-:1052100027BDFFC8AFBF0034AFBE0030AFB7002C12
-:10522000AFB60028AFB50024AFB40020AFB3001C68
-:10523000AFB20018AFB1001410400050AFB0001072
-:105240008F840010948600069483000A00C32823EC
-:1052500030B6FFFF12C0004A8FBF00349489001897
-:10526000948A000A012A40233102FFFF02C2382B30
-:1052700014E0000202C02021004020212C8C0005F7
-:10528000158000020080A021241400040E0000AD4F
-:10529000028020218F87001002809821AF800014A7
-:1052A00094ED000A028088211280004E31B2FFFF87
-:1052B0003C1770003C1540003C1E60008F8F001CA6
-:1052C0008DEE000001D718245075005002202021D7
-:1052D00002A3802B160000353C18200050780047B0
-:1052E00002202021241000018F8300141460003953
-:1052F000029158230230F8230250C82133F1FFFFF6
-:105300001620FFEE3332FFFF8F8700103C11002084
-:10531000AF5100300000000094E6000A3C1E60120D
-:1053200037D5001002662821A4E5000A94E2000A9D
-:1053300094F2000A94F400183057FFFF1292003BD9
-:10534000AEB700908CED00148CE400100013714097
-:1053500001AE4021000E5FC3010E502B008B48218F
-:10536000012A1821ACE80014ACE3001002D3382362
-:1053700030F6FFFF16C0FFB98F8400108FBF0034D6
-:105380008FBE00308FB7002C8FB600288FB5002459
-:105390008FB400208FB3001C8FB200188FB100149F
-:1053A0008FB0001003E0000827BD0038107E001BFE
-:1053B000000000001477FFCC241000010E00162717
-:1053C000000000008F8300141060FFCB0230F82330
-:1053D000029158238F870010017020210A0001914B
-:1053E0003093FFFF8F8300141460FFCB3C1100202B
-:1053F000AF5100300A00015D000000000E00079E62
-:10540000024028210A000151004080210E00034B78
-:10541000024028210A000151004080210E0014EFB3
-:10542000022020210A000151004080210E0000C707
-:10543000000000000A00017302D3382327BDFFE8F3
-:10544000AFB00010AFBF00140E0000390000000024
-:105450003C028000345000700A0001B48E06000047
-:105460008F4F000039EE000131C2000110400024CE
-:105470008F8600A88E0700003C0C08008D8C003C35
-:105480003C0908008D29003800E66823018D282199
-:105490000000502100AD302B012A402101062021BF
-:1054A0003C010800AC25003CAF8700A83C01080087
-:1054B000AC2400380E000100000000003C0308008E
-:1054C0008C6300701060FFE6006020213C0508003E
-:1054D0008CA500683C0608008CC6006C0E0015B652
-:1054E000000000003C010800AC2000708F4F00005D
-:1054F00039EE000131C200011440FFDE8F8600A8A2
-:105500008E0A00008F8B00A83C0508008CA5003C8B
-:105510003C0408008C840038014B482300A9382142
-:105520000082182100E9402B006810213C0108008E
-:10553000AC27003C3C010800AC2200388F5F010022
-:105540002419FF0024180C0003F9202410980012DD
-:10555000AF840000AF440020936D0000240C0020B5
-:1055600031A600FF10CC0012240E005010CE000413
-:105570003C194000AF5901380A0001AD000000009D
-:105580000E001252000000003C194000AF590138D3
-:105590000A0001AD000000000E000119000000002B
-:1055A0003C194000AF5901380A0001AD000000006D
-:1055B0008F58010000802821330F00FF01E02021D7
-:1055C0000E0002F8AF8F00043C194000AF590138BB
-:1055D0000A0001AD0000000000A4102B240300010C
-:1055E00010400009000030210005284000A4102BC5
-:1055F00004A00003000318405440FFFC00052840AD
-:105600005060000A0004182B0085382B54E0000479
-:105610000003184200C330250085202300031842F0
-:105620001460FFF9000528420004182B03E000086D
-:1056300000C310213084FFFF30A5FFFF8F4201B867
-:105640000440FFFE3C074080008730253C031000EB
-:10565000AF400180AF450184AF46018803E00008F8
-:10566000AF4301B83084FFFF8F4201B80440FFFE12
-:105670003C0740388CA60000008728253C0310001A
-:10568000AF460180AF45018803E00008AF4301B891
-:105690008F8300388F8600301066000B0080402119
-:1056A0003C07080024E75C38000328C000A710214D
-:1056B0008C44000024630001108800053063000F53
-:1056C0005466FFFA000328C003E000080000102120
-:1056D0003C07080024E75C3C00A7302103E00008F9
-:1056E0008CC200003C03900034620001008220253F
-:1056F000AF4400208F45002004A0FFFE0000000002
-:1057000003E00008000000003C0380003462000158
-:105710000082202503E00008AF44002027BDFFE001
-:10572000AFB100143091FFFFAFB00010AFBF001851
-:105730001220001500A080218CA5000010A00013ED
-:10574000240400020E000C7C24060140AE00000080
-:105750008F4201B80440000D000028213C064000A3
-:10576000022620258FBF00188FB100148FB00010C3
-:105770003C03100027BD0020AF450180AF440188E5
-:1057800003E00008AF4301B88CA500008F4201B8C8
-:105790000440FFFE3C064000022620258FBF001873
-:1057A0008FB100148FB000103C03100027BD002003
-:1057B000AF450180AF44018803E00008AF4301B862
-:1057C0003086FFFF8F4201B80440FFFE3C094006CF
-:1057D0008CA8000000C93825AF4801808CA40004C3
-:1057E0003C031000AF440184AF47018803E0000888
-:1057F000AF4301B827BDFFE0AFB00010AFBF001846
-:10580000AFB100149363003E008080210080282106
-:1058100030620040000020211040000F8E11000077
-:105820000E0008710220202193670000240400501C
-:1058300030E500FF50A400128E0F0000022020214E
-:105840008FBF00188FB100148FB00010A762013C09
-:105850000A00093127BD00200E0002870000000069
-:105860000E000871022020219367000024040050DC
-:1058700030E500FF14A4FFF2022020218E0F00006B
-:105880003C1008008E1000503C0D000C240BFF80D3
-:1058900001F05021314E007F01DA6021018D40215D
-:1058A000014B4824AF490028022020218FBF001857
-:1058B0008FB100148FB00010A50200D627BD0020C4
-:1058C0000A000931AF8800D027BDFFE0AFBF001844
-:1058D000AFB10014AFB000109366000100808021CA
-:1058E0000E00025030D1000493640005001029C25C
-:1058F000A765000034830040A36300050E00025931
-:10590000020020210E0009330200202124020001A0
-:10591000AF62000C02002821A762001024040002DC
-:10592000A762001224060140A76200140E000C7C3E
-:10593000A76200161620000F8FBF0018978C003446
-:105940003C0B08008D6B00782588FFFF3109FFFFB5
-:10595000256A0001012A382B10E00006A7880034D0
-:105960003C0F6006240E001635ED0010ADAE005061
-:105970008FBF00188FB100148FB0001003E0000833
-:1059800027BD002027BDFFE0AFB10014AFBF001856
-:10599000AFB0001000A088211080000A3C03600016
-:1059A0002402008010820012000000000000000DA0
-:1059B0008FBF00188FB100148FB0001003E00008F3
-:1059C00027BD00208C682BF80500FFFE00000000BA
-:1059D000AC712BC08FBF00188FB100148FB00010B6
-:1059E0003C09100027BD002003E00008AC692BF83B
-:1059F0000E00025000A02021936500050220202106
-:105A00000E00025930B000FF2403003E1603FFE7EA
-:105A1000000000008F4401780480FFFE2407000787
-:105A20003C061000AF51014002202021A347014451
-:105A30008FBF00188FB100148FB00010AF460178EF
-:105A40000A0002C927BD002027BDFFE8AFBF001430
-:105A5000AFB000108F500020000000000E0009338E
-:105A6000AF440020AF5000208FBF00148FB0001053
-:105A700003E0000827BD00183084FFFF8F4201B803
-:105A80000440FFFE3C074035008730253C031000F2
-:105A9000AF450180AF400184AF46018803E00008B4
-:105AA000AF4301B83084FFFF8F4201B80440FFFECE
-:105AB0003C074036008730253C031000AF4501808D
-:105AC000AF400184AF46018803E00008AF4301B84E
-:105AD00027BDFFD0AFB3001C3093FFFFAFB500244C
-:105AE000AFB20018AFBF0028AFB40020AFB10014B0
-:105AF000AFB0001030B5FFFF12600027000090210A
-:105B00008F90001C8E0300003C06800024020040A1
-:105B100000033E0200032C0230E4007F006688246C
-:105B20001482001D30A500FF8F8300282C68000A16
-:105B3000510000108F910014000358803C0C0800A5
-:105B4000258C58C4016C50218D49000001200008AB
-:105B50000000000002B218213065FFFF0E00022491
-:105B600024040084162000028F90001CAF800028BF
-:105B70008F910014260C0020264B0001018080210B
-:105B80003172FFFF16200004AF8C001C0253282B3B
-:105B900014A0FFDC00000000024010218FBF00288D
-:105BA0008FB500248FB400208FB3001C8FB2001873
-:105BB0008FB100148FB0001003E0000827BD003043
-:105BC000240D003414AD00F600000000920B000E0E
-:105BD000240A16803C07000CA36B00219203000DE1
-:105BE0000347F8213C066000A363002096110012D1
-:105BF0003C057FFF34ACFFFFA771003C960200100C
-:105C0000240B00053054FFFFAF7400848E19001C74
-:105C1000AF4A00288FF800008CCF44480319702643
-:105C200001EE3021AF66004C8F69004C24CD00019D
-:105C30003C197F00AF6900508F640050AF6400547E
-:105C4000AF660070AF6D00588F6800582404005094
-:105C5000AF68005CA3600023AF6C0064A36B0037E7
-:105C60008E030014AF6300488F710048AF710024A9
-:105C70008E020018AF62006C9214000CA374003600
-:105C8000936A003E355F0020A37F003E8F7800744A
-:105C90000319782435EE4000AF6E0074936900005C
-:105CA000313000FF1204022C2418FF803C0408004D
-:105CB00024845CB80E000294000000002406000456
-:105CC000240700013C0408008C845CB8A366007DB6
-:105CD000A36700058F4A01780540FFFE24020002F9
-:105CE000AF440140A34201448F90001C3C141000BB
-:105CF000AF5401780A000373AF8000282CAD003741
-:105D000051A0FF9C8F9100140005A0803C18080052
-:105D1000271858EC029878218DEE000001C0000889
-:105D2000000000002406000614A600110000000078
-:105D30003C1F08008FFF5CB824040005AF5F002003
-:105D40008E190018AF7900188F78004CAF78001CBE
-:105D50008F6F0050122000C2AF6F00700A000373F3
-:105D6000AF840028240A000710AA00842403000638
-:105D70003C05080024A55CB80E00025E24040081E6
-:105D80008F90001C0011102B0A000373AF820028B3
-:105D90002402000414A2FFF6240A00503C09080063
-:105DA0008D295CB8AF4900208E040008AF64004024
-:105DB0008E060008AF6600448E07000CAF670048EF
-:105DC0008E0D0010AF6D004C8E080010AF6800847F
-:105DD0008E050014AF6500508E0C0018AF6C005497
-:105DE0008E0B001CAF6B005893740000328300FFD1
-:105DF000106A01EE000000008F6700488F660040C7
-:105E000000E6682305A000042404008C1620FFDEB1
-:105E100024020003240400823C05080024A55CB889
-:105E20000E000287000000008F90001C000010216F
-:105E30000A000373AF8200282404000514A4FFCCD9
-:105E4000240520003C1F08008FFF5CB8AF5F0020D6
-:105E50008E190004AF79005C921800082410000825
-:105E6000A37800218F8F001C91EE0009A36E002003
-:105E70008F86001C90C9000A312400FF109000108A
-:105E8000288A00091540006C24020002240C00201E
-:105E9000108C000B340580002885002114A0000818
-:105EA0002405400024080040108800053C0500013E
-:105EB000240D0080108D00023C05000224054000E6
-:105EC0008F6E00743C0FFF0001CF48240125802510
-:105ED000AF70007490C4000BA36400818F84001C19
-:105EE0009487000C10E0019400000000948E000CD8
-:105EF000241FFFBF24060004A76E003C9089000EFB
-:105F0000A369003E8F90001C9204000FA364003F21
-:105F10008F94001C8E8D00108F47007401A74023C2
-:105F2000AF6800608E850014AF650064968C001821
-:105F3000A76C0068968B001AA76B006A8E83001C02
-:105F4000AF63006C96820002A762013E928A000E47
-:105F5000A36A003E9379003E033FC02412200167EC
-:105F6000A378003E8F90001C0A000373AF860028C0
-:105F70002414002214B4FF7E240300073C0208000E
-:105F80008C425CB81220000CAF4200200A00037360
-:105F9000AF830028240C003310AC00142405002823
-:105FA0003C05080024A55CB80E00023024040081E2
-:105FB0000A0003F88F90001C3C04080024845CB89D
-:105FC0000E00029400000000936B000024110050AA
-:105FD000316300FF10710151000000008F90001C20
-:105FE000000018210A000373AF8300283C08080052
-:105FF0008D085CB824040081AF480020A3650034FC
-:106000003C05080024A55CB80E000230000000002A
-:106010008F90001C240200090A000373AF8200283D
-:1060200002B288213225FFFF0E00022424040084DE
-:106030000A0003738F90001C1082FFA12405040046
-:10604000288300031060016F240B00042414000156
-:106050005494FF9B240540000A00044724050100D6
-:106060003C04080024845CB88F62004C0E0002944B
-:106070008F6300508F90001C000020210A000373E2
-:10608000AF8400288E1000042404008AAF50002042
-:10609000936E000531C900021520015E020028211F
-:1060A0009378002302002821330F002015E00159C6
-:1060B0002404008D9362003F24190012305F00FF1A
-:1060C00013F90154240400810E0002500200202123
-:1060D00093740023240A0004020020213683004226
-:1060E000A36300230E000259A36A007D8F4B017841
-:1060F0000560FFFE24050002AF500140A3450144A6
-:106100008F90001C3C0C1000AF4C01780A0003F982
-:106110000011102B8E1000042404008AAF500020C0
-:10612000936D000531A80002150000160200282119
-:106130009364003F2407000402002821308600FFFA
-:1061400010C70010240400810E000250020020211C
-:10615000937F002324180012240FFFFE37F900203C
-:10616000A3790023A378003F936E0005020020214D
-:1061700001CF48240E000259A3690005020028211E
-:10618000000020210E000340000000000A0003F878
-:106190008F90001C8E0500043C0F0008034F402127
-:1061A000AF450020910E00002406005031C900FFC9
-:1061B00011260176240400888F5901B80720FFFEBC
-:1061C0003C0C400E008C58253C031000AF4501806C
-:1061D000AF400184AF4B0188AF4301B8910200008A
-:1061E000240AFF8024040004004AF825A11F0000AF
-:1061F0000E000C7C240600300A0003F88F90001C6F
-:106200008E0F00043C14080026945CB83C01080082
-:10621000AC2F5CB8AF4F0020920E000331C90004D0
-:10622000112000022402001224020006A362003F93
-:106230009203001B240AFFC03062003F004AF82589
-:10624000A37F003E92190003333800011700011CA0
-:10625000000000008E020008AE8200083C02080028
-:106260008C425CC01040011B00000000000221C2F3
-:10627000A76400088E0D000C240B000124140014E8
-:10628000AF6D002C8E080010AF6800309605001628
-:10629000A7650038960C0014A76C003AAF6B000C91
-:1062A000A76B0010A76B0012A76B0014A76B00165A
-:1062B00012200146A37400349206000330C7000286
-:1062C0002CF00001260200088F90001C0A000373C6
-:1062D000AF8200288E14000424030081AF540020F4
-:1062E000936800233105001010A001070000000092
-:1062F0008F4401B80480FFFE3C06401F0011382B7C
-:10630000006610253C111000AF540180AF870028B3
-:10631000AF400184AF420188AF5101B80A00037455
-:106320008F9100148E0600043C19000803592021A7
-:10633000AF4600208E07000890980000240F005000
-:10634000331400FF128F0102240500888F4401B826
-:106350000480FFFE3C0D40090011602B00AD1025AC
-:106360003C111000AF460180AF8C0028AF4701847C
-:10637000AF420188AF5101B80A0003748F91001435
-:106380008E04001C0E00023B00000000104000E8DC
-:10639000004048218F90001C240500898F4D01B8D2
-:1063A00005A0FFFE00000000AF4901808E0F001C19
-:1063B0003C1440010011702B00B448253C11100022
-:1063C000AF4F0184AF8E0028AF490188AF5101B8AB
-:1063D0000A0003748F910014961900023C140800FF
-:1063E00026945CB8333800041300008E3C02600031
-:1063F0008E1F001C3C010800AC3F5CB8AF5F002062
-:10640000920C0010240B0014318400FF148B00B890
-:106410000000000096090002312D000115A0014E78
-:10642000000000008E020004AE8200083C0E08004E
-:106430008DCE5CC011C00144000000008F69007463
-:106440003C0E800024040001012E6825AF6D00740D
-:10645000A3600005AF64000C3C0C08008D8C5CC090
-:106460008F88001CA7640010000C59C2A76400129A
-:10647000A7640014A7640016A76B00088D0300082A
-:1064800024040002AF63002C8D0A000CAF6A0030B8
-:1064900091070010A36700348F82001C9045001103
-:1064A000A36500358F86001C90D00012A3700036C3
-:1064B0008F9F001C93F90013A37900378F90001C65
-:1064C00096180014A778003896140016A774003A9E
-:1064D0008E0F0018AF6F00245620FDA5AF84002852
-:1064E0003C05080024A55CB80E00025E00002021D7
-:1064F0008F90001C0A0004B6000020213C05080013
-:1065000024A55CB80E000287240400828F90001C32
-:10651000000030210A000373AF8600283C04080005
-:106520008C845CB80E001574000000008F90001C75
-:106530000A000490000018213C05080024A55CB85E
-:106540000E0002872404008B8F90001C0011302B5A
-:106550000A000373AF8600283C1908008F395CB825
-:106560003C1F08008FFF005024CCFFFE033F782122
-:1065700001F87024AF4E00283C0408008C845CB8FD
-:106580003C0908008D2900500089682131A8007F4E
-:10659000011A282100A78021AE0600D8AF9000D0B4
-:1065A000AE0000DC0A0003C2AE0C0108AF6000843C
-:1065B0003C0508008CA55CB83C0808008D0800501C
-:1065C000240CFF803C02000C00A8A021028C58245F
-:1065D000AF4B00288E1F00143283007F007A5021B9
-:1065E00001427021ADDF00D88E190014AF8E00D0AB
-:1065F000ADD900DC8E180010270FFFFE0A0004152D
-:10660000ADCF0108548BFE2E240540000A0004473C
-:10661000240510000E000335000000000A0003F8F6
-:106620008F90001C8C46442C3C056C6234B0797011
-:106630003C010800AC205CB814D00008240400021F
-:1066400097880034978A002C02802821010A382B71
-:1066500010E0001124040092240400020E000C9AA1
-:10666000240501403C010800AC225CB8AF42002088
-:106670003C0308008C635CB81060000524040083B0
-:106680000E0008650000000010400009240400838B
-:106690003C05080024A55CB80E00025E0000000066
-:1066A0008F90001C0011202B0A000373AF84002878
-:1066B0000E000869000000000A0005978F90001C7A
-:1066C0008E0400080E00023B000000000A00052EA8
-:1066D000AE8200083C05080024A55CB80E0002301C
-:1066E000240400878F90001C0A00054A0011102B1B
-:1066F0000E00086D000000003C05080024A55CB8F1
-:106700000A00063D2404008B0E0002500280202166
-:106710009370002302802021360D00100E000259D4
-:10672000A36D00238F90001C0A0005530000182160
-:10673000240400040E000C9A240500301440002AA2
-:10674000004048218F90001C0A00057E240500832C
-:106750009205000C30BF000113E0000300000000B0
-:106760009602000EA482002C920A000C314800020E
-:106770001100FEF600002821960B00128E03001473
-:10678000A48B001A0A00056AAC83001C8F830038B2
-:106790008F8700301067FE88000020213C09080028
-:1067A00025295C3C000320C0008930218CD40000E6
-:1067B0001285005E247800013303000F5467FFFA4E
-:1067C000000320C00A000505000020213C05080048
-:1067D00024A55CB80E000287240400828F90001C60
-:1067E0000A00054A000010213C0B0008034B202141
-:1067F00024030050240A0001AF420020A0830000BF
-:10680000A08A00018F88001C91070004A08700184F
-:106810008F82001C90450005A08500198F86001C02
-:1068200090DF0006A09F001A8F99001C9338000784
-:10683000A098001B8F94001C928F0008A08F001C52
-:106840008F90001C920E0009A08E001D8F8D001CE1
-:1068500091AC000AA08C001E8F8B001C3C0C080021
-:10686000258C5C3C9163000B3C0B0800256B5C386D
-:10687000A083001F8F8A001C9148000CA088002074
-:106880008F87001C90E5000DA08500218F82001CE1
-:10689000240546469046000EA08600228F9F001CCD
-:1068A00093F9000FA09900238F98001C93140010F7
-:1068B000A09400248F8F001C91F00011A09000255F
-:1068C0008F90001C8F8E00308F990038960D001429
-:1068D000000E18C025C80001A48D0028960A0016D5
-:1068E000006C3021006BF821A48A002A960700185A
-:1068F0003108000FA487002CA485002E8E02001CF6
-:10690000ACC90000AF88003011190003AFE20000ED
-:106910000A00057E00002821250C00013184000FAB
-:10692000000028210A00057EAF8400383C070800DB
-:1069300024E75C380087802100002021ACC00000E3
-:106940000A000505AE0000003C05080024A55CB85F
-:106950000A00063D240400878E0400040E00023B5A
-:10696000000000000A0005A2AE8200083084FFFF8C
-:1069700030C600FF8F4201B80440FFFE000644000D
-:10698000010430253C07200000C720253C031000EF
-:10699000AF400180AF450184AF44018803E00008A7
-:1069A000AF4301B827BDFFE8AFB00010AFBF001480
-:1069B0003C076000240600021080000600A0802131
-:1069C0000010102B8FBF00148FB0001003E00008E0
-:1069D00027BD00183C09600EAD2000348CE5201C5A
-:1069E0008F82001C2408FFFC00A81824ACE3201CA4
-:1069F0000E0006F28C45000C0010102B8FBF001407
-:106A00008FB0001003E0000827BD00183C02600EA4
-:106A10003447010024090018274A04000000000040
-:106A200000000000000000003C06005034C30200DB
-:106A3000AF440038AF45003CAF430030014018215F
-:106A40008F4B0000316800201100FFFD2406007FFD
-:106A50002408FFFF8C6C000024C6FFFF24630004A1
-:106A6000ACEC000014C8FFFB24E7000400000000A9
-:106A700000000000000000003C0F0020AF4F00307D
-:106A80000000000024AD020001A5702B2529FFFFA6
-:106A9000008E20211520FFE101A0282103E000083D
-:106AA0000000000027BDFFE0AFB10014AFBF001829
-:106AB000AFB000103C05600E8CA20034008088212D
-:106AC000144000063C0460008C87201C2408FFFC56
-:106AD00000E8302434C30001AC83201C8F8B001CE1
-:106AE00024090001ACA90034956900028D650014E9
-:106AF0008D70000C2D2400818D6700048D660008C8
-:106B0000108000078D6A00102D2C00041580000EE7
-:106B100030CE0007312D000311A0000B0000000053
-:106B20002404008B020028210E0006F22406000334
-:106B30000011102B8FBF00188FB100148FB0001000
-:106B400003E0000827BD002015C0FFF62404008BD9
-:106B50003C030020AF43003000000000240200018D
-:106B6000AF820014000000000000000000000000E0
-:106B70003C1F0150013FC825253800033C0F600E23
-:106B8000AF47003800181882AF46003C35E8003C9B
-:106B9000AF590030274704008F44000030860020A2
-:106BA00010C0FFFD00000000106000082466FFFF19
-:106BB0002403FFFF8CEB000024C6FFFF24E7000442
-:106BC000AD0B000014C3FFFB250800043C08600E59
-:106BD000AD090038000000000000000000000000C7
-:106BE0003C070020AF470030000000000E00071AED
-:106BF0000140202102002821000020210E0006F281
-:106C0000240600030011102B8FBF00188FB1001451
-:106C10008FB0001003E0000827BD002027BDFFD87B
-:106C2000AFB200183092FFFFAFB10014AFBF002029
-:106C3000AFB3001CAFB000101240002C0000882140
-:106C40000A0007B22413000150B300408CE5000C89
-:106C50000000000D263900013331FFFF24F8002029
-:106C60000232382B10E00021AF98001C8F820014F4
-:106C70001440001E8F87001C3C0670003C0320005F
-:106C80008CE400000086282414A300188F85003CA3
-:106C9000000444023C0980000089802414A0FFEA1B
-:106CA000310600FF240A000210CA002E28CB000380
-:106CB00011600016240C000314D3FFE726390001ED
-:106CC000020028210E000700240400018F87001C09
-:106CD000AF82003C263900013331FFFF24F8002049
-:106CE0000232382B14E0FFE1AF98001C0220102183
-:106CF0008FBF00208FB3001C8FB200188FB100141B
-:106D00008FB0001003E0000827BD002810CC001A47
-:106D1000240D000414CDFFD026390001308EFFFF72
-:106D2000000E19C08F4401B80480FFFE3C0F100014
-:106D30003C102004AF430180AF400184AF50018874
-:106D4000AF4F01B80A0007AD263900010E0006F268
-:106D5000240400841600FFBF8F87001C0A0007ACC4
-:106D6000AF80003C020028210E0007000000202117
-:106D70000A0007CB8F87001C0E000740020020216D
-:106D80008F87001C0A0007CCAF82003C3082FFFFD7
-:106D90001440000300001821000424022403001002
-:106DA000308500FF14A000053087000F246600081E
-:106DB0000004220230C300FF3087000F14E00005FA
-:106DC000308900032468000400042102310300FF1D
-:106DD0003089000315200005388B0001246A000269
-:106DE00000042082314300FF388B00013164000130
-:106DF00010800002246C0001318300FF03E00008D2
-:106E000000601021308BFFFF000B394230E600FF9D
-:106E10003C09080025295BB8000640800109602173
-:106E20008D8700003164001F240A0001008A1804C5
-:106E300030A500FF00E3202514A000020003102766
-:106E400000E22024240F000100CF70040109682112
-:106E5000000E282714800005ADA400008F86000CCA
-:106E600000A6102403E00008AF82000C8F88000CFD
-:106E700001C8102503E00008AF82000C3C06001F8B
-:106E80003C0360003084FFFF34C5FF8024020020F3
-:106E9000AC602008AC60200CAC602010AC65201405
-:106EA000AC642018AC62200000000000000000006C
-:106EB00003E000080000000027BDFFE82402FFFFF8
-:106EC000AFBF0010AF82000C000020213C0608007C
-:106ED00024C65BB82405FFFF24890001000440801C
-:106EE0003124FFFF010618212C87002014E0FFFA4F
-:106EF000AC6500000E0008360000202124020001CD
-:106F00003C04600024050020AC822018AC852000E1
-:106F1000000000000000000000000000244A000102
-:106F20003142FFFF2C46040014C0FFF78FBF001052
-:106F300003E0000827BD00188F8300082C620400BE
-:106F400003E00008384200018F830008246200013A
-:106F500003E00008AF8200088F8300082462FFFF6F
-:106F600003E00008AF82000827BDFFE0AFB10014C6
-:106F7000AFBF0018AFB000108F6B00303C06600050
-:106F800000808821ACCB20088F6A002C3C02800056
-:106F900024030008ACCA200C9769003A97680038AF
-:106FA00000092C003107FFFF00A72025ACC42010EA
-:106FB000ACC22014ACC320000000000000000000A0
-:106FC000000000003C0360008C6D200031AC000824
-:106FD0001580FFF9000000008C6E201405C0002011
-:106FE000000000000E0007FA8F84000C00024080B1
-:106FF0003C09080025295BB8010938218CE4000010
-:107000000E0007FA00028140020220213090FFFFAB
-:10701000020020210E000818000028213C0C8000EE
-:10702000022C58253210FFFF3C116000240A00207A
-:10703000AE2B2014AE302018AE2A20000000000035
-:107040000000000000000000020010218FBF0018A7
-:107050008FB100148FB0001003E0000827BD00209E
-:107060008C6620143C02001F3443FF803C1FFFE865
-:1070700000C3C02437F9080003198021001079C229
-:107080003C0C8000022C582531F0FFFF3C116000C1
-:10709000240A0020AE2B2014AE302018AE2A200087
-:1070A00000000000000000000000000002001021AD
-:1070B0008FBF00188FB100148FB0001003E00008DC
-:1070C00027BD002027BDFFE8AFB000103402FFFF4E
-:1070D0003090FFFFAFBF0014120200060200202113
-:1070E0000E00083600000000020020210E000818E3
-:1070F000240500018F8400088FBF00148FB000109A
-:107100002483FFFF27BD001803E00008AF830008B9
-:10711000000439C230E6003F00043B42000718403B
-:10712000240210002CC4002024C8FFE0AF42002C31
-:10713000246300011480000330A900FF00071840F9
-:10714000310600FF0003608024080001019A5821E5
-:107150003C0A000E00C82804016A382111200005ED
-:10716000000530278CE900000125302503E00008E8
-:10717000ACE600008CEE000001C6682403E00008C5
-:10718000ACED000027BDFFE8AFBF0014AFB00010AA
-:107190003C0460008C8508083403F00030A2F00045
-:1071A00050430006240200018C8708083404E000E4
-:1071B00030E6F00010C4001E24020002AF8200403E
-:1071C0003C1060003C0A0200AE0A081424091000BA
-:1071D0003C08000E8E03440003482021AF49002CD8
-:1071E000240501200E000CE0000030218F830040B8
-:1071F000106000043C021691240B0001106B000E7D
-:107200003C023D6C344F0090AE0F44088FBF001419
-:107210008FB000103C0C6000240E10003C0D0200EA
-:1072200027BD0018AD8E442003E00008AD8D081086
-:107230000A000907AF8000403C0218DA344F009082
-:10724000AE0F44088FBF00148FB000103C0C6000DC
-:10725000240E10003C0D020027BD0018AD8E442006
-:1072600003E00008AD8D08100A0008DB24050001CA
-:107270000A0008DB000028213C08080025085FC43C
-:107280002404FFFF010018212402001E2442FFFFF6
-:10729000AC6400000441FFFD246300043C070800C7
-:1072A00024E760408CE5FFFC2404001C2406000158
-:1072B000308A001F01464804248400010009102779
-:1072C0002C8300201460FFFA00A22824ACE5FFFC08
-:1072D0003C05666634A4616E3C06080024C6610065
-:1072E000AF840058AF88009C2404FFFF00C0182121
-:1072F0002402001F2442FFFFAC6400000441FFFD94
-:10730000246300043C0766663C05080024A560C0B1
-:10731000AF86004834E6616EAF8600982404FFFF14
-:1073200000A018212402000F2442FFFFAC640000DB
-:107330000441FFFD246300043C0B66663C06080024
-:1073400024C660403568616EAF8500A4AF880070C8
-:107350002404FFFF00C018212402001F2442FFFF65
-:10736000AC6400000441FFFD246300043C0D66662C
-:107370003C0A0800254A618035AC616EAF860090FA
-:10738000AF8C005C2404FFFF01401821240200039D
-:107390002442FFFFAC6400000441FFFD24630004AD
-:1073A0003C090800252961908D27FFFC2404000674
-:1073B000240500013099001F0325C0042484000126
-:1073C000001878272C8E002015C0FFFA00EF382413
-:1073D000AD27FFFC3C09666624030400240403DC9B
-:1073E00024050200240600663522616E3C08080070
-:1073F00025085CC4AF820074AF830044AF83006C87
-:10740000AF830050AF830084AF8A008CAF840064E8
-:10741000AF85004CAF860054AF840078AF85006024
-:10742000AF86008001001821240200022442FFFFE1
-:10743000AC6000000441FFFD246300042404000349
-:107440002403000C3C0A0800254A5CD0AF8A00687F
-:107450000A0009AE2405FFFF0004188024840001FF
-:10746000006858212C8700C014E0FFFBAD650000C8
-:107470003C0E666635CD616E240C17A024081800FA
-:10748000AF8D0088AF8C009403E00008AF88007CCB
-:107490002484007F000421C200004021000030212C
-:1074A00000003821000028210A0009C5AF8400A08F
-:1074B0001060000624E7000100C4302124A500016B
-:1074C0002CC20BF51440FFFA2CA300663C090800FF
-:1074D0002529618001201821240200032442FFFF96
-:1074E000AC6000000441FFFD2463000410E0001ABA
-:1074F00024E3FFFF0003294210A0000A000020211E
-:107500002406FFFF3C0308002463618024840001FB
-:107510000085502BAC660000250800011540FFFBDC
-:107520002463000430E2001F104000080008688057
-:10753000240C0001004C38040008588001692821FF
-:1075400024E6FFFF03E00008ACA6000001A94021EB
-:107550002409FFFFAD09000003E00008000000005F
-:10756000AF4400283C04000C03442021000528827D
-:107570000A000CE000003021000421803C03600080
-:10758000AC6410080000000000052980AC65100CF8
-:107590000000000003E000088C62100C27BDFFE82B
-:1075A0000080282124040038AFBF00140E0009F524
-:1075B000AFB0001024040E00AF4400283C10000CB3
-:1075C00003502021240500100E000CE000003021A3
-:1075D00003501021AC400000AC40000424040038EB
-:1075E0008FBF00148FB0001024053FFF27BD001887
-:1075F0000A0009F58C430000000421803C03600070
-:10760000AC641008000000008C62100C03E000085D
-:107610000002118227BDFFC8AFB400208F9400681C
-:10762000AFBE0030AFB7002CAFB600280000B821C5
-:107630000080B021241E00C0AFBF0034AFB50024CD
-:10764000AFB3001CAFB20018AFB10014AFB0001060
-:107650000A000A32AFA5003C504000018F94006838
-:1076600027DEFFFF13C00028269400048E9200003E
-:107670003C03080024635FC01240FFF70283102B15
-:107680003C04080024845CC4028410230002A8C0C7
-:10769000000098210A000A412411000100118840CD
-:1076A000122000260000000002B38021025128248D
-:1076B0000200202110A0FFF9267300010E0009FE30
-:1076C000000000000016684032EC000101AC2021EF
-:1076D0000E0009F5020028218F89009426F7000189
-:1076E0008FA6003C3AEB0001316A00012528FFFF1C
-:1076F0000011382702CAB021AF88009416E6FFE7D0
-:1077000002479024AE92000002E010218FBF0034A7
-:107710008FBE00308FB7002C8FB600288FB50024A5
-:107720008FB400208FB3001C8FB200188FB10014EB
-:107730008FB0001003E0000827BD00383C0E0800A1
-:1077400025CE5FC0028E102B0A000A2DAE920000DB
-:1077500027BDFFD8AFB10014AFB00010AFBF0020FD
-:10776000AFB3001CAFB2001800A0882110A0001F0A
-:10777000000480403C13080026735CC40A000A7AA7
-:107780002412000112200019261000010E000A1513
-:1077900002002021000231422444FFA0000618808C
-:1077A0003045001F2C8217A1007318212631FFFFDE
-:1077B0001040FFF400B230048C6900000200202168
-:1077C00024053FFF012640241500FFEE0126382541
-:1077D0000E0009F5AC6700008F8A009426100001A6
-:1077E000254700011620FFE9AF8700948FBF0020D6
-:1077F0008FB3001C8FB200188FB100148FB000102F
-:1078000003E0000827BD00288F85009C00805821D8
-:107810000000402100004821240A001F3C0C080001
-:10782000258C603C3C0D080025AD5FC48CA6000093
-:1078300050C000140000402100AD1023000238C0E9
-:10784000240300010A000AB30000202115000003F0
-:1078500000E41021244820240000482125290001AB
-:10786000512B00132506DFDC106000062484000184
-:1078700000C3702415C0FFF5000318400A000AB1C8
-:107880000000402110AC002624A300040060282141
-:10789000254AFFFF1540FFE5AF85009C512B0004F2
-:1078A0002506DFDC0000402103E000080100102174
-:1078B0000006614230C5001F000C50803C070800E4
-:1078C00024E75FC424040001014730211120000F88
-:1078D00000A420043C05080024A560401480000595
-:1078E0002529FFFF24C6000410C500110000000078
-:1078F000240400018CCF00000004C02700042040B5
-:1079000001F868241520FFF5ACCD00008F990078B0
-:1079100001001021032B482303E00008AF89007801
-:107920003C05080024A55FC40A000ABB00004021F2
-:107930003C06080024C65FC40A000AD424040001DF
-:10794000308800FF240200021102000A2403000311
-:107950001103005C8F8900A4240400041104005F5B
-:1079600024050005110500670000182103E0000848
-:10797000006010218F8900483C0C0800258C6100B4
-:107980003C04080024846180240300201060000F60
-:1079900000005821240D0002240E00033C0F0800B3
-:1079A00025EF61008D27000014E0000B30F9FFFF88
-:1079B000252900040124C02B530000010180482127
-:1079C0002463FFFF5460FFF88D2700000160182139
-:1079D00003E0000800601021132000323C0500FF86
-:1079E00030E200FF004030211040004200005021F2
-:1079F00024050001000020210005C84000A6C02485
-:107A000017000003332500FF14A0FFFB24840001AE
-:107A1000012CC023001828C000AA6021008C50212E
-:107A20003144001F240C0001008C180400031027AF
-:107A300000E23024110D0041AD260000110E004C73
-:107A4000000A1840110D00368F87006C510E005649
-:107A50008F8C0060240D0004110D005A8F8E00845D
-:107A6000240E0005150EFFDA01601821240B1430D6
-:107A700011400006000018218F8400A0246300013B
-:107A8000006A402B1500FFFD016458218F8A008099
-:107A9000AF89008C016018212549FFFF0A000B0BFC
-:107AA000AF89008000E52024000736021080FFD057
-:107AB000240A001800075402314600FF0A000B1385
-:107AC000240A00103C0C0800258C60C03C0408000F
-:107AD000248461000A000AFA240300103C0C080008
-:107AE000258C60403C040800248460C00A000AF928
-:107AF0008F89009000071A02306600FF0A000B13FE
-:107B0000240A00088F89008C3C0C0800258C6180B9
-:107B10003C040800248461900A000AFA240300044B
-:107B2000000A4080250B003024E6FFFF0160182189
-:107B3000AF8900480A000B0BAF86006C000AC982AF
-:107B4000001978803C07080024E760C001E7202185
-:107B5000000A18428C8F00003079001F032C380473
-:107B60000007C02701F860240A000B28AC8C000035
-:107B7000000331420006288000AF28213062001F38
-:107B80008CB8000024630001004CC80400032142AB
-:107B9000001938270004108003073024004F2021EB
-:107BA0000A000B6CACA60000000A68C025AB0032CE
-:107BB000258AFFFF01601821AF8900A40A000B0B82
-:107BC000AF8A0060254B1030AF890090016018210A
-:107BD00025C9FFFF0A000B0BAF8900843086000720
-:107BE0002CC2000610400014000000000006408077
-:107BF0003C030800246359C8010338218CE40000C9
-:107C000000800008000000002409000310A9000EF5
-:107C100000000000240A000510AA000B000000006C
-:107C2000240B000110AB0008000000008F8C00A0A6
-:107C300010AC00050000000003E000080000102167
-:107C40000A000A9900A020210A000AE700C02021AA
-:107C500027BDFFE8308400FF240300021083000BDF
-:107C6000AFBF0010240600031086003A2408000469
-:107C700010880068240E0005108E007F2CAF143091
-:107C80008FBF001003E0000827BD00182CA20030B1
-:107C90001440FFFC8FBF001024A5FFD0000531C2A7
-:107CA000000668803C07080024E7610001A7302136
-:107CB0008CC900000005288230AC001F240B000195
-:107CC000018B50048F840048012A4025ACC8000075
-:107CD0008C83000050600001AF8600488F98006CD4
-:107CE00030AE000124A6FFFF270F000115C00002DF
-:107CF000AF8F006C24A600010006414200082080DE
-:107D0000008718218C79000030C2001F2406000172
-:107D10000046F804033F382410E0FFDA8FBF00105C
-:107D20000005C182001870803C0F080025EF60C07C
-:107D300001CF48218D2B00000005684231A5001FAE
-:107D400000A66004016C502527BD001803E0000860
-:107D5000AD2A00002CA7003014E0FFCA8FBF00102E
-:107D600030B900071723FFC724A8FFCE00086A0216
-:107D7000000D60803C0B0800256B60C0018B30213A
-:107D80008CC40000000828C230AA001F240800018B
-:107D9000014848048F8200A400891825ACC3000064
-:107DA0008C5F000053E00001AF8600A40005704026
-:107DB000000E7942000F28803C04080024846100F2
-:107DC00000A418218C6B000025DF000131CD001FBD
-:107DD000001F514201A86004016C4825000A108070
-:107DE000AC690000004428218CA600008F98006038
-:107DF00033F9001F8FBF00100328380400C778250F
-:107E0000270E000127BD0018ACAF000003E00008FA
-:107E1000AF8E006024A5EFD02CB804001300FF99AA
-:107E20008FBF001000053142000658803C0A080050
-:107E3000254A6040016A30218CC4000030A3001F35
-:107E400024090001006910048F9900900082F82530
-:107E5000ACDF00008F27000050E00001AF860090EB
-:107E60008F8D00848FBF001027BD001825AC000146
-:107E700003E00008AF8C008415E0FF828FBF001084
-:107E80008F8600A0000610400046F821001F210048
-:107E900003E4C8210019384024F8143000B8402BFE
-:107EA0001100FF788FBF001024A4EBD00E00020D4C
-:107EB00000C0282100027942000F70803C0D0800AC
-:107EC00025AD618001CD20218C8B0000304C001F3E
-:107ED00024060001018618048F89008C0163502557
-:107EE000AC8A00008D25000050A00001AF84008CFA
-:107EF0008F9800808FBF001027BD00182708000151
-:107F000003E00008AF88008030A5000724030003C9
-:107F100010A3001028A20004144000082407000247
-:107F20002403000410A300152408000510A8000F66
-:107F30008F8500A003E000080000000014A7FFFDEB
-:107F40000080282114C3FFFB240400020A000BABAD
-:107F500000000000240900050080282110C9FFFB53
-:107F60002404000303E000080000000014C5FFF132
-:107F7000008028210A000BAB24040005240A00011C
-:107F80000080282110CAFFF12404000403E0000847
-:107F90000000000027BDFFE0AFB00010000581C267
-:107FA0002603FFD024C5003F2C6223D024C6007FC7
-:107FB000AFB20018AFB10014AFBF001C309100FF8A
-:107FC000000691C20005298202002021104000080D
-:107FD0002403FFFF0E000A6B0000000002002021B6
-:107FE000022028210E000C590240302100001821E7
-:107FF0008FBF001C8FB200188FB100148FB000101B
-:108000000060102103E0000827BD002027BDFFD835
-:1080100024A2007FAFB3001CAFB20018000299C2C7
-:10802000309200FF24A3003F02402021026028215B
-:10803000AFB10014AFB00010AFBF00200E000B8E28
-:108040000003898200408021004020210220282155
-:1080500014400009000018218FBF00208FB3001CBE
-:108060008FB200188FB100148FB000100060102183
-:1080700003E0000827BD00280E000A1C00000000D5
-:1080800000402821020020211051FFF3001019C0E8
-:108090000E000A6B0000000002002021024028218F
-:1080A0000E000C59026030218FBF00208FB3001CDE
-:1080B0008FB200188FB100148FB00010000018218B
-:1080C0000060102103E0000827BD00283084FFFF76
-:1080D00030A5FFFF1080000700001821308200014A
-:1080E0001040000200042042006518211480FFFBAC
-:1080F0000005284003E000080060102110C00007C0
-:10810000000000008CA2000024C6FFFF24A500048C
-:10811000AC82000014C0FFFB2484000403E00008CC
-:108120000000000010A0000824A3FFFFAC860000A0
-:1081300000000000000000002402FFFF2463FFFF96
-:108140001462FFFA2484000403E000080000000029
-:1081500030A5FFFF8F4201B80440FFFE3C076015C9
-:1081600000A730253C031000AF440180AF400184DC
-:10817000AF46018803E00008AF4301B88F8500D007
-:108180002C864000008018218CA700840087102BCB
-:1081900014400010000000008CA800842D06400050
-:1081A00050C0000F240340008CAA0084008A482B92
-:1081B000512000018CA3008400035A42000B208050
-:1081C0003C05080024A55A400085182103E000085A
-:1081D0008C62000014C0FFF4000000002403400083
-:1081E00000035A42000B20803C05080024A55A4099
-:1081F0000085182103E000088C6200008F8300D006
-:10820000906600D024C50001A06500D08F8500D005
-:10821000906400D090A200D210440017000000002B
-:10822000936C00788F8B00BC318A00FFA16A000C30
-:1082300025490001938700C4312200FF3048007FA8
-:108240001107000B00026827A36200788F4E0178A7
-:1082500005C0FFFE8F9900B0241800023C0F1000EB
-:10826000AF590140A358014403E00008AF4F017823
-:108270000A000D2931A20080A0A000D00A000D1F25
-:108280000000000027BDFFD8AFB200188F9200B8E1
-:10829000AFBF0020AFB3001CAFB00010AFB10014EF
-:1082A0008F9300B48E5900283C1000803C0EFFEFE5
-:1082B000AE7900008E580024A260000A35CDFFFF81
-:1082C000AE7800049251002C3C0BFF9F356AFFFFF3
-:1082D000A271000C8E6F000C3C080040A271000BD4
-:1082E00001F06025018D4824012A382400E830255A
-:1082F000AE66000C8E450004AE6000183C0400FF22
-:10830000AE6500148E43002C3482FFFFA660000887
-:108310000062F824AE7F00108E5900088F9000B0E4
-:10832000964E0012AE7900208E51000C31D83FFFDE
-:1083300000187980AE7100248E4D001401F0602188
-:1083400031CB0001AE6D00288E4A0018000C41C2EE
-:10835000000B4B80AE6A002C8E46001C01093821B0
-:10836000A667001CAE660030964500028E440020D1
-:10837000A665001EAE6400349243003330620004F0
-:1083800054400005924600008F8300D08C7F007C13
-:10839000AE7F0030924600008F8500BCA0A6000092
-:1083A000924400333082000250400007924E000198
-:1083B0008F8700BC240AFF8090E90000012A402535
-:1083C000A0E80000924E00018F8D00BC2409FFBF81
-:1083D0002404FFDFA1AE00018F8A00BC914C000D88
-:1083E000318B007FA14B000D8F8600BC90C8000D23
-:1083F00001093824A0C7000D8F9100BC8E650014C0
-:108400009223000D2CA200010002F9400064C82450
-:10841000033FC025A238000D8F8800BC9650001283
-:108420008F8700D0A51000028E45000490ED00BC9F
-:1084300030AF0003000F702331CC000300AC1021DB
-:1084400031AB0002156000022444003424440030A3
-:1084500090F100BC00B18024320F000415E000024E
-:1084600024830004008018218F8900AC240A0002B4
-:10847000AD030004A12A00009248003F8F8700ACA2
-:10848000A0E800018F9100AC9246003F8E440004AA
-:10849000A62600029765003C0E000CF630B0FFFFE8
-:1084A00000021380005020253C0342000083F82581
-:1084B000AE3F00048F8500AC8E590038ACB900186F
-:1084C0008E580034ACB8001CACA0000CACA000105E
-:1084D000A4A00014A4A00016A4A00020A4A0002220
-:1084E000ACA000248E620014504000012402000160
-:1084F0008FBF00208FB3001C8FB200188FB1001403
-:108500008FB00010ACA200080A000D1627BD00288D
-:108510008F8600D027BDFFD0AFBF002CAFB600289C
-:10852000AFB50024AFB40020AFB3001CAFB2001849
-:10853000AFB10014AFB0001094C300E094C200E2E9
-:10854000104300412405FFFF3C16000E90C400D0EC
-:1085500090C800D1309200FF310400FF0244382B54
-:1085600010E0004426490001108900378F9800B0C0
-:108570003C0508008CA5005C2414FF8000B8602135
-:1085800001946824AF4D002C94CA00E2318B007F27
-:10859000017A482131447FFF013640210004104018
-:1085A0000048A82196A700003C1F08008FFF005834
-:1085B00030F53FFF0015198003E3C8210319882116
-:1085C0003233007F027A782102348024AF50002CAD
-:1085D00001F69821926E000D31C5000410A00048EC
-:1085E0000000000094C300E294C300E294D800E2CB
-:1085F00024048000307F7FFF27F9000133317FFFA3
-:108600000304802402117825A4CF00E294CE00E276
-:108610003C1208008E52006031D47FFF129200DFBE
-:10862000000000008E720018000028212646FFFF7F
-:10863000AE66002C8F8600D094C800E094C900E29A
-:108640001528FFC2000000008FBF002C8FB6002845
-:108650008FB500248FB400208FB3001C8FB2001898
-:108660008FB100148FB0001000A0102103E00008AB
-:1086700027BD003090CD00D2264A000131AC00FF6A
-:10868000008C5821116AFFF08F9800B03C0508005B
-:108690008CA5005C2414FF8000B86021019468243C
-:1086A000AF4D002C94CA00E2318B007F017A482143
-:1086B00031447FFF01364021000410400048A821CA
-:1086C00096A700003C1F08008FFF005830F53FFFC1
-:1086D0000015198003E3C821031988213233007F74
-:1086E000027A782102348024AF50002C01F69821C0
-:1086F000926E000D31C5000414A0FFBA0000000006
-:108700008E6600100012C0C08E6E003000129140C4
-:1087100002587821036F582100CE6823256C008809
-:1087200024020002AE6D0010AF8C00ACA162008884
-:10873000976A003C8E6400308F9100AC0E000CF6FE
-:108740003150FFFF00022380009048253C03420087
-:1087500001234025AE2800048E6700048F8C00ACF6
-:108760008E7F0000240D0008AD87001CAD9F00180F
-:10877000AD80000CAD8000109265000A30B900FF9A
-:10878000A5990014967800083C05000CA5980016E1
-:108790009271000A322F00FFA58F0020967000080A
-:1087A00024110005A5900022AD800024926E000BDC
-:1087B0002410C00031C600FFA5860002A18D000173
-:1087C0008E6B00308F8200AC8F8800B0AC4B0008FD
-:1087D0003C0A08008D4A0054014820210094482496
-:1087E000AF4900283C0308008C630054006838211E
-:1087F00030FF007F03FAC8210325C02102587821E9
-:10880000AF8F00BCAF9800C0A1F100008F8B00BCFF
-:108810002403FFBF2405FFDF956E000201D0A024D2
-:1088200002959025A57200029166000230CD003FAE
-:1088300035AC0040A16C00028F8800BC8F8200D054
-:108840003C0C7FFFAD0000048C4A007C358BFFFFA1
-:108850003C028000AD0A00089104000D3089007FC1
-:10886000A109000D8F9F00BC93F5000D02A33824D1
-:10887000A3E7000D8F9100BC9239000D0325C024A1
-:10888000A238000D8E6F00348F8D00BCADAF00108C
-:108890008E6E002C8E70003001D0A023ADB4001479
-:1088A00091B200183246007FA1A600188F8700BC45
-:1088B0008E6A00308CE40018014B4824008240246A
-:1088C0000109A825ACF500189263000AA0E3001C7A
-:1088D000967F00088F8500BC8F9900D0A4BF001E32
-:1088E0008E7000308E6400300E00020D8F250084E3
-:1088F0008F8500D0000289400002C10090AE00BC0C
-:10890000023878210040302131D400021280000367
-:10891000020F80210002A8800215802190B200BCC5
-:1089200032540004128000020006C880021980211F
-:108930008E6F00308F8B00BC2406800031EE000368
-:10894000000E682331AC0003020C1021AD6200045C
-:1089500094A400E294AA00E294A300E231507FFFC5
-:108960002604000130897FFF006640240109882524
-:10897000A4B100E294A700E23C1308008E730060EB
-:1089800030FF7FFF13F30012000000000E000D16F1
-:10899000000000000A000E240000282194CD00E20F
-:1089A00001A46024A4CC00E290CB00E290C200E2DB
-:1089B000316A00FF000A49C200092027000441C0B3
-:1089C0003055007F02A838250A000E20A0C700E21B
-:1089D00094B100E202263824A4A700E290BF00E28E
-:1089E00090B400E233F300FF0013C9C200199027CE
-:1089F0003298007F0012A9C0031530250E000D1615
-:108A0000A0A600E20A000E24000028213084FFFF07
-:108A100030A5FFFFAF440018AF45001C03E000087D
-:108A20008F42001427BDFFB0AFB000288F9000D058
-:108A3000AFB40038AFBF004CAFBE0048AFB7004482
-:108A4000AFB60040AFB5003CAFB30034AFB20030BA
-:108A5000AFB1002CA7A00014920600D1920500D05F
-:108A60003094FFFF30C400FF30A300FF0064102BE0
-:108A7000A7A0001E10400071AFA00010920900D006
-:108A80000014982B312800FF0088382324F2FFFFC0
-:108A90000012882B0233782451E000758FB2001049
-:108AA00096180012961900100014F4000319B82348
-:108AB0000017B400001614030282A82A16A00002B0
-:108AC000001E2403004020210244F82B13E0000282
-:108AD00000801821024018210003340000061C0306
-:108AE0003065FFFF2CA200091440000200609821AD
-:108AF000241300088E090008001359808E08000C0A
-:108B00003164FFFF3C0A0010008A3825274A040020
-:108B1000AF490038AF8A00B8AF48003CAF470030DB
-:108B20000000000000000000000000000000000045
-:108B30000000000000000000000000000000000035
-:108B40008F4D000031AC00201180FFFD0013702A12
-:108B500001D110240000A821104001C00000000035
-:108B60008F9800B03C0B08008D6B00542411FF80DF
-:108B7000921E00D00178202100911024921900D07B
-:108B8000AF4200288D4500103C0608008CC60058F6
-:108B90003C1708008EF7005430A73FFF00071980EC
-:108BA00000C34021030820210091F824920B00D03B
-:108BB000AF5F002C9148000033D600FF332F00FF39
-:108BC00002F8702100166140000F68C031C9007FB3
-:108BD000018D3821013A2821316300FF3086007F62
-:108BE0003C02000C00A2B021000389400367C821A9
-:108BF00000DAF8213108003F3C1E000E0236B82191
-:108C00002738008803FE88212D0F0008AF9800AC9C
-:108C1000AF9700BCAF9600C011E0018FAF9100B4D8
-:108C2000000868803C0E080025CE59E001AE6021A6
-:108C30008D8900000120000800000000920E00D283
-:108C4000920D00D00014982B31CA00FF31AC00FF08
-:108C5000008C5823014B20212492FFFF0012882B07
-:108C60000233782415E0FF8E000000008FB2001060
-:108C70008FBF004C8FBE00483A4200018FB70044BE
-:108C80008FB600408FB5003C8FB400388FB30034EE
-:108C90008FB200308FB1002C8FB0002803E00008A5
-:108CA00027BD0050915800013317002012E0020444
-:108CB00024160001921F00BC0000B02133F900010E
-:108CC0001320000D241E00018D4800148E03008423
-:108CD0000103B02B16C00002010030218E06008473
-:108CE0008E05006400C5382B14E0000200C020216E
-:108CF0008E0400640080B0218D4200148E0B00644D
-:108D0000004B302B14C00002004020218E04006470
-:108D10000096B82356E00001241E0002025E202BBC
-:108D200014800148000018218D5900388E2F000C46
-:108D30003C180080AE3900008D5000343C0EFF9F7F
-:108D400001F86025AE3000049149003F35CDFFFFAA
-:108D5000018D20243C0A00203C0BFFEFA229000BD0
-:108D6000008A38253562FFFF00E228243C0600080F
-:108D70008F8700B800A6C825AE39000C8CE300141C
-:108D8000AE2000183C08FFFBAE2300148CF800183E
-:108D9000351FFFFF033F7024AE38001C8CEF000826
-:108DA00002D78021AE2F00248CED000CAE30002CB9
-:108DB000AE2E000CAE2D0020AE200028A6200038DC
-:108DC000A620003A8CEC001401964823013750236A
-:108DD00011400011AE2A001090EE003D8E2C0004D0
-:108DE0008E240000000E6900018D28210000502112
-:108DF00000AD302B008A582101661021AE250004F9
-:108E0000AE22000090E3003DA223000A8F8800B844
-:108E1000951F0006A63F00088F8B00AC24060002B9
-:108E200002C02021A16600009765003C8F9000AC35
-:108E300030A2FFFF0E000CF6AFA200208FA300208F
-:108E4000000243808F8500B80103C8253C1F420003
-:108E5000033FC025AE1800048F8400AC8CAF0038EF
-:108E6000AC8F00188CB00034AC90001CAC80000CAF
-:108E7000AC800010A4800014A4800016A480002000
-:108E8000A4800022AC80002490A7003FA4870002A9
-:108E900012C00210240D000152E0000290A2003D19
-:108EA00090A2003E244A0001A08A00018F8400ACF9
-:108EB000AC9600088F8300D024070034906F00BC6C
-:108EC00031EE000251C00001240700308F8200B84B
-:108ED0008F9900BC906800BC905F000024100004D3
-:108EE00032CF0003A33F00008F9800B88F8C00BCE6
-:108EF000020F7023930D00012405C00031CA000346
-:108F0000A18D00018F9000BC8F8900B800F6382138
-:108F1000960400029526001200EA382100855824A4
-:108F200030C33FFF01631025A6020002921F00021A
-:108F30003108000433F9003F37380040A21800021E
-:108F400012C000028F8500BC00E838218F8600D057
-:108F5000ACA70004241FFFBF8CC3007C2ECB0001F4
-:108F6000240FFFDFACA3000890A8000D000B6940A0
-:108F70003102007FA0A2000D8F9000BC9219000D5D
-:108F8000033FC024A218000D8F8A00BC914E000D33
-:108F900001CF6024018D4825A149000D8F8600B8BE
-:108FA0008F8B00BC8CC70020AD6700108CC50024DF
-:108FB000AD6500148CC40028AD6400188CC3002C6F
-:108FC0000E000D16AD63001C2408000257C8009C5B
-:108FD0008F9000D08F8F00D08F8A00C002E02021B8
-:108FE00091E800D091EB00D091E700D0311000FF64
-:108FF000316E00FF00106940000E28C001A5182145
-:1090000030E900FF0363C8210009314000CAF8219C
-:1090100027220088AF8200ACAF9F00BCA33E00882F
-:109020000E000CF68F9000AC8FB800200002638019
-:109030003C0F4200019840258F8C00B8010F582545
-:10904000AE0B00048D8400388F8B00AC000028210B
-:1090500000053900AD6400188D8E00343C0F7FFF91
-:1090600035E8FFFFAD6E001C9183003E8D69001C4A
-:109070008D6600180003510000036F02012AC02111
-:1090800000ED1025030AF82B00C2C821033F802100
-:10909000AD78001CAD700018AD60000CAD60001024
-:1090A0009184003E241F00052410C000A564001414
-:1090B000958E000402E8402402E02021A56E0016EF
-:1090C0009185003EA5650020958D0004A56D0022C8
-:1090D000AD6000249187003FA56700029183003EA8
-:1090E0009189003D0123502325460001A16600011E
-:1090F0008F8200AC8F9900BCAC570008A33F0000E2
-:109100008F8A00BC8F9800B8954F0002970E00120E
-:109110002418FFBF020F682431C53FFF01A5382581
-:10912000A5470002914C00022405FFDF3189003F72
-:1091300035230040A14300028F9900BC8F8600D0E8
-:109140002409FFFFAF2000048CCB007C2403FF80A8
-:10915000AF2B00089322000D3C0B8000305F007F96
-:10916000A33F000D8F8E00BC91D0000D0218782413
-:10917000A1CF000D8F8C00BC918D000D01A538246E
-:10918000A187000D8F8600BCACC90010ACD60014BE
-:1091900090CA00180143B025A0D600188F8F00BCDC
-:1091A0008F9800B88DE20018004BF82403E8C8251A
-:1091B000ADF900189310003EA1F0001C8F8E00B88E
-:1091C0008F8D00BC8F8700D095C50004A5A5001E1B
-:1091D0000E00020D8CE500848F8700D000026140F4
-:1091E0000002210090EA00BC0184482100402821AF
-:1091F0003156000212C0000302E930210002B080A3
-:1092000000D6302190EC00BC3184000410800003B3
-:1092100032EA00030005C08000D830212409000490
-:109220008F9700BC012A1023305F000300DFC821A4
-:10923000AEF900040E000D16A62500388F9000D060
-:1092400003C01821146000020060B02100009021CA
-:1092500056C000868F9700B80012882B9609001020
-:10926000029550233C14002002A91021A6020010F0
-:10927000AF5400303154FFFF00000000961300107F
-:10928000961F001213F30011000000008E17000C4F
-:109290008E0C00080015C98002F94021001927C36F
-:1092A0000119B02B0184782101F65821AE08000C79
-:1092B000AE0B00080014A82B023580241200FE6BB0
-:1092C0008F9000D00A000F3F00000000960B0014A2
-:1092D0008E0500043163FFFF000370C000AE38212B
-:1092E000AF47003C8E0600048F4D003C00CDF023BC
-:1092F0001BC00036000000008E080000250200019F
-:109300003C16001036CF0008AF420038AF4F003097
-:10931000000000000000000000000000000000004D
-:10932000000000000000000000000000000000003D
-:109330008F440000308C00201180FFFD00000000F1
-:109340008F5904003C170020AE1900088F55040403
-:10935000AE15000CAF570030000000003C060800BE
-:109360008CC600442418000110D800D3000000006F
-:10937000960700123C0508008CA5004000A7682154
-:10938000A60D0012961E001427C90001A60900149C
-:10939000960200143044FFFF5486FFC70014A82B28
-:1093A00030A5FFFF0E000F1AA60000143C030800B2
-:1093B0008C630024960500120043702300AE302316
-:1093C000A60600120A0011450014A82B8E02000008
-:1093D0000A0011583C16001091560001241000019B
-:1093E0000016784215F0001C97A8001E8D5F00142F
-:1093F0002411C00033FE3FFF0111C8243C180800AF
-:109400008F180060033EB82532E53FFF00B8502BAF
-:1094100011400011A7B7001E3C1008008E10005824
-:109420008F8F00B000057180240CFF80020F68212F
-:1094300001AE48213124007F012C5824009A2821B4
-:109440003C02000EAF4B002C00A2302190C7000D53
-:1094500034E30004A0C3000D0E000D38000000002E
-:109460008F9000D0240300018F9700B826B9000127
-:109470000019AC00024390230015AC0326F800400D
-:1094800002B3202A0012882B240C00010300502173
-:1094900000911024AF9800B80A000F6DAFAC001017
-:1094A000955600128F8400B032C5FFFF0E000CEB02
-:1094B000A7B600148F9000D00A0011B10000182147
-:1094C0008D590038A620000824040003AE3900009E
-:1094D0008D570034A220000A8F9800B8AE370004E0
-:1094E0003C0F0080930C003FA224000C8E28000C3F
-:1094F0003C0BFF9FA22C000B010F1825356EFFFFC0
-:109500003C05FFEF8F9700B8006E682434A7FFFF7B
-:1095100001A73024AE26000C8EFE001496FF001228
-:109520008F8200B0AE3E00108EF00014AE20001806
-:10953000AE200020AE300014AE2000248EE90018CA
-:1095400033F03FFF00105180AE2900288EF900084B
-:109550000142C02133EC0001AE3900308EEB000C2B
-:109560008F8500AC001879C2000C238001E44021F3
-:10957000240E0002A628001CA6200036AE2B002CCC
-:10958000A0AE00009767003C8F8A00AC3C0342000D
-:1095900030EDFFFF01A33025AD4600048F9E00B8DB
-:1095A000240200012408C0008FD1003824060034B2
-:1095B000AD5100188FC90034AD49001CAD40000CFE
-:1095C000AD400010A5400014A5400016A5400020A5
-:1095D000A5400022AD400024A5560002A142000192
-:1095E0008F9F00AC8F9900B88F9800BCAFF6000831
-:1095F00093370000A31700008F8C00B88F8F00BC3A
-:1096000091840001A1E400018F8D00BC95AB0002A4
-:109610000168702401D02825A5A5000291A70002A9
-:1096200030E3003FA1A300028F8300D08F8400BCF1
-:10963000907100BC323E000253C00001240600308D
-:10964000AC8600048C6F007C2403FFBFAC8F000845
-:109650009088000D310B007FA08B000D8F8700BC20
-:1096600090EE000D01C32824A0E5000D8F9E00BCE4
-:1096700093CD000D35A60020A3C6000D8F8A00B83B
-:109680008F9100BC8D500020AE3000108D49002419
-:10969000AE2900148D420028AE2200188D5F002CE8
-:1096A000AE3F001C0E000D16000000008F9000D091
-:1096B0000A00112B02C01821960A00123C1F080054
-:1096C0008FFF002403EA9821A61300120A00114517
-:1096D0000014A82BA08D00018F8900AC240C000180
-:1096E000AD2C00080A0010458F8300D027BDFFE095
-:1096F0003C1808008F180050AFB00010AFBF001822
-:10970000AFB10014AF8400B09371007403047821EA
-:109710002410FF8031EE007F3225007F01F05824B5
-:1097200001DA68213C0C000AA38500C401AC2821A1
-:10973000AF4B002494A900109768000690A6006221
-:1097400000803821240200300109202330C300F0BA
-:10975000AF8500D0106200193090FFFF90AE00621C
-:10976000240DFFF0240A005001AE6024318B00FF6D
-:10977000116A002F0000000016000007241F0C00D3
-:10978000AF5F00248FB100148FBF00188FB000109E
-:1097900003E0000827BD00200E000F20020020215A
-:1097A000241F0C00AF5F00248FB100148FBF00187E
-:1097B0008FB0001003E0000827BD002094A200E055
-:1097C00094A400E290BF0113008218263079FFFFB5
-:1097D00033E700C014E000092F3100011600003803
-:1097E000000000005620FFE6241F0C000E000DDBD9
-:1097F000000000000A001277241F0C001620FFDE74
-:10980000000000000E000DDB000000001440FFDC33
-:10981000241F0C00160000228F8300D090690113D2
-:109820003122003FA06201130A001277241F0C00AE
-:1098300094AF00D48F8600D400E0282124040005D2
-:109840000E000C7C31F0FFFF1440000524030003E0
-:10985000979100E6000018212625FFFFA78500E666
-:109860008F5801B80700FFFE3C196013AF4001801C
-:10987000241F0C00AF500184007938253C101000E3
-:10988000AF4701888FB10014AF5001B8AF5F00241B
-:109890008FB000108FBF001803E0000827BD002024
-:1098A0000E000F20020020215040FFB5241F0C00A5
-:1098B0008F8300D0906901130A0012A03122003F6B
-:1098C0000E000F20020020211440FFAD241F0C00C9
-:1098D000122000078F8300D0906801133106003FEB
-:1098E00034C20040A06201130A001277241F0C004A
-:1098F0000E000DDB000000005040FFA1241F0C00F3
-:109900008F8300D0906801133106003F0A0012D007
-:1099100034C20040AF9B00C803E00008AF8000ECF9
-:109920003089FFFF000940422D02004100092980D3
-:10993000144000020009504024080040000879400B
-:109940000008C0C001F85821256701A800EF702168
-:1099500025CC007F240DFF80018D18240065302167
-:1099600000CA282125640088240A00883C010800D8
-:10997000AC2A004C3C010800AC240050AF8500D458
-:109980003C010800AC2900603C010800AC280064E0
-:109990003C010800AC2700543C010800AC230058EF
-:1099A0003C010800AC26005C03E000080000000059
-:1099B000308300FF30C6FFFF30E400FF8F4201B864
-:1099C0000440FFFE00034C00012438253C086000E1
-:1099D00000E820253C031000AF450180AF4601841C
-:1099E000AF44018803E00008AF4301B88F86001C34
-:1099F0003C096012352700108CCB00043C0C600E33
-:109A000035850010316A00062D480001ACE800C41D
-:109A10008CC40004ACA431808CC2000894C3000242
-:109A2000ACA2318403E00008A78300E43C030800F3
-:109A30008C6300508F8400E88F86001C2402FF8016
-:109A40000064C0210302C824AF5900288CCD000453
-:109A50003305007F00BA78213C0E000C01EE28216E
-:109A6000ACAD00588CC80008AF8500D03C07601230
-:109A7000ACA8005C8CCC001034E80010ACAC000C3E
-:109A80008CCB000CACAB000894AA00143C0208007C
-:109A90008C42004425490001A4A9001494A4001498
-:109AA0003083FFFF106200178F8400D03C0A08004B
-:109AB0008D4A0040A4AA00128CCE0018AC8E00245F
-:109AC0008CCD0014AC8D00208CC70018AC87002C06
-:109AD0008CCC001424060001AC8C00288D0B00BC3B
-:109AE0005166001A8D0200B48D0200B8A482003ABB
-:109AF000948F003AA48F003C948800D403E00008BF
-:109B00003102FFFF3C0908008D290024A4A00014A5
-:109B10008F8400D0A4A900128CCE0018AC8E002433
-:109B20008CCD0014AC8D00208CC70018AC87002CA5
-:109B30008CCC001424060001AC8C00288D0B00BCDA
-:109B40005566FFEA8D0200B88D0200B4A482003A87
-:109B5000948F003AA48F003C948800D403E000085E
-:109B60003102FFFF8F86001C3C0C08008D8C0050DA
-:109B7000240BFF808CCD00083C03000C000D51C06D
-:109B8000018A4021010B4824AF8A00E8AF49002830
-:109B900090C700073105007F00BA1021004328213B
-:109BA00030E400041080002FAF8500D090CF000774
-:109BB00031EE000811C0003C000000008CD9000C00
-:109BC0008CC400140324C02B1300002600000000E6
-:109BD0008CC2000CACA200648CCD00182402FFF8EB
-:109BE000ACAD00688CCC0010ACAC00808CCB000C11
-:109BF000ACAB00848CCA001CACAA007C90A900BC51
-:109C000001224024A0A800BC90C3000730670008D0
-:109C100010E000048F8500D090AF00BC35EE00014D
-:109C2000A0AE00BC90D90007333800011300000F2C
-:109C30008F8400D024070020908200BC34490002A9
-:109C4000A08900BC8F8400D090880062310300F0AE
-:109C500014670006240A0034AC8A00C00A0013B25C
-:109C6000000000000A00138C8CC2001490CB000787
-:109C70003166000210C0000500000000908D00BC9D
-:109C800035AC0004A08C00BC8F8400D090980113E8
-:109C9000330F003FA08F01138F8E00D095C500D4E5
-:109CA00003E0000830A2FFFFACA000640A00138D9F
-:109CB0000000000027BDFFD8AFB000108F90001C3F
-:109CC000AFBF0024AFB40020AFB20018AFB1001492
-:109CD000AFB3001C9613000E3C07600A3C146006EC
-:109CE0003264FFFF369300100E0012DF34F40410CC
-:109CF0008F8400D43C11600E0E0009BB3631001079
-:109D0000920E00153C0708008CE700603C126012C0
-:109D100031CD000FA38D00F08E0E00048E0D0008D3
-:109D200096080012961F00109619001A9618001E29
-:109D3000960F001C310CFFFF33EBFFFF332AFFFFB0
-:109D40003309FFFF31E6FFFF3C010800AC2B004068
-:109D50003C010800AC2C00243C010800AC2A004463
-:109D6000AE293178AE26317C92020015960300169A
-:109D700036520010304400FF3065FFFF3C060800FB
-:109D80008CC60064AE243188AE4500B4920800143D
-:109D900096190018241F0001011FC004332FFFFF74
-:109DA0003C0508008CA50058AE5800B8AE4F00BC6A
-:109DB000920C0014AF8E00D8AF8D00DC318B00FF09
-:109DC000AE4B00C0920A0015AE670048AE66004C6C
-:109DD000314900FFAE4900C8AE65007C3C03080075
-:109DE0008C6300503C0408008C84004C3C08080044
-:109DF0008D0800543C0208008C42005C8FBF002498
-:109E0000AE6300808FB00010AE8300748FB3001C6F
-:109E1000AE22319CAE4200DCAE2731A0AE2631A48A
-:109E2000AE24318CAE233190AE283194AE253198DA
-:109E3000AE870050AE860054AE8500708FB100141E
-:109E4000AE4700E0AE4600E4AE4400CCAE4300D0E6
-:109E5000AE4800D4AE4500D88FB400208FB20018B1
-:109E600003E0000827BD002827BDFFE0AFB10014C4
-:109E7000AFBF0018241100010E000865AFB000103C
-:109E800010510005978400E6978300CC0083102BC7
-:109E9000144000088F8500D4240700028FBF0018EB
-:109EA0008FB100148FB0001000E0102103E0000813
-:109EB00027BD00200E000C9A24040005AF8200E8A4
-:109EC0001040FFF6240700020E0008698F90001C66
-:109ED000979F00E68F9900E88F8D00C827EF00015B
-:109EE000240E0050AF590020A78F00E6A1AE00005D
-:109EF0003C0C08008D8C00648F8600C8240A80000A
-:109F0000000C5E00ACCB0074A4C0000694C9000A2B
-:109F1000241FFF803C0D000C012AC024A4D8000A95
-:109F200090C8000A24182000011F1825A0C3000AA9
-:109F30008F8700C8A0E000788F8500C80000382116
-:109F4000A0A000833C0208008C4200508F8400E8EF
-:109F50000044782101FFC824AF590028960B000265
-:109F600031EE007F01DA6021018D3021A4CB00D4D5
-:109F7000960A0002AF8600D03C0E00042549240159
-:109F8000A4C900E68E080004ACC800048E030008D3
-:109F9000ACC30000A4C00010A4C00014A0C000D036
-:109FA0008F8500D02403FFBFA0A000D13C0408008F
-:109FB0008C8400648F8200D0A04400D28E1F000CDD
-:109FC0008F8A00D0978F00E4AD5F001C8E190010BF
-:109FD00024100030AD590018A5400030A5510054A0
-:109FE000A5510056A54F0016AD4E0068AD58008033
-:109FF000AD580084914D006231AC000F358B0010DC
-:10A00000A14B00628F8600D090C900633128007F89
-:10A01000A0C800638F8400D02406FFFF90850063F2
-:10A0200000A31024A08200638F9100D000E01021D3
-:10A03000923F00BC37F90001A23900BC8F8A00D0E2
-:10A04000938F00F0AD580064AD5000C0914E00D326
-:10A05000000F690031CC000F018D5825A14B00D3B2
-:10A060008F8500D08F8900DCACA900E88F8800D8EC
-:10A070008FBF00188FB100148FB0001027BD0020D3
-:10A08000ACA800ECA4A600D6A4A000E0A4A000E226
-:10A0900003E000080000000027BDFFE0AFB00010A3
-:10A0A0008F90001CAFB10014AFBF00188E190004D0
-:10A0B0003C1808008F180050240FFF80001989C039
-:10A0C0000238702131CD007F01CF602401BA5021C8
-:10A0D0003C0B000CAF4C0028014B4021950900D4EB
-:10A0E000950400D68E0700043131FFFFAF8800D001
-:10A0F0000E000933000721C08E0600048F8300C8BC
-:10A10000000629C0AF4500209064003E3082004028
-:10A11000144000068F8400D0341FFFFF948300D6C4
-:10A120003062FFFF145F000400000000948400D63A
-:10A130000E0008C83084FFFF8E0500040220302185
-:10A140008FBF00188FB100148FB0001024040022BC
-:10A1500000003821000529C00A00130327BD002094
-:10A1600027BDFFE0AFB100143091FFFFAFB000108A
-:10A17000AFBF00181220001D000080218F86001C38
-:10A180008CC500002403000600053F0200051402F0
-:10A1900030E4000714830015304500FF2CA80006AA
-:10A1A0001100004D000558803C0C0800258C5A0019
-:10A1B000016C50218D4900000120000800000000C2
-:10A1C0008F8E00EC240D000111CD0059000000001D
-:10A1D000260B00013170FFFF24CA00200211202B42
-:10A1E000014030211480FFE6AF8A001C02001021DC
-:10A1F0008FBF00188FB100148FB0001003E000086B
-:10A2000027BD0020938700CE14E0003824040014FA
-:10A210000E0013C4000000008F86001C2402000101
-:10A220000A00150BAF8200EC8F8900EC24080002B5
-:10A230001128003B240400130000282100003021D5
-:10A24000240700010E001303000000000A00150B94
-:10A250008F86001C8F8700EC2405000214E5FFF6B2
-:10A26000240400120E001370000000008F8500E827
-:10A2700000403021240400120E0013030000382196
-:10A280000A00150B8F86001C8F8300EC241F00032F
-:10A29000147FFFD0260B00010E00132200000000E7
-:10A2A0008F8500E8004030212402000224040010C1
-:10A2B00000003821AF8200EC0E0013030000000004
-:10A2C0000A00150B8F86001C8F8F00EC24060002FD
-:10A2D00011E6000B000000002404001000002821FB
-:10A2E000000030210A001528240700010000282161
-:10A2F0000E001303000030210A00150B8F86001C8E
-:10A300000E00143100000000144000128F99001C50
-:10A310008F86001C240200030A00150BAF8200EC9C
-:10A320000E0014BD000000000A00150B8F86001CF3
-:10A330000E00131200000000240200022404001486
-:10A340000000282100003021000038210A001545B6
-:10A35000AF8200EC0040382124040010973800023E
-:10A36000000028210E0013033306FFFF0A00150B1F
-:10A370008F86001C8F8400C83C077FFF34E6FFFFF8
-:10A380008C8500742402000100A61824AC8300749C
-:10A3900003E00008A082000510A000362CA2008077
-:10A3A000274A04003C0B00052409008010400007E8
-:10A3B0002408008030A6000F00C540212D03008135
-:10A3C0001460000200A0482124080080AF4B003038
-:10A3D0000000000000000000000000001100000963
-:10A3E00000003821014030218C8D000024E700045A
-:10A3F00000E8602BACCD0000248400041580FFFA37
-:10A4000024C600040000000000000000000000005E
-:10A410003C0E0006010E3825AF470030000000005A
-:10A4200000000000000000008F4F000031E8001025
-:10A430001100FFFD000000008F42003C8F43003CF4
-:10A440000049C8210323C02B1300000400000000B2
-:10A450008F4C003825860001AF4600388F47003CFE
-:10A4600000A9282300E96821AF4D003C14A0FFCECD
-:10A470002CA2008003E000080000000027BDFFD0F0
-:10A480003C020002AFB100143C11000CAF45003893
-:10A49000AFB3001CAF46003C00809821AF420030B3
-:10A4A00024050088AF44002803512021AFBF0028B5
-:10A4B000AFB50024AFB40020AFB200180E00157D78
-:10A4C000AFB000103C1F08008FFF004C3C18080084
-:10A4D0008F1800642410FF8003F3A82132B9007F95
-:10A4E00002B078240018A0C0033A702100189140EF
-:10A4F00001D12021AF4F00280E00157D02542821E4
-:10A500003C0D08008DAD00502405012001B35821F9
-:10A51000316C007F01705024019A482101312021C3
-:10A520000E00157DAF4A00283C0808008D08005435
-:10A530003C0508008CA500640113382130E6007F3B
-:10A5400000F0182400DA202100912021AF430028D8
-:10A550000E00157D000529403C0208008C42005881
-:10A560003C1008008E1000601200001C005388216F
-:10A570002415FF800A0016003C14000C3226007FD0
-:10A580000235182400DA202102402821AF43002898
-:10A59000009420210E00157D2610FFC01200000F30
-:10A5A000023288212E05004110A0FFF42412100071
-:10A5B0003226007F001091800235182400DA202115
-:10A5C00002402821AF430028009420210E00157D71
-:10A5D000000080211600FFF3023288213C0B0800A6
-:10A5E0008D6B005C240AFF8024050002017340216A
-:10A5F000010A4824AF4900283C0408009484006202
-:10A600003110007F021A88213C07000C0E000CCA92
-:10A610000227982100402821026020218FBF0028B6
-:10A620008FB500248FB400208FB3001C8FB20018A8
-:10A630008FB100148FB000100A00157D27BD0030C7
-:10A640008F83001C8C620004104000030000000097
-:10A6500003E00008000000008C6400108C65000816
-:08A660000A0015B68C66000C1F
-:08A66800000000000000001BCF
-:10A670000000000F0000000A0000000800000006B3
-:10A6800000000005000000050000000400000004B8
-:10A6900000000003000000030000000300000003AE
-:10A6A00000000003000000020000000200000002A1
-:10A6B0000000000200000002000000020000000292
-:10A6C0000000000200000002000000020000000282
-:10A6D0000000000200000002000000020000000272
-:0CA6E0000000000100000001000000016B
-:04A6EC0008000F58FB
-:10A6F00008000DB008000FEC0800109408000F804F
-:10A7000008000FC0080011CC08000DCC080011F0A3
-:10A7100008000E1C08001634080015DC08000DCCDB
-:10A7200008000DCC08000DCC0800127C0800127C3B
-:10A7300008000DCC08000DCC0800158008000DCCD9
-:10A7400008000DCC08000DCC08000DCC080013F05B
-:10A7500008000DCC08000DCC08000DCC08000DCC75
-:10A7600008000DCC08000DCC08000DCC08000DCC65
-:10A7700008000DCC08000DCC08000DCC08000DCC55
-:10A7800008000DCC08000DCC08000FE008000DCC2F
-:10A7900008000DCC0800153008000DCC08000DCCC9
-:10A7A00008000DCC08000DCC08000DCC08000DCC25
-:10A7B00008000DCC08000DCC08000DCC08000DCC15
-:10A7C00008000DCC08000DCC08000DCC08000DCC05
-:10A7D00008000DCC08000DCC08000DCC0800145C5E
-:10A7E00008000DCC08000DCC08001370080012E022
-:10A7F00008002E9408002E9C08002E6408002E707D
-:10A8000008002E7C08002E88080046B408003F008F
-:10A8100008004634080046B4080046B4080044B4B2
-:10A82000080046B4080046FC08005524080054E41B
-:10A83000080054B008005484080054600800541CF8
-:10A840000A000C7600000000000000000000000D6F
-:10A85000727870352E302E306A3600000500000305
-:10A8600000000000000000010000000000000000E7
-:10A8700000000000000000000000000000000000D8
-:10A8800000000000000000000000000000000000C8
-:10A8900000000000000000000000000000000000B8
-:10A8A00000000000000000000000000000000000A8
-:10A8B0000000000000000000000000000000000098
-:10A8C0000000000000000000000000000000000088
-:10A8D0000000000000000000000000000000000078
-:10A8E0000000000000000000000000000000000068
-:10A8F0000000000000000000000000000000000058
-:10A900000000000000000000000000000000000047
-:10A910000000000000000000000000000000000037
-:10A920000000000000000000000000000000000027
-:10A930000000000000000000000000000000000017
-:10A940000000000000000000000000000000000007
-:10A9500000000000000000000000000000000000F7
-:10A9600000000000000000000000000000000000E7
-:10A9700000000000000000000000000000000000D7
-:10A9800000000000000000000000000000000000C7
-:10A9900000000000000000000000000000000000B7
-:10A9A00000000000000000000000000000000000A7
-:10A9B0000000000000000000000000000000000097
-:10A9C0000000000000000000000000000000000087
-:10A9D0000000000000000000000000000000000077
-:10A9E0000000000000000000000000000000000067
-:10A9F0000000000000000000000000000000000057
-:10AA00000000000000000000000000000000000046
-:10AA10000000000000000000000000000000000036
-:10AA20000000000000000000000000000000000026
-:10AA30000000000000000000000000000000000016
-:10AA40000000000000000000000000000000000006
-:10AA500000000000000000000000000000000000F6
-:10AA600000000000000000000000000000000000E6
-:10AA700000000000000000000000000000000000D6
-:10AA800000000000000000000000000000000000C6
-:10AA900000000000000000000000000000000000B6
-:10AAA00000000000000000000000000000000000A6
-:10AAB0000000000000000000000000000000000096
-:10AAC0000000000000000000000000000000000086
-:10AAD0000000000000000000000000000000000076
-:10AAE0000000000000000000000000000000000066
-:10AAF0000000000000000000000000000000000056
-:10AB00000000000000000000000000000000000045
-:10AB10000000000000000000000000000000000035
-:10AB20000000000000000000000000000000000025
-:10AB30000000000000000000000000000000000015
-:10AB40000000000000000000000000000000000005
-:10AB500000000000000000000000000000000000F5
-:10AB600000000000000000000000000000000000E5
-:10AB700000000000000000000000000000000000D5
-:10AB800000000000000000000000000000000000C5
-:10AB900000000000000000000000000000000000B5
-:10ABA00000000000000000000000000000000000A5
-:10ABB0000000000000000000000000000000000095
-:10ABC0000000000000000000000000000000000085
-:10ABD0000000000000000000000000000000000075
-:10ABE0000000000000000000000000000000000065
-:10ABF0000000000000000000000000000000000055
-:10AC00000000000000000000000000000000000044
-:10AC10000000000000000000000000000000000034
-:10AC20000000000000000000000000000000000024
-:10AC30000000000000000000000000000000000014
-:10AC40000000000000000000000000000000000004
-:10AC500000000000000000000000000000000000F4
-:10AC600000000000000000000000000000000000E4
-:10AC700000000000000000000000000000000000D4
-:10AC800000000000000000000000000000000000C4
-:10AC900000000000000000000000000000000000B4
-:10ACA00000000000000000000000000000000000A4
-:10ACB0000000000000000000000000000000000094
-:10ACC0000000000000000000000000000000000084
-:10ACD0000000000000000000000000000000000074
-:10ACE0000000000000000000000000000000000064
-:10ACF0000000000000000000000000000000000054
-:10AD00000000000000000000000000000000000043
-:10AD10000000000000000000000000000000000033
-:10AD20000000000000000000000000000000000023
-:10AD30000000000000000000000000000000000013
-:10AD40000000000000000000000000000000000003
-:10AD500000000000000000000000000000000000F3
-:10AD600000000000000000000000000000000000E3
-:10AD700000000000000000000000000000000000D3
-:10AD800000000000000000000000000000000000C3
-:10AD900000000000000000000000000000000000B3
-:10ADA00000000000000000000000000000000000A3
-:10ADB0000000000000000000000000000000000093
-:10ADC0000000000000000000000000000000000083
-:10ADD0000000000000000000000000000000000073
-:10ADE0000000000000000000000000000000000063
-:10ADF0000000000000000000000000000000000053
-:10AE00000000000000000000000000000000000042
-:10AE10000000000000000000000000000000000032
-:10AE20000000000000000000000000000000000022
-:10AE30000000000000000000000000000000000012
-:10AE40000000000000000000000000000000000002
-:10AE500000000000000000000000000000000000F2
-:10AE600000000000000000000000000000000000E2
-:10AE700000000000000000000000000000000000D2
-:10AE800000000000000000000000000000000000C2
-:10AE900000000000000000000000000000000000B2
-:10AEA00000000000000000000000000000000000A2
-:10AEB0000000000000000000000000000000000092
-:10AEC0000000000000000000000000000000000082
-:10AED0000000000000000000000000000000000072
-:10AEE0000000000000000000000000000000000062
-:10AEF0000000000000000000000000000000000052
-:10AF00000000000000000000000000000000000041
-:10AF10000000000000000000000000000000000031
-:10AF20000000000000000000000000000000000021
-:10AF30000000000000000000000000000000000011
-:10AF40000000000000000000000000000000000001
-:10AF500000000000000000000000000000000000F1
-:10AF600000000000000000000000000000000000E1
-:10AF700000000000000000000000000000000000D1
-:10AF800000000000000000000000000000000000C1
-:10AF900000000000000000000000000000000000B1
-:10AFA00000000000000000000000000000000000A1
-:10AFB0000000000000000000000000000000000091
-:10AFC0000000000000000000000000000000000081
-:10AFD0000000000000000000000000000000000071
-:10AFE0000000000000000000000000000000000061
-:10AFF0000000000000000000000000000000000051
-:10B000000000000000000000000000000000000040
-:10B010000000000000000000000000000000000030
-:10B020000000000000000000000000000000000020
-:10B030000000000000000000000000000000000010
-:10B040000000000000000000000000000000000000
-: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
-:10DA100000000000000000000000000010000003F3
-:10DA2000000000000000000D0000000D3C02080096
-:10DA3000244275803C03080024637A28AC4000002F
-:10DA40000043202B1480FFFD244200043C1D0800ED
-:10DA500037BD7FFC03A0F0213C100800261031D810
-:10DA60003C1C0800279C75800E0010EF0000000091
-:10DA70000000000D30A5FFFF30C600FF27430180E6
-:10DA80008F4201B80440FFFE24020002AC64000093
-:10DA9000A4650008A066000AA062000B3C0210000A
-:10DAA000AC67001803E00008AF4201B83C03600017
-:10DAB0008C624FF80440FFFE3C020200AC644FC091
-:10DAC000AC624FC43C02100003E00008AC624FF8A7
-:10DAD0009482000C2486001400A038210002130256
-:10DAE000000210800082402100C8102B1040005717
-:10DAF0000000000090C300002C620009504000515B
-:10DB000090C20001000310803C03080024637534B8
-:10DB1000004310218C42000000400008000000007B
-:10DB200090C300012402000A1462003A00000000C1
-:10DB3000010610232C42000A1440003624C60002BD
-:10DB40008CE2000034420100ACE2000090C2000010
-:10DB500090C3000190C4000290C5000300031C00A4
-:10DB60000002160000431025000422000044102586
-:10DB70000045102524C60004ACE2000490C2000059
-:10DB800090C3000190C4000290C50003000216007B
-:10DB900000031C000043102500042200004410254F
-:10DBA0000045102524C600040A000CAAACE20008B7
-:10DBB00090C30001240200041462001624C600026F
-:10DBC00090C2000090C400018CE30000000212002B
-:10DBD000004410253463000424C60002ACE2000CAB
-:10DBE0000A000CAAACE3000090C300012402000369
-:10DBF0001462000824C600028CE2000090C30000FA
-:10DC000024C6000134420008A0E300100A000CAA58
-:10DC1000ACE2000003E000082402000190C3000110
-:10DC2000240200021062000224C40002010020212C
-:10DC30000A000CAA008030210A000CAA24C60001A8
-:10DC400090C200010A000CAA00C2302103E00008C3
-:10DC50000000102127BDFFE8AFBF0014AFB00010D7
-:10DC60000E00130E00808021936200052403FFFE46
-:10DC700002002021004310248FBF00148FB0001039
-:10DC8000A36200050A00131727BD001827BDFFE88F
-:10DC9000AFB00010AFBF00140E000F0E0080802147
-:10DCA0009362000024030050304200FF144300043C
-:10DCB00024020100AF4201800A000D22020020214F
-:10DCC000AF400180020020218FBF00148FB00010F0
-:10DCD0000A000FAD27BD001827BDFF80AFBE00783A
-:10DCE000AFB70074AFB30064AFBF007CAFB60070D5
-:10DCF000AFB5006CAFB40068AFB20060AFB1005C0C
-:10DD0000AFB000588F5001289363003F9362000525
-:10DD10000000F021307300FF0002102730420001A4
-:10DD20000000B82114400066AFA0005093420116D5
-:10DD300093430112304200FF306300FF0342202171
-:10DD400003431021244540008F82001C104000181E
-:10DD5000249140008F4201043C0300010043102441
-:10DD600010400013000000008CA3000C8F620030F4
-:10DD7000146201B5240200018CA300108F62002CF4
-:10DD8000146201B1240200019762003A94834000BA
-:10DD90003042FFFF146201AC240200019762003898
-:10DDA000962300023042FFFF146201A72402000103
-:10DDB00093620000304300FF24020020106200053F
-:10DDC0002402005010620006000000000A000D6CE2
-:10DDD000000000000000000D0A000D75AFA000302B
-:10DDE0003C1E080027DE75E80A000D75AFA0003064
-:10DDF0003C0208008C4200DC244200013C01080087
-:10DE0000AC2200DC0E0013D8000000000A000F0353
-:10DE10008FBF007C8F4201043C0300209234000D30
-:10DE2000004310240002202B00042140AFA4003046
-:10DE30008F4301043C020040006218241460000279
-:10DE4000348700400080382132820020AFA70030A4
-:10DE50001440000234E6008000E0302110C0000BC6
-:10DE6000AFA6003093C500088F67004C0200202148
-:10DE700000052B0034A5008130A5F0810E000C8D2B
-:10DE800030C600FF0A000F00000000009362003E51
-:10DE9000304200401040000E24020004566200068A
-:10DEA00024020012020020210E0014E6022030217C
-:10DEB0000A000F038FBF007C1662000500000000FF
-:10DEC0000E000D13000020210A000F038FBF007CFD
-:10DED0009743011A9624000E9362003532850004A0
-:10DEE0003076FFFF00442004AFA400548E320004BB
-:10DEF00010A000158E3500089362003E30420040AD
-:10DF000010400007000000000E00142802402021ED
-:10DF10001040000D000000000A000F00000000008B
-:10DF20008F620044024210230440014500000000BB
-:10DF30008F6200480242102304410141240400166C
-:10DF40000A000E038FC200048F62004802421023B1
-:10DF500004400008000000003C0208008C42310030
-:10DF6000244200013C010800AC2231000A000EF5F9
-:10DF7000000000008F620040024210231840000998
-:10DF80002402000C3C0208008C423100329400FC58
-:10DF90000000B021244200013C010800AC22310005
-:10DFA0002402000CAFA200308F62004000522023F8
-:10DFB0001880000D02C4102A144001160000000051
-:10DFC0001496000602C410233A8200013042000178
-:10DFD000144001100000000002C4102302449021EC
-:10DFE0000A000DEB3056FFFF0000202132820002B4
-:10DFF0001040001A328200109362003E304200400E
-:10E00000504000118FC200040E00130E02002021A8
-:10E0100024020018A362003F936200052403FFFE60
-:10E0200002002021004310240E001317A3620005F4
-:10E0300024040039000028210E00141124060018C1
-:10E040000A000F0224020001240400170040F8090E
-:10E05000000000000A000F0224020001104000F836
-:10E06000000000008F63004C8F62005402A2102356
-:10E070001C4000F302A31023044200010060A82109
-:10E08000AFA40018AFB20010AFB600149342012045
-:10E090008F6500409763003C304200FF034210212F
-:10E0A000004410218FA400543063FFFF244240003D
-:10E0B0000083182B8FA40030AFA20020AFA500284A
-:10E0C00000832025AFA40030AFA50024AFA0002C12
-:10E0D000AFB500349362003E30420008504000115A
-:10E0E0008FC200000220202127A500380E000CA4BA
-:10E0F000AFA000385440000B8FC200008FA2003840
-:10E1000030420100504000078FC200008FA3003C46
-:10E110008F6200600062102304430001AF6300605F
-:10E120008FC200000040F80927A400108FA2003021
-:10E130003042000254400001329400FE9362003EDF
-:10E1400030420040104000378FA300148F6200540B
-:10E1500016A2001A3282000124020014126200107A
-:10E160002A62001510400006240200162402000C4A
-:10E1700012620007328200010A000E5F00000000F8
-:10E1800012620005328200010A000E5F00000000EA
-:10E190000A000E5A2417000E0A000E5A2417001007
-:10E1A0000A000E5E24170012936200232403FFBDB1
-:10E1B00000431024A36200233282000110400019A2
-:10E1C0008FA300142402000C1262000E2A62000DBC
-:10E1D000104000062402000E2402000A126200070A
-:10E1E0008FA200240A000E77244200011262000868
-:10E1F0008FA200240A000E77244200010A000E7547
-:10E20000241700082402000E16E20002241700164C
-:10E21000241700108FA2002424420001AFA2002482
-:10E220008FA300148FA200248F730040004310219D
-:10E23000AF6200408FA20054936400368F630040A9
-:10E2400002A288213402FFFF00821004006218211C
-:10E25000AF6300488FA6003030C200081040000EA7
-:10E26000000000008F6200581622000430C600FF34
-:10E270009742011A5040000134C6001093C50008AF
-:10E280008FA700340200202100052B0034A5008058
-:10E290000E000C8D30A5F0808F62004000531023DB
-:10E2A000184000178FA200183C0208008C423198D9
-:10E2B00030420010104000092402000197620068FB
-:10E2C0001440000624020001A76200689742007A09
-:10E2D0002442000A0A000EBBA7620012A7620012C5
-:10E2E0000E00130E020020219362007D2403000122
-:10E2F00002002021344200010A000EB9AFA30050F1
-:10E300001840000A000000000E00130E0200202139
-:10E310009362007D2403000102002021AFA300507E
-:10E32000344200040E001317A362007D9362003E86
-:10E33000304200401440000C328200011040000ABC
-:10E34000000000008F6300408FC200042404001806
-:10E35000246300010040F809AF6300408FA2003041
-:10E360000A000F02304200048F6200581051001062
-:10E37000000000008F620018024210231C400008B9
-:10E38000240400018F6200181642000900000000FA
-:10E390008F62001C02A21023044000050000000050
-:10E3A000AF710058AFA40050AF720018AF75001CD9
-:10E3B00012E0000B8FA200500E00130E020020216D
-:10E3C000A377003F0E0013170200202102E0302146
-:10E3D000240400370E001411000028218FA20050E1
-:10E3E00010400003000000000E000C9B02002021E2
-:10E3F00012C00005000018218FA200303042000436
-:10E400005040001100601021240300010A000F0297
-:10E41000006010210E00130E020020219362007D87
-:10E4200002002021344200040E001317A362007D75
-:10E430000E000C9B020020210A000F0224020001A2
-:10E44000AF400044240200018FBF007C8FBE0078E3
-:10E450008FB700748FB600708FB5006C8FB40068F2
-:10E460008FB300648FB200608FB1005C8FB0005832
-:10E4700003E0000827BD00808F4201B80440FFFE82
-:10E4800024020800AF4201B803E0000800000000C9
-:10E4900030A5FFFF30C6FFFF8F4201B80440FFFEEA
-:10E4A0003C020008AF44018003421021AF44002029
-:10E4B000944200483044FFFF1080001924020003FA
-:10E4C00024A200120082102B104000152402000329
-:10E4D000934201202403001AA343018B304200FF22
-:10E4E0002447FFFE8F8200000087182B386300014D
-:10E4F0000002138200431024104000058F830004A3
-:10E5000034620001A74701940A000F39AF8200046A
-:10E510002402FFFE006210240A000F39AF820004BB
-:10E52000A342018B24020002A742018C8F820000CB
-:10E530008F840004A745018EA74201908F82000CB2
-:10E5400030838000AF4201A8A74601881060000E0A
-:10E550008F82000493420116304200FC24420004E2
-:10E56000005A10218C4240003042FFFF1440000648
-:10E570008F8200043C02FFFF34427FFF00821024A0
-:10E58000AF8200048F8200042403BFFF978400023F
-:10E5900000431024A74201A69742010C0002140078
-:10E5A00000441025AF4201AC3C021000AF4201B85C
-:10E5B00003E00008000000008F4700709342011242
-:10E5C0008F83000027BDFFF0304200FF0002288249
-:10E5D00030620100000030211040004324A40003F9
-:10E5E00030624000104000103062200000041080B3
-:10E5F000005A10218C43400024A400040004108021
-:10E60000AFA30000005A10218C424000AFA20004CA
-:10E6100093420116304200FC005A10218C42400007
-:10E620000A000F86AFA200081040002F0000302122
-:10E6300000041080005A10218C43400024A40004E0
-:10E6400000041080AFA30000005A10218C4240004B
-:10E65000AFA00008AFA200048FA80008000030217E
-:10E6600000002021240A00083C0908002529010097
-:10E6700003A41021148A000300042A001100000AD8
-:10E680000000000090420000248400012C83000C54
-:10E6900000A2102100021080004910218C420000CD
-:10E6A0001460FFF300C230263C0408008C8431045F
-:10E6B0008F4200702C83002010600009004738232F
-:10E6C0003C0308002463310800041080004310213B
-:10E6D00024830001AC4700003C010800AC23310456
-:10E6E000AF86000C2406000100C0102103E00008E2
-:10E6F00027BD00103C0208008C42003827BDFFD027
-:10E70000AFB60028AFB40020AFB20018AFBF002CE6
-:10E71000AFB50024AFB3001CAFB10014AFB0001010
-:10E72000000090213C16080026D600381440000254
-:10E730002454FFFF0000A0219742010E8F840000A7
-:10E740003042FFFF308340001060000A2453000471
-:10E750003C020020008210245040000730828000DC
-:10E760008F8200042403BFFF008318240A000FD700
-:10E7700034421000308280001040000A3C02002029
-:10E7800000821024104000078F8200043C03FFFF2A
-:10E7900034637FFF0083182434428000AF8200047A
-:10E7A000AF8300000E000F5E000000001440000761
-:10E7B000000000009743011E9742011C3063FFFFD9
-:10E7C0000002140000621825AF83000C9742010C70
-:10E7D0008F4340003046FFFF3402FFFF1462000306
-:10E7E000000000000A000FEF241200208F424000BA
-:10E7F0003042010054400001241200108F840000B8
-:10E800003082100050400014365200013082002047
-:10E810001440000B3C021000008210245040000EF7
-:10E82000365200013C030E003C020DFF0083182409
-:10E830003442FFFF0043102B5040000736520001C6
-:10E840003C0208008C42002C244200013C010800DC
-:10E85000AC22002C365200053C0508008CA5003483
-:10E8600054A000408F8400008F8200105440003D6F
-:10E870008F8400008F8200043042400054400039F1
-:10E880008F8400003C021F01008210243C03100012
-:10E89000144300348F84000030C202001440003260
-:10E8A0003C0200013265FFFF364600028F4201B88C
-:10E8B0000440FFFE3C020008AF40018003421021EB
-:10E8C000944200483043FFFF10600019AF830008F6
-:10E8D00024A200120062102B104000162402000334
-:10E8E000934201202403001AA343018B304200FF0E
-:10E8F0002443FFFE8F820000304240001040000899
-:10E900008F8200048F8200080043102B1440000403
-:10E910008F820004A74301940A00103A3442000198
-:10E920002403FFFE004310240A00103EAF820004BF
-:10E9300024020003A342018B8F8300042402BFFF43
-:10E940000062182424020002A742018C8F8200007A
-:10E95000A745018EA7460188A74301A60A0010D942
-:10E96000A74201903C020001008210241040000BDD
-:10E970003C0210003C0208008C4200D89745010E72
-:10E98000240400802442000130A5FFFF3C01080060
-:10E99000AC2200D80A0010E22406000300821024F2
-:10E9A00010400041000000003C0208008C42003092
-:10E9B0001040000C8F8200043042400010400009DB
-:10E9C0003C030F00008318243C0201000043102B7D
-:10E9D00014400004364600023265FFFF0A0010E2D0
-:10E9E0002404008010A0000D308201001040000BB4
-:10E9F0003C020F00008210243C0302001043000779
-:10EA00008F82000C00541024005610219042000404
-:10EA1000244200040A001097000221C000000000F8
-:10EA20008F8600003C0508008CA500D00006160269
-:10EA30003050000F38A200012C4200012E03000CC0
-:10EA40000043102414400015001021C02602FFFCD2
-:10EA50002C420004544000110000202138A2000282
-:10EA60002C42000100431024104000030006124213
-:10EA70000A001097000020210010182B00431024DA
-:10EA800050400006001021C0000020213265FFFF29
-:10EA90000E000F143246FFFB001021C03265FFFF4D
-:10EAA0000A0010E2364600028F4240003C11080086
-:10EAB0008E310024304201001040003E322200011D
-:10EAC0000220802110A00014325500043082010081
-:10EAD00010400012240200013C020F0000821024AA
-:10EAE0003C0302001043000C8F82000C02403021D6
-:10EAF0003265FFFF0054102400561021904400049A
-:10EB00003252FFFB248400040E000F14000421C0C5
-:10EB10002402FFFE022280242402000116020007C4
-:10EB2000320200013242000450400001365200021D
-:10EB30003265FFFF0A0010E102403021104000075B
-:10EB40003202000402403021000020210E000F1488
-:10EB50003265FFFF3252FFFB320200041040000713
-:10EB60008F82000030420800104000043265FFFF31
-:10EB7000024030210E000F142404010016A00015DD
-:10EB80008FBF002C274301808F4201B80440FFFE55
-:10EB900024022000A462000824020002A062000BEC
-:10EBA000A46000103C021000AF4201B80A0010E55A
-:10EBB0008FBF002C104000078FBF002C3265FFFF75
-:10EBC00036460002000020210E000F140000000055
-:10EBD0008FBF002C8FB600288FB500248FB4002083
-:10EBE0008FB3001C8FB200188FB100148FB00010CB
-:10EBF0000000102103E0000827BD003027BDFFC83A
-:10EC0000AFB000103C04600CAFBF0030AFB7002CB9
-:10EC1000AFB60028AFB50024AFB40020AFB3001CDE
-:10EC2000AFB20018AFB100148C8250002403FF7FF4
-:10EC30003C1A8000004310243442380CAC8250004F
-:10EC4000240200033C106000AF4200088E02080856
-:10EC50003C1B80083C010800AC2000203042FFF043
-:10EC6000384200102C4200010E001C46AF82001CEE
-:10EC70003C04FFFF3C020400348308063442000CCD
-:10EC8000AE021948AE03194C3C0560168E0219807D
-:10EC90008CA300003442020000641824AE021980E4
-:10ECA0003C0253531462000334A47C008CA2000481
-:10ECB000005020218C82007C8C830078AF82001869
-:10ECC000AF8300143C028000344200708C4300008B
-:10ECD00000403821AF830020006030218CE8000024
-:10ECE0003C0508008CA500FC3C0408008C8400F85E
-:10ECF000010630230000102100A6282100A6302B99
-:10ED000000822021008620213C010800AC2500FC67
-:10ED10003C010800AC2400F88F56000032C200030A
-:10ED20001040FFEE010030218CE600003C05080099
-:10ED30008CA500FC3C0408008C8400F800C830233B
-:10ED400000A628210000102100A6302B00822021DF
-:10ED50000086202132C700013C010800AC2500FCE0
-:10ED6000AF8800203C010800AC2400F810E0016BE3
-:10ED700032C200028F4301283C02000803421021E6
-:10ED8000AF4300208F4301048F44010094420048A8
-:10ED9000AF830000AF8400043042FFFF0E000F0E6F
-:10EDA000AF8200083C0208008C4200C010400008FE
-:10EDB0008F8400003C0208008C4200C42442000101
-:10EDC0003C010800AC2200C40A0012AF00000000A1
-:10EDD0003C02001000821024144001358F8300048F
-:10EDE0003C0208008C4200203C0308008C63003881
-:10EDF00000009021244200013C010800AC220020C8
-:10EE00003C17080026F70038146000022474FFFF46
-:10EE10000000A0219742010E308340003042FFFFE6
-:10EE20001060000A245300043C02002000821024D9
-:10EE300050400007308280008F8200042403BFFF0F
-:10EE4000008318240A00118D3442100030828000A3
-:10EE50001040000A3C0200200082102410400007ED
-:10EE60008F8200043C03FFFF34637FFF008318247C
-:10EE700034428000AF820004AF8300000E000F5EBA
-:10EE80000000000014400007000000009743011E2E
-:10EE90009742011C3063FFFF000214000062182536
-:10EEA000AF83000C9742010C8F4340003046FFFFB8
-:10EEB0003402FFFF14620003000000000A0011A5E5
-:10EEC000241200208F4240003042010054400001D3
-:10EED000241200108F840000308210005040001473
-:10EEE00036520001308200201440000B3C0210001A
-:10EEF000008210245040000E365200013C030E00E8
-:10EF00003C020DFF008318243442FFFF0043102B06
-:10EF100050400007365200013C0208008C42002C91
-:10EF2000244200013C010800AC22002C36520005AE
-:10EF30003C0508008CA5003454A000408F840000DC
-:10EF40008F8200105440003D8F8400008F820004A7
-:10EF500030424000544000398F8400003C021F01C1
-:10EF6000008210243C031000144300348F840000FE
-:10EF700030C20200144000323C0200013265FFFF43
-:10EF8000364600028F4201B80440FFFE3C020008F2
-:10EF9000AF40018003421021944200483043FFFFFC
-:10EFA00010600019AF83000824A200120062102B29
-:10EFB0001040001624020003934201202403001A8B
-:10EFC000A343018B304200FF2443FFFE8F820000E9
-:10EFD00030424000104000088F8200048F820008F9
-:10EFE0000043102B144000048F820004A7430194B7
-:10EFF0000A0011F0344200012403FFFE00431024F4
-:10F000000A0011F4AF82000424020003A342018B22
-:10F010008F8300042402BFFF006218242402000230
-:10F02000A742018C8F820000A745018EA746018868
-:10F03000A74301A60A00128FA74201903C020001DB
-:10F04000008210245040000B3C0210003C020800DB
-:10F050008C4200D89745010E240400802442000110
-:10F0600030A5FFFF3C010800AC2200D80A0012982E
-:10F07000240600030082102410400041000000001C
-:10F080003C0208008C4200301040000C8F820004CB
-:10F0900030424000104000093C030F000083182458
-:10F0A0003C0201000043102B1440000436460002CD
-:10F0B0003265FFFF0A0012982404008010A0000DA2
-:10F0C000308201001040000B3C020F00008210242F
-:10F0D0003C030200104300078F82000C00541024F0
-:10F0E0000057102190420004244200040A00124DEF
-:10F0F000000221C0000000008F8600003C050800CF
-:10F100008CA500D0000616023050000F38A2000176
-:10F110002C4200012E03000C004310241440001563
-:10F12000001021C02602FFFC2C42000454400011B4
-:10F130000000202138A200022C42000100431024CC
-:10F1400050400003000612420A00124D0000202128
-:10F150000010182B0043102450400006001021C05E
-:10F16000000020213265FFFF0E000F143246FFFB26
-:10F17000001021C03265FFFF0A00129836460002D7
-:10F180008F4240003C1108008E31002430420100C3
-:10F190001040003E322200010220802110A0001405
-:10F1A0003255000430820100104000122402000198
-:10F1B0003C020F00008210243C0302001043000CAC
-:10F1C0008F82000C024030213265FFFF0054102472
-:10F1D00000571021904400043252FFFB24840004A5
-:10F1E0000E000F14000421C02402FFFE022280241E
-:10F1F000240200011602000732020001324200041C
-:10F2000050400001365200023265FFFF0A0012979B
-:10F210000240302110400007320200040240302139
-:10F22000000020210E000F143265FFFF3252FFFB59
-:10F2300032020004104000078F82000030420800B4
-:10F24000104000043265FFFF024030210E000F1411
-:10F250002404010016A0002E3C0240002743018038
-:10F260008F4201B80440FFFE24022000A46200087F
-:10F2700024020002A062000BA46000103C021000F7
-:10F28000AF4201B80A0012B43C02400050400020D6
-:10F290003C0240003265FFFF36460002000020219C
-:10F2A0000E000F14000000000A0012B43C024000DF
-:10F2B0002402BFFF0062102410400008000000007C
-:10F2C000240287FF00621024144000083C02006002
-:10F2D0000082102410400005000000000E000D26E2
-:10F2E000000000000A0012AD000000000E0012F83D
-:10F2F00000000000104000063C0240008F43012443
-:10F300003C026020AC430014000000003C024000BE
-:10F31000AF4201380000000032C200021040FE6A15
-:10F320003C0280008F4201403C044000AF4200207C
-:10F330008F4301483C027000006218241064002DC5
-:10F34000000000000083102B144000063C02600007
-:10F350003C022000106200073C0240000A0012F448
-:10F360000000000010620027000000000A0012F4F4
-:10F370003C0240008F4201482403000400021402B2
-:10F38000304200FF1443000B274401808F430140AB
-:10F390008F4201B80440FFFE2402001CAC83000031
-:10F3A000A082000B3C021000AF4201B80A0012F428
-:10F3B0003C0240008F4201B80440FFFE0000000004
-:10F3C0008F42014800021402A482000824020002B5
-:10F3D000A082000B8F420148A48200108F4201449A
-:10F3E000AC8200243C021000AF4201B80A0012F4C3
-:10F3F0003C0240000E00131C000000000A0012F442
-:10F400003C0240000E001C53000000003C02400083
-:10F41000AF420178000000000A0011223C02800087
-:10F420008F4201003042003E1440001124020001CE
-:10F43000AF4000488F420100304207C01040000535
-:10F4400000000000AF40004CAF40005003E0000857
-:10F4500024020001AF400054AF4000408F42010041
-:10F460003042380054400001AF4000442402000103
-:10F4700003E00008000000003C029000344200015C
-:10F4800000822025AF4400208F4200200440FFFE70
-:10F490000000000003E00008000000003C028000C3
-:10F4A000344200010082202503E00008AF44002020
-:10F4B00027BDFFE0AFB20018AFBF001CAFB1001412
-:10F4C000AFB000108F5001408F5101483C028000C6
-:10F4D0000011940202222024324300FF2402000E75
-:10F4E0001062008A2862000F104000122862003764
-:10F4F000240200061062003B28620007104000074B
-:10F50000240200091060001A240200011062002584
-:10F51000000000000A0013D1000000001062007B10
-:10F520002402000B1062005B3222FFFF0A0013D19D
-:10F530000000000010400008240200382862003556
-:10F54000104000802402001F1062007E00000000B6
-:10F550000A0013D1000000001062007A240200802B
-:10F5600010620042000000000A0013D100000000F9
-:10F570008F4201B80440FFFE24020001AF50018019
-:10F58000AF400184A7520188A342018A24020002ED
-:10F59000A342018BA75101908F4201440A0013CC72
-:10F5A000AF4201A41080000A240200023C010800BE
-:10F5B000A02275D83C010800AC3075E08F420144B0
-:10F5C0003C010800AC2275DC0A0013D38FBF001C7D
-:10F5D0008F4201B80440FFFE240200020A0013B665
-:10F5E000000000008F4201B80440FFFE0000000050
-:10F5F000AF5001803C020800904275D810400003D3
-:10F60000000018213C0308008C6375E0AF430184BF
-:10F61000A75201883C020800904275D800001821CA
-:10F6200034420001A342018A24020002A342018B5A
-:10F63000A75101908F420144AF4201A43C0208004F
-:10F64000904275D8104000033C0210003C030800B3
-:10F650008C6375DCAF4301A8AF4201B83C010800E0
-:10F66000A02075D80A0013D38FBF001C8F4201B8A9
-:10F670000440FFFE24020002A342018BA75201882E
-:10F68000A75101908F420144A74201920A0013CE74
-:10F690003C0210001440001D0000000093620005B1
-:10F6A0003042000414400037000000000E00130E2A
-:10F6B0000200202193620005020020213442000450
-:10F6C0000E001317A3620005936200053042000488
-:10F6D00014400002000000000000000D93620000D2
-:10F6E00024030020304200FF144300080000000003
-:10F6F0008F4201B80440FFFE24020005AF50018094
-:10F70000A342018B3C021000AF4201B88F4201B806
-:10F710000440FFFE24020002AF400180AF5001848C
-:10F72000A7520188A342018AA342018BA7510190ED
-:10F73000AF4001A48F420144AF4201A80A0013CE9A
-:10F740003C0210008F4201B80440FFFE2402000179
-:10F75000AF500180AF400184A7520188A342018AC3
-:10F7600024020002A342018BA7510190AF4001A4E3
-:10F77000AF4001A83C021000AF4201B80A0013D309
-:10F780008FBF001C0000000D8FBF001C8FB200183F
-:10F790008FB100148FB0001003E0000827BD0020D7
-:10F7A00027BDFFE8AFBF00100E000F0E00000000E5
-:10F7B000AF4001808FBF0010000020210A000FAD74
-:10F7C00027BD00183084FFFF30A5FFFF000018217F
-:10F7D000108000070000000030820001104000028D
-:10F7E00000042042006518210A0013E400052840A7
-:10F7F00003E000080060102110C0000624C6FFFFCF
-:10F800008CA2000024A50004AC8200000A0013EEC4
-:10F810002484000403E000080000000010A0000899
-:10F8200024A3FFFFAC8600000000000000000000E1
-:10F830002402FFFF2463FFFF1462FFFA2484000404
-:10F8400003E000080000000027BDFFE8AFBF001480
-:10F85000AFB000100E00130E008080219362007D77
-:10F8600002002021344200200E001317A362007D05
-:10F87000020020218FBF00148FB000100A000C9BE3
-:10F8800027BD0018308300FF30A500FF30C600FF01
-:10F89000274701808F4201B80440FFFE00000000AE
-:10F8A0008F42012834634000ACE2000024020001D2
-:10F8B000ACE00004A4E30008A0E2000A2402000275
-:10F8C000A0E2000B3C021000A4E50010ACE0002414
-:10F8D000ACE00028A4E6001203E00008AF4201B843
-:10F8E00027BDFFE8AFBF00109362003F2403001262
-:10F8F000304200FF1043000D008030218F62004431
-:10F90000008210230440000A8FBF00108F6200485D
-:10F91000240400390000282100C2102304410004FF
-:10F92000240600120E001411000000008FBF00100A
-:10F930002402000103E0000827BD001827BDFFC80E
-:10F94000AFB1002C00A08821AFB2003027A5001075
-:10F950000080902102202021AFBF0034AFB00028EA
-:10F960000E000CA4AFA0001010400009024020219E
-:10F970008E220008AF6200840E001402AF600040C7
-:10F98000240400382405008D0A0014DD240600122A
-:10F990009362003E304200081040000F8FA200101A
-:10F9A00030420100104000078FA300148F620060F6
-:10F9B0000062102304430008AF6300600A0014666D
-:10F9C00000000000AF6000609362003E2403FFF778
-:10F9D00000431024A362003E9362003E30420008C0
-:10F9E000144000022406000300003021936200341A
-:10F9F000936300378F640084304200FF306300FF60
-:10FA000000661821000318800043282100A4202B41
-:10FA10001080000B000000009763003C8F620084A0
-:10FA20003063FFFF004510230062182B14600004B0
-:10FA3000000000008F6200840A00148200458023C9
-:10FA40009762003C3050FFFF8FA30010306200042B
-:10FA500010400004000628808FA2001C0A00148AAF
-:10FA60000202102B2E02021850400003240202183A
-:10FA70000A00149302051023306300041060000391
-:10FA8000004510238FA2001C004510230040802158
-:10FA90002C42008054400001241000800E00130E00
-:10FAA0000240202124020001AF62000C9362003E5C
-:10FAB000001020403042007FA362003E8E220004EE
-:10FAC00024420001AF620040A770003C8F620050EA
-:10FAD0009623000E00431021AF6200588F62005041
-:10FAE00000441021AF62005C8E220004AF62001857
-:10FAF0008E220008AF62001C8FA200103042000866
-:10FB00005440000A93A20020A3600036936200369E
-:10FB10002403FFDFA36200359362003E00431024FC
-:10FB2000A362003E0A0014BD8E220008A3620035C5
-:10FB30008E220008AF62004C8F6200248F63004069
-:10FB400000431021AF62004893620000240300507C
-:10FB5000304200FF144300122403FF803C020800DF
-:10FB60008C4231A00242102100431024AF420028F1
-:10FB70003C0208008C4231A08E2400083C03000C9B
-:10FB8000024210213042007F034210210043102125
-:10FB9000AC4400D88E230008AF820028AC4300DCC0
-:10FBA0000E001317024020212404003800002821F1
-:10FBB0002406000A0E001411000000008FBF00345C
-:10FBC0008FB200308FB1002C8FB0002824020001CA
-:10FBD00003E0000827BD003827BDFFE8AFBF0010D5
-:10FBE00090C7000D00C0282130E6001010C0000AA8
-:10FBF00030E200058CA300088F62005410620006FA
-:10FC000030E20005144000178FBF001000002021D3
-:10FC10000A000D1327BD00181040000D30E300123C
-:10FC200010C000108FBF00108CA300088F6200541A
-:10FC30001462000D24020001240400382405008D04
-:10FC40000E001411240600120A0015098FBF0010BF
-:10FC500024020012146200038FBF00100A00143F38
-:10FC600027BD00182402000103E0000827BD00188A
-:10FC700027BDFFF827420180AFA20000308A00FFB5
-:10FC80008F4201B80440FFFE000000008F460128AB
-:10FC90003C0208008C4231A02403FF80AF86005054
-:10FCA00000C2102100431024AF4200243C0208008F
-:10FCB0008C4231A08FA900008FA8000000C2102143
-:10FCC0003042007F034218213C02000A00621821E2
-:10FCD000946400D48FA700008FA5000024020002C6
-:10FCE000AF830028A0A2000B8FA300003542600064
-:10FCF0003084FFFFA4E200083C021000AD260000A3
-:10FD0000AD040004AC60002427BD0008AF4201B878
-:10FD100003E00008240200018C8200048F83002885
-:10FD200000451023AC820004906200633042007FE3
-:10FD3000A06200638C820020938300308F850028AE
-:10FD400034420002AF830044A7800042AC8200200E
-:10FD5000A4A000E490A200632403FFBF004310248A
-:10FD600003E00008A0A20063274301808F4201B88E
-:10FD70000440FFFE8F820050AC6200008F420124DD
-:10FD8000AC62000424026083A46200082402000222
-:10FD9000A062000B3C02100003E00008AF4201B873
-:10FDA0008F880044938200308F8300283C0708002E
-:10FDB00024E779F400481023304200FF304900FC6A
-:10FDC000246500888F860048304A0003112000090E
-:10FDD00000002021248200048CA30000304400FF96
-:10FDE0000089102AACE3000024A500041440FFF9A8
-:10FDF00024E70004114000090000202124820001B2
-:10FE000090A30000304400FF008A102BA0E3000004
-:10FE100024A500011440FFF924E7000130C20003CB
-:10FE2000144000048F850044310200031040000D8F
-:10FE30000000000010A00009000020212482000121
-:10FE400090C30000304400FF0085102BA0E30000A9
-:10FE500024C600011440FFF924E7000103E0000874
-:10FE6000000000001100FFFD00002021248200049A
-:10FE70008CC30000304400FF0088102BACE300006E
-:10FE800024C600041440FFF924E7000403E000083E
-:10FE9000000000008F8300449382003030C600FFD2
-:10FEA00030A500FF00431023304300FF8F8200285D
-:10FEB000008038210043102114C00002244800882B
-:10FEC0000083382130E200031440000530A2000313
-:10FED00014400003306200031040000D00000000D9
-:10FEE00010A00009000020212482000190E30000FE
-:10FEF000304400FF0085102BA103000024E700011F
-:10FF00001440FFF92508000103E00008000000008C
-:10FF100010A0FFFD00002021248200048CE30000DB
-:10FF2000304400FF0085102BAD03000024E70004DF
-:10FF30001440FFF92508000403E000080000000059
-:10FF400027BDFFF82402FFFFAFA200000080382188
-:10FF50002405002F3C090800252975F4240800FF1A
-:10FF60002406FFFF90E2000024A3FFFF0006220208
-:10FF700000C21026304200FF00021080004910210C
-:10FF80008C420000306500FF24E7000114A8FFF553
-:10FF90000082302600061027AFA20004AFA20000A6
-:10FFA0000000282127A6000400C510239044000368
-:10FFB00024A2000100BD1821304500FF2CA200043E
-:10FFC0001440FFF9A06400008FA2000003E00008C5
-:10FFD00027BD00080080482130AAFFFF30C600FF7F
-:10FFE00030E7FFFF274801808F4201B80440FFFE41
-:10FFF0008F820050AD0200008F420124AD02000448
-:020000040001F9
-:100000008D220020A5070008A102000A2402001684
-:10001000A102000B934301208D2200088D240004CF
-:10002000306300FF004310219783004200441021F9
-:100030008D250024004310233C0308008C6331A06D
-:100040008F840028A502000C246300E82402FFFF2F
-:10005000A50A000EA5030010A5060012AD050018A4
-:10006000AD020024948201142403FFF73042FFFF05
-:10007000AD0200288C820118AD02002C3C02100059
-:10008000AD000030AF4201B88D22002000431024A3
-:1000900003E00008AD2200208F82002830E7FFFF38
-:1000A00000804821904200D330A5FFFF30C600FFFA
-:1000B0000002110030420F0000E23825274801807D
-:1000C0008F4201B80440FFFE8F820050AD02000055
-:1000D0008F420124AD0200048D220020A5070008F4
-:1000E000A102000A24020017A102000B9343012081
-:1000F0008D2200088D240004306300FF004310218E
-:1001000097830042004410218F840028004310236D
-:100110003C0308008C6331A0A502000CA505000E6D
-:10012000246300E8A5030010A5060012AD0000142A
-:100130008D220024AD0200188C82005CAD02001CF0
-:100140008C820058AD0200202402FFFFAD02002483
-:10015000948200E63042FFFFAD02002894820060E6
-:10016000948300BE30427FFF3063FFFF0002120025
-:1001700000431021AD02002C3C021000AD00003005
-:10018000AF4201B8948200BE2403FFF700A2102101
-:10019000A48200BE8D2200200043102403E000084A
-:1001A000AD220020274301808F4201B80440FFFEAA
-:1001B00024020018AC640000A062000B8F820028AB
-:1001C000944200E6A46200103C021000AC600030D3
-:1001D00003E00008AF4201B8274301808F4201B815
-:1001E0000440FFFE8F82002C9442001C3042FFFF2F
-:1001F000000211C0AC62000024020019A062000BD2
-:100200003C021000AC60003003E00008AF4201B8CF
-:100210008F87003430C300FF8F4201B80440FFFED7
-:100220008F82005034636000ACA200009382004CC7
-:10023000A0A200058CE20010A4A20006A4A300085E
-:100240008C8200202403FFF7A0A2000A24020002EF
-:10025000A0A2000B8CE20000ACA200108CE2000413
-:10026000ACA200148CE2001CACA200248CE20020A2
-:10027000ACA200288CE2002CACA2002C8C820024C2
-:10028000ACA200183C021000AF4201B88C820020E2
-:100290000043102403E00008AC8200209382004C4D
-:1002A0002403000127BDFFE8004330042C42002056
-:1002B000AFB00010AFBF00142410FFFE10400005C7
-:1002C000274501803C0208008C4231900A0016A8A4
-:1002D000004610243C0208008C4231940046102451
-:1002E00014400007240600848F8300282410FFFF99
-:1002F000906200623042000F34420040A06200620F
-:100300000E00167400000000020010218FBF0014C0
-:100310008FB0001003E0000827BD00188F83002C69
-:1003200027BDFFE0AFB20018AFB10014AFB00010AE
-:10033000AFBF001C9062000D00A0902130D100FFE3
-:100340003042007FA062000D8F8500288E43001888
-:10035000008080218CA2007C146200052402000E23
-:1003600090A20063344200200A0016D1A0A20063CC
-:100370000E001697A382004C2403FFFF1043004792
-:100380002404FFFF52200045000020218E4300007E
-:100390003C02001000621024504000043C0200089F
-:1003A000020020210A0016E0240200150062102439
-:1003B000504000098E450000020020212402001454
-:1003C0000E001697A382004C2403FFFF1043003356
-:1003D0002404FFFF8E4500003C02000200A210240E
-:1003E000104000163C0200048F86002C8CC20014C2
-:1003F0008CC300108CC40014004310230044102B45
-:1004000050400005020020218E43002C8CC20010B9
-:1004100010620003020020210A00171124020012BA
-:100420003C02000400A210245040001C00002021C7
-:10043000020020210A0017112402001300A2102438
-:10044000104000068F83002C8C6200105040001377
-:10045000000020210A00170B020020218C620010EE
-:10046000504000048E42002C020020210A00171187
-:100470002402001150400009000020210200202128
-:10048000240200170E001697A382004C2403FFFFDE
-:10049000104300022404FFFF000020218FBF001C36
-:1004A0008FB200188FB100148FB00010008010219F
-:1004B00003E0000827BD00209383003027BDFFE044
-:1004C00024020034AFB20018AFB10014AFBF001C5B
-:1004D000AFB00010008088211462000C00A09021B1
-:1004E0008F8400340E0015C08C900030120200077B
-:1004F00024020005022020210E001697A382004C42
-:100500002403FFFF104300602404FFFF9242000415
-:10051000104000098F820028022020212402000CB4
-:100520000E001697A382004C2403FFFF10430056D1
-:100530002404FFFF8F820028A38000248E43000440
-:100540008C4400803C0200FF3442FFFF006218240C
-:100550000083202B10800008AF83003C0220202164
-:10056000240200190E001697A382004C2403FFFFFB
-:10057000104300452404FFFF978200428F87004408
-:100580008F85003C0047202310A0003AA78400423A
-:100590008F86002830A200030002102390C300BC05
-:1005A0003050000300B02821000318823071000190
-:1005B0000011108000A228213C0308008C6331A0A8
-:1005C0008F8200503084FFFF0085202B00431021D4
-:1005D00010800010244200888F8400341082000DA7
-:1005E0003C033F018E420000004310243C032500E1
-:1005F0001443000630E500FF8C820000ACC2008886
-:100600008C8200100A001775ACC200980E00159578
-:1006100000003021938200248F8500288F830048BA
-:10062000020238218F820044A387002494A400E4AE
-:10063000006218218F82003C34841000AF83004890
-:1006400000503021A4A400E41220000EAF86004424
-:1006500024E20004A382002494A200E424C3000442
-:10066000AF83004434422000A4A200E40A001792A1
-:10067000000020218F820048AF80004400471021F5
-:10068000AF820048000020218FBF001C8FB20018ED
-:100690008FB100148FB000100080102103E000081B
-:1006A00027BD00208F86002827BDFFE8AFBF0014BC
-:1006B000AFB0001090C2006330420020104000082C
-:1006C00030A500FF8CC2007C2403FFDF2442000120
-:1006D000ACC2007C90C2006300431024A0C200633F
-:1006E00010A000238F8300282750018002002821BA
-:1006F0000E001674240600828F8200289042006348
-:100700003042004050400019A380004C8F830034D9
-:100710008F4201B80440FFFE8F820050AE020000FD
-:1007200024026082A602000824020002A202000B3A
-:100730008C620008AE0200108C62000CAE02001445
-:100740008C620014AE0200188C620018AE02002405
-:100750008C620024AE0200288C620028AE02002CBD
-:100760003C021000AF4201B8A380004C8F830028E8
-:100770008FBF00148FB000109062006327BD001877
-:100780003042007FA0620063978200428F8600445F
-:100790008F8500289383003000461023A7820042F3
-:1007A000A4A000E490A400638F820048AF830044BB
-:1007B0002403FFBF0046102100832024AF8200489D
-:1007C000A0A400638F820028A04000BD8F82002873
-:1007D00003E00008A44000BE8F8A002827BDFFE088
-:1007E000AFB10014AFB000108F880044AFBF001845
-:1007F00093890024954200E430D100FF0109182BB1
-:100800000080802130AC00FF3047FFFF00005821FE
-:1008100014600003310600FF012030210109582334
-:10082000978300420068102B144000320000000043
-:1008300014680007240200018E0200202403FFFB3D
-:1008400034E7800000431024AE020020240200019F
-:1008500034E70880158200053165FFFF0E0015E5BD
-:10086000020020210A001827020020210E0016167F
-:10087000020020210E0016598F8400508F8400281A
-:100880009482006024420001A4820060948200608F
-:100890003C0308008C63318830427FFF5443000FD3
-:1008A0000200202194820060240380000043102471
-:1008B000A48200609082006090830060304200FF5C
-:1008C000000211C200021027000211C03063007F35
-:1008D00000621825A0830060020020210220282148
-:1008E0008FBF00188FB100148FB000100A00179945
-:1008F00027BD0020914200632403FF8000431025A0
-:10090000A1420063978200423048FFFF110000209F
-:10091000938300248F840028004B1023304600FF6F
-:10092000948300E42402EFFF0168282B006218245E
-:10093000A48300E414A000038E02002001005821CB
-:10094000000030212403FFFB34E780000043102423
-:10095000AE02002024020001158200053165FFFF70
-:100960000E0015E5020020210A00184F978300426F
-:100970000E00161602002021978300428F82004449
-:10098000A780004200431023AF82004493830024D9
-:100990008F8200288FBF00188FB100148FB0001015
-:1009A00027BD002003E00008A04300BD8F8200287F
-:1009B00090430088904500BD244900883063003F83
-:1009C0002463FFE024020001006238042C6300204D
-:1009D00030E80019A385002410600010AF890034AE
-:1009E0003C0280003442000224050001240600017C
-:1009F0001500000800E218240000282114600005FA
-:100A000030E200201040000524050001912600017D
-:100A100030C600010A0017E60000000003E00008ED
-:100A20000000000027BDFFD8AFB000108F90003449
-:100A3000AFB40020AFB10014AFBF0024AFB3001CAF
-:100A4000AFB200188E0500103C0208008C4231B095
-:100A50008F86003830A33FFF0062182B8CD3001420
-:100A6000008088218CD20020106000780000A02136
-:100A700090C3000D2402FF8000431024304200FF89
-:100A800050400073022020210005138230420003F1
-:100A90005440006F0220202194C3001C8F82002844
-:100AA0008E050028A44301148CC200100262182392
-:100AB000146500072402001F8F82003C0062102191
-:100AC0000262102B104000088F83002C24020018B3
-:100AD0000E001697A382004C2403FFFF1043006F03
-:100AE0002404FFFF8F83002C8F84003C8C62001055
-:100AF0000244902100441023AC6200108F82002831
-:100B0000AC7200208C4200680052102B104000098B
-:100B10008F830038022020212402001D0E0016972A
-:100B2000A382004C2403FFFF1043005C2404FFFF5A
-:100B30008F8300388E0200248C630024104300074A
-:100B4000022020212402001C0E001697A382004CD4
-:100B50002403FFFF104300512404FFFF8F84002C67
-:100B60008C82002424420001AC8200241253000431
-:100B70008F8200288C4200685642000E8E020000D0
-:100B80008E0200003C030080004310241440000D3E
-:100B90002402001A022020210E001697A382004C86
-:100BA0002403FFFF1043003D2404FFFF0A0018E365
-:100BB0008E0200143C0300800043102450400003C8
-:100BC0008E020014AC8000208E0200142412FFFF5D
-:100BD000105200062402001B022020210E0016974E
-:100BE000A382004C1052002D2404FFFF8E0300004E
-:100BF0003C020001006210241040001F3C020080F3
-:100C00000062102414400008022020212402001A4F
-:100C10000E001697A382004C2403FFFF1043001F11
-:100C20002404FFFF02202021020028210E0016B715
-:100C3000240600012403FFFF2404FFFF1443000ED9
-:100C4000241400010A0019188FBF0024022020215B
-:100C50002402000D8FBF00248FB400208FB3001C2E
-:100C60008FB200188FB100148FB0001027BD00287C
-:100C70000A001697A382004C8F83002C02202021AB
-:100C800002803021946200362405000124420001D4
-:100C90000E0017E6A4620036000020218FBF00245A
-:100CA0008FB400208FB3001C8FB200188FB10014D6
-:100CB0008FB000100080102103E0000827BD00283D
-:100CC0008F83002827BDFFD8AFB40020AFB3001C2E
-:100CD000AFB20018AFB10014AFB00010AFBF002426
-:100CE000906200638F9100342412FFFF3442004071
-:100CF00092250000A06200638E22001000809821DF
-:100D000030B0003F105200060360A0212402000D05
-:100D10000E001697A382004C105200522404FFFFCD
-:100D20008F8300288E2200188C63007C10430007FC
-:100D3000026020212402000E0E001697A382004CB0
-:100D40002403FFFF104300472404FFFF2404002076
-:100D5000120400048F830028906200633442002054
-:100D6000A06200638F85003C10A0001E0000000000
-:100D7000560400048F820028026020210A001962B4
-:100D80002402000A9683000A2404FFFD94420060B6
-:100D90003042FFFF104300348FBF00243C020800A4
-:100DA0008C42318C0045102B14400006026020213B
-:100DB000000028210E0017E6240600010A00198908
-:100DC000000020212402002D0E001697A382004C63
-:100DD0002403FFFF104300232404FFFF0A001989A6
-:100DE00000002021160400058F8400288E230014A3
-:100DF0002402FFFF506200180260202194820060EC
-:100E000024420001A4820060948200603C03080038
-:100E10008C63318830427FFF5443000F02602021F1
-:100E2000948200602403800000431024A4820060A8
-:100E30009082006090830060304200FF000211C287
-:100E400000021027000211C03063007F00621825E5
-:100E5000A0830060026020210E0017992405000184
-:100E6000000020218FBF00248FB400208FB3001C0E
-:100E70008FB200188FB100148FB0001000801021C5
-:100E800003E0000827BD00288F83002827BDFFE866
-:100E9000AFB00010AFBF0014906200638F870034C2
-:100EA00000808021344200408CE60010A062006384
-:100EB0003C0308008C6331B030C23FFF0043102B6D
-:100EC0001040004E8F8500382402FF8090A3000D53
-:100ED00000431024304200FF50400049020020210E
-:100EE0000006138230480003240200025502004429
-:100EF0000200202194A2001C8F85002824030023D7
-:100F0000A4A201148CE60000000616023042003F45
-:100F1000104300103C0300838CE300188CA2007C7B
-:100F2000106200062402000E0E001697A382004CE9
-:100F30002403FFFF104300382404FFFF8F830028A1
-:100F40009062006334420020A06200630A0019CE60
-:100F50008F83002C00C31024144300078F83002CC0
-:100F600090A200623042000F34420020A0A2006232
-:100F7000A38800408F83002C9062000D3042007FD8
-:100F8000A062000D8F83003C106000180200202139
-:100F90008F8400388C8200100043102B1040000911
-:100FA00024020018020020210E001697A382004C94
-:100FB0002403FFFF104300182404FFFF0A0019F662
-:100FC000000020218C820010240500010200202155
-:100FD000004310238F83002C240600010E0017E627
-:100FE000AC6200100A0019F6000020210E001799CB
-:100FF000240500010A0019F600002021020020212A
-:101000002402000D8FBF00148FB0001027BD001800
-:101010000A001697A382004C8FBF00148FB00010F7
-:101020000080102103E0000827BD001827BDFFD86D
-:10103000AFB000108F900034AFB3001CAFBF0020E2
-:10104000AFB20018AFB100148E1200103C030800BC
-:101050008C6331B032423FFF0043102B1040007CC4
-:10106000008098218F8500382402FF8090A3000D16
-:1010700000431024304200FF5040007602602021DF
-:101080000012138230420003240300015443007114
-:101090000260202190A2000D30420008544000035D
-:1010A0008F82003C0A001A262402002450400003CC
-:1010B0008E03000C0A001A26240200278CA20020AE
-:1010C00014620005240200208E0300088CA2002474
-:1010D00010620008240200200E001697A382004C24
-:1010E0002403FFFF1043006A2404FFFF0A001A5183
-:1010F0008F84002C8E0200142411FFFF1451000372
-:101100008F8700280A001A4C240200258E0300183D
-:101110008CE2007C146200162402000E8E03002470
-:101120008CA2002814620012240200218E060028DE
-:101130008CA2002C14C2000E2402001F8E03002C6F
-:101140001060000B240200238CE200680043102B87
-:1011500014400007240200268CA200140066182107
-:101160000043102B504000078F84002C24020022E3
-:101170000E001697A382004C105100452404FFFF77
-:101180008F84002C2403FFF79082000D004310246D
-:10119000A082000D8F8600283C0308008C6331ACD0
-:1011A0008F82005094C400E08F85002C00431021F2
-:1011B00030847FFF00042040004410213043007F32
-:1011C000034320213C03000E008320212403FF80E1
-:1011D00000431024AF42002CA49200008CA20028EF
-:1011E00024420001ACA200288CA2002C8E03002C0B
-:1011F00000431021ACA2002C8E02002CACA20030C7
-:101200008E020014ACA2003494A2003A24420001E1
-:10121000A4A2003A94C600E03C0208008C4231B01F
-:1012200024C4000130837FFF14620013008030214A
-:10123000240280000082302430C2FFFF000213C26B
-:10124000304200FF000210270A001A8E000233C04D
-:10125000026020212402000D8FBF00208FB3001CEC
-:101260008FB200188FB100148FB0001027BD002876
-:101270000A001697A382004C8F820028026020216A
-:10128000240500010E001799A44600E0000020216B
-:101290008FBF00208FB3001C8FB200188FB10014D5
-:1012A0008FB000100080102103E0000827BD002847
-:1012B00027BDFFE0AFB100148F910034AFB0001034
-:1012C000AFBF00188E2600103C0308008C6331B0BD
-:1012D00030C23FFF0043102B1040005E0080802191
-:1012E0008F8500382402FF8090A3000D0043102456
-:1012F000304200FF50400058020020218F82003C05
-:1013000010400008000613828F8200289763000AAD
-:101310002404FFFD944200603042FFFF104300555B
-:1013200000061382304200031440000E000000004B
-:1013300092220002104000058E2300245060001508
-:10134000922300030A001AC7020020218CA2002465
-:101350005062001092230003020020210A001ACFDD
-:101360002402000F90A2000D3042000854400009F2
-:101370009223000302002021240200100E00169781
-:10138000A382004C2403FFFF1043003A2404FFFF14
-:1013900092230003240200025462000C92220003F4
-:1013A0008F82003C54400009922200030200202159
-:1013B0002402002C0E001697A382004C2403FFFF8A
-:1013C0001043002C2404FFFF922200030220282156
-:1013D00002002021384600102CC600012C420001DA
-:1013E0000E0016B7004630252411FFFF10510021D2
-:1013F0002404FFFF8F83003C1060001202002021B4
-:101400003C0208008C42318C0043102B1440000633
-:1014100000000000000028210E0017E6240600014D
-:101420000A001B0D000020212402002D0E0016973B
-:10143000A382004C1051000F2404FFFF0A001B0D73
-:10144000000020210E001799240500010A001B0D41
-:1014500000002021020020212402000D8FBF00186F
-:101460008FB100148FB0001027BD00200A0016971E
-:10147000A382004C8FBF00188FB100148FB00010F2
-:101480000080102103E0000827BD00209383004066
-:1014900027BDFFE024020002AFB10014AFB000107E
-:1014A00000808821AFBF0018000080211062008CEE
-:1014B0002404FFFD978500428F83004430A2FFFF84
-:1014C0000043102B5440007D8F8400480E001558B7
-:1014D000000000003C020800244279F40220202190
-:1014E000004028210E00171EAF8200342409FFFFA0
-:1014F0001049007B2404FFFF3C0808008D087A0493
-:101500003C0208008C4231B03C030800906379F43F
-:1015100031043FFF0082102B1040001B3067003F5A
-:101520003C0208008C4231A88F83005000042180C7
-:1015300000621821006418213062007F03422821D4
-:101540003C02000C00A228213C0200803442000131
-:101550003066007800C230252402FF80006210242B
-:10156000AF42002830640007AF4208048F82002891
-:101570000344202124840940AF460814AF85002C81
-:10158000AF840038AC430118938300402402000369
-:101590001462003B240200012402002610E2003DF8
-:1015A00028E2002710400013240200322402002207
-:1015B00010E2003828E20023104000082402002432
-:1015C0002402002010E200242402002110E2001E68
-:1015D000022020210A001B8C2402000B10E2002DA7
-:1015E0002402002510E20010022020210A001B8C9A
-:1015F0002402000B10E2001A28E20033104000061B
-:101600002402003F2402003110E2000B02202021BE
-:101610000A001B8C2402000B10E200110220202182
-:101620000A001B8C2402000B0E00187902202021D6
-:101630000A001BA7004080210E0019FB0220202178
-:101640000A001BA7004080210E001A9C02202021C6
-:101650000A001BA7004080211509000E00000000B1
-:101660000E001920022020210A001BA70040802123
-:101670000E001697A382004C0A001BA70040802191
-:1016800014620017020020212402002314E2000546
-:101690002402000B0E001992022020210A001BA731
-:1016A0000040802102202021A382004C0E001697CA
-:1016B0002410FFFF0A001BA80200202130A500FF14
-:1016C0000E00159524060001978300428F82004486
-:1016D000A780004200431023AF8200440200202173
-:1016E0008FBF00188FB100148FB000100080102140
-:1016F00003E0000827BD002027BDFFE0AFB10014C4
-:10170000AFBF0018AFB000108F4601283C0308009F
-:101710008C6331A02402FF80AF86005000C31821E3
-:101720003065007F03452821006218243C02000A2E
-:10173000AF43002400A2282190A2006200808821EB
-:10174000AF850028304200FF00021102A382004052
-:1017500090A200BC30420002144000022403003476
-:10176000240300308F820028A3830030938300403D
-:101770008C4200C0A380004CAF82004424020004CD
-:10178000106200308F8400448E2400045080002DAD
-:101790008F8400448E2200103083FFFFA784004214
-:1017A0001060001FAF8200488F8300282405FF804F
-:1017B000022020219062006300A21024304200FF2A
-:1017C0001440000D000000000E001B139790004213
-:1017D00010400010004018212402FFFD5462001147
-:1017E0008E230020020028210E0015360220202121
-:1017F0000A001BF98E2300209062006300A21024CF
-:10180000304200FF10400003022020210E00185B30
-:1018100000000000978200421440FFE48F830028FC
-:101820008E23002030620004104000068F840044A4
-:101830002402FFFB006210240E00154AAE22002095
-:101840008F8400448F8300288FBF00188FB100144D
-:101850008FB000102402000127BD002003E0000823
-:10186000AC6400C030A500FF2403000124A90001DE
-:101870000069102B1040000C00004021240A0001D8
-:1018800000A31023004A38042463000130820001C1
-:101890000069302B1040000200042042010740255F
-:1018A00054C0FFF800A3102303E00008010010213A
-:1018B00027BDFFE03C021EDCAFB20018AFB1001440
-:1018C000AFBF001CAFB0001034526F410000882140
-:1018D000240500080E001C09022020210011808030
-:1018E0003C07080024E775F40002160002071821DF
-:1018F000AC6200000000282124A200013045FFFF57
-:101900008C6200002CA60008044100020002204066
-:101910000092202614C0FFF8AC640000020780216A
-:101920008E0400000E001C0924050020262300015F
-:101930003071FFFF2E2301001460FFE5AE020000AE
-:101940008FBF001C8FB200188FB100148FB0001031
-:1019500003E0000827BD00203C02080024426EB8C6
-:101960003C010800AC2275E83C02080024425430D7
-:101970003C010800AC2275EC240200063C01080082
-:10198000A02275F00A001C1C0000000027BDFFD833
-:10199000AFB3001CAFB20018AFBF0020AFB100144E
-:1019A000AFB000108F5101408F48014800089402E9
-:1019B000324300FF311300FF8F4201B80440FFFEA5
-:1019C00027500180AE1100008F420144AE02000496
-:1019D00024020002A6120008A202000B2402001436
-:1019E000AE13002410620025286200151040000884
-:1019F000240200152402001010620030240200129C
-:101A0000106200098FBF00200A001D468FB3001C22
-:101A10001062007024020022106200378FBF002085
-:101A20000A001D468FB3001C3C0208008C4231A006
-:101A30002403FF800222102100431024AF4200241F
-:101A40003C0208008C4231A0022210213042007F6B
-:101A5000034218213C02000A00621821166000BCF3
-:101A6000AF830028906200623042000F34420030A1
-:101A7000A06200620A001D458FBF00203C04600088
-:101A80008C832C083C02F0033442FFFF00621824D0
-:101A9000AC832C083C0208008C4231A08C832C08BB
-:101AA0002442007400021082000214800062182593
-:101AB000AC832C080A001D458FBF00203C020800A3
-:101AC0008C4231A02403FF80022210210043102405
-:101AD000AF4200243C0208008C4231A03C03000AC3
-:101AE000022210213042007F0342102100431021C6
-:101AF0000A001D44AF8200283C0208008C4231A03D
-:101B00002405FF800222102100451024AF4200244A
-:101B10003C0208008C4231A0022210213042007F9A
-:101B2000034218213C02000A0062182190620063FF
-:101B300000A21024304200FF10400085AF8300282F
-:101B400024620088944300123C0208008C4231A8B1
-:101B500030633FFF0003198002221021004310214F
-:101B60003043007F03432021004510243C03000C38
-:101B700000832021AF4200289082000D00A2102493
-:101B8000304200FF10400072AF84002C9082000DA4
-:101B9000304200101440006F8FBF00200E00166608
-:101BA000000000008F4201B80440FFFE000000006A
-:101BB000AE1100008F420144AE0200042402000274
-:101BC000A6120008A202000BAE1300240A001D4555
-:101BD0008FBF00202406FF8002261024AF42002081
-:101BE0003C0208008C4231A031043FFF00042180F8
-:101BF0000222102100461024AF4200243C030800BA
-:101C00008C6331A83C0208008C4231A03227007F4F
-:101C10000223182102221021006418213042007F83
-:101C20003064007F034228213C02000A0066182429
-:101C300000A22821034420213C02000C0082202124
-:101C4000AF4300283C02000803471821006290219E
-:101C5000AF850028AF84002C0E001666010080219D
-:101C60008F4201B80440FFFE8F82002C8F84002831
-:101C7000274501809042000DACB10000A4B00006E1
-:101C8000000216000002160300021027000237C2ED
-:101C900014C00016248200889442001232033FFFD1
-:101CA00030423FFF1443001224026082908300639D
-:101CB0002402FF8000431024304200FF5040000CFB
-:101CC00024026082908200623042000F3442004061
-:101CD000A082006224026084A4A200082402000DF5
-:101CE000A0A200050A001D2F3C02270024026082EA
-:101CF000A4A20008A0A000053C02270000061C00CA
-:101D00000062182524020002A0A2000BACA3001060
-:101D1000ACA00014ACA00024ACA00028ACA0002C07
-:101D20008E42004C8F84002CACA200189083000DD2
-:101D30002402FF8000431024304200FF10400005C1
-:101D40008FBF00209082000D3042007FA082000DE6
-:101D50008FBF00208FB3001C8FB200188FB100140A
-:101D60008FB000103C02100027BD002803E00008DF
-:041D7000AF4201B8C5
-:0C1D7400080033F8080033F80800337052
-:101D8000080033A8080033DC0800340008003400E1
-:081D900008003400080032E0F5
-:081D98000A0001220000000016
-:101DA000000000000000000D747061352E302E30F0
-:101DB0006A3600000500000100000000000000007D
-:101DC0000000000000000000000000000000000013
-:101DD0000000000000000000000000000000000003
-:101DE00000000000000000000000000000000000F3
-:101DF00000000000000000000000000000000000E3
-:101E000000000000000000000000000000000000D2
-:101E100000000000000000000000000000000000C2
-:101E20000000000010000003000000000000000D92
-:101E30000000000D3C02080024421B803C03080007
-:101E400024632014AC4000000043202B1480FFFDCD
-:101E5000244200043C1D080037BD2FFC03A0F021E4
-:101E60003C100800261004883C1C0800279C1B809E
-:101E70000E00015A000000000000000D3084FFFF3A
-:101E8000308200078F85001810400002248300076D
-:101E90003064FFF80085302130C41FFF034418214F
-:101EA000247B4000AF85001CAF84001803E00008CD
-:101EB000AF4400843084FFFF308200078F8500200C
-:101EC0008F86002810400002248300073064FFF84A
-:101ED000008520210086182B14600002AF850024A5
-:101EE000008620230344282134068000AF8400208C
-:101EF000AF44008000A6202103E00008AF84003832
-:101F000027BDFFD8AFB3001CAFB20018AFB00010B0
-:101F1000AFBF0024AFB40020AFB100143C0860088C
-:101F20008D1450002418FF7F3C1A800002989824DA
-:101F30003672380CAD1250008F5100083C07601CFF
-:101F40003C08600036300001AF500008AF80001838
-:101F5000AF400080AF4000848CE600088D0F080879
-:101F60003C0760168CEC000031EEFFF039CA00101F
-:101F70003C0DFFFF340B80003C030080034B4821E5
-:101F80002D440001018D28243C0253533C010800DC
-:101F9000AC230420AF890038AF860028AF8400103E
-:101FA000275B400014A2000334E37C008CF900049A
-:101FB000032818218C7F007C8C6500783C0280000F
-:101FC00034520070AF85003CAF9F00403C130800C6
-:101FD00026731BC40240A0218E4800008F460000DB
-:101FE00038C300013064000110800017AF8800344E
-:101FF000028048218D2D00003C1908008F39045CB7
-:102000003C1108008E31045801A8F823033F7821C1
-:10201000000040210228382101FF802B00F07021B0
-:102020003C010800AC2F045C3C010800AC2E0458B5
-:102030008F4C0000398B0001316A00011540FFED23
-:1020400001A04021AF8D00348E4E00003C0C0800F2
-:102050008D8C045C3C0A08008D4A045801C8682332
-:10206000018D28210000582100AD302B014B20218B
-:10207000008610213C010800AC25045C3C010800EE
-:10208000AC2204588F4501088F44010030A920007C
-:10209000AF850000AF84000C1120000A00A03021A1
-:1020A0003C0708008CE7042C24EF00013C010800E9
-:1020B000AC2F042C3C104000AF5001380A000190B6
-:1020C0000000000030B002001600001424110F00C0
-:1020D0001091001224070D001087023330B0000663
-:1020E0005200FFF53C104000936D0000240C0010DE
-:1020F00031A600F010CC0269240E007010CE02DD73
-:102100008F8B001425670001AF8700143C1040003E
-:10211000AF5001380A000190000000009748010408
-:102120001100FFE53C10400030B84000170000A24D
-:10213000000000008F5901780720FFFE8F870038CC
-:1021400024090008240508008CE30008AF45017845
-:10215000A7490140A7400142974201048F86000031
-:102160003049FFFF30DF000113E002D5012040219C
-:102170002524FFFE240A0002A74A01463088FFFFFB
-:10218000A74401483C0B08008D6B043C156002C459
-:102190008F8F000C30C3002014600002240400095B
-:1021A0002404000130CD0C00240C040051AC0001CB
-:1021B00034840004A744014A3C0508008CA504208F
-:1021C0003C0200483C19000100A2F82530D800026A
-:1021D00003F9282513000004000018213C04010025
-:1021E00000A428252403000130CA00045140000542
-:1021F000AF8300083C06001000A628252403000138
-:10220000AF830008AF451000000000000000000090
-:1022100000000000000000008F8300081060002311
-:10222000000000008F4B10000561FFFE0000000061
-:102230001060001E000000008F4D10003C030020C5
-:1022400001A36024118000198F8F000031EE00027D
-:1022500011C0001600000000975010141600001363
-:10226000000000009745100830BFFFFF27F8000668
-:102270000018C8820019308000C7282133110001DE
-:1022800033030003122003208CA200000000000D85
-:1022900000C7F821AFE200003C1908008F39043074
-:1022A000272600013C010800AC2604308F6A00009C
-:1022B0003405FFFFAF8A00048CE200001045029A4B
-:1022C000000020218CE5000030BF010013E0027EF9
-:1022D000010020213C0708008CE704743C10080032
-:1022E0008E10044C00E858213C1808008F18047028
-:1022F0000168882B3C0808008D08044800007821FC
-:1023000002046021030F18210184702B010F682142
-:102310000071502101AE10213C010800AC2C044C8E
-:102320003C010800AC2204483C010800AC2B0474BA
-:102330003C010800AC2A04708F8D00180120302168
-:102340003129000725AE000831C21FFF034260217A
-:10235000AF8D001CAF820018259B4000AF42008467
-:10236000112000038F90002024C800073106FFF8D9
-:102370008F84002800D0282100A4782B15E00002CB
-:10238000AF90002400A428230345202134038000BB
-:10239000008310213C061000AF850020AF8200387A
-:1023A000AF450080AF4601788F8B00142567000190
-:1023B0000A0001DDAF8700148F6200088F670000FC
-:1023C000241100300007C602330300F0107100A290
-:1023D000241900401479FF4B8F8B00148F4A017829
-:1023E0000540FFFE30A7020014E000030005128242
-:1023F0000000000D0005128230500003001049005B
-:1024000001307021000E688001B06021000C5880FE
-:10241000017380218E0800001500000200000000FA
-:102420000000000D8F6F000405E202B19203000668
-:1024300092070005920F00043C020001000728806B
-:1024400000B060218D8900182771000825EE000575
-:1024500001226821000E3082AD8D0018022020215B
-:102460000E00058026050014920B00068F7F0004E5
-:102470003C087FFF000B2080009130218CC30004BA
-:10248000350AFFFF03EAC8240079C021ACD8000454
-:102490009207000592090004960D000800072880A5
-:1024A00000B1F8218FEF0000974201043C07FFFFC5
-:1024B00001E75024304EFFFF01C96021018D5823F0
-:1024C0003168FFFF01482025AFE4000092030007B8
-:1024D00024190001107902692406000310660279AC
-:1024E000000000008E190010241F000AA75F0140A1
-:1024F000A7590142920300048F86000024070001BF
-:10250000A7430144A74001469758010430D1000277
-:102510003C050041A758014800001821A747014A7F
-:102520001220000330CA00043C05014124030001CD
-:1025300051400005AF8300083C08001000A8282582
-:1025400024030001AF830008AF4510000000000025
-:102550000000000000000000000000008F8B000859
-:1025600011600004000000008F4410000481FFFE91
-:10257000000000008F6A0000920700043C0508007C
-:102580008CA50444AF8A0004975F01043C0F080047
-:102590008DEF044030E300FF33F9FFFF0079C021E5
-:1025A00000B868210000102124E6000A30C8FFFFAF
-:1025B00001B8482B01E2702101C9602131100007E8
-:1025C0003C010800AC2D04443C010800AC2C044044
-:1025D000120000038F8D0018250B00073168FFF8EB
-:1025E000010D702131CC1FFFAF8D001CAF8C001886
-:1025F000AF4C008497440104034C80213084FFFFDA
-:102600003088000711000003261B400024890007C2
-:102610003124FFF88F8200208F850028008220213E
-:102620000085782B15E00002AF820024008520236E
-:102630000344882134058000022510213C06100047
-:10264000AF840020AF820038AF440080AF460178ED
-:102650000A0002858F8B00148F5F017807E0FFFE70
-:1026600030AA020015400003000542820000000D60
-:1026700000054282310200030002710001C268219C
-:10268000000D6080018248210009288000B380216C
-:102690008E0B000011600002000000000000000D21
-:1026A0008F6F000C05E001F38F87003824190001BB
-:1026B000AE1900008CE30008A20000078F78000428
-:1026C00000181C02306600FF24D100050011308282
-:1026D0002CC4004114800002A20300040000000D7D
-:1026E0008F6B00043C0EFFFF00E028213164FFFFE8
-:1026F000248F000B000F4082000810800047482103
-:102700008D2D000026040014A60B000801AE6024E5
-:102710000E000580AD2C00008F5F01083C0A100000
-:1027200003EA382410E001A30000000097460104EA
-:102730009203000724D1FFEC346500023224FFFF2E
-:10274000A2050007960600082CC7001354E00005F8
-:1027500092030007920A0007355F0001A21F0007DD
-:1027600092030007240B0001106B01BA2409000337
-:10277000106901CD8F88003830CFFFFF25E40002BB
-:102780000004C883333F00FF001F2880A219000502
-:1027900000A858218D780000975101043C03FFFFE9
-:1027A000030360243222FFFF004F702325CDFFFE7C
-:1027B000018D4825AD690000920600053C02FFF638
-:1027C000344EFFFF30CA00FF000A388000F020219D
-:1027D000909900143C1FFF7F37E7FFFF3323000F62
-:1027E0000066782131F800FF0018288000B08821A9
-:1027F0008E2D002000A86021A20F000601AE482403
-:10280000AE0D000CAD89000C920B00068E04000C7E
-:102810000127F824000B50800150C821972600267C
-:102820000148C02100874024AF260024AE08000CD8
-:10283000AF3F0020AF0600108F860000240C001070
-:1028400024090002A74C0140A7400142A7400144CF
-:10285000A7490146974B01042407000130C8000234
-:10286000256AFFFEA74A01483C050009A747014A1F
-:1028700011000003000018213C0501092403000198
-:1028800030CD000451A00005AF8300083C060010C5
-:1028900000A6282524030001AF830008AF451000DF
-:1028A0000000000000000000000000000000000028
-:1028B0009218000427110002322F0007000F102386
-:1028C000304E0007AE0E00108F900008120000047A
-:1028D000000000008F4310000461FFFE00000000B4
-:1028E0008F7800008F8F00183C1008008E10044471
-:1028F000AF9800049751010425E6001030CA1FFF6D
-:102900003222FFFFAF8F001CAF8A0018AF4A00844D
-:102910002449FFFE3C0B08008D6B0440974E0104D8
-:1029200001206821000967C3020D282131C9FFFF7A
-:1029300000AD402B016C382100E82021034AF8212A
-:10294000313900073C010800AC2504443C01080073
-:10295000AC2404401320000327FB4000252300077C
-:102960003069FFF88F9F00208F840028013F3821B5
-:1029700000E4C82B17200002AF9F002400E4382396
-:102980000347202134058000008510213C061000FB
-:10299000AF870020AF820038AF470080AF46017894
-:1029A0000A0002858F8B0014975801041300FDC2A2
-:1029B0003C1040008F4301780460FFFE30B94000B6
-:1029C000132000033C0400080000000D3C04000834
-:1029D000AF44014024080800AF4801788F8B000005
-:1029E000974A0104317F000113E000E93146FFFFFF
-:1029F00024D0FFFE240C0002A74C0146A75001483A
-:102A00008F8F00182405000DA745014A8F71000023
-:102A100025E2000830491FFF0349702130CD00072F
-:102A2000AF910004AF8F001CAF89001800C038219F
-:102A3000AF49008411A0000325DB400024C6000735
-:102A400030C7FFF88F9800208F84002800F83021CD
-:102A500000C4382B14E00002AF98002400C43023D7
-:102A60008F8A001403465821340880000168F82139
-:102A7000255900013C0310003C104000AF860020A7
-:102A8000AF9F0038AF460080AF430178AF99001484
-:102A9000AF5001380A000190000000008F6900006B
-:102AA000974401043127FFFF3088FFFF8F4F0178E3
-:102AB00005E0FFFE30FF0007001F182330780007F5
-:102AC00024E6FFFE2419000AA7590140A758014235
-:102AD000A7460144A7400146A74801488F42010884
-:102AE00030510020162000022403000924030001B5
-:102AF00030AA0002A743014A3C04004111400003F0
-:102B0000000018213C0401412403000130AB000403
-:102B100051600005AF8300083C05001000852025AA
-:102B200024030001AF830008AF4410000000000040
-:102B30000000000000000000000000008F9000086E
-:102B400012000004000000008F4C10000581FFFE01
-:102B5000000000008F780000276200088F8D003C85
-:102B6000AF980004944600089451000A944F000C5A
-:102B700030CEFFFF0011240031E9FFFF11CD00A28C
-:102B8000008920253C0308008C6304443C1808009D
-:102B90008F18044000E85021255FFFFE007F782158
-:102BA0000000102101FF302B03028821022648215A
-:102BB0003C010800AC2F04443C010800AC2904404F
-:102BC00024EB00083162FFFF3047000710E00003EC
-:102BD0008F850018245000073202FFF83106FFFFEE
-:102BE00030C800070045702131CD1FFF034D602123
-:102BF000AF85001CAF8D0018259B4000AF4D0084B1
-:102C0000110000038F8F002024C400073086FFF8D6
-:102C10008F84002800CF282100A4482B1520000213
-:102C2000AF8F002400A42823AF850020AF4500808B
-:102C30003C1108008E3104340345C0213402800069
-:102C40000302302112200005AF860038938300175D
-:102C50002419000E1079000D241F043F3C0A1000B7
-:102C6000AF4A01788F8B0014256700010A0001DD4F
-:102C7000AF8700140E0005A63C1040008F8B001497
-:102C8000256700010A0001DEAF8700143C0A10002E
-:102C9000A75F0148AF4A01780A0004B48F8B001483
-:102CA000240E0F0011EE003D30D10020162000024E
-:102CB00024030009240300010A000208A743014A73
-:102CC0000A0001FBA740014694E5000894E2000ACF
-:102CD00094EB000C8F86003C0002FC00316AFFFF81
-:102CE00030B9FFFF1326003703EA20253C05080012
-:102CF0008CA504443C1F08008FFF044000005021B5
-:102D000000A8382100E8302B03EAC8210326C0219F
-:102D10003C010800AC2704443C010800AC380440E6
-:102D20000A0002698F8D00183C1908008F39047C55
-:102D30003C0308008C6304543C0608008CC60478ED
-:102D40003C0F08008DEF04500328382100686821EB
-:102D500000E8C02B00C4882101A8402B01E47021A9
-:102D60000238582101C860213C010800AC2D0454F0
-:102D70003C010800AC2C04503C010800AC27047C4A
-:102D80003C010800AC2B04780A0002698F8D001802
-:102D9000A74001460A00041B8F8F001830D0002086
-:102DA0001600FFC52403000D240300050A000208D5
-:102DB000A743014A975901042738FFF00A00036B23
-:102DC0003304FFFF8F8C0040148CFFC8000080216B
-:102DD0003C1108008E31046C3C0408008C840468AB
-:102DE0000228702101C8782B00904021010F682132
-:102DF0003C010800AC2E046C3C010800AC2D0468BA
-:102E00000A0002698F8D00188F9900401499FF5DA8
-:102E1000000060213C0508008CA5046C3C100800F3
-:102E20008E10046800E82021248EFFFE00AEF821F9
-:102E300003EE582B020C5021014B18213C010800D5
-:102E4000AC3F046C3C010800AC2304680A00048B0E
-:102E500024EB00088F8800383C02FFFF8D0E000C29
-:102E600001C2682401A46025AD0C000C0A0003799E
-:102E700030CFFFFF0A0003A9AE000000974B01040A
-:102E8000920400048E2A000C01644021251FFFF2E9
-:102E90000147182433F9FFFF0079C025AE38000C34
-:102EA0000A0002D48E1900103C03FFFF8D110010A0
-:102EB0000223282400A47825AD0F00100A0003790E
-:102EC00030CFFFFF97450104920600048E2F0010BB
-:102ED00000A610212449FFEE01E76824312EFFFFF0
-:102EE00001AE6025AE2C00100A0002D48E1900102D
-:102EF0008E06000CAE0000000003C0800310882185
-:102F00000A0002A6AE2600201460000D3050FFFF1C
-:102F10003C04FFFF0044602401846826000D582B08
-:102F2000000C502B014B1024104000020000000048
-:102F30000000000D8CA300000A00023E0064102572
-:102F40003A11FFFF0011782B0010702B01CF2024C5
-:102F500010800002000000000000000D8CB800008E
-:102F60000A00023E3702FFFF3084FFFF30A5FFFF5B
-:102F7000108000070000182130820001104000027C
-:102F800000042042006518211480FFFB0005284042
-:102F900003E000080060102110C0000700000000DE
-:102FA0008CA2000024C6FFFF24A50004AC82000010
-:102FB00014C0FFFB2484000403E0000800000000AC
-:102FC00010A0000824A3FFFFAC8600000000000052
-:102FD000000000002402FFFF2463FFFF1462FFFAD9
-:102FE0002484000403E0000800000000308EFFFF8E
-:102FF00030D8FFFF00057C0001F8602539CDFFFFC8
-:1030000001AC5021014C582B014B482100094402CE
-:103010003127FFFF00E830210006240230C5FFFF02
-:1030200000A418213862FFFF03E000083042FFFFD0
-:103030003C0C08008D8C0484240BFF8027BDFFD03E
-:1030400001845021014B4824AF4900203C0808006E
-:103050008D080484AFB20020AFB00018AFBF0028C5
-:10306000AFB30024AFB1001C936600040104382103
-:1030700030E4007F009A10213C03000800439021B7
-:1030800030C50020036080213C080111277B000827
-:1030900014A00002264600702646006C921300041D
-:1030A00097510104920F00043267000F322EFFFF88
-:1030B00031ED004001C7282311A000050000482180
-:1030C000925900BC33380004170000900000000043
-:1030D000924300BC307F000413E0000F00000000AA
-:1030E00010A0000D00000000960E0002240AFF80D0
-:1030F00000A7602125CDFFFEA74D1016920B0004FE
-:10310000014B2024308200FF10400085010C402537
-:103110003C0F0400010F40258F5301780660FFFE2D
-:103120002404000AA7440140960D0002240400096B
-:1031300031AC0007000C5823316A0007A74A01424E
-:10314000960200022443FFFEA7430144A740014624
-:10315000975F0104A75F01488F59010833380020A9
-:103160005300000124040001920F000431EE00100E
-:1031700015C000023483001000801821A743014AC3
-:10318000000000000000000000000000000000003F
-:10319000AF48100000000000000000000000000028
-:1031A000000000008F5110000621FFFE3113FFFFC9
-:1031B00012600003000000008F481018ACC8000027
-:1031C00096030006307FFFFF27F90002001998825E
-:1031D00000138880023B30218CD800001520005756
-:1031E00000183402920300042405FF8000A3F82491
-:1031F00033F100FF1220002C00000000924700BCB9
-:1032000030F200021240002800000000974B100C22
-:103210002562FFFEA7421016000000003C0A0400D1
-:1032200035490030AF4910000000000000000000E8
-:1032300000000000000000008F4C10000581FFFE20
-:10324000000000009749100C8F51101C00C0202175
-:103250003127FFFF24F2003000121882000328807B
-:1032600000BBF8213226FFFFAFF100000E000595EC
-:1032700000112C020013C880033B98218E780000B7
-:1032800000027400AFB800108FA80010310FFFFFCC
-:10329000AFAF00108FA4001001C46825AFAD0010BF
-:1032A0008FA60010AE66000097730008976D000AA5
-:1032B0009766000C8F8A003C000D5C0030CCFFFF4D
-:1032C0003262FFFF104A0036016C2025960600028C
-:1032D0003C10100024D300080E0001393264FFFFB7
-:1032E000974C01040E0001473184FFFFAF50017875
-:1032F0008FBF00288FB300248FB200208FB1001C35
-:103300008FB0001803E0000827BD003010A0FF7048
-:103310000000000024A5FFFC0A0005CE24090004DB
-:103320008CD10000AF5110188F5301780660FF7ADE
-:103330002404000A0A0005E30000000000A7C821D9
-:103340008F8800388F4E101C0019C08200187880BA
-:1033500001E82021AC8E0000000E2C0200C02021CC
-:103360000E00059531C6FFFF023B28218CAD000001
-:103370000002540000403021AFAD00108FAC0010AF
-:10338000318BFFFFAFAB00108FA200100142482528
-:10339000AFA900108FA700100A000613ACA7000009
-:1033A0008F8F0040148FFFC9000000009742010476
-:1033B000960B00023C0508008CA5046C3049FFFF09
-:1033C000316AFFFF3C1108008E310468012A382160
-:1033D00024F2FFFE00B240210012FFC30112C82BED
-:1033E000023FC021031920213C010800AC28046CD5
-:1033F0003C010800AC2404680A00064D00000000EF
-:1034000000A4102B104000092403000100052840EF
-:1034100000A4102B04A00003000318405440FFFC3C
-:103420000005284010600007000000000085302BD8
-:1034300014C0000200031842008520231460FFFB23
-:103440000005284203E00008008010218F85002C31
-:1034500027BDFFE8000530272CC300012CA4000283
-:103460000083102510400003AFBF00102405007F2B
-:10347000AF85002C0005282730A5FFFF0E0005743E
-:10348000240426F58F830030240402BD004030213F
-:103490000083382B10E000092405000100042040BF
-:1034A0000083102B04800003000528405440FFFCDB
-:1034B0000004204010A0000800C350210064402BED
-:1034C00015000002000528420064182314A0FFFB29
-:1034D0000004204200C350218FBF0010000A4C029C
-:1034E000312200FF27BD0018AF8A002C03E000083E
-:0434F000AF89003070
-:0C34F4000A00002A000000000000000098
-:103500000000000D747870352E302E306A360000C1
-:10351000050000000000000A000001360000EA601B
-:10352000000000000000000000000000000000009B
-:10353000000000000000000000000000000000008B
-:10354000000000000000000000000000000000007B
-:103550000000000000000016000000000000000055
-:10356000000000000000000000000000000000005B
-:10357000000000000000000000000000000000004B
-:1035800000000000000000000000000000001388A0
-:1035900000000000000005DC00000000000000004A
-:1035A00010000003000000000000000D0000000DEE
-:1035B0003C02080024423B603C03080024633D14A5
-:1035C000AC4000000043202B1480FFFD2442000487
-:1035D0003C1D080037BD7FFC03A0F0213C10080013
-:1035E000261000A83C1C0800279C3B600E0002BA75
-:1035F000000000000000000D8F8300383C088000B0
-:10360000350700708CE50000008330253C029000F7
-:1036100000C22025AF850030AF4400208F49002034
-:103620000520FFFE3C038000346200708C450000E2
-:103630008F8600303C1908008F39007C3C0E080052
-:103640008DCE007800A62023032458210000782185
-:103650000164682B01CF6021018D50213C010800DD
-:10366000AC2B007C3C010800AC2A007803E0000889
-:10367000000000000A000041240400018F8400388B
-:103680003C05800034A200010082182503E00008F8
-:10369000AF43002003E00008000010213084FFFF4A
-:1036A00030A5FFFF108000070000182130820001C4
-:1036B0001040000200042042006518211480FFFB26
-:1036C0000005284003E000080060102110C000073A
-:1036D000000000008CA2000024C6FFFF24A5000407
-:1036E000AC82000014C0FFFB2484000403E0000847
-:1036F0000000000010A0000824A3FFFFAC8600001B
-:1037000000000000000000002402FFFF2463FFFF10
-:103710001462FFFA2484000403E0000800000000A3
-:10372000308AFFFF93A80013A74A014497490E1659
-:1037300030C600FF3C021000A7490146AF450148D2
-:10374000A3460152A748015AAF4701608FA4001851
-:103750008FA30014A7440158AF43015403E00008AD
-:10376000AF42017803E00008000000003C03800045
-:10377000346200708C4900008F88000024840007A8
-:1037800027BDFFF83084FFF8AF890030974D008ADD
-:1037900031ACFFFFAFAC00008FAB000001685023DD
-:1037A0002547FFFF30E61FFF00C4282B14A0FFF7BA
-:1037B0003C0C8000358B00708D6A00003C070800CF
-:1037C0008CE700843C0608008CC60080000810824C
-:1037D000014918230002788000E3702100002021B5
-:1037E00001C3C82B00C4C02101FA4021031948219C
-:1037F0002502400027BD00083C010800AC2E0084D3
-:103800003C010800AC29008003E000080000000033
-:103810008F8200002486000730C5FFF800A218211F
-:1038200030641FFF03E00008AF8400008F8700387A
-:103830008F8A004027BDFFB88F860044AFB6004096
-:10384000AFBF0044AFB5003CAFB40038AFB30034F5
-:10385000AFB20030AFB1002CAFB000288F450104EB
-:103860008D4900ACAF4700808CC8002000A93823E8
-:103870000000B021AF480E108F440E100000482108
-:10388000AF440E148CC20024AF420E188F430E18A2
-:10389000AF430E1C10E001252D230001936B00089F
-:1038A000116000D400000000976E001031CDFFFFC2
-:1038B00000ED602B158000CF000000009770001015
-:1038C000320FFFFFAF4F0E008F5200003251000841
-:1038D0001220FFFD0000000097540E088F460E04D2
-:1038E0003285FFFF30B3000112600132000000009A
-:1038F0000000000D30B8A04024150040131500C092
-:1039000030A9A0001120012D00000000937F0008C5
-:1039100013E000080000000097630010306BFFFF09
-:1039200000CB402B1100000330AC0040118001237C
-:1039300000000000A785003CAF86003493660008B5
-:1039400000E02821AFA7002014C0012427B30020E5
-:10395000AF60000C9782003C3047400014E000024A
-:10396000240300162403000E24194007A363000A51
-:10397000AF790014938A003E8F7400143158000709
-:103980000018AA4002959025AF7200149784003C5D
-:103990008F7000143091001002117825AF6F001461
-:1039A000978E003C31CD000811A00147000028216E
-:1039B0008F6700143C0210003C0C810000E22825B7
-:1039C000AF65001497460E0A2408000E3405FFFC6C
-:1039D00030C3FFFF006C5825AF6B0004A3680002E2
-:1039E000937F000A27E90004A369000A9786003C38
-:1039F0009363000A30CC1F00000C598301634021FF
-:103A0000251F0028A37F000997490E0CA769001005
-:103A100093790009272A0002315800070018A823CB
-:103A200032B10007A371000B937400099764001072
-:103A30008F910034978F003C329200FF0244802126
-:103A40000205702131ED004011A0000531C4FFFFD7
-:103A50000091282B3C12800010A000140000A0212F
-:103A60000224382B14E0011B8FA500208F4D0E146B
-:103A7000AF4D0E108F420E1CAF420E18AF440E0019
-:103A80008F4F000031EE000811C0FFFD0000000064
-:103A900097540E080080882100009021A794003CD4
-:103AA0008F500E0424140001AF900034976400106E
-:103AB0003095FFFF8E6800000111F82317E0000920
-:103AC000AE7F00008F6500148F8B004434A6004049
-:103AD000AF6600148F4C0E10AD6C00208F430E1893
-:103AE000AD6300249367000814E000D200000000DA
-:103AF0000E00009E240400108F8900483C0832000C
-:103B000000402821312600FF0006FC0003E8502574
-:103B100025390001AF990048AC4A000093780009AC
-:103B20009370000A330400FF00047400320F00FF9A
-:103B300001CF6825AC4D00048F820048064000EAA2
-:103B4000ACA20008ACA0000C9783003C306B0008CE
-:103B5000156000022628000626280002974E0E1443
-:103B60008F450E1C8F670004936D000231C4FFFF68
-:103B700031A200FFAFA200108F6C0014AFA8001894
-:103B80000E00008BAFAC0014240400100E0000C720
-:103B9000000000008E7200001640000500000000CA
-:103BA0008F6400142405FFBF00859824AF730014B0
-:103BB0008F79000C03353821AF67000C937500082E
-:103BC00016A000080000000012800006000000009F
-:103BD0008F7F00143C0BEFFF3568FFFE03E848249D
-:103BE000AF690014A37400088FA500200A000246E4
-:103BF00002202021AF470E000A0000F5000000005F
-:103C00008F5901780720FFFE241F08008F840000D1
-:103C1000AF5F0178974B008A316AFFFF0144482368
-:103C20002528FFFF31021FFF2C4300081460FFF915
-:103C3000000000008F8E00488F8D003800C04821A2
-:103C40000344202125C60001240C0F00AF86004844
-:103C500000E938232486400031CA00FF11AC00057A
-:103C6000240800019391003E3230000700107A4092
-:103C700035E80001000AAC003C18010002B8A0259C
-:103C8000AC9440008F93004830B2003630A4000856
-:103C9000ACD300041080009701123025974E0E0A15
-:103CA0008F8D00003C02810031CCFFFF25AB000866
-:103CB000018240253C03100031651FFF25390006B5
-:103CC000241F000EAF48016000C33025A75F015AD2
-:103CD000AF850000A759015814E0000A8F930038FF
-:103CE00024120F00527200022416000134C6004054
-:103CF0008F580E108F940044AE9800208F550E18E8
-:103D0000AE9500248F450E14AF4501448F590E1C0B
-:103D1000AF590148A34A01523C0A1000AF46015472
-:103D2000AF4A017814E0FEDD2D2300010076A025C6
-:103D3000128000178FBF00448F84003824160F00B4
-:103D400010960084000000008F45017804A0FFFE5B
-:103D500024150F001095006E000000008F470E1410
-:103D6000240202403C1F1000AF4701448F440E1C48
-:103D7000AF440148A3400152A740015AAF4001603F
-:103D8000A7400158AF420154AF5F01788FBF004494
-:103D90008FB600408FB5003C8FB400388FB300342D
-:103DA0008FB200308FB1002C8FB0002803E00008E4
-:103DB00027BD004814C0FED030B8A0408F420E147A
-:103DC0008F84004400004821AC8200208F510E1CDB
-:103DD000AC9100240A00020E2D2300018F910034C3
-:103DE000978A003C3C1280000220A82131580040F4
-:103DF0001700FF300000A021976900108F92003457
-:103E00003139FFFF133200350000202100804821A6
-:103E10001480FEA000A038218F420E148F8400442D
-:103E2000AC8200208F510E1CAC9100240A00020EBF
-:103E30002D230001936A00099378000B315000FF95
-:103E4000330F00FF020F702125C2000A3050FFFF20
-:103E50000E00009E020020218F8600483C1F41007A
-:103E600024CD0001AF8D0048936C000930C600FFDF
-:103E700000064400318300FF246B0002010B48253B
-:103E8000013FC825AC5900008F67000C97440E1401
-:103E900000F22825AC4500048F450E1C8F670004F6
-:103EA000936A00023084FFFF315800FFAFB8001062
-:103EB0008F6F0014AFB100180E00008BAFAF00146D
-:103EC0000A0001A602002021AF6000040A00013EA2
-:103ED000A36000020A000246000020210000902199
-:103EE0000A000170241400013C1280000A000195B0
-:103EF000ACB2000C8F91000025240002A7440158A9
-:103F000026300008320F1FFF0A0001F9AF8F0000B2
-:103F1000AF40014C1120002C000000008F590E1002
-:103F2000AF5901448F430E18240200403C1F10007B
-:103F3000AF430148A3400152A740015AAF4001607E
-:103F4000A7400158AF420154AF5F01780A00022731
-:103F50008FBF0044112000060000000097460E08A5
-:103F600030CC004015800002000000000000000D71
-:103F70008F4D017805A0FFFE0000000097530E1042
-:103F80003C120500240E2000326AFFFF0152C025BA
-:103F9000AF58014C8F4F0E143C021000AF4F01443C
-:103FA0008F500E1CAF500148A34001528F8400383F
-:103FB000A740015AAF400160A7400158AF4E0154DD
-:103FC0000A000215AF4201788F490E14AF4901442F
-:103FD0008F430E1C0A00028E240200403C0E20FF7C
-:103FE00027BDFFE03C1A80003C0F800835CDFFFD67
-:103FF000AFBF001CAFB20018AFB10014AFB00010DB
-:10400000AF8F0040AF4D0E00000000000000000028
-:104010000000000000000000000000003C0C00FF59
-:10402000358BFFFDAF4B0E003C0660048CC9500081
-:10403000240AFF7F3C116000012A40243507380C18
-:10404000ACC750008E24043824050009AF45000891
-:104050003083FFFF38622F712450C0B3AF80004817
-:104060000E000068AF80000052000001AE20442C1A
-:104070000E0004353C1180000E000EA83630007092
-:104080008F8A00403C12080026523BC8020088215B
-:104090008E0800008F5F00003BF9000133380001FB
-:1040A00013000017AF880030022048218D27000040
-:1040B0003C0F08008DEF006C3C0C08008D8C0068F4
-:1040C00000E8C02301F828210000682100B8302B47
-:1040D000018D5821016640213C010800AC25006C8F
-:1040E0003C010800AC2800688F44000038830001C0
-:1040F000306200011440FFED00E04021AF87003046
-:104100008E0C00003C0508008CA5006C3C040800E7
-:104110008C8400680188302300A63821000010211B
-:1041200000E6402B008218210068F8213C010800BD
-:10413000AC27006C3C010800AC3F00688F490100CF
-:1041400025590088AF990044AF890038AF49002055
-:104150008E070000AF8700308F4D017805A0FFFE6D
-:10416000000000008E0600003C0B08008D6B007400
-:104170003C0408008C84007000C728230165F821E6
-:104180000000102103E5402B0082382100E8C821FF
-:10419000240908003C010800AC3F00743C01080001
-:1041A000AC390070AF49017893580108A398003EDC
-:1041B000938F003E31EE000115C000158F8300384B
-:1041C000240E0D00106E0019240F0F00106F001D3B
-:1041D000000000009159000024180050332900FF0E
-:1041E000113800043C1F4000AF5F01380A0002E7AD
-:1041F000000000000E0008EE000000008F8A004062
-:104200003C1F4000AF5F01380A0002E700000000D9
-:10421000938D003E31AC0006000C51000E0000CE24
-:104220000152D8210A0003438F8A00403C1B08003A
-:10423000277B3C480E0000CE000000000A0003432C
-:104240008F8A00403C1B0800277B3C680E0000CE94
-:10425000000000000A0003438F8A004090AA00017A
-:104260008FAB00108CAC00103C0300FF8D68000485
-:10427000AD6C00208CAD001400E060213462FFFFC3
-:10428000AD6D00248CA700183C09FF000109C02473
-:10429000AD6700288CAE001C0182C8240319782564
-:1042A000AD6F0004AD6E002C8CAD0008314A00FFEC
-:1042B000AD6D001C94A900023128FFFFAD6800100D
-:1042C00090A70000A5600002A1600004A1670000A3
-:1042D00090A30002306200FF000219821060000506
-:1042E000240500011065000E0000000003E0000836
-:1042F000A16A00018CD80028354A0080AD780018EA
-:104300008CCF0014AD6F00148CCE0030AD6E000861
-:104310008CC4002CA16A000103E00008AD64000C0D
-:104320008CCD001CAD6D00188CC90014AD69001453
-:104330008CC80024AD6800088CC70020AD67000C55
-:104340008CC200148C8300640043C82B1320000728
-:10435000000000008CC20014144CFFE400000000B8
-:10436000354A008003E00008A16A00018C820064E5
-:104370000A0003990000000090AA000027BDFFF882
-:104380008FA9001CA3AA00008FAE00003C0FFF8085
-:104390008FA8001835E2FFFF8CCD002C01C26024ED
-:1043A000AFAC0000A120000400E06021A7A0000243
-:1043B0008FB800008D2700040188182100A0582123
-:1043C00000C05021006D28263C06FF7F3C0F00FFF7
-:1043D0002CAD000135EEFFFF34D9FFFF3C02FF009A
-:1043E00003193024000D1DC0010EC82400E2C024B2
-:1043F00000C3702503197825AD2E0000AD2F0004F1
-:104400008D450024AFAE0000AD2500088D4D002085
-:104410002405FFFFAD2D000C956800023107FFFF5A
-:10442000AD2700109166001830C200FF000219C2CB
-:10443000506000018D450034AD2500148D670008E3
-:1044400027BD0008AD27001C8C8B00CCAD2C0028AC
-:10445000AD20002CAD2B0024AD20001803E0000897
-:10446000AD20002027BDFFE0AFB20018AFB10014AF
-:10447000AFB00010AFBF001C9098000000C08821B2
-:104480003C0D00FF330F007FA0CF0000908E000195
-:1044900035ACFFFF3C0AFF00A0CE000194A6001E31
-:1044A000A22000048CAB00148E29000400A08021FF
-:1044B000016C2824012A4024008090210105202538
-:1044C000A6260002AE2400042605002026240008AB
-:1044D0000E00007624060002924700002605002800
-:1044E0002624001400071E000003160324060004FF
-:1044F000044000032403FFFF965900023323FFFF0B
-:104500000E000076AE230010262400248FBF001C6E
-:104510008FB200188FB100148FB000102405000373
-:10452000000030210A00008027BD002027BDFFD8F1
-:10453000AFB1001CAFB00018AFBF002090A80000C2
-:10454000240200018FB0003C3103003F008088212D
-:10455000106200148FAA0038240B0005506B00165F
-:10456000AFAA001000A0202100C028210E0003DC0B
-:1045700002003021922400BC30830002106000034E
-:1045800026060030ACC0000024C600048FBF002007
-:104590008FB1001C8FB0001800C0102103E000088C
-:1045A00027BD0028014038210E00035AAFB000108B
-:1045B0000A000420000000000E0003A1AFB00014A8
-:1045C0000A000420000000003C02000A03421821F7
-:1045D0003C04080024843CAC2405001A000030216F
-:1045E0000A000080AF8300543C03800034620070F6
-:1045F0008C48000000A0582100C04821308A00FFEC
-:10460000AF8800308F4401780480FFFE3C0C8000AE
-:10461000358600708CC500003C0308008C63007474
-:104620003C1808008F18007000A82023006468213F
-:104630000000C82101A4782B0319702101CF60214B
-:104640003C010800AC2D00743C010800AC2C00704B
-:104650008F480E14AF480144AF47014CA34A0152A2
-:10466000A74B01589346010830C5000854A000012B
-:1046700035291000934B090024070050316A00FFD0
-:1046800011470007000000008F450E1CAF45014890
-:10469000AF4901543C09100003E00008AF4901781C
-:1046A000934D010831A8000811000010000000001F
-:1046B000934F010831EE001051C000013529000868
-:1046C0003C04080090843D10A34401508F4309A48A
-:1046D000AF4301488F4209A0AF420144AF490154A2
-:1046E0003C09100003E00008AF4901783C190800BC
-:1046F0008F393CCC333800085700FFF135290008CA
-:104700000A0004730000000024070040AF470814AB
-:10471000AF4008108F4209448F4309508F44095419
-:104720008F45095C8F46094CAF820064AF8300500F
-:10473000AF84004CAF85005C03E00008AF860060EA
-:104740009346010930C5007F000518C000052140CF
-:104750000083102103E00008244200883C0A08007E
-:10476000914A3CD13C09080095293CCA3C051100FE
-:10477000000A3C002528000200E8302500C5182565
-:1047800024820008AC83000003E00008AC80000431
-:104790008F4A002C974E09083C0F000E034F38211A
-:1047A00031CDFFFF000D41C0AF48002C97430908F1
-:1047B00094EC001A0080402124020001318BFFFF9D
-:1047C000AC8B00008CE9001C00A0582100C06021C7
-:1047D000AC8900048CE40020AD04000890E30019CB
-:1047E00030630003106200400000000028650002F2
-:1047F00014A00073240600021066004E00000000A2
-:104800002418000310780057000000003C0908003D
-:1048100095293CC093450934934609213C0E080074
-:1048200095CE3CC630A200FF0002C88294E5002A63
-:1048300030C400FF978700580019C60000041C0010
-:10484000312FFFFF0303102501CF6821004DC8253C
-:1048500000A720213C0640000326C02500044C0090
-:10486000AD090004AD180000934F09203C03000679
-:1048700025090014000F760001C36825AD0D00085E
-:104880008F42092C24E5000130A67FFFAD02000C09
-:104890008F59093025020028A7860058AD1900104D
-:1048A0008F440938AD040014AD2B00048F58094023
-:1048B000AD380008934F09373C0D080091AD3CD04E
-:1048C000AD20001031EE00FF01CC1821000367007D
-:1048D000000D4400018858253567FFFFAD27000C07
-:1048E00003E00008AF4A002C3C09080095293CC0B1
-:1048F0003C05080094A53CCA3C0F080095EF3CBC61
-:1049000094E400243126FFFF00A6702101CF682324
-:1049100000041C0025A2FFF20062C825241808002C
-:10492000AD19000CAD180014AD0000100A0004C849
-:104930002508001894E6002494E500283C090800A6
-:1049400095293CC000067C000005740035ED81000F
-:1049500035C40800AD0D000CAD0400100A0004C8F9
-:10496000250800143C09080095293CC03C020800B9
-:1049700094423CCA3C06080094C63CBC94E4002423
-:104980003125FFFF94F800280045C821032678232D
-:1049900000181C0000046C0025EEFFEE006EC82518
-:1049A00035A2810024180800AD02000CAD190010DA
-:1049B000AD180018AD0000140A0004C82508001C3A
-:1049C0001460FF920000000094E300243C090800FA
-:1049D00095293CC00003140034590800AD19000C9F
-:1049E0000A0004C82508001003E00008240201F4AE
-:1049F00027BDFFE8AFB00010AFBF00140E0000608D
-:104A00000080802124050040AF4508148F830050AA
-:104A10008F84004C8F85005C007018210064102387
-:104A200018400004AF830050AF6300548F660054F9
-:104A3000AF86004C1200000C000000008F44007490
-:104A4000936800813409FA002D07000710E0000583
-:104A500000891021936C0081240B01F4018B500418
-:104A600001441021AF62000C8F4E095C01C5682320
-:104A700019A000048FBF00148F4F095CAF8F005C3A
-:104A80008FBF00148FB000100A00006227BD00180D
-:104A90008F8400648F8300508F82004CAF64004489
-:104AA000AF63005003E00008AF6200543C03800095
-:104AB000346200708C43000027BDFFF8308700FF90
-:104AC00030A900FF30C800FFAF8300308F44017869
-:104AD0000480FFFE3C028000345900708F380000D3
-:104AE000A3A700033C0708008CE700748FAC00000C
-:104AF0003C0608008CC60070030378233C0E7FFF41
-:104B000000EFC82135CDFFFF00005021018D282482
-:104B100000CA1821000847C0032F202B00A8102529
-:104B20000064C021AFA200003C010800AC39007451
-:104B30003C010800AC380070934F010AA3A00002AA
-:104B40003C0E80FFA3AF00018FAC0000312B007F33
-:104B500035CDFFFF018D4824000B5600012A40256A
-:104B6000240730002406FF803C05100027BD000804
-:104B7000AF48014CAF470154A7400158A34601522A
-:104B800003E00008AF45017827BDFFE8AFBF001480
-:104B9000AFB000108F6500743C068000309000FFBD
-:104BA00000A620250E000060AF640074936300052A
-:104BB000346200080E000062A3620005020020219A
-:104BC0008FBF00148FB000102405000524060001DB
-:104BD0000A00056E27BD001827BDFFE03C038000DA
-:104BE000AFB00010AFBF0018AFB100143462007056
-:104BF0008C470000309000FF30A800FFAF870030E6
-:104C00008F4401780480FFFE3C188000371100704B
-:104C10008E2F00003C0D08008DAD00743C0A08008A
-:104C20008D4A007001E7702301AE28210000582151
-:104C300000AE302B014B4821012638213C010800F1
-:104C4000AC250074000088213C010800AC270070EE
-:104C50001100000F000000008F6200742619FFFF92
-:104C60003208007F0002FE0233E5007F15000006D7
-:104C7000332200FF2407FF800207202624A3FFFF22
-:104C800000838025320200FF00408021241110089B
-:104C90000E000060000000008F4908183125000454
-:104CA00014A0FFFD3218007F001878C00018714072
-:104CB00001CF682125AC0088AF4C0818274A09802D
-:104CC0008D4B0020AF4B01448D460024AF46014878
-:104CD000A35001500E000062A7400158022010218D
-:104CE0008FBF00188FB100148FB0001003E00008D0
-:104CF00027BD002027BDFFE8308400FFAFBF0010B4
-:104D00000E0005B930A500FF8F8300508FBF001043
-:104D1000344500402404FF903C02100027BD0018D9
-:104D2000AF43014CA3440152AF45015403E00008D6
-:104D3000AF4201789343093E306200081040000DF5
-:104D40003C0901013528080AAC8800008F4700742F
-:104D5000AC8700043C06080090C63CD030C500106B
-:104D600050A00006AC8000088F6A0060AC8A000882
-:104D70002484000C03E00008008010210A000620B3
-:104D80002484000C27BDFFE8AFBF0014AFB00010B3
-:104D90009346093F00A05021000528800085382354
-:104DA00030C200FF240300063C09080095293CC6D8
-:104DB00024E8FFD82405000410430037240600022D
-:104DC0009750093C3C0F020400063400320EFFFFEE
-:104DD00001CF6825AC8D0000934C093E318B00203B
-:104DE0001160000800000000934309363C020103F3
-:104DF000345F0300307900FF033FC025240500081D
-:104E0000AC98000493430934935909210005F882B2
-:104E1000306200FF0002C082332F00FF00186E00D6
-:104E2000000F740001AE6025018920253C09400077
-:104E300000898025ACF0FFD8934309378F4F09488C
-:104E40008F580940306200FF004AC821033F70219B
-:104E500001F86023000E6F0001A650253185FFFF89
-:104E6000001F58800145482501683821AD09002000
-:104E70000E00006024F00028240400040E000062EC
-:104E8000A364003F020010218FBF00148FB00010F8
-:104E900003E0000827BD00180A00063324060012AC
-:104EA00027BDFFD024090010AFB60028AFB50024FD
-:104EB000AFB40020AFB10014AFB000103C01080047
-:104EC000A0293CD0AFBF002CAFB3001CAFB200187C
-:104ED00097480908309500FF3C02000E3107FFFF9C
-:104EE000000731C0AF46002C974409089344010BDA
-:104EF00030B400FF03428021308300300000B02135
-:104F00001060010700008821240C00043C01080007
-:104F1000A02C3CD0934B093E000B5600000A2E03F8
-:104F200004A0014B00000000AF400048934F010B6C
-:104F300031EE002011C00006000000009358093E29
-:104F400000189E00001396030640016B000000004D
-:104F50009344010B30830040106000038F93005096
-:104F60008F8200502453FFFF9347093E30E600082C
-:104F700014C0000224120003000090219619002C96
-:104F800093580934934F0937A7990058330C00FF01
-:104F900031EE00FF024E6821000D5880016C502157
-:104FA000015140213C010800A4283CC6920500188C
-:104FB00030A900FF010918213C010800A4233CC8C6
-:104FC00092110018162000032467000A0000000D4B
-:104FD0002467000A30F0FFFF3C010800A4233CCA0C
-:104FE0003C010800A4203CC03C010800A4203CBCBB
-:104FF0000E00009E020020210E00049A0040202195
-:105000008F4B002C974A09083C0C000E034C3821AA
-:105010003145FFFF000549C0AF49002C97430908FF
-:1050200094F1001A00404021241F00013226FFFFA6
-:10503000AC4600008CE2001CAD0200048CE40020B1
-:10504000AD04000890E3001930630003107F00D620
-:10505000286D000215A0011C240E0002106E010E26
-:10506000240F0003106F00E3000000003C0908005B
-:1050700095293CC0934E0934935109213C0A0800FC
-:10508000954A3CC631CD00FF94F9002A000D1882E4
-:1050900097870058322C00FF00032E00000C2400DC
-:1050A0003126FFFF3142FFFF00A4F82500464821CA
-:1050B00003E97825032770213C18400001F8682592
-:1050C000000E8C00AD0D0000AD110004934C0920C2
-:1050D0003C03000625110014000C2E0000A310252F
-:1050E000AD0200088F49092C24E40001309F7FFFA6
-:1050F000AD09000C8F46093025090028A79F0058EC
-:10510000AD0600108F59093801203021AD19001467
-:10511000AE3300048F580940AE380008934F09376A
-:105120003C0C0800918C3CD0AE20001031EE00FF0A
-:1051300001D26821000D2F00000C1C0000A31025D7
-:105140003447FFFFAE27000CAF4B002C934B093EBA
-:10515000317300081260000D3C0F010135E7080AA9
-:10516000AD0700288F4B0074AD2B00043C130800E2
-:1051700092733CD03268001051000003AD2000084B
-:105180008F780060AD3800082526000C12C000386A
-:1051900000000000935F093F241600062407000466
-:1051A00033F900FF133600D2240800029743093C6C
-:1051B0003C0C02043064FFFF008C2825ACC50000C5
-:1051C0009342093E304900201120000800000000F1
-:1051D000934B09363C130103366E0300316D00FF1B
-:1051E00001AE8825ACD10004240700089349093496
-:1051F00093590921314BFFFF313F00FF001FB0825F
-:10520000333800FF0016560000187C00014F982527
-:1052100000122880026B68253C0E400000C5502318
-:1052200001AE8825AD51FFD8934309378F5F0948F8
-:105230008F490940306C00FF019210210007208245
-:105240000044C82103E978230019C7000008B4000E
-:105250000316402531E7FFFF010730250E000060EF
-:10526000AD46FFF8241200040E000062A372003F56
-:105270000E0000C7020020213C12080092523CD0D0
-:10528000325000031200000F02A020218F82005034
-:1052900024470001AF870050AF6700508F6800546B
-:1052A0000107302318C0000200E020218F64005461
-:1052B000AF6400548F4C0074258401F4AF64000C7B
-:1052C00002A0202102802821A76000680E0005B9F5
-:1052D0003C1410008F8D005034550006AF4D014C2A
-:1052E0008F9100488FBF002C8FB600282623000125
-:1052F000AF8300488FB3001CA35101528FB2001836
-:10530000AF5501548FB10014AF5401788FB500240C
-:105310008FB400208FB0001003E0000827BD0030DC
-:105320009358093E00189E00001396030642005150
-:105330002411000293440923308300021060FEFB15
-:105340008F8600608F82005014C2FEF800000000BB
-:105350000E000060000000009369003F2407001663
-:10536000312800FF1107000C240500083C0C080040
-:10537000918C3CD0358B00013C010800A02B3CD027
-:10538000936A003F314300FF10650065240D000A59
-:10539000106D005E2402000C0E0000620000000090
-:1053A0000A00068E000000003C09080095293CC058
-:1053B0003C04080094843CCA3C1F080097FF3CBC96
-:1053C00094F800243123FFFF0083C821033F782392
-:1053D00000186C0025EEFFF201AE6025240A0800DB
-:1053E000AD0C000CAD0A0014AD0000100A0006E080
-:1053F000250800183C09080095293CC03C1F0800FE
-:1054000097FF3CCA3C19080097393CBC94EF002434
-:105410003124FFFF94EE002803E4C0210319682320
-:10542000000F2C00000E540025ACFFEE014C882527
-:1054300034A2810024060800AD02000CAD1100105A
-:10544000AD060018AD0000140A0006E02508001C97
-:105450008F6E00848F4D094011A0FEB3AF8E0050B7
-:10546000240F00143C010800A02F3CD00A00068D38
-:10547000000000003C010800A0313CD0935F093ED1
-:105480002416000133F900201720FEA8241100087B
-:105490000A00068E2411000494E5002494F10028EB
-:1054A0003C09080095293CC0000514000011340097
-:1054B0003444810034C30800AD04000CAD03001077
-:1054C0000A0006E0250800141460FEE80000000051
-:1054D00094FF00243C09080095293CC0001FCC0023
-:1054E00037380800AD18000C0A0006E02508001047
-:1054F0000A00072E240800128F7F004CAF7F005453
-:105500008F7900540A000697AF790050A362003FDC
-:105510000E000062000000000A00068E000000007D
-:10552000240200140A000807A362003F27BDFFE819
-:10553000308400FFAFBF00100E0005B930A500FF9A
-:105540009378007E9379007F936E00809368007A51
-:10555000332F00FF00186600000F6C0031CB00FFF6
-:10556000018D4825000B52008FBF0010012A3825FD
-:10557000310600FF3444700000E628252402FF8134
-:105580003C03100027BD0018AF45014CAF44015447
-:10559000A342015203E00008AF43017827BDFFD8C2
-:1055A000AFB20018AFB10014AFB00010AFBF002011
-:1055B000AFB3001C93420109308600FF30B000FFFA
-:1055C000000618C232040002307100011480000588
-:1055D000305200FF9367000530E5000810A0000D71
-:1055E00030C80010024020210E0005A5022028210D
-:1055F000240400018FBF00208FB3001C8FB200185D
-:105600008FB100148FB000100080102103E000085B
-:1056100027BD002815000032000000009343010957
-:10562000000028213062007F000220C00002F94003
-:1056300003E4982126790088033B98218E78002482
-:105640008E6F0008130F0046000000008F64008476
-:10565000241800020004FD8233F900031338007C93
-:105660000000000093660083934A0109514600043C
-:105670003205007C10A00060000000003205007CB4
-:1056800014A000530240202116200006320400011D
-:105690008E7F00248F59010417F9FFD600002021C6
-:1056A000320400011080000A024020218F4209408C
-:1056B0008F93006410530006000000000E00066B7C
-:1056C000022028218F430940AF630044024020217B
-:1056D0000E000600022028210A00084024040001D0
-:1056E0003C0908008D290064252600013C010800C2
-:1056F000AC26006416000012000000008F6D0084CC
-:105700003C0E00C001AE602415800005024020213F
-:105710000E00080E022028210A000840240400017F
-:10572000240500040E00056E24060001024020211D
-:105730000E00080E022028210A000840240400015F
-:105740000E00004124040001936B007D020B5025E4
-:105750000E000062A36A007D0A0008838F6D00843A
-:105760008F6600748F4801048E67002400064E0285
-:105770001507FFB63126007F936B00832644000196
-:10578000308A007F11460043316300FF5464FFB04C
-:105790008F6400842645000130B1007F30A200FFF5
-:1057A0001226000424050001004090210A0008563A
-:1057B00024110001240FFF80024F702401CF902696
-:1057C000324200FF004090210A00085624110001D7
-:1057D0000E00066B02202821321800301300FFAAA9
-:1057E00032100082024020210E0005A5022028214F
-:1057F0000A000840240400018F6E00743C0F8000F2
-:105800002405000301CF9025AF72007493710083CB
-:10581000240600010E00056E322400FF0E00004138
-:1058200024040001936D007D020D60250E000062CE
-:10583000A36C007D3C0B08008D6B005425700001AB
-:105840003C010800AC3000540A0008402404000168
-:105850008F6800743C098000240500040109382584
-:10586000AF67007493630083240600010E00056E89
-:10587000306400FF0E000041240400019362007DAB
-:10588000020298250E000062A373007D0A00084002
-:1058900024040001324D008039AC0080546CFF6C50
-:1058A0008F6400840A0008A92645000127BDFFC8AF
-:1058B0003C0A0008AFBF0030AFB5002CAFB40028E1
-:1058C000AFB30024AFB20020AFB1001CAFB00018DE
-:1058D000034AD82124090040AF490814AF400810FA
-:1058E0008F4209448F4309508F4609548F47095C02
-:1058F0008F48094C934401089345010BAF82006423
-:10590000308400FF30A500FFAF830050AF86004C0D
-:10591000AF87005C0E00082AAF8800601440017455
-:105920008FBF0030A7600068934D0900240B005022
-:105930003C15080026B53C8831AC00FF3C1208003D
-:1059400026523C98118B0003000000000000A821A3
-:1059500000009021935101098F9F005024040010F2
-:10596000322E007F000E68C0000E6140018D28219C
-:1059700024B40088AF5408188F4901048F4A09A441
-:105980003C0B000E034BC021012A10233C010800F0
-:10599000AC223CAC8F4309583C010800A0243CD009
-:1059A00097470908007F30233C010800AC263CB033
-:1059B00030E8FFFF0008C9C03C010800AC3F3CD400
-:1059C000AF59002C974209089710002C8EB10000A7
-:1059D000930F001803749821A7900058AF930044C8
-:1059E0000220F80931F000FF304E000215C001A975
-:1059F000304F000111E0015D000000009343093EBB
-:105A00003066000814C00002241400030000A02126
-:105A10008F5809A4241300013C010800AC383CD87D
-:105A2000934F09349351093731EC00FF322E00FFB8
-:105A3000028E6821000D288000AC502101505821B1
-:105A40003C010800A42B3CC83C010800A42A3CC629
-:105A500093490934312200FF0202202124900010D2
-:105A60003C010800A4303CC4240700068F9F00506E
-:105A70003C010800AC273CCC8F88005C8F5909584A
-:105A800000008021011F282304A00151033F20238F
-:105A90000480014F00A4302B10C001510000000011
-:105AA0003C010800AC253CB08E4200000040F809E3
-:105AB0000000000030430002146000F10040882123
-:105AC00030440001548000108E4200043C0908005C
-:105AD0008D293CB43C0AC000012A8025AF500E003D
-:105AE0008F45000030AB00081160FFFD0000000092
-:105AF000974D0E0824100001A78D003C8F4C0E041A
-:105B0000AF8C00348E4200040040F8090000000011
-:105B100002228825322E000215C0016F000000000D
-:105B20003C09080095293CBC3C06080094C63CC8CA
-:105B30003C04080094843CBE3C1808008F183CB418
-:105B4000012658213C0F08008DEF3CD83C1F08006F
-:105B500097FF3CD2016418218F4D09400309C821E9
-:105B6000246E0002033F282101F860213C01080057
-:105B7000A42B3CCAAF8D00643C010800AC2C3CD87F
-:105B80003C010800A4253CC00E00009E31C4FFFF6C
-:105B90008F870048004020213C010800A0273CD10D
-:105BA0008E42000824E80001AF8800480040F80950
-:105BB000000000008F4B002C974909083C0A000E9A
-:105BC000034A38213124FFFF000419C08F8A005096
-:105BD000AF43002C9743090894E6001A0040402187
-:105BE00030DFFFFFAC5F00008CF9001CAC590004F3
-:105BF0008CF80020AC58000890EF001931E3000346
-:105C0000107300FB0000000028620002144001171E
-:105C10002405000210650109240C0003106C00BC6F
-:105C2000000000003C09080095293CC0935F09343E
-:105C3000934C09213C0D080095AD3CC633F900FF9B
-:105C400094E5002A0019C082318F00FF978C00581C
-:105C500000181600000F74003124FFFF004E382595
-:105C600001A4302100E6F82500ACC8213C03400027
-:105C700003E3C02500194C00AD180000AD09000475
-:105C8000934F09203C0E000625090014000F6E00FA
-:105C900001AE2825AD0500088F46092C258200019C
-:105CA00030477FFFAD06000C8F440930A7870058AE
-:105CB00025060028AD0400108F43093800C02021BC
-:105CC000AD030014AD2A00048F5F0940AD3F00080A
-:105CD000935909373C0E080091CE3CD0AD200010FE
-:105CE000333800FF03147821000F6700000E6C00AA
-:105CF000018D282534A2FFFFAD22000CAF4B002CF4
-:105D00009347093E30EA00085140000F8E58000CBE
-:105D10003C0301013469080AAD0900288F4A007468
-:105D2000ACCA00043C0B0800916B3CD031680010F9
-:105D300051000003ACC000088F650060ACC50008CE
-:105D400024C4000C8E58000C0300F8090000000069
-:105D50003C0F080095EF3CCA3C02080094423CBE50
-:105D600001E2702125C400020E0000C73084FFFF4D
-:105D70003C0608008CC63CAC3C0D08008DAD3CB424
-:105D800000CD38233C010800AC273CAC14E00006F1
-:105D9000000000003C1908008F393CCC372C004033
-:105DA0003C010800AC2C3CCC120000858F8B0044D9
-:105DB0008F480E108F900044AE0800208F5F0E18A1
-:105DC000AE1F00243C10080096103CC00E0000607E
-:105DD0000000000024050040AF4508148F830050E8
-:105DE0008F89004C0070182100695023194000046D
-:105DF000AF830050AF6300548F670054AF87004CEF
-:105E00001200000C000000008F440074936D0081AC
-:105E1000340EFA002DA6000710C00005008E1821D0
-:105E200093780081240201F40302780401E418212C
-:105E3000AF63000C8F4C095C8F99005C01992023A3
-:105E400018800003000000008F50095CAF90005CD8
-:105E50000E000062000000008F8B00508E48001082
-:105E60003C010800AC2B3CD40100F8090000000004
-:105E70003C1F08008FFF3CAC17E0FEFC2407000627
-:105E80008F450024974209088F8A00648F94005040
-:105E90003C0F001F978700588F8300548F93004C4E
-:105EA000304DFFFF35EEFF8000AE4824000D31C0BD
-:105EB00032320010AF460024A467002CAF49002402
-:105EC000AF6A0044AF740050AF7300545640007E78
-:105ED0008EB8000432240040548000328EB1000895
-:105EE0008EAC000C0180F809000000008FBF00306C
-:105EF0008FB5002C8FB400288FB300248FB2002000
-:105F00008FB1001C8FB0001803E0000827BD0038D7
-:105F10003C09080095293CC03C04080094843CCA14
-:105F20003C1F080097FF3CBC94F800243123FFFF7E
-:105F300094EF00280083C821033F702300182C0031
-:105F4000000F640025CDFFEE018D302534A28100C5
-:105F500024030800AD02000CAD060010AD030018CC
-:105F6000AD0000140A0009CE2508001C9347010962
-:105F70008F8800380007FE0003E8C825AF5900806D
-:105F80008F5809A08F5309A4AFB80010AF580E1452
-:105F90008FB40010AF540E10AF530E1C0A0009420C
-:105FA000AF530E180220F809000000008EAC000C60
-:105FB0000180F809000000000A000A7F8FBF00304E
-:105FC000A5600020A57300220A000A34AD730024E6
-:105FD0003C010800AC203CB00A00096E8E42000073
-:105FE0003C010800AC243CB00A00096E8E4200005F
-:105FF0003C09080095293CC03C1F080097FF3CCA9B
-:106000003C19080097393CBC94EF00243124FFFF71
-:1060100003E4C02103197023000F640025CDFFF2B3
-:10602000018D2825AC45000C24020800AD020014A7
-:10603000AD0000100A0009CE2508001894E60024DF
-:1060400094E300283C09080095293CC00006240080
-:106050000003FC003499810037F80800AD19000CEA
-:10606000AD1800100A0009CE250800141460FEEDDA
-:106070000000000094EF00243C09080095293CC072
-:10608000000F740035CD0800AD0D000C0A0009CEDC
-:106090002508001093520109000028210E00060077
-:1060A000324400FF8FBF00308FB5002C8FB4002822
-:1060B0008FB300248FB200208FB1001C8FB0001866
-:1060C00003E0000827BD00380300F80900000000C5
-:1060D0000A000A79322400401200FF690000000023
-:1060E0008F540E148F920044AE5400208F530E1C18
-:1060F0000A000A63AE5300248F82001C00804021F6
-:106100003C0401009047008530E300201060000946
-:10611000000000003C0708008CE73CD48F83001887
-:1061200000E32023048000089389000414E30003A3
-:106130000100202103E00008008010213C04010040
-:1061400003E00008008010211120000B00673823B5
-:106150008F8C002024090034918B00BC316A00022E
-:10616000514000012409003000E9682B15A0FFF11F
-:106170000100202100E938232419FFFC00B9C024C4
-:1061800000F9782400F8702B15C0FFEA01E82021FF
-:1061900030C200030002182314C00012306900034B
-:1061A0000000302100A9702101C6682100ED602B9C
-:1061B0001180FFE03C0401002D2F00010006482B58
-:1061C0000105382101E9302414C0FFDA24E4FFFC82
-:1061D0002419FFFC00B9C0240308202103E00008B3
-:1061E000008010218F8B002024060004916A00BCDF
-:1061F000314400041480FFEC00A970210A000B2D2B
-:106200000000302127BDFFE8AFBF00108F4601001E
-:10621000934A01093C1F08008FFF00902407FF806C
-:10622000314F00FF31E8007F0008614003E6C821DC
-:10623000032CC02127090120012770243C010800FC
-:10624000A02F3D10AF4E080C3C0D08008DAD009006
-:106250003C0400803482000301A65821016C1821FF
-:106260002465012030AA007801424025AF48081C6F
-:106270003C1F08008FFF00908F88004003E6C0217C
-:106280003319000703074824033A7821AF4900284F
-:1062900025E909C0952E00023C0D08008DAD008C4B
-:1062A0003C0A08008D4A009031CC3FFF01A618211E
-:1062B000000C5980006B282100A72024AF44002C3B
-:1062C000952200023C1F08008FFF008C910700857B
-:1062D00030593FFF03E678210019C1800146702143
-:1062E00001F8682131CC007F31AB007F019A282171
-:1062F000017A50213C03000C3C04000E00A328212D
-:106300000144102130E6002027470980AF82002C8D
-:10631000AF88001CAF890024AF85002010C00006A4
-:10632000AF8700288D0200508CA4010C004430235C
-:1063300018C0007700000000910C0085240DFFDFDD
-:10634000018D3824A10700858F8B001C8F890024C4
-:106350008F8700288D65004CAF850018912F000DA8
-:1063600031EE002011C000170000000024090001D8
-:10637000A3890004AF80000C8CE400248F85000CFE
-:10638000240A0008AF800008AF8000103C0108001C
-:10639000A42A3CBE3C010800A4203CD20E000B0104
-:1063A000000030218F8500248FBF0010AF820014C1
-:1063B00090A8000D27BD00180008394203E000082E
-:1063C00030E20001913F00022418000133F900FF80
-:1063D0000019218210980039240800021088005BFF
-:1063E0008F86002C8CE5002414A0001B8F9F0020BA
-:1063F00091220000240A00053046003F10CA0047E1
-:10640000240400018F860008A3840004AF860010D6
-:10641000AF86000C8CE400248F85000C240A000851
-:106420003C010800A42A3CBE3C010800A4203CD248
-:106430000E000B01000000008F8500248FBF0010AC
-:10644000AF82001490A8000D27BD00180008394243
-:1064500003E0000830E200018CF800088CF9002409
-:106460008FEE00C4A38000048CE40024AF8E000CE7
-:106470008F85000C8F86000803197823240A0008F2
-:10648000AF8F00103C010800A42A3CBE3C0108006C
-:10649000A4203CD20E000B01000000008F850024D8
-:1064A0008FBF0010AF82001490A8000D27BD001808
-:1064B0000008394203E0000830E2000191230000A7
-:1064C0003062003F104400278F8500208CE40024B8
-:1064D00014800021000000008D2E00183C187FFF62
-:1064E0008F850020370FFFFF01CF1824AF830008EE
-:1064F0008F9F00088CA8008403E8C82B1720000297
-:1065000003E020218CA400840A000BBCAF840008A7
-:106510008CA3010C0A000B9AAF8300188D2C001875
-:106520008F8600083C0D7FFF8F89002035A3FFFF79
-:106530000183582424040001AF8B0010AD2000CC4F
-:10654000A38400040A000BC8AF86000C8CCA001498
-:106550000A000BBCAF8A00088CA300C80A000BFF1E
-:10656000AF8300088F84002C8CAC00648C8D0014E9
-:10657000018D582B11600004000000008CA2006403
-:106580000A000BFFAF8200088C8200140A000BFF88
-:10659000AF8200088F85000C27BDFFE0AFBF001859
-:1065A000AFB1001414A00007AFB000108F86002414
-:1065B0002402000590C400003083003F106200B642
-:1065C0008F8400208F91000800A080218F8C0028EC
-:1065D0003C0508008CA53CB08D8B000431663FFF64
-:1065E00000C5502B5540000100C02821938D0004A8
-:1065F00011A0007300B0F82B8F9800202404003401
-:10660000930F00BC31EE000251C0000124040030A1
-:1066100000A4C82B172000D10000000000A42823EC
-:1066200000B0F82B3C010800A4243CBC17E0006833
-:10663000020020213C0308008C633CAC0083102B3B
-:1066400054400001008018218F8800243C0108007C
-:10665000AC233CB4000048219104000D308300209D
-:10666000506000018F490E188F8300140123382BCE
-:1066700010E00059000000003C0408008C843CB489
-:1066800000895821006B502B114000560090602B60
-:106690000069302300C020213C010800AC263CB436
-:1066A00012000003241FFFFC1090008A3227000311
-:1066B000009FC8243C010800AC393CB43C010800F0
-:1066C000A4203CD28F84000C120400078F8300208A
-:1066D000AF910008020020218C7100CCAF90000C1B
-:1066E00026300001AC7000CC3C0208008C423CB467
-:1066F0008F8A0010240700180082202301422823DB
-:10670000AF84000C10800002AF8500102407001039
-:106710008F86001C3C010800A0273CD024070040C5
-:1067200090CC0085318B00C0116700408F8D001424
-:1067300014A0001500002021934A01098F4209741A
-:10674000314500FF0002260224A300013090007FA3
-:106750003071007F1230007A2407FF80A0C30083CD
-:106760003C0908008D293CCC8F880024240D0002B0
-:10677000352C00083C010800A02D3D113C0108000B
-:10678000AC2C3CCC24040010910E000D31C600202E
-:1067900010C0000500801821240800013C010800F9
-:1067A000AC283CB4348300018FBF00188FB10014B3
-:1067B0008FB000100060102103E0000827BD00200A
-:1067C0003C010800A4203CBC13E0FF9A02002021F9
-:1067D0000A000C5000A020213C0408008C843CB42A
-:1067E0000090602B1180FFAE000000003C0F0800FD
-:1067F00095EF3CBC01E4702101C6682B11A0000795
-:106800002C8200043C1F60008FF954043338003F91
-:106810001700FFE5240300422C8200041040FFA073
-:10682000240300420A000CAE8FBF0018152DFFC0D4
-:10683000000000008CDF00743C0380002405FF8012
-:1068400003E3C825ACD9007490D80085240E000459
-:1068500024040010330F003F01E54025A0C8008547
-:106860008F8800243C010800A02E3D112403000164
-:106870009106000D30C90020152000030000000023
-:106880003C0308008C633CB43C010800AC233CACE6
-:106890000A000CA5000000008F8700108C8800847F
-:1068A00000E8282B14A0000200E088218C910084CD
-:1068B00024090001A38900048F440E180220282116
-:1068C0000E000B0102203021022080210A000C362C
-:1068D000AF82001400071823306600033C01080053
-:1068E000A4263CD2122000058F8C0020918B00BC86
-:1068F000316A00041540001524CD00043C0F080047
-:1069000095EF3CD201E4702100AE302B50C0FF6EF9
-:106910008F84000C2C85000514A0FFA324030042E3
-:106920003098000317000002009818232483FFFC0E
-:106930003C010800AC233CB40A000C7200000000CB
-:1069400000A758240A000C9A016718263C01080089
-:10695000A42D3CD20A000D02000000003C010800FA
-:10696000AC203CB40A000CAD240300428F8300101D
-:1069700014600007000010218F8800242405000502
-:106980009106000030C400FF1085000300000000E5
-:1069900003E0000800000000910A0018314900FFE0
-:1069A000000939C214E0FFFA8F85001C3C0408007E
-:1069B00094843CBC3C0308008C633CD43C19080024
-:1069C0008F393CB43C0F080095EF3CD20064C021E5
-:1069D0008CAD00540319702101CF6021018D582323
-:1069E0001960001D00000000910E001C8F8C002C0F
-:1069F000974B0E1031CD00FF8D850004016D3023C3
-:106A00008D88000030CEFFFF000E510000AAC82183
-:106A10000000382101072021032A182B0083C02100
-:106A2000AD990004AD980000918F000A01CF682154
-:106A3000A18D000A8F88002C974B0E12A50B000821
-:106A4000950A003825490001A50900389107000D75
-:106A500034E60008A106000D03E000080000000075
-:106A600027BDFFE0938700048F8F00248FAD0014B3
-:106A70003C0E7FFF8F89000C35C8FFFFAFBF001CA5
-:106A8000AFB0001801A8182491EA000D000717C044
-:106A90003C1FBFFF006258252D2E00018F9000186B
-:106AA00037F9FFFF3C1808008F183CD43C0F080052
-:106AB00095EF3CCA01796824000E47803C07EFFF40
-:106AC0003C05F0FF01A818253149002034E2FFFF02
-:106AD00034ACFFFF0310582327A500102406000242
-:106AE00025EA00020062182400808021152000029F
-:106AF000000040218F480E1CA7AA00120560003735
-:106B00002407000030FF00FF001FCF008F8B001C08
-:106B100000793825AFA70014916F00853C08080064
-:106B200091083CD13C18DFFF31EE00C0370AFFFF6F
-:106B3000000E182B3C1F080097FF3CC400EA682495
-:106B4000A3A800110003174001A248258FB9001027
-:106B5000AFA900143C0A0800914A3CD3A7BF001615
-:106B60008FA80014032CC0243C0B01003C0F0FFF26
-:106B7000030B18253147000335EEFFFF010C682495
-:106B800000071600006EF8243C09700001A2C82519
-:106B900003E95825AFB90014AFAB00100E00007622
-:106BA000A3A000158F8C0024260200089186000DFA
-:106BB00030C40020108000068FBF001C3C05080078
-:106BC00094A53CC024B0FFFF3C010800A4303CC0A9
-:106BD0008FB0001803E0000827BD00208F98001434
-:106BE0000118502B5540FFC7240700010A000D85EE
-:106BF00030FF00FF9382000427BDFFE0AFBF001805
-:106C00001040000F008050218F880024240B0005C5
-:106C10008F890008910700008F840020010028213F
-:106C200030E3003F8F86002C106B000800003821F5
-:106C3000AFA900100E00040EAFAA0014A380000438
-:106C40008FBF001803E0000827BD00208D19001831
-:106C50003C0F08008DEF3CB48F9800103C027FFF82
-:106C60008D080014345FFFFF033F682401F8702192
-:106C700001AE602301883821AFA900100E00040E78
-:106C8000AFAA00140A000DD3A38000048F8700244C
-:106C90003C05080094A53CD23C0208008C423CCC48
-:106CA00090E6000D0005240030C300201060002C89
-:106CB000004440258F85001C00006021240B00014A
-:106CC00090A3008500004821240A00013C0F8000A9
-:106CD00035EE00708DC70000AF8700308F58017807
-:106CE0000700FFFE3C038000347900708F380000FD
-:106CF0003C0508008CA500743C0D08008DAD0070AB
-:106D00000307782300AF38210000102100EF302B5B
-:106D100001A22021008618213C010800AC27007444
-:106D20003C010800AC230070AF4B01483C1908003F
-:106D30008F393CD4A7490144A74A0146AF59014CB9
-:106D40003C0B0800916B3CD1A34B0152AF4801545E
-:106D50003C081000A74C015803E00008AF48017838
-:106D60008F4B0E1C3C0A08008D4A3CB497490E1606
-:106D7000974D0E1401456021312AFFFF0A000DF6E0
-:106D800031A9FFFF8F8300249064000D3082002022
-:106D900010400029000000000000482100005021A0
-:106DA000000040213C07800034EB00708D6700003C
-:106DB000AF8700308F4C01780580FFFE3C0D8000CE
-:106DC00035AC00708D8B00003C0508008CA500746C
-:106DD0003C0408008C8400700167302300A67821F1
-:106DE0000000102101E6C82B0082C0210319702188
-:106DF0003C010800AC2F00743C010800AC2E007070
-:106E0000AF4901483C0D08008DAD3CD4A748014472
-:106E100024090040A74A01463C081000240AFF91BB
-:106E2000AF4D014CA34A0152AF490154A74001584C
-:106E300003E00008AF4801788F490E1897460E12FC
-:106E400097450E1030CAFFFF0A000E2C30A8FFFF36
-:106E50008F83002427BDFFF89064000D308200204E
-:106E60001040003A00000000240B000100004821FF
-:106E7000240A00013C088000350700708CE3000004
-:106E8000AF8300308F4C01780580FFFE3C0E800000
-:106E90003C04080090843D1035C700708CEC000065
-:106EA0003C0508008CA50074A3A400033C1908004D
-:106EB0008F3900708FAD00000183302300A6382188
-:106EC000000010210322782100E6C02B01F8602188
-:106ED00001AE4025AFA800003C010800AC270074BB
-:106EE0003C010800AC2C00709346010A3C040800E9
-:106EF00090843D11A3A00002A3A600018FA300006F
-:106F00003C0580FF3099007F34A2FFFF00627824A7
-:106F10000019C60001F87025240D3000AF4E014C59
-:106F200027BD0008AF4D0154A7400158AF4B0148A1
-:106F3000A7490144A74A01463C091000240AFF80E2
-:106F4000A34A015203E00008AF4901788F4B0E18A5
-:106F500097460E1297450E1030CAFFFF0A000E60CA
-:106F600030A9FFFF8F85001C2402008090A40085BB
-:106F7000308300C0106200058F8600208F880008D3
-:106F80008F87000CACC800C8ACC700C403E0000881
-:106F9000000000003C0A0800254A38903C0908001F
-:106FA0002529395C3C08080025082D103C070800FD
-:106FB00024E73A703C06080024C637003C05080068
-:106FC00024A534783C040800248430A03C03080045
-:106FD000246337983C0208002442356C3C010800C9
-:106FE000AC2A3C903C010800AC293C8C3C010800D8
-:106FF000AC283C883C010800AC273C943C010800CC
-:10700000AC263CA43C010800AC253C9C3C0108009B
-:10701000AC243C983C010800AC233CA83C0108008F
-:0C702000AC223CA003E0000800000000CF
-: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-06-6.0.15.fw.ihex b/firmware/bnx2/bnx2-mips-06-6.0.15.fw.ihex
new file mode 100644
index 0000000..e9bbdc3
--- /dev/null
+++ b/firmware/bnx2/bnx2-mips-06-6.0.15.fw.ihex
@@ -0,0 +1,5815 @@
+:10000000080001180800000000004A68000000C84D
+:1000100000000000000000000000000008004A6826
+:100020000000001400004B30080000A00800000091
+:100030000000568800004B4408005800000000846F
+:100040000000A1CC08005688000001580000A25012
+:100050000800321008000000000072D00000A3A8C1
+:10006000000000000000000000000000080072D046
+:100070000000002400011678080004900800040025
+:10008000000017D40001169C0000000000000000D2
+:100090000000000000000000000000000000000060
+:1000A000080000A80800000000003BFC00012E70C2
+:1000B0000000000000000000000000000000000040
+:0800C000000000000000000038
+:0800C8000A00004600000000E0
+:1000D000000000000000000D636F6D362E302E31E1
+:1000E0003500000006000F020000000000000003C1
+:1000F000000000C800000032000000030000000003
+:1001000000000000000000000000000000000000EF
+:1001100000000010000001360000EA600000000549
+:1001200000000000000000000000000000000008C7
+:1001300000000000000000000000000000000000BF
+:1001400000000000000000000000000000000000AF
+:10015000000000000000000000000000000000009F
+:10016000000000020000000000000000000000008D
+:10017000000000000000000000000000000000007F
+:10018000000000000000000000000010000000005F
+:10019000000000000000000000000000000000005F
+:1001A000000000000000000000000000000000004F
+:1001B000000000000000000000000000000000003F
+:1001C000000000000000000000000000000000002F
+:1001D000000000000000000000000000000000001F
+:1001E0000000000010000003000000000000000DEF
+:1001F0000000000D3C02080024424AA03C03080015
+:1002000024634B9CAC4000000043202B1480FFFD76
+:10021000244200043C1D080037BD7FFC03A0F021F0
+:100220003C100800261001183C1C0800279C4AA01E
+:100230000E000168000000000000000D27470100CB
+:1002400090E3000B2402001A94E5000814620028D1
+:10025000000020218CE200003C0308008C63004475
+:1002600094E60014000211C20002104030A4000203
+:10027000005A10212463000130A50004A446008028
+:100280003C010800AC23004410A000190004202BFE
+:100290008F4202B804410008240400013C02080017
+:1002A0008C420060244200013C010800AC22006046
+:1002B00003E00008008010218CE2002094E3001687
+:1002C00000002021AF4202808CE20004A743028498
+:1002D000AF4202883C021000AF4202B83C02080064
+:1002E0008C42005C244200013C010800AC22005C0E
+:1002F00003E00008008010212747010090E3000B75
+:100300002402000394E50008146200280000202164
+:100310008CE200003C0308008C63004494E6001467
+:10032000000211C20002104030A40002005A102145
+:100330002463000130A50004A44600803C010800AD
+:10034000AC23004410A000190004202B8F4202B8F7
+:1003500004410008240400013C0208008C420060B3
+:10036000244200013C010800AC22006003E00008C8
+:10037000008010218CE2002094E300160000202170
+:10038000AF4202808CE20004A7430284AF4202889D
+:100390003C021000AF4202B83C0208008C42005CF4
+:1003A000244200013C010800AC22005C03E000088C
+:1003B000008010218F4301002402010050620003DD
+:1003C000000311C20000000D000311C20002104022
+:1003D000005A1021A440008003E000080000102112
+:1003E0009362000003E00008AF80000003E0000813
+:1003F0000000102103E00008000010212402010089
+:1004000014820008000000003C0208008C4200FC3E
+:10041000244200013C010800AC2200FC0A0000DD7F
+:1004200030A200203C0208008C42008424420001DB
+:100430003C010800AC22008430A2002010400008DB
+:1004400030A300103C0208008C4201082442000145
+:100450003C010800AC22010803E000080000000095
+:1004600010600008000000003C0208008C420104FB
+:10047000244200013C010800AC22010403E0000812
+:10048000000000003C0208008C42010024420001F0
+:100490003C010800AC22010003E00008000000005D
+:1004A00027BDFFE8AFBF0010274401009483000878
+:1004B000306200041040001B306600028F4202B818
+:1004C00004410008240500013C0208008C42006041
+:1004D000244200013C010800AC2200600A0001290E
+:1004E0008FBF00108C82002094830016000028210A
+:1004F000AF4202808C820004A7430284AF4202888C
+:100500003C021000AF4202B83C0208008C42005C82
+:10051000244200013C010800AC22005C0A000129D1
+:100520008FBF001010C00006006028218F4401001A
+:100530000E0000CD000000000A0001282405000183
+:100540008F8200088F4301045043000700002821D8
+:100550008F4401000E0000CD000000008F42010416
+:10056000AF820008000028218FBF001000A01021DA
+:1005700003E0000827BD001827BDFFE8AFBF001447
+:10058000AFB00010974201083043700024022000F1
+:100590001062000B286220011440002F000010217F
+:1005A00024024000106200250000000024026000C8
+:1005B00010620026000010210A0001658FBF0014A0
+:1005C00027500100920200091040001A2403000184
+:1005D0003C0208008C420020104000160000182148
+:1005E0000E00049300000000960300083C0608007B
+:1005F00094C64B5E8E0400188F8200209605000C76
+:1006000000031C0000661825AC440000AC45000443
+:1006100024040001AC400008AC40000CAC400010C9
+:10062000AC400014AC4000180E0004B8AC43001CF1
+:10063000000018210A000164006010210E0003254B
+:10064000000000000A000164000010210E000EE905
+:1006500000000000000010218FBF00148FB00010B8
+:1006600003E0000827BD001827BDFFE0AFB2001867
+:100670003C036010AFBF001CAFB10014AFB000105E
+:100680008C6450002402FF7F3C1A800000822024EA
+:100690003484380C24020037AC6450003C1208004B
+:1006A00026524AD8AF42000824020C80AF420024F0
+:1006B0003C1B80083C06080024C60324024010218D
+:1006C0002404001D2484FFFFAC4600000481FFFDCC
+:1006D000244200043C020800244204B03C0108000B
+:1006E000AC224AE03C020800244202303C010800EF
+:1006F000AC224AE43C020800244201743C03080096
+:100700002463032C3C040800248403D83C0508001F
+:1007100024A538F03C010800AC224B403C02080004
+:10072000244202EC3C010800AC264B243C010800AA
+:10073000AC254B343C010800AC234B3C3C01080089
+:10074000AC244B443C010800AC224B483C0108005F
+:10075000AC234ADC3C010800AC204AE83C0108001C
+:10076000AC204AEC3C010800AC204AF03C010800F7
+:10077000AC204AF43C010800AC204AF83C010800D7
+:10078000AC204AFC3C010800AC204B003C010800B6
+:10079000AC244B043C010800AC204B083C01080091
+:1007A000AC204B0C3C010800AC204B103C01080075
+:1007B000AC204B143C010800AC204B183C01080055
+:1007C000AC264B1C3C010800AC264B203C01080029
+:1007D000AC254B303C010800AC234B380E000623FF
+:1007E000000000003C028000344200708C42000097
+:1007F000AF8200143C0308008C6300208F82000449
+:10080000104300043C0280000E00045BAF83000430
+:100810003C028000344600703C0308008C6300A05A
+:100820003C0208008C4200A4104300048F84001492
+:100830003C010800AC2300A4A743009E8CCA000022
+:100840003C0308008C6300BC3C0208008C4200B8EA
+:100850000144202300641821000040210064202B63
+:1008600000481021004410213C010800AC2300BCCA
+:100870003C010800AC2200B88F5100003222000772
+:100880001040FFDCAF8A00148CC600003C05080055
+:100890008CA500BC3C0408008C8400B800CA30233E
+:1008A00000A628210000102100A6302B0082202164
+:1008B00000862021322700013C010800AC2500BC45
+:1008C0003C010800AC2400B810E0001F32220002F6
+:1008D0008F420100AF4200208F420104AF4200A8C6
+:1008E0009342010B0E0000C6305000FF2E02001E86
+:1008F00054400004001010800E0000C90A000213CA
+:1009000000000000005210218C4200000040F80955
+:1009100000000000104000053C0240008F4301042D
+:100920003C026020AC4300143C024000AF4201385E
+:100930003C0208008C420034244200013C010800C3
+:10094000AC220034322200021040000E3222000499
+:100950008F4201400E0000C6AF4200200E000295FB
+:10096000000000003C024000AF4201783C02080059
+:100970008C420038244200013C010800AC220038BF
+:10098000322200041040FF983C0280008F42018018
+:100990000E0000C6AF4200208F43018024020F00EA
+:1009A00014620005000000008F420188A742009CED
+:1009B0000A0002483C0240009362000024030050F9
+:1009C000304200FF144300083C0240000E00027B4E
+:1009D00000000000544000043C0240000E000D7571
+:1009E000000000003C024000AF4201B83C02080099
+:1009F0008C42003C244200013C010800AC22003C37
+:100A00000A0001C83C0280003C0290003442000110
+:100A100000822025AF4400208F4200200440FFFECA
+:100A20000000000003E00008000000003C0280001D
+:100A3000344200010082202503E00008AF4400207A
+:100A400027BDFFE0AFB10014AFB0001000808821D7
+:100A5000AFBF00180E00025030B000FF9362007D5F
+:100A60000220202102028025A370007D8F70007477
+:100A70003C0280000E000259020280241600000988
+:100A80008FBF00188F4201F80440FFFE24020002CD
+:100A9000AF5101C0A34201C43C021000AF4201F8B3
+:100AA0008FBF00188FB100148FB0001003E0000852
+:100AB00027BD002027BDFFE8AFBF0010974201848B
+:100AC0008F440188304202001040000500002821B8
+:100AD0000E000FAA000000000A00028D240500018C
+:100AE0003C02FF0004800005008218243C02040040
+:100AF000506200019362003E240500018FBF001088
+:100B000000A0102103E0000827BD0018A360002208
+:100B10008F4401400A00025E2405000127BDFFE862
+:100B2000AFBF0014AFB0001093620000304400FF6C
+:100B300038830020388200300003182B0002102B6D
+:100B40000062182410600003240200501482008008
+:100B50008FBF001493620005304200011040007CFA
+:100B60008FBF0014934201482443FFFF2C6200050D
+:100B7000104000788FB00010000310803C03080084
+:100B800024634A68004310218C42000000400008A2
+:100B9000000000000E0002508F4401408F70000CD6
+:100BA0008F4201441602000224020001AF62000CD1
+:100BB0000E0002598F4401408F420144145000043A
+:100BC0008FBF00148FB000100A000F2027BD00183F
+:100BD0008F62000C0A0003040000000097620010FE
+:100BE0008F4301443042FFFF1462001A00000000EE
+:100BF00024020001A76200108F4202380443001053
+:100C00008F4201403C02003F3446F0003C0560004A
+:100C10003C04FFC08CA22BBC0044182400461024C6
+:100C20000002130200031D82106200390000000060
+:100C30008F4202380440FFF7000000008F4201405D
+:100C4000AF4202003C021000AF4202380A00032209
+:100C50008FBF0014976200100A0003040000000018
+:100C60000E0002508F440140976200128F430144EE
+:100C70003050FFFF1603000224020001A762001299
+:100C80000E0002598F4401408F42014416020004B5
+:100C90008FBF00148FB000100A00029127BD00180A
+:100CA000976200120A00030400000000976200141B
+:100CB0008F4301443042FFFF14620006240200010A
+:100CC0008FBF00148FB00010A76200140A00124AF0
+:100CD00027BD0018976200141440001D8FBF001438
+:100CE0000A00031C00000000976200168F430144B5
+:100CF0003042FFFF1462000B240200018FBF00147A
+:100D00008FB00010A76200160A000B1227BD001852
+:100D10009742007824420004A76200100A000322D0
+:100D20008FBF001497620016240300013042FFFFBA
+:100D3000144300078FBF00143C0208008C4200706F
+:100D4000244200013C010800AC2200708FBF001457
+:100D50008FB0001003E0000827BD001827BDFFE892
+:100D6000AFBF0014AFB000108F50010093620000BD
+:100D700093430109304400FF2402001F106200A5C4
+:100D80002862002010400018240200382862000A5F
+:100D90001040000C2402000B286200081040002CB8
+:100DA00000000000046000E52862000214400028F2
+:100DB00024020006106200268FBF00140A00041FE0
+:100DC0008FB000101062005E2862000B144000DC3F
+:100DD0008FBF00142402000E106200738FB0001049
+:100DE0000A00041F00000000106200C028620039E1
+:100DF0001040000A2402008024020036106200CA5B
+:100E000028620037104000B424020035106200C18F
+:100E10008FBF00140A00041F8FB000101062002B57
+:100E20002862008110400006240200C82402003914
+:100E3000106200B48FBF00140A00041F8FB00010AE
+:100E4000106200998FBF00140A00041F8FB00010B9
+:100E50003C0208008C420020104000B98FBF0014F3
+:100E60000E000493000000008F4201008F830020D9
+:100E70009745010C97460108AC6200008F420104BF
+:100E80003C04080094844B5E00052C00AC62000416
+:100E90008F4201180006340000C43025AC620008FF
+:100EA0008F42011C24040001AC62000C9342010A31
+:100EB00000A22825AC650010AC600014AC600018DE
+:100EC000AC66001C0A0003F58FBF00143C0208004A
+:100ED0008C4200201040009A8FBF00140E00049333
+:100EE00000000000974401083C03080094634B5E37
+:100EF0009745010C000422029746010E8F820020C4
+:100F0000000426000083202500052C003C030080FF
+:100F100000A6282500832025AC400000AC4000043A
+:100F2000AC400008AC40000CAC450010AC400014D4
+:100F3000AC400018AC44001C0A0003F42404000177
+:100F40009742010C14400015000000009362000558
+:100F50003042001014400011000000000E0002504A
+:100F6000020020219362000502002021344200107B
+:100F70000E000259A36200059362000024030020C2
+:100F8000304200FF1043006D020020218FBF00148B
+:100F90008FB000100A000FC027BD00180000000D20
+:100FA0000A00041E8FBF00143C0208008C4200207F
+:100FB000104000638FBF00140E0004930000000077
+:100FC0008F4201048F8300209744010C3C050800E8
+:100FD00094A54B5EAC6200009762002C00042400D4
+:100FE0003042FFFF008220253C02400E00A228254F
+:100FF000AC640004AC600008AC60000CAC60001095
+:10100000AC600014AC600018AC65001C0A0003F46E
+:10101000240400010E00025002002021A7600008F5
+:101020000E00025902002021020020210E00025E63
+:10103000240500013C0208008C42002010400040C2
+:101040008FBF00140E000493000000009742010CB3
+:101050008F8300203C05080094A54B5E000214001D
+:10106000AC700000AC620004AC6000088F64004CFF
+:101070003C02401F00A22825AC64000C8F62005087
+:1010800024040001AC6200108F620054AC620014B2
+:10109000AC600018AC65001C8FBF00148FB000104E
+:1010A0000A0004B827BD0018240200205082002541
+:1010B0008FB000100E000F0A020020211040002007
+:1010C0008FBF0014020020218FB0001000002821E3
+:1010D0000A00025E27BD0018020020218FBF001405
+:1010E0008FB000100A00058027BD00189745010C3D
+:1010F000020020218FBF00148FB000100A0005A04D
+:1011000027BD0018020020218FB000100A0005C57D
+:1011100027BD00189345010D020020218FB000105B
+:101120000A00060F27BD0018020020218FBF0014FF
+:101130008FB000100A0005EB27BD00188FBF001408
+:101140008FB0001003E0000827BD00188F4202781E
+:101150000440FFFE2402000234840080AF440240B9
+:10116000A34202443C02100003E00008AF420278B0
+:101170003C04080094844B6A3C0208008C424B7487
+:101180003083FFFF000318C000431021AF42003C32
+:101190003C0208008C424B70AF4200383C020050C9
+:1011A00034420008AF4200300000000000000000A0
+:1011B000000000008F420000304200201040FFFD80
+:1011C000000000008F4204003C010800AC224B608C
+:1011D0008F4204043C010800AC224B643C02002016
+:1011E000AF420030000000003C02080094424B680F
+:1011F0003C03080094634B6C3C05080094A54B6EBF
+:1012000024840001004310213083FFFF3C010800CB
+:10121000A4224B683C010800A4244B6A1465000317
+:10122000000000003C010800A4204B6A03E0000815
+:10123000000000003C05000A27BDFFE80345282107
+:101240003C04080024844B50AFBF00100E00051D65
+:101250002406000A3C02080094424B523C0308005A
+:1012600094634B6E3042000F244200030043180485
+:1012700024027FFF0043102B10400002AF83001CAC
+:101280000000000D0E00042A000000003C020800CF
+:1012900094424B5A8FBF001027BD001803E000088E
+:1012A000A74200A23C02000A034210219443000618
+:1012B0003C02080094424B5A3C010800A4234B56C0
+:1012C000004310238F83001C00021400000214034B
+:1012D0000043102B03E000083842000127BDFFE85F
+:1012E000AFBF00103C02000A0342102194420006E6
+:1012F0003C010800A4224B560E00047700000000B9
+:101300005440FFF93C02000A8FBF001003E00008C0
+:1013100027BD001827BDFFE8AFBF00100E000477FF
+:101320000000000010400003000000000E000485D3
+:10133000000000003C0208008C424B608FBF001090
+:1013400027430400AF4200383C0208008C424B6443
+:1013500027BD0018AF830020AF42003C3C020005CF
+:10136000AF42003003E00008AF8000188F82001801
+:101370003C0300060002114000431025AF4200303C
+:101380000000000000000000000000008F4200008C
+:10139000304200101040FFFD27420400AF820020C1
+:1013A00003E00008AF8000183C0608008CC64B64C0
+:1013B0008F8500188F8300203C02080094424B5A0E
+:1013C00027BDFFE024A50001246300202442000182
+:1013D00024C70020AFB10014AFB00010AFBF001899
+:1013E000AF850018AF8300203C010800A4224B5AAF
+:1013F000309000FF3C010800AC274B6404C100089A
+:101400000000882104E00006000000003C02080003
+:101410008C424B60244200013C010800AC224B602E
+:101420003C02080094424B5A3C03080094634B680A
+:101430000010202B004310262C42000100441025F0
+:10144000144000048F830018240200101462000F5F
+:10145000000000000E0004A9241100013C03080054
+:1014600094634B5A3C02080094424B681462000398
+:10147000000000000E00042A000000001600000317
+:10148000000000000E000493000000003C03080070
+:1014900094634B5E3C02080094424B5C2463000161
+:1014A0003064FFFF3C010800A4234B5E148200035C
+:1014B000000000003C010800A4204B5E1200000662
+:1014C000000000003C02080094424B5AA74200A2D0
+:1014D0000A00050B022010210E0004770000000016
+:1014E00010400004022010210E00048500000000BE
+:1014F000022010218FBF00188FB100148FB0001090
+:1015000003E0000827BD00203084FFFF30A5FFFF67
+:101510000000182110800007000000003082000148
+:101520001040000200042042006518210A00051343
+:101530000005284003E000080060102110C00006EC
+:1015400024C6FFFF8CA2000024A50004AC8200008A
+:101550000A00051D2484000403E0000800000000C8
+:1015600010A0000824A3FFFFAC86000000000000CC
+:10157000000000002402FFFF2463FFFF1462FFFA53
+:101580002484000403E0000800000000240200019D
+:10159000AF62000CA7620010A7620012A7620014DD
+:1015A00003E00008A76200163082007F034210218A
+:1015B0003C08000E004818213C0208008C42002024
+:1015C00027BDFFD82407FF80AFB3001CAFB20018BF
+:1015D000AFB10014AFB00010AFBF00200080802179
+:1015E00030B100FF0087202430D200FF1040002FD0
+:1015F00000009821AF44002C9062000024030050AA
+:10160000304200FF1443000E000000003C020800BE
+:101610008C4200E00202102100471024AF42002C4F
+:101620003C0208008C4200E0020210213042007FA0
+:101630000342102100481021944200D43053FFFF90
+:101640000E000493000000003C02080094424B5E30
+:101650008F8300200011340000C2302500122C00BE
+:101660003C02400000C2302534A50001AC700000EF
+:101670008FBF0020AC6000048FB20018AC7300086C
+:101680008FB10014AC60000C8FB3001CAC6500106F
+:101690008FB00010AC60001424040001AC6000188E
+:1016A00027BD00280A0004B8AC66001C8FBF0020CC
+:1016B0008FB3001C8FB200188FB100148FB00010D0
+:1016C00003E0000827BD00289343010F2402001007
+:1016D0001062000E2865001110A0000724020012FD
+:1016E000240200082405003A1062000600003021A0
+:1016F00003E0000800000000240500351462FFFC30
+:10170000000030210A000538000000008F420074FC
+:1017100024420FA003E00008AF62000C27BDFFE8E1
+:10172000AFBF00100E00025E240500018FBF001045
+:1017300024020001A762001227BD00182402000144
+:1017400003E00008A360002227BDFFE0AFB1001452
+:10175000AFB00010AFBF001830B1FFFF0E00025055
+:10176000008080219362003F24030004304200FF88
+:101770001443000C02002021122000082402000A59
+:101780000E00053100000000936200052403FFFEF7
+:1017900000431024A362000524020012A362003F4C
+:1017A000020020210E000259A360008116200003D0
+:1017B000020020210E0005950000000002002021FB
+:1017C000322600FF8FBF00188FB100148FB00010B9
+:1017D000240500380A00053827BD002027BDFFE09A
+:1017E000AFBF001CAFB20018AFB10014AFB0001013
+:1017F0000E000250008080210E0005310000000024
+:101800009362003F24120018305100FF123200038F
+:101810000200202124020012A362003F936200050F
+:101820002403FFFE004310240E000259A3620005AA
+:10183000020020212405002016320007000030217C
+:101840008FBF001C8FB200188FB100148FB0001032
+:101850000A00025E27BD00208FBF001C8FB2001857
+:101860008FB100148FB00010240500390A0005382C
+:1018700027BD002027BDFFE8AFB00010AFBF0014A8
+:101880009742010C2405003600808021144000108E
+:10189000304600FF0E00025000000000240200123B
+:1018A000A362003F93620005344200100E00053130
+:1018B000A36200050E00025902002021020020212F
+:1018C0000E00025E240500200A000604000000004D
+:1018D0000E000538000000000E000250020020211A
+:1018E000936200232403FF9F020020210043102461
+:1018F0008FBF00148FB00010A36200230A000259AA
+:1019000027BD001827BDFFE0AFBF0018AFB100141E
+:10191000AFB0001030B100FF0E00025000808021F7
+:10192000240200120E000531A362003F0E0002598E
+:101930000200202102002021022030218FBF001848
+:101940008FB100148FB00010240500350A0005384F
+:1019500027BD0020A380002C03E00008A380002DF9
+:101960008F4202780440FFFE8F820034AF42024073
+:1019700024020002A34202443C02100003E00008DB
+:10198000AF4202783C0360008C6254003042000891
+:101990001440FFFD000000008C625408AF82000C70
+:1019A00024020052AC605408AC645430AC6254342D
+:1019B0002402000803E00008AC6254003C0260000E
+:1019C0008C42540030420008104000053C03600087
+:1019D0008C625400304200081440FFFD00000000FB
+:1019E0008F83000C3C02600003E00008AC43540805
+:1019F00090A3000024020005008040213063003FD6
+:101A000000004821146200050000502190A2001C33
+:101A100094A3001E304900FF306AFFFFAD00000CA8
+:101A2000AD000010AD000024950200148D05001CCF
+:101A30008D0400183042FFFF0049102300021100FE
+:101A4000000237C3004038210086202300A2102B5B
+:101A50000082202300A72823AD05001CAD04001838
+:101A6000A5090014A5090020A50A001603E0000836
+:101A7000A50A00228F4201F80440FFFE2402000262
+:101A8000AF4401C0A34201C43C02100003E00008BF
+:101A9000AF4201F83C0208008C4200B427BDFFE8C9
+:101AA000AFBF001424420001AFB000103C01080099
+:101AB000AC2200B48F4300243C02001F30AA00FF78
+:101AC0003442FF8030D800FF006280240080F8217B
+:101AD00030EF00FF1158003B01405821240CFF80DB
+:101AE0003C19000A3163007F000310C00003194055
+:101AF000006218213C0208008C4200DC25680001CD
+:101B0000310D007F03E21021004310213043007F9C
+:101B100003431821004C102400794821AF420024CF
+:101B20008D220024016C1824006C7026AD22000C5C
+:101B30008D220024310800FFAD22001095220014F0
+:101B4000952300208D27001C3042FFFF3063FFFFEC
+:101B50008D2600180043102300021100000227C345
+:101B60000040282100C4302300E2102B00C23023A3
+:101B700000E53823AD27001CAD2600189522002073
+:101B8000A522001495220022154B000AA52200165A
+:101B90008D2300248D220008254600013145008058
+:101BA0001462000430C4007F108F000238AA008045
+:101BB00000C0502151AF000131C800FF1518FFC906
+:101BC000010058218F8400343082007F03421821A5
+:101BD0003C02000A006218212402FF8000822024B7
+:101BE000AF440024A06A0079A06A00838C62005090
+:101BF0008F840034AC6200708C6500743C027FFFFF
+:101C00003442FFFF00A228240E00066BAC6500746E
+:101C1000AF5000248FBF00148FB0001003E0000805
+:101C200027BD001827BDFFC0AFBE0038AFB70034D6
+:101C3000AFB5002CAFB20020AFB1001CAFB00018A0
+:101C4000AFBF003CAFB60030AFB40028AFB3002444
+:101C50008F4500248F4600288F43002C3C02001F34
+:101C60003442FF800062182400C230240080A82182
+:101C7000AFA3001400A2F0240E00062FAFA60010A0
+:101C80003C0208008C4200E02410FF8003608821A1
+:101C900002A2102100501024AF4200243C02080090
+:101CA0008C4200E002A210213042007F0342182142
+:101CB0003C02000A00629021924200D293630084A9
+:101CC000305700FF306300FF24020001106200342F
+:101CD000036020212402000214620036000000008C
+:101CE0000E001216024028219223008392220083C4
+:101CF0003063007F3042007F000210C000031940B3
+:101D0000006218213C0208008C4200DC02A2102173
+:101D10000043382100F01024AF42002892250078BB
+:101D20009224008330E2007F034218213C02000C21
+:101D300014850007006280212402FFFFA24200F107
+:101D40002402FFFFA64200F20A0007272402FFFF39
+:101D500096020020A24200F196020022A64200F262
+:101D60008E020024AE4200F492220083A24200F0D0
+:101D70008E4200C8AE4200FC8E4200C4AE4200F863
+:101D80008E220050AE4201008E4200CCAE420104D1
+:101D9000922200853042003F0A0007823442004010
+:101DA0000E00123902402821922200850A00078283
+:101DB0003042003F936200852403FFDF3042003F42
+:101DC000A36200859362008500431024A36200850E
+:101DD0009363008393620078307400FF304200FF09
+:101DE00010540036240AFF803C0C000C3283007F24
+:101DF000000310C000031940006218213C020800D3
+:101E00008C4200DC268800013109007F02A21021EB
+:101E10000043382130E2007F0342182100EA1024F9
+:101E2000AF420028006C80218E020024028A182410
+:101E3000006A5826AE02000C8E020024310800FF12
+:101E4000AE02001096020014960300208E07001CBC
+:101E50003042FFFF3063FFFF8E060018004310235F
+:101E600000021100000227C30040282100C43023D3
+:101E700000E2102B00C2302300E53823AE07001C1F
+:101E8000AE06001896020020A60200149602002258
+:101E9000A602001692220079304200FF105400077B
+:101EA0000000000051370001316800FF92220078E5
+:101EB000304200FF1448FFCD0100A0219222008390
+:101EC000A22200798E2200500A0007E2AE220070A2
+:101ED000A22200858E22004C2405FF80AE42010C18
+:101EE0009222008534420020A2220085924200D135
+:101EF0003C0308008C6300DC305400FF3C02080007
+:101F00008C4200E400143140001420C002A31821C8
+:101F100000C4202102A210210064382100461021B3
+:101F20000045182400E52824AF450028AF43002CC5
+:101F30003042007F924400D030E3007F03422821EA
+:101F4000034318213C02000C006280213C02000E79
+:101F5000309600FF00A298211296002A000000008F
+:101F60008E02000C02002021026028211040002572
+:101F7000261000280E00064A000000009262000DA4
+:101F800026830001307400FF3042007FA262000D02
+:101F90002404FF801697FFF0267300203C020800FF
+:101FA0008C4200DC0000A02102A210210044102479
+:101FB000AF4200283C0208008C4200E43C030800C9
+:101FC0008C6300DC02A2102100441024AF42002CDC
+:101FD0003C0208008C4200E402A318213063007F19
+:101FE00002A210213042007F034220210343182126
+:101FF0003C02000C006280213C02000E0A0007A493
+:10200000008298218E4200D8AE2200508E4200D825
+:10201000AE22007092250083924600D19223008365
+:10202000924400D12402FF8000A228243063007F64
+:10203000308400FF00A628250064182A10600002E2
+:1020400030A500FF38A50080A2250083A2250079D5
+:102050000E00063D000000009222007E02A020211A
+:10206000A222007A8E2300743C027FFF3442FFFFDD
+:10207000006218240E00066BAE2300748FA20010BD
+:10208000AF5E00248FBF003CAF4200288FBE0038F7
+:102090008FA200148FB700348FB600308FB5002C9C
+:1020A0008FB400288FB300248FB200208FB1001CA2
+:1020B0008FB0001827BD004003E00008AF42002C9D
+:1020C00090A2000024420001A0A200003C030800EE
+:1020D0008C6300F4304200FF1443000F0080302175
+:1020E000A0A000003C0208008C4200E48F84003471
+:1020F000008220213082007F034218213C02000C24
+:10210000006218212402FF8000822024ACC300005A
+:1021100003E00008AF4400288C8200002442002025
+:1021200003E00008AC82000094C200003C080800F4
+:10213000950800CA30E7FFFF008048210102102106
+:10214000A4C2000094C200003042FFFF00E2102B46
+:1021500054400001A4C7000094A200003C03080002
+:102160008C6300CC24420001A4A2000094A20000D1
+:102170003042FFFF544300078F8600280107102BD1
+:10218000A4A000005440000101003821A4C70000B1
+:102190008F8600288CC4001CAF44003C94A2000031
+:1021A0008F43003C3042FFFF000210C00062182144
+:1021B000AF43003C8F42003C008220231880000483
+:1021C000000000008CC200180A00084324420001ED
+:1021D0008CC20018AF4200383C020050344200105C
+:1021E000AF420030000000000000000000000000CE
+:1021F0008F420000304200201040FFFD0000000030
+:102200008F420404AD2200048F420400AD2200007E
+:102210003C020020AF42003003E000080000000054
+:1022200027BDFFE0AFB20018AFB10014AFB000108F
+:10223000AFBF001C94C2000000C080213C12080007
+:10224000965200C624420001A60200009603000038
+:1022500094E2000000E03021144300058FB100300B
+:102260000E000818024038210A000875000000001E
+:102270008C8300048C820004244200400461000727
+:10228000AC8200048C8200040440000400000000C2
+:102290008C82000024420001AC8200009602000003
+:1022A0003042FFFF50520001A600000096220000BD
+:1022B00024420001A62200008F82002896230000FD
+:1022C00094420016144300048FBF001C2402000136
+:1022D000A62200008FBF001C8FB200188FB100141F
+:1022E0008FB0001003E0000827BD00208F89002870
+:1022F00027BDFFE0AFBF00188D220028274804004B
+:1023000030E700FFAF4200388D22002CAF8800304C
+:10231000AF42003C3C020005AF420030000000002C
+:1023200000000000000000000000000000000000AD
+:10233000000000008C82000C8C82000CAD020000BA
+:102340008C820010AD0200048C820018AD020008DF
+:102350008C82001CAD02000C8CA20014AD02001097
+:102360008C820020AD02001490820005304200FFF4
+:1023700000021200AD0200188CA20018AD02001C71
+:102380008CA2000CAD0200208CA20010AD02002433
+:102390008CA2001CAD0200288CA20020AD02002CF3
+:1023A000AD060030AD000034978300263402FFFFF5
+:1023B00014620002006020213404FFFF10E00011CD
+:1023C000AD04003895230036952400362402000120
+:1023D0003063FFFF000318C20069182190650040B8
+:1023E000308400070082100400451025A0620040E0
+:1023F0008F820028944200563042FFFF0A0008DC1A
+:10240000AD02003C952300369524003624020001DD
+:102410003063FFFF000318C2006918219065004077
+:1024200030840007008210040002102700451024A9
+:10243000A0620040AD00003C000000000000000071
+:10244000000000003C02000634420040AF42003071
+:102450000000000000000000000000008F420000AB
+:10246000304200101040FFFD8F860028AF880030FA
+:1024700024C2005624C7003C24C4002824C50032CE
+:1024800024C600360E000856AFA200108FBF0018F9
+:1024900003E0000827BD00208F8300243C060800CD
+:1024A0008CC600E88F82003430633FFF0003198040
+:1024B00000461021004310212403FF803046007F96
+:1024C00000431024AF420028034618213C02000CB0
+:1024D0000062302190C2000D30A500FF00003821BD
+:1024E00034420010A0C2000D8F8900288F8A00247A
+:1024F00095230036000A13823048000324020001AD
+:10250000A4C3000E1102000B2902000210400005B6
+:10251000240200021100000C240300010A0009201B
+:102520000000182111020006000000000A00092026
+:10253000000018218CC2002C0A000920244300014D
+:102540008CC20014244300018CC200180043102BDD
+:1025500050400009240700012402002714A20003B0
+:10256000000000000A00092C240700019522003E0B
+:1025700024420001A522003E000A138230430003DA
+:102580002C62000210400009008028211460000421
+:102590000000000094C200360A00093C3046FFFFEC
+:1025A0008CC600380A00093C008028210000302138
+:1025B0003C04080024844B780A00088900000000CD
+:1025C000274901008D22000C9523000601202021BF
+:1025D000000216023046003F3063FFFF240200274E
+:1025E00000C0282128C7002810C2000EAF83002495
+:1025F00010E00008240200312402002110C200096A
+:102600002402002510C200079382002D0A00095BF6
+:102610000000000010C200059382002D0A00095B33
+:10262000000000000A0008F4000000000A0006266E
+:102630000000000095230006912400058D25000C64
+:102640008D2600108D2700188D28001C8D29002054
+:10265000244200013C010800A4234B7E3C010800F9
+:10266000A0244B7D3C010800AC254B843C010800B4
+:10267000AC264B883C010800AC274B903C0108007D
+:10268000AC284B943C010800AC294B9803E00008AF
+:10269000A382002D8F87002827BDFFC0AFB3003471
+:1026A000AFB20030AFB1002CAFB00028AFBF0038E0
+:1026B0003C0208008C4200D094E3003030B0FFFFB1
+:1026C000005010073045FFFF3063FFFF00C0982126
+:1026D000A7A200103C110800963100C614A3000602
+:1026E0003092FFFF8CE2002424420030AF42003CD5
+:1026F0000A0009948CE2002094E200323042FFFF8D
+:1027000054A2000827A400188CE2002C24420030B8
+:10271000AF42003C8CE20028AF4200380A0009A218
+:102720008F84002827A5001027A60020022038212A
+:102730000E000818A7A000208FA200182442003025
+:10274000AF4200388FA2001CAF42003C8F840028AB
+:102750003C020005AF42003094820034274304005D
+:102760003042FFFF0202102B14400007AF830030FD
+:1027700094820054948300340202102100431023F9
+:102780000A0009B63043FFFF94830054948200345A
+:102790000223182100501023006218233063FFFF2A
+:1027A000948200163042FFFF144300030000000033
+:1027B0000A0009C424030001948200163042FFFF7E
+:1027C0000043102B104000058F82003094820016C9
+:1027D000006210233043FFFF8F820030AC530000B3
+:1027E000AC400004AC520008AC43000C3C020006B4
+:1027F00034420010AF420030000000000000000032
+:10280000000000008F420000304200101040FFFD29
+:10281000001018C2006418219065004032040007BF
+:10282000240200018FBF00388FB300348FB2003014
+:102830008FB1002C8FB000280082100400451025B5
+:1028400027BD004003E00008A062004027BDFFA8AC
+:10285000AFB60050AFB5004CAFB40048AFB30044C2
+:10286000AFB1003CAFBF0054AFB20040AFB00038D2
+:102870008C9000003C0208008C4200E88F860034F7
+:10288000960300022413FF8000C2302130633FFF13
+:102890000003198000C3382100F3102490B2000017
+:1028A000AF42002C9203000230E2007F034230214D
+:1028B0003C02000E00C28821306300C024020040A8
+:1028C0000080A82100A0B021146200260000A021F1
+:1028D0008E3400388E2200181440000224020001B9
+:1028E000AE2200189202000D304200201440001564
+:1028F0008F8200343C0308008C6300DC001238C077
+:10290000001231400043102100C730210046382119
+:1029100030E300073C02008030E6007800C230253A
+:102920000343182100F31024AF4208002463090078
+:10293000AF4608108E2200188C6300080043102157
+:10294000AE2200188E22002C8E2300182442000193
+:102950000062182B1060003D000000000A000A7899
+:1029600000000000920300022402FFC00043102474
+:10297000304200FF1440000524020001AE2200187E
+:10298000962200360A000A613054FFFF8E2200149E
+:1029900024420001AE22001892020000000216003C
+:1029A0000002160304410029000000009602000204
+:1029B00027A4001000802821A7A20016960200027A
+:1029C00024070001000030213042FFFFAF820024C5
+:1029D0000E000889AFA0001C960300023C0408000A
+:1029E0008C8400E88F82003430633FFF000319803D
+:1029F00000441021004310213043007F3C05000CAF
+:102A00000053102403431821AF4200280065182109
+:102A10009062000D001221403042007FA062000D44
+:102A20003C0308008C6300E48F82003400431021D3
+:102A30000044382130E2007F03421021004510217C
+:102A400000F31824AF430028AEA200009222000D2C
+:102A5000304200101040001302A020218F83002874
+:102A60008EA40000028030219462003E2442FFFFC9
+:102A7000A462003E948400029625000E3084FFFF7D
+:102A80000E00097330A5FFFF8F82002894430034A5
+:102A90009622000E1443000302A02021240200010C
+:102AA000A382002C02C028210E0007FE00000000B7
+:102AB0008FBF00548FB600508FB5004C8FB40048C4
+:102AC0008FB300448FB200408FB1003C8FB000380C
+:102AD00003E0000827BD00588F82002827BDFFD0E3
+:102AE000AFB40028AFB20020AFBF002CAFB30024BA
+:102AF000AFB1001CAFB00018904400D0904300D19B
+:102B00000000A021309200FFA3A30010306300FF5B
+:102B10008C5100D88C5300DC1072002B2402000171
+:102B20003C0308008C6300E493A400108F820034FF
+:102B30002406FF800004214000431021004410219E
+:102B40003043007F00461024AF4200280343182181
+:102B50003C02000C006218218C62000427A40014BF
+:102B600027A50010022280210270102304400015C6
+:102B7000AFA300149062000D00C21024304200FF89
+:102B800014400007020088219062000D344200408A
+:102B90000E0007FEA062000D0A000ABD93A20010FD
+:102BA0000E0009E1241400018F830028AC7000D8C6
+:102BB00093A20010A06200D193A200101452FFD87B
+:102BC0000000000024020001168200048FBF002CC8
+:102BD0000E000626000000008FBF002C8FB40028D6
+:102BE0008FB300248FB200208FB1001C8FB000186B
+:102BF00003E0000827BD003027BDFFD8AFB3001C9D
+:102C0000AFB20018AFB10014AFB00010AFBF0020DA
+:102C10000080982100E0802130B1FFFF0E00049376
+:102C200030D200FF000000000000000000000000A3
+:102C30008F820020AC510000AC520004AC5300085D
+:102C4000AC40000CAC400010AC400014AC4000188C
+:102C50003C03080094634B5E02038025AC50001CCB
+:102C6000000000000000000000000000240400013B
+:102C70008FBF00208FB3001C8FB200188FB10014DB
+:102C80008FB000100A0004B827BD002827BDFFE858
+:102C9000AFB00010AFBF001430A5FFFF30C600FF7B
+:102CA0000080802124020C80AF420024000000003C
+:102CB0000000000000000000000000000000000014
+:102CC0000E000ACC000000003C040800248400E050
+:102CD0008C8200002403FF808FBF001402021021A9
+:102CE00000431024AF4200248C8200003C03000A01
+:102CF000020280213210007F035010218FB000109B
+:102D00000043102127BD001803E00008AF8200280F
+:102D100027BDFFE8AFBF00108F4401403C0308000F
+:102D20008C6300E02402FF80AF840034008318210C
+:102D300000621024AF4200243C02000803424021FC
+:102D4000950500023063007F3C02000A034318210E
+:102D50000062182130A5FFFF3402FFFF0000302180
+:102D60003C07602010A20006AF8300282402FFFF6A
+:102D7000A5020002946500D40E000AF130A5FFFF01
+:102D80008FBF001024020C8027BD001803E000084C
+:102D9000AF4200243C020008034240219502000299
+:102DA0003C0A0800954A00C63046FFFF14C00007E1
+:102DB0003402FFFF8F8200288F8400343C0760209C
+:102DC000944500D40A000B5A30A5FFFF10C200241E
+:102DD0008F87002894E2005494E400163045FFFFEA
+:102DE00000A6102300A6182B3089FFFF10600004F6
+:102DF0003044FFFF00C51023012210233044FFFFA1
+:102E0000008A102B1040000C012A1023240200011C
+:102E1000A50200162402FFFFA502000294E500D4DB
+:102E20008F8400340000302130A5FFFF3C07602074
+:102E30000A000AF1000000000044102A10400008B7
+:102E4000000000009502001630420001104000040E
+:102E5000000000009742007E24420014A5020016E4
+:102E600003E00008000000008F84002827BDFFE079
+:102E7000AFBF0018948200349483003E1060001AA3
+:102E80003048FFFF9383002C2402000114620027C6
+:102E90008FBF00188F820028000818C23108000771
+:102EA000006218212447003A244900542444002099
+:102EB000244500302446003490620040304200FF38
+:102EC0000102100730420001104000168FBF0018A9
+:102ED0000E000856AFA900108F82002894420034DB
+:102EE0000A000B733048FFFF94830036948200344D
+:102EF0001043000E8FBF001894820036A482003465
+:102F000094820056A48200548C82002CAC8200244F
+:102F100094820032A48200309482003CA482003A61
+:102F20008FBF00180A000B3327BD002003E0000804
+:102F300027BD002027BDFFE8AFBF00108F4A01006A
+:102F40003C0508008CA500E03C02080090424B8440
+:102F50003C0C0800958C4B7E01452821304B003FEE
+:102F600030A2007F03424021396900323C02000A4E
+:102F70003963003F2C630001010240212D2900012B
+:102F80002402FF8000A2282401234825AF8A0034B0
+:102F900000801821AF450024000030210080282146
+:102FA00024070001AF8800283C04080024844B78E3
+:102FB000AF8C002415200007A380002D24020020E0
+:102FC0005562000F006020213402FFFF5582000C83
+:102FD000006020212402002015620005000000008E
+:102FE0008C6300142402FFFF106200070000000041
+:102FF0000E000889000000000A000BD0000000004D
+:103000000E0008F4016028210E000B68000000008B
+:103010008FBF001024020C8027BD001803E00008B9
+:10302000AF4200243C0208008C4200E027BDFFA014
+:10303000AFB1003C008210212411FF80AFBE0058C8
+:10304000AFB70054AFB20040AFB00038AFBF005CC4
+:10305000AFB60050AFB5004CAFB40048AFB30044BA
+:10306000005110248F4800248F4900288F470028E2
+:10307000AF4200243C0208008C4200E00080902116
+:1030800024060006008210213042007F03421821EE
+:103090003C02000A006280213C02001F3442FF8093
+:1030A00000E2382427A40010260500F00122F024B5
+:1030B0000102B8240E00051DAFA700308FA2001832
+:1030C000AE0200C48FA2001CAE0200C88FA2002472
+:1030D000AE0200CC93A40010920300D12402FF8022
+:1030E0000082102400431025304900FF3083007F08
+:1030F0003122007F0062102A10400004000310C03B
+:1031000001311026304900FF000310C000031940B0
+:10311000006218213C0208008C4200DC920400D2BC
+:10312000024210210043102100511024AF42002818
+:1031300093A300103063007F000310C00003194008
+:10314000006218213C0208008C4200DC024210217F
+:10315000004310213042007F034218213C02000C42
+:10316000006240218FA300142402FFFF1062003090
+:10317000309500FF93A2001195030014304400FF26
+:103180003063FFFF0064182B1060000D000000008A
+:10319000950400148D07001C8D0600183084FFFF75
+:1031A00000442023000421000000102100E4382105
+:1031B00000E4202B00C230210A000C4A00C4302158
+:1031C000950400148D07001C8D0600183084FFFF45
+:1031D000008220230004210000001021008018211B
+:1031E00000C2302300E4202B00C4302300E3382346
+:1031F000AD07001CAD06001893A20011A502001433
+:1032000097A20012A50200168FA20014AD020010B2
+:103210008FA20014AD02000C93A20011A5020020A1
+:1032200097A20012A50200228FA20014AD02002472
+:103230002406FF80024610243256007FAF4200244D
+:10324000035618213C02000A006280218E02004CC5
+:103250008FA200203124007F000428C0AE0200505D
+:103260008FA200200004214000852821AE020070BA
+:1032700093A2001001208821A202008393A20010D3
+:10328000A2020079920200853042003FA20200852E
+:103290003C0208008C4200DC024210210045102153
+:1032A00000461024AF42002C3C0208008C4200E48F
+:1032B0003C0308008C6300DC024210210044102112
+:1032C00000461024AF4200283C0208008C4200E473
+:1032D00002431821006518210242102100441021E8
+:1032E0003042007F3063007F93A50010034220210D
+:1032F000034318213C02000E006240213C02000CF6
+:1033000010B1008C008248213233007F1660001912
+:103310002404FF803C0208008C4200DC02421021A1
+:1033200000441024AF42002C3C0208008C4200E410
+:103330003C0308008C6300DC02421021004410248E
+:10334000AF4200283C0208008C4200E402431821EE
+:103350003063007F024210213042007F034220216F
+:10336000034318213C02000E006240213C02000C85
+:10337000008248219124000D2414FF8000001021B8
+:1033800000942025A124000D950400029505001449
+:103390008D07001C3084FFFF30A5FFFF8D0600184D
+:1033A000008520230004210000E4382100C23021E0
+:1033B00000E4202B00C43021AD07001CAD0600182E
+:1033C00095020002A5020014A50000168D02000857
+:1033D000AD0200108D020008AD02000C9502000243
+:1033E000A5020020A50000228D020008AD020024E5
+:1033F0009122000D30420040104000422622000180
+:103400003C0208008C4200E0A3B300283C10000AF4
+:103410000242102100541024AF4200243C02080054
+:103420008C4200E0A380002C27A4002C0242102133
+:103430003042007F03421821007018218C6200D8AE
+:103440008D26000427A50028AFA9002C00461021D6
+:10345000AC6200D80E0009E1AF83002893A30028D6
+:103460008F8200280E000626A04300D10E000B68B4
+:103470000000000002541024AF4200243C02080067
+:103480008C4200DC00132940001320C000A420213E
+:10349000024210210044102100541024AF42002C9D
+:1034A0003C0208008C4200E43C0308008C6300DC12
+:1034B00003563021024210210045102100541024EF
+:1034C000AF4200283C0208008C4200E4024318216D
+:1034D0000064182102421021004510213042007F73
+:1034E0003063007F03422021034318213C02000E79
+:1034F000006240213C02000C00D080210082482163
+:10350000262200013043007F14750005304400FF7F
+:103510002403FF800223102400431026304400FFC0
+:1035200093A2001000808821250800281444FF760B
+:103530002529002093A400108FA300142402FFFF6C
+:103540001062000A308900FF2482000124830001F8
+:103550003042007F14550005306900FF2403FF80CE
+:103560000083102400431026304900FF92020078A7
+:10357000305300FF11330032012088213C02080043
+:103580008C4200DC3225007F000520C00005294068
+:1035900000A42021024210212406FF8000441021B3
+:1035A00000461024AF42002C3C0308008C6300DC72
+:1035B0003C0208008C4200E4024318210242102120
+:1035C0000045102100641821004610243063007F5C
+:1035D000AF420028034318213C02000E0062402144
+:1035E0003C0208008C4200E48D06000C0100202102
+:1035F00002421021004510213042007F0342182171
+:103600003C02000C0062482110C0000D012028215E
+:103610000E00064A000000002402FF800222182447
+:1036200026240001006228263082007F1455000203
+:10363000308300FF30A300FF1473FFD000608821A7
+:103640008E0300743C027FFF3442FFFF00621824A7
+:10365000AE0300740E00066B02402021AF57002419
+:103660008FA20030AF5E00288FBF005C8FBE005875
+:103670008FB700548FB600508FB5004C8FB4004800
+:103680008FB300448FB200408FB1003C8FB0003840
+:1036900027BD006003E00008AF42002C27BDFFD823
+:1036A000AFB1001CAFBF0020AFB000182751018898
+:1036B000922200032408FF803C03000A3047007F69
+:1036C000A3A700108F4601803C0208008C4200E056
+:1036D000AF86003400C2282100A81024AF42002485
+:1036E0009224000030A2007F0342102100431021E9
+:1036F000AF8200283084007F24020002148200255B
+:10370000000719403C0208008C4200E400C210216E
+:103710000043282130A2007F0342182100A8102472
+:10372000AF4200283C02000C006218219062000D9C
+:10373000AFA3001400481025A062000D8FA3001451
+:103740009062000D304200405040006A8FBF002060
+:103750008F860028A380002C27A400148CC200D8D8
+:103760008C63000427A50010004310210E0009E11E
+:10377000ACC200D893A300108F8200280E0006264A
+:10378000A04300D10E000B68000000000A000E0BE1
+:103790008FBF00200E00062F00C020210E00063D26
+:1037A000000000003C020008034280219223000137
+:1037B0009202007B1443004F8FBF00209222000032
+:1037C0003044007F24020004108200172882000584
+:1037D00010400006240200052402000310820007A6
+:1037E0008FB1001C0A000E0C0000000010820012B5
+:1037F0008FBF00200A000E0C8FB1001C92050083C1
+:10380000920600788E0700748F84003430A500FF84
+:1038100000073E0230C600FF0E00067330E7007F4F
+:103820000A000E0B8FBF00200E000BD78F840034D0
+:103830000A000E0B8FBF002024020C80AF42002430
+:103840009202003E30420040104000200000000084
+:103850009202003E00021600000216030441000618
+:10386000000000008F8400340E0005A024050093A2
+:103870000A000E0B8FBF00209202003F24030018A5
+:10388000304200FF1443000C8F84003424050039BB
+:103890000E000538000030210E0002508F840034E5
+:1038A00024020012A202003F0E0002598F8400344D
+:1038B0000A000E0B8FBF0020240500360E000538CD
+:1038C000000030210A000E0B8FBF00200E000250B6
+:1038D0008F8400349202000534420020A2020005C9
+:1038E0000E0002598F8400340E000FC08F84003404
+:1038F0008FBF00208FB1001C8FB0001824020C80F5
+:1039000027BD002803E00008AF42002427BDFFE8E0
+:10391000AFB00010AFBF001427430100946200084D
+:103920000002140000021403044100020000802180
+:103930002410000194620008304200801040001AF8
+:10394000020010219462000830422000104000164E
+:10395000020010218C6300183C021C2D344219ED2A
+:10396000240600061062000F3C0760213C0208009C
+:103970008C4200D4104000078F8200288F830028DB
+:10398000906200623042000F34420040A062006248
+:103990008F8200288F840034944500D40E000AF1F1
+:1039A00030A5FFFF020010218FBF00148FB0001060
+:1039B00003E0000827BD001827BDFFE0AFB10014E9
+:1039C000AFB00010A380002CAFBF00188F450100DE
+:1039D0003C0308008C6300E02402FF80AF850034C4
+:1039E00000A318213064007F0344202100621824C2
+:1039F0003C02000A00822021AF430024275001002E
+:103A00008E0200148C8300DCAF8400280043102356
+:103A100018400004000088218E0200140E000A8461
+:103A2000AC8200DC9202000B24030002304200FF53
+:103A30001443002F0000000096020008304300FFEE
+:103A40002402008214620005240200840E00093E54
+:103A5000000000000A000E97000000001462000938
+:103A6000240200818F8200288F8400343C0760216B
+:103A7000944500D49206000530A5FFFF0A000E868B
+:103A800030C600FF14620027000000009202000A06
+:103A9000304300FF306200201040000430620040DC
+:103AA0008F8400340A000E82240600401040000477
+:103AB000000316008F8400340A000E8224060041A1
+:103AC00000021603044100178F84003424060042CC
+:103AD0008F8200283C076019944500D430A5FFFF71
+:103AE0000E000AF1000000000A000E97000000001E
+:103AF0009202000B24030016304200FF1043000620
+:103B0000000000009202000B24030017304200FF67
+:103B100014430004000000000E000E11000000001D
+:103B2000004088210E000B68000000009202000A8D
+:103B3000304200081040000624020C808F850028C7
+:103B40003C0400080E0011EE0344202124020C80E6
+:103B5000AF4200248FBF0018022010218FB0001048
+:103B60008FB1001403E0000827BD002027BDFFE847
+:103B7000AFBF0014AFB000108F5000243C0308000A
+:103B80008C6300E08F4501002402FF8000A3182110
+:103B90003064007F03442021006218243C02000AA4
+:103BA00000822021AF850034AF4300249082006260
+:103BB000AF8400283042000F34420050A0820062DF
+:103BC0003C02001F3442FF800E00062602028024C1
+:103BD000AF5000248FBF00148FB0001003E0000826
+:103BE00027BD00183C0208008C4200201040001D38
+:103BF0002745010090A300093C0200080342202150
+:103C000024020018546200033C0200080A000ED887
+:103C10002402000803422021240200161462000539
+:103C20002402001724020012A082003F0A000EE2C4
+:103C300094A700085462000694A700089362000548
+:103C40002403FFFE00431024A362000594A700088C
+:103C500090A6001B8CA4000094A500060A000ACCC4
+:103C600000073C0003E000080000000027440100BA
+:103C700094820008304500FF38A3008238A20084F7
+:103C80002C6300012C420001006218251060000620
+:103C9000240200839382002D1040000D00000000DC
+:103CA0000A000B9B0000000014A2000524A2FF8064
+:103CB0008F4301043C02602003E00008AC43001481
+:103CC000304200FF2C420002104000032402002278
+:103CD0000A000E3C0000000014A2000300000000D7
+:103CE0000A000EA9000000000A000EC70000000034
+:103CF0009363007E9362007A144300090000202140
+:103D00009362000024030050304200FF144300047B
+:103D1000240400019362007E24420001A362007E1D
+:103D200003E00008008010218F4201F80440FFFEEC
+:103D300024020002AF4401C0A34201C43C021000AF
+:103D400003E00008AF4201F827BDFFE8AFBF001055
+:103D50009362003F2403000A304200FF14430046F0
+:103D6000000000008F6300548F62004C1062007DE1
+:103D7000036030219362000024030050304200FFB2
+:103D80001443002F000000008F4401403C02080053
+:103D90008C4200E02403FF800082102100431024A5
+:103DA000AF4200243C0208008C4200E08F650054C2
+:103DB0003C03000A008220213084007F034410214C
+:103DC00000431021AC4501089762003C8F63004C12
+:103DD0003042FFFF0002104000621821AF63005C18
+:103DE0008F6300548F64004C9762003C006418237A
+:103DF0003042FFFF00031843000210400043102A26
+:103E000010400006000000008F6200548F63004CD9
+:103E1000004310230A000F58000210439762003C31
+:103E20003042FFFF00021040ACC2006424020001D7
+:103E3000A0C0007CA0C2008424020C80AF420024F9
+:103E40000E000F0A8F440140104000478FBF001042
+:103E50008F4301408F4201F80440FFFE240200021C
+:103E6000AF4301C0A34201C43C021000AF4201F8BD
+:103E70000A000FA88FBF00109362003F24030010B8
+:103E8000304200FF14430004000000008F44014052
+:103E90000A000F94000028219362003F24030016BB
+:103EA000304200FF1443000424020014A362003FC8
+:103EB0000A000FA2000000008F62004C8F630050C8
+:103EC00000431023044100288FBF0010936200813B
+:103ED00024420001A3620081936200812C4200040D
+:103EE00014400010000000009362003F240300040F
+:103EF000304200FF14430006000000008F440140E0
+:103F00008FBF0010240500930A0005A027BD0018EC
+:103F10008F440140240500938FBF00100A00060F54
+:103F200027BD00188F4401400E0002500000000021
+:103F30008F6200542442FFFFAF6200548F62005032
+:103F40002442FFFFAF6200500E0002598F4401402F
+:103F50008F4401408FBF0010240500040A00025E58
+:103F600027BD00188FBF001003E0000827BD001810
+:103F70008F4201889363007E00021402304400FFE8
+:103F8000306300FF1464000D0000000093620080A5
+:103F9000304200FF1044000900000000A3640080CC
+:103FA0009362000024030050304200FF14430004D9
+:103FB000000000000A0006D78F440180A36400803F
+:103FC00003E000080000000027BDFFE8AFB00010CC
+:103FD000AFBF00149362000524030030304200306C
+:103FE00014430089008080213C0208008C4200209C
+:103FF00010400080020020210E0004930000000009
+:104000008F850020ACB000009362003E9363003FB8
+:10401000304200FF00021200306300FF0043102511
+:10402000ACA2000493620082000216000002160394
+:1040300004410005000000003C0308008C630048B8
+:104040000A000FE6000000009362003E304200408C
+:10405000144000030000182193620081304300FFE8
+:104060009362008200031E00304200FF0002140031
+:1040700000621825ACA300088F620040ACA2000CBF
+:104080008F620048ACA200108F62004CACA20014FA
+:104090008F6200508F63004C0043102304410003E3
+:1040A000000000000A000FFA8F62004C8F6200507F
+:1040B000ACA200183C02080094424B5E3C03C00BCB
+:1040C00000002021004310250E0004B8ACA2001C03
+:1040D0008F6200548F840020AC8200008F620058F1
+:1040E000AC8200048F62005CAC8200088F620060CA
+:1040F0008F43007400431021AC82000C8F62006477
+:10410000AC820010976300689762006A00031C008D
+:104110003042FFFF00621825AC83001493620082D6
+:1041200024030080304200FF14430003000000001D
+:104130000A00102EAC8000188F63000C24020001CE
+:104140001062000E2402FFFF9362003E30420040E6
+:104150001440000A2402FFFF8F63000C8F4200749A
+:10416000006218233C020800006210241440000280
+:10417000000028210060282100051043AC820018AF
+:104180003C02080094424B5E3C03C00C000020211E
+:10419000004310258F8300200E0004B8AC62001C81
+:1041A0008F6200188F8300203C05080094A54B5EA9
+:1041B00024040001AC620000AC6000048F66006C57
+:1041C0003C02400D00A22825AC6600088F6200DC8E
+:1041D000AC62000CAC600010936200050002160097
+:1041E000AC620014AC6000180E0004B8AC65001C92
+:1041F000020020218FBF00148FB00010A3600005C3
+:104200000A00042127BD00188FBF00148FB00010D2
+:1042100003E0000827BD00189742007C30C600FF6D
+:10422000A08600843047FFFF2402000514C2000B63
+:1042300024E3465090A201122C42000710400007D0
+:1042400024E30A0090A30112240200140062100467
+:1042500000E210210A0010663047FFFF3067FFFFC1
+:1042600003E00008A4870014AC87004C8CA201086E
+:104270000080402100A0482100E2102330C600FF4A
+:104280001840000393AA001324E2FFFCACA201082B
+:1042900030C2000110400008000000008D020050F4
+:1042A00000E2102304410013240600058D0200548F
+:1042B00010E20010000000008D02005414E2001A09
+:1042C000000000003C0208008C4200D83042002070
+:1042D0001040000A2402000191030078910200833B
+:1042E000144300062402000101002021012028219E
+:1042F000240600040A00105400000000A1000084FD
+:1043000011400009A50200148F4301008F4201F8FB
+:104310000440FFFE24020002AF4301C0A34201C4D7
+:104320003C021000AF4201F803E00008000000006A
+:1043300027BDFFE88FA90028AFBF001000804021F3
+:1043400000E918231860007330C600FFA080007CCD
+:10435000A08000818CA2010800E210230440004DDF
+:10436000000000008C8200509483003C8C84006428
+:10437000004748233063FFFF012318210083202BCF
+:1043800010800004000000008D0200640A0010B7D5
+:1043900000E210219502003C3042FFFF0122102173
+:1043A00000E21021AD02005C9502003C8D03005C30
+:1043B0003042FFFF0002104000E210210043102BAA
+:1043C00010400003000000000A0010C68D02005CCF
+:1043D0009502003C3042FFFF0002104000E2102135
+:1043E000AD02005CA1000084AD07004C8CA2010866
+:1043F00000E210231840000224E2FFFCACA20108F6
+:1044000030C200011040000A000000008D02005080
+:1044100000E2102304410004010020218D02005419
+:1044200014E20003000000000A0010E82406000562
+:104430008D02005414E200478FBF00103C020800B8
+:104440008C4200D8304200201040000A24020001B3
+:1044500091030078910200831443000624020001B6
+:1044600001002021240600048FBF00100A00105410
+:1044700027BD0018A1000084A50200148F4301008D
+:104480008F4201F80440FFFE240200020A00110DD1
+:10449000000000008C82005C004910230043102BB8
+:1044A00054400001AC87005C9502003C3042FFFFA5
+:1044B0000062102B14400007240200029502003C09
+:1044C0008D03005C3042FFFF00621821AD03005CE9
+:1044D00024020002AD07004CA10200840E000F0A66
+:1044E0008F4401001040001B8FBF00108F4301005C
+:1044F0008F4201F80440FFFE24020002AF4301C0D6
+:10450000A34201C43C021000AF4201F80A0011238B
+:104510008FBF001030C200101040000E8FBF00107F
+:104520008C83005C9482003C006918233042FFFFBA
+:10453000006218213C023FFF3444FFFF0083102B30
+:10454000544000010080182101231021AD02005CBD
+:104550008FBF001003E0000827BD001827BDFFE84B
+:104560008FAA0028AFBF00100080402100EA482336
+:104570001920002130C600FF8C83005C8C8200640F
+:10458000006A18230043102B5040001000691821C6
+:1045900094A2011001221021A4A2011094A20110E2
+:1045A0003042FFFF0043102B1440000A3C023FFF43
+:1045B00094A2011000431023A4A201109482003C95
+:1045C0003042FFFF0A00114200621821A4A001102E
+:1045D0003C023FFF3444FFFF0083102B5440000196
+:1045E0000080182100671021AD02005CA100007C52
+:1045F0000A00118AA100008130C200101040003C66
+:10460000000000008C820050004A1023184000383F
+:10461000000000009082007C24420001A082007C07
+:104620009082007C3C0308008C630024304200FF31
+:104630000043102B1440005C8FBF00108CA20108B7
+:1046400000E2102318400058000000008C83005442
+:104650009482003C006A18233042FFFF0003184395
+:10466000000210400043102A104000050000000026
+:104670008C820054004A10230A001171000210437A
+:104680009482003C3042FFFF00021040AD02006403
+:104690009502003C8D0400649503003C3042FFFF0E
+:1046A00000021040008220213063FFFF00831821A8
+:1046B00001431021AD02005C8D020054ACA2010840
+:1046C00024020002A10200840E000F0A8F440100A0
+:1046D000104000358FBF00108F4301008F4201F85A
+:1046E0000440FFFE240200020A0011B30000000093
+:1046F000AD07004C8CA2010800E210231840000214
+:1047000024E2FFFCACA2010830C200011040000A04
+:10471000000000008D02005000E21023044100045C
+:10472000010020218D02005414E20003000000006B
+:104730000A0011AA240600058D02005414E2001A92
+:104740008FBF00103C0208008C4200D8304200208D
+:104750001040000A240200019103007891020083B6
+:104760001443000624020001010020212406000455
+:104770008FBF00100A00105427BD0018A10000844C
+:10478000A50200148F4301008F4201F80440FFFE90
+:1047900024020002AF4301C0A34201C43C02100046
+:1047A000AF4201F88FBF001003E0000827BD0018DA
+:1047B0008FAA00108C8200500080402130C600FF7C
+:1047C000004A102300A048211840000700E01821EB
+:1047D00024020001A0800084A0A00112A482001481
+:1047E0000A001125AFAA0010A0800081AD07004C7F
+:1047F0008CA2010800E210231840000224E2FFFC12
+:10480000ACA2010830C20001104000080000000006
+:104810008D0200500062102304410013240600059D
+:104820008D02005410620010000000008D02005440
+:1048300014620011000000003C0208008C4200D805
+:10484000304200201040000A240200019103007849
+:10485000910200831443000624020001010020217C
+:1048600001202821240600040A0010540000000042
+:10487000A1000084A502001403E00008000000006D
+:1048800027BDFFE0AFBF0018274201009046000A95
+:104890008C4800148C8B004C9082008430C900FF3F
+:1048A00001681823304A00FF1C60001A2D460006DC
+:1048B000240200010142100410C00016304300031E
+:1048C000012030210100382114600007304C000C19
+:1048D00015800009304200301440000B8FBF0018D3
+:1048E0000A001214000000000E001125AFAB0010EA
+:1048F0000A0012148FBF00180E00109AAFAB001000
+:104900000A0012148FBF0018AFAB00100E0011BACE
+:10491000AFAA00148FBF001803E0000827BD0020D5
+:1049200024020003A08200848C82005403E000086B
+:10493000ACA201083C0200080342182190620081E9
+:10494000240600433C07601924420001A062008154
+:10495000906300813C0208008C4200C0306300FF7D
+:10496000146200102403FF803C0208008C4200E027
+:104970000082102100431024AF4200243C020800B2
+:104980008C4200E03C03000A008210213042007F8C
+:104990000342102100431021944500D40A000AF17B
+:1049A00030A5FFFF03E000080000000027BDFFE086
+:1049B000AFBF0018AFB10014AFB000108F4201803C
+:1049C0000080802100A088210E00121B00402021C1
+:1049D000A20000848E0200548FBF00188FB0001018
+:1049E000AE2201088FB1001403E0000827BD0020AB
+:1049F00027BDFFE03C020008AFB00010AFBF0018B9
+:104A0000AFB10014034280218F5101409203008412
+:104A10008E0400508E02004C14820040306600FF6D
+:104A20003C0208008C4200E02403FF800222102197
+:104A300000431024AF4200243C0208008C4200E0F6
+:104A40009744007C92050081022210213042007FB1
+:104A5000034218213C02000A0062182114A0000B36
+:104A60003084FFFF2402000554C20014248205DCB8
+:104A70009062011224420001A062011224020C8003
+:104A8000AF4200240A00127324020005A060011244
+:104A90002402000514C20009248205DC9202008170
+:104AA0002C4200075040000524820A009203008136
+:104AB0002402001400621004008210213044FFFF21
+:104AC000A60400140E00121B022020219602003CB6
+:104AD0008E03004C022020213042FFFF00021040D4
+:104AE000006218210E000250AE03005C9202007DAD
+:104AF00002202021344200400E000259A202007D13
+:104B00008F4201F80440FFFE24020002AF5101C0B1
+:104B1000A34201C43C021000AF4201F88FBF00184D
+:104B20008FB100148FB0001003E0000827BD0020F3
+:104B300008000ACC08000B1408000B9808000BE4CE
+:044B400008000C203D
+:0C4B44000A000028000000000000000033
+:104B50000000000D6370362E302E3135000000004D
+:104B600006000F040000000000000000000000002C
+:104B70000000000000000000000000000000000035
+:104B80000000000000000000000000000000002005
+:104B90000000000000000000000000000000000015
+:104BA0000000000000000000000000000000000005
+:104BB00000000000000000000000000000000001F4
+:104BC0000000002B000000000000000400030D4066
+:104BD00000000000000000000000000000000000D5
+:104BE00000000000000000001000000300000000B2
+:104BF0000000000D0000000D3C0208002442588413
+:104C00003C03080024635F50AC4000000043202BAD
+:104C10001480FFFD244200043C1D080037BD7FFCCA
+:104C200003A0F0213C100800261000A03C1C080046
+:104C3000279C58840E0001AC000000000000000D0D
+:104C400027BDFFE83C096018AFBF00108D2C500055
+:104C5000240DFF7F24080031018D5824356A380C5B
+:104C600024070C003C1A8000AD2A50003C04800A46
+:104C7000AF4800083C1B8008AF4700240E00091510
+:104C8000AF8400100E0008D8000000000E000825B8
+:104C9000000000000E001252000000003C046016EC
+:104CA0008C8500003C06FFFF3C02535300A61824ED
+:104CB0001062004734867C0094C201F2A780002C69
+:104CC00010400003A78000CC38581E1EA798002C67
+:104CD00094C201F810400004978300CC38591E1E7E
+:104CE000A79900CC978300CC2C7F006753E000018C
+:104CF000240300669784002C2C82040114400002D7
+:104D000000602821240404003C0760008CE904387A
+:104D10002403103C3128FFFF1103001F30B9FFFFAF
+:104D200057200010A38000CE24020050A38200CEA2
+:104D3000939F00CE53E0000FA78500CCA78000CC46
+:104D4000978500CC8FBF0010A780002CA78000346F
+:104D5000A78000E63C010800AC25008003E00008C5
+:104D600027BD0018939F00CE57E0FFF5A78000CC29
+:104D7000A78500CC978500CC8FBF0010A784002C9E
+:104D8000A7800034A78000E63C010800AC25008025
+:104D900003E0000827BD0018A38000CE8CCB003CA8
+:104DA000316A00011140000E0000000030A7FFFF33
+:104DB00010E0FFDE240200508CCC00C831860001D8
+:104DC00014C0FFDC939F00CE0A00007A2402005139
+:104DD0008C8F00043C0E60000A00005D01EE302163
+:104DE0008CEF0808240D5708000F740211CD000441
+:104DF00030B8FFFF240500660A00007B240404008D
+:104E00001700FFCC939F00CE0A00007A24020050C6
+:104E10008F8600103089FFFF000939408CC30010D5
+:104E20003C08005000E82025AF4300388CC5001432
+:104E300027420400AF82001CAF45003CAF44003065
+:104E40000000000000000000000000000000000062
+:104E50000000000000000000000000000000000052
+:104E60008F4B0000316A00201140FFFD0000000060
+:104E700003E00008000000008F840010948A001AEC
+:104E80008C8700243149FFFF000940C000E8302131
+:104E9000AF46003C8C8500248F43003C00A31023C8
+:104EA00018400029000000008C8B002025620001C2
+:104EB0003C0D005035AC0008AF420038AF4C00301C
+:104EC00000000000000000000000000000000000E2
+:104ED00000000000000000000000000000000000D2
+:104EE0008F4F000031EE002011C0FFFD00000000D8
+:104EF0008F4A04003C080020AC8A00108F4904044B
+:104F0000AC890014AF4800300000000094860018FF
+:104F10009487001C00C71821A48300189485001AE8
+:104F200024A20001A482001A9498001A9499001EE9
+:104F3000133800030000000003E000080000000038
+:104F400003E00008A480001A8C8200200A0000DC24
+:104F50003C0D00500A0000CD000000003C0308009A
+:104F60008C6300208F82001827BDFFE810620008C4
+:104F7000AFBF00100E000104AF8300183C0308000F
+:104F80008C63002024040001106400048F89001049
+:104F90008FBF001003E0000827BD00188FBF00106E
+:104FA0003C076012A520000A9528000A34E500108D
+:104FB00027BD00183106FFFF03E00008ACA60090F3
+:104FC0003C0208008C42002027BDFFC8AFBF003460
+:104FD000AFBE0030AFB7002CAFB60028AFB500248D
+:104FE000AFB40020AFB3001CAFB20018AFB10014D3
+:104FF00010400050AFB000108F840010948600065F
+:105000009483000A00C3282330B6FFFF12C0004A71
+:105010008FBF003494890018948A000A012A402323
+:105020003102FFFF02C2382B14E0000202C020212F
+:10503000004020212C8C0005158000020080A0215A
+:10504000241400040E0000B3028020218F8700107A
+:1050500002809821AF80001494ED000A028088211C
+:105060001280004E31B2FFFF3C1770003C1540002B
+:105070003C1E60008F8F001C8DEE000001D71824AD
+:10508000507500500220202102A3802B160000350D
+:105090003C182000507800470220202124100001F5
+:1050A0008F83001414600039029158230230F823D2
+:1050B0000250C82133F1FFFF1620FFEE3332FFFF0D
+:1050C0008F8700103C110020AF510030000000001D
+:1050D00094E6000A3C1E601237D5001002662821B3
+:1050E000A4E5000A94E2000A94F2000A94F400187D
+:1050F0003057FFFF1292003BAEB700908CED0014CA
+:105100008CE400100013714001AE4021000E5FC31B
+:10511000010E502B008B4821012A1821ACE8001405
+:10512000ACE3001002D3382330F6FFFF16C0FFB9FE
+:105130008F8400108FBF00348FBE00308FB7002CDB
+:105140008FB600288FB500248FB400208FB3001CC9
+:105150008FB200188FB100148FB0001003E0000868
+:1051600027BD0038107E001B000000001477FFCC24
+:10517000241000010E001598000000008F83001419
+:105180001060FFCB0230F823029158238F87001064
+:10519000017020210A0001973093FFFF8F830014D4
+:1051A0001460FFCB3C110020AF5100300A000163B6
+:1051B000000000000E00077D024028210A00015770
+:1051C000004080210E00033A024028210A000157C6
+:1051D000004080210E001460022020210A000157A7
+:1051E000004080210E0000CD000000000A0001797F
+:1051F00002D3382327BDFFE8AFB00010AFBF0014C3
+:105200000E00003F000000003C028000345000709F
+:105210000A0001BA8E0600008F4F000039EE00012F
+:1052200031C20001104000248F8600A88E070000C4
+:105230003C0C08008D8C003C3C0908008D2900388E
+:1052400000E66823018D28210000502100AD302B9D
+:10525000012A4021010620213C010800AC25003C28
+:10526000AF8700A83C010800AC2400380E000106FE
+:10527000000000003C0308008C6300701060FFE633
+:10528000006020213C0508008CA500683C06080051
+:105290008CC6006C0E001527000000003C010800C1
+:1052A000AC2000708F4F000039EE000131C20001C8
+:1052B0001440FFDE8F8600A88E0A00008F8B00A8A6
+:1052C0003C0508008CA5003C3C0408008C84003898
+:1052D000014B482300A938210082182100E9402B06
+:1052E000006810213C010800AC27003C3C0108008C
+:1052F000AC2200388F5F01002419FF0024180C0035
+:1053000003F9202410980012AF840000AF4400205D
+:10531000936D0000240C002031A600FF10CC001279
+:10532000240E005010CE00043C194000AF59013843
+:105330000A0001B3000000000E0011C800000000C8
+:105340003C194000AF5901380A0001B300000000C9
+:105350000E00011F000000003C194000AF59013849
+:105360000A0001B3000000008F58010000802821CE
+:10537000330F00FF01E020210E0002F1AF8F000487
+:105380003C194000AF5901380A0001B30000000089
+:1053900000A4102B2403000110400009000030215C
+:1053A0000005284000A4102B04A0000300031840AF
+:1053B0005440FFFC000528405060000A0004182BF0
+:1053C0000085382B54E000040003184200C3302548
+:1053D00000852023000318421460FFF900052842CD
+:1053E0000004182B03E0000800C310218F4201B80D
+:1053F0000440FFFE00000000AF4401803C031000A9
+:1054000024040040AF450184A3440188A3460189D8
+:10541000A747018A03E00008AF4301B83084FFFFCB
+:105420000080382130A5FFFF000020210A00022A59
+:10543000240600803087FFFF8CA40000240600387B
+:105440000A00022A000028218F8300388F8600304E
+:105450001066000B008040213C07080024E759F843
+:10546000000328C000A710218C4400002463000121
+:10547000108800053063000F5466FFFA000328C04F
+:1054800003E00008000010213C07080024E759FC55
+:1054900000A7302103E000088CC200003C0390000C
+:1054A0003462000100822025AF4400208F45002097
+:1054B00004A0FFFE0000000003E000080000000060
+:1054C0003C038000346200010082202503E00008D4
+:1054D000AF44002027BDFFE0AFB100143091FFFFC3
+:1054E000AFB00010AFBF00181220001300A0802141
+:1054F0008CA2000024040002240601401040000F8A
+:10550000004028210E000C5C00000000000010216B
+:10551000AE000000022038218FBF00188FB10014A8
+:105520008FB0001000402021000028210000302111
+:105530000A00022A27BD00208CA200000220382188
+:105540008FBF00188FB100148FB0001000402021D1
+:1055500000002821000030210A00022A27BD002077
+:1055600000A010213087FFFF8CA500048C440000B0
+:105570000A00022A2406000627BDFFE0AFB0001093
+:10558000AFBF0018AFB100149363003E00808021CC
+:105590000080282130620040000020211040000FD0
+:1055A0008E1100000E000851022020219367000098
+:1055B0002404005030E500FF50A400128E0F0000BC
+:1055C000022020218FBF00188FB100148FB000106F
+:1055D000A762013C0A00091127BD00200E000287C6
+:1055E000000000000E0008510220202193670000F7
+:1055F0002404005030E500FF14A4FFF20220202113
+:105600008E0F00003C1008008E1000503C0D000C66
+:10561000240BFF8001F05021314E007F01DA602120
+:10562000018D4021014B4824AF4900280220202150
+:105630008FBF00188FB100148FB00010A50200D6E4
+:1056400027BD00200A000911AF8800D027BDFFE068
+:10565000AFBF0018AFB10014AFB0001093660001E7
+:10566000008080210E00025630D1000493640005B2
+:10567000001029C2A765000034830040A363000521
+:105680000E00025F020020210E00091302002021FB
+:1056900024020001AF62000C02002821A762001062
+:1056A00024040002A762001224060140A76200142D
+:1056B0000E000C5CA76200161620000F8FBF0018AA
+:1056C000978C00343C0B08008D6B00782588FFFF19
+:1056D0003109FFFF256A0001012A382B10E000067E
+:1056E000A78800343C0F6006240E001635ED00102C
+:1056F000ADAE00508FBF00188FB100148FB00010F6
+:1057000003E0000827BD002027BDFFE0AFB1001473
+:10571000AFBF0018AFB0001000A088211080000AB1
+:105720003C03600024020080108200120000000090
+:105730000000000D8FBF00188FB100148FB0001053
+:1057400003E0000827BD00208C682BF80500FFFE51
+:1057500000000000AC712BC08FBF00188FB1001487
+:105760008FB000103C09100027BD002003E00008A6
+:10577000AC692BF80E00025600A0202193650005AD
+:10578000022020210E00025F30B000FF2403003E03
+:105790001603FFE7000000008F4401780480FFFE3D
+:1057A000240700073C061000AF51014002202021D1
+:1057B000A34701448FBF00188FB100148FB00010B1
+:1057C000AF4601780A0002C227BD002027BDFFE8CE
+:1057D000AFBF0014AFB000108F50002000000000D9
+:1057E0000E000913AF440020AF5000208FBF0014FB
+:1057F0008FB0001003E0000827BD00183084FFFFC1
+:10580000008038212406003500A020210A00022A49
+:10581000000028213084FFFF008038212406003654
+:1058200000A020210A00022A0000282127BDFFD065
+:10583000AFB3001C3093FFFFAFB50024AFB2001828
+:10584000AFBF0028AFB40020AFB10014AFB000105C
+:1058500030B5FFFF12600027000090218F90001CE0
+:105860008E0300003C0680002402004000033E023C
+:1058700000032C0230E4007F006688241482001D9F
+:1058800030A500FF8F8300282C68000A510000100B
+:105890008F910014000358803C0C0800258C56881A
+:1058A000016C50218D49000001200008000000001B
+:1058B00002B210213045FFFF0E000236240400849E
+:1058C000162000028F90001CAF8000288F910014DA
+:1058D000260C002026430001018080213072FFFF4A
+:1058E00016200004AF8C001C0253502B1540FFDC27
+:1058F00000000000024010218FBF00288FB5002457
+:105900008FB400208FB3001C8FB200188FB1001429
+:105910008FB0001003E0000827BD0030240E0034D3
+:1059200014AE00F9000000009203000E241F168040
+:105930003C07000CA36300219202000D0347C8211D
+:105940003C066000A3620020961100123C0A7FFF13
+:10595000354CFFFFA771003C960B00102403000597
+:105960003168FFFFAF6800848E05001CAF5F002820
+:105970008F3800008CC4444803057826008F3021FE
+:10598000AF66004C8F69004C24CE00013C057F00BF
+:10599000AF6900508F740050AF740054AF66007050
+:1059A000AF6E00588F6D005824140050AF6D005C2E
+:1059B000A3600023AF6C0064A36300378E02001461
+:1059C000AF6200488F710048AF7100248E0B001841
+:1059D000AF6B006C9208000CA3680036937F003E0A
+:1059E00037F90020A379003E8F78007403058024E6
+:1059F000360F4000AF6F007493640000308900FFE1
+:105A0000513402452404FF803C04080024845A7861
+:105A10000E00028D000000003C1008008E105A7825
+:105A20000E00025602002021240600042407000173
+:105A3000A366007D020020210E00025FA36700051F
+:105A40008F5F017807E0FFFE240B0002AF5001409A
+:105A5000A34B01448F90001C3C081000AF48017814
+:105A60000A000362AF8000282CAD003751A0FF98D8
+:105A70008F9100140005A0803C180800271856B02C
+:105A8000029878218DEE000001C00008000000009F
+:105A90002418000614B80011000000003C0808009B
+:105AA0008D085A7824040005AF4800208E1F001886
+:105AB000AF7F00188F79004CAF79001C8F650050C4
+:105AC000122000C0AF6500700A000362AF84002896
+:105AD0002406000710A60083240300063C050800E6
+:105AE00024A55A780E000264240400818F90001CC3
+:105AF0000011102B0A000362AF8200282407000463
+:105B000014A7FFF6240500503C1808008F185A7897
+:105B1000AF5800208E0F0008AF6F00408E090008BC
+:105B2000AF6900448E14000CAF7400488E0E001054
+:105B3000AF6E004C8E0D0010AF6D00848E0A001405
+:105B4000AF6A00508E0C0018AF6C00548E04001C1D
+:105B5000AF64005893630000306B00FF116501D8FB
+:105B6000000000008F7400488F6900400289702394
+:105B700005C000042404008C1620FFDE240200036C
+:105B8000240400823C05080024A55A780E000287F0
+:105B9000000000008F90001C000010210A0003622A
+:105BA000AF820028240F000514AFFFCC240520008D
+:105BB0003C0708008CE75A78AF4700208E060004A7
+:105BC000AF66005C9208000824100008A36800215A
+:105BD0008F9F001C93F90009A37900208F86001C79
+:105BE00090D8000A330400FF10900011000000005C
+:105BF0002885000914A0006924020002240A00205C
+:105C0000108A000B34058000288D002115A00008A3
+:105C100024054000240E0040108E00053C050001C4
+:105C200024140080109400023C050002240540006A
+:105C30008F7800743C19FF00031980240205782531
+:105C4000AF6F007490C4000BA36400818F84001CAC
+:105C50009489000C11200192000000009490000C27
+:105C60002406FFBF24050004A770003C908F000E9F
+:105C7000A36F003E8F84001C9089000FA369003F32
+:105C80008F8B001C8D6E00108F54007401D468231C
+:105C9000AF6D00608D6A0014AF6A0064956C0018E7
+:105CA000A76C00689563001AA763006A8D62001CE8
+:105CB000AF62006C9167000EA367003E9368003EE0
+:105CC0000106F8241220014BA37F003E8F90001C98
+:105CD0000A000362AF8500282407002214A7FF7F73
+:105CE000240300073C0B08008D6B5A781220000C2F
+:105CF000AF4B00200A000362AF830028240C00335E
+:105D000010AC0014240A00283C05080024A55A7889
+:105D10000E00023C240400810A0003EB8F90001C5B
+:105D20003C04080024845A780E00028D0000000014
+:105D30009363000024110050306200FF10510135C0
+:105D4000000000008F90001C000018210A00036270
+:105D5000AF8300283C0D08008DAD5A7824040081E3
+:105D6000AF4D00203C05080024A55A780E00023CE7
+:105D7000A36A00348F90001C240200090A00036209
+:105D8000AF82002802B288213225FFFF0E000236C2
+:105D9000240400840A0003628F90001C1082FFA478
+:105DA00024050400288B000311600170240C0004FA
+:105DB000240300015483FF9E240540000A00043B95
+:105DC000240501003C04080024845A788F62004CAA
+:105DD0000E00028D8F6300508F90001C0000202168
+:105DE0000A000362AF8400288E1000042404008A95
+:105DF000AF50002093790005333800021700015F8F
+:105E0000020028219368002302002821311F00206E
+:105E100017E0015A2404008D9367003F2406001206
+:105E200030E200FF10460155240400810E000256A6
+:105E30000200202193630023240500040200202196
+:105E4000346B0042A36B00230E00025FA365007D4C
+:105E50008F4401780480FFFE240A0002AF50014005
+:105E6000A34A01448F90001C3C0C1000AF4C0178F9
+:105E70000A0003EC0011102B8E1000042404008A89
+:105E8000AF500020936E000531CD000215A0001622
+:105E900002002821936F003F2414000402002821EF
+:105EA00031E900FF11340010240400810E00025675
+:105EB000020020219362002324080012241FFFFE09
+:105EC00034460020A3660023A368003F93790005B1
+:105ED00002002021033FC0240E00025FA3780005CA
+:105EE00002002821000020210E00033400000000E1
+:105EF0000A0003EB8F90001C8E1000043C03000886
+:105F00000343A021AF500020928B000024050050D5
+:105F1000316400FF10850161240700880200202100
+:105F2000000028210E00022A2406000E928D000097
+:105F3000240EFF800200282101AE8025A2900000DF
+:105F4000240400040E000C5C240600300A0003EB5D
+:105F50008F90001C8E0800043C14080026945A7888
+:105F60003C010800AC285A78AF480020921F00037B
+:105F700033F9000413200002240200122402000658
+:105F8000A362003F920B001B2404FFC03165003F59
+:105F900000A43825A367003E9206000330C200012A
+:105FA00014400132000000008E020008AE8200089A
+:105FB0003C0208008C425A8010400131000249C264
+:105FC000A76900088E14000C240C0001240300149F
+:105FD000AF74002C8E0E0010AF6E0030960D0016C0
+:105FE000A76D0038960A0014A76A003AAF6C000C3F
+:105FF000A76C0010A76C0012A76C0014A76C001609
+:1060000012200136A3630034920F000331F0000226
+:106010002E1100018F90001C262200080A00036246
+:10602000AF8200288E0400043C0E0008034E30218D
+:10603000AF4400208E05000890CD0000240C0050D5
+:1060400031AA00FF114C00862407008824060009AD
+:106050000E00022A000000000A0003EB8F90001CD3
+:106060008E04001C0E00024100000000104000F4ED
+:10607000004050218F89001C240700890140202105
+:106080008D25001C240600010E00022A00000000DD
+:106090000A0003EB8F90001C960D00023C140800D0
+:1060A00026945A7831AA0004514000B83C10600090
+:1060B0008E0E001C3C010800AC2E5A78AF4E00201A
+:1060C000920700102408001430E200FF144800D6A4
+:1060D00000000000960B00023163000114600165AE
+:1060E000000000008E020004AE8200083C1408008C
+:1060F0008E945A801280015B000000008F7400743F
+:106100003C0380002404000102835825AF6B007417
+:10611000A3600005AF64000C3C0708008CE75A80C0
+:106120008F86001CA7640010000711C2A76400122C
+:10613000A7640014A7640016A76200088CC80008B2
+:1061400024040002AF68002C8CC5000CAF65003041
+:1061500090DF0010A37F00348F99001C9330001152
+:10616000A37000358F98001C930F0012A36F0036A8
+:106170008F89001C912E0013A36E00378F90001C96
+:10618000960D0014A76D0038960A0016A76A003A0B
+:106190008E0C0018AF6C00245620FDCCAF84002874
+:1061A0003C05080024A55A780E0002640000202156
+:1061B0008F90001C0A0004A7000020218E1000040C
+:1061C00024070081AF500020936900233134001070
+:1061D000128000170000000002002021000028218A
+:1061E0002406001F0E00022A000000000A0003EB34
+:1061F0008F90001C3C05080024A55A780E000287E9
+:10620000240400828F90001C000028210A000362F1
+:10621000AF8500283C0408008C845A780E0014E5F1
+:10622000000000008F90001C0A000482000018216A
+:106230000E00025602002021937800230200202144
+:10624000370F00100E00025FA36F002300003821FB
+:1062500002002021000028210A0005A82406001FB2
+:10626000920F000C31E90001112000030000000032
+:106270009618000EA4D8002C921F000C33F90002CF
+:1062800013200005000038218E0200149608001229
+:10629000ACC2001CA4C8001A0A0005432406000969
+:1062A0003C05080024A55A780E0002872404008BC0
+:1062B0008F90001C0011282B0A000362AF85002874
+:1062C000AF6000843C0A08008D4A5A783C0D0800F3
+:1062D0008DAD0050240CFF803C02000C014D1821B4
+:1062E000006C2024AF4400288E070014306B007F20
+:1062F000017A282100A2C821AF2700D88E060014F9
+:10630000AF9900D0AF2600DC8E080010251FFFFEDD
+:106310000A000408AF3F01083C0508008CA55A7824
+:106320003C1908008F39005024CCFFFE00B9C02171
+:1063300003047824AF4F00283C1408008E945A7848
+:106340003C0908008D2900500289702131CD007F61
+:1063500001BA502101478021AE0600D8AF9000D08D
+:10636000AE0000DC0A0003B1AE0C0108548CFE3014
+:10637000240540000A00043B240510000E00032EF3
+:10638000000000000A0003EB8F90001C8E0F442CCD
+:106390003C186C62370979703C010800AC205A78CF
+:1063A00015E9000824050140979F00349786002CCA
+:1063B0000280282103E6C82B132000112404009238
+:1063C000240501400E000C7A240400023C01080060
+:1063D000AC225A78AF4200203C0508008CA55A78C0
+:1063E00010A00005240400830E00084500000000F2
+:1063F00010400009240400833C05080024A55A78B5
+:106400000E000264000000008F90001C0011202B81
+:106410000A000362AF8400280E0008490000000053
+:106420000A00055F8F90001C0E00084D0000000060
+:106430003C05080024A55A780A00062F2404008B86
+:10644000240400040E000C7A240500301440002AB5
+:10645000004050218F89001C240700830140202127
+:106460008D25001C0A000551240600018E04000839
+:106470000E000241000000000A00051BAE82000869
+:106480003C05080024A55A780E00023C240400872D
+:106490008F90001C0A0005360011102B8F830038E6
+:1064A0008F8600301066FE9D000038213C070800F2
+:1064B00024E759FC000320C0008728218CAC000091
+:1064C00011900061246A00013143000F5466FFFA05
+:1064D000000320C00A0004F6000038213C05080033
+:1064E00024A55A780E000287240400828F90001C95
+:1064F0000A000536000010213C0B0008034B202148
+:106500002403005024070001AF420020A0830000B4
+:10651000A08700018F82001C90480004A08800180A
+:106520008F85001C90A60005A08600198F9F001C77
+:1065300093F90006A099001A8F90001C921800078A
+:10654000A098001B8F94001C928F0008A08F001C45
+:106550008F89001C912E0009A08E001D8F8D001CBC
+:1065600091AC000AA08C001E8F8B001C3C0C080014
+:10657000258C59FC9163000B3C0B0800256B59F8E6
+:10658000A083001F8F87001C90E8000CA0880020CB
+:106590008F82001C9045000D24024646A0850021F4
+:1065A0008F86001C90DF000EA09F00228F99001C98
+:1065B0009330000FA09000238F98001C93140010BC
+:1065C000A09400248F8F001C91E90011A089002560
+:1065D0008F89001C8F8E00308F900038952D00140D
+:1065E000000E18C025C80001A48D002895270016AC
+:1065F000006C3021006BC821A487002A9525001863
+:106600003108000FA485002CA482002E8D3F001CB1
+:10661000ACCA0000AF88003011100006AF3F000088
+:10662000000038218D25001C014020210A00055161
+:1066300024060001250C00013184000F00003821E0
+:106640000A0006B8AF8400383C07080024E759F870
+:106650000087302100003821ACA000000A0004F6B9
+:10666000ACC000003C05080024A55A780A00062F9B
+:10667000240400878E0400040E0002410000000084
+:106680000A00056AAE8200083084FFFF30C600FFB2
+:106690008F4201B80440FFFE00064400010430258B
+:1066A0003C07200000C720253C031000AF400180BC
+:1066B000AF450184AF44018803E00008AF4301B84F
+:1066C00027BDFFE8AFB00010AFBF00143C0760006B
+:1066D000240600021080000600A080210010102B6C
+:1066E0008FBF00148FB0001003E0000827BD001812
+:1066F0003C09600EAD2000348CE5201C8F82001C0C
+:106700002408FFFC00A81824ACE3201C0E0006D1CE
+:106710008C45000C0010102B8FBF00148FB00010A0
+:1067200003E0000827BD00183C02600E344701005A
+:1067300024090018274A040000000000000000009F
+:10674000000000003C06005034C30200AF44003893
+:10675000AF45003CAF430030014018218F4B000093
+:10676000316800201100FFFD2406007F2408FFFF90
+:106770008C6C000024C6FFFF24630004ACEC000016
+:1067800014C8FFFB24E70004000000000000000024
+:10679000000000003C0F0020AF4F00300000000060
+:1067A00024AD020001A5702B2529FFFF008E2021BA
+:1067B0001520FFE101A0282103E0000800000000EF
+:1067C00027BDFFE0AFB10014AFBF0018AFB000109D
+:1067D0003C05600E8CA20034008088211440000625
+:1067E0003C0460008C87201C2408FFFC00E8302457
+:1067F00034C30001AC83201C8F8B001C24090001D2
+:10680000ACA90034956900028D6500148D70000CF0
+:106810002D2400818D6700048D660008108000071C
+:106820008D6A00102D2C00041580000E30CE00075C
+:10683000312D000311A0000B000000002404008B88
+:10684000020028210E0006D1240600030011102B9F
+:106850008FBF00188FB100148FB0001003E0000844
+:1068600027BD002015C0FFF62404008B3C03002048
+:10687000AF4300300000000024020001AF8200148A
+:106880000000000000000000000000003C1F01505C
+:10689000013FC825253800033C0F600EAF47003884
+:1068A00000181882AF46003C35E8003CAF59003074
+:1068B000274704008F4400003086002010C0FFFDF1
+:1068C00000000000106000082466FFFF2403FFFFA3
+:1068D0008CEB000024C6FFFF24E70004AD0B000092
+:1068E00014C3FFFB250800043C08600EAD09003806
+:1068F0000000000000000000000000003C07002035
+:10690000AF470030000000000E0006F901402021D2
+:1069100002002821000020210E0006D124060003D9
+:106920000011102B8FBF00188FB100148FB0001012
+:1069300003E0000827BD002027BDFFE0AFB200182C
+:106940003092FFFFAFB10014AFBF001CAFB000101A
+:106950001640000D000088210A0007AA022010211D
+:1069600024050001508500278CE5000C0000000D77
+:10697000262300013071FFFF24E200200232382B71
+:1069800010E00019AF82001C8F8200141440001622
+:106990008F87001C3C0670003C0320008CE5000043
+:1069A00000A62024148300108F84003C00054402BC
+:1069B0003C09800000A980241480FFE9310600FF13
+:1069C0002CCA00095140FFEB262300010006688015
+:1069D0003C0E080025CE578C01AE60218D8B000047
+:1069E0000160000800000000022010218FBF001C81
+:1069F0008FB200188FB100148FB0001003E00008B0
+:106A000027BD00200E0006D1240400841600FFD804
+:106A10008F87001C0A00078BAF80003C90EF0002BC
+:106A200000002021240600090E0006D1000F2E00D0
+:106A30008F87001C0010102B0A00078BAF82003CD0
+:106A4000020028210E0006DF240400018F87001CAD
+:106A50000A00078BAF82003C020028210E0006DFEF
+:106A6000000020210A0007C38F87001C0E00071FAB
+:106A7000020020210A0007C38F87001C30B0FFFFEF
+:106A8000001019C08F5801B80700FFFE3C1F2004FA
+:106A90003C191000AF430180AF400184AF5F018813
+:106AA000AF5901B80A00078C262300013082FFFF8E
+:106AB00014400003000018210004240224030010E5
+:106AC000308500FF14A000053087000F2466000801
+:106AD0000004220230C300FF3087000F14E00005DD
+:106AE000308900032468000400042102310300FF00
+:106AF0003089000315200005388B0001246A00024C
+:106B000000042082314300FF388B00013164000112
+:106B100010800002246C0001318300FF03E00008B4
+:106B200000601021308BFFFF000B394230E600FF80
+:106B30003C09080025295978000640800109602198
+:106B40008D8700003164001F240A0001008A1804A8
+:106B500030A500FF00E3202514A000020003102749
+:106B600000E22024240F000100CF700401096821F5
+:106B7000000E282714800005ADA400008F86000CAD
+:106B800000A6102403E00008AF82000C8F88000CE0
+:106B900001C8102503E00008AF82000C3C06001F6E
+:106BA0003C0360003084FFFF34C5FF8024020020D6
+:106BB000AC602008AC60200CAC602010AC652014E8
+:106BC000AC642018AC62200000000000000000004F
+:106BD00003E000080000000027BDFFE82402FFFFDB
+:106BE000AFBF0010AF82000C000020213C0608005F
+:106BF00024C659782405FFFF248900010004408041
+:106C00003124FFFF010618212C87002014E0FFFA31
+:106C1000AC6500000E0008160000202124020001CF
+:106C20003C04600024050020AC822018AC852000C4
+:106C3000000000000000000000000000244A0001E5
+:106C40003142FFFF2C46040014C0FFF78FBF001035
+:106C500003E0000827BD00188F8300082C620400A1
+:106C600003E00008384200018F830008246200011D
+:106C700003E00008AF8200088F8300082462FFFF52
+:106C800003E00008AF82000827BDFFE0AFB10014A9
+:106C9000AFBF0018AFB000108F6B00303C06600033
+:106CA00000808821ACCB20088F6A002C3C02800039
+:106CB00024030008ACCA200C9769003A9768003892
+:106CC00000092C003107FFFF00A72025ACC42010CD
+:106CD000ACC22014ACC32000000000000000000083
+:106CE000000000003C0360008C6D200031AC000807
+:106CF0001580FFF9000000008C6E201405C00020F4
+:106D0000000000000E0007DA8F84000C00024080B3
+:106D10003C09080025295978010938218CE4000034
+:106D20000E0007DA00028140020220213090FFFFAE
+:106D3000020020210E0007F8000028213C0C8000F2
+:106D4000022C58253210FFFF3C116000240A00205D
+:106D5000AE2B2014AE302018AE2A20000000000018
+:106D60000000000000000000020010218FBF00188A
+:106D70008FB100148FB0001003E0000827BD002081
+:106D80008C6620143C02001F3443FF803C1FFFE848
+:106D900000C3C02437F9080003198021001079C20C
+:106DA0003C0C8000022C582531F0FFFF3C116000A4
+:106DB000240A0020AE2B2014AE302018AE2A20006A
+:106DC0000000000000000000000000000200102190
+:106DD0008FBF00188FB100148FB0001003E00008BF
+:106DE00027BD002027BDFFE8AFB000103402FFFF31
+:106DF0003090FFFFAFBF00141202000602002021F6
+:106E00000E00081600000000020020210E0007F806
+:106E1000240500018F8400088FBF00148FB000107C
+:106E20002483FFFF27BD001803E00008AF8300089C
+:106E3000000439C230E6003F00043B42000718401E
+:106E4000240210002CC4002024C8FFE0AF42002C14
+:106E5000246300011480000330A900FF00071840DC
+:106E6000310600FF0003608024080001019A5821C8
+:106E70003C0A000E00C82804016A382111200005D0
+:106E8000000530278CE900000125302503E00008CB
+:106E9000ACE600008CEE000001C6682403E00008A8
+:106EA000ACED000027BDFFE8AFBF0014AFB000108D
+:106EB0003C0460008C8508083403F00030A2F00028
+:106EC00050430006240200018C8708083404E000C7
+:106ED00030E6F00010C4001E24020002AF82004021
+:106EE0003C1060003C0A0200AE0A0814240910009D
+:106EF0003C08000E8E03440003482021AF49002CBB
+:106F0000240501200E000CC0000030218F830040BA
+:106F1000106000043C021691240B0001106B000E5F
+:106F20003C023D2C344F0090AE0F44088FBF00143C
+:106F30008FB000103C0C6000240E10003C0D0200CD
+:106F400027BD0018AD8E442003E00008AD8D081069
+:106F50000A0008E7AF8000403C0218DA344F009086
+:106F6000AE0F44088FBF00148FB000103C0C6000BF
+:106F7000240E10003C0D020027BD0018AD8E4420E9
+:106F800003E00008AD8D08100A0008BB24050001CD
+:106F90000A0008BB000028213C08080025085D8481
+:106FA0002404FFFF010018212402001E2442FFFFD9
+:106FB000AC6400000441FFFD246300043C070800AA
+:106FC00024E75E008CE5FFFC2404001C240600017D
+:106FD000308A001F0146480424840001000910275C
+:106FE0002C8300201460FFFA00A22824ACE5FFFCEB
+:106FF0003C05666634A4616E3C06080024C65EC08B
+:10700000AF840058AF88009C2404FFFF00C0182103
+:107010002402001F2442FFFFAC6400000441FFFD76
+:10702000246300043C0766663C05080024A55E80D6
+:10703000AF86004834E6616EAF8600982404FFFFF7
+:1070400000A018212402000F2442FFFFAC640000BE
+:107050000441FFFD246300043C0B66663C06080007
+:1070600024C65E003568616EAF8500A4AF880070ED
+:107070002404FFFF00C018212402001F2442FFFF48
+:10708000AC6400000441FFFD246300043C0D66660F
+:107090003C0A0800254A5F4035AC616EAF8600901F
+:1070A000AF8C005C2404FFFF014018212402000380
+:1070B0002442FFFFAC6400000441FFFD2463000490
+:1070C0003C09080025295F508D27FFFC2404000699
+:1070D000240500013099001F0325C0042484000109
+:1070E000001878272C8E002015C0FFFA00EF3824F6
+:1070F000AD27FFFC3C09666624030400240403DC7E
+:1071000024050200240600663522616E3C08080052
+:1071100025085A84AF820074AF830044AF83006CAB
+:10712000AF830050AF830084AF8A008CAF840064CB
+:10713000AF85004CAF860054AF840078AF85006007
+:10714000AF86008001001821240200022442FFFFC4
+:10715000AC6000000441FFFD24630004240400032C
+:107160002403000C3C0A0800254A5A90AF8A0068A4
+:107170000A00098E2405FFFF000418802484000102
+:10718000006858212C8700C014E0FFFBAD650000AB
+:107190003C0E666635CD616E240C17A024081800DD
+:1071A000AF8D0088AF8C009403E00008AF88007CAE
+:1071B0002484007F000421C200004021000030210F
+:1071C00000003821000028210A0009A5AF8400A092
+:1071D0001060000624E7000100C4302124A500014E
+:1071E0002CC20BF51440FFFA2CA300663C090800E2
+:1071F00025295F4001201821240200032442FFFFBB
+:10720000AC6000000441FFFD2463000410E0001A9C
+:1072100024E3FFFF0003294210A0000A0000202100
+:107220002406FFFF3C03080024635F402484000120
+:107230000085502BAC660000250800011540FFFBBF
+:107240002463000430E2001F10400008000868803A
+:10725000240C0001004C38040008588001692821E2
+:1072600024E6FFFF03E00008ACA6000001A94021CE
+:107270002409FFFFAD09000003E000080000000042
+:10728000AF4400283C04000C034420210005288260
+:107290000A000CC000003021000421803C03600083
+:1072A000AC6410080000000000052980AC65100CDB
+:1072B0000000000003E000088C62100C27BDFFE80E
+:1072C0000080282124040038AFBF00140E0009D527
+:1072D000AFB0001024040E00AF4400283C10000C96
+:1072E00003502021240500100E000CC000003021A6
+:1072F00003501021AC400000AC40000424040038CE
+:107300008FBF00148FB0001024053FFF27BD001869
+:107310000A0009D58C430000000421803C03600072
+:10732000AC641008000000008C62100C03E0000840
+:107330000002118227BDFFC8AFB400208F940068FF
+:10734000AFBE0030AFB7002CAFB600280000B821A8
+:107350000080B021241E00C0AFBF0034AFB50024B0
+:10736000AFB3001CAFB20018AFB10014AFB0001043
+:107370000A000A12AFA5003C504000018F9400683B
+:1073800027DEFFFF13C00028269400048E92000021
+:107390003C03080024635D801240FFF70283102B3A
+:1073A0003C04080024845A84028410230002A8C0EC
+:1073B000000098210A000A212411000100118840D0
+:1073C000122000260000000002B380210251282470
+:1073D0000200202110A0FFF9267300010E0009DE33
+:1073E000000000000016684032EC000101AC2021D2
+:1073F0000E0009D5020028218F89009426F700018C
+:107400008FA6003C3AEB0001316A00012528FFFFFE
+:107410000011382702CAB021AF88009416E6FFE7B2
+:1074200002479024AE92000002E010218FBF00348A
+:107430008FBE00308FB7002C8FB600288FB5002488
+:107440008FB400208FB3001C8FB200188FB10014CE
+:107450008FB0001003E0000827BD00383C0E080084
+:1074600025CE5D80028E102B0A000A0DAE92000020
+:1074700027BDFFD8AFB10014AFB00010AFBF0020E0
+:10748000AFB3001CAFB2001800A0882110A0001FED
+:10749000000480403C13080026735A840A000A5AEC
+:1074A0002412000112200019261000010E0009F517
+:1074B00002002021000231422444FFA0000618806F
+:1074C0003045001F2C8217A1007318212631FFFFC1
+:1074D0001040FFF400B230048C690000020020214B
+:1074E00024053FFF012640241500FFEE0126382524
+:1074F0000E0009D5AC6700008F8A009426100001A9
+:10750000254700011620FFE9AF8700948FBF0020B8
+:107510008FB3001C8FB200188FB100148FB0001011
+:1075200003E0000827BD00288F85009C00805821BB
+:107530000000402100004821240A001F3C0C0800E4
+:10754000258C5DFC3C0D080025AD5D848CA60000FB
+:1075500050C000140000402100AD1023000238C0CC
+:10756000240300010A000A930000202115000003F3
+:1075700000E410212448202400004821252900018E
+:10758000512B00132506DFDC106000062484000167
+:1075900000C3702415C0FFF5000318400A000A91CB
+:1075A0000000402110AC002624A300040060282124
+:1075B000254AFFFF1540FFE5AF85009C512B0004D5
+:1075C0002506DFDC0000402103E000080100102157
+:1075D0000006614230C5001F000C50803C070800C7
+:1075E00024E75D8424040001014730211120000FAD
+:1075F00000A420043C05080024A55E0014800005BA
+:107600002529FFFF24C6000410C50011000000005A
+:10761000240400018CCF00000004C0270004204097
+:1076200001F868241520FFF5ACCD00008F99007893
+:1076300001001021032B482303E00008AF890078E4
+:107640003C05080024A55D840A000A9B0000402137
+:107650003C06080024C65D840A000AB42404000124
+:10766000308800FF240200021102000A24030003F4
+:107670001103005C8F8900A4240400041104005F3E
+:1076800024050005110500670000182103E000082B
+:10769000006010218F8900483C0C0800258C5EC0DA
+:1076A0003C04080024845F40240300201060000F85
+:1076B00000005821240D0002240E00033C0F080096
+:1076C00025EF5EC08D27000014E0000B30F9FFFFAE
+:1076D000252900040124C02B53000001018048210A
+:1076E0002463FFFF5460FFF88D270000016018211C
+:1076F00003E0000800601021132000323C0500FF69
+:1077000030E200FF004030211040004200005021D4
+:1077100024050001000020210005C84000A6C02467
+:1077200017000003332500FF14A0FFFB2484000191
+:10773000012CC023001828C000AA6021008C502111
+:107740003144001F240C0001008C18040003102792
+:1077500000E23024110D0041AD260000110E004C56
+:10776000000A1840110D00368F87006C510E00562C
+:107770008F8C0060240D0004110D005A8F8E008440
+:10778000240E0005150EFFDA01601821240B1430B9
+:1077900011400006000018218F8400A0246300011E
+:1077A000006A402B1500FFFD016458218F8A00807C
+:1077B000AF89008C016018212549FFFF0A000AEB00
+:1077C000AF89008000E52024000736021080FFD03A
+:1077D000240A001800075402314600FF0A000AF389
+:1077E000240A00103C0C0800258C5E803C04080034
+:1077F00024845EC00A000ADA240300103C0C08004E
+:10780000258C5E003C04080024845E800A000AD9AE
+:107810008F89009000071A02306600FF0A000AF301
+:10782000240A00088F89008C3C0C0800258C5F40DE
+:107830003C04080024845F500A000ADA2403000490
+:10784000000A4080250B003024E6FFFF016018216C
+:10785000AF8900480A000AEBAF86006C000AC982B3
+:10786000001978803C07080024E75E8001E72021AA
+:10787000000A18428C8F00003079001F032C380456
+:107880000007C02701F860240A000B08AC8C000038
+:10789000000331420006288000AF28213062001F1B
+:1078A0008CB8000024630001004CC804000321428E
+:1078B000001938270004108003073024004F2021CE
+:1078C0000A000B4CACA60000000A68C025AB0032D1
+:1078D000258AFFFF01601821AF8900A40A000AEB86
+:1078E000AF8A0060254B1030AF89009001601821ED
+:1078F00025C9FFFF0A000AEBAF8900843086000724
+:107900002CC2000610400014000000000006408059
+:107910003C030800246357B0010338218CE40000C5
+:1079200000800008000000002409000310A9000ED8
+:1079300000000000240A000510AA000B000000004F
+:10794000240B000110AB0008000000008F8C00A089
+:1079500010AC00050000000003E00008000010214A
+:107960000A000A7900A020210A000AC700C02021CD
+:1079700027BDFFE8308400FF240300021083000BC2
+:10798000AFBF0010240600031086003A240800044C
+:1079900010880068240E0005108E007F2CAF143074
+:1079A0008FBF001003E0000827BD00182CA2003094
+:1079B0001440FFFC8FBF001024A5FFD0000531C28A
+:1079C000000668803C07080024E75EC001A730215C
+:1079D0008CC900000005288230AC001F240B000178
+:1079E000018B50048F840048012A4025ACC8000058
+:1079F0008C83000050600001AF8600488F98006CB7
+:107A000030AE000124A6FFFF270F000115C00002C1
+:107A1000AF8F006C24A600010006414200082080C0
+:107A2000008718218C79000030C2001F2406000155
+:107A30000046F804033F382410E0FFDA8FBF00103F
+:107A40000005C182001870803C0F080025EF5E80A1
+:107A500001CF48218D2B00000005684231A5001F91
+:107A600000A66004016C502527BD001803E0000843
+:107A7000AD2A00002CA7003014E0FFCA8FBF001011
+:107A800030B900071723FFC724A8FFCE00086A02F9
+:107A9000000D60803C0B0800256B5E80018B30215F
+:107AA0008CC40000000828C230AA001F240800016E
+:107AB000014848048F8200A400891825ACC3000047
+:107AC0008C5F000053E00001AF8600A40005704009
+:107AD000000E7942000F28803C04080024845EC018
+:107AE00000A418218C6B000025DF000131CD001FA0
+:107AF000001F514201A86004016C4825000A108053
+:107B0000AC690000004428218CA600008F9800601A
+:107B100033F9001F8FBF00100328380400C77825F1
+:107B2000270E000127BD0018ACAF000003E00008DD
+:107B3000AF8E006024A5EFD02CB804001300FF998D
+:107B40008FBF001000053142000658803C0A080033
+:107B5000254A5E00016A30218CC4000030A3001F5A
+:107B600024090001006910048F9900900082F82513
+:107B7000ACDF00008F27000050E00001AF860090CE
+:107B80008F8D00848FBF001027BD001825AC000129
+:107B900003E00008AF8C008415E0FF828FBF001067
+:107BA0008F8600A0000610400046F821001F21002B
+:107BB00003E4C8210019384024F8143000B8402BE1
+:107BC0001100FF788FBF001024A4EBD00E00021329
+:107BD00000C0282100027942000F70803C0D08008F
+:107BE00025AD5F4001CD20218C8B0000304C001F63
+:107BF00024060001018618048F89008C016350253A
+:107C0000AC8A00008D25000050A00001AF84008CDC
+:107C10008F9800808FBF001027BD00182708000133
+:107C200003E00008AF88008030A5000724030003AC
+:107C300010A3001028A2000414400008240700022A
+:107C40002403000410A300152408000510A8000F49
+:107C50008F8500A003E000080000000014A7FFFDCE
+:107C60000080282114C3FFFB240400020A000B8BB0
+:107C700000000000240900050080282110C9FFFB36
+:107C80002404000303E000080000000014C5FFF115
+:107C9000008028210A000B8B24040005240A00011F
+:107CA0000080282110CAFFF12404000403E000082A
+:107CB0000000000027BDFFE0AFB00010000581C24A
+:107CC0002603FFD024C5003F2C6223D024C6007FAA
+:107CD000AFB20018AFB10014AFBF001C309100FF6D
+:107CE000000691C2000529820200202110400008F0
+:107CF0002403FFFF0E000A4B0000000002002021B9
+:107D0000022028210E000C390240302100001821E9
+:107D10008FBF001C8FB200188FB100148FB00010FD
+:107D20000060102103E0000827BD002027BDFFD818
+:107D300024A2007FAFB3001CAFB20018000299C2AA
+:107D4000309200FF24A3003F02402021026028213E
+:107D5000AFB10014AFB00010AFBF00200E000B6E2B
+:107D60000003898200408021004020210220282138
+:107D700014400009000018218FBF00208FB3001CA1
+:107D80008FB200188FB100148FB000100060102166
+:107D900003E0000827BD00280E0009FC00000000D9
+:107DA00000402821020020211051FFF3001019C0CB
+:107DB0000E000A4B00000000020020210240282192
+:107DC0000E000C39026030218FBF00208FB3001CE1
+:107DD0008FB200188FB100148FB00010000018216E
+:107DE0000060102103E0000827BD00283084FFFF59
+:107DF00030A5FFFF1080000700001821308200012D
+:107E00001040000200042042006518211480FFFB8E
+:107E10000005284003E000080060102110C00007A2
+:107E2000000000008CA2000024C6FFFF24A500046F
+:107E3000AC82000014C0FFFB2484000403E00008AF
+:107E40000000000010A0000824A3FFFFAC86000083
+:107E500000000000000000002402FFFF2463FFFF79
+:107E60001462FFFA2484000403E00008000000000C
+:107E700030A5FFFF8F4201B80440FFFE3C076015AC
+:107E800000A730253C031000AF440180AF400184BF
+:107E9000AF46018803E00008AF4301B88F8500D0EA
+:107EA0002C864000008018218CA700840087102BAE
+:107EB00014400010000000008CA800842D06400033
+:107EC00050C0000F240340008CAA0084008A482B75
+:107ED000512000018CA3008400035A42000B208033
+:107EE0003C05080024A558000085182103E000087F
+:107EF0008C62000014C0FFF4000000002403400066
+:107F000000035A42000B20803C05080024A55800BD
+:107F10000085182103E000088C6200008F8300D0E8
+:107F2000906600D024C50001A06500D08F8500D0E8
+:107F3000906400D090A200D210440017000000000E
+:107F4000936C00788F8B00BC318A00FFA16A000C13
+:107F500025490001938700C4312200FF3048007F8B
+:107F60001107000B00026827A36200788F4E01788A
+:107F700005C0FFFE8F9900B0241800023C0F1000CE
+:107F8000AF590140A358014403E00008AF4F017806
+:107F90000A000D0931A20080A0A000D00A000CFF49
+:107FA000000000008F8700D027BDFFC8AFBF0030A2
+:107FB000AFB7002CAFB60028AFB50024AFB4002097
+:107FC000AFB3001CAFB20018AFB10014AFB00010D7
+:107FD00094E300E094E200E2104300D72405FFFFA1
+:107FE0003C047FFF3497FFFF2415FF800A000DF04B
+:107FF0003C16000E108A00D18FBF00308F9100B068
+:108000003C1808008F18005C001230C0001291402C
+:108010000311702101D57824AF4F002C94EC00E2BD
+:1080200031CD007F01BA5821318A7FFF0176482186
+:10803000000A804002091021945300003C08080007
+:108040008D0800580246C02132733FFF001319808B
+:10805000010320210224282130BF007F03FAC82118
+:1080600000B5A024AF54002C0336A0218E87001049
+:108070008E8F003003785821256D008800EF702323
+:10808000240C0002AE8E0010AF8D00ACA16C0088F5
+:10809000976A003C8E8400308F9100AC0E000CD6A5
+:1080A0003150FFFF00024B80020940253C02420094
+:1080B00001022025AE2400048E8300048F8D00ACC5
+:1080C0008E860000240E0008ADA3001CADA600188B
+:1080D000ADA0000CADA00010929F000A33F900FF84
+:1080E000A5B90014968500083C1F000CA5A5001634
+:1080F0009298000A331100FFA5B100209690000865
+:1081000024180005A5B00022ADA00024928F000B1A
+:108110002410C00031E700FFA5A70002A1AE0001B6
+:108120008E8C00308F8B00AC8F8400B0AD6C00085B
+:108130003C0A08008D4A005401444821013540247E
+:10814000AF4800283C0208008C4200540044302113
+:1081500030C3007F007AC821033F282102458821CF
+:10816000AF9100BCAF8500C0A23800008F8A00BC70
+:108170002403FFBF2418FFDF954F000201F03824CD
+:1081800000F37025A54E0002914D000231AC003F76
+:10819000358B0040A14B00028F8600BC8F8900D038
+:1081A000ACC000048D28007C3C098000ACC80008ED
+:1081B00090C4000D3082007FA0C2000D8F8500BCEE
+:1081C00090BF000D03E3C824A0B9000D8F9100BC3F
+:1081D0009233000D02789024A232000D8E9000346C
+:1081E0008F8B00BCAD7000108E87002C8E8F0030FE
+:1081F00000EF7023AD6E0014916D001831AC007F5C
+:10820000A16C00188F9F00BC8E8A00308FE8001888
+:10821000015720240109302400C41025AFE20018C2
+:108220009283000AA3E3001C969900088F8500BC86
+:108230008F9800D0A4B9001E8E9000308E8400303C
+:108240000E0002138F0500848F8500D0000291403C
+:108250000002990090AF00BC0253882100403021F9
+:1082600031E7000210E0000302118021000290803B
+:108270000212802190B900BC3327000410E00002F4
+:108280000006F880021F80218E9800308F8B00BC82
+:1082900024068000330F0003000F702331CD00034C
+:1082A000020D6021AD6C000494A400E294AA00E2E7
+:1082B00094B000E231497FFF2522000130537FFF57
+:1082C0000206182400734025A4A800E294A400E24A
+:1082D0003C1408008E94006030917FFF123400221D
+:1082E000000000000E000CF6000000008F8700D098
+:1082F0000000282194F300E094F000E21213000F34
+:108300008FBF003090E900D090E800D1313200FFFB
+:10831000310400FF0244302B14C0FF36264A00010E
+:1083200090EE00D2264B000131CD00FF008D602180
+:10833000158BFF338F9100B08FBF00308FB7002CAB
+:108340008FB600288FB500248FB400208FB3001C97
+:108350008FB200188FB100148FB0001000A0102150
+:1083600003E0000827BD003894A300E20066402423
+:10837000A4A800E290A400E290B900E2309100FFCE
+:108380000011A1C20014F827001F39C03332007F4A
+:10839000024730250A000DE8A0A600E23084FFFF66
+:1083A00030A5FFFFAF440018AF45001C03E00008F4
+:1083B0008F42001427BDFFB8AFB000208F9000D0CF
+:1083C0003084FFFFAFA40010AFBF0044AFBE004039
+:1083D000AFB7003CAFB60038AFB50034AFB4003033
+:1083E000AFB3002CAFB20028AFB10024A7A0001893
+:1083F000920600D1920500D030C400FF30A300FFE8
+:108400000064102B10400122AFA00014920900D08C
+:108410008FB50010312800FF0088382324F4FFFFB7
+:108420000014882B0015982B02339024524001260B
+:108430008FB40014961E0012961F00108FB7001004
+:1084400003DFC823001714000019C400000224032E
+:108450000018140302E2B02A52C00001004020219B
+:108460000284282B10A0000200801821028018210D
+:1084700000033C0000071C033064FFFF2C8600094A
+:1084800014C000020060B821241700088E0A0008FA
+:10849000001769808E09000C31ABFFFF3C0C001007
+:1084A000016C402527520400AF4A0038AF9200B853
+:1084B000AF49003CAF480030000000000000000061
+:1084C00000000000000000000000000000000000AC
+:1084D00000000000000000008F4F000031EE00207F
+:1084E00011C0FFFD0017982A027110240A000E83A4
+:1084F0000000B02155E001019258000131130080C5
+:10850000126001CF012020219655001232A5FFFFF5
+:108510000E000CCBA7B500188F9000D00291A023BD
+:1085200026CD00018F9100B8000DB4000016B403F1
+:108530002638004002D7582A0014882B2405000151
+:108540000300902101711024AF9800B8AFA500146A
+:10855000104001BC8F8900B03C0C08008D8C005489
+:10856000240BFF80921E00D001895021014B28244A
+:10857000921900D0AF4500288E4700103C08080033
+:108580008D0800583C1808008F18005430E33FFF56
+:108590000003218001043021012658212402FF809C
+:1085A0000162F824920C00D0AF5F002C92480000CA
+:1085B00033D100FF333500FF0309982100117140CA
+:1085C000001578C0326D007F01CF382101BA282113
+:1085D000318300FF3164007F3C0A000C00AA88212F
+:1085E0000367F02100033140009A10213108003F59
+:1085F0003C1F000E00D1C021005F982127D90088C0
+:108600002D150008AF9100C0AF9900ACAF9800BC29
+:10861000AF9300B412A0018A00008821240E00014B
+:10862000010E4004310D005D11A0FFB2310F0002B8
+:108630008E4A00283C0300803C04FFEFAE6A000035
+:108640008E450024A260000A3488FFFFAE65000456
+:108650009247002C3C1FFF9F37FEFFFFA267000CD4
+:108660008E62000C3C180040A267000B00433025CE
+:1086700000C8C824033E88240238A825AE75000C23
+:108680008E490004AE6000183C0F00FFAE69001474
+:108690008E4D002C35EEFFFF8F8B00B001AE6024B5
+:1086A000AE6C00108E470008A660000896450012C8
+:1086B000AE6700208E42000C30B03FFF00105180AA
+:1086C000AE6200248E5E0014014B182130A400011C
+:1086D000AE7E00288E590018000331C2000443808A
+:1086E000AE79002C8E51001C00C8F821A67F001C1A
+:1086F000AE710030965800028E550020A678001EFC
+:10870000AE75003492490033313000045600000544
+:10871000925000008F8C00D08D8B007CAE6B0030AF
+:10872000925000008F8F00BCA1F00000924E0033E9
+:1087300031CD000251A00007925E00018F8900BC7C
+:108740002418FF80913100000311A825A1350000F5
+:10875000925E00018F9900BC2409FFBF240BFFDF4C
+:10876000A33E00018F9500BC92B8000D3311007F2D
+:10877000A2B1000D8F8E00BC91D0000D02097824AB
+:10878000A1CF000D8F8800BC8E6D0014910A000DE2
+:108790002DAC0001000C2940014B382400E51825C0
+:1087A000A103000D964200128F8800BC8F8700D075
+:1087B000A50200028E45000490FF00BC30A4000317
+:1087C0000004302330DE000300BE102133F9000224
+:1087D00017200002244400342444003090E200BCFE
+:1087E00000A2302430DF000417E0000224830004DC
+:1087F000008018218F8F00AC24090002AD03000413
+:10880000A1E90000924E003F8F8D00ACA1AE0001A7
+:108810008F9500AC924C003F8E440004A6AC000241
+:10882000976B003C0E000CD63170FFFF00025380A6
+:10883000020A38253C05420000E51825AEA30004D5
+:108840008F8600AC8E480038ACC800188E440034C7
+:10885000ACC4001CACC0000CACC00010A4C0001420
+:10886000A4C00016A4C00020A4C00022ACC00024F4
+:108870008E6400145080000124040001ACC4000880
+:108880000E000CF6241100010A000E768F9000D025
+:10889000920F00D2920E00D08FB5001031EB00FF86
+:1088A00031CD00FF008D6023016C50212554FFFF66
+:1088B0000014882B0015982B023390241640FEDDFF
+:1088C000000000008FB400148FBF00448FBE004032
+:1088D0003A8200018FB7003C8FB600388FB5003464
+:1088E0008FB400308FB3002C8FB200288FB10024DA
+:1088F0008FB0002003E0000827BD0048331100209E
+:10890000122000EF24150001921E00BC241F00015C
+:108910000000A82133D900011320000DAFBF001CB7
+:108920008E4400148E0800840088102B144000022E
+:10893000008030218E0600848E03006400C3A82BC3
+:1089400016A0000200C020218E0400640080A8212F
+:108950008E4700148E05006400E5302B14C0000221
+:1089600000E020218E0400640095F02313C0000471
+:108970008FAC001C240A0002AFAA001C8FAC001CA4
+:10898000028C582B156000A8000018218E4F00386B
+:108990008E6D000C3C0E0080AE6F00008E4A0034DD
+:1089A0003C10FF9F01AE5825AE6A00049246003F7E
+:1089B000360CFFFF016C38243C0500203C03FFEF20
+:1089C000A266000B00E510253468FFFF8F8700B812
+:1089D0000048F8243C04000803E4C825AE79000CE4
+:1089E0008CF80014AE60001802BE7821AE78001436
+:1089F0008CF10018AE71001C8CE90008AE690024EF
+:108A00008CEE000CAE6F002CAE600028AE6E002025
+:108A1000A6600038A660003A8CED001401B58023F2
+:108A2000021E902312400011AE72001090EA003D29
+:108A30008E6500048E640000000A310000A6C82183
+:108A4000000010210326402B0082F82103E8C021FA
+:108A5000AE790004AE78000090F1003DA271000AEA
+:108A60008F8900B895320006A67200088F9800AC76
+:108A70002419000202A02021A31900009769003CDC
+:108A80008F9200AC0E000CD63131FFFF00027B80CC
+:108A90008F8500B8022F68253C0E420001AE80256C
+:108AA000AE5000048F8400AC8CAC0038AC8C001845
+:108AB0008CAB0034AC8B001CAC80000CAC80001084
+:108AC000A4800014A4800016A4800020A4800022AA
+:108AD000AC80002490A7003FA487000212A00135BB
+:108AE0002403000153C0000290A2003D90A2003E6A
+:108AF00024480001A08800018F9F00ACAFF500085A
+:108B00008F8300D024070034906600BC30C500027B
+:108B100050A00001240700308F9200B88F8A00BC5B
+:108B2000906D00BC924B00002412C00032A50003DF
+:108B3000A14B00008F8600B88F8800BC240200047F
+:108B400090C400010045182330790003A1040001FE
+:108B50008F8A00BC8F9F00B800F53821955800021D
+:108B600097E9001200F9382103128824312F3FFFC2
+:108B7000022F7025A54E00029150000231A800047A
+:108B8000320C003F358B0040A14B000212A00002C6
+:108B90008F8500BC00E838218F8E00D0ACA7000480
+:108BA000240BFFBF8DCD007C2EA400012403FFDF2A
+:108BB000ACAD000890B0000D00044140320C007FC5
+:108BC000A0AC000D8F8600BC90CA000D014B102494
+:108BD000A0C2000D8F8700BC90E5000D00A3F82413
+:108BE00003E8C825A0F9000D8F9100B88F8D00BC57
+:108BF0008E380020ADB800108E290024ADA90014D5
+:108C00008E2F0028ADAF00188E2E002C0E000CF613
+:108C1000ADAE001C8FB0001C240C0002120C00EE44
+:108C20008F9000D08FA3001C006088211460000288
+:108C30000060A8210000A02156A0FE390291A023C7
+:108C40000014882B8FA90010960700103C1E0020EE
+:108C50000136402302C750213112FFFFA60A00103F
+:108C6000AFB20010AF5E0030000000009617001099
+:108C7000961300121277008F000000008E05000C82
+:108C80008E0B00080016698000AD7021000DC7C36F
+:108C900001CDA82B0178782101F56021AE0E000CE2
+:108CA000AE0C00088FB300100013B82B02378024DD
+:108CB0001200FF048F9000D00A000E3C000000005C
+:108CC0008E4D0038A6600008240B0003AE6D000036
+:108CD0008E500034A260000A8F9800B8AE70000475
+:108CE0003C0500809311003FA26B000C8E6F000CBE
+:108CF0003C0EFF9FA271000B01E5102535CCFFFF54
+:108D00003C03FFEF8F9200B8004C30243464FFFF27
+:108D100000C4F824AE7F000C8E590014964800124F
+:108D20008F8A00B0AE7900108E490014AE60001832
+:108D3000AE600020AE690014AE6000248E470018BB
+:108D400031093FFF0009F180AE6700288E4D000811
+:108D500003CA802131180001AE6D00308E4F000C27
+:108D60008F8C00AC001089C200185B80022B282178
+:108D7000240E0002A665001CA6600036AE6F002C13
+:108D8000A18E00009763003C8F8A00AC3C04420037
+:108D90003062FFFF00443025AD4600048F9F00B8CD
+:108DA000240700012411C0008FF30038240600348A
+:108DB000AD5300188FF90034AD59001CAD40000CC4
+:108DC000AD400010A5400014A5400016A5400020AD
+:108DD000A5400022AD400024A5550002A147000196
+:108DE0008F9E00AC8F8800B88F9200BCAFD5000872
+:108DF000910D0000A24D00008F9000B88F8B00BC39
+:108E000092180001A17800018F8400BC94850002B3
+:108E100000B1782401E97025A48E0002908C000234
+:108E20003183003FA08300028F8300D08F8400BC79
+:108E3000906200BC305300025260000124060030F2
+:108E4000AC8600048C6F007C2403FFBF02A0882145
+:108E5000AC8F0008908E000D31CC007FA08C000DEF
+:108E60008F8600BC90C2000D00432024A0C4000DDA
+:108E70008F8900BC913F000D37F90020A139000D0A
+:108E80008F8800B88F9300BC8D070020AE6700105C
+:108E90008D0A0024AE6A00148D1E0028AE7E0018D4
+:108EA0008D12002C0E000CF6AE72001C0A00103D54
+:108EB0008F9000D0960E00148E03000431CCFFFF7B
+:108EC000000C10C000622021AF44003C8E1F000443
+:108ED0008F46003C03E6C8231B20003C0000000036
+:108EE0008E0F000025E200013C05001034B500089B
+:108EF000AF420038AF550030000000000000000015
+:108F00000000000000000000000000000000000061
+:108F100000000000000000008F580000330B00200C
+:108F20001160FFFD000000008F5304003C0D002085
+:108F3000AE1300088F570404AE17000CAF4D00307D
+:108F4000000000003C0608008CC600442416000106
+:108F500010D600BD00000000961F00123C0508005E
+:108F60008CA5004000BFC821A61900129609001464
+:108F700025270001A6070014960A00143144FFFFBC
+:108F80005486FF498FB30010A60000140E000E1681
+:108F900030A5FFFF3C0408008C84002496030012D7
+:108FA0000044102300623023A60600120A00105964
+:108FB0008FB30010A08300018F8200AC2404000155
+:108FC000AC4400080A000FF08F8300D08E0200002E
+:108FD0000A0010EA3C0500108F8200C08FA7001C19
+:108FE000921800D0920B00D0920E00D0331100FFE7
+:108FF000316900FF00117940000928C001E56021B6
+:1090000031C300FF036C50210003314000C2C8216E
+:10901000255F0088AF9F00ACAF9900BCA1470088D6
+:109020009768003C03C020218F9100AC0E000CD645
+:109030003110FFFF00026B80020DC0253C0442008E
+:109040008F8D00B803045825AE2B00048DA900387D
+:109050008F8B00AC0000882100118100AD690018E1
+:109060008DAF00343C087FFF3504FFFFAD6F001C5F
+:1090700091AC003E8D65001C8D660018000C190037
+:10908000000C770200A33821020E102500E3F82B14
+:1090900000C2C821033F5021AD67001CAD6A001813
+:1090A000AD60000CAD60001091B8003E24050005D5
+:1090B00003C45024A578001495A9000403C02021FE
+:1090C000A569001691AF003EA56F002095B1000480
+:1090D000A5710022AD60002491AE003FA56E000294
+:1090E00091B0003E91AC003D01901023244300015B
+:1090F000A16300018F8600AC8F9F00BCACDE00082E
+:10910000A3E500008F9000BC8F9900B82405FFBF35
+:1091100096070002973800120247782433093FFF70
+:1091200001E98825A6110002921200022418FFDF2F
+:10913000324E003F35CD0040A20D00028F8600BCAC
+:109140008F8C00D02412FFFFACC000048D8B007CFC
+:109150003C0C8000ACCB000890C2000D3043007F77
+:10916000A0C3000D8F8700BC90FF000D03E5C8244D
+:10917000A0F9000D8F9100BC9229000D01387824D0
+:10918000A22F000D8F9000BCAE120010AE1500147F
+:10919000920E00182415FF8002AE6825A20D00185B
+:1091A0008F8500BC8F8300B88CAB0018016C102435
+:1091B000004A3025ACA600189068003EA0A8001C0C
+:1091C0008F9F00B88F8700BC8F9800D097F900045C
+:1091D000A4F9001E0E0002138F0500848F8600D0B4
+:1091E000000279400002490090D200BC01E98821C8
+:1091F000004028213255000212A0000303D1202193
+:109200000002A8800095202190CD00BC31B200045E
+:109210001240000333DF0003000540800088202156
+:10922000240600048F9E00BC00DFC8233327000300
+:1092300000875021AFCA00040E000CF6A665003866
+:109240000A0010388F9000D0961E00123C080800CB
+:109250008D080024011E9021A61200120A00105948
+:109260008FB3001027BDFFE03C1808008F18005096
+:10927000AFB00010AFBF0018AFB10014AF8400B0A2
+:1092800093710074030478212410FF8031EE007F75
+:109290003225007F01F0582401DA68213C0C000AD5
+:1092A000A38500C401AC2821AF4B002494A9001071
+:1092B0009768000690A600620080382124020030E2
+:1092C0000109202330C300F0AF8500D010620019DF
+:1092D0003090FFFF90AE0062240DFFF0240A005092
+:1092E00001AE6024318B00FF116A002F00000000E6
+:1092F00016000007241F0C00AF5F00248FB100147C
+:109300008FBF00188FB0001003E0000827BD0020B9
+:109310000E000E1C02002021241F0C00AF5F002451
+:109320008FB100148FBF00188FB0001003E0000849
+:1093300027BD002094A200E094A400E290BF011396
+:10934000008218263079FFFF33E700C014E00009DF
+:109350002F31000116000038000000005620FFE603
+:10936000241F0C000E000D18000000000A0011ED73
+:10937000241F0C001620FFDE000000000E000D1858
+:10938000000000001440FFDC241F0C001600002227
+:109390008F8300D0906901133122003FA062011336
+:1093A0000A0011ED241F0C0094AF00D48F8600D466
+:1093B00000E02821240400050E000C5C31F0FFFFC2
+:1093C0001440000524030003979100E600001821D3
+:1093D0002625FFFFA78500E68F5801B80700FFFE8E
+:1093E0003C196013AF400180241F0C00AF50018472
+:1093F000007938253C101000AF4701888FB1001468
+:10940000AF5001B8AF5F00248FB000108FBF0018BD
+:1094100003E0000827BD00200E000E1C02002021E2
+:109420005040FFB5241F0C008F8300D090690113BA
+:109430000A0012163122003F0E000E1C02002021ED
+:109440001440FFAD241F0C00122000078F8300D0B2
+:10945000906801133106003F34C20040A06201133E
+:109460000A0011ED241F0C000E000D180000000072
+:109470005040FFA1241F0C008F8300D0906801137F
+:109480003106003F0A00124634C20040AF9B00C8BC
+:1094900003E00008AF8000EC3089FFFF0009404284
+:1094A0002D020041000929801440000200095040AB
+:1094B00024080040000879400008C0C001F8582185
+:1094C000256701A800EF702125CC007F240DFF80C7
+:1094D000018D18240065302100CA282125640088E8
+:1094E000240A00883C010800AC2A004C3C0108001A
+:1094F000AC240050AF8500D43C010800AC290060CA
+:109500003C010800AC2800643C010800AC27005472
+:109510003C010800AC2300583C010800AC26005C6C
+:1095200003E0000800000000308300FF30C6FFFFAA
+:1095300030E400FF8F4201B80440FFFE00034C00FE
+:10954000012438253C08600000E820253C03100079
+:10955000AF450180AF460184AF44018803E00008B5
+:10956000AF4301B88F86001C3C09601235270010FC
+:109570008CCB00043C0C600E35850010316A00066F
+:109580002D480001ACE800C48CC40004ACA43180B8
+:109590008CC2000894C30002ACA2318403E000082E
+:1095A000A78300E43C0308008C6300508F8400E82C
+:1095B0008F86001C2402FF800064C0210302C8249F
+:1095C000AF5900288CCD00043305007F00BA782104
+:1095D0003C0E000C01EE2821ACAD00588CC80008F0
+:1095E000AF8500D03C076012ACA8005C8CCC0010AA
+:1095F00034E80010ACAC000C8CCB000CACAB000819
+:1096000094AA00143C0208008C4200442549000141
+:10961000A4A9001494A400143083FFFF1062001763
+:109620008F8400D03C0A08008D4A0040A4AA001292
+:109630008CCE0018AC8E00248CCD0014AC8D002094
+:109640008CC70018AC87002C8CCC001424060001B9
+:10965000AC8C00288D0B00BC5166001A8D0200B442
+:109660008D0200B8A482003A948F003AA48F003C87
+:10967000948800D403E000083102FFFF3C09080091
+:109680008D290024A4A000148F8400D0A4A9001266
+:109690008CCE0018AC8E00248CCD0014AC8D002034
+:1096A0008CC70018AC87002C8CCC00142406000159
+:1096B000AC8C00288D0B00BC5566FFEA8D0200B80B
+:1096C0008D0200B4A482003A948F003AA48F003C2B
+:1096D000948800D403E000083102FFFF8F86001C4D
+:1096E0003C0C08008D8C0050240BFF808CCD0008B2
+:1096F0003C03000C000D51C0018A4021010B48249D
+:10970000AF8A00E8AF49002890C700073105007F05
+:1097100000BA10210043282130E4000410800039F1
+:10972000AF8500D090CF000731EE000811C000389F
+:10973000000000008CD9000C8CC400140324C02B42
+:1097400013000030000000008CC2000CACA20064CA
+:109750008CCD00182402FFF8ACAD00688CCC001052
+:10976000ACAC00808CCB000CACAB00848CCA001C71
+:10977000ACAA007C90A900BC01224024A0A800BC97
+:1097800090C300073067000810E000048F8500D008
+:1097900090AF00BC35EE0001A0AE00BC90D9000730
+:1097A00033380001130000088F8300D08F8700D06A
+:1097B0002404003490E800BC35030002A0E300BCA0
+:1097C0008F8300D0AC6400C090C90007312600022E
+:1097D00010C0000500000000906A00BC3542000483
+:1097E000A06200BC8F8300D09065011330AD003FB4
+:1097F000A06D01138F8C00D0958B00D403E000087E
+:109800003162FFFF8CC200140A0013020000000046
+:109810000A001303ACA0006427BDFFD8AFB000104E
+:109820008F90001CAFBF0024AFB40020AFB200186F
+:10983000AFB10014AFB3001C9613000E3C07600AD2
+:109840003C1460063264FFFF369300100E00125580
+:1098500034F404108F8400D43C11600E0E00099B78
+:1098600036310010920E00153C0708008CE70060AE
+:109870003C12601231CD000FA38D00F08E0E00045B
+:109880008E0D000896080012961F00109619001AF7
+:109890009618001E960F001C310CFFFF33EBFFFFE4
+:1098A000332AFFFF3309FFFF31E6FFFF3C010800C9
+:1098B000AC2B00403C010800AC2C00243C0108000B
+:1098C000AC2A0044AE293178AE26317C92020015D4
+:1098D0009603001636520010304400FF3065FFFF3B
+:1098E0003C0608008CC60064AE243188AE4500B446
+:1098F0009208001496190018241F0001011FC004CB
+:10990000332FFFFF3C0508008CA50058AE5800B867
+:10991000AE4F00BC920C0014AF8E00D8AF8D00DCAF
+:10992000318B00FFAE4B00C0920A0015AE670048B5
+:10993000AE66004C314900FFAE4900C8AE65007C00
+:109940003C0308008C6300503C0408008C84004CED
+:109950003C0808008D0800543C0208008C42005C62
+:109960008FBF0024AE6300808FB00010AE83007400
+:109970008FB3001CAE22319CAE4200DCAE2731A07A
+:10998000AE2631A4AE24318CAE233190AE28319472
+:10999000AE253198AE870050AE860054AE8500707B
+:1099A0008FB10014AE4700E0AE4600E4AE4400CCF8
+:1099B000AE4300D0AE4800D4AE4500D88FB40020EE
+:1099C0008FB2001803E0000827BD002827BDFFE084
+:1099D000AFB10014AFBF0018241100010E000845FC
+:1099E000AFB0001010510005978400E6978300CCBB
+:1099F0000083102B144000088F8500D42407000238
+:109A00008FBF00188FB100148FB0001000E010213C
+:109A100003E0000827BD00200E000C7A2404000596
+:109A2000AF8200E81040FFF6240700020E0008494C
+:109A30008F90001C979F00E68F9900E88F8D00C8DB
+:109A400027EF0001240E0050AF590020A78F00E639
+:109A5000A1AE00003C0C08008D8C00648F8600C80D
+:109A6000240A8000000C5E00ACCB0074A4C0000689
+:109A700094C9000A241FFF803C0D000C012AC02459
+:109A8000A4D8000A90C8000A24182000011F182535
+:109A9000A0C3000A8F8700C8A0E000788F8500C8A7
+:109AA00000003821A0A000833C0208008C42005036
+:109AB0008F8400E80044782101FFC824AF590028B2
+:109AC000960B000231EE007F01DA6021018D30211A
+:109AD000A4CB00D4960A0002AF8600D03C0E00044E
+:109AE00025492401A4C900E68E080004ACC800047E
+:109AF0008E030008ACC30000A4C00010A4C0001472
+:109B0000A0C000D08F8500D02403FFBFA0A000D14B
+:109B10003C0408008C8400648F8200D0A04400D2F2
+:109B20008E1F000C8F8A00D0978F00E4AD5F001C61
+:109B30008E19001024100030AD590018A5400030D7
+:109B4000A5510054A5510056A54F0016AD4E006812
+:109B5000AD580080AD580084914D006231AC000FCB
+:109B6000358B0010A14B00628F8600D090C9006336
+:109B70003128007FA0C800638F8400D02406FFFF37
+:109B80009085006300A31024A08200638F9100D011
+:109B900000E01021923F00BC37F90001A23900BC5F
+:109BA0008F8A00D0938F00F0AD580064AD5000C094
+:109BB000914E00D3000F690031CC000F018D582564
+:109BC000A14B00D38F8500D08F8900DCACA900E8C1
+:109BD0008F8800D88FBF00188FB100148FB000108D
+:109BE00027BD0020ACA800ECA4A600D6A4A000E0ED
+:109BF000A4A000E203E000080000000027BDFFE091
+:109C0000AFB000108F90001CAFB10014AFBF0018B0
+:109C10008E1900043C1808008F180050240FFF8094
+:109C2000001989C00238702131CD007F01CF602436
+:109C300001BA50213C0B000CAF4C0028014B4021D5
+:109C4000950900D4950400D68E0700043131FFFF3A
+:109C5000AF8800D00E000913000721C08E06000453
+:109C60008F8300C8000629C0AF4500209064003EE5
+:109C700030820040144000068F8400D0341FFFFF64
+:109C8000948300D63062FFFF145F000400000000E0
+:109C9000948400D60E0008A83084FFFF8E050004CF
+:109CA000022030218FBF00188FB100148FB0001038
+:109CB0002404002200003821000529C00A0012797E
+:109CC00027BD002027BDFFE0AFB100143091FFFF9A
+:109CD000AFB00010AFBF00181220001D000080219F
+:109CE0008F86001C8CC500002403000600053F027F
+:109CF0000005140230E4000714830015304500FF0E
+:109D00002CA800061100004D000558803C0C0800EE
+:109D1000258C57C8016C50218D4900000120000896
+:109D2000000000008F8E00EC240D000111CD0059C1
+:109D300000000000260B00013170FFFF24CA002044
+:109D40000211202B014030211480FFE6AF8A001C55
+:109D5000020010218FBF00188FB100148FB00010C7
+:109D600003E0000827BD0020938700CE14E00038F0
+:109D7000240400140E001335000000008F86001C20
+:109D8000240200010A00147CAF8200EC8F8900ECF1
+:109D9000240800021128003B24040013000028219D
+:109DA00000003021240700010E001279000000009D
+:109DB0000A00147C8F86001C8F8700EC24050002AB
+:109DC00014E5FFF6240400120E0012E60000000065
+:109DD0008F8500E800403021240400120E00127923
+:109DE000000038210A00147C8F86001C8F8300EC51
+:109DF000241F0003147FFFD0260B00010E001298D1
+:109E0000000000008F8500E800403021240200029D
+:109E10002404001000003821AF8200EC0E001279FB
+:109E2000000000000A00147C8F86001C8F8F00EC5D
+:109E30002406000211E6000B0000000024040010BC
+:109E400000002821000030210A0014992407000195
+:109E5000000028210E001279000030210A00147C35
+:109E60008F86001C0E0013A2000000001440001298
+:109E70008F99001C8F86001C240200030A00147CAA
+:109E8000AF8200EC0E00142E000000000A00147CCB
+:109E90008F86001C0E0012880000000024020002C1
+:109EA0002404001400002821000030210000382183
+:109EB0000A0014B6AF8200EC0040382124040010E0
+:109EC00097380002000028210E0012793306FFFFA8
+:109ED0000A00147C8F86001C8F8400C83C077FFF1B
+:109EE00034E6FFFF8C8500742402000100A61824CC
+:109EF000AC83007403E00008A082000510A00036C7
+:109F00002CA20080274A04003C0B00052409008095
+:109F1000104000072408008030A6000F00C5402133
+:109F20002D0300811460000200A048212408008055
+:109F3000AF4B0030000000000000000000000000F7
+:109F40001100000900003821014030218C8D0000F3
+:109F500024E7000400E8602BACCD0000248400045A
+:109F60001580FFFA24C60004000000000000000075
+:109F7000000000003C0E0006010E3825AF470030FF
+:109F80000000000000000000000000008F4F0000F3
+:109F900031E800101100FFFD000000008F42003C7E
+:109FA0008F43003C0049C8210323C02B1300000449
+:109FB000000000008F4C003825860001AF460038B5
+:109FC0008F47003C00A9282300E96821AF4D003CE1
+:109FD00014A0FFCE2CA2008003E0000800000000C7
+:109FE00027BDFFD03C020002AFB100143C11000CB1
+:109FF000AF450038AFB3001CAF46003C008098214D
+:10A00000AF42003024050088AF44002803512021CE
+:10A01000AFBF0028AFB50024AFB40020AFB2001826
+:10A020000E0014EEAFB000103C1F08008FFF004C74
+:10A030003C1808008F1800642410FF8003F3A82147
+:10A0400032B9007F02B078240018A0C0033A702112
+:10A050000018914001D12021AF4F00280E0014EECE
+:10A06000025428213C0D08008DAD0050240501202C
+:10A0700001B35821316C007F01705024019A4821AE
+:10A08000013120210E0014EEAF4A00283C080800E0
+:10A090008D0800543C0508008CA50064011338218C
+:10A0A00030E6007F00F0182400DA20210091202102
+:10A0B000AF4300280E0014EE000529403C020800C2
+:10A0C0008C4200583C1008008E1000601200001CEA
+:10A0D000005388212415FF800A0015713C14000CE0
+:10A0E0003226007F0235182400DA20210240282180
+:10A0F000AF430028009420210E0014EE2610FFC06C
+:10A100001200000F023288212E05004110A0FFF43A
+:10A11000241210003226007F00109180023518248E
+:10A1200000DA202102402821AF430028009420219A
+:10A130000E0014EE000080211600FFF30232882189
+:10A140003C0B08008D6B005C240AFF802405000294
+:10A1500001734021010A4824AF4900283C0408004B
+:10A16000948400623110007F021A88213C07000CA1
+:10A170000E000CAA0227982100402821026020210D
+:10A180008FBF00288FB500248FB400208FB3001C30
+:10A190008FB200188FB100148FB000100A0014EEB7
+:10A1A00027BD00308F83001C8C6200041040000328
+:10A1B0000000000003E00008000000008C640010B4
+:0CA1C0008C6500080A0015278C66000C56
+:04A1CC00000000008F
+:10A1D0000000001B0000000F0000000A0000000843
+:10A1E000000000060000000500000005000000045B
+:10A1F0000000000400000003000000030000000352
+:10A200000000000300000003000000020000000244
+:10A210000000000200000002000000020000000236
+:10A220000000000200000002000000020000000226
+:10A230000000000200000002000000020000000216
+:10A240000000000200000001000000010000000109
+:10A2500008000F2408000D6C08000FB808001060FB
+:10A2600008000F4C08000F8C0800119408000D889E
+:10A27000080011B808000DD8080015540800151C76
+:10A2800008000D8808000D8808000D88080012409D
+:10A290000800124008000D8808000D88080014E02E
+:10A2A00008000D8808000D8808000D8808000D883A
+:10A2B000080013B408000D8808000D8808000D88F8
+:10A2C00008000D8808000D8808000D8808000D881A
+:10A2D00008000D8808000D8808000D8808000D880A
+:10A2E00008000D8808000D8808000D8808000FACD4
+:10A2F00008000D8808000D880800167808000D88F1
+:10A3000008000D8808000D8808000D8808000D88D9
+:10A3100008000D8808000D8808000D8808000D88C9
+:10A3200008000D8808000D8808000D8808000D88B9
+:10A3300008000D8808000D8808000D8808000D88A9
+:10A340000800141008000D8808000D880800133458
+:10A35000080012A408001E2C08001EFC08001F1490
+:10A3600008001F2808001F3808001E2C08001E2C9B
+:10A3700008001E2C08001ED808002E1408002E1CF1
+:10A3800008002DE408002DF008002DFC08002E0820
+:10A39000080052E8080052A8080052740800524809
+:08A3A00008005224080051E0FE
+:08A3A8000A000C840000000013
+:10A3B000000000000000000D727870362E302E3143
+:10A3C0003500000006000F0300000000000000013F
+:10A3D000000000000000000000000000000000007D
+:10A3E000000000000000000000000000000000006D
+:10A3F000000000000000000000000000000000005D
+:10A40000000000000000000000000000000000004C
+:10A41000000000000000000000000000000000003C
+:10A42000000000000000000000000000000000002C
+:10A43000000000000000000000000000000000001C
+:10A44000000000000000000000000000000000000C
+:10A4500000000000000000000000000000000000FC
+:10A4600000000000000000000000000000000000EC
+:10A4700000000000000000000000000000000000DC
+:10A4800000000000000000000000000000000000CC
+:10A4900000000000000000000000000000000000BC
+:10A4A00000000000000000000000000000000000AC
+:10A4B000000000000000000000000000000000009C
+:10A4C000000000000000000000000000000000008C
+:10A4D000000000000000000000000000000000007C
+:10A4E000000000000000000000000000000000006C
+:10A4F000000000000000000000000000000000005C
+:10A50000000000000000000000000000000000004B
+:10A51000000000000000000000000000000000003B
+:10A52000000000000000000000000000000000002B
+:10A53000000000000000000000000000000000001B
+:10A54000000000000000000000000000000000000B
+:10A5500000000000000000000000000000000000FB
+:10A5600000000000000000000000000000000000EB
+:10A5700000000000000000000000000000000000DB
+:10A5800000000000000000000000000000000000CB
+:10A5900000000000000000000000000000000000BB
+:10A5A00000000000000000000000000000000000AB
+:10A5B000000000000000000000000000000000009B
+:10A5C000000000000000000000000000000000008B
+:10A5D000000000000000000000000000000000007B
+:10A5E000000000000000000000000000000000006B
+:10A5F000000000000000000000000000000000005B
+:10A60000000000000000000000000000000000004A
+:10A61000000000000000000000000000000000003A
+:10A62000000000000000000000000000000000002A
+:10A63000000000000000000000000000000000001A
+:10A64000000000000000000000000000000000000A
+:10A6500000000000000000000000000000000000FA
+:10A6600000000000000000000000000000000000EA
+:10A6700000000000000000000000000000000000DA
+:10A6800000000000000000000000000000000000CA
+:10A6900000000000000000000000000000000000BA
+:10A6A00000000000000000000000000000000000AA
+:10A6B000000000000000000000000000000000009A
+:10A6C000000000000000000000000000000000008A
+:10A6D000000000000000000000000000000000007A
+:10A6E000000000000000000000000000000000006A
+:10A6F000000000000000000000000000000000005A
+:10A700000000000000000000000000000000000049
+:10A710000000000000000000000000000000000039
+:10A720000000000000000000000000000000000029
+:10A730000000000000000000000000000000000019
+:10A740000000000000000000000000000000000009
+:10A7500000000000000000000000000000000000F9
+:10A7600000000000000000000000000000000000E9
+:10A7700000000000000000000000000000000000D9
+:10A7800000000000000000000000000000000000C9
+:10A7900000000000000000000000000000000000B9
+:10A7A00000000000000000000000000000000000A9
+:10A7B0000000000000000000000000000000000099
+:10A7C0000000000000000000000000000000000089
+:10A7D0000000000000000000000000000000000079
+:10A7E0000000000000000000000000000000000069
+:10A7F0000000000000000000000000000000000059
+:10A800000000000000000000000000000000000048
+:10A810000000000000000000000000000000000038
+:10A820000000000000000000000000000000000028
+:10A830000000000000000000000000000000000018
+:10A840000000000000000000000000000000000008
+:10A8500000000000000000000000000000000000F8
+:10A8600000000000000000000000000000000000E8
+:10A8700000000000000000000000000000000000D8
+:10A8800000000000000000000000000000000000C8
+:10A8900000000000000000000000000000000000B8
+:10A8A00000000000000000000000000000000000A8
+:10A8B0000000000000000000000000000000000098
+:10A8C0000000000000000000000000000000000088
+:10A8D0000000000000000000000000000000000078
+:10A8E0000000000000000000000000000000000068
+:10A8F0000000000000000000000000000000000058
+:10A900000000000000000000000000000000000047
+:10A910000000000000000000000000000000000037
+:10A920000000000000000000000000000000000027
+:10A930000000000000000000000000000000000017
+:10A940000000000000000000000000000000000007
+:10A9500000000000000000000000000000000000F7
+:10A9600000000000000000000000000000000000E7
+:10A9700000000000000000000000000000000000D7
+:10A9800000000000000000000000000000000000C7
+:10A9900000000000000000000000000000000000B7
+:10A9A00000000000000000000000000000000000A7
+:10A9B0000000000000000000000000000000000097
+:10A9C0000000000000000000000000000000000087
+:10A9D0000000000000000000000000000000000077
+:10A9E0000000000000000000000000000000000067
+:10A9F0000000000000000000000000000000000057
+:10AA00000000000000000000000000000000000046
+:10AA10000000000000000000000000000000000036
+:10AA20000000000000000000000000000000000026
+:10AA30000000000000000000000000000000000016
+:10AA40000000000000000000000000000000000006
+:10AA500000000000000000000000000000000000F6
+:10AA600000000000000000000000000000000000E6
+:10AA700000000000000000000000000000000000D6
+:10AA800000000000000000000000000000000000C6
+:10AA900000000000000000000000000000000000B6
+:10AAA00000000000000000000000000000000000A6
+:10AAB0000000000000000000000000000000000096
+:10AAC0000000000000000000000000000000000086
+:10AAD0000000000000000000000000000000000076
+:10AAE0000000000000000000000000000000000066
+:10AAF0000000000000000000000000000000000056
+:10AB00000000000000000000000000000000000045
+:10AB10000000000000000000000000000000000035
+:10AB20000000000000000000000000000000000025
+:10AB30000000000000000000000000000000000015
+:10AB40000000000000000000000000000000000005
+:10AB500000000000000000000000000000000000F5
+:10AB600000000000000000000000000000000000E5
+:10AB700000000000000000000000000000000000D5
+:10AB800000000000000000000000000000000000C5
+:10AB900000000000000000000000000000000000B5
+:10ABA00000000000000000000000000000000000A5
+:10ABB0000000000000000000000000000000000095
+:10ABC0000000000000000000000000000000000085
+:10ABD0000000000000000000000000000000000075
+:10ABE0000000000000000000000000000000000065
+:10ABF0000000000000000000000000000000000055
+:10AC00000000000000000000000000000000000044
+:10AC10000000000000000000000000000000000034
+:10AC20000000000000000000000000000000000024
+:10AC30000000000000000000000000000000000014
+:10AC40000000000000000000000000000000000004
+:10AC500000000000000000000000000000000000F4
+:10AC600000000000000000000000000000000000E4
+:10AC700000000000000000000000000000000000D4
+:10AC800000000000000000000000000000000000C4
+:10AC900000000000000000000000000000000000B4
+:10ACA00000000000000000000000000000000000A4
+:10ACB0000000000000000000000000000000000094
+:10ACC0000000000000000000000000000000000084
+:10ACD0000000000000000000000000000000000074
+:10ACE0000000000000000000000000000000000064
+:10ACF0000000000000000000000000000000000054
+:10AD00000000000000000000000000000000000043
+:10AD10000000000000000000000000000000000033
+:10AD20000000000000000000000000000000000023
+:10AD30000000000000000000000000000000000013
+:10AD40000000000000000000000000000000000003
+:10AD500000000000000000000000000000000000F3
+:10AD600000000000000000000000000000000000E3
+:10AD700000000000000000000000000000000000D3
+:10AD800000000000000000000000000000000000C3
+:10AD900000000000000000000000000000000000B3
+:10ADA00000000000000000000000000000000000A3
+:10ADB0000000000000000000000000000000000093
+:10ADC0000000000000000000000000000000000083
+:10ADD0000000000000000000000000000000000073
+:10ADE0000000000000000000000000000000000063
+:10ADF0000000000000000000000000000000000053
+:10AE00000000000000000000000000000000000042
+:10AE10000000000000000000000000000000000032
+:10AE20000000000000000000000000000000000022
+:10AE30000000000000000000000000000000000012
+:10AE40000000000000000000000000000000000002
+:10AE500000000000000000000000000000000000F2
+:10AE600000000000000000000000000000000000E2
+:10AE700000000000000000000000000000000000D2
+:10AE800000000000000000000000000000000000C2
+:10AE900000000000000000000000000000000000B2
+:10AEA00000000000000000000000000000000000A2
+:10AEB0000000000000000000000000000000000092
+:10AEC0000000000000000000000000000000000082
+:10AED0000000000000000000000000000000000072
+:10AEE0000000000000000000000000000000000062
+:10AEF0000000000000000000000000000000000052
+:10AF00000000000000000000000000000000000041
+:10AF10000000000000000000000000000000000031
+:10AF20000000000000000000000000000000000021
+:10AF30000000000000000000000000000000000011
+:10AF40000000000000000000000000000000000001
+:10AF500000000000000000000000000000000000F1
+:10AF600000000000000000000000000000000000E1
+:10AF700000000000000000000000000000000000D1
+:10AF800000000000000000000000000000000000C1
+:10AF900000000000000000000000000000000000B1
+:10AFA00000000000000000000000000000000000A1
+:10AFB0000000000000000000000000000000000091
+:10AFC0000000000000000000000000000000000081
+:10AFD0000000000000000000000000000000000071
+:10AFE0000000000000000000000000000000000061
+:10AFF0000000000000000000000000000000000051
+:10B000000000000000000000000000000000000040
+:10B010000000000000000000000000000000000030
+:10B020000000000000000000000000000000000020
+:10B030000000000000000000000000000000000010
+:10B040000000000000000000000000000000000000
+: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
+:10D58000000000000000000000000080000000001B
+:10D59000000000000000000000000000000000008B
+:10D5A0000000000000000000000000000000000A71
+:10D5B0000000000000000000000000001000000358
+:10D5C000000000000000000D0000000D3C020800FB
+:10D5D000244273203C030800246377ACAC40000075
+:10D5E0000043202B1480FFFD244200043C1D080052
+:10D5F00037BD7FFC03A0F0213C100800261032103C
+:10D600003C1C0800279C73200E0010FE0000000048
+:10D610000000000D30A5FFFF30C600FF274301804A
+:10D620008F4201B80440FFFE24020002AC640000F7
+:10D63000A4650008A066000AA062000B3C0210006E
+:10D64000AC67001803E00008AF4201B83C0360007B
+:10D650008C624FF80440FFFE3C020200AC644FC0F5
+:10D66000AC624FC43C02100003E00008AC624FF80B
+:10D670009482000C2486001400A0382100021302BA
+:10D68000000210800082402100C8102B104000577B
+:10D690000000000090C300002C62000950400051BF
+:10D6A00090C20001000310803C030800246372D084
+:10D6B000004310218C4200000040000800000000E0
+:10D6C00090C300012402000A1462003A0000000026
+:10D6D000010610232C42000A1440003624C6000222
+:10D6E0008CE2000034420100ACE2000090C2000075
+:10D6F00090C3000190C4000290C5000300031C0009
+:10D7000000021600004310250004220000441025EA
+:10D710000045102524C60004ACE2000490C20000BD
+:10D7200090C3000190C4000290C5000300021600DF
+:10D7300000031C00004310250004220000441025B3
+:10D740000045102524C600040A000CB8ACE200080D
+:10D7500090C30001240200041462001624C60002D3
+:10D7600090C2000090C400018CE30000000212008F
+:10D77000004410253463000424C60002ACE2000C0F
+:10D780000A000CB8ACE3000090C3000124020003BF
+:10D790001462000824C600028CE2000090C300005E
+:10D7A00024C6000134420008A0E300100A000CB8AF
+:10D7B000ACE2000003E000082402000190C3000175
+:10D7C000240200021062000224C400020100202191
+:10D7D0000A000CB8008030210A000CB824C60001F1
+:10D7E00090C200010A000CB800C2302103E000081A
+:10D7F0000000102127BDFFE8AFBF0014AFB000103C
+:10D800000E00130200808021936200052403FFFEB6
+:10D8100002002021004310248FBF00148FB000109D
+:10D82000A36200050A00130B27BD001827BDFFE8FF
+:10D83000AFB00010AFBF00140E000F3C008080217D
+:10D840009362000024030050304200FF14430004A0
+:10D8500024020100AF4201800A000D3002002021A5
+:10D86000AF400180020020218FBF00148FB0001054
+:10D870000A000FE727BD001827BDFF80AFBE007864
+:10D88000AFB70074AFB20060AFBF007CAFB600703E
+:10D89000AFB5006CAFB40068AFB30064AFB1005C6B
+:10D8A000AFB000588F5001283C0208008C4231A0D4
+:10D8B0002403FF809365003F0202102100431024DF
+:10D8C000AF4200243C0208008C4231A09364000562
+:10D8D00030B200FF020210213042007F03421821C3
+:10D8E000000420273C02000A006218213084000155
+:10D8F000AF8300140000F0210000B8211480005311
+:10D90000AFA0005093430116934401128F450104C8
+:10D91000306300FF3C020001308400FF00A2282495
+:10D92000034310210344182124564000246740007B
+:10D9300014A001CD2402000193620000304300FFD7
+:10D94000240200201062000524020050106200062C
+:10D95000000000000A000D74000000000000000D2F
+:10D960000A000D7DAFA000303C1E080027DE736C5E
+:10D970000A000D7DAFA000303C0208008C4200DCA4
+:10D98000244200013C010800AC2200DC0E00139F81
+:10D99000000000000A000F318FBF007C8F4201049D
+:10D9A0003C03002092D3000D004310240002202BE2
+:10D9B00000042140AFA400308F4301043C0200402A
+:10D9C0000062182414600002348500400080282181
+:10D9D00032620020AFA500301440000234A600805F
+:10D9E00000A0302110C0000BAFA6003093C5000886
+:10D9F0008F67004C0200202100052B0034A5008118
+:10DA000030A5F0810E000C9B30C600FF0A000F2EDF
+:10DA1000000000009362003E304200401040000FC2
+:10DA200024020004564200072402001202002021B2
+:10DA300000E028210E0013F702C030210A000F3148
+:10DA40008FBF007C16420005000000000E000D2173
+:10DA5000000020210A000F318FBF007C9743011A7C
+:10DA600096C4000E93620035326500043075FFFFE6
+:10DA700000442004AFA400548ED1000410A000156F
+:10DA80008ED400089362003E3042004010400007F0
+:10DA9000000000000E0013E0022020211040000DC5
+:10DAA000000000000A000F2E000000008F620044FA
+:10DAB000022210230440016A000000008F62004827
+:10DAC0000222102304410166240400160A000E21DC
+:10DAD0008FC200048F620048022210230440000815
+:10DAE000000000003C0208008C423100244200018A
+:10DAF0003C010800AC2231000A000F2300000000A6
+:10DB00008F62004002221023184000128F840014FC
+:10DB10003C0208008C423100327300FC0000A82156
+:10DB2000244200013C010800AC2231008F63004018
+:10DB30009482011C022318233042FFFF0043102A65
+:10DB4000504000102402000C8F6200400A000DF2C9
+:10DB5000022210239483011C9762003C0043102B87
+:10DB600010400006000000009482011C00551023A4
+:10DB7000A482011C0A000DF72402000CA480011CE1
+:10DB80002402000CAFA200308F620040005120231D
+:10DB90001880000D02A4102A144001260000000085
+:10DBA0001495000602A410233A62000130420001DD
+:10DBB000144001200000000002A410230224882148
+:10DBC0000A000E093055FFFF0000202132620002DA
+:10DBD0001040001A326200109362003E3042004052
+:10DBE000504000118FC200040E00130202002021D9
+:10DBF00024020018A362003F936200052403FFFE85
+:10DC000002002021004310240E00130BA362000524
+:10DC100024040039000028210E0013C9240600182E
+:10DC20000A000F3024020001240400170040F80904
+:10DC3000000000000A000F3024020001104001081B
+:10DC4000000000008F63004C8F620054028210239A
+:10DC50001C40010302831023044200010060A02144
+:10DC6000AFA40018AFB10010AFB50014934201206B
+:10DC70008F6500409763003C304200FF0342102153
+:10DC8000004410218FA400543063FFFF2442400061
+:10DC90000083182B8FA40030AFA20020AFA500286E
+:10DCA00000832025AFA40030AFA50024AFA0002C36
+:10DCB000AFB400349362003E30420008504000117F
+:10DCC0008FC2000002C0202127A500380E000CB230
+:10DCD000AFA000385440000B8FC200008FA2003864
+:10DCE00030420100504000078FC200008FA3003C6B
+:10DCF0008F6200600062102304430001AF63006084
+:10DD00008FC200000040F80927A400108FA2003045
+:10DD10003042000254400001327300FE9362003E24
+:10DD200030420040104000378FA200248F62005420
+:10DD30001682001A326200012402001412420010FE
+:10DD40002A42001510400006240200162402000C8E
+:10DD500012420007326200010A000E7D000000003E
+:10DD600012420005326200010A000E7D0000000030
+:10DD70000A000E782417000E0A000E7824170010EF
+:10DD80000A000E7C24170012936200232403FFBDB7
+:10DD900000431024A36200233262000110400019E6
+:10DDA0008FA200242402000C1242000E2A42000D11
+:10DDB000104000062402000E2402000A124200074E
+:10DDC0008FA200240A000E9524420001124200088E
+:10DDD0008FA200240A000E95244200010A000E932F
+:10DDE000241700082402000E16E200022417001671
+:10DDF000241700108FA2002424420001AFA20024A7
+:10DE00008FA200248FA300148F76004000431021BE
+:10DE1000AF6200408F8200149442011C1040000940
+:10DE2000000000008F6200488F6400409763003C50
+:10DE3000004410233063FFFF0043102A1040000805
+:10DE40008FA20054936400368F6300403402FFFCBD
+:10DE50000082100400621821AF6300488FA20054B2
+:10DE60008FA600300282902130C200081040000EC0
+:10DE7000000000008F6200581642000430C600FF08
+:10DE80009742011A5040000134C6001093C50008A3
+:10DE90008FA700340200202100052B0034A500804C
+:10DEA0000E000C9B30A5F0808F62004000561023BE
+:10DEB0001840001B8FA200183C0208008C423198C9
+:10DEC000304200101040000D2402000197620068EB
+:10DED0001440000A240200018F8200149442011CA5
+:10DEE0001440000624020001A76200689742007AED
+:10DEF000244200640A000EE9A7620012A762001221
+:10DF00000E001302020020219362007D2403000111
+:10DF100002002021344200010A000EE7AFA30050A6
+:10DF20001840000A000000000E0013020200202129
+:10DF30009362007D2403000102002021AFA3005062
+:10DF4000344200040E00130BA362007D9362003E76
+:10DF5000304200401440000C326200011040000AC0
+:10DF6000000000008F6300408FC2000424040018EA
+:10DF7000246300010040F809AF6300408FA2003025
+:10DF80000A000F30304200048F6200581052001017
+:10DF9000000000008F620018022210231C400008BD
+:10DFA000240400018F6200181622000900000000FE
+:10DFB0008F62001C02821023044000050000000054
+:10DFC000AF720058AFA40050AF710018AF74001CBE
+:10DFD00012E0000B8FA200500E001302020020215D
+:10DFE000A377003F0E00130B0200202102E0302136
+:10DFF000240400370E0013C9000028218FA200500E
+:10E0000010400003000000000E000CA902002021B7
+:10E0100012A00005000018218FA200303042000439
+:10E020005040001100601021240300010A000F304D
+:10E03000006010210E001302020020219362007D77
+:10E0400002002021344200040E00130BA362007D65
+:10E050000E000CA9020020210A000F30240200014A
+:10E06000AF400044240200018FBF007C8FBE0078C7
+:10E070008FB700748FB600708FB5006C8FB40068D6
+:10E080008FB300648FB200608FB1005C8FB0005816
+:10E0900003E0000827BD00808F4201B80440FFFE66
+:10E0A00024020800AF4201B803E0000800000000AD
+:10E0B0003C02000803421021944200483084FFFFD4
+:10E0C000248400123045FFFF10A0001700A4102B7D
+:10E0D0001040001624020003934201202403001A7A
+:10E0E000A343018B304200FF2446FFFE8F820000D5
+:10E0F00000A6182B3863000100021382004310248D
+:10E10000104000058F84000434820001A74601946A
+:10E1100003E00008AF8200042402FFFE0082102406
+:10E1200003E00008AF8200042402000303E00008BB
+:10E13000A342018B27BDFFE0AFB10014AFB00010C8
+:10E14000AFBF001830B0FFFF30D1FFFF8F4201B8E2
+:10E150000440FFFE00000000AF440180AF440020F7
+:10E160000E000F42020020218F8300008F840004E4
+:10E17000A750019AA750018EA74301908F830008F2
+:10E1800030828000AF4301A8A75101881040000EE3
+:10E190008F82000493420116304200FC24420004A6
+:10E1A000005A10218C4240003042FFFF144000060C
+:10E1B0008F8200043C02FFFF34427FFF0082102464
+:10E1C000AF8200048F8200042403BFFF00431024A9
+:10E1D000A74201A69743010C8F42010400031C00D3
+:10E1E0003042FFFF00621825AF4301AC3C02100033
+:10E1F000AF4201B88FBF00188FB100148FB000106C
+:10E2000003E0000827BD00208F47007093420112F1
+:10E210008F83000027BDFFF0304200FF00022882FC
+:10E2200030620100000030211040004324A40003AC
+:10E230003062400010400010306220000004108066
+:10E24000005A10218C43400024A4000400041080D4
+:10E25000AFA30000005A10218C424000AFA200047E
+:10E2600093420116304200FC005A10218C424000BB
+:10E270000A000FC0AFA200081040002F000030219C
+:10E2800000041080005A10218C43400024A4000494
+:10E2900000041080AFA30000005A10218C424000FF
+:10E2A000AFA00008AFA200048FA800080000302132
+:10E2B00000002021240A00083C090800252901004B
+:10E2C00003A41021148A000300042A001100000A8C
+:10E2D0000000000090420000248400012C83000C08
+:10E2E00000A2102100021080004910218C42000081
+:10E2F0001460FFF300C230263C0408008C84310413
+:10E300008F4200702C8300201060000900473823E2
+:10E310003C030800246331080004108000431021EE
+:10E3200024830001AC4700003C010800AC23310409
+:10E33000AF8600082406000100C0102103E0000899
+:10E3400027BD00103C0208008C42003827BDFFD0DA
+:10E35000AFB50024AFB40020AFB10014AFBF0028A8
+:10E36000AFB3001CAFB20018AFB00010000088219E
+:10E370003C15080026B50038144000022454FFFF65
+:10E380000000A0219742010E8F8400003042FFFF61
+:10E39000308340001060000A245200043C02002038
+:10E3A0000082102450400007308280008F820004D9
+:10E3B0002403BFFF008318240A0010103442100009
+:10E3C000308280001040000A3C02002000821024AD
+:10E3D000104000078F8200043C03FFFF34637FFF7F
+:10E3E0000083182434428000AF820004AF83000011
+:10E3F0000E000F980000000014400007000000000D
+:10E400009743011E9742011C3063FFFF0002140076
+:10E4100000621825AF8300089742010C8F4340002B
+:10E420003045FFFF3402FFFF1462000300000000CC
+:10E430000A001028241100208F42400030420100C1
+:10E4400054400001241100108F840000308210001D
+:10E450005040001436310001308200201440000B7F
+:10E460003C021000008210245040000E36310001A2
+:10E470003C030E003C020DFF008318243442FFFFD2
+:10E480000043102B50400007363100013C020800C9
+:10E490008C42002C244200013C010800AC22002CDC
+:10E4A000363100053C0608008CC6003454C00023F9
+:10E4B0008F8500008F820004304240005440001FCE
+:10E4C0008F8500003C021F01008210243C031000D5
+:10E4D0005443001A8F85000030A202001440001738
+:10E4E0008F8500003250FFFF363100028F4201B8A5
+:10E4F0000440FFFE00000000AF4001800200202128
+:10E500000E000F42AF4000208F8300042402BFFFA3
+:10E51000A750019A006218248F820000A750018E34
+:10E52000A7510188A74301A6A74201903C02100011
+:10E53000AF4201B80A0010F5000010213C021000A3
+:10E5400000A210241040003A0000000010C0000F8C
+:10E550000000000030A201001040000C3C0302004B
+:10E560003C020F0000A2102410430008000000002D
+:10E570008F8200080054102400551021904200049E
+:10E58000244200040A00109F000221C00000000085
+:10E59000000516023050000F3A0300022E4203EF2E
+:10E5A000384200012C6300010062182414600073DB
+:10E5B000240200013C0308008C6300D02E06000CEE
+:10E5C000386200012C42000100461024144000155E
+:10E5D000001021C02602FFFC2C4200045440001110
+:10E5E00000002021386200022C4200010046102465
+:10E5F00010400003000512420A00109F0000202175
+:10E600000010182B0043102450400006001021C0B9
+:10E61000000020213245FFFF0E000F633226FFFB72
+:10E62000001021C03245FFFF0A0010F2362600021A
+:10E630008F4240003C0308008C63002430420100FC
+:10E640001040004630620001322200043070000D9C
+:10E65000144000022413000424130002000512C217
+:10E66000384200012E4303EF3042000138630001BD
+:10E6700000431025104000033231FFFB2402FFFB52
+:10E680000202802410C000183202000130A20100F2
+:10E6900010400015320200013C020F0000A21024BD
+:10E6A0003C0302001043000F8F8200082403FFFE8A
+:10E6B00002038024005410240055102190420004CD
+:10E6C000023330252442000412000002000221C05F
+:10E6D0003226FFFF0E000F633245FFFF12000027B6
+:10E6E00000001021320200011040000D320200042F
+:10E6F0002402000112020002023330253226FFFFFD
+:10E70000000020210E000F633245FFFF2402FFFEB0
+:10E7100002028024120000190000102132020004BD
+:10E72000104000162402000124020004120200021C
+:10E73000023330253226FFFF3245FFFF0E000F6304
+:10E74000240401002402FFFB020280241200000BBB
+:10E75000000010210A0010F52402000110400007FB
+:10E76000000010213245FFFF362600020000202164
+:10E770000E000F6300000000000010218FBF002872
+:10E780008FB500248FB400208FB3001C8FB2001807
+:10E790008FB100148FB0001003E0000827BD0030D7
+:10E7A00027BDFFD0AFB000103C04600CAFBF002C01
+:10E7B000AFB60028AFB50024AFB40020AFB3001C43
+:10E7C000AFB20018AFB100148C8250002403FF7F59
+:10E7D0003C1A8000004310243442380CAC825000B4
+:10E7E000240200033C106000AF4200088E020808BB
+:10E7F0003C1B80083C010800AC2000203042FFF0A8
+:10E80000384200102C4200010E001B85AF82001818
+:10E810003C04FFFF3C020400348308063442000C31
+:10E82000AE021948AE03194C3C0560168E021980E1
+:10E830008CA300003442020000641824AE02198048
+:10E840003C0253531462000334A47C008CA20004E5
+:10E85000005020218C82007C8C830078AF820010D5
+:10E86000AF83000C8F55000032A200031040FFFD63
+:10E8700032A200011040013D32A200028F42012865
+:10E88000AF4200208F4201048F430100AF8200009D
+:10E890000E000F3CAF8300043C0208008C4200C015
+:10E8A000104000088F8400003C0208008C4200C425
+:10E8B000244200013C010800AC2200C40A00126995
+:10E8C000000000003C020010008210241440010CE3
+:10E8D0008F8300043C0208008C4200203C030800A7
+:10E8E0008C63003800008821244200013C010800AC
+:10E8F000AC2200203C16080026D600381460000226
+:10E900002474FFFF0000A0219742010E30834000D5
+:10E910003042FFFF1060000A245200043C02002035
+:10E920000082102450400007308280008F82000453
+:10E930002403BFFF008318240A0011703442100022
+:10E94000308280001040000A3C0200200082102427
+:10E95000104000078F8200043C03FFFF34637FFFF9
+:10E960000083182434428000AF820004AF8300008B
+:10E970000E000F9800000000144000070000000087
+:10E980009743011E9742011C3063FFFF00021400F1
+:10E9900000621825AF8300089742010C8F434000A6
+:10E9A0003045FFFF3402FFFF146200030000000047
+:10E9B0000A001188241100208F42400030420100DB
+:10E9C00054400001241100108F8400003082100098
+:10E9D0005040001436310001308200201440000BFA
+:10E9E0003C021000008210245040000E363100011D
+:10E9F0003C030E003C020DFF008318243442FFFF4D
+:10EA00000043102B50400007363100013C02080043
+:10EA10008C42002C244200013C010800AC22002C56
+:10EA2000363100053C0608008CC6003454C0002373
+:10EA30008F8500008F820004304240005440001F48
+:10EA40008F8500003C021F01008210243C0310004F
+:10EA50005443001A8F85000030A2020014400017B2
+:10EA60008F8500003250FFFF363100028F4201B81F
+:10EA70000440FFFE00000000AF40018002002021A2
+:10EA80000E000F42AF4000208F8300042402BFFF1E
+:10EA9000A750019A006218248F820000A750018EAF
+:10EAA000A7510188A74301A6A74201903C0210008C
+:10EAB000AF4201B80A001267000010213C021000AA
+:10EAC00000A210241040003A0000000010C0000F07
+:10EAD0000000000030A201001040000C3C030200C6
+:10EAE0003C020F0000A210241043000800000000A8
+:10EAF0008F82000800541024005610219042000418
+:10EB0000244200040A0011FF000221C0000000009E
+:10EB1000000516023050000F3A0300022E4203EFA8
+:10EB2000384200012C630001006218241460008543
+:10EB3000240200013C0308008C6300D02E06000C68
+:10EB4000386200012C4200010046102414400015D8
+:10EB5000001021C02602FFFC2C420004544000118A
+:10EB600000002021386200022C42000100461024DF
+:10EB700050400003000512420A0011FF000020214E
+:10EB80000010182B0043102450400006001021C034
+:10EB9000000020213245FFFF0E000F633226FFFBED
+:10EBA000001021C03245FFFF0A0012523626000233
+:10EBB0008F4240003C0308008C6300243042010077
+:10EBC0001040004630620001322200043070000D17
+:10EBD000144000022413000424130002000512C292
+:10EBE000384200012E4303EF304200013863000138
+:10EBF00000431025104000033231FFFB2402FFFBCD
+:10EC00000202802410C000183202000130A201006C
+:10EC100010400015320200013C020F0000A2102437
+:10EC20003C0302001043000F8F8200082403FFFE04
+:10EC30000203802400541024005610219042000446
+:10EC4000023330252442000412000002000221C0D9
+:10EC50003226FFFF0E000F633245FFFF120000391E
+:10EC600000001021320200011040000D32020004A9
+:10EC70002402000112020002023330253226FFFF77
+:10EC8000000020210E000F633245FFFF2402FFFE2B
+:10EC9000020280241200002B000010213202000426
+:10ECA0001040002824020001240200041202000285
+:10ECB000023330253226FFFF3245FFFF0E000F637F
+:10ECC000240401002402FFFB020280241200001D24
+:10ECD000000010210A0012672402000150400019B0
+:10ECE000000010213245FFFF3626000200002021DF
+:10ECF0000E000F63000000000A00126700001021E0
+:10ED00002402BFFF00621024104000080000000031
+:10ED1000240287FF00621024144000083C020060B7
+:10ED20000082102410400005000000000E000D3489
+:10ED3000000000000A001267000000000E0012C769
+:10ED400000000000104000063C0240008F430124F8
+:10ED50003C026020AC430014000000003C02400074
+:10ED6000AF4201380000000032A200021040FEBD98
+:10ED7000000000008F4201403C044000AF420020F0
+:10ED80008F4301483C027000006218241064004266
+:10ED9000000000000083102B144000063C026000BD
+:10EDA0003C022000106200073C0240000A0012C32F
+:10EDB000000000001062003C3C0240000A0012C348
+:10EDC000000000008F4501408F4601448F420148FA
+:10EDD00000021402304300FF240200041462000AFF
+:10EDE000274401808F4201B80440FFFE2402001C2A
+:10EDF000AC850000A082000B3C021000AF4201B8BD
+:10EE00000A0012C33C0240002402000914620012EE
+:10EE100000061602000229C0AF4500208F4201B84B
+:10EE20000440FFFE2402000124030003AF450180DB
+:10EE3000A343018BA740018EA740019AA7400190F0
+:10EE4000AF4001A8A7420188A74201A6AF4001AC8C
+:10EE50003C021000AF4201B88F4201B80440FFFEEF
+:10EE600000000000AC8500008F420148000214023F
+:10EE7000A482000824020002A082000B8F420148F5
+:10EE8000A48200103C021000AC860024AF4201B8FE
+:10EE90000A0012C33C0240000E00131000000000E4
+:10EEA0000A0012C33C0240000E001BBA0000000022
+:10EEB0003C024000AF420178000000000A00112F20
+:10EEC000000000008F4201003042003E144000115B
+:10EED00024020001AF4000488F420100304207C0C9
+:10EEE0001040000500000000AF40004CAF40005053
+:10EEF00003E0000824020001AF400054AF4000408E
+:10EF00008F4201003042380054400001AF400044BD
+:10EF10002402000103E00008000000008F4201B855
+:10EF20000440FFFE24020001AF440180AF40018491
+:10EF3000A7450188A342018A24020002A342018B53
+:10EF40009742014A14C00004A7420190AF4001A4B7
+:10EF50000A0012EF3C0210008F420144AF4201A4AC
+:10EF60003C021000AF4001A803E00008AF4201B826
+:10EF70008F4201B80440FFFE24020002AF4401802A
+:10EF8000AF440184A7450188A342018AA342018BB3
+:10EF90009742014AA7420190AF4001A48F42014429
+:10EFA000AF4201A83C02100003E00008AF4201B8E4
+:10EFB0003C0290003442000100822025AF44002032
+:10EFC0008F4200200440FFFE0000000003E0000824
+:10EFD000000000003C028000344200010082202535
+:10EFE00003E00008AF44002027BDFFE8AFBF0014D6
+:10EFF000AFB000108F500140934301499342014844
+:10F0000093440148306300FF304200FF00021200C9
+:10F0100000622825240200191062007630840080E6
+:10F020002862001A1040001C24020020240200085C
+:10F0300010620077286200091040000E2402000BC5
+:10F0400024020001106200342862000250400005D2
+:10F050002402000650600034020020210A00139AA6
+:10F060000000000010620030020020210A00139A04
+:10F07000000000001062003B2862000C50400002BB
+:10F080002402000E24020009106200560200202112
+:10F090000A00139A00000000106200562862002146
+:10F0A0001040000F240200382402001C1062005897
+:10F0B0002862001D104000062402001F2402001BCD
+:10F0C0001062004C000000000A00139A00000000CB
+:10F0D0001062004A020020210A00139A000000007A
+:10F0E00010620045286200391040000724020080A9
+:10F0F0002462FFCB2C420002104000450200202178
+:10F100000A00139600003021106200090000000080
+:10F110000A00139A000000001480003D0200202124
+:10F120000A0013908FBF00140A00139624060001F2
+:10F130008F4201B80440FFFE24020002A342018B6B
+:10F14000A74501889742014AA74201908F42014496
+:10F15000A74201923C021000AF4201B80A00139C82
+:10F160008FBF00149742014A14400029000000009C
+:10F1700093620005304200041440002500000000A6
+:10F180000E001302020020219362000502002021DC
+:10F19000344200040E00130BA362000593620005C5
+:10F1A0003042000414400002000000000000000D86
+:10F1B0009362000024030020304200FF1443001437
+:10F1C000000000008F4201B80440FFFE2402000549
+:10F1D000AF500180A342018B3C0210000A00139A39
+:10F1E000AF4201B88FBF00148FB000100A0012F2B6
+:10F1F00027BD00180000000D020020210000302172
+:10F200008FBF00148FB000100A0012DD27BD001858
+:10F210000000000D8FBF00148FB0001003E0000845
+:10F2200027BD001827BDFFE8AFBF00100E000F3C40
+:10F2300000000000AF4001808FBF001000002021BF
+:10F240000A000FE727BD00183084FFFF30A5FFFF3D
+:10F25000000018211080000700000000308200012B
+:10F260001040000200042042006518210A0013AB80
+:10F270000005284003E000080060102110C00006CF
+:10F2800024C6FFFF8CA2000024A50004AC8200006D
+:10F290000A0013B52484000403E000080000000005
+:10F2A00010A0000824A3FFFFAC86000000000000AF
+:10F2B000000000002402FFFF2463FFFF1462FFFA36
+:10F2C0002484000403E0000800000000308300FFF5
+:10F2D00030A500FF30C600FF274701808F4201B8EC
+:10F2E0000440FFFE000000008F420128346340000C
+:10F2F000ACE2000024020001ACE00004A4E300083A
+:10F30000A0E2000A24020002A0E2000B3C0210006E
+:10F31000A4E50010ACE00024ACE00028A4E6001254
+:10F3200003E00008AF4201B827BDFFE8AFBF0010FF
+:10F330009362003F24030012304200FF1043000D8F
+:10F34000008030218F620044008210230440000AB4
+:10F350008FBF00108F62004824040039000028216C
+:10F3600000C2102304410004240600120E0013C939
+:10F37000000000008FBF00102402000103E000081D
+:10F3800027BD001827BDFFC8AFB20030AFB1002CB9
+:10F39000AFBF0034AFB0002890C5000D00809021B1
+:10F3A00030A400101080000B00C088218CC300081E
+:10F3B0008F6200541062000730A20005144000B5AF
+:10F3C000240400010E000D21000020210A0014BBBE
+:10F3D0000040202130A200051040000930A3001297
+:10F3E000108000AC240400018E2300088F620054BA
+:10F3F000146200A98FBF00340A00142C24040038C2
+:10F4000024020012146200A324040001022020211F
+:10F4100027A500100E000CB2AFA000101040001184
+:10F42000024020218E220008AF620084AF600040BD
+:10F430000E001302000000009362007D02402021B4
+:10F44000344200200E00130BA362007D0E000CA9B5
+:10F4500002402021240400382405008D0A0014B83D
+:10F46000240600129362003E304200081040000F54
+:10F470008FA2001030420100104000078FA300143B
+:10F480008F6200600062102304430008AF630060D5
+:10F490000A00144100000000AF6000609362003E6B
+:10F4A0002403FFF700431024A362003E9362003E52
+:10F4B00030420008144000022406000300003021FE
+:10F4C00093620034936300378F640084304200FFFE
+:10F4D000306300FF006618210003188000432821D4
+:10F4E00000A4202B1080000B000000009763003C5C
+:10F4F0008F6200843063FFFF004510230062182BE9
+:10F5000014600004000000008F6200840A00145D93
+:10F51000004580239762003C3050FFFF8FA300100E
+:10F520003062000410400004000628808FA2001CF6
+:10F530000A0014650202102B2E020218504000032C
+:10F54000240202180A00146E02051023306300041E
+:10F5500010600003004510238FA2001C00451023FB
+:10F56000004080212C420080544000012410008083
+:10F570000E0013020240202124020001AF62000CA1
+:10F580009362003E001020403042007FA362003EA4
+:10F590008E22000424420001AF620040A770003CAC
+:10F5A0008F6200509623000E00431021AF62005876
+:10F5B0008F62005000441021AF62005C8E22000474
+:10F5C000AF6200188E220008AF62001C8FA20010EC
+:10F5D000304200085440000A93A20020A360003685
+:10F5E000936200362403FFDFA36200359362003E7E
+:10F5F00000431024A362003E0A0014988E220008E3
+:10F60000A36200358E220008AF62004C8F62002496
+:10F610008F63004000431021AF62004893620000F6
+:10F6200024030050304200FF144300122403FF80E3
+:10F630003C0208008C4231A00242102100431024F9
+:10F64000AF4200283C0208008C4231A08E24000802
+:10F650003C03000C024210213042007F0342102183
+:10F6600000431021AC4400D88E230008AF82001460
+:10F67000AC4300DC0E00130B0240202124040038B0
+:10F68000000028212406000A0E0013C90000000013
+:10F69000240400018FBF00348FB200308FB1002CE2
+:10F6A0008FB000280080102103E0000827BD00383B
+:10F6B00027BDFFF827420180AFA20000308A00FF7B
+:10F6C0008F4201B80440FFFE000000008F46012871
+:10F6D0003C0208008C4231A02403FF80AF86004822
+:10F6E00000C2102100431024AF4200243C02080055
+:10F6F0008C4231A08FA900008FA8000000C2102109
+:10F700003042007F034218213C02000A00621821A7
+:10F71000946400D48FA700008FA50000240200028B
+:10F72000AF830014A0A2000B8FA30000354260003D
+:10F730003084FFFFA4E200083C021000AD26000068
+:10F74000AD040004AC60002427BD0008AF4201B83E
+:10F7500003E00008240200018F88003C9382002807
+:10F760008F8300143C07080024E7777800481023B3
+:10F77000304200FF304900FC246500888F8600403D
+:10F78000304A0003112000090000202124820004D7
+:10F790008CA30000304400FF0089102AACE3000075
+:10F7A00024A500041440FFF924E7000411400009D7
+:10F7B000000020212482000190A30000304400FFBB
+:10F7C000008A102BA0E3000024A500011440FFF9DB
+:10F7D00024E7000130C20003144000048F85003C80
+:10F7E000310200031040000D0000000010A00009CD
+:10F7F000000020212482000190C30000304400FF5B
+:10F800000085102BA0E3000024C600011440FFF97E
+:10F8100024E7000103E00008000000001100FFFDE4
+:10F8200000002021248200048CC30000304400FF2B
+:10F830000088102BACE3000024C600041440FFF93C
+:10F8400024E7000403E00008000000008F83003C70
+:10F850009382002830C600FF30A500FF004310232C
+:10F86000304300FF8F8200140080382100431021B4
+:10F8700014C00002244800880083382130E20003CD
+:10F880001440000530A2000314400003306200035E
+:10F890001040000D0000000010A000090000202111
+:10F8A0002482000190E30000304400FF0085102B0B
+:10F8B000A103000024E700011440FFF9250800011E
+:10F8C00003E000080000000010A0FFFD0000202160
+:10F8D000248200048CE30000304400FF0085102BDC
+:10F8E000AD03000024E700041440FFF925080004DC
+:10F8F00003E00008000000000080482130AAFFFF5C
+:10F9000030C600FF30E7FFFF274801808F4201B873
+:10F910000440FFFE8F820048AD0200008F420124A8
+:10F92000AD0200048D220020A5070008A102000AF4
+:10F9300024020016A102000B934301208D2200082F
+:10F940008D240004306300FF004310219783003AA8
+:10F95000004410218D250024004310233C0308009F
+:10F960008C6331A08F840014A502000C246300E88E
+:10F970002402FFFFA50A000EA5030010A506001231
+:10F98000AD050018AD020024948201142403FFF792
+:10F990003042FFFFAD0200288C820118AD02002C1E
+:10F9A0003C021000AD000030AF4201B88D220020B3
+:10F9B0000043102403E00008AD2200208F820014D1
+:10F9C00030E7FFFF00804821904200D330A5FFFFC1
+:10F9D00030C600FF0002110030420F0000E238255F
+:10F9E000274801808F4201B80440FFFE8F82004803
+:10F9F000AD0200008F420124AD0200048D220020E0
+:10FA0000A5070008A102000A24020017A102000BAA
+:10FA1000934301208D2200088D240004306300FFF1
+:10FA2000004310219783003A004410218F84001472
+:10FA3000004310233C0308008C6331A0A502000C96
+:10FA4000A505000E246300E8A5030010A50600121A
+:10FA5000AD0000148D220024AD0200188C82005CE1
+:10FA6000AD02001C8C820058AD0200202402FFFF72
+:10FA7000AD020024948200E63042FFFFAD02002870
+:10FA800094820060948300BE30427FFF3063FFFFAA
+:10FA90000002120000431021AD02002C3C021000B5
+:10FAA000AD000030AF4201B8948200BE2403FFF7DE
+:10FAB00000A21021A48200BE8D2200200043102449
+:10FAC00003E00008AD220020274301808F4201B8E7
+:10FAD0000440FFFE8F8200249442001C3042FFFF4E
+:10FAE000000211C0AC62000024020019A062000BE9
+:10FAF0003C021000AC60003003E00008AF4201B8E7
+:10FB00008F87002C30C300FF8F4201B80440FFFEF6
+:10FB10008F82004834636000ACA2000093820044EE
+:10FB2000A0A200058CE20010A4A20006A4A3000875
+:10FB30008C8200202403FFF7A0A2000A2402000206
+:10FB4000A0A2000B8CE20000ACA200108CE200042A
+:10FB5000ACA200148CE2001CACA200248CE20020B9
+:10FB6000ACA200288CE2002CACA2002C8C820024D9
+:10FB7000ACA200183C021000AF4201B88C820020F9
+:10FB80000043102403E00008AC8200208F8600149C
+:10FB900027BDFFE8AFBF0014AFB0001090C20063F4
+:10FBA000304200201040000830A500FF8CC2007CCD
+:10FBB0002403FFDF24420001ACC2007C90C200633A
+:10FBC00000431024A0C2006310A000238F83001400
+:10FBD00027500180020028210E0015D6240600823D
+:10FBE0008F82001490420063304200405040001960
+:10FBF000A38000448F83002C8F4201B80440FFFE95
+:10FC00008F820048AE02000024026082A602000833
+:10FC100024020002A202000B8C620008AE02001057
+:10FC20008C62000CAE0200148C620014AE0200184C
+:10FC30008C620018AE0200248C620024AE02002800
+:10FC40008C620028AE02002C3C021000AF4201B8CA
+:10FC5000A38000448F8300148FBF00148FB0001066
+:10FC60009062006327BD00183042007FA0620063ED
+:10FC70009782003A8F86003C8F850014938300287A
+:10FC800000461023A782003AA4A000E490A40063D9
+:10FC90008F820040AF83003C2403FFBF0046102149
+:10FCA00000832024AF820040A0A400638F82001450
+:10FCB000A04000BD8F82001403E00008A44000BEF5
+:10FCC0008F8A001427BDFFE0AFB10014AFB0001061
+:10FCD0008F88003CAFBF00189389001C954200E458
+:10FCE00030D100FF0109182B0080802130AC00FFCB
+:10FCF0003047FFFF0000582114600003310600FF69
+:10FD000001203021010958239783003A0068102B05
+:10FD10001440003C000000001468000724020001A9
+:10FD20008E0200202403FFFB34E7800000431024F0
+:10FD3000AE0200202402000134E70880158200058D
+:10FD40003165FFFF0E001554020020210A001691B4
+:10FD5000020020210E001585020020218F8400481A
+:10FD6000274301808F4201B80440FFFE240200189F
+:10FD7000AC640000A062000B8F840014948200E643
+:10FD8000A46200103C021000AC600030AF4201B829
+:10FD90009482006024420001A4820060948200608A
+:10FDA0003C0308008C63318830427FFF5443000FCE
+:10FDB000020020219482006024038000004310246C
+:10FDC000A48200609082006090830060304200FF57
+:10FDD000000211C200021027000211C03063007F30
+:10FDE00000621825A0830060020020210220282143
+:10FDF0008FBF00188FB100148FB000100A0015F9E2
+:10FE000027BD0020914200632403FF80004310259A
+:10FE1000A14200639782003A3048FFFF11000020A2
+:10FE20009383001C8F840014004B1023304600FF86
+:10FE3000948300E42402EFFF0168282B0062182459
+:10FE4000A48300E414A000038E02002001005821C6
+:10FE5000000030212403FFFB34E78000004310241E
+:10FE6000AE02002024020001158200053165FFFF6B
+:10FE70000E001554020020210A0016B99783003A9B
+:10FE80000E001585020020219783003A8F82003CE6
+:10FE9000A780003A00431023AF82003C9383001CEC
+:10FEA0008F8200148FBF00188FB100148FB0001024
+:10FEB00027BD002003E00008A04300BD938200445A
+:10FEC0002403000127BDFFE8004330042C4200203A
+:10FED000AFB00010AFBF00142410FFFE10400005AB
+:10FEE000274501803C0208008C4231900A0016D65A
+:10FEF000004610243C0208008C4231940046102435
+:10FF000014400007240600848F8300142410FFFF90
+:10FF1000906200623042000F34420040A0620062F2
+:10FF20000E0015D600000000020010218FBF001443
+:10FF30008FB0001003E0000827BD00188F83002455
+:10FF400027BDFFE0AFB20018AFB10014AFB0001092
+:10FF5000AFBF001C9062000D00A0902130D100FFC7
+:10FF60003042007FA062000D8F8500148E43001880
+:10FF7000008080218CA2007C146200052402000E07
+:10FF800090A20063344200200A0016FFA0A2006382
+:10FF90000E0016C5A38200442403FFFF1043004750
+:10FFA0002404FFFF52200045000020218E43000062
+:10FFB0003C02001000621024504000043C02000883
+:10FFC000020020210A00170E2402001500621024EE
+:10FFD000504000098E450000020020212402001438
+:10FFE0000E0016C5A38200442403FFFF1043003314
+:10FFF0002404FFFF8E4500003C02000200A21024F2
+:020000040001F9
+:10000000104000163C0200048F8600248CC20014AD
+:100010008CC300108CC40014004310230044102B28
+:1000200050400005020020218E43002C8CC200109D
+:1000300010620003020020210A00173F2402001270
+:100040003C02000400A210245040001C00002021AB
+:10005000020020210A00173F2402001300A21024EE
+:10006000104000068F8300248C6200105040001363
+:10007000000020210A001739020020218C620010A4
+:10008000504000048E42002C020020210A00173F3D
+:10009000240200115040000900002021020020210C
+:1000A000240200170E0016C5A38200442403FFFF9C
+:1000B000104300022404FFFF000020218FBF001C1A
+:1000C0008FB200188FB100148FB000100080102183
+:1000D00003E0000827BD00208F83001427BDFFD850
+:1000E000AFB40020AFB3001CAFB20018AFB1001422
+:1000F000AFB00010AFBF0024906200638F91002C5E
+:100100002412FFFF3442004092250000A0620063E9
+:100110008E2200100080982130B0003F105200065F
+:100120000360A0212402000D0E0016C5A382004426
+:10013000105200542404FFFF8F8300148E220018F5
+:100140008C63007C10430007026020212402000E13
+:100150000E0016C5A38200442403FFFF104300498C
+:100160002404FFFF24040020120400048F830014E1
+:100170009062006334420020A06200638F850034E7
+:1001800010A0002000000000560400048F8200141C
+:10019000026020210A0017902402000A9683000AB8
+:1001A000944200603042FFFF144300048F8200201D
+:1001B0002404FFFD0A0017B7AF82003C3C02080090
+:1001C0008C42318C0045102B144000060260202127
+:1001D000000028210E001646240600010A0017B769
+:1001E000000020212402002D0E0016C5A382004429
+:1001F0002403FFFF104300232404FFFF0A0017B766
+:1002000000002021160400058F8400148E230014A2
+:100210002402FFFF506200180260202194820060D7
+:1002200024420001A4820060948200603C03080024
+:100230008C63318830427FFF5443000F02602021DD
+:10024000948200602403800000431024A482006094
+:100250009082006090830060304200FF000211C273
+:1002600000021027000211C03063007F00621825D1
+:10027000A0830060026020210E0015F92405000112
+:10028000000020218FBF00248FB400208FB3001CFA
+:100290008FB200188FB100148FB0001000801021B1
+:1002A00003E0000827BD00288F83001427BDFFE866
+:1002B000AFB00010AFBF0014906200638F87002CB6
+:1002C00000808021344200408CE60010A062006370
+:1002D0003C0308008C6331B030C23FFF0043102B59
+:1002E0001040004E8F8500302402FF8090A3000D47
+:1002F00000431024304200FF5040004902002021FA
+:100300000006138230480003240200025502004414
+:100310000200202194A2001C8F85001424030023D6
+:10032000A4A201148CE60000000616023042003F31
+:10033000104300103C0300838CE300188CA2007C67
+:10034000106200062402000E0E0016C5A3820044AF
+:100350002403FFFF104300382404FFFF8F830014A1
+:100360009062006334420020A06200630A0017FC20
+:100370008F83002400C31024144300078F830024BC
+:1003800090A200623042000F34420020A0A200621E
+:10039000A38800388F8300249062000D3042007FD4
+:1003A000A062000D8F83003410600018020020212D
+:1003B0008F8400308C8200100043102B1040000905
+:1003C00024020018020020210E0016C5A38200445A
+:1003D0002403FFFF104300182404FFFF0A00182421
+:1003E000000020218C820010240500010200202141
+:1003F000004310238F830024240600010E001646BC
+:10040000AC6200100A001824000020210E0015F92B
+:10041000240500010A0018240000202102002021E8
+:100420002402000D8FBF00148FB0001027BD0018EC
+:100430000A0016C5A38200448FBF00148FB00010BD
+:100440000080102103E0000827BD001827BDFFC869
+:10045000AFB20020AFBF0034AFB60030AFB5002C54
+:10046000AFB40028AFB30024AFB1001CAFB0001888
+:100470008F4601283C0308008C6331A02402FF80D2
+:10048000AF86004800C318213065007F034528214E
+:10049000006218243C02000AAF43002400A2282175
+:1004A00090A2006200809021AF850014304200FFCE
+:1004B00000021102A382003890A200BC3042000268
+:1004C0001440000224030034240300308F820014FF
+:1004D000A3830028938300388C4200C0A38000448B
+:1004E000AF82003C24020004106203148F84003C9D
+:1004F0008E440004508003118F84003C8E42001013
+:100500003083FFFFA784003A106002F7AF820040FB
+:100510008F8400142403FF80908200630062102403
+:10052000304200FF144002C79785003A9383003899
+:100530002402000230B6FFFF14620005000088218B
+:10054000938200282403FFFD0A001B11AF82003CA8
+:100550008F82003C02C2102B144002998F8400400D
+:100560000E0014EC00000000938300283C040800F7
+:1005700024847778240200341462002EAF84002C87
+:100580003C0A08008D4A77A82402FFFFAFA20010A2
+:10059000008038212405002F3C09080025297378A4
+:1005A000240800FF2406FFFF90E2000024A3FFFFC1
+:1005B0000006220200C21026304200FF0002108016
+:1005C000004910218C420000306500FF24E7000143
+:1005D00014A8FFF50082302600061027AFA20014F1
+:1005E000AFA200100000282127A7001027A60014A2
+:1005F00000C510239044000324A2000100A7182185
+:10060000304500FF2CA200041440FFF9A064000054
+:100610008FA2001011420007240200050240202191
+:100620000E0016C5A38200442403FFFF104300649C
+:100630002404FFFF3C0208009042777C1040000930
+:100640008F820014024020212402000C0E0016C5E7
+:10065000A38200442403FFFF104300592404FFFF3A
+:100660008F820014A380001C3C0308008C63777CFD
+:100670008C4400803C0200FF3442FFFF00621824DB
+:100680000083202B10800008AF830034024020211B
+:10069000240200190E0016C5A38200442403FFFFA4
+:1006A000104300472404FFFF8F87003C9782003AE5
+:1006B0008F850034AF8700200047202310A0003B27
+:1006C000A784003A8F86001430A200030002102392
+:1006D00090C300BC3050000300B0282100031882F2
+:1006E000307300010013108000A228213C03080091
+:1006F0008C6331A08F8200483084FFFF0085202B5F
+:100700000043102110800011244200888F84002CA7
+:100710001082000E3C033F013C0208008C427778B7
+:10072000004310243C0325001443000630E500FF7D
+:100730008C820000ACC200888C8200100A0018E98C
+:10074000ACC200980E001529000030219382001CD5
+:100750008F8500148F830040020238218F82003C75
+:10076000A387001C94A400E4006218218F82003447
+:1007700034841000AF83004000503021A4A400E472
+:100780001260000EAF86003C24E20004A382001C2D
+:1007900094A200E424C30004AF83003C3442200050
+:1007A000A4A200E40A001906000020218F82004064
+:1007B000AF80003C00471021AF82004000002021A4
+:1007C0002414FFFF109402092403FFFF3C080800D3
+:1007D0008D0877883C0208008C4231B03C03080049
+:1007E0009063777831043FFF0082102B1040001B8C
+:1007F0003067003F3C0208008C4231A88F830048DC
+:100800000004218000621821006418213062007FFA
+:10081000034228213C02000C00A228213C02008057
+:10082000344200013066007800C230252402FF8087
+:1008300000621024AF42002830640007AF42080471
+:100840008F8200140344202124840940AF460814F9
+:10085000AF850024AF840030AC4301189383003887
+:1008600024020003146201C72402000124020026AE
+:1008700010E201C928E200271040001324020032D0
+:100880002402002210E201C428E2002310400008E4
+:10089000240200242402002010E201B024020021DE
+:1008A00010E2013F024020210A001AF32402000B4B
+:1008B00010E201B92402002510E2001002402021BC
+:1008C0000A001AF32402000B10E201A628E200330A
+:1008D000104000062402003F2402003110E2009282
+:1008E000024020210A001AF32402000B10E2019DAD
+:1008F000024020210A001AF32402000B8F90002CE2
+:100900003C0308008C6331B08F8500308E040010EA
+:100910000000A8218CB3001430823FFF0043102B4D
+:100920008CB10020504001870240202190A3000D8F
+:100930002402FF8000431024304200FF5040018118
+:100940000240202100041382304200031440017D44
+:100950000240202194A3001C8F8200148E040028E2
+:10096000A44301148CA20010026218231064000337
+:10097000024020210A00197C2402001F8F820034CB
+:10098000006210210262102B104000088F830024A7
+:1009900002402021240200180E0016C5A382004444
+:1009A0001054016C2404FFFF8F8300248F840034D3
+:1009B0008C6200100224882100441023AC620010D5
+:1009C0008F820014AC7100208C4200680051102B03
+:1009D000104000098F830030024020212402001DB6
+:1009E0000E0016C5A38200442403FFFF10430159E3
+:1009F0002404FFFF8F8300308E0200248C630024C8
+:100A000010430007024020212402001C0E0016C5DE
+:100A1000A38200442403FFFF1043014E2404FFFF80
+:100A20008F8400248C82002424420001AC820024A4
+:100A3000123300048F8200148C4200685622000E8C
+:100A40008E0200008E0200003C0300800043102450
+:100A50001440000D2402001A024020210E0016C589
+:100A6000A38200442403FFFF1043013A2404FFFF44
+:100A70000A0019BA8E0200143C03008000431024BF
+:100A8000504000038E020014AC8000208E0200143F
+:100A90002411FFFF105100062402001B02402021F8
+:100AA0000E0016C5A38200441051012A2404FFFF42
+:100AB0008E0300003C02000100621024104000126E
+:100AC0003C020080006210241440000802402021F3
+:100AD0002402001A0E0016C5A38200442403FFFF5F
+:100AE0001043011C2404FFFF0240202102002821A2
+:100AF0000E0016E5240600012403FFFF1043011534
+:100B00002404FFFF241500018F83002402A030215C
+:100B10000240202194620036240500012442000195
+:100B20000A001AD7A46200368F90002C3C030800FC
+:100B30008C6331B08E13001032623FFF0043102BE4
+:100B4000104000898F8400302402FF809083000DC4
+:100B500000431024304200FF104000842402000DA6
+:100B60000013138230420003240300011443007F6A
+:100B70002402000D9082000D304200085440000411
+:100B80008F820034024020210A001A082402002427
+:100B9000504000048E03000C024020210A001A0875
+:100BA000240200278C82002054620006024020218B
+:100BB0008E0300088C820024506200098E0200140B
+:100BC00002402021240200200E0016C5A38200440A
+:100BD000105400712403FFFF0A001A3D8F84002483
+:100BE0002411FFFF145100048F86001402402021BD
+:100BF0000A001A38240200258E0300188CC2007CDB
+:100C0000106200032402000E0A001A38024020215C
+:100C10008E0300248C82002810620003240200212D
+:100C20000A001A38024020218E0500288C82002CF0
+:100C300010A200032402001F0A001A3802402021DB
+:100C40008E03002C14600003240200230A001A38CB
+:100C5000024020218CC200680043102B104000038A
+:100C6000240200260A001A38024020218C82001437
+:100C7000006518210043102B104000088F840024C9
+:100C800002402021240200220E0016C5A382004447
+:100C9000105100412403FFFF8F8400242403FFF739
+:100CA0009082000D00431024A082000D8F86001456
+:100CB0003C0308008C6331AC8F82004894C400E090
+:100CC0008F8500240043102130847FFF00042040E2
+:100CD000004410213043007F034320213C03000ED9
+:100CE000008320212403FF8000431024AF42002C06
+:100CF000A49300008CA2002824420001ACA200288A
+:100D00008CA2002C8E03002C00431021ACA2002CDE
+:100D10008E02002CACA200308E020014ACA2003473
+:100D200094A2003A24420001A4A2003A94C600E032
+:100D30003C0208008C4231B024C4000130837FFFA4
+:100D40001462000F008030212402800000823024D1
+:100D500030C2FFFF000213C2304200FF0002102722
+:100D60000A001A76000233C02402000D024020213E
+:100D70000E0016C5A38200440A001A7C0040182108
+:100D80008F82001402402021240500010E0015F975
+:100D9000A44600E0000018210A001B0E0060882114
+:100DA0008F90002C3C0308008C6331B08E0500103E
+:100DB00030A23FFF0043102B104000612402FF804F
+:100DC0008F8400309083000D00431024304200FFD8
+:100DD0005040005C024020218F8200341040000B04
+:100DE000000513828F8200149763000A944200600A
+:100DF0003042FFFF14430005000513828F8200205C
+:100E00002404FFFD0A001AEBAF82003C30420003CD
+:100E10001440000E00000000920200021040000585
+:100E20008E03002450600015920300030A001AA7E5
+:100E3000024020218C8200245062001092030003A3
+:100E4000024020210A001AAF2402000F9082000DF8
+:100E50003042000854400009920300030240202160
+:100E6000240200100E0016C5A38200442403FFFFD5
+:100E7000104300382404FFFF920300032402000201
+:100E80005462000C920200038F8200345440000927
+:100E900092020003024020212402002C0E0016C5FD
+:100EA000A38200442403FFFF1043002A2404FFFF11
+:100EB000920200030200282102402021384600103F
+:100EC0002CC600012C4200010E0016E5004630251C
+:100ED0002410FFFF1050001F2404FFFF8F830034F5
+:100EE00010600013024020213C0208008C42318C2B
+:100EF0000043102B144000070000000000002821D0
+:100F0000240600010E001646000000000A001AEB3D
+:100F1000000020212402002D0E0016C5A3820044EB
+:100F20001050000C2404FFFF0A001AEB00002021DF
+:100F30000E0015F9240500010A001AEB000020211B
+:100F4000024020212402000D0E0016C5A382004499
+:100F5000004020210A001B0E008088211514000E7D
+:100F6000000000000E00174C024020210A001B0E5A
+:100F7000004088210E0016C5A38200440A001B0E03
+:100F80000040882114620017022018212402002347
+:100F900014E200052402000B0E0017C002402021BD
+:100FA0000A001B0E0040882102402021A382004439
+:100FB0000E0016C52411FFFF0A001B0F0220182186
+:100FC00030A500FF0E001529240600019783003A82
+:100FD0008F82003CA780003A00431023AF82003C80
+:100FE000022018211220003E9782003A2402FFFDC1
+:100FF0005462003E8E4300208E4200048F83001412
+:1010000000561023AE420004906200633042007F1D
+:10101000A06200638E4200208F840014A780003AF3
+:1010200034420002AE420020A48000E490820063BB
+:101030002403FFBF00431024A08200630A001B5159
+:101040008E4300209082006300621024304200FF33
+:10105000104000239782003A90820088908300BD60
+:10106000248500883042003F2444FFE02C82002089
+:10107000A383001C10400019AF85002C240200013E
+:1010800000821804306200191440000C3C028000F9
+:1010900034420002006210241440000B3062002031
+:1010A0001040000F9782003A90A6000102402021D4
+:1010B000240500010A001B4B30C60001024020211C
+:1010C0000A001B4A240500010240202100002821BB
+:1010D000240600010E001646000000009782003A28
+:1010E0001440FD0C8F8400148E43002030620004F5
+:1010F000104000128F84003C2402FFFB0062102489
+:10110000AE420020274301808F4201B80440FFFE19
+:101110008F820048AC6200008F420124AC62000460
+:1011200024026083A462000824020002A062000B73
+:101130003C021000AF4201B88F84003C8F83001442
+:101140008FBF00348FB600308FB5002C8FB40028CD
+:101150008FB300248FB200208FB1001C8FB0001815
+:101160002402000127BD003803E00008AC6400C081
+:1011700030A500FF2403000124A900010069102B01
+:101180001040000C00004021240A000100A310239D
+:10119000004A380424630001308200010069302BCA
+:1011A00010400002000420420107402554C0FFF80F
+:1011B00000A3102303E00008010010213C020800F6
+:1011C000244260A43C010800AC22736C3C0208007D
+:1011D000244253083C010800AC227370240200062C
+:1011E00027BDFFE03C010800A02273743C021EDC16
+:1011F000AFB20018AFB10014AFBF001CAFB0001009
+:1012000034526F4100008821240500080E001B7233
+:1012100002202021001180803C07080024E7737819
+:101220000002160002071821AC620000000028210D
+:1012300024A200013045FFFF8C6200002CA60008AC
+:1012400004410002000220400092202614C0FFF852
+:10125000AC640000020780218E0400000E001B72A7
+:1012600024050020262300013071FFFF2E230100FA
+:101270001460FFE5AE0200008FBF001C8FB20018A3
+:101280008FB100148FB0001003E0000827BD0020CC
+:1012900027BDFFD8AFB3001CAFB20018AFBF00200E
+:1012A000AFB10014AFB000108F5101408F4801481A
+:1012B00000089402324300FF311300FF8F4201B84F
+:1012C0000440FFFE27500180AE1100008F42014410
+:1012D000AE02000424020002A6120008A202000BC3
+:1012E00024020014AE1300241062002528620015A9
+:1012F0001040000824020015240200101062003083
+:1013000024020012106200098FBF00200A001CADE9
+:101310008FB3001C1062007024020022106200379C
+:101320008FBF00200A001CAD8FB3001C3C020800D8
+:101330008C4231A02403FF8002221021004310249C
+:10134000AF4200243C0208008C4231A0022210214E
+:101350003042007F034218213C02000A006218213B
+:10136000166000BCAF830014906200623042000F30
+:1013700034420030A06200620A001CAC8FBF002023
+:101380003C0460008C832C083C02F0033442FFFFD5
+:1013900000621824AC832C083C0208008C4231A067
+:1013A0008C832C08244200740002108200021480F6
+:1013B00000621825AC832C080A001CAC8FBF0020EB
+:1013C0003C0208008C4231A02403FF80022210213D
+:1013D00000431024AF4200243C0208008C4231A09C
+:1013E0003C03000A022210213042007F03421021F8
+:1013F000004310210A001CABAF8200143C0208001D
+:101400008C4231A02405FF800222102100451024C7
+:10141000AF4200243C0208008C4231A0022210217D
+:101420003042007F034218213C02000A006218216A
+:101430009062006300A21024304200FF104000853B
+:10144000AF83001424620088944300123C02080019
+:101450008C4231A830633FFF000319800222102123
+:10146000004310213043007F034320210045102416
+:101470003C03000C00832021AF4200289082000D25
+:1014800000A21024304200FF10400072AF840024FC
+:101490009082000D304200101440006F8FBF00207A
+:1014A0000E0015C8000000008F4201B80440FFFE86
+:1014B00000000000AE1100008F420144AE020004A3
+:1014C00024020002A6120008A202000BAE130024A0
+:1014D0000A001CAC8FBF00202406FF8002261024C7
+:1014E000AF4200203C0208008C4231A031043FFF93
+:1014F000000421800222102100461024AF42002463
+:101500003C0308008C6331A83C0208008C4231A0E7
+:101510003227007F022318210222102100641821A3
+:101520003042007F3064007F034228213C02000AE1
+:101530000066182400A22821034420213C02000C4C
+:1015400000822021AF4300283C02000803471821F5
+:1015500000629021AF850014AF8400240E0015C8EE
+:10156000010080218F4201B80440FFFE8F820024D9
+:101570008F840014274501809042000DACB100001B
+:10158000A4B0000600021600000216030002102795
+:10159000000237C214C00016248200889442001250
+:1015A00032033FFF30423FFF1443001224026082A7
+:1015B000908300632402FF8000431024304200FF28
+:1015C0005040000C24026082908200623042000F82
+:1015D00034420040A082006224026084A4A2000879
+:1015E0002402000DA0A200050A001C963C02270060
+:1015F00024026082A4A20008A0A000053C022700EB
+:1016000000061C000062182524020002A0A2000BA4
+:10161000ACA30010ACA00014ACA00024ACA0002827
+:10162000ACA0002C8E42004C8F840024ACA2001889
+:101630009083000D2402FF8000431024304200FFFD
+:10164000104000058FBF00209082000D3042007FC7
+:10165000A082000D8FBF00208FB3001C8FB2001836
+:101660008FB100148FB000103C02100027BD00287D
+:0816700003E00008AF4201B8DD
+:08167800080034300800343092
+:10168000080033A8080033E0080034140800343898
+:0C16900008003438080034380800331813
+:04169C000A0001241B
+:1016A00000000000000000000000000D74706136B2
+:1016B0002E302E313500000006000F010000000022
+:1016C000000000000000000000000000000000001A
+:1016D000000000000000000000000000000000000A
+:1016E00000000000000000000000000000000000FA
+:1016F00000000000000000000000000000000000EA
+:1017000000000000000000000000000000000000D9
+:1017100000000000000000000000000000000000C9
+:1017200000000000000000000000000000000000B9
+:1017300010000003000000000000000D0000000D7C
+:101740003C02080024421C003C030800246320944F
+:10175000AC4000000043202B1480FFFD2442000415
+:101760003C1D080037BD2FFC03A0F0213C100800F1
+:10177000261004903C1C0800279C1C000E00015CF5
+:10178000000000000000000D3084FFFF30820007E1
+:101790008F85001810400002248300073064FFF892
+:1017A0000085302130C41FFF03441821247B4000F2
+:1017B000AF85001CAF84001803E00008AF4400842C
+:1017C0003084FFFF308200078F8500208F8600283D
+:1017D00010400002248300073064FFF800852021B8
+:1017E0000086182B14600002AF8500240086202399
+:1017F0000344282134068000AF840020AF440080D9
+:1018000000A6202103E00008AF84003827BDFFD8E0
+:10181000AFB3001CAFB20018AFB00010AFBF0024D0
+:10182000AFB40020AFB100143C0860088D14500024
+:101830002418FF7F3C1A8000029898243672380CD6
+:10184000AD1250008F5100083C07601C3C0860003E
+:1018500036300001AF500008AF800018AF40008064
+:10186000AF4000848CE600088D0F08083C07601626
+:101870008CEC000031EEFFF039CA00103C0DFFFF88
+:10188000340B80003C030080034B48212D440001B1
+:10189000018D28243C0253533C010800AC23042052
+:1018A000AF890038AF860028AF840010275B400066
+:1018B00014A2000334E37C008CF9000403281821EF
+:1018C0008C7F007C8C6500783C0280003C0B08001B
+:1018D0008D6B048C3C0A08008D4A048834520070D9
+:1018E000AF85003CAF9F00403C13080026731C44AA
+:1018F0000240A0218E4800008F46000038C300013E
+:101900003064000110800017AF8800340280482145
+:101910008D2F00003C0508008CA5045C3C180800D5
+:101920008F18045801E8102300A280210000C8216C
+:101930000202402B03198821022838213C010800AB
+:10194000AC30045C3C010800AC2704588F4E00000A
+:1019500039CD000131AC00011580FFED01E04021DF
+:10196000AF8F00348E5100003C0708008CE7045C08
+:101970003C0D08008DAD04580228802300F0602142
+:10198000000070210190302B01AE1821006620214B
+:101990003C010800AC2C045C3C010800AC24045859
+:1019A0008F4601088F47010030C92000AF86000034
+:1019B000AF87000C1120000A00C040213C1808002D
+:1019C0008F18042C270800013C010800AC28042CC7
+:1019D0003C184000AF5801380A0001960000000092
+:1019E0009749010400002821014550213122FFFFC1
+:1019F000016258210162F82B015F502130D90200A9
+:101A00003C010800AC2B048C3C010800AC2A048883
+:101A10001720001524040F0010E40013000000003C
+:101A200024080D0010E8023B30CD000611A0FFE9AC
+:101A30003C184000936E00002409001031C400F0EF
+:101A40001089027124020070108202E58F88001450
+:101A5000250F0001AF8F00143C184000AF5801382B
+:101A60000A00019600000000974C01041180FFD984
+:101A70003C18400030C34000146000A1000000008A
+:101A80008F46017804C0FFFE8F87003824100800BD
+:101A9000240F00088CE30008AF500178A74F0140E5
+:101AA000A7400142974E01048F86000031C9FFFF15
+:101AB00030CD000111A002E1012040212531FFFEBF
+:101AC00024180002A75801463228FFFFA7510148F9
+:101AD0003C1908008F39043C172002D08F8C000C71
+:101AE00030DF002017E00002240400092404000174
+:101AF00030C20C0024050400504500013484000469
+:101B0000A744014A3C1108008E3104203C180048CB
+:101B10003C1000010238182530CF00020070282543
+:101B200011E00004000018213C19010000B928252B
+:101B30002403000130DF000453E00005AF830008F8
+:101B40003C06001000A6282524030001AF830008EE
+:101B5000AF45100000000000000000000000000081
+:101B6000000000008F8300081060002300000000C8
+:101B70008F45100004A1FFFE000000001060001E51
+:101B8000000000008F4410003C0C0020008C10244A
+:101B9000104000198F8E000031CD000211A00016F8
+:101BA00000000000974F101415E000130000000023
+:101BB000975910083338FFFF2711000600111882CB
+:101BC0000003308000C72821323000013223000397
+:101BD0001200032C8CA200000000000D00C7F821A9
+:101BE000AFE200003C0508008CA5043024A60001EB
+:101BF0003C010800AC2604308F6D00003402FFFF6A
+:101C0000AF8D00048CEC0000118202A600002021A0
+:101C10008CED000031AC01001180028A0000000050
+:101C20003C0208008C4204743C0308008C63044CA2
+:101C30003C1F08008FFF04703C1808008F180448F0
+:101C4000004838210068802100E8282B03E4302177
+:101C50000208402B0304882100C570210228782146
+:101C60003C010800AC30044C3C010800AC2F044897
+:101C70003C010800AC2704743C010800AC2E047041
+:101C80008F8400180120302131290007249F00088B
+:101C900033F91FFF03594021AF84001CAF9900188E
+:101CA000251B4000AF590084112000038F830020C2
+:101CB00024C200073046FFF88F84002800C3282183
+:101CC00000A4302B14C00002AF83002400A42823FA
+:101CD00003456021340D8000018D10213C0F100060
+:101CE000AF850020AF820038AF450080AF4F01784C
+:101CF0008F880014250F00010A0001EFAF8F001438
+:101D00008F6200088F67000024050030000776020C
+:101D100031C300F0106500A7240F0040546FFF4C42
+:101D20008F8800148F4B01780560FFFE00000000D3
+:101D300030CA020015400003000612820000000DA8
+:101D400000061282304D0003000D4900012D1821BC
+:101D500000038080020D40210008608001938021F3
+:101D60008E1F000017E00002000000000000000DC0
+:101D70008F6E000405C202BD92070006920E000598
+:101D8000920200043C090001000E18800070F82146
+:101D90008FED0018277100082448000501A9602173
+:101DA00000083082AFEC0018022020210E00059EB2
+:101DB00026050014920A00068F7900043C0B7FFF71
+:101DC000000A2080009178218DF800043566FFFF1D
+:101DD0000326282403053821ADE70004920E0005F0
+:101DE000920D0004960C0008000E10800051C821CE
+:101DF0008F230000974901043C07FFFF0067582428
+:101E00003128FFFF010DF82103EC50233144FFFF7F
+:101E100001643025AF26000092030007241800015A
+:101E200010780275240F0003106F02850000000077
+:101E30008E0500102419000AA7590140A745014248
+:101E4000921800048F860000240F0001A758014457
+:101E5000A74001469747010430D100023C050041EC
+:101E6000A747014800001821A74F014A122000038C
+:101E700030CB00043C050141240300015160000502
+:101E8000AF8300083C06001000A6282524030001AB
+:101E9000AF830008AF451000000000000000000004
+:101EA00000000000000000008F8A000811400004BC
+:101EB000000000008F4410000481FFFE00000000BD
+:101EC0008F6B0000920800043C1108008E3104441E
+:101ED000AF8B000497590104311800FF3C0E080035
+:101EE0008DCE04403325FFFF0305382102276021F2
+:101EF00000001021250F000A31E8FFFF0187482B61
+:101F000001C2682101A9F821311000073C01080035
+:101F1000AC2C04443C010800AC3F04401200000318
+:101F20008F8C00182506000730C8FFF8010C6821C7
+:101F300031BF1FFFAF8C001CAF9F0018AF5F008444
+:101F400097440104035F80213084FFFF308A00073B
+:101F500011400003261B4000248900073124FFF8AC
+:101F60008F8200208F850028008220210085702B21
+:101F700015C00002AF820024008520233C0B08001E
+:101F80008D6B048C3C0A08008D4A04880344882128
+:101F900034038000022310213C0F1000AF84002086
+:101FA000AF820038AF440080AF4F01780A0002963C
+:101FB0008F8800148F5001780600FFFE30D1020098
+:101FC00016200003000612820000000D0006128297
+:101FD000305F0003001F1900007F302100062080C1
+:101FE000009FC82100194880013380218E1800000D
+:101FF00013000002000000000000000D8F6C000CB8
+:10200000058001FB8F870038240E0001AE0E000012
+:102010008CE30008A20000078F650004000554024D
+:10202000314D00FF25A80005000830822CCB00416F
+:1020300015600002A20A00040000000D8F78000461
+:102040003C03FFFF00E02821330BFFFF256C000B52
+:10205000000C108200022080008748218D3F000084
+:1020600026040014A618000803E3C8240E00059EE9
+:10207000AD3900008F4F01083C11100001F13824E8
+:1020800010E001AB00000000974D0104920800072A
+:1020900025AAFFEC350600023144FFFFA206000727
+:1020A000960600082CC7001354E0000592030007B1
+:1020B00092110007362F0001A20F000792030007BC
+:1020C00024180001107801C224090003106901D509
+:1020D0008F88003830CBFFFF257100020011788314
+:1020E00031E400FF00042880A20F000500A8482169
+:1020F0008D2D0000974A01043C0EFFFF01AEF8242D
+:102100003143FFFF006B1023244CFFFE03ECC82576
+:10211000AD390000920600053C03FFF63462FFFF74
+:1021200030D800FF0018388000F08821922F00146A
+:102130003C04FF7F3487FFFF31EE000F01C65821BA
+:10214000316500FF00055080015068218DAC0020F2
+:102150000148F821A20B00060182C824AE0C000C35
+:10216000AFF9000C920900068E11000C03277824A9
+:102170000009C0800310702195C60026030828219D
+:1021800002272024AE04000CADCF0020ADC60024F1
+:10219000ACA600108F8800003C0B08008D6B048CEF
+:1021A0003C0A08008D4A0488241F001024190002EC
+:1021B000A75F0140A7400142A7400144A75901463B
+:1021C0009749010424070001310600022538FFFE6B
+:1021D000A75801483C050009A747014A10C0000361
+:1021E000000018213C05010924030001310C000402
+:1021F00051800005AF8300083C08001000A8282586
+:1022000024030001AF830008AF4510000000000068
+:102210000000000000000000000000009205000423
+:1022200024AE000231CD0007000D182330620007F4
+:10223000AE0200108F9000081200000400000000A1
+:102240008F4F100005E1FFFE000000008F710000BD
+:102250008F8E00183C0308008C630444AF91000487
+:102260009745010425CF001031E61FFF30A2FFFF84
+:10227000AF8E001CAF860018AF4600842449FFFED5
+:102280003C0C08008D8C0440974D010401208021F6
+:10229000000947C30070C02131A9FFFF0310F82BCC
+:1022A0000188C821033F202103463821313100072E
+:1022B0003C010800AC3804443C010800AC24044054
+:1022C0001220000324FB40002527000730E9FFF817
+:1022D0008F8600208F8400280126382100E4C02B3F
+:1022E00017000002AF86002400E4382303472021B2
+:1022F00034198000009910213C0F1000AF87002096
+:10230000AF820038AF470080AF4F01780A000296D5
+:102310008F8800149747010410E0FDAE3C18400080
+:102320008F5801780700FFFE30C5400010A0000361
+:102330003C1F00080000000D3C1F0008AF5F01407B
+:10234000241008008F860000AF50017897440104E4
+:1023500030D90001132000ED3086FFFF24CCFFFEB2
+:10236000240D0002A74D0146A74C01488F9100188B
+:102370002408000DA748014A8F630000262F00089B
+:1023800031E21FFF0342702130C90007AF83000410
+:10239000AF91001CAF82001800C03821AF4200840A
+:1023A0001120000325DB400024D800073307FFF885
+:1023B0008F8500208F84002800E5302100C4382B51
+:1023C00014E00002AF85002400C430238F84001481
+:1023D0000346F821340C8000AF86002003EC8021F6
+:1023E000AF460080249900013C0610003C184000D4
+:1023F000AF460178AF900038AF990014AF5801385C
+:102400000A000196000000008F630000975101044C
+:102410003067FFFF3228FFFF8F4F017805E0FFFE96
+:1024200030EC0007000CF82333F0000724F9FFFE1E
+:102430002404000AA7440140A7500142A7590144BF
+:10244000A7400146A74801488F45010830B8002041
+:1024500017000002240300092403000130CD00020C
+:10246000A743014A3C04004111A0000300001821C9
+:102470003C0401412403000130C90004512000053F
+:10248000AF8300083C0600100086202524030001CD
+:10249000AF830008AF4410000000000000000000FF
+:1024A00000000000000000008F8E000811C0000432
+:1024B000000000008F4210000441FFFE00000000F9
+:1024C0008F7F0000276400088F91003CAF9F0004BD
+:1024D000948500089490000A9499000C30AFFFFF97
+:1024E0000010C4003323FFFF11F100A603032025D1
+:1024F0003C0E08008DCE04443C0C08008D8C04403A
+:1025000000E888212626FFFE01C628210000682158
+:1025100000A6F82B018D2021009F80213C0108009E
+:10252000AC2504443C010800AC30044024E200081F
+:102530003042FFFF3047000710E000038F83001890
+:10254000244F000731E2FFF83106FFFF30C80007D3
+:102550000043802132191FFF0359C021AF83001CA3
+:10256000AF990018271B4000AF59008411000003E9
+:102570008F8C002024C5000730A6FFF88F84002828
+:1025800000CC282100A4F82B17E00002AF8C002417
+:1025900000A42823AF850020AF4500803C0408003C
+:1025A0008C84043403454821340E8000012E6821B8
+:1025B00010800005AF8D0038939100172406000E9F
+:1025C000122600112407043F3C021000AF4201789C
+:1025D0008F880014250F00010A0001EFAF8F00144F
+:1025E0000E0005C400E020218F8800143C0B080079
+:1025F0008D6B048C3C0A08008D4A0488250F00016D
+:102600000A0001EFAF8F00143C021000A7470148F9
+:10261000AF4201780A0004CE8F88001424040F0012
+:102620001184003D30CE002015C0000224030009B3
+:10263000240300010A00021AA743014A0A00020DFE
+:10264000A740014694EF000894F1000A94F0000CB2
+:102650008F8C003C001174003207FFFF31EDFFFF4B
+:1026600011AC003701C720253C1808008F1804441E
+:102670003C0F08008DEF0440000080210308682112
+:1026800001A8382B01F0702101C760213C0108002E
+:10269000AC2D04443C010800AC2C04400A00027A32
+:1026A0008F8400183C0208008C42047C3C03080024
+:1026B0008C6304543C1F08008FFF04783C1808000A
+:1026C0008F180450004838210068802100E8282B2A
+:1026D00003E430210208402B0304882100C5702147
+:1026E000022878213C010800AC3004543C01080069
+:1026F000AC2F04503C010800AC27047C3C010800CE
+:10270000AC2E04780A00027A8F840018A740014694
+:102710000A0004358F91001830CD002015A0FFC5A8
+:102720002403000D240300050A00021AA743014AEE
+:10273000974E010425C5FFF00A00038130A4FFFF76
+:102740008F9800401498FFC8000010213C05080035
+:102750008CA5046C3C1F08008FFF046800A8C821EA
+:102760000328302B03E22021008640213C01080091
+:10277000AC39046C3C010800AC2804680A00027AF9
+:102780008F8400188F8C0040148CFF5900E8C821FA
+:102790003C1808008F18046C3C1108008E31046846
+:1027A0002723FFFE03034821000010210123302BC3
+:1027B0000222702101C668213C010800AC29046C8A
+:1027C0003C010800AC2D04680A0004A524E20008BE
+:1027D0008F8800383C03FFFF8D02000C0043F82473
+:1027E00003E4C825AD19000C0A00038F30CBFFFFAE
+:1027F0000A0003C3AE000000974A010492040004DB
+:102800008E26000C014458212579FFF200C7C02410
+:102810003325FFFF03053825AE27000C0A0002E62A
+:102820008E0500103C0DFFFF8D0A0010014D58244D
+:1028300001646025AD0C00100A00038F30CBFFFF50
+:1028400097430104920E00048E290010006E10219F
+:10285000244DFFEE0127602431A8FFFF0188F825F1
+:10286000AE3F00100A0002E68E0500108E0F000C2D
+:10287000AE00000000078880023028210A0002B85C
+:10288000ACAF00201460000D3058FFFF3C04FFFF88
+:102890000044682401A47026000E602B000D102B4C
+:1028A000004CF82413E00002000000000000000DBE
+:1028B0008CAF00000A00025001E410253B03FFFF2B
+:1028C0000003882B0018802B0211202410800002A6
+:1028D000000000000000000D8CB900000A0002504A
+:1028E0003722FFFF3084FFFF30A5FFFF1080000775
+:1028F0000000182130820001104000020004204234
+:10290000006518211480FFFB0005284003E0000843
+:102910000060102110C00007000000008CA2000021
+:1029200024C6FFFF24A50004AC82000014C0FFFBF6
+:102930002484000403E000080000000010A0000848
+:1029400024A3FFFFAC860000000000000000000090
+:102950002402FFFF2463FFFF1462FFFA24840004B3
+:1029600003E0000800000000308EFFFF30D8FFFFBA
+:1029700000057C0001F8602539CDFFFF01AC502136
+:10298000014C582B014B4821000944023127FFFF1D
+:1029900000E830210006240230C5FFFF00A4182102
+:1029A0003862FFFF03E000083042FFFF3C0C0800E4
+:1029B0008D8C0484240BFF8027BDFFD0018450211F
+:1029C000014B4824AF4900203C0808008D080484CE
+:1029D000AFB20020AFB00018AFBF0028AFB30024E3
+:1029E000AFB1001C936600040104382130E4007F7D
+:1029F000009A10213C0300080043902130C50020BC
+:102A0000036080213C080111277B000814A000020C
+:102A1000264600702646006C92130004975101046C
+:102A2000920F00043267000F322EFFFF31ED00409D
+:102A300001C7282311A0000500004821925900BCBD
+:102A4000333800041700009000000000924300BCDF
+:102A5000307F000413E0000F0000000010A0000D04
+:102A600000000000960E0002240AFF8000A76021EB
+:102A700025CDFFFEA74D1016920B0004014B20241C
+:102A8000308200FF10400085010C40253C0F0400FF
+:102A9000010F40258F5301780660FFFE2404000AD1
+:102AA000A7440140960D00022404000931AC000740
+:102AB000000C5823316A0007A74A0142960200021F
+:102AC0002443FFFEA7430144A7400146975F01044A
+:102AD000A75F01488F5901083338002053000001D7
+:102AE00024040001920F000431EE001015C0000212
+:102AF0003483001000801821A743014A0000000021
+:102B0000000000000000000000000000AF481000BE
+:102B100000000000000000000000000000000000B5
+:102B20008F5110000621FFFE3113FFFF12600003DA
+:102B3000000000008F481018ACC800009603000683
+:102B4000307FFFFF27F90002001998820013888068
+:102B5000023B30218CD800001520005700183402A9
+:102B6000920300042405FF8000A3F82433F100FF42
+:102B70001220002C00000000924700BC30F200023E
+:102B80001240002800000000974B100C2562FFFE49
+:102B9000A7421016000000003C0A0400354900302E
+:102BA000AF4910000000000000000000000000001D
+:102BB000000000008F4C10000581FFFE00000000A7
+:102BC0009749100C8F51101C00C020213127FFFFA6
+:102BD00024F20030001218820003288000BBF82184
+:102BE0003226FFFFAFF100000E0005B300112C02EA
+:102BF0000013C880033B98218E7800000002740007
+:102C0000AFB800108FA80010310FFFFFAFAF00105A
+:102C10008FA4001001C46825AFAD00108FA600106E
+:102C2000AE66000097730008976D000A9766000C67
+:102C30008F8A003C000D5C0030CCFFFF3262FFFF4A
+:102C4000104A0036016C2025960600023C10100048
+:102C500024D300080E00013B3264FFFF974C0104AF
+:102C60000E0001493184FFFFAF5001788FBF00286B
+:102C70008FB300248FB200208FB1001C8FB00018DA
+:102C800003E0000827BD003010A0FF700000000026
+:102C900024A5FFFC0A0005EC240900048CD10000E7
+:102CA000AF5110188F5301780660FF7A2404000A90
+:102CB0000A0006010000000000A7C8218F88003824
+:102CC0008F4E101C0019C0820018788001E8202166
+:102CD000AC8E0000000E2C0200C020210E0005B3B7
+:102CE00031C6FFFF023B28218CAD000000025400DA
+:102CF00000403021AFAD00108FAC0010318BFFFFD2
+:102D0000AFAB00108FA2001001424825AFA9001000
+:102D10008FA700100A000631ACA700008F8F00407B
+:102D2000148FFFC90000000097420104960B0002B7
+:102D30003C0508008CA5046C3049FFFF316AFFFF99
+:102D40003C1108008E310468012A382124F2FFFE6C
+:102D500000B240210012FFC30112C82B023FC02164
+:102D6000031920213C010800AC28046C3C01080038
+:102D7000AC2404680A00066B0000000000A4102BBD
+:102D800010400009240300010005284000A4102B76
+:102D900004A00003000318405440FFFC0005284035
+:102DA00010600007000000000085302B14C00002F6
+:102DB00000031842008520231460FFFB0005284211
+:102DC00003E00008008010218F85002C27BDFFE85C
+:102DD000000530272CC300012CA40002008310251D
+:102DE00010400003AFBF00102405007FAF85002C0A
+:102DF0000005282730A5FFFF0E000592240426F5C4
+:102E00008F830030240402BD004030210083382B22
+:102E100010E0000924050001000420400083102B6D
+:102E200004800003000528405440FFFC00042040BB
+:102E300010A0000800C350210064402B15000002C0
+:102E4000000528420064182314A0FFFB0004204260
+:102E500000C350218FBF0010000A4C02312200FF36
+:102E600027BD0018AF8A002C03E00008AF890030AE
+:102E70000A00002A00000000000000000000000D11
+:102E8000747870362E302E313500000006000F00A9
+:102E900000000000000001360000EA6000000000B1
+:102EA0000000000000000000000000000000000022
+:102EB0000000000000000000000000000000000012
+:102EC0000000000000000000000000000000000002
+:102ED00000000016000000000000000000000000DC
+:102EE00000000000000000000000000000000000E2
+:102EF00000000000000000000000000000000000D2
+:102F00000000000000000000000013880000000026
+:102F1000000005DC000000000000000010000003BD
+:102F2000000000000000000D0000000D3C02080041
+:102F300024423C203C03080024633DD4AC40000004
+:102F40000043202B1480FFFD244200043C1D080098
+:102F500037BD7FFC03A0F0213C100800261000A81C
+:102F60003C1C0800279C3C200E0002BA0000000018
+:102F70000000000D8F8300383C088000350700708A
+:102F80008CE50000008330253C02900000C2202523
+:102F9000AF850030AF4400208F4900200520FFFEA0
+:102FA0003C038000346200708C4500008F86003046
+:102FB0003C1908008F39007C3C0E08008DCE00784B
+:102FC00000A6202303245821000078210164682BE7
+:102FD00001CF6021018D50213C010800AC2B007C09
+:102FE0003C010800AC2A007803E000080000000063
+:102FF0000A000041240400018F8400383C05800051
+:1030000034A200010082182503E00008AF4300202D
+:1030100003E00008000010213084FFFF30A5FFFF0F
+:1030200010800007000018213082000110400002CB
+:1030300000042042006518211480FFFB0005284091
+:1030400003E000080060102110C00007000000002D
+:103050008CA2000024C6FFFF24A50004AC8200005F
+:1030600014C0FFFB2484000403E0000800000000FB
+:1030700010A0000824A3FFFFAC86000000000000A1
+:10308000000000002402FFFF2463FFFF1462FFFA28
+:103090002484000403E0000800000000308AFFFFE1
+:1030A00093A80013A74A014497490E1630C600FFA3
+:1030B0003C021000A7490146AF450148A346015212
+:1030C000A748015AAF4701608FA400188FA30014CE
+:1030D000A7440158AF43015403E00008AF42017810
+:1030E00003E00008000000003C0380003462007030
+:1030F0008C4900008F8800002484000727BDFFF85A
+:103100003084FFF8AF890030974D008A31ACFFFF63
+:10311000AFAC00008FAB0000016850232547FFFFD4
+:1031200030E61FFF00C4282B14A0FFF73C0C8000E2
+:10313000358B00708D6A00003C0708008CE7008426
+:103140003C0608008CC60080000810820149182344
+:103150000002788000E370210000202101C3C82B09
+:1031600000C4C02101FA4021031948212502400072
+:1031700027BD00083C010800AC2E00843C0108007B
+:10318000AC29008003E00008000000008F820000EE
+:103190002486000730C5FFF800A2182130641FFF05
+:1031A00003E00008AF8400008F8700388F8A00405A
+:1031B00027BDFFB88F860044AFB60040AFBF0044C4
+:1031C000AFB5003CAFB40038AFB30034AFB200309D
+:1031D000AFB1002CAFB000288F4501048D4900AC81
+:1031E000AF4700808CC8002000A938230000B02120
+:1031F000AF480E108F440E1000004821AF440E144B
+:103200008CC20024AF420E188F430E18AF430E1C21
+:1032100010E001252D230001936B0008116000D4FC
+:1032200000000000976E001031CDFFFF00ED602B15
+:10323000158000CF0000000097700010320FFFFFD4
+:10324000AF4F0E008F520000325100081220FFFDD8
+:103250000000000097540E088F460E043285FFFFD1
+:1032600030B3000112600132000000000000000DC8
+:1032700030B8A04024150040131500C030A9A000AC
+:103280001120012D00000000937F000813E00008CA
+:103290000000000097630010306BFFFF00CB402B55
+:1032A0001100000330AC0040118001230000000039
+:1032B000A785003CAF8600349366000800E0282113
+:1032C000AFA7002014C0012427B30020AF60000C7A
+:1032D0009782003C3047400014E0000224030016AF
+:1032E0002403000E24194007A363000AAF790014D9
+:1032F000938A003E8F740014315800070018AA40CA
+:1033000002959025AF7200149784003C8F700014D2
+:103310003091001002117825AF6F0014978E003C99
+:1033200031CD000811A00147000028218F6700144B
+:103330003C0210003C0C810000E22825AF6500141F
+:1033400097460E0A2408000E3405FFFC30C3FFFF29
+:10335000006C5825AF6B0004A3680002937F000A3D
+:1033600027E90004A369000A9786003C9363000ADA
+:1033700030CC1F00000C598301634021251F002819
+:10338000A37F000997490E0CA769001093790009E3
+:10339000272A0002315800070018A82332B100077D
+:1033A000A371000B93740009976400108F9100348F
+:1033B000978F003C329200FF024480210205702169
+:1033C00031ED004011A0000531C4FFFF0091282B12
+:1033D0003C12800010A000140000A0210224382B11
+:1033E00014E0011B8FA500208F4D0E14AF4D0E1061
+:1033F0008F420E1CAF420E18AF440E008F4F0000DC
+:1034000031EE000811C0FFFD0000000097540E08C7
+:103410000080882100009021A794003C8F500E046A
+:1034200024140001AF900034976400103095FFFF22
+:103430008E6800000111F82317E00009AE7F00003C
+:103440008F6500148F8B004434A60040AF660014D3
+:103450008F4C0E10AD6C00208F430E18AD6300240E
+:103460009367000814E000D2000000000E00009EE8
+:10347000240400108F8900483C08320000402821B5
+:10348000312600FF0006FC0003E850252539000125
+:10349000AF990048AC4A0000937800099370000A85
+:1034A000330400FF00047400320F00FF01CF6825D1
+:1034B000AC4D00048F820048064000EAACA2000830
+:1034C000ACA0000C9783003C306B00081560000234
+:1034D0002628000626280002974E0E148F450E1C43
+:1034E0008F670004936D000231C4FFFF31A200FF1B
+:1034F000AFA200108F6C0014AFA800180E00008B54
+:10350000AFAC0014240400100E0000C7000000003F
+:103510008E72000016400005000000008F64001449
+:103520002405FFBF00859824AF7300148F79000C29
+:1035300003353821AF67000C9375000816A000080A
+:103540000000000012800006000000008F7F0014C1
+:103550003C0BEFFF3568FFFE03E84824AF69001419
+:10356000A37400088FA500200A0002460220202133
+:10357000AF470E000A0000F5000000008F590178E7
+:103580000720FFFE241F08008F840000AF5F017832
+:10359000974B008A316AFFFF014448232528FFFF2B
+:1035A00031021FFF2C4300081460FFF900000000E7
+:1035B0008F8E00488F8D003800C0482103442021A1
+:1035C00025C60001240C0F00AF86004800E938230F
+:1035D0002486400031CA00FF11AC00052408000118
+:1035E0009391003E3230000700107A4035E8000128
+:1035F000000AAC003C18010002B8A025AC944000C1
+:103600008F93004830B2003630A40008ACD30004D9
+:103610001080009701123025974E0E0A8F8D000002
+:103620003C02810031CCFFFF25AB00080182402520
+:103630003C03100031651FFF25390006241F000ED2
+:10364000AF48016000C33025A75F015AAF85000075
+:10365000A759015814E0000A8F93003824120F0074
+:10366000527200022416000134C600408F580E101A
+:103670008F940044AE9800208F550E18AE9500240C
+:103680008F450E14AF4501448F590E1CAF590148A8
+:10369000A34A01523C0A1000AF460154AF4A0178D8
+:1036A00014E0FEDD2D2300010076A0251280001716
+:1036B0008FBF00448F84003824160F0010960084BA
+:1036C000000000008F45017804A0FFFE24150F00C4
+:1036D0001095006E000000008F470E142402024077
+:1036E0003C1F1000AF4701448F440E1CAF440148FB
+:1036F000A3400152A740015AAF400160A7400158C2
+:10370000AF420154AF5F01788FBF00448FB60040D5
+:103710008FB5003C8FB400388FB300348FB20030C7
+:103720008FB1002C8FB0002803E0000827BD0048AF
+:1037300014C0FED030B8A0408F420E148F840044D5
+:1037400000004821AC8200208F510E1CAC91002457
+:103750000A00020E2D2300018F910034978A003C4D
+:103760003C1280000220A821315800401700FF3091
+:103770000000A021976900108F9200343139FFFFBB
+:103780001332003500002021008048211480FEA063
+:1037900000A038218F420E148F840044AC82002098
+:1037A0008F510E1CAC9100240A00020E2D23000143
+:1037B000936A00099378000B315000FF330F00FF2C
+:1037C000020F702125C2000A3050FFFF0E00009E3C
+:1037D000020020218F8600483C1F410024CD0001BB
+:1037E000AF8D0048936C000930C600FF000644000E
+:1037F000318300FF246B0002010B4825013FC825DF
+:10380000AC5900008F67000C97440E1400F2282575
+:10381000AC4500048F450E1C8F670004936A0002BC
+:103820003084FFFF315800FFAFB800108F6F0014D5
+:10383000AFB100180E00008BAFAF00140A0001A654
+:1038400002002021AF6000040A00013EA3600002D4
+:103850000A00024600002021000090210A000170A9
+:10386000241400013C1280000A000195ACB2000C47
+:103870008F91000025240002A7440158263000083B
+:10388000320F1FFF0A0001F9AF8F0000AF40014C5B
+:103890001120002C000000008F590E10AF59014478
+:1038A0008F430E18240200403C1F1000AF43014814
+:1038B000A3400152A740015AAF400160A740015800
+:1038C000AF420154AF5F01780A0002278FBF004466
+:1038D000112000060000000097460E0830CC004082
+:1038E00015800002000000000000000D8F4D0178DF
+:1038F00005A0FFFE0000000097530E103C120500CB
+:10390000240E2000326AFFFF0152C025AF58014C3F
+:103910008F4F0E143C021000AF4F01448F500E1C0D
+:10392000AF500148A34001528F840038A740015A8C
+:10393000AF400160A7400158AF4E01540A00021584
+:10394000AF4201788F490E14AF4901448F430E1CDA
+:103950000A00028E240200403C0E20FF27BDFFE03B
+:103960003C1A80003C0F800835CDFFFDAFBF001C26
+:10397000AFB20018AFB10014AFB00010AF8F00406D
+:10398000AF4D0E000000000000000000000000002D
+:1039900000000000000000003C0C00FF358BFFFD24
+:1039A000AF4B0E003C0660048CC95000240AFF7F18
+:1039B0003C116000012A40243507380CACC7500088
+:1039C0008E24043824050009AF4500083083FFFF2A
+:1039D00038622F712450C0B3AF8000480E000068D9
+:1039E000AF80000052000001AE20442C0E000435D0
+:1039F0003C1180000E000ED9363000708F8A0040D6
+:103A00003C12080026523C88020088218E080000E3
+:103A10008F5F00003BF900013338000113000017ED
+:103A2000AF880030022048218D2700003C0F08009D
+:103A30008DEF006C3C0C08008D8C006800E8C02302
+:103A400001F828210000682100B8302B018D582191
+:103A5000016640213C010800AC25006C3C010800D7
+:103A6000AC2800688F4400003883000130620001F8
+:103A70001440FFED00E04021AF8700308E0C0000C5
+:103A80003C0508008CA5006C3C0408008C84006890
+:103A90000188302300A638210000102100E6402BC9
+:103AA000008218210068F8213C010800AC27006C56
+:103AB0003C010800AC3F00688F490100255900888F
+:103AC000AF990044AF890038AF4900208E0700004D
+:103AD000AF8700308F4D017805A0FFFE0000000089
+:103AE0008E0600003C0B08008D6B00743C0408003F
+:103AF0008C84007000C728230165F8210000102184
+:103B000003E5402B0082382100E8C8212409080081
+:103B10003C010800AC3F00743C010800AC39007067
+:103B2000AF49017893580108A398003E938F003E57
+:103B300031EE000115C000158F830038240E0D00F2
+:103B4000106E0019240F0F00106F001D0000000000
+:103B50009159000024180050332900FF1138000447
+:103B60003C1F4000AF5F01380A0002E70000000080
+:103B70000E00090E000000008F8A00403C1F40002C
+:103B8000AF5F01380A0002E700000000938D003E9D
+:103B900031AC0006000C51000E0000CE0152D821BD
+:103BA0000A0003438F8A00403C1B0800277B3D0826
+:103BB0000E0000CE000000000A0003438F8A004080
+:103BC0003C1B0800277B3D280E0000CE00000000B3
+:103BD0000A0003438F8A004090AA00018FAB0010B7
+:103BE0008CAC00103C0300FF8D680004AD6C00201D
+:103BF0008CAD001400E060213462FFFFAD6D002445
+:103C00008CA700183C09FF000109C024AD670028FB
+:103C10008CAE001C0182C82403197825AD6F000406
+:103C2000AD6E002C8CAD0008314A00FFAD6D001C5C
+:103C300094A900023128FFFFAD68001090A7000092
+:103C4000A5600002A1600004A167000090A300022B
+:103C5000306200FF00021982106000052405000197
+:103C60001065000E0000000003E00008A16A0001DA
+:103C70008CD80028354A0080AD7800188CCF00140D
+:103C8000AD6F00148CCE0030AD6E00088CC4002CDB
+:103C9000A16A000103E00008AD64000C8CCD001C9B
+:103CA000AD6D00188CC90014AD6900148CC80024D7
+:103CB000AD6800088CC70020AD67000C8CC20014F2
+:103CC0008C8300640043C82B132000070000000011
+:103CD0008CC20014144CFFE400000000354A008040
+:103CE00003E00008A16A00018C8200640A000399C5
+:103CF0000000000090AA000027BDFFF88FA9001C5B
+:103D0000A3AA00008FAE00003C0FFF808FA8001810
+:103D100035E2FFFF8CCD002C01C26024AFAC000067
+:103D2000A120000400E06021A7A000028FB80000DD
+:103D30008D2700040188182100A0582100C05021BF
+:103D4000006D28263C06FF7F3C0F00FF2CAD0001D4
+:103D500035EEFFFF34D9FFFF3C02FF00031930248A
+:103D6000000D1DC0010EC82400E2C02400C3702550
+:103D700003197825AD2E0000AD2F00048D450024D9
+:103D8000AFAE0000AD2500088D4D00202405FFFFDB
+:103D9000AD2D000C956800023107FFFFAD27001024
+:103DA0009166001830C200FF000219C25060000185
+:103DB0008D450034AD2500148D67000827BD00082F
+:103DC000AD27001C8C8B00CCAD2C0028AD20002C26
+:103DD000AD2B0024AD20001803E00008AD2000202A
+:103DE00027BDFFE0AFB20018AFB10014AFB00010B4
+:103DF000AFBF001C9098000000C088213C0D00FF60
+:103E0000330F007FA0CF0000908E000135ACFFFF84
+:103E10003C0AFF00A0CE000194A6001EA2200004D0
+:103E20008CAB00148E29000400A08021016C282492
+:103E3000012A40240080902101052025A6260002A9
+:103E4000AE24000426050020262400080E0000767B
+:103E500024060002924700002605002826240014AC
+:103E600000071E000003160324060004044000039C
+:103E70002403FFFF965900023323FFFF0E00007654
+:103E8000AE230010262400248FBF001C8FB2001820
+:103E90008FB100148FB00010240500030000302102
+:103EA0000A00008027BD002027BDFFD8AFB1001C4D
+:103EB000AFB00018AFBF002090A80000240200019E
+:103EC0008FB0003C3103003F008088211062001455
+:103ED0008FAA0038240B0005506B0016AFAA001003
+:103EE00000A0202100C028210E0003DC02003021A8
+:103EF000922400BC308300021060000326060030CC
+:103F0000ACC0000024C600048FBF00208FB1001C8D
+:103F10008FB0001800C0102103E0000827BD002862
+:103F2000014038210E00035AAFB000100A000420EF
+:103F3000000000000E0003A1AFB000140A0004202E
+:103F4000000000003C02000A034218213C04080063
+:103F500024843D6C2405001A000030210A000080F2
+:103F6000AF8300543C038000346200708C48000032
+:103F700000A0582100C04821308A00FFAF880030DF
+:103F80008F4401780480FFFE3C0C80003586007071
+:103F90008CC500003C0308008C6300743C180800CA
+:103FA0008F18007000A82023006468210000C82139
+:103FB00001A4782B0319702101CF60213C01080076
+:103FC000AC2D00743C010800AC2C00708F480E141E
+:103FD000AF480144AF47014CA34A0152A74B0158D7
+:103FE0009346010830C5000854A00001352910008F
+:103FF000934B090024070050316A00FF1147000766
+:10400000000000008F450E1CAF450148AF49015428
+:104010003C09100003E00008AF490178934D010806
+:1040200031A800081100001000000000934F0108A3
+:1040300031EE001051C00001352900083C04080091
+:1040400090843DD0A34401508F4309A4AF4301485D
+:104050008F4209A0AF420144AF4901543C0910000E
+:1040600003E00008AF4901783C1908008F393D8C06
+:10407000333800085700FFF1352900080A0004739F
+:104080000000000024070040AF470814AF400810AC
+:104090008F4209448F4309508F4409548F45095C6E
+:1040A0008F46094CAF820064AF830050AF84004C50
+:1040B000AF85005C03E00008AF860060934601090D
+:1040C00030C5007F000518C0000521400083102185
+:1040D00003E00008244200883C09080091293D9132
+:1040E00024A800023C05110000093C0000E830252E
+:1040F00000C5182524820008AC83000003E00008F6
+:10410000AC8000049347010B8F4A002C974F09089D
+:104110003C18000E0358482131EEFFFF000E41C04D
+:10412000AF48002C97430908952C001A00804021C5
+:1041300024030001318BFFFFAC8B00008D2D001C90
+:1041400000A0582100C06021AC8D00048D24002007
+:1041500030E70040AD04000891220019304400030C
+:10416000108300482885000214A000622406000283
+:104170001086005624190003109900660000000004
+:1041800010E0003A000000003C07080094E73D867C
+:1041900024E20001934F0934934709219525002A11
+:1041A00031EE00FF000E488230ED00FF9787005887
+:1041B00000093600000D1C003044FFFF00C310252D
+:1041C0000044C02500A778213C1940000319702540
+:1041D000000F4C00AD090004AD0E0000934D092006
+:1041E0003C03000625090014000D360000C32025FD
+:1041F000AD0400088F59092C24E5000130A27FFF8F
+:10420000AD19000C8F580930A782005825020028EC
+:10421000AD1800108F4F0938AD0F0014AD2B0004FE
+:104220008F4E0940AD2E0008934D09373C0508001C
+:1042300090A53D908F4409488F46094031A700FF63
+:1042400000EC1821008678230003C7000005CC008D
+:104250000319602531E8FFFC01885825AD2B000CBF
+:10426000AD20001003E00008AF4A002C3C0D080010
+:1042700095AD3D863C0E080095CE3D800A0004C9F0
+:1042800001AE10213C05080094A53D8A3C060800BB
+:1042900094C63D803C18080097183D7C952E00245C
+:1042A00000A6782101F86823000E240025A2FFF261
+:1042B0000082182524190800AD03000CAD19001464
+:1042C000AD0000100A0004C425080018952600243B
+:1042D000952500280006C40000057C00370E8100EB
+:1042E00035ED0800AD0E000CAD0D00100A0004C441
+:1042F000250800141480FFA200000000952400246B
+:104300000004140034430800AD03000C0A0004C488
+:10431000250800103C03080094633D8A3C05080012
+:1043200094A53D803C06080094C63D7C9539002448
+:1043300095380028006520210086782300196C003C
+:104340000018740025E2FFEE01C2202535A381008C
+:1043500024190800AD03000CAD040010AD190018BD
+:10436000AD0000140A0004C42508001C03E0000886
+:10437000240201F427BDFFE8AFB00010AFBF001466
+:104380000E0000600080802124050040AF45081425
+:104390008F8300508F84004C8F85005C0070182143
+:1043A0000064102318400004AF830050AF63005432
+:1043B0008F660054AF86004C1200000C0000000015
+:1043C0008F440074936800813409FA002D070007B8
+:1043D00010E0000500891021936C0081240B01F48A
+:1043E000018B500401441021AF62000C8F4E095C18
+:1043F00001C5682319A000048FBF00148F4F095C0A
+:10440000AF8F005C8FBF00148FB000100A000062F5
+:1044100027BD00188F8400648F8300508F82004C6A
+:10442000AF640044AF63005003E00008AF62005483
+:104430003C038000346200708C43000027BDFFF80D
+:10444000308700FF30A900FF30C800FFAF83003085
+:104450008F4401780480FFFE3C02800034590070D4
+:104460008F380000A3A700033C0708008CE7007406
+:104470008FAC00003C0608008CC600700303782354
+:104480003C0E7FFF00EFC82135CDFFFF000050211B
+:10449000018D282400CA1821000847C0032F202BB3
+:1044A00000A810250064C021AFA200003C01080054
+:1044B000AC3900743C010800AC380070934F010A1D
+:1044C000A3A000023C0E80FFA3AF00018FAC000050
+:1044D000312B007F35CDFFFF018D4824000B5600A6
+:1044E000012A4025240730002406FF803C051000E7
+:1044F00027BD0008AF48014CAF470154A740015801
+:10450000A346015203E00008AF45017827BDFFE84C
+:10451000AFBF0014AFB000108F6500743C06800080
+:10452000309000FF00A620250E000060AF640074EC
+:1045300093630005346200080E000062A362000568
+:10454000020020218FBF00148FB000102405000549
+:10455000240600010A00057027BD001827BDFFE0F2
+:104560003C038000AFB00010AFBF0018AFB1001423
+:10457000346200708C470000309000FF30A800FFCC
+:10458000AF8700308F4401780480FFFE3C18800024
+:10459000371100708E2F00003C0D08008DAD0074A7
+:1045A0003C0A08008D4A007001E7702301AE282103
+:1045B0000000582100AE302B014B48210126382144
+:1045C0003C010800AC250074000088213C01080073
+:1045D000AC2700701100000F000000008F62007413
+:1045E0002619FFFF3208007F0002FE0233E5007F3C
+:1045F00015000006332200FF2407FF800207202653
+:1046000024A3FFFF00838025320200FF00408021A9
+:10461000241110080E000060000000008F490818E7
+:104620003125000414A0FFFD3218007F001878C067
+:104630000018714001CF682125AC0088AF4C0818E4
+:10464000274A09808D4B0020AF4B01448D46002442
+:10465000AF460148A35001500E000062A740015828
+:10466000022010218FBF00188FB100148FB00010EE
+:1046700003E0000827BD002027BDFFE8308400FFCD
+:10468000AFBF00100E0005BB30A500FF8F830050A8
+:104690008FBF0010344500402404FF903C021000FE
+:1046A00027BD0018AF43014CA3440152AF4501544C
+:1046B00003E00008AF4201789343093E30620008EE
+:1046C0001040000D3C0901013528080AAC880000A3
+:1046D0008F470074AC8700043C06080090C63D90EC
+:1046E00030C5001050A00006AC8000088F6A006042
+:1046F000AC8A00082484000C03E00008008010212C
+:104700000A0006222484000C27BDFFE8AFBF001476
+:10471000AFB000109346093F00A05021000528804B
+:104720000085382330C200FF240300063C0908003E
+:1047300095293D8624E8FFD824050004104300375E
+:10474000240600029750093C3C0F02040006340086
+:10475000320EFFFF01CF6825AC8D0000934C093E5F
+:10476000318B0020116000080000000093430936DF
+:104770003C020103345F0300307900FF033FC02592
+:1047800024050008AC980004934309349359092187
+:104790000005F882306200FF0002C082332F00FF64
+:1047A00000186E00000F740001AE602501892025FD
+:1047B0003C09400000898025ACF0FFD893430937BD
+:1047C0008F4F09488F580940306200FF004AC821C6
+:1047D000033F702101F86023000E6F0001A65025F1
+:1047E0003185FFFC001F58800145482501683821AC
+:1047F000AD0900200E00006024F00028240400040D
+:104800000E000062A364003F020010218FBF00145D
+:104810008FB0001003E0000827BD00180A0006351D
+:104820002406001227BDFFD024090010AFB60028CF
+:10483000AFB50024AFB40020AFB10014AFB000108A
+:104840003C010800A0293D90AFBF002CAFB3001C75
+:10485000AFB2001897480908309400FF3C02000EE0
+:104860003107FFFF000731C0AF46002C974409080D
+:104870009344010B30B500FF0342802130830030A8
+:104880000000B0211060012500008821240C0004E4
+:104890003C010800A02C3D90934B093E000B5600B4
+:1048A000000A2E0304A0016000000000AF40004891
+:1048B000934F010B31EE002011C0000600000000F4
+:1048C0009358093E00189E00001396030640018984
+:1048D000000000009344010B30830040106000038F
+:1048E0008F9300508F8200502453FFFF9347093E5F
+:1048F00030E6000814C000022412000300009021DA
+:104900009619002C93580934934F0937A7990058EA
+:10491000330C00FF31EE00FF024E6821000D58807D
+:10492000016C5021015140213C010800A4283D8622
+:104930009205001830A900FF010918213C01080068
+:10494000A4233D88921100181620000200000000E8
+:104950000000000D3C010800A4233D8A3C01080032
+:10496000A4203D803C010800A4203D7C935F010B06
+:104970003063FFFF33F00040120000022464000A9D
+:104980002464000B3091FFFF0E00009E02202021C6
+:104990009358010B3C08080095083D8A00402021EF
+:1049A00000185982316700010E00049A010728217E
+:1049B000934C010B8F4B002C974E09083C0F000EB7
+:1049C000034F402131CDFFFF000D51C0AF4A002CF5
+:1049D000974309089505001A004038212404000176
+:1049E00030A9FFFFAC4900008D06001C00404821A3
+:1049F000318A0040AC4600048D020020ACE2000881
+:104A00009103001930630003106400EC2879000260
+:104A100017200118241000021070010C241F00033D
+:104A2000107F011E00000000114000DE00000000A9
+:104A30003C09080095293D8625220001935F093431
+:104A4000934E09219504002A33F900FF0019C08212
+:104A500031CF00FF978E005800184600000F6C0001
+:104A6000010D80253045FFFF02051025008E5021E5
+:104A70003C03400000433025000A6400ACEC000415
+:104A8000ACE60000935F09203C19000624EC0014FA
+:104A9000001FC60003197825ACEF00088F48092CC9
+:104AA00025CD000131A57FFFACE8000C8F50093007
+:104AB000A785005824E80028ACF000108F4409387E
+:104AC00001008021ACE40014AD9300048F53094031
+:104AD000AD930008934A09373C19080093393D907B
+:104AE0008F4309488F460940314200FF0052F821A8
+:104AF00000667023001F7F000019C40001F82825FC
+:104B000031CDFFFC00AD2025AD84000CAD80001040
+:104B1000AF4B002C934B093E317300081260000D1F
+:104B20003C06010134CC080AACEC00288F53007419
+:104B3000AD1300043C0B0800916B3D9031670010F1
+:104B400050E00003AD0000088F6A0060AD0A000865
+:104B50002510000C12C0003D000000009343093FE7
+:104B60002416000624060004306200FF105600C917
+:104B7000240700029758093C3C0F0204330DFFFF45
+:104B800001AF4025AE0800009345093E30A4002047
+:104B90001080000800000000935309363C0B01030D
+:104BA000357F0300327900FF033F7025AE0E00040D
+:104BB00024060008934F093493480921312AFFFF46
+:104BC00031ED00FF000D1082310300FF0002B6003E
+:104BD00000032C0002C56025018A98250012208060
+:104BE0003C0940000204502302695825AD4BFFD810
+:104BF000935F09378F4F09488F58094033F900FFF9
+:104C0000033270210006B08201D6682100074400FB
+:104C100001F82823000D1F000068302530A2FFFC9A
+:104C20002547FFD800C26025001680800207482172
+:104C3000ACEC0020253000280E0000602412000497
+:104C4000A372003F0E000062000000009347010BBA
+:104C500030F20040124000053C1900FF8E180000A1
+:104C6000372EFFFF030E3024AE0600000E0000C7F3
+:104C7000022020213C10080092103D9032110003C8
+:104C80001220000F02A028218F8900502533000137
+:104C9000AF930050AF7300508F6B00540173F82333
+:104CA0001BE00002026020218F640054AF640054B6
+:104CB0008F4C0074258401F4AF64000C02A02821FD
+:104CC00002802021A76000680E0005BB3C14100084
+:104CD0008F85005034550006AF45014C8F8A00483F
+:104CE0008FBF002C8FB3001C25560001AF960048E3
+:104CF0008FB20018A34A01528FB60028AF55015455
+:104D00008FB10014AF5401788FB500248FB4002008
+:104D10008FB0001003E0000827BD00309358093E13
+:104D200000189E000013960306420036241100026C
+:104D300093440923308300021060FEDD8F860060FB
+:104D40008F82005014C2FEDA000000000E000060E6
+:104D5000000000009369003F24070016312800FF7F
+:104D60001107000C240500083C0C0800918C3D90B4
+:104D7000358B00013C010800A02B3D90936A003F59
+:104D8000314300FF10650065240D000A106D005EC0
+:104D90002402000C0E000062000000000A000690D1
+:104DA000000000003C09080095293D863C0A0800E7
+:104DB000954A3D800A0006F3012A10213C090800AB
+:104DC00095293D8A3C04080094843D803C060800F7
+:104DD00094C63D7C95030024012410210046F8234D
+:104DE0000003CC0027F0FFF20330C025240F080099
+:104DF000ACF8000CACEF0014ACE000100A0006EEBA
+:104E000024E700183C010800A0313D90935F093E63
+:104E10002416000133F900201720FEA524110008F4
+:104E20000A000690241100048F6E00848F4D094003
+:104E300011A0FE9EAF8E0050240F00143C0108000C
+:104E4000A02F3D900A00068F00000000950E002460
+:104E5000950D0028000E6400000D2C00358981009E
+:104E600034A60800ACE9000CACE600100A0006EE1F
+:104E700024E700141460FEEC0000000095020024FA
+:104E800000021C0034640800ACE4000C0A0006EECA
+:104E900024E700100A000741240700123C02080022
+:104EA00094423D8A3C06080094C63D803C030800BD
+:104EB00094633D7C95100024951900280046F82144
+:104EC00003E3C02300106C0000197400270FFFEEED
+:104ED00001CF282535AC8100ACEC000CACE500100E
+:104EE00024070800AD2700182527001C0A0006EE3D
+:104EF000AD2000148F7F004CAF7F00548F79005499
+:104F00000A000699AF790050A362003F0E000062CC
+:104F1000000000000A0006900000000024020014B7
+:104F20000A000827A362003F27BDFFE8308400FF86
+:104F3000AFBF00100E0005BB30A500FF9378007EC8
+:104F40009379007F936E00809368007A332F00FF7F
+:104F500000186600000F6C0031CB00FF018D482562
+:104F6000000B52008FBF0010012A3825310600FFC8
+:104F70003444700000E628252402FF813C03100021
+:104F800027BD0018AF45014CAF440154A342015264
+:104F900003E00008AF43017827BDFFD8AFB2001887
+:104FA000AFB10014AFB00010AFBF0020AFB3001C12
+:104FB00093420109308600FF30B000FF000618C29E
+:104FC000320400023071000114800005305200FFED
+:104FD0009367000530E5000810A0000D30C80010F0
+:104FE000024020210E0005A70220282124040001F0
+:104FF0008FBF00208FB3001C8FB200188FB1001438
+:105000008FB000100080102103E0000827BD0028A9
+:105010001500003200000000934301090000282120
+:105020003062007F000220C00002F94003E49821B2
+:1050300026790088033B98218E7800248E6F000823
+:10504000130F0046000000008F6400842418000243
+:105050000004FD8233F900031338007C00000000D7
+:1050600093660083934A0109514600043205007C8F
+:1050700010A00060000000003205007C14A0005366
+:105080000240202116200006320400018E7F0024F9
+:105090008F59010417F9FFD60000202132040001C6
+:1050A0001080000A024020218F4209408F93006443
+:1050B00010530006000000000E00066D022028219B
+:1050C0008F430940AF630044024020210E000602D6
+:1050D000022028210A000860240400013C0908007D
+:1050E0008D290064252600013C010800AC260064DF
+:1050F00016000012000000008F6D00843C0E00C0FE
+:1051000001AE602415800005024020210E00082E0B
+:10511000022028210A00086024040001240500045C
+:105120000E00057024060001024020210E00082E0A
+:10513000022028210A000860240400010E0000411A
+:1051400024040001936B007D020B50250E000062C9
+:10515000A36A007D0A0008A38F6D00848F66007427
+:105160008F4801048E67002400064E021507FFB623
+:105170003126007F936B008326440001308A007F34
+:1051800011460043316300FF5464FFB08F64008414
+:105190002645000130B1007F30A200FF1226000436
+:1051A00024050001004090210A0008762411000126
+:1051B000240FFF80024F702401CF9026324200FF5F
+:1051C000004090210A000876241100010E00066DAF
+:1051D00002202821321800301300FFAA321000826A
+:1051E000024020210E0005A7022028210A000860A5
+:1051F000240400018F6E00743C0F8000240500031E
+:1052000001CF9025AF7200749371008324060001D2
+:105210000E000570322400FF0E000041240400013E
+:10522000936D007D020D60250E000062A36C007D71
+:105230003C0B08008D6B0054257000013C010800F8
+:10524000AC3000540A000860240400018F68007428
+:105250003C0980002405000401093825AF6700746B
+:1052600093630083240600010E000570306400FF84
+:105270000E000041240400019362007D0202982583
+:105280000E000062A373007D0A0008602404000180
+:10529000324D008039AC0080546CFF6C8F64008408
+:1052A0000A0008C92645000127BDFFC83C0A0008BE
+:1052B000AFBF0030AFB5002CAFB40028AFB30024AF
+:1052C000AFB20020AFB1001CAFB00018034AD82124
+:1052D00024090040AF490814AF4008108F42094428
+:1052E0008F4309508F4609548F47095C8F48094CFA
+:1052F000934401089345010BAF820064308400FFA2
+:1053000030A500FFAF830050AF86004CAF87005C34
+:105310000E00084AAF8800601440017D8FBF003046
+:10532000A7600068934D0900240B00503C1508004D
+:1053300026B53D4831AC00FF3C12080026523D58CE
+:10534000118B0003000000000000A8210000902144
+:10535000935101098F9F005024040010322E007FCA
+:10536000000E68C0000E6140018D282124B4008821
+:10537000AF5408188F4901048F4A09A43C0B000E52
+:10538000034BC021012A10233C010800AC223D6CD4
+:105390008F4309583C010800A0243D909747090815
+:1053A000007F30233C010800AC263D7030E8FFFF51
+:1053B0000008C9C03C010800AC3F3D94AF59002C27
+:1053C000974209089710002C8EB10000930F001827
+:1053D00003749821A7900058AF9300440220F80965
+:1053E00031F000FF304E000215C001B2304F000115
+:1053F00011E0014F000000009343093E30660008B1
+:1054000014C00002241400030000A0218F5809A436
+:10541000241300013C010800AC383D98934F093437
+:105420009351093731EC00FF322E00FF028E6821C4
+:10543000000D288000AC5021015058213C0108008B
+:10544000A42B3D883C010800A42A3D8693490934D9
+:10545000312200FF02022021249000103C010800AC
+:10546000A4303D84240700068F9F00503C010800B3
+:10547000AC273D8C8F88005C8F5909580000802133
+:10548000011F282304A00149033F20230480014772
+:1054900000A4302B10C00149000000003C010800AE
+:1054A000AC253D708E4200000040F809000000006D
+:1054B00030430002146000F80040882130440001AD
+:1054C000548000108E4200043C0908008D293D7470
+:1054D0003C0AC000012A8025AF500E008F45000015
+:1054E00030AB00081160FFFD00000000974D0E0872
+:1054F00024100001A78D003C8F4C0E04AF8C0034AB
+:105500008E4200040040F8090000000002228825B5
+:10551000322E000215C00180000000003C09080086
+:1055200095293D7C3C06080094C63D883C0A08004D
+:10553000954A3D7E3C1908008F393D740126602153
+:105540003C1808008F183D983C03080094633D9276
+:10555000018A20218F4E09400329F821248F00025F
+:1055600003E32821031968213C010800A42C3D8A8B
+:10557000AF8E00643C010800AC2D3D983C01080052
+:10558000A4253D800E00009E31E4FFFF8F87004878
+:10559000004020213C010800A0273D918E420008D8
+:1055A00024E80001AF8800480040F809000000002E
+:1055B0009344010B8F4C002C974A09083C0B000EBA
+:1055C000034B40213149FFFF000919C08F8B005068
+:1055D000AF43002C974309089506001A0040382174
+:1055E000308A004030DFFFFFAC5F00008D19001CE7
+:1055F00000404821AC5900048D180020AC58000828
+:10560000910F001931E30003107300F00000000057
+:10561000286200021440010924050002106500FD03
+:10562000240D0003106D010D00000000114000D991
+:10563000000000003C0A0800954A3D862542000112
+:10564000934D093493580921950E002A31A300FF88
+:1056500000032082331F00FF9798005800047E004B
+:10566000001FCC0001F940253049FFFF010910253A
+:1056700001D830213C0540000045502500066C0053
+:10568000ACED0004ACEA0000934309203C040006A2
+:1056900024ED00140003FE0003E4C825ACF9000863
+:1056A0008F49092C270F000131EE7FFFACE9000C78
+:1056B0008F480930A78E005824E90028ACE8001074
+:1056C0008F45093801204021ACE50014ADAB000442
+:1056D0008F420940ADA20008934B09373C1F0800D8
+:1056E00093FF3D908F4309488F4A0940316600FF80
+:1056F00000D42021006A78230004C700001FCC00DA
+:105700000319282531EEFFFC00AE1025ADA2000CD8
+:10571000ADA00010AF4C002C934C093E318B00081B
+:105720005160000F8E58000C3C06010134CA080A73
+:10573000ACEA00288F4B0074AD2B00043C0C080031
+:10574000918C3D903187001050E00003AD2000089F
+:105750008F620060AD2200082528000C8E58000CD6
+:105760000300F809010020213C19080097393D8AFF
+:105770003C1F080097FF3D7E033F782125E900028A
+:105780000E0000C73124FFFF3C0E08008DCE3D6C9B
+:105790003C0808008D083D7401C828233C0108001E
+:1057A000AC253D6C14A00006000000003C0308007E
+:1057B0008C633D8C346400403C010800AC243D8C7B
+:1057C000120000708F8C00448F470E108F900044A1
+:1057D000AE0700208F4D0E18AE0D00243C100800BF
+:1057E00096103D800E000060000000002402004082
+:1057F000AF4208148F8600508F8A004C00D01821C9
+:10580000006A582319600004AF830050AF6300544E
+:105810008F650054AF85004C1200000C00000000A2
+:105820008F440074936800813409FA002D0E00073C
+:1058300011C0000500891821937F0081241901F40B
+:1058400003F9780401E41821AF63000C8F44095C6C
+:105850008F83005C0083C0231B0000030000000056
+:105860008F50095CAF90005C0E00006200000000E9
+:105870008F8C00508E4700103C010800AC2C3D94EA
+:1058800000E0F809000000003C0D08008DAD3D6C03
+:1058900055A0FEF5240700068F45002497590908F6
+:1058A0008F8B00648F9400503C0F001F978200582C
+:1058B0008F8600548F93004C3328FFFF35E9FF801B
+:1058C00000A95024000871C032320100AF4E0024FC
+:1058D000A4C2002CAF4A0024AF6B0044AF74005048
+:1058E000AF73005416400080323800105700008615
+:1058F0008EA40004322300405460001B8EB10008C7
+:105900008EB0000C0200F809000000008FBF0030CC
+:105910008FB5002C8FB400288FB300248FB20020E5
+:105920008FB1001C8FB0001803E0000827BD0038BD
+:10593000934701098F8800380007FE0003E8C82557
+:10594000AF5900808F5809A08F5309A4AFB8001039
+:10595000AF580E148FB40010AF540E10AF530E1C7E
+:105960000A000962AF530E180220F8090000000077
+:105970008EB0000C0200F809000000000A000AA81E
+:105980008FBF0030A5800020A59300220A000A5B8B
+:10599000AD9300243C09080095293D863C0608008B
+:1059A00094C63D800A0009F4012610213C0108003C
+:1059B000AC203D700A00098E8E4200003C010800B8
+:1059C000AC243D700A00098E8E4200003C030800A2
+:1059D00094633D8A3C04080094843D803C1F080089
+:1059E00097FF3D7C951800240064C821033F78236D
+:1059F00000186C0025EEFFF201AE2825AC45000C26
+:105A000024020800ACE20014ACE000100A0009EF28
+:105A100024E70018950600249509002800062400B4
+:105A200000091C00349F810034790800ACFF000C91
+:105A3000ACF900100A0009EF24E700141460FEFB23
+:105A4000000000009518002400187C0035EE0800C6
+:105A5000ACEE000C0A0009EF24E700103C07080038
+:105A600094E73D803C04080094843D8A3C03080090
+:105A700094633D7C95190024951800280087F8212F
+:105A800003E378232407080000192C0000186C0099
+:105A900025EEFFEE01AE302534A28100AD270018BF
+:105AA0002527001CAD22000CAD2600100A0009EFCE
+:105AB000AD20001493520109000028210E000602B7
+:105AC000324400FF8FBF00308FB5002C8FB4002808
+:105AD0008FB300248FB200208FB1001C8FB000184C
+:105AE00003E0000827BD0038935F010933E400FF9D
+:105AF0000E00066D00002821323800105300FF7E92
+:105B0000322300408EA400040080F8090000000049
+:105B10000A000AA2322300401200FF5F00000000CA
+:105B20008F540E148F920044AE5400208F530E1CDD
+:105B30000A000A8AAE5300248F82001C0080402194
+:105B40003C0401009047008530E30020106000090C
+:105B5000000000003C0708008CE73D948F8300188C
+:105B600000E32023048000089389000414E3000369
+:105B70000100202103E00008008010213C04010006
+:105B800003E00008008010211120000B006738237B
+:105B90008F8C002024090034918B00BC316A0002F4
+:105BA000514000012409003000E9682B15A0FFF1E5
+:105BB0000100202100E938232419FFFC00B9C0248A
+:105BC00000F9782400F8702B15C0FFEA01E82021C5
+:105BD00030C200030002182314C000123069000311
+:105BE0000000302100A9702101C6682100ED602B62
+:105BF0001180FFE03C0401002D2F00010006482B1E
+:105C00000105382101E9302414C0FFDA24E4FFFC47
+:105C10002419FFFC00B9C0240308202103E0000878
+:105C2000008010218F8B002024060004916A00BCA4
+:105C3000314400041480FFEC00A970210A000B5EBF
+:105C40000000302127BDFFE8AFBF00108F460100E4
+:105C5000934A01093C1F08008FFF00902407FF8032
+:105C6000314F00FF31E8007F0008614003E6C821A2
+:105C7000032CC02127090120012770243C010800C2
+:105C8000A02F3DD0AF4E080C3C0D08008DAD00900C
+:105C90003C0400803482000301A65821016C1821C5
+:105CA0002465012030AA007801424025AF48081C35
+:105CB0003C1F08008FFF00908F88004003E6C02142
+:105CC0003319000703074824033A7821AF49002815
+:105CD00025E909C0952E00023C0D08008DAD008C11
+:105CE0003C0A08008D4A009031CC3FFF01A61821E4
+:105CF000000C5980006B282100A72024AF44002C01
+:105D0000952200023C1F08008FFF008C9107008540
+:105D100030593FFF03E678210019C1800146702108
+:105D200001F8682131CC007F31AB007F019A282136
+:105D3000017A50213C03000C3C04000E00A32821F2
+:105D40000144102130E6002027470980AF82002C53
+:105D5000AF88001CAF890024AF85002010C000066A
+:105D6000AF8700288D0200508CA4010C0044302322
+:105D700018C0007700000000910C0085240DFFDFA3
+:105D8000018D3824A10700858F8B001C8F8900248A
+:105D90008F8700288D65004CAF850018912F000D6E
+:105DA00031EE002011C0001700000000240900019E
+:105DB000A3890004AF80000C8CE400248F85000CC4
+:105DC000240A0008AF800008AF8000103C010800E2
+:105DD000A42A3D7E3C010800A4203D920E000B3217
+:105DE000000030218F8500248FBF0010AF82001487
+:105DF00090A8000D27BD00180008394203E00008F4
+:105E000030E20001913F00022418000133F900FF45
+:105E10000019218210980039240800021088005BC4
+:105E20008F86002C8CE5002414A0001B8F9F00207F
+:105E300091220000240A00053046003F10CA0047A6
+:105E4000240400018F860008A3840004AF8600109C
+:105E5000AF86000C8CE400248F85000C240A000817
+:105E60003C010800A42A3D7E3C010800A4203D928C
+:105E70000E000B32000000008F8500248FBF001041
+:105E8000AF82001490A8000D27BD00180008394209
+:105E900003E0000830E200018CF800088CF90024CF
+:105EA0008FEE00C4A38000048CE40024AF8E000CAD
+:105EB0008F85000C8F86000803197823240A0008B8
+:105EC000AF8F00103C010800A42A3D7E3C01080071
+:105ED000A4203D920E000B32000000008F850024AC
+:105EE0008FBF0010AF82001490A8000D27BD0018CE
+:105EF0000008394203E0000830E20001912300006D
+:105F00003062003F104400278F8500208CE400247D
+:105F100014800021000000008D2E00183C187FFF27
+:105F20008F850020370FFFFF01CF1824AF830008B3
+:105F30008F9F00088CA8008403E8C82B172000025C
+:105F400003E020218CA400840A000BEDAF8400083C
+:105F50008CA3010C0A000BCBAF8300188D2C00180A
+:105F60008F8600083C0D7FFF8F89002035A3FFFF3F
+:105F70000183582424040001AF8B0010AD2000CC15
+:105F8000A38400040A000BF9AF86000C8CCA00142D
+:105F90000A000BEDAF8A00088CA300C80A000C3081
+:105FA000AF8300088F84002C8CAC00648C8D0014AF
+:105FB000018D582B11600004000000008CA20064C9
+:105FC0000A000C30AF8200088C8200140A000C30EA
+:105FD000AF8200088F85000C27BDFFE0AFBF00181F
+:105FE000AFB1001414A00007AFB000108F860024DA
+:105FF0002402000590C400003083003F106200B608
+:106000008F8400208F91000800A080218F8C0028B1
+:106010003C0508008CA53D708D8B000431663FFF68
+:1060200000C5502B5540000100C02821938D00046D
+:1060300011A0007300B0F82B8F98002024040034C6
+:10604000930F00BC31EE000251C000012404003067
+:1060500000A4C82B172000D10000000000A42823B2
+:1060600000B0F82B3C010800A4243D7C17E0006838
+:10607000020020213C0308008C633D6C0083102B40
+:1060800054400001008018218F8800243C01080042
+:10609000AC233D74000048219104000D30830020A2
+:1060A000506000018F490E188F8300140123382B94
+:1060B00010E00059000000003C0408008C843D748E
+:1060C00000895821006B502B114000560090602B26
+:1060D0000069302300C020213C010800AC263D743B
+:1060E00012000003241FFFFC1090008A32270003D7
+:1060F000009FC8243C010800AC393D743C010800F5
+:10610000A4203D928F84000C120400078F8300208E
+:10611000AF910008020020218C7100CCAF90000CE0
+:1061200026300001AC7000CC3C0208008C423D746B
+:106130008F8A0010240700180082202301422823A0
+:10614000AF84000C10800002AF85001024070010FF
+:106150008F86001C3C010800A0273D9024070040CA
+:1061600090CC0085318B00C0116700408F8D0014EA
+:1061700014A0001500002021934A01098F420974E0
+:10618000314500FF0002260224A300013090007F69
+:106190003071007F1230007A2407FF80A0C3008393
+:1061A0003C0908008D293D8C8F880024240D0002B5
+:1061B000352C00083C010800A02D3DD13C01080011
+:1061C000AC2C3D8C24040010910E000D31C6002033
+:1061D00010C0000500801821240800013C010800BF
+:1061E000AC283D74348300018FBF00188FB10014B8
+:1061F0008FB000100060102103E0000827BD0020D0
+:106200003C010800A4203D7C13E0FF9A02002021FD
+:106210000A000C8100A020213C0408008C843D74FD
+:106220000090602B1180FFAE000000003C0F0800C2
+:1062300095EF3D7C01E4702101C6682B11A0000799
+:106240002C8200043C1F60008FF954043338003F57
+:106250001700FFE5240300422C8200041040FFA039
+:10626000240300420A000CDF8FBF0018152DFFC069
+:10627000000000008CDF00743C0380002405FF80D8
+:1062800003E3C825ACD9007490D80085240E00041F
+:1062900024040010330F003F01E54025A0C800850D
+:1062A0008F8800243C010800A02E3DD1240300016A
+:1062B0009106000D30C900201520000300000000E9
+:1062C0003C0308008C633D743C010800AC233D6C2A
+:1062D0000A000CD6000000008F8700108C88008414
+:1062E00000E8282B14A0000200E088218C91008493
+:1062F00024090001A38900048F440E1802202821DC
+:106300000E000B3202203021022080210A000C678F
+:10631000AF82001400071823306600033C01080018
+:10632000A4263D92122000058F8C0020918B00BC8A
+:10633000316A00041540001524CD00043C0F08000C
+:1063400095EF3D9201E4702100AE302B50C0FF6EFE
+:106350008F84000C2C85000514A0FFA324030042A9
+:106360003098000317000002009818232483FFFCD4
+:106370003C010800AC233D740A000CA3000000009F
+:1063800000A758240A000CCB016718263C0108001E
+:10639000A42D3D920A000D33000000003C010800CE
+:1063A000AC203D740A000CDE240300428F830010F1
+:1063B00014600007000010218F88002424050005C8
+:1063C0009106000030C400FF1085000300000000AB
+:1063D00003E0000800000000910A0018314900FFA6
+:1063E000000939C214E0FFFA8F85001C3C04080044
+:1063F00094843D7C3C0308008C633D943C19080068
+:106400008F393D743C0F080095EF3D920064C02128
+:106410008CAD00540319702101CF6021018D5823E8
+:106420001960001D00000000910E001C8F8C002CD4
+:10643000974B0E1031CD00FF8D850004016D302388
+:106440008D88000030CEFFFF000E510000AAC82149
+:106450000000382101072021032A182B0083C021C6
+:10646000AD990004AD980000918F000A01CF68211A
+:10647000A18D000A8F88002C974B0E12A50B0008E7
+:10648000950A003825490001A50900389107000D3B
+:1064900034E60008A106000D03E00008000000003B
+:1064A00027BDFFE0938700048F8F00248FAD001479
+:1064B0003C0E7FFF8F89000C35C8FFFFAFBF001C6B
+:1064C000AFB0001801A8182491EA000D000717C00A
+:1064D0003C1FBFFF006258252D2E00018F90001831
+:1064E00037F9FFFF3C1808008F183D943C0F080057
+:1064F00095EF3D8A01796824000E47803C07EFFF45
+:106500003C05F0FF01A818253149002034E2FFFFC7
+:1065100034ACFFFF0310582327A500102406000207
+:1065200025EA000200621824008080211520000264
+:10653000000040218F480E1CA7AA001205600037FA
+:106540002407000030FF00FF001FCF008F8B001CCE
+:1065500000793825AFA70014916F00853C0808002A
+:1065600091083D913C18DFFF31EE00C0370AFFFF74
+:10657000000E182B3C1F080097FF3D8400EA68249A
+:10658000A3A800110003174001A248258FB90010ED
+:10659000AFA900143C0A0800914A3D93A7BF00161A
+:1065A0008FA80014032CC0243C0B01003C0F0FFFEC
+:1065B000030B18253147000335EEFFFF010C68245B
+:1065C00000071600006EF8243C09700001A2C825DF
+:1065D00003E95825AFB90014AFAB00100E000076E8
+:1065E000A3A000158F8C0024260200089186000DC0
+:1065F00030C40020108000068FBF001C3C0508003E
+:1066000094A53D8024B0FFFF3C010800A4303D80EC
+:106610008FB0001803E0000827BD00208F980014F9
+:106620000118502B5540FFC7240700010A000DB682
+:1066300030FF00FF9382000427BDFFE0AFBF0018CA
+:106640001040000F008050218F880024240B00058B
+:106650008F890008910700008F8400200100282105
+:1066600030E3003F8F86002C106B000800003821BB
+:10667000AFA900100E00040EAFAA0014A3800004FE
+:106680008FBF001803E0000827BD00208D190018F7
+:106690003C0F08008DEF3D748F9800103C027FFF87
+:1066A0008D080014345FFFFF033F682401F8702158
+:1066B00001AE602301883821AFA900100E00040E3E
+:1066C000AFAA00140A000E04A38000048F870024E0
+:1066D0003C05080094A53D923C0208008C423D8C8C
+:1066E00090E6000D0005240030C300201060002C4F
+:1066F000004440258F85001C00006021240B000110
+:1067000090A3008500004821240A00013C0F80006E
+:1067100035EE00708DC70000AF8700308F580178CC
+:106720000700FFFE3C038000347900708F380000C2
+:106730003C0508008CA500743C0D08008DAD007070
+:106740000307782300AF38210000102100EF302B21
+:1067500001A22021008618213C010800AC2700740A
+:106760003C010800AC230070AF4B01483C19080005
+:106770008F393D94A7490144A74A0146AF59014CBE
+:106780003C0B0800916B3D91A34B0152AF48015463
+:106790003C081000A74C015803E00008AF480178FE
+:1067A0008F4B0E1C3C0A08008D4A3D7497490E160B
+:1067B000974D0E1401456021312AFFFF0A000E2774
+:1067C00031A9FFFF8F8300249064000D30820020E8
+:1067D0001040002900000000000048210000502166
+:1067E000000040213C07800034EB00708D67000002
+:1067F000AF8700308F4C01780580FFFE3C0D800094
+:1068000035AC00708D8B00003C0508008CA5007431
+:106810003C0408008C8400700167302300A67821B6
+:106820000000102101E6C82B0082C021031970214D
+:106830003C010800AC2F00743C010800AC2E007035
+:10684000AF4901483C0D08008DAD3D94A748014477
+:1068500024090040A74A01463C081000240AFF9181
+:10686000AF4D014CA34A0152AF490154A740015812
+:1068700003E00008AF4801788F490E1897460E12C2
+:1068800097450E1030CAFFFF0A000E5D30A8FFFFCB
+:106890008F83002427BDFFF89064000D3082002014
+:1068A0001040003A00000000240B000100004821C5
+:1068B000240A00013C088000350700708CE30000CA
+:1068C000AF8300308F4C01780580FFFE3C0E8000C6
+:1068D0003C04080090843DD035C700708CEC00006B
+:1068E0003C0508008CA50074A3A400033C19080013
+:1068F0008F3900708FAD00000183302300A638214E
+:10690000000010210322782100E6C02B01F860214D
+:1069100001AE4025AFA800003C010800AC27007480
+:106920003C010800AC2C00709346010A3C040800AE
+:1069300090843DD1A3A00002A3A600018FA3000074
+:106940003C0580FF3099007F34A2FFFF006278246D
+:106950000019C60001F87025240D3000AF4E014C1F
+:1069600027BD0008AF4D0154A7400158AF4B014867
+:10697000A7490144A74A01463C091000240AFF80A8
+:10698000A34A015203E00008AF4901788F4B0E186B
+:1069900097460E1297450E1030CAFFFF0A000E915F
+:1069A00030A9FFFF8F85001C2402008090A4008581
+:1069B000308300C0106200058F8600208F88000899
+:1069C0008F87000CACC800C8ACC700C403E0000847
+:1069D000000000003C0A0800254A39543C09080020
+:1069E00025293A203C08080025082DD43C0708003A
+:1069F00024E73B343C06080024C637C43C050800A5
+:106A000024A5353C3C040800248431643C03080080
+:106A10002463385C3C020800244236303C01080004
+:106A2000AC2A3D503C010800AC293D4C3C0108001B
+:106A3000AC283D483C010800AC273D543C0108000F
+:106A4000AC263D643C010800AC253D5C3C010800DF
+:106A5000AC243D583C010800AC233D683C010800D3
+:0C6A6000AC223D6003E0000800000000D4
+: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-5.0.0.j15.fw.ihex b/firmware/bnx2/bnx2-mips-09-5.0.0.j15.fw.ihex
deleted file mode 100644
index 627baec..0000000
--- a/firmware/bnx2/bnx2-mips-09-5.0.0.j15.fw.ihex
+++ /dev/null
@@ -1,6081 +0,0 @@
-:100000000800011008000000000051F8000000C8BE
-:10001000000000000000000000000000080051F88F
-:1000200000000038000052C00800008808000000EE
-:100030000000528C000052F8080054800000008438
-:100040000000A5840800528C000001C00000A60832
-:10005000080031D808000000000081080000A7C88F
-:1000600000000000000000000000000008008108FF
-:1000700000000124000128D00800048808000400C2
-:10008000000017EC000129F400000000000000004F
-:100090000000000008001BEC00000004000141E02B
-:1000A000080000A808000000000038D0000141E46A
-:1000B000000000000000000000000000080038D030
-:0800C0000000003000017AB4D9
-:0800C8000A00004400000000E2
-:1000D000000000000000000D636F6D352E302E30E3
-:1000E0006A31350005000002000000000000000336
-:1000F00000000014000000320000000300000000B7
-:1001000000000000000000000000000000000000EF
-:1001100000000010000001360000EA600000000549
-:1001200000000000000000000000000000000008C7
-:1001300000000000000000000000000000000000BF
-:1001400000000000000000000000000000000000AF
-:10015000000000000000000000000000000000009F
-:10016000000000020000000000000000000000008D
-:10017000000000000000000000000000000000007F
-:10018000000000000000000000000010000000005F
-:10019000000000000000000000000000000000005F
-:1001A000000000000000000000000000000000004F
-:1001B000000000000000000000000000000000003F
-:1001C000000000000000000000000000000000002F
-:1001D000000000000000000000000000100000030C
-:1001E000000000000000000D0000000D3C020800AF
-:1001F000244252603C0308002463539CAC4000003E
-:100200000043202B1480FFFD244200043C1D080005
-:1002100037BD9FFC03A0F0213C1008002610011000
-:100220003C1C0800279C52600E00026B000000007E
-:100230000000000D27BDFFE0AFBF0018AFB10014F4
-:10024000AFB000103C04800094820108304370007D
-:10025000240220001062000B2862200114400036A6
-:1002600000001021240240001062002C0000000059
-:10027000240260001062002D000010210A00009D81
-:100280008FBF001834910100922400098E300018AD
-:1002900010800020240300012402000914820006BB
-:1002A0008F8200243C0280089442001A000214004D
-:1002B000020280258F8200248C42000C1040001521
-:1002C000000018210E000D52000000008F83002452
-:1002D000962400088F8200209463001E9625000C4F
-:1002E0000004240000832025AC500000AC4500042D
-:1002F000AC400008AC40000CAC400010AC40001416
-:10030000AC400018AC44001C0E000D862404000113
-:10031000000018210A00009C006010210E00043B20
-:10032000000000000A00009C000010210E000C726A
-:1003300000000000000010218FBF00188FB10014D2
-:100340008FB0001003E0000827BD00208F8200243A
-:1003500027BDFFE0AFB00010AFBF0018AFB1001471
-:100360008C42000C3C1080008E11010010400034C3
-:100370008FBF00180E000D52000000008F85002076
-:1003800024047FFF0091202BACB100008E030104F8
-:100390009602010800031C003042FFFF006218258E
-:1003A000ACA300049202010A96030114304200FF3C
-:1003B0003063FFFF0002140000431025ACA20008C8
-:1003C0009603010C9602010E00031C003042FFFF51
-:1003D00000621825ACA3000C9603011096020112CE
-:1003E00000031C003042FFFF00621825ACA3001080
-:1003F0008E020118ACA200148E02011CACA20018DF
-:10040000148000088F820024978200003C0420059D
-:100410000044182524420001ACA3001C0A0000DBA4
-:10042000A78200003C0340189442001E00431025A0
-:10043000ACA2001C0E000D86240400018FBF001822
-:100440008FB100148FB000100000102103E00008ED
-:1004500027BD00203C0680008CC202B824030001A6
-:1004600004410008008028213C0208008C42006002
-:10047000244200013C010800AC22006003E00008B7
-:10048000006010218C83002094820016ACC302808F
-:100490002442FFFCA4C202843C0208008C42005C9F
-:1004A0008C84000494A3000E244200013C01080047
-:1004B000AC22005C3C021000A4C30286ACC40288DB
-:1004C00000001821ACC202B803E00008006010214F
-:1004D00027BDFFE0AFB000103C108000AFB20018A5
-:1004E000AFBF001CAFB10014361201009243000BE5
-:1004F0002402001A965100081462005A00002821B4
-:1005000032220001104000188F8200248E42000029
-:10051000000223403C02003F3442FFFF0044102B06
-:10052000104000043C030040964200140A000124DD
-:10053000008320218E030100240201005462000682
-:10054000964200143C028008904200043042000FA2
-:10055000000225009642001400821025AE020080A1
-:100560000A000157000000008C42000C10400028D7
-:10057000000000000E000D5200000000960201086D
-:100580009603010C8F8500203042003E3063FFFF50
-:100590000002140000431025ACA200008E020100EE
-:1005A000ACA20004960301169604010E8F8200246B
-:1005B00000031C003084FFFF00641825ACA3000872
-:1005C00096030110960401129446001E00031C00BD
-:1005D0003084FFFF00641825ACA3000C3C0220000F
-:1005E00000C2302596020114240400013042FFFFAE
-:1005F000ACA200108E020118ACA200149202010BF2
-:10060000304200FFACA200180E000D86ACA6001C04
-:100610003C0208008C420040244200013C010800DA
-:10062000AC2200403C0308008C63004432220002EC
-:1006300032240004246300013C010800AC23004480
-:10064000108000080002282B024020218FBF001CD0
-:100650008FB200188FB100148FB000100A0000E3B1
-:1006600027BD00208FBF001C8FB200188FB100146F
-:100670008FB0001000A0102103E0000827BD00206B
-:1006800027BDFFE0AFB000103C108000AFB20018F3
-:10069000AFBF001CAFB10014361201009243000B33
-:1006A00024020003965100081462007500002821FE
-:1006B00032220001104000178F8200248E43000078
-:1006C0003C02003F3442FFFF000323400044102B54
-:1006D0005040000524020100964200143C030040F3
-:1006E0000A00018F00832021546200069642001404
-:1006F0003C028008904200043042000F00022500B6
-:100700009642001400821025AE0200800A0001BF4C
-:10071000000000008C42000C10400025000000008A
-:100720000E000D5200000000960201089603010C15
-:100730008F8500203042003E3063FFFF000214002E
-:1007400000431025ACA200008E020100ACA2000400
-:10075000960301169604010E8F82002400031C00EC
-:100760003084FFFF00641825ACA300089603011035
-:10077000960401129446001E00031C003084FFFF03
-:1007800000641825ACA3000C3C02200000C23025F8
-:1007900096020114240400013042FFFFACA20010B5
-:1007A000ACA00014ACA000180E000D86ACA6001C76
-:1007B0003C0208008C420040244200013C01080039
-:1007C000AC2200403C0208008C420044322300046A
-:1007D000244200013C010800AC22004410600008E3
-:1007E00032220002024020218FBF001C8FB200186D
-:1007F0008FB100148FB000100A0000E327BD002065
-:100800001040001F000028213C05800034A2007029
-:100810008C4400008F82000C008210232C43012C9A
-:1008200010600004AF820010240500010A0001EEF0
-:10083000AF84000C8CA301043C026020AC43001484
-:100840008C420004240301FE304203FF1443000BDA
-:10085000AF84000C8CA20100000219C22462FFFCCC
-:100860002C42000810400003240400022462FFFD13
-:10087000004420043C026000AC44691400002821BC
-:100880008FBF001C8FB200188FB100148FB0001002
-:1008900000A0102103E0000827BD00203C048000D8
-:1008A0008C83010024020100506200033C02800896
-:1008B0000000000D3C02800890430004000010215D
-:1008C0003063000F00031D0003E00008AC830080CC
-:1008D0002C8407811080000A000028213C0280003F
-:1008E00094420108240320003042700014430005A4
-:1008F0002783FFA43C02800890420005304500FF9A
-:100900002783FFA40005208000832021000510C05C
-:10091000004510238C8400003C0308002463532C02
-:10092000000210C0004310213C038000AC64009022
-:1009300003E00008AF82002403E00008000010215B
-:1009400003E00008000010212402010014820008C6
-:10095000000000003C0208008C4200FC2442000120
-:100960003C010800AC2200FC0A00023030A200204A
-:100970003C0208008C420084244200013C01080033
-:10098000AC22008430A200201040000830A30010E8
-:100990003C0208008C420108244200013C0108008E
-:1009A000AC22010803E0000800000000106000080D
-:1009B000000000003C0208008C42010424420001B7
-:1009C0003C010800AC22010403E000080000000024
-:1009D0003C0208008C420100244200013C01080056
-:1009E000AC22010003E000080000000027BDFFE882
-:1009F000AFB000103C108000AFBF001436040100FF
-:100A00009483000830620004104000053066000244
-:100A10008FBF00148FB000100A0000E327BD00183C
-:100A200010C00006006028218E0401000E00022084
-:100A3000000000000A000267240200018F82000803
-:100A40008E03010410430007000010218E040100F2
-:100A50000E000220000000008E020104AF82000898
-:100A6000000010218FBF00148FB0001003E00008B9
-:100A700027BD001827BDFFD83C036010AFB3001C92
-:100A8000AFBF0020AFB20018AFB10014AFB000107C
-:100A90008C6450002402FF7F3C13080026735290A0
-:100AA000008220243484380CAC6450003C02800066
-:100AB00024030037AC4300083C06080024C6087035
-:100AC000026010212404001C2484FFFFAC460000B7
-:100AD0000481FFFD244200043C0208002442016C12
-:100AE0003C010800AC2252983C020800244205B8A0
-:100AF0003C010800AC22529C3C02080024420284C3
-:100B00003C010800AC2252D83C02080024420408F0
-:100B10003C030800246308783C040800248409246A
-:100B20003C05080024A52C803C010800AC2252F8AA
-:100B30003C020800244207D43C010800AC2652E0E5
-:100B40003C010800AC2552EC3C010800AC2352F4F7
-:100B50003C010800AC2452FC3C010800AC225300CC
-:100B60003C010800AC2352943C010800AC2052A088
-:100B70003C010800AC2052A43C010800AC2052A863
-:100B80003C010800AC2052AC3C010800AC2052B043
-:100B90003C010800AC2052B43C010800AC2052B823
-:100BA0003C010800AC2452BC3C010800AC2052C0FF
-:100BB0003C010800AC2052C43C010800AC2052C8E3
-:100BC0003C010800AC2052CC3C010800AC2052D0C3
-:100BD0003C010800AC2652D43C010800AC2652DC93
-:100BE0003C010800AC2052E43C010800AC2552E86E
-:100BF0003C010800AC2352F00E0005670000000025
-:100C0000AF80000C8F8300043C0208008C4200205F
-:100C10001062001F000088212792FFA43C100800EA
-:100C20002610532C3C0208008C42002024050001B1
-:100C300002251804004320248F820004004310245E
-:100C40005044000C2631000110800008AF900024B1
-:100C50008E4300003C028000AC4300900E000D1952
-:100C6000AE05000C0A0002EB26310001AE00000CBC
-:100C7000263100012E220002261000381440FFE920
-:100C8000265200043C0208008C420020AF8200047F
-:100C90003C1080008E110000322200071040FFDA65
-:100CA0008F83000432220001104000213222000212
-:100CB0008E020100AE0200208E020104AE0200A8E6
-:100CC0000E0002028E0401009202010B304300FF6D
-:100CD0002C62001D54400004000310800E00021C12
-:100CE0000A00030C00000000005310218C42000099
-:100CF0000040F80900000000104000043C028000A1
-:100D00008C4301043C026020AC4300143C02080008
-:100D10008C4200343C0440003C038000244200012B
-:100D2000AC6401383C010800AC22003432220002DD
-:100D300010400010322200043C1080008E0201405E
-:100D4000AE0200200E0002028E0401400E0003A439
-:100D5000000000003C024000AE0201783C020800A6
-:100D60008C420038244200013C010800AC220038CB
-:100D7000322200041040FFA48F8300043C10800046
-:100D80008E020180AE0200200E0002028E0401805D
-:100D90008E03018024020F00146200073C028008C9
-:100DA0008E0201883C0300E03042FFFF0043102523
-:100DB0000A000348AE0200803442008090420000E6
-:100DC00024030050304200FF1443000700000000DD
-:100DD0000E0003810000000014400003000000002A
-:100DE0000E00096A000000003C0208008C42003C32
-:100DF0003C0440003C03800024420001AC6401B884
-:100E00003C010800AC22003C0A0002D08F830004A1
-:100E10003C02900034420001008220253C02800008
-:100E2000AC4400203C0380008C6200200440FFFEA4
-:100E30000000000003E00008000000003C02800009
-:100E4000344300010083202503E00008AC44002067
-:100E500027BDFFE0AFB10014AFB0001000808821C3
-:100E6000AFBF00180E00035230B000FF8F83FF9C0D
-:100E7000022020219062002502028025A07000251A
-:100E80008C7000183C0280000E00035D020280247A
-:100E90001600000A8FBF00183C0380008C6201F826
-:100EA0000440FFFE24020002AC7101C0A06201C434
-:100EB0003C021000AC6201F88FBF00188FB1001423
-:100EC0008FB0001003E0000827BD002027BDFFE819
-:100ED000AFBF00103C0380009462018430420200E6
-:100EE00010400005000020210E000FDA0000000075
-:100EF0000A000397240400018C6201880440000A60
-:100F00008FBF00108C6201883C03FF000043102457
-:100F10003C03040014430004240400018F82FF9C5E
-:100F2000904200088FBF00100080102103E00008ED
-:100F300027BD00188F82FFA02403000124050001B3
-:100F4000A040001A8F82FF9CA44300163C02800040
-:100F50000A0003628C4401408F85FF9C27BDFFE09F
-:100F6000AFBF001CAFB20018AFB10014AFB000109B
-:100F700090A20000304400FF388300203882003007
-:100F80000003182B0002102B0062182410600005CB
-:100F90003C02800024020050148200818FBF001C9C
-:100FA0003C02800090420148304200FF2443FFFF92
-:100FB0002C6200051040007A8FBF001C00031080D7
-:100FC0003C03080024635210004310218C420000AF
-:100FD00000400008000000003C1180008E24014009
-:100FE0000E0003528F92FF9C8E50000C8E22014403
-:100FF0001602000224020001AE42000C0E00035D46
-:101000008E2401408E220144145000068FBF001C24
-:101010008FB200188FB100148FB000100A000F4675
-:1010200027BD00208E42000C0A00042F00000000A3
-:1010300094A200103C0480008C8301443042FFFFE6
-:10104000146200090000000024020001A4A20010A4
-:101050008C820140AC8202003C021000AC8202385B
-:101060000A0004368FBF001C94A200100A00042F4F
-:1010700000000000240200201482000E3C118000B9
-:1010800094A200123C0380008C6301443042FFFFB5
-:10109000146200050000000024020001A4A2001256
-:1010A0000A0004098FBF001C94A200120A00042F3A
-:1010B000000000008E2401400E0003528F92FF9C1E
-:1010C000964200128E2301443050FFFF16030002A7
-:1010D00024020001A64200120E00035D8E2401408E
-:1010E0008E220144160200068FBF001C8FB200182A
-:1010F0008FB100148FB000100A00039B27BD0020A1
-:10110000964200120A00042F0000000094A200146E
-:101110003C0380008C6301443042FFFF14620008EE
-:101120008FBF001C240200018FB200188FB1001481
-:101130008FB00010A4A200140A00143127BD0020B3
-:1011400094A200140A00042F0000000094A20016CC
-:101150003C0380008C6301443042FFFF14620008AE
-:10116000240200018FBF001C8FB200188FB1001441
-:101170008FB00010A4A200160A000B0D27BD00209E
-:1011800094A20016144000068FBF001C3C02080009
-:101190008C420070244200013C010800AC22007027
-:1011A0008FB200188FB100148FB0001003E0000858
-:1011B00027BD002027BDFFD8AFB200188F92FF9C3B
-:1011C000AFB10014AFBF0020AFB3001CAFB0001030
-:1011D0003C028000345101008C500100924200001A
-:1011E00092230009304400FF2402001F106200AB6C
-:1011F0002862002010400019240200382862000AEA
-:101200001040000D2402000B286200081040002E40
-:101210008F82002404600103286200021440002A27
-:101220008F82002424020006106200268FBF002057
-:101230000A0005598FB3001C106200602862000B81
-:10124000144000F98FBF00202402000E10620078C5
-:101250008F8200240A0005598FB3001C106200D150
-:10126000286200391040000A24020080240200365F
-:10127000106200E428620037104000C224020035EA
-:10128000106200D88FBF00200A0005598FB3001CE0
-:101290001062002D2862008110400006240200C860
-:1012A00024020039106200C88FBF00200A000559CF
-:1012B0008FB3001C106200A28FBF00200A000559E6
-:1012C0008FB3001C8F8200248C42000C104000D68B
-:1012D0008FBF00200E000D52000000003C03800074
-:1012E000346301008C6200008F8500209467000841
-:1012F0009466000CACA200008C6400048F82002471
-:1013000000063400ACA400049448001E8C6200184F
-:1013100000073C0000E83825ACA200088C62001CE5
-:1013200024040001ACA2000C9062000A00C2302527
-:10133000ACA60010ACA00014ACA00018ACA7001C18
-:101340000A0005188FBF00208F8200248C42000CF9
-:10135000104000B58FBF00200E000D5200000000AD
-:101360008F820024962400089625000C9443001ECA
-:10137000000422029626000E8F8200200004260020
-:101380000083202500052C003C03008000A62825B2
-:1013900000832025AC400000AC400004AC400008B5
-:1013A000AC40000CAC450010AC400014AC40001840
-:1013B000AC44001C0A000517240400019622000C0E
-:1013C0001440001800000000924200053042001056
-:1013D00014400014000000000E00035202002021FF
-:1013E0009242000502002021344200100E00035DED
-:1013F000A24200059242000024030020304200FF78
-:1014000010430088020020218FBF00208FB3001CF2
-:101410008FB200188FB100148FB000100A00104373
-:1014200027BD00280000000D0A0005588FBF0020CE
-:101430008C42000C1040007C8FBF00200E000D522B
-:10144000000000008E2200048F8400209623000CF0
-:10145000AC8200003C0280089445002C8F8200245E
-:1014600000031C0030A5FFFF9446001E3C02400E06
-:101470000065182500C23025AC830004AC8000084C
-:10148000AC80000CAC800010AC800014AC80001864
-:10149000AC86001C0A000517240400010E0003524C
-:1014A000020020218F93FFA0020020210E00035D87
-:1014B000A660000C020020210E000362240500013A
-:1014C0008F8200248C42000C104000578FBF0020F8
-:1014D0000E000D52000000009622000C8F830020A9
-:1014E00000021400AC700000AC620004AC600008A4
-:1014F0008E4400388F820024AC64000C8E46003C81
-:101500009445001E3C02401FAC66001000A2282536
-:101510008E62000424040001AC620014AC60001868
-:10152000AC65001C8FBF00208FB3001C8FB2001869
-:101530008FB100148FB000100A000D8627BD00285F
-:1015400024020020108200398FB3001C0E000F2CE3
-:1015500000000000104000348FBF00203C038000DA
-:101560008C6201F80440FFFE24020002AC7001C04E
-:10157000A06201C43C021000AC6201F80A000558E8
-:101580008FBF0020020020218FBF00208FB3001CDE
-:101590008FB200188FB100148FB000100A000E75C2
-:1015A00027BD00289625000C020020218FBF0020B7
-:1015B0008FB3001C8FB200188FB100148FB00010D1
-:1015C0000A000E9A27BD0028020020218FB3001CBC
-:1015D0008FB200188FB100148FB000100A000EC532
-:1015E00027BD00289225000D020020218FB3001C8A
-:1015F0008FB200188FB100148FB000100A000F16C0
-:1016000027BD0028020020218FBF00208FB3001CBF
-:101610008FB200188FB100148FB000100A000EEDC9
-:1016200027BD00288FBF00208FB3001C8FB2001889
-:101630008FB100148FB0001003E0000827BD002810
-:101640003C0380008C6202780440FFFE240200020A
-:10165000AC640240A06202443C02100003E00008B7
-:10166000AC620278A380001803E00008A380001990
-:101670003C0380008C6202780440FFFE8F82001CD5
-:10168000AC62024024020002A06202443C0210004C
-:1016900003E00008AC6202783C02600003E000084E
-:1016A0008C425404908300302402000500804021C5
-:1016B0003063003F00004821146200050000502103
-:1016C0009082004C9483004E304900FF306AFFFF47
-:1016D000AD00000CAD000010AD0000249502001418
-:1016E0008D05001C8D0400183042FFFF00491023B7
-:1016F00000021100000237C3004038210086202379
-:1017000000A2102B0082202300A72823AD05001C77
-:10171000AD040018A5090014A5090020A50A0016AB
-:1017200003E00008A50A002203E000080000000012
-:1017300027BDFFD8AFB200183C128008AFB400201C
-:10174000AFB3001CAFB10014AFBF0024AFB00010A6
-:10175000365101003C0260008C4254049222000C7D
-:101760003C140800929400F7304300FF240200016B
-:1017700010620032008098212402000214620035B9
-:10178000365000800E00140B000000009202004C46
-:101790002403FF803C0480003042007F000211C01F
-:1017A000244202400262102100431824AC830094BA
-:1017B000924500089204004C3042007F3C038006B2
-:1017C00014850007004380212402FFFFA22200119C
-:1017D0002402FFFFA62200120A0005CB2402FFFF0D
-:1017E00096020020A222001196020022A6220012D8
-:1017F0008E0200243C048008AE2200143485008050
-:1018000090A2004C34830100A06200108CA2003C26
-:10181000AC6200188C820068AC6200E48C820064C8
-:10182000AC6200E08C82006CAC6200E82402000133
-:10183000A0A200680A0005E73C0480080E001424FA
-:101840000000000036420080A04000680A0005E762
-:101850003C048008A2000068A20000690A00062279
-:101860003C028008348300808C620038348501009B
-:10187000AC62006C24020001A062006990A200C565
-:1018800090830008305100FF3072007F123200193F
-:10189000001111C024420240026210212403FF8083
-:1018A000004318243C048000AC8300943042007F45
-:1018B0003C038006004380218E02000C1040000D86
-:1018C000020020210E000577000000002622000102
-:1018D000305100FF9203003C023410260002102B0E
-:1018E000000210233063007F022288240A0005F1E1
-:1018F000A203003C3C088008350401008C8200D023
-:1019000035070080ACE2003C8C8200D0AD020000C4
-:1019100090E5004C908600C590E3004C908400C593
-:101920002402FF8000A228243063007F308400FF5F
-:1019300000A628250064182A1060000230A500FFC8
-:1019400038A50080A0E5004CA10500093C028008F4
-:101950009043000E344400803C058000A043000A00
-:101960008C8300183C027FFF3442FFFF0062182482
-:10197000AC8300188CA201F80440FFFE00000000B8
-:10198000ACB301C08FBF00248FB400208FB3001C04
-:101990008FB200188FB100148FB000102402000223
-:1019A000A0A201C427BD00283C02100003E00008EB
-:1019B000ACA201F890A2000024420001A0A2000005
-:1019C0003C0308008C6300F4304200FF1443000223
-:1019D00000803021A0A0000090A200008F84001C95
-:1019E000000211C0244202402483004000822021D2
-:1019F0002402FF80008220243063007F3C02800AA2
-:101A0000006218213C028000AC44002403E000087E
-:101A1000ACC3000094820006908300058C85000C06
-:101A20008C8600108C8700188C88001C8C84002009
-:101A30003C010800A422530E3C010800A023530DD2
-:101A40003C010800AC2553143C010800AC26531897
-:101A50003C010800AC2753203C010800AC2853246B
-:101A60003C010800AC24532803E0000800000000FB
-:101A70003C028008344201008C4400343C03800066
-:101A800034650400AC6400388C420038AF8500280F
-:101A9000AC62003C3C020005AC620030000000007B
-:101AA0000000000003E00008000000003C02000607
-:101AB000308400FF008220253C028000AC440030CE
-:101AC0000000000000000000000000003C03800057
-:101AD0008C620000304200101040FFFD34620400B0
-:101AE00003E00008AF82002894C200003C08080010
-:101AF000950800CA30E7FFFF00804821010210214D
-:101B0000A4C2000094C200003042FFFF00E2102B8C
-:101B100054400001A4C7000094A200003C03080048
-:101B20008C6300CC24420001A4A2000094A2000017
-:101B30003042FFFF144300073C0280080107102BCE
-:101B4000A4A000005440000101003821A4C70000F7
-:101B50003C028008344601008CC3002894A2000097
-:101B60003C0480003042FFFE000210C000621021E1
-:101B7000AC82003C8C82003C006218231860000498
-:101B8000000000008CC200240A0006B324420001B9
-:101B90008CC20024AC8200383C0200503442001059
-:101BA0003C038000AC620030000000000000000038
-:101BB000000000008C620000304200201040FFFD59
-:101BC0000000000094A200003C04800030420001AC
-:101BD000000210C0004410218C430400AD2300001B
-:101BE0008C420404AD2200043C02002003E0000803
-:101BF000AC82003027BDFFE0AFB20018AFB10014D7
-:101C0000AFB00010AFBF001C94C2000000C0802124
-:101C10003C120800965200C624420001A6020000B1
-:101C20009603000094E2000000E030211443000518
-:101C30008FB100300E000688024038210A0006EA03
-:101C4000000000008C8300048C82000424420040C9
-:101C500004610007AC8200048C820004044000048C
-:101C6000000000008C82000024420001AC820000D1
-:101C7000960200003042FFFF50520001A600000013
-:101C80009622000024420001A62200003C028008A7
-:101C900034420100962300009442003C14430004A7
-:101CA0008FBF001C24020001A62200008FBF001C71
-:101CB0008FB200188FB100148FB0001003E000083D
-:101CC00027BD002027BDFFE03C028008AFBF001801
-:101CD000344201008C4800343C0380003469040025
-:101CE000AC6800388C42003830E700FFAF8900282C
-:101CF000AC62003C3C020005AC6200300000000019
-:101D000000000000000000000000000000000000D3
-:101D1000000000008C82000C8C82000C978300165F
-:101D2000AD2200008C82001000604021AD22000432
-:101D30008C820018AD2200088C82001CAD22000CA1
-:101D40008CA20014AD2200108C820020AD22001461
-:101D500090820005304200FF00021200AD22001800
-:101D60008CA20018AD22001C8CA2000CAD22002019
-:101D70008CA20010AD2200248CA2001CAD220028F1
-:101D80008CA20020AD22002C3402FFFFAD260030D3
-:101D9000AD200034506200013408FFFFAD28003848
-:101DA00050E000113C0280083C04800834840100AB
-:101DB000948200503042FFFFAD22003C94830044E7
-:101DC00094850044240200013063FFFF000318C221
-:101DD000006418219064005430A5000700A210048C
-:101DE0000A0007550044102534420100AD20003C94
-:101DF00094430044944400443063FFFF000318C23E
-:101E0000006218213084000790650054240200010C
-:101E1000008210040002102700451024A062005424
-:101E20000000000000000000000000003C0200066E
-:101E3000344200403C038000AC62003000000000EF
-:101E400000000000000000008C6200003042001022
-:101E50001040FFFD3C06800834C20150346304008A
-:101E600034C7014A34C4013434C5014034C6014486
-:101E7000AFA200100E0006CBAF8300288FBF001862
-:101E800003E0000827BD00208F8300143C060800F3
-:101E90008CC600E88F82001C30633FFF000319806E
-:101EA00000461021004310212403FF800043182422
-:101EB0003C068000ACC300283042007F3C03800C0D
-:101EC0000043302190C2000D30A500FF00003821F2
-:101ED00034420010A0C2000D8F8900143C0280081B
-:101EE0003442010094430044000913823048000347
-:101EF00024020001A4C3000E1102000B29020002FB
-:101F000010400005240200021100000C240300010F
-:101F10000A00079D000018211102000600000000C1
-:101F20000A00079D000018218CC2002C0A00079DA2
-:101F3000244300018CC20014244300018CC2001809
-:101F40000043102B5040000A240700012402002700
-:101F500014A200033C0380080A0007AA240700011A
-:101F6000346301009462004C24420001A462004CDE
-:101F700000091382304300032C6200021040000964
-:101F800000802821146000040000000094C2003486
-:101F90000A0007BA3046FFFF8CC600380A0007BAAD
-:101FA00000802821000030213C04080024845308CC
-:101FB0000A0006FF0000000027BDFF90AFB60068D2
-:101FC000AFB50064AFB40060AFB3005CAFB200580F
-:101FD000AFB10054AFBF006CAFB000508C900000A8
-:101FE0000080B0213C0208008C4200E896040032D8
-:101FF0008F83001C2414FF8030843FFF006218216F
-:102000000004218000641821007410243C13800017
-:1020100000A0902190A50000AE620028920400323A
-:102020003C02800C3063007F00628821308400C055
-:1020300024020040148200320000A8218E350038AE
-:102040008E2200181440000224020001AE22001863
-:102050009202003C304200201440000E8F83001C8E
-:10206000000511C02442024000621821306400784B
-:102070003C0200800082202500741824AE63080012
-:10208000AE6408108E2200188E0300080043102151
-:10209000AE2200188E22002C8E230018244200014C
-:1020A0000062182B10600043000000009242000004
-:1020B00024420001A24200003C0308008C6300F4AB
-:1020C000304200FF50430001A24000009242000055
-:1020D0008F84001C000211C024420240248300406F
-:1020E0003063007F008220213C02800A009420247B
-:1020F00000621821AE6400240A0008CBAEC30000C1
-:10210000920300322402FFC000431024304200FF3B
-:102110001440000524020001AE220018962200346B
-:102120000A00083B3055FFFF8E22001424420001B4
-:10213000AE220018920200300002160000021603C0
-:102140000441001C000000009602003227A4001089
-:1021500000802821A7A2001696020032000030213C
-:10216000240700013042FFFFAF8200140E0006FF7B
-:10217000AFA0001C960200328F83001C3C040800B4
-:102180008C8400E830423FFF000211800064182177
-:102190000062182100741024AE62002C3063007FAE
-:1021A0003C02800E006218219062000D3042007FD8
-:1021B000A062000D9222000D3042001050400078C5
-:1021C000924200003C028008344401009482004C9A
-:1021D0008EC300003C130800967300C62442FFFF24
-:1021E000A482004C946200329623000E3054FFFF0C
-:1021F0003070FFFF3C0308008C6300D000701807AC
-:10220000A7A300389482003E3063FFFF3042FFFFF7
-:1022100014620007000000008C8200303C03800044
-:1022200024420030AC62003C0A0008638C82002C1F
-:10223000948200403042FFFF5462000927A400400E
-:102240008C8200383C03800024420030AC62003CA9
-:102250008C820034AC6200380A0008723C038000B3
-:1022600027A5003827A60048026038210E000688FE
-:10227000A7A000488FA300403C02800024630030E8
-:10228000AC4300388FA30044AC43003C3C038000C7
-:102290003C020005AC6200303C028008344401007E
-:1022A00094820042346304003042FFFF0202102B8C
-:1022B00014400007AF8300289482004E94830042AC
-:1022C00002021021004310230A0008883043FFFF58
-:1022D0009483004E94820042026318210050102320
-:1022E000006218233063FFFF3C0280083444010081
-:1022F0009482003C3042FFFF1443000300000000C2
-:102300000A000898240300019482003C3042FFFF39
-:102310000062102B144000058F8200289482003C3C
-:10232000006210233043FFFF8F820028AC5500006D
-:10233000AC400004AC540008AC43000C3C02000666
-:10234000344200103C038000AC620030000000000A
-:1023500000000000000000008C620000304200100D
-:102360001040FFFD3C04800834840100001018C2B6
-:102370000064182190650054320200072406000111
-:102380000046100400451025A062005494830042CA
-:102390009622000E50430001A386001892420000CE
-:1023A00024420001A24200003C0308008C6300F4B8
-:1023B000304200FF50430001A24000009242000062
-:1023C0008F84001C000211C024420240248300407C
-:1023D000008220212402FF80008220243063007FBD
-:1023E0003C02800A006218213C028000AC440024B8
-:1023F000AEC300008FBF006C8FB600688FB500645D
-:102400008FB400608FB3005C8FB200588FB100545E
-:102410008FB0005003E0000827BD007027BDFFD833
-:10242000AFB3001CAFB20018AFB10014AFB00010D2
-:10243000AFBF00200080982100E0802130B1FFFF75
-:102440000E000D5230D200FF00000000000000001E
-:10245000000000008F8200208F830024AC51000018
-:10246000AC520004AC530008AC40000CAC4000106F
-:10247000AC400014AC4000189463001E0203802599
-:10248000AC50001C00000000000000000000000034
-:10249000240400018FBF00208FB3001C8FB20018EE
-:1024A0008FB100148FB000100A000D8627BD0028E0
-:1024B00030A5FFFF0A0008D530C600FF3C028008A7
-:1024C000344301009462000E3C080800950800C6E1
-:1024D0003046FFFF14C000043402FFFF946500DAA9
-:1024E0000A0009228F84001C10C20027000000008F
-:1024F0009462004E9464003C3045FFFF00A6102318
-:1025000000A6182B3087FFFF106000043044FFFF47
-:1025100000C5102300E210233044FFFF0088102B79
-:102520001040000E00E810233C02800834440100F3
-:102530002403000134420080A44300162402FFFF5C
-:10254000A482000E948500DA8F84001C00003021E4
-:1025500030A5FFFF0A0008FA3C0760200044102A5B
-:10256000104000093C028008344300809462001649
-:1025700030420001104000043C0280009442007E82
-:1025800024420014A462001603E0000800000000CA
-:1025900027BDFFE03C028008AFBF001CAFB00018B1
-:1025A00034420100944300429442004C1040001910
-:1025B0003068FFFF93830018240200011462002991
-:1025C0008FBF001C3C06800834D00100000810C2F8
-:1025D00000501021904200543103000734C70148D5
-:1025E000304200FF006210073042000134C9014E42
-:1025F00034C4012C34C5013E1040001634C60142DB
-:102600000E0006CBAFA90010960200420A00093F57
-:102610003048FFFF3C0280083444010094830044AA
-:10262000948200421043000F8FBF001C948200442C
-:10263000A482004294820050A482004E8C82003812
-:10264000AC82003094820040A482003E9482004A12
-:10265000A48200488FBF001C8FB000180A0008FD3C
-:1026600027BD00208FB0001803E0000827BD002020
-:1026700027BDFFA0AFB1004C3C118000AFBF005898
-:10268000AFB30054AFB20050AFB000483626018857
-:1026900090C200033044007FA3A400108E3201805A
-:1026A00090C200003043007F240200031062003B10
-:1026B000AF92001C286200041040000624020004AF
-:1026C00024020002106200098FBF00580A000B08A4
-:1026D0008FB300541062004D240200051062014EB9
-:1026E0008FBF00580A000B088FB30054000411C0BC
-:1026F000024210212404FF8024420240004410249E
-:1027000026430040AE2200243063007F3C02800A52
-:10271000006218219062003CAFA3003C00441025E9
-:10272000A062003C8FA3003C9062003C304200401D
-:102730001040016C8FBF00583C108008A380001827
-:10274000361001008E0200D08C63003427A4003CB8
-:1027500027A50010004310210E0007BCAE0200D0D8
-:1027600093A200103C038000A20200C58C62027894
-:102770000440FFFE8F82001CAC6202402402000273
-:10278000A06202443C021000AC6202780E000932E2
-:10279000000000000A000B078FBF00583C058008AE
-:1027A00090C3000190A2000B1443014E8FBF00584C
-:1027B00034A400808C8200189082004C90A2000803
-:1027C0003C0260008C4254048C8300183C027FFF62
-:1027D0003442FFFF006218243C0208008C4200B41F
-:1027E000AC8300183C038000244200013C01080037
-:1027F000AC2200B48C6201F80440FFFE8F82001C02
-:10280000AC6201C00A000ACF240200023C1080081A
-:1028100090C300019202000B144301328FBF005895
-:1028200027A4001836050110240600033C026000AE
-:102830008C4254040E000E150000000027A400284E
-:10284000360501E00E000E15240600038FA20028B5
-:1028500036030100AE0200648FA2002CAE020068B5
-:102860008FA20030AE02006C93A40018906300C5E4
-:102870002402FF800082102400431025304900FF0D
-:102880003084007F3122007F0082102A54400001F2
-:1028900039290080000411C0244202402403FF8033
-:1028A0000242102100431024AE2200942642004030
-:1028B0003042007F3C038006004340218FA3001C70
-:1028C0002402FFFFAFA800403C130800927300F7FA
-:1028D0001062003393A2001995030014304400FFE6
-:1028E0003063FFFF0064182B106000100000000030
-:1028F000950400148D07001C8D0600183084FFFF1E
-:10290000004420230004210000E4382100001021AD
-:1029100000E4202B00C2302100C43021AD07001C90
-:10292000AD0600180A000A2893A2001995040014A5
-:102930008D07001C8D0600183084FFFF00822023C5
-:1029400000042100000010210080182100C2302363
-:1029500000E4202B00C4302300E33823AD07001C23
-:10296000AD06001893A200198FA30040A4620014C2
-:1029700097A2001AA46200168FA2001CAC6200107D
-:102980008FA2001CAC62000C93A20019A46200206C
-:1029900097A2001AA46200228FA2001CAC6200243D
-:1029A0003C048008348300808C6200388FA20020B1
-:1029B00001208821AC62003C8FA20020AC82000084
-:1029C00093A20018A062004C93A20018A0820009F4
-:1029D000A060006893A20018105100512407FF80E6
-:1029E0003229007F000911C0244202400242102116
-:1029F0003046007F3C03800000471024AC62009406
-:102A00003C02800600C2302190C2003CAFA60040CC
-:102A10000000202100471025A0C2003C8FA80040E4
-:102A200095020002950300148D07001C3042FFFF41
-:102A30003063FFFF8D0600180043102300021100D1
-:102A400000E2382100E2102B00C4302100C2302106
-:102A5000AD07001CAD06001895020002A502001487
-:102A6000A50000168D020008AD0200108D020008BE
-:102A7000AD02000C95020002A5020020A500002274
-:102A80008D020008AD0200249102003C304200405B
-:102A90001040001A262200013C108008A3A900382B
-:102AA000A3800018361001008E0200D08D03003480
-:102AB00027A4004027A50038004310210E0007BCC2
-:102AC000AE0200D093A200383C038000A20200C5F1
-:102AD0008C6202780440FFFE8F82001CAC620240D0
-:102AE00024020002A06202443C021000AC620278A0
-:102AF0000E00093200000000262200013043007F52
-:102B000014730004004020212403FF8002231024BA
-:102B10000043202693A200180A000A44309100FFC7
-:102B200093A400188FA3001C2402FFFF1062000A68
-:102B3000308900FF24820001248300013042007F9D
-:102B400014530005306900FF2403FF800083102424
-:102B500000431026304900FF3C02800890420008E4
-:102B600001208821305000FF123000193222007FEE
-:102B7000000211C002421021244202402403FF80BF
-:102B8000004318243C048000AC8300943042007F52
-:102B90003C038006004310218C43000C00402021A0
-:102BA0001060000BAFA200400E000577000000008F
-:102BB000262300012405FF803062007F14530002A9
-:102BC00002252024008518260A000AA8307100FF7B
-:102BD0003C048008348400808C8300183C027FFF12
-:102BE0003442FFFF00621824AC8300183C038000CD
-:102BF0008C6201F80440FFFE00000000AC7201C0CE
-:102C000024020002A06201C43C021000AC6201F880
-:102C10000A000B078FBF00583C04800890C30001D6
-:102C20009082000B1443002F8FBF00583490008017
-:102C300092020008304200401040002000000000D6
-:102C4000920200080002160000021603044100056B
-:102C5000024020210E000E9A240500930A000B0763
-:102C60008FBF00589202000924030018304200FF71
-:102C70001443000D02402021240500390E000E32BD
-:102C8000000030210E0003528F84001C8F82FF9CB5
-:102C900024030012A04300090E00035D8F84001C72
-:102CA0000A000B078FBF0058240500360E000E32B5
-:102CB000000030210A000B078FBF00580E0003529E
-:102CC00002402021920200058F84001C3442002023
-:102CD0000E00035DA20200050E0010438F84001C4D
-:102CE0008FBF00588FB300548FB200508FB1004C8B
-:102CF0008FB0004803E0000827BD00603C02800858
-:102D0000344501003C0280008C42014094A3000E37
-:102D10000000302100402021AF82001C3063FFFF03
-:102D20003402FFFF106200063C0760202402FFFF10
-:102D3000A4A2000E94A500DA0A0008FA30A5FFFF4D
-:102D400003E000080000000027BDFFC83C0280002F
-:102D50003C068008AFB5002CAFB1001CAFBF0030FF
-:102D6000AFB40028AFB30024AFB20020AFB000185A
-:102D70003451010034C501008C4301008E2200143F
-:102D80008CA400D40000A821AF83001C00441023B1
-:102D900018400052A38000188E2200140000502119
-:102DA000ACA200D490C3000890A200C53073007F8D
-:102DB000A3A200108CB200D08CB400D4304200FF2B
-:102DC0001053003B93A200108F83001C2407FF8048
-:102DD000000211C00062102124420240246300401E
-:102DE000004710243063007F3C0980003C08800AC3
-:102DF00000681821AD2200248C62003427A400143E
-:102E000027A50010024280210290102304400028D0
-:102E1000AFA300149062003C00E21024304200FF97
-:102E200014400019020090219062003C344200409E
-:102E3000A062003C8F86001C93A3001024C20040B7
-:102E40003042007F004828213C0208008C4200F4F8
-:102E500024630001306400FF14820002A3A3001069
-:102E6000A3A0001093A20010AFA50014000211C08F
-:102E70002442024000C2102100471024AD22002449
-:102E80000A000B3E93A200100E0007BC00000000D9
-:102E90003C02800834420100AC5000D093A30010E3
-:102EA000240A0001A04300C50A000B3E93A20010B3
-:102EB00024020001154200093C0380008C62027864
-:102EC0000440FFFE8F82001CAC620240240200021C
-:102ED000A06202443C021000AC6202789222000B15
-:102EE00024030002304200FF14430072000000007F
-:102EF00096220008304300FF240200821462004042
-:102F0000240200843C028000344901008D22000C20
-:102F100095230006000216023063FFFF3045003F94
-:102F20002402002710A2000FAF83001428A200285B
-:102F300010400008240200312402002110A20009E0
-:102F40002402002510A20007938200190A000BB684
-:102F50000000000010A20007938200190A000BB6BF
-:102F6000000000000E000770012020210A000C362E
-:102F7000000000003C0380008C6202780440FFFEE9
-:102F80008F82001CAC62024024020002A062024454
-:102F90003C021000AC6202780A000C36000000000F
-:102FA00095230006912400058D25000C8D26001028
-:102FB0008D2700188D28001C8D2900202442000137
-:102FC0003C010800A423530E3C010800A024530D2B
-:102FD0003C010800AC2553143C010800AC265318F2
-:102FE0003C010800AC2753203C010800AC285324C6
-:102FF0003C010800AC2953280A000C36A3820019B2
-:103000001462000A240200813C028008344201005C
-:10301000944500DA922600058F84001C30A5FFFF3E
-:1030200030C600FF0A000BF73C0760211462005C09
-:10303000000000009222000A304300FF30620020AE
-:1030400010400007306200403C028008344201001A
-:10305000944500DA8F84001C0A000BF5240600401A
-:1030600010400007000316003C02800834420100B3
-:10307000944500DA8F84001C0A000BF524060041F9
-:1030800000021603044100463C028008344201005D
-:10309000944500DA8F84001C2406004230A5FFFF0F
-:1030A0003C0760190E0008FA000000000A000C3608
-:1030B000000000009222000B24040016304200FFA2
-:1030C000104400063C0680009222000B24030017E7
-:1030D000304200FF144300320000000034C50100FC
-:1030E00090A2000B304200FF1444000B000080212E
-:1030F0008CA200208CA400202403FF800043102415
-:10310000000211403084007F004410253C03200061
-:1031100000431025ACC2083094A20008000214003D
-:1031200000021403044200012410000194A20008CC
-:10313000304200805040001A0200A82194A20008EA
-:1031400030422000504000160200A8218CA3001835
-:103150003C021C2D344219ED106200110200A8211E
-:103160003C0208008C4200D4104000053C0280085C
-:103170002403000434420100A04300EC3C02800818
-:1031800034420100944500DA8F84001C24060006B6
-:1031900030A5FFFF0E0008FA3C0760210200A821BD
-:1031A0000E000932000000009222000A304200089E
-:1031B0001040000402A010210E0013470000000080
-:1031C00002A010218FBF00308FB5002C8FB40028D3
-:1031D0008FB300248FB200208FB1001C8FB0001875
-:1031E00003E0000827BD00382402FF80008220246D
-:1031F0003C02900034420007008220253C028000FF
-:10320000AC4400203C0380008C6200200440FFFEA0
-:103210000000000003E00008000000003C03800004
-:103220002402FF80008220243462000700822025CF
-:10323000AC6400208C6200200440FFFE000000000F
-:1032400003E00008000000003C02800824030005A1
-:1032500034420100A04300EC3C0280008C4201009B
-:103260003C038000AF82001C8C6202780440FFFEA9
-:103270008F82001CAC62024024020002A062024461
-:103280003C021000AC62027803E00008000000007D
-:1032900027BDFFE83C068000AFBF001034C7010027
-:1032A00094E20008304400FF3883008238820084B2
-:1032B0002C6300012C420001006218251060002DD3
-:1032C0002402008393820019504000368FBF001003
-:1032D0003C020800904253148CC401003C060800D4
-:1032E00094C6530E3045003F38A3003238A2003F49
-:1032F0002C6300012C42000100621825AF84001CE1
-:10330000AF860014A38000191460000700E020219C
-:103310002402002014A20012000000003402FFFF6B
-:1033200014C2000F000000002402002014A20005B7
-:1033300000E028218CE300142402FFFF5062000B00
-:103340008FBF00103C040800248453080000302183
-:103350000E0006FF240700010A000CA98FBF001011
-:103360000E000770000000008FBF00100A00093235
-:1033700027BD0018148200062482FF808CC301043C
-:103380003C026020AC4300140A000CDF8FBF001029
-:10339000304200FF2C4200021040000424020022B0
-:1033A0008FBF00100A000B2027BD001814820004F4
-:1033B0008F8200248FBF00100A000C6027BD001808
-:1033C0008C42000C1040001E00E0282190E3000910
-:1033D0002402001814620003240200160A000CCA1A
-:1033E00024030008146200072402001724030012BB
-:1033F0003C02800834420080A04300090A000CD738
-:1034000094A700085462000794A700088F82FF9CCD
-:103410002404FFFE9043000500641824A043000527
-:1034200094A7000890A6001B8CA4000094A5000699
-:103430008FBF001000073C000A0008D527BD001808
-:103440008FBF001003E0000827BD00188F850024FF
-:103450003C04800094A2002A8CA30034000230C0F7
-:103460002402FFF000C2102400621821AC83003C4B
-:103470008CA200303C038000AC8200383C0200503B
-:1034800034420010AC620030000000000000000078
-:10349000000000008C620000304200201040FFFD60
-:1034A00030C20008104000063C0280008C62040814
-:1034B000ACA200208C62040C0A000D02ACA2002415
-:1034C0008C430400ACA300208C420404ACA2002472
-:1034D0003C0300203C028000AC4300303C048000F0
-:1034E0008C820030004310241440FFFD8F8600249E
-:1034F0003C020040AC82003094C3002A94C20028F1
-:1035000094C4002C94C5002E2463000100441021B3
-:103510003064FFFFA4C2002814850002A4C3002A5F
-:10352000A4C0002A03E00008000000008F840024EB
-:1035300027BDFFE83C05800424840010AFBF0010C5
-:103540000E000E152406000A8F84002494820012B7
-:103550009483002E3042000F2442000300431804DD
-:1035600024027FFF0043102B10400002AC830000B8
-:103570000000000D0E000CE1000000008F8300240D
-:103580008FBF001027BD0018946200149463001AC6
-:103590003042000F00021500006218253C02800036
-:1035A00003E00008AC4300A08F8300243C028004A9
-:1035B000944400069462001A8C650000A46400160E
-:1035C000004410233042FFFF0045102B03E00008A9
-:1035D000384200018F8400243C0780049486001A3E
-:1035E0008C85000094E20006A482001694E3000695
-:1035F00000C310233042FFFF0045102B384200016A
-:103600001440FFF8A483001603E000080000000047
-:103610008F8400243C028004944200069483001AA4
-:103620008C850000A4820016006210233042FFFF48
-:103630000045102B384200015040000D8F850024BA
-:10364000006030213C07800494E20006A48200164A
-:1036500094E3000600C310233042FFFF0045102B07
-:10366000384200011440FFF8A48300168F8500241F
-:103670003C038000346204008CA40020AF82002050
-:10368000AC6400388CA20024AC62003C3C02000513
-:10369000AC62003003E00008ACA000048F8400247A
-:1036A0003C0300068C8200040002114000431025F8
-:1036B0003C038000AC62003000000000000000000D
-:1036C000000000008C620000304200101040FFFD3E
-:1036D00034620400AC80000403E00008AF820020E4
-:1036E0008F86002427BDFFE0AFB10014AFB00010FB
-:1036F000AFBF00188CC300048CC500248F8200204B
-:10370000309000FF94C4001A24630001244200207A
-:103710002484000124A70020ACC30004AF82002051
-:10372000A4C4001AACC7002404A10006000088212C
-:1037300004E2000594C2001A8CC200202442000159
-:10374000ACC2002094C2001A94C300282E040001C9
-:10375000004310262C420001004410245040000574
-:1037600094C2001A24020001ACC2000894C2001ADC
-:1037700094C300280010202B004310262C42000187
-:103780000044102514400007000000008CC200080F
-:1037900014400004240200108CC300041462000FC3
-:1037A0008F8500240E000D75241100018F820024E6
-:1037B000944300289442001A1443000300000000C0
-:1037C0000E000CE100000000160000048F850024AC
-:1037D0000E000D52000000008F85002494A2001EF0
-:1037E00094A4001C244200013043FFFF1464000233
-:1037F000A4A2001EA4A0001E1200000A3C02800425
-:1038000094A2001494A3001A3042000F0002150085
-:10381000006218253C028000AC4300A00A000DECB9
-:10382000ACA000089442000694A3001A8CA40000E7
-:10383000A4A20016006210233042FFFF0044102BA8
-:10384000384200011040000D02201021006030219C
-:103850003C07800494E20006A4A2001694E300064C
-:1038600000C310233042FFFF0044102B38420001F8
-:103870001440FFF8A4A30016022010218FBF0018E7
-:103880008FB100148FB0001003E0000827BD0020A6
-:1038900003E00008000000008F82002C3C030006BB
-:1038A00000021140004310253C038000AC62003050
-:1038B0000000000000000000000000008C6200001A
-:1038C000304200101040FFFD34620400AF82002837
-:1038D00003E00008AF80002C03E000080000102186
-:1038E00003E00008000000003084FFFF30A5FFFF68
-:1038F0000000182110800007000000003082000145
-:103900001040000200042042006518210A000E0B3E
-:103910000005284003E000080060102110C00006E8
-:1039200024C6FFFF8CA2000024A50004AC82000086
-:103930000A000E152484000403E0000800000000C3
-:1039400010A0000824A3FFFFAC86000000000000C8
-:10395000000000002402FFFF2463FFFF1462FFFA4F
-:103960002484000403E00008000000003C028008FA
-:103970003442008024030001AC43000CA443001037
-:10398000A4430012A443001403E00008A44300165B
-:103990008F82002427BDFFD8AFB3001CAFB2001840
-:1039A000AFB10014AFB00010AFBF00208C47000CC7
-:1039B000248200802409FF803C08800E3043007F71
-:1039C000008080213C0A80000049202400681821E2
-:1039D00030B100FF30D200FF10E000290000982134
-:1039E00026020100AD44002C004928243042007F0B
-:1039F000004820219062000024030050304200FF64
-:103A00001443000400000000AD45002C948200DA4D
-:103A10003053FFFF0E000D52000000008F82002483
-:103A20008F83002000112C009442001E00122400FD
-:103A30003484000100A228253C02400000A2282571
-:103A4000AC7000008FBF0020AC6000048FB2001883
-:103A5000AC7300088FB10014AC60000C8FB3001C75
-:103A6000AC6400108FB00010AC600014240400019E
-:103A7000AC60001827BD00280A000D86AC65001C4C
-:103A80008FBF00208FB3001C8FB200188FB10014BD
-:103A90008FB0001003E0000827BD00283C0680001E
-:103AA00034C201009043000F240200101062000E87
-:103AB0002865001110A0000724020012240200084B
-:103AC0002405003A106200060000302103E00008DF
-:103AD00000000000240500351462FFFC00003021C6
-:103AE0000A000E32000000008CC200748F83FF9C1D
-:103AF00024420FA003E00008AC62000C27BDFFE8E1
-:103B0000AFBF00100E000362240500013C048008D2
-:103B10008FBF00102402000134830080A4620012D1
-:103B200027BD00182402000103E00008A080001A4D
-:103B300027BDFFE0AFB20018AFB10014AFB0001066
-:103B4000AFBF001C30B2FFFF0E000352008088217F
-:103B50003C028008345000809202000924030004D3
-:103B6000304200FF1443000C3C0280081240000861
-:103B70002402000A0E000E29000000009202000537
-:103B80002403FFFE00431024A202000524020012B9
-:103B9000A20200093C028008344200800220202159
-:103BA0000E00035DA04000271640000302202021E4
-:103BB0000E000E8D0000000002202021324600FF82
-:103BC0008FBF001C8FB200188FB100148FB000108F
-:103BD000240500380A000E3227BD002027BDFFE073
-:103BE000AFBF001CAFB20018AFB10014AFB00010EF
-:103BF0000E000352008080210E000E2900000000FC
-:103C00003C0280083445008090A20009241200186C
-:103C1000305100FF12320003020020212402001262
-:103C2000A0A2000990A200052403FFFE0043102477
-:103C30000E00035DA0A20005020020212405002043
-:103C400016320007000030218FBF001C8FB2001811
-:103C50008FB100148FB000100A00036227BD00204E
-:103C60008FBF001C8FB200188FB100148FB00010EE
-:103C7000240500390A000E3227BD002027BDFFE8C9
-:103C80003C028000AFB00010AFBF0014344201000E
-:103C90009442000C2405003600808021144000125C
-:103CA000304600FF0E000352000000003C02800876
-:103CB0003442008024030012A04300099043000511
-:103CC000346300100E000E29A04300050E00035DB2
-:103CD00002002021020020210E00036224050020A2
-:103CE0000A000F0A000000000E000E320000000063
-:103CF0000E000352020020213C0280089043001B6A
-:103D00002405FF9F02002021006518248FBF0014A6
-:103D10008FB00010A043001B0A00035D27BD0018F0
-:103D200027BDFFE0AFBF0018AFB10014AFB0001067
-:103D300030B100FF0E000352008080213C02800859
-:103D400024030012344200800E000E29A043000913
-:103D50000E00035D020020210200202102203021FC
-:103D60008FBF00188FB100148FB0001024050035EC
-:103D70000A000E3227BD00203C0480089083000E0C
-:103D80009082000A1443000B000028218F82FF9CC0
-:103D9000240300502405000190420000304200FF3F
-:103DA00014430004000000009082000E2442000131
-:103DB000A082000E03E0000800A010213C03800058
-:103DC0008C6201F80440FFFE24020002AC6401C0D2
-:103DD000A06201C43C02100003E00008AC6201F8DC
-:103DE00027BDFFE0AFB200183C128008AFB100144D
-:103DF000AFBF001CAFB00010365100809222000906
-:103E00002403000A304200FF1443003E000000007B
-:103E10008E4300048E220038506200808FBF001C49
-:103E20009222000024030050304200FF144300257A
-:103E30003C0280008C4201408E4300043642010067
-:103E400002202821AC43001C9622005C8E230038FF
-:103E50003042FFFF0002104000621821AE23001C18
-:103E60008E4300048E2400389622005C00641823E0
-:103E70003042FFFF00031843000210400043102AA5
-:103E800010400006000000008E4200048E2300381F
-:103E9000004310230A000F78000220439622005CA2
-:103EA0003042FFFF000220403C0280083443010002
-:103EB00034420080ACA4002CA04000242402000165
-:103EC000A062000C0E000F2C0000000010400053F8
-:103ED0008FBF001C3C0280008C4401403C038000EA
-:103EE0008C6201F80440FFFE24020002AC6401C0B1
-:103EF000A06201C43C021000AC6201F80A000FD5B8
-:103F00008FBF001C9222000924030010304200FFE2
-:103F1000144300043C0280008C4401400A000FBCA2
-:103F2000000028219222000924030016304200FFDD
-:103F30001443000624020014A22200093C0280005F
-:103F40008C4401400A000FCF8FBF001C8E22003826
-:103F50008E23003C00431023044100308FBF001C1F
-:103F60009222002724420001A22200279222002749
-:103F70002C420004144000163C10800092220009DC
-:103F800024030004304200FF144300093C02800077
-:103F90008C4401408FBF001C8FB200188FB10014F9
-:103FA0008FB00010240500930A000E9A27BD002050
-:103FB0008C440140240500938FBF001C8FB2001871
-:103FC0008FB100148FB000100A000F1627BD00201B
-:103FD0008E0401400E000352000000008E420004D7
-:103FE0002442FFFFAE4200048E22003C2442FFFF29
-:103FF000AE22003C0E00035D8E0401408E040140A1
-:104000008FBF001C8FB200188FB100148FB000104A
-:10401000240500040A00036227BD00208FB20018A7
-:104020008FB100148FB0001003E0000827BD0020FE
-:104030003C0680008CC201883C0380083465008007
-:104040009063000E00021402304400FF306300FF52
-:104050001464000E3C02800890A20026304200FF4B
-:10406000104400098F82FF9CA0A400262403005066
-:1040700090420000304200FF1443000600000000A0
-:104080000A00059A8CC401803C02800834420080FA
-:10409000A044002603E000080000000027BDFFE068
-:1040A00030E700FFAFB20018AFBF001CAFB1001483
-:1040B000AFB000100080902114E0000630C600FF71
-:1040C000000000000000000D000000000A00102E9B
-:1040D0002400010E3C0380089062000E304200FF75
-:1040E000144600233462008090420026304200FFD4
-:1040F0001446001F000000009062000F304200FFD5
-:104100001446001B000000009062000A304200FFCD
-:10411000144600038F90FF9C0000000D8F90FF9CC1
-:104120008F82FFA03C118000AE05003CAC45000032
-:10413000A066000A0E0003528E240100A200002493
-:104140000E00035D8E2401003C0380008C6201F8A8
-:104150000440FFFE24020002AC7201C0A06201C450
-:104160003C021000AC6201F80A00102F8FBF001C47
-:10417000000000000000000D0000000024000137D6
-:104180008FBF001C8FB200188FB100148FB00010C9
-:1041900003E0000827BD00208F83FF9C3C028000C5
-:1041A0008C440100344201008C65003C9046001BA9
-:1041B0000A000FF5240700013C0280089043000E1E
-:1041C0009042000A00431026304200FF03E000083E
-:1041D0000002102B27BDFFE03C028008AFB10014A5
-:1041E000AFB00010AFBF001834500080920200053D
-:1041F00024030030304200301443008500808821C1
-:104200008F8200248C42000C104000828FBF001867
-:104210000E000D52000000008F860020ACD100007F
-:104220009202000892030009304200FF00021200CF
-:10423000306300FF00431025ACC200049202004D21
-:1042400000021600000216030441000500000000F1
-:104250003C0308008C6300480A00106D3C10800885
-:104260009202000830420040144000030000182170
-:1042700092020027304300FF3C1080083611008076
-:104280009222004D00031E00304200FF0002140085
-:1042900000621825ACC300088E2400308F820024F1
-:1042A000ACC4000C8E2500349443001E3C02C00BAD
-:1042B000ACC50010006218258E22003800002021B5
-:1042C000ACC200148E22003CACC200180E000D8659
-:1042D000ACC3001C8E0200048F8400203C058000CB
-:1042E000AC8200008E220020AC8200048E22001CD2
-:1042F000AC8200088E2200588CA300740043102169
-:10430000AC82000C8E22002CAC8200108E22004069
-:104310008E2300440002140000431025AC820014D8
-:104320009222004D24030080304200FF1443000419
-:1043300000000000AC8000180A0010B18F82002439
-:104340008E23000C240200011062000E2402FFFFE5
-:1043500092220008304200401440000A2402FFFF6D
-:104360008E23000C8CA20074006218233C0208000B
-:10437000006210241440000200002821006028215F
-:1043800000051043AC8200188F8200240000202119
-:104390009443001E3C02C00C006218258F8200204E
-:1043A0000E000D86AC43001C3C0380083462010003
-:1043B0008C4200008F850020346300808FBF00187E
-:1043C000ACA20000ACA000048C6400488F820024E2
-:1043D0008FB10014ACA40008ACA0000CACA000107D
-:1043E000906300059446001E3C02400D00031E0031
-:1043F00000C23025ACA300148FB00010ACA0001890
-:1044000024040001ACA6001C0A000D8627BD002074
-:104410008FBF00188FB100148FB0001003E00008A8
-:1044200027BD00203C0280009443007C3C028008B1
-:1044300034460100308400FF3065FFFF2402000590
-:1044400024A34650A0C4000C5482000C3065FFFF2A
-:1044500090C2000D2C4200071040000724A30A0060
-:1044600090C3000D240200140062100400A2102169
-:104470000A0010ED3045FFFF3065FFFF3C02800869
-:104480003442008003E00008A44500143C03800887
-:1044900034680080AD050038346701008CE2001CF0
-:1044A000308400FF00A210231840000330C600FF34
-:1044B00024A2FFFCACE2001C308200015040000846
-:1044C0003C0380088D02003C00A21023044100122E
-:1044D000240400058C62000410A2000F3C03800835
-:1044E0008C62000414A2001E000000003C020800C0
-:1044F0008C4200D830420020104000093C02800865
-:1045000034620080906300089042004C1443000421
-:104510003C028008240400040A0010D700000000B8
-:104520003443008034420100A040000C240200010A
-:10453000A462001410C0000A3C0280008C440100F8
-:104540003C0380008C6201F80440FFFE240200025C
-:10455000AC6401C0A06201C43C021000AC6201F86E
-:1045600003E000080000000027BDFFE800A61823B4
-:10457000AFBF001018600080308800FF3C02800848
-:1045800034470080A0E0002434440100A0E000276C
-:104590008C82001C00A21023044000560000000082
-:1045A0008CE2003C94E3005C8CE4002C004530235A
-:1045B0003063FFFF00C318210083202B108000040C
-:1045C00000E018218CE2002C0A00114600A2102104
-:1045D00094E2005C3042FFFF00C2102100A21021D3
-:1045E000AC62001C3C028008344400809482005C71
-:1045F0008C83001C3042FFFF0002104000A21021FB
-:104600000043102B10400004000000008C82001CAE
-:104610000A0011593C0680089482005C3042FFFF7A
-:104620000002104000A210213C06800834C30100A3
-:1046300034C70080AC82001CA060000CACE50038E0
-:104640008C62001C00A210231840000224A2FFFC70
-:10465000AC62001C31020001104000083C038008DD
-:104660008CE2003C00A21023044100122404000547
-:104670008CC2000410A200108FBF00108C620004D6
-:1046800014A2004F8FBF00103C0208008C4200D8DB
-:10469000304200201040000A3C0280083462008052
-:1046A000906300089042004C144300053C028008CF
-:1046B000240400048FBF00100A0010D727BD001883
-:1046C0003443008034420100A040000C2402000169
-:1046D000A46200143C0280008C4401003C03800072
-:1046E0008C6201F80440FFFE240200020A0011A6B9
-:1046F000000000008CE2001C004610230043102B39
-:1047000054400001ACE5001C94E2005C3042FFFF25
-:104710000062102B144000072402000294E2005CA7
-:104720008CE3001C3042FFFF00621821ACE3001C48
-:1047300024020002ACE500380E000F2CA082000C11
-:104740001040001F8FBF00103C0280008C4401000D
-:104750003C0380008C6201F80440FFFE240200024A
-:10476000AC6401C0A06201C43C021000AC6201F85C
-:104770000A0011BE8FBF001031020010104000105F
-:104780008FBF00103C028008344500808CA3001CC1
-:1047900094A2005C006618233042FFFF00621821DB
-:1047A0003C023FFF3444FFFF0083102B54400001C4
-:1047B0000080182100C31021ACA2001C8FBF001084
-:1047C00003E0000827BD001827BDFFE800C0402116
-:1047D00000A63023AFBF001018C00026308A00FFAB
-:1047E0003C028008344900808D24001C8D23002C5D
-:1047F000008820230064182B1060000F344701004C
-:104800008CE2002000461021ACE200208CE2002067
-:104810000044102B1440000B3C023FFF8CE20020B0
-:1048200000441023ACE200209522005C3042FFFFE0
-:104830000A0011DE00822021ACE000200086202149
-:104840003C023FFF3443FFFF0064102B5440000143
-:10485000006020213C02800834420080008518213D
-:10486000AC43001CA0400024A04000270A001230E6
-:104870003C03800831420010104000433C03800894
-:104880003C06800834C400808C82003C0048102321
-:104890005840003E3466008090820024244200018B
-:1048A000A0820024908200243C0308008C63002432
-:1048B000304200FF0043102B144000688FBF0010EF
-:1048C00034C201008C42001C00A210231840006377
-:1048D000000000008CC300049482005C0068182370
-:1048E0003042FFFF00031843000210400043102A2B
-:1048F00010400005000000008CC200040048102396
-:104900000A001213000210439482005C3042FFFF41
-:10491000000210403C068008AC82002C34C50080A8
-:1049200094A2005C8CA4002C94A3005C3042FFFF96
-:1049300000021040008220213063FFFF008320210D
-:1049400001041021ACA2001C8CC2000434C601007A
-:10495000ACC2001C240200020E000F2CA0C2000CEE
-:104960001040003E8FBF00103C0280008C440100CC
-:104970003C0380008C6201F80440FFFE2402000228
-:104980000A0012600000000034660080ACC50038E8
-:10499000346401008C82001C00A210231840000225
-:1049A00024A2FFFCAC82001C314200015040000AEE
-:1049B0003C0380088CC2003C00A210230443001476
-:1049C000240400058C62000414A200033C03800848
-:1049D0000A001252240400058C62000414A2001F75
-:1049E0008FBF00103C0208008C4200D830420020EB
-:1049F0001040000A3C028008346200809063000886
-:104A00009042004C144300053C028008240400043A
-:104A10008FBF00100A0010D727BD00183443008054
-:104A200034420100A040000C24020001A4620014E2
-:104A30003C0280008C4401003C0380008C6201F841
-:104A40000440FFFE24020002AC6401C0A06201C465
-:104A50003C021000AC6201F88FBF001003E00008B8
-:104A600027BD001827BDFFE83C0A8008AFBF001033
-:104A7000354900808D22003C00C04021308400FF79
-:104A8000004610231840009D30E700FF3547010025
-:104A90002402000100A63023A0E0000CA0E0000DDD
-:104AA000A522001418C00024308200108D23001CA1
-:104AB0008D22002C006818230043102B1040000F9B
-:104AC000000000008CE2002000461021ACE2002033
-:104AD0008CE200200043102B1440000B3C023FFFEF
-:104AE0008CE2002000431023ACE200209522005C01
-:104AF0003042FFFF0A00128F00621821ACE0002054
-:104B0000006618213C023FFF3446FFFF00C3102B14
-:104B10005440000100C018213C028008344200804B
-:104B200000651821AC43001CA0400024A0400027D1
-:104B30000A0012DD3C038008104000403C0380085E
-:104B40008D22003C004810235840003D346700800F
-:104B50009122002424420001A12200249122002459
-:104B60003C0308008C630024304200FF0043102BFC
-:104B70001440009A8FBF00108CE2001C00A210238A
-:104B800018400096000000008D4300049522005C50
-:104B9000006818233042FFFF000318430002104052
-:104BA0000043102A10400005012020218D420004FE
-:104BB000004810230A0012C0000210439522005C36
-:104BC0003042FFFF000210403C068008AC82002CFF
-:104BD00034C5008094A2005C8CA4002C94A3005CDB
-:104BE0003042FFFF00021040008220213063FFFFAF
-:104BF0000083182101031021ACA2001C8CC2000408
-:104C000034C60100ACC2001C240200020E000F2CAE
-:104C1000A0C2000C104000718FBF00103C02800049
-:104C20008C4401003C0380008C6201F80440FFFECC
-:104C3000240200020A00130700000000346700800D
-:104C4000ACE50038346601008CC2001C00A21023C1
-:104C50001840000224A2FFFCACC2001C30820001FC
-:104C6000504000083C0380088CE2003C00A2102366
-:104C700004430051240400058C62000410A2003E8D
-:104C80003C0380088C62000454A200548FBF0010C3
-:104C90003C0208008C4200D8304200201040000640
-:104CA0003C02800834620080906300089042004C0F
-:104CB000104300403C02800834430080344201002D
-:104CC000A040000C24020001A46200143C028000F9
-:104CD0008C4401003C0380008C6201F80440FFFE1C
-:104CE00024020002AC6401C0A06201C43C021000B6
-:104CF000AC6201F80A0013458FBF001024020005C2
-:104D0000A120002714E2000A3C038008354301007B
-:104D10009062000D2C420006504000053C038008C4
-:104D20009062000D24420001A062000D3C03800847
-:104D300034670080ACE50038346601008CC2001C8A
-:104D400000A210231840000224A2FFFCACC2001CE9
-:104D5000308200015040000A3C0380088CE2003C95
-:104D600000A2102304410014240400058C620004F6
-:104D700014A200033C0380080A00133C240400052D
-:104D80008C62000414A200158FBF00103C020800C2
-:104D90008C4200D8304200201040000A3C028008BB
-:104DA00034620080906300089042004C1443000578
-:104DB0003C028008240400048FBF00100A0010D7B2
-:104DC00027BD00183443008034420100A040000C8D
-:104DD00024020001A46200148FBF001003E0000849
-:104DE00027BD00183C0B800827BDFFE83C0280006F
-:104DF000AFBF001034420100356A00809044000AC1
-:104E0000356901008C4500148D4800389123000C51
-:104E1000308400FF010510231C4000B3306700FF01
-:104E20002CE20006504000B18FBF001024020001A8
-:104E300000E2300430C200035440000800A83023D0
-:104E400030C2000C144000A130C20030144000A356
-:104E50008FBF00100A0014090000000018C00024D1
-:104E6000308200108D43001C8D42002C00681823F6
-:104E70000043102B1040000F000000008D22002086
-:104E800000461021AD2200208D2200200043102B6F
-:104E90001440000B3C023FFF8D22002000431023F2
-:104EA000AD2200209542005C3042FFFF0A00137DD6
-:104EB00000621821AD200020006618213C023FFF4F
-:104EC0003446FFFF00C3102B5440000100C01821DE
-:104ED0003C0280083442008000651821AC43001C6D
-:104EE000A0400024A04000270A0013CB3C03800808
-:104EF000104000403C0380088D42003C00481023D5
-:104F00001840003D34670080914200242442000193
-:104F1000A1420024914200243C0308008C63002439
-:104F2000304200FF0043102B144000708FBF001070
-:104F30008D22001C00A210231840006C000000000D
-:104F40008D6300049542005C006818233042FFFF27
-:104F500000031843000210400043102A10400005CF
-:104F6000014020218D620004004810230A0013AE86
-:104F7000000210439542005C3042FFFF00021040E7
-:104F80003C068008AC82002C34C5008094A2005CF2
-:104F90008CA4002C94A3005C3042FFFF0002104060
-:104FA000008220213063FFFF0083182101031021BC
-:104FB000ACA2001C8CC2000434C60100ACC2001CB0
-:104FC000240200020E000F2CA0C2000C104000476B
-:104FD0008FBF00103C0280008C4401003C03800025
-:104FE0008C6201F80440FFFE240200020A0013FB59
-:104FF0000000000034670080ACE500383466010032
-:105000008CC2001C00A210231840000224A2FFFC46
-:10501000ACC2001C308200015040000A3C038008F2
-:105020008CE2003C00A21023044300142404000579
-:105030008C62000414A200033C0380080A0013EDF4
-:10504000240400058C62000414A200288FBF001005
-:105050003C0208008C4200D8304200201040000A78
-:105060003C02800834620080906300089042004C4B
-:10507000144300053C028008240400048FBF001084
-:105080000A0010D727BD00183443008034420100C5
-:10509000A040000C24020001A46200143C02800025
-:1050A0008C4401003C0380008C6201F80440FFFE48
-:1050B00024020002AC6401C0A06201C43C021000E2
-:1050C000AC6201F80A0014098FBF00108FBF0010F6
-:1050D000010030210A00112827BD001801003021ED
-:1050E0000A00126727BD00188FBF001003E00008F8
-:1050F00027BD00183C03800834640100240200032B
-:10510000A082000C8C62000403E00008AC82001C4A
-:105110003C05800834A300809062002734A501007C
-:105120002406004324420001A06200279063002768
-:105130003C0208008C420048306300FF1462000407
-:105140003C07602194A500DA0A0008FA30A5FFFFA9
-:1051500003E000080000000027BDFFE8AFBF00101B
-:105160003C0280000E0014128C4401803C02800836
-:1051700034430100A060000C8C4200048FBF00107B
-:1051800027BD001803E00008AC62001C27BDFFE04B
-:105190003C028008AFBF0018AFB10014AFB00010E0
-:1051A00034450080344601003C0880008D090140F0
-:1051B00090C3000C8CA4003C8CA200381482003BED
-:1051C000306700FF9502007C90A30027146000095F
-:1051D0003045FFFF2402000554E200083C0480082B
-:1051E00090C2000D24420001A0C2000D0A00144D1F
-:1051F0003C048008A0C0000D3C04800834820100FB
-:105200009042000C24030005304200FF1443000AC2
-:1052100024A205DC34830080906200272C42000722
-:105220005040000524A20A009063002724020014C5
-:105230000062100400A210213C108008361000808B
-:105240003045FFFF012020210E001412A605001496
-:105250009602005C8E0300383C1180003042FFFF54
-:105260000002104000621821AE03001C0E00035221
-:105270008E2401409202002534420040A202002503
-:105280000E00035D8E2401408E2401403C0380000B
-:105290008C6201F80440FFFE24020002AC6401C0ED
-:1052A000A06201C43C021000AC6201F88FBF00187C
-:1052B0008FB100148FB0001003E0000827BD00205C
-:1052C00080080100800800808008000000000C8039
-:1052D000000032008008024008000F1008000F682C
-:1052E00008000FAC0800104408001084800801007A
-:0852F000800800808008000026
-:0852F8000A0000220000000082
-:10530000000000000000000D6370352E302E306A62
-:10531000313500000500000400000000000000001E
-:1053200000000000000000000000000038003C0009
-:10533000000000000000000000000000000000006D
-:10534000000000200000000000000000000000003D
-:10535000000000000000000000000000000000004D
-:1053600000000000000000000000000021003800E4
-:10537000000000010000002B000000000000000001
-:105380000000000010000003000000000000000DFD
-:105390000000000D3C020800244255043C030800B4
-:1053A00024635744AC4000000043202B1480FFFDD1
-:1053B000244200043C1D080037BD9FFC03A0F021DF
-:1053C0003C100800261000883C1C0800279C55044F
-:1053D0000E00029A000000000000000D00A018213D
-:1053E00000801021008028213C0460003C07600000
-:1053F0002406000810600006348420788C420000E7
-:10540000ACE220088C63000003E00008ACE3200C51
-:105410000A000E6000000000240300403C0260000F
-:1054200003E00008AC4320003C0760008F860004C6
-:105430008CE520740086102100A2182B1460000750
-:10544000000028218F8AFD9024050001A14400134B
-:105450008F89000401244021AF88000403E0000884
-:1054600000A010218F84FD908F850004908600138A
-:1054700030C300FF00A31023AF82000403E0000844
-:10548000A08000138F84FD9027BDFFE8AFB000100F
-:10549000AFBF0014908900119087001124020028EA
-:1054A000312800FF3906002830E300FF2485002C56
-:1054B0002CD00001106200162484001C0E0000395C
-:1054C000000000008F8FFD903C0560002402020464
-:1054D00095EE003E95ED003C000E5C0031ACFFFF08
-:1054E000016C5025ACAA20105200000124020004D7
-:1054F000ACA220000000000000000000000000003E
-:105500008FBF00148FB0001003E0000827BD001803
-:105510000A000071000028218F85FD9027BDFFD86B
-:10552000AFBF0020AFB3001CAFB20018AFB1001482
-:10553000AFB000100080982190A4001124B0001C8E
-:1055400024B1002C308300FF386200280E00005B7D
-:105550002C5200010E000063000000000200202118
-:105560001240000202202821000028210E000039EC
-:10557000000000008F8DFD903C0880003C0560001D
-:1055800095AC003E95AB003C02683025000C4C0009
-:10559000316AFFFF012A3825ACA72010240202023D
-:1055A000ACA6201452400001240200028FBF00204C
-:1055B0008FB3001C8FB200188FB100148FB0001091
-:1055C00027BD002803E00008ACA2200027BDFFE0B3
-:1055D000AFB20018AFB10014AFB00010AFBF001CE5
-:1055E0003C1160008E2320748F82000430D0FFFFB6
-:1055F00030F2FFFF1062000C2406008F0E0000390D
-:10560000000000003C06801F0010440034C5FF006D
-:105610000112382524040002AE272010000030219A
-:10562000AE252014AE2420008FBF001C8FB20018BE
-:105630008FB100148FB0001000C0102103E00008EB
-:1056400027BD002027BDFFE0AFB0001030D0FFFF26
-:10565000AFBF0018AFB100140E00003930F1FFFFEA
-:1056600000102400009180253C036000AC702010E5
-:105670008FBF00188FB100148FB0001024020004F7
-:10568000AC62200027BD002003E0000800001021CC
-:1056900027BDFFE83C0B6018AFBF00108D6F5000B6
-:1056A0002418FF7F340C807101F8702435CD380C3C
-:1056B000240A00313C098000AD6D50003C08800A8E
-:1056C000AD6C53BCAD2A00080E0004D1AF88004079
-:1056D0000E00048F000000000E00004800000000D3
-:1056E0003C0760008CE508082406FFF03C035709DE
-:1056F00000A620243462F000108200622419000108
-:10570000AF80004C0E000BF2000000003C0660165B
-:105710003C0760148CC400008CE500A03C03FFFF34
-:10572000008310243C1F535300052FC2105F004F0D
-:1057300034C77C0094E201F2A780006410400003AB
-:10574000A7800074384B1E1EA78B006494E201F8FA
-:10575000104000048F8D004C384C1E1EA78C007426
-:105760008F8D004C11A0000497840074240E00203B
-:10577000A78E0064978400742C8F008151E0000193
-:1057800024040080978600642CD804015300000193
-:10579000240604003C0260008C4504382419103CA7
-:1057A00030BFFFFF13F900033083FFFF10600018C4
-:1057B00024080050A38000769389007651200019B8
-:1057C000A7840074A7800074978C00748FBF0010AA
-:1057D0003C0A600E24EB0388354600100000382197
-:1057E0000000202127BD0018A78000643C010800AC
-:1057F000AC2C0080AF8B0010AF860048A780006CF7
-:10580000A780008AAF87001803E00008AF84001467
-:10581000A3880076938900765520FFEBA78000745B
-:10582000A7840074978C00748FBF00103C0A600E30
-:1058300024EB0388A7860064000038213546001059
-:105840000000202127BD00183C010800AC2C00807E
-:10585000AF8B0010AF860048A780006CA780008A3D
-:10586000AF87001803E00008AF84001400055080E3
-:10587000014648218D2800043C0660000A00010F03
-:10588000010638210A000103AF99004C3083FFFF65
-:105890008F8800408F87003C000321403C0580003A
-:1058A0003C020050008248253C0660003C0A010092
-:1058B00034AC04008CCD08E001AA58241160000526
-:1058C000000000008CCF08E024E7000101EA702509
-:1058D000ACCE08E08D19001001805821ACB9003819
-:1058E0008D180014ACB8003CACA9003000000000DA
-:1058F00000000000000000000000000000000000A8
-:105900000000000000000000000000003C038000D8
-:105910008C640000308200201040FFFD3C0F6000CE
-:105920008DED08E03C0E010001AE18241460FFE18B
-:1059300000000000AF87003C03E00008AF8B005080
-:105940008F850040240BFFF03C06800094A7001ACE
-:105950008CA9002430ECFFFF000C38C000EB502471
-:10596000012A4021ACC8003C8CA400248CC3003C1C
-:105970000083102318400033000000008CAD00208D
-:1059800025A200013C0F0050ACC2003835EE0010DB
-:105990003C068000ACCE003000000000000000009B
-:1059A00000000000000000000000000000000000F7
-:1059B00000000000000000003C0480008C99000002
-:1059C000333800201300FFFD30E2000810400017BC
-:1059D0003C0980008C880408ACA800108C83040C5F
-:1059E000ACA300143C1900203C188000AF19003013
-:1059F00094AE001894AF001C01CF3021A4A600186B
-:105A000094AD001A25A70001A4A7001A94AB001AB0
-:105A100094AC001E118B00030000000003E000089E
-:105A20000000000003E00008A4A0001A8D2A040072
-:105A3000ACAA00108D240404ACA400140A0001BC1C
-:105A40003C1900208CA200200A0001A43C0F005049
-:105A50000A0001920000000027BDFFE8AFBF001060
-:105A60000E0001D6000000008F8900408FBF00109B
-:105A70003C038000A520000A9528000A9527000411
-:105A800027BD00183105FFFF30E6000F00061500A6
-:105A900000A2202503E00008AC6400803C0508005B
-:105AA0008CA500208F83000C27BDFFE8AFB000104D
-:105AB000AFBF001410A300100000802124040001D7
-:105AC0000204300400A6202400C310245044000621
-:105AD00026100001001018802787FD941480000A0A
-:105AE00000671821261000012E0900025520FFF33F
-:105AF0008F83000CAF85000C8FBF00148FB0001097
-:105B000003E0000827BD00188C6800003C058000F9
-:105B1000ACA800240E0001D8261000013C050800A6
-:105B20008CA500200A0001FD2E09000224050001B9
-:105B3000008518043C0408008C84002027BDFFC8A1
-:105B4000AFBF003400831024AFBE0030AFB7002CCD
-:105B5000AFB60028AFB50024AFB40020AFB3001C2F
-:105B6000AFB20018AFB1001410400051AFB0001038
-:105B70008F840040948700069488000A00E8302350
-:105B800030D5FFFF12A0004B8FBF0034948B00185C
-:105B9000948C000A016C50233142FFFF02A2482B73
-:105BA0001520000202A02021004020212C8F00059A
-:105BB00015E0000200809821241300040E00016506
-:105BC000026020218F87004002609021AF80004456
-:105BD00094F4000A026080211260004E3291FFFFAF
-:105BE0003C1670003C1440003C1E20003C17600036
-:105BF0008F9900508F380000031618241074004F3E
-:105C00000283F82B17E0003600000000107E0047EA
-:105C10008F86004414C0003A2403000102031023BD
-:105C2000022320213050FFFF1600FFF13091FFFFCB
-:105C30008F8700403C1100203C108000AE110030E6
-:105C400094EB000A3C178000024B5021A4EA000AA2
-:105C500094E9000A94E800043123FFFF3106000FA5
-:105C600000062D000065F025AEFE008094F3000ACA
-:105C700094F6001812D30036001221408CFF001455
-:105C80008CF4001003E468210000C02101A4782BEB
-:105C90000298702101CF6021ACED0014ACEC001033
-:105CA00002B2382330F5FFFF16A0FFB88F84004002
-:105CB0008FBF00348FBE00308FB7002C8FB6002806
-:105CC0008FB500248FB400208FB3001C8FB2001852
-:105CD0008FB100148FB0001003E0000827BD00381A
-:105CE0001477FFCC8F8600440E000DC102002021E6
-:105CF000004018218F86004410C0FFC90203102302
-:105D0000027070238F87004001C368210A00028857
-:105D100031B2FFFF8F86004414C0FFC93C11002040
-:105D20003C1080000A000252AE1100300E0003FA4F
-:105D3000020020210A00027F0040182102002021D9
-:105D40000E000811022028210A00027F00401821BD
-:105D50000E000192000000000A00026B02B238231C
-:105D600027BDFFC8AFB7002CAFB60028AFB50024E1
-:105D7000AFB40020AFB3001CAFB20018AFB1001435
-:105D8000AFB00010AFBF00300E0000E624130001DA
-:105D90003C047FFF3C0380083C0220003C010800DB
-:105DA000AC2000703497FFFF34750080345200033C
-:105DB0003C1612C0241400013C1080002411FF8006
-:105DC0000E0001E9000000008F8700488F8B00184B
-:105DD0008F8900148CEA00EC8CE800E8014B302B32
-:105DE0000109282300A6102314400006014B1823A4
-:105DF0001440000E3C05800002C3602B1180000B94
-:105E0000000000003C0560008CEE00EC8CED00E82A
-:105E10008CA4180CAF8E001804800045AF8D0014C0
-:105E20008F8F0010ADF400003C0580008CBF000097
-:105E30003BF90001333800011700FFE13C0380000B
-:105E40008C62010024060C001046000900000000CE
-:105E50008C6801002D043080548000103C048000C8
-:105E60008C6901002D2331811060000C3C048000FE
-:105E70008CAA010011460004000020218CA601001C
-:105E800024C5FF8130A400FF8E0B01000E00020D1F
-:105E9000AE0B00240A0002F33C0480008C8E01004B
-:105EA000240C0020AC8E002092AD000031A300FF36
-:105EB000106C00232407005010670026000000002B
-:105EC0003C0480008C8F010015E0000300000000FE
-:105ED000566000143C0440008C8701008C8D01004A
-:105EE0000000982100F17024000E594031AC007F71
-:105EF000016C302500D22825AC8508308C8A010041
-:105F00008C83010025490100013110240002F94071
-:105F10003068007F03E8C8250332C025AC980830FC
-:105F20003C044000AE0401380A0002B20000000048
-:105F300000973824ACA7180C0A0002CB8F8F0010F2
-:105F40008C8501000E0007C3240400800A0002F3C0
-:105F50003C0480008C8401000E001420000000002E
-:105F60000A0002F33C04800000A4102B240300016B
-:105F700010400009000030210005284000A4102B2B
-:105F800004A00003000318405440FFFC0005284013
-:105F90005060000A0004182B0085382B54E00004E0
-:105FA0000003184200C33025008520230003184257
-:105FB0001460FFF9000528420004182B03E00008D4
-:105FC00000C310213084FFFF30C600FF3C07800073
-:105FD0008CE201B80440FFFE00064C00012430258D
-:105FE0003C08200000C820253C031000ACE00180E4
-:105FF000ACE50184ACE4018803E00008ACE301B83F
-:106000003C0660008CC5201C2402FFF03083020097
-:10601000308601001060000E00A2282434A5000183
-:106020003087300010E0000530830C0034A50004F8
-:106030003C04600003E00008AC85201C1060FFFDFC
-:106040003C04600034A5000803E00008AC85201C77
-:1060500054C0FFF334A500020A00034B3087300020
-:1060600027BDFFE8AFB00010AFBF00143C076000D1
-:10607000240600021080001100A080218F830050B0
-:106080000E0003428C6400188F8200500000202113
-:10609000240600018C45000C0E00033300000000B4
-:1060A0001600000224020003000010218FBF00141C
-:1060B0008FB0001003E0000827BD00188CE8201CFA
-:1060C0002409FFF001092824ACE5201C8F8700502B
-:1060D0000A0003688CE5000C3C02600E0080402141
-:1060E00034460100240900180000000000000000F0
-:1060F000000000003C0A00503C03800035470200CD
-:10610000AC68003834640400AC65003CAC67003017
-:106110008C6C0000318B00201160FFFD2407FFFF15
-:106120002403007F8C8D00002463FFFF248400047F
-:10613000ACCD00001467FFFB24C600040000000083
-:10614000000000000000000024A402000085282BAD
-:106150003C0300203C0E80002529FFFF0105402163
-:10616000ADC300301520FFE00080282103E00008C7
-:10617000000000008F82005027BDFFD8AFB3001C85
-:10618000AFBF0020AFB20018AFB10014AFB0001025
-:1061900094460002008098218C5200182CC3008184
-:1061A0008C4800048C4700088C51000C8C4900106E
-:1061B000106000078C4A00142CC4000414800013E3
-:1061C00030EB000730C5000310A0001000000000F5
-:1061D0002410008B02002021022028210E0003330E
-:1061E00024060003166000022402000300001021B0
-:1061F0008FBF00208FB3001C8FB200188FB1001426
-:106200008FB0001003E0000827BD00281560FFF1E3
-:106210002410008B3C0C80003C030020241F000154
-:10622000AD830030AF9F004400000000000000007C
-:10623000000000002419FFF024D8000F031978246F
-:106240003C1000D0AD88003801F0702524CD00034B
-:106250003C08600EAD87003C35850400AD8E0030F3
-:10626000000D38823504003C3C0380008C6B00003C
-:10627000316200201040FFFD0000000010E0000827
-:1062800024E3FFFF2407FFFF8CA800002463FFFF27
-:1062900024A50004AC8800001467FFFB24840004DC
-:1062A0003C04600EAC8600380000000000000000D6
-:1062B000000000003C0700203C0680000120202157
-:1062C00001402821ACC700300E0003780000802177
-:1062D0000E000342024020210A0003B802002021E0
-:1062E00027BDFFE0AFB200183092FFFFAFB100143E
-:1062F000AFBF001CAFB000101640000D0000882199
-:106300000A000427022010212405000350850027DD
-:106310008CE5000C0000000D262C00013191FFFFE0
-:1063200024EB00200232502B11400019AF8B00509B
-:106330008F820044144000168F8700503C06700086
-:106340003C0320008CE5000000A6202414830010EC
-:106350008F840058000544023C09800000A9802475
-:106360001480FFE9310600FF2CCA000B1140FFEB3F
-:10637000262C0001000668803C0E080025CE52A0A5
-:1063800001AE60218D8B000001600008000000005C
-:10639000022010218FBF001C8FB200188FB1001493
-:1063A0008FB0001003E0000827BD00200E0003336B
-:1063B000240400841600FFD88F8700500A000408C8
-:1063C000AF800058020028210E00035A2404000167
-:1063D0008F8700500A000408AF820058020028216D
-:1063E0000E00035A000020210A0004378F87005056
-:1063F0000E00039F020020218F8700500A0004082E
-:10640000AF82005830AFFFFF000F19C03C0480007E
-:106410008C9001B80600FFFE3C1920043C181000C7
-:10642000AC830180AC800184AC990188AC9801B840
-:106430000A000409262C000190E2000290FF0003EC
-:106440000000202100023A0000FF28252406000851
-:106450000E000333000000001600FFDD24020003DD
-:106460008F870050000010210A000408AF820058F6
-:1064700090E50002000020210A00045624060009CD
-:1064800094E5000490E9000390E300020005340065
-:106490000009420000C82025008328252406000AA0
-:1064A0000A0004560000202190E50002000020218F
-:1064B0000A0004562406000B000449C23127003F9D
-:1064C000000443423C028000000820402403168060
-:1064D0002CE60020AC43002C24EAFFE024820001DB
-:1064E00014C0000330A900FF00801021314700FFD5
-:1064F000000260803C0D8000240A0001018D2021F3
-:106500003C0B000E00EA2804008B3021112000050E
-:10651000000538278CCE000001C5382503E00008AF
-:10652000ACC700008CD800000307782403E0000803
-:10653000ACCF000027BDFFE0AFB10014AFB000103A
-:10654000AFBF00183C0760008CE408083402F0007C
-:106550003C1160003083F000240501C03C04800E33
-:106560000000302110620006241000018CEA0808A7
-:106570003149F0003928E0000008382B000780403E
-:106580003C0D0200AE2D0814240C16803C0B80003C
-:106590008E2744000E000E6AAD6C002C1200000421
-:1065A0003C02169124050001120500103C023D6CCE
-:1065B000345800E0AE3844083C1108008E31007CAD
-:1065C0008FBF00183C06600000118540360F168012
-:1065D0008FB100148FB000103C0E020027BD0020C8
-:1065E000ACCF442003E00008ACCE08103C0218DA1F
-:1065F000345800E0AE3844083C1108008E31007C6D
-:106600008FBF00183C06600000118540360F1680D1
-:106610008FB100148FB000103C0E020027BD002087
-:10662000ACCF442003E00008ACCE08100A00047090
-:10663000240500010A00047000002821240204003F
-:10664000A7820024A780001C000020213C0608002F
-:1066500024C655A82405FFFF2489000100044080BA
-:106660003124FFFF010618212C87002014E0FFFAD7
-:10667000AC65000024040400A7840026A780001E47
-:10668000000020213C06080024C656282405FFFFF0
-:10669000248D00010004608031A4FFFF0186582191
-:1066A0002C8A00201540FFFAAD650000A780002865
-:1066B000A7800020A7800022000020213C060800BF
-:1066C00024C656A82405FFFF249900010004C080B9
-:1066D0003324FFFF030678212C8E000415C0FFFA37
-:1066E000ADE500003C0560008CA73D002403E08F71
-:1066F00000E310243446014003E00008ACA63D004E
-:106700002487007F000731C224C5FFFF000518C29F
-:10671000246400013082FFFF000238C0A7840030EB
-:106720003C010800AC270030AF80002C000028217D
-:1067300000002021000030212489000100A7282129
-:106740003124FFFF2CA81701110000032C830080C7
-:106750001460FFF924C6000100C02821AF86002C78
-:1067600010C0001DA786002A24CAFFFF000A11429C
-:106770003C080800250856A81040000A0000202107
-:10678000004030212407FFFF248E000100046880B0
-:1067900031C4FFFF01A860210086582B1560FFFA65
-:1067A000AD87000030A2001F504000080004308078
-:1067B000240300010043C80400041080004878212D
-:1067C0002738FFFF03E00008ADF8000000C82021D3
-:1067D0002405FFFFAC85000003E000080000000076
-:1067E00030A5FFFF30C6FFFF30A8001F00806021EA
-:1067F00030E700FF000529420000502110C0001DB5
-:1068000024090001240B000125180001010B2004BC
-:10681000330800FF01267826390E00202DED0001F7
-:106820002DC2000101A218251060000D0144502561
-:106830000005C880032C40210100182110E0000F42
-:10684000000A20278D040000008A1825AD030000EF
-:1068500024AD0001000040210000502131A5FFFFC0
-:10686000252E000131C9FFFF00C9102B1040FFE7A2
-:106870002518000103E00008000000008D0A000058
-:10688000014440240A000556AC68000027BDFFE81B
-:1068900030A5FFFF30C6FFFFAFB00010AFBF001440
-:1068A00030E7FFFF000050213410FFFF000060219F
-:1068B00024AF001F00C04821241800012419002023
-:1068C00005E0001601E010210002F943019F682A4B
-:1068D0000009702B01AE402411000017000C188035
-:1068E0000064102110E000058C4B000000F840040B
-:1068F0000008382301675824000038211540004162
-:1069000000004021556000163169FFFF258B000112
-:10691000316CFFFF05E1FFEC01E0102124A2003EF5
-:106920000002F943019F682A0009702B01AE402440
-:106930001500FFEB000C1880154600053402FFFF20
-:10694000020028210E00053A000038210200102123
-:106950008FBF00148FB0001003E0000827BD00189F
-:106960001520000301601821000B1C0224080010F0
-:10697000306A00FF15400005306E000F250D00083D
-:1069800000031A0231A800FF306E000F15C0000589
-:10699000307F00032510000400031902320800FFB5
-:1069A000307F000317E0000538690001250200026E
-:1069B00000031882304800FF3869000131230001CC
-:1069C00010600004310300FF250A0001314800FF78
-:1069D000310300FF000C694001A34021240A00019B
-:1069E00010CAFFD53110FFFF246E000131C800FF2F
-:1069F0001119FFC638C900012D1F002053E0001CEB
-:106A0000258B0001240D00010A0005CD240E002075
-:106A100051460017258B000125090001312800FF90
-:106A20002D09002051200012258B00012543000173
-:106A3000010D5004014B1024250900011440FFF4FE
-:106A4000306AFFFF3127FFFF10EE000C2582FFFFA9
-:106A5000304CFFFF000050213410FFFF312800FFB1
-:106A60002D0900205520FFF225430001258B000150
-:106A7000014648260A000587316CFFFF00003821D7
-:106A8000000050210A0005D93410FFFF27BDFFD8B0
-:106A9000AFB0001030F0FFFFAFB10014001039426A
-:106AA0003211FFE000071080AFB3001C00B12823B3
-:106AB00030D3FFFFAFB2001830A5FFFF0080902158
-:106AC0000260302100442021AFBF00200E00056588
-:106AD0003207001F022288213403FFFF02402021D9
-:106AE00002002821026030210000382110430009F3
-:106AF0003231FFFF022010218FBF00208FB3001C16
-:106B00008FB200188FB100148FB0001003E000089E
-:106B100027BD00280E000565000000000040882108
-:106B2000022010218FBF00208FB3001C8FB20018ED
-:106B30008FB100148FB0001003E0000827BD0028BB
-:106B4000000424003C036000AC603D0810A000027B
-:106B5000348210063482101603E00008AC623D0453
-:106B600027BDFFE0AFB00010309000FF2E020006FE
-:106B7000AFBF001810400008AFB100140010308003
-:106B80003C030800246352CC00C328218CA40000DD
-:106B90000080000800000000000020218FBF0018C6
-:106BA0008FB100148FB000100080102103E00008A6
-:106BB00027BD00209791002A1620005100002021B7
-:106BC0003C020800904200330A000640000000002A
-:106BD000978D002615A00031000020210A000640F4
-:106BE000240200089787002414E0001A00001821EE
-:106BF00000602021240200011080FFE98FBF0018EF
-:106C0000000429C20045302100A6582B1160FFE482
-:106C10003C0880003C072000000569C001A76025F2
-:106C2000AD0C00203C0380082402001F2442FFFF1B
-:106C3000AC6000000441FFFD2463000424A50001B2
-:106C400000A6702B15C0FFF5000569C00A00062AD2
-:106C50008FBF00189787001C3C040800248455A8A7
-:106C6000240504000E0005E524060001978B00248E
-:106C700024440001308AFFFF2569FFFF2D480400EE
-:106C80000040282115000040A789002424AC3800CA
-:106C9000000C19C00A00063EA780001C9787001E42
-:106CA0003C04080024845628240504000E0005E551
-:106CB0002406000197990026244400013098FFFF24
-:106CC000272FFFFF2F0E04000040882115C0002C45
-:106CD000A78F0026A780001E3A0200032624010089
-:106CE0003084FFFF0E0006122C4500010011F8C091
-:106CF00027F00100001021C00A000640240200080D
-:106D00009785002E978700223C040800248456A80B
-:106D10000E0005E5240600019787002A8F89002CC4
-:106D20002445000130A8FFFF24E3FFFF0109302BB9
-:106D30000040802114C00018A783002AA7800022E9
-:106D4000978500300E000E5402002021244A0500D1
-:106D50003144FFFF0E000612240500013C05080027
-:106D600094A500320E000E5402002021244521007B
-:106D70003C020800904200330A000640000521C092
-:106D80000A000678A784001E24AC3800000C19C045
-:106D90000A00063EA784001C0A000692A78500226E
-:106DA000308400FF27BDFFE82C820006AFBF00142F
-:106DB000AFB000101040001500A038210004408042
-:106DC0003C030800246352E4010328218CA4000042
-:106DD000008000080000000024CC007F000751C2A2
-:106DE000000C59C23170FFFF2547C40030E5FFFF9A
-:106DF0002784001C020030210E00053A2407000100
-:106E00009786002802062021A78400288FBF00143F
-:106E10008FB0001003E0000827BD00183C050800F3
-:106E20008CA50030000779C20E00031C25E4DF00AA
-:106E30003045FFFF3C040800248456A824060001C6
-:106E40000E00053A24070001978E002A8FBF001418
-:106E50008FB0001025CD000127BD001803E0000809
-:106E6000A78D002A0007C9C22738FF00001878C282
-:106E700031F0FFFF3C04080024845628020028213A
-:106E8000240600010E00053A24070001978D002614
-:106E9000260E0100000E840025AC00013C0B6000B2
-:106EA000A78C0026AD603D083604000600003021A6
-:106EB0003C0760008CE23D04305F000617E0FFFDF8
-:106EC00024C9000100061B00312600FF0064402594
-:106ED0002CC50004ACE83D0414A0FFF68FBF0014DD
-:106EE0008FB0001003E0000827BD0018000751C252
-:106EF0002549C80024060001240700013C040800BD
-:106F0000248455A80E00053A3125FFFF97870024F9
-:106F10008FBF00148FB0001024E6000127BD0018B9
-:106F200003E00008A78600243084FFFF30A5FFFFA0
-:106F30003C0680008CC201B80440FFFE3C08408043
-:106F4000008838253C031000ACC00180ACC501842A
-:106F5000ACC7018803E00008ACC301B83084FFFF70
-:106F60003C0680008CC201B80440FFFE3C0840385B
-:106F70008CA70000008828253C031000ACC70180C6
-:106F8000ACC5018803E00008ACC301B88F83007072
-:106F90008F8600681066000B008040213C070800C7
-:106FA00024E756B8000328C000A710218C44000035
-:106FB00024630001108800053063000F5466FFFA57
-:106FC000000328C003E00008000010213C0708006F
-:106FD00024E756BC00A7302103E000088CC2000063
-:106FE0003C03900034620001008220253C038000B5
-:106FF000AC6400208C65002004A0FFFE00000000AF
-:1070000003E00008000000003C028000344300015F
-:107010000083202503E00008AC44002027BDFFE0EA
-:10702000AFB100143091FFFFAFB00010AFBF001838
-:107030001220001200A080218CA5000014A00011D5
-:10704000240400023C0680008CC201B80440FFFE0C
-:107050003C074000022720258FBF00188FB1001485
-:107060008FB000103C03100027BD0020ACC501808C
-:10707000ACC4018803E00008ACC301B80A000753A0
-:107080008CA500000E0006AA24060200000028219C
-:107090000A000753AE0000003087FFFF3C06800067
-:1070A0008CC201B80440FFFE3C0A40068CA90000D7
-:1070B00000EA4025ACC901808CA400043C03100008
-:1070C000ACC40184ACC8018803E00008ACC301B8BB
-:1070D0008F83FD8C27BDFFE8AFBF0014AFB0001059
-:1070E00090670008008010210080282130E60040D1
-:1070F0000000202110C000088C5000000E00008805
-:1071000002002021020020218FBF00148FB0001048
-:107110000A0004CD27BD00180E000768000000001B
-:107120000E00008802002021020020218FBF0014E1
-:107130008FB000100A0004CD27BD001827BDFFE066
-:10714000AFB000108F90FD8CAFBF001CAFB2001825
-:10715000AFB1001492060001008088210E00073AAA
-:1071600030D2000492040005001129C2A6050000D7
-:1071700034830040A20300050E00074402202021B2
-:107180000E0004CF0220202124020001AE02000CD8
-:1071900002202821A602001024040002A6020012E8
-:1071A00024060200A60200140E0006AAA60200167B
-:1071B0001640000F8FBF001C978C006C3C0B080022
-:1071C0008D6B00782588FFFF3109FFFF256A0001DC
-:1071D000012A382B10E00006A788006C3C0F6006DF
-:1071E000240E001635ED0010ADAE00508FBF001C10
-:1071F0008FB200188FB100148FB0001003E00008A8
-:1072000027BD002027BDFFE0AFB10014AFBF0018BD
-:10721000AFB000101080000400A08821240200807C
-:1072200010820007000000000000000D8FBF001852
-:107230008FB100148FB0001003E0000827BD0020BC
-:107240000E00073A00A020218F86FD8C022020210D
-:1072500090C500050E00074430B000FF2403003E37
-:107260001603FFF1000000003C0580008CA40178AB
-:107270000480FFFE240800073C071000ACB1014069
-:1072800002202021A0A801448FBF00188FB1001454
-:107290008FB00010ACA701780A00079127BD00202D
-:1072A00027BDFFE0AFB00010AFBF0018AFB10014B2
-:1072B0003C1080008E110020000000000E0004CF62
-:1072C000AE040020AE1100208FBF00188FB1001453
-:1072D0008FB0001003E0000827BD00203084FFFFBE
-:1072E0003C0680008CC201B80440FFFE3C084035DB
-:1072F000008838253C031000ACC50180ACC0018477
-:10730000ACC7018803E00008ACC301B83084FFFFBC
-:107310003C0680008CC201B80440FFFE3C084036A9
-:10732000008838253C031000ACC50180ACC0018446
-:10733000ACC7018803E00008ACC301B827BDFFD08B
-:10734000AFB500243095FFFFAFB60028AFB40020E2
-:10735000AFBF002CAFB3001CAFB20018AFB1001428
-:10736000AFB0001030B6FFFF12A000270000A02130
-:107370008F9200508E4300003C06800024020040A3
-:1073800000033E0200032C0230E4007F00669824D4
-:107390001482001D30A500FF8F8300602C68000A56
-:1073A000510000108F860044000358803C0C0800F8
-:1073B000258C5300016C50218D49000001200008EC
-:1073C0000000000002D4702131C5FFFF0E00070C41
-:1073D00024040084166000028F920050AF80006089
-:1073E0008F860044264F00202689000101E090216D
-:1073F0003134FFFF14C00004AF8F00500295282BDA
-:1074000014A0FFDC00000000028010218FBF002CC0
-:107410008FB600288FB500248FB400208FB3001CD6
-:107420008FB200188FB100148FB0001003E0000875
-:1074300027BD00302407003414A7014600000000D7
-:107440009247000E8F98FD908F90FD8C240F1600B0
-:10745000A30700199244000D3C0880003C07800CF3
-:10746000A3040018965F00123C0960003C117FFFE6
-:10747000A61F005C965900103622FFFF2404000569
-:107480003325FFFFAE0500548E46001CAD0F0028CB
-:107490008CEE00008D2D444801C6182601A3302132
-:1074A000AE0600388E0C003824CA00013C0D7F0067
-:1074B000AE0C003C8E0B003CAF0B0004AE0A00206B
-:1074C0008E130020AE13001CA300001BAE02002C84
-:1074D000A30400128E5F001424130050AE1F00346A
-:1074E0008E190034AF1900148E450018AE050048FF
-:1074F000924F000CA20F004E92090008352E00207A
-:10750000A20E00088E030018006D6024358B400029
-:10751000AE0B0018920A0000315200FF125302A66F
-:107520002413FF803C040800248457380E0007769B
-:1075300000000000240C0004240800013C050800A1
-:107540008CA557383C048000A20C0025A208000539
-:107550008C9001780600FFFE8F920050240D0002EF
-:107560003C031000AC850140A08D0144AC83017840
-:107570000A00083AAF8000602CAD003711A0FF99D7
-:107580008F860044000580803C1108002631532876
-:10759000021178218DEE000001C0000800000000FB
-:1075A0002410000414B0008E3C0780003C0B08003F
-:1075B0008D6B57388F86FD8CACEB00208E43000816
-:1075C0008F8FFD90240E0050ACC300308E4A00080F
-:1075D000ACCA00508E42000CACC200348E44001085
-:1075E000ACC400388E5F0010ACDF00548E5900141C
-:1075F000ACD9003C8E580018ADF800048E51001C28
-:10760000ACD1002090C5000030A900FF112E0276F9
-:10761000000000008CC500348CD1003000B1302354
-:1076200004C000F32404008C126000F02402000364
-:107630000A00083AAF820060240F000514AF00680A
-:107640003C0B80003C0308008C6357388F86FD8C10
-:10765000AD6300208E4A00048F99FD90240720001E
-:10766000ACCA001C9242000824120008A322001990
-:107670008F840050909F0009A33F00188F85005011
-:1076800090B8000A330400FF10920010288C000903
-:10769000158000BC24080002240E0020108E000B70
-:1076A00034078000288900211520000824074000A5
-:1076B00024110040109100053C070001240F0080B8
-:1076C000108F00023C070002240740008CDF0018E6
-:1076D0003C04FF0003E4C8240327C025ACD80018ED
-:1076E00090B2000BA0D200278F8300509465000C4D
-:1076F00010A0022A000000009467000C3C198000D2
-:10770000240BFFBFA4C7005C9062000E2407000496
-:10771000A0C200088F840050909F000FA0DF0009D6
-:107720008F8C00508D9200108F38007402582823DF
-:10773000ACC500588D8F0014ACCF002C959100186B
-:107740003229FFFFACC90040958E001A31D0FFFFEF
-:10775000ACD000448D8D001CACCD00489588000253
-:10776000A4C800789183000EA0C3000890CA000846
-:10777000014B1024126001D4A0C200088F92005067
-:107780000A00083AAF8700602406000614A6001419
-:107790003C0D80003C1008008E1057388F8CFD88FF
-:1077A000ADB000208E4800188F86FD8C8F8AFD902A
-:1077B000AD8800008CC3003824040005AD830004AC
-:1077C0008CCB003C12600081AD4B00000A00083AEF
-:1077D000AF840060240E000710AE004B24040006A6
-:1077E0003C05080024A557380E00074924040081F1
-:1077F0008F9200500013102B0A00083AAF820060ED
-:107800002419002314B9FFF63C0B80003C0C08003F
-:107810008D8C57388F8AFD90AD6C00208F91FD8C38
-:107820008E4600042544002026450014AE2600287C
-:10783000240600030E000E60255000308F87005094
-:1078400002002021240600030E000E6024E500083B
-:107850003C040800248457380E000776000000001E
-:1078600092220000241F0050304400FF549FFFE18B
-:107870008F9200500E000E4B000000000A00093FDE
-:107880008F9200502403003314A300323C02800086
-:107890003C1108008E3157388F8EFD90AC5100207E
-:1078A0008E440008240900288F88FD8CADC4003068
-:1078B0008E5F000C24060009ADDF00348E590010E5
-:1078C000ADD900388E580014ADD800208E45001870
-:1078D000ADC500248E4F001CADCF0028A1C90011FA
-:1078E0008E4D000412600031AD0D00288F920050C3
-:1078F0000A00083AAF8600602409002214A9FFB8E4
-:1079000000000000240400073C0F08008DEF5738EA
-:107910003C118000AE2F00205660FEB1AF840060A5
-:107920003C040800248457380E00077624130050C6
-:107930008F98FD8C93120000324500FF10B301694F
-:10794000000000008F920050000020210A00083A39
-:10795000AF8400603C05080024A557380E000719C5
-:10796000240400810A00093F8F92005002D498211C
-:107970003265FFFF0E00070C240400840A00083A59
-:107980008F9200501088FF512407040028870003BD
-:1079900010E001A324100004240D0001548DFF4BBE
-:1079A000240740000A0008F5240701003C050800F0
-:1079B00024A557380E000768240400828F920050D7
-:1079C000000030210A00083AAF8600603C0408003D
-:1079D000248457388CC200380E0007768CC3003CD4
-:1079E0008F9200500A000995000020212404008293
-:1079F0003C05080024A557380E0007680000000069
-:107A00008F920050000010210A00083AAF820060F7
-:107A10008E5000048F91FD8C3C0A8000AD500020F8
-:107A200092220005020028213046000214C0018085
-:107A30002404008A8F92FD90020028212404008DE6
-:107A4000924B001B3163002014600179000000009C
-:107A5000922D0009240C001231A800FF110C0174B2
-:107A6000240400810E00073A020020219245001BE9
-:107A7000240E00040200202134A90042A249001B68
-:107A80000E000744A22E00253C0480008C91017852
-:107A90000620FFFE24180002AC900140A09801448B
-:107AA0008F9200503C0F1000AC8F01780A00094003
-:107AB0000013102B8E5000048F91FD8C3C1F800012
-:107AC000AFF0002092390005020028213327000280
-:107AD00014E000172404008A9224000924120004F0
-:107AE00002002821308600FF10D2001124040081FA
-:107AF0000E00073A020020218F8CFD90240B00120B
-:107B00002403FFFE918D001B0200202135A80020D8
-:107B1000A188001BA22B0009922A00050143102412
-:107B20000E000744A22200050200282100002021A7
-:107B30000E000805000000000A00093F8F92005067
-:107B40008E5100043C0280003C100800261057387B
-:107B5000AC5100203C010800AC315738924600037C
-:107B600030C40004108001658F84FD8C240200065F
-:107B7000A0820009924D001B2408FFC031AC003FD9
-:107B800001885825A08B000892430003306A000149
-:107B90001540015C000000008E420008AE020008A3
-:107BA0003C0208008C4257401040015B8F8EFD90D4
-:107BB000000281C28F85FD8CA5D0000C8E5F000C69
-:107BC000240F000124090014ADDF002C8E59001091
-:107BD000ADD9001C96470016A5C7003C9658001466
-:107BE000A5D8003EACAF000CA4AF0010A4AF0012AB
-:107BF000A4AF0014A4AF00161260015FA1C9001168
-:107C000092440003309200022E5300018F920050E4
-:107C1000266200080A00083AAF8200608E4600041F
-:107C20003C0580003C048008ACA600208E4700087C
-:107C30009089000024110050312200FF105100B83B
-:107C4000240500883C0480008C8F01B805E0FFFE0D
-:107C50000013802B3C18400900B81025AF9000603D
-:107C60003C101000AC860180AC870184AC82018896
-:107C7000AC9001B80A00083B8F8600448E45000492
-:107C80003C0680003C098008ACC50020913F000004
-:107C90002404005033F900FF132400B024060088A8
-:107CA0003C0480008C8A01B80540FFFE3C0E400E6B
-:107CB00000CE68253C081000AC850180AC800184B2
-:107CC000AC8D0188AC8801B8912B0000240CFF809A
-:107CD00024040004016C1825240600300E0006AAB6
-:107CE000A12300000A00093F8F9200508E5000042B
-:107CF0008F91FD903C0F8000ADF000209225001B7D
-:107D000030A900101120007C240300813C04800075
-:107D10008C8701B804E0FFFE3C1F401FAC9001803F
-:107D2000007F10250013C82B3C101000AC8001848C
-:107D3000AF990060AC820188AC9001B80A00083BA2
-:107D40008F8600448E44001C0E00072500000000B2
-:107D5000104000F8004038218F920050240600891E
-:107D60003C0580008CAE01B805C0FFFE000000009D
-:107D7000ACA701808E50001C3C1140010013782BF1
-:107D800000D138253C131000ACB00184AF8F0060E7
-:107D9000ACA70188ACB301B80A00083B8F86004449
-:107DA000965900023C10080026105738333800045A
-:107DB000130000A33C0460008E5F001C3C068000A2
-:107DC000ACDF00203C010800AC3F5738964F000262
-:107DD00031E7000114E000E3000000008E420004DF
-:107DE000AE0200083C1008008E105740120000D967
-:107DF0003C0680008F85FD8C241000018CBF00188C
-:107E00008F91FD908F89FD8803E6C825ACB90018D5
-:107E1000A0A00005ACB0000C3C1808008F1857401B
-:107E20008F870050A4B00010001879C2A4B00012CF
-:107E3000A4B00014A4B00016A62F000C8CEE00080D
-:107E40008F8D00508F8C0050AE2E002C8DA8000C12
-:107E500024070002AE28001C918B0010A22B0011F9
-:107E60008F830050906A0011A12A00088F82005071
-:107E700090440012A0A4004E8F920050924600132E
-:107E8000A22600128F920050965F0014A63F003C7D
-:107E900096590016A639003E8E580018AE380014C8
-:107EA0005660FD4FAF8700603C05080024A5573899
-:107EB0000E000749000020218F9200500000382159
-:107EC0000A00083AAF8700603C05080024A557382F
-:107ED0000E000768240400828F9200500A000922D5
-:107EE000000038210E000E4B000000008F92005061
-:107EF0000A000995000020210E00073A0200202107
-:107F00009232001B02002021365800100E00074458
-:107F1000A238001B8F9200500A000A850000182129
-:107F20009243000C306A0001114000030000000081
-:107F3000964B000EA48B002C9248000C310C0002D2
-:107F40001180FF4000002821964E00128E4D001433
-:107F5000A48E001A0A000A53AC8D001C8F83007097
-:107F60008F8700681067FF4E000030213C08080032
-:107F7000250856BC000320C0008830218CD10000A9
-:107F8000122500C8246200013043000F1467FFFA75
-:107F9000000320C00A000A6A000030213C050800E6
-:107FA00024A557380E0007682404008B8F920050D8
-:107FB0000A0009220013382B3C0B08008D6B573840
-:107FC00024D8FFFE25710100322A007F014790214D
-:107FD00002331024AD020028AE4600D0AE4000D4DB
-:107FE0000A00088BAE58001CACC000543C0E0800C0
-:107FF0008DCE57383C09800C352C0100ACEE0028A2
-:108000008E500014AD9000D08E4D0014AD8D00D474
-:108010008E4800102507FFFE0A0008C7AD87001C28
-:108020005490FDAA240740000A0008F52407100018
-:108030000E0007F9000000000A00093F8F9200506F
-:108040008C83442C3C05DEAD34B2BEEF3C0108000D
-:10805000AC20573810720090000000003C046C62A5
-:10806000348279701462000824040002978A006C3C
-:1080700097830064020028210143482B1120001936
-:1080800024040092240400020E00061A24050200B3
-:108090003C0B8000AD6200203C010800AC22573848
-:1080A0001040000D8F8E0050240C00282404000383
-:1080B00091CD001031A800FF550C000124040001EF
-:1080C0000E00004C00000000104000042404008357
-:1080D0000A000AB58F920050240400833C05080072
-:1080E00024A557380E000749000000008F92005069
-:1080F0000013382B0A00083AAF8700600A000A1EF6
-:10810000240200128E4400080E0007250000000023
-:108110000A000A2AAE0200083C05080024A55738C8
-:108120000E000719240400878F9200500A000A47A6
-:108130000013102B240400040E00061A240500303E
-:1081400014400014004038218F9200500A000A9A0F
-:10815000240600833C05080024A557380A000B7B41
-:10816000240400878E4400040E0007250000000050
-:108170000A000ABBAE0200083C05080024A55738D7
-:108180000E000768240400828F9200500A000A47FC
-:10819000000010218F9200503C0880083C0C8000A9
-:1081A000240B0050240A0001AD820020A10B000026
-:1081B000A10A000192490004A10900189244000597
-:1081C000A1040019924300063C040800248456BC14
-:1081D000A103001A924200073C030800246356B82A
-:1081E000A102001B92450008A105001C924600094F
-:1081F000A106001D925F000AA11F001E9259000BEC
-:10820000A119001F9258000CA11800209251000DD6
-:10821000A11100219250000EA1100022924F000FD8
-:10822000A10F0023924E0010A10E0024924D0011C8
-:10823000A10D0025964C0014A50C0028964B0016A5
-:108240008F8A00688F980070A50B002A9649001845
-:10825000000A10C025450001A509002C8E46001C0F
-:108260000044C8210043F82130A5000FAFE600000C
-:10827000AF27000010B80003AF8500680A000A9A13
-:108280000000302124AD000131A8000F0000302192
-:108290000A000A9AAF8800708C83442C0A000B5A9B
-:1082A0003C046C623C07080024E756B80087902124
-:1082B000ACC00000000030210A000A6AAE40000095
-:1082C0003C0482013C03600034820E02AC603D68D5
-:1082D000AF80009003E00008AC623D6C27BDFFE872
-:1082E000AFB000103090FFFF001018422C62004128
-:1082F000AFBF001414400002240400802403004097
-:108300003C010800AC3000603C010800AC23006474
-:108310000E000E5400602821244802BF2409FF806B
-:108320000109282400103980001030408FBF00144C
-:108330008FB0001000A7202100861821AF8300789D
-:108340003C010800AC2500583C010800AC24005C4E
-:1083500003E0000827BD0018308300FF30C6FFFF90
-:1083600030E400FF3C0880008D0201B80440FFFEAD
-:1083700000035400014438253C09600000E9202531
-:108380003C031000AD050180AD060184AD040188F9
-:1083900003E00008AD0301B88F8600503C0960126D
-:1083A000352700108CCB00043C0C600E3585001086
-:1083B000316A00062D480001ACE800C48CC40004FA
-:1083C000ACA431808CC2000894C30002ACA23184FA
-:1083D00003E00008A78300888F8500508F87FF186F
-:1083E0008F86FF208CAE00043C0F601235E8001031
-:1083F000ACEE00688CAD0008ACED006C8CAC0010ED
-:10840000ACCC004C8CAB000CACCB004894CA0054F4
-:108410003C0208008C42004425490001A4C90054D4
-:1084200094C400543083FFFF106200170000000066
-:108430003C0208008C420040A4C200528CA30018E9
-:10844000ACE300308CA20014ACE2002C8CB9001814
-:10845000ACF900388CB8001424050001ACF80034E5
-:108460008D0600BC50C500198D0200B48D0200B805
-:10847000A4E2004894E40048A4E4004A94E800DA46
-:1084800003E000083102FFFF3C0208008C42002498
-:10849000A4C00054A4C200528CA30018ACE3003066
-:1084A0008CA20014ACE2002C8CB90018ACF9003896
-:1084B0008CB8001424050001ACF800348D0600BC13
-:1084C00054C5FFEB8D0200B88D0200B4A4E2004851
-:1084D00094E40048A4E4004A94E800DA03E00008C9
-:1084E0003102FFFF8F8600503C0480008CC90008D9
-:1084F0008CC80008000929C0000839C0AC870020DA
-:1085000090C30007306200041040003AAF85008C31
-:1085100090CB0007316A0008114000398F87FF1C9B
-:108520008CCD000C8CCE001401AE602B118000327B
-:10853000000000008CC2000CACE200708CCB001874
-:108540008F85FF188F88FF20ACEB00748CCA001059
-:108550002402FFF8ACAA00C88CC9000CAD09006069
-:108560008CC4001CACA400C090E3007C0062C82452
-:10857000A0F9007C90D80007330F000811E0000438
-:108580000000000090ED007C35AC0001A0EC007C08
-:1085900090CF000731EE000111C00009000000007B
-:1085A00090E4007C2418000234820002A0E2007CE7
-:1085B00090A300EC307900FF133800132408003436
-:1085C00090C900073126000210C00004000000001E
-:1085D00090EB007C356A0004A0EA007C90ED007D01
-:1085E00031AC003FA0EC007D94A700DA03E0000866
-:1085F00030E2FFFF8F87FF1C0A000C908CC2001432
-:108600000A000C91ACE000700A000CB2ACA800CCDF
-:108610008F8C005027BDFFD8AFB3001CAFB200183D
-:10862000AFB00010AFBF0020AFB10014918F0015A4
-:108630003C13600E3673001031EB000FA38B0094D7
-:108640008D8F00048D8B0008959F00129599001066
-:108650009584001A9598001E958E001C33EDFFFF3F
-:10866000332AFFFF3089FFFF3308FFFF31C7FFFFC9
-:108670003C010800AC2D00243C010800AC2900445A
-:108680003C010800AC2A0040AE683178AE67317C0E
-:1086900091850015959100163C126012365200101B
-:1086A00030A200FF3230FFFFAE623188AE5000B41E
-:1086B00091830014959F0018240600010066C804E9
-:1086C00033F8FFFFAE5900B8AE5800BC918E0014CD
-:1086D000AF8F007C3C08600631CD00FFAE4D00C07E
-:1086E000918A00159584000E3C07600A314900FF0D
-:1086F000AF8B00803084FFFFAE4900C835110010F9
-:108700000E000BF934F004103C0208008C420060AB
-:108710003C0308008C6300643C0608008CC60058CB
-:108720003C0508008CA5005C8F8400788FBF00207A
-:10873000AE23004CAE65319CAE030054AE4500DC68
-:10874000AE6231A0AE6331A4AE663198AE2200486D
-:108750008FB3001CAE0200508FB10014AE4200E097
-:10876000AE4300E4AE4600D88FB000108FB20018C0
-:108770000A00050227BD00289785008A97830074A8
-:1087800027BDFFE8AFB0001000A3102BAFBF00144F
-:10879000240400058F900050104000552409000269
-:1087A0000E00061A8F850078AF82008C2404000327
-:1087B0001040004F240900023C0680000E00004CCF
-:1087C000ACC2002024070001240820001040004D06
-:1087D00024040005978E008A8F8AFF1C240900500C
-:1087E00025C50001A785008AA14900003C0D0800AD
-:1087F0008DAD0064240380008F84FF18000D660097
-:10880000AD4C0018A5400006954B000A8F85FF204F
-:108810002402FF8001633024A546000A915F000A0C
-:108820000000482103E2C825A159000AA0A00008C1
-:10883000A140004CA08000C59618000297830088D4
-:108840003C020004A49800DA960F00022418FFBF2F
-:1088500025EE2401A48E00AE8E0D0004ACAD0044C4
-:108860008E0C0008ACAC0040A4A00050A4A00054A2
-:108870008E0B000C240C0030AC8B00288E060010F0
-:10888000AC860024A480003EA487004EA48700503C
-:10889000A483003CAD420074AC8800C8ACA8006062
-:1088A000A08700EC909F00C433F9007FA09900C41A
-:1088B000909000C402187824A08F00C4914E007CD0
-:1088C00035CD0001A14D007C938B0094AD48007024
-:1088D000AC8C00CCA08B00C68F8800808F87007C7A
-:1088E000AC8800B4AC8700B8A5400078A540007AF9
-:1088F0008FBF00148FB000100120102103E000088A
-:1089000027BD00188F85008C0E0006AA8F86007880
-:108910000A000D7E2409000227BDFFE0AFB0001061
-:108920008F900050AFB10014AFBF00188E09000443
-:108930000E0004CF000921C08E0800048F84FF18A8
-:108940008F82FF20000839C03C068000ACC70020A1
-:10895000948500DA904300131460001C30B1FFFFCF
-:108960008F8CFF1C918B0008316A00401540000B72
-:10897000000000008E0D0004022030218FBF00187F
-:108980008FB100148FB000102404002200003821A1
-:10899000000D29C00A000C1827BD00200E0000633E
-:1089A000000000008E0D0004022030218FBF00184F
-:1089B0008FB100148FB00010240400220000382171
-:1089C000000D29C00A000C1827BD00200E00005B16
-:1089D000000000008E0D0004022030218FBF00181F
-:1089E0008FB100148FB00010240400220000382141
-:1089F000000D29C00A000C1827BD002027BDFFE08C
-:108A0000AFB200183092FFFFAFB00010AFBF001C34
-:108A1000AFB100141240001E000080218F8600506C
-:108A20008CC500002403000600053F020005140267
-:108A300030E4000714830016304500FF2CA8000620
-:108A400011000040000558803C0C0800258C54049F
-:108A5000016C50218D490000012000080000000039
-:108A60008F8E0090240D000111CD005024020002D1
-:108A7000AF820090260900013130FFFF24C800209A
-:108A80000212202B010030211480FFE5AF88005036
-:108A9000020010218FBF001C8FB200188FB100148C
-:108AA0008FB0001003E0000827BD002093870076F8
-:108AB00054E00034000030210E000CC6000000001D
-:108AC0008F8600500A000DDE240200018F8700907F
-:108AD0002405000210E500312404001300002821C1
-:108AE00000003021240700010E000C1800000000D7
-:108AF0000A000DDF8F8600508F8300902402000251
-:108B00001462FFF6240400120E000C7B000000002B
-:108B10008F85008C00403021240400120E000C18B8
-:108B2000000038210A000DDF8F8600508F830090EF
-:108B30002411000310710029241F0002107FFFCEB2
-:108B40002609000124040010000028210000302123
-:108B50000A000DFC240700018F91009024060002FA
-:108B60001626FFF9240400100E000D20000000005E
-:108B7000144000238F9800508F8600500A000DDEAD
-:108B800024020003240400140E000C180000282105
-:108B90008F8600500A000DDE240200020E000D88B0
-:108BA000000000000A000DDF8F8600500E000C2828
-:108BB00000000000241900022404001400002821F1
-:108BC0000000302100003821AF9900900E000C18F1
-:108BD000000000000A000DDF8F8600500E000C38E8
-:108BE000000000008F85008C241900020040302115
-:108BF00024040010000038210A000E35AF990090BF
-:108C00000040382124040010970F000200002821A2
-:108C10000E000C1831E6FFFF8F8600500A000DDFB2
-:108C2000AF9100908F84FF1C3C077FFF34E6FFFF6D
-:108C30008C8500182402000100A61824AC830018BB
-:108C400003E00008A08200053084FFFF30A5FFFF8D
-:108C5000108000070000182130820001104000023F
-:108C600000042042006518211480FFFB0005284005
-:108C700003E000080060102110C0000700000000A1
-:108C80008CA2000024C6FFFF24A50004AC820000D3
-:108C900014C0FFFB2484000403E00008000000006F
-:108CA00010A0000824A3FFFFAC8600000000000015
-:108CB000000000002402FFFF2463FFFF1462FFFA9C
-:108CC0002484000403E0000800000000000411C038
-:108CD00003E000082442024027BDFFE8AFB00010C7
-:108CE00000808021AFBF00140E000E7500A020216F
-:108CF00000504821240AFF808FBF00148FB000105D
-:108D0000012A30243127007F3C08800A3C042100DE
-:108D100000E8102100C428253C03800027BD00186E
-:108D2000AC650024AF820038AC400000AC65002484
-:108D300003E00008AC4000403C0D08008DAD005839
-:108D400000056180240AFF8001A45821016C48219C
-:108D5000012A30243127007F3C08800C3C0421008C
-:108D600000E8102100C428253C038000AC650028E1
-:108D7000AF82003403E00008AC40002430A5FFFFC0
-:108D80003C0680008CC201B80440FFFE3C08601520
-:108D900000A838253C031000ACC40180ACC001849D
-:108DA000ACC7018803E00008ACC301B83C0D080063
-:108DB0008DAD005800056180240AFF8001A4582170
-:108DC000016C4021010A4824000931403107007F2D
-:108DD00000C728253C04200000A418253C02800080
-:108DE000AC43083003E00008AF80003427BDFFE843
-:108DF000AFB0001000808021AFBF00140E000E75D0
-:108E000000A0202100504821240BFF80012B50247A
-:108E1000000A39403128007F3C0620008FBF001433
-:108E20008FB0001000E8282534C2000100A21825E8
-:108E30003C04800027BD0018AC83083003E0000824
-:108E4000AF8000383C0580088CA700603C06800895
-:108E50000087102B144000112C8340008CA8006068
-:108E60002D0340001060000F240340008CC90060F7
-:108E70000089282B14A00002008018218CC30060F8
-:108E800000035A42000B30803C0A0800254A5480F7
-:108E900000CA202103E000088C8200001460FFF368
-:108EA0002403400000035A42000B30803C0A0800B3
-:108EB000254A548000CA202103E000088C8200006B
-:108EC0003C05800890A60008938400A024C20001FD
-:108ED000304200FF3043007F1064000C000238274E
-:108EE000A0A200083C0480008C85017804A0FFFE4D
-:108EF0008F8A0098240900023C081000AC8A0140C7
-:108F0000A089014403E00008AC8801780A000EFA49
-:108F100030E2008027BDFFD8AFB200188F92009CCE
-:108F2000AFBF0020AFB3001CAFB00010AFB1001452
-:108F30008F9300348E5900283C1000803C0EFFEFC8
-:108F4000AE7900008E580024A260000A35CDFFFFE4
-:108F5000AE7800049251002C3C0BFF9F356AFFFF56
-:108F6000A271000C8E6F000C3C080040A271000B37
-:108F700001F06025018D4824012A382400E83025BD
-:108F8000AE66000C8E450004AE6000183C0400FF85
-:108F9000AE6500148E43002C3482FFFFA6600008EB
-:108FA0000062F824AE7F00108E5900088F90009860
-:108FB000964E0012AE7900208E51000C31D83FFF42
-:108FC00000187980AE7100248E4D001401F06021EC
-:108FD00031CB0001AE6D00288E4A0018000C41C252
-:108FE000000B4B80AE6A002C8E46001C0109382114
-:108FF000A667001CAE660030964500028E44002035
-:10900000A665001EAE640034924300333062000453
-:1090100054400006924700003C028008344301009F
-:109020008C7F00C0AE7F0030924700008F860038F2
-:10903000A0C700309245003330A4000250800007E2
-:10904000925100018F880038240BFF80910A003074
-:10905000014B4825A1090030925100018F90003842
-:10906000240CFFBF2404FFDFA21100318F8D0038D4
-:109070003C1880083711008091AF003C31EE007F32
-:10908000A1AE003C8F890038912B003C016C50242C
-:10909000A12A003C8F9F00388E68001493E6003CA4
-:1090A0002D0700010007114000C4282400A2182544
-:1090B000A3E3003C8F87003896590012A4F90032D0
-:1090C0008E450004922E007C30B0000300107823FF
-:1090D00031ED000300AD102131CC000215800002FB
-:1090E00024460034244600303C028008344300808B
-:1090F000907F007C00BFC8243338000417000002B2
-:1091000024C2000400C010218F98003824190002E6
-:10911000ACE20034A3190000924F003F8F8E00385C
-:109120003C0C8008358B0080A1CF00018F91003866
-:10913000924D003F8E440004A62D0002956A005C0B
-:109140000E000ED33150FFFF00024B800130382556
-:109150003C08420000E82825AE2500048E44003873
-:109160008F850038ACA400188E460034ACA6001CD5
-:10917000ACA0000CACA00010A4A00014A4A0001689
-:10918000A4A00020A4A00022ACA000248E620014A1
-:1091900050400001240200018FBF00208FB3001C4B
-:1091A0008FB200188FB100148FB00010ACA200086D
-:1091B0000A000EF227BD002827BDFFC83C05800825
-:1091C00034A40080AFBF0034AFBE0030AFB7002C76
-:1091D000AFB60028AFB50024AFB40020AFB3001C79
-:1091E000AFB20018AFB10014AFB000109483007894
-:1091F0009482007A104300512405FFFF0080F02183
-:109200000A0010020080B821108B004D8FBF00347F
-:109210008F8600983C1808008F18005C2411FF808E
-:109220003C1680000306782101F18024AED0002C8A
-:1092300096EE007A31EC007F3C0D800E31CB7FFF43
-:10924000018D5021000B4840012AA82196A400005E
-:109250003C0808008D0800582405FF8030953FFF2A
-:1092600001061821001539800067C8210325F8245C
-:109270003C02010003E290253338007F3C11800C52
-:10928000AED20028031190219250000D320F00043D
-:1092900011E0003702E0982196E3007A96E8007A20
-:1092A00096E5007A2404800031077FFF24E3000163
-:1092B00030627FFF00A4F82403E2C825A6F9007AF3
-:1092C00096E6007A3C1408008E94006030D67FFF4A
-:1092D00012D400C1000000008E5800188F8400983E
-:1092E00002A028212713FFFF0E000EADAE53002C65
-:1092F00097D5007897D4007A1295001000002821A5
-:109300003C098008352401003C0A80089148000887
-:10931000908700C53114007F30E400FF0284302BB9
-:1093200014C0FFB9268B0001938E00A0268C00018B
-:10933000008E682115ACFFB78F8600988FBF003470
-:109340008FBE00308FB7002C8FB600288FB5002459
-:109350008FB400208FB3001C8FB200188FB100149F
-:109360008FB0001000A0102103E0000827BD0038D6
-:1093700000C020210E000E78028028218E4B0010A4
-:109380008E4C00308F84003824090002016C502379
-:10939000AE4A0010A089000096E3005C8E440030C5
-:1093A0008F9100380E000ED33070FFFF0002438013
-:1093B000011028253C07420000A71025AE2200041A
-:1093C0008E5F00048F8A00388E590000240B00083D
-:1093D000AD5F001CAD590018AD40000CAD40001051
-:1093E0009246000A240400052408C00030D000FF83
-:1093F000A550001496580008A55800169251000A6E
-:109400003C188008322F00FFA54F0020964E000820
-:1094100037110100A54E0022AD400024924D000BF3
-:1094200031AC00FFA54C0002A14B00018E49003079
-:109430008F830038240BFFBFAC690008A0640030A4
-:109440008F9000382403FFDF9607003200E82824BD
-:1094500000B51025A6020032921F003233F9003FFA
-:1094600037260040A20600328F8C0038AD800034D1
-:109470008E2F00C0AD8F0038918E003C3C0F7FFFD7
-:1094800031CD007FA18D003C8F84003835EEFFFF89
-:10949000908A003C014B4824A089003C8F8500380D
-:1094A00090A8003C01033824A0A7003C8E42003461
-:1094B0008F9100383C038008AE2200408E59002C6A
-:1094C0008E5F0030033F3023AE26004492300048C8
-:1094D0003218007FA23800488F8800388E4D003047
-:1094E0008D0C004801AE582401965024014B4825AC
-:1094F000AD0900489244000AA104004C96470008B8
-:109500008F850038A4A7004E8E5000308E44003066
-:109510000E00031C8C65006092F9007C0002F9408B
-:10952000004028210002110003E2302133360002FE
-:1095300012C00003020680210005B08002168021BF
-:10954000926D007C31B3000412600002000570804F
-:10955000020E80218E4B003024058000316A00030A
-:10956000000A482331240003020418218F90003898
-:10957000AE03003496E4007A96E8007A96F1007A19
-:1095800031077FFF24E20001305F7FFF0225C824FE
-:10959000033F3025A6E6007A96F8007A3C120800D0
-:1095A0008E520060330F7FFF11F2001800000000A0
-:1095B0008F8400980E000EAD02A028218F840098A1
-:1095C0000E000EBD028028210E000EF200000000E9
-:1095D0000A000FFE0000000096F1007A02248024A9
-:1095E000A6F0007A92EF007A92EB007A31EE00FF5B
-:1095F000000E69C2000D6027000C51C03169007F68
-:10960000012A20250A000FF8A2E4007A96E6007AE3
-:1096100000C5C024A6F8007A92EF007A92F3007A8F
-:1096200031F200FF001271C2000E6827000DB1C0B8
-:10963000326C007F01962825A2E5007A0A0010AF5F
-:109640008F8400983C0380003084FFFF30A5FFFF2B
-:10965000AC640018AC65001C03E000088C620014C8
-:1096600027BDFFA83C068008AFBE0050AFBF005426
-:10967000AFB7004CAFB60048AFB50044AFB4004040
-:10968000AFB3003CAFB20038AFB10034AFB0003080
-:1096900034C80100910500C590C70008309EFFFF47
-:1096A00030A500FF30E2007F0045182AA7A0001473
-:1096B000A7A0001E10600053AFA0001090C90008C2
-:1096C0003126007F00A620232493FFFF0013802B68
-:1096D000001E882B0211782451E000848FB3001003
-:1096E0003C1980089736005297370050001EC4007E
-:1096F00002D7A8230015A4000014140303C2902A63
-:109700001640000200182C0300402821001314000A
-:109710000002240300A4F82A57E0000100A0202141
-:1097200028830009146000020080A021241400088E
-:109730003C0A80088D450048001449808D48004C43
-:109740003C0380003124FFFF3C06001000863825D2
-:1097500034710400AC650038AF91009CAC68003CEB
-:10976000AC670030000000000000000000000000B6
-:1097700000000000000000000000000000000000E9
-:10978000000000008C6C0000318B00201160FFFD98
-:109790000014682A01B01024104000390000A821EC
-:1097A0003C16800892D700083C1280008E440100CD
-:1097B00032F6007F0E000E7802C028218E2F001096
-:1097C0008E4401000000902131F73FFF0E000E9003
-:1097D00002E02821922E000031C2003F2C500008E8
-:1097E00052000010000088210002F8803C030800AD
-:1097F0002463542C03E3C8218F38000003000008C1
-:109800000000000090CE0008938B00A031CD007FB7
-:1098100000AD6023016C50210A0010F52553FFFFB5
-:10982000000088213C1080008E0401000E000EAD67
-:1098300002E028218E0401000E000EBD02C0282186
-:109840001220000F0013802B8F8A009C26A9000194
-:109850000009AC00027298230015AC0325450040B6
-:1098600002B4B02A0013802B2417000100A0882125
-:1098700002D01024AF85009C1440FFC9AFB7001080
-:109880003C07800894F100503C0580003C06002015
-:1098900002B1C821A4F90050ACA6003094F40050E5
-:1098A00094E3005203D560231074001D319EFFFF26
-:1098B0008CE5004C8CE900480015618000ACB021BB
-:1098C0000000A02102CCA82B013450210155B82161
-:1098D000ACF6004CACF70048001E882B021178242F
-:1098E00015E0FF803C1980088FB300108FBF005433
-:1098F0008FBE00503A6200018FB7004C8FB600480F
-:109900008FB500448FB400408FB3003C8FB2003855
-:109910008FB100348FB0003003E0000827BD00583D
-:1099200094F200548CEF0044325FFFFE001FC0C071
-:1099300001F87021ACAE003C8CEB00448CAD003CD7
-:10994000016D40231900003B000000008CE2004044
-:10995000244200013C07005034E400103C03800026
-:10996000ACA20038AC640030000000000000000031
-:1099700000000000000000000000000000000000E7
-:1099800000000000000000008C76000032D70020AC
-:1099900012E0FFFD3C118008962800543C0A80002C
-:1099A0003C06800831190001001960C0018AA0211D
-:1099B0008E8304003C0708008CE700443C1500201F
-:1099C000ACC300488E89040424050001ACC9004CD6
-:1099D00010E50259AD550030963F00523C05080095
-:1099E0008CA5004000BFC021A6380052962F00541D
-:1099F00025EE0001A62E00549626005430C4FFFF29
-:109A00005487FF34001E882B30A5FFFF0E0010D3B3
-:109A1000A62000543C0408008C84002496270052A1
-:109A20000044102300E29023A63200520A0010F7EF
-:109A3000001E882B8CE200400A0011983C07005061
-:109A400092280001240700013102007F1447001C06
-:109A500097AC001E8E2A0014240BC00031443FFF37
-:109A6000018B48243C0608008CC600600124282590
-:109A700030A43FFF0086882B12200011A7A5001EEE
-:109A80003C1108008E3100588F82009800044180FC
-:109A90002407FF80022218210068F82103E7C82468
-:109AA00033EF007F3C1880003C12800EAF19002C71
-:109AB00001F2682191AE000D35D00004A1B0000D77
-:109AC0000E000F0724120001241100013C10800039
-:109AD0008E0401000E000EAD02E028218E0401006C
-:109AE0000E000EBD02C028211620FF588F8A009C50
-:109AF0000A0011620013802B8F86009C90C9000120
-:109B00003125002010A0018A241000013C048008A7
-:109B1000348C0080918B007C8F9100340000902168
-:109B2000316A00011140000FAFB000208CD000144A
-:109B30008C8E0060020E682B15A0000302003821F5
-:109B40008C8700603C048008348300808C72007035
-:109B500000F2782B15E0000200E020218C640070F8
-:109B6000008090213C07800834E500808CD90014E7
-:109B70008CBF0070033FC02B170000020320202180
-:109B80008CA400700092182310600003AFA300287B
-:109B900024080002AFA800208FA500200265102B2A
-:109BA000144000B5000018218CC400388E2F000C22
-:109BB0003C180080AE2400008CCE00343C10FF9F87
-:109BC00001F86025AE2E000490CB003F360DFFFF5C
-:109BD000018D48243C0A00203C06FFEFA22B000B1D
-:109BE000012A382534C5FFFF00E540243C02000867
-:109BF0008F87009C01022025AE24000C8CE300140A
-:109C0000AE2000188FAF0028AE2300148CF8001887
-:109C10003C1FFFFB37F9FFFFAE38001C8CEE00083D
-:109C200000996824024F8021AE2E00248CEC000C99
-:109C3000AE2D000CA6200038A620003AAE30002C35
-:109C4000AE2C0020AE2000288CEB00148FAA002838
-:109C500001724823012A302310C00011AE260010E3
-:109C600090F0003D8E2C00048E2A00000010690048
-:109C7000018D28210000102100AD302B0142482128
-:109C800001264021AE250004AE28000090E3003DEF
-:109C9000A223000A8F9F009C97F90006A6390008AE
-:109CA0008F8A0038240200023C068008A14200008E
-:109CB00034C900809525005C024020218F90003837
-:109CC00030A8FFFF0E000ED3AFA800248FA30024FE
-:109CD0000002FB808F85009C3C04420003E3C82502
-:109CE0000324C025AE1800048F8400388CAF0038E0
-:109CF000AC8F00188CAE0034AC8E001CAC80000C15
-:109D0000AC800010A4800014A4800016A480002061
-:109D1000A4800022AC80002490A7003FA48700020A
-:109D20005240018C240700018FAB002851600002D3
-:109D300090A2003D90A2003E244C0001A08C0001A6
-:109D40008F840038AC9200083C18800837100080DF
-:109D5000920F007C31EE000215C00002240700348F
-:109D6000240700308F85009C3C088008350900805E
-:109D700090A300009128007C32590003A08300309A
-:109D80008F9F009C8F9000382404000493F80001FA
-:109D900000997823240DC000A21800318F99003853
-:109DA0008F8E009C31E50003972C003295CB00127A
-:109DB00000F24821018D502431623FFF01423025DD
-:109DC000A7260032932300320125382131080004F0
-:109DD000307F003F37E40040A324003212400002ED
-:109DE0008F85003800E838213C0C8008ACA700348F
-:109DF000358B01008D6200C02E4400012403FFDF7B
-:109E0000ACA2003890AA003C0004C9403146007F53
-:109E1000A0A6003C8F8900382405FFBF9127003C95
-:109E200000E54024A128003C8F8F003891FF003CC2
-:109E300003E3C02403198025A1F0003C8F8B009C14
-:109E40008F8A00388D6E0020AD4E00408D6D00244D
-:109E5000AD4D00448D6C0028AD4C00488D62002C47
-:109E60000E000EF2AD42004C8FA600202407000227
-:109E700010C700118FA300200003202B00048023B3
-:109E80000270982400608021006090210A00114B2C
-:109E90000010882B962700128F84009800009021D4
-:109EA00030E5FFFFA7A700140E000EA1241100014A
-:109EB0000A0011F63C1080003C1980003C0280082A
-:109EC0008F240100905800080E000E783305007FA3
-:109ED0008F8E00388FAF00208FA40028A1CF000004
-:109EE0000E000ED38F9000388FAD002400023B800F
-:109EF0003C0B420000ED40258F87009C010B202584
-:109F0000AE0400048CE500388F900038000050212A
-:109F1000000A1900AE0500188CEC00343C087FFFE5
-:109F20003504FFFFAE0C001C90E9003E8E1F001CA4
-:109F30008E1800180009C9000009370203F96821CA
-:109F40000066102501B9782B0302702101CF58213A
-:109F5000AE0D001CAE0B0018AE00000CAE000010E1
-:109F600090E5003E8FAF0028240E0005A6050014E2
-:109F700094EC00042405C00001E45824A60C00164B
-:109F800090EA003E01E02021A60A002094E60004A9
-:109F9000A6060022AE00002490E3003FA6030002C4
-:109FA00090E9003E90FF003D03E9C82327380001F7
-:109FB000A21800018F8D00383C108008ADAF00085A
-:109FC000A1AE00308F9800388F82009C360F0100C0
-:109FD000970C0032944A00122410FF8000AC382401
-:109FE00031463FFF00E61825A703003293090032EF
-:109FF0002405FFBF2403FFDF313F003F37F9004056
-:10A00000A31900328F8C00382418FFFFAD80003474
-:10A010008DEE00C0AD8E0038918D003C31A2007FE6
-:10A02000A182003C8F87003890EA003C0145302433
-:10A03000A0E6003C8F9900389329003C0123F824C6
-:10A04000A33F003C8F8D00383C1F8008ADB8004016
-:10A05000ADB2004491AF00483C12800001F0702581
-:10A06000A1AE00488F8700388F86009C8CEC00489A
-:10A0700001921024004B5025ACEA004890C5003EE8
-:10A08000A0E5004C8F88009C8F8300389509000460
-:10A09000A469004E8FE500600E00031C0000000064
-:10A0A0008F99FF248FAE002800028140932F007CFF
-:10A0B0000002C1000218682131F20002004028218C
-:10A0C000164000AA01CD30213C0A800835430080AB
-:10A0D0009069007C313F000413E000038FAE00283C
-:10A0E0000005608000CC3021240D00048F900038E2
-:10A0F00031C7000301A758233168000300C820219D
-:10A10000AE0400343C068008A62500383C058000DB
-:10A110008CA4010090D100080E000EBD3225007FF6
-:10A120000E000EF2000000000A0012E08FA30020D3
-:10A130008F8500348CC2003824180003A4A00008C6
-:10A14000ACA200008CDF0034A0A0000A8F92009C1B
-:10A15000ACBF00043C040080924F003FA0B8000C4C
-:10A160008CAE000C3C0DFF9FA0AF000B01C440253E
-:10A1700035ABFFFF3C11FFEF8F98009C010B3024A3
-:10A180003639FFFF00D96024ACAC000C8F030014FB
-:10A19000971F00128F870098ACA300108F0900143E
-:10A1A000ACA00018ACA00020ACA90014ACA0002406
-:10A1B0008F0A001833E93FFF00091180ACAA00287C
-:10A1C0008F1200080047782133EE0001ACB2003056
-:10A1D0008F08000C8F990038000F69C2000E238091
-:10A1E00001A45821241100023C068008A4AB001CE5
-:10A1F000A4A00034ACA8002CA331000034D9008006
-:10A20000972C005C8F8F00383C034200318AFFFF9F
-:10A2100001433825ADE700048F82009C241800011B
-:10A220002411C0008C5F003824070034ADFF0018F3
-:10A230008C520034ADF2001CADE0000CADE000101B
-:10A24000A5E00014A5E00016A5E00020A5E000228E
-:10A25000ADE00024A5F00002A1F800018F8B0038CA
-:10A260008F8E009CAD70000891CD0000A16D003074
-:10A270008F88009C8F84003891050001A0850031F3
-:10A280008F920038964C00320191502401491825D4
-:10A29000A6430032925F003233E2003FA242003216
-:10A2A0009338007C330F000215E000028F840038E1
-:10A2B000240700303C028008AC870034345201008F
-:10A2C0008E5F00C0240EFFBF02009021AC9F0038BB
-:10A2D0009098003C330F007FA08F003C8F8800389F
-:10A2E000910D003C01AE5824A10B003C8F86003834
-:10A2F00090D1003C36390020A0D9003C8F8A009CC8
-:10A300008F8500380010882B8D4C0020ACAC0040AD
-:10A310008D430024ACA300448D490028ACA900481B
-:10A320008D47002CACA7004C0E000EF23C108000B4
-:10A330000A00114C0000000094CD00523C0B0800B4
-:10A340008D6B0024016D8821A4D100520A0010F702
-:10A35000001E882BA08700018F840038240D000187
-:10A36000AC8D00080A0012953C188008000290800D
-:10A370000A00137400D2302127BDFFE03C0D800895
-:10A38000AFB20018AFB00010AFBF001CAFB10014E7
-:10A3900035B200808E4C001835A80100964B00069F
-:10A3A00095A70050910900EC000C56020167282384
-:10A3B0003143007F312600FF24020003A38300A065
-:10A3C000AF84009810C2001B30B0FFFF910600EC74
-:10A3D0002412000530C200FF1052003300000000BC
-:10A3E000160000098FBF001C8FB200188FB1001437
-:10A3F0008FB00010240D0C003C0C800027BD002005
-:10A4000003E00008AD8D00240E0010DA02002021C8
-:10A410008FBF001C8FB200188FB100148FB00010D6
-:10A42000240D0C003C0C800027BD002003E0000838
-:10A43000AD8D0024965800789651007A924E007D9A
-:10A440000238782631E8FFFF31C400C014800009CB
-:10A450002D11000116000037000000005620FFE219
-:10A460008FBF001C0E000FB0000000000A00143C5B
-:10A470008FBF001C1620FFDA000000000E000FB096
-:10A48000000000001440FFD88FBF001C16000022FF
-:10A4900000000000925F007D33E2003FA242007D99
-:10A4A0000A00143C8FBF001C950900DA8F860078E3
-:10A4B00000802821240400050E0006AA3130FFFF89
-:10A4C0009783008A3C0480002465FFFFA785008AEB
-:10A4D0008C8A01B80540FFFE00000000AC800180BE
-:10A4E0008FBF001CAC9001848FB200188FB1001494
-:10A4F0008FB000103C0760133C0B1000240D0C00C3
-:10A500003C0C800027BD0020AC870188AC8B01B8D3
-:10A5100003E00008AD8D00240E0010DA02002021B7
-:10A520005040FFB18FBF001C925F007D0A0014698C
-:10A5300033E2003F0E0010DA020020211440FFAA8F
-:10A540008FBF001C12200007000000009259007D00
-:10A550003330003F36020040A242007D0A00143C26
-:10A560008FBF001C0E000FB0000000005040FF9E87
-:10A570008FBF001C9259007D3330003F0A001498B1
-:04A58000360200405F
-:0CA58400000000000000001B0000000FA1
-:10A590000000000A0000000800000006000000059E
-:10A5A000000000050000000400000004000000039B
-:10A5B000000000030000000300000003000000038F
-:10A5C0000000000200000002000000020000000283
-:10A5D0000000000200000002000000020000000273
-:10A5E0000000000200000002000000020000000263
-:10A5F0000000000200000002000000020000000154
-:08A60000000000010000000150
-:08A608008008010080080080B9
-:10A610008008000000000C000000308008001020BE
-:10A62000080010CC080010E4080010F80800110C15
-:10A6300008001020080010200800114008001178C0
-:10A6400008001188080011B0080018A0080018A020
-:10A65000080018D8080018D8080018EC080018BC22
-:10A6600008001B1408001AE008001B6C08001B6C93
-:10A6700008001BF408001B24800802400800228008
-:10A68000080020CC080022A80800234008002490DD
-:10A69000080024DC08002600080025080800258C96
-:10A6A0000800213C08002AA808002A4C080020E8DD
-:10A6B000080020E8080020E8080026740800267436
-:10A6C000080020E8080020E808002924080020E805
-:10A6D000080020E8080020E8080020E80800298495
-:10A6E000080020E8080020E8080020E8080020E82A
-:10A6F000080020E8080020E8080020E8080020E81A
-:10A70000080020E8080020E8080020E8080020E809
-:10A71000080020E8080020E8080024FC080020E8E1
-:10A72000080020E8080029F4080020E8080020E8D4
-:10A73000080020E8080020E8080020E8080020E8D9
-:10A74000080020E8080020E8080020E8080020E8C9
-:10A75000080020E8080020E8080020E8080020E8B9
-:10A76000080020E8080020E8080020E80800284841
-:10A77000080020E8080020E8080027BC0800271887
-:10A78000080038600800383408003800080037D462
-:10A79000080037B40800376880080100800800808E
-:10A7A0008008000080080080080047C808004800B2
-:10A7B00008004748080047C8080047C8080045285F
-:08A7C000080047C808004B9C8B
-:08A7C8000A000C7600000000FD
-:10A7D000000000000000000D727870352E302E3021
-:10A7E0006A31350005000003000000000000000190
-:10A7F0000000000000000000000000000000000059
-:10A800000000000000000000000000000000000048
-:10A810000000000000000000000000000000000038
-:10A820000000000000000000000000000000000028
-:10A830000000000000000000000000000000000018
-:10A840000000000000000000000000000000000008
-:10A8500000000000000000000000000000000000F8
-:10A8600000000000000000000000000000000000E8
-:10A8700000000000000000000000000000000000D8
-:10A8800000000000000000000000000000000000C8
-:10A8900000000000000000000000000000000000B8
-:10A8A00000000000000000000000000000000000A8
-:10A8B0000000000000000000000000000000000098
-:10A8C0000000000000000000000000000000000088
-:10A8D0000000000000000000000000000000000078
-:10A8E0000000000000000000000000000000000068
-:10A8F0000000000000000000000000000000000058
-:10A900000000000000000000000000000000000047
-:10A910000000000000000000000000000000000037
-:10A920000000000000000000000000000000000027
-:10A930000000000000000000000000000000000017
-:10A940000000000000000000000000000000000007
-:10A9500000000000000000000000000000000000F7
-:10A9600000000000000000000000000000000000E7
-:10A9700000000000000000000000000000000000D7
-:10A9800000000000000000000000000000000000C7
-:10A9900000000000000000000000000000000000B7
-:10A9A00000000000000000000000000000000000A7
-:10A9B0000000000000000000000000000000000097
-:10A9C0000000000000000000000000000000000087
-:10A9D0000000000000000000000000000000000077
-:10A9E0000000000000000000000000000000000067
-:10A9F0000000000000000000000000000000000057
-:10AA00000000000000000000000000000000000046
-:10AA10000000000000000000000000000000000036
-:10AA20000000000000000000000000000000000026
-:10AA30000000000000000000000000000000000016
-:10AA40000000000000000000000000000000000006
-:10AA500000000000000000000000000000000000F6
-:10AA600000000000000000000000000000000000E6
-:10AA700000000000000000000000000000000000D6
-:10AA800000000000000000000000000000000000C6
-:10AA900000000000000000000000000000000000B6
-:10AAA00000000000000000000000000000000000A6
-:10AAB0000000000000000000000000000000000096
-:10AAC0000000000000000000000000000000000086
-:10AAD0000000000000000000000000000000000076
-:10AAE0000000000000000000000000000000000066
-:10AAF0000000000000000000000000000000000056
-:10AB00000000000000000000000000000000000045
-:10AB10000000000000000000000000000000000035
-:10AB20000000000000000000000000000000000025
-:10AB30000000000000000000000000000000000015
-:10AB40000000000000000000000000000000000005
-:10AB500000000000000000000000000000000000F5
-:10AB600000000000000000000000000000000000E5
-:10AB700000000000000000000000000000000000D5
-:10AB800000000000000000000000000000000000C5
-:10AB900000000000000000000000000000000000B5
-:10ABA00000000000000000000000000000000000A5
-:10ABB0000000000000000000000000000000000095
-:10ABC0000000000000000000000000000000000085
-:10ABD0000000000000000000000000000000000075
-:10ABE0000000000000000000000000000000000065
-:10ABF0000000000000000000000000000000000055
-:10AC00000000000000000000000000000000000044
-:10AC10000000000000000000000000000000000034
-:10AC20000000000000000000000000000000000024
-:10AC30000000000000000000000000000000000014
-:10AC40000000000000000000000000000000000004
-:10AC500000000000000000000000000000000000F4
-:10AC600000000000000000000000000000000000E4
-:10AC700000000000000000000000000000000000D4
-:10AC800000000000000000000000000000000000C4
-:10AC900000000000000000000000000000000000B4
-:10ACA00000000000000000000000000000000000A4
-:10ACB0000000000000000000000000000000000094
-:10ACC0000000000000000000000000000000000084
-:10ACD0000000000000000000000000000000000074
-:10ACE0000000000000000000000000000000000064
-:10ACF0000000000000000000000000000000000054
-:10AD00000000000000000000000000000000000043
-:10AD10000000000000000000000000000000000033
-:10AD20000000000000000000000000000000000023
-:10AD30000000000000000000000000000000000013
-:10AD40000000000000000000000000000000000003
-:10AD500000000000000000000000000000000000F3
-:10AD600000000000000000000000000000000000E3
-:10AD700000000000000000000000000000000000D3
-:10AD800000000000000000000000000000000000C3
-:10AD900000000000000000000000000000000000B3
-:10ADA00000000000000000000000000000000000A3
-:10ADB0000000000000000000000000000000000093
-:10ADC0000000000000000000000000000000000083
-:10ADD0000000000000000000000000000000000073
-:10ADE0000000000000000000000000000000000063
-:10ADF0000000000000000000000000000000000053
-:10AE00000000000000000000000000000000000042
-:10AE10000000000000000000000000000000000032
-:10AE20000000000000000000000000000000000022
-:10AE30000000000000000000000000000000000012
-:10AE40000000000000000000000000000000000002
-:10AE500000000000000000000000000000000000F2
-:10AE600000000000000000000000000000000000E2
-:10AE700000000000000000000000000000000000D2
-:10AE800000000000000000000000000000000000C2
-:10AE900000000000000000000000000000000000B2
-:10AEA00000000000000000000000000000000000A2
-:10AEB0000000000000000000000000000000000092
-:10AEC0000000000000000000000000000000000082
-:10AED0000000000000000000000000000000000072
-:10AEE0000000000000000000000000000000000062
-:10AEF0000000000000000000000000000000000052
-:10AF00000000000000000000000000000000000041
-:10AF10000000000000000000000000000000000031
-:10AF20000000000000000000000000000000000021
-:10AF30000000000000000000000000000000000011
-:10AF40000000000000000000000000000000000001
-:10AF500000000000000000000000000000000000F1
-:10AF600000000000000000000000000000000000E1
-:10AF700000000000000000000000000000000000D1
-:10AF800000000000000000000000000000000000C1
-:10AF900000000000000000000000000000000000B1
-:10AFA00000000000000000000000000000000000A1
-:10AFB0000000000000000000000000000000000091
-:10AFC0000000000000000000000000000000000081
-:10AFD0000000000000000000000000000000000071
-:10AFE0000000000000000000000000000000000061
-:10AFF0000000000000000000000000000000000051
-:10B000000000000000000000000000000000000040
-:10B010000000000000000000000000000000000030
-:10B020000000000000000000000000000000000020
-:10B030000000000000000000000000000000000010
-:10B040000000000000000000000000000000000000
-: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
-:10D9A0000000000010000003000000000000000D57
-:10D9B0000000000D3C020801244282603C03080183
-:10D9C00024638320AC4000000043202B1480FFFD23
-:10D9D000244200043C1D080037BD9FFC03A0F02139
-:10D9E0003C100800261031D83C1C0801279C82609E
-:10D9F0000E0011EA000000000000000D3C02800053
-:10DA000030A5FFFF30C600FF344301803C08800092
-:10DA10008D0901B80520FFFE00000000AC64000085
-:10DA200024040002A4650008A066000AA064000B9C
-:10DA3000AC6700183C03100003E00008AD0301B818
-:10DA40003C0560008CA24FF80440FFFE000000007F
-:10DA5000ACA44FC03C0310003C040200ACA44FC473
-:10DA600003E00008ACA34FF89486000C00A05021FE
-:10DA70002488001400062B02000510800044482171
-:10DA80000109182B10600011000000009103000034
-:10DA90002C64000950800009911900010003608086
-:10DAA0003C0D080125AD8108018D58218D670000CE
-:10DAB00000E0000800000000911900010119402158
-:10DAC0000109302B54C0FFF29103000003E000086D
-:10DAD000000010210A000CBE25080001910F000172
-:10DAE000240E000A15EE00400128C8232F38000A32
-:10DAF0001700003D250D00028D580000250F00067F
-:10DB0000370E0100AD4E0000910C000291AB0001F8
-:10DB100091A4000291A60003000C2E00000B3C0013
-:10DB200000A7102500041A000043C8250326C025BD
-:10DB3000AD580004910E000691ED000191E700023E
-:10DB400091E50003000E5E00000D6400016C3025BD
-:10DB50000007220000C41025004518252508000AEA
-:10DB60000A000CBEAD430008910F0001250400021D
-:10DB70002408000255E80001012020210A000CBE03
-:10DB800000804021910C0001240B0003158B00162E
-:10DB9000000000008D580000910E000225080003CF
-:10DBA000370D0008A14E00100A000CBEAD4D00005C
-:10DBB00091190001240F0004172F000B0000000032
-:10DBC00091070002910400038D43000000072A0022
-:10DBD00000A410253466000425080004AD42000CA2
-:10DBE0000A000CBEAD46000003E00008240200015C
-:10DBF00027BDFFE8AFBF0014AFB000100E0014E661
-:10DC0000008080213C0480083485008090A60005B7
-:10DC10002403FFFE0200202100C310248FBF001444
-:10DC20008FB00010A0A200050A0014F027BD001854
-:10DC300027BDFFE8AFB00010AFBF00140E000F4EBD
-:10DC4000008080213C06800834C5008090A400003C
-:10DC500024020050308300FF106200073C0980005E
-:10DC6000020020218FBF00148FB00010AD20018072
-:10DC70000A00101027BD0018240801003C0780008E
-:10DC8000020020218FBF00148FB00010ACE801808B
-:10DC90000A00101027BD001827BDFF703C0880083F
-:10DCA000AFB60080AFB5007CAFB1006CAFBF008CE9
-:10DCB000AFBE0088AFB70084AFB40078AFB30074D4
-:10DCC000AFB20070AFB00068350500803C0780003F
-:10DCD0008CF2012890A40009ACE0008490A6000515
-:10DCE000309100FF0000A8210006182730620001D3
-:10DCF0000000B02114400067AFA0005090A90000C0
-:10DD000024050020312400FF10850016240A00504D
-:10DD1000108A008C000000003C0C08008D8C00DC98
-:10DD2000258B00013C010800AC2B00DC0E0015DC4B
-:10DD3000000000008FBF008C8FBE00888FB700846A
-:10DD40008FB600808FB5007C8FB400788FB30074DD
-:10DD50008FB200708FB1006C8FB0006803E00008D4
-:10DD600027BD00900000000D3C108000AFA00030E7
-:10DD7000961F01168E1901043C1E002036130C005C
-:10DD8000033EC0240018B82B00173140AFA6003066
-:10DD90008E0E010433F4FFFF3C0F004002938021FC
-:10DDA00001CF68249213000D11A0004834C4004034
-:10DDB000326200201440000234860080008030214E
-:10DDC00014C00093AFA600303C05800834A8008042
-:10DDD0009107000830E6004050C000063C0680086D
-:10DDE00024090004122900A2240A0012122A002980
-:10DDF0003C06800834D401003C17800096EF011ADD
-:10DE0000960D000E928E0008326B000431F7FFFF72
-:10DE100001CD6004AFAC00548E14000411600031D9
-:10DE20008E1E000834C3008090790008333800400B
-:10DE300017000028000000008C730050029390230C
-:10DE4000064000063C0C80008C7E0034029E80233D
-:10DE5000060200838EA200083C0C8000AD800044C6
-:10DE6000240200018FBF008C8FBE00888FB7008412
-:10DE70008FB600808FB5007C8FB400788FB30074AC
-:10DE80008FB200708FB1006C8FB0006803E00008A3
-:10DE900027BD00900E000D1A000020218FBF008CBE
-:10DEA0008FBE00888FB700848FB600808FB5007C4E
-:10DEB0008FB400788FB300748FB200708FB1006C94
-:10DEC0008FB0006803E0000827BD00900A000D7ABB
-:10DED00000C020210E00163D028020211440FFDFEB
-:10DEE0003C0C80003C038008346300808C6200346A
-:10DEF0000282F82307E00017000000003C1508002C
-:10DF00008EB5310026B100013C010800AC31310072
-:10DF10000E0014E6024020213C0B80083570008082
-:10DF2000920A002502402021354200040E0014F020
-:10DF3000A20200250E000C9E024020210A000DA71F
-:10DF4000240200013C15080126B583100A000D6962
-:10DF50003C1080008C660030028620231880000868
-:10DF60002409000C3C0808008D083100327300FCC5
-:10DF70000000B821250700013C010800AC27310052
-:10DF8000AFA900308C65003000B4382318E000DB06
-:10DF900002E7502A1540FFDE0000000012E7002AC9
-:10DFA00002E768230287A02131B7FFFF326E00022B
-:10DFB00011C00034327F00103C148008369000807D
-:10DFC000920F000831F6004052C000CE8EA2000829
-:10DFD000024020210E0014E624130018A2130009A9
-:10DFE000921800052419FFFE024020210319B824CD
-:10DFF0000E0014F0A21700052404003900002821A7
-:10E000000E001618240600180A000DA724020001AD
-:10E0100092B6000C3C048008348300808C67003882
-:10E020000016AB0036B10081024020213225F0817C
-:10E030000E000C8D30C600FF3C0C8000AD8000440B
-:10E040000A000DA7240200013A6C0001318B000187
-:10E050001560FFAF0287A0210A000DF80000000044
-:10E060000040F809240400160A000DA7240200014C
-:10E07000024020210E00171D020028210A000D5C1D
-:10E080008FBF008C13E0FF743C038008346800806D
-:10E090008D0400388C66000403C610231C40FF6FFB
-:10E0A0003C0C800003C4282304A200010080F0215E
-:10E0B000AFB40010AFB70014AFA700183C1F80002A
-:10E0C00097E301208D0900309506005C8FB900545C
-:10E0D0008FAC00303062FFFF30D8FFFF0047702167
-:10E0E00037EF40000338682B01CF5821018D5025B0
-:10E0F000AFAB0020AFA90028AFAA0030AFA9002421
-:10E10000AFA0002CAFBE00349107000830E4000837
-:10E110001480008F020020218EA200040040F80924
-:10E1200027A400108FA900303128000255000001FB
-:10E13000327300FE3C048008348C0080918B000810
-:10E14000316A0040514000128FA400248C8D0004DD
-:10E1500011BE00BE240E00143265000110A0000C98
-:10E160008FA400242404000C122400D42A27000DBC
-:10E1700010E000CE2409000E2408000A52280001F5
-:10E18000241600088FA2002424440001AFA4002418
-:10E190008FA600143C038008346500800086F821B7
-:10E1A0008CB10030ACBF003090B9004E8CAE003066
-:10E1B0003418FFFF0338780401CF6821ACAD003478
-:10E1C0008FA600308FAC005430CA000803CC582111
-:10E1D0001140000CAFAB00588CA400208FB0005849
-:10E1E0001090009430C600FF92A2000C8FA700345C
-:10E1F0000240202100024B00352800800E000C8DCB
-:10E200003105F0803C0C8008359000808E0B00308A
-:10E210000171502319400070265900803C180800F5
-:10E220008F183198241FFF80033F7824332D007FFF
-:10E230003C0680003C0E800433110010ACCF0090EF
-:10E240001220003401AE282190A3006B54600032EC
-:10E250003C10800824070001A0A7006B94C4007A3A
-:10E260002486000AA60600123C0D800835A5008011
-:10E2700090B10008322C0040158000043C03800857
-:10E28000326E000115C0006200000000346400809E
-:10E290008C8F00208FB3005811F3000A3463010003
-:10E2A0008C7900000299C0231B0000778FA80058CA
-:10E2B000AC880020AC74000024140001AC7E000483
-:10E2C000AFB4005016C00037000000008FA400500B
-:10E2D000148000300000000012E00005000018214A
-:10E2E0008FA900303137000452E0FE920060102107
-:10E2F000240300010A000D5B006010210A000DF9E3
-:10E30000000038210040F809240400170A000DA776
-:10E31000240200013C10800836100080240900010E
-:10E32000024020210E0014E6A609001292080025E2
-:10E3300024050001AFA50050350200010240202154
-:10E340000E0014F0A20200250A000EA93C0D800860
-:10E3500027A50038AFA800600E000CA8AFA00038B9
-:10E360001440FF6D8FA800608FA5003830B0010009
-:10E370005200FF6A8EA200048FA3003C8D07005854
-:10E38000006720230483FF64AD0300580A000E5584
-:10E390008EA200040E000C9E024020210A000EC432
-:10E3A000000000000E0014E6024020213C05800819
-:10E3B00034A30080024020210E0014F0A076000952
-:10E3C00002C03021240400370E0016180000282156
-:10E3D0000A000EC28FA400508FA200185840FFA35D
-:10E3E0003C0D80080E0014E602402021920A002510
-:10E3F000240B0001AFAB0050354200040240202145
-:10E400000E0014F0A20200250A000EA93C0D80089F
-:10E410008CB600308EBE00082404001826D50001FA
-:10E4200003C0F809ACB500308FB200300A000D5BB4
-:10E43000324200043C07800094E5011A50A0FF6AB4
-:10E4400034C600100A000E8992A2000C122E002A77
-:10E450002A2F001511E0001E241900162418000CA4
-:10E460005638FF3E326500013C1F800893E3001BD5
-:10E470002410FFBD2416000E00703024A3E6001BFC
-:10E480000A000E65326500018C7F000017F4FF8DD5
-:10E49000000000008C67000403C7302304C1FF8420
-:10E4A0008FA800580A000EBF000000001629FF3692
-:10E4B0008FA200240A000E70241600102411000EF2
-:10E4C00052D1FF30241600100A000E6F24160016D9
-:10E4D0005639FF22326500013C1F800893E3001B80
-:10E4E0002410FFBD2416001000703024A3E6001B8A
-:10E4F0000A000E65326500010A000E64241600123F
-:10E500003C0380008C6201B80440FFFE2404080034
-:10E51000AC6401B803E000080000000030A5FFFF74
-:10E5200030C6FFFF3C0780008CE201B80440FFFECC
-:10E5300034E80180AD040000ACE400203C04800815
-:10E54000948300483063FFFF1060001D3C0B800087
-:10E5500024AA0012006A482B5120001A240A000342
-:10E5600094F901208F890000240C001A3338FFFF32
-:10E570002707FFFE0067782B39EE000100096B8248
-:10E5800001AE5824A10C000B116000478F830004DA
-:10E59000A50700148F88000435070001AF87000429
-:10E5A00030CC00405580000F3C0880003C0C8000BF
-:10E5B00035840180A485000E0A000F988F8F000C0F
-:10E5C000240A00033564018030CC00408F890000AC
-:10E5D0008F870004A08A000B5180FFF53C0C80005F
-:10E5E0003C088000950301203C08800895180040F5
-:10E5F0003079FFFF272EFFFE330FFFFF01CF682B7F
-:10E6000011A0000301C02021950200403044FFFF0B
-:10E610003C0B800000A4502335650180A4A4000EAB
-:10E62000A4AA00248F8F000C3C05800034AE01802A
-:10E630002418000230ED8000A5D8000CA5C90010F8
-:10E64000ADCF0028A5C6000811A0000E3C04800034
-:10E6500094AA01163142FFFC244800040105182148
-:10E660008C7940003326FFFF14C00007240EBFFF43
-:10E670003C0BFFFF35657FFF00E53824AF870004C2
-:10E680003C048000240EBFFF348C018000EE68241F
-:10E69000A58D0026AD89002C3C071000AC8701B881
-:10E6A00003E00008000000002402FFFE006238249E
-:10E6B0000A000F76AF8700043C05800034A4007088
-:10E6C0008C8A000090A601128F84000027BDFFF005
-:10E6D00030C300FF0003188230820100000038219F
-:10E6E00010400039246600033087400050E00039B4
-:10E6F00030882000000610800045C8218F2F400080
-:10E700002478000400187080AFAF000001C56821B4
-:10E710008DAC4000AFAC000494AB01163169FFFC36
-:10E72000012540218D054000AFA500088FA90008F4
-:10E7300000003021000028213C07080024E70100E8
-:10E740000A000FE9240800089042000024A50001F7
-:10E750002CAD000C0062C8210019C080030778218D
-:10E760008DEE000011A0000600CE302603A510217A
-:10E7700014A8FFF500051A005520FFF49042000090
-:10E780003C048000348700703C0508008CA53104EF
-:10E790008CE300002CA8002011000009006A382337
-:10E7A000000558803C0C0800258C3108016C48217C
-:10E7B00024AA0001AD2700003C010800AC2A310466
-:10E7C000AF86000C2407000100E0102103E00008E0
-:10E7D00027BD00101100FFFC0000382100066080FA
-:10E7E000018558218D6440002469000400093880A7
-:10E7F000AFA4000000E518218C664000AFA000081F
-:10E800000A000FD9AFA6000427BDFFD8AFB2001889
-:10E81000AFB00010AFBF0024AFB40020AFB3001CF6
-:10E82000AFB100148F8700003C0480009483010E78
-:10E8300030E2400000008021104000103072FFFFE5
-:10E840003C06002000E6282410A0000D30EA8000DD
-:10E850008F8800042409BFFF00E938243503100025
-:10E86000AF87000030F120001620000B3C1400049C
-:10E870002418FFBF0A0010380078102430EA800006
-:10E88000154000863C0C002030F120001220FFF8DB
-:10E890008F8300043C14000400F498241260FFF5F8
-:10E8A0002418FFBF3462004030F901001320000F2C
-:10E8B000AF8200043C02002000E2F82413E00005CF
-:10E8C0003C0B80003C04000400E41824106000CFDE
-:10E8D00000000000956A011E9569011C3146FFFF8A
-:10E8E0000009440000C82825AF85000C3C0E8000BC
-:10E8F00095CD010C8DC44000340CFFFF108C00B08E
-:10E9000031A5FFFF308F010055E0000124100010F9
-:10E9100030F11000522000083611000130F30020C1
-:10E920001660009F3C18100000F8A0241680009686
-:10E930003C040C003611000130E801001500000B0A
-:10E940003C0A00018F8800043109400015200008AE
-:10E9500000EA30243C0C1F0100EC58243C0A100053
-:10E96000516A00AE30AD02003C0A000100EA3024DA
-:10E9700014C000953C05100000E520240000402153
-:10E98000108000070000902100079E023272000FE5
-:10E99000001278803C0E080125CE82C001EE402195
-:10E9A0008F9400181280004702208021108000916F
-:10E9B000000000003C0980009539010E9103000021
-:10E9C000022030213338FFFF2705000410600008C3
-:10E9D0000000A021241F0003107F013A240400023C
-:10E9E000910C00011184011830EA00400012A1C00E
-:10E9F0008F92001C52400001362600403C138000DC
-:10EA00008E6F400031F10100122000CB30D1FFFBAE
-:10EA10003C1808008F18002430D20004330600048C
-:10EA200014C000CC30B0FFFF564000013631000466
-:10EA300002802021020028210E000F5502203021E3
-:10EA40001640000D00002021366501803C04800046
-:10EA50008C9301B80660FFFE2419200024140002E4
-:10EA6000A4B90008A0B4000BA4A000103C0510003D
-:10EA7000AC8501B8000020218FBF00248FB4002096
-:10EA80008FB3001C8FB200188FB100148FB000102C
-:10EA90000080102103E0000827BD002800EC582466
-:10EAA0001160FF7A30F120008F8D00043C0FFFFFD2
-:10EAB00035EE7FFF00EE382435A380000A001027D2
-:10EAC000AF8700003C0208008C4200383C0408007C
-:10EAD000248400381040004B2449FFFF3C03800091
-:10EAE000946C010E318BFFFF110000A02573000410
-:10EAF0003C1008008E1000301200000A30E60100C1
-:10EB00008F8A000431434000106000063C0F0F0064
-:10EB100000EF70243C0D010001AE402B110000DF1E
-:10EB20003265FFFF10C000693C140F0000F4282478
-:10EB30003C18020010B800658F99000C3270FFFF7E
-:10EB40000329982402649021924900042527000497
-:10EB5000000721C002002821362600020E000F55B2
-:10EB6000000000008FBF00248FB400208FB3001C72
-:10EB70008FB200188FB100148FB000100000102168
-:10EB800003E0000827BD00283C020BFF00E4182426
-:10EB9000345FFFFF03E3C82B5320FF6736110001EA
-:10EBA0003C0608008CC6002C3611000524D000015C
-:10EBB0003C010800AC30002C0A00105D30E8010078
-:10EBC0000A00105224100020024028213C120800A4
-:10EBD0008E5200D824040080264D00013C0108001C
-:10EBE000AC2D00D80E000F55240600030A0010E8D3
-:10EBF0008FBF00243C080801250882C00A00107C51
-:10EC00003C0980000A0010C5000048210E000FBC1E
-:10EC1000000000000A0010498F87000015A0FF5374
-:10EC20003C0A00012645000430AAFFFF36260002F8
-:10EC30003C0380008C7201B80640FFFE8F850008FF
-:10EC400034690180AD20000010A000AF3C048000BA
-:10EC5000254F001200AF702B51C000AC24030003FD
-:10EC6000947801202414001A30F140003313FFFF80
-:10EC7000A134000B122000B62663FFFE00A3C82BB0
-:10EC8000572000B4241FFFFE35080001A5230014FF
-:10EC9000AF8800043C108000240CBFFF010C482406
-:10ECA000240B000236080180A50B000CA50A000EFB
-:10ECB000A5060008A5090026A50700103C071000BE
-:10ECC000AE0701B80A0010E88FBF00243C0308001B
-:10ECD0008C6300D02E45000C001221C0386B00015F
-:10ECE0002D6200010045F82417E0FF9A3270FFFF03
-:10ECF000264CFFFC2D84000454800050000020218D
-:10ED0000386A00022D430001006580241600004A85
-:10ED10003270FFFF00076A420012702B01AE4024E0
-:10ED20005500006300002021001221C002002821AC
-:10ED30000A0010E53626000234DF0002028020219E
-:10ED400033E6FFFF0E000F5530A5FFFF0A0010ACA1
-:10ED50000000202124040100020028210E000F558C
-:10ED6000022030210A001098000000008C6640004C
-:10ED700030CF010011E0003D30F801003C120800E6
-:10ED80008E52002413000011323400043C1F0F0087
-:10ED900000FFC8243C0502001325000C8F8C000CDA
-:10EDA000022030213265FFFF0189582401641021BF
-:10EDB000904900043230FFFB2411FFFE2527000498
-:10EDC0000E000F55000721C00251902424040001B9
-:10EDD00012440052324300011460005802003021F6
-:10EDE000324A0004114000048F8D000031A8080051
-:10EDF0001500005A3265FFFF1680FF5B8FBF0024AD
-:10EE00003C138000366501803C0480008C9001B882
-:10EE10000600FFFE24062000240F0002A4A600081E
-:10EE2000A0AF000BA4A000103C0E1000AC8E01B8E7
-:10EE30000A0010E88FBF00240000202102002821D2
-:10EE40000A0010E5362600021140FEE90000A0216C
-:10EE5000952E0110950D000231C8FFFF51A8FEE468
-:10EE60000012A1C00A00108B8F92001C3C05080004
-:10EE70008CA5002430B800015300FF3B8FBF002455
-:10EE80003265FFFF36260002000020210E000F55DC
-:10EE9000000000000A0010E88FBF002436260002A0
-:10EEA0000E000F55240400800A0010E88FBF0024D4
-:10EEB000020028210E000F553226FFFB0A001159CF
-:10EEC000001221C091030001240200011062FEEA39
-:10EED00024040001241000021470FEC50000A021CB
-:10EEE00030E300401060FEC38F92001C952B011090
-:10EEF000950900023167FFFF1127FEE08FBF002454
-:10EF00000A00108B000000002403000334820180FB
-:10EF1000A043000B0A0011343C108000321400049E
-:10EF2000168000033265FFFF361200023250FFFFE9
-:10EF3000020030210A0011B1000020210000202130
-:10EF40000E000F553265FFFF0A0011863210FFFBDD
-:10EF5000241FFFFE0A001132011F4024020030214D
-:10EF60000E000F55240401000A00118C000000005F
-:10EF700027BDFFC8AFB00010AFBF00343C10600C1D
-:10EF8000AFBE0030AFB7002CAFB60028AFB500243D
-:10EF9000AFB40020AFB3001CAFB20018AFB1001483
-:10EFA0008E0E5000240FFF7F3C06800001CF6824A6
-:10EFB00035AC380C240B0003AE0C5000ACCB000871
-:10EFC0003C010800AC2000200E00174900000000A2
-:10EFD0003C0A0010354980513C066016AE09537C4E
-:10EFE0008CC700003C0860148D0500A03C03FFFFA7
-:10EFF00000E320243C02535300051FC2108202622A
-:10F0000034C57C008CBE007C8CBF00783C02600064
-:10F01000344420203C05080124A581382406000A38
-:10F020003C170098AF9E0014AF9F00100E0015F221
-:10F030003C11800036F600C03C1900103C18600CF2
-:10F040003C158000AF1953FC363E0180AEB6013C42
-:10F050008E300000320400031080FFFD32050001F5
-:10F0600014A000593206000210C0FFF93C048000D1
-:10F070008C92014024100040AC9200208C8F0148FB
-:10F08000000F760231C300701070013E2C780041F1
-:10F090005300000824040060241900201079000E99
-:10F0A0003C1F40003C088000AD1F01780A0012227E
-:10F0B000000000001464FFFB3C1F40000E001F66B0
-:10F0C000000000003C1F40003C088000AD1F01789C
-:10F0D0000A001222000000008C940148241700044A
-:10F0E0003488018000144C02312500FF8C830140DC
-:10F0F00010B7017024ABFFFA2D6A000651400013CF
-:10F100003C0580008C86014430A400FF30C300FF22
-:10F1100030D500FF2C76000816C0000226A7000498
-:10F1200024070003240C0009108C01A8288D000A74
-:10F1300011A001942413000A24050008108500146E
-:10F140008F980018000719C03C0580008CA701B8F3
-:10F1500004E0FFFE24140002AD030000A50900082E
-:10F16000A114000B8CB701483C0910003C1F400063
-:10F17000A51700108CA40144AD0400243C088000B5
-:10F18000ACA901B8AD1F01780A00122200000000EE
-:10F19000000692020007C8803C040801248482C053
-:10F1A00003247821270E0001324500FF24100001BE
-:10F1B000A1F2000014B0FFE3AF8E0018000719C0E1
-:10F1C0000A001260AF85001C8E3401283C068008BE
-:10F1D000AE3400208E2A01048E29010094C8004814
-:10F1E000AF8A0000AF8900043103FFFF0E000F4E0D
-:10F1F000AF8300083C0708008CE700C010E0002443
-:10F200008F8700003C0C08008D8C00C4258B00010A
-:10F210003C010800AC2B00C43C1980008F24012461
-:10F220003C186020AF040014000000003C06800081
-:10F230003C174000ACD70138000000005280FF8A24
-:10F240003206000226870140268500802409FF80BF
-:10F2500000E9682400A998240013194030AC007F0D
-:10F26000000DB14030F5007F3C0B200035620002FC
-:10F27000006C402502D550250142A0250102F82549
-:10F28000ACDF0830ACD408300A0012283206000285
-:10F290003C0E001000EE682415A000A68F83000429
-:10F2A0003C1508008EB500203C16800096D2010E59
-:10F2B00026B3000130EF40003255FFFF3C0108004B
-:10F2C000AC33002011E000B6000090213C18002073
-:10F2D00000F8B82412E000B330E280008F990004F7
-:10F2E000241FBFFF00FF382437231000AF87000022
-:10F2F00030EA2000114000B5240CFFBF3C0B000495
-:10F3000000EB302410C00002006C10243462004076
-:10F3100030ED010011A0000EAF8200043C0F002070
-:10F3200000EF702411C000043C16000400F698247D
-:10F3300012600135000000009622011E963F011C5C
-:10F340003058FFFF001FCC000319B825AF97000C01
-:10F350009628010C8E2440003403FFFF108300C860
-:10F360003105FFFF308901005520000124120010F3
-:10F3700030E41000108000133653000130EA002002
-:10F380001540000A3C0B100000EB302410C0000DAB
-:10F390003C0F0BFF3C130C0000F3702435EDFFFF16
-:10F3A00001AE602B11800007365300013C160800A7
-:10F3B0008ED6002C3653000526D200013C010800F1
-:10F3C000AC32002C30F7010016E0000B3C060001C7
-:10F3D0008F880004311840005700000800E62824F8
-:10F3E0003C021F0100E2F8243C19100013F9010A45
-:10F3F00030A302003C06000100E6282414A000A26D
-:10F400003C09100000E92024000040211080000782
-:10F410000000A821000766023195000F00155880F2
-:10F420003C0A0801254A82C0016A40218F8D0018DC
-:10F4300011A0006802609021148000033C09800044
-:10F440003C080801250882C0952E010E910300009A
-:10F450000260302131C4FFFF2485000410600008E1
-:10F460000000B821240F0003106F011E24190002B0
-:10F47000911F000113F9002630E200400015B9C0C9
-:10F480008F89001C51200001366600403C16800028
-:10F490008ECB400031730100126000C530D50004EE
-:10F4A0003C0C08008D8C002430D3FFFB3186000417
-:10F4B00014C0010630B2FFFF56A0000136730004ED
-:10F4C00002E02021024028210E000F550260302169
-:10F4D00016A0000D0000202136C501803C048000EC
-:10F4E0008C8D01B805A0FFFE240F2000240E000221
-:10F4F000A4AF0008A0AE000BA4A000103C051000B3
-:10F50000AC8501B8000020210A001367008010219B
-:10F510001040FFDB0000B821952A0110950300027E
-:10F520003148FFFF5068FFD60015B9C00A00132FFD
-:10F530008F89001C2413BFFF0073282410A000072C
-:10F54000240E87FF006E48241520000A3C1200603C
-:10F5500000F2782411E00007000000000E000D34D6
-:10F56000000000001040FF323C0680000A001295A7
-:10F570003C1980000E0014CF000000000A00136741
-:10F58000000000000E0014F5000000003C1F4000C9
-:10F590003C088000AD1F01780A0012220000000024
-:10F5A00030E280001040FF528F8300043C050020B1
-:10F5B00000E520241080FF4E3C09FFFF35287FFF27
-:10F5C00000E838240A0012C9346380000A0012D20D
-:10F5D000006C10243C0408008C8400381480000265
-:10F5E0002489FFFF000048213C0380009476010E2F
-:10F5F00032D7FFFF110000EA26F600043C12080093
-:10F600008E5200301240000A30EA01008F99000447
-:10F6100033384000130000063C030F0000E3402491
-:10F620003C0201000048F82B13E000D232C5FFFF76
-:10F630001140002F3C0C0F0000EC30243C0B02006A
-:10F6400010CB002B8F8F000C3C0E080025CE00380D
-:10F6500032D2FFFF01E9282400AE682191A90004FD
-:10F6600025270004000721C0024028213666000239
-:10F670000E000F55000000000A0013670000102163
-:10F680000A0012EA241200203C0308008C6300D810
-:10F6900002A0282124040080246200013C0108000B
-:10F6A000AC2200D80E000F55240600030A00136791
-:10F6B000000010218C840140010028213C038000BF
-:10F6C0008C7F01B807E0FFFE2402001CACA4000000
-:10F6D000A0A2000B3C081000AC6801B83C1F400021
-:10F6E0003C088000AD1F01780A00122200000000D3
-:10F6F0003C0308008C6300D02EA5000C001521C02F
-:10F70000387800012F1200010245B82416E0FFD618
-:10F7100032D2FFFF26B9FFFC2F240004148000081A
-:10F7200000002021386800022D0200010045F82465
-:10F7300013E0000600075A4232D2FFFF00002021EA
-:10F74000024028210A0013AA366600020015182B71
-:10F75000016350241540000532D2FFFF001521C07F
-:10F76000024028210A0013AA366600020000202168
-:10F77000024028210E000F553266FFFB0A0013E6F7
-:10F78000001521C010930068000768802406000B54
-:10F790001486FE6D000719C00007C0803C190801DF
-:10F7A000273982C0031930210A001260A0C000016D
-:10F7B00034D5000202E0202130A5FFFF0E000F55D6
-:10F7C00032A6FFFF0A001350000020210007A0808E
-:10F7D0003C1F080127FF82C0029F102190570000A4
-:10F7E00012E0FE59000719C0A04000008F8A0018DF
-:10F7F0002542FFFF1440FE54AF820018000719C0D5
-:10F800000A001260AF80001C0E000FBC0000000058
-:10F810000A0012E28F8700001460FEF73C06000128
-:10F8200026A900043125FFFF366600023C03800054
-:10F830008C7501B806A0FFFE8F8900083C0A800085
-:10F8400035440180AC8000001120009B2418000387
-:10F8500024AC0012012C582B11600097000000000E
-:10F86000947201203C138000240F001A324EFFFFD7
-:10F87000366A018030ED4000A14F000B11A00091CD
-:10F8800025C3FFFE0123B02B16C0008F2417FFFEF7
-:10F8900035080001A5430014AF880004241FBFFFF2
-:10F8A000011FC82424080002A7C8000CA7C5000E29
-:10F8B000A7C60008A7D90026A7C700103C0710005C
-:10F8C000AE2701B80A0013670000102124040100CC
-:10F8D000024028210E000F55026030210A00133C1F
-:10F8E0000000000091030001241500011075FF06BF
-:10F8F00024040001241200021472FEE10000B82169
-:10F9000030F6004052C0FEDF8F89001C95270110A1
-:10F910009518000230F7FFFF1317FEFB0000B82117
-:10F920000A00132F8F89001C3C120801265282C046
-:10F9300001B2702100067A02A1CF00013C0B6000E9
-:10F940008D6318202410000100F098043C05080184
-:10F9500024A582C20073B02501A5A8210006640277
-:10F96000000719C0A6AC0000AD7618200A0012618D
-:10F970003C058000366600020E000F55240400800E
-:10F980000A001367000010210003A080028698215E
-:10F990008E7200043C1160000A00120F02512821EF
-:10F9A0008C66400030D5010012A0003730EC010019
-:10F9B0003C1508008EB50024118000133277000436
-:10F9C0003C050F0000E568243C07020011A7000E6B
-:10F9D0008F84000C3C180800271800380260302182
-:10F9E000008990240258782191EE000432C5FFFF6F
-:10F9F0003272FFFB25C90004000921C00E000F551B
-:10FA00002413FFFE02B3A8242419000112B9003008
-:10FA100032A200011040000732A800040240302149
-:10FA2000000020210E000F5532C5FFFF3252FFFBB0
-:10FA300032A80004110000048F8B0000316A080016
-:10FA40005540002B32C5FFFF16E0FEC60000102116
-:10FA50003C16800036C401803C0580008CA301B8B0
-:10FA60000460FFFE240C200024060002A48C000881
-:10FA7000A086000BA48000103C151000ACB501B8A6
-:10FA80000A001367000010213C0D08008DAD002412
-:10FA900031A7000150E0FEB30000102132C5FFFF86
-:10FAA00036660002000020210E000F550000000005
-:10FAB0000A00136700001021A3D8000B0A001436B7
-:10FAC000241FBFFF2417FFFE0A001434011740242F
-:10FAD0003257000416E0000332C5FFFF365F000214
-:10FAE00033F2FFFF024030210A0014B80000202149
-:10FAF000024030210E000F55240401000A0014A01A
-:10FB0000000000003C0380008C6401003082003E55
-:10FB10001440000800000000AC6000488C66010042
-:10FB200030C507C010A0000500000000AC60004C0C
-:10FB3000AC60005003E0000824020001AC600054F7
-:10FB4000AC6000408C6801003107380010E0FFF91C
-:10FB5000000000002402000103E00008AC60004443
-:10FB60003C03900034620001008220253C038000A9
-:10FB7000AC6400208C65002004A0FFFE00000000A3
-:10FB800003E00008000000003C0280003443000154
-:10FB90000083202503E00008AC44002027BDFFD8E7
-:10FBA000AFB100143C048000AFBF0020AFB3001C15
-:10FBB000AFB20018AFB000108C9201408C90014899
-:10FBC0002402000E00108C02322300FF1062005944
-:10FBD000020428242866000F10C00013286A00378A
-:10FBE000240700061067008E286800075100002DCA
-:10FBF00024040009106000783C06800024090001FC
-:10FC0000106900B0000000000000000D8FBF002050
-:10FC10008FB3001C8FB200188FB100148FB000108A
-:10FC200003E0000827BD002811400059240D0038CA
-:10FC3000286B0035116000053C058000240C001F76
-:10FC4000146CFFF1000000003C0580008CB801B886
-:10FC50000700FFFE34B90180AF320000241F00010D
-:10FC6000241200023C021000AF200004A73100085B
-:10FC7000A33F000AA332000BA7300010AF200024DE
-:10FC8000AF200028ACA201B88FBF00208FB3001CAA
-:10FC90008FB200188FB100148FB0001003E000087D
-:10FCA00027BD0028106400232405000B1465FFD62F
-:10FCB0003218FFFF170000203C0580008F93FED014
-:10FCC000927F000533F900041720FFCF00000000E9
-:10FCD0000E0014E602402021926900050240202116
-:10FCE000352800040E0014F0A26800059267000594
-:10FCF00030E2000414400002000000000000000D8B
-:10FD0000926B000024060020316A00FF1546000AAD
-:10FD10003C0580008CA401B80480FFFE34AD018056
-:10FD2000240E00053C0C1000ADB20000A1AE000B8B
-:10FD3000ACAC01B83C0580008CA301B80460FFFEA8
-:10FD400034AF018024130002ADF20000ADF20004D4
-:10FD5000A5F10008A1F3000AA1F3000BA5F0001023
-:10FD6000ADE000248CB101443C101000ADF100283E
-:10FD7000ACB001B88FBF00208FB3001C8FB2001849
-:10FD80008FB100148FB0001003E0000827BD0028D9
-:10FD9000106DFFAD240E0080146EFF9B000000006C
-:10FDA0003C0580008CA301B80460FFFE34AF0180E5
-:10FDB00024120002A1F2000BA5F10008A5F000102A
-:10FDC0008CB301443C021000A5F30012ACA201B8B0
-:10FDD0000A0015318FBF00208CC301B80460FFFEFC
-:10FDE00034D30180AE720000AE6000042412000122
-:10FDF000A671000824110002A272000AA271000B71
-:10FE0000A67000108CD001443C0F1000AE7000248E
-:10FE1000AE600028ACCF01B80A00156C8FBF00207F
-:10FE20003C0380008C6601B804C0FFFE3462018090
-:10FE30003C06080190C68300AC52000010C00003CD
-:10FE4000000038213C0708018CE783083C0580004E
-:10FE500034AA01802404000234CC0001AC47000421
-:10FE6000A5510008A14C000AA144000BA5500010A8
-:10FE70008CAB01440000202101402821AD4B00241F
-:10FE800010C000038FBF00203C0408018C84830451
-:10FE90008FB3001C8FB200188FB100148FB0001008
-:10FEA0003C0E10003C0D800027BD0028ACA40028AB
-:10FEB000ADAE01B83C010801A020830003E00008BA
-:10FEC0000000000010A0000B3C0680008C9801444C
-:10FED000241900023C010801A03983003C010801FB
-:10FEE000AC3283083C010801AC3883040A00156C6D
-:10FEF0008FBF00208CDF01B807E0FFFE34C7018010
-:10FF000024090002ACF20000ACF20004A4F10008E5
-:10FF1000A0E9000AA0E9000BA4F00010ACE0002466
-:10FF20008CC801443C021000ACE80028ACC201B807
-:10FF30000A00156C8FBF002027BDFFE8AFBF00107F
-:10FF40000E000F4E000000003C0280008FBF00102A
-:10FF500000002021AC4001800A00101027BD0018CD
-:10FF60003084FFFF30A5FFFF10800007000018213C
-:10FF70003082000110400002000420420065182178
-:10FF80001480FFFB0005284003E0000800601021FA
-:10FF900010C00007000000008CA2000024C6FFFF74
-:10FFA00024A50004AC82000014C0FFFB24840004DC
-:10FFB00003E000080000000010A0000824A3FFFFD9
-:10FFC000AC86000000000000000000002402FFFFDB
-:10FFD0002463FFFF1462FFFA2484000403E0000896
-:10FFE0000000000027BDFFE8AFBF0014AFB0001055
-:10FFF0000E0014E6008080213C04800834830080D9
-:020000040001F9
-:10000000906500250200202134A200200E0014F08B
-:10001000A0620025020020218FBF00148FB00010C5
-:100020000A000C9E27BD00183C03800027BDFFF886
-:1000300034620180AFA20000308C00FF30AD00FFC1
-:1000400030CE00FF3C0B80008D6401B80480FFFEC1
-:10005000000000008FA900008D6801288FAA000011
-:100060008FA700008FA400002405000124020002D5
-:10007000A085000A8FA30000359940003C051000C0
-:10008000A062000B8FB800008FAC00008FA60000AC
-:100090008FAF000027BD0008AD280000AD40000470
-:1000A000AD800024ACC00028A4F90008A70D001002
-:1000B000A5EE001203E00008AD6501B83C0680081B
-:1000C00027BDFFE834C50080AFBF001090A700092E
-:1000D0002402001230E300FF1062000B0080302188
-:1000E0008CA8005000882023048000088FBF0010D7
-:1000F0008CAA0034240400390000282100CA4823B7
-:1001000005200005240600128FBF00102402000104
-:1001100003E0000827BD00180E00161800000000BC
-:100120008FBF00102402000103E0000827BD001863
-:1001300027BDFFC8AFB1002C00A08821AFB20030AE
-:1001400027A500100080902102202021AFBF00349D
-:10015000AFB000280E000CA8AFA000101440009B08
-:100160003C07800834E400809086000830C5000811
-:1001700014A000698FA700103C1880083710008079
-:10018000920F000831EE000815C000022408000399
-:10019000000040213C0B800891650011916A00121B
-:1001A000356600808CDF0054314900FF0128202192
-:1001B00030A300FF000410800062282100BFC82B7C
-:1001C000132000080000000094D0005C8CCF005485
-:1001D000320DFFFF01E5702301AE602B118000940A
-:1001E0000000000094D9005C3323FFFF30FF0004BF
-:1001F00013E00074000830808FA8001C0068102BEA
-:100200005040004F30E30004006610232C4600806D
-:1002100010C0000200408021241000800E0014E66F
-:10022000024020213C03800834660080240700013E
-:10023000ACC7000C90C8000800106840346701008B
-:10024000311F007FA0DF00088E390004273800012D
-:10025000ACD80030A4D0005C8CCF003C9630000EAF
-:1002600001F07021ACCE00208CCC003C018D5821D7
-:10027000ACCB001C8E2A0004ACEA00008E290008DA
-:10028000ACE900048FA5001030A4000854800032AF
-:1002900093A60020A0C0004E90C9004E2402FFDFAC
-:1002A0003C188008A0E9000890C50008370D0080C0
-:1002B000240A005000A22024A0C400088E3900089F
-:1002C000ADB900388F0F00148DB0003001F07021EF
-:1002D000ADAE003491AC0000318B00FF116A002CF0
-:1002E000264501000E0014F00240202124040038AD
-:1002F000000028210E0016182406000A8FBF0034C3
-:100300008FB200308FB1002C8FB000282402000182
-:1003100003E0000827BD003830E801001100003D6F
-:100320008FA300148C8A0058006A48230520FF938D
-:100330003C188008AC8300580A00166C8FA7001088
-:10034000240702181060FFB100E610238FA2001CE2
-:100350000A001691004610233C188008370D0080D3
-:10036000A0E600088E390008240A0050ADB9003814
-:100370008F0F00148DB0003001F07021ADAE00344D
-:1003800091AC0000318B00FF156AFFD626450100B5
-:100390002406FF8000A610243C098000AD2200281E
-:1003A0008E27000830A3007F3C04800C0064F821F5
-:1003B000AFE700D08E280008AF9F00280A0016C7BC
-:1003C000AFE800D40A00168E2C6202188E230008B3
-:1003D0003C04800834820080AC4300540240202159
-:1003E0000E001607AC400030240400382405008DB0
-:1003F0000E001618240600128FBF00348FB2003092
-:100400008FB1002C8FB000282402000103E0000807
-:1004100027BD0038AC800058908C0008240DFFF7F1
-:10042000018D5824A08B00080A00166C8FA70010BD
-:100430008CD800540A0016890305182327BDFFE84D
-:10044000AFBF001090A6000D30C7001010E0000CE8
-:10045000008040213C0280088C4400048CA30008EA
-:100460001064000830C9000530C5000510A0001C4C
-:100470008FBF00102402000103E0000827BD001810
-:1004800030C900051120001030CB001210E0FFF938
-:100490008FBF00103C0880088CA700088D06000460
-:1004A00014E6FFF524020001240400382405008D21
-:1004B0000E001618240600128FBF0010240200013F
-:1004C00003E0000827BD0018240A0012156AFFE99E
-:1004D0008FBF0010010020210A00165A27BD001806
-:1004E000000020210A000D1A27BD00183C05080055
-:1004F00024A55D683C04080024847B343C02080089
-:1005000024425D70240300063C010801AC258310E1
-:100510003C010801AC2483143C010801AC2283187F
-:100520003C010801A023831C03E000080000000038
-:1005300003E00008240200013C028000308800FF34
-:10054000344701803C0680008CC301B80460FFFE84
-:10055000000000008CC501282418FF803C0D800A93
-:1005600024AF010001F8702431EC007FACCE0024F0
-:10057000018D2021ACE50000948B00DA3509600084
-:1005800024080002316AFFFFACEA000424020001E3
-:10059000A4E90008A0E8000BACE000243C07100030
-:1005A000ACC701B8AF84002803E00008AF85005C49
-:1005B0008C9800048F8C00282409FFBF0305782342
-:1005C000AC8F0004918E00C42403FFEF31CD007F77
-:1005D000A18D00C48C8B00208F860028A780004C42
-:1005E000356A0002A4C000ACAC8A002090C800C4E8
-:1005F00001093824A0C700C48F840028AC8000DC27
-:10060000908500C400A3102403E00008A08200C469
-:100610003C028000344501803C0480008C8301B89A
-:100620000460FFFE8F89005C2407608324060002BB
-:10063000ACA900008C880124ACA80004A4A7000881
-:10064000A0A6000B3C05100003E00008AC8501B833
-:10065000938800388F8900508F82002830C600FFB1
-:100660000109382330E900FF0122182130A500FFDD
-:100670002468007810C0000201243821008038214D
-:1006800030E400031480000330AA00031140000D81
-:10069000312B000310A000090000102190ED000094
-:1006A000244E000131C200FF0045602BA10D000067
-:1006B00024E700011580FFF92508000103E0000888
-:1006C000000000001560FFF30000000010A0FFFB19
-:1006D000000010218CF8000024590004332200FF90
-:1006E0000045782BAD18000024E7000415E0FFF961
-:1006F0002508000403E0000800000000938500388E
-:10070000938800488F870050000432003103007F37
-:1007100000E5102B30C47F001040000F0064282536
-:100720008F8400283C0980008C8A00DCAD2A00A45C
-:100730003C03800000A35825AC6B00A08C6C00A08B
-:100740000580FFFE000000008C6D00ACAC8D00DC6D
-:1007500003E000088C6200A80A0017DA8F840028E2
-:10076000938800493C02800000805021310300FE44
-:10077000A383004930ABFFFF30CC00FF30E7FFFF21
-:10078000344801803C0980008D2401B80480FFFEBC
-:100790008F8D005C24180016AD0D00008D22012401
-:1007A0008F8D0028AD0200048D590020A507000898
-:1007B000240201B4A119000AA118000B952F0120F1
-:1007C0008D4E00088D4700049783004C8D590024FE
-:1007D00001CF302100C7282100A320232418FFFFC8
-:1007E000A504000CA50B000EA5020010A50C00121C
-:1007F000AD190018AD18002495AF00D83C0B1000BF
-:100800002407FFF731EEFFFFAD0E00288DAC00741A
-:10081000AD0C002CAD2B01B88D46002000C728245C
-:1008200003E00008AD4500208F8800280080582193
-:1008300030E7FFFF910900C63C02800030A5FFFFB2
-:10084000312400FF00041A000067502530C600FF65
-:10085000344701803C0980008D2C01B80580FFFEE3
-:100860008F82005C240F0017ACE200008D39012458
-:10087000ACF900048D780020A4EA0008241901B422
-:10088000A0F8000AA0EF000B952301208D6E000850
-:100890008D6D00049784004C01C35021014D6021EF
-:1008A00001841023A4E2000CA4E5000EA4F90010BA
-:1008B000A4E60012ACE000148D780024240DFFFFA4
-:1008C000ACF800188D0F006CACEF001C8D0E0068AA
-:1008D0003C0F1000ACEE0020ACED0024950A00AEF9
-:1008E000240DFFF73146FFFFACE60028950C0070A1
-:1008F0009504007231837FFF0003CA003082FFFF3E
-:100900000322C021ACF8002CAD2F01B8950E007267
-:100910008D6A002000AE3021014D2824A50600720A
-:1009200003E00008AD6500203C02800034460180F1
-:100930003C0580008CA301B80460FFFE2409001868
-:10094000ACC40000A0C9000B8F8800283C04100034
-:10095000950700AEA4C70010ACC0003003E000084B
-:10096000ACA401B83C028000344501803C04800006
-:100970008C8301B80460FFFE8F8A003424060019BE
-:100980009549001C3128FFFF000839C0ACA70000C2
-:10099000A0A6000B3C05100003E00008AC8501B8E0
-:1009A0008F87003C0080402130C400FF3C0680005F
-:1009B0008CC201B80440FFFE8F89005C938300580D
-:1009C00034996000ACA90000A0A300058CE20010DF
-:1009D000240F00022403FFF7A4A20006A4B9000814
-:1009E0008D180020A0B8000AA0AF000B8CEE00000C
-:1009F000ACAE00108CED0004ACAD00148CEC001C0F
-:100A0000ACAC00248CEB0020ACAB00288CEA002CB2
-:100A10003C071000ACAA002C8D090024ACA90018DA
-:100A2000ACC701B88D05002000A3202403E0000816
-:100A3000AD040020938500582403000127BDFFE882
-:100A400000A330042CA20020AFB00010AFBF0014F0
-:100A500000C01821104000132410FFFE3C070800BE
-:100A60008CE7319000E610243C08800035050180B9
-:100A700014400005240600848F890028240A0004FD
-:100A80002410FFFFA12A00EC0E00187600000000E1
-:100A9000020010218FBF00148FB0001003E0000887
-:100AA00027BD00183C0608008CC631940A0018A81F
-:100AB00000C310248F87003427BDFFE0AFB20018B9
-:100AC000AFB10014AFB00010AFBF001C30D000FFBA
-:100AD00090E6000D00A088210080902130C5007FA5
-:100AE000A0E5000D8F8500288E2300188CA200C081
-:100AF0001062002E240A000E0E00189BA38A0058D4
-:100B00002409FFFF104900222404FFFF52000020A7
-:100B1000000020218E2600003C0C001000CC582440
-:100B2000156000393C0E000800CE682455A0003F37
-:100B3000024020213C18000200D880241200001F2F
-:100B40003C0A00048F8700348CE200148CE3001010
-:100B50008CE500140043F82303E5C82B132000059F
-:100B6000024020218E24002C8CF1001010910031C5
-:100B70000240202124020012A38200580E00189B7C
-:100B80002412FFFF105200022404FFFF0000202166
-:100B90008FBF001C8FB200188FB100148FB00010EF
-:100BA0000080102103E0000827BD002090A800C4A9
-:100BB000350400200A0018D1A0A400C400CA4824AB
-:100BC0001520000B8F8B00348F8D00348DAC0010FE
-:100BD0001580000B024020218E2E002C51C0FFEC0E
-:100BE00000002021024020210A0018EC24020017F6
-:100BF0008D66001050C0FFE6000020210240202139
-:100C00000A0018EC240200110240202124020015E1
-:100C10000E00189BA3820058240FFFFF104FFFDC2B
-:100C20002404FFFF0A0018DB8E2600000A001912B8
-:100C3000240200143C08000400C8382450E0FFD40B
-:100C400000002021024020210A0018EC2402001399
-:100C50008F86002827BDFFE0AFB10014AFBF00189A
-:100C6000AFB0001090C300C430A500FF3062002078
-:100C700010400008008088218CCB00C02409FFDFD1
-:100C8000256A0001ACCA00C090C800C4010938241C
-:100C9000A0C700C414A000403C0C80008F84002832
-:100CA000908700C42418FFBF2406FFEF30E3007FC5
-:100CB000A08300C4979F004C8F8200508F8D002826
-:100CC00003E2C823A799004CA5A000AC91AF00C4D3
-:100CD00001F87024A1AE00C48F8C0028A18000C749
-:100CE0008F8A0028A5400072AD4000DC914500C409
-:100CF00000A65824A14B00C48F9000248F8400507C
-:100D00009786004C0204282110C0000FAF850024F4
-:100D1000A38000483C0780008E2C000894ED012041
-:100D20008E2B0004018D5021014B802102062023CF
-:100D30003086FFFF30C8000F390900013131000152
-:100D400016200009A3880048938600388FBF00183A
-:100D50008FB100148FB0001027BD0020AF85005464
-:100D600003E00008AF86005000C870238FBF001852
-:100D7000938600388FB100148FB0001034EF0C0050
-:100D8000010F282127BD0020ACEE0084AF85005460
-:100D900003E00008AF860050359001800200282152
-:100DA0000E001876240600828F840028908600C4E6
-:100DB00030C5004050A0FFBAA38000588F85003C8A
-:100DC0003C0680008CCD01B805A0FFFE8F89005C39
-:100DD0002408608224070002AE090000A60800086B
-:100DE000A207000B8CA300083C0E1000AE030010FD
-:100DF0008CA2000CAE0200148CBF0014AE1F0018B1
-:100E00008CB90018AE1900248CB80024AE18002844
-:100E10008CAF0028AE0F002CACCE01B80A001936FA
-:100E2000A38000588F8A002827BDFFE0AFB10014CF
-:100E3000AFB000108F880050AFBF00189389002C0E
-:100E4000954200AC30D100FF0109182B00808021B1
-:100E500030AC00FF3047FFFF000058211460000352
-:100E6000310600FF01203021010958239783004CEF
-:100E70000068202B1480001B000000001068004355
-:100E8000240A0001118A004834E708803165FFFF19
-:100E90000E001818020020210E0018588F84005CE4
-:100EA0008F840028948D007025AC0001A48C007004
-:100EB000948B00703C0608008CC6318831677FFF38
-:100EC00010E6004F0000000002002021022028212F
-:100ED0008FBF00188FB100148FB000100A001922C4
-:100EE00027BD0020914400C42406FF800086882589
-:100EF000A15100C49784004C3088FFFF1100001CF2
-:100F00009389002C8F8E00282419EFFF008BF82383
-:100F100095D800AC0168682B33E900FF03197824E9
-:100F2000A5CF00AC51A0002A010058218E05002059
-:100F30002408FFFB2403000100A81024AE020020B7
-:100F40001183002534E78000020020213165FFFF76
-:100F50000E00181801203021978B004C8F8700500D
-:100F6000A780004C00EB8023AF9000509389002CA9
-:100F70008F8C00288FBF00188FB100148FB0001025
-:100F800027BD002003E00008A18900C78E080020CB
-:100F90002409FFFB34E7800001092824AE05002066
-:100FA000158AFFBA34E70880020020210E0017E6F8
-:100FB0003165FFFF02002021022028218FBF001889
-:100FC0008FB100148FB000100A00192227BD002035
-:100FD0000A0019D900004821020020213165FFFFD5
-:100FE0000E0017E601203021978B004C8F870050B0
-:100FF000A780004C00EB80230A0019E9AF90005055
-:1010000094890070240A8000012A4024A48800707A
-:10101000908500709099007030A200FF000219C204
-:101020000003F827001FC1C0332F007F01F870258F
-:10103000A08E00700A0019C1020020218F880028AC
-:1010400024030001910A0078910500C72509007862
-:101050003147003F24E6FFE000C318042CC2002003
-:1010600030670019A385002C1040001AAF89003C9E
-:101070003C0A8000354B00022405000124060001D3
-:1010800014E00016006B1024000028211440000F0B
-:10109000306300201060000F240500018D060074ED
-:1010A0008D1900742403FF8000C3102400027940CE
-:1010B0003338007F01F868253C0E100001AE602532
-:1010C000AD4C083091280001310600010A00199743
-:1010D0000000000003E00008000000008D0F007415
-:1010E0008D0D00742418FF8001F87024000E41401B
-:1010F00031AC007F010C50253C0B1000014B382512
-:101100003C0980000A001997AD27083027BDFFD899
-:10111000AFB000108F90003CAFB40020AFB100140E
-:10112000AFBF0024AFB3001CAFB200188E05001093
-:101130003C0208008C4231B08F86004030A73FFF50
-:1011400000E2182B8CD20014008088218CD3002060
-:10115000106000070000A02190CB000D240AFF8042
-:10116000014B4824312800FF1500000C0005638264
-:10117000022020212411000DA39100588FBF0024CC
-:101180008FB400208FB3001C8FB200188FB10014F1
-:101190008FB000100A00189B27BD0028318500037E
-:1011A00054A0FFF40220202194CF001C8F8E002831
-:1011B0008E070028A5CF00D88CCD0010024D30231B
-:1011C00010E6005C2402001F0E00189BA38200584A
-:1011D000241FFFFF105F004E2404FFFF8F83004495
-:1011E0008F880034026398218D0900100123102399
-:1011F0008F830020AD020010AD1300208C670074B7
-:1012000000F3202B14800062022020218F860040F2
-:101210008E0C00248CC5002411850007022020219B
-:10122000240E001C0E00189BA38E0058240DFFFFF7
-:10123000104D00372404FFFF8F8400348C98002465
-:10124000270F0001AC8F0024127200448F990020F8
-:101250008F320074125300413C0A00808E09000056
-:10126000012A10241440003A000000008E040014EB
-:101270002412FFFF10920006240B001B02202021E5
-:101280000E00189BA38B0058105200212404FFFF6E
-:101290008E0300003C0C0001006C282410A00013F9
-:1012A0003C0600800066A024168000090200282168
-:1012B00002202021240E001A0E00189BA38E005835
-:1012C000240DFFFF104D00122404FFFF020028210F
-:1012D000022020210E0018BB240600012410FFFF6D
-:1012E0002404FFFF1050000A241400018F8F0034E3
-:1012F000022020210280302195F2003424050001D3
-:10130000265800010E001997A5F80034000020218E
-:101310008FBF00248FB400208FB3001C8FB2001841
-:101320008FB100148FB000100080102103E000087E
-:1013300027BD00288F83004400E3C8210259C02B39
-:101340001300FFA88F8800340A001A8024020018B6
-:10135000AC8000200A001AAA8E0400148E1F000020
-:101360003C07008003E798241660FFF92408001A60
-:10137000022020210E00189BA38800582403FFFFA1
-:101380001443FFBA2404FFFF0A001AD38FBF0024BE
-:10139000240B001D0E00189BA38B0058240AFFFF8E
-:1013A000144AFF9A2404FFFF0A001AD38FBF0024B7
-:1013B0008F85002827BDFFD8AFB3001CAFB200183F
-:1013C000AFB10014AFB00010AFBF002090A700C4B1
-:1013D0008F90003C2412FFFF34E200409206000090
-:1013E000A0A200C48E030010008098211072000695
-:1013F00030D1003F2408000D0E00189BA388005830
-:10140000105200252404FFFF8F8A00288E0900183F
-:101410008D4400C01124000702602021240C000E1E
-:101420000E00189BA38C0058240BFFFF104B001AD2
-:101430002404FFFF24040020122400048F8D0028C0
-:1014400091AF00C435EE0020A1AE00C48F850044EA
-:1014500010A00019000000001224004A8F980028F4
-:101460008F92FED0971000709651000A52300048BB
-:101470008F9300303C1F08008FFF318C03E5C82B91
-:101480001720001E02602021000028210E0019975D
-:1014900024060001000020218FBF00208FB3001C14
-:1014A0008FB200188FB100148FB00010008010218F
-:1014B00003E0000827BD00285224002A8E050014EE
-:1014C0008F840028948A007025490001A489007047
-:1014D000948800703C0208008C42318831077FFFFD
-:1014E00010E2000E00000000026020210E00192210
-:1014F000240500010A001B34000020212402002DD5
-:101500000E00189BA38200582403FFFF1443FFE141
-:101510002404FFFF0A001B358FBF00209499007040
-:10152000241F800024050001033FC024A4980070FC
-:1015300090920070908E0070325100FF001181C2B5
-:1015400000107827000F69C031CC007F018D58252D
-:10155000A08B00700E001922026020210A001B34AB
-:10156000000020212406FFFF54A6FFD68F84002808
-:10157000026020210E001922240500010A001B34FC
-:1015800000002021026020210A001B4E2402000AD4
-:101590002404FFFD0A001B34AF9300508F880028FD
-:1015A00027BDFFE8AFB00010AFBF0014910A00C420
-:1015B0008F87003C00808021354900408CE6001078
-:1015C000A10900C43C0208008C4231B030C53FFF85
-:1015D00000A2182B106000078F850040240DFF80AB
-:1015E00090AE000D01AE6024318B00FF1560000845
-:1015F0000006C382020020212403000D8FBF0014C7
-:101600008FB0001027BD00180A00189BA383005854
-:1016100033060003240F000254CFFFF702002021FD
-:1016200094A2001C8F85002824190023A4A200D8AE
-:101630008CE8000000081E02307F003F13F90035DF
-:101640003C0A00838CE800188CA600C01106000834
-:10165000000000002405000E0E00189BA385005812
-:101660002407FFFF104700182404FFFF8F85002880
-:1016700090A900C435240020A0A400C48F8C00349D
-:10168000918E000D31CD007FA18D000D8F83004420
-:101690001060001C020020218F8400408C980010F4
-:1016A0000303782B11E0000D2419001802002021FB
-:1016B000A39900580E00189B2410FFFF1050000241
-:1016C0002404FFFF000020218FBF00148FB0001002
-:1016D0000080102103E0000827BD00188C86001050
-:1016E0008F9F00340200202100C31023AFE20010BE
-:1016F000240500010E001997240600010A001BC0F2
-:10170000000020210E001922240500010A001BC040
-:1017100000002021010A5824156AFFD98F8C00345B
-:10172000A0A600EC0A001BADA386004A27BDFFD887
-:10173000AFB000108F90003CAFB20018AFBF0020D8
-:10174000AFB3001CAFB100148E1100103C030800B1
-:101750008C6331B032253FFF00A3102B10400008EE
-:10176000008090218F8600402409FF8090CA000DE0
-:10177000012A4024310700FF14E0000B00116B82A6
-:10178000024020212412000DA39200588FBF002098
-:101790008FB3001C8FB200188FB100148FB00010EF
-:1017A0000A00189B27BD002831AC0003240B000160
-:1017B000558BFFF40240202190CF000D31EE000840
-:1017C00011C000608F9300441660000924020027B6
-:1017D0008E19000C8CD80020173800052402002038
-:1017E0008E0200088CDF0024105F004024020020DD
-:1017F0000E00189BA38200582406FFFF10460033FA
-:101800002404FFFF8F990034240AFFF73C13800E55
-:101810009329000D2404FF803C0D8000012AF82448
-:10182000A33F000D8F9900203C0808008D0831ACC3
-:101830008F83005C972700788F9F0034010310216D
-:1018400030E57FFF000530400046782131F8007F09
-:101850000313602101E47024ADAE002CA5910000BB
-:101860008FEB0028256A0001AFEA00288FE3002CE7
-:101870008E09002C00694021AFE8002C8E07002C57
-:10188000AFE700308E050014AFE5003497E6003A6C
-:1018900024C20001A7E2003A973300783C10080008
-:1018A0008E1031B02663000130717FFF12300027A7
-:1018B000006030218F8F002002402021240500018C
-:1018C0000E001922A5E60078000020218FBF00201D
-:1018D0008FB3001C8FB200188FB100148FB00010AE
-:1018E0000080102103E0000827BD00288E050014A9
-:1018F0002413FFFF10B3001D8F8300288E080018EB
-:101900008C6700C0150700092402000E8E0A00240F
-:101910008CC9002815490005240200218E070028E3
-:101920008CCB002C10EB00132402001F0E00189B20
-:10193000A38200581453FFB32404FFFF0A001C4283
-:101940008FBF00200A001C0A24020024240E8000FD
-:10195000006E682431ACFFFF000C5BC2317100FFE8
-:10196000001180270A001C3B001033C00A001C59DC
-:10197000240200258E05002C10A0FFEC2402002379
-:101980008F8E00208DCD007401A5602B1580FFE7A0
-:10199000240200268CCF001400A7C02101F8202BC0
-:1019A0001080FF998F990034024020210A001C59B1
-:1019B0002402002227BDFFE0AFB000108F90003C52
-:1019C000AFB10014AFBF00188E0500103C03080033
-:1019D0008C6331B00080882130A43FFF0083102B3E
-:1019E000104000078F8600402409FF8090CA000D38
-:1019F000012A4024310700FF14E000098F8B0044C6
-:101A00002410000D02202021A39000588FBF001841
-:101A10008FB100148FB000100A00189B27BD002062
-:101A2000116000070005CB828F8F00288F8EFED0BB
-:101A300095EC007095CD000A11AC00578F850030F1
-:101A4000333800031700001000000000921F00024E
-:101A500013E00041000000008E06002450C0000F7B
-:101A600092040003022020212402000F0E00189B84
-:101A7000A38200582408FFFF144800072404FFFF36
-:101A80000A001CD58FBF001890C7000D30E3000876
-:101A90001060003702202021920400032409000274
-:101AA000308A00FF15490005308500FF8F8B004408
-:101AB0005160003102202021308500FF38B800102D
-:101AC0002CAF00012F0E000102002821022020214E
-:101AD0000E0018BB01EE30252410FFFF1050000E41
-:101AE0002404FFFF8F830044106000170220202190
-:101AF0003C1F08008FFF318C03E3C82B5720000CDC
-:101B00002411002D02202021000028210E00199709
-:101B100024060001000020218FBF00188FB100149F
-:101B20008FB000100080102103E0000827BD0020C6
-:101B30000E00189BA39100581450FFF62404FFFFD9
-:101B40000A001CD58FBF00180E00192224050001C1
-:101B50000A001CD4000020218CC400248E02002422
-:101B60005444FFC1022020210A001CB59204000346
-:101B70000A001CA924020010240D002C0E00189B42
-:101B8000A38D0058240CFFFF104CFFE32404FFFF3B
-:101B90000A001CBC920400032404FFFD0A001CD4AC
-:101BA000AF85005030A500FF2406000124A90001E4
-:101BB00000C9102B1040000C00004021240A000135
-:101BC00000A61823308B000124C60001006A3804E7
-:101BD000000420421160000200C9182B01074025B3
-:101BE0001460FFF800A6182303E00008010010218C
-:101BF00027BDFFD8AFB000188F90003CAFB1001CDC
-:101C0000AFBF00202403FFFF2411002FAFA300105B
-:101C10009206000024050008261000010066202618
-:101C20000E001CF7308400FF00021E003C021EDC88
-:101C300034466F410A001D1F0000102110A000094A
-:101C4000008018212445000130A2FFFF2C45000828
-:101C50000461FFFA000320400086202614A0FFF94B
-:101C6000008018210E001CF7240500208FA300100F
-:101C70002629FFFF313100FF00034202240700FF45
-:101C80001627FFE20102182600035027AFAA00140E
-:101C9000AFAA00100000302127A8001027A70014C9
-:101CA00000E6782391ED000324CE000100C86021F6
-:101CB00031C600FF2CCB00041560FFF9A18D000098
-:101CC0008FA200108FBF00208FB1001C8FB00018B2
-:101CD00003E0000827BD00289383003827BDFFE0FC
-:101CE00024020034AFB10014AFB00010AFBF001C2D
-:101CF000AFB20018008080211062006500A088212A
-:101D000092240004148000488F880028A380002CAF
-:101D10008E2500048D0700C83C0600FF34C3FFFF7A
-:101D200000A3302400E6102B14400050AF8600447E
-:101D30008F870050978A004CAF87003001474023BF
-:101D400010C00034A788004C8F99002030DF0003BA
-:101D5000001F20239332007C309000030206702184
-:101D60000012C082331200010012788001CF682176
-:101D7000310CFFFF018D582B5160005F8F880028C8
-:101D80008F8900248F8200541049007B3C033F015F
-:101D90008E2600003C11250000C3282414B10078D1
-:101DA0008F84003C8F8A003C8F8800288D4B000078
-:101DB000AD0B00788D470010AD0700888F8700506D
-:101DC0008F860044938C002C01276821020628216D
-:101DD000020C1821A383002C950900ACAF8D0024C0
-:101DE00035301000A51000AC1640005024720004DD
-:101DF000AF850050000020218FBF001C8FB200185B
-:101E00008FB100148FB000100080102103E0000893
-:101E100027BD00208F840024AF8000500087402120
-:101E20000A001D8BAF880024241F000CA39F0058BC
-:101E30000E00189B020020212419FFFF1059FFEE0D
-:101E40002404FFFF8F880028A380002C8E25000427
-:101E50008D0700C83C0600FF34C3FFFF00A33024F9
-:101E600000E6102B1040FFB2AF8600440200202194
-:101E700024090019A38900580E00189B2410FFFFA5
-:101E80001050FFDD2404FFFF0A001D5A8F86004416
-:101E90008F8400288F87003C8CF20030908600C42D
-:101EA00030C5001014A000108F8300502C6800056E
-:101EB0001500002600000000908A00C4246BFFFC7F
-:101EC0003149001015200008316400FF8F8D005447
-:101ED0008F8C002411AC0004388F000131EE00011A
-:101EE00015C0002F000000000E001D0A00000000B9
-:101EF0000A001DE2000000008F890024938C002C52
-:101F00000127682102062821020C1821A383002C36
-:101F1000950900ACAF8D002435301000A51000AC41
-:101F20005240FFB4AF85005024720004A392002CED
-:101F3000950F00AC24B80004AF98005035EE200097
-:101F4000A50E00AC0A001D8C000020218C8200DC54
-:101F50001242FF6B0200202124180005A3980058AC
-:101F60000E00189B2412FFFF1452FF652404FFFF8C
-:101F70000A001D8D8FBF001C0A001DCD8F88002810
-:101F800030E500FF0E0017A2000030218F880028E6
-:101F90008F8700508F8900240A001D7F8F860044A0
-:101FA0000E0017CD000000000A001DE20000000036
-:101FB0009383004A27BDFFE024020002AFB200185D
-:101FC000AFB10014AFBF001CAFB00010008088217B
-:101FD000106200B6000090219783004C8F8500505E
-:101FE0003066FFFF00C5202B1480005B938700380C
-:101FF0003C0880009504012010E500528F8A0024DF
-:102000008F84005430A500FF0E0017A224060001A3
-:102010008F82005C3C0B80003C1F4080244E017886
-:1020200031D00078240FFF80021F60253578090029
-:1020300031D9000701CF6824AD6D08000338802135
-:10204000AD6C081002202021020028210E001D4442
-:10205000AF90003C2403FFFF104300332404FFFF34
-:102060008E0C00103C0708008CE731B0920600008F
-:1020700031843FFF0087282B10A0002330CD003F84
-:102080008F99005C000479803C0408008C8431A89E
-:102090002409FF809390004900994021010F2021DD
-:1020A00000897824000F51403C098000309F007F58
-:1020B0003C0B00808F880028308E00783578000136
-:1020C000015F282530860007352709403C031000B2
-:1020D0003C02800C01D8582500C7C82100A3502518
-:1020E00003E2C021360E0001AD2F0804AF99004075
-:1020F000AD2B0814AF980034AD2F0028AD04007448
-:10210000AD2A0830A38E00499383004A24100003AF
-:102110005070002725A3FFE0240C0001106C001C68
-:1021200024060023024020218FBF001C8FB200181C
-:102130008FB100148FB000100080102103E0000860
-:1021400027BD0020314900035520FFAE8F84005485
-:102150000A001E1F8F9000548F840054306500FFCA
-:102160000E0017A224060001938E003824070034C5
-:1021700011C700188F8500509783004C3078FFFFFF
-:1021800000B87023AF8E00500A001E57A780004C85
-:1021900011A6003200000000022020212411000BB3
-:1021A0000E00189BA39100580A001E570040902172
-:1021B0002C7200201240FFF8000310803C0508013B
-:1021C00024A581600045F8218FED000001A00008E2
-:1021D000000000002CB800051700FFE89783004CB2
-:1021E000978A004C3148FFFF00A848232D2B00059B
-:1021F00011600003314400FF24AFFFFC31E400FF15
-:102200008F9000548F99002412190004389F000108
-:1022100033ED000115A00029000000008F85002883
-:1022200090A700C434E30010A0A300C49783004C1F
-:102230008F8500508F8400283078FFFF00B870230E
-:10224000AC8000DCA780004C0A001E57AF8E005007
-:102250002403FFFF11830005000000000E001B7522
-:10226000022020210A001E57004090210E001AFA79
-:10227000022020210A001E57004090210E001C7BE6
-:10228000022020210A001E57004090210E001BD979
-:10229000022020210A001E57004090210E001A51F2
-:1022A000022020210A001E5700409021938500380B
-:1022B0002404FFFD0A001E58AF8500500E0017CD04
-:1022C000000000009783004C8F85005000402021C3
-:1022D0003066FFFF00A660232D8200051040FFA896
-:1022E0003078FFFF8F91002800B87023AE2400DC07
-:1022F000A780004C0A001E57AF8E005027BDFFD0AC
-:10230000AFB20018AFB00010AFBF0028AFB50024C7
-:10231000AFB40020AFB3001CAFB100143C0C800080
-:102320008D880128240FFF803C07800A25100100BA
-:10233000250B0080020F68243205007F016F702496
-:10234000AD8E009000A72821AD8D002490A700EC51
-:102350003169007F3C0A8004012A1821A387004AC2
-:102360009066007C00809021AF83002030C2000284
-:10237000AF88005CAF85002800A01821144000023F
-:102380002404003424040030A38400388C6600CC7C
-:1023900030F100FF24040004AF8600501224000432
-:1023A000A38000588E5300041660001D3C08800076
-:1023B0009387004930F200011240000F8FBF0028C0
-:1023C0008CB800748CA400742419FF80031988242D
-:1023D00000117140308F007F01CF60253C0D20003F
-:1023E000018D582530F500FE3C0A8000AD4B0830C9
-:1023F000A39500498FBF00288FB500248FB400201B
-:102400008FB3001C8FB200188FB100148FB0001072
-:102410002402000127BD003003E00008ACA600CC78
-:102420008E590008951F01208E460010033FC021E1
-:102430003307FFFF30F5000F32B40001AF860024F0
-:102440001680003BA395004835060C0002A610211B
-:1024500000F51823AD030084AF8200548E490004B8
-:102460003128FFFF1100002BA789004C2410FF80AA
-:102470003C1580003C1420000A001F442413FFFE7A
-:1024800090AE00C4020E682431AC00FF1580002A13
-:1024900002402021938400499786004C308F000130
-:1024A00011E0000B026428248F8900288D2300741A
-:1024B0008D280074A3850049007010240002C940D3
-:1024C000311F007F033FC02503148825AEB10830BB
-:1024D00010C000108F85002890A700C40207582460
-:1024E000316A00FF1540FFE6024020210E001DFA70
-:1024F0009791004C1040FFE8938400492405FFFDAC
-:10250000544500058E430020022028210E00177A32
-:10251000024020218E430020307000041600000A83
-:102520002414FFFB8F8500280A001EFA8F860050B6
-:102530000A001F25AF8600540E001A1D000000007F
-:102540000A001F3493840049007498240E001792E7
-:10255000AE5300208F8500280A001EFA8F86005097
-:1025600027BDFFD8AFB3001CAFB10014AFBF002030
-:10257000AFB20018AFB000103C0280008C52014096
-:102580008C4B01483C048000000B8C02322300FF7E
-:10259000317300FF8C8501B804A0FFFE34900180E8
-:1025A000AE1200008C8701442464FFF02406000270
-:1025B0002C830013AE070004A6110008A206000B2E
-:1025C000AE1300241060004F8FBF0020000448802D
-:1025D0003C0A0801254A81E0012A40218D040000BF
-:1025E00000800008000000003C1008008E1031A898
-:1025F00031733FFF001389800212C8212405FF8038
-:1026000003312021264C0100264700803C1F80001A
-:1026100000E51824318F007F30E9007F308A007F89
-:102620003C18800A3C0E80043C0D800C0085102470
-:1026300001853024014D8021AFE6002401F84021BE
-:10264000AFE30090012E9821AFE20028AF90003454
-:10265000AF880028AF9300200E001867016080212A
-:102660003C0380008C6B01B80560FFFE8F8700344F
-:10267000346501808F86002890E3000DACB2000025
-:10268000A4B00006000316000002FE03001F9027FE
-:10269000001227C21080007A24C2007824196082B8
-:1026A000A4B90008A0A00005241F0002A0BF000BD1
-:1026B00000041C008F8B00203C0227000062902544
-:1026C000ACB20010ACA00014ACA00024ACA0002858
-:1026D000ACA0002C8D7300382410FF80ACB3001820
-:1026E00090E4000D02048824322500FF10A00005AC
-:1026F0008FBF002090EC000D3188007FA0E8000D16
-:102700008FBF00208FB3001C8FB200188FB1001450
-:102710008FB000103C0D10003C0A800027BD00283F
-:1027200003E00008AD4D01B8265F01002405FF80DD
-:1027300033F8007F3C06800003E578243C19800ACA
-:1027400003192021ACCF0024908E00C400AE682471
-:1027500031AC00FF1180FFEAAF840028248E00789E
-:1027600095CD00123C0C08008D8C31A831AB3FFF99
-:1027700001924821000B5180012A402101052024AB
-:10278000ACC400283107007F3C06800C00E6202105
-:102790009083000D00A31024304500FF10A0FFD847
-:1027A000AF8400349098000D330F001015E0FFD572
-:1027B0008FBF00200E001867000000003C0380005F
-:1027C0008C7901B80720FFFE00000000AE12000067
-:1027D0008C720144AE120004A611000824110002FC
-:1027E000A211000BAE1300240A001FCF8FBF0020E0
-:1027F0003C1260008E452C083C03F0033462FFFF5E
-:1028000000A2F824AE5F2C088E582C083C1901B0A9
-:1028100003199825AE532C080A001FCF8FBF002044
-:10282000264D010031AF007F3C10800A240EFF804E
-:1028300001F0282101AE60243C0B8000AD6C002427
-:102840001660FFAFAF85002824110003A0B100EC93
-:102850000A001FCF8FBF002026480100310A007FE9
-:102860003C0B800A2409FF80014B30210109202400
-:102870003C078000ACE400240A001FCEAF8600288D
-:10288000944A001232083FFF314C3FFF1588FF8405
-:102890002419608290CF00C4240EFF8001CF482409
-:1028A000312D00FF11A0FF7E00000000240700046E
-:1028B000A0C700EC8F870034241860842406000D24
-:1028C000A4B80008A0A600050A001FB9241F000232
-:1028D0000800330C0800330C080033E8080033BC50
-:1028E000080033A0080032F0080032F0080032F08F
-:1028F0000800331480080100800800808008000070
-:102900005F865437E4AC62CC50103A453662198584
-:10291000BF14C0E81BC27A1E84F4B556094EA6FE49
-:102920007DDA01E7C04D748108007A8808007AB426
-:1029300008007A94080079D008007A9408007AD4C4
-:1029400008007A94080079D0080079D0080079D07E
-:10295000080079D0080079D0080079D0080079D033
-:10296000080079D0080079D0080079D008007AC42E
-:1029700008007AA4080079D0080079D0080079D03E
-:10298000080079D0080079D0080079D0080079D003
-:10299000080079D0080079D0080079D0080079D0F3
-:1029A000080079D008007AA40800809008007F38D9
-:1029B0000800805808007F380800802808007E2022
-:1029C00008007F3808007F3808007F3808007F380B
-:1029D00008007F3808007F3808007F3808007F38FB
-:1029E00008007F3808007F3808007F3808007F38EB
-:0429F00008007F60FC
-:0C29F4000A0001220000000000000000AA
-:102A00000000000D747061352E302E306A313500B3
-:102A100005000001000000000000000000000000B0
-:102A200000000000000000000000000000000000A6
-:102A30000000000000000000000000000000000096
-:102A40000000000000000000000000000000000086
-:102A50000000000000000000000000000000000076
-:102A60000000000000000000000000000000000066
-:102A70000000000000000000000000000000000056
-:102A800010000003000000000000000D0000000D19
-:102A90003C02080024421C203C03080024631FA0C1
-:102AA000AC4000000043202B1480FFFD24420004B2
-:102AB0003C1D080037BD2FFC03A0F0213C1008008E
-:102AC000261004883C1C0800279C1C200E0002E2F3
-:102AD000000000000000000D2402FF8027BDFFE081
-:102AE00000821024AFB00010AF420020AFBF00182A
-:102AF000AFB10014936500043084007F03441821B3
-:102B00003C0200080062182130A5002003608021EB
-:102B10003C080111277B000814A000022466005C19
-:102B200024660058920200049743010492040004B2
-:102B30003047000F3063FFFF3084004000672823D8
-:102B40001080000900004821920200053042000474
-:102B5000104000050000000010A00003000000006D
-:102B600024A5FFFC24090004920200053042000461
-:102B7000104000120000000010A000100000000033
-:102B80009602000200A72021010440252442FFFEF6
-:102B9000A7421016920300042402FF800043102471
-:102BA000304200FF104000033C0204000A000172A2
-:102BB000010240258CC20000AF4210188F420178FC
-:102BC0000440FFFE2402000AA742014096020002D0
-:102BD000240400093042000700021023304200079D
-:102BE000A7420142960200022442FFFEA74201448E
-:102BF000A740014697420104A74201488F420108BD
-:102C000030420020504000012404000192020004E0
-:102C1000304200101440000234830010008018215C
-:102C2000A743014A0000000000000000000000006F
-:102C300000000000AF48100000000000000000008D
-:102C400000000000000000008F4210000441FFFE61
-:102C50003102FFFF10400007000000009202000454
-:102C60003042004014400003000000008F42101862
-:102C7000ACC20000960200063042FFFF2442000270
-:102C800000021043000210400362882196220000D7
-:102C90001120000D3044FFFF00A710218F83003862
-:102CA0008F45101C0002108200021080004310218A
-:102CB000AC45000030A6FFFF0E0002D100052C023B
-:102CC00000402021A6220000920300042402FF807D
-:102CD00000431024304200FF1040001F000000009D
-:102CE00092020005304200021040001B000000006C
-:102CF0009742100C2442FFFEA7421016000000006D
-:102D00003C02040034420030AF42100000000000DA
-:102D10000000000000000000000000008F421000D2
-:102D20000441FFFE000000009742100C8F45101C6C
-:102D30003042FFFF24420030000210820002108067
-:102D4000005B1021AC45000030A6FFFF0E0002D151
-:102D500000052C02A622000096040002248400082C
-:102D60000E0001E73084FFFF974401040E0001F5D7
-:102D70003084FFFF8FBF00188FB100148FB0001098
-:102D80003C02100027BD002003E00008AF4201789C
-:102D90003084FFFF308200078F850024104000023E
-:102DA000248300073064FFF800A4102130421FFF85
-:102DB00003421821247B4000AF850028AF82002405
-:102DC00003E00008AF4200843084FFFF3082000F30
-:102DD0008F85002C8F860034104000022483000F62
-:102DE0003064FFF000A410210046182BAF8500309E
-:102DF0000046202314600002AF82002CAF84002C18
-:102E00008F82002C340480000342182100641821B2
-:102E1000AF83003803E00008AF4200808F820014C7
-:102E2000104000088F8200048F82FFCC1440000500
-:102E30008F8200043C02FFBF3442FFFF0082202447
-:102E40008F82000430430006240200021062000F4B
-:102E50003C0201012C6200035040000524020004E2
-:102E60001060000F3C0200010A00022E000000006A
-:102E700010620005240200061462000C3C020111DD
-:102E80000A000227008210253C0200110082102552
-:102E9000AF421000240200010A00022EAF82000C93
-:102EA00000821025AF421000AF80000C000000002F
-:102EB000000000000000000003E000080000000027
-:102EC0008F82000C10400004000000008F421000B0
-:102ED0000441FFFE0000000003E0000800000000C5
-:102EE0008F8200102443F800000229C224A2FFF0C0
-:102EF0002C63030110600003000210420A00025517
-:102F0000AC8200008F83001800A3102B1440000B2C
-:102F10000000382100A31023244600018F82001CEA
-:102F2000006210212442FFFF0045102B5440000492
-:102F30002402FFFF0A000255AC8600002402FFFFB6
-:102F40000A00025AAC8200008C8200003C03080098
-:102F500024631C5C000211400043382103E0000898
-:102F600000E010213C0908008D291D80000451401B
-:102F70003C19080027391C5C00C0782100806021C2
-:102F8000240EFFFF00003821015940211120003696
-:102F9000000030213C18080027181D983C0D08003F
-:102FA00025AD1D9C000F582B0006118000461021F6
-:102FB000000218C0007810218C4200001582002009
-:102FC000006D20218CA20000544000098D020018E1
-:102FD0003C0208008C421D8424420001AC820000A7
-:102FE0003C010800AC221D840A0002CF0000202111
-:102FF0008F47002000003021000211C01160004AFC
-:10300000AF4200208D08001C3C0900088CA3000082
-:103010000066182100031880007A10210049102151
-:103020008C44000024C600010068182100CF102B3A
-:103030001440FFF6AC6400000A0002CD000000005E
-:103040008C840000008E102B5040000424C6000128
-:103050000080702100C0382124C6000100C9102B57
-:103060001440FFD20006118024020001ACA200002F
-:103070003C0208008C421D7C3C0308008C631D80D0
-:103080000043102B1440002A2404FFFE0159102194
-:103090008C420018104000262404FFFF0007218006
-:1030A0003C0508008CA51D84008720218D06001892
-:1030B000000420C03C02080024421D980082102118
-:1030C0003C03080024631D9CAC4C000024A50001B7
-:1030D000008318213C02080024421DA0AC650000BA
-:1030E000000631C03C010800AC251D84008220216F
-:1030F0008F470020AD04001CAF46002011E0000AFD
-:10310000000030213C020008034228218CA200006C
-:1031100024C6000100CF182BAC82000024A50004B7
-:103120001460FFFA24840004AF470020000020212F
-:1031300003E00008008010213084FFFF30C6FFFF4D
-:1031400000052C0000A628253882FFFF004510212D
-:103150000045282B0045102100021C023042FFFFD1
-:103160000043102100021C023042FFFF00431021E7
-:103170003842FFFF03E000083042FFFF27BDFFC8D1
-:10318000AFBF0030AFB3002CAFB20028AFB1002406
-:10319000AFB000203C0460088C8250002403FF7F05
-:1031A0003C066000004310243442380CAC825000CE
-:1031B0008CC24C1C3C1A8000000216023042000FE8
-:1031C00010400007AF82001C8CC34C1C3C02001F47
-:1031D0003442FC0000621824000319C2AF830018B7
-:1031E0008F420008275B400034420001AF420008D4
-:1031F000AF8000243C02601CAF400080AF400084E0
-:103200008C4500088CC3080834028000034220214A
-:103210002402FFF0006218243C0200803C010800F8
-:10322000AC2204203C025709AF8400381462000429
-:10323000AF850034240200010A000314AF82001499
-:10324000AF8000142403003D240200043C01080068
-:10325000AC221D943C010800AC231D903C010800E9
-:10326000AC231D8C3C010800AC231D883C130800D6
-:1032700026731C5C240400043C02080024421C74D5
-:10328000240300082463FFFFAC400004AC400000AE
-:103290000461FFFC24420020000410C000441021FF
-:1032A0002442003D3C010800AC221D902402000194
-:1032B0003C010800AC221D7C2402FFFF3C010800F9
-:1032C000AC221D983C010800AC201D848F420000F8
-:1032D00038420001304200011440FFFC8F8200148C
-:1032E0001040001600000000974201041040000545
-:1032F0008F830000146000072462FFFF0A00034B65
-:103300002C62000A2C620010504000048F830000E1
-:1033100024620001AF8200008F8300002C62000A4B
-:10332000144000032C6200070A000352AF80FFCC58
-:103330001040000224020001AF82FFCC8F4301083D
-:103340008F44010030622000AF8300041040000869
-:10335000AF8400103C0208008C42042C244200017F
-:103360003C010800AC22042C0A0006D73C024000B5
-:103370003065020014A0000324020F001482030928
-:1033800024020D0097420104104003713C024000EA
-:1033900030624000144000AD8F8200388C44000839
-:1033A0008F4201780440FFFE24020800AF420178FA
-:1033B00024020008A7420140A740014297420104AD
-:1033C0008F8400043051FFFF30820001104000075D
-:1033D000022080212623FFFE240200023070FFFF1E
-:1033E000A74201460A00037FA7430148A7400146C0
-:1033F0003C0208008C42043C1440000D8F830010F6
-:10340000308200201440000224030009240300013C
-:10341000006020218F830010240209005062000107
-:1034200034840004A744014A0A00039A0000000003
-:1034300024020F00146200053082002014400006B0
-:103440002403000D0A000399240300051440000220
-:103450002403000924030001A743014A3C02080099
-:103460008C4204203C0400480E00020A004420253F
-:103470000E000233000000008F82000C1040003E5E
-:10348000000000008F4210003C0300200043102485
-:10349000104000398F820004304200021040003694
-:1034A0000000000097421014144000330000000098
-:1034B000974210088F8800383042FFFF24420006F0
-:1034C000000218820003388000E8302130430001F8
-:1034D0008CC4000010600004304200030000000DA6
-:1034E0000A0003DB00E81021544000103084FFFF85
-:1034F0003C05FFFF00852024008518260003182BBB
-:103500000004102B004310241040000500000000B0
-:10351000000000000000000D000000002400021C5C
-:103520008CC200000A0003DA004520253883FFFF23
-:103530000003182B0004102B00431024104000053A
-:1035400000000000000000000000000D000000006E
-:10355000240002258CC200003444FFFF00E8102143
-:10356000AC4400003C0208008C42043024420001BC
-:103570003C010800AC2204308F6200008F840038C8
-:10358000AF8200088C8300003402FFFF1462000F3A
-:10359000000010213C0508008CA504543C040800E0
-:1035A0008C84045000B0282100B0302B00822021F0
-:1035B000008620213C010800AC2504543C01080091
-:1035C000AC2404500A0006CD240400088C820000BC
-:1035D000304201001040000F000010213C0508009F
-:1035E0008CA5044C3C0408008C84044800B02821BD
-:1035F00000B0302B00822021008620213C010800F1
-:10360000AC25044C3C010800AC2404480A0006CD5B
-:10361000240400083C0508008CA504443C04080070
-:103620008C84044000B0282100B0302B008220217F
-:10363000008620213C010800AC2504443C01080020
-:10364000AC2404400A0006CD240400088F62000860
-:103650008F62000000021602304300F024020030A6
-:1036600010620005240200401062016B8F8200206E
-:103670000A0006D52442000114A000050000000045
-:10368000000000000000000D0000000024000250B7
-:103690008F4201780440FFFE000000000E00023B54
-:1036A00027A4001014400005004080210000000005
-:1036B0000000000D00000000240002578E020000F0
-:1036C0001040000500000000000000000000000D98
-:1036D000000000002400025A8F62000C0443000323
-:1036E000240200010A00055DAE000000AE020000E9
-:1036F0008F8200388C450008A20000078F65000CFF
-:103700008F64000430A3FFFF0004240200852023FF
-:10371000308200FF0043102124420005000288830C
-:103720002E220081A605000A14400005A204000410
-:10373000000000000000000D0000000024000272E4
-:103740003C0708008CE71D808FA800102409FFFFAC
-:103750000000502110E00013000030213C0C080054
-:10376000258C1D9C01802821000018218CA2FFFCC3
-:103770005102002F006C18218CA400002463020861
-:103780000089102B1040000324A502080080482166
-:1037900000C0502124C6000100C7102B5440FFF484
-:1037A0008CA2FFFC3C0508008CA51D803C02080093
-:1037B0008C421D7C3C09080025291C603C03080044
-:1037C00024631D9800A2102B3C0C0800258C1D9C26
-:1037D0003C0408008C841D843C0B0800256B1DA054
-:1037E0001040001A000831400005118000451021EA
-:1037F000000210C000C9382124840001004B302190
-:103800000043182124A50001004C1021AC680000E1
-:10381000ACE600183C010800AC241D84AC44000058
-:103820003C010800AC251D800A0004A88E04001C81
-:103830003C0208008C421D84244200013C01080027
-:10384000AC221D840A0004A7AC620000000A1180AB
-:10385000004A1021000210C0004328218CA3000060
-:10386000004C3821248400010003194000C9302194
-:1038700000691821004B1021ACA80000AC600018B2
-:103880003C010800AC241D84ACC20018ACE400006C
-:103890008E04001C8F8500380E0006E702203021C0
-:1038A0008F6200048F430108A60200083C0210004A
-:1038B0000062182410600008000000009742010414
-:1038C000920300072442FFEC346300023045FFFFFF
-:1038D0000A0004BCA2030007974201042442FFF03F
-:1038E0003045FFFF960600082CC200135440000527
-:1038F000920300079202000734420001A20200076F
-:103900009203000724020001106200052402000354
-:103910001062000B30C7FFFF0A0004DB24E2000244
-:103920008F8200383C04FFFF8C43000C0064182495
-:1039300000651825AC43000C0A0004DA30C7FFFF0D
-:103940008F8200383C04FFFF8C4300100064182471
-:1039500000651825AC43001030C7FFFF24E20002C9
-:1039600000021083A20200058F830038304200FF5E
-:1039700000021080004330218CC500008CC2000082
-:103980002403000400021702144300130000000087
-:10399000974201043C03FFFF00A318243042FFFFBD
-:1039A000004710232442FFFE00622825ACC500001A
-:1039B000920400058E03001C308200FF000210807C
-:1039C00000431021904200003042000F00441021BB
-:1039D0000A000510A20200068CC4000497420104EC
-:1039E0009603000A3085FFFF3042FFFF0047102397
-:1039F0002442FFD60002140000A22825ACC5000412
-:103A00009202000792040005246300280003188333
-:103A10000064182134420004A2030006A202000739
-:103A20008F8200042403FFFB344200020043102471
-:103A3000AF820004920300068E07001C8F860038B8
-:103A400000031880006710218C44000C3C02FFF634
-:103A50003442FFFF0082282400661821AE04000CC7
-:103A6000AC65000C920300068E04000C3C02FF7F44
-:103A70003442FFFF0003188000A228240082202483
-:103A800000671821AE04000CAC65000C9202000621
-:103A9000000210800047102194450012AC45001030
-:103AA000920200060002108000461021AC45001072
-:103AB0008FA200109203000500021140000318803D
-:103AC00000671821005320218C6200048C830018A9
-:103AD0001460000EAE0200143C0308008C631D8CC1
-:103AE000AC8300183C0208008C421D900062102B31
-:103AF00010400019000000003C0208008C421D9498
-:103B0000006210213C010800AC221D8C8E020018BE
-:103B10008F48002000003021000211C01220000B4D
-:103B2000AF4200203C0200080342282100E020218F
-:103B30008C82000024C6000100D1182BACA200002A
-:103B4000248400041460FFFA24A50004AF48002078
-:103B50000A00055E24020010000000000000000DB5
-:103B600000000000240002D424020010A7420140FB
-:103B700024020002A7400142A7400144A742014697
-:103B8000974201043C0400082442FFFEA74201487A
-:103B9000240200010E00020AA742014A9603000A0D
-:103BA0009202000400431021244200023042000728
-:103BB00000021023304200070E000233AE02001054
-:103BC0008F6200003C0308008C630444240400104E
-:103BD000AF820008974201043042FFFF2442FFFEFB
-:103BE00000403821000237C33C0208008C420440E8
-:103BF000006718210067282B00461021004510217E
-:103C00003C010800AC2304443C010800AC22044001
-:103C10000A0006620000000014A000050000000079
-:103C2000000000000000000D00000000240003045C
-:103C30008F4201780440FFFE000000000E00023BAE
-:103C400027A400141440000500408021000000005B
-:103C50000000000D000000002400030B9206000489
-:103C60008FA4001427A50018000630820E00025C05
-:103C7000AFA00018504000068E02000000000000B7
-:103C80000000000D00000000240003118E0200005F
-:103C90005440000692020007000000000000000DE2
-:103CA00000000000240003169202000730420004C6
-:103CB000104000058F8200042403FFFB3442000201
-:103CC00000431024AF8200048F6200040443000903
-:103CD00092020007920200068E03001C8E04000C64
-:103CE0000002108000431021AC44000CAE00000024
-:103CF00092020007304200045440000B920300047B
-:103D0000920300058E0400148E05001C0003188029
-:103D10003C0200010082202100651821AE0400143D
-:103D2000AC640004920300049602000A00621021B1
-:103D300024420005000290838FA200181040000D5D
-:103D4000277100088FA40014000310820242302360
-:103D500027A500180E00025CAFA200185040000614
-:103D60008E05001C000000000000000D0000000097
-:103D70002400033F8E05001C022020210E0006E7D0
-:103D800002403021920400068F6500043C027FFF50
-:103D900000042080009120218C8300043442FFFF26
-:103DA00000A2282400651821AC83000492020007B9
-:103DB00092030004920500053042000410400014F4
-:103DC0009607000830A500FF0005288000B12821D3
-:103DD0008CA40004974201049606000A306300FF99
-:103DE0003042FFFF004310210046102130E3FFFF67
-:103DF000004310232442FFD83084FFFF0002140048
-:103E000000822025ACA400040A00061692030007D5
-:103E100030A500FF0005288000B128218CA40000F7
-:103E200097420104306300FF3042FFFF004310213E
-:103E3000004710233C03FFFF008320243042FFFF94
-:103E400000822025ACA40000920300072402000198
-:103E5000106200060000000024020003106200113E
-:103E6000000000000A0006398E030010974201048A
-:103E7000920300049605000A8E24000C00431021D2
-:103E8000004510212442FFF23C03FFFF0083202461
-:103E90003042FFFF00822025AE24000C0A000639C4
-:103EA0008E03001097420104920300049605000A55
-:103EB0008E24001000431021004510212442FFEE03
-:103EC0003C03FFFF008320243042FFFF00822025B7
-:103ED000AE2400108E0300102402000AA742014005
-:103EE000A74301429603000A920200043C040040EA
-:103EF00000431021A7420144A74001469742010414
-:103F0000A7420148240200010E00020AA742014A0A
-:103F10000E000233000000008F62000092030004D4
-:103F200000002021AF820008974201049606000A93
-:103F30003042FFFF00621821006028213C03080086
-:103F40008C6304443C0208008C4204400065182144
-:103F5000004410210065382B004710213C01080067
-:103F6000AC2304443C010800AC2204409204000449
-:103F7000008620212484000A3084FFFF0E0001E720
-:103F800000000000974401043084FFFF0E0001F59B
-:103F9000000000003C021000AF4201780A0006D485
-:103FA0008F820020148200273062000697420104AD
-:103FB000104000673C0240003062400010400005A5
-:103FC00000000000000000000000000D00000000E4
-:103FD0002400041A8F4201780440FFFE24020800E6
-:103FE000AF42017824020008A7420140A7400142E5
-:103FF0008F82000497430104304200011040000703
-:104000003070FFFF2603FFFE24020002A742014694
-:10401000A74301480A00068C2402000DA740014670
-:104020002402000DA742014A8F6200002404000808
-:10403000AF8200080E0001E7000000000A000666DB
-:1040400002002021104000423C0240009362000028
-:10405000304300F0240200101062000524020070BA
-:10406000106200358F8200200A0006D5244200012C
-:104070008F620000974301043050FFFF3071FFFF53
-:104080008F4201780440FFFE320200070002102335
-:10409000304200072403000A2604FFFEA743014024
-:1040A000A7420142A7440144A7400146A751014845
-:1040B0008F4201083042002014400002240300090E
-:1040C00024030001A743014A0E00020A3C040040F9
-:1040D0000E000233000000003C0708008CE7044497
-:1040E000021110212442FFFE3C0608008CC6044049
-:1040F0000040182100E33821000010218F650000E6
-:1041000000E3402B00C230212604000800C8302103
-:104110003084FFFFAF8500083C010800AC27044451
-:104120003C010800AC2604400E0001E7000000003E
-:104130000A000666022020210E000139000000005E
-:104140008F82002024420001AF8200203C02400008
-:10415000AF4201380A000336000000003084FFFF40
-:1041600030A5FFFF000018211080000700000000AC
-:104170003082000110400002000420420065182136
-:104180000A0006DD0005284003E000080060102159
-:1041900010C0000624C6FFFF8CA2000024A5000466
-:1041A000AC8200000A0006E72484000403E0000853
-:1041B0000000000010A0000824A3FFFFAC86000050
-:1041C00000000000000000002402FFFF2463FFFF46
-:1041D0001462FFFA2484000403E0000800000000D9
-:0441E00000000001DA
-:0C41E4000A00002A00000000000000009B
-:1041F0000000000D747870352E302E306A31350095
-:10420000050000000000000A000001360000EA601E
-:10421000000000000000000000000000000000009E
-:10422000000000000000000000000000000000008E
-:10423000000000000000000000000000000000007E
-:104240000000000000000016000000000000000058
-:10425000000000000000000000000000000000005E
-:10426000000000000000000000000000000000004E
-:1042700000000000000000000000000000001388A3
-:1042800000000000000005DC00000000000000004D
-:1042900010000003000000000000000D0000000DF1
-:1042A0003C020800244239203C03080024633BD42C
-:1042B000AC4000000043202B1480FFFD244200048A
-:1042C0003C1D080037BD7FFC03A0F0213C10080016
-:1042D000261000A83C1C0800279C39200E0004076B
-:1042E000000000000000000D8F86003C3C039000A1
-:1042F0003C0280000086282500A32025AC44002035
-:104300003C0380008C67002004E0FFFE00000000FA
-:1043100003E00008000000000A000041240400013E
-:104320008F85003C3C0480003483000100A31025ED
-:1043300003E00008AC82002003E000080000102128
-:104340003084FFFF30A5FFFF108000070000182118
-:104350003082000110400002000420420065182154
-:104360001480FFFB0005284003E0000800601021D6
-:1043700010C00007000000008CA2000024C6FFFF50
-:1043800024A50004AC82000014C0FFFB24840004B8
-:1043900003E000080000000010A0000824A3FFFFB5
-:1043A000AC86000000000000000000002402FFFFB7
-:1043B0002463FFFF1462FFFA2484000403E0000872
-:1043C0000000000090AA00318FAB00108CAC0040C0
-:1043D0003C0300FF8D680004AD6C00208CAD0044F0
-:1043E00000E060213462FFFFAD6D00248CA700481F
-:1043F0003C09FF000109C024AD6700288CAE004CC9
-:104400000182C82403197825AD6F0004AD6E002C1D
-:104410008CAD0038314A00FFAD6D001C94A900320C
-:104420003128FFFFAD68001090A70030A5600002A2
-:10443000A1600004A167000090A30032306200FF79
-:104440000002198210600005240500011065000EAD
-:104450000000000003E00008A16A00018CD80028D9
-:10446000354A0080AD7800188CCF0014AD6F001471
-:104470008CCE0030AD6E00088CC4002CA16A000107
-:1044800003E00008AD64000C8CCD001CAD6D00187D
-:104490008CC90014AD6900148CC80024AD680008F4
-:1044A0008CC70020AD67000C8CC200148C83007098
-:1044B0000043C82B13200007000000008CC200142A
-:1044C000144CFFE400000000354A008003E00008BF
-:1044D000A16A00018C8200700A0000B70000000091
-:1044E0009089003027BDFFF88FA8001CA3A9000009
-:1044F0008FA300003C0DFF8035A2FFFF8CAC002C89
-:1045000000625824AFAB0000A100000400C0582195
-:10451000A7A000028D06000400A048210167C82161
-:104520008FA50000008050213C18FF7F032C20261F
-:104530003C0E00FF2C8C0001370FFFFF35CDFFFF35
-:104540003C02FF0000AFC82400EDC02400C2782464
-:10455000000C1DC00323682501F87025AD0D000077
-:10456000AD0E00048D240024AFAD0000AD040008A2
-:104570008D2C00202404FFFFAD0C000C9547003269
-:1045800030E6FFFFAD0600109145004830A200FF65
-:10459000000219C2506000018D240034AD040014E3
-:1045A0008D4700388FAA001827BD0008AD0B0028E2
-:1045B000AD0A0024AD07001CAD00002CAD000018B2
-:1045C00003E00008AD00002027BDFFE0AFB20018F7
-:1045D000AFB10014AFB00010AFBF001C9098003016
-:1045E00000C088213C0D00FF330F007FA0CF0000EA
-:1045F000908E003135ACFFFF3C0AFF00A0CE0001D9
-:1046000094A6001EA22000048CAB00148E29000486
-:1046100000A08021016C2824012A402400809021E0
-:1046200001052025A6260002AE2400042605002050
-:10463000262400080E000063240600029247003082
-:10464000260500282624001400071E000003160378
-:1046500024060004044000032403FFFF965900329F
-:104660003323FFFF0E000063AE2300102624002436
-:104670008FBF001C8FB200188FB100148FB00010D4
-:1046800024050003000030210A00006D27BD002032
-:1046900027BDFFD8AFB1001CAFB00018AFBF0020DE
-:1046A00090A900302402000100E050213123003F96
-:1046B00000A040218FB000400080882100C0482128
-:1046C000106200148FA70038240B000500A02021E1
-:1046D00000C02821106B0013020030210E0000F9E9
-:1046E000000000009225007C30A40002108000032E
-:1046F00026030030AE000030260300348FBF0020B8
-:104700008FB1001C8FB000180060102103E000087A
-:1047100027BD00280E000078AFB000100A0001404D
-:10472000000000008FA3003C01002021012028216F
-:1047300001403021AFA300100E0000BFAFB0001445
-:104740000A000140000000003C0580008CA30E1010
-:104750008F840044AC8300208CA20E1803E0000874
-:10476000AC8200243C0580008CA30E148F8400448E
-:10477000AC8300208CA20E1C03E00008AC82002455
-:104780009382000C1040001B2483000F2404FFF0D0
-:104790000064382410E00019978B00109784000EF5
-:1047A0009389000D3C0A601C0A00017B01644023D0
-:1047B00001037021006428231126000231C2FFFF8B
-:1047C00030A2FFFF0047302B50C0000E00E448210C
-:1047D0008D4D000C31A3FFFF00036400000C2C037F
-:1047E00004A1FFF30000302130637FFF0A00017352
-:1047F0002406000103E00008000000009784000E7A
-:1048000000E448213123FFFF3168FFFF0068382BA7
-:1048100054E0FFF8A783000E938A000D11400005B5
-:10482000240F0001006BC023A380000D03E00008EB
-:10483000A798000E006BC023A38F000D03E00008B3
-:10484000A798000E03E000080000000027BDFFE865
-:10485000AFB000103084FFFF3C10800093A8002B05
-:10486000AFBF0014A6040144960A0E1630C600FF1E
-:104870008FA90030A60A0146AE050148A2060152E2
-:10488000A608015AAE0701608FA3002CA6090158A3
-:10489000012020210E000167AE0301543C021000EC
-:1048A000AE0201788FBF00148FB0001003E0000843
-:1048B00027BD00188F8500002484000727BDFFF85E
-:1048C0003084FFF83C06800094CB008A316AFFFFF9
-:1048D000AFAA00008FA90000012540232507FFFF94
-:1048E00030E31FFF0064102B1440FFF700056882BF
-:1048F000000D288034CC400000AC102103E00008FB
-:1049000027BD00088F8200002486000730C5FFF80D
-:1049100000A2182130641FFF03E00008AF840000EC
-:104920008F8500448F8A003C27BDFFB03C04800087
-:10493000AFB70044AFB40038AFB1002CAFBF0048F0
-:10494000AFB60040AFB5003CAFB30034AFB20030FB
-:10495000AFB000288C8701048CA90024AC8A0080A9
-:104960008CA8002000E988230000B821AC880E1034
-:104970008CA600240000A021AC860E188C820E109C
-:10498000AC820E148C830E18AC830E1C122000FB1C
-:104990003C168000936B0008116000F100000000DD
-:1049A000976E001031CDFFFF022D602B158000ECBB
-:1049B0000000000097700010320FFFFFAECF0E0016
-:1049C0003C0580008CB30000327200081240FFFDED
-:1049D0000000000094B50E088CA70E0432A5FFFF5E
-:1049E00030B40001128000E1000000000000000D62
-:1049F00030B9A040241800401338011730B4A0008B
-:104A0000128000DC000000009373000812600008B0
-:104A100000000000976900103122FFFF00E2202B08
-:104A20001080000330A6004010C000D2000000003B
-:104A3000A7850040AF870038936A0008022038211C
-:104A4000AFB10020154000F127B40020AF60000C8A
-:104A50009785004030B14000162000022403001664
-:104A60002403000E24154007A363000AAF75001449
-:104A7000939000428F6F0014321900010019C24058
-:104A800001F84025AF680014978700408F63001439
-:104A900030EE0010006E6825AF6D0014978C00405A
-:104AA000318B000811600165000000008F65001463
-:104AB0003C0B10003C0A800000AB8825AF7100144D
-:104AC00095460E0A3C0981002413000E30C2FFFFF8
-:104AD00000492025AF640004A3730002937F000AFD
-:104AE0003406FFFC27F20004A372000A978D0040F1
-:104AF00031AC200011800157000000003C0780000D
-:104B0000978D004094EC0E0C97910040000D584298
-:104B10003185C000316A00030005130332291000FB
-:104B200001429825000922030264F825001F90C065
-:104B3000A7720012979500409379000A00158182B0
-:104B40003218003C0319782125E8003CA3680009CD
-:104B500094EE0E0C31C33FFFA76300109763001261
-:104B60009367000900E3702125CD000231AC0007F6
-:104B7000000C582331650007A365000B93710009F1
-:104B800097640012976A0010322200FF8F9100385C
-:104B9000979F004000444821012A982102669021F5
-:104BA00033F5004012A000053246FFFF00D1402B34
-:104BB0003C12800011000016000098210226782B7C
-:104BC00015E001368FA700203C1880008F100E14CE
-:104BD0003C058000AF100E108F190E1CAF190E1877
-:104BE000AF060E008CB200003255000812A0FFFD87
-:104BF0000000000094BF0E0800C088210000902132
-:104C0000A79F00408CA60E0424130001AF86003835
-:104C1000976900103135FFFF8E8C00000191202331
-:104C200010800118AE8400009367000814E000D8DB
-:104C3000000000000E0001B4240400108F8E004814
-:104C40003C0332000040282131C600FF00063C0032
-:104C500000E3602525CD0001AF8D0048AC4C00007D
-:104C60009362000997640012937F000A304A00FFA4
-:104C7000308BFFFF014B48210009CC0033F000FFCF
-:104C80000330C025ACB800048F8F004897880040DF
-:104C90003103200010600103ACAF0008976F0012D1
-:104CA00031E8FFFF06400101ACA8000C97900040DE
-:104CB0003205000814A0000226280006262800025B
-:104CC0003C048000948B0E148C850E1C8F670004AE
-:104CD000936A00023164FFFF314900FFAFA9001061
-:104CE0008F7F0014AFA80018AFBF00140E00019A08
-:104CF00000000000240400100E0001C800000000A5
-:104D00008E92000016400005000000008F7900140C
-:104D10002405FFBF0325A024AF7400148F69000C85
-:104D20000135F821AF7F000C9375000816A000082C
-:104D30000000000012600006000000008F6B0014ED
-:104D40003C0CEFFF3584FFFE01645024AF6A001471
-:104D5000A37300088FA700200A0003160220202159
-:104D6000AED10E000A0001F83C05800014E0FF21DE
-:104D700030B9A0400E0001600000A0212E9100017A
-:104D80000237B02512C000178FBF00488F85003C46
-:104D900024170F0010B700CD3C0480008C990178D7
-:104DA0000720FFFE24150F0050B500EB3C048000E7
-:104DB0008C890E14240502403C141000AC89014477
-:104DC0008C9F0E1CAC9F0148A0800152A480015A08
-:104DD000AC800160A4800158AC850154AC9401788A
-:104DE0008FBF00488FB700448FB600408FB5003C9E
-:104DF0008FB400388FB300348FB200308FB1002CE5
-:104E00008FB0002803E0000827BD00508F910038C4
-:104E1000979300403C1280000220A821326A004093
-:104E20001540FF7D00009821976B00108F8500389A
-:104E30003162FFFF104500A2000020210080A02168
-:104E4000108000E500E088211620FED2000000005E
-:104E50000A0002E72E9100013C0380008C7F01785C
-:104E600007E0FFFE240408008F860000AC64017890
-:104E70003C038000946C008A318BFFFF0166502355
-:104E80002549FFFF31281FFF2D0200081440FFF9BC
-:104E9000000000008F8E0048346F40008F83003C7C
-:104EA00000E0A021240D0F0025C70001AF870048B6
-:104EB00000CF3021023488233C08800031D500FF28
-:104EC000106D000524070001939300423272000127
-:104ED0000012824036070001001514003C09010051
-:104EE00000492025ACC400008F9F004830B900362F
-:104EF00030B80008ACDF00041300009000F99825DA
-:104F000095070E0A8F8E00003C03810030EDFFFFF5
-:104F100025CB000801A328253C0C1000316A1FFF97
-:104F2000269200062406000EAD050160026C98254D
-:104F3000A506015AAF8A0000A512015816200008E4
-:104F40003C1080008F99003C24180F005338000259
-:104F500024170001367300400E0001593C108000F8
-:104F60008E1F0E1402402021AE1F01448E120E1C13
-:104F7000AE120148A2150152AE1301540E00016792
-:104F80003C151000AE1501780A000319000000005E
-:104F900093780009976300129368000B330F00FFAA
-:104FA00001E33821310200FF00E2702125D0000A20
-:104FB0003210FFFF0E0001B4020020218F8600484E
-:104FC0003C1941003C07800024CD0001AF8D004812
-:104FD000936C00099764001230C600FF318A00FF0D
-:104FE000308BFFFF014B482100062C00253F0002BB
-:104FF00000BFC02503197825AC4F00008F68000C56
-:1050000094EE0E1401121825AC4300048CE50E1C1E
-:105010008F670004936D000231C4FFFF31AC00FFC5
-:10502000AFAC00108F620014AFB100180E00019AEF
-:10503000AFA200140A0002C502002021AF600004E4
-:10504000A3600002978D004031AC20001580FEABBC
-:1050500000003021A7600012979000409378000A6A
-:105060003C03800032191F000019798301F84021A8
-:1050700025070028A3670009946E0E0C0A00025E43
-:10508000A76E00108F6E001435CD00400E00015940
-:10509000AF6D00140A000291000000000A00031620
-:1050A000000020210641FF01ACA0000C8CB8000CD0
-:1050B0003C198000031990250A0002B2ACB2000C22
-:1050C000000090210A00028D2413000112800005C7
-:1050D0003C0D800095A60E0830D3004012600042BF
-:1050E000000000008C9001780600FFFE0000000028
-:1050F00094920E103C030500240720003258FFFF55
-:1051000003037825AC8F014C8C880E143C0E1000E4
-:10511000AC8801448C820E1CAC820148A0800152F4
-:10512000A480015AAC800160A4800158AC8701546E
-:10513000AC8E01780A0002EE3C0480008F900000E3
-:1051400026920002A5120158260F000831E81FFF21
-:105150000A000356AF880000AC80014C1280001991
-:10516000000000008C8A0E10AC8A01448C830E185B
-:105170003C0C800024160040AC8301488FBF0048DF
-:10518000A18001528FB70044A580015A8FB5003C21
-:10519000AD8001608FB40038A58001588FB3003412
-:1051A000AD9601548FB200308FB600408FB1002C05
-:1051B0008FB000283C04100027BD005003E0000819
-:1051C000AD8401788C8B0E14AC8B01448C830E1C47
-:1051D0000A0003E43C0C80000E0001602E910001E7
-:1051E0000A0002E80237B025000000000000000DB0
-:1051F000000000002400033A0A0003C03C048000C1
-:1052000027BDFFE0AFBF001C3C1F20FF3C07600034
-:105210003C0980002402001037F9FFFDACE23008A1
-:10522000AFB20018AFB10014AFB00010AD390E002E
-:10523000000000000000000000000000000000006E
-:10524000000000003C1800FF3712FFFDAD320E00D9
-:105250003C0B60048D7050002411FF7F3C0E000257
-:105260000211782435EC380C35CD0109ACED4C1821
-:10527000240A0009AD6C50008CE80438AD2A0008FF
-:10528000AD2000148CE54C1C3106FFFF38C42F7193
-:1052900000051E023062000F2486C0B310400007D4
-:1052A000AF8200088CE54C1C3C09001F3528FC002F
-:1052B00000A81824000321C2AF8400048CF1080860
-:1052C0003C0F57092412F0000232702435F0001010
-:1052D00001D0602601CF68262DAA00012D8B000188
-:1052E000014B382550E00009A380000C3C02601CF3
-:1052F0008C590008241F0001A39F000C33387C0048
-:10530000A7980010A780000EA380000DAF80004872
-:1053100014C00003AF8000003C066000ACC0442C09
-:105320000E0004B63C1080000E000E0E00000000BF
-:105330003C110800263139883C12080026523A08F0
-:105340008E05000038A30001306400011480FFFCCA
-:10535000000000008E0601003C0C800A240AFF8039
-:1053600024C7024030EB007F016C482100EA402452
-:10537000AE060020AF890044AE0800243C03800044
-:10538000AF86003C8C6D017805A0FFFE2419080053
-:10539000AC79017890780108A3980042938F00427D
-:1053A00031EE000111C0000F240D0D0024C2F800E1
-:1053B0002C5F030113E0001C000629C224A3FFF0A8
-:1053C00000032042000431400E0001CF00D1D8215B
-:1053D0003C0440003C068000ACC401380A0004577D
-:1053E0000000000010CD0026240E0F0010CE002A71
-:1053F0003C028008345F008093F90000240F0050C5
-:10540000333800FF170FFFF33C0440000E00092F54
-:10541000000000003C0440003C068000ACC40138A1
-:105420000A000457000000008F83000400A3402BF3
-:105430001500000B8F8B0008006B50212547FFFFE4
-:1054400000E5482B1520000600A36023000C29402E
-:105450000E0001CF00B2D8210A00047C3C044000B9
-:10546000000000000000000D00000000240003AD5B
-:105470000E0001CF000000000A00047C3C04400044
-:105480003C1B0800277B3B080E0001CF00000000FA
-:105490000A00047C3C0440003C1B0800277B3B289E
-:1054A0000E0001CF000000000A00047C3C04400014
-:1054B000000411C003E00008244202403C0408003C
-:1054C00024843B6C2405001A0A00006D0000302182
-:1054D00027BDFFE0AFBF001CAFB20018AFB1001492
-:1054E000AFB000103C108000920B01092412FF8025
-:1054F0000E0004B33164007F8F91003C00515021B5
-:1055000001524024AE080024920301090E0004B3A6
-:105510003064007F24060080240700C0240400407B
-:10552000AE000810AE040814AE060818AE07081C3A
-:10553000920C01090051F82133F8007F3C19800AD0
-:10554000031910213184007F0E0004B3AF820044A0
-:105550008E1101003C0C008035850001022278216B
-:1055600001F24824AE0908048E0E010035980002AD
-:105570003609090001C2682131AB00780165502568
-:10558000AE0A08208E0501008E080100360509804C
-:10559000010218212464004000923024AE0608085D
-:1055A0008E07010000E2F82127F90040333200782D
-:1055B00002588825AE1108248E040100952F000C96
-:1055C0008FBF001C8FB2001831EEFFFF000E69C0C4
-:1055D000AE0D0800AE0C0828952B000C8FB10014FE
-:1055E000316AFFFF000A41C0AE08002C8CA30050B6
-:1055F0008FB000108CA2003C8D2400048CA6001CEF
-:105600008CA7003827BD0020AF830060AF82005018
-:10561000AF84004CAF86005803E00008AF87005C01
-:105620003C098000352309009128010B906A001184
-:105630002402002800804821314700FF00A070218B
-:1056400000C068213108004010E20002340C86DD01
-:10565000240C08003C0A800035420A9A9447000056
-:10566000354B0A9C35460AA030F9FFFFAD390000E2
-:105670008D780000354B0A8024040001AD38000409
-:105680008CCF0000AD2F00089165001930A30003F6
-:105690001064008E28640002148000AD240500020E
-:1056A0001065009C240F0003106F00B235450AA45A
-:1056B000240A0800118A0047000000005100003C45
-:1056C0003C0B80003C04800034830900906700128A
-:1056D00030E200FF004D7821000FC8802724000130
-:1056E0003C0A8000354F090091E50019354C0980CE
-:1056F0008D87002830A300FF0003150000475825C0
-:105700000004C4003C19600001793025370806FF09
-:10571000AD260000AD2800048DEA002C25280028C5
-:10572000AD2A00088DEC0030AD2C000C8DE5003466
-:10573000AD2500108DE40038AD2400148DE3001C6D
-:10574000AD2300188DE700203C038000AD27001C2E
-:105750008DE20024AD2200208DF900283462093C3E
-:10576000AD3900248C450000AD0E000434790900E9
-:10577000AD0500008C67010C25020014AD07000880
-:10578000932B00123C04080090843B90AD00001065
-:10579000317800FF030D302100064F0000047C002B
-:1057A000012F702535CDFFFF03E00008AD0D000C83
-:1057B00035780900930600123C05080094A53B804B
-:1057C00030C800FF010D5021000A60800A00053F2B
-:1057D000018520211500005A000000003C08080047
-:1057E00095083B863C06080094C63B8001061021C4
-:1057F0003C0B80003579090093380011932A001979
-:1058000035660A80330800FF94CF002A00086082C2
-:10581000314500FF978A0054000C1E00000524004B
-:105820003047FFFF006410250047C02501EA302102
-:105830003C0B4000030B402500066400AD2800002F
-:10584000AD2C0004932500183C0300062528001405
-:1058500000053E0000E31025AD2200088F24002C37
-:105860003C0380003462093CAD24000C8F38001CDE
-:10587000254F000131EB7FFFAD3800108C45000053
-:10588000AD0E000434790900AD0500008C67010CF1
-:10589000A78B005425020014AD070008932B0012BB
-:1058A0003C04080090843B90AD000010317800FF6C
-:1058B000030D302100064F0000047C00012F7025ED
-:1058C00035CDFFFF03E00008AD0D000C3C020800E1
-:1058D00094423B8A3C05080094A53B8035440AA4C9
-:1058E0003C07080094E73B7C948B00000045C821EE
-:1058F0000327C023000B1C002706FFF2006650257B
-:10590000AD2A000CAD200010AD2C00140A000533A8
-:1059100025290018354F0AA495E500009564002854
-:105920000005140000043C003459810000EC5825A7
-:10593000AD39000CAD2B00100A00053325290014E9
-:105940003C0C0800958C3B860A00058325820001EB
-:105950005460FF58240A080035580AA4970600002E
-:1059600000061C00006C5025AD2A000C0A0005330F
-:10597000252900103C03080094633B8A3C0708007B
-:1059800094E73B803C0F080095EF3B7C94A400001B
-:105990009579002800671021004F582300041C004F
-:1059A000001934002578FFEE00D87825346A81008C
-:1059B000AD2A000CAD2F0010AD200014AD2C001846
-:1059C0000A0005332529001C03E00008240207D043
-:1059D00027BDFFE0AFB20018AFB10014AFB00010A8
-:1059E000AFBF001C0E00004D008088218F88005042
-:1059F0008F87004C3C05800834B2008001112821BB
-:105A00003C10800024020080240300C000A7202353
-:105A1000AE0208183C068008AE03081C188000047B
-:105A2000AF850050ACC500048CC90004AF89004CA0
-:105A300012200009360409800E0005F9000000005C
-:105A4000924C00278E0B007401825004014B3021D0
-:105A5000AE46000C360409808C8E001C8F8F0058D7
-:105A600001CF682319A000048FBF001C8C90001C7C
-:105A7000AF9000588FBF001C8FB200188FB1001478
-:105A80008FB000100A00004F27BD00208F860060F5
-:105A90008F8300508F82004C3C05800834A4008026
-:105AA000AC860050AC83003C03E00008ACA20004CC
-:105AB0003C0308008C63005427BDFFF8308400FFCE
-:105AC0002462000130A500FF3C010800AC22005414
-:105AD00030C600FF3C0780008CE801780500FFFE1F
-:105AE0003C0A7FFFA3A400038FA400003549FFFFF9
-:105AF00000891824000647C000681025AFA20000E6
-:105B000090F9010AA3A000023C1880FFA3B900018C
-:105B10008FAE000030AD007F370FFFFF01CF58245C
-:105B2000000D66003C090020016C50253526200040
-:105B30002405FF803C04100027BD0008ACEA014C9E
-:105B4000ACE60154A4E00158A0E5015203E00008CE
-:105B5000ACE40178308800FF3C03800030A400FFF3
-:105B60008C6201780440FFFE000000003C038000CE
-:105B700034660A008CCA0020346709800004482B70
-:105B8000AC6A01448CC5002400091540AC6501488D
-:105B9000A068015090E4004CA064016D03E000088F
-:105BA000A460015827BDFFE8308400FFAFBF00109C
-:105BB0000E00065C30A500FF8F8300508FBF0010E1
-:105BC0003C058000344600402404FF903C02100055
-:105BD00027BD0018ACA3014CA0A40152ACA60154EF
-:105BE00003E00008ACA2017827BDFFE03C08800874
-:105BF000AFBF001CAFB20018AFB10014AFB00010BF
-:105C0000351000808E0600183C078000309200FF9F
-:105C100000C72025AE0400180E00004D30B100FF73
-:105C200092030005346200080E00004FA202000536
-:105C3000024020210E00067002202821024020216F
-:105C40008FBF001C8FB200188FB100148FB00010EE
-:105C500024050005240600010A00063327BD0020A4
-:105C60003C05800034A309809066000830C200081B
-:105C70001040000F3C0A01013549080AAC890000B8
-:105C80008CA80074AC8800043C07080090E73B90A7
-:105C900030E5001050A00008AC8000083C0D8008E2
-:105CA00035AC00808D8B0058AC8B00082484000C30
-:105CB00003E00008008010210A0006B32484000CD1
-:105CC00027BDFFE83C088000AFB00010AFBF001454
-:105CD0003506098090C7000924020006350909002D
-:105CE00030E300FF0080802100A06021240B00042D
-:105CF000106200792407000294CF005C3C0E02047D
-:105D000031EDFFFF01AE5025AE0A000090C500083E
-:105D100030A40020108000080000000090C2004E57
-:105D20003C1F010337F90300305800FF03193025E9
-:105D3000240B0008AE0600049139001191260012D0
-:105D400091240011333800FF0018708230CF00FF1B
-:105D500001CF5021014C6821308800FF31AAFFFF9C
-:105D600039030028000A28801460002B0205402314
-:105D7000912400123C0E800035D90980308500FF47
-:105D800000AC182100031080004BF821001F840094
-:105D9000360906FFAD09000435C909009126001136
-:105DA000912F0012000BC0828F2B003431ED00FFC9
-:105DB0008DC4010C01AC282100B810210164F82326
-:105DC0000007840000021F000070C82533E9FFFFB0
-:105DD00030CF00FC032970250158202101E86821FB
-:105DE00000045080ADAE000C0E00004D010A802171
-:105DF0003C078008240C000434EB00800E00004FA8
-:105E0000A16C0009020010218FBF00148FB0001098
-:105E100003E0000827BD0018912500119123001907
-:105E20003C18080097183B8630A200FF0002F88259
-:105E3000307000FF001FCE0000104C0003293025F9
-:105E400000D870253C0F400001CF68253C0E800033
-:105E5000AD0D000035C9090091260011912F0012E7
-:105E600035D90980000BC08231ED00FF8F2B003443
-:105E70008DC4010C01AC282100B810210164F82365
-:105E80000007840000021F000070C82533E9FFFFEF
-:105E900030CF00FC032970250158202101E868213A
-:105EA00000045080ADAE000C0E00004D010A8021B0
-:105EB0003C078008240C000434EB00800E00004FE7
-:105EC000A16C0009020010218FBF00148FB00010D8
-:105ED00003E0000827BD00180A0006C524070012C9
-:105EE00027BDFFD0AFB60028AFB50024AFB4002067
-:105EF000AFB10014AFBF002CAFB3001CAFB200189D
-:105F0000AFB000103C06800090C3010B309400FF3E
-:105F100030B500FF306200300000B0211040009D1D
-:105F20000000882134C409809088000800083E00E1
-:105F300000072E0304A000C4240400048F8700502F
-:105F40003C010800A0243B903C0C8000AD80004840
-:105F50003C038000906D010B31A5002010A00007CC
-:105F60003C0B8000347209809250000800107E00C3
-:105F7000000F760305C000C93C1980089169010B28
-:105F8000356A098091480008312400400004102B34
-:105F900031030008241200031460000200E2982379
-:105FA000000090213C108000360E0A80360809005F
-:105FB00095C7002C910300119102001291C50018A1
-:105FC000307800FF305F00FF025FC8210019788041
-:105FD00091CC001801F8682101B1302130B100FFE7
-:105FE00000D11821A78700543C010800A4263B8655
-:105FF0003C010800A4233B8815800002000000003B
-:106000000000000D9204010B3065FFFF3C01080009
-:10601000A4233B8A308900403C010800A4203B8037
-:106020003C010800A4203B7C1120000224A4000AAB
-:1060300024A4000B3091FFFF0E0001B402202021A8
-:106040009219010B3C0E080095CE3B8A3C0D0800CE
-:1060500091AD3B910019C182330F000101CF28217E
-:10606000000D340024A7000200C758253C0C110085
-:10607000016C5025AC4A000024440008026028212D
-:10608000024030210E00050FAC4000040E00069FB8
-:106090000040202116C00068004020219212010B10
-:1060A0003256004012C000053C0200FF8C930000F5
-:1060B000345FFFFF027F8024AC9000000E0001C817
-:1060C000022020213C03080090633B9030710003C4
-:1060D000122000163C1080088F8C00503C0B80086A
-:1060E00035640080258A0001AC8A003C3C058008AC
-:1060F0008CA9000401402021012A4023190000023C
-:10610000AF8A00508CA400040E0005F9ACA4000472
-:106110003C0E80008DCD00743C05800834A60080C4
-:10612000004D3821ACC7000C3C10800836120080AE
-:106130000280202102A02821A240006B0E00065CF4
-:106140003C1480008F9600503C151000AE96014C18
-:106150008F980048344F00068FBF002C271900018C
-:10616000AF9900488FB60028A29801528FB3001C47
-:10617000AE8F01548FB20018AE9501788FB1001424
-:106180008FB500248FB400208FB0001003E000080A
-:1061900027BD003034C30980906F0008000F7600DF
-:1061A000000E6E0305A0003334DF090093F8001BD6
-:1061B000241900103C010800A0393B903313000261
-:1061C0001260FF638F8700508F82005C1447FF616D
-:1061D0003C0380000E00004D000000003C048008DD
-:1061E0003485008090A8000924070016310300FFC1
-:1061F0001067000D0000000090AB00093C0608008D
-:1062000090C63B9024090008316400FF34CA0001A5
-:106210003C010800A02A3B901089002F240C000AA2
-:10622000108C00282402000C0E00004F000000001B
-:106230000A00075B8F8700500E0006B70240282136
-:106240000A0007AE004020213C0B8008356A008020
-:106250008D4700548CC9010C1120FF39AF870050C5
-:10626000240600143C010800A0263B900A00075AAF
-:106270003C0C800090710008241200023C010800D0
-:10628000A0323B90323000201200000B2416000197
-:106290008F8700500A00075B241100083733008005
-:1062A0008E7F0038AF3F00048F380004AE78003C8A
-:1062B0000A0007663C0B80008F8700500A00075BCE
-:1062C00024110004A0A200090E00004F00000000ED
-:1062D0000A00075B8F870050240200140A00083967
-:1062E000A0A2000927BDFFE8AFBF0014AFB00010A7
-:1062F0003C10800092020109240500010E00065C9A
-:10630000304400FF3C1F800893F8000E37E3008004
-:1063100093F9000F906E002693E9000A332F00FFD7
-:1063200000186600000F6C0031CB00FF018D502576
-:10633000000B320001463825312800FF344560004B
-:1063400000E820252402FF813C031000AE04014C2C
-:106350008FBF0014AE050154A2020152AE030178B2
-:106360008FB0001003E0000827BD001827BDFFE82C
-:10637000308400FFAFBF00100E00065C30A500FFA8
-:10638000344600403C0480002405FF92AC86015452
-:10639000A08501528F8300508FBF00103C02100077
-:1063A00027BD0018AC83014C03E00008AC820178E3
-:1063B00027BDFFD8AFB20018AFB10014AFB00010C6
-:1063C000AFBF0020AFB3001C3C07800090E2010982
-:1063D000308600FF30B000FF000618C23204000211
-:1063E0003071000114800007305200FF3C09800822
-:1063F00035330080926800053105000810A0000CBC
-:1064000030CA0010024020210E00068102202821FF
-:10641000240200018FBF00208FB3001C8FB2001830
-:106420008FB100148FB0001003E0000827BD0028D2
-:106430001540003034E50A008CB900248CB80008FF
-:1064400013380047000040213C0E800835D30080FF
-:10645000926D0068240B000231AC00FF118B0080AC
-:106460003C068000927F004C90C40109509F0004BC
-:106470003213007C11000067000000003213007C22
-:106480001660005A0240202116200008320C00013C
-:106490003C07800034EB0A008D6500248CE8010481
-:1064A00014A8FFDC00001021320C00011180000D47
-:1064B000024020213C1080008E0E010C8F8D006068
-:1064C00011CD0008000000000E00073F0220282127
-:1064D0008E0F010C3C18800837100080AE0F005062
-:1064E000024020210E000670022028210A00088C9C
-:1064F000240200013C0708008CE7006424E6000148
-:106500003C010800AC2600641600000D00000000ED
-:10651000022028210E00067002402021926F0068A0
-:10652000240D000231EE00FF11CD00220240202197
-:106530000E000840000000000A00088C2402000140
-:106540000E00004124040001926C0025020C582525
-:106550000E00004FA26B00250A0008CC0220282163
-:106560008E6300188CE401048CBF00240003160223
-:10657000149FFFB53045007F9269004C264400010E
-:106580003093007F12650040312300FF1464FFAF99
-:106590003C0E8008264800013111007F310200FFC7
-:1065A0001225000B24080001004090210A000899E0
-:1065B00024110001240500040E0006332406000106
-:1065C0000E000840000000000A00088C24020001B0
-:1065D0002407FF800247282400A79026324200FFAC
-:1065E000004090210A000899241100010E00073F85
-:1065F000022028213206003010C0FFA33210008292
-:10660000024020210E000681022028210A00088C69
-:10661000240200018E63001802402021022028215C
-:10662000006610250E000862AE6200189264004CED
-:1066300024050003240600010E000633308400FF09
-:106640000E00004124040001926A0025020A482538
-:106650000E00004FA26900250A00088C24020001E8
-:106660008E7800183C1980000240202103197825FB
-:10667000022028210E000670AE6F00189264004CB4
-:106680000A000914240500043246008038CA00803C
-:10669000146AFF6E3C0E80080A0008ED26480001CF
-:1066A00027BDFFC0AFB000183C108000AFBF00385E
-:1066B000AFB70034AFB60030AFB5002CAFB4002890
-:1066C000AFB30024AFB200200E0004BBAFB1001C7A
-:1066D000920401089205010B308400FF0E0008733C
-:1066E00030A500FF144000E58FBF00383C0980084A
-:1066F00035280080A100006B3607098090E6000075
-:10670000240200503C17080026F73B4830C300FF26
-:106710003C13080026733B58106200033C108000B5
-:106720000000B82100009821241F001036110A0033
-:10673000361409808E1601048F8D00508E38002487
-:1067400036190A808E9200203C010800A03F3B9041
-:10675000972C002C8EF50000932B0018024D70230F
-:1067600002D878233C010800AC2F3B6C3C010800A8
-:10677000AC2E3B703C010800AC2D3B94A78C005420
-:1067800002A0F809317200FF304A0002154000E80B
-:106790003045000110A000C300000000928A0008EC
-:1067A0003150000816000002241400030000A0214C
-:1067B0003C06800034C4090034C30A008C6E0024F7
-:1067C00090850011908200129099001130B800FF5E
-:1067D000305100FF0291F821001FB080332F00FFDD
-:1067E00002D85821024FA82126AC0010017268215E
-:1067F0003C1580003C010800AC2E3B983C01080091
-:10680000A42D3B883C010800A42C3B843C010800DB
-:10681000A42B3B8636B609808F8700508F8900589D
-:106820008ED20020240800060127302302472823A7
-:106830003C010800AC283B8C04C000B5000090214E
-:1068400004A000B300C5802B120000B500000000BA
-:106850003C010800AC263B708E7100000220F80954
-:1068600000000000304A0002154000740040802102
-:10687000304B0001556000118E7100043C0D080082
-:106880008DAD3B743C0EC0003C04800001AE602521
-:10689000AEAC0E008C980000330F000811E0FFFD35
-:1068A00000000000949F0E0824120001A79F0040E2
-:1068B0008C990E04AF9900388E7100040220F809FB
-:1068C000000000000202802532020002144000B4E1
-:1068D000000000003C08080095083B7C3C110800C3
-:1068E00096313B883C09080095293B7E3C03080013
-:1068F0008C633B74011168213C1F08008FFF3B989B
-:106900003C07080094E73B923C11800001A920213C
-:106910008E38010C006828212499000200A77021FC
-:1069200003E37821AF9800603C010800AC2F3B984E
-:106930003C010800A42E3B803C010800A42D3B8AAA
-:106940000E0001B43324FFFF8F8C0048004020214B
-:106950003C010800A02C3B918E620008258B0001B1
-:10696000AF8B00480040F809000000008F85005000
-:10697000028030210E00050F004020210E00069FEE
-:10698000004020218E6A000C0140F80900402021BF
-:106990003C08080095083B8A3C09080095293B7E85
-:1069A0000109382124E600020E0001C830C4FFFFAF
-:1069B0003C0408008C843B6C3C0308008C633B74F3
-:1069C000008328233C010800AC253B6C14A0000682
-:1069D000000000003C0A08008D4A3B8C3546004010
-:1069E0003C010800AC263B8C124000438F8C0044D5
-:1069F0008E2B0E108F920044AE4B00208E220E186C
-:106A0000AE4200243C04080094843B800E0005FB49
-:106A1000000000008F9900508E7800103C010800A3
-:106A2000AC393B940300F809000000003C0F08005B
-:106A30008DEF3B6C15E0FF798F87005097940054E1
-:106A40003C13800E321501000E00062AA674002C9D
-:106A500016A00046320300105460004D8EE500047D
-:106A60003207004054E0001D8EF000088EE4000C58
-:106A70000080F809000000008FBF00388FB7003495
-:106A80008FB600308FB5002C8FB400288FB3002450
-:106A90008FB200208FB1001C8FB0001803E00008F7
-:106AA00027BD0040920901098F88003C00093E0083
-:106AB00000E83025AE0600808E2300208E240024BE
-:106AC000AFA30010AE030E148FA20010AE020E1082
-:106AD000AE040E1C0A00096EAE040E180200F8097E
-:106AE000000000008EE4000C0080F80900000000A7
-:106AF0000A000A268FBF0038240E0001240D000171
-:106B0000A5800020A58E00220A000A08AD8D002471
-:106B10003C010800AC203B700A00099E8E71000009
-:106B20003C010800AC253B700A00099E8E710000F4
-:106B300092110109000028210E000670322400FF86
-:106B40008FBF00388FB700348FB600308FB5002C60
-:106B50008FB400288FB300248FB200208FB1001CA7
-:106B60008FB0001803E0000827BD00403C1F8000E4
-:106B700093F60109000028210E00073F32C400FFF0
-:106B8000320300105060FFB7320700408EE500046A
-:106B900000A0F809000000000A000A2032070040A7
-:106BA0005240FFA7979400548EB60E148F93004462
-:106BB000AE7600208EB40E1CAE7400240A000A17B4
-:106BC000979400548F8200140004218003E0000891
-:106BD000008210213C07800834E200809043006965
-:106BE00000804021106000093C0401003C070800BF
-:106BF0008CE73B948F83003000E32023048000085F
-:106C00009389001C14E300030100202103E0000825
-:106C1000008010213C04010003E0000800801021E6
-:106C20001120000B006738233C0D800035AC098033
-:106C3000918B007C316A000211400020240900344D
-:106C400000E9702B15C0FFF10100202100E9382375
-:106C50002403FFFC00A3C82400E3C02400F9782B20
-:106C600015E0FFEA0308202130C4000300041023CC
-:106C700014C00014304900030000302100A978211D
-:106C800001E6702100EE682B11A0FFE03C0401003A
-:106C90002D3800010006C82B0105482103193824AE
-:106CA00014E0FFDA2524FFFC2402FFFC00A21824D4
-:106CB0000068202103E00008008010210A000A97E4
-:106CC000240900303C0C80003586098090CB007C84
-:106CD000316A00041540FFE9240600040A000AA6F0
-:106CE000000030213C0308008C63005C8F82001898
-:106CF00027BDFFE8AFBF001410620005AFB0001061
-:106D0000000329C024A40280AF840014AF830018BC
-:106D10003C10800036030A00946500320E000A78A9
-:106D200030A43FFF8E0401003C180080370F0003A1
-:106D30000082C8212402FF80032260243329007FBF
-:106D4000000CF94003E94025332E00783C0D10007B
-:106D5000010D502501CF5825AE0C002836080980BA
-:106D6000AE0C080CAE0B082CAE0A0830910300697B
-:106D70003C06800C0126382110600006AF870034E5
-:106D80008D09003C8D06006C0126382318E0007F39
-:106D9000000000003C0C8008358B00803C0A80001D
-:106DA000A1600069355009808E0200383C068000E1
-:106DB00034C50A0090AD003C31A800201100001934
-:106DC000AF820030240E00013C19800037300A00E9
-:106DD000A38E001CAF8000248E0400248F85002425
-:106DE00024180008AF800020AF8000283C01080074
-:106DF000A4383B7E3C010800A4203B920E000A7C94
-:106E000000003021920F003C8FBF00148FB00010A3
-:106E1000000F7142AF82002C27BD001803E000086C
-:106E200031C2000190B90032240F0001333800FF55
-:106E300000182182108F003F241F0002109F006263
-:106E400034C20AC03C03800034640A008C990024D8
-:106E50001720001D3466090090830030241F0005B0
-:106E60003062003F105F004C240500018F86002037
-:106E7000A385001CAF860028AF8600243C19800043
-:106E800037300A008E0400248F850024241800085F
-:106E90003C010800A4383B7E3C010800A4203B9242
-:106EA0000E000A7C00000000920F003C8FBF00140F
-:106EB0008FB00010000F7142AF82002C27BD001868
-:106EC00003E0000831C200018C8800088C8D00248A
-:106ED0008CCB00643C19800037300A00AF8B002453
-:106EE000A380001C8E0400248F8600208F85002440
-:106EF000010D602324180008AF8C00283C01080015
-:106F0000A4383B7E3C010800A4203B920E000A7C82
-:106F100000000000920F003C8FBF00148FB00010E3
-:106F2000000F7142AF82002C27BD001803E000085B
-:106F300031C2000190A7003030E3003F50640028C8
-:106F400034C50AC08CAA00241540002234C80900A8
-:106F50008CAB00483C0C7FFF3585FFFF016510249A
-:106F60003C188000AF820020370509008F8E00207A
-:106F70008CAF006001CF682B15A0000201C020215A
-:106F80008CA400600A000B18AF8400208D02006CF6
-:106F90000A000AF33C0680008C8900488F86002096
-:106FA0003C0A7FFF3550FFFF013038243C04800845
-:106FB00024050001AF870028AC80006CA385001C6D
-:106FC0000A000B26AF8600248C4400140A000B181C
-:106FD000AF8400208D0200680A000B603C1880001E
-:106FE00034C409808C8600708CB0001400D0482B0B
-:106FF00011200004000000008C8200700A000B6069
-:107000003C1880008CA200140A000B603C18800021
-:107010008F85002427BDFFE0AFBF0018AFB100147B
-:1070200014A00008AFB000103C04800034870A00B0
-:1070300090E600302402000530C3003F106200BE1D
-:10704000348409008F91002000A080213C0480003E
-:10705000348E0A008DCD00043C0608008CC63B70BF
-:1070600031A73FFF00E6602B5580000100E0302192
-:10707000938F001C11E0007600D0102B349909800A
-:107080009338007C3304000210800077240300341E
-:1070900000C3F82B17E000DD00C3302300D0102B15
-:1070A0003C010800A4233B7C1440006D0200182121
-:1070B0003C0408008C843B6C0064282B54A0000125
-:1070C000006020213C05800034A90A009128003C82
-:1070D0003C010800AC243B74310300201460000222
-:1070E000000048218CA90E188F88002C0128502BF5
-:1070F0001140005F000000003C0508008CA53B74B7
-:1071000000A96021010C582B1160005C00B0682BB5
-:107110000109382300E028213C010800AC273B741A
-:10712000120000032403FFFC10B00093322B000375
-:1071300000A310243C010800A4203B923C0108005D
-:10714000AC223B74004028218F84002412040006E6
-:107150003C0A80088D4B006C02002021AF9100207A
-:1071600025700001AD50006C8F8C002800858823AD
-:10717000AF91002401852023AF8400281220000253
-:1071800024070018240700103C0F800835E6008013
-:1071900090CE00683C010800A0273B902407000126
-:1071A00031CD00FF11A7004A000000001480001834
-:1071B000000028213C0C800091850109359109804F
-:1071C0008E2B001830A500FF24A30001000B8602BF
-:1071D0003206007F306A007F114600852407FF8059
-:1071E0003C04800834890080A123004C3C0808003E
-:1071F0008D083B8C240F00023C010800A02F3BD1DE
-:10720000350E00083C010800AC2E3B8C2405001014
-:107210003C028000345F0A0093F9003C33380020C0
-:107220001300000500A02021240300013C010800F8
-:10723000AC233B7434A400018FBF00188FB100143D
-:107240008FB000100080102103E0000827BD00204F
-:107250003C010800A4203B7C1040FF95020018214F
-:107260000A000BB300C018210A000BAB2403003046
-:107270003C0508008CA53B7400B0682B11A0FFA84A
-:10728000000000003C04080094843B7C00857821C9
-:1072900001E7702B11C000242CA300043C1F6000E8
-:1072A0008FF954043338003F1300001F0000000022
-:1072B0003C0208008C4200A41040FFDF240400427E
-:1072C00014A000198FBF00180A000C16000000005F
-:1072D0001528FFB6000000008CC300183C19800080
-:1072E000241F000200791025ACC2001837380A00AC
-:1072F000A0DF00689309003C2404000400A01021D2
-:10730000312800203C010800A0243BD111000002DC
-:1073100024050010240200013C010800AC223B6C53
-:107320000A000C0C3C0280001060FF7D2404004227
-:107330000A000C168FBF00188F8800288C89006007
-:107340000109282B14A00002010088218C91006003
-:107350003C0B80008D640E18240A000102202821B5
-:1073600002203021A38A001C0E000A7C022080210A
-:107370000A000B9AAF82002C000B5023122000074A
-:10738000314400033C0E800035CD098091A7007C7C
-:1073900030EC000415800019248F00043C01080023
-:1073A000A4243B923C19080097393B920325C02145
-:1073B00000D8202B1080FF658F8400242CA60005A8
-:1073C00014C0FF9D2404004230BF000317E00002F8
-:1073D00000BF182324A3FFFC3C010800AC233B742E
-:1073E0003C010800A4203B920A000BD90060282130
-:1073F00000A768240A000BFF01A718263C0108001B
-:10740000A42F3B920A000C70000000003C01080011
-:10741000AC203B740A000C15240400428F83002822
-:107420003C0B8000356A0A00146000060000102141
-:10743000914600302405000530C400FF108500038C
-:107440000000000003E0000800000000914900482F
-:10745000312800FF000839C214E0FFFA3C0480081C
-:107460003C06080094C63B7C3C0308008C633B94BC
-:107470003C0508008CA53B743C18080097183B920B
-:107480000066C8218C8E00040325782101F868214C
-:1074900001AE60231980001D000000009158004CCF
-:1074A0008F8D0034956E0E10330F00FF8DA90004F0
-:1074B00001CF30238DAA000030CFFFFF000F610005
-:1074C000012C2821000038210147202100AC182B75
-:1074D0000083C821ADA50004ADB9000091B8000A31
-:1074E00001F87021A1AE000A956C0E128F8A00344B
-:1074F000A54C00089549003825280001A54800380A
-:107500009147000D34EB0008A14B000D03E000088B
-:107510000000000027BDFFD8AFB00018938F001CFB
-:107520008FB000143C087FFF8F8700243C0C800044
-:107530003518FFFFAFBF0020AFB1001C35990A001E
-:1075400002181824932A003C000F5FC03C02BFFFC2
-:107550002CF000013449FFFF006BF8253C080800BF
-:107560008D083B948F9900303C18080097183B8A8F
-:1075700003E9582400107F803C07EFFF3C05F0FF33
-:10758000016F18253C1180003149002034E2FFFFD3
-:1075900034ADFFFF362E098027A500102406000217
-:1075A00001194023270A000200621824008080216C
-:1075B00015200002000058218D8B0E1CA7AA001276
-:1075C0000500003A2407000030EF00FF000F3F00E5
-:1075D000006740253C028008AFA80014344B0080AF
-:1075E000916A00683C0F080091EF3B913C09DFFF76
-:1075F000353FFFFF000A602B3C02080094423B84A9
-:10760000A3AF0011011FC024000CCF40031918259F
-:107610008FA70010AFA300143C1F080093FF3B93FB
-:10762000A7A200168FA8001400ED48243C0B01000F
-:107630003C0A0FFF012BC82533F80003354CFFFF30
-:10764000010D78243C027000032C382400181E0021
-:1076500000E2482501E35825AFAB0014AFA90010A4
-:1076600091DF007CA3BF00150E0000630000000046
-:10767000362D0A0091A6003C30C400201080000680
-:10768000260200083C11080096313B80262EFFFFA1
-:107690003C010800A42E3B808FBF00208FB1001C4E
-:1076A0008FB0001803E0000827BD00288F8A002C47
-:1076B000016A602B5580FFC4240700010A000CFA00
-:1076C00030EF00FF9383001C3C02800027BDFFD8F1
-:1076D00034480A0000805021AFBF002034460AC061
-:1076E000010028211060000E344409809107003009
-:1076F000240B00058F89002030EC003F118B000B1C
-:1077000000003821AFA900103C0B80088D69006C87
-:10771000AFAA00180E00012BAFA90014A380001C13
-:107720008FBF002003E0000827BD00288D1F004800
-:107730003C1808008F183B748F9900283C027FFF8B
-:107740008D0800443443FFFFAFA900103C0B8008B4
-:107750008D69006C03E370240319782101CF68233D
-:1077600001A83821AFAA00180E00012BAFA9001400
-:107770000A000D4FA380001C3C05800034A60A00BF
-:1077800090C7003C3C06080094C63B923C020800AF
-:107790008C423B8C30E30020000624001060001E69
-:1077A000004438253C0880083505008090A3006817
-:1077B00000003021240800010000202124030001E2
-:1077C0003C0580008CAC01780580FFFE00000000C5
-:1077D000ACA80148A4A40144A4A301463C030800AA
-:1077E0008C633B943C188008370F0080ACA3014C9D
-:1077F0003C19080093393B913C0D1000A0B901528F
-:10780000ACA70154A4A6015891EE004CA0AE016DA6
-:1078100003E00008ACAD01788CA80E1C3C0B0800FE
-:107820008D6B3B7494AA0E1694A90E140166302138
-:107830003143FFFF0A000D773124FFFF3C04800035
-:1078400034830A009065003C30A200201040001CE8
-:10785000000000000000302100002021000018215D
-:107860003C0580008CA901780520FFFE0000000087
-:10787000ACA601483C0E08008DCE3B94240DFF9130
-:10788000240C00403C0B8008A4A30144356A00800E
-:10789000A4A40146ACAE014CA0AD0152ACAC015465
-:1078A000A4A0015890A301099144004C90A601099D
-:1078B0003C041000A0A6016D03E00008ACA4017810
-:1078C0008C860E1894880E1294870E103104FFFFD8
-:1078D0000A000D9F30E3FFFF3C04800034830A0060
-:1078E0009065003C30A200201040002627BDFFF824
-:1078F0002409000100003821240800013C06800012
-:107900008CC401780480FFFE0000000090CA0109C9
-:107910003C04080090843BD13C1880FFA3AA0003DC
-:107920008FA300003085007F370FFFFF0066102512
-:10793000AFA2000090D9010AA3A0000200056E00CA
-:10794000A3B900018FAE0000240A300027BD000853
-:1079500001CF6024018D5825ACCB014CACCA015439
-:10796000A4C00158ACC90148A4C701442409FF8040
-:10797000A4C801463C081000A0C9015203E0000859
-:10798000ACC801788C890E1894870E1294860E105C
-:1079900030E8FFFF0A000DC630C7FFFF27BDFFE834
-:1079A000AFB000103C108000AFBF001436180A00C2
-:1079B000970F00320E000A7831E43FFF8E0E01006F
-:1079C000240DFF803C04200001C25821016D602479
-:1079D000000C4940316A007F012A40250104382506
-:1079E0003C048008AE0708303486008090C50068EB
-:1079F0002403000230A200FF104300048F9F0020E8
-:107A00008F990024AC9F0068AC9900648FBF00146C
-:107A10008FB0001003E0000827BD00183C0A0800E2
-:107A2000254A36583C090800252936F43C08080048
-:107A300025082B003C07080024E737B83C0608005F
-:107A400024C634E03C05080024A532383C04080074
-:107A500024842E2C3C030800246335943C02080047
-:107A6000244233303C010800AC2A3B503C01080062
-:107A7000AC293B4C3C010800AC283B483C010800C9
-:107A8000AC273B543C010800AC263B643C01080099
-:107A9000AC253B5C3C010800AC243B583C01080091
-:107AA000AC233B683C010800AC223B6003E00008CB
-:047AB00000000000D2
-:0C7AB400800009408000090080080100EB
-:107AC0008008008080080000800E00008008008090
-:107AD0008008000080000A8080000A008000098081
-:047AE0008000090019
-: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.0.17.fw.ihex b/firmware/bnx2/bnx2-mips-09-6.0.17.fw.ihex
new file mode 100644
index 0000000..7f39b4a
--- /dev/null
+++ b/firmware/bnx2/bnx2-mips-09-6.0.17.fw.ihex
@@ -0,0 +1,6488 @@
+:10000000080001180800000000005594000000C816
+:1000100000000000000000000000000008005594EF
+:10002000000000380000565C080000A00800000036
+:100030000000574400005694080059200000008436
+:100040000000ADD808005744000001C00000AE5CBD
+:100050000800321008000000000090900000B01C62
+:100060000000000000000000000000000800909068
+:100070000000033C000140AC0800049008000400AC
+:10008000000012FC000143E8000000000000000036
+:1000900000000000080016FC00000004000156E407
+:1000A000080000A80800000000003D28000156E8F4
+:1000B00000000000000000000000000008003D28D3
+:0800C000000000300001941063
+:0800C8000A00004600000000E0
+:1000D000000000000000000D636F6D362E302E31E1
+:1000E00037000000060011020000000000000003BD
+: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
+:1056A0000000000D6370362E302E313700000000F0
+:1056B00006001104000000000000000000000000CF
+: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
+:10B030002E302E3137000000060011030000000002
+: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
+:10E240003C020801244294003C03080124639634F4
+:10E25000AC4000000043202B1480FFFD244200044A
+:10E260003C1D080037BD9FFC03A0F0213C100800B6
+:10E27000261032103C1C0801279C94000E001274DA
+:10E28000000000000000000D3C02800030A5FFFFF0
+:10E2900030C600FF344301803C0880008D0901B87E
+:10E2A0000520FFFE00000000AC6400002404000212
+:10E2B000A4650008A066000AA064000BAC67001803
+:10E2C0003C03100003E00008AD0301B83C0560000A
+:10E2D0008CA24FF80440FFFE00000000ACA44FC029
+:10E2E0003C0310003C040200ACA44FC403E000084F
+:10E2F000ACA34FF89486000C00A050212488001491
+:10E3000000062B0200051080004448210109182B4B
+:10E310001060001100000000910300002C6400094F
+:10E320005080000991190001000360803C0D080134
+:10E3300025AD9090018D58218D67000000E0000808
+:10E340000000000091190001011940210109302B42
+:10E3500054C0FFF29103000003E000080000102108
+:10E360000A000CCC25080001910F0001240E000AC0
+:10E3700015EE00400128C8232F38000A1700003D81
+:10E38000250D00028D580000250F0006370E0100F4
+:10E39000AD4E0000910C000291AB000191A400026F
+:10E3A00091A60003000C2E00000B3C0000A71025D6
+:10E3B00000041A000043C8250326C025AD580004F8
+:10E3C000910E000691ED000191E7000291E5000336
+:10E3D000000E5E00000D6400016C30250007220075
+:10E3E00000C41025004518252508000A0A000CCC99
+:10E3F000AD430008910F000125040002240800022B
+:10E4000055E80001012020210A000CCC00804021A9
+:10E41000910C0001240B0003158B00160000000076
+:10E420008D580000910E000225080003370D0008EA
+:10E43000A14E00100A000CCCAD4D00009119000156
+:10E44000240F0004172F000B0000000091070002AA
+:10E45000910400038D43000000072A0000A410254A
+:10E460003466000425080004AD42000C0A000CCC00
+:10E47000AD46000003E000082402000127BDFFE8CC
+:10E48000AFBF0014AFB000100E0015E50080802172
+:10E490003C0480083485008090A600052403FFFE1C
+:10E4A0000200202100C310248FBF00148FB0001081
+:10E4B000A0A200050A0015EF27BD001827BDFFE840
+:10E4C000AFB00010AFBF00140E000FD40080802149
+:10E4D0003C06800834C5008090A40000240200504F
+:10E4E000308300FF106200073C09800002002021F9
+:10E4F0008FBF00148FB00010AD2001800A0010A65D
+:10E5000027BD0018240801003C07800002002021DC
+:10E510008FBF00148FB00010ACE801800A0010A675
+:10E5200027BD001827BDFF783C058008AFBE0080DE
+:10E53000AFB7007CAFB3006CAFB10064AFBF008475
+:10E54000AFB60078AFB50074AFB40070AFB200687A
+:10E55000AFB0006034A600803C0580008CB201287A
+:10E5600090C400098CA701043C020001309100FF17
+:10E5700000E218240000B8210000F021106000071C
+:10E58000000098213C0908008D2931F02413000176
+:10E59000252800013C010800AC2831F0ACA0008423
+:10E5A00090CC0005000C5827316A0001154000721C
+:10E5B000AFA0005090CD00002406002031A400FF41
+:10E5C00010860018240E0050108E009300000000EA
+:10E5D0003C1008008E1000DC260F00013C010800F2
+:10E5E000AC2F00DC0E00165E000000000040182179
+: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
+:10E790000E0016AE02C020211440FFE10000000070
+:10E7A0003C0B8008356400808C8A003402CA482300
+:10E7B0000520001D000000003C1E08008FDE310017
+:10E7C00027D700013C010800AC3731001260000679
+:10E7D000024020213C1408008E9431F42690000160
+:10E7E0003C010800AC3031F40E0015E53C1E8008F9
+:10E7F00037CD008091B700250240202136EE00047D
+:10E800000E0015EFA1AE00250E000CAC0240202139
+:10E810000A000DCA240300013C17080126F794F8EA
+:10E820000A000D843C1F80008C86003002C66023E5
+:10E830001980000C2419000C908F004F3C14080024
+:10E840008E94310032B500FC35ED0001268E0001BA
+:10E850003C010800AC2E3100A08D004FAFA0005845
+:10E860002419000CAFB900308C9800300316A02397
+:10E870001A80010B8FA300580074F82A17E0FFD309
+:10E88000000000001074002A8FA5005802D4B021A7
+:10E8900000B410233044FFFFAFA4005832A8000298
+:10E8A0001100002E32AB00103C15800836B00080FD
+:10E8B0009216000832D30040526000FB8EE200083E
+:10E8C0000E0015E502402021240A0018A20A0009C2
+:10E8D000921100052409FFFE024020210229902404
+:10E8E0000E0015EFA21200052404003900002821B3
+:10E8F0000E001689240600180A000DCA2403000120
+:10E9000092FE000C3C0A800835490080001EBB00C6
+:10E910008D27003836F10081024020213225F08118
+:10E920000E000C9B30C600FF0A000DC10000000065
+:10E930003AA7000130E300011460FFA402D4B02123
+:10E940000A000E1D00000000024020210E0016CB20
+:10E95000020028210A000D75004018211160FF7087
+:10E960003C0F80083C0D800835EE00808DC40038D7
+:10E970008FA300548DA60004006660231D80FF68ED
+:10E98000000000000064C02307020001AFA400548F
+:10E990003C1F08008FFF31E433F9000113200015FC
+:10E9A0008FAC00583C07800094E3011A10600012FD
+:10E9B0003C0680080E0020F8024020213C0308019C
+:10E9C0009063952930640002148001450000000026
+:10E9D000306C0004118000078FAC0058306600FBDB
+:10E9E0003C010801A026952932B500FCAFA00058D3
+: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
+:10EB900012200006031928213C03080190639529DF
+:10EBA00030690008152000C6306A00F73C10800864
+:10EBB00036040080908C004F318B000115600042BC
+:10EBC000000000003C0608008CC6319830CE0010D2
+:10EBD00051C0004230F9000190AF006B55E0003F9A
+:10EBE00030F9000124180001A0B8006B3C1180002E
+:10EBF0009622007A24470064A48700123C0D800806
+:10EC000035A5008090B40008329000401600000442
+:10EC10003C03800832AE000115C0008B00000000EC
+:10EC2000346400808C86002010D3000A3463010015
+:10EC30008C67000002C7782319E000978FBF00544B
+:10EC4000AC93002024130001AC760000AFB3005059
+:10EC5000AC7F000417C0004E000000008FA90050D8
+:10EC60001520000B000000003C030801906395296B
+:10EC7000306A00011140002E8FAB0058306400FE56
+:10EC80003C010801A02495290A000D7500001821F7
+:10EC90000E000CAC024020210A000F1300000000FF
+:10ECA0000A000E200000A0210040F80924040017EB
+:10ECB0000A000DCA240300010040F80924040016CC
+:10ECC0000A000DCA240300019094004F240DFFFE9A
+:10ECD000028D2824A085004F30F900011320000682
+:10ECE0003C0480083C03080190639529307F0010A4
+:10ECF00017E00051306800EF34900080240A0001D2
+:10ED0000024020210E0015E5A60A001292030025FC
+:10ED100024090001AFA90050346200010240202103
+:10ED20000E0015EFA20200250A000EF93C0D800826
+:10ED30001160FE83000018218FA5003030AC000464
+:10ED40001180FE2C8FBF00840A000DCB240300012C
+:10ED500027A500380E000CB6AFA000385440FF4382
+:10ED60008EE200048FB40038329001005200FF3F61
+:10ED70008EE200048FA3003C8E6E0058006E682364
+:10ED800005A3FF39AE6300580A000E948EE200041A
+:10ED90000E0015E5024020213C0380083468008005
+:10EDA000024020210E0015EFA11E000903C03021F2
+:10EDB000240400370E001689000028210A000F11D4
+:10EDC0008FA900508FAB00185960FF8D3C0D800853
+:10EDD0000E0015E502402021920C002524050001BB
+:10EDE000AFA5005035820004024020210E0015EF2F
+:10EDF000A20200250A000EF93C0D800812240059D9
+:10EE00002A2300151060004D240900162408000C68
+:10EE10005628FF2732B000013C0A8008914C001BA5
+:10EE20002406FFBD241E000E01865824A14B001BA2
+:10EE30000A000EA532B000013C010801A028952966
+:10EE40000A000EF93C0D80088CB500308EFE0008DB
+:10EE50002404001826B6000103C0F809ACB600303F
+:10EE60003C030801906395293077000116E0FF818B
+:10EE7000306A00018FB200300A000D753243000481
+:10EE80003C1080009605011A50A0FF2B34C60010DC
+:10EE90000A000EC892EE000C8C6200001456FF6D42
+:10EEA000000000008C7800048FB9005403388823D8
+:10EEB0000621FF638FBF00540A000F0E0000000000
+:10EEC0003C010801A02A95290A000F3030F9000101
+:10EED0001633FF028FAF00240A000EB0241E00106C
+:10EEE0000E0015E5024020213C0B800835680080AB
+:10EEF00091090025240A0001AFAA0050353300040F
+:10EF0000024020210E0015EFA11300253C05080149
+:10EF100090A5952930A200FD3C010801A022952969
+:10EF20000A000E6D004018212411000E53D1FEEA94
+:10EF3000241E00100A000EAF241E00165629FEDC07
+:10EF400032B000013C0A8008914C001B2406FFBD32
+:10EF5000241E001001865824A14B001B0A000EA598
+:10EF600032B000010A000EA4241E00123C038000EF
+:10EF70008C6201B80440FFFE24040800AC6401B8B0
+:10EF800003E00008000000000080502130A5FFFFD2
+:10EF900030C6FFFF3C0480008C8201B80440FFFEB5
+:10EFA00034880180AD0A00003C078008AC8A00204C
+:10EFB00094E300483067FFFF10E000423C0D800002
+:10EFC00024AB001200EB482B5120003F2404000327
+:10EFD00034820100945900208F8900002404001A13
+:10EFE0003338FFFF270BFFFE00EB782B39EE0001D3
+:10EFF00000096B8201AE6024A104000B518000491E
+:10F000008F8B00048F830004A50B0014346800016B
+:10F01000AF88000430CE004015C000333C048000AF
+:10F020003C02800034420180A445000E3C07800071
+:10F0300034EC0180A585001A8F85000C310B80000F
+:10F04000A5890010AD850028A58600081160000F75
+:10F050008F85001434EA0100954E001631CDFFFC77
+:10F0600025A40004008718218C67400030E6FFFFCC
+:10F0700014C000073C0480003C18FFFF370F7FFFDF
+:10F08000010F4024AF8800048F8500143C048000E9
+:10F090002402BFFF348301800102C824A479002622
+:10F0A00010A00004AC69002C00054402A465001007
+:10F0B000A46800263C091000AC8901B803E00008F0
+:10F0C000000000002404000335AC018030CE004075
+:10F0D0008F8900008F880004A184000B51C0FFD1EC
+:10F0E0003C0280003C048000AC8A00203C0F800879
+:10F0F00095EA00403143FFFF5060000834820180F0
+:10F1000000A3C02B5700000100A0182134990180F2
+:10F11000A723000E0A0010053C0780000A00100318
+:10F1200030C6FFBF2407FFFE016740240A000FFE20
+:10F13000AF88000427BDFFE88FA2002830A5FFFF9D
+:10F1400030C6FFFFAFBF0010AF87000CAF820014C6
+:10F15000AF8000040E000FDBAF8000008FBF0010F7
+:10F1600027BD001803E00008AF8000143C068000B3
+:10F1700034C4007034C701008C8A000090E500128E
+:10F180008F84000027BDFFF030A300FF000318822A
+:10F190003082400010400037246500030005C8801D
+:10F1A0000326C0218F0E4000246F0004000F6880EA
+:10F1B000AFAE000001A660218D8B4000AFAB000414
+:10F1C00094E900163128FFFC010638218CE6400046
+:10F1D000AFA600088FA900080000302100002821F8
+:10F1E0003C07080024E701000A00107E24080008FC
+:10F1F0009059000024A500012CAC000C0079C0211E
+:10F200000018788001E770218DCD00001180000684
+:10F2100000CD302603A5102114A8FFF500051A0023
+:10F220005520FFF4905900003C04800034870070A2
+:10F230003C0508008CA531048CE300002CA20020C2
+:10F2400010400009006A3823000548803C0B080084
+:10F25000256B3108012B402124AA0001AD070000D5
+:10F260003C010800AC2A310400C0102103E0000872
+:10F2700027BD0010308220001040000B0005588090
+:10F28000016648218D24400024680004000838806D
+:10F29000AFA4000000E618218C654000AFA0000874
+:10F2A0000A00106EAFA500040000000D0A00106FE8
+:10F2B0008FA9000827BDFFD83C058000AFB100141E
+:10F2C000AFB00010AFBF0024AFB40020AFB3001C3C
+:10F2D000AFB200188F87000034A401009483000EA1
+:10F2E00030E2400000008021104000103071FFFF2C
+:10F2F0003C08002000E8302410C0000D30EB8000F6
+:10F300008F890004240ABFFF00EA38243523100047
+:10F31000AF87000030F320001660000B3C1800049B
+:10F320002419FFBF0A0010CF0079102430EB8000B1
+:10F330001560004D3C0D002030F320001260FFF8F6
+:10F340008F8300043C18000400F8A0241280FFF50D
+:10F350002419FFBF3462004030FF010013E00010A9
+:10F36000AF8200048F820028104000063C0E80000F
+:10F370003C04002000E41824146000CE3C06000485
+:10F380003C0E800035CD010095AC001E95AB001CF5
+:10F390003189FFFF000B5400012A4025AF88000C83
+:10F3A0003C138000367401009692000C8E6340007E
+:10F3B000340FFFFF106F00843244FFFF30780100EC
+:10F3C000570000012410001030F9100053200008ED
+:10F3D0003612000130FF002017E000733C031000DC
+:10F3E00000E310241440006A3C0A0C0036120001AD
+:10F3F00030EC01001580000B3C0600018F880004F2
+:10F40000310D400015A0000800E628243C131F0120
+:10F4100000F378243C0E100011EE00AE3094020090
+:10F420003C06000100E6282410A000193C19100039
+:10F430003C0408008C84002430940002168000D91B
+:10F44000240300018FBF00248FB400208FB3001C61
+:10F450008FB200188FB100148FB00010006010211F
+:10F4600003E0000827BD002800ED60241180FFB3F1
+:10F4700030F320008F8E00043C12FFFF364F7FFFD9
+:10F4800000EF382435C380000A0010BEAF870000AB
+:10F4900000F9C0241700004E00002021AF800010AA
+:10F4A0003C0380003465010094AE000E8F91001083
+:10F4B00031CAFFFF108000C62553000430EF010061
+:10F4C00015E000703C180F003A2800022E7003EF80
+:10F4D0002D1900013A1F0001033F282414A0002227
+:10F4E000240400013C0308008C6300D02E25000C8E
+:10F4F000001121C0386C00012D8B00010165102422
+:10F50000144000143270FFFF262DFFFC2DA40004D0
+:10F510001480010300002021386A00022D460001FA
+:10F5200000C51824546000FF02002821262FFFF890
+:10F530002DEE000415C00007000000000007A242E5
+:10F540000011C02B0298482415200109020028212F
+:10F55000001121C002002821364600020E000FDBF8
+:10F560000000000000002021008018218FBF00242F
+:10F570008FB400208FB3001C8FB200188FB100141D
+:10F580008FB000100060102103E0000827BD0028A4
+:10F590003C090BFF00EA40243526FFFF00C8282B5A
+:10F5A00050A0FF93361200013C0B08008D6B002C1D
+:10F5B00036120005257000013C010800AC30002C1B
+:10F5C0000A0010F630EC01000A0010EB24100020B5
+:10F5D00000071602305F000F001F80C03C030801C7
+:10F5E00024639478020320211080FFADAF9F0010A8
+:10F5F000908800005100FFAB3C0380003C0D800070
+:10F6000035A90100952C000E240B00030240302187
+:10F61000318AFFFF25450004110B00D9000050215D
+:10F620009088000124140002311100FF123400BF41
+:10F6300030F80040310300FF24080001106800C8C2
+:10F6400030E200408C8A00048F8B00245560000655
+:10F6500034C60002254DFE002DAC0381558000010B
+:10F660003646004034C600020140202130A5FFFF8D
+:10F670000E000FDB30C6FFFF000040210A00110A18
+:10F680000100182100F8A0243C0902001289FF8F14
+:10F690003A28000290B100133270FFFF02002821C7
+:10F6A000322700FF24F30004001321C00A00115088
+:10F6B0003646000200E6282414A0FF323C0E8000EB
+:10F6C0000E0010543C1380008F8700000A0010E2E7
+:10F6D000AF82000C1680FF533C0600012624000474
+:10F6E0003085FFFF364600023C0380008C7101B874
+:10F6F0000620FFFE8F890008346A0180AD400000BB
+:10F70000112000B23C0D800024B800120138902B6B
+:10F71000124000AF240C0003347001009603002057
+:10F720002402001A30F94000307FFFFFA142000B95
+:10F73000132000AB27E3FFFE0123582B156000A91F
+:10F740002409FFFE35080001A5430014AF8800041A
+:10F750003C0E80002413BFFF0113782435C80180BC
+:10F76000A505000EA505001AA5060008A50F002690
+:10F77000A50700103C071000ADC701B80000182114
+:10F780008FBF00248FB400208FB3001C8FB20018ED
+:10F790008FB100148FB000100060102103E000084A
+:10F7A00027BD00283C1208008E5200D802202821D4
+:10F7B00024040080265100013C010800AC3100D82F
+:10F7C0000E000FDB240600030A0011D900001821E7
+:10F7D0008C65400030B1010012200046325900040F
+:10F7E0003C1F08008FFF002424140004172000028F
+:10F7F00033F0000D2414000200076AC239A400018E
+:10F800002E6C03EF30820001398B0001004B402544
+:10F81000110000033251FFFB2412FFFB021280246F
+:10F8200030E3010050600015321F00013C0A0F0058
+:10F8300000EA30243C07020010C7000F3C1980008A
+:10F840003725010090A900132418FFFE0218802418
+:10F85000312F00FF25EE0004000E21C0120000022F
+:10F86000023430253226FFFF0E000FDB3265FFFF2A
+:10F870001200FF3D00002021321F000113E0000DA7
+:10F88000320B000424080001120800020234302563
+:10F890003226FFFF000020210E000FDB3265FFFF44
+:10F8A0002402FFFE020280241200FF2F000020210C
+:10F8B000320B00045160000D240400010234302595
+:10F8C00024140004561400013226FFFF2411FFFB0C
+:10F8D0003265FFFF240401000E000FDB02119824A3
+:10F8E0001260FF2100002021240400010A001154AD
+:10F8F000008018213C0C08008D8C00243190000100
+:10F900005200FF19000020213265FFFF3646000239
+:10F910000E000FDB000020210A00115300002021FF
+:10F92000020028210A00115036460002130000068A
+:10F930000000000095300010949F000232190FFF64
+:10F9400013F9FF3D310300FF3C04080190849479D2
+:10F950001080FF3D240800010A00110A010018214F
+:10F960005040FF398C8A00040A00124B000000004E
+:10F970000E000FDB3246FFFB0A00114E001121C0C2
+:10F9800090830001240E0001106EFF3C240800014A
+:10F99000240F0002106F000430F30040240800011F
+:10F9A0000A00110A010018215260FFFD240800011D
+:10F9B000952500109487000230A9FFFF50E9FEA1B1
+:10F9C000010018210A00126124080001240C000320
+:10F9D00035AA0180A14C000B0A0011CE3C0E80001C
+:10F9E0002409FFFE0A0011CC0109402427BDFFC0F5
+:10F9F000AFB00018AFBF003C3C10600CAFBE003889
+:10FA0000AFB70034AFB60030AFB5002CAFB40028AC
+:10FA1000AFB30024AFB20020AFB1001C8E0E500077
+:10FA2000240FFF7F3C06800001CF682435AC380CE2
+:10FA3000240B0003AE0C5000ACCB00083C010800C6
+:10FA4000AC2000200E0017B0000000003C0A00109F
+:10FA5000354980513C066016AE09537C8CC70000C6
+:10FA60003C0860148D0500A03C03FFFF00E3202448
+:10FA70003C02535300051FC21082029B34C57C0018
+:10FA80008CBF007C8CA200783C1E600037C4202014
+:10FA90003C05080124A590C0AF820018AF9F001C50
+:10FAA0000E0016742406000A3C19000127399478C8
+:10FAB0003C010800AC3931DC0E00206BAF80001433
+:10FAC0008FD708082418FFF03C15570902F8B02416
+:10FAD00012D5028B24040001AF8000283C14800062
+:10FAE0003697010002E0F0218E90000032050003FD
+:10FAF00010A0FFFD3207000114E0005D3206000295
+:10FB000010C0FFF93C07800034E501408CB90000CB
+:10FB100024100040ACF9002090B8000833030070B6
+:10FB20001070010B286900411120000824080060B2
+:10FB3000241F0020107F000E3C0B40003C0680007C
+:10FB4000ACCB01780A0012B3000000001468FFFB80
+:10FB50003C0B40000E001F88000000003C0B4000E2
+:10FB60003C068000ACCB01780A0012B30000000014
+:10FB700090AB0009241100048CA70000316800FF3D
+:10FB80001111015D2512FFFA2E53000612600016B6
+:10FB90003C0680008CAA00048F86002494A3000AEF
+:10FBA000000A3E02310500FF10C000053064FFFF6F
+:10FBB0002CEC00081580000224E700042407000351
+:10FBC000240E000910AE01A128AF000A11E0018443
+:10FBD0002410000A2404000810A4001A000749C0D9
+:10FBE000012038213C0680008CD001B80600FFFEC1
+:10FBF00034C40180AC87000034C5014090B60008D1
+:10FC0000241900023C0B400032C200FF00028A00AF
+:10FC10000228F825A49F0008A099000B94A7000AC9
+:10FC20003C081000A48700108CB80004AC98002495
+:10FC3000ACC801B83C068000ACCB01780A0012B316
+:10FC400000000000000AC202330300FF2405000187
+:10FC50005465FFE4012038218F990020AF830024F0
+:10FC600027270001AF8700200A0012F20120382167
+:10FC70008FD100283C0B8008AE9100208FC6000475
+:10FC80008FCA000095690048AF860000AF8A000463
+:10FC90003128FFFF0E000FD4AF8800083C03080096
+:10FCA0008C6300C0106000258F8700003C0E0800A8
+:10FCB0008DCE00C425CD00013C010800AC2D00C450
+:10FCC0003C1F800037E901008D3900243C0760208B
+:10FCD000ACF90014000000003C0680003C08400025
+:10FCE000ACC80138000000005220FF853206000237
+:10FCF000262D0140262E00802404FF8001A4282404
+:10FD000001C47824000F194031CC007F00059940D0
+:10FD100031B2007F3C15200036A20002006C502555
+:10FD20000272B02502C2882501425825ACCB0830AA
+:10FD3000ACD108300A0012B9320600023C120010A1
+:10FD400000F2782415E000708F8300043C1808004E
+:10FD50008F18002097D6000E30F5400027130001C1
+:10FD60003C010800AC3300200000902112A000816B
+:10FD700032D3FFFF3C1F002000FFC8241320007E69
+:10FD800030E580008F8200042404BFFF00E43824A3
+:10FD900034431000AF87000030EB20001160007387
+:10FDA000240EFFBF3C0D000400ED60241180000212
+:10FDB000006E10243462004030EF010011E00010AA
+:10FDC000AF8200048F95002812A000073C18002085
+:10FDD00000F8B02412C000043C1F000400FFC82437
+:10FDE0001320016D0000000096E3001E96E8001C41
+:10FDF0003065FFFF0008140000A22025AF84000C2E
+:10FE000096EA000C8E8440003409FFFF10890085BB
+:10FE10003145FFFF3086010054C00001241200105C
+:10FE200030EB1000116000133656000130EC00205A
+:10FE30001580000A3C0E100000EE682411A0000D91
+:10FE40003C190C003C180BFF00F9B0243715FFFFDC
+:10FE500002B6782B11E00007365600013C1F08005F
+:10FE60008FFF002C3656000527F200013C010800E8
+:10FE7000AC32002C30E401001480000B3C06000181
+:10FE80008F880004310240005440000800E6282416
+:10FE90003C0A1F0100EA48243C0310001123010919
+:10FEA00030A602003C06000100E6282410A0003E17
+:10FEB0003C1810003C0D08008DAD002431AC000250
+:10FEC0001580000624030001006010211040FF830C
+:10FED0003C0680000A00132A3C1F80003C0F0800EB
+:10FEE0008DEF00D8026028212404008025EE000157
+:10FEF0003C010800AC2E00D80E000FDB24060003E6
+:10FF00000A0013AB000018212405BFFF0065682418
+:10FF100011A00007240F87FF006F702415C0000890
+:10FF20003C18006000F8202410800005000000004C
+:10FF30000E000D42000000000A0013AC000000009B
+:10FF40000E00159C000000000A0013AC0000000029
+:10FF50000E0015F4000000003C0B40003C06800041
+:10FF6000ACCB01780A0012B3000000000A0013674E
+:10FF7000006E102430E5800010A0FF878F830004FE
+:10FF80003C08002000E818245060FF838F830004A1
+:10FF90008F8900043C06FFFF34CA7FFF00EA382443
+:10FFA0000A00135E3523800000F8A82416A0001F65
+:10FFB00000004021AF8000103C0380003464010049
+:10FFC0009486000E8F93001030C5FFFF1100014E84
+:10FFD00024B5000430EA0100114000553A7F0002C8
+:10FFE0003C0E0F0000EE68243C0C020011AC0051E6
+:10FFF0002EB203EF908F001332B2FFFF31E400FF07
+:020000040001F9
+:1000000024870004000721C00240282136C60002D0
+:100010000E000FDB00000000000020210A0013ABDF
+:10002000008018210A0013812412002000072602F4
+:100030003099000F0019F8C03C120801265294783C
+:1000400003F240211100FFDCAF990010910900007C
+:100050001120FFDA3C0380003C138000366A010067
+:10006000954B000E2403000302C030213162FFFFD4
+:1000700024450004112300EC000020219109000117
+:10008000240D0002312E00FF11CD00FA313200FFA5
+:10009000240900011249001030FF00408D040004C3
+:1000A0008F8300241460000634D30002248BFE00EA
+:1000B0002D6203815440000136C6004034D3000253
+:1000C00030A5FFFF0E000FDB3266FFFF0000482166
+:1000D0000A0013AB0120182153E0FFF18D04000446
+:1000E0003C080801910894791100FFED24090001F2
+:1000F0000A0013AB012018213C0480008C8A01B84F
+:100100000540FFFE349601802415001CAEC7000098
+:10011000A2D5000B3C021000AC8201B83C0B4000A1
+:100120003C068000ACCB01780A0012B3000000004E
+:100130002EB203EF2FF900013A4900010329C02430
+:100140001700FFB6240400013C0308008C6300D0B4
+:100150002E65000C001321C0386B00012D620001D8
+:10016000004540241500FFA832B2FFFF266AFFFCBD
+:100170002D46000414C0001300002021386D000239
+:100180002DAC0001018518241460000F02402821C5
+:10019000266EFFF82DC5000414A0FF9B0000000090
+:1001A00000077A420013382B01E7A82456A0000864
+:1001B00002402821001321C0024028210A0013FD1B
+:1001C00036C60002024028210A0013FD36C600028E
+:1001D0000E000FDB32C6FFFB0A001467001321C0BC
+:1001E00010B0007200045A022406000B14A6FE7C14
+:1001F000000749C0314600FF00065600000A5E03B2
+:10020000056200B030C6007F000670C03C0F0801D8
+:1002100025EF947801CFA821A2A00001A2A00000A0
+:100220003C1360008E631820240D000100CD4804AB
+:1002300000096027000749C0006C90240120382184
+:10024000AE7218200A0012F2A6A0000214C0004BE1
+:100250008F8C0020000749C03C0B8000AD69002056
+:100260003C118008963F004013E000022405000185
+:10027000240500413C0480008C8A01B80540FFFE43
+:100280003496018024120003AEC90000A2D2000BF4
+:10029000A6C0000EA6C0001AA6C00010AEC000285E
+:1002A000A6C5000896D3002636750001A6D50026FF
+:1002B000AEC0002C3C021000AC8201B80A0012F261
+:1002C0000120382114C0FEF83C060001266B000412
+:1002D0003165FFFF36C600023C0380008C7301B815
+:1002E0000660FFFE8F8900083C0D800035AC018060
+:1002F000AD800000512000DD3C09800024AF0012D9
+:10030000012F702B51C000D93C09800096F20020CB
+:100310003C1980002418001A3256FFFF372A01804A
+:1003200030F54000A158000B12A000D526C3FFFEF7
+:100330000123F82B17E000D32404FFFE3508000149
+:10034000A5430014AF8800042413BFFF3C0B8000BA
+:100350000113502435680180A505000EA505001A7B
+:10036000A5060008A50A0026A50700103C071000F6
+:10037000AE8701B80A0013AB00001821000749C07E
+:100380002583FFFF1460FE16AF8300200120382173
+:100390000A0012F2AF8000240E001054000000008A
+:1003A0008F8700000A001379AF82000C240300FF3E
+:1003B0001163FE0B000749C010C00038000B760027
+:1003C000000B20C03C0908012529947800891821D8
+:1003D00024020001A06200003C16080126D6947891
+:1003E0003C0208012442947C00962821000749C061
+:1003F00000828821000AFC02AE290000A0BF000193
+:100400003C0460008C9818202419000101793804FC
+:100410000307302501203821A4AA0002AC86182049
+:100420000A0012F33C06800091030001241600012B
+:100430001076FF272409000124050002106500043E
+:1004400030E60040240900010A0013AB0120182106
+:1004500050C0FFFD24090001954C0010950A0002D0
+:100460003187FFFF5147FE98012018210A00150B24
+:100470002409000130EF004011E0FF1900000000E6
+:10048000955900109518000233350FFF1715FF140A
+:10049000313200FF0A00141E24090001000E6E0311
+:1004A00005A2000F316B007F10E30008000B20C095
+:1004B0003C10080126109478009018210A0014EED0
+:1004C000240200020A00147BAF8000203C0F0801C8
+:1004D00025EF9478008F18210A0014EE24020003FF
+:1004E0000A001523AF8B00200003A080028698210C
+:1004F0008E7200043C1160000A00129902512821FA
+:100500000A0012B0AF8400288C64400030930100D0
+:100510001260004B240900043C1908008F390024A4
+:1005200032D80004AFA90010170000033332000DC9
+:10053000241F0002AFBF001000071AC2386A000172
+:100540002EA603EF3142000138CB0001004B4025BD
+:100550001100000332D3FFFB2416FFFB0256902448
+:1005600030EC010011800016324800013C0E0F00F3
+:1005700000EE28243C0D020010AD00113C1F80004D
+:1005800037E90100913800138FAF00102419FFFEE6
+:10059000330400FF2487000402599024000721C07F
+:1005A00012400002026F30253266FFFF0E000FDBA3
+:1005B00032A5FFFF1240FE990000202132480001C1
+:1005C0001100000E324A00048FAB0010240200011B
+:1005D00012420002026B30253266FFFF000020212C
+:1005E0000E000FDB32A5FFFF2406FFFE024690241B
+:1005F0001240FE8A00002021324A00045140000EC1
+:10060000240400018FB600102403000412430002EA
+:10061000027630253266FFFF2413FFFB32A5FFFF71
+:10062000240401000E000FDB0253A82412A0FE7B5D
+:1006300000002021240400010A0013AB00801821CF
+:100640003C0C08008D8C0024319200015240FE7356
+:100650000000202132A5FFFF36C600020E000FDB8E
+:10066000000020210A0014000000202124020003C1
+:1006700035230180A062000B0A0014CC2413BFFFB5
+:100680002404FFFE0A0014CA010440243C03800035
+:10069000346401008C85000030A2003E1440000844
+:1006A00000000000AC6000488C87000030E607C006
+:1006B00010C0000500000000AC60004CAC600050B1
+:1006C00003E0000824020001AC600054AC6000406C
+:1006D0008C880000310438001080FFF90000000011
+:1006E0002402000103E00008AC6000443C038000E9
+:1006F0008C6201B80440FFFE34670180ACE4000066
+:1007000024080001ACE00004A4E500082405000270
+:10071000A0E8000A34640140A0E5000B9483000ABD
+:1007200014C00008A4E30010ACE000243C078000E3
+:1007300034E901803C041000AD20002803E00008EB
+:10074000ACE401B88C8600043C041000ACE6002444
+:100750003C07800034E90180AD20002803E0000858
+:10076000ACE401B83C0680008CC201B80440FFFE36
+:1007700034C7018024090002ACE40000ACE40004AA
+:10078000A4E50008A0E9000A34C50140A0E9000B77
+:1007900094A8000A3C041000A4E80010ACE0002477
+:1007A0008CA30004ACE3002803E00008ACC401B84B
+:1007B0003C03900034620001008220253C0380004D
+:1007C000AC6400208C65002004A0FFFE0000000047
+:1007D00003E00008000000003C02800034430001F8
+:1007E0000083202503E00008AC44002027BDFFE083
+:1007F0003C098000AFBF0018AFB10014AFB00010CB
+:10080000352801408D10000091040009910700086F
+:1008100091050008308400FF30E600FF00061A0052
+:100820002C820081008330251040002A30A50080F2
+:10083000000460803C0D080125AD90E8018D582131
+:100840008D6A000001400008000000003C038000A9
+:10085000346201409445000A14A0001E8F91FCB838
+:100860009227000530E6000414C0001A00000000C2
+:100870000E0015E502002021922A00050200202129
+:10088000354900040E0015EFA22900059228000545
+:100890003104000414800002000000000000000D7C
+:1008A000922D0000240B002031AC00FF158B0009B5
+:1008B0003C0580008CAE01B805C0FFFE34B101805C
+:1008C000AE3000003C0F100024100005A230000BD9
+:1008D000ACAF01B80000000D8FBF00188FB100143D
+:1008E0008FB0001003E0000827BD00200200202187
+:1008F00000C028218FBF00188FB100148FB00010E6
+:10090000240600010A0015B427BD00200000000DD8
+:100910000200202100C028218FBF00188FB10014D1
+:100920008FB00010000030210A0015B427BD002050
+:1009300014A0FFE800000000020020218FBF001873
+:100940008FB100148FB0001000C028210A0015D20A
+:1009500027BD00203C0780008CEE01B805C0FFFEDB
+:1009600034F00180241F0002A21F000B34F8014064
+:10097000A60600089719000A3C0F1000A6190010DF
+:100980008F110004A6110012ACEF01B80A00163056
+:100990008FBF001827BDFFE8AFBF00100E000FD4B7
+:1009A000000000003C0280008FBF001000002021EA
+:1009B000AC4001800A0010A627BD00183084FFFF5C
+:1009C00030A5FFFF108000070000182130820001D1
+:1009D0001040000200042042006518211480FFFB33
+:1009E0000005284003E000080060102110C0000747
+:1009F000000000008CA2000024C6FFFF24A5000414
+:100A0000AC82000014C0FFFB2484000403E0000853
+:100A10000000000010A0000824A3FFFFAC86000027
+:100A200000000000000000002402FFFF2463FFFF1D
+:100A30001462FFFA2484000403E0000800000000B0
+:100A40003C03800027BDFFF834620180AFA20000A4
+:100A5000308C00FF30AD00FF30CE00FF3C0B80003B
+:100A60008D6401B80480FFFE000000008FA9000023
+:100A70008D6801288FAA00008FA700008FA40000B6
+:100A80002405000124020002A085000A8FA30000B3
+:100A9000359940003C051000A062000B8FB80000A3
+:100AA0008FAC00008FA600008FAF000027BD0008AC
+:100AB000AD280000AD400004AD800024ACC000288B
+:100AC000A4F90008A70D0010A5EE001203E000082D
+:100AD000AD6501B83C06800827BDFFE834C500803D
+:100AE000AFBF001090A700092402001230E300FFFE
+:100AF0001062000B008030218CA800500088202359
+:100B0000048000088FBF00108CAA00342404003930
+:100B10000000282100CA48230520000524060012F1
+:100B20008FBF00102402000103E0000827BD001859
+:100B30000E001689000000008FBF00102402000183
+:100B400003E0000827BD001827BDFFC8AFB2003082
+:100B5000AFB00028AFBF0034AFB1002C00A080219F
+:100B600090A5000D30A6001010C00010008090214C
+:100B70003C0280088C4400048E0300081064000CC2
+:100B800030A7000530A6000510C000932404000122
+:100B90008FBF00348FB200308FB1002C8FB000288F
+:100BA0000080102103E0000827BD003830A70005B1
+:100BB00010E0000F30AB001210C00006240400014A
+:100BC0003C0980088E0800088D2500045105009C12
+:100BD000240400388FBF00348FB200308FB1002C56
+:100BE0008FB000280080102103E0000827BD0038E6
+:100BF000240A0012156AFFE62404000102002021E5
+:100C000027A500100E000CB6AFA000101440007C09
+:100C10003C198008372400809098000833110008A0
+:100C20001220000A8FA7001030FF010013E000A47B
+:100C30008FA300148C860058006610230440000423
+:100C40003C0A8008AC8300588FA700103C0A80083B
+:100C50003548008091090008312400081480000202
+:100C600024080003000040213C1F800893F100117C
+:100C700093F9001237E600808CCC0054333800FF23
+:100C800003087821322D00FF000F708001AE28216B
+:100C900000AC582B1160006F0000000094CA005C8B
+:100CA0008CC900543144FFFF012510230082182B0A
+:100CB00014600068000000008CCB0054016518230C
+:100CC00030EC00041180006C000830808FA8001CFC
+:100CD0000068102B1040006230ED00040066102305
+:100CE0002C46008010C000020040882124110080A2
+:100CF0000E0015E5024020213C0D800835A600803D
+:100D000024070001ACC7000C90C80008001148403F
+:100D100035A70100310C007FA0CC00088E0500042F
+:100D200024AB0001ACCB0030A4D1005C8CCA003CE9
+:100D30009602000E01422021ACC400208CC3003C6E
+:100D40000069F821ACDF001C8E190004ACF900002A
+:100D50008E180008ACF800048FB10010322F000884
+:100D600055E0004793A60020A0C0004E90D8004E4A
+:100D70002411FFDFA0F8000890CF000801F17024D3
+:100D8000A0CE00088E0500083C0B80083569008065
+:100D9000AD2500388D6A00148D22003024190050D2
+:100DA00001422021AD24003491230000307F00FF58
+:100DB00013F90036264F01000E0015EF02402021E6
+:100DC00024040038000028210E0016892406000A99
+:100DD0000A0016EE240400010E000D280000202158
+:100DE0008FBF00348FB200308FB1002C8FB000283D
+:100DF000004020210080102103E0000827BD0038BA
+:100E00008E0E00083C0F800835F00080AE0E0054B6
+:100E100002402021AE0000300E0015E50000000069
+:100E2000920D00250240202135AC00200E0015EF68
+:100E3000A20C00250E000CAC024020212404003836
+:100E40002405008D0E001689240600120A0016EEF5
+:100E50002404000194C5005C0A00172930A3FFFF99
+:100E60002407021811A0FF9E00E610238FAE001C7D
+:100E70000A00173101C610230A00172E2C6202182F
+:100E8000A0E600080A00175B8E0500082406FF8014
+:100E900001E6C0243C118000AE3800288E0D000809
+:100EA00031E7007F3C0E800C00EE6021AD8D00E04C
+:100EB0008E080008AF8C00340A001767AD8800E484
+:100EC000AC800058908500082403FFF700A3382465
+:100ED000A08700080A00170C8FA700103C05080027
+:100EE00024A55F043C04080024846E503C020800E2
+:100EF00024425F0C240300063C010801AC2594F851
+:100F00003C010801AC2494FC3C010801AC22950092
+:100F10003C010801A023950403E000080000000044
+:100F200003E00008240200013C028000308800FF3A
+:100F3000344701803C0680008CC301B80460FFFE8A
+:100F4000000000008CC501282418FF803C0D800A99
+:100F500024AF010001F8702431EC007FACCE0024F6
+:100F6000018D2021ACE50000948B00EA350960007A
+:100F700024080002316AFFFFACEA000424020001E9
+:100F8000A4E90008A0E8000BACE000243C07100036
+:100F9000ACC701B8AF84003403E00008AF85006837
+:100FA000938800448F89005C8F82003430C600FF34
+:100FB0000109382330E900FF0122182130A500FF84
+:100FC0002468008810C000020124382100803821E4
+:100FD00030E400031480000330AA00031140000D28
+:100FE000312B000310A000090000102190ED00003B
+:100FF000244E000131C200FF0045602BA10D00000E
+:1010000024E700011580FFF92508000103E000082E
+:10101000000000001560FFF30000000010A0FFFBBF
+:10102000000010218CF8000024590004332200FF36
+:101030000045782BAD18000024E7000415E0FFF907
+:101040002508000403E00008000000009385004428
+:10105000938800548F87005C000432003103007FC6
+:1010600000E5102B30C47F001040000F00642825DD
+:101070008F8400343C0980008C8A00ECAD2A00A4E7
+:101080003C03800000A35825AC6B00A08C6C00A032
+:101090000580FFFE000000008C6D00ACAC8D00EC04
+:1010A00003E000088C6200A80A0018198F8400343D
+:1010B000938800553C02800000805021310300FEDF
+:1010C000A383005530ABFFFF30CC00FF30E7FFFFBC
+:1010D000344801803C0980008D2401B80480FFFE63
+:1010E0008F8D006824180016AD0D00008D2201249C
+:1010F0008F8D0034AD0200048D590020A507000833
+:10110000240201C4A119000AA118000B952F012087
+:101110008D4E00088D470004978300588D59002498
+:1011200001CF302100C7282100A320232418FFFF6E
+:10113000A504000CA50B000EA5020010A50C0012C2
+:10114000AD190018AD18002495AF00E83C0B100055
+:101150002407FFF731EEFFFFAD0E00288DAC0084B1
+:10116000AD0C002CAD2B01B88D46002000C7282403
+:1011700003E00008AD4500208F880034008058212E
+:1011800030E7FFFF910900D63C02800030A5FFFF49
+:10119000312400FF00041A000067502530C600FF0C
+:1011A000344701803C0980008D2C01B80580FFFE8A
+:1011B0008F820068240F0017ACE200008D390124F3
+:1011C000ACF900048D780020A4EA0008241901C4B9
+:1011D000A0F8000AA0EF000B952301208D6E0008F7
+:1011E0008D6D00049784005801C35021014D60218A
+:1011F00001841023A4E2000CA4E5000EA4F9001061
+:10120000A4E60012ACE000148D780024240DFFFF4A
+:10121000ACF800188D0F007CACEF001C8D0E007830
+:101220003C0F1000ACEE0020ACED0024950A00BE8F
+:10123000240DFFF73146FFFFACE60028950C008037
+:101240009504008231837FFF0003CA003082FFFFD4
+:101250000322C021ACF8002CAD2F01B8950E0082FE
+:101260008D6A002000AE3021014D2824A5060082A1
+:1012700003E00008AD6500203C0280003445018099
+:101280003C0480008C8301B80460FFFE8F8A00401C
+:10129000240600199549001C3128FFFF000839C0B9
+:1012A000ACA70000A0A6000B3C05100003E000085E
+:1012B000AC8501B88F8700480080402130C400FF12
+:1012C0003C0680008CC201B80440FFFE8F89006894
+:1012D0009383006434996000ACA90000A0A30005CA
+:1012E0008CE20010240F00022403FFF7A4A20006E2
+:1012F000A4B900088D180020A0B8000AA0AF000B08
+:101300008CEE0000ACAE00108CED0004ACAD00140F
+:101310008CEC001CACAC00248CEB0020ACAB0028A7
+:101320008CEA002C3C071000ACAA002C8D0900248C
+:10133000ACA90018ACC701B88D05002000A320247B
+:1013400003E00008AD0400208F86003427BDFFE0D5
+:10135000AFB10014AFBF0018AFB0001090C300D4FD
+:1013600030A500FF30620020104000080080882176
+:101370008CCB00D02409FFDF256A0001ACCA00D065
+:1013800090C800D401093824A0C700D414A000409C
+:101390003C0C80008F840034908700D42418FFBF59
+:1013A0002406FFEF30E3007FA08300D4979F00580E
+:1013B0008F82005C8F8D003403E2C823A799005808
+:1013C000A5A000BC91AF00D401F87024A1AE00D458
+:1013D0008F8C0034A18000D78F8A0034A540008212
+:1013E000AD4000EC914500D400A65824A14B00D498
+:1013F0008F9000308F84005C97860058020428216B
+:1014000010C0000FAF850030A38000543C0780005F
+:101410008E2C000894ED01208E2B0004018D5021AC
+:10142000014B8021020620233086FFFF30C8000FC9
+:10143000390900013131000116200009A388005448
+:10144000938600448FBF00188FB100148FB0001036
+:1014500027BD0020AF85006003E00008AF86005C78
+:1014600000C870238FBF0018938600448FB100140A
+:101470008FB0001034EF0C00010F282127BD002091
+:10148000ACEE0084AF85006003E00008AF86005C2E
+:1014900035900180020028210E0018A62406008243
+:1014A0008F840034908600D430C5004050A0FFBA2D
+:1014B000A38000648F8500483C0680008CCD01B875
+:1014C00005A0FFFE8F8900682408608224070002BF
+:1014D000AE090000A6080008A207000B8CA30008B4
+:1014E0003C0E1000AE0300108CA2000CAE020014E3
+:1014F0008CBF0014AE1F00188CB90018AE19002460
+:101500008CB80024AE1800288CAF0028AE0F002C39
+:10151000ACCE01B80A0018DFA38000648F8A0034C3
+:1015200027BDFFE0AFB10014AFB000108F88005CA2
+:10153000AFBF001893890038954200BC30D100FF3E
+:101540000109182B0080802130AC00FF3047FFFFDD
+:101550000000582114600003310600FF01203021F3
+:1015600001095823978300580068202B1480002716
+:101570000000000010680056241900011199006352
+:1015800034E708803165FFFF0E0018570200202164
+:101590008F8300683C07800034E601803C058000B2
+:1015A0008CAB01B80560FFFE240A00188F8400345C
+:1015B000ACC30000A0CA000B948900BE3C08100018
+:1015C000A4C90010ACC00030ACA801B8948200805F
+:1015D00024430001A4830080949F00803C060800FF
+:1015E0008CC6318833EC7FFF1186005E000000005E
+:1015F00002002021022028218FBF00188FB1001483
+:101600008FB000100A0018CB27BD0020914400D4F1
+:101610002403FF8000838825A15100D497840058BB
+:101620003088FFFF51000023938C00388F850034F1
+:101630002402EFFF008B782394AE00BC0168502B8E
+:1016400031E900FF01C26824A4AD00BC514000395B
+:10165000010058213C1F800037E601008CD80004AF
+:101660003C190001031940245500000134E74000F3
+:101670008E0A00202403FFFB2411000101432024D3
+:10168000AE0400201191002D34E7800002002021DB
+:10169000012030210E0018573165FFFF9787005851
+:1016A0008F89005CA780005801278023AF90005CE1
+:1016B000938C00388F8B00348FBF00188FB10014CB
+:1016C0008FB0001027BD002003E00008A16C00D7F8
+:1016D0003C0D800035AA01008D4800043C09000142
+:1016E0000109282454A0000134E740008E0F002097
+:1016F0002418FFFB34E7800001F87024241900014E
+:10170000AE0E00201599FF9F34E7088002002021CB
+:101710000E0018253165FFFF02002021022028213C
+:101720008FBF00188FB100148FB000100A0018CBC3
+:1017300027BD00200A00198E000048210200202148
+:10174000012030210E0018253165FFFF97870058D2
+:101750008F89005CA7800058012780230A0019A503
+:10176000AF90005C948C0080241F8000019F302487
+:10177000A4860080908B0080908F0080316700FFEE
+:101780000007C9C20019C027001871C031ED007FE1
+:1017900001AE2825A08500800A00197602002021CC
+:1017A000938500642403000127BDFFE800A33004F3
+:1017B0002CA20020AFB00010AFBF001400C0182151
+:1017C000104000132410FFFE3C0708008CE7319006
+:1017D00000E610243C088000350501801440000517
+:1017E000240600848F890034240A00042410FFFF9B
+:1017F000A12A00FC0E0018A6000000000200102123
+:101800008FBF00148FB0001003E0000827BD001840
+:101810003C0608008CC631940A0019EE00C310245F
+:101820008F87004027BDFFE0AFB20018AFB10014B2
+:10183000AFB00010AFBF001C30D000FF90E6000D2D
+:1018400000A088210080902130C5007FA0E5000D18
+:101850008F8500348E2300188CA200D01062002ED9
+:10186000240A000E0E0019E1A38A00642409FFFF78
+:10187000104900222404FFFF520000200000202114
+:101880008E2600003C0C001000CC58241560003956
+:101890003C0E000800CE682455A0003F02402021E5
+:1018A0003C18000200D880241200001F3C0A0004EB
+:1018B0008F8700408CE200148CE300108CE500144C
+:1018C0000043F82303E5C82B132000050240202124
+:1018D0008E24002C8CF10010109100310240202148
+:1018E00024020012A38200640E0019E12412FFFFFB
+:1018F000105200022404FFFF000020218FBF001CB3
+:101900008FB200188FB100148FB00010008010212A
+:1019100003E0000827BD002090A800D43504002073
+:101920000A001A17A0A400D400CA48241520000BEE
+:101930008F8B00408F8D00408DAC00101580000B08
+:10194000024020218E2E002C51C0FFEC00002021EF
+:10195000024020210A001A32240200178D6600106E
+:1019600050C0FFE600002021024020210A001A3268
+:101970002402001102402021240200150E0019E16A
+:10198000A3820064240FFFFF104FFFDC2404FFFF3D
+:101990000A001A218E2600000A001A582402001498
+:1019A0003C08000400C8382450E0FFD40000202187
+:1019B000024020210A001A32240200138F850034CD
+:1019C00027BDFFD8AFB3001CAFB20018AFB10014F1
+:1019D000AFB00010AFBF002090A700D48F90004898
+:1019E0002412FFFF34E2004092060000A0A200D4BF
+:1019F0008E030010008098211072000630D1003F45
+:101A00002408000D0E0019E1A3880064105200257F
+:101A10002404FFFF8F8A00348E0900188D4400D003
+:101A20001124000702602021240C000E0E0019E191
+:101A3000A38C0064240BFFFF104B001A2404FFFF4B
+:101A400024040020122400048F8D003491AF00D4B0
+:101A500035EE0020A1AE00D48F85005010A00019F3
+:101A6000000000001224004A8F9800348F92FCB8C6
+:101A7000971000809651000A523000488F93003C26
+:101A80003C1F08008FFF318C03E5C82B1720001E78
+:101A900002602021000028210E00194024060001C8
+:101AA000000020218FBF00208FB3001C8FB20018D0
+:101AB0008FB100148FB000100080102103E00008E7
+:101AC00027BD00285224002A8E0500148F8400347C
+:101AD000948A008025490001A489008094880080B0
+:101AE0003C0208008C42318831077FFF10E2000E73
+:101AF00000000000026020210E0018CB2405000128
+:101B00000A001AA2000020212402002D0E0019E173
+:101B1000A38200642403FFFF1443FFE12404FFFFBA
+:101B20000A001AA38FBF002094990080241F800010
+:101B300024050001033FC024A498008090920080F7
+:101B4000908E0080325100FF001181C20010782772
+:101B5000000F69C031CC007F018D5825A08B00801B
+:101B60000E0018CB026020210A001AA200002021DA
+:101B70002406FFFF54A6FFD68F8400340260202184
+:101B80000E0018CB240500010A001AA20000202133
+:101B9000026020210A001ABC2402000A2404FFFD6E
+:101BA0000A001AA2AF93005C8F88003427BDFFE8BB
+:101BB000AFB00010AFBF0014910A00D48F87004867
+:101BC00000808021354900408CE60010A10900D436
+:101BD0003C0208008C4231B030C53FFF00A2182BF8
+:101BE000106000078F85004C240DFF8090AE000D23
+:101BF00001AE6024318B00FF156000080006C3822F
+:101C0000020020212403000D8FBF00148FB00010AC
+:101C100027BD00180A0019E1A383006433060003FE
+:101C2000240F000254CFFFF70200202194A2001CD1
+:101C30008F85003424190023A4A200E88CE800005A
+:101C400000081E02307F003F13F900353C0A008374
+:101C50008CE800188CA600D01106000800000000D7
+:101C60002405000E0E0019E1A38500642407FFFF80
+:101C7000104700182404FFFF8F85003490A900D47A
+:101C800035240020A0A400D48F8C0040918E000D3C
+:101C900031CD007FA18D000D8F8300501060001C9E
+:101CA000020020218F84004C8C9800100303782BB5
+:101CB00011E0000D2419001802002021A3990064EE
+:101CC0000E0019E12410FFFF105000022404FFFF52
+:101CD000000020218FBF00148FB000100080102161
+:101CE00003E0000827BD00188C8600108F9F00407D
+:101CF0000200202100C31023AFE2001024050001E0
+:101D00000E001940240600010A001B2E00002021AD
+:101D10000E0018CB240500010A001B2E0000202114
+:101D2000010A5824156AFFD98F8C0040A0A600FC38
+:101D30000A001B1BA386005630A500FF24060001E5
+:101D400024A9000100C9102B1040000C0000402104
+:101D5000240A000100A61823308B000124C60001CC
+:101D6000006A3804000420421160000200C9182BE8
+:101D7000010740251460FFF800A6182303E00008BF
+:101D80000100102127BDFFD8AFB000188F90004888
+:101D9000AFB1001CAFBF00202403FFFF2411002FB0
+:101DA000AFA30010920600002405000826100001D1
+:101DB000006620260E001B47308400FF00021E0034
+:101DC0003C021EDC34466F410A001B6F00001021EC
+:101DD00010A00009008018212445000130A2FFFF57
+:101DE0002C4500080461FFFA0003204000862026ED
+:101DF00014A0FFF9008018210E001B4724050020C5
+:101E00008FA300102629FFFF313100FF000342029B
+:101E1000240700FF1627FFE20102182600035027BF
+:101E2000AFAA0014AFAA00100000302127A80010AC
+:101E300027A7001400E6782391ED000324CE0001CB
+:101E400000C8602131C600FF2CCB00041560FFF9EB
+:101E5000A18D00008FA200108FBF00208FB1001C49
+:101E60008FB0001803E0000827BD002827BDFFD071
+:101E7000AFB3001CAFB00010AFBF0028AFB5002457
+:101E8000AFB40020AFB20018AFB100143C0C80001A
+:101E90008D880128240FFF803C06800A2510010050
+:101EA000250B0080020F68243205007F016F70242B
+:101EB000AD8E009000A62821AD8D002490A600FCD8
+:101EC0003169007F3C0A8004012A1821A38600564C
+:101ED0009067007C00809821AF83002C30E20002E4
+:101EE000AF880068AF85003400A0182114400002BC
+:101EF0002404003424040030A38400448C7200DCE9
+:101F000030D100FF24040004AF92005C12240004CE
+:101F1000A38000648E7400041680001E3C088000BC
+:101F20009386005530C7000150E0000F8F86005C9B
+:101F30008CA400848CA800842413FF800093602468
+:101F4000000C49403110007F013078253C192000F9
+:101F500001F9682530DF00FE3C038000AC6D0830DD
+:101F6000A39F00558F86005C8FBF00288FB500248B
+:101F70008FB400208FB3001C8FB200188FB10014F3
+:101F80008FB000102402000127BD003003E00008DC
+:101F9000ACA600DC8E7F0008950201208E67001041
+:101FA00003E2C8213326FFFF30D8000F33150001AC
+:101FB000AF87003016A00058A398005435090C00D4
+:101FC0000309382100D81823AD030084AF870060CF
+:101FD0008E6A00043148FFFF1100007EA78A005876
+:101FE00090AC00D42407FF8000EC302430CB00FFFD
+:101FF0001560004B97860058938E0056240D000202
+:1020000030D5FFFF11CD02A20000A0218F85005C1A
+:1020100002A5802B160000BC938800443C11800070
+:1020200096240120310400FF148500888F8400600D
+:102030008F980030331200035640008530A500FF12
+:102040008F900060310C00FF24060034118600954B
+:10205000AF90004892040004148001198F8E003460
+:10206000A38000388E0D00048DC800D83C0600FF08
+:1020700034CCFFFF01AC30240106182B1460012181
+:10208000AF8600508F87005C97980058AF87003C60
+:102090000307402310C000C7A78800588F91002C69
+:1020A00030C3000300035823922A007C31710003DF
+:1020B00002261021000A208230920001001248807E
+:1020C00000492821311FFFFF03E5C82B1320012001
+:1020D0008F8800348F8500308F8800601105025A88
+:1020E0003C0E3F018E0600003C0C250000CE68240B
+:1020F00011AC01638F84004830E500FF0E0017E14A
+:10210000000030218F8800348F87005C8F8500307D
+:102110000A001D4E8F8600500A001BEDAF8700603D
+:1021200090AC00D400EC2024309000FF1200001688
+:102130009386005590B5008890B400D724A80088F5
+:1021400032A2003F2446FFE02CD10020A3940038A7
+:102150001220000CAF880048240E000100CE20049D
+:10216000308A00191540012B3C06800034D800024B
+:10217000009858241560022E309200201640023438
+:10218000000000009386005530CE000111C0000F02
+:10219000978800588CA900848CAF00842410FF809D
+:1021A0000130C8240019194031ED007F006D382539
+:1021B0003C1F200000FF902530CB00FE3C18800023
+:1021C000AF120830A38B0055978800581500FF8484
+:1021D000000000008E630020306C00041180FF516D
+:1021E000938600552404FFFB006430243C038000E8
+:1021F000AE660020346601808C7301B80660FFFE75
+:102200008F8E0068346A01003C150001ACCE0000DE
+:102210008C62012424076085ACC200048D54000444
+:1022200002958824522000012407608324120002B2
+:102230003C1810003C0B8000A4C70008A0D2000B83
+:10224000AD7801B80A001BC29386005530A500FF87
+:102250000E0017E1240600018F8800683C0580000D
+:1022600034A909002502018893880044304A0007F8
+:10227000304B00783C0340802407FF800163C82571
+:10228000014980210047F824310C00FF2406003466
+:10229000ACBF0800AF900048ACB908105586FF6E7F
+:1022A000920400048F8400348E110030908E00D48C
+:1022B00031CD001015A000108F83005C2C6F00053D
+:1022C00015E000E400000000909800D42465FFFCB5
+:1022D000331200101640000830A400FF8F9F0060EA
+:1022E0008F99003013F900043887000130E20001B3
+:1022F000144001C8000000000E001B5A000000003E
+:102300000A001D8F000000008F84006030C500FFB0
+:102310000E0017E124060001938E0044240A0034C5
+:1023200011CA00A08F8500348F86005C9783005807
+:102330003062FFFF00C28823AF91005CA780005885
+:102340001280FF90028018212414FFFD5474FFA214
+:102350008E6300208E6900042403FFBF240BFFEF6F
+:102360000135C823AE79000490AF00D431ED007F71
+:10237000A0AD00D48E6600208F980034A78000584E
+:1023800034DF0002AE7F0020A70000BC931200D40F
+:1023900002434024A30800D48F950034AEA000EC83
+:1023A00092AE00D401CB5024A2AA00D40A001C6E25
+:1023B0008F8500348F910030AF80005C0227582158
+:1023C000AF8B0030000020212403FFFF108301B4F5
+:1023D0008F8500348E0C00103C0D08008DAD31B09F
+:1023E0009208000031843FFF008D802B12000023F3
+:1023F000310D003F3C1908008F3931A88F9F0068CC
+:10240000000479802408FF80033F2021008FC82129
+:10241000938500550328F8243C0600803C0F80007B
+:1024200034D80001001F91403331007F8F86003483
+:102430000251502535EE0940332B00783330000728
+:102440003C0310003C02800C01789025020E4821CC
+:102450000143C0250222382134AE0001ADFF08043B
+:10246000AF89004CADF20814AF870040ADFF0028E3
+:10247000ACD90084ADF80830A38E00559383005684
+:10248000240700035067002825A3FFE0240C000167
+:10249000146CFFAB8F8500342411002311B100842C
+:1024A000000000002402000B026020210E0019E150
+:1024B000A38200640040A0210A001CC98F8500345B
+:1024C00002602021240B000C0E0019E1A38B006494
+:1024D000240AFFFF104AFFBC2404FFFF8F8E003444
+:1024E000A38000388E0D00048DC800D83C0600FF84
+:1024F00034CCFFFF01AC30240106182B1060FEE144
+:10250000AF86005002602021241200190E0019E14C
+:10251000A3920064240FFFFF104FFFAB2404FFFFC2
+:102520000A001C1A8F8600502C7400201280FFDED7
+:102530002402000B000328803C110801263192EC94
+:1025400000B148218D2D000001A00008000000000E
+:102550008F85003000A7102193850038AF820030AE
+:1025600002251821A3830038951F00BC02262821CC
+:1025700037F91000A51900BC5240FF92AF85005CEE
+:10258000246A0004A38A0038950900BC24A400042E
+:10259000AF84005C35322000A51200BC0A001CEBA1
+:1025A000000020218F86005C2CCB00051560FF60A9
+:1025B000978300583072FFFF00D240232D1800058A
+:1025C00013000003306400FF24DFFFFC33E400FF4E
+:1025D0008F8500608F86003010A60004388F0001C0
+:1025E00031ED000115A00138000000008F84003497
+:1025F000908C00D435870010A08700D48F850034DC
+:102600008F86005C97830058ACA000EC0A001CC6C3
+:102610003062FFFF8CAA00848CB500843C0410005B
+:10262000014710240002894032B4007F0234302573
+:1026300000C460253C0880002405000102602021C0
+:10264000240600010E001940AD0C08300A001C5A87
+:102650008F8500348C8200EC1222FE7E02602021E5
+:1026600024090005A38900640E0019E12411FFFF6D
+:102670001451FE782404FFFF0A001CEC2403FFFF22
+:102680008F8F00488F8800348DF80000AD180088C7
+:102690008DE70010AD0700988F87005C0A001D4E83
+:1026A0008F8600502407FFFF1187000500000000FF
+:1026B0000E001AE3026020210A001D270040A0211D
+:1026C0000E001A68026020210A001D270040A02188
+:1026D0008F9000483C0908008D2931B08E11001000
+:1026E00032323FFF0249682B11A0000C240AFF8000
+:1026F0008F85004C90AE000D014E1024304C00FF31
+:1027000011800007026020210011C38233030003FF
+:10271000240B0001106B0105000000000260202165
+:102720002418000D0E0019E1A39800640040202138
+:102730008F8500340A001CC90080A0218F900048BA
+:102740003C0A08008D4A31B08F85004C8E04001081
+:102750000000A0218CB1001430823FFF004A602BA2
+:102760008CB200205180FFEE0260202190B8000D55
+:10277000240BFF800178702431C300FF5060FFE814
+:1027800002602021000443823106000314C0FFE4EC
+:102790000260202194BF001C8F9900348E0600280F
+:1027A000A73F00E88CAF0010022F202314C401398A
+:1027B000026020218F83005000C36821022D382B36
+:1027C00014E00135240200188F8A00408F82002C0B
+:1027D000024390218D4B001001637023AD4E001019
+:1027E000AD5200208C4C00740192282B14A001568D
+:1027F000026020218F84004C8E0800248C860024E7
+:1028000011060007026020212419001C0E0019E1A6
+:10281000A3990064240FFFFF104FFFC52404FFFF9E
+:102820008F8400408C87002424FF0001AC9F00248B
+:10283000125101338F8D002C8DB100741232013092
+:102840003C0B00808E0E000001CB5024154000751B
+:10285000000000008E0300142411FFFF1071000619
+:10286000026020212418001B0E0019E1A3980064C7
+:102870001051FFAF2404FFFF8E0300003C0800014D
+:102880000068302410C000133C0400800064A024C1
+:102890001680000902002821026020212419001A54
+:1028A0000E0019E1A3990064240FFFFF104FFFA051
+:1028B0002404FFFF02002821026020210E001A01DB
+:1028C000240600012410FFFF1050FF992404FFFF8D
+:1028D000241400018F9F00400260202102803021DB
+:1028E00097F100342405000126270001A7E70034F2
+:1028F0000E00194000000000000020218F850034E8
+:102900000A001CC90080A0218F9000483C140800D8
+:102910008E9431B08E07001030E83FFF0114302B49
+:1029200010C000618F86004C241FFF8090C5000DF1
+:1029300003E52024309200FF5240005C0260202119
+:102940008F8D005011A0000700078B828F85003407
+:102950008F89FCB894AF00809539000A132F00F6D8
+:102960008F87003C322C00031580006300000000BC
+:1029700092020002104000D7000000008E0A0024DE
+:10298000154000D8026020219204000324060002B2
+:10299000308800FF15060005308500FF8F94005039
+:1029A000528000F202602021308500FF38AD001017
+:1029B0002DA400012CBF000103E4302502002821D2
+:1029C0000E001A01026020212410FFFF105000BEEB
+:1029D0008F8500348F830050106000C424050001EF
+:1029E0003C1908008F39318C0323782B15E000B196
+:1029F0002409002D02602021000028210E0019402A
+:102A0000240600018F850034000018210A001CC92B
+:102A10000060A0210E00180C000000000A001D8FAD
+:102A200000000000AC8000200A001E0F8E0300147E
+:102A300000002821026020210E0019402406000118
+:102A40000A001C5A8F8500340A001D4E8F880034FE
+:102A50008CB000848CB900843C0310000207482429
+:102A600000096940332F007F01AFF82503E32825D3
+:102A7000ACC5083091070001240500010260202147
+:102A80000E00194030E600010A001C5A8F85003400
+:102A9000938F00442403FFFD0A001CCBAF8F005C22
+:102AA0000A001CCB2403FFFF026020212410000D2C
+:102AB0000E0019E1A3900064004018218F850034B6
+:102AC0000A001CC90060A0210E00180C00000000C4
+:102AD000978300588F86005C3070FFFF00D048233A
+:102AE0002D3900051320FE128F850034ACA200ECB6
+:102AF0000A001CC63062FFFF90C3000D307800084A
+:102B00005700FFA29204000302602021240200105B
+:102B10000E0019E1A38200642403FFFF5443FF9BCE
+:102B2000920400030A001EA98F85003490A8000DAE
+:102B30003106000810C000958F9400501680009E4A
+:102B4000026020218E0F000C8CA4002055E40005AB
+:102B5000026020218E1F00088CB9002413F9003A6E
+:102B600002602021240200200E0019E1A3820064EB
+:102B70002405FFFF1045FEEE2404FFFF8F8F004069
+:102B8000240CFFF72403FF8091E9000D3C14800E14
+:102B90003C0B8000012CC824A1F9000D8F8F002C64
+:102BA0003C0708008CE731AC8F8D006895E5007814
+:102BB0008F99004000ED902130BF7FFF001F204023
+:102BC0000244302130C8007F00C3C02401147021AA
+:102BD000AD78002CA5D100008F2A002825420001E5
+:102BE000AF2200288F29002C8E0C002C012C68218C
+:102BF000AF2D002C8E07002CAF2700308E0500145F
+:102C0000AF250034973F003A27E40001A724003A9B
+:102C100095F200783C1008008E1031B02643000178
+:102C200030717FFF1230005C006030218F83002CF8
+:102C300002602021240500010E0018CBA466007854
+:102C40000A001E38000020218E0700142412FFFF06
+:102C500010F200638F8C00348E0900188D8D00D027
+:102C6000152D005D026020218E0A00248CA2002810
+:102C700011420053240200210E0019E1A3820064D6
+:102C80001452FFBE2404FFFF8F8500340A001CC9C4
+:102C90000080A0212402001F0E0019E1A38200641D
+:102CA0002409FFFF1049FEA22404FFFF0A001DEBC8
+:102CB0008F830050026020210E0019E1A389006477
+:102CC0001450FF518F8500342403FFFF0A001CC9F4
+:102CD0000060A0218CCE00248E0B0024116EFF2AF0
+:102CE000026020210A001EBD2402000F0E0018CB36
+:102CF000026020218F8500340A001E7C000018210C
+:102D00008E0900003C050080012590241640FF45F7
+:102D10002402001A026020210E0019E1A38200643F
+:102D2000240CFFFF144CFECB2404FFFF8F850034DE
+:102D30000A001CC90080A0212403FFFD0060A0211F
+:102D40000A001CC9AF87005C2418001D0E0019E1A1
+:102D5000A39800642403FFFF1443FEA62404FFFF8E
+:102D60008F8500340A001CC90080A0212412002C89
+:102D70000E0019E1A39200642403FFFF1043FF50EB
+:102D80008F8500340A001E63920400030260202134
+:102D90000A001ED324020024240B8000006B702440
+:102DA00031CAFFFF000A13C2305100FF0011802713
+:102DB0000A001F04001033C00A001ED3240200279B
+:102DC0008E0600288CAE002C10CE00080260202158
+:102DD0000A001F172402001F0A001F172402000EFA
+:102DE000026020210A001F17240200258E04002CF7
+:102DF0001080000D8F83002C8C7800740304582BF6
+:102E00005560000C026020218CA800140086A021CF
+:102E10000114302B10C0FF5A8F8F00400260202118
+:102E20000A001F1724020022026020210A001F1737
+:102E3000240200230A001F172402002627BDFFD802
+:102E4000AFB3001CAFB10014AFBF0020AFB2001889
+:102E5000AFB000103C0280008C5201408C4B014806
+:102E60003C048000000B8C02322300FF317300FF12
+:102E70008C8501B804A0FFFE34900180AE120000E2
+:102E80008C8701442464FFF0240600022C83001385
+:102E9000AE070004A6110008A206000BAE13002422
+:102EA0001060004F8FBF0020000448803C0A0801DA
+:102EB000254A936C012A40218D04000000800008FF
+:102EC000000000003C0308008C6331A831693FFF1B
+:102ED0000009998000728021021370212405FF806F
+:102EE000264D0100264C00803C02800031B1007F5D
+:102EF0003198007F31CA007F3C1F800A3C19800452
+:102F00003C0F800C01C5202401A530240185382404
+:102F1000014F1821AC460024023F402103194821EB
+:102F2000AC470090AC440028AF830040AF88003429
+:102F3000AF89002C0E001897016080213C038000AF
+:102F40008C6B01B80560FFFE8F8700408F860034D0
+:102F50003465018090E8000DACB20000A4B000061A
+:102F6000000826000004160300029027001227C262
+:102F70001080008124C20088241F6082A4BF000842
+:102F8000A0A0000524020002A0A2000B8F8B002C41
+:102F9000000424003C08270000889025ACB20010F3
+:102FA000ACA00014ACA00024ACA00028ACA0002C65
+:102FB0008D6900382413FF80ACA9001890E3000D40
+:102FC00002638024320500FF10A000058FBF00209F
+:102FD00090ED000D31AC007FA0EC000D8FBF002004
+:102FE0008FB3001C8FB200188FB100148FB0001087
+:102FF0003C0A10003C0E800027BD002803E00008BA
+:10300000ADCA01B8265F01002405FF8033F8007FB8
+:103010003C06800003E578243C19800A031920212E
+:10302000ACCF0024908E00D400AE682431AC00FFF9
+:1030300011800024AF840034248E008895CD0012C6
+:103040003C0C08008D8C31A831AB3FFF0192482128
+:10305000000B5180012A402101052024ACC4002826
+:103060003107007F3C06800C00E620219083000D94
+:1030700000A31024304500FF10A0FFD8AF8400400B
+:103080009098000D330F001015E0FFD58FBF002082
+:103090000E001897000000003C0380008C7901B8F6
+:1030A0000720FFFE00000000AE1200008C7F0144EC
+:1030B000AE1F0004A611000824110002A211000B8B
+:1030C000AE1300243C13080192739528327000015E
+:1030D0005200FFC38FBF00200E0020D402402021E9
+:1030E0000A001FF18FBF00203C1260008E452C08A3
+:1030F0003C03F0033462FFFF00A2F824AE5F2C080B
+:103100008E582C083C1901C003199825AE532C0881
+:103110000A001FF18FBF0020264D010031AF007F54
+:103120003C10800A240EFF8001F0282101AE6024AB
+:103130003C0B8000AD6C00241660FFA8AF85003406
+:1031400024110003A0B100FC0A001FF18FBF002072
+:1031500026480100310A007F3C0B800A2409FF80C9
+:10316000014B3021010920243C078000ACE40024FD
+:103170000A001FF0AF860034944E0012320C3FFF5D
+:1031800031CD3FFF15ACFF7D241F608290D900D464
+:103190002418FF800319782431EA00FF1140FF77DB
+:1031A0000000000024070004A0C700FC8F87004037
+:1031B000241160842406000DA4B10008A0A6000517
+:1031C0000A001FDB240200023C0400012484951441
+:1031D00024030014240200FE3C010800AC2431EC5E
+:1031E0003C010800AC2331E83C010801A4229530E1
+:1031F0003C0408012484953000001821006430212B
+:10320000A0C30004246300012C6500FF54A0FFFC50
+:10321000006430213C07080024E7010003E00008B7
+:10322000AF87007400A058210080482100001021C1
+:1032300014A00012000050210A0020D0000000005D
+:103240003C010801A42095303C05080194A5953067
+:103250008F8200743C0C0801258C953000E2182107
+:1032600000AC2021014B302BA0890004000010216C
+:10327000A460000810C00039010048218F86007446
+:103280000009384000E940210008388000E6282184
+:1032900090A8000B90B9000A000820400088102177
+:1032A000000218800066C021A319000A8F850074EF
+:1032B00000E5782191EE000A91E6000B000E6840CF
+:1032C00001AE6021000C208000851021A046000B7B
+:1032D0003C0308019063952A106000222462FFFFDE
+:1032E0008F8300343C010801A022952A906C00FFD6
+:1032F0001180000400000000906E00FF25CDFFFF4C
+:10330000A06D00FF3C190801973995302723000173
+:103310003078FFFF2F0F00FF11E0FFC9254A0001A1
+:103320003C010801A42395303C05080194A5953083
+:103330008F8200743C0C0801258C953000E2182126
+:1033400000AC2021014B302BA0890004000010218B
+:10335000A460000814C0FFC90100482103E0000870
+:103360000000000003E000082402000227BDFFE087
+:10337000248501002407FF80AFB00010AFBF001804
+:10338000AFB1001400A718243C10800030A4007FC7
+:103390003C06800A008628218E110024AE030024FA
+:1033A00090A200FF14400008AF850034A0A00009DF
+:1033B0008FBF0018AE1100248FB100148FB0001021
+:1033C00003E0000827BD002090A900FD90A800FFA1
+:1033D000312400FF0E002082310500FF8F8500346C
+:1033E0008FBF0018A0A00009AE1100248FB10014F7
+:1033F0008FB0001003E0000827BD002027BDFFD0DC
+:10340000AFB20020AFB1001CAFB00018AFBF002CAE
+:10341000AFB40028AFB300243C09800095330116F7
+:1034200035320C00952F011A3271FFFF02328021D4
+:103430008E08000431EEFFFF248B0100010E68218D
+:10344000240CFF8025A5FFFF016C50243166007F0E
+:103450003C07800AAD2A002400C73021AF850070E8
+:10346000AF88006C3C010801A020952990C3000999
+:103470000200D02100809821306300FF28620005FF
+:1034800010400048AF860034286400021480008E8B
+:1034900024140001240D00053C010801A02D950D08
+:1034A00090CC00FD3C010801A020950E3C010801D4
+:1034B000A020950F90CB000A240AFF80318500FFE1
+:1034C000014B4824312700FF10E0000C0000582178
+:1034D0003C128008365100808E2F00308CD0005C6A
+:1034E00001F0702305C0018E8F87006C90D4000A14
+:1034F0003284007FA0C4000A8F8600343C1180080B
+:10350000363000808E0F00308F87006C00EF702304
+:1035100019C000EE0000000090D40009241200023F
+:10352000328400FF10920247000000008CC2005855
+:1035300000E2F82327F9FFFF1B2001300000000004
+:1035400090C500092408000430A300FF106800574C
+:10355000240A00013C010801A02A950D90C900FF32
+:10356000252700013C010801A027950C3C03080118
+:103570009063950D240600051066006A2C780005FE
+:10358000130000C4000090210003F8803C040801EF
+:10359000248493B803E4C8218F25000000A000080C
+:1035A00000000000241800FF1078005C00000000FC
+:1035B00090CC000A90CA00093C080801910895299E
+:1035C0003187008000EA48253C010801A0299514B4
+:1035D00090C500FD3C1408019294952A3111000118
+:1035E0003C010801A025951590DF00FE3C01080173
+:1035F000A03F951690D200FF3C010801A03295171C
+:103600008CD900543C010801AC3995188CD0005875
+:103610003C010801AC30951C8CC3005C3C010801E6
+:10362000AC3495243C010801AC23952016200008F9
+:103630008FBF002C8FB400288FB300248FB20020DE
+:103640008FB1001C8FB0001803E0000827BD0030C8
+:103650003C1180009624010E0E000FD43094FFFF21
+:103660003C0B08018D6B952C0260382102802821CB
+:10367000AE2B01803C1308018E73950C0160202154
+:10368000240600830E001046AFB300108FBF002C3D
+:103690008FB400288FB300248FB200208FB1001C9C
+:1036A0008FB0001803E0000827BD00303C18080068
+:1036B0008F1831FC270F00013C010800AC2F31FCB2
+:1036C0000A002165000000001474FFB9000000002A
+:1036D000A0C000FF3C0508008CA531E43C030800B5
+:1036E0008C6331E03C0208008C4232048F99003434
+:1036F00034A80001241F00023C010801AC23952CD2
+:103700003C010801A02895283C010801A022952B26
+:10371000A33F00090A00211E8F8600340E0020D42A
+:10372000000000000A0021658F8600343C1F08015C
+:1037300093FF950C2419000113F902298F87006C5F
+:103740003C100801921095103C06080190C6950E99
+:1037500010C000050200A0213C04080190849511CE
+:10376000109001E48F870074001088408F9F0074D0
+:10377000023048210009C880033F702195D8000815
+:10378000270F0001A5CF00083C0408019084951183
+:103790003C05080190A5950E0E0020820000000057
+:1037A0008F870074023020210004308000C7202160
+:1037B0008C8500048F82007000A240230502000661
+:1037C000AC8200048C8A00008F83006C01431023BC
+:1037D0005C400001AC8300008F86003490CB00FF7A
+:1037E0002D6C00025580002D241400010230F821B8
+:1037F000001F40800107282190B9000B8CAE000407
+:103800000019C04003197821000F188000671021AB
+:103810008C4D000001AE88232630FFFF5E00001FA4
+:10382000241400018C4400048CAA0000008A482360
+:1038300019200019240E00043C010801A02E950D4A
+:1038400090AD000B8CAB0004000D8840022D802150
+:1038500000101080004710218C4400040164602394
+:10386000058202009443000890DF00FE90B9000B2F
+:1038700033E500FF54B900040107A021A0D400FEE5
+:103880008F8700740107A0219284000B0E00208214
+:10389000240500018F860034241400011254009680
+:1038A0002E500001160000423C08FFFF24190002C0
+:1038B0001659FF3F00000000A0C000FF8F860034B3
+:1038C000A0D200090A0021658F86003490C7000944
+:1038D0002404000230E300FF1064016F2409000497
+:1038E000106901528F8800708CCE0054010E68233D
+:1038F00025B1000106200175241800043C010801CF
+:10390000A038950D3C010801A020950C90D400FD35
+:1039100090D200FF2E4F000215E0FF14328400FF0A
+:10392000000438408F89007490DF00FF00E410210C
+:10393000000220800089C8212FE500029324000B9B
+:1039400014A0FF0A2407000200041840006480212C
+:1039500000105880016928218CAC0004010C502310
+:103960000540FF02000000003C0308019063950E33
+:1039700014600005246F00013C010801A02495118A
+:103980003C010801A027950F3C010801A02F950ECE
+:1039900090CE00FF24E7000131CD00FF01A7882B66
+:1039A0001220FFE990A4000B0A002154000000003F
+:1039B0003C0508018CA5950C3C12000400A8F824D5
+:1039C00013F20006240200053C0908019129950D17
+:1039D0001520000224020003240200053C01080116
+:1039E000A022952990C700FF14E0012024020002C4
+:1039F000A0C200090A0021658F86003490CC00FF28
+:103A00001180FEDA240A00018F8C00708F89007407
+:103A1000240F0003018068211160001E240E0002A3
+:103A2000000540400105A02100142080008990215C
+:103A30008E510004019180230600FECC000000009E
+:103A40003C0208019042950E1440000524580001E4
+:103A50003C010801A02A950F3C010801A025951101
+:103A60003C010801A038950E90DF00FF01051021F0
+:103A70000002C88033E500FF254A00010329202108
+:103A800000AA402B1500FEB99085000B1560FFE5DC
+:103A9000000540400005404001051821000310804A
+:103AA0003C010801A02A950C3C010801A0259510B5
+:103AB000004918218C64000400E4F82327F9FFFF73
+:103AC0001F20FFE9000000008C63000000E3582382
+:103AD0000560013A01A3882310E301170184C02384
+:103AE0001B00FEA2000000003C010801A02E950D65
+:103AF0000A002293240B0001240E0004A0CE00092A
+:103B00003C0D08008DAD31F88F86003425A20001F0
+:103B10003C010800AC2231F80A00216500000000D9
+:103B20008CD9005C00F9C0231F00FE7B0000000060
+:103B30008CDF005C10FFFF658F8400708CC3005C1D
+:103B400000834023250200011C40FF6000000000AC
+:103B50008CC9005C2487000100E9282B10A0FE948A
+:103B60003C0D80008DAB01043C0C0001016C502425
+:103B70001140FE8F240200103C010801A02295296B
+:103B80000A002165000000008F9100708F860034CC
+:103B900026220001ACC2005C0A002220241400018D
+:103BA0008F8700342404FF800000882190E9000AF8
+:103BB0002414000101243025A0E6000A3C05080178
+:103BC00090A5950E3C040801908495110E0020826A
+:103BD000000000008F8600348F85007490C800FDBF
+:103BE000310700FF000740400107F821001FC08097
+:103BF0000305C8219323000BA0C300FD8F8500742B
+:103C00008F86003403056021918F000B000F7040F8
+:103C100001CF6821000D8080020510218C4B00002F
+:103C2000ACCB00548D8400048F830070006450235B
+:103C3000194000022482000124620001010748218A
+:103C4000ACC2005C0009308000C5402100E02021AA
+:103C5000240500010E0020829110000B8F86003495
+:103C600090C500FF10A0FF0C001070408F850074FD
+:103C700001D06821000D1080004558218D6400009E
+:103C80008F8C0070018450232547000104E0FF025F
+:103C9000263100013C0308019063950E2E2F00028F
+:103CA000247800013C010801A038950E3C01080170
+:103CB000A034950F11E0FEF8020038210A0022F32B
+:103CC000000740408F8400348F8300708C8500583B
+:103CD00000A340230502FE9AAC8300580A0021C9C4
+:103CE000000000003C07080190E7952A240200FF2D
+:103CF00010E200BE8F8600343C11080196319532E7
+:103D00003C03080124639530262500013230FFFF73
+:103D100030ABFFFF020360212D6A00FF1540008DCC
+:103D2000918700043C010801A42095328F8800345B
+:103D30000007484001272821911800FF0005308026
+:103D40002405000127140001A11400FF3C12080102
+:103D50009252952A8F8800748F8E006C264F000136
+:103D600000C820213C010801A02F952AAC8E00003C
+:103D70008F8D0070A4850008AC8D00043C03080101
+:103D80009063950C14600077000090213C010801BD
+:103D9000A025950CA087000B8F8C007400CC5021BF
+:103DA000A147000A8F820034A04700FD8F840034B1
+:103DB000A08700FE8F8600348F9F006CACDF00541C
+:103DC0008F990070ACD900588F8D00740127C021E5
+:103DD00000185880016DA021928F000A000F7040DA
+:103DE00001CF182100038880022D8021A207000B3B
+:103DF0008F86007401666021918A000B000A1040D2
+:103E0000004A20210004288000A64021A107000AC2
+:103E10003C07800834E900808D2200308F86003412
+:103E2000ACC2005C0A0022202414000190CA00FFEA
+:103E30001540FEAD8F880070A0C400090A002165FE
+:103E40008F860034A0C000FD8F9800342406000146
+:103E5000A30000FE3C010801A026950D3C010801CD
+:103E6000A020950C0A0021540000000090CB00FF18
+:103E70003C0408019084952B316C00FF0184502B89
+:103E80001540000F2402000324020004A0C2000910
+:103E90000A0021658F86003490C3000A2410FF8039
+:103EA00002035824316C00FF1180FDC100000000A6
+:103EB0003C010801A020950D0A00215400000000DB
+:103EC000A0C200090A0021658F86003490D4000A40
+:103ED0002412FF8002544824312800FF1500FFF40B
+:103EE000240200083C010801A02295290A0021654E
+:103EF00000000000001088408F8B006C02301821F9
+:103F00000003688001A72021AC8B00008F8A00701D
+:103F1000240C0001A48C0008AC8A00043C050801B4
+:103F200090A5950E2402000110A2FE1E24A5FFFFFD
+:103F30000A0021DF9084000B0184A0231A80FD8BEE
+:103F4000000000003C010801A02E950D0A002293FC
+:103F5000240B00013C010801A42595320A002345E9
+:103F60008F880034240B0001106B00228F980034DE
+:103F70008F85003490BF00FF33F900FF1079002BCC
+:103F8000000000003C1F080193FF9510001FC8406F
+:103F9000033FC0210018A0800288782191EE000A1A
+:103FA000A08E000A8F8D00743C0308019063951069
+:103FB00000CD88210A00236BA223000B26300001CC
+:103FC0000600003101A490230640002B24020003C8
+:103FD0003C010801A02F950D0A002293240B00013B
+:103FE0008F8900340A0021C9AD2700540A00221F1E
+:103FF00024120001931400FDA094000B8F8800345C
+:104000008F8F0074910E00FE00CF6821A1AE000AD0
+:104010008F910034A22700FD8F83006C8F900034B5
+:10402000AE0300540A00236C8F8D007490B000FE24
+:10403000A090000A8F8B00348F8C0074916A00FD71
+:1040400000CC1021A04A000B8F840034A08700FE12
+:104050008F8600708F850034ACA600580A00236C50
+:104060008F8D007494B80008ACA400040303782179
+:104070000A002213A4AF00083C010801A022950DFC
+:104080000A0021540000000090CF0009240D000414
+:1040900031EE00FF11CDFD85240200013C01080135
+:0C40A000A022950D0A0021540000000031
+:0440AC000800334491
+:1040B0000800334408003420080033F4080033D8E3
+:1040C0000800332808003328080033280800334C40
+:1040D0008008010080080080800800005F86543757
+:1040E000E4AC62CC50103A4536621985BF14C0E882
+:1040F0001BC27A1E84F4B556094EA6FE7DDA01E78E
+:10410000C04D7481080058D008005914080058B8F0
+:10411000080058B8080058B8080058B8080058D027
+:10412000080058B8080058B80800591C080058B8CA
+:1041300008005830080058B8080058B80800591C42
+:10414000080058B8080058B8080058B8080058B80F
+:10415000080058B8080058B8080058B8080058B8FF
+:10416000080058B8080058B8080058F0080058B8B7
+:10417000080058F0080058B8080058B8080058B8A7
+:10418000080058F4080058F0080058B8080058B85B
+:10419000080058B8080058B8080058B8080058B8BF
+:1041A000080058B8080058B8080058B8080058B8AF
+:1041B000080058B8080058B8080058B8080058B89F
+:1041C000080058B8080058B8080058B8080058B88F
+:1041D000080058B8080058B8080058F4080058F407
+:1041E000080058B8080058F4080058B8080058B833
+:1041F000080058B8080058B8080058B8080058B85F
+:10420000080058B8080058B8080058B8080058B84E
+:10421000080058B8080058B8080058B8080058B83E
+:10422000080058B8080058B8080058B8080058B82E
+:10423000080058B8080058B8080058B8080058B81E
+:10424000080058B8080058B8080058B8080058B80E
+:10425000080058B8080058B8080058B8080058B8FE
+:10426000080058B8080058B8080058B8080058B8EE
+:10427000080058B8080058B8080058B8080058B8DE
+:10428000080058B8080058B8080058B8080058B8CE
+:10429000080058B8080058B8080058B8080058B8BE
+:1042A000080058B8080058B8080058B8080058B8AE
+:1042B000080058B8080058B8080058B8080058B89E
+:1042C000080058B8080058B8080058B8080058B88E
+:1042D000080058B8080058B8080058B8080058B87E
+:1042E000080058B8080058B8080058B8080058B86E
+:1042F000080058B8080058B8080058B8080058B85E
+:10430000080058B80800593808007688080078EC8A
+:1043100008007694080074880800769408007720D6
+:10432000080076940800748808007488080074886F
+:10433000080074880800748808007488080074886D
+:10434000080074880800748808007488080076B42F
+:10435000080076A40800748808007488080074882F
+:10436000080074880800748808007488080074883D
+:10437000080074880800748808007488080074882D
+:1043800008007488080076A40800813408007FC003
+:10439000080080FC08007FC0080080CC08007EA8D0
+:1043A00008007FC008007FC008007FC008007FC0F1
+:1043B00008007FC008007FC008007FC008007FC0E1
+:1043C00008007FC008007FC008007FC008007FC0D1
+:1043D00008007FE808008B6C08008CC808008CA8D7
+:0843E0000800871008008B841F
+:0843E8000A000124000000009E
+:1043F000000000000000000D747061362E302E3178
+:10440000370000000600110100000000000000005D
+:10441000000000000000000000000000000000009C
+:10442000000000000000000000000000000000008C
+:10443000000000000000000000000000000000007C
+:10444000000000000000000000000000000000006C
+:10445000000000000000000000000000000000005C
+:10446000000000000000000000000000000000004C
+:104470000000000000000000000000001000000329
+:10448000000000000000000D0000000D3C020800CC
+:10449000244217203C03080024632A10AC4000008B
+:1044A0000043202B1480FFFD244200043C1D080023
+:1044B00037BD2FFC03A0F0213C100800261004900B
+:1044C0003C1C0800279C17200E0002620000000020
+:1044D0000000000D2402FF8027BDFFE000821024B1
+:1044E000AFB00010AF420020AFBF0018AFB1001452
+:1044F000936500043084007F034418213C020008C7
+:104500000062182130A50020036080213C080111C1
+:10451000277B000814A000022466005C2466005873
+:104520009202000497430104920400043047000FF4
+:104530003063FFFF308400400067282310800009AB
+:10454000000048219202000530420004104000059E
+:104550000000000010A000030000000024A5FFFCE4
+:1045600024090004920200053042000410400012A9
+:104570000000000010A000100000000096020002E1
+:1045800000A72021010440252442FFFEA742101667
+:10459000920300042402FF8000431024304200FFF5
+:1045A000104000033C0204000A000174010240258F
+:1045B0008CC20000AF4210188F4201780440FFFE09
+:1045C0002402000AA74201409602000224040009C6
+:1045D000304200070002102330420007A742014288
+:1045E000960200022442FFFEA7420144A740014672
+:1045F00097420104A74201488F420108304200203F
+:1046000050400001240400019202000430420010D6
+:10461000144000023483001000801821A743014A8F
+:10462000000000000000000000000000000000008A
+:10463000AF48100000000000000000000000000073
+:10464000000000008F4210000441FFFE3102FFFF16
+:1046500010400007000000009202000430420040B9
+:1046600014400003000000008F421018ACC200008C
+:10467000960200063042FFFF24420002000210436F
+:104680000002104003628821962200001120000DD4
+:104690003044FFFF00A710218F8300388F45101C86
+:1046A000000210820002108000431021AC4500007F
+:1046B00030A6FFFF0E00058D00052C0200402021D2
+:1046C000A6220000920300042402FF80004310246D
+:1046D000304200FF1040001F000000009202000561
+:1046E000304200021040001B000000009742100CF6
+:1046F0002442FFFEA7421016000000003C02040006
+:1047000034420030AF421000000000000000000002
+:1047100000000000000000008F4210000441FFFE76
+:10472000000000009742100C8F45101C3042FFFF24
+:10473000244200300002108200021080005B102131
+:10474000AC45000030A6FFFF0E00058D00052C02D1
+:10475000A622000096040002248400080E0001E94D
+:104760003084FFFF974401040E0001F73084FFFFFF
+:104770008FBF00188FB100148FB000103C021000E2
+:1047800027BD002003E00008AF4201783084FFFF1E
+:10479000308200078F850024104000022483000728
+:1047A0003064FFF800A4102130421FFF034218219B
+:1047B000247B4000AF850028AF82002403E000087E
+:1047C000AF4200843084FFFF3082000F8F85002CC1
+:1047D0008F860034104000022483000F3064FFF005
+:1047E00000A410210046182BAF850030004620237E
+:1047F00014600002AF82002CAF84002C8F82002C4A
+:10480000340480000342182100641821AF8300386B
+:1048100003E00008AF4200808F82001410400008BF
+:104820008F8200048F82FFDC144000058F82000419
+:104830003C02FFBF3442FFFF008220248F8200042D
+:1048400030430006240200021062000F3C02010106
+:104850002C62000350400005240200041060000F89
+:104860003C0200010A000230000000001062000556
+:10487000240200061462000C3C0201110A00022905
+:10488000008210253C02001100821025AF4210006A
+:10489000240200010A000230AF82000C00821025C1
+:1048A000AF421000AF80000C0000000000000000CC
+:1048B0000000000003E00008000000008F82000CF0
+:1048C00010400004000000008F4210000441FFFE71
+:1048D0000000000003E00008000000008F820010CC
+:1048E0002443F800000231C224C2FFF02C6303010C
+:1048F00010600003000210420A000257AC82000060
+:104900008F85001800C5102B1440000B00001821E3
+:1049100000C51023244700018F82001C00A2102133
+:104920002442FFFF0046102B544000042402FFFFE6
+:104930000A000257AC8700002402FFFF0A00026051
+:10494000AC8200008C820000000219400062182135
+:104950000003188000621821000318803C02080040
+:104960002442175C0062182103E000080060102157
+:1049700027BDFFD8AFBF0020AFB1001CAFB00018FB
+:104980003C0460088C8250002403FF7F3C066000DA
+:10499000004310243442380CAC8250008CC24C1CB2
+:1049A0003C1A8000000216023042000F104000073F
+:1049B000AF82001C8CC34C1C3C02001F3442FC0024
+:1049C00000621824000319C2AF8300188F42000848
+:1049D000275B400034420001AF420008AF80002452
+:1049E0003C02601CAF400080AF4000848C45000852
+:1049F0008CC3080834028000034220212402FFF007
+:104A0000006218243C0200803C010800AC22042013
+:104A10003C025709AF84003814620004AF850034AB
+:104A2000240200010A000292AF820014AF80001439
+:104A30008F42000038420001304200011440FFFC68
+:104A40008F820014104000160000000097420104FD
+:104A5000104000058F830000146000072462FFFFF0
+:104A60000A0002A72C62000A2C62001050400004C9
+:104A70008F83000024620001AF8200008F8300005A
+:104A80002C62000A144000032C6200070A0002AEE8
+:104A9000AF80FFDC1040000224020001AF82FFDC87
+:104AA0008F4301088F44010030622000AF8300046F
+:104AB00010400008AF8400103C0208008C42042C17
+:104AC000244200013C010800AC22042C0A00058AA3
+:104AD0003C0240003065020014A0000324020F00D5
+:104AE0001482026024020D0097420104104002C8A3
+:104AF0003C02400030624000144000AD8F8200381C
+:104B00008C4400088F4201780440FFFE2402080014
+:104B1000AF42017824020008A7420140A7400142A9
+:104B2000974201048F8400043051FFFF308200015E
+:104B300010400007022080212623FFFE24020002ED
+:104B40003070FFFFA74201460A0002DBA74301487D
+:104B5000A74001463C0208008C42043C1440000D72
+:104B60008F830010308200201440000224030009CB
+:104B700024030001006020218F830010240209001B
+:104B80005062000134840004A744014A0A0002F67E
+:104B90000000000024020F00146200053082002093
+:104BA000144000062403000D0A0002F5240300054A
+:104BB000144000022403000924030001A743014A12
+:104BC0003C0208008C4204203C0400480E00020C09
+:104BD000004420250E000235000000008F82000CEA
+:104BE0001040003E000000008F4210003C030020F7
+:104BF00000431024104000398F820004304200022C
+:104C0000104000360000000097421014144000339A
+:104C100000000000974210088F8800383042FFFFE4
+:104C200024420006000218820003388000E8302188
+:104C3000304300018CC400001060000430420003C7
+:104C40000000000D0A00033700E810215440001056
+:104C50003084FFFF3C05FFFF0085202400851826D7
+:104C60000003182B0004102B0043102410400005F3
+:104C700000000000000000000000000D0000000027
+:104C8000240002228CC200000A00033600452025C1
+:104C90003883FFFF0003182B0004102B004310245F
+:104CA0001040000500000000000000000000000DA2
+:104CB000000000002400022B8CC200003444FFFFDF
+:104CC00000E81021AC4400003C0208008C42043093
+:104CD000244200013C010800AC2204308F62000035
+:104CE0008F840038AF8200088C8300003402FFFFFD
+:104CF0001462000F000010213C0508008CA504542C
+:104D00003C0408008C84045000B0282100B0302BF3
+:104D100000822021008620213C010800AC2504549B
+:104D20003C010800AC2404500A000580240400085B
+:104D30008C820000304201001040000F0000102162
+:104D40003C0508008CA5044C3C0408008C840448F5
+:104D500000B0282100B0302B0082202100862021C5
+:104D60003C010800AC25044C3C010800AC2404487C
+:104D70000A000580240400083C0508008CA50444B2
+:104D80003C0408008C84044000B0282100B0302B83
+:104D900000822021008620213C010800AC2504442B
+:104DA0003C010800AC2404400A00058024040008EB
+:104DB0008F6200088F62000000021602304300F08C
+:104DC000240200301062000524020040106200E05E
+:104DD0008F8200200A0005882442000114A00005EB
+:104DE00000000000000000000000000D00000000B6
+:104DF000240002568F4201780440FFFE00000000AC
+:104E00000E00023D27A40010144000050040802140
+:104E1000000000000000000D000000002400025D02
+:104E20008E0200001040000500000000000000009D
+:104E30000000000D00000000240002608F62000CE2
+:104E400004430003240200010A00042EAE00000007
+:104E5000AE0200008F8200388C480008A2000007D4
+:104E60008F65000C8F64000430A3FFFF0004240250
+:104E700000852023308200FF0043102124420005DA
+:104E8000000230832CC20081A605000A14400005F0
+:104E9000A2040004000000000000000D000000005B
+:104EA000240002788F8500380E0005AB260400141C
+:104EB0008F6200048F430108A60200083C02100024
+:104EC00000621824106000080000000097420104EE
+:104ED000920300072442FFEC346300023045FFFFD9
+:104EE0000A0003C3A2030007974201042442FFF013
+:104EF0003045FFFF960600082CC200135440000501
+:104F0000920300079202000734420001A202000748
+:104F1000920300072402000110620005240200032E
+:104F20001062000B8F8200380A0003E030C6FFFFDA
+:104F30008F8200383C04FFFF8C43000C006418246F
+:104F400000651825AC43000C0A0003E030C6FFFFE3
+:104F50003C04FFFF8C4300100064182400651825F2
+:104F6000AC43001030C6FFFF24C2000200021083D1
+:104F7000A20200058F830038304200FF000210803B
+:104F8000004328218CA800008CA200002403000408
+:104F900000021702144300120000000097420104AF
+:104FA0003C03FFFF010318243042FFFF004610239B
+:104FB0002442FFFE00624025ACA8000092030005D9
+:104FC000306200FF00021080005010219042001457
+:104FD0003042000F004310210A000415A20200060F
+:104FE0008CA40004974201049603000A3088FFFF56
+:104FF0003042FFFF004610232442FFD60002140077
+:1050000001024025ACA800049202000792040005AA
+:10501000246300280003188300641821344200042C
+:10502000A2030006A20200078F8200042403FFFBF4
+:105030003442000200431024AF82000492030006B1
+:105040008F87003800031880007010218C440020E6
+:105050003C02FFF63442FFFF008240240067182123
+:10506000AE04000CAC68000C920500063C03FF7F08
+:105070008E02000C0005288000B020213463FFFF61
+:10508000010330249488002600A72821004310241F
+:10509000AE02000CAC860020AC880024ACA8001046
+:1050A00024020010A742014024020002A74001424E
+:1050B000A7400144A7420146974201043C0400086E
+:1050C0002442FFFEA7420148240200010E00020C08
+:1050D000A742014A9603000A9202000400431021ED
+:1050E0002442000230420007000210233042000731
+:1050F0000E000235AE0200108F6200003C03080073
+:105100008C63044424040010AF8200089742010419
+:105110003042FFFF2442FFFE00403821000237C327
+:105120003C0208008C420440006718210067282BCD
+:1051300000461021004510213C010800AC23044426
+:105140003C010800AC2204400A00051500000000E4
+:1051500014A0000500000000000000000000000D89
+:10516000000000002400030A8F4201780440FFFE83
+:10517000000000000E00023D27A4001414400005AA
+:1051800000408021000000000000000D0000000031
+:10519000240003118E020000544000069202000712
+:1051A000000000000000000D000000002400031CAF
+:1051B0009202000730420004104000058F82000474
+:1051C0002403FFFB3442000200431024AF8200049A
+:1051D0008F62000404430008920200079202000656
+:1051E0008E03000CAE000000000210800050102161
+:1051F000AC430020920200073042000454400009F2
+:105200009602000A920200053C0300010002108091
+:10521000005010218C46001800C33021AC46001805
+:105220009602000A9206000427710008022020213D
+:1052300000C2302124C60005260500140E0005AB6F
+:1052400000063082920400068F6500043C027FFF56
+:1052500000042080009120218C8300043442FFFF51
+:1052600000A2282400651821AC83000492020007E4
+:105270009204000592030004304200041040001420
+:1052800096070008308400FF000420800091202150
+:105290008C860004974201049605000A306300FFE3
+:1052A0003042FFFF004310210045102130E3FFFF93
+:1052B000004310232442FFD830C6FFFF0002140031
+:1052C00000C23025AC8600040A0004C9920300071E
+:1052D000308500FF0005288000B128218CA4000043
+:1052E00097420104306300FF3042FFFF004310216A
+:1052F000004710233C03FFFF008320243042FFFFC0
+:1053000000822025ACA400009203000724020001C3
+:105310001062000600000000240200031062001169
+:10532000000000000A0004EC8E0300109742010404
+:10533000920300049605000A8E24000C00431021FD
+:10534000004510212442FFF23C03FFFF008320248C
+:105350003042FFFF00822025AE24000C0A0004EC3E
+:105360008E03001097420104920300049605000A80
+:105370008E24001000431021004510212442FFEE2E
+:105380003C03FFFF008320243042FFFF00822025E2
+:10539000AE2400108E0300102402000AA742014030
+:1053A000A74301429603000A920200043C04004015
+:1053B00000431021A7420144A7400146974201043F
+:1053C000A7420148240200010E00020CA742014A34
+:1053D0000E000235000000008F62000092030004FE
+:1053E00000002021AF820008974201049606000ABF
+:1053F0003042FFFF00621821006028213C030800B2
+:105400008C6304443C0208008C420440006518216F
+:10541000004410210065382B004710213C01080092
+:10542000AC2304443C010800AC2204409204000474
+:10543000008620212484000A3084FFFF0E0001E949
+:1054400000000000974401043084FFFF0E0001F7C4
+:10545000000000003C021000AF4201780A000587FE
+:105460008F820020148200273062000697420104D8
+:10547000104000673C0240003062400010400005D0
+:1054800000000000000000000000000D000000000F
+:10549000240004208F4201780440FFFE240208000B
+:1054A000AF42017824020008A7420140A740014210
+:1054B0008F8200049743010430420001104000072E
+:1054C0003070FFFF2603FFFE24020002A7420146C0
+:1054D000A74301480A00053F2402000DA7400146EA
+:1054E0002402000DA742014A8F6200002404000834
+:1054F000AF8200080E0001E9000000000A00051953
+:1055000002002021104000423C0240009362000053
+:10551000304300F0240200101062000524020070E5
+:10552000106200358F8200200A00058824420001A5
+:105530008F620000974301043050FFFF3071FFFF7E
+:105540008F4201780440FFFE320200070002102360
+:10555000304200072403000A2604FFFEA74301404F
+:10556000A7420142A7440144A7400146A751014870
+:105570008F42010830420020144000022403000939
+:1055800024030001A743014A0E00020C3C04004022
+:105590000E000235000000003C0708008CE70444C0
+:1055A000021110212442FFFE3C0608008CC6044074
+:1055B0000040182100E33821000010218F65000011
+:1055C00000E3402B00C230212604000800C830212F
+:1055D0003084FFFFAF8500083C010800AC2704447D
+:1055E0003C010800AC2604400E0001E90000000068
+:1055F0000A000519022020210E00013B00000000D6
+:105600008F82002024420001AF8200203C02400033
+:10561000AF4201380A000292000000003084FFFF10
+:1056200030C6FFFF00052C0000A628253882FFFFAA
+:10563000004510210045282B0045102100021C02C6
+:105640003042FFFF0043102100021C023042FFFFE6
+:10565000004310213842FFFF03E000083042FFFF03
+:105660003084FFFF30A5FFFF0000182110800007E5
+:1056700000000000308200011040000200042042BF
+:10568000006518210A0005A10005284003E0000874
+:105690000060102110C0000624C6FFFF8CA200008D
+:1056A00024A50004AC8200000A0005AB2484000499
+:1056B00003E000080000000010A0000824A3FFFF82
+:1056C000AC86000000000000000000002402FFFF84
+:1056D0002463FFFF1462FFFA2484000403E000083F
+:0456E00000000000C6
+:0456E40000000001C1
+:0856E8000A00002A0000000086
+:1056F000000000000000000D747870362E302E314E
+:105700003700000006001100000000000000013614
+:105710000000EA600000000000000000000000003F
+:105720000000000000000000000000000000000079
+:105730000000000000000000000000000000000069
+:105740000000000000000000000000160000000043
+:105750000000000000000000000000000000000049
+:105760000000000000000000000000000000000039
+:105770000000000000000000000000000000000029
+:105780000000138800000000000005DC000000009D
+:105790000000000010000003000000000000000DE9
+:1057A0000000000D3C02080024423D883C03080034
+:1057B0002463403CAC4000000043202B1480FFFDDC
+:1057C000244200043C1D080037BD7FFC03A0F021EB
+:1057D0003C100800261000A83C1C0800279C3D88AF
+:1057E0000E00044E000000000000000D27BDFFB4B5
+:1057F000AFA10000AFA20004AFA30008AFA4000C4B
+:10580000AFA50010AFA60014AFA70018AFA8001CEA
+:10581000AFA90020AFAA0024AFAB0028AFAC002C8A
+:10582000AFAD0030AFAE0034AFAF0038AFB8003C22
+:10583000AFB90040AFBC0044AFBF00480E000591B7
+:10584000000000008FBF00488FBC00448FB90040AB
+:105850008FB8003C8FAF00388FAE00348FAD003072
+:105860008FAC002C8FAB00288FAA00248FA90020BA
+:105870008FA8001C8FA700188FA600148FA50010FA
+:105880008FA4000C8FA300088FA200048FA100003A
+:1058900027BD004C3C1B60048F7A5030377B50286A
+:1058A00003400008AF7A00008F86003C3C03900064
+:1058B0003C0280000086282500A32025AC4400205F
+:1058C0003C0380008C67002004E0FFFE0000000025
+:1058D00003E00008000000000A000070240400013A
+:1058E0008F85003C3C0480003483000100A3102518
+:1058F00003E00008AC82002003E000080000102153
+:105900003084FFFF30A5FFFF108000070000182142
+:10591000308200011040000200042042006518217E
+:105920001480FFFB0005284003E000080060102100
+:1059300010C00007000000008CA2000024C6FFFF7A
+:1059400024A50004AC82000014C0FFFB24840004E2
+:1059500003E000080000000010A0000824A3FFFFDF
+:10596000AC86000000000000000000002402FFFFE1
+:105970002463FFFF1462FFFA2484000403E000089C
+:105980000000000090AA00318FAB00108CAC0040EA
+:105990003C0300FF8D680004AD6C00208CAD00441A
+:1059A00000E060213462FFFFAD6D00248CA7004849
+:1059B0003C09FF000109C024AD6700288CAE004CF3
+:1059C0000182C82403197825AD6F0004AD6E002C48
+:1059D0008CAD0038314A00FFAD6D001C94A9003237
+:1059E0003128FFFFAD68001090A70030A5600002CD
+:1059F000A1600004A167000090A30032306200FFA4
+:105A00000002198210600005240500011065000ED7
+:105A10000000000003E00008A16A00018CD8002803
+:105A2000354A0080AD7800188CCF0014AD6F00149B
+:105A30008CCE0030AD6E00088CC4002CA16A000131
+:105A400003E00008AD64000C8CCD001CAD6D0018A7
+:105A50008CC90014AD6900148CC80024AD6800081E
+:105A60008CC70020AD67000C8CC200148C830070C2
+:105A70000043C82B13200007000000008CC2001454
+:105A8000144CFFE400000000354A008003E00008E9
+:105A9000A16A00018C8200700A0000E6000000008C
+:105AA0009089003027BDFFF88FA8001CA3A9000033
+:105AB0008FA300003C0DFF8035A2FFFF8CAC002CB3
+:105AC00000625824AFAB0000A100000400C05821C0
+:105AD000A7A000028D06000400A048210167C8218C
+:105AE0008FA50000008050213C18FF7F032C20264A
+:105AF0003C0E00FF2C8C0001370FFFFF35CDFFFF60
+:105B00003C02FF0000AFC82400EDC02400C278248E
+:105B1000000C1DC00323682501F87025AD0D0000A1
+:105B2000AD0E00048D240024AFAD0000AD040008CC
+:105B30008D2C00202404FFFFAD0C000C9547003293
+:105B400030E6FFFFAD0600109145004830A200FF8F
+:105B5000000219C2506000018D240034AD0400140D
+:105B60008D4700388FAA001827BD0008AD0B00280C
+:105B7000AD0A0024AD07001CAD00002CAD000018DC
+:105B800003E00008AD00002027BDFFE0AFB2001821
+:105B9000AFB10014AFB00010AFBF001C9098003040
+:105BA00000C088213C0D00FF330F007FA0CF000014
+:105BB000908E003135ACFFFF3C0AFF00A0CE000103
+:105BC00094A6001EA22000048CAB00148E290004B1
+:105BD00000A08021016C2824012A4024008090210B
+:105BE00001052025A6260002AE240004260500207B
+:105BF000262400080E00009224060002924700307E
+:105C0000260500282624001400071E0000031603A2
+:105C100024060004044000032403FFFF96590032C9
+:105C20003323FFFF0E000092AE2300102624002431
+:105C30008FBF001C8FB200188FB100148FB00010FE
+:105C400024050003000030210A00009C27BD00202D
+:105C500027BDFFD8AFB1001CAFB00018AFBF002008
+:105C600090A900302402000100E050213123003FC0
+:105C700000A040218FB000400080882100C0482152
+:105C8000106200148FA70038240B000500A020210B
+:105C900000C02821106B0013020030210E000128E3
+:105CA000000000009225007C30A400021080000358
+:105CB00026030030AE000030260300348FBF0020E2
+:105CC0008FB1001C8FB000180060102103E00008A5
+:105CD00027BD00280E0000A7AFB000100A00016F1A
+:105CE000000000008FA3003C01002021012028219A
+:105CF00001403021AFA300100E0000EEAFB0001441
+:105D00000A00016F000000003C06800034C20E0053
+:105D10008C4400108F850044ACA400208C430018F4
+:105D200003E00008ACA300243C06800034C20E004F
+:105D30008C4400148F850044ACA400208C43001CCC
+:105D400003E00008ACA300249382000C1040001B69
+:105D50002483000F2404FFF00064382410E00019AD
+:105D6000978B00109784000E9389000D3C0A601CED
+:105D70000A0001AC01644023010370210064282360
+:105D80001126000231C2FFFF30A2FFFF0047302B77
+:105D900050C0000E00E448218D4D000C31A3FFFFE0
+:105DA00000036400000C2C0304A1FFF30000302169
+:105DB00030637FFF0A0001A42406000103E000080D
+:105DC000000000009784000E00E448213123FFFF0B
+:105DD0003168FFFF0068382B54E0FFF8A783000EFE
+:105DE000938A000D11400005240F0001006BC023B1
+:105DF000A380000D03E00008A798000E006BC023ED
+:105E0000A38F000D03E00008A798000E03E0000830
+:105E10000000000027BDFFE8AFB000103C1080007C
+:105E200036030140308BFFFF93AA002BAFBF001455
+:105E3000A46B000436040E009488001630C600FFE0
+:105E40008FA90030A4680006AC650008A0660012A7
+:105E5000A46A001AAC6700208FA5002CA469001862
+:105E6000012020210E000198AC6500143C021000B6
+:105E7000AE0201788FBF00148FB0001003E000085D
+:105E800027BD00188F8500002484000727BDFFF878
+:105E90003084FFF83C06800094CB008A316AFFFF13
+:105EA000AFAA00008FA90000012540232507FFFFAE
+:105EB00030E31FFF0064102B1440FFF700056882D9
+:105EC000000D288034CC400000AC102103E0000815
+:105ED00027BD00088F8200002486000730C5FFF828
+:105EE00000A2182130641FFF03E00008AF84000007
+:105EF0008F87003C8F84004427BDFFB0AFB70044BC
+:105F0000AFB40038AFB1002CAFBF0048AFB600400F
+:105F1000AFB5003CAFB30034AFB20030AFB0002833
+:105F20003C0B80008C860024AD6700808C8A0020AA
+:105F300035670E0035690100ACEA00108C8800243A
+:105F40008D2500040000B821ACE800188CE3001097
+:105F500000A688230000A021ACE300148CE2001806
+:105F6000ACE2001C122000FE00E0B021936C00089F
+:105F7000118000F400000000976F001031EEFFFF69
+:105F8000022E682B15A000EF000000009772001091
+:105F90003250FFFFAED000003C0380008C74000044
+:105FA000329300081260FFFD0000000096D8000840
+:105FB0008EC700043305FFFF30B5000112A000E4D6
+:105FC000000000000000000D30BFA0402419004078
+:105FD00013F9011B30B4A000128000DF00000000A4
+:105FE000937300081260000800000000976D001015
+:105FF00031ACFFFF00EC202B1080000330AE0040DE
+:1060000011C000D500000000A7850040AF87003810
+:106010009363000802202821AFB10020146000F52E
+:1060200027B40020AF60000C978F004031F1400092
+:1060300016200002240300162403000E2405400746
+:10604000A363000AAF650014938A00428F700014A6
+:10605000315500010015124002024825AF690014B5
+:10606000979F00408F78001433F9001003194025E2
+:10607000AF680014979200403247000810E0016EAC
+:10608000000000008F6700143C1210003C118000DB
+:1060900000F27825AF6F001436230E00946E000ACC
+:1060A0003C0D81002406000E31CCFFFF018D202520
+:1060B000AF640004A36600029373000A3406FFFC79
+:1060C000266B0004A36B000A979800403308200059
+:1060D0001100015F000000003C05800034A90E00A3
+:1060E000979900409538000C97870040001940426E
+:1060F0003312C0003103000300127B0330F11000A3
+:10610000006F68250011720301AE6025000C20C0ED
+:10611000A764001297930040936A000A0013598203
+:106120003175003C02AA10212450003CA3700009E4
+:10613000953F000C33F93FFFA779001097700012CC
+:10614000936900090130F82127E5000230B9000702
+:106150000019C02333080007A368000B93710009DE
+:1061600097720012976F0010322700FF8F9100384E
+:10617000978D004000F21821006F702101C6602148
+:1061800031A6004010C000053185FFFF00B1102B83
+:106190003C12800010400017000098210225A82B17
+:1061A00056A0013E8FA500203C048000348A0E00DA
+:1061B0008D5300143C068000AD5300108D4B001C25
+:1061C000AD4B0018AD4500008CCD000031AC00088F
+:1061D0001180FFFD34CE0E0095C3000800A0882179
+:1061E00000009021A78300408DC600042413000105
+:1061F000AF860038976F001031F5FFFF8E9F0000CB
+:1062000003F1282310A0011FAE850000936200084F
+:10621000144000DD000000000E0001E7240400101F
+:106220008F900048004028213C023200320600FFD7
+:10623000000654000142F82526090001AF890048F4
+:10624000ACBF00009379000997780012936F000AA1
+:10625000332800FF3303FFFF0103382100076C00E0
+:1062600031EE00FF01AE6025ACAC00048F84004825
+:10627000978B0040316A20001140010AACA400084D
+:1062800097640012308BFFFF06400108ACAB000C96
+:10629000978E004031C5000814A000022628000691
+:1062A000262800023C1F800037E70E0094F90014F6
+:1062B0008CE5001C8F670004937800023324FFFFF5
+:1062C000330300FFAFA300108F6F0014AFA80018B6
+:1062D0000E0001CBAFAF0014240400100E0001FB30
+:1062E000000000008E920000164000050000000033
+:1062F0008F7800142403FFBF0303A024AF7400149D
+:106300008F67000C00F5C821AF79000C9375000869
+:1063100016A0000800000000126000060000000047
+:106320008F6800143C0AEFFF3549FFFE0109F8248D
+:10633000AF7F0014A37300088FA500200A00034F4D
+:1063400002202021AED100000A00022D3C03800073
+:1063500014E0FF1E30BFA0400E0001900000A021FD
+:106360002E9100010237B02512C000188FBF0048DF
+:106370008F87003C24170F0010F700D43C068000E4
+:106380008CD901780720FFFE241F0F0010FF00F6B4
+:1063900034CA0E008D56001434C701402408024050
+:1063A000ACF600048D49001C3C141000ACE9000858
+:1063B000A0E00012A4E0001AACE00020A4E0001865
+:1063C000ACE80014ACD401788FBF00488FB700440C
+:1063D0008FB600408FB5003C8FB400388FB30034C7
+:1063E0008FB200308FB1002C8FB0002803E000087E
+:1063F00027BD00508F910038978800403C128000E4
+:106400000220A8213107004014E0FF7C0000982101
+:10641000977900108F9200383338FFFF131200A8CD
+:10642000000020210080A021108000F300A088211E
+:106430001620FECE000000000A00031F2E9100016E
+:106440003C0380008C6201780440FFFE24080800B1
+:106450008F860000AC6801783C038000946D008A50
+:1064600031ACFFFF01865823256AFFFF31441FFF2F
+:106470002C8900081520FFF9000000008F8F0048CC
+:10648000347040008F83003C00E0A021240E0F00F8
+:1064900025E70001AF87004800D03021023488236F
+:1064A0003C08800031F500FF106E00052407000154
+:1064B00093980042331300010013924036470001C5
+:1064C000001524003C0A0100008A4825ACC90000E0
+:1064D0008F82004830BF003630B90008ACC20004DB
+:1064E0001320009900FF982535120E009650000ADF
+:1064F0008F8700003C0F81003203FFFF24ED00086E
+:1065000035060140006F60253C0E100031AB1FFFC7
+:10651000269200062405000EACCC0020026E9825C1
+:10652000A4C5001AAF8B0000A4D2001816200008E2
+:106530003C1080008F89003C24020F005122000291
+:1065400024170001367300400E0001883C108000C3
+:1065500036060E008CCB0014360A01400240202182
+:10656000AD4B00048CC5001CAD450008A1550012C0
+:10657000AD5300140E0001983C151000AE150178C3
+:106580000A00035200000000936F0009976E00128A
+:10659000936D000B31E500FF00AE202131AC00FF10
+:1065A000008C80212602000A3050FFFF0E0001E718
+:1065B000020020218F8600483C0341003C058000FA
+:1065C00024CB0001AF8B0048936A00099769001241
+:1065D00030C600FF315F00FF3128FFFF03E838219C
+:1065E00024F900020006C4000319782501E3702590
+:1065F000AC4E00008F6D000C34A40E00948B001480
+:1066000001B26025AC4C00048C85001C8F6700042F
+:10661000936A00023164FFFF314900FFAFA9001007
+:106620008F680014AFB100180E0001CBAFA80014A2
+:106630000A0002FD02002021AF600004A3600002F6
+:1066400097980040330820001500FEA30000302179
+:10665000A760001297840040936B000A3C108000F2
+:1066600030931F0000135183014BA82126A200285C
+:10667000A362000936090E00953F000C0A0002953E
+:10668000A77F00108F700014360900400E000188AB
+:10669000AF6900140A0002C9000000000A00034F9D
+:1066A000000020210641FEFAACA0000C8CAC000CCE
+:1066B0003C0D8000018D90250A0002EAACB2000C6E
+:1066C000000090210A0002C5241300011280000777
+:1066D0003C028000344B0E009566000830D3004029
+:1066E00012600049000000003C0680008CD0017858
+:1066F0000600FFFE34C50E0094B500103C030500F3
+:1067000034CC014032B8FFFF03039025AD92000C5A
+:106710008CAF0014240D20003C041000AD8F000449
+:106720008CAE001CAD8E0008A1800012A580001A5E
+:10673000AD800020A5800018AD8D0014ACC4017898
+:106740000A0003263C0680008F9F00003518014098
+:106750002692000227F9000833281FFFA71200180D
+:106760000A000391AF8800003C02800034450140DC
+:10677000ACA0000C1280001B34530E0034510E00EC
+:106780008E370010ACB700048E2400183C0B80003C
+:10679000ACA400083570014024040040A20000129F
+:1067A0008FBF0048A600001A8FB70044AE0000203B
+:1067B0008FB60040A60000188FB5003CAE04001450
+:1067C0008FB400388FB300348FB200308FB1002CFB
+:1067D0008FB000283C02100027BD005003E00008E5
+:1067E000AD6201788E660014ACA600048E64001CB5
+:1067F0000A00042A3C0B80000E0001902E9100013B
+:106800000A0003200237B025000000000000000D40
+:1068100000000000240003690A0004013C06800017
+:1068200027BDFFD8AFBF00203C0980003C1F20FFE0
+:10683000AFB200183C07600035320E002402001091
+:1068400037F9FFFDACE23008AFB3001CAFB1001464
+:10685000AFB00010AE5900000000000000000000C2
+:106860000000000000000000000000003C1800FFD5
+:106870003713FFFDAE5300003C0B60048D705000D9
+:106880002411FF7F3C0E00020211782435EC380CF5
+:1068900035CD0109ACED4C18240A0009AD6C50004F
+:1068A0008CE80438AD2A0008AD2000148CE54C1C9F
+:1068B0003106FFFF38C42F7100051E023062000F41
+:1068C0002486C0B310400007AF8200088CE54C1C42
+:1068D0003C09001F3528FC0000A81824000321C231
+:1068E000AF8400048CF108083C0F57092412F00013
+:1068F0000232702435F0001001D0602601CF6826E6
+:106900002DAA00012D8B0001014B382550E0000914
+:10691000A380000C3C1F601C8FF8000824190001A4
+:10692000A399000C33137C00A7930010A780000EDE
+:10693000A380000DAF80004814C00003AF800000AA
+:106940003C066000ACC0442C0E0005B93C10800031
+:106950000E000F24361101003C12080026523DF0B3
+:106960003C13080026733E708E030000386400015B
+:10697000308200011440FFFC3C0B800A8E26000090
+:106980002407FF8024C90240312A007F014B4021A7
+:1069900001272824AE060020AF880044AE0500245D
+:1069A0003C048000AF86003C8C8C01780580FFFEA3
+:1069B00024180800922F0008AC980178A38F004299
+:1069C000938E004231CD000111A0000F24050D006F
+:1069D00024DFF8002FF903011320001C000629C250
+:1069E00024A4FFF000041042000231400E00020215
+:1069F00000D2D8213C0240003C068000ACC20138E5
+:106A00000A0004A00000000010C50023240D0F00A0
+:106A100010CD00273C1F800837F900809338000014
+:106A2000240E0050330F00FF15EEFFF33C02400030
+:106A30000E000A40000000003C0240003C068000BE
+:106A4000ACC201380A0004A0000000008F830004DB
+:106A500000A3402B1500000B8F8B0008006B50210A
+:106A60002547FFFF00E5482B1520000600A3602303
+:106A7000000C19400E0002020073D8210A0004C461
+:106A80003C0240000000000D0E0002020000000069
+:106A90000A0004C43C0240003C1B0800277B3F70F6
+:106AA0000E000202000000000A0004C43C02400084
+:106AB0003C1B0800277B3F900E00020200000000F4
+:106AC0000A0004C43C0240003C0660043C09080083
+:106AD00025290104ACC9502C8CC850003C0580000D
+:106AE0003C02000235070080ACC750003C0408009F
+:106AF000248415A43C0308002463155CACA500089D
+:106B0000ACA2000C3C010800AC243D803C01080014
+:106B1000AC233D8403E000082402000100A03021E2
+:106B20003C1C0800279C3D883C0C04003C0B0002E8
+:106B3000008B3826008C40262CE200010007502BE9
+:106B40002D050001000A48803C03080024633D80B5
+:106B5000004520250123182110800003000010218A
+:106B6000AC6600002402000103E000080000000001
+:106B70003C1C0800279C3D883C0B04003C0A00029A
+:106B8000008A3026008B38262CC200010006482BD4
+:106B90002CE50001000940803C03080024633D808F
+:106BA0000045202501031821108000050000102158
+:106BB0003C0C0800258C155CAC6C00002402000124
+:106BC00003E00008000000003C0900023C0804004B
+:106BD00000883026008938262CC300010080282137
+:106BE0002CE40001008310251040000B0000302130
+:106BF0003C1C0800279C3D883C0A80008D4E000804
+:106C00002406000101CA6825AD4D00088D4C000C1A
+:106C100001855825AD4B000C03E0000800C0102191
+:106C20003C1C0800279C3D883C0580008CA6000C7D
+:106C3000000420272402000100C4182403E00008F7
+:106C4000ACA3000C3C0200021082000B3C0560006B
+:106C50003C070400108700030000000003E0000868
+:106C6000000000008CA908D0240AFFFD012A40245E
+:106C700003E00008ACA808D08CA408D02406FFFECE
+:106C80000086182403E00008ACA308D03C05601A75
+:106C900034A600108CC3008027BDFFF88CC500848B
+:106CA000AFA3000093A4000024020001108200039F
+:106CB000AFA5000403E0000827BD000893A700016A
+:106CC00014E0001497AC000297B800023C0F80005B
+:106CD000330EFFFC01CF6821ADA50000A3A000008A
+:106CE0003C0660008CC708D02408FFFE3C04601AF4
+:106CF00000E82824ACC508D08FA300048FA20000B0
+:106D00003499001027BD0008AF22008003E000087E
+:106D1000AF2300843C0B8000318AFFFC014B4821EB
+:106D20008D2800000A00057DAFA8000427BDFFE8FC
+:106D3000AFBF00103C1C0800279C3D883C0580002C
+:106D40008CA4000C8CA200043C0300020044282404
+:106D500010A0000A00A318243C0604003C04000212
+:106D60001460000900A610241440000F3C04040025
+:106D70000000000D3C1C0800279C3D888FBF0010C0
+:106D800003E0000827BD00183C0208008C423D804B
+:106D90000040F809000000003C1C0800279C3D88CA
+:106DA0000A0005A68FBF00103C0208008C423D84FB
+:106DB0000040F809000000000A0005AC00000000D7
+:106DC000000411C003E00008244202403C04080013
+:106DD00024843FD42405001A0A00009C00003021BE
+:106DE00027BDFFE0AFB000103C108000AFBF00181F
+:106DF000AFB1001436110100922200090E0005B651
+:106E00003044007F8E3F00008F89003C3C0F0080A3
+:106E100003E26021258800400049F821240DFF800D
+:106E2000310E00783198007835F9000135F1000213
+:106E30000319382501D14825010D302403ED5824CC
+:106E4000018D2824240A004024040080240300C06B
+:106E5000AE0B0024AE000810AE0A0814AE040818E9
+:106E6000AE03081CAE050804AE070820AE060808ED
+:106E7000AE090824360909009539000C3605098049
+:106E800033ED007F3338FFFF001889C0AE110800D2
+:106E9000AE0F0828952C000C8FBF00188FB100147E
+:106EA000318BFFFF000B51C0AE0A002C8CA40050A8
+:106EB0008FB000108CA3003C8D2700048CA8001C10
+:106EC0008CA600383C0E800A01AE102127BD0020A0
+:106ED000AF820044AF840050AF830054AF87004CB2
+:106EE000AF88005C03E00008AF8600603C09080042
+:106EF00091293FF924A800023C05110000093C003B
+:106F000000E8302500C5182524820008AC83000065
+:106F100003E00008AC8000043C0980003523090030
+:106F20009128010B906A001124020028008048215A
+:106F3000314700FF00A0702100C0682131080040E7
+:106F400010E20002340C86DD240C08003C0A8000AC
+:106F500035420A9A94470000354B0A9C35460AA0F0
+:106F600030F9FFFFAD3900008D780000354B0A8005
+:106F700024040001AD3800048CCF0000AD2F0008C0
+:106F80009165001930A300031064009A2864000280
+:106F9000148000B924050002106500A8240F000326
+:106FA000106F00BE35450AA4240A0800118A004D5E
+:106FB00000000000510000423C0B80003C048000B7
+:106FC000348309009067001230E200FF004D782101
+:106FD000000FC880272400013C0A8000354F0900BB
+:106FE00091E50019354C09808D87002830A300FFFA
+:106FF00000031500004758250004C4003C19600038
+:1070000001793025370806FFAD260000AD280004C1
+:107010008DEA002C25280028AD2A00088DEC0030D0
+:10702000AD2C000C8DE50034AD2500108DE400384A
+:10703000AD2400148DE3001CAD2300188DE7002063
+:10704000AD27001C8DE20024AD2200208DF9002820
+:10705000AD3900243C0980003526093C8CCF000066
+:10706000352A0100AD0E0004AD0F00008D4E000C5E
+:107070003523090035250980AD0E0008906C0012FB
+:107080008D47000C8CB900343C18080093183FF869
+:10709000318200FF004D582103277823000B370071
+:1070A0000018240000C4702531E9FFFC01C96825DF
+:1070B00025020014AD0D000C03E00008AD00001027
+:1070C00035780900930600123C05080094A53FE8B6
+:1070D00030C800FF010D5021000A60800A00063C04
+:1070E0000185202115000060000000003C08080018
+:1070F00095083FEE3C06080094C63FE801061021C3
+:107100003C0B80003579090093380011932A00194F
+:1071100035660A80330800FF94CF002A0008608299
+:10712000314500FF978A0058000C1E00000524001E
+:107130003047FFFF006410250047C02501EA3021D9
+:107140003C0B4000030B402500066400AD28000006
+:10715000AD2C0004932500183C03000625280014DC
+:1071600000053E0000E31025AD2200088F24002C0E
+:10717000254F000131EB7FFFAD24000C8F38001C40
+:10718000A78B0058AD3800103C0980003526093C1B
+:107190008CCF0000352A0100AD0E0004AD0F0000B9
+:1071A0008D4E000C3523090035250980AD0E0008F1
+:1071B000906C00128D47000C8CB900343C1808000C
+:1071C00093183FF8318200FF004D582103277823A0
+:1071D000000B37000018240000C4702531E9FFFCC3
+:1071E00001C9682525020014AD0D000C03E000085C
+:1071F000AD0000103C02080094423FF23C0508003C
+:1072000094A53FE835440AA43C07080094E73FE40E
+:10721000948B00000045C8210327C023000B1C00ED
+:107220002706FFF200665025AD2A000CAD200010A5
+:10723000AD2C00140A00063025290018354F0AA489
+:1072400095E50000956400280005140000043C004A
+:107250003459810000EC5825AD39000CAD2B0010DD
+:107260000A000630252900143C0C0800958C3FEEDE
+:107270000A000686258200015460FF4C240A08009B
+:1072800035580AA49706000000061C00006C502523
+:10729000AD2A000C0A000630252900103C03080026
+:1072A00094633FF23C07080094E73FE83C0F080076
+:1072B00095EF3FE494A40000957900280067102121
+:1072C000004F582300041C00001934002578FFEEFD
+:1072D00000D87825346A8100AD2A000CAD2F00104B
+:1072E000AD200014AD2C00180A0006302529001C22
+:1072F00003E00008240207D027BDFFE0AFB200186A
+:10730000AFB10014AFB00010AFBF001C0E00007C86
+:10731000008088218F8800548F87004C3C058008AE
+:1073200034B20080011128213C108000240200802A
+:10733000240300C000A72023AE0208183C068008E2
+:10734000AE03081C18800004AF850054ACC50004CF
+:107350008CC90004AF89004C122000093604098052
+:107360000E00070200000000924C00278E0B0074F4
+:1073700001825004014B3021AE46000C36040980D6
+:107380008C8E001C8F8F005C01CF682319A0000435
+:107390008FBF001C8C90001CAF90005C8FBF001C46
+:1073A0008FB200188FB100148FB000100A00007E59
+:1073B00027BD00208F8600508F8300548F82004CA1
+:1073C0003C05800834A40080AC860050AC83003CAF
+:1073D00003E00008ACA200043C0308008C630054E6
+:1073E00027BDFFF8308400FF2462000130A500FFB4
+:1073F0003C010800AC22005430C600FF3C0780006E
+:107400008CE801780500FFFE3C0C7FFFA3A400037D
+:107410008FAA0000358BFFFF014B4824000627C0D0
+:1074200001244025AFA8000034E201009043000A87
+:10743000A3A000023C1980FFA3A300018FAF0000AE
+:1074400030AE007F3738FFFF01F86024000E6E0079
+:107450003C0A002034E50140018D582535492000C3
+:107460002406FF803C04100027BD0008ACAB000CD4
+:10747000ACA90014A4A00018A0A6001203E0000804
+:10748000ACE40178308800FF30A700FF3C038000A7
+:107490008C6201780440FFFE3C0C8000358A0A00B3
+:1074A0008D4B00203584014035850980AC8B00046C
+:1074B0008D4900240007302B00061540AC890008D8
+:1074C000A088001090A3004CA083002D03E00008CA
+:1074D000A480001827BDFFE8308400FFAFBF001074
+:1074E0000E00076730A500FF8F8300548FBF001088
+:1074F0003C06800034C50140344700402404FF901E
+:107500003C02100027BD0018ACA3000CA0A4001280
+:10751000ACA7001403E00008ACC2017827BDFFE06F
+:107520003C088008AFBF001CAFB20018AFB1001418
+:10753000AFB00010351000808E0600183C078000A8
+:10754000309200FF00C72025AE0400180E00007C1A
+:1075500030B100FF92030005346200080E00007E87
+:10756000A2020005024020210E00077B02202821F4
+:10757000024020218FBF001C8FB200188FB1001471
+:107580008FB0001024050005240600010A00073C06
+:1075900027BD00203C05800034A3098090660008C8
+:1075A00030C200081040000F3C0A01013549080AAA
+:1075B000AC8900008CA80074AC8800043C0708006B
+:1075C00090E73FF830E5001050A00008AC800008BC
+:1075D0003C0D800835AC00808D8B0058AC8B0008CA
+:1075E0002484000C03E00008008010210A0007BF7B
+:1075F0002484000C27BDFFE83C098000AFB00010D8
+:10760000AFBF00143526098090C800092402000687
+:1076100000A05821310300FF352709000080802198
+:10762000240500041062007B2408000294CF005C53
+:107630003C0E020431EDFFFF01AE6025AE0C0000F0
+:1076400090CA0008314400201080000800000000AB
+:1076500090C2004E3C1F010337F90300305800FF71
+:107660000319302524050008AE06000490F9001126
+:1076700090E6001290E40011333800FF0018708289
+:1076800030CF00FF01CF5021014B6821308900FF2E
+:1076900031AAFFFF39230028000A60801460002C03
+:1076A000020C482390E400123C198000372F01009F
+:1076B000308C00FF018B1821000310800045F82159
+:1076C000001F8400360706FFAD270004373F09007E
+:1076D00093EC001193EE0012372609800005C0825A
+:1076E0008DE4000C8CC5003431CD00FF01AB1021BE
+:1076F0000058182100A4F8230008840000033F006C
+:1077000000F0302533F9FFFF318F00FC00D97025E0
+:107710000158202101E9682100045080ADAE000C21
+:107720000E00007C012A80213C088008240B000404
+:10773000350500800E00007EA0AB0009020010217C
+:107740008FBF00148FB0001003E0000827BD0018A1
+:1077500090EC001190E300193C18080097183FEED8
+:10776000318200FF0002F882307000FF001FCE005F
+:1077700000103C000327302500D870253C0F400046
+:1077800001CF68253C198000AD2D0000373F09006E
+:1077900093EC001193EE0012372F01003726098079
+:1077A0000005C0828DE4000C8CC5003431CD00FF93
+:1077B00001AB10210058182100A4F8230008840010
+:1077C00000033F0000F0302533F9FFFF318F00FC4C
+:1077D00000D970250158202101E96821000450805A
+:1077E000ADAE000C0E00007C012A80213C08800810
+:1077F000240B0004350500800E00007EA0AB0009BC
+:10780000020010218FBF00148FB0001003E00008A9
+:1078100027BD00180A0007D12408001227BDFFD099
+:107820003C038000AFB60028AFB50024AFB4002001
+:10783000AFB10014AFBF002CAFB3001CAFB2001843
+:10784000AFB000103467010090E6000B309400FFE9
+:1078500030B500FF30C200300000B0211040009968
+:1078600000008821346409809088000800082E00F8
+:1078700000051E03046000C0240400048F86005429
+:107880003C010800A0243FF83C0C8000AD8000487B
+:107890003C048000348E010091CD000B31A5002006
+:1078A00010A000073C078000349309809272000802
+:1078B0000012860000107E0305E000C43C1F800813
+:1078C00034EC0100918A000B34EB098091690008C7
+:1078D000314400400004402B3123000800C89823A5
+:1078E0001460000224120003000090213C1080006C
+:1078F00036180A8036040900970E002C9083001178
+:107900009089001293050018307F00FF312800FF96
+:10791000024810210002C880930D0018033F78210F
+:1079200001F1302130B100FF00D11821A78E00589D
+:107930003C010800A4263FEE3C010800A4233FF0D0
+:1079400015A00002000000000000000D920B010BCA
+:107950003065FFFF3C010800A4233FF2316A00407C
+:107960003C010800A4203FE83C010800A4203FE4BB
+:107970001140000224A4000A24A4000B3091FFFF50
+:107980000E0001E7022020219206010B3C0C0800AA
+:10799000958C3FF2004020210006698231A700014A
+:1079A0000E000601018728210040202102602821C5
+:1079B0000E00060C024030210E0007AB00402021D3
+:1079C00016C00069004020219212010B325600407F
+:1079D00012C000053C0500FF8C93000034AEFFFF91
+:1079E000026E8024AC9000000E0001FB02202021DA
+:1079F0003C0F080091EF3FF831F100031220001610
+:107A00003C1380088F8200543C0980083528008090
+:107A1000245F0001AD1F003C3C0580088CB90004C8
+:107A200003E02021033FC0231B000002AF9F00544E
+:107A30008CA400040E000702ACA400043C078000E4
+:107A40008CEB00743C04800834830080004B502190
+:107A5000AC6A000C3C138008367000800280202144
+:107A600002A02821A200006B0E0007673C148000D2
+:107A70008F920054368C0140AD92000C8F860048E6
+:107A80003C151000344D000624D60001AF96004886
+:107A90008FBF002CA18600128FB60028AD8D001478
+:107AA0008FB3001CAE9501788FB200188FB50024FB
+:107AB0008FB400208FB100148FB0001003E00008D5
+:107AC00027BD003034640980908F0008000F7600D5
+:107AD000000E6E0305A00033347F090093F8001BED
+:107AE000241900103C010800A0393FF833130002AC
+:107AF0001260FF678F8600548F8200601446FF6516
+:107B00003C0480000E00007C000000003C04800863
+:107B10003485008090A8000924060016310300FF78
+:107B20001066000D0000000090AB00093C07080043
+:107B300090E73FF824090008316400FF34EA0001AF
+:107B40003C010800A02A3FF81089002F240C000AED
+:107B5000108C00282402000C0E00007E00000000A3
+:107B60000A00086A8F8600540E0007C302402821CD
+:107B70000A0008B8004020213C0B8008356A0080CC
+:107B80008D4600548CE9000C1120FF3DAF86005457
+:107B9000240700143C010800A0273FF80A000869E8
+:107BA0003C0C800090910008241200023C01080067
+:107BB000A0323FF8323000201200000B24160001E2
+:107BC0008F8600540A00086A2411000837F80080E4
+:107BD0008F020038AFE200048FF90004AF19003CB7
+:107BE0000A0008763C0780008F8600540A00086A65
+:107BF00024110004A0A200090E00007E0000000075
+:107C00000A00086A8F860054240200140A000944FE
+:107C1000A0A2000927BDFFE8AFB000103C10800013
+:107C2000AFBF001436020100904400090E00076740
+:107C3000240500013C0480089099000E34830080E4
+:107C4000909F000F906F00269089000A33F800FF84
+:107C500000196E000018740031EC00FF01AE5025D1
+:107C6000000C5A00014B3825312800FF3603014033
+:107C70003445600000E830252402FF813C041000F8
+:107C8000AC66000C8FBF0014AC650014A06200123B
+:107C9000AE0401788FB0001003E0000827BD001883
+:107CA00027BDFFE8308400FFAFBF00100E0007675C
+:107CB00030A500FF3C05800034A40140344700405B
+:107CC0002406FF92AC870014A08600128F83005414
+:107CD0008FBF00103C02100027BD0018AC83000CC1
+:107CE00003E00008ACA2017827BDFFD8AFB00010B8
+:107CF000308400FF30B000FF3C058000AFB10014BD
+:107D0000AFBF0020AFB3001CAFB20018000410C218
+:107D100034A6010032030002305100011460000754
+:107D200090D200093C098008353300809268000534
+:107D30003107000810E0000C308A001002402021BA
+:107D40000E00078D02202821240200018FBF002091
+:107D50008FB3001C8FB200188FB100148FB00010C9
+:107D600003E0000827BD00281540003434A50A00B0
+:107D70008CB800248CAF0008130F004B0000382192
+:107D80003C0D800835B30080926C00682406000228
+:107D9000318B00FF116600843C06800034C2010074
+:107DA0009263004C90590009307F00FF53F90004A2
+:107DB0003213007C10E00069000000003213007CE8
+:107DC0005660005C0240202116200009320D00019F
+:107DD0003C0C800035840100358B0A008D65002441
+:107DE0008C86000414A6FFD900001021320D00017A
+:107DF00011A0000E024020213C1880003710010025
+:107E00008E0F000C8F8E005011EE00080000000055
+:107E10000E00084D022028218E19000C3C1F8008FE
+:107E200037F00080AE190050024020210E00077B81
+:107E3000022028210A000999240200013C050800BB
+:107E40008CA5006424A400013C010800AC2400645B
+:107E50001600000D00000000022028210E00077B04
+:107E600002402021926E0068240C000231CD00FFF8
+:107E700011AC0022024020210E00094B000000003E
+:107E80000A000999240200010E0000702404000178
+:107E9000926B0025020B30250E00007EA2660025A5
+:107EA0000A0009DD022028218E6200188CDF000400
+:107EB0008CB9002400021E0217F9FFB13065007F63
+:107EC0009268004C264400013093007F1265004008
+:107ED000310300FF1464FFAB3C0D8008264700010E
+:107EE00030F1007F30E200FF1225000B2407000173
+:107EF000004090210A0009A6241100012405000475
+:107F00000E00073C240600010E00094B0000000093
+:107F10000A000999240200012405FF80024520245B
+:107F200000859026324200FF004090210A0009A6F9
+:107F3000241100010E00084D0220282132070030D4
+:107F400010E0FFA132100082024020210E00078DB8
+:107F5000022028210A000999240200018E690018D4
+:107F60000240202102202821012640250E00096E12
+:107F7000AE6800189264004C24050003240600013A
+:107F80000E00073C308400FF0E0000702404000146
+:107F900092710025021150250E00007EA26A002574
+:107FA0000A000999240200018E6F00183C18800015
+:107FB0000240202101F87025022028210E00077BB5
+:107FC000AE6E00189264004C0A000A2524050004D5
+:107FD000324A0080394900801469FF6A3C0D8008EC
+:107FE0000A0009FE2647000127BDFFC0AFB00018F8
+:107FF0003C108000AFBF0038AFB70034AFB60030E0
+:10800000AFB5002CAFB40028AFB30024AFB200204E
+:108010000E0005BEAFB1001C360201009045000BFA
+:108020000E00098090440008144000E78FBF00381C
+:108030003C08800835070080A0E0006B3606098008
+:1080400090C50000240300503C17080026F73FB0FD
+:1080500030A400FF3C13080026733FC010830003C8
+:108060003C1080000000B82100009821241F00105F
+:108070003611010036120A00361509808E58002488
+:108080008E3400048EAF00208F8C00543C01080019
+:10809000A03F3FF836190A80972B002C8EF600007F
+:1080A000932A00180298702301EC68233C01080011
+:1080B000AC2E3FD43C010800AC2D3FD83C01080059
+:1080C000AC2C3FFCA78B005802C0F809315400FFCC
+:1080D00030490002152000E930420001504000C440
+:1080E0009227000992A90008312800081500000213
+:1080F000241500030000A8213C0A80003543090034
+:1081000035440A008C8D002490720011907000128A
+:10811000907F0011325900FF321100FF02B110218F
+:108120000002C08033EF00FF0319B021028F7021DD
+:1081300002D4602125CB00103C010800A4363FEE9C
+:108140003C010800AC2D40003C010800A42C3FF08D
+:108150003C010800A42B3FEC355601003554098042
+:1081600035510E008F8700548F89005C8E8500206A
+:1081700024080006012730233C010800AC283FF406
+:1081800000A7282304C000B50000902104A000B37C
+:1081900000C5502B114000B5000000003C01080054
+:1081A000AC263FD88E6200000040F80900000000B5
+:1081B0003046000214C0007400408021304B0001A2
+:1081C000556000118E6200043C0D08008DAD3FDC4F
+:1081D0003C0EC0003C04800001AE6025AE2C0000C7
+:1081E0008C980000330F000811E0FFFD0000000034
+:1081F000963F000824120001A79F00408E3900041A
+:10820000AF9900388E6200040040F80900000000B9
+:108210000202802532030002146000B30000000057
+:108220003C09080095293FE43C06080094C63FF04D
+:108230003C0A0800954A3FE63C0708008CE73FDC13
+:10824000012670213C0308008C6340003C080800B4
+:1082500095083FFA01CA20218ED9000C00E9282197
+:10826000249F000200A878210067C02133E4FFFFAB
+:10827000AF9900503C010800AC3840003C010800B8
+:10828000A42F3FE83C010800A42E3FF20E0001E7B6
+:10829000000000008F8D0048004020213C010800B4
+:1082A000A02D3FF98E62000825AC0001AF8C00487C
+:1082B0000040F809000000008F85005402A0302122
+:1082C0000E00060C004020210E0007AB00402021CC
+:1082D0008E6B000C0160F809004020213C0A080068
+:1082E000954A3FF23C06080094C63FE60146482105
+:1082F000252800020E0001FB3104FFFF3C050800A9
+:108300008CA53FD43C0708008CE73FDC00A7202366
+:108310003C010800AC243FD414800006000000009B
+:108320003C0208008C423FF4344B00403C01080002
+:10833000AC2B3FF4124000438F8E00448E2D001072
+:108340008F920044AE4D00208E2C0018AE4C0024BD
+:108350003C04080094843FE80E000704000000007D
+:108360008F9F00548E6700103C010800AC3F3FFC1B
+:1083700000E0F809000000003C1908008F393FD4E4
+:108380001720FF798F870054979300583C11800E77
+:10839000321601000E000733A633002C16C000452C
+:1083A000320300105460004C8EE500043208004097
+:1083B0005500001D8EF000088EE4000C0080F809C6
+:1083C000000000008FBF00388FB700348FB6003038
+:1083D0008FB5002C8FB400288FB300248FB20020FB
+:1083E0008FB1001C8FB0001803E0000827BD0040CB
+:1083F0008F86003C36110E0000072E0000A62025B7
+:10840000AE0400808E4300208E500024AFA30010E5
+:10841000AE2300148FB20010AE320010AE30001C3C
+:108420000A000A7FAE3000180200F80900000000C0
+:108430008EE4000C0080F809000000000A000B38F0
+:108440008FBF003824180001240F0001A5C00020B0
+:10845000A5D800220A000B1AADCF00243C01080069
+:10846000AC203FD80A000AB08E6200003C01080030
+:10847000AC253FD80A000AB08E62000092240009A1
+:108480000E00077B000028218FBF00388FB7003413
+:108490008FB600308FB5002C8FB400288FB3002426
+:1084A0008FB200208FB1001C8FB0001803E00008CD
+:1084B00027BD00403C14800092950109000028214E
+:1084C0000E00084D32A400FF320300105060FFB8C8
+:1084D000320800408EE5000400A0F809000000000A
+:1084E0000A000B32320800405240FFA89793005810
+:1084F0008E3400148F930044AE7400208E35001C1F
+:10850000AE7500240A000B29979300588F8200143F
+:108510000004218003E00008008210213C0780084D
+:1085200034E200809043006900804021106000091F
+:108530003C0401003C0708008CE73FFC8F830030BF
+:1085400000E32023048000089389001C14E3000347
+:108550000100202103E00008008010213C040100FC
+:1085600003E00008008010211120000B0067382371
+:108570003C0D800035AC0980918B007C316A000293
+:10858000114000202409003400E9702B15C0FFF1D0
+:108590000100202100E938232403FFFC00A3C824A4
+:1085A00000E3C02400F9782B15E0FFEA030820213E
+:1085B00030C400030004102314C000143049000329
+:1085C0000000302100A9782101E6702100EE682B1F
+:1085D00011A0FFE03C0401002D3800010006C82B6B
+:1085E000010548210319382414E0FFDA2524FFFC93
+:1085F0002402FFFC00A218240068202103E00008E8
+:10860000008010210A000BA8240900303C0C8000D7
+:108610003586098090CB007C316A00041540FFE963
+:10862000240600040A000BB7000030213C030800B8
+:108630008C63005C8F82001827BDFFE0AFBF00187D
+:10864000AFB1001410620005AFB00010000329C0E4
+:1086500024A40280AF840014AF8300183C10800073
+:1086600036020A0094450032361101000E000B89D3
+:1086700030A43FFF8E240000241FFF803C110080A7
+:108680000082C021031F60243309007F000CC94011
+:1086900003294025330E0078362F00033C0D1000CF
+:1086A000010D502501CF5825AE0C00283608098051
+:1086B000AE0C080CAE0B082CAE0A08309103006912
+:1086C0003C06800C0126382110600006AF8700347C
+:1086D0008D09003C8D03006C0123382318E00082D3
+:1086E000000000003C0B8008356A00803C108000D0
+:1086F000A1400069360609808CC200383C06800023
+:1087000034C50A0090A8003C310C00201180001AEA
+:10871000AF820030240D00013C0E800035D10A00EC
+:10872000A38D001CAF8000248E2400248F8500249C
+:10873000240D0008AF800020AF8000283C01080015
+:10874000A42D3FE63C010800A4203FFA0E000B8D4B
+:10875000000030219228003C8FBF00188FB1001418
+:108760008FB0001000086142AF82002C27BD0020AE
+:1087700003E000083182000190B80032240E0001AD
+:10878000330F00FF000F2182108E004124190002D8
+:108790001099006434C40AC03C03800034640A00A9
+:1087A0008C8F002415E0001E34660900909F003075
+:1087B0002418000533F9003F1338004E240300014C
+:1087C0008F860020A383001CAF860028AF8600247C
+:1087D0003C0E800035D10A008E2400248F850024B1
+:1087E000240D00083C010800A42D3FE63C010800D0
+:1087F000A4203FFA0E000B8D000000009228003CE0
+:108800008FBF00188FB100148FB0001000086142B4
+:10881000AF82002C27BD002003E000083182000158
+:108820008C8A00088C8B00248CD000643C0E800065
+:1088300035D10A00014B2823AF900024A380001CEF
+:10884000AF8500288E2400248F8600208F85002489
+:10885000240D00083C010800A42D3FE63C0108005F
+:10886000A4203FFA0E000B8D000000009228003C6F
+:108870008FBF00188FB100148FB000100008614244
+:10888000AF82002C27BD002003E0000831820001E8
+:1088900090A200303051003F5224002834C50AC055
+:1088A0008CB000241600002234CB09008CA60048AE
+:1088B0003C0A7FFF3545FFFF00C510243C0E8000B9
+:1088C000AF82002035C509008F8800208CAD006084
+:1088D000010D602B15800002010020218CA4006096
+:1088E0000A000C2CAF8400208D02006C0A000C06DC
+:1088F0003C0680008C8200488F8600203C097FFF68
+:108900003527FFFF004788243C048008240300012A
+:10891000AF910028AC80006CA383001C0A000C3AC5
+:10892000AF8600248C9F00140A000C2CAF9F0020FF
+:108930008D6200680A000C763C0E800034C4098009
+:108940008C8900708CA300140123382B10E00004E4
+:10895000000000008C8200700A000C763C0E800043
+:108960008CA200140A000C763C0E80008F85002437
+:1089700027BDFFE0AFBF0018AFB1001414A000087E
+:10898000AFB000103C04800034870A0090E600304D
+:108990002402000530C3003F106200B9348409008E
+:1089A0008F91002000A080213C048000348E0A00BA
+:1089B0008DCD00043C0608008CC63FD831A73FFF90
+:1089C00000E6602B5580000100E03021938F001CF1
+:1089D00011E0007800D0282B349F098093F9007CA7
+:1089E00033380002130000792403003400C3102B35
+:1089F000144000D90000000000C3302300D0282B11
+:108A00003C010800A4233FE414A0006E02001821DA
+:108A10003C0408008C843FD40064402B55000001C6
+:108A2000006020213C05800034A90A00912A003C06
+:108A30003C010800AC243FDC3143002014600003FB
+:108A40000000482134AB0E008D6900188F88002C7F
+:108A50000128202B1080005F000000003C0508006A
+:108A60008CA53FDC00A96821010D602B1180005C02
+:108A700000B0702B0109382300E028213C010800D8
+:108A8000AC273FDC12000003240AFFFC10B0008D6D
+:108A90003224000300AA18243C010800A4203FFA55
+:108AA0003C010800AC233FDC006028218F840024B7
+:108AB000120400063C0B80088D6C006C0200202123
+:108AC000AF91002025900001AD70006C8F8D0028C3
+:108AD00000858823AF91002401A52023AF840028BE
+:108AE0001220000224070018240700103C188008F8
+:108AF0003706008090CF00683C010800A0273FF8AF
+:108B00002407000131EE00FF11C7004700000000FC
+:108B100014800018000028213C06800034D1098010
+:108B200034CD010091A600098E2C001824C4000148
+:108B3000000C86023205007F308B007F1165007FBC
+:108B40002407FF803C19800837290080A124004CAD
+:108B50003C0808008D083FF4241800023C0108007E
+:108B6000A0384039350F00083C010800AC2F3FF415
+:108B7000240500103C02800034440A009083003C2D
+:108B8000307F002013E0000500A02021240A00010E
+:108B90003C010800AC2A3FDC34A400018FBF001860
+:108BA0008FB100148FB000100080102103E0000886
+:108BB00027BD00203C010800A4203FE410A0FF9442
+:108BC000020018210A000CCA00C018210A000CC1BA
+:108BD000240300303C0508008CA53FDC00B0702B5E
+:108BE00011C0FFA8000000003C19080097393FE4BD
+:108BF0000325C0210307782B11E000072CAA0004ED
+:108C00003C0360008C625404305F003F17E0FFE3D8
+:108C1000240400422CAA00041140FF9A24040042BC
+:108C20000A000D2E8FBF00181528FFB900000000A4
+:108C30008CCA00183C1F800024020002015F182526
+:108C4000ACC3001837F90A00A0C200689329003CA1
+:108C50002404000400A01021312800203C01080059
+:108C6000A024403911000002240500102402000154
+:108C70003C010800AC223FD40A000D243C028000D5
+:108C80008F8800288C8900600109282B14A000021D
+:108C9000010088218C9100603C048000348B0E0020
+:108CA0008D640018240A00010220282102203021AE
+:108CB000A38A001C0E000B8D022080210A000CB03C
+:108CC000AF82002C000458231220000731640003F7
+:108CD0003C0E800035C7098090ED007C31AC00046B
+:108CE00015800019248F00043C010800A4243FFAD9
+:108CF0003C1F080097FF3FFA03E5C82100D9C02BAD
+:108D00001300FF6B8F8400242CA6000514C0FFA362
+:108D10002404004230A200031440000200A21823E1
+:108D200024A3FFFC3C010800AC233FDC3C0108000D
+:108D3000A4203FFA0A000CF10060282100C770242B
+:108D40000A000D1701C720263C010800A42F3FFA96
+:108D50000A000D82000000003C010800AC203FDC4E
+:108D60000A000D2D240400428F8300283C0580005A
+:108D700034AA0A0014600006000010219147003058
+:108D80002406000530E400FF108600030000000008
+:108D900003E0000800000000914B0048316900FF2B
+:108DA000000941C21500FFFA3C0680083C04080097
+:108DB00094843FE43C0308008C633FFC3C190800AA
+:108DC0008F393FDC3C0F080095EF3FFA0064C0216B
+:108DD0008CCD00040319702101CF602134AB0E004B
+:108DE000018D282318A0001D00000000914F004CA9
+:108DF0008F8C0034956D001031EE00FF8D890004DA
+:108E000001AE30238D8A000030CEFFFF000E290016
+:108E10000125C82100003821014720210325182BF6
+:108E20000083C021AD990004AD980000918F000A25
+:108E300001CF6821A18D000A956500128F8A003448
+:108E4000A5450008954B003825690001A549003863
+:108E50009148000D35070008A147000D03E0000808
+:108E60000000000027BDFFD8AFB000189388001C99
+:108E70008FB000143C0A80003C197FFF8F870024CC
+:108E80003738FFFFAFBF0020AFB1001C355F0A00CD
+:108E90000218182493EB003C00087FC03C02BFFF7F
+:108EA000006F60252CF000013449FFFF3C1F0800D3
+:108EB0008FFF3FFC8F9900303C18080097183FF255
+:108EC00001897824001047803C07EFFF3C05F0FF44
+:108ED00001E818253C1180003169002034E2FFFFD1
+:108EE00034ADFFFF362E098027A5001024060002AE
+:108EF00003F96023270B0002354A0E000062182494
+:108F00000080802115200002000040218D48001CB7
+:108F1000A7AB0012058000392407000030E800FFED
+:108F200000083F00006758253C028008AFAB0014E2
+:108F3000344F008091EA00683C08080091083FF92E
+:108F40003C09DFFF352CFFFF000AF82B3C0208002C
+:108F500094423FECA3A80011016CC024001FCF4035
+:108F6000031918258FA70010AFA300143C0C0800AC
+:108F7000918C3FFBA7A200168FAB001400ED482494
+:108F80003C0F01003C0A0FFF012FC8253198000358
+:108F9000355FFFFF016D40243C027000033F382421
+:108FA00000181E0000E2482501037825AFAF001429
+:108FB000AFA9001091CC007C0E000092A3AC00156C
+:108FC000362D0A0091A6003C30C400201080000617
+:108FD000260200083C11080096313FE8262EFFFFCC
+:108FE0003C010800A42E3FE88FBF00208FB1001C79
+:108FF0008FB0001803E0000827BD00288F8B002CDD
+:10900000010B502B5540FFC5240700010A000E0E2E
+:1090100030E800FF9383001C3C02800027BDFFD88E
+:1090200034480A0000805021AFBF002034460AC0F7
+:10903000010028211060000E34440980910700309F
+:10904000240B00058F89002030EC003F118B000BB2
+:1090500000003821AFA900103C0B80088D69006C1E
+:10906000AFAA00180E00015AAFA90014A380001C7B
+:109070008FBF002003E0000827BD00288D1F004897
+:109080003C1808008F183FDC8F9900283C027FFFB6
+:109090008D0800443443FFFFAFA900103C0B80084B
+:1090A0008D69006C03E370240319782101CF6823D4
+:1090B00001A83821AFAA00180E00015AAFA9001468
+:1090C0000A000E62A380001C3C05800034A60A0042
+:1090D00090C7003C3C06080094C63FFA3C020800DA
+:1090E0008C423FF430E30020000624001060001E94
+:1090F000004438253C0880083505008090A30068AE
+:109100000000482124080001000028212404000157
+:109110003C0680008CCD017805A0FFFE34CF0140D5
+:10912000ADE800083C0208008C423FFCA5E50004C5
+:10913000A5E40006ADE2000C3C04080090843FF971
+:109140003C03800834790080A1E40012ADE70014EC
+:10915000A5E900189338004C3C0E1000A1F8002D32
+:1091600003E00008ACCE017834A90E008D28001C65
+:109170003C0C08008D8C3FDC952B0016952A0014C2
+:10918000018648213164FFFF0A000E8A3145FFFF46
+:109190003C04800034830A009065003C30A200202B
+:1091A0001040001934870E000000402100003821D3
+:1091B000000020213C0680008CC901780520FFFEBC
+:1091C00034CA014034CF010091EB0009AD480008DA
+:1091D0003C0E08008DCE3FFC240DFF91240C004076
+:1091E0003C081000A5440004A5470006AD4E000C45
+:1091F000A14D0012AD4C0014A5400018A14B002D4C
+:1092000003E00008ACC801788CE8001894E600126E
+:1092100094E4001030C7FFFF0A000EB33084FFFF54
+:109220003C04800034830A009065003C30A200209A
+:109230001040002727BDFFF8240900010000382155
+:10924000240800013C0680008CCA01780540FFFE1E
+:109250003C0280FF34C40100908D00093C0C0800E2
+:10926000918C4039A3AD00038FAB00003185007FA6
+:109270003459FFFF01665025AFAA00009083000A11
+:10928000A3A0000200057E00A3A300018FB8000088
+:1092900034CB0140240C30000319702401CF682521
+:1092A000AD6D000C27BD0008AD6C0014A560001862
+:1092B000AD690008A56700042409FF80A5680006C1
+:1092C0003C081000A169001203E00008ACC8017856
+:1092D00034870E008CE9001894E6001294E4001024
+:1092E00030C8FFFF0A000ED73087FFFF27BDFFE021
+:1092F000AFB100143C118000AFB00010AFBF001838
+:1093000036380A00970F0032363001000E000B8904
+:1093100031E43FFF8E0E0000240DFF803C0420004E
+:1093200001C25821016D6024000C4940316A007F60
+:10933000012A4025010438253C048008AE27083066
+:109340003486008090C500682403000230A200FF2C
+:10935000104300048F9F00208F990024AC9F006869
+:10936000AC9900648FBF00188FB100148FB000104B
+:1093700003E0000827BD00203C0A0800254A3AA85F
+:109380003C09080025293B383C08080025082F44E3
+:109390003C07080024E73C043C06080024C6392C9E
+:1093A0003C05080024A536803C040800248432844F
+:1093B0003C030800246339E03C0208002442377C67
+:1093C0003C010800AC2A3FB83C010800AC293FB47E
+:1093D0003C010800AC283FB03C010800AC273FBC72
+:1093E0003C010800AC263FCC3C010800AC253FC442
+:1093F0003C010800AC243FC03C010800AC233FD036
+:109400003C010800AC223FC803E000080000000057
+:109410008000094080000900800801008008008069
+:1094200080080000800E0000800800808008000096
+:1094300080000A8080000A00800009808000090006
+: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-rv2p-06-5.0.0.j3.fw.ihex b/firmware/bnx2/bnx2-rv2p-06-5.0.0.j3.fw.ihex
deleted file mode 100644
index 52c4963..0000000
--- a/firmware/bnx2/bnx2-rv2p-06-5.0.0.j3.fw.ihex
+++ /dev/null
@@ -1,424 +0,0 @@
-:100000000000000000000C900000005800000009F3
-:1000100000000000000000000000000000000000E0
-:1000200000000000000000000000000000000000D0
-:1000300000000CE000000CE80000000500000000DB
-:1000400000000000000000000000000000000000B0
-:080050000000000000000000A8
-:0800580000000010B180000659
-:100060000000001F01030300000000080500FFFF5F
-:10007000000000180002000000000008050000FF5A
-:10008000000000180002000000000008AC000001A1
-:1000900000000000050000000000000C2F8000019F
-:1000A000000000002B000000000000002B8000007A
-:1000B0000000001091E0000200000008AC00000108
-:1000C00000000010203F004D00000010213F000301
-:1000D0000000001020BF001C000000188000FFFD81
-:1000E00000000008B1000001000000082C8000B0F2
-:1000F000000000082D000008000000082D8000010D
-:10010000000000188000006C0000000B2FDF0002D0
-:100110000000000C1F800002000000002C070000FF
-:100120000000001091DE0000000000080500555599
-:10013000000000188000FFF00000000B2FDF00021D
-:100140000000000C1F800000000000002C070000D1
-:100150000000001091DE0000000000080500555569
-:10016000000000188000FFEA0000000C1F80000261
-:100170000000000805005555000000188000FFE74A
-:100180000000000C298000020000000C1F8000020B
-:10019000000000002ADF0000000000082A0000051F
-:1001A0000000000805005555000000188000FFE120
-:1001B000000000080224002C0000001800040000C9
-:1001C000000000188000001C000000188000001EC5
-:1001D000000000188000006500000018800000B0DA
-:1001E00000000018800000AF000000188000000030
-:1001F00000000018800000000000001880000000CF
-:1002000000000018800000000000001880000000BE
-:1002100000000018800000000000001880000000AE
-:10022000000000188000000000000018800000F6A8
-:10023000000000188000000000000018800000008E
-:100240000000001880000015000000188000001B4E
-:10025000000000188000000000000018800000C6A8
-:10026000000000188000002F00000018800000F639
-:10027000000000188000012100000018800000EC40
-:100280000000001880000145000000188000004EAA
-:1002900000000018800000000000001880000083AB
-:1002A0000000000C1F80000100000000050000009D
-:1002B000000000188000FFC00000001091D4000072
-:1002C0000000000C298000010000000C1F800001CC
-:1002D000000000082A0000020000000005000000E5
-:1002E000000000188000FFBA0000001091D4000048
-:1002F0000000000C298000010000000C1F8000019C
-:100300000000000029420000000000082A0000024E
-:100310000000000005000000000000188000FFB38E
-:10032000000000188000FFB200000010B1BCB00A4D
-:100330000000000B2FDF00020000000003D80000C7
-:10034000000000002C3C00000000001091D40000D0
-:100350000000000806005555000000188000001736
-:1003600000000018800000BF000000102C6201BADD
-:100370000000001880000006000000082C8000B17A
-:10038000000000082D0000090000001091D40000BA
-:10039000000000082D8001070000001880000024E4
-:1003A0000000000C298000000000000C1F800000ED
-:1003B0000000001091DE0000000000002ADF0000B5
-:1003C000000000082A00000600000008050055553E
-:1003D000000000188000FF9C0000001091D4000075
-:1003E0000000000C298000010000000C1F800001AB
-:1003F000000000082A00000B0000000005000000BB
-:10040000000000188000FF960000001800020000A5
-:10041000000000000682000000000010B18A000801
-:1004200000000010B18C14070000000B050AFFFF4C
-:1004300000000010B18A000300000000860A1800C6
-:1004400000000010918C0000000000082A0000014C
-:100450000000001091D4000000000018000D000002
-:1004600000000000050200000000001091DE000006
-:1004700000000018000A00000000000006820000D2
-:100480000000001091DE000000000010BEE1000539
-:10049000000000188000FF7D0000000105611400CD
-:1004A00000000010918A000200000008B0E1000185
-:1004B00000000018000D000000000000068200008F
-:1004C0000000001091DE000000000010BEE20005F8
-:1004D000000000188000FF75000000010562140094
-:1004E00000000010918A000200000008B1620001C3
-:1004F00000000018000D000000000010B1A0B013B3
-:100500000000000B2FDF0002000000002C20000084
-:10051000000000082C800000000000082D000000F2
-:100520000000001091D4000000000008060055559E
-:10053000000000188000FFDC000000082D80011C76
-:1005400000000010001F0000000000188000FFE6FF
-:100550000000000F476000080000000F060E0001B9
-:10056000000000000F580000000000000A640000B6
-:10057000000000000AE50000000000090B66FFFF14
-:10058000000000000D610000000000188000001352
-:100590000000000F476000080000000B2FDF000282
-:1005A000000000082C800000000000082D00000062
-:1005B0000000001091D40000000000082D80011CF4
-:1005C0000000000F060E000100000010001F0000D8
-:1005D000000000000F580000000000188000FFD449
-:1005E000000000000A640000000000000AE50000AE
-:1005F000000000090B66FFFF000000000D61000015
-:1006000000000000026200000000000B2FDF00026B
-:10061000000000003104000000000000309A0000DB
-:10062000000000000C961800000000090C99FFFF64
-:1006300000000004CC99340000000010B196320292
-:10064000000000080F8000000000000C298000015D
-:100650000000000C295200010000000C295200008B
-:10066000000000080200000E000000080280001ACE
-:1006700000000010B1C40A020000000802000003DC
-:1006800000000008220000010000000C1F80000193
-:10069000000000002ADF0000000000002A0008001F
-:1006A0000000000805005555000000188000FF41BB
-:1006B0000000000B2FDF00020000001091D40000AA
-:1006C000000000082A000001000000002C200000AB
-:1006D0000000001091D40000000000082C800000F1
-:1006E000000000082D000000000000082D80011C03
-:1006F000000000188000FFAE000000082C800006FB
-:10070000000000082D0000060000000030800000FE
-:100710000000000031000000000000082D800006ED
-:100720000000000C298000010000000C1F80000167
-:100730000000001091DE0000000000002ADF000031
-:10074000000000082A000010000000000500000062
-:10075000000000188000FF2C0000001091A0B009DC
-:10076000000000082C8000B1000000082D000009E6
-:100770000000001091D40000000000082D80010747
-:10078000000000188000FFA7000000188000001083
-:1007900000000008AC000001000000188000000B01
-:1007A000000000000380B0000000000B2FDF0002FB
-:1007B000000000002C0040000000001091D4000058
-:1007C0000000000806005555000000188000FF8951
-:1007D00000000018800000310000001880000006B2
-:1007E0000000000B2FDF0002000000002C000E00B4
-:1007F000000000082A000007000000080500555509
-:10080000000000188000FF160000000006820000B3
-:100810000000000C298000010000000C1F80000176
-:10082000000000100CE70007000000090562FFFF50
-:1008300000000010BA6C1405000000002ADF000060
-:100840000000000021000000000000082A00000550
-:100850000000001091D40000000000082C8000B0BF
-:10086000000000082D0000080000000C3162001894
-:10087000000000082D800001000000188000FF7DAE
-:1008800000000018000D000000000010B1A0B00E24
-:100890000000000B2FDF00020000000003D8000062
-:1008A000000000002C2000000000001091D4000087
-:1008B0000000001880000015000000102C620002EB
-:1008C000000000188000000C0000000B2FDF000269
-:1008D000000000002C0700000000000C1F80000139
-:1008E0000000001091DE0000000000080500FFFF7E
-:1008F000000000188000FEF8000000082C8000B105
-:10090000000000082D0000090000001091D4000034
-:10091000000000082D800107000000188000FF740F
-:100920000000000C298000010000000C1F80000165
-:100930000000001091DE0000000000002ADF00002F
-:10094000000000082A00000A000000000500000066
-:10095000000000188000FEEC00000000068200008D
-:10096000000000082C8000B0000000082D000008E6
-:10097000000000082D800150000000000000000071
-:100980000000001091DE0000000000082C80000034
-:10099000000000082D000000000000082D80010567
-:1009A00000000010BEE20005000000188000FEDA22
-:1009B000000000010562140000000010918A00028E
-:1009C00000000008B16200010000001091DE00008C
-:1009D00000000018000D00000000001091D400007D
-:1009E000000000080600AAAA000000188000FF45C9
-:1009F0000000000C298000010000000C1F80000195
-:100A0000000000082A000009000000080500AAAA4A
-:100A1000000000188000FED40000001091D40000F7
-:100A20000000000806005555000000188000FF3D3A
-:100A30000000001091A03C0200000010B1E6620727
-:100A40000000000B2FDF0002000000002C3100002E
-:100A5000000000092CB1007F000000082CD9000024
-:100A6000000000082D000000000000082D80010D8E
-:100A700000000010B1A8000600000010205F000078
-:100A8000000000002C200000000000002CA7000047
-:100A9000000000082D000010000000082D80010853
-:100AA000000000188000FF3800000010B1A6001000
-:100AB00000000010001F00000000000F0F300007B2
-:100AC000000000000A600000000000000AE10000D1
-:100AD0000000000F4B620008000000090B1600FF29
-:100AE000000000000D620000000000090D1A00FF68
-:100AF00000000010073000030000000C0D1A000871
-:100B00000000000C0B1600080000000F4CE300185A
-:100B1000000000000C992C0000000004CC99340067
-:100B2000000000080F8000000000000C2980000178
-:100B30000000000033310000000000082200001611
-:100B4000000000002ADF0000000000082A00000C5E
-:100B500000000010009F0000000000000F200000B7
-:100B60000000000C1F800001000000080500555522
-:100B7000000000188000FEA80000001091D40000C2
-:100B8000000000080600AAAA000000188000FF115B
-:100B90000000000F4722000800000009070E000FA8
-:100BA00000000008070E0008000000080280000195
-:100BB0000000000702851C0000000008828500017B
-:100BC0000000000002854C000000000742851C0068
-:100BD00000000003C3AA52000000000003B10E0091
-:100BE000000000074B071C000000000F0F3000073B
-:100BF0000000000F0A960003000000000A955C0048
-:100C0000000000004A005A00000000000C960A0094
-:100C1000000000090C99FFFF000000080D00FFFF15
-:100C200000000010B1963202000000080F8000059D
-:100C300000000010B1A8000800000010205F0000B4
-:100C40000000000B2FDF0002000000002C2000003D
-:100C5000000000002CA70000000000082D0000107C
-:100C6000000000082D800108000000188000FEFF31
-:100C70000000000C2980000100000010001F00008F
-:100C80000000000C1F800001000000002ADF0000AF
-:100C9000000000082A00000D000000080500AAAAB4
-:100CA000000000188000FE820000001091D40000B7
-:100CB0000000000806005555000000188000FEEBFB
-:100CC0000000000C298000010000000C1F800001C2
-:100CD000000000082A000007000000080500555524
-:080CE000000000188000FE7AFC
-:080CE80000000010B1800004BF
-:100CF0000000001F0103030000000008050000FFC2
-:100D00000000001800020000000000002A0000009F
-:100D100000000010B1D400000000001091DE0000BF
-:100D2000000000102053000000000010001F000011
-:100D3000000000002F80AA000000000C29800001A4
-:100D4000000000080254000D000000002C400000CC
-:100D500000000018000400000000001880000010CF
-:100D60000000001880000011000000188000003909
-:100D700000000018800000DF00000018800000DE86
-:100D800000000018800000DD00000018800000DD79
-:100D9000000000188000000000000018800000F52E
-:100DA00000000018800000D9000000188000000B2F
-:100DB00000000018800000F90000001880000147C2
-:100DC000000000188000005900000018800000C4D6
-:100DD00000000018800000C5000000002A0000008C
-:100DE000000000188000FFE6000000002A0000005C
-:100DF0000000000C29800000000000188000FFE3C4
-:100E0000000000002A000000000000188000FFE140
-:100E100000000018000200000000000005020000B1
-:100E2000000000109196342100000010205F0000A7
-:100E3000000000002C1E0000000000082C800006AE
-:100E4000000000082D000006000000082D800102AF
-:100E500000000000000000000000001091DE000013
-:100E6000000000000D61000000000018000A0000F2
-:100E700000000000050200000000001091963416EA
-:100E800000000010205F00000000000009D80000F2
-:100E9000000000002C1E0000000000082C8000B2A2
-:100EA000000000082D00000A000000082D8001024B
-:100EB00000000000000000000000001091DE0000B3
-:100EC000000000000D620000000000002C13000074
-:100ED00000000018000A00000000000005020000E9
-:100EE000000000109196340900000010205F0000FF
-:100EF000000000002C1E0000000000082C800006EE
-:100F0000000000082D00006A000000082D8001028A
-:100F100000000000000000000000001091DE000052
-:100F2000000000000D7A000000000018000A000018
-:100F3000000000002A000000000000000D61000019
-:100F4000000000000362000000000010234200A324
-:100F50000000000002638C00000000002646000034
-:100F6000000000080204001200000010B906081E6C
-:100F7000000000000F580000000000000A6400009C
-:100F8000000000000AE50000000000090B66FFFFFA
-:100F9000000000000C000000000000000B800000BA
-:100FA000000000080CC60012000000188000FFCEF0
-:100FB000000000080F800003000000000000000097
-:100FC00000000010009F0000000000082711001220
-:100FD000000000006690000000000008A31B001243
-:100FE00000000010B198000300000010001F000076
-:100FF000000000080F800004000000082200000329
-:10100000000000082C80000C000000082D00000CDF
-:1010100000000010009F0000000000002596000066
-:101020000000000C298000000000000032140000C5
-:1010300000000000329500000000000573662C00DF
-:101040000000000031E32E00000000082D80001099
-:10105000000000188000FF9800000000230000003E
-:101060000000000925E6FFFF000000082200000B39
-:101070000000000C695200000000000C29800000F4
-:10108000000000188000FF92000000002A0000000D
-:10109000000000082C800040000000082D00002007
-:1010A000000000082D80011C00000000000000006E
-:1010B0000000001091DE00000000000F42EA001066
-:1010C00000000010004F000400000010B74692001E
-:1010D000000000080249001200000010B5840A0058
-:1010E000000000000D61000000000010BA663457D7
-:1010F000000000088305001200000010004F0002ED
-:1011000000000000034900000000000183068C007D
-:101110000000000083C60C0000000010B187001121
-:10112000000000000B6E000000000010BEE900058A
-:10113000000000188000FF7900000001056914001C
-:1011400000000010918A000200000008B4E90001CC
-:1011500000000010B1E92C4A0000000086692C0054
-:1011600000000000020000000000000902EAFFFF8A
-:1011700000000010000C00020000000002040A0041
-:101180000000000F460C00010000000F0285000166
-:1011900000000010918C01FC00000010B7040E410B
-:1011A000000000000F400000000000000D61000082
-:1011B000000000000A640000000000000AE50000D2
-:1011C000000000090B66FFFF000000000C0000009B
-:1011D000000000000B800000000000080C860012D8
-:1011E000000000080F8000030000000C29520000DE
-:1011F00000000010009F00000000000827110012EE
-:10120000000000006690000000000000264600007C
-:10121000000000002306000000000010B198000547
-:1012200000000010001F0000000000080F800004F4
-:10123000000000000000000000000010001F00007F
-:101240000000000032140000000000003295000091
-:101250000000000031E32E000000000573662C0042
-:10126000000000002596000000000010B187001665
-:101270000000000C298000000000000F0F6B000729
-:10128000000000000D690000000000000A6C000072
-:10129000000000000AED0000000000000B6E0000DE
-:1012A000000000000B800000000000000C87000020
-:1012B000000000080F800003000000102053000011
-:1012C0000000000C6952000100000010001F000027
-:1012D0000000000022C58C0000000000231B00005D
-:1012E0000000000027110000000000002690000010
-:1012F00000000010B8170E030000000C2980000049
-:10130000000000188000FFF600000010B1980002F5
-:10131000000000080F800004000000082200001AEE
-:10132000000000082C80000C000000082D00000CBC
-:10133000000000082D80001000000010001F0000B9
-:10134000000000000D6E000000000003E7CF340035
-:101350000000000C298000000000001091DE000059
-:1013600000000010B18700070000000036140000E4
-:101370000000000036950000000000003716000055
-:10138000000000082C800050000000082D000030F4
-:10139000000000082D80000C000000188000FF2FC6
-:1013A00000000000264600000000000023000000AE
-:1013B0000000000925E6FFFF000000000B6E0000A2
-:1013C00000000003E7CF2C00000000082200001BF3
-:1013D0000000000C695200000000000C2980000091
-:1013E000000000188000FF26000000002A00000016
-:1013F000000000188000FF24000000002A00000008
-:101400000000000C298000000000001091DE0000A8
-:10141000000000082C80001A000000082D00001AAF
-:101420000000000573660000000000082D80000227
-:1014300000000000318000000000001091DE00007C
-:10144000000000082C80000C000000082D00000C9B
-:10145000000000082D800004000000188000FF1725
-:101460000000001800020000000000188000FF15B6
-:10147000000000002A00000000000010001F000013
-:10148000000000000F008000000000080F8000072F
-:10149000000000188000001A00000000280A000068
-:1014A0000000000005020000000000082200000902
-:1014B00000000000290000000000000F6568001017
-:1014C00000000003F66C940000000010B972A00444
-:1014D0000000000C73E700190000000C214200041A
-:1014E000000000003CF800000000000C2980000013
-:1014F0000000001020530000000000082200000837
-:101500000000000C6142000400000018000A000006
-:1015100000000000050200000000000C6142000015
-:1015200000000010014200030000000C33E7001D22
-:101530000000000C6142000200000018000A0000D8
-:10154000000000002A00000000000010001F000042
-:101550000000000F0F470007000000080F80000880
-:101560000000000C2980000000000010009F000017
-:10157000000000188000FEF400000000335100005D
-:10158000000000002A00000000000010B1C6002387
-:101590000000000F0F500007000000000A6000006C
-:1015A000000000000AE100000000000F4B6200088C
-:1015B000000000090B1600FF0000000F4C62001035
-:1015C000000000000D620000000000090D1A00FF7D
-:1015D00000000010075000030000000C0D1A000866
-:1015E0000000000C0B160008000000000CC60000F4
-:1015F000000000000B8000000000000006980000C2
-:10160000000000080F8000030000001006C2000464
-:101610000000000C29000002000000102642000219
-:101620000000000C29520003000000082200000105
-:1016300000000010009F000000000000231B0000BD
-:101640000000000027111A00000000006690000052
-:101650000000000C2952000000000010B197320970
-:101660000000000C29800000000000000698000027
-:1016700000000010205300000000000C295200035D
-:101680000000000022C58C0000000010001F0000B8
-:10169000000000080F800003000000188000FFF326
-:1016A00000000010B1C8001300000010B1C6000314
-:1016B0000000000C298000000000001020530000F2
-:1016C0000000000C295200000000000C2952000309
-:1016D0000000001006C200020000000C29520002A7
-:1016E0000000000022C58C000000000027650000FB
-:1016F0000000000026E400000000000822000016A0
-:1017000000000010B1C600030000000023480000E4
-:1017100000000010B1800005000000002348000018
-:101720000000000C298000000000000F0F5000078F
-:1017300000000018800000120000000822000016BF
-:101740000000000C298000000000000030140000A0
-:10175000000000003095000000000010075000035A
-:10176000000000090B1600FF000000090D1A00FF21
-:101770000000000F31160008000000003162340044
-:1017800000000003F162300000000010205F000044
-:10179000000000002C510000000000092CD1007F47
-:1017A000000000082CD90000000000082D000000F7
-:1017B000000000082D80000C000000000000000068
-:1017C0000000001091DE00000000001005C20004BF
-:1017D000000000080F800007000000003300000038
-:1017E00000000010009F0000000000188000FEA50F
-:1017F000000000002A0000000000000F0F5000074A
-:1018000000000010B1C6002D0000000F4742000884
-:1018100000000009070E000F00000008070E000876
-:1018200000000010001F0000000000080900000177
-:101830000000000709121C0000000003CBCA920040
-:10184000000000000B97A2000000000742171C00D8
-:10185000000000000B0400000000000F0A840003D9
-:10186000000000000A959C00000000004A009A0059
-:101870000000000882120001000000010C1708009F
-:10188000000000000C978C0000000000021800000F
-:10189000000000080D00FFFF000000080F80000698
-:1018A0000000000C290000000000001006C2000427
-:1018B0000000000C29520002000000102642000225
-:1018C0000000000C29520003000000082200000163
-:1018D00000000010009F000000000010B197320CC3
-:1018E00000000000231B000000000000271108007A
-:1018F00000000000669000000000000C298000003D
-:10190000000000000218000000000010205300003A
-:101910000000000C295200030000000022C5360020
-:1019200000000010001F0000000000080F800006EB
-:10193000000000188000FFF400000000231B0000DE
-:101940000000000027110800000000006690000061
-:1019500000000010B1C8000B0000000C298000003E
-:1019600000000010205300000000000C295200006D
-:101970000000000C295200030000001006C2000203
-:101980000000000C295200020000000022C58C005B
-:1019900000000000276500000000000026E40000B1
-:1019A000000000002348000000000008220000178B
-:1019B0000000000C2980000000000010001F000043
-:0819C000000000188000FE6A1F
-: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-rv2p-06-6.0.15.fw.ihex b/firmware/bnx2/bnx2-rv2p-06-6.0.15.fw.ihex
new file mode 100644
index 0000000..dcc443e
--- /dev/null
+++ b/firmware/bnx2/bnx2-rv2p-06-6.0.15.fw.ihex
@@ -0,0 +1,366 @@
+:1000000000000000000008F800000058000000098F
+:1000100000000000000000000000000000000000E0
+:1000200000000000000000000000000000000000D0
+:1000300000000CF000000950000000050000000066
+:1000400000000000000000000000000000000000B0
+:080050000000000000000000A8
+:0800580000000010B180000659
+:100060000000001F0106000F000000080500FFFF50
+:10007000000000180002000000000008050000FF5A
+:10008000000000180002000000000008AC000001A1
+:1000900000000008078000000000000C2F80000115
+:1000A000000000002B000000000000002B8000007A
+:1000B0000000001091E1000200000008AC00000107
+:1000C00000000010203F003B00000010213F000313
+:1000D0000000001020BF0015000000188000FFFD88
+:1000E0000000000C1F800002000000188000FFF9D3
+:1000F00000000008B1000001000000082C8000B0E2
+:10010000000000082D000008000000082D800001FC
+:10011000000000188000003C0000000B2FDF0002F0
+:100120000000000C1F800002000000002C070000EF
+:100130000000001091DE0000000000188000FFEFBA
+:100140000000000B2FDF00020000000C1F800000E9
+:10015000000000002C0700000000001091DE0000ED
+:10016000000000188000FFEA0000000C1F80000261
+:10017000000000188000FFE80000000802240025AD
+:1001800000000018000400000000001880000000BB
+:10019000000000188000001B0000001880000042D2
+:1001A000000000188000000000000018800000001F
+:1001B000000000188000000000000018800000000F
+:1001C00000000018800000000000001880000000FF
+:1001D00000000018800000000000001880000000EF
+:1001E00000000018800000000000001880000000DF
+:1001F000000000188000008E000000188000000041
+:1002000000000018800000000000001880000000BE
+:1002100000000018800000000000001880000000AE
+:10022000000000188000000000000018800000009E
+:10023000000000188000008D00000018800000B74A
+:10024000000000188000008400000018800000DA20
+:10025000000000188000002B000000188000000043
+:10026000000000188000006B0000001091D4000016
+:100270000000000C298000010000000C1F8000011C
+:10028000000000082A0000020000000807800000AB
+:10029000000000188000FFC4000000080380010077
+:1002A00000000010B73C0E000000001880000000A5
+:1002B000000000180002000000000000068200009C
+:1002C00000000010B18F000400000010B18F140373
+:1002D000000000082A0000010000001091D4000076
+:1002E000000000000780140000000018000D00004E
+:1002F00000000000050200000000001091DE000078
+:1003000000000018000A0000000000000682000043
+:100310000000001091DE0000000000090561FFFFF1
+:1003200000000010918A00020000000830E1FFFF89
+:10033000000000188000FFA9000000010561140002
+:1003400000000010918A000200000008B0E10001E6
+:1003500000000018000D00000000000006820000F0
+:100360000000001091DE0000000000090562FFFFA0
+:1003700000000010918A0002000000083162FFFFB7
+:10038000000000188000FF9F0000000105621400BB
+:1003900000000010918A000200000008B162000114
+:1003A00000000018000D000000000010B1A0B01304
+:1003B0000000000B2FDF0002000000002C200000D6
+:1003C000000000082C800000000000082D00000044
+:1003D0000000001091D40000000000080500005546
+:1003E000000000188000FFDB000000082D80011CC9
+:1003F00000000010001F0000000000188000FFE255
+:100400000000000F476000080000000F060E00010A
+:10041000000000000F580000000000000A64000007
+:10042000000000000AE50000000000090B66FFFF65
+:10043000000000000D6100000000001880000015A1
+:100440000000000F476000080000000B2FDF0002D3
+:10045000000000082C800000000000082D000000B3
+:100460000000001091D40000000000082D80011C45
+:100470000000000F060E000100000010001F000029
+:10048000000000000F580000000000188000FFD09E
+:10049000000000000A640000000000000AE50000FF
+:1004A000000000090B66FFFF000000000D61000066
+:1004B00000000000026200000000000002E00000F6
+:1004C0000000000B2FDF00020000000030050000DC
+:1004D000000000003104000000000000309A00001D
+:1004E000000000100060000A00000008051600016E
+:1004F00000000010BA9A140300000000030000007E
+:100500000000001880000006000000188000FF6C4A
+:1005100000000010B60614040000000803060001E5
+:10052000000000082A000001000000188000FF7190
+:10053000000000000C961800000000090C99FFFF55
+:1005400000000004CC99340000000010BA992C027D
+:10055000000000080F8000000000000C298000014E
+:100560000000000C295200010000000C295200007C
+:100570000000000822800002000000080200000EB7
+:10058000000000080280001A00000010B1C40A0236
+:1005900000000008020000030000000C1F800001A2
+:1005A000000000002ADF0000000000002A00080010
+:1005B000000000188000FF600000000B2FDF000229
+:1005C0000000001091D40000000000082A00000183
+:1005D000000000002C2000000000001091D400005A
+:1005E000000000082C800000000000082D00000022
+:1005F000000000082D80011C000000188000FF9FF3
+:10060000000000082C800006000000082D000006F5
+:1006100000000000308000000000000031000000F9
+:10062000000000082D8000060000000C2980000159
+:100630000000000C1F8000010000001091DE00008F
+:10064000000000002ADF0000000000082A0000105F
+:100650000000000807800000000000188000FF4B29
+:100660000000001091D4000000000008050000AA5E
+:10067000000000188000FF890000000C29800001A4
+:100680000000000C1F800001000000082A00000983
+:10069000000000188000FF440000001091D400000A
+:1006A0000000000805000055000000188000FF82CF
+:1006B0000000001091A0B00200000010B1E6620737
+:1006C0000000000B2FDF0002000000002C310000B2
+:1006D000000000092CB1007F000000082CD90000A8
+:1006E000000000082D000000000000082D80010D12
+:1006F00000000010B1A8000600000010205F0000FC
+:10070000000000002C200000000000002CA70000CA
+:10071000000000082D000010000000082D800108D6
+:10072000000000188000FF7A00000010B1A6001041
+:1007300000000010001F00000000000F0F30000735
+:10074000000000000A600000000000000AE1000054
+:100750000000000F4B620008000000090B1600FFAC
+:10076000000000000D620000000000090D1A00FFEB
+:1007700000000010073000030000000C0D1A0008F4
+:100780000000000C0B1600080000000F4CE30018DE
+:10079000000000000C992C0000000004CC993400EB
+:1007A000000000080F8000000000000C29800001FC
+:1007B0000000000033310000000000082200001695
+:1007C000000000002ADF0000000000082A00000CE2
+:1007D00000000010009F0000000000002C2000001E
+:1007E0000000000C1F800001000000188000FF19AD
+:1007F0000000001091D4000000000008050000AACD
+:10080000000000188000FF570000000F472200087A
+:1008100000000009070E000F00000008070E000886
+:1008200000000008028000010000000702851C0093
+:1008300000000008828500010000000002854C00D5
+:100840000000000742851C0000000003C3AA5200FC
+:100850000000000003B10E00000000074B071C0061
+:100860000000000F0F3000070000000F0A96000381
+:10087000000000000A955C00000000004A005A00D9
+:10088000000000000C960A00000000090C99FFFF10
+:10089000000000080D00FFFF00000010BA992C02B4
+:1008A000000000080F80000500000010B1A800083B
+:1008B00000000010205F00000000000B2FDF00028E
+:1008C000000000002C200000000000002CA7000009
+:1008D000000000082D000010000000082D80010815
+:1008E000000000188000FF420000000C2980000179
+:1008F00000000010001F00000000000C1F8000011D
+:10090000000000002ADF0000000000082A00000D9F
+:10091000000000188000FEF40000001091D40000D8
+:100920000000000805000055000000188000FF329C
+:100930000000000C298000010000000C1F80000155
+:10094000000000082A000007000000188000FEEDEB
+:1009500000000010B18000040000001F0106000F1D
+:1009600000000008050000FF000000180002000061
+:10097000000000002A00000000000010B1D40000B8
+:100980000000001091DE0000000000102053000065
+:1009900000000010001F0000000000002F80AA00CF
+:1009A0000000000C29800001000000080254000E25
+:1009B000000000002C400000000000000F4000007C
+:1009C0000000001800040000000000188000001162
+:1009D000000000188000001200000018800000389D
+:1009E00000000018800000DF00000018800000DE1A
+:1009F00000000018800000DD00000018800000DD0D
+:100A0000000000188000000000000018800000F6C0
+:100A100000000018800000D90000001880000000CD
+:100A200000000018800000FA000000188000014853
+:100A3000000000188000005A00000018800000C468
+:100A400000000018800000C500000018800000D2DF
+:100A5000000000002A000000000000188000FFE4F1
+:100A6000000000002A0000000000000C29800000A7
+:100A7000000000188000FFE10000001800020000E4
+:100A8000000000000502000000000010B99A2C21AF
+:100A900000000010205F0000000000002C1E00007D
+:100AA000000000082C800006000000082D00000651
+:100AB000000000082D80010200000000000000007E
+:100AC0000000001091DE0000000000000D61000039
+:100AD00000000018000A00000000000005020000ED
+:100AE00000000010B99A2C1600000010205F0000D2
+:100AF0000000000009D80000000000002C1E0000CB
+:100B0000000000082C8000B2000000082D00000A40
+:100B1000000000082D80010200000000000000001D
+:100B20000000001091DE0000000000000D620000D7
+:100B3000000000002C13000000000018000A000054
+:100B4000000000000502000000000010B99A2C0906
+:100B500000000010205F0000000000002C1E0000BC
+:100B6000000000082C800006000000082D00006A2C
+:100B7000000000082D8001020000000000000000BD
+:100B80000000001091DE0000000000000D7A00005F
+:100B900000000018000A0000000000002A00000009
+:100BA0000000000822000001000000000D610000AC
+:100BB0000000001021C2002400000010B1C6000295
+:100BC00000000010234200A2000000090B66FFFF96
+:100BD00000000010BA9A2C20000000000A640000F7
+:100BE000000000000AE50000000000000C0000000A
+:100BF000000000000B800000000000080CC600127E
+:100C0000000000188000FFD0000000080F800003E3
+:100C1000000000000000000000000010009F000025
+:100C2000000000082711001200000000669000007C
+:100C300000000010B198000300000010001F000029
+:100C4000000000080F8000040000000822000003DC
+:100C5000000000082C80000C000000082D00000C93
+:100C600000000010009F00000000001091C6000569
+:100C700000000010001F000000000010BA9A2C03B2
+:100C8000000000080F800004000000188000FFFD35
+:100C900000000000259600000000000C29800000E4
+:100CA0000000000032140000000000003295000037
+:100CB0000000000573662C000000000031E32E00E8
+:100CC000000000082D800010000000188000FF9632
+:100CD00000000000230000000000000925E6FFFFDF
+:100CE000000000082200000B0000000C6952000008
+:100CF0000000000C29800000000000188000FF9018
+:100D0000000000002A000000000000082C800040C5
+:100D1000000000082D000020000000082D80011CAC
+:100D200000000008220000010000001091DE000019
+:100D30000000000F42EA001000000010004F000405
+:100D400000000010B746920000000008024900129F
+:100D500000000010B5840A00000000000D610000D2
+:100D600000000010BA663457000000088305001226
+:100D700000000010004F00020000000003490000C6
+:100D80000000000183068C000000000083C60C00F8
+:100D900000000010B1870013000000000B6E00007F
+:100DA000000000090569FFFF00000010918A0002A1
+:100DB0000000000834E9FFFF000000188000FF7504
+:100DC000000000010569140000000010918A000273
+:100DD00000000008B4E9000100000010BAE92C4846
+:100DE0000000000086692C000000000002000000E6
+:100DF0000000000902EAFFFF00000010000C0002E2
+:100E00000000000002040A000000000F460C000170
+:100E10000000000F0285000100000010918C01FC11
+:100E200000000010B7040E3F000000000D6100003C
+:100E3000000000000A640000000000000AE5000055
+:100E4000000000090B66FFFF000000000C0000001E
+:100E5000000000000B800000000000080C8600125B
+:100E6000000000080F8000030000000C2952000061
+:100E700000000010009F0000000000082711001271
+:100E80000000000066900000000000002306000043
+:100E900000000010B198000500000010001F0000C5
+:100EA000000000080F8000040000000000000000A7
+:100EB00000000010001F00000000000032140000BD
+:100EC00000000000329500000000000031E32E0019
+:100ED0000000000573662C0000000000259600004D
+:100EE00000000010B18700160000000C29800000EF
+:100EF0000000000F0F6B0007000000000D690000EC
+:100F0000000000000A6C0000000000000AED000074
+:100F1000000000000B6E0000000000000B800000CD
+:100F2000000000000C870000000000080F80000394
+:100F300000000010205300000000000C6952000166
+:100F400000000010001F00000000000022C58C00FF
+:100F500000000000231B000000000000271100001B
+:100F6000000000002690000000000010B8170E03DB
+:100F70000000000C29800000000000188000FFF62F
+:100F800000000010B1980002000000080F8000046B
+:100F9000000000082200001A000000082C80000C4D
+:100FA000000000082D00000C000000082D8000103B
+:100FB00000000010001F0000000000000D6E000087
+:100FC00000000003E7CF34000000000C298000007F
+:100FD0000000001091DE000000000010B187000743
+:100FE00000000000361400000000000036950000EC
+:100FF0000000000037160000000000082C800050A0
+:10100000000000082D000030000000082D80000CBA
+:10101000000000188000FF2D0000000023000000E9
+:101020000000000925E6FFFF000000000B6E000035
+:1010300000000003E7CF2C00000000082200001B86
+:101040000000000C695200000000000C2980000024
+:10105000000000188000FF25000000002A000000AA
+:10106000000000188000FF23000000002A0000009C
+:101070000000000C298000000000001091DE00003C
+:10108000000000082C80001A000000082D00001A43
+:101090000000000573660000000000082D800002BB
+:1010A00000000000318000000000001091DE000010
+:1010B000000000082C80000C000000082D00000C2F
+:1010C000000000082D800004000000188000FF16BA
+:1010D0000000001880000000000000188000FF14CD
+:1010E000000000002A00000000000010001F0000A7
+:1010F000000000000F008000000000080F800007C3
+:10110000000000188000001B00000000280A0000FA
+:101110000000000005020000000000082200000995
+:1011200000000000290000000000000F65680010AA
+:1011300000000000248A000000000003F66C940008
+:1011400000000010B972A0040000000C73E7001941
+:101150000000000C21420004000000003CF80000E8
+:101160000000000C29800000000000102053000047
+:1011700000000008220000080000000C614200048A
+:1011800000000018000A0000000000000502000036
+:101190000000000C6142000000000010014200034A
+:1011A0000000000C33E7001D0000000C614200024B
+:1011B00000000018000A0000000000002A000000E3
+:1011C00000000010001F00000000000F0F47000784
+:1011D000000000080F8000080000000C29800000BB
+:1011E00000000010009F0000000000188000FEF2C8
+:1011F0000000000033510000000000002A00000041
+:1012000000000010B1C600230000000F0F500007BF
+:10121000000000000A600000000000000AE1000079
+:101220000000000F4B620008000000090B1600FFD1
+:101230000000000F4C620010000000000D62000072
+:10124000000000090D1A00FF000000100750000305
+:101250000000000C0D1A00080000000C0B1600081E
+:10126000000000000CC60000000000000B80000021
+:101270000000000006980000000000080F80000336
+:101280000000001006C200040000000C290000024B
+:1012900000000010264200020000000C295200034A
+:1012A000000000082200000100000010009F000064
+:1012B00000000000231B00000000000027111A009E
+:1012C00000000000669000000000000C29520000A1
+:1012D00000000010B19732090000000C29800000C6
+:1012E00000000000069800000000001020530000DD
+:1012F0000000000C295200030000000022C58C00F1
+:1013000000000010001F0000000000080F80000314
+:10131000000000188000FFF300000010B1C80013A7
+:1013200000000010B1C600030000000C298000007E
+:1013300000000010205300000000000C29520000A3
+:101340000000000C295200030000001006C2000239
+:101350000000000C295200020000000022C58C0091
+:1013600000000000276500000000000026E40000E7
+:10137000000000082200001600000010B1C60003A3
+:10138000000000002348000000000010B1800005AC
+:1013900000000000234800000000000C298000002D
+:1013A0000000000F0F50000700000018800000121E
+:1013B00000000008220000160000000C2980000038
+:1013C0000000000030140000000000003095000014
+:1013D0000000001007500003000000090B1600FF7A
+:1013E000000000090D1A00FF0000000F3116000870
+:1013F000000000003162340000000003F1623000A0
+:1014000000000010205F0000000000002C510000D0
+:10141000000000092CD1007F000000082CD900003A
+:10142000000000082D000000000000082D80000CC6
+:1014300000000000000000000000001091DE00002D
+:101440000000001005C20004000000080F80000723
+:10145000000000003300000000000010009F0000AA
+:10146000000000188000FEA3000000002A00000019
+:101470000000000F0F50000700000010B1C6002D43
+:101480000000000F4742000800000009070E000F8F
+:1014900000000008070E000800000010001F0000F8
+:1014A00000000008090000010000000709121C00EC
+:1014B00000000003CBCA9200000000000B97A200BE
+:1014C0000000000742171C00000000000B04000091
+:1014D0000000000F0A840003000000000A959C0031
+:1014E000000000004A009A0000000008821200017B
+:1014F000000000010C170800000000000C978C0091
+:101500000000000002180000000000080D00FFFFAE
+:10151000000000080F8000060000000C29000000F9
+:101520000000001006C200040000000C2952000256
+:1015300000000010264200020000000C29520003A7
+:10154000000000082200000100000010009F0000C1
+:1015500000000010B197320C00000000231B0000B7
+:101560000000000027110800000000006690000045
+:101570000000000C2980000000000000021800009C
+:1015800000000010205300000000000C295200034E
+:101590000000000022C5360000000010001F0000FF
+:1015A000000000080F800006000000188000FFF413
+:1015B00000000000231B00000000000027110800AD
+:1015C000000000006690000000000010B1C8000B91
+:1015D0000000000C298000000000001020530000D3
+:1015E0000000000C295200000000000C29520003EA
+:1015F0000000001006C200020000000C2952000288
+:101600000000000022C58C000000000027650000DB
+:101610000000000026E40000000000002348000055
+:1016200000000008220000170000000C29800000C4
+:1016300000000010001F0000000000188000FE687D
+: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-rv2p-09-5.0.0.j10.fw.ihex b/firmware/bnx2/bnx2-rv2p-09-5.0.0.j10.fw.ihex
deleted file mode 100644
index fe59d16..0000000
--- a/firmware/bnx2/bnx2-rv2p-09-5.0.0.j10.fw.ihex
+++ /dev/null
@@ -1,462 +0,0 @@
-:100000000000000000000E08000000580000000979
-:1000100000000000000000000000000000000000E0
-:1000200000000000000000000000000000000000D0
-:1000300000000DD800000E60000000050000000068
-:1000400000000000000000000000000000000000B0
-:080050000000000000000000A8
-:0800580000000010B180000659
-:100060000000001F05030300000000080500FFFF5B
-:10007000000000180002000000000008050000FF5A
-:10008000000000180002000000000008AC000001A1
-:1000900000000000050000000000000C2F8000019F
-:1000A000000000002B000000000000002B8000007A
-:1000B0000000001091E0000200000008AC00000108
-:1000C00000000010203F006B00000010213F0003E3
-:1000D0000000001020BF003A000000188000FFFD63
-:1000E00000000010B1B8B0150000000B2FDF0002B7
-:1000F0000000000003D80000000000002C380000C1
-:10010000000000082C800000000000082D00000006
-:100110000000001091D400000000000806005555B2
-:10012000000000188000007C000000082D80011CE9
-:1001300000000008020000010000001091DE000035
-:100140000000000F42E0001C0000001091840A161D
-:1001500000000018800000830000000C29800002CD
-:100160000000000C1F800002000000002ADF0000D9
-:10017000000000082A00000F000000000500000039
-:10018000000000188000FFE60000000802000001E7
-:100190000000000F42E0001C0000001091840A18CB
-:1001A000000000082C800006000000082D0000065A
-:1001B0000000001091D40000000000082D8001060E
-:1001C0000000001880000072000000188000FFF19D
-:1001D00000000008B1000001000000082C80010CA4
-:1001E000000000082D000008000000082D8000011C
-:1001F000000000188000006C0000000B2FDF0002E0
-:100200000000000C1F800002000000002C0700000E
-:100210000000001091DE00000000000805005555A8
-:10022000000000188000FFD20000000B2FDF00024A
-:100230000000000C1F800000000000002C070000E0
-:100240000000001091DE0000000000080500555578
-:10025000000000188000FFCC0000000C1F8000028E
-:100260000000000805005555000000188000FFC977
-:100270000000000C298000020000000C1F8000021A
-:10028000000000002ADF0000000000082A0000052E
-:100290000000000805005555000000188000FFC34D
-:1002A000000000080224004A0000001800040000BA
-:1002B000000000188000001C000000188000001ED4
-:1002C000000000188000006500000018800000BCDD
-:1002D00000000018800000BB000000188000000033
-:1002E00000000018800000000000001880000000DE
-:1002F00000000018800000000000001880000000CE
-:1003000000000018800000000000001880000000BD
-:1003100000000018800000000000001880000107A5
-:10032000000000188000000000000018800000009D
-:100330000000001880000015000000188000001B5D
-:10034000000000188000000000000018800000D2AB
-:10035000000000188000002F000000188000010736
-:10036000000000188000013200000018800000FD2D
-:100370000000001880000156000000188000004EA8
-:100380000000001880000000000000188000008FAE
-:100390000000000C1F8000010000000005000000AC
-:1003A000000000188000FFA20000001091D400009F
-:1003B0000000000C298000010000000C1F800001DB
-:1003C000000000082A0000020000000005000000F4
-:1003D000000000188000FF9C0000001091D4000075
-:1003E0000000000C298000010000000C1F800001AB
-:1003F0000000000029420000000000082A0000025E
-:100400000000000005000000000000188000FF95BB
-:10041000000000188000FF9400000010B1BCB00A7A
-:100420000000000B2FDF00020000000003D80000D6
-:10043000000000002C3C00000000001091D40000DF
-:100440000000000806005555000000188000001745
-:1004500000000018800000CB000000102C6201BAE0
-:100460000000001880000006000000082C80010D2C
-:10047000000000082D0000090000001091D40000C9
-:10048000000000082D8001070000001880000024F3
-:100490000000000C298000000000000C1F800000FC
-:1004A0000000001091DE0000000000002ADF0000C4
-:1004B000000000082A00000600000008050055554D
-:1004C000000000188000FF7E0000001091D40000A2
-:1004D0000000000C298000010000000C1F800001BA
-:1004E000000000082A00000B0000000005000000CA
-:1004F000000000188000FF780000001800020000D3
-:10050000000000000682000000000010B18A000810
-:1005100000000010B18C14070000000B050AFFFF5B
-:1005200000000010B18A000300000000860A1800D5
-:1005300000000010918C0000000000082A0000015B
-:100540000000001091D4000000000018000D000011
-:1005500000000000050200000000001091DE000015
-:1005600000000018000A00000000000006820000E1
-:100570000000001091DE000000000010BEE1000548
-:10058000000000188000FF5F0000000105611400FA
-:1005900000000010918A000200000008B0E1000194
-:1005A00000000018000D000000000000068200009E
-:1005B0000000001091DE000000000010BEE2000507
-:1005C000000000188000FF570000000105621400C1
-:1005D00000000010918A000200000008B1620001D2
-:1005E00000000018000D000000000010B1A0B013C2
-:1005F0000000000B2FDF0002000000002C20000094
-:10060000000000082C800000000000082D00000001
-:100610000000001091D400000000000806005555AD
-:10062000000000188000FFDC000000082D80011C85
-:1006300000000010001F0000000000188000FFE60E
-:100640000000000F476000080000000F060E0001C8
-:10065000000000000F580000000000000A640000C5
-:10066000000000000AE50000000000090B66FFFF23
-:10067000000000000D610000000000188000001361
-:100680000000000F476000080000000B2FDF000291
-:10069000000000082C800000000000082D00000071
-:1006A0000000001091D40000000000082D80011C03
-:1006B0000000000F060E000100000010001F0000E7
-:1006C000000000000F580000000000188000FFD458
-:1006D000000000000A640000000000000AE50000BD
-:1006E000000000090B66FFFF000000000D61000024
-:1006F00000000000026200000000000B2FDF00027B
-:10070000000000003104000000000000309A0000EA
-:10071000000000090560000F00000010B18A000B06
-:100720000000000005634C0000000008050A0012EC
-:1007300000000010B9621403000000000300000074
-:100740000000001880000006000000188000FF2450
-:1007500000000010B60614040000000803060001A3
-:10076000000000082A000001000000188000FF2996
-:10077000000000000C961800000000090C99FFFF13
-:1007800000000004CC99340000000010B196320241
-:10079000000000080F8000000000000C298000010C
-:1007A0000000000C295200010000000C295200003A
-:1007B000000000080200000E000000080280001A7D
-:1007C00000000010B1C40A0200000008020000038B
-:1007D00000000008220000010000000C1F80000142
-:1007E000000000002ADF0000000000002A000800CE
-:1007F0000000000805005555000000188000FF1794
-:100800000000000B2FDF00020000001091D4000058
-:10081000000000082A000001000000002C20000059
-:100820000000001091D40000000000082C8000009F
-:10083000000000082D000000000000082D80011CB1
-:10084000000000188000FFA2000000082C800006B5
-:10085000000000082D0000060000000030800000AD
-:100860000000000031000000000000082D8000069C
-:100870000000000C298000010000000C1F80000116
-:100880000000001091DE0000000000002ADF0000E0
-:10089000000000082A000010000000000500000011
-:1008A000000000188000FF020000001091A0B009B5
-:1008B000000000082C80010D000000082D00000938
-:1008C0000000001091D40000000000082D800107F6
-:1008D000000000188000FF9B00000018800000103E
-:1008E00000000008AC000001000000188000000BB0
-:1008F000000000000380B0000000000B2FDF0002AA
-:10090000000000002C0040000000001091D4000006
-:100910000000000806005555000000188000FF7D0B
-:100920000000001880000031000000188000000660
-:100930000000000B2FDF0002000000002C000E0062
-:10094000000000082A0000070000000805005555B7
-:10095000000000188000FEEC00000000068200008D
-:100960000000000C298000010000000C1F80000125
-:10097000000000100CE70007000000090562FFFFFF
-:1009800000000010BA6C1405000000002ADF00000F
-:100990000000000021000000000000082A000005FF
-:1009A0000000001091D40000000000082C80010C11
-:1009B000000000082D0000080000000C3162001843
-:1009C000000000082D800001000000188000FF7169
-:1009D00000000018000D000000000010B1A0B00ED3
-:1009E0000000000B2FDF00020000000003D8000011
-:1009F000000000002C2000000000001091D4000036
-:100A00000000001880000015000000102C62000299
-:100A1000000000188000000C0000000B2FDF000217
-:100A2000000000002C0700000000000C1F800001E7
-:100A30000000001091DE0000000000080500FFFF2C
-:100A4000000000188000FECE000000082C80010D80
-:100A5000000000082D0000090000001091D40000E3
-:100A6000000000082D800107000000188000FF68CA
-:100A70000000000C298000010000000C1F80000114
-:100A80000000001091DE0000000000002ADF0000DE
-:100A9000000000082A00000A000000000500000015
-:100AA000000000188000FEC2000000000682000066
-:100AB000000000082C80010C000000082D00000838
-:100AC000000000082D80013400000000000000003C
-:100AD00000000010205F0000000000082C80014092
-:100AE000000000082D00003C000000082D800124BB
-:100AF00000000000000000000000001091DE000077
-:100B0000000000082C800080000000082D0000007C
-:100B1000000000082D80010500000010BEE2000565
-:100B2000000000188000FEAB000000010562140008
-:100B300000000010918A000200000008B16200016C
-:100B40000000001091DE000000000018000D000001
-:100B50000000001091D40000000000080600AAAABE
-:100B6000000000188000FF340000000C2980000104
-:100B70000000000C1F800001000000082A0000098E
-:100B8000000000080500AAAA000000188000FEA5C9
-:100B90000000001091D40000000000080600555528
-:100BA000000000188000FF2C0000001091A03C0203
-:100BB00000000010B1E662070000000B2FDF00020A
-:100BC000000000002C310000000000092CB1007F63
-:100BD000000000082CD90000000000082D000000D3
-:100BE000000000082D80010D00000010B1A80006D3
-:100BF00000000010205F0000000000002C2000001A
-:100C0000000000002CA70000000000082D000010CC
-:100C1000000000082D800108000000188000FF2758
-:100C200000000010B1A6001000000010001F00001E
-:100C30000000000F0F300007000000000A600000F5
-:100C4000000000000AE100000000000F4B620008F5
-:100C5000000000090B1600FF000000000D620000FC
-:100C6000000000090D1A00FF00000010073000030B
-:100C70000000000C0D1A00080000000C0B16000804
-:100C80000000000F4CE30018000000000C992C003D
-:100C900000000004CC993400000000080F80000020
-:100CA0000000000C2980000100000000333100002A
-:100CB0000000000822000016000000002ADF0000EB
-:100CC000000000082A00000C00000010009F000037
-:100CD000000000000F2000000000000C1F80000139
-:100CE0000000000805005555000000188000FE793E
-:100CF0000000001091D40000000000080600AAAA1D
-:100D0000000000188000FF000000000F47220008CC
-:100D100000000009070E000F00000008070E000881
-:100D200000000008028000010000000702851C008E
-:100D300000000008828500010000000002854C00D0
-:100D40000000000742851C0000000003C3AA5200F7
-:100D50000000000003B10E00000000074B071C005C
-:100D60000000000F0F3000070000000F0A9600037C
-:100D7000000000000A955C00000000004A005A00D4
-:100D8000000000000C960A00000000090C99FFFF0B
-:100D9000000000080D00FFFF00000010B1963202B5
-:100DA000000000080F80000500000010B1A8000836
-:100DB00000000010205F00000000000B2FDF000289
-:100DC000000000002C200000000000002CA7000004
-:100DD000000000082D000010000000082D80010810
-:100DE000000000188000FEEE0000000C29800001C9
-:100DF00000000010001F00000000000C1F80000118
-:100E0000000000002ADF0000000000082A00000D9A
-:100E1000000000080500AAAA000000188000FE5388
-:100E20000000001091D40000000000080600555595
-:100E3000000000188000FEDA0000000C298000018C
-:100E40000000000C1F800001000000082A000007BD
-:100E50000000000805005555000000188000FE4BFA
-:100E600000000010B18000040000001F0503030013
-:100E700000000008050000FF00000018000200004C
-:100E8000000000002A00000000000010B1D40000A3
-:100E90000000001091DE0000000000102053000050
-:100EA00000000010001F0000000000002F80AA00BA
-:100EB0000000000C29800001000000080254000E10
-:100EC000000000002C400000000000092952003FF3
-:100ED000000000180004000000000018800000104E
-:100EE0000000001880000011000000188000003988
-:100EF00000000018800000FD00000018800000FCC9
-:100F000000000018800000FB00000018800000FBBB
-:100F1000000000188000000000000018800001138D
-:100F200000000018800000F7000000188000000B8F
-:100F30000000001880000117000000188000016503
-:100F4000000000188000006300000018800000CE40
-:100F500000000018800000DE000000002A000000F1
-:100F6000000000188000FFE5000000002A000000DB
-:100F70000000000C29800000000000188000FFE243
-:100F8000000000002A000000000000188000FFE0C0
-:100F90000000001800020000000000000502000030
-:100FA000000000109196342100000010205F000026
-:100FB000000000002C1E0000000000082C8000062D
-:100FC000000000082D000006000000082D8001022E
-:100FD00000000000000000000000001091DE000092
-:100FE000000000000D61000000000018000A000071
-:100FF0000000000005020000000000109196341669
-:1010000000000010205F00000000000009D8000070
-:10101000000000002C1E0000000000082C80010EC3
-:10102000000000082D00000A000000082D800102C9
-:1010300000000000000000000000001091DE000031
-:10104000000000000D620000000000002C130000F2
-:1010500000000018000A0000000000000502000067
-:10106000000000109196340900000010205F00007D
-:10107000000000002C1E0000000000082C8000066C
-:10108000000000082D00006A000000082D80010209
-:1010900000000000000000000000001091DE0000D1
-:1010A000000000000D7A000000000018000A000097
-:1010B000000000002A000000000000000D61000098
-:1010C000000000000362000000000010234200C185
-:1010D0000000000002638C000000000026460000B3
-:1010E000000000080204001200000010B9060827E2
-:1010F000000000000F580000000000000A6400001B
-:10110000000000000AE50000000000090B66FFFF78
-:10111000000000000C000000000000000B80000038
-:10112000000000080CC60012000000188000FFCE6E
-:10113000000000080F800003000000000000000015
-:1011400000000010009F000000000008271100129E
-:10115000000000006690000000000008A31B0012C1
-:1011600000000010B198000300000010001F0000F4
-:10117000000000080F8000040000000822000003A7
-:10118000000000082C80000C000000082D00000C5E
-:1011900000000010009F00000000000025960000E5
-:1011A0000000000C2980000000000000066600001E
-:1011B0000000000086611800000000090260000FB6
-:1011C0000000000F0204000200000010B60C080529
-:1011D0000000000C1FBF0000000000102866000384
-:1011E00000000008078F00010000000C33660010AB
-:1011F00000000000321400000000000032950000E2
-:101200000000000573662C000000000031E32E0092
-:10121000000000082D800010000000188000FF8EE4
-:1012200000000000230000000000000925E6FFFF89
-:10123000000000082200000B0000000C69520000B2
-:101240000000000C298000000000001028660075D6
-:10125000000000188000FF87000000002A00000046
-:10126000000000082C800040000000082D00002035
-:10127000000000082D80011C00000000000000009C
-:101280000000001091DE00000000000F42EA001094
-:1012900000000010004F000400000010B74692004C
-:1012A000000000080249001200000010B5840A0086
-:1012B000000000000D61000000000010BA66345705
-:1012C000000000088305001200000010004F00021B
-:1012D00000000000034900000000000183068C00AC
-:1012E0000000000083C60C0000000010B187001150
-:1012F000000000000B6E000000000010BEE90005B9
-:10130000000000188000FF6E000000010569140055
-:1013100000000010918A000200000008B4E90001FA
-:1013200000000010B1E92C4A0000000086692C0082
-:1013300000000000020000000000000902EAFFFFB8
-:1013400000000010000C00020000000002040A006F
-:101350000000000F460C00010000000F0285000194
-:1013600000000010918C01FC00000010B7040E4139
-:10137000000000000F400000000000000D610000B0
-:10138000000000000A640000000000000AE5000000
-:10139000000000090B66FFFF000000000C000000C9
-:1013A000000000000B800000000000080C86001206
-:1013B000000000080F8000030000000C295200000C
-:1013C00000000010009F000000000008271100121C
-:1013D00000000000669000000000000026460000AB
-:1013E000000000002306000000000010B198000576
-:1013F00000000010001F0000000000080F80000423
-:10140000000000000000000000000010001F0000AD
-:1014100000000000321400000000000032950000BF
-:101420000000000031E32E000000000573662C0070
-:10143000000000002596000000000010B187001693
-:101440000000000C298000000000000F0F6B000757
-:10145000000000000D690000000000000A6C0000A0
-:10146000000000000AED0000000000000B6E00000C
-:10147000000000000B800000000000000C8700004E
-:10148000000000080F80000300000010205300003F
-:101490000000000C6952000100000010001F000055
-:1014A0000000000022C58C0000000000231B00008B
-:1014B000000000002711000000000000269000003E
-:1014C00000000010B8170E030000000C2980000077
-:1014D000000000188000FFF600000010B198000224
-:1014E000000000080F800004000000082200001A1D
-:1014F000000000082C80000C000000082D00000CEB
-:10150000000000082D80001000000010001F0000E7
-:10151000000000000D6E000000000003E7CF340063
-:101520000000000C298000000000001091DE000087
-:1015300000000010B1870007000000003614000012
-:101540000000000036950000000000003716000083
-:10155000000000082C800050000000082D00003022
-:10156000000000082D80000C000000188000FF24FF
-:1015700000000000264600000000000023000000DC
-:101580000000000925E6FFFF000000000B6E0000D0
-:1015900000000003E7CF2C00000000082200001B21
-:1015A0000000000C695200000000000C29800000BF
-:1015B000000000188000FF1B000000002A0000004F
-:1015C000000000100866000500000000066600002C
-:1015D000000000008661180000000009026000F0B1
-:1015E00000000010B60C0802000000188000FF1474
-:1015F000000000000682000000000010B18F000013
-:1016000000000008878F00010000000C73660010C6
-:10161000000000082C800018000000082D000018B1
-:10162000000000082D8000020000000C5FBF0000D9
-:101630000000001091DE000000000018000D000006
-:10164000000000002A00000000000010286601F5DC
-:10165000000000082C800003000000082D0000039B
-:10166000000000093060FFF0000000082D8000013C
-:101670000000000C298000000000001091DE000036
-:10168000000000082C80001A000000082D00001A3D
-:101690000000000573660000000000082D800002B5
-:1016A00000000000318000000000001091DE00000A
-:1016B000000000082C80000C000000082D00000C29
-:1016C000000000082D800004000000188000FEF8D3
-:1016D0000000001800020000000000188000FEF664
-:1016E000000000002A00000000000010001F0000A1
-:1016F000000000000F008000000000080F800007BD
-:10170000000000188000001A00000000280A0000F5
-:10171000000000000502000000000008220000098F
-:1017200000000000290000000000000F65680010A4
-:1017300000000003F66C940000000010B972A004D1
-:101740000000000C73E700190000000C21420004A7
-:10175000000000003CF800000000000C29800000A0
-:1017600000000010205300000000000822000008C4
-:101770000000000C6142000400000018000A000094
-:1017800000000000050200000000000C61420000A3
-:1017900000000010014200030000000C33E7001DB0
-:1017A0000000000C6142000200000018000A000066
-:1017B000000000002A00000000000010001F0000D0
-:1017C0000000000F0F470007000000080F8000080E
-:1017D0000000000C2980000000000010009F0000A5
-:1017E000000000188000FED500000000335100000A
-:1017F000000000002A00000000000010B1C6002315
-:101800000000000F0F500007000000000A600000F9
-:10181000000000000AE100000000000F4B62000819
-:10182000000000090B1600FF0000000F4C620010C2
-:10183000000000000D620000000000090D1A00FF0A
-:1018400000000010075000030000000C0D1A0008F3
-:101850000000000C0B160008000000000CC6000081
-:10186000000000000B80000000000000069800004F
-:10187000000000080F8000030000001006C20004F2
-:101880000000000C290000020000001026420002A7
-:101890000000000C29520003000000082200000193
-:1018A00000000010009F000000000000231B00004B
-:1018B0000000000027111A000000000066900000E0
-:1018C0000000000C2952000000000010B1973209FE
-:1018D0000000000C298000000000000006980000B5
-:1018E00000000010205300000000000C29520003EB
-:1018F0000000000022C58C0000000010001F000046
-:10190000000000080F800003000000188000FFF3B3
-:1019100000000010B1C8001300000010B1C60003A1
-:101920000000000C2980000000000010205300007F
-:101930000000000C295200000000000C2952000396
-:101940000000001006C200020000000C2952000234
-:101950000000000022C58C00000000002765000088
-:101960000000000026E4000000000008220000162D
-:1019700000000010B1C60003000000002348000072
-:1019800000000010B18000050000000023480000A6
-:101990000000000C298000000000000F0F5000071D
-:1019A000000000188000001200000008220000164D
-:1019B0000000000C2980000000000000301400002E
-:1019C00000000000309500000000001007500003E8
-:1019D000000000090B1600FF000000090D1A00FFAF
-:1019E0000000000F311600080000000031623400D2
-:1019F00000000003F162300000000010205F0000D2
-:101A0000000000002C510000000000092CD1007FD4
-:101A1000000000082CD90000000000082D00000084
-:101A2000000000082D80000C0000000000000000F5
-:101A30000000001091DE00000000001005C200044C
-:101A4000000000080F8000070000000033000000C5
-:101A500000000010009F0000000000188000FE86BB
-:101A6000000000002A0000000000000F0F500007D7
-:101A700000000010B1C6002D0000000F4742000812
-:101A800000000009070E000F00000008070E000804
-:101A900000000010001F0000000000080900000105
-:101AA0000000000709121C0000000003CBCA9200CE
-:101AB000000000000B97A2000000000742171C0066
-:101AC000000000000B0400000000000F0A84000367
-:101AD000000000000A959C00000000004A009A00E7
-:101AE0000000000882120001000000010C1708002D
-:101AF000000000000C978C0000000000021800009D
-:101B0000000000080D00FFFF000000080F80000625
-:101B10000000000C290000000000001006C20004B4
-:101B20000000000C295200020000001026420002B2
-:101B30000000000C295200030000000822000001F0
-:101B400000000010009F000000000010B197320C50
-:101B500000000000231B0000000000002711080007
-:101B600000000000669000000000000C29800000CA
-:101B700000000000021800000000001020530000C8
-:101B80000000000C295200030000000022C53600AE
-:101B900000000010001F0000000000080F80000679
-:101BA000000000188000FFF400000000231B00006C
-:101BB00000000000271108000000000066900000EF
-:101BC00000000010B1C8000B0000000C29800000CC
-:101BD00000000010205300000000000C29520000FB
-:101BE0000000000C295200030000001006C2000291
-:101BF0000000000C295200020000000022C58C00E9
-:101C000000000000276500000000000026E400003E
-:101C10000000000023480000000000082200001718
-:101C20000000000C2980000000000010001F0000D0
-:081C3000000000188000FE4BCB
-: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-rv2p-09-6.0.17.fw.ihex b/firmware/bnx2/bnx2-rv2p-09-6.0.17.fw.ihex
new file mode 100644
index 0000000..435203d
--- /dev/null
+++ b/firmware/bnx2/bnx2-rv2p-09-6.0.17.fw.ihex
@@ -0,0 +1,392 @@
+:1000000000000000000008F800000058000000098F
+:1000100000000000000000000000000000000000E0
+:1000200000000000000000000000000000000000D0
+:1000300000000E88000009500000000500000000CC
+:1000400000000000000000000000000000000000B0
+:080050000000000000000000A8
+:0800580000000010B180000659
+:100060000000001F05060011000000080500FFFF4A
+:10007000000000180002000000000008050000FF5A
+:10008000000000180002000000000008AC000001A1
+:1000900000000008078000000000000C2F80000115
+:1000A000000000002B000000000000002B8000007A
+:1000B0000000001091E1000200000008AC00000107
+:1000C00000000010203F003B00000010213F000313
+:1000D0000000001020BF0015000000188000FFFD88
+:1000E0000000000C1F800002000000188000FFF9D3
+:1000F00000000008B1000001000000082C80010C85
+:10010000000000082D000008000000082D800001FC
+:10011000000000188000003C0000000B2FDF0002F0
+:100120000000000C1F800002000000002C070000EF
+:100130000000001091DE0000000000188000FFEFBA
+:100140000000000B2FDF00020000000C1F800000E9
+:10015000000000002C0700000000001091DE0000ED
+:10016000000000188000FFEA0000000C1F80000261
+:10017000000000188000FFE80000000802240025AD
+:1001800000000018000400000000001880000000BB
+:10019000000000188000001B0000001880000042D2
+:1001A000000000188000000000000018800000001F
+:1001B000000000188000000000000018800000000F
+:1001C00000000018800000000000001880000000FF
+:1001D00000000018800000000000001880000000EF
+:1001E00000000018800000000000001880000000DF
+:1001F000000000188000008E000000188000000041
+:1002000000000018800000000000001880000000BE
+:1002100000000018800000000000001880000000AE
+:10022000000000188000000000000018800000009E
+:10023000000000188000008D00000018800000B74A
+:10024000000000188000008400000018800000DA20
+:10025000000000188000002B000000188000000043
+:10026000000000188000006B0000001091D4000016
+:100270000000000C298000010000000C1F8000011C
+:10028000000000082A0000020000000807800000AB
+:10029000000000188000FFC4000000080380010077
+:1002A00000000010B73C0E000000001880000000A5
+:1002B000000000180002000000000000068200009C
+:1002C00000000010B18F000400000010B18F140373
+:1002D000000000082A0000010000001091D4000076
+:1002E000000000000780140000000018000D00004E
+:1002F00000000000050200000000001091DE000078
+:1003000000000018000A0000000000000682000043
+:100310000000001091DE0000000000090561FFFFF1
+:1003200000000010918A00020000000830E1FFFF89
+:10033000000000188000FFA9000000010561140002
+:1003400000000010918A000200000008B0E10001E6
+:1003500000000018000D00000000000006820000F0
+:100360000000001091DE0000000000090562FFFFA0
+:1003700000000010918A0002000000083162FFFFB7
+:10038000000000188000FF9F0000000105621400BB
+:1003900000000010918A000200000008B162000114
+:1003A00000000018000D000000000010B1A0B01304
+:1003B0000000000B2FDF0002000000002C200000D6
+:1003C000000000082C800000000000082D00000044
+:1003D0000000001091D40000000000080500005546
+:1003E000000000188000FFDB000000082D80011CC9
+:1003F00000000010001F0000000000188000FFE255
+:100400000000000F476000080000000F060E00010A
+:10041000000000000F580000000000000A64000007
+:10042000000000000AE50000000000090B66FFFF65
+:10043000000000000D6100000000001880000015A1
+:100440000000000F476000080000000B2FDF0002D3
+:10045000000000082C800000000000082D000000B3
+:100460000000001091D40000000000082D80011C45
+:100470000000000F060E000100000010001F000029
+:10048000000000000F580000000000188000FFD09E
+:10049000000000000A640000000000000AE50000FF
+:1004A000000000090B66FFFF000000000D61000066
+:1004B00000000000026200000000000002E00000F6
+:1004C0000000000B2FDF00020000000030050000DC
+:1004D000000000003104000000000000309A00001D
+:1004E000000000100060000A00000008051600016E
+:1004F00000000010BA9A140300000000030000007E
+:100500000000001880000006000000188000FF6C4A
+:1005100000000010B60614040000000803060001E5
+:10052000000000082A000001000000188000FF7190
+:10053000000000000C961800000000090C99FFFF55
+:1005400000000004CC99340000000010BA992C027D
+:10055000000000080F8000000000000C298000014E
+:100560000000000C295200010000000C295200007C
+:100570000000000822800002000000080200000EB7
+:10058000000000080280001A00000010B1C40A0236
+:1005900000000008020000030000000C1F800001A2
+:1005A000000000002ADF0000000000002A00080010
+:1005B000000000188000FF600000000B2FDF000229
+:1005C0000000001091D40000000000082A00000183
+:1005D000000000002C2000000000001091D400005A
+:1005E000000000082C800000000000082D00000022
+:1005F000000000082D80011C000000188000FF9FF3
+:10060000000000082C800006000000082D000006F5
+:1006100000000000308000000000000031000000F9
+:10062000000000082D8000060000000C2980000159
+:100630000000000C1F8000010000001091DE00008F
+:10064000000000002ADF0000000000082A0000105F
+:100650000000000807800000000000188000FF4B29
+:100660000000001091D4000000000008050000AA5E
+:10067000000000188000FF890000000C29800001A4
+:100680000000000C1F800001000000082A00000983
+:10069000000000188000FF440000001091D400000A
+:1006A0000000000805000055000000188000FF82CF
+:1006B0000000001091A0B00200000010B1E6620737
+:1006C0000000000B2FDF0002000000002C310000B2
+:1006D000000000092CB1007F000000082CD90000A8
+:1006E000000000082D000000000000082D80010D12
+:1006F00000000010B1A8000600000010205F0000FC
+:10070000000000002C200000000000002CA70000CA
+:10071000000000082D000010000000082D800108D6
+:10072000000000188000FF7A00000010B1A6001041
+:1007300000000010001F00000000000F0F30000735
+:10074000000000000A600000000000000AE1000054
+:100750000000000F4B620008000000090B1600FFAC
+:10076000000000000D620000000000090D1A00FFEB
+:1007700000000010073000030000000C0D1A0008F4
+:100780000000000C0B1600080000000F4CE30018DE
+:10079000000000000C992C0000000004CC993400EB
+:1007A000000000080F8000000000000C29800001FC
+:1007B0000000000033310000000000082200001695
+:1007C000000000002ADF0000000000082A00000CE2
+:1007D00000000010009F0000000000002C2000001E
+:1007E0000000000C1F800001000000188000FF19AD
+:1007F0000000001091D4000000000008050000AACD
+:10080000000000188000FF570000000F472200087A
+:1008100000000009070E000F00000008070E000886
+:1008200000000008028000010000000702851C0093
+:1008300000000008828500010000000002854C00D5
+:100840000000000742851C0000000003C3AA5200FC
+:100850000000000003B10E00000000074B071C0061
+:100860000000000F0F3000070000000F0A96000381
+:10087000000000000A955C00000000004A005A00D9
+:10088000000000000C960A00000000090C99FFFF10
+:10089000000000080D00FFFF00000010BA992C02B4
+:1008A000000000080F80000500000010B1A800083B
+:1008B00000000010205F00000000000B2FDF00028E
+:1008C000000000002C200000000000002CA7000009
+:1008D000000000082D000010000000082D80010815
+:1008E000000000188000FF420000000C2980000179
+:1008F00000000010001F00000000000C1F8000011D
+:10090000000000002ADF0000000000082A00000D9F
+:10091000000000188000FEF40000001091D40000D8
+:100920000000000805000055000000188000FF329C
+:100930000000000C298000010000000C1F80000155
+:10094000000000082A000007000000188000FEEDEB
+:1009500000000010B18000040000001F0506001117
+:1009600000000008050000FF000000180002000061
+:10097000000000002A00000000000010B1D40000B8
+:100980000000001091DE0000000000102053000065
+:1009900000000010001F0000000000002F80AA00CF
+:1009A0000000000C29800001000000080254000F24
+:1009B000000000002C400000000000000F4000007C
+:1009C000000000092952003F000000180004000048
+:1009D00000000018800000110000001880000012C4
+:1009E000000000188000003800000018800001118D
+:1009F0000000001880000110000000188000010FA6
+:100A0000000000188000010F0000001880000000A6
+:100A10000000001880000128000000188000010B71
+:100A20000000001880000000000000188000012C69
+:100A3000000000188000017A000000188000005AB1
+:100A400000000018800000C400000018800000C5ED
+:100A50000000001880000104000000002A000000CF
+:100A6000000000188000FFE3000000002A000000E2
+:100A70000000000C29800000000000188000FFE04A
+:100A80000000001800020000000000000502000045
+:100A900000000010B99A2C2100000010205F000017
+:100AA000000000002C1E0000000000082C80000642
+:100AB000000000082D000006000000082D80010243
+:100AC00000000000000000000000001091DE0000A7
+:100AD000000000000D61000000000018000A000086
+:100AE000000000000502000000000010B99A2C165A
+:100AF00000000010205F00000000000009D8000086
+:100B0000000000002C1E0000000000082C80010ED8
+:100B1000000000082D00000A000000082D800102DE
+:100B200000000000000000000000001091DE000046
+:100B3000000000000D620000000000002C13000007
+:100B400000000018000A000000000000050200007C
+:100B500000000010B99A2C0900000010205F00006E
+:100B6000000000002C1E0000000000082C80000681
+:100B7000000000082D00006A000000082D8001021E
+:100B800000000000000000000000001091DE0000E6
+:100B9000000000000D7A000000000018000A0000AC
+:100BA000000000002A0000000000000822000001F0
+:100BB000000000000D6100000000001021C20024B0
+:100BC00000000010B1C6000200000010234200A285
+:100BD000000000090B66FFFF00000010BA9A2C20ED
+:100BE000000000000A640000000000000AE50000A8
+:100BF000000000000C000000000000000B8000005E
+:100C0000000000080CC60012000000188000FFD091
+:100C1000000000080F80000300000000000000003A
+:100C200000000010009F00000000000827110012C3
+:100C3000000000006690000000000010B198000362
+:100C400000000010001F0000000000080F800004DA
+:100C50000000000822000003000000082C80000CA7
+:100C6000000000082D00000C00000010009F000094
+:100C70000000001091C6000500000010001F0000D9
+:100C800000000010BA9A2C03000000080F80000436
+:100C9000000000188000FFFD000000002596000005
+:100CA0000000000C29800000000000003214000049
+:100CB00000000000329500000000000573662C0063
+:100CC0000000000031E32E00000000082D8000101D
+:100CD000000000188000FF950000000023000000C5
+:100CE0000000000925E6FFFF000000082200000BBD
+:100CF0000000000C695200000000000C2980000078
+:100D0000000000188000FF8F000000002A00000093
+:100D1000000000082C800040000000082D0000208A
+:100D2000000000082D80011C0000000822000001C6
+:100D30000000001091DE00000000000F42EA0010E9
+:100D400000000010004F000400000010B7469200A1
+:100D5000000000080249001200000010B5840A00DB
+:100D6000000000000D61000000000010BA6634575A
+:100D7000000000088305001200000010004F000270
+:100D800000000000034900000000000183068C0001
+:100D90000000000083C60C0000000010B1870013A3
+:100DA000000000000B6E0000000000090569FFFF55
+:100DB00000000010918A00020000000834E9FFFFE3
+:100DC000000000188000FF74000000010569140095
+:100DD00000000010918A000200000008B4E9000140
+:100DE00000000010BAE92C480000000086692C00C1
+:100DF00000000000020000000000000902EAFFFFFE
+:100E000000000010000C00020000000002040A00B4
+:100E10000000000F460C00010000000F02850001D9
+:100E200000000010918C01FC00000010B7040E3F80
+:100E3000000000000D610000000000000A640000D6
+:100E4000000000000AE50000000000090B66FFFF3B
+:100E5000000000000C000000000000000B800000FB
+:100E6000000000080C860012000000080F8000033C
+:100E70000000000C2952000000000010009F00003C
+:100E8000000000082711001200000000669000001A
+:100E9000000000002306000000000010B1980005CB
+:100EA00000000010001F0000000000080F80000478
+:100EB000000000000000000000000010001F000003
+:100EC0000000000032140000000000003295000015
+:100ED0000000000031E32E000000000573662C00C6
+:100EE000000000002596000000000010B1870016E9
+:100EF0000000000C298000000000000F0F6B0007AD
+:100F0000000000000D690000000000000A6C0000F5
+:100F1000000000000AED0000000000000B6E000061
+:100F2000000000000B800000000000000C870000A3
+:100F3000000000080F800003000000102053000094
+:100F40000000000C6952000100000010001F0000AA
+:100F50000000000022C58C0000000000231B0000E0
+:100F60000000000027110000000000002690000093
+:100F700000000010B8170E030000000C29800000CC
+:100F8000000000188000FFF600000010B198000279
+:100F9000000000080F800004000000082200001A72
+:100FA000000000082C80000C000000082D00000C40
+:100FB000000000082D80001000000010001F00003D
+:100FC000000000000D6E000000000003E7CF3400B9
+:100FD0000000000C298000000000001091DE0000DD
+:100FE00000000010B1870007000000003614000068
+:100FF00000000000369500000000000037160000D9
+:10100000000000082C800050000000082D00003077
+:10101000000000082D80000C000000188000FF2C4C
+:1010200000000000230000000000000925E6FFFF8B
+:10103000000000000B6E000000000003E7CF2C0052
+:10104000000000082200001B0000000C6952000094
+:101050000000000C29800000000000188000FF2420
+:10106000000000002A000000000000188000FF229D
+:10107000000000002A0000000000000C2980000091
+:101080000000001091DE0000000000082C80001A13
+:10109000000000082D00001A000000057366000023
+:1010A000000000082D8000020000000031800000D8
+:1010B0000000001091DE0000000000082C80000CF1
+:1010C000000000082D00000C000000082D80000426
+:1010D000000000188000FF150000000806660001EF
+:1010E00000000010BA9A197F000000000A64000096
+:1010F000000000000AE50000000000090B66FFFF89
+:10110000000000000C000000000000000B80000048
+:10111000000000080CC60012000000188000FF2E1E
+:10112000000000080F800003000000000000000025
+:1011300000000010009F00000000000827110012AE
+:10114000000000006690000000000010919B32003B
+:10115000000000100293000000000010B19800038E
+:1011600000000010001F0000000000080F800004B5
+:101170000000000C2980000000000010001F00008B
+:1011800000000010BA9A2C000000000031E32E008D
+:10119000000000000B800000000000008CCC8C00E0
+:1011A00000000010B5CC8C02000000080C8000018B
+:1011B000000000188000FF1B000000080F800003E3
+:1011C00000000010205300000000000C69520001D4
+:1011D0000000000022C58C0000000010009F0000ED
+:1011E0000000000027110000000000002690000011
+:1011F00000000000231B000000000010B198000355
+:1012000000000010001F0000000000080F80000414
+:101210000000000822000003000000082C80000CE1
+:10122000000000082D00000C00000010009F0000CE
+:1012300000000000259600000000000C298000003E
+:101240000000000032140000000000003295000091
+:101250000000000573662C000000000031E32E0042
+:10126000000000082D800010000000188000FEE241
+:10127000000000188000FEE1000000002A000000CD
+:1012800000000010001F0000000000000F008000A0
+:10129000000000080F800007000000188000001BFD
+:1012A00000000000280A0000000000000502000005
+:1012B00000000008220000090000000029000000D2
+:1012C0000000000F6568001000000000248A000084
+:1012D00000000003F66C940000000010B972A00436
+:1012E0000000000C73E700190000000C214200040C
+:1012F000000000003CF800000000000C2980000005
+:101300000000001020530000000000082200000828
+:101310000000000C6142000400000018000A0000F8
+:1013200000000000050200000000000C6142000007
+:1013300000000010014200030000000C33E7001D14
+:101340000000000C6142000200000018000A0000CA
+:10135000000000002A00000000000010001F000034
+:101360000000000F0F470007000000080F80000872
+:101370000000000C2980000000000010009F000009
+:10138000000000188000FEBF000000003351000084
+:10139000000000002A00000000000010B1C6002379
+:1013A0000000000F0F500007000000000A6000005E
+:1013B000000000000AE100000000000F4B6200087E
+:1013C000000000090B1600FF0000000F4C62001027
+:1013D000000000000D620000000000090D1A00FF6F
+:1013E00000000010075000030000000C0D1A000858
+:1013F0000000000C0B160008000000000CC60000E6
+:10140000000000000B8000000000000006980000B3
+:10141000000000080F8000030000001006C2000456
+:101420000000000C2900000200000010264200020B
+:101430000000000C295200030000000822000001F7
+:1014400000000010009F000000000000231B0000AF
+:101450000000000027111A00000000006690000044
+:101460000000000C2952000000000010B197320962
+:101470000000000C29800000000000000698000019
+:1014800000000010205300000000000C295200034F
+:101490000000000022C58C0000000010001F0000AA
+:1014A000000000080F800003000000188000FFF318
+:1014B00000000010B1C8001300000010B1C6000306
+:1014C0000000000C298000000000001020530000E4
+:1014D0000000000C295200000000000C29520003FB
+:1014E0000000001006C200020000000C2952000299
+:1014F0000000000022C58C000000000027650000ED
+:101500000000000026E40000000000082200001691
+:1015100000000010B1C600030000000023480000D6
+:1015200000000010B180000500000000234800000A
+:101530000000000C298000000000000F0F50000781
+:1015400000000018800000120000000822000016B1
+:101550000000000C29800000000000003014000092
+:10156000000000003095000000000010075000034C
+:10157000000000090B1600FF000000090D1A00FF13
+:101580000000000F31160008000000003162340036
+:1015900000000003F162300000000010205F000036
+:1015A000000000002C510000000000092CD1007F39
+:1015B000000000082CD90000000000082D000000E9
+:1015C000000000082D80000C00000000000000005A
+:1015D0000000001091DE00000000001005C20004B1
+:1015E000000000080F80000700000000330000002A
+:1015F00000000010009F0000000000188000FE7036
+:10160000000000002A0000000000000F0F5000073B
+:1016100000000010B1C6002D0000000F4742000876
+:1016200000000009070E000F00000008070E000868
+:1016300000000010001F0000000000080900000169
+:101640000000000709121C0000000003CBCA920032
+:10165000000000000B97A2000000000742171C00CA
+:10166000000000000B0400000000000F0A840003CB
+:10167000000000000A959C00000000004A009A004B
+:101680000000000882120001000000010C17080091
+:10169000000000000C978C00000000000218000001
+:1016A000000000080D00FFFF000000080F8000068A
+:1016B0000000000C290000000000001006C2000419
+:1016C0000000000C29520002000000102642000217
+:1016D0000000000C29520003000000082200000155
+:1016E00000000010009F000000000010B197320CB5
+:1016F00000000000231B000000000000271108006C
+:1017000000000000669000000000000C298000002E
+:10171000000000000218000000000010205300002C
+:101720000000000C295200030000000022C5360012
+:1017300000000010001F0000000000080F800006DD
+:10174000000000188000FFF400000000231B0000D0
+:101750000000000027110800000000006690000053
+:1017600000000010B1C8000B0000000C2980000030
+:1017700000000010205300000000000C295200005F
+:101780000000000C295200030000001006C20002F5
+:101790000000000C295200020000000022C58C004D
+:1017A00000000000276500000000000026E40000A3
+:1017B000000000002348000000000008220000177D
+:1017C0000000000C2980000000000010001F000035
+:0817D000000000188000FE3546
+: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-rv2p-09ax-5.0.0.j10.fw.ihex b/firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw.ihex
deleted file mode 100644
index f325e69..0000000
--- a/firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw.ihex
+++ /dev/null
@@ -1,499 +0,0 @@
-:100000000000000000000E80000000580000000901
-:1000100000000000000000000000000000000000E0
-:1000200000000000000000000000000000000000D0
-:1000300000000FA800000ED800000005000000001E
-:1000400000000000000000000000000000000000B0
-:080050000000000000000000A8
-:0800580000000010B180000659
-:100060000000001F03030300000000080500FFFF5D
-:10007000000000180002000000000008050000FF5A
-:10008000000000180002000000000008AC000001A1
-:1000900000000000050000000000000C2F8000019F
-:1000A000000000002B000000000000002B8000007A
-:1000B0000000001091E0000200000008AC00000108
-:1000C00000000010203F006B00000010213F0003E3
-:1000D0000000001020BF003A000000188000FFFD63
-:1000E00000000010B1B8B0150000000B2FDF0002B7
-:1000F0000000000003D80000000000002C380000C1
-:10010000000000082C800000000000082D00000006
-:100110000000001091D400000000000806005555B2
-:10012000000000188000008F000000082D80011CD6
-:1001300000000008020000010000001091DE000035
-:100140000000000F42E0001C0000001091840A161D
-:1001500000000018800000960000000C29800002BA
-:100160000000000C1F800002000000002ADF0000D9
-:10017000000000082A00000F000000000500000039
-:10018000000000188000FFE60000000802000001E7
-:100190000000000F42E0001C0000001091840A18CB
-:1001A000000000082C800006000000082D0000065A
-:1001B0000000001091D40000000000082D8001060E
-:1001C0000000001880000085000000188000FFF18A
-:1001D00000000008B1000001000000082C80010CA4
-:1001E000000000082D000008000000082D8000011C
-:1001F000000000188000007F0000000B2FDF0002CD
-:100200000000000C1F800002000000002C0700000E
-:100210000000001091DE00000000000805005555A8
-:10022000000000188000FFD20000000B2FDF00024A
-:100230000000000C1F800000000000002C070000E0
-:100240000000001091DE0000000000080500555578
-:10025000000000188000FFCC0000000C1F8000028E
-:100260000000000805005555000000188000FFC977
-:100270000000000C298000020000000C1F8000021A
-:10028000000000002ADF0000000000082A0000052E
-:100290000000000805005555000000188000FFC34D
-:1002A000000000080224004A0000001800040000BA
-:1002B000000000188000001C000000188000001ED4
-:1002C000000000188000007800000018800000CBBB
-:1002D00000000018800000CA000000188000000024
-:1002E00000000018800000000000001880000000DE
-:1002F00000000018800000000000001880000000CE
-:1003000000000018800000000000001880000000BD
-:100310000000001880000000000000188000011696
-:10032000000000188000000000000018800000009D
-:100330000000001880000015000000188000001B5D
-:10034000000000188000000000000018800000E19C
-:10035000000000188000002F000000188000011627
-:100360000000001880000141000000188000010C0E
-:100370000000001880000165000000188000006186
-:100380000000001880000000000000188000009E9F
-:100390000000000C1F8000010000000005000000AC
-:1003A000000000188000FFA20000001091D400009F
-:1003B0000000000C298000010000000C1F800001DB
-:1003C000000000082A0000020000000005000000F4
-:1003D000000000188000FF9C0000001091D4000075
-:1003E0000000000C298000010000000C1F800001AB
-:1003F0000000000029420000000000082A0000025E
-:100400000000000005000000000000188000FF95BB
-:10041000000000188000FF9400000010B1BCB00A7A
-:100420000000000B2FDF00020000000003D80000D6
-:10043000000000002C3C00000000001091D40000DF
-:100440000000000806005555000000188000002A32
-:1004500000000018800000DA000000102C6201BAD1
-:100460000000001880000006000000082C80010D2C
-:10047000000000082D0000090000001091D40000C9
-:10048000000000082D8001070000001880000037E0
-:100490000000000C298000000000000C1F800000FC
-:1004A0000000001091DE0000000000002ADF0000C4
-:1004B000000000082A00000600000008050055554D
-:1004C000000000188000FF7E0000001091D40000A2
-:1004D0000000000C298000010000000C1F800001BA
-:1004E000000000082A00000B0000000005000000CA
-:1004F000000000188000FF780000000002020000E9
-:1005000000000000029A000000000000060C2C0011
-:1005100000000004C60C340000000010001F0000A2
-:1005200000000010B196180C0000000806960004A8
-:1005300000000009068DFFFC00000004CD051A0034
-:1005400000000004CC9A18000000001020D7000022
-:100550000000000C2B56000000000000000000000E
-:1005600000000000000000000000001020D7000084
-:10057000000000080F80000100000010B18001F4AD
-:1005800000000010001F00000000000C6B5600006F
-:1005900000000018000400000000000006820000B7
-:1005A00000000010B18A000800000010B18C140790
-:1005B0000000000B050AFFFF00000010B18A0003D5
-:1005C00000000000860A180000000010918C000056
-:1005D000000000082A0000010000001091D4000073
-:1005E00000000018000D00000000000005020000DF
-:1005F0000000001091DE000000000018000A00005A
-:1006000000000000068200000000001091DE0000E3
-:1006100000000010BEE10005000000188000FF4C43
-:10062000000000010561140000000010918A000222
-:1006300000000008B0E1000100000018000D0000FB
-:1006400000000000068200000000001091DE0000A3
-:1006500000000010BEE20005000000188000FF440A
-:10066000000000010562140000000010918A0002E1
-:1006700000000008B162000100000018000D000039
-:1006800000000010B1A0B0130000000B2FDF00022B
-:10069000000000002C200000000000082C8000005A
-:1006A000000000082D0000000000001091D40000A0
-:1006B0000000000806005555000000188000FFDC0F
-:1006C000000000082D80011C00000010001F000029
-:1006D000000000188000FFE60000000F47600008DF
-:1006E0000000000F060E0001000000000F5800007F
-:1006F000000000000A640000000000000AE500009D
-:10070000000000090B66FFFF000000000D61000003
-:1007100000000018800000130000000F4760000870
-:100720000000000B2FDF0002000000082C800000FA
-:10073000000000082D0000000000001091D400000F
-:10074000000000082D80011C0000000F060E0001B3
-:1007500000000010001F0000000000000F58000003
-:10076000000000188000FFD4000000000A640000B0
-:10077000000000000AE50000000000090B66FFFF12
-:10078000000000000D610000000000000262000097
-:100790000000000B2FDF0002000000003104000009
-:1007A00000000000309A0000000000090560000F02
-:1007B00000000010B18A000B0000000005634C002F
-:1007C00000000008050A001200000010B9621403BE
-:1007D0000000000003000000000000188000000678
-:1007E000000000188000FF1100000010B60614047D
-:1007F0000000000803060001000000082A000001B4
-:10080000000000188000FF16000000188000FF9E06
-:100810000000000C298000010000000C295200019A
-:100820000000000C29520000000000080200000E29
-:10083000000000080280001A00000010B1C40A0283
-:100840000000000802000003000000082200000170
-:100850000000000C1F800001000000002ADF0000E3
-:10086000000000002A00080000000008050055559F
-:10087000000000188000FF080000000B2FDF0002BE
-:100880000000001091D40000000000082A000001C0
-:10089000000000002C2000000000001091D4000097
-:1008A000000000082C800000000000082D0000005F
-:1008B000000000082D80011C000000188000FFA629
-:1008C000000000082C800006000000082D00000633
-:1008D0000000000030800000000000003100000037
-:1008E000000000082D8000060000000C2980000197
-:1008F0000000000C1F8000010000001091DE0000CD
-:10090000000000002ADF0000000000082A0000109C
-:100910000000000005000000000000188000FEF349
-:100920000000001091A0B009000000082C80010D0B
-:10093000000000082D0000090000001091D4000004
-:10094000000000082D800107000000188000FF9FB4
-:10095000000000188000001000000008AC0000013A
-:10096000000000188000000B000000000380B000B1
-:100970000000000B2FDF0002000000002C004000F0
-:100980000000001091D4000000000008060055553A
-:10099000000000188000FF81000000188000003176
-:1009A00000000018800000060000000B2FDF00028E
-:1009B000000000002C000E00000000082A000007C4
-:1009C0000000000805005555000000188000FEDDFD
-:1009D00000000000068200000000000C29800001D9
-:1009E0000000000C1F800001000000100CE7000751
-:1009F000000000090562FFFF00000010BA6C14053A
-:100A0000000000002ADF00000000000021000000BC
-:100A1000000000082A0000050000001091D400002A
-:100A2000000000082C80010C000000082D000008C8
-:100A30000000000C31620018000000082D80000149
-:100A4000000000188000FF7500000018000D000075
-:100A500000000010B1A0B00E0000000B2FDF00025C
-:100A60000000000003D80000000000002C2000005F
-:100A70000000001091D40000000000188000001554
-:100A8000000000102C620002000000188000000C22
-:100A90000000000B2FDF0002000000002C07000008
-:100AA0000000000C1F8000010000001091DE00001B
-:100AB000000000080500FFFF000000188000FEBFD6
-:100AC000000000082C80010D000000082D00000926
-:100AD0000000001091D40000000000082D800107E4
-:100AE000000000188000FF6C0000000C298000014D
-:100AF0000000000C1F8000010000001091DE0000CB
-:100B0000000000002ADF0000000000082A00000AA0
-:100B10000000000005000000000000188000FEB387
-:100B20000000000006820000000000082C80010C7C
-:100B3000000000082D000008000000082D8001348E
-:100B4000000000000000000000000010205F000016
-:100B5000000000082C800140000000082D00003C2F
-:100B6000000000082D80011C0000000000000000B3
-:100B70000000001091DE0000000000082C800080C2
-:100B8000000000082D000000000000082D80010575
-:100B900000000010BEE20005000000188000FE9C6E
-:100BA000000000010562140000000010918A00029C
-:100BB00000000008B16200010000001091DE00009A
-:100BC00000000018000D00000000001091D400008B
-:100BD000000000080600AAAA000000188000FF38E4
-:100BE0000000000C298000010000000C1F800001A3
-:100BF000000000082A000009000000080500AAAA59
-:100C0000000000188000FE960000001091D4000043
-:100C10000000000806005555000000188000FF3055
-:100C20000000001091A03C0200000010B1E6620735
-:100C30000000000B2FDF0002000000002C3100003C
-:100C4000000000092CB1007F000000082CD9000032
-:100C5000000000082D000000000000082D80010D9C
-:100C600000000010B1A8000600000010205F000086
-:100C7000000000002C200000000000002CA7000055
-:100C8000000000082D000010000000082D80010861
-:100C9000000000188000FF2B00000010B1A600101B
-:100CA00000000010001F00000000000F0F300007C0
-:100CB000000000000A600000000000000AE10000DF
-:100CC0000000000F4B620008000000090B1600FF37
-:100CD000000000000D620000000000090D1A00FF76
-:100CE00000000010073000030000000C0D1A00087F
-:100CF0000000000C0B1600080000000F4CE3001869
-:100D0000000000000C992C0000000004CC99340075
-:100D1000000000080F8000000000000C2980000186
-:100D2000000000003331000000000008220000161F
-:100D3000000000002ADF0000000000082A00000C6C
-:100D400000000010009F0000000000000F200000C5
-:100D50000000000C1F800001000000080500555530
-:100D6000000000188000FE6A0000001091D400000E
-:100D7000000000080600AAAA000000188000FF0476
-:100D80000000000F4722000800000009070E000FB6
-:100D900000000008070E00080000000802800001A3
-:100DA0000000000702851C00000000088285000189
-:100DB0000000000002854C000000000742851C0076
-:100DC00000000003C3AA52000000000003B10E009F
-:100DD000000000074B071C000000000F0F30000749
-:100DE0000000000F0A960003000000000A955C0056
-:100DF000000000004A005A00000000000C960A00A3
-:100E0000000000090C99FFFF000000080D00FFFF23
-:100E100000000010B1963202000000080F800005AB
-:100E200000000010B1A8000800000010205F0000C2
-:100E30000000000B2FDF0002000000002C2000004B
-:100E4000000000002CA70000000000082D0000108A
-:100E5000000000082D800108000000188000FEF24C
-:100E60000000000C2980000100000010001F00009D
-:100E70000000000C1F800001000000002ADF0000BD
-:100E8000000000082A00000D000000080500AAAAC2
-:100E9000000000188000FE440000001091D4000003
-:100EA0000000000806005555000000188000FEDE16
-:100EB0000000000C298000010000000C1F800001D0
-:100EC000000000082A000007000000080500555532
-:080ED000000000188000FE3C48
-:080ED80000000010B1800004CD
-:100EE0000000001F0303030000000008050000FFCE
-:100EF0000000001800020000000000002A000000AE
-:100F000000000010B1D400000000001091DE0000CD
-:100F1000000000102053000000000010001F00001F
-:100F20000000000C6BD70001000000002F80AA0019
-:100F30000000000C29800001000000080254000F8E
-:100F4000000000002C400000000000092952003F72
-:100F500000000018000400000000001880000010CD
-:100F60000000001880000011000000188000004AF6
-:100F700000000018800001280000001880000127F0
-:100F800000000018800001260000001880000126E3
-:100F90000000001880000000000000188000013FE1
-:100FA0000000001880000122000000188000000BE3
-:100FB0000000001880000145000000188000019A20
-:100FC000000000188000007B00000018800000F97D
-:100FD0000000001880000109000000002A00000045
-:100FE000000000188000FFE4000000002A0000005C
-:100FF0000000000C29800000000000188000FFE1C4
-:10100000000000002A000000000000188000FFDF40
-:101010000000000003820000000000188000FFDADA
-:10102000000000010C161400000000008C181400D1
-:101030000000001091980003000000080C960002C8
-:1010400000000010B1800003000000080C960001B1
-:10105000000000000C000000000000000D1900005E
-:1010600000000010205600000000000C2BD70001EB
-:10107000000000080F8000010000000000000000D8
-:1010800000000010001F00000000000C6BD70001E2
-:1010900000000010011301F100000018000700001B
-:1010A00000000000050200000000001091963421AD
-:1010B00000000010205F0000000000002C1E000057
-:1010C000000000082C800006000000082D0000062B
-:1010D000000000082D800102000000000000000058
-:1010E0000000001091DE0000000000000D61000013
-:1010F00000000018000A00000000000005020000C7
-:10110000000000109196341600000010205F0000CF
-:101110000000000009D80000000000002C1E0000A4
-:10112000000000082C80010E000000082D00000ABD
-:10113000000000082D8001020000000000000000F7
-:101140000000001091DE0000000000000D620000B1
-:10115000000000002C13000000000018000A00002E
-:101160000000000005020000000000109196340904
-:1011700000000010205F0000000000002C1E000096
-:10118000000000082C800006000000082D00006A06
-:10119000000000082D800102000000000000000097
-:1011A0000000001091DE0000000000000D7A000039
-:1011B00000000018000A0000000000002A000000E3
-:1011C000000000000D61000000000000036200004C
-:1011D00000000010234200DB0000000002638C00CE
-:1011E0000000000026460000000000080204001273
-:1011F00000000010B906082E000000000F58000083
-:10120000000000000A640000000000000AE5000081
-:10121000000000090B66FFFF000000000C0000004A
-:10122000000000000B800000000000080CC6001247
-:10123000000000188000FFCE0000001020560000C3
-:101240000000000C2BD70001000000080F800003F5
-:10125000000000000000000000000010001F00005F
-:101260000000000C6BD700010000000827110012DD
-:10127000000000006690000000000008A31B0012A0
-:1012800000000010B198000600000010001F0000D0
-:101290000000000C6BD70001000000102056000079
-:1012A0000000000C2BD70001000000080F80000494
-:1012B0000000000822000003000000082C80000C41
-:1012C000000000082D00000C00000010001F0000AE
-:1012D0000000000C6BD70001000000002596000004
-:1012E0000000000C298000000000000006660000DD
-:1012F0000000000086611800000000090260000F75
-:101300000000000F0204000200000010B60C0805E7
-:101310000000000C1FBF0000000000102866000342
-:1013200000000008078F00010000000C3366001069
-:1013300000000000321400000000000032950000A0
-:101340000000000573662C000000000031E32E0051
-:10135000000000082D800010000000188000FF75BC
-:1013600000000000230000000000000925E6FFFF48
-:10137000000000082200000B0000000C6952000071
-:101380000000000C29800000000000102866008882
-:10139000000000188000FF6E000000002A0000001E
-:1013A000000000082C800040000000082D000020F4
-:1013B000000000082D80011C00000000000000005B
-:1013C0000000001091DE00000000000F42EA001053
-:1013D00000000010004F000400000010B74692000B
-:1013E000000000080249001200000010B5840A0045
-:1013F000000000000D61000000000010BA66346AB1
-:10140000000000088305001200000010004F0002D9
-:1014100000000000034900000000000183068C006A
-:101420000000000083C60C0000000010B18700110E
-:10143000000000000B6E000000000010BEE9000577
-:10144000000000188000FF5500000001056914002D
-:1014500000000010918A000200000008B4E90001B9
-:1014600000000010B1E92C5D0000000086692C002E
-:1014700000000000020000000000000902EAFFFF77
-:1014800000000010000C00020000000002040A002E
-:101490000000000F460C00010000000F0285000153
-:1014A00000000010918C01FC00000010B7040E54E5
-:1014B000000000000F400000000000000D6100006F
-:1014C000000000000A640000000000000AE50000BF
-:1014D000000000090B66FFFF000000000C00000088
-:1014E000000000000B800000000000080C860012C5
-:1014F00000000010205600000000000C2BD7000157
-:10150000000000080F8000030000000C29520000BA
-:1015100000000010001F00000000000C6BD700014D
-:101520000000000827110012000000006690000073
-:101530000000000026460000000000002306000016
-:1015400000000010B198000900000010001F00000A
-:101550000000000C6BD700010000001020560000B6
-:101560000000000C2BD70001000000080F800004D1
-:10157000000000000000000000000010001F00003C
-:101580000000000C6BD700010000000032140000C6
-:1015900000000000329500000000000031E32E0042
-:1015A0000000000573662C00000000002596000076
-:1015B00000000010B18700210000000C298000000D
-:1015C0000000000F0F6B0007000000000D69000015
-:1015D000000000000A6C0000000000000AED00009E
-:1015E000000000000B6E0000000000000B800000F7
-:1015F000000000000C870000000000188000FF1EA3
-:10160000000000010C161400000000008C181400EB
-:10161000000000080C9600010000001091980002E4
-:10162000000000080C990001000000000D190000E6
-:10163000000000000C000000000000102056000018
-:101640000000000C2BD70001000000080F800001F3
-:1016500000000010205300000000000C695200013F
-:1016600000000010001F00000000000C6BD70001FC
-:101670000000000022C58C000000000023120000C2
-:10168000000000002711000000000000269000006C
-:1016900000000010B8170E030000000C29800000A5
-:1016A000000000188000FFEB0000000082970E0091
-:1016B00000000000A3120A00000000082200001A27
-:1016C000000000082C80000C000000082D00000C19
-:1016D000000000082D80001000000010001F000016
-:1016E0000000000C6BD70001000000000D6E000030
-:1016F00000000003E7CF34000000000C2980000048
-:101700000000001091DE000000000010B18700070B
-:1017100000000000361400000000000036950000B4
-:101720000000000037160000000000082C80005068
-:10173000000000082D000030000000082D80000C83
-:10174000000000188000FEF800000000264600009F
-:1017500000000000230000000000000925E6FFFF54
-:10176000000000000B6E000000000003E7CF2C001B
-:10177000000000082200001B0000000C695200005D
-:101780000000000C29800000000000188000FEEF1F
-:10179000000000002A00000000000010086600059C
-:1017A00000000000066600000000000086611800CE
-:1017B00000000009026000F000000010B60C0802F2
-:1017C000000000188000FEE8000000000682000013
-:1017D00000000010B18F000000000008878F00019A
-:1017E0000000000C73660010000000082C80001838
-:1017F000000000082D000018000000082D800002E5
-:101800000000000C5FBF00000000001091DE00002F
-:1018100000000018000D0000000000002A00000079
-:1018200000000010286601F5000000082C8000036D
-:10183000000000082D000003000000093060FFF0E8
-:10184000000000082D8000010000000C298000002D
-:101850000000001091DE0000000000082C80001A3B
-:10186000000000082D00001A00000005736600004B
-:10187000000000082D800002000000003180000000
-:101880000000001091DE0000000000082C80000C19
-:10189000000000082D00000C000000082D8000044E
-:1018A000000000188000FECC0000001800020000BC
-:1018B000000000188000FECA000000002A0000009E
-:1018C00000000010001F00000000000C6BD700019A
-:1018D000000000000F008000000000080F800007DB
-:1018E000000000188000001B00000000280A000013
-:1018F00000000000050200000000000822000009AE
-:1019000000000000290000000000000F65680010C2
-:1019100000000003F66C940000000010B972A004EF
-:101920000000000C73E700190000000C21420004C5
-:10193000000000003CF800000000000C29800000BE
-:1019400000000010205300000000000822000008E2
-:101950000000000C6142000400000018000A0000B2
-:1019600000000000050200000000000C61420000C1
-:1019700000000010014200030000000C33E7001DCE
-:101980000000000C6142000200000018000A000084
-:10199000000000002A00000000000010001F0000EE
-:1019A0000000000C6BD700010000000F0F4700077C
-:1019B000000000080F8000080000000C29800000D3
-:1019C00000000010001F00000000000C6BD7000199
-:1019D000000000188000FEA6000000003351000047
-:1019E000000000002A00000000000010B1C600291D
-:1019F0000000000F0F500007000000000A60000008
-:101A0000000000000AE100000000000F4B62000827
-:101A1000000000090B1600FF0000000F4C620010D0
-:101A2000000000000D620000000000090D1A00FF18
-:101A300000000010075000030000000C0D1A000801
-:101A40000000000C0B160008000000000CC600008F
-:101A5000000000000B80000000000000069800005D
-:101A600000000010205600000000000C2BD70001E1
-:101A7000000000080F8000030000001006C20004F0
-:101A80000000000C290000020000001026420002A5
-:101A90000000000C29520003000000082200000191
-:101AA00000000010001F00000000000C6BD70001B8
-:101AB00000000000231B00000000000027111A0096
-:101AC00000000000669000000000000C2952000099
-:101AD00000000010B197320C0000000C29800000BB
-:101AE00000000000069800000000001020530000D5
-:101AF0000000000C295200030000000022C58C00E9
-:101B000000000010001F00000000000C6BD7000157
-:101B100000000010205600000000000C2BD7000130
-:101B2000000000080F800003000000188000FFEF95
-:101B300000000010B1C8001300000010B1C600037F
-:101B40000000000C2980000000000010205300005D
-:101B50000000000C295200000000000C2952000374
-:101B60000000001006C200020000000C2952000212
-:101B70000000000022C58C00000000002765000066
-:101B80000000000026E4000000000008220000160B
-:101B900000000010B1C60003000000002348000050
-:101BA00000000010B1800005000000002348000084
-:101BB0000000000C298000000000000F0F500007FB
-:101BC000000000188000001200000008220000162B
-:101BD0000000000C2980000000000000301400000C
-:101BE00000000000309500000000001007500003C6
-:101BF000000000090B1600FF000000090D1A00FF8D
-:101C00000000000F311600080000000031623400AF
-:101C100000000003F162300000000010205F0000AF
-:101C2000000000002C510000000000092CD1007FB2
-:101C3000000000082CD90000000000082D00000062
-:101C4000000000082D80000C0000000000000000D3
-:101C50000000001091DE00000000001005C2000529
-:101C6000000000080F8000070000000033000000A3
-:101C700000000010001F00000000000C6BD70001E6
-:101C8000000000188000FE50000000002A00000044
-:101C90000000000F0F50000700000010B1C6003018
-:101CA0000000000F4742000800000009070E000F67
-:101CB00000000008070E000800000010001F0000D0
-:101CC0000000000C6BD700010000000809000001B3
-:101CD0000000000709121C0000000003CBCA92009C
-:101CE000000000000B97A2000000000742171C0034
-:101CF000000000000B0400000000000F0A84000335
-:101D0000000000000A959C00000000004A009A00B4
-:101D10000000000882120001000000010C170800FA
-:101D2000000000000C978C0000000000021800006A
-:101D3000000000080D00FFFF000000080F800006F3
-:101D40000000000C290000000000001006C2000482
-:101D50000000000C29520002000000102642000280
-:101D60000000000C295200030000000822000001BE
-:101D700000000010001F00000000000C6BD70001E5
-:101D800000000010B197320D00000000231B00007E
-:101D9000000000002711080000000000669000000D
-:101DA0000000000C29800000000000000218000064
-:101DB00000000010205300000000000C2952000316
-:101DC0000000000022C5360000000010001F0000C7
-:101DD0000000000C6BD70001000000080F80000617
-:101DE000000000188000FFF200000000231B00002C
-:101DF00000000000271108000000000066900000AD
-:101E000000000010B1C8000B0000000C2980000089
-:101E100000000010205300000000000C29520000B8
-:101E20000000000C295200030000001006C200024E
-:101E30000000000C295200020000000022C58C00A6
-:101E400000000000276500000000000026E40000FC
-:101E500000000000234800000000000822000017D6
-:101E60000000000C2980000000000010001F00008E
-:101E70000000000C6BD70001000000188000FE116C
-: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-rv2p-09ax-6.0.17.fw.ihex b/firmware/bnx2/bnx2-rv2p-09ax-6.0.17.fw.ihex
new file mode 100644
index 0000000..d2f2757
--- /dev/null
+++ b/firmware/bnx2/bnx2-rv2p-09ax-6.0.17.fw.ihex
@@ -0,0 +1,425 @@
+:100000000000000000000970000000580000000916
+:1000100000000000000000000000000000000000E0
+:1000200000000000000000000000000000000000D0
+:1000300000001010000009C80000000500000000CA
+:1000400000000000000000000000000000000000B0
+:080050000000000000000000A8
+:0800580000000010B180000659
+:100060000000001F03060011000000080500FFFF4C
+:10007000000000180002000000000008050000FF5A
+:10008000000000180002000000000008AC000001A1
+:1000900000000008078000000000000C2F80000115
+:1000A000000000002B000000000000002B8000007A
+:1000B0000000001091E1000200000008AC00000107
+:1000C00000000010203F003B00000010213F000313
+:1000D0000000001020BF0015000000188000FFFD88
+:1000E0000000000C1F800002000000188000FFF9D3
+:1000F00000000008B1000001000000082C80010C85
+:10010000000000082D000008000000082D800001FC
+:10011000000000188000004F0000000B2FDF0002DD
+:100120000000000C1F800002000000002C070000EF
+:100130000000001091DE0000000000188000FFEFBA
+:100140000000000B2FDF00020000000C1F800000E9
+:10015000000000002C0700000000001091DE0000ED
+:10016000000000188000FFEA0000000C1F80000261
+:10017000000000188000FFE80000000802240025AD
+:1001800000000018000400000000001880000000BB
+:10019000000000188000001B0000001880000055BF
+:1001A000000000188000000000000018800000001F
+:1001B000000000188000000000000018800000000F
+:1001C00000000018800000000000001880000000FF
+:1001D00000000018800000000000001880000000EF
+:1001E00000000018800000000000001880000000DF
+:1001F000000000188000009D000000188000000032
+:1002000000000018800000000000001880000000BE
+:1002100000000018800000000000001880000000AE
+:10022000000000188000000000000018800000009E
+:10023000000000188000009C00000018800000C62C
+:10024000000000188000009300000018800000E902
+:10025000000000188000003E000000188000000030
+:10026000000000188000007A0000001091D4000007
+:100270000000000C298000010000000C1F8000011C
+:10028000000000082A0000020000000807800000AB
+:10029000000000188000FFC4000000080380010077
+:1002A00000000010B73C0E000000001880000000A5
+:1002B000000000000202000000000000029A00009E
+:1002C00000000000060C2C0000000004C60C3400E6
+:1002D00000000010001F000000000010BA8C2C0C61
+:1002E000000000080696000400000009068DFFFCCF
+:1002F00000000004CD051A0000000004CC9A18008C
+:100300000000001020D700000000000C2B56000059
+:1003100000000000000000000000000000000000DD
+:100320000000001020D70000000000080F8000012E
+:1003300000000010B18001F400000010001F000058
+:100340000000000C6B5600000000001800040000C4
+:10035000000000000682000000000010B18F0004C1
+:1003600000000010B18F1403000000082A000001F3
+:100370000000001091D4000000000000078014006D
+:1003800000000018000D0000000000000502000041
+:100390000000001091DE000000000018000A0000BC
+:1003A00000000000068200000000001091DE000046
+:1003B000000000090561FFFF00000010918A0002A3
+:1003C0000000000830E1FFFF000000188000FF96E9
+:1003D000000000010561140000000010918A000275
+:1003E00000000008B0E1000100000018000D00004E
+:1003F00000000000068200000000001091DE0000F6
+:10040000000000090562FFFF00000010918A000251
+:10041000000000083162FFFF000000188000FF8C20
+:10042000000000010562140000000010918A000223
+:1004300000000008B162000100000018000D00007B
+:1004400000000010B1A0B0130000000B2FDF00026D
+:10045000000000002C200000000000082C8000009C
+:10046000000000082D0000000000001091D40000E2
+:100470000000000805000055000000188000FFDBA8
+:10048000000000082D80011C00000010001F00006B
+:10049000000000188000FFE20000000F4760000825
+:1004A0000000000F060E0001000000000F580000C1
+:1004B000000000000A640000000000000AE50000DF
+:1004C000000000090B66FFFF000000000D61000046
+:1004D00000000018800000150000000F47600008B1
+:1004E0000000000B2FDF0002000000082C8000003D
+:1004F000000000082D0000000000001091D4000052
+:10050000000000082D80011C0000000F060E0001F5
+:1005100000000010001F0000000000000F58000045
+:10052000000000188000FFD0000000000A640000F6
+:10053000000000000AE50000000000090B66FFFF54
+:10054000000000000D6100000000000002620000D9
+:100550000000000002E000000000000B2FDF00029E
+:100560000000000030050000000000003104000021
+:1005700000000000309A0000000000100060000A37
+:10058000000000080516000100000010BA9A1403CC
+:1005900000000000030000000000001880000006BA
+:1005A000000000188000FF5900000010B606140477
+:1005B0000000000803060001000000082A000001F6
+:1005C000000000188000FF5E000000188000FF9D02
+:1005D0000000000C298000010000000C29520001DD
+:1005E0000000000C295200000000000822800002D8
+:1005F000000000080200000E000000080280001A3F
+:1006000000000010B1C40A0200000008020000034C
+:100610000000000C1F800001000000002ADF000025
+:10062000000000002A000800000000188000FF51B0
+:100630000000000B2FDF00020000001091D400002A
+:10064000000000082A000001000000002C2000002B
+:100650000000001091D40000000000082C80000071
+:10066000000000082D000000000000082D80011C83
+:10067000000000188000FFA3000000082C80000686
+:10068000000000082D00000600000000308000007F
+:100690000000000031000000000000082D8000066E
+:1006A0000000000C298000010000000C1F800001E8
+:1006B0000000001091DE0000000000002ADF0000B2
+:1006C000000000082A000010000000080780000059
+:1006D000000000188000FF3C0000001091D40000D2
+:1006E00000000008050000AA000000188000FF8D2F
+:1006F0000000000C298000010000000C1F80000198
+:10070000000000082A000009000000188000FF35E2
+:100710000000001091D40000000000080500005502
+:10072000000000188000FF860000001091A0B002B9
+:1007300000000010B1E662070000000B2FDF00028E
+:10074000000000002C310000000000092CB1007FE7
+:10075000000000082CD90000000000082D00000057
+:10076000000000082D80010D00000010B1A8000657
+:1007700000000010205F0000000000002C2000009E
+:10078000000000002CA70000000000082D00001051
+:10079000000000082D800108000000188000FF7E86
+:1007A00000000010B1A6001000000010001F0000A3
+:1007B0000000000F0F300007000000000A6000007A
+:1007C000000000000AE100000000000F4B6200087A
+:1007D000000000090B1600FF000000000D62000081
+:1007E000000000090D1A00FF000000100730000390
+:1007F0000000000C0D1A00080000000C0B16000889
+:100800000000000F4CE30018000000000C992C00C1
+:1008100000000004CC993400000000080F800000A4
+:100820000000000C298000010000000033310000AE
+:100830000000000822000016000000002ADF00006F
+:10084000000000082A00000C00000010009F0000BB
+:10085000000000002C2000000000000C1F800001A0
+:10086000000000188000FF0A0000001091D4000072
+:1008700000000008050000AA000000188000FF5BCF
+:100880000000000F4722000800000009070E000FBB
+:1008900000000008070E00080000000802800001A8
+:1008A0000000000702851C0000000008828500018E
+:1008B0000000000002854C000000000742851C007B
+:1008C00000000003C3AA52000000000003B10E00A4
+:1008D000000000074B071C000000000F0F3000074E
+:1008E0000000000F0A960003000000000A955C005B
+:1008F000000000004A005A00000000000C960A00A8
+:10090000000000090C99FFFF000000080D00FFFF28
+:1009100000000010BA992C02000000080F800005AA
+:1009200000000010B1A8000800000010205F0000C7
+:100930000000000B2FDF0002000000002C20000050
+:10094000000000002CA70000000000082D0000108F
+:10095000000000082D800108000000188000FF46FC
+:100960000000000C2980000100000010001F0000A2
+:100970000000000C1F800001000000002ADF0000C2
+:10098000000000082A00000D000000188000FEE5AD
+:100990000000001091D40000000000080500005580
+:1009A000000000188000FF360000000C29800001C4
+:1009B0000000000C1F800001000000082A00000752
+:0809C000000000188000FEDEBB
+:0809C80000000010B1800004E2
+:1009D0000000001F0306001100000008050000FFD2
+:1009E0000000001800020000000000002A000000C3
+:1009F00000000010B1D400000000001091DE0000E3
+:100A0000000000102053000000000010001F000034
+:100A10000000000C6BD70001000000002F80AA002E
+:100A20000000000C298000010000000802540010A2
+:100A3000000000002C400000000000000F400000FB
+:100A4000000000092952003F0000001800040000C7
+:100A50000000001880000011000000188000001243
+:100A600000000018800000470000001880000137D7
+:100A700000000018800001360000001880000135D9
+:100A80000000001880000135000000188000000000
+:100A9000000000188000014F0000001880000131A4
+:100AA00000000018800000000000001880000155C0
+:100AB00000000018800001A6000000188000006DF2
+:100AC00000000018800000E400000018800000E52D
+:100AD000000000188000012A000000002A00000029
+:100AE000000000188000FFE2000000002A00000063
+:100AF0000000000C29800000000000188000FFDFCB
+:100B00000000000003820000000000188000FFDAEF
+:100B1000000000010C161400000000008C181400E6
+:100B20000000001091980003000000080C960002DD
+:100B300000000010B1800003000000080C960001C6
+:100B4000000000000C000000000000000D19000073
+:100B5000000000080F8000010000000000000000FD
+:100B600000000010001F00000000000C6BD7000107
+:100B700000000010011301F300000018000700003E
+:100B8000000000000502000000000010B99A2C21AE
+:100B900000000010205F0000000000002C1E00007C
+:100BA000000000082C800006000000082D00000650
+:100BB000000000082D80010200000000000000007D
+:100BC0000000001091DE0000000000000D61000038
+:100BD00000000018000A00000000000005020000EC
+:100BE00000000010B99A2C1600000010205F0000D1
+:100BF0000000000009D80000000000002C1E0000CA
+:100C0000000000082C80010E000000082D00000AE2
+:100C1000000000082D80010200000000000000001C
+:100C20000000001091DE0000000000000D620000D6
+:100C3000000000002C13000000000018000A000053
+:100C4000000000000502000000000010B99A2C0905
+:100C500000000010205F0000000000002C1E0000BB
+:100C6000000000082C800006000000082D00006A2B
+:100C7000000000082D8001020000000000000000BC
+:100C80000000001091DE0000000000000D7A00005E
+:100C900000000018000A0000000000002A00000008
+:100CA0000000000822000001000000000D610000AB
+:100CB0000000001021C2002800000010B1C6000290
+:100CC00000000010234200B3000000090B66FFFF84
+:100CD00000000010BA9A2C24000000000A640000F2
+:100CE000000000000AE50000000000000C00000009
+:100CF000000000000B800000000000080CC600127D
+:100D0000000000188000FFD0000000080F800003E2
+:100D1000000000000000000000000010001F0000A4
+:100D20000000000C6BD70001000000082711001222
+:100D3000000000006690000000000010B198000460
+:100D400000000010001F00000000000C6BD7000125
+:100D5000000000080F8000040000000822000003CB
+:100D6000000000082C80000C000000082D00000C82
+:100D700000000010001F00000000000C6BD70001F5
+:100D80000000001091C6000600000010001F0000C7
+:100D90000000000C6BD7000100000010BA9A2C0371
+:100DA000000000080F800004000000188000FFFC15
+:100DB00000000000259600000000000C29800000C3
+:100DC0000000000032140000000000003295000016
+:100DD0000000000573662C000000000031E32E00C7
+:100DE000000000082D800010000000188000FF8126
+:100DF00000000000230000000000000925E6FFFFBE
+:100E0000000000082200000B0000000C69520000E6
+:100E10000000000C29800000000000188000FF7B0B
+:100E2000000000002A000000000000082C800040A4
+:100E3000000000082D000020000000082D80011C8B
+:100E400000000008220000010000001091DE0000F8
+:100E50000000000F42EA001000000010004F0004E4
+:100E600000000010B746920000000008024900127E
+:100E700000000010B5840A00000000000D610000B1
+:100E800000000010BA6634640000000883050012F8
+:100E900000000010004F00020000000003490000A5
+:100EA0000000000183068C000000000083C60C00D7
+:100EB00000000010B1870013000000000B6E00005E
+:100EC000000000090569FFFF00000010918A000280
+:100ED0000000000834E9FFFF000000188000FF60F8
+:100EE000000000010569140000000010918A000252
+:100EF00000000008B4E9000100000010BAE92C5518
+:100F00000000000086692C000000000002000000C4
+:100F10000000000902EAFFFF00000010000C0002C0
+:100F20000000000002040A000000000F460C00014F
+:100F30000000000F0285000100000010918C01FCF0
+:100F400000000010B7040E4C000000000D6100000E
+:100F5000000000000A640000000000000AE5000034
+:100F6000000000090B66FFFF000000000C000000FD
+:100F7000000000000B800000000000080C8600123A
+:100F8000000000080F8000030000000C2952000040
+:100F900000000010001F00000000000C6BD70001D3
+:100FA00000000008271100120000000066900000F9
+:100FB000000000002306000000000010B1980007A8
+:100FC00000000010001F00000000000C6BD70001A3
+:100FD000000000080F800004000000000000000076
+:100FE00000000010001F00000000000C6BD7000183
+:100FF00000000000321400000000000032950000E4
+:101000000000000031E32E000000000573662C0094
+:10101000000000002596000000000010B187001FAE
+:101020000000000C298000000000000F0F6B00077B
+:10103000000000000D690000000000000A6C0000C4
+:10104000000000000AED0000000000000B6E000030
+:10105000000000000B800000000000000C87000072
+:10106000000000188000FF2F000000010C16140083
+:10107000000000008C181400000000080C9600010D
+:101080000000001091980002000000080C99000177
+:10109000000000000D190000000000000C0000001E
+:1010A000000000080F800001000000102053000025
+:1010B0000000000C6952000100000010001F000039
+:1010C0000000000C6BD700010000000022C58C005E
+:1010D00000000000231200000000000027110000A3
+:1010E000000000002690000000000010B8170E035A
+:1010F0000000000C29800000000000188000FFEDB7
+:101100000000000082970E0000000000A3120A00F9
+:10111000000000082200001A000000082C80000CCB
+:10112000000000082D00000C000000082D800010B9
+:1011300000000010001F00000000000C6BD7000131
+:10114000000000000D6E000000000003E7CF340037
+:101150000000000C298000000000001091DE00005B
+:1011600000000010B18700070000000036140000E6
+:101170000000000036950000000000003716000057
+:10118000000000082C800050000000082D000030F6
+:10119000000000082D80000C000000188000FF0BEC
+:1011A00000000000230000000000000925E6FFFF0A
+:1011B000000000000B6E000000000003E7CF2C00D1
+:1011C000000000082200001B0000000C6952000013
+:1011D0000000000C29800000000000188000FF03C0
+:1011E000000000002A000000000000188000FF013D
+:1011F000000000002A0000000000000C2980000010
+:101200000000001091DE0000000000082C80001A91
+:10121000000000082D00001A0000000573660000A1
+:10122000000000082D800002000000003180000056
+:101230000000001091DE0000000000082C80000C6F
+:10124000000000082D00000C000000082D800004A4
+:10125000000000188000FEF400000008066600018F
+:1012600000000010BA9A1972000000000A64000021
+:10127000000000000AE50000000000090B66FFFF07
+:10128000000000000C000000000000000B800000C7
+:10129000000000080CC60012000000188000FF1DAE
+:1012A000000000080F8000030000000000000000A4
+:1012B00000000010001F00000000000C6BD70001B0
+:1012C00000000008271100120000000066900000D6
+:1012D00000000010919B32000000001002930000FB
+:1012E00000000010B198000300000010001F000073
+:1012F0000000000C6BD70001000000080F80000404
+:101300000000000C2980000000000010001F0000F9
+:101310000000000C6BD7000100000010BA9A2C00EE
+:101320000000000031E32E00000000000B800000F0
+:10133000000000008CCC8C0000000010B5CC8C02AA
+:10134000000000080C800001000000188000FF076A
+:10135000000000080F800003000000102053000070
+:101360000000000C695200010000000022C58C0042
+:1013700000000010001F00000000000C6BD70001EF
+:10138000000000002711000000000000269000006F
+:1013900000000000231B000000000010B1980003B3
+:1013A00000000010001F00000000000C6BD70001BF
+:1013B000000000080F800004000000082200000365
+:1013C000000000082C80000C000000082D00000C1C
+:1013D00000000010001F00000000000C6BD700018F
+:1013E00000000000259600000000000C298000008D
+:1013F00000000000321400000000000032950000E0
+:101400000000000573662C000000000031E32E0090
+:10141000000000082D800010000000188000FEBBB6
+:10142000000000188000FEBA000000002A00000042
+:1014300000000010001F00000000000C6BD700012E
+:10144000000000000F008000000000080F8000076F
+:10145000000000188000001C00000000280A0000A6
+:101460000000000005020000000000082200000942
+:1014700000000000290000000000000F6568001057
+:1014800000000000248A000000000003F66C9400B5
+:1014900000000010B972A0040000000C73E70019EE
+:1014A0000000000C21420004000000003CF8000095
+:1014B0000000000C298000000000001020530000F4
+:1014C00000000008220000080000000C6142000437
+:1014D00000000018000A00000000000005020000E3
+:1014E0000000000C614200000000001001420003F7
+:1014F0000000000C33E7001D0000000C61420002F8
+:1015000000000018000A0000000000002A0000008F
+:1015100000000010001F00000000000C6BD700014D
+:101520000000000F0F470007000000080F800008B0
+:101530000000000C2980000000000010001F0000C7
+:101540000000000C6BD70001000000188000FE9521
+:101550000000000033510000000000002A000000DD
+:1015600000000010B1C600250000000F0F5000075A
+:10157000000000000A600000000000000AE1000016
+:101580000000000F4B620008000000090B1600FF6E
+:101590000000000F4C620010000000000D6200000F
+:1015A000000000090D1A00FF0000001007500003A2
+:1015B0000000000C0D1A00080000000C0B160008BB
+:1015C000000000000CC60000000000000B800000BE
+:1015D0000000000006980000000000080F800003D3
+:1015E0000000001006C200040000000C29000002E8
+:1015F00000000010264200020000000C29520003E7
+:10160000000000082200000100000010001F000080
+:101610000000000C6BD7000100000000231B00003D
+:101620000000000027111A00000000006690000072
+:101630000000000C2952000000000010B197320A8F
+:101640000000000C29800000000000000698000047
+:1016500000000010205300000000000C295200037D
+:101660000000000022C58C0000000010001F0000D8
+:101670000000000C6BD70001000000080F80000381
+:10168000000000188000FFF100000010B1C8001336
+:1016900000000010B1C600030000000C298000000B
+:1016A00000000010205300000000000C2952000030
+:1016B0000000000C295200030000001006C20002C6
+:1016C0000000000C295200020000000022C58C001E
+:1016D00000000000276500000000000026E4000074
+:1016E000000000082200001600000010B1C6000330
+:1016F000000000002348000000000010B180000539
+:1017000000000000234800000000000C29800000B9
+:101710000000000F0F5000070000001880000012AA
+:1017200000000008220000160000000C29800000C4
+:1017300000000000301400000000000030950000A0
+:101740000000001007500003000000090B1600FF06
+:10175000000000090D1A00FF0000000F31160008FC
+:10176000000000003162340000000003F16230002C
+:1017700000000010205F0000000000002C5100005D
+:10178000000000092CD1007F000000082CD90000C7
+:10179000000000082D000000000000082D80000C53
+:1017A00000000000000000000000001091DE0000BA
+:1017B0000000001005C20005000000080F800007AF
+:1017C000000000003300000000000010001F0000B7
+:1017D0000000000C6BD70001000000188000FE43E1
+:1017E000000000002A0000000000000F0F5000075A
+:1017F00000000010B1C600300000000F4742000892
+:1018000000000009070E000F00000008070E000886
+:1018100000000010001F00000000000C6BD700014A
+:1018200000000008090000010000000709121C0068
+:1018300000000003CBCA9200000000000B97A2003A
+:101840000000000742171C00000000000B0400000D
+:101850000000000F0A840003000000000A959C00AD
+:10186000000000004A009A000000000882120001F7
+:10187000000000010C170800000000000C978C000D
+:101880000000000002180000000000080D00FFFF2B
+:10189000000000080F8000060000000C2900000076
+:1018A0000000001006C200040000000C29520002D3
+:1018B00000000010264200020000000C2952000324
+:1018C000000000082200000100000010001F0000BE
+:1018D0000000000C6BD7000100000010B197320D22
+:1018E00000000000231B000000000000271108007A
+:1018F00000000000669000000000000C298000003D
+:10190000000000000218000000000010205300003A
+:101910000000000C295200030000000022C5360020
+:1019200000000010001F00000000000C6BD7000139
+:10193000000000080F800006000000188000FFF281
+:1019400000000000231B0000000000002711080019
+:10195000000000006690000000000010B1C8000BFD
+:101960000000000C2980000000000010205300003F
+:101970000000000C295200000000000C2952000356
+:101980000000001006C200020000000C29520002F4
+:101990000000000022C58C00000000002765000048
+:1019A0000000000026E400000000000023480000C2
+:1019B00000000008220000170000000C2980000031
+:1019C00000000010001F00000000000C6BD7000199
+:0819D000000000188000FE0475
+: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/bnx2x-e1-5.2.13.0.fw.ihex b/firmware/bnx2x-e1-5.2.13.0.fw.ihex
deleted file mode 100644
index 651f434..0000000
--- a/firmware/bnx2x-e1-5.2.13.0.fw.ihex
+++ /dev/null
@@ -1,10191 +0,0 @@
-:10000000000028B0000000600000068800002918E9
-:100010000000161400002FA800000098000045C042
-:10002000000073C400004660000000CC0000BA2845
-:1000300000009A700000BAF80000009400015570AA
-:10004000000057BC00015608000000B80001ADC810
-:100050000000CE200001AE880000000400027CB049
-:10006000020400480000000F020400540000004594
-:1000700002040058000000840204005C0000000636
-:100080000204007000000004020400780000000078
-:100090000204007C121700000204008022170000F6
-:1000A00002040084321700000604008800000005E6
-:1000B0000204009C12150000020400A0221500009A
-:1000C000020400A432150000060400A80000000489
-:1000D000020400B802100000020400BC001000007E
-:1000E000020400C010100000020400C42010000030
-:1000F000020400C830100000060400CC0000000418
-:10010000020400DC00100000020400E012140000F1
-:10011000020400E422140000020400E8321400008B
-:10012000060400EC000000040104012400000000AB
-:1001300001040128000000000104012C000000005F
-:10014000010401300000000002040004000000FF70
-:1001500002040008000000FF0204000C000000FF81
-:1001600002040010000000FF02040014000000FF61
-:1001700002040018000000FF0204001C000000FF41
-:1001800002040020000000FF020400240000003EE2
-:1001900002040028000000000204002C0000003FC0
-:1001A000020400300000003F020400340000003F61
-:1001B00002040038000000000204003C0000003F80
-:1001C000020400400000003F020400440000003F21
-:1001D00002042008000004110204200C00000400A6
-:1001E000020420100000040402042014000004197A
-:1001F0000204201C0000FFFF020420200000FFFF7B
-:10020000020420240000FFFF020420280000FFFF5A
-:1002100006042038000000020204204000000034E0
-:100220000204204400000035060420480000007C41
-:100230000204223807FFFFFF0204223C0000003FB7
-:100240000204224007FFFFFF020422440000000FC7
-:1002500001042248000000000104224C00000000BC
-:10026000010422500000000001042254000000009C
-:1002700001042258000000000104225C000000007C
-:10028000010422600000000001042264000000005C
-:1002900001042268000000000104226C000000003C
-:1002A000010422700000000001042274000000001C
-:1002B00001042278000000000104227C00000000FC
-:1002C000020424BC000000010C042000000003E82C
-:1002D0000A042000000000010B0420000000000AB6
-:1002E0000205004400000020020500480000003222
-:1002F000020500900215002002050094021500205E
-:1003000002050098000000300205009C0810000063
-:10031000020500A000000033020500A40000003028
-:10032000020500A800000031020500AC0000000238
-:10033000020500B000000005020500B40000000640
-:10034000020500B800000002020500BC0000000227
-:10035000020500C000000000020500C40000000506
-:10036000020500C800000002020500CC00000002E7
-:10037000020500D000000002020500D400000001C8
-:1003800002050114000000010205011C000000012B
-:100390000205012000000002020502040000000125
-:1003A0000205020C0000004002050210000000409F
-:1003B0000205021C000000200205022000000013BC
-:1003C0000205022400000020060502400000000A89
-:1003D0000405028000200000020500500000000714
-:1003E0000205005400000007020500580000000844
-:1003F0000205005C00000008060500600000000423
-:10040000020500D800000006020500E00000000D13
-:10041000020500E40000002D020500E800000007CE
-:10042000020500EC00000027020500F000000007B4
-:10043000020500F400000027020500F80000000794
-:10044000020500FC00000027020500040000000176
-:1004500002050008000000010205000C0000000178
-:100460000205001000000001020500140000000158
-:1004700002050018000000010205001C0000000138
-:100480000205002000000001020500240000000118
-:1004900002050028000000010205002C00000001F8
-:1004A00002050030000000010205003400000001D8
-:1004B00002050038000000010205003C00000001B8
-:1004C00002050040000000010406100002000020A8
-:1004D000020600DC00000001010600D80000000058
-:1004E0000406020000030220020600DC00000000F7
-:1004F00002060068000000B802060078000001143F
-:10050000010600B800000000010600C8000000005D
-:100510000206006C000000B80206007C0000011416
-:10052000010600BC00000000010600CC0000000035
-:100530000718040000950000081807600014022343
-:10054000071C000034D40000071C800034CF0D3697
-:10055000071D00000A191A6A081D14605D7402253F
-:100560000118000000000000011800040000000055
-:1005700001180008000000000118000C0000000035
-:100580000118001000000000011800140000000015
-:1005900002180020000000010218002400000002E0
-:1005A00002180028000000030218002C00000000C0
-:1005B000021800300000000402180034000000019E
-:1005C00002180038000000000218003C0000000182
-:1005D000021800400000000402180044000000005F
-:1005E00002180048000000010218004C000000033F
-:1005F0000218005000000000021800540000000122
-:1006000002180058000000040218005C00000000FE
-:1006100002180060000000010218006400000003DE
-:1006200002180068000000000218006C00000001C1
-:10063000021800700000000402180074000000009E
-:1006400002180078000000040218007C000000037B
-:100650000618008000000002021800A400003FFFFE
-:10066000021800A8000003FF021802240000000086
-:1006700002180234000000000218024C00000000C2
-:10068000021802E4000000FF061810000000040039
-:10069000021B8BC000000001021B80000000003420
-:1006A000021B804000000018021B80800000000C2C
-:1006B000021B80C0000000200C1B83000007A1204B
-:1006C0000A1B8300000001380B1B83000000138805
-:1006D000021B83C0000001F4061A2000000000B2D3
-:1006E000061A23C800000181041A29CC0001022740
-:1006F000061A1020000000C8061A100000000002B0
-:10070000061A1E3800000002061A1E300000000201
-:10071000061A080000000002061A0808000000027D
-:10072000061A081000000004041A1FB00005022871
-:10073000041A4CB00008022D061A22C8000000203E
-:10074000061A400000000124021A4920000000009F
-:10075000061A14000000000A061A145000000006D1
-:10076000061A150000000002041A150800050235DB
-:10077000061A151C00000009061A15800000001456
-:10078000061A09C000000048061A0800000000020E
-:10079000061A08200000000E041A1FB00002023AD8
-:1007A000061A2C2800000002061A23480000002028
-:1007B000061A449000000124021A49240000000097
-:1007C000061A14280000000A061A14680000000621
-:1007D000061A154000000002041A15480005023CE4
-:1007E000061A155C00000009061A15D00000001456
-:1007F000061A0AE000000048061A08080000000275
-:10080000061A08580000000E041A1FB80002024120
-:10081000061A2C30000000020200A2800000000135
-:100820000200A294071D29110200A29800000000F6
-:100830000200A29C009C04240200A2A00000000070
-:100840000200A2A4000002090200A4FCFF000000B4
-:10085000020100B400000001020100B80000000124
-:10086000020100DC000000010201010000000001A3
-:1008700002010104000000010201007C00300000C0
-:1008800002010084000000280201008C000000002A
-:1008900002010130000000040201025C00000001BE
-:1008A000020103280000000002010554000000308E
-:1008B000020100C400000001020100CC00000001A0
-:1008C000020100F800000001020100F00000000138
-:1008D00002010080003000000201008800000028B2
-:1008E0000201009000000000020101340000000439
-:1008F000020102DC000000010201032C00000000E4
-:100900000201056400000030020100C8000000017F
-:10091000020100D000000001020100FC0000000103
-:10092000020100F400000001020C10000000002091
-:10093000020C200800000A11020C200C00000A0022
-:10094000020C201000000A04020C201C0000FFFF13
-:10095000020C20200000FFFF020C20240000FFFFFB
-:10096000020C20280000FFFF060C203800000002C7
-:10097000020C204000000034020C2044000000352E
-:10098000020C204800000020020C204C0000002136
-:10099000020C205000000022020C20540000002312
-:1009A000020C205800000024020C205C00000025EE
-:1009B000020C206000000026020C206400000027CA
-:1009C000020C206800000028020C206C00000029A6
-:1009D000020C20700000002A020C20740000002B82
-:1009E000060C207800000056020C21D00000000107
-:1009F000020C21D400000001020C21D800000001EB
-:100A0000020C21DC00000001020C21E000000001CA
-:100A1000020C21E400000001020C21E800000001AA
-:100A2000020C21EC00000001020C21F0000000018A
-:100A3000020C21F400000001060C21F80000001057
-:100A4000020C223807FFFFFF020C223C0000003F8F
-:100A5000020C224007FFFFFF020C22440000000F9F
-:100A6000010C224800000000010C224C0000000094
-:100A7000010C225000000000010C22540000000074
-:100A8000010C225800000000010C225C0000000054
-:100A9000010C226000000000010C22640000000034
-:100AA000010C226800000000010C226C0000000014
-:100AB000010C227000000000010C227400000000F4
-:100AC000010C227800000000010C227C00000000D4
-:100AD000020C24BC000000010C0C2000000003E804
-:100AE0000A0C2000000000010B0C20000000000A8E
-:100AF000020C400800000365020C400C0000035487
-:100B0000020C401000000358020C40140000037552
-:100B1000020C401C0000FFFF020C40200000FFFF01
-:100B2000020C40240000FFFF020C40280000FFFFE1
-:100B3000020C403800000046020C403C000000055A
-:100B4000060C40400000005E020C41B800000001AD
-:100B5000060C41BC0000001F020C423807FFFFFFDB
-:100B6000020C423C0000003F020C424007FFFFFF26
-:100B7000020C42440000000F010C4248000000003B
-:100B8000010C424C00000000010C4250000000002B
-:100B9000010C425400000000010C4258000000000B
-:100BA000010C425C00000000010C426000000000EB
-:100BB000010C426400000000010C426800000000CB
-:100BC000010C426C00000000010C427000000000AB
-:100BD000010C427400000000010C4278000000008B
-:100BE000010C427C00000000010C4280000000006B
-:100BF000020C44C0000000010C0C4000000003E89F
-:100C00000A0C4000000000010B0C40000000000A2C
-:100C1000020D004400000032020D008C021500207D
-:100C2000020D009002150020020D00940810000033
-:100C3000020D009800000033020D009C000000022D
-:100C4000020D00A000000000020D00A4000000053D
-:100C5000020D00A800000005060D00AC0000000217
-:100C6000020D00B400000002020D00B800000003F5
-:100C7000020D00BC00000002020D00C000000001D7
-:100C8000020D00C800000002020D00CC00000002AE
-:100C9000020D010800000001020D015C00000001CE
-:100CA000020D016400000001020D01680000000255
-:100CB000020D020400000001020D020C00000020E1
-:100CC000020D021000000040020D0214000000405E
-:100CD000020D022000000003020D02240000001893
-:100CE000060D028000000012040D030000240243E0
-:100CF000020D004C00000001020D00500000000237
-:100D0000020D005400000008020D00580000000809
-:100D1000060D005C00000004020D00C40000000489
-:100D2000020D011400000009020D01180000002945
-:100D3000020D011C0000000A020D01200000002A23
-:100D4000020D012400000007020D01280000002709
-:100D5000020D012C00000007020D013000000027E9
-:100D6000020D01340000000C020D01380000002CBF
-:100D7000020D013C0000000C020D01400000002C9F
-:100D8000020D01440000000C020D01480000002C7F
-:100D9000020D000400000001020D00080000000127
-:100DA000020D000C00000001020D00100000000107
-:100DB000020D001400000001020D001800000001E7
-:100DC000020D001C00000001020D002000000001C7
-:100DD000020D002400000001020D002800000001A7
-:100DE000020D002C00000001020D00300000000187
-:100DF000020D003400000001020D00380000000167
-:100E0000020D003C00000001020E004C0000003208
-:100E1000020E009402150020020E00980215002018
-:100E2000020E009C00000030020E00A0081000001E
-:100E3000020E00A400000033020E00A800000030E3
-:100E4000020E00AC00000031020E00B000000002F3
-:100E5000020E00B400000004020E00B80000000002
-:100E6000020E00BC00000002020E00C000000002E2
-:100E7000020E00C400000000020E00C800000002C4
-:100E8000020E00CC00000007020E00D0000000029D
-:100E9000020E00D400000002020E00D80000000183
-:100EA000020E00E400000001020E014400000001F7
-:100EB000020E014C00000001020E01500000000271
-:100EC000020E020400000001020E020C00000040AD
-:100ED000020E021000000040020E021C000000047E
-:100EE000020E022000000020020E02240000000E6C
-:100EF000020E02280000001B060E03000000001274
-:100F0000040E0280001B0267020E00540000000C59
-:100F1000020E005800000009020E005C0000000FE5
-:100F2000020E006000000010060E006400000004C5
-:100F3000020E00DC00000003020E01100000000F92
-:100F4000020E01140000002F020E01180000000E16
-:100F5000020E011C0000002E020E00040000000121
-:100F6000020E000800000001020E000C000000014B
-:100F7000020E001000000001020E0014000000012B
-:100F8000020E001800000001020E001C000000010B
-:100F9000020E002000000001020E002400000001EB
-:100FA000020E002800000001020E002C00000001CB
-:100FB000020E003000000001020E003400000001AB
-:100FC000020E003800000001020E003C000000018B
-:100FD000020E004000000001020E0044000000016B
-:100FE0000730040000C900000830076800130282BF
-:100FF00007340000334B00000734800037090CD35E
-:101000000735000030161A96083572F051A2028496
-:10101000013000000000000001300004000000006A
-:1010200001300008000000000130000C000000004A
-:10103000013000100000000001300014000000002A
-:1010400002300020000000010230002400000002F5
-:1010500002300028000000030230002C00000000D5
-:1010600002300030000000040230003400000001B3
-:1010700002300038000000000230003C0000000197
-:101080000230004000000004023000440000000074
-:1010900002300048000000010230004C0000000354
-:1010A0000230005000000000023000540000000137
-:1010B00002300058000000040230005C0000000014
-:1010C00002300060000000010230006400000003F4
-:1010D00002300068000000000230006C00000001D7
-:1010E00002300070000000040230007400000000B4
-:1010F00002300078000000040230007C0000000391
-:101100000630008000000002023000A400003FFF13
-:10111000023000A8000003FF02300224000000009B
-:1011200002300234000000000230024C00000000D7
-:10113000023002E40000FFFF06302000000008003B
-:1011400002338BC000000001023380000000001A4F
-:10115000023380400000004E023380800000001007
-:10116000023380C0000000200C3383000007A12060
-:101170000A338300000001380B338300000013881A
-:10118000023383C0000001F40C3383801DCD650061
-:101190000A3383800004C4B40B338380004C4B407B
-:1011A00006321AA0000000C206321020000000C85B
-:1011B0000632100000000002063214000000004059
-:1011C00006325098000000040632508000000005EE
-:1011D00004325094000102860632500000000020C4
-:1011E00004322830000202870233080001000000A8
-:1011F00004330C00001002890233080000000000D4
-:1012000004330C400010029906321500000000B4AF
-:1012100002321DC80000000006324000000000D865
-:10122000063217D0000000B402321DCC00000000CE
-:1012300006324360000000D807200400009200003E
-:1012400008200780001002A9072400002CD100000C
-:10125000072480002AE50B350824DC6062DA02AB43
-:101260000120000000000000012000040000000038
-:1012700001200008000000000120000C0000000018
-:1012800001200010000000000120001400000000F8
-:1012900002200020000000010220002400000002C3
-:1012A00002200028000000030220002C00000000A3
-:1012B0000220003000000004022000340000000181
-:1012C00002200038000000000220003C0000000165
-:1012D0000220004000000004022000440000000042
-:1012E00002200048000000010220004C0000000322
-:1012F0000220005000000000022000540000000105
-:1013000002200058000000040220005C00000000E1
-:1013100002200060000000010220006400000003C1
-:1013200002200068000000000220006C00000001A4
-:101330000220007000000004022000740000000081
-:1013400002200078000000040220007C000000035E
-:101350000620008000000002022000A400003FFFE1
-:10136000022000A8000003FF022002240000000069
-:1013700002200234000000000220024C00000000A5
-:10138000022002E40000FFFF062020000000080009
-:1013900002238BC000000001022380000000001027
-:1013A00002238040000000120223808000000030F1
-:1013B000022380C00000000E022383C0000001F45D
-:1013C000062250000000004206221020000000C843
-:1013D000062210000000000206222000000000C0CB
-:1013E000062225C00000024004222EC8000802ADDB
-:1013F00002230800013FFFFF04230C00001002B588
-:10140000022308000000000004230C40001002C565
-:1014100006223040000000A00622354000000010E7
-:10142000062236C000000030062240000000020004
-:10143000062235C00000002006223840000000309F
-:1014400006223000000000080222511800000000AF
-:10145000062223000000000E0622241000000030A7
-:10146000062232C0000000A00622358000000010D5
-:1014700006223780000000300622480000000200EB
-:10148000062236400000002006223900000000300D
-:1014900006223020000000080222511C000000003B
-:1014A000062223380000000E062224D0000000305F
-:1014B00002161000000000280217000800000002B9
-:1014C0000217002C000000030217003C000000047B
-:1014D0000217004400000008021700480000000244
-:1014E0000217004C0000009002170050000000900E
-:1014F00002170054008000900217005808140000E2
-:10150000021700600000008A0217006400000080DB
-:1015100002170068000000810217006C00000080C4
-:10152000021700700000000602170078000007D0C4
-:101530000217007C0000076C02170038007C1004C2
-:10154000021700040000000F0616402400000002ED
-:10155000021640700000001C021642080000000144
-:101560000216421000000001021642200000000195
-:10157000021642280000000102164230000000015D
-:10158000021642380000000102164260000000010D
-:101590000C16401C0003D0900A16401C0000009C52
-:1015A0000B16401C000009C4021640300000000861
-:1015B000021640340000000C0216403800000010F3
-:1015C0000216404400000020021640000000000106
-:1015D000021640D800000001021640080000000179
-:1015E0000216400C0000000102164010000000012D
-:1015F00002164240000000000216424800000000AF
-:101600000616427000000002021642500000000060
-:101610000216425800000000061642800000000238
-:1016200002166008000006140216600C0000060096
-:1016300002166010000006040216601C0000FFFF86
-:10164000021660200000FFFF021660240000FFFF6A
-:10165000021660280000FFFF02166038000000201C
-:101660000216603C000000200216604000000034BA
-:101670000216604400000035021660480000002396
-:101680000216604C00000024021660500000002585
-:101690000216605400000026021660580000002761
-:1016A0000216605C00000029021660600000002A3B
-:1016B000021660640000002B021660680000002C17
-:1016C0000216606C0000002D0616607000000052CB
-:1016D000021661B800000001061661BC0000001F80
-:1016E0000216623807FFFFFF0216623C0000003F4F
-:1016F0000216624007FFFFFF021662440000000F5F
-:1017000001166248000000000116624C0000000053
-:101710000116625000000000011662540000000033
-:1017200001166258000000000116625C0000000013
-:1017300001166260000000000116626400000000F3
-:1017400001166268000000000116626C00000000D3
-:1017500001166270000000000116627400000000B3
-:1017600001166278000000000116627C0000000093
-:10177000021664BC000000010C166000000003E8C3
-:101780000A166000000000010B1660000000000A4D
-:10179000021680400000000602168044000000058A
-:1017A000021680480000000A0216804C0000000566
-:1017B0000216805400000002021680CC00000004D3
-:1017C000021680D000000004021680D4000000043D
-:1017D000021680D800000004021680DC000000041D
-:1017E000021680E000000004021680E400000004FD
-:1017F000021680E8000000040216880400000004BD
-:10180000021680300000007C021680340000003D8B
-:10181000021680380000003F0216803C0000009C49
-:10182000021680F000000007061680F40000000594
-:101830000216880C01010101021681080000000057
-:101840000216810C00000004021681100000000442
-:1018500002168114000000020216881008012004FC
-:1018600002168118000000050216811C0000000508
-:1018700002168120000000050216812400000005E8
-:101880000216882C2008100102168128000000088A
-:101890000216812C000000060216813000000007AD
-:1018A0000216813400000000021688300101012078
-:1018B0000616813800000004021688340101010177
-:1018C0000616814800000004021688380101010153
-:1018D00006168158000000040216883C010101012F
-:1018E00006168168000000030216817400000001E2
-:1018F00002168840010101010216817800000001F2
-:101900000216817C000000010216818000000001A7
-:1019100002168184000000010216884401010101C1
-:1019200002168188000000010216818C000000046C
-:10193000021681900000000402168194000000024B
-:10194000021688480801200402168198000000054C
-:101950000216819C00000005021681A0000000050F
-:10196000021681A400000005021688142008100148
-:10197000021681A800000008021681AC00000006D3
-:10198000021681B000000007021681B400000001B9
-:101990000216881801010120021681B8000000011A
-:1019A000021681BC00000001021681C00000000187
-:1019B000021681C4000000010216881C0101010109
-:1019C000021681C800000001021681CC000000014F
-:1019D000021681D000000001021681D4000000012F
-:1019E0000216882001010101021681D800000001C1
-:1019F000021681DC00000001021681E000000001F7
-:101A0000021681E400000001021688240101010190
-:101A1000021681E800000001021681EC00000001BE
-:101A2000021681F000000001021688280101010160
-:101A300002168240FFFF003F0616824400000002AB
-:101A40000216824CFFFF003F021682500000010088
-:101A5000021682540000010006168258000000029F
-:101A600002168260000000C002168264000000C0FE
-:101A70000216826800001E000216826C00001E0022
-:101A800002168270000040000216827400004000BE
-:101A900002168278000080000216827C000080001E
-:101AA00002168280000020000216828400002000BE
-:101AB0000616828800000007021682A400000001BA
-:101AC000061682A80000000A021681F400000C0825
-:101AD000021681F800000040021681FC000001009F
-:101AE0000216820000000020021682040000001787
-:101AF00002168208000000800216820C000002001C
-:101B0000021682100000000002168218FFFF01FF7B
-:101B100002168214FFFF01FF0216823C0000001330
-:101B2000021680900000013F021680600000014014
-:101B30000216806400000140061680680000000262
-:101B400002168070000000C00616807400000007B6
-:101B50000216809C00000048021680A00000004889
-:101B6000061680A400000002021680AC00000048A7
-:101B7000061680B0000000070216823800008000C0
-:101B800002168234000025E40216809400007FFFD4
-:101B900002168220000000070216821C00000007C7
-:101BA000021682280000000002168224FFFFFFFFB9
-:101BB00002168230000000000216822CFFFFFFFF99
-:101BC000021680EC000000FF02140000000000017B
-:101BD0000214000C0000000102140040000000018B
-:101BE0000214004400007FFF0214000C00000000FB
-:101BF00002140000000000000214006C000000004D
-:101C00000214000400000001021400300000000172
-:101C100002140004000000000214005C0000000038
-:101C2000021400080000000102140034000000014A
-:101C30000214000800000000021400600000000010
-:101C40000202005800000032020200A0031500202A
-:101C5000020200A403150020020200A801000030C7
-:101C6000020200AC08100000020200B000000033C5
-:101C7000020200B400000030020200B8000000318F
-:101C8000020200BC00000003020200C000000006C7
-:101C9000020200C400000003020200C800000003AA
-:101CA000020200CC00000002020200D0000000008E
-:101CB000020200D400000002020200DC000000006A
-:101CC000020200E000000006020200E4000000043E
-:101CD000020200E800000002020200EC0000000224
-:101CE000020200F000000001020200FC00000006F9
-:101CF0000202012000000000020201340000000284
-:101D0000020201B0000000010202020C000000010A
-:101D10000202021400000001020202180000000288
-:101D200002020404000000010202040C0000004052
-:101D300002020410000000400202041C0000000423
-:101D4000020204200000002002020424000000021D
-:101D5000020204280000001F060205000000001215
-:101D600004020480001F02D5020200600000000F80
-:101D70000202006400000007020200680000000B7D
-:101D80000202006C0000000E060200700000000459
-:101D9000020200F40000000402020004000000013E
-:101DA00002020008000000010202000C0000000115
-:101DB00002020010000000010202001400000001F5
-:101DC00002020018000000010202001C00000001D5
-:101DD00002020020000000010202002400000001B5
-:101DE00002020028000000010202002C0000000195
-:101DF0000202003000000001020200340000000175
-:101E000002020038000000010202003C0000000154
-:101E10000202004000000001020200440000000134
-:101E200002020048000000010202004C0000000114
-:101E3000020200500000000102020108000000C878
-:101E40000202011800000002020201C400000000AA
-:101E5000020201CC00000000020201D400000002D6
-:101E6000020201DC00000002020201E4000000FFA7
-:101E7000020201EC000000FF0202010C000000C899
-:101E80000202011C00000002020201C80000000062
-:101E9000020201D000000000020201D8000000028E
-:101EA000020201E000000002020201E8000000FF5F
-:101EB000020201F0000000FF0728040000B5000046
-:101EC00008280768001302F4072C000035D500002D
-:101ED000072C80003A3E0D76072D00003B471C067C
-:101EE000072D800022BC2AD8082DC770471202F6A1
-:101EF000012800000000000001280004000000008C
-:101F000001280008000000000128000C000000006B
-:101F1000012800100000000001280014000000004B
-:101F20000228002000000001022800240000000216
-:101F300002280028000000030228002C00000000F6
-:101F400002280030000000040228003400000001D4
-:101F500002280038000000000228003C00000001B8
-:101F60000228004000000004022800440000000095
-:101F700002280048000000010228004C0000000375
-:101F80000228005000000000022800540000000158
-:101F900002280058000000040228005C0000000035
-:101FA0000228006000000001022800640000000315
-:101FB00002280068000000000228006C00000001F8
-:101FC00002280070000000040228007400000000D5
-:101FD00002280078000000040228007C00000003B2
-:101FE0000628008000000002022800A400003FFF35
-:101FF000022800A8000003FF0228022400000000BD
-:1020000002280234000000000228024C00000000F8
-:10201000022802E40000FFFF06282000000008005C
-:10202000022B8BC000000001022B8000000000008A
-:10203000022B804000000018022B80800000000C62
-:10204000022B80C0000000660C2B83000007A1203B
-:102050000A2B8300000001380B2B8300000013883B
-:10206000022B83C0000001F40C2B8340000001F41C
-:102070000A2B8340000000000B2B8340000000056A
-:102080000A2B83800004C4B40C2B83801DCD650013
-:102090000B2B8380004C4B40062A3C400000000480
-:1020A000042A3C50000202F8062A300000000048D2
-:1020B000062A1020000000C8062A100000000002B6
-:1020C000062A31280000008E022A33680000000032
-:1020D000042A3370000202FA042A3A70000402FC57
-:1020E000042A3D0000020300042A15000002030236
-:1020F000062A150800000100022A197000000000DD
-:10210000022A197800000000042A19600002030462
-:10211000062A4AC000000002062A4B000000000404
-:10212000042A1F4800020306022B080000000000DA
-:10213000042B0C0000100308022B08000100000013
-:10214000042B0C4000080318022B080002000000BA
-:10215000042B0C6000080320062A3A8000000014BB
-:10216000062A3B2000000024062A14000000000A72
-:10217000062A145000000006062A3378000000D812
-:10218000022A3A3800000000042A3C5800020328C2
-:10219000042A3C680010032A062A5020000000028E
-:1021A000062A503000000002062A500000000002FB
-:1021B000062A501000000002022A504000000000D1
-:1021C000062A50480000000E022A50B80000000104
-:1021D000042A4AC80002033A062A4B1000000042B3
-:1021E000062A4D2000000004062A3AD00000001400
-:1021F000062A3BB000000024062A14280000000A2A
-:10220000062A146800000006062A36D8000000D806
-:10221000022A3A3C00000000042A3C600002033C11
-:10222000042A3CA80010033E062A502800000002A1
-:10223000062A503800000002062A5008000000025A
-:10224000062A501800000002022A50440000000034
-:10225000062A50800000000E022A50BC0000000137
-:10226000042A4AD00002034E062A4C1800000042FD
-:10227000062A4D3000000004021010080000000182
-:102280000210101000000264021010000003D000C1
-:10229000021010040000003D091018000200035055
-:1022A00009101100002005500610118000000002E6
-:1022B0000910118800060570061011A00000001812
-:1022C000021010100000000006102400000000E0C2
-:1022D0000210201C0000000002102020000000015D
-:1022E000021020C0000000010210200400000001C4
-:1022F000021020080000000109103C0000050576CE
-:1023000009103C200005057B0910380000050580F8
-:1023100002104028000000100210404400003FFF5F
-:102320000210405800280000021040840084924AA5
-:1023300002104058000000000610806800000004F1
-:1023400002108000000010800610802800000002AB
-:102350000210803800000010021080400000FFFFD3
-:10236000021080440000FFFF0210805000000000B7
-:102370000210810000000000061081200000000211
-:1023800002108008000002B502108010000000005A
-:10239000061082000000004A021081080001FFFFC1
-:1023A00006108140000000020210800000001A8028
-:1023B0000610900000000024061091200000004A42
-:1023C000061093700000004A061095C00000004AF5
-:1023D000021080040000108006108030000000020F
-:1023E0000210803C00000010021080480000FFFF37
-:1023F0000210804C0000FFFF02108054000000001B
-:102400000210810400000000061081280000000274
-:102410000210800C000002B50210801400000000C1
-:10242000061084000000004A0210810C0001FFFF2A
-:1024300006108148000000020210800400001A808B
-:102440000610909000000024061092480000004AF8
-:10245000061094980000004A061096E80000004A12
-:102460000212049000E383400212051400003C10A5
-:10247000021205200000000202120494FFFFFFFF79
-:1024800002120498FFFFFFFF0212049CFFFFFFFFF0
-:10249000021204A0FFFFFFFF021204A4FFFFFFFFD0
-:1024A000021204A8FFFFFFFF021204ACFFFFFFFFB0
-:1024B000021204B0FFFFFFFF021204B8FFFFFFFF8C
-:1024C000021204BCFFFFFFFF021204C0FFFFFFFF68
-:1024D000021204C4FFFFFFFF021204C8FFFFFFFF48
-:1024E000021204CCFFFFFFFF021204D0FFFFFFFF28
-:1024F000021204DCFFFFFFFF021204E0FFFFFFFFF8
-:10250000021204E4FFFFFFFF021204E8FFFFFFFFD7
-:10251000021204ECFFFFFFFF021204F0FFFFFFFFB7
-:10252000021204F4FFFFFFFF021204F8FFFFFFFF97
-:10253000021204FCFFFFFFFF02120500FFFFFFFF76
-:1025400002120504FFFFFFFF02120508FFFFFFFF55
-:102550000212050CFFFFFFFF02120510FFFFFFFF35
-:10256000021204D4FFFF3330021204D8FFFF3340BD
-:10257000021204B4F00030000212039000000008C0
-:102580000212039C00000008061203A000000002D3
-:10259000021203BC00000004021203C40000000485
-:1025A000021203D000000000021203DC0000000051
-:1025B0000212036C00000001021203680000003FD9
-:1025C000021201BC00000040021201C00000180805
-:1025D000021201C400000803021201C8000008032F
-:1025E000021201CC00000040021201D000000003E2
-:1025F000021201D400000803021201D800000803EF
-:10260000021201DC00000803021201E000010003D5
-:10261000021201E400000803021201E800000803AE
-:10262000021201EC00000003021201F0000000039E
-:10263000021201F400000003021201F8000000037E
-:10264000021201FC0000000302120200000000035D
-:10265000021202040000000302120208000000033C
-:102660000212020C0000000302120210000000031C
-:1026700002120214000000030212021800000003FC
-:102680000212021C000000030212022000000003DC
-:102690000212022400000003021202280000240398
-:1026A0000212022C0000002F02120230000000096A
-:1026B00002120234000000190212023800000184E4
-:1026C0000212023C000001830212024000000306D5
-:1026D0000212024400000019021202480000000623
-:1026E0000212024C00000306021202500000030610
-:1026F00002120254000003060212025800000C8667
-:102700000212025C000003060212026000000306CF
-:1027100002120264000000060212026800000006B5
-:102720000212026C00000006021202700000000695
-:102730000212027400000006021202780000000675
-:102740000212027C00000006021202800000000655
-:102750000212028400000006021202880000000635
-:102760000212028C00000006021202900000000615
-:1027700002120294000000060212029800000006F5
-:102780000212029C00000006021202A000000306D2
-:10279000021202A400000013021202A800000006A8
-:1027A000021202B000001004021202B40000100471
-:1027B0000212032400106440021203280010644037
-:1027C000021201B0000000010600A0000000001687
-:1027D0000200A06CBF5C00000200A070FFF51FEFBC
-:1027E0000200A0740000FFFF0200A078500003E088
-:1027F0000200A07C000000000200A0800000A000F9
-:102800000600A084000000050200A0980FE0000070
-:102810000600A09C000000140200A0EC555400002B
-:102820000200A0F0555555550200A0F40000555582
-:102830000200A0F8000000000200A0FC55540000B7
-:102840000200A100555555550200A1040000555540
-:102850000200A108000000000200A22C00000000FD
-:102860000600A230000000030200A0600000000784
-:102870000200A10CBF5C00000200A110FFF51FEFD9
-:102880000200A1140000FFFF0200A118500003E0A5
-:102890000200A11C000000000200A1200000A00016
-:1028A0000600A124000000050200A1380FE000008E
-:1028B0000600A13C000000140200A18C5554000049
-:1028C0000200A190555555550200A19400005555A0
-:1028D0000200A198000000000200A19C55540000D5
-:1028E0000200A1A0555555550200A1A40000555560
-:1028F0000200A1A8000000000200A23C00000000AD
-:102900000600A240000000030200A06400000007CF
-:1029100000000000000000000000002E0000000089
-:1029200000000000000000000000000000000000A7
-:102930000000000000000000000000000000000097
-:102940000000000000000000000000000000000087
-:102950000000000000000000000000000000000077
-:102960000000000000000000000000000000000067
-:10297000002E0050000000000000000000000000D9
-:102980000000000000000000000000000000000047
-:102990000000000000000000000000000050008D5A
-:1029A0000000000000000000000000000000000027
-:1029B0000000000000000000000000000000000017
-:1029C0000000000000000000008D009200920096C0
-:1029D0000096009A000000000000000000000000C7
-:1029E00000000000000000000000000000000000E7
-:1029F00000000000009A00DB00DB00E900E900F7BE
-:102A000000000000000000000000000000000000C6
-:102A100000000000000000000000000000000000B6
-:102A200000000000000000000000000000000000A6
-:102A30000000000000000000000000000000000096
-:102A40000000000000000000000000000000000086
-:102A50000000000000000000000000000000000076
-:102A60000000000000000000000000000000000066
-:102A70000000000000000000000000000000000056
-:102A80000000000000000000000000000000000046
-:102A90000000000000000000000000000000000036
-:102AA0000000000000000000000000000000000026
-:102AB0000000000000000000000000000000000016
-:102AC0000000000000000000000000000000000006
-:102AD00000F700FE00000000000000000000000001
-:102AE00000000000000000000000000000000000E6
-:102AF00000000000000000000000000000000000D6
-:102B000000000000000000000000000000000000C5
-:102B100000000000000000000000000000000000B5
-:102B2000000000000000000000FE01030103010E90
-:102B3000010E01190000000000000000000000006C
-:102B40000000000000000000000000000000000085
-:102B50000000000000000000000000000000000075
-:102B60000000000000000000000000000000000065
-:102B70000000000000000000000000000000000055
-:102B80000119011A00000000000000000000000010
-:102B90000000000000000000000000000000000035
-:102BA000000000000000000000000000011A0152B7
-:102BB0000000000000000000000000000000000015
-:102BC0000000000000000000000000000000000005
-:102BD000000000000000000001520176000000002B
-:102BE00000000000000000000000000000000000E5
-:102BF00000000000000000000000000000000000D5
-:102C000000000000017601B5000000000000000097
-:102C100000000000000000000000000000000000B4
-:102C200000000000000000000000000000000000A4
-:102C300001B501F0000000000000000000000000ED
-:102C40000000000000000000000000000000000084
-:102C500000000000000000000000000001F002354C
-:102C6000023502380238023B00000000000000007C
-:102C70000000000000000000000000000000000054
-:102C80000000000000000000023B02760276028095
-:102C90000280028A00000000000000000000000026
-:102CA0000000000000000000000000000000000024
-:102CB00000000000028A028B0000000000000000FB
-:102CC0000000000000000000000000000000000004
-:102CD00000000000000000000000000000000000F4
-:102CE000028B029D000000000000000000000000B8
-:102CF00000000000000000000000000000000000D4
-:102D0000000000000000000000000000029D02B270
-:102D100002B202B502B502B80000000000000000D7
-:102D200000000000000000000000000000000000A3
-:102D3000000000000000000002B802E600000000F1
-:102D40000000000000000000000000000000000083
-:102D50000000000000000000000000000000000073
-:102D60000000000002E6036D00000000000000000B
-:102D70000000000000000000000000000000000053
-:102D80000000000000000000000000000000000043
-:102D9000036D0374037403780378037C0000000060
-:102DA0000000000000000000000000000000000023
-:102DB000000000000000000000000000037C03BBD6
-:102DC00003BB03C303C303CB0000000000000000EB
-:102DD00000000000000000000000000000000000F3
-:102DE000000000000000000003CB041F041F04319A
-:102DF0000431044300000000000000000000000057
-:102E000000000000000000000000000000000000C2
-:102E1000000000000443044D00000000000000001A
-:102E200000000000000000000000000000000000A2
-:102E30000000000000000000000000000000000092
-:102E4000044D0453000000000000000000000000DA
-:102E50000000000000000000000000000000000072
-:102E600000000000000000000000000004530456B1
-:102E70000000000000000000000000000000000052
-:102E80000000000000000000000000000000000042
-:102E900000000000000000000456045B0000000079
-:102EA0000000000000000000000000000000000022
-:102EB0000000000000000000000000000000000012
-:102EC00000000000045B045C045C046E046E04807B
-:102ED00000000000000000000000000000000000F2
-:102EE00000000000000000000000000000000000E2
-:102EF000048004ED0000000000000000000000005D
-:102F000000000000000000000000000000000000C1
-:102F100000000000000000000000000004ED04EECE
-:102F200004EE050205020516000000000000000086
-:102F30000000000000000000000000000000000091
-:102F40000000000000000000000000000000000081
-:102F50000000000000000000000000000000000071
-:102F60000000000000000000000000000000000061
-:102F70000000000000000000000000000000000051
-:102F80000000000000000000000000000000000041
-:102F90000000000000000000000000000000000031
-:102FA000000000000000000000010000000204C05A
-:102FB0000003098000040E4000051300000617C03E
-:102FC00000071C800008214000092600000A2AC0D2
-:102FD000000B2F80000C3440000D3900000E3DC066
-:102FE000000F42800010474000114C00001250C0FA
-:102FF0000013558000145A4000155F00001663C08E
-:103000000017688000186D4000197200001A76C021
-:10301000001B7B80001C8040001D8500001E89C0B5
-:10302000001F8E8000209340000020000000400020
-:1030300000006000000080000000A0000000C00050
-:103040000000E0000001000000012000000140003D
-:1030500000016000000180000001A0000001C0002C
-:103060000001E00000020000000220000002400019
-:1030700000026000000280000002A0000002C00008
-:103080000002E000000300000003200000034000F5
-:1030900000036000000380000003A0000003C000E4
-:1030A0000003E000000400000004200000044000D1
-:1030B00000046000000480000004A0000004C000C0
-:1030C0000004E000000500000005200000054000AD
-:1030D00000056000000580000005A0000005C0009C
-:1030E0000005E00000060000000620000006400089
-:1030F00000066000000680000006A0000006C00078
-:103100000006E00000070000000720000007400064
-:1031100000076000000780000007A0000007C00053
-:103120000007E00000080000000820000008400040
-:1031300000086000000880000008A0000008C0002F
-:103140000008E0000009000000092000000940001C
-:1031500000096000000980000009A0000009C0000B
-:103160000009E000000A0000000A2000000A4000F8
-:10317000000A6000000A8000000AA000000AC000E7
-:10318000000AE000000B0000000B2000000B4000D4
-:10319000000B6000000B8000000BA000000BC000C3
-:1031A000000BE000000C0000000C2000000C4000B0
-:1031B000000C6000000C8000000CA000000CC0009F
-:1031C000000CE000000D0000000D2000000D40008C
-:1031D000000D6000000D8000000DA000000DC0007B
-:1031E000000DE000000E0000000E2000000E400068
-:1031F000000E6000000E8000000EA000000EC00057
-:10320000000EE000000F0000000F2000000F400043
-:10321000000F6000000F8000000FA000000FC00032
-:10322000000FE0000010000000102000001040001F
-:1032300000106000001080000010A0000010C0000E
-:103240000010E000001100000011200000114000FB
-:1032500000116000001180000011A0000011C000EA
-:103260000011E000001200000012200000124000D7
-:1032700000126000001280000012A0000012C000C6
-:103280000012E000001300000013200000134000B3
-:1032900000136000001380000013A0000013C000A2
-:1032A0000013E0000014000000142000001440008F
-:1032B00000146000001480000014A0000014C0007E
-:1032C0000014E0000015000000152000001540006B
-:1032D00000156000001580000015A0000015C0005A
-:1032E0000015E00000160000001620000016400047
-:1032F00000166000001680000016A0000016C00036
-:103300000016E00000170000001720000017400022
-:1033100000176000001780000017A0000017C00011
-:103320000017E000001800000018200000184000FE
-:1033300000186000001880000018A0000018C000ED
-:103340000018E000001900000019200000194000DA
-:1033500000196000001980000019A0000019C000C9
-:103360000019E000001A0000001A2000001A4000B6
-:10337000001A6000001A8000001AA000001AC000A5
-:10338000001AE000001B0000001B2000001B400092
-:10339000001B6000001B8000001BA000001BC00081
-:1033A000001BE000001C0000001C2000001C40006E
-:1033B000001C6000001C8000001CA000001CC0005D
-:1033C000001CE000001D0000001D2000001D40004A
-:1033D000001D6000001D8000001DA000001DC00039
-:1033E000001DE000001E0000001E2000001E400026
-:1033F000001E6000001E8000001EA000001EC00015
-:10340000001EE000001F0000001F2000001F400001
-:10341000001F6000001F8000001FA000001FC000F0
-:10342000001FE000002000000020200000204000DD
-:1034300000206000002080000020A0000020C000CC
-:103440000020E000002100000021200000214000B9
-:1034500000216000002180000021A0000021C000A8
-:103460000021E00000220000002220000022400095
-:1034700000226000002280000022A0000022C00084
-:103480000022E00000230000002320000023400071
-:1034900000236000002380000023A0000023C00060
-:1034A0000023E0000024000000242000002440004D
-:1034B00000246000002480000024A0000024C0003C
-:1034C0000024E00000250000002520000025400029
-:1034D00000256000002580000025A0000025C00018
-:1034E0000025E00000260000002620000026400005
-:1034F00000266000002680000026A0000026C000F4
-:103500000026E000002700000027200000274000E0
-:1035100000276000002780000027A0000027C000CF
-:103520000027E000002800000028200000284000BC
-:1035300000286000002880000028A0000028C000AB
-:103540000028E00000290000002920000029400098
-:1035500000296000002980000029A0000029C00087
-:103560000029E000002A0000002A2000002A400074
-:10357000002A6000002A8000002AA000002AC00063
-:10358000002AE000002B0000002B2000002B400050
-:10359000002B6000002B8000002BA000002BC0003F
-:1035A000002BE000002C0000002C2000002C40002C
-:1035B000002C6000002C8000002CA000002CC0001B
-:1035C000002CE000002D0000002D2000002D400008
-:1035D000002D6000002D8000002DA000002DC000F7
-:1035E000002DE000002E0000002E2000002E4000E4
-:1035F000002E6000002E8000002EA000002EC000D3
-:10360000002EE000002F0000002F2000002F4000BF
-:10361000002F6000002F8000002FA000002FC000AE
-:10362000002FE0000030000000302000003040009B
-:1036300000306000003080000030A0000030C0008A
-:103640000030E00000310000003120000031400077
-:1036500000316000003180000031A0000031C00066
-:103660000031E00000320000003220000032400053
-:1036700000326000003280000032A0000032C00042
-:103680000032E0000033000000332000003340002F
-:1036900000336000003380000033A0000033C0001E
-:1036A0000033E0000034000000342000003440000B
-:1036B00000346000003480000034A0000034C000FA
-:1036C0000034E000003500000035200000354000E7
-:1036D00000356000003580000035A0000035C000D6
-:1036E0000035E000003600000036200000364000C3
-:1036F00000366000003680000036A0000036C000B2
-:103700000036E0000037000000372000003740009E
-:1037100000376000003780000037A0000037C0008D
-:103720000037E0000038000000382000003840007A
-:1037300000386000003880000038A0000038C00069
-:103740000038E00000390000003920000039400056
-:1037500000396000003980000039A0000039C00045
-:103760000039E000003A0000003A2000003A400032
-:10377000003A6000003A8000003AA000003AC00021
-:10378000003AE000003B0000003B2000003B40000E
-:10379000003B6000003B8000003BA000003BC000FD
-:1037A000003BE000003C0000003C2000003C4000EA
-:1037B000003C6000003C8000003CA000003CC000D9
-:1037C000003CE000003D0000003D2000003D4000C6
-:1037D000003D6000003D8000003DA000003DC000B5
-:1037E000003DE000003E0000003E2000003E4000A2
-:1037F000003E6000003E8000003EA000003EC00091
-:10380000003EE000003F0000003F2000003F40007D
-:10381000003F6000003F8000003FA000003FC0006C
-:10382000003FE000003FE00100000000000001FF59
-:103830000000020000007FF800007FF80000026F27
-:1038400000001500000000010000000300BEBC20C5
-:103850000000000300BEBC2000000001FFFFFFFFCE
-:10386000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68
-:10387000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58
-:1038800000000000FFFFFFFF00000000FFFFFFFF40
-:103890000000000300BEBC20FFFFFFFF000000008F
-:1038A000FFFFFFFF00000000FFFFFFFF000000031D
-:1038B00000BEBC2000002000000040C0000061806D
-:1038C000000082400000A3000000C3C00000E480AC
-:1038D0000001054000012600000146C0000167808C
-:1038E000000188400001A9000001C9C00001EA8070
-:1038F00000020B4000022C0000024CC000026D8050
-:1039000000028E400002AF000002CFC00002F08033
-:103910000003114000033200000352C00003738013
-:10392000000394400003B5000003D5C00003F680F7
-:103930000004174000043800000458C000047980D7
-:1039400000049A400000800000010380000187000D
-:1039500000020A8000028E0000031180000395001F
-:103960000004188000049C0000051F800005A300CF
-:10397000000626800006AA0000072D800007B1007F
-:10398000000834800008B80000093B800009BF002F
-:10399000000A4280000AC600000B4980000BCD00DF
-:1039A000000C5080000CD400000D5780000DDB008F
-:1039B00000007FF800007FF800000174000015008F
-:1039C0000000190000000000FFFFFFFF40000000A2
-:1039D00040000000400000004000000040000000E7
-:1039E00040000000400000004000000040000000D7
-:1039F00040000000400000004000000040000000C7
-:103A000040000000400000004000000040000000B6
-:103A100040000000400000004000000040000000A6
-:103A20004000000040000000400000004000000096
-:103A30004000000040000000400000004000000086
-:103A400040000000400000004000000000007FF83F
-:103A500000007FF80000050900003500FFFFFFFFB0
-:103A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF66
-:103A7000FFFFFFFFFFFFFFFFFFFFFFFF4000000012
-:103A80004000000040000000400000004000000036
-:103A90004000000040000000400000004000000026
-:103AA0004000000040000000400000004000000016
-:103AB0004000000040000000400000004000000006
-:103AC00040000000400000004000000040000000F6
-:103AD00040000000400000004000000040000000E6
-:103AE00040000000400000004000000040000000D6
-:103AF00040000000400000004000000000001000F6
-:103B000000002080000031000000418000005200D1
-:103B100000006280000073000000838000009400B9
-:103B20000000A4800000B5000000C5800000D600A1
-:103B30000000E6800000F700000107800001180087
-:103B400000012880000139000001498000015A006D
-:103B500000016A8000017B0000018B8000019C0055
-:103B60000001AC800001BD000001CD800001DE003D
-:103B70000001EE800001FF0000007FF800007FF8E8
-:103B8000000004480000150010000000000028ADEF
-:103B90000000000000010001000D0205CCCCCCC1EA
-:103BA000FFFFFFFFFFFFFFFF7058103C0000000009
-:103BB0000000000000000001CCCC0201CCCCCCCC39
-:103BC00000000000FFFFFFFF400000004000000079
-:103BD00040000000400000004000000040000000E5
-:103BE00040000000400000004000000040000000D5
-:103BF00040000000400000004000000040000000C5
-:103C000040000000400000004000000040000000B4
-:103C100040000000400000004000000040000000A4
-:103C20004000000040000000400000004000000094
-:103C30004000000040000000400000004000000084
-:103C40004000000040000000000E01B7011600D641
-:103C50000000FFFF000000000000FFFF0000000068
-:103C60000000FFFF000000000000FFFF0000000058
-:103C70000000FFFF000000000000FFFF0000000048
-:103C80000000FFFF000000000000FFFF0000000038
-:103C90000010000000000000007201BB012300F3CF
-:103CA0000000FFFF000000000000FFFF0000000018
-:103CB0000000FFFF000000000000FFFF0000000008
-:103CC0000000FFFF000000000000FFFF00000000F8
-:103CD0000000FFFF000000000000FFFF00000000E8
-:103CE0000010000000000000FFFFFFF3318FFFFF16
-:103CF0000C30C30CC30C30C3CF3CF300F3CF3CF308
-:103D00000000CF3CCDCDCDCDFFFFFFF130EFFFFF69
-:103D10000C30C30CC30C30C3CF3CF300F3CF3CF3E7
-:103D20000001CF3CCDCDCDCDFFFFFFF6305FFFFFD3
-:103D30000C30C30CC30C30C3CF3CF300F3CF3CF3C7
-:103D40000002CF3CCDCDCDCDFFFFF4061CBFFFFF61
-:103D50000C30C305C30C30C3CF300014F3CF3CF399
-:103D60000004CF3CCDCDCDCDFFFFFFF2304FFFFFA4
-:103D70000C30C30CC30C30C3CF3CF300F3CF3CF387
-:103D80000008CF3CCDCDCDCDFFFFFFFA302FFFFF98
-:103D90000C30C30CC30C30C3CF3CF300F3CF3CF367
-:103DA0000010CF3CCDCDCDCDFFFFFFF731EFFFFFB2
-:103DB0000C30C30CC30C30C3CF3CF300F3CF3CF347
-:103DC0000020CF3CCDCDCDCDFFFFFFF5302FFFFF45
-:103DD0000C30C30CC30C30C3CF3CF300F3CF3CF327
-:103DE0000040CF3CCDCDCDCDFFFFFFF3318FFFFFA6
-:103DF0000C30C30CC30C30C3CF3CF300F3CF3CF307
-:103E00000000CF3CCDCDCDCDFFFFFFF1310FFFFF47
-:103E10000C30C30CC30C30C3CF3CF300F3CF3CF3E6
-:103E20000001CF3CCDCDCDCDFFFFFFF6305FFFFFD2
-:103E30000C30C30CC30C30C3CF3CF300F3CF3CF3C6
-:103E40000002CF3CCDCDCDCDFFFFF4061CBFFFFF60
-:103E50000C30C305C30C30C3CF300014F3CF3CF398
-:103E60000004CF3CCDCDCDCDFFFFFFF2304FFFFFA3
-:103E70000C30C30CC30C30C3CF3CF300F3CF3CF386
-:103E80000008CF3CCDCDCDCDFFFFFFFA302FFFFF97
-:103E90000C30C30CC30C30C3CF3CF300F3CF3CF366
-:103EA0000010CF3CCDCDCDCDFFFFFFF730EFFFFFB2
-:103EB0000C30C30CC30C30C3CF3CF300F3CF3CF346
-:103EC0000020CF3CCDCDCDCDFFFFFFF5304FFFFF24
-:103ED0000C30C30CC30C30C3CF3CF300F3CF3CF326
-:103EE0000040CF3CCDCDCDCDFFFFFFF331EFFFFF45
-:103EF0000C30C30CC30C30C3CF3CF300F3CF3CF306
-:103F00000000CF3CCDCDCDCDFFFFFFF1310FFFFF46
-:103F10000C30C30CC30C30C3CF3CF300F3CF3CF3E5
-:103F20000001CF3CCDCDCDCDFFFFFFF6305FFFFFD1
-:103F30000C30C30CC30C30C3CF3CF300F3CF3CF3C5
-:103F40000002CF3CCDCDCDCDFFFFF4061CBFFFFF5F
-:103F50000C30C305C30C30C3CF300014F3CF3CF397
-:103F60000004CF3CCDCDCDCDFFFFFFF2304FFFFFA2
-:103F70000C30C30CC30C30C3CF3CF300F3CF3CF385
-:103F80000008CF3CCDCDCDCDFFFFFFFA302FFFFF96
-:103F90000C30C30CC30C30C3CF3CF300F3CF3CF365
-:103FA0000010CF3CCDCDCDCDFFFFFF97056FFFFFBC
-:103FB0000C30C30CC30C30C3CF3CC000F3CF3CF378
-:103FC0000020CF3CCDCDCDCDFFFFFFF5310FFFFF62
-:103FD0000C30C30CC30C30C3CF3CF300F3CF3CF325
-:103FE0000040CF3CCDCDCDCDFFFFFFF3320FFFFF23
-:103FF0000C30C30CC30C30C3CF3CF300F3CF3CF305
-:104000000000CF3CCDCDCDCDFFFFFFF1310FFFFF45
-:104010000C30C30CC30C30C3CF3CF300F3CF3CF3E4
-:104020000001CF3CCDCDCDCDFFFFFFF6305FFFFFD0
-:104030000C30C30CC30C30C3CF3CF300F3CF3CF3C4
-:104040000002CF3CCDCDCDCDFFFFF4061CBFFFFF5E
-:104050000C30C305C30C30C3CF300014F3CF3CF396
-:104060000004CF3CCDCDCDCDFFFFFFF2304FFFFFA1
-:104070000C30C30CC30C30C3CF3CF300F3CF3CF384
-:104080000008CF3CCDCDCDCDFFFFFF8A042FFFFF31
-:104090000C30C30CC30C30C3CF3CC000F3CF3CF397
-:1040A0000010CF3CCDCDCDCDFFFFFF9705CFFFFF5B
-:1040B0000C30C30CC30C30C3CF3CC000F3CF3CF377
-:1040C0000020CF3CCDCDCDCDFFFFFFF5310FFFFF61
-:1040D0000C30C30CC30C30C3CF3CF300F3CF3CF324
-:1040E0000040CF3CCDCDCDCDFFFFFFF3300FFFFF24
-:1040F0000C30C30CC30C30C3CF3CF300F3CF3CF304
-:104100000000CF3CCDCDCDCDFFFFFFF1300FFFFF45
-:104110000C30C30CC30C30C3CF3CF300F3CF3CF3E3
-:104120000001CF3CCDCDCDCDFFFFFFF6305FFFFFCF
-:104130000C30C30CC30C30C3CF3CF300F3CF3CF3C3
-:104140000002CF3CCDCDCDCDFFFFF4061CBFFFFF5D
-:104150000C30C305C30C30C3CF300014F3CF3CF395
-:104160000004CF3CCDCDCDCDFFFFFFF2304FFFFFA0
-:104170000C30C30CC30C30C3CF3CF300F3CF3CF383
-:104180000008CF3CCDCDCDCDFFFFFFFA302FFFFF94
-:104190000C30C30CC30C30C3CF3CF300F3CF3CF363
-:1041A0000010CF3CCDCDCDCDFFFFFF97040FFFFF1B
-:1041B0000C30C30CC30C30C3CF3CC000F3CF3CF376
-:1041C0000020CF3CCDCDCDCDFFFFFFF5300FFFFF61
-:1041D0000C30C30CC30C30C3CF3CF300F3CF3CF323
-:1041E0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF57
-:1041F0000C30C30CC30C30C3CF3CF3CCF3CF3CF337
-:104200000000CF3CCDCDCDCDFFFFFFFF30CFFFFF76
-:104210000C30C30CC30C30C3CF3CF3CCF3CF3CF316
-:104220000001CF3CCDCDCDCDFFFFFFFF30CFFFFF55
-:104230000C30C30CC30C30C3CF3CF3CCF3CF3CF3F6
-:104240000002CF3CCDCDCDCDFFFFFFFF30CFFFFF34
-:104250000C30C30CC30C30C3CF3CF3CCF3CF3CF3D6
-:104260000004CF3CCDCDCDCDFFFFFFFF30CFFFFF12
-:104270000C30C30CC30C30C3CF3CF3CCF3CF3CF3B6
-:104280000008CF3CCDCDCDCDFFFFFFFF30CFFFFFEE
-:104290000C30C30CC30C30C3CF3CF3CCF3CF3CF396
-:1042A0000010CF3CCDCDCDCDFFFFFFFF30CFFFFFC6
-:1042B0000C30C30CC30C30C3CF3CF3CCF3CF3CF376
-:1042C0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF96
-:1042D0000C30C30CC30C30C3CF3CF3CCF3CF3CF356
-:1042E0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF56
-:1042F0000C30C30CC30C30C3CF3CF3CCF3CF3CF336
-:104300000000CF3CCDCDCDCDFFFFFFFF30CFFFFF75
-:104310000C30C30CC30C30C3CF3CF3CCF3CF3CF315
-:104320000001CF3CCDCDCDCDFFFFFFFF30CFFFFF54
-:104330000C30C30CC30C30C3CF3CF3CCF3CF3CF3F5
-:104340000002CF3CCDCDCDCDFFFFFFFF30CFFFFF33
-:104350000C30C30CC30C30C3CF3CF3CCF3CF3CF3D5
-:104360000004CF3CCDCDCDCDFFFFFFFF30CFFFFF11
-:104370000C30C30CC30C30C3CF3CF3CCF3CF3CF3B5
-:104380000008CF3CCDCDCDCDFFFFFFFF30CFFFFFED
-:104390000C30C30CC30C30C3CF3CF3CCF3CF3CF395
-:1043A0000010CF3CCDCDCDCDFFFFFFFF30CFFFFFC5
-:1043B0000C30C30CC30C30C3CF3CF3CCF3CF3CF375
-:1043C0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF95
-:1043D0000C30C30CC30C30C3CF3CF3CCF3CF3CF355
-:1043E0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF55
-:1043F0000C30C30CC30C30C3CF3CF3CCF3CF3CF335
-:104400000000CF3CCDCDCDCDFFFFFFFF30CFFFFF74
-:104410000C30C30CC30C30C3CF3CF3CCF3CF3CF314
-:104420000001CF3CCDCDCDCDFFFFFFFF30CFFFFF53
-:104430000C30C30CC30C30C3CF3CF3CCF3CF3CF3F4
-:104440000002CF3CCDCDCDCDFFFFFFFF30CFFFFF32
-:104450000C30C30CC30C30C3CF3CF3CCF3CF3CF3D4
-:104460000004CF3CCDCDCDCDFFFFFFFF30CFFFFF10
-:104470000C30C30CC30C30C3CF3CF3CCF3CF3CF3B4
-:104480000008CF3CCDCDCDCDFFFFFFFF30CFFFFFEC
-:104490000C30C30CC30C30C3CF3CF3CCF3CF3CF394
-:1044A0000010CF3CCDCDCDCDFFFFFFFF30CFFFFFC4
-:1044B0000C30C30CC30C30C3CF3CF3CCF3CF3CF374
-:1044C0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF94
-:1044D0000C30C30CC30C30C3CF3CF3CCF3CF3CF354
-:1044E0000040CF3CCDCDCDCD000C0000000700C07A
-:1044F00000028130000B81580002021000010230DE
-:10450000000F024000010330000C0000000800C052
-:1045100000028140000B816800020220000102407D
-:1045200000070250000202C0000F0000000800F067
-:1045300000028170000B819800020250000102709D
-:10454000000B828000080338001000000008010002
-:1045500000028180000B81A80002026000018280BD
-:10456000000E82980008038000028000000B802863
-:10457000000200E0000101000000811000000118AD
-:10458000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6B
-:1045900000002000CCCCCCCCCCCCCCCCCCCCCCCC6B
-:1045A000CCCCCCCC00002000CCCCCCCCCCCCCCCC5B
-:1045B000CCCCCCCCCCCCCCCC00002000000000007B
-:1045C0001F8B080000000000000BFB51CFC0F00360
-:1045D0008A7BD81818F67020F843015F646260B8CF
-:1045E0000CC45781588099812198918121849178B8
-:1045F000FD71A208F61321A019C240330419184E08
-:104600000B23C40F02D5988830307C878A5503D994
-:104610000CA2D471FF40E375529862AB2510ECF503
-:1046200058E491F10634792E4954FE4602FA071AED
-:10463000DF5744E50B2940E86CA8F803347961A8FA
-:10464000FC79A8BF1E2A6237F702541E005BBBD25A
-:1046500053600300000000000000000000000000A4
-:104660001F8B080000000000000BED7D0B7854D577
-:10467000B5F03E73CE9C9949662627214F1E6112E4
-:1046800020028638BC0228B74E480850691D6C5578
-:10469000B468070810F296A297D6F6CB04428C8035
-:1046A00036F8FB408B3ABC2A2A6AC048510187A7DA
-:1046B000E8F5F606AB9656EB8D68519147E456A5A2
-:1046C000FF6DAFFF5A6BEF9D39673201ECD77BFF6F
-:1046D000FBDFEF8F9FDF619FBDCFDE6BAFD75E6BE0
-:1046E000EDB5F7D86D1EA65FCDD8D7F807CF7A1BEA
-:1046F000632C23F67CC4CE7E18743356B0CEB7C27A
-:104700009D0EEF77E56D4FF63196B37BAD3205DE4A
-:10471000E7AC6F53E615C6BE0FB8A0723CBCDFB560
-:10472000562981F7396FB42973F1E9B0B14E68CFDA
-:10473000345F0AC3270B3096C9D890894CFC05DC3E
-:1047400039C58C0DC47F4217E78C64C6C63196B755
-:10475000D216092BF03E5439937919DB0470E5A485
-:10476000C177EA5FF6D9B16D8376BCCBC998537334
-:104770006A5FE733963B9BD9183C072FE3EFF1EFD5
-:104780006BF83F2F6C2D0F61A6721E963DE92760D6
-:1047900048E6619EAFD544F076EBC151B179CAE7E6
-:1047A000FA465FA65BEBFD5E3E97DCF6897E177CE2
-:1047B000FD18B61BCA5824AE7D6D58D7D815F00425
-:1047C00004B417F6FE7E262B29463ADCCAA6D0B3DF
-:1047D0005EF3DD8878A93F62676180BBBEE1443942
-:1047E00096D92E850DCBEBFDFD2866277A943045B2
-:1047F0003B81F3F5322FCE4FADF13D540E786E482C
-:104800000E9461BF0F2787E829DF67CF9B9E1D02AB
-:10481000784A17158619D0FDDC3AC5EF80CF3F5690
-:1048200022BA1DE851FDFD86A269D0EE6D3D740DE2
-:104830007EB7488DB6D861FCDA390D054001D6A99E
-:1048400073FE19BCABE4530DE83698B1704A1AD226
-:1048500085B1E3263AE0DFF1E1A2ACF68DC78B3DEE
-:104860002BB01F0D7B89D07CE5FBBCF0912143E38D
-:10487000C663C5040F433819EB5212D175F08B256E
-:1048800047B4A2BEC7FBCF9F4798CB21E00EE95BA0
-:10489000EBD123CB01BFA52FD8A357033D6A3728FF
-:1048A0001107946D7B5D01A4CF99CD5006BA443DAC
-:1048B0003AB53F6D38A95CEFE8BCF72A2877BFA06E
-:1048C000B28DD8EDF0241BCADD09013B1B0765C082
-:1048D000C742172FD66ED8772BF657B9CBC15C4895
-:1048E000CF17177DF72A282F027EC326B55B9AF4CF
-:1048F000FE505E1C51DAB17C760A23FE08A7E991CE
-:104900002D30DE596F67E6F5202F271B9DCC07A0C1
-:10491000ACF074667E1FF8A82AB2BD1CBFABDAA645
-:10492000F811EDA52F6C399C83F37A12F80AF8A8D8
-:104930007A6B32F349FCC1FF27602A5743FD129876
-:1049400027CAFF22D656CE541C7FADEEF3C4F075B5
-:10495000B2D1A0717AE4E9491807BEAB7B56F1E306
-:1049600014EB6C2C847275E645D7EC4D6E9C5F930E
-:104970005EE0C179DDA563BB4591B93B5165554505
-:1049800036E8E5505FB57E83BEB010F1067AAF1011
-:10499000E1EA67856B9D1A40FC2E49756E54013F14
-:1049A000CC1DC8BE2E01FF9C6C043556102B57A1A0
-:1049B0007C933E89E8B34CEDCB9554E2D7EAAD2A1F
-:1049C000F359F889D33F7C94D33FBCC713D99217CE
-:1049D000A3DF1283EB4949BF25A9829E5A77712232
-:1049E00078EE457A003C6D882F78AE11F07927B3C8
-:1049F000120DE8E20D30436117E7CF363B9BCB60E9
-:104A0000EC37D982803609CA3ABB8DF91933B4DA4A
-:104A1000401994FFC2826FE07C18F3FB8280E71696
-:104A200085CDC6791F4260613E2D393AE1AF6D6A8E
-:104A3000F126551130A76379E12F57E5D1F76FD1F2
-:104A4000F71A7C3FAAEFEF8DF28996EF8DF24AF9C3
-:104A5000FD7BD88E392FFC7D5BF995D6F1CBABE48D
-:104A6000F71FD1F8EE0BC36F4C9B6C1D7F5A0D7D69
-:104A70005FEFE0F4EA4E75463642B9D9E50F684873
-:104A8000378D45F1BD9656B011DBA9921F5867408E
-:104A900085EFDDDB52C7AC6266BE98F2271CCF0300
-:104AA000D262E68B948949167E4C0DA459CAD093E4
-:104AB00071E2F2981E0A789D048FDE5F277D51D245
-:104AC000DF49F0DEB1D745E53BAEE4F0DED1DF4DA6
-:104AD000728630B01C28EBA12B0CD37A04702A2CE0
-:104AE0009BB12F94904B196F7EEFB3E1FB2495356A
-:104AF000E07C921C8CF4D15D79C59BC226FCB40E7F
-:104B000002FA42395DD1391E055EEF1AB4307BAE30
-:104B1000699C9641FAEC8D85FCFD7C378E17CC5450
-:104B2000500FEADD0586BBF7388EFC8996719CB97B
-:104B300095344E5EDC388EDCCAB8719CB3378AF788
-:104B4000629C21171AE7AEFC2BADF3C9ADA2718AA6
-:104B5000E2E7935B15374E129F0FBC17E3F8117F06
-:104B60007DCE67C864EB7C06D7D03857E138E34D7B
-:104B7000F3195C13378E9BC6C1F7380E18523E9658
-:104B8000057477742F24FABFE2227B4177849EC09C
-:104B90007ED9BB2E46FAC407E366A15E81C519E43F
-:104BA0005753D2689C2F9380FE6E339DB93EA22747
-:104BB000E89F05024416018840FFD4091EADD8368F
-:104BC0002BB7099FBB4AB3E7A25D72BFC73F0C4436
-:104BD000E7CCAE527D7E02FB66419BFD4497857F0C
-:104BE00085DE9BC28637C0F81DA86C4CE513A0BFBC
-:104BF00018E8ADE3A0BFF0F9B1B04F3F02FDC674B5
-:104C000033BC4D348F131AC7E389F57C1DF972ED5F
-:104C1000513B187B38CC5B8500F70D621A0BDAC06C
-:104C2000F833C959BDA047F78B8EC846A2476080AC
-:104C30000DF89CADEB07B812EDC0CEFC83B047E198
-:104C40006F800D6CD99B5BB71FC266EF2873072D71
-:104C500081F9CEEE586B1F00E533F6AE5BFD6E5367
-:104C60003FB3EDC771DE4EF80FFBB92964B7D8A783
-:104C70003FA8B4966F89B3576B947C410F31AE2F28
-:104C800062477ADD90C9E1B9059F63B0DA207ADD29
-:104C90006AF06F253CF577DA5994D6A3AE0C5688A6
-:104CA000F8C820BB2824D79538F86EB53B0341A03F
-:104CB000E7AD3F56098FF1F076ED4D0ED8C05EEAB4
-:104CC0005AF76F76B4BF2F06FF0F9759EB59988F9D
-:104CD00027F12AF9E0C6D925FD3E32B5BB2934A318
-:104CE000DF47267EF941E52C4BF996869B2CED7F1C
-:104CF000B86CAEA57E6E78B1A57E7EEB6D96F28225
-:104D0000B61F5BDA2F5AD764A95F1CB9DB525FBDAF
-:104D100075ADA55CDBFEB0A57DFDAE0D967ADBDE44
-:104D200011D7A23CAE785B65689F7DE13E712FDABA
-:104D3000575F189A1FDBD421AF811C7ED2984DFC9F
-:104D40007DB2D147CF33BBC63AD11EAF4F02798671
-:104D5000B57EAFF28770EB64D423D01E74F87EE585
-:104D6000C370189CA7D7141FF1BDBA4E6751605588
-:104D700085A5F5F075B71AABD7BAA07E6CDFF5EA5A
-:104D80003A2D61BDD6A525ECF7ACD25D80F65DF875
-:104D9000770E8676605FF603FC0DC0F5A2AFFA537E
-:104DA0003656D96ED23B27141BF1C10DCA9413A8F5
-:104DB0009F6B742EEF353B72A6A03F58A3470B1A8A
-:104DC000DC1718AF1D80C9C27EF2695E8B230362B7
-:104DD000F24BF41B6291FBA52CF447D4CFA7F6A9A4
-:104DE000A46759F440EEF746E1F88113F89EEDCA46
-:104DF000A0F5F19DC640BF8FC09F3BD6389D9EBF9A
-:104E00006F0CF6FB0874CD7B8DB3A9FC7E63889E86
-:104E10005D8D95F43CDED840F51F352EA3F289C692
-:104E2000303D3F696CA5E7C9C636AA3FD5B88ECAE2
-:104E3000671A23F4ECF103843DCAD285FD27EC7593
-:104E40005839A87C4ECC41857F73BFD59F8D727D2C
-:104E5000CEFD6501DAB9E78E816192C03F94CF78CB
-:104E60007EEB9B7E015AEF174680FE637BD7BB9299
-:104E7000387D5C36369D81FEB97B98CE34183FE98B
-:104E800095CBC95E86F71A237D19F1CFF224E81F6E
-:104E9000E79C75713AF5F0C723FF5E8CF1871B84A0
-:104EA0003E4C3AA03670BA6DF223DD4CF8E376D969
-:104EB0000B429FC7E1916CB99CDEF83C9D21F1D972
-:104EC000998B7180FB95E0081BF0C1B90E07CDEB03
-:104ED000DCEEE408C36F313832E94278E370546F96
-:104EE000751966FD50DB9E6A58F5458E61D617E749
-:104EF0008E6CF2A2DC2FC9B6191F8D45FE0808FE84
-:104F0000E07C27FBAF6DCF33DC967EACE5736DCADA
-:104F100074F48340B9A77C3F817F209F4BB275E337
-:104F20002390EF935B87A4E0B8E0C71938CEA94679
-:104F3000C3E0E3661B66BEAC599644ED257C7DF567
-:104F4000FBF7860F2D830F9D8C50FFF5906FEE675A
-:104F500033ED4F14CF61BBED5FE2BAE380FFBFA634
-:104F600078804665D96F7DBB1A765C81EFB759C6EC
-:104F700083EF7CD287C6F5AA6FBA6BEC84292E50DA
-:104F80008763907FE4243A87A0C714E8EFACE66E0D
-:104F900055609CE9361FD5D70B7EAC7576E9217834
-:104FA00075BA83D3A3AF714E361EF169A03F2A9D17
-:104FB000E091C13895ED23CA503F9EEE58911902F9
-:104FC000BEAD56CFDD114CF07DAB4DE1F044ECDDD4
-:104FD0005DA6F9C8380A63D0AF33063F72FA0953A9
-:104FE000395E5FCBE77DD82FF047DDB6A3E55701EB
-:104FF000FC75BB3ED7118EE9B6D07DB68CD8FC15BA
-:105000009C3FF453B5F5031DE7F7893D5C70E70558
-:10501000F4546F38DDD914B793F0855927DA31F39A
-:105020007AE28ABE1BDF05D1FCF49FEC6C15C0C18F
-:10503000FE02ADA0DE2E6A2B58D08BF89AD7514DC8
-:10504000F1C54F6DD26E6A2B46FE38CD6CD3717EA2
-:10505000A7D99BDEB126FC75D8B8DDCF5AB91D1390
-:1050600086FF101EB0672D76CDA275D6F242765D12
-:1050700026EA8D85F7DB590450B418ED22C91F309C
-:10508000EFCD366EEF2E620D2D68CF690EEE1FCC80
-:1050900033983600E0AAFDD5A3C568F7BF6CB311FD
-:1050A0007D649C61711A87BB2A3DA207A0FEC38E56
-:1050B000B1375C85DCE788B4E0BACC52987F0BEB63
-:1050C0008DCFF9AD56F82E067F3CBC8C2DB7C02194
-:1050D000FB9570A85B95402401DFBD26F94EE89151
-:1050E00034D56AE767C595DFB389F8A5CA54A4F338
-:1050F00069C319B6A550BD3F8AF1911D0EFF0AA0E4
-:10510000EFEDB66017EA67B00B8A98A9DDEDB6102F
-:10511000BD3FA5BCB110ED53A6458BD0BF8735452B
-:10512000437ED0053FA849DE228CC77A18AC9F2069
-:10513000970E840FFA69F154CE6445187F053985BE
-:10514000FEEEF1961F51A0EC727730ECCF916D8D91
-:105150002FBB7CD6723DFE03E9309C511C2779B8E9
-:10516000B51E162C86FCE6F15BDFFFEF1E3C458981
-:105170006FBDC4D2F074BAA32A8CCF266AA7CC76AE
-:10518000739D93C34F7E39B45F2AECF93AE60B5313
-:105190009C389BF3C1D219368267A9C7E70F43BD7C
-:1051A000A20518CA1FC6AACDEB58FD7910B97EA674
-:1051B000B2D6AD235FD69FD75804F47D912DE4512C
-:1051C000C723FE0264E73A01595F03C89A7BBAC558
-:1051D000EE6503D3C4FA3AD030CBEB40A4F3F81811
-:1051E0009DA55EB00BBD08FA224BCD403DD85D4E6B
-:1051F0007E09EB223D21DBE9B17603118EBEDAB9DF
-:1052000062EDF212F557FBAB67768601FF55CF3D95
-:10521000E005E2B34FB5B64C3FBCAFD9B2D28B7C00
-:10522000FC8916F6E2BC3F8DA8D313F1F30DAA2238
-:10523000FCB1805B417F58D0E9E453ABBF8B78FF72
-:10524000728BDDC026F55B1D510710B1AE6331E7EF
-:10525000A7AD8E0F78F9AECF919EF5BBACF256F5A7
-:10526000C4039918EF040C71BF9145C97EAEDBFCF5
-:10527000C772B447EA5937E989F8EF70FCF369B4AB
-:105280007ECDD5537AD7CBFD977AC1F7F51DAB3FCD
-:1052900057BD58B6CA77A5F047A6A99E748A2B4D6C
-:1052A0006013906E120F2CC2EDE1154F3E54F401C5
-:1052B000C0716AF33F79154BDC88EB8773EDF31F00
-:1052C0007FC9D7B75E3F23FCF9D87711FACEB78BE9
-:1052D000DBEF6C377FD6D8A35EF4976A36D8FD2013
-:1052E00099ACE6994DBF7C04F9FA770E8A33543FA6
-:1052F00073E89D2BA15CBDDD9E3E934FC3AD64C69C
-:10530000E8510FFF2F1B13C37FD5F38774DF28FEEF
-:10531000FEA769313A546FDFA7B351BDF156DABE2B
-:105320004FEF7227A047FB07E5686FAF78F22B1DA0
-:10533000E5EAD3BD0ACBCAEBFD7DE5864364CF2108
-:105340009E887E823E3DF4EA45A7E8775F1A47EDE6
-:105350000C5CBFFAA2D3485CFB32888F9F7D09E3C7
-:10536000F7BF77F871FE95CFFEC88BF3F8586BE066
-:10537000FCFCE8CACC008C5B690F671AF4E4EF2BE5
-:105380001FBB9DF86CD1D1DB33291EC00239365AC0
-:1053900043C33938BF05EBAFA7F92D6421E2B7CA83
-:1053A00047D56004E3591A9BBE3D813CBC21E4E132
-:1053B000E38D0E5C7BD8C7A860D13F7C53A57D02EE
-:1053C000C66EA378C3ED721F822DA1F2174E4EA7B1
-:1053D0004DAA4DC6379C163EDD7C5727D2E7E4A088
-:1053E0004016C627010F61812F05F58E7A746A1663
-:1053F000A70FF369C5E23BD08BA5F81EDB77DA0374
-:10540000AE22CB77621DE3E32F15E303DC49688FFF
-:105410007D9C09F64D82F97DA54ABD0CF68689BFB3
-:105420004C72CDE57CF3DD5CAEA59C47664DC7FABA
-:105430003FBDC5E507BFC3751DE08A6651FDBEEFE0
-:105440002BA4071C2C9A489E37DB853C5BEBE5FEC2
-:1054500024C0ADE1FA14E313E83F8DF04F76DAC2D1
-:10546000FBE13B935EAEC7F1A89D1E7B6F5AD71739
-:1054700009F97F5515FBA342FED97A2EF77DDBBDD6
-:1054800061EE1FD823BF7C04E515E413D7999A6712
-:10549000EC419CF767DB0EBC7333F0F567ED524EC1
-:1054A000AD7A335E4E2B778C6789E4F433B79F2552
-:1054B0009453789F504EDD5DC4C7FFD97A53E2ED17
-:1054C0004C9CDE947AB02FFCC5EBC135AA2FA11EEF
-:1054D00084BFB758716FBE93FC26F9ACEAE9DAC114
-:1054E000143792FC28F9AD871F25BFC5CFD38AB7E3
-:1054F000F8FA1785BE9174B62F67610FC64BF7A8EF
-:10550000E45F9F05985A80BE67B7E54530EEBCD290
-:10551000C5E317678D6E6F1A3C57A6F2727786DE69
-:1055200082FA41BEEF76F1F8F6D960B737D5E45785
-:105530007CB05BF5FAA0BE2BC2A627F23740F3126F
-:105540001C5DACAF7A1E0F9EAABA7397A1DFDEA6D0
-:10555000D27E7645D38D5EDC073EBB7BC8CF513F04
-:105560002D780D0C4C80F72CDA812938BD80867996
-:1055700009F305BD3F61E10727C3FCE6EFE6FE4204
-:10558000C59A38FBDEBD54477D03F6FD716B5C9B0D
-:10559000F34D95E8A772BDB5BE8AAD21BA55C5F1E8
-:1055A0005148F8811334C147A3D968E187F1F885E0
-:1055B000D05753D5C29FA39D71F6088F2B9EDBADAC
-:1055C00012FECF6D532218F7A1F8EE24A47FB7CEB8
-:1055D0004CFEF229E437BD6F393EF5C21F8AEF84D5
-:1055E00026353BDF2DFA053C4FEDFC5DC1CB58FE67
-:1055F000D56F73DF65BDDB97EEFD33ED1F9FDDEBF0
-:105600002038CEEE7D35F74E2CBFE4F0239C679713
-:105610003B68FF2CBCD7131986F58380DEB86EEE8D
-:10562000F9AAA88BD69D66A2D33C8DEF779CDBFDB3
-:10563000EFEF2B987FB0DBE1C379D4EFE57921F56B
-:105640002FB928EE7276CF57C521F7DF6F3E753A36
-:105650000B11FF79D8EC1DC8AFA97C1FA0FEE5494E
-:105660009B9A703FBC639F8EFB2BA5AFFCB508F5E2
-:10567000CBD91DDC4E3863EF7A0CF7416BB5A1CB6B
-:10568000ED28F768B3F507BBD3BE604AB830115EAA
-:10569000381ECE021E705E80974AD48B7DE1A359DE
-:1056A000E3FEE67F3F7C7C7E2B8E5FB37B02C94DA1
-:1056B0000C2F4A80BFF7449C0ACD9FBFDFFB5511DA
-:1056C000DA3D9FB537D13A7EB1796FFA1F376F2532
-:1056D0007A29F3DEFFDF9CFFA76B7C5D8A9783DE70
-:1056E0007CFEAB3BA8FCACC74FF05EA2FC1FFF9F4B
-:1056F00046F71D4077EFC5E9AED8FFBBCEFB62741D
-:105700007F4DD0DD63605EC1D93D7FA578B99CFF38
-:10571000C5E6EDFB7F74DED2FE5965F3B7E543FBCA
-:10572000352CDAE90338570EBFAE0DC34CE0260422
-:1057300013D923413BF78F5485C761D8201E1762C8
-:10574000C29FA014301FC65116925DA7B95BC8CE88
-:10575000649ABF3300F85835729E9F7235D89863AB
-:10576000212C0F9CECA7F8669C5FA58DFCF611B46C
-:10577000EF9B9B003E18A7D9A319602931FB705BF2
-:10578000D45144CF0FF079978867D90DDDE257B82F
-:10579000E3FC0297CF5AEF10FD3BD97E03F3889CC0
-:1057A0007E8D45B01D6B0B9BF3071CCCF41DD417ED
-:1057B0006200D6643F7E53FC35F5E06F4C6700F124
-:1057C00037C246712D4AEA237CF823AB781E85D375
-:1057D0008ACF964EC4A3C6C0FFE3F322BF91097FD0
-:1057E00051135D68C36D0197B59DF08B2E4A1F4E16
-:1057F0008FDC1A419F25167A48BC5F802E167A48A6
-:10580000FC7E53BAC4D3231EFFDFB7F3B89BA49327
-:1058100025BF2383FB2151F0435EDDB689E21DA73E
-:105820009FFAE0BBC8A7D52FABCC09DF9FD9E661B3
-:1058300051945F2DA2A33F55D5A1268CF34ABBBC42
-:10584000FA390FF179D50E4764267C5FB5F3C32290
-:10585000B29B96771F1E807181A7144EBF7057119F
-:10586000EEDB5569DC3F88EF6FBD9DC7054EBD98E7
-:105870003C1BE30FCA569EAF58D57EA3DD61DA7795
-:10588000FE5F769EF70AED489EC34F2AB4DEF4868B
-:105890008FFB05A79E54387CBBEC11CC7BACDABAED
-:1058A000410FA15FB9F5738A63973EF78CB78BFC04
-:1058B00045D5EA3F6F55899EF024BAC5FBB1751DE9
-:1058C000B5E427D4B50B3F31CE8FAA7E6ECFCE3054
-:1058D000A0A6FAF927BC187F39D9B9C54BFEE956FD
-:1058E000EE7F6A6E2DB17F7A31BFB4FDEE847EE922
-:1058F00049FC07F813FBEC71FEFCD67E97B67FF9E6
-:10590000CC178F619CF4D48ECF1E43B86BFEE3DFBF
-:105910001E43FB9EED75195B60BEF54FBD4DF12634
-:10592000F9DDBB424ECF0C62E11C6877E6770ECA08
-:105930001F39B3E7E35CF4E7CE6CFF7326FAF54B4F
-:10594000F74CCDC2792F7DA1348B259077F944BED9
-:105950008C5C429C309E0E073A0E901F72FA988320
-:10596000FCBE9EF8427B2D8FD7F8445C615BE23829
-:10597000ACF487EB3A3E2CE7F131E1175F2C8EF067
-:1059800016D0F18A4BA0D73611278AA3D769FC0716
-:10599000D0E5AB387A7DC1428FE7E03E6447BF3E39
-:1059A000E308D14BC0938CEF1EB6076C3ACAC18E88
-:1059B000E41E3ACD443A3DF3452EC6C33FB177933A
-:1059C000DDD3BDC761A07F5FB5E7B72417675E3839
-:1059D0004AF15326E2AC6758CF1F8F8B29627E9B1A
-:1059E0003D3CFE20F08DF1099F97DE8B3804E75790
-:1059F000199FE82B2E314117794F22EE5CBBF95DE0
-:105A00009DC5C579948948A70F2CF17139EFF8FE2F
-:105A10000CC4C304737C2D71DC47FACD313AF1B864
-:105A20009A8C9F9DD920E26EF07EE018F407791CD5
-:105A3000A33EA2FC96259043195F1BA3C7C961E44E
-:105A4000D2E26A1783F76FC5C7309DAF0B122FA73D
-:105A5000FE92580F7F47E7723DDD169AA99BF6B379
-:105A60007F28F65924BE24BCA7441EDEA9A7548A69
-:105A700007B5B41F207D1A2FCF757D9C83B855E7DD
-:105A8000F1D6BA5DFB8A50EF9CDAFF22F15DDDB6FC
-:105A90000FF430F47378EBF33AB727399FA39E8E57
-:105AA00098F4F4A967F715F1B81FCFBB8DEFBF5A73
-:105AB000F45FBFDBDA7FFDB6CF2DFD5787DB75BE08
-:105AC0005E5E789C935AE0469CEFC94E3B437D77DF
-:105AD000B25D9D1E496407EA76CB3E68CB519DD6E8
-:105AE000AB716F26517EEED2A3D3DF4DC17D3A104C
-:105AF00033B47F3B9A385F75FC2C3000E9D271F4E7
-:105B00006615D78D9D8847931D5CFC5643A907E415
-:105B1000B5F8BDE03864AB783D30E198CD02378C04
-:105B20009385FAB819FAC17C7ACC1FC2FD51D55BB6
-:105B30003E1DE1510D9BE14AB87EF2FEECEE2043A2
-:105B4000BBDC6E58F395B3AF1371B4A8356F3D5BF2
-:105B500067C3711F9CD992FCB81FB0644460F421E4
-:105B6000CCAB5F904D71E29CEFF1EF4E1BEEB0EDD0
-:105B70008AD8BE6DF279E81FF3606C91B573E0BB13
-:105B800064AD5DC17D007832A4CBEDB6D0463D0357
-:105B9000DBE9CC07AAF1315DD128FF429C7B91FD66
-:105BA000C9767DED07CB7348AA807F88D80F1EC4C5
-:105BB000BA14DC0F5EEFE1E79106BBD3E9BCD12656
-:105BC00061AFF970DF15DB3558D7ED8B9E476AB5AD
-:105BD00096D34B4B6E1BEC073F58BFA354037D90ED
-:105BE0007E63C9F60106EE4BDF5F8A79F7E94F94D1
-:105BF0008CCE81F26C475119D5FF4BC9E85C28FF68
-:105C0000A8755219D5572B9417B847EF2E0DBB63C3
-:105C1000F29901C62DE65B80DCEE47B93D1D3CD50F
-:105C200082B5B5D77FA9F3F3302C88F31F3491CF19
-:105C30007FA0FBBDED38DFC1B6AE26E4BFC7F77C61
-:105C4000958AED7CCCA0791AACD9C07D797835F1F4
-:105C5000EB0BE4FFC4E7C1487E7F2E39F41B84E3DD
-:105C6000EE79C31F2A479D5AE3273E8ADF276646FF
-:105C70003AD1A542D005E1749AF2902BF12402E9C1
-:105C80009B3203C751C235EAD7977F73784E487E5F
-:105C900011E7C04CE7A43E45381F4E0ED133FE9CA1
-:105CA000D47E3DF819F253CEC2F3B908BF3CFF547D
-:105CB000BAC84D718173BB59C491407EE4736323AC
-:105CC000CBD086F65DFFB623F4671C37FF15DF8E59
-:105CD00023D0DF1515BA1F53D7AE58362E431BCB32
-:105CE000F884D09E1074CB465AA27CDDC1F8B91C52
-:105CF000871240BFF1EC8F0CD2BF032B66925F710D
-:105D00003639AF1DF327CEDEC9F300608557500E3C
-:105D100006ED4E89A2FF037CFC651C1F7F695D6751
-:105D2000ACE39EFDDAB7AB8BFA33447F60E864A244
-:105D3000DCF0BFB32AB7B3CF36FA080E300BF7E169
-:105D40007A7AA9E3653BACE7F400EFFD1D26BCE7DA
-:105D50003AFAA45F9E83D38F9EF1F45BE86CC8454A
-:105D600039AE0AB697A36BFAF1C23B8A91A9DFD686
-:105D7000439761FB9AD99D8779CE504301EEB3F5E5
-:105D8000A62F3F8F95B97B6E931DE315481F5F6F5C
-:105D90003A5EB1CC9FA1F5B3D0752CC27FC5EECFD2
-:105DA0006D08BFA4E74322CF3FFEFB6F3914316E6D
-:105DB0004D931DE324BB74B267E3DB4DC74355E34A
-:105DC00063E52267318D9B65E3F18EDEEDF9FA170D
-:105DD000EBD749E7B2FAE2C72283F707F8FFB61913
-:105DE000FFDFED1BFFB3B01DE09F9EDF00FF3762BA
-:105DF000FBBEF02FEDE86AA117AA711F05F8E88F26
-:105E000081EB3287C2F8E5AA9BE460F11695E40FB6
-:105E1000DACFCCC98CE991C5931AF6E17C173FAA79
-:105E200010BF568873A69F89BCFEF87CA885B3C3B3
-:105E3000B4BFD32B2F2A12E7D7C5E5BBD7C7F87657
-:105E400030CF53E3E7B6542117A58B0A53D01EDA9F
-:105E50006BF7FD0BD9D9AFA96C6302FC6F402633F9
-:105E6000D1755083CD9227CB2A522DFD962D2AA491
-:105E70007DEF251EDF05FDAAC1CBACEB765ED87A9F
-:105E8000CE6848ABF59CD1B0B6FE96F697ADCBB7D1
-:105E9000D48F888CB4D45FBE758CA53CAAFD4A4BC8
-:105EA000FB2B764DB1944747BF6D693FF6C8759699
-:105EB000F2F8CE9B2DED271C9B67A99FD45565A9B1
-:105EC000BFEA932596F23F74FFC46AA7D818E94742
-:105ED00096A490BE3CD8383117F3B1D938A50CF14F
-:105EE000592AF2090FDEA6DB0C2F3E0B6C06E8AD3B
-:105EF000FD0B66D2BA7FF0B6CC808F9EC501F46BE5
-:105F0000983A795CA27CCDA9C6A45C735E54A9D3EF
-:105F10006ED16F530D6B79A743ECFB0DE67CF372EA
-:105F20009C7CD91B2647C13264FD170FCDC2F140BE
-:105F3000CEF60A3DB7F792F45C6643319641CE0E39
-:105F400026923326D6D912C14FF00CE8981F59E695
-:105F5000A1F538802F7DF43EAC81BC4C71FA071E50
-:105F6000C279D9FCE9C88465B38307797F625D662D
-:105F7000C36DDF645D96729E6D13F96B693C7FEDB6
-:105F8000E1050529CC84DF3F386CC28E6EE34FE318
-:105F900088AB276F35DFFCFE9324CD942FA72C9A76
-:105FA00049F922D97DE8453D3B7FC666D0C77A8E48
-:105FB0008F9EF27DCB6C5BC23CB06EA147A5BD3518
-:105FC00022666F75233D4E67BFF920E629D5CDE9DE
-:105FD000267B2BDBD676DB619CD7EBAA885FFAF8B1
-:105FE000F92A61272F9871DF6D87715FFA9F87917A
-:105FF0007E92E3AC6F9C3E43339D231FD887DF74B2
-:10600000B993C3F358E3F0191594B76DF0F3A2A256
-:10601000FFDC706D39DACD8345BEE983B6C4F92E55
-:106020006ED14F16921CE135DC2427A717BEE7D5A9
-:10603000601E8FC0EAE5C47DDB2B3A8BB91D16F0DC
-:10604000E339D4DCE82D0F62FBDC6C8DF25DE3C735
-:10605000CF9A136ACDC3F8679ACDEFA672B782EDD7
-:106060001D3F65AC1FB46FFE0F95E069DE3F89F2FE
-:106070003F1CEE0686FBA9725E07D21E21FCA81DFE
-:10608000C9B40E32B12F2EE3AD5F645774A2BDF1D7
-:10609000C5FD761AEF0B98A301FD7FD1A1D2BEEB0F
-:1060A000E1B4A4A80DCA6AAB87D6EF5CB43DA1FDEC
-:1060B000C20E4FC49717C38BB66E329D87710CE426
-:1060C000F36F4E7347DC7934EF749CB78453CE7B07
-:1060D000501F7E6689803BE7B29E731A0CF95835D3
-:1060E00034EA77412A3F8719699C28E8659D4F4B20
-:1060F000F675D7DE84E787DE5219A686F8BADA6825
-:10610000FE0B61FE115F6FFC9EF6E57D695309CEC3
-:106110001284535D574EF3A076F05DEDE30A7B24C5
-:106120000FF930349DE8DADF46E7027BD9074E2EBF
-:106130005F339C3C2F57CF2E98B1B91F3E87925C9E
-:106140007CC7D9E7BA1F74727D44CF6F70BF00ADB2
-:10615000FF521FA9019BB073B95EEAB19FF4D00F43
-:106160009C19B1B29AF2D322ECB76FFB6CFB3E1DC7
-:10617000ED333723FB59EACDBEEC33B4CB90DFA42B
-:106180005DB6386E9E30BF1A31BF9A44F3EBA56FEF
-:106190006F6E9076CD12E705ECCA0C3DB13E7A5297
-:1061A000D0A1DED019C59B688D02BDB3D846E78D5E
-:1061B00099167199CF97AF774ABB6EF73E1DF10CD8
-:1061C000F3463C6783FF5C4E7AC79E302FFC62FE2D
-:1061D00048FEEAC21D47B03FB07311FA736DBE941A
-:1061E000B40BD817F665AFBBCC78BDCF29F2B96335
-:1061F000787C40E0F18184784C073CDA2CF6E1CEE3
-:10620000021FE1F117CE0BD887A7BFF77E31AE474B
-:106210006704BEEA7AFC5CAE9FFBC32285F1AA5AF2
-:10622000CC5F76F232EE07E15E0CC6E18A6CC127E4
-:10623000B0FFFA5DD673873F73F2381973F373B307
-:10624000B2BF4CA1EFC1AFFED61F7DA4F7FF11E78F
-:1062500013F3AFBB8AD1BF5AF1C26529689795ED98
-:10626000BCC9C0E7B9F4A1B49E9DDEE908209CA793
-:10627000D378BEDEE99D130E63FCE1B3C623F96655
-:106280007D7FFAD9A3C576E8E7F48EA3C51AE507A2
-:10629000472C7661EDD7BF29C6735832AFBA875FF6
-:1062A0009C7C9DB8DFC5E31A19997A0BE68B9F4F4A
-:1062B0004A257C3D9069BB3751BC06D527EDDB7B79
-:1062C00074DAA75C32C2B7C28DF19A3C83F2705780
-:1062D00028819C05B8CF32CBE9C77D80F47C363C61
-:1062E0002F055118626EC0A7E3601B1D374DEA34BD
-:1062F000F6A17924E3385A29D7B7DDD7EB9437963E
-:10630000ACF91E9A03E5ECD91AAD7732AEE348E654
-:10631000E792655CA7079ED7ECB40E2DC90BB59527
-:10632000C0774B26A5D177DE59EF10BF9CF5D9C2B7
-:10633000769C8FD64DF19D9F370ECF180A78347218
-:106340006C33C8A6F90B60CB94FFEFD5583805EC39
-:106350009BD5C0FF4381FF3B1A9DD4BE05EC432370
-:106360008DEE4988DDF361929B1D8D06B5FB65635B
-:10637000367D775FA38F9E3D7604E3DF5139817EC2
-:10638000FDCF7ADED3C8EF1391E57F1B07761AD0D5
-:106390003B7D025015F0922ECE9FCBFA471A5F1B21
-:1063A0005236542003F0D9BFC6D8B0EA02F0A63B5B
-:1063B00022A978C4F872170B974DC43CBFEE7BCB73
-:1063C00053F17CC45D656523008FB8BF7D2590CAFD
-:1063D000755F339E4FCDA9F13561DC2F6797D28E63
-:1063E000EB57CEAEB525B88F00EDE8DCA0EC37C397
-:1063F000C5F55CF2818795FC51B8B9C0F7E5D99E27
-:10640000E448A2F3A5E35C5CCFF95D7C7F70B5D86E
-:1064100057EF9EE526BD987CC045FC92B3FB72DA2F
-:10642000DF73F7B1AF1CDF4FF2813F531CD8ADB41F
-:10643000EDC37D4AB680DB9F929FFAFA0EDBEB97A5
-:10644000D0FEAC5FA3B83098BD34BFD3B30612BE44
-:10645000B1BD598F9FD513DB650181A795F6C47136
-:106460007A8DF171C67576D37E26DEDB84F8CE791F
-:10647000AB4D417FFDB4C2F331FA033E764039673C
-:10648000721BDDEBF49C3354EE82EFFE641C2B5840
-:1064900009E0B80A7F9F8BDF497CA845BA13F5490C
-:1064A000CEEE0FF8391F5B978EF96F8BEE7E9EE272
-:1064B0008FAA1ECCE3E5952B313E99E10D6E403E4F
-:1064C00061E1E7CB0E029F3C20CE2DE31BD47BABDA
-:1064D0005DA21C6E6F0E009FACB6F3F2A2BB9F23B1
-:1064E000BE596D0F2EC673CF586E86FE57A7B6677E
-:1064F000DBA0EC6E7AA6F9C8202CCBF6CF34872728
-:10650000831DEA92FA39988378EF291B501E652A79
-:106510006BBCCC9CFC29E7577BE0CF870700BFD43E
-:10652000EDE6F7DCF4E06DD75A05D7A35F361EF130
-:10653000356B424EA4FE8075FEB26C467E8A1E51BB
-:1065400022F90ADEF7D19A69CE57F941B222E21652
-:10655000F0BD39FE1877AE8D8ECAE0FADCCCF3427E
-:10656000E2E9FA7652495B52069E470DAD52510F51
-:106570003E633728AFBE4B23BD7D4AE6D537D8C929
-:106580001EAC11E75CEDCB43AB46A05CDCA2F9315D
-:10659000BE509DD75682F650F58B79FE2616CBD38A
-:1065A000AD4E6DCF1CE38EE5E9CAF20A1197CA4AD7
-:1065B0006D484D2DC4FD98B5B9B85F52C7DA6EFD70
-:1065C00009C2FB86CA90DF3FDD372905EF1DAA858A
-:1065D00032C6C16A3B8EEA2168776512BFEFA6AE6C
-:1065E00003F8C6CDEFA1091430B641339250CFFF66
-:1065F00032D030124DE24DAE5F97B9FE81B127F235
-:106600000306D2F995BB8F353BB1AC1B23D8682C60
-:10661000FF6B33F259F5681BE559B2F0BF1E0C0C45
-:1066200015FBBD506E750D9A6A8E7BE7887386F5F3
-:10663000EBDD741E0CD6E58DC8DF75EB6C61DC3FBD
-:10664000B3393BE91CD02B2E26E8633D3F75BFC212
-:10665000F56178018FA72E9D91F66D3A3FB532DF37
-:10666000085F20AE5B793E89CE49C9F295493EEA82
-:10667000BF520BD33E52E5792F9DAFFAFB8DE7B4A5
-:106680009CD7EA3D9E9BE091E3D5C4C623BA1E1871
-:10669000F3FA8343816E4BB7DB6D0E13DF2DDD2ED6
-:1066A000F6E75D812CEC2743E77866E80F02AFD16F
-:1066B0001D37BC1CD6B241FF4BF90E9F6B2E9B8C35
-:1066C000748BD533ABFC07D01FBF274996FFBDB9EC
-:1066D0006C6082F64971EDF365FFEA4AEC3F1E9E5D
-:1066E0008CA458D909EDB5BF3A7ACA08DF5A5B5C69
-:1066F0007F69B2EC5E89E34BBE6ABD3BFD5018F882
-:10670000EA9ED4B612D4FFDD0B980FEFD1427EF58E
-:106710009BF46DAB8BCB75E5F97C0BBD63782FB02B
-:10672000D0E5E3C66CCBBEE7A2394B697FB6D52571
-:10673000E8C5C2FC9CCDFA012C628A07FD7F38FEB9
-:106740005638AEEC038E6FFD17C3E1B38C1783632D
-:10675000A805BEBF158E8D37147C3B0F9A3CA084D4
-:106760009DF9B82EFC8CE7C5A9A965BE26DC97F972
-:10677000994671FD618CE7BBE46BEC883606E5A7B2
-:106780002D807110B69CDB2BF0BED53E86D621F253
-:106790001786EC76CCC5BC8DFCCAC0627CB2818504
-:1067A000B4EF23F749998813CA7D9E61062BC17BFC
-:1067B000FF8E27CDA5752A3F38A71AE3EAAA675CA2
-:1067C00012AE870FD822611C2F7C1F1F2FC31669A2
-:1067D00077A2BDE41D6AE07A97E1E5FA8FAD2AA4BD
-:1067E000F56FA32D7FE46D00C74AA524E935C47376
-:1067F0006A3EC5C7F13DDEB3B351AC5B6AAADFC0E8
-:10680000756AA358B75608FD2EDF27A705E7A21D16
-:10681000F1F355D3A63A27A11E0AB4F683F5E6DEB6
-:1068200055D356664FC2F5C697EF84F5E5DEA469E9
-:106830002B9D30998D4DBEFE466AAC3CECAFB05AF4
-:10684000939E98B632007AA7D9BDA40AED1CA83F42
-:10685000847EE2136952EFF0FA7CA9A7502F811EC3
-:10686000539B7ACA61D44BF93D7A671AE99DCD8F63
-:10687000A9545E0AE3A11D03F308E3FD60DDC33400
-:10688000F28F5C004B12945D23F269FF0CE6CD920F
-:10689000D0FF1FC1EBE57E873ECC46FB1DD81EF125
-:1068A000E8CAE1EDF559FCBCB4EE7193DF26F74F71
-:1068B00054B17F9724F254146316F9C1CE35639610
-:1068C000A01FE51C6ADD9FD6E3F259D4F8FC1677C9
-:1068D00094ECAEB62411BFEEC7B2E9DE04F11E2C73
-:1068E000E531F8CCBCA9B984EED3F33003F3A9B3F6
-:1068F000435166B697E4D301EBA8CF24370E370B8C
-:1069000024CAA75898CCED61F7798DFB890AD8374E
-:10691000B88E7A841D2EEC23BBBCE7286EDD95F67D
-:10692000925DDCA7B774C6942C3C97A4BA034EB40E
-:1069300073F61963689F4665FE6B4B4CF64E737495
-:1069400006C5273523C0D0CE795DD839AAE1676660
-:106950003BA7A5111C7058AB361517D0FD358FB865
-:10696000A2CE2148DF076C7ED41B07C65485158C48
-:106970004F2E6324A79B8A33A7E03EC3062D98724F
-:106980000BCACB5B309E8FD38DEF73AF50309EFE22
-:1069900085339882FAE09E5466F1A3AE4DE6FEC8B8
-:1069A0009624AE7FA49FD002F044010EEDFC48BABD
-:1069B000CF67B4B04BF53965142FC334208C7F3AC0
-:1069C0005803E587CAFBEA1CD9364BFEA376BE887E
-:1069D000E2895B92F83872DCBBC47D83B2EC640D53
-:1069E0003C6E0C3C9EC87FAB15703AC01EF2917D88
-:1069F00012B7FFDFDB3E227B45D2A7C74E51F8B965
-:106A0000D0BEECA3FAF3368B9E8D9D67D7492F9F9E
-:106A100011F705C83C10B7D0672DD9A1B6ABF2620B
-:106A2000F70368221F648DB81780656BDDE673F885
-:106A3000C9188F81FA669117921C77AEDFE55E4A1E
-:106A4000FE826BB8663907E66421FACEE1B3BED7A1
-:106A5000B2E3EF0B08F7E48151DEA2C61E56E872DE
-:106A6000006EEF0E107958A793DFA77823D8BB07E5
-:106A70009CB42FC1CF89CA78D837B58F5F47BB8AFE
-:106A8000FCC2E9A3B1DF45B81E613C9B0573F8A6C3
-:106A9000633BA3BCA1247F17E3778E91BDA54A3D3C
-:106AA000177EBE19FDA80CB37D67B2D72E5FFD7CA3
-:106AB000737321F91D545E74771BE9C1952E595EDD
-:106AC0004D6558AFA2E8F7B09D0E1FF2137C1F4032
-:106AD000B961371490BDACE6834B0B7097E1FD872D
-:106AE000B83FB0D3B111ED59F06BE7B94C71B2D3E7
-:106AF0009E63B9AC30617F614B7FB9DFAC3F18BF9B
-:106B000003F38C647D99775D54E5DFF9F03B36B093
-:106B1000F3FD30F4FFC00B0EBA9744DEB31CCFAFC9
-:106B20005392B9FF8E7AC39CCFA9CFA90820734A8C
-:106B3000F974642759F2BFA5BC6AE787937CCAEF52
-:106B40005E4FE2FBC79A16A0B89A76BE90E47F8BA0
-:106B5000A06B4BA3719171D2FA18670CF5D3F7387B
-:106B6000C5424F30B13FA619E67B64FA92D7F8FDD3
-:106B7000C078FD269F52BFED15FDCF4DB6C697AB31
-:106B8000D6B51F4616FA892D54913C1EF3BEDEF38E
-:106B9000E2525C638B16A1BCDDDEFB7D1D4EEE4731
-:106BA000224E50B0F5B6FDC8AE0DC9A1F54950AEA4
-:106BB0004A16FB00D9B0AEA9B86EF1BCA587B11ECC
-:106BC000F31B42BE87A6A29E9A554EF1EBE7928335
-:106BD000BFC1EFEEBEAE98620512EED58D3CDF4E22
-:106BE000EA4B37E20BDA3BB4061EF77407A2685F84
-:106BF000DC97FCF6540DF950E372B06CF5FE951875
-:106C000017716A7EE22BA7DBE6C3F5DD09FE1DAE38
-:106C10007B4D6E1BC59356E03DC0F0BE599969A0EF
-:106C2000BC2EF1E467B10BE847ED7CA6D0BFD67B64
-:106C300075FEFEE3A4D3F7BDEEEF3930298AFD6976
-:106C40007E46F93388840F4D7A55AEEBF1DFC5F7F8
-:106C50002FF129F1EBD04284571DED8604703D9948
-:106C60006CDDB7CD92FA33F59D8228BCAD55BABC28
-:106C7000689F805E7C12F9A46E54F7AF151FE9D3AC
-:106C80004C6ECF84E57D0596FB91645C5E7573BBAD
-:106C900046C2BFE4B5079CE67DA77878E3D74B777B
-:106CA000A1353FC3393029EEBEE0263E8E1624BE04
-:106CB000B14F0E38514E9A8C3106DA2BCD9AEFB780
-:106CC00001CA2BB193DD0C76B8657CF9BC47DC0FAB
-:106CD0007C54D851F1F51E719F72FCFBCF85FD707D
-:106CE000CFBE9B480FF7453F3C508DF4F5E433038E
-:106CF000CFE7D805BCDE8BF4DB171FDDBB8FC77574
-:106D0000B589CE08BA58F1E3A9F66000CF93A9A3DC
-:106D100019D9BBEA203E3ED0D2C0B8B0775C1A1B6E
-:106D20006E5A67EF1E7A1DBFDF39C3A0F37DAAC775
-:106D3000164C64674A3C1D4C96F75470BEC9967C4D
-:106D400033ECF7740FBA896FBA13F1CDC164AEAFEB
-:106D5000100E333DEF1E9A9F95883E31BDC8F9EA6B
-:106D6000627CD121EE4BAC45DC807F5323CEDB9F90
-:106D700012F704CD4B16F70519DC2E96F75F7468F1
-:106D80008164B4ABE6F5EC5307E85C4A8D2B903296
-:106D900009F9F228B77B3F2EE1F7967D6C0FA4200E
-:106DA0009E3F3EAA2A4DB4CFCFF302659ED5C7764B
-:106DB000DFEA91503FFF176AA089AAADF6DC2916D9
-:106DC00018FBCF68DFEE5269FF28EFBEB9EA2868EA
-:106DD0005F01861EF2D1BC527718D7DF8EDF37BC39
-:106DE0008F7A68FE630EDF7218E7E0BAB15F62F96E
-:106DF000C41A8FCF4171B27C05EF155FBA36CFA0B0
-:106E0000FDA3654CD81943CB4B8732F614FE53C60D
-:106E10009D9D74CFB8A80FB694C1FC466674D8DCAB
-:106E20000053C41D6CC1734E2B9B82D9E8FF5DBB20
-:106E3000A6A005E38F999981CEAB411FAF5833BC13
-:106E40001CFDC18E47447FE1112DE8EFBD6C0BE5C1
-:106E50002950FFD49A29E594973B44F67F03D5CF78
-:106E60007BFCB22F8F1988D3CA728C9915CF91F001
-:106E7000D49697826E5F30599697E8584E4F669633
-:106E800038983DE64F529CADA3C77FBCA31CE3607E
-:106E9000F3A734946AD07F9EE7A72D85201A13DAD2
-:106EA0004A8C005E99EBB9AF3C39036FCD0B54E3CC
-:106EB0007A32D2737F39CE27BD9FB5FF7455C45344
-:106EC000D9BA16ECAF07BEF0D6168CAFCAF66FDE95
-:106ED000F34E4B78608CEFBF1BBB5FE93BEE0CBA07
-:106EE000B7EE3086D8729775EB3C9F57E4DF0CEC19
-:106EF0002AE27945A23CBC8BE75DCB72362F772C1A
-:106F00004FBCCEFFDCCBE5AD232971FDCFDC5C5F50
-:106F100000DCA4E7538EB1C0B6047254E17653BBD3
-:106F20004360E739D362F274AD83B18998DFE4E45A
-:106F300070CA7EE2BFBF538CC3C2D7A6211FCF1435
-:106F40007C3EC4AFF03CA55DC911FC3D06F0B2B477
-:106F5000EFC17CB68A78C45617FBE12C183A338906
-:106F600085F0DE9C8C7E502EA4EF03DBDDB1FEDECF
-:106F7000E022CCA60E096EC6FEA666E58C5E9117D1
-:106F8000EB07E06E768EB1C0AD4D4CC3FA707F8CCE
-:106F900093F4E0B390CF03F884F005C33C8DBF1F9A
-:106FA000D0D139321FF5EF484CBA31E9F9E2CEEBD6
-:106FB000E83CCD52AFD81FF1F1EF334A79DE4BF701
-:106FC0008BC9FCFE4C676781793FEB21B7C833B8AA
-:106FD0006BE643740EBAD3CEE8FCC2F6920BE61D04
-:106FE000D6605CCE6437D66851F2C76A302E371649
-:106FF000FB7B83CE1F623F3E117FC6B85AC68AC450
-:10700000F497EB60CD798385FBF5D697B1FED35924
-:1070100078ECC5E715EBCFEA37F6EE4F17717C81B8
-:10702000774DE05D4F0CE75EC9A7806F9B89BF1667
-:10703000087E93FB8167768ED868DE7F95E7864071
-:107040003F3F8DBF8F10EE4C227FA5580B5C83ED28
-:107050008B3BD3687F40F287E40B49D78EB4068A16
-:10706000B7743FACD039AE78B80E49B8D6F17BFBD7
-:10707000B2E68454F33DE3521EA0FF0ED1FFB8895F
-:10708000243F8F727900B9B905E517EF61C179F82E
-:10709000BB8ACCBF4720E12F425E1C4F74E4F87FCF
-:1070A000C125F25738DE7AE3BFFF45E8994BF42C4F
-:1070B000EEDC4FF3ACE9436EABBC5E9EC7762CEAC8
-:1070C000F541BB3182FF3BDA3FA47BC53A76A94C40
-:1070D000F1F179A3DE2AEED1C7E35F9D02FA38AB66
-:1070E000A70CFAD28774E8D19F51A733D6FE07DEEA
-:1070F000F1D39A515F8A7B7BD355586DC6C4E0F8B3
-:10710000939BDB57134389E3580D5E8F458F3DBC3E
-:107110006C0AFB10E67FA59BE75F4DEC0AD3EFEA14
-:1071200048B98ED753FD3C9C8E86E7FF929E725DD8
-:10713000444FB9A49EE2EF0FA1CD3B06D7D7AE22B4
-:1071400005ECE60A5B2013FDAF8F8EFE84CEA72CE4
-:1071500012F939A3303F07D7CD63415A573EC54A8C
-:107160009EA733D09381F9DAD63C1DB6999F6B8DDB
-:10717000E7AB181F8585FD26E010EBC1B58EAE6725
-:10718000793CC32ACFB20C70D6D98698EADD7CDD73
-:107190009274007A37D33DC7428E8FEFCCDA80FAF3
-:1071A000F64D0FCFB3491F12188DF3977209EBAA52
-:1071B000E013DB0FAF7373BD715D02FE9DECE17AEE
-:1071C00076C13ACE371DFFBBF41AC47BC79B69A9B1
-:1071D000CB4D7AA24CC8B1EC57EA21F99DAC9F2265
-:1071E000FA9BE6E17251E6E67C877024CA272833D1
-:1071F000ADAFC43FAD9C7F60BE61337FBF29FA8DC8
-:10720000E153ACAB02CFB53AE017F0B7D51EEE8F25
-:10721000F949C59D36EAAF629787F2322BDA391EFB
-:107220002BDAF6D9AA4DF889EF6FA987CBD1067171
-:107230000FED211BF01BE2DDCDE13BB33387F4E71B
-:10724000220FB71B2EBE6E5C9A9ED920F23180BEF3
-:1072500094BF58FBD2800D563DCDFB4BEF175A81A2
-:10726000E7F0D21F627ECC29033C451580FB4B8F93
-:10727000D03B7A40C7F3B6DD0F33DA8F1F362730A5
-:10728000DA07E5FAA07B8C02FD15B4713D5C7C3F0A
-:10729000D83128774EB92EBCB6CD3CDE9D1E8FE589
-:1072A0001C61C53A8EBF6160FF3C8D4FE8E759B263
-:1072B000E3393CC71F6CBF0AE34EF2FB5641FF8B1C
-:1072C000C1578CF08D8BC187FD53FE8A3BB81CFBE8
-:1072D000ADFBCD8E01E67E1FE8E977DE1417EAF9F3
-:1072E000B5B0EE9074860EE0B98B8ADDA906DE9308
-:1072F00000F26C437F478E5BA1C9DFCBE92AC67BD6
-:10730000C20B7AC69174FDDD33E6F96FF2B8FFAEB9
-:10731000F4EDD043349FEEED00AF2F86978EF6B993
-:10732000CB5DB84E1C637E5C2724BCC3E674793108
-:107330005FA45EAC1F305F1BFA2FE9BFF0B1158868
-:10734000B7CE29744F423C5F4B3A0D675C7EA49FD9
-:10735000361C03FC50DEED2912FA87919F7BFCA5B9
-:107360003D4FF37B2D385DEAE7703A7679425F7ADC
-:1073700032627208FA9CEE2FAEB8BF471FB5F3F722
-:107380009DB973009FBFF64839B7D2253DD8EEA20C
-:107390004B66055F9F7E71546415A7338DDFD1EE78
-:1073A00089280A9EA36D68427F5BEA0984C79CAF67
-:1073B00024E1E9A123033A8E8ABD1F3687F7570FD0
-:1073C000F28E7C54A33628390AE9018AAF66A11EE1
-:1073D0008072563B6FC776F3FB1B249E6A6E844E09
-:1073E000C1EFFC574F21CD43E22B6B4ED45653884F
-:1073F000F9CAFB077F64A2F311B15F8078B98EFCF4
-:107400000DAEAF6BD4E040F45B599683CEA1C23A87
-:1074100044FAE5908B692EE8EF5578E2BA3455BD11
-:107420008DCE094D1DA2901C830690F11EFA3DAE33
-:107430006BAF4EE6795B7FF9D1509C674632E743EC
-:10744000E8C729FA71D23A28D6837FC905BB4E898D
-:10745000E9E5438A42FD1CFA87CB37AE50627C894E
-:10746000FDA1FD7448993590D6CB8E0C911CD46546
-:10747000C927EBBD9E75E562BDD95F44FF2EE66F5F
-:107480002A774D039E9A30BD3D8A574E3785D56980
-:10749000FF08E34E057FD385FAD3CBF9FA505E5847
-:1074A000F5225CC314BA5FF97052A890DFD3CBC742
-:1074B000C914719B4C91AF8CF6023E235EAEFF4720
-:1074C000A6F0E78FC533D39B38CEB356D4D78B7B8A
-:1074D000AD579524CE671BE8552CF1966BC5BE05BC
-:1074E000DEFFEBE57EA7C8B3E5FB1C60DF137E4B38
-:1074F000EF9A43FB765F745E9FC2EF6FE0FAE04362
-:1075000025F0EB1B157C06E9FEBCF0DB2AE5BF7F0E
-:107510006404BC98DF549B94380FBB44CCAF56CC6A
-:10752000FFE3467EDFC27CDC4F03FD31D6CBE7B103
-:10753000A86D6C39D27BD11A85F6D3E4BEBDA46F99
-:10754000E57AD5124F9F8FFB69FDFE163FCADF8794
-:107550001F35CEE247C971E3FDA9E38DD996B8FF87
-:10756000BCB621E29E0BDE7E3EF313DCF35B0758D4
-:10757000F6FF586BC6A5DD030AFE5338217C3AE9B5
-:107580005BF9FE78A39385CD707C3294F21E067A67
-:107590004337217D637024B3B0190E3699FFEE9501
-:1075A0008BC75DC10EE7FE0B3C37B8C94EA77B6A9F
-:1075B0007BE260A03F8C14D4472573BDE3637E83D8
-:1075C00094AF9AC989FD8771C2CF1DE7E6FE71CAE3
-:1075D00031E94F27F9502F4A7B3CFEBB861EBEB5D2
-:1075E000DA93178B3F00FF86CDFE517CBF2DA2DFC3
-:1075F0006FCE2FF97DF04BC17F89DF5D3C3944F1BF
-:107600003DD6A6502ECA8432AB1FF48897AFE78FC1
-:107610007893E97B695757CCB1B67B0CDB8DC76794
-:10762000F225C573CCF6BB3204F51FEF4FFEEE4ECC
-:10763000DEC93729FFF377E827427F6FA404B6201D
-:107640007FAC11F9F21BFE7A207B3EDA43FF6CA778
-:10765000FDFA924797AEC07C6677BB62D0F9A35D16
-:107660005679F8CEB2F6C115808F7641A71A3F9FA2
-:10767000478D3FAA0F75637E351F7F60FB3E453304
-:10768000F1DBC04ADEEE25AFDD129FD98B65E867DE
-:10769000B7D7907ECBBE19E9D83EA0A11DD01F7FE1
-:1076A000EF06E0E9DFC0C88EEE3F4EA1FEBF336EAD
-:1076B0008382BFBF25E7D96A9B5568C077AD99C95A
-:1076C0007E5C6F328DD0419C67CD7BD1282E8F138D
-:1076D000DEEBD4D0BF1A6E040EA1DCC979F954A335
-:1076E0003FDAEDC9EF71F8DA7AE24A7CBD616CB538
-:1076F000B04337727B4C654718B7C7695DCF5C3EB6
-:107700009CD63D399FCC34B16E64B210E61F43FB6A
-:1077100056B2539C7CDDCF5CCE7F2F4FD233E667D1
-:107720008E18837EE69035516D1E7CF7D27A5BC24F
-:10773000FB353E14788779BC6F9EC7C5F4956C679E
-:10774000EF23CE28F93D797A62FF9DB17BA9BEE493
-:10775000D1F49B492E9B75BA0F51E27FB811FC1CE6
-:10776000E1E9DFBE4141DC1C177905C7573DADA0FB
-:107770001DF9A3C5CC5013F0538FBC2EDB31B8C21A
-:10778000A437A17FA2C786B83C71196F71A570FF9D
-:10779000E71623C852C653DE2EF9CF8B37F3DFDD51
-:1077A000E8131F97882FA592DBE535B3F9EF8E9686
-:1077B0003CAA11BDAB9BF9EF0ED66CDB4EE7ECD8C3
-:1077C0004F991FE5BDA67DBB5201E3566FDBAE2C82
-:1077D00030E16F404D84F2AB2FF3C87D8728D9CDBF
-:1077E000F17C8DF102B4530EBBB8BC9F2A71877136
-:1077F0001FE2943D5483ED4EE524FB719F52E2FB62
-:10780000D5EDD3E8BE03CF0E47149FADB68DD94E4C
-:1078100068D73A52F7231F0D3742C3102F695AB069
-:1078200003BF4F4DF7F8711FC3E7606368BDBE44E7
-:107830003C4C88E387093FE57272638A57C805A309
-:10784000BCA7AB533CD27E22FD74D8CEE7B1837186
-:107850007823DEC0B814E4C323FC7713FAD74415A9
-:10786000CC17891F37C64F812B11FE4B87B35D475D
-:10787000BD5E2DF44CC9A39B950F4D70CF40A30A5C
-:10788000F973DB0605E364504F7A06DA33CC4BEA32
-:10789000BF8DFBA5D550BFC0A457E43C12E897208C
-:1078A000C2E77EAFF320D72F51BE2F20E08DA7E790
-:1078B0009C141F8D5F0EE601BDD7C3C3D12F3E9C24
-:1078C0009F44FD49798F97CF3982CFFBAFDFACD88A
-:1078D000DCB47F4276A4844FB67B23654A08E199E5
-:1078E00030BD93F050BB5EA3F94CD583436F33C9D1
-:1078F000435D0AB7E3F6DFF83EDDFF73FFAF8E129C
-:107900003FD6823F4DFE44DB51FD7A5C57C24FAA01
-:10791000B8DF750D3749D883E25EAC6B3AB8FEAD7F
-:10792000EDD8AEE13D92924FF34EEEA7FBB46ADB89
-:107930001D0CFD28E0BFA548EF783EBD547A821E9D
-:10794000E27E525817F1BC501EFA39523F47843D2F
-:10795000CADCFCFDBD024F31FE09B5A458F4AB8B67
-:10796000E422EFE498FD989759EB57E8BCA48427EC
-:10797000BD34B17D2EF5A2D4D718370C9AF4FA5A3B
-:10798000A4EB782A47B93FCAF2715D9670C6D3E975
-:10799000E514AEBF13F0D3232909D62BB97EE73DFA
-:1079A000B643C37B91249F5C83F435F1C99329FCD2
-:1079B0007EDD275334EAFFC112BEBFF8A09DAF534E
-:1079C0000F3639295FF2D59B78FE96E7663D8ACF60
-:1079D00043B67935587FA83F87A3D5B69CCED781CB
-:1079E000FC3D95427CE2655C0F72BD77FFF35C6FF6
-:1079F000D584DDE4CFD684BE5F4179ADE92E3FDD8D
-:107A0000F7193AA85FEF89E1359E8F7C3BF6D1EFFD
-:107A10001D5FD3CEE50DF426F1510C7F1CCF524EE5
-:107A2000A43C44E4FE0DF001B77BB8BF5428CE3B24
-:107A3000563AFD745EB252C4550BC5B9C7E2630134
-:107A40005A0FE6093A14D982AFE2BC2AD6C4C5550A
-:107A50002FD1EEAF5EF6FA08FC5DB0AAEC23F494E9
-:107A6000F2087EA9456EDF11FEDF1E41EF3F08F9E7
-:107A7000AF1ED74EF256FD5103C9A97B3AD757EE38
-:107A8000F7AC7A96B17BC47CD7D0775393DBCB71BC
-:107A90005F78EAE30ADDABD9179C8BF01C18FA6F0C
-:107AA000EB0F78E7A23C8BDF8792E765CE08393988
-:107AB000B55515BF97D9A05FC8AEBE587F2CFA96B2
-:107AC00042F795089FEFD4B6D2497F44BF736B0A43
-:107AD000FD7EC967DBBEF7E33FA6E3EF835CEDC73E
-:107AE000F53F7D4590F8A53BC3E5DFC8E3ACD33156
-:107AF0000ED5D47EC08BE76B3E7DFA8A31A88FF11C
-:107B0000DE2D9CFFC9E7D5658897E54F3CF72DAC86
-:107B1000AF8E28FDD02E3DB5F5F1FFC0DF81AADC88
-:107B20005C4FBFF3BCE2E957C8BEFF3F75A9C786EB
-:107B300000800000000000001F8B08000000000013
-:107B4000000BD57D0B7854459A689D3EFD24DDA140
-:107B50003BE93CC9A393404025A1131208F2EA2453
-:107B600084872076408620AFE61D20241198591C7A
-:107B7000DD9B8620221767E2EA28F8DA0E838A3333
-:107B8000CE18306A90A0CD43C4195D5B040767919D
-:107B90006DD4419090F446671677B8C3ADFFAFAA95
-:107BA000749F930EA83BCE776FFCFC8A3A754E3DCE
-:107BB000FE77FDFF5FD51A5FF3DF52ED8454EFE9E6
-:107BC0006F3510422EFEF2E1716428218D2D8DFA61
-:107BD000A099902F7FD98CF5C3CFBFF4C67FD3F780
-:107BE0006ADCB14E78EFCB970FE9E1798D47EB6A0C
-:107BF000A125F11CD5CFB2D0D2FB824C1209994AF3
-:107C0000D8DF637B0FE91D79B4DE221142BF27550F
-:107C10007ADFA02CFA5DCB5EED1233BCE123A49891
-:107C20008EFBFCC2511EA8B7251092127EBE554F86
-:107C3000BCC6385AF623C444CB4BA566AFD49F903C
-:107C4000D565E6AD505EFA8DA9CA47BFABD50773BF
-:107C50006D309FA1C405F578AB86900418E76E5D82
-:107C6000AD19BFC77E3ED21102651EF192F34308E3
-:107C7000A16FEDBE361CC6FB2DBE4FDF2B3115129A
-:107C8000327BDE3909E61333B45EB71AE7F96BD6F7
-:107C90004E571DD93E623D1D8F8E7B0DFEC687CB94
-:107CA0003CAB19DFA700C132B5B532CD01EBB71B34
-:107CB0009CB07EB1BED46A4FA3853EBF6DBDC729BF
-:107CC0003B0879FDC289890368FDF921D270195EEC
-:107CD00097A5856EDA7FADD78CE3ACD950463EA32D
-:107CE000F31D6F95F0FB442BB1DF4AD753A12576E6
-:107CF0003394849CD41542FFCF62BBC3405CA488FC
-:107D0000966FCE7E7623FDE4319D27A518FAD91A09
-:107D1000D03BA0DCCDE64FBFB79A0BB13FEBADF047
-:107D2000BD91AC85EFBA364EB36F93B0DF802E2E87
-:107D30003C6F424219B3F2587F4500A7C9DE2A784A
-:107D40009F38F4B8BE2FE115C4A3377F7E1E940F71
-:107D5000B1F96A8807E825514F4B84AB27AB92D223
-:107D6000CD7C6B6995B5385C26F663ED6AB83E0547
-:107D7000ED149E67AC2E2CC99E784246F57E4F943A
-:107D800002FE876777EA8374DC470F9C43BAAD0530
-:107D9000BA85F13D9FEB611D826E9708BADD7F0EBB
-:107DA000E976499B84F454DB56A0077ABDD4E022DF
-:107DB0009F69699DD3DF63527039D0B577BFC9FA27
-:107DC0002C8553A7A0CFEDE7CECB141ED96D290E7D
-:107DD000099EEF6774FA9646E30538BDB5EB96E663
-:107DE0004629729E1B113E5235413EA9AD273E03E6
-:107DF0006D2F7D7AFD8929B4BEA69A380D943E6A0E
-:107E0000557494F5CCA75B805E6C35A4C8E480758E
-:107E10009E9D3880F65F5B438A814F5327B8F643B7
-:107E20009DB4496410D4ABDD4B61FCDBEC2B9D327F
-:107E3000EDDF36C1DD0AE3DD661FEB94697F8FA5B8
-:107E4000B76C31D2766F05B13EEB00FC36956969AF
-:107E5000FDB10A87954292C26D7732B493217AE7D9
-:107E6000B340C79EA535D05F6DF25C27D0492FFE89
-:107E7000DFBF7108CCB7D6D1CF69A2EF4F6D939019
-:107E8000AE88D74C60FEB514BE509FEA1BED83F957
-:107E90005CE6F01370ECD40516C0FC3A5F31102F8D
-:107EA0006D9F3A81D1AB6D420BCA8FB7F74F3A2E17
-:107EB000E587E9D2F2AAC10FF538AD5572825C228E
-:107EC000330D91786DD291856EFA9D6D32EB2767F7
-:107ED0003BC3EF739C9F9E03B981A59EF36F13A3D1
-:107EE00077AB37DF4DE9E132C73FFC3968BFABF113
-:107EF0001F143F4BFDC84F352FB2FEEC0657C1BAD9
-:107F000008FAB59713E4E33D26B2B0923EDF63630F
-:107F1000A59A5EDFE5F3C87A662DE27D09C53BE0F0
-:107F200035753B7D0E70A3740170A378443AB8CDCB
-:107F3000BE02F1B664BB7417E2D13B82403D219E84
-:107F4000AD53DD7F80CBC53D26779144FB0B255893
-:107F50009CBB24988F4B63827A81CDB98BC0F7EE9E
-:107F6000DD305E4292C9D91821AF08711769E8382F
-:107F700017122D0CDFBEF7B533F2801F1DD86F82AC
-:107F80004CFC04E50FC976E785BFABC861FD55F031
-:107F9000FEA63579F349368307C285C3C3B7B15FFF
-:107FA00055A43CFD08E041FBF5DD44AA406EBCA5AC
-:107FB000276623F46FA5E3D0FE12778DFEE5369C8D
-:107FC0005F23BEF7A6D58A6545BCBBA81E44708E4C
-:107FD0007B3DC045AC530D8FF91C1E87672F28D001
-:107FE000001DDF697602DF3D7A405A8C74ED355210
-:107FF000A604BA677C48283E802F88478BF8A8AD36
-:1080000077FBA2D37D25F259ADDDE4344948F72E44
-:10801000D47F5EB38FD13DD37F319399BE0239595E
-:1080200099D75B1E083903FA0DE859F045EDB860A1
-:108030002EE0F7DBCA954E1DE3F34E0A07E023C19D
-:108040003796D719BF6CDBE82885F66D94EF23F1DE
-:108050007D4CEF45FE3D96DDCF09FDC23CDD96B07F
-:108060007C4FB4BAFBD9609E1AFF166D56581ED7C6
-:10807000BEFE60AE270AFD09796CD4323967F4C5BB
-:10808000F858BF6C3C2305B7A5104B2FE8A3980DFB
-:108090000C3EEA7ED26D664E8F46EBE7548F4FA7BB
-:1080A00048EA9F43C8648D27DD46FB5F630C1EA32F
-:1080B0009825191B427A984722E82EE09F5D313EB1
-:1080C000905B8989C4B32F4ABFFD6D8CDE045E9A34
-:1080D000E2181F25C6B2F747D918BD0CB5313E2DA1
-:1080E000E3EF8BF90BFA77683CE788DCB71E13DF08
-:1080F000D17961BB980FFD7E2B61FA17E79BB829F8
-:1081000077D7B6087C84F9E8A642C053CE76BF760E
-:10811000B1393C8ED0A76AFCC3FC817F603D95439A
-:10812000FB7EAFE910E347353D4EE17C62B0112C98
-:108130009B74FE3F235FDD6D21BB607E3B882B9EE1
-:10814000CEABEE8DC18C1F5CA15CE8FF609C6737F5
-:10815000E063E4044EE7F4F90CFA7CB596780D146C
-:1081600027ABF7E87C4123E3996BF4FF62C0139DD2
-:108170004797C5E895299DBF1FE7A982EFBD65C454
-:10818000E907BDF4532A3F80FF88BF18E44B1D095F
-:10819000C6029C6BE5402EA1F8BF1AE3990FF4F8D4
-:1081A000A9269001CF090922BD9E31C5E613DA5FE9
-:1081B000ABDE9FFE4F30EF7764B28BF6D34D5C534E
-:1081C000611DDD014D9C97AEE393B60F7F73807EFA
-:1081D00035FFC0E5F9F70294B6C52C789296F38C7A
-:1081E0001AA37678181E672CD1E5EB8F395D2434FD
-:1081F00032BB2BB4D1E003F8A8DF1B1FC7F05F77B9
-:10820000259578E3239F33395AA70DE9C184ACBB88
-:108210009241BC74DC4F34A4BA258A9DF9A18DE942
-:10822000AB564AFAD1DA4F733ADBA323B93B603E2F
-:10823000CD540E02FCB40E9417D58F6439B7D16AB1
-:108240006B76E818D811A15F4828FFCFE898DCA129
-:108250007F771A4784F5279827601F565BBD7E0DF0
-:10826000951BD5EB2D7E391F9F6BC700EEBC562D9D
-:10827000C8C1C55C2F2EA97FFB1B2996B66B8971DF
-:108280000CFDEE0BF3D258500BCB7FBC2E118CEFB4
-:10829000A4794DC89F844CB0823D2EB9A6C9D7623F
-:1082A000AE67CF69D16E477AA1F82D8F733F09F879
-:1082B0009ED79FC17BDEBA189F3742FEDDC1E1A386
-:1082C000A6B33D40A374BE6725A657D4E3BC1057A0
-:1082D0003609FAFDABC5FD1CF6BFEE32CAB379070D
-:1082E0004C19A0B7565FD1205EBA0A02B91BB28002
-:1082F0009E43197FA0F05BDD6EB07A1DD0AE57E0D3
-:10830000F5D3062AD072C3F5C517064E246680AB96
-:10831000730BE079C9D618E21D129E1F18D240B720
-:10832000B55708F6B3B8FDEDD320A76BB541A48BC4
-:10833000C54633C2BDF68A16E741B6EA3A82E27B09
-:108340003ABFF858573BCCDBFBC018DBF95BE8C3FE
-:1083500024FA1CD7E5390CFCF4784C2C71313EF032
-:108360000DA6F3EF363AFAC75138D4E929DE876112
-:10837000376E6384DD44D22C4ABCB6BFF30DCC67A4
-:10838000A9D1A307782CABAAD703BFCDEBEF2FB6AB
-:108390000E8DC4E718F9DA2DDF1E9FCF73F9F2892D
-:1083A0009ED27B14FE3ACDE5EF782E273E49657CC0
-:1083B000F14906A9DE07E5CDB4A4DF7D92CDEB85BA
-:1083C000ACAEEEE72AE78B4FF2991EF2AE657A412A
-:1083D000FD5E271FAF3CCE751EE0269E0F8F63CF3C
-:1083E0005F88735D043853397799D3A1DF46FB9BCF
-:1083F000F7A601E9906C0EE5021E7BD695CBE79BB4
-:10840000187D5EB670BF5F437FF43D17DAE36F9867
-:108410007CB0BF20D3A8DC0539BB369D809CA5E38A
-:108420005EC5F772E9B8F89E01D741B652F94B190B
-:10843000ADABD88178D9564AE913F8FFA0C10AFC40
-:108440002FE849D0919A7E4C7142AF31FD7A07E80E
-:108450005719F5AB298EE9573DF02FED51CFECBC04
-:1084600081886FA433F9DBE3FBA09170F8BAE3E3F2
-:10847000509FFBF3DC79BDE12CE4DF27FD9474E130
-:10848000E3781CC0DFEB81731C7BCF9EC3F499B0F3
-:10849000FB6FE1EBDACDE5B428857E1A3959696FB7
-:1084A000ECE6F263B72D164B8A97C1B07EA1D77A5E
-:1084B000E1FB29866FFADE5058CF3C4368413CD53A
-:1084C0004B3FA2F68EBE10BF7B1EBEEBE57F98C071
-:1084D000F469DD5A0B017D3F228ED9B1A4289401A5
-:1084E000FD9121B4CC03FEA3F246BA31FE60AF9FEA
-:1084F0004279E4F65807DB57CA7440E09921C40179
-:10850000FD517897C62584E1AD1EEF0C3451FB6E0A
-:108510006A9CA43D0F382A200580AF051F7C659911
-:108520004FBBBC6C357A35543FFC58E3B903FAE9CC
-:10853000B8E71DB4E7CFE8FDB94DE628ED7AFF3383
-:108540008F4BE1F6852FC85E3D9533AD818E5FCCB4
-:10855000A674B938203B61C8C5F7FDF9BD91602705
-:1085600007744ED8AF523B61BB96CEFB8C86E1932D
-:10857000D42BF7FBAB38DEA9BDA42523C2F249E812
-:10858000FB95C43F08EC8225C4A587F2D3BB574CAA
-:1085900023145ECBCCEB516E5D5C3B05EDE0E5C496
-:1085A0008BED4BB6EA3E8DD413CB9A94F5153B94E4
-:1085B000F5953E65FDD24F18BDF5A67B665F259407
-:1085C00047B71B1EE17479491FBDBD318ED169F9D2
-:1085D00003D31E47FE0FE88881D2C9FA83A5492438
-:1085E000CAFBA2ACBB924D7C117A286C57E412DF17
-:1085F00070E8EF2AFAF9A01FD8BFAE37B992609F92
-:1086000071A92CFA3CFE778FDDD2AF8F7E63B1DF8C
-:108610004BD9D75F67DD1523BED7FB7B33F64BED18
-:10862000A7A8DFEFE670B81417BDDDD7D37F32EA15
-:10863000C5F0778C0FC2E3A4A15EADBB6255E8E93B
-:1086400070BB9DE955BEFFA778F5A2BDCBED39AA59
-:1086500010ADE763C2724CD78FCD47F0CD671231B2
-:10866000A6A0BFEC612E479DF960F77E067615F057
-:10867000ED24C71B413AD525F78ECAD56687F94A3E
-:10868000BD1E4A8F5F0623EC82B6388B1DF5B99369
-:1086900038615CC10F0BEEA9E8EFA178FB8FFBCA34
-:1086A000933C4323E9CE8BE3D7EA853D6756E871D7
-:1086B000A2D2F34BDADE417B6DA9D19D0BC2E94F0B
-:1086C00007EF413E594EDC89C01F5D07076778FE02
-:1086D00007FA5DCC67A677918ED9E714A8946F67E7
-:1086E000F0F9CC6C67F6A2C6E8D2E1382EE2B026EB
-:1086F000E2169CCD970A592DAD8FED993F3813099D
-:1087000019C3E72FC1F714BE637949167B9261DE66
-:108710000618978E6722BE64281B47391D508E9716
-:10872000DC5A360F1FE27922A94F83F735C6A0CC59
-:10873000D649679008DFF7C00BEB165EDF7C67F762
-:108740008265F0DC6C41F9A3E7F3F846C84D2331AC
-:10875000C2BA0D66FF4558978597DE32667F7BB3B8
-:1087600089B391BED68FB41018D76CBEEC85C55AAC
-:10877000895582BAC9DAED877DC865ABD9AB198650
-:10878000F2F4FFA03C95DE5D0E78A1F29BF9A5FA0C
-:108790006AD7FA71FF23E4631C9F5F23978F2984B4
-:1087A000C1C14EDC875C94AEFFC5B27C1A89053529
-:1087B000EEC1F177C64E3E0EF305C0A39E9FACFD01
-:1087C0003452CF24B8B50AF99754A5ACA77894755C
-:1087D00023396305FA95FCEEE46BF1B8AF1B027E1A
-:1087E0001A1D973777F663F312F49316AF51D82119
-:1087F0006EBECFAF8DD313F40F261A8D6418DA2511
-:1088000069F1CC2E394B314DF7832194E705E35DB7
-:10881000837E41E1BCE503D9B989E2698BC5B151D9
-:108820000BF6DE1CC9F92C92678B1FFC3ECD0B6C3E
-:10883000CE6DD06E72FDFCFF40FB0732017BAB0EAC
-:10884000FCEDF1F0A2B514BE6BCEB0E27BF6F210F7
-:10885000FA49430F12B4A77AD1E9553A7F0AEF5F7C
-:10886000429DC2B76EA975F58BF4FD14778C538ABF
-:1088700068DF0DED749E12A70B783E7E04EC6BD979
-:108880005F4E7B41C0057E0B978CFAB0AEBDE08891
-:1088900099CE23C753E004B21DD8CEE32A76838F46
-:1088A000C51528D7D279CC32B279D4B597DE514CE0
-:1088B000DB07068613882FC41C77CCAD81260DDD1F
-:1088C0004FC3776531E8CF3AC9FD4A84CB83912AFB
-:1088D0007E1B1DA67F6C2F10756A36B84630770553
-:1088E000D6ED8C0F9C44FC31FEBC9584FFE0FBF27E
-:1088F000707F288F26849BC3FC469756687436D6B3
-:10890000D0F7DEAA9C84745807FB2E8A8F915AFFF9
-:1089100021E0EFD1BC2CE02559DC84F0DCB6D17F1E
-:108920005897052E14B70CF511D6071BA1BFB192AD
-:108930001FCB8CAA871B81AC5E03E30CED4E4F0569
-:10894000F0E3960A6205FBABB1C4E9B4D2A6D955EF
-:10895000CCEF3AABCAE8033FFE2C2D61F12EAD27D8
-:10896000EB4794AF7E348FF97BA13E2FC29F22E26A
-:108970001B27E93E666F147BE0B578A6C7C4F77580
-:108980009BF58A38D2CBF1CCBFB5337EE24FE2D92A
-:10899000FCB280FFEE8BE77265081902722582EF48
-:1089A000BDF05E47E9EFFB920BCA762E1766B91E43
-:1089B000D1A11DCFE58390C36EE043FA5D4072E91B
-:1089C000007E1F9731F89F285D89F26136F1E073D0
-:1089D0004A203A77A41F6972843D44C799E556DA64
-:1089E00047B3AB947541AF62DC391E65FB0C61DFA8
-:1089F0004E56DAB7F3FEE9AA0DF56FD2736BAE658A
-:108A000062DC04F7FF75144F2C6EA2657194CD7A69
-:108A10001FD849756D77BF95007C741FE17CB457F2
-:108A20005A3A14FDB0D2B2083B62408D4F02B93FB2
-:108A300098AE2980780D61BCE8A4CE7708E228279B
-:108A400057D215D3791ED1B378E45113F1823F5A2E
-:108A5000D0A76506F3A75232C6B8489A35C609F4BE
-:108A6000B4555388FED7ADB11667A4BF73DB464A31
-:108A700077117E578781145A39DD44DBFFBEC9E583
-:108A8000E16312F37F7BE71871BF9790E356C41B35
-:108A90001264721AFC883F897788F7D1CF01F1BA46
-:108AA000E1B4F449CC9EE9F95E269BD1EFA8923F50
-:108AB00009F14EF4F727F4CF43BF7D557BC16E9487
-:108AC000376693739014EEBFCAD3AC5D06FE83F68F
-:108AD00066ED527398EE4E00BD02DE62480CD06B1C
-:108AE0008F1F6F9F01FD783FD6B83F02BAACD1FB14
-:108AF000F389929EF1795F7A6C05A7175D997BCE19
-:108B0000323A9FAEF7F4CCAF751F417E7D79BF0D31
-:108B1000FD90DA1904F5C9E65282F4D0D52CA1FDF6
-:108B2000F685AD1AF7019BA526D4139D7113117F0D
-:108B3000ABCC47715F5BFD94EED348BB6BD56E65E4
-:108B40007D3509E0BEBAE6C55EF48CF24BC8C7DAE3
-:108B500056E57764A0523E1670B95FE876CEAC80D9
-:108B6000A9573973D8BE9AF80D741DC5EFEAB9FF3D
-:108B7000771ED39BE43909ECAD2ECB0599F13993DF
-:108B8000C7C5BC3FB51E2AE6F6D4382AB760FF2910
-:108B9000EC23FA3ED68F6ADAE5644D785E45FC3BFD
-:108BA000619709B92DF0525A424809A5FB643B97D9
-:108BB00043D9241BF04AFB477EA0E37AF571D8BF66
-:108BC00017F66DA3F97814EF5ED0B35E8DD10774FC
-:108BD000B445AA47396D245C5E4B1E94CBAF79BD7A
-:108BE00032C07514A99F398DBE37C61888017850D8
-:108BF0007A48B32784E9A491F833F64A0A7AC1F691
-:108C00000EDBEFA3D28BD02FFE8F997D3195AE185E
-:108C1000FAA980400E2D8F4A6C5F38C9FCA816BE99
-:108C2000FFBD660AD2C364E2D3C2FC2AAC4A3C4F01
-:108C30004A56D6A7387AD1810CE3BA383CA70E51F0
-:108C4000B6BB845C234AB99645AE229EC983C77ED3
-:108C50000C7E81980D6408D81DD442447E53CB838A
-:108C60007176B3C23E8A88838CB317F78E83747192
-:108C7000BFEEAD24B8FC45A937BD74BEB5414E8EDC
-:108C8000A02B41C7AFF3BC09E94D1E6F2D62FEC09A
-:108C9000B09E67F43282D76E057AA3EF2F147492D8
-:108CA0004932814EC6B699FC32856B01EFE756A07A
-:108CB0009BC2B03EF76BCC0E7D36D08773AB2CF7E2
-:108CC000B6DB13E31C4827C3352EA49362E28C075E
-:108CD000FC94185B1AB530FFFD230778CC0ABA580C
-:108CE00062473942E902F9AA975E54B6ABE846E01A
-:108CF000EF38B7972711EF40188F8AB1A3602FFB89
-:108D0000B318DD541017D2C9DBD953783CDAA3C5A8
-:108D10007E88521F961B9574A0A62B3AA226725CE1
-:108D2000359DF54537994037421FC6DF986EEEEF07
-:108D30009B6EEEBF1EDDA8E945C893BD266B39D8F2
-:108D4000A575D512CAE1E1EF0D6C84FAE0355998AA
-:108D5000D7B2D7E644BBB5AE9EB517055C32E4BDCD
-:108D6000E4ACE7ED59EE72A8D76D60F187E2932C81
-:108D70002F66E07DACBD6053FD110BE8772FFBFE45
-:108D8000F58B5BE458DAEEDBC2BF2F6D2A877ADD04
-:108D900056F6FD17103FA2F81D71DAD708CF6FDA2B
-:108DA0009EE564DB4F66CF8EE774BA57DA7704BF6F
-:108DB0006B62DFAD3866EC47D00E6676EB38BECE20
-:108DC000F14FB175DA3FBB6DB283D2EFB29017EDC0
-:108DD000A6F39A9A11286FFAD867964A4D695052AD
-:108DE000BA4139E33252BACE66F1C55D7488437632
-:108DF00066078AB81CE40944E6051CB233FFA37871
-:108E00002F318EB038F21316F4078BB8A1FF712200
-:108E1000019FC11AB9FE8F1A479C94538FF1C34921
-:108E200099227E18D42EA6E3165CFB6A62347FCAB0
-:108E3000713EEE059EF7209E57FBB23440177B81B2
-:108E400048520148AB7F0776D35EF0BF32A5E125DB
-:108E500025805756FFC8BE62DBD6340A5F4DBDD6AB
-:108E60000B4A2683EEBF68D7D303C4DF3FB6F7FCB7
-:108E70002769891FF413D1B2F92F6FA47A500ACB56
-:108E8000A55942EC8C19847C7A27C7D367766E6F1C
-:108E90000C27C341DECCE278FB91B15EC7F4659349
-:108EA0004EC5FF5F20FFEFECD36E56B6ABE4433503
-:108EB0001F7739B797579210DA05E7251F9617766F
-:108EC000327B79B5F924DA155D4F303BB18604D198
-:108ED000EE50FB0F57EF51D6D7B428EB756DCA7A19
-:108EE000579E17C7E9DAB96604F8EFAA77BC877E00
-:108EF000E16A21277C4A39410D2426271EBF19FD2E
-:108F0000361A2395134500AE7E9847329CB8E2414D
-:108F10001E8092BD46EB0FC22729B4AE711B1350C1
-:108F20005E4C8EFF5C8C2F639CF63D97238C979E46
-:108F30007DA14A4E14087FCCC038F45709B951C0FE
-:108F4000ED123259BD6F7C14F96F38AFE52428F764
-:108F50003DC2CEA0DFA39D11D0987D1A4DA45DE146
-:108F6000437E2C34523D812CE434B2FD4A1351E14E
-:108F70007730ACEB3AFB2665BB0AFF62DF3282E357
-:108F80007F0EF10C007CDC49DC6F817E38F171B51D
-:108F900062BFF4F11F270A7F0AEE9BBEFB7EC9FF6A
-:108FA000BDF64B3D783751FB9196E533A60CFA059B
-:108FB000C4BD5B4D98CF5927313C27CE399911E973
-:108FC0003F3CD14012B4117CDF38C56084F860A307
-:108FD0008EED27664CFD64C4E208B9F192B1746A63
-:108FE0004231E021F0937F87FDC53B32C17C99F689
-:108FF00004C47B77137D4EE9ADFBA95B9C5EFAF858
-:10900000928EC51BBF90EA97438A9398C7F20DBF13
-:109010003369A91E5B21FBDE08427C55F2BD5A4331
-:10902000DB4EE93D73A0FFD51ABF9EF9ED0218276C
-:1090300015FDF7ED87F4A2BED31F667A3124F573D0
-:10904000323FAE373732DE5495C8F657EFC7B9977F
-:1090500001DE85DE13F18433774FEA0FAAE16BE27C
-:10906000EA0F714E490BB1A7DEE341BEC0E608BF6F
-:10907000F21953F4B8C0DA04265FF7016FD1FFED9F
-:1090800036D73A18F702DFFF5DE0F1AE0BB12CFEE8
-:10909000F5BF7ADE67E5A309CCDF7D81C7C72EC4A3
-:1090A00029F78DE2BDC778F97983D1B839029F8E4F
-:1090B000C70DF53ECC93E27921EB09DB27EDB735FF
-:1090C0006F8B8887362794EE837925E4B8F42900DE
-:1090D000BFFD4C0F433C1AE2C64556CF76C04BADA0
-:1090E00083B820EE4A1C41FD4C883FC2BE13ED07F9
-:1090F000462F5D26568A79352754EE83EFBAEE0E59
-:10910000223E7BEA954C3E3627B871DCAE59A29DD3
-:10911000D71F0A72FC33FF81F067F7150F53C7BFE3
-:10912000A8E26076B689C93175DC7BBE90633CEEFF
-:109130003D8FCBA1F9EDCC3FBEC048B60CA0ED0BE6
-:10914000DB93D87E31D69BAB887B7B63BE531E837B
-:10915000A0CFAEF4404FBCF6898878ED1A1EEF5BC5
-:1091600023D6D7AA5CDF9B097DC66BDF4C8812AF84
-:1091700055E705BC0AFA7D60189E6BAD6CFD157253
-:109180004DB91EE4C45282F9E16BDF59D268A4F5EF
-:10919000B50F82E70FFE98BDBA86C3ABAFF925B80D
-:1091A00035C4A1F013F7238E887D718A274E51476D
-:1091B0000B3822BF724075AAE2FBF4FA6CC5FB992A
-:1091C0001B6E56B467790B15F59CADB72ADE1FD41C
-:1091D00054A6A80FDE719BE2FD0292D31FE3B1C734
-:1091E00065F095909B7C3314EDB7ECB94BF1FD170E
-:1091F000A4FEB131F4BD5613D303C4EB0A0CA57021
-:1092000059CAE79FD7B258F17DA3D432C24FDF5F6E
-:109210001A60FEF6616DAB14FD5D8A9DC8F6113CC7
-:10922000FE584FFF6372DC21A33DD4269127A4DEB4
-:10923000F1C8EAF687B70C20BDED0AFA877A7E15E9
-:10924000D5F36047A9ED0C39D16247FD904A52AF82
-:1092500045F055980ECC6887753F25A33FAD800C2F
-:109260007E7C0CC247477C8EDEF8EA26CCCFD3FD4D
-:10927000A2C509FEB215EF2C41FA33242BE9C0E454
-:1092800050D241CC10251D589C4ABCF72F51E25DAD
-:109290000D679B4B4907028E02CEF193957421E036
-:1092A0005B42FF03F81692D031CC9FF6494E3F89BE
-:1092B00012EF6D6BC675DCC86ECB53C173F8515796
-:1092C000A319E1C4F2A9849D64E0FE69B5DF5CD80E
-:1092D0001F6313B9DDC3FB117EEE2D9217ED9C9E2B
-:1092E0007856893FC39F05F64E3D61FE127769624D
-:1092F0004254BF1A3EEFCBAF26E028EC99D560CFA1
-:10930000D07196110FCAA5CFB93DB3C2FC28C605CE
-:109310002FFD91C1B79AF8505E7FD77839D889244C
-:10932000C2DFA886A3D42EF92DC0075C6EA7927663
-:1093300021B73D983741C9CE3842115F50DAA1C4F8
-:109340002545CA2761978AF1043C85DC12E3194858
-:10935000BD9C0C7CA092636488DA4E55FA3D849FD4
-:1093600004078B88638CEC894FB07D62D8EFC5FC15
-:109370001C7266562301FBDB2AFC1A81B9F05CF8EB
-:1093800035D4FBFB1BC545677AA5E09359BDE3A126
-:1093900022BE4A97F9D9BFD38FC7488E74186FC6BB
-:1093A000EB831388269A5FCE79FA00ED47D684E2E4
-:1093B00023FD65C27FFDB614C479FF88B8EE27117E
-:1093C000F6422D699938370BFC9F546FC542C9FC92
-:1093D0003EA44D6D97B278A286AE04E87B358988AD
-:1093E000176685DBB12EF7AE8B3C971BE97747926A
-:1093F000559C5BC965ED4CBE89FD5B5FFB2511CFBC
-:109400007F4B4F615218CE6B793191EF33F3493E68
-:10941000F44FF9AA2511F7E7940FA548BEEBC983CD
-:10942000C1F65E7CA75ABF88E7CB9622F4BB2C8995
-:109430005CEFB78087B023BEA26B83725BA203CBC5
-:1094400035FDCE7CE482E6A24046A4BD5BA76779E9
-:10945000C1A445693F9F4CD47078B9E46F03A7BE9F
-:10946000F1C0F3C2381EBEAD3D24F2C204FCFE289A
-:10947000E46018DE671572AC67DFD603EFB3D1E4A2
-:109480009C80C7E5E2C0738027D9723211E0FC5797
-:109490008BFB33C04FFAE9E0794903FAAEE3B92711
-:1094A000417FB5C9B83FAA1DCBF2836AF763B09C70
-:1094B00074B61B301E58DD7604EDB28E062A4007C6
-:1094C000F60D9F9E75AAE0DCD73E45ACE3BF557410
-:1094D00026F244E8FAFEA6A0A7DEEBFF5B347A137F
-:1094E000F94915F2D0FEC188FD483BDFF798B46E0C
-:1094F0006D12FDAEE8C3B458804B85DC7E2C15E0C0
-:10950000B05EC2F347E30DC40B7EFE147E0EAD24A5
-:1095100058EFB4527824A799F13CD1E01FCB6E8864
-:10952000637EB27E5DDC125A7ED94087A6FB8DC178
-:1095300092C68D7446F69DFD6911C4D7E661DEF1D1
-:109540007C038BFB67FD24C69F43E5C39B7A6204C3
-:109550003ED365D7E3798B904DC67D865D2613801B
-:10956000AE049CED316C1DE279E9D3BB25C86312D2
-:10957000CFC7378686AFA5E539C07771789DE3CB35
-:1095800043C3EBCD61388BFC40A20D65CC88E08BEA
-:1095900037393C6A13F45B400F761AF9FE8FEF03FC
-:1095A00089558BF2633D8FB39F194477A2D88FDF23
-:1095B00002F958B52657FF91E0E7823C025A7C6DCC
-:1095C00075F5B7E1FA1D682FAFE7765527CFDB5E5B
-:1095D0003FA52C09F6517DE53D952631FBBE86C79A
-:1095E000BFC5F31AAD1FF3956A20DF3822DFE9BB50
-:1095F000E61B8BFCF13EE160D3122D8543AD44DCCC
-:10960000D77BEFC0DFE4A8FBDCEA24CD75F3DF16DF
-:10961000F2F589FCB65AC86FA38FD6EF2F4D2251B1
-:10962000FAEBD133576E55E49189FCE8DA2BE3303D
-:109630008FACFC810E3CF707FD38CCE1FCB6BEE0F8
-:10964000FC66229B472DE4850D8F7CCEE446B87FD7
-:109650003BE2E1570040F073B4C9E88FFDD571CD0E
-:10966000E45D51E6FB501283CFCD095AE48F5BFCD9
-:10967000C4D51C657CF19E38170270AECCEB3DBFA3
-:10968000D6B2E002983FE4AD461BAF2189EDAFC5ED
-:10969000BC5BE382CB399DE3B98C9EBA5589C77F09
-:1096A000E572BFF5B660069E2F9A123D3F5EE07BE5
-:1096B00084B65E0278042D9E03686FCEA6956190F5
-:1096C000D7EFD7B0FC29C6677DE13D0C6F8D229F97
-:1096D000B037BCF58867D19FD88F5CDC2163BCFFB5
-:1096E000E209CE97C46596287F2DE2FAEA226171DD
-:1096F000838B4D12EE43167B08D940E5CBA2DDAB40
-:10970000316EB3FCD9E15B404DC1F3FBA81C599409
-:109710004CC8385A2EDEAC8CDB2EDDDE2B4E4322BD
-:10972000F522353B715FBDFC51E577D564FB7F8247
-:10973000DD53ADB26B06733FD7BE249ECF37828C0C
-:1097400000F9BEF6D9AFF490B2DB17BD7F49F97AC4
-:10975000A016E4A015CBA349AEFD49141E1F26791F
-:10976000DA416E777DC0E0D05DD3CDE4FE5376D490
-:10977000370610CEF49F86B92CFEFA001517107725
-:109780003318985D23EC39595E27C7D2F6517F5ABA
-:109790001F07F8B3FF7AD264B0F7137E1DE3027897
-:1097A0006D2B7515C0FE7F5BA519F3188C0616F797
-:1097B000F5FD6AD46108030C6C79B80CF69FD6F6F7
-:1097C000437EF08F6CD5FC279E2BD93A8EE5B98964
-:1097D00071EADA2BF7C27C32EE647A635B96ABC037
-:1097E0001AD12FE1F6592D8759D7C1C13F1F4DF12D
-:1097F000F8E471348FE9FAB2D10F773361F814F9D4
-:10980000543076A41DDA41F50F24E589FACD2D9266
-:109810005F47D7B3A6752FC62F6A36F913E7829E26
-:1098200079418BF11F313FFB9B296510E711FA65E8
-:10983000AE6445FD2FECEC3944FCB1385115A783DB
-:1098400039DCBE9E1BC3E0BB983833E0BBBB8C2425
-:1098500016FCD373CB5B8A51FFACD6D940AF8B7863
-:1098600047DFF640743F51ED7316763E560AE542E7
-:10987000275FD27D0761FEA2A8E78D4CC99CCF72FD
-:10988000B9BD3790B820BE56FBC6E066F00718FA9F
-:10989000B1382C953BC69242B4778DB08F5979C0C0
-:1098A000E467FE6A1F3F07EB2A807C90BA1969853E
-:1098B0009897709ACA0F0B9C2F0C66209F52B92262
-:1098C00051DD969D1C334D4BE9BB3695DA53B4EE12
-:1098D000DE91CCEAD9C1E51A5ADF905CC8EA3707B5
-:1098E000CF437D53F258562F0C2E9769FDE9E4A91A
-:1098F000AC0E1B3B4A58BF4A9E31CD0BF6848DEB14
-:109900006B6710CF05D7BE3E5813E9A77C2C99C9C9
-:10991000A52FB9BFF5CB2CB27006C07B4810CF9DE8
-:1099200089F77E9A2CEC5B96DF2BD629BE23C9D112
-:10993000FB2FE0DFADE4E779C7C790AD2616A7F2AD
-:10994000C652F81F6D1F8C71B6C4E438E68FB3D2CF
-:109950007E8AC2FD08388AFEC4B8AB40AF82BCD54F
-:10996000317FA9681F97CCE4381D67338E3394C1CB
-:10997000BF76465A01E08DE24BCBF1A565FBCE6682
-:109980001C17FAB5E5A37C1F0EFEEEA357E9FB59A1
-:10999000E179ABE9632AA78F958D2CBE18B2E5203B
-:1099A0001D8D8F61F61E2952AEE3690E87C7926D39
-:1099B0000C8E3DF84892709C460EC7340AF7BCEFF7
-:1099C000BEEEF93FD0BA23F0E592A1BDEDA65D91C0
-:1099D000EB11F9DAA29F2F37AABE2B617953B5712B
-:1099E00039F8DD032662C4E76457CF7759F9CCCE46
-:1099F00004FB53DCD740BCE3D04950C3A546CFFDA0
-:109A00000B2D3C7F70A08B9D3F9E31AD88AFCFCAA0
-:109A1000D7673546DCBBD0C38F274319775A7AD333
-:109A20006F0FDC7BFA1B5AC8FB53F075B4FE803F06
-:109A3000FAC2C7CFFFDEF810F354C1B307CEAAF9BC
-:109A40000978023FE3774395F428E6B92959E40BF6
-:109A5000ABF83AEB7B8E57CABE5B730FCF03762809
-:109A6000E9794D6B9606E2E7E2BBC9E0634F08FB7C
-:109A7000DBF625F37D6B1A49EB23FFEDD5E4E87E99
-:109A80003A7CAEDEBF75D958DEB3DA6FD095E00C04
-:109A9000C0793EEF65763E7DB4CADE80F8CB3E737A
-:109AA000F8BBB03E51D6E514C607BDFD40213C4F82
-:109AB0005B64287BD9E1A47B9DE4EA695A6A571468
-:109AC000F52F5B9745EBA79257A1BC2E1A50F65580
-:109AD0001695DF7F485ECDEAB7947D950DF51DABF9
-:109AE000D9FBE35D2F837C27DED5D326A484ED87C5
-:109AF000D3C90E849B5CAE21404706F96E27E84926
-:109B000001CFBECA2283A63E9A7D7AAE870E587CCC
-:109B1000A284EBE712B13F0F6A15FBF3AE5876DE75
-:109B2000B80BF4295D6F47B2E77C32D829311D0BA1
-:109B3000B268579B62CEEAC11E925C5477819FC384
-:109B40006125F3209FAE639B1BEC23B2CA69D4222C
-:109B50003CB9DF89AEED1AEDE7C01B2FDC3B800D71
-:109B6000E386798CE2FC5FF7C6377F81F868DD9782
-:109B70006627B8F546B5EF5C07F6D5A8F6DF7FC3D4
-:109B8000F42D3BA721E63D0AFC87F479499B01E7C8
-:109B90003FAAFDA665F0FEE80FDB73803EC69EF18E
-:109BA000378238E83AF8DA00C5F90CF285F47DCE50
-:109BB00067F4C0E34FD478EA8FF030A624003CAEBF
-:109BC000629E5467C2892D41B4D394E760A85D8E2C
-:109BD000F1D56ED2CF097102718E5BEDAF3C5D495C
-:109BE000D7479F8F0DD11944D8CBE3AFD0FD7D84EB
-:109BF0009D5D4A6C8A7AB93145F17E85354BD13EFF
-:109C000029F92645FB144781A23E75C828C5FBB734
-:109C10003B4B15F53B4AA628DEAF74552AEA05FEF4
-:109C200016C5FBC38FB729DB4F3A100FC3CFB8CB94
-:109C3000C18E77063C8D508EEC682AEFEF20BDFC7C
-:109C4000B445415F233C1F7DB5BED84FA29C5F59F0
-:109C5000E541FF7EAFF32BA5EC7C7BA7869DDF1053
-:109C60007ED9AB319EB180A7B7250A760AEC71C6C2
-:109C7000503CE0AB62E143982FD51D22E8CF6AD576
-:109C8000077F361AF4FC7C19EDDE569E67D35A9591
-:109C9000E7035FDE6929F82AC4E9BDF3D9F980B189
-:109CA000D4C2C575434C53023C7914EB2E252B5579
-:109CB00078BA5B51AFB0DEA3787F52F24645FB1411
-:109CC000C7832A3C3DACA8DFEEDCA9C253B30A4FE0
-:109CD0002F28DAC77E1E6C04361ADFE1952D74FE3C
-:109CE000B79E6E2A07BC8C3EE39D0FFC52E4F7340E
-:109CF00082382C3E5A7F044A3FDD4F819FEA7043F1
-:109D00003296471B1CE8673AD63004CBE30D4E7CF5
-:109D1000FEBB86122CDF6D7061F96F0D93B10C34B0
-:109D2000B8B16C6968C1F7F735B4614921980EFA8A
-:109D3000C21EDF73AF423AECE73B35C15A88A0AE92
-:109D4000DB7900E56467BF6027D43791D7A74D80E2
-:109D5000F35CB09902FB0A4A8ACFFB525D7F49A1AE
-:109D6000F54D29AC2EF2125A34AE02B0AF1FD8799D
-:109D700064BB369D90FB37BA93AD365637D23A2244
-:109D80001BFAF01ED9EE4A23E437A0326EC5FA342E
-:109D9000A8779958FBA69D47A679513FB0F8F19D49
-:109DA000E1F8F10330AE3A7EFC9B0B0E0BF8534EFC
-:109DB0005C1D6C81759DE0FE231729D02DA265A93D
-:109DC000B640077AF1B4CA8E10659DA6B409FA6D43
-:109DD000D13867615EF06D3A0279E83324B61FED41
-:109DE000B10353991CEFBADD80FB9D931AD732CC97
-:109DF000779242CF00BCF6A49C44BDD265096500B1
-:109E00001C9E4BF990D51342CF48CE88BA8EADF345
-:109E10005F534EE03E22CA3A77A7448993BF90C26F
-:109E2000E3067E573A9EEBE5F59395AE35A0274EB7
-:109E300096BA06C17C4EB80DC83F5EB7C507F99605
-:109E400044EB2A9E15E157C949D5E17777EA199F76
-:109E500091BBE4A8E7CD4B53999D857883FDDC9CAD
-:109E600018B4C34F6AA29F179F93CAF4F5A57ED179
-:109E7000FD2B77F1F6B29916ECAF6BBD09E3B75D38
-:109E8000EEC1680775D5532851FEE8BA507FF91521
-:109E90006C3788D016C629E77239F59BF6757F3E78
-:109EA00045DF3FBB3EC68932DC7A33EAA7BBF8CB3D
-:109EB000F3E38D68B7CC9F915E067A692E8F772D7C
-:109EC000B0681331ECA5B5E9E18AA0A5E6822DA022
-:109ED000FE97DB2BF5365AAF4EBB7B0B94AB063EA1
-:109EE000AC87239A3543F76E01F3710D65AD62DCE3
-:109EF0002F05DF6BA0F35AB84176B0FD933877B8E1
-:109F0000FA3BE557083A3CC9F364287C715F38375F
-:109F100095ED7BC4777339BD5D4CE1765B1EC9BBA3
-:109F2000A68CE35C063AE998FF5E6E1F7E77653B80
-:109F3000B7DB3ED2B371D5F7508871E771BC9FD4BF
-:109F400013970476DC5D16A48FFCAAAF3615D3F503
-:109F5000E7B75B35188717723CC0EE032BFEDC8336
-:109F6000726E6447F0B95304E9BC0DF8E4467A6AAE
-:109F7000A67723EA87515F53FD0372F1AAE7EC2924
-:109F80006CB5473D8FE96FA8E6F2B11EE5DAD186E0
-:109F90000D583FD6E0C5F278C3562E1F9BB0FDDDAD
-:109FA000861D5C3EFAB87CDC83CFDB1BAAB07CA3A9
-:109FB000C183E55F2DEEB8D40420360FE667BEB549
-:109FC000D340E0DEB4EE7603D229E580679EB44349
-:109FD000FE8BC10AE7EED479306A79DB83FFD65E67
-:109FE000F76164A41647E4BD807D96D937FD9C20B7
-:109FF0000E0BC893114F24DD0EF2F984C36101BB2F
-:10A0000075646A32ABBB1C161DAD973C41EB54BE68
-:10A010009CF0382C065A1F959AC2DABD0E8B89D651
-:10A020006F7D2285B5FB0806A9C73F91713BC89F8C
-:10A0300052221D057E2837664D8094D90A6BE9515E
-:10A04000E08349C98B26001FFC36C5817438C5B131
-:10A05000F128D4A70E69D6C2511B97B960337C573B
-:10A0600066AFD4C27713D2EEDE0CDF4D1CF8B036EB
-:10A07000F2BBC943F76E86FA3467B316ECC1DFA6AC
-:10A08000B0F3FDA21F5117ED42BE8A3CAD61ED6EEB
-:10A0900094E3F96D6E94E3022E657756DE0F7EBA77
-:10A0A000BA36C92AC13CEE947A82EF900B577B9561
-:10A0B000720B95B3D39FB8C9B291F2571DD46FC537
-:10A0C000FA431BA3CBDD99A951F4CB1F389F82DE45
-:10A0D000847CE83FE8D97D1E2FF3F5D5B52FB22C4F
-:10A0E000427DE5B1807EDD9FC2F4E541AE1F2FF3D6
-:10A0F000B29B3FAFD3B8E6C3384B53FBE4EB6A687F
-:10A10000A77CAB3A27D0473BE7EB55A95C3FF07BF8
-:10A1100013D610769EE846F95A2B23F76F5990977D
-:10A12000D3720CF245D5F90F3570CE28A7771E30C3
-:10A13000958B2CEFB14D993FDAB3FFE8C7E41E1CB5
-:10A140005F844D4763DFEB7E2035E1BAEB56B6F313
-:10A1500075AF242CBF59BD0EE24940DE12F9CEBDC9
-:10A16000D7138CBE9E5EEBE0F7EEA9F2ACA91DF40E
-:10A1700038CCA762A18580FF26524E9CBA8E9C5097
-:10A18000CB9DBF973CBB8EBC79319ABC11E79DD566
-:10A19000A5B0E7E09C14E4DBC17D2FE0A7FFA74456
-:10A1A000CF6BD04F5759E82F1AD89FD9834867767D
-:10A1B0009BE775782EE959DC5DE4B15ED0787F0BC2
-:10A1C00076D1B12796A01CEA04E540F9F10D5A07B3
-:10A1D000B9536475FB017E6408A39FBEF233DFE6CA
-:10A1E0007AB177C9F849E42976357F93817EAC1B33
-:10A1F000D07B5F70A890C704E13C4077490C9A3C43
-:10A200001D12F14B85906F9D88764447BA5E0BE531
-:10A21000DF7B9FD8919E8BFDABF78B1D29254636A2
-:10A22000EEC4C950B6E93D3B16C13E699401F749F9
-:10A23000EFF3FCBEE99F5EB583BE9A2EFB13F3A538
-:10A24000DEFBCC8E77E69539F27BEF37E9FA26C054
-:10A25000FA6EB4EF741B03710046F5FEB366C35F7C
-:10A2600008E4458FDE7095C07D6437DE8F1219C417
-:10A2700044E169E711288B3F77611ACE880BF547D7
-:10A28000A01CF535DB9EDF289FE8D62B2D47D8F1A3
-:10A29000F0A1CAFB164A7ECFF6ABBCEC754FDB2AA9
-:10A2A000AF324FADD45F8C7914723016CACB5210D6
-:10A2B000FD5EB286DDC320EE5FA0FBD8C401C5B051
-:10A2C000EF65F952E321CF884EAEE2A71F2FB817F2
-:10A2D000F9DE84F64FCF3EF6150DE609B46A5DFD52
-:10A2E000C7C23E76C320E7465AFF8F40C22F0ED02A
-:10A2F000B2CEFA1712797F5BCD866E45BD6363F8E7
-:10A300009E20C883AEF99B8C7AA78690AD80AF1A49
-:10A310007258BF36420F9296FFEC81FB302AE72A33
-:10A320000170B8AFD24C77D1F72AF97E83781B59E8
-:10A330009DEFB308F9EC7617EDB73281BF4F664F4A
-:10A34000C77ABA68AF62F541A2BFD7D8FB29A2CEBF
-:10A35000FBBB49D47FCEEA59E2FB16F67D9E18FF7F
-:10A36000BDDBB1DDC2DE1F3F60FD74900342BE570E
-:10A370000CE0F925FC7E1F2AEFA70C48B86E5E8919
-:10A38000B29DEB03719F4FC54FA7C4BC07FCDC22F5
-:10A3900061EE5BCD7D3AF46F5F8A6BC98F3C9F2C79
-:10A3A000F250DCE51617D87B6B5E1DBC4BE6F93826
-:10A3B000606F6CE3F1E50AD98CF188EEED4CCEF7D5
-:10A3C00065AF2DDFF0BA029FBDDAF93DCA18A8A328
-:10A3D000E35D7E2809F3DBC9C000C6C3570C90C4F7
-:10A3E000F92A3CDF2AF2BDEC39C405FB53FB6B268E
-:10A3F000764FE5E70194BFCB5F63FEDE353B8FA070
-:10A400009E5B2C3B908E0F6779D600DD765AD87D07
-:10A4100084CB37BC81FCBA2193DB09D6D050053CF4
-:10A420007BC3FF9E1BC0FF9E7F24FCD57E66713ED2
-:10A430007AD577CC4BEBB4B038A893E3E9538D636E
-:10A440000487D723B09ECBCB02B9361992860389F5
-:10A450002CEFE8DD62D80775D75BF09EA379EB3E61
-:10A46000C98F3C97224AB5FD7F0EF8A8380CAFE69D
-:10A47000DEF07D16F0731DF82ADB7F60F826698315
-:10A480007A27C44D4FB37BC746043ED547E6BBBCD5
-:10A490003580E9DDFEFC1E6A75DED65B032C0C4FB1
-:10A4A0003C1EB366C6BB63201E23F8617C0C6901A9
-:10A4B000FF3AA56B27A76B27D0B5A0DF705C867E1F
-:10A4C0001785BFC2F44B147969EF0E50DE0B46E1DD
-:10A4D00016B801DD06FE9174DB4AED5F8C63BE6247
-:10A4E00042FF891ACE5F71B80A786BD3AE0F676DE1
-:10A4F000DA0F03676D9A43E17F10F0EE4B3FA9F14D
-:10A5000023E61D854F8BBF0F9F36A67339A50D62BD
-:10A510009EA81AEF3169BDF0DE3FEDFA7857B6FF1D
-:10A52000C07857C34D5DD6F0F8A6FA795E9A88FFD9
-:10A53000FE3070FCFFCD7F3EBFFE90A27DE18677AE
-:10A5400014ED8BBC1F28EA638281722073E10F1F18
-:10A55000772184F6E5F7F5ABF7E54F9FFEF20A0D9C
-:10A56000C4DB4A02CC9FFF65BA67531A85F3FB1A16
-:10A570005FA385C275E49916766F57752EE60FAD09
-:10A58000E373FC6ACC7F9DBD97D2CD57C480FE4E4D
-:10A59000FFA19BB48EBCDE74507A45435C11796890
-:10A5A000A5469BD685FE1AE28A46370F70BAC1FCD3
-:10A5B0001FCAEF5546A2B3533EAFAA9230DFA98A15
-:10A5C000B07C685AFA3DB47DBA96F8E1DEE34AB34E
-:10A5D000D66FC0389FF23CB381DF8B4CECF18A73AD
-:10A5E000CDB24BC6BCB459252C3E7897B905CF9354
-:10A5F000CE39BEE9F2BDB49D6CF616B37C6B71FE2C
-:10A60000EC8F9AEF12F77B208DF17997C4E3C89213
-:10A610000EEFC7527F37378DF1D97479A30CF92E1D
-:10A62000A10F08DADD82EFE8FA8E1B0AD9F90AF8E1
-:10A630005D8A4AA2F30FC6F3CE0F97C3FB35271DE1
-:10A640000897BA928DF980C7BA09D239437E785FEC
-:10A6500053B7E16BECA7427EB111DEEF3ECD5CE17A
-:10A66000233BE83EC511E9AF0C2E00BEBCD1FE472E
-:10A67000CCFB4C831FE9E96CC3712CDF1FF7FB6235
-:10A68000B033820D81A87EC9EFEB1F107E01E12758
-:10A69000107240DCCBB7378DCB05A33400EF53D31A
-:10A6A000B252C8CBD7D27AD92B076E205F0FFC23CA
-:10A6B000E5EBB7A5F39A64A617D5F4ADA66B41CF29
-:10A6C000709F37FC1EC15DD4DE03BD3A9778F36AF4
-:10A6D000A89CAD5AD1A41B2D7D7FBA5E65FE3C833C
-:10A6E000443967F2DDE5B983E54796CBB83F10F909
-:10A6F00009020F9DBDF1D69D767D3B53D9FE0FB764
-:10A70000E33F5FF0FDF41A51D80396F45EEBB6A573
-:10A710005F7FDDCAF61F78DD11E75F16C89AF07912
-:10A720000FC81F063BAECBC7CE33566735E13DF2AF
-:10A73000A424140B76E3CA8332D221D1BAB42911EE
-:10A74000F74D7510FF47408F2BC6ACC07370BDEE40
-:10A750008932B7E2B938F57D51225FB896F7A3BECA
-:10A7600037AA96E709D7AAF27646A4F3FCE042524C
-:10A77000C8F22B9476A9BAEC6C200ABF64E7D50620
-:10A78000F4038C4B6FF999372D8C8709E9BDECB830
-:10A79000C937C0DBE47F24DED4F42A5B76E379A8F2
-:10A7A000EF4AAF57335DF3D313C272781EE47015CE
-:10A7B000C13DEE061FDCF72FEEC7EE92D87D345D6B
-:10A7C000E708FA8D6E74BFF2A8931E3CCF39F25D94
-:10A7D00097CCF20858BE81B05384DD32BA2324B33B
-:10A7E000FBEDF939289E17F46DE5973360453B473B
-:10A7F000F8DFFE5E7E6BA1E70E1A995C13FEC1A224
-:10A80000A01BEDB84E9DBF18EEB3F7EE3745B5036C
-:10A810007E96AEB9EE3DAE7FB5787E06F43293CB30
-:10A8200077719F6B85CCEE7BEE0EC8E8BF5BFFCFE8
-:10A830001FFEF649C78DF7F575D6EEA8FB2251D657
-:10A8400069D87989C27207E6EDC17E09FC77C29F9B
-:10A85000A77EFFF5CC321FCCAF421E83F76B76EF9D
-:10A8600060F3E90B2F751B42387E9FED7CFCBA83A9
-:10A87000C5D6C8FB30CEA5F7ECCFACE78D61BC7E6A
-:10A880005BFC8F0D5529EC9BFFD7F70DD3656A3A1A
-:10A8900052FD9827F9987D4A989D3A8F04B05C4004
-:10A8A00042587A08CBA75F4C9C582E256E2CA76582
-:10A8B0007A4EA5637E4B2811F3215FFDEB50A09BE0
-:10A8C000CBE3463741EEDC0F65A775153870FCAE5B
-:10A8D00057FE9A01792D37E2FFF858D70598A73A25
-:10A8E000AEF16FA532C64F88712DCAFB4A7E4B026E
-:10A8F00099C0E262DB12B390DFC2F22FA959C83FC0
-:10A9000088B7E69DD3B0FC909512DEE7DA16D42026
-:10A910006BE52DCBF2C1FD3C6DADAC3D6F8DCD2710
-:10A92000D17ADE28136BBFDBE683730FF34910F98E
-:10A9300071219C7A90E11C0C936FE2FE736AB167FF
-:10A94000839DB5ACDDC8F2F7497020C8F1FC3EF636
-:10A95000371332189F0FCB66727B5899D20FD18F65
-:10A96000B7AFCC2C5B960171D90C574C065DDFB0AC
-:10A97000B8C0B6478AD02F8FBFB3F2C5A87B307E50
-:10A9800028BE6BCA2CB3C27B2F492CDFDC7B90FF27
-:10A990006E01092546DE273A2DB33C11DE4BCF2050
-:10A9A000DC6E8E0E57F83D3A7794FD9CC8671C0606
-:10A9B0007B2AF48FB37BA95E92583DFF19EB1D9B58
-:10A9C00087A20FDF0B766D53A66730AC63989E109D
-:10A9D00033CCFF69836F17DA9FF519E08F5CF18C38
-:10A9E000410376C1C754ADC2B9927F6F3062F90995
-:10A9F000DDE742F91F749F0BE539BACF85F233BA10
-:10AA0000CF8572D91527251A42DEC970B9603D225B
-:10AA1000DEA69EEF28016F31FE413D8EBF32D3830B
-:10AA2000F0EDC1F77EE28378C84BB6506ADC75E87A
-:10AA3000AD6F39E3E5FBBDE8F959C332D8BE36BF87
-:10AA4000558B7A3CBF2D18BB3CE2BDE9197A6CCF1F
-:10AA50007BE5733C27DA69ED81AF4BA24B9EAE617B
-:10AA6000F5E9CFE4227C5766BA96C1BA297FCF8038
-:10AA700075E4B77DF82F709E87F68F79045D52E8F4
-:10AA800031B4F355EB50C341ACEB255B601B7CFF4D
-:10AA9000D22BD9B0122A6F08E31BA02329DA7A3708
-:10AAA000E27CEF30848AE09CCA1DD7E4A879C32BEE
-:10AAB000334B11CE12D05B42049C38BEBE2F5FF7E1
-:10AAC000C4B3399D1271BF06C84E07E8A1ABB1608F
-:10AAD000D755F2787D5BEBC0F7617DDEE33219E498
-:10AAE00040FA55F0DD0E8E1F51E61DD4BB014F2FED
-:10AAF0001D3C3F10EE5FA5781908F7B16ECD18A484
-:10AB0000F02FE68DFAE68947ECF83EFCB21A95CFB5
-:10AB1000CD15904F32D778E82D58D27CEBB90AC8C2
-:10AB20002759982C1D837291236B22E491887CF71E
-:10AB300025434A8F012B4D7356A23D560AC225422A
-:10AB40001F941B63F865D042FFC42BEA9392072839
-:10AB5000DE9FE2C851B44F1D728BA25D8C3BCD3994
-:10AB60005CF1DEB0B85036ECBFE83AD8FDD7CFCABA
-:10AB7000987797F7CAC9DB6EA1F5E9CFCDC2FBFE86
-:10AB80005EE2EDD3F795E3EF0B765178EAA92175F4
-:10AB9000A1E4C1C71E81CE54F67DCDC15F1E7339BD
-:10ABA000AE63DFDFC0AE17F27575BBB118E4EBB76B
-:10ABB000B5F3D578792583DF1FC2EDFEBEE8A58702
-:10ABC0001F2407A3177EDF969A5E20B394D11F2B14
-:10ABD000A79F60E7C0BEAB1CFB13C8B18873983D4C
-:10ABE000A5CADF364CEF7C7F1DF8DFDF93099EABF3
-:10ABF000E3E7F396C3BFE5309D93A5CDF7C37D5240
-:10AC0000F4B917EC4F3807EAA2FD5FCEE07653CDDA
-:10AC1000A1FB538AC2ED64FD39C5FBE43E698BA2FA
-:10AC2000BE394B59DF5EBA25F2FBBEE4E1F21D8B63
-:10AC3000F41E3CBF2945FD3D57319F8AC326CCCF2A
-:10AC4000BB1DF24EE8A3DAA20FB4106FBDBD0FFD1D
-:10AC500029E4CE1C99D4476BBF92C1E28ED30E9BE0
-:10AC6000309FE5BBF6FB318525E60BBEC6F4E7C792
-:10AC7000FD03DA48BCCB99ACFFCBC50FFFF35F20D7
-:10AC8000EEB99F60FEE6651B93FBF9AD5F6834B4D7
-:10AC90001CD68FD14BBE35A8017DD2551DE385FC56
-:10ACA000FCBA9516CCEB1C961DFAC85840484CE6E9
-:10ACB000B69F1B29BDFD110E3346E8D32ED8E3D035
-:10ACC000BAFD5F1FBC6333FDF7D4C326BFE67BAC80
-:10ACD000C74E6D28D47F658CBF1700DD70BD02BEE6
-:10ACE000F3BAFB498F9E017900EB87FA6D990FBD8E
-:10ACF000FF289D77DD3B8CBF21534EBD6F9F1BB15D
-:10AD00006F274F31BE34D2FFC09E5B75B4490FFB35
-:10AD1000B91BF3770BE6CD7C5BBECECFBC211F9F6A
-:10AD2000984AF152B79FDD33D1DD3E08CFB5F6A585
-:10AD3000BFEB766890FF44BDB35D9E0CF4AA3E273E
-:10AD40002EE049ACB98A7B9CD68EFDAF19A027D7DF
-:10AD50001ED4B2648FBEC6D9AA218E88715E7AC312
-:10AD600050CD7EA792CDBF4BE8E7837F8E2B1DCAC7
-:10AD7000CA8D51F41CD5CB3A3BE8E54AF67B0BA7CC
-:10AD80000E269501FC4F49C4EFC073572CCF78268F
-:10AD9000EB0E9E9BF1FE90E421DAC87B0EC53E725D
-:10ADA000D6C15983C08EFCA875F1298A19B22833FF
-:10ADB00007E96536F1A2DD7BCAE64E077FC3741E44
-:10ADC000EF3F650B75803C3E35364682F83DED7FA2
-:10ADD0003389B8AFEF94CE9DCEEE831079C5377F1F
-:10ADE000AF7BDB2AE4FB4AA742BC7A1EB1C23EF22B
-:10ADF0000E99D9B5E44DC69742DED549813898E71A
-:10AE0000B4CC19EB3221FEBBE167B8AFEC819B9665
-:10AE1000FFDED3B7B46B7BF6AF7B24764F8993D933
-:10AE2000FBB5632EFD62369C73A3FB6C89CE677104
-:10AE3000DB21BC8747BDAFEED9DFFC0FFDA3BDF71B
-:10AE400047EE87607DC2EFADDE27F5D8E5C2BE7B59
-:10AE500096E5B91F19FB78E76A5A5FFF6C0CC2F1DF
-:10AE6000E233062FC8EF8BBB0CB8DFB918173AB323
-:10AE70000EEAFBF29C5E1C2D17CF7709FA5EA171DA
-:10AE8000FC01F40EF99D0EEFDDF8E26903FEBEC78A
-:10AE9000CA5FDEB40BF64F5FA43B7EFD22F8F77E5F
-:10AEA0009D80F7019064F6FDED9C1F81BF1C141F6F
-:10AEB000F2F316B41B56BE9C82F24BE0EFC2D326CF
-:10AEC0003C077FF1F8CCFEE007EBD0EC65BF3329FF
-:10AED0009BBD208757EF32A1DD47F49E9760FDE5CB
-:10AEE000CFDF3E7B388CFF610281F574B5BF8CFEED
-:10AEF000C7307EA3EBF5EEF61C26077AF42CCB9B2D
-:10AF00005D18BEA7F915E87F0D11F720B2BCD94234
-:10AF10005962BF3BF950F473E0C73299BD5823FC26
-:10AF200025F1C4980C7CE821ECDEC78706E33DBB25
-:10AF30006733F9F96512E2E71D05BD9DA93D80FE65
-:10AF40001203CBD7EBE35ECB1399367C7FB9F16B61
-:10AF500085DFA476C315657D28FB1DE6C246C7F0D4
-:10AF6000BB69B98EC3F9BF92DCA7607DAB5A1E7E68
-:10AF7000F55D84CB533FF9238C7BDC8C7E1AF22E5B
-:10AF8000839F7AFFB2DC18E271876685DD7B7EE7FE
-:10AF90001F307FE4FC2BB7E0EF942D9603E7E17EB2
-:10AFA000AC4E4BE0ECBDB4DC77FC04E2453DDF5E2B
-:10AFB000717889C9951A58C770C85F715FCA44BE55
-:10AFC00065FCFEE9B63C849FF0D3765D8CBEBF1273
-:10AFD000F314FD8BF989FEC57BDF707C5DD607F22B
-:10AFE000412FFB200E11B1AECBB1817CF8295C5F03
-:10AFF0003ACBE7BE1C47EB117473A378CDFF055C19
-:10B00000F134E600800000001F8B08000000000003
-:10B01000000BAD580F6C13E7157F77679F1D623BE0
-:10B020008684FC217F383B10D2262447FE786902B3
-:10B03000E39A908822B69AC0B48CC138DA42293497
-:10B040008D97C086E8242EF5C43F819A69DD46A716
-:10B05000D2192618D2404D3340AC02E68256C8863B
-:10B060005A77651ADD2274CB5A16AD2149195B85D2
-:10B07000D42D7BEFBB3B9C73025BABD98A5FBEFBDD
-:10B08000BEEF7DEFFDDEDFEFDA00E26A15C0B3B997
-:10B090006F80A31AE8137667037C05CC4F56A6038E
-:10B0A0004200ABE87F099FD7FDF62EE703580DBDA0
-:10B0B0004E2806B8CE776F130580E1DEEF3B550FC3
-:10B0C0002D5AE2BF590AC0697FE4C7CB00C6E9B375
-:10B0D0007832057000ADA3CFB840BF1AC04CFC6DEC
-:10B0E00084D208F2B9E5F7687C25C02C8973DC743A
-:10B0F000E3742114D23A9C97E33548FB5C7214E563
-:10B10000D9C6878B24DCF7AC18AF0021B96F1BAF11
-:10B11000B2E7C3DCD58D10A4E3E215612FC0E8745B
-:10B1200011B80CA433E58492857CFE01F251E4331E
-:10B13000EA84B63E3CB7A6898FF4313D1C833ACAF7
-:10B14000C703C7E4AB29C3E7E5008BE8B9DB943B51
-:10B1500080CF2BEDEB93FAD8C767249EE95793C9AC
-:10B16000477ACB27E3F1B8391F85B840B8E2679535
-:10B170001B716F307107500440BB3C678E9F737B1F
-:10B18000E24205CAED736B02EAD3700EED82E3066C
-:10B1900047FC4DA29C02B07D06AE3DEB1CBE2707CE
-:10B1A000E1905BE6203EF5A67939E4B506D7EDE2FD
-:10B1B0002240E7BAA187D17D5C82C9F1451863546A
-:10B1C00001BF8328C2CFE8120833DA021146974242
-:10B1D0000FA3CBA097D1E59060141E8E4721402786
-:10B1E0007DC77F331DC9634FF3E3486BBE0A915E91
-:10B1F000CF641CBE4938D43E08078D237FFCAC3891
-:10B20000B4809ACBF8A5E25150CAFC3B150F17F950
-:10B2100023DA2D0D62B94417812E105D4C8E8B7C84
-:10B220001E05C941E32650D8B8F97FC4A14E571D69
-:10B230006AF91478344DED173B4CBF1827DD6726AB
-:10B24000ED745292D8D8B217A09CE1F993ED683D05
-:10B25000AF496FFCBBE407F841AC31ECC8C3717572
-:10B260006357318E8F49ADC6B8A1F117411C1F8FAE
-:10B27000AD0C3B1E21BF6EAC76CA00DDDDABC24B10
-:10B28000705E4DF35500C615B495F0E43F5BFD06C6
-:10B29000FE6AF736D98F71A4167A64D2CFED42CC0C
-:10B2A000103FA158803AA4454BE3179DB86E89A87A
-:10B2B000F6503CB6BBE33E0971DFDADD9C03A8EF34
-:10B2C0006ED158EFC27DEEAAA45EF85C4BC3715FED
-:10B2D0005F591717BCFFF9C8F790544B72CCD58053
-:10B2E000E438CDC986251B73DA304F0C279CB04F4C
-:10B2F0004A9EF3A31CF508C901EE1220BBE7BB0D63
-:10B300003EC37D65656497930412CD6705AA09B7AE
-:10B310000F73C22769FDA8D7F0AF936487DAFBD318
-:10B32000DF4BCACF697DEAF3D10F5100DC7F415278
-:10B330005F27793BD23F2DA1BC34B2E0BD5D7A20BE
-:10B34000E9A71C9EBF06F58E2A1013591E59E8BFA7
-:10B35000897914D006E368CFD10DC80771A809AB6D
-:10B3600051273EFEC29AB1102629E27B8ECEED1007
-:10B37000F5A205B8EFA5953744C3CF0A0C3F33F3C8
-:10B38000D0F90BFDCFE71BC3304C88AB8E0B77FF9A
-:10B39000F927C4AFE3B647A6E5C9787AB90B7CB400
-:10B3A000C863CB1B569CD59F75C5051F8D1FDA4002
-:10B3B000EB16BD37504C7A2D1ED0A35EE273FE0F04
-:10B3C000F9861C665D503EE13E4F5D6816283903E4
-:10B3D000749E16622EC4AB938B5CF2D2F824276B5A
-:10B3E00028FF5FDDE81F19B45EF1E4A15E9B4CBD50
-:10B3F000DAFB8FEEF222DDF4CA93CBA182C2C1C97F
-:10B40000F2B7845F8AFF2DC79DC97CCE7ED110A87C
-:10B410006707589FB8487ED0DE6B5FD701FB3FA619
-:10B42000BCD33131CFA35CC392378BD9CBAC57405F
-:10B430002504F93D6DEE253D3C24F77931E6E29097
-:10B440001EEA92FD3436E3074EBCC0FCD25A0FAF61
-:10B450006432DB5BF1F4CC1E943D338957E53197C0
-:10B4600042B8571ECB5148BF4A11D68519DE31E686
-:10B470007795E81B1CFAD36BD3C7823C9EF3DAF9AD
-:10B4800052193328BCB15381BFCC49CAD769C653BE
-:10B49000B370A249443FB8FD14F83124A1B3FFA70B
-:10B4A00051378E3BF702AD80DBF4837C6E0FF131B8
-:10B4B000E253DF5F9D4BF63E65C6A72B97076902F7
-:10B4C0004E69D234904A93630B5F97699FF4D21907
-:10B4D000B679AF3CCBB63FA32E68DFAF2989F21017
-:10B4E000E56363FF74E561DBFADDBE962BE4978BC1
-:10B4F000121B97132E994BAB6CF32170B3FEA1B6C0
-:10B50000C023C7703FDC31EA791D7E593D808840F9
-:10B51000FA35E8003F467BD40F3B6C764FD3D11F02
-:10B52000715DDAB50976C73F97641FCF0F987E50DB
-:10B53000000513FD2089B3E71E8ECC0FFA7111E1CF
-:10B54000EC1563D8724CC22904733268BEF68A00C7
-:10B5500031867B971CC7E733C376BC73DAEC78E798
-:10B56000A9767CF337D9F12D8CD8F19DBDDD8E679E
-:10B5700040B3E357BCA7DEB67E6E4FA36D3CEFE051
-:10B5800032DBFA8762ADB671D9F1D5B6F5F37B9FA0
-:10B59000B0CD579EDD6C9BB7FC2AD5EE0BE29DB675
-:10B5A00075A976AFBEB2C3C6D7B2B386DFFFA79D7B
-:10B5B00037A7D8F95B281BC5DDDBBEA1FD14865F6C
-:10B5C0004E37F252B3B030A190BD173A65B2E93BA5
-:10B5D00052669397E2DDAC4361B30E417817B37BBB
-:10B5E000D8F41339215FA23C5A753DDCE4C3718D58
-:10B5F0001EB944E93834D4D39421313791FCB89E34
-:10B60000337179BC8E03872D5E709C9DC46DA5D669
-:10B610002D64E0E2864F6351962EC9A9F0FC567363
-:10B620009EAB33F2FA0A250D1C13F058643E072A2C
-:10B63000DAC86FA131052BCDFB00F6E520525FCEB5
-:10B64000BB63D1C054FDA47C50607D92CAFAA6CBE6
-:10B650009CEA24BACA9D28A2FA75285B7D298079C4
-:10B660007E849725D667717A94941A25C558D17926
-:10B6700027AC9453FF8EFFCEC2BCCB5F0D6B1E2652
-:10B68000BE5F47F955539EC301F55000F11FE4FC1E
-:10B69000BBAA71EFDBF51F1551FD71098804E6C1E6
-:10B6A0004C9FF2133A47DBBD703AB35B0EEA8779E1
-:10B6B00054E725D63F683B38761FF888983D3221FD
-:10B6C0004EF73859DD01F37EB4D6C4CBBA1FAD3185
-:10B6D000CF1F44169B304FAF3D7B99E1B2257718C1
-:10B6E0001C99CCDF589FF46481A76A1FE9A454CB4E
-:10B6F000ADF3E9B9755FCA173E4B5D6C16CA33F4FA
-:10B7000029FA458B6EC91D62F7B97BFB4F1875E4AA
-:10B71000FEFC355667937A1BFC07F7A6B3FA32B8DE
-:10B72000B7B0916892FF08E3BF36F2AECD4FD66D49
-:10B730007FDFE67FEBB53FDBE6F5AC31673EEAAF96
-:10B740009FC96BF93AE277EBB42B44F746B4DB358B
-:10B75000B28BC55F3F306F099DF7DFF5FC1BC377E8
-:10B760006067021C73927ADED8799D8DF59D3AA3AD
-:10B77000A97A5AF74C8B8A17A1D481F619E3A6C986
-:10B78000470293CFD91C34FAF08147B31BA9CE0EE0
-:10B79000148A0E839618E3BC3AB7316E594A74D4B2
-:10B7A000E9D943F7CC010E140EFD610DA7BCBA1EFA
-:10B7B000F97E3B5BFD98FCB363F3588503E3A1A3DB
-:10B7C00052FF0647A97FBA7A87F4E7B0BDCB9BC189
-:10B7D000E42CA1BE6388D72A38CC0515C19C15D4AA
-:10B7E000970F4DD346A812971C99618C45233E4272
-:10B7F000C17FB178A8F1ABFF263E1F70429CFC567A
-:10B80000FB25173BCAFC4D175BBD2C9EDAE8DE45D5
-:10B81000F75DBA6F8CA619D419E4987E620AA55E0A
-:10B820009D682868E4B566617F0947FDC1411750EE
-:10B830003CE0390AF515DA7957EC288EB35176EAEF
-:10B84000537E2D1AFD7CD5AF5C71CA1B1BDD77982A
-:10B850009DF28201C62FAB183317F2C97AD1158B2E
-:10B86000927C7AA26805CAD7E3C4FE85E2FA1ACEB2
-:10B8700023DF5B07E61DD937C11E7941E37E084F00
-:10B880000118F3398769BEBD7FF006E5918B01B5DC
-:10B890003088FC0779294479A4DDF7A648F9A73256
-:10B8A00028B17D282FD317F3C1773986B3DBFF0189
-:10B8B000FAEB3A4C3619747FE3D5B9C15ABAA7E806
-:10B8C00022F1438F60FDDFFDF4BFB521F1C372A407
-:10B8D000235EB988CEB1CE45392A898FA5B72547D1
-:10B8E00092CF83FD7AA37BCC16BF375FDE5D4271BA
-:10B8F0005225700C9FD4F52D262E034EA3FF4B9D91
-:10B900005F4FF6AC9DC23EF3007291BAA661AD43A3
-:10B91000BA927042FC6E7D0DF5617D8BB280ECDBDE
-:10B92000DEEA91296F59FC918FFAFA03CEF92427A8
-:10B93000FC25B2C3E6C8F7CE5C9592F3E87FCCAEA7
-:10B94000DA01C35FDA2FBC7FE3793CE5999FCDAF85
-:10B95000A63C6DED4FC579C42BB1F73B4F087186FE
-:10B9600023E2BB9AF8F75DF95D36E162E1FC79719B
-:10B970001D2D4C88C47FF4F0DD2209F7B79FBB7CF6
-:10B980009DFCB6DD7CBF00A7ECEF0D102F8DEE9374
-:10B99000F7EA08E5D6D96C9A9BD8B7B9ACFD050E85
-:10B9A000FB7E6CD0793CEF94796F394BF9628AFB5E
-:10B9B000EDA904CF4AF4A95CEC0BA9FE60BDA77AFF
-:10B9C00063D5FBADEFF22C0EB60680CD935C6457C9
-:10B9D0004E7F8BD51FEBFD4594C3BA8AB8758AEAB2
-:10B9E0000BE497A076B17A24CC46BBE2BEBEDF2C36
-:10B9F00033EF69467DAB35EB592DF121F9CB335847
-:10BA00009DAB31CF0DB9B17F0A52A9D0CCF734E646
-:10BA1000FB8CBD6FD9EE77FF01E91E35E2601400A3
-:10BA200000000000000000001F8B08000000000064
-:10BA3000000BFB51CFC0F0038AD5151818D6293159
-:10BA400030DC5266607055616038278F90A31556C0
-:10BA5000E5A04CFF0B4606865740FC0688DF319276
-:10BA6000AE5F4B18C15EC9CBC0A00DE4D7006955CD
-:10BA70000106062E205B0788F701F9F780F81510FC
-:10BA8000BB08313070F331309802B11810EB02E589
-:10BA90007D81F4373EECE6EB09E3B7FFB9002A5F9E
-:10BAA000521095CF20805F7F97207E796921D2C385
-:10BAB000C44E9DFCF868A240EF40E09B0CA87C0BB4
-:10BAC0005906062F3906861E7908FF1A92FC3CA0FB
-:10BAD00098A52C345CC5816907C8BFCC80DD5C1992
-:10BAE000A0BC36507E15D41C00DF43986568030067
-:10BAF00000000000000000001F8B08000000000094
-:10BB0000000BE57D097C54D5D5F87DF3DE9B2DB384
-:10BB1000852C842D4C58141070085B1094C9860134
-:10BB2000020C8B881675588410208980FD51B51F32
-:10BB3000139688967E0DA2965AB0030D82FDB00D25
-:10BB4000183560A0C366B1451B5C10BB7C1D16D9BF
-:10BB50000C2404A5A3C5FADD73EE7D99F75E664853
-:10BB6000B4FEBF7F7FFF7F102FF7DDFDDCB3DD73F9
-:10BB7000CEBD910D76424613F235FCD07499400843
-:10BB80004989A6F4E79F5FA71232C94CFF2512929C
-:10BB90002FDA081942C8441B099A689D89A3E8C78F
-:10BBA0006442DEAD128222B4A1F502C3082926EC5C
-:10BBB0006792446A85DB0969CE7AB562909B10C1B1
-:10BBC000EB25CB3369EA769199908E3AF085E020A7
-:10BBD000C4996520A40F6BF335FD9BE8B5625F4AFD
-:10BBE0003EA9A083269FE2EBACA9DF71460F4D79F9
-:10BBF000277F3F4D7997A24C4DBE5BD91D9AFADD48
-:10BC000097E768F21981719AFA3DD74ED1E47B57D4
-:10BC1000DEAFA97FEBC6D99AF2BEC1624DF96D3B8A
-:10BC20009668F203AA1FD3D4BFBD76A5A67C50E8C0
-:10BC3000694DF9E0A3CF68F243EB5FD0D41F7E7269
-:10BC4000ABA67C44F8579AF29117766BF27736EDF3
-:10BC5000D5D41F1D39A8C967933F68EAE79ADFD793
-:10BC6000E4F35D7FD6D4BF3BED8CA67CACFB534D9B
-:10BC7000B98207E3FB5CD37C9FE0F987A69D447CF7
-:10BC800014D884184919A6665289A99554636A2361
-:10BC9000F5989E49F7DF8FF8F962A08250BC5B15DA
-:10BCA00068FAEF249ABE9BD5D3E9EF0FBD7909A1BD
-:10BCB000783B91754D269A6D2191E299C94C0216F7
-:10BCC0008A0A8E08C5B7248A771182A92B42F16DA2
-:10BCD00030C5BB8819D30E910EF83D29E2C2343924
-:10BCE000D219BFA744D2304D8DF4C0B463C48D695E
-:10BCF0005AA41FA69D227D30ED1CC9C4765D221E6C
-:10BD00004CBB46EEC0EFDD225998A64772F07BF798
-:10BD100088175377641CA61991024C7B44A660BD1A
-:10BD20009E111FA6BD22F7E3F7DE911998DE129946
-:10BD30008DE9AD113FA67D22C598F68D1461DA2FED
-:10BD4000B204DBDD1629C3B47FE431FC3E20B21C13
-:10BD5000D381919598DE1E0960EA893C8DF50645F0
-:10BD6000D6629A197906BF0F8E54623A24F2027E87
-:10BD70001F1AD988E9B0C8564C8747829866457E15
-:10BD800085E988C80E4CEF88ECC6762323D5988EBB
-:10BD90008AECC5EF77466A31BD0BF02D09F02E8491
-:10BDA000A937F27BFC9E1D398A694EE43DFC9E1B3F
-:10BDB000A9C7342FF227FC9E1F3989E998C8694C1E
-:10BDC000EF8E84312D885CC2746CE402A6E322CD30
-:10BDD000D86E7CA409D3C2C897F87D422482A9C238
-:10BDE000EF4896DC1056F0AF07FC7FA6EBDC6D94B5
-:10BDF0002F11BFE16B9A121BC58311D1FAFA94720D
-:10BE00003BE49332C5AB048ADF899417023F9C5808
-:10BE10002604EFCEA0F8911C3E0C7939CBE436D144
-:10BE2000FC03A44906FC25A4DEEE1B40C88111E7F3
-:10BE3000BB8629BEBE9B12EA46911B7E90DFCA30AC
-:10BE4000A79EC06F1BA430FD3E31F9608ADF06ED6E
-:10BE5000296D64027AD3F101BF293A025F7E402244
-:10BE600001079DEA71E86104D60B99687E6621F1AD
-:10BE700066D2FA15234C3382749C8A4C5F918FA64C
-:10BE80003FCEF0CD80F4F7403C74FE87787A9C1862
-:10BE900030FD32DD85E9CC477A337ACAA340ECD451
-:10BEA000361C1E4865ED88AD291DD6D7DE7612A159
-:10BEB000ED8646EBBF4C7C1FC2F7400EE953668B04
-:10BEC000D6A3DF4F42BD18DFFF1CEB7BAD813202F2
-:10BED0000AFF400763701BC827E2764E867999DD1A
-:10BEE000CE29F6F8F37A7285ABBFD44B3DCF20CE86
-:10BEF000EF4981CCA866FC256DCA00EC1FE561C046
-:10BF00006AC1FE450E7FA5DD67004FDAEE3D8BAFBF
-:10BF100091C9537757848BCDD52EB8D076D7112EB3
-:10BF2000126D676F7FBBF869258333F1BA711EFC10
-:10BF30007BA9890404BA8EA66DF6E0D60CC06137E1
-:10BF4000F2CF221767A0C9141854AE1725C21208E1
-:10BF500039BC3F2164A0F573B6D9B7821ED09813BF
-:10BF600078DE0770DE2A936DB4CACAFD3F3AF173DA
-:10BF70009ACFD9221313CD2F48786E18A170BB55D4
-:10BF800010D8F801EF815EB47F3F517EBC02F43FD0
-:10BF90009FB0FE1B054647816D4E84EB85BCAA8A87
-:10BFA00091340DEF5B5C48281F3F4FC1DA89E2F7FF
-:10BFB000022B9120A51CDC88F009C867C38A7C414C
-:10BFC0007A96A279B1757E3EE415FAA7EB5E1094DD
-:10BFD000A379FA77E10E6D5E052FDCF7268B1CDC6A
-:10BFE0008A78D585C1478197B70B831F87579E45B0
-:10BFF0000E1892115E41E0034EC18D7028B2C82127
-:10C0000091F65344E1082458B4EFA95480D3C21DDB
-:10C0100016D759D5B88BAB1335F9D2DA4EAEB32A51
-:10C0200039DA7CF4970EA0D3256906D759CADF1AEE
-:10C03000567893CED22DBBB2A20053053F16576758
-:10C04000B86C9A7EB4F9E64AA180E1B7DB396D405D
-:10C050007C3C5B9266749DA5A47A690793B797565A
-:10C06000985D304EC30A978B8D9B86A902AF45CB56
-:10C07000AD585F995FBC7EBFEBF9115243CE9881FA
-:10C080009FD3B29EF1EBC7A527E93323D2499D7C0C
-:10C090001DF0C64CFF7E6D403CC2BCD26F69B51826
-:10C0A00030DD0EDF776AC6A3EDDCE754F2253EDD16
-:10C0B0004AE49C0A2F97420748A766DC673FEDD108
-:10C0C00049FB6B946C6B418F9AC0F1A714EA517EC7
-:10C0D000B0D81C36FAE9A7CB356C3FE28D7369C541
-:10C0E0008E2EC0D78ACC9546605645D57DF3809E6E
-:10C0F0002ED7AC4A05F9B2506CFEBE2F46FB1F2B63
-:10C10000741B949BB4F232C8E749FBD5D019B1B582
-:10C11000AC9BE61B0C74285BEB7E7F2A30B953B2D4
-:10C12000F3F8989174FE25B5578D308F0982FFA7DB
-:10C13000424A74FD02AC9FF653BCE39411D677419A
-:10C140000EDCF278C64DE0D96A9EB6B47309AAF93E
-:10C1500005A82249E9757616A757E2BEF7CF943EA7
-:10C160002FFE41264FD379901BB4162D4FE7A573B0
-:10C1700089CF01F09A5DB310F9CF45E03F208749A0
-:10C18000E530C08FCBC45000EBBB4CDE730C56C106
-:10C19000EFA060E4F0A1AA2CE507261C0AE1D6096D
-:10C1A000F895A9A8A25E1C08DFA500E74BC2D7C876
-:10C1B0004F8202F2B322F63D40CCE5B88EB58C1F1B
-:10C1C00005E81FC83F5CA9E54FF3376AF3F3C8944D
-:10C1D0005489F29779CFCAB447CADFD4FC8FC2EF33
-:10C1E0006581C9DDF9A4ACC245E7BFD948F789CE5E
-:10C1F0007FB68B485DE8FA16BFB179D82C9A7F5B81
-:10C200006072ECD20A3AFD5B683F1DD8FA8B970743
-:10C210008DDEFEADD777A666F0F49104FB63F2B134
-:10C220005891BFC42D0D436E4995DCF8EBEF5223B6
-:10C230007A2D0EA847BFABF8F39CB5DAF5B5B57EFD
-:10C24000FD7A097906F1AD78C7640278A6AC47D9C2
-:10C250002F653DF20EC11B8C4107618EAF0A5F6BEB
-:10C26000E2F053F48ECF75F92F75F9AF757905BFEC
-:10C27000654EDF14EF3F1786023D378D6178123629
-:10C28000B2F30CAB678CD6FBF266F54C9C5E68BDD6
-:10C29000AF6F56CF12ED4F32A4B4AEB7F88D575EE4
-:10C2A0000F50FC2EFECD730E42F1F1A25499EAA17B
-:10C2B000DF176D5BE300385D90020EC09B8B41B1D0
-:10C2C0002016BC46180445DFB00974DF4B14FC1F70
-:10C2D000553E11E4FBF56DB2EB69BA2FA53B4C213D
-:10C2E00013DDEF929A05856420E64FB1FC93570168
-:10C2F0003F4A6BE5D3EA7D2DDEFE5CAADB8EFBD0E8
-:10C30000C5003A30097521342DA9FA640CE8D1A58D
-:10C31000A409F159DF0EC687A31DE5D7B38CCED68D
-:10C32000E5CAB9B1947D22A5353FBA0AE7C65222C3
-:10C330009D56E35111E032D5F3FA19ECC9705E2035
-:10C34000C3C970E02B0A1C483005F9F2AA977F3A5E
-:10C35000F0149D4743D51F1C820A3E544342B83413
-:10C3600057CFF95BD24DE4C2158A9FE41675BB2006
-:10C37000B673D7D20974A4D93A962E92438E9114EB
-:10C380009E8BB6C81E8A9964D12BBF7CE9054A777B
-:10C39000E46393A73785F7C2578E9CB883E617EE00
-:10C3A00092930BD9326C426A743F4AE95FB0CB2852
-:10C3B000F02F7EF588D13D807D7FA243741F16EE5D
-:10C3C0003A6024035AC32DB7FA80316C8BB11FD564
-:10C3D000A7C6803EB3EAE5BF1B61BF2FEE1748C773
-:10C3E0008CD6ED8BB61C41FD05E084FBC7F7A76535
-:10C3F000BF5AED5368E2DE2158CF05FC3ADE3ED944
-:10C4000041560F453CFEF55E3A7ED19F4C1E587F4B
-:10C41000D1AF973A601DE7A53286CF9BD7A47AE9C2
-:10C42000B8457220D58529FB5EF4E2A38867F38FB7
-:10C430003F8A7A19C58F4E069419814EB0BE873750
-:10C44000DD83EB9B47FC886F459B455F10F880447C
-:10C450000A76C5A087DF707A38BF95724ABABEF3F4
-:10C46000C01F41CF7D4FE4FCF111D4231FE56BA524
-:10C470009A0CE63F37B37DAA301814BB9C5983A7AA
-:10C48000554F221FBDD4CDDBD1D51FE1A0F04DE427
-:10C49000A7E2F1FC8E6C7F18FFC57614EF72E13BCA
-:10C4A000D4AF97BD96819A769C5FB2F197F1F1E98E
-:10C4B000BCADA07F9C4F657242BFBE3F1914FE48C1
-:10C4C000E5AB0ABF5474CDE8BCEA2946D70A9D07FC
-:10C4D000271740F9671F30FA8176207FE8BC421D9C
-:10C4E000B1FCC03401F980898462D17395CCE959DB
-:10C4F0005B4E3934EA6F74DE92E054E309EDBF031A
-:10C50000C21FF59279CFD2762A7DBA14C6C37AC6F5
-:10C51000E8F78C28DDCEE7F4FF2BA0FF8428FD93FD
-:10C520004D29ED3A9F2D92832FBD00F44AE933E067
-:10C53000067A957DB0EE4F771E3A713FC5EB4FAB53
-:10C54000153AD5F24D3D9D16ED7E94007EEAE9F454
-:10C55000D3AE6524269DD2EF31E9B46BF87F856FA9
-:10C560002A703BAE831BE583BFD8EB8E0F3F3D1F88
-:10C570002C35B863F241FAF30119D61AEF147C5343
-:10C58000F0ACF8BF1677077ED3828F0ABEB5E0A362
-:10C59000826FFA756AE1A62FDF04FC46A51FC82B3F
-:10C5A00049C04EF7B9699F88E7C4467793A3031D36
-:10C5B000778D853C047A76A38BE71359BE29C5583D
-:10C5C000017C41F9DE642133003F1B7D4D8E449593
-:10C5D000FE7CAA4E74B8697938480A62E9D594E3BA
-:10C5E000E2F86112AFBC1CE1972FDAD2970F81738A
-:10C5F00095E801DD6D6EF9BD0E305934D6F59C34E9
-:10C60000837E7FF86D116D1A8D56C74098173DB720
-:10C610004B9D287CE7F07DBE4002CF8FA2EB9A5362
-:10C62000C7F4E2B9EBB4F098675B66043E43F5CF1C
-:10C63000281EA8F045F113146DD296179375B85FB4
-:10C64000C53AFCF1F3F34E2791E3CF2032889F37B0
-:10C650000CD0DF12CEA7F2C5FE936650B8371E1578
-:10C660008989E69BEB445201EBDC290409D0712057
-:10C6700005F1B084F207A23A1736009E19E3D36F92
-:10C68000C36B7F1DF638ADB2E8F53F0FFC394D1B8B
-:10C690005EFFF8963721FFC647E97F26ADEBE7EE50
-:10C6A000FFE241E0EF8DFB4D04ED24FB7F97FE3868
-:10C6B000E4F79A3C68E75869F2A27EBCDF1EEC0DF5
-:10C6C000E5DD987D69D5BEBF0F0CA3BC598DFB94E9
-:10C6D00027B2734473DD3FFE5B488694AE0AE4E8FC
-:10C6E000FE04D4AF4BF75A8270E86CDCF7F7617E3A
-:10C6F000DB77B79E1223F123FED9C98CDD80AF8989
-:10C70000CC9E56FAE6885F96D3F117D71C30CEA19F
-:10C71000E5B9BFFD6A20F095C6DD4C3FB822875FC2
-:10C72000241E422689CF95CB74BFAE80AED699F237
-:10C7300025F14476C0160B2E0C0E8D140EB02E0A69
-:10C740009722E087F1E031EFDF161E571F84F117C3
-:10C75000D50D2762861A2E82977DB707CD02AE9F30
-:10C760007DDFFFF781C0773FAD2E47F9DDD6BAD721
-:10C77000C0BA53FE5F5AB7106ACFBAABFE6DD7CDC1
-:10C78000F0BF9FC8E4919E0E5AE3F91BDFC7FCAFD0
-:10C79000ED1E9C6F3BE9FFF0BFEDFABFE5BEEF1663
-:10C7A000D01FD7D6BE9FF9B75D775BFBFE36DF772C
-:10C7B000BB0BECBD8DFBBE4A27AAF5B7B56E83F463
-:10C7C000EFCADF6EBE6E45EFA93794B986D0F97D0A
-:10C7D0004C2AEFC9A0E91FBDD792E1384A69C017BA
-:10C7E000EBDC9029B1738309EC4C50F11E41B11779
-:10C7F000D56BFCB85D8B50CF98E8FD31EA07442A31
-:10C80000ABCFA6F5EB73E6789EC61A9927FD909FED
-:10C810007627CF6BCF531373C61F05BDEEDD723A7B
-:10C820003F885BE826B9A8A644267945D403698ADF
-:10C83000FADF87E963B0DEA42CED79E23EDD79E032
-:10C84000DE19DAF27B78FFD3C9332960779B3E97F4
-:10C85000D9DDEE25656B5CAA7DBA47D78F4322DC14
-:10C860004EF2EDE037B7057E4B101E245BF46C23CF
-:10C87000ED801F61F0AE9F3628087618227918FCEB
-:10C88000A62FF6A01D949F3365DE5EB6ADAD07BA48
-:10C890009589F67CA99C13DB8233E1E74FECAF4727
-:10C8A00014EEB257C4F3A7AA5F848BB21FDF741FC4
-:10C8B00094FDFBB6FB310CF62386FF6C81D97C0F0F
-:10C8C000F82FCC7D043CB74F5A27621C8CB9BF802F
-:10C8D00070F465C9E8DFF9C4E01B068A73E1E0E1A2
-:10C8E000258FB16E3D009F051C8EF34819EA9DE42B
-:10C8F000C6D75F8F02BF114286967B099940CF2130
-:10C90000F34609212B5DF77C89049C9960D714C8F4
-:10C9100069B55D33A8CDC3CF5DA9D17EDAAA1F8FDB
-:10C920003F7CD7E9DF283F3ADD8B9E572095707812
-:10C93000497D4E7CA88EC1B1749110EC817814921F
-:10C940007D2ABFCEC71CAFFFF6C460E473D93F1980
-:10C95000E0C4F3ABB71FEAFBA55CDF6F0EB89D60C8
-:10C96000AF69AEEBE9047B4CF3D15C879A2F2AE9DF
-:10C97000717E8E7C7F8519D3C63CA15284F31669E3
-:10C980009A887238CF4280EFE8DBED9114BB4B19E7
-:10C99000F333D21F7118EC23FB994F9B3A3BA8F657
-:10C9A0006DDD848BD2C0D6FB003FA7557E927F15EC
-:10C9B000BE706E05B81EB784C7F862ACF70F1C7E58
-:10C9C0008507BF30829D604A5D860C709992276A08
-:10C9D000E26E0E49FC3C35980C8679151E1CEB184E
-:10C9E00001FB7254F458287C4BEBAE1AFD31FC6D00
-:10C9F0007A7842FF60173E237BE6013CCFFCD842A9
-:10CA000002941EDEE1FE1F5AE405FE45BBF2827D64
-:10CA1000EC0389F915FACACC2E3EB5305B4EA1E382
-:10CA2000F6AF710D0211D399D7EF2BBBB1BC0B6FD1
-:10CA3000A7D4EBBC88D53B657495C45AFF04235B2F
-:10CA4000FF7CE2F97E96F0EFB76FD93FB187724075
-:10CA5000BEE709C8475AE33541FA682E1082207FA5
-:10CA6000E11C8BF94201E5FF3B06561E98C2E4A586
-:10CA700082F77A380B3283B3327E86CCF0D92833F2
-:10CA8000F8287056E0AB9FAF529FF2ABD16AFBCA59
-:10CA9000A4DA41BF06FDA4A44E7081E9AF440A1B8D
-:10CAA000810E4B6BD7CBE02FB8CFCDFA25926FA07C
-:10CAB000DA5FDB5796703E873247A2FE786D1DD352
-:10CAC0008FBD73AF3A400F7AC7E0F9E348A0C7774C
-:10CAD000458C278807C73FAFD8312D4F52F79B8130
-:10CAE000F39CBA285B0673D0F7161D903BAAF0A9F9
-:10CAF000AFDC01CB95EF9D17B933E13B1D0FE7117B
-:10CB0000F84F13D946BBE85F5D9F9340CBBF579664
-:10CB1000C8F0B0A8FA8011F319585F194F19474FA0
-:10CB20004FD30A1334F939B9E1AE009742536899EB
-:10CB300027069E1E96153FC93794135E8AB703FFDA
-:10CB40007F901357C77863C06D83DC4A3E748C2591
-:10CB50001F9694BB3B02FC97ECEBD9118863C9DBB1
-:10CB6000F9A9B1E4C3872B983FF023CACF206D9C6D
-:10CB700046E5C3ED2AF930CD82F8A16FF743B99DA0
-:10CB8000F241D9AFFF653EF321C88718745D296B68
-:10CB9000E5C3F4BA59281FA64F13895B658F7B52F2
-:10CBA000E67EAEB8F2213BF53ECCCB9E841878F3FE
-:10CBB000213F97005C218571404EFC96F37DBDBC02
-:10CBC00088C7CFA71805EEAF6E839FFF5F82B3C201
-:10CBD000CF97D0F30BE881ADF19020BF5E721FE5D7
-:10CBE000E702E023E3E74B1EE076491D7FF5017F76
-:10CBF0001DA2E6AFAC7D899FC983D2DA8C9FCEA4FB
-:10CC0000E5F757CA1E33AD7F7F94DF0E53F3DBDFAA
-:10CC1000727E4BE19CEE8AB1BF33662610B7965FF9
-:10CC2000F5023E7566D0EFFABF0A78FF8E887EC4A3
-:10CC30004FB81C3F36E87743C07E9E6C94107F3E11
-:10CC4000E1FCEBCA8AE0B43C4AC7B973993EBC78B0
-:10CC5000A7887028A9617A5E492F6BD04DF36332A3
-:10CC6000BF407FE0C27DCC1F48015598ADDAC78533
-:10CC7000EF842BBA40F91601FD99F33C0BD18E4F8E
-:10CC800036323BB199FE61711D5EB4232FE6F05A36
-:10CC900050B705EDCD0B825A3BF4E25EE32EC2396C
-:10CCA00040E1BF0B77E8CA3D4FA1BF6231D89B5529
-:10CCB000E70F91EB0F0F8BA1FEAF426CE71FD9B9C5
-:10CCC0004ABFFF4ABD96F517FD8BEB3F4ED73FE4B9
-:10CCD000BB5F7F7BD72D1B39BD679221401F9F18FB
-:10CCE000BC48EF81DFD3F5D371E6AEEFDD511D67B0
-:10CCF00094C4E9F21D83BFA213D42B11B0DEFC4D06
-:10CD0000BB8EA4D2FCCC6A3208CCF4F3376AE5625D
-:10CD10008B1CAE71A39C9D59B64B98DD1FE04DCA8C
-:10CD200000CFE6649AFCE04F3D6E6942FEA5E0DD6F
-:10CD30009D4686CF23F9B8673A37E5E139A25670A8
-:10CD4000215D842CEC5C41E16FA1F94323FE3E861A
-:10CD5000C31BED31A5B56C7F4AE97E005D8DA9E36B
-:10CD6000F91D4C0FFB1E9537E80FAB3B2043BB2250
-:10CD70005A3F09F94D3F8D9F0BFC73D9A9AA7DDB62
-:10CD8000778AE1ED36C14362EC5B1FFA27E6BE7D90
-:10CD900047F8AAC0E34E23D7E7F9FE1DB7D4170E14
-:10CDA000463F94E0D90A95EB12D18F72B6B227EEC6
-:10CDB000E3788EBF7ABC06FDDEADB2274D8689438F
-:10CDC000BC658105E3DC70DC1E4CFF51F313FDB93B
-:10CDD000B994D4A31E3341F0FF5552C5B54DE7F1C8
-:10CDE000278A9F5655EFA7F24DEA91349701F8E450
-:10CDF0005225DE12E28753316E097F0E751BF6D184
-:10CE00004CBADE6B6B450FF87FEE35B84F8C02FAEB
-:10CE10007D5A268097D78EC95EA6772620DF9DF59E
-:10CE2000CE19194C21B3284C60BF67FD90F1D73360
-:10CE3000D019FDF6272AB7BCE0AB27D543217E7871
-:10CE40009AE740BE9BEECB3D438EAF013FDCD45C06
-:10CE5000D7891300DFA74402F03DBD3617CF274B1B
-:10CE60001F1110AF4F523842FB7BA6659C3841C75B
-:10CE70007D606D0AFAD5667A8FE4039ECD9964B71A
-:10CE8000817F6D7C1F91F855707C80D4A39D626674
-:10CE9000D923F7C07C8BA81C003B6B51DDF1FC8EC5
-:10CEA00090DF2478DCB4FFD280DFD8916E61FDC6BC
-:10CEB000AB46B0B7CCA3F5607B4A37B17AA55582B3
-:10CEC000C702F858B71EF9CEBC2A81B8A03ED5F7E4
-:10CED000CCACDFA099F65BBF89B6A7F9F9D01EFAF2
-:10CEE000AD4A9C0E7EB4D263226B9F55FE16F0A510
-:10CEF00079B41D2D26F5558F607F0B3609248DF6EC
-:10CF0000579495F19F59D0DF31D903E51F1DF8994A
-:10CF100011E6FD201DAF13ED7F8E18CE87FAE47168
-:10CF2000C1B50DED4D2C4EB691D301F9A013A32F31
-:10CF300081E7B91EA8C8C3F78D3D109FE62D2FAF1E
-:10CF400080758503291970042AADBD6A04BDEE2CD5
-:10CF500085B39FEA6D67781CDBA1C0196358C5A72C
-:10CF60009A8C3DB1FDDCDA6CA4EF87890FFDDDFE04
-:10CF70007226874FADB10405D03F6417CAC9436B11
-:10CF80006E7D1ED67FE51519FDA357BA85D11E7B90
-:10CF90007E934C02748EAB3689C837CEEF64762010
-:10CFA00071B38CF9F98F1A317F68D3D431C00FCFA8
-:10CFB00053F8031EE66ECE37427E3EE5EBA618FC24
-:10CFC000639EBB98F10B1D7F98BF514BFFADF8C519
-:10CFD000B2318CBFEBF8C1E2AE1568E7D3F38952EA
-:10CFE0006253F84326E4EB439D107F4B8EC904F453
-:10CFF000B912C9F5E046C09B9916F01453BA081D42
-:10D0000001BE762D28B803B4FC7B0FED190AF03B66
-:10D0100007F006BA589784FED479C1590857259E5F
-:10D0200070FE462D3E2BF14BF7F945E255CB81A220
-:10D0300004E255D5FBE887142FE9780FD50A418B18
-:10D0400000F9536F3D3A04F32EC0C392E55C9EAEE7
-:10D05000B323DE7EF483AB6B002F1F7C42C0F993B9
-:10D0600080BF02E44AC946C10D76CCF94FB0F6F351
-:10D07000697BC0978F7EC6F087E2B11BF0BC64D39A
-:10D08000FAB7B07E95E086FE3FDA320BE56F51408D
-:10D0900024585E750AF5632A07300EE850404C05A7
-:10D0A0003C2F596D72C13E2AF8A2E0DF2999F9EDB3
-:10D0B00089D933702A6DB7C5E8C675EBF14E9C91DE
-:10D0C00081F855BA5346FC280D307C3AF58A8878A9
-:10D0D0007868CDBD883F57B60971F02FD7D809F0D1
-:10D0E0002FC8CA5BF0EF6581E31FC3EBF3CB183E9B
-:10D0F000E64239E0DF6B5C3F25C4A6D63B14FC5307
-:10D10000F0A92DBC6B2597E2E01BD58DA7C3BC967B
-:10D11000AEB1E0BC732BF64C5F8E7423A37F3EB799
-:10D12000E207A940A7F3241687A1C071B1C4E27435
-:10D130005ACDE3D97263A7F6CC47378F0351B9981C
-:10D14000097211E24A42749CDFEDFC25C6AF5DFE18
-:10D15000D5298C4B5CF826DD775AFFCA4E3B09A1D6
-:10D160003E1D44FE525C23625C289142C3A6AAEE97
-:10D170008F28F1160B7F6347F816EF36050B69FB16
-:10D18000E2D7CF0C447FF8CAA6B7807E02BF1298C0
-:10D190005D3E101E3815E22A2516F7A197BB234CD9
-:10D1A000CC5ED3B0276106E83FC28E03E84F2AAEBB
-:10D1B000BE5736A9EC931E938CE3D27AEC9E0BDD1E
-:10D1C00077F023C2FC260F50CFAF9CF5F732A39B1C
-:10D1D000E25A19F5A2E21D5BD0AE57BAE32AC6BDEA
-:10D1E000E6FEE61507C0A1B456D4C643ED104326AB
-:10D1F0008CD7124F99187FD2C42595D4B07B1925AE
-:10D20000D53CEE471717B3F037FB5E0F50D02C7CA0
-:10D2100075BB03E8E852FD3607C093F687F14493E7
-:10D22000B2E2C41BB5156754FD54CC38A34BF00FC4
-:10D230008A200F9AB4F1996407E35374D787F9628F
-:10D24000D833157D65E12B9FBF0871AF0DBB3F7DC6
-:10D2500011E6BDE89FD75E84B80DB2DFE202FDA102
-:10D26000F4571F62FCA0D26EB9899F7F5EDE8E717B
-:10D2700097573E36A1FE7765DFF974D00FAEECFA12
-:10D280002215E22997EDCB47FBC3B2D7723B921828
-:10D29000E75B2505BC0CB623EE53BF0F876AC4902D
-:10D2A0008DCEF3F24913D2774BBC58F562167FE767
-:10D2B000E671623B63C7D52AF14D25355327DD0959
-:10D2C000FCAD86C9F19678A7B6E2C33EA0FB797B98
-:10D2D0003BF66D278FFFD3EDDB65F807DD9FE74C4D
-:10D2E000DAF8B0CF6B1EFEC50B505613FB3E9942C9
-:10D2F000C76DC14B89DB9D63F2064D4037BBFF0B09
-:10D30000E3F060BF0ADD20E73F4F07BBE505B90941
-:10D31000ED814DFB4C2E88DB2ADEF711D2C795D765
-:10D320008E635C2CE1F1B35748CB0F8B77E43689E1
-:10D33000D22A3B8B2BE37087B833B703BFF3F832A5
-:10D3400086B74ADC59BC78B30F4D3DF8BD0B1617B4
-:10D35000B7D85D6F04F8ABE3D0842CD8A7539AF804
-:10D360003D65DDFAFE5C0087E1EAB8C978F17C5CD6
-:10D370001F6FD927C687AF6CE171942DF19184742A
-:10D38000CD84781F26EF4A83C24724063D2A719335
-:10D39000F57A7A0CB62F5EB2EDF97E3B781C32310D
-:10D3A000FB930297861BB1F9F1A79CBEE9B9E49201
-:10D3B00049752FE5217E2E51E2C894F9565433B9B0
-:10D3C000DBB083E9857A7A2EE1F676FD385FF0717D
-:10D3D0004A6A0F0C04BED370700FC73786CF253B47
-:10D3E0004F19039C3F07D5FC19FA8BC14F4433EB0F
-:10D3F0008F9E6363F657BAF36ACCFE2E49DE7B61DB
-:10D40000FE97EA999E71A95A2C08C6E8FF32973F09
-:10D410002DEBB61BF15C253AACC87F96D9B34E3ADA
-:10D4200093213562FCC2AA721EEFF0434F1AC079F5
-:10D43000957D1C81F9AC01F8A8CE99B2CB4F40CFB5
-:10D4400091D37C43E0FCA4CC572937261B4850BD20
-:10D45000FF5200EF474EECF17709E44BFD0AEDBDBA
-:10D460008E7AC9752489F6579F2778409F6D8D67FE
-:10D47000DAFE277B458D3D0C6CCFB0AE668F01F791
-:10D48000D36E08B9681562B7D4A7E141CE4DDC521E
-:10D490002A8674A35FFBE9153BBAC13D2B07F1084F
-:10D4A000506EF7B4DC6FC1FE9C4417671D201FC08F
-:10D4B0007D481B67264EE23A0076096B1FD207FCB7
-:10D4C000D62E62F5C0FB0A1BF8BDC775763FCADBD6
-:10D4D000B874E361F75E143B91334BD2DC8B49F4B3
-:10D4E0006AF349BA7B900ABFC62B7414FE63F8BB7B
-:10D4F0000F89F96CFD60AFEAAD9A6F620AF184A002
-:10D500007C820DE3996D36363F65BE743EC80F28A8
-:10D5100098D87CFA8703A087D379E9E898E0BD27FB
-:10D520003ABFD3BAF969F4B8FBCC5C3E4844023E3A
-:10D530006233D7130EE7666D9C698040BC81B305EA
-:10D54000AEB49CF693214C3241DC820B4EC13D714E
-:10D550003C5DBBAE2EF57DB15AF8C708F4171D36F9
-:10D56000829FDF2CC0F19974045C032048F54600CB
-:10D57000C64F6D4A3E84FAA2AFE6389E3F17571F4A
-:10D58000C77203E4699A94E0CEEB328890A7D6E69E
-:10D59000E5A5F5857AB3D20C1ECC1F96808E26FBAE
-:10D5A000D30C8360FA79AB0F8F22643B29EB07160B
-:10D5B00025F36AEFE1A3DD00AF083AED48C07B1820
-:10D5C0007073BB92A70C10DE57D86E6DC97BCD94DB
-:10D5D0002F6EEFD1920F40BE0A807F078CE73DBCD3
-:10D5E0001AE27CCCBED5663AEEE4CD06A4BBD111DE
-:10D5F0001B9E3F48B803F26742CAACBE18F7A55B52
-:10D60000EC3CBC5E5B7C7C3B8F479EECF77BE0AAEE
-:10D61000F7702E8F892B3C18EE63379A673F6F5651
-:10D62000D3E1E666B1079DDFF3B0F7B4BDB3C03513
-:10D63000AE0F9D9F739381C5CF9AFD3F87FABD9F23
-:10D64000F01BA0CA68125E2A001FFE4B32CE47199B
-:10D65000A7621F3B5755AC31045722FEBA05906FA5
-:10D66000D1FD0BEBF6AF89ED5FED29DCBF92BA532C
-:10D670006CFF6AB71C30727B3C9C5BB613CF2E30BC
-:10D680003DED5A3B234FA2FB92646AAA807D95C967
-:10D69000F4BCC2BE08D7DFC4842B9F5F5B70DD7E05
-:10D6A00061EB8F06825EDF60F0F426517829F54E3B
-:10D6B00098599CD864ABBF0EC6297D365C01E7DF64
-:10D6C000BD17DE433F70EF86E6D0403ADFDEA3B8F9
-:10D6D00039858FBBBD612BFA33B7031EBBC175EF14
-:10D6E0005F0972323E3C187EB7C0A3E614C2C70081
-:10D6F00079FA7D37BF4791532B78414E2499A81C66
-:10D70000A5E91FCDEC1C73C62CF294D9199D0D3DD3
-:10D7100024D08B73A619F03CE5E46974FD3CFECF80
-:10D720002C69E48BB29F0A1E11529900E79C02A754
-:10D73000FF2F5ABC7926A1072D1F7DF6F452B0EBBE
-:10D7400029EDB6AD209EB9AAFBD0147FF668DAE5C4
-:10D750003F6A057BA8521FF032D63981B6BB04ED73
-:10D76000601C58C79EB3CD22C0BBBDFBAAFF5EBFE5
-:10D77000828ED72B3EFDF8B2D9BD22FDF77F9A15D8
-:10D78000BF23D347BCD17B7FFF047C586C0E3BA6E4
-:10D79000D1FD2DC9BE660438AC4CB8323296DF33A9
-:10D7A000DE3CEA6FDC6A03397D30628A798FA0AF94
-:10D7B00085E917EFAE98E1013FFC532DF704983C43
-:10D7C000CBE37C37AF577121635AAAB83130587018
-:10D7D000B9990F5FE8FC0AB27649203FF3894A5EA7
-:10D7E000323BC504D0479ECA1109C6A9B9648D7CD5
-:10D7F0001B0FF67207BC0B52761886BF3B4D7B0F92
-:10D8000074D2A85312BC5730368B8A6301DEA7D17D
-:10D81000968FD7DD139DEC9DE5C9E3E5D7F0FF4179
-:10D820005CE7A4ACFB3C796A392155F6817D3EFE6C
-:10D830009518536F7CB4053E3E84EB1B160A9FDBA4
-:10D84000619DB3563399747378E8E1A8874BDE5F26
-:10D85000E6317BA10E1E77DFA83C9C14030EADD7EA
-:10D860005DD907E4A6023F3D1CEAA12EEA4DA620A1
-:10D87000E881F55218E1584FE118E07EAB7CF53EA7
-:10D880002BF3E1FAC378FE5D0F4F3D1CA97E81FAB0
-:10D89000C3D80176B4831D0378611C40E50726FADE
-:10D8A000FDED5E32791A785F6834C619DE45105690
-:10D8B000E40DA12C0FFD322EE65FA1F29CE1C35FC7
-:10D8C00098FDAA30C2E63FC6CDE265283C4EEBE0AB
-:10D8D000715A87079A738B7E9E6FC03F46C4C00FF4
-:10D8E0008E078B2CFC7C934EDC70FF7FD8C7439C4B
-:10D8F0008C2FC4968FA323BE967E98DEC1DEE710E0
-:10D9000088BFE5BB8BF613F2CA18FF996B76217DB1
-:10D91000E4126F12BC07014186304F655E8305DF5C
-:10D920000F2D29F07ED3D824F5FB10CAF8CABEE427
-:10D9300072F8E592C0013887E612E933F5BA95FE30
-:10D940002A2C5CCFEA4EBAA39F1C8CA143A3FD29CD
-:10D95000EB4B4A22217C3F4430E33D27FA5FC0D89D
-:10D96000213A9E123F9A689F526941BF4E196171D8
-:10D970001221DCCF1C5E9EC3DF6922E6B8EFF29075
-:10D98000AF13A2F37BD12248F86E029FDFE5A3E636
-:10D9900000C46B3C26F8B7021C1A846303015E5472
-:10D9A0001FBB05EFE9EBCAAF9D3C5C02E5B4DE3C72
-:10D9B000ACC7D7B5506476327AFEC7F7505AF371C8
-:10D9C000664FA3E426C1FC15FCCFB132FA1E4FDC32
-:10D9D0005DF1BD34E297203D6C61F7D0EE3EF90C6D
-:10D9E000EEDF1FAC771F057A2B204109DFF9716943
-:10D9F000F1B04D3CEDA33FFFF2775DA4A67480EB40
-:10DA000041CBADBD408E29FAC27B16DF6F61BD07E9
-:10DA10002D8C3F9FF60E7D17E4C2ECECC12786D01B
-:10DA2000D460F6E1BB0B0F035E517866015ED1B6A0
-:10DA300007A1EB4E88574761DFE6ACD5E19599D950
-:10DA4000D36653B605EBC8592B7FA99E570BBCB8BC
-:10DA50005C6C4B3F2487A9429F0AEF2D30FC3C6849
-:10DA60003105406FCB798AC547CC21FE172B057C49
-:10DA70000740A3AFCFB530BBF7DC9F5990CE69E329
-:10DA80004D65E0E7B2F0F71CFAB077775AC6AB54B1
-:10DA9000B5877D37A7221ECEE5FEC3B3023BB7CCC8
-:10DAA000B5E4B37BBF1BE566353EEAC78FDBAFAE9F
-:10DAB000DD4181D9490ECA6E8C0753DA5DB1303928
-:10DAC000DE6CEEBDC97093FBE0F3CC1DFA4B49D17F
-:10DAD000FC398B65462CBD40E9AFE55CDE729E30BB
-:10DAE000AE39DC357A9E3094CB47B4E709F9C8BF2C
-:10DAF000729EB03F2D1F594DDBBF6DF3A55A617C5F
-:10DB0000C9D717E0FE1CD70FA926D3576D974EB57E
-:10DB100032FD3075790E393338FA3E9B20D199E0C9
-:10DB2000FB1AFE729037D20C82FC9FF2998762C575
-:10DB30000525DA733A5B8746E9EF2983BBAA92C5CC
-:10DB40002BA0BFD7B77C36EA7353971761DA78FA00
-:10DB5000C62D4087391C9EB75A995E5A9AC0E84331
-:10DB600010FCB7427FF55ED10EFED485B522F7D703
-:10DB7000B177ADA64E1053E0FB19B38CE7C08376A6
-:10DB8000B6AF67087B9F26E7B8C95743D31B247BF2
-:10DB90009C55A5EFDD2079982769A9E8BF56EE2BA3
-:10DBA0009E21196CBE6B997FA0796D06C6311F94BA
-:10DBB000B5F6A85156A60F8FB2B2FD9DCDDFB103C9
-:10DBC0007C82F724664B6EB40FCE8E18D93B6A74F4
-:10DBD0001E886F166D3FF956163F91CFE13F1BE44B
-:10DBE000E460A8A7EF4762FD73BCD5C3FD4D4BEEC3
-:10DBF0005880D30DE21D6745BEEE96003E39430EB8
-:10DC00009F04FED6363F0F08C0CF4B6F08A1EE60D1
-:10DC10002FAB91F17CD6C0F5FBCB35875267D3741F
-:10DC2000F1AEF71D700EFC9E95E95397A57A7C77AF
-:10DC300062D16B22DE9BA6689AFA3D6C3F6718BBE7
-:10DC4000F7C1EE2D2872EE8EAF7A76F5613D76FF44
-:10DC500040D1AF72CD8120CCEF60B98876292A07F8
-:10DC600035EF90E4D7B07B097ABDEB11ABCCE3354F
-:10DC7000D93E2E73B171E2D16D4EC44A822ABACD1B
-:10DC800091DC12CC3F27E220410AF7CB17B66E9801
-:10DC900048F13C9026E3398F1E7F0EA3DEA7F8C122
-:10DCA00003344FC739CCD773A466EA34785FE52DC7
-:10DCB00052B67A00AD9317F6273322A6A7B4615166
-:10DCC000BD2BDFA5D5F7F4FA6041DDFAD5F0164B90
-:10DCD000037C80F1CD268C236EA5279AEF8EA91F99
-:10DCE00012B21EF1F08ED77E391EDE9FB8E3A2C1BC
-:10DCF00005F39B6C7533FB62CD357C1FA18484A634
-:10DD00004379498DE80AD1564748CD6D201715391A
-:10DD1000AEC02574E390D903FCDE22BA56C23ACDD8
-:10DD2000F7D820CE626463FF64906707CD32DA21B2
-:10DD3000732CBD6D7354F87C3099BD1B7024B9A74A
-:10DD4000F6BB79C36D20D7F6F0B8B5C3E7EEB7855B
-:10DD5000B1DED464D4CB1439AED357157BD7D8DE1B
-:10DD6000628BBD4BADE71271D3B3165A3EFE561906
-:10DD7000EFBDE58599DFB4951CBFE15FCDCF239A58
-:10DD8000EF055C3F6825D7A370D6E8A16F58B95E50
-:10DD9000E9260340AF0CDDD8B010EFCBD625B8563E
-:10DDA000A23D81E92D8D678B374C80EFC744661FFC
-:10DDB000B921221D1DDCBFB07B5845BF5422E0BEF7
-:10DDC0005D1F74F5CA9B745FAE7F62F504E0B354C7
-:10DDD0007D5B6CBF5890C329D499D9D9039DD93B99
-:10DDE00018ECDC7957F4DCF90EF001784706C443EF
-:10DDF000DAA65346381F5FA6AA38E2175D34E0D78B
-:10DE00005DDEB0A8BE7F738AF3DFC956EFFBC01F8B
-:10DE10000324A70B55424891D59B0D71E04D938982
-:10DE20006B2B5DCFBE0B39824CF3A3B66578049A99
-:10DE3000DF0D8A25F0CDD7C420C493EC867B6BB46C
-:10DE4000DF05F595C60C3A6EA04644BBFE026E1F78
-:10DE5000BF2007D21355F85199C0F8C905D9FF0B57
-:10DE6000E8E7C2C726B4775FF8C41A53AECE48605D
-:10DE70007CF74D2ECF3213DC980F35EC7DAB339D04
-:10DE80005728E21A04702FDE7155847793EEE4FA76
-:10DE900057E1B3F5ABC12E33715393047CC71774AC
-:10DEA000E583489DB2C323831C9AB6D327839A3D4A
-:10DEB000BDA60CE39066D4561E81FCFDA16ACCF78A
-:10DEC0004FF047002E77AD6D3A04E8D2AB9248F898
-:10DED0008ECF674CAF4AE5F3E811F11C7422366728
-:10DEE0001B00BF5BC67FA25E02D57DE26A363EEDB7
-:10DEF000CF9040D77D5759532EC8B5F4E5ACBF74C9
-:10DF000072A0DCE98EF63BFA46BDA0B617BCF898C5
-:10DF1000AD88F15B06F7F4C73B6FC173197159F116
-:10DF20005D454E4F398FDBD00F70FD07CC0F707DF4
-:10DF300010D3A7AFFFC0160CC4D0A7A378163231F8
-:10DF4000FC52F08D9859DE6B067CFBFEF36556A003
-:10DF50009B649FDBA88E3FCCD950D8EF6DE8DF6281
-:10DF600042BB5CCB78EBD97810880B78ADC8B1D9BF
-:10DF70003AFF4B940F30BAA05D04615C2525C24A7C
-:10DF80001751E749280DE6939EC0F85C95D13D13E3
-:10DF9000C6ABB29A5C30DE6C736F23F0AD16FB2615
-:10DFA0008F4F1BC9F5CB7D170E26C1BE5F1F549E38
-:10DFB0000E7A73C8F073E4536DE1DD4FACDEE10916
-:10DFC00038CF00EAF94AFD3DE7ACFD414EBE69603D
-:10DFD000714FC433AB3BAC5769378DA7BBB99F4E6C
-:10DFE000A193E47AE2DDD21F41E5DDAD82C7A4044E
-:10DFF000468F4ABA5B7607189DB1B8CEDDF690B968
-:10E0000027D0F39E9E984FF6119B07E2586A7B7BC0
-:10E01000C05F43F9C0A404955DEA4ECE1F92EB9B0E
-:10E02000902EDB7B1E18C6E11B92AA397D11E453AA
-:10E03000405F8C7F87BAF0F778D0FF077C83EF4F83
-:10E0400027210DE3C1719F95752773BEB08CD33D19
-:10E05000C001CA4B795E295FCCE1952FF677AAE320
-:10E06000C75AC9F5E56904F4C7FCE59D312DE5F310
-:10E070005D605E8FF6D205C9EBD14E9AECADC474EB
-:10E08000415E257E4FDB340BF163C1C6D8EF8C1D9A
-:10E09000E57AD9E50B06F69E94C1DA19F04F297F8F
-:10E0A000C72A737EE97F1CF0E162CD86E707BAA339
-:10E0B00076DFEB96CA89F703FE6F135DE5B03F5537
-:10E0C000F9823B065EA9E107F02AADFA1CFDA62500
-:10E0D00024CCFCA6DC2FAAF84F83558C9F5EE4FA73
-:10E0E000599155AB57562618383FAD1F7F3B1D3F02
-:10E0F000D4DC2B13FC4121292C4A6CFFD06E047C0C
-:10E10000D885F8FE74FA638047821DF51EE0ABBB2C
-:10E1100054F8B170E7968ACEF49F77DD60F77742C6
-:10E1200012B1A9F9B782270A3FD6AF6F2BC75F0597
-:10E130000F4746E5D4D6046E1FED49FB2D59DF8C01
-:10E14000F6D137147A067C037A5EABE0DB20037BE2
-:10E15000374D4BC7C3BF23FEBEE79917D2D1FE9000
-:10E1600045E916DE5903BA8E8117BF6DE103FEBD86
-:10E170000931E4C145C1FF8BA49ED1F67BCE8DEB66
-:10E18000375BD5CFCF389E5F97FDDD5D31E01585DC
-:10E190002BE90CF850447706E04036092E75DC7BFD
-:10E1A000F22666E7AFE7F055BED7EBE03D3AFABEA0
-:10E1B0005C3D8377931144765A90E905C430AE33C1
-:10E1C000C8F90556EF38B4B7AC37107C4F55C84185
-:10E1D0007C4FAE7AEEDC574320B5F440BF09711B8B
-:10E1E000008F163CE5C6F3E0CA972C8897E71258D3
-:10E1F0009CC4CA2A99E1A75C89F875F193E2EEE024
-:10E20000770950B9DE3B86DCF9AD4E9EBFCAE5A862
-:10E2100082773DD631BCAB92BCD644155E6E27DE0C
-:10E220004CE6EF6772251E3E46F1C83548C1A3593A
-:10E23000F47B8FB56111F68BEEE335A0DF9EEB9A90
-:10E24000909FC5DB47C5BFA6ECA7C2E787DBB4F745
-:10E25000FA641B5B4F729C7880A89CD3F26578FFB0
-:10E26000CF36544B0F70E552594F23874B3CBA9829
-:10E270006363EF3E57FC75C38340CF15EBAD9E95AE
-:10E2800024EAA751FCA7CA3C3ADA048D3F47EF675E
-:10E290006934FB536D2ABC023FA01BF93DF3AB2848
-:10E2A000BF8760C93616E7B4078A808F9CB506D54C
-:10E2B000F7776F958857CAA470B565E0BA6F0516F1
-:10E2C00042F3C9CB8DA4173D775D1F71E0B083D6B3
-:10E2D0009FD0142EBC9D2E718F313C6D12D87D893C
-:10E2E000B718F40CB4D103FE37B07E89AB5A33CFE4
-:10E2F000811CDECAFE54FC754E5A2C3F8002C77842
-:10E30000FB3287C3C3C9CBF5F46FE1E59FB69B7EB3
-:10E31000034EA0DFBB48A01CE22FE8011DE3D65A44
-:10E32000E8971ED8A1FF029B967E957C0CFA2DB033
-:10E33000A9E9371266F4CBE9D459257B63E92DD3DB
-:10E340006DEC9CECACCACF0679E4F461D839D00D01
-:10E35000D2FB024AEF40C701A0DB8E004F86673D2B
-:10E36000BC9518EFD8A38AE9E3D713D97A17DCE96B
-:10E370003D00EF252FA0E7018156ADE4F41E1FEE0E
-:10E3800021A7C0E49B13F8CC5DA3C2B92087DD6050
-:10E39000EFE888BFFA023765F428120CD17D77DFE9
-:10E3A000208C7F7CF2C2838F01DF586FC37B4F8A42
-:10E3B0005C4A4DF017DB86C6A76B8A975EB0572D77
-:10E3C000F9C2C6CE8D71FCE2A3971B48AF24C4F3FB
-:10E3D000A56A3C1FED6B1201AE4909FE34399190DC
-:10E3E000D5B69C31E66E747D1954EFA5F9729A5F2B
-:10E3F00007F6B70E61C2F315B64EDFDE5EB77A9D43
-:10E40000F72DB0D7BD94E05D09EB82380048EFEA04
-:10E41000D224227F6BA75FBF14EC77743DA7EFE98E
-:10E42000F7D22CFA75F67DBE0A2855ECC9C3B93D62
-:10E43000B9B46E10DA995576E50DB0FE7876E5B68A
-:10E44000C67570BAA7F88DE73F47569308FC51E1AF
-:10E450002B5B6C1D383E8709BCD7AED017F025D09A
-:10E460007795F802B03BDAD15F11447C85BC333339
-:10E47000CA6FD6551A62C63F55DB6C1A7A51F82915
-:10E48000A9FBC7EB8F29EF2C32FE5AADE6AF5595AD
-:10E49000A75399FECADE2D5BCA6D001B567AFED8C3
-:10E4A0002B397AEF7984C91880F716E981CEED52BD
-:10E4B000C54F0A7542C80E71795FD222C0A32F0DD5
-:10E4C000986EF80F5F4106D8594E1A90FF96F07B70
-:10E4D0004D59DD09BEC353CBEDA3D9676C5EF0FF88
-:10E4E000370A66E49F8DA7AC0190AB8D7603DACF37
-:10E4F0000FEF33215D5CEB65E5F68FA0C64EA2F809
-:10E5000073AE1D9B9304FCFF79EED77CFEBE5BD0FF
-:10E510006EA9D8732589C2BC0384E9B07B9939CB35
-:10E520003BA3BD55B1EFA69A67092C8888F52F99B2
-:10E53000D9BA5225BF00F6F12D6DC43F9CB1191513
-:10E540003DF82F00DFD227C24638E72A7AB022AF43
-:10E55000BB37F438007110DD0B98396D4B83C10067
-:10E56000EBDB42D12831A3355EB5E04FEB38838B2E
-:10E570001AB9B486C519B4E479BB5FF03883D167A2
-:10E580004FBF8AEFE999FD1F6BDAE5A75863BDD34A
-:10E590003D7DF963D83E1EDE4F37B0F779F4DF13C7
-:10E5A000EC9C6F4B655DF07ED4DFBE9FE08E61C753
-:10E5B00099FED7D9F87B24F476B7E8F8FFE1C9A330
-:10E5C000FB26DBB9DF2F9DA4835FAD2D3FA67EDE4A
-:10E5D00027647FB758F2491F67A78CD7BA3D3B978E
-:10E5E000B5D43312FF2E1BEB3753D5EF283BD37F27
-:10E5F000A60B04E3DFC95704E5B4822714EEDDED72
-:10E60000B47CD83B67065BD1CFD324021FB876B267
-:10E610005757F4AFC739872AF321C4DF3B561CC7CD
-:10E6200074788727C6FA46D8997C9E2E333F85702A
-:10E630005F6FB40B4CB7980475DC7E6F65BF74FEDA
-:10E64000D88396E178BF11ECF9B1E0A7F7D3F606CD
-:10E650001FEA5006174F0C7C52FC820A9C2BB2BD5D
-:10E66000D912B3A7E13DB5642FE39FC90504FD6B43
-:10E67000C3052FC263BC3D03E7B785C7C75D3BC673
-:10E68000E2598765BBF1F73C51393116E03A9A847B
-:10E690005F35A8E2AD143CA97885CA638DBD31A071
-:10E6A000394F27723EEC82F72654F5DC4F000F8875
-:10E6B000CA81AEABCD9A7CFA321791547222D19BAB
-:10E6C000A6C977F5B9AC708EEA5AE0D6B453F04ECD
-:10E6D00089F7C39F6458B70BDF3DEAC0E7335CF0AE
-:10E6E00023DE005F033BF202BE9F74BDF371BD05E4
-:10E6F000E16B6ABC51D6DBD6BA4EAF70232F3CBB60
-:10E7000082CE97F28539EB32CAD310EE2E02E78B18
-:10E71000732BCCF8FD61DE3EF1D959788F3671B597
-:10E720001BEDB889DEB2B7E09E4F62991BEF15CCA6
-:10E73000AD1404B0F7503E83ED36AF7061AAECB76C
-:10E740008B960BB6E83BE3F1E4D75A7BBBE5D75A8F
-:10E750007B0CF965307BDE06BFFFE23AD10D78B164
-:10E76000AAB003DAFD3654B3FB6E87EA58DCDD86C7
-:10E77000E94C8E28E35E79CD89F2E28AF2FB54BC43
-:10E780005FA64EC178802F5381CF6EB3F99FB7AB90
-:10E79000F8E586BAA116FEFEB246FED01F17DC7F52
-:10E7A00040DF9C007AD2A0B5524FA4FB1761BE6433
-:10E7B0005E78B0A527E0A9FF7D78A7F4DAC9CFD2AB
-:10E7C00061FF143F9FE20754C651FC8482E0DF6E74
-:10E7D00057F1A9D67E40ADFF4A7498314E374B644D
-:10E7E00071BA2A394B601F57813E48F16CD5292BED
-:10E7F000C263D5578CDEE83C5F85710EDB8721FE56
-:10E8000028F294CE73E0BB243ACF524353BAFA9D18
-:10E8100052D53CEB6E3E4F5D1C2B9F97689770BEA8
-:10E820008DC4EA8179D51A3D27FD2067AF58D19E66
-:10E83000D7E8BDC302EFCD36923B2CF00E6DB5CDBF
-:10E840007F14F643ECD6E4003DFB50DDE0BE30DF44
-:10E8500078FED8265BCE31A84FD7F7474847BBC2D2
-:10E86000D77EED8EAEEF267EDCF7A1FE3758FF5F38
-:10E87000BEC9FA4BE1F767300339EA5302E7BB7AC6
-:10E88000BC12EA0E7C01F143947E306E33904E82CE
-:10E89000AB289C2A0630FC227309FFFD395A3CD86C
-:10E8A00066F335C07C14BABB097C9A609D1B6DBEB3
-:10E8B0006648611E700F84F299CFB8BC7AD568881B
-:10E8C000EA5149498C5F3525128CAFD1FBC913ED54
-:10E8D00053FE01ED52FBF80557FF6F84E792E3A664
-:10E8E000F00B615C84720F7531F87321BEAB466E1C
-:10E8F000D0FE9E1D2D1CAA6D3E8703FC3839EC3DD1
-:10E9000039C02B78FFED26F0E8E04078F85320B5C9
-:10E91000CB145F002859B3D200CE8D666F2AF895CC
-:10E920007697333834BEC3E0B0E7AC01F1F839D2A2
-:10E930000FE92ED3D0FC20F44FF9477758D7A8A67B
-:10E940006A01CEBF1D8BDC06E0B35D9A3CA2E1E616
-:10E9500078DBD381FCDE7F8B83EDC352D887C1C7C0
-:10E96000987DE62678DBCF91F28DE03ED891D27E7D
-:10E97000FE42F16AB8438557ED8D9B12F8FD497D43
-:10E980007FF43C84FE83037B4CC88F4A76B3FBA2A2
-:10E9900025FBCFE3B9BB64AF0991326FAF85DD7B57
-:10E9A000A861E557B263C70178E1978F817CA87EA3
-:10E9B000C4A395BB0166AFF436BB7A8951BF6AD256
-:10E9C00004768F60158F4752FCAB0E8E6749DD7C55
-:10E9D0005E902B49F904EF13386C2CAEB0F57D0135
-:10E9E00046B729BC9DCBE51600DEFAFB0329F09E55
-:10E9F00034F38F23BE8806AB07E47E5281AE9EAD12
-:10EA000000FDAF29BAFB06F31DDCFF6A2469C0478D
-:10EA1000AA2DB1EF097DE650F43A2B9EEB243EAFD0
-:10EA2000C376237BE7C56EC6752F49244985989721
-:10EA3000509EEBFB69C12BAF41730F25A9C0AA798A
-:10EA40006721C5D74193EF38A3B3A67E277F0F4D2B
-:10EA50007997A27E9AF26E65999A7CF7E57768EAD3
-:10EA600067508453E77BAE1DA7A9DFBB728A267F60
-:10EA7000EBC6FB35F5FB06676BCA6FDB51AC291F94
-:10EA800050BD4493BFBDF6314D7D318E9EBD87C3D1
-:10EA90005954F46CFB103FDE3BB29B0593EA3CF704
-:10EAA0002CAF97ED284803FFF76AFB9834386F1EA8
-:10EAB0004E1CE60CC7E85749BFED396CB743D0D8B8
-:10EAC0005773B8FDECCA41CA45E0F7591CA27880DB
-:10EAD000BFBFC9BFDBC1F5A9596EA8CFDFB5903C58
-:10EAE000B88EE90E33DAC5F4FD3FEB706BEC758A36
-:10EAF0005E2F1A3CAE42213EBC3E6B27BCF67E47E1
-:10EB0000F03AA18B1752CE6FFA76571DCC7E4AF998
-:10EB1000ED07C00F5BCE69A449F4E139EDB32B01D9
-:10EB200002FC94A0DE124F0F50C61704DF5FA11F36
-:10EB30003D3FF52D9FC7CE99062FDED78A777EBB46
-:10EB4000CAD71F3DBFE5CFC0FD48346AE0F4B71611
-:10EB50003AF76ACE6FAB1387E1F96DB5EC4D6BCF29
-:10EB6000F9ED6FC0938602DCD9BEB6ECA7D1E3669F
-:10EB7000F73CB5FA4B6B7D9BCA3FBACE0DA0C709D7
-:10EB8000A0972531FD7B377B0F4019B71DFAB6E4FE
-:10EB90006C87BE6D229EB59288FB657532FD7AA9A1
-:10EBA00045FC56FA7592F31BC8BFF7640FC6FFBF4A
-:10EBB000374124F02ECBB582E1788F3A1E3E7EC0DD
-:10EBC000ED2FEF39197CDBB25FBCB7A2E8A6F72FB7
-:10EBD000DE1BCBE22CA7E8DEDF1DE164783095A7D1
-:10EBE00014406887B8FCBA1DE3E52F8FFB107F6FD8
-:10EBF000D2E59AC14302F87BC23CCB20DE2660B34B
-:10EC0000A37D6FCAD8A143CAED2A3CE2BF8F2CF77F
-:10EC10008D771C60BF99B2AB674AC0161F7FA6F202
-:10EC2000F511297C0BC653BF79117F5FCD943DBD93
-:10EC300053987D511B9FA6B7FB4C595E82F8A6E402
-:10EC4000174708C6A3B5E42576DF787144C2F8B546
-:10EC50006ECE96F8F6F49BBD9BD65E78EABF2BF09D
-:10EC60007C6FEC45766FDE125BDF58E1143476245E
-:10EC7000FDBD9578F731E6F1FEAF158CC0FBF7537B
-:10EC80008CEEDEEDB1532970AABF713E01F8C27E51
-:10EC9000B80F13A3FF879C8C9FEDF77E920466E963
-:10ECA0006C73532EE07F36B783C788D75F0A7434FE
-:10ECB0003A52F09DC4EB3FE1D4C6EB1738195FD14F
-:10ECC000C7EBB775DF68B231B67C9BC1E14EE1F7A7
-:10ECD00021D0EBD2CD32C6FBCDA7730880FD6D8B62
-:10ECE0008CF6B7F76F9808F841CE6F927F09F169FB
-:10ECF000459B7B6E7E96E68BC69AD06F337F0B7BEF
-:10ED000087848CB504C12F5BB4E5D1547857FC538C
-:10ED10004AB78BA8D2347FF373180FF3FED9A7310B
-:10ED2000FEFA22D033FD5EF4D593D301FE7B8C95A1
-:10ED3000B70DA2E9A29D82E6FE447195459357E284
-:10ED4000FE94FD2342F45E859BCA91979CDAFB53A7
-:10ED500083A3FEAE979CE8EF0A639C7CC904767F90
-:10ED6000EAD039767E3FD28BC50586C6DE5B388811
-:10ED7000AE636C0A7BBF451F4748C03906EFABF056
-:10ED800038DFB11F4B2DF75C58B9D796AFBA3FF0BB
-:10ED9000D68A32DC97B13F637693B1192CEE3D6E83
-:10EDA0007C615AAB7B007D406EB68A2B8CDEEF39DE
-:10EDB0001D0B6F0EE9E8FAD039164738EF187B3F84
-:10EDC000AB2DBEF9019FF7FB67FB3DF06B0A8FF798
-:10EDD0000B18177FFFC6DD6BF07D1A9F40209EF356
-:10EDE000FC8DD8F7C8529C8ADEE46FB96F03FB3301
-:10EDF000B560414B1EC8F21EDF239AFB38EDE737A2
-:10EE000037E7274F3AD93D4A3D7FD7E3FDFF29FE3B
-:10EE10003E65EC9174B89F4FD397F09EFE2EC61FAF
-:10EE2000F574AEE7E733747C30CAC70D9A78E319FE
-:10EE3000C00786AAF9B911F9FCFF00D1E7EDCB00B4
-:10EE4000800000001F8B080000000000000BDD7D2B
-:10EE5000797C54D5F5F87DF3DE2C496692C96412AD
-:10EE6000B2336189A088C3BE457D098B51080EB8B5
-:10EE7000A1824E02216C21816A456BBF1948C08076
-:10EE800060635D8A8A76A041D1A20D8835D6A01331
-:10EE9000A5086A357EC5AFD62A0D82088812412D95
-:10EEA0006DA5FCCE39F7DECCBCC984A5B5FFFCE26C
-:10EEB000A7BDDC77F7B39F73970914319DB9190B80
-:10EEC0000CD782B50A631BED7EB33395B1A1F66012
-:10EED0004A2163ACCEB921C13F80B1941476ABCF47
-:10EEE000CED869FCBB3C9C76D88BE2B0FEAFE2FC8E
-:10EEF00076E730A8F75666114B646CC8DB4D8A1F65
-:10EF0000EA1F53D8B4A618ED4EC5991883FA5BCD05
-:10EF1000BC7C2BD61B102ECF74169E8A837EB7D94D
-:10EF200020857A8CD99C07FAC1BC988925A98C9533
-:10EF300028FE4C1CB7D2D67E5F29942EDCFDBD0581
-:10EF40008AD843167FBA3614D69369F16ECCEB3A61
-:10EF50006E1F271F376D4911DB3F8431AB8D05E2F2
-:10EF60000633A6682C601E8CE3F8979AA0BD368DF8
-:10EF7000B155008F3D3037ACCFFAA59B581A633F8F
-:10EF8000B131FA0B14319C0C0B7C161FAC85714E01
-:10EF900031FD425CFFBF987E11CEEB13A60FC0BCC3
-:10EFA0001CB74EAC533331FF9618F028772A7C1CDF
-:10EFB000E6CBF739205FC4FC91F090A9CFA951BDF1
-:10EFC000C2876FCC6D87F2CFF7DD94CB20DDF1D017
-:10EFD00088A4F618F565FA8B9A6AEF38687A6F8D0F
-:10EFE0009FD224C6749CCF9A9A39DE717D187342E1
-:10EFF0001EE7556EF1E52747F433C499CC18AC27CA
-:10F0000071D4D6B65E40270756AB4EC503293315DB
-:10F0100063FBFDC1A4E26D03783BB7A11D9FA70A66
-:10F02000E4C57AC3BAEDDA3FDA05EC4E335C2FA3C0
-:10F030007EBB5B67B9C09385796DD8DEF2D9553652
-:10F04000D60BFA537427E6253D8C8211901EEEC133
-:10F050004FA3605CC57FAB93DAE929B2FC741E8EC6
-:10F060005F4C79393ECB763196D13DBC98A2CFC268
-:10F070007E0E31BD1CD3664BE02227ACB7399ECD46
-:10F080008945CFF3117FB09EFE4E412FCCEE3C78E8
-:10F0900091180FE6F76482BE10FB3966F355637A68
-:10F0A000595647AD8A7413E714F5DB19E21DCA6F90
-:10F0B000C77296DECEAE06785F06935D05D9970FD0
-:10F0C0007DC63C00A7C48E03CC03E32722FE62C0AA
-:10F0D0002D2199C3ED0F8C15C7E63B4E670131CF4B
-:10F0E00046E017933BCC2F4F41BB2D0390EFFC82A2
-:10F0F000EFF4AB503E34FED2A5AC82F25EBAC784C8
-:10F10000F4E16E637A10E121E02EFBFFC469A17E79
-:10F11000910F9533F0E143E7C9878DBF9C648AC3A3
-:10F1200079DEC5BC7D3D58EE596683FC138B9DDEB0
-:10F130005590EFBD1A080DEAE72C89DFA042FDA02B
-:10F14000E0A79E0FB26571503B6F5D8786F261D27A
-:10F15000DD6D9A0DEAE7D5B56B289F5EBAEBD15C01
-:10F16000A4ABC39F5FA53AB0FF6F64FF0020E0F738
-:10F17000314E8E4336B2B427E2A709E79D1AC15734
-:10F18000F1FEDF22BF5F56DD31D60AD57297300D12
-:10F19000E5E561C5FFEB94DED86FFCB4E000442FD9
-:10F1A000A7B7970E1EE95F06F9ED92DF95A24C9680
-:10F1B000CE5841A399E059D0F8D02D08EF82C62B44
-:10F1C0003405AA3CA185140DD759AD6B01C8BFEB1E
-:10F1D00034D3F8873F9FD753C1F9FED9CAFAC68006
-:10F1E000EF9BA2FF2681E7972DB1E97667A7DCE1C7
-:10F1F000FC34862952BEEE443A04F99AD81BE0B199
-:10F20000F0CEE3245F9F727A68FC27B4A69D993400
-:10F210002FE60DC0A7799BDE23792FC791F5E66F06
-:10F220005EBF02EB65DFE61CA47AB05D7B1CD2CF2B
-:10F23000F7711C5FDFDF191F5CAA10FD0FF25D1C68
-:10F24000830F59C86A4A270CD878AADB4C2301AF30
-:10F250001D1D8528F7A0CB65C89757257B681DB273
-:10F26000DDFA0E673CF2CBD9F4C14181CF73A5C35F
-:10F270003792B9DC0A74D59B47115EE7A1373B840E
-:10F28000DE3CF16FE94DA12FA5FE94E54A32C7E7B8
-:10F290003DCE6EF5A6923CACABDE74B3E0BD03612F
-:10F2A0003DECA8C9BB91751D3720E4DBD178DD9A10
-:10F2B0000C6981C27C386EE2D1CF98122187160B7F
-:10F2C000BEDE2AE9C0C56E9D12631D95A23FD3F430
-:10F2D0000E4B3BF6D3A210FD775DAF85EA815CEC67
-:10F2E00081F3BEAC27C84DA5ABDC8C818F5CAC9F95
-:10F2F000F5B6FE3A12C9E8E4C60440FF99F0D10B16
-:10F30000EBFF2A4EEF8DEB93F01F7C5ABDD537A053
-:10F310002BFC2F1470BECCA1F7C7767F137CD61DB3
-:10F320005E4625737BE6AA648E97AD0E512FCE58AC
-:10F330006F6632874B45B2912F23F0372A3986DD2D
-:10F3400023E5F0D1785F0196FFE1D0D604A42389AC
-:10F3500027297FA2F115E6B3A5341EC0793CB68FEC
-:10F36000D63FB27DB41E0AB70FD0BCD7231D21BF34
-:10F37000211D79B89E583F203C3F49E77EB1CE1F02
-:10F38000E2F52908BFE8793A8F9A9433CD33B9C3AF
-:10F39000AD20FF27EB4E4A5F3E6452705ECE0E4DAD
-:10F3A000C17939857E8CD683202E045C793F6F0825
-:10F3B000B9B1E2AB99E988E71585FEF46AA83FD9AF
-:10F3C000A1CF4238DCE3D4CB717EA50E7D36E64F6B
-:10F3D000C571FE1F95ACCFC1EFC9C28E8A9E67B5BD
-:10F3E000C01FC0B30AEB258E6301D487979FB40773
-:10F3F00041C4020860DEA01F12756711EAB1C4752E
-:10F40000CC8B749A92D0D16A857CC743CCBB01F275
-:10F41000F9018FC98AFAED367D19A62BBE52C9EEC5
-:10F420005C51C882CBA81F6E87B2BA5E41D2DFC0E2
-:10F430006F91F4BA4CC079593297736087D42473B2
-:10F440007E5A9A1C6187483EEACEAE88E0C3FAF342
-:10F45000E4C35FE078E7C1870F083E7CF05CF8F01A
-:10F46000B1301F3E8AF5CFC687CF083E7CE32C7CA7
-:10F47000B85BC0ED5D513F061F3E138B0FDD821E52
-:10F4800024BD231FA2BE0F2577CACFDFC5A2F77305
-:10F49000E0CBE6E473B00B3BFB3B47FAEFCEFE1B41
-:10F4A000E33AB3FDB7C7EEA4F5487E067E793399FB
-:10F4B000F48EFE16C205F8E56DCE2FB1F9AB53DF21
-:10F4C000747039C1584302D28F9CE7E702AF00AF96
-:10F4D0000FB01FC967D24F91F0EBA40761F71E155B
-:10F4E0006962C7670CE502C06D6F24BD3E25F82533
-:10F4F000309211BF8047558476E54B47C18E44ABAF
-:10F50000CFC5E75BB0B6ED756475A635244C757450
-:10F510000FA72217B773BA83138C7F2C963C6D41CB
-:10F52000BCD9BBDAF3D1F8FA44ACC7E952CE88AF04
-:10F53000B3CD43C20FE77109CDC3635A15A1E7CD1F
-:10F540002E45F2B7E682F4F2711D2AA3798512C026
-:10F5500085EA94A72C1BDA0FEDDADE1E6E6F77C1F9
-:10F560003C2FD7A1FD80707B189FE45DEFDB409EB0
-:10F57000919DAC9B503FADC8E3F4104DF78D683FB3
-:10F580000C88C0574326E1EB3E9B3F13FB6FD43CF6
-:10F5900026B4EB1AEB9D4A80F0581D8FF463B7EB4D
-:10F5A00044B731E490C7757E72A88F8BCBA1BEAEF5
-:10F5B000739043035C9D72E822ACEF3C8B1C1A23D2
-:10F5C000EA17B8B87CE94E0E5D26EA1509F8C69030
-:10F5D00043635C31ECB96D369DFA8DC1A79763FD2D
-:10F5E0004CA7AEBBB85E2B7445E835683716F3F709
-:10F5F00089F6AB1B4CFDC87E66F1DE587E86CF6572
-:10F6000037D829970AFF81B5FCF3F7770D67AC0A65
-:10F610008BF83C7DAED4B03FD1D8F0591AE21FFE32
-:10F620000C7195079679DFED83787B476568873E97
-:10F63000F03FED168477737CE240764978DCAA7F50
-:10F640000041A6005EFE61A254E27161CBD2210CA2
-:10F65000FC88C2FD3FE4A25D796CDF3F283ED261A9
-:10F660002FF3E3F83BB6F338C989B767A6A07D2E20
-:10F67000C75F8CF882798D5707348560BDC777598D
-:10F68000BCA86F55E6F95501CCA76A979905494E74
-:10F69000311BD637F3E932F3AE156D6A22E6B58039
-:10F6A000886F28A7C99FF12421DD9A77A90CF990CA
-:10F6B000B9797980D9969E067F3369A4897922E247
-:10F6C00021C97A3CF344C427528A5D867CAA2FD391
-:10F6D00050BFC7B45E86F20CFF8586F2AC39830D4D
-:10F6E000F99CEAD186FA3DC1DF89CCE705AE32D478
-:10F6F000EF5D3FD590EFDB7093A1FE056BCB0CE582
-:10F70000FD83F30CE515BB9FB7A05F7DD1A6C58631
-:10F71000EF1737DD6568070069EB0374328B71F80A
-:10F720005FD2BCCC507F56FBBC4948B78342AB8C00
-:10F73000ED1ACC07383C030CE1F905F35B90CE34AD
-:10F74000D6B1330BE0BE30A87843506D6E735E6F58
-:10F75000E4872FDF2CDEA50C8479ADE5ED643F73E3
-:10F7600083C6FC7C7533F14F349EAB58AF24CF5029
-:10F77000A40395059530DEE76F32B66718EF827601
-:10F78000F3C57AA2E9E20B56FD7001D247406FEB58
-:10F7900093165EB799350D0FE17741274E412772D9
-:10F7A000FD72FE72DD4EF80FCB41E15B90CE663705
-:10F7B0002BEC51A5EBFAE6B4DCBF222BC63A190BB1
-:10F7C0005AD0DF8E9EFF0E97C37D3001FE91CB7223
-:10F7D000316EC5BAF0879DE4F1F1756AD00A74AD57
-:10F7E00006FA45F18771FDD1703C5F7EF10838580B
-:10F7F000D38DFC12E7898FA6B7E121D615AE09FD9E
-:10F800008C7C24E128E1EAF066C6A42B0FFCC7E15A
-:10F81000ABB31F13BE1D08DF8BC2F03D66F39F40E4
-:10F82000397CE2A36F55A23B7FFB10D463DDE9A5D1
-:10F830006447D1DF44FD5CAC5F9500723109FAF991
-:10F84000EC877CE4B74EB9BCA4CC3B0EE4A2A2F892
-:10F85000594A6AF87B9BAE3A8602BEE637AB5ED465
-:10F86000C3C7347BBD72092DD3E34C43252DF1C6AC
-:10F87000F128F1A6B4BCFE7705E0056DFC168CBF3F
-:10F88000167B6D384FC6A6539C5301F7E67402E908
-:10F89000D9C414D2BF3AA3F8DF71E6AD85FE6A1D64
-:10F8A000BFBFE82CF110570AD90FFEB478B43F3A25
-:10F8B000DA4F3C87DD6B6D4E1C678ADF4FEB198199
-:10F8C0001304BB9A39014E11F12268978DE34E79EA
-:10F8D000FC9709680FBF74E0B84AFAE51337D9C33B
-:10F8E0004F315F7F940F5DEDEB00E93D69AF837FA2
-:10F8F000D43B85DBDB7D5322FDA34EBBFACCFD80E0
-:10F90000DDD10FED99EE52E53595F4698712EFDD03
-:10F9100010439F8E4C31EAF94BC3F1B8912911FA8B
-:10F9200073E1ED2776E23C00DE63709E0E07D8356A
-:10F93000CA39D93597633FBF4A4824BAEED8AD06D5
-:10F940002F8006C76D9E2417DA9142CF2A1AE8103D
-:10F9500057843F6B730DD0866079FF2416C34F9197
-:10F960006911D64B09E75F8B33FAA32B06F3794D68
-:10F9700011EB5C29ECA7F2146EE754611C2E251CD8
-:10F9800087AB9AC6E3CC0F45C52FCB531C547FA53C
-:10F99000BDA81CD7BF224F21BB6985A218F6915282
-:10F9A000530ACB71BDB78AFECBA16F1CF7A95E7C51
-:10F9B0005EEE28FF3D0FEB0FC394F70B9CD41FE9BD
-:10F9C000CFA2AA31E1392F45C4B1E399B4BF896F01
-:10F9D000260ABE9920E4E5957D415E1273E993C63F
-:10F9E00043F93851CED4757BAC503EF10233433AE3
-:10F9F0001B877209E5BCD3FC597BBFB09C9FD0AF7D
-:10FA00007A078A872BD2E17B843C2966BE2CA483AB
-:10FA10002B3DC6EF13F74C388CFC3A9169D40F7D1F
-:10FA2000CFE3704D7085E97D594AA7BCF79C06BEAF
-:10FA30000EC5FB1F28C1F8C39F54EF066AD53624B4
-:10FA4000D22FFB85C0DB6AE1A7E03E12FA1F2E91A0
-:10FA500046C3E717293CEEB0DBEEFB05C2F3214BB2
-:10FA6000DB4F70BE214B7B6D128EF301A37132E729
-:10FA7000E8AD981FE6F3308C13AFC863762FD2E75A
-:10FA80002013C541DC7EE7380BE4DDEB14B4849928
-:10FA9000596301C7E0B05C684EC913F3AA6D4D828B
-:10FAA000FA49EBBE61BDC87F708E73A21C9AC56215
-:10FAB000C6359F167431E5F15E1AFA614936450F75
-:10FAC000C658C7D302CF201736E13A2EB7ED1BA296
-:10FAD000907EE07E07BAB2F47F074CC18D4AD7F61C
-:10FAE00076FBD8E7900E251D5FAAB2EA2D764E5F11
-:10FAF0005322E458B3A4A7738C470F9BC362C64D2F
-:10FB0000DF17782AB7F95EC1F90EDBE3A1FD8E0A93
-:10FB100029EF679998067478A320C31BD7B5FE9D7B
-:10FB2000EC8B1F4E9F56A5DDCEA87F86FB0F150BD5
-:10FB30001C41DC8FA868C90B50BC698E42FB245560
-:10FB40002DEFF9305F3174A893E46482A21CEC4776
-:10FB5000263FE37251630725FDA90248D0FF34A177
-:10FB600067409FAC4E807555AC5BDF9A01457F01C5
-:10FB7000C301F1FF9089FB7FD1EB4A8BE7F059314C
-:10FB800005FCE04128764FACDC918D78AEBE50F19B
-:10FB900082B1B2F4F8EE5D978AB85826961FDFADB1
-:10FBA0004B3F3293A61162309FA7E23BF3BA2D9DE3
-:10FBB000E481CC0730DF88CC361AECB5078EEFAE87
-:10FBC0001B40F44B7A8969200F2E0EF3FB47AAFFE6
-:10FBD000A39FC1BAAF0365BC6430A61A9B4E784A96
-:10FBE000A7755E2BD619F807530EDAC270B9AE6549
-:10FBF00037C1FB23338C07CC632EE2A031DF954461
-:10FC0000FBC9603FD03AAFB7358C47BD7ECCD2310F
-:10FC1000D08BF184ED1FE60460FC4F7F7EC2C18073
-:10FC2000EEFEAA7538F0FBA1BBDF77E880DF4FEF6F
-:10FC3000568B917E6F117A52C22DCECDE9E166B717
-:10FC40008FB9511ED69C1AEE8F8C0B2D4925FD368F
-:10FC50003708338CB097E66F4A400BAE335FD994C8
-:10FC600062C84BBD576965D5B1E2A097BA39BEE607
-:10FC70006E5E6FC9F2E0F87E178E7F08F40BD2CD6E
-:10FC8000A16D8E20FAEF723E659B0759D09EFA6BEC
-:10FC90008B9585D03FD3DACCCCCEE5A602F4EA171B
-:10FCA00074193DCF9DAF24507FE50F71395B0A6316
-:10FCB0002D01B8FA5BE6923C8D5E47F9A79E093D9F
-:10FCC00000DEE52BC172F1F0FA7703DEFC4BEEF9B2
-:10FCD00006EDD3E87596068CF27566BD312FE57E8C
-:10FCE00085C037889B7AB4F3CB1B8CF52A5AEEA5D6
-:10FCF000FE2B502ECBEFB0FE216E61170E67235006
-:10FD00000ED7DA7B25F9CFA0678FD680419ECFD85A
-:10FD1000911A1BA5876A18A5CCED217C2C6879EF78
-:10FD2000A748370B9BB758B09FBAE078279033B3FA
-:10FD3000B600C7A33D8DFBE3D07406EE8FC33C6BCA
-:10FD4000712219B87FEE1BEF067C999D51FBE5628D
-:10FD50007DD305FC99DD45F4351DD73310BF6BDF2E
-:10FD600046AEE7F8AE21361C77B25CD70858977AD2
-:10FD7000EEEB92EB91EB93E595203763C90549DFF4
-:10FD8000CCCDF5CDACC6292B320114B5DBBFA038E4
-:10FD900000137E8826F0A3D957911FA231F033F8C3
-:10FDA0003AB91F12607B58049D45D35105C2019991
-:10FDB000D8C9DBD9847FD2493F2D6B081E12CFD022
-:10FDC000613ADFB70CA5E3BE25D0D181283A32E4F1
-:10FDD000CB1B8CF9AFCDEDB9C8DF402F0722E1FB7B
-:10FDE00075D4791999CE70F7E2EBF7E8139C505E61
-:10FDF000CE7C2B9CB4FE06E2C3435AC3CE9F21DFC8
-:10FE00003572BAFFABC0FBC76E5F2DE29D69FA4049
-:10FE1000946F45CB325437D42B5DAD38919F66D665
-:10FE20000D9A807C3898E9D4DF8C6EECCB8D02FE85
-:10FE300065D5666601E3A0CCC348AE956D53833C9F
-:10FE40004EA7DB4B00BE73041E2A576EB164403AC6
-:10FE5000A7BA82DB3D41CE2F0057B27BE6AD6EA53F
-:10FE60003802F85131F94DEAA9CA266379155B4D7C
-:10FE700078A88AB27F82921EBDCC8BF4E8FFA9C31A
-:10FE8000A6249D7DBDAC6B9C88E248C777F5257B99
-:10FE9000F8B8C7D303EBF901E76D68E76BFE11F81B
-:10FEA0001DE044FAB263694210EDFD7D27C18F4524
-:10FEB0001BD4E91F6101B8B47F9C437A5CD2A75C74
-:10FEC0004F956D35D1671533FAC9A5E09061FCB740
-:10FED00074634A10CF0340FF039BD18EDA68263B40
-:10FEE00029C016A733A033DF7233C9C3B2E664F268
-:10FEF000D3CBEAF8BE51D9E6E4A0CAE30F7B30EEDB
-:10FF000022F1B0AF6EAC2583F094E745FDCB9ACDDE
-:10FF100006FA96F889F673E7D5B7EE4CF7741F0723
-:10FF200089C0CF816EF07320123F7BA2F0C3EE4EEA
-:10FF3000E17266D11FFBE23ED9F1EA38AF1AC36F16
-:10FF4000927A886503010E0FC7138B33393E98E60A
-:10FF50004D437C9E583D8CF0158DA7E27FCD247CCF
-:10FF6000B08F1D0CE3CC337AB35BA7C2F75B15CE21
-:10FF70001F336AAF2C467DFD959033EF827CD22DE6
-:10FF80008CBD07F24907F9F43EC82DCC7F50934E43
-:10FF9000F90F6B3C94FEB9A61FA50784DD27F9066F
-:10FFA00008C08276E309C12F27A4FC62B7A5A3E9A4
-:10FFB00050FCAFF7879930741BB8EBAAF160CF5CA7
-:10FFC000AD1BF5DDB46B8DFAACDDEC9C908E76EE5E
-:10FFD0004A85F653CA7C630CF599E6B14C417FBD66
-:10FFE000DF90F077B25F3D96A9C0EF374E4A31D42B
-:10FFF000BFBE3ECB904F48F5D0FCA614F7367CBF71
-:020000021000EC
-:1000000069FA45867CE94900C210A46617E1E13629
-:100010001B13F104178FF38AF334DF568FE871074F
-:10002000CCF7DBB7CD541E8D0F89D7596B4DCC0F54
-:10003000539BB916D606FD1E68003C41BB2F3F728C
-:1000400030A4E3159B87BC3312F2FB369B295EBBC1
-:10005000AF2EE53EB48FF66D4E4DC438B07F852A85
-:10006000EC08A78545C8ABB1754BE99C4D69D0EA52
-:10007000257B6147E00999F728C8F78CF3CB1E353B
-:10008000887139C01F8F673C63A57D884360B7398D
-:10009000412F1C52581DA6A85892A0FCBBB6D420D4
-:1000A000F273F1BF543D1DE9E99938B1CFA4507FF7
-:1000B00047DEEBBB6115D197A729447C6B25FF6711
-:1000C000663B5F1F53066721FE0F25333D192651FE
-:1000D000B9F8C3BD1AE0696E7EDBC010B49B9E17F1
-:1000E0004ABD01DA1D6D34D3B91BECD709F9CADF5B
-:1000F0005AD77339A2F7407F220CCFE0405CF70C4F
-:1001000093EFF254C0DF91D9C18124CFEE4E25BECA
-:100110008A86FB018B9FE01B403E50C2F231CC67C8
-:100120007CFF10845A06CA9999666F1AEAA703AB36
-:10013000CD647782FE48C4F119DB4A747C40F34CED
-:10014000C0751FA8CF6328AFE4B865AB55F2B39074
-:10015000FEA8FEFDAA1F6C0426F554A05EF1B31E96
-:100160005DE9E6278B46F4C0F544DBB732FD1A782B
-:10017000D51F612FCCDBAEFAD03F6243DBB56B2FCE
-:100180008E5C471DDFB748E7FDDF26E4FA825E6F2D
-:10019000ECB59B50AEF74E42BFE7F01E95E8EC7011
-:1001A000AF86E1E9BDF178CC6BC3EF80FC97258188
-:1001B000831AE49FB0FA17205CE79B563FA140BB2F
-:1001C000632DFBEF1B03ED8E3C6BF6E2B0F39E99C3
-:1001D000DB93F619847DDD556EE9D23E4853D2D1CA
-:1001E0008E7092DEF6D4C120B4FE20CDF366D6B474
-:1001F0001CF1E65CC0BFEF1FE65885719A99C01EDE
-:100200009176F77E33B70BFE2795FBB552BFB7A4A7
-:1002100072F932D3C4E99ABDA2909F8AF64E9F0824
-:100220007D2CE5F29A546E4774EA65D644F26A363C
-:100230009EDB81F52DD8640D06F3A88D13F97C2E75
-:10024000470FDB8D7202C69D6779F661E4A10AD67D
-:1002500046FAF3883938BB2D0FDBAFAF73517BB350
-:1002600097E2C5429FD88081501E5508BEAB6C50A6
-:100270008221E21BAE17CB45FF0CF54C84FCEAAAA9
-:10028000578CFAA45CE8D17216156F6E30EA375FAE
-:100290000277E2E7C1B8A82FC3F302FB186036DB90
-:1002A0001FDC3999E6AD788331E651C13A422ACE56
-:1002B0007B33DF77889E57F43ACE759EB3BD53C625
-:1002C000250F8D18376ADE12DE14B08EC08384FBD2
-:1002D000EC0087E7EC1685F0F5B9B0CBE4BE8BC433
-:1002E0007B05F34DC6F384150F82BCCC0BD341A71D
-:1002F000DEDF12A4FD952F5943A21DE87EC1DA2D41
-:10030000D78FC276EBDE23FF62BA2BD4D794CC58BA
-:100310004AE0F355C53931F655A2EC831F0B3E3840
-:100320007B6DB86807F0286F54F5B881867AD45E83
-:10033000DA077302010BC661E788F8E6D9E659854A
-:10034000F5069FCB7C63DB33FFE9BCBF4F15F1B9EA
-:100350002EF650DF987E54A71D7416FDFB89399444
-:1003600083FAB7234723FDF3ADE6FDB0D08DFAB88D
-:100370002FF905DDC9D7D9420F97A35E86F4E0DADD
-:10038000E713D16FFFFCC1E7693FD7F26C7922DA3E
-:10039000C507D7CEBC2F002C7570F34CD2C3158F78
-:1003A0004A3DECB744EAF7B16B4B7FFD73A4CF4DE8
-:1003B00071B41F317B875FD8DDE0B7A01C5CAB3028
-:1003C000D20B0F72B95781FA6A00E9AB0BB0DE4F5E
-:1003D00067FB2F403A8FF84E7AECA733FD23A83DF8
-:1003E0007386D0EF02C919427D25F5A9D4B39AC905
-:1003F000DF270DE1A5BEFDC19DB0FEAFB6AAE4DECC
-:1004000055AAEB739DB8CFD18DDCFEF7E16DEA8480
-:1004100077DE39C0BB0CE14DF60F87F767F51CCED0
-:10042000FB5773B8AFD8DC3B11FDDBCFEA7B93DD24
-:10043000F3D9E6BE04EF59AB00DE64F77A8C764F51
-:100440003DC01BED7C84378C5BB6C323E0EDE5F04B
-:10045000AE177A67354F6775816BE01694273FFDBD
-:100460008DD58BFAFC505C2815FD91435B5486E7D3
-:100470002C3AED2261BF48387FC71A9E403BAA8BB9
-:100480003D73BF95617C76EE0B8E2083FC11A5B089
-:100490000722E068C31B89385E78FC4E3B665ADA57
-:1004A000B0083BE61CF1B390F9E81EC2C296373E95
-:1004B000423B5ED1B95FBFD0660F21DF82BF73348C
-:1004C000529E2B1E94691827F1DA6C4807D9CCE3A9
-:1004D00023BB46EE77F919EE777DDFF79B5B1613AA
-:1004E0003F77E447C6C9ABE243668C2F756C510871
-:1004F000DF95B715261632DC4FABA679DC9EC6F524
-:10050000B1A2EB1437B402DDC4C3784BD23C24CF84
-:10051000158F93C711D7C1B88EF07CA3BF4F46D2B9
-:10052000437D6E8F1D77DE98C6ED804AD5447EC729
-:10053000020BF73FE47996E5621ECBD3B81F726FCA
-:100540001A3FCF770CCF8340BFC72EB58AF3D9E3CC
-:10055000289ED9193F9170736A5F77CA2BE42BAD3F
-:10056000231BE1B477F47B66946B7BB12D19D380A8
-:1005700080E168C7F0F6EF98EDF56857DE3CF20DC4
-:100580008A83EE8DF379D0DEDA9B6AF3221D05B6FD
-:100590005B89FEEE89E7F16FE64ED2909F6E12F214
-:1005A00076468155C720EFCD05F7F830857102B842
-:1005B00009B1A2F0F5E54847B7A6EFBFDD064B5AF3
-:1005C0006AE2F6CA5217A373409780B98E71583CFD
-:1005D00022733AE54C74638C5B2FC0F8EC68C60953
-:1005E0006A24C1D39007B852FEE587AF9BF8603606
-:1005F00063FFCB3C17239E17204C900E4A93C8FFF5
-:10060000BF1AE3C42E4C35A2AFA91A0B98785A8FA3
-:10061000213519379E2CD679DD48164A82F5857624
-:1006200033435CFD8690297401C0ED6A2DD48AF0B5
-:1006300033D93C66F4037CC5CA60F48F172C3BB7F2
-:10064000F9BEF3B07FE283059037F1C38B1D772AA3
-:10065000C10D00A79B81B9912E6FD1D80E7530C7FF
-:100660001BD25D95CB13A07A8B14B13FC4E3F91272
-:100670002F83A0FB48F8DE2CE607FDD427627B4BD6
-:10068000ECB8D1C769D2FFE576E67CC1A7F3259D1A
-:100690006D36F2E73F249FA03D0B70BB59A4DDD11E
-:1006A000F9DF44FF7F1374FEF9798E576965215A8B
-:1006B000F7762BE1518E7BB548BF4BE3F6B29C87B2
-:1006C000A45F26E24F2690184847071A6AC95E9A27
-:1006D0001315FF6591712A3556BE53EE984E636A25
-:1006E000E99885F3512E8B237EB9D9D2D4B7DADEBF
-:1006F000B51ED8D184A24ABB8DECBF85AC9DC7B3D3
-:1007000084DD2FEDC5B968E761BCB291DBB59AB065
-:10071000C74BC13F43A22BAD8FB077E17F939BB70F
-:100720008CC7783E18267EDAB7B0DBE8DCC6E40575
-:10073000463BC92CEC2273945DC4A2CF85083B29AB
-:10074000FA5C882AF817EA727F459C0BD184FDDB9E
-:100750004947696681CF80611F7E3A6B33F3FB6244
-:10076000227E27F4F378D5DE0FE5CD7425DE8BF6F7
-:10077000FEB14247C09484F125338D371DF800E562
-:10078000C82771FC7CC58CA49F4E463B787AA24555
-:10079000C3F45367AFA41B18CA1B55EC1B0527E213
-:1007A0003E532DCA4D9EBF57CFA62898C86F7C0BCD
-:1007B000F767AEFD01E64BF92727EAE0BF1DFBA373
-:1007C000280F401EE975B9E4DBDFF2FC43B2FC7789
-:1007D0003CBF52966FA3F18EAD91FD8BFCFD51E5B0
-:1007E0004BA3CA1FE1F9F13DB64D0C207CC4BED32A
-:1007F000F4D10AED3BCD41BE02F84D5F16227A9A44
-:100800006E7A8DA7452C84FB8E67ABB7A8876F0ED9
-:10081000EA67D571C081F6C99D19FA1CB4AFAE4D17
-:10082000F5FB7AA05F3845095870FF714F305FE8DB
-:10083000AF98E7E7E7083E5D98EEA3F6D2DE857E47
-:100840006EFC77FA39D5A34B3F653D52CFBF9FDD94
-:10085000E97C7D11FDCCFF77FA1998619C8FB4FF7C
-:10086000DEC8D457E0FAD801B7E15CE4FCFFF1261A
-:10087000A1FDC8F05C24807EFEB2A6DC21D0FFFC86
-:10088000E75ECA9D1D115F5878D2C474B013AB4E99
-:10089000324ABF6CFDB3C503F359B8ADD53201EA96
-:1008A00055413A36625E0BE4B960D6AE4D8DB05F0D
-:1008B000EEED6112FC743FBFC7F5DC61DA3F9E6F5D
-:1008C0006A3AF828F2E3681E678C5EDF4F7AF0FD23
-:1008D000BEBD783E20867F727F0F6E8F6CCFD61B99
-:1008E000709D8B5146423AB636F6F98A8F457FD3D2
-:1008F000E3B93C9F39DC61F35C82FBD9FE5ABCAFA3
-:10090000377B5DDE608C57DF915AF4688F33C67F8A
-:100910003B78FCB785C77FA7BBDA6E0365C53EF899
-:10092000D5FBF7DAC05F9DF82BD6B91F8C71D56265
-:10093000ABE4BB2313C715503C8FF2CD3D0EDC1B3F
-:1009400080F6BBE2F9F99119232E8E4779D09E9754
-:100950006072829C08B84B3FC079CC1871E904FCE6
-:100960005E6875E497F2FD03A28B80DBD784EBC64B
-:10097000FA18BFF15B783CCFFFA64AF13CFFC004F8
-:100980007FACF307CF09387CD083DB67BB00CD6831
-:1009900057C979C8F1C120BBAD0DFA3BB02C63102B
-:1009A000DE8BFCD85DB887E022C6FFD8ED6F8D1CCA
-:1009B0001F963B10BF9FEB3C5E1174B147E0CD57D3
-:1009C000A0323D42DE4F1D9760C85F3B2985E9910B
-:1009D00071E56BB30CF969D37B1BEADF34EB22437F
-:1009E0007989B56D68F579D8F9550E473C9E6FF851
-:1009F000B4E5BBFFBB19EDD746D5ABC07AE66EDFD9
-:100A0000F87F63A0D6713C364CF6A887E27B47F0AE
-:100A1000BC21F29EA66B91FB525FB1363AA719B189
-:100A2000EF61D85F9AEFDC41E7447FAC7DA9133DCD
-:100A3000C4BEC7603C628E7AE8835C3C5FB2D0CEB5
-:100A4000D7F3D54BFB2C74BF03F507D0F715D8505F
-:100A5000453E0F50BC7D6CF33EBA47F7500F2E97C2
-:100A600017662FD2C002655590A2DC9F00F22909BB
-:100A7000E8A3AD955DBC0DCF57E739E83C4CE5C91F
-:100A8000A98CA5201D05062C827AF3EB8B29BFF0DB
-:100A9000643CF5FBAEDA3681CED1BFA8D0BE484962
-:100AA000D68C65682760FD9FC07825BFBBA218E182
-:100AB000B3701B3F3753A2FEEF50EC67414331B593
-:100AC0002F51D92E05ECA18963B97E2D415B06F229
-:100AD000EA70C72AD4ABAA2594FF18CA138B83E403
-:100AE00049D2C99B68FCAA93366A9F95CEED3473B0
-:100AF0003B9FD7F8933EFA2EF19E97DECB70EFD353
-:100B00009CDAA895D9B13EA3FA579DBC9052B9CEB4
-:100B100037FBFDC68D72CC9CFAED043C27FCA65B2E
-:100B200071927915256F4F548F486231E4914CAD25
-:100B300042CEDE7C929F43EF95A98F4887794EBEC7
-:100B4000BB5DC37D2A66B739115E93470EF2CC8E2A
-:100B5000E023F5B51BD1336056778719F5F9CD90B1
-:100B600046CAE35BBB91C797A69B0CF776A47E6150
-:100B7000C11BC9FEBE45DE53167C72A1A82FDBB790
-:100B800091ED04787CC14A76D4984CBF2F1DCADB06
-:100B90000AD9B4AD241FDB72717FE8C79A3FE0D950
-:100BA000A6903FD34EF730268FF498D03EBC2EDD72
-:100BB00064B0D3CEB68E2251FF5D952D417DF2EE0D
-:100BC000E597B7E9D05FEBCF860C41B92FC79D9D64
-:100BD000CEEF9D3367C70FE8B756BD92E041BE2EFA
-:100BE000C1BDD6A161BB1DBE338C7356BD62DD8015
-:100BF000E799AA12C16F87F1C7BE1A17423A6E7DF4
-:100C0000354E43FDF075B67F36E273ECAB178CC3FF
-:100C100073747A8B556364DFE81508B7EEE67B36AC
-:100C2000F9144D67922FFDF59C5F4A059D9609FECC
-:100C3000F30B3E3A51DD83F8F0C4DD30695847D9F3
-:100C4000DDCAC5DBD01EF038E81C96E4CB12F4F305
-:100C5000E07BC945C9E4EF46F01DF1E182934EEA1D
-:100C6000AFF2A447F0B98BF292DFCA04BF48FAF69C
-:100C7000093BE26799FE87111E25B5C0EF787F73A7
-:100C800059C650E4A330BD589C4857402FE9B323C0
-:100C9000E8A1B615E8C541F44272C8076924BD5CF5
-:100CA0002DEF1531E7843498F7E4BA3CC3BDA2C7F1
-:100CB000CE93EEEB05BD94D9437DD15E3557C77910
-:100CC000F19EE47137DF875ABC92C36FB1D93716F2
-:100CD000ED87C58F285EC00CD915288F867F546D8F
-:100CE000898CABDE787220F3C0FAAF39D987D23B5A
-:100CF00052FD4F231C4A4F5E2FE035F0DFDAEF1C28
-:100D0000A6F3389A3968F5AEC7FDC438BF8AF83DF6
-:100D100094C39C0F44C4D130EE87F13FB90F2AE34E
-:100D20006A56DC378ED093DF690DB9E8E77489AF76
-:100D3000151AF70B17B4FEEF7013941FC9D329CE01
-:100D400036C3E47F1DE979DED4E07366C8CF5FF374
-:100D50007C22C6F5253C9BB4505FD4934D00478C54
-:100D6000F735AD568B83DC9E49E0FB7C9CAE251DA0
-:100D700047D3F7BC93BD889E4E545B49EF9C007AE5
-:100D800065117A275ADF483AAED498F05B93E8DCD5
-:100D90008894FF617DB3FEBED148774735A2FFB08E
-:100DA000BE99EA2BE4F44FE7CEA3E9FFC59A743A63
-:100DB0004F24F548B4BE8996EB525F7D92E1FF1E49
-:100DC000E154F4DB7F3EFF317CBA4AE37AEB2ACD73
-:100DD00041F4F3DF92FBFF3C4FFA3F2CEA83FD4ADC
-:100DE0007621CAF5C8FEC66416256640794A06D73C
-:100DF000ABFF6D799F92717EF29E65F0F99F4DDE9B
-:100E0000E76770791F2DDFF1A222CAF763DBFBD3FE
-:100E10003EFC5E06FA00F55E4B8267A390FFA41FBE
-:100E2000E293826792FFDBB367E667C496FF1764BD
-:100E3000FC07F2FF7CF944D26F77FC32F15E6E9FC3
-:100E400031B4CF9448FB8CC365D7855C0F44D86917
-:100E50003C9E027CD55789E49B0DF78D46BE39E652
-:100E6000F6E25940C927926F24BFDC2CF8E356A163
-:100E700017247FBC9AE1BF11E125F963C1D668FD53
-:100E80007066FABAD95DCD503FDC0A69247D593BC2
-:100E9000F583912F6EE9A4AB73E38B4919E766479D
-:100EA0002CCAE0F7DCFF8B74B508E927065D2DFE40
-:100EB0004FE8AAABFDFAE150BCAF766228D0515E94
-:100EC000988E26BEC5B8DDD09BDBFF9D7462C9A19C
-:100ED000B8CEC4D3FC1CAFA45389DF68B9F85CA6B4
-:100EE000EF61C4B7F41BFE5BF2EFB1F3C4F3CA7356
-:100EF000C4F36681E71FD15E7C31165E99D36588A5
-:100F000047007F5F43765C48A32341DDE1D5BC9673
-:100F1000F397CC2F0F6952EFA6A0DE057A69FE4F3A
-:100F2000E8A5642C13F18D4393304E39F11722CF8D
-:100F30008E4E423EBC7EA42C3FBC5AEF837286C9C3
-:100F4000FD038A8FBCAB8A7CE0C8DBE3605E131FC5
-:100F500060E1FD05281F5F90D4194F41D743D6FFAC
-:100F6000F0912FDE5E4DFCCCCFF9307FBBC6F7D5BC
-:100F7000447E28E41D11F99151F975BC7EA2D6CEAC
-:100F8000F8B9CC20D7032A6E3572FAF145D82580FE
-:100F9000C909787E62F236C589F1909B0A8ED1FE2E
-:100FA0007378FDC727E905B82FA888FCF76FE37AA7
-:100FB0006FDAC6F3A71EF9C7EA8026FA4BA37819A1
-:100FC000FD599B145DC5F320239560AFBCAE703E08
-:100FD00015A5F7F04F33B66778CEEA7CDA239EA9E1
-:100FE0007D2F6A1FB29EC7F83714C4BE27E2C8140B
-:100FF000F5445C81FA07585ED314FB1E4CAAA8DFA7
-:1010000086FB4504AFA43508BF368B8467E21AA47B
-:10101000A7F18CE77B3E9A581218C0A7AF47ADFFE7
-:101020004CF35732BBAEDF636C1F3A13FCAC5DDA96
-:101030000BFA9963A4A724CDB7E304CC23C9AD3838
-:10104000D13E5EE88B5B8D7E40983E324A703D6DAE
-:101050009D71FD68FACF2C41FA5FC864FDEC35E460
-:10106000E7983AEB737E90F405EDFBF1F7F7A8FDF6
-:10107000A847B3D6207C003F544E79ED0CFCD01429
-:10108000952F88E21F41FFC4BF28E7013E7D63C85A
-:101090009969023E5F8973E46D45DC5E6C13F7E28B
-:1010A0009664F238AD3F93DB637324DE23EECDB05C
-:1010B000083C3371AF2662DD04A71BDD72DD052518
-:1010C00093605D6D2E5EBE3873E49A4076381FDD06
-:1010D000DF6D990525B83F11EE7FF49F506FDC2836
-:1010E000E0B62473CC9F025C1E2AC89795442080EA
-:1010F000F76D4A80CE61215DC458B7DE95AE0251CE
-:10110000ED75F319DA4FE8DA5E8F6ACFCCEEF3694A
-:101110002FF036290AAFC551781D17959F2EF34140
-:1011200083FC9372B1ACF9FEE5696E8C4F2A74A70B
-:10113000374CCF57113DCF774AFA9DF827A4D730C7
-:101140003D4F22384F6D92F2B0640DCAC329280F6B
-:101150004787F3D7A0BCA0FCE4123D29525F5CBDD9
-:1011600046073CDF502FEBFBA8FE4D75B2BF29545C
-:101170002EF1C802534B70FC1B870A7D11B8E64F55
-:10118000583EAF85B7FFEDA3D7FE29D0E70CFCD0C2
-:101190001005977551F94054FD07CFA25FEAA2DA16
-:1011A000DF1D55BE3A2ABF362A5F6F6C5F3A4B216E
-:1011B0003E2C057A40449C8D2F5FCEECF47F3AF5AF
-:1011C000A96227BBCDC057136B79FE8F8F9696D43B
-:1011D0000F88C867CE2C89E40BB9BF0AB23680FAF3
-:1011E000CADC8DBC7CBE3BBAEC17AD6F79F95FF100
-:1011F0009F19B4CF63B00B5E578DF95655CE7BD196
-:101200009F6E1B10B91F5A5D8271966EF75DD8C232
-:101210009271917649A092E844AE53D69F70EAB499
-:101220008AE3FD25B3B2A411F7758AC47EA48BA707
-:10123000A0D754D49B55222E3301CF0363BDF85061
-:10124000DFC59176086BCAC775B6FE8CDF9308D4EC
-:10125000027E30CEC6BC168CABB426252D7912EAA0
-:10126000BFFE337509EAD1BD4B52E81CD66559DC87
-:101270008E7C3DA9675A39E45B136EB5E0FDF3D669
-:101280007BC653FA9AAAAFE8005EFBFBA37797D818
-:10129000FB637912C1E7BBCC25254B81CE4FE225FC
-:1012A0002568EF7739D3F01E075B6566FC3D24EFB8
-:1012B0001344376BAC83D08F2E5D7A11ED5F953D73
-:1012C000346502DDD3586EA67D0DF8A3FB3AFE55BA
-:1012D000E3E99CD7AC3A9106AEA0F4D57FFDA636E3
-:1012E00011CF2D3CAED0FD904BBF6D7A0BDF5DAAC8
-:1012F000A8EFED45D4BC02763D9EBFFA6CED0574B7
-:101300002F647F5C359D7385FA0CEB57FCE07967A1
-:10131000F250ACAF3AF148C941F88EF6F0C195EA07
-:101320000605E795E888C7733C074F79DE41BB1691
-:10133000CA9DCBE0FBC1E573D3D0CE3AA878121595
-:10134000BCC7F0D8AA92F40C7C3FC12AF0B9CA51AC
-:101350000A7C5D6AEAA417D21FB393793E356B55B8
-:10136000C94698FFC1472EA0736EBFCCD2D3B2003E
-:101370004EB766EB3DB286E13CB99E7AF55F7CDF05
-:10138000F0E5A36569484F79599C8E5F39599656A7
-:101390001661EFCCFE4A23BCBF6AF1DC86F37C35D4
-:1013A0003E47A1F3E8AC2905E3DEB3849F09F4BB13
-:1013B000E4F91876CF0F992AF57BC0BA84ED8779C6
-:1013C000B7DE7BDD5807C0A5F54585F0308BF96B9E
-:1013D00031CF9A63EF8BFE90563410E71FA6FF754E
-:1013E0002467C9DF80FCC8AC47D604D00610E73BB1
-:1013F00019BE3E85FCBA392E1807F09CE5D6276049
-:101400007D96DE943FD511C1A7A2FEA7017E7EF98D
-:1014100053A88FFEDEA781BF3822F72F64FD8A44D0
-:1014200047008D8F2F1C0E0DF1B657AB3988E71E84
-:10143000673F6E263D31FBF1D4BB3B701D405F7DA5
-:1014400059D775D46599895FBADF2F7DDAC8B7ECB3
-:10145000E933F2EDD4C7369534DABBE7DB0AE1D7DE
-:101460004C78DC4CE7F82B863934DCB72C7AFC8FCF
-:101470001BE9DEF1A2B8C1787FA3E2712BE1B7DDF1
-:10148000E10838715F35D1A125632AE8616916E763
-:10149000B3B12AD36C8329A57B1B723FF0F092076E
-:1014A0001EC663A64758F0FA1100BFE3882880CB18
-:1014B00071796F2D6A7FB072F7F396427686FDC11F
-:1014C000B3EC0BE20D78E4DB73DD1FBC232B7A7FDA
-:1014D000D09C8FFB8F15627F70EC3A1ED7A958C243
-:1014E000DF65199BC2E3C4076A02F81832AE37E021
-:1014F000C47BD60F727D54C194A00DFE79C5BA4548
-:10150000F45EED1121874AF15DB501C85FDE5CF440
-:10151000EB673F1E4770AD7862EEFF3D02EDDA9754
-:1015200096B823FDE835821EA07F86F798653F5F59
-:101530002CFD792ECABFB1BF067F18EF4326B3E753
-:101540006ECC433C65E4E23EA6AC57B1EC67F9BC17
-:101550001EF8D3E03797AE54797CEA052BE9479023
-:1015600009E92CE23EFAACBADD16CB80F0FDB8CF2B
-:10157000208F4F2C44DC93B320BCE4BD2DFC4B1FCB
-:101580002EEC730FC91B7A6F7ABA49A1FB5D20E973
-:10159000E85ED4CB593C1EDA94C5EDDED25C2FDD7B
-:1015A0000FAABCCFEA5DC6CF2BB1CE7BF1781ECCA3
-:1015B000D4369BF62D7F6FA5384A555D9C1E97C883
-:1015C000CF536C1D40E7C6350BEEB778B85C795940
-:1015D000D05F9567CA15482F50FE9186E7D51C5CF1
-:1015E0007E56268BF700A1BD09C63986FFEACDFBE2
-:1015F000CD181831BE22BE433F9EC470BFBB4CAC59
-:101600001EE33458BFFF408463CAF5D3707ECFAA6F
-:10161000C4C7B0F8FB46A23DF8AC3A04FDE0D29551
-:10162000AF4F588BF92D83F046072B7DEE7DD22FDF
-:10163000F305FEDBC5B9B932C8E33B057B041FF9EE
-:10164000551E1FDA23E025E9409657AEE4E7A72AA6
-:10165000975BC9DEA95CFA21F55BE9684B43395D0C
-:10166000F98299EE797F28E65DB634A7E023A0AB36
-:10167000327312BD2BBE205062C1FC820685F2E19E
-:1016800076A9B948A75FD6BD9888F4B33F2ED41782
-:10169000F556C7A2382F9E5794F1B92FEBFA6EC0BA
-:1016A00038CE2C679B03EF6BCDBAADB70BE5FC5E74
-:1016B00067C882E57B9BF24C98D79DCE02CCEBDAD3
-:1016C0002594FF529C57A13FA41785E379C1E6D723
-:1016D0002DBD60BC1FC47ABF7AF6FD7CD46B95B972
-:1016E0006DF9A87F800EF2B310CECF28A4B7176E85
-:1016F000E6E7F8251D2C443A00BE9B27E860E1B6DA
-:1017000017EF407E5888F81FDC958E804E77D0F713
-:10171000ADEB2730DE7E07D289D47790AF33BB3074
-:101720005E27F2300EE64F213C8751F9385E1E18D5
-:10173000C0CF03B6D3F9C62A719FB3533E7583E772
-:10174000CC6CB17FB6D44AF236339BAFBB7DE50B90
-:101750008988C7AF9E7D7D27C6892BB78256F7C47F
-:10176000E00B01972A844322AD83EC902A5C7762D8
-:10177000180E9DF42FF8B18AF175CA755769020EDB
-:10178000B25CB4CFCAE6EB5CC004DCB65DC0F94F16
-:10179000F01BF233BDBB24D6E77719DF97D7C5FA24
-:1017A000FA8B7401D005DE5F63787D53CA0928FA8D
-:1017B0006ACB7A8A13497CC9794FCDF6483DA22776
-:1017C000BBC2786C37C57E5F7B54369727FB96F794
-:1017D000C86D06B87D09FE189D37007AD522C693DC
-:1017E0007423C71BFBDB2957E17AA1FF10F62FC733
-:1017F000DD1B48D0B09FBD8CF307D227CA4FC997D5
-:10180000636B675C3508CF4307BE72F4467B5BE0D1
-:101810006F6A367F0750473B01DAEBCD0AC5A9F75F
-:1018200009FF7FDFF21713CB22E0E413F3967486EF
-:101830007F18BF92F3DDE5E271DFE8794B3924E7E9
-:101840003DF69E1BAEC2EF72FE925E257D4A384A7F
-:101850003A95F703A3E995684DEA4FD520EF493F44
-:101860005E91FD8DC56FEFFA3D3ADF6937D5A5EF83
-:1018700088BCF7B65F9C77EF48653CDECF806A2373
-:10188000F48ED4F3117A65B516A157AADC3ABDB728
-:101890003367E8A27CD4632F64F37329475893A578
-:1018A00010FA5B70A86D42A2276CAF5EFA6D48C556
-:1018B000F76E166CE3E7D724DC171CDD41F45F29D3
-:1018C000EE6F95AE7CBF6404D2F9D366DAE72C5D87
-:1018D0003E9EEE69CFDD387338D211DEFB40B97E13
-:1018E000B871D810FE5C9B33ED7ABCFFD1F8C0F51F
-:1018F00037C1F759CDAA97E43BF4837C5B7AFB10A0
-:10190000A6D07ADB4B70FFB4E34ED58976FE988D76
-:10191000C3EEC6FA631C3D93713D7A630AE5752DEB
-:1019200089F483B48FE5B9BE5A33A78B5F67737FA1
-:10193000F5E1CE5411E7F96AF371FFBD637D1CBD7B
-:101940007335DD22EEBB6EEF417E489505AF5ED26A
-:10195000FD59B2C7E658982D839F0FB765C0F7DDD4
-:10196000E6B6DB518FECBEDD3188EE1FA83F0C2FB1
-:10197000E3FE23CDA324C5F8AE949CC71382DEA357
-:10198000FB93ED7789F3D9FBC5FC0FD73D7D3DEA8D
-:10199000C1C39BFABA70DD5F6C8FA3F771BE887A02
-:1019A000AFF37CEFB301FD46DD175B46F36BCAB6C0
-:1019B000F3FB5CC28E93F47ED6FB5C9FB8A3F6115A
-:1019C000CE7C3EE9680DA37BE7B7812D8EEDC72560
-:1019D0009C7A1ECF05CE6EB03AF1DECF01A477DC43
-:1019E000BF7A41E5F7936D9CFE0F6C1914447F7329
-:1019F000F627FC1ED68EFBEFA17309E5605FE2D1EE
-:101A0000CD4E7BF9C1FBAF473638EEF5AFC88076D7
-:101A1000C737F173145DDE77D8FDFCCEC8F71DCE55
-:101A2000D74E3E57FB58C6233EC936BE1F20E12A7B
-:101A3000FDA45701FF230787E1F475CD1CB28F8FFA
-:101A4000D6F8293DA6ECBB6F0CD2AD2389EE37BC8E
-:101A5000DCFC808AEFD1546E1BF403FAC5A3ED4978
-:101A60004EE4D7AF6B96D0FEE8D19A6AFEEE4AE715
-:101A7000BBCA414A2FDDD64AEDBE6E1ED282F78127
-:101A80005FB12709B91FBD1FC4F1D8DD3D67B9AEED
-:101A90002377727CCA791FD9343311D7D5FA584AC3
-:101AA000CB28C463429213EDBC0A714EE4E05A6E37
-:101AB000471FB2253D3909E07368DD3569F85E508E
-:101AC00079EBB5D7E3F7D9DB1527DAFFDEED531253
-:101AD000D13FFB5C6B4FC4FB5F9FAF95F7C682F4B1
-:101AE0007EEFE86246FB55A3431AF3E4D1D633D127
-:101AF000C9A8A31ADDCFFD12F7B1305EF2433CC591
-:101B00004B98D89F2A7F89C7593AFD59E1CF8D114B
-:101B1000EB1E91E392FB0EF47DEC48FEFD8B75CF3E
-:101B20004FC6FE0E379A9D38EFAF1BF93B16F3C038
-:101B30000FC3AB008736713F675E93427EF1E14D84
-:101B4000A0A7615D958BCC3ADD6B8DA2BFB1508EA5
-:101B5000E72225FDCDD38344D7D1EF8C24B326BA19
-:101B6000FFF663D1E3C539467FAD930EBBC3BF809B
-:101B700013F22DD2A1C4F3BCB5FC7D5B57D3A042B8
-:101B8000A42789F7E87B0EB51646F71902A6787ADE
-:101B9000177A8ADD635660FDD7B8DBC7A1F87C24CD
-:101BA00087CB4575AC49C7FB7AAC96BF63D0253E61
-:101BB0009DC3E5E89B398CD2B21C7EDE58DE5B9378
-:101BC000292C2487DE654C707DE7812AD7E46C9A46
-:101BD000ACC1FCA78C71DDDEDBCBD8CD39CF4DD6C7
-:101BE000806EA70C71BDD00BF2331EDFCCF397B81B
-:101BF000869921BF54F9DDE47190BF2B479F9293E2
-:101C00001A1E47F60BDFAFC5EF8752FC37E40C43D3
-:101C100039CEDF2D3BA6740C5C9217AEFF9EC2F648
-:101C2000BEAC84F3ED6646EFE594E1FC53BB4F3761
-:101C3000E4E8FE9C6131CA19A3FB6365017E1F08BD
-:101C4000FE7CB6343AA746F45426EF07D51BEF07BF
-:101C5000312FBF9F26EF6DC97B59FDC3F7CDD69DB0
-:101C6000CF7DB363E27E5CF4BD3FA585DF97AB0D0E
-:101C7000B0F638C243D47D9F04FE7EE3E217BEDA9D
-:101C800081643557DA2BA86C8787DF3960E9FCBCA3
-:101C9000C0ED820EBFA8617DFA002B5FDDD696E80D
-:101CA00081C91E9D1CCA47FEF658FDF508A72FD610
-:101CB000D5662F76E3FD58AB7712D43F14E4F74F87
-:101CC0001708BB9335A60A3E57439743BD5D79FD80
-:101CD000E99D8B5F0A7A3A9A17CAC577870279DC41
-:101CE000CF817A74FEAD78D915A958EFE8967BFAC2
-:101CF0009403DEACF8AE9F8B5286F7C5AE84BE4728
-:101D0000BAE8BD3FA6D2FE6E90FAC37A89A8D73D45
-:101D100033D379FC9DDF2F947892F0EF82179802ED
-:101D2000DAA5261B33E3FCFBB3754ED4C7123FF292
-:101D30007DDBC52FF038CA62A5BD2E05F3CF2A740E
-:101D40007EEE0B1BBF0FD455CF6DB420A8E7AC9B24
-:101D50006978C748BE23FB63C7835ECA11F7C20711
-:101D6000B14191EFF45688B6E3D5E91E7C677471F2
-:101D7000AA8DDE3759FC786FD2272C703BD181AC0D
-:101D8000C7D6A5107DACC85309CE739B19BD4F545F
-:101D9000D29C49E71D2735BB284D3C994EDF0F3FAC
-:101DA000F9D6502E7F381E4A9EEA41EF8A973C753D
-:101DB00041117F74AFCB3B49FC3D6DBB8DEE1B2FBA
-:101DC000DECDF5D2E2EB548A5332710FCC27A6E375
-:101DD000B3D7535CC7C762BF0FEC93EF03EBE63397
-:101DE000BE0F2CE16B15F8897E2FF8BADD43D2D1F6
-:101DF0005F95EF05CBF708DBC47DAFE87783EF494C
-:101E00009C40EF064FD3B91E897E37580BC479D159
-:101E1000BE3567DBF9BB16FEE87784DB355CF7F58A
-:101E200005FC1DE1EBA619EFD3990BBE21396D2EF0
-:101E3000E8F28E9219E9DBEA33D6FFBBD42FFD59C5
-:101E4000FF33BED39C6DA1F7F0347CC71CF2D78B57
-:101E5000779AD18E43FBFCB8CEDFDFB3C6F375B7FC
-:101E6000B1A1E9C8F7FFBFBF4F7EB677C9A3DF2195
-:101E70008F7E7F7CC8AE5F1AF2C3DA1E35D41FF1A5
-:101E8000D10643F9A8F6670CE5630E6D35E42FED36
-:101E9000F883A1FEE5275F33E40BD95B86FA636D17
-:101EA000EF1BF2E39D7F31D4BF227DBFA1FC4ACF5F
-:101EB0009786F289FD4E18D7A3F927E4223F7BFFCE
-:101EC00069683799797E81EF7BDFE036D1BB26C523
-:101ED000B946BA1B97C3E30AAC0FCB45F9355E9DF3
-:101EE00044EF241D6F52F8FBD2DDE8B124B0F7B403
-:101EF000887192751B3882E17C4AB1D3904FF5A569
-:101F00001BEAF798E6319467F8FB19CAB3E6780D37
-:101F1000F99CEA9186FA3D97E8867C5EA0D850BF8E
-:101F200077BDCF90EFDB30CD50FF82B57E4379FF98
-:101F3000E01C43F9459BAA0DF98B9B9618EA5FD2EA
-:101F40001C30940F0AD51BCA87EC6A30E487B5AD04
-:101F500035D41FF151D0503EAA7D93A17CCCA1264F
-:101F600043FED28E6643FDCB4F860CF942B6DB5062
-:101F70007FACED3D437EBCF3CF86FA57A4EF33949C
-:101F80005FE9396C285FF0A597EE4BB397F97ED8DF
-:101F9000C47EDF18CACD6E46EF6057B2782FEE3B95
-:101FA0004ABBA6C4FB7743BF4FE6F2380AD0527B48
-:101FB0001CBE1F19F051FCC7850702514EE13D754B
-:101FC000173F4F339DE2486ED26FA48A3C78BE071C
-:101FD000EC8044F4AEF2F2D04E4E08DB63D9A72376
-:101FE000CED79DCD1EDB96CB681EFB73FD4FE7A6BB
-:101FF000A2FFB16502BDFBCE022B701EF23DC07781
-:10200000A2DEBB96E995B6432CF25DECDD710DD9ED
-:1020100083CFE0BF5F693BCAF0BDEDCE7E45BC42D9
-:1020200081F52D8EE8FF3EF017B43E8C35D400FFCD
-:10203000808DF4CB1A27E51FAC49A7FCC3351E4A97
-:10204000D7D6F4A3F4D11A2F95AFAB1949F9276A63
-:1020500074CA076B8A29DD50E3A3EF8D35D328FFBF
-:1020600024F8C5986E023F19D367C0DFC5F2CDE0F2
-:10207000FF62FEB99A00A54D35F5F47D6B4D03E581
-:10208000B7D5ACA5FCEF6B829436D76CA2F40F35B4
-:102090004D54DE52D34CF9576A42940FD5ECA2FC52
-:1020A0006B356D94DF51F311E577D6B453BAABE6D7
-:1020B00010A56FD67450F9DB3527297F54C45DF71E
-:1020C000E51AF723645EBE5B21EDBFC968BF2371CB
-:1020D0008C347F6DB0DFA3ECE8687C1C11E3E03B3F
-:1020E000BD43816ECD99F91B6A23FCA7AFC478F27A
-:1020F000BD8AE8772798B04FE5FBB0F23D8BD962F7
-:102100005E1582FE87217DF623FA7CFB7CFC05E9C7
-:102110000F5E9BEA3F45F499630A903F6CE7F791A5
-:10212000EF48F5B39EC370DFB07C278DE7F4D2FE95
-:10213000618935947AC3507A079EE272DD8D572506
-:10214000CE89775BFECAE16CB4A78BFFA5D27B6416
-:10215000EF981DF4BB97293D395C527A9A0CE93F00
-:1021600053FDAE9E907EEFA8BEC504F3FFFEB245C0
-:102170004FFE242FEC275F8DAE26F8375398C74CBF
-:10218000E71199FEC73CB49BC0B0C2FC0D2C40695E
-:10219000C0EDCFC275DD080637E6FDA3ADB9B1D6F7
-:1021A000153DAF7C31AF7C311F99F64FF3F7C5FE7B
-:1021B000BE77E834AF77465D918FEB92F39A27DED6
-:1021C0009D98CC3A9EC0F97DBFFD9B834AEF30FCC1
-:1021D000A53F4EEF02A0BFB34811EFFF75797F8096
-:1021E000CAA7DFAE907D3603FC19DC2792EF0D1CE9
-:1021F000AF36937CC4F709701FED78F5E776246756
-:10220000A8C7709FA3160FF64079EDCF15A2AFE9CE
-:10221000F88E08B49F9196C7EF4B339B8E7A787AED
-:102220008B753DD2E974B0F7D07F02FA2844B8CF5D
-:102230001BA5D27DF5774CC17C85F693CB2D0ACCBE
-:10224000ABC2ED35FC8E4434FE178AFB07F23BD05F
-:10225000D54484D7D72F8DE847F1F7574679104EEC
-:10226000B5267EEF28F0A62A7EDF8B8B6675CCC55F
-:10227000145F649AD78B71A212714FA555654B629A
-:10228000BD1F5F29F0F44E3A7F5FB0366A9FA5BC50
-:1022900027F72FCB7BF2B873C96BBBE99DA585BB34
-:1022A000F87B906C68FB80C877793AD7B3E4CDFEB1
-:1022B0007D22D651D5BC8F9FAF60ED0322CF9FAF5B
-:1022C00010E34BFA512D0EFF7A7BE4FC3AE97901D9
-:1022D000D17332D0736FA2E783B8AF38D9EA49BA65
-:1022E00041C15FC7635FE3FB47FE5F3BE93C913C55
-:1022F00057348BF928AD00F423FDFA02F7D37BB7EE
-:10230000F358137D5F387226FD3E6D15EB18970E5E
-:1023100070BBAE7EE91FF1B9C06B1AEE1F8F71D58D
-:10232000A9C1D23F623AA5513988FE29F0C3CF1125
-:102330001FED4AF5723CC279D3E6C2E5B83538598B
-:10234000E5F8606F717C00BDE8AAABEB3A81FE97BF
-:1023500013FD27EBB40E35B1D840FFD397315D7133
-:1023600087CFC777F2C3C8F97FC52D60A675D0BEE9
-:1023700079D52B5617E2791EE3FA3A6CFF493DCD29
-:10238000F5FF7CD0FF58EF88A0E723398CEE211CA5
-:102390005118DD6F97F623CBF5A70FEE1DD6B74783
-:1023A0004CC1E189BD491FAFC3F9EE4CBF86DE0FBA
-:1023B0009AEFB6D1FBB0479283B951EFA1D07B4DD4
-:1023C000327E759F99C793A2E7A58CDCC97FE7C4CD
-:1023D000C202B82F81BFF33D1CF938D3427C568B23
-:1023E000A0C5385891CF13ABFF3AD1EFAE53DCCF35
-:1023F0000DE4F0774BBA8CE314E3C4F371A4DEE888
-:10240000FC5DF13466186F7BCF3CCE070E9DE6BFB6
-:10241000D4944C7226C3E66FC1F5CB788EF4FF7668
-:10242000E57DD187FCF41F6AE93D267ABF00CFF530
-:102430005CC6E5D13B660FBD4BFC4E611EC5EDA5EC
-:102440009CBD7A248F7B5D2DE35C055171AEA8386D
-:102450000B2B881DF762CC6BC671FBB34F247C2815
-:10246000BEF25A8166F83DB1D784DF79BCD83D947D
-:102470007E2FCAC3CF5925A6F0F7463A1C2AD1D9D8
-:10248000EB01AF1D7F9F6495888FAE8E7A177CD548
-:10249000D0C54E3C176075F0F73ED714C5CF893CC8
-:1024A000BFEECEE7EFC33C995F98E18174803D5861
-:1024B000446A59D73C387F45ACE72227C0DB84F615
-:1024C000A64FC439E5EFDC8C23BD2CF17CAE7AF944
-:1024D000192DB82C1ED7EB66C4778EB536929F6A3D
-:1024E000931EC2A3D4B3F2A71E47B9C1345F3F1CE9
-:1024F000A775783CB343FDEF5B2D147F7AC554F686
-:102500006B7C97B8E3CF5686E71C9A1C591A1AB70A
-:102510004DA72E1C47A963CC04FE3E274BC0774431
-:102520000739D96F7E874812F7C92CE9CFF80E809A
-:10253000DC6E52D82EFE0E979E80EFE13599D88939
-:10254000CB617EFF0FA64C086300800000000000F6
-:102550001F8B080000000000000BED7D0B7854D5A8
-:10256000B5F03E33674E66269370327930E40167EA
-:1025700092C98B4CE290F054AA93106840D0E15578
-:1025800083243A58F446854C8AB445AF5F339000B3
-:1025900001F42FA2B548BD7640A568B50D4A6D6C13
-:1025A00023770242B197EA606D8BBDB57FF0F6F7F5
-:1025B0006AAD12C47AB1A5E5AEB5F63E9939930974
-:1025C000A2BD7FFFEFBFDF8D1FEEECB3F7D98FB554
-:1025D000D77BAD7DF28CA3F6FECB18639359C0CCAC
-:1025E0004A18D34A838A96CBD854D641F57B954076
-:1025F000DBEE1C289D565F18FAD58E33F919D4D915
-:10260000C78E48A9C458E0986C313B18EBF3041D01
-:10261000F8DE05FCB90A9EBB4C16C5CBD84685B57D
-:10262000F54299E1B3336665F47301FE05CE953149
-:1026300056C7D858CDC4D814C6BA5DFE985F8ABFB5
-:102640009F5C32551E1AD4DF2FC6FF17AA6FA58BC9
-:10265000BA9931AF23D22061C52F6BEA54C6E8770F
-:102660008DB12A95052D30451A0B30DC0F9BEEB34A
-:1026700006AAB1B1517DAB02FBF9A50BE9179997F9
-:10268000C90CFBE9F3FC6102A3F51EB267D6B031B9
-:102690008C851BB4FB1A2743F953B3AF8B7AA993EC
-:1026A00071FCCC6C1635C1F3A10C73648F9BB1C364
-:1026B00061EDA95EA81F96AB088EF774C266000490
-:1026C0005B3BA1A2C4E7DB3A798DAA013CD332CCB3
-:1026D0005F3A8C702E32A9A5B08FCDF3ED4D1180ED
-:1026E000E3BD0DF6362C73CA2C8C01BC97165B68C3
-:1026F0003D7BCBEABF5D0CF5564760B6A47138B0A0
-:10270000BC381CE001E3FB0D32DC6F8BCA06A5442C
-:10271000B830804B06DF00BE770DDF32BB4666E186
-:10272000314EC65E9EF1F663BD304EC64E587736CA
-:10273000BCDF71460EC23AD8F90B57D901DE01BD94
-:10274000FF4C89BD9978CEF0EFCD0AB13F37C15328
-:102750007D4B6F375F3ADC2D4BD6573058EFA64E86
-:1027600017C1AB47F2F9C7C27872C7A93BF0F94667
-:10277000193A02BCC25E25F238CE23072A703FFA0E
-:10278000782BCB1A6ED0004E19D3FE907E0BF4FB43
-:1027900028CFA42170366A377DDF8EE777329DE13E
-:1027A0007B99D9B1B647A17DE8F572B60786F9E8FD
-:1027B000D6E00415CE630B9CD39B1E5C4D64AC69C4
-:1027C0003A9683634D2E02AE8B9741177FCE447BA2
-:1027D00084EA6FB98BE99C00FEA2FF20F5DFA26CB2
-:1027E000B7DA711EB755DD9380F7579959472FCC4B
-:1027F000F775A40B7CEF7C97B63003EB12D5EFEFA7
-:10280000DC19F89D07D713A1327B7E840501DFEC2C
-:1028100015612D0CFDAC1B5810DF4F86E7DB6E9960
-:10282000DEB71E7A8869D02FDBE39382D02F673E14
-:102830008CA7C399D1B987C7D442BF3D80309311CB
-:102840003EF64838055D5E93DB704CCE1CFDFC9275
-:10285000F180093CD0CFD3FA577310F902632E13DD
-:10286000E2DB5A2BC7D3C6622BA379D729BBD3602F
-:10287000DE27B42C5AF787390D639877F4F91E8157
-:10288000F309033D4580AEB0DCD3A9B230E0C963A3
-:10289000802F58DFDBA951B9AFB382CA273B7DD463
-:1028A000FE54E774AA7FAFD34FF5DECE26AA3FD3FE
-:1028B00019A0FA81CE66AA3FD719A4B2AFB38DCAC8
-:1028C0001F7576507B7FE73AAA5F9506E786FBA9DE
-:1028D00008BB16C179F4DCA9F83580CFA038C7C38E
-:1028E000FEE26C1F9CB7ADC2043407E5F11D0CF786
-:1028F000637399FC1138874DAE1DEC8B505AA66658
-:10290000F448C057363EEDE8918031DBE4FB19F224
-:102910008347A4701BF331F693483020CF60CCE39B
-:10292000FA528313EA3F8BDCB2DD0A785BA62D6C8A
-:102930005E9F50D7326A6FDBAFC6EB13BCBB653B03
-:10294000B4BFAADDBA3D47E2EB60F98CFD26727B8D
-:10295000603DE051B4988511EE436E2582F8B812BF
-:10296000CF4BC6F5ABB4FEAB5997CB04EB9FA02978
-:10297000B54837D03FCA722EBDFFA0A6D1F3E4F709
-:102980002ED6CF34F992FA31F345C6C376E922E365
-:1029900058A5C5D618AC7D9B45F08F5C07F18F1EFE
-:1029A0000BBB310070EFB1F1F2CA6289F8ACB3B879
-:1029B00061B71BE6DDEDE672ABC716561B70FE6A0B
-:1029C000930FF9055BE7FE7931CCF7959FCA6CABA5
-:1029D00016C7CFFF1078503A2183CBCF7FB4464A39
-:1029E000619ECF4F78BADB09F5D2477D3E33F4DFE5
-:1029F000C67C76C493F03D26F638D4BF3BB9C4B943
-:102A000010BA574DF98113F9ED5237E70311C69A01
-:102A100010DFD66FBC65C220941F9DE07C4A71F325
-:102A200079765B621D749E531C6C0F0981EDE9C8B9
-:102A300077D6BBE090A631661AC74BC5A25E8FFD64
-:102A40001410D461588FF29769D6008CD7752EADCB
-:102A500009F90863B174E4638A2DA866C1F3ED61D6
-:102A600013F1852ECD119160DC6D8EDA631AF24F71
-:102A7000D5E42B45387A4D04C76EC7172266E4CFDC
-:102A8000D2FA36942F11F519AB1B9E47BC2615E9D7
-:102A90003CE25FD484F57050F6956A8241607BD049
-:102AA00019D98AE3B2A17FB90CDB5B980FE1B03191
-:102AB000EF4F87D2A1DEB554F599796F4D06B93342
-:102AC0000E7F8329BB2C831BD2711DCB787FF8CD61
-:102AD000B710E5701A3FBFAF0FCC558B49EECB61F5
-:102AE000A14748178010658BCFEA83F61A476D938C
-:102AF0001F4A39A3D6AAC13EBBD55AEB0ADA3F73A7
-:102B0000803284228FF853976A22398CED5F447AA1
-:102B1000EF662F7AF28894A8BDDBB16300E121DF74
-:102B2000CC985BC3F5C17C3ADF0378584B661ED363
-:102B3000601F3DB738691FB2E4A33ABB59A675E7D9
-:102B40006BF628AB013EAF2C38C6807FE45B6F9FED
-:102B50008FF5716DF2EF0613F8F4D8A0B19EDB6C1F
-:102B6000AC6733A85BE3F32E7273FC4D865B323C9B
-:102B7000C6A9DD2770FDE382323D4C5EFF43EA03C8
-:102B800059F50CD7E9A075E6396EAA070801CA0500
-:102B9000D623FEFDADEBAC511759DD307F4D8E894C
-:102BA000D496CBD8D0061C779BC0F71E373FCF38C2
-:102BB0005D9975BADC8A7439619D898513E48E3B11
-:102BC0006C67E184F94A7A9C867AE9F67C43FFF2E5
-:102BD0009DC586F6CAC844437BD5BE5A43BDBAF7E5
-:102BE0007243FFCBFA1A0CF549D17986FE75C716E8
-:102BF00019EA5362D71BFA4F3B7993A17DC6E06D6A
-:102C000086F62BDE5E63A87F6EE82E437F5DDF4E87
-:102C1000968FDD822F7C5A3D3BCD05989D305FB26B
-:102C20001E9FAC875BFFDAA56D407CCE54089F6584
-:102C300094E7505F73A7124943FCBFD2A7217FB925
-:102C40004BE0A3B7DC7F1F9E5B7DA695E482ECE0A2
-:102C5000FD64C71CD253C6EF04BE54875A231B6EB3
-:102C60004F47FEDC190E783CF175DBD4ED0CE9B76B
-:102C70003EB3890D3AE2EFCBAA9F0533703E8DE655
-:102C8000B3AA61EA67D3E0FD847D1D34999803F906
-:102C9000F88042FA7A6F46818CF4D7FB97898D547D
-:102CA000665C3107F17D92CA1EFD3EF4EF95D83186
-:102CB000067A52AF899D059D8D3D936447E9F6D311
-:102CC0007813B363B95B1ABC83A19DD271A2612C46
-:102CD000233BEB59DCF7BDA043E0BEEEADE17AD675
-:102CE000C6BC791AEA653DEEDE63C5B89E5C902BE2
-:102CF000480872C0877A85BEDF37C479CAC53D836C
-:102D000028FFD6645935D49764EBF6C0EF005E8F88
-:102D100058069FE8827AB7A4AE42BB237CA7C3F7CC
-:102D20003843FD91C34DCB30D56D80717BD7FBE52A
-:102D30002C68EFDDC27CDD481F39F51BB2E07969F4
-:102D4000E10A9313E9C1B37E0396AFA01E0BF0AB6B
-:102D5000F4EE3665437BD5E4FA6686B25785F9B260
-:102D600047C72773E64E86FB611EF92DC42BD4BAE4
-:102D70002FC0D2EB9D70DE30AF0DCF5BA292E06032
-:102D80003BE788D8B0EEE170B1F9A5483AD4733C7E
-:102D90007EC9EFC5F776D2F9DAA2463D16ECCF37F9
-:102DA000DC53509F359EAB6C7D80D6B7CDC4E9A275
-:102DB000274B3B8EF2B9C7ED717669F175EA7CE578
-:102DC0006D618FEACF75BE723DDA1453E2FA0DE001
-:102DD000F94E5309EA67DB19F227DBDDDB19E2B5AF
-:102DE0004D0D6B0CF5F0AF8509CF75FDF60E413337
-:102DF0008DC5CD5694D767736A499FB5ADDB4BE758
-:102E0000950C37DBA089F92F02D7CCB25D24DF8186
-:102E1000016B68871FCA73B4ED4EA1F76FD0389D60
-:102E20006D01328E79098FACC8AF2DC2CE004C3007
-:102E3000A17C3BAB326E27F6BAA97E4716AFEBE317
-:102E4000DC915B3BF662FAB70DECC260C23EB6C0E5
-:102E50003C08978DE71736215C994CC4C1B6FDC577
-:102E6000BB7B2BC252D8351B04BCBFAE71F88E574A
-:102E700018D905BE9CF94D24FF5C4FD2F905CE153B
-:102E800093109E56EC24F883116DEEA0F55B74F957
-:102E900064BA7019AD595360FD05F8A4184B2EDFC4
-:102EA000A0CBC00509F97F823CE305C9F702FE3BD0
-:102EB000C803637BF94E63BD3292F47E98BD86F2FF
-:102EC0007F25E3F0AADA676CFF16CA71E01B2B8539
-:102ED0001C67DB2D24EFACB0A20B5CFEC6E521F035
-:102EE000876B7A63F5E9304ED1748B414E1624F628
-:102EF00003F8D5DE6A0AA0DDA0FB5F74B807DA4CE0
-:102F00001685E84123380D3F17FE9664FE3D3E8D41
-:102F10009FCB212523B2C1CDFD12C1326E6707813F
-:102F200024EF957DBF6A417BEC98D907983D7C9E44
-:102F3000C9E7BF6F583F0ECC2F267B77B00EED6FE1
-:102F40009C2F98309FEE37292C0F2E2A86FE1F3497
-:102F5000E54CC6734A2B6416A463DD2FA2DBF9BBD4
-:102F6000115760BC6DBE573B0EC33A369F4C239F32
-:102F7000C66CF3F1639D505F532413DF53A7ADFA82
-:102F800036DAD30DFF0AEDF0CE664D1B4BFAFC315D
-:102F90000BD9F50D02DF1B849DA6FB4F6E2BE6FAC5
-:102FA000F42DA28437ECDC4E8FDA51EFADDA073C1A
-:102FB000DB882FE9BCDD4F7A71756F72BB9F21BD35
-:102FC0004F14F80075473DD427897A2F93B25538AE
-:102FD000E7CB9A070FA1C9E17DE9881DF5B0FD3661
-:102FE0008E1F4F0ABD2F8F49BE28AC3F6F9FC3175E
-:102FF000817E1966B63F06FBF0BD28BF399800CF29
-:103000009A7E63DDCB12EA6E5C87B17E8FD621217A
-:103010005CEE690154842D6F28CEC879AB8A21CC2F
-:10302000CB10FF669B1D93D0EE5A53EF6008D7B4C8
-:1030300053E5DF8C219F396166283FD474EDBE468D
-:10304000785FFD976CDF7A2D7EFE4F76228B67ECE2
-:10305000C10B3ED6ED89FBA99E82F34479F33DB0C6
-:10306000C7B1BD17CE15EBCF803D8EE501B0C7F1DE
-:10307000F973608F63BD0FEC712C7F04F6383EEF5F
-:10308000077B1CEB7BCBEA1F4CF66F25FAF9E2FEBF
-:10309000AD4149F76FA5015C1BD04E9C92E0E70A59
-:1030A000723FD7278FE3D7C721FFE1887186FD885C
-:1030B0005615FD27C5F0C61878FEDE9DBFDE8B7263
-:1030C000658114DC87F8BD7ACA9B0AD7B38714ECF4
-:1030D000FFB00DF01FF854E128FEC32B679DBA2303
-:1030E00017ECF41F15B72E443BFFCADB4FD58D8775
-:1030F0003A2B39C6EBDF39F56C01F0EA5B4AB6F0E2
-:10310000FAFDA7CE1642FB18F6ECC2C619E47724E6
-:1031100039F6B0C49A13F5C09F08FA0CADDB41FC38
-:1031200014E400433874E505488E9ECE19CA5C014C
-:10313000FD43B94379375D84CF87D63D48F2AA2B4A
-:10314000F3F7A4A7740DCB151FC9157D5E5DAE7C8A
-:1031500020704F972B6B6CBC3ADC2F5842CFEF1787
-:10316000FE1F1629A57AB68DD7FF5783F60ADA47D0
-:10317000001FB2870F674EFCFA4CB43F9B645F1A86
-:10318000D4EF77D4DA502E9D15F40BE386D1DE0F01
-:10319000CFB6461EC743CDD1881E9DFAF8391E54BE
-:1031A000CE9853ACE3C5CBED51F40774355AF7A074
-:1031B000DEB9C3514CE3754D57C2E887D1EB1B2EE6
-:1031C000BFDC8A7A4756A6D38D759D3FE9FE5BF832
-:1031D00031E3B80D62BB0D5647D49C89E861F943D1
-:1031E000A23EED6031C21F9F090C17A0B7AF9570CA
-:1031F000BCAA63BE667CAE481D6144C68771EDB84B
-:103200008F0CE1CF44093535611FFE02BE2F7D1FB3
-:10321000194A58EC83F4A91D0E5314F5C21DB02FA2
-:103220001CEFDF8B35824FF2BE18BA6861DC59D3D0
-:10323000C5BAD59907701DB34DFE6E7CEFC8C72D7A
-:1032400039887E7358878CCF4BC0F245FF2DA07410
-:10325000F7858BE827C9FEDB2BFF4DA2FDB0DB1500
-:103260003A17A58CEF7B97127133328423E31665EE
-:103270008C8EBF2525FC7CE3F8EB67484F5D4E3F05
-:10328000C75F7528733DE26FD650DE06DA5734E526
-:103290007924E371F2F9D4206D73396046F87ED257
-:1032A00079EAE7A8E341B2FCFA5A89AA9FAF8BF604
-:1032B000E9AFE074A0EB5B0CECA18C91F0DB04E3D4
-:1032C0006965F1BAE20A901E6DC9F155A09FB7EB8E
-:1032D000AFE6B6547EDE1B049CD667DA49BFEECA61
-:1032E000E4FAF540E63C835DD408769204F861CEBA
-:1032F00066BD4847E631D7939FCC3C1635285C57CE
-:1033000092DE3A663ED75B55D05B53CCAB9732EA40
-:10331000AD29F4D961BDD5398FEBAD990AE9AD0F6F
-:103320006728CDBB53F09BA9255C2F1CC07DA4B0A2
-:103330000BC11E247FA56E0F2A6A90EC3A7D9F5325
-:10334000055DE9FDD3D40E86FE33B3E2D3502F35AD
-:10335000DBB99E9906DBAC4890DFFAFC934A785CB7
-:1033600025AB9CEBFB262BD74FAE7C45EA4805F7F7
-:103370005089EE5F498D777F03DE105FA875287E48
-:10338000D40F6A1DAE06D40F467B0F4CD2F0DBCEB5
-:10339000385FF1FD75AA99E48FEC73219EF55A060A
-:1033A0009F7D05EDBD230E9237BD1985349EAE5F1E
-:1033B000835D1BAE8041F6FF1928D134D29E053BB8
-:1033C0006B4B09C6BFD6E44DE6E3829E573D52AF34
-:1033D0004CF61B0CD37BE65E377F2F320EDF93D685
-:1033E0004C1F8B78954CEF7A59E4FA69D14A5857BB
-:1033F000D1B86354EACFFF8999C90F97DC3F327C7B
-:103400000E5C2E57C26463CC248F23B8EEF7D6BE71
-:103410009AE783A5B4CB67482E7FD0317DCC668DEB
-:10342000F3DB7D2867BE2413BF2DBC7520CB9970BC
-:10343000CEBB3AFB8A640FC61762458D1EF2F7F9C0
-:1034400053ADF7B83E7F7402F1678BC0032D27366A
-:10345000B71CE0AE394C3E542540F81AF840BD9CEC
-:10346000D5A8C2FC459DCCE780BA9BA9E4F72ABA4F
-:1034700060267C2B3ABC8CF07842CE9014F626CC99
-:1034800083AC38217EF2614723D167D1D8617B8F2D
-:10349000E20C1FE64417227D7FF8005F51D1A3C6DE
-:1034A0007690B1E497BE65AD3D8226E384BB5513AB
-:1034B000D68BBE2DB14237AEE3B07B33FA757E9822
-:1034C0004E7E1DF34E0FF965BE2D050F105C23DAFD
-:1034D000574C2562B3D06FF557ED7BB6921C8BCD60
-:1034E0002539F665137B3C85DFE9E725DC8FF19A0A
-:1034F000C0F722D7CB452BEBB03C4EE77DA9F4C4F7
-:1035000004DFDE3C663BC5C5C20DAC02EDC31E0B3D
-:10351000E0550A7AF57B387F19E6C7027E36B45645
-:10352000602CB324F4BC7D4F3EF9641ECA6D46F690
-:103530006472BC36BDA2971AD37D7E86FE0949F51A
-:10354000733EAB865D618C03FDC59C12AFC77804EA
-:103550009F766F7261FF468FCF857430E09EEABA26
-:1035600009E0E770282C2D810FEB78F262C654D267
-:1035700043F471D664145FD42E57801F6B1791D318
-:103580000AFAC7519F3934C3AAC17A37396A63A886
-:103590006F6D72E4D4929FDD017C23C1EFE4701C57
-:1035A000253C74F8B83FCE81FC17FD4E62FF03EE58
-:1035B000A3B47FBDDFBB820F397C511EA7046B060D
-:1035C000FBD9E44018ED0C5B0E23BBD266E5F49406
-:1035D0000EC7614DE023FABCBF2BE1F6DAA6C2DAD2
-:1035E000583DAD4F46CF01DBE4AA75913C4438A36A
-:1035F0003E3A6E581F25FF4AB180B33E4ED700DFDA
-:1036000067609DCBDF988D7668C0E5C1711D375925
-:10361000C3281732265F743CAF4732F887E2E3AD28
-:103620009B25C62BC6F1CC19B52A8E67413E910267
-:10363000FF6688757D56FF19405425BB8D71FD0AC4
-:1036400030DE954A8FD04BABF0838D7C8FF349B73A
-:10365000B05F804FCEF6A0DD52F8E6D17AEAC5ED34
-:1036600016E75CB94286F3FA004ED02CC5EDF8643B
-:103670007DA6DE3C44724D9747BA7CDA85FA8C12FF
-:10368000A7A77CCEB958415B80E4B6941320BC0157
-:10369000FD4643BA31637C3805DCB608F84B99D354
-:1036A00035A497C6F38305F8DEC18CB70B5882BFEB
-:1036B0004DE7872F7EBCD786ED1FB6355C546FD1A2
-:1036C000E3C7A3C58D33EFFAFD9712F596D1E2C893
-:1036D0009F143F3E94A9909FEE11C9C897BA043F2A
-:1036E000FA9AC00B6771F02B88478F48011FE98D4C
-:1036F000C29FE22D0FDE89E733BE47616138CF8379
-:103700001F4F75217E5C2A7C753F7BBED0A7F21DC2
-:103710007B25A4D3FCB688847EF282B65EC97F91F5
-:103720007E8B3C9C9EF5FE1631FE55F29019E5D538
-:1037300055828E0BCEC9AC22410F5CE0E1FA944574
-:10374000E8EF99879EB0E178874C819E32940F997B
-:1037500026EDF1047AB7DC5A6B6D48840FC67F52B0
-:103760009CDF773DC37A17D947BABCB5E8722247C8
-:1037700036C889503AC75B5DDF095DCEED21490A45
-:103780003E86F03E7DF9EFAF4196755AEA55304ED0
-:10379000FE49F18F61BDC61459A1DB31482F3E5956
-:1037A000FDF120BC3FE93BF5440F535890CA698CAA
-:1037B000EB7DA0473DE321FD0E969C70BE0C5D0F96
-:1037C000799FBC8F473C5CDEDD2BC7C8CF7AEF7991
-:1037D00089F878327CFEE8D1FD5AC371BE8BFA4974
-:1037E00035F493BA316E65F463D61D33D6A7C48C15
-:1037F000F5692793FDA2FE5F24FA451F06BA427EB3
-:10380000A0FB410BC3917A15D65BC47A296E58D0C0
-:10381000E634C0F54AB3C8A7607E29D13F5B202FAC
-:103820007807DFFFFDF0B98749CFBA45B4FF43E31E
-:10383000CAAF74A3ED3CEC67D5085EFF3077D16C5E
-:103840003CD7647F6B514742FC918DF4B3DEF2B0FC
-:10385000C5D01EF04F223B60F112A37F96D691CBCC
-:10386000F75B503B72FE4F9E17FE3947CEAF8FBBC2
-:103870000BF80DF251761ECE752AC28DA1C78115A7
-:10388000C95109E3D7F91DCC8FFA70C15AE64F151B
-:1038900007282CE578900C6716BE8AE0374B3CCBA6
-:1038A0007798C94ECF5F6B223D301FF801F2816BD4
-:1038B0005601B940BD6095467AE4B56D26867280A2
-:1038C0009DEF34BC0FCB257FA77EEEBB703CD4238D
-:1038D00057B38809F7D33191E889D6556CF08BBF7F
-:1038E000C9E16525785D3BDD62F06B16A11F3301F0
-:1038F0002E3A1E14243D7FC1A31AE802E45961291F
-:10390000E13F9773A528E76049EFCD38B917F3D9A0
-:10391000AEDCC068BF4359F608CF93188E27982FA6
-:1039200094037FB2CEAA40BFCA36D56EC27C8683CE
-:103930005983DF62598CD594B270E34CC6FED93EF0
-:10394000542541FDF2D24777F4C0A11CB40D7D1778
-:103950009DBD0EC7938B9A3E17AF67661EA43A9B18
-:10396000CE3419E063C719609F7675DE3E33CC6FA5
-:10397000F73AC8096967C3744AFBE9BE5CBB07F341
-:1039800041BA4B4DA427B1C476D8C7774A553DBF3D
-:103990008CF2DD58138FEF278E2FE75C64FC7930B3
-:1039A000FEE44F31BE95AF3F0F1F817CC9C3F5A325
-:1039B0009F1AC7C7F3456751E2FC623C998577635C
-:1039C000FC05E673487C3E15F34DF29831BF6078F4
-:1039D0003E15E6ABFE3BECA779E479582E761ED770
-:1039E0007FBAF3E836F969BDE11A07D93F0C9A4D61
-:1039F00053D1CEE0F3D964F6A25CCBE1DA3D350ECB
-:103A000057D0F7685CE8BEFE8280B305E1AC2A04BB
-:103A1000E7D1E07648E5F94E5B547B64BDFBFFC11E
-:103A200079B9F87925CE877AE325CF773DCC97739E
-:103A3000E9F3217C917E86E10B67B221EFD2E10BA5
-:103A4000AB0A5F0A7C0FC1B8A604B8C6F38A1E523F
-:103A500051FFB75902561FF0DF03A53C5FD19BB35E
-:103A6000C84A7906B98BAC98BFB7D1EB68C278DD8C
-:103A700046CF12AB25414E6FF4B6503BF4A77C28DD
-:103A80006FD48EEE0956CD6264FF6F99D9E85A81E2
-:103A9000F8D3C1F3ABF47C235D1E3211BFA47DC10A
-:103AA0008B633E7760E810F4DFD23199F2C9C664C7
-:103AB000FD89F2A8B6B5F97CD8FE2D8C33813EF194
-:103AC000A0883321A2921FADE6F247312E5B5BBA8C
-:103AD00046C2748EC25546F9949F94A7537B26D64E
-:103AE00080F9586C05CFB772B5C849F2D048B7DB3A
-:103AF00010AE3C2F2A2271F81AC6FB3D32E95CD485
-:103B0000EFF730B4EF9E85B1CC46FA32617E523287
-:103B10003DCA8A5FAD47BD7C8D89D65180217F101B
-:103B200071B5D5F35D2BE079E1CDB24F82E763BD8E
-:103B300077539E1268F5A46F78BDC71BB03E629F95
-:103B40002B8DFB48DE57F2BA4170911EA29F57EDB4
-:103B5000195F3ADA51B5A58B288F8C7E747A372796
-:103B6000ED271BED5F93DF0672CCEE49D81733F4D7
-:103B70001376DA7F6DFD242213D25172FCEB6B01B8
-:103B80005A671AF359157AAF85EC453DAE968FB456
-:103B900083E73E9EF1B844F2FB53F9FBCCC5E36CDE
-:103BA0006976303D81FEA4DBECE4BF4C4B833A9C4C
-:103BB0008FA430EB3878BE4BF8FDD64B4CC67A7CE0
-:103BC000BE28E5A9774981ED3E3796DC5EB26405F3
-:103BD000280F11C3B48976E721CCEF80F635B7BA48
-:103BE000C7A2DF6E0C10440CED661197D2FD24992C
-:103BF0002583CB517E1797952CB6A27C46C7D2E57C
-:103C00008C5DB6B7E8FEF0CC385DA69DCB675A82D6
-:103C1000FD922677509E47DAB9F1067F4A54D85D67
-:103C20007ADD9F2337E27C73D02EC0BC26A676E3D4
-:103C30007BF500142DD13F7ACE6518273E7EA16119
-:103C4000DE28D8CF897180D1C74F675A45E2F8C5C1
-:103C5000A38C5F9634BE9A72FCF8B8D9867137CAC5
-:103C60009C5F8473EC9154FEBC95650D5797E58E6F
-:103C70009E87F6C532E177B302CBC7B893C09BCD20
-:103C8000AE0ECA4B33DB797CD422E2258733DA8847
-:103C90005FB142635E5A0353656CDF9839E798045D
-:103CA000ED0D0EA39E7ED5F937CDC877AE928D7AF5
-:103CB000BA9F75107E5EC98CCF2D85463E40BA36C0
-:103CC000FAFD3326C7287F2DD7417906A3F90F7E49
-:103CD000D3C928AFCA921EE840197777D9B4EC8DC2
-:103CE000D3A13E86E3D7D6B2F98BD11FF41B81C78F
-:103CF0001B81EE118E2D6BC6EE36278CDBA2444B5A
-:103D0000518EB498781E3FFDC0FCBFC9CD277F6A95
-:103D1000F2BC94099CE08F6AED90029E847DFC4683
-:103D2000D0C5F07C7714EC463D7678BEB4E8149AA2
-:103D30006F381F48CC97F7D9E67B43D0B33E5FEB93
-:103D4000578CFB6B5562B4BF561313F9FF7CBE371B
-:103D5000707FEECF309FC8EB1A9EEFABC6FDB5A6C5
-:103D6000C5687FADC3F6A4982FEFB3CD97A6745066
-:103D70003CE63E899FEBA1BD4BEE477FFCD9F96B3A
-:103D800034C437DD3EA3FB3366BA3F4372EFDA42F9
-:103D900085F4067DDC7D9DD3995FE17E1B2C2B662F
-:103DA0004A740FA072BAE4C778D8C340F7FE32F461
-:103DB0004BA9D41EE97451B9A753A3F231B007FD42
-:103DC000E49FF251FD6C19B787EF1BA72E5B89FAB0
-:103DD00042BD9DE741CFBC0234D1B8BD0506D82114
-:103DE0001BE61B7E814DDA8A68BE93C323A7312F61
-:103DF00082E7649FF462AC13EA6933CC1AE677A7D2
-:103E0000B9592095DFE57D913FB359CF9BFF9CC405
-:103E1000E3EDA08FD4C3FE6F14A066E6F912EA5555
-:103E2000D77E358BF491962583192AACE30669D2A7
-:103E30002F3C008FFF2DF4911BC7733A4EB62773AA
-:103E400050B24CC6BC3E732402BF2ECE584CF6E88E
-:103E5000E2A58C39E1FD6BF13D902BAF087DE6E5E5
-:103E6000C13486F65AB891C7996FB8DB6847DE67E8
-:103E70008BAAA8C7DD372987E179B4AC35B66F16B0
-:103E8000F182C54976E5B5497934A065F27C10DC4C
-:103E9000F30CC6DE2DCBC8A13C589147F384F00B40
-:103EA000B1C21C4AB676CEF58CC1F8639A92FA7EFE
-:103EB0008E3E5E8EE03B2CC74F70D0F3CA99F9A9B5
-:103EC00049F4BE984F7F6F97F4D4B88BF935416FA2
-:103ED0007B6BB082CB67D4AF59B931DFE7ECFCE242
-:103EE000AF37B254783B24A35F415FFFFF2D7CFDC9
-:103EF00011EE17CA57667D3899DF432B6489F7CFD7
-:103F0000F47CAAC5C37599A15EB954AFBA86BC78D2
-:103F1000DEAF7D2EDDB795F04FE80FD1D74D17D22C
-:103F20003FFD78C3EB70F98BB83F4EDC1314E38D83
-:103F300006E7E47C07DD6F433F53E3FED8AEDD3C8C
-:103F40002F323FA7E11DBC3F85CFDF34E095F19EC6
-:103F500054D7C01312DA17DFC27B5F727C3EF4D3F2
-:103F600086497F35DEDF1A218F19BF97A3AFA74B94
-:103F70006115648F9A803FC07C0B1C83B2A4A1DFC3
-:103F80007D88EEF3DD59CECF057387F97D18AEE756
-:103F9000990B4C3C7F6382C6F53ECFD0F8C4B8D0B5
-:103FA0000DE55CAE2F487F75AD06F26F49F9938B36
-:103FB000313F69C19857D7BAA17E5DF97717CB8099
-:103FC000470B0A5EFDD00D3ADBB2F2A778BDEAD509
-:103FD0000F8BA1BEBCFC695EBF8211505ACBBFB72C
-:103FE00018F9EA0DE5AAF0F3C50A71BE0512A78F0C
-:103FF000CF5A9AD34C29E3F7FF50AEFB139905E74C
-:1040000009F4FFE424F2A380EE7FF527C51BB12954
-:104010000FEF13899F9C4CD267E6E1EF00CFABE531
-:10402000E800BE6FB24609AEE59837534128F0C0AC
-:10403000858BE44724E39104E8BA0EF5654D652DC0
-:10404000A01F77AD63415B49029E33BFC0739EC71B
-:10405000A3AF479F7FC4BAE0486567E2BA1EA67166
-:10406000F4759D9E9416C67B677AFC545FD7696988
-:10407000E811744644AB0697E2B99ECE181A2F4158
-:104080005DAB5097503D77E811C99750B7F073BCBE
-:10409000B7FC27A4F7AC95FCF79623BF541C74BF5C
-:1040A000AD47E879DB728361C6F57BCA770C17F1FF
-:1040B0007B038D93257F627CFF9B02BFF22A7839B8
-:1040C0003B6D7BC709C0C7D00189AD87FEA1F367EF
-:1040D00015B4C717F49F52D0EE6E3F704A41BBBA79
-:1040E0001DEB304EFBC30AF1AB64781754980D7189
-:1040F00074DD9E385254B63107D6D3BE52F2618A6F
-:10410000EC9AE7B366637DCD0ADC2563D7CFDC3F4D
-:104110001BC9BB3530B011CB1BD9E0118C172C0B50
-:104120001AF5FCE56D46BDBCB5C3A84FDFB81D4E02
-:1041300007E4D78DEB0A0CEF31D490613DCBC47905
-:104140002E73DD1333D7603DE1BE8E44644DFE9D7A
-:10415000E57C07501AFD160BFA25A2E3F6662BF94B
-:104160005F8F14F13CFBD02A33E50585101DB0DECE
-:1041700021097F969FF8A32EBF67F79D395A80EFDC
-:10418000AFB2101C58D81F43FF43B3C0A71B9B9B63
-:10419000DE413C6BD66EE3727CC25E0BF957825CEB
-:1041A0001FD784FFBBA5EFBE4627EA9F6B25F26FA2
-:1041B0002C6F33EAEBADF80BEA6FEBA448D48D70AB
-:1041C00032B6DFB8CE587FBD5CC8DB2A568574F2A4
-:1041D000DB7249A67BC5A2FE87A25FBE1C8589EE65
-:1041E0009202A710EF5629D11A946B774941AAEB96
-:1041F000EDF0BC9DCB1D2EEF4D4051C4772DDCAFB3
-:10420000105E2D113E2E1F21FF13F403F3C87A4ECA
-:1042100005F7B777D9026BC95E7A4152511F69948D
-:10422000FDB2D31BB76793F13157E0F7CB6CD08B5E
-:10423000EB2A43A003FCCB168F89A03FACEC9F5721
-:10424000507E63599DE433113D9BD8BA5A2C65E2E8
-:104250000FA86FDAA02C33F73613BFBE4C5179FE8E
-:10426000A08B25F201FF134C4278E1D271DEAB0B3B
-:104270008F7D8CE778CDCE7BCE20BFF394F86BEFAB
-:1042800083F56DB3F1F9B73D2F91FEDAEE3D4A7C2F
-:10429000712CA009CEDBEE12FCB10FF8A3BEFF62B9
-:1042A000BCD70FFC0A2F8ECCF7D2BCE3F4F8809E6B
-:1042B0005F1B6D305D00BE3356CC5B50A311BCF26A
-:1042C0006EEB9570DF452CBC1EFD44328E991B2F82
-:1042D000753FFED278BCFA9B789EAB5D830AE9DF1E
-:1042E000225E9DA2DFEE94FDFCCCE047986D3E9FE0
-:1042F0008971E5352F945C34AFC26C3519E8D5A2CD
-:10430000DA0D747D758591CE17F88CF47DEDF4127D
-:1043100043FB427F95A17D71539DA1BE347085A161
-:10432000FF75CDB38CF6BE6B9EA1BF4D5B64A8A795
-:10433000575C6FE89FE1BBC9C86F727A297F40B1B3
-:104340008607831ADEAF676CBA33CEAFAB32AD9857
-:1043500064CCEC753607963D93D2A2786E3DF93C5D
-:104360009E9AF6D2975D5184FA98A7ACF5507E5785
-:104370008A3460BCC82AECBC897733033FFFA72A84
-:104380008EE77AB9A42278632594DE7D5A01CF970F
-:104390008E4DC4F3B1A20311F1F8392BE91D972515
-:1043A000E9BF4535F5CB2AF0BDBBFD73C92FD5C795
-:1043B00054BC57BB47E1F94CE1E778FEACB76FD08E
-:1043C000E44FA0B7FF53C1E5FD37020D949FD4DE43
-:1043D0000FD20CF17BE79B0AFAEDDAFB0732516E44
-:1043E000D404DE5450BF8E3F17F2441EB263FCF279
-:1043F000FBBDA9F3D0BE51A1D0F84705BF6DFD327A
-:10440000E7B78070F3D13ED2F967EB7EBEBFD6A589
-:104410000AD1B7CE47817F1AE261C97C79F9CCC84D
-:1044200046A45DE0A306FBE5C62573DE417B0824B8
-:1044300035E931C0478DED859B88BE6F4CB26FBAB0
-:104440002A86F9A9F702D0CBC98029E5BEF654C95E
-:10445000B4AF93C15904EF6F00DCD06EFCC60838CE
-:1044600071F87D127C9E16FE44FD9C92FB7DA78A0E
-:104470009FD3D3A3F0CB77059FDD23C56A919985A0
-:104480000276C2D3E556EB52CC33385AF4D1268C9F
-:1044900027B4FE40425B96FDEBC04B799877A0ECC9
-:1044A0003F9287F910A1DE23790CE0B4CAA2AD4790
-:1044B000BD18F0C0B71ECEA5BD2F4AEB5FDD5B3740
-:1044C00080CF57F7493E6485A10367E6D03ED9E027
-:1044D00026D4E3F78CB2AEFD153CAFADBF42E37915
-:1044E000F7419813E5EC8134B2635BF7031FC275A3
-:1044F0003D2FD13D8C3D5BACCDA9F493A7AAF877B5
-:104500001B5EDCA2308CA3AC82F7711F478B8E2A16
-:1045100056C49BFD12D984A1DE134BD11F1F5A6BC9
-:104520006118B7D5D7F75E51ECB7B8FFD7575A180F
-:10453000DE2FEC5AC9E3B1AFAF35D338E69B2D542B
-:104540005F762BCF133EBCF2DF3615C0B8AFAF920B
-:1045500028BF7ED6CD7F3C8AF565B7723D28197F8E
-:1045600087F135093F97058D7837024FDB3E1B9E5B
-:104570009EAC10F66B15AB41390BE73E7B2CE2CFBE
-:104580009D8CEE37369F3F6C190BEB2DDEA4FA3075
-:10459000B45B6D8E6CCC43BE7098B74F5AB55BE27E
-:1045A000FC45A37BEF053D0A43BBF15D715EEFE285
-:1045B00079E5E2D68624CC6B6372AC18D7E716791E
-:1045C0005CCF5858F37EF423C99CBF54FFD0B53B51
-:1045D000D18FB44BE0A3CEF7AAC0DEDF4F7EE8DE7A
-:1045E0007CBC8FFEB485FBC7C68BF14A4B86E62C9C
-:1045F0008432BD92CFFF47B10EBDFE9CC07FF687CF
-:104600004709BE0BAC1CEEF3D6455B701FB7C8C1A3
-:104610003F23FF9B3FFE97AB50AEF514FFD44BDF1B
-:1046200065611349AE85C4791C9EF1EF0FDF81F9F6
-:104630007695763AC785871E8AE1B9B67B64CA3318
-:10464000B4954E1E1BBC881F21744E33DCEF6BEFFC
-:104650003F33C79F82AEF757F1FD578B7B7CAC9FF2
-:10466000FB0F801FCBD36BE3FDF4FDEB7E0F5BE90B
-:1046700063744E777C894DE2F7FBEFA37196AF3AF6
-:1046800021E1BD94EB2C7E8B03E0FCCB316C29DA6D
-:10469000C13FED64744FED38DE570356F272A74AFE
-:1046A000F598B8B7F66AA746E5754A603CCA95A57D
-:1046B0002F769422BC0E173D18C0EF359C3E2EF489
-:1046C00059A6F2FB8E02F7CEF69B9915DACF1E9013
-:1046D00022E43411EBBFE15C3E0B023FF9B5B81F99
-:1046E000B77ADDCF89CFF9DACECC413B63D2AA537A
-:1046F0009BB01E5AF7C739A837FC16E404E257A846
-:104700004F622E18A7E59C93DE5FDD7742417BFE6A
-:1047100069D3D01C847FF8A044F7AA421D67887F24
-:104720003E2CFC2B37546671BED13FC944E7E99F4C
-:10473000C8ED1371FE0313FF9489FCCBBA4E7BE5E1
-:104740000A3CC763663AC7AD0D43996A8A73390953
-:10475000E3A24FFBD7221F2FB9BD5909935FB6596A
-:10476000E06D72FBF59526DD0EB7883C2526C17AF3
-:104770005A047EB532FE9DA0963E296A07BA6DEDB9
-:104780009F45FE8DD68E8B7F0766347CBBD4B29D51
-:1047900071FF865E47FB2B315F0BED2FE37DF5301C
-:1047A000E1555A91676CF022FA5D68309FE227ED7F
-:1047B0003D8CE225ABCF4DA4F2FDE737D3BD27AB4F
-:1047C0007DE841940BACCC447AFDEAB051BF992D01
-:1047D000E876B6D06FD654827D52C186ED13B043D1
-:1047E000BE5CC9ED90CC43CC609F243F27FBC42A1C
-:1047F000FC86305CF09914EB9E57D57057652ED22D
-:10480000D576C26F06F88D7895BCCF8D959C3E7598
-:104810007A5E76E81D05F5DD505F6A7A5E5A55BF0F
-:1048200011D7B36594FCBBAB05BDAFDEC9085EA173
-:104830009D4E82D37B6C67A001F0F23D5807DE5F8E
-:104840003F1D08A467C1FBA78381748CCFE9F4DF07
-:10485000BED34EEF6DF12CCAC6EF6DECAAE4F1F3B6
-:10486000F7FB665911CE37ECE474A7CFF7DBE8B25B
-:104870006CA49F29962105FD9385FDA73251AF9B1E
-:10488000F2FCE26CA4BFD1D6B975A258E7BAFCA578
-:1048900074EF077ECC40F7B70B3916DA105510FECF
-:1048A000B7AF6384BF03CFFD6B3BD2EFFBFDE92ABB
-:1048B000CAC9F75E480F23BF3F7D302D6282A156E3
-:1048C00089EF24BD6719BC86F4C7E7CD94AF103AD1
-:1048D000F8EE83488FA1E7D2E81ECDEDFD9BCFA077
-:1048E0009C5BD53FF71D19CBA7FEBEF4B07ADDF86F
-:1048F000A589F9C5EF76EECB47FEF9BECCF9C4ED3C
-:104900007DCF923E7BFBF9B335983FF8DE0B7F9E5F
-:104910008AFC2CF4CF67A7221F0BFDF8EC546C0F18
-:10492000FD30BD23957EF2E32AEE3FD1E5A3FB35B2
-:10493000D9E067B959E087BB7B7B137ECF60CA891A
-:10494000251407D0DBA794F27BCC537ED1987D73DE
-:10495000C27BDD3199F225269F684C5F998097D7FD
-:104960005759747FCDA5F947441E82EE1FD9129383
-:10497000F9BDBA36337DBF6E798CC7DF93FD268CC7
-:1049800005AEAEC6F3BE35D787DFF1C1FBEB181716
-:10499000397D676984EEAF87AD473C097AD0B2981C
-:1049A000299A867E90FEB428EA43CB62F2A9B40429
-:1049B000BFC86FD56736A21ABF2C68F46324FB41C9
-:1049C000E027434E889FB4AE8D5A7439B500E6FF98
-:1049D000E546A662DC66847FA4F9F3E48749F69392
-:1049E00068B107ACF89EE6E1DFDDD1F54C3CAF03E2
-:1049F00029E87DC344CEB7743AEA8E99E81CBA63BD
-:104A00000D560F94FF28DA0F80D80C635E50FFE23A
-:104A1000C7D14EEF3E7F5D3AC2ABFBB5450CBF2B15
-:104A2000715A6DB096E27BE73F6F5DEA8DE3C70890
-:104A3000FE3191F3C7617D6014393753CCFBF79297
-:104A400077D3279A84BFE1FF6F790776F55513B9BD
-:104A50005DBD9CFB3DB85D9D2C2774FEAB8F1B128A
-:104A6000F01EC97FDF21FD05EC5FE2BFA1891AF5C9
-:104A70002BEC5F984D76F16B4BB235C7C8F14B64A8
-:104A80009FC9E91D39BEAEAF85C2FE2356B463FC93
-:104A90003CFF34B444A2EF4B850212E9D9A1164B76
-:104AA00004DBF5F5C496F0B8E0529F44DF0BD1F576
-:104AB0003F5D3F1C6E9F0CEDEEB8BEA8EB85B100CC
-:104AC000F78B2EF15BA8FD3A25780BC2E9B7511B95
-:104AD0003D9F32838F0B7CE008FA3FAFFB8244DFBF
-:104AE000F3D2F5451D3F93F5C90FFA4B2EFA9DBA47
-:104AF00087055EEAF4353E892E7439B5AB92C3A7BB
-:104B00001DE57436CAE98F9541C7E87A37C8E9BB15
-:104B100070FDBB2A19BD3FF917722095DD9D21C696
-:104B2000DF8AE7066561ECC57A5C6F118B515ED454
-:104B300068F2F3B62A4E0FA3B5EFAABC343AFE8151
-:104B400098FFEF45C7FB27FEF7D05B87F53F25F5BC
-:104B50003EE755D5FF6822C0D56EEEA0FB51EC5F55
-:104B60002CE4B74EEE1712F218E499018F8F142936
-:104B700026B47B426DDCEEEFC9D25E21FBE4257EDC
-:104B8000EFFE7691AF74DB3995CA1EFC8018B67FB4
-:104B9000D94D7E9BDBF69DB0F8E1FDE56BA549E8BC
-:104BA0000F5ADE66DC4F4FAE7F6EA21FBC675C2FD4
-:104BB000C515C28F9768387E2B6E16FD213DF91101
-:104BC0008C3DB6A31FE7327C9E70DF02E6592D9E16
-:104BD0005F21FC3B2C490FF8F1C0EBE4EFC1B810AA
-:104BE000D2AFD22F515E48E818F777B4F773BEF012
-:104BF000769B44FCE46D919F115A6723FFB6AE4744
-:104C0000BC23FADD7AA744FADE08BDC26F8CBBACC8
-:104C10007EEC17C41793F508E7013E0EC65BD02F54
-:104C200073A468AA84F5D56017E2F74B439A766DB2
-:104C3000015F1F8B107FF11BFC281F1CFB37B22369
-:104C4000973F2FB16CD23B92E22F3DF392E22F4778
-:104C50008F14E03842CF50E13FF41F26EB19ED7D71
-:104C6000272C68177C529C45A91AF6B7905F708272
-:104C7000CCFDAC13FA2515FD4913049CA66DB113A8
-:104C80009CE6BCB1321BE95C3F9FF717F2F37AFF59
-:104C9000F50FEBF1BDA96FC82AF2DB1FBFBEF6E727
-:104CA00005BCAE59357C6F6D3ADA21EFBFB1261DD8
-:104CB000E1F86328F13B4A3F3C29A7F41FAE15FCFD
-:104CC00008E45B4115E6DBDE2DFCC632C8B78CB8C4
-:104CD000FF25F9BD1DC21EEBC1EF1B21FE3DCFE339
-:104CE000DB3DE382F3A8FE5031CF239639BE3EDB95
-:104CF0009FA5A2BE57059BC538ECF7ECAC1BE32B78
-:104D00003DB9C19F127D3C6422FC85F7F97727F6F7
-:104D10006B24EF106418FFA8015963A5BCC61C8A58
-:104D200083E8DF85190776A8F88EC2128CBB5689F6
-:104D300038488D9DC938FE364B706B25C65D0664BC
-:104D4000DF7A7C47F665E3F79292E3317A7C588FFD
-:104D5000CBE871E2D1E23212CE53C3F12CF13B2702
-:104D60007AFC857D81E76F764DEFA0FBAF63B12FB5
-:104D7000F1CF11F194D5686F26C753EEAAD4FB1B6F
-:104D8000E3695B2B9E217CFBB471B41F4C1C6D7ED0
-:104D90008D9E27CF3F39EB833CB25FFEF21F9924F3
-:104DA000CFFACF92DC393D9426EE710E723F75BF7B
-:104DB00085ECF5D36007E526C8B35F55F2710FF5B2
-:104DC000CF227C3C106B4CC7FE7FADE4F0D9F2DA09
-:104DD00092C5A84F876332CFC766DCAE391093A760
-:104DE00070FD60049C364D4C0127AB3D751ED054C0
-:104DF00081D753ABF8BE67BDCEED95D05A1E3F505C
-:104E000005BD859A14E227478BF224DD8F3C365589
-:104E10007CE1F921E2B3ADB7F2F8EE25C717FA0647
-:104E20002CAC3885DFB6690EF19B4BF5D732B482D6
-:104E3000A7C6F9F3769D9F5473FFADAB8AE7F33BAA
-:104E40003B26D5E377F1F47DA78023F35E5A9C2FB0
-:104E5000B3FAD2FA2DACB8B47E9B2B529C5F8A7EFB
-:104E6000DFB8C47E3FB8C479D353D1578A7E7FBCA4
-:104E7000C4795FAAFC9FF8E7703D39BE991C0F4DBD
-:104E80008E73A6BD747318DB364BF70C4511BA99B7
-:104E9000CF35E3F7D3E5ACC7ACC8D7E6CFE0F180B8
-:104EA0002D8DD6C86E291E17D5E1F55135D7BB54C7
-:104EB000EF99307E3F71BC3FD6980D747C7A062303
-:104EC000BBE1B44D7C0F4956C72DA4F353E97B38A1
-:104ED0003DB6D4F1A527C578A3F191A29AFAF3556E
-:104EE00053E8FE50CAEF54DC2FF440B58F91BF86D3
-:104EF000C9DAB84534AF360EE5CC9817F9F3CC28AB
-:104F0000A3FC3E68772F22FD5973E3FA7688B897A1
-:104F1000735E991BFD744E90B71817B90FE323E425
-:104F2000D757A99F3E5F9797CFB7C3C2248C63859D
-:104F30002B795E056BE935C4358E5BA2BF5B2151D1
-:104F40005C632CD2FBCF4C51EF1E373F1784AFF779
-:104F5000804AF19697677CA782EEC58B38C71D2AD9
-:104F6000EF7218ED0C58C71D2FD411FE2E3F34E3FD
-:104F7000572DA80F7A6482F3083D5CD85727857DAA
-:104F8000A8DB5783682726D81B555ED3687CA92ADF
-:104F9000155FDA2171FB37FC336EFFD629BE92C450
-:104FA0007CAA69021E2BA2DC0FABDBB535FE88297B
-:104FB0000FE05077A7399A06B2B76E53B582FCBAA4
-:104FC0006E53919DFC4A2BF79B7478A73AF77AB100
-:104FD000CE2DC786282EF16CF23D732F8FBB0E09A4
-:104FE000FCE9C2B385FA1DA572178ADF3133557308
-:104FF0002ABF782BE8FDB8BE153D7CBD7A1CA435D0
-:10500000AACDC2794E1D19DA84656D9B7B16F90D08
-:10501000579DD984723374FEECD1ABC80FA068A938
-:10502000EE0B586BCCB48E6751114178CD95296F3A
-:10503000B76EAE4CE7ED6CB5911DEEB430337E9F8C
-:10504000D5B990CBB1DAA69C5958674BB2480ED768
-:105050001ED3B26EF6C6ED7CE7DCB5B908A74F8A61
-:105060000FE9FE82EB14FF4D788E9F363EB4FAF8BE
-:105070006B946776C3A0313EA4C77B468B0FE9F1E2
-:10508000D950D387867872481E9A837E95BA174E78
-:10509000517C38D427A92E773C6E143A704621F8FB
-:1050A0008A7811F457F0BD3A38F6714EFCDE008F65
-:1050B0001F3D87F9B80A7E4F4FA5BCDB1F613E6ECE
-:1050C000197E4F8FE7E31EC47C5C05EF7FF07CDC2C
-:1050D0004322BF37D47F86E24D3D5E63BC428F479B
-:1050E000DC2505B679730DF10AAA27C72BCC766E9D
-:1050F00087868E59E8BBE8A1E356E2B3F5FD2B267F
-:10510000A03EA67FAFBC1DE30509FEA5F7FD3E1B33
-:10511000DEEF793FE0B3619CA06EE01D4523BE1336
-:105120002DC014A67639A6A0BD8F70A03CBFFE7A14
-:105130001BC2F513FDFA7DFFE3D7FF347EFD8C38EB
-:105140005D12FFA80D98E85E79ED31BFEDE604FE33
-:10515000B025C0FDC35B3CC5447F0F048AB356260F
-:10516000FAF19BB8FDE69CEBB1253E5F54C3EF0F0F
-:1051700038A5D4F70B5EF7EAFED711FCF6756F4A37
-:105180007D27753C604B13E723BABF7F647CC0F773
-:105190009227C1CFFFFECFACF47717069E4F23793D
-:1051A000FED10B697B50EFAE6D5A392103EAB5276A
-:1051B000D3989BCB23435C617993C96FCB4C154744
-:1051C000F017D0F74293E3054D26E2EFC3F18226B4
-:1051D000F914D5857E7EC3997FCFC04F643F2B45A0
-:1051E0007AD0BE7876B5E41B6023E3073070019B6C
-:1051F0000EBB68E27682AFD94A76C127C5155A0E32
-:105200009CD8887E82496C7B0F7E7F7292C7A48275
-:10521000284A1157E0F99DB5428F48F60F207EA02D
-:10522000DC4FF60B665673399459CDFD983B51AF60
-:10523000CF8D8FA3BF977CEE5F147269343FE3621A
-:10524000D1DEDD54BB05CF2D3CDFC490FF77373571
-:10525000583D09E3B9AB79DECC0E8C53E424C62962
-:10526000783C22393EA1F3A7BA818FE7E0B93FD05D
-:10527000CFFD472117F767D61DACA77B26F17572C6
-:10528000FC7CC0357CCF308BF17D312BF773915F87
-:10529000A176FE8787F0EF12B04016FD9D83D07196
-:1052A0004F9703F9C87C798AA4917F7BD8DF8DFE64
-:1052B000A8C5AFB4CDC37CE0BAA5934EE0B92C6DC0
-:1052C000B150DED1E2579AE9FBE3BABCAA5BBA7BE4
-:1052D00003FEDD9AA51592CFA6617B5303B65FFD51
-:1052E00054143D7B6C01AE0EE825761C7A17937F33
-:1052F000BBBE1AD65BB750F8BD5BB85C5DDABFD0F9
-:10530000C23F6E659473878B3E22BBF96C7F1DF99B
-:10531000B3B331DEEA8DCB99BA1740FE64C4E5CF52
-:10532000DF2A77BE58CDEDC0CB40FEE07A9C0B79EA
-:105330005C30F9FCDDE2FC479327A3F14F941FFC9E
-:10534000EFF2840B24575CEE6A684F4F8BCB5FB54E
-:105350000FEA6347C7BF87847E95358AFEF580C014
-:10536000F751F335FAFE3E7EEFEDD5FF3DE257BA39
-:105370007DA3FBBF757BE8F702CE7AF9AEC08BBF89
-:10538000395F198562CA7C6567EA7CE51B7A25FA74
-:105390000E8BC8573EA2B0FAFD3998A727EE2544D8
-:1053A00002A4DF1CD9F5EB4D4FE4E0BD044945B143
-:1053B000B3BAF704C9E7D5A0CF901ED4FF2EF74BA0
-:1053C000F5F2FCD2D57DC6FB0F7AE9ACE1F1F646E9
-:1053D000D80FF991451EDF9C039CAE437E25A2B9F0
-:1053E000D12FF41539D12F14D262B97A7E6084CBD3
-:1053F000A594797CED6C88F2FDDADB241FCA83CF9B
-:10540000EC27F2F3FCBE4BF513FDBCDA987F7AAEC5
-:105410008ADFFB690E4A12EAA356536015E5F71EB0
-:1054200094D45479A2EF087973B5F0D3EE55381EB1
-:10543000ECBD5CA2BC5ABC1783E7BBF720CF9FDF53
-:105440005BCBF3E775BFAC9E175F19F7CBD27D1826
-:105450003D9F5ECF8FD7EF872EDC698FA27EB1CDC7
-:10546000D2EB423A1CFE4E0FEA22D06E17DF194FE4
-:105470005EE72FAAEB775553BF51F59B3F56A7D058
-:105480006FFCC24EFB73F5A87AF95FAB8D7A39D504
-:1054900093F5F2FF2ABFEC37C43E53F9D552EB67C0
-:1054A00023FABD7889FD7E980A1E5DB6D4DF0B6DA8
-:1054B000AD11FC37E9EF92B011F77BB87CEB91B4FA
-:1054C0005F5D41712E0BC5B974FED293C1C7F78AD7
-:1054D000F1F4F2F3359CCF8CF65DC945A2DF5AC9D1
-:1054E0005F553305BF1F6FF49355F71AFD6497F5A9
-:1054F000390DF549D17C43FFBA63C586F629B189D8
-:1055000086F669276B0DF51983971BFA5FF1768391
-:10551000A1FEB921A39FECAA738B92EE1D71FCAE84
-:10552000078C487C6F96F58B867E056DC67D15755C
-:1055300018F735619D715FFAB8EEB0717F253DC6F1
-:10554000FD39D17FEFFDECFEFB9857E3DFC1E92F7A
-:10555000A1EFFEED68F2D077AEF5FB7FFF09FEEF1D
-:10556000D922F072000000000000000000000000DE
-:105570001F8B080000000000000B53E16760F8512A
-:105580000FC15BF918182EF021F8F4C01CCC0C0CDC
-:105590009C40ACC8C8C02001C4FC40CC06C49E0CD2
-:1055A0000C0CFF81F81B10BF05E22740EC0CC40770
-:1055B00058B09BE3C6CAC0E001C4DC40B378988908
-:1055C000B7DF8917C17ECCC3C0700E889FF1D0377A
-:1055D0000C061B5E27403FBB7E43ED3A2932F0FEAE
-:1055E00006612131609A1447F0A78AA3CA0B8B2168
-:1055F000D8C9D294D9950FD40F00F19321F080032C
-:1056000000000000000000001F8B080000000000E8
-:10561000000BED7D0B7C94C5B5F87CBBDFBE92DD45
-:10562000CD26E44900370960501E4B80C84BDDF0A1
-:105630003252C40411828A2CAF10027914A9A5FF3A
-:10564000DABB0B2804AADE5851A37F6A17041B2D6E
-:10565000DA80D11B6DE02EA208D56A684551AB0DEA
-:10566000888808498C8F6AB57ACF3933DF66E7CBF3
-:105670002E89B6FE6FFFBF7BC3AF1DE79B993367D3
-:10568000CE3973E6CC9999B3268383192E60EC1B2F
-:10569000FCBB9C319B893136A62B6D573A86AB39C2
-:1056A0005DE5B7F9BDCC6B66ACCE6FA5748B3F9D45
-:1056B0007907C3779FA1306867EC5EBF8BF2BFF0BC
-:1056C00017525AEB2FA27A77FA4B287FBBDF47E9B4
-:1056D000667F197DAFF157537E837F0DA59BD4451F
-:1056E000692C05FA66458559C98C553D9393B719C0
-:1056F000725B668D4F504743FE15233366017C9FD6
-:105700004AFD31D5BD69E0E8AE7A1A9E9BD449FDC9
-:10571000104EED128E17B3325B8C7A5938CE3B9710
-:105720000878F6D69A9CE4A8F50623BCDB4B00DE8D
-:1057300050287085AC39D1E15D8CF03697A8BC5EFD
-:1057400072B0263B3A3C0FD6ABB941C04B0F586301
-:10575000D41B83F536DC20F0EBE7ABC98ADEEF78AB
-:10576000ACC75CEADF5AAD8CFEBEC9C6FFB7BB4E04
-:105770005D2CF246CC263136AEAB9D3E652CC0701A
-:105780009C2AF315121FDC995F7F93CFD84D081325
-:10579000DA0726B19011FA0F24B1E0FA2CA9FE4CD9
-:1057A000AADFDAF7EB6F52A5FA014394FA26D6A0E6
-:1057B00060F9CF518E80EFF7F97329DD28E4E7BE59
-:1057C000A106C6B05DBA393808DADDE3F790BCDC73
-:1057D000ED1F4BE5770939FC7721674121670FA25F
-:1057E0009C41BA15E5CC8CFDF95A4B014EFBDE7895
-:1057F000B6D94DF2B598F05419C1DFB077C8F6CDDF
-:1058000000FFBE1B569DDE06F46F6B1EE63142BDE7
-:105810007B866AF2C5BC2CB9ABDE3DB34F38170DA1
-:10582000257A97219CBB3D827F2A0C2CA2DEDD339A
-:10583000C2F52AB0DE5D9E30BC5064BF774D09D7FB
-:105840005B457C56584983BD3B5F763085E623082F
-:105850000AD1D784F48579F9EC80EB9456689F924D
-:105860009C97C6A0DDFD381FCD38EFDC4417AD3D59
-:10587000D2D907DF332CAC1AE10365F71B015FD3E4
-:105880006C7722D2E5F66B8B98328CB1BEA23C3598
-:1058900050A464015CFB9C2205BF9B6643397C7766
-:1058A00089F2E435BCFC762C7774952762397C4FFD
-:1058B000AA8672C8DBE7F2F23BFCC089C15DF5360F
-:1058C000019F7DC4EF74FE1DD88AF4318DE6A98650
-:1058D000F713282440BF83988EE9C27FD3A07B337F
-:1058E00016DABBF0B50DAEA7BC86DFA6C17194D7A2
-:1058F000F0B15DD82F6321A47D97F465DE5C311F84
-:1059000058773A277AB3A5F24CD593A0029D325F1F
-:1059100032B200B02013C413E1E9DB153103E1D941
-:10592000E3FC4BEEDDFC330D95E9A0A547053D34C6
-:105930003A6CEC2FD3C13240A6C3C601321D2C17DE
-:105940009C9F0E3B989BE81C8B1E5ABF9B87C8FDF3
-:10595000C65D24F7BBF922B9DFB88BFF39FDD664E9
-:10596000C9FD5AB3E57E6BB2E57EAD39FF58BF4C39
-:10597000F5C064407DA5FD5D28E9B7AB99EF2CB675
-:10598000473D87F349D373A6641FF3D9BBF809EBEE
-:105990001463F99170064B7A15E07C8AF5008EF756
-:1059A000FC705C3A3883F470BE16F8B0483DDD0DEB
-:1059B0000E1BA81F8749E1ED428688FE99EA6345E0
-:1059C0008EC8761E5DFF39FAFE9D8A1887E1BCFD00
-:1059D000BB7574CDD6E39326F06186F3D183B97499
-:1059E00070B2F470DC029F90725E386EFD382E1437
-:1059F000FD071469FD027A0CEB6AD70EF8D13A95CF
-:105A00006709EE04FD10DAF7E5295C07CE355EEB99
-:105A1000B640FDFD232DA1CBA1FC5CB0206881F236
-:105A2000C94F1E75A21D53F1A451C572C33E1BADD3
-:105A30002F6D3B142AAFB2B4DC3901CA3B9E34B29D
-:105A4000EDD45DA601C7774AE81416E2F9521BCFE0
-:105A5000566CDB7F23B62F6BB2301BC0AB787AD984
-:105A6000CC09905F76C8C4B04AC5CEB5E6BE905F9B
-:105A70001E541A300FF8D23A15C8B3057742FD7597
-:105A8000FBBE6C43FCCF359A06213E67609D70C318
-:105A90003AF192A3257536D0A73CB87B1AB62FDF12
-:105AA000A57840C301FE3B0F6620FE8F281E0BB079
-:105AB00070457D3C7347CC97538D461AEFAA6D4ACB
-:105AC0009001BC65AC761AD2B302898378782C41F8
-:105AD0009BD235DFCEF8EBA83F2D5FF108F407ED40
-:105AE0002B1F573C38E44A03F3E13C6E7BDA56F255
-:105AF000901DC7BBD63CD881E3DC68C67ACB820B4D
-:105B00009FB2B911CF6DE66988EFD66DE6D2A14894
-:105B100047B6A06828E2F77F65FCEA8C5E1CEFAA16
-:105B20009196ED46C083D943036739BAEBD933B0B8
-:105B30005EB923D6CF72067A9FD6EFA0B97858D730
-:105B4000F72F0D89A43F56D41B99DBDAD58F261F7A
-:105B50008123423EF63A88DE1A3F57B9F814D0F84E
-:105B6000B92A51F057EDC89F35AC3B3E77225FC84C
-:105B70009E7651FA0B583731DD02EB3CD2EF5EB026
-:105B80009FDC64977BE8FB03602761BA15EC244C2B
-:105B90001F043BC92DEC24ACB71DEC244C77809D31
-:105BA00084DF1F067B1CD37AB0C7F1FBA3608F6331
-:105BB000BACB1FA0EF8FFB6B286DF0D752BA07F955
-:105BC0000669A33F48F59EF2D753DAE46FA0EFCF02
-:105BD000F89B28BD5DD0D1399115E03AEAF432172F
-:105BE000923D6986B7C004F9A4229E4FBD21506042
-:105BF000867CAA0FF24097BE2B430516C8F7ADE688
-:105C0000E5036E6193AC901F10E0E5D9B77B27D90F
-:105C1000209F5DCBCB076F0D4C8A83FCE0202FBF0C
-:105C2000685768523CE42F6AE0E5C39BD9643BE4C3
-:105C30008787783EEF25EF6407E4F35A783EFFCF7D
-:105C400081C94EC8E7B7F2F6E3CF068DEE28EBEF39
-:105C50001E937B31AA9C03CADB5E3503F266F74DC7
-:105C6000A8128F2AA728DF68F252F9FB4ABB578592
-:105C700075BED1ECA5F22F94CF29FF94C947E5F169
-:105C800006A580F2661F95F737C451BEC914A0F26D
-:105C900011863E3C6F0E507981A15F01C27FC61410
-:105CA000A4F26B0C8378DE1CA4F25FA8C30BA640A1
-:105CB000FDC70DBEBDA8EFD62BBE32B40F99DA904A
-:105CC0008EFA4AB32B77E2E0D0CECC30D33CD8F377
-:105CD00087FC87681EE05F32E64B1F46BB14E01C62
-:105CE0002438268063EC194EDECB632538792F9754
-:105CF00069705E2138B6DEC1D9F3F278199F97CB6F
-:105D00003538C7088EA377E3CA7B65A28CCF2B2BCF
-:105D10003538C7094E62EFF0693C2AD3A7F168987D
-:105D20003E67707D589FD23B7C46BF26D367F46B9D
-:105D300061FA7C4CF864F40E4EE36B327D1A5F0B13
-:105D4000D3E72B82D3BF77E31AFDBA4C9FD1AF873D
-:105D5000E96332209CACDEC179EA6D993E4FBD1DEE
-:105D6000A68FD380F419D4BB71E5BF23D327FF9D41
-:105D7000307DD2089F21BD83F3D43B327D9E7A27AC
-:105D80004C1F37E133AC77E3CAFF8B4C9FFCBF84D9
-:105D9000E93384E08CEC1D3E4DEFC9F4697A2F4C59
-:105DA0009F3C8233A677F88C3D25D367ECA9307DE4
-:105DB00026109C71BD83D3744AA64FD3A9307DA60B
-:105DC000109D2FEDDDB8C6BE2FD367ECFB61FA5CEA
-:105DD00045700A7CF5840F03388ED8709E3927D31E
-:105DE000E7997361FACC213853014E4ECF70C6B794
-:105DF000C9F419DF16A6CF02827365EFE03CD32603
-:105E0000D3E799B6307DCA88CE57F56E5CE3DB6583
-:105E1000FA8C6FE7F4A9B278263BD0BE4B649EEDB6
-:105E2000D0E492930D079C9037D99907C1BEA48402
-:105E300076207C582BC92E543D9A9DE2616887CE0E
-:105E400070BA3DE8F7316AF6086BA1FD827D57A272
-:105E5000E40FFAD230E916C4D701565BA45D923044
-:105E6000364EB28712BD4952BE4F615FA97E4A517C
-:105E7000B6549E567291549EE1CB93F29965E3A578
-:105E8000FAFDAB2749F90BD64C97EA67056649F945
-:105E90009C9AEBA4FA836A1749E517D6954BE5431C
-:105EA00082ABA4FCC5F5FF47AA3FAC619D543EA25E
-:105EB00069B3543E32F40B293FEAD00352FD312D31
-:105EC000DBA5F24B8E3D2A958F6BDD23E5279C7E6B
-:105ED000466707CAFBFFF5058CDB831966B20743EB
-:105EE0000E33E5CDFB6C64FFEFC73CF0D3DC7706E7
-:105EF000E5CDCF2E7627E37E1A01C07A5FD0B7ECCE
-:105F000042F4F7DC3CDE77A10BBEDF6CF68D70450A
-:105F1000F1477854DF3E03F98B5A14968EA9DB8043
-:105F2000699C51ECD72D5CBE3666E53F148890D352
-:105F30009AFE30FF207FD86026FB5593EF8DFD4BF6
-:105F4000D31746F4B3A1BFB964FB50FE7DB11DFB6E
-:105F50002B7A11E75995B96330E2A5EFC7923D5608
-:105F6000EAC73AA08CFA790DFB89F07B590694E9CF
-:105F7000FAB1966C17DF453FC7705CB1FAD9983D0E
-:105F80005E1ECF8072EAE75D5D3F1B0794EBFA89E6
-:105F9000E3E381EFA29FF7CE3B9E9C89F2782E58D7
-:105FA00049FD74E8E866B960A5AE1F3BF583DF17CD
-:105FB000933F17760169C0674B4729C9C17FDA58FB
-:105FC00000E4C29C59FE6BCCB3B76C6C10F6E38650
-:105FD0007EA11ECBE5FEA3A70D49349ECFE280FF34
-:105FE00011766AD77E3640FBE2A5024516048C6026
-:105FF0007F5B296473C9AEE20137B9216D3A30F095
-:106000006EEC678BC33308F26D4D93CD8BA3C8D371
-:10601000D25AD3A9D648BF88B6BF99C472ABA1FFE4
-:106020005D369794D7D2958A8B097F04E54FC0BE21
-:1060300085C17EE0CFB02F6040AA774D7C9FF60EE1
-:10604000EC6F30DF0AFB1B2C676C2DB53B21FCB4D9
-:10605000276E578248EFCF7EF24313E9F1007B357C
-:106060003D15FD6EFC6FC19A78F4F187F15B18E87D
-:1060700023E5415D661AD2695F48FBDF8EA72DC11B
-:10608000ED48D79A4CA0A9A897CDD8EBB0C9CD4878
-:10609000A26CA6612C63B3AB8BA7A6D12C52FAAF2E
-:1060A000023C67358E34410BD6666ABDD163EF8200
-:1060B000CBBCA613481F2BFC4338D714423EA2FF8B
-:1060C0006B8BE4FC5CA676E581DF838DD9826FA2C1
-:1060D0005FB7D7847C2D4AE5F8CCC5340F8BB9BFA8
-:1060E000A3C4C5DB6AF8542D36B110ED4F03290C5B
-:1060F000FDD18164AA779DB6CFD4E15762B27A8B85
-:1061000080AE250B8D44573DBE6FEE8BF71A86434C
-:106110005A73B7095D9B3DE13FCF2797B332DE9FAE
-:1061200046574D5E4E09FE9E40FE43FA3EF21FF07A
-:106130003E29F8DF25C79CFF5516DF4CE47FC7FDDD
-:106140004646FC127C9F23F8BEB456E6FB1CF49333
-:1061500043FD39ABB382EBB17E5D1F89BF307099CF
-:106160000EB5774D05B5DA0DFFB7851C5C57B3FB4F
-:106170007964EFF565BAF1093EDC28F8305F478FA6
-:1061800039826FF305DF96B1C06D19E43F0A9AD0EA
-:106190002F36AF4C61A82FAA7EAAF1AD55E29B4FD6
-:1061A000E39B0EDF1B05DF6EFC09E79B1EEF56C16C
-:1061B000B7D6BA8F4D2CBB3BDE7A3C17ACD18D2BBA
-:1061C000A0E75BAD38777099D1DE29F616F439195E
-:1061D00051FF9AC22BFB9C8CD00BD716154BF9B9EB
-:1061E00025F3A4FAF37C0BA5F2EBCB964BE5F3ABCE
-:1061F0007F28E517ACF989547F6160AD54BEB8665D
-:106200009354BEB4F62E29BFACEE7EA9FEF2E03662
-:10621000A97C45FD23527945C36E295FD5F4B4545A
-:10622000DFB06FC8D5285F2F1D3532F4977DEA792E
-:106230009FFC759F7A4C1EAC538932370EE5D94DC1
-:10624000F27CCA9F4BE969BF87E4FD8C7F2CA56D6A
-:106250004D07ECE87FAC8A03BD9F0876B8F1CDB559
-:1062600035FD70BD81F6E3196B36B6AE0D40FE000C
-:106270001E46C1BC99516766A1510CA4BB6F589EC4
-:106280003B8C11E5AD3D94D7A92CD4A77BF98CD6D6
-:10629000E8DFDB958EC119E8277CC3C27646F8EBB0
-:1062A000BA9F57B04CB42B62959F35B0B2C8F3ACCF
-:1062B00093467E4EE2344E3A698474A599CFFF9599
-:1062C0007B32263127E64383ABA3F85DC2FD350060
-:1062D0003269C8E71C69DE2FABBBB86B9E33EC2775
-:1062E0009BE476797094F47D45FD04A95DAEE27B74
-:1062F000D708F5CEEE37D27ACD4207065C330CF1E3
-:10630000F39EC4EFAC2985ECAE16BFB7CFC9818C24
-:10631000FDD15F48E9ABFE224A5FF397507ACCEF9C
-:10632000A3F44D7F19A57FF65753FA8E7F0DA5ADC7
-:10633000FE00A527FC35949EF4D7527ACA5F47E940
-:10634000697F90D233FE7A4ACFFA1B286DF337511A
-:10635000AAE9CF9EE4EFB4585FCFA0FC459133F398
-:10636000AD6C5DCDC42E398B532DEB50CE34FACEAF
-:10637000A8B308794895E42111D76192B31ECAEBFE
-:106380004C420E63B58F5E8EF2D6F77B9037C6D641
-:10639000911CCC1472F75DE58DA1373E05E52953BC
-:1063A000274FB21C6A72A4E9815CA568B83AA64B73
-:1063B000AE661AB99DA4C9D5CFD14E8C626FDDA04F
-:1063C0002A62FDE3F611F36518D07E5B25FCFECC56
-:1063D0009D4EF94ED1F77A00D782F5D4602EAE23C8
-:1063E0009DB97F1B8CFEF1CE6316867EF858E3D3F1
-:1063F000CB4B6CBA7B69FF501A84456D54F7725BC6
-:106400001CA7ABCDC00A591E9ECFE61FF3013FE388
-:10641000FEF3E23CDCD7C27795915D15F41447F1A9
-:10642000B73394F1B49EE9ABD53FF5C097F9786ED8
-:106430003E53CCF3B803467EAE1D7AC8734DC4F903
-:106440000CECB7D3D1EFDC31C8EC22FB21D457A63A
-:1064500063B0AF44C703833E1B8CE71B9B400E71A8
-:106460007E750E1C9CC0CE231F3DE9F99EE8B9281D
-:10647000D8B797F434333C37027A6EC7FB2FBDA5EB
-:10648000674F7AB227FD786233A7B353D8A7B1E834
-:10649000DC3E09E65D1439BE475565396603F97976
-:1064A00087467FDC9746D0FF52BB9BEA3FB7EFADF4
-:1064B00001ADD04F67E385098C9FE7905DD7F1A4CC
-:1064C000B0DBDD99321F5BFB125C0DCE734FBE3E1D
-:1064D00000F7C9B76106E6D993F145BF5253BAE058
-:1064E000F5F61C3ED6B8767FCBF9D99EAACDCF96CD
-:1064F00001284F9F093D10737C3DC9298E0FE05C38
-:10650000A5F0F16D3016FD0EF54C787CA3537A356D
-:10651000BEAA04335346007E0EB3992530B643F528
-:106520001D54691FE7690DA09F625FBC673DB0A461
-:10653000CA79E6E5901BDBC9FE8C15F536976C3FF2
-:1065400025BA64FB29C315693F751E7AC8E903FCA7
-:1065500056A51B5C2747E13AE715EB1C5F5735FC56
-:106560002A1AB25C76098E9CEFAC550A1B489EDC59
-:1065700009B3A39C9769E9AA74B3EB24AC5767EA03
-:106580007312B0DF337EAB8BAFAF2E17EF37DD1555
-:10659000B9BEAE5C1347F535FC62C1FD67E3C75871
-:1065A000237BD78AEB2294E5C4AE1F939FEA27662C
-:1065B0003A976E367D86F6BB2D57B3DF55CA6B70A2
-:1065C000AB1A8C01CB08FCBE4BEA0FDAB9B53366C7
-:1065D0006C175B6E54764AE327F0DF8A07EFB46FDF
-:1065E000B5129F7D003101E0B5ABF61A94AB132ACA
-:1065F0009FCF55424E2BACAD669F9BC8DD82F2BC4F
-:10660000682CD326CCDCB7404F7FF0A289EE69B16D
-:10661000AF007A7ED7558125ACC8894ECF458D2BEA
-:1066200066E0BAFD8141DB0FD7E6E3B8CF31432105
-:10663000EAA573EC8FCE5111F3758889FB63580D71
-:10664000DFE704E01F8E6F69ADBCEF595627E74BBB
-:10665000D9AC54D4B7A55B4C2C08B82FC77D933662
-:106660006ED0BF1926EED758C6AA37E03EFD5E139E
-:10667000F7F72C72313513F0AAF88F5FE6A3DFC766
-:1066800063E27687769EBC3C89E35D3E3B68F642DA
-:10669000FD771B47CD018D0BED831BC8FE29669E40
-:1066A0009DAC3BDD17D7C8F8F584BF1E5FCD0EEA61
-:1066B00076AE2DF048AE57BCC1287AEE329322F662
-:1066C0007F7C7ECC36C9FE9C7926D9EFA3C981494F
-:1066D000C8C109D577B5690CE73BF251513BCCBE37
-:1066E000887AE6AE7AB3CF57CF82F58C546F9E2965
-:1066F00005EB754CA3FD3103791ADA55CFD605EFBA
-:10670000460E4FAE57F11F8F3D15007929FFED3D25
-:106710004E06EBE6076A6DAA07BEAFDC799BD30B8A
-:10672000E96935E0447E7E10341646A3C796303DB5
-:10673000BC7605FD69423E594D80FC149FED34B98D
-:10674000C8CF5F6F0959404E2B1B97CF60C3297F7D
-:106750009CE7377E64C47C93CCAFF25FDF93EAE6BC
-:10676000F76CB83F8985C8CEADDCF1DE345C2FAA6A
-:106770005807C999BE1DF6FF7912CDEB85E684EE68
-:10678000E58027F913AAC42CAB6AFCF9474627E633
-:1067900065F92813F62AD209F7F9B7991CC9A7E2B7
-:1067A000217B09BB04E7B9460F16E476EBFA47EE06
-:1067B0001B7E1CF039BBE345A73234523F7039EBE6
-:1067C0006C58FC2BAB21B61E6903398CB48F00309A
-:1067D000B57337097BBB99A72B4D2127DE6759B9C4
-:1067E000CDE40109642B1F3332BC07C0DEB004D1F5
-:1067F0002FBAE2B1E75F1B0F745FB1DB943C830FEC
-:10680000C7AEA476F1A50AFEB726AF8B0FE54F3CC5
-:106810006F760FE3DF6F49EAE2C78ADDFBCD6C5884
-:1068200077FA4D6ED86F6EB547E14BC3F169B8CEBC
-:10683000AE7FE4AF66F4277EB04F616959DDDB9728
-:106840006D7B9ED63BA413F151F029CCB76EFC0AA8
-:10685000CD7C6634D573A11E8CC5AF6542EF823CFA
-:106860003FFE0CDEFF79D3E2C1F1973D7E9313C763
-:10687000F1BE5ACDE5FA97B7A5E2FC2E3305525D7D
-:1068800094F2EF650FFE88E46DD9911FA592BDC00B
-:10689000BC1906D2C5810C1CDFD2ADD7D2F84A99FB
-:1068A0008FE4AEEC97C622BC8FF8A9CA0A77479945
-:1068B00017716685F0797F3B183230BEF7717F899A
-:1068C000FAEC8F46BA17C5D80FE9DED88FC45861E5
-:1068D000E5A3FCA756CEA7E3424FE24496E475C772
-:1068E000C616E4CF99FEDE343CE7003A0404BD94BA
-:1068F0006F00AEF1C8D434CE1FE656F3453BD0EF5F
-:1069000093F13BD66F31796DC3A576421FF2FE57E6
-:106910008BFE01EF385CAFDE4F8D6EEF8D11E383A0
-:10692000BF1616215F11F39BCFF71D9BF8FCD6E62F
-:106930007BB0B810CB3F7995CF1F6C87EB03E01588
-:106940004AA3F2FDB315D207B0AF8E36AF7798C425
-:10695000BC96CBC152A4F51EF0569584483901F877
-:1069600049447FDA07976E817611F65715F647F599
-:10697000CC5DDF23D68765420F98CC30FF2FEE9A8F
-:10698000FF6C2B9FF73DD9932B4DC1871FC0F9FAA0
-:1069900086C51370E37C3515E1B83FDC75E0B5EBD7
-:1069A00040AE3F6CD0E6A9AC3FF5F3B46CCF1816FF
-:1069B0006D9E7E6887FD55B4790ADFA3CE537B2B8D
-:1069C000C9F1F7AD3F35BA0D35CB7A13F5E033EEAB
-:1069D000D8F4D3EBC1DF9BDC4447BD1E84BF5759BD
-:1069E0007E77B9D3E44D93B3F2DF545C80FA262C62
-:1069F0008F9ABC85E5519337FD3865BAE9CBFF2AFC
-:106A0000F4CDF5D6C26BD02EB67630DAAF14CC36D4
-:106A100006719F6CFD84D17C9F74433CE5E71A5B53
-:106A20009F409BEFAD8AB9C3701DBF9E054CFCDC37
-:106A3000BCD64476EA57DF7C3311C6739DA0EBF5D4
-:106A400040E6AB800F25AA128A033CE7A92C909060
-:106A500084FE62859D88C0E3FA32398F7F97A576E0
-:106A6000C1E9A9FEB7B5ABBF6B7AC4CFCFAEFE8488
-:106A700029ED2FC0708E90A3E2667E4E51355A09E3
-:106A800066D3FC6B558B22F6098F99B99D7164CA48
-:106A90003563907E05738725907CD70EA17D609528
-:106AA000D05B9D017702EAF3CEE61CDAF7751E5A39
-:106AB000ECF045D15F07849C3D2FCE59DAED4AAD0D
-:106AC00011E4BD9D7590DD12B0DBA2FADDEACC06C3
-:106AD00061EF08BEC19F11FA2F1172380F9A26E498
-:106AE00045F06DF6551FA8CEEE7CC0BF1311FB8696
-:106AF0007F94BE28D748DF03B6D6694551FC338F53
-:106B00000A7D7DD9B35F98719D9BD25CA0221DA7A1
-:106B1000D88D92BF63BB365F87B2A188D765CF2E71
-:106B2000BF630CC871D521A3C706E3AB6AFEC8ECEE
-:106B30008BB27FD3D313E1A3FDD86AE6F6F15153AC
-:106B4000D152A4EBD16BF979EE9FCC9E8A6878CEB6
-:106B5000B6723CE7B1A24F472BFF7AF42D98EB08B1
-:106B60004D027A74DAF9FDE4EEF2C7E77DA74B092E
-:106B7000AE55500E8D3C9FCCEFFF4E63BE3B262A98
-:106B800034DF2F8FD45F054DC58FE17D96CA66C572
-:106B90006580F24AB5D58C725CD5B45B45BBFC0709
-:106BA0006EFECE82A9D5C36647F8B75ACDDC9F7476
-:106BB000E06FD7CD47FA7E3CDBC2102FEFD08F9C21
-:106BC000B8DE7FDC3C8AE641AC71FDC1EFB9660AF4
-:106BD000FAE3CD5C9FE9E5615A72BC94BF7632EB73
-:106BE00087E7BC97595A6FF244E1DF3A0B9FA7BD84
-:106BF000D66FD6FF61FA6D22E8372ED7A648FD364C
-:106C0000DDC2E53E42BFA545D36FABD6BAD3502E09
-:106C100056EDCD4943BEAE3ABC34259A7E7B41EC5D
-:106C20006B0F8B7BD2EDFD40BF8D88D06FFD40BFD9
-:106C300045F1838FB66876670FFACDFADF33FF5ED2
-:106C400040FD1665BC5708B9D3F45B61F35AD26FA7
-:106C500085FD8CD27DA4CB2CC28E8BA9DF16DE7372
-:106C60002DE54D9EF828F2837445FD7658E839EC01
-:106C700007F5DCCF2CDF4ECFCDB3727C7BD473FF16
-:106C80004D74D6F4DCAAFE0AD92FDDE590EBB95598
-:106C9000595CCFADDACBF5DCAA415CCFE9F5DBA4DA
-:106CA0006EFA8DB7AFCC85F6B44FCCBAEF06BCCF39
-:106CB0005762F258A1FE0CB7F6BEA07A4CA4BEFBF8
-:106CC000992586BEF380BEB3F7ACEF5E417DA792F7
-:106CD0001E1B88F3482F1FD307C64BF7D58E7E7136
-:106CE000EA37BFC5F9F20723DD077ADDC0F743FBBA
-:106CF000BE38350AE7DDCB880FCC979D42FEDAFC23
-:106D000063499F4E1ECAE77BC5A1385A272A1B1527
-:106D10003EDE5B94A01BD781BF7D4EFBE4F97BF97F
-:106D20003E79AE85D383FDD8C8DF4500091646C835
-:106D300043C9E7E5E4E72B519915EDD70587A67F11
-:106D40008076EB82CF6BC8DE5D80DFF17EC5EED64C
-:106D50000D99D0EFFCE50AED3798B80FA1DD97B893
-:106D6000BE793FDD5FD1DF83D0F4F9FC6AF9FB0225
-:106D70009D5D7F408C13EC59A20B7BC518D53F77E6
-:106D8000404F0F0F1F7FC56A6E1F87E901F4712BFB
-:106D9000DDE9011C9DB130B56BFCF39F8471257753
-:106DA0008D4BA3877E7CDAFE6481981BB1C6ABD184
-:106DB000AFDB78357AEAC6FDBC45D84517B36138F4
-:106DC000CF5E37F8EE188372F17B183FE03367DE51
-:106DD000A0B4483DFCA2D0E757F98E4F497523BDBA
-:106DE000F8FBBBEBCA763F9F0AE3B8DA9B9587575F
-:106DF00011AEFD9BD9877E8403B60ED26B9A5C5D83
-:106E000068E572FE7701E7685FD7145A3F9A141756
-:106E1000CD97904E6F897B6155404F9C8F554D6249
-:106E2000BD0179C3F9364D5B7F90FEF09F573573F6
-:106E3000FA57552B44FF99ACE320D2B73259F1846D
-:106E400000D4B4A6DDB7E13DAA176CF01DE76D993B
-:106E5000E2D9CEC961CF488D2A976A34B964D54347
-:106E6000C8AFA0AD830BB05E12BE17793D05ED1320
-:106E7000BDBD7199A5E528E271D98F4D6C1BEB6EF4
-:106E80007F68FCCE857FDF44BBCFD383FC0E12F638
-:106E9000E50B486F3BD2B5C38C725F15E2EB8656AB
-:106EA0005EA5BAA7107D347A37C1BA309AD31BDFFA
-:106EB0007DE9E979B5964779C6FACD8A09DB5F099C
-:106EC0007CE80345930D5F1CD4E417DF89E9E98270
-:106ED000FBFF8C88F98E7A29F2DCB1B2E908D16522
-:106EE000FA6A30AB22E88EFAEA7CF4E9361F9AF6A9
-:106EF00047BD07F56DE7C38556793EECB375BC38E1
-:106F000002FD5B7B15D207AC3951DADF5F61E5FB2F
-:106F1000A603361FC96DC76113DDF7D6EB8DB182AD
-:106F2000FEB89F887C0737190782E7BB2E1B7B576B
-:106F3000C3239BCB4FA4BE7EC1E6233EC5823F4DFB
-:106F4000C08F652F85F1C5FEF03CC52DF7A75F2FDB
-:106F5000343F4F4FE3BA46ACF7DF755CE1F349D6F7
-:106F60006266DC9FBFDB1C71CE3447F8F9353F58B1
-:106F700044BD999631B1EBA1BF2504E37E61D743AF
-:106F8000E4D73DF7E8F19928B72B7E676456E073A4
-:106F9000DB2E070BF17B14665C57CB1B8D51CF4565
-:106FA000185B4FF8ADF8AD83F44AF91E4B7006B488
-:106FB0002F7FEADDE1E89F6A5BC7F54BE051211FB7
-:106FC00081D6E1785E5EAEF2F3623DBC1F0B79398B
-:106FD000FB747C09EA47A59EBFEB2C6F986BB2440B
-:106FE000ECCB2BF1C08DD7A37BC8814714F28377FC
-:106FF000C76F2DAFF708D77BE54DA620BE0F2DAF8D
-:10700000DF46FBD9AAFA8FCC68C74DFEED63644713
-:10701000543519653F61BD3164213FA6F138A67A28
-:107020007F5D656305CDC7CA06E10FD3F98B56FCBA
-:1070300076EF530120CD8A277EED443D73A665A7E8
-:1070400093FC70F5DCCFA6DAD5E87EB89EFC6F0D18
-:107050009BA2FADFCEE07FC0FCDB6A95FD6FACBE81
-:107060004FAFCEC1573CF6E983782E7476CF870FA9
-:1070700022DE2BBFFEF8C19FA27DB2CFE6C2F5AEE5
-:10708000EAD1A3E457D7DA3D25E655DB23BF7EF8E6
-:1070900001987F6D6F58E8FE55DBDEF707B8619CFD
-:1070A0006DBBBF4845FFE5EABD5369DFB2FAC9C908
-:1070B00069E7BB47827219ECC579889E0F071A8D64
-:1070C0000CDF419E3B66213B23EC476DA8E07E69C7
-:1070D000B7F09FEE8A7EEEA4F9FD2A1BAFB9FA52F3
-:1070E0005CF71A4D1E377D177EC09EFCA6AF023F8F
-:1070F00047F4826FBB845F5CC7B773F81FC09F3FC4
-:1071000059657FF3A78D4B7FF5009635F689E937F2
-:107110000DF5825EDAB9D636ABF71D2BCE873DBFB3
-:1071200021FF34F20B6C6ED6F6D8A703D0DF70DAED
-:10713000D47123DDBFD86BA17B42E57B5FA7F9D17A
-:10714000F6E4113A2F62E25CA98D85FFF83980D808
-:10715000CB54ED70707FABA03BFA63DD4EFA2EFC92
-:10716000AE5C6E357F6C2C3F6C1F9BB8072ECED962
-:107170002A76BC65663ABFB63216F9745C3A17D403
-:10718000C6AD87E7423A5C12799E10CBCF2DF468EA
-:10719000984FFC1CA16D9B385F089F1B30D62F0FAA
-:1071A000EFBFF3F3EEAAA0F23A8B321FB5F304A7B8
-:1071B0004D371F83BD3B47E819DFEF460FC5C6F7C4
-:1071C000AD1A5DCE7E155D1F0FB129E2FD812FD76F
-:1071D00016B1EE2C10EB4925D08BBF27E3F89E1596
-:1071E000FBBBB38F1A83B80FDED07080F4AA7E5E2B
-:1071F00057B2E8F143C6DBB83EA96CDA3F1CF5CFC5
-:10720000D9679F26B9ABDC75DC1C003807EB9F30D3
-:10721000B70EED9273D4D7C1087D7DF6F1FDC3F9A9
-:107220003907DF47EAE15F21E05735CBF0AB767DE8
-:1072300024C15F116830BBEC3DF77346F5CEC5F154
-:107240009E6931515C94330DC6C268F14A86622052
-:10725000A9942E3A6D70F0F771C62433D991AB1D05
-:10726000638F2524636A76E33E7AFD5A7E1F72FDA2
-:10727000CF3CE9C897F58973E81CA856474757B231
-:10728000AB00F7D7AE2945A351ACF47A20D16B906F
-:10729000F05EED284CC3F7DCB70A7B84A91E7ABFE9
-:1072A00067744E2BC471185D06972DEA3ACAE199AE
-:1072B000EC45142FC2E492DFD37DEFF11FDCFDE437
-:1072C000F80F817EFF68FC07467130FEDFC77F083C
-:1072D000603FFF02F11F42E4B7D1E23F247FCFF1CC
-:1072E0001FD63239FE83E06738FE83E0E7FFC67FB2
-:1072F000F8FF2BFE8331EEEF53303E8316FF21253E
-:10730000CE3C3532FEC38571095323E33F8C8B4B52
-:107310009F1A19FFE10771595323E33FCC8FBB68D4
-:107320006A64FC87AAB8515323E33FAC8D9B48792C
-:107330002DFEC3DD7153A7CAF11F664E9D02F9B63B
-:1073400038DFDF71BD8A15FFE13D9C2C637A8EFF2B
-:107350000070CC716362C77FD0C38915FF01E02440
-:10736000109C18F11FBAE11323FE03C049273831DE
-:10737000E23F74C32746FC078093457062C47FD008
-:10738000C38915FF01E05C1497123BFE831E4EACCF
-:10739000F80F006714E11323FE43377C62C47F00BB
-:1073A0003813094E8CF80FDDF08911FF01E04CA570
-:1073B00071C588FFA087132BFE03C09949F8C488C4
-:1073C000FFA087132BFE03C0994BF8C488FFD00D94
-:1073D0009F18F11F008E8FF08911FFA11B3E31E233
-:1073E0003F009CE5042746FC073D9C58F11F00CE5A
-:1073F0002A821323FE831E4EACF80F00E7A7042752
-:1074000046FC876EF8C488FF00706E253831E23F75
-:1074100074C32746FC07807307C18911FF410F27FA
-:1074200056FC0780732FC18911FF410F2756FC07B7
-:1074300080F32B821323FE43377C62C47F0038F530
-:10744000248731E23F74C3E7BBC67FB085062A3983
-:1074500014FF81E24486E33F247FEBF80FCD88EFF1
-:10746000FFC67FF89F19FFE166BBEFEB38F2837E22
-:10747000B7F80FB6F86F17FFE1667B517C3CEE2F33
-:10748000BF65FC87D4F86F17FF01FA498F1F13BB44
-:107490009F58F11F7274FDF414FF01FA1974DEF1A4
-:1074A000C488FFE0D1D1EDFB8AFFF045DCF9E33F72
-:1074B000FCCBC559806D0A9EFF149328B27F99B802
-:1074C0000BD7C6FF93E32E90B1F0AF1477417BBF8B
-:1074D000DF60C2F5EA4DC1F7D7845CBC25E22F1C02
-:1074E0008B197F217815F94597CBF117A60B3ECE66
-:1074F000F3C9F2309DF1F386E953B278BCCC325D2A
-:10750000FC855CF9FC7A86EFC81400C7AEF2C8E3CC
-:107510003822E46166C947CF217BAE1E1B3DFEC207
-:107520002CC18F621D5DA60BBE158BF47A7C920276
-:10753000F23CA3EC888A749DE96E55C9AFFD038DBA
-:107540007F6E897FB3055C3DBEB304FF665DC9F9FC
-:10755000A7C7FB55E49F13D2B251C43F3DDE7A3C2E
-:10756000F5FC6791FC8E889B51C0E4B80B93AD721B
-:10757000DC85A92E39EEC215E972DC852BDD72DCC3
-:10758000851FE4CA7117AEF2C87117AE1E2BC75D16
-:1075900028F6AED5C57DD8A48BFB70972EEEC3FD23
-:1075A000BAB80FDB74711F1ED1C57DD8AD8BFBF04F
-:1075B000B42EEEC37E29BFB8E6B0547F69ED112921
-:1075C000BFACEE0DA9FEF2E071A97C45FD07527932
-:1075D00045C34752BEAAE90BA97E6FE33EBC2ADE33
-:1075E00003BF26DE031F13EF81DF8C11F7E1AF3FEE
-:1075F000FFE2B6C8F7F85FFEFC9BDBF03DBE41BC86
-:10760000838D15F7215C1E23EE4357FB6F1FF72177
-:1076100025F99FFF0E3FC7CECF3727C44FCAB1A76A
-:107620007CF777F8D716C9EF99E796C8EF9973EC0E
-:107630005C9FCFF3C9EF9AAF2F93DF3597D97CD9F1
-:1076400088873EEEC384786F8E1DF5A5789F1FC294
-:10765000F7A9B0363E8BEF53217D0EE33E407A1002
-:10766000E33E407A08E33E40FA7B8CFB00E94B188E
-:10767000F701D29731EE838A712302226E448D88FE
-:107680001B512BE246D489B811411137A25EC48D3B
-:10769000681071239A44DC8810C139E13F44E949FC
-:1076A0007F0BA5A7FCC7283DED6FA5F48CFF34A583
-:1076B00067FD1D94B6F93FA7B4B7712334B9FC3305
-:1076C000DA0D66EC9FCBB126A733EC033744CA69C9
-:1076D00091FDA20D28A7B1E245CC459AA6C48E170C
-:1076E000112E8F112FA2AB7DEC781169A3BFBF784B
-:1076F00011FF16CFE5F51F8D1731BF5A8E67B060A9
-:10770000CDF9E34594D98A56A35C6AF2F86FF1FC8F
-:10771000BCAAA77811DBEC8A58AF812E6877015D8F
-:1077200068BDEEE1BDFD738E8773713FD1997BD14A
-:1077300079E31CE8E52236BD795C83EBBEE73811BE
-:107740003DD155ABFF66398F5FF06FF1E78F5FD0AA
-:107750002D4E444FF105067D467AB2B771227A5A12
-:10776000177AA2E7ACEF394E444F7AB5277DFAC7B6
-:10777000E99CCE13E2CF1F8F231C17CEDA72901A2A
-:10778000BBBC34B555F10EBC60B68BFC27EDBBC459
-:10779000BD312F73BB52F93B75B437DBF7240C674F
-:1077A000F47EDDC5BCC09F78F15DD9B57F3F9EA753
-:1077B000DFEA64DEC4248A07EF36E6E03E6CA415F7
-:1077C000FD29158D1FBDFC3B806B6B36D27DB276DB
-:1077D000C0A185EC3E6F22F22D9EDD4EFB743CE392
-:1077E000FAA64FE47B66DDEF37609588F39BA946E8
-:1077F0003BED9B3AB7F27B9E4676F17D1347D37DF6
-:107800006A167413FFC84E5D21F0ECC414EBFBAC98
-:10781000643F2E3BFC447E88F1F3CA48BF419F423F
-:10782000D94F5367730EC777952CE06D41FB7B8969
-:1078300080975224FB6F3E5C547808CFE997F84A52
-:10784000E91E425A89ECCF61E2DD386EC7C2F7E526
-:10785000009FD226853DA0747F475ED67CD706DC8C
-:10786000E72C0FEAED6F968B7256CEE23CB8EF5DD7
-:10787000512F973B1CE23E879DD97B45B7D60BEF36
-:107880009B987C5EBA7942587F9783EEC32E3BBCAF
-:10789000D88CCCB2A4CB74B3B965BAC5E7CAF4D15D
-:1078A000D3CFE191E9A3A75FC258D9FFA5D14FBBC0
-:1078B0006FA832715F34C8EF91767B87DFB48DF0AB
-:1078C000D4D34F4FAF510E714FA28B5E45D6545259
-:1078D000F98467861A22F9D6CF874C7B48C1FFEE20
-:1078E0009F1C5C4BAD3C0E15F5563A07CD9425BC5C
-:1078F0005D3CCE078C2BCB3C341F70478FFEDD7870
-:10790000F66721F7EFB26F20BDA9F8B9E38BA07439
-:107910002BCADB08FEFB0BE4AFD27E3781795CB863
-:107920008F6AF05BDD4B543C1764EE2503F13CD0CD
-:1079300045E99DE2DD6FFB5046FBFE86D027A97826
-:107940008E76675EC74CF43F542D6545B87EFDC802
-:10795000C9DF5D6C12E90827F7CF6C2E3230EF6873
-:10796000FC1D1E635041BFABCB7BF872B4479B4DEF
-:107970006E7A47ECEA78F97A2A1F45EFA3330CB503
-:1079800023111FA84FEF6BDB9BDF752E8ED0C36DCD
-:107990004D770FC1FBC5F71BA2BFEB2D7568EFDB61
-:1079A000F8FD8E115D71064A1D63281EC19DD9D058
-:1079B0004F657127F15193CB0982FECF954E27FC7D
-:1079C0009E6C56DCE8AF9B66BCE107C300BF714705
-:1079D00055AEBFC4BDEED1A2FED3CC938EF88EBB04
-:1079E0009429387FC6BDC13C0124717529DDA7FBF0
-:1079F0009D73DA21E4D7946690279C0F67ED1EBC37
-:107A00002A3FA645BE2F9738C57700EF175E728CC8
-:107A1000913EBBE498AABF1F63C4FDFEB856F9FBB4
-:107A200004DDFE739D26774E968A72B7E52B23E11F
-:107A3000D5DEC13CEB006EFB92BE746EDBFE09230B
-:107A40003BB1FD2B6361B4FB25773BB8DFEB7E33A5
-:107A500023FD7D7FA99DDE393C5B5A7E01DA179FAD
-:107A6000FDC47741343F65849D96C0DF9F7B13D86A
-:107A70005894C35B154EEFDA8CA228EB9626779AC2
-:107A80001C6AF297511AE78B765F33D9C9EDA34987
-:107A9000A5B98A19E5679FC290AE6DEB00AFF3AC54
-:107AA000DB01B62E13F1A96AFA98EE61599B95A8ED
-:107AB000BFCBF384C3C9EF03AE0BACC5FB1737C311
-:107AC00024423D9561AECD8A063FC0B6905DFA80F6
-:107AD000C3CDDF0D58451C21B53603EF23B4354D1A
-:107AE000BE7203E0F900CC07E4EFFD260FE11DA80C
-:107AF000608CEE930A7F5DBF996CDBE608FB77AF85
-:107B0000A3E030CAED6107B71BFBF83C0AE2EDF9D0
-:107B1000FB5F9D08BFFD730BF1AFAFB037B57627A4
-:107B20001D9C3E254EEF016CCFCA9249F9787C4EE0
-:107B3000F7923EE837077A47B1AFB4753DC9C7E859
-:107B40007C22C96E089272F27ADD2EE9BE7780E659
-:107B50008D360F584861F85E5FD36F4AB31272805A
-:107B6000DC8FB6DA4378FF2CA90CC69D8CF13CACB7
-:107B70001C5E8B7A56F66B813CE6A371CFE8BD3F65
-:107B80003A5211BEA6F7347D796B22D747B7DEA5EE
-:107B9000523CD0AD6AAB0DFDA9595EF7240C4D9354
-:107BA000A4BAE95E4AFF323E0FE3737E9918B6032A
-:107BB00060928FFCDAB820DA7BA60C94A714A49705
-:107BC000EF4307A4C30F753C8BE682C7C6FAF0FBF0
-:107BD00053424F08BB669A58EFC6BD67E0EF284393
-:107BE00097B3C8F7457A3D0172FF27FCFD9EFBDF86
-:107BF00053294E68583F944EA3F58919871E403982
-:107C00009BF022E3C751423FB8E01FD2E792977C36
-:107C1000EB118DEFAA17F4FC66216B388F3FCD3640
-:107C2000EA10CCB7C875D629D67BA1476E2A1EB8F4
-:107C30001EE797264717DCE231FA22E8A86F1FF605
-:107C4000532AD6F077770EEA91978C783FACBD0037
-:107C5000F80D747912E70BD03BF193E095C8F72D3E
-:107C6000CD57D850BE6F0D4D72CD803689D6226269
-:107C70005E22F3923F270FA8837122D69350C07ED5
-:107C80005D2DCA72A6E03DAE42C9DFA3FD2E1E0CDB
-:107C900094F812E603C871E43D564D3EF5F2A8C9CA
-:107CA000EF7ADC60E1F91D7ACC21352A0DC4200B76
-:107CB000DBEA423DABD997EBC3F65C22ED33560BC2
-:107CC000BB68BD7D9A95D4C0FE645ACF57E3FA04D1
-:107CD000E35F9DC2681E68E3D0CB63D5E706168CD0
-:107CE000D81F54A91D748FAFEA73330BF6C171FB13
-:107CF00026E1B835BA8C1474D1D321DB29F69B82E6
-:107D00001EB1F1CC77E1FDD944AB976D243C27D16E
-:107D10003DE786509E15D7DBDB7478F602BF39D17C
-:107D2000F053ED31F013F1DB2630DFEF5A415EF313
-:107D30006FAACBE0EB057B353D827FFA7933B6A99C
-:107D4000FA803962BE687E5DFD3C19D1CCAE41BA85
-:107D50008F0BA90CCF5F7B9A2F9F88F156C5737A42
-:107D6000B5CFE9188CF2B943F5553BC9BE6835600B
-:107D7000DCDFF6A719CD67CFFE934E8A6FD4D2BB56
-:107D8000FBE99A1DA5D94FFA7A9AFDA4E95DED7E2B
-:107D9000F876A7CF8FFD2B4D209F30FEF52EBE2FFE
-:107DA000DAEBF0ADC3EFF130063C4A62B9A12CFE2C
-:107DB000FE5596FF58F21EAF93E706A013FD4E1630
-:107DC000E8FF414A773CB4FEA73813F9790BCC663B
-:107DD000D443FDF219EFAC92D1FDC97EC3990FD700
-:107DE000A77E79FCDE5F50ACDBDB84BED5D2BD8ED6
-:107DF000A2FB117F93CA0296BCEF8E37A28AF7B11D
-:107E0000B73BBDF7A1FC590BBD348E4C17F3A0FD59
-:107E100099A93628F86E3269A55BE1F7B059D73BCE
-:107E200026809739C35D80729289FB68ACDF1C3D68
-:107E30008ED6134E9364677A58384ED513D82FD800
-:107E40009907CD80779F195ADC2BEDDCC6A3209DC6
-:107E5000DA1C7308E9B64F156E8F27727AE9F703BB
-:107E60004878C44F15F9DBCC4CB525B1AEDFE13411
-:107E700058C98E8F679E06D44B2F3BB3C5B9A8A7B0
-:107E800006F3FFAE7658138776C9F19D13677954D0
-:107E9000A8E2BCB47338EE99409E0F23BE6D133B2D
-:107EA00007DF4AC4E818C0E5C66B94E2E268F46FE5
-:107EB0003249F4B7E13E3B520F3ACCB48F6C53E2F7
-:107EC0003C38CFDA962B1C4FC52AE206A9F2FE5F9A
-:107ED000E8234DBF763AB308FF7816A07D00B37A49
-:107EE000AC748F5DE08F7115C9AFB3373EB81DCF4D
-:107EF000A3747114F57116272FB6D3BD8B2D7B6D2E
-:107F0000B42FED2CE2E7F39DCD16D2BFB1E6691A8E
-:107F10002A83F3C40B04BA7520DDD24CD589A8F7A7
-:107F2000D2E6F3F9AFA7473B0E14F73B7F3005A32A
-:107F3000BD57D7D2F4F4BEC56897A567A453AA7DF0
-:107F4000AFB3AB51EF611B1314294EDF10E851ECB6
-:107F5000738C09F0FD9CEF8FAF7959D7BDF6BA3815
-:107F60004EBF4EDFF8848751AE40E0E8F704B473AB
-:107F70004DB19FD7E22769FD6CF15B8B31E467DD82
-:107F8000A2E9365C075298F7CA793829B798D84ED3
-:107F90006A972BDD77BDD73FB218DF276726F07BC6
-:107FA000B49F6C994AEF9953D93ADB60A043699129
-:107FB000C183FE80738BDE741A407E1665B6E4A31F
-:107FC0009C26987C990963C87545FB8D6525E660FC
-:107FD00008E8955C070A81E818B892E8B8D010D58F
-:107FE0003F9C9DC0F79D6F89F5243D7D40F19251E6
-:107FF00091F97E44574D8E60FE642C19DD150F13E8
-:10800000F87951429479D06E624DF85E42D347C9F7
-:1080100042CC347DA8C97132CE0FB4E38A403F49C7
-:10802000E77D5035B5EBF70C95E617BE403BD679AA
-:10803000E924D237306F6B48CE73B9FEB4A13E8BC2
-:10804000F05BB5EF7DBD3FBE637AFB671F3BF05D24
-:10805000CB5FD40E07EAAFD3B7FCC98171C0DEBED7
-:1080600085EF936FD4D9FF5709F90826144D41BA0B
-:108070002EF0FF3D3FD25E636BB8FF7979507EBF33
-:108080008AF7BF23FD80150DFAFB00011EA74CFCEB
-:108090003EA79E0FEB041F96EFDA66CE7463FFBE19
-:1080A00039D8FF69B1BF39DDE8A0F7141A3E8B76E5
-:1080B0008D34A3CDFF97668B78A7D762E27AD93B40
-:1080C00003DFE7F804DDF4781EDC174FF096DEC31B
-:1080D000DFAF2E84BED6805EF435F3384AFA712CB9
-:1080E0007DDB3D0DFDE84B3729B48FC3FAB7C03AAD
-:1080F000E15BB391DEF1E8C7B93020FB73F4F11A0C
-:10810000B5FDC032C1FF25F86BBC3951E23836F3FA
-:10811000F774CB74F645E7A19C781CFF9A0461675D
-:10812000E7B34B306EE79E43D909D1E26168E95964
-:1081300071DE8FF7FA313DED67944E4970F3785D4B
-:10814000CD476E46B9AA6CDA4DF111F705DFEB3376
-:108150001EAA14347F6144A12A10F6D87C618FEDE9
-:10816000615C6EC08EDE8CF27FF9E73A3B5A8CF38D
-:10817000064DEE0F2591DCDC80E31A8EDFD54FA291
-:108180008DEBEE04F9FD576FC7A58D471B9F565E1B
-:1081900021DE9FEBDB69723E45C8DD921DC51BFAEF
-:1081A0000229D6EF7D7F8088234771B63439D2CB40
-:1081B000C932C1B7B03C34DF41E3D2F806F29E2E9B
-:1081C000DE25A5A33FA327B9D0F3BFCDD43A00E75E
-:1081D000AB9EFF6D31CE7DB627F0738D256EEF34EB
-:1081E000F4AF8079B8C115613F9C566B0FFE14E760
-:1081F000D10E2EC791EB22194B2F9A689D5DE57029
-:10820000A725DA05DFC6E1FB454B00EB69FD9CF2D3
-:10821000D7CC1A48E78DB5B3060EA4771B946AE550
-:10822000A5F77FEC44FBB43D97917FA1CD21E37B83
-:1082300004179B319872FAAF545BBE7E0B75D08EDB
-:10824000168ADF7AEA2BE19FF8CA52186D9C6713F1
-:10825000B81DA8DD3FB951CCA31B9BF97BBB455B87
-:108260008BCDE4075823DFD77849714DCB84A6BE68
-:10827000869166E4B39E1F4B3D57D03BF06E7C6108
-:10828000B7135F97EADFB5897B4C0B847CCC74B95C
-:10829000859DE6A377C44BEA8C64DF2F7357D3FE2A
-:1082A00066851AFD3DD61897E1BCE3D18F6361A3C3
-:1082B000427A4F8FFFB21D6B37F465387E3EBEEEBB
-:1082C000E308F5233D23C6C95A2FE7EF32C5BAFDAF
-:1082D0005F995EED8C008000000000001F8B08009D
-:1082E00000000000000BB57C0D7854D5B5E83E7356
-:1082F000CEFC24334926FF21413C21111212E29089
-:1083000084000171F24BC4080301826075405184FE
-:1083100090207A5BEFABB79990682DFA7AA358CB8F
-:108320006DEDFD062BAD0A4880A08126E9041403FB
-:10833000040D820A96D68014B1053280B5587D8F1F
-:10834000B7D6DAFB64664E92426F5F87D69D7DCECC
-:108350003EFBACBDFED7DA6B9F65ECD94B720E636A
-:108360000FB7CB8CE53356FBACEC65A98C2D63CAFB
-:10837000E9BE0C46BF6BA9F85F67E59204C6EEC57F
-:108380003F5568DB57553278AE5CAE9985CFF56FB7
-:1083900090995982EB1EEF53C971D036498E461819
-:1083A000C71E379EEEB33066817FD746D33C8C25FF
-:1083B000E0FCFCD723B1A75260FEB38AFFBD08786A
-:1083C000EE2CC0E181799678F873F47EF8FF32C71D
-:1083D0008C2F2478DFFDEDF229730E5E5D6D32C0C7
-:1083E000F8A52F496C1D8CBFFF69DD78B12EFD3AD1
-:1083F0001EDAF0A3B9E91981710F7B9F0BE9C3DA8B
-:108400005456C0D87D023EF6EA7F05EE73F84DAEB5
-:1084100008C632ED117167B3A05BC0265D4B63AC3B
-:10842000CE1A99C3A2A03533C2233B64F46E02B8BE
-:10843000D644C08201CE355BA3BD1EC4E3EA68C644
-:1084400046C0B8F68D26B70DE6C4DFED8C9DAB6F48
-:108450009E9B9E0EEBAF7F7A6EBAC2D82CBB9DB1AD
-:1084600089408FB6E7685CB7E29A6487FE2A4BDFE3
-:108470008FEF5683F03899D363995C696286C07C2C
-:10848000FA7659B3F1CBBEA0751621FC56F86312EB
-:10849000C02FFF3DF8D5C4685B006EFDBC7FAADF2E
-:1084A0001002F74A85395B6C81F568E326DA0DB472
-:1084B0001EFDF37A7A30E6A5717ABAAC443A04D15B
-:1084C00017E15400AF3D1D56EF5A89F888E0F67465
-:1084D0008411DC1793D6CD3D93C7D8617C00E0AE04
-:1084E0001DF132F55F515C6E7B3C5EF48F728DC77F
-:1084F0006762199B323CDE6046C6607C2ECE0FE37D
-:10850000768539F3988CD75DB1C807D31BFAAA2CAE
-:1085100040AA3AFBA40A05DE33FDB9BEAA30E83F03
-:10852000629FCCFB9BFA8E5A1C8C35B02915A5F0A6
-:10853000FC63700FE7BB5E9B6F762D66C05735807E
-:10854000534B0CB4C7C6BC8DF256D35B5921454280
-:10855000CB984FCA057E7046FAAC39D4678530AEE9
-:1085600033CAFD1FB8BE55579B2EC938EE98C2E5D9
-:10857000A53B8EF0A000EC61F05C53B853B503BE90
-:108580009A622C8EC654BAEE098BC1BE535583AE87
-:108590006BF4C0E7108E2603734643DB75604C54C2
-:1085A0005FF6F078EBAA57AB14A0FFBEFA0C6AF5A1
-:1085B000F78B4CF674073C5F6460EE16DBE0FBAFB4
-:1085C00022BF109DD414A4736DB789E41C7F12F0F0
-:1085D000FD2AA1876A81405100CFAA63CC171E896A
-:1085E000E3CABF50B06D95D8E910BE6281BE3C3C75
-:1085F000DC37DAD6E27C4A309F703C152BA9554A0D
-:10860000D07B4B6D99217D39D19081EB6172B8633C
-:1086100013E0574E31ACDE01EB976F8616F0A1D810
-:108620001DF212689B4BA6CB4BA16D34B2852DD8A1
-:108630001AD8F2603C750879D2DA4B76D76F90EE93
-:1086400017DEEF2DB0929E1A6927F916EB6D941C78
-:108650003ED4439E2EE6D804D79A6417E37CDCC24E
-:10866000908F7F2FE671980D3B55E0D7F7EC0F12F6
-:10867000FF3AA20C8FA642FFA3E615150AF0AF231E
-:10868000C570251578F478F34ADECF325C190DFDFC
-:108690004F9A6B787F2A4C99CCD8C9E655159E6CB9
-:1086A0009C97EB31B6C59985EF510C12C9A9B2D789
-:1086B000E46D843F9B22393F3519812F6370BC4A9A
-:1086C000E39F6A28DE6C05FE578A9DEA6A1BC73560
-:1086D000F2C3FFB4D5F0285B0DAB118FD822BECF0B
-:1086E00088756B7460ADCEAC39A8175A9C5973234A
-:1086F00010AFEECF11AF793DBDD3510FB77EF0492A
-:10870000813B9BD30BE7C9EB612C12D673E1AD9B88
-:1087100036CA52803E97EC45E7515F4BA0A61F87B3
-:108720007549AA9DDD0372D7E864AA09D695C85E8B
-:10873000B2A3FD30207D4005B532AE5F3AA35C5F49
-:10874000E2736CA48FEC4CB5DDF515BE5FD3CFACF6
-:108750003766483DACD757A69CC765067C1093D2B8
-:10876000767C29EAF3DF9A1DB7A8088F933D0E7037
-:108770006C333085C5107B642870DFCAC21DEB5096
-:10878000DE1D2CC903F2856823E0E01707F6D02828
-:1087900064485B073C5FCAA09D8470DD4AEB929100
-:1087A0009F2630978C7AAB8079ADD8F677BC9584CC
-:1087B000F87A3E8CDDE782D6F22A737A83F4467E1D
-:1087C000B444F89F1563A436DCD83217F934FC1290
-:1087D000B3A31FD0FF0B9382F38360DC89D71DFB0B
-:1087E0000D0CE1FCB5D16B8F82BE3F53515F6681AA
-:1087F000F9FA059DB5799F37A999D1D0AF8A91082B
-:108800002FBF2EE2F6D8FF85C9FB722AE2C7B2DA83
-:108810001B2457E3A3F9B8BAB8E2B1D1F07C4B47B7
-:1088200038C3F74FEA0C3720FE376FC90D433ED8E7
-:1088300086B881F5C798ED8FE07C315700DE54BAD9
-:10884000EE24BC2AEA8428C06BE14C9BBA0EF0FEF1
-:10885000EBB09699C8F7FEAD06F632BC629BC93103
-:1088600007FBDB2EAB76D4B3BF4E6D09A7F56C3595
-:10887000D07AB685FBC7AD01B8D7652815089F62C9
-:10888000650AEA5FC550AC3E02D7A74573FDA8E96B
-:10889000E39A6895FACF4BF0FE5C1C57447253265E
-:1088A000DB48DEFAFDCC6B86F7C4CFEB95911EE179
-:1088B00073809590DF159FCC703E17121A5A9BD18A
-:1088C000AB929E75DA9600DDA70B3D3BFD644D250E
-:1088D0008BC48EE3D854986F9FCDC8705DB7B13EFE
-:1088E000D902FDDBAE32870FF9E7AA427E981DFE62
-:1088F00005FB7B65629E5F494C898271455FAA0AD0
-:10890000F257110BF5DBCA36947F81F6ADC4A2BBDA
-:108910008EFE5C24B64AE03ACCB3285AF861A3D85C
-:10892000A86BA4CF60D6046147555C7FF67FE1BA9F
-:10893000FA2B4C0E5CFF769BF3E3A9A8077B8D6CAA
-:10894000131B5E8E7E550F1A7D0C08C7D570E68D01
-:10895000253EB421FDC76D68F684C17AC7A5F3F939
-:1089600091DF506F8CFD455C2CEAED8868AE4FB40A
-:1089700056E32FE4237B14E723FBAD01F9FB5E7480
-:108980002A8DD3E409F90BE7D963F42E760D61172C
-:10899000812FBF877CB9DDC62A90CF9F1961598886
-:1089A000F2A4BD67B7E07B7DFB54C39A2E23AEFBD8
-:1089B0002FA0FF01EED2E4ABA660FBDD15C7E12DD1
-:1089C00093BF25BFFA62BB44FE7C423BD7D7C17C34
-:1089D000316268BE7801F17A3DBED0C7011A5FEC02
-:1089E000B81E5F74FF637CF18B68E1DF0ECB17DF8D
-:1089F00046E2FA1FEB2849647FC78F69137C30DC9D
-:108A0000FD2956AED7F4D7DB053E779B9AEFCC41D4
-:108A1000B9BFCBE040B906AAA7CC05FBB23B9C3F4F
-:108A2000C794D569D8DFAE703DB2BDDD4C7A64BB6A
-:108A3000CDED267B9D6461E82730C5DDF77DD47FD1
-:108A4000C916755D10DF3E2EF4408BD137E573F407
-:108A50007F0F70FA4EBE2B5736C1B8110F70B9CECA
-:108A60003F67DA28C33CD53145BE6818DF17CDED26
-:108A700062DD1918057C597BC644FAEDADCE23E5BD
-:108A80004E1BF9374EE4AF497B8E941767E378CEDF
-:108A900047DDA2D5FA53704D3164768E25017E5D97
-:108AA000C24E4C615C0FB9903F72027DE634523C7D
-:108AB000A6F1413563596827E6F639CA908DAA2A8E
-:108AC00042E95BED9B4971DFFCE3CEB20858D77CED
-:108AD00097EEBEA07FB58EFEE007FF01E564D5E608
-:108AE000DE4E1BF2ADCAED698B697516F77B56A792
-:108AF000A1FFAFC911FD004F2DBFCF78795D901D4B
-:108B00005763F83A9F752874DFD367F2DE0297FE49
-:108B100037E3CFB5087BF3AD90E3DCC7DE588CFCC0
-:108B20009BB7DCB90FF1BF284EA6EBFFC97C96348A
-:108B3000A48F4321FFABC5A8967C2E05C631C595F1
-:108B40006183FB7BE2C3F3F0FDD531EE6B4827A6D2
-:108B5000F8BBF1B94985B9792857B6094DB1687F95
-:108B600034B801AE8A4DB6001C1A5CE785FEA98EAA
-:108B700059720DF180CFA15E693B75D682CF6B74BF
-:108B80006FE9B8C4E91D447FA47780FED27DD8D7B1
-:108B9000F06011ADD6FFE7E9EF1B89F41896FE18D7
-:108BA000F747FE8FE83F2A6608FA833F958ED73550
-:108BB0007FAAC5047E7576A0AFD1BDDA5E44E31C02
-:108BC000265819FA4F9D1057A21CBAA3D1B9613B80
-:108BD000EDFC5DFDBF3F3B0A5C4036292686CB930A
-:108BE000C93F06FD8D093E89FCBE0920F0F7909F24
-:108BF0003592F49D43E0879D95A4B319DC05BF969B
-:108C000082FE9F2F16E56082B9D287FCBEC33A3D33
-:108C100005FDB75CEBB434E4A737331E3B8426E78D
-:108C2000CDE4E53B5F51037E8EA6D7F68969B5F7A3
-:108C300097C770FADF0E6A16FD3D740D83E1D0F41C
-:108C4000379205E1907CD5866B56D2C7ED7D80AF1B
-:108C5000DB110EC06B97C45A517F17199C7125E820
-:108C60008FC5FB14EED77D3D4A05BEA96C7FF73852
-:108C7000C25B69B1F930DFC21CC6F37D41F912BD98
-:108C80009FABF9259ADFAFF92D5A7C89FE0DDECF17
-:108C9000C7EB00BFDD0C00A2FDF159BC0DF0FEE7F3
-:108CA0002FAB994E21AF0AACA352AC6336EB25B87B
-:108CB000D8B7D7AE4D03FACC12F8A8EC86B8300777
-:108CC000EF337617E0E12E85C78B7739203E0CE233
-:108CD000A3D99343FBF89B9E1098E77AE3F5FA7FBC
-:108CE000AAC817FCB371A6D676831D3A0D0C70B0D6
-:108CF0009EC73485A3658F82F1803BD380FC5827C3
-:108D0000EC1A84C943DB2321AF8586BE1C07E0B77C
-:108D10006BCF3764FFF6EEF9E623F4E7A67CA130CB
-:108D2000333C5FF8457E14EA07E60A9DB7EE8FAD47
-:108D300056C6AF13FFD48AB5EFAFC78C18C267A170
-:108D4000F637E79F5F8FF37D7946E1BC2DDE5F6EDE
-:108D500072A7DB6DD8F2787FBFC4FD1DEDFE7E23C8
-:108D6000C00DD737C568717FAF42F919F89983E80C
-:108D70007C17C6FBB901BADE75AEE20B2567307D04
-:108D8000F0F7FF23DED7E2FCB744FCC0F69D30A924
-:108D900000D78CD64714F4A36724C9CC19F4DE3B62
-:108DA000542B7306C5FB6FC4E8FC907DAFAD9F05E7
-:108DB00076A4AE477684A1BCB66F3F9483FD5ED99E
-:108DC000611D828FF4F89DD1FE8882FC9F10CBE557
-:108DD000E67AEF2F1C077C722BD29D911F77B14052
-:108DE0002239D2D377EF9E9FC7F6650F8FEFE1E868
-:108DF000AFA7C36FCE1747215EAE470F3DDF76C2E8
-:108E00003A3DB03E1FACD303FED6DE7A3BF5DFAE73
-:108E10004FA2BEC6AF751DBF8C457F4DE3D3B25880
-:108E2000CE375376AF8F65B600BD347C5D1474AB1E
-:108E3000668EF9B3E0CF5D922382F48487F5261520
-:108E400004EC55F5B172F233347B552D671B51FF9D
-:108E50006AF60AD3C2A8CFF4F6697E7A9111D5AA30
-:108E6000DE2EC1028DC8BFD50B43AF57F4342B1192
-:108E7000D433109D2449E043F8D51A3C1F3217C162
-:108E8000ABA7A7069F1E2ECD9FAE1674837596E1E5
-:108E9000D2E7AA45B48E417655ACF746EDA93936EE
-:108EA00034CEBA72AEF4FD9C21F87538BED5DFD74A
-:108EB000F44039BE20975A0FFA1109B10944AFF2B4
-:108EC000AB26E6047BC14686B1CF82F3EFAF649256
-:108ED000BD7B54D8DFE1F8A6F6AA81B96303FC6331
-:108EE0006C7BCE8AFCB35B69B662DEF136DB9CC676
-:108EF00028C053E91F8BE7A15F57D76760989A2A6C
-:108F00006BBFB40FE3F6BAE3CC81FAB0B8BDAB04E3
-:108F1000F9ED6DA557A638FA4BC69E0BF20FDBDABA
-:108F20001BADE83FB5C5C914A7EF8FE6FCA8DD6F00
-:108F300089E5FCD776E6F22CE710F73F13F74B4FA5
-:108F4000E51AD148F6C74750BEA1FC6903ADBF542E
-:108F5000B25755A2FF718791FC7A885BFEF07DCCF9
-:108F600037B599B763AABEACED878FD881102DFFB6
-:108F7000E7B30633E60FE6488E97615CB9EAEFC2C5
-:108F80007EF9BC54DA8799F47F65F25FFD774B94E4
-:108F9000F7280776C17EF93DA95ECC3FEC9178DFDA
-:108FA000D3C1F3FECCEE899D05EFF9A03276C23A2B
-:108FB000E229AD7F4BEE3A261838289E7A6C17DFEF
-:108FC0003F7AAC4CA2FDA3327B0AF304F155F9D3EE
-:108FD00040CF3CE0C7F6C462E4DFAA0A997983F87F
-:108FE0007ABECBCABC41E3F7877178FC92D98BF982
-:108FF000124D5E670AFEAE5E181B327E0EE37EE205
-:1090000042D66C44F9AE13F0D415013CF0FC4C117F
-:10901000A7DEED4E09796F256641606856DC68B2BF
-:109020008FB3BFEC23B33A473E796C31BC87657090
-:10903000F9D0E4AC4CAE69223E48921C181FCF9781
-:10904000C0AB9451DF85CAD1ECC9A1FD394EBD7EBC
-:10905000089577BD1ED7E47C7E876CC4387A7E91F4
-:10906000E46043E803BD3FADD703930C8E7730AE89
-:109070009E7BD549FC35480F9CACF887F4C05B203B
-:109080005B93415E7FA4E9839BD84DA80FCAE42D72
-:10909000EB913FFAC1AE9987E00FCD2E68F176399A
-:1090A000C827F2033BCFF725CAAE829CC606E2ED85
-:1090B00001FD007E8363087FE657B16921FB490308
-:1090C000FA22C86F3016FCF37E4319F88BA65C8435
-:1090D0006F24F3E4919EA2FC1EB43ECAB3255DA2A8
-:1090E0003C4A1DC4F114CFB35F125CA8D7A498000A
-:1090F000DFEBFD092D4F3B42E409F4FC3090B79BB8
-:1091000067F4229F69FC506EE772513E4FA6FCB98E
-:109110009E3FB4F75D8F2F7C12F085F477F842C83C
-:10912000D38DF2C5218D1FD259FA8DF083C6071A4F
-:109130005FE8EDC5415DDE65387B71F23AF6E29D90
-:109140000C23E965BD9DD0ECC28138AE7FC7C7F264
-:109150007D8A9999F36DE8578C407D80FE9EB037EB
-:109160000379A30D9C0FDEE95BAA486837500FA472
-:1091700006E15DE44D35BEAB7D9A51FEB052E89FED
-:109180008B1D3C9F56572A7B2DF06749FB73EB796B
-:10919000DF48F9B622A54BB1C0BCB31D9203F3352D
-:1091A0004E917F9B75D5E455293F3FF47E7A95E03B
-:1091B0001B8C7370FC6CA7E4851074901EAABACA4D
-:1091C000EDBE5E1F5589FDF22ADD7EB9294ED0F530
-:1091D0006676F3BFD2EEC7C72570B919868EDAF36B
-:1091E0001A1D35FA4DC0B1283FFBBE36A911DC3F30
-:1091F00046FACDB8AAD03CA3E242FD962FCFE7FEB7
-:1092000027C574627C5DFB25937BFCF0F05FCF2F5C
-:10921000BD59F3C3855FAEBD7726C8780A3A863A52
-:10922000FBA1BDE7BAF6423CAFA7D3E4B8D0784281
-:10923000A387A64707E15BE8D9E1E8753D3DABE9C7
-:10924000B37FB59ED5E6D7EC80F65EBDFE1D2E3E03
-:10925000D3F4E9531B0D9417B94DC4C1B7893CEB46
-:109260008342CE970B7DDBFF178B01FDAC6D9DDC40
-:109270001F7198ED87D06F08E4F3385D9F8C601EF6
-:10928000DC2F674AAF85F62F8B81A4B87F99CCF786
-:109290002FB7283E17E96987C21A405EFE2AF216E8
-:1092A0004FEEF52C463DFDE4E93106DA47577CBD2B
-:1092B00018174FCA55683F28DAAC52BEF76287D9F3
-:1092C0008ECFF5EFFE5E9711E7F90B7360A8F67687
-:1092D0008779603F06F54299DC23635EBEDF0FBEEF
-:1092E000388C9FB6D05782F1CE6DACB711E3EA420D
-:1092F000A4E310F47B55675FF479FB920EEE27959B
-:1093000044F0BA9FE980467CEFF43613F985D7CB59
-:10931000DB177DC9C85F1A94AF6FE37A0606119F09
-:10932000DC68DEBE107D3DE0E39FE8F40E1B267F87
-:10933000BFCDC4F773FC478C0CFD5E762E6EC8BCA7
-:10934000CBF5F2F8BB3BC39D6A24EEBB71FF7C7783
-:1093500067B253CD197E7C4E9FBF18F395DBB6CC18
-:1093600055284E14F9CF41FB223AFCED9058931545
-:10937000F369ED8E528C3F86DBE728F63B69DE1BF6
-:10938000C51B63CD9CCEA27EE9762163DBCE863BF6
-:1093900091BFB79D4D76223CBB057F6AFCBEFBCCDE
-:1093A000E570DACF343955DC07F6475B1C2F13BF65
-:1093B000723E6F1931C68BFBADDB853C6C0BF71F22
-:1093C000CC8A0BDECFE0FB179DF59EAA33E9B4DF14
-:1093D0002D61BE51DB27F680BC505D4E0C237E32E2
-:1093E000B21686EF6D74B29F633B7D9A1A85F8BE04
-:1093F0001CA7ED47AA519467F8F64A816BFC60BC44
-:10940000EFA877513D496BFDC22A05607CB3DE4D64
-:109410006D5BFD726AF7D4AFA6FB6B0F453E8E768F
-:10942000BFCEB9A04A09D21B9FC5F3FC526ED6E944
-:1094300012E473F60D6318EF4C7FA24F463D71FBAB
-:1094400055584748DD887219F14CF9CBB4403F5567
-:109450005A12867C79FB55E8078D97E2A3391D9A4D
-:1094600094A65B0A485A881FC2E29D17E3E0FA0FF0
-:10947000ED2E7F5C3CF241F5BE0B8CFA97F1FA0EB3
-:10948000E96EF9028CCBF31551DE380FF3C6B9340F
-:10949000ED62C4DFC42E13ED7B6BF9DB5C31AFF3FF
-:1094A000ABD03C729EC8DBBEC9FA289F9C6F81C0BE
-:1094B000CA807071FA39A5F94912E6FBE24D0EAC8B
-:1094C000579898E6CAC37C6B573CA3FC695757C2B0
-:1094D0004815F0E054785ED7A9E575D9DFCFEB7673
-:1094E0007F1AE9217D057E0AEAA7EEA3910E1FED02
-:1094F000FF59C8FFDB810F627D4338AF1760F3E689
-:10950000511EFD760B5F07D89FF878CAFBF9F61D50
-:1095100086E77E7B99F17DC4DE93B43F5D62C84CE3
-:10952000EC0338F74963A3B07DF1D3C86C6A8F466A
-:109530009E47FC741AAC2ABEF7C37A56857567CE6F
-:10954000F76DB49F31FD7D9B82EDE1FA3EAA477B2A
-:10955000BFFE1CB547EAFDD41EADBF4AED3B701DF2
-:10956000F9E7103C8F6DEEE2087A6EC7A20813C2CD
-:10957000DB19C9B668EFC17A335FB8AF1593F9EF5D
-:10958000C57FBECE7213D83BB37BBC3481B113F11F
-:109590009FCF54A07F68C6A87FFF0BDCFFDD4F2E56
-:1095A000ACB3005CF38EDA5A7BA0FFE94F2EAEB36A
-:1095B000A19E3D140ECA0EF546FF41907496873663
-:1095C0003D9971053B19FAB1A2EFE99F590A245F51
-:1095D00050D297C580B5A6FCC43FD302785C6075B5
-:1095E000FF1BF64D9E976696DE847DE6C17A2EBF00
-:1095F00064A4F89E8D94E2B07E6599DD7D2C3EC812
-:109600007E3BA53FD2FE51815362D1714457DACFE0
-:1096100062F653B1C1F2B6CC5E760CE971473CDF1D
-:10962000BF9A384D7206D749E8C74D3CA396229D94
-:109630000ACE9537613BBB229AFAAE85939A509E2B
-:109640004B6DC33D5F42CF2F8837127F162B524898
-:109650007D887E5C1E3013FAC7FE03E1941798786C
-:10966000CCDD8875A36549A9B9B2D0798CFAD11B34
-:10967000711F6D62E587A5B1283F36C981E6A180DB
-:10968000F535C5C661FD231644E1BA9E2BC1FA9D8E
-:1096900089AAE440B41539BB5AF1F9224784A308DA
-:1096A000FDF1636A299A9CA3CA84C3F9306E46BA55
-:1096B000ECB0C044477D774CBD00FDA28C28CAE3C6
-:1096C0001629ABAF1CA67E84A341C5756CFC792D11
-:1096D000CD63267BBE6356C97F20FF14BBA228E75B
-:1096E000576A3B3537B82E0CD64D7017D9656F9831
-:1096F00084FCFD83523BF4778C9218CACF515FE60D
-:109700009FE97E77B81A0680EE30D94B71BE1D26D0
-:10971000C9BE96FAAE121CEF196354314F541EF7AE
-:1097200045C8FC334AA5296710FEECA80978AD624C
-:10973000E4A590FB3D8BAC64272ADFCF267FA8678A
-:10974000510AD98BCAF7A71563DB63E07E7AE5FB84
-:10975000951574DFC0E3DFCAC5DF718A3EC5BB95CE
-:109760008B5751BF4B4AFC777CDF95ECA85CCCA3B0
-:10977000CD4CFF7AAE12ECFFADCE24F9CF1579BCFB
-:109780002243E6FA6900FFA307F83E4465B6145287
-:1097900037372BFF54483DA86BDA1721FDB9A59741
-:1097A00042EA43E7557E1DD25F304FAA0A1E5F7A18
-:1097B000209FEC6BBEA85FD2F24B458285DEA9CF1D
-:1097C000A82A05B93C00ED03A01F8A7A45DE55E1C1
-:1097D000717506FC433D586AD3E577994AFBD91564
-:1097E000DD7CDFBA3CCE783AD83E54C84F707F411A
-:1097F000B7FEDC0346B293B9D132E5AB34F82A4662
-:10980000863EAFF95F1502CE1D0677530CE5C79C67
-:10981000BDE87F68F06BEFD7E0AE90EF29A5EDBF14
-:10982000EBC0AF87170025FF4D0FC78178118780E8
-:10983000BF41FE5937AF4B835FDC50765BF3CF2BD4
-:10984000414F4507EB299B1487F576C3E9296DDE67
-:10985000E1FC306DDE6576173DEFDCFAD9D1423997
-:10986000A89F7A2A3626B8FFDA67EB43EEC79FAA8D
-:109870008A0EEE6FFAAC0AEF4F57D4461BF0E34165
-:1098800026393CC89F3DAA82FBCF25C79C4DD89660
-:109890009D746399299B71C6D384EDD4F3DE1E3386
-:1098A000ACEB8E0C59C5B85DF33FF4F09A13781CFD
-:1098B00072F0AA6AC5FDD31D1ED58AFEFB8E275401
-:1098C0002BFA1F3B9CAC02E331679A6135FAF3CE69
-:1098D0002C5E677855E8E16FE2F9F35A7B5A717FA5
-:1098E000837A11EBC2D127A8FDDA4F75E007D1AF1B
-:1098F000CA1EEC571D54BC367CDFC127BCB6E07DC8
-:10990000C21BF5ABFE8C363A1EF96C4E887C96581D
-:10991000EEAE0A96EF32FB9290FB9FC6A904FF8C35
-:10992000A48743C6DDA13E12D2077F3103FD9146D5
-:1099300013A33A598F81D7C9EAF1F8A8C0A3C36627
-:1099400047378619E354AA6BD38F739470FCE9AF41
-:10995000A727F0B86823C80CB6F72470F8F475B1DF
-:10996000FA3EC47C0B713E983909F9DC61355C0123
-:109970005797391392EEA47AD93CC3A369D0AF4E5E
-:10998000C8E2FDA9869D581F7B774236EFDF6AC883
-:1099900033821FF02B36FE4EAC07AF0D13759D0FB3
-:1099A00024D27E9816DF2886532F2EC638738F91C7
-:1099B00061FEFE1913D8BDDCC0BEB9D5CCE352ABF5
-:1099C00089D76D3F957AF429D41B6A987B7A02F97E
-:1099D00051C52AE2EFBCDD42759D8FED2E4B44FA56
-:1099E000DF93C0F35C593BA726A17EF917BC7F56D5
-:1099F000C2C4E1DF8F75BE38CFF91D59E47F67DD42
-:109A00000CE89502F887F098AE87419840E72598D2
-:109A10003309F36C8DD1269AE79E04CE7F37DA0E98
-:109A2000AAFB8D32ACDE0EEDFD82FE0FE07B095FFE
-:109A3000FE51737063CEEE1F35773CEF237D6539A1
-:109A4000D78F7EACFF3B11B4AFC246FA69FFE5E3A6
-:109A50007BB21CE89F7E12CEF1B7D03BBAB14FC5A6
-:109A6000FA0DEF4D582F9191E8AE453C2C327B6FAB
-:109A700021FEB1AD8EC0F96FB41E78F07B21800459
-:109A8000FA544FE1F4D1DE0B38B5A03DF8589C03F1
-:109A9000D1E080F7FF00F9408367000E5D5DB89666
-:109AA00067AEFBA381F20C7512E83DE8EF3CC91CE0
-:109AB0001E98E7A2E6AF8BBC266E45E17BA61C5E36
-:109AC0005A628336BF6D258F737B95903CD7A4E394
-:109AD0008A7EBF83ECD654ED795D9E71AA886BA710
-:109AE000EAE2DA1713849D4966C9C1798035226E8E
-:109AF000B8DC333A0AFD4CD45132E0D5A4CA6C72BA
-:109B00004C40CE5B21EE674171BFC667E38FD9EF52
-:109B100047B8C71F63F7915DD7E61DC82F70BC5CBF
-:109B20003ECEF132A12FE3A7D3A06FEC3632AF1AAD
-:109B3000584F2107955DC6FFE078BBC98B75CB05F3
-:109B4000077E99E7834BE624035383F010A6863300
-:109B500035482F5A336242FAB2866F61CFF3C4FCA4
-:109B6000118EE49079F6C49477A37DCFB32D27FBB3
-:109B70001E357974C83CAC4709B1F3B028DABF9CF4
-:109B80000840FD0CF05A704C09B1E793E23CB86212
-:109B900036F9A4A2B3FFCD32CA41E199D0EB0786D2
-:109BA000A3CB70F863393F45FFEE1FC55FB4331494
-:109BB0007FB115A1F88B7785E22F7161289E46B899
-:109BC00043F192B27C5CC8FD9B56E786F46F7EBC85
-:109BD00030647C2A18A4E07EDAD33343C6DFD23C5B
-:109BE00037A43F76C3A290F199DEA521F7B35E5D5D
-:109BF0007143F41EDFB226649C9EDEB7B6FDAF90C3
-:109C000079357A7BE0DFBF82DEE6C4507AA70AFDB1
-:109C10001AEDE4F565FD46DBD312E8234C13A15E93
-:109C20008B6E7FF76BCC43788A55AA9FF3CC64B4D4
-:109C30000FFD82EC92500FA5C0148634AA5FA7FADC
-:109C4000BB1F1B0C21FBE28989DCBE2726F27CCDE1
-:109C5000CF4DFCDC520AF88F64870C2C102F031EAA
-:109C600022315EA678FAC7CF60BCDC14DD97A14232
-:109C70007C6CC6FE4D017DB9C8AC36F6013E26C8E7
-:109C80005C1F829E4C4B84F93F919E30723FC263B1
-:109C9000443F22C5C23C91B9643F287F1CCDE224D9
-:109CA000ACC78F0AE869F51A106BDF8A2C3A07F502
-:109CB0001E4282FEAF2586ECE8DD9A7E5A9E49FA66
-:109CC000E9B22DD40FBBFC401A5D3F71AF99F6FB92
-:109CD0004F883A446DFDE784DEFA53BD85DAF3F52B
-:109CE000F6103DB67CE3FA08F41F4F64707F51BB59
-:109CF0005E82789B88AD2CEC9AC58EF9AC7BC0381F
-:109D00004701BE5775F7452E62E43716E3BA6B3745
-:109D10005EB9F74DE8D719FC09DC3E7878BDCCC7B1
-:109D20008CFCCFEA6F5888FF343791C7E973C5FCC4
-:109D30000BA0B1039E1600FEA3B17D775A39F2271E
-:109D40005CA7F369B3BB19D59FCC71A7D23EE35191
-:109D5000E6F8701780F89D4495E09CC75CB45FFFFF
-:109D6000D1BDAB2270DCC07CDA3CC028E86F7C1C23
-:109D7000ED312660DC7F1BAF6F80F759F0BAEB9EA8
-:109D80009427D10E69EFFB88B92F7C88FBDDCC418D
-:109D9000F36AF3331613A29F762C5FF9692CBC6F1C
-:109DA000CD0103E513D6749829EEEA5FF1D7AD2F04
-:109DB000C2FDFB52FA6E42BBFCC98A6FC6203FDC73
-:109DC000BD01F410ACB130CAFD7062509C72E281EA
-:109DD0002B11781FECEBA617D1386E36537DEF2789
-:109DE0002B368F09F6471F4D2CAAC5E7D8E41B3B3D
-:109DF0006F58F27A6622D563097E7A58F0D39AD7E3
-:109E0000C6921FB52662809F787F13AFEFD0D6F140
-:109E1000A1E0C715AF7F5D107CCE7407F0913A8644
-:109E2000EF6BA920533B7B2EE7E0FD57147713C25D
-:109E3000D779F57424F677BEF737829FCDBB31789A
-:109E400051063D0581FD65EDDCE5C2F6D83CA43B3D
-:109E5000C85933CEBFE837AF5DF81DE2A763F3A65C
-:109E6000EFE3981B3C7FC9847D71083C807DA1F89D
-:109E7000A09F85F3731D428F2AB8839E86E7991CA5
-:109E80002AF1B3931DC27D97C62E03C3BA9548DC51
-:109E9000B409CAB345CA06CD08392D49A09F855ECD
-:109EA0007925F1E49D4DE4E787FA3DF96FAF08F1BC
-:109EB000775CF08FFC9D97DC8D9807BAAEDFE333BB
-:109EC0002C3145DDB8FF0381B0532A105B38F06BAD
-:109ED0004B14FB22420F77A21C61FD3FCE85F97A1D
-:109EE0005F383F670CA602F5F80F604DF8B02945C2
-:109EF000B4D2C50C0BE8C5BD897F78E669D09396CE
-:109F000074BE5EEC37E2DFDD9CDF06FCABB7C791C9
-:109F10009E62DFC2DB100F225FA1A7533EC8078BF2
-:109F20000D9233F1BC6FFFDF22314FBB35467D1FF1
-:109F3000E9E03F20D33E4D98D2678A1E222E7B1344
-:109F4000F59E89FB4D546FDEC6F38116D5C9300EE0
-:109F500008B3DB27049FB36B17FA6ED5FE4F469903
-:109F6000800E170C3D91D9307FCDAE1D91E8C6DF34
-:109F70006B747F8A7CB7F2C40705763ACFB671144A
-:109F80009D03F08DA6BA83F10AF328B983E1A8DB1B
-:109F9000904BC6B8760325E3D9F8F6BC87501FD599
-:109FA000F9F83A716E2CFCCB6C63D4BFD8D6188309
-:109FB000F3D5FDB62319E567733C8F135FBF3A8E67
-:109FC0003FAF3005C77F99182DF8D96BC03863B300
-:109FD000884F2E5E35D038EDFDE3DB8A643BF043DD
-:109FE000B6AF792FC543ED6615E91AF60AE378682E
-:109FF0000F2339AFEB9CC1309FDF1FCD1C12DCDF7C
-:10A000001AEEFF039D33EB30AB981F0DB337B31837
-:10A01000987FABD80FCD048EC2F34ADA75ED7D611F
-:10A02000ED3FC55802F981F2B4614A33BBCD168CBD
-:10A03000E708C2733CF2533CBEC767C0FC88FF16FA
-:10A04000C65E26B80270327AAF066726F9735B4D9A
-:10A05000FEB3787E05E0B223FD33198793B58F55A3
-:10A0600031BE0FB33B691D6176D5E19106C35597AB
-:10A07000C3BC68BF7FBC960DC82BCA6F5D78A06F4C
-:10A080000119D83A9A09F9B63F5B3A2DB80F8A649C
-:10A0900072E0F9711B629E6D1A49718347C63816CA
-:10A0A000DA88185CA7CACF3B636A2897E301F7C533
-:10A0B000AD167E7F603CF0B70DFB363ECE1165B726
-:10A0C000CE94484E28AF572BE4FD31C977F67690F1
-:10A0D000D3BFF8F6E6A8004BCDBB7B884F571ADA02
-:10A0E0005F1C0FF7375ADCF94980CFB74E1AE81CCE
-:10A0F000E99F5E0BF35662FCB87B63827308F9D06C
-:10A10000CFFFC3E36B9F4F41FAEF9654CC9BF61BF6
-:10A11000FDA310DEDAF6CF4D548FD0768AEA938E07
-:10A1200024B99DF89EC96D0DB46F3C8535D3BE71C1
-:10A1300096387FDD92C4F5C7E563635E6E08C2FFA3
-:10A140008349DC0F637EF7CD2837ED423E3BD12FAC
-:10A15000817697F08F7675DD9DA606E5FD1AD8DE2F
-:10A1600014C4F75AF636B5DAF57E2F3FCF98F5913D
-:10A17000E53E6710FFB993B89FE716EFF327B917CD
-:10A1800024A1DC769D3645AA785EA56514DA911681
-:10A19000F09FEC43E065406E757254A7F84D38BEF1
-:10A1A000EE1C3F770A746EC2FAFFCD1FB58D5B02BD
-:10A1B000D77701AEB1DED373C24C758FBB8CAE14B2
-:10A1C0001CDFF0E15739A8B72A1069F0BFAF3A5643
-:10A1D000DE8C7803BE2F0E47F9DACE488F69F299EC
-:10A1E0008DF209CF6723DFE7633F93F4F056532FD7
-:10A1F0003FF7B98B9FFB04BE273900BEB7A39F90E2
-:10A200006D0739A0E7C7927C6FED35D0F9540FE8A0
-:10A21000F15BA85F5C85FDADBDA576926FCCC3E711
-:10A22000A29CFAF6D23C2D108320E924E60AF61F00
-:10A23000DB1323898F35FD783091EBFF960C350ABF
-:10A24000EBFFADB21C2217417690F7859DECDD50F7
-:10A25000FCEC0BD3D0DE09BB20FC27769CEBF94746
-:10A2600085AD5AF34EE1EC2DB0CE3587E5817A6E9F
-:10A27000F4577D824FF60AFF15ED849AC7EB67F01D
-:10A28000FAC40DBCCEB5C0B9BA04CB38265734EFEA
-:10A29000C3B6D0D55282678EA72DECDDC7CF1EF393
-:10A2A000F3E3AD7BEFC8C27DEAFE136686FB24AD07
-:10A2B0007FF3FFE175C0C3773B01FF43D825580EFC
-:10A2C000F11F58EA149634F87EBFA4E98FF9952857
-:10A2D0006F175BE5401FEC612D3038F67F9D54F51C
-:10A2E000AC07004B1BE17C1D59A230D94D6DFF918D
-:10A2F000BF25A02DD8758CFB4DAD266716F24FEB10
-:10A30000E8D0F3FA5AFB62123FE79C6F6643E625FA
-:10A310000F09BB37C6C39E413EAA6D95ED5EA0FBFB
-:10A320008556D96902FFE6ACD39D806765CE31CFF3
-:10A3300082A968E745DCA87D4F6519FA2760A71E4A
-:10A340007C61501EDF807CF450BBC47E066B5EFED9
-:10A35000D2D0FB0A35629E87DB36EE4F013AAE78EB
-:10A3600025745C8DA813ABD1F92F8792447C98C6D5
-:10A37000D2D02F01FE21BD605458B719F8F5C16441
-:10A380007707C61B9BC5770C407F921C7608BEDC06
-:10A390002AEA04FC5B25DAD7CB7CD52B1BE0F942FB
-:10A3A000C52BA39D62D0E23EC164A7BB1CF10BEBA1
-:10A3B0003E86FB35CB851E5CAEF9655EBE9F01E631
-:10A3C00096FCB229CCDB1889EB7E5572F854FC8ED2
-:10A3D000C8A03A5C5A779D5877CD8623FB318C5BB9
-:10A3E000D5123AAE4EACBB4EB76E6D5FFBCF49BADD
-:10A3F00073C837B86FF16723F7133E10F368F7CDD2
-:10A4000023B83EAC05F0906E355ED9EBE57E9D0D30
-:10A41000BFC373BF80F77E41EF3AE633A5C0B8559E
-:10A420002FF075B26743EB3F1F6C7DC484F1959E9E
-:10A430002F966F31923F0A8833A1BFA8E78B156230
-:10A44000DD2B74EBAE754B3AB8B89F3C18AE960551
-:10A4500048D7555B8C0CEB11F5702D6B59528E7CE7
-:10A4600036985F395D5688F90270AEA6737C370A5C
-:10A47000E7A811822FC7B17144978AD81BA28BDE3F
-:10A480008FDDBE7F9C15E5FB72F7688ADF35BAEB7E
-:10A490009F2F177EF08C0D8CDA0B6D25D6F118A747
-:10A4A000F4181C924AF156E478C0475E87CC2AA182
-:10A4B000DFDF9EB6DE0378CF3D9C5F85F17CDE61F9
-:10A4C000039D77DBD99D4FFBC07907D263D3281F4B
-:10A4D000EDA0EFCDC03C643FFB7B72D7E3B980FEBB
-:10A4E0009ED27C9C57827168E773851D68E8C9B568
-:10A4F000069FEF2E18C1E3F5A7923EFB31FAE13338
-:10A50000B61BE97CC30CA3FF3DAC9FDAD9ADD0BE2E
-:10A5100075CDE1A56BC390AEAF49B46FBDBF774DAC
-:10A52000DC62E4AB76A31DF7A1FBDBFF6D2FDEF74A
-:10A530006C91E87B12751D65595BA19FBB31CF11F2
-:10A540007CDE2B375A25F8D8082BC5C3336E3292E0
-:10A550005D3C9F6CFD25FA372B9C1B498ECFEFD9B4
-:10A5600069A2FAB9AD1243D3BF3F69DF1B888FF3ED
-:10A570006F1E31A1935DD27AC4D4F777ECFD052F1D
-:10A5800004FE1407379B304E59B551EBF799904EA6
-:10A590002EE1FFD4BE728AFA2BDA24D2332B5E92DC
-:10A5A000E93CFBBE8EB74CC8C7B55B2496981A74BD
-:10A5B0007F8314F21D84A58CF3C152A1675632EF3C
-:10A5C00053C9306E6533AF23604F87D6E5AEDC32BA
-:10A5D00087BEDBB4AC79687DF3B0E0EB87301EBC9E
-:10A5E00015BF83143AEE61EDBB5C3A7E7E5CE3E717
-:10A5F0004C9689FCFC55911A950DD7BF3AB2E2E60C
-:10A60000A1CEB1F7083BACD9C1CB3E03D911FDB8FF
-:10A610008B6D5708DEBA9ECB26B483E5ED9708EF25
-:10A6200095ED5D54C7711773D7209EEE6AB7DA5166
-:10A630008E2BFBB85E9AD96EF67A25BCDFD284F4F5
-:10A64000ECEFE4758B9E3D12F92F9ABE7A48E0EF4D
-:10A650002181BF874041A7E4A21FCBE3DE873336C9
-:10A66000EE8F81FBB5E27ACD817D91E8EFCD6497E5
-:10A67000EE457AC07B18BE87BD148AE73B1987E395
-:10A68000CE2DBCDE596FAFFA4764CDA6FC23C49D26
-:10A69000084FCD96503CD7EAE2ED7523B87DDEA495
-:10A6A000C373A59F59B3110E5576786974AF82EFC5
-:10A6B000EDCE9128BFDAADA6450DB5FFA8B5EF09DF
-:10A6C000BF59EBCF16E7AB5BECCDB6E038D894CCF6
-:10A6D000EDFF8A29B207E934103FA4EFCB510D8179
-:10A6E000F801E286DF8C88E771041674BC3B526681
-:10A6F000717181F8E18749EB2B73A15FB785CBF9C5
-:10A70000C5C9301F7EDF4B61E45FD66D31D339C0E0
-:10A710003AA03BC509EDFC1C83AB5D2A437A83FF5D
-:10A72000FDEE888978AE8619E360DD73DA389FCF55
-:10A7300029BD447C72209DAFF7B2A2260EE58F6B37
-:10A740007E389EC35283CF3F805CE2F8DA765E0F9C
-:10A75000D4BAF7EB51A9A8D73AFE3A6A09B45746DA
-:10A76000F0F56B7E9E1FFCBCD1DCCF3986FEE78303
-:10A770009ADCD8F93EDA83C2CE30A989F8BBD6D8A4
-:10A78000F2760CFA4D5BF9BE3DDB6DC46F9CB18671
-:10A790000F5E6F8A81755F7C5DA27A347CFE09E072
-:10A7A000B38B4B5B4EA31FFDD5560BF98F0F828FDA
-:10A7B000383D77B03C6A72AB7D77AA81AD257F7258
-:10A7C0002D6BA27695E0E38B6D8D26CA9B79839ED7
-:10A7D0001F3DD8EF58A5E33B537228BF357C104E80
-:10A7E000FE5FFF01D98EFB2780A7FF4E0EC687F0C4
-:10A7F0002F5AF786113DFB8FD8C85EFC49F0D979F6
-:10A8000091376E982CD3FA0D53789BD5F9D668A45E
-:10A810001FE21BEBDE3777BE358E9FA7F612DE57A1
-:10A82000BE8A49F120385BAC94DBD3FA0D1F2CA211
-:10A83000EFF0D4ED19806B8C292E00D770FC2F49D6
-:10A840003C1E3448A1F160DD6ED9155CEF05EBB913
-:10A850000FF54F929003A6F813D02F1999AC92FDE3
-:10A860006A68E7F43474F016DEBF80E73B8CF4FED0
-:10A8700041F78B3D3578FFAB542BDF4FBEEAA9C4BF
-:10A88000FE7747CB544FF9DD0F568C0DD69B0CE16C
-:10A89000047AD619FD0914371E31107C75472E270E
-:10A8A000A4DB501F6D2CB567A3DEE1FA6EFF68EBE9
-:10A8B00072E4630FBE373130CF6BC2DE325C6F1291
-:10A8C0007A152FF079C57AD7B2B9223EE67C942D5D
-:10A8D000FC3D882B26264F1C1C57DCA83F09F6E0C0
-:10A8E000E86209EB89140FC6B53B8F737DD0D0F1B8
-:10A8F000D0A7C8E7759F98A9BEEABB9D0F8DA53A62
-:10A900005BB7FB56F42BBEEA7CF856CAF3496B09D9
-:10A910002E0FC29784FECB8709580FBAAAE3C3044F
-:10A92000B2AFBB26AEF744A09F927B275E07BF81E4
-:10A93000F80FFC17E2BF9D3DF99ABF62C579571D1C
-:10A94000505C889F5507F20F55A21F71B8381FD56C
-:10A95000B874389FFC953CF4576C01FF455B4F651C
-:10A9600032AF77E9EF0AA33C81C44673FE61E92167
-:10A97000FC53D3FA0ED9F59A3639A46E507BCE9D8E
-:10A98000ACF07D7E8D7F5A2427F1C776DED6B4EDFC
-:10A99000A4F5AD34B610BD1BB618F9FDADBCD5EAB3
-:10A9A000AA3D2CC683F8388497800E334D5EFA6E2C
-:10A9B000C5C154EEBFEBE9F15932CF631C3CE1BE97
-:10A9C00019F9E560917BAC7D08FBE061C53C3E95E3
-:10A9D00004BE5BF97925FDB853C93C8E8F8C0D3DC3
-:10A9E0003F3A605F9239FFCC340DFD3DBD9F69F267
-:10A9F000C4D83306E08BA39546FB3AE1B78F08FA3B
-:10AA00005E42D55D46F20F8E32FB3B5867384BD322
-:10AA1000AF93B95DD5F2DDAE0D2ADFD7197CAE91CB
-:10AA2000F4E47C6D3EFD7969E1D7CCD7F935EB359F
-:10AA3000FD37868D41FDD722CEB9ADC90CF306E7AF
-:10AA4000A3F4ED7EB18F81E775B06DC8FC98F23646
-:10AA500007BB4EBC41756627C2D8689E97A3FCF51C
-:10AA6000AA61F2D70D03F2382F84BF347A5C10DF6D
-:10AA700055D1D3E30D81776D9F2D5CECB39D56DCF2
-:10AA80006F24535DD67913FF8E9A9FE2AB864CEE0E
-:10AA90001F5D2893685F1CE01C650ED2EB1746F023
-:10AAA000B8EABB0B24CA9B76E1788C9F5A24AAABE8
-:10AAB0005EE5EB35211F8D695DF224C9AB871D630F
-:10AAC00041DFA9986DE17671806EDABA07EC568C99
-:10AAD00087EBE1386A713CDAC159C2EEE9CF218DCA
-:10AAE00065BDE51857563B2507EEDBEBE93D77E101
-:10AAF0008477E2FF013A9F4B761F21FDD67B7901D7
-:10AB0000E63F0F667E3E0AED65ED307CFB3BC1B74C
-:10AB1000DAF7591C63D546FC3EC98F12DD9F207EB3
-:10AB2000FB0DDF468E63F87CDF7FAF91902E8CE8C3
-:10AB3000319C9C9C12F39D4A16DF258CE3FB24CBB1
-:10AB4000B18FF26AF48EA4FC42F68DED4B35EC7EAB
-:10AB50003707F5D6C5AE0339A6203A9E5F03F28EBD
-:10AB6000F6A3635F826A0BE63303F1972469FCA6C0
-:10AB700008BB18CA77E791EFB2B1FD30321DF5EE90
-:10AB8000F6A391B7E07CBB783BC09FED328D837814
-:10AB900067CCFC8860F89E24F82EB4F07918EB1B83
-:10ABA00053353EF87EE3707C6B4CE1F584217CAB41
-:10ABB000ADB705BF8783FE7DA799BE8783F9E6E819
-:10ABC00020B9484DE1F230497CFF660AF3D0F70026
-:10ABD0002789EFE04C51984F89C17D2E9FCCF765B6
-:10ABE000F9798602C1BF93145F17D6394C11FB3235
-:10ABF00085AC97C64D677E6A9DCC4EE7148A9983D3
-:10AC0000DAC916DF9D9876C96E69A1FA3F5F821294
-:10AC10007DD622CE430C41B7C0FA15FAEE0DF1A550
-:10AC20008CE76186FE6E4A650A9773FA3807D2F799
-:10AC300002A3FC147EDF0C5F325561155877749BBC
-:10AC4000C22CE100EFF6B70D24BF9D7DAA17EB40A3
-:10AC50001DB1E2B92F18D5BB4E7272F944D382757B
-:10AC600012DA7AF5782884F9303F364981C892F0B3
-:10AC7000E8A3F7DDCEF8398D22A6D207566EC78F2E
-:10AC800027935EF7539C54027112EA7583C543F80B
-:10AC900028C3E4CA44BEBF1109F314364BEC38EEA6
-:10ACA00057A4F1F56AF3170223E0B9BD32B15E4C47
-:10ACB000811E8FE1FB1E9154385C6AE7DF094AA0D0
-:10ACC000EF04DD285EFB13F8772123EFF75FFC7EAE
-:10ACD0007E60FFC781DF0D8A0C7C8FD281E74C300C
-:10ACE0007FE753CE07FBCD77A72CAD4E9918A897D9
-:10ACF000636EA6A25FA1AF9743F49D0B3ADFACD57C
-:10AD00007BBCEA9DABE2B9B98571163A4F9B6B19D2
-:10AD10009587762B23D15D9D42751F5B6EA14914EB
-:10AD2000EF44574480CFADCC3919F11CA8D7E3DFED
-:10AD30004F1A38CF94C0E8FC9FD5CCEB199F01B9CE
-:10AD4000C0EF178154A958D7C29E28A1FAC7A7A25D
-:10AD50002D0E3C87604678AD01781B2DA2EE47573B
-:10AD600077D96833D0F7381B59389DE79E15E6FE32
-:10AD70001EAEFFB188623A2F9DB56D5A12F983B0AD
-:10AD8000DE69DA7A0D83EB10B1FE0F9FD3D7FF692E
-:10AD9000EBC2E3EBF85EBBC097B64EBB76DEC7A94D
-:10ADA000849CF7D1D6FF4C385FA71177E2D3E859DE
-:10ADB00015F5837E7D1A3FFC3FDDFB356D605C0041
-:10ADC00000000000000000001F8B080000000000D1
-:10ADD000000B7B2ACBC0F0A31E818565181826F1D5
-:10ADE000A18AD112CFE066607804C42C3C0C0C859B
-:10ADF000407B23807424101F01E2A340ACC2CBC06F
-:10AE0000100BC471403C07C89F0BC4A5409C05753E
-:10AE1000632B0B03433B107702713710EB30333059
-:10AE2000E832136F7FBE0803C31309045F51126831
-:10AE3000A734FDFC3FD8F00A7DFADA276DC0C0B018
-:10AE4000D502C15703B2B759A0AAD96E81DF8C1DB4
-:10AE500068F23BD1F8BBF0E83FAB87CAB7D540E515
-:10AE60004B693130782285899D067EB7A0E30AA020
-:10AE7000DE4A200600FB72DB43680300000000008E
-:10AE800000000000000000001F8B08000000000010
-:10AE9000000BE57D0B7854D5B5F03E731EF3C8CC9E
-:10AEA0006412420818C2092FA30D382121058AED2A
-:10AEB000400091A206B50A1575C22309794DC0C795
-:10AEC0008FB56D0682111034582C51A39D2028781F
-:10AED000830E3448908003581A7A5183D7FA687BDE
-:10AEE000BD4129200412F185DEB6FE7BADBD4FE6E3
-:10AEF0009C9319E0DEDBFFBFFDEF1FBFF6B0CFD99B
-:10AF00008FB5D76BAFB5F6DA7B648B8B484308F906
-:10AF100016FE7E40C8748910D23FFA74BE4E549219
-:10AF200048485D0E2DA710923E9C848840C8E46A74
-:10AF30005ACE23E4D13B49C89A49C8FE2316FCBE29
-:10AF4000CACFCAB45DD8720DFD3E82BD7F328BB6CA
-:10AF5000A3EF9FBC2062BBE04C12DA4CCB4984F6D5
-:10AF6000368CD021FCF89CECADB78FA2F51BEFB46A
-:10AF700010AB4AC8137418329E1017F1D9096DBA74
-:10AF80006A38EBEFF19996E745013E46D2E6D3F2F7
-:10AF9000EA29C5F9AB69698DCCE06A9853FC7C90CD
-:10AFA000F6EFB10CC379D07A4F3A69BDC7DE2F21D5
-:10AFB000AB69BB0D732D427136ADD7A4CC0E65477E
-:10AFC000E7AF3DE71289B70B5A2DE3E0E9E3CF88FD
-:10AFD00002CF5F4CB4E0386BAB193E683DC592467A
-:10AFE000484BC7019B9FF6B7B6A2E5E834FAFD913E
-:10AFF000E1162FC52079A4E380FD4A3A7E30CFE2E6
-:10B000001D416BA74B11C1E38C8E379E50C0C7D238
-:10B010007ADE1D36D5D9B73EED7712CC7B0DC5BB98
-:10B0200098196D3706E0A4EDD6529285E9B8BF9421
-:10B03000BD8761DC5FDE902C0449B4DEF50024D4CA
-:10B040009B6B21115A8F483D3642C7593DF16DDB4C
-:10B05000085A7F75A1052641D67AB5EF5E3B81FE81
-:10B06000A68E3C3C1CE87A3DFD0EF3C87E7C36CCB7
-:10B07000FBB1290A01FCFF52A0F5288A1B8A941F04
-:10B08000027CAE6AE281F7F4E98B85D756C18670FF
-:10B0900090351B08C9270002FEADF685560E05FE49
-:10B0A000CA235E28A77B697B67DFF69D8215E9D2FC
-:10B0B00020070702FEE2D16F38C7E7EAAC2576A089
-:10B0C0000721F56985A308590F78824125BF3ACB3E
-:10B0D00015ADBF5260F85927139F40E79790A7849A
-:10B0E00096513C5BB23D7360BE4EBF42AEA3E55588
-:10B0F0004270A0087419A590CD2AF2857D042DAF69
-:10B10000BD2AD90BFC572784D324F87E03FD4EBB00
-:10B110003C5038660EF067A357417EA6FC7318F0CA
-:10B12000BDD69F4C56ABF8BD03DB3B877BAC880993
-:10B130000A0FC54B3FCA4B80D79C9BEAAE1F06F453
-:10B14000196BF10085560B93D4F9203F49360F8CCB
-:10B150002F8FBD19E927F74F16888EDE3F077A53E8
-:10B160003C3DAA16FE1C9E4FE77D943482D65F9329
-:10B17000F34A03D0E999FB6D48BF67C6762C06B940
-:10B180007AF242EEFB7E944BC5BB99F6F36CCE8906
-:10B190004C42077C7CFA474980BFC1C3EBEF216E6C
-:10B1A000FA9CD953434653F8487DE1824CE413E1BD
-:10B1B000168AD7C14B15A2DA182DBF25F09DF8C20B
-:10B1C000D9ACECA4F319CCE9DCD2F1B6AD08FA9B0A
-:10B1D0004B2223DDF8DE969A1CD53383F348249561
-:10B1E000F6FFE4C24328E7CF5C9DEA65729E86FCC9
-:10B1F00092C1FB4987FA54BFA4D94830813E07B7B2
-:10B20000F7DC0C700DCE3A3117E0DCFFC62101E807
-:10B21000F6ECE85415F45192BF837452BA0FCE7E07
-:10B22000F741A8E77286D20AB3B1FE5FB19D09FE6D
-:10B2300066D5B709F0B64DA83E0CF409E658BC8CAB
-:10B24000DE4C0FAEB93735047A64B0E34FB3C4A116
-:10B25000C80784A452F83C04E5A44E88D88641BBB4
-:10B260000758BB212424009E076705178B6EA8EFA3
-:10B27000170A5D7DC76D018D08F241391DF875BB58
-:10B2800042CA0A63C8C16B5C9EEB04321BF9994841
-:10B290007F03BE1992C4F8462B3F0BF0D071B7BFA5
-:10B2A0009EFCC36C0ACFAF960ECD11293C8F42BBDA
-:10B2B0001872B396CB81A39D04058AD7FDBFFB9D71
-:10B2C0001DF0B6DD424AA1FEA4ACB0AD93D315E8A3
-:10B2D000B190B0FE1BB337DA505F0859C8770BC77F
-:10B2E000293EFB6890BFE5829FB64FF330BDECF27C
-:10B2F0002A21D0CBAEB4A060A1F0A8D9C4B33193B9
-:10B300007517A4F89B07FF00469758FD356B9342CD
-:10B31000ABE9F779D954D0006F1457163AEE02C250
-:10B32000E639CF5BB718E84748A105F0B9DAC3E8BA
-:10B33000D308E3D0A934A6B37ED6DE4742CB818FB3
-:10B340003CACFD706842E9363CEF95FF25D07ED3DA
-:10B35000793B907B68979016B259683BB5DA4210FA
-:10B360003E29725800BA8F4A55019EC634EFBFCCB1
-:10B3700004F8674BDE8DF4F3708083F6D3586DF1DB
-:10B38000A1BEC8539A404FAFF6313DAFE12B938F2A
-:10B390009BEE8D0874EE2493EA49C4932F62F74024
-:10B3A000399BC19399C7E6D50BFF2825B49C364E2F
-:10B3B000B74508D4D3F050CCFB2BE6F370A68556E6
-:10B3C0004A00771E839BAECB084F7AB6D2047290A8
-:10B3D0009EC6FA53297E34BC035C0E0DAE3C5A1F48
-:10B3E000F4B0576902567070F88AB3193CFB8FBCF1
-:10B3F000DD2EB0FE50AE1C1C5E079F3F017853B996
-:10B400005EA7FD35CB1141A4F5436389BA918DA6A2
-:10B410004AF9D1EF8F57533CD082938F43D65B517B
-:10B420001EE8ABE0B7940FE6D7D37256543E46AC55
-:10B43000B41AE4C5C9E74DEA991C51B68940BB4C22
-:10B44000C2CA1628D379146719E58C7875650A87FE
-:10B450000BF89DEA9F65E315C63F57313B86105DAB
-:10B460003DE0F3B1EA736BF0BB82EB7AC64F150394
-:10B470007C83AB53278BA04FDA9FBAD9027C752F00
-:10B48000B18889C8CF42AFFEA2E3ED5812B1C32400
-:10B490001DED85C980B78CEAE4C90AE0B1DD8F658E
-:10B4A000477BB50F9FB0348D216410D18D9309FA7D
-:10B4B000D553DE4CF14AAA9530E8EBB17A38E9F77A
-:10B4C0008CD7EB6701BD1E5E7C6820C86FAAA9FD02
-:10B4D00068CB5094D3C1AFD35A38FE899F41FD55F4
-:10B4E0005C9F3800E231F87C1D9E839D54CF523D15
-:10B4F0009D4111AC8C89EA8BD557BD9BE37772FED9
-:10B5000049C667049E66BDA2AB7F15AF1F142E5AB5
-:10B51000EF04D6D3E0317F3F2758504FB9C0CEA4B7
-:10B52000F87D8C78E6E0BAECB5E0BA98C0DF87BD6C
-:10B530000726233DC3C42B6482BEFD9B55CF073F26
-:10B540008197A06FA530CA8992E140FB90CA710231
-:10B55000AC7B8D527529BC0FA73B08E88503530FC0
-:10B560000980CFF456FF109043CDCE9DEC0DA7C1BE
-:10B57000FB470EFBAF44F98C63376A76A2793E57DE
-:10B580005CBB1CF5C1107F4F3BACF7CE0AC97B1DDD
-:10B59000F0979FC2E5443DA992EF52F8BDC165A066
-:10B5A00067553F2D0FA0CF0AFE2C65DF57D594E6D7
-:10B5B0001E97A2FDAE1A4EED51AA17D777ACB7DD94
-:10B5C000007646B54505BE5DEB7DDBE673427972DC
-:10B5D0003FC0734BA166F74504182FFD1D1FDA7994
-:10B5E000633D8A0794D6286B64A047B75E344E7DCE
-:10B5F000770CC0416EA5441C189F8E74BEC867F1BD
-:10B60000D61380C5A25B47F667EDC0F5E50D721550
-:10B61000D2455B57B475047BA4FA653E97A347D423
-:10B62000B04D407D456597D2673ED7234EAE37A9D2
-:10B630001E667A8EAF276B17A7E27AA2E94FB0ADEC
-:10B640004149CCE7FA766DCEF3493750989CA06714
-:10B65000412FA591C9B0FE8E003D03FA490A0A3078
-:10B660005EE3580F598DEB98519F8EA8667AF09142
-:10B670003482FC44D7A12658EF1AD3C369D04F6354
-:10B68000F501C1AF5B3FB5F5CE55DD41400FCECBE7
-:10B6900063EBDCBC6C36DE1F00416319BCA057CDE8
-:10B6A000EBDE2F26EE406599C0ED2D33FE050BB382
-:10B6B000031F9BF936E271ED82C7F149EA37607FDB
-:10B6C00069364683555907F0FD1ABF653AD8DDEB58
-:10B6D000A58E95C329FCEBA7CF5382F4FB1A2FF359
-:10B6E000BB564F9CF73CAC6B568BC2E0AA2E457BF9
-:10B6F0003581C3B501FA463F5141BFE8BE3B37AE85
-:10B700001C4AFB49A37E8CA042A590CD4ABF3B8139
-:10B71000A6A0BFFD1106BF974C2631E0FF57C1C15F
-:10B72000FC507F47FB08A4A7C503F026787B6CE09C
-:10B7300027AAD40F53558057B58F42782D9E656A3E
-:10B74000B4FDEFB9BF70172CFC60DFCF79773AC832
-:10B75000D7BA3B995F6686FFBE49A1760B8E43D070
-:10B76000AD73C5C1EB5CD060A07FBC2184CB95C517
-:10B77000E03A2E307A3DD631F97AF4930AE97BDA51
-:10B78000D1E31D43ED20DF667BEF99840F73D0DE9C
-:10B7900031AD33972A0F36E9FB51D6F00CE4B76D83
-:10B7A00016D45384303D27108BFAED305844185C82
-:10B7B000C87A547FAF90237316D0FA2B763A09E0FB
-:10B7C0004BE38774DEE7EA6ACA0731E6DD2E88F1CB
-:10B7D000E8CEEC0C4EF70E18AFFFA5E94FA5D90E39
-:10B7E000765B385437A80CFC8F6AE6EF8623075047
-:10B7F000FFA44FB90DFD942D4DA97316005F65F997
-:10B80000BC800E0D1EB04F62F989332CB68BFAEF57
-:10B81000F1F47043C50AF47B1B3A62CF7FA285F92D
-:10B82000DB61AA27BDD9F1C7CFB7303B3AC9C2F90E
-:10B830006EEAA134FD7AA6ADABDA3A3B582241510B
-:10B84000B71EDECAF1675E3789546F1BC9F81CFD4D
-:10B85000C786052C0EB161A205E32B1A9FD37A6926
-:10B8600080573A0FB4E7281F86C09E7B8CD4A3DC98
-:10B870000469FBCDA42FDC7712CB65CD6F029F5FEF
-:10B88000EF78DCBFBE8BEBAB7539F7DBA12B3A5EF3
-:10B890001AF047C0CDF464A58BD9B1053BE5C80FBC
-:10B8A000281C954D02DA59967D7684F3DC265AA63B
-:10B8B0005D475C0AD63FEBB1613960ED78F47BB44B
-:10B8C000DCB35324684766392CC0AF2738BF923C9D
-:10B8D0005A067BD8CE8A954DFBEF82FE4A5BADC4FB
-:10B8E0004EFBAFDC5D72E3F768B9A45D2650A5722C
-:10B8F000F33265102D2F0A096128774FA60B15E04A
-:10B9000025590981DFDEEDEE48FD119DF7E91A1B8F
-:10B91000512928B5AE8ED45B293ECA42DBA741BB74
-:10B92000B2660134229DC7E64303615E5B052FF8D2
-:10B93000F7E55B120CF6E0093A951FD0EF4BE83CB7
-:10B94000412E4B48FD3458E72A37AF53545DFCE194
-:10B95000748D07C7D1CA955BE938B45DD54B8217A2
-:10B96000A65865217ED043E776DB673FE784F92D53
-:10B970005346BA605E0F2B50AF2454F48A5D05F82D
-:10B980009A9469F47B59639302F1AD8095DC0D7E46
-:10B990006EF9967E46B81A4494D72549B68DA0CF45
-:10B9A00089D39776F3A8BE743E5D4375ECC868B939
-:10B9B0000CF421F2614899A5AB3F444C427E2DDF47
-:10B9C000221AED6CBEFE078F32FA07F7BA30EEA7E7
-:10B9D000D16F09F79735FA2D49E2F4947AF263C1F1
-:10B9E000F328D083C2530FF8A2CF351C3EF7443260
-:10B9F00009E22E6E1FF10831F8DAFCAC974911B05C
-:10BA0000EE3F2D9F35491A88EEC362883C7956CCAB
-:10BA1000993485967F6F29DC6C41FDE155418E3468
-:10BA20003FFB590B93CBBA810AE2AF7E6AFE732CBF
-:10BA30003E4170DDAB9F5AFC3CD805B4FD360BCAC5
-:10BA4000216D3F2A7E7BCFB47186F69E69A55AFB95
-:10BA50009DD8DE76F1F6F5D32618C79F56A6B5DF3A
-:10BA60008BF03B2F0EBFE7BA89C6F1AFABC0F60132
-:10BA70002BA3574F920DED9A1576AF4F6276540473
-:10BA8000DE4BC92337423D51E307D2E103FBDBD94B
-:10BA90009C346635D1F3C5E437000E1795163D5F2B
-:10BAA000248E7318F831C9976C28D39E3C27BEC3E7
-:10BAB000CB3088DB86F0288314D4179306D910DEA8
-:10BAC000FBF7D9B17CFF0406EFFD839C2867B8B66D
-:10BAD000503ADEAFF8AFD1DBADB0324128E94DD1FD
-:10BAE000FF11E037FA5EB5C07B8748AA513F5B097A
-:10BAF000EAA38733F39F0BEAF0B37230A52F2D9F93
-:10BB000005FBA77F14AF0F0F2E4E2BD28D53375846
-:10BB100099BD319BBD9FEF84F10ABB010F01A56761
-:10BB200024D895E671AC43C719C6B16594E238DFF5
-:10BB300098C6B166949AC6B1CDDEC8DFF371FE0235
-:10BB4000F38A37CEC3432718E7935186E35845D38A
-:10BB50007C32CA4CE338D87CE87B3E8E5DBCD87C16
-:10BB6000864D34CE6748058E93222A86B89575484F
-:10BB700085691C278E03EF611C92CEFC1BC5DA532E
-:10BB80008CF47FCD4EC09E56ACFE17A05FF2473BB3
-:10BB9000417DA2D27107805E49C6FD827FB524E354
-:10BBA0007CBE7450FA3BF5740E6A7601DA3B0B39B1
-:10BBB00088245487FE7915E7D105CDB33296C1B3F9
-:10BBC000B520AD08FCECF52E2FC44FCFB51628F3E9
-:10BBD00063D8050BEBE5139D06FEE57A6F32C9AA23
-:10BBE000063F8BDB015AF904D55F84EAAD8FA8FECE
-:10BBF00082E74999EA69FAFE38D56F44D1C3BB0C94
-:10BC0000DB9D90181E4F34B275E4CB7547658CF3FD
-:10BC100005C93B59741EB7F1692CAC4F60BE028751
-:10BC200023C0E9D1B3DB1ADA88F4F05D01760F693D
-:10BC3000E84771C5EB0D057C517149C6E215601FDF
-:10BC4000FD78E5F6DF40B57785A2C14BE87C67B7A4
-:10BC5000AC93AFA0E57372E75D5EA7AE9FD9F247E4
-:10BC6000306F1BFD0FFA99E3A765DDF877941ACBC7
-:10BC70007712295AA6749B2A0EE5F4E0E3AA21194B
-:10BC8000E8755B2A83E74E788E81CF1EA4D75D1EB0
-:10BC9000D6568327F0A04C22B81E75F667C66D7F76
-:10BCA000ACE7D7D615137C77C9365F21A5E75D0FC2
-:10BCB00088884733BC9DFB127C16EA5775367C2674
-:10BCC000837F7929F8EF5E6AFC4E826C3C0DAF1AD7
-:10BCD0001FDC3E7B52BFE3BA7A73FCD7F73BAEE37F
-:10BCE000973B4A6719CA7756CF31D4BF7B6991E138
-:10BCF0007B517091E1FBFC958B0DE585F50F18EA02
-:10BD000097342C337C5F145A65F85EBE659DA15C48
-:10BD1000197ED2503FD0DA64F86ED977D54D208F96
-:10BD2000B5BF1709D8675F384F3C0AF6D5174E09DB
-:10BD3000FDAA2AE0352A87A76AD290BF4FD7A8F874
-:10BD40003CD79A8BFB6301079567BAD66FA83DBCB9
-:10BD50006CE544D023B43ED5E14FD7BEB52C487D29
-:10BD6000F78D10A4A67C2F362824D20FFC98E45E11
-:10BD7000BEEE1175DF3B2FF1BD812E58B97DBF8B13
-:10BD80009DB1DF770B3D23C1BE0B7E60C5FD9B7867
-:10BD9000F603FDBB82C4F01FB46717C437747AE79B
-:10BDA0003591D9D5D788935F13E9B34261F25EB17B
-:10BDB00063E064881754289191D531ECECDEF1C230
-:10BDC000149801D00F939745A12BA2F28BF41B6618
-:10BDD00090FB1B2CFE7DA09FBBF68B6C7F207230EE
-:10BDE00003F669AE117DAFC17BD2DA1FD7C7776B7F
-:10BDF0007CFD8E0F27E4FD9AE9F8FC434D613F88F6
-:10BE00001FFDA96636963FACF1E3B3B3A6149F1F9E
-:10BE1000D554E3F7E3354BB17CA22688CF53352BBD
-:10BE2000F179BAA61EBF77D53460F95C4D089F9AA8
-:10BE30001C68F62849E1F61FB7D7E9CA81E5F37C0B
-:10BE40000E22FD7707CAB5370DE4FABCF3CB91603B
-:10BE5000E79E7FDF8A41F4787832F35B7CFAF970F1
-:10BE6000BD2F0E51FAE7F6FD6E7730FAD82D643A01
-:10BE7000F867AB462804E2EA8ED7BE83F6327D2F00
-:10BE800011D49721AF7E1FB1B77F98F3804BD34970
-:10BE9000AB7FE2A97FCF9F970DF461F4751C14ABC3
-:10BEA00019DD9EF302DD74F86376D94EAECF4D787E
-:10BEB00094B8DC99F179B6BF86CF8E0C88B7548AD6
-:10BEC000851689BE3BDF62C5799D6F4B60FBD89EAE
-:10BED00094CB8AE7956FB17BF4FAA1329CE431EA06
-:10BEE0008B811EBDBE38DFFE9C1BE47E499AC57364
-:10BEF0003C17F8C3C7F983F19DD67F6538D3E33487
-:10BF0000F4632C9FAF17A6B37D4535F1D618FE819B
-:10BF1000F65C92A6788E53BD707ACBB0441897FA2F
-:10BF2000711E18A7ABC6E361E3A679F47C59B1D4BE
-:10BF300081F535F8E2F5FBF7860F76FC3EB6B15891
-:10BF400013C469E2D58F4B0FE97305FC03D2267F3A
-:10BF500009EB8E234B5B77242C6BFD06C262D07AF3
-:10BF60000DBC6F368C47DBA99A0F0DEDE2D35D2235
-:10BF700027347A523D791DCF0FA1CC8C74F6D31E95
-:10BF800013697FDD927325C479332515F55D0006AD
-:10BF9000A2FC5469EB54FC2AA2BB03E39EE334B930
-:10BFA000576FFF2365B94FFE59C67806F90BED9D13
-:10BFB0007E97F9D705A4D00D4EC6BC96F299A0275E
-:10BFC0003FB168F6407D3ECCFB2CB1E07EFE59F2DD
-:10BFD000B63B576797954A3C3EB992ADCF41FA1FA1
-:10BFE000CC8FDA6986F5BAA4C1582E2637A7823CD1
-:10BFF00014AF9761C7962C82F55EB76F325BF2E0A3
-:10C00000BC4B48751DD829AB65B68F3ACF43A42BDE
-:10C01000285C95BB9EC9077B3620317DAFF9CF8B5D
-:10C020009219DC652921C547BF7FDC927BDBF708CD
-:10C03000B40FD5815E0BBA8837563C66FE4A237C26
-:10C040009782DF0C2F21CB0D7068FD6A70885B84AE
-:10C0500098791A3F93041ED761F2B15632DAAF8F46
-:10C06000733C68E50DA672A3A9BEC62732E7934CC0
-:10C07000C9FF38E89F4A5BCF34B4D308E58FEC683A
-:10C080003D255A6FC3C5EA59A19E88F51AA5B1F19D
-:10C09000EBD9A3FD35C5EAAF72D7B65782949FCAD4
-:10C0A0005E7EC20D41DF4FA4FA54887F556C7EC876
-:10C0B0000D783A2505DD40EF4F4262CCB8E07BBDFC
-:10C0C000F8F23905F02390B529DE5F7CE446D0D73D
-:10C0D0005F6E96312F26B0C51AB1523EAE6A593402
-:10C0E00013E2F7B47C8C951FFE14F60D03AD467A6F
-:10C0F00096BDF0442AC489282699BD4D22687754FC
-:10C100006DFAF334D0E301D2837C686E07E35F48B5
-:10C1100046B92F5212FB7ED7F215025CCE022D8F4C
-:10C120007C0A79090113FF94F6AE279D0AC411DA3F
-:10C1300025570AFAE5DF25DF053DA0E18384983D18
-:10C1400051BB75C3E863149EAE4DFFEC160C7E37F1
-:10C15000E3C3F3E1F9BF7A558DAF67CE717F28DA7B
-:10C160002E84EDD45666FF9036F6AC90236EB03731
-:10C170002B9A642FE55052B1EDB9E79F023FED03D2
-:10C180002BFA69E5DB7EF3EE045A2EDF2EA7CC6492
-:10C19000D3710AA951BA04E8FF968E89D2A1ECD7CF
-:10C1A000BF51D451ECFD4F93A3F428DFBE5F21A310
-:10C1B000FAE2AF20BC5FE974C6A04BF8D834B057A0
-:10C1C0006AB77EA580DFF5C93E810CC8ECDBBEB442
-:10C1D000E937B81E029E908E9C4EBD74EB43AFC8EB
-:10C1E0008DAFE6613D0FE8C978F47A91EBE5CA5D61
-:10C1F0002E9204F1CF3F584333818E2FDDE38679B1
-:10C200009C94AA195F3FF3502AECFF95CAC1540FC2
-:10C210003ED9FBD267EF437E2B11AA53D93EA66FBE
-:10C22000208F970F84F92D6CFC11CEAF98F891EF09
-:10C230004A9F110B213EFC8544A66F8F211737C8FA
-:10C240006CFFE9E4462B24F9919360E7837DFDB60A
-:10C250008871564216E33ED87D5A1C972CC1F217BE
-:10C260007C5F6AB86CD1FC439B815F373DDC01F495
-:10C27000393DD83700E0A47808727C09B0DF2F1E62
-:10C280009D3A80D187E51B603BAAFF0BE03DD4EFD0
-:10C2900090719F50D78EEB4B36FEBD7C7C0AB70366
-:10C2A000D6B393A96CBFD23CBFA57C7EF4AF83E824
-:10C2B000F84B27DF4CDE37AD62F2ADC97B68D67430
-:10C2C000F8FEF93B4C7EA01DAC1F14AEC800FCBEAE
-:10C2D000FF5601F581954462C9F52699CBB5F17BEE
-:10C2E00080CA29C40528DC12E43344F984F69F8C03
-:10C2F000F847BFA4783D6DA7B3CF02301ED653A236
-:10C30000EF75EB4709D703D365A3FC93C6FE97658A
-:10C310002F56C82408A665C50756F4BB2BB6C98599
-:10C3200030EF33CD07DFFD31E5EB33614D4E8DFA54
-:10C33000D32CA7A53B360BC09F66393D534A57EB1C
-:10C3400058724ADFC794D3D2CEFF2BFA53C35BC0D7
-:10C350008437AA07872459E2E3CFAC075DB21A53AA
-:10C360000FD2BF77487E5FBED3F84DE3336AA10D8D
-:10C3700001FDDDCB8F1ABFF5F2A3C66FE6791AF186
-:10C3800066FE3E010C350A57E16E19FD928A36B6FB
-:10C390007F43DB1DBA220FF1E3C3E58BD41FBA2222
-:10C3A000455F0E99CA61537D9FA95C68AAEF3795D6
-:10C3B000AB0DF52B5A0F2A2CC92862A8675DFA1419
-:10C3C000F938867DAFAD3381964F9520F0437A8F53
-:10C3D000027A4E5E4E4D33889FED15D1DFEA567BD3
-:10C3E000DCC9F4FD4376E6C7767B783989957BFA1C
-:10C3F0002B75A0E7B4F73D7616E7EC2EEC7127E934
-:10C40000FCFB636DA21BF6833B432C1FB52F3CB591
-:10C4100028379D24DE7716179C2A3A339682FF56DA
-:10C420002F7AC1355CB0EC7637ECBB75B70DBB69C4
-:10C43000367DBFF0B008E633E976B847035C24E800
-:10C440009306E6F3FC09FA778A047F3911F226DABB
-:10C45000987DBD608DC91E76DEAB607ED97A5D5C4D
-:10C460004BC7FF65BC9FD246E3F732B206F9AFCCAB
-:10C47000240F7EEE0F1CD5E42187E4B0FD6DC2FCD5
-:10C4800058AE77A78AD937CDA678EF6E17316FF6F9
-:10C490007C9B48EA609ECD02EE7392607F94AB2A4B
-:10C4A000D283FA4EC34B17C88D125F1F75EDFCD7B0
-:10C4B000FC07813F5EF9E3E8A7E9B3EB950F46EE91
-:10C4C00081F2AEF732FE48FAD62FD8F735EE237652
-:10C4D000EFB3629CAB7BDF6F331E84F2AB568C7381
-:10C4E000752FB7E23E4A709F2B3402BE0F66FE40A6
-:10C4F000EDDEAF46B33CC91548A7BFC8CC1F39DF36
-:10C50000F6EF1F42FEC8F9363A2BB00BF625A0DC39
-:10C51000045EB5A3FFDDBDF7AB7CBFF3EF379F2A09
-:10C5200085F891FF5C64F60EE0D724160F0EEC1927
-:10C53000FF1CE43757B6EC5720CE5EF0DA5F478336
-:10C540009EECDEC1EC9D7372E7B3B01F66553E5D95
-:10C550002E533C9F03E11944C873CA988260762C1D
-:10C56000BC303C74533CC0BC285E4A41BFC7C34783
-:10C5700086F28F8A8F4FEF627AECBB98671FC58B6C
-:10C58000E063EF5D219B80F367EFF77D351AF4CC14
-:10C5900099F032B4472E35EF6B15B6CFF23F67DE18
-:10C5A00042E472E63DF71F96DE8CFF3F82F5B57FD1
-:10C5B0005F39E8CBE7BBEEC7F24B2E2FC27B99F277
-:10C5C000FFD3FF6974DF41E9EEBE34DD9FFE879D36
-:10C5D000F7A5E87E98D3DDE581FDE5EEBD7FC5B822
-:10C5E000A936FF4BCDFBD5FF47E7ADD9EB332CD5B3
-:10C5F0004766D1FA4748647D2185F3F5F4A9EFCC6D
-:10C60000A25F7F1BC71E39ADB0F8C76F09CB130CF3
-:10C61000A6092CCF83FB450584ADEB05592568673A
-:10C6200014643D82F60191AA8FE4507CCCC858E88E
-:10C6300065F96063F01CCA7503AFF5623CD0E41F76
-:10C64000165C7D7D3BF829079751F8E83807078B82
-:10C650001E6A299129E972C43A1A9FC7E079C83D38
-:10C660001DEB4D711AFDA399E0DFE8FCBDEB55E32E
-:10C67000F769BCFFE9E4400AE4934CF7CA2404F5E7
-:10C6800048FD0AFD3EF234533F87C0AFD5C5CBFE0F
-:10C69000A3F84BB7323FF2B764C9911CC05FBA8CA4
-:10C6A000F1C04BE28FB0FCAFEB06E6E079142279E3
-:10C6B000117F330655727C32BF59E2ED25675D0765
-:10C6C000C8AD44A8DFCBEC32F49735BFF7527826DB
-:10C6D000DC9F96F8D01ADEA57419F35675FD225E1C
-:10C6E000347AFC47E9A0D1EF3F4B8F73267AA47FC1
-:10C6F000EE91403E0BB8FD3FE5F30E11CBE95E092C
-:10C70000F7A3B8FD3FC9992481FD7FAD745404B9E6
-:10C710002CB1B5CE8038BDCD2B205F5FD96541FFF0
-:10C72000C6962720DEB31A242C1FB578C682A17DB9
-:10C73000E3F7769D7980407CD8A7A0E14D0A597C2B
-:10C74000FE2FDF7E3B513BAF81DF09B981FA5F0BE2
-:10C750001A49C441E7B75022C1C46488EF0AE423F0
-:10C76000437CD75886BFEFA746FBB954FD787AE4DF
-:10C77000EFFDDC45F5D647942976C313F755282BF2
-:10C78000E8FCE3EFB6317C058E90D050D40B3EB17F
-:10C7900050B76FF68895E98F5D7FDA910B71B149DB
-:10C7A000DDD9894C9F0E47BF20C0FD82F3444D84E4
-:10C7B000FC83F36DC312715FB05D74F963C465B639
-:10C7C00072FFF99F209F823EBB37917A3887D14D07
-:10C7D0007A301E1BDC648BB9BF7BBF558B3771BAB7
-:10C7E000D13F513B6FA462BE4830514FB7AE999FC5
-:10C7F00048A3FBD201FE3ED2ED97FC57F10BFE3A67
-:10C80000E077ABBD735AACF3602B39FE6E3CF0356C
-:10C81000C631AF6E6BB200FF5EBDC962D86F0C5AF5
-:10C82000B9DF35868C01B86E3C6077E5015DDA458D
-:10C830002FE40F06DA3E55FC31F6ADCCF884FE212C
-:10C840002EBECFCAE2FC7BE4F07CC0EB9EB336CCBC
-:10C85000CFD9ADD497C782F34A3BD3730B49F89E27
-:10C86000D199FF78F89DD4ED8C4C063F7313E1719C
-:10C870000C33FF11E4E3F35B089E0F05BF14F4C211
-:10C88000F966760E98A2642DF8D354DE7FA08FCB84
-:10C890005CD9BAFD9FC00EA86A133C903A5B25751F
-:10C8A0002A106F0DB42689B0EEE6A85A5EA567D4AB
-:10C8B000AD3AB9D86765F9C60727ECB903C6FDAC30
-:10C8C0004B21608FF85EEF71C3BAFD595B6E62ACAD
-:10C8D000BC79EDF9EB1A32638A04FD10C4BB991FD1
-:10C8E000B29B1D86F2F744FF2090AF1BAD9DF77AF7
-:10C8F00063D0CF6F637C76D9FA2DF4FF997E7B47A6
-:10C90000D36F7EB150274759B63EFA6D402CFDB625
-:10C9100044500700DE97EC1D3600E8BAE4B0DC3F77
-:10C92000967EDB56C3F6F35EE6F9B0DD2D54BF5DAF
-:10C93000A3D36F2D36CC8B33B74BB659F8BA7809E1
-:10C94000FD16FAEF91BF6DA0DF62CC77848DE90D03
-:10C950004DBF8D6E3B86FA6D748BC590379A6EBB5A
-:10C96000947E13FADF0AF670BBEC4D88C13FDBB84A
-:10C97000FDFD32CFC3837140CFDD6163FB9B97AB7D
-:10C98000E7B2ED8CDE97D473FF4D78D6F4DC929D40
-:10C99000DA3947331F323DB76437D57302F023D3FA
-:10C9A000734BF6B27B1CCCFA2DAB8F7E2358BF2A7B
-:10C9B000C2DA075A3337CCA5FD8DF1C95E1BAD3FF6
-:10C9C00026AAEFC6EAF5DD1D3676EF421F7DD77E3B
-:10C9D00079FA6E27D777548F0D05FD6AE60F6F9BA6
-:10C9E00031EF78CFF893CDBF06797943C47DC3A3E7
-:10C9F000FC5CDA9BE34FE6017F35DB98FEADE5FC9E
-:10CA000077AE2688FD17BCCEE657E964F9C8552DE8
-:10CA1000CC3EAC6A16422AFDE7B4095F2B00FFA2A8
-:10CA2000BD021940CBB3ACAC3E7941DBF722337386
-:10CA300074FCB0605C39C6ED1748C40671F972E742
-:10CA4000B44F201E5F3E8EC5F1CBF9FB45873BEB13
-:10CA5000209EBDE84901F73D09CF07D0F21B4BDA14
-:10CA60009661BCD69C17A0E9F34521E3FB72533EC7
-:10CA700063139FE72CB113F142DE1263E62534996C
-:10CA8000F1D1CEF1B149C475B3171F143F6A665F87
-:10CA90007C508ACECC498DCE7FD11B745E79D17902
-:10CAA00069F830CF4F8B3B97F376F1E6ABE1AFCF30
-:10CAB0007C357C9AE6FD1CE80D5008392417F2629B
-:10CAC000281FA0DE08FE4EC4F3FB8593460CD0EB76
-:10CAD000E1AD5C9FE7D64F2A1848005FA41AF8A67C
-:10CAE000B861F1A18174DE63DF57C7C0F2F8BD09F8
-:10CAF000563FEC8F6EB5F7A05ED3F8EA1BCE57EF2A
-:10CB0000723CEE19548DE75403AD8207EC8A40C4A1
-:10CB10008EF80B50FCC1F995003FBF18A0FC05F240
-:10CB200074F0C92F19BEF60A2AC4C7A769EB0FE033
-:10CB30009FD6CF6D63F80F8404C47F1EE9C1FD91B9
-:10CB4000AA06C11BA1F5AB5A1763DE83A66FE99F46
-:10CB5000534F0F1D3F4AB1F8112BE9D6BF725EEF5C
-:10CB6000466BFDBBC09F37BE2093261D7F66D1FF5D
-:10CB7000BE8D41270D9F97E2CB0B1C4FDB008F4EE4
-:10CB8000C0570FB39F225FE3391AED7B400A1AF0BA
-:10CB900058F0D4858BE269AC8627E053D0536D45BD
-:10CBA00022948B5B05D22FB3EF3C617F522FB78B62
-:10CBB000F61E63FD3F23E0BD2566BED5E6DD876F2B
-:10CBC000E3F02B9C4B03BFE872F9F61B13DFBE6941
-:10CBD000EF39920B7CBB5760F183B624C3FEE22091
-:10CBE0003B5BFFB7DA297FC3BED661D9BB51ED2BC2
-:10CBF000DF097CFD02BB5F7F2EE92A9808E43D6EC9
-:10CC0000B1611E19C23194D9957ABDBACD4EFADF01
-:10CC10009A17BFFF81BCFF78768D561E05E341BE93
-:10CC2000572B1D2F2B3A9E59AF6B7EFEA5E635F292
-:10CC3000BF38AFDE3C4CD281FB4E9992FF31AB2E18
-:10CC40000FEE369E67442140FB4A572FDB76917AE0
-:10CC500024CD83E79FEEF1687CC6F2DD0B791EFBE5
-:10CC60005471E27BB07E7EE663FB7C7916F2FB8931
-:10CC7000A09F27CB788EEFB32332C66B3F9BC2F2C7
-:10CC8000386F7AE3A004F1999B4039517CDC34562B
-:10CC9000407F058E61C1BED92E6ADFF846E27C7204
-:10CCA000E11C57CEA6FA02387F3C664BA8169EDEE2
-:10CCB000829E9437018F93440278ECF0F52B80FB31
-:10CCC00093EEF933C1FB43E83A8BEDC7B493FE50C2
-:10CCD0006F82AF3FBA03E35BD617407C74D641A79F
-:10CCE00013EE67C96AB4509F218ABF0924540B719F
-:10CCF0009BF1C77DB700BCA5D45E80B873695B5358
-:10CD0000AD1BCA8D8257A5FD0782FE696E3A8F6DF5
-:10CD10000D9F4EFB0EC823AD07DD041A59BDC0267A
-:10CD2000B87808DEAFC33C9BE24D021EFCDA161257
-:10CD3000888DF51BB2D17EB735D2F679B04ED0F6DC
-:10CD4000D0EFA64FDFB905E4FD88C8DA37B37DEA36
-:10CD500062DA4E05BEDDB418FB5BD4289034DA5F8E
-:10CD600069335B074A8FC85EF8DEB2FF495CC7666D
-:10CD7000D2F1066682DE8F4C8132C9153C18EFACC9
-:10CD8000188974EBE6724E268E60FA43E065EE3742
-:10CD90006876D3BB7696EF5BEC5DA6F4A3FDBC3959
-:10CDA000AE7F26A405045A3FC5FDE7E314CF7EDA23
-:10CDB000E5519EB77170DCC74AA76E1DFACCCEEE66
-:10CDC000B75AD03A09F319169242CC67B8713CB3FE
-:10CDD000D7DEBAD61E822B0EDE927BD2E1FDC16B6E
-:10CDE000AD68FF9EDB26231F9D1BDC89F1E9938D37
-:10CDF000329E1BAE6D64F7739D6C66EBB8F80CDB6E
-:10CE0000D72F7129583ED878CB3458DF4E6E62E761
-:10CE10001D0B9E99AA40B9A449F0B2FB8B987ED411
-:10CE2000FCB7620FCB47D0F45F259F779FBC45933B
-:10CE3000BEABD4D61B93BEAB847D65373C8DEF0370
-:10CE4000C4C9F420D8FD40F7C8D7C8BF554764020D
-:10CE500076BFF071D734CCC7DA2B603C7F7C9BE087
-:10CE6000837DFDD2F7AD21B457434577FF04F4F835
-:10CE7000075622A890D74EF14EF5C3386BCF9F7E50
-:10CE800041DF7F72D4069930944F8A10CF5AFE67E3
-:10CE9000DE6696C79277747D2A9CB72453FAA1BEAA
-:10CEA0002D6910895FA7373E117CB7FC98E965BCF6
-:10CEB0009F42A35F9E525F0CEBD83007D34BEA66CC
-:10CEC000197244C8611E27A1F6349EBF5DB47B5D14
-:10CED000AA42EBD5F1FC8F457BD7A58AF47D2DAC1A
-:10CEE0005FB4FE2285F5BF689FE069D2F5AFB5D784
-:10CEF000FAD3FA51761BFB19B697972FB31F0D0E75
-:10CF00006DFC78F6F8B87FB9B01EEE8B19F79688ED
-:10CF100049C7E33E9E394CBFDFA13DB5F86BFE3BF0
-:10CF200016E2D3E16DDC9F1CC4A7E38B96B154BE1F
-:10CF300029DD6E681542004ACBD8634A651E963DCE
-:10CF400020CF553C4E5B3585ED5BB5E41C5D01F2B1
-:10CF50003D334F403E2041BFD22F05ED2015F6173F
-:10CF60004AF258FB12DA1EE4AEE5492687541FA8A0
-:10CF7000A02FAA1AD74DC3FA9B0415FA6F692AC2CB
-:10CF8000F5BE749C48F0FBA663687F94B61E4B0107
-:10CF900079A5F2B91ED6DFAA8956BCCF4B933B4D7B
-:10CFA0008EDF92F97D4D36CF28C8EB7F10808A2125
-:10CFB000BFE211C2FCD46619E52C308EC9E55BDBFB
-:10CFC0004494E783D7DE8E72786EB310478E0B14CD
-:10CFD00038977C32C4BEF7CAF15681CB31D30F27C4
-:10CFE0009D4CAE0BE03BC8F14E81FB83CC1E34CB95
-:10CFF000B126979792DFF22D26798E23B71D52E73F
-:10D00000AD30EE3DD7DA11EE82EFEF7EF71ED43F62
-:10D0100032E67D147CFF8154D077C512CB57D2F015
-:10D020005829B17CB63E70AC5FA60CBC2C788C70D5
-:10D030003C6D7745F587087CCEEEE10A6E9291CF84
-:10D04000CD72F85F959FBF973C1FE6FCA3C123EE0E
-:10D0500065ED217F2C42F1F4DBE6E7304FF5EC8BF8
-:10D06000C76E043C97EFA17C4BE77BAED9C5EF7B45
-:10D0700009E13A53D622621E389122F9B7B8F47208
-:10D08000C9F290CA5F76217F94ED60F9A465AF7C08
-:10D090003C1AF34496F7607E55F0456E6F063B47A9
-:10D0A000035F97492C1FCA2CE7B73A98FDD9B53BC7
-:10D0B0006136CC43D8C2CEE997856F97810FB57A98
-:10D0C0003F74C85A3DDCBF0C52BE85FD75804F7F52
-:10D0D000EE5CCB83EADACAE4BEAC55467FA96C4B62
-:10D0E00013C6B1035B3EC53CF78297B761FC20D005
-:10D0F0002A1AF31EB788B87F459FB84F65CE3FAC5C
-:10D100006AA9C4FDB6AA30CFEF33E5BF95BFBCF71F
-:10D110009520454DF9AF5F70831E38DDB1D90DF80C
-:10D12000A4FD61DEE0F73F970C7951F1F37B7DC6FA
-:10D130007CC2F0AA98F984A7E11F94C11F70707E89
-:10D14000D5F230B7F4E379DA91FCC218F1FBDE7363
-:10D150003BDBBE7816F2DCBB769C7916E0AEF8DBE2
-:10D1600067CF423E13D967C77529F0E2EF314F58B8
-:10D170006BF70B07F7F3B7BE80F9D5E73EB0A29F78
-:10D18000736EEFC90CC85F3BB7FDEB5488C7DDBBBE
-:10D19000772AC62BEFDD593080C4D0EFDA13F8328E
-:10D1A0007419F9DD663A1C6C3988795767DFB7A2C4
-:10D1B0003EEBCD0B0D57B23C5B95E78336C7CEA354
-:10D1C000D7F218AB5A6EB9E95AD0CF2DCC9EEBCD21
-:10D1D0006BBC541EE83B949ED75C06DD9A799EAFEB
-:10D1E000896E67E11F943E6113DDBE6859F8ABA7F5
-:10D1F000E05B4BBFB879A091CBC09796A7FF738730
-:10D200006F8F03CEFDED4808A6317A85660A60EF80
-:10D210007D9101E71A4EC93D98EFD1B3D7EA817CE1
-:10D22000C6B2BDEFA17C9CDB7914E3AA84E7C99F59
-:10D2300023BD7F2CAF59E0F3DBE462F9A31CEF9030
-:10D240005FAABAF13DCF23657CABE597C6CB2BED4A
-:10D25000710C6571687E6EA092FA49FCDEACDE7CD2
-:10D2600053611CD0E998214F579BB7B93F0FD79B0B
-:10D27000D1FCE8D879BB5ABE60944E6C1DD1F29FA8
-:10D28000CF35F1BC69FA3E7D0CE4C1B1F53A10121C
-:10D29000DE2331E451CB8F3EE330E545872E2F2F3F
-:10D2A000FA52F0FE67F1F1A183C5AB35BC74FD25E0
-:10D2B000B63E561298DD49FD533901F705987F7A3D
-:10D2C00037F74F357C69F0D68599DDD0B585F907FC
-:10D2D0006679AE8A735F520A1FA7AA75FF68D03BB2
-:10D2E0005D0776737E63FC5CD57C8CE5DD52FD1CAE
-:10D2F000D2EB677EBF84B9BF0CDE5FA02D767F8145
-:10D30000E64F63F6775AF2DD0EF09FEE6076D2E9D3
-:10D31000B0383DD6FD36B604D9903F50E762F76588
-:10D32000886E07DA47F7BAC6BD9F98024F05F37AB1
-:10D330006A97F13CA09F79F15ED15AD70C02F03C7C
-:10D3400004F8D1C519648F9F809D26A715E6896AC8
-:10D3500014DE5E7AA45848484F7F29920EFAFCC327
-:10D360009C9332F4F76FA6F8C8BF49A46E0085EB12
-:10D37000DF828277991ADFAED6CAFE9F8A86784608
-:10D3800095B5E743B0CFC96B76DC0F17F7D9831893
-:10D390001F7B96DDAB7170E757CFE3BD3CBFB21288
-:10D3A0006E170AA00F4A789CE2E4CEAF9EFD77B0DC
-:10D3B00023A1311DBFE4595A1FECE7E604B4F7BBC3
-:10D3C00077248E863840C96B0FDE08FAA204741FDA
-:10D3D000D8992F0F08D5D2FE4EF467E513DB06E38C
-:10D3E000B980F21D2ECC273CB8735715E8FB732F7C
-:10D3F0002710D0F767E5CEBF4139B0279134A9682F
-:10D40000F7A9FA7575119154BD3D570E65437E0B12
-:10D41000C1FC168CBF517E2E6F4DC4F31FBA7A5CCF
-:10D420009E8383F83D518340EEA8DDA81AF39ED970
-:10D43000F705094C7F05AC3DF7B3FB1058FD80D2D2
-:10D4400053CCCAF58398DC7660FDC51ABFF2EF7D38
-:10D45000FB65F503092C1E10ED87B5AFB2B2FB35A5
-:10D46000CCF4FD6982C0CFE3FEF5CA58F74FC48003
-:10D470009FDDCB259020DCBF4AB6DB314FAB428924
-:10D480008C847CF55714B6FF51E18E8C847CF53D7D
-:10D490005CFF55386899BE1FC4E180FA5026B6CEAD
-:10D4A00097F05EA75D76BC0FAFF235970FFD8457FE
-:10D4B000BE3AF1741EE4AB25609E74E56BFF0BE988
-:10D4C0005F698DDC05FCDFB3DD8AF793766D3F9CE9
-:10D4D000017643971CC948BEC8BE4E65D86AD8A716
-:10D4E000D6E671BA66E90438C7AB9D332C8BA32FFF
-:10D4F000DE4860791D4D09BE5F313D67BC5FE67453
-:10D50000CD6CC3BD8965B6D87AAC19F4822E8E274E
-:10D5100046CF153643BF674967DD204A924AA107C7
-:10D52000F7C7CBB664A683BF7BC07E25EE5B1D909C
-:10D5300055F407E1A9D7C7A76ABCB9129EA7CFCAFD
-:10D5400095281CDD4D9F160F22901F689F1D4B3F95
-:10D55000ED4D48407E2AB359639EDFFC1DE7B76D51
-:10D56000206F63D978DEECE8B807E49002704C7461
-:10D57000AA389F32EA07B07BA2E6E4EACF6D2F9289
-:10D58000EAB11E952FC4C722B25EC973F6D52B8BA4
-:10D5900096E6E54AB9A8B0BEE9E537314A27124C0C
-:10D5A000413B49E23424EB071AF2FD25B9D006F8D5
-:10D5B0005248A1471281D4F528A70E12C6A7939A04
-:10D5C000216C1DAA26101F3FC5F767AD92FA18DE21
-:10D5D00037D32EA23EBF14DEDE4B7023DC56A99A51
-:10D5E00078D1DE98E9017B4C08FAC9B7941F6A6BC1
-:10D5F000A6E7B273E1C407796E6EC2E0737B0E7D5D
-:10D600000DF601E533768FD5F749A8968E07C78CBE
-:10D6100031FE3799DD676F1EEF2F9C0E24B8DF7047
-:10D62000DF39FCF568F7E781BF9EF8B771B01FE3FB
-:10D63000F49008D84B094E1249180DF7E449A7F5A4
-:10D64000F2EB26AC3C94B233E835CF44E377335F5A
-:10D6500013AFF479AF5E14B1FDE7A6F69F5FACBDE2
-:10D66000868F806DA3F7786E142F0E3E87E064EFEF
-:10D67000854EC0C768B7B716E8A8F47CF820E06309
-:10D68000B493F983290D44EFAFE53A99BE5AC1EF3F
-:10D690009FA67F854E5D7FC463C3F8E82A8EF7DEC0
-:10D6A000FA5ADCA44F7DBB0478ED53DF1EAFBE23D6
-:10D6B000767D573C781262C39314A7FF60ECFA554D
-:10D6C000AFBDF7664485974C6F40709E9F5BCE75EB
-:10D6D000827F95F8616A11E30AB61F60A29B03F886
-:10D6E0008FF28363B8EE3DFC5FB68E7E4363D09FBE
-:10D6F0004490EF8A383CB4EC1C48E1FB310777CA10
-:10D7000026B65F39F75E1627FAB18DE5971EE3F767
-:10D7100001CD6D607EF5DCA56C1F9194B2733E1E49
-:10D72000FA1F8C77277442E97D67BD108A64C2BDF9
-:10D730003526FBB5F77E9C450AD42F32C55D347E75
-:10D74000D2CE23CDE7F67526E7CF85A4C705726F45
-:10D750003EF7FE3AD76B9ADE0FAE2359706E5FB478
-:10D7600038BCB03F2AF273A6C4CDEEF323BEC1ECA1
-:10D770007E392D8F2B4B4D84F58D84F97BBECFB236
-:10D78000E47A7580FE9C9674C181F783D4CADE3436
-:10D79000D083F2056AD751574DB93094A8BA736453
-:10D7A000D49E43E1963DECBE44C953484AC00EE4C2
-:10D7B000F703909419BD76D75B140F4BD6A9786EFA
-:10D7C00075A193D999BF7015DEE31C0BF6E5382FD0
-:10D7D000BBE7D648C7E04E36BF5A985F665FB86B66
-:10D7E00015AF17EDCE19D462C0388E177FDF41B464
-:10D7F000AAEFA9208FFF2CB3DF2BE8830746BFF3E6
-:10D8000029C9782FFB02F7EA0F814FD7F0FB0857A1
-:10D81000D664E173754D1ADA9D75355E7C6A78B110
-:10D8200079EBF1DE37DB70D69FCDE3677605B56522
-:10D83000209F42F25447A06C4BAF2660EFDA7BF199
-:10D84000538FF8517ACB7E2C5B3DEC7723E486999D
-:10D850008867DA9E94D0EF4B5CFEA7404EECEAD589
-:10D86000867BE4AC69634CF70D9AF0A6F1C7368667
-:10D87000BFB502E30F33FED6CA1D2AEC2BAFBDBEE7
-:10D88000F7DE19C41F35EF19FE7EC7F6D9E2E2CFE5
-:10D89000938CF6EB82FCBABB204FFA11BEBFF87036
-:10D8A000CD38C4D72A7E8FE443353E7C8A803F3A08
-:10D8B0003F6B7690C0FDE8ECB721E8D359E883FBD5
-:10D8C000678177017FA293E1D39A568DFB6B362750
-:10D8D000C397E80C225E6427C397E864FCA6F0B205
-:10D8E00004F8CBC5F6F89EE2EF00F0972D7D82019B
-:10D8F0005F4ACAE4CBC3DF93147F148E142E5F6695
-:10D900003CA428EC7E4A4DAEE2D9714FD0F9C3BA9F
-:10D91000BDA186E0B37F1C7F71A88BAD9B2996EAE1
-:10D92000FD32E02399F0F52448D2F3094B3D84BF42
-:10D93000B42051A12C303848FD60C3BD92A24732BB
-:10D94000DDCBA66E003E587F58B640BEBCB874868C
-:10D95000E13CA838DB97A4223EFD784FF323352A1B
-:10D96000D26F1DD011EE01E5FED7439C9E0FF37BD5
-:10D97000285771F958CBE5E5312E27B5FCDEE435A3
-:10D98000D3599E554A8E85DF571621FA3CA6246F3F
-:10D990009828142EB4A9557CE23D8BE47D6B680475
-:10D9A0006D97904D7CC02749EF3F1062F735160EFA
-:10D9B000043B2849BB7F71A29A34070FC24624E674
-:10D9C000775055887E4C8725D63D55B5DE03368881
-:10D9D00087C68327C1EBCB7C888E97D0E042FBBD06
-:10D9E0009FBF70CE425A76362460FC2F81FF3E8B5B
-:10D9F00093C25DA2A377BC7BA837BAAE4F74517AAD
-:10DA00007A0046FA7CBC6118FE2ECB137221FE8E82
-:10DA1000CB137C3DD5EE39D7DA7DC3F5A33BEF6A56
-:10DA200083DFBA5EF6613BCF44A3FCAFE7FA3679F9
-:10DA30008A91CF357D7BBC57DFFA87023CA917A6B8
-:10DA4000A01E4BB939B6DEAD9515BCB7BC761493A4
-:10DA5000F36091C2CEB5F4D50318A73EEF1FB911FC
-:10DA6000F4A8C657CB09D33B41E2F0E23AC4EFB782
-:10DA7000D1ECE095700F20D7AFF01487B3DF1F48CB
-:10DA80009DCBEEF35DC3EFB17A94F215C17B4FBD30
-:10DA9000F89CE162FB13CB6D63F03EB55AA705F528
-:10DAA00084F48135042687B47FBC07E20592ECED4F
-:10DAB000F041BCCF2585E1DEDC5A671EDEFB2E245B
-:10DAC000E57980FE5FBA160CB9583E1D9D28DE9799
-:10DAD000E94929241F65E36E009E5F913D37138855
-:10DAE0001B6E48A9B603DEC6BB585CBFA1281FF158
-:10DAF00048F17B93AB7FB49F01B367F4DE8305DD10
-:10DB00006E88730EE60E17B397487A900CD7C979D2
-:10DB100083F63B276A9064E9E47DF9886904F68717
-:10DB2000FACA791C3DB699E9B115426C3DA6D9995E
-:10DB30009A1E934DFA417BD60D996E38A7A5A4780D
-:10DB40008177E119B478C1BE7BA5EE8E24C443353C
-:10DB5000E081A4CDE8F55F7F3014ECC7FC98FC664B
-:10DB6000D65F0B7AD7735F2AD0E994AC0E9803FC8A
-:10DB70007438F67A3EE9F1AB1E033E58F03B51D0C3
-:10DB8000EFA7945C5889EB69F18571F82C6D988E3C
-:10DB90007C4F200AAEF3C34E36DEE706B84E36F0B1
-:10DBA0003C80463904F919271BEEC3FB4A20CF5BA2
-:10DBB000D4EDEF933C15ED4BED9EB193A17BDCFAD8
-:10DBC000FDDDE25FD87D60B7C6E3AFE2C6D87E3D3B
-:10DBD0009E35828D3CE2CD027B98DA373D11B07FD5
-:10DBE000365ABD41122D071FB7C7CC4F5CE29AFAD7
-:10DBF00004E07D89CBF70CC83971B27B41E3F3397E
-:10DC00001BF7046C02C37ED3533C4F53F2BBF5F7B2
-:10DC1000BBF5DEC7C9E324C416E7BB43FB7D8338ED
-:10DC2000DFDD2C9F8378627FD7FC8484A89FD00A95
-:10DC3000F3A86C3853F701E289FB091CEE533283D9
-:10DC4000FBD4F356F63B3726BE38C5F34716090C0E
-:10DC5000AF1A7F9FEAB577FC780F8D99FF848D57B7
-:10DC60006D184FFBFDAC5DC6385C05E51FE01B6120
-:10DC7000E378CC5F171E1FFF18E4257D7E44C4EFB8
-:10DC800065176CF8BDEB67DE0D7321CEF3868CF75C
-:10DC9000757FDE3E3591C5798C71E8856EB6CE9F75
-:10DCA000E6725F7C6135F2672F7FD42F5440AE8AD5
-:10DCB0002F3C8AF64CF11601EF8924C19E43932430
-:10DCC000CE8713A0FDD969CB01DF13EB717FA3646D
-:10DCD000B3D5BB5AE84BE7D32ED570AF7A49E71AD4
-:10DCE000EC97507B2A45B7DF7D8AE701975C60F7A8
-:10DCF00003124F90A401DF73BD13E55FE3BDAF5D79
-:10DD0000F6D871F66FB83D537C6182C16F88CEEF53
-:10DD1000FB4C3EF97A5ED2398EC1D53B9F0DE36351
-:10DD2000CD273A8F89D8BE2B29F6F8991CCF276AC0
-:10DD30004AE1E406295558BDE2FAFB14D027C58D07
-:10DD400049C9826E5E250DE5863C8C92C622659E91
-:10DD5000AEDF281D1CBF9D343C4A87CC47E5EB96BF
-:10DD60003B61BD2F74B961BC8D8BF27FA2427F4CA9
-:10DD7000FF7C22D76754A37EB9C71DEB5C43A65B2B
-:10DD800035C4954A1A387DA89D9CA7A38F46177362
-:10DD9000FB134D25F93F8178F293EC5690F87AC742
-:10DDA00044B7CCD8789BD08BB72CCC07BA34DEBE26
-:10DDB00063C8FBE983374E5F0D2FDA7B6A1FE502EC
-:10DDC000BE2640C0A93FF4C3E87F297C45C7E5F4DF
-:10DDD0009F147B1EFEDE792C25416A3F2CB8E43C63
-:10DDE0001E2441DB45E6A1D19F5C6DA0BFFFD11190
-:10DDF000D7811C6AF45E70E049E4DF05541E615F60
-:10DE0000FE64FD7D86F5210A5F1CBA0F0F92ECFCC3
-:10DE1000FF7374FF440E6640DE57701D5B474E6D06
-:10DE20007C24438FE725AE490B812E6453FFCB5AE8
-:10DE30003F8293BDED2AAE4B32C6C376BBFC0137A1
-:10DE40007D5FCAFDEA1549D346C65AF7A95F381166
-:10DE5000E2CFB535D32742BC4DE67623FCB216D8C7
-:10DE60009B70057AACFBB5EA395D1FAAA9C6F835E7
-:10DE7000B10589477FDE9730BBE81BC2E22D5A3BD4
-:10DE800045F67B20FEA908A410ED39C9BF32330F37
-:10DE9000E2182939411DFE1E7533BB6E4DDA010FA4
-:10DEA000E4935A69FF108FB1A54BE78DFB94AC9CAE
-:10DEB000238C97613E724A98603C339BBED7E15BEE
-:10DEC00049A1705EC4DF946C6EDC2F9208B3D3B4AA
-:10DED000F9D337B89E3DCCD7A5E510C74D013BCC53
-:10DEE00082FED07A1EA7FC654D21C78384EB98354E
-:10DEF00089D5571219DC76885B8BB0AE46B0EC82C0
-:10DF00001B7644BC9A0C7F7F3489A8F83B7DFD4882
-:10DF1000A40EEF3199D4793FBCF725F8B7001F7CE8
-:10DF200039B0E34301E2D085FE2B61FD6D108339EA
-:10DF30002AADFF2BB12707EAC1EF7BBD9FCC9E43E3
-:10DF4000206FD9AFDB9762F772AAFAB89EB93C642A
-:10DF5000A964DAAFF9CB95FAEF4D09BE5D0047CA67
-:10DF6000C702EEC3D4DAD9BD3EB5AEDB1261FD3EC9
-:10DF7000CAE985F407FE696776CC79494D4CC6F845
-:10DF80006656EEEB86F1BD86B2C4FDB74D941F25F3
-:10DF9000DDBDACC3259F05F865443D7DAFA75F8C13
-:10DFA000B85AB213AFBF8DB90FA3C147C725803F81
-:10DFB000F1C234B6BE9AF8608FC0E00FBAB8BF4560
-:10DFC0008222D0738E765FB0B48295B5DF8B002A43
-:10DFD00052383ED0F617C80A56E6FB9481796C1F7A
-:10DFE000D20CCF9CB6873B20AE3FA76DE07CD89F7C
-:10DFF0009AE31CF96778EE917B0E24801D789F8050
-:10E00000E73F7EFCFBD7E504FADCF9CE463C6F7CAB
-:10E0100096CBDD5DA407EF61F7130FDF270FE1FB60
-:10E0200079F00373580ECBE0A7CF8D847E74032D57
-:10E03000DDF97AE80630DBEE6AEFF90DA8017FD84A
-:10E04000330DF700B476ADDE43ACCCDA45F160E3D6
-:10E05000F6A80DE7159DB70DF1F0416FDE7810E9D8
-:10E06000D18B277EAF928697DE7927DE3603E2BC1E
-:10E07000F1F4D91C67D69FD9E60783CB8CA7CFE1F3
-:10E0800013B5233F77FBEC8954BF7DECF639E0599B
-:10E0900061EBC99086A2BCB8A15C25FA87A4523C6A
-:10E0A0009C1DECBFB23FE0A3A3DF65E9D10FED4CAF
-:10E0B0000F90BC0C9C8F76EFFBC1074EBAC0EEAC44
-:10E0C000DBF95E063C2BC5CEB5B7637C53447FE8D5
-:10E0D0007CCB95173D1FF621C49DE8FA372251E30A
-:10E0E0004336BFBBF9F99ABB5B12F07CCDDD4B45E3
-:10E0F000C3BDCD772F65797744EA187DABC15E5FEC
-:10E1000011B71F880398FB99BF7432F9B81FECB39D
-:10E110007A26615CE059C65FF3A7F844C8479EB011
-:10E1200052C078CBF8E36A6B272DCF0F25E1EF1DA6
-:10E13000CD7F60492EDC4350D5C1E27B03C4C53995
-:10E140003F83F8C901B68E437931C8B7D3A73A7572
-:10E15000F1FE2EB93A07EEDD0BDEE9F401FF14DD26
-:10E16000EAFB007F2F91C721B47575574311E6B1C3
-:10E1700016CD55C701DD8BC276FCFDC1221B911C5B
-:10E18000548F1549C406CF010A91ECF074101B3C62
-:10E19000F397B37BB28B1B66A17DE01E57A8C0FD31
-:10E1A000B7456D2F7C01ED4BA4C87E76AE85E1A707
-:10E1B000A8EDF0D7C03F0B7D859877F89D2D8AC1DB
-:10E1C000FF1B153696AF6935967322C6726EBBB1CA
-:10E1D000BC15EE38D3D91107F65A719D283FC3CE2E
-:10E1E000E9BD2AC0DA04F1602BCA5341795B3EECE9
-:10E1F000479F79C96581EF7BFECAFCDE9EAD76BC88
-:10E20000EF6DFF1F1CC40179852FDB37C2F7338EFA
-:10E21000703EC4E1687DF63B5B85E191E0BFBD7275
-:10E22000B5E6A78746C3BC5EF91BCB93E9D96AC59F
-:10E23000DF4F39B3FB8597605FECCCD62BD0CE7A1D
-:10E2400055085AA0DFE02A467F339F966F31FAC502
-:10E25000F727327DD32D307C5FD9609CF755216341
-:10E26000F9E789CC9F9A4774EF3361FF5EAD4B832A
-:10E2700075F5B9D8F70D3FC4E5E2C517158D6F45A3
-:10E280007E3F1B5175E797F644F7EFEEBD02F22A89
-:10E29000001743A3EFCB4DE36AFD1726B27DF814B8
-:10E2A000BE3FD3F38688F8396DFADDC25EBBAEA6F9
-:10E2B0007AE014DD3A54DCB03FB508FCA3C6FDA9F2
-:10E2C000F374EB4BC5D683A977605E9284BFCB54C1
-:10E2D00031E7F94727A4C07B310CF0C277887B7502
-:10E2E000857FE3867AD4DE1D23EAF05ED270DFC03C
-:10E2F000293A39FD8FF2A5264F15DC3ED935AE639C
-:10E300001AE4899737B0DF6F2A0FFFE816F8FD454A
-:10E31000D2C8CE99E64BA450A4F253B1FD473F8436
-:10E32000DFE30A3C33D60BF0D02E6E85F7E5CD9FA8
-:10E33000E27982D5A6DF11D09EFB387D69FD888504
-:10E34000D65F7D9BB314F413EDF775281FC8DA88E8
-:10E35000F79BB84FB1382D7DFF3EFC24CAA9C9C137
-:10E3600037EFA04DCF90F0BB3764C2BC8D7C46F92F
-:10E370005600BBAB67B380BF6B4B2DADFC9BC1A4FC
-:10E38000F62DC3BC5BFAFDEE58E79D17858CFD9812
-:10E39000E9FF07CEBFF42F4BCF47E67AFD6606F1C3
-:10E3A0005C62C552AAEF74767EC5F17ABCCFD13CCF
-:10E3B0000E06E174F906B05EAA28DF76EDFE21C1F3
-:10E3C00096CFF36687B132DE5B08FC4A19A5FC6A7A
-:10E3D0003245057CDF4CA6C3F35521F2A828323D17
-:10E3E0008171A06D09A827BA3C9DCF3F0DFCD53C9B
-:10E3F0000AE34F83F879CF2E3582F73C76F3F86441
-:10E40000978795CBDAEC980773E6AC827A7459F863
-:10E41000A01BE8D1F592DD02BF4B7A667BBFC990A5
-:10E4200027D91566F7FF9E0EF7C3DF7F8DB76E996C
-:10E43000F581B64E1E837FC27A9AE8FB06D65BB2A0
-:10E4400082E5910EE8579D13EBF724B476294A75BF
-:10E450000EF829FF1B63EBB5D4008000000000001C
-:10E460001F8B080000000000000BDD7D0B7854D5E9
-:10E47000B5F03E73CEBC92996466324926218F096D
-:10E48000841020E024860814EB24040C187542D173
-:10E49000A2B638804080BC44DB46A55F26244242B9
-:10E4A00051428D08087140B1F48A6DB0A8C106EFE1
-:10E4B00080F86AB537DADE5EB5FDB92370295A1ED9
-:10E4C00023F452DBDBD67FADB5F799993349AABD6A
-:10E4D000F7B6FFF7FDE9478FFBECC7597BADB5D722
-:10E4E0005A7BADB5F744BE6EF1EC2D60F0172850A5
-:10E4F0009C8C5DF2BB3C9BA0BC4482573318333AE2
-:10E500007C465B3A63D672C6BCF0CFF186BC5786B8
-:10E51000FA53B2E79BB6718CDDC57C0686CF72BF1D
-:10E52000818D853E9DD0388BB1650A0B290E782EE2
-:10E53000F4BE2F4DA53263D07FD92E29D801FDEF2F
-:10E54000DA6C64CCC4E8EF33F8B7A217CAC5B1F2ED
-:10E550002A16343019FE63575C3B187F95123A2A0D
-:10E56000A530B6DAC442C930EEEAA7B4FDD6B01081
-:10E57000C1D370E03363FCF8303FC600B4FF64EAF7
-:10E58000BCBC6EDB34C69C0628C3BC236FEB8388FF
-:10E5900087FF907D34AF35CC4FE3DCDE5AC54EA506
-:10E5A00031D67C5F6BD65DF0BCD87A7FD65D5743A1
-:10E5B0003DC201DFB730DE9FC1BCF601CED654B3F9
-:10E5C000502EC0B71CE69B5406E541293405CB26E6
-:10E5D000164829E3EF53CBF87CBD71F0D5B31EFA92
-:10E5E0005EFD2EED7BF68B34C267031BA27AF654D8
-:10E5F0005C3DE0A341E0A1E100BC8FC3C3CC03526A
-:10E60000C07A1596821D19005FD359C63641A9E913
-:10E61000D06746CDF8AC8731C04366126366A0D799
-:10E62000A3125BD45F42FD26D64D8136F8771D9646
-:10E63000DBA9DD0981BF476F5991E587765BEC5017
-:10E64000CE16089E0EDFD0E1C7A91C32C17792AE6C
-:10E650008E96A9BE623D2FD7D98A6BB6E730B64DEC
-:10E66000EFCFB2011297C9BED77480BF271DFE5BE2
-:10E6700090DF96E9BC790ACE97798B7C00076BE531
-:10E680007878ACAC65624B490CAE187C9CBEDBA4C0
-:10E69000FE900EF82C7058F2EC7323DF46F47E4B9C
-:10E6A000AC5DB34DA279A41E0BBF3606E9FEBCC417
-:10E6B000F642BB1DD287AF8D817E3BE6B9590794E8
-:10E6C0005D4027B90CDFB34E09F0527EA8EEEE573D
-:10E6D00091CEE5499EF1F0683C5429375A68FE779F
-:10E6E000FA009ECCE4963D3AA8CFBCB3B80CF91B17
-:10E6F000E67DE702787FAFCD4DDFCBB270BABBD6F7
-:10E70000070AD696E0F77D77BF0ADF8B4C49F2E027
-:10E71000F733015756073DBBCCD88EB54BD8EED159
-:10E72000143E7EBA4EBEB30ECB65BCEC582779F7CB
-:10E7300012F36DA579671A590DC289EF8325B46468
-:10E74000BC07A93EC8E93BBBA514C7CB1CC79F4E5D
-:10E75000432807C7794BA5F760968E6520BCF0DF8C
-:10E7600000CFBD072B331DD0FFAD732645970A4F51
-:10E77000176343D84E0959183E0B8B797B93685F1A
-:10E780003A3B131783334FDBEEA2DE9B7A35E0254D
-:10E79000F08ECC901EBFB37853EDD0EE4B063E8F7B
-:10E7A000443AF6217D603ECD9F02E46971745B744A
-:10E7B000C580E3357FAAB0E0D5B1F7E7DA4C2C5835
-:10E7C000142B37D41F9B8BED1AD9D006E4ABC6FEB1
-:10E7D00064168CE3F72F258DFC5D95BF9B3FD5B16B
-:10E7E000401AB16F8ECF8AF8896C588EF01F91D87D
-:10E7F0003E86F5061688FB7EF3A70E6D390A67067E
-:10E800008D136BC7B4ED067E4FEDD8F4700A7EE72A
-:10E81000822D9CE210F3C37ED9326B41BA5C0CEAC4
-:10E82000027A58C717DCBCFE226335FD96587B750B
-:10E83000BC0B8B0C2C44788FD0B8889700C8B69D41
-:10E84000839F18DC506E183C4A7851F9211E3F8195
-:10E8500038B991D13114D2C19AFE856D55578919B5
-:10E8600048714C5DBF6BBABCB3A05ED669D67372FB
-:10E8700079747D93587954270B79D0D0553D2BBEB0
-:10E88000CCDBC7FA37D654C3FA2F2FE1FD4FD89A05
-:10E89000DE58AFC4E411CC230FF1122D9B12CA161F
-:10E8A000284F892BDB12EA9D09F5AE84720E6F7F2B
-:10E8B000CE1ACA933D8C7D645B5BA3807C3997152F
-:10E8C0005A2C417973C7BD35D520E71ACB87BC32A6
-:10E8D000CACF41C923B118FE9A3CCC1B04FC593C59
-:10E8E00061C3B212C4C3D06BB8FE1B06249B047C68
-:10E8F0006EE93F18A232F673C7F5EB97A85F43FFA6
-:10E9000087D46FD4F18B75B48E37159FA4768000B1
-:10E91000DB69A0D35799C45201A5058AFF8FA8BF10
-:10E920001AFB7FC3F52E8B18F8FCB81CBC90E57D54
-:10E9300085E4E011C986EB2ECA7738AE25C6EF6AAA
-:10E94000FB5F4D19FC571C26F9DE4FDA1568FF7F77
-:10E950001A7F338D01A97E854D66A05C0D4E447DE6
-:10E96000BC93F927A21EFA7AE3F8A33A6877421F0C
-:10E97000DECD005FC5F64D350AB43B610DE74A2098
-:10E9800043266DEDE5E5F4F06EC46760EBA384DF2C
-:10E9900013B9E15C1D94A7DA43BC3C3EBC1BCBB76A
-:10E9A0006E7D8697A7847365E83F3670A0A61ACA65
-:10E9B000FB6C23AFD77C3B97E32A7C97C779B3EDF9
-:10E9C000E9C8765C4FECD603C6401E2E5EFDF1B35F
-:10E9D000FB000F8BEF4F2639B5EFDC57E6FB68FEE7
-:10E9E000019F5201F290B33ED763248F15B203B258
-:10E9F00050773962F4B0E60DB949CE4F6A3988FADA
-:10EA00003E737109C9F94F53BDEDF669B1E7271996
-:10EA1000F00438DAED362E97659D97DA3F6025BB16
-:10EA2000678B99CF07D60DD1D722E8512EE6536ECA
-:10EA3000D7D133CF3687C6FB40F2EE30C9F8640138
-:10EA400033D2735512D91977EC01B90072B957C096
-:10EA5000DDBB75623000E3DF21311FCA8D5EBB373D
-:10EA60000BE5C30B7F91EFC4F9F69642199E3F1652
-:10EA7000F2BEB7CE9B658FD38BBD7B78BD2A777AEC
-:10EA80000B787F55DF6476F0EF646E99B817E791E5
-:10EA9000AC302F96972F2ADADB4E7A7B01CD9B790B
-:10EAA000BD5912CCF7F4AAB13AB42355FAA4157A99
-:10EAB0006FC2F9DC8EE35B627452BFDF8EF346BD3A
-:10EAC0002F83DE87F93EE0F0D3FCC10E984A76A092
-:10EAD000B003DA71BED362F8654A781ABEFFFF0848
-:10EAE0004FF760FDFF144F23C88B00B66B6C0579A0
-:10EAF000A18B9317027FDBA4903E93CB0B0FEA39D7
-:10EB00007CBF00E4E3ED36FF468447FDFEE2071AD2
-:10EB1000C9EE53E14AFED68B355F65C3D759A25D76
-:10EB200076E203D366067AEC84A19FE4E289F9CC0D
-:10EB3000D38EF243C7EA118FAA5D5971FF9AB718B5
-:10EB4000D8B397ED32D1B95BF266E1BCBA81AE269B
-:10EB5000D4C37586E0BE82985EECB50777AC40BA48
-:10EB6000DE52E209B8493FD27A0BB42653BB5E7B32
-:10EB70009829583FC36D034890CE448FC86D86E0F6
-:10EB80005E09E9CDF9A577D5A4604022BA07A8FFB0
-:10EB90006D9C7F7AEB18D9F7BDB7B9886FCC2C681C
-:10EBA000467846E3838C0E467CC414EFD43A6B0C53
-:10EBB0000F3F13EB3AB93CFCFCBFA11DB9D94C7611
-:10EBC00024EA4CDC77B19E4C8217E8F902F187BA4F
-:10EBD0005F7A242BB889F6679E0AA4C746AB7709EB
-:10EBE000C1FFED6437C2BFCBCCBA4C65B8FD609DA8
-:10EBF00024EF043CACE73186F6D99DC23EFBF7FA20
-:10EC00004B56B4035EB573FB0A19C504F26F29E3D2
-:10EC1000F54BD7257F88FB99A5EBE49011F62BAC3B
-:10EC20006B8E371CB7CF208E82F1FC425EB2ED11A5
-:10EC30002BF28D1FFBA5E0F87FB4BA2D5886FE534A
-:10EC400091ECD0BF38D6FF3DB16E17CB1C7ED69667
-:10EC5000EC46FC26CAF5F754F87A1EF3C67F4FFD42
-:10EC60004EE2B8B08F7B1FF105780FA5A23DFF6D76
-:10EC700099E89A08AFD31079C80CF58BDB64FB7A5E
-:10EC8000C0A7BFD54AF355E1BD3333722DEDAF12A6
-:10EC9000C63F93DC54A1E0FCC5FE83ADD3EEBF18A4
-:10ECA00033C4CAC017CB5984F631C3DE8B7D6BE207
-:10ECB000BE8FB1BF18E3DBA9EB85B9A504F8055FEA
-:10ECC000B92505E9E69738DDA2F44E805BC5A7ECCF
-:10ECD00018199F4E433817E595BFD5487848ECAFD3
-:10ECE000EABDC7CCB03E80AFB64B12F1E3F6FB9263
-:10ECF000498F3113A763F3EA2437F2E74E43E469FF
-:10ED00005A372F1919D2F5A239F202C9A342EE37A8
-:10ED1000B8F833790FB6BB90CEF9FAC2613DAD2792
-:10ED20000E0CD83B3F93F752BDC4C7BDD09EECC676
-:10ED3000F5D88C9884EF3707FEAB8D01FE4EE9F8CD
-:10ED40003EB87940BBDFBD00FFEACB6272E122E34F
-:10ED5000DF090C703900335D45DFB923896D82719D
-:10ED60009B749217EDA3A6D593821D9C5F4CB85E51
-:10ED70001A04484D3AD8F795C5D67793EE6411EE4C
-:10ED80009B1A4C9B87E414AA3F8EFB2D86FB25E83B
-:10ED9000B71A3B150CE7E7A6CDBFFD33C2DD7448BB
-:10EDA0004BF786187F489F49D83F8E5F0A627C40A8
-:10EDB000F635CA876A161C2F713F0C96936B8682B4
-:10EDC000E8876916FE89F463E1B9C81FD6F27EB6FA
-:10EDD000149ECD67B97D317370CF2BB8CFB5D70CEA
-:10EDE000E5E2349B5BD75E7DFAEA187D5538670C07
-:10EDF0006E9571FFA6DA2571FBC7890BA6C43FD7B4
-:10EE0000533FDC8FE2F7C2F80AD785C2F5D936A1A5
-:10EE1000CF40EF91DC5DDE3381F41EEA25945FEA9A
-:10EE20007E16E519CA8F271D558B1C30CF92B4AAC8
-:10EE3000AF38A6F1EF901D8F9BA019C3F199A85789
-:10EE4000D476B8AF6DB18CDE2EEAE7D991CAE583EE
-:10EE5000225179C54FF57B36117C0AF1CBDADD05FD
-:10EE6000246F557F4C83F043AD10FE9B15C27FB3DA
-:10EE700072BB91B9E3FD55416DB941ACF74616E659
-:10EE80007EACFD501FEFB7A966212BD6A3FF069FCE
-:10EE9000FDDAFECD2C385B41FA0E7C668C7FCF7A92
-:10EEA000F97CEF1474DF61E67E9B99EBF6C8DC1900
-:10EEB000C5E79B5AE62D7810F5C49B7AF22FFC87A4
-:10EEC000A0938A17A3A3EAEB88EF24DC8F61BB072A
-:10EED0008D8497D3A08F0F0ABFC602DC67B6F9B343
-:10EEE0000A0B113DB6BC05D6E1F8DDF492B91EF966
-:10EEF00065B343A7E1A72A879ECAE4EF41BCB727C1
-:10EF0000935D0D689E8A7C543156D5936C2AFA998C
-:10EF10003ED483BD05E5A65B2D7E1C2F8C76019427
-:10EF20007708F9B5C361A0F1D472741F27F805BE44
-:10EF300043E3A1DFC517C707C168FBADC25EE4723A
-:10EF400061DBAA24924731BED531E2DB129F01FD7D
-:10EF5000452F0939F2122094F651FD662E47142EE2
-:10EF60009F5E3A3B89E4DE1B1FAF26B972695112DE
-:10EF7000334AD4DE2B61FDF3C6E07A28DF25FCA8F6
-:10EF80002F49DC0E0C1CB1D2380D06FF0EF42B34C9
-:10EF90003C37DE0314632F1882DF7F1AEB5F369352
-:10EFA000DFAA2185C3D9F0D21892933FD6079FF9E3
-:10EFB00001F9218C649F3524B953A9FE27690CEB14
-:10EFC000BB92FD8348CF6C23B71B1B0CA1223BE0F7
-:10EFD000F16490DBBF2751D0E0F88356B26B00CCD0
-:10EFE0002CFCFEA9EE4CCF26770C2FA71E9A4CFCCA
-:10EFF000BF4DCFE91638CCFD9A27F5BEB959503E22
-:10F00000F97CA907768EECA2CF1032008CCD5BB8CC
-:10F01000BDB64CE7EE6B45D9F472B247B3DF7C78EE
-:10F02000652DD637AF5E7713CAC1D1D633CAF37810
-:10F030007FED0516C9A3FD66FDD8FE107CF7C2E082
-:10F04000440FA947E60262039FD878DBD37AC03722
-:10F05000F2D7113DF1EF171D1FE78BFB3FD42FF8BF
-:10F060009D6690BF513F32C9DFB8B23C5299D3B3CD
-:10F07000F9A54C619F69EBEF48F55F40B9D6F4DD27
-:10F08000DF9F6825FC4648FEB11EEE1F3FADF72E00
-:10F09000463EB557870C4BE3F6B78634BE8E9619BD
-:10F0A000855E672143FCBA53EB2BAAB47CAE3EF5D8
-:10F0B000697C1F691DE2727C78BD4EAC9BAF185114
-:10F0C0006F71D70DECA7CF727F8621CD4DF533CF71
-:10F0D000860CCBA09CBF2E6458219EB82E00DF2149
-:10F0E00013CCFBF40E2B5FCF80061C67C57446F66D
-:10F0F000C80A19ECD0327CEF1E08035DCE3C6FE7E6
-:10F10000FCF527C00AE07B0913ED8C60B782DC7A3E
-:10F11000B1530AA15DBF64BB71AFB900D7B157B697
-:10F12000223D774B24B796745616ED80F2EA43538E
-:10F1300088FE29D3395FAE0EDA49FFCD147270997B
-:10F140003168203BFA19EEA783F1C91E6E804E5933
-:10F1500065C3F180F25BC30F416D9C6166BF90A7F0
-:10F16000FBE3E20B63E3E47A7F427FB0E3B4FC119C
-:10F1700050F50E9773CC9D89724E95C34687AF3478
-:10F180008DE4526126D217E8C9E5E44189F0DAC876
-:10F190005AB8DE10F23EFA5DA12FCEC801AE978CB0
-:10F1A0005BE93937AD80E8B61AF50DF9CDF9FE6E99
-:10F1B000343E989BA6137271643EB85EF041C35909
-:10F1C00016BA16BED7B08E851AA7F2A7752AE941DE
-:10F1D000AE0F4D229E61E2F18ECFD38B897A70986B
-:10F1E000DE4BD0779906A1DF049DE3FDD9A8EF6738
-:10F1F000AE0BCAE8D7CCB379AFCD4C8FD92FCDEFBA
-:10F20000994CEEABB0EC63632DE89FA97CC685FEFC
-:10F210005DD88FE3BA4A06BCEC81F7BB55FBD6C577
-:10F22000E7EB3270FED52B3E566A41BA0CD17E35E3
-:10F2300092CE6CC88F2A3E775BA15F19F6E3EB2D67
-:10F24000DADFC43A93E2FA57BD6426B97AE5B035FD
-:10F250006824BBC39F6F87F1327E65243BF4C24BA9
-:10F2600056D29F1784FE73AAFB7EB681E8D38A74B8
-:10F270004D476EAA1A83FE5326CD1F832250B5C375
-:10F280001AEDA3F9B3457DC1D0AD9CAF8CB45FBC82
-:10F29000620F7F13CB000F43FBBA05E98CFEF643E8
-:10F2A000B34B1F80F7CD3E8B8763DF5F8AFC6A9488
-:10F2B000EFBD15FD2A73E57591FB601E8DB9169B98
-:10F2C00011BA54E7FFFA97B741F9A3437A66443A73
-:10F2D000EF9BBD888D1D5DFEAE0AEA4F86E3D6CB5F
-:10F2E0009AFDDA7263BFB6DCCC9493E13879FC58AE
-:10F2F0009AD5796632C90ECF67C0DF4663CBD93D58
-:10F3000000AFF1C746D2470D69FE5D69E837D545C4
-:10F310005E433C1BF3CF4D453F4555FE9F28AE73E2
-:10F32000E5DBCC83705F315792FEBEB2C3EC0EC4F6
-:10F33000C9AF66C1FFBD79B554DFBBD3E896787D10
-:10F34000EDB40AB407E9DBF867D201FE9BB7CFFB47
-:10F3500088F64D68B543B917ED4BECF79C146C4734
-:10F36000FB713BD77BE7C17E34A1FE14EBA9591E8C
-:10F370009C6B82FFEC75D44C44F9A2FC59F121FD41
-:10F3800037E25071F6EEE1E8FAE47E9C1BD08F3351
-:10F390008EFC3887516E349AC2864A18E7BA3FFF0E
-:10F3A0008EE4F2CAD6A564D7C7EC5C23C99195F761
-:10F3B000F9E9FD2B3BAEA7799D8179237ECEECE662
-:10F3C000FBB995399620C2779D9DDBBF2BA19F2469
-:10F3D0000DC74B221E7EB3EB7A17D2FB378C7F2FE3
-:10F3E000D0CFED84DFD8865248FEB85B52D0CE6BCA
-:10F3F000DE7EFD4728B756EE963DA8C7D9112BF9FA
-:10F400003D56EE9E3371B905C7B99C568978EB9B82
-:10F410006393E9BDEC0B72FFC9D075F05EE9BBC622
-:10F420008DEBE4F86E2387CF6E7A1AE1BFEECF3210
-:10F43000F1BDA2637EB4577B0DDE89B8DEDCBBF67E
-:10F44000CD45BCFEA62E5B47ED9F95980DF1606FF4
-:10F45000CDC0F72B25C587EBAB7EFBAADA787BA462
-:10F46000334D267C57E6AFCB085B88DF6F453DD731
-:10F47000B85B4F76DDF1051FFCF236678CDF57CAAB
-:10F480003DB7CE8CB3379A77DD28F8013436E06982
-:10F49000A5C093317F5D117EF7F3F87FE5FA9622E0
-:10F4A0001E8FF9EBEB20BABE77F1F5F007D0F7B479
-:10F4B0005FCF7168ECFBD1F641AABFD9E461DE7D74
-:10F4C000168A1B7A719F9BE754A83ECFC9ED6CE565
-:10F4D0000F6BF7BF0DF0F7A7F98D4E789FCFBCA546
-:10F4E000485777C45605E6244E89EC1FB6CBC8EDC5
-:10F4F0004985FBDDB6A5B3A737C5C1998DE3A5D373
-:10F50000FAB43961DC0BEFFFE935C45F53DEB9A90A
-:10F510003C9EF63B8A4F590679DCD2E2F131E48B0E
-:10F52000E6C13A7657494C1E367BB8BC4E9CD77222
-:10F5300027DF67343B23344E753A5F67AABF77678E
-:10F540006B12F9F5763A8366BEBF0D3094E73795B6
-:10F55000CB3CDE22EC129FF09399BCAF308CC730CD
-:10F560008FEC190FE521EFA9CE3428BF5D3EC723EC
-:10F5700043D9E27DB26B2CCEDBA317F5E3C85FF86D
-:10F58000D6AC4AB24F6EF2CAF45D569F42FBF521EB
-:10F59000EFCF9D77C1776F66DEB4D3F08D1A50D66A
-:10F5A00048C721FC36DA018ABFDC19E75FBDD133D9
-:10F5B0002FED74BCBEF472FD8FFBF17E113718097C
-:10F5C0000F2569953311BFD77D99D3E1E367F9FE24
-:10F5D000E36333F763ABED3EB6723D53EB94841DAA
-:10F5E000D89F87723E5AFE5AB1260EEC34F4E7E1FA
-:10F5F0003AFBADA41D6775978EE2B3ABBA18C5632D
-:10F600003FFEFE8B79286F3FDAF762DED238F812C0
-:10F61000FBA9CF5B9D5ABF94EA87748AB8F4528FD6
-:10F6200091FBFB46F143AAEDD976BE1FBB08D21D64
-:10F63000F94EED77B13EC98B76E545662279B67411
-:10F6400050F835BDDE4227EE1FD4FE09E36F41FEC0
-:10F6500001B8A40189F6E7C9251192AFAB4CBED71A
-:10F66000C6B8312FC54BF499877494905FBD069C42
-:10F67000B722F67946C5D788F45CDEA3A56396D396
-:10F6800026E2944EA2BBA1C9A2A07EC8E810F2FA5D
-:10F690001B3ADABF18B25D16944BD715257562DC9C
-:10F6A000DD99943215FDE6B9D9C5D43E50C5F93A75
-:10F6B00090C1C86F95C55A2492B736EEE7CE99CE61
-:10F6C0006C98E7F1A293DB832EE6D92E933DD82FD9
-:10F6D00091BF5FCC5F95EBC82F28E73E964CC42FB7
-:10F6E000D2A044F69DACEB5F8CE38EC63FBD09FC17
-:10F6F000D3FB0FE69F3EF57BC3F8C74F71BAA52E2B
-:10F70000D3C8FC23FCAA5FB8FD6871C26F98543F50
-:10F71000B384F3AD15E3D59A2C21792AC98773F107
-:10F72000FED45D6067E27E448D2B8EE958E2E6767A
-:10F73000FA5018F7E5C9D79848CF7D47375480F677
-:10F740007C629C11286B47798F3286FC8AAD55BE4E
-:10F75000D36971FAFE08DF3734DDE7A5F7B307B9DF
-:10F760007E6F2E3490DDD93C200590CE4D3E43D0A7
-:10F770005440719525A4B71F32BB799CC4DD4E71EE
-:10F78000926FBB791C25EA470DF73D80FC566F212F
-:10F79000BF4362BCE585BFC8FCFBE3197DBFB794DE
-:10F7A000C7777AE7B9C9AF911847635DDAF5ABC699
-:10F7B000512E5A0131F0BDA59BCD44876C99E39938
-:10F7C000A59AB87E192E07C85F9B315D1046C43BD1
-:10F7D000A2EB1A240396B345BD1A9FB196F80AD03E
-:10F7E000C2BD3DEDB93793D2FF967C86D6EFFCD5EE
-:10F7F0007C8680B116F3194C683D8B7A041BF4ADFE
-:10F800005AF69ADD18BF89D52B60379A0624F1BDC8
-:10F81000E76F9853087890D4EFAFDFE4B550BC5849
-:10F82000F3BD78F89484F1F530BEC52DDA070ECC1F
-:10F830009BA3505C52D47FD68DF91B5BF4DAF108A0
-:10F84000A5A23F16D4EF1DCF9CFB9DCD3931BD0F36
-:10F850007680297D5A4CFF6FFCA0B6E72AF856B295
-:10F86000EDB201F5AAAAC79B9D3CBF2171BD3AD25A
-:10F87000F97A05FBD5914E7283DBB5B5223E09F6C8
-:10F88000EC5C5C5ACDEB7C0CE393602F64A4631EAC
-:10F89000C3FBE7CE1C45FA2DF898ECF9E64F15EEC0
-:10F8A0007701BB03ED7393E07336A0277DABF2C104
-:10F8B0006A217F7AEDA0EF915F8F48D302C4172DA4
-:10F8C00079B7000DEE4FF7BA697CB1EF4A847746FD
-:10F8D0003AF793341757ED28C2F19F9218EAFB4D7F
-:10F8E000C52733D02E691EFC3063795CBF55038F6A
-:10F8F000121E56EDD78F38FF19E9DCBE6C3AFC3C7E
-:10F90000F9073F0E4AB496EB9560F74C28D7D7EB32
-:10F91000D04263E5C125B791BF7F91818D87F9E51D
-:10F920000B7DD4BCFF2B8199B83F837F12BCDAE9F1
-:10F930005B417A6FE7229305E30ECDC54BEF263C82
-:10F94000D892BC88874DC55559F89DA6BAB9368A54
-:10F9500013807D85F54DF7DD4E7E1315AE4D03FA10
-:10F960001AB4BB2AC0CEFA11C09DEB985FE381F5B3
-:10F9700037463E587A8F05E3C223CBDF7FC9E0F4D8
-:10F98000EC947C819BCBC94FC8E2FD7EF903DC9EE1
-:10F99000AB4B3768FCC275E9DCCE9C15189A8DBC60
-:10F9A000F7B2124E46BBB799793FC1FD25F359DC3A
-:10F9B000FB884E5C8E38DBDCE43F3239C3DFB90AAA
-:10F9C000EB6729B47F604AF811FCEE856EA76713D8
-:10F9D00013FC8BE5FB4A822847FF39DDBF18F9ACE1
-:10F9E00042D88F170E5F5F8A7E36D53EEADE630E01
-:10F9F000621CB0DBEAFE6E0DCAC13F283CEE6D8A88
-:10FA00000CCD467AFCD141E3769B83DD48FFC0569E
-:10FA10003DD51FB6FA5721DF9CADAB29A2BC1B4BCD
-:10FA2000A008E3BC7A670F433B01B60BE44F3039C3
-:10FA30007D0CE3A1B3034B1409E57C82DD315BE46B
-:10FA40008F92F084F755428C8D072E3863A225D013
-:10FA5000F9595ACC0E79E34F0B157CA9DA273A13E2
-:10FA60008F67552F4A6232F2FD86C86B3AF45F3BCE
-:10FA700087C87E6DEC97E83B8DC5CF513ED81A9173
-:10FA80007714CDFF51C2940FB53E3D59E8F14ECEEB
-:10FA9000EF6C88F6CBEC00A7276361CA938AED234D
-:10FAA000DAA99D3A9E41F8DD1B85DF053418D53F64
-:10FAB00094AEDA07EBC553CDEBE2DFDD260D7965B9
-:10FAC000C46BA9A4F117ABCFA7D2B97D987A2C3219
-:10FAD00017D76FE4B09AA7C9F330774C9BE441D3B2
-:10FAE00069589EE6C02773916FC0D0A6F5DA34F04E
-:10FAF000C5F234BF2FF60DFFEB799A1EC9BB179ED6
-:10FB00003F4AB773BF959AA7E9E1F853E36C89F9C7
-:10FB10009917B2420ACFB70AF7ED43FE1C30521EC6
-:10FB200057EDC0EBEFA17EAC35B17E8C4326DA19E0
-:10FB30006DB6AF0C22DF5F3C7FA6EF418679BA2F0E
-:10FB400078285F23C17E48DC27ECC52659A3DB7BE0
-:10FB5000EF46E9C9EDBD68F97FDDDEE3F67C601FA5
-:10FB6000CF0F50E579B3D89F5DACBF94827AE6445D
-:10FB7000149E843C86A7441EC3E0C8790C8AC8073B
-:10FB8000027B3D407C7290C775DE783A99E4C725C8
-:10FB90009BB217EDA5F3D6C83711598AB0933A8FA7
-:10FBA00018DD282F40DE91FC0E1CD4F3380DC66DF5
-:10FBB000308EF3F24411C711F1A29792C96E6948D1
-:10FBC00071A7627F354EF363A16F1A92787CA62BE2
-:10FBD000D97F397D84B8CD1E617FED81A16C38DE7F
-:10FBE0007B4611C7060181FB9D877279DC41C46D9C
-:10FBF0002E8AB8CDA9625DC8C0FD10E4A77277292E
-:10FC00002C0BEADDEF99836EEECF32E940EF2F53F4
-:10FC1000E3362F733FD532119F39B5602EE5072D9E
-:10FC2000C7FC7719FD18DCCF1CCDC767361DCE6722
-:10FC30000D888B9D28620280F56BE0B5A493D09E61
-:10FC4000707742998C656F4F0D7C7769A78EF6238C
-:10FC5000CBBAB4FEF22B9BEEAE41FDBDB193C71FF4
-:10FC6000035D12E9EF65CCEB427B43E587828C3480
-:10FC7000A273A053E7C5EFCCC8E0FE04407D90E638
-:10FC8000279E9D7AE1671770B4335D089F3A893FDC
-:10FC900037DA949A11F5B218AF53DF62AA443B36B3
-:10FCA00057477EDE2B06EF22F2933A8A886E9DD666
-:10FCB00096AE1A5E4F6BE58A39E2A3FA6B156EE8D1
-:10FCC00031B703E564668688DF24CC77798FB69CEC
-:10FCD000187F5815D4969731FF842C3C87B05FFB72
-:10FCE0003E3383CBA92B9B0A849FDF437EFE4EBD10
-:10FCF000FBDD029453DD0AC9C9F61C8E2F5D2E7FF1
-:10FD00008EB5572F22FBC00E7605C1CBE11F7BAD10
-:10FD100053427DD969E77CF93F853B11DECA8C22CD
-:10FD20006E27A07187EBA85B0A727C71B8BFA8BF71
-:10FD3000626986F01708F9132DFFEFEF37393F7628
-:10FD4000CB62BDD948FE2C15F1C65392E7E910BE2F
-:10FD5000B7805D00702FEB96CBD03E99FD150BCD93
-:10FD6000A3E96573D008F58DEBC279B88E9AAAC263
-:10FD7000452D23E015A15554B905ED963A617F80D4
-:10FD8000EBB64B1B871A1E57F47E2B231DF721A7BA
-:10FD90000EBE8EF43E6826BD04FF75D488FE8EC369
-:10FDA00005642F4D4DF5B765A03E4F0AF57DAF00B8
-:10FDB000ED136E1F350E1AF7A0FDB7B4537B6E8698
-:10FDC0006DD6C6B9589783FC19AC57FB1ECFA768F0
-:10FDD000FA0D8B7B713DBFCDE09F8876DD755FE6C8
-:10FDE000F1F5F3AB740CE9BB4CF6AC403972DEAC08
-:10FDF000B5BBCF5B39BDFAA274F614219DFB46A5B5
-:10FE0000B3A708E9BC4CC7FCF1E334229DAFC6ECB4
-:10FE1000734EE7F3CF5F5384743E77F09A22A4F3D6
-:10FE2000367D8F17D7CD930EFF5EC4CFE9393EB232
-:10FE30009BD4BCC92FCA8F8732B4FA305AFE3BF923
-:10FE40003F46D383A1281C5A3DE834B873501E2E78
-:10FE50003519FFAA3EC4BF11FD692623F9235EFEB2
-:10FE6000D3E58751BF050665B23FD4F15E56FCE38A
-:10FE7000D05FF0F27B2E4F401A7DFC066157B94CE3
-:10FE80002C807E0FD5DE57EDC64479FC0B319FD315
-:10FE900019DE1AB4B355FF6CBD18D314BCCCEDD326
-:10FEA000A724F2BF9ADCFD3C7FFEC8121BFA67CF85
-:10FEB00006B93FB6E9F952F2D7AE0ABE12C2FC2724
-:10FEC0003628D970DFB0EAA90F53309E0DFBD0530E
-:10FED0001971F19539621F7A36782A05E3DEF0FD53
-:10FEE0006AFC7EB2336240FE6D82FD1934614D4A78
-:10FEF00084CE0D353919E9FBF201ED7E4D8D4FEEC3
-:10FF0000F41948DEED1C9482B83FCB30F80B7250E8
-:10FF10003FB11CDB99E4D87AF924C36BCB9C161F44
-:10FF200017F65ECE88CB570AEF48253E0CEB999723
-:10FF3000EC801D56219778BCE63F77D9833C7F89BA
-:10FF4000B7FFCF600195557DBD429CC35B21CEE1DB
-:10FF5000A1FC0E25C8EFF87234DEAC9E3703791E83
-:10FF60001A29FE1D97B714DFBF8945447EDE674618
-:10FF7000CDB8D17C9D965237C0BDE66B163A67D896
-:10FF80000C7CDD5A16E3C3063115950F9B845FB7D1
-:10FF9000B9FE24ED039AF17C05DA551ECE870DB02B
-:10FFA0003FC2FCCDC475CBFAB5F98CA3ADE329995A
-:10FFB0005ABD122DFF83FC98D333B5EB579DBFEA92
-:10FFC000078FCE7350E2EB2B615E89FBCA44FFB50D
-:10FFD000BA2FFCA272EDE64CAD5C8B96FFC172EDC0
-:10FFE0008ECCD1E49A363EF037CBB5C4384121F7F8
-:10FFF0007F639C00E3B6FFD338C147EE9E0C1DCF54
-:020000022000DC
-:10000000C3D7C44FBBA4969B4CE330AEC8E3CB8DA3
-:100010005623C56113E3AACDEEB9228E38F4CB196D
-:10002000A8370FE919EAF37ACB4A8A5736CB070C7F
-:1000300078A470583C51394A76FBDF1A575F9F19F4
-:100040008DAB17605CFD15CBE5347F1C3DAB4AC022
-:10005000C02F193DDF68B3A053B2C88B30290166A9
-:100060008FEB3F5ABFDE4C6E27BF22F2635C069EC9
-:10007000C7BEC50AFB3098BF4BC7F377EE4FF76D8D
-:1000800043F9687273FC3E71F8AB0CCF1D3DA1EFD4
-:1000900027391268B478501EAA7E17757C45F80F70
-:1000A000BE28DFFF2081EF7FF077E6FB447C0CA8C1
-:1000B00072E76F8D876D07DC68D607A3B8D75B182A
-:1000C000CF2918CEC7A38D331A3FFF34D3F75A2652
-:1000D000C947EF54CACBFD82F226B93C720AFD3BF8
-:1000E000EC90D18DFB0D933897C13667893C4A4F10
-:1000F000451DE513F3730DEAF98FD1ECC20FA3721E
-:100100009ADB851F8E2AA7FF7B76E1030EDF299CF1
-:10011000E7E94A6F11EACD8D56801FF77BDF378EF6
-:1001200078CE423D0F00FCC4CF9B3CCBE3E0897C02
-:10013000F58704FDF287BFB37E194D9EEA5D2A1C48
-:100140007F67795AFFC714F47B8E3E4E80E0A8A8E3
-:100150001AF28AB815C3B8913A8FE6219E7F96218C
-:10016000F2AAD4F7116117DEE9F266BAA0FFB9F777
-:100170004D26960A2610F218DA633E0BC5039AFA4A
-:10018000799E48D33A46715FF51C65D3401D43BB49
-:10019000AF3FCD5F8079601B3FB004E454F4932FF0
-:1001A0006068EF5D789F971BD2FCE3294F6C5D5828
-:1001B0001377A8F8ECF206F46700BCE41F708AFC21
-:1001C0004C15BE3A179767EAF32681EFE8BC9C1CF2
-:1001D0004ED62F07D14E4C760F911FA9E91037DE6E
-:1001E0002A642FF9EBD91A079D9F683A54594AE7B8
-:1001F000CDFBCDA568E756FCAAD686FE8973D73A13
-:1002000029CF204F0EAF423BEB9FD3FDB3105E6B67
-:1002100079701EDAA9F960A7A2DD7BEEE0BC527FFF
-:100220009CBF7B1BFABB61DC6D56AD3F9B99789EF2
-:1002300078FD5E9E077CD8EA9F8BF8DD66E6F006C7
-:10024000B68ABC67E1E74E5CFFEABA8F9E73BCC317
-:10025000447169552E6CD3333FEA3D559E94883CDA
-:1002600039C007CFD31BACE3F91EA26C716AF3153A
-:100270004F67CC2941784AD0D13B0DEF518848E8EF
-:10028000775F2EE2F0D78B7C0A357FCAA8F8BE8E46
-:10029000EDD9BA9A58FC7D2CF617F177912793FC8B
-:1002A00029B79FC7DA0CC43756585FE41F01BE4117
-:1002B000FACC8A0CCDC6F34485BDA15988CF973FAF
-:1002C000D5113E94BAB7287E928A648371C66D0EAA
-:1002D000774F403F8AED17D7225DDC3DB62A445D5B
-:1002E0007F9AAF91E0505A8A715F59F5AF7A9E07B5
-:1002F000782499FC03BD790D940778E103E388E73E
-:1003000046D46780ADA7BCBFB1033F273FBEF59081
-:1003100034623E6797CBC2CF0D078628BF8CCD7263
-:10032000123E9423BFA2B8AFD2AD9007A353EFD52E
-:10033000E139A8403B23FFE5F85E9B0EE9922FF2DE
-:100340004B2EBEFC5F53FDB44F51FDF6419E0FA4F2
-:100350000F6FC07D97D21EFE32AC60D678C8AE6BF0
-:100360002AC1F1224D3CAF3D99219FE40F8C5BFFE8
-:100370002528E777D99884F2E7A535F9E42F857920
-:100380008E1F619E77BB78FE8E722459877A4BD977
-:10039000CA28FF50B1675411DC8F4219C65923F89F
-:1003A000468D4702B82ED44777BAFCBB11CFD17324
-:1003B00032AD49FC9C8C3877696DFDE0593C7FD2A9
-:1003C00067E0E70C8FBD3C7901F9EDBA1509E970DA
-:1003D000C5BE24DF06EFF78B756B558698CD128F5F
-:1003E000FF63946F39F608CF4B53F49C4F946EE73C
-:1003F0001EF40B7E9AEAA7BCD26B3B4332C5B36CAA
-:10040000A71FA971C7ED6BB6733DD2B49FEFA713B9
-:10041000F7319FA73F8EBAB47649B4FC0FB24BDEDA
-:100420004AD01B7FF3FE8469F77589F649E23E6E78
-:1004300098DD9D30DE68768A9AD75115FB0EF1C3A0
-:100440002B56D50E0A68F25EAA2CE2DC9B493BFED5
-:1004500053224F47CD83C9E870B7635E79E4DB8CE4
-:10046000FC6C6A3E4EA08AEF1B023A139D8773B163
-:100470001ECAC319C3429244F67F98CE7566623E87
-:100480000EF47BDF3596E0DECD3C5D32C943B784A8
-:10049000709B318F83F236833B56E0776EB1D07715
-:1004A000CC98C7713586E2BD3B507ECEAEE77188F1
-:1004B0006CD0B7C8B7D9859C0FCD8B783E879AAFE3
-:1004C000A1E657A878A812F8CD9EB0A200F707DDE4
-:1004D00092FFFBEA79DAF873D2D1F3D1ABC6D279C5
-:1004E00093E8F9B94226EABFD839E9447CAAF91D54
-:1004F0005536BF2D2B7DF87959953FE2E84670EDD2
-:100500003CC2EDF5AA7A03C17F71D57CF2235E5C13
-:10051000A563B86EAA068D9CDF12BEB7337A0F466C
-:10052000D04CF75D08BA7F9EBD0AF42C463FEDB172
-:10053000B69AAB4F036E8FB7F9E879D12CF5CB574C
-:10054000D179C6C528992E67EDACC57B0A2E5A23F2
-:100550007978CFC1E5EC076FA4727AE404965376FC
-:100560001EBA11EF3DB8383ED287F71E14EEACE448
-:10057000F5C883D98C5D9555716380E6CDFD4EB38A
-:1005800063E7B3CB113F8D2CBC6188FC3B3C7F1FE4
-:10059000F3FD900E2E8B81EC1997C8B364D522EF32
-:1005A00012233050EEC82AA578B585B90F0D617DAC
-:1005B0000E3F2704F5C4BF1DE3B95FD824E8CA7213
-:1005C000543F523880F2A9A3C04EFDA372F490317B
-:1005D000C8FD59FCFBEF3C3F85E24B6AFE2863B641
-:1005E000DC855328DF445356EF37608A2D17ED859D
-:1005F0000EBDB04B45392DD55F97156717BD33E755
-:100600005B25B80ECEBFF04021CAA5EB0D60B78FB9
-:1006100020877E9DCDE5D045BDA54B023BEDE7296A
-:10062000FEDB719CF79217CFB5C3BC16A5551AEC2B
-:10063000086FE0FB32CAC574416FFB420E9FBDDA02
-:10064000272D87713BCCB07EA17FBA5FF1529EBD52
-:100650007FA1740BC0DD2171790B9D52695F52EC53
-:100660004EC5FCE506715E5216EB7E46FF5619ED4F
-:10067000E977DB06662A8531F87E2EE2CB3F2F60D4
-:1006800077D68DB0DF6DCDE2727B81EC9E827CB43B
-:10069000411A78AB360BDFBBE9FD9C94D672CC3B9C
-:1006A000BE3EB9A51CF5CFB0F7A9F0BE24AE6CE4F0
-:1006B000ED1A4C913C3C9FEC4DF6AFCBC2B8D092BA
-:1006C0000F296EF9CDEC774E60DEC13BFA9ED92939
-:1006D000A85F0AC4B97EE1377C6D82EA3734F1F253
-:1006E00064EE378CE6734DE1F964B50BF939C55A00
-:1006F00091AF30D7C6CFF5CC2D2FF074008837B12D
-:100700008882726FEE7BBE14DCB7B385FE72DF9415
-:10071000D1ED19E6D2BBE3D7EB3C775C19FEDD5097
-:10072000AC2DDFE8D1966F9EFEE709F1E53DC9DE0D
-:100730001D38EF1F4B3CFF313083D9689E4E298016
-:1007400076C7E417B3C5F94E9EA7F74F625FF4E290
-:100750007446F519FB4D7B31FF5DF533CBA27EB2BC
-:100760008B99F21DFCBE00D4571149E4FB39299640
-:10077000C25EB8DBC6F1076D0D30CE0B4BDCB43E6C
-:10078000322C3AF6655C43E526B2432AC69892902D
-:100790006F8E09BE53CFEBAA7C58A1301FE62FC045
-:1007A000A717E2F31DBDED28FA97031F31C6E955DF
-:1007B000A950FEA1F81663ED547E4CF0F7310153B9
-:1007C000E0DB0AADE757AD06A2A7FC13790FEA09F3
-:1007D0008CCDA0DFF8D2E649049FBA7E6055173A67
-:1007E00033C8A52DC655740844B1B02754FE460B36
-:1007F00008DB8DC1FF2C203E27791399C6EF4FF8F7
-:100800007901972791AD0E711E8CC7CB724DD171B6
-:10081000BD386E56F43BFCBC51862843554807F35F
-:10082000FE4D560197CB83AFFF81F4B2C5E3C7EF0E
-:1008300018524C744E465D37B6CEDFBE553B03E7CB
-:1008400059F40D9AE77CAB0DE7590C6CBDC8414FCC
-:100850006F1A8DC7D78F9CE471E33AF94ACDE199BD
-:100860004A1CDF40FF46DE3F59DBDF05FD1D71FD01
-:1008700053A07FC9F0FE4F594D21DD541CA7C21D66
-:1008800026791EA2C9CC17F3923378BFF9221FB480
-:100890003005DAA3BE29D6E66BB0E91E13BFAF431D
-:1008A0009B9F71BDB42E0BD7D53C53E36018C67B1C
-:1008B0005DD0ED7A9DFF77783FDDEB8B8B8EE37A11
-:1008C000AB310515DC0FDDC0421B9098172BFD4F97
-:1008D000D8C7913CF80BAE8B26D93FC101E5F3FA9E
-:1008E0009EC2BB0B68BD7C96356D38BC2A5FA8F0F4
-:1008F000227F209F45F92301EE289D6EEAA744B68A
-:10090000DD60F7E053B583186BE1F9C6EEDCD8BCC7
-:100910008089E69A5A0AD10E79BD3D4072E37AFB8E
-:100920002394D7F4E7317E6736C0B5E8AA4FE85E76
-:1009300013E65A3201ED7B80373D3BFDFF1DBCAA1B
-:10094000BD372CDFF6238326DF76B475A57EB799F5
-:10095000F1FB69660FEEA1FCD9E685160F9E836850
-:10096000C6FCCF728A2F911D87E784E99E13C924A4
-:10097000ECAE2F9A97CBD7616FA39BECB7A81C174F
-:1009800079E5BDA51CEEDEBBDDEA3D27DCBE5BC222
-:10099000F83D29EA3D27CB6D54AFE69FF7EEE17EA7
-:1009A000BCDEE727D07929B0DFC85E60A93A0E5FC8
-:1009B00081F67E15FC933262F9D2DBF4DCDEDCA931
-:1009C000F354209E77621CE8AFC47FBF9AADF59BBD
-:1009D000A8E544BFDE930EFFEDC817CB4BBC7912E0
-:1009E000F0CF3203F7DB017FEDC2B31535ACE5295B
-:1009F000BC3F701E6BF9856E1CF1979FF86BF22758
-:100A0000FC5EC1187F2DE1FC1520A1A4F25794AF24
-:100A10008A13F3ABFCABB17DAFBDFF574D68A70E9A
-:100A20001A892E6A9E5CE23A8E83E7B49EC3E394F1
-:100A3000658267ED48F07C113E8FE7AF4CC6F979CF
-:100A4000347ECF5458C05A16E3F73DC9FE76843F32
-:100A5000CAF71BF87E6418DCB285F8E3D6DB649E27
-:100A60003F9ECCF515C62BB2E0FB75E2FBB7767363
-:100A70003EBAD56A20BEAB1B6CA47C2256CDE30ED9
-:100A80001EF81FDF077A09BF8B44BF85CE523DB2E7
-:100A9000ECC25A6D7C6291458D7FF8F4B81E6F5D93
-:100AA000A83F19AFEF17B1CD9F60DEDB228C63A8A2
-:100AB000FDE0BB8F6747E31813308E715CECD32FDA
-:100AC000027F23FFBF9ABE72D7DDC0B7131E2F2946
-:100AD000437FCE9C8C554F6D85F2F7764EA2F2ABDC
-:100AE0001977DCFB0ED6F71551B91A2F71C1FD46E7
-:100AF00023EF5F5C71DBFC02F8EE71B31817D715BA
-:100B0000EEFB92FCBD75D0CE35756C19E623560B05
-:100B1000F970F16E9E0F7FC355569EE2B9D24D7E9D
-:100B2000A3EA2451FF753EEE5BA5FF568679A9D551
-:100B300063238BE93EC6B21F4FC2F271E993C5230E
-:100B4000C54D26174BA189809F6A076F5F5BF6FD35
-:100B50006CDCC75757F1F2644F65F738ACD75D5A74
-:100B60003CD2B9D09F8AF5143DF724D6E98BDE0F2D
-:100B7000E99C93CF2479708ABEE91FF27B892C927D
-:100B80000DFD8F3E6F81827ED2D95E9EB758656A19
-:100B9000CFC2FDEF4D7E4339E69FDA4CA5C7D1CEDB
-:100BA000489D5E390DE93BDBC4F4A89780CFFF85F3
-:100BB000F8FC9A4FF25290B92C5A3E57F9A84EE5DC
-:100BC000EF6A2D1FC3FAFCD7ECF4CF97AFA3F13136
-:100BD0007CFFDFB1FFA22F69F54A74BC84F596381B
-:100BE000FE687200FFE2E55C0C8E7E5A573998155C
-:100BF000360ED75D8FBAEE220887413744E73EF2C2
-:100C000025CF243AF0388AFE57E1CB05D9C6CA86EB
-:100C1000C3857F8A6A9771086CB60CFC2EAF877EFD
-:100C20005EE688C105DF676350EF6FE0F0EC965A2F
-:100C3000B8DC1076B1BA3F6E52E73BA09D6F45120B
-:100C40003FEFEC42FF05F673964EFA6B70370BBD23
-:100C5000B9D0E47BC80873B8C5BE8CF8E1AB2CF002
-:100C60003CDA27C654BF634C3AEEBB0247C205E4E8
-:100C7000CFA5BC01A077DA9838FB44852B111F4D16
-:100C8000A3C8C344B813F110A3CF10D957EAF9A9E8
-:100C9000E8BC12E6D361E5EB3532CDA8DE5F528CBD
-:100CA000EBE26D699227DE9E7E3B416F27C2A5DA9B
-:100CB00011AA5E55E1417F11FF7EA41DCF90DD3862
-:100CC000662CD99D2ADF640AB80C3A69C438EA8DCB
-:100CD0006374AA7F4E43C7C4734E2ABED4BCA044DB
-:100CE0003CA9793DC3E23509F1C8D1DA49603F8FAB
-:100CF000710CC79F1AEF7144FD5C029FA512C93F9A
-:100D000087F073CDF6F0F309B5ADFC9C7C6D0D4C0E
-:100D10000070FFB6F01FA8787EC8EEBF8DF347784D
-:100D20001AEED3BF3BEF698A73A8F7C825E267F9CB
-:100D300028F8198DCF47833F2DD5B712BF7B5E1A98
-:100D4000AAC0CA2DE9E2FE41E62FC07560B715546E
-:100D5000A21F02E4EA679FE1660EAB80AEE50E7F5C
-:100D600033F2F957996F0ED2D751E3D773FF3A2375
-:100D7000FFED5AB1DF9A23F4EDA55D32C507AABD98
-:100D8000131F9B8576E21B7A16A4F5EE25FDB94666
-:100D9000C07F099FD8DEC2F5EECA377F54012B868B
-:100DA0004DD8AE8BDDAF00FF26069334F72B4CDE1B
-:100DB000EFD094A7F4676BDA5F353056535F1A9A19
-:100DC000A4A9BFFA8D324D79DAD04C4DFB6BDEAB66
-:100DD000D2946784E76BDA7FE9EC024DF9DAC8ED6B
-:100DE0009AF6A7C4BE9805BC43C51978BF389FEFD3
-:100DF000759F2ED5F4FB6DCADC37900FEFDACCF37C
-:100E0000972B01339A7B267AB85DD102FFE374F504
-:100E10002988AF15606F63DEF2CAED5ABBA37E70FE
-:100E2000EB0694A5897915AB594B155E49979857F0
-:100E3000516D5BA243BEFBA731C2EEB8865D23EEC7
-:100E400085F9AB742D62E3FF5B7435BAB47435BBBE
-:100E5000B5744D2ED6D2D5EAD1D23575BA96AE76C6
-:100E6000AF96AE69355ABAA6FBB474CD5CA4A56B37
-:100E7000965F4BD731F55ABAE6B668E99ADFAAA56C
-:100E80005F4160B5965E09F456E5E5B8AEB59A7671
-:100E900051BAFBEA291F667CCFFD9A7155BA07E06B
-:100EA0007F9CEE2D94AFFEB7D29DB120F95F13E980
-:100EB0007E3681DEA0AF3E42B90076C6397C2E9ADE
-:100EC00020EC79DFC876862A7FE2F57AFCBE75349D
-:100ED000B9344C8F897DECA87A2C611FFB3E66F1FA
-:100EE000907DB499FC3CB709FEBC8CAF66A01FF5A1
-:100EF00007A49FDF0740A6035CEF23DCF09DF79378
-:100F000026939FE10E16D2D3BDBF98890883DE8950
-:100F100089C932DEE7E3A6E732A1BF970B3F8437EA
-:100F2000D99F92C3FD0FF919F8DD9C217EFFF25B7A
-:100F3000695FE89E8293E887079D721AFDF0F0BC16
-:100F400060E6FC7046950F5EE676C6E16DE96C8959
-:100F5000F4323A7C703FBBF4AB12C51996FE9E3F4B
-:100F6000C7E770BB37F1D9D1AAE28DEF876EC871A0
-:100F700093FECD61FDC27E637ECB381A87FBCD9F89
-:100F8000E4F78F3E2B3165BA838E49111D334D1C1A
-:100F9000AE67F5CC84F87B86F9DD8897EF28209A38
-:100FA000789EFE24E487A5BF7F672CFAB164D975CB
-:100FB00013DE2F3D1DBF0770CCF95A8B847EDD4CAC
-:100FC000578B847EA361EF0FDD2FE1F9C26899F1A1
-:100FD00076F8877850FD73C53A1EA78EDCCDF717DB
-:100FE0004F7D9D91DFA9A3355019C0F8940C0607D9
-:100FF000E6B1E8F979E41B72B8DF2D8B0DD1BDA6FF
-:10100000EC3561178AFBE04B44DEFB0511E759B173
-:10101000C7C4304FA2E4E05107C67556002D875073
-:101020009F297EBA5FA364C7AB0E7ECFB8DE8EE782
-:10103000D8543D3A3ABD1576262E7F1CE8D8329218
-:101040001E5F93CBE3B31D6D35B3302EA3C2F360A7
-:101050009B7716F287AC7818C693F0DE9DF8FC33C8
-:101060008313EAE3D6AF62A9D194F5161F5D66B18A
-:10107000A1AD85F84C2FEE07DA98B3D616FFBB0169
-:10108000AB7374E21EF200433B9B8B7A7C2A675061
-:101090003EFC91F17DA8D105E3C4CBB57BF358BCF0
-:1010A0005FB9ABCD47F06E90FC7E1CC458C842E6D9
-:1010B00014CC5BC0B397F07EC7F56F601E8DC1BACC
-:1010C000D613728F8E37A34BB9122F971EC801B952
-:1010D000941C934BDF6D3B4B78EA685B44DF037CE9
-:1010E000318C9F05B2B87DDAD1B684DEEBC0CE423A
-:1010F0007E7A65C784A36EA83F01FFF09E1CA39370
-:10110000C3C5CAF3483F2D167C803EAB5CE09F13FD
-:10111000AD7AE2B37B722D415C84F7BC3DFE28DEE4
-:10112000F369005E92FF06B8A3DF11783208B904B4
-:10113000FCE4C3F566C856C8FFEBB02D203AFD7736
-:10114000C753F16B3033BA87C6906B21BFCD17857B
-:10115000F37B39097ABE3C8FE4E83D022FAFECE027
-:10116000794727EE6564BFDE731FF7BFDDD3C8285C
-:10117000FF9BB5C25F458C6F54799D8E3781C0CB84
-:101180009E361034458C3DDC66C293572C19FD64A5
-:10119000E36274ECF12A7674C76FAD76D6E1F3E1C1
-:1011A000E9A77B50AC6C99F5BB217CA28F1BBF6F6C
-:1011B0006B6141B43329160BDFB7D74319BE9F22A9
-:1011C000EA53FCBC9C2AEA5317F172AEF739A91A0C
-:1011D000014B8883E45A1CF30A51EEDDC5F8B95B74
-:1011E00071EE7EB790BB632C8EBA6AACFF1AA37CFB
-:1011F0007CB5FE71519F6539D9350EE5F2426DFF20
-:101200001D020F9996933DB3295EA2AD57E31BE9EA
-:10121000964B6F50FF126DFDA3A2BFD57269683661
-:10122000D6176ABFFF90A84FB67079C87CFCFE54F1
-:10123000B5FE3BA2DE8CF5F87D8FB6BE5B7CBF436E
-:101240000A127DE88E585C3FE9DC5FDAD7C6AEC58E
-:10125000F5D3D316A175F470DBA7442709992C3D6B
-:10126000B6AE6CAD6CC4F3E092906729EEB0D73B9C
-:1012700082BC53EB1D367EDE5D7619888F8C16217D
-:101280002FC43A8CCA0BA9C5C3998BFBB13F8F9F62
-:1012900061815D41FB220FFE909F73EED5317F9CF3
-:1012A000DCCA6E4862FEB8F6AEBB1C9A72C6D7B2F4
-:1012B00035ED9D0BC76AEA2DE59334F5CC9B4BEBDE
-:1012C00065ADE0ABA492324DBD7A0E9FF5E46AECB9
-:1012D000677DE14C4DBB4BC56EFAFD9033F3D4DF17
-:1012E00019F198502EACB58ECD44BDF34CDB74345F
-:1012F000B2D9B3B09EF0E8D4013BCF2F3E807159F4
-:10130000B4D7DBBCF47E1FD483E5C29E84F5E686A9
-:10131000F67BDA6C547EA2CD45CFDD6D6E7A3EDE73
-:10132000564CF53BDA3C547E0CC6C7E7A3300EBEE4
-:101330007FA4AD86CA5BDB7C54DED2B688CA0FB50B
-:10134000F9E9F99DB67A7ADFDDD642E58D6DADF427
-:101350007CB02D40CF8EB62EAABF46D0FB8038C7BA
-:1013600078A0929F4B4EA4E3AC5C49732F983596BE
-:101370003F302B17F307FAC39AFBDD71DE349E99D9
-:10138000CF3F71BC3A1C0FBE3B890DB527F3754C9E
-:1013900071C7F1039EF5C9C0EF635A381D0A0622D2
-:1013A000549F55CF695127E065CE00CBA9E0C750C7
-:1013B000B1DD0569A82A99C76129BF8CB9609E155E
-:1013C000E27E1C62BBA00EE152A673BDA9D2353AE3
-:1013D0006F3B8713E73F12BC5F13F397CBFBF9FD1D
-:1013E00017353D2164FB246F0BDD7F615AE40BE16F
-:1013F000EF57387D7E3A8F3FE9D3B9B0B90139F361
-:10140000E997991B9E390DDA7D4FF65D659AFD854A
-:10141000FCE9C3CC7D358C5BA2DD9F2415AED5F4F1
-:1014200033E5DCAFA93738D76BEA97AE29D8E0426D
-:101430007C8E61149F316E6E6718525CDEBB95E046
-:10144000DA24F07E4172D379DEC041353ECFEDF330
-:10145000EF09BDC24C9B693D4CB0F362516A4087B5
-:101460007AE1DC8F52491E3DFD842E88FED7892CFF
-:10147000A8C3F53F19CC3DAC9F8237E8CA74A58A52
-:101480008CE552E696B17C358BD0FE04ECF3F5B9D1
-:10149000DC3E7FC28CF1C15CFFF778DE5288F466D7
-:1014A00091A06791BA1FD9AE24FA65BB72890FB5B6
-:1014B000E7993A859DDE6EAFC8C4B8E88551F2CA97
-:1014C000ACAE9933F177B4AC59D3E9A9BE7FC8ADBE
-:1014D0001BF19CEEE3025F2ADF4F0426177CFF38E6
-:1014E000CEE37CF9BB19B8DD6B2A8C10FF5F90BC92
-:1014F000AE2588D73765CE878359342F45E05539D7
-:1015000058E95A02F853DE1EE709B0D8779E6EF309
-:10151000CE549458B948E445EE6FAB9B591DF7FE85
-:1015200075014F311BAA41FD545CA2F30469649715
-:10153000467E990B7BBC78CE5C29631E146F1359D1
-:10154000CF7AD4D5CA5F64CA73518ECD606ED81776
-:10155000582C21867941AF47E7C934BFAFF43B5BD4
-:10156000752ADD17981D957BA813F1F79486907F57
-:101570007ED7ABE7F33AA6AD2FB6F0FC9D15C58636
-:10158000A05BC2B07A0FDD8BA7F4490C4D7FE52F2D
-:10159000B3090FEC8564E2BFE4ED53E94AED9B1417
-:1015A000FF0F91BEE743EE1774E3042F42BBC6C999
-:1015B00086BD688F4D40BCE0840A8B09AFCBC57CEB
-:1015C000F7B72D213CFD5ACCA33337011EE6F1E2DB
-:1015D000BD912B7A55FF87769E0F9557DD8CF7ECE2
-:1015E000750CC9C256D2E273937E682AFE36DDF9C5
-:1015F00030C025139CBF46FACBDB2BE8F795408122
-:10160000D0FC1A9F80FD7E01C9A31AD2DBD374944B
-:101610009F9AC857A7841C6BC9E5797F56D79767EF
-:10162000E2EFBCC5CAB3883F9FD1B162CA2FD1F1E6
-:10163000FDA59ABF0186831BF775A579BAE83D1A07
-:10164000F3515FDB7594F727EF49A2F389B25DA1EF
-:101650003CE34E4BB56D358E635328AE32579E3505
-:101660008476B3D1AEBB1AEDEEE37BEF1FC2FC1262
-:10167000395761E82FEAB429DCEEC8D1513E9662B1
-:10168000AF36611CA6C872BA12F17974CF37C9BFE0
-:10169000217F43E488087F925E90AC93B5D0F881B7
-:1016A0001C45DCE7E1AD2DCD10210437EE7F6A3E0D
-:1016B000423FCA71DB2533DA2B6ECB0AF2A715E65F
-:1016C00015D07CF4186F83F213EB2ED9516EBDB98F
-:1016D0006783A300EDE7A0423648F19F3BB2E9DC07
-:1016E000F91E039D8B57F19A1F503471BBDC566D68
-:1016F000D99810BFD3279C4BCACA2B107A6E110BF6
-:10170000C5CD47EFE2FB35E6B4D07EA7304F629FF0
-:10171000E962E531A2BC5F1FC8F6007E8EED5991EB
-:101720008FF3BA72D84F79BEA3D9FB1FE7BAD5DFC2
-:101730004332EBE87ED59019F37E9F6A63E968DF58
-:1017400099820AE55DEF13F2ACD0C2F9DF90CFF9D0
-:101750003CF159D8C3D79D722029988C74B3F59762
-:1017600005804F26BF328FB941FF15DABCE43F2C0C
-:101770006C35A463FEC0DC1F5A884F2E5992C84FA7
-:10178000A8B42679F07DC7DE8A62771CDCC1365B9F
-:101790003AE6E5EC6D33A5A39C0A8E225FC7D975A6
-:1017A00094AFECD6F17CBAF9791CAEF979FCBE970E
-:1017B00079A2FCA4125880703E09F4C43CE9A39BB2
-:1017C000B93DBCB6DD4470AC7D731CD955A3E1EDC9
-:1017D000E936573ADE0FBF77B32E1BFD4795DD85FF
-:1017E0009BF09E84B5567E4FAC9C3AE9314C4567E0
-:1017F0003FD533B4DF3B52667A96C5C97739755603
-:1018000031F2952C07B2D12F7267DEFC9B315F124B
-:10181000E8B713CB2BFB4A79D91AC8C6FCCAE6BE77
-:1018200069BC9C1ED889F995DFEA9BC1CBB9816C54
-:10183000FC1DA9B6BE6B79797C60279637F655F208
-:1018400032FA9E40766EE99B7333CAD90E83A71E87
-:1018500005F20F00FE1280BF5F3CB70ABCA8F5CFAF
-:10186000E17BC0F321F14CAC7F41F41B18A5FE25B0
-:10187000513F38CAF82F8B7EA151FA1F13FD8E8F6E
-:10188000D2FF35D1EF8D51EA7F22EADF1A65FC9F46
-:10189000897E43A3F47F57F4FBC528FD7F29FABD59
-:1018A000374AFD07A2FED709E39F10EDC3E2FD58BA
-:1018B000EBE60F42C07763418EA05C2AB66E76E0FD
-:1018C0003ADFDB554EFCDF51C1E33B2ABF8FC5DF5A
-:1018D0006F827A5D3EBF4F4A97CFE33CCF88F1815C
-:1018E0000FB720DFAD7D5BA63C9B0E9DE76C10E53E
-:1018F000E8261DD9036BDFE4FBF3B5DD4A30FEFCBF
-:10190000C53309F06F10F0750A789FCCE3F139A365
-:10191000CB955E1BEF47B269CB9896857217E4377B
-:10192000E5ED167757751597638C4C471688D26886
-:101930000AE17D0D8A55E8055B794F31C26751E8B0
-:101940009CBA625742FBB1BFAB9CEC3B15BE4E8BC1
-:1019500042F775C956AE07E6FE70960DEDAC4EE641
-:101960001FF2627F9742F6FBD1AE321BCA3D83F570
-:101970002E1BAEDF76379F5775537112CA6BF92154
-:101980001DC9EFE336BEDEFB5C3AF25B805EA1F37D
-:101990002C20AF3DA82326B0503B9D8F78F885259D
-:1019A000DCAFC7ACA515745E448D434B4A9CFD7FEC
-:1019B00059E0275FE81105F50B3C9F2C17E71C0247
-:1019C000DCFF0464738D893BAF79394FE6E740D47F
-:1019D00038A25C4BF716E5AD5334FEF79C7BB5653A
-:1019E0004382DE5012F4CAB82E9093717AA7206019
-:1019F000D3944FE609BF8E8779D07E9DFBC3CD245B
-:101A00000F2FA17E9346977B51F92BE4F193E21EB1
-:101A10009E2703FC1CF1D1CD653F417AAFEDD6D1B5
-:101A2000BDD35F548E3E93C7B87FDA0F7A07ED19A6
-:101A30008565E37EE9F3F0305EEF73D0BD0A9F83E6
-:101A40008FF18F963B50DE8EF72BA47786E98DCFF2
-:101A5000C1D7B392E73D3FD2D19EC4ED6A1B9F77B9
-:101A6000678693DF4724CE1FCAC25E7B50F8C195BC
-:101A7000D4B96EFC89904E7B0B9537489ECC1BA049
-:101A8000FD46C96FC3F21B8E24AE777293880FF7A1
-:101A9000A32D43F71C16F8D03FD21F34A8F71486A5
-:101AA000F0FF0E627E8E7A0FA28BEC33710F63EF24
-:101AB000CDD5D85EB14D469373DA138F6DD1830DBA
-:101AC0007AD0C0A2EDF13CD533C775E29EC4DD5B90
-:101AD000D05E3D98C434F7401E443F3A8D17DC82F7
-:101AE000F73EC2F76E90610F767DFEF7B658B26290
-:101AF000F054B90F6C69A73C59BE2FB1337E4FF734
-:101B000079773805970BEC4FAECAC77DF99ED3198C
-:101B10009ADF5D13ED5345FBA6C148D30137B59F4E
-:101B2000960FEBA07120925242EB2B5211DF3E45F3
-:101B3000ECF7E3DA7F89C61FA57DB10ACF81776F05
-:101B40002DE1ED2B71FC0BEE7006E5BC24C0933645
-:101B50007CFCEBFF1A3C9344FBF3A177A9FD05162F
-:101B6000CE985240FD6EC27E17DF7AB742CC3B035F
-:101B7000ED64908A37E37B34B7F8EFB1B490FDDCC5
-:101B80006FEAB1A1BD66D6F7F850EE16E2BD4ED3AE
-:101B900063CF05F985DCAE4A78DF6F6269B5C88F1F
-:101BA000AD3ADABFF49B86CA4AD09E7ED102320F8C
-:101BB000F5C23A0FCAC181F05A4F09B4EBCB99452F
-:101BC000FB8A8386967E3ADFBBC442E74FFB6C3DBF
-:101BD000365C3F667B8F0DE308F27DDC7E52965AC1
-:101BE000FC4F213F85D6162F8F5BBF556E3DC1DF61
-:101BF000FDAA6533EE03BAF59E9E0968675B15CAB8
-:101C00003F57960ECEA7F3823FD03192EF30AF2AE6
-:101C1000287736EAE8BEFA87DD4BEF413C30C5E76E
-:101C2000AB827E79E98A84E72F1E547C268C5F186C
-:101C300085DDD6E7E1BFF7AA7E7787B02F77E4F39B
-:101C40007BABBA971C287E0DFAF5B5AEEDC7EF99C0
-:101C5000279A18E699F5E59CE9C6F3A28FBB60C701
-:101C60000B78B034E8E8F75A1EAF8536A9E8CF30D4
-:101C700068FC15CF4AFDD43ED0A8A37D82A5C4A0A0
-:101C8000F16FA435E8BCE8773CE0F66F427EBBFA22
-:101C90006DE506FC9E6BBC6243FDF490EB17261DC0
-:101CA000C09952AE1DD7364B3B8EA35A5BEFACD5D5
-:101CB000D6672CD4D6BBBE6648F0D768CB29C847B8
-:101CC0008847900116D04349BC8A2559AED0EF858C
-:101CD00075FB77F54C8036C6E440E96B006FD2A403
-:101CE00024DAEF6F7C3509171FC81F467267E314AB
-:101CF0004679AFC772BFE9427D9A889FBE1C03CD6B
-:101D0000D75208F82CC0FDFA59FA5D2F0B8B6B5790
-:101D100080F8F13E93CFF7EFCC5581FE394672F053
-:101D200059D57F7C0B3F4FD5D7CAFDD20F2DE27915
-:101D30008134830A5CDFBC7D0AFECED854F4DB77A5
-:101D4000DD8DF98E8978CDC4FC3239C61F1BD4F3E2
-:101D50002B787AB2828B655C7797DCFCFECD970599
-:101D6000DF1C14F72D44DB23FE3218DFCAC2786F64
-:101D7000E6ABFE077E1E609B1A8F1165BCC610CBBA
-:101D8000078F3B6EC0F5B46DA1A30CD7D346619706
-:101D9000A5E618BC1301DE47DE3004A4ABA0ACB04E
-:101DA000E37AD0E7071DFCBB86379302789EEA11E1
-:101DB00057399DCFFA389FFBF39EABF4FCBC96D607
-:101DC000A342E7DF1E717ACC65DCDEC0BBAE19A58D
-:101DD00016816971B4B68CF6A98F783D665CAF8FB9
-:101DE000E478CC989F6CCE526CB88E1D2E85EED1C7
-:101DF0007AC4E4B7A1DDE2000588BF1F67C8ED998A
-:101E000047E7920087BA0A1E1260228F0FF3E8D2CA
-:101E100004BEFA5C77D9F0FCBAB3F0D0B7D0AF9E6D
-:101E200086E3A5F07E8827BBC0D3A57C37CF4B16B1
-:101E3000E3A7DDF51CB5C7BFCE8AB8F13C9CBF0C4B
-:101E4000F358907E074D7C5F1D273A3EF392DF7E6C
-:101E5000C34F38DEDA73F9FD4186358CF661CF5514
-:101E6000FAF71F45FC6425D13E3BDB955D85FC916F
-:101E7000FDC6CE05780E61C34FB8FE342CE7F1A63F
-:101E80006C8599BE8CF34EF7DB108F89EB30EB78C5
-:101E90004F1D32DBFF054658D4C60080000000000D
-:101EA0001F8B080000000000000BD57D0B7CD4C503
-:101EB000B5FFFCF6954DB249360F424248D8CD8B5E
-:101EC000401E6CC24344D4E5114445BA913722FE0A
-:101ED000420204482080F6A6D69AC50445C51A2AAF
-:101EE0002A5AD48D02C58ABA5440ACE85D1E5AAA5B
-:101EF00056D3AAB7542B4D842AC82B86F65EDA7ABD
-:101F0000ED7FBE676692FD2D89D2DEDBCFE7FEE373
-:101F1000A71DE637AF33E79C3973E69C33B33B9399
-:101F2000D82D3E076349136DCC6567F4F777FEBF84
-:101F3000740B5B674E622C650AFF5E10F63D2D65E3
-:101F40007C7E0963A9D38DF5D35858DECDEB1DEE09
-:101F5000BC8DC53336A0DA58EF89D8A3A5CC845CF4
-:101F6000D877F3B7E79BB5F67B078F60CC9F6EF110
-:101F70006C75319619311E635F4721AF3193EBEFDA
-:101F8000398C8D772532D60FDFEB5DBE62C676DAEF
-:101F90009C131C298C75AE649EA779FBF12FAF9F13
-:101FA000FB36CFFF67A6C319C56B651C6E692BE2B4
-:101FB000DFD95E7D30EA6FB6E84FC5F2F2CD47FA61
-:101FC00033BFC658542CAB0F723CD94C4C47FA77F0
-:101FD000FC5D8D71AC34CE78179FD448C67817015C
-:101FE00053DA3F9F06070E2C747AD09FBBCDCEFBF1
-:101FF0000D5A9C85169E1FF9D4A30F5A33310F0E2C
-:10200000E3189AB6978D66ECB9437CDC013CE77F18
-:10201000E2C189165E1ED35DEE47F94E9349E4FD99
-:102020008107278E656CE0A1E01A8793B18AA7B675
-:102030003F68E7788BFE9528F7F1BCDF02BCD40E31
-:102040006AE7F33B90B594E6DFF4BB2816C5EB15C1
-:102050009B3D9B90671F47B3AD3CBF7DF7D8D92E02
-:102060005EAF296E944B2F626C9A4BA3F95720ED0B
-:1020700077F1BCCC368FEE715CFCFD7A8937C63CBB
-:10208000475A397D8B9FB1B1FB786101E006BD5A9B
-:10209000A3034F83BE2D8F72A663ACDA29685EBDA1
-:1020A000E7BEACFD3C7D25AEA2CAC5DB57C74D4C93
-:1020B000053C191718D39339DD1AED4CE7B8CA4817
-:1020C000F999C6387C03530E8D630EF04DDB1A2749
-:1020D000D2FA18A687F165C6050BD387A33F2FF563
-:1020E000873F7B2AB850FC3527E96C0D87C7CF7135
-:1020F000BD15DCE98CE9D04AC0F813BDED6A7D64FA
-:10210000834FD9EC6011B84EE0C1C6716A2DE3A9C6
-:10211000C3128AEAA5FE6DB29ED9EE089987F1D462
-:10212000F9E611EAD76139DD6EEFA9670F58081F8C
-:10213000AC9605F234C2933F0AF98424CA33AFD770
-:1021400095920AFE6784DC0C0B3B14C5C725EEE5AF
-:10215000EB279D85287D82A3C791834A99899FC5D6
-:10216000327C62E0E3A7199B1CCED72A350D3211D1
-:102170007CB90DA67EC7397E0A0F46131C96752CB6
-:1021800010CD07CB053D38DD72D7B380C58D7AB64B
-:102190007EC793D1CE25F9C06962345E7028D6D54A
-:1021A000A6371DEB5902D197E4CEA61856037CA999
-:1021B000F1185B43FC10907CB1B9D1497454E5032C
-:1021C0006B0F44D031C94047552FE3C200A2674F7F
-:1021D000BF01EA2FA36117F143C6852CC927AE6F53
-:1021E000E93FBB8FFED3A87DDFFD0FA4F19F087DE3
-:1021F000903895A3E2C79DBB127D3C8DB6B6F83CE6
-:10220000BDE039E356A39C1CB6D72877155EA2AD76
-:10221000DE940A8EFFE8DB4C9E56DEDF65478CF5C8
-:1022200026BB3F4CC47AECA91F4A9986FA75A2FED8
-:1022300015278CF57DE37647D417F05D7DC1582FC7
-:10224000923E91F072B8FACD08836B823DCAD07E7F
-:1022500076E54570F59B1506D73569C6FAFA9ADE1C
-:10226000E1BABE20EA1BE152F5BE33FAD2EA45CE0E
-:1022700063DAE4A83EF02EEACF9A7D69FDDE54F3DE
-:10228000CDF56E69881CC72FF72BBEB6F83A4EC63F
-:102290003FF812486E3079A3F93EEA649D0CEBA832
-:1022A0004BAEAB24E6A4F5CC17BE8675F53EFE9981
-:1022B000CED810B7EF2BC8AF0976EFBC8779D58998
-:1022C00072BF6253788F97A3735FF18DC517F31FA9
-:1022D0006377115CAF6ABACE689FB57BB6F2F55DE5
-:1022E00098C1ECE95C0F606981EC1BE3188B752BDE
-:1022F00079CD450D8773A8C4DDF30382AB12699DC8
-:10230000079200CF3F3A6E7FB737C9DDAFA77E6433
-:10231000BD9EFA024F365B7025E0ECAC7378B03F9F
-:102320007C8022DEEE9999512133C7D739AB639D6A
-:10233000C6E5CC91D8F96FF6E378783F5E77A1FFD8
-:10234000D9B3AEBD1B79ED40B26B1587EF5C65FB71
-:1023500028E0D51BABE7BA391CB5767D502A9FE241
-:10236000994C7D7002F0EB4B26BCF27F14FB7A8512
-:102370005FC0335113F84F4ED08B31CE4453DB93B3
-:102380003E7CB3B48D423BE6EC47F09DB17179D70A
-:10239000CBFA5778182FFBD96FF57CD5C9E7B77FF3
-:1023A0004382A789C35B9D3C6BFE0A5EB4D0E44BBD
-:1023B0000D990D705F81F16A1D9583D201B755C2E9
-:1023C0006DEF27F1EECDFD26B89B301EF6B51F68E8
-:1023D00081AD6E414BE45FF62706EEE3F928D3F9B1
-:1023E0000F203F3A8B4D1EBE47B0CD5CBFB0F37D92
-:1023F000E53D89EF27B8FA634FA2EFEBF03D2D469C
-:10240000B44F7BC41468E2ED7DE35F213A3DB3DC59
-:10241000E131F3B12A99CB06BEAD625E1BE0FFE36A
-:10242000B8BFBDD6CEE737C7AD4FC73C6E4936659E
-:102430007D4070E885159CDFD85881FF6FE307C6A3
-:10244000D69BD828C66E94FAC14289C769CC6BC5A1
-:102450003833986EC5B8BF396BF3422FFD0D7450F9
-:102460000EEF2CE6A7EF735880D29B5888EADFCC9A
-:10247000DA29FFEBD892CC060E5FC5A383F3B01E1A
-:10248000C3F0BE54F2CB2D29825F3EEF0FBC6FEC40
-:102490007749FC5BA109FC0D71EBABDDB45E5D29F6
-:1024A0001EC0E49C30D01717B67E26F613FC677169
-:1024B000E67DD3FA69EB8A2F61C3481E38D2391EF4
-:1024C000AE91A4BCC6BB6C0AE60B0982F5FA1DB935
-:1024D0005ECBCD0E96C2E9D2E63207A2382C93C766
-:1024E000AD4CC37C7FB186FD6A38A7DF2FC69959F2
-:1024F00013D5F452BBA9B2BFA903279D847EF20E67
-:102500000BA58CE0EDCA2FE88712387EA69A7734A7
-:10251000738D9B4D1E68FDB43D4CAE5D9BB2D3C226
-:10252000B8FE725DAEF1FB94229E0F93BB5399A54A
-:10253000A79CD37F3FF003B9C35ACCE0DF47DD71DE
-:1025400029D057D85036549C0F3835C2E6D365FF92
-:10255000DA768EB77BCBAD3F093E5A9578763EE969
-:102560001D16319FE5EF9A49AFFCB49181F3D87104
-:10257000AE1F7AF319FB8CEB17C89F684CA3F40BC2
-:10258000AE0F203DDD5840E5671B3D94FFD2EDFBCB
-:1025900009E8B460DD9716EC4BF7442B7C0B3856FA
-:1025A0004BBEBB2773D4A37FE578BDE71DBE303893
-:1025B0003C35C19649007B75E6A777417F5EFDAC4F
-:1025C000E641BD65FBBC36078767E121FD6E90796A
-:1025D000F13BED532126EAA0BF72BDE15EAB6F3740
-:1025E000C61BF9E1F1549D57F0EEEB783399D7FF14
-:1025F000BC7134C175B2D14B709D6A9C4C694CB6AC
-:10260000EF55D4F7B22F6DA87FC38E0E4B06AF5F88
-:10261000EED5BC588F57795920C0E1D96415F27DA9
-:102620001397EF589FE38A6F7CE25606F9ABBF81A0
-:10263000F63392AACA93F9F7A9A32B2DA837EB2B4F
-:102640002ED3DC3D7CF8EDEB50E0A34ED2E5CCEB95
-:102650001AE1E9CC9EC2EF5CC1FB7BFDB0999939D0
-:102660005C5D174C0457D79198009456556FD56E02
-:1026700033E993AB326D01E06FD5EEC2FED0A74EC9
-:1026800071BAB1FC9EF14E3DFF6F2E3D4C8E9E4ABD
-:102690000AFEE74790539F0839C5F5CDCF1E871C2A
-:1026A0001B38C003BA9FB572BD1C8866F5B1D8C788
-:1026B00096DBE4FAE27206F95331E21C3CEA858CBF
-:1026C000F1582F18CF65EB9143F92F3C9AFD7D57B8
-:1026D000CF78DB830B3F7A9CE7CF044C7E2BDF6700
-:1026E000CEB0E0D99F438E6E7178703EB847E3F06C
-:1026F000601FDD3A80F2059A25A681F83940EBB5D6
-:102700004073591AB8FCA9FDD96303C04FAF721CBE
-:102710008CE6E5AF6E8825F9F4AAD573B401FD3DCA
-:1027200021FAFBC90FBFF7E95EA40FD4957D0F48CE
-:10273000CE4E227C57FF68C950B4E7FB344BE7FD0F
-:102740003DF7B2168AE6EBB378E3FEBBD2397CC321
-:1027500036779806F0B4748BD684B430F3BAC36677
-:102760005E6ECF76111CC377B8CD19585603021F81
-:102770005D4DFBB7715F2FDAF8E5781C2FD5FE3E73
-:10278000540B7ED18AF370D691329DF0D742FDEC86
-:10279000DE37EDFD9B18E6C13507C05D69F3D07EDD
-:1027A00012F0B782CE67F402CF7D58D33EFF63A00C
-:1027B000EF193DD583FD658FC91F3F06F58F5A6818
-:1027C0009E2F6FF975BC95E713765959342FAF2BAF
-:1027D000ED9C84FA75992E3A87673E79CD64E0675F
-:1027E000F9AEDDADD44FADDDA3619DED3EFF6606D4
-:1027F000CE43D7324F1EF86E97C8DF3FD1EB01BFF3
-:10280000D5B4FE59E4DB7C94F799FD6E0BEA5709C9
-:102810003DE751B98FB1F6129277C4CAAE1E7ADD88
-:10282000CF8B51BEC9ED4FAF77F4EC7F7CDF2ACC64
-:10283000E6E5E936D9DE392DCBF70FEC5B36B90F7B
-:10284000A9FE1EB5317F34EF27937FD7B0AFDAC42E
-:102850007EBB95CB17F08BDA6FF9B857648BF65EB9
-:10286000C8C90CBEB996F2F9643C1A15A03DFD1218
-:10287000C7577AD28A1821CF94FE313BB9E9B57691
-:102880008ED73FC5EBD7607E0BE57ECD2C9E34CC3A
-:10289000EF58BC7732C6AFB57766610E7C3F9C823D
-:1028A000FC7233D79F72C2F427FBA5ED875109DE76
-:1028B0001BD1FE52EB8F8DE95DFE8EED1A4DF2F7C6
-:1028C00035297F57FFD9C44A797EF5C351244F6813
-:1028D0004FEB052FAFF1F5AE73F9F2EFB01BF0F44B
-:1028E000CA3FB59BE9FC71C854FB26DF4F69E86C11
-:1028F000FC5F6753C208CA7B41E6ABFE64EAF57C25
-:10290000A8524EA77ACCCBFB95D1DE70F5574E1B63
-:10291000F5EF48BAA4F99AFB98AF395ECC771FE679
-:10292000CB69B7FACB329297FB2E719E9951DE3567
-:10293000A06FE43C38DCF7E07B24DCDDFCDD79696A
-:1029400070DFA631BF09EBEC4B5B00EB6C1F07138C
-:10295000EB76DF92A200D6F31E9BC8FBE36DA47F4B
-:10296000EE8B637EC88F7D15A901BF1B729009FD98
-:10297000B41F13E5D1B2FD9C546A3F208AF33FCFC8
-:10298000B39B6264FFF56F17A37C4D868743C0F548
-:10299000DBC0BA6CD26FCD64373C22E5F5C6C4D03B
-:1029A0004D66FE7DE397F90CE31C61A18C15A857D9
-:1029B0001343726863A2373D89E371CFD766DA1794
-:1029C0003696F2BC83E434D977365678D313797EC1
-:1029D000AEA4CBC6D6C0D647D05F4581C7CFC719F6
-:1029E0006066F554CF2DFAF9C82ADAFD4ED285AFCC
-:1029F000635AE7EF672F0801CFFAD4580BEC221C7B
-:102A0000E3E91A87FFF1EA3C46F252DABD664B1A57
-:102A1000CCEDE103AF7D14F45AF13767E1D668C815
-:102A2000E31935D164973A5273579C8B8F374337EC
-:102A300087A2A0FF4D2F37D89DDECFF6D2B8FC601D
-:102A400021CF09A12AE0F1F54E3B835CEE8B9E7508
-:102A5000C171C9C7C3F8A1C626E4C709A90FBD1231
-:102A6000A7BF0B7E5FB1F7DAE4E361FA5EF5C2F26D
-:102A70007CB2FB565FDAF9AE09741A46EBD56F02E9
-:102A80007F04A389FE936FB413BDBB1CA6A76197F7
-:102A9000BC45CAAB261C84F9F7A6DD5181BBF8B74B
-:102AA0001551A19990579CFECF6E035D5F8B26FA5E
-:102AB000D7DA043FD5FEBC90F86B8FCDEB5E8BFE72
-:102AC0005F8F22BAD7C6BB12A8FCAD6426F98FF47B
-:102AD00086DA98507E22C7E7BA58FD24F0C6F98EF0
-:102AE000ECC1B536F1FDA8E4ABA3BC0FC0E1AF8FDC
-:102AF000237E6432AF7F3F99CE535C1F25FED51FE6
-:102B00002CA4BC6EF3A62FC4FA58154BF01D95F6F5
-:102B1000B4A3B589C4DFF31E5CF60EE3F43CEADB34
-:102B2000766F3EAF77749FD5837DE9F70DE6908D84
-:102B3000D3F5EC1DC7466DE2F9F6BB3ECED2C3EC31
-:102B400068F3EEAA9B8276F396DE3115FB655FF89B
-:102B50009E571BC5656E0F9D5272BCE61C8E7F4F43
-:102B60008E6ECBE1F35C51D4BE0872EFACADED4993
-:102B70009C0F3E4AD0A3F1FDDC2B9F6F237968E9BF
-:102B8000CC877EBEDCC2F9007C29F7CF15922F5F7F
-:102B9000CCD113509FE38FF4F1D8A23621F7EEB8D1
-:102BA0003439FFC5BEAD7B343ECEB2987DCB2935DE
-:102BB000074AD0CF292D14AFE5007F5C8FE3FD9D40
-:102BC0007686E241075D9E9B966D37CE0B7FB0AB5C
-:102BD0002CC33F78BB654133D955F8FE6E03FCCB5F
-:102BE00060E935F813845CE1FD3C4DEBD0F1FBF975
-:102BF000DFE7F85FFAEC9032E893CB12F7FEF00AC9
-:102C0000AAC7DB293E375F9C57F3B9181E31BFD3E3
-:102C100092CF4F33290767DBBACFE1D083CE3EDFB7
-:102C2000DFC037679F1D42F92FB44E2D86C37556FE
-:102C3000CA23E6098EAAC001C21B1C057DF611F944
-:102C40007D59727014E48F9247CC1E2CA17375418C
-:102C5000B004E74925CF982F984FDF03C17CB4DF3C
-:102C60006312760AFAC3BC9FCB68253CD8C57A5C50
-:102C7000FA5C21E1458D1349BFC8F94ECD11FE0123
-:102C80000EEF2D3E5E7FF0269BA17C48C0989F29C9
-:102C9000EB0F8AA0CB0073E7FE28C8FB6718ADD7FF
-:102CA000C8716FCE11F6F49FFEB49B0E66795E6418
-:102CB0002E457F97D0B7ADC0F7EFBAF17D6B069781
-:102CC000A7CB30C7EC9EF9EF29D53320F7CF9A84F4
-:102CD0009D7A4F22CF1741CF11F8547985C7483ECE
-:102CE000BAEB778B32E04F5997D3EDE7E80F7E6B65
-:102CF00082BCE4F2A2C92AF0F14563CDF0E3169C50
-:102D000047EBD3AB2D3DF359B4A9D48EF5B278730C
-:102D1000A97D41D879A769FBF0C32E4E97D3DB2D4F
-:102D2000643668B2047E083DBA69BB39E867546E00
-:102D3000F7F2FAA71D07DE45BD459B13CBA0F7AA06
-:102D4000F68B37DD965E1D86EFC2ED46FC17078DCC
-:102D500079D8A3C3F33F822E38F21F6F571A32E699
-:102D6000871F36E63FFFE0D69960E397470B7E3F2B
-:102D700011880BC04F55F3F1A4C3D8D74EEC793965
-:102D80001EF459F649F59B38B72CDE64E4334E3710
-:102D90000D7ABD7F9B46FCB12410B9EEE47ABF6882
-:102DA0003DAE5176CD82703E89A4E729169CE9E5B7
-:102DB000FC54DBB06A38FC21355338E372782E0FAF
-:102DC0006EB0C16F10395E5FEB9E39BC2ED8AB2A56
-:102DD000478BB2310DE3D931187DD7FF7A12D65B1C
-:102DE000E5FD1AEDFF952F0D3E04F9DDB173CE75AB
-:102DF00094CE9C4C7850F6B3C5FBB4501CCF3B47E7
-:102E0000BBF6B6F3760B031AED0F0B9AA37AE41018
-:102E1000FF5FF5FA083836869573F817EFDDFF1770
-:102E20008DF75FB3D9D86E09C717E4FED22D7F8F17
-:102E30000AFFAECE7D63F6B59A31EF850A7EFF5567
-:102E40000CF3122E482E3AA4BE721C192EEFA39238
-:102E50007C6DD85FC66C14EDB8C0AAC47CEB1C3680
-:102E600017E65B6767A1580EC7E1389BD7C9BF9FBC
-:102E7000DF1447F6A945515C2F2CA3944597A19DDB
-:102E800087F6E9CFDE3393BE5287B1D1CF531A9D77
-:102E90007FEA606C44FE19915FC242340FF08B37B9
-:102EA0007C7E01639EB5887353AD25B41FF858CA64
-:102EB000DAC5B987D3D11BE68FABE5F33C92047D2D
-:102EC000C8D87E050B52FD157BFF1E15FE3DCC4E6E
-:102ED0004AE73975AE34DB9817FAB1F9CE18DAEF54
-:102EE000B9208E017FAED5BC8FD9CD48C5BCFC1BA7
-:102EF00084FE33B755EC175C3FCD077E366E18E283
-:102F0000819E3297EBD9D1D02396C450BD8D898C48
-:102F1000EC2B1BE7E40B3DFBEB974218A7F3618D0D
-:102F2000EC231B4B45BF1B1F1842E590871A8D13DE
-:102F3000457ACBC60A559E497AD247002D1D7AAEF6
-:102F4000FCDECF45DF0798BDF9D0D7D943D174DE79
-:102F5000577AED33497A7C6EBF9EF92A3D98D55C4D
-:102F60009AFEB755EE779D1B84FFF7B8E67BD31426
-:102F7000A6970ECA15FBC3A8F1DE6DB21EF901AA11
-:102F80004D15F75DCDE1A97EC4E46A72F7E09D7945
-:102F9000BDF998FFF10DD165E0B351E385BDE76858
-:102FA000A990DBB1239837C0D3825CB17F14E49A37
-:102FB0000C695A0CE73FDECFF172611F8E1BE123D3
-:102FC0003B1BD7D9487E47CE638484AFDAE67BEBE0
-:102FD000CA5EE0E9E6838942CF38BE527B5AC0C55B
-:102FE000E9CAF3A37E144DF6B9E3725F51F8E77CAA
-:102FF0003392F66929AF36483ED900FA633F5B2227
-:10300000CE413D7C62E483B99AC02B7B40E8A71B8C
-:1030100013455EF1013FEFB0BF824FCA19E1BDAF6A
-:10302000738F9AE7C65651CEE93D05F48E3CF728DA
-:103030007A334B6024CE8D7DD17BC1E8C4519A890F
-:10304000FCD67EF8ADB1D7115EEEB504EEE2700CA1
-:10305000B408FC675A047F71A9EC8F29A3FA5E1BA0
-:10306000CF573EB4987979FDCA0C46F6205E9F256D
-:10307000A03EEF06712CD82BD0AE3241F45BD99F25
-:10308000D13981FEB8BCCA459A4DFD7A4D49A27D21
-:103090007C19B5F79B447BAF85A78372843EDFB96B
-:1030A000362AF034E4F33D99F9E08329E38D7CF08E
-:1030B000EFB962BF57E9D03C97342A79D2B0BE1736
-:1030C000340FA1FDA229DA57B71B747B5EE8FF9588
-:1030D00077DF7CC348C0F742B207E07D317527F93E
-:1030E0001B1634CFB9ED439C1BB647D3F76BF2F4F4
-:1030F000DB7347420F74CDDFCD3F2C9871D096C65D
-:10310000DBEBC18A333FE7E954FFCE77A10F4C9D3B
-:103110006EA6FA5399B08FB26631CE0DFE2F2D698F
-:10312000BCBF1BC66A1433D011EDCC5AC9E1AF94B1
-:10313000F4BB5BF26F53349BFD3307E0CACCCFE6A0
-:10314000DF6F8086D98BFFEA90AA3F4EDB0CBD660D
-:10315000D004B1BE547DF4837EDF92EB6983C48BCF
-:10316000CA73BC52FDEA75511D39F148ADA1C13C8D
-:10317000EDCC1FFF30F86A4A369BB40978FF9E19E0
-:10318000B10A1CDECE4A5AF771F92EF0A9CE588842
-:10319000E223024388AF3BC67576DCC3F31DAD83E3
-:1031A0003D64F391E7E885385FB9502EE498922F9B
-:1031B000479DED71C4AFF25C5D2559E38F0D131E81
-:1031C000B98CD7AF72D83AB01F2C7C785A3CE24CFD
-:1031D000AA369A453CC77AE3B99A9F7F5F045D227D
-:1031E000CFC991E761F00CF8A87ABD467C38A8C930
-:1031F000634B2739A63931BF6A472817F2BDDA1366
-:10320000ED41F9E9466FF2F15CF8232653CABEE2BC
-:10321000781F057B2CA3208E0379FA3EE0A9B2A586
-:1032200092CE8BB1453AC9A7BFE5BA08CF53604FDC
-:1032300084BCB1B4A7631DD6A9EF49CE7C07F17356
-:1032400034031E3AACCE7CC0D5B136DA847D73CA65
-:103250005D82AFF93AB35B78FB7B2D2C06EBFD3E2C
-:10326000D97EDE1A8BAF95E707DA99252E097C55B2
-:103270004A7C5D3658DF003C9CF8011B8DFDBF6A1F
-:10328000FD068247F105B3B44D4C867EB7D55D7619
-:103290001FEBE1A3B2C1E3DF47BB6E7E98AE111F07
-:1032A000F0747F0EF1C38D47503E657C2877551131
-:1032B000FC58B5CC0B3F421AF3C01ED0C53A499F0B
-:1032C000E8E2FA04E49992274A6E703EF022AE4793
-:1032D000D157C98F6D8D1C248ED7ED8D764A7FDA3C
-:1032E000E864162E037634A651FE854617A5C1C69E
-:1032F00002FAFEB3460FE577358EA6FC9E462FE513
-:10330000F7364EA6F4E78D3EFACEF1427248C91563
-:10331000258F143F29B914C947F3397AAF2AA3F688
-:1033200024F794BCC33C4C653DF248D1375BF3F9BC
-:10333000D3DC9063ED73202FCACDA79F7F197692BF
-:103340001A8727CA05BC08B9D7E5B0939CCFB2B19C
-:10335000BD38AF37ADF476DC13B6AFDE54A3314BD6
-:10336000189FDE5C1FCD2C617C7C4B43A2213FAFBC
-:10337000E1FD37FAF3FEB544DD91C7E1387AE7673E
-:103380004FFC967F7FEACE2FF2406F0EC7D64731B3
-:10339000EE1D31DD702421DF6C25FD61508C380776
-:1033A000E10F7459C0C4FA7CEACEBFD2FAEE688845
-:1033B000729979BD050D5184AF8F40278ED7DF4BB1
-:1033C0003A55AE3DF6FCCB58E777D848CE2D6896F7
-:1033D000EB721DC76798BEF6693A23BD4CF33206FF
-:1033E0003FCCA73FB085F89ECF3ED5EC010DBA0F7C
-:1033F0003F24CDE3DFF575BFA0F82BADE130E9C385
-:103400003AE2B26027F05B0DF1585A838CD36A1F01
-:103410006888A38A1DE1B5413E80A741B70505072D
-:1034200018D6356BD19CD802AAE5F7EA751AE91BC4
-:10343000DDFA429E99E8589F6BA1F45DAC71DA2FDA
-:103440005A687F52FCCAE585378075D1526A5B1491
-:10345000268717C8EF5505264AD5F7FA5C1BF5F302
-:103460002E8403EFF7BE826CDB4292732E1BE48046
-:10347000AABFA0A0ECEEEC11E8675C0A0B5B8FDE44
-:103480003C0BB5AF47A017CE477661FFAFED631F8A
-:10349000507AC909FCF372829FCE5B4B5F78EE05D0
-:1034A000F8C7967E1C45745A3A4CDA238A02A3A6C2
-:1034B000913EE375687C9ECB25FD273EF7497C3B1A
-:1034C0002F5FB14BD82F79DA8174F91D3564D75A43
-:1034D000EEE1EB230972D5E8473EF4C2C7F1ED7483
-:1034E000AEF06720BE906F0B192C0DFEA2639360A7
-:1034F000175FC13AEF465C5764BB15DA57F1C2BE9D
-:103500002FFCE4CA7F59FEDA9F53098EDDE7532171
-:10351000D756BCB63655EF65DE2B22FCD7CA6FAE48
-:10352000EC602BD8FA2FE1778BACB72A4FFAB52F86
-:103530006397919DC2C2288E61955DE0A12B909703
-:10354000C07A19AF7BDC4D5CB0F3736897C595E02A
-:10355000E1709EEB238EEFE53CB13F9F917ED473EB
-:103560003BCCA4179EDB1147FCBF7CC7436F5EC1F9
-:10357000F3CBB7681896D5B136C2D3F25D66660F45
-:103580003FDFC06E93DC379CCB9E8BAB073F2D0992
-:103590006ADEAD45F0CBBB12FA85EB8B929F964568
-:1035A0000547111D24FCF749FD48D55BB2EF211BEF
-:1035B000E8C5EB9D25BDE5C558E8DAFCAFF35DC075
-:1035C000796AF370F2EB2E09EE5C4EFBFE8E582703
-:1035D000A6F885D5688F0AE489F514C813FAC629B8
-:1035E00069FF3DF58299E40FE0C43AFC4213765E30
-:1035F000D56E9B6CB74DE2ED863CB11E55FD25C1E5
-:103600008EF85C5EFFF3BDEF531A94F35AE2682B19
-:10361000C17EF9F9AED8C9014A7F3CE9553EDE9931
-:10362000E0B8142D6C5DBD9627E286CF6C364F0650
-:10363000BE5840C51905693EA776646874AE05BEDC
-:10364000397E4EED7A29DE44EBD62FDA493A9AECF0
-:10365000C29EEAB6B8A4FDC2EE849E31976B75098E
-:103660005CDED5ED12F10091DF557D5A6FE9E0F790
-:103670004E9BE07FE9BF97FE25C489903F3ECE1662
-:10368000C0FE3A7F986BD64D90676F5B053D06BADA
-:103690001EC5B96AFE7BC964AF586575F547FE4F14
-:1036A000EF58C97E3E7FB85CE769ED23619FEC70FF
-:1036B0008B7DBD761D5F217CCA0338FDFD7C7EB508
-:1036C0000113C5531ECBCB26B81EAF31796DE4E78D
-:1036D00008E5C34E79D4C6FC66E8C93F8B26FDAE2B
-:1036E000365BD8DD1F07BFF3B43629949F0C7B9758
-:1036F000A463ED8DBC3C8C9EB54F87F2A1B79CB600
-:10370000093B1ECA9D48CB44BD26C937E807FD7654
-:10371000B89D6749BFDC1DC7A0E79B5E8E13F6848A
-:103720009F4493DF41F57B5EF25593F473F9B70A3A
-:10373000F80017F4E625B6967CE8956ADC25F12DAD
-:1037400034DE6939DE929816E13F907161A84FE34B
-:103750005B9917E7F1CE67A3483FFD22BD6D0FC609
-:10376000FFE2D921E407EF700716EDA572AEB7713D
-:103770003A2CFD695408F09E7C368EFC9C27AD42A5
-:103780000F3A19974A7AD0E1B847E6A3BFAE2D5158
-:103790001AEC292735664B43F9D67EE4AF5ADAD8BE
-:1037A000407E82A57CB9C31FCDD3C9F02B9FDC3AE4
-:1037B00084EC2C277F6926FF22FFBE0EDF75D632F0
-:1037C000FF76ACBBEDB16467FBE2A77F1B12EE7F17
-:1037D00050E9D22D467B92A2BF2A4FC917EB2B2569
-:1037E0005FE0312D5FEC3375B1C147B2699E62BDB8
-:1037F000723AD0798BAF8F54D8A78F065F49D51C0A
-:10380000C07328FFC7C0FB7671AEF9628795FC22B2
-:103810004B5F8EF392FDE69ECB4CD82F969A85FE99
-:10382000BB94B39B48857D68697C3ED98738BEE9E7
-:10383000FCD8B9D52CC711E39EDC9629ECEF219971
-:10384000DF531C009F4F4962B7DC48FACDE612E017
-:10385000F5FC965813F8828FE385DF7EE9EDDF17DC
-:10386000F84C5844FA38431CF428F8CB85BCACBB60
-:10387000E78A04C4C3B0F7CC0CA2EFBCC5D31FF2D7
-:1038800030125F8BF3A5BCDCF3840DFEB35ABE5E31
-:10389000101FB44CFA4D97FD54237D6ED9DD573C73
-:1038A0004A72F05D2BCBE3709C0E3E141F4E8F0AC4
-:1038B000D94F4F7B0FD55FC6EB8BF66FC7133CDB41
-:1038C000AC1EC01349C74B6EFF53F325B5EFE68F0F
-:1038D00020DFD74B2E9EF779D6F6DD8F2147764431
-:1038E0007BFCF435487EE753D6E022CCFBD4F3D101
-:1038F000245F4E258AF5FE3997877E1BE0B8FE418E
-:10390000B26FFC661A83E85E1C30F6ABC69D992F39
-:10391000E46F5DB22701FE8C3A4E07F4C7E9F21D51
-:103920006AFF9E95DA47CE63A46CD7BD3E9F8F2574
-:103930007E393540D0E3D40B83695FE948147CCEEF
-:10394000E1CDC239E554A2487153067CB0549E4380
-:103950004F8D0BD2B9FB94B693D20EAB68B7B4417E
-:10396000FA6D39DFA5816FC093F05BD9D7B7418F6E
-:10397000807D7A5419A5A1A8A48BEDCCE04FEC432F
-:103980002FE40B7B16D41AC875F26F907E12B441E7
-:103990001EEB528FABDD71B1BF8CFCA03B34F2FB50
-:1039A0003C20D729A04E51F671CE8FCBFC9A17F14F
-:1039B00046CB9A572E01BF2FABDF7013F85DCD6356
-:1039C00099854DC6F9AA4333133C1DD17CDD000F08
-:1039D000E1E365F7E07793821720A7929E49CAF545
-:1039E000E67CB15F21DFC2FBAB6DD6D6D3386E75F6
-:1039F0009E14F35378E268B1C14EC6CFF9A2BC8FD2
-:103A0000F92B3823E7AFE009E60BFB4487DBF5E051
-:103A100058D0FB5766B29F9EFF6A7842D237E8655E
-:103A200038B175DB8B39FCAFF1BD1AFDF821DFB081
-:103A30009E618FE670E66F36FA3F0AB618F3437759
-:103A400018F345BB8CF9927DC6BCE79031BF558E0B
-:103A5000ABF084732EE2DA70CE458A73AE2B5F9C96
-:103A60007391C7391729CEB9F88E732EF238E72231
-:103A70008F732EF238E722C53917DFCF4AF95D2B55
-:103A8000ED8EA003C557BD12ADFCE0B45ECECD49AE
-:103A900025F9A9FC99E7961451BEDB9E5361277B5B
-:103AA0008E8AD3B929413F924F7EC3B6BBD34137EB
-:103AB0004B3BD97157FC5CD8716BCBA21DB02FB4B6
-:103AC000AFFDFC6EA84F2509FA27F914D7D4B94DDC
-:103AD000C42B85486EB4AF71BD77B5A01FD93954DA
-:103AE000DC4D25F6BBA4BEE918E94761EB8D7E935A
-:103AF000483F4AA4FF24920F94DFE4296B673AE41D
-:103B0000FDB167EDEB01FF31691F63B39DA47F2910
-:103B1000BDBA5BFF7A407B1AFBF6D7F949D4BEEBFE
-:103B200030D7B77BD96F555A75A18CF4C6EEFC7AA5
-:103B3000CD44712369F1B40FAD963065699D1DF7D1
-:103B400040DEC599681F3FEF30D1B9E0FC0766D26F
-:103B50002306433F0F9BCF90408C81BF0AB7274578
-:103B6000F8FF0618EA0FDB9B1DE1FF1B6AF44B4DC3
-:103B70005FB31FE7EB69EB871BEA55FBAE88C0A379
-:103B8000845BEAA54D776CCA82FC591DD745F0AF1E
-:103B9000DE1D4D71B5D51C5E2FFC72C87014D4D8D3
-:103BA000BD5381BF9AA03511FB7C95DC7F58837192
-:103BB0003FAEB130BF33A987EF6A9CCC9BC8DB9F77
-:103BC000296DD966E2743B63DAFCC85817FC4AAD2C
-:103BD000594ECE57B76AC1D4CB797F7FB3E84583BE
-:103BE00039BF6559433F9C0779B93387ADE1F58EFD
-:103BF000AD7F299EF46EC9675956670CE8DDDA621D
-:103C0000A67301EC52E6A41E7E686D498EC975F458
-:103C1000CCB387FE5FD1FC385D3CB8A7D8E538301F
-:103C20007035F4B8A0986FCD38CD4F7AB29CCF2ABA
-:103C3000B9AFB05CD1CFAD327F5C9E17D4FC4E0FD4
-:103C4000D95FE2821FB3716F961972DCB4631BEE09
-:103C50000FDC19A35F337824E225F37E3B968FBBFC
-:103C6000F44311AFFBC78D13E22F87FEF9BCD533A8
-:103C700085E7EF6979C68673F1524BC0867367CDCD
-:103C8000B3AD362F4FAFD9DE4ADF176DAFA4F3F6D1
-:103C900062564FE7C8132AFE56E2A366BCB6D9C9DE
-:103CA000E17E61B0901B3531226EA3DC3CF60DC481
-:103CB000A59FDFAE9562BED37D3B6D95B03FCB7ABD
-:103CC00091EBA3EB9D69E5FD604F0A0ABF675FEBCF
-:103CD0006146A880D6C3B40B2E4AA75F184AE7D81E
-:103CE0000F99AF98E44451C479F61D1187DCB54FA4
-:103CF000AC831A5B28651AD6C9EB565A27755C7EC9
-:103D00008D2EC33999B1313CF58D351BF875C5C47D
-:103D100058033FCF6649063FF24C5CDA0CCB4F9F0D
-:103D20009263A83F6B7A6104FF97F594931C196323
-:103D30008833A9BBC3EFD2289E65BCF13B4FEF206F
-:103D40003EBBCED0BE8EDDD8530FE7E02DBF263C64
-:103D500033D666C379ABC624E26A66EB1DF27B3BC1
-:103D60007DE71331ACC341399EDF8A7DD14A767934
-:103D700065979E8D7FE7F4B62F7242CB71111F0AB3
-:103D8000FB8221BE900340E74F26E85027ED3D75AA
-:103D900005C2DE53E76FB321FE96E3DF92C151B255
-:103DA000BC45237B1EAF6FCF4812F93BF07D97F1E6
-:103DB000BE01FABB80F2C3E64AAC97C8F2E57CDEEE
-:103DC000D03396C34E033B93EA5FF6ABF873F1260C
-:103DD000A3DD6839EC396174FC72B08BF874E9F6D4
-:103DE0009D6F0EE07899E64B2CC5FAA90D56582B1D
-:103DF0008B2EE63325DFCFD798C8CFDDF5CE41E255
-:103E0000B3AE1A0BF1F3B7E163B957D83323F96FA7
-:103E1000119F0FFCB28B76699E8026EA012F03C0AA
-:103E2000971178C9E8055F0A4FDD788B285F8C7F92
-:103E30008C40DC801608B97BC38BC4A3EA3F024FD9
-:103E40006CB4110F8B74D77B90378B0E9B59E0129B
-:103E5000E6BD18F3C3F87C7E18FFC60BC24EA2FC69
-:103E600006332F5828DFCD273E113F3D7D8A715DF7
-:103E700076F38D4FAC93191752A9DDFF36FF7C1BEB
-:103E8000DF28B823E393D5FD9EFF1A2CED8423D9B8
-:103E9000485AFF971837ACF67B85E741778EA678AE
-:103EA000A22E4736E90FDDFB8DD358BE2A2E9BE2AA
-:103EB0008875699F53725797F5D43895BCDC351CCB
-:103EC0007C3C301576D7BB9B73B2DAC3F4127DAD60
-:103ED00095ECA6596B9229AD8C76A662BFA85C635F
-:103EE000F6611FFCF4DEFEA9A361875F6B4D99C2EA
-:103EF000BBFEF47B23B25831F2E5941EDB10353B58
-:103F0000DC9EAD525781D80FEAEE3C42FBD719D365
-:103F10003BF1B3B1CED6EE8E4748CDB2B5EF8F723E
-:103F200072D5A3D5A20F2A401CA1D6BACD09BC399F
-:103F30005B4B608F1E06DAF5EBD11396AE2DEF0FBB
-:103F4000FB57EDD7079FC4FEAEAFB1A642CF3CF9F9
-:103F500001DFFF34DABF483F3881F8E314F8AD627F
-:103F6000E97EDB098D79E1BF5962DE5FE234ECA7BF
-:103F7000FB66028E5762F46105E4A70D6C4BC3F833
-:103F80001E3FC54BEA6BF2127AB397A874C526A1FF
-:103F9000BF6D53F65A69D785DE8E3CF4763885A01E
-:103FA000B7230FBD1D29F4767CAF90F6FA414D9DE5
-:103FB000A53877FAC7B3827ADA5F1D05D0CB576B85
-:103FC000311EC89BD59AA73FEC606C4BBAD85723DB
-:103FD000E8ABD22B3BB96E15C6EF575FB0B3F0F824
-:103FE000B1712CD1909F604F37D42F77BA0DE5D7A0
-:103FF000A40D31945FEB2A35E4AF2FB8DC50FF06F7
-:10400000CF3843FE3BA3AF35D4AFF05618F2D326DA
-:10401000CF31D49FE1AB3494CF9ABDC4503E475FBB
-:1040200069C8DF54F33D43FD9BEBD718CABDCC698B
-:10403000C1FEB60FE7298EF7D7719EE2E9EA5FE588
-:1040400039C2E93A7682A9BE377BFC7725FF6E1A22
-:10405000E25D09FECC94F74032E57D8EE60217F171
-:104060006706EEEDD379B62D1D7C13592FB27C6C0B
-:10407000EC81F32E4EC33F6C9F39DDC2E5C3D8CB34
-:104080000E0CCFE1F9A421F74FB770B932F68A03CD
-:104090002F65F3FC80216F88F26107CEA3FCFE211F
-:1040A0000F8AFC3446AA45F690F1D3FD7C1E63AF1F
-:1040B000CE5EEF11F6905EE32D550A3C206E11782E
-:1040C000401AE2FC89F400E74FA487387F56E732B4
-:1040D000F626E74FA487F9B912DFDFE2E74AA4EF3B
-:1040E000F07325D277F9B912691B3F5722FD4DE3D2
-:1040F0006C4A3F68D4A9DD7F34D6507AA4B19EBE05
-:104100007FD4D840E9EF1BFDF43D50A0EC0721B26D
-:10411000B3287FD272F8F16087DB6B3D1DEE6755E7
-:10412000FE40E5FF6BAA67EDB158A7ED96C4CFEC52
-:104130003D7EBDBEE5AC857D16A66FB5C67A9F2BCC
-:10414000203BC94027C96BF97DBC362DB38CA77FB6
-:1041500071E93B41EF1965556B13DCB807526F05E8
-:10416000BF7C68EAFD5E707381B03FAC1AE2DD434C
-:104170007C22FDD8CA8FDC1D9F12E6E73685C5C5B7
-:10418000D05F587C8BF237AB789AABEC223E4FF97C
-:104190009355DC8CEAAFFC02237977E53A0BE927EB
-:1041A00071161642FF2A3EE64A7BB014F10257D63A
-:1041B0003A280EAD3FFF6E2BA37A5E334FB7FC99C2
-:1041C000D72FE9F15FF797F0F37282BFFC824E764A
-:1041D000D72BA5FF1EEDEDA2DC8FF6889D829EC138
-:1041E00053B2AB3D8138A7B21E7F3AEAC78AFA21A3
-:1041F000F497FB9F7CBCF89EF59399142C453C5595
-:10420000E67207C5536D1E17A2FB5B2BDCFAA7A055
-:10421000932FCAF9492CAD9F9C4CD8092AA4DEFBE8
-:104220000D74F81CED147E149E155D147EC3E28E91
-:1042300008AF7DD129923E917451F428BFD0836795
-:10424000E0E9623AF4D009F6D8FF2B74186109D27C
-:10425000FDBFA85ABB07707D1B5D6EE96493709F1C
-:104260007870B6DE0C3C575E70BD897C151B370933
-:104270005B932AF77C4BF92C94F7EBBBFCB63ECA58
-:10428000DF8E56F1085E4729A7CB04293F56970BCE
-:10429000FC4E769B09BF138A16933ECA1C42AF732D
-:1042A000F1FF204F267DE56B467F93528CFAA1F2F9
-:1042B000075F27FB9B1CE107BE4EEA8DD745E885CB
-:1042C000A38648BDCFCDDCE2DC27EEB94F94FB746A
-:1042D00086A4730E3FCC8F051D996E81D03A847BE6
-:1042E000EE25B807EEA7FCB52C40E9F52C44FBD62B
-:1042F0000D5CC021FF1DC6289EF160ECD4792B789F
-:104300007F13864FC8C5F7B07B7DD70CE947F7FA16
-:10431000FEE00CBBD77760A28BF48603F61CD26359
-:10432000B00EAC6176B45F72B98F5086837C5F400B
-:10433000FA06DF17723993FF82EF0BC85F57B0861A
-:10434000A1DD249731DE44B5BFDE399E5986F72DB5
-:1043500077AF2F796520EC2B6F270E9E08BBF3DB20
-:1043600089974DC47CDF4EEC6F1269948DD2E29731
-:10437000737BD3B3141FF68C378959922FC6AFC203
-:1043800067241E157EFF097CAEEC0D9FCDC001ECAD
-:104390007AF6F7E3D3B2E1FF12EBBFEEE5E2FE807F
-:1043A000FF2440435CB25DE025D2BEF379231B08B5
-:1043B000FCB22D09F4FD36C94357368CA1FA5735A6
-:1043C0008CA6F95D11A3DF35848F73BA2C94CF3599
-:1043D00007F6F9E626BA7F7BE605B307FA77ADD98B
-:1043E000B5DE83B5FEB6B82FC7BE3A98057F1BDB96
-:1043F000D27BDC6EAD5DE1CD4FF8F4667B9BC5FEF4
-:1044000027EE11ABFD776094887755F759FBDA8F6B
-:1044100047C508B932304AC8414527DE8EF219BC7B
-:104420009F515C6E643C1843FAF78824EF63C0A781
-:104430003A4723BE09FBD455A1C204E427E33CC993
-:10444000F36FC9FB696F0DAD4FC9E6F83E68D39FA6
-:10445000413B66FECA8C75DD94A7D13DF7AEC339EA
-:1044600029C0F756B5EE4A5849F87B034A3FEE1E7D
-:104470002FC54C7EF155F08FA6E0DC64277BD1552B
-:104480002C9FFCA613E5F8E5BFACA27710D4BD8F36
-:10449000A83493F1FD1C578CE13D98D88224433E0B
-:1044A000CE33C0503F6174B6A13CD13BD4509E3C4A
-:1044B000B9CC90EFE71B63A8DF7FF678E3BB6EFA19
-:1044C0007586FA1935371AF24A7E65884F2CB37E05
-:1044D000AEA1FDA0860586FA6EFF52E3FB367E6F25
-:1044E0005B412AE49EF8CB59B7CA50FEE37871AF1E
-:1044F00061B26311BD5791D772BB717C49A78C041F
-:104500004127E612F2D5CFFF03DF94A719E5ED04AA
-:10451000A7F1BCCDF5410DFB7B46BDC5F0FDD3FF3A
-:10452000219D23F1D2C5B7A610EA431FE2F9ABF4EF
-:10453000A10FC2AE3131C5EA0930614F0F9F17ECB0
-:10454000E9E178803D3D3C0F7BBAF15D2823DD61D8
-:104550004F0F2F1F7ED848F7916D46BA5F76C4483B
-:1045600077C58F91F4B9BCDDC80F91F4B9E244046A
-:104570007F487ACCE6FFFD5DDC93267A4D7268ECCD
-:1045800071F73F4F9FD4A19C3E853DF4F9EF0C3D60
-:104590007D683FDC4F3F9F6503BD3AC57B7D2BA502
-:1045A000FC54F184FCBC2BEED3DD6E26FFFE515390
-:1045B0000BBD9774C0A9BBD1FE96A27A0DFE8334C1
-:1045C000E6DBB988C337FFDFA3C89F307F90B8D739
-:1045D000C98ADA29CE5EC9B9F919228E65C850791F
-:1045E000BEF0887896A2A1422F8CF33829EEB5B29E
-:1045F00048DC23E0C782ACF9C5E09F77A2F16E6189
-:10460000D74661BF6FB78AFBA57ECE47F08B414F7F
-:10461000841E9729F5A8A6DFD9ED807FF02666D8FD
-:10462000178704EC86B8CBC2ED4E43BE389866A817
-:104630003F6CAFCB505E1A2A30940F3FEC31E44709
-:10464000B68D36D4BFEC88D790BFBC7DB2A1FE1525
-:10465000277C867C06EB7C0CF81DA489F368F5505A
-:1046600011C7C3D710F993E6DF9328EE0FCA73AAD8
-:10467000D283553CAE2EF92E529F1E64D329BEB76D
-:10468000299D79E81E805D9E4F9851CFD6653CAD3F
-:10469000D24799DF184FABE268BBF571A97F2B7D3C
-:1046A000382C8ED61B1E473B5FDEF38DDCF7EA25E8
-:1046B000DD23E11F6413F36DFA9E8DEE2D28B822E1
-:1046C000E1F99B8CEFDC6AEFFDFEC89D4385BFFDE1
-:1046D0009739BEEF825F9F84F8C8E96D3C4FBB9F5E
-:1046E000F357D30F6C9EBB5CDF3EDEFC61623EF392
-:1046F0004CA65B2A8A286E69F6CFC2C6FFA11C773A
-:104700007591D6EBFCE62788B822966073817FFB13
-:104710001E4FE033CDC69AE99E8B8C3BBF797DF06E
-:104720000198C8E7D95AACE2FDB28015FC30653C6F
-:10473000D79F4A61B7FAFA2107D7339E6CB0901D14
-:10474000E2E1A137CCF0E7F6DC2318C4CF17E00F85
-:10475000E82A3897D88B44DCEC9EA162FD979BBF7A
-:10476000EA8EFF267B3A63527E8B734B2FFC467C8E
-:10477000A8E6F1AF8E038FC4933A1732B9EFE44A3B
-:10478000B814FEBACFF1127F2A1EDFB5D2EA7BDA67
-:104790004171FD9311CFA4E837B048F0E589A182BB
-:1047A000DEA80779D457BD72735102ECB55DCC9584
-:1047B000E0FC067BE4BF0A2F0AFF7DDDEFE94B3EFC
-:1047C0005C2417FAB8EFD3177FD2DF3F70EF274C86
-:1047D0003E88F812498F40AE89FCB9F7C419D771E9
-:1047E000FF4281DF7D6ABFF0F3F3A4514E30D897CA
-:1047F0009BD69AA59C10FB2AF40D7C5FB8D64AFA8A
-:10480000066B10F1C835521633E64B1D3302FE58C5
-:104810002BBD67759597913EB2C0610BB4F2FA95C6
-:10482000FEC87DD54BEDC95FE3C2BB259EBB617F52
-:10483000AF5A67ACB7D821DEF55A18712E5D2CCF70
-:10484000A58B23CEA5D185725FF6300FE94DD2FF3F
-:10485000ACE0ECE6AB400EC505E39C6A16F6128AA6
-:1048600057EAB6E3C3BF10F68E26C7674C01F6EDD4
-:10487000664BAF7164DDF8ECC34F7E1A7E7217D6BB
-:104880007F17DDFFE9DA152DFC68CA7F21EB9FF663
-:104890009FA772D4476F674ADB4AE047EAF677443E
-:1048A000F84DBA1CA6F8D1E86F87787F41C5012C76
-:1048B000FD6BA0C419E6E7D4DB4D86B88BC8545F06
-:1048C000B39BE2025A2D7A59219FC7298BC78EF7D5
-:1048D00022EF751C48C57DED29D25E13096FB71E06
-:1048E0003A56137E42BFD043BB266BA48772B9C829
-:1048F000B08E943FBB828552902AFF81BE6E34E118
-:1049000059F90F2A43A309CE194D8BAD78B2AFFDEB
-:10491000B13BCA635C3D7E85F64C118FD2977F61B7
-:10492000DA050FF537FDC218EAA7A2D02DEE7135D2
-:104930003FB0127C34743BB3629EED11F1D82ADD96
-:104940005F28ECDF470B95DC96712E6B34A1676B0B
-:104950004CC5BD90DC56F9F32D325F2EF2ABD78AF1
-:104960007CBB7CC7689BB437609E48311F9C8B77AB
-:10497000487B04E68114F3C077C829E421A7908717
-:104980009C421E720A29E414BE2F60BEAC52B3F0E2
-:10499000834C0C5B37F0834C0CD383E00709CFC307
-:1049A0000F125E1F7E90F072F841C2CBE10709CF73
-:1049B000C30F125E1F7E90F03C1B7D6D4F1E72CDAB
-:1049C0005B61C84FE3FAF8C4B0750B3F4878FFF05D
-:1049D0008318FAD3571ADADFC41A0CEDE10709AFCE
-:1049E0007F4B8366F093DC22EFA5576D4A22FE9839
-:1049F000E3F6FDB090D3F70FB15FDF66C539CDBCEC
-:104A00006F099D9FEA623C82CE2D9305DD4D4CD00F
-:104A1000B9730ED1F90E9BC8978BB8D8DEFC0D1375
-:104A20007385BF0129FC0D48E16F400A7F03DEC397
-:104A300086BF0129FC0DF80E7F0352F81B90C2DFE0
-:104A40008014FE06A4F0372085BF01EDE06F400A18
-:104A50007F03BEC3DF8014FE067C3F0ABF476E0F94
-:104A60005CD0DB730DE73BCE8786F39DD39087DE6A
-:104A70001E5E1F7A7B7839F4F6F072E8EDE179E892
-:104A8000EDE1F5A1B787E7DB86BA685D427F0F6F7E
-:104A900007FD3D3C5FDCE27F0336A61B369F3D846D
-:104AA000B43D4E7B52E3A2E0BDE78ECD80DFA83D52
-:104AB0005ACB4AE44BDEAA9D9C3191EB67BA8C2F0E
-:104AC0002B619DF4BEB32EDFADD1438CE2618BFF31
-:104AD0009226E482BA37843F4EF7D25D8CCE011520
-:104AE000723F55ED3DCC6926B925EBF7E47BAF1756
-:104AF00039BEAA47F2320C0E7E402C451C44E91DFB
-:104B00008E32C4716F3369220EF22E11871AC95783
-:104B1000E6222197B699761E88415C4BA546EFC5E3
-:104B2000E75BD861BCE35DDC525F067DE15461A2C6
-:104B30009C57FD18C4C528B8951D90CB09BA5735A8
-:104B4000B693D9AA8BF09E18B32D847CB7093D018A
-:104B5000ED707E2CF46BDEA7C3F8FBCF85627FD3AC
-:104B6000FD2BC754F3EF853BEAC7E0BED69418D1BE
-:104B7000EE274FC5131EA7366B4FE35EDCD81DCC66
-:104B80008BFB975F4B795AB8C369ABA6719D74CF05
-:104B90004BF55BB9398BEEA555B2F6896964CBD775
-:104BA000E81D7385373EBF43981F17F187ADA48F6B
-:104BB0008AFB2231F2BE88BA27E2B6F8424347F6B2
-:104BC000DC17B972446239E2B5D83EF1EEDE0D234E
-:104BD0002AD7F6E3FDEB01F1EEDE957FAA7F83F2A3
-:104BE0005BC4BB7BC406A3681CDAD706FB357AEF2F
-:104BF00061AABFD594E2C2FDD135D654D4DFC13C01
-:104C0000507F0633710F52C157C4DA4C78779C6FCE
-:104C1000310793C3F8884B80E9A07BA9C74AEF41CD
-:104C200054589C56C88DC87DFCE278BA083D2122B4
-:104C30001EA2E98E2359E66CD87B4C9E10E4D6EE7A
-:104C400058D21794BE5329E3A0CE37BF41EF59572E
-:104C5000EE14FA81CEE500E49F8A8FA8CB0964990F
-:104C6000A02F0C682D49328BFDBF08F791FC2FCD8A
-:104C70001CEDC23DC637285EBF72EDC804715F47A8
-:104C8000F81FAA259EAA65FC0B2B72A642EF54EFD3
-:104C900098969BC726D07DB716A1CF29FB4BE5AFD1
-:104CA00086BF093A573E21DF03595749F78022E36F
-:104CB00050947EA8DE3B59D26CA5F89625117AE077
-:104CC00032A9072E8BD003AF2B8AD003D5FB74B249
-:104CD0004EE5AF0ECE203DA55EBCC7376F8DD05BD5
-:104CE000D84EF18EFDBC35134C78B762DE6EAF47FF
-:104CF000EB853FDE93FACB140C9A8C389F0194CE4F
-:104D0000BC9046E9AC0B052407701703F46F7F8550
-:104D1000913EFDBED4576620CE0FF7E3FC51329E84
-:104D20008F91BE54CA9CE5901B43BDDA4198AFA752
-:104D300058F5B588239CD2CAE83ECC0DD06B78C11B
-:104D40006CE839C3C1E7EE72BA173059A3FB1537C7
-:104D50008C5829F99AF339039FFB25DFFA28DFBD28
-:104D60001F48FED6FD1D167A97D5AFD9F02E9B2E83
-:104D7000CFB38A7F23F97CBEFCBD09E61076A66E10
-:104D80003B1480A5C755AE9A097D713E6C7703240C
-:104D900021398AE28A447973D155339B71B8F91F5E
-:104DA000DA27E6A9DF61E07A16E4E9CDB796DA16EC
-:104DB00084C9958A92F1CF14F7EBA1FB82EE7B6355
-:104DC00045FDA1FFAFBA37AFFF37DD5FACE278C674
-:104DD000FA989FD07E1B5EC6DD52C4BC1347E33DEC
-:104DE00066354F1642BCDA5C99FF75D1E2FF585721
-:104DF00044F8A17C60C794997E5A2F425EDD047905
-:104E000065869CD29F2CC2FD0E7BFB24D023B6A8C6
-:104E100053DE8797FB51843DE2D745820E91768918
-:104E2000AA2221C799C5957513DD5375915D4FC1B0
-:104E3000FFA9D5786F50A5BF54FB48E3BF26DEFE1F
-:104E4000CB54FDE7901F8F98C4FDED01E61626EDCB
-:104E500043E27732E4FA61F23D831EFA73A901FA64
-:104E6000DFAB39C3E9AFAFD3C4BDE93EEC38ACA08A
-:104E7000F3B1ADB0E3358ADFE7782A5FF0D153B7FD
-:104E8000DB48FF9E676B7B03EF34293C7EDCF0231D
-:104E9000ABF89D97501EDE9F9A5B1F4DEFBD569459
-:104EA000F8DA4097D8220FD1E319C494F2FAED4E04
-:104EB000DFFB984FDDFAFD4FE2FEF88A7D6EBAD730
-:104EC00058B9B7F46EBC6B5151A21F4179A5C369A3
-:104ED000C3FEBDBC3991F6B3F9FDE5FD42D6497E6E
-:104EE0002A85FFCE2261C7DA5622FA3F27CF21104A
-:104EF0009415867A32AE38629D28FB60A49D21F21B
-:104F00003D81BED68FB227C07E600BB32F2AFB84B3
-:104F1000B5E0D339D83FE7D98CF7E154EA2E96E7CC
-:104F20005C790E5CD8BD7F154DEA0F7D798346BF55
-:104F30005B53ED70CDBA9CE7AB0F5B1129C8A6247B
-:104F4000B9C43B12F78A772416F0F50A79334FC6B5
-:104F50000D556F1A4DEBAD3AC0D3E4BED7E54D1BEE
-:104F60000E66BE02FE0979E99E78B5D36B4B0A5BEB
-:104F7000F7552D9AE19EB9CA27160B7BDC3C3C61A4
-:104F80005E0679E1B6E12D97795CAD401C9ABBD8FD
-:104F900065F0BBF27A14C730259BBD29DEF1E170C4
-:104FA000BBC5786561FD2F6831DE97E7F5C5BB1499
-:104FB000C571D45FA593CF1BF60FA793E0E47820CB
-:104FC0003C753EC0FB73D138448FAA50C08AF3F6BB
-:104FD0003CC44FF0FC5C67C08A7116348B772BF4AD
-:104FE000F5621C7D5DA2AD18FA92C569CB04FEE4A2
-:104FF000BBF61C3E9283D51C2FB8FFA3EE0146E200
-:10500000A752C25BDD9268D4C35A3658418F397DAE
-:10501000DC9FBF41D27D41F338BAFF5C6DF1527C19
-:10502000BD2EF1FBC795D1F7C13F3067E3A35637DB
-:10503000CF5F592CF8F70689D729D9A13C7A9F660A
-:1050400065B40770CE71B6D0FCBAF1FB30C7878665
-:1050500077507C845FCE177EC491556F34D2B307EE
-:105060001E81DFEA8D95B4DE1659749B331C8E4D7C
-:10507000FBF370AF670E5FDF7877873975BA6FF330
-:10508000D9C3B3B2689E1C4EE035CEE39A84F7666E
-:10509000389F101F2B7E51F783D5780B8BC53DC1F0
-:1050A00085C5BDDBD77BD6A597F49B264E5FD8BDC3
-:1050B000FB5A97365C34E2E3DAAAC53B6091EB54C5
-:1050C000AD4FB52ED53A55EBF749AB2F94A6F5C8A1
-:1050D00019BEDFD6FFAC173C3D23E19D2BE9CAF199
-:1050E0007A28FC5ED1FA62218FE6651BD73BFA4332
-:1050F000BFB7ABF2F1A13CDC0354F5D5B8F3E4EF54
-:105100007481EFC16FB74BBAA3FE2AAA6FBC1F51BF
-:10511000D52D2F76AC4D85BCD8A991BEBBEA818335
-:1051200099FF063DF679A1C79EAADDBA3C1D76031C
-:105130004B202BFC7DA6EA90900F0BB9FE0379B1B2
-:1051400048EED3D7E4E9F7168F0CABF7D0F3F9BAF2
-:10515000902F21C897DF3FFFEA87635C3DFBA78262
-:105160007FC1BA5F5B2B1DE1F8127C7E5F4117DDCA
-:10517000FBAA72D85C88B3AD6AAE2479CBD2F87939
-:10518000420B8B938AE083CA668DDECDAA6A18151E
-:1051900030FF2FCAE5AAF515F4368FA2937A7F4324
-:1051A000EDA70AFE1D12FEB9928F5F94EB6F6E8D14
-:1051B000DBB688D6BDDB5605FE97E573AA8DDFBB4F
-:1051C000E9D4ED672EBA3B4DDE63A173C97AABB06B
-:1051D000EFED88237DF5D4AA97DF9DC9EB7DF148DB
-:1051E0006B16F41305C76269C75B28ED718BA4DEEB
-:1051F000CAE9F47A71989C5DFC94A053D50BBFFA70
-:1052000004EF43CDCB96F2EC0171BF7C417027D106
-:105210006DCEBA0D5637AFF76EB1DB20A7ABEA4BB8
-:105220009DB04FCF5DD76A851C78B758E02D92DFCF
-:10523000E7C9B8548557EC3B5A98FF42D587FCDB49
-:10524000C9C7B97565743CE232D438FF25F9B8AAEC
-:105250003E3109E355D557FE10E71E25EF23D7DD74
-:10526000B168B11E16F0FEB02E8F8DF3D03DDB7904
-:10527000F2F7A522EB9F9574FBB155BC2398111B47
-:105280007C96E20A56C478201F7273DB031817FC61
-:105290000CB86D26F1EE606E6DFB978083ABC51484
-:1052A0009F8214EF1D414D4EE5F9A74DE23E10627D
-:1052B0004B90A694087E80690AE52CA59DDE3F0BE5
-:1052C0008BCF34F0AB8D6D5987F7576C298C7EEFFF
-:1052D00045F1A7EA47F1A7E2DFBEE6E728B9B4F94E
-:1052E0001D734B3B4481270BF728E63F3898DEE7D8
-:1052F000FFB679DAE43B78DDF38D12BF5B70D17CC9
-:1053000073C5B9A5EFF96E2C4FED65BE91F354EB63
-:1053100044C55E77FB155A845FE198C6F72FDEEE31
-:10532000D8CA688AFB52F35276EF4B8D97F79424D4
-:10533000493B427B1CF4C879F2F7205848E4F1BDA0
-:1053400022ECBBDAF7D5BB614A3E1FAF97FB226B5D
-:105350007F00EB9935E4D03B19475B8EC5E1FD8EAC
-:1053600063E3047CAADDAD5671EF95C5D95C783F47
-:10537000919FAFE8771F1636F7A773E4CD0D392458
-:10538000176EF6270ABB83D4EF174939187B6BE5F4
-:10539000DD97A1FE26B753E3E32C74783EDB44EDA2
-:1053A0000B3DD007633756D8B249EF15E700E50744
-:1053B000BA55633EBACF043989F565DA9F8B7D67AC
-:1053C000F126710E986262EBE02F1CD4E49B940EE0
-:1053D00039F1987837926D36BEAB7420CF777D095E
-:1053E000F016F11ED9ADD6A0B73FE438D7376067C5
-:1053F0005AE8F091DEFE969493473776D0FBE40AA4
-:10540000AF17DD53B1897BA99D7126B2BF5DEA7DDF
-:10541000956AE94F527CA3FC518FE3FF2E079E4C07
-:10542000B4AF959BE7D1BB3E776F9C4069F586F2A0
-:1054300047FCC5B80FEB4B1D43705BC93E565D374B
-:1054400041DC1F7D3A2A11E79B2CAB3F2B5C2FAD33
-:105450006EBD87EEA99C688DA67B2A139D1513133C
-:1054600053E8BD5DBAF7A5EA7D5FAECBA575130C19
-:10547000F74C16F23E1107FBE7602CC595AAFB23FB
-:1054800077C6E8DF2DE927EE915CEE12F747D2A947
-:10549000BEAB577BB84A3F6B14F711C2EEC54C9DAB
-:1054A000C3DBD7D6BD148F7E963DFCFE288E19D85F
-:1054B0009FEE02DDBAEFC56C12F7629A705E821E33
-:1054C00099E49B3907F8FFA599F0DFD77835F851B3
-:1054D00092B073C4CD8104D25BF510B3C19FAC3BD5
-:1054E00019E9C527CCAC017A80D25FD4F747245E96
-:1054F0004E24B464813F966C7B340BFBCBC938914E
-:105500009FB76DD65B9057FA9628A19F5B18E9C3A9
-:10551000557EA15FB39A24F52E66F47CF8634B6246
-:10552000C53B3CF2FE8C824BBDB77AD222DE8BC1EA
-:10553000BD18F0FBC796D042D0F763AEBFE21CFBAC
-:105540007D29C73E6E31D3EF8EF8F942811EF2718C
-:10555000CB4B71B89FABF4B572F3EFBD788F66D5C6
-:105560006E714F15EF9AD39B95D20EB25CDA41560D
-:10557000BD629D84DF1DE1FA177DA9B5846CBDD1A4
-:105580006FA9D4AFBAF3BB76D2B9AD7687D01F6A14
-:10559000831DA43F287D44DD8B5BB6A383F409D52E
-:1055A0006EF92E8197BA5DE27B25E2D6E5EF856A3A
-:1055B000B9384F6B94FFA468C1AC3596F07C25E5F3
-:1055C0003F2952F6914ED207EF2BF80D9DC3EB9A6F
-:1055D00065BF3C6F0D1BEF0D30693FF13DC781F694
-:1055E00062DF57E575BB12A97DA82E661DF679EF1F
-:1055F00072870569539D83F6FDCDF5A602CB0800A1
-:1056000017E3811EB74FC66FF55BF61FD1B01FA41D
-:10561000B3CE8378F7F580533F027E55BF67A9EE7E
-:10562000BD9C7BEDF3E1E8FFAA41EDE7F1C6837590
-:105630004DDD2CF827DA4BE43C8ADA8783AFFB1D7B
-:1056400010F2F9092B5B47EF075B7C0C76FB90F4BB
-:105650002BFAFF6212BF2FA1859E09D7AF52860990
-:105660003DDC1725FC8B5EB77E12707C47B3169726
-:10567000E24CED32E7A17FF53B2A4A4F1D2FE5733F
-:10568000A63C5FD906A439C0C79AD74BF710EF2ABA
-:105690003A50857DF9FE4E3BFDBEAA8AC31BDF1939
-:1056A000437A6BE680C9B49FA97B29078A4C7EBCEC
-:1056B0007B7E3FB38BB8007B845E6B8AA678646D7B
-:1056C000DF2FFE02799E61FEF2207EA724E3DF3405
-:1056D0007AFF727ED7674FE03766E6B14029BD8317
-:1056E00097A89B86410E774DEED039C9EE7706ED2F
-:1056F0001EB14FB070F8F77DEF2FF149A61EB8CE5E
-:10570000757E46EF0A9EEBB493BD76FC3EF9DE5EF5
-:10571000043CE7D25C1417CDEB85F0BECA3987890B
-:10572000DE191BBFEF20BD9B375EBDAB6737BEAB3D
-:10573000C7DA3213614F261B2A570A529B04DDAE8B
-:105740004A309E13F38689F356DE30213F14FEBAA9
-:10575000EC67DFD6B59E75B842F9EFD5EF4DD5446D
-:10576000D1EF4D75EDCBF9C6F713DE87FEC0F5829C
-:10577000F5D9DEE261FD7AF6CF19122F6A1F36CB1A
-:10578000FE6748FCCC7098043E227E6F43F187A2EE
-:10579000BF8257D157D18DDDDEF606EE05717A1541
-:1057A0003FC8884E97119DFEF2CE5A5CF31F60F6FB
-:1057B00076E8EEFF8B740A450F869EF0B0F8FDADDB
-:1057C000C8B84656C0689DCF37C7901D5097EF8226
-:1057D000F3F5FD06D6B75AD78326B717637F3CCAC1
-:1057E0008FDE80ABDD14A4EFDF1D26E20907B2B621
-:1057F00074197F33127A59937CFFB8FB770C973872
-:10580000E8BD917301F5FE71E0B1457CDC8D338A12
-:10581000C8AE7F8EC9F55ED3FD4EB678FFB8FB9D4E
-:105820006CB39FEC247362C8CED3FD4E769E78EFA6
-:10583000FA558DE5E31D5A7F859DE2E323DFC9E636
-:10584000FBCCB3F0673C5E13437E28F53EF278A7AD
-:105850005E0F3A46BE8FFC88E69BB310FD153BA851
-:10586000BFF639312F6C13680EC18E73B4218EDEF2
-:1058700085567CA9ECD783FC1D8F014FEA5EE71F9C
-:10588000247F29BCAB7B6D0AFF8ACFFC5646F73FCD
-:105890004107BC2BABDE67D7EE907243DD277CDD82
-:1058A000E342FA40A2BE0E7037ADE47283ECE2ED43
-:1058B000B761BE4F7C2FCE0BB88E9A8CBFDFABD2B8
-:1058C0008786990CBF133A5FEE57F355DC7F83311F
-:1058D000EE3FF21DCDE404DFC3C378FB33DAFBA354
-:1058E000F0F19DFF36F71A47F2A45CFF2362F5271B
-:1058F000505FDD7F50FAE13BA59F67D2EF8D7C754D
-:10590000907E5771AED31740BDE85CE10FF8437A43
-:105910003BDDD7F8C39CBF66923DF90EF1FEE7A5CB
-:10592000C279F17D5AC10FAB178A78C30C564FFC70
-:105930009BD6734F331A70FCFF769FB6E7BEEBE43D
-:10594000E1C729EEC247BF5711498FB151075E72B7
-:10595000F193CA6F877D318BEE93261C58EDE6F9E3
-:10596000A32F9E15F98C03E7DD9C36ED2F9E13F9CE
-:10597000C203E7711FF5D3173B45FE0A46FEACE3B1
-:105980002F7E390BF74FFBBBF53F825E332FD4BF21
-:1059900081EDF5C335372E74D37DCA8ACC02719F51
-:1059A000F26394CF485DB03641EBB94F69F2F8FE2F
-:1059B00008BE3DF7A5E06F3787157CF2CFA6EA3E1B
-:1059C000A992B77DC945B5EEFE55F761D53A66DBBC
-:1059D0003CEBAC6042FF3F7D4F9579F8BCFE1F9BCE
-:1059E0004A017000800000001F8B080000000000CA
-:1059F000000BB57C0B7854D5B5F03E73E6994C920C
-:105A000049C80B02E104420C18D299BCC05BEA1DE4
-:105A10002089015A1B6CB52018068D90D76442A8C6
-:105A20002DB5D80C0611A8DE0B5754B068274000DE
-:105A300035E8A0012718EA00922252BF98FB37F2FE
-:105A4000FD5FE10B3E90979310B557EF55B96BADE5
-:105A5000BD4FE64122DAFE7FF8DAEDDAEFBDD77B03
-:105A6000AD7D86B1B196F3D18CFEAEC98C1D3FFCE5
-:105A70009EA249646C4681D16A90A034772BC602FD
-:105A80000EBB01DE7595F935B1BC9F36B45FA2D768
-:105A900066C17E7566EA973908FD72B1DF9F476B74
-:105AA000B1BE416F356430F6B48EB94D098CC5680E
-:105AB0008EC8B84ECC2063CDD07FAC8131631E63DD
-:105AC000297AC6B01DFA312394BB06F97AE3121A7B
-:105AD000563098675C85D9DA9C81BBF53056C8583A
-:105AE000DA28FF68DC5FDA4A3DD5C7687A94063366
-:105AF000638126FFDC0F33192B8E8ACD653F8052E0
-:105B0000CFB2711F4C13656D85F54AE4AFBAD20070
-:105B10006EEC906CB0342B36946F671319ABD702D0
-:105B20009088FF33795A711D6D77F51EE8D7939CE5
-:105B300066DD08E0D8D4832C331FC6BBCA72D804F4
-:105B4000C68E5A1C39D62468679B241C1F9DC3C768
-:105B5000FFAC2C7A870CE3FB0FDF54E880BA3B0CD8
-:105B6000CA0166652CDF3B7A81F61680E39442C950
-:105B700002B075EC02ED688053940312B41BDDA3F0
-:105B80001714DF82E7335A3ECC66EC174C62718003
-:105B9000970CAD63BA15CEEB2CFB44CF34D83EA0A6
-:105BA0002F9F0AF76A854960FDA4A3704FB0CF818B
-:105BB00039319E1D703E96A314627BBA6E20D602C8
-:105BC000F7D1FF95B6CC63A671B13F87FA6BF8F7B2
-:105BD000AF8C3DD72953BD0AABE5375689EED79533
-:105BE000697E0CEFAF3ED568A4B2F36A29C379B4DD
-:105BF000E59977C03C763D5B529E73FDF801AB861C
-:105C0000F695B10E103A86C8CBCE14F8BF28A6C2BE
-:105C10006E369DB1965F41C5BFF0763809D34FD23D
-:105C200008F896ADC5DAB0FE76EC1F6C6776230BEC
-:105C30008E775AA76E5D9B29D6433C2F639E497091
-:105C40008434D62031B8BF54E627FCBC644BA07323
-:105C5000D11FE0E9D94453CB46A45719E8328F4A03
-:105C60006681322D1AD683F6B4374C1EA4AB5D265E
-:105C70004EB7991A5EEED2F0FEFA28E6463A1D07B4
-:105C80003083F26D9BE377B6249AC74FF3C8FB6D60
-:105C9000488FA39997D64F616EDA8FDA6F2CEB3667
-:105CA00021CCB40359844F5933EC7D26D9666E4616
-:105CB0003A0B34D9D947DA607D203A765528FEEA86
-:105CC00071BC3974DC2C1AA78E77AED2B08F46E146
-:105CD000E1FD443FCE4C8DDD9383E3D89B521ED62D
-:105CE00077EBCB6382E37A9B8CEC23B8D7FFD3C4EA
-:105CF000A83CDD64A1F5FF6F532A957F6B52A8FE87
-:105D00006C5336957D4D56AA7FBF693A95772D8A9B
-:105D10002940FA77F966B28F8C42CEC0FF9C5E9D17
-:105D2000A32F04EE9D393C1DBD26E8A83763F8F685
-:105D30006E6C077CF6DECAF1D97F3FF3ECC820BA5F
-:105D40005C6B49B81EFF30C284E7EB8F610BBC70FF
-:105D50004F6F1748347FFF680EEFB7EA683EBB8687
-:105D60006DC5F16F17E8F9FC133455D86E4FE0F3A9
-:105D7000F666010CFB59307DE6CBC897F664A8CFD8
-:105D80000BC2BD5378BB7D0CAF57F7ABB6FFCE66E9
-:105D9000E17428F0DEAF83F57388DE697EB5FFD746
-:105DA000459C0F23FB7B3235659E61EE23C1C6FB0C
-:105DB000135FC07DB8910F3242F8A25E21BE50E958
-:105DC00050A5BF976CFC9E330D82CE4127D0FDA11C
-:105DD0006E40F99A027C20D1BDD8199C679724F8AF
-:105DE00025921FA04439AEF283CA072ABDA7019F9E
-:105DF0004909C173FC28825ED5F2B495E3A53B390D
-:105E0000E601C26BA7CE02A210FA03221310BEB3A2
-:105E1000C00EE34A1E35370C27BFE2FED97B50E5A2
-:105E2000C108F770DDF9F5BCFCBEE727F986721BE7
-:105E3000E9761879F5B53581F6A3D26D92CDFE5F7E
-:105E4000483FFD92492BC54169E2741379FEB70BB7
-:105E5000F83954FA79C9C6B8BEC4734EBC5EDEA91F
-:105E6000E7193AE77246722F338AD747E2573D5710
-:105E700088DC8BB11506EF93316E0F8C057B606368
-:105E800046907E03495F2E43FDB5CDAAD0FEFEA00D
-:105E90009109FFAA3E19AA97E425F373C2F40CB343
-:105EA000001E070E1B88BFFD1A56F50A8C6B255580
-:105EB000113CF76D362E0F06174CD2AC827D05FED5
-:105EC0006E76A3DE0A8C19382BC1F8C0563040C854
-:105ED0007EB0FF584A66EC7ED029A897AE809C63BE
-:105EE000598CC9DB3E3F2BC1BE976D9319DA350142
-:105EF00010DB328C733D19E331F2718CC1B83A3149
-:105F0000AE79EBA777217D9D07FA44FBE62353FD8D
-:105F1000040676CFEC6D3ABAC765317A0FD61FDB2F
-:105F2000FAC48945009F6F9714B4374A6533B5D7D3
-:105F30003C2F7B709D3A73E94509EC9C407BCB5329
-:105F40005150EFDCAB63261857DA2E59FD30FF7243
-:105F50006F0CDE0C5BB645F77E5F76506EDE26F486
-:105F600058D52EC90314C3AAB687B7D7EC0A87EB56
-:105F7000983608C3FCB36C318964FF4D6636B4FFB4
-:105F8000D89604545643723B92AE506D237EEC8DEE
-:105F90005C1E33F659F21D4097F2E1CFD3DF377321
-:105FA00078BE80CF01FCC9E7FCFED57BAB1732FF82
-:105FB00093D1ACC00BE7AC3F6CB2B8E160F51D32D9
-:105FC0009D23E08DA37B7645F5DD4E7C7A48B6A017
-:105FD0001DB6C127BBB1DDD969DAA98173D61F907F
-:105FE00018DA9F4E9FC1C3EFE9EA326C5FEE335976
-:105FF000146C3F6460328C0F00DE4C88C7717D8466
-:106000007FC42BDAA7F0F763A928887F19F19518C8
-:10601000C457F356BE9FF37B397E4AE5D55AC25723
-:106020008BC45242F0FC67CD8B43F8C27EB3B7FD00
-:10603000B50BF1BC0CF6675010EF32E1F93CE0070C
-:10604000E7D51FFE28BDCF1CC4B70CF8FEAD3A1E25
-:10605000FA2FBF01BEAB987B1DDA73DF17CF69C87B
-:10606000FF4964F79EFF03DABD31608F23E908FB27
-:1060700038A9B6F778222C589170D9B902EA27A529
-:10608000BEC232C14E90E21D8F225F9F9DF39747A3
-:10609000101D3D735FB4215D34EBFA5A9F860A7779
-:1060A0007CB41579B03F63FEF6D7609DE2842FD3B0
-:1060B000F723BFFCC96041727A42F023FE1901FF49
-:1060C0004EC6EF1BF0780ECFEFEC34F80D708FACAE
-:1060D000BDC43E640F4C407DECD5A39C2AD10F5427
-:1060E000AC407B1CE6C375242023E4EBDACE3F9F53
-:1060F00096609CA424B2C5081BCD7E19E769D35DC8
-:10610000193A37CC2359FE42FDDA6C13E8FC1353DD
-:106110007EA4A0FC695EC81C5113BF4DCE3392F320
-:10612000CF0A7F6544FB6F0479AFDA7DCC3D361E24
-:10613000F90BEF82F30F973BCBA733F127F842C05F
-:10614000556BDCB146E8BCFC666B2A9EFF63A4B3CA
-:1061500058A4BF53DA51B0AFBA5689F0568FF483C2
-:10616000FE15EA37A8EFF70A39F27C77F1A8442C3C
-:10617000252B702AABEE94AD7E68AFF6717ABA8E9D
-:106180006E84FCA869E3F2E33A3A6A0338C44EAB82
-:1061900047BA5261C0F7C9A0FC987A0DF6FBF234F9
-:1061A00026F4955BD05B4E5C1FD0CB2053E22C399C
-:1061B000217A4BE2F6962A576EDA0AA23E64DDC9CE
-:1061C0001E23D386AC7BF35E4B183CD59B1AD6FFBF
-:1061D000073E25ACDDE6CF0E6BCF3F610D830BBBD9
-:1061E000A787F59F76DA1E06DFD25716D6FF8717E8
-:1061F000CAC3E0C11C38CF3076C7901E4A95C2FA98
-:10620000CF514C61F3CFCB8E0F8307CDE27E841D3F
-:10621000A8DAA75FD8B81D1459AAF7FB136BF83A90
-:10622000AA5FFCD3E9E1EBCDB787AFF75DF1B21B15
-:10623000EC7E2DD8F57B413F62F902D8FF5AB0EBD6
-:10624000DBC0FE47F825B0FFB1F482FD8FF5AF80CB
-:10625000FD8F703BD8FF081F047F05615F531995C0
-:10626000879ACAA9FE46F7D725D63D21D63D29D61D
-:10627000FD47EF492D9D6593345F009FCE4CB8A834
-:1062800047396C6FEC2BC538C0C05B32DB810CE248
-:10629000F09C684A447D348AA1DDC2CA07DEC63854
-:1062A00045FD8189968D0AEAA1FF7C07DB03EDB2EB
-:1062B00082F2FCA8EF83589CE7CA17C087F938EE32
-:1062C0008358F48FEBBE64046F847605E039FB419C
-:1062D00030903D03720DFB67AAB047CFA02C6FDB57
-:1062E000AF477CD4EEDD4FED6F7975E1ED7B5BC29E
-:1062F000DA2DD81FCA5AAD87FCFB4B3E753E3FF5E1
-:10630000AFCB94EC68175FDAFB9FC9CBB05FDBBB08
-:10631000C9F77DCB7D7F72F0C51C94EB4ED0C37E58
-:1063200073701E67874EC07CDF7599FB4B1350114D
-:10633000B4496C121457D826B60AE45DADAFB50E59
-:10634000E5506DF6221DCB207924E20D206DD15E43
-:1063500042E71EEEEF8AF7D3D8FB60DE37BCC76F8B
-:10636000B723FE3A8FC5E2BAFDED72983F73771EF0
-:10637000B75BEFCED313DEAEB41F8B55A07D83F792
-:1063800018BF6FAD9FCE7D54C0FD50D23DFB643A27
-:1063900077F5171ABA7F75BEFBF3649A678E6F5252
-:1063A0000C9EABC7CBD773E529B4CE9CCCA595B8D2
-:1063B000FF93A90B0B65B2F34030A35C9D32AF1580
-:1063C000E303B55ED93E9CBFB546CCDBA5E374F8CC
-:1063D00056E6AB5D63803E4E968DB291CC17FD7E46
-:1063E00093C7EDF152BD2313F5428F5989413A7E8F
-:1063F000B86C620CE2F52896585FB653EF80B2A6EF
-:106400009DAFD763E98E457AEB69CF97D16E51E79F
-:106410005B89EB1686D0F510DEDC84A72A4F8B193A
-:10642000E709E28FD7BBF2B81D7ED2F3EE5D68A715
-:10643000F464475B112F5D7A46FE6D2DE015F54142
-:106440004F675A0BDE83BA9E4BE0A33F5B43780D48
-:10645000F874A2DFA25616D64FC7F1B52B7C3F16B3
-:10646000CFB97F5B847AE959B0ABA1BA4ED7908C93
-:10647000E7FF787BF8FEAAC43DD7E9FCC9C921F43F
-:106480005AD731C42F66A2EF0E953F14C2A78AC710
-:106490009E6C6EB7F5A41A3CE82FD6ED6F25BABEF8
-:1064A0003EBED39D81767EDAAF8D1437BC913FAB73
-:1064B000DA01217E0F433F4E5736B1503321A8EF0A
-:1064C000AFD9EC2FE615A23F544EFE5E0F1B588647
-:1064D000CADF8976701CCADDBF3D85EB0EB683BD71
-:1064E00007EB3A8DBEB91F829D35680546817D0F49
-:1064F0006ED779847F6246FB7499B04F3F561C4536
-:1065000032E857E71A0D9DAF2E278ADBB5424E7E43
-:10651000B23FE3A748AF7527648B11ED50F05B08DD
-:106520006EE37641BD37E3DF67A0BDDDA6233B40C8
-:10653000B53B9CC2EE382FECD9F36B06F464AF1E6A
-:1065400096D813B08F2ADFE6AE346877E6CC257B89
-:10655000D529B751FC71F9D670BBA0DA130ED7EE6E
-:106560000D879D117683EAB7F5E40DD90F93D1FF1E
-:10657000289167A4201F7C2CF0A9FA232BA75A533B
-:1065800090DF376895B96A3C00EFC975F8D56ADCC9
-:10659000AFA72ECA4A7EC1AA43749FFD9F71BFA3B5
-:1065A0003F9571FB88F17BEDF771FA76E924EE6790
-:1065B00000B9D27C46C9B3069AFADD83B124971894
-:1065C0002B437E685CC8FD483BC65CA1DC9727E294
-:1065D0004511FAF2566D9F1C1F221F3ECB9B40FBBC
-:1065E0002FD63307EAA9953156D25BE38DDCDE2E38
-:1065F00059EDB5211D8C07FFD81012CF1E6F1E90CC
-:10660000B0DFAE8778FC5CF5EFE76B2DBAF810BD14
-:106610000792276C7E90247CFC8DE6B7C0FCE6E0F8
-:10662000FC70DF7178DF9F1658491FA7CF67AC9BBE
-:10663000F8B181F8513DCF15A0B362A0338C9920F9
-:10664000DEEAB61FA138B09375933F521ACBF751CB
-:106650008AFB41388A97967C2E37CAF3F9BD350BF1
-:1066600058955B6FE5DBE3F3A1DC9BEF48CAA77AA3
-:106670000BD1E54A412B60A7A4F40D23771BFFC281
-:10668000FDAA4F810F90CFEF699094CC303B88D317
-:10669000B78B57B1CBCCDB3B03EFC16DEFCE4E4692
-:1066A0003F8AF3D59255262533844E5D48E7702FF7
-:1066B0005596EA1FA3DDED5895AC60BCDF85743FAD
-:1066C00001AF91D37522FC43FFE23A3AF786C3F05B
-:1066D000B71DE9AB9E19ACA8475CBEC876AB16E304
-:1066E0003AF9F9C0073707F9205DD0658B43F2A06E
-:1066F000DC6FF94ACBE3588B258A5BDD0995489717
-:10670000F487FDAA667A70FE3B01447F886D4924B8
-:10671000BEA14690233F17E7BD53EB3F827C7C5CD4
-:10672000E7CDC078CA7127CFEB2C646070807C59AC
-:10673000CCBAA9EC8DAE3FE0A7C9DDE3D06F7ECF28
-:1067400061A0384ECBDA1D31284F73D95ACBF96C82
-:1067500054EE6CEFB5FC91ED0A2024765EC50BC5B6
-:10676000853611FE55BCEECDB7CF47FC8F34BEF653
-:10677000AF076E4797A2F681567D0A279BEEECA2E3
-:1067800020FE5CCC9B8DFB55F135843FD8F358B887
-:1067900087056CA008FD1A156F46F8371CDED4FB80
-:1067A0004CD70DFC0CAF0CF412C997487CAAF75BD0
-:1067B000CF1A743CCED5F0CE42E87FF75A8D82F6E0
-:1067C000E175F8BD011EFC26DEE48F91C8DF1C09CF
-:1067D0002F2A3E54FC9C8EE7E34EDF23539CEEFFB2
-:1067E000355EDECA773CFA6DFC18C97F23F1DB9277
-:1067F00055117C19C17F2ABE1CAB6289CF543CD68F
-:10680000298CFCD6BACE18AB8705F167867F883F06
-:10681000CC53503CA65D62CF48DF850FFB28AF11FB
-:10682000891FA00D3BCAF59D11FCA7E26D24F9A3B9
-:10683000CAAF33CC7FDC22517E80F3E7AF0C1ECC95
-:106840002FAAF901350F704CC8BFC8F20CD81D989B
-:1068500077D998DD9384F65AAF5E9D87E71FCFAC5A
-:10686000E91EB702C69F99C9CB5EB4D342607B14C0
-:106870008FC39D196D70E3BD9D9126CF423D7E462D
-:10688000FAF5ED1C4ED12B082F4C996501B857A78E
-:10689000C6ED1E1672D843E59985D38AA99FC4DE3A
-:1068A000C4FB5024564EEB48524219ECE7CC0393FC
-:1068B000F29A59F0FCAFE4737BD62BE4F9501CFB41
-:1068C0003712C5B197800AB060BC7DD6D36513A0DE
-:1068D000FEEC83136D94FF6B0C5F1FF56806C50714
-:1068E00037D37CB77E31A05B9A13DCD790FE2BBEEA
-:1068F000CAEB2B27913F512570684F98CCFD58CF9C
-:10690000C438D447AA7E1A3CF1AA39347E7911F4EE
-:1069100017D387C0931F4F0FD56F4776FF3E0BE706
-:10692000A9D2BB73AD507FA1E50FE9680754ED7E96
-:10693000348BECD2DD1BB2D0BFA8DAF1FB2C3BC10B
-:10694000D10EF26FB4FCDC97F7DDB27363881DFCE7
-:106950006021F70B161B8F94A07D3AF7E64F1EC1FE
-:1069600078F8A407258A8BDDC3BA1F41BD5991CDA4
-:10697000F9886D31925C87F928EFD83AF927BB5036
-:106980009E9FCCFE405709FD4C055ABA8F0AE67906
-:106990002C05E361EB258A8705FB8FA33CE6D2B586
-:1069A000923E3511F561BC4D56705C3CEDE3DEF571
-:1069B000B62EACAF58CDEBE71A3CED3D38CFD37ACD
-:1069C0006BAB8213954F280FC90B9B0AB8DFB5E458
-:1069D0003189EC71759D494F25B7849ED35420F4BD
-:1069E000F98C6EE2FF9F0ABCFC78F5BB6FA62A9873
-:1069F0004F72C41540FB3B4F9ECF44F9559C7031FC
-:106A000007E97C92DEF14C359E7B8781E28705B9F0
-:106A100069720AF4CFFBE5CC27B05CB27AE933D5D2
-:106A20001807DD6A243F4ADD5FA3A468D0DF3CD6A7
-:106A3000F28B7BF1DE2E3C69243BBAB1E5A614361D
-:106A40000C9FAAE51EC0BF92C5D8F34D462A5F6CC5
-:106A5000B230058EB8AF2995E0979B142AD9024E23
-:106A60005F8DC25F1D69BE7CF0F715905705EB6125
-:106A70003EB0376D26FB143CE7A429CE1D1BC4B9DC
-:106A800026C1789B3B6336DE43C186155D688A2646
-:106A900017F0FCE2DB3DEBD3C98E5E7DEEB96A6890
-:106AA0005F5A509E5F00F76DDC7E95FCFC631D8F86
-:106AB00056505C7F87819F4F9CFBC2935929CF60C2
-:106AC000DCF52D1DF9DFAEEDE79EDB00E57D8FAD3A
-:106AD000D087D2FB773DAF4DECE7467C35D23D7C8D
-:106AE0007FBEFA7D3AF1CF0EE0AB9C7F9CAF5CABF2
-:106AF000D7D0FD3D5A507E37DEFB059D3B1DF9E9A1
-:106B0000C2E41F119DBB0F4B74FFAA1C57C72F1067
-:106B1000E7ADD5781F237B50C8F1CFC1F3C3FB3D50
-:106B2000D2F17116DAC39FFB167EEBB90F36610600
-:106B30001DE35A462A23DB8BF48E8956385F9186F3
-:106B4000DBC191ED0F17A871719E6FC73F8C0BD7FA
-:106B500009FDE9848DC525A0FE93FC51B998E7B8DD
-:106B6000EDA216FD2FF0EBDE0FB72FD9FB217A7CBB
-:106B7000A4FDDEA8ACC779B441B93BEDB486F943B6
-:106B8000F4F62D7D51CC1FB2EE90DF01757ACCB3B7
-:106B9000748C26B98078C3BC4CA063F20E842FEAB3
-:106BA000391E0307C1BFE27115261705CF79B1E37E
-:106BB000722ECAD9C8F3D61FBA4CF451E77BF4AA97
-:106BC00044E79F73519B7BE3F31FD97D3917F1771E
-:106BD00051D757847E5440DF978B78A87F9DCBF3A5
-:106BE000EF7B0F6A7DF57A3D8FEF4916F2074BE494
-:106BF0002BE4C7074E703FBEBE6327C9D3C14E1EEC
-:106C00004F7169BA4B5330FED070AE0BE5D9602A94
-:106C1000F7AF607E3BDEDB8C89420F6A07D2E783E9
-:106C20005C3B2AF2B5AA5F7701F9578FF378EBE85E
-:106C30003D526E3443BBE212F233D457ACCA58878C
-:106C4000747EC193849120F676EEFFD453FCED8DD3
-:106C5000688B4C762BD486E06FE81C1E993F9C61B4
-:106C6000AA9F1ECDEC21FD5C7AE5A7E41F9FE47985
-:106C700032D714CE4FEC10E727E7DA23FAD490F995
-:106C80005E52E587B01FE7BEF13FC497A76CF6538D
-:106C900028CFA25116E27CA9711E4912FD8A827981
-:106CA0004073A7F0C7CB646A77F964361AC7A4C6E5
-:106CB00050BEBE8C6DD2A2BD3B977967F077327D16
-:106CC000FFF643689FF7869C8FEFB1C07EA6FC71EC
-:106CD000699423B311ED238D24EED55B303F549F8F
-:106CE00015727B6B862C911E1B181D4D76CA9C0558
-:106CF000CEC5B85FB55F9996EB339887EC2CE61953
-:106D0000C8C57C26F30FE4629E53ED77D71BD10DE7
-:106D1000A41799B7E0AE9075C61472BDF929E69F25
-:106D2000419EB844FEB344FEEA29F4A31A0FF33C93
-:106D300061AF26E33D7CAFE5867B46BC5E06BCDAF0
-:106D400051FF3898DD8EFC3335C983FCE3DA2731F7
-:106D50007CB756DF61D881719D7A5D5F32D2F306D0
-:106D6000DF5FF548CFAE03EFEA95A9389EC781C033
-:106D70005ED7E0FDBA84FE72FA6E7A0FE36ECE1330
-:106D80005C8B3AB5EF925F5FDBBE9FFCF73AE6277C
-:106D9000FFBDAE2D9C5E0653799C3D923FC6142AE2
-:106DA000617C31672BE78BBB64D680728E89B8E932
-:106DB0009CD414B24782E3849D285F7E04ED97FE45
-:106DC00009925582A9FAA3DC6BD12E7267717BA65A
-:106DD000FF4F2F162C23B9E229F819BE8B11F6EEBE
-:106DE0009CF59BB572C87EE674F238617F14AB3AAD
-:106DF00048F8768C453CA4E7958F2DE4EF6472E962
-:106E00009D8F86C73523CFF1AC88E39CC4384F4EA5
-:106E100070DFF3D2D2B81C631EA29F2E0D5F5F7D80
-:106E2000F7A28E5F21E869C81F92787C6A24B98234
-:106E300079944A9147A91479944A9147A91479946D
-:106E40004A9147A91479944A9147A91479944A918F
-:106E500047A9147914AC3F895BA5F7703B9F417A31
-:106E6000E8421E1B13847B1322E031E1FD7B13A457
-:106E700070788C44FD8B0B773EE3CEC138A645C8B5
-:106E8000252506EDAF0B261E5FEA8871CC2D84FA0E
-:106E9000CA39CDBBF97B443BBD67294E58B818F9B8
-:106EA0006B30D1C0500EB90B1DF3111F274ECCCE45
-:106EB000DC4CF2D164C53C77EFDD37C7515CEE2D79
-:106EC00099C9B0E4CCECFCB50500CF344B44B720F5
-:106ED000277E50AEFA9330CFEC4E9ECF2891EB2A0E
-:106EE00071FEC6D1A67C8A6BE53B161586C40F4A97
-:106EF000C72CCF443BA84BA7BC87F154F75F740C59
-:106F0000FD2835FEA6F6EBCD9B598DFB9A933D717E
-:106F10006D1ECA1B602E946F763D6BC37DD935D133
-:106F20005233C92B458BFC5F2DF03D4BE1F6B05F32
-:106F3000AF6813D06F8F9A99E85678BEAA52E4AB27
-:106F40002A45BE0AF1730AE36650BE03F55876433C
-:106F50003D9691EFB9761794AF24BA6503E9A1EF96
-:106F6000C1E6225F7139938EF4FC8288C367178A69
-:106F70007769F9E50FF2715E9AA756C4DF2EEBC26E
-:106F8000F378EAB8E07846E51D3FE0F299C5E9F903
-:106F90007BD7B1CC8DEF69EF786D34C593021E8D30
-:106FA0005B170730F038CA2FF61AF76F592AE797A0
-:106FB0003B5E4DA17ECD220EEA4CE8CE4A40BD2B71
-:106FC000F84A850F7EC3DFF938F30086F275899F92
-:106FD000CF794777563CC001C9A4C1F8B873076F91
-:106FE000EF117CE79C20E613E761466F3AE2A3FFCE
-:106FF000F06BE9F702BCD1EC5FC6E5BD3F8BE43432
-:10700000F367E17BA1CB92F72CBEB7FDF5C17F59A9
-:1070100084EF6B2FEBBCCF21FCDB8333382CED3FAF
-:107020006B096D4FF2A6E37BDC5F1FFCE1227C9FC6
-:107030007B3969FF73F1D61058F7CA596CD73F3CBA
-:10704000635131F49F67F09C6842BA7999D397698C
-:10705000DF81F3783FB51DDC5E9FB5EFC0955750DB
-:107060001F1F88A17CBDAF3083EEBBB963CF6348DF
-:107070006F81FD3AE2838D6D7F7DEEB7D4CF4061A5
-:107080009479066F01865CDC457FBB1BF7352FDAF0
-:10709000FB19C29B8B6EA37DCE1BC5F9F9A9A2B9C2
-:1070A0008B903F0307F6FD0AF96F5E1C18B2B89F7C
-:1070B000174D849F9A572717631C2010D35D81F3C7
-:1070C000D7BF60B0229DD6BC9A320BE302C70B79C2
-:1070D0007CBA7ACAA674D4AF9A43CFEFFE2DC629E4
-:1070E0005F30517EC695C0EDBB1AB9A56805E16F4A
-:1070F000E76E7C371278DE4479D26A9803D7ABDE2C
-:107100003D89E2EAAF7FFD4105E2A144DEBE1BEB13
-:107110003FDB65D2E03DF4E8ED713F423EECD191BA
-:107120009F592DE0EADE517C3FD17DA584BFC44D3F
-:10713000E9A85F6B46FDE676DCF73C79D373E8E7B8
-:10714000B03D06CA155C7C1EEE0DC65D6CD5D12B1C
-:10715000D5C0F3315AA497CBD2A68A6770FE56DE0B
-:10716000EFB26913DDA7BBF52686EB413F86F2EA55
-:10717000B2B439ACFE62EB9E5CF4432FBD308FFCA1
-:107180005195CE557EA9D96508D387240992C57B30
-:107190000952B36E66063D5B2DC04B07B7059E6175
-:1071A000C1F197DA747E3DDC51B581ADC5F7C12AD6
-:1071B0003FD4A4DD5686E7ABD1B464A1BD529DDFB8
-:1071C00057817C71D1C48CA9F88E4EE8AB9AF63504
-:1071D000F3D1EE1D693FB1E25DDFE7820F3FF79922
-:1071E0003CA1F9C1C8F26F4D4C3915F26EF89E06FC
-:1071F00003D9EEEA7C6FEBBD75E89FD52770F97176
-:1072000016FAB7811C331771B9B76455787FA9880E
-:10721000BF4BACD7F765A1DE53E7FFA650956B7D5A
-:107220005928AF22C7CD9385BC7951227953D32EEB
-:107230009D93E19E6A8C6E0FBEDFA94167929F53BA
-:107240007B4DE2E3528BC4BDC3D8A78B3268DD9A75
-:107250003693DD04E36AA3FA62D11EAA8BE98B455B
-:107260003B277048663B04BA1293057E2608948536
-:10727000C41DABBD3ABB2977183CA3DD84EF73F086
-:10728000BF61FDB622CE2755BE685A8F59FA8A9043
-:107290004EABB6878FC3735942F82FE0DB991CEAD7
-:1072A0008FDBC4BEFBA573C427FD5FBF9F8E78AF85
-:1072B000D1B0B59847BC24F1EF1E00A6EF1E2E8971
-:1072C0007C64CDDFCD51482F973EAF23BE0D487D66
-:1072D00024D7CE1C5C407229A0EB23B9D65354416D
-:1072E000F22110DF578172EACCC17ADE3EBAAF429A
-:1072F00081F64E84B17D1C237D7FB9E801921FF396
-:1073000064FEBE81EDD459781C687D6F13F9153A7F
-:1073100025D4EFBE52A4E66DF4C173CB41BE093053
-:10732000655F3BF2619599E239603FB5BD8276DEDB
-:10733000C2642BC6C5AB701CA7037D68FE2F31E16C
-:10734000CB65889F45718E3B8B308F9DD347FE0365
-:107350005035D9E9F57F32901FD9AF1BD88D722AED
-:1073600037CEB1B008F651A7EF5E87A1A72BBABE02
-:107370002ECCFBCD95B93C627B385D057276F2EF81
-:107380002444FEB0BA88CB5FD05BAC05E942E2F89A
-:107390003DE67BF514CA9540F74492C7917C73D1C2
-:1073A000F7442CCA87D3A0C7DD217EFEE9A57B2840
-:1073B0004FBF00DF654079EFDA707A18FCEA67E4C6
-:1073C000EFB1C742EA910EB784C3917484F4E80F19
-:1073D000933B6EA29B3D82AF6A6775D7E33D0CC1BC
-:1073E00077002C87C04723E088FEAC9CDB097BF04C
-:1073F000BF61DEBA71FE5EF2CFF7F177B1CDA0BF0B
-:10740000083E104D7963CD3ED04F895C3FA15EA808
-:107410008DEDA6B854E08081F2230F777C4CEF19F4
-:10742000810E29FE52DBF15A32FAED3EF4139248F6
-:107430000F26D33B95031DC9E86FA8F5751A6F9603
-:10744000788F4F76BA5AEF94FD59B8FF5AA93B1777
-:10745000DB7D8516D11F60196146E7A89338BFB35D
-:107460000E99E47924DEF60A7A05B9904BEF2C0EDA
-:10747000F1B8802A07AA853C398AF5399CEF2D6A34
-:107480005E49C2F772D1C3CA879B8A547BB881E236
-:1074900036BB8A147EAF623CCDCBE34AD45EFFFAA2
-:1074A000E5DC0939384E11E342E4D0C4A05C41FE6A
-:1074B0004F25FE7F58970CE7AA794EB236A39C5A07
-:1074C000BCA614BAB3E5DA15A5142F13EF3F23F7C2
-:1074D000154947F6228EDF1A4D7C4962C87C97C059
-:1074E0005D4FCD233943EFE8EF4F7CBC14E313BF6E
-:1074F00058BC99E87948DF84F2399E673B97E3C826
-:1075000036D734D7D3F1F286967529C3EC23729F10
-:10751000D58E96D264E5FA7A75BF974CEAFE66E995
-:107520009242EF61C19AD22428971BFFD17BE0E7FA
-:10753000BDD461F0A35EAD5EBC625DDC3074739D52
-:107540003ED81EA2BF26207E3D94D71869FF9165C4
-:107550009DE4EFC5381103BE6A25FE027E09D10BFA
-:107560006542BF0EC51BAA968E47BF9339968E47BC
-:107570003D037C55611DC6AFC42F4B34F476C34D1B
-:1075800065E47E3E2BE271D2B222CE2FA76CF66F5D
-:1075900050BE8EF4BD85619AF4ADDF5BA46906DF51
-:1075A000417E4B4B8E51300F54323B9AF73B6CB2BD
-:1075B00060DCA6FFF09714D7ED7FC4BC80E70BCC4E
-:1075C0006C34B477A54EDD11AA473CD3385F46171B
-:1075D00070BBC595ADFBF6B8504ECC505C88EC86C0
-:1075E0009C68CA93047C9F92DEEAEF2CB4603E2331
-:1075F000D00DDE21F093EBEBFF4A46FD1AE8FC8844
-:10760000DE8305BEFA98DE896D10EFF48EFAC43B76
-:10761000AB6E2586BE8B2BFBA014FB6D1465303E34
-:10762000C0E35A6AA9FAFF21FEEF946985C3FABF45
-:10763000090E73685C4049192E8E121A17C8D4F2CD
-:10764000B800961817C8CCE4710184312E8025C685
-:1076500005B01EE30208635C00618C0B208C710195
-:107660002C312E80F59F89EF1FFA4130F178A599D2
-:10767000E4FA4A7CDF0EF7B7F230CF3BAD6C9529C8
-:107680007F8BDF3FA07EBBEEDD4CBB7837E3DD4C6C
-:10769000793CD701D98A2872E9068E631CC7B55F89
-:1076A000B2AE41B9D2B480D6DFD059F8DE62AC6F49
-:1076B000D559350AD111C7638B44EFF46B3A5B2976
-:1076C000EE549C72584FF56D12C338E95D06EEE733
-:1076D0003A65A8CDA33C28D9C14E4337F91FB57BE5
-:1076E00025A532F49DC6F4AB2407D47CF232DEC467
-:1076F0009C5E935239CC3B90A177E7E2DDF432CC2B
-:1077000033E37B71F92B7AD7EF04877414D2E156F7
-:10771000FEFED902FF88DF23DE35D574EE5F87EFEA
-:10772000A122F3CD43DFD345E49DEBA789BCB28D05
-:107730007F5F51F664E5BE03B0DEE02603D91BEEA1
-:1077400042C703D39230EF6FA7F8C8F1C326F28B7C
-:107750003EDC7C53587C84E53B1E9C46F9F9B11411
-:10776000AF68D449A48F67974D4CC17B9C7D42473D
-:107770007AA737AF7C35F66B9CAA503CAAC4C01ED2
-:10778000A079C47B29151F25CD924703F05266A529
-:1077900077F64BE09A305ED9AF33AFC7774D4B18D1
-:1077A0007FE7A0D24DE36689E8060304789F15E2DF
-:1077B0003E9774FEF94B7CC7709F81DBAD691A9EC2
-:1077C000BF4EDBC8DF33DCCF1C7AD4B3CB91BA64B5
-:1077D000D28F7FEA837A47F4D8746E972B2938FFCB
-:1077E000D2933A7A6F5B92F2932C07E9E9627AC7F7
-:1077F00020F917C9D76E1E997F22DF311CD771B9C6
-:1078000002F748FE5017D225C5651C549E6CAAA2EB
-:10781000F277E27B88EBDFFF0F9C453F312D25C6D9
-:107820008A726EC4EFDDA2BEFD7BAF17C4FBB53418
-:107830004D4FBE82F7F177B315EF437D2778CA56D7
-:10784000BE1FF1648F656E0B7D0F061210EEB5142E
-:107850000F22615CDB6BC7EF8E060E4B167A977CAE
-:107860009D7CDCFC08BE1371654A1649C1F8F7A679
-:107870009264D877E9840CDAB7CBC7E3A37443C921
-:10788000183FE7F84ACF731C9B5618AC9F27F82681
-:1078900000FD399DFCD083F4F61DE2A6BBB0BF9B72
-:1078A00099E87B6AFA83FDCCBB791CC54F55BA19A0
-:1078B0006C4BD98174F39E90FB8B17BFAB43FDDFFC
-:1078C0009BEFE8C17D54545E7D2499CE377CFC4A01
-:1078D0007DA71E19BF0A959FFF3FDEA79F6A6AA07A
-:1078E000F29DA655547637B9A93D44FE5F1A41FE74
-:1078F00047C63FAF227F47C63F99518923FD09FC08
-:10790000CDE3CD11F1CEB251F7AE87FB9BBD456FF4
-:10791000C52A35FE89EF87579A491EFCF7B461E303
-:107920009EEABD99294E3AC84C7978FFB3B2276ACE
-:1079300035D0AE9DCEF1A7C61D913FF07CC81F5833
-:10794000227F68B541FE78560F2C5CC0F5BC9BF4D5
-:10795000BC89F0BA6E0DC80F80EF639630F97125BF
-:10796000427E80C371377D57D56960182754DF5137
-:10797000CE82E28BBC61E48997CB937151DEE7E95B
-:107980007BFFFA287A9F7B5CBC873BBE81BF87ABBD
-:1079900064E5B4EE30722516F171DFA881B37F8003
-:1079A000FEF7FDDE4CF6CABAD1CB8AFE19B9724D8C
-:1079B0007CD7F234FEAE80F6DB7E57E03109F3A1CE
-:1079C0008DF7301BE259FD5D811491CFFE1EBF2B58
-:1079D000306D7AE177FF5D815BA78F5F1CFABB0298
-:1079E000B7FA3238ACFEAE001BBF7884DF15983D85
-:1079F0003DE9FADF15B86D3AF71747FA5D01B02790
-:107A0000CB705C92CD3E07CB34B1CFC8EF694F8AC3
-:107A1000FC5D97C6B118CBD258B796EA359E02FAEC
-:107A20000E5EE3FD25F981F98E9FE3794B9FB04D02
-:107A3000C90638CDE02539D99B67BF13EBAFD9EC28
-:107A400077E13A917173C42DFAF7B09FBBB13DF263
-:107A5000DD958ACF15D3B9DC6814E58CE6E1BF2744
-:107A60006F9CCEF3F237DA37ECB706D71BDAFFA6F6
-:107A7000A505B81FD86F2DD6C37EEBB064E684B0E1
-:107A8000EF53AFA73337D155E3744E5F20CFE67D78
-:107A9000C8ED412AB3B49E78B41FC73CE489C7FD42
-:107AA0008E691930E177107F740F9850BFFF71F520
-:107AB0008009EBFF68E7EF9523E77F793AF703B298
-:107AC000660CD0F8F168E3937D3E108FF65356D5DF
-:107AD00087EB28DFB27732E997F142BF8C7F68826B
-:107AE000AF0FE86DFCB638CA67B3E2446AAF3172D3
-:107AF0003EAD79A8F2E00185BEDB9AF76188BD331F
-:107B0000D903FB0EB3BFB483FCDD25C0784F7B7572
-:107B10000423CDA27DE564FCDDE5182137D04E5B62
-:107B20000C72C159F5E69794F7C7F1381FE66891D2
-:107B3000FE7CBA41F17D9A05FDD0E50BD674915FCC
-:107B4000B875A85EF899FBD7A1DF0CF65B587D4DA0
-:107B5000E5912ED437B57BC3EB9D0D57C97F05FB4F
-:107B60002DACFE9E5F9ED3F3DF2F08AF07FCEE45E2
-:107B7000BA54F17B5CE79D8C7EDE71679495BFDF24
-:107B8000F7D2EF95EC10DF3FEFFC8F599C6E04BEEF
-:107B900061BC3774FCC8F4D14CFDDDB35836F2C378
-:107BA0008D4A552E0DFDFE899EB929BE373786E4D4
-:107BB0008E4BF855F59516D2F369F546925F25720E
-:107BC0009415E1A1DF3F2993859CF212FFF7DC1E9B
-:107BD0004F713C3A00C2095329EF93DCCCE1812478
-:107BE00003C987124D79DD1E28DFD4847FC7FE2CA0
-:107BF000CA0719F9977F87E9D27BF977E25AA5106E
-:107C0000FDDC66C9BE0DBF7B6C96441CB1DA4CF935
-:107C1000827E8C2FC279B6C47BB62D8375B6DC9973
-:107C200043F6713FE3F2D4BD80E7ADB6C4972F5E53
-:107C300081ED0BA750FBC16F263E5E80F653759415
-:107C400015EDA72D366E5F6F999F4DEDAF4BCA1A9C
-:107C50003CB7FB2146EB6C99CFCFBDE5F171E2FB60
-:107C60000B8F09F9794B8B7D34E6A366591C1710ED
-:107C70005F63443E6E4B06D443F99454BEF07E9C41
-:107C8000672ADFEFEF6C0AC98FE30BA73CBE5B21CD
-:107C900035E2C7BC906B6E0CF9C1FF0BB81F749432
-:107CA000704700000000000000000000000000001D
-:087CB00005020D0000000000B8
-:00000001FF
diff --git a/firmware/bnx2x-e1h-5.2.13.0.fw.ihex b/firmware/bnx2x-e1h-5.2.13.0.fw.ihex
deleted file mode 100644
index ea3e254..0000000
--- a/firmware/bnx2x-e1h-5.2.13.0.fw.ihex
+++ /dev/null
@@ -1,12849 +0,0 @@
-:1000000000003BE8000000600000068800003C5053
-:1000100000001968000042E0000000AC00005C50E5
-:1000200000008DF800005D00000000E80000EB001B
-:100030000000E3140000EBF0000000940001CF0882
-:10004000000058E80001CFA0000000C40002289082
-:100050000000F9640002295800000004000322C0D7
-:10006000020400480000000F020400540000004594
-:1000700002040058000000840204005C0000000636
-:100080000204007000000004020400780000000078
-:100090000204007C121700000204008022170000F6
-:1000A00002040084321700000604008800000005E6
-:1000B0000204009C12150000020400A0221500009A
-:1000C000020400A432150000060400A80000000489
-:1000D000020400B802100000020400BC001000007E
-:1000E000020400C010100000020400C42010000030
-:1000F000020400C830100000020400CC40100000D0
-:10010000060400D000000003020400DC0010000020
-:10011000020400E012140000020400E422140000B3
-:10012000020400E832140000020400EC4214000053
-:10013000060400F000000003010401240000000098
-:1001400001040128000000000104012C000000004F
-:100150000104013000000000020401D00000890603
-:1001600002040004000000FF02040008000000FF79
-:100170000204000C000000FF02040010000000FF59
-:1001800002040014000000FF02040018000000FF39
-:100190000204001C000000FF02040020000000FF19
-:1001A000020400240000003E0204002800000000B9
-:1001B0000204002C0000003F020400300000003F59
-:1001C000020400340000003F020400380000003F39
-:1001D0000204003C0000003F020400400000003F19
-:1001E000020400440000003F020404CC00000001AF
-:1001F00002042008000002110204200C000002008A
-:10020000020420100000020402042014000002195D
-:100210000204201C0000FFFF020420200000FFFF5A
-:10022000020420240000FFFF020420280000FFFF3A
-:1002300002042038000000200204203C00000000DE
-:100240000204204000000034020420440000003575
-:10025000060420480000001C020420B80000000131
-:10026000060420BC0000005F0204223807FFFFFFE5
-:100270000204223C0000003F0204224007FFFFFF6F
-:10028000020422440000000F010422480000000084
-:100290000104224C00000000010422500000000074
-:1002A0000104225400000000010422580000000054
-:1002B0000104225C00000000010422600000000034
-:1002C0000104226400000000010422680000000014
-:1002D0000104226C000000000104227000000000F4
-:1002E00001042274000000000104227800000000D4
-:1002F0000104227C000000000C042000000003E840
-:100300000A042000000000010B0420000000000A85
-:1003100002050044000000200205004800000032F1
-:10032000020500900215002002050094021500202D
-:1003300002050098000000300205009C0810000033
-:10034000020500A000000033020500A400000030F8
-:10035000020500A800000031020500AC0000000208
-:10036000020500B000000005020500B40000000610
-:10037000020500B800000002020500BC00000002F7
-:10038000020500C000000000020500C400000005D6
-:10039000020500C800000002020500CC00000002B7
-:1003A000020500D000000002020500D40000000198
-:1003B00002050114000000010205011C00000001FB
-:1003C00002050120000000020205020400000001F5
-:1003D0000205020C0000004002050210000000406F
-:1003E0000205021C0000002002050220000000138C
-:1003F0000205022400000020060502400000000A59
-:1004000004050280002000000205005000000007E3
-:100410000205005400000007020500580000000813
-:100420000205005C000000080205006000000001F9
-:100430000605006400000003020500D80000000665
-:100440000205000400000001020500080000000190
-:100450000205000C00000001020500100000000170
-:100460000205001400000001020500180000000150
-:100470000205001C00000001020500200000000130
-:100480000205002400000001020500280000000110
-:100490000205002C000000010205003000000001F0
-:1004A00002050034000000010205003800000001D0
-:1004B0000205003C000000010205004000000001B0
-:1004C000020500E00000000D020500E80000000742
-:1004D000020500F000000007020500F80000000718
-:1004E000020500E40000002D020500EC00000027DA
-:1004F000020500F400000027020500FC00000027B0
-:10050000020500E00000001D020500E800000017E1
-:10051000020500F000000017020500F800000017B7
-:10052000020500E40000003D020500EC0000003779
-:10053000020500F400000037020500FC000000374F
-:10054000020500E00000004D020500E80000004741
-:10055000020500F000000047020500F80000004717
-:10056000020500E40000006D020500EC00000067D9
-:10057000020500F400000067020500FC00000067AF
-:10058000020500E00000005D020500E800000057E1
-:10059000020500F000000057020500F800000057B7
-:1005A000020500E40000007D020500EC0000007779
-:1005B000020500F400000077020500FC000000774F
-:1005C0000406100002000020020600DC000000010A
-:1005D000010600D80000000004060200000302200B
-:1005E000020600DC00000000010600B80000000068
-:1005F000010600C800000000010600BC0000000069
-:10060000010600CC000000000718040000A900004B
-:10061000081807C800070223071C00002C2C000044
-:10062000071C800038930B0C071D0000293119317D
-:10063000081D686052F40225011800000000000047
-:10064000011800040000000001180008000000006C
-:100650000118000C0000000001180010000000004C
-:100660000118001400000000021800200000000122
-:1006700002180024000000020218002800000003F5
-:100680000218002C000000000218003000000004D6
-:1006900002180034000000010218003800000000B9
-:1006A0000218003C00000001021800400000000495
-:1006B0000218004400000000021800480000000179
-:1006C0000218004C00000003021800500000000057
-:1006D0000218005400000001021800580000000435
-:1006E0000218005C00000000021800600000000119
-:1006F00002180064000000030218006800000000F7
-:100700000218006C000000010218007000000004D4
-:1007100002180074000000000218007800000004B5
-:100720000218007C00000003061800800000000290
-:10073000021800A400003FFF021800A8000003FFF9
-:100740000218022400000000021802340000000019
-:100750000218024C00000000021802E4000000FF32
-:100760000618100000000400021B8BC000000001EE
-:10077000021B800000000034021B804000000018B3
-:10078000021B80800000000C021B80C000000020C3
-:100790000C1B83000007A1200A1B83000000013806
-:1007A0000B1B830000001388021B83C0000001F4B0
-:1007B000021B1480000000010A1B148000000000CE
-:1007C000061A1000000003B3041A1ECC0001022711
-:1007D000061AA020000000C8061AA00000000002AF
-:1007E000021A1ED000000000061A1ED800000006E3
-:1007F000061A36E800000004061A36E0000000027F
-:10080000061A500000000002061A500800000004FA
-:10081000061A501800000004061A502800000004B0
-:10082000061A503800000004061A50480000000460
-:10083000061A505800000004061A50680000000410
-:10084000061A507800000002041A404000020228F4
-:10085000061A400000000002061A400800000002CC
-:10086000041A62C00020022A061AD1000000000209
-:10087000061A200000000124061AB000000000281B
-:10088000061AB1400000000C061A330000000014E4
-:10089000061A33A000000068061A81080000000252
-:1008A000061AD1C800000002061AD1D800000020A4
-:1008B000061A249000000124061AB0A000000028A7
-:1008C000061AB1700000000C061A33500000001424
-:1008D000061A354000000068061A81100000000268
-:1008E000061AD1D000000002061AD25800000020DB
-:1008F000021A292000000000061A30000000000241
-:10090000041A30080005024A061A301C00000009CB
-:10091000061A320000000008061A5000000000020B
-:10092000061A508000000012061A40000000000263
-:10093000061AD0C000000002021A2924000000009C
-:10094000061A304000000002041A30480005024F29
-:10095000061A305C00000009061A32200000000868
-:10096000061A501000000002061A50C800000012BB
-:10097000061A400800000002061AD0C80000000253
-:10098000021A292800000000061A30800000000228
-:10099000041A308800050254061A309C0000000931
-:1009A000061A324000000008061A5020000000021B
-:1009B000061A511000000012041A401000020259D9
-:1009C000061AD0D000000002021A292C00000000F4
-:1009D000061A30C000000002041A30C80005025B8D
-:1009E000061A30DC00000009061A32600000000818
-:1009F000061A503000000002061A5158000000127A
-:100A0000041A401800020260061AD0D80000000242
-:100A1000021A293000000000061A3100000000020E
-:100A2000041A310800050262061A311C0000000990
-:100A3000061A328000000008061A5040000000022A
-:100A4000061A51A000000012041A4020000202679A
-:100A5000061AD0E000000002021A2934000000004B
-:100A6000061A314000000002041A314800050269EC
-:100A7000061A315C00000009061A32A000000008C6
-:100A8000061A505000000002061A51E80000001239
-:100A9000041A40280002026E061AD0E80000000284
-:100AA000021A293800000000061A318000000002F6
-:100AB000041A318800050270061A319C00000009F2
-:100AC000061A32C000000008061A5060000000023A
-:100AD000061A523000000012041A4030000202755B
-:100AE000061AD0F000000002021A293C00000000A3
-:100AF000061A31C000000002041A31C8000502774E
-:100B0000061A31DC00000009061A32E00000000875
-:100B1000061A507000000002061A527800000012F7
-:100B2000041A40380002027C061AD0F800000002C5
-:100B30000200A294071D29110200A29800000000E3
-:100B40000200A29C009C04240200A2A0000000005D
-:100B50000200A2A4000002090200A270000000002E
-:100B60000200A274000000000200A2700000000059
-:100B70000200A274000000000200A2700000000049
-:100B80000200A274000000000200A2700000000039
-:100B90000200A27400000000020100B40000000185
-:100BA000020100B800000001020100DC00000001A9
-:100BB0000201010000000001020101040000000127
-:100BC0000201007C003000000201008400000028C7
-:100BD0000201008C0000000002010130000000044E
-:100BE0000201025C00000001020103280000000075
-:100BF0000201607000000007020160800000000137
-:100C00000201055400000030020100C40000000190
-:100C1000020100CC00000001020100F80000000108
-:100C2000020100F00000000102010080003000001D
-:100C3000020100880000002802010090000000006E
-:100C40000201013400000004020102DC0000000186
-:100C50000201032C00000000020160740000000784
-:100C60000201608400000001020105640000003000
-:100C7000020100C800000001020100D000000001D4
-:100C8000020100FC00000001020100F4000000016C
-:100C9000020C100000000020020C200800000211CD
-:100CA000020C200C00000200020C201000000204C4
-:100CB000020C201C0000FFFF020C20200000FFFFA0
-:100CC000020C20240000FFFF020C20280000FFFF80
-:100CD000060C203800000002020C20400000003406
-:100CE000020C204400000035020C204800000020C7
-:100CF000020C204C00000021020C205000000022B9
-:100D0000020C205400000023020C20580000002494
-:100D1000020C205C00000025020C20600000002670
-:100D2000020C206400000027020C2068000000284C
-:100D3000020C206C00000029020C20700000002A28
-:100D4000020C20740000002B060C207800000056D6
-:100D5000020C21D000000001020C21D4000000018F
-:100D6000020C21D800000001020C21DC000000016F
-:100D7000020C21E000000001020C21E4000000014F
-:100D8000020C21E800000001020C21EC000000012F
-:100D9000020C21F000000001020C21F4000000010F
-:100DA000060C21F800000010020C223807FFFFFF9C
-:100DB000020C223C0000003F020C224007FFFFFF14
-:100DC000020C22440000000F010C22480000000029
-:100DD000010C224C00000000010C22500000000019
-:100DE000010C225400000000010C225800000000F9
-:100DF000010C225C00000000010C226000000000D9
-:100E0000010C226400000000010C226800000000B8
-:100E1000010C226C00000000010C22700000000098
-:100E2000010C227400000000010C22780000000078
-:100E3000010C227C000000000C0C2000000003E8E4
-:100E40000A0C2000000000010B0C20000000000A2A
-:100E5000020C400800000411020C400C00000400C9
-:100E6000020C401000000404020C40140000042195
-:100E7000020C401C0000FFFF020C40200000FFFF9E
-:100E8000020C40240000FFFF020C40280000FFFF7E
-:100E9000020C403800000046020C403C00000005F7
-:100EA000060C404000000002020C40480000000A0E
-:100EB000020C404C000000F0060C40500000001FE7
-:100EC000020C40CC00000001060C40D00000003AAB
-:100ED000020C41B800000001060C41BC00000003F8
-:100EE000020C41C800000001020C41CC00000001CE
-:100EF000060C41D00000001A020C423807FFFFFF29
-:100F0000020C423C0000003F020C424007FFFFFF82
-:100F1000020C42440000000F010C42480000000097
-:100F2000010C424C00000000010C42500000000087
-:100F3000010C425400000000010C42580000000067
-:100F4000010C425C00000000010C42600000000047
-:100F5000010C426400000000010C42680000000027
-:100F6000010C426C00000000010C42700000000007
-:100F7000010C427400000000010C427800000000E7
-:100F8000010C427C00000000010C428000000000C7
-:100F90000C0C4000000003E80A0C400000000001B7
-:100FA0000B0C40000000000A020D0044000000325B
-:100FB000020D008C02150020020D00900215002089
-:100FC000020D009408100000020D0098000000338C
-:100FD000020D009C00000002020D00A000000000B5
-:100FE000020D00A400000005020D00A8000000058D
-:100FF000060D00AC00000002020D00B4000000026B
-:10100000020D00B800000003020D00BC0000000249
-:10101000020D00C000000001020D00C80000000227
-:10102000020D00CC00000002020D010800000001CA
-:10103000020D015C00000001020D016400000001CE
-:10104000020D016800000002020D02040000000110
-:10105000020D020C00000020020D021000000040F2
-:10106000020D021400000040020D022000000003E7
-:10107000020D022400000018060D0280000000127C
-:10108000040D03000024027E020D004C000000014C
-:10109000020D005000000002020D00540000000884
-:1010A000020D005800000008060D005C000000045E
-:1010B000020D00C400000004020D00040000000145
-:1010C000020D000800000001020D000C00000001EC
-:1010D000020D001000000001020D001400000001CC
-:1010E000020D001800000001020D001C00000001AC
-:1010F000020D002000000001020D0024000000018C
-:10110000020D002800000001020D002C000000016B
-:10111000020D003000000001020D0034000000014B
-:10112000020D003800000001020D003C000000012B
-:10113000020D011400000009020D011C0000000A4C
-:10114000020D012400000007020D012C0000000721
-:10115000020D01340000000C020D013C0000000BE8
-:10116000020D014400000007020D011800000029D3
-:10117000020D01200000002A020D012800000027B6
-:10118000020D013000000027020D01380000002C84
-:10119000020D01400000002B020D01480000002755
-:1011A000020D011400000019020D011C0000001ABC
-:1011B000020D012400000017020D012C0000001791
-:1011C000020D01340000001C020D013C0000001B58
-:1011D000020D014400000017020D01180000003943
-:1011E000020D01200000003A020D01280000003726
-:1011F000020D013000000037020D01380000003CF4
-:10120000020D01400000003B020D014800000037C4
-:10121000020D011400000049020D011C0000004AEB
-:10122000020D012400000047020D012C00000047C0
-:10123000020D01340000004C020D013C0000004B87
-:10124000020D014400000047020D01180000006972
-:10125000020D01200000006A020D01280000006755
-:10126000020D013000000067020D01380000006C23
-:10127000020D01400000006B020D014800000067F4
-:10128000020D011400000059020D011C0000005A5B
-:10129000020D012400000057020D012C0000005730
-:1012A000020D01340000005C020D013C0000005BF7
-:1012B000020D014400000057020D011800000079E2
-:1012C000020D01200000007A020D012800000077C5
-:1012D000020D013000000077020D01380000007C93
-:1012E000020D01400000007B020D01480000007764
-:1012F000020E004C00000032020E00940215002085
-:10130000020E009802150020020E009C0000003022
-:10131000020E00A008100000020E00A4000000331E
-:10132000020E00A800000030020E00AC00000031E8
-:10133000020E00B000000002020E00B40000000423
-:10134000020E00B800000000020E00BC0000000207
-:10135000020E00C000000002020E00C400000000E7
-:10136000020E00C800000002020E00CC00000007C0
-:10137000020E00D000000002020E00D400000002A5
-:10138000020E00D800000001020E00E4000000017F
-:10139000020E014400000001020E014C0000000199
-:1013A000020E015000000002020E020400000001C3
-:1013B000020E020C00000040020E0210000000406D
-:1013C000020E021C00000004020E02200000002099
-:1013D000020E02240000000E020E02280000001B74
-:1013E000060E030000000012040E0280001B02A281
-:1013F000020E00540000000C020E0058000000090C
-:10140000020E005C0000000F020E006000000010E1
-:10141000020E00640000000B060E006800000003CE
-:10142000020E00DC00000003020E000400000001B8
-:10143000020E000800000001020E000C0000000176
-:10144000020E001000000001020E00140000000156
-:10145000020E001800000001020E001C0000000136
-:10146000020E002000000001020E00240000000116
-:10147000020E002800000001020E002C00000001F6
-:10148000020E003000000001020E003400000001D6
-:10149000020E003800000001020E003C00000001B6
-:1014A000020E004000000001020E00440000000196
-:1014B000020E01100000000F020E01180000000EC5
-:1014C000020E012000000000020E012800000000B2
-:1014D000020E01140000002F020E011C0000002E5D
-:1014E000020E012400000000020E012C000000008A
-:1014F000020E01100000001F020E01180000001E65
-:10150000020E012000000000020E01280000000071
-:10151000020E01140000003F020E011C0000003EFC
-:10152000020E012400000000020E012C0000000049
-:10153000020E01100000004F020E01180000004EC4
-:10154000020E012000000000020E01280000000031
-:10155000020E01140000006F020E011C0000006E5C
-:10156000020E012400000000020E012C0000000009
-:10157000020E01100000005F020E01180000005E64
-:10158000020E012000000000020E012800000000F1
-:10159000020E01140000007F020E011C0000007EFC
-:1015A000020E012400000000020E012C00000000C9
-:1015B0000730040000E50000083007D8000502BD30
-:1015C000073400002EF7000007348000311A0BBEEC
-:1015D00007350000356F18050735800038C42561D0
-:1015E0000736000014C5339308363400398002BF33
-:1015F0000130000000000000013000040000000085
-:1016000001300008000000000130000C0000000064
-:101610000130001000000000013000140000000044
-:10162000023000200000000102300024000000020F
-:1016300002300028000000030230002C00000000EF
-:1016400002300030000000040230003400000001CD
-:1016500002300038000000000230003C00000001B1
-:10166000023000400000000402300044000000008E
-:1016700002300048000000010230004C000000036E
-:101680000230005000000000023000540000000151
-:1016900002300058000000040230005C000000002E
-:1016A000023000600000000102300064000000030E
-:1016B00002300068000000000230006C00000001F1
-:1016C00002300070000000040230007400000000CE
-:1016D00002300078000000040230007C00000003AB
-:1016E0000630008000000002023000A400003FFF2E
-:1016F000023000A8000003FF0230022400000000B6
-:1017000002300234000000000230024C00000000F1
-:10171000023002E40000FFFF063020000000080055
-:1017200002338BC000000001023380000000001A69
-:10173000023380400000004E023380800000001021
-:10174000023380C0000000200C3383000007A1207A
-:101750000A338300000001380B3383000000138834
-:10176000023383C0000001F40C3383801DCD65007B
-:101770000A3383800004C4B40B338380004C4B4095
-:101780000A331480000000000233148000000001BE
-:10179000063220000000010206328020000000C84E
-:1017A000063280000000000206323DA8000000045E
-:1017B00006323D800000000904323DA4000102C150
-:1017C00006323D00000000200632500000000400F8
-:1017D0000632400000000004063240D00000000243
-:1017E00006326B680000000204326B70000202C215
-:1017F00006326B1000000002043274C0000202C402
-:101800000632DA40000000020632E0000000080064
-:10181000023308000100000004330C00001002C66F
-:10182000023308000000000004330C40001002D610
-:1018300006322450000000B406322AD00000000214
-:1018400006321000000001A002323DB80000000086
-:101850000632500000000020063251000000002037
-:101860000632520000000020063253000000002023
-:10187000063254000000002006325500000000200F
-:1018800006325600000000200632570000000020FB
-:1018900006325800000000200632590000000020E7
-:1018A00006325A000000002006325B0000000020D3
-:1018B00006325C000000002006325D0000000020BF
-:1018C00006325E000000002006325F0000000020AB
-:1018D00006326B780000005206326E080000000CE1
-:1018E0000632DA880000000206322720000000B429
-:1018F00006322AD80000000206321680000001A03D
-:1019000002323DBC00000000063250800000002082
-:101910000632518000000020063252800000002074
-:101920000632538000000020063254800000002060
-:10193000063255800000002006325680000000204C
-:101940000632578000000020063258800000002038
-:10195000063259800000002006325A800000002024
-:1019600006325B800000002006325C800000002010
-:1019700006325D800000002006325E8000000020FC
-:1019800006325F800000002006326CC0000000526A
-:1019900006326E380000000C0632DA9000000002B9
-:1019A00002322A300000000006324010000000021F
-:1019B0000632D0000000000602322A340000000087
-:1019C00006324020000000020632D0180000000657
-:1019D00002322A38000000000632403000000002C7
-:1019E0000632D0300000000602322A3C000000001F
-:1019F00006324040000000020632D04800000006D7
-:101A000002322A400000000006324050000000026E
-:101A10000632D0600000000602322A4400000000B6
-:101A200006324060000000020632D0780000000656
-:101A300002322A4800000000063240700000000216
-:101A40000632D0900000000602322A4C000000004E
-:101A500006324080000000020632D0A800000006D6
-:101A6000072004000093000008200780001002E611
-:101A7000072400002ADE0000072480002E050AB893
-:101A80000824E4A061D202E8012000000000000068
-:101A900001200004000000000120000800000000F8
-:101AA0000120000C000000000120001000000000D8
-:101AB00001200014000000000220002000000001AE
-:101AC0000220002400000002022000280000000381
-:101AD0000220002C00000000022000300000000462
-:101AE0000220003400000001022000380000000045
-:101AF0000220003C00000001022000400000000421
-:101B00000220004400000000022000480000000104
-:101B10000220004C000000030220005000000000E2
-:101B200002200054000000010220005800000004C0
-:101B30000220005C000000000220006000000001A4
-:101B40000220006400000003022000680000000082
-:101B50000220006C00000001022000700000000460
-:101B60000220007400000000022000780000000441
-:101B70000220007C0000000306200080000000021C
-:101B8000022000A400003FFF022000A8000003FF85
-:101B900002200224000000000220023400000000A5
-:101BA0000220024C00000000022002E40000FFFFBF
-:101BB000062020000000080002238BC00000000166
-:101BC0000223800000000010022380400000001269
-:101BD0000223808000000030022380C00000000E3D
-:101BE000022383C0000001F40223148000000001DE
-:101BF0000A231480000000000622100000000042AA
-:101C000006227020000000C80622700000000002BA
-:101C1000022211E80000000006223000000000C08F
-:101C2000062240700000008006225280000000045E
-:101C30000622670000000100062290000000040058
-:101C400004226B08002002EA02230800013FFFFF84
-:101C500004230C000010030A022308000000000007
-:101C600004230C400010031A06228100000000A08B
-:101C7000062286000000004006228C000000003C86
-:101C80000622B0000000020006228800000000804A
-:101C900006228DE00000003C0622404000000006C5
-:101CA00006228380000000A006228700000000407A
-:101CB00006228CF00000003C0622B8000000020062
-:101CC00006228A000000008006228ED00000003C20
-:101CD000062240580000000606228000000000088E
-:101CE000022211480000000006223300000000021A
-:101CF000062260400000003006228020000000081C
-:101D00000222114C000000000622330800000002ED
-:101D1000062261000000003006228040000000081A
-:101D200002221150000000000622331000000002C1
-:101D3000062261C00000003006228060000000081A
-:101D40000222115400000000062233180000000295
-:101D50000622628000000030062280800000000819
-:101D60000222115800000000062233200000000269
-:101D70000622634000000030062280A00000000818
-:101D80000222115C0000000006223328000000023D
-:101D90000622640000000030062280C00000000817
-:101DA0000222116000000000062233300000000211
-:101DB000062264C000000030062280E00000000817
-:101DC00002221164000000000622333800000002E5
-:101DD0000622658000000030021610000000002876
-:101DE00002170008000000020217002C0000000388
-:101DF0000217003C00000004021700440000000825
-:101E000002170048000000020217004C000000907A
-:101E1000021700500000009002170054008000904C
-:101E20000217005808140000021700600000008A22
-:101E300002170064000000800217006800000081A3
-:101E40000217006C000000800217007000000006FE
-:101E500002170078000007D00217007C0000076C12
-:101E600002170038007C1004021700040000000F65
-:101E70000616402400000002021640700000001CFC
-:101E80000216420800000001021642100000000184
-:101E90000216422000000001021642280000000144
-:101EA0000216423000000001021642380000000114
-:101EB00002164260000000020C16401C0003D09085
-:101EC0000A16401C0000009C0B16401C000009C4B0
-:101ED0000216403000000008021640340000000CDA
-:101EE0000216403800000010021640440000002096
-:101EF0000216400000000001021640D80000000158
-:101F000002164008000000010216400C000000010B
-:101F100002164010000000010216424000000000BE
-:101F2000021642480000000006164270000000023F
-:101F30000216425000000000021642580000000045
-:101F40000616428000000002021660080000042409
-:101F50000216600C00000410021660100000041449
-:101F60000216601C0000FFFF021660200000FFFF49
-:101F7000021660240000FFFF021660280000FFFF29
-:101F800002166038000000200216603C00000020AD
-:101F90000216604000000034021660440000003564
-:101FA00002166048000000230216604C0000002466
-:101FB0000216605000000025021660540000002642
-:101FC00002166058000000270216605C000000291D
-:101FD000021660600000002A021660640000002BF8
-:101FE000021660680000002C0216606C0000002DD4
-:101FF0000616607000000052021661B80000000171
-:10200000061661BC0000001F0216623807FFFFFFC2
-:102010000216623C0000003F0216624007FFFFFF0D
-:10202000021662440000000F011662480000000022
-:102030000116624C00000000011662500000000012
-:1020400001166254000000000116625800000000F2
-:102050000116625C000000000116626000000000D2
-:1020600001166264000000000116626800000000B2
-:102070000116626C00000000011662700000000092
-:102080000116627400000000011662780000000072
-:102090000116627C000000000C166000000003E8DE
-:1020A0000A166000000000010B1660000000000A24
-:1020B0000216804000000006021680440000000561
-:1020C000021680480000000A0216804C000000053D
-:1020D0000216805400000002021680CC00000004AA
-:1020E000021680D000000004021680D40000000414
-:1020F000021680D800000004021680DC00000004F4
-:10210000021680E000000004021680E400000004D3
-:10211000021680E800000004021688040000000493
-:10212000021680300000007C021680340000003D62
-:10213000021680380000003F0216803C0000009C20
-:10214000021680F000000007061680F4000000056B
-:102150000216880C0101010102168108000000002E
-:102160000216810C00000004021681100000000419
-:1021700002168114000000020216881008012004D3
-:1021800002168118000000050216811C00000005DF
-:1021900002168120000000050216812400000005BF
-:1021A0000216882C20081001021681280000000861
-:1021B0000216812C00000006021681300000000784
-:1021C000021681340000000002168830010101204F
-:1021D000061681380000000402168834010101014E
-:1021E00002168148000000000216814C0000000425
-:1021F0000216815000000004021681540000000203
-:1022000002168838080120040216815800000005D3
-:102210000216815C000000050216816000000005C6
-:1022200002168164000000050216883C2008100197
-:1022300002168168000000080216816C000000068A
-:102240000216817000000007021681740000000170
-:102250000216884001010120021681780000000169
-:102260000216817C0000000102168180000000013E
-:102270000216818400000001021688440101010158
-:1022800002168188000000010216818C0000000403
-:1022900002168190000000040216819400000002E2
-:1022A00002168848080120040216819800000005E3
-:1022B0000216819C00000005021681A000000005A6
-:1022C000021681A4000000050216881420081001DF
-:1022D000021681A800000008021681AC000000066A
-:1022E000021681B000000007021681B40000000150
-:1022F0000216881801010120021681B800000001B1
-:10230000021681BC00000001021681C0000000011D
-:10231000021681C4000000010216881C010101019F
-:10232000021681C800000001021681CC00000004E2
-:10233000021681D000000004021681D400000002C1
-:102340000216882008012004021681D8000000052A
-:10235000021681DC00000005021681E00000000585
-:10236000021681E4000000050216882420081001EE
-:10237000021681E800000008021681EC0000000649
-:10238000021681F0000000070216E40C00000000B5
-:1023900002168828010101200616E410000000043E
-:1023A0000216E000010101010216E4200000000015
-:1023B0000216E424000000040216E42800000004D1
-:1023C0000216E42C000000020216E00408012004BA
-:1023D0000216E430000000050216E4340000000597
-:1023E0000216E438000000050216E43C0000000577
-:1023F0000216E008200810010216E4400000000860
-:102400000216E444000000060216E448000000073B
-:102410000216E44C000000000216E00C010101204D
-:102420000616E450000000040216E010010101014C
-:102430000216E460000000000216E46400000004DC
-:102440000216E468000000040216E46C00000002BA
-:102450000216E014080120040216E47000000005D2
-:102460000216E474000000050216E478000000057E
-:102470000216E47C000000050216E0182008100196
-:102480000216E480000000080216E4840000000642
-:102490000216E488000000070216E48C0000000128
-:1024A0000216E01C010101200216E4900000000168
-:1024B0000216E494000000010216E49800000001F6
-:1024C0000216E49C000000010216E0200101010157
-:1024D0000216E4A0000000010216E4A400000004BB
-:1024E0000216E4A8000000040216E4AC000000029A
-:1024F0000216E024080120040216E4B000000005E2
-:102500000216E4B4000000050216E4B8000000055D
-:102510000216E4BC000000050216E02820081001A5
-:102520000216E4C0000000080216E4C40000000621
-:102530000216E4C8000000070216E4CC0000000107
-:102540000216E02C010101200216E4D00000000177
-:102550000216E4D4000000010216E4D800000001D5
-:102560000216E4DC000000010216E0300101010166
-:102570000216E4E0000000010216E4E4000000049A
-:102580000216E4E8000000040216E4EC0000000279
-:102590000216E034080120040216E4F000000005F1
-:1025A0000216E4F4000000050216E4F8000000053D
-:1025B0000216E4FC000000050216E03820081001B5
-:1025C0000216E500000000080216E50400000006FF
-:1025D0000216E508000000070216E03C0101012098
-:1025E00002168240003F003F0216824400000000B5
-:1025F0000216E524003F003F0216E5280000000017
-:1026000002168248000000000216824C003F003F84
-:102610000216E52C000000000216E530003F003FE6
-:1026200002168250010001000216825401000100CE
-:102630000216E534010001000216E5380100010030
-:1026400006168258000000020216E53C0000000059
-:102650000216E540000000000216826000C000C0C3
-:102660000216826400C000C00216E54400C000C02B
-:102670000216E54800C000C0021682681E001E0057
-:102680000216826C1E001E000216E54C1E001E0083
-:102690000216E5501E001E00021682704000400027
-:1026A00002168274400040000216E55440004000CB
-:1026B0000216E55840004000021682788000800033
-:1026C0000216827C800080000216E55C800080009B
-:1026D0000216E56080008000021682802000200043
-:1026E00002168284200020000216E56420002000EB
-:1026F0000216E5682000200006168288000000020D
-:102700000216E56C000000000216E57000000000F3
-:102710000216829000000000021682940000000061
-:102720000216E574000000000216E57800000000C3
-:1027300002168298000000000216829C0000000031
-:102740000216E57C000000000216E5800000000093
-:10275000021682A000000000021682A40000000100
-:10276000061682A80000000A021681F400000C0878
-:10277000021681F800000040021681FC00000100F2
-:1027800002168200000000200216820400000017DA
-:1027900002168208000000800216820C000002006F
-:1027A00002168210000000000216821801FF01FFCD
-:1027B0000216821401FF01FF0216E51001FF01FF5E
-:1027C0000216E50C01FF01FF0216823C0000001317
-:1027D000021680900000013F021680600000014058
-:1027E00002168064000001400616806800000002A6
-:1027F00002168070000000C00616807400000007FA
-:102800000216809C00000048021680A000000048CC
-:10281000061680A400000002021680AC00000048EA
-:10282000061680B000000007021682380000800003
-:1028300002168234000025E40216809400007FFF17
-:1028400002168220000F000F0216821C000F000FDC
-:102850000216E518000F000F0216E514000F000F16
-:10286000021682280000000002168224FFFFFFFFEC
-:102870000216E520000000000216E51CFFFFFFFF26
-:102880000216E6BC000000000216E6C000000002CE
-:102890000216E6C4000000010216E6C800000003AC
-:1028A0000216E6CC000000040216E6D00000000686
-:1028B0000216E6D4000000050216E6D80000000764
-:1028C000021680EC000000FF02140000000000016E
-:1028D0000214000C0000000102140040000000017E
-:1028E0000214004400007FFF0214000C00000000EE
-:1028F00002140000000000000214006C0000000040
-:102900000214000400000001021400300000000165
-:1029100002140004000000000214005C000000002B
-:10292000021400080000000102140034000000013D
-:102930000214000800000000021400600000000003
-:102940000202005800000032020200A0031500201D
-:10295000020200A403150020020200A801000030BA
-:10296000020200AC08100000020200B000000033B8
-:10297000020200B400000030020200B80000003182
-:10298000020200BC00000003020200C000000006BA
-:10299000020200C400000003020200C8000000039D
-:1029A000020200CC00000002020200D00000000081
-:1029B000020200D400000002020200DC000000005D
-:1029C000020200E000000006020200E40000000431
-:1029D000020200E800000002020200EC0000000217
-:1029E000020200F000000001020200FC00000006EC
-:1029F0000202012000000000020201340000000277
-:102A0000020201B0000000010202020C00000001FD
-:102A1000020202140000000102020218000000027B
-:102A200002020404000000010202040C0000004045
-:102A300002020410000000400202041C0000000416
-:102A40000202042000000020020204240000000210
-:102A50000202042800000020060205000000001207
-:102A600004020480001F032A020200600000000F1D
-:102A70000202006400000007020200680000000B70
-:102A80000202006C0000000E020200700000000E46
-:102A90000602007400000003020200F400000004BB
-:102AA0000202000400000001020200080000000110
-:102AB0000202000C000000010202001000000001F0
-:102AC00002020014000000010202001800000001D0
-:102AD0000202001C000000010202002000000001B0
-:102AE0000202002400000001020200280000000190
-:102AF0000202002C00000001020200300000000170
-:102B0000020200340000000102020038000000014F
-:102B10000202003C0000000102020040000000012F
-:102B2000020200440000000102020048000000010F
-:102B30000202004C000000010202005000000001EF
-:102B400002020108000000C8020201180000000291
-:102B5000020201C400000000020201CC00000000DB
-:102B6000020201D400000002020201DC00000002A7
-:102B7000020201E4000000FF020201EC000000FF7D
-:102B800002020100000000000202010C000000C867
-:102B90000202011C00000002020201C80000000045
-:102BA000020201D000000000020201D80000000271
-:102BB000020201E000000002020201E8000000FF42
-:102BC000020201F0000000FF020201040000000008
-:102BD00002020108000000C8020201180000000201
-:102BE000020201C400000000020201CC000000004B
-:102BF000020201D400000002020201DC0000000217
-:102C0000020201E4000000FF020201EC000000FFEC
-:102C100002020100000000000202010C000000C8D6
-:102C20000202011C00000002020201C800000000B4
-:102C3000020201D000000000020201D800000002E0
-:102C4000020201E000000002020201E8000000FFB1
-:102C5000020201F0000000FF020201040000000077
-:102C600002020108000000C8020201180000000270
-:102C7000020201C400000000020201CC00000000BA
-:102C8000020201D400000002020201DC0000000286
-:102C9000020201E4000000FF020201EC000000FF5C
-:102CA00002020100000000000202010C000000C846
-:102CB0000202011C00000002020201C80000000024
-:102CC000020201D000000000020201D80000000250
-:102CD000020201E000000002020201E8000000FF21
-:102CE000020201F0000000FF0202010400000000E7
-:102CF00002020108000000C80202011800000002E0
-:102D0000020201C400000000020201CC0000000029
-:102D1000020201D400000002020201DC00000002F5
-:102D2000020201E4000000FF020201EC000000FFCB
-:102D300002020100000000000202010C000000C8B5
-:102D40000202011C00000002020201C80000000093
-:102D5000020201D000000000020201D800000002BF
-:102D6000020201E000000002020201E8000000FF90
-:102D7000020201F0000000FF020201040000000056
-:102D80000728040000C00000082807A8000B03491A
-:102D9000072C000032FC0000072C800035780CC0A6
-:102DA000072D00003AC11A1F072D800039E228D0F4
-:102DB000072E00001C3E3749082E3710391E034BE2
-:102DC00001280000000000000128000400000000AD
-:102DD00001280008000000000128000C000000008D
-:102DE000012800100000000001280014000000006D
-:102DF0000228002000000001022800240000000238
-:102E000002280028000000030228002C0000000017
-:102E100002280030000000040228003400000001F5
-:102E200002280038000000000228003C00000001D9
-:102E300002280040000000040228004400000000B6
-:102E400002280048000000010228004C0000000396
-:102E50000228005000000000022800540000000179
-:102E600002280058000000040228005C0000000056
-:102E70000228006000000001022800640000000336
-:102E800002280068000000000228006C0000000119
-:102E900002280070000000040228007400000000F6
-:102EA00002280078000000040228007C00000003D3
-:102EB0000628008000000002022800A400003FFF56
-:102EC000022800A8000003FF0228022400000000DE
-:102ED00002280234000000000228024C000000001A
-:102EE000022802E40000FFFF06282000000008007E
-:102EF000022B8BC000000001022B800000000000AC
-:102F0000022B804000000018022B80800000000C83
-:102F1000022B80C0000000660C2B83000007A1205C
-:102F20000A2B8300000001380B2B8300000013885C
-:102F3000022B83C0000001F40C2B8340000001F43D
-:102F40000A2B8340000000000B2B8340000000058B
-:102F50000A2B83800004C4B40C2B83801DCD650034
-:102F60000A2B1480000000000B2B8380004C4B4088
-:102F7000022B148000000001062A29C8000000046A
-:102F8000042A29D80002034D062A208000000048A8
-:102F9000062A9020000000C8062A900000000002C7
-:102FA000062A21A800000086062A20000000002032
-:102FB000022A23C800000000042A23D00002034F85
-:102FC000042A249800040351022A2C500000000017
-:102FD000022A2C1000000000042A2C0800020355CD
-:102FE000042A300000020357062A300800000100BE
-:102FF000062A404000000010042A40000010035937
-:10300000062A6AC000000002062A6B0000000004C5
-:10301000042A840800020369022B08000000000053
-:10302000042B0C000010036B022B080001000000B1
-:10303000042B0C400008037B022B08000200000058
-:10304000042B0C6000080383062AC000000000D88F
-:10305000062A24A800000014062A254800000022A1
-:10306000042A25D00002038B062A266800000022CD
-:10307000042A26F00002038D062A27880000002279
-:10308000042A28100002038F062A28A80000002224
-:10309000042A293000020391062AA000000000281B
-:1030A000062AA1400000000C042A29E00002039334
-:1030B000062A502000000002062A503000000002BC
-:1030C000062A500000000002062A501000000002EC
-:1030D000022A520800000001042A6AC8000203956F
-:1030E000062A6B1000000042062A6D200000000432
-:1030F000062ABCD000000002062AC360000000D8E7
-:10310000062A24F800000014062A25D80000002210
-:10311000042A266000020397062A26F800000022EF
-:10312000042A278000020399062A2818000000229A
-:10313000042A28A00002039B062A29380000002246
-:10314000042A29C00002039D062AA0A0000000282E
-:10315000062AA1700000000C042A29E80002039F3F
-:10316000062A502800000002062A503800000002FB
-:10317000062A500800000002062A5018000000022B
-:10318000022A520C00000001042A6AD0000203A1A6
-:10319000062A6C1800000042062A6D300000000468
-:1031A000062ABCD800000002022AC6C000000000A7
-:1031B000042A29F0001003A3062A50480000000E3C
-:1031C000062AB00000000006022AC6C40000000063
-:1031D000042A2A30001003B3062A50800000000E93
-:1031E000062AB01800000006022AC6C80000000027
-:1031F000042A2A70001003C3062A50B80000000EEB
-:10320000062AB03000000006022AC6CC00000000EA
-:10321000042A2AB0001003D3062A50F00000000E42
-:10322000062AB04800000006022AC6D000000000AE
-:10323000042A2AF0001003E3062A51280000000E99
-:10324000062AB06000000006022AC6D40000000072
-:10325000042A2B30001003F3062A51600000000EF0
-:10326000062AB07800000006022AC6D80000000036
-:10327000042A2B7000100403062A51980000000E47
-:10328000062AB09000000006022AC6DC00000000FA
-:10329000042A2BB000100413062A51D00000000E9F
-:1032A000062AB0A800000006021010080000000165
-:1032B0000210105000000001021010000003D000A6
-:1032C000021010040000003D091018000200042341
-:1032D0000910110000280623061011A00000001894
-:1032E00006102400000000E00210201C0000000076
-:1032F0000210202000000001021020C00000000287
-:10330000021020040000000102102008000000014B
-:1033100009103C000005064B091038000005065056
-:10332000091038200005065506104C000000010069
-:1033300002104028000000100210404400003FFF2F
-:103340000210405800280000021040840084924A75
-:1033500002104058000000000210800000001080A1
-:10336000021080AC00000000021080380000001045
-:103370000210810000000000061081200000000201
-:1033800002108008000002B502108010000000004A
-:10339000061082000000004A021081080001FFFFB1
-:1033A00006108140000000020210800000001A8018
-:1033B0000610900000000024061091200000004A32
-:1033C000061093700000004A061095C00000004AE5
-:1033D0000210800400001080021080B00000000184
-:1033E0000210803C00000010021081040000000068
-:1033F00006108128000000020210800C000002B5B7
-:103400000210801400000000061084000000004A32
-:103410000210810C0001FFFF06108148000000022D
-:103420000210800400001A80061090900000002412
-:10343000061092480000004A061094980000004AC6
-:10344000061096E80000004A02108000000010807C
-:10345000021080AC00000002021080380000001052
-:103460000210810000000000061081200000000210
-:1034700002108008000002B5021080100000000059
-:10348000061082000000004A021081080001FFFFC0
-:1034900006108140000000020210800000001A8027
-:1034A0000610900000000024061091200000004A41
-:1034B000061093700000004A061095C00000004AF4
-:1034C0000210800400001080021080B00000000391
-:1034D0000210803C00000010021081040000000077
-:1034E00006108128000000020210800C000002B5C6
-:1034F0000210801400000000061084000000004A42
-:103500000210810C0001FFFF06108148000000023C
-:103510000210800400001A80061090900000002421
-:10352000061092480000004A061094980000004AD5
-:10353000061096E80000004A02108000000010808B
-:10354000021080AC0000000402108038000000105F
-:10355000021081000000000006108120000000021F
-:1035600002108008000002B5021080100000000068
-:10357000061082000000004A021081080001FFFFCF
-:1035800006108140000000020210800000001A8036
-:103590000610900000000024061091200000004A50
-:1035A000061093700000004A061095C00000004A03
-:1035B0000210800400001080021080B0000000059E
-:1035C0000210803C00000010021081040000000086
-:1035D00006108128000000020210800C000002B5D5
-:1035E0000210801400000000061084000000004A51
-:1035F0000210810C0001FFFF06108148000000024C
-:103600000210800400001A80061090900000002430
-:10361000061092480000004A061094980000004AE4
-:10362000061096E80000004A02108000000010809A
-:10363000021080AC0000000602108038000000106C
-:10364000021081000000000006108120000000022E
-:1036500002108008000002B5021080100000000077
-:10366000061082000000004A021081080001FFFFDE
-:1036700006108140000000020210800000001A8045
-:103680000610900000000024061091200000004A5F
-:10369000061093700000004A061095C00000004A12
-:1036A0000210800400001080021080B000000007AB
-:1036B0000210803C00000010021081040000000095
-:1036C00006108128000000020210800C000002B5E4
-:1036D0000210801400000000061084000000004A60
-:1036E0000210810C0001FFFF06108148000000025B
-:1036F0000210800400001A80061090900000002440
-:10370000061092480000004A061094980000004AF3
-:10371000061096E80000004A021205B00000000101
-:103720000212049000E383400212051400003C10D2
-:103730000212066C00000001021206700000000078
-:1037400002120494FFFFFFFF02120498FFFFFFFF25
-:103750000212049CFFFFFFFF021204A0FFFFFFFF05
-:10376000021204A4FFFFFFFF021204A8FFFFFFFFE5
-:10377000021204ACFFFFFFFF021204B0FFFFFFFFC5
-:10378000021204BCFFFFFFFF021204C0FFFFFFFF95
-:10379000021204C4FFFFFFFF021204C8FFFFFFFF75
-:1037A000021204CCFFFFFFFF021204D0FFFFFFFF55
-:1037B000021204D8FFFFFFFF021204DCFFFFFFFF2D
-:1037C000021204E0FFFFFFFF021204E4FFFFFFFF0D
-:1037D000021204E8FFFFFFFF021204ECFFFFFFFFED
-:1037E000021204F0FFFFFFFF021204F4FFFFFFFFCD
-:1037F000021204F8FFFFFFFF021204FCFFFFFFFFAD
-:1038000002120500FFFFFFFF02120504FFFFFFFF8A
-:1038100002120508FFFFFFFF0212050CFFFFFFFF6A
-:1038200002120510FFFFFFFF021204D4FF802000E8
-:10383000021204B4F0005000021204B8F0001000AC
-:1038400002120390000000080212039C000000080E
-:10385000021203A000000008021203A400000002EC
-:10386000021203BC00000004021203C000000005A5
-:10387000021203C400000004021203D00000000082
-:103880000212036C00000001021203680000003FF6
-:10389000021201BC00000040021201C00000180822
-:1038A000021201C400000803021201C8000008034C
-:1038B000021201CC00000040021201D000000003FF
-:1038C000021201D400000803021201D8000008030C
-:1038D000021201DC00000803021201E000010003F3
-:1038E000021201E400000803021201E800000803CC
-:1038F000021201EC00000003021201F000000003BC
-:10390000021201F400000003021201F8000000039B
-:10391000021201FC0000000302120200000000037A
-:103920000212020400000003021202080000000359
-:103930000212020C00000003021202100000000339
-:103940000212021400000003021202180000000319
-:103950000212021C000000030212022000000003F9
-:1039600002120224000000030212022800002403B5
-:103970000212022C0000002F021202300000000987
-:103980000212023400000019021202380000018401
-:103990000212023C000001830212024000000306F2
-:1039A0000212024400000019021202480000000640
-:1039B0000212024C0000030602120250000003062D
-:1039C00002120254000003060212025800000C8684
-:1039D0000212025C000003060212026000000306ED
-:1039E00002120264000000060212026800000006D3
-:1039F0000212026C000000060212027000000006B3
-:103A00000212027400000006021202780000000692
-:103A10000212027C00000006021202800000000672
-:103A20000212028400000006021202880000000652
-:103A30000212028C00000006021202900000000632
-:103A40000212029400000006021202980000000612
-:103A50000212029C00000006021202A000000306EF
-:103A6000021202A400000013021202A800000006C5
-:103A7000021202B000001004021202B4000010048E
-:103A80000212032400106440021203280010644054
-:103A9000021205B400000001021201B00000000192
-:103AA0000600A000000000160200A0EC5554000023
-:103AB0000200A0F0555555550200A0F400005555E0
-:103AC0000200A0F8F00000000200A0FC5554000025
-:103AD0000200A100555555550200A104000055559E
-:103AE0000200A108F00000000200A18C5554000063
-:103AF0000200A190555555550200A194000055555E
-:103B00000200A198F00000000200A19C000000004B
-:103B10000200A1A0000100000200A1A400005014B6
-:103B20000200A1A8000000000200A45C00000C003C
-:103B30000200A61C000000030200A06CFF5C000055
-:103B40000200A070FFF55FFF0200A0740000FFFFFD
-:103B50000200A078F00003E00200A07C000000005A
-:103B60000200A0800000A0000600A0840000000564
-:103B70000200A0980FE000000600A09C00000007D3
-:103B80000200A0B8000004000600A0BC0000000372
-:103B90000200A0C8000010000600A0CC0000000336
-:103BA0000200A0D8000040000600A0DC00000003D6
-:103BB0000200A0E8000100000600A22C00000004A2
-:103BC0000200A10CFF5C00000200A110FFF55FFFE6
-:103BD0000200A1140000FFFF0200A118F00003E0A2
-:103BE0000200A11C000000000200A1200000A000B3
-:103BF0000600A124000000050200A1380FE000002B
-:103C00000600A13C000000070200A15800000800C7
-:103C10000600A15C000000030200A1680000200073
-:103C20000600A16C000000030200A17800008000E3
-:103C30000600A17C000000030200A1880002000031
-:103C40000600A23C0000000400000000000000008C
-:103C50000000003100000000000000000000000033
-:103C60000000000000000000000000000000000054
-:103C700000000000000000000000000000310032E1
-:103C80000000000000000000000000000000000034
-:103C90000000000000000000000000000000000024
-:103CA000000000000000000000320056000000008C
-:103CB0000000000000000000000000000000000004
-:103CC00000000000000000000000000000000000F4
-:103CD000000000000056008C000000000000000002
-:103CE000008C009000900094009400980098009C34
-:103CF000009C00A000A000A400A400A800A800ACA4
-:103D000000AC00B100B100B300B300B5000000008A
-:103D100000000000000000000000000000000000A3
-:103D200000000000000000000000000000B50102DB
-:103D30000102010A010A01120112011B011B0124E7
-:103D40000124012D012D01360136013F013F0148BB
-:103D5000014801510151015A00000000000000001B
-:103D60000000000000000000000000000000000053
-:103D70000000000000000000000000000000000043
-:103D80000000000000000000000000000000000033
-:103D90000000000000000000000000000000000023
-:103DA0000000000000000000000000000000000013
-:103DB0000000000000000000000000000000000003
-:103DC00000000000000000000000000000000000F3
-:103DD00000000000000000000000000000000000E3
-:103DE00000000000000000000000000000000000D3
-:103DF00000000000000000000000000000000000C3
-:103E00000000000000000000015A015F00000000F7
-:103E100000000000015F0160016001610161016259
-:103E2000016201630163016401640165016501666A
-:103E300001660167000000000000000000000000B3
-:103E40000000000000000000000000000000000072
-:103E50000000000000000000000000000000000062
-:103E60000167016C016C0179017901860000000095
-:103E70000000000000000000000000000000000042
-:103E80000000000000000000000000000000000032
-:103E90000000000000000000000000000000000022
-:103EA0000000000000000000000000000000000012
-:103EB00000000000000000000186018700000000F3
-:103EC00000000000000000000000000000000000F2
-:103ED00000000000000000000000000000000000E2
-:103EE00000000000018701BE00000000000000008B
-:103EF00000000000000000000000000000000000C2
-:103F000000000000000000000000000000000000B1
-:103F100001BE01E9000000000000000000000000F8
-:103F20000000000000000000000000000000000091
-:103F300000000000000000000000000001E9021A7B
-:103F40000000000000000000021A022102210228E5
-:103F50000228022F022F02360236023D023D0244A1
-:103F60000244024B024B02520252028A000000003D
-:103F700000000000028A028E028E029202920296D5
-:103F80000296029A029A029E029E02A202A202A631
-:103F900002A602AA02AA02FA02FA031103110328D6
-:103FA0000328032B032B032E032E03310331033489
-:103FB000033403370337033A033A033D033D034019
-:103FC00003400381038103880388038F038F0393D6
-:103FD000039303970397039B039B039F039F03A3F1
-:103FE00003A303A703A703AB03AB03AF03AF03B064
-:103FF00000000000000000000000000000000000C1
-:1040000000000000000000000000000000000000B0
-:10401000000000000000000003B003C20000000028
-:104020000000000000000000000000000000000090
-:104030000000000000000000000000000000000080
-:104040000000000003C203D703D703DA03DA03DD5D
-:104050000000000000000000000000000000000060
-:104060000000000000000000000000000000000050
-:1040700003DD040A00000000000000000000000052
-:104080000000000000000000000000000000000030
-:10409000000000000000000000000000040A050D00
-:1040A0000000000000000000000000000000000010
-:1040B0000000000000000000000000000000000000
-:1040C0000000000000000000050D0514051405188F
-:1040D0000518051C000000000000000000000000A2
-:1040E00000000000000000000000000000000000D0
-:1040F00000000000051C055C00000000000000003E
-:10410000055C05650565056E056E05770577058017
-:1041100005800589058905920592059B059B05A4E7
-:1041200005A405FD05FD0613061306290629062D1F
-:10413000062D063106310635063506390639063DA7
-:10414000063D064106410645064506490649065014
-:10415000000000000000000000000000000000005F
-:10416000000000000000000000000000000000004F
-:10417000000000000000000006500656000000008D
-:10418000000000000000000000000000000000002F
-:10419000000000000000000000000000000000001F
-:1041A0000000000006560659000000000000000054
-:1041B00000000000000000000000000000000000FF
-:1041C00000000000000000000000000000000000EF
-:1041D0000659065F0000000000000000000000001B
-:1041E00000000000000000000000000000000000CF
-:1041F00000000000000000000000000000000000BF
-:104200000000000000000000065F066E066E067DDE
-:10421000067D068C068C069B069B06AA06AA06B996
-:1042200006B906C806C806D706D70748000000002A
-:10423000000000000000000000000000000000007E
-:10424000000000000000000000000000000000006E
-:10425000000000000748075B075B076C076C077DE1
-:10426000000000000000000000000000000000004E
-:10427000000000000000000000000000000000003E
-:10428000000000000000000000000000000000002E
-:10429000000000000000000000000000000000001E
-:1042A000000000000000000000000000000000000E
-:1042B00000000000000000000000000000000000FE
-:1042C00000000000000000000000000000000000EE
-:1042D00000000000000000000000000000000000DE
-:1042E00000010000000204C00003098000040E4029
-:1042F00000051300000617C000071C8000082140BD
-:1043000000092600000A2AC0000B2F80000C344050
-:10431000000D3900000E3DC0000F428000104740E4
-:1043200000114C00001250C00013558000145A4078
-:1043300000155F00001663C00017688000186D400C
-:1043400000197200001A76C0001B7B80001C8040A0
-:10435000001D8500001E89C0001F8E800020934034
-:10436000000020000000400000006000000080000D
-:104370000000A0000000C0000000E00000010000FC
-:1043800000012000000140000001600000018000E9
-:104390000001A0000001C0000001E00000020000D8
-:1043A00000022000000240000002600000028000C5
-:1043B0000002A0000002C0000002E00000030000B4
-:1043C00000032000000340000003600000038000A1
-:1043D0000003A0000003C0000003E0000004000090
-:1043E000000420000004400000046000000480007D
-:1043F0000004A0000004C0000004E000000500006C
-:104400000005200000054000000560000005800058
-:104410000005A0000005C0000005E0000006000047
-:104420000006200000064000000660000006800034
-:104430000006A0000006C0000006E0000007000023
-:104440000007200000074000000760000007800010
-:104450000007A0000007C0000007E00000080000FF
-:1044600000082000000840000008600000088000EC
-:104470000008A0000008C0000008E00000090000DB
-:1044800000092000000940000009600000098000C8
-:104490000009A0000009C0000009E000000A0000B7
-:1044A000000A2000000A4000000A6000000A8000A4
-:1044B000000AA000000AC000000AE000000B000093
-:1044C000000B2000000B4000000B6000000B800080
-:1044D000000BA000000BC000000BE000000C00006F
-:1044E000000C2000000C4000000C6000000C80005C
-:1044F000000CA000000CC000000CE000000D00004B
-:10450000000D2000000D4000000D6000000D800037
-:10451000000DA000000DC000000DE000000E000026
-:10452000000E2000000E4000000E6000000E800013
-:10453000000EA000000EC000000EE000000F000002
-:10454000000F2000000F4000000F6000000F8000EF
-:10455000000FA000000FC000000FE00000100000DE
-:1045600000102000001040000010600000108000CB
-:104570000010A0000010C0000010E00000110000BA
-:1045800000112000001140000011600000118000A7
-:104590000011A0000011C0000011E0000012000096
-:1045A0000012200000124000001260000012800083
-:1045B0000012A0000012C0000012E0000013000072
-:1045C000001320000013400000136000001380005F
-:1045D0000013A0000013C0000013E000001400004E
-:1045E000001420000014400000146000001480003B
-:1045F0000014A0000014C0000014E000001500002A
-:104600000015200000154000001560000015800016
-:104610000015A0000015C0000015E0000016000005
-:1046200000162000001640000016600000168000F2
-:104630000016A0000016C0000016E00000170000E1
-:1046400000172000001740000017600000178000CE
-:104650000017A0000017C0000017E00000180000BD
-:1046600000182000001840000018600000188000AA
-:104670000018A0000018C0000018E0000019000099
-:104680000019200000194000001960000019800086
-:104690000019A0000019C0000019E000001A000075
-:1046A000001A2000001A4000001A6000001A800062
-:1046B000001AA000001AC000001AE000001B000051
-:1046C000001B2000001B4000001B6000001B80003E
-:1046D000001BA000001BC000001BE000001C00002D
-:1046E000001C2000001C4000001C6000001C80001A
-:1046F000001CA000001CC000001CE000001D000009
-:10470000001D2000001D4000001D6000001D8000F5
-:10471000001DA000001DC000001DE000001E0000E4
-:10472000001E2000001E4000001E6000001E8000D1
-:10473000001EA000001EC000001EE000001F0000C0
-:10474000001F2000001F4000001F6000001F8000AD
-:10475000001FA000001FC000001FE000002000009C
-:104760000020200000204000002060000020800089
-:104770000020A0000020C0000020E0000021000078
-:104780000021200000214000002160000021800065
-:104790000021A0000021C0000021E0000022000054
-:1047A0000022200000224000002260000022800041
-:1047B0000022A0000022C0000022E0000023000030
-:1047C000002320000023400000236000002380001D
-:1047D0000023A0000023C0000023E000002400000C
-:1047E00000242000002440000024600000248000F9
-:1047F0000024A0000024C0000024E00000250000E8
-:1048000000252000002540000025600000258000D4
-:104810000025A0000025C0000025E00000260000C3
-:1048200000262000002640000026600000268000B0
-:104830000026A0000026C0000026E000002700009F
-:10484000002720000027400000276000002780008C
-:104850000027A0000027C0000027E000002800007B
-:104860000028200000284000002860000028800068
-:104870000028A0000028C0000028E0000029000057
-:104880000029200000294000002960000029800044
-:104890000029A0000029C0000029E000002A000033
-:1048A000002A2000002A4000002A6000002A800020
-:1048B000002AA000002AC000002AE000002B00000F
-:1048C000002B2000002B4000002B6000002B8000FC
-:1048D000002BA000002BC000002BE000002C0000EB
-:1048E000002C2000002C4000002C6000002C8000D8
-:1048F000002CA000002CC000002CE000002D0000C7
-:10490000002D2000002D4000002D6000002D8000B3
-:10491000002DA000002DC000002DE000002E0000A2
-:10492000002E2000002E4000002E6000002E80008F
-:10493000002EA000002EC000002EE000002F00007E
-:10494000002F2000002F4000002F6000002F80006B
-:10495000002FA000002FC000002FE000003000005A
-:104960000030200000304000003060000030800047
-:104970000030A0000030C0000030E0000031000036
-:104980000031200000314000003160000031800023
-:104990000031A0000031C0000031E0000032000012
-:1049A00000322000003240000032600000328000FF
-:1049B0000032A0000032C0000032E00000330000EE
-:1049C00000332000003340000033600000338000DB
-:1049D0000033A0000033C0000033E00000340000CA
-:1049E00000342000003440000034600000348000B7
-:1049F0000034A0000034C0000034E00000350000A6
-:104A00000035200000354000003560000035800092
-:104A10000035A0000035C0000035E0000036000081
-:104A2000003620000036400000366000003680006E
-:104A30000036A0000036C0000036E000003700005D
-:104A4000003720000037400000376000003780004A
-:104A50000037A0000037C0000037E0000038000039
-:104A60000038200000384000003860000038800026
-:104A70000038A0000038C0000038E0000039000015
-:104A80000039200000394000003960000039800002
-:104A90000039A0000039C0000039E000003A0000F1
-:104AA000003A2000003A4000003A6000003A8000DE
-:104AB000003AA000003AC000003AE000003B0000CD
-:104AC000003B2000003B4000003B6000003B8000BA
-:104AD000003BA000003BC000003BE000003C0000A9
-:104AE000003C2000003C4000003C6000003C800096
-:104AF000003CA000003CC000003CE000003D000085
-:104B0000003D2000003D4000003D6000003D800071
-:104B1000003DA000003DC000003DE000003E000060
-:104B2000003E2000003E4000003E6000003E80004D
-:104B3000003EA000003EC000003EE000003F00003C
-:104B4000003F2000003F4000003F6000003F800029
-:104B5000003FA000003FC000003FE000003FE00138
-:104B600000000000000001FF0000020000007FF8CC
-:104B700000007FF800000CDF0000150000000001BD
-:104B80000000000100000001FFFFFFFFFFFFFFFF2B
-:104B9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25
-:104BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15
-:104BB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05
-:104BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5
-:104BD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5
-:104BE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5
-:104BF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC5
-:104C0000FFFFFFFFFFFFFFFFFFFFFFFF00000000B0
-:104C1000FFFFFFFF00000000FFFFFFFFFFFFFFFFA0
-:104C200000000000FFFFFFFF00000000FFFFFFFF8C
-:104C3000FFFFFFFF00000000FFFFFFFF000000007C
-:104C4000FFFFFFFF0000000300BEBC20FFFFFFFFCF
-:104C500000000000FFFFFFFF00000000FFFFFFFF5C
-:104C60000000000300BEBC20FFFFFFFF00000000AB
-:104C7000FFFFFFFF00000000FFFFFFFF0000000339
-:104C800000BEBC20FFFFFFFF00000000FFFFFFFF92
-:104C900000000000FFFFFFFF0000000300BEBC207B
-:104CA000FFFFFFFF00000000FFFFFFFF000000000C
-:104CB000FFFFFFFF0000000300BEBC20FFFFFFFF5F
-:104CC00000000000FFFFFFFF00000000FFFFFFFFEC
-:104CD0000000000300BEBC2000002000000040C017
-:104CE00000006180000082400000A3000000C3C0FB
-:104CF0000000E4800001054000012600000146C0DC
-:104D000000016780000188400001A9000001C9C0BE
-:104D10000001EA8000020B4000022C0000024CC09F
-:104D200000026D8000028E400002AF000002CFC082
-:104D30000002F0800003114000033200000352C063
-:104D400000037380000394400003B5000003D5C046
-:104D50000003F6800004174000043800000458C027
-:104D60000004798000049A40000080000001038064
-:104D70000001870000020A8000028E0000031180FB
-:104D8000000395000004188000049C0000051F80AB
-:104D90000005A300000626800006AA0000072D805B
-:104DA0000007B100000834800008B80000093B800B
-:104DB0000009BF00000A4280000AC600000B4980BB
-:104DC000000BCD00000C5080000CD400000D57806B
-:104DD000000DDB0000007FF800007FF80000192ABA
-:104DE0000000350000001900001000000000000065
-:104DF00000000000FFFFFFFF400000004000000037
-:104E000040000000400000004000000040000000A2
-:104E10004000000040000000400000004000000092
-:104E20004000000040000000400000004000000082
-:104E30004000000040000000400000004000000072
-:104E40004000000040000000400000004000000062
-:104E50004000000040000000400000004000000052
-:104E60004000000040000000400000004000000042
-:104E7000400000004000000000007FF800007FF8C4
-:104E8000000005C700001500FFFFFFFFFFFFFFFF49
-:104E9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22
-:104EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12
-:104EB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02
-:104EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2
-:104ED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2
-:104EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2
-:104EF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2
-:104F0000FFFFFFFFFFFFFFFF400000004000000029
-:104F10004000000040000000400000004000000091
-:104F20004000000040000000400000004000000081
-:104F30004000000040000000400000004000000071
-:104F40004000000040000000400000004000000061
-:104F50004000000040000000400000004000000051
-:104F60004000000040000000400000004000000041
-:104F70004000000040000000400000004000000031
-:104F800040000000400000000000100000002080F1
-:104F900000003100000041800000520000006280EB
-:104FA0000000730000008380000094000000A480D3
-:104FB0000000B5000000C5800000D6000000E680BB
-:104FC0000000F700000107800001180000012880A0
-:104FD000000139000001498000015A0000016A8087
-:104FE00000017B0000018B8000019C000001AC806F
-:104FF0000001BD000001CD800001DE000001EE8057
-:105000000001FF0000007FF800007FF80000112E73
-:105010000000350010000000000028AD0000000076
-:1050200000010001000D0205CCCCCCC5FFFFFFFF45
-:10503000FFFFFFFF7058103C000000000000000060
-:1050400000000001CCCC0201CCCCCCCCCCCC0201F9
-:10505000CCCCCCCCCCCC0201CCCCCCCCCCCC0201BA
-:10506000CCCCCCCCCCCC0201CCCCCCCCCCCC0201AA
-:10507000CCCCCCCCCCCC0201CCCCCCCCCCCC02019A
-:10508000CCCCCCCC00000000FFFFFFFF40000000B4
-:105090004000000040000000400000004000000010
-:1050A0004000000040000000400000004000000000
-:1050B00040000000400000004000000040000000F0
-:1050C00040000000400000004000000040000000E0
-:1050D00040000000400000004000000040000000D0
-:1050E00040000000400000004000000040000000C0
-:1050F00040000000400000004000000040000000B0
-:10510000400000004000000040000000002625A0F4
-:1051100000000000002625A000000000002625A0B9
-:1051200000000000002625A000000000000E023252
-:10513000011600D60010000000000000002625A087
-:1051400000000000002625A000000000002625A089
-:1051500000000000002625A00000000000720236BA
-:10516000012300F300100000000000000000FFFF1A
-:10517000000000000000FFFF000000000000FFFF33
-:10518000000000000000FFFF000000000000FFFF23
-:10519000000000000000FFFF000000000000FFFF13
-:1051A000000000000000FFFF000000000000FFFF03
-:1051B000000000000000FFFF000000000000FFFFF3
-:1051C000000000000000FFFF000000000000FFFFE3
-:1051D000000000000000FFFF000000000000FFFFD3
-:1051E000000000000000FFFF000000000000FFFFC3
-:1051F000000000000000FFFF000000000000FFFFB3
-:10520000000000000000FFFF000000000000FFFFA2
-:10521000000000000000FFFF000000000000FFFF92
-:10522000000000000000FFFF000000000000FFFF82
-:10523000000000000000FFFF000000000000FFFF72
-:10524000000000000000FFFF000000000000FFFF62
-:10525000000000000000FFFF000000000000FFFF52
-:10526000000000000000FFFF000000000000FFFF42
-:10527000000000000000FFFF000000000000FFFF32
-:10528000000000000000FFFF000000000000FFFF22
-:10529000000000000000FFFF000000000000FFFF12
-:1052A000000000000000FFFF000000000000FFFF02
-:1052B000000000000000FFFF000000000000FFFFF2
-:1052C000000000000000FFFF000000000000FFFFE2
-:1052D000000000000000FFFF000000000000FFFFD2
-:1052E000000000000000FFFF000000000000FFFFC2
-:1052F000000000000000FFFF000000000000FFFFB2
-:10530000000000000000FFFF000000000000FFFFA1
-:10531000000000000000FFFF000000000000FFFF91
-:10532000000000000000FFFF000000000000FFFF81
-:10533000000000000000FFFF000000000000FFFF71
-:10534000000000000000FFFF000000000000FFFF61
-:10535000000000000000FFFF000000000000FFFF51
-:10536000000000000000FFFF00000000FFFFFFF34F
-:10537000318FFFFF0C30C30CC30C30C3CF3CF300A4
-:10538000F3CF3CF30000CF3CCDCDCDCDFFFFFFF1FF
-:1053900030EFFFFF0C30C30CC30C30C3CF3CF30025
-:1053A000F3CF3CF30001CF3CCDCDCDCDFFFFFFF6D9
-:1053B000305FFFFF0C30C30CC30C30C3CF3CF30095
-:1053C000F3CF3CF30002CF3CCDCDCDCDFFFFF406B3
-:1053D0001CBFFFFF0C30C305C30C30C3CF3000141B
-:1053E000F3CF3CF30004CF3CCDCDCDCDFFFFFFF29A
-:1053F000304FFFFF0C30C30CC30C30C3CF3CF30065
-:10540000F3CF3CF30008CF3CCDCDCDCDFFFFFFFA6D
-:10541000302FFFFF0C30C30CC30C30C3CF3CF30064
-:10542000F3CF3CF30010CF3CCDCDCDCDFFFFFFF748
-:1054300031EFFFFF0C30C30CC30C30C3CF3CF30083
-:10544000F3CF3CF30020CF3CCDCDCDCDFFFFFFF51A
-:10545000302FFFFF0C30C30CC30C30C3CF3CF30024
-:10546000F3CF3CF30040CF3CCDCDCDCDFFFFFFF3DC
-:10547000318FFFFF0C30C30CC30C30C3CF3CF300A3
-:10548000F3CF3CF30000CF3CCDCDCDCDFFFFFFF1FE
-:10549000310FFFFF0C30C30CC30C30C3CF3CF30003
-:1054A000F3CF3CF30001CF3CCDCDCDCDFFFFFFF6D8
-:1054B000305FFFFF0C30C30CC30C30C3CF3CF30094
-:1054C000F3CF3CF30002CF3CCDCDCDCDFFFFF406B2
-:1054D0001CBFFFFF0C30C305C30C30C3CF3000141A
-:1054E000F3CF3CF30004CF3CCDCDCDCDFFFFFFF299
-:1054F000304FFFFF0C30C30CC30C30C3CF3CF30064
-:10550000F3CF3CF30008CF3CCDCDCDCDFFFFFFFA6C
-:10551000302FFFFF0C30C30CC30C30C3CF3CF30063
-:10552000F3CF3CF30010CF3CCDCDCDCDFFFFFFF747
-:1055300030EFFFFF0C30C30CC30C30C3CF3CF30083
-:10554000F3CF3CF30020CF3CCDCDCDCDFFFFFFF519
-:10555000304FFFFF0C30C30CC30C30C3CF3CF30003
-:10556000F3CF3CF30040CF3CCDCDCDCDFFFFFFF3DB
-:1055700031EFFFFF0C30C30CC30C30C3CF3CF30042
-:10558000F3CF3CF30000CF3CCDCDCDCDFFFFFFF1FD
-:10559000310FFFFF0C30C30CC30C30C3CF3CF30002
-:1055A000F3CF3CF30001CF3CCDCDCDCDFFFFFFF6D7
-:1055B000305FFFFF0C30C30CC30C30C3CF3CF30093
-:1055C000F3CF3CF30002CF3CCDCDCDCDFFFFF406B1
-:1055D0001CBFFFFF0C30C305C30C30C3CF30001419
-:1055E000F3CF3CF30004CF3CCDCDCDCDFFFFFFF298
-:1055F000304FFFFF0C30C30CC30C30C3CF3CF30063
-:10560000F3CF3CF30008CF3CCDCDCDCDFFFFFFFA6B
-:10561000302FFFFF0C30C30CC30C30C3CF3CF30062
-:10562000F3CF3CF30010CF3CCDCDCDCDFFFFFF97A6
-:10563000056FFFFF0C30C30CC30C30C3CF3CC00060
-:10564000F3CF3CF30020CF3CCDCDCDCDFFFFFFF518
-:10565000310FFFFF0C30C30CC30C30C3CF3CF30041
-:10566000F3CF3CF30040CF3CCDCDCDCDFFFFFFF3DA
-:10567000320FFFFF0C30C30CC30C30C3CF3CF30020
-:10568000F3CF3CF30000CF3CCDCDCDCDFFFFFFF1FC
-:10569000310FFFFF0C30C30CC30C30C3CF3CF30001
-:1056A000F3CF3CF30001CF3CCDCDCDCDFFFFFFF6D6
-:1056B000305FFFFF0C30C30CC30C30C3CF3CF30092
-:1056C000F3CF3CF30002CF3CCDCDCDCDFFFFF406B0
-:1056D0001CBFFFFF0C30C305C30C30C3CF30001418
-:1056E000F3CF3CF30004CF3CCDCDCDCDFFFFFFF297
-:1056F000304FFFFF0C30C30CC30C30C3CF3CF30062
-:10570000F3CF3CF30008CF3CCDCDCDCDFFFFFF8ADA
-:10571000042FFFFF0C30C30CC30C30C3CF3CC000C0
-:10572000F3CF3CF30010CF3CCDCDCDCDFFFFFF97A5
-:1057300005CFFFFF0C30C30CC30C30C3CF3CC000FF
-:10574000F3CF3CF30020CF3CCDCDCDCDFFFFFFF517
-:10575000310FFFFF0C30C30CC30C30C3CF3CF30040
-:10576000F3CF3CF30040CF3CCDCDCDCDFFFFFFF3D9
-:10577000316FFFFF0C30C30CC30C30C3CF3CF300C0
-:10578000F3CF3CF30000CF3CCDCDCDCDFFFFFFF1FB
-:10579000302FFFFF0C30C30CC30C30C3CF3CF300E1
-:1057A000F3CF3CF30001CF3CCDCDCDCDFFFFFFF6D5
-:1057B000305FFFFF0C30C30CC30C30C3CF3CF30091
-:1057C000F3CF3CF30002CF3CCDCDCDCDFFFFFFF6B4
-:1057D00030BFFFFF0C30C30CC30C30C3CF3CF314FD
-:1057E000F3CF3CF30004CF3CCDCDCDCDFFFFFFF296
-:1057F000304FFFFF0C30C30CC30C30C3CF3CF30061
-:10580000F3CF3CF30008CF3CCDCDCDCDFFFFFFFA69
-:10581000302FFFFF0C30C30CC30C30C3CF3CF30060
-:10582000F3CF3CF30010CF3CCDCDCDCDFFFFFFF744
-:1058300031CFFFFF0C30C30CC30C30C3CF3CF3009F
-:10584000F3CF3CF30020CF3CCDCDCDCDFFFFFFF01B
-:10585000307FFFFF0C30C30CC30C30C3CF3CF300D0
-:10586000F3CF3CF30040CF3CCDCDCDCDFFFFFFFFCC
-:1058700030CFFFFF0C30C30CC30C30C3CF3CF3CC94
-:10588000F3CF3CF30000CF3CCDCDCDCDFFFFFFFFEC
-:1058900030CFFFFF0C30C30CC30C30C3CF3CF3CC74
-:1058A000F3CF3CF30001CF3CCDCDCDCDFFFFFFFFCB
-:1058B00030CFFFFF0C30C30CC30C30C3CF3CF3CC54
-:1058C000F3CF3CF30002CF3CCDCDCDCDFFFFFFFFAA
-:1058D00030CFFFFF0C30C30CC30C30C3CF3CF3CC34
-:1058E000F3CF3CF30004CF3CCDCDCDCDFFFFFFFF88
-:1058F00030CFFFFF0C30C30CC30C30C3CF3CF3CC14
-:10590000F3CF3CF30008CF3CCDCDCDCDFFFFFFFF63
-:1059100030CFFFFF0C30C30CC30C30C3CF3CF3CCF3
-:10592000F3CF3CF30010CF3CCDCDCDCDFFFFFFFF3B
-:1059300030CFFFFF0C30C30CC30C30C3CF3CF3CCD3
-:10594000F3CF3CF30020CF3CCDCDCDCDFFFFFFFF0B
-:1059500030CFFFFF0C30C30CC30C30C3CF3CF3CCB3
-:10596000F3CF3CF30040CF3CCDCDCDCDFFFFFFFFCB
-:1059700030CFFFFF0C30C30CC30C30C3CF3CF3CC93
-:10598000F3CF3CF30000CF3CCDCDCDCDFFFFFFFFEB
-:1059900030CFFFFF0C30C30CC30C30C3CF3CF3CC73
-:1059A000F3CF3CF30001CF3CCDCDCDCDFFFFFFFFCA
-:1059B00030CFFFFF0C30C30CC30C30C3CF3CF3CC53
-:1059C000F3CF3CF30002CF3CCDCDCDCDFFFFFFFFA9
-:1059D00030CFFFFF0C30C30CC30C30C3CF3CF3CC33
-:1059E000F3CF3CF30004CF3CCDCDCDCDFFFFFFFF87
-:1059F00030CFFFFF0C30C30CC30C30C3CF3CF3CC13
-:105A0000F3CF3CF30008CF3CCDCDCDCDFFFFFFFF62
-:105A100030CFFFFF0C30C30CC30C30C3CF3CF3CCF2
-:105A2000F3CF3CF30010CF3CCDCDCDCDFFFFFFFF3A
-:105A300030CFFFFF0C30C30CC30C30C3CF3CF3CCD2
-:105A4000F3CF3CF30020CF3CCDCDCDCDFFFFFFFF0A
-:105A500030CFFFFF0C30C30CC30C30C3CF3CF3CCB2
-:105A6000F3CF3CF30040CF3CCDCDCDCDFFFFFFFFCA
-:105A700030CFFFFF0C30C30CC30C30C3CF3CF3CC92
-:105A8000F3CF3CF30000CF3CCDCDCDCDFFFFFFFFEA
-:105A900030CFFFFF0C30C30CC30C30C3CF3CF3CC72
-:105AA000F3CF3CF30001CF3CCDCDCDCDFFFFFFFFC9
-:105AB00030CFFFFF0C30C30CC30C30C3CF3CF3CC52
-:105AC000F3CF3CF30002CF3CCDCDCDCDFFFFFFFFA8
-:105AD00030CFFFFF0C30C30CC30C30C3CF3CF3CC32
-:105AE000F3CF3CF30004CF3CCDCDCDCDFFFFFFFF86
-:105AF00030CFFFFF0C30C30CC30C30C3CF3CF3CC12
-:105B0000F3CF3CF30008CF3CCDCDCDCDFFFFFFFF61
-:105B100030CFFFFF0C30C30CC30C30C3CF3CF3CCF1
-:105B2000F3CF3CF30010CF3CCDCDCDCDFFFFFFFF39
-:105B300030CFFFFF0C30C30CC30C30C3CF3CF3CCD1
-:105B4000F3CF3CF30020CF3CCDCDCDCDFFFFFFFF09
-:105B500030CFFFFF0C30C30CC30C30C3CF3CF3CCB1
-:105B6000F3CF3CF30040CF3CCDCDCDCD000C0000B9
-:105B7000000700C000028130000B815800020210B3
-:105B800000010230000F024000010330000C000051
-:105B9000000800C000028140000B81680002022062
-:105BA0000001024000070250000202C0000F000086
-:105BB000000800F000028170000B81980002025082
-:105BC00000010270000B8280000803380010000002
-:105BD0000008010000028180000B81A80002026021
-:105BE00000018280000E829800080380000B0000F4
-:105BF000000100B0000280C0000580E80002014002
-:105C000000010160000E017000038250CCCCCCCCAE
-:105C1000CCCCCCCCCCCCCCCCCCCCCCCC00002000D4
-:105C2000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB4
-:105C300000002000CCCCCCCCCCCCCCCCCCCCCCCCB4
-:105C4000CCCCCCCC04002000000000000000000000
-:105C50001F8B080000000000000BFB51CFC0F003B9
-:105C60008A59051918AC84117C7A607E4ECAF43BBF
-:105C7000F232303803B12B103700F1616E06862303
-:105C8000DCC4EB3F298F607BCB32309403F1766923
-:105C90000606133984B8AE0203C33C203F012AF63E
-:105CA000144867CB53E6EEC182155431C564951193
-:105CB0006C452CF2C858094DBE461995AF4C40FFB3
-:105CC00040E3781D547E8F16847EAD0DA113D0E481
-:105CD0007BA1F28E507F25EA6037D789487FA7B233
-:105CE000A0B9078DDFCA88CA37E340E52741D5034D
-:105CF000000749300AC8030000000000000000004F
-:105D00001F8B080000000000000BED7D0D7854D5BE
-:105D1000B5E83E73CE9C9949CE4C26BF4C20C04975
-:105D2000082168A4C70069B0584F2060A8D40E1499
-:105D300069AC8A032244082452EBC3ABFD328100D4
-:105D4000010204B13414A44300A5B7B43752B4D44B
-:105D5000523AE0A7C5D6F7BDE0B356AFB66FB4145C
-:105D60007F8A12F3AED6BE6BEBDB6BEDBD93734E49
-:105D7000664810BDED7DEFC6CFEFB0CFD93F6BAF1A
-:105D8000BFBDD6DA6BEF71BBFC246F34211FC3DFBC
-:105D90007584FC2F8D1092DBFF747B4934FD738476
-:105DA00064E698D1441921C372CC389944DF075571
-:105DB000DD23F5B713CF9399334350AF25D70C119B
-:105DC000DA474BE67C1281BE227584E411A2780981
-:105DD000FE89FAEEE05C2F29C3577FFB587C9709B8
-:105DE00059172CCA8076CEFE09891132D95A7611FC
-:105DF00022FAA4EDBC006F068557A72F289C699353
-:105E00005CB1EB0B29DC7A0CE14E2FA070D3F2C908
-:105E100091CF78C7D0F2A66B5D86075BDF4D480552
-:105E200021ABA02FDA76D35571FE5D31A03C433E05
-:105E3000DCAC427B9D181E5AF65FD51857B19DA960
-:105E4000E5D37641C2DA054B97CC261308C930D585
-:105E50007EB8583D9C7F3AAFE7D1E9F7D2FEEFE933
-:105E6000A4ED3D3900A50409FB69FF958EEFA5332C
-:105E7000DF807ED389A55F3A8FEDF08F7C42BE40F4
-:105E8000FC39E7A0F3CF93CF031E487516215306C4
-:105E9000E2AF1F6F51A42F217536B8041D3418636B
-:105EA0000C21D7B7265E72E550784C17013CCD9493
-:105EB00035DF185ADE765A463C6CABEDF106359C60
-:105EC000DFEC7CDA6E34EF677425C5039DCF9E2628
-:105ED0005AF60CC46FC1A46E13F8C33FA95B22B479
-:105EE000BF0283906C3A9F60232D17D176247E6683
-:105EF0000CE52FF2009B6F94FEF771513F1E331992
-:105F00000A88E6C07326E091E2A9E01EC7FB4A8634
-:105F1000BF4C62C16B217213E2E90EC0DF95C8F37A
-:105F200063117FD12CC4EB50F127E011F80B723EC6
-:105F3000BEBE2651AB00DF4CA5F8037C513CA6D376
-:105F4000F9F6BEE489C985D08DD91D027C8BF95440
-:105F500032FED9C2E1DA08F81B879F5CAE1021BE81
-:105F6000B22E93C94B5C82727A199D01EDCF6732D4
-:105F7000FCCD903509C6DB5CCAF8940E20B92A071F
-:105F8000C245FFB0FD660A8F668167B3B7CB2BD1E0
-:105F9000F2760A6F14F04F8E04811FC5BC3DBACB58
-:105FA00086572594E6E07306A7806FBBC9E4D80244
-:105FB00007BE27DD5DAD1285F383192EB2491ABCE9
-:105FC000DF6D7DFDD8FB77F63B287C89A0AF98CEAE
-:105FD000EF8367656313C5CF66BDABD545E1D85682
-:105FE000CDE63B90CE97395E4F8FB77892653C8374
-:105FF000C9CBA73E0EC9B4CFAB32E80B965DFE38D5
-:1060000024B87034D03F153D3E35F8750ABF054FB2
-:10601000BEE2A004FDFBAE7AD04B50EE8F78010EAD
-:10602000E73803E0758CEB1C47298D9A0A96ECFA49
-:10603000C8138C1162D12F58478727D3CBE9865DCF
-:106040009FF84AEDFAD9A9CF15D03701686FD7D795
-:106050003D42CF083D3D69887AC6AC43788B48DF26
-:106060001FCAF3182ECFD30F253ABC147FC57B84EB
-:106070009E7EE057A5941F0E829EA6E5831D04D741
-:10608000C38347498CC935D3D713786713B8DEF972
-:10609000419FBEB1E3E7CA76731AE89D3262BA7CCB
-:1060A000B49F31878911A7EF0F93F8DCF1A0C78E59
-:1060B000B1F97BE97F563D7D05C7E395871B5D40C0
-:1060C000CF317BEC78BC82E3B7ECA8E33DC7DF15AA
-:1060D0000EFC6D837F507CE54B1C8F634909E27198
-:1060E000EA10D73B8E47A7BEEEC3E31EAAAF29DE58
-:1060F000B2830C8F2D6D2E02FAA137E642FD585A5D
-:10610000D8E842FDC9F5F6783EBFF17CBD3BC0F151
-:1061100027E02C9E6D5401DEC612E324E8E5CC7620
-:106120008A37027ABAA00ACA3B1E22489FB10FE9F9
-:106130002EAEDF109E4CBEFEEEA82E7F16E4A2F718
-:1061400021C590E9380789B1C62BF5E3379B8F9FAE
-:10615000CDF1F86543B6F1A1938ED91CAF4EFC94F6
-:106160001EB0E37FAC834E63DAEDE56C075D6E90A5
-:106170001CF6C710E9E15148D49305E518DA755EBD
-:106180008AFB5C5A967FFC940978D63AD8BBCC3609
-:1061900057AC908EE36F6165A54D8955513CDC0687
-:1061A00086172D8F6B2531B047E56A9324281EC7CB
-:1061B00005E344A678CBAE268837E2B02F05FD8AEA
-:1061C00039131473FECFF872B90FE8B52348F10EF6
-:1061D000EBE26C85B7377CE1ABFAF1EED40F5FAB45
-:1061E000B5E3FDA670BA0D5FB3F46C5B79E2E9E14B
-:1061F00017A593D01F828F04DE06D0A1D55EF65777
-:10620000DBCB4EFD13951CFA678874524F91529068
-:106210008B71AE34A3B37060BDED928BDB43DED8DF
-:10622000593ADE4222910CDAFF0A921805F83EA68E
-:10623000E9F87DA52B9107E50BA467E7C831FDFDC3
-:106240008F52C83189DAED1245EF6A0AD2702F8970
-:10625000A7A33D4CC2DE3C4401E245A2FFDF8AFC1D
-:10626000A2B8005F2382EC3D896628500E11F1A789
-:10627000239D3CFC9FF9AB9FF98B44E92BF1A70CC4
-:1062800074A4E3BB4904F9C14BDAB19C46BAF0A946
-:10629000916E7C06A8C68667900425786611039FD8
-:1062A000E48AD8637194C30782C8F7BE3F908FD346
-:1062B000FBE7B38ED36D3809FF48CA053AC4895746
-:1062C000EEE7433FE7436AAFA15ED64A19FF6A9300
-:1062D000E8BA5A86F28F7E17F988E2B702C665F5EA
-:1062E00005BEB772BB7A4B9317F5CDE6A6203ED517
-:1062F000A98D61002FB33AD17107A55786AE1AD781
-:10630000D3F90FABEE89839CF85B99DF966630FC7E
-:106310009EDCF8C44B8BE8FBB6428DF9412DCC9E38
-:10632000CDE0586C9B9C88ADA5F06D2DF41A56FFFE
-:1063300040E8A7ADD7260EEDA7DF3B75DA23FDEBCE
-:10634000AC3E9258037253A08226229B27FC930EE8
-:106350007A2DADB8A7C9AA77B40F65A6BC0AA25119
-:10636000E02B3ABF282CEF4EBE6A2BBF02F562DB52
-:10637000A967894E2B14D5C44DC0977F2A3565E98E
-:106380003CFC35BA2BAA8154465E053C67B4062511
-:1063900093E22FAB5A9F0632AA119DE96BA53B04ED
-:1063A000F23BA0FF91F1D01DB4BFE8B5AA7110D99E
-:1063B0004A77CDF7A796872D1BEFFDBA99C4AE0A91
-:1063C000BA24A4FBA96BF3F2C1FFF591607EFA2415
-:1063D000902F951C8475EBDA25A32349DAF5CB5968
-:1063E0005CD835499FA9DAA5CBA4B1CBD26F898BF4
-:1063F000C9A1CBE5C5676619E3A3A252EE17B71290
-:106400003396040E93C3AF2971C2FC39DDF559E20E
-:10641000EB6DAE2FB648A4B62BC9F74E0ECF0C7954
-:106420008F09EB6FC646B64EFA28A85D14BE2285CA
-:106430003E2DED66F1FA87F8F312F450DE4320307A
-:106440003943D3833EC7B8E259FE09C6DD46C79536
-:106450005D415CF704DE9DF4144F97CB87F53EB8A1
-:10646000F6C5101881A9E0D4414687D167017F861F
-:1064700050D713BD943D9DE35D6A7F5F74B1793859
-:10648000FB2507985D95C1D7AF93534A9AD1EF9DED
-:106490002DFC50BBDE007F18F451E701BAF01782E3
-:1064A000DE60E5CD318276566F1965E42288277467
-:1064B000A3BE2D20119463FA09CBAD5CFFAD07FD9F
-:1064C000479FEF93F02DAEC9A04762A7145A69F613
-:1064D000A4BBA7258B1FDD09F231F9D2D6A92FD293
-:1064E000E7426F7829F4AF19674C505B99F3249415
-:1064F00027A75C51F60CCDB5C80D91055F30796AC0
-:10650000E1FC0E723387966B8A93C3D9B9B1223FEF
-:1065100082FDE9C3D1EE50F4E1D67E3BBFCCE46A04
-:1065200087437E3AB8FCAF017EBCB479E6D5D0672C
-:10653000D08899A02EE7471B9F06BACD93221B5CFB
-:10654000B4DEBC7BC26E903FED40375D23F1FD268B
-:10655000C0478DDE0E94239AD91D85E7E6B245A883
-:106560009F7B436CEAA9F82ACD74D9FD27A73F3851
-:1065700044791C6F44A701BC7AED7B277375A05347
-:10658000E461806B64F86415A05DD3CF9859167AE6
-:106590006597327DB882F371E66C4A37D0778A19F5
-:1065A0009AE387688EB91FE63BD4F153F13DD89D3D
-:1065B00080AF6CCEE72D06E3732107195C0E5AE01D
-:1065C0003BE06B12E3FB96607930D93AB187AFF3C9
-:1065D000DFE37C5F4092EBA193AE4BB7C3C6D367BA
-:1065E000095DC1009EF749E469987F1697B3CCEA2C
-:1065F000980BE011F234DB38539D9D03768A5E0ED2
-:1066000076B118F71DCE6F0BBDE6AFA17D4D71B30E
-:106610009245E735AE8C18A05E6715674A563EFF77
-:106620006D5FFDF0F3505F2BEB46BF7CB076DD7CF9
-:106630007EF3A4F0CBC87F0FB42B5EA47BF815ECDF
-:10664000E7816EE2B5E89B228E6779E3A92AA04331
-:106650006F2309025FCED71B9F9680BF43E1752E43
-:10666000CB3C66E9763B9EF2F99BD0EFC8463B7F78
-:10667000D69076855CC2BA314A8AF400BCB31FE872
-:10668000467833AB993F4CE1EE45BDF2E9C3FDF1ED
-:10669000C5E07E13843517E47D1FEA330A9F225339
-:1066A00038C6CD8E2B5988F7330AC047F1ACCA16CD
-:1066B000391FAA7CEF00E0260F2EE72DF08F29600E
-:1066C00027477264E03B61F7264E12E66FD9E396E6
-:1066D000C25E0E84A8BD4CE525B32641C03FCE3E28
-:1066E0002D1BD7D32AC36A8804FE9FB063B3B85C5E
-:1066F0000AB8B6723B794B5308E5285BEB390D714C
-:10670000FEADF92E630D01F9AD40FB6D4755220436
-:106710007E60B0B262E31DB47D5B938EF5373619AF
-:10672000D87E4353253EDB6B5E47FB776B88D9BF32
-:106730009B9B4AB9D3C1E0CE1276728D885FDAE1B5
-:10674000A2ED6DFB1FA23E0959E25A4596F63AD3D7
-:106750003783B54F9F648F8BF5B53787D6DE67D803
-:10676000DB57998956F087833CEE2FF45E80D7097A
-:1067700056BAD06F1678F694DAE9DE5E937C3F471E
-:106780003C9DE3113DCD367F12AD43F85671F85272
-:10679000F5B38EC75F44D9CDED4567BD15325F1F98
-:1067A000F9BE54908FB5C3A4F8B0C461B239DF6D9F
-:1067B0009DCDFC321264F13AE197B909B1F9656EE9
-:1067C000BE1F8565D4F751A68F1DF08BF62A6F9FEB
-:1067D0000A0ED5D9DF59DA4F85A51F079CA9E073AA
-:1067E000EE939137EDFDA4D65F8E76E7874687015D
-:1067F000EDC06A28B596B31CE5E18EFA458EEF57D9
-:1068000038BE973BCAD738EA4F7394BFE4A83FD746
-:1068100051FEBAA3FE22C7F7658EEFAB1CE57FB22F
-:10682000D72FBBEB93E1F7FF333C09B91A88979850
-:106830006D9FD7295745243E2A0E7E43E6734BE0D1
-:106840005342969473CC1761712D129F60F55FFFD0
-:10685000A845FE00EB58E747665A98CAD581F6E787
-:1068600003A08FC4FBF3D2AB81F13A21F56A7C25FA
-:106870008B03B5A3DCA411E5F544295049C2F8996E
-:10688000575B8C28F716D3F7567DD5CEE4AD18FCB0
-:1068900022DA2EBA5D45BB2F3A92C4C6D2766A81FF
-:1068A000BDBE9BF74F7258FFF89EF65BAE307F215E
-:1068B000146EAF02D91D5EDB75129E4EFC84A64796
-:1068C000AF7E06E20B3B981F7E6006F5032C7AEE46
-:1068D0006685E9B7DB944BF64B5F9C28F7F77FE0C2
-:1068E0005B9AD14CAB1C0020C0EFFF963706F18CB1
-:1068F00051109F639B07189F1B49F81F8FC381BBD3
-:1069000008EBCB48ED34C6DBF4BAE029D0757395BB
-:10691000121CEF7B52CF7818CF957EFE6AB62EFE02
-:10692000ED63B47B38FE429B2B12518A3FB24D354A
-:10693000C61258520D94238F425A3CE5C01E0CDFFC
-:106940006B61D565EF157F16C4D9C2585641EFC2A9
-:106950003A067C24C3FE761CCB7E92C07206B76FCB
-:10696000C781B3087E00D125A6270D09F6994237C5
-:10697000503F3CC9BA1196AAC62993FBE39492CE24
-:10698000E29152DB337F91205E594A74B64FC5E3E2
-:10699000821B65E96388B70687B6CF13BAC54E5721
-:1069A000A2B49339163EBEA58F9E0C5F63426CFE67
-:1069B000A16D6A23F8310766D9F940D497954BF653
-:1069C00007774E18F3D9F141A63206E119C807B787
-:1069D00006213E2D4529DED2878EB7A06C7E5DC193
-:1069E00079122CFF40326F053A89B242CC05D6F2BB
-:1069F0006FE5F0422847A791D246ADBF1FFA7E71DE
-:106A00008AF74B93BD1F27ECD5B36CFD2EE1323EC8
-:106A10006C4FD005766461C7AA34AB7D55C2D7E907
-:106A2000473B8EF860BEBBEB93EB3FF1DCC2FDBD94
-:106A300054F502527718E841262BE460127BFC499A
-:106A4000E06F8B1E0D38ECC2EA966815B4CFAA75BC
-:106A500011880BD3F51DEDBA426E1FEE9C1A9554AA
-:106A60002A873B7611B48FB35A16F9ACF3C9E7F312
-:106A7000D9393B2F0DEC957D8B177D09FD156AF7F4
-:106A8000CB181F8F6C82FEF36BD83EBF13BECD7C3C
-:106A90007EED8B199E9CDFD355124926874F2ADC49
-:106AA000CF55A212C9EBDF37D97CF2BE5F8DA7E3C9
-:106AB0009554BA0C9FDE0FE7B83E7B2981F84ABF98
-:106AC00046096E027BAA43B5D999FBF63CB86B31F7
-:106AD000F837F43DA88347AE6D1C1EA6703DFAE55D
-:106AE00025CFDE057CBFCE45401F0938B432BB9DA3
-:106AF0007BB24F3EEDE3D27E991F47970F39C9FE17
-:106B0000C9E5E2A3838F9B8A4F9CEBA9930F2E6567
-:106B10007DB851BEFCF9FD18E490C293C7F3B58669
-:106B2000D5EACC6FE37294ED158A848D93C7F92C66
-:106B30006BF6833EE0B35DB5E5283FBDB31749A0D2
-:106B40004F441E54AAF152C193EE6EF7411C74D704
-:106B5000E207A56478CB8FB0F890F3BDE966FAB48C
-:106B60004D6997A07DAA7AA3DC9C1FB85CE5F379F8
-:106B700085A6C6C380AF3C43216B28BE76CC5E544D
-:106B800055027C47E510E22AD53504ED877C93ED6C
-:106B90000B0529BE9EA4EBDECEC5C488D37A3B4D3F
-:106BA000D5B61F23E4D0C98F3B175F5CBF10AB7F06
-:106BB0004EF95F716B6C7FB09814831DB523857D92
-:106BC00076A9F80D2D76B1F86875F920FABCF9525E
-:106BD000D7A9F9D7023F0E35DFCDA12FC853BB6629
-:106BE00095805F6B507D4192E1C7AE1F06C387134E
-:106BF000FF13009FE99F1D3E9DDFB3DD3CBE3D447A
-:106C00007CB4D516FD0FDC034F51DF391FD14EE4A4
-:106C1000A77D91F4C820FF2670E818F0260C7C565A
-:106C200093303EBB95C857DCB4FE4CD28865117FCB
-:106C3000AA53828C1E3CFF45EC732BD319DF8F9B2C
-:106C400048629DB07E4C9DCB377F15F39C178C36E8
-:106C50000A47127F8A903538EF118EF558C427867F
-:106C6000D5B7CF2EA7FD8E98EDC2F8C588CA23B63A
-:106C7000752CC0E547F4B7BB7268EBF3238EF5F9CA
-:106C8000112581F95D8F54AE6986E546C97A339442
-:106C9000ACFDB80E3B5EB77ED4E50B278167F7E20B
-:106CA0006398C7B5BBF2E2F1934706E19B7172723C
-:106CB0007BF68B1EB6AFB43BD37B334B2E5A6DCBDA
-:106CC0004320B256681D77F74724337C517D629785
-:106CD00097AD6E9E6FE0277EE0FF54F810CFCF1A7D
-:106CE0000F8F4E6B5C164ED2BEC4C3EC89759924CF
-:106CF0002A533E79F4652506790E84EBE18A9BF5EB
-:106D000018D80BEB404950FDFB6815C1EF1599FCF5
-:106D1000FBC33AE6558DE8205195AE67235E5ABC19
-:106D20002393D66B5B4C3DC7C2FEF76DC6A956D800
-:106D3000177EE20517C6732B7C71AF41E755C9D7A3
-:106D4000C1DD8B4F61DE71748F628C45FD2E11A900
-:106D500002BD785B1CF3845B61EBBDF1A04FA7ED36
-:106D600077E909ECE79B534E7975D82F2FE8F6C2E7
-:106D70003CB754B2F5F2C8E2A2AF96205AED79269C
-:106D800033E5A9DD261D6FCB62B65F9199E8F67AEF
-:106D9000E87C02B50AB99EC217D0D87CDBD6911820
-:106DA000AC53E53C9F442273D01FCE77E409E5390C
-:106DB000F24D82C6CCB760DF3F08FBFB3009B97EDD
-:106DC000C755A06F1B5C3C0DD54439F5F3F9F90D9F
-:106DD00013EBCF948FFB60DF77578B12C4F5CFD1C5
-:106DE000AF731E411239694AD80F8EB3EB21B64EEC
-:106DF00006276B06D558B429873B48E1CEA643B693
-:106E0000D8E11678758EE37794DF14FC3C828C050C
-:106E10003D24E2CC027E27DFE654C48E3E4FE7BB22
-:106E2000FB050DD7EBDD95CFDFD200EB7CA907F397
-:106E300023BEF4C1A1FA7FA1CF5FBF77AC189E3704
-:106E4000E41F98D4007880FC8889A42F8E97073D92
-:106E5000A3FDCAF59A18AF6C5F8B3B075F45FDB485
-:106E6000BCE5D4CB75108FCEAF2768FFE62B8C3FE7
-:106E7000FD2DAE5833853FE79A76E48711B571044E
-:106E80005AABED92A29678A7C8FBF6D747308FE2AF
-:106E9000FADA76CCF7F6F3B8AF7F523BDA4933E44F
-:106EA00057BD68AF71FA89FC77217F4EFA942CEEBA
-:106EB000AE817E46B42806803DA2BED105709554B1
-:106EC000D2358BD2ADA4A34B62FE1FCBA76729CFCF
-:106ED000F419AEC3BC2CB287E5178A3CF040BD9DC7
-:106EE0007EC1BEFCF9880BFCEFC20EC7F770CD1B4C
-:106EF0008C0FEDF42C52393D4B781E21C7C3088E00
-:106F0000872DF57C7F4EF3C62E66D7BEC0F7E75EB1
-:106F100084F98F1BF8FDA614FAF746D0BFE0B7BA84
-:106F2000BA5B011FE41A17FA714E38B6D633BD7733
-:106F30004075D9ECF8CB1DFF36AEFF6557E2EF3256
-:106F40007E7DDFFCFF3EE3DFFF771E7FD3DF19FF8F
-:106F5000BBFECEF33FF41F3CFFF9A592CD4FEB549F
-:106F6000BDD8DF4F3C223E66D7DFB22BB9BFFDBA9A
-:106F7000EAB2E5138BFCC4E9B5E6428897F80D76D2
-:106F8000DEC3D9DF0CF9B956D083BB785E36D5A302
-:106F900026E4A9664C1179324CFFD570FD57C3F534
-:106FA000DF91147AB5BC92E9776A5FC4F442583233
-:106FB000DAD19F099C56303FFB08A1CB0CE835DDA8
-:106FC00093343F3B8FC3EDD4A7795C9F963FE7781E
-:106FD000CFF5A8739D2FEC8B9F128C9FFE7795E7C2
-:106FE000033BF4AAC0C3AE4A662FE7CC4D6E0FB682
-:106FF00039E8A84D6AC4FC03273D5E57997F2DE808
-:10700000B1D06BBEA2E6A6A67782D3FB3A4EEFDFE5
-:10701000A83C1F8AE789A4A277A5878DF379FFD9B9
-:107020005033CC265C857490399D64D2D68DF15F47
-:10703000F24D62F52FB77E44ED1058FF35CD584321
-:10704000CB9FCF212E9174FF91D89FA37FEE6E1618
-:107050004795735487BFE5B483BD513837B3DB74AC
-:10706000C5A285604F74EE5E09EBD30B6998A7BC8F
-:107070003BB3E339F4E7DA272A0087B01B098FCF47
-:107080008249C1F2509CFB4E76BB7FF7475D71B0E1
-:10709000BF828512C6FD5AF50773929EC773D8FB4F
-:1070A0009AC76FF377C9F543B3DBD7727A537F3151
-:1070B000D76391EFB5FE9913591E547510F67724D6
-:1070C00073A60BE2E9A9FA8148EF39CB7E539D62A2
-:1070D0008E84FE24F01F4BFBFD47420A587C5ECC99
-:1070E0007FA8E707EAEF62FBDE1CAF39D7747D2A81
-:1070F0007EA4F0FB453D919FE7ACE7F4C7AF779BDB
-:1071000053607E43857F2F301CC4B3CBE49A64F177
-:107110008304D7AF5AF8B1676FA25527CD93587C37
-:107120009F9A6DD6FDB4B61CA52659BCEB975C4E54
-:107130007EA3EA5CAFC7499684F92404E625E4D12E
-:1071400039FED57CDCAB2F73FC17B85C5FCDE59ABC
-:107150001003F763528D5BC5F586787ED271137C80
-:10716000DE552A8F6B0C32EE1C3ECF399739DFF398
-:107170007CDC39439CEF423EDEC2CB1CF7433EEE43
-:10718000C2218E7B37C7EFDD978967C52BF17E86DD
-:1071900086E7663E5EF3658E1BE4E3360F71DCED39
-:1071A0001CBFDB2F13CF057CDCED0E3CA792DFCE9E
-:1071B000CB1CAFD4CBE4E700975FA75E13E36BF97A
-:1071C000AE30B4DF1DB2F77383878D2F9E24FE315E
-:1071D000FAAF23F8BEEE9495F72E32938C2BEA3B50
-:1071E000D7E354E3DCC2E335E229C609F0FDD02938
-:1071F000D7D07192E047D4BF5A657A3055FFCB386B
-:107200003CCB2E711EA27E15F43F3975FFF7713805
-:10721000EE73C03F58FFA2FE9C41E06FE570B45E84
-:1072200022FCA2FEC241FAFF0E87E33B9708BFA8EB
-:107230007FF720F87984C3F1C825C22FEA370FD22F
-:10724000FFE31C8EC72F117E517FFB20F8798AC384
-:10725000F1D425C22FEA1FE89377BBFC69E23E0612
-:107260008394429EF1289266E0FD0646E224F801EE
-:10727000DA6A76BF01E9729E87B29CA3A2227EF2EF
-:10728000BE9228D4DF7B178BFBEDBD9AA01FB137D0
-:1072900097E729F3B896C6EDC1BD57B338C8DE10DD
-:1072A000FD6EF1CF44BC68AFC1F29C7B0B581EB39E
-:1072B00056D68E26260E97C74D441DF269D8B92A98
-:1072C00061EF89F3556B799C6AAF49304EB5B78C45
-:1072D0009577579398ABD072EEAA348EF9A760D801
-:1072E000423CB6FFDC984956975BF23156C731DF16
-:1072F00040E179231421C49697E138AF25F60F6F4A
-:1073000032CC19A0E60A27B1FDBCC2B0DD7FA88748
-:10731000435CB4FEEFB99E0C4E4A7E9EE6B05761C8
-:10732000F4E3F99AF3F8FC05DECA393DB7CE79AF3C
-:107330007B3A9DE7B353DD983FFAEC698EC7A9729B
-:107340008CED9F1377B27338A9E26C5A47E3293862
-:107350009F7BD373C40032FAF798EB748CAB7D84B7
-:10736000FC8771353AEE4D7BDA15E0BF591DFA7492
-:107370008807CE7B4E5FAB41DE7507314C40EF474F
-:10738000DFC07EB25A881163A46A0EA29DEB88CF3B
-:10739000F17393223E07E16AAB7F398BCFBBBC25EB
-:1073A000B80EB6EECAAB3D36FB7516F733BF627A40
-:1073B000ECE725F9F9C7590E3FB3C36B8FD7691DA9
-:1073C000E11910FF96E79D31E1FCF3B8B0141C46BB
-:1073D0003FDF16DEAE407C72D69E46CC5F4FB5BF17
-:1073E00095F1F05CBFD57E17FBD9BFD973717B5D7A
-:1073F000C41944DCE134E4157BC04F0F71BA30BED0
-:1074000012FC91354FB2F1498797E9910E2F8BE32A
-:10741000FF179F7CBA7CF23BAF3DFED001DFA83C5A
-:107420009618C9F7E9EBBCEA7FC9EB674087802F64
-:10743000391D487D862D8F58E45539F1B681E34DCD
-:1074400094BD29CEBD14F8F83AEBF4EB5F8D54C12E
-:10745000BC449C8690FB1DFB9B538D8BC5256471A2
-:107460005F8CEB5519E653EAE3FA47210AF6EF98E9
-:1074700007CA7D1E9E53643038FA5BC7CFAB89794B
-:10748000B98BC326DCB742C7C0FD3EC8573F520682
-:10749000EB63D0366FD3C7D69B4DA58CDF36952ACC
-:1074A000B174965F65BFB7A8B8D39BCCAE104F62DE
-:1074B000BDB7A26820BC6A71246A8547E5F038FB35
-:1074C000999B129E3A5BFCEB52E1F18C27A41BF8CE
-:1074D000568911A697BF61EBCF551AC3F3FDA9FAE0
-:1074E00051743E2F075D528DEF2DB0E741A93969E8
-:1074F000367E57B42C479E9483BFFAE242431BCF9B
-:10750000796EB1859F4771B6F729EDC44882779FA0
-:10751000EECCC788211D9CE76ADC4107DC8EFEDBD0
-:10752000E05D923C1C71DFD006BEAE6D5462686FA8
-:1075300045299890EFB98EF3A5128CE1BD5EDFF678
-:107540004949E74F8CE4EBAD529C1C7E6F811DEFE7
-:107550006A4E969D0E4AF2731C1B85DC070F98F647
-:107560007BAC9C727EDCB8D87ADE77AF96F43BF9C0
-:10757000633AA5833EC73D0943A4AFF261369E6BD3
-:10758000EF2B53BD0AF15A2A2398CFEBAC7F46E08C
-:10759000EFD54E845FE8E9F43D22AFF693CD4392F8
-:1075A00008DF27B7B74F29875CCFC99CAF9F1E6400
-:1075B000FEA9E89B56ECCC2B1C1A7D7D20F7B0EE83
-:1075C0002926BF0CCB2EF7A9C6234136DF4B95FBEE
-:1075D0004F0A67764D84803E53431112A1EB7C7EA7
-:1075E000A81DF7C935A9270AFE1895291DE8BC3B37
-:1075F0005B67F76658EA4DA3EDDC85AEA81BF24049
-:10760000F87D30D110E982FA108FE92CEBAFA74951
-:10761000240CFCAEE52A61782FFACB986AEF8F9A9A
-:1076200009B2F51C96C817405787CEDF3D85FAA7EB
-:10763000B4BD4AEDD07DC9F4491AB343D39FF29942
-:10764000982710D662C092F9936298CF995F470C41
-:10765000F0E74A3ABA498476FA6D8063327CA7F340
-:10766000D620FFA31DF7ED733CECDC7A7E7DBBB426
-:10767000D0324E691AE3EF6973BDB84E7CA38A9D80
-:10768000DBEB0E2D6AAF82F12AF97D7A390A194EA9
-:10769000F1E17FC9C3FCCF490902F809F2BC863782
-:1076A0009B48F9E2B184BCDDE4C5E7F9A6203E833E
-:1076B0001FFDCF10E4B9AC9B5CA143BEF507FEBA39
-:1076C000D1B06EBCDB14C2EF5BBE65E8904F249F67
-:1076D0007A19EF8FE8E7F7A84C2A210F366102FDEF
-:1076E0002CF3EFF459F6F9FBE645E7BB908EB3595E
-:1076F00072DD0EE3417911F2A957562DF91F2AF7D1
-:107700001BDDEB48F8B132B8C72426DD5D6679EFA2
-:10771000A3761BACAF938348F77E7CC69A39BEAF85
-:10772000067F37FF398ED7B99517DD37696B8A77B2
-:10773000578FED2F6B29CEBBCD714FBB2E0DE2467F
-:1077400070D8938E377D6EE930C0D743EEE4F72FC3
-:10775000C8C1894631D48DE6BB500EF93D2BABC66E
-:10776000EBC3322DFDCFE17C299FFA29E237BD8C96
-:10777000E587D0BFD9F996FCFF82481DDE8F441AF9
-:10778000D93918B10F39FAD644336C498C5E6D3F44
-:107790001F33939FF32C5CE7C2FCD7C229A843494F
-:1077A0006133BBBF6ABF6C94037F3F4C5EC88403E8
-:1077B000EB0514BE9154540BA3F67EF62F99FD0CE5
-:1077C000C401C4B9D1B52DACBF51BA715A87F849BB
-:1077D000990BEDE5D1C4F042FFA3351781734563E2
-:1077E00088A59F4238476BEFD7096FA1DFE5827804
-:1077F0008780671439EA3573B07F12A3ED0BA89B1D
-:107800003722097CCE71C6887A579597C7499271FD
-:10781000494F33EC0B0D187F907E9BD2B81DEE279D
-:1078200001D0E77B2436FFE8B3B27110E87AF72184
-:107830008CD714ACEAC075BD238DD977EBA93DA0D8
-:10784000B9C14EA1CFB1A9F9500E52C465E0FA9169
-:1078500094FF1E4DABDA9606F1B0B469DB800FD30E
-:1078600014FD6B783FE76937817DCC34B31DE50F9C
-:107870002E64023B6373595106C85B5AA39AD45FC6
-:107880006B4973237C7BD22405F242296FE1BC94BF
-:107890007AFD3B3369B13BD7FC1E8CF397DC083E85
-:1078A000C5FBD0A25A1DF873FAD2328C7FF5764808
-:1078B00018FF7A438AA990AABD7C5EE304B82F67BB
-:1078C0004E66E41168B7548EAF77537856DCDA58B9
-:1078D00002F8990DF97EB9305C94F98305AF1B0A63
-:1078E0009C072B50E26ECADFDEE0A997D8335A0519
-:1078F000FCEE859330949E8162F32DF09BFCFC1C82
-:10790000924C7AA2901718984AC8EB16BA814F6722
-:107910002DC39EAEB59C0AFF833D17D3B6AF8F85AE
-:1079200055DE3025B40B62883F35684C0038E5D011
-:10793000E9BC62CB3AE7E1F3F34C5FC4EF4932B9FB
-:107940007F6310AB7FEBE1F3021DFEBAA5BD3B6484
-:107950002FCBC14F771EC2EE967EF1D77340C7B5CD
-:107960008FBB31EE39FD7177FC3A5A5EB14FC2756B
-:10797000C67582E9F5770F4828F771BF8A7AE09DCE
-:10798000A017CB0D9EEEAD5FA0E59EC765D28968BE
-:10799000A9C57BA5CE89F5F4182B2FE10ED28A7DDF
-:1079A0002717407F75C73C04D689153F5D7AE317DA
-:1079B000687929E563A8B2E260B33A9C96EF8A49F8
-:1079C0005D50BE308D209F45B3D418E4B55C08747B
-:1079D000E7DDA4E13A46F471B0BFDD9D378FF2E3F5
-:1079E000B2D86333A1DDB2C3124452E93C0E3E93D8
-:1079F0004FE15AF17D09D7C7E587D2D95D2B1C7FAE
-:107A0000E7E854AEA3DF57D179823E5C4ADA6702D9
-:107A1000BD561CDCAE5AD7B9B79B4A31F5439457D3
-:107A20007C9F8E43DBADFC9164C0145742BE03AC17
-:107A3000973FF5D5EED7607ECD6A891FE6B54185C3
-:107A40007A4B630B9FF0E900DF3E7526FDBE6CCFDD
-:107A50003E754919E08DDC0EEBEAF2435712DD4228
-:107A6000D7731D32FA0BAB32BD9D78BFA966BF0F2D
-:107A7000A51F2E62836B19D71BD4EF53ADE7DD9E94
-:107A800048CF443E5D7E48B68D23E81F3D43D879FC
-:107A9000B49FFBF13C9AA09F58AF04FD56890BFFA1
-:107AA000949E8A64F06C057AC0B91BEADFC0F3C10A
-:107AB000A6103E1F6AD2914E3B018FE3585E0ABC6E
-:107AC000A7725B05F756054CB8180CCEA5985590D3
-:107AD00087991566E5BC5B23927E113B5D3C77BAC6
-:107AE000230BC1C8999AFEDD190AF5C776AA91BB86
-:107AF00021641D543A6754D335AF3E3D5C916ED935
-:107B0000F75B2FB1F37D9F4BD771FEEBF355C4F7B5
-:107B1000CEDB2AF6F3F813AE933B6F5BF208C4C7D3
-:107B200069FB2FA6837FC1F7FF52B5CF5B50696B0E
-:107B30009FB7A04EB49F89EDBD176FBF73C135F6D7
-:107B4000F1172C13ED6F44F8B58BC39F77FB54FBF3
-:107B5000F8B7D763FB060FA36F4FA617F3AD5B7C97
-:107B6000461CF4315EA83609F2C94B3AA19E5877FB
-:107B7000A8E637217F5B3B9C59BE8958F968DA0239
-:107B80008003F2B2AC7C9451996693AB4C33CB56E4
-:107B9000CEAE196EAB9F1B2EB27D1F567B85832FF9
-:107BA000353CBF8865000A0C730AA73A5C457D54D2
-:107BB000359CD9C1F79EF061F9DE6BD8FCEE1DAEA5
-:107BC000A11C03CCE097DFAB463E67BDBF95C03D2F
-:107BD0004854A7DEA945EE8379F4BFD75DF03E8D0A
-:107BE000E73BA57908EABB0D8515FBA3167CB68E8D
-:107BF000A4FC40CB2DE92AC33BA7C386914B425638
-:107C00007B7DFD48B516FC0D787F8706E385D7C3DD
-:107C1000780D6A4F09D81DCE713C4595B671BCA34D
-:107C2000EA709CEDE92C9E2AC6F18CAA738CE3AD18
-:107C3000EDE4EFF9383B80CF528DB3A1E81AFB7C1D
-:107C4000462DC371F63AC6D9306A99639C34361F03
-:107C5000FA9E8F13BBD8389E3153EDF3195D8FE335
-:107C6000FCC0399FD1F58E71341C07DEC338D4F0C7
-:107C7000D5E1BE2CD5D3B304E9FF0B1FDA39AA270F
-:107C8000F228DA39AFF8D0CEA1B54CA8474A997F8F
-:107C90007B4F7A16D2E783344A7FCD4AE728CF3B21
-:107CA00088A25F7C270791C4284454BFADE43CB848
-:107CB000F8F09C51CDF03C363DB410FCD187FC1857
-:107CC000C77BF7D874F58E24FAE8CE76F7B98485A9
-:107CD0009FFBF42A8FC786D2D93EA4289FE3F19F49
-:107CE000D7214E449F6FB809FA436779BCA81FDEBD
-:107CF000666C778EEFEB9DDBC3D6A90FB69F71A3A1
-:107D00001D11252F9451B8E7F369DCD96EBF2FB34D
-:107D100081D3A3E7A71E760E889823F03EBC8E6C15
-:107D20005BBCF07727BEFC0CCBBB2323E0DEDFAFD0
-:107D3000B73EF634547B515A3872159D6FEDD1ED34
-:107D4000EE11B4FCAE3BB1C0D02CFDD4BAF1DCBD19
-:107D5000F0436E8EB86DF6F32D75F6F26D0E7BFA6C
-:107D6000D5F422B13FCBC6D5636EA0D77CD863A52E
-:107D700024BC0D9E987C17447A2D08B2B6029E86CC
-:107D8000FBDD248EEB5D2217E39CD15C8CD344C4D5
-:107D9000BAE5806F81DB6B86293D17DC27231E9DAA
-:107DA000F0264EA49B2EEAE7243AFEB71BCEF10C38
-:107DB00006FFEDABEDDF49D46DBB8740F0C1D76A5C
-:107DC000ABF69FB5F0C7CD9159FBCFDAF034C7566B
-:107DD000BEADF1665BFDDB572FB47D5F18BDCBF602
-:107DE000FD8ED6BB6DE53BDBEFB3D55FDAD16CFB27
-:107DF0007E576CA3EDFBF243DB6DE5155DBB6CF5C7
-:107E00001B8EEDB37D779D18FF15F4037F23E37977
-:107E1000E7F7B5735BC17E7B3FA8E07ECE9B7CFF1E
-:107E2000EE6D7EDFCF4AE0BD29203F13BDE0373441
-:107E3000A45179A6B6C4042D777DEB54D02304AFAA
-:107E4000D428D746AC8F5267770A3F9F2877A8245B
-:107E50009E0DDB2BFD71D81EB9FFBB92A0DF27A6BC
-:107E6000FE2E772849BF2B092569BF17A49E12B0A3
-:107E70001FA32F7B929E03EF974B32825CE43EC997
-:107E8000F32E5267F5DFE66B2C3EF44CFAB4F95A48
-:107E90002EDC8FC1E4BDFE48FE34F01BEAD57849E4
-:107EA000B27D9BBEF1BA24BC3770BEC6E4E5AED845
-:107EB000085B3C6DF9A13136B97F292D729346EBF1
-:107EC0009D3F29A39E25F1A7467DF52A18DF9C0F2B
-:107ED000EFC9B15C5C1F5F6C32F79FA57EC04B4D54
-:107EE00035F8FCD7A6F0FEB3D4257CB5A916CBBFD8
-:107EF0006F8AE033D15487CFD79B1AF1FBD9A6D52F
-:107F0000583ED714C5E79B4DADF87CBBA91DBF9F5C
-:107F10006FEAC0F2BB4D317C0A3910F62E09737B33
-:107F2000526C981056EEE57390F3441CD3C0FBA33B
-:107F30007AB50F4AC08EEE7DC98379B7A9F0E4E423
-:107F4000BBD4F43371BD5F12B3C799C5D397C6E8EC
-:107F5000E373911AC891D83856C5385ADA2FAE440F
-:107F60007B9CBE57D865B231634E927B3BF142E4B5
-:107F70006183D349D43FF7DD7FAF585406F42942DB
-:107F80003CA53D253732BAED37BE7AD5E0F8439BA4
-:107F90002F7F201EA55FFC6E14C4A7DEC915F8EC68
-:107FA0001E05C12D450BEF023EEC3DEAC179F51EE1
-:107FB0004F67F92810541B42FEEBF243BE98553F21
-:107FC000ACE8CA8CD9F5457ECCAA2F7A4FEF0F804A
-:107FD000DCAF0AC9B1B313813F4CCE1F8CEF44FF15
-:107FE0002BBA0A639AAD1F7BB9B75DAAC17B1F8903
-:107FF0009E312F89FF219EAB422A8EF3F6A1319844
-:108000007F40FDC4D85916EF8CB17143312B5FD638
-:10801000AF4E8F9DCDEE872F55BF9F367C841C259C
-:108020007FF0A63E8F3BD89328FFA6E2FD6EC7DD0A
-:108030001FC0BAE3A1FF7F8CF9420A9645BF0D5DD0
-:1080400072D403E779C961DB78B49D2E7C7458AF94
-:1080500052D3DD9E0FFE7BE0255CB7D9F9F2089C78
-:108060002FA7FD5D50B456E973FDE7CB1B385FAE1B
-:10807000F026D4087DF5CED13117CD0779BBE97450
-:1080800050190B7904ED7871445DD7F86AD08FEF01
-:108090001C5D9B07F1B4E572EFBDC9CECD7EA8B1E2
-:1080A000381B89B97B1296F988F80C21B45F6F3FB1
-:1080B000FCC0E9E72C65A7BE164F979FC5DD571E8C
-:1080C0003E33F30B14FE95C7DE53018E635AC4E5AD
-:1080D000B7CC5FE2E7EB971D7A4D85F9BDE98E9647
-:1080E000DC7F113D35104E2D64DB0F8D926E90E3D9
-:1080F00045EC3718809FBEF60A15CDB77EED26F009
-:10810000BB0E62BF429C7B584CC201C0D7A2A3CB1E
-:10811000313EFCD61337707BAEBD02F8E31DE2AAF8
-:1081200081F9BD439E0F4CB4E0AFD8CFFC18D2CA42
-:10813000EC18712E90DAB336BB666987BDBC84CC6F
-:10814000CD03BDB1E42137895114DD452CF72FD182
-:1081500079E7F899BDBB9434AE077B4EF130FF60F0
-:1081600051902823A83E5DF193872BC0EEBFD2CF5C
-:10817000F61D451CE3AE2C66EF2DCB89A9B09FF010
-:1081800087A313E77F01B8CF135B0FEB32C948BE5B
-:10819000FF7747AB1DBEC1E077C22BCEBD0F88A7CE
-:1081A0007038E44352D2FCB4297ECE775C8FACF1B8
-:1081B000DBEDFC0D8EF26C3F8FB3CA44063ABF1361
-:1081C000F4465D19F81DCFD9468F788CB53ADCA7F7
-:1081D000150E037F51BB6002B1D4FBA316C1F7E7B4
-:1081E000A5E796E03973253E01F3F1BC04F314557D
-:1081F000CE0F725A6002F91CC4491BD1A95FEB0B68
-:10820000744279BD9F9D836A0039A5FD6D09CC3C00
-:108210000D717D2F698F9B85B0FF6D8F7FFB747B08
-:10822000391DE409F409BC007A1804E345E9A5F610
-:108230007A7EC35E5ED687A7B86C3DF711F06A718F
-:10824000F89D2152A99CB7DACD2BBD0C7EB8111C2C
-:10825000EADFC3EDF995448F62DE6288F1C13DB378
-:1082600058DEC43D7EDD88D2EF9262E2F9880DD0FF
-:10827000D4B28E357C28919845AF37283D2AF065D9
-:10828000C3870ABEDFAB45BE057855898976AE97B0
-:10829000220DF6AF15ADC666F792027E2FA0237FA2
-:1082A000A1CD1FB4F97B422FB8B95EA4FA62833F17
-:1082B00017F460CF4CB6AF9E50D9FE0EABA7F6D7E1
-:1082C0006B033852D5F3F5D7DB9EACDE8A9FFCF00A
-:1082D000892895F765FFF2ED006CA6BDA5B4E741CE
-:1082E000FE43FDC17501E0E337956800E6FD562CBD
-:1082F00079DEFB2FB9BE837C27382FBF92D3E9EDFF
-:108300007FDE7C23E0FD83836E3C6FDF70C813F754
-:108310005022AE3C7A17E3A7439ED7587903FE6EEE
-:1083200054C331BBBC2D7BF4DB793A6EEE4547F08C
-:10833000FBD8D17E5E79E08F33C11E69203DA8272E
-:108340009CED60FC0FB370FD5A08E7FE9DDF45BE53
-:108350005503E7FB86A39B31AFAAE1E82CCCA36AC7
-:1083600070C8791DF7438EF9EDBFB321F04162CC9F
-:108370002E5EFBFDEF4C788DC273FEC0AF03922DD5
-:108380007EC4F4446FD71DDF7B524FADDFDFE57E47
-:108390007D7FBB18B6D38F313B9E1C67CF7A773C6D
-:1083A000007E53FD3EB7413508A9FFE1FE47BE0BF5
-:1083B000FCFDB207E30DCB7FF8F48BD7D0F2F2C708
-:1083C000DC39B3D93434C80316748133EE90AF2B43
-:1083D000E8B0ECC74FABFA55ECFD0359FDF458FE7D
-:1083E000D849955C35107FD3BB4EAAECFCB9832EDF
-:1083F0005DAFCD04BB7BEDF7FFAC827CBD75422247
-:10840000C30A07B6AFDBF734DA758027A423A75376
-:108410001FDD06D02B7EE39393B05E10D6B1C1E88A
-:10842000F55DE0995CE4EB1F3D09FB05FFEA3100D7
-:108430000F753FFA4600E6F386D2C8F8FBE175797E
-:10844000B08F5EE78EE605F1C9DED7EDFD26F2DDE1
-:10845000D233DFCC637950663EFB5DA3683EC60134
-:10846000F7DC84F35C4222C87F750FCB9887FEBE91
-:10847000426A1E4B221FD705981E7BA3D38397DF2A
-:10848000BD010A17FCC5E7E5183B6FCBF212BF2907
-:10849000F63DE0DE465A7EDFCBE8951B70897BAD6A
-:1084A000BC36BE3DB0A11BE8F4F6487318C42B29B6
-:1084B0001EA21C6F12E821F9CC8C618C4E44572A05
-:1084C000783BAA27A7C37BA8DFED367D136CEDF8B8
-:1084D000BAC6C6BF878F4FE14E03FBEC8D3C6AEFF7
-:1084E0002499DFF280907F6A7F58F8CC22E74CEE27
-:1084F0000F6C64722EE43E36A706BEFFDB0B4C8E7B
-:10850000A01DACF314AEF830FC7E729E847AC14399
-:10851000E2C9E4FB809BCBB7FD3BF5CAD1BE157C1D
-:1085200042E15760DDEAE717B6CF4BE980F6DB9210
-:1085300087687BAB7D0EE3623DB5FFBD65BD5FCA5D
-:10854000F5C13501C7EFEEECC91DD27D79F5EED846
-:1085500023DF05F9A5F20AEB4FFD0FDD9827F2A7FF
-:10856000C34FBDF875CAE77FEA12726BD7A74EB941
-:10857000AD3B32992493DB3F6906492AB7F47D521B
-:10858000B9D512C8CFFF51FA54E06F51C09EE7240D
-:10859000F4632A3C3AF5E3DFFC3AE2D3A91FE9DFB2
-:1085A0000BA462201F0AFE137CB7EC072BF0774167
-:1085B000FAF853F05F1F7F0AFE73CED78E3FE7F7BE
-:1085C0002BC15011F162FA74AF21513FC4537F2E79
-:1085D000633CF50285693DA5F385C385788E789D5A
-:1085E0008FF9E717823D81AC32BC0707CB3DB9EA72
-:1085F0007AD017E27D8F8FC5BF2F847B02D63C9047
-:10860000D78ECB01D8EF4AC4484D327F846A648448
-:108610002341527D67F1E20B60FFC17869A362409C
-:10862000B719B2366A35F8F9EDECBCFCE2E6AF05F5
-:10863000601FFEC2F131DB407FDDF9AC4CF8EF2862
-:108640002A906F7207A7FF9B24BA732A9DE71DC764
-:10865000995FB1B82D39BF2CE3F59768F7A8A097BB
-:10866000A85FF0BA351EBE8CFF9E64DD1EC7FBE31B
-:1086700037205F2D73F05584FB8D3F147C7535B921
-:108680009AFB6D2E6B3EDB0CB96C1BD825174EB3D5
-:108690003864EF7119E9D17B5862F94F100F9E02CF
-:1086A000FCD0A35AF3D8CE03FF25B9DFA0EFFBE33C
-:1086B000BFABB89F56A97FE29509BBE9F3FC132F26
-:1086C00097FC0CCA3FF9EDA857C8C0FAD34FFC0578
-:1086D000F7B32F9CF0201C174EFC72D4FD507ED2B5
-:1086E00083F7D55C58E361F99F27FCB1B1F07D2495
-:1086F000CB175AFBF33F4F48E0BAD482747B29C0B2
-:10870000FCB1DEE3FFFE7BC81FEE3DEED1611E0D26
-:1087100027D2717FABE1491FC6692EFCFCCF15D66D
-:108720007CA6CB9DCF4A7E1FE2053FA9853CE50B89
-:10873000996CDFA0E16753F6C339A215474FAAB081
-:108740001F33FD177F9D007AE7C211664FBCEB4EC9
-:10875000EC857DD63F046EDFE086F82EACD7C309EA
-:1087600069CA885D0FF7E10CC40BC3C3058A07987B
-:1087700017C54B1DE8CB54F8F83FFFB0F8786F01F0
-:108780008C5F7FFCF32837FD78914CF6DE1F83A3C6
-:108790004D74FEECFD893F4F00FBE84F5DCDB8CE38
-:1087A0000F36EFFC8CFFD7E62DC58732EFCA7FD896
-:1087B0007933FE3F11D059DE9F430E06F2F94FEE9A
-:1087C000C5F28FFC06C23B44F9AFFD879DFF27A48D
-:1087D000FB114AF7C0E074FF6F196C5FF81F6FDE82
-:1087E00083D1FD594E777F10F2102EFCFCAF185F3D
-:1087F00017F31F6CDE3BFF93CE5BD8439B5C467B3D
-:108800005121E461C7BB750AE7BAD2B9ED1096925F
-:1088100079DEB513AE6732987F214B2C6E4346B29A
-:10882000F811E1FE46DFEF416AEC7C95A2AD67F7F7
-:10883000912906DEAFB7E98A4506E67690F29722DF
-:10884000502E988ABF73EBF4BB942BBE741AECFEC7
-:1088500096660A1F1DA7C5AF04A9E544DCA5AEB8FE
-:1088600067023E5F83E7061EFF7207559BDFA13953
-:10887000FC059F6EFFEEE1FD7BC9A920E42F790D79
-:1088800005F3537DA43D6ACD37F0104B3BFABD1381
-:108890007E10D0624F5E2AFEFE9CC1FC4F592AEF2B
-:1088A00086BC5832DEC5EE3727EC5CF1A60223B653
-:1088B00089E55D78EDF85CDF0D785408F50FD9BCDB
-:1088C000D0AF24DC9F5478174AA9CBF4D9EB717F41
-:1088D0006950FA307A8CAAE7F45965A387C0FB4542
-:1088E000E862A387C0EFA5D2C5490F27FE7F95C1D7
-:1088F000E274824EB67C905CE697C4A981FCCBC33F
-:10890000FB312EF2CE3FBF7623F0E9F29FC9C44B74
-:10891000DBBF7BD84FE220BF4A4C053F6BD95119D2
-:10892000E3C2FF174BEE49A70080000000000000E3
-:108930001F8B080000000000000BED7D7B7C54D5F0
-:10894000B5F03E33672633999964F29ACCE4C52496
-:10895000811834E0248480823A218020F43AA008EF
-:108960007AA38E10209827485BDAEA8F09411A1EF5
-:10897000B641E5A1453A2028ADD8061AB9A0A8838A
-:108980003CC4566FA3E5DEA2450D8A82C823A51715
-:108990003FDACF5BBEB5D6DE3B73CE6402DAAFBF43
-:1089A000FBFDF3E59F937D1E7BAFBDDE6BEDB5F761
-:1089B0005CBE0C7FB73076595C196B652C83B1BAFD
-:1089C0005F3B184B67ECC19D09E1C9F970DDF5E922
-:1089D000503684B1734B7A0E65C3FDD02F15DF5628
-:1089E0007C3DD43DF40EB8FFA0CAEE0F9444FB9139
-:1089F000D754A781B1E18C9DD9639B11B633A66C86
-:108A0000DB771FF5DB31DD94A044DFB33A4D342E24
-:108A1000BCE7C7E7A15F28E1414ADFFE186BE1FD33
-:108A2000FD42E1F0ED3685AD08DFB64DE620C0D160
-:108A3000B4EDCF663FC051F5EB1793BA61BCA6DD2C
-:108A400046162966F47799E173632461285D8FE304
-:108A50009531BF5DA960AC11FFF5C2B5B361324B72
-:108A6000826BC7CA3F1B93F07BD327DD96E8F7756F
-:108A7000BF7E7557085053F79BE793BC703DDDB53B
-:108A8000358995507F0F98931953EDAAEE7DECF739
-:108A9000526ADF7E605CC65C709FDF624D1DCBF961
-:108AA000789DDF39C9103E06FD48B8617EA7F11FE9
-:108AB0000F63239D8EF4CFAF83FF47B011978D7066
-:108AC000DD96C6D80D7DF114C55788D3F3C58B1B31
-:108AD00043809F333BBFDC88F0D7FFFD2F1B7F0413
-:108AE000F863AF599D5B61DE4DBFFC8F24A4AFFCE2
-:108AF0006EAA53A1EFCEE5B29007DE3BF77E423877
-:108B000004B7CEBD7A32CF0BF33DB7E3AF2E2FBC07
-:108B1000BFF0D5719938FF852F5565327BFF709C6A
-:108B20005BCC5838410B5798E8E8DD0D9D664273E1
-:108B3000AFB8C6D0637FE7FE3C84F3ECD1045F029C
-:108B4000E209EE2D2A43FA009D86F2F6C380DFC6C5
-:108B5000ED3FFEB371683C3C87B20D6EA4EBA7E31A
-:108B6000114EC622D9CC8DF8ED59E6B4F77DBF97EA
-:108B70005E47809ED77F03BA6D5FCEC7ED00BA25F2
-:108B8000F5A5DB59FC07E8D38474B345E976910574
-:108B90007FEE298476671AD1351EBE22DF005FB5CD
-:108BA0000AEFFF26A7FF874E949F9DB65E7A4D463B
-:108BB0007ABD78318F01BD4F997AEE63E58CF5BCB3
-:108BC0009AE0DC0CF71F7CF58F2427E75E7AD78CC0
-:108BD00074843FBB02F33AC77AFFBA709E8D8A98BD
-:108BE000E716472421298AF7C6F09409DE24BA7FC4
-:108BF0009CEE8739FF22FEB2913EE17D772A71E833
-:108C0000D1E12CA079B07006CDBB61CB9FCCC83729
-:108C1000924E481F6524D2EBF878BC2FE924E71D5B
-:108C2000DB9F13F1304243B72D5C0EFBD2B5C7CCAE
-:108C30000AE3D10BE0C5EF105E689FDB94A02AC960
-:108C4000FC7E0ECCE39C89CDE84038C2CA1FE3D13C
-:108C500097B125349F1762E552CCEF6A727935B827
-:108C6000FF51BC3CE37452FF123F67BE8EAF9F0FB3
-:108C7000A19C03FCBBEDC183C83F8C59C227A09FB8
-:108C8000FB99C2920BA37893F09E5119E9DD33BF93
-:108C900034864330FF651DFB49CFC6CA37CCCBDFD6
-:108CA0001167BC3F8AF11A77EF1B8A7AE8CC1B7BED
-:108CB00088FF1AB71F3787A09F43DB7E63EE2E899C
-:108CC000F23BEAEFB0467F9FF9D5BEA1A46FB1FF9A
-:108CD00038FAE684E8BF69AFBEFFA6ED7FD6F55F40
-:108CE00017EA303BED571FE7B4EA9F8EF33DDD6591
-:108CF00062A8FF4E77182784E38CFB96B05F124F73
-:108D0000CBDE35931D2B7F2F319C00785AF8EE84F3
-:108D10003F25A7E3D5EC05D4B2CE16CE579D8FF8EC
-:108D2000B3912E9DEFDE63447BB20BF1784DB4DF3F
-:108D30008A23CD550E90DB8A63817264AB587D30F7
-:108D4000E2A84107378C9389FA7929F4E3857E9864
-:108D5000EA7307A05F63D2F809088FD169705AE3FC
-:108D6000DA55DE9FC91E604180CB0476DBABE1277C
-:108D7000F7D4A4A12C19A7E731A05E5800EC85FA1E
-:108D8000D96D66C52AC0C70C89BEADD0EF82C1FEC1
-:108D9000D283D05E30DBED0BC173CF1DFCBBB34E75
-:108DA0007BC8703DB6F3C22847B64B46E605D5777B
-:108DB00046797B0E039560137C95DD61233B6353FD
-:108DC000BDEBAAA16DAB557D8051F6993D989B9264
-:108DD00081DF99E93B4F8AA27E8EF34E6249286F6C
-:108DE000B27FF99EEC97A991A1387F66612A03BBF7
-:108DF00092C338DC46319F42D6A5207FB74E49DA70
-:108E00008CED0D8E5AB2FF79AC679F1FE8F66CD2DD
-:108E1000F8C3A8C7E05F03BE97DBACB7EF0316E962
-:108E2000DBF92135467EBD8600F05F619BFE7E7AD0
-:108E300055E5FC013EC6EE4BE99CA082FE4E9F5ECE
-:108E4000B9231B703A69C57BBCFD7C65A907DAFFB5
-:108E5000B1BA61A20A7A24FDF795A579D0BE90FA3D
-:108E60008389F4BC0E907423A8FED54327864AA2BA
-:108E7000729B0160261B499E6F463C9C0D9C598647
-:108E80004F1BA67D658647F817403CE48EE478C802
-:108E9000B11FDBC1E0FD0186EE16E4CB9FBFFABF38
-:108EA00052F03D2F73D27C9D6CA9F3730B4E9E8DB7
-:108EB000BC3CEC4AFA4C659F4B3E3446E520D91544
-:108EC000BC3D05F86AD9CCE275E351D7D6FB88BF23
-:108ED000606427D943F9BE339DE85323E883705A71
-:108EE00080CF66F357582D6B177A68AC13C7514281
-:108EF000F5C6CBD77D7B78664ABE713007DE57EB6F
-:108F0000BD045757867F36E2EBAF1941BACAFBEE74
-:108F10009933BC41C0EFCD2981B9380FCF9C4B7933
-:108F200008FFE41446FD55CDB5FBD1AE5ED80BEA83
-:108F30002F8E5CC9EBE6C5CCA70EEAFFF9D4D4E0CE
-:108F400077B1FF82D7BD3B0F437FD7D7987D5618A7
-:108F5000E2FA45E53E358DF109A1DF21E8E6465A02
-:108F6000A2DC7D8F8551EECE27287E3FB4CF3FE433
-:108F700024BD9C5333F930DAB3F3B6FC8E08DEFF20
-:108F80009197E4113C0005E521776F72C49A44FC87
-:108F9000FC550C3F7FA5E75FFDB8E72F7B77775344
-:108FA0007F4ED11F3844F03C57D0E9BC91FBE5E738
-:108FB000177B090E701FF7A1BDFDA6E33D9922FCAA
-:108FC00024419F47ACFE35480FC0FF3A2DFE7FD6A7
-:108FD0003F1D37E27B4047BAC6D2718EA5390FF5E7
-:108FE000C283818EF1A0B1D9C939DFAB40E69E9230
-:108FF00012DC82EFD7CFE83A6422689A8B506EFB7E
-:10900000D259217DEEDAFB408B09DA4D48276F5F9C
-:109010007A5EBFA894E8A6A16F07F67FFDDE3F1B2E
-:10902000107E49D7750AB703B1DFBF92A28871EBF2
-:109030005B4C80CF0BBBCDE4FFC6BE7730C54BEF9A
-:10904000C9F6504B854F0539CD34B060BC7E0FF664
-:10905000E9D7E24B88037F6F7F4EDE1FE0FF4D2D87
-:10906000FE7FD73FFEFF5DE0FFDFBF25FE8F209D27
-:10907000FBC3BFF4BBEB847EA863ABC8DFFCCC3F73
-:10908000D53510C61F6FB4933CCCDB6A243984F706
-:10909000277B5C517D32EF86E67D38DF79CF28C4AF
-:1090A000B73541AEE7BF9C33F910EAF7D9ED7AFF47
-:1090B00069CE8C9019E19CBB5E7F7F5E38261E6472
-:1090C0001ABD0E7C7126CABF03B8DE7193BD340A87
-:1090D000F9A89A5B928CFED26B26EFEFC91F7FCB6B
-:1090E000C836C7C17F5E6A3ED963D9CE6D06246992
-:1090F000EC3CABB11A505FCA7EC7CE2DC944BF66E7
-:1091000081C37BC5386CC022BD5DCF0F2532AFA6B1
-:10911000DFC2B6545D7B507B96EEFD6BD617E89EA2
-:109120000F0E5FAB7B7EDDB6325D7B48C78DBAF735
-:10913000AFDF3D46D72E8DDCA67B7FD8E1A9BAF6FE
-:10914000F0AE7B74EF8F383A53F7FC86EE0775CF9D
-:10915000479D5AA06BDFD4F343BD1F6360A427591A
-:10916000A2427AF3C0E253152790E1CA95B188CFA5
-:10917000AA91FCDD03F3CD0667125E8B0C4EE08FE7
-:1091800037664F263FE0C07C97DF4BD70A3FC63F8C
-:10919000CC38BA3C18C7CF1DE7FCA2E28466DC2AB3
-:1091A0008B49A7E7C639F5ED61A9227E18C0F9669B
-:1091B00064AA5EBE8CCD9323666866CD1B9889E356
-:1091C000819C8D4AE57246D7ABCA59527305B641A8
-:1091D000CE2A53E3C81913F6B652F0135CFDE632FB
-:1091E000642C07D9653FDEF4D2FD900AF1CA188BD2
-:1091F0002FE720CECBE04B47261C3B237080F72780
-:10920000EC332B367C1BFB2CE5DC6DF086C8AEA561
-:1092100032CA2F3D35BB289969F07B4FAA41E883BC
-:10922000761E473AB70D53251E0BB4F7270C578B04
-:10923000A3F795B9933351EEDCFDE845B3BB70F06D
-:1092400016D0C7664F3E5DE5FD65330C13C271E86D
-:10925000DB90CAE30CE9770D8EFA5D0D88DFB3EE83
-:10926000F7D60E027C3556F790DFE536B4CF3F8453
-:10927000F3FAAD91E7CDC0B342BD305BF8D1B3276F
-:109280003E3EFF10E8A7D9EF0C22FD24C7D9B03825
-:109290003258EB37E4F413576D13F06C5CEC1F5C41
-:1092A0003388E022FD20FDF4BC50C3788C7706B0F3
-:1092B000668A1BD71A586DBC7E968B7E3291E40865
-:1092C000AFD34E727276CEB12415E691E8082E47E0
-:1092D0007E9B797D5705F7C7FCBEA9C03F79917B7E
-:1092E000D7E2FB796E958595BEE3675607DBF261A1
-:1092F0007E4B530D3E3BB57B147C3FE161C6D2E013
-:10930000FDA57F37123C4BDFB88161BC96606F666C
-:10931000E8D7CA79ED4F7D9AF063ECB4911D64E80B
-:109320009202FEBE2B687FD15DD3857EC7C5274DD7
-:1093300034DE4598A313FABFD8690CA3F37E283511
-:10934000316280B6B1CD41F63B0F7D50787F4EA79C
-:1093500023ECCD8FE2455D3F9A45C0DE25E4F0F970
-:109360002F4DB587EDF934EFD5386F09A79C776E8F
-:109370003F71682495DB59E62FD6D1D903315917AF
-:109380008EAD82F30FFD189F34519C383BC54E7053
-:1093900086178706D798FACE6F997BEAED77033C5C
-:1093A000AD478CCC08FD78BBDB091F73001F616FD4
-:1093B0005F7C9FF5E67F653012DC11E447E3FAF14C
-:1093C000342F867E3D7CD7F073853D9D8F7C199C24
-:1093D0004074CE32B0ADF97DE7F1662ACFDF1E4E84
-:1093E00075D2D5EC2EE272E21E38780BF4F736EA2D
-:1093F000290B8BE707FC3E95FBD3748DD54F600797
-:109400004308C785F50AD1F3A412369B006575772A
-:1094100036933F20F593D16F24FF43EA290917E8DB
-:10942000B10F5235F6D198FCF050ECB77F7F6DC785
-:109430003E33FA6B4E46FE9AD4A3FDF96BE8A721A2
-:10944000FF493FED54CC3C617E5F8AF97D196F7E08
-:109450007DF4EF3DCDD2CFF973EA15FCCC0C737CD3
-:10946000FD744D1AA74393D3CC283F85F132FA0FF0
-:10947000F30CE1CD988752C3D6291AFC64A5493F65
-:109480008FFB1BFDE9BDABC525052B4B48FF5EE8F7
-:10949000F226A7C235FD53A5395E3FC6452F0C43C2
-:1094A0003ACDB356DAD2004E679A1E5F4F2DEF6366
-:1094B000BFD2D238FEE8DA077F76C09F41E727EEB9
-:1094C0002AF212FE3C6957F013CFDEF15105DAA5FE
-:1094D00073024F8DBD712FD7D35960AC30AFD5C05B
-:1094E000FCCF9E28E6EDCB0AAD7A50BE6EA33D3090
-:1094F00008FB6FDA3DF159ADFDFE3A95E7D3983D93
-:1095000095F2ADB23F97D0FB1067DFFC9997F4FF5F
-:109510005748DF68BCDD5D81F156EB4BD724A37F54
-:109520003676D7DD4EBC5E481F48783DBB2BC18FD9
-:10953000709E4D057D6CC7F688439887F872F1E1FF
-:10954000542D5DCEFEEADD0A13F47376E7BB152ACF
-:10955000E63344BEA6D71E5DFE434500BE0F8D61B7
-:10956000C5CD760D9F58B8BD78D2CAF31D192EF31C
-:1095700032763DC4231929F4FD1A97E12778DF6874
-:10958000F943DE0994B398FCCE93266FAB1DF80C1B
-:1095900062391FAE132C18ECF7CCC6FCCE1437E59D
-:1095A000655A15AE4743B3791C9A5EC08AF3A13F52
-:1095B00093C168C4EF7A3CCCB7195E4938D01E41DC
-:1095C000B597D8D5E147F0CB1353099FA3CE3815F3
-:1095D0008C27643E48ADE2FDF54C3387376BF24093
-:1095E000EE192AD9459BDAC1504F3F90914AF0CBF2
-:1095F0007C50D5D419814A84EB5103C533A078152A
-:10960000D487D9621EF99E9DCBA56FA3BA902D1960
-:10961000267FD84AE0FF8180E724AFC18FF9D7A425
-:109620009CC85113F877D94B19FB44E347DACC4275
-:10963000DEDE3192BC39BEBEC53203FC235B22CFD5
-:10964000AB260596CDC7BC38DEFFD732A40BFF9EF4
-:10965000E863C434150B2503C88E91FA7E25FD3AC4
-:10966000175B7C0381A1772E76D2F5B9C56E82EBAC
-:10967000F1C55EBAFE747131DDEF4F4EAF767D6C91
-:10968000318CABE1A7F4118015986FBA91913C3FF2
-:1096900036BC2279661C7F405E9F5E7CD835769012
-:1096A0004020D023ABDEB969453ED119850866F765
-:1096B000CE72FF68C61E35F9E73360ADD5695F8F9E
-:1096C000C5BCD54AC54079AAC7D3DE5C1ECAC1ABAA
-:1096D00097E86EDBFF3EC37CA7A7BC5D4179F7D45A
-:1096E000B7131F947775B1A0B8EF87B6E708BFFF2F
-:1096F000A895E379156313105EBBC202783D67E558
-:10970000FEE0E756AE1FBF10D72169C18D28C7FF05
-:10971000E53C5AF42880672DF9200FD73B6CFBFFFE
-:109720004AF960E350B305E5C3B3F738AD83180DCC
-:10973000DD660626F9F5273EA6FC9AD11CC8E7EDA2
-:109740009756603B2329B0095D3616FA78E2013757
-:10975000C80DF2C38D848D10CAF14AAB68878E1193
-:109760001E569A78FBF527FE44F35E690ACC43BC8B
-:10977000607B29F4B732A5C36D80B6BDE5FDE587F2
-:109780006FC2B67CFFFDE521F8FEE534A96F021E2D
-:10979000D41FBD6D27B48768DA2A6F330BBFCAF9AF
-:1097A00035ECFFEBA16CE0D7C6BD4A0782E6D9BB1A
-:1097B0005AC1797A76AF267CD31FC8074E83F2A4AC
-:1097C000969019BF7F6EF161E752A0B39ADAE64234
-:1097D000BC5FE30EFAFDF1F21319D2FF85F7B579FC
-:1097E000B6B0A9A75BE38F7B18971BB614F4431C94
-:1097F000FF626846E517E9D0CF934A708511F5CC32
-:109800008B2627EA11D6C5F5D019D1170B67917FA2
-:10981000536FE54DD392E08AC1A827EE557D183FDE
-:10982000D7E5B757A27DAFDB93EF6B61517EA94BB4
-:10983000E9709521FFA4E8DBAD22EF9299D29C92CA
-:109840005282EB11ABF370BDA091B5DFF74384F703
-:109850006D23433FFD8B7D37248F827603B4D16F18
-:1098600068E87CD78CFCF9443AD79F8D9DC03FD0E7
-:10987000CF2A902F3F38329B546722EAA7E7FCCDCE
-:10988000D7A28BF7F5137F9B6805FA3E5FE077223E
-:10989000BDDDE9A61516701A9F373B07B3526CDB86
-:1098A00089BFEA4A0D5C8E98FDB77E55AC7F42FBBE
-:1098B000F813136FD3E6773DB82E03786EDA600F96
-:1098C0001992C9DEFC6FB4B78DEB0D21D45F064B46
-:1098D0009719E9EBC6B55DA28F93F0B650EAF3187D
-:1098E0007DBD7062EA6DD85EF86881337485FC6571
-:1098F000ED251B0B6BFCA327D2B91CD7AA215A4715
-:10990000A9BD9444CFFF79E3595978D895C6B3D30C
-:1099100073395E7D743CA2EBFEB2DFAE1D08745B52
-:10992000B8C36448D0F0DDC21D62BDDAEACFC47EA0
-:1099300032CC4CE01DFC7DC0AF9ADFDB0EA920E7E6
-:109940008FF5CAF98015634723DDA2CFD9489D1E44
-:10995000F063BCF958A2D403D7C47F3F31E6FD02BF
-:10996000D9F6AD189BD3179E8CC468DB02EFABFF12
-:109970009DD0DB46F8561B62FA4B95E38FA4FE247C
-:109980005F1D4FABFC6D68203C4F69AFC4FA8D9EE4
-:10999000D9CC8B7619F9D5A7D1FBC7D3B85CD75EE4
-:1099A0002AD4D13B8AF722DDFD938BDDBA75BFB98E
-:1099B000D50B697DF238EA79EC878528AEAADD906F
-:1099C000CDC21A7FEAFFC3F18FC231AA1F386EFEE3
-:1099D0001F86235F279F513806EAEEFFA3706CBEF7
-:1099E000ABE8B67C78658D12B214A05D78C440797E
-:1099F0001363CA586F0BAE3F3CA2929F872E09D6C5
-:109A00007F14A8ECB05A86F2D3EEC7389F2DE1F947
-:109A100023B8DF662A233B447E70E1DE8407D04F03
-:109A20002BA8F5CFC32BCB29A1F50DB92EC8441E09
-:109A30004CAE670C72B24A159CB751190F909D2A13
-:109A40000854D7A13367749427A27D5C630887709C
-:109A5000BCD0E37CBC0C43B8C382BA3769A013ED19
-:109A60005D4612D77F6C4509D9BFCD86826BE7036F
-:109A70001C8F2A95896F219E530A28FF8BF717C0E8
-:109A8000FDCDC26E19537C4EB4539B85DD6A15FA29
-:109A90005DDEB7A5061E407FE254FAC2DB2C37A07C
-:109AA0001EF2B7A581BD3999BE7085DB83F6C65B12
-:109AB0006001FB72F2C987C8DE6C6EF1663953A291
-:109AC000ED41FF0DD69AF4C4432BD05F596A5FF085
-:109AD00020FA3BF0FCB716D0B3CFA70ABD239E17E0
-:109AE000F4EA29D04BA0C78C2DBDED10EAA5825E0B
-:109AF000BDF310E99D2D1B8DD47E07C643FF07E6FD
-:109B00001132E27C07A9E4D75B019644685B071732
-:109B1000D03A11CC9B25A27F3D983F97F97CF3204A
-:109B200003E5F3F17DC4A3D5C3DF374F613E5CD7B6
-:109B3000323BEC1487C8F501A358A74A14751A8A5A
-:109B4000730AC5779655650B301EB30CD4AFC39A14
-:109B500063EA398CB1F51DF608F95F5FA48BBC7E12
-:109B60001A735F2E8CDE07BD5D8657D7DD4B2B1138
-:109B7000DE050EE634625E2518A175CE58BB66017F
-:109B80003BEAD5C887C5CEFCF1EA090E65703FD621
-:109B90007E49A5F8E64905FC1BB4A30ECE67D23F6B
-:109BA000323925DFEAEDAEF4974C297C2E0B278E57
-:109BB000C9C4F8DD68F75BD0CFD9E72CA3BC80918E
-:109BC000F96EAFD4F83B4B231329FFA63AFDE48787
-:109BD000178A38D1E8F431AD9FB36C310496D73091
-:109BE000F66C45D1189487A7AD114B21D2778D81A2
-:109BF000E2BDFD650F8614CCBF2D6224A7CF56B8F9
-:109C0000C6601E7D931A48BE17E5E5088CE7E5742B
-:109C1000E3EBB9AD0AE68B2F5A02C9A80F1E43BE6B
-:109C2000D7E0E5D7021F7F4FE7FAE75113978B651F
-:109C3000004F04E0502F5D47F9ADD5193CEF61AE00
-:109C40001E4BF91F33E003F37B09AC39E4A4F9F2AE
-:109C50007C5D82DBA0AB0B542F0DA5EFFF9E6ED079
-:109C6000C5D56D304FAF467F595988F27588E3AD41
-:109C700071FC977732783C62017FC84BFE49CC3A41
-:109C8000775FFF88FC15499F5E3F4501FFE40AF1BD
-:109C90005813C4CB5A7DDFA4F690FE6D827818EF7E
-:109CA0009F735AC83F94750F76A1CF96B983EDA3E1
-:109CB00090CF139386621E40651D84945558F7809B
-:109CC000FAD0ADF6F4F23FC87CAB356933BEB75479
-:109CD000D441D87C7AF94964ED113FCA67B1466E28
-:109CE00018E23B44FD2678F5F7190B328C33547794
-:109CF0006C9D44A8B71E8AEAF954F614AE5F4BBFB8
-:109D0000375BD4239DB57D447934F07B2BD3681D1C
-:109D1000A087E21699EFF9B67E7221F68179844523
-:109D20007FA938817236657C3EDEB7A99C4FC0158D
-:109D30005713CA30BC1A3F2F05E67FB7B07FE9C67C
-:109D400076AA1B795DC4B3FFE59CE1A1380AF0490E
-:109D5000F53689BE6E8A17859F66ECD58F1F2FF763
-:109D6000EBFDCE90D6CF5BB9E6E3E54B79BC42ED97
-:109D7000D79F8890FE7CD42ADBAF501BEC5C04E3B9
-:109D800025B62BC18B7C08DFFB51DED85D45E4672F
-:109D90001B0B5816E2636C9285F4A67157C266F4E9
-:109DA00083212E7E394DB35E7CD671340FFDE138B0
-:109DB000FD8574FDE57DBBFE60FC4EACC791CFC751
-:109DC00026AD8F18F9775EFC8EE5747D1482FED780
-:109DD000BC94C056000A9F36E9E55D5E370B7946B4
-:109DE0007DA3AD873457D7F891A9A55C27B813593F
-:109DF00044C34F52CED54B835944232785197C5DEC
-:109E00005555FD9447522F95D0F3BFA34CD338CE70
-:109E1000AB8C93DACF38C3487FF43F4E85D02F4CBC
-:109E2000AC5FA9545723F5427F721EBB4E16AB1789
-:109E3000E555EAC5CC0CDEFFBE0C7DFEF5C1F51D77
-:109E40008790854EDB830732A83EEA58129AF07A53
-:109E5000436428F2F1677DEF37E2E4DE4EE379FFF9
-:109E6000A26DF3DF4076EDCA085E443FE8B71962A1
-:109E70007DD20DF6D088F60EEC4509E5732FA6636A
-:109E80003E37E85D378EA13CDD45F9DC6457A00420
-:109E9000FB5F36B582720E12EE958B799D9AD4B324
-:109EA000763548F8B2A8217E7506C186337621C37F
-:109EB000344955109F5C8E8EAEB940726055FDC41A
-:109EC0005756A7C18B7E8115E242D4BB2D4E035F4E
-:109ED000BF715B28FFBF4C810811F4C68294822BAE
-:109EE000AE8F9B2FB9C8DE02246EADDEFEE78F93E6
-:109EF0002EEC837E1CD5C9FD06B69FDB6144C2A74C
-:109F00001A7D2CFD81D8EF62FB97F894F8B5205E9E
-:109F10004BC81EC6F537AC2EFD7A66A6D4B71947D6
-:109F20008B2270B741E94E42BF06F4A8D5857A7AF4
-:109F3000484F92C14BFAD7C5FDA090E06B66D7F2AF
-:109F4000B5CC53CB7949F817BC35DBA25D7F898549
-:109F500037D6CEDA4BF4750B56AFBE6E41EE0B30F2
-:109F6000AA01E21BD368BF05E5A4C559E6443F67D3
-:109F7000A9EAFDA39FEA2D4CE46F83FFAE1B5F5E51
-:109F80001F03F947384A5D065D5D8DBC3A701D259B
-:109F9000CE77535C5C4F3DB6EF6ED2C3AA8FAF3322
-:109FA000C5D28FB176E21747117352FE54C09B742D
-:109FB000957EFBE3A39FECB3929FAC8EB484B1AECD
-:109FC00033763CA329E05750EF9632F2938DB97C5B
-:109FD0007CE3204675E049E5A9AC5883C765EEA946
-:109FE000F47C41869321BD8D0E43201EBF483C0D5D
-:109FF0007419747CE3967CE3F9A008E540C33781CB
-:10A00000787C33D0C5F515C2A1A5EF327741663C07
-:10A01000FA44F522E7ABABF1C54C1BF7733ACD5CC4
-:10A020006F36208E205EAACF302FC3FCF7190B7F2E
-:10A03000CEFCC5DC2FB3709E9B69CB0BA33FD4A98C
-:10A04000FA6DE897CDEC5DB7F5D37E8F7AAB3FF92B
-:10A0500006B48FEF72BFF964A5BD4D817E4E9AFCA8
-:10A06000C988EF93EF1A95165A07E7F573B20EE910
-:10A07000A4C9BBF25A783EEB67467F0B3DD6FB8303
-:10A0800067987FD83BE81FEF36D27A4BFEE30F1874
-:10A0900087C0FB35E028223FCDACB287D00E777E5B
-:10A0A000D0FC11EAA3591B13BC4BB08E65FDB0AFB9
-:10A0B000B0FDF92A873781F26C058A07F35FABF3AD
-:10A0C0009DB46EB2888978EECE4955A0437F89430E
-:10A0D000CBFC35CCF973269F87568E85795E9BD154
-:10A0E00069B0034CCABAD04A0BD0EFD196801BE3BB
-:10A0F000C70ED7F495183FBA5CFEAE5B205E3CE11C
-:10A10000BA7B12B63B9F96FDDDB3D20F7AF91543A9
-:10A11000305F81E7B6CC872651FD6AA1EC7F193DFF
-:10A120009FF9F36BBE3A0AFD97AE5B3F09736E155C
-:10A13000D5E2FBD03304DFECD1B2BDD9563510BE29
-:10A14000B7315D1ECD148D47294FD7D9EB5F3D3711
-:10A1500009E3CF59639AAB54E87FC9BAED2B4B4062
-:10A160004446B4573AFDD0FEF1BA3726D980DF3ADB
-:10A1700099BF0EE3DD95EB0E4CB2DC04FDA7E9FBC5
-:10A180004F378A7C6CE8F04ACCE3F5C2C7DE5FE962
-:10A190001F187D7F983B61552827CAFFFF22F81FB3
-:10A1A000F8FD572E5C07B4741FC2145DDEA21E3387
-:10A1B000AF7B15F52939DD4379DD8D681777F33AE3
-:10A1C00065D976F376E792F8F6FECF6E2E779D8905
-:10A1D000F19F7F24F439C0EDC7FA95E4A3CCBF3DCD
-:10A1E0008E3C1D74D949FE0E82BF67498DCAD5EDDC
-:10A1F00020DB23B1FEC7C2E194FDC47E7F4CE8277B
-:10A2000016BA3D15F978B2E0F3429FC2EB7876DBDF
-:10A21000C283D0DF6311F50E98CF3691CFD8666533
-:10A22000F74F81A15D892CB803FDCF346897D0F733
-:10A23000FE1DF6687F6F735166E30A035BB0BF7162
-:10A24000999ED2D6FC683F00F7524B990E6E75640A
-:10A250002A3E0F65CD2FD1E0B384CF03F884F005FB
-:10A26000C3BC700BC84B67D7B5052B600A2B5D5E6E
-:10A270005DDC57D13595F6A5FCA79BFB3FCCCBBF4A
-:10A28000CFA8E275213D7B6C94A76096AE22A49383
-:10A29000FCEE92C047D58F27AFC3F7EABB4C8CEAE0
-:10A2A000FF77545ED11FA8C7BC9EC67FAC5723144E
-:10A2B000CFD5635E6F18F6F7B619ED18F6E315F90A
-:10A2C0006BCCCB65B4C6A7BFB487F5975258685816
-:10A2D0005FBD19ED3F9D9E5F6D5ED1FEF47167DF3E
-:10A2E000FECC621D40E05D157837C7877340A6E05D
-:10A2F00053C0B741C35FB305BF81F6243FE0DCAE76
-:10A30000C19B57E46BC7E5FB6E403FBF700BEACBC8
-:10A31000AE448A5B2A54FF247CBFA22B95D6172417
-:10A320007F48BE9074ED4C6DA67C4DCF530AD9C1C9
-:10A3300058B88A245CEB158223B33A687C40039FAB
-:10A340009407E8BF53F45F3E92E4E7192E0F2037DD
-:10A35000F7A2FCE27A25CEC3D73D74EA90BEF0FFA7
-:10A3600014EDDF70A223C7FF4B5651CFC1F1D617B2
-:10A37000FFD957A1671E3DAFE87A83E659DF8FDC2E
-:10A38000BEED4E2238338F4692BCF0DE1382FF3B87
-:10A390003B3E4D1A8572B1DBC8142F9F37EAAD0AD8
-:10A3A000A98FD99CB7C780FECBEC6D83BEF4221D6C
-:10A3B0007AF567C46289BEFFAA7BCEE4A5F02C3D86
-:10A3C00081CB6BBA11AC4D59148E6999DCCF1A1937
-:10A3D0008CEF97BEE776D07389EFA71655B14F6122
-:10A3E0007E3F73F1F5CF91DD2105E922E53A564F25
-:10A3F0002DCCE4F2383FF3FF919EB25E454F59A554
-:10A400009EE2F70F427084EFB95CDD4315F09F6B5D
-:10A410000C7E17C66127DEFD21EDE3982BEA5686F8
-:10A4200060DD0ADACDA301B22B5FE0435EBFF20824
-:10A43000C680B3DBF5F52B6C0BDF271ACB57513EEB
-:10A440000A09FF5DC021ECC1ED09DDBFE245C67A16
-:10A4500079966D80B3D150A8796EE7764BD201E83A
-:10A46000BD94A546E5F8935D999B50DF0E73F3BC50
-:10A47000627AA1BF14E72FE512ECAAE013C3FD53E3
-:10A48000ED5C6F4C8DC3BFCF08F99CBD9EF34DE7CB
-:10A49000DFAA2621DE3BDF4B4D59A2D1135B851D80
-:10A4A00094FD4A3D24BF93CF9F15FCB12D3389DA2B
-:10A4B0005B5D0E91E731C4DD37B755635F897FDAA5
-:10A4C00038FFC07C435AFE1EE65674F6B5D7AE0A76
-:10A4D0003C379801BF80BF6DA65016D6ED54741955
-:10A4E000A8BF9ADD0EAA07ACE9E078AC69DF67A8DF
-:10A4F000D3E027B6BFFFC8E4FEC02603AF233A6807
-:10A50000007E43BCDB397CE77679487F1E16EF5D21
-:10A51000DD6E7C333DB3C9CCEB4881BE54CFD7F060
-:10A5200072F626BD9E6E11F80FB6E23EB6F475CCFB
-:10A5300087B55680A78802704F770BBD63F69B7175
-:10A54000DF6ACF538CD6F30755FB4BBDD06E0AD8CC
-:10A55000CB14E8AFA89DEBE18A27C18F41B9B3487E
-:10A56000BBF0D676ED78C7321D221EE1FC5CB39EAF
-:10A57000E36F10F83F2FE015FAF915F9F11C9E4F23
-:10A58000D6768CC2FC93FCFE0B41FFABC15781F029
-:10A590009547E1C3FE919F983DB004FB6DFCC3CE8F
-:10A5A0006C6DBF5F65727D9B6E9C39C68A7A7E3505
-:10A5B000D81D92CEE07EDC9750B337C5B982913C6E
-:10A5C0001B30EE91E3D6883C24C85DC514985A51DF
-:10A5D000EF3892AEEFBFA89DBFEAE6FEDC3F8BBE30
-:10A5E0009DE620CDA76707C0EB8DE2A5B3E38125EB
-:10A5F00056B41347990FED84847750757712D69D22
-:10A600003409FB01F33560FC92FE332F6B45BC75BA
-:10A610008D3163FC14CBD7924EC58CCB8F8CD38AF3
-:10A62000718100DAB9EEA142FF308A773F79F9D51E
-:10A630001756507CC5E9D254CDE958E90E4E7767DC
-:10A6400044E510F47905EAAB9A277BF55107BFDFA3
-:10A6500095570DF8BCDE2DE55C4F97F4408715D774
-:10A6600035245F9FDD3324BC82D399C6EFEC708420
-:10A670001505F7A136B760DC2DF504C2A3ADC39470
-:10A68000F0F4D291011D8744EF0FAAE6FD3581BC9D
-:10A69000231FD51B9B158F427A80F2AC99A807A087
-:10A6A0009DD9C1DF637BF9B908124FF5D3A1538857
-:10A6B0003BFDEE129A87C4576675C4500FB72658F3
-:10A6C000AAFC2734FEDA61B1DE8078994AF106D718
-:10A6D000D7F5C6400EC6AD2C3381F671821D22FD22
-:10A6E00072D0CA542BF4F7265CD12E8D33CEA77DC1
-:10A6F00034E30A159263D00032EF13417FFAF65B20
-:10A700006C24FFECEB8706E23C336C9C0FA11F8BA3
-:10A71000E8C7427650D883DFE7815FA744F5F2416E
-:10A7200045A17E0EDE74DD66AA2D147C89FDA1FF95
-:10A730007450999243F6B23343141771F8FBB7671C
-:10A74000DD79F85C1B2F627C178D374B57DD0A3C97
-:10A7500035624247C4E044E9289FFC7D807F1CC4E9
-:10A760009B5698FF0382AF0FE6878C4908D7209845
-:10A7700037DC3A94182C69B647C77189FC8D4BD4E5
-:10A78000EFA2BF80578387EBFF9F78B8BDF8505C7E
-:10A790005D49F1F33D17C5F38FED5C4FAFA88CBF5A
-:10A7A0006FFB11615764DC79BB58EF80B8F3113748
-:10A7B0008F3B45FD295F1F01FF9EF05BF5E36A5A61
-:10A7C000F7BBD8352D999F87C0F5C12C51FF79FF74
-:10A7D00023D37E8A7C7602EBCC010F9F0A7E39E17F
-:10A7E000F427619D544362FC3AE267053C0D020F79
-:10A7F0002717F3F30B66E1BA1CF0DF1A37F7F3E61D
-:10A80000B60F1B8F749FBB4AA17539B9FE2FE95C47
-:10A81000BBC1A8CBAFCFC275B9B47F249E2AED27A8
-:10A820009E2AD7C55372DCD8B8EA93C56EDD3AC00C
-:10A83000CCF642717E047F7F16F311DCB3DAB27579
-:10A84000EB88AC2DE31BEDFBC7382A14173EB3EEA3
-:10A85000FE278B2D2CA485E3D440AA9F78C41D7CB1
-:10A86000C5AD83C3C642BA7CE86827ED27B2F23C87
-:10A870002CF8E33C8E81EB263BF9EB13D09FEDCD1A
-:10A8800087811E7126A35EAADCEF1E1E8D1FA49C6D
-:10A89000D58F8E1F47AC117ED01A178F93938FCA16
-:10A8A000B83AD18BFA51FAE5B1DFBDD7CBBF7ABF49
-:10A8B000F26A7908E0E390364E8AEDF794FB1F8D3B
-:10A8C000BF0BFBE197A2FF91F8BB627490F27CACE6
-:10A8D0005DA19A961163F5F1D0D768D787E3D5A625
-:10A8E0008B876AAAF5EF310FB7FFCC63D3F9F1FD7F
-:10A8F000E153EBC72B85A807797F8D822FF24FBFDD
-:10A9000047F5A4A33DDC2FF265F9133C705D25EA01
-:10A91000C95759F97EFE4DFFBDDF3D0BFDA3774CB6
-:10A92000B4FECF7673BEA97C66612B9E0F60EF509C
-:10A930009CDAFDABDF59A4F86B40AED3847EACF754
-:10A94000F1F9D4FB22E68176AC2FE670E474EC5387
-:10A95000540DDFE5D4F2F7723D265D5E3C5FB4072F
-:10A96000789C328ED937311DDFF7ABE81764752834
-:10A97000643FB39A19F9D559E50AF5FF9DF24DCA1E
-:10A98000AC92E87CDB0C534A9CF05D9BCBE643FB2E
-:10A99000F3C3ACE0351E84EF582482E672C4B12EB6
-:10A9A00015E3AD5559FE62C4839CA7D7E8CC423F5E
-:10A9B000DE768CC3D7DE9B67E2F687B195C22FDDCA
-:10A9C000CCFD33233BCCB87F4E76DEB5A498ECA00B
-:10A9D0009C8F2B55D811170BEEB4D3FB6DE4B758F1
-:10A9E000B81FE05A5244FEBCA46B34EE1C5C867166
-:10A9F00067E1AA883A13BE7B798321EE7915E305D6
-:10AA0000DE611E95DA795C4D6FC9F74CFDE41D25BA
-:10AA1000DFDB26C48FE7C112D2F3CA67D2EF21F978
-:10AA20005C6A6698AF96F85F9515B813E1C9EAD8E5
-:10AA3000A4206E3E11750A9F24F27CFC272B5E50E9
-:10AA4000D0BF7C681E731A59FF70D72F32FA6BB4CF
-:10AA5000F2BCD44C7491F14A141E9E8769F070FBCD
-:10AA6000B42F2B5083E337EE5E4D71F5BC2DC7CD6F
-:10AA7000575C87F88678536AB9BF5E3FC342F54C8E
-:10AA800095CFA844F7BAA5665A37ACDFBE83F6A7C0
-:10AA9000B187990FE5BFBE63875203E3D66DDFA18F
-:10AAA000CCD6E031BB3E4CF5DBD738E47A4484FCAD
-:10AAB000E958FEC63C02FA2F87AC5CFECF54DA435D
-:10AAC000B83E71C614ACC7F7CE786C3E5CC79478BC
-:10AAD0007F73C7AD745E8063674204AF6D86CD6ED1
-:10AAE0000BBCD776ADD987FCB42A2BB81CF192AA3F
-:10AAF000063AF1FB9474870FD737BC09AC8CECF79E
-:10AB000037C4C38818BE18F130979757847E813FA9
-:10AB1000AAA77AD6C3FD725C5E427D75C8C4E7B150
-:10AB20009371780D1EFF7A944B763895C6CDAA8F17
-:10AB300028587F113B6E94AFFC1B3D19DF06CE0EEB
-:10AB400033EAF93AA16F2A9FD9A27CAA81FB458FEB
-:10AB500091E0CBDABE49C1FC193C277D03EF33AC51
-:10AB600077CADACEE3D53A783E5BA35FE43CE2E80D
-:10AB7000994E84CF7EACEB00D73311BE5E20E08DC2
-:10AB8000A567C4E3A5F1C783BB40F7CDA1628C974D
-:10AB90000F1524527F52EE63E534E2E17E65D686DE
-:10ABA0002D8AC14EEB2AE45F4AF8E47BBEAC310744
-:10ABB0003C84872EC243C30695E633CE1C18385F0B
-:10ABC000230FEF89FEDE98FE119DABF3E4BFBD4B72
-:10ABD000FCD8007136C519EDEF9AA7A19D09FDC2F9
-:10ABE00088EB6093B88BC2D68A73A72675723DDC5A
-:10ABF000D0B9439D658FF269FEE937E8BCAA868E1D
-:10AC00000486F115F0DF518427964FBF293D411F7F
-:10AC1000F1F829641679BE603EC63F524F1B84FC92
-:10AC2000333BBF7F41B4A3FC133CEDD1E9592BC9A1
-:10AC300045FEE9B237B0DEB3C1A7D0791D129EF44C
-:10AC4000AAF87EBBD48F526F633E31A0D1EF1705B7
-:10AC50005DA11DE1712A2B403B2DE18CA5D3802CF9
-:10AC6000AEC7E3F0D3DF11DE58BB25ED79FEC69DFC
-:10AC70002AEEBF917C3209E9ABE113479699E07067
-:10AC800064A9D4FFDA4ABEEEB8D6C4EDD5DA160B05
-:10AC9000D561BE7937AF0B73DC638EE0F5A06166DA
-:10ACA0003D3E3F98C5E168332CA1FD68207F49599E
-:10ACB00019C827498CEB41AEF79EFC0DD75BF521F7
-:10ACC0003BC5B9F5C13B6B68DD3FDDEAC37A591678
-:10ACD0003C609EE688E235968FBC3BF799711E93E7
-:10ACE0003AB8BC81DE243E8AE22FAC9313290F864A
-:10ACF0005E3F2198CFFD201E479588FD81B5161F28
-:10AD0000ED2FAC15F9D612B14FB0E2A89FECC14CB3
-:10AD100041878DF6C0755998A75915936FFD8671B7
-:10AD200040DDA2DF51DCF5A0FB2DBA4A79847855CD
-:10AD300027B73766713F3B5F5C2BB3389FD495775D
-:10AD400090BCD59D682639B54FE0FACA7E2CC62F37
-:10AD5000648F09BE5B45E38EB3758CC7F5E2713F26
-:10AD6000579CADAC7F38E7E23E2B8CE736EC4F7A50
-:10AD700000E5F96B882634FB70A666713939B30D8E
-:10AD8000104EF6A8D97C253FFB6AFDB1C81185CECF
-:10AD9000F910B83CB3BDEA86CF707D675BB20FF7A0
-:10ADA000D37FB9FD8E1F7C06709FD9728B0FED7F0C
-:10ADB0007A6B80F8A527C3EADBCCF3AF13303FD51D
-:10ADC000D2B13F09F7ED7CF1C2F565A88FE7657157
-:10ADD0003D75FA37C645889725CFFFFA667C5E1722
-:10ADE00056D2D02F3DB3EDE77FCF827E6AB734E1F4
-:10ADF0000962ACF585D7C9DF378437F1FBDB92C92F
-:10AE00007FFDE2D9D53723BE5B3B5AE9F9E96737C5
-:10AE100051FB8DE77FFDDADFE0BDFA4012ED673EC2
-:10AE2000FD9B7D4497FAA04A75E7BD7C1CAB077774
-:10AE3000ECE37A10ED37F2FD0CAE9F241F4BFEFDC4
-:10AE4000E2F9FB6FD0DA0379BF4DE469DA12B97D1C
-:10AE5000F852C869DD187B1B5EBF7CD14AE76E36AD
-:10AE60009ABB8B307EAF2FE17CF17D818FFA8EF91A
-:10AE7000A6463B7D4FFDFC27303D5E87007F627D0F
-:10AE800017BCB5E532D529FD8AEB99443612F33863
-:10AE9000D3AB8FF37D9B25CDA63A82F305FE1C66CE
-:10AEA000AD7D5EB1307EDCB83ACBAECBD366754EAD
-:10AEB000C9F192DC27F80669FCDAACDA60AB03EE84
-:10AEC000DFB630E8C37DEF2F9F7A6F3CEE4F78BE40
-:10AED000581946F4372ADC7E85EC344E03AE0F4118
-:10AEE0005CF1AC9013084BD36F84F98C53593A6ED4
-:10AEF000DD1DC7D81113E985ADF41CFC17F2CBBCDE
-:10AF0000AF4FDF8AFECC5A53D0331CFB6913766FE8
-:10AF10000B871FBE77DACBA83FE78DDC0F5F80DFA2
-:10AF20009D6F999C8E7E3BF4DB65D2C459C09179AC
-:10AF300068F7B0BF72C4D384D00CB23F5E33CD4F3C
-:10AF40009EE709F31F7AEF90A87CC6E691503F6117
-:10AF5000DE775F56E55ED433F2EAEA270FC3B2F933
-:10AF6000737FB69FAEDFF47CD037A69FE3F6FB95E8
-:10AF7000E3C4B78DC8B7387EF084CE7ECF927CBB59
-:10AF8000E738F1EDACDDDC7E37EE2E3523BF7EB940
-:10AF9000D8CF3E0507B651F0DF5AA57B0EEDFFDA9C
-:10AFA00063A57D7DE7247FAE3AFE39D69B16ECF68D
-:10AFB000509EE0DC1ECEA7070D068AEF0F6EBE6E18
-:10AFC00053ABD2D76E821F4D72D2D8CC841FBDF046
-:10AFD0003DF4BB1A6A799D79630C1FE56FFC641917
-:10AFE000F24B0A78BD583F037ECA78DA1759CF86EC
-:10AFF000A39C668DF5EFC9A6F53F1E7767D5823E07
-:10B0000081F66DE9F37C789455CA58F07791FFD2B8
-:10B010006FF2613E6C6D6EC732F48B43E3189D9BFB
-:10B02000BAD6D43E06E3DBB5E3BC4EC024E06D0BDC
-:10B03000F9CDACD82CEC570DF9DB8DEE7FF551BE78
-:10B040003A56FEF7B490DFD6E84DF4E139B6937680
-:10B050002B0BB89F6267087F23E017DB93C2A3C264
-:10B0600008CF59813F89C773A62E3A4FF7DC4B09A9
-:10B07000743EE1A4B19C5F53C67690FE7873CFAD69
-:10B08000649F255F3A7625909D4E559D0AE62F18C0
-:10B09000BB23414BD77651879B22EC48E12A4EDFF8
-:10B0A000C46CEE6724661BC4D52CF85C9EB712A254
-:10B0B0007CC259417FFCF36ACE6B6AA889903CD56B
-:10B0C0006FE7FDA527F84B1FD2F0AFF497E47A2B7A
-:10B0D000AEBF4E89C3DF3E0147FEC60544F759B5F2
-:10B0E000E23C8755DC8F60C0178837A023F1C16D23
-:10B0F000E973896EB35629F7101D431594D7947ED2
-:10B10000576CFFE5D95C2F6EB306CAB18EAF27C36B
-:10B11000E1C3FA806D297E03AD0F94A6507E2323F0
-:10B120008DFB8119C20F8CCA7DA0DC00E39C7239B3
-:10B1300038BDC3BF57316FEDCFF6C6F5EBFAC6EF9A
-:10B14000BCBFC9EDA1A118CFC8F563898F704BE2D0
-:10B150000CAD3EBD51E0233C98CD40BD0171829DB8
-:10B16000F2EB4E1807F3049B473DCBF304FC5CE77E
-:10B17000C26C9EA71B97162847BF2CA330B090DB4C
-:10B180004F3ECF587CEC13F6FD8DE9F795627CDAE3
-:10B1900078A7DD8772F7E42BCA4CE2EB90050FFB32
-:10B1A00001BEE772080E13D5ADB1A04AF4686C0E6B
-:10B1B00084E3F3FD1492B346F0F3D0BF9F847C9EEA
-:10B1C0004E7C1FE67CCFED9FCC23A09ED4AEAB4837
-:10B1D0007D20F50CDA37E46729178D377717217D45
-:10B1E000BFA95E3967E2727E0EF0807224E5C6F177
-:10B1F000329797152DDE4A7CBE02E45E4BEFD8B83D
-:10B200000BE1C4F855EAF71F66051AB3318E3044D6
-:10B2100096D1DE52A18F1B5F5E5E146F7F90D4C704
-:10B2200016711EA6256C0B6BD741B0B6C25146D71E
-:10B2300010DA23DBA2F87996966C695FFBD4A5B58A
-:10B24000640FEF5B97E642DB85F2B3D946FBD4642B
-:10B25000DE29B6DF87B2155D7E47C625B89E81EF31
-:10B260003F23E4A75DF0E573D932CF1BD6F1BFD7FA
-:10B27000103C8E7505FDD931F9DD3F2B0F26C791A6
-:10B28000F63496FE723D06E733A5A4FFF7DAF731F0
-:10B29000B1CEA7E7C717859CD46533BAB69B2217F2
-:10B2A00049AEE63B18D5F3AC67FE345CE77BED1A9C
-:10B2B0002E0FFE9E22EC7F606ED09A9311CDF7E2A6
-:10B2C0007D8C3FEB54164A009AD46D3385B5FB64F0
-:10B2D0007E86B58600C779872564043EAFC80DEE2B
-:10B2E00045FE0A8DE1FBE1423FB4D2FA1438D2C3E5
-:10B2F00051BF34B1EE24C473A3B1AB08F393D5AE00
-:10B30000E03EA4FF2786AE3C5ED7C1D7CF8E897CB6
-:10B31000EE3191CFED344772BF9F1E3D9FEE02E3A9
-:10B32000755517BA0CA918F77DB8FB0F2FBE025F31
-:10B33000DFFBCAD97B7F84D85A61BBEF6770ADB69B
-:10B340001803AA26EF76CC115FCF7E20F8A8B7EEBF
-:10B35000A925216E3E7F6B0E7FAF2966BD7A6B0EED
-:10B36000D7A7D17D4F7CBDFAC37ECEB5BA2147D4D5
-:10B370004B8A7AACD8E737E7707EDB666245EB1123
-:10B380009E4D0E5AE7672A3F8FACF6897C1FAECFE1
-:10B390007716F0F3EF7BD62864078E99B8FE81BF4D
-:10B3A0003B2D15513B8A6E0AFA89B5CE50C400FA7E
-:10B3B000A376A12382E760C27D7534CA5AC8497555
-:10B3C000C133857D9CD5FCE65F319F51AB32CB68A4
-:10B3D000F8EEA4BD2609CDC39CEF3E8447CCB0CC8B
-:10B3E000EA76513F2ACE57F34F365EB65DC9AFD3EA
-:10B3F000EF1BF9454E80E5C0FCAB9339BEAB1FE2B5
-:10B40000E7ECCAF77F23E43696DFB621AF02BC1F14
-:10B4100029DCBEC48EE3CC1DF302F253B53B60A31E
-:10B42000FE1F3A4B7AADFA152B9D7F5487EB5CA03B
-:10B43000F2CE9776152DCA47BEEEC9FB23E6C9F6B4
-:10B4400026505D721DAE7769D6A7FB5BEFEA7F9D44
-:10B45000CB6B46FE6DBCA410FD67EE7DF328EAEBD6
-:10B4600046B59BF862A6C54E786FBCA4D273D6666B
-:10B470003AA3DDDFB6D0EDCF47B8433F1E9D42EB88
-:10B480006599709FF0574CE7632C10F5E0CEDC60B7
-:10B4900031BEB7CE96743FC67D172CFC3CA4263334
-:10B4A000AFFB6662DFB0A43FCB71E8E9BBF7ADBF8D
-:10B4B000225C3596209D2B397B06C4C946A447647F
-:10B4C000B8B3444BD7D1DFEA5C5B7B0ED7371F9A0A
-:10B4D00079DD4F5FBEE67A69AB7C2F8BCBC787796E
-:10B4E000AC76275EAF852B7CF761816897F1766C2F
-:10B4F0003F33857C7C3894DBA5D0025BDCF33CEEEB
-:10B5000014E3FD22C73F19F125EF3F25E4CF99EB66
-:10B51000BF1DEF83DEBB03F51EF0632405FAAB7E8F
-:10B520009DFFBE005BDA4375A7BDF32A12F0BAE2B5
-:10B53000C3F5FD68BFF7607FF09E9FFCF3D7ACB406
-:10B540006F8D4D063D8C7A77412E43BD0BE3CEC403
-:10B55000F1A1DF480ABD9740F3606DA08F41E0CEB6
-:10B560000FF7125D5654029F968BF3F2BD51BE92B7
-:10B57000FC14CB474D424FC5598F6F42B862D7E399
-:10B580000112A237F1DBB7D8FF352A8DEB7F90E7A8
-:10B590001FE4905D8D0CD1D6F3493C4B3DF861A280
-:10B5A0009E2F4C02CE16F15E2F9EC5F953E985DC25
-:10B5B000BEC93860B5A0BB557C27AFD25EC5E6F3E7
-:10B5C000ADA25F6B4E92A4CB6308A7B4737DE8BDB8
-:10B5D00081D31BDE7B9CF44742CF7D6960A7EE02DE
-:10B5E000FF07CF9F84EFECF85D9F7CC4586E5F9B94
-:10B5F000163818DAFF0D39A24EBBBC87AFB715C39A
-:10B600007508CA1FE81DE5EAF4C3D8DF037AEED750
-:10B6100058EF01E329583F944A6AC08BFD01BE9F51
-:10B62000D7E23B76BC63F808FCBD1D39625F5C293C
-:10B630002B457ADDF7EE5F1CF77AF17C72BE1FF7BF
-:10B64000337BF025ECE7CC0FDE22FFFE983952D495
-:10B650006E8FF3DC1CD9B84E893EBFFF17C610FEB3
-:10B660001E4567D79935D3812F6776197D38E4CC8D
-:10B67000872FBE3302FDE62E13AD1B81DFB00ACF4C
-:10B68000E73C26EA0059B33EFE7F57D047EE0B96C3
-:10B69000FA49DAFF79CCC7F552223F0FFD93F973CF
-:10B6A000695F700D0B1CC2F3D0BF583091FCE2B93A
-:10B6B0002C48E771CF6AD39F871B7B8E6EECF9B95C
-:10B6C0009880477CC59EA3FBE5F7AE9C2F97F52B92
-:10B6D000B1CFFF26F8F1CB7EEACB4F0BFE95F500FC
-:10B6E0004DB21EE0D52BD70334C5D40344FD0C590D
-:10B6F0000FF035AF0778555F0FF0E598F8705C10E4
-:10B700007034E1393A71FB4DA2FB5F165C799E4DB6
-:10B71000782E4EDC7DDF76BADF5F3D822D57E0A9C3
-:10B720009F7A8C845CD9BF47678F6DB9DE183F2B39
-:10B73000879E37C5D435449FF37A06991700BA52CD
-:10B74000FD9CF4EF62F7C3CB7CBC949F4F1566F170
-:10B75000501E6DB5881B7C43D11FFE14FD2C94DF59
-:10B760005BBDAF7503A8B37E7443915A1095AFD8F3
-:10B77000F9005F9ED6EE3B1F902BCE6FF0311FED90
-:10B780004B147271DF0FC625633EFFE387AB74FB7A
-:10B79000CD7AF7A39BA57F67D7D9731663EF67EDC3
-:10B7A0007E8BFCB71A4B80F6BD7DF6EA0FC8CECF74
-:10B7B000610117CAC9F957AFC90BFE5FD87909CF24
-:10B7C0001DA1074CDC6F4F27FF64AA80E78EBDDC0C
-:10B7D0007F3458FC261AC7CFBC4E1785E61C5E5036
-:10B7E000B678EEDD4DBDF097D07919A305FC0A7E41
-:10B7F0000FF8BD495CD9CCA01BE196FBF881EBDCCE
-:10B80000786DBDC1E7C5EB2D4A40659AFD9DE359B2
-:10B81000730EBE6FB0741BC5F962742E7C42145F48
-:10B82000D47688F6D23B2FDC371BEFDBF9F9C26602
-:10B8300001473057EC5BB6300BCE3BC11EF982D6C8
-:10B84000FBC4353486FBE3A1025E479C88E717C042
-:10B85000B876FBD9104ED6C99CB42FDFEABC10C114
-:10B86000B844F3BB1035B9C335BF0BC1223C5FD51B
-:10B87000DFF398DF8D4815F0B50A3DE9C1F3050BFC
-:10B88000E91C05D2938F3BE6D079E219F685B40E18
-:10B89000FD54D2045AA77421E2B13E7E82E61C0414
-:10B8A000789E11D09F7F903943DFF604F56D0B3BF6
-:10B8B00046F55C4A24E0BE9C163DE7D124F4CD9DBC
-:10B8C000891CAE3B1379FCD69AABDF971990BFE782
-:10B8D00092CACF4938E7B258B0AE02FC93D65CEEBC
-:10B8E0009F7C0494863891FFDE4BE92DFE416BCAA4
-:10B8F000F1774C8CBE2540A7650E6F8B8A7EDFDD0D
-:10B90000E277BFD40EAA57D8745F8A0FEB6B9659B3
-:10B910009D9598070DE5F2FC4F93D8A70114A9DB7C
-:10B920000EDF6D9A9A4DEFA557F550FEB467392397
-:10B93000BFAA0F9F7E0DFC0FF87E16DB787E438D2D
-:10B94000AF0BF7ED7AFC46AA3396CFB7E07380537E
-:10B95000117C81F76FA988FE2E53E1DED2FD78FEBF
-:10B96000240B2A3E9E8EF412BF4F13FE7CD3DECAF8
-:10B97000DB87035C855DC3888D07EE15EB2FE90936
-:10B98000627D989FBF1BFBFE407C1FDAB6C3DE7F43
-:10B99000ADC7470688BBF1BB31369AF711917F627C
-:10B9A000423F8C8891BF515179A0E7A5A2DD24EADE
-:10B9B00001F1CC087F054F6FD07BE95C3E7C4CFEEB
-:10B9C00071B9BD9145FFB09FAA68BFA4A7C6461F25
-:10B9D00047E510A65866F1B5D6C37B07A7F075F406
-:10B9E000116A641FCAFB28712D155736B39DF0BB31
-:10B9F000A225F286291F532D0123B62B9CCB5BB1C8
-:10BA00009F9B94085DF366AC6E4535EDCD2B14FC21
-:10BA1000161C87F2B96C1CDFDFDC3AD2E773C2A3D5
-:10BA2000E933787E76DA0C0BD54D4F53F9794C4CCF
-:10BA30000DE6DF0572765735CF0B63BB5A937791CE
-:10BA4000EB204720BED911C73FF0E671BB25BF6F81
-:10BA500012753EF2790E1EF40C001AF2C67F9C4B52
-:10BA6000F684AFF77E962BFCB462561CF3FB315F75
-:10BA7000901EA8FC5D7F7A42FF5CE88969FE274C36
-:10BA8000E4DF0B7D21F57240D42F75897354DE1FDE
-:10BA9000C3F1FE5EE53CD21777B266D2E777B1908C
-:10BAA00009F1DBABFF2768FC2318675A40EF2F4DE5
-:10BAB0009F11EB57717E95E3DE1DD43F9F2AFDDE7B
-:10BAC000097ABFB7FAFB5FA7905DCC7CAEE1F2804C
-:10BAD000689D52534C9D52A3A8536ADA3DFF60867D
-:10BAE000A64EA9692FAF536ADC7DB53AA51E5A57F9
-:10BAF0003A620AEFC3F59623F3402400CEFDA2AECE
-:10BB0000E500D6B59445F9D23195E75D817D69FDB3
-:10BB100024C769F3213FB519CA284FDB96E4F069C1
-:10BB2000F3A22B5A80EF34F959599774A49FB8B8EF
-:10BB3000388FC7A96B159E270FDD6DA13830A33054
-:10BB4000A05B97C830B2A3986FFC58F8416B451EB4
-:10BB500004D7F586C135AC70FFA6F77BDCEF84F91E
-:10BB6000C9187D9491E6A375818CE42194DF9FB17F
-:10BB7000B7740BE91BBBD587F5FCB2FF19C14D2A81
-:10BB8000D60B35EDDDA4D6D8A37C372A4FF0AB8D8C
-:10BB9000D9905F7BF37D3B1328DFF7993D704B1EF7
-:10BBA000CCA7DE1C19CAF4FC4CF7FBB36B7305BFC2
-:10BBB00098C604EE9E0DF09C7FC7CCF35E0F3392C7
-:10BBC000D7DFEC49A17CA53A95917D595AC9F8EF88
-:10BBD000BB6C52C89F3B99C2CF0D5A3A85911D3C10
-:10BBE000973A9EE8378F850FE1B940B51B4CBAF301
-:10BBF0007F1EDCA26FD7B30EB237F5DBFBF033E963
-:10BC00002DA91F1B98D7887AA8B153FF3D1BA8D731
-:10BC10008FA5C21E0C9B36B6D504DF0D3370BDC593
-:10BC20001EF6654FA5B8BB9ADB51F61C9D3775DE35
-:10BC300071CAC8E59CEBE3E151ADA9B34BC3857F65
-:10BC400075B3CA7F1741FA4BC3C5EF241C30EC35DE
-:10BC5000D26FF20878CAC577D24F93FA5AD2A5723A
-:10BC600024FEC603443779C2DF2960054857E89FA0
-:10BC7000E441C140891F714CBFB7304A8C0774E75B
-:10BC8000E7CD192C61E4A3654A33E9690B13FA5A2D
-:10BC900009925EFEB750C8887C70036BBE037FBFFD
-:10BCA00073B4A5CB467EA93DF868DEF0289FB4B2F8
-:10BCB00048DE0E45C72FF4FC4CCAEFE2F28BB42BE2
-:10BCC00091F7B9BF3189811F08E3FA3FE07ED001C7
-:10BCD00085C78BE00F1EC078F1778689C40F13618A
-:10BCE0001AF8DE38A79ECEB7BAF5ED89DE3E7C6045
-:10BCF000D4FEFE04489C8AF04C2AD6BFE797FA8D02
-:10BD0000E9F55B3EFB9AD7C12F3FF45DCC1BD816FB
-:10BD1000B162F463C073F4C5FB7DD16DC25EC459DA
-:10BD200037D99697D177DDE4BCC8FFDEC8BAE76C97
-:10BD300057FAF2CDB9838B8C6E0D7F497E7E59D434
-:10BD40005928AF8BF5D9729E2F8CDA79CE3715A290
-:10BD50007523F21DBCFF96E417F13B2137EDB64683
-:10BD6000F077704A453F3722FF9445ED7AC460F77B
-:10BD70009A0B904F7C6D46635F7FDE95EA257E19B6
-:10BD800066F013BF0C67BE34A4D3484B47AB8AF0B0
-:10BD9000EF19911DB4EBF8E31DE20F05F883F2599A
-:10BDA0007DECA3FE790CFF483A1E167EF4ADCC4B19
-:10BDB00071C404E14747F239FF54D9EF54F1FB371E
-:10BDC0000B78BE612C2E28D23E53BD5DACB2E8F993
-:10BDD0002096BF60448376DC587EEB8F6F0620DFB1
-:10BDE00048BB987675BE39DF3FDF9CBF12DFC4F2D7
-:10BDF0008BD42B3BACCE2A3BE6B76A15D2C7C3DE49
-:10BE000019D88AED6B1AF2A90E66478A6F3F3D6F0B
-:10BE1000E6CFCBBBFC46AC93295C289EE707AAB0D3
-:10BE2000DDB488AF530C3FC2EB68063ECC9F972E23
-:10BE300069DE8FFBFA9A42FCFB97BF5846FB9BC218
-:10BE4000CBC4F795ED55D86E6AE3DF9FC4F5A6EB3A
-:10BE5000B1FE2DDC8AF707AFCAF7F1B094FBB5B796
-:10BE6000083EDDA1ECDC4FDFB5F3EFE61EB224D2D5
-:10BE7000EF060ABFF56631CF5B36F079A67F7A1BF5
-:10BE8000FD8EE8EC9E10F94F9F1BEAE9776AFA8B6A
-:10BE90003F2B95F61CBCDE8AFA040FDFB2005F1759
-:10BEA000F0F5C8CD30C47503B83F28D7F1B0AE4027
-:10BEB0005B4770DD001E17C9F75CA97C1F1A7BDA8F
-:10BEC00041F962B9CE1859C71494339CA3F003E228
-:10BED000AE3BDE5AD84CEB8DB70E90EB8DDD2A9E33
-:10BEE000A35E7AF92FE3E3E559CA06F03CD0295165
-:10BEF0002721EFD786F3E977C1762093D03EFAF079
-:10BF0000EFA92DCE056762DFDA8E7CDEF60FD8F062
-:10BF1000D3B61CC0AFA159C573D4589E42FBF6FEE0
-:10BF2000A58B459293FAC27FABCA2266BEEF8EE024
-:10BF30009FD36ADECCF74F72BD344DAA9DD18348A2
-:10BF40004EEF1474FACE00E1770C63C350DF4C134C
-:10BF500074BBCB027E2BE9B576538CFC4F1980FE67
-:10BF6000C653FDFACFFAE731FAA1568C3B47F8CD1C
-:10BF7000F3F0F7478D78BE3BF79F4F3DC5FDE607D1
-:10BF80005907E523CF3FCDFDC506981EF24B9FDF35
-:10BF9000E7DAA66F3774C4FE2E6C88FAEFF3BBABFA
-:10BFA000253CAF7BFEA9860ACCEFD5AE7F87F2C7D2
-:10BFB000B5525F84F5FA021C0CAE2FD65D4B791D8D
-:10BFC0008385FF2EE630D017586F320CEB48A1FF67
-:10BFD000A162DFFE72FC84EFD77F6800E98D09540F
-:10BFE000674AFD19697DF71DBF374A1F693762F53A
-:10BFF00045A9CCD70C4CA57C96D41FA5C24F611384
-:10C0000062E3C727490E8789D64F06E8E320E97720
-:10C01000C0F7E4777419EC618341EB6784492ECB58
-:10C020002C602F48947C1626F6FFC7D0F971A273B6
-:10C03000FF7194FE790C1FC838A642F0C1DDCC4FC9
-:10C04000F1D12EC107EFBDCF7FBF6D9A7D21F1E108
-:10C05000FB1F70BF53C651DF3E7E8AFC43F1532F56
-:10C06000DDADE04FDAF07728260E5A83EBE49D56DB
-:10C07000FE7BD50AA7B3EBEE2379DAFCE27BF8BBB3
-:10C080002B9ADF73689D9860C175C456138F2FA6D5
-:10C090004EFAB062A6467F0C49ABDC85F85AA6740E
-:10C0A0007DEF4F186FBC25CE4FDD9B4174BFD0C5CF
-:10C0B000EF5FD8709D2F04B7BF3489F3A894E63999
-:10C0C000581A25E198237EA765AE31FC5A37AEC7D2
-:10C0D0002AE15DF50AFDAECA01ECBFCE1031F3BC1A
-:10C0E0005E17E5E965FFFDE72943A4CFCC6F70FB40
-:10C0F000D8A324FA789E37A4FBBD9E035E1E6F551D
-:10C10000E406BA060C8FDABFD8BA8363F36FA57D55
-:10C11000A9FFC5FCC9B82EAAA8FCF79963C7C53A00
-:10C1200083A59A3CF5316BFCF5838F849ECF435CED
-:10C13000C1F88BB2FD1FE33C4F89B8F094581F3B08
-:10C1400095C4D7CB4E0BFD9CE715EB79E27A4AAC50
-:10C15000A79D4AD5C793F23D83977F7762B125B0FB
-:10C16000544357EFBA8466CC4B64148ABA92858CD8
-:10C17000C74F7B5274E72438BC9579DE0C7C4F9C0A
-:10C1800033B087DB655CC7C675E6F559C14B88B728
-:10C19000462FF3E33A2DF3769BEFC0F54AB13FF714
-:10C1A000BCE09BF3567E957039BC53F2BC88EFF926
-:10C1B000DD44D7DEF6946ED297FF072EE42C97006D
-:10C1C000800000001F8B080000000000000BD57DE0
-:10C1D000097C54D5F9E8B973670B9909939040101D
-:10C1E00088938D246461B261D86492808A22262C5F
-:10C1F00015651B50C2964DA0FDA5D5BE0C06117944
-:10C20000DA426B5BFCBBBC01C16AB52562B0B126EA
-:10C2100076544AA1D53A22286A6A4754D69044A057
-:10C22000567FF2FBFBBEEF3BE764E6DE4CD89EFA9E
-:10C23000DE4BFC7972EEB9F72CDFF9F6F37D07BB24
-:10C24000B322C999C058F7ECA099A98CD965FD21F2
-:10C250005E871F031BCCD862FCCB09A5D5E657F33C
-:10C26000E0EF0DA6CE6026B5B36F52185354E665C5
-:10C270007150C964CE0A3B3E9DE0389A0D4514B416
-:10C28000433F7566DB066534BD5E6185FEE68BFE69
-:10C29000D870BB11FB9FC7BB62F3DBF67FA5C43030
-:10C2A000B6C0CAD60F83F6856D43CC3003B62CC614
-:10C2B0003BD291836F4C761C8571156FB4FA4D3467
-:10C2C000F48D3F93FA968C19D951393F5A8797319B
-:10C2D0005CD78800AD6B63694FD27F1531D6D36EC2
-:10C2E000716C83716ADAFE7A588175D5C8F5B568C4
-:10C2F000D797ED54182BC69AD5F7A995B15B98C27C
-:10C3000006423FAD364F36C2ABC61AA479428FE61D
-:10C310008A5C18EDFE09B1B4FE21F03DCCE7C546BC
-:10C3200037FBC41482E72A075FFF14B5BADC1CCFC1
-:10C33000D8993B99C3028F56EDBFA3C90AF5550F93
-:10C3400030071FDD6D6063A07F01AFFEE69750618F
-:10C35000604EABA8E3B07306306766A83ED413A75F
-:10C36000A943BF0CE7B152F43B6CD9559AEF47D4BF
-:10C37000A768DEBFBA6194A63DD95BA0A9A76E18D5
-:10C38000A7793F7D5399A69EB1E546CDFBF92C7563
-:10C39000208375D6ED53990F409BE59BA169CF7E15
-:10C3A000FA76CDF7C758FDAF27C07B2D5131790CF8
-:10C3B000F0A8292A661B96CCEB0EE4007CEE14EB69
-:10C3C000C86D5EACE9E754CC75FB705FEF0C544D63
-:10C3D000638057A35B5768FA5DA956F37DDB643A27
-:10C3E0001284EFEAE117E159C07AF60E03FCA8F5D2
-:10C3F000292E3F342FDDC2DBE577CB5BB7D277CB7D
-:10C400007DDAE72B9FD6D6BD652CB3DE06EB74DA5A
-:10C41000E38F02BEB2ABD855DF84D155080FE025BB
-:10C4200018EFCC63AACF928CF0C9F8CD04828F8923
-:10C43000F99C7DF7EB0C632E3FBEFF9CDDE585FA92
-:10C44000D2FD77D07C2C895A3C88726AF1203A530D
-:10C450008B07769776DF079668F75D0FDF58F7A8AA
-:10C460000BC277D00D5ABC90702D81DF6F13AE8F49
-:10C47000E8E059B8C7DD642338B159D631083F3EEA
-:10C480005F0BAB50592AFC1D0F7C069EBB7817EC46
-:10C49000B4C3E63500FE3CE3548CC427443FF94660
-:10C4A000FFABB89EF58A97E17751CC9788FCA2A99B
-:10C4B000C49FE4877D29B0D6E3CEB1CF6C15BF47CA
-:10C4C000BAAF36FBF3B05DF6F799CD43CF3B953766
-:10C4D000AA18AC9719FD79C40FAD8CC697701C33A0
-:10C4E00080E3F14A5661C6715E14F8FCE9FBCB08A3
-:10C4F0008E55AC7EAF1BC63BF50187EF72E6A5F704
-:10C50000966CD2C2A10FFC747003B471E2B875626C
-:10C51000DD2B18F31952FBC2536953FCF63C04435C
-:10C520009BE4DB9E6F0A39DA213CC7B1DE1FE2DFF4
-:10C5300012BEF08212CE9F703CC7E0D078129E925D
-:10C540006FC9712CAC5E4D443AD0F13196A9DD270C
-:10C55000864C620CFD473F7F021E6A8D13830DC619
-:10C560007E70F28C5D23C6618B3D8908272BDB44EE
-:10C57000FBB751716D50611CF5EAE42606F02C748E
-:10C58000B855DCAF6216988BCF4BACCD4D46E8EA80
-:10C590006A76DE41F834E4A99A6F0685D6A1C8759B
-:10C5A00079156684FA44519FE955828F26E37AFE15
-:10C5B000FA158E3B519433B184FD83657EF2217C64
-:10C5C0003C41718EC0F166FC292301F166BD52CF5A
-:10C5D00074F33BFC32F4A31A7A06E17B5398C7C884
-:10C5E000E5AE8FE4CD5F9520CDFB07CC7D1F965245
-:10C5F000BED5B2E6EBE642BDB605E4560C96517EDA
-:10C60000154AD6AA8327331EC1BA015682F8BD1235
-:10C61000EB72DF9343ED5457FBD6D7C21A86C65D43
-:10C620005CBE3F98EC10F2B167246FE7FC6D998017
-:10C63000D73229B77CDAF975E01F4319FB8B1960F3
-:10C6400052807464F51A063296980C7489F3CC63A0
-:10C6500079D83FD0D5F064E87F701CD0A1124E7716
-:10C66000FC7DD9DE87EE74EB67F5B0B96301DEF6C9
-:10C6700022B30758EE1DE1EBBD0478483D6221BEB0
-:10C680000BE37DE174525933A0E35D373617059211
-:10C6900050FECB7DAA33334F33EA2DCD0934AE7C27
-:10C6A000EE4E360878013E5E029CFADF8734D28770
-:10C6B000E43E5CAA3E347E109FBF84DF75C9820FC2
-:10C6C00086E07DA3069E0CE099AB81F78D91E02D6D
-:10C6D000E171BA38F014EE936A3F3818E13C2FB19B
-:10C6E000E2966400C188C3C1A38A01E55DE7538F68
-:10C6F000A2FC6A555D48C3B513397FAB7D492592CD
-:10C70000EF6AB3F814F87E59EBEBA4977536020381
-:10C7100035F50F9FDE75EAE0DC170E7CFFE43AAAE0
-:10C720007478B6E0EDB3F6F94E5ADF8AE4840BAEC6
-:10C730005FDB2ED67FEA476C61450EAE2F67603017
-:10C7400027346E26EE37BCFFD3988A7A845BD13BC0
-:10C75000C363102E53D4B6BD57211CD6282E0B8C84
-:10C760003BC9C2BC51B0BF431BCAD927B04725C182
-:10C770007A9703E09138DCE652011E193F542B7C76
-:10C78000D0EF3FD7AC8EBB03CA938D30743A3C5781
-:10C790000C1584676CD7473F81FE32ECF35C1BA11C
-:10C7A00036DF02F38171927F14ED4F05FEF067339F
-:10C7B000B3229D9952EA0F4C857E7B625517EABFE2
-:10C7C000F12A9B8C7825E11C1FCDD7219F973EBE77
-:10C7D0005D09DA42CF2735F514AE82F2E66427AD63
-:10C7E0004BAE7352794F21EA3B12CEF1A9FC7D6624
-:10C7F000EC499A114617D9021E1DA8CF013C6B13B4
-:10C80000CCEB51FE7559799DB93349EF5D63E57401
-:10C81000D11195E443B9D8016B0D507F7E3BB385B0
-:10C82000F1C328F7C06B60DDEC6D95ED80E29CC331
-:10C830003D3096E0E1E0FD083DAB8BB11B104E6B47
-:10C84000A6960D898332A189C3478F273B93159AFA
-:10C850005FF597407085A1E7D546BFD961C3E7660C
-:10C86000CDF3230037AF25545F7C3CED3A46FCC541
-:10C87000B51EDFBF634334F386E9552D621EFDC14B
-:10C88000A536D6C88C008F5A85555CE8BD97FF5BEE
-:10C8900025F8EAE7FFAEE02F09E591D7F76632B752
-:10C8A00067CAEF9FF61BD43B6B03266681476B5E1E
-:10C8B0002A1DC222F4D70BE72FC733DFA0B0BA314D
-:10C8C00048F0A8FDF25A7A5E7E7FA719F11EFB712F
-:10C8D000C2F33551EE21AE0BC0395BC0B9F6CB586F
-:10C8E000E61D14FE9CE355A8FF786AFF1D0210F0B8
-:10C8F000D6DBAAFA76C0A7BFDB67B8615B84F97E96
-:10C900002DD63F2AC148F492ED67EEAD11C697EFE0
-:10C910000D8E033E6DE370AECCED3BBF96B2E002F0
-:10C920009CFF3593993BD278A7C57B72DE2D71C1F0
-:10C930002A81F7232BED617587761FA3C5F82D3764
-:10C940000693B0FFAEA96C4E7384FEE57E8F31D6A0
-:10C950002B088FD2444F06F291EA5BA10278326431
-:10C960009EDFE0C909D15D7FFB1E8237D85D851748
-:10C9700082B799DA657F270E08BA646E9B02F4B419
-:10C9800048C8AB45DB574E03DED96BBF9CD802F6D7
-:10C990000B0C7182D5BF6EC7FA2685EC93C51EC6F7
-:10C9A0001A80EF54ED285C8F626B512263D7C6F179
-:10C9B000E7F760B9CE1492B3F47F370B978B72FC14
-:10C9C0003B1FD4EAADCBD8839FA3DE73E200E70F11
-:10C9D000A09E92FD5DF5B0B6BF65DB6F3A86F35C55
-:10C9E000A6D37F3250C103FD233545D81363D81831
-:10C9F0009403AB769C35C738FBA7839340EF69E976
-:10CA0000C82F1D548E49718F4A81FDE87E9BCF73DC
-:10CA10004A8A272F05FD0D6FF3799DA93EC3E5C412
-:10CA200063F1249F2CC8CCE14FCB5CABAF09E6711E
-:10CA30003FB09328808FC5C2F520A9FFA9EA6A35C7
-:10CA400006DAC77EB6260EF737FED9EB6FC0FE12A8
-:10CA50009E8D76E37A3696BAF3D15FB0B1D2E66AAC
-:10CA6000822EADF03DCA0FDFEFC6BE76156A07CD48
-:10CA70009BCB8621DAB5BDEA477FCA06C3E77B8731
-:10CA8000C1FB1BAE65AE26161AA7AEADF2799C4F60
-:10CA9000D22C2E673626BBF31D61FD32A1CFD50AFD
-:10CAA000D875B767FC7C3CECEFA3FB489D86F5A5E9
-:10CAB0000C44BE318AF17D66E7014E80273876B896
-:10CAC000DEDA09F28A6584EAA39A15BF09D653D340
-:10CAD000F2BC01E561F5BDFEC173512E3D63746D7D
-:10CAE0000B9B5FFC9F8796396342F268AEE2207D24
-:10CAF00041EAE5B731F99343783347E0CD6D421F02
-:10CB00009F1BCDE1BB98B992F0BBDBAD2CC60024D6
-:10CB100035B7BCB998E4D54A532CEA3FB89648FBE0
-:10CB20002DCBFEFC4AB54FD9BD0AEC7B97D2331210
-:10CB30003B3989BE1EEE5FF26D4BEEDBCFDD298205
-:10CB40000E470AFD308DB9EDB0EEDA5732B66E847D
-:10CB500026CB00D8C702E24BD69202D28FAD68F73F
-:10CB60002C7F39CAAFC484E0C21CEE7C03FA09668C
-:10CB70000C2FD8883AE961E02F40605DA66012D1A1
-:10CB800031F01D0564DFC329932B8D80E7B55781F4
-:10CB9000FE05F5D7B655F27A4AB0CA00F593292BAF
-:10CBA0002B8D8097B5A38247B17E2EE547BC5E10E2
-:10CBB000AC52A13E30751D7F1F0D4140ACE1A9FF75
-:10CBC000B3D20BFD9F8C15F2DD155C80F853FBA7EB
-:10CBD0000CC3C6B0F55A5339DF3A19C5DF3B99CCBF
-:10CBE00016CE4078670647E23C7BF12245EAC39BBC
-:10CBF000A894EB94DFB1C4C8FD3F99C2FB5F5E2EE1
-:10CC0000F49268B601E106DBE48D01F8EF69CBD858
-:10CC100086EF6F488913F0827E8A42FD4838CAFE4B
-:10CC2000E4B82B50EE223F36013F0EE3A3CD295C42
-:10CC30006EC238EB689C1C0EFFDA19C3F371DF601B
-:10CC4000BF8C62BF8CDC4EDDCAE707FDC6E611FF74
-:10CC50002F34C2FB7BCEC3FBC9A179EBF1A35DE00E
-:10CC6000C7F2266084A4A7A5121E4D8AE6FA212BDE
-:10CC7000D2AE63602A879F353596AFB3773F86285B
-:10CC8000344E9380E370807BEEE5AFFB2D319F6FD8
-:10CC90007BDD61FBE556B1BD356B5BF87A18DBAC2B
-:10CCA000E9E7E45ADD77254080388FB854FAEEFE84
-:10CCB0002866A5E76C5BEF77C9795C2F457DB546A3
-:10CCC000E8D5CC7B2D3915AA05D7A8D910303BB1B2
-:10CCD000BD5971FB103FD3607D08DF19D38AC4FAB8
-:10CCE0001C627D0EBE3E9F064FD9C19EA459F6BE62
-:10CCF000F8DB0BF7DEFE720A447F1ABA8ED41FD21D
-:10CD0000477FFBA1A47ECBFB21E7A983672F9C75FE
-:10CD1000F393F0447AA6EF72B4F828E779AE3FBAFD
-:10CD20004EBEC2F14AF977353F867D44FDC4A9C5A0
-:10CD3000E79A9664C3E29CD077ADB897C521FF5CB3
-:10CD40005AAAB07387B3E1C8BFBD65DC8FEADD6561
-:10CD5000713539C9AF97995A1CD1AF47CFF5F65EF7
-:10CD600077AC9929A41769FD0CDD09AE801BF5D4B9
-:10CD7000D3CCB503FA1DAFD33BBA613F77D942DFBD
-:10CD800085E489B6FE43C13FFBFA8D7A92707E45F9
-:10CD900096B2179C2EC6CA52B712BF2E1A58B63A70
-:10CDA00019EAD7A73E49FCBA6858D95974CD4C4DF9
-:10CDB000DDCEEBD9656753B0FEE476FEFE24F70BBB
-:10CDC000C8DF99777BE5E4A121FDE1C654278DAB4F
-:10CDD000961B18E29145BDCB857252C2B3BFB2C853
-:10CDE00062A88FA4BFCEECA5677E9E5122E4738912
-:10CDF000B4E783468D3DDF1D63F5AA00D76E94A787
-:10CE0000B0DE05A99E3908FFBAE8CE05A80ADF1BE7
-:10CE1000FD9119F521C50DFA06FA459C0E360FE66F
-:10CE2000A9746EAC203D7085CB6A24780A3F15AC9E
-:10CE3000ED1BE8E7E5579EB97B181FA602E73156C0
-:10CE4000D07FDD2B5F7DF121CAD1933617AA816394
-:10CE5000DB1E598DFAD5D8B6BF7FC5E5AD8DCEA9FD
-:10CE6000E4BCC7A2BF119E97B45A68FE63DBB296BA
-:10CE7000E0FBE3DF694B45FC98D8E16F4276D0DDFB
-:10CE8000FEC7619EF0732B764CF926FBF2F58B5EA4
-:10CE9000787C6666A85F023C7EC2E171BE0AFD8AAC
-:10CEA0005D0907D607494F1BCEFD98E27BD0CB33F7
-:10CEB00091CECFB0012E3C57E8B6F37EF4FECDC341
-:10CEC00095B03E783EB1076610A6374FFAD20A0CED
-:10CED00024542F65B19A7AB975A8E6FD298E644D60
-:10CEE000FBF589599AF6A9CE7C4DFDA6CCB19AF7EF
-:10CEF0006F76956AEAB7944CD5BC5FE9AED4D4F3AB
-:10CF0000FDCD9AF70BF7B56ADB0F3A691F0A3B2A8A
-:10CF1000CA519F77053C4D585ED3B9A97CA093F5C3
-:10CF2000F1EB16057D4DF87CFCF9FA623FEBEBDF87
-:10CF3000652B3C741E60C17D51C3CE074A03448FEC
-:10CF40005D069733DC8F3B6FB067672AF97101ECA0
-:10CF500000EC6BAD3D8370BFA62C7C488DC17DE994
-:10CF600061E4FF6A31077F361EE5FC7C95F4DE162E
-:10CF70002323FDB1654EAE0F7D7F8795E08B1F2289
-:10CF80009F9A1F4DFC642268B8B46E3C0355709F95
-:10CF90003C9A7597B2E5BA7DBA4B539FE2F8B1E679
-:10CFA000FDEB13D76ADAA73A1FD0EDD3664DFD66C5
-:10CFB000D723BA7DDAAADBA76734ED133F0D3621FC
-:10CFC000194DEAF4AA7698FFB8C39BCA715FC67779
-:10CFD00078E723BD14F93D4DC442F6D4BF8EA51F9A
-:10CFE000EC2AF46BBDD69848E59E4627F9A5F6369F
-:10CFF0006652B9AFD145CFFFD65842E51B8D6E2A98
-:10D00000FFD178039581C60A2A9B1B9BE9FD5D8DA4
-:10D01000AD54020447A0BC881F24E40FD4D1DEEF36
-:10D0200032046BF1C4F5B327CF115FEC1A10ECC2D8
-:10D03000FABDEC2CF1C5401A233AB4A633E2635D85
-:10D0400069EE6569509E4BE5F56E936D03CA816686
-:10D05000833B1FF5EBAF9E3CBFD93882B1FBD65660
-:10D06000243A6279DD0A75DA6C34CCBCE737BB87C9
-:10D0700033F67B1419E3A85E89F5EE28DE7EEEC94F
-:10D08000F3955E9A1F3F6F9E153A6FFE2A35C2795F
-:10D09000F3EF8F3BEDE86F39703EC38EEB3A20FC27
-:10D0A0004B6E966F5A0465A931DF8472F1B04E8FD2
-:10D0B00090E5BF6CA5065C4FB3C1351BF514EF8D31
-:10D0C00026B603F8C50C85DBA3BD7A601A9747DD49
-:10D0D000375BC8DE3968702F413C073EFD04C2EB68
-:10D0E000AA34FB0C845FB7BD2709E1909866E3F58D
-:10D0F000849E27145758DDC4D7199B163DA39F75EE
-:10D100000E4E8BB0CE61690E1A9FF9DD2350FECA18
-:10D11000FAC14A770DCA8983A5EE749CCF810A0BA8
-:10D12000D18FB7C2EE4B4726677417CF0EF3BBFC07
-:10D130002ACD44FB36CBCCE98CDDAEFA7644B0D3B5
-:10D140005E48E3FA3EED1BDA73B745931E7ED0C00E
-:10D1500096ED8A00C7BFA77139776A4064FFCB1B81
-:10D16000027E6533EDD45FF79A283AEFEDAEC82022
-:10D170003DA8BB1EA004F4D17DBCFEF46E6AB7C806
-:10D18000A3303AD79C2BF8D4EFDB56FFFB10BCFF43
-:10D19000D19A6817F170C728924FB78B97E70FB2F3
-:10D1A00092DE327FC68832944B73C5F9D802BB71C8
-:10D1B000301D931963CD0EE8E74E5BFE7A14FF55E0
-:10D1C000F195E658A82F1B7ED77A2C57A46D36C749
-:10D1D00041599DF3FC7A541F6B80B48AC95E0ABE24
-:10D1E000D908F35AD8A03AB9FD24E49A7BE565C57D
-:10D1F00063483C4438229E027CC92E7C53C05B7E2F
-:10D20000F7A680E7DC34A1B7E5B2DC6FB4E73E0BEC
-:10D21000114F3AE7BF39B21F3FBDB65DE86DEF9AD7
-:10D22000F9B82B9F36F9C2FD4972DC7F88791C342E
-:10D2300033B7827ADCED76C28FBC3967EF2D86F585
-:10D24000E7B5390C746E2FF9788091FFBEF8530F53
-:10D25000F1B96B3A834F1D6284E7AD4827179353AA
-:10D2600033BD6B493E8C3D07F207F9E279CF478722
-:10D27000880F2E137CB09EF8D79EC606AAEF6DF4D9
-:10D2800052B9AF7183E0839BA8FD8DC62D820FFA42
-:10D29000041F7C9A9EB735CEA1F295468FE083FCA1
-:10D2A0005C7586C0A779899E7548FFF2FC7296D599
-:10D2B000634278FDE5110B53F17CA2CD42780A144C
-:10D2C000F0C4A3F1182F63716C74F68D9BD1F3DB5E
-:10D2D000DEFDD79DF3AE49746FC27DE98D9341FDAC
-:10D2E000ECEAFEF1E70073DA919F3CBDBD82F8C71E
-:10D2F00001A7D38E7AEB3369953350AF3DE076DAF0
-:10D300004D50FFDDF64ADEEE71DA2D507F366D06A8
-:10D31000AF7B9DF628A83FB75DD47D8C0EB59FDF0F
-:10D320007EEB0CF4639432650FD243B9357932B099
-:10D330006B908FA57B900EAE4F5C3419E9C099E6D7
-:10D34000247C98EA5CBB07EB37656E350E72A2371A
-:10D35000347F1D7E57165F69C4EF260FBF6B1D7E9D
-:10D36000775DDA6663F87737E43CBF0EEBD35C5B3E
-:10D370008DA80F3AD3F879A9EC47D665BBE4AF681E
-:10D3800027209E8E6EAB203E9ED75A417C5CC2A564
-:10D390006C56E57DE8A7AB6B551C0ACE6396D27B35
-:10D3A00058AF800E517B1EA805F8AC7FFBE2B8B5E4
-:10D3B000188782F57154FFC5DAC87CF72F88077A81
-:10D3C000BEFB9EA053949B95D0CF7B403FBBA09EBD
-:10D3D0002ED657D7B6C8BE88EC198F1DE56B761AC6
-:10D3E000978BA385DC5C28EA778AFABF6CEEB7706E
-:10D3F0009C77FBA7EB0FB01DE8B68ACFA30F5D6B40
-:10D40000DB055D770838B2A29E24ACD7B04DE42787
-:10D41000BC587CD7F270FB2D19E3249A29FE421FD9
-:10D420002751CD02BCBF665D9C050B9AE93CB63521
-:10D43000EC39F123617F0CE07C6F0E326BC0BF7F53
-:10D44000A78973C7BEEBFE4AF0ABFED6AD6D17EBF6
-:10D450005ECE7C14D7A65F07F324106DADB41DA477
-:10D46000FDECBB9E60E4F5F45907B7DF651C8BF457
-:10D47000CB831E14955E8C7CD0CED07F13CE270E2E
-:10D480005D804FE8F9D1B7C5E72EC06F92709E7AE4
-:10D490007E23E3B3F4A5D4E7A0EEC5F83CEF2B510F
-:10D4A000E4A7FFC4E9C9C27EBACB7ABE30A07D161C
-:10D4B0001F243C6B002B0F9F2B667E4E0F5F8CC48E
-:10D4C0007D3B6EF0FE01F5A2921D8F119FEA42E1B5
-:10D4D00000F4E8823AF29D2D575514E0772C93E33F
-:10D4E0004FB7C2E5A2A47BD007A91C9BCEE551DFB4
-:10D4F0009269E21ABBB77E95447EAC8BE07B7F706D
-:10D5000098A24E087A91DF974493CAD3A930BF02FC
-:10D51000FA5F67E960D2233A47988D587EDB7662DE
-:10D52000E78891D4BFDE5EEC1C5A62E5E35E7703C8
-:10D5300096AD66CF964568278DB5909DF496880781
-:10D540009C1ECDE3A7DEC27362786FFA91F3F128D7
-:10D55000BFF4F666E7FE7965CEBCBE7627AC7332C3
-:10D56000AEB3FA63C37DF8EC72EDD0EA862F987102
-:10D5700010C8ED86F3CC587829762953915D141C98
-:10D5800076BD8E65F1A781B83C27DA9F527F10F6F1
-:10D59000E945E2904A7AB8BE30E93CCB3416A19F07
-:10D5A00069009DDF28257FE776AB28E5B9C8043EF2
-:10D5B00005B6C060F39953347148894628E7A9C17C
-:10D5C0003158EF62013A27D1DBB37F157E28B06B6B
-:10D5D00037A6935F8AC727C18E0C42FC9DF293F752
-:10D5E00017DC4D7C208AF4A15EBB76B781E20C5A31
-:10D5F0008CEE8113D1AE6D4877AD85FABF0209BFBD
-:10D600007A19CA3AC717043749BFD50D67099EBDB5
-:10D61000E703C2EFBBC904F207CAEAFF56490E5539
-:10D6200033B681F68DBD665E15261759F3E7BDF05A
-:10D630001F0D7CAF12014876D684996EF8AE52D891
-:10D640001FCCDBCEEBC2EE626CC44C37F453992096
-:10D65000DE679B79FB08D9FE0B5E4F97FD7D3E830D
-:10D66000EA43655DF49725EBFB793D598E7792F798
-:10D670009F2BEB165EB7F3F75F48FFC34CE40B92AA
-:10D68000DFBF942EE4443ECB177139EDE9C5178C0A
-:10D690004BD1B60BF9B0F019D56B1E8DFB3335FAB3
-:10D6A0004DA4EF668562E7AAEF3191BFFB545C732E
-:10D6B000DEEA307B45C6B15494DBDDA8FFD5BC98CB
-:10D6C000B14D15F13CA87F7CE1E47AF914D546E729
-:10D6D00013671EE47CBF3FFDADAAE165CD7EF66910
-:10D6E00057156E8FE3C11D8C77FAA1215BC9BE4827
-:10D6F0000BD0F9F98782DF0D06DE5A12178A178BD5
-:10D700004F656EB457E3FF08FC19F7F8D300F1E357
-:10D71000AA3F72FF6FCD23AF93DC5BAC3AC99F5B2E
-:10D7200096E3F918E1D3650F905FB1AAE1159AD796
-:10D73000992C61573A7A72C2E179A22FFC4F5F04AB
-:10D74000FEA7BF4FF8EBFDCE2B6C7B68BD2B2E33B5
-:10D75000AEADCBCECF455D629F8E189C6304BC2CD2
-:10D7600023012EA7970446C6AA18741C18CCE3966A
-:10D77000DE2846BBE84CBD9DE1BECF5BFDCF3C4FF4
-:10D7800004BFAFDE1EB80DC72C0EC12B61641FF89D
-:10D790000EC5F12E005F6DFB770CDF21C6A0D98589
-:10D7A000E7A88719F5332670C41C1E1F337624C7DB
-:10D7B000CB81ADFCDC481FF73576A49DEF93389FF5
-:10D7C000A999F1C6043C9F91F430299A35A3BF1D55
-:10D7D000F0DA25F0DA85782DF137744E03DF45A0B5
-:10D7E000AF10FE6AE1EAEE0BD7C9232F8CB7DAF649
-:10D7F000EF18AE2DA00FD3B9E6EE28F2A7E8E1BCF2
-:10D8000074243FDF92F06EB8089C1BBE2338378C1F
-:10D81000746AFC1112DEFDC927FDFEC87947A0D34A
-:10D82000E22BA1D3AF33847D630C529CA97EDF1B16
-:10D83000FBEE7BD345E8A9E9FBA4273DDCF465B505
-:10D8400038EFD43FDF3A92FBCDBE2B38FEFFE64FD8
-:10D850009F5FFFAAA67D61C37E4DFB22EFDB9AFA94
-:10D860008460A01CD15CFAC7AF3DDEF33AD6AFD4DA
-:10D87000CFDE9F7F7DFA0B4B0D78FE5612E0FEFD4A
-:10D88000C5999E2F90AFBC65F035D901AED77434E1
-:10D89000AB741EE6CBA773C0D5628E6727FCE7A3E7
-:10D8A000BB016FCE320BF93FFDAF66199DB97DF11B
-:10D8B000A0F44B95B9C3F4C4526BAC11F5A75260F8
-:10D8C0007991F0E66B8137140F04F43EC7CA4CF12E
-:10D8D00040E773E62814FF3487F1786A28FD1E6854
-:10D8E0009F6E647E0BD42B6D46BF85CEFD78BEC384
-:10D8F0006C3E4D663182C686F65DFC20B28367E1E0
-:10D900004398AFEA56299E6D76093F2FBCDDD66C51
-:10D9100042797ADBBE7B4FDF0DED6C9DB798C76B0C
-:10D92000CBFCB50F0C97730EF8F5484EE7DD8A383F
-:10D9300057564C2E8C73D57FF7D6484E67D3D5B546
-:10D940002AC6BFF4BCCD48EF967407EBDB6729E02D
-:10D95000F919E3709DCCE4CF8841FD797339BE5F3E
-:10D960007DD04970A92B599B87FB583759F9D8921C
-:10D9700017B26FEA1ACE919E3E457DAE09DF3F7326
-:10D9800098BBC6AFE9F4AA68AF84FC97C105489775
-:10D9900017B383E4BC3B1AFD844F1F35EEA3F2ADF1
-:10D9A0006BFF5E8C7A46B03110D17F79A5FE02E91B
-:10D9B00027907E03C907FE754FF910C4CB74C917B1
-:10D9C000ACCA30E40BCCC84BC92FB333FAF0D7D173
-:10D9D000191796ABDAF6EF98BF5E2A9E572772B9F1
-:10D9E000A8C76F3D5E4B7C86CF8A1518F776D0F7B7
-:10D9F00050AECE65DEDC6AE0B373966E328D57AE04
-:10DA00001CAF57D83E4D6211F2542E9F9F3B79BCFC
-:10DA100064B94AF6818C5790FBB03843F81943FB40
-:10DA200056957161B9A86DFFDEF5F84F175C995CEA
-:10DA3000639AFC86B57DF1F5BE8BE0EB7DDF27BEFA
-:10DA400086E5CF2C500DA17C118C27463DAEDBC75F
-:10DA5000F32197256F8AA1E0CC929E18D41B97B72B
-:10DA6000AB8487CCE8360E057C5D2AF0B593F9DFF0
-:10DA7000457C5C3A6129E5D12D7B2C725C71AD78D7
-:10DA80007F85ADC58CEB5CB15DFB5EAD882BAE7E5A
-:10DA90004EEB17AD9D70FD31ECB75617CFF36C868A
-:10DAA000881F2E60053CEE42AB9FEACBAE46A6F146
-:10DAB00057769D6F247FC00BBF3DF94BEF8430FB41
-:10DAC000BF2FDEB65F046FDBFF6FE2AD6ADF4E791A
-:10DAD00055978BB73F1AE53E80F396FC781EF226E9
-:10DAE0001877DECB169F17CF478B9DDCBFA9F89A1E
-:10DAF000F0BCADFB2B46FEA3C5C2CFD95F5EBA8C8E
-:10DB000037187BD0D7C4E30DDC2AE6898ED957516C
-:10DB10008EC715856FD4933ED2EFB995CCAF12F175
-:10DB20004397CAD7A45F6FCCF17AD2B35C0107E9FF
-:10DB300043E3BE6C7E1DE5E3B7E5EF96F270FC2093
-:10DB4000EEBF280A56909ED765F217BF877AC24B60
-:10DB50005111F5047326D78B667A179978BE619FA9
-:10DB6000F34073269E070AFE6FB0BA4D08A7296AD4
-:10DB7000E7AF6E45FC09A8E4DF5BF3D377FEF0A8BE
-:10DB8000F3E2767F9DE32CE90DFDE9FF75069E7FAC
-:10DB90005150EEA4383FB4A7D0BF27FD7DFAF78BD4
-:10DBA0004695256692FF6942C08DF3D9C2E7D3DF5F
-:10DBB000FED4357CAEF12FF6377E5D7BB1637118F4
-:10DBC0001DDC96A948BBC371D41ADADF4BC5838923
-:10DBD0003D7334FACFFFEB76C57415544B909FB963
-:10DBE0008A8FEBAF8CEBB1F35880CA05AC874A0F34
-:10DBF000E3F1F78B998BCA3B451EF3DE2CCFCD9911
-:10DC0000781E61EA194CF1932F7E9D837873FADABE
-:10DC1000F19B30D6EEBBD2E3BAF39D347EF7EEAF84
-:10DC200093300EE6627C614DA2DB9319E1FCF91F93
-:10DC3000A52A9DB7B0C38F929CA814B730B0C9FC79
-:10DC40001CED0B6732E143882F0ED92AF9229ECFB3
-:10DC5000E67E6CE0F124CB155F3ABCDA1A34106929
-:10DC6000E52E49F6A9586FE1EDB935B13E05EAB99F
-:10DC700063A378FB5DB13EF4A3CF6741A2C78540A3
-:10DC8000A2582E629CEFDDC1DC3CDF81F5A4A01E12
-:10DC9000B6A4CDCAE3FD59300DF97B5E3FF64F5B6C
-:10DCA00026E7D3A353383F1F5DA6F553DC2BF8C0FE
-:10DCB000275965FF447A3A96E96EC272745C60E354
-:10DCC0002F8BC86FCFD07E3836F6C774DE28BF1BC7
-:10DCD00030AA6C03C26FA7C2E3D3BDED168A8F8052
-:10DCE0002F065784C5F5EFCD2AFF19F6F72BE1F77C
-:10DCF000EB0FAEF09D266F36444F5E9ADF68B4B9E5
-:10DD0000C8FF0E0F4A685CAA3FF5F4B459EB72C81D
-:10DD1000C7EF45BD77C028CFFFC2798D363366C3C4
-:10DD2000F93F6EF16D23FDB43E09FD954B9FB01890
-:10DD3000506F781FC42DE6A17CD868A5F29F6007BC
-:10DD400063F92FB083B1FC18EC602C3F013B18CB7A
-:10DD5000255FE683B060AC2CCBDD9A591C3A9FD38B
-:10DD6000CFF77901CFDEF1DBCD34FE27591E826F6C
-:10DD7000EF7EBFC47C78A8B333B6E7AAB80BE05BEC
-:10DD8000FF7C86C3459E17EADB7F2BF63DAFC54877
-:10DD9000F23DAF35185315F6DEDE4C33B5E7EEFE37
-:10DDA00094F250BB1CBDF0752BB0E4E9065EDFFBBE
-:10DDB000F46282EF2759EE7F225C81BEFF86655EAA
-:10DDC000EB3BBFC0FC1FE89FE20EBA959E5F931D20
-:10DDD000A05B871E0E725D3B63031BF1FB9DBB5373
-:10DDE0007025C06F18A71BC42325D27AD7D27C6FA9
-:10DDF000B1F414615ECB2DDFA811E38C3FC92A2555
-:10DE000038FF18F12D210C4E62BFAE94AE7BCFBF10
-:10DE1000059E32797F07F24E27CAA1F331A8EF554C
-:10DE20008AF3FDD696B4B7707DDE7D2A4B7712FE5D
-:10DE30006AE8CE91C5F14496B9EDE60ADCA79DEDFE
-:10DE400047D3EEB4D1BEA42DC171B3D235FEC7DC29
-:10DE5000B15FFDD72FE3E97D070E751BDB3A05E3C4
-:10DE60004FE65A5FFD0B2E69BEE3E329187FB230FF
-:10DE700051D98BE52267F275187722E3E3EFC82CBE
-:10DE8000DD8BA434CD55497A5A2932973079506EBA
-:10DE90008DC643C1DEFA14C7204DFDFAC4619AF75E
-:10DEA000A73A5335ED3765666BDAE5B8D35C859AEA
-:10DEB000F746C7F5A4A07D06EB207A603B548AD3D1
-:10DEC000CBDD7DF0C66CA84F7F6AB60BD5929DA2C4
-:10DED0007DFAAE721FEE4737C0D30C0AD4F1920719
-:10DEE0007EFD4BEC4CA7FF57B73FB9D7EDBC0CFDFF
-:10DEF000BF1FBD5FF2D9956DD662E4B3976A07E89C
-:10DF0000F7272F4B6B17F48737BD74A13839DEEC38
-:10DF100057D98E08788311A91C0F7939FD00CF1FBE
-:10DF2000BB5C7EF619F2B34121FAE82D757EB9D1BA
-:10DF300066D75BABD14FFFA6CA281F4FE4F555E16A
-:10DF4000DF6A08DFD99D5BEF1B1A4FCFBDA8E762E0
-:10DF50007EA91BFAAFCA12FEEFEA57EF1B5A146AEA
-:10DF6000676B3ED6BCCFEE51D66BEAEB92B5F507A8
-:10DF70004BD7877FDF1F5FACDAB2C8ECA1FC4FC57F
-:10DF8000ED8BC01FE47CA6BC1645717D3763BC0ACF
-:10DF90003CAA2D7ADB88E7B437F7234725FFB94D34
-:10DFA00065F591DAEF12FD4E7B2D8AE2602EB7DF28
-:10DFB000F701961467F8472E47DF1F183086EFFBEE
-:10DFC0003D595C0F3D5DBCF9A75FE0F9E84B8CE281
-:10DFD0003E4FC772FE9FD772CC608072F4008E2FC6
-:10DFE000798EA001E54AF7B2682FC6F5D72DB75351
-:10DFF0003CE8E8949E77ADB0F5EB9ED9FBB015F602
-:10E00000ED034C820C93ABDD681441FDA1ACBDB3B4
-:10E01000D6C1DF37BD16E5375CC17A1EC2730994DD
-:10E0200083659CCE1720DE08F9823EF6BAFB58AF16
-:10E03000BC41BE80EBC7FA9E67F61F7C18F5F0FD69
-:10E040009CCE31C24E6FDFCF0DB3EFD9639C2EADA6
-:10E05000F0CBE39474F4BD6793D976413A6FA6B8D8
-:10E060009B4BA5EFA7919EB32F48CF076E82FDA9CA
-:10E070007B89DF6B71A62D9DF262FB93E7755B5484
-:10E08000A24359EF6A536F40BCD5E7A14BB832B7F2
-:10E090008BE853DE1BB56AE27F66A0DC5CD56EE4DC
-:10E0A0004122FD8DB34165CEB07176BE625946798D
-:10E0B0006E62FEDD525EB7FF3BAE3487976B23C8BE
-:10E0C0003D90D3A67894D3950AD99587DA87942181
-:10E0D0009C0E29CCEFA4BC2D1EA73C937787CF6D57
-:10E0E000745F496226C5274BFB52DA95B3DB67A7FD
-:10E0F000A35EF96ECBE243B073ECC3AC541AEF5697
-:10E10000E6253DF8506CC508F44B4C17F1018762C9
-:10E110007B3A912F1F9A18ADE0793FF4BF0EFB9721
-:10E12000EB3A64AA18C1EF9F9071C9A3AEE89EB8FC
-:10E1300029EA3DA537E1F9F63CE640BBF21695EB3E
-:10E14000B9ECCF9C3E25DFAB53027138CFBD5933BC
-:10E150004E67C177431A7E26FCAA026E461E877858
-:10E16000A97A6EAF3DFBB4C2EF457171FDBF76C2B7
-:10E17000A95FDD8A797260772B309FC5ADAFD2BDC4
-:10E180003F7A3BBBD7DEF93FF4A7F6B5972A2CA31D
-:10E19000C2FCE47ABBA9574F97FADE0E1E27FFFA9E
-:10E1A000C4DF74AD84FA9A1DD104C7134F58BCC89C
-:10E1B000C74F6CB390FD7322AEA76335D677E5BA2F
-:10E1C000BC349A4B732FDA5283F33D943FEC6F26A5
-:10E1D000BAD7E3D8E3163FC67B2C7F326B1BDA53EA
-:10E1E000C746389F7D0EFD81CF26D03D03CCC3BFEF
-:10E1F000BF59D023D29713540FF5B776D22396BFC9
-:10E200003094F898DCBFE38F47511EFD897D3307BA
-:10E21000A2BFACD3F03CE5F130D5E6457EBC725BE5
-:10E2200014E9810D0E4FD628585FF96F6FBEB510F7
-:10E23000C77F2781E17ABADB5E207F65687F23CBC9
-:10E24000F7336DA99C0FF4CA5B1E77BB10E36E53C6
-:10E2500029EE7634C2B786C97B1779DC6D81AAB8FE
-:10E2600029EFE0A1C879E4EE515C7FAC96FE9341C2
-:10E27000CC9A8874E861B4DEEE8732B6A1BD33670C
-:10E28000545CEFFD4C3C5F52E25B47EDCBE43FB1A9
-:10E29000F078BFA8C8E7D8D346F1BCE22AEB398DA5
-:10E2A000FFA6B6E12B8D5FA5368791DC2D6872162F
-:10E2B000DE05E56A01E7E52915B7E0FA56346F7E19
-:10E2C000F10D82CB633FFA00C7DD6723BF0D7B836F
-:10E2D000C34F6FCF54593F17F4B45573CFCCD147C8
-:10E2E000DEA37893A3BBB3F370DF16AB81A3781FD3
-:10E2F00057973DF0D1DD50EEDA7780F6453FDF3EAF
-:10E30000E7F60AE72BD5B88E4118EF52B16414D165
-:10E310002DA7F7231B73097ED29FDB7D22B2BD257B
-:10E32000E729FB97F393FDCBF7568BFD3A6D0EE48F
-:10E33000A17C4ECC746AD6753A2690176BC3E7DC85
-:10E340009F773A0EEA6178F35D9DEFDC2EFC3C8707
-:10E350000D6B7F6806FCEB6CFEA5C913CE472FF34F
-:10E360005C47CE57C695CA3CDA874789F388116C5B
-:10E37000443FF9B75B90CEAAFBE6DFD2F3FEF26F23
-:10E380007BF36DFFCDF36D657E6D51B9A13E3CCF42
-:10E3900056F2C3A26C789E83E7FE5AF95E345AFBAC
-:10E3A0007E7FFCB1209BDBD7458322E7BBEE1FC5F8
-:10E3B000DB9B989FDF3F28E4E278017779EF97D4E1
-:10E3C000536A05DF96799EE3DB78DCE67891B70344
-:10E3D0005C80F25CFBDCEF96984D7255DECFA74077
-:10E3E0005FF3E222E50B07681ED7B21E2ADDCC617F
-:10E3F000C412C04FE5645641E575AC9ECA1BD826D1
-:10E400002A6F64CD544E63012AD928BF88F7BC8790
-:10E41000E7994E5D6A40F95A746B64BDF8D445E1E2
-:10E42000E0A5FB032F170ED7317ECF5F1F780CCFEF
-:10E4300024FCD6C3439FAF399105E9E2924988B8DD
-:10E44000A968073B29BEB59CB9A93EE512E1501267
-:10E45000F418797EAF0E1EE591F1E29CA0FF9FA219
-:10E46000EC2C0EED5356B693DFDF20F60B0CB144C7
-:10E47000E4FFFA7D94CF8BA2CBCE3A8145389E6DD6
-:10E480009C4D79DC8565AB53A19E92BD6936E579DB
-:10E490008F2F7B01F3BCD39EDDCCEBA3CB0A4D2E9B
-:10E4A000D022D7FE6236E6337A44DCB447C44B331D
-:10E4B0004FBEE69E2CCFDA1FD2BD639E113617AE3B
-:10E4C00053E685ABA9FC7C35E906FF6B2678AFDD0A
-:10E4D000E189CE46B965F5C738514F583B85EE8F77
-:10E4E000BADFCCDF97F7D9C8F5C97B6E76EDCA5E87
-:10E4F000ADA45C7C1ED0FF50ECDFB3369DF2E33C54
-:10E50000BB15910F5736640EF08DCE8089617E81E8
-:10E510001CCF94E249C2F71926C5035D0C1372B8EB
-:10E5200073577636EE5356B638DF8F4F2E4438DEAB
-:10E530009A529185EFCBBCE82CDC9784FECBCA6C59
-:10E540007706BEAF7F2EF3B2C7657B72B1BD2EFAE0
-:10E550003CE59B75E5BFB33E98DC374FBDC9CD7C2C
-:10E5600066E22BDAFCF4EE2566BACFA9A8C2D38402
-:10E5700021CAD7CCEB1983FA31F45B929D80F7095D
-:10E580000693F2E1BB8767F2FC777DBE77FB2BFB3E
-:10E5900035F9ED92CE7AF3DBCFF0FCF6107D3DB28B
-:10E5A0009A85E5B74BBA9174370EF3DB63B09EB52D
-:10E5B00004DF9BF84E07E5B74FEA088AFCF6F7B48C
-:10E5C000F9EDEEFF5C517EFB3171EFDB312BBF2F9C
-:10E5D00049DE27B56A373FFF5DA5F0FBA456FD9ED7
-:10E5E000DF2725EDC265627D35FB77ACC773BE655D
-:10E5F0008FDD41F75131710FAA137EC3ED42792FA0
-:10E60000A93E0FA60EED41D29BFDA477E9F361EA86
-:10E610001E2B277BB04EA747AFC816F6A090674CBD
-:10E62000E87F4BC5B7B80E1BD96766D23B573DBED6
-:10E63000DAE5C0BAA02BF6D87374EE26DF678F0D2B
-:10E64000225C9074B67C8342FAAB84DFE8A72C6E20
-:10E65000BAC7F8A921A4B782BE2DF2987DDCCF0FEE
-:10E66000B882F1F03B637B52504FDED99EE9020E37
-:10E67000CBFED4EFFDD3CFE9EE9F7E5273FFF419AA
-:10E68000FC1FEA69C70D3EEC670CCBFCF904A81728
-:10E690001F37BA7CCED07DCC17BB7758C2DF22F6AD
-:10E6A000EB72EF21D6DFF72CF31FF4F711DF2FEE1B
-:10E6B000239ED8CF7DC416B54D25FDE19C51732F07
-:10E6C000F135629D254EE6C37B7EC7751A35FB5F2B
-:10E6D00012DCC4501F8A3A68D4F8112C4E6DFD39F3
-:10E6E000890FE27E91BEF0B6F5C2D342F04CFB0D2D
-:10E6F000C15377CFB38453EF3DCFC36D84F7E3F6B7
-:10E70000BFA0223FB8DCFBBEBFEFFBBD2F769FB79B
-:10E71000FE9E6EFDBDDCFDDDF32DF73DDFBF4AF350
-:10E72000BE7EDF0BF7FD447B0FB5D86F2FFC7E9BC1
-:10E73000FB7D325BF877C57EF7E00568C0CFFE1140
-:10E7400073FC4124CBE9D1E23E3869D74F30919D2B
-:10E75000F5967350B91DE95FC8A90A21A75845333A
-:10E76000AF0B7C7105781C41C1617E7F455190C71C
-:10E77000138C391E393FE896124573BEDBF7DE6213
-:10E780009E673CFE3C8FD3D39FFBCBBCA14A7794C2
-:10E79000F6FE867EF288A41F07F47866463DDEC04A
-:10E7A000EFB38B70CFF11635353C8FC843FE9D59C2
-:10E7B000D64012E27354B2273E2721946F3409F3F6
-:10E7C0008A14B20785501AF8038CF3ECC624DBAB2D
-:10E7D000307FD4F603CC9381E93B8263B8B98B3F99
-:10E7E000C9399E1139C0078F288EF585F0ED3FC6D7
-:10E7F0009D4A42F964C173ED023AF7BD3A27FCDC49
-:10E8000057DCCF1F343849BFF0FE4421FBE11476BA
-:10E8100036368C5E3798445EA3EEDF2F10F694FCFC
-:10E82000F70B8E4017CB806FCF6FE579D42B133B5E
-:10E83000851DC6EF71BD63B88DEE7F62EE4217B7DE
-:10E84000C3A57D354CBD1CB979B1F8A29589273493
-:10E85000762E7B6ED0259D2786D6CDFB3FF24034A9
-:10E86000C99B230F8C203F5FA8FF2EB2FBE7D76B1D
-:10E87000E38C1736BCAFC1BF45DE8F35EDC1F81E46
-:10E88000D330587FF0C5A1D7CD05F89DDE6D198333
-:10E890007406FB362B27CC0E0E3E943199EB0117F4
-:10E8A0005BE7299A4787881395EBFCA8F130D5835D
-:10E8B0008D415D3C8F576397CAD2FC1AA37B727A55
-:10E8C0009401AE487E9693395C6FEF1079901D22CB
-:10E8D0000FB243E42D76883CC50E91A728F3473B41
-:10E8E00014E6C6788A798AFB8945C9943F7A17AEBF
-:10E8F000B36E454F1EE6DBD58D0E2E5054CA1F5DFC
-:10E9000083CF23E48FE661DEFB1F726EFD01EAF91F
-:10E91000C70778E95E92A79E9BC1EB664E1F2FE664
-:10E920004CFC01CF27F5FC0FECE75345F5D3FD1761
-:10E930002F29749ECADC41F38C0BE497DE97C3CF7A
-:10E9400017D6EB4AF2452760FF4CE47B3D3892F244
-:10E950007EB65828EF07C6A1FC2B79FEAFCFCF2A91
-:10E96000F8B3C58F7C43FA611EC94996F702937FBD
-:10E9700025FEE7169EB7150C24619E17C6FBE0BD69
-:10E9800019EC2073F33C307E7F9FDC87477244DCB8
-:10E99000195EA45F14CA13ABD97FE423E42365395D
-:10E9A0009EC771FD327FA926E6558A9BD899E3A4BC
-:10E9B000EF60BEB45EE007EB1482731F3FDC0EFC19
-:10E9C0005E9FFFDEDFFA4F2F09FC3A2739943F158F
-:10E9D0009637B53327CC5F26E711EAE7C2782DFDDD
-:10E9E00049217FD7FD23914E0AD00F1EC1CEDE2BC9
-:10E9F000E0D2618AECBFFB384789983F5790C11835
-:10EA0000FA0BE57D93EF209CD0EF749B8BFB4119B3
-:10EA1000BFB7AE6686CD857C4BF68FF7E53E7F812E
-:10EA20007196A754BC89EB5F51CFFD7DB2BD5BE110
-:10EA3000FBEA7D88E34BCD2BEF7F74378CB2FCB7BC
-:10EA4000B985C8A7E5F77A3877D979FEDE62D54F60
-:10EA50007004F87E80FBA4F7F35D295C2F377F1AE2
-:10EA6000E045F730F6F583032285E96F16F9FD706E
-:10EA7000EDFD6616FC771860BC1661F7B408BBA7FD
-:10EA8000D524FE9D1C9D1DDC12E071442D89668AF3
-:10EA90001362E2DF7590727FCDDB3CAE684D32A32E
-:10EAA000769C1FEEAF12DC4B72A8F79E2A05E42B72
-:10EAB000C0EF94C3A3E6A21FDAB39AE4927A35ECCE
-:10EAC0002FFA4DFF76A3B0E7B89C2B1672AD18FB5A
-:10EAD000C175E40C24795724C61D63AD277D7A2CBB
-:10EAE000F30AFF8EF0833CB097ECC0FF0D9F4D61A1
-:10EAF00077606800000000000000000000000000D7
-:10EB00001F8B080000000000000BFB51CFC0F0037A
-:10EB10008AF92C181856593130DCB0666070B4612F
-:10EB200060D86C8E90BB218E6053133F97A74CFF2B
-:10EB30003C4906860540BC0888974892AEFFB71648
-:10EB4000825DACCAC0F007C87701D25FD519186ED4
-:10EB500003D97F81B803C85F03C43B805804C8BF92
-:10EB600009A499D518189E00E97F40BE34907D44D1
-:10EB70000DBBF9FFB5F0DBBF5D0395FF128D7F4143
-:10EB80001DBFFE284DFCF2AF09C863C35EF6E4C7A3
-:10EB9000471F057A0702AF474BD7E2A60C0C7A66EF
-:10EBA0000C0C85D0B4BF0649BE192826610A617FC6
-:10EBB000D103E617207F258E7CF11528CF0F94EF27
-:10EBC00037C76FBF38335A7AE1C154F39609C1AEE3
-:10EBD000174295DB248CA9FEA708030300E92850FF
-:10EBE00078D80300000000000000000000000000D2
-:10EBF0001F8B080000000000000BE57D0F7454D54A
-:10EC0000B5F7B973EFDC9924772693106042024E72
-:10EC100012D458038C18302613B821098424E0003C
-:10EC20007E34565A07E421B640A3B5ADEDF395E125
-:10EC30008F315AACD0F2FAD4767DDF40D5D5F6B913
-:10EC4000DE0A8A4A43422790502488112DD66AFB57
-:10EC5000A276D9F81AED80C1C6EFA38FEFEC7DCE76
-:10EC6000C9CC3D994942F5AD7E7F64B537F7DE7377
-:10EC7000CFD9679FBDF7F9ED7DF63963B7B988E75E
-:10EC80000A422EC17F0B09F95C2E21645EFC2A9E8C
-:10EC90002F729270C61C42B29C077A67E710B2D8F6
-:10ECA00050FD4B7C844C75AEED26A5840488C3E7EB
-:10ECB0005008E9525EE89D4DEF8FBBEC7E0781FF67
-:10ECC000EE22643E21773BE99FB4FCF173F40AEF36
-:10ECD0003FB145082D5FAB361205BE772A7E870F00
-:10ECE000CA9BC6B22984D410F6DF8273A446A1CF92
-:10ECF0006BBC773492D984547B68AD4EF6EE12FE2D
-:10ED0000BF49082D5F4158FDA6D3FABE82EC3AA751
-:10ED1000BAE12EA60667D1FA2EEAD6F7DE257F24C1
-:10ED20006E2897F0BC80F603FEA03CB88AB872DE6D
-:10ED3000CBA07FDF406EB8A4D2AB3689901BE37CBA
-:10ED400091AF848409994C483BFF5E23C1D9704F31
-:10ED5000C833D87EB6E0635D3FF1D27EE79411FF01
-:10ED600012CA87A9756617A17CADA8D1191F6BE7D8
-:10ED7000E7F61B84FCE083B63C52423F8F6C423E78
-:10ED8000E6703E767DF0FC9B5B806F7504F976D86B
-:10ED9000EECF0D968CA62750979D46683D7B824707
-:10EDA00033B01E42FEF3D2145E4F11211DC1C2CCFE
-:10EDB0005092EFC4F591AD1E421CF1FBDD26A96B0C
-:10EDC0003346977B1E06731E54BF06E9ACE0BCFCBD
-:10EDD00081429ADAB0DD261CA7C39CFE6EF368461A
-:10EDE0007F09BC8F66D8683FC2E76CE4495A45C7C3
-:10EDF000E0A274A077BB698BC2F38E413D02FC2078
-:10EE0000DEB6BC15B346D37FF8DCBAB9D8AFD0268E
-:10EE10004BBBDF1FA4FD35A07FCF642CA6F59C1F44
-:10EE2000B479543AAE7BF8F3C3A1B60C0F7C37909B
-:10EE30008DE3F9C856FAF7D5A9F9F1C8822F1786DC
-:10EE40000C28E7B4F263F0FC89223A6E1D7B353F53
-:10EE5000F46B3C7E7E9FB723EEB3FDD16A0FAD37D6
-:10EE600010F32BA017D983844C2A00BDE838E6861E
-:10EE7000F16D24A84781E0A2B42B593FFCAA0FDE14
-:10EE80009F52413E029E28F663841EA0EF6AA0D3E3
-:10EE90008BD747797B3F8471C4FE6D4FBB8AD27B91
-:10EEA000BE4CC37AF69BDBAB34ACEF62540579DC25
-:10EEB000C4E429C717DA6607FEAF27FEB00FEA25BC
-:10EEC000D8EFFFCEFBFF635E9F68A76330BB4A03AA
-:10EED000FA9A881FD4A456BDAF0BBE0F6C64F4CF52
-:10EEE000B8B75901FE5D715F3F5E239CCEDDF03DFA
-:10EEF0002D90DF1C53806FD3EF89E275EFB6B7BA60
-:10EF000080BECC9D240D6CC19E1A5B167CB767F148
-:10EF1000B43478EF0E52C5A7F620E0F7DCD54DFBF0
-:10EF2000B3B746433AF70E52FED372EEB0C70F7A2C
-:10EF3000ED0EFBF8D5EF87F2BFE4FC38CCDBEDE457
-:10EF400074B8C3262FD75C02E5DCE1305E23BC9F9A
-:10EF5000C4B719E5EE6E2E77BFB4873E077CCF1994
-:10EF6000245E42F5F9F087F5B9D0AEA85F2EFFD444
-:10EF7000E3FFF37A783F7990BC6D9F0DD7E85A682C
-:10EF8000EF6AE8871BEEFBD62A68A722A847E6456A
-:10EF90001B21C5713B95331C5C7A13DAC75AD42305
-:10EFA00061072A06759B9299A86735A8077BB91E49
-:10EFB000D40C46514EA89E1DB3513E853FA07A46C3
-:10EFC000E5EB70D086E3FD444C473B4C8AA3792B9C
-:10EFD0005CA3F5A8E3DC86B9C06FA14FA3EDC7FF22
-:10EFE0001BFAB597F62394C4AE89F684BEC9EFC761
-:10EFF000D5374F18F5AD83EA5B18F819B4A5CD04E1
-:10F00000FD6BB5A19E786BDABA98BE6C427DCB5988
-:10F01000CFE899BA26827A309EDEEDF579AA34A837
-:10F02000BF89E969C7E03BDB1C301E6B08B71317CB
-:10F03000BBE03E702FD36B59CF643DCC0CF4A17E66
-:10F0400016EC8C11B8FA7634A25CD356D250FF522B
-:10F05000E86107E861E9FF3F7A5823E671CA982C16
-:10F06000CAFFFA186178C8B30FF150AD8FE3A182DF
-:10F07000D76FFD2A7DFFA23D03C7F5C5C9F421DE88
-:10F08000AB110238E3CA7F5973372D5F9F23F0CF4E
-:10F0900046D4EF3AAEDFC7E011D59FAA7E85CCCF2C
-:10F0A0008672EFEEAEA6E54F0E103FBC3AE9531163
-:10F0B0004F750F12AC4FE8671DEF6F37BC07791B18
-:10F0C0002611D04F81236AB97E9FCC61EFBB2F12EE
-:10F0D000B403A2FC49A244547A7F9CCBDFF9E2DB63
-:10F0E000FF87BB90903F6F8BCD8ED2E7FF6E8B7DFD
-:10F0F000DD468BFE7E99EF69B81FE0E5FE83CBE924
-:10F1000020C70D27AE0DDDA450FC5349621BEE86CF
-:10F11000EFBC458FCC2550DF47330865ED57AFFE78
-:10F12000CB7BA4102869D383AEB85E89FA443D2F07
-:10F1300078434D0A1D8F81C8BB6E18BF0F0E7E34F9
-:10F140001BAEC49884386B3C3C1610E315EBDB0116
-:10F15000B883D450B9981F978BA9B1BE63886387D1
-:10F1600018FE22759B711C2A3D8C4F5D17CEE6C19F
-:10F170007747385D9DE7FAF2D01ED659EBE9B4F730
-:10F18000AF09B2FAF1FB80878DA3A0A75DD8074530
-:10F19000E025365E01FE7DB9D637690EE57FF909B7
-:10F1A000D5BF8D7E573EDC5F4392D89D889285FD0A
-:10F1B000AA18B0CA67E785E32AF085D2AB02BD95ED
-:10F1C000B13E95D96D2657012E5795B133167B2E3A
-:10F1D000DAEF8C9D699803F66380D9A7547CEDE63D
-:10F1E000FD38CAC7FB88D04F12C900FA7B28FD0F33
-:10F1F0008DF17DAD47B5D02DF4ADDA9961C1E70B46
-:10F2000087B325BC6FA5778116457E2D007E91D4EE
-:10F21000FCFAB6928DF52F1CFEDBF825DB11516F41
-:10F2200027F0B164345D04845BD0ADFE9FCFD74E30
-:10F230006E67A8BFD20DFA4AFA0FA8A08FB5AA81AF
-:10F24000F6A5E26625E248B02FA29F0BB95E4DBD40
-:10F2500048D06E980304CB1D8E31FB9F8ACEA35BF2
-:10F260004DEC5FD645DF4E98571719C17CD09BAE49
-:10F27000C97F647AA69C43FD322FBED7FB55CAFFD7
-:10F28000535CEF0E6FADC3EBCB5B9B912F014371D2
-:10F290005D0F54CD64FA562DEC1A9F4F4E70FB71E2
-:10F2A0009CCF33AF6E0DE1F357B66EE47C65FD592C
-:10F2B000C4FB1335AA0D18CF6E6711CEFB0B355367
-:10F2C0004BE65755C4AC7274CC47F18E0178EBA86D
-:10F2D000713DCCC7D43F46BCC2EB19F92E5F6953D0
-:10F2E000E6C4EFCF0A5CC4CBFDCAFF2CF3EB6ECEB5
-:10F2F000C0F9A02216AA05BED63629C4097C9D3EB7
-:10F30000AB318B3EFF7C93759C457D3D39EF4E02C2
-:10F31000BE5704825A905E6BA3B7683E57EA71E805
-:10F32000D1828DD7E1F832FDA988F5D798948E2542
-:10F330009E8246F44787351BD8C3463ACFF5A35E75
-:10F340007890CF62FE3895A3D64500EF0DEECF0042
-:10F35000FABB3DEA64B86E87C981CA51ED458A4F50
-:10F36000E78CD1FEB046794E2BD2A2CC5FA3F5C07C
-:10F37000B5C750F9F3208E470FAD179E77FDF5877F
-:10F380008D737300F7ABC89F00F9DAA9EB60FEF24A
-:10F39000DB91DF426F851C741B6C7EEC8959E7475B
-:10F3A000C4B7F455CFE0F76F5E09F323B1235E12C3
-:10F3B000F8577C7FC4B87DEF0AD03BA2FA0919FD4B
-:10F3C0007DF066D5A247E57EAB9ED5974EB2DCF7C1
-:10F3D0000CAEFBF15DD05E2C9DB517DE64A1F78805
-:10F3E000C1E6DF9E08C30762BE16EF0344D66FB9BD
-:10F3F0003F8B4EF9C1CE50F9043B53FD49A951430F
-:10F40000EBABC9513DA097C73CDBCE82BE7C10F868
-:10F41000F53760DEAD2BB1D2DF3138977DEF5591F6
-:10F42000BEF69CEBF1FEB0D72EFA6F2C037AE02FDC
-:10F43000FAFE08E97F7536AD7755C44AD78A6086EB
-:10F44000E57E73DD24896E6B5CA8FAE2068CEF2CF6
-:10F450002AEDDA914DEFCBC11415419CC961F92E0B
-:10F46000E0B4DE97437C877EB78048CF2F2EC6B8A6
-:10F470004E39C475C473E0A764C7E93DD221E6796B
-:10F48000593EC57C9D4A7EDB6D6423C443C8D0CA07
-:10F4900071E242DB93CEF744DBABC0F897739CD0AC
-:10F4A0006E6FCB80E795E798FD2443D949F18D3CF9
-:10F4B000EF13F2359423C14FE209939CF9C8C7A416
-:10F4C000FD127C69A5C37209F00EC749F87112FDDF
-:10F4D00096BF9F02FA4DFBB3B8E9408687CA5775BD
-:10F4E000CC86F2D561EC41FD6CF7AB5C1FFB2F25A0
-:10F4F000CA674353D529880FD2F204F4B7C3B80BB7
-:10F50000F537781DD35FAADFA88F01AA8F897858B5
-:10F51000C8BF2CEF03247CF67A68977CF4DA2AC003
-:10F52000C10759BBB2DE53BD433D3E4FD4547A8E22
-:10F530007AD943F532593B97AFE73613DA3F7FD09C
-:10F54000C570F7283D7FB56612B4E754587B9FB16C
-:10F550009E1FE1FA23CBF7687D5F6480FD3F6FC893
-:10F56000FACEECDD62D7BBAFCE66C52D7AFF59E986
-:10F570007BA0789F0A5049E8F178FAFEB7EA794A09
-:10F58000FD9DA07ECBCFB7D814A62F29F433AEF7BC
-:10F59000612CB7C3458A213ED6AEA4FBB717809E27
-:10F5A000B3788D5C3E5DE5F51267F80FB43F6BA94B
-:10F5B00053964959BD99F4CF808156737DA8775BE6
-:10F5C0006CFD53E0FECF2436E55A15FC067208E2C6
-:10F5D000408A49C8BD9424C5E7216BA8A3D5A2865B
-:10F5E0002ED968796520FA890203790FF101AEBB43
-:10F5F0005A09D954FADC41F963D0F2443B83788F3D
-:10F6000022201CA7E55C09963B8D28C6CFCBEC8356
-:10F61000FD426ED05F5BE379EF5A5A2F892A97AE8D
-:10F620008DF7F3297B24CF6F403F233FDA02F1A609
-:10F63000C774FF93BED1FDFCC426FC9FCBEBE7272C
-:10F640005456909F36C6CFB02DDD0FF12CB97E53A6
-:10F65000BDECFACFA6D36B05F071CE683E2A839439
-:10F660007FC007ED3F2F81BF57E16572A5FE593777
-:10F6700021BE425467E4CA2474ACE774B4A8E66CB3
-:10F68000E0B75ADD86FC390CE36F00FF72C8371211
-:10F69000E4AB52D5B17F6A0369C67985446D6037A2
-:10F6A000C61B0FBB463415C6B1EF12DADB164E9FF0
-:10F6B000833E37E6A61E2FB5C11F8BD271227F660F
-:10F6C000E37478A9552EBFC6E9FF32D0358F992152
-:10F6D000A8BFDCCBEC90FA27BD3992448E7708FEA8
-:10F6E000737EC9E50FDFC2FA2FCA7F87CBFD372FA4
-:10F6F0005FFE574F2D4A3D6E42DE95C1E3A9C6AF6E
-:10F7000039D9FC364BB5713AC2CA44F4A15265727C
-:10F71000A956D37183FED55AF9F86DCE8F55BCDE4C
-:10F720002F2A6633C8C3D54AF06E15DAA9E943FD1E
-:10F730002B847AE8F36B89790F3CA7EFBF01E5488A
-:10F740009DF53D7DFE2D7CDED487EB4AE279976204
-:10F75000FE23FFEE9FB05ED3FA9ECAE156784EE5D7
-:10F7600085A873E1B90FE9A172429C602FF6DDFE16
-:10F7700005E02BFDFE7EAC9F9CB17C6F070391CD15
-:10F78000AECA5C767D1CE48EFB993B9A4CE4AB4E92
-:10F790009AB91FCCE6AD057CDE728202C33CECD187
-:10F7A000715ED4D2CC48945EB33D5113E278934855
-:10F7B0005F18FCA8D5D27CDBB4C63ABF7C61BD75AE
-:10F7C0007E59B329CF72FFA57B8A2CF7A1FBAEB57A
-:10F7D000D4B76EE7F596FBF5BB2A2CF71BF6565B04
-:10F7E000BEDFF8E306CBFB2F3FB1CA72BFE9E95B8E
-:10F7F00093AE4B8AF9EE41DBDB9BC01FDB01AF12FE
-:10F80000E60B2DBEEE686338CCFA1D153F9F361F00
-:10F81000CA110C29C872AA49EB96AF8FE8CFDD96C2
-:10F82000F9F668B820C74B596A166806C6DBC26687
-:10F83000DFCC29F1F9BCDA47E76337F8E1C9D757DC
-:10F84000355EAE8AF457C3B8999AB59CC6D7590DA0
-:10F850007F0CE329F23AABE663F3B44CEF19D5958C
-:10F86000037689D6EDC3F555237B42EBABE3F68FE8
-:10F870005AC209F58FB75705FD2C4ADDAF05A531F2
-:10F8800015C89B68BFE2745A718F58DF5EC68A92B2
-:10F89000F282273280DE653E86874829C3374EFADA
-:10F8A0008FCDB38CFF0DBC7CF01E8F1DE2C8C11A3A
-:10F8B0002B9D0D1C3F513DD4C04E94174BEF81CE74
-:10F8C000D950CE8A93BAB93CAA1A5FE79E4FE6E3B5
-:10F8D0003870BD5D21F4B696C5278827F9FA77FD03
-:10F8E000302D84819888256FE06471513A7CB7ACE3
-:10F8F00095F81C149F3C386F9B6711D5FF46D3EEDB
-:10F90000AFA3A5ABFD2C1E5E6FAAB8CE7B4531BB65
-:10F910006FAC51224B287DF5A13E8CE735AE8F6C44
-:10F9200083EBB48D510DE990F8FAB82F926553E34B
-:10F93000FCCDE3FCCA137CE57C14767CDA26EB383C
-:10F9400036965AF9B59CF353E6F372CEC7E5121F0B
-:10F9500045FCAC44E3F22CF17119C7A1CE794563A3
-:10F96000FA758FF33897901F4D9AD784FD1899DF59
-:10F97000B8FCB6801D079CE7E13885CF7B55331571
-:10F98000F4836ABD0AF2B776E63E4B7C73C9885CA5
-:10F99000323A6BF97897E7BF8A71CDCE1C3EEE9470
-:10F9A000AFB5F3E372D83093E563ECE4FDEEE038F5
-:10F9B000BA9DC72D5BBC67D4C4B857C78CBE7C3F0B
-:10F9C000BD7FE942DF9AAF517A1AF3157F1DB41B50
-:10F9D000E271565EEFE1EBB6E5037D27CEF561DC23
-:10F9E000E7A59CA231E38802BFCBF250EE0FD6C050
-:10F9F0007CB224FA0B15FA5F1EA36C53002747351F
-:10FA0000C05F8DDEBB358C73E5DFA541BCB1367FB1
-:10FA10005F35B41B20A1DD5510F7CAB1FBA33E88AA
-:10FA2000FB8477BA419F4B985E6EA4FF12F552D0CB
-:10FA30005D31D8AC019D4B7C92FFC2E5A8D62B3D31
-:10FA40009FB904E52820C9D13D420FAF245726CAEB
-:10FA50008F8817E8E70AB91E26971F310EFFCEC719
-:10FA6000E1773C7EFC268F7FBEB1D587D75F6D2DB9
-:10FA7000C6E73D5BFD78FFFAD632BCFF358FCBBEC3
-:10FA80000A71568C930679BCB509EF7B79FC54C892
-:10FA9000E7037CBDA356EDC0F860833FE4F424ACDB
-:10FAA0002B3470BA51A4015F9414255DBF75CC3816
-:10FAB00084FC3B3322FF04EDC0CAC682FD0F51BE59
-:10FAC00038BE434280171D477FA15D45E5BAA1AE10
-:10FAD000C0BE01DA0BB769D7D3FA1AA2BFD08AE049
-:10FAE00079E375F6DB93B42FDA49D5BE6CB756D5FA
-:10FAF000A9921F2AD68F4261E8E7D458280AF40554
-:10FB0000BCBACF9104F777E56EF0825CB59C0B79B7
-:10FB100041AE5A72D93A032059901B9DCBA9281F98
-:10FB2000F05AD7D7754E77077D0EF476C4C65EF7C8
-:10FB3000167A20CA55686DAAC748DD3F397EB4538E
-:10FB400049EE8F5ED46CF89D1BFA4FED37B5851AE0
-:10FB5000E8198828D03F958A0DE8976110B42F19CD
-:10FB6000FE10B7B7D6F939AB2C18AC827239C4BFC6
-:10FB700004CC96D1EF05B951CB16BF0FF327294915
-:10FB8000B0C7E0CFC8FE7CE2BD8A262AECCA86ABAD
-:10FB90005C8EF1D7E022D47A1DA3EF7B03D6F8AFB9
-:10FBA000C1F95BEE3BF11BB097DFF3DB58B91CB634
-:10FBB0004E7ABE6C1DE2AD728EF71D6437964F27EC
-:10FBC0006D78DDC1F97DBEEC0C81F95BD5281ECEC8
-:10FBD000017A9C9130FDDE2DD96DCDB0F25BA13C58
-:10FBE0005903B87940B3F8114A19B3DF4EF0C3C1D5
-:10FBF0003FE1B824EEBF85C82560FE0471D24EBB3C
-:10FC0000D5CF12D7DF6ACC0FB1D9A5FCB6FFEBF97F
-:10FC100077FC33E59FF0FF46F0DBB13B09ACA788EA
-:10FC2000FC3E51FE57521C49CF7FBBC64CC2F72A3F
-:10FC30003BE3FB7576096F05E476D2C2C04F9DFAAF
-:10FC40004969CAE87A52B54706E68E138FDAC6FCD0
-:10FC500044CDC3FAC7F373A8BBAD58FC0EA7E905A2
-:10FC6000BF6FD4F75E9B454F47D3CDF8F359D3BB55
-:10FC7000903A9A705D2EEC7019C3892B7C1427D2B0
-:10FC80003F57184C4E4F572991ED28A7A6C58FAA6C
-:10FC90002B5BF23EDA25EA67E8F339FEA6F4B742B9
-:10FCA000BDB49E5772C57723F6C47669CEE87A82D2
-:10FCB000350CF790F0CF9726C60582545C8AE74250
-:10FCC000BDEC7B5AB4EB52323AB8DD0A96DDB5DCB6
-:10FCD00070C3BDA93C0A38AE24011F005F673AAC6F
-:10FCE0007C96EC5FCD28BB67B5B78BA9FC1EA2ED57
-:10FCF000D4A9CD8D35B4FC923DEB0EBE88E408FF4F
-:10FD0000C297B4DE53F0C78D80F6AC7885F8599E63
-:10FD10004575D887EB822B7214122900FAAD742C2A
-:10FD2000CE97FCAB1CB91FBB711C8F6A741EA1E37C
-:10FD300075948EE36EF47B93FB49C27F5B583084ED
-:10FD40007E92F0E308F7E33CF45F221EABE4E5AB00
-:10FD5000EEF169B07E5025C58F2B47F28109FA4933
-:10FD60000B8995DE4AEECF554AFE9CD0F79F0ABD1F
-:10FD700015FE2AB78737093FA93239BE10D70E2999
-:10FD8000BF8DE247B3ED32F4800055B4BD4632C2B8
-:10FD9000278B7C75155CD516A57CBDC99FC6F2AFB7
-:10FDA000299D9AB0E7C82786B797F3F237F974947C
-:10FDB000FF804741FBDE384E3C2250C6D6555E36AA
-:10FDC0001496371826AFE17A11A7A786FEEFDEB9A1
-:10FDD000D09E552EF27D7DD59939306F28FE0819B9
-:10FDE0002DAFB57C5CE1FBFBB2C14FA1BE7636AC5A
-:10FDF00067C8F1883E0899527F9CFA4A05A3FDF92D
-:10FE0000057C7CABFC04C47E943FBF808FEF8251A5
-:10FE1000FEBA1567BF1C7B07F3ACCE9728B82ED26D
-:10FE200055F031FA09629D26CEBFE3E84F05CA3E80
-:10FE300062790323FE08AB6FB9A8AFEC18E617DEB2
-:10FE4000EF3986791CA74FB0F5EBD35ACC007F640D
-:10FE5000A9C05794A35191FF5E007912ACBE28CF80
-:10FE60006778D9F96A06D84D9117D21948BE3EB7BE
-:10FE70005065F16371CDD7198E2BD6D9FC23EEC511
-:10FE8000F88EC8937AAA94F97BDFB68CBB5C3F945A
-:10FE90006FC2B85FB42438467E41A3C4678F6EC575
-:10FEA0001BE3E15AD14F990F723F47E98BCEE260D5
-:10FEB000ABEDE6747D72BC1D31DFC9E5573893E7C1
-:10FEC000CD549559E38E72DECC6A7BA804EAAFD696
-:10FED000949D993EB46BA84F472F1A8863CEC78E66
-:10FEE000EE8461ED196271CF4AA2F23C1AB311D6C9
-:10FEF000D3C43E871A1EA790E918AFFDCAA17EF4AD
-:10FF0000B3AB866335207F3705BAD0AE2EA37675A6
-:10FF10005212BBBA581DDC3909F4D7AFA07D78F96D
-:10FF2000ADBE9A494C9F313FD5AC2CD226811C786E
-:10FF300092C7A116703949A577F4430D70C344F5F3
-:10FF40006EA53E82836EB85434FE38A59287F3B115
-:10FF5000F35F4B161F15D7EA14E3BB8548FCEDB0E1
-:10FF6000C695E57A449C87A81DF9A0CFC2FF95CB22
-:10FF70007D5B67F1FE9E597790FE04BF4ED803BDAE
-:10FF8000ACCD80F8446FD9D8F3859CAF5645ACEB27
-:10FF9000CED54EEBBA73AB66FEA36EC1496B99BF6B
-:10FFA0005AB616FDD5E5250EF457BB66DD81FEA9D0
-:10FFB000F0AB5B6E3C807117914725FC5399EEDEE8
-:10FFC000DC670C28371EDDC28FEF74B03C20F0DBFD
-:10FFD0007DE8B7BF8DF94572F9430EC6AF2735F3FB
-:10FFE0000740FF4EBBE95D0BEB87B31CFE27938CEC
-:10FFF000C31B0EA6DFBD29D6514FC382C664EC07D2
-:020000021000EC
-:10000000F2419E6F841F2BF60D4DF532BD6DE07EE3
-:100010006C45C95AD4C72C2FF55B816F7EE6B79229
-:1000200041AB9FBADCE8CB83F197E73B7588FBB522
-:1000300013F45B1F48637214F210A797BE4FD328C6
-:1000400034A5F3E82E75D173C08F07B208FA03A761
-:10005000B3F4C8FE24F18617B9BDAB553759E4ADEA
-:1000600092E312BDA6DF8078C0E9A1B1F3F21E923F
-:10007000707A6131A972B8E11AAB027ED07BD3816C
-:10008000D718E64B7F77D686C264F5ED6FD592CE52
-:100090004B6FF1715BC9E7BBAC3A169FDC52A263B0
-:1000A000BC776ADDDBC7514E1BB99C2E7360BF7BEA
-:1000B0006769382EBD3716B4C17A65EF2C27E6275D
-:1000C00074CD7AE1ADBBC1AE96297CBFD9468BFC1D
-:1000D00056525C9D0EF57B55C42B5BA8FF920EDF3C
-:1000E0007BED0CBFF03C90CD7C4C4F1F64F8E64399
-:1000F000816F381F5709F96F14F1502B8EA2E6C497
-:10010000B24E43F8FAC312562DB5534C1F3E6C64E1
-:10011000F1CC2DA2FF870EEC043D6CE072D475612A
-:100120008317F5F5D0018CA7B5CC5A8BF1A3AEDCC3
-:10013000B33ADC6FF6BEA7C3BD8C33C4386F297BDE
-:100140001671482F1FE7CD1077A7F2BFC4CBF0552B
-:1001500074CAB5769F11CF6396F1DDCA681AF67F2F
-:10016000D5451BFA9D2BF9F747A6FC4987EFB64406
-:10017000A91E53FBDEA0F5CF00DC9221E1C50F9F45
-:100180003B900FFADD33FB8F58EE8AB2B75B80EEFF
-:10019000696507308E9F77E8407736AD7F7931F11A
-:1001A0009BBED1EDD7F2F9694B0EDB07B1C51F0934
-:1001B000C33EB00F8608CE4F0B9F3B56ADF892ADB5
-:1001C000B79804708858AFD1BC7CBD83AF3B908B8F
-:1001D0009794C4F16AD0424EB0BF2D65AFBA81DEAC
-:1001E000C283EA5A90EB9AE7AEFF22C81FB9D1E169
-:1001F000B992F6E703CFAFDD5719ECFD1DACBE0594
-:1002000021CA8F869203F91B668DB62B237A53F28F
-:1002100097AD214AC7E9A52FE4035E7B95DA5B1F02
-:10022000B4C7ED95EC272D94E6D3C090B4CE24F559
-:10023000D7A5ADB8D1310FC6F347DE820479A2FA53
-:10024000BF0EE8DFFCA8D303FA9275E8155D05BB85
-:100250004671FB920479DECCE5A5C16076AF6516E8
-:10026000896C5740CEDE6BAC007D7B5165FB500E38
-:10027000BDCDF23EA579A197CF1742AE7B73DF715A
-:1002800083DC7D7890EB47D8A624C6918CB2D8CD7C
-:10029000301E823F1D929D0990E4F3C22907C3A935
-:1002A000951A7B6F50BB0DEBD4F27B13FC28C04139
-:1002B000DC9F12EFD73B18DE15D7CBC82BF8E177C0
-:1002C000A8BE77ED3AEABD1DED9381787DF3A103D9
-:1002D000C5B00633E5E0811A9EF78DFE98CAFB395A
-:1002E00095F8D03E2D379CB87E20CBB7BD6C5F14FF
-:1002F00060B3989FC111D7A6C4ED869A187F48E2D3
-:100300007F91B0F9DACC843C2C3AAF13B01FD55EA4
-:10031000167795E524ABECC04E361F50294C58C7D4
-:1003200095E5B6C10879617D9AEACDFB6C3D93CE27
-:10033000531097501BFD389E5C3E6DF41FCC7B190B
-:100340007EAB7CDA8B750B4E91E978C4C1D7C5388A
-:10035000EE17F37296B71FE95B6EB4E543FB53BD2E
-:10036000FDE86751BB9E0F572167C24E8FC8DFACB7
-:100370001BEAC14E815CC392F7E9B2EBD3C1DE3513
-:1003800078193E21521CBDD73BB69FD12DC9E369D8
-:100390000FF3AB1ACA48BA2713F49DC59B7A1FCE38
-:1003A000DE9791108FDB630FFDAB6372FCDE5DF2B5
-:1003B000F97A8F1BEC0BCBC72AA766CB5E148F6331
-:1003C0008A78A958BF13F1D15171CC922ECCD7B2F3
-:1003D0008B3C0ABE9E372A8F6782F9678EED6D9A35
-:1003E0009FAF93200E6BE4F1B7A1B9E3C441B70905
-:1003F0005C76DC31797C5CF628F72BDF00E341AFDB
-:10040000B7383C783520BF8492DA9B961CAF1DE04C
-:10041000F8E572F4F3840ADFB176DE7458FD4AF130
-:100420003C8E83991E4C2D3BD09D88832B5B296F7E
-:10043000E838E9AD6406C94C2D77CB47ECDEB3163E
-:10044000F91AC1C5E3E061215F83AAF967C7BCD48B
-:10045000E51A381DA9DEB7CC723441FE142D47A62B
-:1004600066B2EBD5F4DA3DFB40BE8D3E3F09B82BBA
-:10047000818EDEC70E613F5ED6D9FE97DE0B1B0A6A
-:10048000611EEFD24CE29C3771F991F5C939CFF476
-:100490006DA3FAD799EFC4FD7E9D5E86375E81928B
-:1004A00009F2B45E0F799C93718A304936377242F3
-:1004B000CEC168D64C6CFFD66D19FDF70413ECFA6B
-:1004C0002E78958BE70660BF1ED4FB31BFE6365A07
-:1004D000BB83B673CC50A7ACA3F7454E66F78F85A8
-:1004E000ED16BE886B9193C9DD7A3D58047492B6BF
-:1004F00066D4B3B58A1A04FD27FE89C5E576B4270C
-:10050000CF132D8DD73F07EB3F48EB07DCE0E771BA
-:1005100077E2999234CECEFB1D25A40EF4E57B59EB
-:10052000563F739693E9D99C78FD1589F5CF7132C2
-:10053000F9A7CF17E0F3A7D9F35CFEBCAA88E5A919
-:10054000093E8A7A6BE3F5D5E27787D877939D7C6D
-:10055000BD80D32DF0BD9CCF74431A1B8F2AA17789
-:100560009A8278BB9CE26FC4F7DABE6318BF73F25D
-:10057000FD91690E7CDF916B477CDFF10941FCD96D
-:10058000E962F1C8AE0B676FFD2ABDD78689251FCA
-:10059000DCC165481B7A0AE36FE5F97C3F1BD7573E
-:1005A000B16FEB486CBF655D55ECF3E974F23C0C40
-:1005B0005EDF025E1F9170BBE897C039ED7C9F4EF5
-:1005C000B9E8DF407407DA958128F6ABD2C3D68349
-:1005D000BBB2BE81FEF503179ABD8971C1AEE9C7F2
-:1005E000D9BEFD7C4A77499C2E8DE3B1F261DBA632
-:1005F00003C00F4DC18CEDAAE88B1905B4FF8B4EDB
-:10060000A8FE34E8BFE4672CC9E779D41CE7A6C28A
-:10061000F5BF54623F80FA6D19178B80FE2353FE9D
-:1006200055053C5A1E7D43059C5EA9B1BCDD851273
-:10063000FE6887F33A809EBFDA2236DAAF9EF3EF88
-:10064000A9307F5C311CC17E4F1BEEC3BC89BC014D
-:1006500016DF5D30534985EB7764421E868FED735C
-:100660002DF7EFAEC9867A87F8BEE5D8F94940D7AD
-:10067000685C6FC529015F15F67B04E7E7B3B8D264
-:10068000E5E2E94AEED708BF408C3FE503EEE36AB6
-:100690001FBEDB09F36315E76B61BE8DF907D30B52
-:1006A000D7A07FF089EE817CDF073C5F77A27F4097
-:1006B000DF837F5009FE4126C4E5FAF236B846F7DB
-:1006C00047C853E1D0C75B43B4FC11FBEB79806BA7
-:1006D0008F5E782A0FECB2C80B17B85E9477695515
-:1006E000CF83BD16790802E73B04CE8F3513D8CFF0
-:1006F0005F396CB3E07C0797AB4A83E955FB5F0930
-:10070000AE7375BDFF5E6F01FDBEF34516879E1A81
-:10071000EB5713717E39E777E7277D78FE8890FFE6
-:10072000CEF7D939221DF97C7F0AC7F98B092BBF77
-:100730001870BEFBF271FEEC3466774C8EE317F353
-:100740007C54F1BE9FDB7119DFCBEF2F17DF138EC7
-:10075000DFE3B8D82AB75DBB0A713DA5DCE364FBD3
-:10076000CD0662CFDE45AF5362A127F600BF2FA6AC
-:10077000FBE13307F7BFC6CDE794F0FE5412D79BD9
-:10078000287D9495DF8F7A5249F504F6938FD2072E
-:1007900019FFE7C78E41F90584E955F57088AD8FDB
-:1007A0008D83F72B8DFE3CC4FBC38BDF677EC3D8E4
-:1007B00078DF94F297EA663AC6F64FD3AC786C814C
-:1007C00088770C37B378E47033C623170C717B79C4
-:1007D00081D94B319E0F70B913F65CE867E785B39A
-:1007E0006A28C16E8EC8F730DB872BBEEFCC6778E6
-:1007F000FF275A1FEA73E7D0DCF4C438958CF73B27
-:1008000001EF97401C89E2FD39A0BF04ED5E27E0AF
-:10081000FD04BDA578FF9AB404FCE61E5A5DEF8185
-:10082000F5E009E613083F7631F8B1D909F152A78E
-:10083000D58F4D25DF67F9FC1DE7671F9B7F86FB82
-:100840008E25F253E3B8D60178724E7CFF7A672A80
-:10085000BE7E62DDC72CF2B53B8727E637515C5B75
-:100860009F363975B94A4E47AAF70F5CD011D702A7
-:100870001E9F3A875DAFA6D7EE8FFBF212712D3126
-:10088000181EEB7CEC37B83FB8338BE2D992443E6C
-:100890006F1B077FB0FB055E3B5F87B1E20922CD8E
-:1008A000FFED2E260747291EC1F848DAAF908F1DAD
-:1008B0009F9CC5F6657C22F0888C4388843F04BDEC
-:1008C000EDF98CEF476267BEEB877D7327C43E531B
-:1008D0002B2E91F9353E1EE9437B2ECB7987CBC475
-:1008E000BCAB383ED1116F3C60677843E0138A3B64
-:1008F0008EAD05DC3140481A89D32F708AC01D6245
-:100900007E6C1FE6E72D79F8BC20E19411FBFF29EE
-:10091000718AA847C629723D9D3CAFA39DE2966DA2
-:1009200088638EE33C3B51FC22E395F17049E54C32
-:10093000864BDAFDEC3C268167645C52E7EBC23CF7
-:1009400040815F268A5304CE91F18A4C5727E09765
-:1009500092387E91F18A2C4785F9642DC4F7058E73
-:1009600049A59F50EE0E771CDFA42A47ED33E29E87
-:1009700094F50CC52E17F7FC1AEC4A6ADCC3C6B90D
-:10098000F222C13CA05478E4017F3F3B8F489A3764
-:100990008EE49F7913F7690EE83E157111B5934601
-:1009A0006A3C24F46EA4BF60074AE2F3524ABE0CCC
-:1009B00070FDC81F7BFD65A27849CC17B3D3D87CE6
-:1009C000906A1D323D9DE1AA070B997F2CBF8FE7EE
-:1009D00095587113C99985F2FD55BE2F39158E2290
-:1009E00024E66671A930B683F9E480C34037E7F3A3
-:1009F000BC024A6A70269909718D20BC8775AC7952
-:100A00004A244C495B01CFE9B856D5B075A033B341
-:100A1000D83913A7AB1C38AEA73E6479875D2E1674
-:100A2000573D7D5D9A7F3F25E143A897CEB767D2BA
-:100A3000FA4A615CA78B7E66B37E2ECB886EC27548
-:100A4000F0EBAFB5850B46DB8707D3391DD906AE72
-:100A5000A735F0F814AC07E6CD1DBD1FA035BD00CD
-:100A6000FB0DF9EF79B4DC4E5BDF770BE9A3341BA8
-:100A70005B3F95F9FADB7445E4EB841D097C689CC7
-:100A8000E934D3A83CA67D8EE50374D638709D2941
-:100A90000D96CC69BD0F1517BA92C987E897FCFC73
-:100AA00061DEEF33D363787EC6CB3C8F77B3A68409
-:100AB00081DF6880617E9A346DDF43B4E8D274765A
-:100AC0006ECCCBCFBD8271A197B2381F4C05F31508
-:100AD0004EFB983E853D4604F655D2EFEDABC7D0B0
-:100AE000E7BEAA25C51C8F1105D6C9E08FC2D1FC6F
-:100AF0005E55A762BF577976DD05F3C699BA5733BD
-:100B0000E0DCC7E54336027AB7CA537E073CEF7292
-:100B10003139063E03FE5F55F3F9AFC0F3C646EB2D
-:100B2000781C4C2F44FE56686C3C60FCF2E68E6EDE
-:100B3000977848489F92C0FFC00BDF5412D62144DB
-:100B40007E8A3345BE5EAA7E2B8976578DC719A74C
-:100B500096EDDB0DFB5B82A5ECFCCB061F09C37A8F
-:100B60006E839F440BB87C61DE4CF74CB6AF87EBCD
-:100B70005756D9BED642884B0E696C9D599A5F2A4A
-:100B8000E858E567439C9C8DCFE9792AE2910AC831
-:100B90006BC4F32B197E6F30D722FE6F7CB87B5766
-:100BA00021BC57F36BAB7C6C1DD492477588C5DDB7
-:100BB000564872EE92E2FA157E290F90E7EF75160D
-:100BC0003FE101F979309BCBCF5C05F5E815C5F71E
-:100BD0007061C23C7363BAF0CB88CF9E201F23F2B2
-:100BE000C0C757E67B2A7ECA7C92E542E6F7699742
-:100BF000C4AF14FC4FC5EF8AB2AABF2B7F3FB03BF6
-:100C0000EC20B75DF63FE6B37815B5C109F644E6CA
-:100C1000DB0786CF0576E2CC108B87BD34DDF74548
-:100C20003C8F8AEA319E9FC9F5213E0E541FDC8914
-:100C3000FAFCFA0CD0672A6776A8A7D154CC34D036
-:100C4000BF830FDC85FD063D75C7F548E6FF28FD2F
-:100C5000A3FFD304BD45A3F548CE0FFB5BF5EF4ED4
-:100C6000B0E7946F73D37D7815F6B49178BE98B8D9
-:100C70000F55AC937715B40461FF78C3808DC07CA9
-:100C8000D33EF48CB60EF6A5D62938AD19A40FE9DB
-:100C9000355A59FEC3558FDF4B203FFDE1E9C40FA4
-:100CA000F6CA6865F910F43DE64308BC2ECE4DA4A3
-:100CB000EF4DE687B376EB79BB2EBF359F67E5E056
-:100CC000225C4FE82EE6F148EE37883C5622ED6371
-:100CD000698127B9F1FD1EAD1722E83FB4A7D8D727
-:100CE00022AEB21F205F7B8EFEEC2BE00754CED4E9
-:100CF0003D00292A87A24EA8EFBB2547EB105FD500
-:100D0000291E5867EBF9B86D07A172B4B2E49DA42F
-:100D1000B8E4F0073FF4433F0EDB77FBB3C13E6C12
-:100D200067F356DAD525D3D78D817B427555750586
-:100D3000B353E78DDC9AC1E7F7AE3BF73F08EBD939
-:100D4000833AC643EB393E6ED07637ADA3E3D9BDC7
-:100D500054F16FA3CFBBAFD9D37C14E2C8EFEBC083
-:100D600071D27BE1A97CF0234E3EE66C82FA7B3E99
-:100D70007EEAC7983732A8CF87FE8ED07FA5C1DE26
-:100D80007FF8FC09B0332B8B5796423B691AD90D7B
-:100D9000F274C550DB9B70AE41C3803E0FECCFCAEE
-:100DA000BA7DCE7F003ED53DEBBC925EA70DF96AC1
-:100DB000613C33D243733228BD792505F7E7403BC8
-:100DC0007EE23791AF7D04F8BA528A3F5672B96914
-:100DD0005F5AE04A8C639C192A74617E421DCF4F92
-:100DE00058AA06C10F3EE3B9D28571C73A9697203B
-:100DF000F36B25C7E92BEB0AA627C3E385757F4173
-:100E00001CDE7E8DA32919BF6FE2FC4EFBD386FD4D
-:100E1000D0DFB41F393D00AFD352E45B6667F07C8E
-:100E200052EFC4E22002CF50BE3AED0971108AF7AA
-:100E30006FCE4888AF5C6EFBF519CC0E0CAAA12FC3
-:100E400001FF2B781C64BCF843F938EB6E548E908C
-:100E50004F2B797C62A5884FD4174CB7C42788E9FB
-:100E6000053B7B06D6DDC0CFD6566C013A7A3F6093
-:100E7000EB6EA9E477E5CCA76E3D9A60EF7AED269C
-:100E8000EE97ECBE86F949FF55F23B226775CFB667
-:100E900096D2E70F95AC9C0CF62F418E5B613C2EF1
-:100EA000578E65FEB52F2D7211232ECF428E47CB64
-:100EB000A582FEA890EF54E301E5C01F5D398E3F87
-:100EC0007A66E9D549E53F5ECFB931F5A086CBD545
-:100ED0004D5CAE2A89E9C173A9F2DE44BFF557DC47
-:100EE0001E8FC889AB0FE341E1279DB83EDE7941F3
-:100EF000C7F3CD3B9FD8F8139837BA871679DEC36E
-:100F000079BCCAB38AD2750DF80F25383EDD5A4236
-:100F1000BCFB8D0CB11E6ECDDFFD37CF1FB2ABD841
-:100F20003C6B54517ECFE1F3C4E70A9E4887F97CBD
-:100F30000ECFA39FDDA1279D973984202539AFD8F7
-:100F400000FA971CB4963346F691B7D960DDEF737B
-:100F50004F4BEFF9FE6739DFB13723F9BE6731DF59
-:100F60003A2F8C1D47FC39F7AB9FE6F9BCFFC6CF83
-:100F7000ED6BE3E7DC3E03FB56E9F520EC5BA5CF28
-:100F80009F877DABF4FE10DFB74AF227762EBB3881
-:100F90008749E77C68CD8D58D607C53EEDF652955A
-:100FA0009D53E1D5F11C548A9B6C987FC2F1A22D10
-:100FB00023E0D4E9B8EAFF4130FFE4EBEFF7A13CCE
-:100FC000ECE2F3AC8C633A243911573DCE470DE285
-:100FD000589DD3434DC1123E602037F3A6EE7B28C7
-:100FE000014FFF2F2E172DDC6F0B5F209127957877
-:100FF000F9972E90A71E421C45C22AE00EF88B8A54
-:1010000070FD00411C575FFA00FA5F80030197E111
-:10101000F96085101F7D1EF15CFDD0FC3BF8FAC124
-:10102000281C37C23715F9C4F079E92B1827A91FF6
-:10103000482E6FF1BCA5A6EE9909FB0C1A87C43A9D
-:1010400005A5644A7C5FB92EC9955C4F56A982E319
-:10105000B2AC98EDFB12EB1C623C7734F7617E4733
-:101060006FA9C307F1051927CA385F2F65FBC2B402
-:101070001BD9FED4FA0B2CCF1005664AFCFC349D1C
-:10108000E7EDB67B427E38AFA4C12FE1DE189BF7B7
-:101090002A8BAD785EC6FBFA802EE1FD309B0FB740
-:1010A000B3F13CFD21413FEAC9BD2C3E70D8EB6352
-:1010B000F24722E8F72CF4DAAE7BC807EB526CBF9C
-:1010C00065F9103B6FB37CC087FBA7170E92E855FC
-:1010D000B3213E4A5AF13C20897F0B095B7758E8DF
-:1010E000F5754F86F8A34676C23930539C6B4DD0C8
-:1010F00003DDDB8CFB6BAA9D0A9E934DF8FA98E00A
-:10110000AF9E7E6A07A8C0429ECF277E1762AAF3D1
-:1011100000CA813E4E5C56AC7FE95CEEC47A56153F
-:10112000AFBF6A90E5B1C97290E53CF7269CA3BCBD
-:1011300068C8C0753179DCE5715D64C4DE7D04E2A8
-:10114000F617D2FDDB619C9D6C9CC538EA6A870A64
-:10115000FB3588C6C64BAC7355CABF0F21ED8393D0
-:10116000E912E71F7CC590F685711CBF8853D79A9A
-:1011700076C0B2BE22AF031CE6F9083FD1D839A22F
-:101180008707C75EAF3ACCD7AB886782E70EF2F32A
-:10119000022ACA483AE09C8A41C2E4EB615B2471AE
-:1011A0007D4BDE27EE1E5C5D8FE7AB793C789E427F
-:1011B00005A1D7523CE715F31B4D72C0B21E6772F2
-:1011C0007BAFF3B898AEB07E093EC9F4DD3664F566
-:1011D00087BE18B6EE6FB8F55EEB7E8C5B9AF32C8B
-:1011E000EF976C2CB2BCAFF55D6BB9FFBCD77ACE74
-:1011F000CF7F0B59CFF959D5542D9D63673DE7E754
-:10120000A63AEB393F0DE6AD92FE9AD67507A58F4B
-:10121000AF5FBC5534569C37617FE198E7FEA01F55
-:1012200098645F8BBC3FF1AC21E28D563DE80E57D0
-:10123000B17371067C7BABE8FD51E2D7D0C1E5E725
-:10124000FF887D7BB55EB69E337ABF1DA34BD84128
-:1012500079DF8F38B7AF62B00FE5A0523E9FCF9BCA
-:10126000FC7CBE570C8E17C4391729CEB318357FB6
-:101270004FB47F7C1D6FDCFEF176CB49DF3138E760
-:101280002355FF26DAAF91BC2D383790F2A30F1EFD
-:10129000E5B2F706D5B79D59C5789E85DDB92866B4
-:1012A0004C8EC73B8979FDC4F66DF3383E31578DBE
-:1012B000539EE9BDDDE9637261327CB45331237022
-:1012C000CE5DFC3C0B827640E7F3A97CAE45DA4E5E
-:1012D0006296501685179128E28D42676407AC83A9
-:1012E000E6B27DA32DD7D870FE693967EE86FC93F0
-:1012F000D66B34DCB758AB1A585ECF67F35300D6C1
-:10130000A0203FE2A4D964398FC3BBDD037AA2FFDA
-:1013100098BD4FD59F8E5CB63E2C3F2F72313CD48A
-:10132000A505F35C281FA697AD4744F0DC32916F0A
-:101330009B2ACF9602470FDA6D22F0011BBFFB619B
-:101340003D2589FEFA5D4CCF02254AC40E79A337AC
-:1013500093887D0CBFB2C36B4B1ACFC875F1B8E848
-:10136000C54B781E9D2ECEC7CB63E7E37549E74E8C
-:10137000E6F27E1E7039991C143CC5F6A34AE79428
-:10138000D7FB3690443C5BCEE7193DF60EC6994E2E
-:101390000F8C8DC3C5FAD32EBE4FB9FA822D988C0F
-:1013A000FEDFBB3496176CD893F66F3DA7B7638604
-:1013B000FFB5209583967FB6E1F9D2016FCB34DC7F
-:1013C000C7EDFA07C2E25D8CFE7AAEA7016F640733
-:1013D000A1E31788BEF128FC3E875EE6C0F5E7D39F
-:1013E000D7507C426568578CE2C58278FF5C7CBE32
-:1013F00009EC3D5A5754CACECD8778CF9201964713
-:10140000BEBC6C1F3F77A51FF725CABF0F525E17E2
-:1014100032615E5EDE18DD81F8C7EFABC2DF0B2103
-:10142000FE6D6CBD50DE3F6920EEEA186272DFF19E
-:10143000537F17FEFE8657E046B3B1764AFC7CAF79
-:10144000CA734777C2128C7CBE977C8E90F0CB74A7
-:1014500009570A7FAC81448E69CAE838732A7FEC49
-:101460009F5C1C8F5C43FD313AFEB73958FE6CE03F
-:101470003EA50C9CC6B4FB945CB05F2D7C9C5EAB1F
-:101480000C615E404B8AFD747FE472FF5A6514F76D
-:1014900029751484BCFE31CAE7BA542CAF5F64E7E7
-:1014A00078E84E96D73272E5795C42AE0BDD0E7667
-:1014B000AEA19BF9DB0B2F3D9D37D6FC591E0811C1
-:1014C000E80FB52F49F365F689F6A3EC3C0ABDF5A4
-:1014D0009D9A64FA2CF470BD1EFC890BF61D2ACD72
-:1014E0009134B403133F7F728EFAE9EDCD9F0CF374
-:1014F0001968FFA4FD5F7CA01F3B42D6DF7512D7A1
-:101500009346C889FCF71ECD007FF377E9A1C3603D
-:10151000F720DE0DFB053B62CF38D19E4A7C97EB6E
-:10152000B9CDCDC653F7B1F7E437A66F65429CE459
-:1015300006371B17BBD3EC81FA67DACDE340DF83B4
-:101540008B92AF43BAB44527A1DC7546F01494EBF7
-:1015500088EDC7F8F12769E64BF0BC54334FC375EB
-:101560008FDD7C99D9E91ACF7BC5F17D0CA9C6190D
-:10157000162EDE2B4EE4D7A7E3B3DD19EC87F6E990
-:101580003C18322E739CDDF45A07730BFDBEBF323C
-:10159000F97A7B0B9727AA67989F25F6B904BCC4F4
-:1015A0004C367F89F274FCCF035D0FEAE120ECD763
-:1015B0003A3DCD46F627D839712E414B8CF985E757
-:1015C000EF51F633BF90E0FD4FEF2CD80FEBBB3758
-:1015D000CFE07ACCF759DC7E8F75DFB368F7CA4C61
-:1015E0006542FAF9CD4C260777673AF0BA2D93D1C8
-:1015F0003B61FDCC61F5083DD535765DEE61ED9F33
-:10160000E1F57FCCEFA91EE6B8991EF6BB2E6F7CE4
-:101610007EB8AAE8D3CB87D007DD6FCD33FD16D7D0
-:101620000761AF289DD7B8518E9A43E99747E79451
-:10163000F2CF408EC57E033543B1C4C303DC7EDEEA
-:10164000E416B8C8AC7433FD5D00D731F477919BD4
-:10165000E96F8DDBAABFB56EA6BF8BDD4C7F97B857
-:101660003F85FE9E05FD81FC3C1EC727A7AC768703
-:10167000E2E255D07EBDA6F07DDBE40F4A82FF5149
-:101680003F1022269B2C9F48C40D14BF9AB85FE3DD
-:10169000356B7D3D7CDEA276EC4B506F0FD7DF1DA6
-:1016A000BF65FC033E3E93442F051F55C75A2FE4E8
-:1016B000C5A79AE7026EB6BFBDCAC1F6539013B470
-:1016C000FD5996FE6C067E8DF4274C3DBBE4FD096A
-:1016D00027ED4F9FB5BE84FEDC0BF58AFE2CBC7453
-:1016E0006A4C7D0C087DF4445598B7035AF279A1F1
-:1016F000DDCDE6CDDF67983BA17E59BEC475179757
-:10170000AF54FB5EBAB445BB80DFE51AB383C4882F
-:10171000F6AB09FD2B2F5E2BFA1DB225C6D906921A
-:10172000DBC947DD237AF728CADF5EB64F87CAF5E3
-:1017300063D0CE6D933CAB715FD747CC6E9EFDEB13
-:101740007D76F89D94A69C3DF7C3F5A49BE5BDACC2
-:101750003D57E88661E8AF64FB1D5B72D9F9682DDF
-:101760008AF59CB4937C7ECCCD147EF5C4CF11C792
-:10177000B392FF4EF31BE54F07B74BFD69459767E3
-:1017800097E67D06EDDF3C83203E6ED9A7E33E035E
-:10179000A137B7C1D8B2730D4CC8A3F812BDB7D1E9
-:1017A000FB7E70BA291DA17C42BC73B15C58C77323
-:1017B0000FCCD7983D327F0DE34BEDD0596E875E4D
-:1017C000877B6A877EF369ECD0336EA637AD54868B
-:1017D000FA400EB508DF8FC3FD11DED7F2E2639643
-:1017E000B89DF0A73A06F61B61C81B2C66FB4F5349
-:1017F000B52BF205C7FB3D82AA7F5EE70427600791
-:10180000C575104715BF5FD701ED1BD09EAD11F810
-:101810007A92A8B80E2FD7D7329DCFFB2E2ECFB9F4
-:101820001BD0BF927FBFAEDA1BD93597D613387164
-:101830003B3B2FE1E2ED64F52CC0272102E76AEA89
-:10184000F40AFBDA05DDAECCAB2CF1409D28DAE2E0
-:1018500092B81DA98E91E8C252C437B87F0BEAF145
-:10186000F17A42B360BECFC273564F1627CF4FD81E
-:10187000A58672322727F041FADD0B3AFE93E13D4F
-:101880001DFF2999F370FCA766B279C80BF7BFE179
-:10189000E3B84B0DE6C1F3500E5B82A6E5F379F990
-:1018A000E9999F819CEC20EC776F417E13D7ABF7D1
-:1018B00070FBF0B3C9A11268AFE6A72BBAA7D14F4E
-:1018C00036B5ADC5738A175E11FBE865CA1F92A7CE
-:1018D000E37A60CBC3D679E4071CFFFC3C53ACF73A
-:1018E0005D1E8EA0F6EFC64CA48FD9BFB097FDBE8B
-:1018F000E7DADCC2EF31F8481DCC29F1736A6B3CA2
-:101900002B6AE0F70ABFFC74C15C38D74AE7F67966
-:10191000B1B74B5F07E30ABFFF94C49E378ED8412F
-:101920006ABD2DF354F2FCD42F65B2F993EAF1B2FB
-:101930004CA6BFCB81CE7D93CD9B32E7FDFDECA3C2
-:10194000B043218DD91BEA3785C16F5A3DDCDC03DA
-:10195000D35413D9530BEB1B542E3700BD5F701EAD
-:10196000E8613F9D129E06ED5279BC83CBE3462E83
-:101970005F777279FCF2A7E9D76A687C5E6AFC2916
-:1019800070B8C0DFD4CE7F2B93E1649FFBB399374F
-:1019900076F0FA42EECB9C376EF90CDAA778E3FBCF
-:1019A000C0C7924C3226BE7D94CBD5639923F8F6FE
-:1019B00031F86EA1D37C3C33116F949CF803E4C9D9
-:1019C000C5F14697CAF1869618CF0E50FCC5F3EACA
-:1019D000D6DBE6C7F5448F25C7216599237ECACF9C
-:1019E000D0AEEC6238A46C846EFF4004F4701AD759
-:1019F000F737983D5EABF7AF07FB7C3E8B7D1FCB87
-:101A000062E3F81CAFEF6DC59534BEF942E608EE0F
-:101A10007901DBBB8FB5A7665CC77EB743D815BB22
-:101A200082ED88F87059B6B59D79D9360B4E95DBA5
-:101A3000E98EF7AB1BE5F81EB1EFD7EC81760371A9
-:101A4000BE4613F90AF6C5363F819F1CD7A5C27161
-:101A500009FC7B05FBD3CADA19E15F28B99DC5DF14
-:101A60003564B8F475A02F957CBCC5E5E37771F9B2
-:101A7000F81D978FDFC37737CF60E370DB24EB7EF1
-:101A8000F277F977F7723E89F192E9FF7A362B37D0
-:101A9000C20FDF892712716DA0386B7513C42D5BDF
-:101AA00055BFCD375ADEE87F336D09F6581F88E001
-:101AB0003C510FF296C4EEFE25CEAFBFE0B8D43055
-:101AC0007E75A5F0E3EECC66FDBE257F5FCD646834
-:101AD0003F7CC9F27B2D5FD8D8A526FA09FF1BBE33
-:101AE0005F0B5400800000001F8B08000000000006
-:101AF000000BE57D0B6014D5D5F09D9DD9D94DB275
-:101B00009B4CDE1B48C224040D1A708110A304995B
-:101B1000BC780688BC4445591E86F04A22624BAB0D
-:101B2000FE2C2684A76DB43EB045BB2054AC682380
-:101B3000A64A31D00D08E2B3A1ADA2B58F2008A806
-:101B400008216A5DAB7EFCF79C7B273BB3D905D4AB
-:101B5000B65FFBFFF1EB77B977EEDCC7799F73CF08
-:101B60009DBDFEC3E373350721E7E06F44B0AC4A87
-:101B7000B010924C48FD0CF741359F10AFCBE2DE20
-:101B80004A7AF65B1E2F63BF51D93E298EF67BE35E
-:101B90002C5136D37E374C11345F1E21233B89E60E
-:101BA000A3E37F192F103294104591B0FF1509ACB3
-:101BB0003E4AEE985B1966FEBEFCF9689568CD74E6
-:101BC0009CD10AD17684E977295FE7A8E8F0E38C15
-:101BD0008271E8F331848D13FA7C1C7F3EAA24FCC9
-:101BE000FB97C1F8741DD35DCF94271058CF26AB57
-:101BF00087F6CBB16AB90A6D5F53D2B128DC7B4E50
-:101C0000A9240F9E4751D059071372337DD742073D
-:101C100098494B9996EB45CF6085CEEBA1E070D10A
-:101C2000E7B45BAFCA01840C726843A0FD8B282D1A
-:101C30001FCA7C491B0AE3DC6BD50AA04E889F9023
-:101C400002422610F637C1EEF08BB1F41F85D65351
-:101C50001D76D6762E1BFEFF0CE5F8E58408C42F12
-:101C60009CBB1CEA3E11C6BF5A3DF8B640FB5FADB7
-:101C7000BF77520A792F5D391EC3EB22AE0BE1B359
-:101C8000CBFA90EAB0F4DCA75EEE7278EC0087BF86
-:101C9000447BC6C33AEB5D9B1D2A85F72B9E66BB32
-:101CA0009BB61F8E2308C7BFC66813613FF5BB48AC
-:101CB00075336D176384BA6603FCA6280C9F531511
-:101CC00086FF36499B0AFD47D8B56930EE944C8AA9
-:101CD000273AEECCC48EA546B8CFE474309DE3EB32
-:101CE0006699F50B5DE754DEAF4812BC31B026C7EC
-:101CF000C163620A8507E9FECBB1D0FA58F8974A6A
-:101D0000FB9D54A64D4FA2385B2DBA2DB42EE70A89
-:101D100048CFA1E32EE2EB9D2B572E82F512B54E54
-:101D2000AD7452FA90C3D3C731DEBF3C025D66F199
-:101D30007596C1F330EFA771FE284B6A13097DBF7A
-:101D400088F35B68BF490922E36337191D6E9C7AEB
-:101D500085D13F5D773DD297C2D69D63AD5C09FBCF
-:101D600098A11C2A8FA7CDC5F7244D2349000F0B3E
-:101D7000B165219CEC84C249E270A2CB24505F6221
-:101D80006775297A1189A365A6CBB76E20C0AFC14C
-:101D9000EA5669FDBD93EF8984D2D9D6FBBB0442D4
-:101DA000E5C5AE4E4212B3601C1946843FCB39A143
-:101DB000E778F4992AE9F351D05C739268364ABF08
-:101DC000D714764E22B1A6F7C9393A9EA3B3DD2BBC
-:101DD00000FEECC41B730592F11F735270541C2F4C
-:101DE00095CE0BFB913F253ED88FE6F2549081842F
-:101DF000C47776FCAC16DB1DEE51B82FE2007E0BEB
-:101E0000EE7309F29FBE2ED9D1F1D88F69FFD6CFDC
-:101E1000A2DD77C3BE3B477EC0D643BC4EE06BB16C
-:101E2000C2EDC983F76CB83E0BFD0FF86C7880AE3D
-:101E30003797AF1726C937AC9FF4DCCF7AB1F27968
-:101E4000C0C74C3BD16207A37CD809F5BE56DA81E6
-:101E5000C2B151117C5EDAAFF1FEB9ABB3405EAFF7
-:101E600097DCFD08D039D929503A1F46E75D46E591
-:101E70008E5C481C0AADCB2EB6FFC67B9236C508D9
-:101E8000F05C2233E8F3619DFE2F040A8758575512
-:101E90008542F721F3F7050A38785F501532633031
-:101EA000D06DBB48503EB8101E3AFF689712E1381B
-:101EB0005D373C02FA2A9388D74EFB0B2E36EE355F
-:101EC000A453247D010F5411D0B284B8B16C143DD9
-:101ED0006F02FDD9658A57BA7EBBC5EE5B2100FE55
-:101EE0002A5F1B8D702F538EE706E5592439049025
-:101EF0003BAEC355FCEE72AF7C6978BEFA30C83792
-:101F00001F32B94CF986CE33259BC99DFDCE8E1963
-:101F100046BE5FAA30B9B494F33D91189FCD95B5F4
-:101F2000B380C7487CBE8CBF9706CA07F89884E781
-:101F3000E39FC7B3F54CB9DBD7D88BC26F4282E0C1
-:101F4000063D5CBE7D96D45B0DF693B9BE3B97AC67
-:101F5000917894C3EE93BE24D03E32EAF7C677C898
-:101F600074187F16979F27F8B8EFC7B375C4703DF4
-:101F70007E44704E0F0717677CB71C74C2F8C4C349
-:101F8000E022C60CEAF4D379486F3E8F55C079DA67
-:101F9000B2997C8C4F30CF13CBE53895FBC9F12833
-:101FA000F77DE9D0EF152B5B5FE8BCE9C179D37110
-:101FB000DE456CDEB120E781FFD5832F829C2FE2C6
-:101FC000743AB6D343C0EE011EB61404E5BDACFAB4
-:101FD000C53ADA5E1441CEF70FCED31FE7A9637876
-:101FE000DC9EA25D06EBA476C1E550B6652B282FDA
-:101FF000DFE865219B295FCE4ACBFE11884D7D9C91
-:102000004D7C9F6D598DAED9145F722771DB90CED8
-:10201000AB51EE1571F952BFCB43E0B9B7179599A3
-:1020200086F7E5CED976E2C0ADFCCF39BD3FF051A1
-:1020300067769C270C5EF472DD72268A88BA18DFF8
-:102040005BC2DF0BEDE778606F0C8CBF16FA5F4A5E
-:10205000F996EB1BBA615CDF58CE3BF59D9B633A6A
-:1020600068BF5DB9734CEBC1E7948F1A731F8B0186
-:102070007BA93583EA0190532F8B28271B9D0C8F5A
-:102080008D6955C4638073A9CB2F1E8771BE9A4397
-:10209000A651FC15B93CE4126770DD45B9555E21C7
-:1020A00009DB9F8BA2E3CC89BF04E946CEF3909174
-:1020B0000E804B33A9A2FB9715BFE8A6656927F1EF
-:1020C0008FC887FE54CE0B6C3CD5691C8734C3384F
-:1020D000B29BD203BCD7E9C7F5EC3A797E383AF225
-:1020E0002C26F9ADF325B5EB6A802ECA946BCBE2B2
-:1020F000E9F80BB6670D16E9F8235D6DF2EC3C9438
-:10210000DBB5401F9B92B53AA49FFF257B6E3AF149
-:102110005901EFA332991E985023F83653F83486AC
-:10212000D8098D9C4E2F0DDA37AB61FDA450B71343
-:10213000B435F1E7B783EF893FBF1DFC93F8F07624
-:10214000F0FDF1CC0E7E209ED9C10F4249EDE08713
-:10215000E2BF831D3C5C21BA1DEA43F8C7B37AFD98
-:102160009F983D1ABAFEF9F1CC0E5B4DF7DA0E746A
-:1021700029F92446E78C4FAFE67C3AF624E597BC74
-:102180009EF4DF4AE9DF4BE9AF8BDA4D6256647AA1
-:10219000F25F245F163FC0F8BEDEB517F9EEB79CBC
-:1021A0003F5BF9FCADB96205E0F315222AA2D073BA
-:1021B000BCC60C8F0BE47A28FF695F99E9B9D4E5B6
-:1021C0005B3F18F8E6E01C372C2B941F655A560D20
-:1021D00008AEFBF79C0FBBE51311A49117C1873024
-:1021E0008E6700D819F112F05F3D61F37A0F8AA86B
-:1021F0002722F111A59B77E30DF31503B00DEBA793
-:1022000074F367C02FE5B3BF7C177AF93EA70FEAD6
-:10221000871C87F192787D5604FFE2E3F86EBBE0FD
-:10222000639C7706D343CE7895BD479264D02F9AAE
-:10223000989109F2858E7B16C6DD1377FE710341F6
-:10224000BD1340BA5DC6C67D1E8CECE49EE38E4A8B
-:10225000A0F6479871EC5C8EDF10C15F50B85D430B
-:10226000F2BAED136B02FAED6C7D4F246BB684E489
-:1022700020DF1471BBE525C1AC9753B93E57B83F79
-:102280002726B0FE646EF7B80A8CA3C353B7036663
-:1022900071F9A08F93C4F92F2E4161EBAA66EF1359
-:1022A0005E1FC9FD270A97DEB82E3B7B7E21BFE863
-:1022B0002E85C52D2671BBAA1336C8F41BC27574B2
-:1022C00024BF2B68F7F507B81037EB9FC6E143DB57
-:1022D000F3B0BD82ADE352450D1B3F88841F1DFE48
-:1022E00052025F4F2E1B9F78BBE17625EC53A797D8
-:1022F0004870DB13C7E056A0C3AD818F13220FD601
-:1023000049CD7625CC3E47727AD5EB31B966F910C6
-:10231000299E9215D413E3111FF96CDD91E22BFD78
-:10232000F87E2FE378A0EF4D41F839D87AEF52BA12
-:10233000DBAFC3F67436DECC60FB0D388F8BF58FC8
-:10234000E4F7CFE4EB9A9AD08DA759385E127B2F31
-:10235000349EA09737F2F54D0FAEAF1ADFCB61EF89
-:102360004941BC2FC4F6D1ACFDFAF44D65C92AE051
-:102370008D8E037AC2C5F4C10DD56DA2D1DEB93EF2
-:1023800042FC4DE2F35605D7FB7DDCA7C6F67F2263
-:10239000AEBBFD87386F119B3792FC3811C7C6BBA7
-:1023A0009DEFE31AF08BE918F101922B2581D714E8
-:1023B000ED1E45BBA406343FE88F924F6515E474CB
-:1023C000B9E8F00A541E4BAA1DFDE4288968E0D73D
-:1023D000B67DF63D57471ED6FDA0D7574515DBC144
-:1023E000EF5C9D25B9411F16DF2B31FFFA9405E5FF
-:1023F000FD4871118EB357D1EDDC5B4D7EB4AAA8B8
-:102400001551B00EBB4854E6FF578CA7CF477079E3
-:10241000BDD79E6881F18665B078C108B50AFD75A3
-:10242000F215F3A335FA1F93DF1AEA6599BF27A5C2
-:10243000D711014BB3BF2D93F567C581A817D08E77
-:102440001AD669F6BF6575E409185F2686F7E8BCF9
-:10245000DB129C49684FE5907EE728FFD872056241
-:10246000BB02FC6CCF76C0CF18B54A29A1FBB1A541
-:102470007BEC208773ACFEDE104F684897DD5E6012
-:10248000C3FBCBEC59E06F3551FF1CE1A0255C3B51
-:102490002088275B9146800E294E90BFBA4B072BB0
-:1024A000854486C7B7136C580EE275FD7928DEB3F4
-:1024B00013A319FF13BBF7582EC80981C4513A5C06
-:1024C0004C3A32811EC534C6E735968E14A89F213A
-:1024D0009D2949B4AC6F924687F37FD6F1B8D41AE0
-:1024E0004B787BE95EEB9857010E12C40DAEC0B875
-:1024F00080C7D637183FD0ED553D8E10C96E6D148C
-:102500002BDF04BA1614FF17D0BFA7FDEB65FB4EF7
-:1025100067725A2FF5758C4F64FC6E4BB463BF3DE8
-:10252000779692D92AE2E908C7D3C12B012A5973B9
-:1025300015C0D3CB590FE6405CCA9E757F12F0E7F9
-:1025400068C2ECD372FA8E8B962B1D9E9309067B84
-:10255000634CCE2CB49B8A32EBD09E5A15C12FBD52
-:1025600085AF43E27432C8E1390BFBDA7AFF123BE4
-:10257000BC2F2995D150EE094CC292DABD9FC0F311
-:1025800055E9AC7E213CBCC4F939D2FA47815E8062
-:10259000784D7AF73E84C4647CEE950707F761585E
-:1025A0009F3531CCFA3EE5FA485F9794C3E932D7BC
-:1025B0004C77457CBFA989BABF78D174F7D6C5D00E
-:1025C0005DE87EC7642D1DDD9F04D7AFEF57DF3F69
-:1025D000DD6F1FD86FB9C4F6BF55F168300485B3FD
-:1025E0000AFBECB12F7B78BDEF48B47CD3FD3C985F
-:1025F000D0F7E2F7F30DC69D96F80DE0B47FB8E68C
-:102600000279D2904CE993E2A94160A5DEFF0B6EFE
-:10261000A7FDFC9BE32BA5DF37D85FB14B7811F406
-:10262000E108CF9152D86E59D120503BC08F930111
-:102630000F2579F74AB369BDF1CE39283FF70FAFBF
-:10264000C375AF729AD7AB9742228FE3676AC87F90
-:102650000D9CFFCA09F323F57E4F72F918CA1FA11A
-:10266000E385F2F54A873617D62524323D1BF4FF61
-:10267000DA45A3FF57C2F5D770FB6DA6F8C770EE19
-:10268000FFADFA34DBE1A51BEDA27AED9FE2FF7D01
-:10269000419F809F945E6237FA7F0DF6526C5F9582
-:1026A000A18DBE2209F4B1E8BE9B20FCD01FF40A24
-:1026B000A2B2358C3FB82A43F68FA0CF6D0AF90538
-:1026C000ACAF94EA4B88BFD8148D5C32A0A75FB83A
-:1026D000D75E4A206ED2A590E7C01FBBD07E1E48B1
-:1026E000BCC464474AE017F2F1D12F54EA4807C648
-:1026F0007B4A09D835D0AEA25DA5118F13F408F539
-:102700000B0DF2A9CB7E1BF27BE87C546E3D027C64
-:10271000DEA0303E0EF507BB389FEB7236941ECA22
-:102720005D8C6EA2E8D2AD4C6EFC2271684FBAF897
-:10273000E6F2696E19B800D79115FBC1559B1AE8EE
-:1027400094C0E59993C8F8A9D2F14C033CD7C70FC0
-:10275000C50FDDB906F174B06758FC86DA6BD48E0C
-:10276000B2527B6DAD109C7F0DA78348F888A4AF53
-:10277000F775CBB5D038D16DE6F317C54B920A5833
-:102780005C9F8481BFC8EDA4D5945FE0FC668DD5C5
-:10279000ED02BFA2BE5FD1DB1EA0BF7E32B377A425
-:1027A00026D7B561FC90B511E2DAEF2526203CA3CF
-:1027B000732C26FB8C7A0626FB31D2BE095F9795D7
-:1027C000EF4B0078E61AE119B2EF3205F70D663DDE
-:1027D0008C1B6B71133FE58BD84CE24681156BC1A6
-:1027E00038ACCEE70AE7735D1E3814F6DEB0A4BE3F
-:1027F000EC7C4F74748A145FEB92A83D4DC7A9D747
-:10280000F6A25ED5DF8FE3FB770C67F14687D3AF87
-:102810002861E4DD8F2F80DF264D8A2FA3EBFBB1EB
-:10282000C2EC6F69B8A5D287F12816AF5538ECC451
-:10283000E27C3BD8ED05E0780F85F5EC508C712BF0
-:1028400091AF27C649D7731E39B98AF3B75EB7A9C6
-:102850001D65B07E294B53E20DEB1F94A4EB9576DA
-:10286000E4EF48E3DDC3E5BC2DDD4DAAE8BC768787
-:10287000DB0FE75A36ADAA00FC05BBEA26730CED68
-:1028800076AD6088CD80F7A67EF2F4707CB92089A1
-:10289000C97FA7A455C27B4E4522704EE6E4F6726E
-:1028A000A47123ADE342F38D8A349F1ADEAE884DC6
-:1028B00062FC270DDF5109729A0C9048BF307A42B2
-:1028C000E0FD62E50E15F88AD2A327DC7867126571
-:1028D0000EEF7F117FE8767771CBC16CBADE7A8715
-:1028E000E416407E159E6C570D7281EAF509490683
-:1028F0007B59747850BE892A3B771F6D63FEF6FEC4
-:10290000E1E673B2299C5E5EE56524B97079928533
-:10291000DB4DFF9A7D7E53FC0D4A2226B834015CC4
-:1029200008F0D77D0DF561E42585CF926F039F6593
-:102930009CBE1EB9007C32FECDF0B9105F07F9CC09
-:102940004B8E86916FF54E396D8E89FFA91D12A1B0
-:102950005F95A13D121FEAF4310AF002FCD0A49960
-:10296000E2027292B79DF995B79BF59CB8C8CDE588
-:1029700033F9AA808539E12FDE41FC31B1C1F1E59F
-:1029800032733CE1C9241E17882251009F2EF72480
-:1029900001F214A22C3306410834853409A02752D1
-:1029A000609C81D44FE6F23C540F266BCC4FEE4D29
-:1029B000EA04A657D2717D497C1DA17A308DFA3583
-:1029C000108F0154833FDD5B82182F3CD5F01C5CD7
-:1029D000F05AD05F76119F00E3A7930E2CFB402A9C
-:1029E000021D3F8BB40B39147FF796570D02F9FD8A
-:1029F00062C83E2E648FEAA56E7F2CFB37C1FB9D1B
-:102A0000FF5E78AF2835C0BBEB3BC27B0A973BA18A
-:102A1000F1BC31DDF1BCA617310EF715B33FDABEBC
-:102A20009631BED790C5E279E562C506B0E7C7A882
-:102A30003201FD26E576AC833C27DDEE049704E207
-:102A40005C7ADCCFDE6F4EE560782E9D4438E1D9AC
-:102A5000908AF2CC998CF286D91123F8FAC7A8553E
-:102A6000F62CD5E83F3599CECF644E07635C25E858
-:102A70003F357C757EBBE362FDA43DD2030EB06B97
-:102A800074FFA83E670EDA3DA1EFF9A5A63F435CAF
-:102A9000D29F6353575078BCCCE5D5CBFD1E928CAA
-:102AA000E7BFA17E906E578DE0EB2FCD997510FC9E
-:102AB000AE31CA6C06130E0799CFD3E0EAC273F0A9
-:102AC000DF7E65417FAB8BFB5B63B89F05FE4E9558
-:102AD000B3E73E87279BCFD574FF694CB7FFD4245B
-:102AE00019FDA73111FCA7D1B6CE57AF80BC9057C6
-:102AF00045CC0B8904DF50BF2954FF8C4E667A67A2
-:102B000076323F270A81A71EEF0B3D976ED4F94F0F
-:102B1000F20A46FE0F9D5FDE3B06CF05896288C73D
-:102B20006607E38982E625CB0607E38761E2863301
-:102B3000920D71435D8FE9746CA37DED78CE1C3EE0
-:102B40009ED89A75A02FF30B5F4C04FC972B2C6E2C
-:102B5000A4AF8FFA85F3930D7E615127D3DBB6FFC7
-:102B600053D7B182C297241037F30FEA547B3EBA91
-:102B700013896B591C1DF3B4C638048C874BFE288F
-:102B8000AC979D72FBA268DDB6F76109FC84524ADE
-:102B90003F5142907EC670FFA221E7E83AA0AFAE57
-:102BA0005392FB7C7E7799430CA1D3E8601DE55BD3
-:102BB00082A9BE5AF2AC647CDB2B086F11F2C1B261
-:102BC0004DF9675B25AD11F63DCAAEAD4AFECFC4E7
-:102BD000FBCF605D8272E05BE13D380FD30760B3ED
-:102BE0009134C37C0EDA7815CCA322FD77C7A59764
-:102BF000123C8FD90638033FF763E28338CB0BD6FC
-:102C00009744D0478D7C9CAB49932AF765EB857E32
-:102C10004F6C756D5A0BF238390BC77BC1E1590FF8
-:102C200036E4C12DD22088DBD4ABCFDA217F76EF1A
-:102C3000D6C6F40E03FF1D7CC2D3279C7FA897F451
-:102C40002FCE5288FB8A65A5265A5CD82E42BD87B6
-:102C50007DB6A54581799ED86A0F6B4775713EBFD9
-:102C60007A0BB36B47E75ADC1402A48878A50438C2
-:102C70008F7113B79F36C40CD8D15E02BA284B446B
-:102C80003F9FD6F7C5D27ACC500DFD83FE0376E088
-:102C9000FBFD3F2E71B33C4AAF6330ADAFCB2D1976
-:102CA000BA16FA477BDE04FC513DD324A13E6D8E5B
-:102CB000813C8098019392A98D4B620452192E0E8B
-:102CC000F84132B3F39EB0EA7095300F72EF5619A7
-:102CD000F9EB609A88FC46E1B608EA7F4F8B2194B5
-:102CE000124999E62D03389693E67AF0A7CAD46B79
-:102CF0005F8C25DF027EF93B14E0FF756087875902
-:102D00005F1B5F1F0A114A3F07B634DC40C2E45123
-:102D1000EB74F88B18ED1380C31A7EAE4B5C939066
-:102D20007E22E3FB6EA41F67B3BF3E9AC2F1EAEDB9
-:102D30004DBD8CE3EF4F564DF1371DDF90FF4CAE8C
-:102D400080FC5B0FE6D3D69FB420FC5EC9137C02E7
-:102D500085CF815C91DA6C745539765F3F5A5FCFCD
-:102D6000E9B862FBA1865E00A494245CEF2BB98FC6
-:102D7000D9597EEBC5C7AF87503E5800E7C9141F2D
-:102D8000A394689F4AF1B51086C887FC1CBBCF4F3F
-:102D9000E76B73B697C6D1295E4816DC9B815E72DD
-:102DA0008902F2035D100B439442EB2032909E9215
-:102DB00008E673AD2BC8DB0CF2766DBADA0CF98637
-:102DC000BB07D831DF2C349F78B750F7623CE499C9
-:102DD000C40B28AF0FE4FE1ECFE90EA4DB08D02BF6
-:102DE00026FCD2E70D098C4F63F2CDF6677E4A16BA
-:102DF000F7B389D756105C574C8E5D8BA284F45282
-:102E00003C7BFF608EE0037A3BA872F940F7BB156C
-:102E10001201A91D346D4064BCBEDC6F94AADBC5F1
-:102E200082BE4F4BCF7DBC20F85667C33EFAD37DA0
-:102E3000D0BA3357C0F99DCADA5B099685F3E01C16
-:102E40003374FD35298C2E654A76B920DF9A578F69
-:102E500031E6C7C885B74E70C4621E13DA95A9B9AA
-:102E600002D35F27D9796E8FFC6C857864137EA8B6
-:102E7000D591121C2FE6D3E7BE0FF9BFE30A057FF9
-:102E800014AC87E737D3FF6B03FD22E7CC62F9D799
-:102E9000B99B703F630BAD6E38CB19EBF03595D015
-:102EA000FACB1F4818CF1E97330AF3AB43E75FAB4B
-:102EB00010FF680ADF97F3248477D4258FE1386FF9
-:102EC000E45950DE8C837C6CC85F36E655A33E34F3
-:102ED000E7738F13FFAC1543B39BF12B91BCBD403F
-:102EE000BE4F7099E1E73C693E2FAEC8B799EAE35F
-:102EF000F2E49078A597C58733185DBCD45FF06D78
-:102F0000CE0AD2D9D893093EA033F8130B4C7034B3
-:102F1000ED33A653D6007E07FB3FFE1338278951B9
-:102F200057DD8AE7E01CFE3A9DC470BC3BD39FFF8F
-:102F30003EE8291DFEA17470F1F8BFB6B218F09FEB
-:102F4000AF9FDF87E03F04DF1883D4F7D1B727DED8
-:102F500071FEAC9EF8D6E9A0C7BEEF69599D4DF150
-:102F6000FA8A933E003C6F927D770B413C5D10AF37
-:102F700039C548376B952607C8FDA84B8E3AC0DF88
-:102F8000D0E98288ADF946BFE39F85EF92F50273E1
-:102F900026DD820FE27ABF83475705E77936A53BE6
-:102FA0009FE8D914D013952C8FA35E1BCCEE5DE562
-:102FB000337DDA433EA4B07B1D6DD697D2CF97A761
-:102FC0005AE1F010381FAB877C3BBA3F79FD2CB833
-:102FD000D140E429B3505E92F5028BCB17FD01E599
-:102FE000FB5C976FA510663EB464709D2A937B4589
-:102FF00089D89F4CD7F3922A5FC5F54F61F58B5D59
-:10300000D7EBFFA4751DA0B4420CFEE7446E37EB6E
-:1030100076F70407CB3B9C5024223EDED822F830C2
-:103020003F92F6F3523A59C0C97622B703BB0A9FC2
-:103030006D1CA4823DA899EC4EA1A80DEDBEB8422E
-:10304000B33F18AF459BF09F383AC1544FAEEC6583
-:10305000EA9F3A3DDB1C57F05C667ADEBB7AB0A98A
-:103060009E5177B5A97F9F6525A67A9677ACA97FF3
-:10307000DFD5934CF57E4D3798FA5FBA61B6E979A2
-:103080007FDF02D3F3CBB72D31D50734FFD0D4FF88
-:103090008A9D779B9E0FF2AF353D1F72F03E537DA8
-:1030A00068FB4F4DFDAF7C7BB3E9F9551DBF343D47
-:1030B0001F767287A93EBC7397A9FF88C05E53BD77
-:1030C00098BC6AEA5F6AFF83A95EAEBC6BEA3FCA3E
-:1030D00075D4F47C8CFA91E9B94E07E3723F31B5AF
-:1030E0008F777F19724FA712E59B0CF180BEF0A875
-:1030F00009CB68D2CCCE75483B962F1578DCA94019
-:103100009F8F7A1B2121A9DEDBF957389A7EA3B065
-:103110006F1CB39F3462949F7A7E2AF55BBC5194F6
-:10312000146203946E8750BA0B08582A012A591367
-:1031300021DE138565422011DB1303F15826057A41
-:10314000637B72200DCB94405F2C53035958BA0215
-:1031500097639916E88F65AFC0107CAF77601096C3
-:10316000E98161D89E11B80ACBCC4029B6F7091481
-:1031700063A906C6619915188365766032F6EB1B64
-:10318000B816CB9CC08DD8DE2F703D969704E660B4
-:103190007969601696B9818558F60FCCC7F2B2C02E
-:1031A0006DF8DEE5815BB1CC0BDC81ED03023FC045
-:1031B0007260A01ECB2B022BB07407D661BF418179
-:1031C00035580E0EFC04DB8704EEC5323FF0336C3D
-:1031D0001F1A7818CB82C063585E19D8846561E0E5
-:1031E000492CAF0A3C81E5D58167F1BD618167B0AB
-:1031F0002C0ABC80EDC303BFC1F29AC03E6C1F1104
-:1032000068C3520BBC8AEDC58197B12C09FC01DB68
-:103210004B0387B02C0BBC8BEDE58177B01C1938C4
-:103220008AE5A8C0112C47073EC2724CE0032CC7A8
-:10323000063EC1F7C605CE625911F812DBC707BEBC
-:10324000C0B25BDE45CC57F658D09FE57E6A647FFE
-:10325000C18B72D2CAEFC5416E35E6FFD709BE51A8
-:10326000943452933A305E682DB461BCF026D26932
-:1032700065E7D0ED4ED04B6D579D488738DA1BC9B6
-:10328000FE0C63BE8395C701CAC553188F9A90B4CC
-:103290003719F4E94DB419F28C88760EF32027F033
-:1032A0003CC89B24EA60D1A51E8211AEC27E7E1B63
-:1032B000ADCFA820DA60DABFF12A1BDE2F6A1C4CE2
-:1032C000FD205ADE93C5F2657DA94C5F3ECCCBC78D
-:1032D00053D9F9CB5F0B589EEB8C5BFB317E2A4BAD
-:1032E000BC80DFC4E0307420CF8F757466627EECE2
-:1032F00045BEF7A714FE1EEFBF3CB5F2C954BA0E87
-:103300006F09C9AD7304FBD1F6A723B43F03F220C4
-:10331000B47DAF85E1C3FB96C8FD84CAB849E7F127
-:1033200013DE58DE7ED98BFD82F5DF45F043095967
-:10333000C1CE0FF77E50711DD587130B4537951CF5
-:10334000E4CFCB770E3FD68FCD0B71506F8988F1CC
-:103350008B194587F627D2FA8CA5F19877DFBDAE99
-:10336000122B3E9FE07AEBB217E9D66FAAFBCDF0A5
-:1033700063A6789307EDAEDB388D12CDFA8F0EFD84
-:1033800039D22B8BFBDE0693AB20FFAC386EBB66CD
-:10339000F59D2F3F866836A299E89EC16B1DAC1F34
-:1033A0007C7F62B7C0BCB1BC0F852BEA7D6FACECF3
-:1033B000AB17C07957E380EE62F23AC9F9E2CB006D
-:1033C0004F092E4E920E07D83191E029B8581C347F
-:1033D000AE487379297E1ABE16316EBC2FBE4001ED
-:1033E000FAFF91232715F843E2FD1ADADEC1F856F9
-:1033F0005C7E27F13A58FC5EB5C139BA1DCB95CB3E
-:10340000DD58362C2FC4726DFA7D76889788C9985E
-:10341000094CA232E6623C489FDF1A3FDB5EEC2695
-:10342000E4CB87BE1E07212411E20CD444F89AD6BF
-:1034300057509FE2642AA3CF375CC71CC00F2753A5
-:103440005596876F61E7C631F97E0DE28D316EA525
-:10345000445283EDF89784ED9BC11F798374AC9F30
-:103460000C70D4D87D8C7A7EDFB4BEB81F87ABFEDB
-:103470005E08DE43F02CCA6E3CB716A369FFBCC8D9
-:103480007875B9585E02D09744E9EB6FB06EB037EB
-:10349000B5180B8CA7E3B74BEAC47CAA7A217CDE73
-:1034A00065B68BC987064553CE778E4214E91F4611
-:1034B00079EAC8DB1942CF0E94AF58877C2E2EAF25
-:1034C00076A46AB92E3A7EF3355C0EA427A01CA020
-:1034D000EDF75D4DD7BBD3C2FC146F828CFC4281EB
-:1034E0001087792F76356ED279F220562D5734C950
-:1034F0000AE7036A1CC06B15CFD7831BCA4639F095
-:10350000AFEA1794173E961719D27FA785F3557423
-:1035100014EE4BE4F0D0DF9BEE62F2F8C1ACCAF1DE
-:103520002E8C8FA8E92057697D22C08BEE3F1DF8B5
-:103530008AD6AFC5BAD25D9F8CFD5DAC3F26D25C0A
-:10354000841CA6EFDD80EF49DDE3CCC0BAA37BDEAF
-:103550009B719EA4EEBA079FA7B3FE173B8F5E76C2
-:10356000EFFFF74C4E7E2A697109143E95CBE65465
-:103570009651BD3D79D97C2CDF5BDEAE815C3D4E42
-:10358000E54903856B6571DF24F073268FEFEB50FF
-:103590000DF43A8FC735F7AEB68E067D57B246ACFE
-:1035A000DC82FCB4C214B7FBBECBCAE34D6C1D5524
-:1035B00094C7EFA424376FC3A1CB1A0CF6E86CE2D2
-:1035C0009681DEE7ACB606E99A18F853616D3B2D9B
-:1035D0009E1F5D0FFB582BF2F30ACEAFF184FBF375
-:1035E0006A4AE579F40E596D239E30F2B8277C08BB
-:1035F000F907E5834F1D391897A5969A3DDCB83A2F
-:103600009C22CD372F42FC5787930E6FBDFDE8FA01
-:10361000210AB3AB7D2638CEB96728C62BE7F178EF
-:103620003D89B773FE64FDAAE83C3BE03D49538108
-:10363000DEA11E4EBEE8F356D17FDD39381C7C3941
-:103640001CD65A991E0F81EFF10DFD62410F85E2E4
-:10365000EF62E15C6B23789FA273AB93C59192A656
-:10366000E3F8D57C7E923403D753CDE77B714F8C42
-:10367000DF42FB976C756E063FF84C89F7C14A90A4
-:103680004F9BAD98CF76F79E756FFD0CEE7D6CB2BB
-:10369000E299C9FC98070AE0FCF42F5C8E5205D031
-:1036A00006DF4FF010FD4F1360FC79848D7F463F9D
-:1036B000FFD81A87F03C59B6A571182D3B762FAE6E
-:1036C00080B8CB893DE30F80DF3C3F9A4878979DD7
-:1036D0002832F29FD77ACC6C1F48C1BAD8B33E0FBC
-:1036E000EA86F8D17C9FF59891CE176E33D78DF08E
-:1036F000B218E1A59699E1A5969BE025FCD6E917BD
-:103700000DF02A8BEA97047A7DBF4BC5F1AAA35628
-:10371000A6007CAA77AFC172E1B628EF31C3BC8B9B
-:103720009BE34DF5DA9D695EA35EE93AF8582CD02B
-:10373000E11297E83D46F5DCA9E55A3DD831A79757
-:103740008FC652C7FFE2E62CAFC3348EB9DED52454
-:103750008C66F2598D9B721E7E5DE292719E0FB750
-:10376000317FF3C3E5762FCC736AB9E265F3BABC57
-:10377000CC8E62F05AB42CC67B6C48707D91C6FD2D
-:1037800067AF8F901672D44EF0CECEB9F3E8ED88C5
-:103790007249FA5446FDD16AFD3BD08D9DFEEF1C67
-:1037A000C65125ACEBE3D6368B5EC8272664BB69D1
-:1037B0003EFA9E7ADCC06F91F582F93B13FD21162B
-:1037C00086F2999D8378E01C848E774672AC8638A9
-:1037D000827E0E520B13D1BE8BED1DB287367DDC7F
-:1037E000D2F7BCF7CC299EB2402F57DB9B6450B672
-:1037F000D5CDFDCB809F3E6EA94F01F9B150ECFABB
-:103800005EB8FB5EA5699C6F7DD64EB3BFE8D3D78B
-:10381000992599F88C38BAF74DEBA722E40B8F4F16
-:1038200063F66CCDF6432387D1F5D7EC3C2B63DEF2
-:103830005A9A677C9A61FF023F075AB0ED888CF66E
-:10384000A7D57BC91DE7B3EF7BACD3E132E51D7A89
-:10385000493BF0E7EC42A233EC75EF5279F3C1AB90
-:103860005602E787E42BDA8B3ECFE44FE792CA5843
-:1038700080D7EC9685287F3E786EDC01967FD45405
-:1038800000F4F131B160DEDCC7E4F7B1430CF05B6A
-:103890009626EB7144BB31BF852E300DF3D3AB1BA5
-:1038A000DBE1DE988D485E2E9704F6BD1A9F80F20C
-:1038B000AC9AB57B897D05EE633593475EFA1FD4DC
-:1038C0006F6932CBA7791BCCF52A322905F2BBAB45
-:1038D000EEB7420611996F947F147E33D3581EFBC6
-:1038E0003C52D708F6DC2332C5135DFF6C8548BD1A
-:1038F000A91E5AFCFC2305B3687D791A3BDFF990B9
-:10390000FB19F3C13CA5CF172CF3C95A5ECFFD1D9F
-:103910006D19326D18C1F198DE5AA0DBAD448538BF
-:103920007E6FF85776E4FDF76E11F1DCA937B41B12
-:10393000E4F39CD5E6FD5D68FFA1FB25E43EDCC712
-:10394000826DD7A2DFA6EF47C797BE1FEBB6F0F791
-:103950007C1FE4F4DA7DBECAE1A7FBDD4FA631FB94
-:103960005DAF3787D47F1D52D7E9DBCAF99BD2FD03
-:103970009369C9C0CF9D23199D74C8C6F35039D827
-:10398000AFF97CFD6C9C5F68BF5F9FAF5F5470BCFC
-:103990005DE1FA2D7EFEA9E7C01F5DF0AB0762E195
-:1039A00030E803A92905F284166D5D190B703A29D8
-:1039B0007963816E3EF089A3C3C1ABB31B5E9A43AA
-:1039C000A078AFD1E9BF68C504D0EF7FDF6A55C0EA
-:1039D0002FACDD66F3C3F7976A5AE6E3790DAD1FA6
-:1039E00061F55578AFB276A7F53D235E173CFE40F2
-:1039F0000AE677106F6F769EEEEF0D9F0EAAD9F252
-:103A0000FE48F0936B4927D273E87B307F2001E5B5
-:103A1000F52C39AEE7733D6E5ACB9A486DCBBAB3ED
-:103A20001037AD6D197302F8BE9648EF19E9A91A5F
-:103A3000689AFA2B47D278DEDD95E44A902F3A3C1B
-:103A4000882F19E573FD130F0D3C42D7736ACBAB7A
-:103A5000B182D15FE5E7ED5DCD73FE96781EFD7016
-:103A60009AD2A9313F5E97BBEA4EBA80545A6D652F
-:103A7000E522AB3F761885EBA24D56BC1FBAE8A9EC
-:103A8000C77EF153C8237AC786E71F0B9FDAFFD69C
-:103A9000D5B4BEF0196B5205DB8603CE8375BCD45A
-:103AA000D2FFC1F9848E8705CFEE9721FF0BDAC1D3
-:103AB0003FD0F1B1F09936990CE809BFD2E636B99A
-:103AC000C311062FCD4746E23DA3273E9701EF1FC6
-:103AD000EC11486A56CFF7AB37ED473B06E08478E8
-:103AE000E478EAC65B0F7CF927ECCAC77E0AC8ED0A
-:103AF0000BE16B1FE8D564A4EBA777D17554FFC920
-:103B0000E60638543F7D5B2CECE78454C7E8FB9114
-:103B1000952990E7566DF5A62858B2F6EA476F4703
-:103B2000BA9B77E8F61476CF414BE3F91D69B0CF25
-:103B30005B364EC57D56110FD25FF5236225E4C179
-:103B40007C2691D1CF84E18FEA5E4CAF9ED84C9118
-:103B50004BF77902E46552D0DFD1EF35DFDE1D0788
-:103B600061E7909FF173C86B7A594CFAA59B6EB7C9
-:103B7000AC42B9FA6186960AE793140EBA1C45F96D
-:103B80002A1E2A4F657862F218DFA3F4570AEDD097
-:103B9000BFDD8AE7C286F7B8FC64F32FE5F3D3757F
-:103BA00047833D722285E98DD0FDDDCFF747E0C226
-:103BB0008681CE0C7CCEF87ECB1AC6E73ADFFBAE10
-:103BC0001D0DCF3FFD23E323780FF4115D973F15C3
-:103BD0009FB74D11502ED8883F1C7F6FB172FE36B3
-:103BE0003FA71209ED399D4EE8FA25F81E59905E5F
-:103BF000E83C098807B457AAEEA7EF1BECEC5A98EB
-:103C000017FBC9C1F6AC201FCFE3F2604E2FB33CC7
-:103C1000201B932F2A2EB0C8EAFBC54F817F29BFF6
-:103C20007A55E05F2BDEBBF968FBBEB76EA074FE71
-:103C300051B3CEB766791ACAB7D53B6EC7F86028BC
-:103C4000DF7E945E47C2F26D3ABF3717CAB7E91DEF
-:103C5000FF5679AAC36F5D08FCA87CFCF92E3532AB
-:103C60001C43E5E3A5BDD4B0F291FEFD9114F4A48C
-:103C7000439DFE74BA5BF0E4E23E2087BAE953A7A5
-:103C8000BF6EFAD4E92F74BF66F8853E9F02C94E15
-:103C900006FBC17A37F13A29BE3B778BF8BDA433D6
-:103CA0006A672CC47F5646919960879F51783D9EE4
-:103CB000D53B93E54690137A7B67148B579EA9EC0E
-:103CC0008C8D37D8D7475AC55888EF76F8C2DFE7CA
-:103CD000C08C443A7F4784FB1E7A3CE24C74EC4033
-:103CE0009C2F3AD307F82A171D99CBF2C10F13F175
-:103CF0003B3E73575C170BF921675AFB4E9C4EDB1A
-:103D00006F79997FC6CFAB496914CE7338DE4F12F5
-:103D1000EF8345747F735A99FD3C777D783AD1CF14
-:103D2000CDAB1C4B659047D46E0DD20781E7EC3BC1
-:103D30000BD51B43DA5BC7213D2D08A1270FF78F59
-:103D4000DE047A82B8EB203288FB2716633E48B93E
-:103D5000983711BECB79E6A08879EB5DAD226984F6
-:103D60007D6E177C04F8DB9B8C745943E58731FE2C
-:103D70007B0AE8EE3CF7E84EFDFA2F0577D02E8B54
-:103D80009E7B77E0CF6879EAB9772E7901EACF1F79
-:103D9000CE7C9784F1B3F67C7133C8FF337B6C041F
-:103DA000E32A7B5ECABC03EABB6C987774E66E9B21
-:103DB00086F6F41E27E6D19DC960F1D4FADD9F0F87
-:103DC000C47C74D2C0E8AB37BBB7D5D5FAE55FF198
-:103DD0007E6D2BDD15E8DB3D31688FD7EE8AF281F1
-:103DE000937A66F7E705C6F38BEFBA9F1A99C5EF8A
-:103DF000CF38C974887B9D896771EBDA17AE7A0C6E
-:103E0000F2E117B7B4C9706FA7F4B75F0F04797305
-:103E10006607B3234E5B3B1E256E42627ADF768FC8
-:103E200095C2F934D87694571EEFDD321ECE377A1C
-:103E3000C285C1E10C8503EC8BC2A51AE464247829
-:103E400064FFC7C2E3ECCD30FFA2D62BF1FC210802
-:103E5000174163ED4E9F5DC0FDB3F63D9F0F0479A2
-:103E6000FC51F30AD4EF17DA77F1FF73FB16FC1756
-:103E7000B36FCF7FECBE19FD1F07FD94DC930F7A63
-:103E8000D2F9F3DFC3FAD34E37AEF722F9DFDB9B6B
-:103E9000C51DFEF3F6FF2DF1BE43C0FC950BE1FD01
-:103EA000E7FFB5787F99E3DDA9409EC499DD5F67A0
-:103EB00012C3FE2FB4EF3DFFA5FBD6EDA0764B9DC0
-:103EC000924FD7F70E699A9A45CBDF699F2481DB21
-:103ED0006A8B704E73BA37F32B6C02CBFB265305FB
-:103EE0003DBED46ECA7B4AAF467B6382760FFB3EF3
-:103EF0009354D70E79A7ED2573DC6BB1C7E0B73DBE
-:103F0000509F329CD7CDFED684927107C1CE7B6381
-:103F1000055D1FE4F965480ADCE598A8896817D2B1
-:103F200012EDC137334762BF8985667FE3FA103FE0
-:103F3000E1BAE9E6E753F9F8D3C87DC910A79B3683
-:103F400097C5E9AE23752B8DDF519B1A32CE2B100E
-:103F50004033D891DF147E6ABA0EBF25080F52ACE9
-:103F60009FDB5D007E84C1BB7DCA20965F2CB919A2
-:103F7000FCA62D7663DC94FBA156FEBED5B1BA1D1E
-:103F8000F8D64ACCFEA7EE475E08CE84FBA7385E83
-:103F90007610EE564D44FFD4302EC245C7C737C504
-:103FA000838EBF6F8B8F2EC087E15C572FE7DB6757
-:103FB0002D8473083BE4BBD37D4D5CCFEE8FD8F3EB
-:103FC00004846365A115EF4DBE6FA92C00C3B962CF
-:103FD000C895353F64C3BA013EF3391CAB481DDABE
-:103FE0009DE4AB73E78A0AF0F40FEDD6F91A21E3EA
-:103FF000A95F525524F8A3E9BEE749C41B3718E26C
-:10400000A00279CF1807F599EBF0774D4A709C0B19
-:10401000F58F241FFED9E5DFA83C7A8F22FB089498
-:1040200098374324A3FF38B395C1B17691E0CB46CE
-:104030003AF25B8DE7BF0FA4B378E3DFEE1C827228
-:10404000AEF8C703E2985F9B8FF93CB5DCDEEFF278
-:10405000AA7110CFE96AED1B07F19AAE83A5B1E111
-:10406000F2780E71BFF20FCBED589E29139AC43827
-:10407000BC773201F570591401B913FADEEDE97A13
-:104080005CA68E9D4B1296875FC5F7318FBE1A973F
-:1040900060C0DBFAF11F48037BE201FEDE339CAB1C
-:1040A0007C57F8821F0B703D14D53132DCF709576D
-:1040B00071F855ECFD4286F8C1A4D62CFCBEE4A4F0
-:1040C00032D194A7BA3C9DFB5343C8105857C5DE64
-:1040D00031B157015E0E8AEE280ADFDAD6B3B22775
-:1040E000CCF95C283C617C88231FB5BAAB009E47A5
-:1040F000EF89C2FBFFAFF3F3A23CFE5D48F87410FA
-:10410000C4CF9AD2593EC8FBE92C8E3EB9A2D89AA8
-:104110004CE7CD6B5106415E592FDEFFFD74159FB4
-:10412000F7E6EFE9FD7A2D62FD8EC84A4DB8FDC76E
-:10413000640AFC3CC4FDBD42E13F0F6FC53F76FA07
-:10414000E15E5C5799C0EFCD84D23541FEE81A2D6F
-:10415000F840FF821F8BF50A01F5FFEB7ADEDD24C4
-:10416000A62F75BA0F85F36E0E677DFEBFF0FA5E5F
-:10417000AE377438EBF00D5DAFDE9FCAAB11C67879
-:10418000CBC49D839E06FBA4A655502C74A81AA9E7
-:1041900043063EACDD79AF15CE17AEE7BFCF42A4E4
-:1041A000CA81C6F3DDF7D3D9EFBCEC1B3C0CEDC7DD
-:1041B0004FD633FB589B7B3616ECA0D72DEEDF0D88
-:1041C000037E7C43347DD73CB47C77B9B2A0CC6A03
-:1041D0001C370BD7397951B115C243372E6AB3A6B4
-:1041E0001AE8E97DC8C31A1A6CEFB548C5FC453A10
-:1041F0001FAEC3FB231B817C8CBCE6F69218FAFC35
-:10420000C6BA784687D5CD6D32D6D97786F5F9F41A
-:104210007942F9694A458CA93EA7B4231DE0526151
-:10422000F32F7587A1536F867EAEF20DF58446E9B4
-:1042300076E0FF0F7AE2ECC870DF419D98D1433FF2
-:10424000A486D30F4B56A8A900FF25BBFBA602737B
-:104250002C79B93C259C7E7873393B3F3CCCF32EBE
-:10426000CF4CA1FAE10A837E981285F411FADE554B
-:104270001917A91F747CFD9BE5CC9BA01FC2F0758C
-:104280004586593F4C6B9D85FA61DA1491A8867872
-:104290005C69068FDF46D40FC529D763DDEA8E0936
-:1042A00043376F72BF04E00A25CC037AE28E0C26F6
-:1042B000F743F5452479AE5CAC3CFF5F82B32ECF6B
-:1042C0009750FF85FD0E4E281D1294D74BAE17F068
-:1042D000F74B96EC66F27CC94D3C2E19225F2B41C0
-:1042E000BEE61BE52B7BBFC6C3F441EDCEAC8766B3
-:1042F000D0E7373459DD76DAFF86A0BC2D30CADB33
-:104300003B32241DCE994A18FC4E9F114354B3BC36
-:10431000CA01397574D04B79CF02DDBFCEEE99BD9D
-:10432000CFF5F86B835ECA8778FAEFF9B89B391D31
-:104330009D5E4E1694513894CE65F6F0E2ED22C2A1
-:10434000A1A685D97935DB04BCCF3B72F017786E16
-:10435000B870373B3784EFF9161BF0B8F0F58EC60E
-:10436000DEF07C9380E79E55EE85ECDEDF061627B7
-:10437000B6D3FF205F624D74EC6682793A1AC69B11
-:104380001773B855D83A0FC0FB158F0BEE4D28D7D1
-:10439000CCF1E9C539633F00BF60E1B69076F71A0A
-:1043A0003CCF580C7167831FD2C6F7778BE8CF7B61
-:1043B00016F2027F2786FDBDB3B65038547F4738CA
-:1043C0001CA270C8FFF670A86DBD17F36FBEEBFEA0
-:1043D000F76570FB7030C9077E79DFA221FF7B5F34
-:1043E00011F15EF1DC7BFBA51AF3940E6530BBE2A4
-:1043F000758BA7310DFAD5B0FBC7F3363EB31FAEB0
-:1044000086CF682683206C3F6F83594F76EBE51685
-:1044100015F5EE8CBA6704F89EFF2D22C1DF019BD3
-:1044200033D8E681F3D743519D28CF743AFC12E884
-:1044300090C2FD0B3EEFD15E9D65E857EC1414E48D
-:1044400013F89E06D4291EA2603F577D3E92C31DDD
-:10445000E333B53B199E6A295E80CF46527B17F441
-:10446000C88D54EFE079596B9B15FA57D37E892894
-:1044700077DCE8EFEAFA09CEEF8A530C78DB7D842B
-:10448000D1EF56C14DC2E02D97FE773EBC45C29795
-:104490006E3F5C2CDE74787CA9CB6F8EBF4351EDF0
-:1044A0001543F09C8AFD0E10698DC77395634D7D91
-:1044B000118F519982E9BB32DD7805FD68882F5D47
-:1044C0000B0BC70FD747619E1CCE9BCDEC21A37C65
-:1044D00009F5A36B493BDA35629AE7E174435ED88C
-:1044E000349EBFD27DAE1BEC37392339723FE22AAE
-:1044F000C1F31F3DBF167E390AF3C1787D5F46C107
-:10450000E11974BF9FAC16F17EF27516F5AD22E08D
-:10451000E3B5560274F9C96B568DD9A13128876766
-:10452000BD7ED40AA19159905F40FBCDBA8BC9DB07
-:10453000A330186DFB13D5631A7CB784340F85BC88
-:10454000FD29EEB672C8DB9E9A7F68259CD34D2E5E
-:1045500055DE7A0BE0BB462400DFF75697A2BF7208
-:10456000DBAD02D2F5DBCBF1B7B0C8D429596FBDB2
-:1045700045E7BD6975329EB3CDD0F69703BDCD99A1
-:10458000E874C039DDB85C91780C70BC89B463DC28
-:104590006246DDAD5361BDD5542F40DCB5BAF55050
-:1045A000792AD4370AF83B6AB55E8F0C57A0DA3700
-:1045B0009C9521FE5245FB017A6A37B27EB55B04B9
-:1045C000BCDF5345E503ECAF6A8B40E022493BB5C5
-:1045D000FFEC6C5C9F9D8EDBBE91BE4FEBF3E07DEC
-:1045E00018774B3CFEDE5DED6BEC7E5055E18A03A7
-:1045F000209FAAE87BF43169DF722B8E377FA340BE
-:104600002035B8BA30EB478530DE6B56FC2EC8E15A
-:10461000B6876558F7CD74BE343AFE1CB1A31CF3BF
-:10462000ACEF1014CC83FEEA07C80767381F90D799
-:1046300096313E13789DDB85BA7EBC37339BE5BB54
-:104640002F5BD108FBEAF02667814B54BBF3AC0C1F
-:1046500076DEB1E5F0E1198A379E07B7CF7B54EEDD
-:1046600030C8A9A733FBB2EFE4EF2C463EBF855418
-:10467000E2B9B86705D3CB475646F904B047AC0A50
-:10468000EACD7D2B2F7D10F67FFA292B9E979ECEAB
-:10469000E8C0F8EC898D56FC6E48FD4611E5C889E6
-:1046A000ED2C2E243E3275641AC08FCA01A0BB7D4A
-:1046B0001B4B659087277C02BE5FFAC8ED292CEE64
-:1046C0006B961F55EA0294178F4431F9306F43F807
-:1046D000F3D588F262E94826DF43E4C1E2F4468C70
-:1046E000FB85CA895AE2D0E5C360A8B7FBD3907EA8
-:1046F0006B5EB312B0EF6A24E5E60D403733A2E0FB
-:104700002499F2857F3FC8B74F7C82EAA5CF6F9C82
-:10471000F99BA100BFE3006FE08BF58978BE5AE5F5
-:104720009B8570D5F311E76D30D3B39EF774BD4709
-:104730000CDEF3A1FFBBB13A8668867E87EFA274D8
-:1047400049E79BB953C0EF211DBEEBC881DBF3B134
-:10475000AE001DD62CE37A75BD13E9F6F00FCEAE90
-:1047600004BABCF94E01D74FBC9E46D02B351B0472
-:1047700015E29AF3EE64EFCFA3EF03BD1C7E98D150
-:104780000FA56315E8BC66E3BD07B0FF164185F1D0
-:104790000F6F9A857AB8DA2B127CBEE508DACB5413
-:1047A0001F60DED03EAF9802745ED3605300AF3A14
-:1047B000BDE8F477847F7F9AD8DD0327C3EF536485
-:1047C000AAECBE7C08DD89D3B390BE6AB75B915E6C
-:1047D0006ABD8C9E8E3C25221DEE5B79DD48A09F34
-:1047E000D35B8508F447E92B3F485FE223567C7F83
-:1047F000DE132CBEB06F23A3EB132DCC3E2D7DA476
-:104800001FFA35F35EB712167F200EA3FD71213A11
-:104810000CA5BB1E7A89D36124BAF3589BA741FE2D
-:10482000C1ACA7E9FAD520BC4A1B7F807180D2C6F3
-:10483000EB71BF3AFFC0BD16C8DB98DBB482E5332D
-:104840004A2CBFE71BAF2B641DCB339D41FA175990
-:10485000FE899FAEE3A5ED8FA11DF0F12F8F607E45
-:10486000E3C21728FE69FFD3DB9DC48F76B60FE540
-:10487000CC821611F34B89E42F986CB8BFA5E7657D
-:104880002CFC9513E1BE6087CD5741DF5FF0DCD192
-:1048900081784E7E37B353BDBF64DF9921DE8E81B0
-:1048A00093213F5362F921A1FA3790C9E230A77EE4
-:1048B0001383DF6312B6B5E139D382E6EBAC36433E
-:1048C000DCF24CA615E7A5FDD83D338A7F385F841E
-:1048D000F5197F4F42CF0B39F504E39F053BAD68D7
-:1048E0001F2DD8B609E37DB5DBCE62FE6CE9AF9E25
-:1048F0008A0538D4EE14CDF953DB44BF0DF3BCC4A4
-:104900002336F65D0E531E534D0BBBDF51D3CCF354
-:104910008442F26716FE6AF7735E0A9A85CF3E1EDE
-:104920000BFCF461FBD65880271D0FF38F2616462B
-:10493000C84FBA505E52F31A9E97341E7FA7233495
-:104940002FE943F807D5E3997D42F2BAB631B9456C
-:10495000B15F10EE1E926EBF2C7CEAB347218FF63A
-:10496000D48E8F1E85F52FFA9F4F1E85BC0EB22761
-:104970004A017BA2F6976F62FEA1FE5E611F664F41
-:104980009D7EE271CCDF3CFD8E0DEDC2D3BB4F644A
-:1049900082BD70FA992F52202F73E9EE728C4F2C42
-:1049A000FD7529DE0F8DE46F027DFA2E227F34140F
-:1049B0001FFB5A44BF83AEF3E3B76DC8FFDD7966D2
-:1049C000CD8B59FE9ECAF3CBB687CFD3D5F3A16A60
-:1049D0005A264F1C0EF2AE85E9F5EEFCA80BE595C4
-:1049E000FD91E2F58A8BC0DF769E3FD83C3E6C5E3F
-:1049F000D9C7F00F8AA76921F8FBACE5969FFF1491
-:104A00009EB584BFA7ADF3F585E0A6E701F7EDA35A
-:104A1000CDEA037CB4E349CCE303BC55A8A0FF3F37
-:104A2000CB84F8E6496B27C60D3B77DB14C8F75AF1
-:104A3000B0FB30F2CBE95F1FC23C5BC2F3714F9316
-:104A4000EE3F9637C96317B55B9C2C1F8DC31FF2D1
-:104A5000D5D4586CE779698C8EF57CB548796A0FA6
-:104A6000F5C966F1439E9FBC586D971547105F804E
-:104A70001FA110F075C494FFA7EF3B743C05E070D4
-:104A8000A531FF32523E20B7D37BE08BC9E5D39BE3
-:104A9000783E66779E2521E983213F88E9C35A9FA6
-:104AA00070381C7EF5FCCBFBFA70BF53E74FDFC5B7
-:104AB000E55D5E78DDDF0E2E0D7DD8FD001D3EA785
-:104AC000BE0A2FA79FE2FC4EFD96ED7D0CFECD4C5D
-:104AD000EEB7E87967FA7A1B9B995E3EB58DD98D62
-:104AE000A1FC5D13E1F7B45EE8C3E20D353BDB06E4
-:104AF000821C3AB5F7379CEE7CFC1ECE11D9CBE573
-:104B0000B6CF28B723FC7ED97E3E1EF577C38E57DD
-:104B1000BBFD6CD8F13E94B4EB60FD1FB6333BE4B3
-:104B2000C36631ECEF20FCAA8FD5E407363A65F472
-:104B3000BBC4D86894474B9D856FC377DD963A65B3
-:104B4000CC77A85FC1F323EE72E3EF78D43BC7E2E2
-:104B5000F74B57027C0C7EA855F1E0EF4E585D955F
-:104B6000F9E05F85DEEB94932CC467C4BFE4C5FB1A
-:104B7000BD13B23F9740EFB42F37DF1B699794FD09
-:104B80008974BCF632C10DF66E4F3A338F7FAD2675
-:104B90009AE26710AB867D75B9D9F7D09C16BF42F3
-:104BA000BB106754BB0B1D3D95FD5E35FC4C179C3F
-:104BB00083AF5D6ECF817B5CB1C48DDF1976BABBEC
-:104BC000EFCFE0787124246F9BFF5EB5830B95389F
-:104BD000A2B441DC223A97FDFE8342A2DDF0FDA2A1
-:104BE0009FC46A78AF69BDD3837A3822DFB8D9BD54
-:104BF0001A3D9E1457C8EE51FE5FBBEBC4160080F1
-:104C0000000000001F8B080000000000000BB57DB5
-:104C10000B7854C5F5F8DCBD77379B6437D9900421
-:104C2000C2FB6EDE0921591E09A82837E16110D0A8
-:104C30000511505137E1FD4AE2A396AA9505621A83
-:104C4000296D8380528BBAD050FD5AB480B4828DC6
-:104C50007603D162AB36A0566DD52E101194C70ADB
-:104C6000948FFAC3F29F7366267BEFCDE681ED3F0A
-:104C7000FDEA30F7CE9DC779CF3967660921E40A8E
-:104C8000FD7F92A6B485EC04FFA09E4C747537FCA2
-:104C90005723A4373CA77F2A211365072123E977EF
-:104CA000132C811809DF4FC9A2EF1DEC1392944A0F
-:104CB0003C41783FD5E1F1D3F60E876F0A49206475
-:104CC0004382F6A6444BE2518E8672A12B955C4935
-:104CD0002724B120E4B7D0C789A3E973DD3CE89F5E
-:104CE000E475E2FC8E9AE677543FBFFEAA33E5787E
-:104CF0003CAD2844B922D3F1ECAD84D0D2E951CEF9
-:104D0000C13891FEFC4429A1E3F0792612FA9EF6FF
-:104D1000E396362A57E83A5CC425910C1CCFF4DDA3
-:104D20000017F60F75DAEF5EF8C73584F45BA6B6A8
-:104D3000D8E83ABD76C90560E843E7DA0A40505A38
-:104D40006D008CA71CA21EB49102DA6ECF215B8885
-:104D500096CB771EC2F716A8D332395E1DDF7F18B7
-:104D600021930359DEB43C68579166F160BD554903
-:104D700025A46E9A2FCD320CA69FD5D0328090E715
-:104D8000494DBE44DFDB6BDDAD07AF27005A3A1952
-:104D900078EF6ED50AE03DAF131224741DCFC7B56E
-:104DA000D7357B1AADA7B7D7FD506F04E05F0BE393
-:104DB000B95B6BE9F7BB54EF44958E3BED190B9152
-:104DC0005208197BC91190800E42BD08E90B9FD58E
-:104DD000C4015EAEC0DFD84809F025A99176E6F798
-:104DE000E676749EE53BE9FAA7F92ABCE347103260
-:104DF0004A627025AED088E94E9847E56CB538F226
-:104E0000DDB467CEC9E9747EB3294D11FA3CB1DC3B
-:104E100075532E9D5FE2160A2D15DAFBEE82796737
-:104E20003DE2B300798C25A1FB258A4FF2490ACED9
-:104E3000478C53F79A8CF45BF79825B01AE957958D
-:104E4000BC43F5F80B99F01766F8DB7B04F157D5F6
-:104E50007484E16FEFD666C07F5593E48A51613D5B
-:104E60009E5D9488C8FD816BBCCA408AD798701D2E
-:104E7000E0D54A4679A7C4225CEF85F574802B9F64
-:104E80005F77707DFEC4B61F17D2A6FE53164F166D
-:104E900089C04BB4DBACDA102E7DD27D8F021CAA08
-:104EA0003786EA62E9BC5E3D7138C147E79B75EA27
-:104EB0005CB090CE376B0CB271FBB8CF9FDAD66C7A
-:104EC000A3FF7C1EE898BEC826BED52E4757F060CB
-:104ED000F4DD0E8F3D47103E16A8D3E7BB6D64117D
-:104EE000E0B56CAFA40580BE63C83D5E5AAE572DD9
-:104EF000B88EEDAACC4B89E1F154BAA2D2EFCB66C1
-:104F000058B4002D137919597F2DB6DBAE2A580AF3
-:104F100078087C0A3A22A4217E1AC5635A8EEF597A
-:104F200023DD3C119F4EDF8F6D3B7A3FB144BEDBEA
-:104F3000BE9278E75923ED28FD3C6CF86EC2F7E28B
-:104F40007C0591F64097402766FCD0EF7630BC3E5A
-:104F5000110FEBD8D7764E0678F714AFE6E7AD2BF6
-:104F60007DDEF1D6CEF9C75B2A7B01AEE6E7418054
-:104F70002FC2C7EE6FCB05A92D91440A6AB9AF2F96
-:104F800008F35B6E0F25CCA0F8AD2A3D6F0338AC5B
-:104F90008E3F739D2F4A3F9DCDA3F5728EC34BD795
-:104FA000B7FF520CC2DBDCFE2B8ECF7757CEF68ECE
-:104FB000A704FA785C42210A5B3F793F93EA87F1C4
-:104FC0005CEE8ECF5C3285092DC5CFE5B8742586A1
-:104FD000A0425068BB09F084CEAF7CF42E85A44378
-:104FE0009DB613F2D88DFD6E2345800F6B1B3CB729
-:104FF000D3FF811E999C79D349D02FAD4A684D22A9
-:10500000057D6B9A84FAE7C6CB0D2DA0BB6E4CB321
-:105010001AF4DC24D5589F0C7A4F37CE348DE29D9C
-:10502000BF3F8FFF0DE0FA6E56296869FF3767C6EC
-:1050300005FC74C9B78CBEDD3B5EA72F0E7D2BDF50
-:10504000E32DE8089FD16E011F2FC2F595580A9FE6
-:10505000225867452DD3495DC3C30C47335CC67FD7
-:10506000B2600A29EC08979EAEBF1DAE84FC04D640
-:10507000375993C95A7704AE66F8D0BFA9D0EE501D
-:10508000296D27815D704AB1D0FAA46B2422EC828D
-:10509000097ABCF3F999E16A869FB03726F3EFDE0F
-:1050A0000678517A9A2C6F71003D4CFA61EBF864E6
-:1050B0002AC7260D64F825410A5CAAD76F20083359
-:1050C00080EB36A43B9715ED0CAAD7197D7C32F105
-:1050D000A444C79F7289BEA3F39CA84A01CA2200B8
-:1050E00097A326B81C35D1C551FDBACDF37D05FE79
-:1050F000714D147A511A7281EF8BDCDC3E1944D465
-:105100002B541F957C3C3291C987E87A72EC256F4D
-:105110007B3F0C1E0D483712F1B53F77D17E829A46
-:10512000358582818CB3BB904FC6116D4D9B1D4060
-:1051300021E33CC5BC4EA6793537FDBE944C5AD30D
-:10514000A687F327429F33788FE3F01B47FCCD728D
-:105150000294CA05FDBA457F93C47A0693C1600FD5
-:1051600035AB2AD3FBBC3FB1BEE4641294E804C360
-:10517000923DB04D82F913BFAD57643C2BC7EFC7CA
-:1051800099D36F75A3DCAA21002F305B009F65FCCB
-:105190007D99DD1184F910BBF5543B5EC086217307
-:1051A0005CC787205CC895F8C8FC2ADC92723C3743
-:1051B00032BFD307ED7E99D2B5A7AF6FBE9BCEF3BA
-:1051C00094F47621C08BDA65D920CFCDEFCF7FD490
-:1051D0005205EF69BB05D88EAF6BA92C21DD845F2A
-:1051E0008B096C734793E7AB98FCB5534BB42442DF
-:1051F000F765718CCF2713AF02F6E5FE58C6672D11
-:10520000B18B911F26929ADAA1B4BFBFC4DD78108A
-:10521000F86C12F163BB092E231D7647A73791F076
-:10522000DD60F74ECEB59AEC683FE2677F6C4E26A4
-:10523000E8B3FDB14C2E0BFBE149B7778D1BDF0FB7
-:105240000A805C3EAA15BF0B7AA2B274C4DF46D2B4
-:10525000D262F7DA009FF381BE285C47037DD16FED
-:10526000F743D77D91BED601FEE6D69BE8CB9E8C58
-:10527000FD7BA91883799569D66FF476753BDCB808
-:105280009EECCE5E242D0AC9A5709DC7E9747F6C83
-:105290008C1FECB8B2C7291F53F8CD25BE671B245D
-:1052A0009887D560BFCF8BB5A2BD37EFE7B1C8EF08
-:1052B000F4E32D3574C805F4F95ADA0FC95507E837
-:1052C000F53A69D07D0FF8B7AB488FF35CEC591B0A
-:1052D000EDA36F2FE8974A370A4FB2D97A4E4F970E
-:1052E000E6F13BEDD7F4DD7E89CC06BDBADFAA0E30
-:1052F000F0E8F4C76E37B39BCED9B3B658D23B872C
-:10530000D3027BB2A68C88D48FC7C6CE8E66278880
-:10531000FE045C23FB8B130D2D6322FB0BCBAA2F0A
-:105320004CFB8B2FFEABFDC5A1AD5FB4D6D2F934DB
-:10533000647AFF0EF446146F1EC07D13B71729A5BB
-:10534000E44DD3E1E1EF6E66CFF45E318E1CA3A491
-:10535000146327FED8E194DF15E2B70E87F6BE5539
-:10536000168A57653641FD43E50DDA99E6F57E9CD0
-:1053700059F6198C27F8B02C8ED239E5BBC72D6AA7
-:105380006303D8D37F96A96D49475F3117EDBC5BA6
-:10539000572CC6F2ECD1CBD9C0FF651CAEA7417F1C
-:1053A000835D1DCFF8A73A9EF1CB2B69BED340FF9A
-:1053B000AD9AEC1C49FB5BBA57F6C4E0F2C38360BC
-:1053C0007DB74E9553E1F931BB15F789FB9D0CCFA5
-:1053D000C78854BE13ECDE4331DE3DB45C9056EA20
-:1053E0004AD7D9830BD2C6639D9453C38ED2DF7D37
-:1053F0007646F7C7889BCDBB5EF26CA78FCED5BB38
-:1054000013810EF75B89C1EEB0A4337BD992CEE055
-:1054100058798932E108465F3574FC4A45B5819D6B
-:105420005F79C986CF611E487FB1C67EE2793FF1C0
-:10543000EDFD48E80CD81F6BEE4761CF391D9BF19D
-:10544000F0A87B5C22AC67419AE64A4779AF2A0014
-:105450009FB2912D1F81DCEB5ECEFB2590F3D5979B
-:10546000A5E060BAFE537BACB87F3BC5EDFFD37BB4
-:105470000EF4AEA4E5F25DEF25C03ED19DCEF075F1
-:105480005A694D80F92DFB1DB59B0B906C7BDF8914
-:10549000DFCF2D59CB86B1EBF5DFB5DF660CF062BF
-:1054A0003B3AC19288FD35CEEE0FC0FCF6AF926755
-:1054B00003DEA87E14F69704F270C21E598B2DEC01
-:1054C00068978D4AB7727E63787CC0C5C6E98C8FB9
-:1054D000CB2EC593808E8FCB145581F9975D4AC032
-:1054E000E7A74F6CDB7033A57B7F9A15F781747B40
-:1054F000D48276A1C4FAA56CDD9249C769E1EB7943
-:1055000063CFAD33AEA3FF7C13F40C6D333EE44B9D
-:10551000614C4D777125113B6B82CB680F9AED453D
-:10552000A1B7CA9BD6D7F62700F7C0ADD7011D9EFD
-:105530005008D061077BDA7E632776E37A84C7ABB5
-:105540007B7E89FBA53EE92AE3AB3DE727021D5799
-:1055500091E04CE8B76A8FEC0AD2D66F903D434099
-:105560007F08FDDEBEDFB97CC0EE01F91F2BBB5604
-:10557000C33AEDB739540AA7EBCE16A4A09EB35B8D
-:10558000CB41FE95C56639E6EAE8797F8A5C0E7400
-:10559000F0464A86F1B97DC310D073FB2C4C1EB582
-:1055A0001CBFC311C276B7A6A0BD26F4BBC93E1569
-:1055B000FEB0495972209ADD4BE42D1B63E9FBC90B
-:1055C000395622839D1E5A827ABF837EBFECC37DEB
-:1055D0008059CF0BB8534823BF74B04F237036D8CF
-:1055E000A98FA6533B6D08D2C050B03B8397372C90
-:1055F00085799E6D8A77AD46BF03B36BCEB62DD944
-:1056000030159EBF2DA31FE5EC6519F969FFEB4B23
-:105610000787747C4C3505E2E9E2B0AFCFFC81E24C
-:10562000E7E2E7711E3F3C56760E89B62F16FB2542
-:105630003A723F4B1ACEBF9F6534B21BEE4F6F8854
-:10564000EC4F37A6E3FE343C11D446DA962336A05D
-:105650008BD3D45487F9FA29F2B753B8DEA0856406
-:10566000976E3E2FA44BDCDFA13D0D72C54FCAFAE9
-:1056700053E3842C8AD34AAF03BB731A716DA3EB37
-:1056800079ED449964A5F531DBDD1E89D67783E198
-:105690000974FB3B39B09DC2613795C7BB69BF8BAD
-:1056A0005B1B6C6E3AAE7F0F9DD4285AA7880438D6
-:1056B0009CB0FA0725E9E8645606932B27ACBEE7B1
-:1056C000A09F131FC710D8079EF83C2EAABE1D9C92
-:1056D000C1F4ED1FB89EFB37A7F7E0A957DFEC47F1
-:1056E000E715BCE41A06705FF2C2D772051DE77AAF
-:1056F0006E974DD9D85A0BFE9B9BB78415903FDE11
-:10570000806B02A8DAE92F78ACA09766ECF05AC15A
-:105710000C9FB9A7C60AEF67EF6D7803EA770477A5
-:1057200062FD7CBAEF8F00971BEAC307805C321BD7
-:1057300088027C412E307BEB533E8FF44B9EFD89DB
-:1057400048D5A516A0F3F6F11F6955C0F4B9B9966E
-:105750008D4FFB7B0BF074434D781CE8B7412B5801
-:105760007F8348F3AA4435D2EFD8CBAD92DEAFF0B9
-:10577000EC438E454CEE32B80F7AB8DFD6B5C82769
-:10578000AE38D0F782AFCA1E766880EF8B3F880BA9
-:10579000C4B881CE98BD7DF1078E803F8ABD1DA122
-:1057A000B3600CA32F416FC4CEEA9A1DE8EDC12768
-:1057B0006BE2407EA478559B4F87C7B20D53F2DF52
-:1057C00082FE6363D07FD73EDE7A361EFD3E1FE841
-:1057D0005AE8B34AA007835F4AC803C617B48B00D0
-:1057E0008C2B4A22AD76117D9D04D3603E9F03DC55
-:1057F000E9778D36750E8CD71817E382F12AED59AB
-:1058000036905FED7E5070265239721DB73B5F3B7C
-:10581000B13F19F07E71D8AA41B03F085A7E81F29B
-:10582000AA3BBABB2D5DFB0FD3B7FE41B0BF12ED53
-:10583000F71D8F2B007DF9079077801F4FC56058AB
-:10584000AFF8AE7F06D3F7945F70FD824F525A894E
-:10585000B6B50041A5EDD6C1A337E70B51EEB6AA08
-:105860007EC667D44E01BE7306ED19C0CFFB32B0C1
-:105870009EE2250E0F7D5FBD37CB23AB28077A67ED
-:10588000A446E4C3F55C3EA4B486912F7BBA4FF8DE
-:1058900096C337A8ECE4FC45504E017F31391EEC2D
-:1058A000CFE490BF3FE005E406C74F5F89960B3910
-:1058B0009EC5BA53B85CB84EAC0BEC375A2FC960D2
-:1058C000F247BC1FC9E136412E480C45F1FFB4D365
-:1058D000DD8ABE04ECC9092BFA635992C1E6BBD834
-:1058E000BE1EFDAA8B53D6A33F35456BC072F1F89F
-:1058F000067C9EB6A502E963F166C9E01F15E5CFF7
-:10590000B87D76FA8405F51BB1C4F503FA13EF37B9
-:10591000723BA44FBAAF0CE07C72CF86270BD588C0
-:105920007FF8626CC3CD7700FD6F975DAB003F8D54
-:105930001324350A5DE9E107F0AA6EFCD744985FAD
-:105940001509D5817C569B24949FEA5E5AF6A1C422
-:10595000DFC8E4E9496EA72D8A33DA97B338DC4E05
-:10596000585B2717D1F183E73287835F27A88464C8
-:1059700085E18F007F801C7621BDAF1DF410D09192
-:10598000E444FB07E4EA2E1D7D2CDDB1B5AE1FFD1E
-:10599000E70D975DC364EC8738F4F25BD08990C75C
-:1059A000E6F52DE6781574785D444F2DCEE07E54F3
-:1059B0004059D5FA73E8477D94E3AF11E80DF8B983
-:1059C0005ED0DB300BCA5B131F8FFA1FC9F77D4F08
-:1059D0003C3D08FD13A329DF52BE3E097C1D852EE8
-:1059E000EADAE5806F5546147D7052F23D979C11BE
-:1059F000F97EDFF19BF22B75FDF8383C2E5A7D8342
-:105A00005D51E015812BE907F4B0886206E040B6ED
-:105A1000482EB00BC5FB942D2C1EF014E723F15C2F
-:105A2000D405BCC702BC3310DE4FC17CA95D600346
-:105A3000959D16607601B1DCD40FF4FCE238ED26BA
-:105A4000F4C7ACB710F02F11A90CE93DA571D3F143
-:105A50006F4742199B8EF1156A77031D2D7E5CC539
-:105A60007DE2EA5FC5225DBE98918EEB5ADD6865E6
-:105A7000F4696D40FA3AF9F992C1109FF153BD9E55
-:105A80001545EFD499F4F943194C8F0ABA4B5FC707
-:105A9000E8AE51D1E2927474F93CD18683DC167A77
-:105AA000A5337A8CD0916B98A0A30AFA3CBD3E2412
-:105AB00003BE281E5F053ACC58174679D6191E45F5
-:105AC0001C4EE053C8F9FFF0F98BF1DFE6723E851A
-:105AD000DB3B1DF1BACAC00FD747F8E12F0C3F11CD
-:105AE0007EB0AA91F5FC9EC3A533BEC8CF7461BF3A
-:105AF000759F6EB81BF8B96E7D9C673589C4734479
-:105B00009C55CCE3334E879DC56376A9BE4F334C7D
-:105B1000F14215E53D8BBF4CE076FA7DDB63D0BEEC
-:105B2000D807AF408EB4C505C0BE14DFE528445386
-:105B30008613F255861BE79F032284D65356D84816
-:105B4000261DF7E235CD2D09B4FDD470684A115DEC
-:105B5000E23E5B68C62DE01726DA12B033D0970F0D
-:105B6000F47F8AF54B5C3B0DF3FC1787B7C04FDD24
-:105B7000A773D3A2C50B041C3BC34B7E268F9FF19A
-:105B8000F766FE6F15FAAAC7FCEB4F04FEBD81F85D
-:105B90005741FC845C262ED0D3EDFC7B99B0F85C99
-:105BA000A6917F453D0AFF2666EAF9F75288F12F54
-:105BB000E7D3C446AB16CD6E19986965EB6A9C5065
-:105BC0000AFA28D14BD06F429789FCBE98F23BF07D
-:105BD000B11FF8B60FC093C9DF74ADE16E789FDED8
-:105BE000C8ECF18B496CBD8BAFD79A65E07FBA1FCB
-:105BF0009068D306CEEF9DC33D982831FD9608727C
-:105C0000E68631A171A08755881BF481F531FC8EA1
-:105C10001D4302418A77F53261F2E3F3A7EF7E0874
-:105C2000E4C67A87274B8DE8A54FD37DC332533B1B
-:105C3000E76B4A971AF8B1EEFBB783ED1F3B899FDC
-:105C40008F5D2123FD513ABF365307FFB1DEB00C03
-:105C5000704D8EF7A55993E83EB0316BBA7D205D4B
-:105C60009F9BDABDB45E4EEBEBC02FD72B4478FD83
-:105C70000947DFFF224F2033F330F8F1966768932E
-:105C8000328B31AE3D19E67343FFB08CF2AD87F134
-:105C9000FF6AF0EBD1F51CBD2DFF5715F469E5ED5A
-:105CA000DE3A782BFCCCA3B89FB9BA6918FA9F7575
-:105CB000FEE63B60BCCEFCCDDD8D9BC0F99ED237AD
-:105CC000EEFF12468765908F42AE2CCAECC5E939CB
-:105CD00044A60F8DF017C825B077451E02F8239D06
-:105CE00018CF0820FD413D717844DEAC6BB094477D
-:105CF000A3EFEF673AA2CA53D2F47FBF7FA884AE66
-:105D0000175E31F9FAFD4C9D7C6D6C38DA9BD9AF8A
-:105D100054FB537BE27EEE03D8B0DAF3D74CA0BB42
-:105D20007765F4C35C1363F34BE02FD088EAEACDC8
-:105D3000FB03B66B9282CE425AFF46221AF837BF57
-:105D400091B1DCF0A8B7DC0DFE968F2C287FABC09C
-:105D50007EA3F0193D9804ECF49F7BB9DFB4F4986E
-:105D600043833C81B3921DE5E7D923717ED0AB67B5
-:105D70009D16F4ABB7BC16837C713E338EFB41029B
-:105D8000067F8988F79C7F7B6E32C8FF2779FCF3FA
-:105D9000C958E68F7DF2F66CF4630A7FAFA250D843
-:105DA000F782B41E0AD75E6037F7473FACF0FFF6C4
-:105DB000B657482CE9888DA3D8D9FA7A2B3E09FC2E
-:105DC000E75BBBC997F84DA64DD8C38D00E7EA47FE
-:105DD0004236D8EF0A7B58E8EDC1A7D29B216F620B
-:105DE000703973AF6D3D65B1C03AB752724A727780
-:105DF000A42F41475B3BE625ECCAD4EBA7C7585E0E
-:105E0000427B9D7FF71CCF4B18DB76F465B0F328FF
-:105E1000BF6F357C372135CE17456ECD5CF1307EB6
-:105E2000DF19FDCFB4105F343DF21ED72344A9E93A
-:105E30000F7A8AFCF3C178358A3F67E6A795A900F7
-:105E400017B31F2E32FEA338FE3B99EDF1CE411061
-:105E50007FEB2EDE699EF7DFACBE81D1F494C0B338
-:105E600079BC8EDFB3FD597B3B1BF1ED72B07E87B1
-:105E7000EBFA55B2981D345362F17CF22D417D2D21
-:105E8000E884C2FD0BA08B92778E8D88C338505862
-:105E9000067970FEA3CC01188FEF643F2AE6432DEC
-:105EA000E7AC68791F743C6F343C48594C8FCEB4D2
-:105EB000B23886747B16FA0766C6C648313AFBE4E8
-:105EC00074BBBED50C71DBFDB1A346A2DFD3AA0E15
-:105ED00088063F733CF774264178025C3C51E849E0
-:105EE000C49D059CEB4AB55285F9D5C83650811A38
-:105EF00093A329E504E36FA3240DE1910C467331CC
-:105F0000D03FCBA73BFFB68C72A1A4540D4008959F
-:105F1000EA8BA4AC62CCCF7AD9A2CBCF127452F761
-:105F200022D5CB06BFA3DFB0AF4EE2F2985A8FDA8C
-:105F30002E5D3BF5119001117D30A0D66EA80F7A31
-:105F4000C045149DBE48D2D20CF5015E571CECA78B
-:105F50000694AB86EF04DD89FC40FC4B8175BB02E7
-:105F6000901FD18BCF6794E443BA01F9067EE561B7
-:105F70001C9F74BD4559B41C5B1E3AAFA71BB1DE14
-:105F8000EED67574259D0F15606D2BE97CA95C9884
-:105F9000BBCEBD2A0DE1EE22B0CF38BED28ECFE708
-:105FA000F3EF933656D4F5A54324D5AAE8CF4DD2C6
-:105FB0006ADEEC0BF99835B44EFFE6354812F87DF1
-:105FC000A89CC1EF9E59E9C252E0DB45DF4BF4BD0E
-:105FD000BF8CE4427CA7333DE6CD7218ECBE2EF4B4
-:105FE0009837ABB8A31EB3D83D6F417EC0F2265997
-:105FF00005BA5833A517FAFF36EC943CE08F3BD036
-:10600000C4F2F436CC64FA448C7BE67789A837CEA8
-:10601000488CCF494B12F2417512C74D6D12C66BB9
-:10602000CFF2FDF6B24C9F2F4B672F6D682A8EC5BD
-:10603000B8AD492FD13F9744BFC3D89D04F6D3B024
-:106040007A2503E5C022F89E2C088D88CD00BAF58C
-:10605000BD37460239706110E0D31C0F1471431133
-:106060004F7C25CD77AF7EFC8E7142637C4B4EB06A
-:10607000E7029F8D96E33CB251FF12C0EB1AB013BA
-:1060800029DDAD391287F059F32DE33F3ACF1F02D6
-:106090009C5B9C25484F42CFD27916BE4B3ACEB37B
-:1060A000DA12463FA26E9E7559C55DCDD39407CBDB
-:1060B000E7D50E7F1ED7929D0ACEFF2C89F3C03CF8
-:1060C000F7DA3C1FF9400F9F8943BF9FC04F15E788
-:1060D000B1B3141F129DE7D9BD23622D0EB08F7C82
-:1060E0004F02BCE481E104B0CF0F348DC883F57456
-:1060F00016DFDD9B59F67416F299EF19E43357E871
-:10610000FC4B6A64FD5DC485B742FBAB80CFAFBB7F
-:10611000C6A3113ED58AA35E628E75B4C3242EA792
-:10612000CD74273535FF1BF29228BF615EA87F1022
-:1061300009ACA170AB1BCAE88FCC232AEA65139D7A
-:106140002CCBF4BE0AF8127CDA057C5E8779DF93EB
-:10615000E90D4209F3E83F1CE5D2FE2CA6DF5EB64E
-:1061600059F07B96DF9244305FC71C77FF38B3F25B
-:106170002DFC5ED85FB93EC95570557C70B86BF880
-:1061800005912E9673382D877830E4B3EDB19E32A9
-:10619000E44D98E0F0FD4CEF270C0E94CE46323AD9
-:1061A0005B43BA844708DADF93E93B06A5D34AE9A3
-:1061B000058032BA220DE0BC4BD5303F61F72A068C
-:1061C0008FB3EF3078EC6BB3205D6F22F9C897C3C3
-:1061D0002DE7EE86FEA97C390DEB1A13DE29C1BE30
-:1061E000B9CF22D50272B97FD8235BBAA6DBAFB391
-:1061F00070FFE4BBC0F1703FE061C4DBCCAFD305FE
-:10620000DD5EE274DB53B84BD95DF27507BAB26656
-:10621000A746E8AAA7F958942E48FF5E1DFBA3FBEA
-:10622000288C3B34EF8B417955B55B42795EF5FAAA
-:1062300017B85FAF7A35068972FCABB1F8FEDC1E89
-:10624000F6FE4C69F43C8284EC5EA8A796EFBCD7BE
-:106250006BD4D37ED4473FD3CEB932E5485C367990
-:106260002A3BA7B086E73D89F86C02A7B3E4815EBC
-:106270000DF450F20482F984090E96A7D8F13C027D
-:10628000E3DB54FE9DCBA54A0067F3F904398EE5A4
-:106290001FA692755F039C92CB8DEF531DE518AF3F
-:1062A0004D359D6310F02ECEE6F6B38DA4811CD93A
-:1062B00069CAC710E5FE6C6E07D626E17E50E1F391
-:1062C0006A71DA906EEF73DA71DDF72591E429587F
-:1062D0005750FF9BFB1165926621AAFE9C45791CD5
-:1062E0005175F651AAB797A1DE67763F43FBBEBE54
-:1062F00074C3FBFE8BF20DEF07D60C37D407AFB893
-:10630000D6D0DE4D01A0AF67D4DF64689FD530DD05
-:1063100050CFD97C87A17D5EA0D2F07EC80B4B0CFC
-:10632000EF87EEBCCF502FDAFB90A1BDDC895DFE7C
-:10633000A36CB63F92855DEE1CE903BA929D762967
-:1063400046B7FFABE4F8284D284F83B879AD7362A8
-:106350001AEC4F5B92A83EEEC2EFF65DF76D7E81C0
-:106360007F6E7F9571BFDB99FD548A50FAAB3A403E
-:10637000E9A008ED2F7F36F72354A8D03E6C437D6B
-:10638000A278701D3313ECE84F33F75F99AD1AFC18
-:106390007C621F205B3CAE2952E7F01274D91DBC11
-:1063A000EA395CFF5B78FDCD946F24F67BE6EFFE67
-:1063B000986DE1F6B86F5BB67E5F47C2B217F775AE
-:1063C00017CEF809C85182764D75BC0BFD12663B9D
-:1063D000408CFF4A9AF7372057CDF2D4BB62016B4D
-:1063E00067A11B0CB9F3FDDE1FB3CDFBBD09B311D3
-:1063F0001F4936039C5E6CC7B366D8EFD52695E07F
-:106400007EAFD6AAA5F564BFF762364178D7035EA2
-:1064100075FB3AD9E6515D28E78DF64B47FB9CEAC0
-:106420003FBACE0D60D749609725337B7DB784EBAB
-:1064300016E37E07FBFCFDEC1ED8E731C453AFC862
-:1064400088BFBF67337BFCFE58F93BD9E3C7AE4634
-:106450001F1EB67A30CFFDF05499ACA2703C5F3E5F
-:10646000AA0F89228F45F93EF7DF6CCB2188B7EE62
-:10647000FC1F87572EEAF2BCC7E1492C8F733AD034
-:10648000916EDCD81C46171939DC7F13C3FC18A7A2
-:106490007FEFC47309A76FFA208138212F6EC4489B
-:1064A0003FE43913CF0390B7E37738D14F387D52AB
-:1064B000F1C8554E1D5D8D66701EF7CA3B09E0FFA1
-:1064C00099BE2B23D5EFE89C9E32F8FA8812CAC6F3
-:1064D000BCED3F9CECADD272FABEAC54E6A734E6FC
-:1064E000BB99FD46D3575419F878F925890492755C
-:1064F00075A515F30A975F52F0F9E96CA35FA953EC
-:1065000078F5109EE6E7029E87279D1C04FEF43373
-:10651000B1D1ED8F5B38BCDBE9C7744EA6B3F31F76
-:1065200025BCFFF3E5D7F4013937DDA666F5C4CF06
-:1065300025E0D47AF98B789013AFC3F99B28FD1727
-:10654000E5B0B8D2EBDAE7703C8294DAC3E380EED0
-:106550004BB93F3DCAB9807139E087B954FE3F3924
-:10656000173025C7782E202D478D7A2EA0BBF34DEE
-:10657000D36CD1F55D6E047E1F00BFDEFF8CD505A8
-:10658000F35A08B613F8EFB65AD17FF7DEE51802D2
-:10659000F1942FB6587F09796E8B9EC9786623AD2A
-:1065A0002F9A1483F19F855BAD2C3E37293600AEC0
-:1065B000AA455BBFD77B2E1DEF2BCAB7CBB2E8FB3A
-:1065C0006736615ECD7B6D6B31BFFB24F0337DBEE2
-:1065D000E8DB1FCD04F8EFB3350C190676FF0EC9C2
-:1065E000704E634963ACA12EF20805FE881439BFD2
-:1065F000A1527DF2608EF1BCD68848DCECC11CE66D
-:106600002FC13CFCAAA9ECBCD681E36CBFFF462697
-:10661000CB330C4E9A3565185DC7A4542BFA4BCC7E
-:1066200079898420D2C9029E373CE96305CFE54EC3
-:106630001AEA443BF0CD95358807FA9D6382EEBC9B
-:10664000C2A49F33BFCB2437CBABEF345FD194A729
-:1066500028CE0F75C84F8C9C1F3A1A8D6E36E4F009
-:106660003C45CED7078EB37CC4056FCB6C5DDDC8CF
-:10667000CDF7F93ADE6BCBBFEB250A8FF7CA991439
-:106680007FEFF28D8F81DFEB0BAF44203FF48BCB9C
-:10669000D1CFAD7DDEAE5F7DEDE77A003FB7962FBF
-:1066A0006EAF035BDEE6BDD770EEA7E7F2A66B79AF
-:1066B000322B87C521CCF2DD4CF7FFBFE4FBF44958
-:1066C0006F0CF23BB1FC1594A77631F968E673B311
-:1066D0003C17F332CF77F925D990BF9CCBE54044E6
-:1066E0009EDBF03D35F7713DFE1225B046423BE0A2
-:1066F000831CDA6EA423905C4A87A8756D8BEFCA61
-:106700007F43F7CF1F43FB3BDCBE4FA04CFE4BBF8C
-:1067100032D0F723DEDE89F987673BC9436F769B6A
-:10672000F2DA2463BCE0CB9CD266C8E77F50A5A513
-:10673000CEBE1E499990E73D7CC9F9F3A710B7ACCE
-:106740007AEB22F2E7269B2F0DFC03FE7E36CFF676
-:106750002879231772AEEE3CC316EE9F27B9B9868F
-:10676000781FF889306FE1681CFA89D6A669DFC006
-:106770007C9E4BD3FE0FCA2169DAE51C1D5E6AF9C7
-:106780003A154B74BBB83857D0BF17F5F8FC322A0E
-:106790007FA3D0A19ACBCE01943E79FB20F0C77D98
-:1067A0007EE48E41201F5B368DEA32DFED67C09FAD
-:1067B000547EFE18E47E56249EFA13CE37C2DF3D87
-:1067C000DFE6CDD6E769C9B949385EC235BB5BD3D0
-:1067D000299DB4AD93517EB739587EDB318752DEA7
-:1067E00058C0BE4B317CA7B0FD07D03DE563C5A1C5
-:1067F0007CA39747C5B90CAE9DADB33897ED136C2C
-:10680000C46387EF6D476FB2831E9525CDC5FCFF2E
-:106810008C1EAEA123003DFC88CBB19369BEA2DCE7
-:1068200062F88EE9DB6BB8BE551C26FD3AA0EBF88A
-:1068300078639A3632978E3F314D2B86FEF6DAFC1E
-:1068400043806FF6C645CF57BB2E97D923FFCEE1C5
-:10685000F4421C68BFE27832C6E96FC865717A0DF0
-:10686000CA1BFA87D7401E7AB3DBC5DB87F0DC1D75
-:106870007D3F01DE93B410B905F2E7E864E17CC422
-:106880001F4E1C2520BF12C26D04F269124C79B054
-:10689000A2FC0787DBAB3CEED991EFD83CBD1CFED8
-:1068A0008D945FE0BCA8E01788AF43BEC483AA8F75
-:1068B000F31DCBF7687CA297047196744DB5007DEB
-:1068C00040FE29C827737ED08E5C76FE1DF850EA04
-:1068D000820FE7F379F6940F1B9F98628985793EC2
-:1068E0004430AF8372C26A3BAD3F7B9FCB03E7C7A7
-:1068F00032D611DC070D5C11B70DF649351C1F832C
-:106900003792D5B1B4B59BE7F7897C6A776D48C1FA
-:1069100073060FB1FCBD939FDF243BA1FFAF45FF82
-:10692000C67C4191DFE7CFB518ECC2DBD27D0F23E7
-:106930003E4DF9D89DE7817D9907790E3F11FCCE38
-:10694000F370C6F03C9C318D9BD01F37A6F14645B5
-:10695000A24D9E558212ECF79EADD114D037CFE5F3
-:10696000B2BC9CEEF2E39EE6FDFB01CFA99DE75988
-:106970003ED92E773AE4593E999BAACB2BFB01CB0B
-:10698000B3FC7E2ED323CFF23C9A676B98BF6EC9BF
-:106990000B8750DE8B71443B918F37E001968FF768
-:1069A000AC128A05FAB9184BDAF3CC57A1533E342E
-:1069B0002CFAF90591576ECC271F1C0E97623E10DA
-:1069C00021784F42BF3CD5A007B7865D71C02FDD4F
-:1069D000E983DFE75E9D3E782A8FF14D14BDD9949F
-:1069E0007B757A33087443F5E60128AF5A6F727DE0
-:1069F00029F4A7787F88E373562ED39F51F4E621BC
-:106A00008E5783DE4C2101CCD320A72C1E7DBEA83F
-:106A100028BDBCDF97D3B50F61BE63B83F25E1D475
-:106A20005122E9E45019E76B71FFC4F3BDC83DD3AF
-:106A3000A2ACE37ACE9F963961BCAF22A1498A9A73
-:106A400087D6ECB689F8ED1730EF1B0653B92975D8
-:106A5000949B51F07106E6D9FF6DED0010C9B54960
-:106A60008DF1603E75818F73B968C768E7A114F036
-:106A70001F7EC5B88F14F0FF86C3C396A5FD1BC645
-:106A8000F913E7B3CEF0129BC7F0D12F8FD9332281
-:106A90007F7DB7C91E1D91C7E0322ACFC8973AFC47
-:106AA000C5E645B17B841C7E39DDEB80F7AF9ED80F
-:106AB0001D0F7424F024E48F195F113E5B85E352AF
-:106AC00038A7E6A576D43FE27BB31E8A7CEFC7F9F0
-:106AD0006E053A1AC9F27DF07C013FA720E627E84F
-:106AE000DCC3D779205D73E715779CA7EB9445EA63
-:106AF0006A9E49E11409F83F497361F98713160941
-:106B0000E6E50A2B982FEFE2FAD1AC07A9B8E074BA
-:106B1000C3FA798ACB8DBAD32C0FB1AED49706FEC7
-:106B2000FFDE59DAC83CE423AD18CABC2CAD04E63C
-:106B3000D9EC66788ECDD346435DE40B98E7A9E5A2
-:106B4000B5E71D8C857609E3891FF421DC370371D5
-:106B500096049EC790A0B9CA408F256C21982790B3
-:106B60001C1F6E8E81F8DF26E2817353D97ED50219
-:106B7000FBAF8C07B4D550D69DE6F7E694123C7770
-:106B8000D99E47579B8E7974C06F7A7A9DCEE73134
-:106B90003D8FF125B5436EC963F39A06A5B0430452
-:106BA0001F756657E8F87076DED5F1E13DD0FE2A14
-:106BB000F8706E1EE3C379793DE0C3A579ED7CB82A
-:106BC00004DA77C7870F71FE7BAA1B3EFC39A7CF7B
-:106BD000E7F23A95A30FE54595A38C1E04BD031F6C
-:106BE00082BE6FE0FD51F9B9321ABDF7802FEBF389
-:106BF0007A6017B6F7D743FAEFCCFE8BCFEFDAFE09
-:106C0000DB0279E3BAFD1EE597A7617E945F7E0102
-:106C100025E5972D8C5F54965F6EE2AF767D136607
-:106C20007202F2F3F4795ABFCB6BD737DB01CEE6B1
-:106C3000BC9C31267FFE3B9CBE9B7899103E4A400F
-:106C40002E50B8BDA4A7D7E739BFF847B3BC53AAA5
-:106C5000D9CAC0AEDC778ADA91003E2E0FC66C6EC0
-:106C60003D007623511AE2E11EACCEE0D42B5F1535
-:106C7000F99551E144C7FF633479DA04787374B449
-:106C8000E7CDF8DA91C7E83CC4E1F15DE721E00720
-:106C9000F328C279A896B53A3DFF41445EBD0F780E
-:106CA0001B3B3E2C139C57301EE227429E9201F460
-:106CB000FB911DBFFF24F2FD27B0DEB11AFDBE20FF
-:106CC000F27D12B8F233408E51798676B286E71C97
-:106CD000EBDC8C1ECC74DF6863E724DAF1D5D00FCF
-:106CE000F1E5557D5F42FF8D0A3B4FD258EF92D8B8
-:106CF000394196EFFB5E8686FC1A450E85AF520E33
-:106D00005DC843FB4CFB1794DDC9A1CB9CBFA91CFC
-:106D1000FA3F681FCAE95A0EC5E7337839F2997C01
-:106D2000E94C0E25F076BDF225839F522787E2F3CA
-:106D3000A3C8A107550687287C9A985F0CFE15CD3D
-:106D400095CFF834295FA7D7E877C9D09F17BE4FF2
-:106D5000C5BC33CCB7F093384FB47D869AEFE86961
-:106D60001EB59A9FDA31FF8C749347BDE1D1900D27
-:106D7000E02DF29CC4B8E6FC6981C7AAA65523C8D9
-:106D800050C8D3BA3C08ECCAB347BE41FFC8DECCFA
-:106D90004A0FACB3E5B55186BC2C31FE7DDC9F3685
-:106DA000412ED809FED973076DE8F79489FAD418F3
-:106DB0003A9FEA8356124039C5EE2910F130EBC1F3
-:106DC000BA56F0C75B89EEDE28DCCFA88940B7D67B
-:106DD00083ECFE2692C2DEFB897D15DEB738DA1819
-:106DE000E74FD28C71FEE4F25EA6B8BF31CEDF670A
-:106DF000B631CEDFD7678CF3F75F34DC14F737C6D4
-:106E0000F907AF2833C5FD8D71FE8CFAE9A6B8BF2E
-:106E100031CE9FB3D918E7CF0B18E3FC0BDF7AD93B
-:106E200006FBEA212FDC678AFF1BE3FD1420AD99E6
-:106E3000BAFB648AF6AE36B49F1762F7940D0BAEB8
-:106E4000357ED7C0EE39F0D3FF013CBF203E1BD0CA
-:106E50009942C26FF687FC9680E409D2668BF7EE02
-:106E60002A817238F78B2FDC6CBC1F6171C058FF10
-:106E7000EACFE507210FAC1A9888F653FD82140873
-:106E8000B83BC7FBD2178CDF0B3FEF52BE9E73DCC3
-:106E90002838B745C6F3CC663A59F8D6ADFC5E3112
-:106EA000AD15EE8F107010F4E2E2F422E625E0B1A9
-:106EB000545E867C2EE020EED7AA32ADBFC37AF7AF
-:106EC0006EC5EFCCEB36AF6353BE31CE473AF08997
-:106ED00083E509D175419C5CF6E79AF8C40887CE32
-:106EE000E0D753BE51391C62D28C7C13ABC699E9F2
-:106EF0000EF16D86677CAE919FCCF0747AFA45A551
-:106F00002F713F2AAE07E2217B25F2B4D411AE8B5C
-:106F10009AD6D7F58F424F840430CFC30CDFE67C7E
-:106F200063BC6597EA6B01F978FEA30B32E2D517D3
-:106F30001A01FAAC8BFCB383BC7D4FE3ED87F2758D
-:106F4000FE1173BCFD2CE449EACEAB48ED78D34C7E
-:106F5000799207FE0D7124FA8DCF067ED8728F9D2F
-:106F6000DD1766CE5FF3FD331FF5B046D00F788E88
-:106F700078D6D0FED6387F3FA41BBFC8B1FC62963E
-:106F80005F00FA6B6C3874FE25E85E6975C138D114
-:106F9000EE29359D3F3C0DDF77760FE4F3C49B4728
-:106FA000A2C4ADC5FE55D8ED749F74219FD9331787
-:106FB000A1BFF67D52BB7DDD753F228FACB352DAA7
-:106FC0002FA35E0D4B719E68F798C50E31EEFF75CD
-:106FD000E73D6387E8F468D5F7CEBF09F3A0F07604
-:106FE0000CA1F3743AA97D23F5C8BE71413F4FC58A
-:106FF00027205D87DF9203396EB8DF4A4DEC55D00C
-:10700000F19E2691575803F73025C3F3BCC4AEF266
-:107010002FCA4CF76099EF33AA1BCEE695CED7392D
-:1070200085DB5125BC2ECEA5097F5CF56CE66FDEB5
-:1070300064F263960C71627B6F665909ACBFCE2D0A
-:10704000A1FD5427498678D2F1FC527CEFE1FD97EF
-:1070500000EF15E3F93A9C578A691F7F8EB73F9777
-:10706000CFFA857BB180FE6CB21C159ED70D61F303
-:10707000FF3BB7A3BEC3FD34EFC78CEC783F8DF95F
-:10708000FEC489B9352D201ECC71DFDF75773FCD69
-:10709000FB13A3C67F01BEF1BD22743F6388F19E3E
-:1070A000C4609C6FC354F047BC237BB6E157AD234B
-:1070B000F4FBB48A21CC2E5DC7F72D1057C2FD0812
-:1070C0002FCD70AAE0706AC8F45600FD6DB2B5DE2F
-:1070D0000FF41BB4B1FB42C31F101CA7DF22AD1974
-:1070E000EAC55E15CF57D4B98903EE190A0FB3A0CC
-:1070F0005F24C5E71A0FF7FEA66C917A0138855C0C
-:10710000B02AC4EFA4F4B276881BF1B08EAC6986C5
-:107110007B5112B77C4DD2713FE11AEF0279348F67
-:1071200044F5733ECCE963DA33E90AECCB12EDD1D6
-:10713000EF79787888C863F33E04F431D67E6484AE
-:10714000847A82ED43606B8BFF69B318CE358BF286
-:10715000BD8C717EF84ED0F3F532A9D9E56074A6E6
-:10716000BF7F6DED90ABF34F172F2251FDA8DBF9D8
-:10717000BA72546F03C0BDF87D15E31F0B85DC9F09
-:10718000672170CFE9ED9C1C6FDFC2F2E1C9E52BEE
-:10719000576461C713EC9F403C62E1326700E21321
-:1071A0000B9BDC78FF1F592461DCA4BAE99017EA35
-:1071B0000B478E74A1BC8C9724B807124C08261F6D
-:1071C00015725CD09FCC8144FB9FCDF50DD52BEB88
-:1071D000E2E9BA166ED9DA0CE72CFE410D08C0FFC1
-:1071E000267E6EDEBC2E713F5DE4FEBC4F36E9EFBD
-:1071F000E7B6ACFAC707C6FBF3FEF1C17F737FDECB
-:10720000BEDFFCE303B89FDB7C7F9EE0FB8F64DF87
-:10721000470FD37FDF4695F28AE1502A640EE229B8
-:107220000DD73983AFD3FF0D918EDB2370B9ADE954
-:107230002D84F747563A1E651E6B19038DF5A14440
-:107240008C2F8B7CA499F68609A0D7CFDAC28570E3
-:107250005EECEC6B1F0E84BC834F7F78DE097908EF
-:10726000FF54C24E787EE291F79C1AC5EFA78FB00B
-:107270007BB6EEE6FA52C0ED1F9C1E0A0BBC87815E
-:107280001EEE59F96D89FEBE20B22215F5DCE280B2
-:107290008C292C428E2C7D211E2CB9F6FAF29DC928
-:1072A00086BAD07FCB63484D34BFA8AB80F1CDE226
-:1072B0001D5B6DFD5518DFD706E39F80C4694A3713
-:1072C00027F638D14E16F3A9DC31CC0676D53F9B94
-:1072D000624810F66B4AAB959D37D5A648945E7D03
-:1072E0009C2ECDF37CF3F578EC6FFE26266F2BE811
-:1072F000582B285C7D4DECBE4FF33AE67FAA4EEC4E
-:1073000043E13DFF716AC1A8ACFD23146FBE153F78
-:10731000C2FC71F33A2BFCE6FB3D3594F70B397E4A
-:10732000E7D61BDF2F6CFA31F6338FA8EB204F72B4
-:107330007E83F9FDA42F8048179AF2D16D055C1E5B
-:10734000979051208FF7DB3312A39D3B15E5A9954C
-:107350002E64A22F57DAB13CB192607978888A7096
-:107360005FD674E841A09FAABDBBF01EA696C0845C
-:10737000144AD6E4C6A6DBF1FEDA1B79DCFCAE8E3D
-:10738000F78BA6151443FE91E9BC375FF71C8E07F7
-:1073900071FE7B0EACB7109E2B17F4EB397730C320
-:1073A00001E3BAC5BA46D175C93D5F97588F589F5A
-:1073B00078BF9CCACFA8F1704EE787B9BC9ED7387A
-:1073C000ADAE1F05C59AD7BE40FF00E1FB92F6FBAC
-:1073D00091ED3F6E85798F27A67D899FBC4F74F410
-:1073E000B69068783FAC99AE049EA9DEC6EFED7CFE
-:1073F000DFD24E4F4D3F41B8087CC30D82FA7BA9C6
-:10740000285D19F609948E0CF5F90DC6FA196B680A
-:1074100010F0FB42D3EF459C31E5D388D25390CE98
-:10742000E0A06A13E1DCD07CE2AD6379C7ECDCE17B
-:1074300009A5E1CD87810F1B191FFC93E37F6781AD
-:107440007716E09F285A21DE17B9BAAF0C171F57DD
-:10745000AC935CC05F736B87E1FD43C38986FDDD40
-:10746000D589DDF910E7FFCA1A2BB15163A1928EBD
-:107470000172AE728F2CEEFB724CED0DF7D7303EE1
-:107480005AFEF82E5B5F5A2EAA59C8ECA100E31BE6
-:1074900071AFB6A03FA19F96AC6B46BF03DD6F19DD
-:1074A000F8AB1ACE8114021F9B9ED7DC8878A836D1
-:1074B000D945DF2BE0FB330FF1007DFA1E74DAE1D2
-:1074C0001C5977EB261DFD49E86F3A77300BEDE547
-:1074D00073AADA07DAF912D83DFE92E21B05CF292A
-:1074E000BC508F8657C5E3BDC6472EC944C5FB5562
-:1074F0007CA3E0BC7FE8EF0309BBAF8DD1AB586F35
-:10750000B57D1DEEA3AB4DF45A41376CE027AED8E4
-:107510009E8C796AB4FFC2BD605F6DB7A2FDE4279F
-:10752000F7A5C1BD1ADEC7D8BDBC957B93701F5FA0
-:1075300059CBE24B953B92F09C30DD47BF0FFE19D3
-:10754000818F23B5E36C7D115F6EBC2F8CECB5FA97
-:10755000F93DE748E7024F1DF7C1263CD537BF99F3
-:10756000A676DC17EBF0D4D6099E0CF758FE5AC865
-:10757000118E27F208973FF7BE910571B57335B1AB
-:107580001E39CAFEAAFD3EE379D7623E9DF03F96C2
-:10759000F713BFAFE0E90D783DBFAE18F166C657EF
-:1075A000F97FE6225EC8DF9D04FCD27765907BA65A
-:1075B000D3E7F7488C5FEE5A33A91CF4F9810266D1
-:1075C0001FFF95CA2D2D879043546E69546EBD4799
-:1075D000E519D43F589986F50F57AA587EBC321743
-:1075E000CB366E170A3EA2846003BBF2AD0266EF93
-:1075F000BC5520FCC10FA4816951FE9FF78A2DE084
-:10760000EAF5CF9F3981DA3BB768467D387B8651F2
-:10761000DF85ACAE89707ED9FF38BB17AED27B9DBB
-:10762000A13D5154DB34D8D7E78E883C477E536D5B
-:1076300070FEFEF629C986F633EBFB1BEA470A54B7
-:10764000764F507986E1F91D738618EA15FCDE5BEA
-:10765000A28E46BE7980E7C912329AE185E7DF5CE7
-:10766000A819D5E7FB74BE17DEB6E27B333E045E95
-:10767000E76D96898FF6377733955F748A6D0D14B1
-:107680004FF4BBAF3E72C2591952B763C4BBA36972
-:10769000FDC80E96AF7BA436F9A7603F1DD9919A1D
-:1076A000007E635F9DCCED0C17DEF726FA1D57BBFD
-:1076B0000AF3722A023178EEA2A2C5FFACA8C34F2A
-:1076C0002EA089077CF3BE1C084A883FE6F7F875B0
-:1076D0000CC62D4E50BBCE45F5C40989D4420907CE
-:1076E000C512E9FB7FB5A60680AFCBFF236B6940CF
-:1076F0004FBF8EE5712909FBFBF250D6B6B5485F46
-:10770000EACE20F26F0CEE8FE686D8FA8834BC3FC2
-:10771000E0FF4412D192E82496DFF7E1670AC5D36F
-:10772000E2ECD642B817678E3B983A8B7E77AAD1A7
-:10773000CAEEE9A7FDBA687DF96F62F8FD8F5A1F9E
-:10774000D86F44E019288475A7F6F3A60EA5FCF1BE
-:10775000E5824021CAB5475291AFCC706FB3F910A2
-:10776000BE7EE003292227237CC6E28D54B8F505AE
-:107770007933D7EAE90DFAAA6D9D95DD8FA76809DF
-:10778000ECFEC9DD48C76D8A3A11D6DD56EFC6FB5F
-:1077900083C4B895EB648DDD5F49E912DAAF977D5C
-:1077A00070DF8FD05BFE7AC907F70299E9E6FE7BAE
-:1077B00047619EBFD9FE15E519CAAB3E9D1DB1E4D8
-:1077C00035197FD7838C0C29330CF783B1DF3F2128
-:1077D000BED186FCDB65E97FFACC6141BB2611F6A0
-:1077E0004527DF9791CE4EA63794A465403ACDFE4B
-:1077F00092EFD3FA5753FDC7E11CF13D837D65003D
-:10780000D7A59675CF4A1638777DECA770CFEE973F
-:107810002F5A3D30EC925F2F1E8C71096E7F77944A
-:107820005B9AB0177AC33D5115AA0BF5B85A2B11C4
-:10783000B6FE00CEF34EB2F331C09B6B197B7EAC2B
-:10784000D8B916FC03734DE7D88EF17B3A660C6508
-:10785000F244E8FB0D4399DD34D7C2E89ABC2EB15F
-:107860007BB4F8EF5F087D20E4B590FBF38632FB34
-:1078700042C86B6A39A0DC5A00B747D1752E7B210C
-:1078800086F9D355E202382E6668225B873279B1D9
-:10789000C4F6E293C04B0B492BEAD32FAD8105AD63
-:1078A0006EF87E6B6D2FFCDEEA41FF32D72F70CD74
-:1078B0003FC8A5859CFF963748781F14E17A723E31
-:1078C000EF9FBC608DE88DF428FAC5A457E673BD20
-:1078D0003A9F98ECC006A3BEF3C6B3CDFE123A2E73
-:1078E000E8CFC8BCA8FD4C61B7C01778F3669CB759
-:1078F000E4094499C742120EC2BD58CB77307FBD10
-:10790000795EE675F4749E0B3CD3C6278DD48D6BDF
-:107910009AB780373AB8757810705FE067F05CD03E
-:10792000C4E21F9F737B4DC46BCCF85F48BC3743E8
-:107930003EE2C28D547EBA23F420E860F1AE00C668
-:1079400067BE220D090ECA07CB36EF9A798D0AFB66
-:10795000FC43B80F99D32B9865492224D97FE8C9F5
-:10796000F281DDC727FE577022FC7E71FC8EC26556
-:107970007E23BB3F5CD78EE7DDFB91AE17F9FD366A
-:10798000F0DF2EE2FED0EEE659ADB073FEDDCF970C
-:10799000C1F17F3DEF778776661F6545DD6FB5DB0B
-:1079A00045DDE8E34FACC181A08FC30315D4471771
-:1079B00014CF87A529A09FB370DFD099BC5DC0F517
-:1079C000F27CD0D3B43CBEF965BCE7E9F38D2F63FC
-:1079D0003CD8F6E2FC04B0978F6F9EFB53380771DA
-:1079E0007CC75CD4CB0B9F167AD967D3EBFB719B1A
-:1079F0002B9EFB21D0E90BB118C758D0E2E3F63833
-:107A0000DDD7805CA4E3A19ED8C8E4E042D05F0546
-:107A1000A8BF72A0DD830B7C3940EFBAE7A8D71E60
-:107A20009CEB1B85DF135790DDB3EA0A82FE12FA46
-:107A300055E8DD57FBFA2E0F053E92DFFEE0077496
-:107A4000FDA777CBE8D3592E6F1D04BF0FD3991C28
-:107A5000FFEEF0B6B4C3DBDD03785702BCD11E6283
-:107A6000F03E5ACFE07C6C1D837BDD8E8C04D80702
-:107A70001FADCF403BE8E88E2C84F7BCB514DE6820
-:107A800007AB463BA89EC21BEC7F80371DB7B245B3
-:107A9000E5F0F63078D7733DB48E95F33AC0D57FD4
-:107AA00037C895077F19E3C1FBBA6383A9B04F3983
-:107AB000B14B2690A7D16E27717B46C0F95FA4E138
-:107AC00059B0AB3AD837EB6308F87317FFCE89E7A4
-:107AD000A4BE944AFB00024E35FC2901C68B8CDF04
-:107AE0006ED7780A8B75764D0FF15345BC788EA111
-:107AF000AAE94F1F815D0FD72CC1BEBF4ADC8FB1F1
-:107B0000D7783F86A4824CC3F3B2763BD0C100F352
-:107B1000FD213EFCBD9C8B595FDF7D1FF273385BFE
-:107B2000EF57AF8E0B5AC11F15DE2521BE973F5070
-:107B30009A504A200E5783F3985AC8F4B3A469E8C0
-:107B4000678CA1741347C7F3C265C2F05C7531BF7F
-:107B5000E3163AAE33325FF3F39B4110817E7744F4
-:107B6000F753FF908FB35CB6E03E64998DED4744C8
-:107B70003ECC5D85CC6EB8AB90ED4BE616B27C93F7
-:107B8000B3903C45FB3D7B7D0CCFEF1E8FFE4F71CC
-:107B90003F8222E0E652CE187E674209E3EFC07CC6
-:107BA00076ED21BC7FF733F8168D6B8A8012B06BAF
-:107BB000D8F7EF5AD9BD2E778EFE13FA4D3F8BF5CD
-:107BC000AA607F7D966AF7001DF9E11E3C4A7F3F5F
-:107BD0008A63FE729292A8007FDDC1E5ED5D63626B
-:107BE00034D04B778EF991174A3A8E1F821675A5BD
-:107BF000071E033ABA27EDD8F7EC7449AB2CCC6ECC
-:107C000059D58B601E511135DFC16F4B5FEDB992B5
-:107C1000DC15DD18FDDCCBC09F7B2D6104351AE13E
-:107C200069A853B8627DC34BA5B3360E20E430512A
-:107C300087029E97014C800E2A12D12F700BF89567
-:107C40007B41A9207D4D5788DFC2CA7A07DEFBC180
-:107C5000FCCC37F375DE369A0413E9FA826F118390
-:107C60001F7E56D012CCA170BB45093603FC2C7682
-:107C7000D50AFB026FB9341CF6CBCB56F76CBEBFEE
-:107C80007A69CAAC8D6368DDC2F21CC23F90F09E77
-:107C9000963B2973035DDEAD90167938C31BD05D2A
-:107CA000752F761F79F85E89C79398FF5FE0651896
-:107CB000ED5E0FDF3BF9FC683FF509F0BD2DBA5FC3
-:107CC0006937A753616F2EE57CBA54D0D90E237F54
-:107CD0001E167C02F62D85DB9DBCEC8CCEFFCAFB0C
-:107CE000FF6B21F35FBD7695E32D8F2141FDEF56AC
-:107CF00089716FE1E53B85CC6E16F310F44BB85FEC
-:107D0000CA422506D0515BC31AB4971699FCC444E5
-:107D1000EFBF92A3D5DBE58EE50A94B6F03C988FD1
-:107D200074432CF2CB9DB69D59EC9E1963BBE50DB7
-:107D30008CFE973BEC68078AFBC5C53E40D88D8B0F
-:107D4000C1DE037BBF91D9B70AB7CB2BE87E0D8884
-:107D5000CE4A42B5FD61DF5CAFB37F519E717FCFEC
-:107D60009E613E18E74E871DE39F372F33DA4B564F
-:107D70006E475A3BFEFE9D31AF84DB4BE6BC129949
-:107D8000F3316DCBF6313CAF44E1F6B0A0A30F0B5D
-:107D9000ADDCAFE237C4F1E790562BBF778EF9F731
-:107DA000B89E9E203BF03E863912BB67EB6CA9D390
-:107DB0006FA172E9137ECFCDB91A76CE79CE0FD8E6
-:107DC00039DEBB121FBC19ECE239093605CA4FF87F
-:107DD000EF7D7DEA4A4F9C4540FEC83CEEF4935946
-:107DE00010BF59037294D59FD2C6A0178DD79FF8A4
-:107DF00010DECFB84CE78DF50DB3343ADED937F845
-:107E00007B3FAD437CE831C1C79B597D9378BF85EB
-:107E1000D51F17EFB7B2FA4F44FFBCBEDEF47E9514
-:107E2000E9FDCF597D70D1D6597EB0E379DC6ACEB9
-:107E3000B512C6AD34E0330ACF39AB83485F732C3B
-:107E4000FB5959468210B7ECAEDDE422AF06FA5A70
-:107E500076B639C15E99314CC37AFE505F7E11C54A
-:107E6000CF926992DF06F1CBF703D95C9F45CFC76C
-:107E7000E7FA699287F527EC5FDACF88A2E2ABEFE9
-:107E8000E7A3A20EFD8CF92EFD34769CCF84EFB2D1
-:107E9000AED861C67E843DB86DB8E6837991F1D7DE
-:107EA00019FC9C4B1FF524823D49DE65BFBBB574B0
-:107EB000F5CE412368FF4B5FDA376881CEFF5075FE
-:107EC00049261A95C3D597242CBF6AFED806F74BCE
-:107ED00054ED69B64D2C80DF0B6AB68DD3CD6B990E
-:107EE000C833262165BACE9E995F64E17CC57E7752
-:107EF00068E94B2731FEBCD4B2F3F8D3C097D73230
-:107F00003FA4797D53F9779F417E4194FDCAD222E7
-:107F100026879F1EA92D01B84D0198D1F6E3D644BE
-:107F2000CFD3D8C3FB9B13C7E4FBDC12A75D2D8224
-:107F300078B86F0D9CFF5BB0C53D1CFCDA5387968B
-:107F40003D50D4A57F38CCFCC34DCC3F3CA757EB6C
-:107F500003547991DFFE36F814DCFB3CF929D21E7C
-:107F60004F06BF2B1E8747BEFB70D6F831E8EFC324
-:107F7000FA1345879E82F3DF07F9EF31DC356A6833
-:107F80001CC885903BDEE2A2FC3CA3A0E2B780BF08
-:107F9000BB465D3F119E97C638B32B589C01E962E2
-:107FA0004681772DBC87F6E0DFF1D998BFCFF76720
-:107FB00019FD7DBEC2785FB4FC857A0E87DF16B1ED
-:107FC000F31B072D749EC323F310E35303ED815677
-:107FD000DA5FDBEABEC3E09CE5CE82D297909EF8E2
-:107FE000F83B0B7CBFD08F0F1409CF7B3A8FCD4568
-:107FF0004C9FBEC4F1E61D43E94D27F7A78F8F378D
-:10800000D4674C49269ADEEF3CA3BFA13E7B4E8647
-:10801000A1FD1DF38618DE4F8D691D597315767FFE
-:10802000B5D31907F9119F36FDEB6F77823DDB2839
-:10803000E3EF172D7E6DFBDFE0F7BCCED10527A364
-:108040007DAAA2FFEFCB83EC775889A229FA38D614
-:1080500069D2FA24C47D75F191A8F163111F59EA20
-:108060006AC13CCDFF368EF56E118F630D87D475D6
-:10807000D0471F0C823C952A075BD7E97D47F0F774
-:108080004C20CFE34A09C47F091A89D59756E1EFFE
-:10809000C88DE3BF275D5DC4E473D5807B15B8B799
-:1080A000A09A9620FF2752399548E9A4B5990CDD8E
-:1080B0000379DB6E27E6D52CBF742BFAF50FC6F9D2
-:1080C0000BEEA5ED96D64FC27AD5A578ECF7AF7238
-:1080D000EB44CCCF7F45C2F8C9D4FE77AD86F943D7
-:1080E000FBFBE978537F7B6339C0A96A0FCBBF994B
-:1080F0002A1F1E09FD2C6B9884DF4F95C94189DA30
-:10810000498997EEC47EA7828D43EB7289732DE86F
-:108110005DD916CCFE05C8159B13E54AF5A558FC9C
-:108120006EF238A69F2F16B17D8B35C4E635E1D2AD
-:10813000347C2FF07FB928DD709ED49ADAA8C07DF8
-:10814000ADD69084ED6FBA34044BB1CE3FE7FE124A
-:108150007F9FCC9A7A6122E4DFFE394572A1D9650E
-:1081600092BBE76B4625EAF7D3FF0F762BD097003B
-:10817000800000001F8B080000000000000BCD7D78
-:108180000B7854D5B5F03E73CEBC9299C9E4C9843E
-:108190002470024908106032791042209310109127
-:1081A000C000550906199047401E21BEE295FB67A5
-:1081B0004212088216B5BF45453A205AB4B6372256
-:1081C00056DA224E006DACFE366A1F786B6D502F6A
-:1081D00082458DE0B5F416E5AEB5F6D999394382FE
-:1081E000D0DEFEFF1F3EBE9D75F63EFBB1D6DAEB3C
-:1081F000B5D73EB978117ECA19BBA895E6F332F31C
-:10820000263276D37989790B18FB3ADF9BE04E66EC
-:108210006CD6861EC592C418B3599C4F66025C92F8
-:10822000AF2ECF0BBF271FA961EA18783FA9D7E867
-:10823000B5C1FB504EB185EB1731E6ED0098B11E8C
-:1082400065AE3DFCDCE53630968CCF9B192B827EEB
-:10825000FBDAFD8CB114C66E7632FED3088D52194E
-:10826000336AEDC5FBDD12D4C1BC022F98834FC227
-:10827000EF291EFF6837F4D35DC1E6EFC77E94EEA9
-:108280002173ECFF73F3AF9699454AA0757871DCC2
-:108290005925AAE15EE8CFDDB78E0095DFB68E0CDA
-:1082A000ADFDAF65D6D801F3F8757979B717FAEB5C
-:1082B000BCA7A04056C3E356B84D8417E6ECBDC03A
-:1082C0000A195B773856BD17D6590D3442B8F725D1
-:1082D00073704F263D67521296E63D12D4AF73F489
-:1082E000E6F860FC292F5B436C2CF4FBB25561303F
-:1082F000CE1B85FE0AA4E794974754490E98E421C3
-:10830000B3C2A0DD75E3BC9588B781E67B318A4FA7
-:108310004429D6CBAA261A583163B759F86BD3E64D
-:108320004881B838C6FCEDD73206735D7C7E1E638B
-:10833000C04F4BCEC712ECDFCE9F9FAB1F340DF169
-:10834000786E034C1AD6B1648334E600AC8BA97600
-:108350007736E0A13A6DE146E640BC1B68BDD5A387
-:10836000E3832DD0F4BA29F680218EE8D185F45824
-:108370007D3E9EFA5B733E93C6597B3E91E075E766
-:10838000AD542E393F9A9E0BFEF6217F437983C769
-:10839000BF1EF151DD72CD741CC7BF31B5D06F8BDC
-:1083A000E4179313F90AF8C5B53C821F5A3A815F66
-:1083B000ECC42F8A17F0EA8332925F6623FDF31034
-:1083C00013CE692930EF59AD99867B59B8FE4EA47A
-:1083D0007FD195F3FD2D1ABF2CB185B20DD09FB181
-:1083E000DEEADE08F33A9BA44E43BC346CE1F86B42
-:1083F00030FAA6D861DE0D8F486EA00CBBA5D86EF2
-:108400006180A7E2E3F5267F04BFD79C1FCB54C051
-:10841000C7BCF35954568FF1B722FD179FBF41A334
-:10842000D3582A995A62C0F9DC8E74557142259C42
-:10843000CEDAFCBEAC1F3FE82E18FFCB378C545F62
-:10844000E40DDC8CF33106CDEEDD309F5356BF8C4E
-:10845000F43D95C19C0FC1144F1959C009F4BA6578
-:1084600087CC02D0FF5228FD509E8A67DE780FE24B
-:1084700013D699CBFBBE08FFFF53D93E840D07BA34
-:1084800036FCFE7D6518632B73BAC786A0DFDA8AD7
-:1084900050F28DD0EF99BD467700C65DDDF976B11B
-:1084A00001EA3FC9F40E6232A06AB07F17D275D5D7
-:1084B000DCE04F8C00DF7ADFF38E096A189F1D4ADB
-:1084C000285B81F73B008F019857C736797A90F087
-:1084D000CF62E78C09F3B5E0E368FE5E757E38E1B4
-:1084E000E75CBD79CC01E45FE0577CBE46E3F35B1B
-:1084F00091EF890F39BF0B3E5EA37079B5C6161791
-:108500000CC03A8C3DBC5DF5BF01FF01CAD71ED837
-:108510007D7F29F2DD1985F87FB5B64FAAE5B9BE92
-:108520000ACEFFEE1678FE62930B9015E6FFA9E7E0
-:10853000E750BBB8F337517F82EFA3E579C4BE6142
-:108540000CDE7B31DFFF16E2A9F2477F7BFEDFE125
-:10855000D10C2594F358129676E29F7F96DCFFDDCE
-:1085600055F2FF31ADFD74335BE4CBE3723DB2BF36
-:10857000144FE5695CC7676E89CBDF7FB2BCFFEC47
-:108580002AE5FD1FAE50DE4BF95CDE47CB7706FDDA
-:10859000A17CFFFCA5914194FFEF33D007A8F70E13
-:1085A000C5AA4F6AF29FF4434C5CF072F2FFD1C24D
-:1085B0005BA4FCFEE5BF21FF1F90FF7FEF3E11FC97
-:1085C00018BD5FAEDBDA4D7A81BD283194BF62FF02
-:1085D00074C570BC748DE27A20BC6F24DA570CF637
-:1085E00055B614B96FF6DC5F8AFBE6F324770B1BF4
-:1085F00078DFDCA4ED93459A5E10FBE3D17C7F61CC
-:108600007EC4FE58BD3F5A3F5C9EBF6E4AAA67A813
-:108610001F164119C95FE63EFDA0DF1713F2AF6ECA
-:108620005F8CD0DA7F1B5FCDFCE7F3D5CC01F8AAD5
-:108630003A3FF9EFE7AB687E3A57FFFB4215E67326
-:10864000AE10F82833CC3FD7BDCEB8DD30DCEE7E9F
-:108650009245F0892923D882ED2EB27AC463B43CC6
-:10866000147CBB05EC009CA7A07B574C206F7DDEE3
-:108670003F4FFEDD997F7576EFD2FC2B931F9B91C8
-:10868000CED8EFFF9CBDF8607F74655E6E1784E9FD
-:10869000629E47765C08149C34305D8D3BF8FE1278
-:1086A000705B48117A3711F52EF0CB43FF08BF54A9
-:1086B0004F815F0723FCBBF9DE74E8EFBB1A1C781F
-:1086C000773ED2E7861251FFFB1DDE2C9433F06B10
-:1086D000298DE06516C2AF061F3F5E85FCFB505F2B
-:1086E0007D00EBA796C569EF332FBA1EA2FDFEFCF5
-:1086F000DF1EDF46FB793BDFBFFE1EC53726022E9D
-:1087000004D81E019744C13B797B87D2C39C848FD8
-:1087100020DFAFD0BFE4E1FCE38BB04B8092D3E22B
-:10872000D1AE3C2039EF05FA2F28FBDC84F40AAFE8
-:10873000BF87D6BFF690A4C11F1DF70269161CE0C3
-:10874000F0F1FC533B028AD61FE079B58666738749
-:10875000E495818EAB4BA4E0B0CC4BF17CBC4F3E9A
-:108760008979802AD6BFCF4C8557F73EEE6F7A7F46
-:1087700018BD1F325FC5F83796316FD07669BB538D
-:10878000A2DD058045FF80CB79B0BE60DEA5ED7B24
-:10879000B5F6DD068386AFAF7720FEBA4D029F1790
-:1087A0007678CB80FE8CC3FF957F617E208F4FDF74
-:1087B0001BB5FECBCDFFBD7CBDDD803FAAFEFDD04D
-:1087C000E5F0F7C125F8D3F8A74ECF4F718AEFD85F
-:1087D0003998475C92E444FB78ADCFBA0DFD803008
-:1087E0007F986B703DDD56D6C7CF7AFEB7D454C1A3
-:1087F000FAD632511FF308F93986BEF67C3FF4F100
-:1088000017F3E6023FA10980EF2779AC8F046C448F
-:108810001FAA2738EB32FBA1230A2E8BDA3F1AFF5F
-:10882000D3FE45390FF8C9EE47CE1478387E3E9511
-:10883000D87C9493DD95DC5EEC1EC6CB791E89EA6C
-:10884000277A381DA66865774C041ED2C374869FAC
-:1088500010FA2311EB263CD52469EB0E8CAC990958
-:10886000EBEE4EE0F5D5FBB31F099485E1E8FE661B
-:10887000EF1F59837CD3D77F60C4BB88D71A0D6F95
-:10888000F3F6E7BE1BE0F250C27DB9861804A87566
-:10889000400AC8B0EE35C817FDAC3BCD73C9BE0A5F
-:1088A00044BDEF355EE6FDCC4BDFF746BDCF8C49CE
-:1088B00057F3BE46B79951749D1E45D7AA28B8569E
-:1088C000C0419DFC137271C9C107DA52601EB7EE38
-:1088D0009350CD44F07309F1F3AD4EC1BF13DE45A3
-:1088E000791FE6E75282E776087E9DF808CAFF39CD
-:1088F000280F4BC3F03C94170497D578C745EA8BF3
-:1089000049547F63BB683F99E005ADA2BFF2475071
-:10891000BE0A3A02FA6A70BC9A42A12F2ADEC5F654
-:10892000AB0EF1F737792ADFBDEC7ED81E85979D17
-:10893000517020AAFDF7BE45BFB446BDBF21AA7E37
-:108940005B14BC230A6ED7BFBF78A944FB7031F01B
-:108950000312E2DBF6E5C39E3E3BB54F9F4A36B2BB
-:10896000DB74FBEABA160E073DB36BDA6D11F07ECD
-:108970005F8D266F695F1819FF01591B407D651CCB
-:10898000405EDE3F105FE646EB5B5EFF27FC351581
-:10899000ED60A6B30B8ECA7AB853D6E61DB8F9DDE2
-:1089A000DBF3F0A18017D6A07F70DDF7F5EB02BFF7
-:1089B00055ABBFA9A6AA2CC22E6137119F88758A14
-:1089C000F6D3BEBE28E3783FDDBFA0662FD4D756CE
-:1089D00086B2EBB14CE025E83519F5E63A2D2E3399
-:1089E000ED25D9877AAD362694DD106987B08E1CC7
-:1089F0005C67E73D32D127D002F4C1381B739B304E
-:108A0000AED21917D7F814B43F7A8FDC887AF4FD08
-:108A1000C6C4149C7F6A01B7238FC60D4D590670DA
-:108A200067EC22930AED3A374FA5F288ECDDD40BC0
-:108A30007BED379E5535B691581F47F8E9DEBFAC40
-:108A4000A619F6C13B1E95DEF72738530EA2FD7C12
-:108A5000AF913DA9E27CDCBB886FEE33E7A31FBD7D
-:108A6000B879740ADA934BFEF79C69A9D06E499BDA
-:108A7000D12D513B3616E7EDBF77AA09EB97B66AC1
-:108A800065E01A2A5FFEE6891607B4EF7D5C72EF97
-:108A900081F693BEEC787D2CC02BDA87BB913487AE
-:108AA000CF1B9813C6F960C788A00CFCF8A1B5FECF
-:108AB000D559BC3DC3F62B2EA86FCE2AC4F6B2738F
-:108AC00023B43F09CFD11E3EB945DE23E1BC1CF6DD
-:108AD00018099674F26BF54DB46BA1DEB9119E9F27
-:108AE0006C5B998276D649497548B0FE5E4F638DBE
-:108AF0000BF865C50EB346BFC6D4C5B0AF171BFA99
-:108B0000F885F4C7F2780EF7EEBFABE64998FFC9D7
-:108B100047463810CF6B0BBC5F78501F157ACF7A61
-:108B200092719E5C4FBDFC8DBC08EDF15F9C59922B
-:108B30008271BB0B1A1F1F3EBF24654984BDB3FC65
-:108B40005385E8FEB249BD1DE7F9724C8684F12CCD
-:108B5000A07B22C6BD976A7E26F06FE3F3FDD83D69
-:108B6000BFF7C844A78FCC8DEC43D8549D5BAF9F13
-:108B70006207BC74BE28111D96327F0BC2ECA0E4C4
-:108B800046FA45BFFF9BB195D682A248FEDF4272EE
-:108B900096FC0D80139FDF44FA906D800713A03C74
-:108BA0006A253FDDF8AC3568057C2E4DF24EC3F6E4
-:108BB000CCD59133D71EB14FB5F67F0CD8A9FD1F88
-:108BC000A13DFA7B7F0CFCC1CE6C97DAFD2B1CF625
-:108BD000001A1F1FDBED0AD2ED7DA5E9E4DDF0DE12
-:108BE000F2C78DA427963F9EBCA117D701FC95CD57
-:108BF0002E5D87BFC048F81D70DFB2EFD754E9FC87
-:108C000089872FBB6FC7143C5CB3376FE07DBB42D5
-:108C1000F36BA63D6EF4E1BE5B51645718E89BCA46
-:108C2000C75F7912F7C78AF5568F1926BEE27133EE
-:108C3000D1B7C76E0F38A1DEEFB02BF1504E2CE04C
-:108C4000FCB0B040A5728ACC148B87CA568CAF9EFC
-:108C500085F924027CBAF1A187C7C3389FB0E00D23
-:108C6000E3017F6791508097B307648A3F32C5ABB9
-:108C700054833CAD635C8EAC79ED795305FC5A5757
-:108C8000BF6226FA812B83C60F7A341FEFA2B64C3F
-:108C900094BFEBF823D0C3FAFA756CDB17F2586275
-:108CA0007B13EEDF351D51F5F5D77C8C719C754C2F
-:108CB000F9A047C479611EF30AEC49274703E06134
-:108CC0001EC0103B5B6FCC61B0C41536D887B0DED8
-:108CD000293B797C6745A31C3443FB29893C5EFC16
-:108CE0005113D07F04AD3BE00478C5F7B85E5AC19C
-:108CF000A4A0057EBD66E77A05F7CF2B1E8EA7C51B
-:108D000012F3E17EF8D0EA1E82FEFDF2C7AD84DFE9
-:108D100015BB56FEEE1178AFA7B93A29D29F5EA9CE
-:108D2000F105F4CF2C09E17E3E6EFED7212807A77E
-:108D3000FC00FC6258EF8A78F6939A4CA457EA102C
-:108D4000D5166EB762E33D39BC1DF8D5B0EEC55BF4
-:108D5000641EA77AC14C7A1264838BE4B886CFA5CF
-:108D6000ADAF994C7928D7B775CBD0FE0380651B82
-:108D7000E12BA0E1D184F85A84EFA6F2775CC59A82
-:108D80009DAE92DCF1E3FA6A0DD2A2B9A4077A4D46
-:108D90002807BE5FC0EDDE6D5AB97888FB668A434E
-:108DA000DF6F76A35CC31F59CC03FCB03586EEE5BC
-:108DB0001807663F35533C655DABD56B75909FE2F8
-:108DC000DD8FF3539862C2731795CB97EF6B7CB826
-:108DD0004E9D730DF20DD41F57A07E8D9DCBD135C6
-:108DE000F180776ED77A0D30CEE7F8DB70DE6FEA70
-:108DF000D888F125ED39F4A33AC2FD7619583BC65F
-:108E000065B0FDC8B188C7C41BE6E3FC7E2CD37EE9
-:108E100086C5DF5F8276E18FE502F487176F393A06
-:108E20006D07C2CFE53BB1CBC53F7987F4CCAD1A16
-:108E3000FD7BD03F40BD03F073507668FBC92FF334
-:108E40003851878627C107A27ECD16238FDFB799B9
-:108E5000C9EE59D3FC7BEA778DBD3B05E5F59A1742
-:108E60008CC528D79FD7E6BDA439A3EC38F0D5121E
-:108E7000639C538247AB03D52684576F97080EBF78
-:108E8000973C04F9F4CFAD2F3A907F3EB486B251AF
-:108E90007FF5AEB7BAF7E002B438DD9F5BB3F76099
-:108EA0003C67A9B3DB2E41FDD2DB8727A0BC7FDF67
-:108EB000193261FDFB1D990684BD4E6719C25E65BE
-:108EC0001CC17F0651D6A1F9ABC86F6B254EE7D503
-:108ED000CF1E350D83F18E17F0B8F9A73F7E270717
-:108EE000F5DB9A21DD39A887800F72D210CFCF48E9
-:108EF000A4BFD73E2B7BAD63C37CB016F900F6DD73
-:108F00002A8D0FD61E78F12EDC0F6B91FE9E4BF949
-:108F100008F8F4183DDFBF7B1AE3EF1F433E117AD8
-:108F20000FE05623C6DF4C1A0CE320FCAE864FA898
-:108F3000AFE2F581BC7A1E5733A19DBAEEA031D0C5
-:108F400013716E34109DBF2AD0CED19ACD2477BF35
-:108F5000D2D6DDB3E50507D2F1D31F1F7D15E3C5DA
-:108F60006BF6837657FBD9171A5ED6211E1CB40EFA
-:108F7000B247D6E1BA1D613CF4F1BFB61FD731BE8E
-:108F80004EB1EE758A860751AFBDFF176D9DAB9947
-:108F900086B70323F8FED3F61BEE6794AB627DFE23
-:108FA00004FEBEE0D3F442BE3E6321E7D7D5C0172E
-:108FB000EE3CE21FAF49C809A8FAF4B9DD142F123C
-:108FC000F412F31E5BA80A79E78D4F08D3B1C7C02E
-:108FD000EA3AFA89B3241772FC9D681B34E420E056
-:108FE000EDCFE097A1FD85FCAA448C27F8468C378D
-:108FF000E5477366E07AA1FF10F62FC67D3F10AB00
-:10900000603FEF33BE3F903F517E8A7D39A565E1D9
-:109010008C7C07B6FBD43E3C0FD7CBC71F5BE8A4C4
-:10902000F7BD682FC0FBDE8312C5AB4F687180139C
-:109030006D2F3A9644E0294F7B4FF019FE601C4B90
-:10904000CCB72B81C77FA3E72DE49098F794CD3759
-:10905000CEC0E762FE825F057F0A3C0A3E651B9236
-:10906000C9AE89E657E235A157659DBC27FD784D0D
-:10907000FA1726BFEDD2E7D1709FFDD4EA3A9615D4
-:10908000A1D73FC4380FCA93A7E520C913065C1BBC
-:10909000A17784BE6F5E7F8D13CF198DCF4A6E345A
-:1090A0007D22F4CC362542CFD415AECF417DF6607B
-:1090B000E1302EF793BCA7919EAB4F754F73A8611B
-:1090C000FB75D29721390EE36107323D917A75F530
-:1090D0009963B40FD6B0EE4DE87F2DDEF24EF578F1
-:1090E000E4F7A78D74EEB9B86DAA09FD81954FDE3E
-:1090F000528CFCF441FB7092EFA7F71615107F31EC
-:1091000067CA0DB00F96EE7DE88605F07CE941D97F
-:109110004D721EFAC1FDBBF88E0226D1BA7BAAF1B0
-:109120003CB5F76ED98976FFC4278B3660FB89F68C
-:10913000A1F1B80EEFDE4482BD4A1CE909612FBFE0
-:10914000AFC9CB1623E78F0DDABEBAADAFE4FC335F
-:10915000A5A52507CFE37B77839CC6736993DA11B6
-:10916000C2F15E1A447EC93A70A35C40FF5312B745
-:10917000CFEA4CCC92EAA1E7965478FE9AB1FB0E66
-:10918000D427AFDD61CF6FC609C8178A97707F9269
-:10919000E60176348D2FF026E6714F21D74FD1FDB1
-:1091A00089F7BBD0FF40B9AACDFF74EBD337A03EFF
-:1091B0003CBD2F3B01D7FDF14BD676B4AB3E3672AA
-:1091C000F9D867EF048D1F45DA6B60DFE960B0E71F
-:1091D0007430F0F1477AFB7023CDEBBE429BCE9EFC
-:1091E000137C5FBB3E3B2E320F21DA8E6759D1E7ED
-:1091F0003DE3E3583F724794679A0051C0A873D08B
-:10920000B68771AB62BF7EBE1BEDFEED66A719D6B9
-:10921000F911F23D9E67BD2007F1FC066D74DC0775
-:109220001F3D971F44FF73F97BFE69D8FFB10736D6
-:10923000539EC232B033074911F6F3F71EB801D975
-:10924000FFACDBBF2915DE3BBB8FE75540B52DCA10
-:109250006E7E3555FDC7EDE62BB597459CE2E7855B
-:109260009ADDEC666EC4B3C0AFF09F5E063E28F197
-:1092700084F1F559531DD9CB679AFC547E2E9DB8C5
-:109280007F22F2AF3DCEBD075EFBC5C187E434A4AB
-:10929000F381FC0BE82F97DAE29CB86F3F6B6AA46E
-:1092A00043CB334DF5540A3A8B38DDA4039DF4DEED
-:1092B00067070B0E4D84F70EDBE2B81EB8E49C88FE
-:1092C000D3333A8FE4B6F5E307E173B1AE4FEEE680
-:1092D0007415F3FE64DF2D0E5C57E7638987262043
-:1092E0003D63E39C68F7ADD0F2474EEEE076F5299A
-:1092F0004BDC533331EF64E7BC1406F27659E77761
-:109300006EC0E7CB5F929CE80FB85F9AE3C078EB42
-:109310007F283D0E2796F05E08E7A304659447A5D5
-:10932000D3199D63958614A666D2D130F1CB8433D0
-:109330004A10F34EFE8CE75B1847B910437114A630
-:109340009D5B2DFB198FBFF4F9B99A9F37515B775D
-:109350004A5102E76FEDF99412FEFCE39DCFCFC2B4
-:10936000FE4EEF353A71DE9FED3552FFABC03F3315
-:10937000C07C4FEDE37ECFAA0E89FCE5D3FB406FA6
-:10938000C3BAD6AC377A4D7197F2E114A8EFB18524
-:10939000F970953748FCCD347EB4C0BF8BC32EE541
-:1093A000C778D6B109F1F18FF2A5AD48EFC7F5F155
-:1093B000E3407CA0E10BF731F2A3A0F72AA00B9EBB
-:1093C000CF2674E457205F09FA0B3911A864B9A8B5
-:1093D0005F5B4C2C17F37802861837EEEF3936D5E1
-:1093E00028011EE625F554A138BDBB88CB49798AF2
-:1093F000C16B40FDD2622639102D47B28BB8BDF447
-:109400002CF234FCAF2872723B8AD5933F224AD0AB
-:109410003B19A8C7E7C426FCA70A4D3C2F7C7F81D7
-:1094200002F39F3331E18EE16EE09B171E5FA000D7
-:10943000FFCE2948786118C065453B393C2EA1C84C
-:10944000087073F3AE055500D71479DD45C9E17195
-:1094500044BFF0BC009FFF7CB4BF18CB75261BC96E
-:10946000E9CFA5DEB18D99E1F66F49ECFD5F48616A
-:10947000B8C7C886A09D57D137FFFECB8D45DE7299
-:109480003EAEFEF912C6DA28FF2EF0CBE312F7C784
-:109490007C9614CA6323BE5A62B185C8AF6F379EEB
-:1094A000E9A337F2913B4E41BACED2F868B612EA40
-:1094B000C4F747B256E7490B99523B2F260E2CBFF3
-:1094C00061E3B193A23FE097CF8DB05EE06B09D826
-:1094D000B311B68C0448AE05F9251DFAE55FB1DF7E
-:1094E0009600EBB1121D6A9DC86712F31B2E42B99C
-:1094F00026D63116E3276B62870491EF1B5EF8F4E2
-:1095000018B2D74A61BFF84B88DF6F77F2F5307F2A
-:1095100029F1E31D1A3F7EDCC4EAB360EBCDEEEE29
-:1095200076A830E933B34239B8DFFF34C45F5784DB
-:10953000FEFECE96F406E09F4FF79BDD33A1FDA91A
-:10954000E0F314BF5BADD9A56C6FB2B6EFE550394F
-:10955000B4EBCA1CB907F54B4311D7D76732434365
-:10956000EE41B991C9FD2068477972D3375E938C7B
-:10957000EDCE3CB7396B19D0CFACB0803D814AE617
-:1095800080755F0B7D97006C0458A673E020D10BAB
-:10959000DB3950DFABB7B8789C9EF950AE087A093A
-:1095A0003A5C421F9802DAAD060B33E2FC47B29DEB
-:1095B000CE93B1613A7D6C013C621CCD027884FD92
-:1095C0003D15830F85884F1E7769907A5A1311FED7
-:1095D000B144797797EAC1274D88F2BA9DB790FCDC
-:1095E000117247857FFDC99DAB8E1FED9CD2AFDC0C
-:1095F000790CE50EAC83E5B3FC8BDC4024FAAED0ED
-:10960000DE9D2AD7AA0ACE3BD9E2C6B85AC3E3C325
-:1096100049DFB00BBF217F58B4633B13895F3665C8
-:10962000CA84F79507259E1F79308DA95035F360C0
-:1096300022958EF3A9F4FCF453AF1772B9C4E95222
-:10964000FDC3419594AFFAC311548A7934687C37CD
-:1096500055CEEB08A11D61837900DCF01AD75B0DB4
-:10966000D7CB14DF6428A2539098FCC7676BA73848
-:10967000908FF5D9F9D245B2DFD538A48BAF4B66C0
-:10968000C83FE07504389E2DCD8867B3CBC0D47E2B
-:10969000EC0FB34627AB1AC3D408FF43098CFC6E0A
-:1096A00019C665BF637407A1BEC5EAD883FB8905E7
-:1096B000BCDDE847CCD7DEEBB672FE88CD4DD0BD21
-:1096C000BFD931AD0BF96DBE97EB1DBB7BB06E7C86
-:1096D000B3BCDA884CC6FCDC5E14FC407C09E3CEEB
-:1096E000F649A45FAF9F0FF511FD1ACBBE20396E6E
-:1096F0002CD3DB99669FBEDD1F84DE19C94646D296
-:109700003F8C779B17EDF4B35E3BF13168F7EF9731
-:10971000017C439791E17ACD317C5D671153181F2D
-:10972000F5CA418C9B6C463CC0F3B8123D3EE3BD8C
-:109730007AFC254ED7E323D9A75FFFA0F9C374F5C0
-:10974000A9FE51BAFAB43A8F0ECEA82FD5B51FDABA
-:1097500058A98333033374ED87B7CFD5C1D9DB174D
-:10976000E8DA8FD8B144573F32B84A573F7A5F831F
-:109770000E1ED3F12FBAF6E30E6ED4D5E787EED5E1
-:10978000D517743DA8838BBA1FD5B51F7F7C8FAECC
-:109790007E42CF33BAFA89A7F6EBE049BD3FD7B591
-:1097A0002F3F7F440757B0D775EDA758DED1C1537F
-:1097B0009D7FD0B5BFC6F5A1AEFE5AF5CFBAFAEB84
-:1097C00072CFE9F93586CBBF6AF7DF74EF7D9EE68D
-:1097D0001F558C3A533EA320DFB62C945822C6D591
-:1097E000BBE659500EE4156B7248E3C3E1453C2ECD
-:1097F000C1B2D810946753E5990CE376673BB87F04
-:109800003D90BE8B0375A5448C1BEFB58003198674
-:1098100013A73B7570B2CFA56B3F68BEAAAB4FF5DF
-:10982000E7EAEAD3EADC3A38A3BE44D77E68A35716
-:10983000076706A6EBDA0F6FF7E9E0ECEDF375EDDD
-:1098400047ECF0EBEA4706EB74F5A3F7D5EBE03114
-:109850001D8DBAF6E30E0674F5F9A1765D7D41D74C
-:10986000761D5CD4BD43D77EFCF1A0AE7E42CF3ED8
-:109870005DFDC4531D3A7852EF415DFBF2F3211DAB
-:109880005CC15ED3B59F62794B074F75BEAB6B7FF2
-:109890008DEB84AEFE5AF5B4AE7EF59FDD213A071E
-:1098A000F8053F57BB2EF70B5DBD3109EC5A8C43D1
-:1098B000B218379E5F0AFBA7DAFD575DBFF7160F98
-:1098C00023FB0278A9C72AA37DE4A3F85102261638
-:1098D000025FC6811043BE4257A196E25049A4EFF1
-:1098E0004835A99827047602000986CC4CB4A763B2
-:1098F000C3765BFAC5822BB7DB76409F388F5F1645
-:10990000FBEF2B4E467FE5B96968B7AF64814D38F0
-:109910000FD07B713DB03FDEB4EAE319A2BCD602A2
-:10992000F88918EF35EBF674CF65FCFE6B2D67A850
-:109930007D5FBF5A9C4382F53544F47F3FF8150A9A
-:10994000D875DB9B60FF80C3F8609393E0EF35B977
-:10995000087EB849A57247532E958F36B9A97E6700
-:109960005309C1BB9ABC04079BA653B9A7C947CFEB
-:10997000F736CD27F829F0A3B1DC077E3596CF80E6
-:109980007F8CF5CF82BF8CF04F9A02547634B5D3DA
-:10999000F3FD4DDB093ED0B483E09F3605A93CD8EA
-:1099A000B48FCA9F377550FDA1A683041F6E0A119C
-:1099B0001C6AEA22F8485337C1C79A8E13FC6A53CF
-:1099C0000F955D4DA7A8FC55532FD5BFD1749EE0D0
-:1099D000335ADCF6956249776F4AC08C55113F08BF
-:1099E000FB7016DAF9C81C25C6CF74767E94BD1DAF
-:1099F0004D8F4FB4718C95602E62FC7070CE9E9628
-:109A0000083FEB2D6DBCCD312C6005F9D66CE07EA6
-:109A10006D7302A33C6EA6D9AF2B34BE6449DC6ED5
-:109A20005DAECD6B85C6FF45C89FB9C49F6F5C8D89
-:109A30005F21FCC65163FC27883F330C01F29F6D08
-:109A4000C11CB49FABC7F83F42B97EB67ED9AB34D8
-:109A50009ED34DE78FD5E650F28D181F794DA6782D
-:109A6000DE40E3ADD3F2CD07AC3F7C3A1DEDEDE92E
-:109A7000DFC87EC4D39B46FB7C8C17FCA598FBA754
-:109A80007F2936E8CA77C6F8BFC2797E65AFBFD9ED
-:109A900000F3FF6AF2FAA76ECB0CFBD3B3D1250516
-:109AA0003F680E538D94D7C8BCAF644257D78381AB
-:109AB00085F08D2C40E577F2FC17715D35608823C9
-:109AC000EC2F350FE96F5DD1F38A19CFE71533DE3F
-:109AD000A02BA5B17EEBF8229C9797E6F5E6846B68
-:109AE00072705D625E956355ED3E44EF2E9CDF57CC
-:109AF0002F7D71521A1EC6BFF0DB375568F928EB6F
-:109B0000251E9713F69A96CF22FC8EDA3BA420DA14
-:109B1000EB0BC1DFC173A6F734FBF33D2BD7CF6747
-:109B2000EB8D24276BA518379EC79DADFF0F1BB289
-:109B300035B467785ED282894250DFF2AF12F159B4
-:109B40002DF463807E8AC666D27A6A99C58BFAB88C
-:109B5000F6907937F26B2D987FE867019FE48C4788
-:109B60003E9920074C6007BF6908E648742EBDCCBB
-:109B700024C1FC5624017F0C1B980FD66AF719C428
-:109B800073E02F37F6F7D9CFC6E7521CFFF0041564
-:109B9000F1D562E0F79802BF92DD3C3F868B687991
-:109BA000E2188A4F32C5EDC6F852B576EFA5536676
-:109BB0008DCFF5233FE78EE7FBEB4D97717A90FA57
-:109BC000D59FD7CC18CFFDD0195ABBEA23AF65E09B
-:109BD000BDADB55D46F24358614F9ECFDECF7A1AD8
-:109BE000B7DE9915C1D7EB0E9EE0F91AAC272F32DC
-:109BF0009FFD56AD5FC147B2C9EEDF6D8B9C1F1F45
-:109C00001FF87A0EE2E1AB78E0EBE1C4D727D1CEC2
-:109C10009E6556E36E84B207501482D2FF0327E597
-:109C200027893CA5A5CC47E50A6003E4635FE00112
-:109C300013E27F15EBA0E76B4B6E1982F03AD65B0F
-:109C4000E5423FA2BDF91517CC72DEF607A6625CAD
-:109C5000766E70F12B58CED92B9D44BF15F6C512E8
-:109C6000E4E31EA9BE6D308CB7E0D98AB634783EE5
-:109C70004BE6F460AF737A00BF78E5844BD709FBFD
-:109C80006015ED83782FAD43764CD7ED83DA8DCC1C
-:109C90002B2585F3EDFBF645C9AD7F4A433F48E9E7
-:109CA000A5F3F77587CD0948E7558CEBEDB01D2876
-:109CB000F435B7036E053B00DB7DA2F1F327198C69
-:109CC000EE357C228163E709DB916C88DFE5191EA4
-:109CD000D6BB9F1882C58EE1A4979B71BEAFBAE632
-:109CE000A9182FBB35C9E296B13E3E38849FA3F632
-:109CF000C9777631361CEFBADFC8E34FD1F3924A09
-:109D00005EFD2BDA0D66130BE0B906EC6B568CFB8F
-:109D100079B089F6590BA216E366953EB5BFFE5B96
-:109D2000B57EBBBEE6FE6F00D683F77C2E19C7A9B1
-:109D30008D13C3C711FA03C723F991C274E3ED1958
-:109D4000CFF7F59B762FCDBFD9104FF2E60F43FD2D
-:109D5000BB91EF44DC47F8855D991F6791FF7EA1B9
-:109D6000251DED73E05F9EC73899CBA5378D6A003E
-:109D7000E1372B3229EE2FE4EDEC121E279B2DE26A
-:109D800062655171B1A8780C2BEB3F4EC698DB8809
-:109D9000E38E64EF09FC501CE6489942740F00DD25
-:109DA00031CE7C44F34F2B62B95F9E509248EB4C0E
-:109DB000B8368BF8CD91C842740E659789DF8EB2A4
-:109DC0007C5B42849CB8578BAF6E033B8845C4D5FF
-:109DD000EF2D6CB060BEC1661BBFFF785F654C5D48
-:109DE000647E7CE2649EFFF2C3C915AC04F0976701
-:109DF0000B5692BAF62A2AAE47D2D637DA09F83786
-:109E000060D73E2D4EEAB6F0B85415E96B41F72BFA
-:109E1000D5D7CF28C18D31B8FE2446FBD0BEC34A6A
-:109E2000F254EEF08630557BD9E4B9EF223F33C5CA
-:109E3000978BE37416C7301BB4FFAAD344FEFD61B1
-:109E4000C3921F9870FFBD6B6678DED9614F535087
-:109E50005F747C3DAA8A4AFBC4698CC739630D20B4
-:109E600028F29DEC897F43A269F7D54CAEA3933EBF
-:109E700002147748AC8B51DCCD1B6B009FACC3C088
-:109E8000CE95C3FCF6DB3C0F8D2316F4C9B8DEA1DA
-:109E900093FC9F227F15B37A82EF33F9EA76C3F8F9
-:109EA000F72558886F3CA906BA3FC8FE6AA3BC1FB5
-:109EB0005F97624415F76299FFDCF808BBCCE73284
-:109EC0001831FFA7CD04F23B0FE32831FCCC8A7197
-:109ED0007BDF773E87E6F78D264F5B5DDE6EBC88C5
-:109EE00032205E9D4A6F5FDC84F8329DE27D02CFB6
-:109EF00091F47416EBE8E93746D2B304E8392692B8
-:109F00009E5EE96AE8F90E26A1155DCAC7814AF589
-:109F100081AA42AEFF30952E9A8F2BCC936C980776
-:109F2000D3E9900D48D7CE98B43C8CDB093E167C23
-:109F3000DD0F3FAF3F8A72255D71E279B2B93A8693
-:109F4000CE67047F0BBE9E5EDAC7DF8F95023E1799
-:109F5000DA7C5351F644F337C6CF22F9B876407E07
-:109F600067CEC87D3E0BEC8DB804B4934EEDED8802
-:109F7000E0E3DAFA2F142E772E96C71487E37DB329
-:109F8000CA24F64124BDE1FF07B9DAFAC84E52C827
-:109F90003F1378BD52FC1BBFD39C8B76DF26BCFFE2
-:109FA00008F86A97DCDE411807AB3F711B3E6FD3A0
-:109FB000EE2507F24CDC1ED3F695E86FD9E4CA69AA
-:109FC000B8FFEDE3CFC42E87765FA51854444E9BAF
-:109FD000BAE4DF689F1E8F65F89E23B1BBEE09DAF5
-:109FE0007723189E277EB5D23F14CFF7B7009D3E4A
-:109FF000A0A4EDE020039D7DF50CC27D07C875F19E
-:10A00000D2EFE2CF99561F24F80F138669E78C5ED2
-:10A01000AD7D0FB5DF62DA6E89C171322DCE3D1193
-:10A02000FC5FAEC5E35B4BC4FD9F1615F3DF5A4BD7
-:10A03000B83DFB50D3BE491F65E37C3A267D04F34F
-:10A04000499C19647EE0EB98DC808AA923966FA670
-:10A050004878CF818D621D18A7C7E7CD63C2FDAFD9
-:10A06000D4FAB5A09D03F4B36C0CA89172D662909B
-:10A07000FCFDE5C9FC718242FBD5B29151BDE5C83A
-:10A0800023F4FD80C42CB784F9D5968DDB199EDFAF
-:10A090005843FC795296575A1AD16FD24C9877048C
-:10A0A0005F007F05E2402E59F6006316221D6228EC
-:10A0B0005E193DEEACE4CA2EC531309F44F31BD38C
-:10A0C000F84DF08D5827DD8089F80E40D5300BE92A
-:10A0D000C9B646D36EB4CF7795C4135EBE4CAA8C76
-:10A0E00063FDD8A7A2DC057C1030A33F6DA1720FE1
-:10A0F000F8E38111E84FBB087E0AFC712CF7813F21
-:10A100008EE533E08F63FDB3E08F23FC13F0C711BE
-:10A11000EE007F1CE1FDE08F237C00FC71847F0A50
-:10A12000FE389607C11FC7F2E7E08F63FD21F0C735
-:10A13000112E37037FE07A7203AEB940D7F6BB4DDC
-:10A140005ECC33FC6D0997A747BDC312DD407F6B22
-:10A15000AE8162E5D6371E64B81EABCB40F7CC3675
-:10A16000B91E64B7A09F5B6C277BABEDC7DC8EB1DB
-:10A170002A0F31943BBBA4401D73C3782537D5E229
-:10A18000B960966B7D6502C0474A16EFB4C0FEC841
-:10A1900051E7CC6F8E8055BB67D573CE303C346FA2
-:10A1A000B7029E0CFBE5C15B76E215239C07E61720
-:10A1B000BF55B2BC16F3EA43C318D923BD9926CACA
-:10A1C000E3598AF4CAC6F9F373C0EB588B0BCF3945
-:10A1D00087AAE02D49D49EE24C57DAFEB7252A3DE6
-:10A1E0008F7EEF72ED0C8557D48EC997E90FEBA5E2
-:10A1F000CBF46391E659BA61EE5B8D9A9C4AB691B5
-:10A200009C6AC7B80FE0BDDDCACBFC52BECF8DA59E
-:10A21000950F4F80F2E1099CAEEDD680B312C71FB7
-:10A2200063A03C07D698F9CE3018EFCE5F290CF327
-:10A2300045057F9ED1F8207BA89DEBEB7B2C74CE4F
-:10A240007FCDD01FB726009CFD84DB8DF9105B9974
-:10A250003B06F924B0CD4079913F2A1C9E30079AE5
-:10A260008F2E7A2101E5FA8C097C1E412D8FA8B929
-:10A270006DF9508C537DF51697877FD3C6D96DEC59
-:10A28000AE277A16D918CFCBDA4EF648B30B880D25
-:10A290003AD390CA4B93D1B900DB99C030C0BC6DA2
-:10A2A000D3D7E32DE80FB69C374FE779B5DD649F30
-:10A2B00098AC7E673C3CDF1E30905C68516D940723
-:10A2C000B7D5E6E9C27BD301A781F265B7E61908E5
-:10A2D0008FADB61B82E8072852731DEAB1A073BF89
-:10A2E00025139E07F30C94FF18F4CE9D8E70C0CFFB
-:10A2F000BF47413F58EF4FA0FBE25B59EFEBE3B0A4
-:10A30000BE96DB696D29FF752416E3E2D73BDDFCC1
-:10A310001886A9983746296406F4C77B36C6E23CFE
-:10A320006A98E6EF06C8BF759839FDBEDB79AD7354
-:10A3300018D91911E75D668CE1B92D6EA81F6BF372
-:10A340004C47FF53B17B2C9817D8EAF45816D3FA30
-:10A35000793E1BE56B40BF2D4E03F9C1587F0BEED4
-:10A36000F75646F97083B5FA56DB839D880F651959
-:10A3700063992ACE4F09449E275A869775A9B08EB5
-:10A38000F6E509B40E457213CC962934EFC16A0C78
-:10A39000DD937EC854DD85F6E460CBAD74EE955A4E
-:10A3A000A7E8CEA506F9F570F27C3D9CC894F0B9FB
-:10A3B00016F2D9041197D3E32D1A1FA9CED6B77080
-:10A3C000FEA97EBAC47BC9FC1F717E2FBE82E13C10
-:10A3D0006D34CF14DB920AB49B9299AF19F9EF1F39
-:10A3E0009DE758E75C4B268C3F36C940E6D138D60E
-:10A3F000BB11FBDDAAF17B7B26A767785FC9625F93
-:10A40000364D48C6F305033874E1FE3303E0D8E95E
-:10A41000CE17127470F6F6C1BAF623760CD3D58F28
-:10A420000C8ED2D58FDEE7D1C1633A4A75EDC71DD8
-:10A43000ACD4C1F9A119BAF6055D73757051F70274
-:10A440005DFBF1C797E8EA27F4ACD2D54F3CD5A025
-:10A450008327F5FE8BAEBDB0EFA3F5E3DD13B87D2A
-:10A4600071B576BDD93558F7DD9C68BF21DAEEB7F6
-:10A470007CD3A26E447E7698889F15D4E7780E7DB3
-:10A4800037F79F2C93DD2AE5396BFC5854EEDD84B9
-:10A49000F2B4C26121BDA0D8783BC5368DEC9521C0
-:10A4A0003B4CF43D1FC5C9FAEA63513E37052665AA
-:10A4B0006587E76D756E67B87F2B1CD319E6298910
-:10A4C000F715A797F9318F1B3FD28376923340ED72
-:10A4D000AC2ABC1FB18EC30603B3A11C073F0FFDFE
-:10A4E0008381FC3AE1CF09FF6D20BF4DF86B430C2F
-:10A4F0002C06CBDD52CF6DE8DFE7D5BF553988910B
-:10A500005FB70FF9F53EBC078EFEDC586E67B5A548
-:10A51000CC5031DED39ED9D1350CE7936CA0382ACC
-:10A52000D8CDEEB911F6E2DB9AFE5186B5F7A0FE62
-:10A530006B88B7A8682F2996DD933E027CED32F632
-:10A540003C8DF18B56C9B9BA03E5E2DD36CA0F7905
-:10A5500048C39B6A37146C847E3B9ABD0ADEF7EFD2
-:10A56000D8C2DCADB83F922A36C6C3F3ECF4C506B8
-:10A570000C138DC86ADE88E5B109FC3C6864DE6EA8
-:10A580004322D48F2EAC988F7131D9B99BFCD981DD
-:10A59000F84976EC60B81E96A59C44BE42EBFE22BC
-:10A5A0004CBD2201E80DE35A91DE12958407EB7948
-:10A5B0005BD08A7016C78BD52B0563256EB7627E7C
-:10A5C0005D45C20EA2AFB067D1CEF5737FF76DE4E3
-:10A5D000A3A4997ABA2A96BD848FAD06BE2FDAE37A
-:10A5E000D537503FB7676625B4A8E1790AB9F24775
-:10A5F000CD0E17CF855C998D3938C961FB06F87C83
-:10A6000007C6E7ACCA76BAE769DDB09D215F5BF1AA
-:10A61000563CD9FB01D547FAC3A7CB4FAB1A36DF5F
-:10A6200082FAFA5C9287EC596BE34F697ED178B37A
-:10A63000F6F03CB581F0EAC87994F43B086015FD6A
-:10A64000FE2329B6BAC8B8A828EFD2FC13A3C8279E
-:10A65000024F02F5D93991AFE48DE5F38BE7F0D1E4
-:10A660009C0534BFDB923D832E676F5BC1DFF447EF
-:10A67000D07D8BE2B3201EDA2ECC994EEB56683398
-:10A68000B0AD5FE7EDA678B3E62FDDA5E1B7B58401
-:10A69000E3738889DF337027CDA4EFA40DC6F84893
-:10A6A00041385E32AA94E737BA034CE6F1BEBEFCED
-:10A6B00076C3C571346715EF1FE09920F2631AE382
-:10A6C000FA0C9A74623ECBF076459F0FAFE9F334F3
-:10A6D000FE3BC87F7DFD881D7A786430EAFD00FB73
-:10A6E0000DEA7BB477299EB14F5FFF18EA6D901396
-:10A6F0004B35BDCDB6F3FC120BCCE822D7B761FDCC
-:10A7000007F260564777452CF49351A2CF3B498B13
-:10A710006C07F8F3AC34D0BD1211DF1178F7D519FE
-:10A720008C26E27F55770E27E239D1F25ABAE7CC70
-:10A730007ADC5715B1B12ACA598C77F8CDDC7FF78E
-:10A74000833F739FE2FE7D2DFA5F5D32E561097AFA
-:10A7500046D37F6F9F3DEC2B2F253FBAA700FD7A94
-:10A760001CCF1F319E88CB6497FBA7623B119F399A
-:10A770003B5D794552C3F116113F7818F719B4DBE8
-:10A78000EA7EBBFE28CCE3E87133C54AA6CA6F74E3
-:10A7900035619E55864272CE397EF50FD04FAFFCA3
-:10A7A00003D4635C52550791FDDE65A47841A5C6CC
-:10A7B000EF959A5F26E2320BB579D7940A7B281081
-:10A7C000C3FDFF500CDAB9A3F7818CD6F34B2CAF45
-:10A7D000E771BA311DD1F55ECA7F1AA5F103E6AD66
-:10A7E00055A460BA18873B9894E8043A8F9BDF73AE
-:10A7F000045D8CBCD75E8941BBEB392BE78F673496
-:10A800003B2F85496ECCEF4FD9677307A19D5D66DD
-:10A81000CF75C33ADCC7145D9EDAD8437A388F45CA
-:10A82000C099380F3DBC4DADC7A36BB6AD165811DE
-:10A83000967C47A9964792C37290FFA6CAB67CF44D
-:10A84000B31A2A6C0CF16A3E31E2FBDD2857DE9226
-:10A8500019EA0B67ACFA4015BCEF7C3DD1DDAC8644
-:10A86000E9FF0CF8DBA8471EBEE866ADC670FCEB3E
-:10A8700059A067169D4F3BA9BE03E88AF07EF0BF42
-:10A88000B3E87C3A979EFF14FC6F840F82FF8DE53E
-:10A89000CFC1FFC6E787C0FF46F887932B1EC4B819
-:10A8A000D97BD00EF92226FF806538C6CB6D32DD0C
-:10A8B000DF89E6C7CDF51FDA6E049936CA953C33B9
-:10A8C00019F9E17699EE45432733D1BF8D8CBF4509
-:10A8D000C623C3F1B71E49C4DFCC409F519A7FD92C
-:10A8E0001787F3F338DCB7F7E315FD509CF3927E3E
-:10A8F000FAE29D96C047B928B2241607CF3FBDFBA8
-:10A90000DF9F427D24A7FAF7E23E5953F48189DBA9
-:10A91000E7FC5E56BAB68F765A793E6ABA96471405
-:10A920001DE79C3CE5C46DC980B2177F7ED3428C85
-:10A93000134CBEF544C11080BF29FD25877F78E206
-:10A94000F934C0D3D289ED1C7EE8C4B97437E671FE
-:10A95000EC5F88F9C38E44AE07776AF79B047E8F5D
-:10A9600069FB665DE313A4EFC11E61888F96141F17
-:10A97000E9E1CF937A1D8BD1AE4BEE4D597219BDE3
-:10A98000B1AEF1297A7FA7E43E15C4794FB0F0BC8F
-:10A99000554D2F9DD57857E8A5062B07C57C187314
-:10A9A000D1F387B47811F3A6D17B89560E1F759425
-:10A9B00092FEBABF52FDB5CACF3FC98F3EEA18F525
-:10A9C0005DCCCB6B99AED0B9E443368F15F5DBE7A0
-:10A9D000DABAA0FF00C60902532D745EC492E6D312
-:10A9E000BE4E10E324D5523E4382369F63A53121EB
-:10A9F0008C23B45459F6A01C7DD0368CFA6B2931C7
-:10AA000005307E23E08DA5301FC067BC2321136174
-:10AA100021E7447C99E1E91CF45BA92DBB52E44990
-:10AA2000588C6722ED701BEB26FE711B5419EDC884
-:10AA30000D13395F1530F77C7C6E92EA03C88CB831
-:10AA40000E43E43AD42AFD3AD4A9BA75480D9610BB
-:10AA5000DA8F2D53611DD0FE98BD98E61B4D37B19E
-:10AA60009E0F4B55C257F43A99762E25EE1F543A55
-:10AA7000CB0EE0BCA61ABCAD38AF57FE5A9B841F64
-:10AA8000E89BC6EA157C3E3C9C0FD47A35F91693B8
-:10AA90003F94F839DAAD265A9F71329FCFA3A66052
-:10AAA000265D0C5182A9787E3C101F674E8CE663B0
-:10AAB0002FC3FDD592E0E57CECEC7534231FC7F77E
-:10AAC000A66CA47585FAA54F343F47D32B6F22138C
-:10AAD000DF079111FFDF465F41D7E8F334C12F1B39
-:10AAE000263A05BD5DB4CED010DD7923F4A0F6770B
-:10AAF000CEBE09FA5323CEE54C2E1FD9E3C62477E8
-:10AB00002EC6A55BBE91FBBD7F59ABE1A9D9114310
-:10AB1000767A8B83DBE99D8E193AFFAA0AFC2D3CDD
-:10AB20008F96135907EE2B396E01C5DBE441689906
-:10AB3000115BE8EDDFB899DCFE757A2E7BFF4AE900
-:10AB40009175DF73BBC4FE4D98C1ED5F8789ECDF63
-:10AB50009D76D3FCDDFDC89DC289DC4FEAC475F447
-:10AB6000E35F825F49714FE1579A9C7EF20FC53ACD
-:10AB70000BB57D26DA9B9DF50CE370B2C9ADA2BD85
-:10AB80002B6BF764312F3A37C22E10E38F9BC8ED41
-:10AB90008EC1E53C5F53E4C74FFEB554DF1FDED7DF
-:10ABA0004C147649FF7CF70FF00DC9098FCDE445B1
-:10ABB000BBC36373511EF940EFE151F8A984B09C07
-:10ABC000717F532C933E52DC742FA0C3D8F3FCAF9B
-:10ABD000D16F7CC5467AA7C39E4EFD09BBBD2296A8
-:10ABE000517E33F8C9815CE8ECB9BFC18E3484FD75
-:10ABF00063F0D7364F8C38D73CD27092CE8BA2ED13
-:10AC0000D5E8F843DF7E773C95C9E7134CC5FD2BAB
-:10AC100035940C42BE8ADEEFA2CC70158C5A0AF332
-:10AC2000CA48CDA7523C7F9CC9D3FBFB6EDBAE3E2E
-:10AC30003A703D3D12068B93493FEFC2797F7AFB14
-:10AC4000DB296E15EFEB7E417AFA6C7D49DC66E418
-:10AC5000F7DC0492AFE9DAFD33319FF4959DF109F9
-:10AC600036CC03EC1D89F973C126DFA82A23C50D54
-:10AC7000BDFDCDF757DAFE63A1A12CF2BB446A52A9
-:10AC8000F7B52300EFAACDE056697F3949FF0939AE
-:10AC900050A1C4573981CF339A98DBA6E2A79B9D78
-:10ACA000143FCBB82813BF651CE5DF971E9AD42B41
-:10ACB000E1778FFAC6D1F2A4C439CC97F555B43FE9
-:10ACC000330631D68D7210F43DCAF92F934273705A
-:10ACD0007F7FF93D3EA38C27F4F5A07329BEBDFC10
-:10ACE000F698A00A5D0FDD00F3C3F9FC4062E99914
-:10ACF000388FA3999B313EF4622CC587E41D59140B
-:10AD0000DFB93ED5BF7F22CCE3D3A07AA761B8B626
-:10AD10005868B7E6AE18FA2EC14EA9FB5ACACBB88E
-:10AD2000C340DF6D8DC6D75B13B95FF9F644BECF64
-:10AD3000325CC59CDEAEC2514B13AF7C3F7D83DFDE
-:10AD4000D601FA6E8D0BD2799EC82BDB66EC9FAFD5
-:10AD5000CACAB87CE993C71AFE2CE80521BF489AF5
-:10AD6000DDB7EF99679E4961FC8AE2307E6E197902
-:10AD7000BE1C9315A4CA18B797E48FE4F47239EB9C
-:10AD8000AC770580BF377F2DF73BBEBD4C93D31901
-:10AD900077BAB07D95EAA6B233A3F8F862C09FCD2A
-:10ADA0006662E608392CF8245ACF37D8875DD6DF9B
-:10ADB00037813C562F138F306979649B8E4CB0E0FD
-:10ADC000774B37D93CDD687F6DB22579285E6F03FC
-:10ADD000B91111BFB2D95E253EB4B9795CCF86F204
-:10ADE00017E357B8FE3C9CFFABB47ED1EEB4268788
-:10ADF0006CEE109DAB5ADDDBA99D45F1D1FD3B4BBF
-:10AE000012A37C088B937FEF3426CBC02CFDC8E3C4
-:10AE10000F501E433F9BF23CDD95343F05AF65B1BB
-:10AE20004D2E8F8BF421E219DE3F6A2F8E8BC4CF1B
-:10AE3000500DCF2D9D7C7DBEC654675501FAB5BE21
-:10AE400094B222EC678905BFAF27DB0B2FDB4F6E77
-:10AE500019972BE17E1E49A94AA47E86623FB2DD86
-:10AE6000E3C47E8CDA775BA3F15CA4BDFFF7C6DD9B
-:10AE70000083940F447821C2847474892E6D183F26
-:10AE80004BECEF3D2E173335FF05E4624519CC6BD3
-:10AE90004DDE07AFF23DC6FD96846B79BED1592DCC
-:10AEA000DF3C3A4F23DA8E11FA47E823E847C67EA3
-:10AEB0001E453B6644781F0DE6128BA5D5F9F87E3A
-:10AEC00049F211BF805DA3E27E91B57CC1E8F56CCB
-:10AED000D6F027394A54D41755177AD2F0BDC3F6A5
-:10AEE0005369DC8ED59F471FFBEB5356ACFFB2AEC8
-:10AEF000F2B2F68A387F1EE8DCD9F12F9FAC8FB40E
-:10AF000057063A87FEB6F3E7230E13C5F97649FADA
-:10AF1000FBF5CD9A1CDA5026E232FEDB901EBB24F4
-:10AF20009F9B5F98E6F199A272FF9DF87C48BB89D0
-:10AF30000580AE87FF5AECF247F473A57816F1FA54
-:10AF4000C19A3D35D8F69484FB74705D50C2787B0D
-:10AF50005A5D87E4BD4CBBD9655C8F8BF646ADFF6F
-:10AF600072A557467D55EEE47A31EDBCC27223E4FA
-:10AF7000CE8C32BE7F8D9AFDEE38F2B415FB3B626B
-:10AF8000F0B5E7A07E7018D42723F6BB71A5C75291
-:10AF900019B1BE163C47EA878ECF94F5D95DA4BFA0
-:10AFA00085BE350A3D91A4E8F4C4BA58CEC7C2DEC6
-:10AFB0005957CAFDA175B1DC2F7FD1E57F02F7F3A8
-:10AFC000E7A59FCC1AAEE23DDB0E139EBB7FDB797B
-:10AFD0004A9F7D63082E16FE0CF2BF5B71FEA2072E
-:10AFE000DECFFF6105D97B45F8E512198F70B9FDF9
-:10AFF00007F6D473385E014E3D82DE2CEABB860331
-:10B00000AD67277E4BAD08E37FDD14C7BDEF82D46B
-:10B01000EF7D8A2FCB84BDD0776E78D938AC8A711A
-:10B02000D84C3C07D3C7490BBAF47051B71E1E7FEA
-:10B030003C3AEEEAFD6D64DC7527EC33941322CEC6
-:10B040009A1E0856E03DF30CD641E7906975093A1F
-:10B05000BC4E96B5FC0CFCBC7244FC374DA93E8D31
-:10B06000EF9FEE5B5780E9EE07542DBD133FC519E6
-:10B070008EE3AA84AF15D7CE9D8A748D8EE766D4F1
-:10B080002BBAFB84D171DCE53BF5F70D7DDE7CF25C
-:10B0900007E67D471FFF1579EDB8DE34CFA5E37FC6
-:10B0A000FBB8F03FE1D2F145BF8F82FC21F9AA7DC8
-:10B0B000C73803ABB01F2524E179F8E07A46DF33C7
-:10B0C0004EBB9D79FB3B57489BC4F1158D671628F5
-:10B0D00027FC4DD19E0DB6F1BCD7C1B71BC81E1CB5
-:10B0E0000C7281FEDEC16AC612014E5BAD923D3923
-:10B0F000BBCEC0503FB00B4DBAF761BA144F1574B8
-:10B100007FD4C6F37A33D6B0A001D7533F8AF61363
-:10B11000CD6B982EEEAEFB2EC1EC12FD7DDF8CA820
-:10B120007BBE820FD2A29E1F2A73EAF605E8B9B44D
-:10B1300049C4275CFF65A3FE83297D3AE1F8539853
-:10B1400087377923E3DFC3898FD1BE87D3775E2129
-:10B150005F047E3D6299928BF6CA56678C01F32399
-:10B160000EC7F73CC6E2191B338905F0FB9D2FC7BC
-:10B17000F48E96009EF0D29E5DED4094C3D6DE1F05
-:10B180006130D9B6EDE99BA747C08EFB5F22989549
-:10B190003015BF2F84B9ABB8EF629C33F6E1F77C72
-:10B1A00063F26C149C8C61FAEFF8B496AADB30BFA2
-:10B1B000A435DBA0DDB38EA887753C35C929F2E242
-:10B1C000284F8F4DE7F90291FD639EF780FDCF80F8
-:10B1D000FE0BAFA27F0B9F7F0A3E023D9382F3C717
-:10B1E0003838F68FF4C5A051E4F85A7F0A0BECC644
-:10B1F000F31D18CF26F1F19C98BF92C2F4F90A7D95
-:10B20000E33961BC31FF17D633FF527A182F478FCD
-:10B210000557478F568397E61B186B233F08BF8758
-:10B2200085DFBDB36AE359B5EF7F215E5B8BC378E1
-:10B23000053B90FA85E6CD17353C633E628AD344E0
-:10B24000781E086F479C3C7F6A8B3326D89CF9FF99
-:10B25000805E2E4EAFC8F1D09EBCE2F116C0784998
-:10B26000573E1EE217F74F1F7E81261B53AE1CBFB1
-:10B2700030ABC095E0F708F46B88C06B384FE9112C
-:10B2800027FA0556A3CF82799BCF4FE2F98F7949F0
-:10B29000732D94B7903C97F290DBF26C9457DF9645
-:10B2A000F51D8B31424FB7E5D5523DB4A7FCAABC82
-:10B2B000500C8629D818D64D71802D65552EF40B6B
-:10B2C00003F53C5F4BE42F097DC8B4F3515A17BC1A
-:10B2D0001837E940EF1168BFA5BE90F2D3E2E2FF54
-:10B2E0008BF2B2B6D6B9DD58FF189E63813DF1B03E
-:10B2F000768E858C4AF1B4B1A54FE0B9AF27BB413A
-:10B30000C2E3A6F4D57AFD34382AEFC7F345772592
-:10B31000E677B1C53C7FCB55AB44E943FDBEDD8A42
-:10B3200078E579564189E357D7DFE949C9A4E7B6FB
-:10B3300064ED6115D0EFF3D097ACDF5F06CC778A70
-:10B34000DE8F8AC94BDF29630D069A471AA6108043
-:10B350008AF38C99E95A0CCFD39729F4FDDA417915
-:10B360001B28EF09AC7CB237F2F2DEA844F89275E4
-:10B370002ED5AF237A5DD1F316DF5716F4F27CE1B8
-:10B380008E45FFCA933D97F2D2E847EC77396A3D84
-:10B39000600F5B930CF45DB998AC8875315D3BCD63
-:10B3A0007FFB9F857F3F8971FB39FA5CEC7FF1FB66
-:10B3B0004766E6B698E83D715F879FB70DC6BD83C7
-:10B3C000741FC2787E78F4FBC5FC7DE6E2E76FE689
-:10B3D0001866C1FB3AD2AA188A639ACD00E37D1E93
-:10B3E000ED7B658F6AF1B6668929A99EC8F1429402
-:10B3F0005F2F5BAECB42BFE188659E93EEC9697E4D
-:10B400009431DE47F98D2C3741E78F1ED1EEBB35E5
-:10B41000ACCC1C84F1BB38A8EB46BF5A715B90DE04
-:10B42000226EE218DE7313EAF16193872FB2002EC9
-:10B430000EA3135CCAD8B8C3193FC0EF148BFD69C3
-:10B440003ECFBFF7D1072BF5943F623E3F44F73C18
-:10B45000A4F96102F626295538DE34F40F92F1DEA4
-:10B46000B8B315DFAB00E4E8BE2FA07D3FE4D2FE09
-:10B47000D375CF43E05F479E0B0CDC7FACEE3B0502
-:10B4800066F077FAEF3F27AA7F67BFFD87FB4DD4B1
-:10B49000F5DBA670B911488A09F617DF5B36B9F2F9
-:10B4A000BAC94503E7B72D9DACC5E12C20FAF11CC4
-:10B4B0004AE39FCDAE7ACA779363F8B9A911C4085D
-:10B4C000F2D3517B1DC92D96AECF7713DF2769C309
-:10B4D000EF8E407DA54D6FAF57B0DEA3E324F4534C
-:10B4E000F5F6FA645439783EC5A2EDF87A3A273574
-:10B4F000A6EBE5C2456DBF18EC85DD941F976CA3E4
-:10B50000BC8681E20BEF3531CADB32C6FAEA51E77D
-:10B51000FDEBE1F143DB4A008EE37CB6F5F0CC4570
-:10B5200018377A4FE3E736900374CFB561D06E39A0
-:10B53000A2DF5A53281BF54AAD81DF17A01F18FF61
-:10B54000BDE4C114678D1E577C7F46C00BEBA54937
-:10B550005911EB7B4FDB1F7DE3DD96B61BEDDABEA9
-:10B56000F1CCA1221AAF2FFF481B2FE5EF1BEF8F65
-:10B57000DAFE16E32DBC53BFBE85A66E5ADF42ED40
-:10B58000FBA762BC3FE2FA32FF8EF1B4BCB1BEF160
-:10B59000EED2AF6FA1B99BD6B7B0CFBFD4C64BF92F
-:10B5A000FBC613F90E66737D1DF2D340790F22DFBF
-:10B5B00021C795A8CB77C09B2715598C3D2071BE1C
-:10B5C000787D72CD0F30CE7F6E66839BEC14CDDF1D
-:10B5D000A37B4432DD23223D3A3B9DDB21A2FF7D4C
-:10B5E0004D25CC3B82C783B0CC2D93E89EC2C812B8
-:10B5F000C98BE76C3B417EE077F476C13EC7FA60C9
-:10B60000938BCA3D4D2A957BC1BFF452FCCB4DF0C4
-:10B6100085C9DC5F7C20D559B314ED8F8A189EA7AD
-:10B620005D36112CDBB0FF06FBE58815F3216F605A
-:10B63000F9F8772D7376707C2655A5D0F7F663F26E
-:10B640008F753701BCB9445631FF7CB3DA7F3CE7D4
-:10B650002F5ABECF662DBF3280F72E49A9803F59A1
-:10B660004C7F3F8BFFC833E95ECEECBBE2C9BEA97D
-:10B67000FD4E8FDD09F3B859CAFF6D16E0E34F9A0E
-:10B680007DB368C80C9207D1FE69126AAA42CC3B0E
-:10B69000948341F8759E7D1EF9B7F3AE672C01DEE9
-:10B6A0009F8DEF819EFAB5661FBDD96366E8FF05E1
-:10B6B000AAF8F9F5CD1BF47EE903D69013EDC20785
-:10B6C000F29318D2A3F6767DFD6613DF6FF3A2FC2A
-:10B6D000D4D951793FE23B8A9BF1D7098C7D395906
-:10B6E000FB8E9196F7B35F8B33B1F4044A0617F7DC
-:10B6F0003DCD66D6EFB9A4E82F11041DBD97E42512
-:10B700003C88BC77263F9B8FEF8BF1C47B8F4ACF61
-:10B71000A65E2E6E0A76E0C99E5CAEEFD15EB7964D
-:10B72000EBE7796EE6B0EF56B1FEF8B657C1388553
-:10B7300098FF3F8B5F8FE27A414EFF7ACA9785FC74
-:10B740003E5E3A8BBC8727F2BFE6F5C10A7D9FF8C3
-:10B750007A01BA7AF390DEBF9914EBBE97F84FB333
-:10B760004742EF1A2EC65E7D7F7DF370793374F702
-:10B7700060B5FE06C2F340DFADA09FE2709CB7A5A6
-:10B78000D9EDA27B77C9FC9C6D7052E569BCE78559
-:10B79000F51FE8F84B7F9FABA5F36909FD96C7F04D
-:10B7A0001E9C31224E54D721B5D9B0DF208F2B8576
-:10B7B0009EA6F86F7A5D486ACD0BDF1B8A968BE9EF
-:10B7C000ABF5F7D2A2BFC7586DEB512415E3FDBD11
-:10B7D00074DFB1AD5C3B9F411C63BB646E4FCA69B3
-:10B7E000069E2F3254E5F66556EF90C8F38E55E568
-:10B7F000DC6EA88E7DFB761544AFBFBC6311E645B9
-:10B8000055C7BD7D7B26C0B7943FB708BFB3589DD1
-:10B81000F6F69799206F9795EFE7F0E8B7BF1C060B
-:10B82000F08AF2E7398CF91E80A495E50716A1BCD1
-:10B830005D552EBEBFD84DF7BFE554CE477F776923
-:10B8400036F4BB2F6F2B17714B46F7BD7D877E7982
-:10B850001CE5944FC479BDFAF34DA67D7FF13AC142
-:10B860005E490EB29766E0EF80CFEBB4EFF6182C8E
-:10B8700021C2EB88F07751BE7735DFED09DFB7E7FE
-:10B88000DF9D6A69647EFDF715BD1AFFF3BC2131A7
-:10B890001F31FE25F3C2EF0B2644CE6B27F523E6BE
-:10B8A000F579BE39208D0B9FD78A797D2EF5EEC2B2
-:10B8B000A047CF94DEC548D7CFEDBD43F0EFAB94A2
-:10B8C0008786FA094EEEDD25B9236023A7E323E539
-:10B8D000FF87ECA951A9DE47CA317FCFC4BF83D00F
-:10B8E000AED9915B93FD01F4EB81DF286F3390C1FA
-:10B8F000EF3B5415EAFF0EDC131A7F1579F9F9F4C2
-:10B9000054F3F6FAB70AF1BBEC126B86F6EB2E9CF9
-:10B9100033A1DF5F7DE88409FDFBB5074E98D07F3A
-:10B920005F8B30F4B376A7A9DFBF4357EA95C5FE16
-:10B93000D5F92BAF64E4B425C17CD62EE5DF016BCD
-:10B94000F859FC54841B16E32AF1EFF93D37155FD3
-:10B950005BE8EB6CC37211EB7905CF256AFC7A3F8B
-:10B96000E2A63ABDDDBFB05E6FAF2FDA0ED401BDE7
-:10B97000B6A8312DEA7B80FC3B83351A3D6B5CDB3E
-:10B98000BAF13B06352CEA3B83011E47BA89AF006A
-:10B990004A7D7CA41AFF9E15AE63B54C71DE57320A
-:10B9A0003629784F6E5DBD44F97B530F7E61A27AD4
-:10B9B0006887E74A2983F9F7F484FC14FAFDA6970F
-:10B9C000761B315E10FDBDC145F3A7D377C5E7AB4C
-:10B9D000ABB87E1FFABBA909F03CFA3B82B507B9A8
-:10B9E0007EAF6D9482F8DDDE9BEAF4FEC042D6DDC8
-:10B9F00086FECCC27AFDF3458D7AF823A1D746B3F3
-:10BA0000D1B83F4E974B0AED170D3E93F1BB37432C
-:10BA100030BE3BD5C7BCC027AB4DA1B1A8E7DCA960
-:10BA20007E82453D3C5F8BF27FA07DF8FF4BF9DFC6
-:10BA30005818855400800000000000001F8B08008B
-:10BA400000000000000BED5A7D70545596BFB7FB07
-:10BA500075A7BBF341E73B31045EBE58244D68D265
-:10BA60000441778AD7DD494FF8723A40866008343E
-:10BA7000B350152549478953B1CADD341063072DEA
-:10BA80004B59B4C0F28F06C5D51ADD0D92C1CED286
-:10BA9000301D302C3A387676D08171B582CB3A524F
-:10BAA0008E9088A3B8CB167BCEBDEFD1FD3A2F8AFE
-:10BAB000B353FEE16E527073DFFD3EF77CFCCE396E
-:10BAC0009710E1A3B1D984E8082537F484EC344811
-:10BAD00056E7024202EDD47E5024A419DB4D84FDCA
-:10BAE000DC28C1FF797F56D74FAE3B244A480DCCA6
-:10BAF00063F676119CE718B51E844FB5822464D98D
-:10BB0000E03B254D0369D0177F96C4CB05928E90FC
-:10BB10005C427E43C66CA48C90592930610E94AB74
-:10BB2000A78502B0EEAC5F6D0A50986F9683DA7508
-:10BB3000B0AFE5B0E3EE6A2C05B21ECABB0542CC3D
-:10BB400050CED20F34E1BA649ED17A90EDB7809096
-:10BB500085842CC33F619CF432A11FC37970EBB87C
-:10BB6000EEF2E9A7BFA619307EEFE3137A28CBCB1C
-:10BB7000A4EAA7607F8F99F9FA8F0DD1D07698A7A4
-:10BB8000C376EA1CF6CB97085BB7A3202D8AFD4944
-:10BB9000D8F0C79BE72F8576D14AD6674165858D5A
-:10BBA000AD5B28D30E56261F433F1A75E96E5442EB
-:10BBB0003F79DD1F794476EEBCFB06289EBB9804D6
-:10BBC000B65358AF0CD6413A2A2521A6C04518DFF6
-:10BBD00008F7340DFAE90B7DCF2F8171ED0563462F
-:10BBE000528AEDE346EF5CCD7EAF2EA9D1E8270166
-:10BBF00001617F0F58395DEAF4D73380F2E4816345
-:10BC000065F9C436F97E94526FD21151E107F86795
-:10BC1000B05A88383B5E5F3E3B5B555F692F52F5FB
-:10BC2000FFC9A232557B8354A96A5F5DEF50D51BD3
-:10BC3000BD77A9FAAF6D72ABEA2905CB54FDCDE211
-:10BC40002A553D75F63DAAFEE9F69FA9DA49CE4090
-:10BC500081379D10A32930E6033A04815717C1FDAF
-:10BC6000A518D382741A219519D0194A8BC39C86C2
-:10BC700065707E4A14EF2D785B4615D653DE7CB096
-:10BC8000208A549FF68AC909E52F68C8950D73006C
-:10BC9000997C0340C7390F13299440CF636E1DBBB5
-:10BCA0004FA5DC26F9FECE09A5ED25B1086E047E70
-:10BCB0006273F07E4C16F813F9F88829847C3C0FE7
-:10BCC000E6248BE3F32CF138BB251CF7B0B414F950
-:10BCD000948489B502FA1D30C2CD423D70C4C8C6F5
-:10BCE000D9C2633A2941DE042797CFA7BDAEA53854
-:10BCF0007F47845A09F2F7DE8F8CA20DEBC319122D
-:10BD00009455DE8F8C242DF1FB05237EEF10C62D7C
-:10BD10005628FF69405F1FD2E09341C9C8F8F95423
-:10BD2000B191C94FCB83FA500A65FCBFC209FCD65A
-:10BD300024CB61CBA1F1A81ED66F013D13804F4DDE
-:10BD4000E27D2B08CA93CFC0F48D097E519E9E2EB2
-:10BD5000CC3840E671F92179846C94A5E99E45516F
-:10BD600003D2ABB9D510D74FF06FE31ACF255A05E0
-:10BD7000F376267D9FDEC7E47B63A2BE427A49E963
-:10BD8000391F833C924A62BB01F272CEABD33CD7DF
-:10BD900009B7C0CE75CEE766F47E1AE8A6A748C7F5
-:10BDA000643A71FA7D1B7D5EC5BB4EB8A7E47EFF89
-:10BDB000E2A6BCDF14FAD2E2E4ED0768AC1A95996A
-:10BDC000DF6B617CDA6CDAB4F5A203E9FF651F452D
-:10BDD000FAFF92921498FFFDE137F344E4F3432312
-:10BDE0007963309F7F60248F009FB519C4ED420EA8
-:10BDF000E303FB76B8978E7094EDBF7DC0318CDF86
-:10BE0000DBC3D48EAAD03F38E161E724637DD6340A
-:10BE10005C577B5F31598FBF2F898CCFFC3E5833E5
-:10BE200007C7A7844214EF1DF410EE6B889227A178
-:10BE30007EA0DFD414D298E70CD21BC6BFD16F24EA
-:10BE400002F0491B8CC7739C2A3E653421DF1C829B
-:10BE500073513CC768632ACEDF6520228DEFEFB3B4
-:10BE6000E2D88778FEF39B0D2400DF776ED6337A15
-:10BE70009FEFD2B379F45BFEA3AF08EAEB80FF52E9
-:10BE800060AB27375F3D5504F39E6F853A9CD7BD65
-:10BE9000C5C0E46FDDFD94F54FE65F855F9F95F9C2
-:10BEA000739D4FCD6FC9FC3A894F5BBF1B9F7E15B9
-:10BEB000E7D32AB4B370EF75F9C83F0F11FB419473
-:10BEC0009FEB270DF9B0DFD23EAB7D07D4E7EA4305
-:10BED0008FE4A15E38C9DBE7B7EDA75CBF88F7E068
-:10BEE000B98A8246B28B221FF1FBB23845568A646A
-:10BEF0009CA6A2BC0AB152D443B0B484F7FC9A8188
-:10BF0000341DB2E177AE5FE6BE5EB07F5702DF0E52
-:10BF1000499C1F15BD576924BE4369D87FE0B6060A
-:10BF200098E755188FDF67C8F355948D7B1AA09C4E
-:10BF3000E3E47A3047DE87527F4FE67FD22A50A46F
-:10BF4000E34A13A7FBB2EEE87A3C47E974DF6DA839
-:10BF50003757CC78AF0DED5AB0F42D9B0FF747EC67
-:10BF60003AECEF97E97E72F11F9EDB06E735DF6E54
-:10BF700061F7DA70625F0CEFB9A35C2078EFE68AB4
-:10BF800005F93E0DFE534AFFB512E2CB8ED73B2298
-:10BF9000131E4943AE47DD5CAFCE35F2F393081074
-:10BFA000A990E963615175BC9F727E4276B0FEE64E
-:10BFB0008A17D83D6DBB9FCC67708A3CC5CEDDDC4F
-:10BFC000364A37C13C6B0D92210DE8FCDEB4A6ADBC
-:10BFD000172B0879AB0754241CE44C8F89F8FE0A10
-:10BFE000F0528F95D5633D05ACFEAF3D222B7367B4
-:10BFF000787F84F4697CA3B302E975B2F819AF0BBA
-:10C00000D6B972C6C0E840888BD1699BCC7B5723D8
-:10C010007A6282F6AB833444687CFF1BAE15111F35
-:10C02000E893DFE37A30B0BDFBB74CCFD95B273C58
-:10C03000621AF2D5853EACFBBBFFE441DCF021D8AF
-:10C0400009E42F7F9892029867FDB56C36BE3D3C9F
-:10C050006A14910F74E31EA47FE03825C897FECEC2
-:10C0600009A63F9F837349B0EFBF756672BD1199F2
-:10C07000AFE3F7B980E314F9FE87E7FC6706EA2F20
-:10C0800053B7F8CE5D788FA7F5EC1E77B9C633AC01
-:10C090001AF7720EE625297CFF5826B737190315C3
-:10C0A0007618D724F36D72FB43323F02850D881357
-:10C0B000F08702DDD6CBFCD50247990678617D98E2
-:10C0C000462D20B72D11F72501CB4E4A3E52E903EC
-:10C0D000423E4AC0C953F1DBAD961D385F45BCBE38
-:10C0E000CE079326E09CE6D65434A209EB07185FEE
-:10C0F000A51497E7FBBE01DFF9C700AFC17D75004E
-:10C10000101281EFDBAF55B2F2F2D0A322CA89C977
-:10C1100032FE0CDA05324BC7707D7B408D6F36CB1B
-:10C1200072BBD9CDE5F929271510F782DEAAC473B1
-:10C13000DB0B7D7B902FFF58FC5EC609F8DC668C1C
-:10C140005611EDEF1D88874D284FB06E25DCCF6B63
-:10C150001AFBBED7EDDAE7CC45B97A92F13701FE8A
-:10C1600046BE4A3EE70B32EE51E479DD894B46C4C8
-:10C17000BBFEB0B63C77B99D2FE07EFA09A9D7B2D5
-:10C1800073F7C9F2DEBE97327AF9F766333A7D4625
-:10C19000F67A5DC0979FC13E0E005F5EF17A533321
-:10C1A00061FC159F37352B2D2EFF1D7B53D9B8FE13
-:10C1B000F255D99BA03E847C0FE7B81C769B90CEAD
-:10C1C0001BF672B953D6FB30BA2E1BE5A7C6306EEC
-:10C1D000B443FBF4C8850CC4753543ABB351FEA61C
-:10C1E000DAE7CB2E7E1FEDDDDBB65ECCE6FCA007EA
-:10C1F00079DA2ADB31FF8EA811E9BFB59B30FE1D2D
-:10C200003EF27E07CAEFE548AA15EDDE67C7520386
-:10C21000A8EFAF1C4F09E960AA36E477D0679F19F1
-:10C22000C6EE66F871486F45FFCC7FFCD367501EA1
-:10C23000FD47401A61DEAD914727D0BEB545965EF9
-:10C2400012B07CE5FB9587F6EE9FB3F32AF54F7BA2
-:10C250004C22EACFCB02D7135BC387199EDD7AFD50
-:10C260006A95D786E7FCAF85A8CFFCBFBABA10F5B0
-:10C2700098FFE8D585D8EE7F3DB5530B9FBCEFD630
-:10C2800033BA2AF6B1E4AC2025F6EB95F9A3A4F76E
-:10C29000C9FA52A05FCDE81ABB5E8CB7D754E8BC90
-:10C2A000D8BFE6DDDAEC2D89E362423D7E5F305A8D
-:10C2B0009BBA39812F1F721B643D04520DFA679D92
-:10C2C0004CC375058FC7F455581702328EA0371826
-:10C2D000DE26A2B010FD7782CE3DE98F090CCF0497
-:10C2E0005AF5A10A686F8EE9247315F3EF038938B4
-:10C2F0008310EFF2B978DFF7E6DA7789CCDE931EA8
-:10C30000AC3F5411427B4F02A691F2041CB42EA6FE
-:10C310008BA600DF344552A28887D6C5840BAC2E8D
-:10C32000E3A30FADAF3D826E27E0A38B893807F002
-:10C33000D045355E22E9B85F052FBD87B80AF06C9D
-:10C340004B57D480F60A7092AAFFC6A61F5F423FE1
-:10C350006C63B7FA7B494CD0AD84739680BA433294
-:10C36000F4C7F698503E149C89F735A821EFFB5D81
-:10C37000FCBE1439EA8DE9D83DF4C65CA672289F4C
-:10C3800095E568D0AA230198BF37B2FA20FAE9BD33
-:10C39000D7D7A622BD7ACFAE223B50DEAD2E5305B5
-:10C3A0008EBBFE6353A32DCE1F93F4878BEBC73850
-:10C3B0001ED0B673CDF2BEBE2F7BB7D6F5C3B07715
-:10C3C000E0576F70E532BFBA99C73DB85F9D6C27E3
-:10C3D00014FDABCCFB847CCF93F5EF25865FC0FFCB
-:10C3E00065FAF70997C8FA4D8F346433BFF8EC9AB1
-:10C3F0006C316DF2FC65825D97659B3CBF82D7FC1A
-:10C400000169C4847E8CA467F2E95F434314EB5E48
-:10C41000CA70B67FBD2184EDCA7E626B28EBD768F7
-:10C42000A721338DE33F051FDE6C5F00ED2571BC56
-:10C43000A8E0C29897323F688D6460EDB9337C8F75
-:10C44000B86AF07C66F6BD66319F17F4C008FA47FB
-:10C450006B7F4A09D303325E54F833194F7E1E298D
-:10C460009BF64D71A3E764BE54E46B46925C28765C
-:10C470006A48B6D31D68A71D68A7BF36A21C4C85A5
-:10C48000BBC14EEF73B171848D5FF0AEE0D5F2BBEE
-:10C490006DB21CBDACDC5BEC0D27EEB798C4B6A347
-:10C4A000BF3895FDEC9771CC54ED43323EFC3639E4
-:10C4B0003E2B9FEFFB92E3D80F448E6FE23FA3F633
-:10C4C00039EF753BCF23FF5AF49D3127CADDAF0DFD
-:10C4D0002C6E9DDCEF09D91E833D53DDCF48B15151
-:10C4E000877E8FBF95C7018299E23BCC3F79534F3E
-:10C4F000709EADD70A194EBBEF5A262B838584DB7D
-:10C50000D1074B58DCE6BE97460D128C6FEEA2F3B6
-:10C51000311ED4DCAA3E4F30575A9A18070F160E18
-:10C520009C42B90A1C2C1371FE163C2CC6435A338C
-:10C53000433B317E81719C79F8DD12A703ACD32E89
-:10C540007FBF4B8EEF90241C7074F83C8BF7F8077C
-:10C550002941F93546407FA03E39CDE31D1D11AE7E
-:10C56000173EE936337DF289C0CFE1EFA6A1ED3465
-:10C570008E232E459ECA43399B842724C01379718C
-:10C580003CD1FEC2BB4C1F26E387AC41BE8EBF4DE3
-:10C590001FC278CC48F1428AF576F007F311278A5A
-:10C5A000E24F8AF8BE4888E91549152739701BB74C
-:10C5B000FB9F9FFE77E647360F5192CD7087142B75
-:10C5C000CF8BE38E8DC165CCFE2B3863E3CC532338
-:10C5D00045389F8C33ACF08BF1C3649CD1111E3570
-:10C5E000A05F30094F24E1880AB73A2E3853E07132
-:10C5F000D699116AC578D24C999E77F45B182EF6BD
-:10C600007CB0391BE55CB99FCB0DFCBE2E9FFFC2F1
-:10C6100089E3167E205851DF1E3DDFF5DB225E17D1
-:10C620004D228EEB4A453FE4F2070FA4223D8F4294
-:10C6300049405E5F3F2768C60FFF3E1E37BED38D61
-:10C64000F6ED61396E2C807D4B8FC75F92C7BD269A
-:10C650008F0B829BC1E28E4384F16FB0D0B78CD533
-:10C66000F79592832CEEC3F9F57024D38A78AF1234
-:10C670000EDB0D7AE21F2DA417F32BC15CDF5B4CA0
-:10C680003EF6E918FFC2789697091C1299BD4392AD
-:10C6900061FEA3CA087BA9267C3190B739F2BD158B
-:10C6A000821F8AF917D8CD9A1B40A74A390F5265C5
-:10C6B0002102CEFF98C1B7EB76CCBB0C0BF6ED3860
-:10C6C00046B06737A44FCEC70077B37D2979198A62
-:10C6D00079976FC8CB505CA78AF31BCBC31089DE58
-:10C6E000488DE75FC84FBD2C29B473512741BF73F4
-:10C6F000B187F0EF93F3298F3B35F229FBD0FE3061
-:10C700007DABCEA7ED9AFD1AE3B7EF9A473BEB520C
-:10C71000E64B5E5FE47E67D2FA0B323FCF63FECB1F
-:10C720007F7F95C1EC59E42AB33B57C653488CC56B
-:10C73000EDC6789C3A6260FEFA15F0837213ECD96C
-:10C74000974E4E87131137E3C7C1586D2AF62F96BF
-:10C75000ED65FFD935AB57229FC4047B05DB25F778
-:10C760006B0663420DC70793E874D0A5919F3259B9
-:10C77000B83E4FE6CF46993F1BDD9CEEEEF3DC5F03
-:10C78000F177F1FC815596377F27657AE554711E64
-:10C7900055E2C8F95AF985A171A6675BEEA5F68046
-:10C7A00038757E61B7EC6724EBA18EF0217E6FC9EE
-:10C7B00071DB7A0FD33BB71AB725E80D2F8CEBE965
-:10C7C0000145AFCCE571DC3BDC5676DEACCEF9CE74
-:10C7D0007C123FBF063DC55AAD3CDEE47EF3EA6EF7
-:10C7E0002D2FD829DD5ABF17A55B5B77F016FB9D6F
-:10C7F000BDC57E73B4E44CA35F8EF3D6CEF18966DB
-:10C80000BFFFA379D0E43C67725E3439DF99F2E66A
-:10C810009600B63D4A1F1F8F2275338E3451105932
-:10C8200021F30513CAC98AC53C2FD05F6B0AEDA757
-:10C83000F1FCA842AF020FC75F56DB44201BE83C67
-:10C84000438AD566833C5F594C98FF70C5CCF3038F
-:10C8500044B01636B0FBB316AE02BD1F346BE79979
-:10C860007E5D27E3E929F4C9128F733ACA8B1571EB
-:10C87000B9C63D1E96E394D63061711B228885AB04
-:10C88000D8BA6221DA9B696FF0EF195122ED67FB8C
-:10C89000124B56311C2D96E0FE76CBF9AFAC65B34A
-:10C8A0004A305E97057617F3234F619E84F901564F
-:10C8B000D64F59EFF95ABEDE6E03A198CF0ADCCEEF
-:10C8C000DF57907FB3AAF21B670CD18B9B28CB6FED
-:10C8D000DC81FB7F5B17B51D28E1F782F4B50D5AAB
-:10C8E00059DEE5378BFF61B68FADC3F31DDBACBC02
-:10C8F000CB49F437601FDB8E3918FF369F58FCBBDD
-:10C90000F5880BCB0546E749785CF6B3CEC97EA225
-:10C91000E2678DA1BF98E0772CAFD54DA59796D74C
-:10C920006AC8D56ECAFDE0C0DBDC0F7618ED659DE8
-:10C9300009F7B4B696F3C3A6288FC72AFE6D9514DF
-:10C94000D2E5011D1C0FE9A32960AF1D7D738DA8E1
-:10C95000B71D7DC516165FDA7C48A7D05BEBDE37C6
-:10C96000D5723BD27F7A9CE5270E27E5299FAF350C
-:10C97000B2F62C991F9FAF251C4F55083BD10C4F89
-:10C98000FB6BAB5E2B3EDE02F81FF7B729C8F7AB97
-:10C99000E4435AA2A21BD7B93032DE8765756B8992
-:10C9A0009BC50FDB26FAD07EFAAF5F3DB584C50389
-:10C9B0008C22E2ABE479E778F46CFDC30848905E22
-:10C9C0004B8510F6732C15D87D67B598993F9E65F9
-:10C9D00020FA34AC37707B565D9FE3C63A5993C951
-:10C9E000EC71F56931738B2DEEEF672DEDCA453A89
-:10C9F0007D5B9E48891BE4CE907620BF7DD73C515D
-:10CA0000FB99B3463CF78631759E48C9FB4C952788
-:10CA100052F2B4FEFA2F547965BF30EEC1F88AE3C2
-:10CA2000D8059627F687A9B5A0249E3FF20F4E1889
-:10CA3000197DE5BC11F437E2B8C11E9E3F3A02EB06
-:10CA4000631986F34AB08F7F86F3621981F3E2F7A8
-:10CA5000E33DB35919EDB1B3F244CF22563A806D9C
-:10CA60000AB330EF34C1F24E2FD5AAF3164A5EC294
-:10CA70005EE8FD05D229216FC1EAC9790BBD85FBAE
-:10CA8000A3FED306FB01F8EE3F63627AD619D934D0
-:10CA90001371D997A3BE99569607C8667EA5C20F93
-:10CAA0009725BB3913FD01AFDD8CF902C7F025A333
-:10CAB000C8F44EB4089F3275083123FAFD4807893F
-:10CAC000E139A719E9FAADF1FDF0FFC7F7BF4B7CDB
-:10CAD0007F5E5C2E99FEA8F6EAA4FD589E96CC5B7C
-:10CAE00012F443BF97C789FBCB4B99FCEDF19666D7
-:10CAF0006E4E8CE7D7733F2E6B69B939F17B97C7C0
-:10CB0000C0711F255E2D3DF6F5D4FAF66B2D7D4BD9
-:10CB1000A6C80BF4D7733DA2C4FD27E709EC6F96B6
-:10CB200027C4FB2FBF0D7C0A7EEBF0500AB3E75FF2
-:10CB30001E4B3980F8BBBA7EF3CC74A8579F4B21AB
-:10CB400025DC1EA9F20BCDF53AC99CA1954F908A20
-:10CB500074C0B793F206F53AA6DF6FE60DEA850BCF
-:10CB6000AC2EE3F40D137F482FA148FF5010FD8C2D
-:10CB7000C3EDD43E4C26E71160E222B2084E517F4D
-:10CB800096E595ED9DD42E8ADF9E5FC893E30C1D3C
-:10CB9000E14C3DF279CB1B84E0BBADC979867A8646
-:10CBA000F7ABC993C15A7C8F55AEB3A23D4B8E17DC
-:10CBB000209FA0FD4F8E13CEABE3F7384FC62B61FD
-:10CBC00019DF57CBB84419977CFFBD75EA7C4472D6
-:10CBD0007B97DCDE5B5FDD8FF71758A12368077A50
-:10CBE000EB5DA6F284F95C75FC1DCD6ECC5BE42494
-:10CBF000E62D787E22395FA1E829C7F0D71EBCFF59
-:10CC00003D111E4FF217F0F8A6E3B8F334CA7D7C4D
-:10CC10009FDCDEEE813B8E311C65CF24FC5CC4C4FE
-:10CC2000E35E2CCE50BDE28B13A9483F2FD82BD406
-:10CC30004B67CA77A6A13E5921D45091C5BB6FC698
-:10CC4000BF313EB5FA9DD66504ED7FE3FC51A47B70
-:10CC5000E37A037B87A4D8ABD5EF347978FBFE1D4C
-:10CC6000166C9F4DED6611BFD7BBF0FBF257A218B3
-:10CC7000E9232B91DA2037B13317059497DC19BEDD
-:10CC80009FA17FE46890E3E0EBB97D6D8C34184898
-:10CC9000DA647B77B2F84BE6475F8D38587C3B1BF4
-:10CCA000F3AFB6B8BD701C033B94FE97B343BD759C
-:10CCB0005646CF796087703F590D3C4F987CFF2EC8
-:10CCC000F9FEA7B22B53E951B423BA455C6E684113
-:10CCD000DCFE8AE85FDF11B7C3D630D4F3BF21EEA4
-:10CCE0002DE3ACCC2970D82F657E9FF2FD46F8FB72
-:10CCF00089831FAAFB81C4C1653F4789872B7E5169
-:10CD00009A8C639532DDC3E9FEBF7EBF8CC651F3BA
-:10CD1000FD7296F6FBE50D03147186F27E79C44828
-:10CD20009C8772F0DD1E25DB51BE430D0CE78C3C69
-:10CD3000FBFBBE97E17BC720B5A2F9691F1865769A
-:10CD4000BA1D700DC343914F799C6A80BF376D0F38
-:10CD500053492B0EBA40B6CFB512617AA35D7ED788
-:10CD6000E719E4721D8F13FD5C488C13F9C558AEAA
-:10CD7000F25E30C4ED93E6BBBE0E32CEDE0376B477
-:10CD8000527B14BE27C78D92E3454FCAEF00A78C94
-:10CD90001B49DFEDBDDF9FEAD2733E061650E2CF9E
-:10CDA00005B53C4ED4E4A314E737E9BC6DECDDEFE8
-:10CDB000716AD57A3F9AEAE17667B91CBF7DD1C81E
-:10CDC000F9E1C53B297B4FBF9CF038ED8BC7F9BB20
-:10CDD000FA17ABF9BB7A255EABBC97BF3D1EAFDD42
-:10CDE00083F15AE59DBDF26E9E9010BB8786BD967D
-:10CDF00028E28DC70C0305288FCA7BA3A375DCDE50
-:10CE0000595248A7967C7E55E73C5AC7FAE9A6884E
-:10CE100077FAF23D1A71209FECB7157BA6C4E9A200
-:10CE2000275785D3593D19A7FFA5E2B547EAC8544E
-:10CE3000FBBF5F1BAF4DEA77F116FB9DABD3A0C7DD
-:10CE40004E397E924CDF1E8FA287A75B193FDDDC37
-:10CE50003FE1F95C39EE3522DBB920157F7717CB3E
-:10CE60007F1958FE4BD133C1743EFFDDB29E51CACB
-:10CE70007BE53268D08ED374C9ED730AA595788F9F
-:10CE8000952FA9E3667307D471B379E12C557D7EA4
-:10CE9000F436557FC7E952557B4D6C8EAAFD8E73D3
-:10CEA000D5AAFAE2B13B55FDEFFAC4A5AAFF685C2A
-:10CEB0001D375B724D1D3753F8DB091C9138CE6D61
-:10CEC000FA1B55BFA256F5B98A3BD5E79AD9AD3EB4
-:10CED00097326F49407DBEB2A0FA7C5918D7B7FD92
-:10CEE000F971FDF15A518EEB979971DCEEFA7233BC
-:10CEF000E2183DE631E1FBFF001DADB367003400F1
-:10CF000000000000000000001F8B0800000000006F
-:10CF1000000BE3146060F8510FC1D3F9191836F310
-:10CF200023F8F4C0C79819188E83302303C33E201A
-:10CF3000DE0AC46B80F83D0303C352203D078827F7
-:10CF400003711710BF048AD5B1623787858D81813F
-:10CF50000D884F02CD3AC54CBCFD8A7C08F6215E97
-:10CF60000686B5407C9497BE6130D8F00C41FAD962
-:10CF7000F50C6AD76ED181F73708B38A3330304A5F
-:10CF800020F8FD12A8F26CE20876960C6576950101
-:10CF9000F50300295128158003000000000000005F
-:10CFA0001F8B080000000000000BED7D0978544540
-:10CFB000B670DDEE7B7B49BA3B9D90952574802051
-:10CFC0002A4BCB1201113B2189010306440928D2C7
-:10CFD0006C2184249D01661E3EFDFF6E0842C4D173
-:10CFE000898A1AFC195F83E004079DE0A0139DC0A5
-:10CFF000348B8833E804C70597795F401E204212BE
-:10D00000A338E8F3C9AB73AA6EBAEB763769B7FFFA
-:10D01000F97FFF840F8ABA55F7D4A9B3D5A9537500
-:10D020004F149D9524DD40C825F8A1E5AB0A2124C5
-:10D03000255876489DC3E581C1F6B55E177119097B
-:10D0400079C06BC272BD379DB8AEA0CF47EB8AFCEA
-:10D050001642EEF7DAF1F9E3DE122C1FF59662F9CB
-:10D0600088D78DFD1EF29663F92B6F0D96F77A8B9C
-:10D07000B0BDCEBB0AEB372A0BD2605C425CA6ACDB
-:10D0800064423C2F0F1CB981D6D6678E4F9047D390
-:10D09000FA5FF5449F45DF1B2D17F987D206B9A427
-:10D0A000286B74B09F8AE78D4A5E5F80F3F8581D45
-:10D0B000EB67AA792D3B72BF2C3286E2395646FCCB
-:10D0C00089A564727672C47E8301DE2343D93C89CC
-:10D0D000DDF9DAA0C8F0AE06780F0DE5F825DB27FC
-:10D0E0000F8A0CCF09FD7EE5E4F0D23B0F0F8CDCFC
-:10D0F0006F0CF4AB7372787D7DA60191C71D0FFD97
-:10D1000062E013C589105F8BD19F9DF5FDF9455CE9
-:10D11000F42FC5A763AF79EB0609F9370DE8B4D64C
-:10D12000BEFCCC163A4E7BCB30A7DE41C8672E67DB
-:10D1300082DD1213DF6E8179C4C0B752182706BE94
-:10D14000CD8D916F0BA05F0C7C5B02FD62E05B6597
-:10D150008C7CFBD94F846FF7021EDF836F1B62D478
-:10D16000B75FC5C8B78D31F26D538CFAF6648C7C0D
-:10D170007B2A946FEA73B5DC4124B48B372A253BB4
-:10D18000A09F27B3CD3620EB27C1BF3DDF53EFF67D
-:10D19000C7C8BF5763E4DF11A04F0CFC3B1A23FF45
-:10D1A000DE89917F1FC4A8776DB8CE58E4AFDA86C8
-:10D1B00010FCB93400FEB5D84F5DCDEB7AC03B8989
-:10D1C000908C7039504BCA51940799B8DBD9BA5535
-:10D1D000F0CDA51C425698E87FE9FBBE3C12D0D3A7
-:10D1E000F17D36E2AF9584FE9F039E84E47F732930
-:10D1F00055E8EFD345EC4F74D0FE30C815E5FF6617
-:10D20000EF102CEBB91C6D2ED2A13CF8920D285FCB
-:10D210004F789DD8DEE01D8BE5635C2E3772397A3E
-:10D2200000E4EE0A90C3522E574CEE082971945335
-:10D23000BA76EC89271B1C28576609F09499BCDD47
-:10D24000BBE7CAAD1B28FCCD35BA2BB785C8D913AF
-:10D2500045AA7C51C94C0EF67BA2FC846DC150A43A
-:10D26000B70DE03414EBD47EBED07E0DEEEE7EBD65
-:10D27000A0DF63C55CBE6412081DF7B1D2EE7EE983
-:10D2800012A5CBBD12296DB284F3658AC4F4942A29
-:10D290000AF243E6F4DD9F7796B4D1F76DF6916913
-:10D2A00084964F827EA2FE39B054DFAFA7747653C6
-:10D2B0007A641A494D13E04B5A2585E22B8F752469
-:10D2C000821C3D34CE45242B21FDA19D8EDF677449
-:10D2D0001BC9A265E2F836220D837EB49DD6537831
-:10D2E0007BC650DA4EE13C04EDD6607B2A6F4F736B
-:10D2F000F0F7AF63ED0F7B098EAFF6BB8FF2D94D20
-:10D30000F15B47F1C5E7C5C4057494293BFD21F3E2
-:10D310009F2DE971DE95BC54F1BF2FFB54C6FCA1D3
-:10D32000417CCD832F66CC0FC1EFBEC173B0AEE29E
-:10D3300063BEA212EBFD57F5A69E18D707124EE763
-:10D34000D49903847687EC443FCD71444F7C945F3D
-:10D350000E2A9E91F8F30515E71F54FF5C8C1EDA28
-:10D36000F6BB3574589721D2C1D05BA4C3BADE2274
-:10D370001D0C7D2E4F87299203E147A3873AEE8645
-:10D380002BC571E3AE12C7DD7095386EDCD53FCC8E
-:10D39000B8EBFB89E31A33C571D7678AE31AFB7FC1
-:10D3A000BF7189ECA40F99B9200EF8679E60DF2E3B
-:10D3B00010F7C3A0DF60E7F4C9413B27DB4B88DBF4
-:10D3C00012E42791E9CB39A170EE14EC2A85F37FA2
-:10D3D000381CD7E5E1D83570E66AE16CE37048A8FF
-:10D3E0009D0E8343EED0CEE3B7FCBD802E647CBAA5
-:10D3F000BE92126BE87B4ECDF8B76BC7DF0D760C93
-:10D40000E6A1BBECF80E0D5DE768F1D9C3E110DDD4
-:10D41000E5E841EC1A38B3B5700E713801E9B27025
-:10D420004AB5F3785DE5AB24AC5F941EC382EF751B
-:10D43000E4759E423FE845C5B19DB64B7FB2066E8E
-:10D44000A0FD8F6C91FC465A0FEC8DC7F5E3FCB63E
-:10D45000E958DF778D11D789F3CEC97E23B527939D
-:10D460005E78DB06F6A5EA05BD0C75DDDE8F6D6D19
-:10D47000142F8FB1F5C1EBE8F3CE17F4642B4A6398
-:10D48000A10EE87E8ACB2659C5EA656656ADDAB2AA
-:10D49000EF4E805BDE6C24660AA7EAA525D3AEA317
-:10D4A000F5258715025DAAB6AF36F4A6F5A57EA9C7
-:10D4B00009EA1D79A41CF469CDDEFF6C87F5E8FC50
-:10D4C0006E251BC63F4BD70907B5C747ACADA9337F
-:10D4D000291E15FE5D85F05EC54EC9492D1CC57718
-:10D4E000FBA10CC07787E434527A2F6B8C270ED5C2
-:10D4F000DED1BFA776EB71FECBE9FC0985B784D4FA
-:10D5000017023DAB803830BED3E8374B417D3BEB53
-:10D510003D8CE3A9F5AA1D743CFA7EF5739213A61F
-:10D520005AAD236EC0B3FD2573E9531698E76AC35D
-:10D53000602BCC6FBD01FA2DF1CF7FD1EC003CB751
-:10D54000180A01DFCD5B0C6543817E645EC950C063
-:10D55000EF2F227E0D7A17CC77F935C6AD7AE0A78A
-:10D560002530688635DCCE9EA5EB952364FDAC2086
-:10D57000CCEE13D96F983E2CF8FC257D22CAC1B29F
-:10D58000463D7184DA0D2E1FBEA384F9317BACFEBB
-:10D59000ED59413E2EB77379E57C5C9EC8F92A7738
-:10D5A000E6CC18168ECF83C01723F38FA07C98AEDD
-:10D5B0009B0EF47F1C48BFC7A8FFE440FFC889CF7B
-:10D5C0009FA07E12949BA99F04E593D44F82D24FD3
-:10D5D000FD24E8B795FA49506EA37E123C7F9AFA73
-:10D5E000E7503652FF1C9E3F43FD7228777A7DF844
-:10D5F000FC396F1D964DDE7A2C9FF73660B9DBEB58
-:10D60000C77E2F7A1BB16CF636E1F397BDCD58B6C5
-:10D61000780358EE053ED332E06DC572BFF7189619
-:10D6200007BD6DF8DE21EF192C7FC9E96E9B4072B2
-:10D63000652A2F3617B1039B928A5DB9E0AF249516
-:10D64000B07AEA1DBE5C03ADA7BA699DD2B1776519
-:10D6500020D748EBBD6B587BE63D24CF44EB993E89
-:10D66000D63EE097AE3C33AD0FA867ED8337FBF2B3
-:10D67000E2687DB09FB55FB53390174FEB5735B17A
-:10D68000F6E12D649285D68707587DE411D7242BC7
-:10D69000AD8F6C65F59C0F7D936CB49ED3C6DE1F79
-:10D6A0007F2E302981D6C777B2F6895F937C3BAD58
-:10D6B0004F2412D6F32CB9F989B49E6767F5C2BE20
-:10D6C000F3654784F57DAFD2B6104CDACF7539B922
-:10D6D00032F513F61ADA5680C95DAFBB21571E47E3
-:10D6E000E9A79045D0BE4957C4EA06B212DA7FAB2B
-:10D6F0009B8EF5FD8A03DBF7E8E6B0BAC181ED7FCA
-:10D70000D52DC4FA41C585EDC77595AC6E7061FB2A
-:10D7100067BA9FE378871437B62BFAFFCDEA06374E
-:10D72000B63F2CAFCFCDA7FD2BF56E8F8ECA75AD52
-:10D73000E42E2703415E9BD2C11EAEE37EEB2C9DFF
-:10D7400003E57E5D8601F56CEF7FE53C857A063F5B
-:10D75000C9502F7B1AFC5E0A6715C251281C7DCF69
-:10D7600070267E33568033F19B7215CE6A84638EA9
-:10D770000DCEDE6FC68BF87C53A1C2D9A0A3F6BE36
-:10D78000D61ADBBC265E9A20E273A95285F308E222
-:10D7900093181B3E01E55A014E4059A2C2D98C7024
-:10D7A0005262C3C7651827C0711996AA70B6239C28
-:10D7B0008CD8E0040CD789F81896A9709E43FAF427
-:10D7C0008B6D5E2EE3F5223EC62A15CE1F109FAC50
-:10D7D000D8E0ECB78AF4D96FEDA64F00E164C73604
-:10D7E000AF3C9B489F3C5B377D5E433857C606671E
-:10D7F000BF4DA4CF7E5B377DDE4438C3629B575E4E
-:10D8000082489FBC846EFA7C8070AE890D9F83290C
-:10D81000227D0EA674D3E724C219131B3EF9A92258
-:10D820007DF253BBE9731EE18C8B0DCEC154913E4A
-:10D830000753BBE9F305C2B93EB679E5A789F4C938
-:10D840004FEBA6CF258493EB6E447C0885638D0E49
-:10D85000E7503F913E87FA75D3C7A407380514CE29
-:10D86000C09EE114668AF429CCECA64FA21EF46295
-:10D87000726C700E658AF43994D94D9FDE88CFD4CE
-:10D88000D8E655D85FA44F617F461F8FB173921DB4
-:10D89000FCC644E2DC4A5F9994FCB383B0EE2816E0
-:10D8A000E204B047A4C036804FD756F44B65A7EAD0
-:10D8B000073909F8B9C5368713E2017AD5DF21ADFA
-:10D8C000B81FB1EC4C14E24D2FE9F38603BE56EAC3
-:10D8D0001586FA3D0963E3047F2BD19524D47B158B
-:10D8E000F516FAA7940C10DAD34AAF12DA33DC2318
-:10D8F000857A9FF2F142FF7E357942BDFFAA294227
-:10D90000FF2CDF0CA13EB06E8ED03FBB7E81D07E5F
-:10D91000454385D07EA57FB950BFBAF15F85FEC370
-:10D920009AD608ED239A3708EDD7041E16EAA30EFF
-:10D930003F21F41FD3BA5568BFF6D83342FBB8B6BF
-:10D94000E785FA75675E16FA5FDFB95FA8DF70F1E9
-:10D95000CF42FF5CF237A13EC9F481D0BFC0FE9137
-:10D96000D07E63FA271A3F568C5FD4E612E6CF6664
-:10D9700018D09F0D580D5837EC35B3FD0DD49321B9
-:10D980000E518C75C3FE858E6488070000EA4FE453
-:10D99000F62EBF02E255BF18EFBE02E2B8BF30B8A4
-:10D9A00047D823F841EDB2FB1E3DC6135B25920E0E
-:10D9B000A54307659C9EC7138C4C7ED767E53CE565
-:10D9C0000BD183BA7ED4BFA0F5F57A8AC798A0FEA2
-:10D9D000ACEF57963E3F649C75FD0CA55B87B2E7A4
-:10D9E0000B2D305EC97D309EC7D03918F0D28E63C2
-:10D9F0001C305618C794598EE36C84715282E31818
-:10DA000033CB35E3984AB7F2E77C9CC7406FA28DD1
-:10DA1000B37EC078713E991538CE16CD38EB332BD6
-:10DA200034E3C4B1F9D0E77C9CA72E378E71E004B3
-:10DA3000713EFD2B719CE7B4F3E95FA919C782E33E
-:10DA4000C0731887F4A5BB9834CA67636719CAC145
-:10DA50009FCC182733F4A9F80DD4C90766920DE3BB
-:10DA600038E8B8B41F199244859A907FD127217F56
-:10DA7000BE88A3FC0F89A705F7E33EDCD72FE62875
-:10DA8000123FC588EE93AAB96C2EDA393D738583AF
-:10DA900096CD07063D02E36CB43AB369BDBD7992F9
-:10DAA000616104795A5CAF9C6A0B91F3EEFD591EDB
-:10DAB000195243C75F1167477CD4BA5A26E9C4E7B5
-:10DAC00027E8BE8BD0FDC987749F42E87EE5238599
-:10DAD000ED33FF9DEECFA0DE46F767D04EC86A7CDF
-:10DAE000EF048F339FF8A5E4077A7F71D7CF145CDA
-:10DAF000277CE4ADF4548826B09F79ABE2291382E9
-:10DB0000F8CDF7F512EAD41CF7D1A5E3BE16E3076A
-:10DB10009D2F19FD5B81AE757D284D79BF0184BCB9
-:10DB2000BB77EA21C986D53EBAB184CCAC995E9068
-:10DB3000865A24F55B4EF19CB1FB1A85BE41DA95FD
-:10DB4000B63B9D96205CE2524E007D4CF40FC0B96E
-:10DB5000A588D643C6BFB544ACCF2272B04EF97D7E
-:10DB6000523F80B0F83F1FD7E15280AF25748E1925
-:10DB700094D5B3A01C09CD2C5E536A67EFAAF87840
-:10DB8000162A2480FB6B5F0AC4B1892F19FBCD5183
-:10DB9000F7C91AFC4A1593AB84D2B574BE1EE9AA24
-:10DBA000C5F7FDBDF12EDD705AD63DA24068B627FF
-:10DBB000FC67BBC57652CEC653E9AACACB29CEDFD5
-:10DBC00013C07F5A9E06FE53BC4F72FE07E598F1C4
-:10DBD000DF63744F03FE776ED213E417E7FB6D9C8F
-:10DBE000EF8BEB45BEDF06E771B4FF6D2BB358BC7E
-:10DBF000A9A197C05F3A71910EF50F1550B31A861F
-:10DC0000FFDFB91CCCA9DBF50AB0F7F672CDFC3802
-:10DC10001FEEE47C98ABA1C76D9C6F7339DF961043
-:10DC2000DFBD1918BFF02B10D79B5D2E11B0179ECA
-:10DC3000BB55BEB5097C73AB7CD3E07B27E7DB9D8E
-:10DC40007731BE69F16EE37C6B6BF84C2103C2F156
-:10DC5000D6E2396F95665E3E2DDFEAB95CDA0DE0FB
-:10DC60004F4D77E5AE3819D2FF96A2C92B4E86D814
-:10DC7000855B4BA60BF559A5B385FEB3DDF385F6A1
-:10DC8000DBCB970AED736B7E26D4E7ADBA4BE83F4A
-:10DC9000DFB75A685F58779FD0BEB8FE21A1BEA4F7
-:10DCA0006193D07FA97F8BD0BEAC7187D05ED5B495
-:10DCB0004BA87B9A5F12FAEBF65E7933C8D791B71F
-:10DCC000F504E27D179CA731CE78C1A938A1CF49D0
-:10DCD000AF03E5F89477089667BC4E94F3B3DEB1D2
-:10DCE0005856834C8E033B7BC002F1534F1CB5FB4F
-:10DCF00089741D97C7ADA99B00EB0D6D1F4FC8BF61
-:10DD0000CA37ACF1F5A55A00716F4AFFE206030964
-:10DD10008C2254BA7B77CB73A73EA4BDAD87F606A1
-:10DD200099047A85B717B7457EDE21750ECE80B887
-:10DD3000EC7B46B23D24DE187EDE42FA805F11ADF8
-:10DD4000FD9C8E94879EF76C95D939CF117DDE5658
-:10DD500099E2556960FA5FF97C461EB1413D30B8E1
-:10DD6000C67299F19A283269C0E78182DE2F69B8BC
-:10DD70003AA8E704C661F674A97F94F07C59E3756C
-:10DD8000C27B6F48EE2D80C7B97D7A5CAF49E04019
-:10DD9000E62DC3003FD75619D6D1E614F4BB5ABDC1
-:10DDA000AE15271542DEF41661F996B704CB77BCA1
-:10DDB000A5581EF3BAB17CDF5B8EE587DE1A2CFF17
-:10DDC000DDBB0ACB36AF0FCB13DE3A2C4F7AEBB16B
-:10DDD0003CE56DC0F28CD78FE5596F2396E7BC4DBB
-:10DDE00058B67B9BB154ED674FF27786AFAF674172
-:10DDF0000E8DE1727670EDBC35757D837276582E8E
-:10DE0000433953E95BDC60E4F2902AC8C35F611DCB
-:10DE10004E0179E9A1BD41E17218EDFDC8ED206F19
-:10DE2000BD7F047923640DCA8105E4EE7BC81B81A4
-:10DE300053841490A73E1A7912E550952355CFDFED
-:10DE4000904ACE817CA9726591993FA4CAD5FDE024
-:10DE50002746F0B77A2B125FFF987F4402B93A2029
-:10DE6000D9727E5E417C2EAC77F1B16B29B856E851
-:10DE700027FB87C03AD235E4ABC110DFEF3A4685C5
-:10DE8000202BFAFCB4F2129DEE2EDC3F94F929F31C
-:10DE90007B85B79BE3185DCD3A524446C2F972CEFA
-:10DEA0003137E567DC9FAE1E09FB66FA5C26490048
-:10DEB000C7EF9C1EE1BC800C2248E79EE8ABF63F12
-:10DEC000F5C47FE6C0B9BF05F49CCE3DEE80BE86AA
-:10DED000E9EF53CE5B42CE973C46673AC4C13BB3B1
-:10DEE0000D76E63F4C12E94826E1F9814AC703D98D
-:10DEF0005F0C86F399FBA81C827E750D1A9C402E40
-:10DF0000231F3DD9FB9EE8B900E61B133D0D04CE4F
-:10DF1000B9283DB7C27DC758E9D9939DECC93E9E4B
-:10DF2000D8C0E87C84FBA7D1E8AC9E8769F1B845EE
-:10DF300091391FB81C933B34F42F15E8DFD7EAC0A2
-:10DF4000FE07F77E9009E7785DBBAF48204343DFCB
-:10DF50002F60E73DDDEFE70B7A20FDE9EF99B03F59
-:10DF60003EF8C2BB58AE254C0F375A4AE62A6382A8
-:10DF7000F062BD47106D5E1E4512E7D5837E76A424
-:10DF8000AAFAD99A09F2B49BDB81B0F9F5209FEA8D
-:10DF9000FC0EC0FC289CA920D3741EF972C95DC276
-:10DFA000FC46A7E0BC7B9A9F27C140A411143FAB5D
-:10DFB000C14012A83C2AEEB50AEEEB9C6D3E885398
-:10DFC000EC8D77D65296786C67DF0838E03D319E4D
-:10DFD000B1ACD15C23FA4F8935A2FF945113EA3FCB
-:10DFE000751D7ECAE6A6F82D4FD7D79CEC05EB9C95
-:10DFF0008BAF736C5D55F1AB6ACAAAB10870C47A75
-:10E0000057BD54C4EEE13812664638EF53CBE5E90C
-:10E01000061CE76CE3C00418F7ACD754C3D6577B93
-:10E020000D1B37BD26747DAD5C155F73725410BF38
-:10E0300068707F68FCA844908F4CB02ED2B681D116
-:10E04000FB47E5A7FCB901CFD55B942FC07F370F05
-:10E0500051FD7719EB2A5C4F93DE671C01CF770ADD
-:10E06000E3D1F71CEAD938BC175D6E64724AE5A7A4
-:10E070001ECEBB08DF1F9890CF6E0A3181C2EB9095
-:10E080002D7520577E85E9B387CB6995A9CDE076BC
-:10E0900020B95B41AE178C55E5DC31EB036AA73F35
-:10E0A000FE8B82F7CCC8D7147A4EF0AAC3225262F4
-:10E0B00083A0EA82DDCB8A61DDFEF8C59BF83EBD18
-:10E0C0003E07E67D9EE88AC02E9D276FDA4685E8EA
-:10E0D000EB6985C5B1481DDBE7F8E81F98DFE27AF8
-:10E0E00071DFB3A441AC979119A9606FCB362AC4F4
-:10E0F0004F715F0AFB2675DED4FEBEABD811B92581
-:10E10000A4661DECD31F5358BC67819DC87DA8BD74
-:10E11000AEFAC3AF7320EED3AE307F573D0F5F9A98
-:10E12000C4F6831533FD0617EDFFD1EE51B7518BC1
-:10E130004BDFF7AF43FF673A716E27E1745F5827F3
-:10E14000E2D713FE5A7C553F28EC5C9EE391DC2815
-:10E1500045BC2FF535B773AA7E2419EC42DC274D58
-:10E160005357E540E172E057DC56430AE33BF05178
-:10E17000923B0DEE907E8660BF24C398E8FD8CD064
-:10E180004F8FFDD258BFCE42DC1F132A4F4383FD71
-:10E19000CC41787DD9B862BFAA3F3CFBA28FCA4B65
-:10E1A000C5EF1EB511BA6E7E2CD7A73AE9F3CAEDBA
-:10E1B000F7DA5CB43C23FB6CC0CF8FFDFA88F77DA7
-:10E1C0006F31A8F470592488A771F924753E8C53D7
-:10E1D0007CB15DB1E33942A33160A4F259BD7B69E2
-:10E1E00031198EF5E3ACBEFE533DD49B457E55FC04
-:10E1F000E6D15407BB27C4E24924807E6EF5B6FF02
-:10E200002884F5C2433A51CEB4EFC1F8179350AF0A
-:10E21000E71B12C2DBF162702ABCCF7E3CBBEFFF72
-:10E22000546F8372F269D0238F464ECAB9DF0AF465
-:10E2300082FD7EBEC19A8CF6FE5A722DE8BB4A174B
-:10E24000E267FE6BED8EC7871FA7789DDBF6179BF5
-:10E250003434D44E3079EB6A5AF86F265D747BD231
-:10E260004EE531D44FA280F13D4733F7BB5B58599F
-:10E27000A9046C701FA7728BE2A492482A9FD51341
-:10E28000B89F40DE33FA213EBAECD957DE194FE988
-:10E29000BF6C97925CCCA663915283FCF1D0BFAB6C
-:10E2A0004606F951F1FB570C8E61ECF93D4941BE30
-:10E2B0002CDBB5CF408685D37152D33E439B2502DC
-:10E2C0007F9A8E17C27A5BBBE31F06882B7EBC57F2
-:10E2D000226959E1EF976F7905D73DA013F293F3C7
-:10E2E000AB9B7F617C0B4C7B7934F6B3833DEC892F
-:10E2F0006FD9B09F4B41F97EEE65B8C7F4BED10926
-:10E3000074287F6E850DE6735AAE6172FEEB7B5307
-:10E3100041DFCB155FAA1D4BF6BCFCC99FA3FC2DAA
-:10E3200039FAF354F41F882B4387B6D99701F35C6D
-:10E33000BCF9569C671971A31C96FF5A5F02F74CF3
-:10E340002FC8A46857043DF98B81ED5F4E6FA5CCB3
-:10E35000A5F33C0DF8817D7B53EFDF8E71F39FE1D8
-:10E360003DB89FF339D39510EB174C8C5F5B0C3A9B
-:10E37000351E6A12E477DBFA56E0D3D97EAE343824
-:10E38000F7A074F071BA4997285CFDD18234C62792
-:10E39000E29073F87BD4DE4F82E7D0BF5571998746
-:10E3A0000BEF71FBC8C65FC9C7A778C7C1FA753A3A
-:10E3B00035B2FFF70F3E3FFAD34A42E42C44DF99CF
-:10E3C000FE6FBB8FE9BBAAFFFEE945D0FEF95B4CAF
-:10E3D0008FE03D582F285E81346CDF375342FB407D
-:10E3E000F7D991F47C9BC2F55C6CA73B1C5CFF5594
-:10E3F00039A1F8CB5242A8BCD07192900FB83F2EF1
-:10E40000DB48DF0FF1CB3C302EF633049F87AC1B8B
-:10E410004BB85D38A4B10764734A4C7E74A5E27FA3
-:10E42000FA09D0DFF78C4E9F03F4572981F97FB2A8
-:10E43000F3C03B73A89C7FD2A4EAAD6857B57A5B62
-:10E44000FEFC1812496F3FB1D07D5724BDA5CF23E4
-:10E45000EAADA50DE5F9FF965D55E9D7AEA11FD848
-:10E46000C7971DD1E9A8B58F1B0C8E88F691FEBC0D
-:10E470004572C2E550953F55EE2A7E5BD51FEC50A4
-:10E48000B77CAAF2D72D9FAAFC69E72BD24FDBFEFF
-:10E4900007D06F8AD7EDA64DD3C07F3675128CC3D7
-:10E4A000E7CED4E33D4DD3E784DDD3B8231EEBB3F1
-:10E4B000F46DBF079FF083AA59C3609DBF9DF814F8
-:10E4C000766E5FAFA01FFBF5A54B13E87CE670FAF4
-:10E4D000DE4EC93D95F2A35496027114CFD932F1A4
-:10E4E0002524413C59222742F0B8BD5CACC3CFC4BF
-:10E4F000D4209C9EFA7F5BBFFBBB9647295F4F648D
-:10E5000013F2372871FF411DEB10799ADEC2CE312C
-:10E510003CA325FF00D4C336B924641FE13132FB8C
-:10E520007334FF963140BFDC59C312989C0FC6FD6F
-:10E53000A287DBB12E9F2301EC7B57CB40DC177603
-:10E540001D5E687547B06707B89CBDC2CF613A2CA5
-:10E5500052BD9ECA7D07E944BFC66731478CCBCD0B
-:10E5600031AA769AF38DFEE8E9F8A55C0E67D357D9
-:10E57000134686F06DE6D48F655B381FE0E744C82C
-:10E58000BEE2FBD217E41AE87BC0DC565812217EAB
-:10E5900053C9E93771FF970658F7F25B7265A063BC
-:10E5A000BE452FC4431619B9BE0E254301AF89FBE2
-:10E5B000973E3086CAB1E7B0DE69A6F3F3B47C6A51
-:10E5C0007047D8DF69E909F0C1BFDC6A64FEF2DB9D
-:10E5D0004AC962A0EBDBB7B2F3DEBF199C5591F0DC
-:10E5E0004C37337F733629B9305AFAE9D1377796E9
-:10E5F000359047E9D16561F7B5C3E58FE97D975D52
-:10E60000F2AF96400EF5AC9ECCEE371712F703131F
-:10E6100024D4F71B42ED576EF3F467E13E4D758B42
-:10E6200064D7D1F66AB9CD0072EC69DE2583DF7E4E
-:10E630009383B8707F2DD70C9B1912FFA2CB1ED2EB
-:10E64000EBC05773E6027D3F9B692480976BE8A778
-:10E650003658FF3F6B19857A106D5EAF7BC9B47C6D
-:10E6600005E0307BA69587C2E478A17EEB24D21723
-:10E67000CE81271ADB563823F02FDFC4E42C66FB4B
-:10E6800066FAFFCCBE4DA0F68DC9B5126ADF2CA686
-:10E6900030FB9616C9BE2D5FED4803B958BE672002
-:10E6A0007EBFB5FCB5C52991ECDBAB7CDFFB1ABFA7
-:10E6B00007DED197DAB71121F6AD2FB56F11E2E47D
-:10E6C0005FC46ADF4CFF33FAF72AD8B708F3359BEB
-:10E6D00044FB56D4B21AED5B515FBD705F8998A8B8
-:10E6E0007D8BBF9C7D9BFFE8AD58579CF111E407E3
-:10E6F000E80AF6ED356EE7601CB0733798587C3346
-:10E70000563BD72F563BF73F4467D5CE2DEF27A179
-:10E71000FF122E87CCCE2DCF62766EF91E66E7965D
-:10E7200067333BA7B56F7961F68DBD5F3D84BE8FC2
-:10E73000FBC7ACC7EF80FB84A58AD344FB173BD44F
-:10E74000EF276AC684DABB1B4C32D239CCDE393FA4
-:10E75000C5EF607AB2777F057B978D766C10E89174
-:10E76000563EA60C8A17EEB3BDFDE5A9DFFE0EF4FA
-:10E77000E5753DDE177A57C7F6477BBF3C350AF48F
-:10E78000EE2113B3BF4B4C8C9FED5E1FDAD3494390
-:10E7900099BE57DDC3E857BD5B62F35DA9F73B60E7
-:10E7A0001DF8EA22EE9FE7EE61FBE759C6D69478A2
-:10E7B000B897F42F0A61DF7D90E2F921F2507AB127
-:10E7C00002E380CFC7D9B6C2FEB2542626F063E773
-:10E7D0001D9EF231F8AFF32ED6A1DF3B0F9EC33959
-:10E7E00009BF27A1DEA398D3BCEB953E24FC7EC4D1
-:10E7F0004423E3C3C415927F4B16DC4710DBE76963
-:10E80000FCFA757C9ED49F45BA90BFEA23C6EFD62A
-:10E8100069E9E164F3AF5AA917E9512345A407E573
-:10E8200068F1FCD4E0FCE7BED0B6AE0FB42F957013
-:10E830003FA5D2433B4F953EEA7E651ED7114FCB95
-:10E840002E05F8A59DBF4ABFB079ABF4D4CCBF4E1E
-:10E85000B51F579361A06FEFEADC0F8C01F9F83315
-:10E86000A503C5EBB6D9D969A1F6F8416E97A6BA4A
-:10E870008FE7A73A806EECBBC439E5BB5E49A5F3D0
-:10E88000B9D9953512BE1FBEF52B831BE20B07CC01
-:10E890009D68DF54F9FA84CB7B80C379BBB73D1FF9
-:10E8A000D79166C98E7A13D0D82F7E7FCC730FD3C1
-:10E8B000AB03D23FD6F5198D7485658014AAEB1091
-:10E8C000F081FE776A0BE38307F840FF3B8D741EEF
-:10E8D000023A57274BCE00F46FDE752FC8CDAB66DA
-:10E8E000FA1CF4B75C72B2EFCB882523F5B2F2299B
-:10E8F00047924F0C4EE404D7C579D02F29DCEF980E
-:10E90000686C7D1BF09848F5610B09F74354BE0F06
-:10E91000A17F2E45BAF7D3831C7FCCE5F355A0B772
-:10E9200005E8DA69007FC61360EB87DAEE911DF91E
-:10E93000481F95DECD747D18CDE8AD8B40CF9BD5BB
-:10E940003AA7A7A74552E0FDC974FFDA4B82D3ADC1
-:10E950002F0FA9720CDFC369E901F1808C10BD078C
-:10E96000FB147A3E59DD7C14E932652575AF42E827
-:10E970000E76EB72F489A617D5CD3F8C5E7CA2D1C2
-:10E980008BBDE6CEBF8C80F8D71E09ED0369491414
-:10E99000F6FBF166E6671C30BB517E3B5F53F0FE31
-:10E9A000B9D68E7CCDE51EF617A1DFFD4D8289809C
-:10E9B0009DB39BC9472A1E03981C85DAEF57CD6E7D
-:10E9C000E45734F8717C1D8EE63FA9F51B613CB815
-:10E9D0008FE810C70BF32F78FCA7A779A5F171BFBB
-:10E9E000EBBCBACF3349AB81B0F8FF0A63C8B9D4E6
-:10E9F0006DFC5CA03B4E16EC67375DA61FC45F0242
-:10EA000074DEAFEE7C0AE3BFE79F393E0DE477D9B1
-:10EA10001FF5C444F9DCBED34A02ECDE8501D6D929
-:10EA20008ADDFA88E72884D4B2EF1C7F6745FB5261
-:10EA3000F1BCD15F4CDFAF78F1A3E110B76A5FC3DF
-:10EA4000EC8CEF192E1FBEB6E170BE5E21B3736170
-:10EA50002DBCEBB8BC9C7B29BE14ECA4D4C8BE5F13
-:10EA6000AD689AA51843F6E923CD0A8E4BFBE1BDAC
-:10EA700065DF0E09E3E5E1F8AD66F07630FB57D1CE
-:10EA8000ACF8E13BD88AC62DB8BFF5347E6A00BF2A
-:10EA90006ED2EF9E65DFD736EBC5F861A33E60C44A
-:10EAA00038A7FEB87138D35B49884755A15E563701
-:10EAB000F13899267EB4EC777B5EF451D22CFBFDC5
-:10EAC0006F6C606FCEB66EB7617CAE91C5DF648B44
-:10EAD0001C393ED7535CAEE93E1E979B7A9A0C0FC9
-:10EAE0008FCB9D85FF503D9C6FE6FAAAC6351B7BF8
-:10EAF000C5747EBEECD90B4FC279D2B9E73F79120B
-:10EB0000F0AFFCE6B327EF867389BD663BAC7F9E12
-:10EB100067DEC6F8BBFADEDD5CCEDB77FCE6E92714
-:10EB2000A81EB6BF67C47B5BED7B4E67C2F78CED5A
-:10EB3000BBBE4C85F8E6CA3D05B89F59F9C2A4B4DE
-:10EB4000CBDD3F01F9F4C7707EA2E5C781DD7A0213
-:10EB5000DF739E3F6644FFA33BCEDA54C5E2D70E77
-:10EB60001E5FDD19F9BC4A8D0756EFBEE5E6EB6185
-:10EB70001DDCAD381DF89CC7077B8AABBE45F93A52
-:10EB80002206FEEDE4F1F3A6A911E3AAE7E13F9422
-:10EB90004F9BCC625CF5C2EEC5FFF604B4EDEE15FA
-:10EBA00035AE1A88816EEA795899D9B5CD0CFAF14B
-:10EBB000FC6F318E0D7CA33E39697FF64226C4235B
-:10EBC000CE289D77E23DE53D46BC6754B1E75DD474
-:10EBD00097F6178EE23913E1E751EDA4FB879D1BF1
-:10EBE000F0BD8E679B95C56339FD215EEBB0E17387
-:10EBF0001E976572ACC66BA3C569DF37B3FB50EADD
-:10EC0000F95CD5B60F0C4413FF96C602BF8E0BE716
-:10EC10008AEABCB5F0EC40876B43CF1FA2C5C3B9ED
-:10EC20005D0DE3173B7768DFC2CF23BACF1908E940
-:10EC30003B12CEC7D9B9B9C72FBD1B89BFEAF9C3EB
-:10EC4000DB5AFDF4C776EED033DEDF8D2EAF9AD9D6
-:10EC5000FE56A5CFB9AF23DBE94EAEEF749DE93088
-:10EC6000E3B9315B67E6F175A69AD28D7DF7C6F000
-:10EC70003DC7F781E79ED1FB61BFBCAEE900DA5B1F
-:10EC8000AD9E571316FFD28E27C531FFA0BA79DF8C
-:10EC900070B047E7F6BF84F257BDF3B8C147E11C37
-:10ECA0006AFCBDA16D6850DEC18EFB43ECF8B9E78C
-:10ECB000F60D67E72291F3B4D8387C4F8B08DFB3A9
-:10ECC000F35301FE325F93C16EE9799CB3B26B16C8
-:10ECD000CCF76CAB42E03EFBD9267D913FC2B89F9A
-:10ECE000C13A362648A77556F61D9F3EC9807EE676
-:10ECF0004AEBD863F0FDF84AABC101FBEDDAD5EC85
-:10ED00005E65EDFF72A6035F6A136FC373A37A0D8E
-:10ED10001DEDC9F65CD887DBF34B46835869ED419E
-:10ED2000A24B27E0BDD25A94E6B0405E2FE6A71072
-:10ED3000D989DF19EA6D8545300FBD5D6737475CBE
-:10ED40005F193CC5C2F2662876F1BBBFEF9007831E
-:10ED5000403E8E6F9D07A3539307A3FCC6FFD7F2D7
-:10ED600060F8609C9F401E8C00C677D43C18C93F59
-:10ED7000721E0C882F8D0EC983D1A9C983C1F9F8E1
-:10ED8000CF3C18FFCC8301A59A07E39D0D65059044
-:10ED9000A742CD83716683A700F252A87930BEDA0C
-:10EDA000B08AD5791E0CCBFDAB0B42F36064DEBF9D
-:10EDB00001DBD53C18CEFB1F2908CD839177FFE6F8
-:10EDC00082D03C1833EFDF5E109A07A3ECFEE70A0F
-:10EDD000843C186BFF500079305E8F77B7C6A5442E
-:10EDE000CF83D11CE788290F0685F31EC2899207BD
-:10EDF000430B275A1E0C0AE744DC98E87930C2F02E
-:10EE000089920783C2F904E144C98311864F943C77
-:10EE10001814CEE738AF287930B470A2E5C1A070DD
-:10EE2000FE0BE144C983A185132D0F068563884F2E
-:10EE3000899E07230C9F287930289C048413250F72
-:10EE400046183E51F2605038E908274A1E0C2D9CA6
-:10EE5000687930289C2C8413250F86164EB43C18F4
-:10EE600014CE55F163A2E7C108C3274A1E0C0A67F6
-:10EE700014E213250F46183E51F260503813104E1D
-:10EE8000943C185A38D1F26050380538AF287930A0
-:10EE9000B470A2E5C1A070A6213E51F26084E113D6
-:10EEA000250F0685330BF1899207230C9F287930B3
-:10EEB000281C37E213250F86164EB43C1814CE5288
-:10EEC0008413250F86164EB43C1814CE7284132575
-:10EED0000F46183E51F260503877239C287930C293
-:10EEE000F0F9AE7930CC8141D240CC8381F938BB86
-:10EEF000F360247FEB3C18BF027CFF9907E39F7906
-:10EF0000307E8C3C18B75ADD7F8FC77DE377CB838B
-:10EF100071265E9337A2873C18B75A4BCE823C7F4E
-:10EF2000DB3C1817E2BF5D1E0C3ACE3F2E374EB4C5
-:10EF30003C183ACBB7CB8341C7912D632E339F2822
-:10EF40007930122C62FE901F2B0FC6B1F8249C4F13
-:10EF5000B43C183FB97C13749B05FBB4E9288AE4E0
-:10EF600027937F62B485C70D7FA8FC1330E99C9F6F
-:10EF700052FE09358F419302EBE1FB9CEFEF70B934
-:10EF8000F880E7A13816350F857F2AC677978A79EA
-:10EF900028A6703ECE768BF23085B0739429F9594D
-:10EFA000FE5AD8AF976BF2500C11CFE98BDD47F3C7
-:10EFB000293832D529CEE328978769A59F1E04F604
-:10EFC000DC3C36721E8A199C1FD3357499C2F936FF
-:10EFD0009D97B7C3A739549E8BCB8FCA40D7698EF4
-:10EFE0003619E3F437A9FC7308FC9BC9E16AF19D6B
-:10EFF000C1F9376332E39F16EFB7807F14EFB7CACA
-:10F000004721FFB4786BF1D4F29F84F23B247F4810
-:10F010002E11F34F4C3289F9270AEC62FE891BD37B
-:10F02000C5FC13931D62FE899B8688F927A63AC505
-:10F03000FC13378F15F34F4C77ADD6E4BFB84F9321
-:10F04000FFE2214DFE8B4D9AFC175B34F92F766859
-:10F05000F25FECD2E4BF784993FF629F505F58F7AC
-:10F060009AD07F71FD51A1BEA4E13DA1FF52FF7175
-:10F07000A17D59E3C7427B55D3A742DDD3FCA5D080
-:10F08000BFA7FC036FF1EFA1DFE1DF431FE3DF4325
-:10F09000BFDF43FE8B772C4BD785E6BF78DFE25985
-:10F0A0000779098E5B1C3CAF40E4FC16DDED51F2A4
-:10F0B0005F04DFFFF6F92F52927FF87C043A2BFBB6
-:10F0C0001EB0B7254F674DF9EEF9086E2D11BFEB55
-:10F0D0009E552A7ED7ADB3B2EFB567BBC5EFBB6F08
-:10F0E0002F17BFEF1E11E796000F6DFE8BDE1697F0
-:10F0F000CE0AF692E72908C077BAD9106F2BC2F270
-:10F1000020E4BFC886785B29968721FF052DFF0C78
-:10F11000F92F687904F25FD0F20DC87F910DF933B1
-:10F120007C3C7F461DCF9F51CFF36734F0FC197EA6
-:10F130009E3FA391E7CF68E2F9339A79FE8C00C233
-:10F1400039E13D8CE5496F2B96A7BCC7B03CE36D18
-:10F15000C3F2ACF70C96E7BC9D58B67B2F62196BD7
-:10F16000FE0C552E3F04BFE10A189FC9B32AA757CA
-:10F170003FF0C8BAD0FC19231ED884721A2D6F46EE
-:10F180000E7CD397123D6F46777B94BC19C1F7A3D1
-:10F19000E7CD481BFDE3E5CD986BF961F266CCAD98
-:10F1A00011F33ACC5B75F9BC1923E24A6E41F9E3DD
-:10F1B000F238D7125BDE0C9F55E2DFE553BA80DFF1
-:10F1C00045E982EB750F79070E5A9F1E02FB89AE47
-:10F1D00021575D36DF83562EA2D39BE57798F32324
-:10F1E000E7CBE889AE6AFFF72B581E87B9966F996F
-:10F1F0002FA3877C0B07B3BF403B196BBE8C9ED6F9
-:10F20000879EE839E347CE97D1935DEDC99EBE391D
-:10F2100085D1B9770F7456BF97AE34B51EC297ED3E
-:10F220002E546D997F0F9F3BD38EF1998E9DFC5E7E
-:10F230009C8B38ECA9EC7B7DF0373B9E4F184EF051
-:10F240003B7E3B7151FEC4F3E7D2CE7DFBE05EC056
-:10F250005A1B71252681B3471CFA81B00FBBC60427
-:10F26000F19AAADD9FBEF1470AD7DCA2C7FB721D47
-:10F27000148756F4FB5C89C0B778F24BDCA7C3193E
-:10F28000DDA55EA1DF756B7E0F0774490D9E3F15EE
-:10F29000E82DB86FEADACCEEB3EAC9D58F4F188DF6
-:10F2A000F7C689DF81FC433F7519C7B38B10670030
-:10F2B000FAEFB4E2FDD525AF2D34C0A070DE1A1AE6
-:10F2C00037E85524C6811ACCB6E1706F2F5DBDBFFB
-:10F2D000E773B5821FBE88C34D2911E3449F2C28D4
-:10F2E0003A0CFEF3227719DEAB482B15E346847FF8
-:10F2F000470FDB32F03365C2EF75FAD97DCFB0EF3F
-:10F30000EA9BB7209E4BFD9AFB4B8D625DA5DB39D6
-:10F310002BBF9762219698E8D676C5E31392BF3D3E
-:10F32000DD8CE922DDCC0E916EF14344BA68E966CA
-:10F33000758A74D1D22D61AC185F53E9A6DEA7FCA3
-:10F34000A1E89664E3F73C82F42A31A5A2C9473CC0
-:10F3500033E400CAB7561FFA5802F01B7E48BF6458
-:10F36000FF6A7CCB6995C16EA533D0445AC4DE8B4D
-:10F37000077D80FCBDC489FAA0FE3E8A78F2219701
-:10F38000FB8FC8255AAE987EF0F802DABA19E46D00
-:10F3900004FB3D1A18AF4A22B89F5388D30EFBA82E
-:10F3A00026AFC9B94881734DE25C940DE799762C7C
-:10F3B0001FE4DF3B770C25B8EF6F0A7C9E0AF70647
-:10F3C0001E1CD9390DE20F9EC5A404D6AF59096C95
-:10F3D0007D5DC64B5B028BCF6C28D111D768F87D61
-:10F3E0004A7ABF44C76BB7BB5EBB01FCD116763F00
-:10F3F00080D83BDFB81DDB47E1F7E119BAFA6B00B3
-:10F400001FDA1FBF2BEE68F9C8B630C40EB7373FFE
-:10F410007225DC6BDDA48BFC3D73818DFFFE1D7EB0
-:10F420003F654430DF42816D0CE6657870001DA7B2
-:10F430007A7A17F25195CBEB38FD0F964D41FC5E71
-:10F4400068911C10AF2BD4DF71D3308ADFB8B76559
-:10F450007EAF97DD5F1FCDFBD79AA9FEA2FDAAFF65
-:10F460001BFC9E95974ECA980F71744D19DE13FCC4
-:10F47000A3ADF030F02BC7D5340AE429BF2511CF56
-:10F48000713D1F12277E9AD52ADE07CCE1F7B673AD
-:10F49000DA881F84E2DA6362FBB836B17E9D66FFCC
-:10F4A00039DFC6F5D4465241EE367EAD9760FDE8B1
-:10F4B000E824CE3514DF8E45BD71FC8ECF09FA8964
-:10F4C0001D5FEB8B22DD8F596E63FCDB642068BF10
-:10F4D000379559F0DEF9FEB28AFEE05F7C7197BB8A
-:10F4E0007FA43865889F96C0BEBB772590B12087E2
-:10F4F0006B2546EFFA8C9208EB962A77AA1CAAF2A3
-:10F50000975116E78E740FF5339B847296573644E5
-:10F510003280FCEC9530FCD5BE86E2759975DB47F0
-:10F52000D6F4017C3CCD9FE17D32538BE48A744F4D
-:10F53000E7619B8DDD6F5CE35B0DF7467E419508CF
-:10F54000EC5486A13E2B127C1FD9887EE95D3607DC
-:10F550007BCFC4F320C9F519709FA2BD79D2E475A1
-:10F5600014CF27A83EC07AB5497122DEBE2A42F0E8
-:10F570009E2C8FD7F59D46B66C08F17F37DB721B4A
-:10F580006D145EA38D7D6FD9CBED94006FE77FFD89
-:10F59000C306F03B2E1A917FBDB9BFA9BE7780D3B9
-:10F5A000675C826B2BBC4FE0979F51E3E374DB9C5D
-:10F5B0008B46415C9ED23BC40E06F9E663F951DCF2
-:10F5C00004CF3F922C3A9443E27239ECC27D761F0D
-:10F5D000EA8DAA07242011C853A0DA37A9450A5892
-:10F5E000A9DC8F365902708F2EA99CCE3B19F29A56
-:10F5F0009818BC56F99C18D7A2F29803CE3DC1AB1F
-:10F60000F3104805F8AADD53EDE5DA44668FD63EDF
-:10F6100024635ED4CD729B19E2A9592E471EA4889B
-:10F620004C921D78AFA65F3971520C49FCC05F2720
-:10F6300076FB0154C9AFF9463F2FD2775B176DCCEB
-:10F64000DF1E97E0FE33D06BF8E1CEFDE02E38CD23
-:10F65000A417BBFFC5ED04F76B0AF97A37EE3F74C8
-:10F66000EC7BD1C00D24F43B2AAD9DD86466EBFC45
-:10F67000B8EBD9BA37EEBC05D7BD6E3B515688EB17
-:10F68000D4C8965107E09EC5C80F997E126E1FEC34
-:10F69000F40FD029E7B04F0FF4F9B67641CB6F12D3
-:10F6A0003075D787EAE01C86EA5BC8FB673576646D
-:10F6B000C5F441B5185EE672D4FF1EA7DE1D4247B1
-:10F6C000EDFBDD714AC9D4FDDC3110ECC8113DDC25
-:10F6D0000BE9C8A5F3A3F3DFC8F525F173FF649820
-:10F6E000D7C6961BCD20DF6B0379F662FA4EA2A92E
-:10F6F000049997485C18CF19493D32C88F518B4205
-:10F7000041FD41A58424A4C03DB42221DE432C49FF
-:10F710003CFF4B00F9D22DA7548E43EFE5AAF2A986
-:10F720009547557E6BE1A005CE0721624E4BBDD4B7
-:10F7300084878146B2D90EEBBBEA5FD6727FAED624
-:10F740009CE9C7EF977C19E81FADE4FE51ADA5D049
-:10F7500084E6605F32AEEB2B217E42E9B03285D980
-:10F7600079753E5AB9F45CD4137FC83EC12377E261
-:10F770007D44CF45033E5FA7B807C0FC55FA5CC384
-:10F78000E9A3A58794C0F79D9C2E3DE39B63877BEF
-:10F79000C1892617598FF8E6E13DEEA6C04813ACA3
-:10F7A000BFF76AF08D01CF6B13C684E3295BA2E03B
-:10F7B00099CCF0BC8EB8FFD846E53767455D6D3C07
-:10F7C000EA15792B3D275CAFB47AA4EA8D1AE7BD20
-:10F7D000B6B2FE005EBBED416F3CF18C2E4EA5042F
-:10F7E000EF5739F7C4A31DD1EAD3E77CFE9E7846D4
-:10F7F000BF058A7B06CCCFA3EBCC043919EE20BD24
-:10F800008A2992C39BF5A8E7A435B67BF8AA7FA501
-:10F81000FA55DA7EAA5FA5DA63F51EFCDA04F77CF6
-:10F820009003A999CA2DC5A7D6CEF64B9B6DEE4580
-:10F8300080573CC53D0EF68D430259ECFB5F512FBE
-:10F84000A2E941BC46CE9B0232AE0B3EBA2E644BBF
-:10F85000E178A8E30F4A48647CA45A0EEB7DDF1CD4
-:10F86000C206AB269837A7EF70E28675ABEF4876F5
-:10F870009F714D02B3BFB5096CDD52CBCDB692BBC3
-:10F8800051BF65E2338EFCEE7803AA70DF7C6D8297
-:10F89000EB2EA087A9C885F3E863274EF04BFBC881
-:10F8A0004D127C379A54E990D83D7312FC7E8BC27E
-:10F8B000EB53ECC8057DED03FB6BE8DF1239CFD8C5
-:10F8C000A309EAFD5EE67F3A49771EAF471398FF2A
-:10F8D0007908529FF42A56F382A9E7394E09E8D4F1
-:10F8E0006EBD0D916EBF20313F3D91D14BBB4F009E
-:10F8F000C287FEFEBD7B0D44362791E0EF59D599B6
-:10F90000D0BF8F27CE26B057BB1206F0734C671DB1
-:10F91000D47F25779A128706E55D95E30727CC709B
-:10F92000422A52DBF55DC3614F45E57A27D0BF7DA2
-:10F9300042D760CC41493A3399FCB8F442BE209595
-:10F940000FCD8AC00733ECC343EDA4D53004FCD1FE
-:10F950007629CE09F72CDA974A0C5FC9C4F329C976
-:10F96000C23CD3E3997FDDC1EDD53B09592827AAD5
-:10F970003DA6F3AB83523B0F8F11EF7490CE3DF158
-:10F98000FEAD706EA5C93FA9CD4F3969A105EF7FC6
-:10F990006CDC63C6FD6B57093BC7EF6A31A27D8EF5
-:10F9A000A6B7696DE688711CB5A4F47B0BE897A631
-:10F9B000D424823D4C9B7BD2067CD7D2A543F25DFA
-:10F9C0007308F645AF2B11BFBB55CBF4F49B121750
-:10F9D000D1FEE91993B1549F3758E488F7CD4F739E
-:10F9E000BD52E5F14A3A22DF0F9D06793CEF7EF3E6
-:10F9F0001D1709DEDF6F8863746C886374EC728F87
-:10FA00004F781AE4CD9781FAB0583D07E5FB7F3572
-:10FA1000CF943ADE46AF2951A62AD0B0608A19D6D3
-:10FA20008914E29A3C1B9475A342E03BA2C7BC3BFD
-:10FA300012F3318E6D12EFF9DAD9BDE1CF3716E04E
-:10FA400077DEA9648D7930A5475989CE09F183F312
-:10FA50000BDEB7E9A83C2DE8D39A03F2FBBAE22605
-:10FA6000F63118EAC2FDC99252833F40F996DC4054
-:10FA70000D05A5CB7F03D85B39A8008000000000EE
-:10FA80001F8B080000000000000BB57D0B7854D5DB
-:10FA9000B5F03E73CE3C92992433794E1EC009E1F5
-:10FAA0009D108724BC1F4E9E448830BC0485EA808C
-:10FAB00028CF2488D6DFB6DECBC444F4A2B745E90C
-:10FAC000AFF4D6DB7FB0A2A8200182069AA413402F
-:10FAD000E4113408A8A8AD5129620BC908EAC5D6BB
-:10FAE0007BFDD75A7B9FCCCC4922D8DE4E3EBFED62
-:10FAF0003E8FBDD75EEFB5F6DA872EC977134B641C
-:10FB0000CCB7D8C0B64A8C7D87BF1B43ADD96E60D9
-:10FB10002C89B196383BB54EE70CC7D284F07E8570
-:10FB200063693E63D5D6D85C16876D7F3F8B85F1C0
-:10FB30008A58EAD202685BACAE5A95B12546AFDD71
-:10FB40000ECF774EBA3CA48EE12FD8DF3392B12E80
-:10FB5000236B94E2B01F606C0C4350F8CFED56ED70
-:10FB6000D097F0FFE1FD448B2D20C3B8CCA35CEC13
-:10FB7000B0F047BE1B281E4D66CC285E939ADEF877
-:10FB800046CA652C7672116370DFCA5C8FB22CB8DE
-:10FB9000318CA99E18C6A2D833F6F3D98C19F07D02
-:10FBA000584757F3BBFD7C00C71FFEE54A0C83FB9B
-:10FBB0001F29C118570E63171E3C15E3B6C1F50780
-:10FBC000E5723FF46F4740C687F0926F870BA31929
-:10FBD0007BC4EE1981EBBA63DD7F8FF1DA42F7D98E
-:10FBE00003703195B1157E19E7E6F0C27FABB659C7
-:10FBF00019B384FA95F509117DC018E1B5D2CCD6B8
-:10FC0000D4DB7AD26305D203E65DB17D8B295DC575
-:10FC1000F9BD93ECD0BFA0C0AB80EF0B0D317E5F80
-:10FC200066089E25DB4799D2E1D6474D661680755A
-:10FC300030A5DDC86C84B50A09F0E61578D3C37920
-:10FC4000B8C54AE3DDF57F65BF1996BA18E67A2094
-:10FC50001E9E6F5A51C1727BAEE3AE3FA86529402C
-:10FC6000BCBBFE4D623E953FFF601E3CFFC0235F64
-:10FC700020DDF4EB5CEC337ED211B16E376300CF44
-:10FC80003241EF3B1F8DBCBFACE9311A6729F39AB3
-:10FC9000909E776DD4DFBFE933E4BB654C095D0707
-:10FCA0003C5C3E9265453CDC618F493C0F20038FF4
-:10FCB0008DFD0EDEDF7D64609C37A7277EB5F6E202
-:10FCC0003AE06F33637F5E67A1F6C23A46ED08BB48
-:10FCD0004AF459DD74F27EE4AFAAC65D261CA7C5BE
-:10FCE000FFA78409F04861D3373232572173DF7B95
-:10FCF0000EF0F92326B3EF007FBB19E79FF546CF3F
-:10FD00003D48AF1BAF96D37DFDFA1769FC7F249E5B
-:10FD1000F86711AE3B17AF2B5FF6B6AE9FE2BA8025
-:10FD20009FD95858977CFDEBD2D6A3AD4FBB5F2926
-:10FD300003DFF5F2BEC6EF23843E58FADCACF5696A
-:10FD4000808ADAE6CFFA77103FB1D328BF1A3F2D69
-:10FD50001374D2F38D46C76EFE68FA775A9F463FFA
-:10FD6000E07FA7C1896DC06918D7934FF47CA1E7E4
-:10FD7000834E63477F945F3D1F744A6C416FEBFA7B
-:10FD800037FB405AD752D55D6687FB7731CF7A3B38
-:10FD9000AD67235DBFA06C3CFC3394ABE7385F7765
-:10FDA000EB3933973776DCE847BDB936464D71D825
-:10FDB00004FD80CE9DBBCC3E7C4E9BE7FC3AB77BDE
-:10FDC0009011F15E4EED9FD779DC830687EEDFFD63
-:10FDD000AB2BB12ABCDF358C95A3DC77C644C2BB04
-:10FDE000CF2E133CFB900EC87F4AFBFF7C803AE984
-:10FDF000B9F631A847CF7FFB5FB11E78BEEB5B73CE
-:10FE0000796FEB3C2DE807EAE5B413F8EC7621674F
-:10FE1000B73755125D963C33CB84FCCC1EE0F8B46A
-:10FE2000C01FEAD7B6A8D867711D8B1B24D2237ACE
-:10FE30007ADCE59AFA39EADB3BFD85F47E0FFAB00D
-:10FE4000C789BE77213D8685E831D6A1727854F8FE
-:10FE500003BEB943F0CD79658DC9007AE4FC3380E7
-:10FE60006F007995C2DCBDE9C1FE0ECE877DAD473E
-:10FE7000BF8EBEE05FF65CCDFA3486EB1F654AEBC1
-:10FE800045EF68EBBF8BB96249EF88F5B28E1B492D
-:10FE90005EAB2D7C5E6D9D2B9AEE9C817C51B519DD
-:10FEA000E895D973DDA87717F7026F997CD168813F
-:10FEB000F7BA1E905CA86FFBA283A627EE12F85A31
-:10FEC000B96DF10C349A8B613E3913F5D1176FC6B9
-:10FED00024A25C415FFA1E7A35C91F9B711D8CE319
-:10FEE0007B09E07B8374FDF45BB6B9D03D28ECB9A7
-:10FEF00015FE9BDC83C2F5998EAE6CDBACD0F3644F
-:10FF0000B7DD26B4C7F10EA1BF845EEE5BBE60E133
-:10FF100000E7DA1D0EB26F6C8D83F46375D3165350
-:10FF2000B8DDD5E44B93B7B10E3BF15955E313F46B
-:10FF30001CE85FD501FD4A4BC7CF6F55C3F0394E62
-:10FF4000D051AE30A1FEEE4B7F82BEF9B2236C9D44
-:10FF5000231CC2AE08FD7B2DFDA0C1AD1F57D307EA
-:10FF60001ADC1ADF6BEBD1F37D5FF0E9E9C2989FF1
-:10FF7000FB0B3AFAAC427A84F5115E05F0DBD66CE5
-:10FF8000F53F04F0B6491C7E5F7314C1DFE92C769F
-:10FF90009F033FAF2A7521B527F0C554F4EB3CD33E
-:10FFA000109F9A3FC70A1222FC247DABF93779C211
-:10FFB0009FDA1BE5CE0713093F4F02F2C3949A8ED6
-:10FFC000391620D9AD8EEDE50A8C3FE5898E395181
-:10FFD000D05FE8D8C1FB5B3B4E595C8CD5B057CAAB
-:10FFE0004BA07F3BA013C7BB565B60F62C44F95D6A
-:10FFF0000D7E9205ECD1EAD3430EA1DCAD6EAF28A5
-:020000022000DC
-:1000000097C0EEAC068323813DAA74C706ACB9D471
-:100010006713E0B9E7EDDE65C42F57EBC86EAD3E60
-:10002000AD70B9399248EB5700F62878AF2E1AFC1C
-:1000300055C0575DBCC5559B49D77D51F1D877ABAD
-:100040006AD8758D1EF81EC25167606E07B4AD4741
-:1000500087C4757C8FDD6E5DC72A14E08383EB2C2B
-:10006000D4EAEF179AEC83D0EE151A98B7377DF9DA
-:10007000A483FB8DC0E4E948E7AA23269277FCA17C
-:100080001F5829F4511510280EE0A93CCD02D1B11A
-:10009000F85CD9E70AB60D12FB24C25F61A1BEDC91
-:1000A00037DCD7DB56E17883C3F984E3A948912A8A
-:1000B00094B0794B6C51117D39C5300CD7C3E468CD
-:1000C000D756C0AF9C6E58B31BD62F0F8016F0A129
-:1000D000D85DF2626837164F9197405B6BE476B556
-:1000E000D6C09687E3E905811FADFDC0E1D98A74CA
-:1000F000BFF456FB182BE9AB0C3BC9B9586FADE404
-:100100000A50DCD4CA5C5BE15A9DEC619C8FEB1910
-:10011000F2F11B621C97D9B047057E6D747C40FCE0
-:10012000EB8A33DC9B09FDC0131FF17EBAE14A263E
-:10013000F0F781273ACA15900757B6E1CA40E81F81
-:100140007AE2637E7F220C0906EAF0139F94FB6C2F
-:10015000382ED7676CBB3B1BE7510C12C9A972C084
-:10016000E4AF85FFAD8BE5FC54073C82FCF786B01D
-:10017000B3EB6B8A5EB602FF2B456E750D8CE3C741
-:100180008069F4DFDF6A7894AD068A53B0457CBF9E
-:1001900029D6ADD18135B8B367A15EA87767CF8E78
-:1001A00041BC7A4F225EF3DBDAA7A03E6E78FBFDFE
-:1001B00031E8AF22BD709CFC3688DD603D975EEB78
-:1001C000B7450E8B473F7014BEE3003996DCDC9FC9
-:1001D00094543B5B047257EB66AA09D695A28BEB4D
-:1001E0001A18D72FCFDB3D7FC4F7584680EC4DA1BE
-:1001F000C3FB31CEAF8F57597B7CAF7A59AFB74C29
-:10020000B90FC8E8E7C4A737BEB704F5FBEFCDAE1A
-:10021000C12AC2E5660F003C3B0D4C61F1C426C308
-:1002200094028C3FA35D1B50EE5DCCE90339C330D3
-:100230008D80845FE298B0B855AC07DE2F61D08E18
-:1002400045F86EA0F5C9C857A3984746FD3586F90D
-:10025000ADD87635BFE644BC3D19C5EE40BFCFB240
-:100260008DB9FD61FA63403CF7F726251809EE6861
-:1002700063FD6CE4D7E82F981DFDAAAEFF34293842
-:100280003E08C874BCEE3A6C6008E70B46BF3D0EF2
-:10029000FAC1E18AFA2C0B8DD725E8AD8DFBA44974
-:1002A0001DEE407D93C0FB2F1472FB1CFCDCE47F31
-:1002B0003613F16359E30F932F673CF75BBD494554
-:1002C000F1F1D0D63747339C7F6C4BB401E9F0F2A3
-:1002D000F6BC28E4879D881B587FBCD97E0F8E17FB
-:1002E0007F05E0CDA4EB6EC2ABA28E8A03BC4E9814
-:1002F00066533700DE5F88AA9F86FC1FDC6160CFF3
-:10030000C2143B4DAE59D8DF7959B5A3BE7D21B398
-:100310003E9AD6B3C340EBD9191D1CB116E0DE30AE
-:100320004C2947F8142B53500F2B8622F51EB83E4C
-:10033000349EDB574D2F2F88E7F2F3A404F3E7E157
-:100340007385243FA5B28DE4AE2BC8FC669827695F
-:100350006EBB8CF4889E05AC847CAF046406FD49BA
-:100360001E46498D4936A35F257DEBB62D06BA4F53
-:1003700011FA76CA87AB2B78DCE33A3D11C63B68AD
-:1003800033325CD764D621A33F38F92A7305907FB6
-:10039000AEF278C60E7FE83F3DAFF3074BC578EE6F
-:1003A000A0BD042F17B2483FAE7473D9E712CDA396
-:1003B0002A68A78B2DBAFBE8E7C5621B193795C5DC
-:1003C0000BFFA63FEBFF1DE937E05E98EF3E3B9F3A
-:1003D000AF54CEF915AEAFABDCE4423CECB2B9DFC2
-:1003E0009D887AB1DDC8B6B2BEE5E979883FFDE007
-:1003F000730CBB6A65FE7CE2471BAE67C4E68DBE2C
-:100400002858F788417C7CE43BD42343FF333101F7
-:10041000F5F855A15FB456E333E4277B1CE727FBCF
-:100420000D2139BC333E939ED3E40AF90CC7D96F32
-:10043000F42FF4F46227813FEF44FEDC6563144738
-:100440003D966A598072A5CDF3BCE0637DBBBE6664
-:100450006DAB11D7FD15D80380BB24EDAA29DC9E16
-:10046000EF49E27C552A7F4BFE766793C4D0CF4F8D
-:100470006EE2FA3B9C3F527BE78F5F225EAFC51F67
-:100480005ABCB0FB87F2C791BF8F3F365C933FBE2B
-:100490008D453CDCD75C9CC2BEC7BF6914FCD0D77D
-:1004A000FDF156AEE7F4D75F1178DD67DA383D1716
-:1004B000F5C0CD0617CA39503F7D36AC635F347F37
-:1004C0008F296BB2B0BF4BE17A65579399F4CA2E6E
-:1004D0009BD74B76DC6961E83F30C5DBF133D487CD
-:1004E0006916754318FF2E8DE7FC566F0C8CFF0CB8
-:1004F000FDE2A39CCEE36ECE934DF05CEA522EE774
-:1005000005174C5B300E2B4D28DC817C7402751670
-:10051000B4D5E7E029407CD53913E9BBD75A4E96CC
-:10052000617E11FC1E37F2D9D8FD27CB8A72F07993
-:10053000AE4FF78A56EB8FC735C5B3EE78D723ECAD
-:10054000C678C6F59207F92437D4676E23C56B1AAF
-:100550003FD447033F805CCC67AA3116869C73CE9C
-:10056000F330984336A73C92CEF303D3283E9C7BCE
-:10057000BAFD55D0CC6C9E47775FF0C17C1D1F80C3
-:100580009D3D1E8FFED2F180C980F399D664737FA2
-:10059000684D16F293264FF4033CD5FF61D8B31B88
-:1005A000C2EC7B6C0297A3C75D0ADDF77598FC83EC
-:1005B000E1D2BF33FE5EBDB03F9FA33C63FC70DF62
-:1005C0002B0BD18EE62F771F44FC4F4F92E9FA2F69
-:1005D00058C09285F47129E497D51BD5E2CFA4D0F9
-:1005E000734CF10CB3C1FDFD49D1F9387F6982F735
-:1005F00022D28929C123F8DED80979F9285FB651BA
-:100600007509688F34B801AEF2ADB6101C1A5C677C
-:10061000055F94262CBE88EBC7F750BF347E7CDE86
-:1006200082EF6B74AF6FFE82D33B8CFE48EF10FD00
-:10063000A53BB0AFE1E12BA157B4FE3F4A7F2D7F30
-:10064000704DFA637E20F6EFA2BF352129447FF07A
-:10065000B3E2B1AFF7B3EA4DE077E7F4BC5EE82868
-:10066000A4E75D265821FA552D1077A23C7A1DB4D7
-:100670002FB0C7CEE7EAFAC3F9FEE022B2C109F112
-:1006800084F76A537008FA21A30212F985A340F097
-:100690001791FF95417ACF25F0C4CE4BD2F961DC9A
-:1006A00045FF2E1DFDC34002FA51A3CC1501E4F70E
-:1006B000DDD629E9E8D7E5592765215FBD3AECBECB
-:1006C000E368825E4D5BBEE73935E4FF68FAEDA072
-:1006D00018569BBF2081EBA11B41DDA21F882E6312
-:1006E000381C9A3E47F2201C5260BEE13B2BE9E5E4
-:1006F000A60EA0C78D0807E0A155620DA8CF0B0D6F
-:10070000EEC462F4D392020AF7F7BEE98FF9C18A08
-:10071000A637DE43782B703F04E35097F162773EB3
-:1007200062604F3F58F357B4B840F367B4F813FD15
-:100730001EBC3F405CB79B0140B447018BBF06E63F
-:100740007FF2B23ADC2DE4568175548875CC64EDA5
-:100750000417FBF6BBEF26017D66087C541C81B8AC
-:100760003117EF337633E0E16685C79337BB207EE0
-:100770000CE3A399E322FBF89B921C1AE75ACFEBF8
-:10078000EDC044DDFECC3FDA1E017BF409B8CEC7D4
-:10079000D6F1B874C240D9A7A0E11C9769407EACDD
-:1007A00016F60DC2E85EEDD24BC22F9E60E8C8750A
-:1007B000017E5BF7FF8DECE081FD7F7B07FDBCF1E7
-:1007C0009F2BCC0CEF4FF8BC200EF5041BA7125F3B
-:1007D00069E356FFA9C1CAF875E2FF2AB1F6C30062
-:1007E0008F7B28C267A1F677179FDC84E37D794E63
-:1007F000E1BC2DE62F337907611EBBCCC4F3018722
-:1008000025EEFF68F70F1B016EB8BE2941CB0BB474
-:1008100093DDC79F398CCE37633E202F44D79B2F63
-:10082000947FAEE4F6A40FFEFE37F2015A1E60ABD1
-:10083000C01F3B78D6A4025C531BEE51D0BF9EEA8A
-:1008400094993B6CDE9B542B7387E5039E49D0F94A
-:1008500023075FDC3403EC49759BEC8A42796DDA3F
-:10086000753C17FBEDB2CBDA0B1FE9F13BB5E91E86
-:1008700005F9DF98A8927C5F6BFE0923804F6E40DC
-:10088000BA33F2EB3AC74824477AFA1ED8FFEB8412
-:100890008E9CBEF1DD17FDF574F8DDC522DAEFB9E7
-:1008A000163DF47CDB02EBF4C1FA02B04E1FF85D9A
-:1008B00007D6D9A97F689D93FA1ABF5637FF36012C
-:1008C000FD368D4F4B1338DF8CDFB72981D942F4C9
-:1008D000D2F0F5A1B0577BA3347FC3356F065C3AE5
-:1008E00005768718D4C7DA9D6342F66BFEE932F2CB
-:1008F0003734FB355F5E544A6A53D82F4C23A35ECE
-:10090000D3DBA9B9EA6223EBCD3E2D88EC97B76D16
-:100910005462A867203A4992C087F0B33538CE3088
-:100920000FC1A9A7A706971E1E6D7D9A7F3D5FD0B8
-:100930006FCEA04C23C2DFC3AE8A75E2409887B861
-:100940005EBBFAB58E9FAF5C28792BB717BEED8BD7
-:100950007FF5F7357D508613E451EB43BFC298987D
-:100960004C742BBB6A626EB01B2C238A7D1A6657AF
-:1009700058C550E29F7B851DEE8B7FAAAECACC9BEB
-:100980001FE22363E31356E4A37DCA462BE6272721
-:10099000DB66D5C6019E4AFE543417FDBCEA0E0341
-:1009A000C3145669D3170731AEAF7E8FB9502F16D7
-:1009B00035B51623DF1D52DA658AB3BF64EC893082
-:1009C0007FB1B1A9D68AFE5463A24C71FC6107E7DE
-:1009D0004BEDFE9644AE3F1ACF5D9EE1EEE5FE196B
-:1009E00071BFE4E33CE2A3B24741AE310E4D8AA1B0
-:1009F000BC4489649F53817EC84D46F2F3218EF931
-:100A000023EE035E6A34EFC2D47E69E323F7D88114
-:100A100010F5FFFD698D19F30BB324D7B3F05C9982
-:100A20001A6CC57ED9DC4CAA7B18FB3F32F9B3C1E6
-:100A30005B25CA8B9401BB60BF6C51A61FF313FBEF
-:100A400025DEF735F37D0266F725CC8079DEAE48EA
-:100A500018B581784AEB0FCEDBC0042387C557F762
-:100A6000ED9549CFDC572AF971BFA9D49ECE7C61A0
-:100A70007C55F6A889D635BB29A508F9784EB9CC9E
-:100A8000FC61FC1D107EE13C0FC4E161EF1D8EE2B4
-:100A900070051703DC52486EA7093E9FC5B89F3802
-:100AA0007F4142C47BF0C62D688F6E6D8238157A07
-:100AB000D344FC7AAB373D625E0FE37ECD09162C42
-:100AC0008983F1FB250D24FE9B11B48F0EA8A87716
-:100AD000CE24A25E63C3B89C6872572AAFAE237E51
-:100AE00070F27DB2791248938CFA2F529E668E8BEB
-:100AF000ECCF72F7A83788907FBD5ED7E47E5EB3F7
-:100B00004CFB72F30A2517EB453FE8FDECB1D17DB4
-:100B1000E8856FD587E37AD30B1F96FF5D7AE135C1
-:100B2000082BC681FCFE3451E8877EAC1FEA875251
-:100B300079FB26E4972EB077E65EF845B3175A3C6A
-:100B40005E06F24AF27E91EF67945E4D65BEFC5000
-:100B50003CDEAD2FC09F70F5E2E73C9D984572D416
-:100B6000AD5F34FD11E64F18C7FCE3FE4429F89150
-:100B7000A63C842F83E02B633C1F588685439897BF
-:100B8000737E41F9966A88F329DE67BF25B850CF96
-:100B900049F12139D0FB195A5ED72AF2087ABEE80A
-:100BA000CEF3CD35521D8CC61765762E1F65736545
-:100BB000CABBEBF9449B4FCF1F015D5EE69AFC2157
-:100BC000E4EC87F24773A2D8571DC4065D0F5F6837
-:100BD000FCA0F187DE8E1CD3E567FAB2236FA21D5D
-:100BE00019DDB71D797D9891F4B5DE7E68F6E27760
-:100BF000495C2F6724F27D8E69C3E7D9D0EFB02618
-:100C0000F13A0DCD0E75E79736737E78BD63892274
-:100C1000A13D41BD9019867F916FD5F8AFEA51890A
-:100C2000F28D15422F7536F3FC5B7589ECB7C0FF6A
-:100C300016373DB189F78D949F2B545A150B8C3B79
-:100C4000D325B930AFE316F9BA196E89E7EB5C9199
-:100C5000FBF42D3AFACE117C349305EBD01FD7EB81
-:100C6000A53957B95FA0D74F73C4BEFB1CDDBEFBCF
-:100C7000554DDE07B001FF4C7FC09CF4FDFE80F6B1
-:100C8000BE46478D7E2AEEC5A11C1DFCC6A4C670BB
-:100C9000FF19E937F5AA42E3D893045F0A7FE6CB50
-:100CA0008B79BFA0984F3C5FDDF485C93BB26FF8EC
-:100CB000AFE5B7C6A29F3E3AE4B76BF34E53184B6D
-:100CC00047C74C674F6689EB3FD47E0CD7AD43A333
-:100CD00083A6477BE059E8D9BEE8742D3DABE9B364
-:100CE0007FB69ED5C6D7EC8036AF5EFFF615B769E6
-:100CF000FA74FD1603E54B268BF878B2C8C3CE4FC5
-:100D0000E2F1C1AD493CEEECFACA62407BB9B38571
-:100D1000FB272EB3FD38FA05A17C1FA7E7C331CC12
-:100D200087FBEC4C69B7D0BE67119012F73DD3F842
-:100D3000BEE77625E0213DED52580DC8C9397C0F3C
-:100D4000E679F8806F21EAE9873F1962A0FD7725EF
-:100D5000D08EFEC9D83C85F68F1C6695F2C19DCD1C
-:100D6000663BBED7B5EFFFB41A719CAF980B43B882
-:100D700043CDE6EEFD1BD407A5729B8CF9FBAE209C
-:100D8000C8083C3F6941A018E3A0C9ACBD16E57B8B
-:100D900002D2B117FAFD2A498BB37BCFEF17377315
-:100DA0003FAE3846263F6E8AAFBD18F7ADA62892F3
-:100DB000AB169FD5E5F75FD1C51FA1FCBEAAF0FA1F
-:100DC000435DFEBE91EB99EBCDEB4F40DD067CBC65
-:100DD0005EE373A16F581FF9FD9D26BEEF133C69BA
-:100DE00064E807B30B89BDE663AE95E7DFD712ED84
-:100DF0005663719F8EFBEBFB5AD2DC6A6EDFCFE746
-:100E000076048BD03CEEDC3E5BA1FA35911FEDB150
-:100E10007FD2C7FE88BBD17E08D5695FFB21C55F45
-:100E2000AA94F6B95EBC69750B4CD43FDDC8B49F7B
-:100E30009BE474E7F96837F2F9CEF3696E84EB79D5
-:100E4000C1A71ADFEF3B77399AF6414D6E15F78F40
-:100E5000830E8BEB59E25BCEEFF5A943FCB84FFB59
-:100E60001B21173BA383C7B213C3F73DF83E47CB03
-:100E7000BA47679F33D27EB984F9486D7FD907722C
-:100E800043753DF18CE20F23AB67386FAD9BFD1AC4
-:100E9000DB2993D438C4FBE5446D1F538DA33CC4B8
-:100EA000B757A8CE508FFFDDEB9807EB511AD659F4
-:100EB0003C0AC8FFABEBECD46F5CE7A476FF3A9535
-:100EC000DA878EC73E8076BFDA6DF22861FAE39D3D
-:100ED00064EE77E5657F524CC5DF7F6354873EE55E
-:100EE000C10E19F5C58D57611D117527CA65C43727
-:100EF000E537B342FD4C69710CF66FBC0AFDB0E7F3
-:100F0000AF2439B83DAA53EA462793B4105FFC2DAD
-:100F1000C9DD9104D7EF71783EC176B734FFE02583
-:100F200046FD73BC7FAB7C099ECB0F14525E391F0C
-:100F3000F3CA7934EC42C4DFE85613ED976BF9DD60
-:100F40003C4DFEBE8ECC33E78BBCEEABAC83F2CD1A
-:100F5000051608B40C0817A79F5B9AE794301F98F2
-:100F6000647261BDC3E82C4F3EE6635B9318C547CE
-:100F7000ADADC9196A0E720FCFFBBAB5BC2FFBFE1F
-:100F8000BCEF918F627DA4B7AE9A687FFAC8A9586A
-:100F90005780F60B2DE4FF69F5C82DD1BCCE8065D6
-:100FA0002CA03CD38DA29ED162F69A93495F050E88
-:100FB0009E80F77E7F99F17DC7F60F695FBBD830C1
-:100FC0003C05EB7E0F4A43E3B07DEAA3D81C6A4F91
-:100FD000C55E44FCB418AC2ACE7B669D5A82756D02
-:100FE00027D6B112AC637B6B9D85DA93EBECD49E74
-:100FF0005AE7A4F675B88EFC731C9E477E71BF65D8
-:10100000A37D92296FD9146CF316C650BBFBB6189A
-:1010100013C2DB12CBB66BF360BD5A203AD080C945
-:10102000FED6A7BC8F59FA81DD337B474AA3186BE4
-:101030007BCA3B5D990CE34EEDFF93AFE0FE9BC98D
-:10104000CB1EB3005C734FD91ADAA0FF76F2F2C759
-:101050006CA86F8F4783D2C3F5AE38EE1E0474437D
-:10106000A590C605978D837E82D65F31BD641263DD
-:10107000B71477643360ADECE495D32D80C75BACD7
-:10108000DE1F63DFE44B9A5ED20FFBCC87F5604135
-:10109000C948713FCB9012B1FE65A6C3FB4672589A
-:1010A000FD9E5BFA13ED338D714BCC41871F8CB4E1
-:1010B000EFC5EC1F2784CBDB4C47E91B488F89C960
-:1010C000BC0E78F424C91D5E5FA17F6EF439B504AF
-:1010D000E934E642591DB633CB1DD4F72C185B8793
-:1010E000F25C62EBEBFD627ABF3C99D78D1429521A
-:1010F000445D89FEB97C6026F48F8347A3294F3075
-:10110000FAB4B716EB4F4B9D9979B2A6FAA8EFD86F
-:1011100082FB6DA32BCE9424A0FCD824179A89318E
-:10112000ACA32E01EE17DAB1A00AD7F54431D6FFF1
-:101130008C562517A2ADD0DDDA80EF17BA625C8538
-:10114000E88F9F564BD0F49C52469D2880E7A60E10
-:10115000925D1618E854E0A68997A05F382C8EF2AD
-:10116000BC85CA9A2B27A81FE3AA51711D5B7E5D1F
-:1011700045E398C9AEEF9E51FC2FC83F459E38CA43
-:1011800009023E4AC2EBCA60DD0477A15DF6474919
-:10119000C8DFFF5A6287FEEEFE1296CBC37CC3FF08
-:1011A00042F78F44AB5100E86E93BD04C7DB6D92EC
-:1011B000EC0F51DF538CCFFB861855CC1F9525467D
-:1011C000458C3FB5441A7F0EE1CF891B85D7CA33C2
-:1011D0001C11F7DB6EB3929DA8782B87FCA2B6DBBF
-:1011E000D2C95E54BC35A908DB3603F7D32BDEAA7F
-:1011F00028A7FB061E07572CFC915BF429EEAD587F
-:101200005849FD5629E52738DF959CB83CCCAF4DB1
-:101210001B945AA244F8810349FEF3447EAFD030B8
-:101220007CD32480FFDEA37C9FA2222733E2F9191E
-:1012300005524978FDA8675254447F7689A324BC9F
-:101240000E756E456A44FF96B99911FD92A3056427
-:10125000BF410F5494801E380AED5260C1025107FD
-:10126000A5E59F0A054B15B68BBCACC2E3EB61F05C
-:10127000877AB0C41669A77747733B5FCED6D0068E
-:1012800049F911BEBF5D9668FC24DC4E94CB15363F
-:101290005E97158987BCA346B2977931921FE3FA0E
-:1012A00092A34BEBD0F4966744BEAFF961E5023EE2
-:1012B0006D5EE673B7A33FA2C1ADCDAFC15F2E2F68
-:1012C0002AA17CF735D6A18797C17A503FE8E1681B
-:1012D0004A16FE1AF81FE4AF897324F04BECCD7E5A
-:1012E0006BFE7A05E82B47B8BEB2498958B7D79745
-:1012F000BED2C6EDCB2FD3C69DE9F0D0FBEE1D9F2D
-:101300009E9A2087F5333F4E880FEFBFF8E9A688F5
-:10131000FB491FCF7184F7B77E3A07EF4F51D45A7C
-:101320001BF0E53126B97CC8076DAA1203F4283EEC
-:10133000EDAEC3B6F4432F96ABB2A9E77C75D84E99
-:10134000BCE86F33C3BA6E1A26AB18BF6B7E881E1B
-:10135000DEBF26F3BCC3B1ABAA15F75977FB542BFC
-:10136000FAF3BB1F54ADE887EC76F37319EE2C0348
-:101370009D8F7167F37AC5BF24F3BA834EF1BED651
-:10138000FA8DDE4E841BEBCCD137A8FA264875E5E2
-:10139000C7D0BFCAE9E95F1D53FC369CEFD8837EF6
-:1013A0005BF87EE2F5FA577F041E43380A99E40998
-:1013B000D723C596284FB8DC96DA1D11FD93C20FCE
-:1013C00099EA4C8D78EF263533E239F01B87A15F1F
-:1013D000526B62546FEB33F07A5B3D1E57A4F0F80A
-:1013E000CE65B3A33B83FB66726FE7915CC5865EF7
-:1013F000CFB7A5A4707FF03F5218C1352B85C3A786
-:10140000AFAFD5F76BF17C0FE293B99CC8E72EAB79
-:10141000E10AB8BCACE0E927A6535D6DBEE1DE2C65
-:10142000E8573CBD753AAFAB35ECC13ADB194F3FDD
-:10143000CFEFDF60C837823FB0CDF7C274AC2BAFBF
-:101440008AE2F5095551A23EB46E7444DCA3183EFD
-:101450007E6A21C69FFB8D0CF3FC8F99C00EE6853A
-:10146000F6D9AD661EAF5A4DBC0E7C7DE6A9F5A837
-:101470003F3E8BF2E6A5509EB148453C5EB45BA86A
-:101480003EF4BE7DA529C807B35278DE2B7BCF443E
-:10149000279D2FFBE7C151FC7D7060FD308E73717D
-:1014A0007736F9E5D903189D27D1E801E1335D8F3F
-:1014B00082F081CE6330B713F36FB50E138D332BEB
-:1014C00085F3E3F5B63DEA89E30C6B7641BB2085F5
-:1014D000C7CDB7E2BC046FB0FF2CDCD0B307FBCFA5
-:1014E0001EC9FB486F59CE0BA27F1BFC510CEDC3EC
-:1014F000BC1FCDF1C63282B46FF3EEA26CD706BA30
-:10150000CEF1B8C03FB0B643C5FA0F7F3FACB718B5
-:10151000E8F42E457CDC66F60F26BEB2AD89C179B3
-:10152000AEB7DEB8EFF921E0047B327F3CA79736F7
-:101530003FE0D882747C579C3BD1E001387E8C70B0
-:10154000687075C3A3AB3FEF147E7B278E971BCAD1
-:101550005357FFC940798A6A09F424F4F77CC85CC0
-:101560003E95E8437950DCD2C2F9C69F58526C834D
-:10157000B6A071158F8FDB9588BC9866CF268AE759
-:10158000C7BEA744D8A38922FE1DAFCB4F4E6C9C8B
-:101590004EE7F826EAE2E25FA488BC651A4B0BCF5F
-:1015A00023AC15F1C6E5B68171E89F2A10E7CA8021
-:1015B0006F932AB371F121BDD0B08E459C53D4F8FE
-:1015C00070E469FB9D38DFC8D3EC0EF207B471BB41
-:1015D000F3131C2F97DFE37819D531ECE949D037A5
-:1015E0001E3132BF1A5AE7040E2A833087E2A4CB99
-:1015F000176C645FC61C9D43F5DE66A781A961EB8D
-:101600008F52A3991AA62FADC3E223FAB2A04F5D61
-:1016100054A41F902FE68971A5458CB73FBEEC08F6
-:10162000FA05F9B6E5E417C48D1B18311E6B532279
-:10163000FC833CE67163DCE802FAE27ED998D34A87
-:10164000841F302EB091CEA18EFB30F2FA847391BC
-:10165000FD037DD1A52FFCB1DCA7D12FFCA1F87330
-:10166000B823F197501E89BF244F24FE521644E23E
-:1016700027D51B898FF4E52322EEF75B9317D11F43
-:10168000F0C08488E733C18085F7B31E9D16F1FC56
-:10169000E08DB323FA4337DF16F1FC70FF9288FB2D
-:1016A000D9DB56FE207A8FAC5F1BF1BC9EDE37344F
-:1016B000FE34627C8DDE3EF8FBDFA437730AFF50F8
-:1016C000D03B51D859879BD7AD75196D8FE2797C86
-:1016D0003C3682FACE81E7E963D1FEAB5497E79BB3
-:1016E000C6685FFB97B24742BD940EA8356451BDF2
-:1016F0003CD5F5FDDC6088D867B73BB93F647772AD
-:101700003DFE6B133F2F950EFE26D929030BC5D93D
-:1017100016AC77648299AC8F639C5DE7E818A63AB3
-:10172000306F07FDC921BDAAE9D1DBCC6A6D07E89E
-:10173000975132D793A03FFB39619EF7A5078DDC07
-:10174000FFF019D1FF48B7305F6C1ED919CA433B6F
-:1017500058A284E700E2427A5CFD0E887570653617
-:101760009DC37A134140BF5975D17ED3AD9A9E5A1D
-:101770003E9CF4D4655BA4FF767969165D3F7BBB24
-:1017800099EA07CE8A3A470D0FFAF3D6DA396CEDAB
-:10179000FEF22D9B62D0EF3C2BCEFF6AD7270BFCCD
-:1017A0004D76CAC2FE59D6603E6C1118F138C07B26
-:1017B000E5918ED8DB18F99B9370DD555BAEDCFEAE
-:1017C0002AF4AB0DC1646E377CF4DEFC77F9B9EE18
-:1017D000F97F8BFCAE408593C7F91562FC5BA0B125
-:1017E000039E6E013A38B07D635219F2275CA7F36D
-:1017F00071338F3023CAF32C6F26D54D9C62AE33E4
-:101800007B01C4F94E95E09CCB3C46CC5BBD737B21
-:10181000650C3ED73D9E360E300CFA25EF3A7CC65D
-:1018200064CC1B4CE67513309F05AF7B16A53F8C2F
-:1018300076499BEF1DE6BD7406E83B9BB9685C6D7D
-:101840007C86E9F9303DB57BF9AA8F1260BEB547B9
-:101850000D948F58DB6CA678AD6BE57FED780AEEC2
-:10186000DF91DED10FEDF6FB2BFF3604F9E1D6CD8B
-:10187000325381DEAADD7BA7336C5FE5ECD22B31DE
-:10188000781FECEED6A7D058BE6CA63AE2F757BE4A
-:101890003C24DC8FAD74162EC7F7D8B8EB3BEF585D
-:1018A000FCD2F014AAF712FCB442F0D3DA178792F4
-:1018B000BFB536A69B9F787F2BAF1BD1D67146F064
-:1018C000E3CA97BE89F8CEC46EE023D5CCF7C5D461
-:1018D000A160EFDB2EE7D2771F8CDE7F75C2BC2DB7
-:1018E000573F89C5FE9E37FF4AF0B3B9D7072FCAC5
-:1018F000A26F4C687F5A3BEFB9A029211FE90E72F5
-:10190000B601C7BFED772F5EFA00F1D3FCF2D69F88
-:10191000E133D779FE7397967714F6C625F001F672
-:1019200086E28B2E16CDCF9308FF46C11DF92CFA07
-:101930009E874A7CED66C7711FA7B6D5407526B154
-:10194000B8091496AF8B950D9A51725B9CA0AF8528
-:101950009EF97FCEDB2AEAA83E20D21F2A38B43275
-:10196000C20FF2C05FAF7ED033DE5ACC2FE9FDA1AB
-:10197000F101C36253DCF7F84587A6F5EA17414049
-:10198000ED96C688AD21F835E8F4F37E2157F53899
-:1019900016E6FF03D1FCFC33980EF47B7F9ACAF560
-:1019A000B72D83F1F36952E7300BE8CB16E7A2C7F6
-:1019B0001F856B96417CDDD8AFA53335F9C47FDD3B
-:1019C0007ED7A111A4B7D8B7301BE243E43DF4742D
-:1019D0002BC0F3ECF9617227DE0F1CFE6B2CE67D49
-:1019E00077C4AB6F213D824765DAFF89523A4C8E4E
-:1019F0005EE2BB57510F029FCAA9DC1E581A797EBE
-:101A0000D1A2BA19C60F5176FBA8F0737F8D4E1E76
-:101A10004F561E7EBFBF09E871C9D0169B03E3AFC6
-:101A2000DEBB3B16DDFF0C93F703E4C35567DF1EF7
-:101A300063A7FCCD96FE180FD607F87730462ACC60
-:101A4000A7E4F584A37A332C2601CFE927503BB2D3
-:101A5000297F19F2597580AF13C7C642BEE18D12B6
-:101A6000F53B1B6BE371BCEADF37A7A13CBD9CC40F
-:101A7000E3CD97AE66F3F715A6E0F341A74310D385
-:101A80006FC0F8E46511D7745E95E9396DFE918DEC
-:101A900085B21DF82127B0F100C5514D6615E91A30
-:101AA000F51CE378688A22B9AF6E99CAD0EE77390F
-:101AB000984B82FB3BA2837FA4F36ECD6615F3ADFA
-:101AC00051F68D2C1EC6DF21F659870347E179298F
-:101AD000EDBA365F54D3D31873203F50DE374AD95E
-:101AE000C826DBC2F11C437876A4723EDA111D30A1
-:101AF000609E253898B16709AE109C8CE6D5E01C35
-:101B0000EEC7F3843B4CC1F3786E06E0B223FD8749
-:101B1000330E276B1AAA629E20CAEEA67544D955C9
-:101B2000974FEA0957752EF3A35DFFF943AC5B6E3F
-:101B3000518EABA3437D0BC8C08E814CC8F9CF1F1B
-:101B40002FC908EF836219177A7FC8AF363E5E3718
-:101B500089E2099F8CF12FB431F1B84E95D6A76078
-:101B60008A298FE301F7DBAD167EBFFB79E06F1B9F
-:101B7000F66DFC39579CDD3A4D2239E1F5B8421F2C
-:101B8000DC2705CEDF08A4FD2A702057055856BF74
-:101B9000B19FF87495A1E9A99170FFEE28AF2B15BC
-:101BA000E67BED43039D6BFDF38B51FE0AC0C7B08E
-:101BB0007D5B92DDBDC8877EFC47DE7BE8C974A4EF
-:101BC000FF3E49C53C6C973148DF37A96AFACC44DF
-:101BD000F50D8D1F53DDD39BA9DE4938CFB8C61A4A
-:101BE000DA8F1ECF36D27E74B6380F5EEFE4FAE39A
-:101BF000F2E921CFD684E17F492A972F16F40E40CF
-:101C0000B96912F2D9827E0AB47B85BFB4B7F5D622
-:101C10002C352C7F58C30EA423BE1F6287A8D5AED7
-:101C200077F9F9B9CAEC772C77B8C3F86F9190F7C8
-:101C300045A9224F96EA9D8DF0AE6AFDC414ABE231
-:101C40003999FAFE6857EAC19FB2F782976EB9D503
-:101C5000C951B51234E1F3D517F8F957A0731D9E99
-:101C60003778F99DC6118BE1FA5EC035D695FACE6C
-:101C70009AA9BE72AFD1938ECFD79CF93A17F55679
-:101C8000090201F07CDDBC6A00E20DF8BE281AE50D
-:101C90006B17233DA6C9670ECA27BC9F837C5F8054
-:101CA000FDE1A4877798DAF9F9D3BDFCFC29F03D72
-:101CB000C901F0BD1DFD861C3BC801BD3F94E47BFE
-:101CC00047BB81CEC9FA408F0FA67ED11CECEF68CE
-:101CD0002FB1937C635E3F0FE5347080C6A987D82F
-:101CE000044927314FB83FD9E88C25BA69FAF1B0D9
-:101CF00093093BA1C6E17903AB2C47C845983DE465
-:101D00007D612F4FFC2AF0F82FD176B8855D10FE4B
-:101D100014F3E6939EBF57D8AAB5AF4F98B91DD616
-:101D2000B9F684DC5D3F8EFE6B40F0C901E1CFA2C5
-:101D30009D5013783D0E5E1FBD99D7D58E71AF298A
-:101D4000C6B3CFE3CA371EC47682A7BE18CF3E4FB4
-:101D50005AD07E909F81E6E7D91B0EDC948DFBDE86
-:101D60005D67CD0CF75D1AFE1AFCE34B8087FB5BC9
-:101D700000FFBDD825580EF11F58EC74E6EC79BF72
-:101D80004BD2F4C7A90AE4C7CE0639D40740AA80CB
-:101D9000C1B1FFDBD4938FFBA09F95E67E3E15FD7E
-:101DA000ED742FB55D27FF9A8CB660EF69EE47356D
-:101DB00098DCD9C83F0D0323BF1FA0B54FA61A89D1
-:101DC0000E057D7CBFEB482ACF6F0EF1B1C7908F17
-:101DD000AA1A64BB1FE87EA941769BC01F3AEFF6A2
-:101DE00026E3D99C0BCC77CB44B4F3228ED4BEF738
-:101DF0007217FA2960A7EEFE65EFFB0FAB99F65B51
-:101E00006340BE5AD624B1FF001C2C7F26F2F9D5C0
-:101E1000DAF76A1AB71CC6EF88AD7C4E771FFD153E
-:101E2000FA0E46A41F732455F827592C0BFD13E016
-:101E300023D20F46851D3103DFAE48F7EE437BFC0E
-:101E4000B2F8BE02E85192C77D4E615744FD417021
-:101E500007AF2B1EBECD2F1BE0FD098A5F467BC559
-:101E6000A0C57D87716E6F197D87C9E73E8DFB3EEA
-:101E7000CB853E5CAEF9697EBE3F026637C24FAB92
-:101E800016AB1FCFFCB5B1B8FE6D12C5CBABB645D6
-:101E9000EEA7548BF5AFDE7CF2309ABCCA7ADD7DBA
-:101EA000B1FE6ADDFAB57DF3CF5323EBBFAE773FCA
-:101EB000E42F46EE37BC2DC6D1EE9BD2B87EAC8265
-:101EC0006520DD56FB65BF9FFB7936FC5ED09D62C9
-:101ED0005D770AFAD33AE1B9CA6D923F803CFE7849
-:101EE000649DE95DF58BCB90AE7A3E5929D6BD7CD9
-:101EF000BB91FC55FCFE0FCA9D9E3F568AF5AFD4A0
-:101F0000ADBFCA2BE9E0E37E744FF8EA6F413A5760
-:101F10006E37B2DEE0D3E8B552E3EB3EE0D5E0D475
-:101F2000E0FEA1F0F64F13F9AD116C04D1A93CE12C
-:101F3000BAE8A4F773771D1E41DF5BBB7C6420C544
-:101F4000FB1A1FE8DF2F137EF2D4CDDC6FBCD45810
-:101F50006C1D89F14C9BC125A9149FC58E04BCE45E
-:101F600037CBAC02FA5D4D599BF0FB8379270AE62B
-:101F700060FC9F7FC240E7EFF61C29A07DE7FCA331
-:101F80008312B228CFEDA2EFE3C038645FBBDAF270
-:101F900036E1F984AEB692021C5782E7D00FC8131F
-:101FA00076A2A62DCF1A7EFE7C4C1A8FEFD73B3F30
-:101FB000FD39FAE9537719E99CC55463F04DACDB60
-:101FC000DA7344A17DF2D527963C1485F47D51A2A5
-:101FD0007DF2C3ED6B1317229F3519EDB8EFDDD5F8
-:101FE000F4E30378DFB75DA2EF5E54379766EF80C6
-:101FF0007EDE967C57F8F9B33C874AF0B1542BC586
-:10200000CF53FB19C96E5E4CB3FE16FD9F95EE2DA6
-:1020100024DF17F7EF3151DDDE0E89A1293BEC3CBF
-:10202000F80AE2E3E2AB274DE88417379C34757C6D
-:102030008F3F70C92FB300C5CD1B4D18C7546ED14B
-:10204000FA1D26A49347F84755CF7D4CFD95E8CF60
-:10205000C37C2B9F91A97EF760F36B26E4E7AAED82
-:10206000124BC90CBBBF598AF85EC312C6F960890E
-:10207000D03FAB987F7D1A3CB76A23AF5B608F4639
-:10208000D6016BFCBD42F0F7AAEDB3E8FB533DBEB1
-:102090005B8871E30DF81CE7EF659B23EFAF107CC5
-:1020A000BD42C7D73F4913FA67381B8E7CFD75A127
-:1020B0001A9703D7BF3EB972406FE7ECDB84BDD6F9
-:1020C000ECE5E58081EC8DFEB9CEC62B046775DBAF
-:1020D0006513FAA7654D5F10FE2B9A5AA97EE46638
-:1020E000E65D8DF8BAB9C96A47B9AEE8E07A685AD0
-:1020F00093D9EF97F07E3DD53977B5F0BA49DF7EB9
-:1021000089FC1C4D8F69DF775C26F0B80C14787A57
-:102110001EFABB3C6EAE1271F28A615B0EE33E7B2F
-:1021200095B8BFFAE8C158F40FA7B12F6E47FAC0AF
-:102130007C0CE763CF44E27DBAD08BD3B773BDA8E4
-:10214000B76B5DA9D933298F09712AC2B57A7B246F
-:10215000BEAB74F1F963693C3FF6820EDF15416650
-:10216000CD413854D9E5A7A7DB159CF7482ED85B9D
-:10217000B4936AD6F77E87F14DE1676BFD99E21C57
-:1021800078BD7DA32D3C6E8E4AE7FEC2CAF1B20F28
-:10219000E9D51D6F0C3A98AB1A42F106C419CD6906
-:1021A000493CEEC082923732649698188A371E7185
-:1021B0006EAAC8837EF5762EF79DE3603C3C7FAD2A
-:1021C00030F247ABB79BE99C6235D09FE28A267E0E
-:1021D0009EC2D3249522DDC15F3F9A86FBB19852FF
-:1021E0008575CF6AE47C3FABE40BE297A383F87A72
-:1021F0002F2B6A4A6FFEBBE6B7E3F93035CC7FAFD1
-:102200000239C5E7AB9A783D52C3816FFA67A29E47
-:102210006BFEAFFE8BA1FD5AD845CD2F0C825F38E7
-:1022200090FB45F4BDC9BB857C2DB3F37DBABB855E
-:10223000FD61521DF17995B1FE503CFA593B78BDD4
-:1022400000DB871F8503FDF8F64B75F1B0EECE97E6
-:1022500024AA87C3F7F17B949D4BEA3F41BFFBEB78
-:102260001D16F237EF06BF654A5E4FB9D4E45BFB3B
-:102270006E560D7B88FCCF87581DB595829F3B1B02
-:102280006BE9FBA09ABF42EF0FECE98F540ABEAF97
-:10229000D4F15F547A24DFD5BC1D4D7E63D751D96C
-:1022A0008EFB3180AFDFA485E345F8210D07A288BE
-:1022B000AE5D276D6447FE2CF8EDA2C83FD78C9326
-:1022C000090F86F1BCCD6E796D20D211F18EF5F734
-:1022D0002FB7BC36829FFBF613FE576D9323BE0FBC
-:1022E0005B591FF9FDD79AB76FA3EF0855EFEF863B
-:1022F0006B88293104575F7220493C8E34489171B4
-:1023000064F53ED9135E7706EBB903F551BA900731
-:10231000A6049331FF35009D0680AFA689D3D5D0A2
-:10232000CC5B98FF169E2731D2FC3DEE17F956E3A1
-:10233000FDAF33AD7CFFFAAAAF02FBF70F94A9AE55
-:10234000F3FEB7570E0DD7A30CE104BA561B83C991
-:10235000146F9E34107CD5272F270FB2A15EDA525E
-:1023600082DF0F9D2EF4DFE181D6E5C8CF3E9C379A
-:102370002534CECB69BC7E8FE17A9DE86DFC928FCF
-:102380002BD6FB109B2DE26ACE4F39697CBD108F96
-:102390008C4BEF251EB95EBF13ECC3A98512D63353
-:1023A000293E8C87F7BCC7F5424DF3B28F90DFAB67
-:1023B000DF37539DD7FD2DCB8652BDAFD77B03FAB8
-:1023C0001B5FB7ACB881F283D24304970FE173A2CD
-:1023D0005F732619EB522B9BCF2493DDDD3B7A9361
-:1023E0002F06FD97BCE9781DFC09E23FF06B88FFE2
-:1023F000F6B415687E8C15C7AD3CAA78103F95479A
-:102400000B8E57A07F71A2A800D5B974A280FC984A
-:102410007CF4636C21BFA65B4FA6733FA6AB358AE5
-:10242000F20B121BC8F9870D8AE09FD50DAF93BD43
-:102430005FDD2847D42F6AEFDD99AED038CB34FE6C
-:10244000A997DCC41FBB78BBBA710FAD6F95B19E65
-:10245000E85DB3DDC8EFEFE0ADF67D581F8BF721E7
-:102460003E8EE325A0C334933F03F3D3C732B99F15
-:10247000AFA7C7E7E93CFF71ECAC7700F2CBB14204
-:10248000EF507B2F76C2C78A785C2B097C37F073BC
-:1024900053FAE73E4B97C4774222CFB76AEDA9744F
-:1024A000AE3FA7997AFF2EE06FD2B57309EC3143A6
-:1024B0000146C546FB06E1D7A7867DD761CECD464E
-:1024C000F2174E31FBEB58EF3843D3B3E3B87DD569
-:1024D000E7CBE789F73C9B55BE5FA43B3F334F3BBF
-:1024E000DFA43BEF364FF83BF374FECED3E9C28F47
-:1024F0001FC286A01EAC17E7EFD60E8FF287E7B398
-:10250000F4ED61B12F82E787B0AD19FE2EE57D8E27
-:10251000B59E7D85EADDCE46B1813CAF47F9EFCA75
-:102520003EF2DF35DD72393782CF34BA5C12DF8399
-:10253000D1D365B7A6AFC4BE5DB4D8B7F31BBDBBDE
-:10254000519E2B2D174DBCEE3068427D56339CFBBF
-:102550004D974A25DA6F0738FB9BC3F4FBA5541E41
-:102560007FDD7F8B4479D7567C1EE3AC7A89EABC49
-:102570002B03ED26E4A7210D8B1F26B9F5B1D32C33
-:10258000ECBB1A332DDC4E76D34F5B77B71D8BF740
-:10259000717D9C482D3E8F767186B083FA735143CE
-:1025A000597B593AC033DF2DB9B01EA02F3ACF5E08
-:1025B00030EA7544C3F5D2BB33DDFB4E3ACA79FB32
-:1025C000E55B308F7A6CF867FDD18E56F5C1C71F79
-:1025D0000B3CEBBF2BE31AAAD6E2F7556A9DDE0E41
-:1025E000D29F866F6347301CA7E3376B25A4132364
-:1025F000FEEF4B7E3E13E37E96CEBF770FB8A77DEE
-:102600009755E9BC4EEB98D19F41798A9CEBDBF75B
-:10261000AAD9F7462EEAB3CED6A3B9A630BA5E5CE5
-:102620000B7A00ED4AF3C164D516CE7706E237493E
-:10263000D2F84F11F632920F2F221FE6607B2676DA
-:1026400010EAE35DA76207E3787B79DBCDAF4DFC51
-:102650007BF6101F0D9917130EDFC304DFA57A3E1A
-:102660000E631D43E68C0CBF5FDB171F5B33888F47
-:102670003B22F8585B6F3D7ECF07E38016337DCF5A
-:1026800007F3D78E3039199AC1F5CF58F1FD9EF175
-:10269000CC47DF391C2BBEE3335E6101251EF7CD2D
-:1026A0000232DFF7E5E72DC6087E1EAB045AB18E75
-:1026B00062BCD8E799C0DAE9B9292C48AD9BD9E9C1
-:1026C0001C451173513BCE12988EEE544E7D3DD574
-:1026D00025069215C7798B38AFD10BDD42EB57E851
-:1026E000BB3DC49F329ED7E9FDBB2FB333B8DCD3CB
-:1026F000C74590BE9718E5B9F07B6D38C9448595FC
-:10270000637DD3648559A201DE5D870C24CF2D1D26
-:10271000AA1FEB535D09E2BDCF19D5E18E75737920
-:10272000459383F518DA7AF5789800E3619E6DACED
-:10273000029128E13140F3DDC8F8399242A652FDFA
-:10274000736946A6D0F7418AA38A218E427D6FB075
-:10275000F8081FD33354BA8FFB25B130CE848D12C5
-:102760007B0FF73FB2F87AB5F1270023E0F9C2E911
-:1027700019DC9E614AF5BD78BE8F124B05CD2576DA
-:10278000FE9DA364FACED1F5E2B52B997FEF32F628
-:10279000CE60E7CF0A42FB492EFCEE516CE83B9B32
-:1027A0002EEDDF830844FE7B1077642CF911F2A331
-:1027B00056AFC7BCFCDF7DD0D7EB85D5E7B10B6149
-:1027C000E7B0B5BA926DFED92A9EF35B9068A1730B
-:1027D000BF7996FEF968C7063ABD34FEFBD2F6C152
-:1027E0003498E21FED8909F1BB95B9C721BE437545
-:1027F00083FC3B50DDE7AE92199D57B49A797DE595
-:1028000063201FF81D26902E15EB68D883C5548FC2
-:10281000B9DE6171E1790933C26D0DC15D6B11DF04
-:1028200005B5F07D717D3D68ADCD40DF1DAD65D155
-:10283000740E3D29DABB2E03E0BA2FA688CE776747
-:10284000EF9CE444BF317CFD93B4F51B7AD647C2BC
-:102850007A1FC9E8A51E515BA7F6EF76D805FEB42E
-:1028600075DBB5734A6E25E29C92868FC7A2F9BAD2
-:102870008DB8F39F45EFAAA837F4EBFDFFDC29BC28
-:1028800016A064000000000000000000000000002E
-:102890001F8B080000000000000BB3D36660F851E6
-:1028A0008FC0C19A0C0C5DD2A862B4C41D120C0C6E
-:1028B0009780F80B106702EDF5926460F006E26D08
-:1028C00040BC1D88C5A518180280381088FB80FC04
-:1028D0007E204E07E224A81BB30519187281381F09
-:1028E000880B815848808141588078FB8B151918D6
-:1028F0005EAB22F85A6A0C0CC91AF4F3FF60C3816C
-:10290000B6F4B5EF16D0BEE56E08BE0490BDC20D9C
-:1029100055CD4A37FC66AC42935F8DC65F83477FD7
-:10292000810D2A7FAB292A7FAF3903C3072435DB0A
-:102930004CF1BB051D2B00FDA788274C9730A2F258
-:102940002732A1F2F9A17C00BE1E313CA803000091
-:1029500000000000000000001F8B080000000000C5
-:10296000000BED7D0D7854D599F0B93F736726992A
-:1029700099DC24433260126E7ED0A001879860B04B
-:10298000586E20E147A30E082CB440262888166D07
-:10299000C49FC6DD500609BF0921E14F70D11D104B
-:1029A0005DEA63FBC5565B75BB7682D646AB356880
-:1029B000D787767765A015BFBA761BD96D976EBBA2
-:1029C000F57BDFF79CCBCCBD9900FEECB7BBDFF30A
-:1029D000C5C7E770EE3D3FEF79CFFB7FDE73C725BC
-:1029E000FB59701A631FE31F9413731963B5A9B2DF
-:1029F000C5C362D9398CE576488CD530B6B25D89CD
-:102A0000CF827F1676B4BC82F5E56D6EC35DCA5881
-:102A1000FF036E7F0DD44F6F57C26EE8DAA8F8A897
-:102A2000BEACCB15761BF07CEB472FE7E3FB8D525A
-:102A300098419DB1BB199BCCD81A0FFC13EACB2A45
-:102A4000921DF8FEDD2D523886AF99E99B04EF6F99
-:102A500065FC7DF3038AC664A8EFBBAD894D64ECC9
-:102A6000961E98C5430DD9C7BC3D63058C45F82318
-:102A7000D6B205DE57A6DE4758D7470AF46B8E3923
-:102A80009EEF9BF53E0BE07B2DF51CD6730CFF31C2
-:102A900085B14B993F783A1BFE1D66E18F15281BC7
-:102AA000F2191B9DC297B3640CA01FC5D85CC65C0D
-:102AB000AC1CC6A9BDCCC5CA607D161EDB381E97EE
-:102AC000354984C7653E46F577E74AF1074BA91FAC
-:102AD0009B5E0D253C2FC88332C8CC4228231E960E
-:102AE000C806F8E7B65DF61EAE7F034E359ADA27C4
-:102AF00002F07E018BBA18C0F7672C46E56216A774
-:102B0000F2CB2C41702C6543252AD4EF52129B182E
-:102B1000CC130E45A7E3FEFEAEFED8BB12BCBFBF72
-:102B20005AAA9D0225F3E5D1BA2FB43E6B7E954596
-:102B3000AEC37118935D113F63E3AD751E66B18A34
-:102B400020637A8F8FD3CB61D6CFA03EBE41D04BCE
-:102B5000E3FB7208D6DDF33C0B633D049B3905EAC9
-:102B6000A1AEACF806A8F73C1EAB47BC1C6B01CC71
-:102B700043FF638D6E295A05A54B7745A00CA98CA0
-:102B80002980A7FA86F59202EDE646F938E34D4D25
-:102B9000665742FD704C52C573ECAFEB314987FA72
-:102BA00078A83F28E17BDDC5609C86865C57B20A29
-:102BB000F1DD334687B2E2B0969001BFF5A64ECF65
-:102BC000195B4474355ED0DA5C93F79B7B38CFCFCA
-:102BD000E83DFBD3C7D67BC0EF25457CDF8E1D2E9D
-:102BE000CB417859D4DEBF4865314F5E0ACF3BD721
-:102BF000C10B770ABFBB0E976D45BC1DEB53C3825B
-:102C0000946DE3C3B8BD0DF0FE4C951C560CE4B3B7
-:102C1000220E7F85EED77DA97176AE83F697A5E06B
-:102C20006854A6F6133E4C46FC38B706DA57A5DAC8
-:102C30003F81ED018E3D080FF55B73D48BF3441893
-:102C4000CD33123DBCB04EA77E83621DD7FCEF3062
-:102C5000EDD3DC861689CF2BE06BB0C36795167C6D
-:102C6000238D7F4CC0658D6FCDF7C4BA10958D4A0A
-:102C7000D523F7E2BA8E687C5DF38DC77723FE8E8D
-:102C800078C231A83F79DDDF8CB91786B862FAF3D4
-:102C9000973FC370BEE50FDF8EEB7A2E8BD6F5D44F
-:102CA00087675EBB910D9FF72D81879F9E9B3F4459
-:102CB000756BFEB9A63446023AAB34A5840BE8E541
-:102CC00058FD571EBED7C07ABF89F2A4D23C664ACF
-:102CD000504E846168BF99FAA78F419E554277E4B0
-:102CE000C7490D520BB67BE2C687BE741F3CFAA9DA
-:102CF0008BC37DC55F72B82FBB7EED9308EF653740
-:102D0000AEFDF93350BF028520F0DDA537ED5FF34E
-:102D100077F0CF6F2CFCCBE57B18C9855836C09176
-:102D20006B4A0CF777D9F7DD36B972EC793FC99564
-:102D300042B33486FCB7AC4F22F9DCDFE866417C55
-:102D4000FF3377DC8DFCF5806452FB67DD71940FF7
-:102D5000C75C8CA13C5E76DC1B477E61AB9691BC68
-:102D60008E58F2DACC5F7A2F8CF76E8325CF399D9F
-:102D7000D27B58DFBBE62FB65F0DFDCF98AE308A11
-:102D80004D4B5E38F1FCAEC06FA4BE9CE860999AD2
-:102D9000748533D043739B6293DBF50D2789AE9620
-:102DA00041C9D2F874AEE0B3650DBF10FCA9935CC5
-:102DB00072C2F3466D617126BA3B25E0490A7A7BFF
-:102DC00017F7FB32840F7A21DD742971254D4EC32C
-:102DD0009F2B3281EA3164E95BB6D8E1B4E4764BEB
-:102DE0002CDBA6AF40FEFE0BCACDE6B67CDBF3B90A
-:102DF00039AC76EAA793C37F20399C94081ED0BFD4
-:102E0000B4FF91B81447B968EDCF1D627F22158CCD
-:102E1000D6F3AB03523C06FBFBAB23627DFBA4B8AD
-:102E20002211BD9AA73D382ECC599EDAFFDBC5FE94
-:102E3000A7F68FE3C7C2574ACFE56E4A02082DBEF8
-:102E40004809CA6B8B7F2CFCF6EFF95109EE5F61E4
-:102E50005B69771DC2794021FEFDB0FE6431EEDB77
-:102E6000BB2EC02BF48F1C7E2CC07C29F85B841CED
-:102E7000FCA003E8059E4B0867651A9C026E17D6F6
-:102E8000A1DDED0D521FF2E92FC5BC56BF1F6D9994
-:102E90003113F173478FC4103FB71FE95DF6E7B0F8
-:102EA000FED5F1EC304EF1ABC6E2C02500CF8A1E54
-:102EB000FB7E9EDA727300E9E6C3BEFC021CE7F6F5
-:102EC000A9090DE15C9D78553380CE6699BD5A32D3
-:102ED000035D7DD8B72180ED3F547B6EBC06E7D9FA
-:102EE000A784D7C3F8AB8F94CE34399D12FDAE16AC
-:102EF000F83DA9F6CC1C03F0B57CA39CE4C17B7D16
-:102F0000CAEC7806F9F97549213A58DDE696719DC3
-:102F100023D1CB871D2E96C079D404E173A4761FEC
-:102F2000F4B5D0FBFE070A6F40FBEDF67617C98BB0
-:102F3000DBDBDC444FAB1BA4389352FCB642C0BB76
-:102F40007AB742EF4F9A12C90F6BBF6E17F476F241
-:102F5000F055AFA0BE3F03F207E5EE8C8D3FD42EB7
-:102F6000013CACD8C2E5D1C9DDB94BEF413922F4FF
-:102F7000E51D62DCDBE28A8D3F56B667DBF623DABD
-:102F8000956FAB9F3E927F631DD2759742FAF39681
-:102F90008D8F6921924F767B13396C5241CABE3CAA
-:102FA000C186165C23A5E8C9A29F5BDBC0DE0C0CC2
-:102FB000B7375B8E48648F5EB49DD90676E6C4E170
-:102FC00076A6254722689F95A7E4882537EE52A26A
-:102FD000638300C7AF5DD1CBF2CB496E3C20D522D5
-:102FE0009DE8BF45BB92C5945A946F172B2F68B1CB
-:102FF000161FC1DF7B1D405719E87506D215CC336B
-:10300000B3A73F233DCF900C1A2F4537B704886FE5
-:10301000715080A3D96376219C97C0C4DE6A2A9937
-:1030200092C74B15EA9B1166A087536BA5F8A15276
-:10303000DECE87F214E0BA069E37775D1EDF26A14A
-:103040005D087FA83FDBB8DD0DED4C7F1E3D3725C9
-:10305000288BDA4B5FC6FDB904048056CDDBE33C18
-:103060006067114AA07DC25D4D5D6301288BA19F01
-:10307000CCFBD37B6C1720391EA7F5E2F8384E85C0
-:10308000125F8372C6A2E36542EE805CAD5481BEDE
-:103090009A595618F566735BF979ED971BC276F964
-:1030A00071539D5D0FCC35EDF2FFE6D997D8DA2F3D
-:1030B0008894DBDEFFD9A22B6CEF1747AFB2D5BFE8
-:1030C000BCEA0BB6F64B5B67D8FDA49FE6D27AD676
-:1030D00008BE1C09EED785BCFC89C33EB5CAA6EB69
-:1030E00013356FC33EB175EEF0E3509C98C316F5EF
-:1030F000A5C9159F2C113E7F036CC2FD833F7D4CFB
-:10310000780CF1799BFEC2DD9A89EE34D10FCD2582
-:10311000B4979CED4F2C8679D2FAFD9B24111D9E0D
-:10312000EBC73C3DBF04905B80937300F577B264BE
-:1031300009EE9B3BD7A0F777C9C902ACFF860DED1E
-:10314000CDC7FDF5258B917F9A55F69C9483FDC2E2
-:103150001E37CC07D6106B03FA6869FBD171B4E354
-:103160002423C89660DDE34B207FB30ED787490B3D
-:10317000EFC087BDA1E88712C021B5F7FF5EC2F797
-:10318000DF6706EA61962CCA45FF11A74AE7C3A686
-:1031900019AC15F175A2D18E37AF58C7CF2599DA82
-:1031A0003DC7CCDF221F9D9474BE3E01EF36C93C63
-:1031B0008BF35970BF9BAB6BECD3C1ADC8B508F7AF
-:1031C0008F08EE0DAD2C99AD8C0CF715CC74CBA3FC
-:1031D00086C373969959999ECF0276CDF4FC7237C7
-:1031E000AB447BF58494155E5F8AE5D03F7E0DF895
-:1031F0002AF60D5FF87163385D4C957369FE666160
-:10320000EF16B64B896CB44F9987EC57D6F390E91B
-:1032100041B926445C4B9B7412D7CF3A1ACDA427F0
-:10322000B55E66482CBDDDB97D6F73537B4BDE58B0
-:1032300072CBC2A725572CF965E1D539FE48720635
-:10324000C753F310FEE824399D4E74C0C70484C7E9
-:10325000ACC6FDB3F60DDCC898A77AE47DB3E414E0
-:10326000B463E8FF8FB45F8027B2EB5C6146787A85
-:103270003738B4F42958F7401BD7D7EF1631B20FBF
-:10328000CFB45D359083F8F1782A103F857C2A56BB
-:10329000181C5A87F2D5A726FA11AE42A1BFBC8CE2
-:1032A000EBAF4266ECB81AFDFBF6934BB09DB53F11
-:1032B000B9627F9A617FD01F69F60D15A39DE44620
-:1032C000BD06EDDC2077512E17B6BFFF1FA8170BE8
-:1032D0001D7A112161E9706455EDB8DA481FFFA32A
-:1032E0008D685F5AE35287F4FD0F6A2711BF85EDA1
-:1032F0009BEF5602B6F1A58F110F426EA3D9756EE2
-:103300009E52B457E5843B90A20B275C56BF91E8D0
-:1033100084A5CF536EAB933DE1ACBBC39A4D3EBF8A
-:10332000FBC7F29C56DF79E8CD399E93BE9D7C2089
-:10333000F0F029E87413A7532E172CBEFDCFA2D3AB
-:10334000A8B5AFB1DC3B8EA07EEDD2C2B30CB413F6
-:10335000867EC8ED04B77108E92C266555C2FB6866
-:10336000874A76A36557F4AFFDEB2D65F0FC44ADBD
-:103370004C7EC489F59CEEF73CC0ED514B6F478500
-:10338000DE46BB00F10A76C3809B971E1CC7BFFEBA
-:10339000E65209E0F61843FD6E6CDF6690BD9A5365
-:1033A00017D71BA18C571CF28C3352722919CBCF23
-:1033B0005B0EFBF5AD5C635984ECEBE8E8B9FED439
-:1033C000FB1FCB5C3F4D2B6179B361BCE45639FCEC
-:1033D00020F44FBAEC7ACC2AD7285C5F26BDAC0427
-:1033E000FDE091DA0D29965ED535DA97F903C771BC
-:1033F0009F46DA07D8019DE298E7E890E31DE6A131
-:10340000F1937EBB1E3A29F49005FF27D0AB0B8BBE
-:10341000813EF64A99E1FE488C177D0E0080FD8EB4
-:10342000AACCCCD4CEB9EE7F10FD12B24AF3EDA8EF
-:10343000D8391BF73B1653C2E9FB61957FA170FD9C
-:103440009933B721B711DAB1F599DBE589768FDDCC
-:1034500097B508FD2B409D8AF19A504C9F371BE38E
-:103460009153F326A18FFD63D43F30EFEEC819BD11
-:10347000C5F789F051105246C6C79BB2CCF7D1C1EF
-:10348000B77BC05D43F999943C147F6989B933F2E5
-:10349000B125A79CF2C8A9E724D3646DD5C3E58AFA
-:1034A00035EE27D567201FB2945129BBFD9C3EBB4A
-:1034B000587A1C410E94C82CDA97C13FBD5AE17866
-:1034C000EA8FF138856ACAA4B7662A4D4C023C6D72
-:1034D0000832920779B8D7C8B70D2C0E2860F92C9E
-:1034E0003CE0437912945982FC56A71F6836A11F0D
-:1034F00018E4A0317D54597F213C0FCE5F49E70C81
-:103500002CC2E5AD0EFF713E32495FB8055EA3B136
-:103510004914E7CC6BB2CB7137FA81201FF506C78F
-:10352000F3F933E9BCC1CDD29EC33AAE52FCC1D34C
-:1035300060DAB36A5683FC59BDFFAA5D8B61FC9AC1
-:10354000476E7E1BCBC907EFC9FF1294758FEFBA88
-:1035500019CB92D7A26333C553AD123885C9750014
-:103560009F8F19EE9C91DB19EB9508DAD5B08F1D72
-:10357000480FC9587916D2F72A85F37FFF022D80AC
-:10358000F119750B97ABEA7C401ED13FF7D39B53E3
-:10359000FE34F915AAF093947685E20849BD8CE2D1
-:1035A0002D87B6C81A96206763388F357FAF88534A
-:1035B000778A78AB13BEDE92A162948327D67F44CC
-:1035C000F6A1A2678567C37C5D7E5642708878410C
-:1035D000B3D8BFE4DA7A4F7ABC48117E4EC7D139EE
-:1035E0000306D2C18012F61AC4371A8E1BDD329D33
-:1035F00061FC65961E66684F740ABF47F1990CF727
-:10360000355B6733D1AF85575A08FB57B17002FB62
-:10361000B7F7236E61BDE6EDC8073FB896DB2127FB
-:103620004AED721B48A80BF694CD2A5AAF226D368C
-:1036300005275D8534FF7BA540C8554EAF6FD44E3E
-:10364000796C1BD0C1736EF31E65D427E023875CB1
-:10365000FF01B009EEDBA3925D9E5BE541271FB53C
-:10366000496417AA265FE74CE5C346D4931BC16E95
-:103670002C3486F3CBC6D719D98D1B81FF62A5994F
-:10368000F8A75A421971B1FC93D79E2B611CE3B382
-:10369000F2CF5F2AE29C4EF00FD05902ED984725F9
-:1036A000A3730AACEF3BFB1A7F3C055E3F7B604592
-:1036B000F635507E2FBEF1FA6B60FEDB1FDF938D77
-:1036C000FBFCE8ABC04FE7F1E32D7E6A461BF63CFE
-:1036D000713663AD9D9F8CF515C44F6F295C7FF5E6
-:1036E0002FF8DD1B57FF7F7E3A1F3FBDAD007D4E9B
-:1036F000FBD3D9E2E879E45B7311D3D0DE823626BE
-:10370000D27934682F7D6A16E17B9D8BCB31BFCB9C
-:10371000CBED8E107FEF1CEF6FD44F1E3F5850FE45
-:10372000D9F9749DCFFCE8F3E077903B246F4E8C81
-:10373000B3F37DA78BD3DDAF5C9F787DEF7CE17326
-:10374000581FD8F564DF5DA73203FD80892F7848C4
-:1037500058BC3A6EE311648969F03C94C7DFBBF34F
-:10376000485EC6D18E19522AA9BFC9B81DDF54B30D
-:10377000F9083F9718AC5804FEF21CF817DA23D763
-:10378000F9B85F01E3B0108CBFDA1B2D5647D17832
-:10379000E45FBEFAFCBE20CA97D73D66093E674982
-:1037A0003517CF072CBB63647E57D9E9343FEB69EB
-:1037B0008D111CA72ED5285E89622C00F5ADA5972A
-:1037C000529C928563C725AC8FD219CA71251859AE
-:1037D0004C76489BDB9805F5AD6040C58244B72424
-:1037E0003795F6DE5000E500D825F85E8DCDF568FA
-:1037F000E8BF8C923108CDDC6D1F91DF7DA298CBA4
-:10380000DB8E298CCE69061EF8B7A532DA3BED6E49
-:103810003AB700BB91F8352AE44632383DD4827E6F
-:1038200046911696A0BE29F68BE35FE3F2C4F44CF2
-:103830004E8F8FF078474B88FBBB4EBB6FF3D72F73
-:103840007BD3C0F17EF85AD7E550BEFEE4CF5FBF10
-:103850001CDEBDF1ADD76A30EEEDAED36C714737EB
-:1038600033DE447B0B7CA68486F2397672096E6661
-:10387000CAAF9362889F688D3F8EEB45DE46FC247D
-:10388000A728FC7C11FE42005F40C0D71D3C554577
-:10389000F3C4DEFF8F4CF29EFE260B3D02ED36E7B1
-:1038A000DD1F4739929A6F12C9A728C827F423A3AE
-:1038B000BE9E256B683E7FF841ECF347D8D5C9A979
-:1038C000F3C2435BE6B5209EE72EF0E84867EED8EA
-:1038D000E6BB91CE9DEB3CE37BF0520CCDD9E607E5
-:1038E0003E715768A697EC5F7698F64334B1E0D600
-:1038F000418160DC01FA2F5BC132F437A03FAE1387
-:10390000E419DADB563F206313D77BC637FD528AB2
-:10391000F78B7885D5EFA69844E7043795031B9479
-:103920000FC7D3069FFC93AFE1B94B4CD1154E079F
-:10393000A18A34BCE19F3D6EC6E9E2B27D76BD0B43
-:10394000F32F2CC5F73185E8C5C92FE3E3F6F61B45
-:103950007CE73FD71FBE9F1CCF1305BF59FD2DF835
-:10396000085E29537CDD7E2E73539DBD3E77183E45
-:10397000CE0FD774D57E6ED3E0B38F3733687F3FD9
-:10398000BBC85EDF80F19B4FB26E07DF3D3DC6FCDA
-:103990008EFA19FC7A4BEEBEEF89FC2D8DA38619A9
-:1039A0008ED3BF60EFFC794007853AB73B0AE72F1B
-:1039B0006CC8AD4139C5449E4966FBA350E87BA560
-:1039C000FD252507FD5193B74F2E796B460E9E17A7
-:1039D000D7313A4F8FAAF7C4728C943DD2AF966715
-:1039E000219E3F7F7BE46E6F7ADE4DCA1E79E055E3
-:1039F000A326833DA2DE239930CEAC25608F54A54B
-:103A0000DB23AD12CAA0EC25608F90DD117D0FF194
-:103A100035925DF263CBBEF767B6ABFFA0723D0B8C
-:103A20007AE69F3E8B9E19E735FF45FD1CEC8169C8
-:103A300025C6CA48063AFC40E5F10E4B7F36061310
-:103A40000A9E9D83DE545DF0FCDABAE44B288E3B7F
-:103A5000F49D415C37ACC7E5AAFDF4EB39A372785D
-:103A600026AA3C0F66A47EDF1AC15FF16A5E61B7C9
-:103A7000D8F7BB7FC13BBA8CFE0BF831E8BF247D81
-:103A800065DB302E7826A652BC4E9DBF72F75CA433
-:103A900027B0B3393D9FDFBEBE7648B6F1F1B4B36F
-:103AA0005936BEAF67F673BA191EFB395DA36E3F78
-:103AB000A79B15B29FD3CD31ECE774D757DACFE986
-:103AC0009CF6FDCCD1AEFF9EF67DA891113F5DC066
-:103AD000BE077EBA09E969247EBA2EDFB83F92613B
-:103AE000BFAB356EA7AEF6461620DD4D33B85D1779
-:103AF0008DADA77CC0BC28C89B528A1B52DCCB8AE8
-:103B00006B59712F2B2FD08A6739E35756DCCB8A3C
-:103B10006349311EB76AF6445720BCCDED27659442
-:103B200023FA73300F3282758E372C3EC7E5414B36
-:103B30007BE6B89C33FE3662BB4FC9579F837E58E5
-:103B40008FEBB5F403F0F9839F85CF416E6DC3F120
-:103B5000FE05F97D14C9936EDABF0AC035DAE9B003
-:103B60000F1AC6E9179CDE8FF138F5B89BF8F6629C
-:103B7000FD5F4C749061D3A2E083633C2B1A2B252C
-:103B8000FD62F18DC5274EFF78187FFC57F3CF45B6
-:103B9000FAC7C03FDF739D471F017F3C8FF89E56D9
-:103BA000C9F1EBE4078BFE8124125235EE773481A4
-:103BB000ED2D7A672F864D8473A2F06B4E8CD6C89C
-:103BC000BF38F1FCBFF373D8E73DE171628DF87E39
-:103BD0006277417C5B698ACF2C7E6AF7447FEC4A2E
-:103BE000CB03B1F21D0F7BCCD7F17948ED4BA0BFD1
-:103BF000129ACDC21B0CE2B363FC39E7535F9851B4
-:103C0000FCF433FB657B5D713C1F6A91869632F252
-:103C10005B99867CAB0A79F26256F424E2B3797A36
-:103C2000A484D3D3D0381FC0F58B0E85FCB5CFCA82
-:103C30004FCD23E1FF1C3EA243AEDAE1F901E97268
-:103C40000BE55B28A4C5374819E495C0579C85C788
-:103C5000E0FA603FFF1DF19857C5245A8EE0E366F5
-:103C60008FF907D767B33F14AD36C5C780378F8646
-:103C700072B11AF0563E1C6F275D7CFD4EFA0BA9FF
-:103C80004919E93F0472748394764E2AF062AD6755
-:103C900024F96CD169DA7943484B5FEFFFA372D9FD
-:103CA0009297977BA293711FDC6644C83F93F6D727
-:103CB000296786DB41329D339E01BB07BB5DAC7C2F
-:103CC0009D76D68B87256CEA5985CA6BCFD2E109E0
-:103CD000FBE2D96C2ACDB3F954D69FCDA572FAD99F
-:103CE0004BA89C717634950D67011830711ACF96E8
-:103CF0005239F3EC1554CE3A3B9ECAD967AFA2763F
-:103D000073CE4EA2F2BAB35FA0F2FAB353A874DA3C
-:103D10003FC67A95E4B725BF2CF9EE94DF96FCFBFD
-:103D2000BF26BF630D1765FF80FEFBAA761EF93D17
-:103D300092BC00BEBE4F4B971329FD7CBFF619F80D
-:103D4000FAB8E053E0DFF7300EE3012F8EE2546162
-:103D50001EA70A189A81791AFBB0096CA9BF3472A0
-:103D600012E306CD0B3C7A0CE01E28D5483E6D0BC5
-:103D70006A74EEB659D2477379904C20FDED0C6908
-:103D800034DEB63F2A5ECC5F7869544100E7E9F63D
-:103D9000CB3AB6FF566E72DF2D788E3F85850FC108
-:103DA000782BF6ECF1A4FBE1FBD13800F802B1A7C7
-:103DB0001903BEDE38EA774B713EDF5446F118280E
-:103DC000CD4CF962DF748BF36975288478DAEA9355
-:103DD000491F74EB1E91879A1C68413FB74E66DB02
-:103DE00060DE0DA3DFD98260ABE3CA7694417D67C4
-:103DF0005D991737E9E9573E08913D01EF10142806
-:103E000013A23473607F3ABD61E37CE76D8A31B4FD
-:103E10000E8915FBBBAB476EB7C93F1042FAE89855
-:103E200034B9F21698BF7752C1689C7F7BCD511B85
-:103E30003E14DD1E4F5130E0887E785D92E26A1BB1
-:103E400064634719AC2F20F2AD01CCCA485ADE8119
-:103E5000058712867570B8120A5F0F2B80E7B97557
-:103E6000895892AFD7C4B8ABCF970CA1BFA8D49D47
-:103E7000A6785BA73FB988EA0E38ACF17FAB5979D9
-:103E8000019C6F7C826F9A277D7B11E5915769B405
-:103E90006FDDAEA105588FAD75B1C733C46F36085D
-:103EA0007EDE5679FEB88CEAB3C3D1EDB5FB8B1636
-:103EB0003CEF8BD20947B36B6854A6FDFBB4F35FAC
-:103EC00068DD9FF77C9D23E40F5CEEB6EF4340C8AE
-:103ED000F3E629DF0EE1B9B8054FA704FB50F3F96B
-:103EE000EF43F3142EAF3FEFF5FE4F1BF7F71A8F9A
-:103EF000AB009FCE2EC738E398C9218CD7FAAC7897
-:103F000074384EF949018C47532F83F490AAF3314A
-:103F1000149525900FE5EC0F13B84F4AB566282489
-:103F20006733EFBB12DE44796D4EFEB4E0A6BFC925
-:103F3000C274A0F343AF159F36D4C9FCBE04C67F3C
-:103F400015669DCFF2F8B4D55FAD90291E4D81EC7A
-:103F5000B47154D0C3788EA3609C3A6FF8FCDF4DE7
-:103F6000D1A37DFE221E1F5754EE07BE27717CC4CD
-:103F70005E5528DFB3EB792EDFD87146F2BBABD6A6
-:103F8000A073951DF03FFA0FB15A5F1CE95671E41A
-:103F9000E39DA99C1E42396AC5C5693E7E3E4071BB
-:103FA0006ECC53A4B8B9C12AF07DB700CD1A47B57D
-:103FB000E2F2956B26613BBFC13CCFC1FAFC752C88
-:103FC0007109C01B74B76EBDBC34433CBC72CD37A5
-:103FD0009E8479773F35FD574F427D971C7EB50E05
-:103FE000DAE57FB98EF0EA8C876FAB944D1DE583DF
-:103FF000CF7708F7156C68A28B5B7BA4183ECFF6D1
-:10400000F90EF2FD6E0D298817D0938817AF332F64
-:10401000321DDF6508C7CE8179F06FEFD679CB709E
-:104020005E841BF32B57F4D66BA867824BECE71723
-:10403000FE267BDD5B658773ABD8BF0BD1BF330F2B
-:10404000B1C79CB708E9F64C5063286F36AEBDFA8D
-:104050004692FBDB1536AE3403FD3AD6D5A9B948F6
-:10406000FF771BF57B2B506F346894D7D31DF7C6B1
-:1040700031C57B7B5DEADCC466BF1B1A3FC7AA91D2
-:1040800013EE4C76BC381F0B8867CC710ED63D5BA7
-:1040900026BBA6BB87CF638DD75DF79607E5C448DF
-:1040A000E33E3DC63CE2467B2A9A7751F72EEEDB93
-:1040B000E8E2743D458B4BA5688FEA0B17417DF311
-:1040C0003899EC2126FCBFEE6BF979E2C39A61BB0B
-:1040D0005FB169CA4AB21B6E72EB82BFC02E9C9060
-:1040E000BA6F71C06BBEE086E7EA733012D803EF97
-:1040F000E5866F44BA680C7E4476D4AD45B28EF442
-:10410000B5624F23AD6BB32EB304DABD6A2B19A988
-:104110004DACD5C4F3004CD444BA9B036F64BA17BA
-:10412000913CD40970CE195738691BD4DC45AD9445
-:10413000C7D26848E4875D07984179D0521C51A5E1
-:104140002AEC37FF1DB4FBE6044B65F4F7AF535977
-:104150008396669F835D7CCC9DB6AE13E3F604E543
-:104160002A9C1FE6C1F91779E83E811BEDE32B532A
-:10417000F6F14444649A9DFC6B342A319E5194F8C4
-:104180003DE5797F3F29E3BCEC0556BD4DFAE47E61
-:1041900035F897BFC4FD8C33A31F530D3F6B5CE212
-:1041A000EB9AD827716FE5B027F21B1CDF8A074C0A
-:1041B000D4F8FDE6CD2D2C1C4B8BAB6C7EFECF8F47
-:1041C000A3BD6AC55FCEE5DD09382DB837492C8B14
-:1041D000F4BC27FA0777BA5FCC926573277C7E70B0
-:1041E00067C897F3D5023F8D15FC93575BE145B93E
-:1041F0003916F37D701FDAB93C31E1BFF47C1F45FD
-:10420000305F30DCDA2F1BC3E59222EE4D015D4BAF
-:1042100068C73AF38114CCFB99385C6E1C10F47FAC
-:104220008947E4FF4C6693B91F6E3FBFF22FE57AD2
-:104230009FB5E665BC87FA7DA1F75F147E6542DC19
-:104240006B3C2AEE2DBEBCCE203FEF957595540EEB
-:10425000AC0BD3F3D7D6D55199BA5FC5E7CD177656
-:10426000988A41353CE7F7B1B801F0FA47AD192813
-:10427000453EAFE3F7BBBB9B4E6D2927BB919F5BD0
-:104280006C2EAA4E14A2FF02B0E643DDE5EBF3F07C
-:104290007B5EE6606501577388F7FFEAF30A275DE6
-:1042A000E8D6FE3BF6DBC75A19CABB8069DFEFECE4
-:1042B000B0D3BFE1FBEF2ABAB87DEFC57FC03E7E29
-:1042C000C9DAF7ABD9D5FCFB0C17278F918F2A855C
-:1042D0001C1803FC7400FC79B7C2F3D5F3799EABCC
-:1042E00019E2FC66AABC1E1B2FDABB3809B1813C5F
-:1042F0009ED75ECCCF13A81FE695E37B0C4BBEC0C8
-:10430000E35B2C47E4BF8F15E3AC16E34EACA67B12
-:10431000BBFCFC9FF5E958FA5892EAB9C007580669
-:1043200059AB84C81CC306C9DF2E9686A86E487A8E
-:1043300016D6CBA47019F7C3E3A43FCB15F3DB1556
-:1043400084FC88CCE345C9C5644F825E46B91857E2
-:10435000238B50BE6C68D3C28089737972787F0ECC
-:10436000CB0D7D350378FE118BC9247F94E75896D9
-:104370007E25D97BA4BF36ACCF3B984DF91A49CAEC
-:1043800073DFEF29B5E9A989BE85D7E9B05F1B4581
-:104390003E9D0BFAB30CF9A7563E1D8C5B92E9BD0E
-:1043A000556EF46B8B32F9FD0F7B2411CF488EA62E
-:1043B00038A0D8D7F85439E37DC67D1E6ED73C5A55
-:1043C0009AD99E66EC411A6FBF47778C9B6CA1FB14
-:1043D000333A8F6F64B94CCAAFD9D8C6EFE95BF8EE
-:1043E0001B0D762DDAC31BFBE6CF46FE8E55AA9435
-:1043F0006F0EEBF721FE5C222F79E3F8E0C16C1E13
-:1044000097284539DD8FF8AB4DC35F706513E2AF78
-:10441000E3559EDF0BFADCC732E41B5AF873F9D878
-:104420001733BDB7CA8E51DAA24CF7868F7A2C3B70
-:104430003D59CAE984E32FEB5A3592A97D42E0BB8E
-:10444000A48C45CF87BF7E8F6E1BD73AF755468821
-:104450007749BE04C5B9266ADCCED8B098E375C3E7
-:10446000F3D71C8FA69D43FC12879C928A075B7131
-:10447000634B6FB67BA2FFE81995D297ECFB8CE4F7
-:104480002E7BC17310F72DC339C4294F6D867388F5
-:104490009E8BFBBECB58C1B787B61C9D87F3FC55DE
-:1044A0001D23FB2AF00C9F37576771B914BF536067
-:1044B0004A1867B926A2D7A3FDE66A6726E6CF8C1D
-:1044C00015719BC2F63E05E922087B5928E1BDA67D
-:1044D000640CBF67327637233F512D9CB96ABD21EA
-:1044E00044695A7E94C286FA697DED9AF1782981F1
-:1044F000F553D40F63C4FB40FBCC5FA1DC1C1389D4
-:10450000521E2EF48BF9D1BE10782CF072BE5DDEF7
-:10451000109624681F0C26293EE994EB63003F9710
-:10452000A4D96F015167ABB89C96E13FD4F3F91160
-:10453000BBDC1EE7B8171D70E4BDE47A45BEBB25A1
-:10454000B78BF8A64E5007E54C7E794ABF3AE04358
-:1045500019569DEA1FB0EA9F113E2004A2670B1E68
-:10456000BC4A8972778F4BFFCA53A89FEB359E4791
-:1045700026EECB650BBCFBD061867603535E3171B2
-:104580005F7784F97769CE4C9D477E68769D759FED
-:104590008EDF5786328671BA6C31BF75AF2E9B198C
-:1045A0006F96033D649B49BA57A75BDF55305902AC
-:1045B000F370749F4C7974BA2F42F2A9678147C790
-:1045C000EF7C68E29E9E4BDC1FCF364FD3FDBAECEA
-:1045D00061EBE3F7EB2CB8B3B3AADE2C376CF3AC8A
-:1045E000C7F836AC7D74C6FB7575DC4FCA36791CCE
-:1045F000226D7CBA5FB7636A99ED7E1DCD837E9C88
-:10460000A03FEB9E9D13AE73FD6A32DB6913C27649
-:104610003BE242F7EB5C217BFB1D17C8CFFAC4F7E6
-:10462000EB041E86B573D8832ECB0E1D2533DCBF5D
-:10463000330D327D4724F7A3646486447109D2F7B1
-:10464000969D97C787FA6F67E7E55979FD0E3BCFCF
-:10465000B2DF7267DBF1EDB4FBDC5511EA73B176C2
-:10466000DE2EFC07D0CB435E879DD794993E9CF20B
-:10467000229F0DEEBE12C6395AFB2305F3D576E50F
-:10468000F2EF1FB161FEC15B33685F7CFC7B47BB0F
-:10469000A6F4ABF8FD9BDF2D656427597104B78044
-:1046A000795791BC9EC2EE5D0F117E82020F4DF8CC
-:1046B00001B21AC2557C1CF199E9C5BC85FC26469D
-:1046C0008D0A2BC2B4EFF85902992E6DC554D4E36C
-:1046D000F58895343CCDF0D8BF13D0A8E73BF6D190
-:1046E000BECFE7CEC11FE4DF539863D8F7DDF29366
-:1046F000D09CC5F9AEAFB4D3C1092932A84097A761
-:10470000B34A85FD33A8A3BEEC5EEB22BBF1A12525
-:10471000655BAF447F3528EBFC3872681CDA47CD07
-:10472000474D2FDA79DB23D3BDE3E0FD431D4A1863
-:10473000CDC3A796AC7915EBB1DD2EB2839EEA9B73
-:1047400057B0228DEF36EF5EB07031BEEF70917EC4
-:104750005FB1E7BE81D220F677D5A67F6FAA65E369
-:104760007D3AFA6D6FD47A33DA31576771BB64A33F
-:1047700096A4F8D3C6791A43976B6349FDE8156888
-:104780003F5CA365BC4F7E57969BDFE773B54A2815
-:10479000DF0BA399EF0558EDC6D6FC96CE3182B358
-:1047A00065867E9CEBFA7932D61F827DD5A5143DB5
-:1047B000E5097ADA5874EFD60A5CDF40E67B875663
-:1047C000B9366B1CA7D3889DCF5D854DA371DD2EB7
-:1047D0007764A01E89AB50D6312EE272B7466E4682
-:1047E0007BF46A175238DBDCF1C38645B82F614988
-:1047F00097609EA01A59457416CC62A80F1A964469
-:104800005A112F85A0FF30B45758F44B3AA728AC63
-:10481000D39817EA9E253D0917BCF75444AF42BC14
-:10482000BFB4967FE7A530E8A37B4185117E0E5784
-:10483000D8EE6668326C0417D845FE814471222791
-:104840001F59EB6A5ECAE5F8EEB5BF1D95E97B33EB
-:104850001559658457AF615FB707F52E8C33D51CAA
-:104860005C42F8AE71B338F1AF9BE87B57AD8BE09B
-:10487000DA35E5E45710AEDFFD3E8BF6FB5A664AAB
-:104880000857FE103F67B5E6C96F1A54783C9CF391
-:10489000A193EF2C7E70C2B773F63C3A8FDBCC0647
-:1048A000E723BE636765A2A3CD456BBCE971D15612
-:1048B000417FB00F245F623AA3FD56FE95ADC77CE1
-:1048C000D88D5F8C54227FBCEDE5F756EF5BAAD103
-:1048D0003A1E9AAB51BCF1217F2BD1FDA98DAEF0D0
-:1048E000210447D517E27EEE2EAE0863BCEDEFF053
-:1048F000F039CD3FD83DEA4B9588CF2FFE218B8FE5
-:104900003345B5C6F919D17BAD97E09CA1B4FF6CD6
-:1049100005DAA14BE4C9943BBD6A09C92F9790E31E
-:104920002F2FC9AB473F2570C372C6E5218F5304B3
-:10493000D656F3FB0C0EB99FA85377CFA05DE2F1DA
-:104940009F7A21EFC6DE30BD1ED7592FF482A966AB
-:10495000FE2E63AE685F381441936C58FC2757E80D
-:104960008FB1BB1DCF855EC81D16071FACB819E4FB
-:10497000CF97B2841D3942DC67D79279C40F678024
-:104980001F282E5D7292E83F067202EDE637A4649E
-:104990006845DA7998F59DB99F887850C42CA53C74
-:1049A000E1B7443CE8A7E2BB73EF8878D071110F00
-:1049B000FAB98807FD03C683F0FB61DECB69DFC669
-:1049C000D57DD48F719C9D350B3C068C33551F7C57
-:1049D0000981FCA239E813F9F7046FD0D24373CFF1
-:1049E0001FA74A205C6E8C4B71385F16DFA37B4596
-:1049F000C03520E07A4DC065E941941B48676CAC36
-:104A0000AA67928741B555C2F35E9417FD4192178C
-:104A10003C4F3CB84632260C971330DEE8743BDD41
-:104A2000A2BF53A37C44C7CEF11FCDE2F70E5F5A5D
-:104A30003B6B3F0BA6C9A3C8C2554877F9B03F28C6
-:104A40008FA24D5C8E47F1DE459A5CB5E269B023DA
-:104A500061D23B37703C8D245F2E24570A1D72654E
-:104A600037CA15A8EF46B9124C972BADFDB8EE200A
-:104A7000CA1596D243C1C827932B3FF396D9E22497
-:104A8000967CB91AD898ECC430E853FFA7D7A76F23
-:104A90000B397121BD6AE57F044C467A7D0FE685AE
-:104AA000A03F339ED13D1CC51CA47CA2DC7617C35D
-:104AB0007C90ADD86534FA330B291F64C77C8F8E88
-:104AC00074F1B09408213EF7493D5EBE2F7A3FDA7B
-:104AD0000BDB26F038C98E3FDEE3453BFBA5DB0B45
-:104AE00002788ED39B6BE581E88B6F85FAA94646E9
-:104AF00074B262CF0A5BDEC3CFB3F2081FB9319044
-:104B00003F808F876FE7FA4737781E089419F34084
-:104B1000DC3E110F526321A48F6D52D4437198462D
-:104B200099F4546F98E7AFF4825F8EE783BD0D3B35
-:104B3000E7A07EDE70ABCC285FBCB2E71E94331DCD
-:104B400013161AC897AED1656FA239BEC1277BD3A1
-:104B5000F348F13841ABE6E786A2347300E4CD5E5A
-:104B6000D338DFFD5155F87DD8DF7D9E3CF8CEDC93
-:104B7000D0688C13F4362E0CE1BCBDA322A13CCA34
-:104B80004F1943F6C0C6519B1663FCA963B9C6D240
-:104B9000EDA461F305EDF6B51567541B78FE488763
-:104BA000CCFDCB5C713E0D7C5589784B5F27C2A94B
-:104BB0009A3C7F04D7ABF0F5D2F74D731BC03FACE6
-:104BC000E2EB47FF55F7E9A3517EA80D3C7F64B3A4
-:104BD0005F5F8C7EA3130E6BFC6BB3259B7FA45B86
-:104BE000790BF56BF8396211CF5BE8759D3F6FA1CA
-:104BF00043C843CB6F1C091F2EC73975AFD71E079B
-:104C0000B4E0B952944E3846CA17F8B4F35F68DD81
-:104C10009FF77C23E511ACC9966CF72B72AD7C969F
-:104C2000C635219413163C9B2F903FF269E16A6EC2
-:104C3000E4ED3FEFF5FE4F1BB73E9BEB47E0D301A2
-:104C4000BC47D931716608E5502A1E3334508EF6C0
-:104C50009CB8CF68E58FB874FE4F55E5DFB993B3C4
-:104C60008BE83BCBEA749E3F427F19F240363136E7
-:104C70001BFD1D55C46F9C7C7A21F89D792337FB61
-:104C800084DF1875CC27F2449823EF440DF1FC1211
-:104C90002B9FA44B82F50553F92023CEEBC0DB7884
-:104CA00021F7DF73F41FB6EE30BF5F69E59F0CCBD1
-:104CB00023992AEFC72D18964722F2517A728D3820
-:104CC000CF13E77925A836319E372C8F64EAF4108C
-:104CD0007E53725A89E87703A3EFEFF67879BD77B0
-:104CE0000E8BE3F7CE7AB18EFC54CB28AF65587E9D
-:104CF000C9D43584278D4596F1F31D7EDE6FE1C161
-:104D0000995F72417ABB401E49D0677D8F2242F382
-:104D1000F4F8C33FA923F8643A8F2FF8D2F170FA60
-:104D2000F897F8B89CEC1179783DB9F67CBCFBC4D7
-:104D3000BE548876CEFDD58B385D77D5EB1477776A
-:104D400037F078E5B0EF40D4D8FD01673CEF8490B0
-:104D5000D7175ABF33AEB76D84FB660B7C3C8FEB25
-:104D6000A12587282FF6CC2AD0B380AF87319FA505
-:104D7000E6E2F3595ECFE2F92CBD46FDC24B518FFE
-:104D8000453586F2B417F359E0FD868611F2594491
-:104D90003CD18A8F8E94CF927BEE3CDE9ECFD27B2D
-:104DA0002BCF67E9EDE1F358E3F53654939D35D207
-:104DB000B84F8F31651FEE7FC5C59D9F4E2B89FC77
-:104DC00019E6AFF4946AFA8306D20BA7E7AE468DD4
-:104DD000E8BBCBC5FDD8D868EE3733351E5A086D11
-:104DE000B6F8138B289E2CF2327AC5FDF9BFCF326C
-:104DF0006CF67167E3774368D7031DBEAC733EA1C1
-:104E000071F2D5D2F5600332B7DE62A24F3990CD90
-:104E1000E308AED0B181BA343ADD22F41DE2470690
-:104E2000FCE44AE7F015950B28BA4F7F6B047DBE72
-:104E300091CDE7B7E890A993C2FCFC8F55A01CB1B7
-:104E4000FCD761ED3CBCDD30F9E390233D98DF8673
-:104E5000154B9EDC60C9133B5D5AF28339E4CC39B3
-:104E6000793287DBE9E7E409C80FFCD499530EF5E2
-:104E70007AB9BEB0E071A3600639F29E2B6C8BD379
-:104E800038E5CE85F8E8F3963B2F65E70BFB83CB3F
-:104E90009D20D206F24DB6758EC8EF3D9C99FA2042
-:104EA000C9438FCAD7ED8930FA9D00ACA33CF7E027
-:104EB000394A46B95E2D51BC419C8BE48BEF0F3EC5
-:104EC000EC0A537EDAC3C0CFE8E74D309CF6D9F93F
-:104ED000CF159CE7490FAFFD1AF7CF00DFE8775DEC
-:104EE000AC1CB2E4C487D97CDDE7E8CBE4705AF4AB
-:104EF0009546CFF47D018B7EAD712D3A66C8A00535
-:104F0000E7A15741D7188EA638754C8A631CC4CACE
-:104F100023B3C67BC3C7ED9191EE5759EDBE63F93C
-:104F20005DE7E2C17A40A77CB21EBA6FCEBA38FD07
-:104F3000CD61BBD53555944FA032CA278894A03F88
-:104F400073D867F78BAD7CB06925E110CA890DC2B3
-:104F50004EB7F2C8ACBCB4C3BE5CEB9CD9969FB64E
-:104F60006184FBD96F9EC3CFC57FFF04BFDBB6DA78
-:104F70006B3E8E7211F0658AEF39511E9A35EE77CD
-:104F8000059E5EF7984FFA3EC3FDC917B3EC7957FB
-:104F90009D3EC31117E0789DA8C7EAE93E5E94DF05
-:104FA000AB729EAB8F74FFD5796FEFDCFD5771FE4E
-:104FB000DEEC89BE4CF0BFC8F3DFF470F46027FB71
-:104FC000FCD673C06BFE04C7EF14FC3D2DC8EFED9B
-:104FD000BCEF89BE8DCFAF63DCAFB6EC9CC3D80EFF
-:104FE000FAFB5F06A90DF4B2A996D36B5125A3EF86
-:104FF0008F4F6FE5F51D4BF9774DFB5FE7F73EB639
-:1050000045F9F74CA15F9F0C78D9319EEBC3FD5554
-:10501000BCDF7EBCDF847C5AC1EDAE3C8CDE2B282D
-:10502000AEA3544EAFE9F14E80F70796CA1417DDD0
-:1050300023F822C04C8A736CABE4F3ECAA909F1067
-:10504000DFA359740BD43B67AF9C8CF74BB68B78BE
-:10505000CABEC52B9FC0BCBE0F02E582EE1274EF24
-:10506000B5E7F86D141F7968499EB412D6B8EF60A1
-:10507000E6FC962ABF2AFAC5DC229E24CA8486E56D
-:105080005653E4ADB632F13DF69886F1A76706793E
-:10509000DE6AF7EA678ECD447D5C29539E59D7E0DE
-:1050A00051EF65B8EE3A9ED753A426A474FFC5EB22
-:1050B00077713BADE6A8C7A81ADEFE99C1A3447775
-:1050C000DB01EF4A9AFF270B38BBD19F807E7B5DC7
-:1050D0003D0333A1DDDE717952CC48B51BEDE7FC11
-:1050E000D7BD4416DFA167F41D874EF39407E5662C
-:1050F000279E7F40FBEE1A2B2FB587EE65ED9D3383
-:10510000790EE6896FBB81074BBBC287C84FEE990A
-:10511000CDEDB2BD12B4837DD9D7A25D4FF7985AB9
-:10512000799C08CA8C71A25E4C0446BC8A733B4AC7
-:105130007D81793B1BFA06709EA23AFE7D8BA29A76
-:10514000CCFD5F08B8A9FF3E578CE29F23EDDFBF7F
-:10515000FA383E3BABF8790163718A4BED167E1746
-:1051600053A346FA77425B021C3F3B5DCCC478995F
-:10517000AF4E23BD2E870DB243FD603F623C6E9B58
-:10518000145B8CF921B1491A7B9C30627AC761FCAF
-:105190006E425E18E96F939408E1779563E3787C3B
-:1051A000FB686427DDBB3A00763485835982F4546A
-:1051B00077348FEE431D8D540F527F5F85EEB634EA
-:1051C0000AE6CDD38722199B74D9A6AD68D7744E51
-:1051D0009175CCDBEC94EAA3385E2CD7437164D78D
-:1051E0009479B47FAE517952BA3EBAD1CFF5C2D0DC
-:1051F00084C88D7E585768CAA95C8C5B6EAF7D658C
-:105200001FEEDF23F77B888E1EA91DBC1BE7D97F0D
-:10521000F6AAE351E24B7E5EF768EDE952B47B7685
-:10522000359DCA45FC15637C0EF46171058FA3A101
-:105230000624FB4CED6137031E8BDB3466A4E96367
-:105240002FE3E779F8E79B4C728FFE9E193CE569E6
-:10525000C1F196B0C4A5017AEEC1789625678AEBB4
-:1052600058A200E4E1FE15EFC4304FEE91890574B9
-:105270008FB248BC27C909E39588F1FADF78653D0C
-:10528000B67BB4BAC04079513C30340F954471D5E7
-:10529000698AB385ACFB1F5163FFAD449F327DA784
-:1052A000B238FCCE5FE03A02BE3ED273D09EE266D8
-:1052B000CE7504269AF7F9018FDF945A5F1D174CBB
-:1052C000F963F487FC782FBF975D9CF50F7395B455
-:1052D0007CDB121117D8240DCE26BBF4016E878F0C
-:1052E00065719273C555B1BB79BE6D94F26D9DF336
-:1052F0006EF79FD3AF12DDA3CE6F12F74AF8EFD847
-:105300009488DFB171D27D28945FD57155AABE2FE4
-:105310007A8AE8FF69CDB82BD3F71EF609B9B049F0
-:10532000F863D6F86373F9F856FD519DD3E3D32F94
-:10533000E75D5F05EBF9ABB6B24918FFDC31821FC0
-:10534000B732C0E92F7B002C1CD003FDAFBDE6C5F2
-:105350007C96A765B60AE5547D55C293AC12788455
-:10536000F1C91783F10F84BFED41B9F4D54025C1D0
-:10537000B5622A8F1B74563D48E740219DEB1DE422
-:105380004F94EFBE504CC2B8F7F21AA61F12F19616
-:1053900018E09FEECECB2C95D7BF3D97FC1CE015B7
-:1053A0007EAF067393268BDF9F28C773A24D778B42
-:1053B000FC5919F1DD29E601BEA5790E148971EEBB
-:1053C000E3F63FFA17D8BF5CCC535EF7DDAFA11E02
-:1053D0002FD2395DA4E0EBF3107CAD3223F8D4C4B6
-:1053E000ABE8876E9F546020DD1C0885DF6E82FA73
-:1053F000F2452AC5E3CB6B381C075A65FA3D207F7E
-:105400009D7690EE8F99A02FD2F06588798B6A12E5
-:10541000129E6B19AD7C5DD0CE8B72D108033C50CF
-:1054200037C4BACEC13F4923F88B3C83985B740ED6
-:105430000F2B713CA0DF9575BC9F3FD4B705E5D815
-:10544000F23A0E37E87782A728AC1D447D5F14E25C
-:10545000E32D07FC1C925270655B70D5C9947F5593
-:1054600054A31D443F385BC0B732CCE1E97FFDD483
-:1054700080C4C73370BC6C016FB6583F25EC16086A
-:10548000FD00E33DE54AD4E3BD9C5353987188CFBA
-:1054900046F12CEBFDAE56C003E0C72FE661BBDD45
-:1054A000C44FB0C4D8C732FFFD10232D6E51B15B7D
-:1054B000B3D5FD62FF58177F4E7E1CA9445E9785C9
-:1054C0005FB7B2CADE8FD5A4D5CBF07E19A7F7F5AA
-:1054D000D7F2F38E0313B87D847EC739FE463A9F18
-:1054E000623CD615C4F71AE9BB9276FBB8C5AD0588
-:1054F000D3513E140F3C3C4F86F514DDCB64258719
-:10550000E8593A27FF60BE6FAF49D0FDD9EC81481A
-:105510001ECABB92D6BCE9F8FDB7EC8128D5B3070B
-:105520005A4D9E7F062E4C1EE6EBA5CD538A729AED
-:10553000E7D3B156AD0FE55A6D3A9CF0BEE4E59E57
-:10554000B9D87FF3DDAF8C46FE2D70F4F7E470FF21
-:10555000A1F8656815C0F94FAFC5F6567C271B2129
-:10556000CEA3F2652C8B7D208FA12C11F97796BCF0
-:10557000E89CF0CEA4A84FD00FE5E3B144BA9DEF6C
-:105580002CA1FD78D13E269DB7DD696A3752BC69F2
-:1055900020C0E34D0161AFF630633FE9F71A9EEF9B
-:1055A000E1C3E7A03FFA6A8E4EA7FDEC6361A4E772
-:1055B000E2B63FB9D3E5F5CD8152710F3A4174AFF0
-:1055C0009564D1F91EF0317DDFF480DA4AE7AC7DD5
-:1055D00045FC5CF3E89C5724C467D1733C4FDBB2B5
-:1055E00097A7D72442F8BCEBD5E865C49F23D89F82
-:1055F00096BDE95CCF25F50F923C181B655E3C5FBC
-:10560000F3AF56298FB5240A7055A15C00922E0481
-:10561000F86B62EB916E8C28AF1BAB45B90ACAAB35
-:10562000C1BE5D3750FE4B576ADCAD1560D7A2FD99
-:1056300034B8DB7303DA2BAD608D18682F9EF2E06F
-:10564000F754BA5BA7E7239E9F8958F66542C2F1DB
-:105650008B7E6A92BD58AB6B3AC66126B813A3D352
-:10566000CFE90ECC79A79ABE2736FFE2F2C946D21F
-:1056700027088B9CA647FAAB8E927E79C23F9EF498
-:1056800090A5572C3D4223827CB945F0519791F06B
-:105690004824AF807701CE5B508E001DFB8BB83C59
-:1056A0000739CCE59CA54FEEE67ADF929F15629C08
-:1056B0005B50DE42BFEEDA27726F40B922E4AC3FA6
-:1056C00064CCC4F3B90A215F991A9370BE0353F8EE
-:1056D000F72A030E795AD1CAC7E90A31A227D04363
-:1056E00007916E0E1425E89EF881D6A352FA3D5319
-:1056F0004BDF055A930CF77F5C1D9783E3845CFDB9
-:105700008EDFE0F4E9E172F59CDE13F276AB79947A
-:1057100089EFC266CCC3FA7BA1CF7B2A0E915FB022
-:10572000EDD653844F2B1E1A12F1D0EEAAB7E8FD26
-:10573000F628BF07B0CB9C3E87E08F2CD728FFB45C
-:10574000E6E89C32F4379A966B68D79D0C1458E7BC
-:105750005FDE85684FB6AE22FBD727F6F1A1301386
-:105760007EA7467ED67D4BBF3D80FD43E0174906B0
-:1057700036EAF3B891CEF17B0A88EFE82075F6D5CA
-:1057800018F41D08E73ABE17E0DFA5F5479303E3D9
-:10579000685F65BAD2E3AB61E4772E07BF0E87DDA1
-:1057A000AD86BD13E0FDEE26595FCF52FDFF578059
-:1057B000E7A34DF4F37B0A3B179FDE8271BE9D4B3E
-:1057C000C577CE1CF0DFD7D8E751681E8C09501E74
-:1057D00073C6EFED57F9B3F8F7176AFA06D09E0FC4
-:1057E0005471B85E0C181CEF831C8F3D1199F8683A
-:1057F000D760B517F59DD36E7C24FBDD493CAFC562
-:10580000AE6F2E542F76C8FD09EEBEEB48DE7D53F9
-:105810002679C518977712930DFC5D8D9600A7A782
-:105820002A21AF3B5C89FD9857D0F1AC8FAD375240
-:10583000745124C6EC6C9533FE7EDAA180C2F77FEA
-:10584000F8BE73FB41ECFB93020F17DA7F0CB3A099
-:105850003DDD17DF34E60E94E3ADDC7FEE4BBC4557
-:10586000794745B31792DF73E4E0A5E40F14559927
-:10587000B6DFD7CC1EC16FADC8F19C371E30923C4D
-:10588000DEB7BA83FCEC7D8399EFC514E4F0BCB4B9
-:105890003E9097F87D9391E6D77338FFFD5340D043
-:1058A000DD9C77E87B19697AF665A16749DF16AB5D
-:1058B0002CA6A4E5394C10F873EA4FA6C63D97D63E
-:1058C000109D13FEF689F38B874C99F06ED1399EAB
-:1058D0001F205E611DA6A0433ADFE861710FF24D03
-:1058E000AC89E77938E19EE0972F6A7DC11CEE878D
-:1058F0009C9B4FF8EB13FD1CEE9DB5F7D33D4798ED
-:105900002F84F421FDE03F4ED37DA8675DF47BB684
-:10591000339E752530A675E741FE7B8BF28B5E8248
-:10592000F39F0FF3EFAB27FCDC1EFBB5CE7FAFE898
-:10593000ABEEC1EE2F407DE85985913D1907C505B5
-:10594000F47A5AD02B7B8ED7577A79F5CE83FDCB5C
-:1059500070BC55CFF13CCC3B9FBFEDC62F40FDB690
-:105960000117DD19B8F3F1F5DA18A8DF1E97FAB0C0
-:10597000FE9BE98C7EEF3396A7519CEB3781C18269
-:105980000580EF0FD679987119C649070BE6031EFB
-:10599000EE883F3D13FBDDF1941446B69DF1ECE338
-:1059A000AF8C06B8EEFC8644F95F5F39926DB30B9D
-:1059B0004FC352A6C1FB3507F9EF46DEC67A662211
-:1059C0003EEE7CBC977EFFD0C2E707EB2A9991F6AA
-:1059D000BB61777EE369FA3DC3BBBE25D1EF2BDE09
-:1059E00025F37B44FFFCBC77D1633E5CDF7AED524C
-:1059F0003FAE6BB386ED6E8BB77C17539AEE881F64
-:105A0000D466C2FB3B0E1CD456A25FE666CDA87FCF
-:105A1000BE72E40A9BDC39BD4F21FF604DAE87EEBC
-:105A2000D7339F199A3761F83E7FB08ED9E0BAC359
-:105A30008A13A8716D6E5A7B97CEFDDFAF1C516C37
-:105A4000F3587640EC18D70BB1BFF553FCDCDABF46
-:105A500035C2EFB6F66F8D15885787266782A71B6C
-:105A6000F703E0E959A753B9735D88CADDEB0CDA97
-:105A7000A7BD884728BB04DC81A9AC1EBFCF1F305F
-:105A800079DA715E93598F77CBF222BC5EB0244AEB
-:105A90007EC848768C55EE75455BD087ECDCD13FEF
-:105AA0004B05BB67AF16BD1B235F7AC7ABB31AA00C
-:105AB000FE3739918D39246FC206F29DE59F7F3DF7
-:105AC00087CBDD4DA335C2F7DEA5931F532CFF0B0B
-:105AD000E37E4B573E81F604F4DF9E437C1BA6EF2A
-:105AE000748DD4BF60599DAD7FC1B25556FF3DD472
-:105AF000DF73FEFE7B975D639F7FD91D56FF4708CE
-:105B00007EDFF9E12F689E6A9FBF7935F5FFAA9B7A
-:105B1000EFEF50AE87F2E93BBCE1848BFC6746DFD8
-:105B2000E750F32E3D44DF4F3A17671A3451CFFA4E
-:105B30009ECAAD463996A2A3E9DFC475F881BBD2EF
-:105B4000E928A72ECBC657B9669EAD9E3F7B8CAD8C
-:105B5000FDA84899ED7DE1A2CB1D74E9D3290F96EC
-:105B6000717D6A629C13E0D4C6F0EF35D58FF1D019
-:105B7000FAEE7FD14BF5FBAFE1EBBB7F8C8FF89852
-:105B80007417ECFBFD5AF4CA74FB18D62561C8EBF8
-:105B9000193D3A90539BFEDC90F17996C27FC72E57
-:105BA000CBCDF5E5E6D2C98FC5D2F0B9A518E8018D
-:105BB000EA6FE768B638CFE6E295A196B479361574
-:105BC0006B8B0E55F1E7B7A01DAF47FE0EE7FBAAA2
-:105BD000367429DAAFCE79DC6575B6793C25AB68C9
-:105BE0009EA4631E77C92AC73C9E4587C47331CFE4
-:105BF00029A49391E6D95C768D7D3D2577D03CBF75
-:105C0000C6796AD3D6537287639E2CBE1E782EE661
-:105C1000F9CD79D7533ED5BE9EB1AB699E7F77CC87
-:105C2000E31EBBDA318F8FE6C1E7380F2BE27E949B
-:105C3000E61E5A49FBFF032FC33890E68EFE355D02
-:105C400052F97B2FC585A19589EDFE0FF9438DD2C1
-:105C500000800000000000001F8B08000000000012
-:105C6000000BE57D09785445B670DDBEF7F69274F9
-:105C7000773AFB420837801034C40E840CE0320DB2
-:105C8000411E3A80C1155CA0C3923DE988380F4798
-:105C90009D34041111B551D4A0C034080EF840034E
-:105CA000132040C006D4C119D438CF7199059B4543
-:105CB0008210930651F1CDE25FE754DDF4BD9D0EF5
-:105CC00030CBFFBF79EF8FDF4C51B7F6B3D539A793
-:105CD0004E55939C0442461172308EA62308F92635
-:105CE000C67DB5C34AC8F7F0F74342FFBC8424F32E
-:105CF0003485903984FFF9170BA490905A33CBCE9A
-:105D0000DE3C256B01A42D45692505F41F2B6CCEC7
-:105D10002B14423A5B8A8CB372C3FDA9E91C9F7CA9
-:105D20003298C3DA7E4FC2E378C7929C3A3A7E59E2
-:105D30009C03E7A3E64FD6D3BC899063F504D376E2
-:105D400099CC28A6DF4FD4D3090CD6CE7701B63B29
-:105D500029D17F26D17495E0F70A745DCB3F90C9B5
-:105D6000001CE6C31CBA8E3BF832E6F862093187A4
-:105D7000E7E1311117B40BED32F9D709F0D5D5C7EA
-:105D8000904693C64442D4F9F627E48FFB26BD2DF6
-:105D9000D831DBC7309290BB966C7D0BAA7D2494E2
-:105DA000F49D4BD73BB579B9DC87E63BE5E074A7BA
-:105DB00055D3CF54F918ACDB4CFF837EA6B9695E8E
-:105DC00033FEDDE5FAFCBD440AE7B309B9CAD19F49
-:105DD000E3838FABF865C0D71D744DE91485F74296
-:105DE0003A0C8A1D88AFE90ED6569D8FE72199049B
-:105DF000603E523099E4424932D673433DA5E7FCF8
-:105E0000A6CB665731C5E7F407458463E47C83FB82
-:105E1000625D863C9A367E2593FE979EFF8CF9FA4A
-:105E200072E265E3A97055E9E0CEA9639E3DA1A1A8
-:105E30008F69EE1B9F3DA183D3145DFEDEBA69BA64
-:105E4000FA33E697E8CA4BBC15BAF2594BEED3E5E4
-:105E5000E7F81ED4D52F6B5CA02BAFF03FAE2BAF75
-:105E6000DAB85C97AF695AA9ABEF6959AB2B37EC3D
-:105E70001B7233A1706CF8AD484C148E5F5B4F3EC3
-:105E8000754D12A49213E07EAA3E0DE9FA74BD820C
-:105E9000692DD0DE28E09FE16637C5932726544A56
-:105EA000E20979C477ED9225D7D2BC91968FA6D41A
-:105EB000EE1BBBC49B49C8128782742F361A4980D7
-:105EC00092AA4012BAE93A246ACA8397286F944882
-:105ED0006078CF723118FD7B97101A9441D7E1FD9D
-:105EE000D44436083DF93CCC97A40F49EBBDBCC364
-:105EF00040CA9B34726783C380F349768CDDE0A08F
-:105F0000F4506D64FC5EBD2D7D2CB1433E30A8CEB7
-:105F10007A91F19AE86452A11FC62F15FE3E61FEE8
-:105F200045FC0DD0F1FDE038F77A071DAF63BF38AF
-:105F300015E6410207B36E1D0AE3BB36C077D242B5
-:105F40003B49A7FC5DEF7AF6C415847C523F01D330
-:105F5000DFD5173F7B4226E40FF553317FA4DE8D5A
-:105F600069B0BE1CD363F575587EA27E3EE64FD65F
-:105F70007B313D55BF04D3D3F53E2CEFA86FC47CD5
-:105F800067BD1F53950FA83C9A510C7C5A5C6C005E
-:105F90003E9D6B21FC8FE5CFF13588F4DF6DC8D7CE
-:105FA000CE34E0EB73D66F0665507A3BF70925A631
-:105FB000ECDEE1144977BDE3CF6500FC95FA29F1E9
-:105FC00024F62CB7C430FC580C6402A1F2E7F12B84
-:105FD0008C44A2E3C7BC71D53A311BBF4B403A7425
-:105FE000E3704EB145E97F20417C5D0A4F6AFD9325
-:105FF0002FFEA970662EE0A73FD249CC41B18EE1B9
-:10600000ED6527E0ED52F093387F45C25178E38F7C
-:1060100059415AFFCB64159E6D5984A6B73A8A4FF1
-:10602000011D9C6B36E1BACEB5C6FA09F4E14842CF
-:10603000BAE81D6E6C1E551B2D3EAD7CA8698AF713
-:10604000E9E545BA4F2B2FCE1D7AD90E7C3F374D4F
-:10605000F49D180EF4E1E2F4C1E84EEDBFA629DB91
-:1060600067D5F5A3CF9FF309139A50CE2B71B70DC7
-:10607000ED7D9E73D38C38CEE98D03E260DCD3F5E1
-:10608000661F8CD351EFF0B171D37C5ABAAC9E1F0E
-:10609000EB3B91189E5F6FFDFEB3E7474833396EC7
-:1060A0002608FAEF07F45EBF577C48E78DC5401F0E
-:1060B000ADF237B0EFC4E4A8FB8E8479B55F4F939F
-:1060C000E8355D0DDF37EBC6A3ED94932A9EFA5FAA
-:1060D0000CEF1239A9AE93CAC9A15476039D52623E
-:1060E000463CBB698F71B4BF2EC9BA44A0E398E2A5
-:1060F000152CF7C040949E6ACC41A35B4170B781D8
-:106100009E3573A4CAF7CA9DBFA724F7C5AF65B271
-:1061100014CAFF4C7BA7E5322F9D4D8AED848E3744
-:10612000B3B96A22C8C92F76FC88EB29BE4258F75A
-:1061300097C43001F8E44BF21BFB708D5E3639DEFC
-:10614000C8E6B784EDCF5EFA1FAC8FEA69BAFDBA34
-:10615000AC519F2F25B7A4003F94AE90899FCEBD30
-:1061600002F67B75DD94EFAF8F677A5C19A95B0C43
-:106170007ACA52994C057CCF7410A90F9513353B00
-:10618000571796D0FCEDF106A4ABD354BF53A81C0F
-:10619000AA48607A4C6592DFE8A2E5C79B87DF7169
-:1061A0000D81F6FEC520D7BC36E2DC407AC27DD632
-:1061B00012FDFC2E35FFC8F912B210E7ABCE43ED4D
-:1061C000579D87B85170F9A3E8B3B3E285B09E4CF0
-:1061D000D3FBE3F5FAEB7CC86BF4DB4722F20B232D
-:1061E000F22A9DC89C4E4CF1EEF9F1C94017A1F17D
-:1061F000A8A7114A1FB9E17AC670BD472E56CF0431
-:10620000F544ACB7F062F52CE1FE1E8B56AF66E7A5
-:10621000961D5E4A4F95AF3F6727549E7F21F952E6
-:106220009CF47BF58647ED00A75392D70EF8FEC28B
-:106230002F4E8806AF7DDDF0725905B02390B4294A
-:10624000DC5F7D6232E849DF6C901D22ADE2D968E7
-:106250000A9828FDD636574C2479983FCAF28F9D6C
-:106260001521DFA2C767E5CF9F4B516C8807A66F4A
-:106270009300EA1DB5EB3F1F0F72DC434248879144
-:10628000ED60FC0B09C8F725C6B89EE5749EA827EB
-:106290007B389F799A9F382BDA21BDB11DF8CC133A
-:1062A0004147E5DDFB4BD0584CE7F37ABC2DE9E4E0
-:1062B0005534FB03F20390072A5C889FE9150D9B78
-:1062C0005EC83B4AE7D5B1FED77621572B47183D2C
-:1062D0009E6B9AF5B3DD4AEFF2A693DB45E1767E3D
-:1062E0006CA7B4303D88B4B2B45A0ED841EFAC5E5E
-:1062F0002B3B29A592EA2D2FBFF222D86B9F9AD073
-:106300005EABDAF2D647A369BE6AAB9C34912DC767
-:106310002AA484F1E3A1FF9B3F2C8C8FCA5FBC654C
-:106320005486B2EF0F2784F152B575BF910CED0979
-:10633000C7A2A6FDC6A0350A7E9A8E8E07BDA561AE
-:10634000D3B746B0BFBED82790D4EC9EEDCBD7BE16
-:1063500085FB22C009F1C9F1D58DBF1E780B4CDE3B
-:106360005D80F51C202F2F85371F97D3353B6D247B
-:106370009ECEA3FC7726FF44C0E76BF7DB613DEDC3
-:10638000521DA3F3D58FA6B8E8F8E5B237C5812929
-:10639000FB5EBEE601A4BF32A12EC581FCE44A37F4
-:1063A000A0ECF6A6C33AE7ACBA1DD7594ADC488739
-:1063B000E5ABC5623F4DBF96C884AD51F8A43081AE
-:1063C000F149FB3A8A5CBACE76D0FB41DFFE8DE81C
-:1063D000DF80F6E97D04E4FF037CCD74A7C4FCD71D
-:1063E00066862F6B8241B517CD3AFA5DFF581BE0E8
-:1063F000E9745F572ACC93C2C1CBE1267C4FFB15D1
-:106400003FB82195E1892852216F47F78322F80E82
-:10641000F5DB6497254FD78ECB4F36FE3C3E3E9D35
-:10642000770CEC6FED2954BF8FB2BE99B03EDC17EC
-:10643000E93EA7A1330DBF33FE5FFF38E37795FF39
-:10644000FD532640F9F90F191F413BD84FE8BC0214
-:10645000A958BEFF3601E5838904A2F1F97A99F3C0
-:10646000B9BEDC43F915FC042A9DD0F94B429C9639
-:106470005EE838098807B4574A57D0F65AFD06C671
-:10648000C57AC6F077CDBE52C6E5427E029507B109
-:1064900061794056255F961E592D132FA89CD59FD4
-:1064A0009AD01EAFDE2217C3FACF6C3EF8D15D94AE
-:1064B000CECF34A97CAB97AB917C5BBE6D8300746F
-:1064C0001AC9B767CAE92E1E8D6FE9F7A87C5B1E53
-:1064D000FC7F2A5755F84D4BD0CB532A1FFB810A1E
-:1064E000D11B1C23E5E3D7A06F25F7948FF4EF436E
-:1064F00052D8930E55FA53E98E6A70FD40AE77D3A9
-:10650000A74A7FDDF4A9D25FE47AF5F08B2CEF0F78
-:106510003612A593E25D54A3A3F8AC6E15FC26E4F5
-:1065200073EFDB7D0A104E2EDCDE88EFED3E49DA9C
-:10653000BC3F22DF1451DF15912F8EA8EF8EC8D7F4
-:10654000E9EA57B71C3412C47F4057CF34FF257295
-:106550003C8A3DA8EE3F9EE6B3462FD04566C8086C
-:10656000724F5E485537F0AFED15D1BFD6A584EC1C
-:1065700009F4FBA31666A77539783E9EE543C9C6A4
-:10658000C520F7D4EF210B41FBBCAB38648FD7D8C3
-:10659000FF475B45BB42CB837E3241EB4708CFA729
-:1065A00001F11D24BD9533BF61578C3D0FC78BC9C9
-:1065B000F203FDDD205AB3E683BDE7139D947CC84A
-:1065C000EC0577DA09A5B3AED601374FA5DFE7BCF6
-:1065D0002382BA4DD1E392D229DDCCE2747C8A7851
-:1065E0009FBF96AE6F562BD3C3672F8B4EF795BCCC
-:1065F0007EA9759E11E42BD5A38F69FDA295641920
-:10660000D25DF9AA88EFAD3F42FEA88CE00F37B704
-:106610001FF6AAFC914FF251BE10C2EC5F2E976F8D
-:1066200010736F9E4AF1D07548242605EC59912CC1
-:1066300086756E16FCE02F20DE64E4B35A124279B0
-:10664000A8C2A903F86870EF72AA63FB1F0B1F02B0
-:106650007AD9F1FBBC9768DAB1E3D3417B20BFF371
-:10666000E3ACDF939EF58BF67D371DF6B3AE7D264A
-:10667000F48B75EDFB65D64390DF6D42BF58D74272
-:10668000930BF8C0BBCFE6BF02CAFB32FBA161EFA0
-:10669000B77941DC5F1721DE4E2530FBE55CEB9FCF
-:1066A0008E084990D25581FEB02F16F9C8B3DB820F
-:1066B000F67AD7DE6F0BDDD67FDE7A6A8DC48DF475
-:1066C000682353B701FDC633FFB167CFA89717D032
-:1066D000F16B9AF71B67D1F2A237FE9207F2B36B08
-:1066E0001BD38B3AE5E01AE224E4AB84B2C765F031
-:1066F000F301336510F274E2C61BBDB9D1E0C2E00C
-:10670000D045E100EBA2702907B9DF1B3C62128D76
-:1067100048EFFF7AF0383B9DC9B51F10F00B85E1BB
-:1067200022B8D8779BDF2CE0FAD9F77DDFE681DC51
-:1067300039D3B400F5954BAD7B48E2BF2A1DFCBDB3
-:10674000EB160297B3EE09FFB2F866F4FF5E8282A1
-:10675000F38CE4839E74BEF3C7987FCDE6C4F95EE4
-:1067600026FF97FF6FC3FB368A77FBA5F1FED8FFA4
-:1067700058BCBFC3F16E7398409EEDFD0BFA59D51E
-:10678000F55F6ADDAFFC0F5DB7AAC7DF64A83B3CCD
-:1067900085D63F4C022B8AE93CDFCCBCE1C329B44F
-:1067A000F497BDE8271F25323BF097A07C80FD972A
-:1067B00026F837A05DC1ECA622C2F6F5A29C32D421
-:1067C000378A729E40BD81487587F3293C6ECA9A0C
-:1067D000E35C8AD5877DE2A6F97F4BBFCE89FEC3F5
-:1067E00008FBB1E8CA1B0F81FD7270019D1F1DE7F8
-:1067F000605FD1413527322E530E98F2303D0AE9C1
-:10680000DBF609586F9C556F3F4D04BB47630FDEA5
-:10681000A8E8CBC7F3FE2790034912ED7F825326E9
-:106820007EA8477C8BB4E7CEE323FAD946754CADFE
-:106830007FED6F859F3989D999BF24730FE703FCDA
-:106840003265F41F5E127E006F8457BE7F29E856C2
-:106850009213E17753460D8727B3AB25DE5EB22E48
-:106860006E03BE9508B58B995E86F6B46A175F0A0B
-:10687000CE84DBDB121F5A85BB9449ED6D7DBF08CA
-:1068800017151F7F2B1E54FCFDBDF8F81DE0634457
-:10689000181F99E71D12F06711B707C69D6F1331D6
-:1068A0009FE994F0FC85DB0363ACF112D803D74970
-:1068B0001F88C09765E65D95708E60760A48D7831D
-:1068C0003B0C68EF980B04847B4EA384F90F0C8E6D
-:1068D00011A0684FBE66E7990709F8935D46A67850
-:1068E00017337FFE9FBFFFFEDA42F0ABB0BF32FA34
-:1068F000BF49D41E9BBD8A0462E8FAE648C40B2156
-:106900000E737C0239A6F307EBF3F0777D4AB89F4C
-:106910004BD5EF4D8EFCB3D39D546E1DBB82905D65
-:10692000903267BFA4B59B7FD0CAE0E5394CFCFD2F
-:10693000512EB8C462CD39DBBF2731F9B1F30FDB7B
-:106940008683FF6C4C576E1C93A70506A04B0FB7B0
-:106950000BCE11250EE215CEB50E88C373C443A22B
-:10696000CD1DC56FB389DBD3FF518F4E65D2B59E68
-:10697000F844B09B4808FDB7DEF5E6A8E7C13393BD
-:106980000C9C6E38DEE89F5808E7166CFC39B46939
-:106990009C166F1D13BF90F27AE201FE8E69CE57EE
-:1069A000FE51F882FD0EF0DD64098E2F8E223FE647
-:1069B00071F84D3EF01DFA3BAF6C5D6B00FABD7295
-:1069C000BD41773E599DC4EDAE616418CC6BF201B8
-:1069D0008BAD00F07248745AE8FA3CAD678DEE2832
-:1069E000E75C91F084FEC18FFE6A123B17D8233713
-:1069F000CD02B8EEF9D24CBC14BFBB8CBEAA68F372
-:106A00004C4A61726E0E69BA3F2FFB5F0FBE63BACC
-:106A1000AC81B16067AE27DCAF11497F04E9F8DCD7
-:106A200046E287FD14EC52900BE73613DCCF294881
-:106A30009E04BB9AF2FB0FB57E9AC12D5BFF03F457
-:106A400080DA56C161A0E5B552D008FE584F4BBC64
-:106A500008FB6EBE425C783E2C3986DEA6E18B5781
-:106A6000932484EFC1D17BEE8671BFEA3012D04708
-:106A70005C6F86ECB06F7FD53A1CF9A0B775FDA2AC
-:106A80009E548E93A11F260F23E92177738C2E7FAE
-:106A90008DE8CE00FE9A6C0ACE7346C1DFC4644610
-:106AA00067972DDFFCFF9FC9B70F55F9E6168B35A9
-:106AB0007C9494CCE85E23DF52A3C9B7B982920AD2
-:106AC000709FBB77402AE075EE3B727234F9B6A531
-:106AD0009E9DFFBD4EF911D2AE662ADFAED6C8B775
-:106AE000662ADFB27BB6FBEBE5CA37FF7F0FFF6D8F
-:106AF00001F91665BDF11C7EAA7CCB6B3D8AF22D97
-:106B0000AFD940148DDFC99C7C29F92624DF06FA11
-:106B1000F021D9191B857EB670FDFB751EB707E302
-:106B2000809CFBB764765E7AB9722E3D85F1C925EB
-:106B3000E5DC7F139C553937773B9573D9D1E890C5
-:106B4000C9B9B9BBA89C13801E999C9BBB9730FF09
-:106B50005B847CCBE921DF08D6AF0DB0F69E96ECC6
-:106B600017EEA1FD0D73C94E33AD3F2C2CEF4668D7
-:106B7000E5DDBF254B08E71EF2EED0E5C9BBED5CB5
-:106B8000DE5139D61FE46B247D385B6374F93DA375
-:106B9000DA37FF02F8E55D11CF173F30B073A0F789
-:106BA00046B517007DADE4F3F170FAEBACF762FF88
-:106BB000456FB2F5D56C66FEEFDA66A61FD6AE1746
-:106BC000FD0AFDE7F8D1DF1961FE157B05924AF356
-:106BD000534CBEE7AD20837F2E13762E4626E66B00
-:106BE000E861F6C82AF4E33758ECEB08E5E3D9127C
-:106BF0003183BFBECA3AFE0BF0D3578D64FEFD2A27
-:106C0000FE9DF0B801350EB2B4E5BEB7FB909EF123
-:106C100003934D0C8F935F16FC6BB3217E495F5E2F
-:106C20001511FFF8145FE71431887021EF8B51E3E1
-:106C3000189E8A84C7210E0FBA7E1D3CFC425478F0
-:106C4000508C4ECC4F09AFBFE2DDE062F0E757ACAD
-:106C500014F0DC578547E43A55F8A8FEE92ADEDE51
-:106C6000D37A1F9EFB47AE5F855F8F75ABF08C5864
-:106C7000BF2F999F7BE593E1104F43E901E587F72B
-:106C800057140E749CE23157A46AE5F1F31C0EC34D
-:106C90007D638AD209C08DD401FD9436DEF7763A41
-:106CA0005DFF884F9461B04D5E33DAE48673D44D56
-:106CB0009610CA3795BEDA557AE7FDECC9A81B8B4A
-:106CC000F67A8BE000FDC213B0201C3D94CE2CB4AC
-:106CD000CAC195DF8CE770749890AFF8BE43E16E3F
-:106CE000A0F5C7ABFB10853BF0CDF0D6B3789E5B2B
-:106CF0004042785E52DB283803741DB52D0C5EAA25
-:106D0000BCA57F562D3EA2D0A3148D1E0938890B39
-:106D1000C3FB6015AF37D9E4FB08CE6126537A5F19
-:106D20004BC278CCA1FF011E23F1A4C2F352F4F9A7
-:106D300039D73FB6001CAD00AF10D3A302745FB0CB
-:106D400085CB3D925707C7A2172F30FADA2B287050
-:106D50009ED00D27A0575A3EA295D12BC04D01B809
-:106D6000B79688902FA5F04DCCEEB94E38BFD4F22F
-:106D70006FC5DEA3ACFFD5829344A15F75DDBDD1A5
-:106D8000EF3F4AB7ED1174FB9E25747838D0ED5E65
-:106D900081F9115AE375E78EA61476EEBEC942E971
-:106DA0001BCEBBDE919DEB949E7C7E81C313F47F52
-:106DB00045E3971A020B80B3C08D668C3FC379F40C
-:106DC00067FAA556BE6EB190E4DB0A7AEFDFC8ED34
-:106DD00081DEF41B353F14C603B9D742C7CB098FF8
-:106DE0001729DF557BFF52EB4A4CF9C7D6D51DBF9B
-:106DF00049DAF0FCC914EF7E2809FD3F2C3EE90E6C
-:106E00001E9F4467807A96A65E5AF288DEEB913424
-:106E100033EEC3F7F3B8F81B442BF1D2757CE5923F
-:106E2000914EE92EFDDB6B412E8FA5FB084DBE3A3E
-:106E30003CE2E37BB05CC4F3A89BDF4DAC8173BA4A
-:106E40009B4118D1EF37E70BB8FF7E009D8D023DC7
-:106E5000D64C5C264EC2B47CE40FE2D16F94BFDE08
-:106E600057A4507E1AB6D1DF00A9B32894F41EC0EF
-:106E70006F8C48007E6DAEC422D8BFEEFF9CE48BC1
-:106E80000AEEB3D8CFB0432419EA8D7625A3393062
-:106E9000AA794511F847A71CB45A81CE73561988B0
-:106EA0005B43BFA389BF01FC36A34EB86E05FE2B22
-:106EB000A7FA02F89DCB5BD736D821BF4A702AB417
-:106EC0007F8FD73DDE4EE7B5A5F1ECF8AB800F69BB
-:106ED0003DE8C6B38AD5F3AC179C102A5BDABA1C1E
-:106EE000E3714AD70BC401F5FD0231B37EFD66DACA
-:106EF000EF9655B43DCD97417BE877FDD90F6F05EF
-:106F00003E3F2CB2F69BD9B975296DA700BDAEBF27
-:106F10000FFBAB58259034DA5FF96626FFCB0FCB19
-:106F20004E286FDEBF12F7B18974BCF46C90F78104
-:106F3000719027C30507FA3B33EF42BEEEE27C4D6A
-:106F40003AA632B921F03CB71B54BDE9400A8B0F79
-:106F50002E752E3026D27EDE1B999C0D61029E96E8
-:106F6000B3781E7D82C2D94DE1FC018FE73838F23B
-:106F7000B831A8D97F3E4B19807438BB650CC6392F
-:106F8000CC21C518E7307914D3D7DEBFCEE217E89D
-:106F9000BCDE974399F0FDE07526D47F3BB7C878F7
-:106FA0005EDCD93788FEE9F6553281788D86552228
-:106FB000CAC5F6CD6C1F1757DF3E3E1DE0B74170C6
-:106FC00082DC3CB8AAC808FB5ABB5FC0F645AB1FC1
-:106FD0004861760C9387AADD56EAA8D0ED1F91F29E
-:106FE0004D957F351C0E9172AE46DD6722E45C0D37
-:106FF0009C37DB21D57FF7102B937FA0F703DE03AF
-:10700000DF21FDD61E9609E8FDC2F18EF118B70505
-:10701000FB262D1FD52AB8E09CBFFC13931FF55506
-:107020007FC98C9F80FCFED4440405E2E029DCA9E2
-:107030005C18690AFDE159FAFD8B0FCC102143E978
-:10704000A404E1ACC68B166C60F12D051FAC482979
-:1070500005388C4B44395BD62812B7465E7C21B884
-:107060006EBD8BC963C7068D3C2A30FA4A61FF7238
-:10707000A43239A86C902166846CE7F289EAD32E99
-:10708000D01B2A762D4F31D27A8B793C48C5DEE56C
-:107090002954349006D8B768FD0A23EBBF629FE0FD
-:1070A00058ABE95F6DAFF6A7F663DCA5EF67C05E8E
-:1070B0009EBFCC7ED479A8E3F7A68F8FFCCF0B2B95
-:1070C00004DADFC8F7450C521E797CE200ED7987BF
-:1070D0009AAAFED7C20F0DC4A581DBC83FC4109782
-:1070E000862E9A4750FEA6789BD4C2F4A1E611479B
-:1070F0008D35059877003FD7723F6DED38766ED5A8
-:107100009CFFC122E0EF890502D201F1BA8D8949C5
-:10711000A8072970BE5056C0DA97D1F6C077CD2B9C
-:10712000191F5279A080BCA85DB57C3CD65F2F2882
-:10713000D07FF3DA12DCE7CB478A04CBD71F45BDFB
-:10714000A3BCE56812F02BE5CF15B0EFD65E6B72ED
-:10715000007FA87CA7F2F1FB328B0F2166C750B8E5
-:10716000075096A244E55FF1306176EA6619F9CEE0
-:107170003392F1E5FB5B44E4E783D7DD391EF8B0D9
-:107180007383D00B1F533E2D08F3A9B89AC5EB9417
-:107190006D62F6CAC1554C3EB437333DB168B53C5B
-:1071A00009F265EFCA84F9BD983E78B9FCDC434F1B
-:1071B000D9189D9F7BE3DFC972D347F7D3F9DDFC74
-:1071C0001A9DBF128657D1F50FDAD14F7FFD345C7F
-:1071D000AF2A874A2516CF34DBB780C5FB4A2CEE91
-:1071E000ED6F9E57C43C1E4BB185E58808F41ECF59
-:1071F000E2A4D7CB48EF91FCF88FF2D13F8BAFB729
-:10720000733A52E723EE65ED21AE2C40E1F8CBCD89
-:107210002F635CEB97AF1E9D0C78AEDA43E997AE17
-:10722000B773B38D04406E497EDC6F2A9B458C1F7B
-:107230002752A0F0569B963F597C52D5EB36A49B23
-:10724000CA6D2CEEB472C7F13C8C175918C2B82B1A
-:10725000EFAB5CDFF406F380BE2B25162715C9EFD4
-:10726000635299FED9B12B762AAC43D8B81FCF5BB5
-:107270002B9BEE9481FEBAE547AAACD6C3734C2F84
-:10728000A55F386787F94D19AA9DDF02C453C72649
-:10729000C6FF952DB2DF02F3DBB816FDD99E8D67D0
-:1072A000313EBEE8F52DE847F0B488FAB8C88D2223
-:1072B0009E63D114CFAB22E3136B9B6BF0DCADB6B6
-:1072C00089C7FF45C4C555BDBE77879782A6EA1713
-:1072D0003FB7833C38DDB6C10EF0A4FD615CE1F53B
-:1072E000E7255D7C54EFF1C02E7DBC61D3E33CDE2D
-:1072F00070523BC9EB196F781AFE01FB4D6A44BC12
-:10730000E6C6441EDF1D282C8EE2CFEFBEF7B3E5A4
-:10731000EB351027DFB1EDCC1A987FF55FBF5A032C
-:10732000F14D649F05F729CFABBFC5B862B5DD82CB
-:1073300054466F9D9B7E8E71D99D9F9AD0DEE9DC6D
-:10734000DB9E05F16D9D5BBF4B01FFDCBCBD37A033
-:10735000FF72DEF6A2541245DEAB29D0A7FF32E25F
-:10736000C223F171B0F920C6617DF98909E55B7727
-:10737000FC68530D8BCB5578DCE8E6E871F86A9C25
-:10738000636DF3AD375F07F2BA99E977DD718F97D7
-:107390008A17FD90E2F5EACBC0DF661E17DC3429C0
-:1073A0006ABCE897F00F8AA79FA5EAE345BF6E9EE7
-:1073B000F3B317A1AC39B1D778D1C065C04D8DF307
-:1073C000AF4E75BD9A0A7CB42DD69BC6F0E69F28B9
-:1073D000801EF87516DC8F382587300E24B4D7E46C
-:1073E00080B8C7CABD1F23BF746EFF00FDAD84C740
-:1073F000D97792EE3F160F2DF075AEB7B138530E18
-:107400007F884355ECF89DC79B323A56E3507B8BFF
-:107410003F0DA6F2FBC3FCDE410DB59B589C7A38AC
-:107420002E551809F83AAA8BEB55D71DD99F83CB57
-:10743000D1705C75F4385F358EB027BED8BEA2C659
-:107440004D77AEE5F1D6F47BE630889363FBB9C7A0
-:107450002F7C1C0DBF6A5CF5EF23F0ABAEAF37BEDF
-:1074600050F9F352F3FE7BE1F26E2AF367ABF0E9D9
-:10747000F8737439FD0DE7776AB77E9DAAB16F671F
-:1074800070BB55859B3ADFC54D4CAFE8D8C8EC873B
-:1074900048FEA6EB71458BB397D298FE5BDBB23FFB
-:1074A0000FE450C7815D9CEE185DD76E3ECAE27452
-:1074B000A9DCF66BE536617EE4C8FEECBC3F4F6BA1
-:1074C000F4FE3C9BCF46EDEFB4E4BA13E67FBA8DF1
-:1074D000E951A79BC409FE28FD5FE0FB52F7BA6D96
-:1074E000468C9712ED31A84FCDB38DFC242E095256
-:1074F00023C6FD342CE071428F38D300CE0DB69BED
-:1075000008CCE751808FC6FF203BDC04F43839AD4E
-:10751000B84054C2F355CB8D4906E2D7E25F0A6406
-:10752000827C3F92DF2E437F9F45F84D3E93C8E219
-:10753000543AAFCFBC827381D2BBDEADE6DD0F8B98
-:107540003A3F47AD297404F477F28605FDD6E23E52
-:107550008B17FD666B2CB8CE83DBBF7D05E0D5F9BC
-:10756000331361E7089430A85C28E3FE8BF6EDDF67
-:10757000AEF913E899D0988E5FB686D607FD7A7378
-:107580002CDA035DDBE2F2509F7CE3A1C92037CA0D
-:10759000600F033DEFF5547F03EDEF6432CB9FDCCA
-:1075A000D217EF13546DB361BCE1C1ED3B6B41FEEB
-:1075B00077BE1E0BC7D1E44B39F857C87BF6C49190
-:1075C000B50AEA818A76BFAD2092A2D5F3AA20AF90
-:1075D0008B7F2168A7A33F8ED273554B1CDE1FD132
-:1075E000D4E3FCECCD60F7650219C077549FD48DCD
-:1075F000A396DF96D69FDFEF0DFD98BDAFC0EA7B67
-:107600008CA15296F76530BE6DC3FA252ABDF2F201
-:107610009EFDB2FA33D2FAEBEAA9ED6B4DA42E1A15
-:107620001F54A709FC7EEF5F06477BCF22CAFCF1FF
-:10763000FB0302F11A400FD86AC138AE6A636010CA
-:10764000C4B7EF30B2F3916A7B6010C4B7EFE1F2D8
-:10765000AF3A86E6E9F70C3E0FA80F79620EBE0638
-:10766000F8AED969214BC17E7FC3E6023CD7ECF866
-:10767000F6E44B0510CF168B7EAB9A37FE1DF15FFB
-:10768000630A4C07FA0F6D359175B47EC7D677B291
-:10769000408FE8900359091739F7A96932E9CEB14B
-:1076A000D5759CAEF70F84FBEBEABDC5CA5EE4C599
-:1076B000DE34A68F2E4F733D9D867C6D75A0BC86F3
-:1076C000FE44E8A76580F65E73A5125D8EAD4A9311
-:1076D00075F768C5F03DC555D0EF9724B83883A23B
-:1076E000A44608E1F979E5C6B343C11EFEECA757ED
-:1076F000E1B9D667C6D05090DB9F6585866AE5F113
-:10770000A97AB322C9E897C0B46BEDD9D20C02F1C3
-:107710008396A9D1E4D396B4589C47E5C3B151EF01
-:1077200083EEE6F4B61A6830998D0B7E0875DCCFCF
-:107730008C7E23CC23375DC1F2CA4CBF11BE576D7E
-:10774000DC3540F7EE84E4C37A94BF101E156485DF
-:10775000B1C0DA53AE54CCB72A12DE8F96FEAB9B83
-:10776000DEC4309ED0C909716A1C877467423FA885
-:107770007A1F40928BCD002F2329764822A0DA87EA
-:107780007C1A439A30B5527584ED437504E28A4EF3
-:10779000F1F35B93A43C0DF2C3744844797E29B89D
-:1077A000FD32CD8EF3364975C4897AC74407E8D5D2
-:1077B00082D74DBEA7F4D050BF71C00976FEEF82CC
-:1077C00038383B61F3B33BDEFE0EF4034A6768676B
-:1077D0007BAF27FE063A9E6464793296F8A39DC774
-:1077E00077703C10EF7E943F5612FE0BD17C2C4AF2
-:1077F000283A6EDC5F47829D6B759000E84DB1566C
-:107800001288A5A935573AADE55F3B61F9FE949C16
-:1078100041AE39AED59747D235714AE7BBE5A2886C
-:10782000EDCF47B43F7FB1F62A3C3CE601D9ECFEF0
-:107830003B834B0C5F8377ACF34210E09167773664
-:10784000001E8DA1230F013CF2ACCC4E4C6A245A91
-:107850003B6E403A93578B04B65FD2BF62ABA63FF4
-:10786000E230A3FFF4710EF7EEFAAA5FA5477D8B15
-:107870000470ED51DFD25BFD98E8F56DBDCD273684
-:10788000FA7CE27BE9DF1BBD7EED1B1FBF1750E0DA
-:1078900023931B1231A8F7A007A483BD157724A555
-:1078A0008451053B2788C05B0CD01FA58798819A1F
-:1078B000EFF07FB91AFCF58F827F1240BA2BE1F30B
-:1078C000A1796B3A9DDF5D7CBAE3D6B373CC7BE6DE
-:1078D000313FD25D0FB3FB42477FCAEEEDDFD3C825
-:1078E000ECED7BE6B3733352CEEE0139E87F30DE48
-:1078F000BDD009C5F7BD3EC11FC886777022F4D739
-:10790000EEF7761E90A07E49843F46A527F5DED28D
-:107910002CAE5F6773FA9C434236E0FBC87BF4CD24
-:10792000692C2E8D9A632E58DFDD7C7DEA3EE05D6A
-:107930004E72E05D00D110E384F31191DF5B257698
-:1079400023BBB77A5B824EFE9CCB51E260BF236FB4
-:10795000F2EFFC3DA2B9372AA9DA7B5ED285587CCA
-:107960007FA44176A6815C942FFC8828942F8C17E5
-:10797000061045730F8DEA77C8ECB283A01F4772DB
-:10798000149332D00BE3399D25DDD4AD87BD4FE193
-:107990003277B982F760EF4C67FBCBD28CE239408B
-:1079A00017A27DA4D36DED8957EF76B6BE06585F5A
-:1079B00076CF7937189D4ED4436FA21A04FA7B9C78
-:1079C00066988F68523E56803F7F2D13B0FF7BC272
-:1079D00081E1F35C52821FE25F66DB971E01BA5DB4
-:1079E00056EFC073B425F539982EAD4F433D7471F1
-:1079F000BD1353152E66A7CF2552389B07B2FECC78
-:107A00000E37D333E83E04F11792A32E0079736644
-:107A10001D01FDD7D20D1F1FC2C7D89D7763DE049D
-:107A2000799ACA8D1311BEB43D29033F6A867B192A
-:107A3000C0C7A25C49140D5D98D286E9F23DE0A66C
-:107A4000D2C71606BF2705461F91F07B526E53E042
-:107A5000FCF9C91BBBDFB541F851759FC1EF57EC6D
-:107A60007CAE57F83912509F9D5DB8783AC4553FA7
-:107A7000C1CF211FAB1F89F07A1CE2BA06837DE0DB
-:107A8000C25404F8513A32E57A8948DB9B143667D0
-:107A900093B5D8652860B40BF013AD0C9EA6B43A2C
-:107AA0003C8F335B19BC44AB17E1225B19BC442B00
-:107AB000A33723CF4B00BFE1D81EBF53F835A78FA4
-:107AC000003C8CD6C1CB9834F6F2E0B792C28FCE90
-:107AD0002389F357241C92E09E426E98AF7AD3EB31
-:107AE0009EA3EB877DFC050A1F48937BB11F933350
-:107AF000981C4D32D4ED97011E0984EF2F5E9259E8
-:107B00004858A822FCA57989027981CD83ACD7E3B6
-:107B100055744811EFBE292F001DAC784736C03987
-:107B2000A938FF47BAFBA4E25457BC82F0740BB0EB
-:107B30003F3F51AF20FE96031E07C3FEC8ECB1477E
-:107B4000393E1F033E41FC32FE7892F3CBD39C4F6B
-:107B50001A9CECFEC4B2092C2E2B29DFC0DF430B8C
-:107B6000106DDC53BCB38918E9BC50C756300DA06A
-:107B70009EF189C97F056D179B4B5C4027F19F3CA7
-:107B8000E8C7B592E274D08BE2B9FE4BAE55E2A7DE
-:107B9000E145DA80C4EC102A0AD1AE6933447B0790
-:107BA000ABC179C00C7ED3DEE6B37FCA0EA4CBD2C4
-:107BB000AB313C9824BA8BA7CDA1796B632CFA0723
-:107BC000639DEEC24781CF1B6D48A7563AFF320D29
-:107BD000DE637BC1EB8B19371A32281D8AA0B451A2
-:107BE000FC3ED338C002707E4E2E4E07F9FA1CDFE1
-:107BF00067290E14ED3954079793F6822B75F6EC2E
-:107C00000AD985ED1CD7EAE5C00A2E7713C6E9E943
-:107C10005D95BB1F75CB5D7732CC27E5C238E4C7D5
-:107C2000A45BA2CBDF06D9E88577051A86327EF7FA
-:107C30009618D97D989EF200FDDAE7DC83D6813C68
-:107C400055E96B2161F2C74B629CB81FF177745400
-:107C5000FD7809BC37C8E52CA4E24023D24DCA3DCB
-:107C6000068CCF5BC6DFCB7A8AD217A43E4A5F90E0
-:107C70005E97C1CE33169A87E1BB6D0D5603CA0BD2
-:107C8000E95393DF0AFAEAFE510EF02348B2B3CD6E
-:107C900005FE409BD4B48E40BD0233BC2721C417DF
-:107CA00038800EBEB1CDEE77B1383C8A4E01E8C8BF
-:107CB00091544C8EE5E2E901DE7B911DB710F02B6B
-:107CC000BE90546701B8E56630BBABB1A410E14883
-:107CD000E13B362339DC4FEAD49BBADFDB826E5FAF
-:107CE000E8E5FECCE40CAE47677AC9400DBF370A21
-:107CF0005C0F53BC2447C3F70BAF184FE05CA927B8
-:107D0000BFF722CF363079B648882ECF54FD539531
-:107D10006772849C50D3C5FD26E8EE7719939C408A
-:107D2000BB907A0D144592F7EA27EF8E4738CC02C4
-:107D30003890B49BBAEDDA1FF607BDB2302ABD45C4
-:107D4000CAB1D9DDFBBA2B05F0744A5652A7013DE2
-:107D5000BDD3DBBEEE2A453AF4F551605FDAFFCCC5
-:107D60008FD0AF73E2199B0272A8ECC2E3B83F94C4
-:107D70005E18856979E38DB89F0BCF4E2A047A6827
-:107D80005F7543DEA7E0E7F1D970DF6E6F2C1A84D0
-:107D9000E791BE5805E23BDA1B697941B81CE2C5A0
-:107DA000454DBC0001EFBBE6FE372950502F55DF93
-:107DB0003DA3769D7D34F885568B782FACF4599B86
-:107DC0000BF4CFDEE8AF7455747F00DE614AC70163
-:107DD00073408FDE6F1F1D0AD07E67AF63E7080D0B
-:107DE00046D7C900E84DCF58F01CB22121FABB207C
-:107DF00073326E580672604E86EB39C49395BD534C
-:107E0000DA3B3FB0F14FC221339C63BDC8DF4791DD
-:107E1000DCF629BA7336768E7592FB5988B997F2DB
-:107E2000185EAEF4526E67F122C411BD5CB53362C8
-:107E3000C3764613ACA3A6F1CCE24F115EDCCEE0D4
-:107E4000F33E25B3799F7AC5E45F1885FE4FF1F8BC
-:107E5000940A81C157E58353DDFA911BDFC389A4DE
-:107E60005361DD901746D17EBF3A24E3BE514DE900
-:107E70000BE96ADD288C8F179E19F534C40D9F3FDE
-:107E80002C6279E5050B96773CE27C01E29E42EF9D
-:107E9000CA04E4D3F94337C4313F91DE8F7D6F1FAD
-:107EA00026178E71F9507AE109A4DF6E3AF1CD31CF
-:107EB00002FF955E788AD1F74601DFAD24DEEA77CE
-:107EC000C70CE4F4391ADA574C5A08F0BED687E7E3
-:107ED00024651B4C4ED00722F17C2C43D1F93DCABE
-:107EE00082CBB05F42F5AF24CD79FA291E675C766C
-:107EF00081BD57481C5E9206FCC0E553988EF5EF95
-:107F0000D07658A2FBE9CF71FDA7F4C2353A3B23E6
-:107F1000BCBEEBF17B29DFFFCB82A3301F5ECF0B12
-:107F2000A3A2AD27BC8E6BB17E477CF4F1D3399C04
-:107F30004FD6971317956FE54656AFD4F78011E4E7
-:107F40004EE9AAF80441B3AEB2C62A5D9C47D9AA4D
-:107F500012E34C4DBF613C2C7E778C14C643FA4B28
-:107F60000B262DB4825E502CF7017E5A5751F81320
-:107F700005FA63F2E90BD99705F2BABDF17E7BB43D
-:107F80007B13E97D22F0D3C8F143F5EA020D7E545C
-:107F9000BC44B63FB9B6ACF027E08F5EC95E21E9BC
-:107FA0005DFE44E02D3B3ADC8675C32D07E38D2E44
-:107FB0000DB7AB7471453DE0C6F1ABC245FD4EF562
-:107FC000A8ABFA8C80F108BBBFD3C8F07F297885B5
-:107FD000C7E5F81F137D1D53BBD7319F7829A3CE6A
-:107FE000BEE43A1E225EF345D6A1E29FBCA2C3FFC7
-:107FF000D497D6221FAAF89E7D6025D2EF6CCA8F37
-:1080000070DEDFEE7BC01E2DBE686A6F781FE8252C
-:10801000B985FFF7F0FE85ECCD82B832EF720BDA4E
-:1080200023A7D63D91A585F39C8C31F7025EC8FA53
-:10803000E4CBDA3FBC639D87C0BEF43E23A33F6D13
-:108040006B86BB0CDA97733B7C51FCF841D1F4830F
-:1080500047EB0F0D013F5D437D1BA632D72F09E88B
-:1080600097D9A82FB9A2BDEFB5A40F932B8FD6B780
-:1080700031BFA7D94B1CDAFBC484E94FFF4598BF39
-:10808000466D6794DD0EF09F1A05528C7A9FE45E70
-:10809000925D007E8FA47CAF067E8BFBB0FB48CB4D
-:1080A000D20E38E03EB189F60FFE1C73A6744E7FE7
-:1080B000CEC9F2F9C2A722C437CB494D04FDA1B9FC
-:1080C000F4BB06DEC6A4369D7F3A120E92D98EE727
-:1080D0004D1261FA9CBA7EFA05F7A5C7F8BEB482C4
-:1080E000FB359FAF6F42BFFFC2583BEE7F8BFB1942
-:1080F000983D6596F0BD1A533CAB6F8C63F3B68028
-:10810000DF5B847D3580791BBCE823E2D36802E421
-:10811000E38922403E910416E33B2963823F86EFC8
-:10812000CE34B71FF0F84D7ADB1101FCD8C5EEC193
-:10813000B0FF368ADE7C85D6FF9918CA877A59B493
-:10814000E8930496F6837868B7E65C8BBD13AA685B
-:10815000FD8291F97EF3A588F39E3F0FD6962F4FAF
-:1081600073BD0EF368B0B07786928E0B789ED360A5
-:1081700061EF0D35D8EE88837DFC577D98DE8E74D7
-:1081800000747488E933E724252E81F94995377501
-:108190007E7EB3F2A6661C89DB7BEB295D4A9A736F
-:1081A000958192CB007473858F7ED7CE338A3F2E14
-:1081B000C18ACFF2463DCF51E70771FB0047F1C2BC
-:1081C00078B4D722E9614FB79FD92B023EA7A9EF18
-:1081D000174B8B583E9EA87F687F7DDAAD8F2E624D
-:1081E000797ECEE999C9CE311B4AE2303E4E9DC719
-:1081F000B4D6C7DA404F9DD69A3E0BCEB7A65907E4
-:108200007D0EE91E39742016F4C00704BC5772D7DE
-:108210006FDF946369BAFDC375789FF9732E4FA71A
-:108220009310BE0BEF260E7ECEEEC7EF338993E799
-:108230009B64B0EBEF09F86F9F4473F7BEE99F04AE
-:108240006ADBF443A1B7400CB89B1CE3F10C416D11
-:10825000D7E27C9BE559BBEEF54B665C4F78BD667B
-:108260005CBFBA3E3A53847F377CF87B4D2A3CC4CE
-:108270009974DD945EA6C5DD7113B9885E3ECD9A12
-:10828000F3393B3461F38984CF7928A2FA63471F1D
-:1082900017C9A4F8FB7D1F970069B5399425F547E8
-:1082A0003E91215F2BBAFB41E8F3977DDD8393017B
-:1082B0000E6D8997253F8F5818FF1F017A8638AFBA
-:1082C0000B49B82EF51DFA830FB6DB40EF5CBCFD01
-:1082D000637C67B9460C3E7927FA4345B49BCE359B
-:1082E0000FBEE8FDB323E0A7A2FB5FDF4CF59E25A0
-:1082F0005BE70C89F1C98CE6588CC79F315FD4BD10
-:10830000233D633E8BE723525BDE6D3A7D7D51AFAB
-:10831000FD80BF20B29F59F38BC8F1E1704EEB187E
-:1083200083FE83358CBE668D738910EF3C7A89801D
-:10833000E7ADA34E282D419A9FE58F77027BCE7A39
-:10834000F03F07C03B07B56DCC1F982ADE97FF08AA
-:10835000F8590EB07D1CF2F7019D585D8A55735E89
-:10836000D021D7E5C37B7FDE7BAD2EE0FF92DB5CC7
-:108370009FE27BBEDC5FA1EEAB3B1B4B304EB6E415
-:108380001E6524E0BFA4C9E2C2D44CA4182AC74A7F
-:1083900024628634D548240BA431C40C69E142F62A
-:1083A0006E7769E314D40FEC238B8DF01E6F49EBCD
-:1083B000CFBF86F6655260BF9017864F49EB3BDF13
-:1083C000015EE7B88A319EF1AA8D469D1D38B449F9
-:1083D0009FBFBA459FCF0FE8F3C30FE9F31B3209E4
-:1083E000D2D14CF3ADB900AF037B4D742F82F83F6F
-:1083F00013C6BB1C13187EBC9B2C280F8BAA5A0BD0
-:10840000C10E3EF39ACD0076F49EBFFC02CFC3436B
-:108410005B6209C459EDFF5D0C898178C5D72DEBEE
-:10842000A0BC8AE20EFC9755AF5BD6821DBEE34A24
-:10843000D58EF7E7C17A76FC95C5D7843699FC705E
-:108440003E7E66D7CF5F83F3B4339BFAA07E754C34
-:10845000F01A6260FC2F98FF33C8DF8B0BF2F7E253
-:10846000AA36EAEDE2B9994CCE04175E13174D6FA8
-:1084700052D39CB4C4DC71746E5D8F9B66801F68A0
-:1084800070A31E2E6ABD217EFDF78778FFA3893178
-:108490004CA7D91027E06FB0C3FEFB72F477921798
-:1084A00072FE79F5D5EE76227F278E289A7B53616E
-:1084B000F94DE6F581F80D807FFFF0F72AA2998F3C
-:1084C000463F99C0FBFFCACCE29993F8FBFDA7EBAE
-:1084D0000FE1BEDFADF7D5BB5CE334F9D2C6FD29B1
-:1084E00025603FADDA9F325303AFEA4D0753EEC626
-:1084F000B827093CB8A47ADA2B4F81BFA27A93D867
-:1085000004F38472805B47D35B76A847F5E161E0B2
-:108510000709EBA337B8C669F8F86FA55B95DFAA22
-:10852000B9FEB27364DB788853AF6A149C50ADAA6D
-:10853000E9F65B2701BC57B17BAE85122916297F6E
-:10854000556FBDFD4743216E66F50827CC877671D0
-:108550001B7CAFDA7C16EF332C8DF8DD0335DD9D07
-:10856000C9F4425A3F60A0F597DE612D07F945FB3B
-:108570007D13F20772D6E1FB2AF653ECFC817EFFF5
-:10858000C440F5965363BDEFDD4D9B9E214D1F4DBD
-:1085900002BF52A39E1E297D0BA097853608CE757B
-:1085A000F87561E12DA072BB1660BC2F2D9F11EDF7
-:1085B000BE75855FDF4F24DE3FE2F3A57F395AFAAF
-:1085C00089AC9738D18BF1E4D5F3A93CD4F809AA4A
-:1085D0004FF8F07DC9C8718896AE993E41149087D6
-:1085E0005B2CEAFB4782B990C7E90E60797C571192
-:1085F000E894124AD595649C02F0BE854C80743490
-:10860000C815784F7F64531ED4DF2D045F7909FBB2
-:10861000B3A11CEF7004F09DC90C7ECFB44361F987
-:108620002EEEE754CB2B5B2D186773E64B23CAD98C
-:10863000054D07318EBEE3358BC140E5C199AD894B
-:1086400063211EB3A389BD537CBA2971ACF122FB0F
-:1086500076A4DC50F7D3A3F04FBAEFFE29D3F54D43
-:1086600026EC538B58BC6A6A625D7EB4DFBF50DB78
-:108670002519EBF2C18E09DD6B75AE433879B32550
-:10868000F483A739214EA84460FD1AFB158B7D6940
-:108690007D1BAD0BFEE8844322FE5EC371D1F963FE
-:1086A000C7007C4F1EF5A0D9056E7C9F922C62718D
-:1086B00095B324129028BDCD82FD280FF32897672B
-:1086C000AD1230AE6CF632FD7AE09D5CED3E5A4163
-:1086D000FCEC7D0BAD1FB13FC4BBD0FD06DEB53455
-:1086E000B3F88BCAF5FA76552480F3A9DEFCBD29D0
-:1086F0001ABCBE26EABA5C99B02EE11633CEEBFE68
-:10870000E7E2D8798F91B8603F0D3D6743F95E4548
-:10871000DCD8DF5D7C5FF73C58E29A0D7278FE2C66
-:10872000D7EC44B86FCBF63F34F990BF05DC77AA9D
-:10873000C691405FF6EE06817DB5AA55080C85BC52
-:108740009978EDC3D877787F00D6ADBD5F534E7C66
-:10875000385EF92AFD77F221C36B35BFC748D66B67
-:10876000CAFB837EC6E051BDD9A4F3EB8CDE2C7826
-:108770006D78DFD5DF9042E7577B8ACA0A0271AA7B
-:10878000DF9B74FD433CCF08DCF78985E2EDB96ED1
-:10879000B9EE1F122DCEFF0887E373B797A603BF6C
-:1087A0003E0D7A6B0607F448945BDC7F4002663A24
-:1087B0004ECCF0EE3C96172E64F9C9AB5F99DC788D
-:1087C0002DB5F364379E0BCD128BDF86FB602FF740
-:1087D00073DFD2978E33CBE0CA92906F5D83D01F48
-:1087E0003A9FC1E185617543EAA2E8812A9E9F17FD
-:1087F0009A02702EEBDDC5F42F5B4148D6EEAFD563
-:108800007D993C8A3B10C47B13A1ED02DEB35C2949
-:108810001CC5FB882B6F5408D8F769144F208F575D
-:108820000A649140E152D03CE5BEB700CF05314E1D
-:10883000F8B98B9AE631628D15D7CFF4B4D8BAB5B2
-:10884000709E933A236718D0395DF78C5BE8F7FB8D
-:10885000FA2A385EBA95E13D6DA1371B7E072AEEF4
-:1088600040F17D6F011F0E8DC17BB2A91456B60475
-:108870004C9780FE9546160850EF393BEB3FD920C8
-:10888000CE9802F9612C9FF0B0E05A87C4B71CFB68
-:108890004F359109304FF80E7AA419FC0A58EE674B
-:1088A000F82DAACB87FE5207B034C918C8847E0EB3
-:1088B00077E3DB8D76C53CBE8FCDDB3A2615ECBC6D
-:1088C000C31DD4E0A672EB709AAA0F05ACF8FB505A
-:1088D0000373587D6E17CECB67F70D92B2F4F5BADD
-:1088E0006457DC7090A31F303DFEBCD585FEE96B5C
-:1088F0008CD1FD592FF5657A8BE78240FC9A7DC0BB
-:1089000033F51BD42B3D1724DDF78E7AB32ECEB969
-:10891000BAFC00DEBBAF216D18875DD314AB8BDBD7
-:10892000BD2626FAB82A7D7B2E88C41B755CA3FE63
-:10893000FB8544E24D8C562F45FF9DAE43976FF962
-:10894000B67B1DF09D8C0CDAC11E9CC8F5DA2EBFDB
-:10895000C12B5F1DC64BA723A8DB773A1596EFE224
-:10896000E7716AB9DA7FE75423BF57C4DE5506F8CA
-:10897000780713F262EB59F44757B7EE1FCF7EDF4B
-:108980008BD185164E5E8DFC4869680B18286FFFE9
-:10899000A6EFA9A7728750123BA0F2F1E9A75C9459
-:1089A0006F5344838EAF630BBAF91CC5CB7306912A
-:1089B000CB85334F8DBB569B67F5C3ED3B268FA30D
-:1089C000BA7D412E6BFF87BE5FBEB77060582ED157
-:1089D000756415DB34797344DE4AF34335794744D3
-:1089E000795244795A443E93D5EFB005B2442721D9
-:1089F000ED7DCF4E9646C13976603ABC28B0ACE1E9
-:108A0000ABC9E368BEA6A00DE3676A5B05271EEB52
-:108A1000ABF1F14EA667599D41FC3DBBD882B6B77C
-:108A2000410E54B7080E81D2BBB5692BC6D554434D
-:108A30003B45D3AE89D99DD54D47B15DAFFDE71814
-:108A4000909F97E61CC37AEAF9D19DA4FBF73A2ED2
-:108A500080BCAC696A67FB70C4F95167BAEB20CA85
-:108A6000C388FBAF1EE8D71AA67BB5FEEF87B6FE1C
-:108A700016BA899D77768144EBFFB1A67D04E84B59
-:108A8000F0C625C8FDE705FF10D89F5F24EE21B092
-:108A90001FDD5B73C57E03AD77440EAE86A71A0655
-:108AA00065596E96A89C3E620BF615A82CC9599381
-:108AB0007833C0F34872105F68F8E99A2456DE37BD
-:108AC000D817CE5D73B37EC8F257045743FEB63550
-:108AD00057B2FCD0605F91B6EFEFBDEA6680FF064B
-:108AE0004774BEED9BC5E4B93ABFB27C575A16E84D
-:108AF0009BD56CBF80EB97662A17A7579EDEB28185
-:108B0000C261FA4F62515E6DE8B8F5A6625CBFB70C
-:108B100018E2DCD813EF7C3F43B92CA11E900E7BEA
-:108B20005842181FB6AC3605E5FD95755B61DF4F01
-:108B30009D9E8BF2FE7CA6AB3E6B4438FD76004BCF
-:108B4000EBB3D87D8F54D180F106A90FD9500F7A9D
-:108B50009A9F2751BE41FC5A393E866531F9372C20
-:108B60008BD949197D6FA887F5DCC5F5D3158FFB27
-:108B7000375928FC7F07449284FE6DD477EF5E4B13
-:108B8000E5461CC453B8D2411EDC0DFEDFDC705E2E
-:108B9000D5DF57E4D3BC356CA7AD98E24AD7C60100
-:108BA000AD58CBCA5579B3229BB557F79DD406066D
-:108BB0009FD4A787AC8375C44A04EF5FCC993A6809
-:108BC000DD02DCBF6FC1F912972B1DECEF1315FD11
-:108BD0000DA057AAF8792CDF3511D723B278751577
-:108BE0004FEAF8F57CDDB344BAFFD3753ED4CF8DA0
-:108BF00070A4FA401E0B2E60FA403D386293C3F019
-:108C0000255270047CFF5F04A7FB60DDFF289CA257
-:108C1000C88B9FC2B835F3A9BC3068E40587DFF381
-:108C200042404E2DD0BC5F42BF831D78675FF7A3E3
-:108C3000599A739CE90FD5A0FEA7CE2BF6DF774E8D
-:108C4000B893F4E4B348FDECC8EFCCCBD00F686C1C
-:108C500042B978E426E25C00F2839FCBAAFA65E190
-:108C60004FAA0E831D752E4BC4761615AF42F1D652
-:108C7000520AA7C7E9B60AF7D1BD53587C8FBA6F1D
-:108C8000AEE0EFEEAE78F02A8CF3EB2241FC5D36DD
-:108C9000EF4882F2AFBB7CDA202CA7F8F65A80DFCF
-:108CA0002B62F0770756E413BC67B362DA9558BEBF
-:108CB00047F52B4D33E3382BA6307A5A51C1E230B9
-:108CC000611F01B8F5460F290DCCBF4124579E36D0
-:108CD0001EE05D8EBFD882E0F68F41AF5C6641BD7D
-:108CE00012F64E3C1FF1A5E27814AFDBB390BED96B
-:108CF0003C663D9BEE5F8AE33AD13E7FCCE62A415B
-:108D000079F548AC02F35F65214BCCC3C01C218BC5
-:108D100050EEF1F910DF0B18E73183EB6B9F959F55
-:108D2000B3813EF02697374030602FCF24AC7CE6ED
-:108D3000C3B147C1BE99F9B088F70BC9921B5CFA61
-:108D4000F30E3AD714F08FF3BFC6900DE0E08676AD
-:108D500076E8FFBF6CF09E89FB6176BF9778697BF0
-:108D60004D3CF4C7C0BFE06717D9FC497DAC12ED9C
-:108D70005DD08FB97CA7F37769C753C789EC97DAC1
-:108D8000779F00BC28DC03700F2CF488C87FAF5598
-:108D90003FDF2463E8490B2D9F5E2FC62FA4F0749C
-:108DA000CFB7E17AD5F9CE480D5DC77E1756DFFF04
-:108DB000C9D8DA42F087ABF60879586F8F815FA285
-:108DC0003B2F629C34DA353DBE737B36D20E24E4F1
-:108DD000AF266DBDEE7B1A8A10317F4E578A200177
-:108DE000DEDC3C7EA11BDF11F356E169E8171D9E16
-:108DF00049C6605F905BEEF9268443647B75FF7B18
-:108E0000C142BC6027360A02D263E383B1B89F1126
-:108E100033C3A3A7324601FA7CD118C23826EF6EBD
-:108E2000F6FB9F5D96D00E944B03993FA1EB3D71ED
-:108E30002DD4EB4C6674DDB94BE6FC44D83B12EF05
-:108E400089EBB05C60FD762E88C5F828B8FF698490
-:108E50007B99DE3FD5837F45B5E38FEF60EF29C077
-:108E6000EFF668ED60B8375B3E2C2C1FF07D18E004
-:108E7000E79658EE277257E07877C71088C3A83571
-:108E80000818D75B5B7925DE2321FC1DE76A3EB518
-:108E90005A03B5078785F9BCD6706C10D853D5E650
-:108EA00065F8BE332D7F13EC30F899DDEEDFF1C8A5
-:108EB000EE49D7B5CBCEFC05EFB537EBF15F1DA67C
-:108EC00013BC1F57A9A59BEC303DA0BE0D72621CC0
-:108ED000C17BF9369E8F9DD0E6073F8D87FB2D9293
-:108EE0000FB0776B6D054D04FCA69E534CDF18DD6B
-:108EF000BAF620D8BFF113DAC0E2A2F599DF2DF25D
-:108F0000FED0A8D6E522D875AA9EA2B12B87DC3266
-:108F1000549BB2FBB660A7C27841F804FC21B1FDB6
-:108F2000ED79BEBFD17D10E5F11CDF60DC07619FEC
-:108F30000239A6DAB920D7408EBCDC6FECD47E743F
-:108F40009D79CAD85BFBB1739821A8D77B2FEFBC62
-:108F500049AD07F6EEC5FD610C6EA195714C4EC092
-:108F60000F80829FF8D7F25A7CD71B042F9DEFDC2D
-:108F7000D5D92877553F4D35F7539572BF4E29F710
-:108F8000EB805F551BF70A7E4B6DBE9AF37D0DFC9F
-:108F90009E14BE17600AC7BD823F671C09D8A01C7B
-:108FA000FC3A7676BF4EDBDE43FC4512D2F9F7265B
-:108FB000DDBB582BD87A6770BCAFB4307FCEE88762
-:108FC000D78ACC49C5D61B37CC95FD6841F87DAE14
-:108FD000CF399E54B818FB8DBD17E01E23B2F7CDD4
-:108FE000438FB2DFBB3E41F7E7ADDCDF718B15EF9E
-:108FF00017BB06425C82E4C8BA25CAEFB62EDD6D07
-:10900000C177FA97F563E7C1EAF7B1FDD8FD5DF4E2
-:109010000301DC17C4A29E4DC19C077454D85FDDC8
-:109020002F491EF89F8EF2F8CEDA3BAC6EE82FC8BF
-:10903000FDE22BFBB17D6B653FF6DEBF9AEFB6EB31
-:1090400038BDA8E758E08FD1FAAFFDDDF599FF44B0
-:10905000DD5F9FAF8841B914A65B03DE9F8CCD2DE9
-:1090600036821F6937972325DC5EDF0D07B4204F5A
-:109070009AB8DF59724C87DF05DA7D2A17E325930A
-:109080008C4CBEECBE2B8640FCDEA1D3AF3EF11E65
-:109090002D3F77CA88EFE1CDE6FED6DD0271C178BB
-:1090A000DEED26F423561B99BE58BD6F28D3538C92
-:1090B000EE9510D7EDDD26A35FABDAEEDFF40A966E
-:1090C000A73B2966E13E28D37377C5B2F631FEFF90
-:1090D000780DECCE7DA94E2FAD3F3FCDBD0FF09A60
-:1090E0006152E2887AAE2A84EF8B1EF333BDF81802
-:1090F000081E18A7D5C67F47CE953E87F673FCF1AC
-:10910000545C0F95B7A83F1D7FCA84E766CF778F61
-:10911000CBFC9FC7E4627C2FE6D8F67C27B52C49B0
-:1091200057B13100FE6DCFD34C9F9B6550D6007C6C
-:10913000C8BE58A7CE1E7DAA8CBD1F51F9F0E48B86
-:109140009D63837CD7FA773B49280BEDD1F2FE4D26
-:10915000104FDAD93AC4C98EABD2F090A4969F2FA3
-:109160009F90197C437B65A4E7CBED1FE8A2FB77BA
-:10917000EE4482BFDFA63D4F8B3C87E8996778F4C9
-:10918000EC4EE57A9BBEFCD64C7708E45BED33DF12
-:109190001E99AFC078219487C4C7FCE92764D774AF
-:1091A000A0DBF871015D9C9659617C35CBC4F77BDF
-:1091B00012306AF9502D2F1C4BA29EDB9814A60783
-:1091C000D8F8B97364F9FF014BC990C00080000062
-:1091D000000000001F8B080000000000000BC57D90
-:1091E0000B7854D5B5F03E73CEBC92996426992481
-:1091F00093F7C93BE4014308112DEA24040C98D2EB
-:1092000009A062B538BC41C943B0BDB1C5662011E3
-:1092100002A2861A1128E0848762D5367801A34617
-:10922000EF8048B1D5FBC7475BB4F7F78B4A2952AB
-:109230008188964BEFB5F55F6BED7D92394322D86F
-:10924000DBDB3F7CB0D967BFD65E6BEDB5D65E7B0E
-:10925000ED1DB36A602C81C1CF4C334B64EC1AC650
-:109260007F324F316FD0C6984555A9FC9A5321D310
-:109270007CC867AE0C991689D40FE909230B59CA2B
-:1092800021DD620FEECCC2965E86FD2C9A00FF8532
-:10929000A68B64D66629C3EF6A4FBF8BB193079C38
-:1092A0009EF5F09D7DF995CC2A189BCB443D336B00
-:1092B000B7C431F67C9B14B240BDB99BCD3BADD059
-:1092C0005FC56AAF6C87FCC076C9B313EACD6DABDE
-:1092D000CCDF02F93BF7977A64681A83E3603EE8D3
-:1092E0000CCA50FF9AE649ECE3718CCD37074D0A62
-:1092F0007C674F4B6C0FA3FEDBB0FF65D02819E0F5
-:10930000F90A7FAE1F4A176F36C364F9DCBFC27F0C
-:109310008261F96CE8B7BB4B66305FB617BE170EBB
-:109320007D5FA6840E49318CD57747B4677F330FB4
-:10933000D643405980F0E832B13B7C369A74525D96
-:1093400029637FC0FF263366CAF48D53C76326376F
-:1093500069861DE65DC5E735B04F22BCD6B326133E
-:10936000C37E3AE319BB3A6C5C0B0B45437A520E51
-:1093700050F922F3464A6BD42C1AEF4ED66F62395D
-:10938000D8EF80C907E3D9FB80AE2597CEBF06F999
-:1093900060FCC87C3055F0C1B2532C742D8CB76C76
-:1093A000250BD58FE6A91DD2450A0BC4005E170117
-:1093B0000E62451A55C6F1AA160EE16569509F471F
-:1093C0007CAA6178463C869737F67C650ECF279954
-:1093D00018B3C60DD119084570274D6A1ADB047001
-:1093E0005EB3322833985F4ABA77522EC01B5DCEE7
-:1093F000E7DB78DC6251C760DEC7B2A1DE17699592
-:10940000CFE54179A3C2BCDD501E0D78E982EFDBC8
-:10941000AD2C80FD3F9EA752BF6E13E75FA3E263B2
-:10942000636D4897BE9001E992C01CC88F1A3EB781
-:10943000DBA15D19B693A8DD607B0B6B8B0A6B5FBC
-:10944000F5A29531582F175EB007CD509529FE4CE7
-:1094500027F497F87B335B0FF9B32FDA97607F67B8
-:109460008D6C7637D477C9ACA99BF8650DE1FF8781
-:1094700048D7F1C84D55A90C795F9A96CADC58BEF9
-:109480009ABED73B81BF86A1EF607956DFCD9CAFF6
-:10949000CCEA4E18EF82B3FF079807785800F2CB5A
-:1094A000550E77E3FE49637F04DF1B7D360FC7BE91
-:1094B0007F2CF2AB59BEE7660BF0D71479E5C0BD3F
-:1094C000308FFA749BC30C4DAA33FFE3B7B742FE4B
-:1094D00093FD4666463AEF99349B655F0A87962E60
-:1094E0000D1A3FEA0F5B2F77EDD5E7EBBBF5F94699
-:1094F000A67CD4AFF101A0608B6A779D8C26D9E160
-:10950000F90AF8DB6C6E3AD505F09A5F327B56C1EA
-:10951000E706D5BF03D7538361E028E2D99CF9E978
-:10952000683FE0A52AF3CBA3A988FFFB9807E1BE1B
-:1095300060AD9C4BF4D862550361F2AB51F07F678C
-:10954000462D95776E35AB122FAF1D0F726B092D1F
-:1095500061AA623100FE1B374FFD441A4DE516A487
-:109560004727F029B57B4E0AAE82764B362FAE6583
-:10957000507E86054D1680E70F623D35CABD532CDF
-:10958000F0DFCEB89A51285F94BF2A3EA4FF5AEC70
-:10959000EAEA217CBD34B83E2D1D27002F373289E1
-:1095A000C5E2BC9DFE97709EF5967E5325F473FD33
-:1095B0005FBF20B9BCB8F9D59C13E350DE78E71241
-:1095C000BD617E284716DF7B88BE4B332C04DFC984
-:1095D000745BD00CDF5FDD62E679A789F227B74BB9
-:1095E000945FDC2D052D5958FF627C25CAEFED46AE
-:1095F00087995D8AA748BCFC71DBEF621880FC4745
-:10960000102DB8BE98A329C667C7B2A69819A58819
-:10961000AF1B3E41F9B578BBEC09A19C7ED9EEC9E0
-:1096200063989F3C6AA10DDB7F1E5F89F8DB31D90F
-:1096300021D377D987728829DEBEEBE1BBB2E32A5A
-:1096400015D7CB91ED1CEEC54ECB1348E7EBFF2AA7
-:1096500013FF2B06E6DF67433A7847E1BA53B7EDCD
-:109660009982F8FD635D8A81EA3F2B3107E2C3D915
-:109670009C88DF174B8A0FD7D992CD4B6B59CC10F2
-:10968000DED7A832E1BD32736562BF8DF8FE66D4C5
-:1096900077F5DB81CF71FC19EFFFF656D710DF4B62
-:1096A00033364FBF06FB7FD248FCA5F5D3B8EDDBC0
-:1096B000823F180B019E160B3C993357E6E3F8974F
-:1096C0005B0F8B5737E53B6C975F1783EB7D1BACCC
-:1096D0008F62C6FEAA4AEC2BA0034B8B233D33D2EC
-:1096E0007AD4F493ADD0C0F5BE8779F7409A64661A
-:1096F0005E09E457769642E5D95926C287F297E586
-:109700007BDF04F89F53FDD15990CF64DEB1A86789
-:10971000D40147552CF4664306294738CCC13D2473
-:10972000E7200F78DA94C09E581F066786E80FD6A8
-:10973000AB0BFB39FBDE9747118F0D199F8E46BD92
-:10974000DD78F10B930AF4B4F54A24676D1E1F43CC
-:10975000FE68ECAD630B4A86E463A387CBEF4BE472
-:109760004C9691CB33D700F533359BCBB74E275F63
-:109770009F5B9BA38228F7B6BA8256043ABA3CC0D4
-:1097800050BE4F2F973D08B666A7F82C9C5E16EF8B
-:10979000AB4C467EF5C81E14F17DDE8FDBE221FF67
-:1097A00066F9648F0C799B77577B36CEDB6314E5C3
-:1097B00039019CF71B132BC95E99EE95695CB624A1
-:1097C0002688AAA2CFFB8E6B018CFB1DE67DE404EC
-:1097D000D0B1069437D2B10FC7067A9D71F8272011
-:1097E0005EB4F97CDB33F59113E1768697DB03F009
-:1097F00089EBB1F2E1F1305AADBC0EFBB9FE3A4E45
-:1098000087D3CF9A83AB61FCD356D03361FAE2B4ED
-:109810009DEB1D5F9624ECC2EE0C94FB837965945E
-:1098200001D7FD3D0E8E0F97A93B03D7DB9F247D0B
-:109830003F77B6CB2C08726669BBC48200E2E9A709
-:109840009ECF40F9FBC99EE733E685C117D94E4B41
-:10985000BFAB8DD7F198D702E3CD63DA78A1341C82
-:109860006F9EC7FC21CA0FD63ED9DB1F663F90848E
-:109870000CABCF367B497E9F83D5887CA7B53BB7A1
-:1098800024CA8B76E63966094A30D4BC5E3964C690
-:10989000FEBCDE5C17D0BB416B1FD17FA7E01FA9C8
-:1098A000470AD9A17E74C900C9DBA516DFD15428A7
-:1098B0005A8A7484FA53918E12F2ABD784F35624E9
-:1098C0002ECFCF387C7767C1BC1676E8E9989EE545
-:1098D000E0F375B8B83DD86053505F24B6326E07D8
-:1098E0007EDF10447DED8A8A19CDC08E31A5B86D1A
-:1098F00028A7AECF8F6A33C4E2F78C20D64F4F290A
-:10990000A476812ACEDF8144166C95B0CB2689ECF3
-:1099100040473F53E07BDA04E6580FD9DE2C6E2730
-:10992000BA9967B34C7662B78476A286074DBE2398
-:10993000DFA0DC3B2D59886FA45E89EC3ED9D03D79
-:1099400007FB1D898FB644F0D1967F321FED1A9127
-:109950008FFC2AF191DB323C1F81DCFC46F559C0BB
-:10996000A700BE9204BE1E16F265E0FB16A21BFC09
-:109970004838DF5AD15FADC5169247939CF87450B2
-:109980007E433FDBC0FEC47D4A32DACF90A6B6CE1E
-:1099900055B9FDDED72F417FD1575948EF3D60E8DB
-:1099A000CB423B3FA9A8691FF247D29C92B256B264
-:1099B0004FD29C28F751D6E0FC1B9A27F9B81D001E
-:1099C000FD221FD599683FD1706FA58FDB0135B49B
-:1099D0003E1A375855D467937AB356217F34AE0474
-:1099E000FB08E56F4FD79645906F9865F3A09D6291
-:1099F000B5CC2CC176AC5DBFCED649DD641707A6C9
-:109A0000320FCAED734143C03806E56CFF8E1FA1CB
-:109A10001E5F5AE209A8B8DE045FE632D20B9D4E03
-:109A20006F721CE0F5E0DF64DA17758E853CA42FB9
-:109A3000097A76D679939D909FB7C14A78EFECE288
-:109A4000E5E7EC8020E83F45E6FDB1580BD73397BA
-:109A5000CA030BE23D7102D37E36633E45CB773CB1
-:109A600046768CB6DE3BB3383CF6125F165ABEB76C
-:109A7000ABE3FAA260BD27CA066D531440BB3B1A84
-:109A8000C7E4792F0EF7A8010049C1EC7F6FAC9EA7
-:109A9000189EE7F587DA3F30A33A8DF4EB60398200
-:109AA0000D7A57CB7BAD00C75AFB50B902F6A4A57F
-:109AB0004712ED27CC980CAAF89C24C60F281BBD92
-:109AC000808F87AD4C375E387C4A44FF46E8DFA67E
-:109AD0008AFA8152DFE45C80B74C6BBFAAC30BF0FB
-:109AE0003D6CD4F7472815ED31A38DF7EBDCD73764
-:109AF0006E481BD2FF600FD8B3C70FD9016BDFAF21
-:109B0000ED180363453B3E37A17ED5F479A34B2284
-:109B10003B2372BD2665F3F50A766D5236C90D6E8C
-:109B2000EFD6A2BD2B939D3B059756E34A1F43FBFF
-:109B300012EC86D46CB21B3E3D7908BE77CE384D10
-:109B4000767EE34585EC8F46B03FD06EB7F4727BEE
-:109B500096F51849EF6A74BF53C89F4E27E87DE415
-:109B6000D397A5F1C8A78C3565DC043468C9F6E63F
-:109B7000211CDA7E2C12DEEBB2B95DDE5858B52519
-:109B80001FFBDF2D31D4FBEB0B3F4A44FBA4B1F7A5
-:109B9000C3C48561ED96F63C4A7858BAD738ECFCD8
-:109BA000AFCB9669FE0D2F1CF0E27A3F1D94682D15
-:109BB0002F5182EBD0AE5CB2C480961A2B0FCEBD73
-:109BC00015D73D9B6D627930BF5CD44BB89FD83BB5
-:109BD00033700DEEDBE0AF049FB6FA16D1FADE3A31
-:109BE000DB62635908E7BCBB090F8E282FE2617D59
-:109BF0006155328ED35037C581FE9346B0B3B0BCA9
-:109C0000E1DEEF923F45836B7D8FB106EDAF0AB089
-:109C1000B7FE15E04E8F9B56E381F5982AEF1BBBEC
-:109C200002F29B4690BFBFC9E1F46C937C81EFE0E8
-:109C3000BA7F41627BD4A1F2CC1E6ED7DD9CCDED04
-:109C400040EDFBCDD9DCDE9C18E89B84BCF78AD2C2
-:109C50001F8DF66F23F37E86FB4EE6B3A97B884EFD
-:109C60005CEEB85A54F22B595CFD0F8CC1F2890A94
-:109C7000ED2798D2FF088E7B769DCBB39E09FEC55B
-:109C8000FCBD2541DA3F64FBE7237D2B841D79F67B
-:109C9000851BC6CE2B19B293D6755983AB010FEB3A
-:109CA000ECEA4F6A50BEFD4521F9C62C037D939026
-:109CB0001EFF1547FDAEB306D721FD031B8D54BE15
-:109CC0002FC5DF807C79AAAE261FF7C1CC16C8AF9E
-:109CD000037E32BA3A18DA0BB07D203F83C5E563C4
-:109CE0002AE42705E62A12CAF908FB6312FA796802
-:109CF000DF0083C3F72A21B6F2800B4E5A6809B4FD
-:109D00007D153F648F1CFB7296821F353BC560F149
-:109D10002FC5A6D5B3A3988C7CBF66E0A801E61337
-:109D2000EDEA233BB6BE5BA271EA0B9F33A1DFE4F1
-:109D3000AE6EBE2E1BC53E00F09781F6C0DAEC6811
-:109D4000A1C7DB38BFB33EDA47B367383D19837A22
-:109D5000F6F0FDC42AAAA7F5675ACDFD5EF5C21F2D
-:109D6000037290CA7F922D897DED6A9176F0548CB2
-:109D7000BB49EAF3CA88D7B192279C6FB4F4292172
-:109D80002F620F0F4CC1F53B00FC857E992D52DDF3
-:109D9000DDAFC1FCB68C2FF2A009E5067692CBF0C0
-:109DA0003BB022E0BDBCE7B329C8376070D37A6D01
-:109DB000E8A994EB6DA4B769FF9814DDD485E54953
-:109DC0007714925E8D1AC7EE9801DF7F2EF09A6CA1
-:109DD000E37E2EF7EA40D6F2121CDF77F76B387E6F
-:109DE0006914F929938036F6384ADBD12FE466AB43
-:109DF00024ACF7680CEF3FC120DF5157427297F255
-:109E0000711EC9BB13D29E6C27F76799590DC28981
-:109E1000DF693F069C81FB59F473613F49393C3D42
-:109E20009B1C5250406C65FD3BF6207FF6981D88C8
-:109E3000A7DA9E5F1E477D596B61DD32DA2B117602
-:109E4000C6CAF49987903FCF9D39B9E37EF8F6E80A
-:109E50004D073D7EA28BDE7E88DC2FECC42AC92311
-:109E6000DB7BBFCBD6DB7B83F97FB8BDC7EDFAC008
-:109E70009E68754F983C6F14FBB4734BCEC7A09E81
-:109E8000F97890BF404F570CD92BF376477F88EB7A
-:109E90006AD0EE8FB01B8E3D111D40FA9FEFB69237
-:109EA0009F4E41BB07E039631FF80122C765F27975
-:109EB00025DC3FEC337A56437F8D779EFEB901D681
-:109EC0009DD205764F2CDAFB6A2CC9D9D765B60727
-:109ED000ED32C5EB40BF8706BFE29CE2F696A05C80
-:109EE000E4F35F660AE5931D64624B281F13CA47BB
-:109EF000BBE725A1779645411EBE37BBFD7F41BA22
-:109F0000A598B9BCC276F8BD4BD85B5D801207E25C
-:109F1000E538ECBBB384FEC6FDCF83E9C1F5E4C7E9
-:109F2000B1103D3F7EC5BC13FD3C1F171A4226EE03
-:109F300097203F96DAAEB064A8AF1EB70655EEEF95
-:109F4000B21840FFCF7FF8AE37705F31FF15EEC714
-:109F50009A7FE7CAE9B8FFF878C61413CA9B85CC84
-:109F60004F7EE7C58CFBA197B220F757338701C717
-:109F7000BB0BC4C656143501C0FE55F059324868B3
-:109F800057A86D9027A3D9DB5103E3CE6B33D0BE26
-:109F9000647EBBDE9F7E61FDDD35A8C7D7B619B8EC
-:109FA000FDD82E911E9FCFBC6EB43B34BC16E4C4CA
-:109FB00073FF689BC18BE35C9F6322FE03120569FC
-:109FC0007E226D330A3FBC80631533843035483CB4
-:109FD0005DEB506A86D3CF5A7F6DC6260BFAC30657
-:109FE000D20DE407BE60F2CE263F6A5C3E433F627C
-:109FF0009BBDA9BD8697D39AB9601DF051F9B50AEA
-:10A0000037F8981A87F2323D87DB0F91F35DD8A1BC
-:10A01000CF479E4F2C0DEAF3F399BF203907FD4639
-:10A02000FAEFE9395C5E5D589F25CE013C740ED095
-:10A030006654DFCE4279B54E2179B92A8DE3CB90B3
-:10A04000CED36C67F56CE25F27D817042F873FFBF0
-:10A050005A97847AB3CDC9F9F27F0A7724BC37E4E2
-:10A06000E413BC6D68E4C1786DEBA420C71787FBCF
-:10A070004AFD174B72F4726830FF8FDF77727E5C97
-:10A08000278BF5E6203934CFC1E7F4B1E479228497
-:10A09000DF6D601F00DCF3D7C96568A74C9A69A320
-:10A0A0007934BC62257F6BFDCAFE0CB267ABFAF354
-:10A0B0009B86C12B42AB68F20BEACD73C13E01D740
-:10A0C0006DBBFE9C0A342D0B3F779A99E6BD2F2776
-:10A0D00001F7231FEFFB25D27B9F95F413FCEF9034
-:10A0E00019E5D70B596437E5A7F9EFCF41BD1E1528
-:10A0F000DAF16416DA29DC4EAAEF3577A11D38AF04
-:10A100002DECDC0BFFD9A03F0763ED71E4DF609D10
-:10A11000FAEF4BB645B4BBE45C8CEBFB4D26FF2855
-:10A12000B4EFAEBFCE9B8C72F5CC520343FACE9700
-:10A130003D8B508E9CB1EAEDEF33764EAFDD8374EC
-:10A14000F6E4239D778F48674F3ED279BE81F9C3ED
-:10A15000FBA9473A037D97093A9F3970553ED2F9DA
-:10A16000D37D57E5239D37193BBCB86E7665FAF76A
-:10A17000221E4F4CF691FD04F22AFF9BF0E38B1157
-:10A18000FCF8E2FF1E3F52BB91F4E1D19CE1F5A146
-:10A19000CBA4A6A13C9C67317FAD5EC49F61FD6BE3
-:10A1A0001633F9255EF9F2F3879E403BA457263B10
-:10A1B00044EBEF15C59F837E85578EBB3D0169E457
-:10A1C000FEEF16FB18B78505D0FFA1D9FD9AFD1843
-:10A1D000298FDF17783C9DE3FD36ED1785BF768923
-:10A1E000E8D312FC9CDBA9BB25F2C75AD46E2FDA48
-:10A1F000BD0D2FCF75A0BFF65490FB671B0E8C25AD
-:10A20000FFEDD2E0ABA154B40B7B2507EE1F96EE19
-:10A21000FE3006CFBB613FFA494ED87E74B2D88F6C
-:10A220009E0A7E1C83E7E230FE54D4CBD1AE0113EC
-:10A23000F26F03ECD3A00A6B50068E627F0D2EE600
-:10A2400009A0A8E8D1EFDBB4F3CBAD3E13C9BBAD99
-:10A25000BD5210F76989267F561AEA2796E6A07341
-:10A260002EB15EFE33C79B983B3EFCDCD8FB971CAF
-:10A270007EAE4CEDFBB7C4121FF61B9997EC802DF8
-:10A280007621971492537FDEE6A47D0FFD40FD3FBB
-:10A2900007B328AFE9EB450A0B2980F745B3BCEFBC
-:10A2A00021DD507E8722E477787EF03C9AF571FDBF
-:10A2B00002F23C34DCF9B838A7C6F3DDF0F60D6CD9
-:10A2C00080DAE139AFAE5F6D1FC09AC6AA00F75DB4
-:10A2D000B7DB3C68BF34025F37970DF1E1323115CF
-:10A2E0008D0F1B849FB771C947B41F68EC911CE8A0
-:10A2F000DF5DE6E17CB80CF649E6D197AE5BD60DA2
-:10A300007C1806F748EB785CAE7E1D0FE6FF49FE31
-:10A31000CCEB72F5EB579BBFE6171F9C67AFC4D71A
-:10A3200057C4BC22F79791FE6C6D7F78A572EDA69D
-:10A33000087CDCF4BF8C8F91E4DADCDC91E49AFEDB
-:10A34000BCE01BCBB5C873835CEE07C773033CD777
-:10A35000FD9F9E1B7CA276241A480F7A75E7A96898
-:10A36000A7E338EDDB65B20FA6C8FC1CBADE6E268B
-:10A370003F6DE4796BA33A459C2FF6FDF66AD49FB6
-:10A38000FB8D0CF5FA12DB623ACF6C949F3139D415
-:10A3900061CE19954364BF7FD3F3F775B983E7EFB7
-:10A3A0005978FEFEAAEDF3787F185DAB4AC0D02F36
-:10A3B000A1389661E5F623824FA245FC8445093019
-:10A3C0006758FB91DAFD3497DBCBAF8A381AB7892F
-:10A3D000B5637CC6C3F6682FEE4BDC061EE7D3924E
-:10A3E000EDDB8E72D2A2723C3FFEC22DCC00F37F19
-:10A3F000DCD84DF224506FF3A05CD4FC305AFF56E9
-:10A40000B15FBD52FE3F30C8779CFF07F3FF247950
-:10A41000F06FDA78DFF49C6C33E046B74E189D8716
-:10A42000BD81E73B5997F2F348FD8CC4D76FE7FA3B
-:10A43000DECC25B9E01D4DE7FE572877A2CB073EBD
-:10A44000467F0FDB6F5671DF817E0FD2971B92B96B
-:10A450001E533C158867B0F72A304EEA03FCEFD54F
-:10A4600023DB87A706E513B70F4F8D289FFE3EFB22
-:10A47000F04799BED3C867272ABDF9A83FD7DA01AC
-:10A480007EDCF73DC5E36BB659397F6E93385FB21A
-:10A49000E678CD7F42F30A3CCBCFC723F98AE5E9C2
-:10A4A000F96A30FF4F96ABB64138FE97E5EA92FF66
-:10A4B0008A413FE8C8FD04886E15557D84B78197B1
-:10A4C00025B633CC3FDDD8C7E3D4D205BCDAF70BD1
-:10A4D000C2DE5D94E7CDC078AF4FDFB358582C98FB
-:10A4E00042C8636897F96C743ED0D0CDE3481A56E1
-:10A4F000323A0F6E40FF6709FA05EB18DA7FCFA9F1
-:10A50000FEC2BCF1789E610BC8B1E8379FC1D0EEA6
-:10A510003BFB1ECF37A8FE122C6F5CD9AF3B87A840
-:10A52000F8EAF335E8D70078C94FE042BF4D189DEF
-:10A5300066E7F1F84B2DBD29027EF4E313FF77CBDC
-:10A5400041B417A3D53E3A1768D8CF8DB80AD94B76
-:10A55000FE7B76571C433E6AD85F39F635AA6F1DDD
-:10A560008BF66EC5EF6B1DE8A7F8F45A17C51F648C
-:10A57000C8FD4BD1DE3A92ED9F84F8B09707A7A2B1
-:10A58000BD9A09F62ADABF9FEE9B3A16E1D6E4DFC0
-:10A5900026F47F43BF9BEC7AFF36B378B3EE47FFD8
-:10A5A000F7CE24DA3FEE4BF17F1BE7BFC9CAE10DBE
-:10A5B0006CB4F2F52AFCDE91EB5F5BF749B281C621
-:10A5C00049BACD42E7D49A5CD864647E4BCE903CC5
-:10A5D0001927E2E9001F3C9EAFB78EC78188BCCD2A
-:10A5E000A58F6B3C9D33791CC2332E4FA1760B2D6A
-:10A5F0000312FAE1178AF3F91B449C85166775C6A6
-:10A60000E15B80F8602B6B86CEE5B3B1BD83F3BF11
-:10A61000889F89BEC8EDE86C8789F8C6DECEF8B998
-:10A6200012F00DD267E240DFA458984F6E6768229F
-:10A63000E2F3958B06C28752F7069DA7C422D9A0E4
-:10A640009F9C0DFDEB0AD09FE278F75AA48BDAE1CC
-:10A65000A842D43DA7FAEEC9A375DE5488FBCBAA65
-:10A66000DF1879BCE0CBD1640774662CA378C1B342
-:10A67000EF03BF665DAA0FB434C056537C6076CF3B
-:10A680003BE4D7B7EF97868DFB7C38CFC6E36F02EC
-:10A690007D1487C626BA081FCACBBF0FA0FDA1AC88
-:10A6A00053C893D166F41AAC48D7558CFCF0799D09
-:10A6B0000E03D22553C49D9C7BE5BF47FB69BFA217
-:10A6C000F9F1833C4EC8D8BF06F75FCAAAFEEB601B
-:10A6D00005B3FAFD4E4303FA3D8D030DE437793996
-:10A6E0009AFCA3993D39ABBF05F9CC76079350FE90
-:10A6F000BC785726F27500E69937CC3C9BF38CB4B6
-:10A700005E9497A30DA8B7948D8CE214156762151B
-:10A71000C1FD28E4A19FE5826FB4F34900D78DFA0B
-:10A7200068519E7F37D23B5AC801D61C45FE44BBB8
-:10A73000C2FD1EF6E6F79F5D05F91DC21F7BF89569
-:10A74000E219E4BF5BA74848870BCEB9990EF8FE23
-:10A750008B3C6E8FD8953EE6B085E3FF30C56566CD
-:10A76000BFCCE3D61423E713659DAB0BFD835FA439
-:10A77000F929FEF4DAB6904CE75B8E138FD4A8610A
-:10A78000FB9BCD5C8F34ECE5FBEAC8FDCCE5F4C760
-:10A79000B13CBD5D3E98FF27D925EF0C8EFF77EECB
-:10A7A00053987E7F17699F44EEE72EB1BF23FA1BB3
-:10A7B000C94ED1E23CAA86C6217E78D5AED94101E8
-:10A7C0005D1C4C958D8FCB2CFAFE9F12F13B5A5C91
-:10A7D0004C62ABBA0AE3CF07EE63E46FD3E276B420
-:10A7E000389D4015DF47040C20F7B2F07CA883E2C7
-:10A7F0007352594892683FD0CFB07D12C6E940FBF2
-:10A80000FEBC6C827F3BF3B4CB24175509E1B762E1
-:10A810007C473CC21DDCB208C7BBC946E35931BE08
-:10A82000239EF611B48E537C3CAE73D2121E0F9A47
-:10A8300002FA17F329B99C2FADB34D14E7A9C56DE2
-:10A8400068F11D1A5EAA04BE530A1665E17E418BAB
-:10A8500003D914157CCA2A63FC8790FB4B0D24F79F
-:10A86000B5F8BACE3C3588FC7E0EE3406D571EEF3E
-:10A8700011895F2DEEE3FA747F72FE788AFB203D2A
-:10A88000AAC56B68FC1246C78015C6DFFA32B7DF6F
-:10A89000AB969808FE734BA7917FF1DC5203C3750A
-:10A8A00054D56BE6FC1731DED6D92616C27E95A0AC
-:10A8B00015E5A7C60797B35F81AE85E8BF3DDCB25B
-:10A8C00037E704ACF9232DDD949EB34ADDF2184C32
-:10A8D00007E6A0A41AFD64C64CE56A8C6319C8900B
-:10A8E0008075CAF6E6CEA27CC2C007989FF6E4AC9B
-:10A8F000590AE8897379033B24A8EF2FF87026E5FD
-:10A90000912753189BF0C46F660668DEDC1F35493B
-:10A91000F8A3CC4EFFB5F909785FA07F4D1FF97DF4
-:10A9200078DC3FC605223DDC3613D9376E118FC95E
-:10A93000AA457C269ECC40BE35792C9D67DB98BA13
-:10A94000BF0FCBD3CC5CDF33CECFAD79DC5F4C2AED
-:10A950001265679AE65FEA0FA0BC6ACD7252FB41AE
-:10A96000B9BADF1CE47E2E3EFE5B074AE91C4A8B27
-:10A970003365CC913EAB94E25174F987ADFC5C94A5
-:10A98000298E74B41F5A8DC24E15F9A834FF77F37F
-:10A99000C3ECA4B726FF4B09AE8733077F948B72B5
-:10A9A000EA0613D8F1C3C8A5D4422E97CE196DED8F
-:10A9B00012D86D6FA4FAE723BE8E47CF99E284794F
-:10A9C000CD8EAF343911DEC05332CAC904416FE7AE
-:10A9D0002C0E9FB3DA272D847E5BADB09EA17D82C5
-:10A9E0005FF192BDEE9F25DD0470B74AC27E676AB3
-:10A9F0002CD9ED856A2C9EFB2D6B7E87E2AE6521FE
-:10AA000007642107DE6EE9CF55F240E5766F94D1F9
-:10AA1000DE7E479C3FBF93C5EEA81B66FFBB299F08
-:10AA2000DB873364B514F9C875FFC4776A812F6476
-:10AA3000932748F44BB7ABC8EF87EC15EE7EE84799
-:10AA4000CABCAF1CE3965BD3EF2BC7B81339CEE378
-:10AA5000F685E537E5733EAEC67A88B7E8A672D4C8
-:10AA600063FFB0FE62A1BF92BFBFBFC17ECC1CAE70
-:10AA70006596810C05D6A7C7EDDF8A74BB30F74316
-:10AA80003A8FFD41CA5B1F60FCC45BC68E4931280A
-:10AA900087B224C1B7DC5E3B5AA0F93D79DCFBD11B
-:10AAA00062EEF70439C4E32B4BF93D9BDA598CD69F
-:10AAB00073AD88BB98E2E0F796A69467795A616A0D
-:10AAC000D3D98082727ACA715F0CD28FCDF297FB94
-:10AAD0004A47B6C398DBA886CB95A96A581EFEDE06
-:10AAE00058A8CF7FDBA3CF7F67C25F0BC2F31BDD0C
-:10AAF000DEE771DE2F493C8E33703573D03C5D52FA
-:10AB000000EDA5E2E753BA847F97E20D7F26F67346
-:10AB1000CF4F60549EB8D7B213EF1F687E7259941E
-:10AB200017BB9925338EF0417A764012718B2E3AFD
-:10AB30000B6207EF7670FC415D13F47370AE4AEB65
-:10AB400038D16660D7E15A2FB790FDA4AD8B562B54
-:10AB5000F037E0B122D51285FCDE6AF46CC6BEE4A3
-:10AB600028B38A7AB532C6427DCB3F56482FADB264
-:10AB70009A29F4F5F0835194AF50980FE33500C44F
-:10AB80005998BE65F4049B70BE500FE7DBEA64245D
-:10AB9000AFE40A13E969E897E87A78A321C868FE68
-:10ABA000950AC5630A98B5750723D1F7C7C4BA9645
-:10ABB0000D2C44722CC54272EC08F48FFD1E7E5D94
-:10ABC000EE223F5BA17A3B969FB714D0FD9CC6C195
-:10ABD0007B478A01812B147694B397DF0FD3D6B3CA
-:10ABE000265F22D73348C15C5722E320AAF80F4CD6
-:10ABF0002311F53E237B5E3B3F4CB768E58A17C7C0
-:10AC0000491EACCFEF67258A7C6A4116AD37A81282
-:10AC10003294A1FDF1CBBF20DF6AF261C7DA1F9346
-:10AC20007CB814FF85DFA7FC34BB83E3BF200DD7BE
-:10AC3000A11C559086FAAED5E9517D61F94258467E
-:10AC4000B3E3103F500FF2336B3ECC55C2FC83A9E7
-:10AC5000052A094BA8E78D07380E5BD5345CAFC3D6
-:10AC60008C5BCFC78DFEC78EEB8671A1DE613B8CFE
-:10AC70000BF5765BCD2143CC70E34F5071BCCB8D8F
-:10AC80000BE824A44E137806BE08A05FEAB0DD40AE
-:10AC9000FC394DC4EF1E4EE0E3B1427D7C4D6E1495
-:10ACA0008C4FFE587D3CCD0DD2B636D4CB8F596338
-:10ACB00076223FFE52F0C9D1E81FE7A25DF5CB39FD
-:10ACC000F94750AE4C895DD5864C328D7593BCD119
-:10ACD000E4DE85E40F2B300FF2EF9A02A0FB0FB2F7
-:10ACE000DF9A839D1F713E968BFA0FE4C3B70A1259
-:10ACF0002E855FE3470D6EE4435C07837C1801BF3C
-:10AD0000C6476C7A3705206E07BB1453CD4E65AC31
-:10AD100089C789ABE943F303269E6269E2F35815BC
-:10AD200020B86F703E42F168D78EF2FB10DED96317
-:10AD30003ECB50B0B27B6E01EEC300DEBAFF9FF097
-:10AD400046DAE5978B97D6E08A5CC7DAF8D28CBDF5
-:10AD5000142FDD38CB46F1D39344DC69E31203C5ED
-:10AD600011C1FE8DECFE066609A21CBE46D8D15A62
-:10AD70001CFF8B12F77F060E98D53D61F6F8A57182
-:10AD8000D42AC5690756F278EB417BBB9EDBDB8397
-:10AD90007A4DDC1BE81CCB6579E7DD2AC553BC2462
-:10ADA000F1FA81B98CDBEB75A27CA143C45BC05C7A
-:10ADB0001287E2D93BBB18F17FA73D9BCA5364AE13
-:10ADC0007FD8B7B8FEE9CCE2F664E7ADF9540EFBE4
-:10ADD000825188F7F932D8CFFCFC9EEF0FF2F87859
-:10ADE000917EDA4D05DC2E1BB473443ED22FBB2B73
-:10ADF000D3BF05F9656189374302BE9A6FE27E577A
-:10AE0000E0BB6D7867A68635ED5672F0FE45D3BB84
-:10AE1000861CE2BBC789EF8A81EF72747C172C18FD
-:10AE2000CFE52F0A538DEF06F9AD30325ECEFF1419
-:10AE30008EDBE9ECFE7D03EE2B7ACD44072DEE315F
-:10AE4000729D87C173C2C8E171C932C1B36F3878CE
-:10AE5000AE84FFC3F92D89713E1F691D24292C6022
-:10AE60002F1B5A071BDDFE10C23FB81ED6F07DE433
-:10AE70002570CB36E28B9B6F9539BF46737D8EE78D
-:10AE80004DC9307E9D18FFE675BE6A27D6AB930884
-:10AE90000F75BDF51417C6AAF9B99107FE203CAD90
-:10AEA00042CE69E75BB345FB998E3A23FAE366D558
-:10AEB000EACF9966DBF839D6CDB38C1F85DB3DB37D
-:10AEC000D986CF308E71369E4369F5818FDE2F187B
-:10AED0003C872AC073A823C2CF720EF81AF9FEB5B8
-:10AEE00084C5DBEE06BE2BF8694919FAE326272E46
-:10AEF000DDBD11F24F6E2DA2FC6B89B7DDF3169606
-:10AF0000EFC8A77CB541223E3D57CFDB1756DC3A50
-:10AF10002D2B06E5BFE817D713EED7A3FC9D755080
-:10AF2000CF3D3ABB0CE34BAB85DFE0DCDD8CCA6F79
-:10AF30001C63E721BB8B55F2FB554789F2EFF17E8D
-:10AF4000DF18FBBB328C33AECE1E9883FCFD46D996
-:10AF50004B45983F227D3667B873AFE24229340AE9
-:10AF6000F0521DC7EBD7963D95827E98EA2A9E2F18
-:10AF7000F654AECBC172C3F939C3DDFF8D12FB9E0F
-:10AF8000C1FB6C625D3FEFFD90EEAFF92C9207A71D
-:10AF9000E89BF021F91D984D72A0EBCCE7CD52D083
-:10AFA000CF3DC9CBE350AB2CAB92517E4DF79BCA42
-:10AFB000319ED861197B04E30C6227548E47BA4E48
-:10AFC000B230A22BF0794C21FAB5AFFA2C230699B6
-:10AFD000CBA6E7738D8FEA34FEAED6F331AC4F5774
-:10AFE000E1F8CBCBDB91F818C6CFC0F6B3BFA5D73D
-:10AFF0003783FD45ACB7C8FE479203F8132E178779
-:10B00000E0E8A6759586D17D39B8EE3AB475370675
-:10B01000E13019FAE81E4FA6E429A20BAD133C1645
-:10B02000D24711706BF0A5836C636597C2853F8A28
-:10B03000662F72081C8E441C9797433B2F8B1B82F4
-:10B040000BC6BF1EE9C0D67078B64B4D5C6E88FD4E
-:10B0500081E6CF68D0E6DBA39F6F4514BFD7EE46ED
-:10B06000BF13B6738D2DFA3AB81B853E9D65F13D31
-:10B07000688639DCE49C4FFC700B683427CCFF6F8A
-:10B08000A9FE3AC447AB1478B93F8BFCF114FF0119
-:10B09000F49E51186607687045E2A36104791809A7
-:10B0A00077241E86E8D3978CA9761F6E705E11F305
-:10B0B00069B5F3F53A30DECCDFB550C01485FC9BA2
-:10B0C0005211C5A16870BD2971BF6440E2F78F3489
-:10B0D0007B2212BEC87B7A1A5CE8EFE3700CACC22C
-:10B0E0003B820F166A7E3E4EAF24019FC9200D7B26
-:10B0F0001EFE60A141F3B3EAE819797F4DC39B16A8
-:10B10000E715892F2D4EEB9273B78873E591EA49C5
-:10B1100060A7A7C65D8A47EDDC2E6ED04FC9FD4003
-:10B1200003F7DA490EC60DFA298F2968DF4FF21CA2
-:10B1300052D02EAFAD8109000DDE147E1F0DDF0F42
-:10B1400064F8B71492DEEE1F8FFE959F4C7D82CE81
-:10B15000AB3E30703F7D247EF68C809F91F87D243D
-:10B16000F8A3D27C4FE2B867A4BE0A2CECCC16E759
-:10B1700042CC9F85EBC1E9C8AA44FF11C8D7AFBE36
-:10B18000C24D2B16015DCB33FDBFC076B730DF64F7
-:10B19000A46F5C8DDFC8CF4918F9E1978BFDE3649C
-:10B1A000A177CF6FE3F11ED5DE518F4D44BBF198EF
-:10B1B000910569DD7B497FDE25E03F0F2A3684F566
-:10B1C0009FB193FE5DFCFA7C8AE328D86C187A4F15
-:10B1D00003FE8E0A46E9DED328DE1BA7CB9776A7AF
-:10B1E000E8EA8FE9C9D6958F0D15E9CAC71D2BD39B
-:10B1F000E5C7F75DA3AB7FD5F12A5DFEEAFE69BA2C
-:10B20000FADF3A354397BF76E0BBBAFA1F0FFA0F61
-:10B2100084DD10F0F615C2BC1788795F7F719EAE91
-:10B22000FD9F62A61C437E5CB081C7A55702867451
-:10B23000EF8B7470FBA209FE207D27B3018A076C97
-:10B24000084A9E10C3F836BDFDB1B4A78BF078B99B
-:10B25000FBF805AEB90634B94F170AFBE32A761599
-:10B260008F67FD7ABAE6B3BCBF8BAE66B79EAE56AB
-:10B27000554FD7E8423D5DED1E3D5D6327E8E9EAA5
-:10B28000F4EAE91A5FA3A76B824F4FD7A4D97ABA21
-:10B2900026FBF5744D5DA2A76B7A939EAE99CD7A8D
-:10B2A000BA6505EED4958F446F4D9EE6B42FD7D581
-:10B2B0001FA4BB6F09C537E575FC50D7BF46F70023
-:10B2C000FC41BA17301187F93FA47BE1283DBD410D
-:10B2D0006F8D1A359EEC8D124C671708BBDE37BC9C
-:10B2E000BDA1C99F70FD1EBEAF1D492E5DA2CFC47A
-:10B2F0003E77447D16B1CF7D8F81BEA5413690DF6C
-:10B30000EA56C19F87A338DE3FC7A2ABA11ED499DE
-:10B310000070BD8770C338EF4515933FE2BBACDBCF
-:10B3200088FDDFCEFA289DC30628F53307E9EF79BB
-:10B33000CC43E902E63309FFC4F45109E8B7E8AFAA
-:10B3400040FD7F61EE5B1FD0B9D61BF157F40EC5EF
-:10B3500047787E92C7D849210F4EE0390AE4CF5A88
-:10B3600007F5ABEA0AC3DB49E16F9C3749223DCDC3
-:10B37000E4288AEF9A778B44E744F3FE93A78B4641
-:10B38000493C1E24226D6DD6F0C7F7473B47A90400
-:10B39000471AEB16F61CF3DB72A81F7EEEB1CB4406
-:10B3A000FB58B785C3F7ACC4940971741D8EE8EAE5
-:10B3B000B670789E35320BE2F369E65791180F2884
-:10B3C00020A2F83D8C22E48F79FFF95636FAE9A2E3
-:10B3D000A25E98557D359ECB0456919FFC7B4CEF29
-:10B3E00027BFBD49223FF9F7004E48DD0E8F1BED08
-:10B3F0007C2DFFB080B71AEBC1F7247793847EA928
-:10B400007F587FFB7FC8EBFD9DFD0DF6C3385CF8D0
-:10B4100083F4D3FC9E85061E27317037DF1FEDFEB7
-:10B420001EE3FEBBE6406500CF45653094308ECA12
-:10B43000C8EFC7EF1CC5FD9EC9AC8FFC0BECA8661E
-:10B44000D7FA49FE9688FB1767C5B9E2A22E0BC34F
-:10B45000389D927D87E2F01C7111F0601FEA61C592
-:10B460004FEFBF946C792D8EFBFD8C4EBC57A9E934
-:10B47000FF91F9546127C3EE3100DF350D677FBCC2
-:10B480005AC4E3035A5BFA46E139A006CFFD2DC743
-:10B49000282F2B1E86E797F83E5478FCA3C905E5B4
-:10B4A00061F24EB141FB303964B4F9E89195352D24
-:10B4B0007D74BE6814EF58AD4D5BEEF087D9898777
-:10B4C0004609FBC71260B84FE02A0A53E524CAB503
-:10B4D000FF627C1F6D76433FE1F2F362020B3F1F78
-:10B4E000686F394EF0AE91FC7EECC49CCB4256A006
-:10B4F0008F59C1BBC0F07DCB0DC7308ECB645FEEE2
-:10B5000009A923E3CDEC562E84CBD3B723E4E94F2E
-:10B510005A068A719CD6967E0D5F0CCF6B03C9DCF0
-:10B52000BE6E6DF984BE1BC03E447E7B754BC1214F
-:10B5300015CA3F80BFF8DE8ED9C5E162175DA457FA
-:10B54000E7083E405F5C3AF0CF07CD46E2B315E92D
-:10B55000363A2758F166DE212FAC67134C57FE06AA
-:10B56000700F8DC3F16412F214F8C987F2C194A26E
-:10B57000D079419C6306D1E9EFED4FC3AFC9CAE86A
-:10B580009D2453BA8DEC822B85F36FA3F83B408347
-:10B59000F6C94517C9FF15022FDABB4F1FDCC3C818
-:10B5A000DFB3E25EEE375C51CFE81E026B869F8A06
-:10B5B00021BED1F44C02BE50031F3B5A60C5411757
-:10B5C0000FB55898BF00EC108CDBCF19A2638757DA
-:10B5D000716288C1C66A571DA60F4D38D181E2EF4E
-:10B5E000E1895FF4618A670438BEA38905D13EA66C
-:10B5F000B37F18DFB904F2307E8C288FF1F37CAC76
-:10B60000288F9DCDF3E9DEE7A46A042CE23C2BDD14
-:10B6100016373517E5F402C6EF818B7720B60B7D20
-:10B62000916A8BABABC6F2DB19DD0BD1CA7F2ACA9C
-:10B63000936D1FB5E7A01E99A56FBF45E021C9F620
-:10B6400051C7243AF7D2976BE74A09B6F3C7A87DEA
-:10B6500089BEFC51D1DE6E3BDF3709CB73F5E33F8A
-:10B6600028CAA36D5C1E321FE3EF1588F20744B9A8
-:10B6700015CB717C0F2F97B5773944BD75020E8CB1
-:10B68000A923BFEB28EE77DDD1622921BAB45C246F
-:10B69000FA3CD4C2287F6B511CC909430DC7779C63
-:10B6A0008BF383A3990DFB4EC1AD42AEC5A8FD5EE1
-:10B6B000EF30724F2B8F73F0771864B789F8C96C2D
-:10B6C000137243ACC741B92135793893713FFDE519
-:10B6D000F81A16DA05B48F32E007F93AED1E03F3D3
-:10B6E00087C9CB946551CC1F56DFBD204E974FBC08
-:10B6F0003D4557DF352B5B576E2B2FD295B35971D4
-:10B70000B46E960BFE8A2A29D3956BEF43B0DDA267
-:10B710009E58BFC6DC6B74F5CE17AAB1C8E327A745
-:10B7200082FEA178068F05E5C3727B7612EA9FA799
-:10B730005B2610729E857505462B7BC6C9E3DC9F90
-:10B74000C1F34328FF598B97BEEF817215D25DB0CC
-:10B75000EE54A8DFD5E2A0FCE32D6E4AB7B7A8945B
-:10B76000FEB4A590CAB7B47828FF18F48FE9A3D027
-:10B770000F7E7FA4A586F21B5B7C947FB86536E5BF
-:10B780001F6CF153FA40CB12FABEAEA589F26B5B87
-:10B790009A29BDBF2540696B4B3B6F57C4F5CC332D
-:10B7A000E25EED3395FCBE7C241D3B8B841F52C4AE
-:10B7B000ADD887E2563A8B306EA5BB9FEC702D6EEC
-:10B7C00005E74DFD59F9FC23FB7BAA88DB6F45ACEF
-:10B7D0006F55345FCF743E9CD7E3591D0D7C9FDAC3
-:10B7E000C4E990D53340E5C94B382D9E12FCC95CA5
-:10B7F00001965641510254EFACD45715CDCFD529FF
-:10B80000CE91B9619E15E2FD2662BBA001E15226F0
-:10B8100070FDA9D17570DE4E0E27CE7F3878F70BFC
-:10B8200078E5F26EFE2E4B4D4708D93ECADB44EF59
-:10B83000B25866FB420AA42E9F9FDE8928BA3805BB
-:10B840003667206F2E5EC75448D396E9F76D290BF3
-:10B85000CA74FB22F9E2434C0539602BD1EFAFA249
-:10B860007297EBDA59D27EA82B37B956EBCAE7DDCF
-:10B8700095B5C68DF84CE5E74BE60DAB5832C0B533
-:10B88000B07323C1F59198C75949A5FBE5817D5A4D
-:10B89000BC05DF5F3C29F40BB36C207BACC0C9B3A3
-:10B8A000F9B10103EA874FFF3596E4D2138F1B826B
-:10B8B000E84706F164C0F55F0C661F9697B27ECA32
-:10B8C00063A80CE6C73255C6FC383640FB2BD85F60
-:10B8D000BC5F8471ABB2FF712BE4CFA4FB9FE4711A
-:10B8E0007321D29FF9829EF9DA7E6AB312E95FEE84
-:10B8F0002F22FF8DFE7E5D9BD85FB459B99F6E9558
-:10B90000B32209EDD6B323C439DADDAF1E5D00F8EA
-:10B91000B6271FA274D02FA71A86BD3FFE4504FF8D
-:10B920008F026617FCFF05F2FF99F2B713D10DD510
-:10B93000903B40EBE0ACE475CF45FCBE2E737E84BB
-:10B940001D17CE4F11F855F655BAE7021E953773FD
-:10B950003C013634CE132DC773300E41CBE78B3804
-:10B96000DDBD2DC9B9D561DFD5624EC742D657833B
-:10B97000FAAAB0C4E00962C75E87CE8F61CDEDF050
-:10B98000E27B084A19F3A0981BC53A56A3EE56FE6F
-:10B9900026539C9572F86AA6C27EC6660B318C4B04
-:10B9A000D3FA65C21F728F909B5F38AA63E99DCB63
-:10B9B0009441F9873A927D61F3F6211F7DD169E4C4
-:10B9C000F33AAC2F2FB471BFE1A242535095F05D12
-:10B9D000B50E7AC751D921B1B42C846312E1811D0F
-:10B9E0008C263E8CDE3C9A0560BD943BFD9662F44D
-:10B9F000DB85D483861CC19350AFBED8B413EDB39E
-:10BA000002C48B0DF1726B6E350E9D5B48F85D289C
-:10BA1000E63DBE98D3AB2D3D021EE6F1E27BA78B3F
-:10BA20003A353F8E7E9E0F96577D07DF856CED93EE
-:10BA3000B95A8BC0E77A63DFE8B9D0F5997E804BBD
-:10BA40002638C717A30DBAB98205488FF3F9D53F39
-:10BA50002EB1AD5924976A488F8F37B0F0F3532D2C
-:10BA60009D58CCE5EFB1221E876A771F257E1CCA40
-:10BA70001F39BA00F0F1B48115D2B9B181EF8FB599
-:10BA8000781D19FD0078AFA158C845D6C6A6A1DE1D
-:10BA9000761A28FE54EE8AA27BB3B253A1B8F736C9
-:10BAA0005BB5E34EECC7A1D039D11479621FDAD16E
-:10BAB00066A7611CDAE14776FEB00FE386E4748581
-:10BAC000A1DFABCDA1703B24CD40F1808AB3DA82F7
-:10BAD000E74AF9B6139588CF435D3FA07722E4EF9C
-:10BAE0008B981DE117330A92B5B126EA3F90A688DC
-:10BAF000F766BCB56313C591888AFBA19A4F70BFE6
-:10BB00007DC471DE8AFB02D5B688FC81F715F37D12
-:10BB1000A211CF0F21FFF8CAF34E945FAF77AD8922
-:10BB2000CB427B3AA8902D52F8D7D6147A0FA1CBEE
-:10BB300044EF356878CD0C28BA73C8F4667DDE1CF6
-:10BB4000711E698CB827B75C8C8F2797A1B0F91844
-:10BB5000DD7CFFC65C36DAFFDC572CDEE914F97BAE
-:10BB6000447EAF3190E201FC1CEE5A9489F3BAF0A6
-:10BB7000829FE2CE47B2FF2715AB62BC80D540EF73
-:10BB80000287AC1887BEBB8579D0CEB30415BA073F
-:10BB9000B047C8B35C1BE7FF3B4AF87A8D4C733B58
-:10BBA000F8BA539E890A4623DD1CDD650158E7C5B6
-:10BBB000AF4E652AE8C15C87D780FEF7DC66930745
-:10BBC000EDCF29BFB0119F9CB7F1382EA5F9011513
-:10BBD000BFB7EEAC2854C3E00EB6383C289F76B60B
-:10BBE000583C181B1F1C41BEE6380D143FAF1A7895
-:10BBF0003CE72EB11E7715F3F788760A39B34B0967
-:10BC0000CC403877013D316EFFD0066E1F2F5F6547
-:10BC1000213896BF9E43F6D548787BA2C5EDC9452D
-:10BC200078361852D05F55B92E773DBEDFB1DCCEE5
-:10BC3000DF3796638B1EC3AB11ECD74686F67C6B61
-:10BC4000CC359EF961F25D8E9D58887C25CB8114A0
-:10BC5000F4E7F43C7DE1268CE705FA6DC57CA8F895
-:10BC6000839B307E77AF3D9082F1BDC78A3FE2E58E
-:10BC70000981AD18DFDB577C9297A707520C903FE4
-:10BC80005E7C9A97E705B662BEBFF82CCFE3D91B5E
-:10BC9000C8CE53C5E76F0AA0BFC5E4598202F9E7D1
-:10BCA000007F092CB16E919E1678D1CA9FC3EFB068
-:10BCB00001DB2FD2C8F283A25DCF08E52F8AF2DE26
-:10BCC00011FA7F45B40B8DD0FEB068776484F647D7
-:10BCD00045BB632394FF4A94BF3142FFFF2EDAF540
-:10BCE0008DD0FE6DD1EEDD11DAFF56B43B3E42F948
-:10BCF000FBA2FC3F22FAFF40D4EF17DFB3ED1BDEBF
-:10BD000047FF7D36C811944B85F60D71B8CE77B6D6
-:10BD10009713FFB756F0732A8DDFB32546EF0EDF7A
-:10BD200056C2DF3BBBAD84CB71A584F339F0E1C3D0
-:10BD3000C877CBDF94299EA8D5E039154439BADEFF
-:10BD400040F6C0F2D7F97E7DF93A25187E1F486B80
-:10BD5000AFC1BF06E103C66DC314D6DB97C5FC9C1B
-:10BD6000D1EC767B6AC3E499D1A1CF83BC602877FC
-:10BD7000417E53DC78E1BAAAF6C2723CEB339005FF
-:10BD8000A2D45B42F88E8862177AC151DE5188F0E6
-:10BD9000D9147A3F4193F3CCE6D6F935DA6C0ABD73
-:10BDA0002727DB79F9945F4C74A09DD5C6FC7D5E96
-:10BDB0006CEF56C88E3FD45EE640B967B22F70E094
-:10BDC000FAFDB894E3BDBAA1300AE5B5FCA081E460
-:10BDD000F711075FEF3BDC3CCE0AF40ADDAF0279D6
-:10BDE000ED411D51C042AB506EEE7DE8E05CEEE7E8
-:10BDF00063F6B115747F493B579794B07D406D0948
-:10BE0000C74FA6D0230AEA174877958B7B3701EEF8
-:10BE10008FCA54983B35ECFE706D89CCEF3D69E7D5
-:10BE2000A1722DBDAB95B152D19D23A4DDA3CF9BB3
-:10BE300022F48612A15772DA414EEACE4F1CBAFCA8
-:10BE4000B74A849FC7C33C68C74EF9C5069287E7C7
-:10BE500051BF4923CBBD41F92BE4F12E4400CAD197
-:10BE600000BFDF7E6843D9AF90DECBD719E83DEB4A
-:10BE70002B95A30AE218F090E797482FC0845270E0
-:10BE8000DF74393CE4197D71F4DEC765F091F76821
-:10BE9000791CCADB3CBF42FD5FA2372E83AF67250A
-:10BEA000CF713FD2D11925EC6A6000F4DBC545752E
-:10BEB000E1F9BE49F853B438652549E1EFF58B7BCC
-:10BEC000B2B2E0E3FB99578DCBC1F78A9AC8BFBFE6
-:10BED00062DF3D6EB4DBD71AFC0ECC1F8B9B368025
-:10BEE000E32C874D3FE26F2FF641EF72BE7D33FAB0
-:10BEF0004DBA8326ED5DCD10FEB30FE38FB4773BD3
-:10BF0000DD64AF897CD5CDD530DF6EC5518C266818
-:10BF100047C9E44D46B049F799D8607DBCEFF7F4C6
-:10BF20001183E8EFC64DD52097F64531DDBBA5FB63
-:10BF3000D0CF4EF9E99BF09D5218EF4619F6663BBB
-:10BF40009F99B5C976F5103CBB9FFDEEA655E8B0AC
-:10BF500013FB1427E3EFCD9F51FB6390B4B05F59FF
-:10BF60005F82FBF5AE1389E1FB75AD7EACA8DFD037
-:10BF70003BD0F08C4AF53B4A801FEA7B06624A08B8
-:10BF8000DF0315E1F563841F20ACFEA6AFAB5FA80D
-:10BF9000C1F3CCDB3797F0FADBB0FE59B53F9162C5
-:10BFA0007A22E089BFB4FF9D04FF08FD1789FA6774
-:10BFB000426F53FDB3AC3FB1348BDA3D85E39C7BDC
-:10BFC000E3ED0A31EF443CC779D7E6FD197E6FC136
-:10BFD0003E707FA734A9F8BDDBD2E140FBCD6AEC0F
-:10BFE000F0A11CCEC5F7C7260CA5CFA2F2187FE999
-:10BFF000F7487EEEB6B0F85AE4D76603ED6F7AFAEA
-:10C000000D0F205FEE489BE8C0FDF33E535F5909DA
-:10C01000DAAF076C64BF1A323FB5A2DFDC5CC0D771
-:10C02000BFD5D9E42981BC35BD84DE0F95EF5DDE37
-:10C030004DEF98DFC7DFF7527E6CF2EF46FE0A2D18
-:10C040002F5C18B6BE7797F27B96EB5EB36DC0FDA2
-:10C05000C13AA3A7A300ED70BB42719FCA8F0F4ED8
-:10C0600023FBF0E70646F21FE65905FDB6CD55E87D
-:10C07000F7300C94CEEB2B217CF87C55502F2341CC
-:10C0800091F07ED0FD8ACF82E71D6661D7EDF0F09A
-:10C09000FB61DAB81784FD79A184BFB7B623EDC27E
-:10C0A0007B8B5DF8FE8389EE75DA961942A618BC83
-:10C0B000E7B6F3D462A46774FF3ABCE71C95A238D4
-:10C0C000707E3FAD85323A97EBA6EF817A03ED1B88
-:10C0D000E29719BCE87F8CCA35E9FC1D361827DCCD
-:10C0E0001F1233DAFF47A4E7B837951B11CFEEBB19
-:10C0F0000DF43EEA83EE772D068033A65CDFDE3159
-:10C1000051DF3EAE5A5FEEAAD59727CED297BB6FCE
-:10C110003745F875F4F9268DAF4026D8404F45F1E4
-:10C12000221665BBD082FB9EB5AF4531A2CFCA4D6A
-:10C130001D05B83EA307085F514551E417589B6C95
-:10C1400022B9BEB694FBF50FA79B6EA43CCC0BF9AD
-:10C150006347DA51DA8F5C8217DBA9BF62FF3616BC
-:10C16000F61DFDF2A3BD96521E57C3DC15E8C7634A
-:10C17000240F9F95BC9E4388EFB7B8BF624733F743
-:10C18000633F388BC741D20C2A70BDF3FA31960D4C
-:10C190007DB82F8BB1B5DF8DF19D91784D14E70DF2
-:10C1A0003BF0762FF29D9FBF1BBD46BB6785DF2B03
-:10C1B000E8D604BD8B366BB478EF4FD809B1EEF8F2
-:10C1C00092B6B0FB1A89C26FF2F0C47956D41FFB45
-:10C1D000C43B2283FDA934280F79457F54A9E6AFDB
-:10C1E000E1ED3769E73C229FE0E4F97D47E26EC468
-:10C1F000F5B569565C19EEF7D70AFB2E36CDE41D6E
-:10C2000005F37AE49829208D81BCC28E18C12ED8FE
-:10C2100017C7C735BD1E15C07B818FB8CBE99E619E
-:10C22000AD80FBB94ACF3BB8DE07601DED84FE1F31
-:10C230007179AC65E2DC3400F051A8159828876A62
-:10C24000CB68BFFB88D76345BDF9489AC78A71DAC6
-:10C25000D664C581716B716E85DE897BC4E277A07F
-:10C26000FD13078AD484E749E91D53E97E1DE0DA0E
-:10C2700050C18F1A98886FC4F8C27881CF1DEE051F
-:10C280000E7C97C195BBFF5FD04F1F8FFDC5F07629
-:10C290008827A7C0D3AC5295E07689FEE3173C47C8
-:10C2A000F5F1A7AD22AC3F4147D35416C47D9A3671
-:10C2B000BED6CF60FFCC4BE7006B7EC5F1B62A9DA2
-:10C2C000BF8F65BA8BD17EEEB94AFF5EE4B381E4DD
-:10C2D00028927729EE942AE4A394635B67E0BD8BF0
-:10C2E00035BF8AE2E32CE4FC9EA230CB7538EF0424
-:10C2F000BF03F118B95E938F74D421536A74895CBB
-:10C30000BFC90A6B97E32E5DC7C96E5755FEE8613A
-:10C31000D673C47A493E36F07DEC3F725D6F8FFE76
-:10C32000602CD72361DFE5CBE7DBA4FE7524879380
-:10C33000155A67E911E3E13B7B98979841C5B8E846
-:10C34000DDA54EC1C7A0974A91EF1D936CFCBC9D23
-:10C35000F8ABEAF90DDFFD35E42FE0EFF3815AA9E0
-:10C36000C73AFA482FF6F80BB0FE36C5FF38FAD3B5
-:10C37000B71D4FA2F72BCDD1FCFD5153C47B299A99
-:10C38000BED85DCAFD486AC4BB9BDF34ED4E4B2B63
-:10C390007678B0BFB77F6B49F8C7DB3F6947BA57BC
-:10C3A000D9604D3F5372F326BCFF6C7D93973F0DD0
-:10C3B000F980827859467E97C31977D2FC5BDF33C8
-:10C3C000933FAB54F66CC63CFBBD95FC717B0F4CA8
-:10C3D0009C8DEBA4D55EA1A2BD7F40ACE37F156927
-:10C3E000E4BC6493C78FF640E4F7674B35FF9BE7E7
-:10C3F0007817D0B7749789DE711A8C8FE8B2F2780B
-:10C400005461872E10F26CC1C1F5198718BEC35153
-:10C41000F75A29B45F60AF4E4478522F4ACC0FF2DE
-:10C420006F9B389F4D753D27A19C49731DA9447989
-:10C430009FCEFA56A1DC486FD29F97A55E54A8DD27
-:10C44000BE142FF5873F18076A62624DC7F9D92AD3
-:10C4500094F329FCBCC5E488E271A1EE6ADD3D6A73
-:10C46000ED7DDBB7851C35014E8D6590DA147E6F4E
-:10C470003FA2FEEF443D19FDF6E8FC771C3D4EFD62
-:10C48000DA944FC3E34D715F4A426B193FFF043C9E
-:10C4900005701FCA62E3F879A9D7AB86C7DFA68209
-:10C4A000DC359761FC4980E24492C5BD082DAE079A
-:10C4B00030E044BF9B16F7B193E9ED112DD5F6E7B7
-:10C4C000B9CD32ED3B8A5FB5F2FD413B0B5A25F405
-:10C4D0008731923BB91BF8F9B4E617BB0D1713EA85
-:10C4E000257C0F97C6EBA6386ACDAE02FA92DC59CE
-:10C4F00017F1CE94F68EB66134E78B6D2D0EA2A3A4
-:10C50000569EE68FA4A3FE9C53AB977A3195F9E330
-:10C51000C3FB0D527FA9CDFB891F522F6650F9B680
-:10C5200016F532FD678FD07F32F1CBC8FDA751F9E8
-:10C53000F6D0BBCEE9808A9F0EEC77FA54942BA1FB
-:10C54000A99E61F09C7A8F5E4E8EE9D1CB5D0D2F56
-:10C55000DB14AFAB0EF0BDED1E83A78B61FCA9BE53
-:10C560005E4DD66F9CFC5D6BAD7EC83513EB2FE343
-:10C57000F5BF754A5FDF577920B23EC177FD457D33
-:10C58000BD48FA44C20B7025DC1406D7248BFEF795
-:10C59000DACD9E7B095C09B784C175835B5FDFBF21
-:10C5A0006A78B86E2C347F2D5C5ABDEF4CB8B27AE5
-:10C5B00091F39859631E01EFBCFE2DB3AFACDFDBE6
-:10C5C000967C7DBD3B9A23C7096871DB3A7B24BE0C
-:10C5D00099DBEF0E364071269ADD11C71C22FE8BC7
-:10C5E000DB0DEFE07F93197B60B46FCEE804C4BF2E
-:10C5F000F7F64755BC1FC3F515ABE5EF56C2BEA411
-:10C6000034FC5DEE21B85653BF2F61BC13E9598B42
-:10C6100007EDCEE254664946E3CB1DCCC6F7C7EA28
-:10C62000476BF29AC7971709DC3D9BD2BDDC49EBFB
-:10C630003C1887F07CD371EF1DEDBD67F4F8A1FACB
-:10C6400023F95B343C994CDDF47B1D06EA6D1ED466
-:10C650000FEF6211B4DB75B3398476B516877A3C77
-:10C660007ACED10495DE3D588DFDCFBE65EA1ACC59
-:10C670004B87E3D5E536BC37D5AFDD2F5D83785BDF
-:10C6800066F167261AE87CB500F7C3CC172F2E2376
-:10C69000FB4A878BD3D0E0A99638FEA3D2FC0FE3E8
-:10C6A00038D586BE1D3EFCA6F4F17DB62381BFBB06
-:10C6B00084EFEB0CB3FE353C54897E0E193D5F0EC2
-:10C6C000C0FC0E6D8CA57BF80BE26F99836FB22CCA
-:10C6D00034F812F1003D0CEEED04B76D6E6632C217
-:10C6E0006D14705B1204DEBDB95F07F760BCCC7DD2
-:10C6F00092F67E3AE59F0F38E9BEBBD9F0F9BB331D
-:10C70000510F971A3C68776E03FB02DF77FB3F02FD
-:10C71000DFDBF18C258EBED3BB6F6E71EFCBBDC955
-:10C7200040EFBCF8AA5E203AED6AB07970DF3E9720
-:10C73000A9F4EEEA7C710FE60F95FFFD723FCCEF96
-:10C74000A5D1FE83388F3BE20D19EF121CFE627AF1
-:10C75000476BE295C5CF6AE7F033847DB050E07156
-:10C7600026F352DCEE4DCC6FC471DF3E6BF2A25D5E
-:10C77000FAB68847BE8505E8FBAD2C48E96D2C4428
-:10C78000F5BF872FCA42FEADE8D1E9CD005FDD637A
-:10C790000579B81EC3F0FE06D219F8E50E17E79723
-:10C7A0003F2621DE3B13AE887FEB248EBF0746FB7E
-:10C7B0007FC3D7ABEAF2204C8E4969E847195C3F4A
-:10C7C000D5099CFF1447DED7AD9FBEF3DA7D7FAF5E
-:10C7D0002DB902DFFBE23F3778EFA278718CCB777F
-:10C7E000011DFA547ECF11C4863D0074AAA9942974
-:10C7F0006E6FED67E27E363A31A0DE2FC7CAF43E97
-:10C8000099762E395DF4373D8DDF57ACAD9CD91646
-:10C810000B7899F2657F7908D29A34FDFDC5A9AEEF
-:10C820002E7AD27C5AAEFEFB8DAC830E886B4BF415
-:10C8300071E6D323FC9F87706CE0AB8BA345BC648F
-:10C84000112B0ABF6FF01DD1F67CEDE7A673307E89
-:10C85000C918FF57488FE5DFFEC31CDAD729ECCD96
-:10C860007130BF867F97C99EFCA80566528071D53E
-:10C8700016E60583FF24D815983FD5E2A6F434D8F0
-:10C8800001987EDA5248E5675B3C949F35C667198C
-:10C8900003FDCE6BFF4C417DB4568BC7167068719B
-:10C8A000856B45FCC40AFBF2E318BFB08202DE19B7
-:10C8B0002CF68E2908FE9D3DDD473185EF32EE4393
-:10C8C000566C94C8AFB3F0887F0D9279F11BFDD3FD
-:10C8D000514C8CFFCD8944DCA7D7A31D0BACBF22E4
-:10C8E000CE9B340658C0DBFBE1D178A8FFC7960980
-:10C8F00004DF272D5E82EF4F2D3594D68FF1A5539F
-:10C900003DF619BDF3F4ED673E54F0F7B34DF64A2A
-:10C91000E4BFBFCECB8241C0EB662397EF9B41BE05
-:10C92000E3FAAC2C9DB1FD1E86F2D75F80F3BC29E3
-:10C930006EFEE478F83E7DC25C05EBDDF225E8A0F2
-:10C94000AC213EBC1C5F9F794522FC9C79C549F80F
-:10C95000D0F0542FE875E660F177F0DDB3578EC95B
-:10C96000147F7AFEA281E03B7F3C8AE25323DB2FD7
-:10C970003F909384F6D89F807E78F0B1FC4031F9E7
-:10C98000E3FFF4ECBFA8E171BF7F8AEBBEF03ECAC3
-:10C99000A9FFCBE514D89B27B7A21C4B4BA1F77B73
-:10C9A00006E3D5585334EAB10693585F206730FF49
-:10C9B000A728BE0FAEF8796A15AE171C0FE3BDCCE1
-:10C9C000E2F760407F1FFC10FA3BB8D54DEFFD7CCD
-:10C9D000BAEFB16C1C7F6FF7C2F7B742FF6782FCFA
-:10C9E000F7609C61DD675F4479BADB467ECBB512A8
-:10C9F000C085FA744F0AE50B2525AA999C19411E9A
-:10CA00008722A90ABE7FB6ECB92D29C85F784F1DD1
-:10CA1000E3EA5FDA184D72EA25A3E78366EC6F3B21
-:10CA2000EFEFC987EEFDA807D307EBCBEE4539370B
-:10CA300086C7312EF8C9D2226C0FFA9A7EDFF3D363
-:10CA4000CF4B21F48394761E5A8D714C63B67D686A
-:10CA5000488174EC6EA915D3E2F469C7D07F70D712
-:10CA60001895DA8F7B264BC6D8F4A294E0FBD7F357
-:10CA7000B8119D7E2FE9FCAC0AB7999A9E2F92BA05
-:10CA80004F77E1BE38E37819BFDFC5DFAF3ED03B5B
-:10CA9000F39DDB18CE032C08847BAE89E22E583040
-:10CAA000D085743EE32FF4D0BB2ABEC016E4AF336A
-:10CAB000FE44BA5F78D01088C1DFE314F880FFBE6F
-:10CAC000A1E777BF1583F114B1FB8D0C7F2F76FDA5
-:10CAD000D88129141F92AED27E3C7DC70D35889F28
-:10CAE00086FD07BAA89F65160FFA63971CF89CEE9F
-:10CAF000BDB0A93C0EF5CC7E9E7FA0DA4BEF9D2FFA
-:10CB0000E9FA33CFF7F928EF930359747F623EB700
-:10CB1000771E13FA8CF58F66E1EF2169F47A008AAB
-:10CB2000B17C73562019DFBDD2F420E8AF8770FDC9
-:10CB3000A1DB91DA3B66F27BF257A8BF4C421F693A
-:10CB4000FD3D66E2EFF4A218C1DF8BB3CDC4F5EE74
-:10CB50001E9037C82F9ADE857177E0BA3589FB328F
-:10CB6000A9A064C7C27C521F3373F97D85E347DEF9
-:10CB700067D5EC90D9F1AD746FF5D354FFCF701C2D
-:10CB8000EDFE2A533CF4AEE0EF53BD4F8F49E0EF8A
-:10CB900075E01C402FFE02F30D32D85139617694B6
-:10CBA000E5CAF4E2DF52BD07709C2BAD1F29872731
-:10CBB0000AF857D80D8487158F9AC91F3651DC4360
-:10CBC0009D78FE7834CA93157F2E23B9D2CAD8B087
-:10CBD000F879B985C779FF1BFA1120BDF68B7E99CC
-:10CBE000F623470CCB8E827E2510C87F38D01A5B87
-:10CBF0004E792F92FBBA2F0CC3EE17B514E8F52E21
-:10CC0000C9E92FF5FE87EBBF74D0EFCD64B6B82B22
-:10CC10009AF7D0FB3EFAF96BEF6CC1FCFA51BFAF4B
-:10CC2000F8CC40FCBBE2B332929BBD57385FABCB34
-:10CC30007B12E18C9C0FC0FF29D22712FE417E1F80
-:10CC4000B832F8BF2F31FA7D43A0AEC8BFDD2BDE6E
-:10CC500031E85D5A42EF691CC4F748506ECEE0F7E8
-:10CC60008E7AC5FDE4DE0407BDF7F19291E703B7C4
-:10CC70008AF6E27DC8DE5B53F87B1DE6A65F97620D
-:10CC8000FFAD3C3EAED718A4DF53FBFF00D94A30BE
-:10CC900097008000000000001F8B080000000000CB
-:10CCA000000BE57D0B78D4D5B5EFFECF2B33C9242F
-:10CCB000998490072161F220040D3879F10C3040FD
-:10CCC0008268D10610058C71420284BC088FF6C4BC
-:10CCD000969AC100A2C51A8E886851070A14156D6C
-:10CCE000A888A8C13382505A5F69B51E5B2D4D04D8
-:10CCF0009F3C1282F6620FB7BDFBB7F6DE99F90FC3
-:10CD000089DADED3EFBBE7BBF1D3EDFEEFF75A6B69
-:10CD1000AFB5F65A7BED69FFD12097D7C998D13AC4
-:10CD200037E7743E63EFF90C5E7334632D9AFF5658
-:10CD3000630163DE0B16B63B8DB12D31FEE4E53C9D
-:10CD4000BF65D95554FF3DC666B6E5E0BB3B2996A5
-:10CD5000A707FF66BCBDD4CEF3B93CCFD39734361A
-:10CD60009FCA67BB9362787E6178D468760DCFEFF7
-:10CD7000F0EDDE1A87EFD9D4CF10236BA47A69A225
-:10CD80009F3F9A45BB3F30FE97C4D8A366E6B5C522
-:10CD90003236DEB568B8AB9031CF8D1126168D4294
-:10CDA0007792C6E7F348D57076AFC6B3AD0F3116AC
-:10CDB000CFD87C2BA33F351E2A5AC730364F7C660E
-:10CDC0000B16EFB679F87CE655DBBAB4D17C1DD5ED
-:10CDD00077453AF978F33C467F5814AF705389BBD6
-:10CDE000335BD4FD7B3AC675D3B8AC6A10CFF0D4B0
-:10CDF000E4AF647CDC977BACEC5E0E97BFE36F4ADC
-:10CE000020E510636C30639FDAC4F8F56D531F386A
-:10CE1000ADFAE3FF565BEC1BB56894A7FA181F7FC9
-:10CE2000FF104F01FA5F7EE8BA074E5B03F5AA16C2
-:10CE30009764314360DCD07142C76B01DEF878C380
-:10CE40008047DEA485171880BF369B0FF863A69E27
-:10CE50003F2CE5F996F957B9EEE5D99973AC6E8D8B
-:10CE6000E3A1F740982F4CC3F77037D6D57238D26C
-:10CE700067E0F9DB3501FF168DD177EF7EB36F37B1
-:10CE8000FF5667F13DB187B7AB7B79A48B8FCC0E92
-:10CE90005AF87F50FE6284288F72A7AD2F40790226
-:10CEA000E1F725B3339ACA7F6D64541EEECF8AE151
-:10CEB000F06E4AF4CC71F1790F09E3F8B7A35FF192
-:10CEC000FDA4A4BF93BC5BE0D7DB1849FD3299F702
-:10CED000FC7090EF5E5A8F3B6931F2ABAEA6F578ED
-:10CEE000300F3E2FD6A0D17A4F3A7CF764F1F293FF
-:10CEF000ED83691E71921E4E96FEE58DB1BCDEC9B2
-:10CF0000434617FAFCA0C9E8B744A15CE0439B6321
-:10CF1000CDDAC6DB9D7A31D215C6CBCBEEAF7D1D07
-:10CF2000DFCBEEAA9F4569CD9A1B19AFDF79D7FBFE
-:10CF3000A99E9C2BF15156C75B05E1F14E97BB1E94
-:10CF4000F87DC4E569C47A97E7742E619CAECE5B28
-:10CF50003A1E6346C6DE1DEA5985EFDD2F7CB20717
-:10CF6000DF399EB24A47F16598389D807E3B471372
-:10CF70005D2F97F49B9EEBB903FD713896B30CC6F9
-:10CF800022723A2C98075B33F85BD1C9E7EDBB0FEF
-:10CF90006A7C9CDAF0F6064A8DBED1E8E78CE68F13
-:10CFA000D232088E1EECBFB30E7F14F0E131F03C9C
-:10CFB000C74FED5EFDBAF067E2F3AAC5FFF076B5A4
-:10CFC0006D46B70DFB87F92C987F2DB304EAA7892E
-:10CFD0007D083AE0FDECA4FD6AFFA0FC871C0F353C
-:10CFE0004F8CCCBB97E3A736E6D04F26523DDE4EA2
-:10CFF000ED17E39579B59E2BE723D67756EE83B3ED
-:10D00000FC8B19F4B32F4CD03F13F471FE892449E3
-:10D010003F826ECF3F31C287F9C4CB7D735EF31A76
-:10D02000C2D1EE47CCB59BCF8BB9DAC6CC1E85D921
-:10D03000B78D9913C9D856C9D76A07B58D01BF52A4
-:10D04000FC8B59DB46CFE6E52CBB6DF49C5101FE11
-:10D05000C74ADBB2E8BBAF2D0BED0F1A5835E0A97C
-:10D06000E653F354F20E828755ECD79AA7AE26F812
-:10D07000A8715AC047C08FC12FA2AE5CF7CB2E4D0E
-:10D08000ECFFC83109E06B03E13F3B71500E58C91A
-:10D09000F90596DBDDBCDF11DB2CBA7E54BD913E79
-:10D0A000FDF75FA17F4E6FC342F039C4D8F34A1831
-:10D0B0009F2FFB198713BB72BC3765BB279FECC33F
-:10D0C0009F51E09331A7A21B27C149E0E90F1685C4
-:10D0D000A7D5C99C5FD70226E901781DCCF524436A
-:10D0E000AE9C471EF22686E779DA20E1AFF20AEE1F
-:10D0F000A1F477D71F962477F2F6FFE532D0BC4231
-:10D10000E1BA96C30FE52D66767B296FFF79F38927
-:10D110008CD3E6C07A3E6E76BBB9A8E9CB2FD99600
-:10D120006BC5BE5BBA3DD7BA2808EE2D7BF34F38EE
-:10D13000395ECFEE356124D662F2FD64421CBE1B1F
-:10D14000DBBC8CCAAD6E5EFFACFDC89BA8B7647B30
-:10D150004C9ED11968BF745B89BB2A08FE57EFD576
-:10D16000E363549B3E7FCD217DDE9CCB881EFED1A8
-:10D1700076B97E7D3EFF843EFFC93BAB6FC63678F5
-:10D180007E9CD8379FFA227D560ED7EAF7679C809F
-:10D190001CFDF4E0F351C057ED9FAA8E2733AC433A
-:10D1A0004FA71C8F9A89AFD7BB47237A59E60BDD6F
-:10D1B000BF926F5CB1AFD712BEB0B382E92614BF85
-:10D1C0006758DBCD6E4E5F754D6F67408FA99EC56A
-:10D1D0000919F2BB6DB385D9AF1C6F20FEC1EC6E8F
-:10D1E00027E3F457314E944D689ACE4EF1FED8A6FF
-:10D1F000DFCEC07EADF8B146FA46C5B3235E05DD8D
-:10D2000074ED5F703DA537CF24385432B705FC70FC
-:10D2100069BBE68FE479C738E7A14EDE6EB14F7384
-:10D2200061DE8BD68505F819FFB76A53C83CB60492
-:10D2300095F3F92F3DF4CA571AEFBF7ABBBEDD3222
-:10D240000E2FC88F9A5D7F0F0BFECE152182D784DB
-:10D25000F61D46AC7BB19CBF927FCC3B99617D13A0
-:10D260004413761AFFE172C332CC539C5B1890834F
-:10D2700013B688F69CF15560DDF5768B13EBAEB7EF
-:10D28000327F049FCF89488BDBC1BF5FDC1649FA30
-:10D29000C39230E6B5E651CA6C7968E78A46BB8F1F
-:10D2A000DF32929E54CF790FF5F3B8E66B413F46DB
-:10D2B0004DE47F26F2CB989FD603BA7107AFD3A770
-:10D2C000CFB3D641A497D499FCAF002E35AC93E0F0
-:10D2D000CD383EDD0A8E1C6E757C9DEFC542FFD2B7
-:10D2E000B75FCEDAA8FEF2437F0F0BFECEF54C6699
-:10D2F000E5F5B787F394E6EF23381A2DCC6DE0F30C
-:10D3000034DE19EEF3921E521A0E3A354B7D79CB6C
-:10D310003DEE2CCC7BBDE6CE72808F6DB6B9C0C71A
-:10D3200016EE1072684B0CD75FE3486FA6F60BA1A0
-:10D330004F414F5920F8DD9698363FF8FE9607D3B7
-:10D34000843EF53723C1A5E73E9B6FA7067D5AE8CB
-:10D350003D5B368FA0F6E097A44FDD1729DACF1694
-:10D3600070DD32D8E1F3F2FC1F31C524E8D9EE2C90
-:10D370002BB5E37A5A5A404E297DFA67C33C7701B0
-:10D38000DF6ABD4AFF66D5DF4EDFDC2DE567CF667D
-:10D390003E4FDEFF69ADF4B821481F7E2057F0FFF5
-:10D3A00031D3DC7B643D17EA551966DF3B85CFB787
-:10D3B0006AABC1D99216803B73BBB300E7D39B6DB8
-:10D3C00079A0B331D3189D274EE60A7E1E51C0DCEA
-:10D3D0003E9E6E97FD6ECF35E8D2C4704E7FBC9FE7
-:10D3E000D3257E33F01B59506A813CE4329CF87996
-:10D3F000E83AF6E60AB9596529FDCDA47EE6D34799
-:10D4000007C5426F39BD42DB29E625F03CE6DF6DFA
-:10D41000AE165AB7989F823BA79B4292F7926FC570
-:10D42000F4D189EF091B47ED66A54F03FF9A8E4E95
-:10D43000089E5BEE1B45785C28F1CCEEB3493A615F
-:10D44000ECAF282F7152F9379DB7D43A391D5039B6
-:10D45000C7B71FF80E3D6F297C3393AFB0347260AD
-:10D460007C2F1A173346E3A04E36316F18870B64B2
-:10D470001EC1E51E93EF2E3E9FA12601FF1493A02F
-:10D480002FCE9DBDE17954DF6DE1F98A07963237E1
-:10D49000AF5F91CC5C9AA8CFA2519F7763E42964D7
-:10D4A00006DA55448B7E2B1298EF2EA9F7835F6521
-:10D4B000224DA77EDD8658D13E2A8FDA7B0DA2BD94
-:10D4C000DBC4D3611962BFF4AC0FA3FD5371774A7B
-:10D4D00016E860D6343D1DE4E709BA51E9E3794E18
-:10D4E00029675C89D8DF8BD68D24B9D1622BAD7FBB
-:10D4F0000EF87A3A82F4C18A0DB7DD5088F93D33CF
-:10D50000081A0EFBFCC6FD63406F8BD62DF8DEEFCC
-:10D51000711ED96BA3EFED799EF3B9D0B73567F9DA
-:10D5200073FCC3A279472D89BCBDA76DF6B91779E5
-:10D530007AA377FF9BD00B6EBCC948F56F646D7FF3
-:10D54000F923F8C23A31CE0DDE0BA644DEDF0D45DD
-:10D550001A437997CD91BA82CFBF42E2EFAF721FE3
-:10D56000B4D8D8FC5FDA31AF94AC74FEFD0668AA7B
-:10D57000FDE881E3F2A49E3855DB0EBD67D874B197
-:10D58000BF547DF4837E27031EBC9E59C245E539F6
-:10D590005CA97ED5C6B0AE8C28A466FF089E2E2E50
-:10D5A0009866CBE3F566A5B3193837F5DC61643BC3
-:10D5B00069BE3D15B4EF23B39CD8F71EC6FCC4F773
-:10D5C0007C2389EEBBA6F674DDCDF35D3B46B85AED
-:10D5D00088AF8BF3FB620723F9DE3555F035C55F65
-:10D5E0004E3A3A23895EE579BE5292C6474DD3B78B
-:10D5F0008EE5F52BED962EC883C50FCE8D72F27990
-:10D60000566EE1E7792EC7D826FD799E9FB733F293
-:10D61000065F792E0F3D7F83664047559B34A2C33A
-:10D62000612D2E4B12F131CD81F555D9FD99907FA9
-:10D63000552E9B0BE5679BDD0F9CE6FAE1F9E69919
-:10D6400094B2CB1CEE7C9E5701797CDF8FCDF7B86E
-:10D6500000A78AD60A3A4F46E478883F2D97743758
-:10D660008B835903BF317526611F76E5CAEFB18EF2
-:10D670002C3BD1B38D010E5D664716E6D5B5DE664F
-:10D6800080DC9C7597A06BBECFAC26DEFE1E130B14
-:10D69000C77EFF1BDAF37596AD3595EEE0F9A1561E
-:10D6A000668A8C055DE5125DFFBCC063061C3EFD0D
-:10D6B000111B07BDA072D3669A8FA20B66EA281EC3
-:10D6C000043D6F775A1ECED78A8E7E5E30EDDABC6F
-:10D6D000607AB849233AE0E92B19440F7366113D8B
-:10D6E0004CF367AEE4F32A31D63137EC0C89CC1514
-:10D6F000C6E7DFCB7A489FE8E5FA04E499E2278A97
-:10D700006F703A705BE303F8DDD3CCA7C279F2DE29
-:10D71000662BA54F363B9889C3775F7322E59F69D7
-:10D720007652DAD69C4DDF7FD9ECA2FC81E671946B
-:10D730003FD8ECA6FCA1E69994BED85C4ADF155F01
-:10D74000E270213EA4F88AE2478A9E145F0AA5A3EC
-:10D750007227F606B527BEA7F81DD661C80BF023C1
-:10D7600085DF74ADD49B98063ED6B900FCA2C47880
-:10D77000F6E9E7397C7BABEDAE3027E022F85EAF0F
-:10D78000DD4A723ED5C20EE1FCDFB2C2DD75779094
-:10D790005CBDB55A63A620BABDADD1C64C41747B01
-:10D7A0007B538C2E5FD6F4F6B104DEFFDF533C5E74
-:10D7B000E0E5E49D1F3FFA9FFCFBE3777E3E1CF80B
-:10D7C000E6F3D8FD10C65D13DE378F58E4D79949CC
-:10D7D000CE0C0B17E7A461E1E29C843FE0671113D4
-:10D7E000FBF4F13BFF4AFBBCAB29CC6984FE017C16
-:10D7F00071F87E20F1B5A8298CE058B1FED4D3CFC2
-:10D8000063BFAFB110BF5BB44EEECF8D1CAE417A9B
-:10D81000DB87498CF433CDCD581387DF873FB2F8CF
-:10D82000B9EC671F6A569FC61B6AFCD054C6BF7B03
-:10D8300036FEEA3DE8DB5AD309D28F3D56BBDF887E
-:10D84000F979CD6783FBD39A8E533DD63934E6E31D
-:10D8500008DA8A0C708C28705BC02740DBC0DFA21E
-:10D86000EC230CFB9BB56A8EE17C5D55F27BD546C3
-:10D870008DF40E05FF27F28CB4AF4EE79A08AFD3B4
-:10D88000B0670713032339A5E896F30DB70FFBA381
-:10D8900035D7B224881F2F92DF2BB30D94AAEFA7A0
-:10D8A000F9B6443FD3B0B978BFF766A75B1613BF8C
-:10D8B000735AC00F54FD45D9791BD20BD0CFD43841
-:10D8C00016B42F9FCB33C97939841CB37239C6DBA8
-:10D8D000D50D200F947EF229FE773CCD9FCE5F358B
-:10D8E000CF3CF5CC8BB04BBC1F4678AAB946DA3793
-:10D8F000727C63E6925EE3B66B7C9D0D12FFC54FB2
-:10D90000FD29AA93972F3F20ECA73CED42DAB0A661
-:10D910009AEC650D2EBE4FB00F0E993FEC0CA2CBCA
-:10D92000579F793FAA93CE17DE644322527F32E39A
-:10D9300069C381533318FA633D1B1CF62BDB2DD7CB
-:10D940002ED33953ADA3E4F097F134BE76299EEA85
-:10D950001F5E1FDF9F1D6439337DD8B77FC9CEE0BE
-:10D96000D6D9D596B34D178C7CBECBD7CCFC0474DE
-:10D970001E5AFF93BCC838D00F1BCBC6921DC3C420
-:10D980000CC0F74AAB8043AF6F7834FB1AFBCBF285
-:10D990006DBC1157B57A4DCE68179F6F37ECE7FD18
-:10D9A000D4CFC91772FD1CDF478C9FA5BAF719E9C0
-:10D9B000BCD0BD2F92E8BF61DF03C727F27CC32E26
-:10D9C0000DC3B27AD641706A386064D6607906FBBE
-:10D9D000CEA081E759FB546423E869599BE6DECD6C
-:10D9E000E7D36B75460F0E9A8F2D5FD0536D58DBC2
-:10D9F0001882AB9CFFDF253F53F596B53F6001BE13
-:10DA000078BDF3A4BFFC228291DD8CF5BC89799EA0
-:10DA1000D99EEF827D6F59DBFE0692FFFB221CC36D
-:10DA2000F93A3E97767ED5CFE07CB19F06E70BBDF5
-:10DA3000E38CB4E79E79C6487C08F3C43EFC1C7AAC
-:10DA40006ED03C93E53C93F3857E7304FBB130507C
-:10DA50007F595B575426AFFFC9A1B7291D2EC7595F
-:10DA600066EF180DB9F9C98188993E4A7F3AE325D6
-:10DA70003EDEB9B6A9715AD0BECACB3753BFE7B69E
-:10DA80001B67025ECC3748EAF96DB49E33FB9235D2
-:10DA90003ADF02DE5CCF3F73E0D92803ED5BAF686D
-:10DAA00027F168B00A3B6D588C53EA99D656E81BAB
-:10DAB0000BB97617CDF95DFD810B247F43BFABFA1F
-:10DAC000B4DF9270FEEE21BB06FF33807EEB1D02B9
-:10DAD000E725C69C04EC83F26B9CB7DC0A3EF69A01
-:10DAE00059E061A8F3219CABCADF1A44768B956696
-:10DAF0006702F25FBCCE0F827CDEE5F9727F27768B
-:10DB000016C2CED99526E47ADD467E50E1EB19C2E5
-:10DB1000F1EEE54BAEF31999273FE0279A9F9F4E10
-:10DB2000EB7BA4DAE0B6909FC59F05BBE7490BF3FA
-:10DB300092DFE89736E10F481776FD47A4BFA82E7D
-:10DB4000D69F3508F62F89C7BA39BC3C089F753B6C
-:10DB5000FD59D05FCE5A849D0FE50EA479A25E8B4D
-:10DB6000A41BF4837EBBD21CE749CF7C2E9241DFFD
-:10DB7000373C1F29EC0A3FB7ED0C0B929BD592AEB8
-:10DB8000B8CEE4C5FABDBBC5FC302FE8CFCB2CAD79
-:10DB900059D02FD5B8CBA25A69BCB372BC65E1ADE0
-:10DBA000C23F6111F648D4A7F1CD8CFC283D4F84CB
-:10DBB000919EFA7952C7418CFFF9132319E47857E3
-:10DBC0009A6FC9212AE7FA1BC747CD93617ECCF72C
-:10DBD000B327227D8CD7FFCC2CF4A1CF22E3491FA1
-:10DBE0003A11B9B59CFC32BBC234D8553ED3982506
-:10DBF00011E5BB851FA3A6B989FC0F357CBBB33CDF
-:10DC00004A67B258948F247BCB67BFE6FB54A3EFDF
-:10DC10001BF1DDC35ACB7F807DB73782EC6E9F3F0F
-:10DC2000F95F23FBF35BD4ECD2DB97141DA8F27BE6
-:10DC3000245FBA47C2F1BE7C07E1BF3EA26D6B3ADA
-:10DC4000AD53EC578E073A77F1FD110F7BF7C9B64C
-:10DC500017E2353BE0ECCFFA29E0BE579C6F3EDF80
-:10DC60006726BF4BCDF3916EB2E3DC3DD600795110
-:10DC700063147A708D81838FA7DA9D7BB3A067B719
-:10DC80003C61CB033C38BCE91CD9B3DB28C711E3AA
-:10DC90007EB62745D8F5FD327F7014D9F567C5B239
-:10DCA000DBE7909EB37D34E07A7157840174C1C77D
-:10DCB000716B1C3E353FF8A18067F412D2CBF9FEA0
-:10DCC000237E5927F965FDDD13A327623FBD6564F7
-:10DCD000D00B2E9A5C09E087A1F0FA40F295DA8326
-:10DCE0008F5AE0B7ABE3FBC6C3F74DADF48FD53E1B
-:10DCF000A9915E57BB61E243C407DF34B3E17C1EE8
-:10DD000067DB1E880AC6C771C9CF02ED5D54BF9696
-:10DD1000D717ED5F8BA2F9EC31BB309F503C7EEB07
-:10DD2000F64F1ABF55FB3EFA68E3727DF495EBBEE1
-:10DD3000C83ABEFF3EF8C93E1BD9AF38DE53A177C3
-:10DD40009C31B72DC1BACF3C6D233E732646ECF70C
-:10DD50004F383FF48EC03CBE733FD9377E37974172
-:10DD60001E2CF5E9FB55E3BE26F96FFD205734EC78
-:10DD700064F51C0FE88FE3E5BBD4FE2D33B50F5DD2
-:10DD8000C793685718B43F9F8E207A393344E0E335
-:10DD9000CC332348AE74C5083AE7F34DC579E54C5A
-:10DDA0008C481994114E0735F23C7A666A1B9DBF68
-:10DDB000CF68FB29ED328B76354DD26FCCE92E1131
-:10DDC00074039A843FCCBAA903FA04ECD563F22811
-:10DDD000F587C55E6977067D420E651408F9C53082
-:10DDE0005EBCF47F909ED266015FF6483DAE6EDF6A
-:10DDF000957E38E0B76E9F467E2483EA87CF3A4E01
-:10DE0000D9CB393DD67A35B70DF359B76219F991A7
-:10DE10001A37DF0A7A57EBA835B199380F7569467A
-:10DE20009A4F978DEF1BC02178BC20BD2B32300E4E
-:10DE300073C4939E49CA754C819057C8B7F2FEEAE5
-:10DE4000D6699B689C3475AE14EB5370E260B1C028
-:10DE50005EC6CFFBA27C80F5AB7986AE5FCD6778DE
-:10DE600081B05374A539EF2F02BEDF30BA704EBFB8
-:10DE700078393F3AF66BF4329CDCFAECC67CFE79DA
-:10DE8000A0293EFF2F257FAB855D9ACF336BBBDE8C
-:10DE90001F92BD4B9FBF6A9F3E9F73409F1FDDAE89
-:10DEA000CFBB5ED5E787C871159C70EE758E10E705
-:10DEB0005EA438F73AC3C4B917799C7B91E2DC8B36
-:10DEC000EF38F7228F732FF238F7228F732F529C7F
-:10DED0007BF1BDB240F0EF3A6977041EE097612F05
-:10DEE000D8949F9DF64BF78278E29FCA4FDABD2CFB
-:10DEF00087F27D769DD956B2EB90ED86EB25738740
-:10DF00007A6E282884FFB4634312F066EA247BEE1D
-:10DF1000F217853DB72ECF66879DA173FD271BA005
-:10DF20003E650DF5CC41FD6E73CF1EA203939FF8A5
-:10DF300046E75AE75B5304FEC8DEC1ECB1743EA964
-:10DF400080BC8B1D188FA17E15B649EF4709F5AB34
-:10DF500084FA5342E940F9511E37F72481DF9F7A52
-:10DF6000C2BA09F33F25ED646CBE95F42FA557970F
-:10DF700018ED04A795F7693B21A75615C452FBDE9F
-:10DF8000135CDFEE47DEAAB4F252BED0AB557E93EF
-:10DF900066203F8DC74D7268959C53AAD6D37537BE
-:10DFA0006824D24072FCA2DD40E7828BEF18498FD3
-:10DFB00018B1CDA05BCF485FB88EBEAEDE1B1BE2B2
-:10DFC0000F1CA2AB7FCDA1F4107FE0557A3FD54D59
-:10DFD0006B5FC1F97AEEA67C5DBDAAD289217094EF
-:10DFE000F3967A69CB9A6DA9E03FAB227B69FEABD1
-:10DFF0009EB3D1BD8B2A2E5FDC7CDDD5C870FE5868
-:10E000006D75DF08F855B7996360D7AA94F2873524
-:10E01000E9E571B589791DB101BAAB7630770C6F3E
-:10E020007F2EB7758F81E3ED9C61FBD62227FC4BD9
-:10E030003B521D9CAE566B6DF1E3797FA7623C3B72
-:10E040000AF87E4E35FB7F52067EB93F83ADE5F57B
-:10E050004E6D7A368AF46E4967A9664738F0BDA3DB
-:10E06000D548E702D8A7600F52F4B0A3755078A640
-:10E070003DB0CE00FE2FD3FA385EE8DE48AFFDC8D3
-:10E08000D055D0E3DAC47AABA76A5ED293E57A566C
-:10E090004AB9C2D6897E56CBFC69795E50EB3B3BD0
-:10E0A000F295D14EF8359B0FA51AC1C70DFBF6248A
-:10E0B00041BF48F0B463FF54EF18FE9F457CDC9AE3
-:10E0C000DF1B19FCC81F6D991E351EFAE7D366D7F2
-:10E0D0002C9EBFBBF567169C0B6A4C3E0BCE9DD5A4
-:10E0E0004FECB0C0FF7FEDDE1DF47DC9DE0A3A6F54
-:10E0F0002F658D748EFCD42CE4B48247F5346DBB4F
-:10E1000083CF3BB350F0D7EA70711FA4C458742C6E
-:10E110000EEBDDABE562BD3795EEB754F0EFEF4A9D
-:10E120003E1CBA3F7A5F9F5B321876A536E1071D29
-:10E13000683FCCF38FA4FD30F7521AA5375DBA9A29
-:10E14000CE55BF67A5A3884FE4849C675F370ABBA1
-:10E1500059BBD807D5167FDC5CEC9397CDB44FEA5A
-:10E160004DB07DE39CCCD8049E96161975F4BABCCC
-:10E17000384247CFF359ACCEAF7C331BA2CBDF3450
-:10E180002B4357FF969BAE0EA1FFBC4039F191097E
-:10E19000BAFB2BF56BBC4E8DEC68D3F4DF79BA86F5
-:10E1A000E8EC7A5DFB7A3627500FE7E05DBF253853
-:10E1B00033D661C179ABDA20EEEBCCF774C9EF9DB1
-:10E1C000F49D2F44B70F8765B8FE53C84533D9E790
-:10E1D000957D7A3EFE3FA33FB9C8112DC78D360A03
-:10E1E000FB8247AF7774D0F993093CD44B7B4F7DCA
-:10E1F000B6B0F7D47B3B2C8D7682BF299983A4A13E
-:10E2000055237B1EAF6F4D8E15F935F87EC01CB0BF
-:10E21000B330D1DF25949F305660BF849637F075B8
-:10E2200043CF6880BD86EC4C333F213B931A47F6C1
-:10E23000AFE874E936BDFDA801769D207C2E2B74D5
-:10E2400012BDD6ECDD7F7C0887CFDCD2985CECA3D6
-:10E25000BAB6D9E68A9C2BE94DF1F98BD506F27B4B
-:10E26000F7BE7E94E8ADB7DA4474FD4D7069700B6B
-:10E27000BB66281D2EE1EBB2F2F1971CD05C3E4D3F
-:10E28000D4037C86803E43E093DC0FDC14BCFAE0D0
-:10E290001752BE14FF5380FB049ACF9FD61F5C42D7
-:10E2A000E0A9C60981171BA787C7128FF32DF09F1E
-:10E2B00025278CCCF72DD6BF14EBC43CF83A318F10
-:10E2C000399784DD44F9136EBE64A27C1FDD94721D
-:10E2D00078E561DFE9F7691F1D958A7D33EF523CD0
-:10E2E000B5FB57D1D337D1919ABFE2DB817D74174B
-:10E2F000C98DE58591711F7356C1FFBF90F882E407
-:10E30000AF03EBA55EC1473D7A3933ECCE7174EFB4
-:10E31000A8D79E4E7A459F1C72E8CB5746A627A0E9
-:10E32000DC23ED768A1F7B643D354E052F770E0288
-:10E330005D0F8D873D76C3BA8CD4CE207DC5B3DE0C
-:10E340001C0F7B61EADA419456D81CF19023156BBF
-:10E350008DA5908F1FDE93103F0EF6F9F5E6B859A4
-:10E36000BCEB0FEF284865A3902FA1F4D4E6B0F9D9
-:10E37000C1766E956E2B147A68FD9DEF915C3B67BC
-:10E38000783D6A3EF6DDFAE7A270F5A676FDDB631E
-:10E390001C5C25B93BC6F35021F95177EC71006E36
-:10E3A0008E1DA361A7FE396C688303FA43CDFA92F0
-:10E3B00004D8C5EAFE76F431C87DCF5A733CF4CF59
-:10E3C000CFDEE1725123B9467AC3A73646E7A54F9F
-:10E3D0007747F8E0BFFF54636EF87796195F19ED41
-:10E3E000D0C9D9F69B318FBD099E9F1716627CDF7D
-:10E3F0009E448CEFF2D2FD4CCFDAE1D1FDD95154DD
-:10E40000BA7C9BD0EBF6283BAEB4F7429F471EFA8E
-:10E410003C1B21F479E4A1CF23853E8FEFC7A41DD7
-:10E420007F584B4F2ECEA3DE692CBB91E4AE3D1B33
-:10E43000FAFA2A2DDC457AA6E64A807D8CBD1323A4
-:10E44000E46D087E553AA987EB5C41743FE59295EF
-:10E4500005DF339BCA6274F9E9D6245DFD12479A41
-:10E46000AEFCDAC491BAF2EB9CB9BAFC77B2C7EB56
-:10E47000EADFE09AAACB7F77DC75BAFAB3DDB37531
-:10E48000F9B93317E8EACF2BADD095DF327F99AEDB
-:10E490007C8167852E7F6BF51DBAFAB735AED595B1
-:10E4A000BB99C304B9D78E731687FBCB3867F17459
-:10E4B000D51BC3EDC1782D9A6E68ECCF4E7F5EEA16
-:10E4C0004313C7BA3F037DA418041DF2D40D15E20F
-:10E4D000B2942BC9CCAF89736E4712E826B45E683C
-:10E4E0007951C4918B4E8EC32507636F35713E52AF
-:10E4F00034F6487E06CF3F336681C84F3CF26C3A13
-:10E50000CF1F3CB8F55613E71F45D71CB988F2D189
-:10E5100063CB457E2E2395E3C898BF2DF4F2751486
-:10E520004D49DFE41276927EEF69AA1470C0FD4671
-:10E53000C001A99FD327D2239C3E91BECAE9B3CA8A
-:10E54000CCD8714E9F484FF0F326BEFF869F37917F
-:10E55000BECECF9B48DFE4E74DA41DFCBC89F47719
-:10E56000CDF3297DA7D943EDDE6DAEA6F4BDE64619
-:10E57000FAFEC7E6264A3F68F6D2F7C431CAAEE0D3
-:10E5800027FB8BF23335C0BF07FBDC21F3D9603F9B
-:10E59000ACF2132ABF604B23EB8CC03EED34C57C3C
-:10E5A0006C0DF8FB06E6B326F671901EB639D19DC8
-:10E5B0003186C61FEA207F8FFC3E4D9B9B02D7DF32
-:10E5C000ADA33D23C7707CCFCBAB5C1FCDF9C79407
-:10E5D000CB8D66D0CBEFE53DD5D0FE2F4B3A891BD6
-:10E5E000EB1E8D7693ADE21EDE64ABB86737D9D4EF
-:10E5F000D9027ED4F22573E21ECD2B9116E24F2D67
-:10E60000F7987CB0536A5F30CA4F8A63946FF9B24F
-:10E6100083EEE54D76B81249DEC87C9FFF1C7F4132
-:10E62000F765943F5BDD9329FEA2733AF480497647
-:10E630008B332CC4FF0EBFF52B91EFAAF9308CA7BA
-:10E64000FCE4BBBE647EC3E8803F7CB2B5230D769C
-:10E650008249ABADAEE0FB3FCAEFAD7DD161843CFA
-:10E6600051F77CD4386ABE9126DE5F5EE01ECF642F
-:10E67000475B2EEE35B4D4DBA9BF04FEDD9247F52F
-:10E68000DC466AD7960B3BF0A43ABB0BF66DE56F00
-:10E690004F90EBE6F5689DC55F78E8BEC12479DF51
-:10E6A00000FD5845B917FD4C8AF32799B0FE468BFB
-:10E6B0000BF6D04735DE3E2FE0FF47FD88A0FD8BEF
-:10E6C00079A2DFCCBFF0F9426F77BB09BE73D5F9F1
-:10E6D000CD29F3523E33EB34B25F1965FEB7A33D4B
-:10E6E000CB81F7D230C79F22689F67A4C0CE315B31
-:10E6F000EAED5F432FABFF7BE8C52DF03D94913DE4
-:10E700002D946E145E149E07A22385F7A0FB5A84F5
-:10E71000E7BEFB57B29F50FA1A88AE143D4DB60AB9
-:10E72000BC03AFB847A3E848FBA26D07ADA3CE4A30
-:10E73000724ED151281D5C4947822E5BBE67A5FEF3
-:10E74000AEA4A300FE018F7F9E8E3A8C90BBFF2863
-:10E75000FDDCDEC36644F3A27BAFF15C86DCA8B8C7
-:10E76000E43C8E7C259B3A0324A5CA1F40F9E02B8C
-:10E77000CB43E94BD57F7180FE3C5FF498A383E8DF
-:10E78000729294817F18A0FE6BF25EFC6B3675DF8F
-:10E79000C36DCFE574305DF2E1552582BE66A619E2
-:10E7A000C99F313D6729E9F7CC2EF46327FF87EC39
-:10E7B0006DD2BF7EBD6C37E372E93A8C33234EAF26
-:10E7C0007F5F2FF5EE9921FEF6EB73AE253DFCFA47
-:10E7D000103DFBBD31528F4E6369E27CBD89F4DF91
-:10E7E00062B91F9325BE339C4656C4E15EC23C26E7
-:10E7F000088157CF5BDCE8EF5AE6A5FC75CC47E90A
-:10E8000077989FF4801BB8C040FEBB8CD1FDD1A38C
-:10E810001137962DE7FD4DCF9F9E89EF75D69E54FB
-:10E820008B01B7033D9F413E34183D7F869E792E74
-:10E83000C53302E7E323C54ED2C38E5833482FC4F5
-:10E840007E3207D92B7FCDE56826977347B99C4563
-:10E850007A8CCBD94C2EEF7EC5E52CF2D767AF650D
-:10E860006837C3A9BFDFA3DA7FC7319D99060D2C96
-:10E87000C7BE33FA85A1B063BD1633A218787B2DCD
-:10E88000666C31D6FB5A4C8241A461164A473D9FC3
-:10E89000D99FDEAAE83530DE0C1A2F14BE0A9EA1DD
-:10E8A0007054F0FD27E039686CE195F0BC0CFD1E5A
-:10E8B000F653EBDB5189E9F033CA78BA08C107EBAC
-:10E8C0009F1F958075D459055C26354DA47472D36D
-:10E8D0007866CA273F9317F0FD0C4B80C139C4CE30
-:10E8E000C64CD328FF3D495BD9099EE198C7D93C66
-:10E8F0007F16D7C8D827DB5BA2703FF3DC334617FF
-:10E90000CE357546E72617ECE4AF19455CD0E5A394
-:10E91000A9F06FB25DFDDF97AEB32AF87909AE3F7B
-:10E92000BBC64DFB8DC13B1B1FD06B8686897BC64A
-:10E93000E45EC81B58CF19132EF8CCD030C11F1578
-:10E94000BE783B2177793F63385F4BBE3F9CCE3525
-:10E9500005C3DC45580F3F2F505C516F7604D92B0F
-:10E960007E23E31227FBAFA6B8BC9938B7F3EFC6F6
-:10E97000F0A89DD8F7BF917189BF18E4B916EDAF23
-:10E980004DCB4B043CA630E157B9CE6A76F9F99CE1
-:10E99000AE1B2BF7E168365AC6F5E8CE1FCA4ED239
-:10E9A0001B6724393499653D043B41F10933D9098A
-:10E9B000FAEEBB250ABF68EF898B46F09592488D29
-:10E9C0000D4A0BC4E784251A9833486FB739C399A9
-:10E9D00033687F4464C7EAF291AE21BAFAD1E3D238
-:10E9E00075E531EEAB74E58366E6E9F2834B27E823
-:10E9F000EA27CC9FA6CB2779AED7D54FAE9EA3CB27
-:10EA00002BBE972C3EB194C685BAF6C39A16E9EA96
-:10EA1000A7796B74E50A0FCCEBEEC88E075F147F05
-:10EA2000191B57EAEAFD344AC49BCCB42F9985FDE3
-:10EA30003EBCF507FA79195FD7287ED429F8AD973F
-:10EA4000FF033A2A49D4F3DFE90EBD5D23B9D1A40F
-:10EA5000CB6FF847F1ECB94A87E7507870BCBBFC44
-:10EA6000A8CFE5B797E74B7E5D69827E01FF45F051
-:10EA7000FCE1BF085E2FFC17C179F82F82EBC37F42
-:10EA8000115C0EFF457079FE093D9E0B3BF4781E2C
-:10EA9000FB9E1ECF8AFE06C2C7F84E3D1D84E26370
-:10EAA000E2A7217421F1309FFFD31F1EE828C2E99D
-:10EAB0007F7A2323FBDC37E1E58510BC4C1AE9693A
-:10EAC000C77E9D3FE862AA0578EAF18CC079F233EF
-:10EAD000692709BDC7E9E5EA00C521FCC048F1374F
-:10EAE000270DAD1AF8B23FC5736C2CAF7F7B4E2358
-:10EAF000D14F222BDDBF84CFA7FC3FC2C88F533E2E
-:10EB00004CC4EBB29C4E8A7350FCAE3C59DC237A69
-:10EB100063AC3CBFB9C47DA28EB1429F8D7439E80D
-:10EB2000DE71458E88E3E0C7AED4F251A09FD76D69
-:10EB300023400F5B84DFA413F1C271817861E89BED
-:10EB4000D0EF52A47ED5F207AB15EB18B18DE9E4F6
-:10EB5000E4489F5577EFF5EABD0E5D7E545BA2AEAB
-:10EB6000FE35879CBAF25C7FB6AE3CFF844B972F94
-:10EB7000EC18A7AB3FF63DB72E3FBE73A6AEFEC462
-:10EB80004F4B75F964D6F330E03B4C13E77D2BE730
-:10EB90004B740FCC29E281CAEF8E1171A0D20EA066
-:10EBA000F469751FDA23E92E544F1F66117A6A4BF8
-:10EBB0001213E730AB3C6F31BDBEEE91F799959ED5
-:10EBC000CABCFAFBCCEA1E739F5E2FF576A51F0721
-:10EBD000DD637607DF632E97F1DBA1F22F6E9CB029
-:10EBE000EF85CE7F9845ACB7E50E0BC58DA879852E
-:10EBF000CE67799EA0DBDDD6FEE377D2C769D47FEE
-:10EC0000516EE99071BCDE6366978FEC28578CE7F4
-:10EC1000EAF4E25CF9238BEB2EE7378F577E8D58B1
-:10EC20004F99C170FBEC1CBA2F36FF9741E3E78D7B
-:10EC300013F41D3F41EB777DE5D1E23E178BB638EB
-:10EC400041BF038F27E0996861EB28CE48DEFBBF08
-:10EC50006D53DB7D23785199A5D54CC60BE63383E4
-:10EC60001E664DE3FA542EEC822F3E62E7FAC6632D
-:10EC70004D26B2F38C1F37AC8C6B627D711CC3F8D0
-:10EC80007903F4019D05E79427C71B699C85E3C4BC
-:10EC9000FA4A8C97FBEEDF93FF8231C9BF19DD87FB
-:10ECA000E987DE880ED53AFE55F7F115DD86C249B3
-:10ECB0009D2F99943B99725E0A7E6A3F28F8A97845
-:10ECC00008E70A73E94E3BC555CCC43D3285BF9772
-:10ECD000C70B7EB409F02814F5C08F06AA5762CC82
-:10ECE00089863DBC9739A31D5F63EFFD17C62910C8
-:10ECF000FC078AAF1A883F5CC1170688B71A883E9E
-:10ED0000E9EF1F88BB0AE20FE25E8FC4872FD34072
-:10ED10007EF4BB23F5FBF8857102BE1EB98FB97C6A
-:10ED2000B5E7EAF90483FDBE65BD51F2092157A19B
-:10ED30006FE0FBE2F566D237182BDD8A38A28FB67A
-:10ED400098E97EEB64B773864BF8E749EF20BF176D
-:10ED50009F5A85572F4FB97CDF093D780A736D8024
-:10ED60003FA372A3BE7CA97DC66790E78B43CEA567
-:10ED70004BE5797569C8B9F4A971521EBB988BF43B
-:10ED800024E9E7AF9675FAE8C897112DED2EB43F48
-:10ED9000794AF7C2145C9CF0D7E407F21C7EE1D9F3
-:10EDA00090D3EB4CFDDED7EB83DF00F711CEE23ED4
-:10EDB0008213FBBD97E2AD7A0FD8849F52F983642A
-:10EDC000FDB3DE8B548EFAE8ED5C6EC768E8217DFA
-:10EDD000FEA3103F54AFDD10350EFDED33537FEA37
-:10EDE000BE45CD5F7DA31D41FE644FA75177BFE5B2
-:10EDF0008AF9AF7D8EEE5FDC1DE379077CFC8CC960
-:10EE00006505FEEEB11F89479CFC2C69B7099D6F13
-:10EE10009FDE59A4093FAC57C4CDF6CED4E81E00FE
-:10EE2000E7830CFB46DD1B98CDFC7148953FC6B3CC
-:10EE3000713CC159F9632AFCE3699EF35A969AC35F
-:10EE40007995CE87D794843B037E9ACE1471EF6771
-:10EE5000207FCDDC4BB9D4DF4D9726523F17C7A595
-:10EE600009BD6BDD7D2B404757ED6566ACB333E4E0
-:10EE7000DEBB4A2B25BFF18E577C5ADE275AAB11D9
-:10EE80009DAFD498BA5F447C5AE52FB6CA7C89C836
-:10EE9000AF5A2FF29D66F1CECC1E696FC03A9162D7
-:10EEA0003D3817EF93F608AC0329D681EFE04BC845
-:10EEB000832F210FBE843CF81252F0257C5FC44A98
-:10EEC00053738DC2AF541CB46FE0572A0ED27BE04F
-:10EED000570ACEC3AF145C1F7EA5E072F89582CBB3
-:10EEE000E1570ACEC3AF145C1F7EA5E03C1B775DE3
-:10EEF000200F3EE69EADCBCFE5FA7771D0BE855FA1
-:10EF000029B87FF89574FD7956E8DADFCA9A74ED6E
-:10EF1000E1570AAE7F7B93A6F33BDD2EDF03A8DC2F
-:10EF20003688E8E3A5D1A5AEF17CBFFE39E26FDFFC
-:10EF300033E31C606C5F06BA5D591FEE12786E9D5C
-:10EF400029F06E6002CF3D0B08CF6B2C225F22EEC2
-:10EF50001FF7E7BF29360BFF0D52F86F90C27F8372
-:10EF600014FE9BE2E1C27F8314FE1B7C87FF06290F
-:10EF7000FC3748E1BF410AFF0D52F86F90C27F8312
-:10EF800076F0DF2085FF06DFE1BF410AFF0DBE9F5F
-:10EF9000841F29E8DD0CE8E999BA731DA743DDB9A0
-:10EFA000CEA1CB434F0FAE0F3D3DB81C7A7A7039DE
-:10EFB000F4F4E03CF4F4E0FAD0D383F3ABC739893E
-:10EFC0005F425F0F6E077D3D383FAAD57B0CB6A32D
-:10EFD0001BB69F7F156967A4F698C659C18A170E9C
-:10EFE00094C1CFD669D3526338A7346B2F9615F3EB
-:10EFF000BC47DEE31BCD7A0CC037F9D939DE3C7E45
-:10F0000046F78E477D9544E5CAAF4B7F1CEFB907A5
-:10F0100018E9FDC764BCA76AEF620E2352553F9002
-:10F02000EFBF5EE8F8AA1EF1CBA079F083612EEE67
-:10F0300099E4AEB1E7E1BEFC1E8326EE9BDE25EE31
-:10F04000FB86D2D56EC997F618F61F09C7FDA10A2F
-:10F05000CD8538862C133B61CE039C1AF3A01FDCB0
-:10F06000373E46AEAB7102EE1FA9792B3B20E7136A
-:10F0700014BF56D4C32C557C9C495F30CB62F077CB
-:10F080008BD00BD00EE7C5ABBD9A7B67107D3F34AC
-:10F090005EC8378F77C5842AFEFDEA7D8D13101771
-:10F0A000372B5CB4FBF9E35104C71BD7693B117FD5
-:10F0B00058B48FB911EFEA93F3BE7A9FC35245E378
-:10F0C0003A289E4EF55BB13D95E2FF2A586731E242
-:10F0D0002B5881C6E01F5570E3EB7B15EBCBE25B51
-:10F0E000C54CFAA788CB099771392A1E272CA6B4DC
-:10F0F0000A724BC5E54C2A8829C1BD38D6CE5C08BA
-:10F1000003BEA1A062FD60DEBFC7E776E15ED1A4C9
-:10F110002F1A8F517E5729E5890CC6D03824D7463F
-:10F1200078357A5FE346EF0E439C13F1BA6BCDF16D
-:10F13000A8BF8FB9A0EE70514371A76A7E39ACC3E6
-:10F1400060D38077767450101D710E7013F09EEBB3
-:10F1500032D3FB1BB34D0E33F846A81CBFF2DE6260
-:10F16000889E1072BFA465CD7BA9C674DC2F31B810
-:10F17000FCE05BCF4590BEA0F49D0A79DFECE2BADB
-:10F1800063836FE1E515FB857EE0D9A611FF53F798
-:10F190004DEA337CA906E80B43768C8E350AF90FCD
-:10F1A000BE78C6FBECCDD8A215EB8F515C44C5FAF6
-:10F1B000C268111725FC1055124E55F25E11CB7125
-:10F1C000C443CFFC90F31DF708BA97184D7185AD75
-:10F1D000429F53F616A50FAAF7632ADEC83F0EBC5E
-:10F1E000573C2ADF65D95841F157A1F77C6AA5BE83
-:10F1F000B76C9D99EE0F2D0BD1076BE57DA1DA1051
-:10F200007DF0DCF8107D509E5FD47DDE8A378ECE97
-:10F21000237DA5D14C7EB9B2B5427F61FB990FF138
-:10F220000C656BA71BF06E48D9736E97D60F9DBC0B
-:10F2300025F598599D3682EB9C4BC994DE7C298933
-:10F24000D25B2E897B94887D011D74BEC0488F7E61
-:10F250005BEA2DF370AF12F188DE30797F9291DE98
-:10F2600094CB1C25E01F57B9B5A350FB66993DEB25
-:10F27000716F73D60E46F1473740BF41FC17F41D3E
-:10F28000D8DD0BD24A280E63A646F12C3714AC9079
-:10F29000F4CDE99D81DEBD927E4B29DF2717249DA9
-:10F2A0007BBC5D26C0FD06AF66C13B7C1E798E55DA
-:10F2B000741C4AEFE511D2FE6417F6A53EFB132637
-:10F2C0008B476DBCD1B7E17E6B396C764398403C7F
-:10F2D0008779648E281FF162F46DEB70A8F9BFB4D2
-:10F2E0004B94190C22DE89EB5BE0ABB7ADCEB52CAD
-:10F2F0000AE22F5F4C9C3663626100EF8B42E2F4BE
-:10F3000056DE333CE1EBE2452B399CB14FCAA33BBF
-:10F31000BFC729945D3B81B98BF999750163EAF107
-:10F320001E3FEE052E94F9D52F8EFBD3463BC187A9
-:10F33000F2D327A4DEE625BE2AF8D6ADE05B46F080
-:10F340002BCFD409C4AF3A67001F11393DF21D021B
-:10F35000299742EC10AB2738C57A43EC11953982D6
-:10F360009F339333F5568A0B76923D4FCDFF43B3CF
-:10F370003E4EB3CF2F3241CA93E67F4D7CC3FFCAC6
-:10F38000F0DC86F56D3588B8F921C65626ED42B415
-:10F39000FF15FF60F21D8900FEB99E467E74CD11F7
-:10F3A0008C7FCF464DC4A90F60BF61D93D0FEF865A
-:10F3B000FDAED9C210E7FA7896A0A3C77F60213DC1
-:10F3C000BCCCD2710CEF642938BEDFF4EF66B2CB4F
-:10F3D00033FF70BCFFB5B0D1E6027FFE6262E92A5E
-:10F3E000CC3B22C745F898C1B719FA3F9952FA7D2C
-:10F3F000C2D7A6571E43DCFEF2F6348A23AD3894FA
-:10F40000BB01EF897C31D1F3C309F0E3DA1D16C8E3
-:10F41000F186753124D7CA13645C27EB213F9582AE
-:10F42000FF031384FDEABA2241C7DDF23C028639AC
-:10F430005B574FDEE30ED927CA2E186A5F087DC7D7
-:10F4400061A0FDA3EC08B01B5882EC8ACA2E61CEE5
-:10F45000FE7001E46899451F7FA8D25795DD4D9E47
-:10F460000717F7C9B19C1909D09B376B0EC8B12A91
-:10F47000BBF396F13C5F75C28C1B986C56AC53BCC9
-:10F48000DF718F78BF6311DFAFE03765F23E56D58D
-:10F49000B6F1B4DFAA7C3CCD1F785FDEBAF968CA4A
-:10F4A0000BA01FBF9BE2F2AB1C6E4B6CD0BEAF6CCF
-:10F4B000D57471FD2A7F6082B0C39571351DF0BB94
-:10F4C0006D759A056FE89471F502F7FB5E9DE0D4C7
-:10F4D000C555F37A74AF61563A3B2EDE4FE2F34ED8
-:10F4E00013E3E505F5BFA855FF3E01AF4F7AD1CB39
-:10F4F0001322097F150EBEEE34A40E9A278703C18E
-:10F50000A9E73EDE9F93C6217C54FA7D669CBBCB67
-:10F51000709F82E7173A7C668CB3689D782FC4B3DE
-:10F52000498CE3D918631905BDC9E4B0A4007E383D
-:10F530002CC7D1FC880F5671B820DE4AC55D86C243
-:10F54000A742CEB7AA3546AF8FB56E36031F0B065E
-:10F5500078AFA047D2EDA2755329DEBCCAE4A678E5
-:10F56000068F84EF472B6CF7C22FB060CB43E63495
-:10F570009CB32708FB738FDC77B3D2FDC3E95DA092
-:10F58000153617E6B9C0D14AEBEB83EF831C1E1A80
-:10F59000DE9F2925F872BAF0E27E5ED5163D3E0365
-:10F5A000F311F0ADDA5241FB6D89C9637104CF6389
-:10F5B000DB2BC3710F6501DFDF78EF88393C14DF87
-:10F5C000F4F183B7A4D23AF93CE91E94CB3903EFA6
-:10F5D000FC703A213A56F4A2E2B2D578D689222EAE
-:10F5E000D33AF19BF6A59BF49A168E5FD8BB07DA47
-:10F5F00097160476F1712D55E2FDB5D07DAAF6A7D8
-:10F60000DA976A9FAAFDFB98B9D49FA805F80C97D2
-:10F61000B78DBFEC074E33E47C174ABC72B8BE1AF4
-:10F620001CC775CD4481D7B274FD7E477FE837652E
-:10F63000A2D8EF65D3FCC31177A9EAAB71CB6245C1
-:10F640003BD03DE82D65A2A1AFFE4AAAAF8F47A9E6
-:10F65000ECE317FBD6C7835FECD748EF5D79DFD1CA
-:10F66000947F833EFBB4D067CFD4ED6E4882DE68D2
-:10F67000F2A506BF8B55E517FC6131D77FC02F96E9
-:10F680004839DD9EE7C99918B47FAB1E783ACB2381
-:10F69000F88B1FFCE583A75FFAFD0467407EAAF99B
-:10F6A0002FDAF85B73853D185E627DF766F7529C32
-:10F6B0005DA5DDE2C4FDE5CA7515C46F59223F574B
-:10F6C00068017C87D241C53A8DDE17AB6C1AE333F3
-:10F6D000FE37F2E5CA4DB3E94D248527F5DE899260
-:10F6E000A76AFEDF95F35F28E978CE44B1FF16568E
-:10F6F000A75996D0BE4FB35482FE65F9822AFDF712
-:10F700003E3CF5F9977336607F206E88CE279BCC00
-:10F71000C2CEB72F92F4D5332B9F7FF3665EEFF303
-:10F72000AD3B52A19FA8792C95F6BCC5D22EB7440B
-:10F73000EAAD1C4F15C1785AFAB8C053E5336FFCD7
-:10F7400009EF7295A54B7E769F88E75FD4B69FF050
-:10F75000B660E366731AAFB762629AEE9E4C652399
-:10F760003FE872782EDCB8C30C3EB062A2805B2802
-:10F77000BD97C9FBBE0AAE903B5A90DF42D507FF4A
-:10F78000DBCFC759BDC21605FBB41AE71149D7959F
-:10F790008D31B118AFB2B1E2273877287E1FBAEFAA
-:10F7A0004ED9C47E58C4FBC3BE3C35D54571CDF09F
-:10F7B0006BF52757374BBCFDD42CDE6F4C8E687B26
-:10F7C0000270485E1EEE027FC8CCEC24BF31E819FF
-:10F7D000F3B618C47B8F99759D17300FAE52D3FDC9
-:10F7E00014A478670A2A763CCFEF3488F8AB74A368
-:10F7F000489F97F0E1E57E94B3B84E7A77AEEFDD9F
-:10F80000A4107AB5B05D1BF1DE8D258EB95A9C012E
-:10F81000FA54FD28FA54F43BD0FA7E21F9C837ADEA
-:10F82000EF549AB44764BB5211A7527EFF0817ECFD
-:10F8300033DFB44E8B7C7FB06FBD9C58C7C5F6B329
-:10F84000DE4C716E1978BD5B4AE2FB596FE83AD520
-:10F850003E5177DAFBFC0BADC2BF704AE3F28BB7C7
-:10F860003BB5C246F7BFD4BA94FDFBDBC621BC3D15
-:10F870003156DA133A23A1479685CBFDEF17797CF1
-:10F880009F1DF45DC97DF55E9BE2CFA71BA55C645F
-:10F890009DF7613FB3A60C7A9FE464EBA948BC973F
-:10F8A000726AAA989F6AB7DA2CE28C59A4C589F7C4
-:10F8B0000FF9F9EA6413FC3EEB12E81C795B53067E
-:10F8C000F185DBBC31C2FE20F5FB25920F46ACAEC4
-:10F8D000D88077BE176F4B73687C9CC576D7C7DB23
-:10F8E000A8FDD52EE883115B665BD249EF15E700D2
-:10F8F000E5275AADB1528A1B039FC4FE32BC920960
-:10F90000B9B3749B3807CC32B08DF0130E6B299DC0
-:10F9100091043EF1B04671E66CBBFE1DABB1F9A59A
-:10F92000E7E9FC17F20EDC6A739B3B017C9CEB1B46
-:10F93000B0372DB69792DE5E2FF9E4C92D5DF41E27
-:10F94000BD82EB15F13F161107DC1369203BDCB7D4
-:10F950008D03AA927E254537CA2FF508FE331E7007
-:10F9600032925C2B3196D17B4A1BB64CA7B46A739A
-:10F97000C956EF28C41F97C64FA0799BC94E56554C
-:10F980003F5DC4EBEE0C8BC1F926D5EC4D0DD64B8B
-:10F99000AB76DC4DF13F9FEEB051FC4FB163767119
-:10F9A0004C1CBD774CF175AA5E6A91E03B35F5D3EE
-:10F9B00075F13B8B799F7867F3CBB608BA1FA6E247
-:10F9C00072EA123C494583457CCE78A788CB49A290
-:10F9D000FACE7EEDE22AFDB859C47904C51BDDB824
-:10F9E00080B7AFAB7F360AFDD43EF8F6188781ECBE
-:10F9F00050C3D17F5FBCD136116F9425CF4BB3621A
-:10FA00004B6F5E00F8FFDA48F01F68BCEA439ACEFD
-:10FA10008F779B2F9AF4568F9F59E047F63818E955
-:10FA2000C59F1A5913F400A5BFA8EFE3255C3E8DCE
-:10FA30006E4D057D2CDBF3502AE4CB6791225FB637
-:10FA4000E796DF805F79768509FDDCC4481FAEF458
-:10FA50000AFD9A55C7AAF7486DE59C8EA6174588FA
-:10FA6000778FB6E9E3CDD53BB79F99C4FB3C883788
-:10FA700002BDBF6FF22F067EDFE7FA2BCEB1A9459C
-:10FA8000823EDF6F35CEA07B437CA3400F79BFF56C
-:10FA9000D948C4432B7DADC4F8811BEFFFAC7C4E2D
-:10FAA000C405E37D7A7A2B54DA411AA41D64E50B70
-:10FAB000E619C971A47FD1973A93DFD21FFE6AA4D9
-:10FAC0007ED5973FB09FCE6D75FB84FE50D7D6454F
-:10FAD000FA83D24754DC61EDBE2ED22754BB860395
-:10FAE000022EF507C4F78A6C83B2A3B8B54C9CA765
-:10FAF00035CA7B5FCC2F5F6B0ACEE795AF05B39F0E
-:10FB0000A0EC233DA40FDE9BFD3B3A87D7AF93FDCE
-:10FB1000F2BC3968BC6A1051A1F89E61477BA7EE20
-:10FB20007C577F2086DAFBEBC33742CEBB1BEC262B
-:10FB3000A42DF57692FBDB1B0DD9B8A7EED6C25DDE
-:10FB4000D0E3DAE5FDADC1B5EFDA603F48623D478D
-:10FB5000F1DEAE3FC5F3C322DE6F025E773106E20F
-:10FB600089BA0F7F928FFE270FEBBC883735CCDA2E
-:10FB70009472F8295A8AE43A723AF341D7838F088B
-:10FB8000FEFCA8996DA4779B4DA50CF67BBFF42FC6
-:10FB90007ABF32D0FBB3ED9AFF67C1FAD521499FF6
-:10FBA000A561C2CFB873B46713E6F15DCD3C2A9767
-:10FBB000EE1D1A87A3FF6EE987547AEA34C99F5372
-:10FBC000E4F9CA3224D10E3A56F7ED34B79BE23D40
-:10FBD000EFCA395209F9FCE31E2BC50B4CEB092780
-:10FBE000BD3565C84C9267EADD7615F77324C7E02A
-:10FBF000C57BF43F6656712FC01AA2DF1A6C743FA2
-:10FC0000596BFFD557E0EBC9C60B47A3715FF6DF11
-:10FC1000347A7FB4BCF7E347DF62380FFB72291EEA
-:10FC20003AC5B307EB39D93BB3CBC351F763479B15
-:10FC3000D525E4050B5E47FB1D5F45C51A02F3EBB6
-:10FC4000EEF998DE75ECEEB192DD765ABB7CE730CA
-:10FC5000643EDD894EBA27CDEBD1FBCFDD7603BD07
-:10FC6000EF36ADFD28BD57384DBD6768D5BF67C8B5
-:10FC70003A52626057265B2A570EE25B04FE264723
-:10FC8000EBCF8BAF15097DF1B522ADDFF7EE55DC7B
-:10FC90008A922B2FDBF7DC26EC52629F2E577EFEDA
-:10FCA0004BE9A44FF4B6677CED3B166F43AFE0FA27
-:10FCB000C2856BDC6F171506E4EA3C0927259F55C2
-:10FCC000DCC23C09AF797683804FC8EFAE28BA0911
-:10FCD000A58B50BC2B7CB21F741C433C16C7E3A8F9
-:10FCE000FB19E1EF24E1EFABD7D7E3D985214677C4
-:10FCF0009727EDFF45FCF96D23A0473C68203D4266
-:10FD0000DD77F4C8F7DAD5BD4796CD881F941BC3BD
-:10FD1000C95EE891EFB4733E700C7C40EDFF613337
-:10FD20003B47418E9EE44774CCAFD3D046DF532788
-:10FD3000A5D37E1DCA3A92E4FD9C42E86FC6C0FB83
-:10FD4000D444F72D9AEFE125B87F39CF4EF7DCBBCD
-:10FD50007D21EF53CB77CCBB99E40FF3D53BE67C09
-:10FD60003FF3765B1688F2BE77CC87333A476DC98E
-:10FD70006559D0BFD4EFFE0CF88EF9B258B29B3E55
-:10FD8000F2886F24E4817ABF7A4A8A2771D2E02B05
-:10FD9000DFAFDEAA952EC0EFC0784789F9762E082E
-:10FDA0007F668F00B71FF69E934D91F46EB7A253F6
-:10FDB00065E71EE6ED7A18705271B57F96F4A6E0FD
-:10FDC000AFE20AE342F0A0E8CE6B6614870B7C201A
-:10FDD000CEA8EFF763D648FEA2E23A5F763991FEED
-:10FDE00038D5933B09FB70058733D9D13BBF87F5E5
-:10FDF0003E7A47A41BF33B297FD722745F154D320F
-:10FE0000287F31C50D944BF956AEE2049AF4710285
-:10FE1000A1EF9C860F2D9D0CB89DD3DE1E838FAF66
-:10FE2000FF6F63BFF74FAE9D24F84466A267C624F8
-:10FE30009273D374FAE4EBB99FA4D0EFCC5C3E3A52
-:10FE400014F2EF9694D2EBD0AF2D53F80FFE9CD462
-:10FE500049711E7F5EF0D714B23FAF11EFB37EDB66
-:10FE6000795E19D72CE861D562712F319935121D51
-:10FE70002706E2656D98C7FFB4B8E640DCF15EFA8C
-:10FE80007D91979BDB324E0FEF07EF61479E75F236
-:10FE9000938DF7F0CBE514F71B7D64551ACF6F3CBB
-:10FEA0007CB49CE27C938F5C4CE3B8B9F7F0AB2256
-:10FEB0007FF5918B880BDE74F898A80FFFC110C6F0
-:10FEC0007E72F878B997E3E38ED19EFB81AF9B2FCA
-:10FED000351E8338FEFDDA398BD328AE75764AB6E7
-:10FEE000886B5D07BCCF8B5FB43E5A0BC4B5EE9BED
-:10FEF00024DA755F10FBA0FB82A0F330F083C1FF12
-:10FF00007CAAE27B151F1E885FAA7DF8AF8A4F5638
-:10FF1000FB99ED716D348318BDFF74DCF093936829
-:10FF20005DFAB8E16E73CF63E457BAC09CE013AFDB
-:10FF300044BEEB84BC682914718D5A4F8713F73186
-:10FF40008A0A44BEE54287137C1E79D8B7BA634457
-:10FF5000BCA38A8B6DB9E04FC23E2942FC22AF5F41
-:10FF6000DCD3530E3E5A84FBBC69E8FFF851391EBE
-:10FF7000437FBB2E88B8C36E5B87D321C7413F7CCC
-:10FF8000DC34F0C7A2D556BA77D472A17105F55307
-:10FF900066EF1B570B19D7FAF5E34ED782C6CDECA7
-:10FFA00015F19D18D7A91BD74F71C1BC3F8A3FEDF2
-:10FFB0008E7125E2DCAFF2C528E7F987E4EF54142F
-:10FFC00039FD46C8011527956091EF71CB730BAFD2
-:10FFD000477199BB7AC53ACF37FB6BB09F8A25DF53
-:10FFE0002EB608B9C90CE12EDCC72E315E3E9E8CC0
-:10FFF000F3C90BE27C521C56BA1DFBB1C124F80DAB
-:020000023000CC
-:100000008B53BF97D6B1ECE7BCDEEFE293E9F7C5BF
-:1000100086261E6499381F2F9F9903B9C1F5EE33C8
-:10002000C0F7EF58AB267E874BB49F3B3382EEA1DF
-:10003000741F1E5188FD3327CCF91CE3FBB677D221
-:1000400057B44FE7443B0B71E2E93DFC5F229FE070
-:100050007C0EFE5D2BFB8AF473E5AFBD25E0AFFDA2
-:100060005F18A77EE6398BD0CF7AE89DE6FF9A2409
-:10007000DEA7E3FA3BE91F3DD7C97737739C852894
-:100080004F35F744016EDD974DE2DD5AD6137553B7
-:10009000907FF6B176F19E6D285D1F9E2CE4C0F234
-:1000A0004C3BBD77D69068B552DA7E6106FD1E8C5A
-:1000B000A93413E703B7A57FBBE32F260B7995B6C9
-:1000C000C112F0BF73F9E10E672AEF65E318DBF1A7
-:1000D000FDF0BEF317448C65B83C8F79131F2F36A3
-:1000E000E9EABB51BFAF9C8967DA54FB9C97ED8F5F
-:1000F000AF33C9F180E725E2FE44A8BC689812DB63
-:10010000F75E21C9DD381BDDBBCA344A7B1EAFEB6D
-:1001100020BBA0F0DF26FF878DE2E876D9041D66BC
-:100120001A44BACB20E37DA5BD4F9D637E3CC53309
-:1001300069CA60EAC74FFD18F7E742AF48626D34FD
-:10014000BED2CF543DAE87D988C9C8DF7B2B321AC7
-:10015000FA85E73B93A7964E2E045D7BD947417203
-:10016000E27C44545330FE1A8C7ABBE73B93A75190
-:100170003BD5BEBE693AFB88E211FD443FF59906C6
-:100180003AB73618D9ABF4BB03AC83FC99AADDBBF4
-:100190009C4F7E44EF36B8297D8FF3CB8FE8BEDFCE
-:1001A0007C4A3F68F6D0F793CDD594763637D2F7B0
-:1001B0000F9B9B28BDF9D6C802D0FFF2436BD947ED
-:1001C00041F2B1BECDEC09BE5FF3EED4FEE9E8FB2F
-:1001D0009385DFE6DDB4FECBEF57E593053EBB1715
-:1001E0000B3D93D3E53A47ECC0FA4277A4B897F0B9
-:1001F000D234717EED4E12F9C6C9E2BD50B7816DA1
-:1002000043FB97A65928FF6EBA81DE7570C78A7EB8
-:10021000DFCD32909E76FD8CA90D80933B9E7FCFE3
-:100220000BE4DFBD4A94BB8788EF6ABEAA7CD294F8
-:100230003E3B4296381F0BFF3BA777EABF0FBFC577
-:10024000627EA1F5D57DFA5078FC56EE5BDA17D0C8
-:10025000DFB10FD282F6458393F685A243457F0D29
-:1002600053C47ECD0C9374CE6517C10F320CE7E3F7
-:10027000041BF907DDF05FF0F5EC92F1EE57EC07A7
-:10028000E90F50FB41ED0345EFC97C9F097F87587B
-:10029000C72463FF76FA87268B7577C447927EDC86
-:1002A000DD6E7640DE4C320ABF4377FBBC02DC0BCE
-:1002B0002FB9DBDED81FFF7A53B6FFA7E1A0F8C144
-:1002C0000070B862FD1669B7FF07D74FFC0D7C7B45
-:1002D000B1B897194AAFED9395DD5DD0ED3B93DD55
-:1002E00007413FDD9ACD84734AB7ADFF7BE42F4DC4
-:1002F00013FB42D14FC31426DFA1E1EBCCB892DF50
-:10030000A9F5F4AD732923BE9729E38D43F1ABD64C
-:1003100015C4F75E9F3C38004FC6B8BEC2FB195AE1
-:1003200067A773AAA2DFF383BF5A02F9357FB253DE
-:10033000F8990C46F91EAC90277DDF3523C55D0585
-:10034000C91906BDA5E7B0F0C7F9F93909FE2CD8DF
-:10035000A083E3AE2D53C4BA7BE7171A602738FF9A
-:1003600017BB1772EBFC909E93D04BCE6F13EF9D93
-:10037000F31E6769B83782F81F277EB745F8418CAE
-:100380000F7F7912FAD092878DA4BF9CC7B199B71D
-:100390005BFEA0F89D3B757FB04EB66BD976F166DB
-:1003A000FA7D334E9FD07F3EB235A4432F9EFEF0A0
-:1003B0008327F0FEFA92E734989BD951D8DD79FE75
-:1003C000E3BD46F13BAB32EE6486BCDF5FB35BDC82
-:1003D000EFAF43BC09F497033BB6E2F727EBF79A7C
-:1003E000998D7F9F8177D2F8384BDB22F94192F7C4
-:1003F000BB451F377A2DF36E803DB97ABBFE7BCDAE
-:100400002E7DBE2EE4DEA23645FE9EC148964BF7F9
-:1004100013B7087BB1E2DB57EABB5E82AF7BA5BABC
-:10042000AFFB05BDEF6D3CFC65EA8776919F2DF330
-:100430005D3C7FEE4B017F05B706C9F3CF25B18246
-:1004400036BEBE86C33607EC000D2F083BC1F9B699
-:100450006882F3F2F04EF22BB0178D0EE861F71CB4
-:1004600032925DA1BEDDF633FC2E6DC3731ABD570B
-:100470005B7F28CC27E0736109CA971EB2399C289C
-:100480007F318CC1FE7C9EE30DF762CFA77412FE14
-:100490008157D825F8DF2CFC7E85C2BFF161E14F82
-:1004A0005EF284C4CFB65526C2AB4F63096957E2EA
-:1004B00049E1F95786A7FAF08476D31FFEFD7189CA
-:1004C0007786789BA3DB2AE9773114BE2D873F4AD4
-:1004D00085DEABF06CE478FEA16AEF94EFE17D0D70
-:1004E0009EAB8167FB3F8EE73F423E1692DEFBF1FB
-:1004F0004FA1F7465AC88FAEEC1ACA6E31B8F6DD76
-:1005000063717CE0E189CF929E5B1E7BA67E052312
-:100510003BDAB5536047BBEE0DFCAC2FFBDDF54F6E
-:10052000E5823E5ACC9DF4BB31DE18F1AE7C77DA21
-:10053000ECEDCFF3F18A63BF4ADD8F7DF37218B91A
-:100540004FE6CA7D893F6BF0BB80ED36B2B7D5B7B9
-:100550008709FBDA01BDFFAC3B49FC4E5F89A5A7CB
-:100560007C05F472DE1FC651E7C1DA76F9FB2FF283
-:10057000FC56ABEC0CFB42DE8772BC41F5EAA68868
-:1005800078DB8C84494EF0A19605CC139EF175FC66
-:100590009E11BF57BF9737A01E3800DF57FA1FF3D1
-:1005A000EAED1C8AFF2C95BF2FD9B73F64BE7AAD08
-:1005B00037CA6A24BAA3771BEA1E15BFAFF809E849
-:1005C0002E2A404F0D323EEDD8F77F63C2EF3475CF
-:1005D000EF12F7233887DC8A7BFA67DB443C5C4DFB
-:1005E00041D718BF13BFD321F8D0B27D9ACF99D687
-:1005F0000F1D31DF06F1AE7D083DEDFBFA770FEF01
-:100600000DF091517FE7F0DC51C2A4DCF2F61B3F04
-:10061000D927BF427EC7E37F5A3C776F0E5FCFD7A3
-:10062000F81BAF4DD4BFE3729D53FF3B4DDFC9D6DE
-:10063000FF4E53AF5DC247EA834A4F3D3445C8F190
-:10064000D054C1F706977E1C752EFEEE38FD78B3A8
-:10065000DDFAF1BE2D5EFE5571ADDF04BFE372DC45
-:100660001372DCDFC871FF5938A974A0F1FE7F4D09
-:10067000FF0F822563C60080000000001F8B08006A
-:1006800000000000000BB55B0B7C94D595BFDF7CB0
-:10069000F3CC7308210904C2242421608803245464
-:1006A0002B94C9D300D6065C2D68840152C83B80C8
-:1006B000B5D2D6FE3208222F5BA8D1A2224E82E10B
-:1006C000A1613B118289863A286411AD1B698BFDBB
-:1006D000FD56DCF828F23213A374E5575DF6FCCF23
-:1006E000FD3E321942B5DDDDE4A737E7BEBE73CF6C
-:1006F000FB9C7BA929CE317C394588DC9873E69E2A
-:1007000008215CAB7A8A12B385E87B43154D0E2134
-:1007100084DB7BBC3E5688DA8EE1625332C1257D94
-:100720006F1A00B78DB36FA2F18DED7F781BE3BD1B
-:1007300007558785C65F6BFF280AFB5CFC325C8827
-:10074000E158F7519420B8FAB2C2F0261A77103C5B
-:10075000AB5515FE4CDACFE83363FC62AA0E7BCDB5
-:1007600082DA929656730FB5557B5B79FC0D9F69C3
-:10077000F0F8DEC641E376CCA7B6CAE88DB2537B6B
-:10078000BE5DDFCFCFF3AB53159717FD7BFF10B7DF
-:100790000CF35ADE895B4AED15FCCCBCB6FDF4D0F7
-:1007A0000B996E5A57D341FB440CEC53D361D26082
-:1007B0008977756A6B510CD14BB428228D9A8B6264
-:1007C000AB584DF4AC6A6FAE16D45F95718F49107B
-:1007D0005D023EB518DFA71F8388A37576FA8BE804
-:1007E00077D1F779D452DAF755DFB1DB5DD4063A29
-:1007F0005F8FC2770307697EE6003ED35D44BF1C6E
-:10080000B4662146D0BA83AF4739687CA3EF7549F7
-:100810006FA39FCFFD9A0607A8653AB7AB7CEE8A17
-:100820002F55A6BFBEDFAD2E95F799D59E168973BD
-:100830009DF4C9EFCD7539647FEAE232E07F226131
-:10084000418E9ACC78BB000726CE69DE44A854F9C5
-:1008500068DFCC6BE9B654DBB7CB24E6FBC0B7D47A
-:10086000035DA3483E4E140F9F4C2357E7DDE33250
-:10087000F0BC22B33B7505CD3B19E188B4D37E0FA4
-:10088000158F8B045F5F438BFEE25D6637B595077E
-:10089000E5F74EDABBA3206F270F4E553DCAC07E49
-:1008A000776ADF15C2C3ED00DF3CCCA7726F63042B
-:1008B000F619E09FEC9FEBB2F3FC13DE77EEBA87FC
-:1008C000CE773223DC09BE749945B98FE5843E8228
-:1008D000EF752636820EFAF7E6821FB42E9061601D
-:1008E000BEF6B69BB479F7348B41F34CCCB78BCFC3
-:1008F0000DC6C7EEFDE097F7D0FCEA675461A1EEA4
-:100900006AD38A389CFF931D83F12BD7E85C6DF284
-:10091000C7C505C96B75C7557D8960F9EED0F5C3AC
-:10092000C1FCD4F978324395782558BC8250AE6E1C
-:100930006D66B92675F3D8A6702BECD4268677277A
-:100940002B74FEC407ACCEB584FF738A366EA03616
-:1009500086608384CDD45AA97DC624FBA1B6583FB6
-:1009600086D8A9106C2A1E976348A17DD4D6C9E009
-:10097000EBAB335D8FBA088FCD334B66CC043EA210
-:100980006F99A06FD65C8AF08868210AD5F79EC05F
-:1009900077FB0F9A04EC478DB5A3F26392D37E27C1
-:1009A000290AE1DDBFC3E4F5B0FCB9229469422C09
-:1009B000BB49EACD270EF734751CCD5F63E0F355D4
-:1009C000B7A85E1BCDEBAD271210C93F6D4DFE01E0
-:1009D000E4B5FAB86AB7D2B9F37DC9BF9A0EB8C503
-:1009E000E4B4D0FA5A1F75125CBB57F13AE4FE0228
-:1009F0007A597313CBBA3863AB4D1159D4AEE9337E
-:100A000063DE99C38A788CE66D0E8B6A02DE3599B7
-:100A1000B3CF2951D4AA5BD627D27ECBB79B3EEC6D
-:100A2000B1CAB557E8BFBACE6D2CB715DEC1FD55BA
-:100A30007B07C335C23800D3FECDF8E36621DA5C0C
-:100A400091B1676EA0BF2788095754D0697A3CF4EA
-:100A5000E104F84AF2241A88D82385B86F92331E2D
-:100A60007ABFD1E8980D3A043A4D76D0ABEEF081DA
-:100A70000AE0EDAD0E731AE8A8B5AB5F61BA06BE29
-:100A800020BADF486D82E0F30784A46FA05DCA79C5
-:100A90009D49F15AB19E68C8FB5915EF1A1A0A7898
-:100AA000FAA3D83E09510CBD58B520C7003B073505
-:100AB0001684CAAF747D506C46251AADD4FFEF1969
-:100AC0007BD4614176E23F5D298C7F8159B87DD42A
-:100AD0007F5FA4331A723FD61A9505BCC65A93BCE1
-:100AE000A0FB5863DF1A7C7FF328C5F1106D7D24CD
-:100AF000EBE5C90AE0DA0827E44449586C043D36BE
-:100B00008F5A6C84BC8FB5FB324A3207E0028C43AB
-:100B10001F8497BF5714E136E23BCF8D54FC06DAB1
-:100B20003F6023FCA02746BB09F8054C121662CD96
-:100B300020FCC82231FCFF8E9F9DF08B18C08FF8DF
-:100B40001D8DF59F67137DA84D9A2B4437DB8515C6
-:100B50006C17747A5E24792F205EA529526EAA77CD
-:100B60001C29C2788DE85E8F754551F21C45380FFF
-:100B7000E030D9AAB9925FB95A7B7FAEF42FBAFDA3
-:100B8000ECC8751973A9DD9E5B62465BA866C6F763
-:100B90000C61EF5729569693CF49FF608FEF5DA107
-:100BA000D8533306E45BD7AB3AD975557FAA7EBFDD
-:100BB000CB2C52F0395777068D970BA9D78B56DB84
-:100BC000ECA9C17A043D237A94DB2B6E13A46FEE5B
-:100BD000D571F6D4A9D4AF5E340BC89EA65FB1F42C
-:100BE0007B256508FDF285E865FB60D86F9372EEA2
-:100BF0008F54BC6B09FFD4DCC17A97A4E941A35B95
-:100C0000E1F3357E6564D853AA7841F33BA9737547
-:100C10008C7638CC2BCFF5C23FDE496029FA1B62B7
-:100C2000594F7990ECD7BF68E7BCD3E83F02FB711E
-:100C3000CCE44BB6D3D0B11AAB13FB2F1014E89011
-:100C40005D2B15DDDC9E0AAF6DF3F3E69E3190AFB0
-:100C500077DD1627E2B0C6754D91B0E359629DFD70
-:100C60004C06820AB1F7CAD4EBC7332438E28CCEE3
-:100C70001738628A53C06F9DAFDB735D79B939D77E
-:100C80005F5FF5A7B6DBBF03FB757FB3395E8A49AB
-:100C900077C6B401BEE97CAD131EC65BE7D755FE2F
-:100CA00011EEA3410FF5E25CB633CFAA82E30A8DC1
-:100CB0007F56FA1D8A7F3A7D676A7C58DE21ED51A6
-:100CC000285F757AFF9036C4F7C98FEE607E080BF7
-:100CD000DBBF50BE7F135F28C22CC5507EAC458061
-:100CE0009F8906691F1397919C10DEF708F7E11E94
-:100CF0006AEF0A7FCBC472A8F1E75EF087A6BE2B2D
-:100D0000BCDFCF48FEBFE34F476EC903C17A18AAC4
-:100D100077D7D3B36A87F3DF75BF479686F42B4442
-:100D20003F43F44FE7977B7514EBD9553EAA2D52FC
-:100D30005F357E45D0EF90FA863FE87B35ED8AD768
-:100D40009FFC2DF44F21C4896F8F85E89DCE9FEBCA
-:100D5000D91DDD4E9D16FE63763AFFA9141907785A
-:100D60007E62F136034E3794C3EE9D9A28DB039AD8
-:100D70007D0B6D4F539CA3901FDB94717204FCF5A7
-:100D800029B3BE8FCDDB4CF89F5ED33D6625AD3FCA
-:100D90009D2BDB53880B836057985804BB7E7AA445
-:100DA000C5033A9D5626E4C13F9C561EB85DC2F16C
-:100DB0006607E005F17976824F99E47CDDAFE8F6CD
-:100DC000FFF482EF14F03C451C053D1C8A28E1EF3E
-:100DD000284A4C31E173FAFEB4296BC5C0F99B7205
-:100DE0000DBCCEABD96FC283E9DEF753C5DB445DE2
-:100DF0008BE05208FFE4BCDF14A750FFFB3F1B371A
-:100E000019FC75AD1AFC7DF8EBE41B016FE37DBEA8
-:100E1000F7659F6971905FBAEA270B3E93FD6539CC
-:100E200006E84BB9C64357CC8468F0A7DF3B2E1ABF
-:100E30007E47F743FDC70F44B883F8768EFC9418BD
-:100E40001F044F783429D88F1DD9BD391DFB949BC1
-:100E50003D594EEA3FDBF87412E28DF2DD8FA47348
-:100E60001CBC7B633AF299F2A6CDE92E86C3DD9CC9
-:100E70004F19E5B92FECBF79D7A6A0B8BB2A5F659B
-:100E8000FC4BAD470AE16F67DFF0E9C3769A97F64E
-:100E900033C50EF1BA57743F0CFFB810F131F2B7F9
-:100EA000062BDB73DACF05FE374FF8FE73D0E31362
-:100EB000191F99CA68DEE55C23D367A1F06E89A784
-:100EC00071B141B1378BE0F9631A317FF13AC59CBA
-:100ED000003BB062D864D58175C3188F251B267777
-:100EE000A17FE183B27FB6C57BF024F6F98DD9D915
-:100EF000EC607B9352326900FFCBB9665EB7688BBA
-:100F0000C2F1BFFE9DB427E21A83CF7959E3BFF83F
-:100F1000CAA2802F3FD0F872DB83EF1C4DA07DED7D
-:100F2000B1EE2BB01B6F3F7E26D54FFD0531E7326A
-:100F300021E76966F75315387793C5897364672588
-:100F4000AAF1347FCA8F731F43BBE8C1C54F55C098
-:100F5000DE6EB772DEA6E3B74A711A608F5F6FFC70
-:100F6000E112D0EDECE3568EDB57358E8F1743E858
-:100F7000A9DEEE21FE3B28D1D9576FE5F6857ABB75
-:100F800070903CECAF4F60F8B7F50E6EC57C295FF2
-:100F9000ABB4FCF87AFB4DFD325C38289ECDDE60A8
-:100FA000130EB2534971AE517974CEB489354D1BCD
-:100FB000B573A5D1FAC99EE47CD0217BE3CA2E8407
-:100FC000BCE63C998FBD797243128CF2F2073FD890
-:100FD0005941E373F34AC6E551BF75C7675C57785B
-:100FE000BDE39185A0777993459E4F3BF7D9C7D351
-:100FF000E39FA2FD3D6F9838DFAFDBF1C1CE8DD40A
-:101000002EDDB2D21C2CEFDFF6BCC91A3EDFA4578E
-:10101000D7A3C33FAE579B93587F9A48AF32FF790F
-:10102000BDAA7B700DD3EF81BC92D9A0FB59932749
-:1010300009FA7476C20C9673CF6185E9AFDB717DD6
-:101040007DB176DE2A836FCBF4E4013B7E496433C5
-:101050007D8F747C928EB8F752FB82BF7BEE437417
-:101060006E3F9DBB9DE8EB1F7FEDF834B37B9C93F7
-:10107000CE37CD20E3DD6BE2D63C83562FE83697A2
-:10108000444A9A2BA8CB68FE93FC98279AF0A9EEC5
-:1010900054FC6159F067B79E3322DFA3BCF1C3E073
-:1010A00038827E3E0CF2DBD7C3F79BDA5AEC9336DC
-:1010B0006077BFF36783F007F9E99B7BC2843FE861
-:1010C000BB57F313EA33139F7A3B46B25D00DF8CC4
-:1010D000A8C7754C68027CCE2CF9D87B88E22659CB
-:1010E000C711EAB481739EEBB890053B1B7ADEDA38
-:1010F000972FB07C54B73FF299C2E79F75CE98F511
-:10110000CDE73FB2FB4216F877CED4330DF956AF98
-:10111000B9270B7CA87D45DAF37F940E7A7FC5064C
-:101120003A08E979AD62653929542F72DDA0F7B824
-:10113000AC1BD476EC627BDADF29EB377586EEA246
-:1011400078D43B567CD0057BD69F20F328DADF0588
-:10115000BA4D1FA7F941635FD25CB26B2F5E950752
-:1011600099FF9D85FE8EC73EBE6AD80191152E104F
-:10117000579C873E53FFC2D5C9EB21E767BD23A625
-:10118000C03EBE99F5B75AAEF7BD1A6E5739EEA1FB
-:10119000DE20FE5D3D875715AE41F58070E10A9A6D
-:1011A000576776FC80E3E313AA405C573751EA9314
-:1011B0007859EA53CDBA23E684A0FD76429F186F92
-:1011C000192FCE7EF56FAC975B66BA3AA197E1B066
-:1011D00085D82F21DAAB28DA3CE27FAD864344A7DD
-:1011E00096F717AB3C5ED7AE8A91589310E94DA3A2
-:1011F00073148BAD46C4D3B3856F3AEA36C2D8F3C5
-:10120000CB5B687CCEABEAD44D82F3A745259C57D7
-:10121000BA5357213E32281A5D7DD97383FD599EFA
-:10122000F453D35585FD58DFC8708E5366CDAF2972
-:1012300005BEFABCAC61721EEDC37196F0F665CDC9
-:10124000857EFAFBB2E6450ECCBBEBD5F015EC176C
-:10125000852FFBAEA0EF84E5CBFAE8E7E447202733
-:10126000759764BDA350FDEA09C4E7AB0E93BC209B
-:101270003E3424BF6B801D273A83AF1788AF2EF80A
-:101280001FB770B9A03F934678A13F75FB15614425
-:101290009DA8C3D2843A52ADA9270EF2BCB1FD4F2E
-:1012A00066C8735DDB3B66C724AC9775275248B6AA
-:1012B000E3759AFFAA691FFF2EEA7C35C7A517AD13
-:1012C00031BEC3F97BD5C156CED3AB859FF3F4EACB
-:1012D00096C1F2D29FE0E0BA48A87E84E53B06E9D9
-:1012E000C5ACED522FEE52C50AD839A1D569672594
-:1012F000C4733C32B04EC6BB2EF5C2C3885F022910
-:101300008A53A1AD02619E75888B3CE9329E09FC2F
-:10131000EE85EC656C57BCD977D0B9025ABC3B6BF3
-:10132000C336A31A84CFAC4E59970C8489F243CCB0
-:101330006FF768F041B84A22F27358AFB2605703B2
-:101340000659470D3D47BD562F3A817A52E600DED9
-:10135000731213A51D135E969F2E83FCBECB40E334
-:101360005306D62FC997EB07F2215907BB9E5DD9CB
-:101370004DFC2923FEEC253EA37D9EFC7119D999D5
-:1013800016F2C780FF95FC315A5F7D06F7BF58EF14
-:1013900064F860FD4D0C1FAA7731DC5E5FCCEDCBAD
-:1013A000F525DC7F02A87E17FF7BBA11F2D0051D60
-:1013B0001B35009F8A0981470D9E7F2A46190C8F95
-:1013C00052787E76FED38D1ED48B66DA35FD764458
-:1013D00022FE3A6B9375A8B33659876A1DE5BE2580
-:1013E0009FC6CB66ADDD2DF350573AE615C42CE011
-:1013F000FCB59FF257D8A395F9EE3CF0E5F8F1FC67
-:10140000D46D6C276D5C073D75F70DD15C077C834F
-:10141000F271FA746EC6D475D904E746282CBF64FD
-:101420002F6E2CD1F34ADA27BF53DEA314AAD56559
-:10143000D87FD548DB54D8DFCF5DEEDB80874EEF19
-:10144000A251CB53110F75991CEFA28EEBF9BD4938
-:10145000209FD2EB7DFABC0E57EEDD58372B63DCB4
-:10146000BA29B03BA464B0732EB368015E2E43B8B2
-:10147000B296ED96C3083B70B726C7790E1917FBD5
-:10148000CD0E630CEA3761B9B11E5AD7A5F1F9B890
-:10149000C6E7131A9FDF429D8CDAB7A91F6D37F597
-:1014A000A39D01FA4A7965BA3D915752C6F22BFACB
-:1014B0009200EB75C1D9D02F696F9220D75B34F9B8
-:1014C0004DD0EC4D576E49955CE7E37DAAB47ADBCD
-:1014D00005ED1E443FAFBE6E60BDE076DE8DC2639B
-:1014E000859D7F49E69D6234C52304CF7B299EED0F
-:1014F000906ABD23F363D2F37953651E200E58E43E
-:10150000BC04470EF464AD566FEDF51A3C26D4A723
-:1015100063BAD363E07F35FDD2E143FFADB2BDAE28
-:10152000994230B5AF28F27C35F3BAD38761BD62FA
-:1015300033707DBB498E9FD4F4AF2645DB4F3B8F84
-:10154000B0FA92C08FC0E197929610BC29C2BF4CEE
-:10155000DA7D7F3ADB6BE14F9F07BBA8F8DE174EC1
-:101560008A2B0BA62E318E043D7C3B015717E42CB1
-:1015700031DE8CF1D6F7EDC1E3237C498A1D70B6CC
-:101580001C1FD1BA7398330836BDF83EC6CD869C71
-:10159000250504CFB1788FD7436E7E2BE5CBB6BF40
-:1015A000ED0CE856D521E3F6BCFD6D175F845F6E48
-:1015B0008B74C2BCEFCB4F667AAFEDD8B305F2D6D1
-:1015C000DB2AEF0336B5FC69E7CF799E05D724B453
-:1015D000AF2F5BD077561EFDE362E03527DCF705C1
-:1015E000E0878ECE643CE70C977AFDC8D1BC25D04D
-:1015F000D3DEB6FD3F81FECD89A68016F8BC60E340
-:101600003A44E5810905D0D3DEC8EE85D8BFF67926
-:101610008B13725A79203E0FF58143F9B21E5E3169
-:10162000716B12FCACE1E57DBB7F8EFBD5E76D7C79
-:101630002F541723E3BC4AB571DA4AE6DFAEDD4F1B
-:1016400003EF7D36BE9FAD40AD8AE08ADD695CC7A1
-:101650007FE5EB8F16820F85EA8EDDE8FFE2399B8E
-:10166000017438697645CF801E9E3471BE59A1C180
-:1016700015A7864B7CC27B8A987FB15B93E0672B72
-:1016800087FFF476E03D47DDBA13F98ED863E1BBFE
-:101690008973FB886EB4EE5CB3690AB8DCBB2FD2E9
-:1016A0000879B9A06C5DF814F66F96F32ED8B632AF
-:1016B0003D3DCDE305BE47F304ECD60565DBA0FE5A
-:1016C00073CD7BB2908F9E7F7E0EE7A5BAFCEAFABF
-:1016D00052F99C65905F644B40F6A852FB5BD83D85
-:1016E0002282FC6D85069E3FF464EF536260FDF933
-:1016F0001693DF4C34AAB08875D698017DA84CBCEF
-:10170000B518E7AB3434A6236EA998DAB3107A7112
-:10171000CE26AC0934EF4DCD6F551E5C3317F1EF7B
-:10172000F5F0B9A2D9A34B09D27F5D6AB77983EFEF
-:101730002543DBF7EA85FDADB401F8DE15168EE131
-:10174000F5FDDE34FBAA91A7D5C648FBF13ECD6F6F
-:10175000213BF6B5E6EF16AD1E3CBF3F3F86BF5FAF
-:101760006BEE4987FFD3F70FE46B7EC3D8930E7BF4
-:1017700015BA6E0EC211D8911714B6239507950F9E
-:1017800054A253A5D5E355411761D6CF69BCA2C871
-:101790007509D334BAD3DA0D05C9FCDDCA169BCB63
-:1017A00046EBAAC27AA210175547F64421DEE97D1E
-:1017B00059154D1ABB62E334FEA4682C0BAA3756A8
-:1017C000F84C2E5BD6107C46FC44F396E36FFAFE91
-:1017D0003305297C9EF2F670FE9EB0F74C839C96F2
-:1017E000EF18BC0EE7B207E95F6FFBAEB8E0BC3C98
-:1017F00045C33BA07CC07A12F8FAC324F0BDD220C6
-:10180000D6E1FEF23CADC1BD26C1C22A61BEF7AC35
-:10181000FC6B4418E4E5FCA56AD6DB5EA587EDDA2F
-:10182000DB0573D92EF59A7AD8AEBD7EF42EB60FAD
-:10183000BDC37A16C24EBD5DB05C8E8FEC59E8A078
-:10184000F1FD3A3C46B0DF7FEF680DDB8F39AA7CB3
-:1018500057217699ECB21EB4E1543DE71726477044
-:10186000FE7DBA40ABF70CF087F32E5D6F7A85638F
-:10187000FF41E8617904D775288E6A7911F1DE821B
-:101880003827DE6B94639D940373F07D636CCCE525
-:1018900065E0CF1DA3DD450539B8DFECE13C82A44E
-:1018A0009AFD4DEDEF2C9C4F064C7DBB61A7D247B6
-:1018B000BB6717101ED5E6EEF5D984D245534F17F6
-:1018C0004AE4B355698FC41E2957BD99BBE43D8DC9
-:1018D000765F79B7467F41494C23E44291FC7DBD58
-:1018E000FDC05BB02BBDDDE3D81E87EACDB9F6C7DE
-:1018F000A2601FFE4C7EDC1394EFFF79F11EBE67E1
-:101900009D8FF720D42E5937581EFABFBA83F33E65
-:10191000B125A81F72D830180E9523C8A37F90DD7B
-:10192000F130DDB76B7A5595D75D0B3A5C85E711E1
-:10193000AC06C1AF85C021F345898C13B6C3FF1334
-:101940003DAAC7F84F719EBEDF2460C7D792FF62E1
-:10195000B82DDC8B7CC5B09FFC53ACF44FF00B551D
-:1019600051DD5C9FEA6DB3F07DEF431D9F24E1FCE8
-:1019700024875C87A9EA78290EF9FB3E2D5F203F7A
-:1019800018C7EF63DA3AE29077E8FDD5065F3AF0E0
-:10199000A28888E375BDBF46F5A703FF2AA53B0BC8
-:1019A000E3FBF2EDDA7C8255C082CF51AD487D1762
-:1019B0001D2ADBF350BE3DA9C92BD9852C7EDFF152
-:1019C000B2AC0FE876A042B327AFA13F53EABD5DAA
-:1019D000BF57A2A515D0F721EC4342811E17AFE0F7
-:1019E000FACDE3050E096BEB795F595FE2F1DA5747
-:1019F0002E64A564629D362FD80E8D1BB02BD0FFB0
-:101A000004D6FF874C7174AECA9D8A732DEC54E9DD
-:101A10009A229A2E961B571671DD4C78386F0BC59B
-:101A20002B548E2617483A551A8615C606ED779E12
-:101A30006C7AC214B6337ED89D1FC53E5A843AC50F
-:101A40000F4BE5BB81ABFE2658CF719E1DD28E4356
-:101A50006DAE18AE95E3E52B1AD7C70F8147289EC8
-:101A600015EEC6A238C7B5FD3ABEE76D3A7E79A637
-:101A700011C17498BFA66804B5CBADFF2C1DE479E5
-:101A8000CF7758FCF0AB15A52BD7470F2137D7F8E8
-:101A9000831D41FE2B05FCF5F2FDC6F5F00F6DAB85
-:101AA00015FF29D48B04E95533EB17E94B905FB848
-:101AB000B920A4EE50BE782CE26AE15E3C167E8628
-:101AC000F46AA17388FC920CE42803BF19F1701B1F
-:101AD0008ACF5F0AE4BBA49B0BA49E6F99E90AC05E
-:101AE0006ECE500D1C8787EEF765818C27BAE322F6
-:101AF000EFD7DF7380D9335449B74443FFDBD0B706
-:101B0000C4B84807EE830AF3C3E5BCC3363BEA37E3
-:101B100081C397B9BE1B783862BEBC378810236971
-:101B2000BC2B615253B01FF975A13C6F78B68C5B2A
-:101B3000EA324C7FBF3E941979B53EC47143663892
-:101B4000DF97F4B67FCE7E2BD09963C7BD466F3743
-:101B50006587A44F755FFF571CFC6B6FE75FF81D2F
-:101B60005AEF579FF0FBB48DDAFBC0D7DAB5F75DBB
-:101B7000DD8E48F4078A3F2AC2BC4D5A3B5027905D
-:101B8000F562BDD5F35FBD1E1094078F2E1C3A0F72
-:101B90008E714704D7091CF143D55582EB04A9691E
-:101BA000B24E801675825493AC1300469D002DEA08
-:101BB00004E8479D0030EA04805127008C3A015A1E
-:101BC000D409D0FFC57CF95E2640422CEB97116CFE
-:101BD000DFEF6B56BD88CFEF3B2CEFA1EE6B54F8D7
-:101BE0009DD645FA3EFCDC35EF750E6AEF757CDB61
-:101BF000F85EAFAE4D75825575A6BE63A8EBD4B541
-:101C00002ACE35B02FF5F3F9FB1B3B73DE2D457F54
-:101C1000B3C96970804F97E250AFAAEC6CE6FA53F3
-:101C200041FC6133F3B74511A897DE6591796E8D5C
-:101C30004ABD53F83E94E3E01A4B37E71F557B1536
-:101C40007B59F07DEE4D9FB11D586B8B6A029E351E
-:101C50003E9BBD6C88F71F7C2FEC1057EF9B97C9FC
-:101C600029A226A288EF9B97E19E995AA17E65E45E
-:101C7000FB634A4C87431EF1AE2A0366DD2EF53E18
-:101C8000E43D556567EBFA4471ED3D342A03E07F8E
-:101C9000E8FDB3BB3032F64C380C85988CB8A9F807
-:101CA000F1B2FD6DF4BDFEAD168E3B56E6BB97431B
-:101CB0008E8E995C5C273976D8C6F9D1C7DBC60F02
-:101CC000AA937CEE725717F2FDFC68AE5BAC32292A
-:101CD000EC97F38BC7C5F3BB81E326F63F1DAE92AD
-:101CE0005ACC5B35C9C1F5A9428BB89FF7D1DE69E3
-:101CF00051CBFA54B856F11A085E2C9C66E8CF22F4
-:101D0000221BCB8B296203DE532D12F27D832E37EB
-:101D1000ABB6291C1770A1200EF79292BE8B3AFF2A
-:101D2000ED32DE2F2CB5C8F835D120EFB31337C90B
-:101D3000F72D3F126E33FCED72F28B68C94FFEAE89
-:101D400087FADDE1A393647CEE88C7FE8B4F98F899
-:101D5000BD6F61FCF7D3DDECAF0BF81D83E2BF472D
-:101D6000BD72C3F5F527F41DC33193B42F4447CE9C
-:101D70008BBA20975C9F71737BA2BE9CDB1933A545
-:101D80009DBEFA2E91786407FEE17DEF235F4C8CB7
-:101D90008F74C2DEE97A7FCDFBC430D9EAEF13C776
-:101DA000502B82DE276E713978FF44C3C9A90ED04B
-:101DB000E3AF114ED0437FA7B86566C92EF0C915B1
-:101DC000253CF82EEE51B6125D8B701005756E9F96
-:101DD0004B45DDFAB062E777D1D7D8C96D0FE31D67
-:101DE0004F5DAA62571CA8876F2D8C23BC8B529223
-:101DF00019EFBA76592F650AC5A19EAEE983CBDDEE
-:101E0000563862A07F8EA617BD345FCAC92D5EC842
-:101E1000DBB7A8A33E87F91E6173366BF91AF83E4B
-:101E2000E786315C4FD5E5A6BF25BE0972F346A112
-:101E3000F433A5A5EF98100774E5BA8FE2FC0BCB3D
-:101E40003E7B388ECF37741D8BEC28DF4B86D6B1A6
-:101E500074BBBC5BAB83C37E1AB53AAB51ABB31A50
-:101E6000B53AAB51ABB31AB53AAB51ABB31AB53ABD
-:101E7000AB51ABB31AB53AAB91EB772BB87DBB7EC8
-:101E800035B7DDF51E1E0FB2FFEF5DC7FE87D641E9
-:101E90003FC2BCD03AA8B03AA2D98F927ECBFA7397
-:101EA00048DDB378F8920D44BFFC06B3135D7A1D8C
-:101EB00014EF97EF8B607B70B170C8FAA74EB7082C
-:101EC000AE97F60BDB14D03F2F639CD140E37FD558
-:101ED000F8A0D71FA11F381FF4032DF4C39836A014
-:101EE0001FCF984985B3A5BFF7B0BFB7315FD7AF54
-:101EF00021FB41F052611F643F2E86D80F4A3CEE11
-:101F0000061ECB3AE5BB26FDFD661E355F4E19C2A7
-:101F10009EF8A43D1913E6DB87EF8CA90DE3F7C10A
-:101F2000C7B4F758C736CA777165A284BF3B845DD2
-:101F300089023F960EEF7BFF699ABF747304C72D29
-:101F4000EB472E9BF6BFB12B9F150AA6DB6FEAFD70
-:101F5000951F132E056152FE0ACC2203F735C210DD
-:101F6000C67A50A86E51703FBAEA5E31197C2EB025
-:101F700094EC009EF1DAFDB688D5EAADC6EE8A3D56
-:101F8000049F8C4B74E25E6B74C22181F74F8575A0
-:101F9000C599B08BFE31EE09453978BFBC55C1FA01
-:101FA000F04C79FE3B8AC39B205781C3E373C0EF9B
-:101FB0007916471BEA00CEA284A5C8F3E7453B7219
-:101FC000500770768D9270BCA34D7122944D585A73
-:101FD000C0EFCFAC5B3FB6E2DD9A22A2E95C96612E
-:101FE000EE1C7CA7A6F85399378B3EF6633717C9CA
-:101FF000FC6BC46BC28F7BABBE59917C7F26321DBC
-:102000003918A7B8F2BB45241F7FFC9EEB16AC4FD6
-:10201000D4F08CC72DA20AAE76DBD09ED0EEF3BAF8
-:102020000CEE52B445511E23F71BBCD968DF34F8BF
-:102030007E8C7E92E722EC57F4D8E4891904275A63
-:102040007C6C273B5CAE5BB1FFAB335DC5180FAD5D
-:102050009F83B7C8F3099FDB302FF41D96CECFA521
-:102060004552EECB8AA4FD98BE56DEC786F2BDACC3
-:10207000C8A0D9B7BF8F37E15B8AEFE9F88BAD8B8A
-:10208000B3810FE17B2FF0247C17625C44C470BDE8
-:10209000E3FA72E6E1EF951549F9227B56F5B1B402
-:1020A00067DCA61BBDC3103F8EFA857718F01DD5DF
-:1020B000D867C3BFC378D6D367837F7FF6C13E1B83
-:1020C000FA9F75C977D2A1FB3716C9F713E9D3FB7D
-:1020D00078FD58FA5637C7E97DC31047A5977FBCEE
-:1020E0005EDEBB64B07F19ABF997B1BF4869EF21E1
-:1020F000791BFB6434DF6F8B82581EAFB44A3DAD51
-:10210000FC45D9A1366AC76F277C83E2AF095EC25E
-:102110007B505C64EC97EF2D09069DF69A1886CCEF
-:1021200022BEAA11F2BDE528CD6E206E2B25BB5034
-:10213000537EF432BF03C07AEC8F3B5BC85FBB4970
-:10214000C2E4AE918F2E9FBFA68BF3C3ED57FBB5B4
-:102150007CB3753DF2678ADF06F557961DE982BFAD
-:10216000A9DA3BB8BF66C5679CC752FC36A8FFDE3C
-:102170001F7FC0EF6CEADA07F7137F9F029F75FE9F
-:102180001E33F92620DF3B5613E694FF7EC0B712BC
-:10219000FADE541DC1EF6777FD3A8FE546E737ADAC
-:1021A0006FFA76F2B196E77BF24406F4E19BDA5ED1
-:1021B000D8A7B441F6C9C375BED9916C77EAB4FC0F
-:1021C000AAB6CCCE7E3EB1D6CAF6AB500D7302AEE7
-:1021D000354A3B238A55CD4EF958FF4FDE3E8CEBF6
-:1021E000797C00C03193F8DD71DC5A09F78DB0B00D
-:1021F0007D28349454EFA1F6A86105DB8104BCB8B6
-:1022000024BE3F03FBA0427F655DB5CEEC53E4FDE9
-:10221000BE2307F9AE7EDFD4B0D1DB7A10F9B2E28B
-:102220007D7219EA8A7746F0FD4100F5463A4FC3C0
-:102230003069471B16A4B31F088892D2958843E6DD
-:102240008771FDB16198E351DC2736544CE438FACC
-:10225000D07F4BBFDB37D7EA441CD530D9B106EF6E
-:10226000551A7EE1E0F15714B99FE751499F86B9AD
-:10227000F2FC0D15319CF7E87C6868748DC4FDD4C0
-:10228000CC31EEFF00DF4769F7730DC9D44FED1372
-:102290004AC9821F619F4912DF19331DAC77C716E7
-:1022A0004C7C74B783DD891FF74475B32307E5C5FC
-:1022B000FF033C759D8B10370000000000000000FC
-:0822C00005020D000000000002
-:00000001FF
diff --git a/firmware/bnx2x/bnx2x-e1-6.0.34.0.fw.ihex b/firmware/bnx2x/bnx2x-e1-6.0.34.0.fw.ihex
new file mode 100644
index 0000000..33b584c
--- /dev/null
+++ b/firmware/bnx2x/bnx2x-e1-6.0.34.0.fw.ihex
@@ -0,0 +1,9476 @@
+:1000000000003BB0000000680000070C00003C202E
+:1000100000001AF8000043300000007C00005E3051
+:10002000000079E800005EB0000000B40000D8A035
+:100030000000800C0000D9580000008800015968B9
+:10004000000039C4000159F800000090000193C07D
+:100050000000ABA80001945800000FFC000240080B
+:100060000000000400025008020400480000000FD5
+:100070000204005400000045020400580000000083
+:100080000204005C0000000602040070000000048E
+:1000900002040078000000000204007C1217000037
+:1000A00002040080221700000204008432170000BE
+:1000B00006040088000000050204009C12150000E0
+:1000C000020400A022150000020400A43215000062
+:1000D000060400A800000004020400B8021000009A
+:1000E000020400BC00100000020400C01010000058
+:1000F000020400C420100000020400C830100000F8
+:10010000060400CC00000004020400DC0010000023
+:10011000020400E012140000020400E422140000B3
+:10012000020400E832140000060400EC00000004A1
+:100130000104012400000000010401280000000067
+:100140000104012C00000000010401300000000047
+:1001500002040004000000FF02040008000000FF89
+:100160000204000C000000FF02040010000000FF69
+:1001700002040014000000FF02040018000000FF49
+:100180000204001C000000FF02040020000000FF29
+:10019000020400240000003E0204002800000000C9
+:1001A0000204002C0000003F020400300000003F69
+:1001B000020400340000003F020400380000000088
+:1001C0000204003C0000003F020400400000003F29
+:1001D000020400440000003F020420080000021155
+:1001E0000204200C0000020002042010000002049F
+:1001F00002042014000002190204201C0000FFFF6A
+:10020000020420200000FFFF020420240000FFFF62
+:10021000020420280000FFFF0604203800000080B0
+:100220000204223807FFFFFF0204223C0000003FC7
+:100230000204224007FFFFFF020422440000000FD7
+:1002400001042248000000000104224C00000000CC
+:1002500001042250000000000104225400000000AC
+:1002600001042258000000000104225C000000008C
+:10027000010422600000000001042264000000006C
+:1002800001042268000000000104226C000000004C
+:10029000010422700000000001042274000000002C
+:1002A00001042278000000000104227C000000000C
+:1002B000020424BC000000010C042000000003E83C
+:1002C0000A042000000000010B0420000000000AC6
+:1002D0000605400000000D0002050044000000205B
+:1002E00002050048000000320205009002150020BF
+:1002F000020500940215002002050098000000305D
+:100300000205009C08100000020500A00000003358
+:10031000020500A400000030020500A80000003122
+:10032000020500AC00000002020500B0000000055C
+:10033000020500B400000006020500B8000000023B
+:10034000020500BC00000002020500C00000000021
+:10035000020500C400000005020500C800000002FC
+:10036000020500CC00000002020500D000000002DF
+:10037000020500D400000001020501140000000184
+:100380000205011C0000000102050120000000021E
+:1003900002050204000000010205020C00000040FA
+:1003A00002050210000000400205021C00000020AF
+:1003B00002050220000000130205022400000020B4
+:1003C000060502400000000A04050280002000002B
+:1003D000020500500000000702050054000000075D
+:1003E00002050058000000000205005C0000000843
+:1003F0000605006000000004020500D800000006A9
+:10040000020500E00000000D020500E40000002DE0
+:10041000020500E800000000020500EC00000020DA
+:10042000020500F000000000020500F400000020BA
+:10043000020500F800000000020500FC000000209A
+:100440000205000400000001020500080000000190
+:100450000205000C00000001020500100000000170
+:100460000205001400000001020500180000000150
+:100470000205001C00000001020500200000000130
+:100480000205002400000001020500280000000110
+:100490000205002C000000010205003000000001F0
+:1004A00002050034000000010205003800000001D0
+:1004B0000205003C000000010205004000000001B0
+:1004C0000406100002000020020600DC000000010B
+:1004D000010600D80000000004060200000302200C
+:1004E000020600DC0000000002060068000000B800
+:1004F0000206007800000114010600B800000000A8
+:10050000010600C8000000000206006C000000B8F0
+:100510000206007C00000114010600BC000000007F
+:10052000010600CC0000000007180400007B00005A
+:100530000818076000140223071C00002A1E000090
+:10054000071C800031E60A88071D00001DDD170228
+:10055000081D4470577202250118000000000000B9
+:10056000011800040000000001180008000000004D
+:100570000118000C0000000001180010000000002D
+:100580000118001400000000021800200000000103
+:1005900002180024000000020218002800000003D6
+:1005A0000218002C000000000218003000000004B7
+:1005B000021800340000000102180038000000009A
+:1005C0000218003C00000001021800400000000476
+:1005D000021800440000000002180048000000015A
+:1005E0000218004C00000003021800500000000038
+:1005F0000218005400000001021800580000000416
+:100600000218005C000000000218006000000001F9
+:1006100002180064000000030218006800000000D7
+:100620000218006C000000010218007000000004B5
+:100630000218007400000000021800780000000496
+:100640000218007C00000003061800800000000271
+:10065000021800A400003FFF021800A8000003FFDA
+:1006600002180224000000000218023400000000FA
+:100670000218024C00000000021802E4000000FF13
+:100680000618100000000400021B8BC000000001CF
+:10069000021B800000000034021B80400000001894
+:1006A000021B80800000000C021B80C000000020A4
+:1006B0000C1B83000007A1200A1B830000000138E7
+:1006C0000B1B8300000013880A1B834000000000FE
+:1006D0000C1B8340000001F40B1B8340000000054D
+:1006E000021B83800007A120021B83C0000001F4CD
+:1006F000061A100000000273041A19CC0001022728
+:10070000061A2008000000C8061A20000000000297
+:10071000041A499800040228061A2E280000000234
+:10072000061A2E2000000002061A0800000000022F
+:10073000061A080800000004061A08180000000243
+:10074000041A08B00002022C061A2FD0000000067E
+:10075000041A2FE80002022E041A2FC000040230EF
+:10076000041A300000010234061A300400000003AD
+:10077000041A301000010235061A3014000000037C
+:10078000041A302000010236061A3024000000034B
+:10079000041A303000010237061A3034000000031A
+:1007A000041A304000010238061A304400000003E9
+:1007B000041A305000010239061A305400000003B8
+:1007C000041A30600001023A061A30640000000387
+:1007D000041A30700001023B061A30740000000356
+:1007E000041A30800001023C061A30840000000325
+:1007F000041A30900001023D061A309400000003F4
+:10080000041A30A00001023E061A30A400000003C2
+:10081000041A30B00001023F061A30B40000000391
+:10082000041A30C000010240061A30C40000000360
+:10083000041A30D000010241061A30D4000000032F
+:10084000041A30E000010242061A30E400000003FE
+:10085000041A30F000010243061A30F400000003CD
+:10086000041A310000010244061A3104000000039A
+:10087000041A311000010245061A31140000000369
+:10088000041A312000010246061A31240000000338
+:10089000041A313000010247061A31340000000307
+:1008A000041A314000010248061A314400000003D6
+:1008B000041A315000010249061A315400000003A5
+:1008C000041A31600001024A061A31640000000374
+:1008D000041A31700001024B061A31740000000343
+:1008E000041A31800001024C061A31840000000312
+:1008F000041A31900001024D061A319400000003E1
+:10090000041A31A00001024E061A31A400000003AF
+:10091000041A31B00001024F061A31B4000000037E
+:10092000041A31C000010250061A31C4000000034D
+:10093000041A31D000010251061A31D4000000031C
+:10094000041A31E000010252061A31E400000003EB
+:10095000041A31F000010253061A31F400000003BA
+:10096000041A320000010254061A32040000000387
+:10097000041A321000010255061A32140000000356
+:10098000041A322000010256061A32240000000325
+:10099000041A323000010257061A323400000003F4
+:1009A000041A324000010258061A324400000003C3
+:1009B000041A325000010259061A32540000000392
+:1009C000041A32600001025A061A32640000000361
+:1009D000041A32700001025B061A32740000000330
+:1009E000041A32800001025C061A328400000003FF
+:1009F000041A32900001025D061A329400000003CE
+:100A0000041A32A00001025E061A32A4000000039C
+:100A1000041A32B00001025F061A32B4000000036B
+:100A2000041A32C000010260061A32C4000000033A
+:100A3000041A32D000010261061A32D40000000309
+:100A4000041A32E000010262061A32E400000003D8
+:100A5000041A32F000010263061A32F400000003A7
+:100A6000041A330000010264061A33040000000374
+:100A7000041A331000010265061A33140000000343
+:100A8000041A332000010266061A33240000000312
+:100A9000041A333000010267061A333400000003E1
+:100AA000041A334000010268061A334400000003B0
+:100AB000041A335000010269061A3354000000037F
+:100AC000041A33600001026A061A3364000000034E
+:100AD000041A33700001026B061A3374000000031D
+:100AE000041A33800001026C061A338400000003EC
+:100AF000041A33900001026D061A339400000003BB
+:100B0000041A33A00001026E061A33A40000000389
+:100B1000041A33B00001026F061A33B40000000358
+:100B2000041A33C000010270061A33C40000000327
+:100B3000041A33D000010271061A33D400000003F6
+:100B4000041A33E000010272061A33E400000003C5
+:100B5000041A33F000010273061A33F40000000394
+:100B6000041A340000010274061A34040000000361
+:100B7000041A341000010275061A34140000000330
+:100B8000041A342000010276061A342400000003FF
+:100B9000041A343000010277061A343400000003CE
+:100BA000041A344000010278061A3444000000039D
+:100BB000041A345000010279061A3454000000036C
+:100BC000041A34600001027A061A3464000000033B
+:100BD000041A34700001027B061A3474000000030A
+:100BE000041A34800001027C061A348400000003D9
+:100BF000041A34900001027D061A349400000003A8
+:100C0000041A34A00001027E061A34A40000000376
+:100C1000041A34B00001027F061A34B40000000345
+:100C2000041A34C000010280061A34C40000000314
+:100C3000041A34D000010281061A34D400000003E3
+:100C4000041A34E000010282061A34E400000003B2
+:100C5000041A34F000010283061A34F40000000381
+:100C6000041A350000010284061A3504000000034E
+:100C7000041A351000010285061A3514000000031D
+:100C8000041A352000010286061A352400000003EC
+:100C9000041A353000010287061A353400000003BB
+:100CA000041A354000010288061A3544000000038A
+:100CB000041A355000010289061A35540000000359
+:100CC000041A35600001028A061A35640000000328
+:100CD000041A35700001028B061A357400000003F7
+:100CE000041A35800001028C061A358400000003C6
+:100CF000041A35900001028D061A35940000000395
+:100D0000041A35A00001028E061A35A40000000363
+:100D1000041A35B00001028F061A35B40000000332
+:100D2000041A35C000010290061A35C40000000301
+:100D3000041A35D000010291061A35D400000003D0
+:100D4000041A35E000010292061A35E4000000039F
+:100D5000041A35F000010293061A35F4000000036E
+:100D6000041A360000010294061A3604000000033B
+:100D7000041A361000010295061A3614000000030A
+:100D8000041A362000010296061A362400000003D9
+:100D9000041A363000010297061A363400000003A8
+:100DA000041A364000010298061A36440000000377
+:100DB000041A365000010299061A36540000000346
+:100DC000041A36600001029A061A36640000000315
+:100DD000041A36700001029B061A367400000003E4
+:100DE000041A36800001029C061A368400000003B3
+:100DF000041A36900001029D061A36940000000382
+:100E0000041A36A00001029E061A36A40000000350
+:100E1000041A36B00001029F061A36B4000000031F
+:100E2000041A36C0000102A0061A36C400000003EE
+:100E3000041A36D0000102A1061A36D400000003BD
+:100E4000041A36E0000102A2061A36E4000000038C
+:100E5000041A36F0000102A3061A36F4000000035B
+:100E6000041A3700000102A4061A37040000000328
+:100E7000041A3710000102A5061A371400000003F7
+:100E8000041A3720000102A6061A372400000003C6
+:100E9000041A3730000102A7061A37340000000395
+:100EA000041A3740000102A8061A37440000000364
+:100EB000041A3750000102A9061A37540000000333
+:100EC000041A3760000102AA061A37640000000302
+:100ED000041A3770000102AB061A377400000003D1
+:100EE000041A3780000102AC061A378400000003A0
+:100EF000041A3790000102AD061A3794000000036F
+:100F0000041A37A0000102AE061A37A4000000033D
+:100F1000041A37B0000102AF061A37B4000000030C
+:100F2000041A37C0000102B0061A37C400000003DB
+:100F3000041A37D0000102B1061A37D400000003AA
+:100F4000041A37E0000102B2061A37E40000000379
+:100F5000041A37F0000102B3061A37F40000000348
+:100F6000041A3800000102B4061A38040000000315
+:100F7000041A3810000102B5061A381400000003E4
+:100F8000041A3820000102B6061A382400000003B3
+:100F9000041A3830000102B7061A38340000000382
+:100FA000041A3840000102B8061A38440000000351
+:100FB000041A3850000102B9061A38540000000320
+:100FC000041A3860000102BA061A386400000003EF
+:100FD000041A3870000102BB061A387400000003BE
+:100FE000041A3880000102BC061A3884000000038D
+:100FF000041A3890000102BD061A3894000000035C
+:10100000041A38A0000102BE061A38A4000000032A
+:10101000041A38B0000102BF061A38B400000003F9
+:10102000041A38C0000102C0061A38C400000003C8
+:10103000041A38D0000102C1061A38D40000000397
+:10104000041A38E0000102C2061A38E40000000366
+:10105000041A38F0000102C3061A38F40000000335
+:10106000041A3900000102C4061A39040000000302
+:10107000041A3910000102C5061A391400000003D1
+:10108000041A3920000102C6061A392400000003A0
+:10109000041A3930000102C7061A3934000000036F
+:1010A000041A3940000102C8061A3944000000033E
+:1010B000041A3950000102C9061A3954000000030D
+:1010C000041A3960000102CA061A396400000003DC
+:1010D000041A3970000102CB061A397400000003AB
+:1010E000041A3980000102CC061A3984000000037A
+:1010F000041A3990000102CD061A39940000000349
+:10110000041A39A0000102CE061A39A40000000317
+:10111000041A39B0000102CF061A39B400000003E6
+:10112000041A39C0000102D0061A39C400000003B5
+:10113000041A39D0000102D1061A39D40000000384
+:10114000041A39E0000102D2061A39E40000000353
+:10115000041A39F0000102D3061A39F40000000322
+:10116000041A3A00000102D4061A3A0400000003EF
+:10117000041A3A10000102D5061A3A1400000003BE
+:10118000041A3A20000102D6061A3A24000000038D
+:10119000041A3A30000102D7061A3A34000000035C
+:1011A000041A3A40000102D8061A3A44000000032B
+:1011B000041A3A50000102D9061A3A5400000003FA
+:1011C000041A3A60000102DA061A3A6400000003C9
+:1011D000041A3A70000102DB061A3A740000000398
+:1011E000041A3A80000102DC061A3A840000000367
+:1011F000041A3A90000102DD061A3A940000000336
+:10120000041A3AA0000102DE061A3AA40000000304
+:10121000041A3AB0000102DF061A3AB400000003D3
+:10122000041A3AC0000102E0061A3AC400000003A2
+:10123000041A3AD0000102E1061A3AD40000000371
+:10124000041A3AE0000102E2061A3AE40000000340
+:10125000041A3AF0000102E3061A3AF4000000030F
+:10126000041A3B00000102E4061A3B0400000003DC
+:10127000041A3B10000102E5061A3B1400000003AB
+:10128000041A3B20000102E6061A3B24000000037A
+:10129000041A3B30000102E7061A3B340000000349
+:1012A000041A3B40000102E8061A3B440000000318
+:1012B000041A3B50000102E9061A3B5400000003E7
+:1012C000041A3B60000102EA061A3B6400000003B6
+:1012D000041A3B70000102EB061A3B740000000385
+:1012E000041A3B80000102EC061A3B840000000354
+:1012F000041A3B90000102ED061A3B940000000323
+:10130000041A3BA0000102EE061A3BA400000003F1
+:10131000041A3BB0000102EF061A3BB400000003C0
+:10132000041A3BC0000102F0061A3BC4000000038F
+:10133000041A3BD0000102F1061A3BD4000000035E
+:10134000041A3BE0000102F2061A3BE4000000032D
+:10135000041A3BF0000102F3061A3BF400000003FC
+:10136000041A3C00000102F4061A3C0400000003C9
+:10137000041A3C10000102F5061A3C140000000398
+:10138000041A3C20000102F6061A3C240000000367
+:10139000041A3C30000102F7061A3C340000000336
+:1013A000041A3C40000102F8061A3C440000000305
+:1013B000041A3C50000102F9061A3C5400000003D4
+:1013C000041A3C60000102FA061A3C6400000003A3
+:1013D000041A3C70000102FB061A3C740000000372
+:1013E000041A3C80000102FC061A3C840000000341
+:1013F000041A3C90000102FD061A3C940000000310
+:10140000041A3CA0000102FE061A3CA400000003DE
+:10141000041A3CB0000102FF061A3CB400000003AD
+:10142000041A3CC000010300061A3CC4000000037B
+:10143000041A3CD000010301061A3CD4000000034A
+:10144000041A3CE000010302061A3CE40000000319
+:10145000041A3CF000010303061A3CF400000003E8
+:10146000041A3D0000010304061A3D0400000003B5
+:10147000041A3D1000010305061A3D140000000384
+:10148000041A3D2000010306061A3D240000000353
+:10149000041A3D3000010307061A3D340000000322
+:1014A000041A3D4000010308061A3D4400000003F1
+:1014B000041A3D5000010309061A3D5400000003C0
+:1014C000041A3D600001030A061A3D64000000038F
+:1014D000041A3D700001030B061A3D74000000035E
+:1014E000041A3D800001030C061A3D84000000032D
+:1014F000041A3D900001030D061A3D9400000003FC
+:10150000041A3DA00001030E061A3DA400000003CA
+:10151000041A3DB00001030F061A3DB40000000399
+:10152000041A3DC000010310061A3DC40000000368
+:10153000041A3DD000010311061A3DD40000000337
+:10154000041A3DE000010312061A3DE40000000306
+:10155000041A3DF000010313061A3DF400000003D5
+:10156000041A3E0000010314061A3E0400000003A2
+:10157000041A3E1000010315061A3E140000000371
+:10158000041A3E2000010316061A3E240000000340
+:10159000041A3E3000010317061A3E34000000030F
+:1015A000041A3E4000010318061A3E4400000003DE
+:1015B000041A3E5000010319061A3E5400000003AD
+:1015C000041A3E600001031A061A3E64000000037C
+:1015D000041A3E700001031B061A3E74000000034B
+:1015E000041A3E800001031C061A3E84000000031A
+:1015F000041A3E900001031D061A3E9400000003E9
+:10160000041A3EA00001031E061A3EA400000003B7
+:10161000041A3EB00001031F061A3EB40000000386
+:10162000041A3EC000010320061A3EC40000000355
+:10163000041A3ED000010321061A3ED40000000324
+:10164000041A3EE000010322061A3EE400000003F3
+:10165000041A3EF000010323061A3EF400000003C2
+:10166000041A3F0000010324061A3F04000000038F
+:10167000041A3F1000010325061A3F14000000035E
+:10168000041A3F2000010326061A3F24000000032D
+:10169000041A3F3000010327061A3F3400000003FC
+:1016A000041A3F4000010328061A3F4400000003CB
+:1016B000041A3F5000010329061A3F54000000039A
+:1016C000041A3F600001032A061A3F640000000369
+:1016D000041A3F700001032B061A3F740000000338
+:1016E000041A3F800001032C061A3F840000000307
+:1016F000041A3F900001032D061A3F9400000003D6
+:10170000041A3FA00001032E061A3FA400000003A4
+:10171000041A3FB00001032F061A3FB40000000373
+:10172000041A3FC000010330061A3FC40000000342
+:10173000041A3FD000010331061A3FD40000000311
+:10174000041A3FE000010332061A3FE400000007DC
+:10175000041A4CB000080333061A400000000124AC
+:10176000021A492000000000061A2500000000109F
+:10177000061A258000000012061A09C00000004861
+:10178000061A080000000002061A082000000012D5
+:10179000041A2FB00002033B041A4CF00002033D70
+:1017A000061A500000000004061A449000000124AC
+:1017B000021A492400000000061A2540000000100B
+:1017C000061A25C800000012061A0AE000000048A8
+:1017D000061A081000000002061A0868000000122D
+:1017E000041A2FB80002033F041A4CF80002034108
+:1017F000061A5010000000040200A468000AFFDC72
+:101800000200A280000000010200A294071D29111D
+:101810000200A298000000000200A29C009C042488
+:101820000200A2A0000000000200A2A40000020921
+:101830000200A4FCFF000000020100B4000000014F
+:10184000020100B800000001020100DC00000001FC
+:10185000020101000000000102010104000000017A
+:101860000201007C0030000002010084000000281A
+:101870000201008C000000000201013000000004A1
+:101880000201025C000000010201032800000000C8
+:101890000201055400000030020100C400000001F4
+:1018A000020100CC00000001020100F8000000016C
+:1018B000020100F000000001020100800030000081
+:1018C00002010088000000280201009000000000D2
+:1018D0000201013400000004020102DC00000001EA
+:1018E0000201032C0000000002010564000000302A
+:1018F000020100C800000001020100D00000000148
+:10190000020100FC00000001020100F400000001DF
+:10191000020C100000000028020C200800000A1130
+:10192000020C200C00000A00020C201000000A0427
+:10193000020C201C0000FFFF020C20200000FFFF13
+:10194000020C20240000FFFF020C20280000FFFFF3
+:10195000020C203800000020020C203C0000002176
+:10196000020C204000000022020C20440000002352
+:10197000020C204800000024020C204C000000252E
+:10198000020C205000000026020C2054000000270A
+:10199000020C205800000028020C205C00000029E6
+:1019A000020C20600000002A020C20640000002BC2
+:1019B000020C20680000002C020C206C0000002D9E
+:1019C000020C20700000002E020C20740000002F7A
+:1019D000020C207800000010060C207C0000004F54
+:1019E000020C21B800000001020C21BC0000000123
+:1019F000020C21C000000001020C21C40000000103
+:101A0000020C21C800000001020C21CC00000001E2
+:101A1000020C21D000000001020C21D400000001C2
+:101A2000020C21D800000001020C21DC00000001A2
+:101A3000020C21E000000001020C21E40000000182
+:101A4000020C21E800000001020C21EC0000000162
+:101A5000020C21F000000001020C21F40000000142
+:101A6000020C21F800000001060C21FC0000000F10
+:101A7000020C223807FFFFFF020C223C0000003F4F
+:101A8000020C224007FFFFFF020C22440000000F5F
+:101A9000010C224800000000010C224C0000000054
+:101AA000010C225000000000010C22540000000034
+:101AB000010C225800000000010C225C0000000014
+:101AC000010C226000000000010C226400000000F4
+:101AD000010C226800000000010C226C00000000D4
+:101AE000010C227000000000010C227400000000B4
+:101AF000010C227800000000010C227C0000000094
+:101B0000020C24BC000000010C0C2000000003E8C3
+:101B10000A0C2000000000010B0C20000000000A4D
+:101B2000020C400800000562020C400C0000055148
+:101B3000020C401000000555020C40140000057214
+:101B4000020C401C0000FFFF020C40200000FFFFC1
+:101B5000020C40240000FFFF020C40280000FFFFA1
+:101B6000020C403800000046020C403C0000000C13
+:101B7000060C40400000005E020C41B8000000016D
+:101B8000060C41BC0000001F020C423807FFFFFF9B
+:101B9000020C423C0000003F020C424007FFFFFFE6
+:101BA000020C42440000000F010C424800000000FB
+:101BB000010C424C00000000010C425000000000EB
+:101BC000010C425400000000010C425800000000CB
+:101BD000010C425C00000000010C426000000000AB
+:101BE000010C426400000000010C4268000000008B
+:101BF000010C426C00000000010C4270000000006B
+:101C0000010C427400000000010C4278000000004A
+:101C1000010C427C00000000010C4280000000002A
+:101C2000020C44C0000000010C0C4000000003E85E
+:101C30000A0C4000000000010B0C40000000000AEC
+:101C4000060D400000000A00020D004400000032B2
+:101C5000020D008C02150020020D009002150020DC
+:101C6000020D009408100000020D009800000033DF
+:101C7000020D009C00000002020D00A00000000008
+:101C8000020D00A400000005020D00A800000005E0
+:101C9000060D00AC00000002020D00B400000002BE
+:101CA000020D00B800000003020D00BC000000029D
+:101CB000020D00C000000001020D00C8000000027B
+:101CC000020D00CC00000002020D015C00000001CA
+:101CD000020D016400000001020D01680000000215
+:101CE000020D020400000001020D020C00000020A1
+:101CF000020D021000000040020D0214000000401E
+:101D0000020D022000000003020D02240000001852
+:101D1000060D028000000012040D030000180343AA
+:101D2000060D03600000000C020D004C00000001D5
+:101D3000020D005000000002020D005400000000DF
+:101D4000020D005800000008060D005C00000004B1
+:101D5000020D00C400000004020D0114000000097F
+:101D6000020D011800000029020D011C0000000AEC
+:101D7000020D01200000002A020D012400000000D5
+:101D8000020D012800000020020D012C00000000BF
+:101D9000020D013000000020020D0134000000009F
+:101DA000020D013800000020020D013C000000007F
+:101DB000020D014000000020020D0144000000005F
+:101DC000020D014800000020020D00040000000187
+:101DD000020D000800000001020D000C00000001CF
+:101DE000020D001000000001020D001400000001AF
+:101DF000020D001800000001020D001C000000018F
+:101E0000020D002000000001020D0024000000016E
+:101E1000020D002800000001020D002C000000014E
+:101E2000020D003000000001020D0034000000012E
+:101E3000020D003800000001020D003C000000010E
+:101E4000060E200000000800020E004C00000032C8
+:101E5000020E009402150020020E009802150020C8
+:101E6000020E009C00000030020E00A008100000CE
+:101E7000020E00A400000033020E00A80000003093
+:101E8000020E00AC00000031020E00B000000002A3
+:101E9000020E00B400000004020E00B800000000B2
+:101EA000020E00BC00000002020E00C00000000292
+:101EB000020E00C400000000020E00C80000000274
+:101EC000020E00CC00000007020E00D0000000024D
+:101ED000020E00D400000002020E00D80000000133
+:101EE000020E014400000001020E014C000000013E
+:101EF000020E015000000002020E02040000000168
+:101F0000020E020C00000040020E02100000004011
+:101F1000020E021C00000004020E0220000000203D
+:101F2000020E02240000000E020E02280000001B18
+:101F3000060E030000000012040E0280001B035B6B
+:101F4000060E02EC00000005020E00540000000C1A
+:101F5000020E00580000000C020E005C00000000A1
+:101F6000020E006000000010060E00640000000475
+:101F7000020E00DC00000003020E01100000000F42
+:101F8000020E01140000002F020E011800000000D4
+:101F9000020E011C00000020020E000400000001DF
+:101FA000020E000800000001020E000C00000001FB
+:101FB000020E001000000001020E001400000001DB
+:101FC000020E001800000001020E001C00000001BB
+:101FD000020E002000000001020E0024000000019B
+:101FE000020E002800000001020E002C000000017B
+:101FF000020E003000000001020E0034000000015B
+:10200000020E003800000001020E003C000000013A
+:10201000020E004000000001020E0044000000011A
+:102020000730040000B00000083007680013037692
+:1020300007340000332700000734800032520CCAF6
+:10204000073500001A8C195F083539A058CC037881
+:10205000013000000000000001300004000000001A
+:1020600001300008000000000130000C00000000FA
+:1020700001300010000000000130001400000000DA
+:1020800002300020000000010230002400000002A5
+:1020900002300028000000030230002C0000000085
+:1020A0000230003000000004023000340000000163
+:1020B00002300038000000000230003C0000000147
+:1020C0000230004000000004023000440000000024
+:1020D00002300048000000010230004C0000000304
+:1020E00002300050000000000230005400000001E7
+:1020F00002300058000000040230005C00000000C4
+:1021000002300060000000010230006400000003A3
+:1021100002300068000000000230006C0000000186
+:102120000230007000000004023000740000000063
+:1021300002300078000000040230007C0000000340
+:102140000630008000000002023000A400003FFFC3
+:10215000023000A8000003FF02300224000000004B
+:1021600002300234000000000230024C0000000087
+:10217000023002E40000FFFF0630200000000800EB
+:1021800002338BC000000001023380000000001AFF
+:10219000023380400000004E0233808000000010B7
+:1021A000023380C0000000200C3383000007A12010
+:1021B0000A338300000001380B33830000001388CA
+:1021C0000A338340000000000C338340000001F418
+:1021D0000B33834000000005023383800007A120F9
+:1021E000023383C0000001F406322A88000000C2D6
+:1021F00006322008000000C806322000000000025D
+:10220000063223E80000004004322E580004037A0E
+:10221000063250A000000004063250B80000000250
+:102220000632508000000006043250980002037EFF
+:10223000063250000000002006323000000004008A
+:1022400006321C0000000004043218300002038033
+:10225000063224E8000000B402322DB00000000075
+:1022600006324000000000B40632300000000020BA
+:10227000063231000000002006323200000000204B
+:102280000632330000000020063234000000002037
+:102290000632350000000020063236000000002023
+:1022A000063237000000002006323800000000200F
+:1022B000063239000000002006323A0000000020FB
+:1022C00006323B000000002006323C0000000020E7
+:1022D00006323D000000002006323E0000000020D3
+:1022E00006323F000000002006321C1000000002F1
+:1022F000063245A000000024063227B8000000B4D2
+:1023000002322DB400000000063242D0000000B4BA
+:1023100006323080000000200632318000000020AC
+:102320000632328000000020063233800000002098
+:102330000632348000000020063235800000002084
+:102340000632368000000020063237800000002070
+:10235000063238800000002006323980000000205C
+:1023600006323A800000002006323B800000002048
+:1023700006323C800000002006323D800000002034
+:1023800006323E800000002006323F800000002020
+:1023900006321C20000000020632463000000024F5
+:1023A0000720040000870000082007800010038237
+:1023B0000724000031A500000724800008190C6ADA
+:1023C00008248EB06C9003840120000000000000FF
+:1023D00001200004000000000120000800000000AF
+:1023E0000120000C0000000001200010000000008F
+:1023F0000120001400000000022000200000000165
+:102400000220002400000002022000280000000337
+:102410000220002C00000000022000300000000418
+:1024200002200034000000010220003800000000FB
+:102430000220003C000000010220004000000004D7
+:1024400002200044000000000220004800000001BB
+:102450000220004C00000003022000500000000099
+:102460000220005400000001022000580000000477
+:102470000220005C0000000002200060000000015B
+:102480000220006400000003022000680000000039
+:102490000220006C00000001022000700000000417
+:1024A00002200074000000000220007800000004F8
+:1024B0000220007C000000030620008000000002D3
+:1024C000022000A400003FFF022000A8000003FF3C
+:1024D000022002240000000002200234000000005C
+:1024E0000220024C00000000022002E40000FFFF76
+:1024F000062020000000080002238BC0000000011D
+:10250000022380000000001002238040000000121F
+:102510000223808000000030022380C00000000EF3
+:102520000C2383000007A1200A2383000000013848
+:102530000B238300000013880A238340000000005F
+:102540000C238340000001F40B23834000000005AE
+:10255000022383800007A120022383C0000001F42E
+:10256000062250000000004206222008000000C899
+:10257000062220000000000206224000000000C6E3
+:1025800004224318000503860622432C0000000B9A
+:10259000042243580005038B0622436C0000000B05
+:1025A0000422439800050390062243AC0000000B70
+:1025B000042243D800050395062243EC0000000BDB
+:1025C000042244180005039A0622442C0000000B44
+:1025D000042244580005039F0622446C0000000BAF
+:1025E00004224498000503A4062244AC0000000B1A
+:1025F000042244D8000503A9062244EC0000000B85
+:1026000004224518000503AE0622452C0000000BED
+:1026100004224558000503B30622456C0000000B58
+:1026200004224598000503B8062245AC0000000BC3
+:10263000042245D8000503BD062245EC0000000B2E
+:1026400004224618000503C20622462C0000000B97
+:1026500004224658000503C70622466C0000000B02
+:1026600004224698000503CC062246AC0000000B6D
+:10267000042246D8000503D1062246EC0000000BD8
+:1026800004224718000503D60622472C0000000B41
+:1026900004224758000503DB0622476C0000000BAC
+:1026A00004224798000503E0062247AC0000000B17
+:1026B000042247D8000503E5062247EC0000000B82
+:1026C00004224818000503EA0622482C0000000BEB
+:1026D00004224858000503EF0622486C0000000B56
+:1026E00004224898000503F4062248AC0000000BC1
+:1026F000042248D8000503F9062248EC0000000B2C
+:1027000004224918000503FE0622492C0000000B94
+:1027100004224958000504030622496C0000000BFE
+:102720000422499800050408062249AC0000000B69
+:10273000042249D80005040D062249EC0000000BD4
+:1027400004224A180005041206224A2C0000000B3D
+:1027500004224A580005041706224A6C0000000BA8
+:1027600004224A980005041C06224AAC0000000B13
+:1027700004224AD80005042106224AEC0000000584
+:1027800006224B000000001704224B5C00010426C7
+:1027900006224B600000000304224B6C000104275A
+:1027A000062238000000004006223000000002002F
+:1027B000042251C00004042806221000000000C0BA
+:1027C000062215C00000024004221EC80008042C86
+:1027D0000622390000000008022251180000000003
+:1027E000062251D00000000606221300000000025D
+:1027F00006221410000000300622392000000008D4
+:102800000222511C00000000062251E800000006D0
+:102810000622130800000002062214D00000003037
+:102820000216100000000028021700080000000235
+:102830000217002C000000030217003C00000004F7
+:1028400002170044000000000217004800000002C8
+:102850000217004C0000009002170050000000908A
+:102860000217005400800090021700580810000062
+:10287000021700600000008A021700640000008058
+:1028800002170068000000810217006C0000008041
+:10289000021700700000000602170078000007D041
+:1028A0000217007C0000076C02170038007C10043F
+:1028B000021700040000000F06164024000000026A
+:1028C000021640700000001C0216420800000001C1
+:1028D0000216421000000001021642200000000112
+:1028E00002164228000000010216423000000001DA
+:1028F000021642380000000102164260000000018A
+:102900000C16401C0003D0900A16401C0000009CCE
+:102910000B16401C000009C40216403000000008DD
+:10292000021640340000000C02164038000000106F
+:102930000216404400000020021640000000000182
+:10294000021640D8000000010216400800000001F5
+:102950000216400C000000010216401000000001A9
+:10296000021642400000000002164248000000002B
+:1029700006164270000000020216425000000000DD
+:1029800002164258000000000616428000000002B5
+:1029900002166008000006140216600C0000060013
+:1029A00002166010000006040216601C0000FFFF03
+:1029B000021660200000FFFF021660240000FFFFE7
+:1029C000021660280000FFFF021660380000002099
+:1029D0000216603C00000020061660400000000265
+:1029E00002166048000000230216604C000000241C
+:1029F00002166050000000250216605400000026F8
+:102A000002166058000000270216605C00000029D2
+:102A1000021660600000002A021660640000002BAD
+:102A2000021660680000002C0216606C0000002D89
+:102A30000616607000000012021660B80000000167
+:102A4000021660BC00000001061660C00000003ED7
+:102A5000021661B800000001061661BC0000001FEC
+:102A60000216623807FFFFFF0216623C0000003FBB
+:102A70000216624007FFFFFF021662440000000FCB
+:102A800001166248000000000116624C00000000C0
+:102A900001166250000000000116625400000000A0
+:102AA00001166258000000000116625C0000000080
+:102AB0000116626000000000011662640000000060
+:102AC00001166268000000000116626C0000000040
+:102AD0000116627000000000011662740000000020
+:102AE00001166278000000000116627C0000000000
+:102AF000021664BC000000010C166000000003E830
+:102B00000A166000000000010B1660000000000AB9
+:102B100002168040000000060216804400000005F6
+:102B2000021680480000000A0216804C00000005D2
+:102B30000216805400000002021680CC000000043F
+:102B4000021680D000000004021680D400000004A9
+:102B5000021680D800000004021680DC0000000489
+:102B6000021680E000000004021680E40000000469
+:102B7000021680E800000004021688040000000429
+:102B8000021680300000007C021680340000003DF8
+:102B9000021680380000003F0216803C0000009CB6
+:102BA000021680F000000007061680F40000000501
+:102BB0000216880C010101010216810800000000C4
+:102BC0000216810C000000040216811000000004AF
+:102BD0000216811400000002021688100801200469
+:102BE00002168118000000050216811C0000000575
+:102BF0000216812000000005021681240000000555
+:102C00000216882C200810010216812800000008F6
+:102C10000216812C00000006021681300000000719
+:102C200002168134000000000216883001010120E4
+:102C300006168138000000040216883401010101E3
+:102C400006168148000000040216883801010101BF
+:102C500006168158000000040216883C010101019B
+:102C6000061681680000000302168174000000014E
+:102C7000021688400101010102168178000000015E
+:102C80000216817C00000001021681800000000114
+:102C9000021681840000000102168844010101012E
+:102CA00002168188000000010216818C00000004D9
+:102CB00002168190000000040216819400000002B8
+:102CC00002168848080120040216819800000005B9
+:102CD0000216819C00000005021681A0000000057C
+:102CE000021681A4000000050216881420081001B5
+:102CF000021681A800000008021681AC0000000640
+:102D0000021681B000000007021681B40000000125
+:102D10000216881801010120021681B80000000186
+:102D2000021681BC00000001021681C000000001F3
+:102D3000021681C4000000010216881C0101010175
+:102D4000021681C800000001021681CC00000001BB
+:102D5000021681D000000001021681D4000000019B
+:102D60000216882001010101021681D8000000012D
+:102D7000021681DC00000001021681E00000000163
+:102D8000021681E4000000010216882401010101FD
+:102D9000021681E800000001021681EC000000012B
+:102DA000021681F0000000010216882801010101CD
+:102DB00002168240FFFF003F061682440000000218
+:102DC0000216824CFFFF003F0216825000000100F5
+:102DD000021682540000010006168258000000020C
+:102DE00002168260000000C002168264000000C06B
+:102DF0000216826800001E000216826C00001E008F
+:102E0000021682700000400002168274000040002A
+:102E100002168278000080000216827C000080008A
+:102E2000021682800000200002168284000020002A
+:102E30000616828800000007021682A40000000126
+:102E4000061682A80000000A021681F400000C0891
+:102E5000021681F800000040021681FC000001000B
+:102E600002168200000000200216820400000017F3
+:102E700002168208000000800216820C0000020088
+:102E8000021682100000000002168218FFFF01FFE8
+:102E900002168214FFFF01FF0216823C000000139D
+:102EA000021680900000013F021680600000014081
+:102EB00002168064000001400616806800000002CF
+:102EC00002168070000000C0061680740000000723
+:102ED0000216809C00000048021680A000000048F6
+:102EE000061680A400000002021680AC0000004814
+:102EF000061680B00000000702168238000080002D
+:102F000002168234000025E40216809400007FFF40
+:102F100002168220000000070216821C0000000733
+:102F2000021682280000000002168224FFFFFFFF25
+:102F300002168230000000000216822CFFFFFFFF05
+:102F4000021680EC000000FF0214000000000001E7
+:102F50000214000C000000010214004000000001F7
+:102F60000214004400007FFF0214000C0000000067
+:102F700002140000000000000214006C00000000B9
+:102F800002140004000000010214003000000001DF
+:102F900002140004000000000214005C00000000A5
+:102FA00002140008000000010214003400000001B7
+:102FB000021400080000000002140060000000007D
+:102FC00006028000000020000202005800000032CB
+:102FD000020200A003150020020200A40315002035
+:102FE000020200A801000030020200AC081000003C
+:102FF000020200B000000033020200B40000003002
+:10300000020200B800000031020200BC0000000310
+:10301000020200C000000006020200C4000000031B
+:10302000020200C800000003020200CC00000002FF
+:10303000020200D000000000020200D400000002E2
+:10304000020200DC00000000020200E000000006B6
+:10305000020200E400000004020200E80000000296
+:10306000020200EC00000002020200F00000000179
+:10307000020200FC00000006020201200000000025
+:103080000202013400000002020201B0000000014F
+:103090000202020C00000001020202140000000102
+:1030A00002020218000000020202040400000001F3
+:1030B0000202040C00000040020204100000004064
+:1030C0000202041C00000004020204200000002090
+:1030D0000202042400000002020204280000001F73
+:1030E00006020500000000120402048000200434DF
+:1030F000020200600000000F0202006400000007EE
+:1031000002020068000000000202006C0000000ED5
+:103110000602007000000004020200F40000000437
+:103120000202000400000001020200080000000189
+:103130000202000C00000001020200100000000169
+:103140000202001400000001020200180000000149
+:103150000202001C00000001020200200000000129
+:103160000202002400000001020200280000000109
+:103170000202002C000000010202003000000001E9
+:1031800002020034000000010202003800000001C9
+:103190000202003C000000010202004000000001A9
+:1031A0000202004400000001020200480000000189
+:1031B0000202004C00000001020200500000000169
+:1031C00002020108000000C802020118000000020B
+:1031D000020201C400000000020201CC0000000055
+:1031E000020201D400000002020201DC0000000221
+:1031F000020201E4000000FF020201EC000000FFF7
+:103200000202010C000000C80202011C00000002C2
+:10321000020201C800000000020201D0000000000C
+:10322000020201D800000002020201E000000002D8
+:10323000020201E8000000FF020201F0000000FFAE
+:1032400007280400008D00000828076800130454B4
+:10325000072C000033FC0000072C800038B20D0062
+:10326000072D000039171B2D072D800005D9297364
+:10327000082D8A204EBC04560128000000000000E2
+:1032800001280004000000000128000800000000E0
+:103290000128000C000000000128001000000000C0
+:1032A0000128001400000000022800200000000196
+:1032B0000228002400000002022800280000000369
+:1032C0000228002C0000000002280030000000044A
+:1032D000022800340000000102280038000000002D
+:1032E0000228003C00000001022800400000000409
+:1032F00002280044000000000228004800000001ED
+:103300000228004C000000030228005000000000CA
+:1033100002280054000000010228005800000004A8
+:103320000228005C0000000002280060000000018C
+:10333000022800640000000302280068000000006A
+:103340000228006C00000001022800700000000448
+:103350000228007400000000022800780000000429
+:103360000228007C00000003062800800000000204
+:10337000022800A400003FFF022800A8000003FF6D
+:10338000022802240000000002280234000000008D
+:103390000228024C00000000022802E40000FFFFA7
+:1033A0000628200000000800022B8BC0000000014E
+:1033B000022B800000000000022B8040000000185B
+:1033C000022B80800000000C022B80C000000066F1
+:1033D0000C2B83000007A1200A2B8300000001387A
+:1033E0000B2B8300000013880A2B83400000000091
+:1033F0000C2B8340000001F40B2B834000000005E0
+:10340000022B83800007A120022B83C0000001F45F
+:10341000062A3D4800000004042A3D5800020458D2
+:10342000062A3D6000000006062A30000000004821
+:10343000062A2008000000C8062A2000000000021A
+:10344000062A31280000008E062A33680000000397
+:10345000042A33740001045A062A3A780000000254
+:10346000042A3A800002045B042A3A700002045DD8
+:10347000042A3E280002045F042A3EB000040461CE
+:10348000042A250000020465062A25080000010020
+:10349000062A297000000004042A29600004046739
+:1034A000042A2F480002046B062A3378000000D853
+:1034B000022A3A3800000000062A3A88000000324A
+:1034C000042A3D880010046D062A502000000002E6
+:1034D000062A503000000002062A500000000002B8
+:1034E000062A501000000002022A50B80000000115
+:1034F000062A50480000000E042A3D780002047D90
+:10350000062A3C1800000026022A50400000000055
+:10351000062A36D8000000D8022A3A3C00000000F3
+:10352000062A3B5000000032042A3DC80010047FE8
+:10353000062A502800000002062A50380000000227
+:10354000062A500800000002062A50180000000257
+:10355000022A50BC00000001062A50800000000E24
+:10356000042A3D800002048F062A3CB00000002699
+:10357000022A504400000000021010080000000160
+:103580000210101000000264021010000003D000AE
+:10359000021010040000003D091018000200049100
+:1035A00009101100001006910610114000000008DB
+:1035B00009101160000806A1061011800000000229
+:1035C00009101188000606A9061011A000000018B5
+:1035D000021010100000000006102400000000E09F
+:1035E0000210201C0000000002102020000000013A
+:1035F000021020C0000000010210200400000001A1
+:10360000021020080000000109103C00000506AF70
+:1036100009103C20000506B409103800000506B961
+:1036200002104028000000100210404400003FFF3C
+:103630000210405800280000021040840084924A82
+:1036400006104C000000010002104058000000006D
+:103650000610806800000004021080000000108046
+:1036600006108028000000020210803800000010C0
+:10367000021080400000FFFF021080440000FFFFA6
+:1036800002108050000000000210810000000000C5
+:10369000061081200000000202108008000002B520
+:1036A0000210801000000000061082000000004A96
+:1036B000021081080001FFFF061081400000000297
+:1036C0000210800000001A80061090000000002404
+:1036D000061091200000004A061093700000004A76
+:1036E000061095C00000004A0210800400001080FF
+:1036F00006108030000000020210803C0000001024
+:10370000021080480000FFFF0210804C0000FFFF05
+:10371000021080540000000002108104000000002C
+:1037200006108128000000020210800C000002B583
+:103730000210801400000000061084000000004AFF
+:103740000210810C0001FFFF0610814800000002FA
+:103750000210800400001A800610909000000024DF
+:10376000061092480000004A061094980000004A93
+:10377000061096E80000004A0212049000E383401D
+:103780000212051400003C10021205200000000285
+:1037900002120494FFFFFFFF02120498FFFFFFFFD5
+:1037A0000212049CFFFFFFFF021204A0FFFFFFFFB5
+:1037B000021204A4FFFFFFFF021204A8FFFFFFFF95
+:1037C000021204ACFFFFFFFF021204B0FFFFFFFF75
+:1037D000021204B8FFFFFFFF021204BCFFFFFFFF4D
+:1037E000021204C0FFFFFFFF021204C4FFFFFFFF2D
+:1037F000021204C8FFFFFFFF021204CCFFFFFFFF0D
+:10380000021204D0FFFFFFFF021204DCFFFFFFFFE4
+:10381000021204E0FFFFFFFF021204E4FFFFFFFFBC
+:10382000021204E8FFFFFFFF021204ECFFFFFFFF9C
+:10383000021204F0FFFFFFFF021204F4FFFFFFFF7C
+:10384000021204F8FFFFFFFF021204FCFFFFFFFF5C
+:1038500002120500FFFFFFFF02120504FFFFFFFF3A
+:1038600002120508FFFFFFFF0212050CFFFFFFFF1A
+:1038700002120510FFFFFFFF021204D4FFFF3330D6
+:10388000021204D8FFFF3340021204B4F0003000EB
+:1038900002120390000000080212039C00000008BE
+:1038A000061203A000000002021203BC0000000484
+:1038B000021203C400000004021203D00000000042
+:1038C000021203DC000000000212036C0000000181
+:1038D000021203680000003F021201BC0000004019
+:1038E000021201C000001808021201C400000803FF
+:1038F000021201C800000803021201CC00000040BF
+:10390000021201D000000003021201D400000803DB
+:10391000021201D800000803021201DC00000803B3
+:10392000021201E000010003021201E4000008039A
+:10393000021201E800000803021201EC000000037B
+:10394000021201F000000003021201F40000000363
+:10395000021201F800000003021201FC0000000343
+:103960000212020000000003021202040000000321
+:1039700002120208000000030212020C0000000301
+:1039800002120210000000030212021400000003E1
+:1039900002120218000000030212021C00000003C1
+:1039A00002120220000000030212022400000003A1
+:1039B00002120228000024030212022C0000002F31
+:1039C0000212023000000009021202340000001945
+:1039D00002120238000001840212023C000001833E
+:1039E0000212024000000306021202440000001905
+:1039F00002120248000000060212024C00000306F8
+:103A000002120250000003060212025400000306D4
+:103A10000212025800000C860212025C000003062B
+:103A20000212026000000306021202640000000697
+:103A300002120268000000060212026C000000067A
+:103A4000021202700000000602120274000000065A
+:103A500002120278000000060212027C000000063A
+:103A6000021202800000000602120284000000061A
+:103A700002120288000000060212028C00000006FA
+:103A800002120290000000060212029400000006DA
+:103A900002120298000000060212029C00000006BA
+:103AA000021202A000000306021202A4000000138A
+:103AB000021202A800000006021202B00000100468
+:103AC000021202B400001004021203240010644029
+:103AD0000212032800106440021201B0000000012D
+:103AE0000600A000000000160200A06CBF5C0000F1
+:103AF0000200A070FFF51FEF0200A0740000FFFF9E
+:103B00000200A078F00003E00200A07C00000000AA
+:103B10000200A0800000A0000600A08400000005B4
+:103B20000200A0980FE000000600A09C0000001416
+:103B30000200A0EC555400000200A0F05555555568
+:103B40000200A0F4000055550200A0F8F0000000AB
+:103B50000200A0FC555400000200A1005555555527
+:103B60000200A104000055550200A108F000000069
+:103B70000600A22C000000040200A0600000030761
+:103B80000200A10CBF5C00000200A110FFF51FEFB6
+:103B90000200A1140000FFFF0200A118F00003E0E2
+:103BA0000200A11C000000000200A1200000A000F3
+:103BB0000600A124000000050200A1380FE000006B
+:103BC0000600A13C000000140200A18C5554000026
+:103BD0000200A190555555550200A194000055557D
+:103BE0000200A198F00000000200A19C55540000C2
+:103BF0000200A1A0555555550200A1A4000055553D
+:103C00000200A1A8F00000000600A23C0000000491
+:103C10000200A06400000307000000000000000094
+:103C20000000002E00000000000000000000000066
+:103C30000000000000000000000000000000000084
+:103C40000000000000000000000000000000000074
+:103C50000000000000000000000000000000000064
+:103C60000000000000000000000000000000000054
+:103C70000000000000000000002E004D00000000C9
+:103C80000000000000000000000000000000000034
+:103C90000000000000000000000000000000000024
+:103CA00000000000004D008B00000000000000003C
+:103CB0000000000000000000000000000000000004
+:103CC00000000000000000000000000000000000F4
+:103CD000008B009000900094009400980000000079
+:103CE00000000000000000000000000000000000D4
+:103CF000000000000000000000000000009802DE4C
+:103D000002DE02E802E802F200000000000000000B
+:103D100000000000000000000000000000000000A3
+:103D20000000000000000000000000000000000093
+:103D30000000000000000000000000000000000083
+:103D40000000000000000000000000000000000073
+:103D50000000000000000000000000000000000063
+:103D60000000000000000000000000000000000053
+:103D70000000000000000000000000000000000043
+:103D80000000000000000000000000000000000033
+:103D90000000000000000000000000000000000023
+:103DA0000000000000000000000000000000000013
+:103DB0000000000000000000000000000000000003
+:103DC00000000000000000000000000000000000F3
+:103DD000000000000000000002F202FA00000000F3
+:103DE00000000000000000000000000000000000D3
+:103DF00000000000000000000000000000000000C3
+:103E000000000000000000000000000000000000B2
+:103E100000000000000000000000000000000000A2
+:103E20000000000000000000000000000000000092
+:103E300002FA02FF02FF030A030A03150000000052
+:103E40000000000000000000000000000000000072
+:103E50000000000000000000000000000000000062
+:103E60000000000000000000000000000000000052
+:103E70000000000000000000000000000000000042
+:103E80000000000000000000031503160000000001
+:103E90000000000000000000000000000000000022
+:103EA0000000000000000000000000000000000012
+:103EB000000000000316035700000000000000008F
+:103EC00000000000000000000000000000000000F2
+:103ED00000000000000000000000000000000000E2
+:103EE0000357037B000000000000000000000000FA
+:103EF00000000000000000000000000000000000C2
+:103F0000000000000000000000000000037B03BB75
+:103F100000000000000000000000000000000000A1
+:103F20000000000000000000000000000000000091
+:103F3000000000000000000003BB03F700000000C9
+:103F40000000000000000000000000000000000071
+:103F50000000000000000000000000000000000061
+:103F60000000000003F7043D043D045204520467BE
+:103F70000000000000000000000000000000000041
+:103F80000000000000000000000000000000000031
+:103F9000046704ED04ED04F204F204F700000000ED
+:103FA0000000000000000000000000000000000011
+:103FB00000000000000000000000000004F704F80A
+:103FC00000000000000000000000000000000000F1
+:103FD00000000000000000000000000000000000E1
+:103FE000000000000000000004F8050A00000000C6
+:103FF00000000000000000000000000000000000C1
+:1040000000000000000000000000000000000000B0
+:1040100000000000050A051F051F052205220525D1
+:104020000000000000000000000000000000000090
+:104030000000000000000000000000000000000080
+:1040400005250555000000000000000000000000EC
+:104050000000000000000000000000000000000060
+:10406000000000000000000000000000055505DC15
+:104070000000000000000000000000000000000040
+:104080000000000000000000000000000000000030
+:10409000000000000000000005DC05E305E305E783
+:1040A00005E705EB00000000000000000000000034
+:1040B0000000000000000000000000000000000000
+:1040C0000000000005EB062B062B06330633063BEB
+:1040D00000000000000000000000000000000000E0
+:1040E00000000000000000000000000000000000D0
+:1040F000063B068806880695069506A20000000085
+:1041000000000000000000000000000000000000AF
+:1041100000000000000000000000000006A206AE43
+:10412000000000000000000000000000000000008F
+:10413000000000000000000000000000000000007F
+:10414000000000000000000006AE06B40000000001
+:10415000000000000000000000000000000000005F
+:10416000000000000000000000000000000000004F
+:104170000000000006B406B70000000000000000C8
+:10418000000000000000000000000000000000002F
+:10419000000000000000000000000000000000001F
+:1041A00006B706BD0000000000000000000000008F
+:1041B00000000000000000000000000000000000FF
+:1041C00000000000000000000000000006BD06BE68
+:1041D00006BE06D006D006E2000000000000000087
+:1041E00000000000000000000000000000000000CF
+:1041F000000000000000000006E2074F0000000081
+:1042000000000000000000000000000000000000AE
+:10421000000000000000000000000000000000009E
+:1042200000000000074F0750075007630763077639
+:10423000000000000000000000000000000000007E
+:10424000000000000000000000000000000000006E
+:10425000000000000000000000000000000000005E
+:10426000000000000000000000000000000000004E
+:10427000000000000000000000000000000000003E
+:10428000000000000000000000000000000000002E
+:10429000000000000000000000000000000000001E
+:1042A000000000000000000000000000000000000E
+:1042B00000000000000000000000000000000000FE
+:1042C00000000000000000000000000000000000EE
+:1042D00000000000000000000000000000000000DE
+:1042E00000000000000000000000000000000000CE
+:1042F00000000000000000000000000000000000BE
+:1043000000000000000000000000000000000000AD
+:10431000000000000000000000000000000000009D
+:10432000000000000000000000000000000000008D
+:1043300000010000000204C00003098000040E40D8
+:1043400000051300000617C000071C80000821406C
+:1043500000092600000A2AC0000B2F80000C344000
+:10436000000D3900000E3DC0000F42800010474094
+:1043700000114C00001250C00013558000145A4028
+:1043800000155F00001663C00017688000186D40BC
+:1043900000197200001A76C0001B7B80001C804050
+:1043A000001D8500001E89C0001F8E800000934004
+:1043B00000002000000040000000600000008000BD
+:1043C0000000A0000000C0000000E00000010000AC
+:1043D0000001200000014000000160000001800099
+:1043E0000001A0000001C0000001E0000002000088
+:1043F0000002200000024000000260000002800075
+:104400000002A0000002C0000002E0000003000063
+:104410000003200000034000000360000003800050
+:104420000003A0000003C0000003E000000400003F
+:10443000000420000004400000046000000480002C
+:104440000004A0000004C0000004E000000500001B
+:104450000005200000054000000560000005800008
+:104460000005A0000005C0000005E00000060000F7
+:1044700000062000000640000006600000068000E4
+:104480000006A0000006C0000006E00000070000D3
+:1044900000072000000740000007600000078000C0
+:1044A0000007A0000007C0000007E00000080000AF
+:1044B000000820000008400000086000000880009C
+:1044C0000008A0000008C0000008E000000900008B
+:1044D0000009200000094000000960000009800078
+:1044E0000009A0000009C0000009E000000A000067
+:1044F000000A2000000A4000000A6000000A800054
+:10450000000AA000000AC000000AE000000B000042
+:10451000000B2000000B4000000B6000000B80002F
+:10452000000BA000000BC000000BE000000C00001E
+:10453000000C2000000C4000000C6000000C80000B
+:10454000000CA000000CC000000CE000000D0000FA
+:10455000000D2000000D4000000D6000000D8000E7
+:10456000000DA000000DC000000DE000000E0000D6
+:10457000000E2000000E4000000E6000000E8000C3
+:10458000000EA000000EC000000EE000000F0000B2
+:10459000000F2000000F4000000F6000000F80009F
+:1045A000000FA000000FC000000FE000001000008E
+:1045B000001020000010400000106000001080007B
+:1045C0000010A0000010C0000010E000001100006A
+:1045D0000011200000114000001160000011800057
+:1045E0000011A0000011C0000011E0000012000046
+:1045F0000012200000124000001260000012800033
+:104600000012A0000012C0000012E0000013000021
+:10461000001320000013400000136000001380000E
+:104620000013A0000013C0000013E00000140000FD
+:1046300000142000001440000014600000148000EA
+:104640000014A0000014C0000014E00000150000D9
+:1046500000152000001540000015600000158000C6
+:104660000015A0000015C0000015E00000160000B5
+:1046700000162000001640000016600000168000A2
+:104680000016A0000016C0000016E0000017000091
+:10469000001720000017400000176000001780007E
+:1046A0000017A0000017C0000017E000001800006D
+:1046B000001820000018400000186000001880005A
+:1046C0000018A0000018C0000018E0000019000049
+:1046D0000019200000194000001960000019800036
+:1046E0000019A0000019C0000019E000001A000025
+:1046F000001A2000001A4000001A6000001A800012
+:10470000001AA000001AC000001AE000001B000000
+:10471000001B2000001B4000001B6000001B8000ED
+:10472000001BA000001BC000001BE000001C0000DC
+:10473000001C2000001C4000001C6000001C8000C9
+:10474000001CA000001CC000001CE000001D0000B8
+:10475000001D2000001D4000001D6000001D8000A5
+:10476000001DA000001DC000001DE000001E000094
+:10477000001E2000001E4000001E6000001E800081
+:10478000001EA000001EC000001EE000001F000070
+:10479000001F2000001F4000001F6000001F80005D
+:1047A000001FA000001FC000001FE000002000004C
+:1047B0000020200000204000002060000020800039
+:1047C0000020A0000020C0000020E0000021000028
+:1047D0000021200000214000002160000021800015
+:1047E0000021A0000021C0000021E0000022000004
+:1047F00000222000002240000022600000228000F1
+:104800000022A0000022C0000022E00000230000DF
+:1048100000232000002340000023600000238000CC
+:104820000023A0000023C0000023E00000240000BB
+:1048300000242000002440000024600000248000A8
+:104840000024A0000024C0000024E0000025000097
+:104850000025200000254000002560000025800084
+:104860000025A0000025C0000025E0000026000073
+:104870000026200000264000002660000026800060
+:104880000026A0000026C0000026E000002700004F
+:10489000002720000027400000276000002780003C
+:1048A0000027A0000027C0000027E000002800002B
+:1048B0000028200000284000002860000028800018
+:1048C0000028A0000028C0000028E0000029000007
+:1048D00000292000002940000029600000298000F4
+:1048E0000029A0000029C0000029E000002A0000E3
+:1048F000002A2000002A4000002A6000002A8000D0
+:10490000002AA000002AC000002AE000002B0000BE
+:10491000002B2000002B4000002B6000002B8000AB
+:10492000002BA000002BC000002BE000002C00009A
+:10493000002C2000002C4000002C6000002C800087
+:10494000002CA000002CC000002CE000002D000076
+:10495000002D2000002D4000002D6000002D800063
+:10496000002DA000002DC000002DE000002E000052
+:10497000002E2000002E4000002E6000002E80003F
+:10498000002EA000002EC000002EE000002F00002E
+:10499000002F2000002F4000002F6000002F80001B
+:1049A000002FA000002FC000002FE000003000000A
+:1049B00000302000003040000030600000308000F7
+:1049C0000030A0000030C0000030E00000310000E6
+:1049D00000312000003140000031600000318000D3
+:1049E0000031A0000031C0000031E00000320000C2
+:1049F00000322000003240000032600000328000AF
+:104A00000032A0000032C0000032E000003300009D
+:104A1000003320000033400000336000003380008A
+:104A20000033A0000033C0000033E0000034000079
+:104A30000034200000344000003460000034800066
+:104A40000034A0000034C0000034E0000035000055
+:104A50000035200000354000003560000035800042
+:104A60000035A0000035C0000035E0000036000031
+:104A7000003620000036400000366000003680001E
+:104A80000036A0000036C0000036E000003700000D
+:104A900000372000003740000037600000378000FA
+:104AA0000037A0000037C0000037E00000380000E9
+:104AB00000382000003840000038600000388000D6
+:104AC0000038A0000038C0000038E00000390000C5
+:104AD00000392000003940000039600000398000B2
+:104AE0000039A0000039C0000039E000003A0000A1
+:104AF000003A2000003A4000003A6000003A80008E
+:104B0000003AA000003AC000003AE000003B00007C
+:104B1000003B2000003B4000003B6000003B800069
+:104B2000003BA000003BC000003BE000003C000058
+:104B3000003C2000003C4000003C6000003C800045
+:104B4000003CA000003CC000003CE000003D000034
+:104B5000003D2000003D4000003D6000003D800021
+:104B6000003DA000003DC000003DE000003E000010
+:104B7000003E2000003E4000003E6000003E8000FD
+:104B8000003EA000003EC000003EE000003F0000EC
+:104B9000003F2000003F4000003F6000003F8000D9
+:104BA000003FA000003FC000003FE000003FE001E8
+:104BB00000000000000001FF0000020000007FF87C
+:104BC00000007FF80000016A0000150000000001ED
+:104BD0000000FF00000000000000FF0000000000D7
+:104BE00000000000140AFF000000000100000000A7
+:104BF00000201001000000000100860000000100FC
+:104C00000000860200008604000086060000860878
+:104C10000000860A0000860C0000860E0000861048
+:104C20000000861200008614000086160000861818
+:104C30000000861A0000861C0000861E00008620E8
+:104C400000008622000086240000862600008628B8
+:104C50000000862A0000862C0000862E0000863088
+:104C60000000863200008634000086360000863858
+:104C70000000863A0000863C0000863E0000864028
+:104C800000008642000086440000864600008648F8
+:104C90000000864A0000864C0000864E00008650C8
+:104CA0000000865200008654000086560000865898
+:104CB0000000865A0000865C0000865E0000866068
+:104CC0000000866200008664000086660000866838
+:104CD0000000866A0000866C0000866E0000867008
+:104CE00000008672000086740000867600008678D8
+:104CF0000000867A0000867C0000867E00008680A8
+:104D00000000868200008684000086860000868877
+:104D10000000868A0000868C0000868E0000869047
+:104D20000000869200008694000086960000869817
+:104D30000000869A0000869C0000869E000086A0E7
+:104D4000000086A2000086A4000086A6000086A8B7
+:104D5000000086AA000086AC000086AE000086B087
+:104D6000000086B2000086B4000086B6000086B857
+:104D7000000086BA000086BC000086BE000086C027
+:104D8000000086C2000086C4000086C6000086C8F7
+:104D9000000086CA000086CC000086CE000086D0C7
+:104DA000000086D2000086D4000086D6000086D897
+:104DB000000086DA000086DC000086DE000086E067
+:104DC000000086E2000086E4000086E6000086E837
+:104DD000000086EA000086EC000086EE000086F007
+:104DE000000086F2000086F4000086F6000086F8D7
+:104DF000000086FA000086FC000086FE00008700A6
+:104E00000000870200008704000087060000870872
+:104E10000000870A0000870C0000870E0000871042
+:104E20000000871200008714000087160000871812
+:104E30000000871A0000871C0000871E00008720E2
+:104E400000008722000087240000872600008728B2
+:104E50000000872A0000872C0000872E0000873082
+:104E60000000873200008734000087360000873852
+:104E70000000873A0000873C0000873E0000874022
+:104E800000008742000087440000874600008748F2
+:104E90000000874A0000874C0000874E00008750C2
+:104EA0000000875200008754000087560000875892
+:104EB0000000875A0000875C0000875E0000876062
+:104EC0000000876200008764000087660000876832
+:104ED0000000876A0000876C0000876E0000877002
+:104EE00000008772000087740000877600008778D2
+:104EF0000000877A0000877C0000877E00008780A2
+:104F00000000878200008784000087860000878871
+:104F10000000878A0000878C0000878E0000879041
+:104F20000000879200008794000087960000879811
+:104F30000000879A0000879C0000879E000087A0E1
+:104F4000000087A2000087A4000087A6000087A8B1
+:104F5000000087AA000087AC000087AE000087B081
+:104F6000000087B2000087B4000087B6000087B851
+:104F7000000087BA000087BC000087BE000087C021
+:104F8000000087C2000087C4000087C6000087C8F1
+:104F9000000087CA000087CC000087CE000087D0C1
+:104FA000000087D2000087D4000087D6000087D891
+:104FB000000087DA000087DC000087DE000087E061
+:104FC000000087E2000087E4000087E6000087E831
+:104FD000000087EA000087EC000087EE000087F001
+:104FE000000087F2000087F4000087F6000087F8D1
+:104FF000000087FA000087FC000087FEFFFFFFFF2C
+:10500000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
+:10501000FFFFFFFFFFFFFFFFFFFFFFFF0000000399
+:1050200000BEBC20000000000000000500000003DE
+:1050300000BEBC20000000000000000500002000B1
+:10504000000040C000006180000082400000A3001A
+:105050000000C3C00000E4800001054000012600FC
+:10506000000146C000016780000188400001A900DE
+:105070000001C9C00001EA8000020B4000022C00C0
+:1050800000024CC000026D8000028E400002AF00A2
+:105090000002CFC00002F08000001140000080003C
+:1050A000000103800001870000020A8000028E00D8
+:1050B00000031180000395000004188000049C0088
+:1050C00000051F800005A300000626800006AA0038
+:1050D00000072D800007B100000834800008B800E8
+:1050E00000093B800009BF00000A4280000AC60098
+:1050F000000B4980000BCD00000C5080000CD40048
+:10510000000D578000005B0000007FF800007FF872
+:1051100000000166000015000000FF000000000014
+:105120000000FF0000000000000019000000000067
+:1051300000000000FFFFFFFF00007FF800007FF885
+:105140000000035F000035000000FF000FFFFFFFBD
+:105150000000FF000FFFFFFF000000FF0000FF0046
+:105160000FFFFFFF0000FF000FFFFFFF000000FF29
+:105170000000FF000FFFFFFF0000FF000FFFFFFF19
+:10518000000000FF0000FF000FFFFFFF0000FF0016
+:105190000FFFFFFF000000FF0000FF000FFFFFFFF9
+:1051A0000000FF000FFFFFFF000000FF0000FF00F6
+:1051B0000FFFFFFF0000FF000FFFFFFF000000FFD9
+:1051C0000000FF000FFFFFFF0000FF000FFFFFFFC9
+:1051D000000000FF0000FF000FFFFFFF0000FF00C6
+:1051E0000FFFFFFF000000FF0000FF000FFFFFFFA9
+:1051F0000000FF000FFFFFFF000000FF0000FF00A6
+:105200000FFFFFFF0000FF000FFFFFFF000000FF88
+:105210000000FF000FFFFFFF0000FF000FFFFFFF78
+:10522000000000FF0000FF000FFFFFFF0000FF0075
+:105230000FFFFFFF000000FF0000FF000FFFFFFF58
+:105240000000FF000FFFFFFF000000FF0000FF0055
+:105250000FFFFFFF0000FF000FFFFFFF000000FF38
+:105260000000FF000FFFFFFF0000FF000FFFFFFF28
+:10527000000000FF0000FF000FFFFFFF0000FF0025
+:105280000FFFFFFF000000FF0000FF000FFFFFFF08
+:105290000000FF000FFFFFFF000000FF0000FF0005
+:1052A0000FFFFFFF0000FF000FFFFFFF000000FFE8
+:1052B0000000FF000FFFFFFF0000FF000FFFFFFFD8
+:1052C000000000FF0000FF000FFFFFFF0000FF00D5
+:1052D0000FFFFFFF000000FF0000FF000FFFFFFFB8
+:1052E0000000FF000FFFFFFF000000FF0000FF00B5
+:1052F0000FFFFFFF0000FF000FFFFFFF000000FF98
+:105300000000FF000FFFFFFF0000FF000FFFFFFF87
+:10531000000000FF0000FF000FFFFFFF0000FF0084
+:105320000FFFFFFF000000FF0000FF000FFFFFFF67
+:105330000000FF000FFFFFFF000000FF0000FF0064
+:105340000FFFFFFF0000FF000FFFFFFF000000FF47
+:105350000000FF000FFFFFFF0000FF000FFFFFFF37
+:10536000000000FF0000FF000FFFFFFF0000FF0034
+:105370000FFFFFFF000000FF0000FF000FFFFFFF17
+:105380000000FF000FFFFFFF000000FF0000FF0014
+:105390000FFFFFFF0000FF000FFFFFFF000000FFF7
+:1053A0000000FF000FFFFFFF0000FF000FFFFFFFE7
+:1053B000000000FF0000FF000FFFFFFF0000FF00E4
+:1053C0000FFFFFFF000000FF000000FF000000FFD4
+:1053D0000000FF00000000000000FF0000000000CF
+:1053E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD
+:1053F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD
+:1054000000001000000020800000310000004180FA
+:1054100000005200000062800000730000008380E2
+:10542000000094000000A4800000B5000000C580CA
+:105430000000D6000000E6800000F70000010780B1
+:105440000001180000012880000139000001498096
+:1054500000015A0000016A8000017B0000018B807E
+:1054600000019C000001AC800001BD000001CD8066
+:105470000001DE000001EE8000000F0000000000CF
+:1054800000007FF800007FF80000021A00003500DD
+:1054900010000000000028AD00010001FFFFFFFF29
+:1054A000FFFFFFFF00220006CCCCCCC17058103C9F
+:1054B000000000000000FF00000000000000FF00EE
+:1054C000000000000000000000000001CCCC020140
+:1054D000CCCCCCCCCCCC0201CCCCCCCC00000000D1
+:1054E000FFFFFFFF0000FFFF000000000000FFFFC4
+:1054F000000000000000FFFF000000000000FFFFB0
+:10550000000000000000FFFF000000000000FFFF9F
+:10551000000000000000FFFF000000000000FFFF8F
+:1055200000000000000E0000011600D60000FFFF82
+:10553000000000000000FFFF000000000000FFFF6F
+:10554000000000000000FFFF000000000000FFFF5F
+:10555000000000000000FFFF000000000000FFFF4F
+:10556000000000000000FFFF0000000000720000CB
+:10557000012300F3FFFFFFF3318FFFFF0C30C30C5B
+:10558000C30C30C3CF3CF300F3CF3CF30000CF3C5F
+:10559000CDCDCDCDFFFFFFF130EFFFFF0C30C30CC1
+:1055A000C30C30C3CF3CF300F3CF3CF30001CF3C3E
+:1055B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C2C
+:1055C000C30C30C3CF3CF300F3CF3CF30002CF3C1D
+:1055D000CDCDCDCDFFFFF4061CBFFFFF0C30C305C2
+:1055E000C30C30C3CF300014F3CF3CF30004CF3CE6
+:1055F000CDCDCDCDFFFFFFF2304FFFFF0C30C30C00
+:10560000C30C30C3CF3CF300F3CF3CF30008CF3CD6
+:10561000CDCDCDCDFFFFFFFA302FFFFF0C30C30CF7
+:10562000C30C30C3CF3CF300F3CF3CF30010CF3CAE
+:10563000CDCDCDCDFFFFFFF731EFFFFF0C30C30C19
+:10564000C30C30C3CF3CF300F3CF3CF30020CF3C7E
+:10565000CDCDCDCDFFFFFFF5302FFFFF0C30C30CBC
+:10566000C30C30C3CF3CF300F3CF3CF30040CF3C3E
+:10567000CDCDCDCDFFFFFFF3318FFFFF0C30C30C3D
+:10568000C30C30C3CF3CF300F3CF3CF30000CF3C5E
+:10569000CDCDCDCDFFFFFFF1310FFFFF0C30C30C9F
+:1056A000C30C30C3CF3CF300F3CF3CF30001CF3C3D
+:1056B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C2B
+:1056C000C30C30C3CF3CF300F3CF3CF30002CF3C1C
+:1056D000CDCDCDCDFFFFF4061CBFFFFF0C30C305C1
+:1056E000C30C30C3CF300014F3CF3CF30004CF3CE5
+:1056F000CDCDCDCDFFFFFFF2304FFFFF0C30C30CFF
+:10570000C30C30C3CF3CF300F3CF3CF30008CF3CD5
+:10571000CDCDCDCDFFFFFFFA302FFFFF0C30C30CF6
+:10572000C30C30C3CF3CF300F3CF3CF30010CF3CAD
+:10573000CDCDCDCDFFFFFFF730EFFFFF0C30C30C19
+:10574000C30C30C3CF3CF300F3CF3CF30020CF3C7D
+:10575000CDCDCDCDFFFFFFF5304FFFFF0C30C30C9B
+:10576000C30C30C3CF3CF300F3CF3CF30040CF3C3D
+:10577000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CF1
+:10578000C30C30C3CF3CF3CCF3CF3CF30000CF3C91
+:10579000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CD1
+:1057A000C30C30C3CF3CF3CCF3CF3CF30001CF3C70
+:1057B000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CB1
+:1057C000C30C30C3CF3CF3CCF3CF3CF30002CF3C4F
+:1057D000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C91
+:1057E000C30C30C3CF3CF3CCF3CF3CF30004CF3C2D
+:1057F000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C71
+:10580000C30C30C3CF3CF3CCF3CF3CF30008CF3C08
+:10581000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C50
+:10582000C30C30C3CF3CF3CCF3CF3CF30010CF3CE0
+:10583000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C30
+:10584000C30C30C3CF3CF3CCF3CF3CF30020CF3CB0
+:10585000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C10
+:10586000C30C30C3CF3CF3CCF3CF3CF30040CF3C70
+:10587000CDCDCDCDFFFFFFF3320FFFFF0C30C30CBA
+:10588000C30C30C3CF3CF300F3CF3CF30000CF3C5C
+:10589000CDCDCDCDFFFFFFF1310FFFFF0C30C30C9D
+:1058A000C30C30C3CF3CF300F3CF3CF30001CF3C3B
+:1058B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C29
+:1058C000C30C30C3CF3CF300F3CF3CF30002CF3C1A
+:1058D000CDCDCDCDFFFFF4061CBFFFFF0C30C305BF
+:1058E000C30C30C3CF300014F3CF3CF30004CF3CE3
+:1058F000CDCDCDCDFFFFFFF2304FFFFF0C30C30CFD
+:10590000C30C30C3CF3CF300F3CF3CF30008CF3CD3
+:10591000CDCDCDCDFFFFFF8A042FFFFF0C30C30C90
+:10592000C30C30C3CF3CC000F3CF3CF30010CF3CDE
+:10593000CDCDCDCDFFFFFF9705CFFFFF0C30C30CC2
+:10594000C30C30C3CF3CC000F3CF3CF30020CF3CAE
+:10595000CDCDCDCDFFFFFFF5310FFFFF0C30C30CD8
+:10596000C30C30C3CF3CF300F3CF3CF30040CF3C3B
+:10597000CDCDCDCDFFFFFFF3300FFFFF0C30C30CBB
+:10598000C30C30C3CF3CF300F3CF3CF30000CF3C5B
+:10599000CDCDCDCDFFFFFFF1300FFFFF0C30C30C9D
+:1059A000C30C30C3CF3CF300F3CF3CF30001CF3C3A
+:1059B000CDCDCDCDFFFFFFF6305FFFFF0C30C30C28
+:1059C000C30C30C3CF3CF300F3CF3CF30002CF3C19
+:1059D000CDCDCDCDFFFFF4061CBFFFFF0C30C305BE
+:1059E000C30C30C3CF300014F3CF3CF30004CF3CE2
+:1059F000CDCDCDCDFFFFFFF2304FFFFF0C30C30CFC
+:105A0000C30C30C3CF3CF300F3CF3CF30008CF3CD2
+:105A1000CDCDCDCDFFFFFFFA302FFFFF0C30C30CF3
+:105A2000C30C30C3CF3CF300F3CF3CF30010CF3CAA
+:105A3000CDCDCDCDFFFFFF97040FFFFF0C30C30C82
+:105A4000C30C30C3CF3CC000F3CF3CF30020CF3CAD
+:105A5000CDCDCDCDFFFFFFF5300FFFFF0C30C30CD8
+:105A6000C30C30C3CF3CF300F3CF3CF30040CF3C3A
+:105A7000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CEE
+:105A8000C30C30C3CF3CF3CCF3CF3CF30000CF3C8E
+:105A9000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CCE
+:105AA000C30C30C3CF3CF3CCF3CF3CF30001CF3C6D
+:105AB000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CAE
+:105AC000C30C30C3CF3CF3CCF3CF3CF30002CF3C4C
+:105AD000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C8E
+:105AE000C30C30C3CF3CF3CCF3CF3CF30004CF3C2A
+:105AF000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C6E
+:105B0000C30C30C3CF3CF3CCF3CF3CF30008CF3C05
+:105B1000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C4D
+:105B2000C30C30C3CF3CF3CCF3CF3CF30010CF3CDD
+:105B3000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C2D
+:105B4000C30C30C3CF3CF3CCF3CF3CF30020CF3CAD
+:105B5000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C0D
+:105B6000C30C30C3CF3CF3CCF3CF3CF30040CF3C6D
+:105B7000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CED
+:105B8000C30C30C3CF3CF3CCF3CF3CF30000CF3C8D
+:105B9000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CCD
+:105BA000C30C30C3CF3CF3CCF3CF3CF30001CF3C6C
+:105BB000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CAD
+:105BC000C30C30C3CF3CF3CCF3CF3CF30002CF3C4B
+:105BD000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C8D
+:105BE000C30C30C3CF3CF3CCF3CF3CF30004CF3C29
+:105BF000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C6D
+:105C0000C30C30C3CF3CF3CCF3CF3CF30008CF3C04
+:105C1000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C4C
+:105C2000C30C30C3CF3CF3CCF3CF3CF30010CF3CDC
+:105C3000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C2C
+:105C4000C30C30C3CF3CF3CCF3CF3CF30020CF3CAC
+:105C5000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C0C
+:105C6000C30C30C3CF3CF3CCF3CF3CF30040CF3C6C
+:105C7000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CEC
+:105C8000C30C30C3CF3CF3CCF3CF3CF30000CF3C8C
+:105C9000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CCC
+:105CA000C30C30C3CF3CF3CCF3CF3CF30001CF3C6B
+:105CB000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CAC
+:105CC000C30C30C3CF3CF3CCF3CF3CF30002CF3C4A
+:105CD000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C8C
+:105CE000C30C30C3CF3CF3CCF3CF3CF30004CF3C28
+:105CF000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C6C
+:105D0000C30C30C3CF3CF3CCF3CF3CF30008CF3C03
+:105D1000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C4B
+:105D2000C30C30C3CF3CF3CCF3CF3CF30010CF3CDB
+:105D3000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C2B
+:105D4000C30C30C3CF3CF3CCF3CF3CF30020CF3CAB
+:105D5000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C0B
+:105D6000C30C30C3CF3CF3CCF3CF3CF30040CF3C6B
+:105D7000CDCDCDCD000C0000000700C00002813069
+:105D8000000B81580002021000010230000F024097
+:105D900000010330000C0000000800C00002814038
+:105DA000000B81680002022000010240000702503F
+:105DB000000202C000100000000801000002818003
+:105DC000000B81A80002026000018280000E829810
+:105DD0000008038000028000000B8028000200E021
+:105DE000000101000000811000000118CCCCCCCCD7
+:105DF000CCCCCCCCCCCCCCCCCCCCCCCC00002000F3
+:105E0000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCD2
+:105E100000002000CCCCCCCCCCCCCCCCCCCCCCCCD2
+:105E2000CCCCCCCC00002000000000000000000022
+:105E30001F8B080000000000000BFB51CFC0F003D7
+:105E40008A5B591918EC39107C7AE0A58C94E95FCB
+:105E5000C3CCC0B019882F00F12E66D2F57F9642D0
+:105E6000B0CF483030BC03E29D620C0C2B2411E211
+:105E7000D1D20C0CFF81FCD350313BA09EDD52945B
+:105E8000B97B140F0E7C471D957F5C15428740C57A
+:105E9000EFA2C99F80CACF5780D0F7D4B19BBB0077
+:105EA0002A0F0001FE3753600300000000000000CD
+:105EB0001F8B080000000000000BED7D0B7454D513
+:105EC000B9F037E735672633939390C704123C83C4
+:105ED00001820618303C54AA93F068E8A53A3C04C5
+:105EE000E447195034822411D39AB6FC7F4EC8E49B
+:105EF0000102C617A52DDA81E2BDD185BDD1466B61
+:105F0000FB6B5710A5B9B5772DA4A8B4451BD06B72
+:105F1000C10237DA72A1FFB2977F7F7BEF939C7348
+:105F20003293876257EF6AC3D2937DCE7E7CFB7B30
+:105F3000EDEF754E141803CA8D0097F0875CD7B942
+:105F40000020BBEF6ADE073556095900154145DFD1
+:105F50004A9EAD17237A7D09B97F85107E0AF0FE2F
+:105F6000B839300940C671790053F17FD300A4CC11
+:105F7000969C988FDC1357A6E3D59CCFBC5648005F
+:105F8000DA547CBE6D5CB2E7BDEB27E49E6E15E88B
+:105F9000CFA53100B5C76F9DFF9AD926FF8D027F2F
+:105FA000D68757935F66C08C4B22C027F98BD23BB4
+:105FB000F5D4F37D54D7A54963012ED42D9FFFDA84
+:105FC000D8FECFD78B50DD5EDCFFFE75A052BC80C3
+:105FD0006A28D1897DFB5E0FD0E9CE0468CEDFCC84
+:105FE000F69B4590752DB9DFF66F9A54D407E77A82
+:105FF00089F49BDA7F3F00069DD79CA7777CA2CBD4
+:1060000036DE39AE773E3E1E24F26F3A00ED42F6A0
+:106010003FCD15BB11EFBBF3171923497BFDFE5292
+:106020008815A786BF975E9F117E735C4A3AF27E01
+:106030009FEC6B6822AC071F2AAD375D47F8E8F785
+:10604000CF89E1CDC847BBC7CF8100B90F8C8F4C3A
+:106050003A9DDED790938C3F52D1E97F8387F29FA0
+:10606000C95F15C2CAF44EF8ECFC7537F2579A8531
+:10607000BFDA170F38DF67E5AFB893BF383ECEB44D
+:10608000B3FDC3AE118C2E9C5E4EFAA4A4CB671D4B
+:10609000D79F9FB6205EDDED8B8D9190849F38BC9D
+:1060A00026BD3E2FBC83F111402BA5334054C4F5CF
+:1060B000FBEEB3ABB7447381409B87711F23F83E5F
+:1060C00046C49AEE13089C7E682D1F1722EDEED56C
+:1060D0000B500EFCC7E79FC66B6371595719E997C0
+:1060E0001ED616CE23576F11B8709F5B70B2EB703F
+:1060F000BE4AA3B418E905B4FD8C7147C4403C40C6
+:10610000042007E06B7C4F00822E91B682BF8E493F
+:10611000B60F053A193E5C97DCFDC7A7DABFD23748
+:106120000E2E85F0FF1B01F737D8385840C6A988D6
+:106130000E83E23BC3314F7A843D37E9E3074B9B43
+:106140003C3F8ABF507CDFF757594F8347549DA887
+:1061500014A550D012D81FB40C89B4BD7388222264
+:10616000678D16EC31047D70BA340294B7FB28C3F6
+:10617000C1427F1F7CA7C145F7135C130F3591798E
+:10618000CF97F8C2943F34F2DFD4FEFB79B00E19FA
+:10619000D9D22EDE0BC8E771C24763C878A3989C9A
+:1061A00087084FE1F39A555FA5B95C9C2F9DFC01D0
+:1061B000BA341DC50C59855C0B858827F0F9F94365
+:1061C00072E071A8FC91B6C0421F183EBD82DC6E21
+:1061D000182A7F7CDEF54CBAF697AB7A4ED71A15A3
+:1061E0007C782E2F4A6A7FA4A6EB2394AEDE4288E9
+:1061F0002492E8E902978BCB8161D337F44AE823F4
+:10620000F692F77E1BBDC4DCE9CBF70C800F31CBD7
+:106210008E0F735E4FADA87F80CA4BD2049C4FC1D6
+:10622000F990CF828F1840CECFF3C8DB041F62EB0A
+:10623000944E6C432150BB8CFC74BA48DB138C2405
+:10624000B68618FF235D4CF8DCBA60C3AF94E5B5A1
+:10625000B561B9E1B2C2EFA955281C0AB511C83C15
+:106260001A9990A042F24127F2ADC9AFC80697AE85
+:10627000C4F6B76C7CD0A24F85647430F915D1CACE
+:10628000F8F55B43D32FCEF596D8E11DF2389FA4E5
+:106290007F683987528F93E043933E048915388194
+:1062A000850F9A6578C93519A0217F29C4C8DD6694
+:1062B0007C44CEB126BCE6211F4ED5E879D9E692C2
+:1062C000104EF35C856026ED37CDA5D3F904B59A61
+:1062D0009EABA22FC2CE57FE3C355C6CFD1CBD357B
+:1062E000A211FCE6426B4420F4914A20DC09A84745
+:1062F00023807C0061C61722B7D3CDF171CECF1EAB
+:10630000384AC713ED6A68F43CB3CBF15C913C2486
+:10631000F36C2982849BD2A955C5B6542401FA0591
+:10632000443FF9F2A6A39EE63FE28230C29F8EE789
+:106330002BF2C72CCEDF2EA2CF089E7D2576F9F654
+:106340003AE45FE2E7713F7D96C29F30AF4EFBEDCE
+:10635000FB2E6EBFA5818FD29B8F075F727BD5B45A
+:10636000DB4CBC660B40F109BF90134F85F8DE484B
+:106370007BE3BB1909DCB751165DDD48F0609C7406
+:10638000851B909E52A4279D3CFFF09F45EA2F65F8
+:106390002FADBD02D7DB5E678C2DB4D883DB25CD56
+:1063A0008B78DE139FAAC62C7AE66688BDE8B2F821
+:1063B0005FA160D3D8C26B28FF9DEC2EC2A3C2455B
+:1063C000F9CFE38B075F47B9E4F77BF1636D8BFD92
+:1063D000DB59B9C0CE4BB8A93442D66D41DD3592F8
+:1063E0003E365C04CE963CD6FE797D4E299E9F2D8E
+:1063F0007ED6FEA4FEFD483DE58B981A25F76A81FE
+:10640000E3A58BE085D25FCF5D3831355D9CFBDF46
+:10641000211DF6E0FE9FF01D993F1ECFCF99421837
+:10642000D1FE44CD116DB5051F2DEEB2B7111FA3DE
+:1064300020E102A45F3C8BCA4F107A7F22D8CEE3C2
+:10644000F2940F8769BFD1D19E52196F2DD75EC5C7
+:106450006B53F0F90C2A4F3047FB90CABFE8BA746F
+:10646000F5D0E53DD57E032E8826B3E7378A9954CB
+:10647000AE022564DF36BD9EAF517EE4F37E0D692A
+:1064800044F6B72783C04484678FDCBA3C9A84BF44
+:106490007FEE1268BF787C5E742DE533761E8CE645
+:1064A000E741E3E2DBC3C80F50A8E7227D242D4675
+:1064B000F5AD84E707E11F398BE915498DB48C27C9
+:1064C000FC1A3A2A8241C6855A33CA54D40F1A504C
+:1064D000FB05D1B96422DB2F9EAF6EC2712897995C
+:1064E000E47AC9B26F087AFBE4750CAEA3D0752EBE
+:1064F00003BDB3846983D37924B497E261968ADEBD
+:10650000979BCEA9C63BE91B7031F9DAD87021629E
+:1065100010FC351D7709222AC5D6424A2F95EBA6D5
+:106520000B724C45BB71CBD704D84BF130B09D12E8
+:1065300077D82992168DB8C8F89115DA5464A15409
+:10654000E3765608E58924F3960B4CEF6FA978A4FF
+:1065500095AABBD7ECFE9EBC3242ED52E2F79523E2
+:106560003DCC719E42C647B08FEC87F49739FF5DF2
+:10657000C85E940E49E4C0BC7E0FE11FDFD71EC584
+:10658000F9CBD9AF5AE4F6D5636C7ED3DEB9903738
+:10659000F0FC267E2E960B7018E1937A3C40E53D88
+:1065A0009BDA61A3391349B5846FC8BA3274D7E353
+:1065B00079B753808AF662BE69D2CFCDE9F3FDFC8C
+:1065C0004F3CD8EF3651A0F08C8AF46C41BD3F6A45
+:1065D0009300E88F548A3ABD9FBBB2FA804CEEB765
+:1065E0003442D8A7E33A6CDE96031E7A5E2A5990AD
+:1065F000F090FE8742399B915EEE3844DCA49FFB0D
+:106600005E2272D82E84844E9ECBB53103E19582F2
+:1066100051746FE060E82EB59BFA2D60E39BA64DA8
+:106620001B55ECD7AC6FEC0AA1DF522851BF45D106
+:10663000AA23945D3F25F830FD0A2217A138740A79
+:106640002554CF277CB483CAE8A67139DA350B3AD2
+:1066500089DCB6647CBD13E133A601954BB403D04D
+:10666000340089D813647CFC4E2DBC15F922CB7004
+:1066700059F97437C4B659F943D2DA297FB4FC45C5
+:106680005C9E4C2FDE2B307C5673BD77414ECC4741
+:10669000BC6EA92772E0EADFFF7A8EFFEF1A8B6EDD
+:1066A0001E4FF5133B7FCCE75D2EDD16AF1C7951F5
+:1066B000A1FB71DA2FF3B8FDD2944FEC178A07587B
+:1066C00080F64A1A277D5318E8737706240C428F08
+:1066D000341E178062667FA8E41FEAB9DCE576BB4A
+:1066E000C5EDB04F52D92DDF7445DBA95E232A09D1
+:1066F000E1DFE56A9D3F0EF19DC7FC46E7BEBBB8F2
+:10670000DF3857DC166A22703D992584DD7A1F3FF9
+:106710001470B978128C1397C83C7BF2059D58C051
+:10672000B0A746A0F6C9799DD9E7F08187F6BF8268
+:10673000C3D2B86911F58B7AF532979B6D75AA4D66
+:10674000BF38AF3EA53596EC5CF273FAA4CD8AD083
+:1067500038872F9CA0E70EEE33993DFE6071993A81
+:10676000909E938A94D5147FF965A725BCCE74FAC0
+:1067700045C9E7755EC16A4F8AA9FB0DF5BA85E088
+:10678000E9A46C9D3FAAE239E121E728CA85274C9C
+:106790008EA4005EB51C84DF130EFBE8B5BBB49C71
+:1067A000DD8F6EC5AB3AABE7F06CEAA74994EE7BA0
+:1067B0005462075AF031490C517CF6E2B750B0ED03
+:1067C0005F95AACB914FD57C01904FD5D8D7BB2EE2
+:1067D000E17C84FE6343C9F848E2FEA99D6FF69010
+:1067E000F30606A0C3E7E58B5F08A69F6CA717FD1D
+:1067F000B1C63D389D7BE9DF2F7EF1B7416F75163D
+:10680000A137E299D09BF9D7DA569433292E50FF5D
+:10681000C7EC77411863A39F74916852E237EF2A5F
+:1068200085A4FAF082A0D0FE443F94882CEEEAC200
+:1068300078E65C71533930B906F4B754E22F50BA98
+:1068400093F550CE9B3FAD5311EF6A4CA1F679976B
+:10685000ABAEB45E1A8E9E6470C16E66978C32CFFA
+:10686000D90D433B672F9043829DB3D5F43C92BA38
+:10687000ABD55202EF15F7B2F3116DB04CD21E4DED
+:10688000CEB7CE501FFF85F83A7271EBE17149CE59
+:10689000A3EFC53F39E046FD950FEC5CAB6D8FA0D3
+:1068A0005EF1E777E2B6F1BC5921127CE5151AA535
+:1068B000B8A591BBE6D17D7C57022A47177061824B
+:1068C0008F9D9B9FA8376611B98B443B0511FD62D4
+:1068D000A07A91D8B9DCAEB3AFFBFD4D4204F1EB29
+:1068E000C910F6A008FAEFED34DC16BD4CD6BD0792
+:1068F000D735CFBFBCC276C0F59D76414A7BE02F2D
+:1069000022F7B3A6D7A3DF950F0CCE873727EAD19E
+:106910004E2C7547EEA7F477F807BDF1251EC75E2C
+:1069200033D314227DD96FC93AF774C9B0159B9F30
+:1069300092DE96F8CE3D780E117DB3869F63774246
+:1069400034800FCF8240E36667E148E01A0B9D1F59
+:106950001215B64E8B7CB2DB12B75DDBCADAA6FE2F
+:10696000B97B97BD7D172CCA9108DEEE7A4C460F95
+:106970000DEE71F8A375A246F9FB6EA86E423C3489
+:10698000CA4C0ED668208D202ED2861F3F311DEDB9
+:10699000FF9D22F36F3E22FCA55BF4CD3A5F42419E
+:1069A0007CBDDF71CDD2EB01C7279A46A2BF9D0106
+:1069B00049CFCD3B5AECF00D06BF135E80CD14DEFF
+:1069C0005470486DAE48327B7A9F69B7727AD5AA07
+:1069D0008149180CB9E06157A30CA87D61BCE74957
+:1069E0003490750E70FB9158429359FEA27A065E60
+:1069F000071B7748D4B93E1FDEB83752ACB741ED1C
+:106A00005690FFAB24A3DC25F4C5A154B93A328AD1
+:106A10006C497EA9B493D8EAD67E2D43EC572E0C50
+:106A2000D0CF09EF694D3584C9FDE1BE1962C75069
+:106A30002E2E08B14AEAFF73B8DD886711AF12A5A0
+:106A4000278D8B84705D5F0BFAD11E5F07B5473CC5
+:106A5000BA64A37795A9078A80C673D28AECCF9DC2
+:106A6000F1923F8866FCBE93CA170D75922D0554AE
+:106A70005FA788F6E14CE94C6F7FB25E25EE6B3282
+:106A8000ED44F54B0DD72F95A03F34AB84CA178D3D
+:106A9000C3D5CC1F63201C35D97A18FD7009C211EB
+:106AA0003A8783AFAA2EBA2061F1ABABA41E05E5ED
+:106AB000A88AE86FEBFD8D4116274EA5B765507586
+:106AC0005F11DAB102C593A891B665DF9FB4BACA67
+:106AD000B91F94BE64007F776390C581D76C199B02
+:106AE000CEE229767D758E9F0F3FDFFF0305FD9770
+:106AF000B3CF9CB809F7B9FEFF8AA09275CFEDF726
+:106B000043273D37120A9E1BEB3AC4A471768006D8
+:106B10009617FF573FA5D7BAE7DD890564FCBA177A
+:106B2000DF9F0404BE739B7B0E8D42FBF919178B0C
+:106B3000771BDD931693FBEB2458154D325FA1C4F0
+:106B4000ECD4333F495B8EF2EB6A3B703B9DB77DE3
+:106B500099ECB69CDFA32499AE4BFA45F0B9F1B499
+:106B60002B3136895F62E619CE3CED62F0BD2453CD
+:106B70003F6F5DDB1E2546E0A86AFB98EA8BD9FFD4
+:106B8000FA6C00F150F59268B3E3AADAC44EF72428
+:106B90007A3D81578C9FBAA6239F707EE9D840E347
+:106BA000A695ED0F7E2C0670BC5D6F11BC843B1169
+:106BB000AFEF88E105D8FED1BF047482AA8F0E3FE3
+:106BC0001540BC9279572BE9189FB7F337CE7F3128
+:106BD000B3FF7C003D348F5BD5BE85ADE7D08B1F06
+:106BE000E12F79FDE3ABFF24D9F3E3D036B4FCED1C
+:106BF000FA67CF3F6990F5CE3CFF87270D02F7BDBE
+:106C0000FFFDC727BF8572F9338F867ABDEA99B732
+:106C10000260E1C3B512D3AFE70A88CB44FA9DFB0B
+:106C2000B53B8106C1B9577E3F5A27FB3DF7DC9F34
+:106C30007374D2BFE695B9B9B8FF9A1766E70E64C8
+:106C4000DF229F26DC56B812747EFD251733165EB0
+:106C5000E657075D0E761C1C8D709E3DE60E635A4E
+:106C6000AE8ADCAB9D8A74DA40CF596C6F22F8ADE6
+:106C7000DCDFFC31EA87FE7836460934A845D4606B
+:106C800010E9FCFE3C4A2FE8A1E7A3B37FD55142AF
+:106C9000C7C9A9E9761E3E5550CF55EDDFC2D67360
+:106CA000D0ED2CFE726D7FBA6D76D0ED3CDCFBFD35
+:106CB0003CCC97778CB0E5077AEDD4DEB878343DDC
+:106CC0003A807E30E57F30BCD2FC09812B2A451EFC
+:106CD00091508E9E4FEBA5EB02A4EBB3E74703E187
+:106CE0008B5372CFED781EF4BCE2D6303EB0EE95F9
+:106CF00077A85C9D7BE14D45A7E718F85CC4AE3CE6
+:106D000007BD3F87D1CEAC643E3E54EDF377BA0366
+:106D10007DF4A94C2C2CD703F4FE097A3FC1F8BDB1
+:106D2000327160892B09BD7E298D61FA3F914DF149
+:106D3000B261DF6F15F0D9E9E89A89743C310FEF41
+:106D4000A7A2A3B97F0DF73FC342CF7D4C4E9DFD57
+:106D50002B893CE279D74BD784EB1D482297E7F685
+:106D6000B8253CEFCEA15D95341FCAEC99E1E64D04
+:106D70000E39E5DACC9B703CA4E60F26DF83ED6F7D
+:106D8000B8F8EB90741B1F99783CF369727D7F9281
+:106D9000EB8B4A30CA475ED9DF0E91206A8C0AF528
+:106DA000C17B061D52C27F679E1169FCA7A9FD2009
+:106DB000D5DB4E3D518971CB24EBFDD15CEFA503B2
+:106DC00093509F9D79F527943F2BF79F50D0BE3F5E
+:106DD000D4F623A5BBB84F1EF03C4858CE83333FB2
+:106DE0003C3089E981E471515A6047E0AC7AD93E80
+:106DF0007FD5FE8F6DF3AF37DAA97D30D83A1F49C2
+:106E00009165B8DF8F0ECBD49FFCA85D4C1A27FE8E
+:106E10000F3C0F2D766DD39BF37E8BF9AD92235EE5
+:106E20001DCFCD8ECD91DCED68AF1D9181E60FA415
+:106E3000C81FDCA4DDF1A657C7BC73C791A5A26E1D
+:106E4000F1437FECC0E78CA3C66C3F996F4637F1E6
+:106E50007FF5FE7A63E671E25759F8A0E6CDF25C61
+:106E6000D4F7E887EAE371BD7010FD5C3130AF9C68
+:106E7000E5A505CD93F4BC66F3C9BE288D4FC99A2C
+:106E800000BA65DE5190A8C73C3AF87CCEBC4354AA
+:106E9000B5E697961F3E802E66D6E297F3709E0069
+:106EA000C4B50FA9FD09E14B03D85FCE3C8389CF60
+:106EB0005EF94B917748D36E0F1E80FEF3F5CFAF8E
+:106EC000C454CCAF34F9D6B4842CF995A660BFFC79
+:106ED0004A4426786871258F478C91CBE6E073E2AF
+:106EE0001DC7923D5F2E333EBF11BAEF5F8D7046D6
+:106EF000599E6696035F5FE2F8FAD964B271A242C6
+:106F00004B41976482DFD94B227199DC9FBBB2E77A
+:106F1000EA5769779EA731C60B97D2868EBFE1E606
+:106F2000E34ADD8B56CBD983E7E352E585FBE030BE
+:106F3000B83F9E69CB4F1C7CF7011AAF97A1BA25C9
+:106F4000648913E5747A208271FE2C9DDA87399D5D
+:106F5000F77C672DC699B3F2C31EE83F8F74F17AB0
+:106F60001ACF30F3F4527E84C6E5254D2F15E93A49
+:106F7000CB2298CF6FD681DA1FCDC181E33553E4A0
+:106F80009881F4942EDE40E715545E5730C47D7E20
+:106F90007B7180E23940F08CF24EFD1FDCDF71170F
+:106FA000CF87771B22E6C34F64D0FC404082228CFF
+:106FB000075C7079C39B43D02F1F9E8A7FB74B8697
+:106FC0004AE3247ABF7CF82ED9124F53311F4E8BDF
+:106FD000F9ECF970D557137C5D47FFC662EF86FA6E
+:106FE000FAF5C99D231F8E73615CC6689E8D764538
+:106FF0007306F0FC38CB8737F37CF8B38DD366A3E8
+:107000009E6DF698CF67B0FE66DBF8F5AB111FAD4D
+:1070100003A1EDD372CF66EC9F350AAA69FD9914DE
+:10702000855B2C7AF0B82CB13A5539F2BC6CAD279F
+:10703000E2FC60E67B0EBEFB7BCA57781D8374279B
+:107040007C8571A99CCED360D5ABE6D5E49F667DE7
+:10705000E0F8AE7C710ACD9398ED40562C1249C2EF
+:107060004757BAD9B963F271200809D4AF8199B1F1
+:10707000EFAC45BE0EFAC26914CE07689DC90E0D6D
+:10708000749AA770EC6387BE91F2EDF92CC2E516F5
+:1070900079E90FFF0D1C7EE61F9FD7781C306840F2
+:1070A0002C097CF2C512BA8F2972E4B7563C665D92
+:1070B00091BCCEF60E85EDA731BA92E5D12BEC79D5
+:1070C0004F4C335BE3A6D35CB153A837CCFCB9A0DB
+:1070D00046797EC330E3EAC1DE78B68EF580F71AD2
+:1070E000A8DFE495ED860BAF592C1F22AAB18FAD16
+:1070F0007C2C69DD4C0E1DF9BDB9E2198A971D8300
+:10710000D06F5B1DCBA76EADD3A8BDBDA52E48DB50
+:10711000CD753ABD36D545E8FDFEFCF4F3E01DC85B
+:10712000473E2FCD270DC6270FD585E97CF1BA99AB
+:107130006C5E97C9EFEE06E4774530E5C74FDB3E5E
+:10714000D1948F2CDADEEE62CFAF514653F931F98C
+:1071500079B0FD8989E994AEC39D3FE57E67F986E4
+:10716000B4DFF44EB6EE50D7713BD6D9314BA57A89
+:107170007947FE20EBB4B27506879FE16BDB81D3C4
+:10718000B45EC04DE4DF43F6E1D62249E5C1949FE9
+:10719000FEF3B8A9DE6ECE62F94FB9D0174165DEB5
+:1071A000ACF37C21916BB47FE4A29C32BC2F87AFFF
+:1071B000A2F5DC72B18FE6E3E4C29C3BB0BDEDC04A
+:1071C00016AD8CEA01819E5FB5D00D58974BC486F1
+:1071D000C663E5C2A2B5D85F43B9247064BA99FF0B
+:1071E00024175E77378E3F30E590DE9085E716E313
+:1071F0003FE8966CFCEF94FB94FA2B68AF5F04E9D0
+:107200004E40BF74DB94BB8AA87CAA967AC62475CC
+:107210007DA63E217A638D62A9E354608E8179D385
+:107220009DB7DE154EE62F91F3749D92DD7F1E73A0
+:107230007C851CDDA0B0BA74B0D7A527CF4737072F
+:10724000CD7C74B58AE7A814ECADA75B9047F0C27B
+:1072500052A9D05B4FE733EBE9C22CDFD54AFE25BC
+:10726000CB4B3BEBC42F573DDD16A5B79EAE00EBD5
+:10727000E97E2A43B813F3EA6F89E1BD7A7FBE73D2
+:10728000CEE77C2FC23C0752C965A762CF87E6C50F
+:10729000ECF950B8D3635BEF359497E2C1F5CBA816
+:1072A0000AFB3C05D5F6FAD72B6A336DED9031D247
+:1072B000D6FFCA9631B6E7635BAFB23D1FBF6BAA7C
+:1072C000AD3D21719DADFFD56D65B6F6C4F6AFD865
+:1072D000FA4F7E6991AD3DA57385ADFF355D6B6C51
+:1072E000CFA71D5E677B3EE3D8465BFBDAEE6FDA25
+:1072F000FAD712F34641B9CDE2F5C259B98235CF7A
+:10730000DA924DCE25E2B7EFC8260C43E3D9ACFEA6
+:107310004A618F7BF380CE7192AE44349AB71F37A7
+:1073200007AF20D5D0F354D273CA747A7FFA3CBC2D
+:107330004289BD0E56D1591D31FA65F67CBFBD1E7E
+:107340005811B7D1B206F7F12F77B926F5A7AB924E
+:107350006F9783A1D613CBBA63DC30E5E28C291793
+:1073600005442E683CED5311FD1E98E3A7F685C534
+:107370003FA27834FDA31B5488A3C968CA45E9CA53
+:107380009E51B48EAFD72F720BC3A95F33E52F6028
+:10739000D1FB91AC3E3DD33C7368FA554C5C63B372
+:1073A0000F9DD786C0BA54FA31E01E403F4E91A3DC
+:1073B000196EF42FA5880196F80B54CB36B8870ABE
+:1073C000E7673D07561386B3EA15134E85E86DCC83
+:1073D0002B352DBE893AF55003363ECD591EA5FEFC
+:1073E00009B10BAF76DBC633FBF06FCD4EFE8D6C73
+:1073F000DFA7692F9B780F84C2B49E04F204407FFC
+:10740000AE69562C88F1B416EC62F10F1F705F491B
+:10741000E7690C2A02D6B93776B1387B835ACDE2B8
+:107420000E72358DBF34640B5AB23AAE3BDD2CBFC1
+:107430002BD63E3876DF007C252AC9E30E0D7C7CF6
+:10744000C3816F74B17352D1D19F06E234BE6FC94C
+:10745000BF8970381A72E13A3BE83A010E57A040F2
+:1074600080FAD0E070DECCFD1DA976CB80704A0892
+:107470006712BA9870C611CE92D470FAB3CB687EF8
+:1074800052AADD46D731F1BACACDE8E584DBC4B7EC
+:107490000C91F2D9D83EF1E5284D8712B223BFEF07
+:1074A00098C9FC66A2D86DFC6AFA2D845FEB915FE7
+:1074B000258DF92FE6FB055F716B0CAF9C8EA067E5
+:1074C000D2B8432016A775E7FE18F3B7FBF40DE317
+:1074D0001BBF1C01EC2FF9049ABF5378BCC2ECF718
+:1074E0009E9BC5891A667547711FCDD74AB019F59D
+:1074F0000FD63763FC2E9FED378EFB22F0FCCC9D20
+:10750000C1F891AFEB8525E9B41052DC1F1C480F80
+:107510007B117F23FAEBE327DDFCBDE03CC863FA77
+:10752000B87819E6A353CDE3B44BCCFAE7E1D7B56D
+:1075300057D33846B36F6317C681CC381C044B92BF
+:10754000C6CDFBF0CAF2897DF45DA67712FA49D365
+:10755000A6523E69CEE7F4AD76D4E99A75DD9CAECD
+:10756000669C1B822CBE63D2D9D38BCFDD03E2D3C2
+:10757000C3E5C689CFAEFFA1F8FC11DA28E4EAF72B
+:10758000B3F7C2E1E03780E68DF2EDF2688E33F9B1
+:10759000DDB9FF536E7EBEFF0FDDBFC90FA9FB1B18
+:1075A00049FD1433FFE9E7FCA6E2DB4D44F1BC3EA4
+:1075B000F364CB955978FE32BFDA3F334EDFAB959B
+:1075C000C1D0502FF8CDFAD912FB7BA0DE62BB9D53
+:1075D000A53AFC1185D72DF57BCF95DB63CEF797C8
+:1075E0007AF1EBA0D7683545FE6A88EFFDECE4F947
+:1075F000B4BC9AD67AF46FF3EE6475F6BB65588521
+:107600007577232B0CC19B85F995D0736964FF793D
+:107610002F3F5C3F0A4972A71E42B3E17BAA6E8BE3
+:10762000EFE7DDDB5AEA65CFA7E03CBB54A677F372
+:10763000CA5B693D59C30BE3D3D16F79EDDD651AA0
+:107640009EF79F6415D2B8EED917DD11CCEF9DCD12
+:10765000840A5AB7F5E28C436897FFA1AE2B53B268
+:10766000F0C9D91FBE395D26443AFBFC9BD3254A9D
+:10767000AC84EDDCDF70E957D3116EA30C8AAA311C
+:10768000BFA629F47D932A95E5B3CC7A9C9D394A0F
+:10769000135E7FE261FA382757D881ED5A0C70A14A
+:1076A0009DC0E3EDD79FD197613D644697ECC27AC8
+:1076B000B9875D86E123D70B271EA6EF5D2B9DD5ED
+:1076C000183621F7C30711E5C658E6675C08415133
+:1076D00088E87DEFE1EAF1D43E76D42399FC2FCD02
+:1076E000061A97E8B9554DEC0D617C58FFF64AB281
+:1076F0005EC34A89D6CB6C970EAB5A123DF68667AD
+:107700008C0DEF7E1E2F3EF8EEDDADA564FCC62984
+:10771000AC8EDA77624A3A2491DFED7533E9FA816B
+:10772000BC93E5A508D6A7E4EEF43EBFC727819138
+:107730004E8E4839241832C18B6F26C0490BDF3575
+:107740000910D1C8F317EB80CED351A7D26B5B9D44
+:1077500036B69018FADFAD0BD2EB63753ABD3E52E8
+:1077600057449F3F5417B6C93DAE77B288B743A977
+:10777000E5F6725FF17DD8931638764E24524FE8C5
+:10778000B593E78B1E2C9E9ABE66807CC3EEBAAE84
+:107790001173C6726411FAE5D7687BB60E00FFEE6E
+:1077A0007AD7AA459837B94F8AEEA5FA3196B7C865
+:1077B000A21F1BE5581E1056BC5FC99C33278FCAF9
+:1077C00023959792C331C03A9BBC60AB0BE3D6794B
+:1077D00047D97DF3FD074A2F22683FCE9AE39251A5
+:1077E0006F16433B82A514C7A08CF49F91BDA414CF
+:1077F000EFC344FBFDE90A936F9CB78C5CA7AAD149
+:107800003615EDA6CC5DC6B3643F7FEA70EB988772
+:1078100079E8D53F2B187F8FFF5A51D18EC97BF95C
+:1078200004AD4B88BBBA156292C11B2D6BE748446F
+:10783000CFC4793E802A16C22771D4B1349EF9FB99
+:10784000F89C627CFF2476DADA7FA737761FB65180
+:10785000F1AA41C2471EB3FF9A78249FB4797DEB09
+:107860001B2DABE3066D93FE53583B4EC6BF9811DC
+:107870001B25107CF9EA57C5BBBE846DB3FFAA383F
+:10788000D6C31E52593D26F8622194B7DEB646DAB9
+:107890007E4B5B626D50D9D5DCEF86837F3E847A68
+:1078A000AEF265573B8246F41EC3FF4B0FD3EF2465
+:1078B000B4D575697199D3DFA40311C90941A07EBC
+:1078C0008A927025C610FD31817F1722AF24A2D77E
+:1078D000A37E4DC861D49B577899DD382141E6B12C
+:1078E000C8D58414DF1FA17959A4E33656D7DB8F9E
+:1078F000BF3CCC9EAF05632BFA0DB05FD668BE903F
+:10790000C71DCF98E71CF73FEFF5B0A6BCD9F05ED6
+:1079100085FA67B544E35AEB43ADA50A5967FD4FB5
+:10792000426172B242A387D51DACCF68CF994AF8A5
+:10793000A431C3DE7E98D7B906338C8CCC62AC0BF5
+:10794000787834E6ED2BA1F5F66F22BCBF64F9C15F
+:10795000D307AE4DBF9EB437FC92C5753774BCA932
+:10796000C4483FC1C3EB093AA67C05F757B94D009F
+:1079700021C4E433329EE039D27A9544F864A27788
+:10798000C45C4F01C0D363229A40F860FED68246A1
+:1079900015DB8A3601E566FED6C246E4ABF513CDAB
+:1079A000EF2414BE1E29E4F54C23719D07E21877DD
+:1079B000DEB7A2FC2B78CCE6084C6E0923D2FC9EE5
+:1079C0009811A779A7FF6C14685C1B53EE9BA66205
+:1079D0003D1D7449E4BA5361F4339AD8FB0CE47E3C
+:1079E0008B3C15E9C2DE1B228E24D5FB635F76D368
+:1079F00038726175E41E6A1768C592F5BD2CE0798E
+:107A0000E32BF03732CF780D4AF1BD80A73D2CFE35
+:107A100057B87CE97A1C27FA977851CE73C4844111
+:107A2000E7FF1E8B3BEF1412EDF81EA31128A4F400
+:107A3000DD19607C613C524CF9629F5076D57D84A3
+:107A40000E8DAED55BFF0DE99A51084857BCBF912A
+:107A5000DCDFC7E929668435A4DF3E4ECF784230AB
+:107A6000B07EC5BCFFA26BCD3D286FB76ED93F4736
+:107A70002578CD71475A47103A2CDFB23F1EBC968D
+:107A8000D2618C4AF0BEDCB33F8E74D8571F19A95F
+:107A900059DAE3FF42AC115A07BE9FCAB394F1C84A
+:107AA0003A9477F2FC3595F0E9D399A6BE60CF0BF6
+:107AB000C7F4EA8F0890B346ACEFD3272A391F0AE0
+:107AC0002DFDE710F9FEE727599DF997C87A28EFB1
+:107AD000641F343FDB33414AA0BFEB25B0A0DDE299
+:107AE0009D3886D6CF917D03DA253D13257ACE9A2F
+:107AF0007169F70481BEE78DFD911FBC05AC3F1194
+:107B00009428EA4D295F02D4EB92B83B3241C7700A
+:107B100030CBBBBAB485F43D514F9125CF0A7D756A
+:107B2000BAB41DA29F97B1B5C7BABBF3046257663A
+:107B30001D5FE81A4DE65BEAE1FE4616B1B7C9FDE6
+:107B4000151E662F3D1035BE8C210DD0BBF3A87ECF
+:107B500082E854BCE6DE56989B2C1FD277AE3BEDF4
+:107B6000EA6E6A3FECF009E5C9EA4F0BBD3CDEE086
+:107B70003B42BFE7510B44FE512ECCF764B9FE30B7
+:107B8000DF1F70D6FB9AFA44CE607BAC995F968B70
+:107B90007A40E2F5439216D6B0FEB1D45F42EDBE14
+:107BA000C7B99E120F5C7B33BE47A1A03E00D45FD5
+:107BB0003103F3FF3D79D08EFC2A052360CDD39AA3
+:107BC000FAA0A94EA5D7A7A68E2B4339796A6A4E8B
+:107BD000994664E0E0A49F7661DEE8FC6E26BFE78C
+:107BE0000FAF35687CC960F122642B1A67EC7C9476
+:107BF000BE27FB0329FA10AD7BC5FA0502D2B60CED
+:107C00007B7DD5082FABA3ADE2F036CAEC79731DAE
+:107C10008B072B17AFA671A9F3FCB93B76277DAF75
+:107C2000C24DCE327CCF5105C360DF196078C0F7FA
+:107C3000986C798B8B93E8F82A0FC3BF59CFE1ACCE
+:107C4000DB30E119CBE1E9FFDE849D1EA6FF65D2A2
+:107C5000C11C5FE38AE46A03F04DD545111296F822
+:107C6000475FFDB542EF9FC3BAF574ACB389B55E0B
+:107C70001F42394850FFC8E3AB01E0DF35A27C1A50
+:107C8000947AAC75E2698EBAF57EF2A2DBDBCEBAED
+:107C90008515C81CD3981EA7F5A6127CC745E87D9C
+:107CA00036EDBDE968D75611F5A062804832345CE4
+:107CB000FF1CB7F7A597EF8B8CD2FBF663C60BCCF6
+:107CC00076E54B0B691CA16A9F8FD6E357A2FE9BFA
+:107CD0008C75FD4697DB56CF1FE9C4FA39F9253676
+:107CE000DFE31C9E3F691579B8EF37B8FF9323C4D3
+:107CF00044F652CA618A87B827720C34A6CF24C2D0
+:107D00001371B3DEC2581B478761A702367B69A790
+:107D100097B5FF73CBDA789C9DB3DC9EF984DA3F8C
+:107D20008D1EB37D96EABB9D4A6B27EA3BE345B7C0
+:107D30008EE717194FDF93365614D173201E8291A8
+:107D40008887D73214AAE7E22FB8F7A29E9BAAC66B
+:107D50000EA916BFE16CC6DBA3D1FF4A329F619B1F
+:107D6000AF6078F391F53B10AFE6F3D73276768AC1
+:107D70006C9C4EBFAB917F78F46AD2CE79D14DDF47
+:107D8000EB31FD4D275F2A5E265F4D8EF7F314948D
+:107D9000371FEADB6A2A67EEA03DAF65CA9D7271A4
+:107DA000822DBEFF383F67152986A14AF2BC983E56
+:107DB000AFE2746DE27506A9D7C94CB1CE35549EB9
+:107DC00053AF339DCB3B703996B4DEEFB10CF01E50
+:107DD0009F33EFE1D453BDF2CAF5D0169C1FE3BA2E
+:107DE000101BE325D77589F6795E3A3A3609EDE03E
+:107DF0005F737FBCA8EDE157F1786E7147EEF24CEE
+:107E0000A3EF657D17AFC39587F95EE0F1947E7AA5
+:107E100088D95777327BB566FE546ADFD56C1FA3CD
+:107E20001903F8491517D36C7A48F0E8FC3B77063C
+:107E3000D547151703F4F9E55BCF637BBFA4FF7A41
+:107E40003EFADC5CEF5E879E3D38E9173B0BC9BA12
+:107E500035CFC982DBB24ECD73BC3EDF43F4AE5D9D
+:107E6000DE2328EF52087ABF4782FA619BC2DBC645
+:107E70008CC639F968D75AF4C34CB4BFFAC6E3F7D5
+:107E8000E5B679CDF19146B487FAF54F73F41F63E7
+:107E9000CE5F4EFB3BE131F50FB6D1DE92FEE2360E
+:107EA000E1A3FAEB61C1315FA6B9FE423A9F69775F
+:107EB0009F6BB9F57543423E6D2D45FFA9672DE8CF
+:107EC000F8DD871F48616FD8C2B7E75466F7575C83
+:107ED000BCD246EF3EBC8FB3DDFF7D5DD0564F7BFD
+:107EE00077AC86D6519F5339BD88654EC7ED1E6568
+:107EF000ABA3FD071C9F158EEB53C071C35F198E9A
+:107F0000904D3EFBE028B4DDFFAC704454A68FE7F3
+:107F1000F1EB5C8DBDD73A5777851BC8ADB9E4BE90
+:107F200087F0FA97C95525D7B912183EFA3DD20401
+:107F3000EB4FDAE8DFDFFC97FB3FB89126AA82B669
+:107F40003A0191D7613BF50EBE77CDEAD854DBF705
+:107F500042CCAB5764F594CEFBDD3C6EF0EDAB2B21
+:107F600001ED6962AB277DAFACD1C7FA811A146C01
+:107F7000716EDE36EB702F175C7FE4E7F4B7AFBEAF
+:107F80000930AE2B215C49FAB573B89AD408CDC339
+:107F9000C5B581BF07F359E191D34C3CDD40F124D5
+:107FA000A6C0D32A1FB72FB418F5939A825F0C3C52
+:107FB000B9BDF00C8C9F6FA43178E0E215948F442A
+:107FC0004EA7265FF2EFDB98F98F26F58B857F723F
+:107FD000DAD0E8BB87F7FBA2E95B3A44FA8E30F9C6
+:107FE0004DFB62E1593C4478AE35F92D18A1F4FA05
+:107FF000A2E0593B44787E6ED24BFF62F1F3C01091
+:10800000E139CBFB29692C3EDB54C4DEF7F08AD181
+:1080100087B0DE6130B9F016DAFD6C35DF6BAFB3D7
+:10802000FAC05EC7956A9FBFE1FB4C254F2BE44425
+:1080300036D2EF581D8B07BCCDFD93DF5434F86961
+:108040007CDEB14E5370AF7FA0B8CDFFAAB0BF3772
+:108050003B981C17A4B1FCCFAD31FBB865CBD31C4A
+:10806000756106FB4E30C75FAAF9FE5EF0361993C4
+:108070009843C01BC1577A6800BFE172E32B95DCBF
+:108080000D175F716D78F81A4CDED722BEA60D1D54
+:108090005FA6BCFEBDE24B1926BEFEDEF9ABF41FA7
+:1080A000F81A16BE160F571EB95DFBF78AAFA1CAA4
+:1080B000A3D36F23FE5D78A0F7FF2F37FE9CEB7FE5
+:1080C0005E3C9AF3AD48E1E7A5C2E7607098D76ED1
+:1080D000EF10F1EAF43FFFDA7875ACFFB9F1CAE7C7
+:1080E0001B365E0781C3BCFE11F13A0CBBAE4D617D
+:1080F000DFF574CE93ED67DF5B1BEFAA3E321FF313
+:10810000C75F15697EFAC8EE391BACF540D97E66AB
+:10811000FF1F299FBD81D65747D368EDD95121FC58
+:10812000EF2598575EC4C639E73FC2F1F55FBE0C34
+:108130001ECFD6B391AE47A38B07944728B7EC8BDD
+:10814000E68D2CF415FBE3FB08E8DB4B300FB12088
+:10815000391C269D53AD3B5CFA1E8DFE6058FA67B4
+:10816000B0FDFE876FA8767A82E2310B7AFFDECD12
+:108170005588CF3681D5C31DC75B79F8DD35A09D05
+:10818000962DCFDD83748AF9595EB043D13760FEF6
+:10819000C4BD78C1837E42B7A3B764B8DC167C5DEA
+:1081A000E3677ED5F495C9FDAE08E783BEF12E18CE
+:1081B0009F84BF27F37EB7AC64DF07032952B0C8A2
+:1081C000F21EE90ABE8EF9DC397EBE3F40C71F4D64
+:1081D000F15EFEF57CFE654B061E0FD5ECFB3B8485
+:1081E000EF0AACEFB1F6F219978FE3BED81C3F81CE
+:1081F000E76D57EC89AF211F4DF0B1F7802408617E
+:10820000FD95394F96049D0AC1FB07B25E8079CD7A
+:1082100024F37C75A07952E1D5DC8FB90E8A227ED9
+:108220004767AECAE28825118059183F7487EF630B
+:10823000F943C60799BC0E7146755AA21EFD5E89A8
+:10824000ECD3026FC7FF9BFD4FF8BCE388A0D1F7CA
+:10825000CF1D78184C3F6CE47C9325C6367B306F7D
+:10826000B2CA95F43B73EBFDECEF0C15F87BEBA574
+:10827000E83AE31E8BC9F87D8AA512CB7F114E2CFC
+:10828000B0FEDD9102CE07CE715922AB37827798CE
+:108290003CB7ED5D57904C7E7EC5E5B4C05F64ABE6
+:1082A000735C12BD4F46F95CB260A1ACFBF0B9CE75
+:1082B000F88DC3D1A6C40AA6F8FAF094520F71FC47
+:1082C000741C8B35E0773956D5BA689D40F126C6C7
+:1082D00077AB361D103690EB1E2E7F0B910696F96C
+:1082E0009EE0746DDBEB1D8DF0B799F91B9C98C077
+:1082F00071FB2EA0F990C7FD1F34613EA4DB053C45
+:10830000FF1B2DC7FC6F37AF6F7B8E3CAF4778E705
+:108310006453F91EB7E9E31AD4CF1D0AD0BF7BF12D
+:10832000BB2DEE04BE4F60F24BAF9ED874A10EEB96
+:10833000871F553A2722DF6437547F2D59FE743F3B
+:10834000A7C39F7CD1F46476A07935F5B9D96F9134
+:10835000A4CBC9FA2F2E779C6B1CEE11EECEB390F6
+:10836000248FD9CB878981EDB4B7B81EFF9523CF71
+:10837000BBE458F23863975FE0F396ADA7E796E168
+:10838000D669CD3487C7C45796C1F0B4748968D311
+:10839000B7AB16A439EC1E86D79BDDFA93B88F478E
+:1083A000F7FE62227D2FCA713E78C59882CFEF8694
+:1083B0004E19F5C42951A7D7B7EBECDFFD7E1B6240
+:1083C000DBA7E1F9592B2695ABF739FFBCBDFC8E35
+:1083D0005B28FC715143F84FAC1C71D34CD42FCBAC
+:1083E000E5F05832EE44FC7EFF5ACBFE7BED1A07D7
+:1083F0005CBFA9B863C0736BD9723BDDDA14661732
+:10840000185F6172780FE1D15994BFBAB7CF20EBF2
+:108410001F49644ED9CABA03FE7DA7C5FCF7534273
+:108420006CC70CA26F4E0B2C4F627C9DE98D258F83
+:10843000451B31757ABAF69A57BA49BF8B7C7FEFE4
+:10844000D50E7C3E3AF969DC63767B6FFA31507069
+:108450007CAC26F979B0554BE37FC72B3C1AF5CBA2
+:108460006D9B92F7FB213233A1EFE9FF162B92C5EA
+:108470002727680CDE55D1E4E327687EF61CCFA5DC
+:108480002478FE2090C6F59C361AF5F4AA14F076EE
+:1084900007D8F9F57EE303B7A11E3825D8F5F39187
+:1084A0000093D7F600E3EFD37B57C8D948A72697A8
+:1084B00086FC7032233C01F96D75FC047DDFE55FBD
+:1084C000020CEE43DEA81E9886F2B2686E36A14B0F
+:1084D000C74A08BBF4D4FABF2860EA7F16AF25E785
+:1084E000DF0778FE91A11F50FB438A8CBE75229D49
+:1084F0009AD6819F168C75B4CE70AF97D595427879
+:108500009AD58E9FCEE13EBD6F78F4BE25EAB0834A
+:10851000FAD97FAD9574DD7D691AD6A51C29173B64
+:108520006F24407EB82F8D7EBFD62917A9D61FAEE7
+:108530001D787ADFF0ECC0C1F6BD32101A921D78BA
+:10854000BEFCD11D2528474AEBA464FAD7D4D347F3
+:1085500079FCDDC93FE6B582F3C5A9C4C070DDBDB5
+:10856000CB0ECF6DD576784C79399568F0AE463C18
+:1085700041E744AB5D0A73A60D72CEB2FC542A38B3
+:108580003705EC7A02390FE9700FD737EFD53E1A6D
+:10859000B0D2C1B9FFD302F70F9E6475B963A3AB24
+:1085A000CBB2F53EFEDCC2E7BFDC7C699E33CE7900
+:1085B000FED6F9D03CE706E3C3AC14799C027C718B
+:1085C000998C5F2D690AE6EB0B023A6B83360F5FDD
+:1085D000D58299E6DF57D147E3FB5FA7F77AE97BBE
+:1085E000C0C6567702BFDB7E6AEFF513ACFBE9E24B
+:1085F000F459B524837E9EE294109E9F4BEBCE44AB
+:10860000FA9DB5B78F65CEC3F6A38705D4D0705B4E
+:10861000CD6A11F7F77A80BDB7B36AD39BD41E1C1D
+:108620002E9FAFAAB69FFF13701FD9163B4BEA29A6
+:1086300041FE49858717100FE8074517CE45FD7C99
+:10864000C72617D5B72FF279EE9022546F439C9D21
+:108650008FA0127C9023E4046E02F1F138FFAE94F7
+:108660001455ACEFC9ADDDF6C05CAC7B75CACB97D9
+:10867000D3199EA6A433BD7DC81B7B2F90DDA79F79
+:108680004FBAAA0FE4922EEB039AF91D5F2AA7E6D0
+:108690007ED673B8889DF62CFDBE30DF1FF438F807
+:1086A0004D68ADFC29E2BF4CA57681D74DF43ED68E
+:1086B00045FFC04BEBA84CB932ED1DE7F8A552CCF5
+:1086C00066377ECAF59ED976DA21FF382F92F71FDA
+:1086D000931E1A929C5EAEF36252FAE5392F04CED5
+:1086E00067CE73A357AE9BD8FB20278E7D32379978
+:1086F0005CDFF819E170CAF3A9BD5EF65DE31BFC0F
+:1087000054EFF4F953B909F4979D7281FE147EC7B2
+:10871000E3D1BD6F4CC4BADE13DB1FB82D193DAFDA
+:10872000D6781D7677AE2D9EB72600B4FE1BC87A8C
+:108730004F59E637C7F5CACB20F1CBA52BAEA5FE26
+:10874000E4DB2BAE1FBDBAB8BF5FD1AFBF2BF6F8CD
+:108750002DB86E3DF7A777B82BF626F303395EFBED
+:10876000C789EDF6FD2D9B4A1BD1A5DE9C76C397EC
+:108770006249D6EFF56B36258FC7FD9F74875F631F
+:1087800010BF86E0A37BA5189859D2E7D7741B5F6A
+:108790008C5FF33BE8F9F71954FE93C3F7643AB3DF
+:1087A000534F29B11DD712F84E13FFC740F911C816
+:1087B00038E497EF26F7D71EE1E37EB76998FAEA27
+:1087C00098DD9F49257FBD707D4EF96B537A0A5025
+:1087D0000FFC6ECFA7EF3E80FBD9E3A5F876CE73F2
+:1087E000A32672FFC24BF9D63C9F3B14A6FF7FF72E
+:1087F000D591F4EF553BE503A0F5A6EBC8F3E37B79
+:108800008529F81DC4B6BD6915C9FC9C159A8BFB5A
+:1088100017F6780F70FBEE16CE6FDADE67AAADF1B1
+:10882000E877B8BE32E300AFA4B37376C982850A95
+:10883000C67BD6F6C69B803A2BDA55F97BF03B52C5
+:108840006FF1F7B98C35FEA4EFC7FD82F3E56071D7
+:1088500088E52BED7182250B063E6F3E4C24AFCB95
+:1088600032F939D57AC33D5FDA12C3CB8B0DB64FDF
+:108870008F36347FE416A8FE12C63B964258C6EBEC
+:1088800012A89EF85382CA0F772DA6F0BC65FEDDB4
+:10889000E14FEF9F68B563FE8BE3FBFC92FBBF8A61
+:1088A000EAF21DA57A62B2F3C919F7792B053ECF1A
+:1088B00070BBE71DA433F2EB5231299DDDDC8F7FC5
+:1088C000672593A3FF0F425212950080000000001D
+:1088D0001F8B080000000000000BDD7D0D7C54D5CF
+:1088E00095F87DF3E62BC924992433934FC2840075
+:1088F0002206984008A80813422428950904080A6B
+:108900003A7C88817CAAD8B25BB74C0860A46E1B05
+:10891000566A5DAB74A0C152C536D1D422A638A028
+:1089200028FEABFF06EBBAB845775017F9924456CC
+:1089300017BBEB963DE7DC7B336F5E6620B6757741
+:108940007F1B7FEDE3BE773FCFF739F7DC3B972EF8
+:10895000C1DF0CC62EE99E8BAA5516B232FABB04B3
+:10896000FFAB9E9B145576D9ED8C3919FBC7A5AD8D
+:1089700089FE22C64E19E065096381C7D4E06E0501
+:10898000CA41FE5EF6E7B22B54FF547041AADF36AF
+:10899000783CF9BCEB5118774C649C65CDD1E386EB
+:1089A00059602D73C038C144FBEE0286FF0C592676
+:1089B00046DA77DA0D340E3B9569602EC6EE936D7C
+:1089C000E38CF7BB0DD0C15583EB571BBD26BB66AF
+:1089D0009E2B52DD8C4D8E94ABE746CF3335C54E82
+:1089E000DF19B3E7FB92193BBD2BD14BF0989E1CCE
+:1089F0001C05F3ACB0B2800DE6F9F093D7BCCF46BE
+:108A0000305625E051EDFBD484F0386DE8DF9C8CC6
+:108A1000EB7ACB60DF0D43951EF39AB4F05B9BA21B
+:108A200050FFA73B2E0FBFB5297C9E0B2AA3E7B7AB
+:108A3000F058625459BFDE7FFE9B072662BFFFFCE1
+:108A400037174DDAFE177D91CB421991F21D358A09
+:108A500037583478DC8E54F390E0DEA183E31D5F59
+:108A6000E453FF0E953577C65897C76EA5FA0B7D70
+:108A7000652627C073E5FD8A47812E8AED6E1A6F41
+:108A8000A591793B613ECCE8CEAF02B83B5B9BEF52
+:108A9000F3C5E8678D9DC3EF339B2FD57E19F8BDD5
+:108AA00023E841D65B64F49B62D55F5C130DDF3035
+:108AB0006395B1E67FFF57A44739BEBEFE50E7512C
+:108AC00097C2F932C312FA84A9F0E21CF453FA15E2
+:108AD000C6D5D5D78FFBD702EEF1C63FFD47B536D9
+:108AE000161CF60AF8FB7D403F31BF27D3F7B75875
+:108AF0007BE37EE2EF24CF6E0443C7CAEF01DAD9ED
+:108B0000EA39F7BD0AAFD91F920B68FCA5BEA315C1
+:108B10000856F6E5C3E311EF9F573EFCBD1298DA05
+:108B200069B3BF35191A9CDEA87802EEC1E3BC8593
+:108B3000EBB430F6F6062BADF70FD096F0330BFE04
+:108B40002F9BB131AAB70E850AFBB6C5BD5BC3B773
+:108B50008EF51737B0F18CED31FB36E21446DFFFAE
+:108B6000E93A86328F0569DE1F983C6B08DE8C116E
+:108B7000DF1FDF65DBB915EAFD3199E3032839DF33
+:108B8000374E23278C762A0F153FBF8B839FAF2A42
+:108B9000A7E43AE38D0390A7F9CE9F696B5352196E
+:108BA000EB36BBEFC4F5F4CF49B0EF0214CE377B00
+:108BB0006F46F8BC75D4606829A06E8D48A70BF885
+:108BC00010ACE09682EF8E2D41F963F226C054AAD4
+:108BD000A00DBB16E868A62D80FD95FC6EEED3882F
+:108BE0009F876B2C6E15FB9BEE7E4F85F2FC9B2CBA
+:108BF000EE8DD05F69EF88830EE87FE15CC5CEA083
+:108C0000FDAC39A39C61585FD27AE82707A7F79D8E
+:108C1000CAF2918C3D85835DC7F8840116F3155126
+:108C20000E3CD5360BE4C15867B7C106A05EB8ED5F
+:108C3000A9362BF4BBB9C597654F83C9A6B5B459FE
+:108C400087813E72797B6778189B9AD65A69BD01F5
+:108C5000D6F998EC6F539B378FB1170DFE0205BE06
+:108C6000DF91F644A511E6EF2894E377D2F7453774
+:108C7000ADD9BD0EFADFBCED50A511E7BD548EFF96
+:108C80005A65B911C69D26CB6F58B1EC4812ED71EB
+:108C9000BE5319338D88CCDF9805E3A7CBFABD9579
+:108CA000B3A0ED3B65CDE54618FFDD6DEFB41525AE
+:108CB0003036656E99DD0BE5F7D3CE5726017EBAC7
+:108CC00019D029943F48EBA7F93B5483E8FFD336EA
+:108CD000EF349C4F602C7E57029FB5551633D660FB
+:108CE0000DBF8AE4DAB43E6075C13F262B9C4EACC2
+:108CF000A6666F2EC0CEB4AF2C944BD369E7F4991F
+:108D0000171A877A6CA03C06CAE334E52C5EEEDEC7
+:108D1000C8EE88256F83E95CEE7527C6FE3E318D6F
+:108D2000CB03801BE993D463CCBB37865EC94EB3BB
+:108D3000513F871359C09A1EE1B779C0C353812FA1
+:108D40009995CF53F633487FA4713DCB02F3D2916E
+:108D50006FE66217B0F4428F1240BA66CD49C15136
+:108D6000483B2C645C80FA4335D07C9DAA72471541
+:108D7000F4E74A64FE2E783A331895A1BDB7CB16B6
+:108D8000E9EF0D41F71585BE0EECAF2233BBB8B548
+:108D900020D20FCC7B937562D4BC8D53D3F1FBFCF6
+:108DA000E2BB8B34F02CE2EB003AA07630CCD3332C
+:108DB000800FBA7BC78ED80AF3FB5027774B7BE72F
+:108DC0009B18D4DB9C2EE4899BB7779673F9D37FED
+:108DD00077527017F2A7D5538C7892EDE60AB897C0
+:108DE0003F30F78758AFBED7C42C506F5D57592618
+:108DF000BB8C5EACFFE27A169CA4291B4366943BB5
+:108E0000F55F4CA7F7E50FBC61463EC57EDCB0AE12
+:108E10007509DE4C0FC2AD3536FE196BA179D47FD2
+:108E200091C60293B4EF399C22FD3BE8FB95D61521
+:108E3000E94F65C18CCBF567A6EF0370370AB89B85
+:108E400063CFF35E49A7006F8386BE160A7A03E9F3
+:108E5000E7457978FC96A25D28EF23E36EA476DDE2
+:108E600046C023DA81BD896EB48B4B8D5C7E96F64D
+:108E7000A6DB034A843E245D48BC76A73797D17AA7
+:108E8000AB14FBAE82C1F3FA6B392FA14F3397FAC3
+:108E9000D5E59AF9497E80FEBB45FF2553897F9E23
+:108EA000E0FC007CB30CF917ED165C8727346E7E6E
+:108EB000F2E0F97F0CE485F5018F1CFEDFB005516F
+:108EC0000F48B80D867FEE15F0994FDF4B7B0F9959
+:108ED000719DF571F8F6DBE929346EE6B1508A1B15
+:108EE000EA9DB57379D5DD3929E17AE48BB9068637
+:108EF000220CD78DF66AE980BCBDE1F599A01F323E
+:108F00006519E5AD1BF130207F43566BA47EC3DFAE
+:108F1000DD306713D4775800FF4564875A99C69FA0
+:108F2000F8591A976353FD2CA6DDD2929E4CDF258B
+:108F3000BCFF7E7D39FB10D6F7AF76CE9753C301C9
+:108F400005F122F95A2FA78E083C1EFE1F9353CA23
+:108F500015E454959053FCFD6130F3B19ECB151A86
+:108F6000A7804E5CF1FAA451E8CFDC93A5BA3F028A
+:108F7000BE5AA078863D03FD565BDD9B93DD113A1A
+:108F8000A96656B70DE10E46D325D4FB7313A88C02
+:108F90007F68975C6857381D32776AF5B8F8724871
+:108FA000CEE39E2C338DB7E2C151A97EEDFC849EA9
+:108FB0009867093DC30A07F3B92CC3FC1B0CAAE64A
+:108FC000BB8DEBB3AC64EF87698087B7145643F36E
+:108FD000D1D94BFF21FC36BDBDB449D8914E342FB9
+:108FE000898F0DE49C66B659828C3709A09F9AD967
+:108FF000C904BF860CF51A3AB8989647F358BA18C0
+:109000003E4E00A6B4BE3CE1230D1F1DC1F9905E8B
+:10901000084D463E05B119358FA5AA2F4F41BB35E6
+:10902000D3E24139037822381C4E60C60418F73564
+:109030007822DE2AD4BB0F9A1C48078AA795A0BFC6
+:1090400053D8A72C84FA66DE8C24B25BD997F78EAE
+:10905000AC0278389338DD423F56D18F95E844C84A
+:10906000BDDFE65FBD0BF593949F120FEC4B95FAB5
+:1090700093DF0F2B557976281F765E55DCAA44DBEB
+:109080003F680F45ECA7C40767033F4EA9EC0C19D6
+:10909000EC285592E77C0BED70B09F12603D19E90A
+:1090A0005C0E1C2E08A829D8DF285807BC7A35D1B9
+:1090B0005FD46C8BE0036C1C3FE2CF6586A78DF319
+:1090C000073EBBD23932AECFE0CFCDE2E94AE1F57F
+:1090D000F5F4F6830CCE9F6B150EEFAD655C4EE894
+:1090E000EB8D17FD36580395AE115AFBCAC7900E8B
+:1090F0008D8CDB5913D2059D947378953FB0341550
+:10910000F5E6E7BD0B535951448E6E56FC760FD4ED
+:10911000DF6CF27D9FE21DFFA032F447CC697E7BBD
+:109120003AD4CB488AED2F57A7F3F966A03F0DF547
+:10913000BE27FC1DD317D7909F7D23DA65F03D2510
+:10914000AB9AE439C2D00DFDA6B2FE805D83BFD4D8
+:10915000A98628BFC1F4C5786AFFD5ED86E23876C6
+:10916000434994DD20C7D5DB0FEF6DC8A2F9CBF6DC
+:10917000CBB2DEAE609AFAB7B3F066ECEFF675B933
+:109180005171A27876C75A8127B4130231E7658EF0
+:109190007AFF1EF88901EDF8A7F8F891719380D154
+:1091A00022E34E48F7D6A5133F4DB39FBC061E6081
+:1091B000BB5F5249DF90DC07BDE4DD69237D548944
+:1091C000F25AFA47C8F7F654E4EBB27BD3276BF4B4
+:1091D000A368A797439F087FFA13A167528F497B23
+:1091E00031D1AD28117D33585F093DA3938B57B220
+:1091F000AF815E035AFDAFEFF787E97FAA5D59188B
+:10920000873E46FFB7D895A5D3FCEA38949B950ACC
+:109210001B058F29B3A2F5FCD3E9DCFF783A3D2981
+:10922000CA5F99BF34BADE2FB0DE647C260DC95FF9
+:10923000D1EA21454579C7FB6B14F45070E62DB394
+:109240001BE4EF19B483A0DED10CEFF348579B1257
+:1092500053C6A37ED8F99FE56376C2BCFBDF3479A1
+:10926000766177FB387D942D59D76A84F7A64EC571
+:109270006E6191F9D9D6774D5805EB3D28F054EF42
+:10928000E0EBA87784CC2361DC9C7A3E7E5EE741EC
+:10929000C5A8916F79B5BCDE6FD24D51FAE6B758CB
+:1092A000867EDE94FE070BB65494607DAF712B88EA
+:1092B000BE9C4E85E2C139CD0000A0831C0FEFDFBC
+:1092C000E6092A2B8B22EB6C335415A15E687325BB
+:1092D00079502F6439FCFF80EBAC3F1E0A2198A621
+:1092E0001CEF35A27D37D1E17D87F84AACD3ADDAEA
+:1092F0007350AE261DE7F36BD7D13B63DF15F3DA6E
+:10930000C5E5ADCA8E30C407CA0E18CFB5710CE9D9
+:109310002559DF952EF4848BF99F25BB8AB531C280
+:1093200017A375B8368E26FB5EE23362475D3D11AA
+:10933000EDA8C28742C615D06EFFE386CA5876E212
+:109340006702EEB08E3EED3AE2F185D463B29E291B
+:109350008E1F2DE93DA932B67D0A1A80BE972D7168
+:10936000DC8AEBAEDF6466162502FF890E9F21C3FF
+:1093700089F8DAA9206C247D6D4A7F4AC985F5DD1C
+:10938000BB86D955167FBEF5EB9F9BB04AE36F4174
+:10939000FF848F9D6656ABD5A7D29FC8C9E0F6F46F
+:1093A0006A872F0DC76DDCB7CD8CF85DD371C2AC69
+:1093B0008D770F5AC710E1A5D4723FA5BEC61AC457
+:1093C00075962D3112FEEA369983288FEAF7768555
+:1093D0000C684FDFCF3CC8EFF59D5DAFE6005C72D7
+:1093E000EBBD935577A4BFDCFAA082F3710111F6AF
+:1093F000929F1732A37ED6D335DAC36897BC9AC042
+:10940000F9FD5C992DA000FCCE99FCF558EF5C7637
+:109410009227501081F76B5DB38F28C0D2C9CF5A05
+:1094200042F86C33ECCAB242BDB6B1660FD2D14439
+:1094300087BF3403E0946EF47563FB3447B2A7052D
+:10944000DABA2D6C22E9E721C2618A8E1EA6DCCF32
+:10945000F9A4362345DA7B13510EF93278DC156313
+:1094600042289F5E35F1756C627CBE5DE9DE0AC400
+:1094700013B3A7D3B839F52105ED7DFDB8117AF204
+:10948000DE9CF115E81BEC3C33CAF53A2167CA961D
+:1094900074281F6AE8E0563064B05ECEDE9D0AFA9A
+:1094A00081F0BDA5C241F59905E5CC5EBE1F51070F
+:1094B000DFEFD4C815B98E18F26539C2D776BCF77C
+:1094C000152E5F42447F72BE7A7C3664B869FC1BFD
+:1094D000C12CA0F7E6C01837F4F7EA8844EA4FF247
+:1094E000BB9E3F1B049DE7D474281837702471BBC2
+:1094F00051CE4FD63B9A31F36E9CCF94CA5E8243D5
+:10950000438D91F026E75361F68D44FF6B83E8EFBE
+:10951000D0E2F7CD61286FFFD551A2C78676C54B43
+:109520007E41FB51F3428CCF057EA6623CF6666E0F
+:1095300092B0477E7994F4C8CDDD3C4ED0D0DD6545
+:109540005C698BD069C19943B7239D35745A5882A1
+:1095500082F8E376AB9E4E41BE10DDB38099F6B340
+:10956000403E06489E327F01FA2352FE7689B81F9C
+:10957000B3F1F77F27E62DFB8DC8CD04A2F7823328
+:10958000130F59019E0D1EC503A612D8DBBC1EF495
+:109590001F22F9CBD808F4CB64FF7AF81D10F679B6
+:1095A0000C3CEF40B8EAF588D4AB053B66327C4A08
+:1095B000FC1905DC65BFCF6498A9DF67328CDCBF7E
+:1095C0002BE3F1EB4D26AE3F36B55883C8D7AFA598
+:1095D000DD7844190F704A3787F079D8B0A21EBFE2
+:1095E0001FCEE1F368336C1CD3CCF5D7CF713E8727
+:1095F00016A7302E9FB83CDAFE1C9727F5011BF901
+:1096000089F5FEEA55B4FFE048F0A0BDCFFCAF9865
+:10961000172647E8418F5FF7B307CD6EF87E7327B3
+:10962000E78308DCB89E92740B728EF0DE952EF7FD
+:1096300023FC050857F0DF5B30CE20FDF794A5BE74
+:1096400040B27B30BF6608FF7DB2F0DF4D53AD7F87
+:1096500051FFBD6EFD6FB2B1BC36EB757A4A7E012B
+:109660003F318AAF7E2FF01D12CF0F04BDD4957409
+:10967000123FD47DD44C7C64ABE4F2C4763C5A0EE9
+:1096800032F6B7C22E7888E05091D479A38AFEF0E2
+:109690008F157B2B8B3FEFBB94E6FF7F2DE2A54B15
+:1096A000A57D29F62558F5A500D704010351EF3310
+:1096B00041EFE7F60022902F8DCDE6CBD9BF57EAD8
+:1096C0009785DE5610DF7502D6E7F6965FFB2F18FA
+:1096D0004FDC93EA19054B3FBB77C15FFD0BB43FED
+:1096E000D731C3837ADAD1EA23FAE9772678306E64
+:1096F000E850C1B2057A68E97C39E57ADC177B7AF3
+:10970000C244949B490EEE079E794E5D8FF0D9F8C6
+:10971000D35F4CC7EF75412503EDC6737B7EFC47D5
+:10972000D48BB51D4DE869B0D6A75F223BDC10DCB9
+:10973000C9DFEF4925FBF2F44FB64D47B8B776B60F
+:10974000D2F7333FD949E5433FFDC5817F477BC30E
+:1097500097E2C17A679EDBF69D7F473AAF4EF1E014
+:109760003AEAFD46BE6F2BE95B2FB7BA0E129F4A4D
+:109770007AB919F52EC2A986CB1F49CF1F887DA5BE
+:1097800015E5B63694671F6C4DAE8D154F9C20D6EF
+:109790008B31179263350AC5D3DA806A30AED19621
+:1097A000C8A6E233A92864CE8571162FED9A4E76AD
+:1097B0004FE0C46AACBF605F02DB4AF1370CDE8267
+:1097C000FD4FA4CED838108327C14F86DE3B2E81B3
+:1097D0007DFD0EC807D23B3AFB7F41DBEB7F403972
+:1097E0005A6D0D1F74BA23EFDB449C06EA93DE2901
+:1097F0005D173B1E3AC561137CCBF5664E77559ECF
+:109800009BE484C5334A63970E3BD6BC15C410CB8A
+:10981000A9EDBD11D771D398E593882E30CE87FA84
+:109820002760A3FE1B304E097C56E910F10F3B73F5
+:109830005C07E3571899C3864FC6DE36911CD94D95
+:10984000FD82FD417695FBA5C5BBD11E79C4E4CF51
+:109850009E8CFDB409BDD5C1E70DEDEDB85F0AFDE5
+:10986000D9AF9B48FDF49AD2A97D80B79FDDD1A2E4
+:1098700044E60B949A8F7A0BFB2BB1A19E09D4106E
+:109880007EDC665AD719AC924DEB1EBF6C5C847FB0
+:10989000F5F11D9467B80FBCDA51B6DCE18C3C657C
+:1098A000DC470FCFDDE2FB470EEF7207CE634F467A
+:1098B000945E8967AF1C5A7C9EEBDF174F90BC69A2
+:1098C000443AC6F1FD1F45E9DF95928E5F38417439
+:1098D000BC721FD7BF8DFB8ACD48B7673778D98751
+:1098E0006080368A7DD64794F06A8AF3BC9060C760
+:1098F000F8DD79A16FEA1E3A7112F74747ECCB26E3
+:10990000BFFEFC0B0935D8CF618381E07978D7356C
+:109910003B5B15ED3CB93F007630916A23D8A9DC5A
+:109920000E5EB50DFDB3865AE641FE6FD4D14FE30E
+:10993000BEA3442FD20E2ED8317F15B73F133C095A
+:10994000E8BFCDE2F628037B14EBA7CD0AB69889D1
+:10995000BE8A4B91BE0E2D3EB005F578E32C66C74E
+:10996000FE1F19E67D2197D6A330CC6779C4D43E7B
+:10997000D308ED1FA970DB019200B70EB27BD91896
+:10998000B3D073ABC85E6ECCBACD437CA697072F1D
+:10999000B490DDD5E84EA4F9DCBC4FB987DB2336A3
+:1099A000C6E7AF107DDE1CBC3E88FBCA9F08F849A5
+:1099B000389E37F5DE8EF038FF4B2044F87EF32CCE
+:1099C0004EAF69B33A498EBCF6C26CD2E3922E9385
+:1099D0009FB7903E4F37DA150FE9B505162D5EDBC0
+:1099E0004D5C2FA5093D53F810C7EF2F043FFDC272
+:1099F00061104FB3A073116FB107C6A3DEFD44E041
+:109A00009FC408CA77214F1A5685889FEAF7F2FE4D
+:109A10001C166FF1BD1AFA759473BD28E3FEB80FDA
+:109A20005015435EBC2DE651B063C536B4976F0246
+:109A3000BCA34AC91923E428D005C22DA7D6477470
+:109A40007093E32E8F5A40FB07E427F6B79859AC82
+:109A500038CF31B12E6786AF04E3CDCECC64B2737C
+:109A60009C6A992101DB152B9E5D6EDADF243BAFEA
+:109A7000DF99EDD915C5EFBE1203D43BE54AE67870
+:109A80000EFED6387F1CF2A15BFAE95176DF607FCB
+:109A90009BDB8D73DB03E3D10F91FB17120EC19695
+:109AA000C41AADFC7C5FC02178358FE7837D6FA33E
+:109AB000F8B51DC641BF7ED7F53FE17E7D2BD57B36
+:109AC000CDC1E31915B03EB4DB9C85BE755C9F2605
+:109AD0007B62C163B543DAE5B717A35FD9586DF36D
+:109AE00020BF6D7F515941F48CC141F4B7FDAB08E3
+:109AF0000F0CF080FCC0FCDC2F6D6CF60563D37B93
+:109B000015F15F23F29F42F44EF176A0F720A7777C
+:109B1000AEFFA4DF8FF2B12AC67EA8942F8DE6F0A7
+:109B200068A463C90F8DD3C3A3116E439527E74D76
+:109B3000C0FFC83F0007E41FC92FC9FB399F6C6DE8
+:109B40007197E1F7AD15CCDEAAD1477A7F09E78995
+:109B50007EA794EB590E5FBA13E30086D016CCA310
+:109B60009072B871FF83A363E5B949396C3572F916
+:109B7000660D26055B35F4857B7BC913E949793B86
+:109B800049EB63C745463979BC6EA879112ED4E5F7
+:109B9000286F762505515EC93891BEDF4CA7121596
+:109BA0008F917E0BEE2F60FD3227B7434A9C9C2E8F
+:109BB0006F72CA786C30CAEF711BFC27309F289EE9
+:109BC000FE92EDFE52712B398ED4A37AFCCBFD119F
+:109BD0005C4F5551FC7AED07B97CD2D3E37C617FB1
+:109BE000A5E25AE17F3F17FB5983F1CBFB6135C6F4
+:109BF000A8FCB73643576DACF8D7C10D222F6ABB0E
+:109C00007148F9753F17F5BF27F2BFD85263543E2C
+:109C100095CDE36EC1F8E9841E77B14AE3F2385678
+:109C2000F274F629EAE194A9ED63304FC9E98BDEBD
+:109C30001FC9AC498CDA7FC8F6A74795736B73A22E
+:109C4000EA0F6B1E11F57DF8FAB151DF0B0213A379
+:109C5000CA856DD745D51FD53E33AA7CD5A33745D8
+:109C6000D5BF3A383FAABCB5A5B306F172CD9E5B0D
+:109C7000A3DA4D30860DC5F07E5CE78AE83C311DE5
+:109C80003C67FE518D49873F7016103E27EC8B864E
+:109C900047EAD46878605A1CF697CA447F897FF0F7
+:109CA0005C2E8F3595193F0BCBF60583E98159ED75
+:109CB00025DAFC8308FD04A3F2DF661A55DD3C02B9
+:109CC0007F12FDC59BA7DC5F8BBB8E3870DB27E462
+:109CD00084848B492C2B757ACD65E162BA125C586D
+:109CE000D83314B8E8F7F706E2CDBAFE3626355277
+:109CF0003EF0DB58D0D8C761C147B2BC2890CAF546
+:109D0000906FC115EC681E07F65BF8FEA4FEFB45DC
+:109D100021D79C300782CF10F9FA7D8187E3C8D71D
+:109D2000E870EAF97AFDA78733517E5732F29BED4E
+:109D3000CD2D9FA2DEBAC31862C530EFED623D8F14
+:109D400008B9F0E8063BF5F398D87F7C7C839BDE6E
+:109D5000EFD830869EC10D1E7ABF6BC3547A7680D1
+:109D60003D87CF273754D273CF061FD57B6A430D6B
+:109D70003DF76EF0F3790DC2172B253BC7971133D2
+:109D80005EBA3CA00E094F4CCD8BA92FE3F6A32E53
+:109D9000BD6C1EF9FAE34BE6BCA2E11B8B2BD9414B
+:109DA000FB9953D814DCCFBC52FB8B1B6AE6BC3248
+:109DB0006AE87C24E9897D9931DA17237EE417F972
+:109DC000936F3B2F6E0DD8E2C32B4267B1E1546D08
+:109DD0003D9F83CEFA78B41934ED8FE9F8B8DA9F55
+:109DE0001AD36E287771FAACB1F0FDF7253AFEEE82
+:109DF00010DF3B5CDC2E7C378E9CB9CE6510FC1FDF
+:109E000030D17EE020BEFBDE0DB1E0DBED7247F12C
+:109E1000F112BF0EAFBA7EDE35B50FF3C4E0B32B3F
+:109E2000F523D7A76FB7C9C5E5D6AEFFA3FCF9EEFA
+:109E30009DC9E43F20DC9C9AF5BF7B67524DACB8CE
+:109E4000CC5E17DF1705EB9C15A493A91F30A3ADBB
+:109E50003886B9F93EEF483BC687641E407C7A35A8
+:109E6000521C8960A80E862BE0C36D2E84FE8D03E4
+:109E7000E3848C388EC710D16F9853C334E73CD439
+:109E8000C1F400ED0366CADF09E750DEE357A427FB
+:109E9000A63E3EEA72FB7483DA7F4539B3FD6B96CA
+:109EA0003392CFD9970F8F8AA5276B50CE5C07646A
+:109EB000E82AFE6EA0E8CAFD7E55F8D5A861DAB79B
+:109EC0001E32FCF6398614975A6F4D198FC6D5C5C8
+:109ED00004FE0CCC64FC3CD6FB0941B4F343629E07
+:109EE000E0F84FE07E75F3147CF664F90EB9A0FD3E
+:109EF0000A33F713F35CDE975D502F51EC039B336D
+:109F0000CD5BF0C9EC7C1DE3311F14BADA6270E757
+:109F1000E33A3E523C57A39F6237043DF84C61A19F
+:109F2000713CEF2EE847FF2CE39A4437FAB789A338
+:109F300019EBA578B82701E366E6A4F05B23D19F6F
+:109F40007DD148F1A1F198CF06E5F17F9F1B0C90E0
+:109F50003FE726F99021E0B615ED70683F8FF9DFF5
+:109F6000C5F99EB65B030698D7C3951313301F2A15
+:109F7000B4470D98F1BC42EFB9BFBB19D63DA1570C
+:109F8000A538F30436E9F59128577A4DB4DF5B67BD
+:109F9000640F21DFC483E7D96FC6CEEF2ACAE4720B
+:109FA0004FE66DE9BF2789EF67E3E411FF87D00B28
+:109FB000323FC624F3639CDECBE6C79874F93126A2
+:109FC000A38FE13EB069203F6629A3FC18E8479BB8
+:109FD0001F737666EC79A8997C1EA62F92E2F49BFB
+:109FE00042EFCF8EB8FC3A4D5F2444E55947DADBA7
+:109FF000E87DBCFC9C3C09A738F9495903F3CB66C2
+:10A00000810C6D3B4EBF9171F2E8BB4997E713F9A4
+:10A01000CEF37B36A5713A399865772C87AE97B326
+:10A02000B009E9F40E9BC384F1231FF374D1B91D69
+:10A03000A3A93F2CF96E04D6337E8076B601242D79
+:10A04000DAD977AC377D10D6C8A92A6F7499617DAB
+:10A050008DDC5D9FC568BE8963C7505EDF05E64E37
+:10A06000B55F466E2EB5AA56A366BDC7E3D80D7E72
+:10A07000019FE3D9B1E13727D31095A734B87D4AC2
+:10A08000D479B47BED979797085F7F86B67F3D1EA6
+:10A090001CF4FD4A7076B672FEEE2F5378FEFE5F1A
+:10A0A0001CDE69229F8D9F0B30E9F2D0D767B9394A
+:10A0B0005D0DCC9BE7A1BF6CF7ADC8A476EED1DAFD
+:10A0C0007300DD466FD244781E1772470F973D022A
+:10A0D000CEFA75778B7CFA4495357769E0AF5FEF00
+:10A0E000E3028FB2FE2613DFBF823F9F15F0B28CD2
+:10A0F0007139DB9A3942E485A719511E2EE55DB00E
+:10A1000065F657693F49C27910FC04DCF570F431FB
+:10A11000F7ED98B77D25782E3F9A6846B97FBBB595
+:10A12000FF30FAA6E15EC33B23E179C236F2640751
+:10A13000C37DB731CF1F62180FF1F0FC09368BECED
+:10A140001C2590AB5EBA66E876CE9614FF18E48BB9
+:10A150008F44BEB5D4435B72CE8CC6BCF9D4F4B286
+:10A160009A2C27C5DBBD19483FBFB670FA79147A1F
+:10A170008272D381AB77A27E69C9F22FCA9A1CC9B9
+:10A18000DF63DEFED1987FF055E1037F26A49F2B8D
+:10A19000C1675B26E37C98129B3E8EC4A10F3D5F96
+:10A1A000D0B9B292AF8F2F243CE57E859CDFA22CE4
+:10A1B0004E7FF229E1A6CF1B5A946510F5B8DC68F2
+:10A1C000C9F2119CFB867D7A3201E67E5C97E73509
+:10A1D00020BF86B87E09EFAF4BFE1E4F8C3DBFFE01
+:10A1E0004CBEAEFFA9F92D91F31B1F7B7EA6ACA13F
+:10A1F000CDCFC7FADF4FFB1AF417E07909E2996D6A
+:10A20000EA27B9783C3DF63C470E799E7ED3D7A12C
+:10A2100067257DB3C0F25ADAA7CF4A8CB94FBF0881
+:10A22000FC26F47BF4FBF5725F1EE407ADB7DADAC7
+:10A230007F7B06E27D9658B78B85D2701FF38085B1
+:10A24000E2FEFAF55F23D60FF02A4639C5E6F6534B
+:10A25000FCE2F8E8D872A1388BF3C540FD363E4EDB
+:10A26000BC7305D70AFEBCD2B90256E2A7B85F9903
+:10A27000D51652010FF7087C9873D77AD02E2CCBC5
+:10A280007AE318AE13E07F6E009E9A3CBE331B8EBD
+:10A29000D8479AE2CBED3AF5D9D2E618EB99E7F434
+:10A2A000CFC5750CD4DBF3BA7DA4065FE358D8C0E4
+:10A2B000CF45F71BA2FCE14CF695FC61AF95F34B43
+:10A2C0006ABA8FF401EA07D43B5BF65F5B8CC84443
+:10A2D000FB02F378FA9313498EB6E65C37C6AD817C
+:10A2E000676396B45BD538F6E29F97F71FB19794F2
+:10A2F00028BB35D2BF91DE4BFC94D9FE5F4C7CCCA1
+:10A30000737AEF453A1C9DEE5D874F3DFC020F4C82
+:10A310004B23FF18E13723D2DF00FEE3E0F9C74EFD
+:10A32000EF77B0BFDBC4F91945E6EF0DC4298CF611
+:10A3300093D608BC878A97EFE13FC03FDD91E5DD0A
+:10A340008A78315B043F321B9D0B97F60AD3D935CF
+:10A350006C2ACF275D96F5C61F30CEB32585B3ECAA
+:10A3600096EF24505EDD1D8ADD8CEB06FBE3BD1FFE
+:10A37000417D3F0BBDF76DDAC7927646927A296927
+:10A38000E8F3947EF295F2A80FA11D06F39969B047
+:10A39000D1BEE621209B6C901B33CDFC59361BA807
+:10A3A0000AFA9BA9E6F584615E9FB373E93740EB37
+:10A3B00044114F5C77747202D2E54CA3E98C566E5F
+:10A3C000E9E31C5D59D1718ECFD9DCEFD3DEEF18F4
+:10A3D000EEEF3F3C7766A636CE3210E710EB581012
+:10A3E00058CEE5A94ECE497966B0F2FB439897B9AD
+:10A3F000ED2E8A1771B883736D84F20DB28CCE097D
+:10A4000094A7092429D81ED67D8378B215FE2C94F2
+:10A410003398BE83E381D79785CFD66B3D6E7CCED4
+:10A42000507C463E8F20CF3764CD7958DF600DAB2E
+:10A43000FC5C1ECCC085EDE578BC9C2CCA9BAA2F89
+:10A44000DC7EA77B70FC82D992C9DE358B799DB604
+:10A45000DB0206786FB1854E535EAA78EAE31C17DB
+:10A460000D8100E6657F4B0DD27C935828D48B710B
+:10A47000092B80C040F1831348A7E0D534E23C1398
+:10A48000EC1742DF6698DFE855B09CA1D3474EDB5E
+:10A490003ACA7776FA8C3A3DE457906F326BF4EF14
+:10A4A000A3F593951DA773404AC8977529E3CA7110
+:10A4B0001A7D7CC63493A3B87F0DB77BDF49E4EDEA
+:10A4C000245D28D95CFF34A69B19E5B9B8AC56B415
+:10A4D000DBCF279FC2A396A837DA506F584D5E8214
+:10A4E00087D41F0DDD7733C44FE3BE2A86F4FA4FBD
+:10A4F0000ADFF70C2C53283F41DED75053C4DE84CB
+:10A50000966C59F6086AB7F0887F593D94ABDF60C6
+:10A51000E34250AF7886AF02EF65691DC73C1BA1CF
+:10A52000DC9AE07FE697B89EA32AF5D324CEC33207
+:10A5300066AFDB0BFDEFBC7598672B2EA9BC7F0BBC
+:10A54000E6FFF43FC8EC982F32884EBF84F501FE39
+:10A550007F82659877D32AFF13F741FDEC37988700
+:10A56000EA88EFE88B20DE14410FF87E06BC6F12FC
+:10A570007453D8A3F07D7B8785F226D8B14CE2973F
+:10A5800085563E4E534FD9BCC930AFC2DE4944C692
+:10A5900023A13EE635616601CFAB63E427EBEB8F89
+:10A5A000C4FA6E8A52F17C9A1C33DD7BC4849C9B76
+:10A5B000A2E3B7EB23F44FDF8B45B949E8A3283E6C
+:10A5C000C17EC02FF796F26D7C6AE7E0FCE061F295
+:10A5D0008FF3ED752CF287FD9647C621F93B4B7C36
+:10A5E0003BBC640EE5734F31860E225F5F2F9EC524
+:10A5F000E2897C6D05382E36361F76C27AD2D63384
+:10A600004F0B8EB2D4DD8AFD95309F8A702EB53FF8
+:10A61000D88AF3BB76E9D10CA4AFEDD985447FD3BA
+:10A62000AC9EC2042091D6A91E8F1D5ED52C550864
+:10A630002E0B6BAC41CC5B5B38704F8FBF6011F061
+:10A64000CD62BF22CECFFB0B966AE2B0329F6F91F4
+:10A6500005FCE718727A7B36B78764FB2671DE4407
+:10A660007E6FCFB6D1F76F66DFB82C9BF22A789E4B
+:10A6700033F0BD3F7B72448EC0B89487B280794D71
+:10A68000B8AE05826F25DF2FF4DE4B76EB425FB468
+:10A69000FDF94F0AC777608942F6E0E29ACBDBA763
+:10A6A0004DD9729F37CF7E3229F25ED29594DBF37B
+:10A6B000518FA3BCAD04BDADB18F977EEBCB346A97
+:10A6C00097F964C3A5E191F32D4DBAF32D8DE27C8A
+:10A6D0004BD3BE16930BE95D9C6F69EA39B1459B7C
+:10A6E000D727E134F87C4B3FE5332E32070FE2B930
+:10A6F0009F456B618D50FF65711EE2153C0F313136
+:10A700004247C9B7268478BE9C97F2F6F2EC491E00
+:10A71000CC3369334CA43CA1B694648F362F676B5D
+:10A720004B7305D693F941F23CCBA238FBC08F673F
+:10A73000733BF91185E76905965809DE4E951DD3DF
+:10A740009ECF7716FA283F6E59B69BF0FE88882375
+:10A75000603EE9247806C11CE3F8E2EDF5F201FA67
+:10A76000DB84FD95177A282FA63C95E79739337C33
+:10A77000C5F71445FAADEEE1F978D5BE4F5FE5793E
+:10A78000B55525084FBD3C97F4A597EB407F9D48F4
+:10A790008F170D5CEF44E4BB6FC99DD05FDF9B66F4
+:10A7A000CA9B63F77B1513B47BEE75BB07CFD16DE6
+:10A7B0002AF35555D077239DF373D5B09005BE97F6
+:10A7C000BC61DE85F97AB5ACDD8CFDD5EAF4D65AEC
+:10A7D000DB2B66E4CFB51DA6083D32CC33F414A2C2
+:10A7E000A0ABDF3B28EE41F247CA253D1DB391D116
+:10A7F000F2A758CA5B900B5C5F2DE57A8E3DA9608D
+:10A80000FCA72FF9942AFC67927793A590D2C9F9F7
+:10A81000C93DAF91BD321DE403FA670A96C7537D67
+:10A820002A83FC1C8379A3D7B344A2AF41768298D4
+:10A8300057C9C0BCB93D24E562D9546E6A4ABCC050
+:10A840003844CF729F6E32DEBF03CFEBC5B8DF3224
+:10A85000788B420AE289050D856847F8C9DED1DBAD
+:10A860003FA5D6E6242BAC6F2A6B27B938E5F02B31
+:10A87000242701CF9FA09CF9359378F65851CE54E8
+:10A8800060C29F8ACF683CCDB66D37229C6667E96F
+:10A89000F11130225CE7B807E189CE0778E3E0C91F
+:10A8A0002BE5088B962305EC4B7E1EF9C157EF4331
+:10A8B000BFF74A76C821A7DF9C43F233DA1E899797
+:10A8C0004F979A63137EEAD0F2E9FA4CDC4FB88EC8
+:10A8D0008557EF5506D3C5F9C3EBD52C0DFD48BA06
+:10A8E000DC2FF2EB959744BE6E4932E9B9885EE4FD
+:10A8F000F82F15A5EB90AE34F8BF615F4248057A9A
+:10A900002B16EDAF437A9818D18B2183CD6D8671CC
+:10A91000B7289E363506DE5DE96ED27F930C5E95D4
+:10A92000EC29E6C9403C03DE8B105E53AD9DAD467D
+:10A9300098E749B3E747E8AF943137E1BD4CA75FEB
+:10A94000CA6DD546E4CF72AB1EBF5EC27B857DD09B
+:10A950007BC39F82F7E18877A93F86607F02DE2B69
+:10A960007262EC13C6C3FB2D7F22DEF5F8967CDF06
+:10A9700095602FB7615CB796E7114F7A73642B9699
+:10A980005D0D0574BEA52BCDF3327D6FE6DF4B7AEE
+:10A99000BD2ADE9B58B80EBE43B9ABC0578EE5A6A4
+:10A9A000F50AC9CBC96FFB5BB13CF27EFEBD786393
+:10A9B000F3CB78FF585380B7DF7F7A0BDD2311DCB0
+:10A9C00022DA97B59763B9A98DB7FF38D91A40FF36
+:10A9D000BAF458B015DF5FFD109F87B4EB66083AF4
+:10A9E000EB529E7D99DAB5F37677BD6A4DE4C96E78
+:10A9F000DC4E9B2ED639E371BE4EC7873755BA81E0
+:10AA00000EEFEC0F98900E4E1AEA4B495EC6F1B766
+:10AA1000CA94F63C7CCE06B9C008DF409F23789EDE
+:10AA2000E92E18626B0EB78B647E26E6895769F0B3
+:10AA3000B53587FB09B29E2B9DF17CE2C792C96EAA
+:10AA400095F9A3A11F3205E300B846D2AF71F249D0
+:10AA500067173693BE9C3D5CE691868D2B60DCE2E9
+:10AA60004BFF7A632CFF7A9B18F794C87B97EF6BA8
+:10AA7000830506F43FBA9078E87EB5796FA25DD27F
+:10AA800085FBC19AFB41BA0A78F9C78FDDFCB76D27
+:10AA9000E0ACDE6568360650E8E72B74DFC92DBDF3
+:10AAA0002C949A3278FEB38D2CC4F31DF8FC57B762
+:10AAB0009A776DD5D8E90BA5D898368AF448B5C0F1
+:10AAC0009394170B05BE80BFF7207F2FB236935D9E
+:10AAD000B844C8F7352C48718A353AFEAEB37DF6D6
+:10AAE000BEC180F1B0683E6E80E970BDD0BFE35D4D
+:10AAF000807FEDA3C976D4F30D9DD1F56A1F7DF358
+:10AB000018B7AFA2F9BC56F279309ACFF1A649E254
+:10AB1000F31F8EA5FD17799E2FC1DAFF7E8045D6E3
+:10AB20003BA0DF75FC9780E7FBC6A0DF62E079857C
+:10AB3000A22CC7BDD0CEF57000F4B0F07348D45E3F
+:10AB4000383E2788F4502CF857F271B1D0E783F4DF
+:10AB500075A5DE8FD94EFC31499424DCA57E867E16
+:10AB6000483FCBF382A097DFF4927F0FFE27CE738E
+:10AB70006C34BF6C55403E1744FC15C0DB3F23DEF0
+:10AB8000401E5B799CA29DA13C8B6BF7DBD6C5B4C4
+:10AB9000FBC18FA07D80C1F67E28CA8ED7E32B9E95
+:10ABA0005D3F80AF04B09792D08F67242FF7E17399
+:10ABB00008F91C20A7FF3D967E361FE2F5FA77269E
+:10ABC00050BC40C6C725BFF5E572BBFA57595E9623
+:10ABD0008BFB57A2FFE377CFA67DEACF9897F6A924
+:10ABE00031CF2837469E04EE536FD2C4498FA7C594
+:10ABF0008E5B27E772BFE71BB97C5D794E6F4A2EEB
+:10AC00003C4F99795CFC54A278A6F07D85EC81FAE2
+:10AC10005C4E4C10E55322FFFA547A743C5DD62BFF
+:10AC200016F53EDA60B56ED2C815F70F2DCDA8AF78
+:10AC30009C85225F7D1DA7D7BE17D2766AEF699BE0
+:10AC4000965BF60D9C97B3D06BCEC638CB0B5C2FC2
+:10AC5000341AC366CC2BB9C1E1BF0AE1D4E866DE81
+:10AC600067B11F77D8BC00E0DC27F6E7FB4CDCDFE0
+:10AC7000E84BE04F39AF69B955DFC0767D7787493A
+:10AC80003E0C94ABC2C4FFD3727D346EDF42F95DDB
+:10AC900094FF969799F00FCB045F509C37465C77F2
+:10ACA000701C37FADE992673EC7D6596971C159F0C
+:10ACB0005DD6C3E386B75BD9965CF87E474F26F92D
+:10ACC0000FB52981D1768AE3FD7971D7BE61BDB414
+:10ACD000AEAD65FDF98F95D03E2EC57D1A7A5E2307
+:10ACE00039D720F9A43B9A4F96E40E6DFF431F1706
+:10ACF0001F02FFACC88DC13FCFA37E3245E07F8FDE
+:10AD0000C877AA50EBCB312E746115A373AFF7BC93
+:10AD1000AE123DDDF38C42F74048FBAC41C037DE5C
+:10AD20007AF0DC805B233FF0DC805BE39FE1B901DC
+:10AD30006D19CF0D68EBE3B901ED773C37A0FD8EBF
+:10AD4000E706B4E562B6B215E36C4D6DCC1E74F344
+:10AD50007304DAF6788E405BC67304DAF6788E40B8
+:10AD60005BBEC0381C2F3CAE529C1ECF1368DBDF8D
+:10AD7000F5FAA42CA49BEE049E3FC602DEDE2280E0
+:10AD8000CB2A01173C67A0EDEF6CCA8D4718D0DDC8
+:10AD9000AADED573F13961DFDAA8FEEAD47AA243DC
+:10ADA000D6CEE56E33FC47F2532D52711E9FEF5302
+:10ADB000584601DE1BAED39F3DDBB6A0E859138C8D
+:10ADC0007E5FC734F1DA82C171F98EDC64C7499EB7
+:10ADD0006B9CA38DD344E8C0E609E1FADF563DB190
+:10ADE000E8A0985D954AF199232AC61ED8C7ACF908
+:10ADF00091698A267EAF8387252B9A1E12DCD1F4B7
+:10AE00009034269A1E923DD1F4903A359A1ED2BCC7
+:10AE1000632F0BDF8CCA68FAD0C3772AFC87F09DBA
+:10AE2000883742625C09D68971DEBF147C7B75F07D
+:10AE3000FD9C4D2BB7B9E973B5B534629F941C697D
+:10AE4000A64D5A7DDC53C251DA09327E3999713FE1
+:10AE5000DD8AE72C0BD10EE0FE1BEA7F94AB27CDF9
+:10AE6000DC6F430A42397927F3933CBA53A7FFEFCB
+:10AE7000B26D37A3FE1FB45EB0B8F0BE40FD7AD10C
+:10AE80008E629A78925EFF2B3D4A28793C2EB74716
+:10AE9000CA65FF253276BCCA50E4C5719BF7739C26
+:10AEA0003F3A7ED6D2A8786F4C7B4ECE43C2458EB9
+:10AEB0006F61CD6A16D2F318BDFD15ED2F4BFF9AC9
+:10AEC0003AD5C4A3A57F2CFD133D9CD5E10564773D
+:10AED0004DB24BBFB8F7367C2FFD61BD1F7AA57D03
+:10AEE000A9050125FCA382883D7983782E10F122E3
+:10AEF00058D687BF87C6D314F7301C6FFEFEAB9CB5
+:10AF0000482F5B9466A69BDFB117A11FD5D09FC1C8
+:10AF1000E32FFEA8FDAAD79430CD7B11F36EC66750
+:10AF2000A388A73576BF46FBA88DDD3C5EC0F645FD
+:10AF3000E3456FEFAF659DE60265B0BD5FCF7AA9CF
+:10AF40003FBD7D3F884EAEA0C777E4C97B3B78BE4E
+:10AF5000001372A956C02B9E5F6044005F1BB9B7F7
+:10AF600013F8A12C6F72247FD6950E7E8C8A7918E7
+:10AF70006E73AC3C298697AA804DBAD2564D726248
+:10AF800065DBA0B88499F8A9FDF2EB9376C05FE584
+:10AF90003182FB883C37DF874A9C7BC48B9F4B7A8E
+:10AFA000F3B5E73E9ACCFCBC216B8E3E97BF3ACFFF
+:10AFB00020CF4DA94359FF60B8FE69F9F832FF0070
+:10AFC000E0B7460B3FB98F20D7F3C9E4DE27317EC7
+:10AFD000A826CFB2A25F9B9AEE6FCA73E2BD0CE1C6
+:10AFE000930ACA339B9BF243CEEF3BFD0EFAEF72FE
+:10AFF0007D8C851FC17B6D6BF7A9E40FD6EE7B9925
+:10B00000ECA2F8FE5EFBC0FD09627FE37E1C473FB9
+:10B010002F99CF5CA116A5863576FABC3C1E0F1879
+:10B0200035DCB711DB95FC2E2F05E76B1AD149F7FC
+:10B0300061F5DFC7ED6087CA6621FC40EF71BD6F27
+:10B0400033D2BE832329A0A6A01DB79CF1FBE73C09
+:10B05000CD1E2415755811C5695DF7A93EB4BFDF33
+:10B060005BB7320DCF29BB9257A515C2738685DF1A
+:10B0700047E3520C3E7EDE74451ADEFFB1CCC2F7C8
+:10B08000E50BBE99142A047E7BC9CCEF197524F90F
+:10B09000E9DE82FE3495E67366032C6D14EE7B7C4C
+:10B0A0003609EF1BC8F9D23611E7932DEEB3A8CFBE
+:10B0B000E3E7B7CF3E737112FAABEA251B9D6B979E
+:10B0C000F4E7288CEDAFCC17F06874F27CF7F3C28C
+:10B0D0007E3C2EF65B65FEFB3AB10F787CF4C0BD7A
+:10B0E000604ECC0B694CF0A62EC678C451156FCCBF
+:10B0F000609FD9BDA9696437F33CF675C27E382FCD
+:10B10000F23DD7CD999989FE45BC3CE997F2B8DD6F
+:10B11000FB75DD5329F34EE3C221CDC88C13E8BE85
+:10B1200025DFE5EABDF84735263C4F8AEFF1F2E529
+:10B13000DFCBE37E9BCC876FC47C7878B5EE85B29D
+:10B140004C76993CE946BC875C935F837E1AAEAF30
+:10B1500011EF21A7FB49CFD1FD1CD80FDE1776A533
+:10B16000FB22E70B3837621E7986F6BD9BBF1FE8CE
+:10B17000DF41DF9F12707BEA88A172578C79260E1F
+:10B18000E3EB1EEB34FA705FF29A10BFEF335E3DD3
+:10B19000797E3BDEBCBA67866FC779637E66ACF1A9
+:10B1A000BE147094F3ED4E0FAFF6F1FDBCD155C94E
+:10B1B0009AB2BD3F7FBE46BE4E11F8E9BE299C4FF4
+:10B1C000F700CCE1FE6B3C3C971A9B1584C31769D2
+:10B1D000FE5B50FEC97B8AF11E639EE711B82CBE50
+:10B1E000237056A3CE1D0C86B399BECBFEA4DC39CA
+:10B1F000FDA84A72E7F45B821F99D7A694A2BEE22B
+:10B200007C759AF1B8EEE976FEBB1F2BFC607B8261
+:10B21000FC58DE5137177FB763F5EE495B50FCE30E
+:10B22000FBFB41FE2CCF626C3A3C576C8ADE1FFB65
+:10B230009C3D447A6ED5437A7DE633A39C5DBD3D4B
+:10B24000BA7E2D7BE853B40F6A7576AF4BE85DBDCF
+:10B25000FDEB1926F27E4A59E95739DFF428F34EFF
+:10B260001946FA9FEFB74D16FBE9FAFA4FB8399C29
+:10B27000EFD9FDAF66FC29A078FD9E01793112FA65
+:10B280003DB7C14ECF6F0CF3CEC4FE970DF3570CF4
+:10B29000C338C4510EE70BF51756535CBA86DB0171
+:10B2A00016BC5C05FE69B9CD4A7EF40378BF18C0B0
+:10B2B000D962E1F685B4AB54F55E3505BE5FFB2F70
+:10B2C000ABD2707D8EA76757A2FFE17C3AC98BF89D
+:10B2D000D85AE62D46F9BDB5CA46FBC43B0DFCFE67
+:10B2E00041AB85EFCF059FBAF610868347766E9BFC
+:10B2F000897E86BDE76008E3126D06BEFFDA369DE3
+:10B3000089FBABF9784D3D555D38AFFC6A90F7D0BD
+:10B31000DFD6026FB15DD33F13F652A3C045DFAF56
+:10B32000AFFA3EDE77F5A32364AEC23A4750FC6B1A
+:10B330002CE37423F34BE8373134F1A273A07F98E8
+:10B34000E6DCF3D84E25644AA17BF5288E5DBF313B
+:10B35000E4BA0DF5E7CFF87EAD9C9FE3A5EC991814
+:10B36000EF97FAF436CC6FC338B0B07B9730F9C79B
+:10B37000F70B6A045D2F11F6EE6D491CCE2B9887F2
+:10B38000CE5DDD6A6529185FBEADBC7332DD7B5DC5
+:10B39000674A437B45C6BDE3E13D5E7CA6F1C964D7
+:10B3A0007E4F8ED23F1A3B398331909248BEBDBE4C
+:10B3B0009F8787097E1E2DECB491CC8BFB2C8D07CB
+:10B3C000AEA27C7C4B22DF5703F96645BC1E467D4E
+:10B3D0000EEB5EF3624288EF1B07C57D382C40FB05
+:10B3E000310732695FC151E8A57DF7F3A6703EC908
+:10B3F00003905F0AE8CEBDC37A6FC1DF6169CC01FB
+:10B400003B0ACAEF3EF1DE2D46A0C7C611E1D57852
+:10B410004FB8B2E3DF78796CF82496937628F3A8D6
+:10B420003C31BC5A85F2E81DA9F3A83D3A5040587A
+:10B430009376B8E6E139E233227EC93C61BA1FA8AF
+:10B4400071FF55066D7C70783EB737CF24F07A6770
+:10B450000AD81DF311DE63C2A3B5BF97A0E61B98FF
+:10B46000F65E65B94ED98E65C5EEFF45A107D68853
+:10B470007B7D6624B1B604BE5F1140FBEA959EABAE
+:10B48000082EC161E9025E61BAAF51F6A33FD72F22
+:10B49000C75D8B7A1BE5BA29FA1CD191615C5FC04C
+:10B4A000389B689C226F31DEC7D3383FAF18F10656
+:10B4B000F8320A7C19B91FB893CF0FFA4D1B4F7A97
+:10B4C0006412E689BDF225D42F88CC5B4F1F6F0B29
+:10B4D000FA58D3CAF799FAD30A898E662471FB8F7A
+:10B4E0009500FC408E8D16F01D9E9FC6E13780872B
+:10B4F0004C85FA6F15F0CBE3F5BFEA7A4F7E4DEB42
+:10B50000D5E0C98B79C7AFECBB9AF024D7C3D8B6C6
+:10B51000A87ECEB4E8DA4DE579298DE985D4EE012F
+:10B5200071BFBEBCAF18DB1540BB19E5FD93901F82
+:10B53000E47D6D2C309D9CF57A212D06EE5FEBE4C9
+:10B54000F9296CA497DF43347F6E89589F5DACCF97
+:10B55000AEBD8F6E800FDFEECFAFD6DC472DDF0F95
+:10B56000C07DA0BFA289A2BF287E8ED51FF2453C18
+:10B570007C64E573BAF88BE143CE5307CF0138EB17
+:10B58000E627E1897C4CED8AA2F949CE3369008F28
+:10B590003A7E2EF813C713F9FD0D7F25F221DDD178
+:10B5A000F4DCD05D60C0FD53D9AEADB3C587725E2B
+:10B5B000C6BB2DDD5501D47F4D3D6594B7D9F0ABA9
+:10B5C000679E0F40FBB5BFF8410A26D39E36B6BB37
+:10B5D000D0CEADDFBD39C58BFB25C6400ACACFD35F
+:10B5E00041B532D639C0C67C45FAD16447350A7DAB
+:10B5F00073E6A9EFDE82F0F8B7DD263BEAD1A63D7F
+:10B60000969085E2206BC88E82F2095E7EE053F44C
+:10B610004B9BF645DB496B7FFA03979BE829906BC0
+:10B62000C0332E2C94CBE0D9D861F2841C3C9E0808
+:10B63000C3B026D6BF05E7A76F8FF3F802F0DED4BC
+:10B64000A92EC7F3BCFAEF2049C80E6BEAFE2ED92B
+:10B650005D4DDA3803E0A1368EDD75477E74BEB5E8
+:10B66000840B0B3AC9AE69FDD90FC79FB0E13D9A73
+:10B67000BF49518AB4FA7223C1E942E7CA1FEF7782
+:10B68000C7D7ABE7D12EB068DB71BCBAF729B427B6
+:10B69000C17AF8B3DE144A413FBF7EA7C9039A9727
+:10B6A000D53FF39327713F84BD6BA17B0FEA9E3991
+:10B6B000FCCE7550AEEB3239E6F2E9DB1457043FAD
+:10B6C0004D6E6E9F487CAC7DEE30DD2F88EFD1AEA5
+:10B6D0009578A9EB3A6866E306C3AFBCF3A0F8BD62
+:10B6E000051D7E3A4FDC48F778FEECA219E9FAF422
+:10B6F000018565160C6E5FBBF3700AD21FC209FD8F
+:10B700004B89A701BC0DC257E896FD25548FE21A5C
+:10B71000F1F0E6CD677C9FE757CFFC1C7FFFAFF6CB
+:10B720009F2C1E5C7FEDCFEF4DC1757C6C6CE6F4F9
+:10B73000FDC4669717C6AD35055C767AF2F7B53B62
+:10B74000EE23BABBEBE87D2EFE3B1ADE6CC3545AE7
+:10B750006736AEEFCEC717D2FA56333FD15DED1341
+:10B760003C3EF1B9F81D063D3E4F0AFEF87897853C
+:10B770002E2DFA1813D1318FF02D55E4F9DECDB40A
+:10B78000F75780C54DE5CF457CE0C5017B805999D1
+:10B79000262EDBD4F1402FE2E7CC306F26EEAB0152
+:10B7A0001C02025E0ADEABAB1EADC8E4F8616EA3FC
+:10B7B0008C2B83FD5D8EEFB17EAFC99B303EAA9D81
+:10B7C000D8AFE7E3CBF804CC3B11F7FD3E76C53E9E
+:10B7D000B7E5182EF99FF5322D7DC5E3F78E078961
+:10B7E000AE3E7B9BF34D63B0AA92BEF79A4278A41B
+:10B7F000B83178B05A21796089BA6F69802E3A4C95
+:10B80000829FA3BFC33C8D8A16BE07785EEDEAED2A
+:10B8100096A87B102274638EBC2F88F0A7F4A3EE49
+:10B8200012FCAF5FAF5E1E9CD0C903F6B87348F739
+:10B83000C9D49B824F3E86FC0BFC8A7E66FD332674
+:10B84000F2F3CFEE7DF99D5B81CECF764ABE8D9629
+:10B85000AB7ABEAD7D76328BC5B7676D1E16936F22
+:10B86000E17D4CBEB545F669DCECEB93AB77C59159
+:10B87000AB89C3C57ECEC03996A254CC753FF35474
+:10B88000DD708A0BE8E02AFD59BDBCECC877C7948F
+:10B89000970CAF9ED2C051C24FD2E3DAA71B689C6F
+:10B8A00001BA957429E976802E07E55746C151FF04
+:10B8B000BD57C8A38173431BC14F413BF6D72AFD37
+:10B8C000FE491FCC650BC0BD6F6F01ED836E167610
+:10B8D0007E9FBD3F05E37A9B855FD18FF1C4D4C8BD
+:10B8E000FBFE049137E0EB4F49D3D845277AD414B7
+:10B8F000B4E3C2C1D8BF232BEFA70CC7F99D597978
+:10B900007EA942B5E5AFC7386D3BDF9F5CD5B23845
+:10B9100005E3197D3D85F43B4277BE0EFE2ECCB784
+:10B920004FC635035E637669E45ED3532C40FB95C6
+:10B930002B7BEA68BF501F07596DAB4EC5FD407D9C
+:10B940001CE42ECC83C23CE4C7A3DFAFC5F808E2F9
+:10B9500049474F7EA4A7ECC1F4543D5CF065312B00
+:10B960008EDA7F1572AD422DFA3EDA277DE0B7639D
+:10B970003C88A945BF457DFA39FAF1C8000127D1B5
+:10B98000699DFF94CCB322BA9674A7F7DFF5CF7305
+:10B99000BF7CAF14CF03D53FFFFBF13F82E7B9E790
+:10B9A000DF1DFD22967FF58FF9BF6783EB971FF8A8
+:10B9B00003F92B7D072C349FBE03AFE57F1BCBFB28
+:10B9C0002D1E9C6FDF460BFF1DE803C974DF74DF7B
+:10B9D000301E676BFDF5C5F161D2539B7812F27092
+:10B9E0007E4FEC859EFF781FEF55BDD0637163DC01
+:10B9F000A1E94012F9E14DFB13E87EF8BE5F5F2C30
+:10BA0000D5C68BFEDCF5348AF3167DC9AC06F35B34
+:10BA1000FAD2B8BFD6F4E2B53F692940BBF420DDC5
+:10BA2000575CFED27F8E47F9D3F72CB72BC03FDF90
+:10BA3000819B88DF1DFEDCF74DD978DE88915F7D24
+:10BA400095FB33F2AB07C385C3A10FE080EB02B8CF
+:10BA5000D03DDDF1E0B1EB7F2D3C3E257FA1BE67FF
+:10BA60000AF151042E0AFFDD919EE4A055A1F5F3E1
+:10BA7000F7072E8E473BE96C670BE9FD2BADFBE02A
+:10BA8000FFB9752BA1A1AC3BFCBF76DD9CFE570F27
+:10BA9000E7FA49CF0783E9FC57DFA4F2CF933D349F
+:10BAA000DF21F23F6EBFA27CFFEF5EFF7F01F65207
+:10BAB0009D150080000000001F8B080000000000A2
+:10BAC000000BD53C0B7454D5B5FBCEBDF3493249C0
+:10BAD000261F2008C19B2F51F2194802E1A7938429
+:10BAE0005050C409488B157000955F4822D89A566B
+:10BAF000DFCBC4440CD4D547D5565BD135A0509E7E
+:10BB0000CF3E530C96564207540AADD5D142054D4F
+:10BB1000E948AD480D6404157CA5E5EDBDCFBD99A0
+:10BB2000B9378988ABAEF55EB2C8F1DCF3DB67FFED
+:10BB3000F73EE7586F035F8713A03711E6EF28C47D
+:10BB400032053C900ED0F0E2C4A75AB20056777E80
+:10BB5000B408CA00EA764F0019EBD5BFFE477198CA
+:10BB6000FAEF903CE27B62C021E1F73D9F89EF7BD9
+:10BB7000CE1503961FEE90827212D6EFB32F0FD020
+:10BB8000BC9930BF03CBD6AE73C5612C01DA00CAB5
+:10BB900001AE546D5C9ED9FDF763523A95761570EF
+:10BBA0009D863D0940F337FC2A2E00387F6FD7B9B8
+:10BBB000F13E9CF722FD5C0BD0D38C538C8ED6CDFE
+:10BBC00065CFCE3F8DBF07BBD4BDF04EF1E358F635
+:10BBD000BC7034FF45AAFFE2AD51EF60597FC97DCB
+:10BBE000EFB52DC5F63BAE5419BEE8BEF7DAA08816
+:10BBF000F67B7011F5EFDD93E8B267117CFF180555
+:10BC000031FBBFD4BEAFF97FBA6F003FC01000ABAD
+:10BC1000EC7564237C0F4230A462793FC08C0E67C0
+:10BC20007F785651E3101A0721180A2083F891D320
+:10BC300057CE82242A377C2417D3F83933B2100E1A
+:10BC4000BF6A716F55A98785F1D03ED21DD880702B
+:10BC500081E25DBE19EBD62BEBDC1B78863B01C67F
+:10BC6000037CCBA1CD3774D60C09E76B6D41B8705E
+:10BC70009ED62116572BCEA3A896A0BD98CB77A908
+:10BC80007C60E87507685DC56983A036F622FE739F
+:10BC900002D60BB43AAE179F1B53C77F71B0CFA526
+:10BCA000E0FA716E0502B8253BC48CC7FE33551708
+:10BCB000EF331E027E97F3F2F1F4F825F064C68F9D
+:10BCC0008EB77E780270D07885FE8BF69FBE2144B9
+:10BCD00072A880E20F8BFD481725C2A73BC381F3F2
+:10BCE0005993EF706F90F8BBAA8CD7C659E8CF1A5A
+:10BCF000037E117F9EB8E2289E63E6E3FD9BF17C04
+:10BD0000B9F8D5E912077398CE71239DEE00C27F72
+:10BD1000BF2AF07E3FE25D92A2F8D5F166A6433DD0
+:10BD2000F14E7914FFD1728AEBFD314C48B888C8C6
+:10BD3000F557414123CE53234F09FB71FE331509BB
+:10BD40006E3BC98B0441691C969543AB00F7D193B8
+:10BD50006953A89C1AC13DC5C07BED79072831FB0A
+:10BD6000AB841443BD27339FC7573B861BC6F50CD6
+:10BD7000AF70D0F71A5796A1FFEB7149C55042E357
+:10BD8000A6CFA0F6AF655C651837FB78CFA6C5587F
+:10BD9000DE2885CB88397A0E2EA8227CCD54C71A8E
+:10BDA000FAED42B542F21CA991035B101FB5527027
+:10BDB0006831E2EDFA828946F8249846FBACB3205C
+:10BDC0006B61BF1BDC9586F61B2B661AE6ADF5D4BE
+:10BDD0001AEA754D9F82920630B9E90228A50063E0
+:10BDE000831D86F1A5077619FA27BD0A722296638C
+:10BDF0000FA9AD5496768752897D6D690EBF2519BE
+:10BE00005938ECADC6EDC0F80F1A5FA2B2C981F87F
+:10BE1000C0EFE7E24489F4623EF71F8B0BB422BC0B
+:10BE2000E72C011FE1E16E39504065FC883B8A2117
+:10BE30001BE064C6837232C10FBE632AF2C1C48F95
+:10BE400003AD54BFF64287EC233DBC5DF6DB4A8868
+:10BE5000EEB3127E4F7AB74302A27B9DD3E20990E4
+:10BE6000DD4AED285E1BC35F1F7E1B6EF516F6973D
+:10BE7000D74D7995119ABF2DC3B3712FE9CDAA3F44
+:10BE80002D92B3FBF703971209EB78C9A671DEEC8C
+:10BE900091384E4E9CE620BD1E5F2DF3BEE06BD662
+:10BEA000C0569C679DC51DA7093FDB57D774EB663D
+:10BEB00092EBF62CA11FE27F07AA84F0C7A7F9E452
+:10BEC000221AF71F126C85E87A4B2B80F791926546
+:10BED000117CAFB8862C2CA2F1895C1F5F21F00881
+:10BEE000B32C813C9C72EFD413FE44C443FC8D966A
+:10BEF0004CB4409054E1F95D2ED6C787DECC94490E
+:10BF000096A0C042FA640DAA37D227C31ECC7A7419
+:10BF10001F8D3F60853C2C962EF09CCDC5FAF767AF
+:10BF20005940C2F6CE8AAA84A218FC259D97402DBE
+:10BF30008DD6DBB3548623490903C971D27985DBD9
+:10BF4000A129DF42FA465F276981FAD6DA9875405F
+:10BF5000F1AC22B8375CDDAD92BE4A3A22F6091048
+:10BF6000CEF0E2D6FE86765125422AE18C8589FD07
+:10BF7000E9F0B7EDE5292AD231ADD29DE2A6F2670C
+:10BF800088E4498C673FA9BFEFD39F2BA8F6686868
+:10BF90001AB66F271D28DA83807CBCC1A6B5930A28
+:10BFA000C17A9AA4B5FB1FF54E233ACAC6FE25D91D
+:10BFB0007DFD3D8E8CE8FC53363F1A6A2BEC8FD703
+:10BFC000BD53ED6C87E3910FECD877CD5585C360F9
+:10BFD000003B11C56BC225F09A24F07A01B53DAE45
+:10BFE000739743ACF39EA48E22FE7AD882529F03AD
+:10BFF000F092CB579D554EF0078BE8FB9224CFB0C3
+:10C00000A9C86F9D36CFA8EF901EE98A736FC171E2
+:10C01000B5777EF85813C9F1ECBF15A007039D8AC8
+:10C0200027611CAED3E0FA94E5BF462E4C26FFA64E
+:10C030000F8FC4BFB8E6F72DD13AE983A4285E3D3F
+:10C04000B9D8BE2106CF0E07E92B51FFF7AC67BC6C
+:10C050006D44DFDB1C8CA7B59A0CB5A5C0460BF26E
+:10C06000FF59D7B6AF133F9CDD6E05F2933AA99105
+:10C07000EC638183E508D2C319B5C8F7456F58BC96
+:10C08000E48775237F78883F1AF30DF39D9DF25660
+:10C090006A118E3B9BAEA4127E56866D8CB7850AC4
+:10C0A00004EDA81F3BD36FABAEC4F6CE232AB777FF
+:10C0B00068F33C9BE7599EC576659AEB7DDC97E477
+:10C0C00099245F1C3338BDC862BEAFEB43C4730311
+:10C0D0006D3375703E68AB7404C8AF6CA8682924D2
+:10C0E0007BB026257F18E03E1AA6496C5F1B9A3E5E
+:10C0F00066BCEBF32BE76550D3A275778ECA7650FA
+:10C10000513CCC0FCA791BB7D7359D65BD8DE06416
+:10C1100091DCF4B408FDB6D10AB7D66259F74FF9ED
+:10C12000D65AEC5F872CC5F601F6D9D6C4E83FE8AD
+:10C13000F8A84FCF9720ED1E9EF5663CE9D55AC969
+:10C14000350F700F87B36DB5CA70ACC7B9E64958E3
+:10C150000F6CE9F5723DD335CF82F58EACDA5A65B6
+:10C1600022D687BB7E687103FC69CB4AD13FCB7571
+:10C1700098EA07B31E10ED89820F7E98755BADBFFC
+:10C1800090F8CBC97839D39EC0F231189E9735BD4F
+:10C1900068C04BBF7659BAD54B7C355FE8C153EBCD
+:10C1A000476C66FF2737944F6B6E273D8B781B8A51
+:10C1B000B4A9C07FAFA0DC3B100FE939E0B160FF4C
+:10C1C000F45FA0FDA1FEEF854611FE96FD222E280C
+:10C1D000213D563FF1928DECCF1259CD27B9FAF59A
+:10C1E00068DF7F935C9D4E0C717D59D31E86EB1FDB
+:10C1F000B92EE19FB822855EE4CFE5B0D146EDCB04
+:10C2000041394E7602B528FB312B9D2FDBC80F5BE1
+:10C21000F9B4F57838C68EAE82F03192D3BA67ADF4
+:10C22000C7C331F616687C0C7F1DB70838140D1F84
+:10C230004BE4D0229B806B2FC1B53A15FD7999CC88
+:10C240004368A88FFDA0BA028E4332E281F86EDD0A
+:10C25000156F17FB06B07B1DCD68E751E47634EF10
+:10C26000E2B21DE724BD334C09DBDC384FBDA69795
+:10C27000C7878EDB2066FC31CD7E25EF92B85DD777
+:10C2800017D176619FA0D033D68270AC9EF3EA14AA
+:10C29000A28B4ECF6B13A0232E95E9E2D6E8E226BF
+:10C2A000BAE8F8477C962A38EEE50B382E6B20BEAC
+:10C2B000D0F12FE0ED8C17FA22B2338EFD2433FC3F
+:10C2C000E7343ED0F791902DEA83C19F909D28E8F6
+:10C2D000FA2F863F215BC8B1791FBA1CF7C57D2DA7
+:10C2E00003FB293ADC97CF6721DB17E1335DCFD41D
+:10C2F00083AF80E6D7F58A8E671D4E1D5F9D14FFC4
+:10C300000C00A7D2F44BC37E945015050D50909DA0
+:10C310002DF458C74C203A284DBBB9DFE5EE47D77E
+:10C32000B783ED4BD7B3E6FDE9FA56DFA7AE77F555
+:10C33000FD4E4545C2FA10C3768AABAE3DEF33F8E9
+:10C34000BD95B0C2E017573BEE34D46B5CDF31F4DF
+:10C35000FF5A468BA17DA6BADED07E7DC10F0CF5BB
+:10C360001BDC3F36F9ED9B4D7EFB7F1ADAA7844339
+:10C37000EC67BFD63C031474ACAEF920C2FE76B0B5
+:10C38000D9C5F57DCD195CBEDCACB27CEF6F2EE07B
+:10C39000F240B39BBFFFB6B982CB579B3D5C869AF8
+:10C3A000BD5C9AF5C2ECE7BFA1507C5211DA584D42
+:10C3B000AA7C5B8EEFEE6CE487D72D81D644C4D384
+:10C3C000846EE18FC372B33D3E77EC1EB2EB2E9BC1
+:10C3D0009BEC61DBDE89923A803F9784F6CE13C3F3
+:10C3E0002F49B3C2E021BF07CDF340FC756FB6857E
+:10C3F000E9476A1F50EEE63BC09A8EF2367FBEE4F4
+:10C400006E15E6C00FA95C067DD83E5B013FD9FFE3
+:10C410005AA712B42731685E07C2394F8009766A7D
+:10C4200027FB9D9EA690DF7A137D4478658F0CD7FD
+:10C43000E0F77915BFFB8CE2E46F3A3BACC42737D9
+:10C440001FB8EFD43DD80E6DFE72928F3EBFC1FF74
+:10C45000B6E572FC867BB3855CF54AEE9087FC9D61
+:10C4600014C51DEBFFEBA5375BF8FFB35BFD721244
+:10C47000E233F206B01FA7CB23EEAF9DE0D7E5A2D3
+:10C48000D6A504472791BDFF4135F5AF3BA4325EE9
+:10C4900074B9D0E5408FFB7439A8919F6DA5FE67F4
+:10C4A0008E00C7CF137A7C1F3C4FFB34F99D15914A
+:10C4B0008DD514875D2A4E9C74BEE325EAB7A7D9B3
+:10C4C000C77CB4BB793E97C1E6E51A7F3672FDE5BD
+:10C4D000E626AEEF6FF67379A0B95DE3CF8DDCFE93
+:10C4E0006AF3635C7FAD39A0F1E976FEEECE11F61A
+:10C4F000F7E350F530E2BFA7B245DE061C951C47B6
+:10C500008022CA2FCA2775192F0A7FCAC41F66BE88
+:10C51000D0F901506F4888AF6FA29D25FB700BF8D2
+:10C520008B1663397FD946EB64E9CBF3C54A671BA9
+:10C53000FB1F667DB80282ACEFFAEB77E1FF5F4A42
+:10C54000BFCB189F92BDD2F5DF6A08F37C76F94E17
+:10C5500037E54FBE3ABBE2D2EC0A2CA6FE7D7176DF
+:10C560007CF722D972E9383B7BA418AFC7D9E83FE2
+:10C5700002D9E5DE80CC7EF5F2AC8D491C675744CC
+:10C5800092C80F58D125333D30CE548623DD9669AD
+:10C5900074EB81E01F892ECBA62CE33CDCF24DC668
+:10C5A000FDAC74DE941C5407F4D306DC673D3CF804
+:10C5B00011E5E3EA357CF17784A7A9FBE6992FC75B
+:10C5C000F4FB243B319DF355136002E103E177074F
+:10C5D00049CE0EC92C6783F1C5698C4F88CFCF3502
+:10C5E000CF9FF932F2FDE90BCD1C7FFD33FB811F9C
+:10C5F000F8477E75F45A97E74DC8E1BC5BD846F220
+:10C60000A3D36F1DE948847B5D95234081766FB984
+:10C610004BA1F57B258F4C7987DE77C1DD82F8ABA6
+:10C62000DCFD9B23241F950E279F1BE0267A62E9E1
+:10C6300039F190AFD589FD26BCEA91C97D2F7F39AC
+:10C64000DC4ADD747BA3DB9FC93D11D9C779815CCE
+:10C650009623C0D8E262CE17972373BCD94AF1263D
+:10C660002AA4B3CEE90CEFD920B8E97B348F25F2A8
+:10C670004B932F78E424846F9D161F4E7CCFCB7094
+:10C68000781C2AEB17BB164FDA332CF82D8A479704
+:10C69000CDB79DF29DF0AB38CEEB9AE19B9023F4A1
+:10C6A0007872AA7702E3D7A9E653DC5023F76C7BB4
+:10C6B0009CF8A133C14D791BB3BED5F5DB607E7B01
+:10C6C00083EBEC807EA45E3658C439C1B86AB59459
+:10C6D000E23FF22F292ED4E34473FF9ABCAAEB0861
+:10C6E000BE1A794AC84370B92C9FCBA70D4D1F7D48
+:10C6F0006E9CA6AFDFD055EE5A12930769CF91B466
+:10C70000FCAEE27ADF11A5DB17A5EFD4C87C83FD70
+:10C71000F9BFEEAFCD46374742192A9202C28F00C9
+:10C72000E14F2C8010978B20C2A50F3989CA25E0D4
+:10C73000E6F236F07219CEF535E790BF608D0C2524
+:10C74000393EF5C2DF0B892F4E5D33D995A546EDF5
+:10C75000AB6E6F2FD7AEC6D379D200FCF090C6B7C0
+:10C76000BADE1E943E26BDDD3B16F5834C79A1C88A
+:10C77000A21729DFBBC7EEDA1AA31FC06FF4170791
+:10C78000D317358A88DBB75BDCAF531ED1FF5A1A4B
+:10C790000C245F7A399BFC49E4C7E40561251BF949
+:10C7A0002D3FD5F334F1B3FF812929AC87498F5C44
+:10C7B000897478579CB7C00A299087FBDAD529EA93
+:10C7C00045B7A70424B6E741A6C742085B691FB76F
+:10C7D00002B0FE5C0C2A974BC1C374C199138A51F5
+:10C7E0009FDCDEA98CDB807095A446B249CE8A26F8
+:10C7F0001E4D9570FD62F2639D9C6369277F4387A0
+:10C80000F3448EF0632FE67876115D4B52431B1E86
+:10C8100026FF6EA705C8BF3B31F13B77408C7D1CDE
+:10C820009157D545FB784E12E77CFE2EBBC88F4151
+:10C8300064A837C6AF0EE756BF44F3FD568BE7A199
+:10C840007B3D9FFFD4BA044E61DA10C6018E1B45B2
+:10C85000FAA7BF9CF9795C09E97B91EFF34305AF37
+:10C86000CBF577724ED4B689FDF8C9AF1A91E73B84
+:10C87000447095D850A511FC4FD8035BD8FF691CB4
+:10C88000457988654FDA2D648F8FA23EA5F3CE7768
+:10C890009A1D5CFE09E3142AFF8C710A95EF629CD5
+:10C8A00042E55F304EA1F2F6F3635129231D723D3C
+:10C8B0007F617D39C83E06D7177ECDBF86F9039DBF
+:10C8C000D3756B7C5DDCF9DE7D09C407BB64771E24
+:10C8D0008250B453E17CC2E9DD130272562C5E7DB6
+:10C8E0001182A378D71F1E9A5C46E3149784FD4FEC
+:10C8F000EF3A3B94E31F137C7DF8E8B2097C68F0C3
+:10C900003E9712DA40E39FDB994D10A23E00C187AB
+:10C9100044CF01F261002DCC27CFE708FFF6467B1C
+:10C92000A42CF65C12C8F453DE51B31735F285A47B
+:10C9300070A1967F9D487C9DFB3AADE73F20431E4A
+:10C94000F3A731BF50902BF0A097455D362FE545FA
+:10C950009EEBFAE39CEB110FB327CD2C9763E42DEC
+:10C96000237788E837F1B39F3C9CCEFD5DB4D4CDEE
+:10C97000B0B9C685FD6E71EC7D8550B0D0F56E4DB9
+:10C980000AD66FCD90F653B958CD9A9EAA12B80127
+:10C99000DECFD282CAFDC462B3DCB536B2AF952415
+:10C9A0005431FAB3DA914027A07DF51A579AA1FEC7
+:10C9B000B58C1186FE33D51C43FBF505630CEDFAEF
+:10C9C000BAB3DCA5867E24AFE4FFE23E98EEB05514
+:10C9D000E6F394A29D1FBFBD8AF77F7319EDBF17C1
+:10C9E000F1674307E1838AF53F7A98D4C6CE7D4943
+:10C9F0007CBE6AF233EBBA9EDAEF5107F7333F8120
+:10CA0000DD03FA67F583F8675FD4CF44FDF110E9E1
+:10CA10008F92176EE2F3F2E7267E76854AFE722E3B
+:10CA2000FA9F884AB3FFD9ABF99F66FEE9E3534901
+:10CA3000157C7350667DABFBA166FE01B84FB3E376
+:10CA4000A2BC5C399FFDA6B03B7F25794F8BE56B7F
+:10CA5000AD34E5154A6C680728DFF77B19B6D08737
+:10CA60000B08878EFF9C28DFC36D9B5F195EC6DFB6
+:10CA7000FD89B864BD966768CED5FC8EBABDAF0C93
+:10CA80004F8FB6C35DEF1AFAC3BDD27E43BD2DCB27
+:10CA9000587FB0727FECF8C1F4D0B24D77DA7C9455
+:10CAA0005F7E44E41BCDED3A3C35FBE23CA42F9580
+:10CAB000DD768E6BEA5D1ECE832883E44174BD7003
+:10CAC000B30C8D03E9B70DDABCB3F6C581FC25E6DE
+:10CAD0003D8ABC42F0F87F21ECCCD1640F7863D65C
+:10CAE000F961AEC8039F4AD9F86F9F62BF53BF0474
+:10CAF00037A1FE548AD0B7C59D272C16B213F182F8
+:10CB00005F8A5D614B2ADD53599EE0A773E086156D
+:10CB1000897E3AFF29C98EFCD181A47F2277EE431A
+:10CB20000EE4BBB72D1683DDE9255D87F56D4FCF8C
+:10CB30009943E76DD7EF8B0B5ABEC47EB6511E9357
+:10CB4000EC549590F745C437FAF916CA47C3FD600F
+:10CB500038EFA2FD53FD58EED7DF7C84CE6B0E0A72
+:10CB6000F9C766A739AEBC2526AE844D427E1DF8B6
+:10CB70004BFECBCA9737DA28DEF9AAE47E6FAE33D4
+:10CB80001A5F8EEE2FCFBABC371C16F27E66F727DF
+:10CB90006F925E3F83F62E56DE757CE972DEF0986A
+:10CBA000CCF2A87F3FBD5B9E111800BFCF6A7C000E
+:10CBB000AE7CC3F9D79AA9E7E6905D5BD3A5F0B93F
+:10CBC000DE60F6BAA1DD78DEF5DC1EFB72711E2C8C
+:10CBD000F6D1ABDBD3AE4F522B0B45D9C2E7AE1B20
+:10CBE00035BD23FC18B4A3D674B2A3B512E7D10E99
+:10CBF000770DE37B15872508AAE3788A9B1C48B745
+:10CC0000B9623AFAEE247F0C320A145A678E46CF84
+:10CC1000B95A7E675ED7BC3CA2D71F3B971CF66013
+:10CC2000D327B939BCCF6F809FFDC1C329DE4CBA71
+:10CC30005F30BB55F0F7E194480FE5830E4F4D9000
+:10CC4000E85C09E76F8BF5F70E5BBD998DBC2FFD96
+:10CC50009CF16AF962C265C4B39A3E447AFA25111E
+:10CC60009731FF2BC31F64BE5A0181FD1E5CB7DEE6
+:10CC70001D64BF741588F8DCEC97D74FF9D0467661
+:10CC8000C11C4756EEDA7B84CE2FFAE5134CFC7AB2
+:10CC9000A9FC81397E1DCCAFCF4FF566E4C5E4EF2A
+:10CCA000CCFE799F1FAAFB515B13F87CE7A5A98FE7
+:10CCB0009E5E85F5BBB626B8285E3EF9A4DD4F7AA8
+:10CCC000F9E4167B40C2F693A9916E8A134EEE28C2
+:10CCD00072E30CB0CCA2FED7B364D79FB1325FE051
+:10CCE000CA86FB096BA6DECDF7F6D66C4D94E8FE3E
+:10CCF0000C6488763D76937F9AC87EC18AE787F375
+:10CD000079A56E5F483EE87CF98327E23CE4E49F26
+:10CD10003C303799F2763D969FF3B93CC8F71EA395
+:10CD200073F755DB12C7F1FD8B4260BA2DDF721528
+:10CD30009F536E547C9368FFD53FBD6118DD075B40
+:10CD4000F1872140FBE9DDFD3C9FE345FDF481FDDA
+:10CD5000BB33BB7392A1308A273D9FD7FE748B975C
+:10CD6000E85E2EA9E2BC051A3D23882F76D502CDB8
+:10CD70003B4E16F73D23EB13D82F35F35D6D9EF038
+:10CD800003EBF4BC411A3832487E7CC078E85D3F42
+:10CD9000660B9D6BADC84BD5EC74247F4ECC7DC229
+:10CDA0001AB9BB9EE2BD339BEC9CCFE8891BF83CD3
+:10CDB0006B615E0AC3B7CC613CFFAE6FFACC582FF3
+:10CDC000040FE99D71AD6AE99D58AED5F0DF92E997
+:10CDD000F5E5E17A2B3B7EF0C2AB8C974DDF7E9B75
+:10CDE000D63DE01479945705FECCFEFF3287C85734
+:10CDF000006C6678F5EF279E788BCF494FEC1C933B
+:10CE00002FCE7F43EF3F9EC5E7BEC7EEC172C781FD
+:10CE100037992E6678FB9DDF4912EFB78EF6914663
+:10CE2000E7B4DE6FE7F1FD1D11B72DD950C4F8D37B
+:10CE3000CFD17A4F0E1C9FE870EAF3EBF0E9F3EBE9
+:10CE4000FD5A357A5DA7C507A76CA1D37C1EFEC22B
+:10CE50001889F2747DDF5343C52931FCF255E5C5CD
+:10CE6000BFA9E5358E585ABE65A3FB6D1D0F5B7DCE
+:10CE7000B17AEF32F3E17D7EA00754D750614AD8F2
+:10CE80006EE1E694A1746EA7D54918B03E45034FF4
+:10CE90002278E8BE9F56C24A5F06E7BB693E99AE5C
+:10CEA0000F06B8DE5AE956A9BC56F22AE2BE5680F1
+:10CEB000F9723A348EA47D581C613EDFD2EFABCCC0
+:10CEC0004B59774316AED73604D6911FD3661572E9
+:10CED000E15F9CC0F19B8E27DDCE80ABD0605FDA36
+:10CEE0005CA02A38CF7C05DAADA9A2DF9588E7C31C
+:10CEF0000796BC427EC25B4AE3105AF7A8F3912220
+:10CF0000C942FE5D209162C4B7DF7CA6FCF7D8F76A
+:10CF10001DF04C7522FFDCF41B07EB7D733EE276BF
+:10CF2000F0717D1984AD1FE3B83F4FFC9FADFB202E
+:10CF3000BAAF3F4FFA7427C507B7A4DC574EE3F5E5
+:10CF4000FB93E67B7A275D4EBECF67BEAF7723F8B3
+:10CF500042C4CFE72CBE7A91FF689C40F6B737C534
+:10CF60000612F6EF1DA2E1E314303E7AADDAF88F37
+:10CF700054AE97558FE3BC229C53591F4F36D99B13
+:10CF8000B2311611875D14FDA7461483BD292BD13C
+:10CF9000F2367F57D92FBDF6BCF2B9F6A82E5FE462
+:10CFA00059CAD22C8D03F98756ADBD1582B2D88FE0
+:10CFB000F01326F7F1954726FAD56BF57AB267C8D4
+:10CFC0004FBD490E3F5D509CBC5BF0D76425B897C0
+:10CFD0004AD4AED0447EC52EB4773A1C74D697316D
+:10CFE00086F96092CE9F38D702ECB74E6AE4B8C596
+:10CFF00041FE0C961BA410C3710D44B8F46876BCB6
+:10D000000ADC5C4E032F97C89F5CCE404B42E5750F
+:10D01000D0C1E52C0809BB7F75B095ED19DCEBE2BA
+:10D02000F86FE6320BF91B65DF18385E187D493C56
+:10D03000A0C08DBF7C3C4C0794BB9C01F031B280FA
+:10D04000F587191F66F99C0A6199E59314430EE56B
+:10D05000095496D36AF070BDE60BE2A122EC533876
+:10D060004F63C647F5C07CE1D6F0F1E77C10E71FBF
+:10D070001A9D96E6AB5CD7E985729541FC6FA6A335
+:10D08000FEBD2CA1EA2C5D29BF7E5BE65CBA1F5574
+:10D09000565AB59654F282FCA2B9743FAA6C72D566
+:10D0A000F37474B9685BB1A89754955ADD68DF5A78
+:10D0B0004AE64EC3FE3EED3E31CC17FEF55D9ADFEB
+:10D0C000E26BF996DB8572E2CB74BA697F0E74EE7F
+:10D0D000E95E8A9C23CEF946CD08EEB362BFA38AEF
+:10D0E0006F7A3E9DF73982492AE2FDAE961ABE7FDD
+:10D0F000F6804DF4B7DB457E55DF177EF7C7617DBF
+:10D10000C78E316BA5ECC1D7C779E7E60F2138F29E
+:10D11000FC24AFBE9D925B50B26AD87C94CF9E90A7
+:10D1200015281FAAAF939EE99B4F7080239FF3643D
+:10D1300023347FA667C798314497A5F9DA7DAAF40E
+:10D14000AC52C25B43A67729CDDF9B28F86B29D16F
+:10D1500061C8E0E5F7F23D8B697EF3F7DEBF2200A0
+:10D1600038FEAE7CDF329AAF21E102DBF7D363FFFA
+:10D17000B02E9C15E5530989B400F7DDEA81808D56
+:10D18000ED8076CF5C3B77EABD1DE7413C94797D2D
+:10D19000ADA4D2262C888C27FD89F3AEA1751B6C1B
+:10D1A000E1516371DC23738FD9049F8D147CA6E950
+:10D1B000A1AE3D07EF1921AA5E8891AB863D9F7D08
+:10D1C000FA0EE2AFE18CD34DDDA3F2F4E3B51C4FD0
+:10D1D00082D3A03774399BB4CBCE7EF5E4DD57DD26
+:10D1E0004EFDA6FEA13B87F6756D7798CFB37ABB4F
+:10D1F000DE1A21E0D0E38D73D297B1BB74DECA7121
+:10D20000DC4E71DEBA466A7C2991EA3F93DC7E846B
+:10D21000FF846637F4B878B9B6AFD507B7AEA3BC0C
+:10D22000C8F24D4B67F17D9C80881B54FC25F9FFAB
+:10D23000045EE573EE55DBCDF144C446F45FDD6179
+:10D24000BAD743F130DD5F88D5EF03C4C34FE56B38
+:10D25000F9AE4CC8E47DC80B927D03E83B73BCFB80
+:10D2600018789EC9677FD62BD3FAE5CAC0F9842700
+:10D27000A2EF3B581E96696B139E9C1CEFDAC4BD4F
+:10D28000DF27D6BA5D54D7E47333F24A05F9D16D7E
+:10D290003F66FED7C7E9F2BAA25DDCAF864D69CC26
+:10D2A0007325DBEC1EA26BC9B6611C5F601CC47EDB
+:10D2B000DFE66DF676AAB7DE1FEF974B289F1CB905
+:10D2C00082F22AAD71E27D129947BAEF59922DF29E
+:10D2D0001CC774BDAED975FDDE6C5FFC9398CFF7AB
+:10D2E00093FBDAC38A21DE68D5FCE732828FFCC06B
+:10D2F00046AB889FE204FC7BDFF87A02F9B13B156C
+:10D300006F02E5A5CF1CCA4E8601F0A697E5685EC0
+:10D31000E073CE0BCBDF9A95F379F42A7B4CBB6795
+:10D32000AEF1E7AF9A3DF0176B941EFABE6AE46760
+:10D33000AB6D94E7B80D5C94F75873F0A9567A2753
+:10D34000B3663D7046E10CFDA178E1030B9F674F8A
+:10D350003A589A41FCD8A9E93B3ADF5563F86A3C50
+:10D360002585B07FF94808D0BBA138351ED498B8C0
+:10D3700038A120D5504F745F61189F5C916D68078C
+:10D38000BF2754383EEABFA678AE36F47F20693A0C
+:10D39000BFA3991ABA83F34A6933C619DAEDC8D71D
+:10D3A000745F013E16FE4F05FEB25D854699E09C16
+:10D3B0001C06F809F2DDA41EA37F5411DEC87160BB
+:10D3C000DC21C510D7DB2F91674A1AADC9D54818A3
+:10D3D00029F48319DFC67B0D6B0ECAECC7ADC944B7
+:10D3E000C7336B707CEBF2A7E37D88D788F761F3D6
+:10D3F0008D781EEE33E279C472239E331B8D78BE86
+:10D40000B2C988D72CBF118F39ED930CFDF3365676
+:10D4100019EAA31FBBCED0FFAAC01C437DCCF66F78
+:10D420001AFA17752C31B497EC5AF9B9741F1B5CB2
+:10D43000636837D3BDF4C0774D7CA8309ECBB577F9
+:10D44000553AFDFDF84BF49F0CDEE4A044E9407F23
+:10D450002BC9E3BF8AFEB3476BF75874FA7F41BD0F
+:10D460005AA8F94FE6F759B31384BE79EDC0994332
+:10D470001EACBFAE965A33C86FD2FC03AF7E1E619E
+:10D480008AFBF438E5C60AC974DE1E67386FBFD45C
+:10D49000FDB4F250D0501F7B48BC6B1A77C4FD120C
+:10D4A00095E5EF79E4D8774C133F66B3DC2FEED4E3
+:10D4B000EFB9E97113643CC971E8021D7E1282F173
+:10D4C000FDF38B7A7C6A8E5BF578B5FF3B29E1979B
+:10D4D000DC2D0F16C78AF8558F5BBF0E1E7E0F56C8
+:10D4E0003ED2B76E34DD9FB244D2A85D8F6709B1DA
+:10D4F000746EDC4B8865E7E2E05C4F21BF23E5BC3E
+:10D50000F7CA9657E6D27D7D04DF151E2FD23FF471
+:10D51000F3E468DFC6D1A8778F4BAE75A538F6B5B2
+:10D52000491F8EA2F91E1E2DF20C76193184F66762
+:10D53000D8020FD0F7FC54CF23A387F4BF676D2E1A
+:10D54000CDF77F3A9B835C2A2E37DFBF31E707C3D5
+:10D550001695FD4EFF7725BE6FF321013731EAAFF7
+:10D560009C69B7B2BF025A3CBE50C3BF9EB758A019
+:10D57000EDE7384EB11CEDEFC25DBF61BAACCAE851
+:10D58000D1F21D8DEC5F2F1DE91CC7F7C93CA56EBC
+:10D5900091E7D2F318232EEB9DC8A5F6BF2AE3A48A
+:10D5A000218F04CFA67DA1F3EDE8BEC5FCC7D78BC4
+:10D5B0007CE4F1F5999CFF8ECE7F9AF3490B1BDF3B
+:10D5C00030C8C5AD4D470D72B0D8FFAEA13D9C1E11
+:10D5D000B152FE30FCC2F0E9B720FE4EEDB4F33B91
+:10D5E00066E4833746C7E4CFC2EBC74CE3F79097B6
+:10D5F000DCE7870C47777388E9ABEFF358F311AE9C
+:10D60000879BC35C9AF7A9E729F4D2B60F0AE89E74
+:10D610007D448A77535ED89CBFB8DBA2BECFF72289
+:10D620000BB2B57382C6122FD34FE42BBAB577A1D4
+:10D63000DDDABBD06EED9D67B7F6AEB35B7BBFD9CD
+:10D640006B75B6535EA35B12F77716489E2717E3F8
+:10D650007AC9237D1F915C35AC8C142BB84E43499D
+:10D66000789184741E39C4F731E145C2706138BFC6
+:10D670000BF2F33DAF0F2CFE627A47E32EC8B88958
+:10D68000E2BC0FE2FDA7C91329D89E26EA362187FE
+:10D690001505FF60B97B0F27A3FDF97F2989BC928F
+:10D6A000336CA3775053D37D503044DCDFE2F72F47
+:10D6B000F89DF852CF73F65A851FD8ABF983F6025E
+:10D6C000710EE83095D944F3725A0F343FFFC17C94
+:10D6D0007E37B2C90EE4BFE2FAFC4E46BF67627EF7
+:10D6E0004733EED7767EEFA0E743471464F17CF42E
+:10D6F000BE86E432FD7B09ACB7201C1A45EF71FAF7
+:10D70000E03D24DE439EA23C724CFE794481F6CE7D
+:10D71000F13630BCE7597DF0F8318AB37E3DDA77D7
+:10D720006501CEBFC4A28E27BAAE4EDACBF9AEB138
+:10D73000052AAF8BF08AFDCAD046745AED08737E75
+:10D74000EC52F9F0C1F67FEAF6D08F0A39FFAB163A
+:10D75000F37B3A6D5D84636C414CDE5A87233ACF8C
+:10D76000E7F3BF9ED7D5EB279E78205FCBCBDFEAD0
+:10D770001DC09ECED0F0D26D1D388FBEB440C423E4
+:10D78000FDE8331A4D11DD538C471B81E53CC21374
+:10D79000E5816FC6FD707EC23396E8BB7A8E93DF5B
+:10D7A0008DEBF3E33CBE9F7FCE3A2D99DE1B89FFC4
+:10D7B00056368ABCBBDEDE2B09BAFAD78B3CE8EAC8
+:10D7C0003D478FD1FFBF60C54F8B4A39BED7C69B3F
+:10D7D000F18CF8E5F74D4B64716E85F85D40F39B75
+:10D7E000F3ED5F16AFBD99E27CB577F367A3E8DD93
+:10D7F000E86ABA7F46EFBCB4FC15741AF352882F5E
+:10D800003FE52BFA9F47019F6BD9353B62D7C78F06
+:10D81000540CE3BB9DDEB5C41F2F687A03FB072CB5
+:10D82000B87EA71E279BF2289D2191EFECCCB0B1CA
+:10D830009F4CFE0ED927DDDFB9EB0D91EFBC2B4BD2
+:10D84000F8D1041FD1573AB29FFD843EFB2FB95542
+:10D85000C29FDDEABB9FD607DF5AB65FF295485FED
+:10D860003ABFF8ED755A3E40D8C372CDFE95D33C11
+:10D87000E4E01426B35D2CD3D645FF91F36E13C1BB
+:10D88000D72A80D1F266EBF7731EE17F01BC43AE6D
+:10D89000E0704400000000000000000000000000F4
+:10D8A0001F8B080000000000000BFB51CFC0F003ED
+:10D8B0000917B0A1F2AFA1F1933951F93F5951F9CC
+:10D8C00017D0F884B02E1303C30A46D2F420E39D88
+:10D8D00040FD0780F838109F6322DF1C103E28CCE3
+:10D8E000C0F0458C816116906E01D26781F82B10D3
+:10D8F000DF06F245441818948178BE28034314903B
+:10D900005E0AC40522107D8780748D287976AAF37B
+:10D9100050E6E6514C195E298DCA2F55616058A614
+:10D92000CAC0F05A0DC25F8824CFA0CEC050A60254
+:10D9300061EBC931307400D5CC94C66EAE3E50BE9A
+:10D9400013282FA00EE10300D191FB3B68030000D8
+:10D9500000000000000000001F8B08000000000015
+:10D96000000BCD7D0B7855D595F03A8FFB7EE424E6
+:10D97000B9819B90C049081834E0490C0F11F12679
+:10D98000441A6CC41B8C1A6768BD606B231588C869
+:10D99000687C4C7381248497066D2D83FEF462AD00
+:10D9A0004329ADD16287A98FB9202D689D1A2D56C4
+:10D9B000ED4FFF46C6B1D42A7F44F1552CB3D7DAD8
+:10D9C000FB24E79CDC04D0CE7C838FC33E673FD62C
+:10D9D0005E7BBDF7DAFBBAA104E0128053F8873D05
+:10D9E0006F9000206FF0095EA3092200CD9A5B5F63
+:10D9F0005F0CF04DC538A857B1F7A365E3073ABEF1
+:10DA00009F580B610005EBE70318F83FD66E4D7089
+:10DA1000F5A84490BD531666E1D3ECDF7C36AB002D
+:10DA20005A257EDF3831D377F30929577F9F17E8CE
+:10DA3000CF29066AEBE1D727EF37CBECBF020845C9
+:10DA4000DE0AB0BF4C87E9A71480E3C10559691805
+:10DA5000BEBFB7DBBACF5327007CD4F6DAE4FD13A0
+:10DA6000867EFFA6022D3DE543DF4F0736E854C40E
+:10DA700047D21D9F3C38EF81790619922E64ED0143
+:10DA8000D29E1CF6DCB1F93CB56C104EE73C00921E
+:10DA90001CBF9FB39D2752932E60A50A29318BE0AE
+:10DAA00052D93FD300A82A5B97253B1A80E072C069
+:10DAB000DB11F9DBC03BEC7A897AC783AB3B91B4CD
+:10DAC000D6B838BDB4E7C9C66A184A2FE67A98783E
+:10DAD0003CD3F5B81D7C348E4947CDF2C211D7FD39
+:10DAE0007474743DD2D179FFFD7494FCDF4B471DF3
+:10DAF000D4CFFF323A02E8E6F8823E15C71F7CCF4A
+:10DB00009F91853D12D2192BF622DC457C28286A8C
+:10DB1000EDBC599EC2C41418CF9DC3E45651DFA278
+:10DB20007A847BF4E1797FC26767634DDDA56C7E03
+:10DB3000F94D3D2F7D893D23F1949460EB751FC80D
+:10DB40002854587F3725ABD9FCDAB1B399008F241C
+:10DB500017C592385F88018C02F8073127005957A2
+:10DB60005939447FCD340F37A4393EA4539EA1EDDB
+:10DB7000879B7F08DB99758AF1FF2B00E777BA76E0
+:10DB8000B0928F9764FF20BEC70C8E4FFDE4375BC9
+:10DB9000CA80F8B17FEFC5BF107E6FFE1F19AF00BE
+:10DBA0002A7D281F42F5B296C2FAD093ADB272E434
+:10DBB0002615D24C461454754B2EFDF4EBD2095069
+:10DBC000D7C3D7476A080DC2F79F2011FD8CBDE36C
+:10DBD000CDED6B19C99D581834883E3480DC9CA16A
+:10DBE000F3F94E1B12B2A5DC582325683CE3B95269
+:10DBF000D63ED9C8F5DE7DF50BB2ADF2CA23490297
+:10DC00006F4EFA005D9D866CC5E943AD9763BE29F2
+:10DC10005F9C3ED4CF491F792B2DEDE0ECD72B62D2
+:10DC2000DA0567481F5F743C735D87F2D52AB1AE91
+:10DC3000A53E607C7B6FDD828C76C6F0EB5A49FC9A
+:10DC40001EA987582A43BBFC81F54C0E7DB2F551C5
+:10DC50000696F716DB7A29A3A7356D1F011F4AC464
+:10DC60003E5FB35F5FABA2BF99CB8AAA26637F6E8C
+:10DC7000EC8FD1D9BAE8BD4960FC7002699BE143E1
+:10DC8000E9AE4863194AC1F881804066655F349601
+:10DC90005A4F7490A27531E1F3E8B20DFF6AC46F78
+:10DCA0002B435352B2C2EF6B75131C6E1C8FD1BB4A
+:10DCB000A2B10E192AD420A47D61ACC1E14732384B
+:10DCC000351ECB77DAE8A04BAF844CEB60D22BA2A9
+:10DCD00095D3EB9D67265F9CE335DAE13DE3764122
+:10DCE000557FCBA287866FA7C25BE6FA30247E0DF4
+:10DCF0003B983AB84E6B5DB0473A9FE9EBC2AB2117
+:10DD0000C1DEAEC54F17129D923DB3B6B05243BAB5
+:10DD1000821D928A709A7A14A23954AF42D2A91FF6
+:10DD2000D9DB02584F09C6E8697E1F1E2E417FC904
+:10DD3000D8DE52D6EFE5627D2F177A0DAA5C6FF61A
+:10DD40009970939E5507CB6C1EEFDECEFEC7E8247C
+:10DD50005921A57E200DFD5E8F7A91C9A57A7C6F31
+:10DD6000912B5B06F8204AEB552FBE3DFBC4AB134D
+:10DD70002F60F4D16B2880626BF5139E582DEBFF5A
+:10DD8000A58BA5944712F03238E70B385F88E5166B
+:10DD9000219DF6D67A888EE77FE9A30892F1B13DFE
+:10DDA000BF5133D1CBFC59AE4138D87FCBADF363F3
+:10DDB000FFFDF3C0BA14D238265C4B2B1582A37733
+:10DDC0009694C271F6FFFE8F775FC4E07CA14A3261
+:10DDD0003C3AC11B02365E6FECFDC8887E8739BEB7
+:10DDE0000E1AE2D339BEB91EE1314078853F30BC0E
+:10DDF000B2F19235FD7D6B10CF4724630D1B2F6B65
+:10DE000076EB381CA7589609DE75B3BCB2C2E8079A
+:10DE10005E1B25233E8382CFB3DCDDDEF10CCECE4C
+:10DE200009323CC45EAD2B1D599EB53BE499AAC591
+:10DE300063126BAF27B54A6504BE48C5E4BA4CF21D
+:10DE4000EE7989EBC98EE402AD14A7B7DF6E07A2A5
+:10DE50005E8A5BF42AB3179F97D8FC5D114EC7D931
+:10DE6000B5716E27F68E22F91510EB9135654116C6
+:10DE700064B083879D071B2893DD9C2D73F8E030E9
+:10DE8000EF5F35FBCF19B9FFB5A2FF8F9B25E845A2
+:10DE9000F8D4B817D71F621544CF7E419FB03287A0
+:10DEA000CAA6DCF594C5BB8AD93A7AA232E83ACE42
+:10DEB0002F49EBBC81AD712103C55FCBBEB3AA1B5B
+:10DEC0003E53C82EC9964F24930C8E0D7B6F049D34
+:10DED000D9A9FE680AA83CF9062FE26703530A7C19
+:10DEE000FC1EC0F1038C6C51BE06987CD551BEEA75
+:10DEF0003D699995D53A3062EC534833243F2399D4
+:10DF00007DD192552A7BDFBE10887E01AD080B7E45
+:10DF1000DBA32FC71406576713905DD319A9A1F986
+:10DF2000B597D7788BD1DEA957E93D9C64F830EDE1
+:10DF300010260FFD6510C3F136E4432A88BC549BBC
+:10DF400047F4E8D6F8FCF52DA590BE807DCF9EB6AF
+:10DF500017C74FFE231813F89024D754932ED44498
+:10DF60005242FFAE5533D667A0BB2D90C892A7DAB8
+:10DF7000E894F4AE136F596EB80CF1DB59C1E8BFE9
+:10DF800078683F85C83F8CDE52C6822B4A328C535C
+:10DF90002CEB441F6659FFD84DF00F577FB01EB3CE
+:10DFA0003373B1EB98847881DA08CD2F0706FEC46D
+:10DFB000B09C2BE63B0A5AA85E7446F75EE4B38237
+:10DFC000584F35E2E23BA1AB5FA2758307358C4722
+:10DFD00030684B4FE50ECA895890CB89E3864CF2E6
+:10DFE0003124A7B518EB20E4EB8D92B2D681FC88E2
+:10DFF0002C6CC2005EDFD63D19FDCB3018127E0FAF
+:10E00000196AD22A7FB280956DF61F1C2A9D46A4FC
+:10E01000C5F902B4BDC8325A59CB39D8DF7D0C20BE
+:10E020001FF393378612A42F3EF285A7E0601FC925
+:10E03000F1AC346F5F8676F76D8ADF588FF46070CD
+:10E04000FDE065FFA0FCCB9AA1DAE47176CC5ECE50
+:10E0500075E88DB94A90E69B7D39087D10AB9F30FD
+:10E060006A103E065903D2CDE65A1570BC6090C3C3
+:10E0700065C299AB9C4CCB40701C4138187A088E15
+:10E08000701990BFC7E039E280E788039E23567875
+:10E090005ABD7CBE4EBF7FB12CFC7EE6F7A21E3C73
+:10E0A00001EFC4EA90606245A457C21AAF1BF4F6B0
+:10E0B0009251A58146EBEFF4FBD9FA1CB7E9871919
+:10E0C000A2AC33BBBE84E0B37F8742A2132A2B30BD
+:10E0D000E0BF2E9E61E247BFE6FF32BEBBF1A00B60
+:10E0E00090AF18FF2AF8DD25BEDE28FCD8C5A8FFB2
+:10E0F00099DEFE1AC4C308DFBB2093BDFC2EBC1CF6
+:10E10000BEC02217EF93DD428FB305B5F22F185131
+:10E11000F4ABD56067AF1226349874269DA2753390
+:10E1200080FCEE20A7B7247857917DD1C5F5A3E9EF
+:10E13000F77DBDDBAEAFBFB1C55EBE01168C42FA46
+:10E14000BAE1DB2E48B17E6FB4DA1F6C7DEE9035FC
+:10E1500082EF1BD0D2A905C9CE6AC2792CD6404520
+:10E160003F6DE9BFFC9F698BD87CB60A3DFA3693B8
+:10E17000EBBA456F2C89A4DCB1F2A1F35B2319F350
+:10E180002F92869FDF5A57EF7CB40F929B5CE4D7A7
+:10E1900081D35FDBAD90BF666947F05EDF659FDFCF
+:10E1A000E9E6EF9C2FF35868BE4B762C22BD39DC94
+:10E1B0007CDC3BA4582A837E7BCCD48742BE98F477
+:10E1C0006DF275B206B8BDF7FF7CA9356CBC57502F
+:10E1D0003ED2FAB79CCFE3282DD3F179BA76BFFBB4
+:10E1E0009CEDFEF039DBBD29E4B8B3DD526F9F1B17
+:10E1F000D773B99AAC93E4413BDAEB6A898D61A895
+:10E2000070EDA94EA32966A9D77586F50E4A256734
+:10E2100054AF4E1EA1BF63C2CE38B0EBFBEE3EE45E
+:10E22000BF9D6FCC47FDFECD2715F0B2791DDB15E4
+:10E230008234D2A79A72A3BDB284D1558ACAE96941
+:10E24000575AEC2A46B1D4FF371F0D917DB0E471C7
+:10E250004FAA9EB55FF2B3FF98020C0FC756F7FFA7
+:10E26000720CD2EB4E89FB7FC9BE2957B2F74B54D3
+:10E27000B82E9E814E6485F3CB3BFF1A6842BB4F9C
+:10E28000DAB1F7ABD46FCF352E94CB66BD4F6417A0
+:10E290008DCBEAC5F07BF287526A82C4E16B983C71
+:10E2A000D4EF7EE78712876F8F2BE543F8766C7784
+:10E2B0002758BDE53BDE23BA9DF3E88FC38887E589
+:10E2C0007B149BBFBB7C8792F64CA1E71BF844CD27
+:10E2D00028317E5B26F875D9EEA5A40796F56C78F3
+:10E2E0000FF975F91E974DAE33BC1869C4EBAB8AB4
+:10E2F000518FE59FFE735867A87A3BBA33AC9553AC
+:10E30000BF8BDC8CAEAE98616F87FD7F9C33B43FD2
+:10E31000807E8A6B2EEF59C7C703AE6F4C3E7D1BC4
+:10E32000FF923F546F4C52ECFB0E27E08569148737
+:10E33000DC919BD18F33F585C9AFDFFCF1896D4945
+:10E3400036EE3B8FFF795B92C17FD35FDFDF7627AD
+:10E350009B173CE3D3500E2DDFF94A182C78AF55AC
+:10E36000B81F76EC87FFFCC856C62FC75EF7905DD6
+:10E3700077ECE93F8ED5D9BC8F3DF6C928B43B5721
+:10E380003E7DE968A4AF954FCC190D23F80F48AF37
+:10E39000298F755D53B4AEFA1E098330004F89A7EB
+:10E3A000637D9EDDADA43174FBEE6B9E9487E167C7
+:10E3B000397BD75A89EBB594F41096EF62785EB644
+:10E3C0006BED7BCA944CF84E8E91A3F8646C13C528
+:10E3D000F5BEF28A8BABF0E93274A40FE827F9EFAF
+:10E3E0006CB7FC105BD7F3875FC71370D28DF85FF3
+:10E3F000BE6B1D1FD7B18EEFE25F2ECCA0FF87ACA6
+:10E40000E34DDFDB8A1F77E7D2BA0FB78E4B9FB899
+:10E410006A44FFCC9407A7C36FB3C4E13A5F89ADE8
+:10E420005090AF1EFFD1235B237C7DEB19428EFD04
+:10E43000F8C4580C2E1F75F57F15E564FFD31EED4B
+:10E4400021D666C9D3AF129F1D7BE225B74E72124B
+:10E450008212D37BC760E04F2FEAC165122F2C7F59
+:10E460003894F68407D76959AAA14E0FD3FB37E831
+:10E470007D8AD3FFB2D4DE4629C3BAED544AB85CD4
+:10E480004EE5115E96EABD6E2D685F4F6906AEE3FC
+:10E490001B7391EE865B4773FE1ACE7FBA653D1FF4
+:10E4A000E67C3B1C7F1EDBEE51A5ACC1F53D26ECA6
+:10E4B00083E529E955C8C0B700AB39BCC3EC3F9A26
+:10E4C0004F273D3CECA007B3BD39EFD3F1F5E9E7A9
+:10E4D0007376F8FAB6A2DBE8C6C4DB3B2733CBFB86
+:10E4E000B49013CB205957307EA8BE52219E1C53A6
+:10E4F0003C086F678F4272FC9D1D0AD9E94EB9B086
+:10E500006C187FFCD70AB73F96EDD93B05E5D73BA2
+:10E51000FBFE55D021A7F365BBDE702785FC4F5964
+:10E52000E53FF697613D5E13702F7F2A737FCB77AF
+:10E53000BD97B1BFB7D5D83508FFDBBD2E48B22E89
+:10E54000DEEE5132C637F6292E5B1CB73334EDB5FB
+:10E550002C8C6F86FD3ACE7BCDEAD8AB49B4435EB6
+:10E560007601D981AA71D4C3BEAF09F969DF7B4DA9
+:10E57000F806D02D7ABADD8127351A273F588DC489
+:10E58000AB78EC3565F3475D9A6C831BD46421C688
+:10E59000537E5DFC4715FB7D11EDBF7306EBBFA8F5
+:10E5A00042472EEBEFC59864AC820CF12947FFF18E
+:10E5B000590AE8563A8B95C9D6F86A78DFED149770
+:10E5C00068859634C689A0107A7E60E9F7C1360D59
+:10E5D000D26C7CA82B93ADF1554F4B4BCCC3E028AC
+:10E5E0005CA995A06936DCF8452DB23DAE2DC65F1D
+:10E5F00021E209B063E7CE9DACDF3AFC56827E0C87
+:10E600008F5731778AEC9839420EFE9BB083F749D9
+:10E61000F1FDE867C5F4CD2ACA39A974B38AF6C4F6
+:10E62000BC93DDEA620B3DCE2B5D5588F472F0336E
+:10E63000A529135D35AA9CAE5615AF2DC4F6077DEE
+:10E64000B7157227344AF32C10F3DC5FF48D601F8A
+:10E65000EB776FF137364E6470D54515C0784B5D5A
+:10E6600064D1C60A36FF82438AE163E582E6A49A52
+:10E67000983C749C6D28EF19FE1E423C32F81F6EC8
+:10E680008B52F991369D9E3BDACAE8B9B3CDA0EF23
+:10E69000BBDA6650B9A7AD8E9E8FB7C5E97DF80E7F
+:10E6A0007F02E977775B13BDFF595B829E352AE7CE
+:10E6B000B779021F9679D33E58637B7835C6514CA3
+:10E6C000FC39F15DCB282E87F60D241DF13D5AE56E
+:10E6D00072C589D7D6D620D9A5DB24B0E1739ACAF2
+:10E6E000EDC8B880E3696FE23215F7F9EB4ACBC9A0
+:10E6F000EE81B881727A9B14BFA782F1CB81A2E927
+:10E7000051ABDC0D051371D5422F63BB787C66BA23
+:10E71000CAE5531DACDA9FC5E08B9D041DE9CC9C76
+:10E72000E7BE6ABD10E5E2BE550C9E72FC2E439911
+:10E7300085CECCFE660AF82098594E0FD22DE7FF01
+:10E74000E8CCB2CD1827668EA7314127ABDBD66E59
+:10E75000B36AC6BD75A263934E18FF1C288A503752
+:10E76000DC5F6C2EE6DF7D9CCE5BFBDEA3F856748F
+:10E7700014D8E28D1DCD32F9395B0FF3B8F489E678
+:10E7800092CD1359FD6A8637F4DB73E69566252C26
+:10E7900074BD51D0D3566F3C4B1B417F758A7A664E
+:10E7A000F9902FF12D5C97EF8EFB493ED2F356572F
+:10E7B000EA5A948FAD873DFA6A36A593817812BFE5
+:10E7C000C70BD97B06D289BA951E9A5A90EF3FB4EF
+:10E7D000DEA56F3EC7C2E721C3CED7DB5A478E4BBB
+:10E7E0009B706F43B84788CB9A709BEB71A2AEB118
+:10E7F000FF1B30140FCE7E73E6358E38FE83C8774C
+:10E800001EC2C3362BBD15B668B4CF60B637E7EB72
+:10E810006CEF9CEF60BEC299EDCFF4B82017D7F330
+:10E82000B1BF8CFDE98B804B1E57508E5DA7267AB9
+:10E8300010EFD3A085CAA0F6E723BFFCD6CFF970AE
+:10E840006BE723F9C4476AAA18F5C2998ED701F17C
+:10E850007835EA2D4336ACF2DC7CFE4235E30469C0
+:10E860008A1FD116331B520EDC15CD84E781FE0BB7
+:10E87000D577ACFB491B01B89F9EF6D23E070644F4
+:10E8800034562E3E0895EB597F3B853CA956B95F1F
+:10E8900078C1417DBBC2E3474A43C88247114F3527
+:10E8A000E3581D701768ACA95BADD88BD54D3EBC45
+:10E8B000C29DF82DE2CB1DD569FFDD1549105F81A2
+:10E8C000887FCF1271FA4B95C301945FADD01B388E
+:10E8D0001FF9F99002E41727C6135F5E34CC3EE1BE
+:10E8E0002E619FEF10F2FA1141370FA3BC66CFEAF9
+:10E8F0009EDE34B2F4AC875373F0F99090DF292197
+:10E90000BFC355FEB4C4ECCEBBA71D4DB43038BA5E
+:10E910008F1E5770294D793153C067CA87993E0EB3
+:10E9200047B8BFF366B4BFB7A1FC473DE73A30FE36
+:10E930001E86AF8E84DBF0907C89D7B5E03C0A65FB
+:10E940009AC7CF0B6B641F2B3F658081FD3DD816A6
+:10E9500023389EF2F6BFFF22C6F767B98D247B1FCE
+:10E960003E79FF2DD86F58FDD13FE0135213F8FCCC
+:10E97000855C32F9ED59D70109F5F9D38540E38576
+:10E980004FEEB90DEDE7F0C9E76FC77697A4A03653
+:10E99000C0EA072B767FF97CD67FD6E532A0091A2C
+:10E9A000ECEE4F74B3FAA5AD2DD538B57F93D201F7
+:10E9B000FC9E9CA7921C1C0BB15518E7C8DB9890D5
+:10E9C000F07BE8418EB78BB6F4FEAA1A109FDA3EB0
+:10E9D0001C6FBCAB98CB5FF9B939B8F7E2297AD391
+:10E9E00087EBFAECD11580F2CAF3814CFBF14F7F33
+:10E9F000B002BE61CDAF38AA668C838D7779F8BE40
+:10EA0000D5070BBAA7E89CBC907F66FEA9D64B7CC5
+:10EA1000FE02D8F661CDFD2AB37D859418EFCAA316
+:10EA20007D09BE7F25DA5FA4A02DC78A7F96F97E77
+:10EA3000693C15B0C641827F92E399ECCC2A974A93
+:10EA4000F0B41BB5477FCDC653A75F4DFA17BAED9B
+:10EA50007038DB3138AA381C1C3E138E2246EF3E3C
+:10EA600036FE53C77F978FF07D5C67EA95DE00FA2C
+:10EA7000F97B4FC8C46F9BFA81F4CABEAA7D5EC4FD
+:10EA8000E3C6AA1A3FB773383DE6087A7CB88ED73A
+:10EA90003F51C5F7F5E1E429DAF77289EF3979FBDF
+:10EAA000BCB457918C05ABA7A17E32FF58F2081871
+:10EAB0006E8A93F63C02B935C7562E8202477E4ACB
+:10EAC000C9A05C453FBB2EF2FC38064A48EC3B57D8
+:10EAD0009BFBD8CA6103E7FF80A9FFDABCF4DCDE48
+:10EAE000F25000E31CBF30E9A4B9670ECE6FD64DDB
+:10EAF0003DCF86D97C2E3ECAF7CD9C792928F75088
+:10EB0000CE6ED4D2B9563D0AAA87E031F7372E3EF1
+:10EB10006ACF5399E5C84319928F75967EE572972F
+:10EB20003DBFF0046C9C4474D15B625B9FED173277
+:10EB300037E6FCA1FEE540BFC27F8228976F3942CD
+:10EB4000AEDC7D87D28CF651F8B2CA6CEB7E68BB26
+:10EB50008BEF9BEDFFBD0730FEBEB6D64B711B732E
+:10EB6000DFDC5CF70D986485F90DED3F0B205E9FAF
+:10EB70008C94F8F0F9ECCC9D245FCDFD7F8F98D379
+:10EB8000EA993BBFDC8C72294F269DD251B86F0C9D
+:10EB9000EE27DE5BEBA5FDFD70A0AFE759560E7EBC
+:10EBA000E436703FFBE9EA7493D55FFDB18BEBA5CA
+:10EBB000FB5DC2CEDA68DF6F66FC70BF8B7DF70449
+:10EBC000E3B45F297B459E84C3AF31F111DE972FFB
+:10EBD000174FE6CF92C983F6F883827EB60AFF66A6
+:10EBE000A3B0CB9DFD14376BFBDC68E7DFA4552A8F
+:10EBF00019F8735CABDD2E286AB1D3FF98663BFD34
+:10EC0000878C02871D9126BD65EADFB5BEE078B42A
+:10EC1000BF2A997EE4F680265BF7D79DFA77A71A7C
+:10EC2000FB99EB2CEC907020DE82F876DAB5FB04D1
+:10EC3000DEFFA2C4D288DF801ADF47FDAA719237B7
+:10EC40004E3B61089CC0E09C3C229CBF3A1B384F65
+:10EC5000B71FF0911CDFF22203797616883C8B10E7
+:10EC6000D91F1D21EE9F74B8B85FD02FE8E80D972B
+:10EC700042F33B26CAB303D092397F8CC7878EA359
+:10EC80002182F54667CED7450B85BE8FC9FCFDB8FE
+:10EC90008BEFABCD1E37F2381F88717EADC6FEBF3D
+:10ECA000CBB26FF3A42BF69EB5FCA18BEF830DAC1A
+:10ECB00087C8C735EDA53D6AEC235786BCB49C795F
+:10ECC0002AEDDF9E00BFA130FC3C930FBB81C991B0
+:10ECD000672481CFDFFB488F99F81EB0A7517EA033
+:10ECE0003E381C4861FCC45C0773DFC59C87693FE4
+:10ECF00094B9B93C6174E37313DC71BE3F08699247
+:10ED00000F05826EB6FA16DE53CB9E77CF7CFB35AD
+:10ED1000CC4F78F7099F8E706DAA3A12B6CA4D682B
+:10ED2000B6D38FF9DEF5F118DA97BF554A8C765BCA
+:10ED3000E328917E37B67F46D2C97F4BBEA290DDD5
+:10ED4000FB8C949A44FBE82AD0FEC533374653EB3C
+:10ED50002DFB1B4EBB3EC7D7F7C0729C7733B39FCA
+:10ED600060E8BA9976B959C63C106BFBF96CD9B911
+:10ED70005DCDA6CBF8BA42CCDB50630A100926E879
+:10ED8000391D747A32FBDF7033BC5D00FDF9C84772
+:10ED9000AB03632FE2F6C67F1BDE66E378FFDBF092
+:10EDA0003648B74E3DCDF719F2041E42D042FBED76
+:10EDB000BF685ABC6E021BCF5D18247B35AFA9FD1E
+:10EDC00066398CD97DBD1AFA977962FF1B1AB97E14
+:10EDD00036F7A373EAEDFADCA9BF3DC2EEF00CA34F
+:10EDE000D79D727338BDBEC46DD7EB03F1E261E409
+:10EDF0009F335E7C7AF9A7DF535B8C7919B1576B2F
+:10EE0000D9BAEC9BA5527C333C1EAE8B5BE8E1B0DB
+:10EE10005BA1FE0EBB791C643DE3D7D4399CCFE1E6
+:10EE20001CD4074C01E1FE41919CC2FC9AB5C95427
+:10EE30001DE69BAD552768D675AC2E62762DC3EBCB
+:10EE4000A61A7FB3D5DE7ED3EFE271D840F541E458
+:10EE5000C7F260AA86DCBB1873FC46F13C4B5CB77A
+:10EE6000F334E8C37D570F70BDCD38C2CBF54AAD42
+:10EE7000F616E56326E0546024BD60CFBFDCA9A68A
+:10EE800056FB111F111E6F096D91281947E989A5BD
+:10EE9000D17F981C58B095E4901A2FC371F64E6339
+:10EEA000662FABFFE15E37D9393DA1312ADA95CF24
+:10EEB000C88BBFE766F3ED7FDD03B87FD2F3D9B926
+:10EEC000748EA12774D15CA4831E099827CBE6CF4A
+:10EED000F88727FB4000E3F4E13931C03865FF2FA4
+:10EEE000C078888DEF8AFE344E79BA100BC833583B
+:10EEF0003B1F7461BE8AF1A9FFFD4B18DD3D1EACBE
+:10EF0000BCEF7C18F4FB4D7FFF627FE231E4C78EDB
+:10EF100051BF6B463EEB62702A6487C5A2087765D5
+:10EF20009E4CFC0779C1D404F6BEFA60A416F3CF58
+:10EF3000AAD50A94340C0EBEDE877C892771BEB533
+:10EF40005A436D36AB5F7548277B656EF4E6FD5816
+:10EF50009E7698973BDC40F620F22F58F8AFFAE304
+:10EF6000B134BF5F0A39DE1E8DF5C6A411D64353F6
+:10EF70001DE737EC792B563AD0A6D9E820E1B2D27A
+:10EF8000C10C460793AD741093CE860EBE8D5838D3
+:10EF9000237EE17C729BC2F96628DDB77873CA874D
+:10EFA000F28739EEFAAA9C08FA19261F68D3EFD225
+:10EFB000B0EC59E4267FCFE40B931F4E7AF9BE02E2
+:10EFC000E38B3A1F7B3606F54B33F105FA7356FA9D
+:10EFD000BF72183E990FFDFB31C77EBE0AC92C26B1
+:10EFE000427E7DE1D1D2B116BA77E269FE2C098E5C
+:10EFF00058E4D1A953BC6CC1A33690F7AC9C39BE80
+:10F000005F56F58E8885EF3A99FD8C4661976C4086
+:10F010005E31F2DD62BF07FDD5FAC7A214CFF7C497
+:10F020009B294F6DFA3B811B181D7E384AD671F221
+:10F030001DFAE247897F5F0B00DA6D9BA62D1987C9
+:10F04000FEC9873726C6A13FB68EE1FF081937A94A
+:10F05000D132E53EF58DE6FB637A943F1351FE1EF7
+:10F06000C4F79428C744BD3EAAC7D6D9260F377B1C
+:10F07000397D6FF6723B709DBBDB8BFCD55FECA5D9
+:10F08000FD53B3DE250AB7DB6678787D38B946C70D
+:10F0900078D50C0F6F775F5B2AFEE6048473073D1B
+:10F0A00073EB5380F17F7F5952C7F8BB7735243219
+:10F0B000D97DF779791CC0BBEF9F68DF28B7D4A052
+:10F0C0003856A49EF56759AFF90C35594C7E30700F
+:10F0D0006348C71DBA9FECB0F9919A3FA95386AE19
+:10F0E0002FFE39625927EF5F95440FC50BF87EC696
+:10F0F0004AE1CFD59678892F3A5ADDDB712A0B3C4D
+:10F10000D9DC0E8DD48C982F8B7E53D283712E2F09
+:10F110003D713F23790EDFCF487AF87E46D2C3F7A0
+:10F1200033F089FB19F81DF733B0FC93B6189571CD
+:10F130005F03CBB8AF8165DCCFC032EE67E0734FC1
+:10F140005B333D7FDED642DF9F6A6BA5F2251E6EE4
+:10F1500067435932BA80E1B9EB76770CF7A9D789C2
+:10F16000F5793656926BB075F445B8DFE97BE15E10
+:10F17000C0F9F8A23C6ED419BD17AE67CFAEA9A1F5
+:10F180002EDC2FF63E1AA4A74FBD0FF420EE4F241D
+:10F190009B3153B6C5F3C41C95E9F7D2E8CD353998
+:10F1A000AC7CABE7C93518BF9AA8AF32166B836544
+:10F1B0003D54B9E4314B795CF976D5CFEADFB9F645
+:10F1C000E935C8A708071A6F1D9EF49C556CC9D372
+:10F1D0002540E735FA8BDD29A4B3AFE17A21FD782C
+:10F1E000B85DFF655813453F799CEEAE44FE60F56F
+:10F1F000D39C2ECFACFE3ADC94CA1BDA6EA47A7292
+:10F20000D519D5036584FEF0BB34423F1DB046C31B
+:10F21000B3631B9097312EE80B909FD6E5E27CD923
+:10F22000E5E3CFA35E73FFA8669E978D3B4FF06921
+:10F23000972F5E87F9CAFD93658A17F4B858179817
+:10F2400084DB5AFC9B1236EEADCFAB8071E694871F
+:10F25000DB3713C685B8BEBCD34BFAF24BE37EDC7A
+:10F260009EC3CA13BE6F18A8FF3680E1473A496EA5
+:10F2700094693FF74755E3731A58F5F3A63E918317
+:10F280007184CF047FA7F07C112BAFEAB8611CC654
+:10F29000953E7C89CBA547C538DB5DBD2DB49E531B
+:10F2A0008364370074935DB02AAAD23EBC9CCF9F82
+:10F2B0006E97F67758CFCD146F92C1E3FE6CBA9774
+:10F2C000FCEF8F3DE25C5A2FD90B6E5F42CB66EFAD
+:10F2D000BB9332F1FB1ACD9FC2D4FB0DC14A3A2732
+:10F2E0009B2C5729CF7A43398FD3054257A7D04E4D
+:10F2F000B867AF8FCB87A097F2AD52E5BB0FD6446E
+:10F30000F0296BC8EFA9D8823AC2BB266B94B7C567
+:10F31000FE46DF9B239497BD01C4BA34F37866C7D9
+:10F32000A84F7F85F1DB355FD70C715688F21EC977
+:10F33000B491F1DC6EFFBE00C2F315F39C51DFEA1D
+:10F3400000ABDFBE5833701DA66835751827ECD0AA
+:10F350006ABCC85781C9B5DE45248706F292E93CEC
+:10F360005B7B39B757F13BF225B4C37E3CBF3246D5
+:10F37000C8B24076A584764E473D858D306FD796CE
+:10F3800067D99E7319E5B12BF37308CE0E8879B156
+:10F390007EB29EC79DC704BD69B4E3C698F1434CD5
+:10F3A00031B6F811B937D9F394F39B55DB398ED1C7
+:10F3B000097B394FF805798E7CE64F3DE63E8A1D84
+:10F3C0004FCEF9E6461ECA467873F160B23E743EEF
+:10F3D000F7452A1B709E63343FC11DD55657A3FCC9
+:10F3E0001A0D2DAB90EECE1A5E079C53CADB7B71D3
+:10F3F000DDA7E82A9D5B381FFA5763BF1B049D7782
+:10F4000015DBF564CAC3FD06C68F95C88F18E74A99
+:10F410005AC6C7386FD232DEF8AE1C5B79427781AC
+:10F42000ADFE395B4A6CDF27A5CEB57D3F6F47A5A2
+:10F43000AD3CB967A6ADFEF97B6A6CE58AF465B6AA
+:10F44000FA171C5C602B4FEDFD3B5BFDE9AF2DB661
+:10F450007DBFB06F89EDFB454757D8CA17F7DF610D
+:10F46000AB6FDACD4EBD58EEFD7CF6B207CF75D945
+:10F47000E282767BDC694F7BFFBA465F8D722DECB2
+:10F4800026FA56518FB3F28ADBB93FE39D6DE82827
+:10F49000574A841C0D056317E2BA5587BDA40FD4E3
+:10F4A00020AFA706E792DD31760B934717A015082A
+:10F4B00003DF032897DB92F152D720DC3EAD9BCED1
+:10F4C000285487EB00E3BD667B558B412284E3E93A
+:10F4D000DC9E61DE22D6F3E9ACBD651ECFC8321DCD
+:10F4E000E9EE677ED74316BF6B383FCBE9579DA93E
+:10F4F0001F3556063F3EB74BF1167C96B7BC54837A
+:10F50000E974CCBFFA0AE261933BDEBC1DF7434AC3
+:10F51000FCB42F66FA575DC53DC417FDC52AE9172F
+:10F5200050F5F20596F8569797CBFB80F701F2EF6E
+:10F53000D492190775C4FB2A95E20E1B241E1F499D
+:10F54000B27540BDB66DE6D1F7FE91BDF79678C7AE
+:10F5500078993C329E75C770BFF33E81D712ADA239
+:10F5600086595CCCBE68D887CF893AB333D8B3AC60
+:10F570006CF33E7CDEE1E5F974E71A8FD5A02CF13F
+:10F58000CEE6F69F32C59D5A8DEBA7713886A33320
+:10F5900035670BDFAF2A55DF427A436BFB943C485B
+:10F5A000073EA403899E443FBE4890F4860F0F7720
+:10F5B0006159955201F63D521A9330CFA23ABC855B
+:10F5C000F6557C69BBBDCAFCCD2EC46BA4DEBEDE85
+:10F5D00001EF3682AF5DE2F1D7AE6CFD851A067F92
+:10F5E000575E490EC64E303ED16091379B85FDD6A1
+:10F5F000E4934DFD4FF24646DE983A68EF30FADF6D
+:10F60000228F47F8BA01E596EFAE6E407AF7696C43
+:10F6100035D1DEFE5692E8DFB4776F11BC555BD270
+:10F6200044FB5EEF472AC9BEF5B5FE2423FE7C7D70
+:10F630000AC42E181EAFE1895B49DF43895B47BBD3
+:10F64000A25577C7B667900786D007EB30CF03E1A6
+:10F6500011791E5D021FE6BEDBFB66FE93D807BE76
+:10F66000251B6CFB7FB7E4558E1EC91EF731BF2FDB
+:10F670006181771D1B07F1D271B2A12E4EFB80C0B4
+:10F68000CFA57D56BE9DCEFF0AFFC510F6CB0C0F51
+:10F69000C7EF5837909F3007E31717A0B7F9E53A3F
+:10F6A000E44B33DE71C49B43F83792A0B490BDE2C3
+:10F6B00032F5967CEA7C8259779B714A3279B95E41
+:10F6C00063FFEEC57314E3BBECE7932674DBCBE773
+:10F6D0006CB19727A5EC6566351F42BBA001387E4B
+:10F6E000CEDB61FFDE60C6F96AF9B90A2F1BF91497
+:10F6F000D7BFB673AC20F4BF194F2DEA4957A37892
+:10F700002D5C69D7AB0542CF1738F4676548213FB8
+:10F71000BFFA60643FDA8F66FCE510267F59E2A9E4
+:10F72000661CC529CFFD873703FB42FE72C2C3E3C7
+:10F730000B09E6DFB4168AB845117FBA14FDC585FA
+:10F7400064A7B59C83F2E9696FE2032F192DF67364
+:10F750000FC7EBD45F483A1F276119E7B6B2E497A9
+:10F76000F8F453944762C6314C3FFD642036CFCB4A
+:10F77000D67D83F172CBB318477ADD03D8CFA5CA03
+:10F780000B07DB587945914A798FDAF49BBEE7C7BE
+:10F7900038207E67E5EA627D34D1FF732EF2D7D739
+:10F7A0000A7A36CFE398718F6C1FB79F433ED32EF2
+:10F7B0004AFA455EAB1FEDDCF37630D96CD3733C6F
+:10F7C0009E66C6CD26F7D8BFF78094ABB1F53BBF98
+:10F7D000292573BB2A16ACB6C4D5CF15EB356561A8
+:10F7E000FADE85ACBC0B5295783F4485A00B63BF15
+:10F7F000FDFCD72890E89CC0A8438A9162F5A73CFD
+:10F8000065FF5EEE381F76AEF3BC9823CE1B52E048
+:10F81000BD456CBC8D7A8B84F273E34266C3B3F250
+:10F82000B93E912F3C112622FD5DAA048D34E2F7EA
+:10F830001585F486E78D735E5D84FAFC259E97A29C
+:10F840008DD737D7B2B2F62B85F49316808A8AE02B
+:10F85000605CF8FE5306B4BB06E34C3BD9BA964E47
+:10F8600040FFDA0BA8577EC2D617CB3DCC1FC7F29C
+:10F87000E3CC1FC7E76EE68FE3FB9F317F1CCB7B9A
+:10F88000983F8ECF9F337F1CDF3FC5FC712C2F0F1D
+:10F89000545FE28C5359E3768371AA3EC98C53A11D
+:10F8A0002839EED6699D07E255091EAF3A7D3F31F2
+:10F8B000B31F8A070EE947C405DFBDFD778FE079E6
+:10F8C000E9A5535777E1B957AFCB8C8BF13C08339F
+:10F8D0008FD9E4BFA5BB6FA6FD6077FEA1165C8F34
+:10F8E000DD5541BA53C8ED4A68281F9DFE97E97758
+:10F8F00039ED5FF3E9D4477EB4032E403BA99BE288
+:10F900003EEB5D5046E76025BF817CE18C439A7CED
+:10F91000FCA2AF24E3F9A5817C58119FF140CA8B6A
+:10F92000F132B724E629F2354984B12E36203F5B07
+:10F93000F28B83E5698A73048331B2BF24669791A1
+:10F940009DA625A21887EA1C26FFF541C1A7ABF2A8
+:10F95000DD746F44673EDFFFAF2D34A2D87E4DFECD
+:10F96000B4A8351FD6CCD7DD1F9AE6EDB3F4B72285
+:10F970005432A29E52985ED547D0AB8A87E7ABAF90
+:10F98000D977A117F390D70717F7A27DB53E1AA133
+:10F99000F3EA7BF3A791FD31503F3A83F29595202E
+:10F9A000B75B95A897EC5615E75F3E58DFACD72AB2
+:10F9B000E433633F8ACF05823D54CFA3C629FEE1DD
+:10F9C0008900ED5779BC3C5F20C8FC6BAF2D6ECA37
+:10F9D000C7BDD9C7E5DB7A3D11C776EBA3AA8EE296
+:10F9E000687D5925E1798DC0F39A3C53EF1B646F14
+:10F9F000F4083968F6B346F8EB6B9ADD6477C55BBB
+:10FA0000B363B5B9947FF903E4BFF5C187BC98CF60
+:10FA1000EECEAF1AB1DF27C5FA0DDFEF1B35B517F4
+:10FA200050BF3D3E36BE3BB458C37E5DC3E4D91FD4
+:10FA300014707E5EFB92614EA3FD2E30F56D2A6A36
+:10FA4000DD27763EFD68275E30B4DD52BD6F2EE6C1
+:10FA5000F9AA90ACF32B43CF292CDBC3EF9DDAA49A
+:10FA6000F692BDB3E9A494F1BC43965F12CEFE803A
+:10FA70001F6EB357C6087E1A23BEEB68AF14A35F90
+:10FA800069B72F2E38682F4FEDB597A7BFE6B4574B
+:10FA900062AFA0BDD228E45D2F93CF3C69A25F4541
+:10FAA00039104FA6AA11EE06E85985FB942E11676E
+:10FAB0006E14FAEA0AA1CF5C7E1E971DD3ECB7F94B
+:10FAC00089E6FD1985A2FFA2DAFD37B7A3708D9BE9
+:10FAD000F68F4EFE65D1BCC7AB494C3AECA0869878
+:10FAE000FDFCE9150E3BC7690F55ABDB29BFB2C062
+:10FAF000117F30F729719E780ED739FED98E6BF6BB
+:10FB0000B795E92DB457CC7B09E8DE2ED6BE484D1B
+:10FB10004B06C353410B50BEDF989510DB9E818E80
+:10FB2000A789751F82B7E42584B739E25D4190DF6C
+:10FB30007B5250ABA4F462CCDFEF21FDBDE0263652
+:10FB40001FB2974FD13EB4593F27BB672FEE136EBC
+:10FB5000AD97B8FF9804B243CC75DE1AE4E7651A96
+:10FB60002E965232B66F29A1F109AE92C1F5657891
+:10FB70003AC2F1C4F3CBAEACB39FEB6970D81B268D
+:10FB80003D5CE178FFBA4F23FA30F9E0DD0B5F9B73
+:10FB90003896C1B1544AD6059433D79316FE709D5A
+:10FBA000423EC4BF8FA2A9107FECF3FE54A3FC8099
+:10FBB000ECBE078091E4657E48D6CE02F8377FFF21
+:10FBC00079122B37F8CB3BBA2EC6E389FD3F42A30F
+:10FBD000CCE3A9B8B4AE68B0ECF75F4CE588188701
+:10FBE000B91649BEDE967B0A18BCDF15F9011B6207
+:10FBF000B059C11C4B59DB6C140FB6CBC176D2087F
+:10FC0000EDE2B059CDD02E68B663E8EA34EFF528BE
+:10FC1000C127FF2E0B78ACE3AB88374D0FD2B99DCF
+:10FC2000B9AA86790F5F148E51A79B770236BBC69F
+:10FC30000F6DC7C05E65C22F67863F85DFADE3BB32
+:10FC40004680FF6F8D8FD3F5E716DFCF1A3E567DC6
+:10FC5000F5A8E1E78B70B9E87E0C3D285BFAB9673F
+:10FC6000EF2714BF56AF053A97A3BA629AC1E8BC12
+:10FC70005CFB36F9E16A76AD8676C03A56463B6063
+:10FC80005D4F37C5A9CB4BEFED42A22F4FFB01E5EE
+:10FC9000C164D0B277B17E276B2A66E2807AF17EAA
+:10FCA00019E3DE7039D0B990ACBD7E7E8F45F1CCC2
+:10FCB000EFA37F949DEDA53850207BDAF7B9B1CB47
+:10FCC000E3C126FC81EA43351827571BC040565430
+:10FCD000A5145423934D02DA87F0C776DF86E72B0D
+:10FCE00099E223FD44773BA05E1571F1D19C64A09D
+:10FCF000CBAD35A09F907C5EA5F8FB68BCF2861169
+:10FD0000657979CE6684A73CC13A90107E1ED79A59
+:10FD10009C908D34EBBFF23DDE0EFE9D9F0760BED2
+:10FD200044D313C141BC9A7265B488974717DAE38C
+:10FD3000C9D0CFE6CCDA57FEFB821F603C61D410FD
+:10FD4000F9CDFD6BF3DE9CACF720FE04ED6BDAF52C
+:10FD5000865FDC4FE177DC7B302E683F8737C46FEE
+:10FD6000F8569CF480070CAF9BEC8B85643798FEAB
+:10FD7000C856AC88F1FF22E079D9CEF6D3787B88DB
+:10FD800072FFC4E367665E25FBBEC41FA37C1F0F22
+:10FD90002B333C4A6EF0E6B3F705328F8BAC9240C2
+:10FDA000C5F2E07869DAA75F2B195D8634E8FFAE0B
+:10FDB000D10CCA1F809539367BD9CC435D7163F174
+:10FDC000E81CF6CC1A3CFFA3213DAEC82B25FB391D
+:10FDD0009CDBF7F7285F8FAF5F7FA917E529E62F38
+:10FDE000CC04F8ABBFA323C9E4ADE7E331A05BECDF
+:10FDF000328FDA427130CFC7636DEFD36DF6F38285
+:10FE0000B1A05C8BE3E461F23EC683416BC776D55B
+:10FE1000603F17E8F938DF66A70FF65F687B9F66DB
+:10FE2000F68CF53E8AE1FB0F805E66ED7FFC30FDCF
+:10FE30004F74F4AF65EC7FB0DF5C5BBF1D2A8F8F22
+:10FE400026237E5A77A73D3039505310C81B217E98
+:10FE50001FE0F1C7B5D1168ADFD700637846279730
+:10FE60009C3CA2F0F36B40761B14DAE3F735827EFC
+:10FE700065461148BF97A8F67BC06683F35E30BB2A
+:10FE80003DD48B8C827E65A8AA97E2F89F0475F416
+:10FE9000BF86B3977BDB80E2C7B3037DB7E03EF557
+:10FEA000A51B1E7075CC10F9AF05CC8ED8D0732968
+:10FEB0009EF3EB15E7F33A2232E1255E339ACEDB6F
+:10FEC00098FDC4DD3001E5615CE6F909F4878DDF5A
+:10FED0009B57F0D0FA0CF8739EE76C8849F1520BEF
+:10FEE000DDF4CA0CAFD6F1E68CD9AE58E611F7C0F6
+:10FEF000541A4FD8B903E38DFA7CE3BD24E24EE6F1
+:10FF0000780D73EDF36B706B34BF06C1BFE6782FCD
+:10FF1000E1FC32E0F7B4E3C99C6E06C6FB927D7E3D
+:10FF20000D1E8DE6D720EEF51D186FD4E71B6FADC3
+:10FF3000AB258176DB6689F3FFDD817FED40BFED88
+:10FF4000FDFA1551D207C22EBE021BB07A57A87C0B
+:10FF5000BCF985DED42ACB785B991C88893CF7985C
+:10FF600007F337342AA7DAA2F47C88D9D931CADF5B
+:10FF700028A3EF8FB41954DED136839E663F6533D4
+:10FF8000F83D3393664919EDED5F06B8DFB8395F88
+:10FF9000BBF66BA897AAFDFCFCE38C8B2066B17FB7
+:10FFA0009941BCCF87FB2F574305EAB6895B38DC04
+:10FFB00091DA51295C3F7FC5FEDE3656F6B85C3AD1
+:10FFC000EA53C60BF14C7EEADE00F7C33D6E2EEF1E
+:10FFD0006126BFB770BED02BA0D44B2EC4C715D995
+:10FFE000B4DFBFA03116D218DE1A25E99552A1A7B9
+:10FFF000F0FCCA5562A99C767E043506EB37125395
+:020000021000EC
+:1000000052781FD15585079B502FC74357927F10B9
+:10001000670D73583F57093D59FD860730DF012EA4
+:1000200075131C8D8D767B7EB32FADA17DB2B92269
+:1000300002B83E0BEAEDDF3D6ECE8771C73D05F39A
+:100040004F736F01DD9D95218FD4199F7C32608F96
+:10005000439E80F27B6AF1636164C47B0B5604C0EB
+:10006000BCD73263FCC884E74D94635391DEF650ED
+:100070003CCC84AF404D4928AFC734EFB1E53531B2
+:10008000C492316CC6E141D955817E88733E5BA52F
+:100090005DF923DD535200EA5B7D65E21E4F69E89E
+:1000A000BC7F1710F9B703F39EF5622964E21F1EA7
+:1000B000779D7F503156E9837831F1F03FCD479DF0
+:1000C000018ECF17E77C50C5FDB742DB7D99E63D39
+:1000D000C0570E9455502DF47CC51237D93310EB10
+:1000E0002F47BA3B747180DFDB66DA2FE9D765B43E
+:1000F0005FBE78FFB1225BDEA6E877B8F572E61145
+:100100005ACE7D0EE6B9637E89C4F7B10A30CF2D91
+:10011000CCDF1FB1DB99B63CB7357B7F28619CEF04
+:1001200001CCC7B3EC5B8F61FE3CCACDC29BEC79BE
+:10013000754EB8CCBCAA8173B3B31AB55D3ADD93E2
+:10014000D88D17CF746D49C6C1921F699E1334FDB7
+:1001500069E7F94025C8EFCB8B8AF316CE78F06DAE
+:1001600072522B96301F35E5AD66CFF29C848147E5
+:10017000D36F539275F85E193DB319F1B0B0F54ED7
+:1001800003E3775A6EE6B8F442A1BF2F0A72BA3978
+:10019000EC4A17611C3B91537351302F43FDD66FCE
+:1001A000517FB387B97FBE51F4F380D0E7CEEF978C
+:1001B00007795CE59AA532DD67E183504A2AC67D5E
+:1001C000E3EE19742E6FD95623D3B9B783E144BD3A
+:1001D000151E5F293F6F0DD07321E26BDD5F1EECB2
+:1001E0007994A132E72F4192A3390AEFD7D2BE31D9
+:1001F00053FB673EF92D9D537E06CFA9CCC4FEB6B6
+:10020000CEC5F8F7A6813224252C678B72F2B6B9D9
+:10021000E8EF0D962BE6566319699011D9ABC1DA58
+:100220004EA4974D120862BC94D777F1FABBC5F77C
+:10023000D997BDF37D3C970BD3DCE4076E12F688AB
+:1002400009DFEB419E37F3FA69F079ABF81E447C85
+:1002500046CE0A9FB766C2C7EB39B1DB8253B19F66
+:100260001EBA17D2F717EF4ACC23FEA73630BEC608
+:10027000E6F080B1FB87F700B5FF5670EAD0F6F3E1
+:1002800072626DD86F70E9119A5FA83488EE0DAC78
+:100290009B0ED44F0638D666EAC75CD774169763B0
+:1002A00027D076CEC375E5F69FE2E98DE2FEBF5614
+:1002B00075FF2D1A93239DC5DD4D99E8FB3B21BEAB
+:1002C0004F9D3D4CBC7A97A0C757B5F877118E76F5
+:1002D000ED5EBA4FD52D71BB61DD8C3E902CED7E6D
+:1002E00015E2F519DCDFC3FAEE0BF93DA72186779D
+:1002F0004C300B5571F8D7E98700F3BA43D14394DA
+:10030000171AAAEA237EA7A30A059CAED05FF30AB8
+:10031000FB6C57F0DAB94817398A49777FEE443ACF
+:100320005406CB4497DB7378FB97427FEE4C3291B7
+:10033000BB8DD92F78EF46B280E78D38E7F72F21B4
+:100340004E1FF787638F23BC43F0E9E9FBFE3DAC0A
+:10035000FDA609FCBCCD6CB9B7E97AA4CBCB82640D
+:100360007FB1F74DD673C86F0A7CBD19E4F6D3A6EA
+:100370004FBCF4DDB91EC3D1EB0BA2FDE7A0D7172C
+:1003800032D109A3D77F477AB3D0EB0790995E0F9C
+:100390000D43AFAF607B275E9C6505625B707F5647
+:1003A000FD74EE0EEC4FFDF2AC2D8FB2A7F2E95DBD
+:1003B000495A4D43B29D2F35C7A99012FF11B4C8B9
+:1003C00077F33EEE1B83BCFF21FD4E9FB605E5D8BB
+:1003D00019F47B2C387568BF4F0539BCB32F0B2639
+:1003E000329D1FDF1252E9FB43213EFE707C7330C9
+:1003F000C4FDD9E1F8E65141578C6FFE7A267CF3B3
+:100400008741BE7187F2CE846FBE4D4F5F29E71BD7
+:100410003A863C7328DF40F2D54E94AF9DC59C2FA1
+:10042000466F7AB313E31C037C943C41DF95C132E1
+:10043000C963938FFE73D309E22367FBF030F75251
+:100440008D15F33E188E17E13C62E769EDFC9C4D7B
+:100450001FE9EDEDD0BFD74379B63CAFD59F4CC671
+:10046000B8D9D00B78BE7FA2C0C336F4C1D0CF9923
+:1004700026E24C6A2F2C080DE5E75055BACA7A9F40
+:10048000C0D362FC0F43F1C9A1A9385EDF24B4BF19
+:10049000865BA74A31DE3DD9B1CA5006FE3F9D1E9C
+:1004A000BA26C4CFBB5E23FAC9F98BB705ED4F2737
+:1004B000BFCF5EF6F33F3D32423F8DA27D7DE873B4
+:1004C000F37F7D2833FF5F1EB2F37F15DEB799817E
+:1004D000FF1B33B567FC7F55E86FCBEF8B4219F8F4
+:1004E00072E619E2FB6181EF87BF20BE570B3AB974
+:1004F000E3F3E3FB8E61F07DE719E27B7528837DF2
+:10050000C1F0BD2644F6CAE3047F480F521CBB6B02
+:100510003AEC964A32C2B1C1DA8F57E7FD30BC7F60
+:100520002031BA9FFD699791E99E19D6EE5E2BFCAA
+:1005300066BBCA9066266FDF8CFEF9035F0E52BC65
+:100540009FE9C7FBFFC674F050263A982D7339F423
+:1005500041F0B14E8CB37D81FE7F92A9FF6621D719
+:100560004F6717EC1574C1E6FD4468EA50F9B75DB2
+:10057000FC2ECAFDE1C45321C257DF3C9457DBEE89
+:10058000C891301E55184B4BE8273C2EF4D87921E2
+:100590009D9F6710EDB6A96909F359B6B568129E1B
+:1005A00037B2F4F74B1C6FB8FE9C7030F89EC3F165
+:1005B0003F0CC59EC767A598DFD9DA490DD9B19719
+:1005C00043A47FE287486E9F6397DBE63CE478377D
+:1005D000E5BDF86664FEDD96C783AAD063F1DF5BF4
+:1005E000E5FF2B0374C5FB3B5BFDC3E07B2BC4F530
+:1005F000CAD14CF039F1723A38F34203701EC77E0B
+:100600009D7ACAD99FE9B79AEBE4469D648DEB0CBD
+:10061000E8BDC45F897F3B643A87345FC893F93390
+:10062000B285DDAEF9B1FF07449CFC819BEEADC6FF
+:10063000FDEEED77691588828266AEF7F49BC652AF
+:10064000FCD317966C714CF339D0DEDD3309EF190A
+:1006500067E386C2ACDE25B3208D7E6316DA0D1407
+:100660008FD0E877BB723CDD518C9FAE93BA9B165E
+:10067000A35E9D17E4E74AA28DA7B9AF6DB58D6E55
+:10068000215A759AFAABA8BE16E8A6FB2FCEB8BEC3
+:10069000A7BB29537EC994B06CE275527824BC463E
+:1006A0002314D732F13B741CBE7ED5F11609F11D1F
+:1006B000AA92343C7A15627482F6925CDA4BF94C59
+:1006C0009757717A01E6978C7C7F46A769AFCD0A70
+:1006D000E77D71B8CC7AC38F27EA39CE2BE0BE17FD
+:1006E000C567835C8E5145563E7E303763DCDF7CC8
+:1006F000AE6DD30A5597B5FF14E179ED40FEB41104
+:10070000457BAB15383D42D44B7618DDCB6E59CFC7
+:1007100084589FEF66C5FF3E4CF019740F2168DACC
+:1007200019CD87B55B4CED54D62E74E6ED867F9AD5
+:10073000BF5767E871CBBD6726BF8E4E2401EF9986
+:10074000F1978326B1F58F84CC7D424E07DF0E9A58
+:10075000E5246D92C74BBB795EBE6ED209972B5ACA
+:10076000A0272657006CBEBBEE4BD149ACBFD2448C
+:1007700014AFD067E5032AF9E1BC0CC9BA03FB0B3F
+:10078000917FB4732583E9A9F6DA03072F067E5417
+:100790008A7E4FADF600C93BB38C175294B1B27F3D
+:1007A000A01CF34659B964A09CC4F236A12737DFD8
+:1007B0005D7BA03D48726CA3953FAA051DFEADE987
+:1007C0006FBBDEAEE13983645425BB6A9D831EF6A0
+:1007D00084F97D2C93B5C4365CD7F977F5AB787482
+:1007E000C55B1C09213F8C8B7E90C4FBF2C6CD12E9
+:1007F00069AAA5FC9E86EDD195C497DB715D80A7A3
+:1008000025607C72707D5299D7A72C45EBE3D7F910
+:100810007719CBE46FF3F85BA08CF3B3E6E1F1BD9D
+:10082000C704BDA6C33C7E9416F2352BDA4EFE9467
+:10083000B74EA6F871569D6CD31BF48B77D44EB58A
+:10084000DDFBFF7A4EE2A9B0452FB01AF132360F28
+:10085000FFA4480EEEBF5497A92BD1DFFE9EB0FF38
+:10086000D83A3D40EB5411F127486EC79FB5CA8F67
+:100870008175137839DDBAFDB62D61D4BA865FB7BC
+:10088000ABAF5532DE93F6DB30F75F8F35FDE7FD1A
+:10089000389DA5DE7EBABFBBAB7415C561CDB8ABC4
+:1008A0006777757A8C3E980FB83A109E854FE7B8F7
+:1008B000BF3DF95D8DCE897CE2C9B89F7452E0F9E5
+:1008C000505B13B5630B4CBFB7721D4E85E7B1D9B2
+:1008D000CEF199E711BE0A9C181AE38B2E4739B462
+:1008E000B849A17B1BAE037B3EC557CDBCAF563389
+:1008F0003F8EE77D25207B2EB2E1A2A4E3F722C044
+:10090000988BE7E887FC8E84D8DFFABA236FE29AE7
+:10091000A64546ADA8F73EFD3F45F369D4B9FC6D49
+:1009200034F8FD3D57C5AF356A2DFBD1AF7EA664C7
+:10093000CC9B9C9765E2236ED44E188A8FC571C9F3
+:10094000ADE9A7C7CB99E261915A31374F1F8A07AA
+:10095000E7FC19C636219EBFCEF08C76E770F860B2
+:10096000F5683D5EBD56A1DF8F99ABD4BB701FE427
+:10097000FA0689F698187EC3222FAEFE520BBC4EA3
+:100980003C3AF175FDD340E706AEFF4E88E26D2F8D
+:100990009BF8495F42FB17E6FE89659E4778FE9605
+:1009A00046F35C30A3E217786F42A25DA2FB1AD92E
+:1009B0007C6DFB808B219E85E716D8BC8F0CB3EE37
+:1009C000B6FD40277C4EF87D42AF38F7C5404D97C5
+:1009D000A31E9C9D25F605A78021F6C7B2281DB74A
+:1009E00034B3BC75DE3767D2D975AD0D03E362FF52
+:1009F000122406CA1A9ED77A4ED97415FBFB8A2890
+:100A0000FF1DC3F8B5B91DF86D3E98BF2F14A3FDA7
+:100A1000A6EB04FE1A98C787BF7D7609134EB8AFC0
+:100A2000373FE6D38396791EEF96EAC439AAACC65F
+:100A3000C9D82EB957993214DE1551FE7B858C0E1C
+:100A40003FB0D2A16F02BF47D68917135F8B06F163
+:100A500032E56CF0F22A2ACE3CDAAF213BB75FF2E6
+:100A6000D27978731F87FD35E966A2F3D6AC62614F
+:100A70000FF0799BF77701B4907DBF509CC73AEC9B
+:100A800082A6C7827C5FA7D222B76ECBA9BE35CB28
+:100A9000E2579BFB3AE67D51263D7FD51B4C2B9CB4
+:100AA0000E6DF7410DE63125288F49C9BA49477CBB
+:100AB00074E1A70BC9EE5985FD2B01BE5FE57BEE06
+:100AC000A75D57E983EBB7FE6B4F744F6565FFD7A2
+:100AD0007F93A44EF51CC25B48AC5BB55837133E00
+:100AE0007F397F6F593F1E3F2B13F133B18EC3E91E
+:100AF00009731DCD75433B0AE9D757A67E9AE9775E
+:100B0000F7607F553FF26922AA520E5D427AB383A5
+:100B1000EED9027D1BEEBF5FD7EAB2FDDE5202CFF7
+:100B2000E963FD753EE19718D47E713E6F0F65DC79
+:100B30006E1CA0FB246B6FC903026F7814AE5B1FA1
+:100B40006B8B7962ACBF51A8EFA1CB324EC9D0718B
+:100B500087EDCFD14E19D837310CC322AF1FCBE26E
+:100B60007AF278B4AA47CE107F319F8BBDB985AA9F
+:100B7000253FEC48BEB729E3EF0689FE06EE8D1B44
+:100B8000B013DF39B07FD6A09DB8C1F5C703078B7E
+:100B90002C7622FCF100F9ED03E5B3B3135FCFFA35
+:100BA00023D9891FFDDE43FAEA789D9FD621B775C8
+:100BB0000EFC079EB755F1B7FCC8BEA77B6FBCAD56
+:100BC00063683E92CA3087BF07A61B12E2FB4896B5
+:100BD000CEF7637548871870B9AA2121BEEE15FEBD
+:100BE00028A3B349D6DFFF3D22E66B8EE3F1421224
+:100BF000CF199BFD323A584579A5F5407AC4DC8778
+:100C000035F9D9ECE7589664CBAB3E03FE3D9635FB
+:100C10007528FFBE20B7FCE11FD17E7D5EA17CD090
+:100C2000AF446FA7F757B75E4FCF6B5B6FA4E7C7B3
+:100C3000423FDF2A253E463EED6DFACD576E63F406
+:100C4000BA7CB787CE952DBDF54F77237F7A5BD9D8
+:100C5000BA63BBAF5FFF9DA9ECBB7B824CF66B57C1
+:100C600011CFE770AF9278BC5F77D7ED66CFE670B3
+:100C7000F544CD02D77F01C39B58310080000000AE
+:100C80001F8B080000000000000BE57D0B7814D5D9
+:100C9000F5F89D9DD94792DDCDEEE6B5900713C2DC
+:100CA000230AC44D202128D60D011A2B81A0A8515A
+:100CB000826C0884008104B4B2552C1B021830D613
+:100CC00068B562B57C8B85D6B6DA06A52D6D23DDB9
+:100CD000085AA81463B50A562020B5286A228FB294
+:100CE000B6B6FEEF39F74E7666B21B82EDEFFBF734
+:100CF000F7FDE2D71EEEDC3BF771DEF7DC7367EB46
+:100D0000EC5347390A09216EBB811411B2CA42FF64
+:100D10002D1372F1E8FDEE05C984C45BAD1EFA84A3
+:100D2000989AB21F32D0323920921D148809647EFD
+:100D3000C5580ACD0CBA1D122185000D081D00539F
+:100D400008B184054292A09DC7D368A56529401CBF
+:100D500000C3123E370942453B7DFF0BF8BB2E0214
+:100D600095FE2C619190F1309EFE7D133EDF249B19
+:100D7000CAE07D3189CD43793F9BBF9FCDE76309B1
+:100D800027B07924E9FBB1B3E722696CB7F69FC7B6
+:100D90007D89A5231D741D7576EF288084741B2B17
+:100DA0006C84DC61FDFD61218F428B35245248FC4F
+:100DB000C68FBA7309FE7D311CFEBFCAF1FE184210
+:100DC00004D22D7C41879EF9B9101A46F11757229B
+:100DD00006D765532838CA274CA0CD4A8C1EC06759
+:100DE000D78864DB70D5F8C50E01F1F7BAE4B0C15D
+:100DF0003C2BA68915C1B1D87DCA1CE8675A4DD1D4
+:100E000066369C85A412329FFD9BBC2E6F6F194ED7
+:100E1000EB0301A36724A5E37C4B2008F39B4FA4BD
+:100E200040B7059B085F080865A988BF47E73B7F77
+:100E3000AAE88DB36BDA912FE83CC97AB26F04ED62
+:100E4000FF0E810F10A065FADE315E3C3EF5DCCD71
+:100E5000B08C6EE2300DA7EDEFE8AE9E41F2B0CA65
+:100E60000AFCB488B79BEF379EEAEB97FEAF3AA037
+:100E70002D2F28CE7F859281E225583601F8EC0A85
+:100E800003F2594D8BB6DDA277AFFF80D8A15FE9A1
+:100E9000541FBE619EE461C66FD39A1D32C5D3381C
+:100EA000878C749F39F5BDA9849667117233F43B22
+:100EB0006BAAE808D1D6AD7E03F1D2891FF28A4130
+:100EC00081AEED506EF781EB006FC5467907AC350A
+:100ED000973C785332D48F77009E2BE0D9106C4F1B
+:100EE00008B4735B8223E9B32EEF7BD61A15DF1D9E
+:100EF0002A7EEF0A1FA5D75603A98BC64F8434E17B
+:100F0000BCF6DD138FFD1C7F54089AE9FCA7899F6E
+:100F1000FF61229D4FCD7D468F59C6651980AE3346
+:100F20003C4C1E09F15AA7517CDE4158F93D525103
+:100F300014A2E3D7E41F2D31D37E6A360828A70A0E
+:100F4000FE29BE4FAAF1E66BAC480CC98877CD7379
+:100F5000DA9909F899E2F9640C3C9F54E3D9FFEE61
+:100F60009171FB54ED363B6CC9C0E7A480147C4101
+:100F70005173814C4E1C4FFAAF5B8117D71E1EB7C1
+:100F80006F24218F12EFC3A87748B754318ED2490E
+:100F900022DE687A60BA9DC9C134F123A4CFD96238
+:100FA00051067C1DF27F68A51C460E7D2E96019E83
+:100FB0008997369A1479EF870E13E279AB89780115
+:100FC000CF5B875A824DB4ABCE7BAE4CEB46FAC8B2
+:100FD0008F4F063AFEDE4876C8B1E76BF38B6404A8
+:100FE00065CC72BF8050A1DF307F1C91C647DA0DFF
+:100FF00023D1E7BF1BE498B64F59430C321DD719D4
+:1010000020DE6014BE50DA2DB7F44E9708B60F39C3
+:10101000E9FC56C886A040D79B2FC88CBF8D8DDEBB
+:1010200074DA54EA981D4827300F11E721D3F949A3
+:10103000747ED9FE042C0FF72721CCF13B118EF0E2
+:10104000A763FD487F0EC251FE6C7C3EDA3F06CBA3
+:10105000B9FEF108AFF0E723BCD27F0DC231FE52DA
+:101060006C37D65F82709CFF067C9EE7BF09E15516
+:10107000FED9083DFEB9589FEFAF4158E0AFC6E733
+:10108000E3FDCBB03CC17F27960BFD2B1116F9EF8A
+:101090004538D1DF8CB0D8DF84ED26F91FC0F2D5FA
+:1010A000FE6F23BCC6FF30C2C9FE27B11E1410E07C
+:1010B000219ECBE303F242079514E07019F83896AD
+:1010C000DC5DE4F668BEC37B1CF84E696732109F96
+:1010D000BABDD2EE1CB71B4EA06B94FE3EE1F4FAF3
+:1010E000C473F23BA349846E2DEEA60A2246E8653E
+:1010F000DE55124AA7FF5CB17B3601BD40729335C5
+:101100007CDA5F3FB0F51DE3FA6BABD4E515817F68
+:101110001B8927401F954F785D807EB6C952593094
+:101120000ABF8D761AF1BD710EDFBFC05E25649FC8
+:10113000DA07FA6456C0F18729C02F63937F3F8591
+:10114000F6376CBD0146A0AAC4D13985EA1D792ABB
+:1011500041BDB88D1094A76DF15A7B3ACCC9F041CE
+:1011600048FBFEE1284F230A98FDE9BE1EE4CB743C
+:10117000CF70B2391BE42D2448B4BFC02A42762870
+:101180003603DA6F5CF003A88FF467C2750E6B212B
+:101190002F59E844B2DBE4297114E66CF1BE144720
+:1011A0005F1919F44D89A7E5D1CF045E0278457B1C
+:1011B000704A02856376875EA2E6948C0B754FB108
+:1011C000D2F255FBC95E406B7E975C6AA3E5F1875E
+:1011D000BD7B291B90C26E5FA95D86F9049BED74EF
+:1011E0003E5B8F114F132D177FD426261215FD4D10
+:1011F000C4B7534517DB84AEA949F49F197739F278
+:1012000045785FEA8E738EED4F9F6DB06E5827B5AF
+:10121000233BE8BA32BC21C1A1E2931B9C4C6F5125
+:101220003A5CE5043BB4A65782756E5BEFB221FDD4
+:10123000E21D253064EF34E2785A063E96104FA640
+:101240000DC351DE15BEA3F8BD62B64D8D3741D139
+:101250006B75ED6363E3F70627D37FFF2DF87DC73A
+:10126000C1E421167E2DC02B932E2DC755CE3E39BD
+:10127000AE74A6C46ED7C4F1AFC7F33603D94F6DB1
+:10128000151D97F229932B12A04DD770FEBE145E48
+:10129000EFFE2FE3DB9B9C03E395C8C9A82729BF7A
+:1012A0005E417262EB1BE82F9AFD7A80E351A5E75D
+:1012B0004CE02FB638A89ECB89ADE76E755E427FB5
+:1012C000713D63E27A5C196F0BE7EFFDF68AEF8000
+:1012D000DC58371802206725C4867241DCC99C4F50
+:1012E0001CF1C02733444709E81B329AA01F9D30E8
+:1012F0003618807DCAB0805C20423350CA80C7A1B6
+:10130000B9C1CDB4EB6CEA674894FEB4AB10408B26
+:10131000EC302CA0EB4E54E4CD51ED56CB9B62EF5C
+:1013200023F2A8F0856BDBE66CC6AFB3A9FFF236FB
+:10133000C753A41F01DB6DFCC6D06D9B557A709B13
+:10134000DB8D65A57D2CFEBDA0F0EFFA75C407F21C
+:101350003139BADFF0BA53E47CDBEB053E0F7C8514
+:1013600038C09F71AE3F89FAC949F59380FA898DDB
+:101370009FE18FFF418096BB9CA95C9F3BE26FB1D0
+:10138000FDFFE3E71D4EC2F4D46447A748EB875145
+:101390003B24839C4EA6739F00F83221DD65C2E892
+:1013A000284F2641F07B29DE4206D0BF065B10ECB9
+:1013B0008CC9D4E60579262627AE7FBFDD77DC39D8
+:1013C000805C3812E47C206AAF335C66A5FCB731E0
+:1013D000DB110FE58F69B9D54DC77575135E6EB119
+:1013E000A2FCD0BFA148C510DD1B807D54CA5E0B96
+:1013F000B41FDE570E40792BF82457D3FE1FFEDBB7
+:10140000FEF51431B39DDE4F9C8CAF7B017A47D340
+:101410000D6A4E849F2FE50F28F219912747BE22AF
+:101420004FD563511FFEDD5918E92F967FB38BEB23
+:10143000CF04D7C0FE8DC2F797EDDFF0F97EC6F579
+:10144000522CF98F3BF0C696EDB4BCCA2DCAA7A8A2
+:101450007F671BFA569744CB16EA6FBE47CB064B05
+:101460009704EDCAA9845A29BEBDD4C983FD8765F6
+:10147000022BC31FEC3FCEB609654C5FCB8973C608
+:101480000D84C720AE6795DB84E3C58D1C9108727F
+:1014900065E77C4524210876DC5EEC9016607FDDF4
+:1014A000E446DA5FAECBA0916BD05BCF8F05BDE495
+:1014B0009260BF6EB69080CD15E91FCA890511FDF7
+:1014C00044F83EEE4EBE676A5BE7491C01727A88BB
+:1014D000C551DABEC9E4B23C8304D7819EF012D96B
+:1014E00041DBC711E58F0A2E2D1B7969C6DF05E2A6
+:1014F000A5F33FF87711A13082846C74BF57EE11C9
+:1015000042B00F34192C41B0A525432DC40465BB4E
+:10151000216806F93829E03A4D050941507E538784
+:10152000162776D3759C3BB8D7EA8B42FF5B7DD5F7
+:101530009EA9E363E3B1AFDDBC971D80C727E5F546
+:101540000EF023036E09E30E9BA0A94AAFDFEA3237
+:1015500029FED06C17F8430B7BD79B80DED9C9E8F6
+:101560000F91112EE4DB21EE5D9B4AC064D533FF61
+:1015700074280936A9FD2A85BF8EB87C73A19F27E0
+:10158000B91DA162D9350AE2555724BBC02F2D6978
+:1015900018DA01FEEE136B8967A111F5C14C68EFF3
+:1015A0004D6ACF07FE7DD2B3EB470F013ECD745F8E
+:1015B0000C7A7CFC51AB4CE95555B83705D6F3078E
+:1015C000DDFCFBFC0FFF37112FFA7DF03217DD0732
+:1015D0008342CC2379B00F3EE7B9293184BC9514FE
+:1015E00055BEABFCF7623FCA7EF85D6328D3115548
+:1015F0000EB5F856C6AF12D8BE961805A6FFB81D90
+:10160000A5FAE53E58277D0DEDA6D72C3C0DF6E654
+:101610009C67BC07EC762C7DA3CC87E27164852D9A
+:101620004ABD402AA2E989C75DCC5E5719E97E818F
+:10163000D60B2B0B1B615E5536AB007CA7B46BE65B
+:10164000ED147E56E25562E2E785407F880F465BE7
+:10165000FF7C229D57C7A39A41D65218BE3C51FC2D
+:101660009558F83A6C6C2B87791D5E249226DACF58
+:1016700039DFC43412E57D05BE037C43E9B21CF6B4
+:10168000FC852A7A8E888EBFC36BEB3C538D117A12
+:10169000F6ABAF8EAB04FB5D0978548DBB9FE3E5E1
+:1016A000848BD97B62F6C90E5A6F5AF098838C03EB
+:1016B0003D75BE306083B858EFCF9B80DEF7D930E0
+:1016C0005E51597DA1B0699C0A9FC5048DE4FCBDA3
+:1016D0004F3864FABC72E4FA948035361E4FB8D89D
+:1016E000BA1E800793301EB3D77519F11832D6850C
+:1016F000FC46F6C67942108FFC93E801BF01C6F59F
+:10170000A1FE64F1E4BB1C6C5E713A3FAFD2BF42F4
+:10171000A35F12C2020926A9CA523BC66713C212AE
+:101720003ED7CBDB0E178F3B717953F01F8B9E0A90
+:10173000FEF5CF431CEF87AB97C8103734C547F78A
+:1017400083D392040D5FBDB5D6A719EFED7F8A9ABA
+:10175000FDB202CF73FA9EF34D4A837855A5293026
+:10176000723072AEE0E7ADCF1F7740BF719F99A393
+:10177000CADFC7DC3E517BDA72B3ACB2A7B789EBE4
+:1017800001EF0912D76F3AB9F3825DA5F8BC0EECF0
+:101790002A9D62C225ECEA7C12E88438B27E7CC5C0
+:1017A0009EEAF94BB1AF7ABA297CE04CD2EA4B25DC
+:1017B0006E184BBE14B93AC2E55F8F7F3DBCD5A40D
+:1017C000F57B14F87E1F3DE24880EAC73B4BC420FE
+:1017D00011903FD03E1E7E4C407F33546D46BB5C23
+:1017E000531D87F1D99A7C11EB6B1E14D17E86A80C
+:1017F0007EA8A7F3F903D713FAF86C09113C5355E7
+:10180000EB9E39214E53BE6DD1B7FFB016E2CBC56A
+:101810004619C63B24B37873C02BA2FF4AFBF08461
+:10182000203EFDE8B51EB0670A3F1CF28A286F8192
+:1018300037450F0CDBC5E3D1875AF28322D059F02C
+:10184000F58D23E740FF3532D0E1887B8B03F45DD3
+:10185000DC3F1FAFA8C0FDA34FCE47BB499D553A03
+:10186000EF382EA7A5438B6F013B7EBCD548206E79
+:10187000747CCD3994E7EEB58D9EA92323F16525BF
+:101880003EAC8F33EBE3CBFDE2CABA78B2C20F7A3B
+:101890003EB939067F28FA2A167F503D5695947234
+:1018A000F97A4CD11FEFF075960EDDF26013C54347
+:1018B000C24211F1A0F0E591CFEFFF1EE8E138CA76
+:1018C0001FEB809FFFF9C397611F42960851E3C841
+:1018D000DFEBB37B942EB911BADCE65BD25706F18D
+:1018E0009F5BB7B2AF0CEBD7DB95D87A6D60BD3597
+:1018F0002C89C581F476472F0FFF69BB5359FD58DA
+:101900002EBC5F59BD280870D3504B1DE85FBD9EAB
+:10191000D0DB09653EFA79268445121CAF9EB78C50
+:10192000ED2276C284F57E8B3D0F9CF58B710C0603
+:10193000C00904BFF4585CB019C76BBCAA02E7DF4A
+:101940003811A09F78BA03B03E773CC60FDA325800
+:101950007BF1FA78E68F4F70E13A45C5213FEFC43D
+:1019600072335FC35897EFD9243A8F66AF210ECEFA
+:10197000154A6DD20108B9B44D31103389E049F1EF
+:10198000DF094406E87AB14E807D67BEC59483FEC8
+:10199000E92EE4DB6FD27D21E5F78307C55DDBE847
+:1019A000120F7AC62746F3CF1538CFFD0DD40BB7EB
+:1019B000F86B101EFDFADB5920AF770BBEDFC2BCFF
+:1019C000BA2A6B1E2CA4F369D82DE2B9D2BCBB8F06
+:1019D0008C62FB34EDF9A468B7E4421CA55988F782
+:1019E000801E51F0D86933A17E693ECAF460F309C4
+:1019F0008197D93E621FAF3FF7AE0DF7190ADEE9B6
+:101A00007A0EC1F8DE6F3B713DCA3EE3DF58CF91DD
+:101A100081D793E1407D017C2546E62FDA245C578F
+:101A20000F89F7C0FCFD3C1E44DE8D43BF59A16FFA
+:101A300003E73F85BE2B387D7B3A2E7CEB1ADABE5E
+:101A4000CDEBC253063193E07A7BDE4D40FE50D69B
+:101A50004BF9E06398DFDE0E6627DA8ED918BE6C8C
+:101A600045B9303FC5BF7624313F59BFEE2ABE4F3E
+:101A70000F27097DFE2DC4297CAE29E1A428F2A000
+:101A8000F8B514CFFF80FA1207391F24113C2BE35D
+:101A900028E32AEF9993B5F255C5E30AEF1A4925D1
+:101AA000C41361DC02D5FC56BB4ACCC929FDC7FD75
+:101AB00037E8E84ABE0C3A3648D6162191F4ED8B49
+:101AC000319426F79773BD9C091D9D9FC1F9BC5E9B
+:101AD000FE2F1A1A8940FB5D2DFA0EBB286CF69179
+:101AE0006E734E7F79B8941EA1F4BE32B9B0BF3E7A
+:101AF000192C9D0B93FBD1B93079003ACBAE8A8972
+:101B0000500FEB4F2FC07DDE2428839E300DC7F190
+:101B1000902F7B9D24F8346D94C4E328CA7C202E3A
+:101B20001147DF2B4BCE46FA0B120918693929D71A
+:101B30002380DE1F041F94A9E7F71FE0839B06E6BE
+:101B40008310FA25CB39BD972B7916BB06CEB31877
+:101B500004DDAA61DC8B064FAF2FFBF2E956DF9F55
+:101B60006EF503D3CDD700F2D36C22E7D10F2FAEA1
+:101B700076C378FBEDDE9389F4F99E26AE4FB22949
+:101B8000DD68FDCBC922EAAB47C895A887BF6230A4
+:101B9000E0FC7BA8FE7D3A3B1ADF0724177DFFE2BD
+:101BA0008D04CFE3E8FABE998CFE4F4080E7ABE7A7
+:101BB00013033C77CB4DC470197A6813D713AA75F9
+:101BC0006E52EB81287AA815EA293FDE05FC689160
+:101BD0001DD2407A68CBE5EBA12DFF613DF4FD817C
+:101BE000F9EFB2F9EA598677AD3E50F858D917C4E3
+:101BF000CA17A2F248D25DFDC725C483E7612576E6
+:101C00000BB3BB3B05B4B3CD27F27D58B659502971
+:101C10002876F8EC2E562F4E89EE0FFE3CD985FC27
+:101C2000BBBC7DA547D2E48104F0F943DEB38E113D
+:101C3000542F4E17ADB8BEA472163F54D64FF5ECD4
+:101C40008C69A93C6E4AD79394C9F09044FD013841
+:101C500047B3F3FD4162B1A4F1FB15BCAD162B04F3
+:101C6000887B3B9309A4DD50BF7ECD6838BF777A6F
+:101C7000B5ED5348EBA7220E42501E5CD47E431CA8
+:101C80002BA94CD70EF62179D05EF53CBBFF7EE246
+:101C90007832DF4F98881BEC0A11AB06E41BD57E27
+:101CA000E2FDE441EC273E4A56CEC7B5F6AB3D8E89
+:101CB000448D0BDC93C2F71FE79DE8FF8ADC6E4D75
+:101CC000EDCEC6FC94553619E305A2E8B1CCC8EEBA
+:101CD000FFBED36B20B26A7D4965F14456ED1F52B9
+:101CE0002A5C9A725AE5504DFB21BEE19AFAF4BA89
+:101CF0002B35F5998D059AF230FFD59AF6D9540017
+:101D0000D4E59C96AF69DA8F6CBB51531EBDE57666
+:101D10004DFB2B820B34F5639E59AAA91FD7BE4AEF
+:101D200053BE6AF73D9AF6CD3CEEABC7CBB51CAFC0
+:101D3000CD12D33B4DD6028C47365BB5F1C8B414F7
+:101D4000A67F4A1227E7421CBCF9647E2EE07B9FE7
+:101D5000FD6A8C8BC7E20BBD1E8BA53FF5CF8BF8C0
+:101D6000789FBC6432801CACD84BE5F52A5AB6BECD
+:101D7000B311D6D432969DA74A84E5F728E72BCA3B
+:101D8000FB7DE72B9287C557ED56B2390A5FA4A5B4
+:101D9000C851E39F0A1FC5C2DB3D83C4DB5778BB34
+:101DA0007F176FEF0AA4523D8F2A7E9EAD7F6F751D
+:101DB0008A819F07FB2A5398BF33211E3D7107CAB2
+:101DC000E3E5EA7F651E54FFD7A4A480FE7F63DEAF
+:101DD0006AD0FFBBCC1ED8937D52F946EDE332B4F6
+:101DE000AF65ED0D9E5CA04BACF8F7EA947EF1EF89
+:101DF0003A16FF8ED7E06D514AF4F877B3FDEF182D
+:101E0000FF6E3679720713FF5E043A2305E8C0F8C7
+:101E1000A38FBE3C7E1E6B1FE427E48000FB1EAB3D
+:101E200024C339D7A5F6B5743F9B0BE7A96DB06FF6
+:101E300052ED73E8FE96EF6FE2D02E50BBD79A8238
+:101E4000FA911C90E9F38B74DFBB5986A262FFBC48
+:101E50001ABFDC4C3C169388F47C04E849BE49EE7A
+:101E60008A13215E163A3839FBDFB2E7DF4BB90C33
+:101E70007B4E2E7D2E8776A79CAE7F5D14BF4B7F59
+:101E80000ED7E77F839F26E0791CE26903B58B704C
+:101E90001ED799C2ECF386A36C9FBCE1C46C37CA11
+:101EA0004D4AD180E77083D537BF4DE9E797FE36BD
+:101EB0006500BF5459FF2ABEEF9D268E6D8778E3DB
+:101EC000D9B009F12612961FD9B0DF4882484F9643
+:101ED00067ACD0D118DED805F6D948F479C572229E
+:101EE000ACDBB85F44FD4492597D80589AC0CF491D
+:101EF0002CD6DA2DA7576BB792CA5C3A3BA6B55BD6
+:101F000069955ABB35C4A7B55BE975053A3BA6B5DB
+:101F10005BC3FC5374764C6BB7725A6ED4D931AD37
+:101F2000DD1ABD456BB7AE086AEDD6986756E9EC89
+:101F300098D66E5DB57B9DA63E3FB459533F7EFF5C
+:101F4000239A7261D77735ED171F7801F36F261E3C
+:101F50007E5AD36E52F78F35ED28C2BB204F7B21BE
+:101F60009284906B4E3FAFA95FC8FDB46B7B7FAD91
+:101F7000E987B4B17CEB00FD0FE8F557E2338173DC
+:101F80002291DE57D2295D5704054F88365BB27B1C
+:101F90006711CCE3CCB1EBF7433F8BB768F3B49751
+:101FA00004B5E506323C11F44303E58B20E5936567
+:101FB00090BFADD26BCB48A31DF32106C9678B0F31
+:101FC000DC4430EF33E0ED82FC74659D0ABF793963
+:101FD000BF29F353D6BB8CFA7D2139B24E2FFD8F2A
+:101FE000ED23BB4DC0B7B5BB05F25DA1FF7AEA3A60
+:101FF0001EDE981E655DFA75E8FDCEBC546D1C7B37
+:102000009A68C5B8FED937450F8B0F6AE570D501C0
+:1020100016CF5FF59C80F1353D3E14BF34165EC48B
+:1020200000DB273424936050257F32C787D9AD95D4
+:10203000BFB3F00F98CF536210F282E2E4783DBF55
+:102040001585487F3C27E46AE5548F679B67685491
+:10205000BE92E97F308F5AC2CEA5F47CA5C7FB8A19
+:10206000DD0F9B402F5E2EDEE7A56ACF0795F38339
+:1020700012BA5A53943C3805AF745F5E935A187B7A
+:10208000DFDA907AD9FBD686D4FFECBEF59ED40178
+:10209000EC5C0FC4CBA85FA98F97F58F8FEDFD4C3B
+:1020A000B0631C9AC5BF7C1E0BCB57D1D9C95CB796
+:1020B000C64EF6ED7B4F0AC166DAF912BB7713CC38
+:1020C00067A9DDBB196099DDFB807ABDCD142F783F
+:1020D0003F87DAA99D51FCC3975315BFA802E3229D
+:1020E0001B4A587B7DBB9FA5B2FB3C9D29456EF4E6
+:1020F0003B4FE433FB692B1AD0EF7C889FE73C0011
+:10210000E7852323793C0FF273152A765EA0DB0660
+:1021100063855B9DE7FB48AA13C7B34F7ABE0BF2FA
+:102120009D9B1D06872083FF6CC073D1F55E6BD924
+:10213000AEB1ECBD64CD7B12DA6111F00DFEBC5581
+:10214000FABB9A6F5FA6B884FA58EB7C3995F9BB55
+:1021500046E2B580DE55CE738D27F32DA06F25C1E5
+:10216000E38896C769E4795253F879AEE860E7BB33
+:102170007D727E893CA97ABB6F9F9A6ECAB9EE1CAC
+:10218000BBF765A0AB5F0A98C1BFF45BA2EF7F5FAE
+:102190004D65FE470B5F1F7534918F707C7150F158
+:1021A000933753312E17C07CC5D5A2E734C4E70658
+:1021B0001BAF3A9EDACFFF399E3A70DCFC64229C5A
+:1021C0004F240E95703B21797281FF5BE0DF9330E5
+:1021D000BEFA3EBCDF2FFF5476F17C5A79C07C5AA0
+:1021E000A59FD94EEFC78057DA5F4F2ACBFB5B2FF5
+:1021F000AAFAB15FA21F8AA7DC46EBA0F0F739C3A9
+:102200009FE7340B265C5E5CD39CD62FDE674E1BAB
+:1022100020DE77F1E8E844384F56E256FA76167F2A
+:102220005286FA7E4C8B533BFEC6025676A531BAD7
+:102230002D4E647C3F8ACF43C90354E2D69619C41D
+:102240000BF71D1EE1F9D94A3FA3D26CD83ED13518
+:102250006514CC7763B680FBCA8D4E41B3BF3C9901
+:102260005A322A8DB69379FFA3D2189F6E1BCEE205
+:1022700033FA3CC833BCFD99D42908E99B57003E8A
+:102280004DA218158F63D2581EC64988911546E293
+:1022900067358FB1FB5D4ADC4C890312E2792B81F3
+:1022A000EA95F75A8D04E25A8B44EB46E0C3BEFB35
+:1022B00073FC5CDD41FF037B593DB602F38FFEDD0D
+:1022C000FB5B80CF04577F7B599AD6E7A7782EF324
+:1022D0001ED7D7D22EE3BCBD3B9EF16DAFCD8AF1A8
+:1022E0006C7DBB859C3EAD3C4E01FA1AEC864B24BE
+:1022F0008DD1ECC7C234C637178F9ABDE8C794C5D5
+:10230000633E8772FE2149C01B98061E0068F1A734
+:1023100067C07DA2BEF30F99E07B49562BBE27C94B
+:102320002464832BA1924780FCB26E53F7863498C5
+:10233000EFB58207EE0FA455393AD392E11EA18C76
+:1023400062B6319BD88BA13EDF80F5CE398E8D46AB
+:10235000C8BB96099C6413231DC746C7694DCBC6ED
+:10236000F5B7066EEA4CA3ED12E55E327C2CE8115F
+:10237000C77437C87125CB5FD7AFEF3E2E1FD60D80
+:1023800074DF00F890A3E781DFC7F98FEA99354041
+:102390008F1299EC62F7A2581E2AA45963BEA08737
+:1023A000E54B2740BE510ED33350FF90B3741DF060
+:1023B000B9225F22C737F0BD3A1FBE95E33B4927DC
+:1023C0009F0A3EE9004D900F21CD20C8D7B3AAA2A5
+:1023D000CFF7879CCECBED158FC07C674D6EC23C8E
+:1023E00077F2F9175F8845E0F43239A1EF1388439B
+:1023F000C42533FD1B27CBA88F8943C03C538BECEE
+:10240000A983729CF56A870876CFCCCF0B171A8800
+:1024100044E5AD94F7E3AD24C2FBB92CCECAF4ABCE
+:1024200044DE57E442E4C82902FBC9FEA85FD49AFF
+:1024300040D7536A3D88E78871231A4BE05EC1CBD1
+:10244000F3591F8FC4C8DB3F99C8E8E0127D6E03C3
+:10245000F8F4E4E4ABFB26239DAF841B9A0F6C7861
+:10246000F7D5FD993C7E0EF9E281775FF55ABF7C86
+:102470007EF9BEC7DF7D15F2CBBF3CFF7B04D0E306
+:10248000272963C1BCF5FCAFE8B3C3A2EFF0BD14CC
+:10249000FF3753A6F21700944815D29BE50FCDE104
+:1024A000780EFC9DE2D912C1F3CD1D07107F878DF8
+:1024B00074DE747CE314866AE33D893C1F2388FD47
+:1024C000DF62699B06FE4D8FA9370FC6ED79F1EDEE
+:1024D000CC00D52747EF3B672394FF8E4BBD367862
+:1024E0007E7ACD1B36C0D7D13522DE7FC37BC9AA09
+:1024F0007CA0F7395F95BA2B8E025FCD5FFBCF22B0
+:10250000B59F4DFC296877970445B8E3DBA7FF9694
+:102510003D93C0998E9597B72769CA8A3D5E6E8EA6
+:102520007E4F3CDDCDE8BEE4D96D26C8872F75FB14
+:102530007A409E4EF37C83D3BB6CB8BF52E6B3E0C7
+:10254000D97C13EC278F77984908F85EEA32128C11
+:1025500053796708946F7D9C0FF5F37C654F02F605
+:10256000B7E83111E348D5742C3FC5ABAF6309DB45
+:10257000DFEAD6B1E8A83C1DF4D5A24D0209C8ACEB
+:10258000FD1A4A379FFF7E3C5FD1AF536F5F2E909D
+:102590003526D0237AFBB290785A2683DD6AD33E63
+:1025A0005FDCF100F6BBF812E7314E37DF9F159183
+:1025B000895FE4409C7938E60BC6B237A7D732A1D1
+:1025C000FC70AD05E1476B1D088FA631BE5DB6BB43
+:1025D000F3957414EBAE22B04371074A2DB793887C
+:1025E000FF2C6DBB29F4A40C7CA9CD87ACE27856F6
+:1025F000FCE7C5FC9EC1A5FCE72A58E700F9905509
+:1026000083CC873CBB7FBC059E8F57F03191E203A2
+:10261000EDEFD8D7647269FB1B0B2FB1DE5B0EDFC9
+:1026200039888267456E8E723BB270FBEC8D43E950
+:10263000049A5FFC6B5637F2258B4328E754A27B44
+:102640006317AC5F24BAF85F80BC4954FCABE7CF9A
+:10265000C5C4C3EC8E95BD67E171893EBEEC7810B0
+:10266000F1AAF011DC2830B80186DC86E2FEDF0D2D
+:10267000E8F77D80366DF913637716E88DC5BA7873
+:10268000C12742F4FDD734F770B67ED93B1DF22244
+:1026900016918A8D2CAEDE86F8392DB5BD722FC805
+:1026A000F376264FCB7FF9DC2F404F2DFDD9637693
+:1026B000D0531F486DA9305EFD8E0D762FE82B2973
+:1026C0006087F73F088A51EFEB06DDFC1C9078AD80
+:1026D0009017B602590C042C3013F4E4DF76181D61
+:1026E00010476D78C61C32537CACD8C5F048CB2758
+:1026F00058F97EC457C36EAD1C2EFDE163A932EEBE
+:10270000E703E91C7FE9A0AA576C3762FEE88A3725
+:10271000450F0CD3407A717DFAF7611E614AB78686
+:1027200076B1DA94D8BF9E7A3C2690B3865D8C4E03
+:102730000D3A3FB38EEB653DBFB7E9F89CE205E388
+:10274000614A3E2B0932FDDCFCA3C7F34ED0797DF4
+:10275000B4FD55BB3036C2EF04B22E291DCEB6D71C
+:10276000CC873C83587CFE09978B3EBDCFED8CBC5B
+:102770009B4E0C7CFF0E06EB8D21FB35141FF5DB09
+:102780008C9E007D5CFF9CE8B5829F74C48CDF77D3
+:1027900058F6DCCB6F5D4DE7B76CA73179065B86E9
+:1027A00015F4B342A706E0EF82085D96BEF0B209C9
+:1027B000F220E1F91A57843ECB76769A20AF528FF9
+:1027C000C7D2F64E13932F1D9DDA4F4C07BBDCFC8E
+:1027D000A38B26E0830FF608045C48FDFB75DB5EE7
+:1027E000B683FE003C81FD50E8D547BF7E740BCD1B
+:1027F000FCF5046CE780739A58F45B09732944FE76
+:10280000FEE9AFE9F875EF983DB0FEBA9FDE698743
+:1028100075FC556A647CFEBD0DA9608FEB8C8154FC
+:102820000742F6BC6EEBD791FF16BFFEF554827AD5
+:10283000D33B04E497AE7308AC6FD15337E3FA6A25
+:10284000890FF9AFEE7B6205F88917245216CDCFB8
+:102850001F3284C9C95F9F36E3A6E0AF26C2BEC35C
+:10286000F14791E5F19195E8877C9DAF956A622CDF
+:102870005FB0303A7DCCED33E17AAC81B76AD87E77
+:102880003FEAB10F33BD6920EF140FDA78EAEBD3DA
+:10289000D2B8FEC3EFA5E07B94EF4AE139B4EF3242
+:1028A0007AE3F234EFF1BC5636FE5D7C7C3AEF7889
+:1028B00088CBFD3555BB7F55E05787287130D24511
+:1028C000D4FC154BEEB76F42BE3AFF26D32B2B82BA
+:1028D000B3CBB0BECB184A83FA60E71C01F502F512
+:1028E0002FA2C9F57623976B6D3D9DA724A8F1BB58
+:1028F00087DD8BAB7D94B653F92111BE31459E67C0
+:1029000047E453C9AF58ACF3CF14A8D70B4943B42D
+:102910007A41799F3C9512F51E56441F0490AEF5FE
+:10292000C6E00FBE0B727CC48CF70CEB9F33E2F752
+:1029300072CE3CBBF7ADDB29BF9F6957E457AB674D
+:10294000F5F25BF7FCCD249AFC9E49AE2051E59749
+:102950003E8F2ABFC92C7FFF7F5ACF2E8EA167AF33
+:102960001DD2CF9F48BC86163FFCF1B261B8CFD2D2
+:10297000E155C1A75E6FBEE596A3EA4DFAF7265171
+:10298000E151C19FC2974B7FB21CC7E9E35F853F0E
+:1029900015FEEDE34FFD7AB578D4D71BE0CE51613B
+:1029A00084EEC675747F0DE7AE2F8A78EEDA23F7D2
+:1029B000DA5D1097E579373D0E5E76B2726F8A69FF
+:1029C00023E80FE5796F1CCB43E8A9E8B53B557EBA
+:1029D000FD890ED10E79F5DDC1E8F912984901F1B2
+:1029E0008C18F914CAFDD969A235CB0FFBB2367623
+:1029F000DEB3B0E9563BF8D33D1D39B32AC18F3F52
+:102A000020A24FD513CFF3AB025E6908C56B0D5BF7
+:102A100032394D02DF013FBBA663D90CD8342E6C8E
+:102A2000D5E2A3D63A07CFB36A1F3546F88280BFF6
+:102A30001334819F55F794F6F952C8AB02FAE8F8BF
+:102A4000C8077C14E51EC646858FF2493EDB27F396
+:102A5000F32AAED7A68963675542FEE27E764FE23F
+:102A60006C874836C27A9FE5E7578114E4CF159406
+:102A70008FD571CE8F80CF46C7B6DF1FFDFC68D1E2
+:102A8000BDB449FD2FFE9CF724851FFDE2C8A8DFD9
+:102A900040F9976F67FD99F46F5FBAE7B33B308FEA
+:102AA000728F99C0BEA867CFEFB2EE85F2AFCD1E90
+:102AB0009867CF3AB63F0EECB1A15DEFC964FE5FF7
+:102AC000F38B17F3BAD13EAD477AED1CC2EEA99E47
+:102AD000EDF8C73101F2E93AE8AAC0EEF27D57C33A
+:102AE000AFE3707FDDF3E245CDBEF2DF5DCF0A7E5E
+:102AF0005FA9C7462AE17E718F93DDEF6CF8CDA404
+:102B0000EFC37DC5E5BB3A4D35B4BEF4B7FFCC038A
+:102B10007DD3F33CF327A87FBB155CEA8E275E6D5F
+:102B20003552FA7D023EDF50BAEFFE6E4239DCC309
+:102B3000E88F1786871E8A075817C54B1DE8C958A6
+:102B4000F8786308BB3FF2DF878F4FEF80F1EB3BF4
+:102B5000261288A747F02278D9731BE65DD0F5B31B
+:102B6000E77B2EE6817F74A9F57EFA7F6CBD8943F1
+:102B7000FFBBF9FDF12132CE4FCFF7FDF9FA977780
+:102B800063F9A7360FCE7790F27ED5D0FF5BF42E97
+:102B9000FF5F4BEF039CDE36079CA7F4BCF8CF2CFD
+:102BA0007219EBAEFF5FBAEE3E3FC7E0B14CA0F347
+:102BB0007B87046F2E1162E7713E3154BB8F98C939
+:102BC000FD8899C9B5E83FCCF4B2F84A3329D80F4B
+:102BD000F7D4025E11CF1D309986E2A16B4E7E10B4
+:102BE000F3B6A4C0C8EF401ED72DCB3DEC3B5FDA57
+:102BF000FDD5CCD4B232F0DF0E35D179D176876CE9
+:102C00000647335DC22CAF88FE1E85E8E7FD69CA22
+:102C10000D981732AB58BBCFB85DB76FB8B5525BE4
+:102C20007F0B793A05F2EF6EA93362BED0CDBAF6CA
+:102C3000AB873A709DB792C60D2C3E7379783AC037
+:102C4000F1D41F0F03E3AD1F9EF87E127379E4FEEB
+:102C50007833FBD8FED24C2BB8BFC5F3E4560D0A2F
+:102C60009F84EF3BCD7C6805BF662FFB5EA7AA5F04
+:102C7000C48B82F7CBC5B742273DDE15FC2A78D33B
+:102C8000D3E12938934889E03F02953C121F51E770
+:102C90005BCEECF31BAD88C7D7B6B3FB0AAF15D735
+:102CA000B4E643F95901FDB50B93C7130B5DEF2152
+:102CB00023D9CDEE7F79654751249F4528FE1D9E7F
+:102CC0002B403EA17A5F0AF984EA75413EA1BA0C15
+:102CD000F984EAF6904FA8AE877C42753DE413AACA
+:102CE000CB904FA86E0FF984EA32E413AADB433E7F
+:102CF000A1BA0CF984EAF6904FA8AE877C42753DE4
+:102D0000E413AACB904FA86E0FF984EA7AC827542F
+:102D1000D7433EA1BA0CF984EAF69047A8AE873CA7
+:102D200042753DE40DAACB902FA86E7F5DF8254D2E
+:102D3000B984BCAA695F6A7943539EE6F8B3A6FDDD
+:102D400057DDEF69EAAF97CF68EA15FADF907B4E5F
+:102D5000F31CCE2C0245B08F617FE59E7F68FA910F
+:102D60004805C6994DA411A105E2B714C69376840F
+:102D7000562AE6004B47F972D2815FB706360273D6
+:102D80001D9A74310BF4FF6B936F62F1077E4E3026
+:102D90000BFE2953264EF83C03F6B5CAB9A73D2CC5
+:102DA00092D078CA876101A1239C404249940FC305
+:102DB00071085DE1247C9E1476224C0EA7E3F39407
+:102DC000F01084A9E11C8469E16C84EEF01884435E
+:102DD000C257201C1A1E8FEFA587F3116684AFC15E
+:102DE000E799E14908B3C2A5F87C58B804A11CBE14
+:102DF000016176F87A84C3C33761BB9CF06C84238D
+:102E0000C273F1F9C8F06D0847856B108E0E572319
+:102E1000CC0D2F4378457809C22BC377E27B63C280
+:102E20002B118E0DDF8BCFC785BF81302FDC8CF04F
+:102E3000AA7013424FF8016C971FDE84B020FC6D1E
+:102E40007C3E3EFC30C209E127F17961F8098445F6
+:102E5000E1EF239C18DE86B038FC138493C23F4216
+:102E60007875F8057CEF9AF04E8493C3BFC1E7D71D
+:102E7000867F85F02BE1BDF8FCBA7027426FF855CC
+:102E80007C5E123E80704AF80D7C5E1A7E1DE1D495
+:102E9000F09FF1F9B4F01184D3C3EF21FC6AF80478
+:102EA000C2B2F01984D7873F40F8B5F0397CEF867D
+:102EB000F0A7086784FF81CFCBC39F21ECDBEF4FE6
+:102EC0008E752FD167F802F6CF56D7A0BEF345C84E
+:102ED00016CDB9D4E30976D493B3D6B03C928D2500
+:102EE000E7A6A25FBBD22CF3EF6BEAF4EAE756F059
+:102EF0001F3640CD10D607E401CEE3FCFB5AF1DECD
+:102F000014F097361674D7433CE4C1ECEE2A84E9FA
+:102F10002CBEBA9EC307D259BCF4F651CCCE56ADE6
+:102F20001C89E757247970EBF803D8E79448FBFA3B
+:102F30004C5EB6F666E1BD8041F633D87697CA8F0F
+:102F40005A95EE0BA6A35FA4BF9F37E8F79F413DBC
+:102F5000F1E5DF6F1FE8FDE39C5EF68C8A5D384F7C
+:102F6000C99B07F553D60D1193693FD5AD8203EC8C
+:102F700064CDFAFCE940BF02E2C578E2BC18795D95
+:102F800047D2599EC682462381B8E20299603C77B7
+:102F9000C12E96E70B71D072CA17759C2F966FDA07
+:102FA000690217B4AE7131CB3F0AB2389385FE0780
+:102FB000FCBCB47536E61F2D7B461B7FAA87B88EF6
+:102FC00008E7C8DAE70D3CCEA48F57EAE34B7F4C05
+:102FD000E7F1250FCB3B226206AEF7025D2FE473CB
+:102FE000F8EEB65940FF533CE03989B27E255EA920
+:102FF000E081F4BFCF8079A167F78FC43CB5B3B24D
+:103000009C06ED7C549CBAAC90FFE09B08CF29FE57
+:10301000309FA4B72901F3914E507D2E43E293C314
+:103020003711BE9FD6FD4E26E1DF6FD49E1B585A46
+:1030300031FFBADA4807A6EDAA7724E1FD47DA5F47
+:10304000DE6E8847EE30623E5080AC7293E2FEE75F
+:103050000A151B8CC81F0B763B597E58C0FB26E413
+:10306000EB2BF438B13E673AE4152D68C9CEC7B0F2
+:10307000DB6E23FA79CA79A942A7FE79D11589F0C6
+:103080007DC4A52DAF233D29BD34F5F5AD9FE2FDEF
+:10309000014AAF5331E8756A207A5932B4F482B8E4
+:1030A000F2AD50B92609E5B46A5D6864A38A1FF5DC
+:1030B000717A9261C5FB8E4A3E71D950460F2279D2
+:1030C0005281AEE75A0B915E7A3A95FDAB06E94123
+:1030D000DEB1E1F776E7E590F937D2E7F379DC7214
+:1030E0005EF3F5E83F676730BFFEB5B5906B49C842
+:1030F000EB6B2DC44B9DE737D63AB0FCA7B56E2CD1
+:10310000BFBD564678646D2EC2532696CFA3C81312
+:103110006500CCAB1B9DC1E4687486B2AFBACB0D21
+:1031200071E9B27FBD5108F93D2981E499D3AE45DB
+:10313000BF5B93A75139479B87D16DE4795E9B04B0
+:103140000F7C476541C5359AF624777CA40CF6833D
+:10315000E78D2C6871E2F7DB6E9B91A4697F4B4B86
+:10316000BAA67C5D868CF39B5D96A3797E7BD51891
+:103170004DB99AFF6E02B1C41BD4E753D4336279C0
+:10318000DE0ED6F67CE3C4B4D574FCF3078D58AFDD
+:10319000A7C7295300F7E381A7CD1EB043A7E11EBF
+:1031A000192D9FFE9388FAEEB491041C54759F1656
+:1031B000C87A804462F274E13093A7B27F8904F642
+:1031C000E1E4C7663CBFABD9229000DCA1EAA59838
+:1031D000A7E3DEF52333AE7BE11691F8F0BE92DC77
+:1031E0000EE7D677ED18ED8173CB7939A14CB8B7DE
+:1031F000D7FBF338CFD3B4B6A69BBD7F9AEEAF9D75
+:1032000090972414E0F9C1C7E56DB506C837100FD3
+:10321000A6809C7EFCBC88F194252BFF54E400BD65
+:10322000F64AFB5BC5749C536D228E7BE619F33620
+:1032300011E5DD9B06DF758DAC3B8871867DEE8ADE
+:10324000BA0CCAC71FD606F350EFAC61F1EDFEF819
+:10325000A1EB057A03BFAAF458C46EB17332AA7CFD
+:1032600086807EA8317AF0DCF454AB11CFF3A8FE4F
+:10327000C7F3FF536D4906A67F9E47BE5B20C92654
+:10328000F5B80B5A452FFB5D08D904F3250F8B3E8B
+:103290003211CA2C5F21D022F8D8798D96BE77AE34
+:1032A0009C88F78BF5F9530AFC84CA944F750EB4C9
+:1032B000F445763E4B26744BEAFC7125BE42DCACED
+:1032C0007FE53B3EF5C31FFFD6640ACF7AD92707B7
+:1032D0002F6CB7A17EFCC8F052D16A0ACF9407DEEA
+:1032E00097285D1A45DFA380CF6586D6AD029E8BF9
+:1032F000BCF72D388FFFF039A307C590E76B2DFD84
+:10330000F1926103E507C10CD8F972285570C357D3
+:103310007909E66FCC25ED3C3E1064E75830098A08
+:103320001F473D3BC77AAFD0B619EEE1D6E8EEEDC8
+:10333000BEC7EF2DFC3043D0D8E7BFF0728D81C9F6
+:1033400027D9C3BEBF08792F2354F654D1A7BFC8CD
+:10335000188EE3F6D955D28E7AA5967F1FB8FE193E
+:1033600033BBA7231307C8E312461E7216E4998ED7
+:10337000B3D4F4DC77809D17932EB4731F1A83B5F2
+:103380005DD9F0FEB6F52E7CDFE80982FC723B6069
+:10339000A18A03F4C762C2E6B7BC4D088654710A1D
+:1033A000E5F73808D80595BEE96F0FB4766011B718
+:1033B000778B882EDFA74D6B972A126CB8AEA56D60
+:1033C0003CEFB96F5E22F982E2ACD6177C6526CE5F
+:1033D0005BF004A3CC6331E90DC17780973FCBEE5E
+:1033E00003E9E7A55FC760E759EB993D15BE27DC08
+:1033F00037AE6EDE0ABE095C5052D141C17B6D8092
+:10340000E1B3B643407AFD85FB55CA3D3B85EE8B63
+:1034100049C54CD06B8B1FA5FBC2EC081FF4D9EB40
+:103420009D41F497CE9036BB95F27FFD969DB74CAB
+:1034300082F79E7ADD04FC5DE50A8D3438E1276968
+:10344000EEF956596614FBAEB3E7FF29FC101E6770
+:10345000C2F7283E166D1731AF41D58E9FEF07108A
+:103460004F7501827944756F8A9E66FAB40E7ECEDE
+:10347000A7E0F2E7ABE0E77F7ADE7A3F263B7360B6
+:103480003F46AF5FFAF9313AFB09F726C05EF6A670
+:10349000B03CF0F39237D1857A59A777530AF0BB45
+:1034A000A38ADEADE5764F196711D83B5A7E7FCBF4
+:1034B0000B76883FFCE5D11752318F02ECCBD888D0
+:1034C0007DB9BB868D77F72FE3306FE9E3F2AE3C31
+:1034D000F0FBAABEF73BBBFABBA6756EDF75993051
+:1034E0005F6E0F978BDBB21C600FFDD1F32AFAEDF4
+:1034F000BF62ADD3768975DAB4EB5C00EB54DD07BF
+:10350000A9E1EB3CD9C2D6F75E2B5BEFC27EEB0C98
+:10351000E039C8DDDF377B02E86784D08E9FDE2983
+:1035200012B87FD6E767E8ECFE05D2B615F0B17C9D
+:10353000D5DBC724CA174B4651FC503EA87AD88C1D
+:10354000767EC9CFD9F9E78742491A1EC0EF0BD959
+:10355000BF419F2FA5FE01F8179179F4D9FDC599B8
+:10356000852ABB3F48FCADE071A8151DBFC3DF8BAA
+:1035700012BC2C1F7285F21D98DDBAEFC0C8A003E3
+:10358000D83D790BD02983C86C9FA88DA7FE6DE428
+:10359000A777AC42FEEF1DA5FE5E6F437CC808F91D
+:1035A000BEBD3B05F48B96DF55622F2190DFCAE24A
+:1035B00060EB3399FD12BC5ECC7B3153BAC6D3F1BC
+:1035C000EECF94D973D9C1F2BA9F22F8DD1965BE46
+:1035D000FAE7101FB780FDB31AD0FEE9D7FF8B4C76
+:1035E000E62F2F170DE84FD79B985FDDC3BFFBF089
+:1035F00028AF7F3493F9D7DFE5F1811EF023E17C1A
+:10360000FA5A33FE5E0F2153314E2E11C67F92823D
+:103610003787F4499F7CA3BFDC9B0178BA83741978
+:10362000819E338B67CB706FE058AA05BFA344FF20
+:103630002AA09FB9BC9F4346764FE0188C41D735EE
+:1036400097C7938FC16740E9F8C78698D08F0DBCA4
+:1036500068463FE1FE7816EF23C98912F0F9ED5C68
+:103660004FCD9B6CF6C2F9C0DCC9F75700A4FD052D
+:1036700008C55795A577433E1DA7C9C0EC7C938B21
+:10368000E07D49B2BEBB10F07715758B214F9EAE21
+:103690007ED7174903F191F69E423DC415AE268CA4
+:1036A000C18A11BF9A72BD89D51FCC3C36F3D10CAB
+:1036B000BABF866C26B0338023E08BEA44DCE7CEC9
+:1036C000823C7E174009F9ED4689040C0CB658F18E
+:1036D0003B442CAF5F3907B9B9988412E9FA420725
+:1036E000B4F7286E0D1942A3E17C470A7502FE0C5F
+:1036F00016D9E8A0E35494090580F7FA75839BEF87
+:10370000F1CC0F70BEF5F0BD2B98E73704CCE799EC
+:103710004B851EF8F40E89EC130B18FD800F1B5C13
+:103720007200DBAD647CAEDCDF50E8924FBB57E348
+:10373000772E9F1FEDA7C50EEF9BA2C74DCE70F948
+:1037400050FCB4655C6E97297CF7AC565E6D5932BF
+:10375000FB9E1AF883146F73398CC5F7F159ACFFCF
+:10376000F82C165FFBDB658EB7DC4C42B8EE17CD4C
+:10377000484765DC591C5AB258FEB2320F857F6B40
+:103780004923E6DFD4F2788C816A12CCD36DFB3EFC
+:10379000E6F7EBF384A8838479674BB7EB9FABE242
+:1037A00039A2462F619C5330F52E84F9095F89F3C5
+:1037B00000BFCF35B5633C40DFCED826A09C1B5B55
+:1037C000A83F25F0F32D5A36B70AF8FB0E73337A6B
+:1037D000C7E1F7CAB95F5DCBE94AB5F774B80754DA
+:1037E0000BFE149E7FF1EF446D617EA4C4FDDF05E6
+:1037F000AD5A3F63EE7A959FC980E65EBD59971F2B
+:103800006EE4FEC67153EF38D0F7FA7BF6C70D6C45
+:10381000FE815482F991CA3D7B89FB930A3F0DC911
+:10382000326ACEC594FB9C55A0A7D8F70E74F95404
+:1038300056FCEE4A95C0BF57C9E38A67A9BF89DF26
+:1038400095391A87764B8933F694D8028644F89CCA
+:10385000252BCF4BBC7B26F89955769304F0A2A17B
+:103860001BC7592D76D9B2B32371DC8D25E3B74040
+:10387000DED0ACADA3675932F19483DF471AFB1A4F
+:10388000E4ADCFF99CCE1FCBE36679E9FEA8E7E56E
+:10389000DE3B2C54452FCACA9B25517BDEF358EFE3
+:1038A0005628AFCE9A384BA276B0E7C1DE2CF88608
+:1038B000F0EAADD7B0FA26A5BF6B66417E70CF1394
+:1038C000AC3C87D607C0CFE5F780AAAE1650CFAE86
+:1038D000E6F647891F55195E62700AFB9D8F4BB54E
+:1038E0000B6455AC063F47B49DC2DF13D82C7BB1A7
+:1038F0007C5F866F7E16ECA3660B0113DC8B7F3337
+:10390000388ADBAFA8BF7BB13A93C9E5BA61AC3F57
+:10391000055FB49FBAACC2CBEFC701FD146AFA5978
+:10392000F965E673B4FF7CEEF932F3F1CADAF928EF
+:10393000FE99F29DB957B2BDDF81F92DFB26DB0F51
+:10394000935356CDFDFF738DBF1C0576FFDCB3E6A8
+:1039500024E0C3653FFD55562DF87FDC1F3AD3792F
+:10396000C40479DF2BC2ECBB380D61F69D9C15BBFE
+:103970003A4DD3C7421E6BA7A95435BFFAC8EF5CB6
+:103980004937AAFC9827B30C3CDEC67ED771D94FC5
+:103990003FC0EF092E33B4BF0F79BEE46A1647D398
+:1039A000AFB399BF770CCEFDA3C40BB66531BFE3AF
+:1039B000628E3708EB5C9745B02CC6F86ED787BC93
+:1039C000BFAA78A6C76B8A6C1699E2BBF04D5F332D
+:1039D000E49DD63E955D20D2790433A6FC386BC0B9
+:1039E000F8662F8B6F76B0F86695ABEB2E6AA4C89D
+:1039F0005FB6CE7DC8722D21373C4EFAEEFB41DC1E
+:103A0000B0CCACC8CFAA595327B3781994F767D56F
+:103A10003F04F2B39FFF3EDBBC89E3E241CEBBB380
+:103A2000130C0E2AFF3BD3ABFF027C316FE2B5D300
+:103A3000E17989D936AA9AC5C7913F76A65784A05D
+:103A40001EDA43DCC3670AA5DC4AD7E1FBBD8879EF
+:103A5000D3BEBC045FB47B2A7BB8BDFA4B163B0FC8
+:103A6000DA6FA0F32C88CC43199F72FC5D5D10B710
+:103A70005A37241FFC687B46C9A9ACC2C8F8F60CAB
+:103A8000DFEBEAF1E972F3E0F960E77188D3E31460
+:103A9000A75BC56411BE94D0A7D76F9C9AA029CF0D
+:103AA000999144BCEAB8E99C744DB9B22A47D3FE57
+:103AB000F6856334F5E5E6AE098D97E1EF37D89EDC
+:103AC000C1FCDEA31D17DE9A0B7EEC76D123D0F568
+:103AD0002C7971C75B907F7D167E82A480C5C5D886
+:103AE000F71AF9798CE49534E731075E3081DFAE5F
+:103AF0008AF3EBEEE51DC438BEFE3C46C917FFB2A3
+:103B0000E731D230FDEF797EF40A5D1929DDDD89D8
+:103B1000F4693EC0F2989BA9DF02DF13FBEA2E7323
+:103B200010BEE1FEF1AF4E9864D5B94C43B8097FA1
+:103B300057B774F7093CB7D991C5F4F68A8E4F4D43
+:103B4000704FEAAB1D2B519EA753FD9548F9A6ABCC
+:103B5000938CDB05F1E46C1BE6E12C6BB91EE3D41E
+:103B600089E1B908EBDBAEC7FE96876FC2F20AFEA9
+:103B70007BBEFBE3BBA6831DDEFF0B27EE075F13B7
+:103B800043A39E847ECC36D40FE5E9F3D6819FB063
+:103B90003F3E30F64E3A5EF9CFBE8A79E82B760981
+:103BA00018372D17C97E01F2EFC371D85FB9F8C776
+:103BB000092BE9F31B4A995D2D071F87D68B45B664
+:103BC000CDF83DE918BF93E619C6F48AB19BCD7BC9
+:103BD0005A7836F6A7D4170D1BAEF99E9F3165BBF8
+:103BE000B4C01A598FB15B40F8B5F018840DBB66AC
+:103BF0004B907FFEFBDCEF27039E687BFC3E587FEB
+:103C00007D3C319144D15B0A34733D3C17F4309CC8
+:103C1000DB677B670C4B81DF23EC962CA047AD164E
+:103C200007F82F338BF3E55AD5BAC4976EC37B10D0
+:103C3000E6E45E23D8EFB914AAF5F6FC1876E6C6DA
+:103C400061CA3D9B26F6FBBB8A7E7FF7EBEC3BA867
+:103C50003C3EA0C8D375C30C9AEFE974094C2E0200
+:103C60003F67E702D3B37D0B61BE5D25A4F279D433
+:103C7000A35D59701FFD3F357F4A5F0BD0DF2E7566
+:103C80001388632C19A6D81D26CF979AFFAD7CBD4B
+:103C9000AF89C40F7CF1DA75D77579E9BC3AEF1DAD
+:103CA0003F1EEC8232DE3DC3589E2971F47E8EF9B0
+:103CB000867B126488EB97C399C784883F0FF98885
+:103CC000103F6CD8637E1A3E90DA60A7FB7B2BE432
+:103CD00005C685806F3B7F1B2781FD1833C277CFD8
+:103CE000B042783E7A2A7CC7C7DB619608FA41DE8B
+:103CF0007B015FB1E67B29FDA5C8A39ECF7C2D4C3F
+:103D0000FE7C5C0EAB39DF2EE072582D7912E13C5F
+:103D100066FE4111EF452E58238CDB05F101D98653
+:103D2000F7F4153954E4CD087C391EF893F1657D1C
+:103D3000D8C9E53B9BF7CBE4A05C64F976E5639CCE
+:103D4000B87F5E114EC2768ABC2A72BA3EDBF76338
+:103D500058777933956F3A8E6FDD9009202F113E99
+:103D60003139809F289FB86B557CD0DCF999047C51
+:103D7000629C2C209F98292C55F151459F7FE298F9
+:103D80009E4AE731737D367E4F59A9FF591FBF0CFC
+:103D90008EDF9FE2ED17584323C1AF3536C679E079
+:103DA0003BF2679365D463AB3609F8E384AB8C15BB
+:103DB000A5E05FAC7A42C0F81EF81DA07F8A0E37DE
+:103DC0009AD4E720B785F3F0BCFAA6F00884C10CBA
+:103DD000DF8BC017D5E15B381EF3A29EF79D6FBC49
+:103DE0001FE36AE783660FFBCE98367E57E8F5E05F
+:103DF000F99FF1A0916C9321EEE613F17C2F93389B
+:103E0000BE2DB0F81DC4F394F89B724EA7C4E1CC4C
+:103E1000F03D5C951DBD20B565C13EA45F3CAE8400
+:103E2000D9FD8FB61BD9BDADCE3F161968FD87D918
+:103E30005E8CCBED73FBDE86F52CBD31F853232D64
+:103E40002F7BF0053BC4CB157CB64BA191B05F6ACC
+:103E5000A77884F8607BAB581664FE4EC26C557E22
+:103E6000452CBE5E1ACE41FC28F646D1DFBF5CEB86
+:103E7000C64DA9A2C72F658714FE5ECEE56039C87E
+:103E80000151DB9BD915F0BB662457C07BAE117B7B
+:103E9000C3E441D1D394DF516ECA733231AEAEE880
+:103EA0006DBD3DDA2BB67FFB6A3847937D7132C515
+:103EB000CF949FFCE385776855FDF33F9A0A742AF7
+:103EC00019231038C7BC949EFC7FD95BF3F900809E
+:103ED000000000001F8B080000000000000BB55B15
+:103EE0000B7854D5B5DE67CE9C9949322FF28020ED
+:103EF000249C993C0825E0F08884879F0702018470
+:103F0000E0046F1135CA2422CF840494CF28F4CE64
+:103F100009090894DAA0D6528B7642C1528B6D788B
+:103F200058D38A303CA441AD1DAF7DD02A7450CA0D
+:103F30004B9088F582B754EE5A6B9F939933495052
+:103F4000DBAFE3E7B7B3CE5E7BEFB5D7FAD7DA6B7B
+:103F5000ED73100F7E2EC94318B3AE2C678A9DB146
+:103F60007BA12D81F63AFE6E634C624C69059AB1D5
+:103F7000A879A623F6DC299B18CBC0E70D8C153158
+:103F80003643E77B7F3963B73076BF9BF15F3D30C7
+:103F9000F565ECDA0013F14DB1B239FE42786E8E60
+:103FA00064C7CF57EA9920CBC09A270B34EF8C9582
+:103FB00051B32D1DF8EC36F7360FD0C5C3E4798523
+:103FC000317EF12BCA5D26329B900AF29AA32CB562
+:103FD00010E7D7E556F93A5F22779AC6FF3B91D5AD
+:103FE000B7C2F8DFDD765B4401B90EAC18314294FC
+:103FF00063EB15CB16DA5F591A8C1DC958C76BD6FF
+:10400000D016909BC17C02F05F7A6D50683D6CEDDC
+:1040100004EBB8C68056F7A6C8B8AFDA7D29C45FEE
+:104020009BEC0A09D05FEBECC8F7833C25FB93C2FD
+:104030006C28ACB33FC9CC60DD2B390F14CB45F8ED
+:104040007CE044C10942EFB59A19F0A9D9CA68D4F5
+:104050005B4FF2EBF225B6FAFE4BCB05D5E5626C71
+:104060005A89433541BBE86A0E6323185BBC762A44
+:10407000B5AF043341C98C4DBA5A0ECA60ACE6EAFA
+:104080009DF47CC9D514A2A77D3B528AFB61AF0881
+:104090006C1BC85FD6EFBE550CE46B4F6643F6C091
+:1040A000BEDABD59BE46E8AE6E9E4AFC65BF983C7E
+:1040B00005F7B5640F30E3B8022194877A3A653783
+:1040C000B1DE8C3D64E3E27F5AF7A791328CFF7436
+:1040D000A4631803D64362EB536304B2673BDA73FD
+:1040E000C2CFFEB1FB2FC0275D159902F258AF0A6F
+:1040F000D446E4C022D407F031067CD5BBFA8E0C3E
+:10410000D8BF0A9E7E25C98047A9FA1309F16485A4
+:10411000B624AE7F8E8693443DD6CA1CD75FD50F9A
+:10412000EEFB8A785A8578CAF88FE26915EAA91BEE
+:104130003C3522CEFE553CDDC08E3EE689E16CDA90
+:104140009B1C1F2CC7E1DBC6082F2477BB252BD473
+:10415000087CF7A25D115FD7591DEA730EDA372D7F
+:1041600086D7973C819FC4DBB93D592D5C5AF855E1
+:10417000EC7C37C3B8716F7A1D53E0F91C68E3E338
+:104180008615ED57D8757F3BBEA69D9FD5F8BFCC51
+:10419000CEAF6976666EB0E348B29F8C764DB43B85
+:1041A000DA15ED5EBBCFBAE546761D9C1B68EF2E97
+:1041B0004E3077B209E58CD9C57A27E2E6D3B099BB
+:1041C000A17FF564576913D7BB4EAF0E9BA784E858
+:1041D0003C6069E543082F47FF9DF85356D2FA77B4
+:1041E0005B2FC6CEC8757E33F0CF2A86AE9BB07FDC
+:1041F00069B362C6F8027F8EA1191566237D6AF441
+:10420000B2C844D8EFB4A73AFB55EC9F34CEA58D85
+:10421000670A6CAB93FFB45C1BD9407237733B06E3
+:10422000A266FF90387A24D08E38BA3881DECCF975
+:10423000F11C71D33C211EEF617E6138D2FA7C9A69
+:104240001FB08ED25E60BF197B04F77AB0F73DE3F2
+:104250002E59D03E6525D123FD60BFFF273FEAB729
+:1042600027C1738C83206FB2A7A159356BE3C17F3F
+:10427000AA35355A5B0545043B55170B21AFA7AB53
+:104280001E933DC6F30C7F66E3786619F9F5C6A365
+:104290001D69BC97C687AD5F63FDBBC63125D44D94
+:1042A0009CCCD4F9AE01ADCF0FBABB13F617EAC65A
+:1042B000DF640FF79F88C954C3405F059EEF35DB6D
+:1042C0006E05FB328E8F6F789EF6AB855C5C256148
+:1042D000BF3792D7E9D1FD38B65FD9383E7C237D10
+:1042E000A577D197868F0546BCB8CCFEC39F821CAC
+:1042F000AE74C1AD82FD97F893363017DA5FC7F719
+:104300008FFC4A7FD85F12EBC4AB11DF21FF44D092
+:10431000E312A6F76F69C673C96FEAE4E778DF2B8B
+:10432000748E2F00FCB8181F3FD1D3D2ACDAC91E4F
+:10433000D44F74EE0DF0DE9A408F4BF00F0DDFE49A
+:104340009F18B7413F79DDC48D4A4DBF1705361B15
+:10435000E35E6402CFF7225EDE3678787EB750D314
+:10436000E352AD8D24C7E9A17FCCCEF00BB302C3DD
+:10437000BE494F77A76BFB56C3FEE9B0AF482A1B77
+:1043800022004E56B4EC6D6ECA8A8DFF564BD88F04
+:104390007AE89C4FDD17C1B87FB7A6A78696FD11B6
+:1043A00095C73301FDAE86000138D823A822ECB3AF
+:1043B0000671D0CD3EA775F51B3561BC22DD607C52
+:1043C00079571C2A09E39994FE75C66B769A9E600C
+:1043D000C72909769C984057E874C810CFF438571D
+:1043E000D5B671756F9063F176018F098CD7166120
+:1043F0001863CF78DEF0DB47235E65A91FC4FC6736
+:104400003D6F456C80E5728C6784DFDF362B6097EB
+:104410003BD1DF897EDBAFB8103F75AB33813FE422
+:10442000F95DB30D58EF69DA28614EB3D5F34EB399
+:1044300019EC77F7C85F1CC1F9CCC2BB91E9C20D7A
+:10444000F0DA9CB08FCD09B49AC0FFF497C4F7A6F8
+:1044500084F12B13FA3724D09B12E8B5C6F195737B
+:1044600005F2934AB01F2AEECBFCE6D79ECE7CA184
+:10447000F33C13EC942719703FAD91D3873D27FD92
+:104480006B0BE3E8960FF47848389618FFDD9BCE67
+:10449000543C3FA41EE2D9AE9EE25941E279C7FBEB
+:1044A000FF8A7FF6C5BC9319CEE543A2913E20EA70
+:1044B000FED61179D88E0F75FA921FF3F169DF37A6
+:1044C000EE0BEA42ADFFA27F22F8FFB4EFEAFD1740
+:1044D000FD4ADC3E75FED27F5E1771BDBFB45CF055
+:1044E0006F85F92A2684F3EAB04DE52D9C33229E90
+:1044F00063B536EE4FA5AF897E3C672A92C379CB70
+:104500000AE3F6C95AF3719F075688641FB591D71D
+:104510002355CC6761500A1D70B9EA5F00FE432B3A
+:10452000C47A3CD74ED4A7F546F9077B79BD77C846
+:1045300035A0F783401F4899639181EFC0E393A8AA
+:104540003D282A6B3A00C7573DD7FCF641D8EF22E9
+:10455000FDFCBDE58ABF01E2F4158F4CE303A9EE33
+:10456000DE6D98AFAE97D83619E5F13D4FB8F98EAC
+:1045700075D87A90A3B261706FCCDFAABE575EDAAD
+:1045800017F8AA564B3E81F8D850943BB07E92055E
+:10459000FBE73669AD3A99DAFD5FEC7E7328F07778
+:1045A000AC137D5B8079DF55AFB30AE4FA3089C77D
+:1045B000E10F2EE43A51CEEF7A03A217EC5AE974D8
+:1045C000240B7878B865E74C9877438E62F616C569
+:1045D000F8F77F21CEC17CF3D50B55BD03403BBD21
+:1045E0001CAFFBAE56F5AE8A3BEFE75D34939EF70A
+:1045F0005BE48731BFDC9F9C25A8E4C7AD69E5E09B
+:104600002F73B5FC1AF052BFBB9B73FF1F1E917036
+:1046100076CA5ACF3E04101FF876C63894531F57F7
+:10462000F4FB40A303F1DC5F1E1E9F47BBB227DCF7
+:1046300084FB88E12CF51D3C2F298F063ACFEBDA5D
+:10464000A802AED821C8FF518E74A514FBD94A60C8
+:104650008038C6325BF3E3EF236279EA2A2D1E70BD
+:10466000BEE3AA83EAD6E33B924258CF1C57DF73DE
+:10467000307B3C3FF793F94E878A87F11987C38CCB
+:104680007A3D610E9E7E14C6CD7B4EA2383AEFB9BC
+:104690008C951D180FC09E79ACEBBAFFED9568DDC7
+:1046A0001EFD84C9E513C7C5F9893AA01CF7D39349
+:1046B0009FDCE61D50BEB5B0673F99AFE5EDA5CFD5
+:1046C000497EC4F9FC228799DD0C75F673AF6F4300
+:1046D0003CCE5F9A34DC0A82CF7FCE4AF68D3A1CFC
+:1046E000AA1BFA034E87B917B4FFA5E121DA90445B
+:1046F000758AD8DB42714F5C5324A37E4A4466B668
+:10470000C1B9223A7DB29FD34D6EA8DB563B8A6574
+:10471000B4EF0AAF4C7AEBEC77CDBE5D80BAE632EF
+:10472000EC230DC69DAB7FEA995120DF79169A35AF
+:104730000AF47E190D0DEB5CDE238654AC8BCD8A1A
+:10474000B90CE2DE02C6FDBDE6E86ECB78F8734137
+:10475000DDFCE9581F2D0C491F44B5DAE73AFCFF90
+:10476000197BCB82F9EDE2EDC6E7E03116F4AB9AA6
+:1047700056E3F35AB6E1137128B6E60FA205DA73D1
+:1047800058B7FEFD3F0F391CC757ED75A49F1E0C8F
+:104790007F0C67C341B3B04EA1EB2E845DBD48F2E0
+:1047A0008AAB9242A847319B9F0F9399104A42408F
+:1047B000B861DFB0EE95E0B121870110E2632348D4
+:1047C0002FA78280A781A00FA78DF8C5C7C4901519
+:1047D000D62D49634A2FD4E733E58C39489FAA1B6D
+:1047E000E8C9E975668C4FE7B4F85229307F2BF998
+:1047F000BD2F1BEBE379CF2591FDE63FBFF08F3F47
+:104800001889F62A4B8FF7A3C735DCC17CCC961AE2
+:104810009BE74CC3B7B2519E921F415D89F5A61824
+:1048200078E66E8A97293E8A5BEEE87746214E1A33
+:104830005286AD678893BED9DEC2D8F8F9AB56E48C
+:10484000F3F150AF3A315E25D17EAAF7580927958A
+:10485000EB4485CEC72C0B9D8F1F3425115DDDBF2A
+:1048600098FCACD2C402B80FC8053329AE7395B317
+:104870006A3B5376DB31CE6F88884EB28FAAD9CD92
+:1048800082F6D9E24DA3F5E7A08EE1DC3AE8D5F453
+:1048900062E2F861FB84D0368A4F7532FA7F85492F
+:1048A000A03897E88FBB3109C371D9BEFB715CCDCD
+:1048B0001356DF2A0F9741D4E5013CD59822F37EA9
+:1048C00088F3FED24AF71AB5B08F2427D517CA2E1F
+:1048D00090BFD6CCCC16BC9792793CD3E5A995CBAA
+:1048E00027234EA1FF9819FA6B1C3C1ED7F4E2F760
+:1048F0003DCC610B6D8B5F0F65CEE1E36427FAD988
+:1049000068C20BFABD09FA2F31DE5FE22C96A3F0E4
+:10491000BCDDC4D6E23D09CA336868DCBA40F71D85
+:104920008A785C6AF63AD00E69B366E37A2F891406
+:1049300097C0999E28C6FCEF257104D6B195EB0E61
+:10494000956E427AE730378A50F9F377E97C5AACB2
+:10495000E12C8A793F9E5740EF84F63D2FCF2F02FE
+:1049600022BFC779CFCBF37F5DAF7A7FCD3A89EC99
+:1049700051B39AE3A1A6E14F346F8D23D21BED51C1
+:10498000F3B2740BE2FA941627AA1AB2C61D037C7E
+:1049900054492EB7008FAAD5320BD2D5CD02D1FA09
+:1049A0007A35EBFED0DB54C8E7C3D6AAE128366FD0
+:1049B00046369E671FED48CBAE8CB3FB474DAF38F4
+:1049C000653BFA4D38CF8DF7304B937C5BC84FB9C0
+:1049D0003D3E6ACADB82F73473DD118700FD731F29
+:1049E000CE49C573EE843B6CC1FE13AD1E13D28A53
+:1049F000DB3D0E69C57C33D11F41086FD5EA56C433
+:104A0000F11281E3A67AC7218B17D64BCAE138BBD6
+:104A1000F8D2BBF9785F50931DC9C7F3177095DFC3
+:104A20000FEDF2A24079C2921DA292343486AB25DA
+:104A3000882BF0FF451AAE96EC79E511F4D3258862
+:104A4000A7E15D710975E5617ABEABA594F1F187C7
+:104A50001177FA790F749384F76A168D8675904EE4
+:104A6000CEE1B881FE89BC5F2DA47384452D980FDB
+:104A7000D78A3C4F007FCAC43CA2B64D523BE325C7
+:104A8000AE8BFD85B1FE9E703338879F27550D563E
+:104A90003A8F066B7A89AE7BD989B8B8F8D2A12350
+:104AA00063B0BEDA25B831DE77F1434D6FB5A82784
+:104AB00027ED93F2A25AD48B33A6A74E7FD3705121
+:104AC000CBB81E74BDD49A353DE9FDDAF8C21C8E10
+:104AD000C36AA6E975CF40EEEF9A7FEBE788BEBFC9
+:104AE000402A1FAFE3EBBE1C8EFB31DA3EAB013731
+:104AF000BE42C29762B945ABFBA1EBE2CE16BA3714
+:104B0000D2EDA9CBBD5C5B1FE2B4D22B3566E7A822
+:104B1000892DE8EE9EDAAFE94FB2F3B872B2A1DFA9
+:104B2000FDF5A0BF453B441F290F6BAEB875ADA680
+:104B3000A883F2D2C74437EEABE467E5B7E3BE75AE
+:104B4000DC49DB0573DB48AC337A91FE75F94AFA30
+:104B5000F86FEFC57117467974394F0A61B297BA89
+:104B60005370F33C376AC1FB43DD4F13E5BD2F475C
+:104B7000D0F201618C7033CAE393D1BF199C8324B6
+:104B80008FFDD80A5A4F3DBEC23334B6CE09D56127
+:104B900046BE138CC7011D9727B5FB8893AB5FA159
+:104BA0003C585FE7A1AEEB04EAD3BBAEA3F32FD62C
+:104BB000F875BF684FE5F82F69FA13F1E971167FB0
+:104BC000780FA7EB53D75B9C5F1AF4A3FB97EE4FCC
+:104BD000BA5DFF55BF622B33285F7D5CDB37F94838
+:104BE000EFD8B980F8C4F3CE6A015CDA0DE726E5A8
+:104BF0003593FB7F620974F35CD753E2F3583DE5CC
+:104C0000CE46FD4FB6679A300F604D998773E3F239
+:104C1000B20FF1BE0BE36906E3EF33187865DC7978
+:104C2000AEE76BFA790DBF0D9DB884F1B5E9CA39CD
+:104C3000EC5F3072693EE6119772BCB4EE79D66AC9
+:104C4000190FF3559F8D943AE558BD72EBDFC3A25F
+:104C50000BEF03F7780CF542F585C3E4DF352CB292
+:104C600006EBDBCA75EF968D42BBFF14F271E09B39
+:104C7000DBECA173EFDCD6074660295BB93A8FE81D
+:104C800085DB1EE4F43A9ECF55AE2E7A01EFE33F6A
+:104C90004C524A11DF1D1B0537D65B63B715ADBCFF
+:104CA00007FAC73A06F442B98F6FFDB06C0CD60D07
+:104CB000F522F98BB2F5A959D8AFB4893EDCEA5C8C
+:104CC000E65E790FE2DBEC227F3BA19D138D12C7DC
+:104CD000D91B5A9C38A8C58D831A0E4B1A1BF34D4D
+:104CE000B86E0B9C4FB0FF0A8BDC1AC6BAEFB53E0C
+:104CF000BE2DA82F285333014767059E7F2FB03064
+:104D00001BE2EAA814598EF21F5DEE18D6800288C5
+:104D1000D76E41BF50B43A0BEA265A57D797BEFE1A
+:104D2000512D8EE8F3E8E3DA319FC2F34393F75C49
+:104D3000D34F67619E706E7B5E2A8BD3FB39DC1785
+:104D4000E87B21C4C55DDDD47F7FCCD1EF23427CDD
+:104D50001DEDDEF0A8D4DC1FDFDF421E7F2A3E2FD0
+:104D60003FD39264433C421E6F7C2EF1F304F278F1
+:104D7000C373F09B53C67C5FABEFC40A57A09B384C
+:104D8000A4B78979FEB91C7BFAE914D625CFD7FDE3
+:104D90002E71BC9ED777DEB3BC6F4F781F33CAC568
+:104DA0006EB0FE852018066ABF16F45D907762CA61
+:104DB0003F7747B09E6CB6BAADA0DF53E857F81EF8
+:104DC000F06591E78936E60B032E4EFD61840FFDF9
+:104DD00070DEFBDCEFE6B50A217CC57E78E3E322DA
+:104DE000F23FB859607D84B83AEBE98DB3D0ED2E2F
+:104DF000FB026BFA02FFE5ED824F2509157B427D30
+:104E000075A4AFDC737DF5EFD655FA3D53A2DE33C2
+:104E100073B5FACAC77C46BDF3FA7C3FC0A7787861
+:104E200057BD5F0806A88EFA38B880DAD1AD2D25B7
+:104E3000FD40FE4BC2C927C6A2FF385C744F7221E9
+:104E400058472F013F6E1B716D06E8E755BBCB8DB0
+:104E500071E3E3603D3DEFC48B86CF5BF71C10FB35
+:104E600031E2DF3B16F8F7D95DF85AA39BF76DDC0A
+:104E7000BE9041F1F7A35ABDFDD0D2517DF0B9BE2D
+:104E8000DFF38F723BEBF29FDFFE8013F3D3033F20
+:104E90004CDB3B1AED9BE272238CE66F12596004E7
+:104EA00063A737F13874D6E67A613AE8EDECE63B71
+:104EB0007B633DF8A0D461F1C1BCBED7CA9D787FA9
+:104EC000F63773D4E9C616F8C32887392462FC1B69
+:104ED0003385D17BC0316133933DF48A9E7032FAC1
+:104EE00082391406FA237C3F88E7F6B564FE9E5E9D
+:104EF0007BEFF7E0AFF87D5AE7FD89768F3056DB20
+:104F0000EFC3B9A95C4FDAF39262FEFCCCE6DD3365
+:104F100070BE735B2537CAFBF15689E65F0475BC2A
+:104F200009707816F086F16BD1EF451F42FADC76F6
+:104F30005E272F02DCE27D71CD5249B1B8BAE2B1F1
+:104F400044E7DB2B507DADE37291122A25BD6BF84F
+:104F5000B4C17FD7E1C8E8C55AD7A03E1271FAAFF5
+:104F6000D6FD8B1197DDC583041CE8FAD2F110C37E
+:104F700027235CEA764F6D1D36BE1F0D50295EA8B3
+:104F8000135801E6058D165660461C98927DE8E799
+:104F9000F536E750BC67BA92C4DB474CEED7B15E3A
+:104FA000BE62922501DA13B91EB2C323A26F12D2D8
+:104FB000527A94EE07C4129362C2F3AED14AF12240
+:104FC00031DE3C9ECBE3703F041BB43FCE75532BC8
+:104FD000B13ACA1FF416369885F949794AEA673218
+:104FE000B03CBD75CA4C33ECAF7C6CEAF21CC82CEB
+:104FF000376F9D3113DFEB968F487DD90BF4F3B9F2
+:10500000659CBE39B54802BAA1E18E991381FFD5DE
+:105010005CE5C9DCA2D83AFABCF0FC7BB940BFDE43
+:1050200027B009DB5A8B7D2DC6FB4B42C712931864
+:10503000E37F4760275E1562745462D9984FFF186A
+:10504000DF7915F5DC9EC9555A72BB795EC5D86A01
+:10505000D46395FA9B6398AFC1CF6F03BCDDA1E128
+:10506000ADCA660F232ED85AE942272EBC18975C8A
+:1050700066F4EF199AB9EF30870FE0F841ACC97DBB
+:10508000DA46A9E0E6EB693DC779704C765A9F0F86
+:10509000F6774982FD825D05056C0D2E2580922BE9
+:1050A00020BE097B7FF339CEDBA8B26812D9A1C23A
+:1050B0008D71516001D375686B52000FA0A7652FE9
+:1050C0005F3C8CF05FA8E75399FCFB8CE51A1EEF60
+:1050D0008828DF6F01A1CE04597A2ED8FA223BF836
+:1050E000B119D63D670AFC06F55D6D7A2B7B998C6C
+:1050F0007EDBE8C4FCE5E2CF45DF741857ADE5ED93
+:10510000EC9A18BE0D9EB77B066D591F87A3482EDB
+:10511000CF172E78C2D92B307E7878DDC9AE1DCA64
+:105120005E01FC53BC538BF05C7A9A29FF931BF70A
+:105130007E7186B9FBEF2FDEBC89E73B6C2B3F5FAE
+:10514000AD66A63A52A9654ED0C75490A518680915
+:105150006891DEC787687DE473629E223F90C9DF55
+:10516000D7303FFAA36E47DD3E5DEC0622637E6ECC
+:10517000B23109FD6510DBEC46FFD6ED3749B4537B
+:10518000BC59F632BF8F5B26449BD2907E09CE4B32
+:10519000D497E6975DCFCD6D1634C582CD0F507C88
+:1051A000D2E3920CFF217EFE53F792D7F57373186A
+:1051B0001B86B8FAB27C478F4B601F4B5EC6D7B0D8
+:1051C0000FAA08F63B5F5B7B9258219B512F193643
+:1051D0001FC6E565CFE5D079C79A9E64F17C6C73F4
+:1051E0001AE1738D47243B96B5F563323C5AD826B5
+:1051F0003019CEB9E96D69443BAFF625BAEC277D8D
+:105200002660FEDFF9DEF22703893EF7C29B230307
+:10521000FC7EC586F3FB992E47612BE64397ED2074
+:1052200007D8C16F5F4BF7857ED659C708D705A44D
+:105230000125E84F8AA472BBD81AC8AFB57D2D737B
+:10524000733B2E3BCACFDD65E3F9FB3DB33AC8851E
+:105250007890DA451602FA9B47C5A230B0366A71DB
+:10526000D99A6962729C3D92E46426C7D56F4C5509
+:10527000225827CDD6709252906AE87F5C08482861
+:10528000D76CFB3CC28DC3779361BE4876693BE91E
+:1052900023C0F35B1D4F4CBC6046393F1B27B03425
+:1052A000C0C53767437FDCBCD2B84F260AD41AF397
+:1052B00062D0CBA91BE1696A9E86A7416C10E129E7
+:1052C000413FE01F947F5E86731CD326C82EBE3FED
+:1052D0000EE859ED120BC9946F92FF5C5652E8FE2E
+:1052E0007EB5A6271D77FE81CCA1C0BCAE62A3DE31
+:1052F0007A2946BDA54D31EA29C36FD44B9FD95EAB
+:10530000437FDFC0370CFDFD160C37D05975630C99
+:10531000FC03EA2718688F7ABB813F67ED4C039D39
+:10532000D77C8F817FE0A62A43FFA0D02243FFE0F5
+:10533000EDCB0CF490D6C70CFC37B7AD32F40F0BA5
+:10534000AF37F48F687FD24017459E35F08F3AB65D
+:10535000C5D03F3AFAA2A17FECD95D06FAD68E5F9E
+:105360001BF86FBB7AD0408F676F1AF84B6CEF1A3F
+:10537000E849EEF70CFC93333F34F44F953F32F499
+:105380004F2BF8D44097F9FE61E07FF6A6C0268C3B
+:105390003FB34D1B8EAB0CE3B3FCDD7180E7BBD29A
+:1053A000CDBE30327DCDBA2D94A7E5691A6E3F632C
+:1053B000F6FB4DDE2F8F83AB312FC8405C4F6778F3
+:1053C000DF7BB955205CF7743EBB20DF35C7EDA30A
+:1053D000976283023C46A74D711BE80C7FA681BFF4
+:1053E000CF6CD9D0DF375060E8EFB7C067A0B3EA21
+:1053F0008A0DFC03EA1503ED51A718F873D6FA0DD0
+:10540000745EF36C03FFC04D0143FFA0D00243FF65
+:10541000E0ED75067A486BBD81FFE636D5D03F2CAE
+:10542000BCD6D03FA2BDD94017453619F8471D0B51
+:1054300019FA4747B71BFAC79E6D35D0B776B4192E
+:10544000F86FBB1A36D0E3D951037F89ED1D033DB8
+:10545000C9FD6703FFE4CC9386FEA9F239437FF5CB
+:1054600047003FCC9F5F15E8FDD7B4824F0CFD523B
+:105470003AE4E9783FCD927DA2D0354FD7F3B732E9
+:10548000DFE786751E31D5D17771574C3CAFB3E459
+:105490007B097790BFDB6C1467E1841A42572D0DAE
+:1054A000989FBA54817087A94605DD17A6D37B055E
+:1054B0003A1A65FC0E0DF21B20524D1E0FD60F2915
+:1054C000B13CB4FFF5115F3D0F4DCF67FCBE293FE6
+:1054D00090949F81F5D8CE52AC4F1632750DCA010B
+:1054E000E7AB0BDF33BD9D64BC37D2DBA936D05FA1
+:1054F000DC7A47939AFB0FBF81DF4EB55D20FECE6D
+:1055000079B57B2501F6B72C6EFE27A06E324309D4
+:10551000D91C04FF023F7D32E826FAE96026D1CF8C
+:1055200004656A37050BA87D36E8A3FECDC162A2EB
+:105530009F0F2A44878253A8DD12F4D3F3ADC1D95B
+:1055400044BF100C50BB3DB880DA178375D4BF231D
+:10555000584FF4CF832AB5ADC1B5F47C57B099E864
+:105560003DC14D44FF3218A2B62DB89DDA5F075BEE
+:10557000A97F6FB08DE87DC130D1E1603BD1078359
+:1055800011A20F078F117D2418A5B63D7896DA3742
+:10559000821DD4FF56F02AD117B4FBFEF1F9FC5E50
+:1055A0004ED78B4E333691F0A0E7B533B06E4170D5
+:1055B000144B1F1BEA9684FA21D11EE7B575A40986
+:1055C000706C639E7353FE96C6B87CBF4C5BEFF164
+:1055D00064A62641FC6BC0621EA0D890CA428DF41E
+:1055E0007E95E7DDF3355CB2749E6FCFD3E49AAF5E
+:1055F000F94311E2B380F0F9D6D7A993F43AF95BF5
+:10560000FD03F7113EB34C2ADD13D843F998F78711
+:10561000FA0702F920DFE5BA078FD07A6E5F3E2ED7
+:1056200052660D67DC85F73F4745BA2FED69BD5AD5
+:10563000EDDF2FF4D8BFEF5C7F3C87A67C21D27DC5
+:10564000FADB926336DE8F2CD3F4B22CDF6468076A
+:1056500066F997A29C67F2EA5E7808582A96E6B93E
+:10566000306FBD034B6BF0FB72264BF47D2C535E09
+:10567000C74F26BF09891DD2773195DA9DFD028F6C
+:10568000E17EEE860202E9C0186B7677FB4994A7AB
+:105690004993A74993436F2766F91B71BE53798AD3
+:1056A000419E47B364ED7BF78EE751AEFF7DED93EE
+:1056B000D3424E4CDFFABDC49AF1DAF7534B05FDE5
+:1056C0003D35CF076D4CCF07A9BF6239BF9FB90FDA
+:1056D000EA327C5FF9BE160F2FD749142F2B846452
+:1056E0001FE6D397EB960FC4FD24C6CD0A18678238
+:1056F00071158C7F0F51F17E0AE10BE663F8DEAD88
+:10570000023277ACFFAAB3F47B8FA83D83CBA3E032
+:105710007BD8397BAD2D58A7024EB6104E468BAACA
+:1057200005EAE4B74DA17C41247C580490777E3A89
+:10573000E0A39BBC40C7C112EDDFC7E8CF015F3BD0
+:10574000507F1FFF6A5401BD37D9375A46FD359A3D
+:10575000C01E785FF386C8BF93C02B76FC8EC355FE
+:10576000D842DFF9631281F61AEDA0F721074456FB
+:10577000BFB39BF8F9DB7C5E5FBD9D294D09D1BCB1
+:10578000C6F77C47343B1ED1EC5B76F068D62330FD
+:10579000EF927689EA1D36325AE8EFE6FBA6DAFA8E
+:1057A00037FBE6C6EDA3B6ED24FF2E8A450BE3BF1B
+:1057B00087FA9BB6BE8E27D1E208B4D8E3E5E3F7BB
+:1057C0004580EBB7345C9FC6BC7E865576DD0543CD
+:1057D000A3A09A30B4811FB9E9BB3AFDFBBAB9CC9A
+:1057E0004FED7C8003E2D8AF6EA4FA77116BA5E78A
+:1057F0004B8A1FC846BA96754CCCC4FA656DC3EB8C
+:105800009920DD9DCD1B27E1FDF3CC50E5EBD8962B
+:105810006F154E63DD0D7E711CD78F0A75ABB124F9
+:10582000BD67C7F8D578CF3B43E476606F723B0025
+:105830008E1431B5EBFEC00F4EE178F003925FF7A6
+:10584000838A551C3FFABFC7E8F48BE2C57FED871A
+:10585000EF3ECC1DF45D48ED3E6B2AE26B11569E87
+:10586000627C5EA89FCF3C2F580C7901F29D97B8BF
+:10587000FDCF1F4FA27FF7725E007C0CEF8A7B3D4D
+:10588000CFBC62E2F76E8F88B04511EBE5A7484FB9
+:105890000B6CA1A1A827389FBF401C2EFAB075CD74
+:1058A00030BCEF9B10CAC67C557AD1EA6BF418E283
+:1058B0003CBB9E12BBC77B42E2F76A89F276C95BAA
+:1058C0008A8F7C8EF984D5C2547C9F04FECFFDFE66
+:1058D0000497FF8A2990798BC8F315AAA3FBFBA92B
+:1058E000FE67BD6DBEF542D7F59BB475DBFFC9EB16
+:1058F00069358BD1F7388972086EBE6EA23CD664CA
+:105900002E877EEE749587DB4197277FA087DF5334
+:10591000642BB4EF06532F8A5F97C440DE403C2FC0
+:10592000B5FB31BD8E6DF79CA1B8CEAE35F6E7DF85
+:10593000F7867B3A4F2F74D6CFDED879A7DF33B105
+:1059400071DDDF0BFA6D6E09ED3693F928EE0F620B
+:10595000EFEBFAA17BA6FF0732EFAAC6A039000041
+:1059600000000000000000001F8B08000000000085
+:10597000000B7BC8CEC0F0A31E82C539106C6271CB
+:105980002D0B03C37B56D2F5C17005507F3110E754
+:1059900001712610A700713C104701712810BF0249
+:1059A0009AFD14881F00F16D20BE06C41781F80C03
+:1059B000101F47B277291B03C31A36D2EDFF8DE4BF
+:1059C000E70940761910CF20231C46F1F0C0723C45
+:1059D0000C0C5ABC08FE5E5E5479791E047B99203B
+:1059E00065766D05EA070050DE58A18003000000CF
+:1059F00000000000000000001F8B080000000000F5
+:105A0000000BD57D0D7C54C5B5F8DCBD773FB3BB2D
+:105A1000D97C10120870F3014608B8240141B05E29
+:105A20003E8CD1A206B4482DD505F908494822DAA2
+:105A3000CAABBC66490209883628225AD4054141BE
+:105A4000898D7CD8D406FECB4731F6A98D1615ADCD
+:105A5000B641FB14154844119FB57FDF3967E666F0
+:105A6000F7DE6C08D6DAF75EF8F19BCCBD7367CE33
+:105A70009C39E7CCF99A898D6532CB10C6BEC69F9A
+:105A8000CB18BB59668C8D8994A3EFBCAEACA90032
+:105A90007EFF9BCDBF558DB4D3CB214CA2768CA578
+:105AA000323696B1CB1CF02BB49BF2FC893F5D944F
+:105AB000CCD87E26333B3C0A2B5392AE867EF67FB3
+:105AC000C5FCF8DEF2BC3BBDC38DDF05194B61ECB4
+:105AD0007B8C7F17CE50D37DB95861167CAE39E8E8
+:105AE00077E8276B63157C7FE60B377D6F86432F46
+:105AF000D957161616DF7C9D89FD2A9F75E4887A92
+:105B00000683C19980379DC6D5E13DF4CE0704EFE9
+:105B10000105E055638CEF00F89323F0EF67D7C5DC
+:105B2000B35C0EBF363602FF378587E6DF8FB1FAEA
+:105B30006AF5FBD956C6EEAE66DFCF1ECAD85DD574
+:105B40000EAAAFA8F651BDB63A95EAF50A7C0278DE
+:105B5000A8DFC64241F8DE5B00EDF5FEE0BF3BD7B3
+:105B600061A8DB92E17B47A4AEB8530D7547BA6AD2
+:105B7000A80338475261DE23F823181F7060C7F16D
+:105B80001D4CBB00DF0F25BC3805DE6A3DC36EC867
+:105B900004BC34BC22332419ABAACD42F886BA6DBA
+:105BA0006A08E01BE15E308D79615C6F8031685777
+:105BB000FB2063F7C2F3E1EEC20FF1F913D07F03CC
+:105BC000F42B7B1B8EDAE1FDAA0C9B2A235E762840
+:105BD000EF229E1CF00FF196B391D723F332D687B4
+:105BE00033A8EBF380EF7F9FB0FEA80470D466DB90
+:105BF00054BB1419A77B5DFAE87FD8BA73F73F54FA
+:105C00002D9E8C74AAF73B8C056A7CEEFFBDFD8E41
+:105C100000DC26E545FAD5C7E9B35F58FE62F876A1
+:105C2000D846160A4B3DC719AAFA8B82B8DE1B1557
+:105C300016CAE0CF93811F860A7EA84F9FE10AB85B
+:105C40007BC2C3A2C7C98CACCB50D536C7320ACAF7
+:105C5000EC996512D0075B17F55D262750E4975F36
+:105C600054FB881EEFAECEA1726BB54F433EB9FB1D
+:105C7000EFF2ACE6DC9E7CF8579453F0DD3D5646DF
+:105C80007418DCCE425B25ECAFEAE81CA8AF199D86
+:105C900092B75A25A02D28C774FA5E23A944DF4184
+:105CA000A06F947F66FEB8DB5A7C15D2FBAAD11692
+:105CB000A906F19CCDE97DA835ECC882E76BD665D5
+:105CC0008E0688D91AFFAB1D38EED0A1C388BE87D7
+:105CD0006773FAFFFD98F50E9483DDF35F9AA26572
+:105CE0002731168FEBE38EAC97EF3CE9C037310AD2
+:105CF0005F31E8401FE79FCD0FDF1D7D359E93BECE
+:105D0000D6F8333FB4C3FBADC0E7B2D413AEC42161
+:105D1000E1D4E2DC9EF436341BE80CD7C97F6E3A3E
+:105D200033976BAB43EC3D187C7D752AD1DDBA6AA5
+:105D300095CAD54887202751D6B0F150473AC4F5C7
+:105D40004A2FA07AAFFB155B4EFB51C2D410433EE5
+:105D5000598FF479093E5FA169B045F5CFD1EB2C9D
+:105D60006C01D9BF0EDF0FA0BA865BD85D925E7F53
+:105D700026A8C1F7FD7278BD507A26589B0DFD39D3
+:105D8000F9F745D2292D981EFDFD5D9A3631D21EB8
+:105D9000EAE1C9D9D1FD41FFB9D1F01CA4F67A7F5F
+:105DA000F3A4635A10EAEB9CBC7D8374F45FD2FFCA
+:105DB0006AA93115379A5552375EA89FD57A3DD8D2
+:105DC000A869B9917132963FAD05A3DFB3A70DEF76
+:105DD000C72E6F0C06016F0FB0E22C09D637715633
+:105DE000552AA844CC393BA459D568F838BE23F3CA
+:105DF0005B4FF0BAB2F9FB5CE98F5A6DD4FA4C9262
+:105E00005E0E22FCBA7E63E5A4057A4FFA6D2F027E
+:105E1000BD5BFBDBFCA467A443250DC69B1A642A6B
+:105E2000C06151830CE5815555DE8FE6039DFE0070
+:105E3000CE71046771D5AC5EE00C46C3A9C3D1171F
+:105E4000DC3A1CBDD3291FDF4C4F936F1CF78789A9
+:105E500040E2CE76AB1FF53C54995822FCF2D57D3A
+:105E60009A025DA6DC04B85769DD66B1AC9EFDF60A
+:105E70009F358085A2E6F9CF5ED72CAC8F21BCDDA3
+:105E80002C8D89AC2FD4E744E3719C6867A63F7DD5
+:105E90007E0E9C9F1A3DBF5A4D2988CC8F298DA913
+:105EA000C59EBEE7B7CE593CABD8DDB3DDEF25AE1E
+:105EB000474F9E31EE5AC6C72359928CE3E545C63B
+:105EC0004B9EA98F178A395EBFE2EF169F667ED47C
+:105ED000E17522BC19D1F0F2F5D7E15D6D05BE8DFB
+:105EE000B1FEDF35BCE7CB7F2E90BF2A7C6FC901A6
+:105EF000FECBED9DFFFED9FD25E3AF404F9F2A2C41
+:105F00007C19E0F1F6E98E50508AC8B97F35BE524F
+:105F1000F015ACDFED2FDD72EC320B5680AE47464C
+:105F2000C6AF905482BB37FAEE6D3E8C850CFDFCFB
+:105F30004FCDA737BC7ED772E87CE56BCDEB2E6EDC
+:105F4000DF65B310F27F7DDBE5F10CBEAF7F714AF8
+:105F50007F84C3DE308269F98CDD8F9F805E512F94
+:105F6000F45D767DDE79E919ABAB995607FACB1E65
+:105F70006F15E945F512A3EFD780DE16023DA6E0C6
+:105F8000952D8E396ED4ABEEA5B2DECA488F297836
+:105F9000E5906F0A4CC135347134DA79F54EFDF96C
+:105FA00091A22C787E57363C07D2A8F7F0FEE07914
+:105FB00031B68F1BCA9FF706571CA84D75517877CD
+:105FC000DA428158F2F17B160BE1E75ED4BBECA814
+:105FD000F7AB543A5D8D01243AD7609BBA39A3E7F9
+:105FE00077B32C5CEF5F3BF4D9306E73AB84FE76F5
+:105FF000E0F2C7892F5DD98D9A05BFF773D7C0BD71
+:1060000026FDCA9DABD753A529B067BA4CF5BBF5A1
+:106010007D37A84E427DCD2BF49D4935974EAA8DF4
+:106020007ECF2E9A84FBAEFEFEA69A31F43ED1516D
+:106030007574228C9F08F2B316594751A52AA4976C
+:10604000EB1363D2CBDA2B1DB342F07EEDE5C33206
+:10605000E6C7B0736015699DF57A529191AEEF1560
+:10606000FAEADD427F4D451E8F926B4EDEB45BAE89
+:10607000392FE072CD95A32E47BA4C2A627ED4B355
+:10608000D702FE0251EBE4CC01F9166577242AC64B
+:10609000797D57F37980693FB4F4EBBD7F337F3D61
+:1060A000C00273B07DA2D8A75C397E2990DBF7FCD3
+:1060B000CDF3ED6DDEDF17F884712A628DF3AFC288
+:1060C0004BA21BC629F8E78FE3C271A2FD45E78901
+:1060D00077D84784DF8DC9B80F98ED2A57814F6272
+:1060E00016AAB6A3FD9D84AF00EF1ED658340CF857
+:1060F0003AA978E5AD68AF79DEBEF243360AEA1D0B
+:1061000073A66159979BD73619DAC5FB7DD30B89E6
+:106110004E19E1791576467CB768F924981FE1009D
+:10612000F8EE51CB4D9382B99CBD71BD7F22E682C2
+:106130009AB7A2EFEB99B1E66163618E5FE96B7B81
+:10614000CFEF7B9BBF35F29DF0F72D213F695FDFDD
+:10615000B16936F21B06E11FDAA309A67EE2355BC0
+:10616000C4AFC8104F517578FF42375FDFFA2F195F
+:10617000CFC7EE75A8A807655B7C68A7C7335F0229
+:10618000EA7FAEA9A00880BCF02577052D6ADFEB79
+:106190005207A605ED674077D3A3F4DB3F5BB87EDB
+:1061A0009C3C636AC60AE8F74C01F70327F9B8DF9D
+:1061B000C13C9FBB603F0BDBA3EAB99B897F6B812E
+:1061C0009E32812F82B916F267AFCADEE98BE66B89
+:1061D000264B026F66FA60AA027894057DC8D9162C
+:1061E000CD39EADBD387FC0FD247DCB4A8EFD83730
+:1061F0005F2F8FFCCDE8E3DB8EA7AF6B4FBE5A2E2F
+:10620000D6759E03F59B95A933E263C9D9DED7F510
+:106210005E5A57B067B5508CFE13BBD733D8B34C1A
+:1062200011EB493FB719D64BEE3F76D6A673AD5B5F
+:10623000B2111F7ABFCEA5B2FA57145E8A8FFCE462
+:106240000ED1DF2AF5DE20EA2967706F077CC88D42
+:10625000A3C3B89FB26CE6DFCA9B901EE254B5D0D0
+:106260006AAE2FD3BAE8F0D9D22D86F194649701A3
+:10627000DF6C1668D951F03B97DA080E078E07E3FA
+:10628000C83EE85042FF3F0B3BBDD423F587437D1A
+:106290009D85F53B0D74509F9E1773BF53C4BAA2E2
+:1062A000B9CAE9F5CEF3932FE6F1AE37C27BDEDF54
+:1062B000B915F5FD283F5DEFDF29EC7D1D5F80C43A
+:1062C0001F77D33B5FA79556D622C5833C489DC90F
+:1062D000022AD4F115EC630D588E473ACCF3915E47
+:1062E000B04D52104E626915FFF3FD6E382AB5406D
+:1062F000B7164780F024BB3546EDD5F3DB0FCF5AF8
+:10630000B99E9C2C3143FB65B28DDE2BAC98A1BDB0
+:106310007CF69D2B52A95F0D1E8D8DC061EE77B866
+:106320001C58268F41B2E3F0E007E81F601D39E4F6
+:10633000CF4E13383B3B7F06D913BDC1F7A089BFB1
+:106340001E14F6012B2EE8635E9C8FCFC298EDD809
+:106350005E515D380E3B9E437CA08AF1370733E9DE
+:10636000F9E68673F3F92F110ED04F1FAD7650F971
+:1063700058B58F4AFDFD63C2EED922713B447FFEC2
+:10638000B9CCED845699EF179B1D8D4EF2431F7CBF
+:10639000F0CA61C05F038EC87E27E02F6B913F314A
+:1063A00010435EE865F61A23BF3179F639E15DFAEC
+:1063B000F6A4E987A2F8B149F624BF1F07BF5CCC59
+:1063C0002E46FAEBEBFBB3D5DAF44343BF3D5EB6A2
+:1063D000083BF4F3DA9797939E13BE8CF87380A072
+:1063E0009B01E55C1EA8752CA422FF7EF5358BA6CB
+:1063F0000FD8A92DE84F1F58C2D843D07EF33C8B4D
+:1064000086726BE05A5BC842FCAEAEC67ADA11996E
+:10641000ADA6BAE69E13E58F4F93DF5E0E14CC86D1
+:106420000AFD4CF7ABEBFEFF4141637C62208BF22F
+:10643000CB437F6942BF4B33F9F1BFED7AFCE57F77
+:10644000683D1E53FC2E5FD4F759122B8EB50F9E5C
+:1064500011FB54D6DD5BB83D52E266EF45C52BB665
+:1064600048FE44DC0C1E5DB373BF0DE35125CC3FE9
+:1064700014F09D5EE5B344C3A72871D48F9569E1FC
+:106480000BA0CB15736676EC45B9359119E4580C21
+:10649000F9A128F85D32971F8FAD99C1CBAF647217
+:1064A000EAA4055908E35B53E755EDB7A22828672E
+:1064B000E4EF4D2B094A08CF802AE65755A22BA2BC
+:1064C000AFB4D92CA4F178CD9154A08FC182BA0673
+:1064D000235DE0FEB3D418171A5865A48BB4126379
+:1064E0001CA83FD2057CD7DF442FE67E06A87E8A13
+:1064F000C765042D3C5E34CB18D749635D1F3E81D0
+:10650000F01D72FBC3384E9D715C73FF0A0B5CA0DB
+:10651000801CD9F3F3896002C3AE1C9C9C8478D99B
+:10652000EC288E27B982C1AB187E971EF4AAEB1D0A
+:10653000BDB48FC8D1A0C1BF662E1B86A6DC36179E
+:106540005AADF204188D1FCC20F96E15F1CA8319CB
+:106550003F75A05FA33E398FF213F6631DFD38EA45
+:10656000B0FED172DF8A7EA4A4487D85885799C782
+:106570002B54385DBECFB442C4C3687B3015E9D913
+:10658000AEA6E4231CF654D0BB627C374E71717BFF
+:10659000CFA77C698CABB97DEF8BE029F16172E20A
+:1065A00079E1235F09FC10C70F4E067302E93F91A2
+:1065B000856A717DAB1AF93E17697713D231B40B36
+:1065C00062FCBFBB5D00DA8D34B4BB45F4A719DAB9
+:1065D00015F7685722FA638671B51EE32E16ED484B
+:1065E000AFEB6EE7EFD1DF12312EE983DDEDD41E84
+:1065F000FDDDA1C36768E7EBD16E990E9F615C6614
+:106600001CB7FBFD705BA896F4CB62F2C71EE8577F
+:1066100048F472A85F6111C6C16F7BC1CA65C436F8
+:106620009EE7210BBADA2FDAD5B9395DD556B371A9
+:10663000E5201F1B44BE4AAD7BAE2310F55C5F3FD7
+:1066400078EE8BFD7C8983EC31F15C6970925F138D
+:106650009E933D56F777596C5A3F9B8C71CD0674CB
+:1066600054613D78758D960DFC9EA618EAABD2F963
+:10667000FBAFEBAEAE09A2A34F29A6F808D0E7F70F
+:1066800073A3F8B07BFC7F19FCDC7F1C81FF4735CE
+:106690009A120D3FAFEBF0EB75E720FE5EB6CE9E93
+:1066A0008CF35921F6F5CF946535E44FFE5F3BBF7F
+:1066B00045A6F55964581FBDAECFCF6A2DFD3F36B4
+:1066C000BF3B4CF3BBC334BF3B0CF3B35B974E0EE5
+:1066D000669FFFFCCCED565B8B49DEAEE8F7782A6F
+:1066E000C2B542F8A79D56AD6639C61DFA75EBDBFB
+:1066F00024DF4733ED6F2837FAFA6EA3A2927C7637
+:106700007A2C3C68D3CF161A9AC1E19A0172A1453E
+:10671000F171F92DE03C62AA7799EAF0CB97B86F56
+:10672000FA986E4F9AE47C1FFB5A7D06DF4F1A3CA5
+:106730009A44792E625FB3E9FBDAA099B48FAD4831
+:10674000CD23FB65FFA005248F56A60FEBCFF3F0FA
+:1067500052495ED9C55EF34035CF5BBB5FE407AD00
+:1067600048CFA376F7EBF19250BA61DF3CF0830596
+:106770004519201F4F1FE1F98AABADDC7EA8AF663B
+:106780001ACFC37350B90FFA0D408356D0F7B07CBF
+:106790000EF43D2C5BAA53A97CB65AA572278C8BAC
+:1067A000E5AFAAFD5436558FA352D7171F14FAE24E
+:1067B000F7D22DB47F3E56CDC62BD0FFA66A0795E3
+:1067C0008F56FBC62B40970F57A752795A9A31CE56
+:1067D0004AFED38EDA7858AF3DAF6653BED2C4744A
+:1067E00085FC1E4C09CBF10591E73A5E4F4B932F88
+:1067F000B502DE2F512DBC9D2354EB8DDD6E32F69C
+:106800003F4E55081EE60ECADEE498EDAEC0766334
+:106810009339DCCC17A8F5C4EE6F1A8E9B972CE049
+:106820004B566BDDB1FB9B8EED2E4A15F0A5761D08
+:10683000888BDD6E268E3B3255C097DE3E392EF6B4
+:10684000B83FC2FEFA2736521CE932B477A03F7B2C
+:10685000BABA897C16A2DDE64155CC0274DB3FA9A9
+:10686000B10ADB5D5A55CC32A1CC4C296616A07F0B
+:106870007B32BC077852453F13E6F1F79BF1BD2709
+:10688000EABDF87E7C09BC877A667FE37B7D3C7B32
+:1068900023D3E54998813CB0AF61DD793D584FB1D4
+:1068A000F0FA9DD60393296E69E3ED1FC13AF463B4
+:1068B000AF337E9FE2E2F57BF4F65EFEFDD3A27D70
+:1068C000FF443E6FE78D8E10C6C51EFDF79FA6CD17
+:1068D000CD8DCC77C8CF975E38376A7E8FFE7C35FA
+:1068E000BDD7E733A47A0DBDEF8D5F53675B981674
+:1068F00025B7521A73499F1C6DAF22B9337AC8CCA1
+:10690000F01C58176B31876BDF8A553535D9045722
+:1069100090F205045C0FFFC408D7A09F1AE17AF833
+:10692000A746B806DD716EB8565BB95CEB0D3E1834
+:106930005F8B1E3FB4DC38BE5A631C3F54631C5F40
+:10694000ADFDD6E387A3D7E5917F338E3FF867C6C9
+:10695000F11FF99971FCC1777EBBF1FF59FAB8D7E5
+:106960001AF80FABD0C7E568BDB32A68D03BA15D6C
+:10697000BB681794A3F5D840D0A0C742BBD7443B0F
+:10698000CDD0AEB847BBB7443B661857EB31EE5F8E
+:1069900074F82CD1FDF97BF4F757ABB0172CD1FD6F
+:1069A000A93DFAFB5087CFD0CED7A3DD29D11F3325
+:1069B0008CCB8CE3C24F0EE6F3DCC15C7EF4F72E89
+:1069C0009DDA40F1AFFE2C20A1DFCF97C4461FC255
+:1069D0007D398BE7DD27142E1D82FB784382D1DFC2
+:1069E000D5CFC6F729C52653BFBE38564579878E01
+:1069F00060DAF4A87C8B32D1AEFBBD3B98765DD4D7
+:106A0000FB14F17D83885727AD1C538B72C537105B
+:106A1000DAC7A0B7541BB70BF5F72CD9DFAE01BC12
+:106A20001B7E3C63CC6A163DAE95B71B22C64D8FCC
+:106A30000D5743061FB714C7CDC5E7BA7E114C23C7
+:106A4000BCF978A93F5FEFF9A9F457C04BFD548713
+:106A5000458E87F76BB89F53F7B727D8AA1C98B70E
+:106A60005B3BC8C236AB94877C4E3F4E5DB5D1EFE1
+:106A7000A9F88A35B4F70694F8F264D6FB770F15B7
+:106A8000598A62C51D0AC4BCEA4A263766C3F8ECB7
+:106A900090D17F0B84CDA2F36186CB81025B2CFF6A
+:106AA0006D1DF79FEA7A50C28073FB6F6B857ED1B4
+:106AB0003D0FE828D6FACD12F0B10D1C6F8A8EB7C3
+:106AC000C41964DF25D45CE9F0C5F86E95A97F2769
+:106AD0009BA161BBB8E446662179C2CF4DE87A55E7
+:106AE0009D6F33DF87D280A6300E94BC338CFC734D
+:106AF000A6809FA35052434189EC513E4F542BF145
+:106B0000274E0907D1DF386083C2C220B7D65A02A8
+:106B1000B36C185FC96E24FF98E2D324C4D3596BB9
+:106B2000E84A3A5700EAE266A927BCB7D8B83FF866
+:106B30002175C61F3262AC63894D35C4B7077C61CD
+:106B400063E1FCDEDB47DA71B8BAE93415E8732497
+:106B5000C90DA2D34A592BB7119FA7FBC8EFA8CBE9
+:106B6000579DFF459C7BEE38267ED41BFE04F358D0
+:106B7000D46665C83FEC2B681D15FF5924FC5F7374
+:106B8000855F751E2BF6E2CB93CC52847C7592BD4B
+:106B9000EACD8F5AAF069B8DC3D56025FF961ED7D1
+:106BA0009DDF6835F8BB166E30D617B019292897C7
+:106BB00016ACB3B210E07391C91FB614E70BF02FF7
+:106BC00064552B7DDCAE207D7AAE8F2949B0752CC3
+:106BD000FEF5C363E740FD17887718FF23A017353C
+:106BE0008AAF4ADD211BE647BDB73B7FE60486DF5F
+:106BF00087560E40799AC0629E2FBAA5C1085F5F82
+:106C0000F09BE165ACE69C7028DBA498FEAB877531
+:106C1000FE10EBB5D4E11DC540CE9C75F2B2DB9FF2
+:106C2000F26727C9F7BD4847B4DE5517F1FDA0EA62
+:106C3000622CFBFAEE80A03FF3778B1D1D36E48FAC
+:106C40004AA5AA48B244E24D766B401B08DF595B67
+:106C50002685073243BB86F36CD726659E57BB2239
+:106C6000CB39FA3B25E4E5F33B1EB3A15D76F2C9CF
+:106C700063D7201F96FD56660E68776A878785C999
+:106C80002E09D9509E94EE9663C667290300F056EC
+:106C9000F62B0FC989D29DF6D034F8BEF4D9F74649
+:106CA00031C0C3A99AAEC303711F7D52E271D26095
+:106CB000C728DCB74A157673718CFE3A04DD9DF85F
+:106CC0004D1CE5B548DBF6DF44FD36DF60B547C94E
+:106CD0008737705FE2EDB87F6DBB141A1A437EE808
+:106CE00071AD13DB250E5F8B35E444F8B66DB2054C
+:106CF000008ECA6D9F101D4DF9559317F150D92282
+:106D00001BFCBE95DBE4B07D1495C7B0C478890444
+:106D10007C5DC1B87CACD8BD98FCE115CD777D22F7
+:106D20007BF17B233D035EFC61C4EB1BB27F1AD673
+:106D3000773DE15501551FB56FF5225EA1DF39B6EC
+:106D4000788CEB1AFDD8D8FF17893DFB03CBDD8685
+:106D5000F455D9BC8A8F67E2978FF097B49EF113F0
+:106D6000BBDD934C7AA21E3FD996745E7A6259D3EA
+:106D700099478230DE899D1F3F1204B8CBFFFFA7E1
+:106D80008FDC897ACD3EA70FF9BDF2C9D7BC2C6A3A
+:106D90001FCCB073BE3BB5FD89C71F023E39F5A6B7
+:106DA0009DF2F24EEDFD6030E6D39E7AE6BF52547E
+:106DB000687FFBDECBC99EBF7DCF94FEE7DA0F91E3
+:106DC0004E43F668B842D4BFDA22A1B20586BC2889
+:106DD0004DEB7270B7CC9C00E7C9A3F610E63557AF
+:106DE000C2B3A579B84E8B49FE627D19E0B7624700
+:106DF000FD27F2A858780E0EB4A46209EC928AEB33
+:106E00007CDDB597166069F5AB4817AC8BE4A7F944
+:106E1000BBCA23B09E17F5BE7E67D85736CC3FA9B4
+:106E2000DCB18A8F6B5ABF93F8CBF89EEB7799DD74
+:106E300018FF3AC3CA1F7D085FEE4E8A19D7D5E303
+:106E40005F8BF7FCE09C7A932E07FAC26F89C4E14E
+:106E500072DBB56BEDC84F3B9F7AFCA164BEBED31D
+:106E60000021A79ACE0C66401FC7AD5D37A17CEC10
+:106E7000DA6BF7E17E5EBAF70DE2AF537B5EB1A944
+:106E8000241F995B023DE114EBFE6947BDA142E27C
+:106E900095CA2D9EB0DD1B59A78AD0F422D54BCFC1
+:106EA0008FD1F310A7FB8AD0FEEBA518EBB6D29ECC
+:106EB000C9E571A81FE165F1963FD9288E1DB59EE1
+:106EC000D2385CC76385F8BCB775D4E7EFC3F95F08
+:106ED0001CB59E5B38BFF6C697A736D915CC4BD0EC
+:106EE000D7F794C8BFAD0C496FB018FCAAEF6FDF9D
+:106EF000341EBADC440FFA7CFBE2E7BEE7F1CDF0CA
+:106F0000742B26578EE989AF135FC596EF1B857CDE
+:106F1000A860554503B27AEE4F0A188C033322F06D
+:106F20009EC05800D0D98927653A2FBBB2F920C935
+:106F300069B35CA8E8454F6EB2733BA7A265FF2812
+:106F4000945F270EFC86E8B062C7311BDA4787B72B
+:106F5000EDB275E446E81EE57F741EE689A7F78F5B
+:106F600022398DFDC7589FE744FF95ADC6FE2B77AC
+:106F70007C62E8BF2CD86C23BF681FE37CA4683711
+:106F8000E07C3F6AB732CCBBFFA8592E8AA5DF3C14
+:106F90006AB71AF3613C638FA25F514EB4A928EF20
+:106FA000EA966B6F04715F7CC5CACF3D2ADA51CC7B
+:106FB0000BA84DB0A968AFD6796632354A6E379ABC
+:106FC000F0E94BF64DC2B89A6F6A7141B4FDA4C3A3
+:106FD0009FA0590CF0DFEE29EA8FE79FD00E53F106
+:106FE0009CB1E227BFB2EC2D2CC2F9C83E8BCF1961
+:106FF000737FE6FD59DDC56437597D96EE5C13EC71
+:1070000077F4949923D075A630D5A0E7AF9DCAE355
+:10701000B8FAFCD70E621B19C8DDB552571BE6B390
+:1070200007AFE4F9814CD8E95EB4D3337AEA734C04
+:10703000D354943F247E787BA6459D0FB903C0B1FD
+:10704000601E8FC54FCAFC1DB246793D361C370BFA
+:10705000EDA7103D8F6361AA5B1C5CFE7858153D5F
+:107060008F671D8DD9D0F9DBF6E2B32837EF2D4AB3
+:107070009438DC61CADB4810E358E2D2D3CEC5FFB6
+:107080006CAA7222DAEF63671BC92E41B7E3D749B6
+:10709000113CE879717ABF6B9D1325DC6F707E031C
+:1070A000F15C8F3837EFEB9EAF46F57E7ADD340E1C
+:1070B000B6F48D155B2CB162405264BC2DA091FCDE
+:1070C0001C03583395E9AC9DCA44874F5208BEB79C
+:1070D000C92F6561EFB2AFE34CF09D873E7ED6A22B
+:1070E000BD1980B2D62A9EBFE3096D85FABA04663F
+:1070F000381F9CE9E0F264ACC3A2E72707A2EDAE1B
+:107100005A564E737726F3632CFA773F7004863B0A
+:10711000A2E219B2BB9DE77F09FB57B7D72F97971C
+:10712000F1F87B2AB7AB7B5B9F15D5C506BBDA5C54
+:1071300036F673CCD9C4087EEEA7921CFCFCB2C60E
+:10714000545F34FD61AECDD8E8BC464D23FB5EBC38
+:10715000B7C2F4F0A51DF128F7A4BF62A4BF7E4812
+:107160007F1DA2932EF25354CA81229C6F6A76959A
+:10717000C49F0724EECFD2649C6F8AE8DF12579E2B
+:1071800076AEBC2A360BE8232AAF659DB01F158565
+:1071900029AE3C8467A35877335D1AF354757DCDCF
+:1071A0002D6A76912FF7BB8257E93C8A92ECA6FCB8
+:1071B000147741DDAD789E5C61553E949F6E3DFF36
+:1071C000C4CFF30A75BBD89963CCE7B49BF257AD33
+:1071D000C2FEEE91CF2DF6DD7BF0410C7DD8BCEFE9
+:1071E00056394C7AB4F89E8D8B9D37A8EB61E74BEE
+:1071F000F7663BB2DCD17E9806F769946FA9087FE9
+:10720000C3A4EB7DE407EFDC21F1736B263AEADCE3
+:10721000193F0AE521F22FDE6F11279E4B3BF6EF57
+:1072200047BDA9CECBB484449273AA0C785F298D54
+:107230007648502EDEFDC9CBBF45FF7AABCC706BD4
+:10724000EE84B9B5E3FC142D01172B8EAD31ACEFF4
+:10725000379D4FCFB822E7B7253E9DDFDCF4FDE92F
+:107260001D129D9F92D98807F01C44659B9585E06F
+:10727000FD69C6FB3FBD91EB030B5F805160FD379D
+:1072800088F1715F8ADE3F928A5C4C8DCEE3096A99
+:10729000ED78FE7F9EC047BFE244C3FB8FE716B583
+:1072A000917F26B080F44F3C5716DD5F99BCEC020D
+:1072B0001C8F093F860AFF90FEF4F99FB5046C7C91
+:1072C0009F288E0F933E03F62FDA0D2189F295CC7D
+:1072D000FE8E8A1689F6A745B03FE1BD028B422695
+:1072E000FBD19447A7E3DB4C97071D421F7433770C
+:1072F0002F78F587797C94F86AC90B3C2F6C4993F9
+:1073000014A27CE68E0BE219E15926BFD107AC6AC4
+:107310003DEC1C11FA35E1CD9E6AC4B35335E23918
+:107320002EC788578FDF8847339EE3C7651ADA97E1
+:10733000C9E536223281E71CF88778063948F3A878
+:10734000807984D59EF82C695DBB12FD1B7DE2D14E
+:1073500084BF8F4DF83BC35AF7F3B720525388B51B
+:10736000797EA41226FE31F39B8EA7745FFB247AEC
+:10737000E6F790BF38557422CDE3DF0D703473E625
+:10738000C9F313BFE979C271DDFBE57BEC6B286FB4
+:107390009B7EE818C6D3CDFCB5114BE0EBE66A87BF
+:1073A0006F1E8CF77435F3CDB362BCDA47658C7D04
+:1073B00094FA077AA4FDE01E8C4B26235F2BA1CD07
+:1073C000DCE68A9B86E7FC5AAD3EF45BDE93D7751C
+:1073D0000DEAED95F3799EE38F5D7C5FBDD5C5FD2C
+:1073E000B08A8BE737AF2EB6300DEDFB563924A1AE
+:1073F000BFC8A7BD7019EA5DAD5695F6355FD7CB0E
+:107400003FA2F7F93E8CEFA6591A47231CD09EFCE9
+:10741000ED9DADEF796F89D2774EB5DC7721EE3BEC
+:107420000F5A58492C3D3EDBC9C73F95F36E0A926F
+:10743000E3624717D9D1F51D55C5382FDD8EB0ED64
+:10744000E6FEAD8A96E9A44F1E5AC0CF63EE39C15D
+:10745000CF6316CAB3BF3F12EAE35F53B8DC64DA06
+:10746000B43929D484D6711DE64B221FFCD512AA4B
+:1074700021FC34FE11E354B5FFA950BE6C4115BF89
+:107480001FE4B7DEC2362CC76ACDF9C8D7535B13E9
+:1074900026E17999CAB7795EE59876A33F87C9E571
+:1074A00007D10F76E628DF962F3EAA98ED2E19F722
+:1074B000E3F11DC6E713FAA0DBC94EB11F7959CA23
+:1074C00037C98BBDDBA25DE9E4712C3ACFE5576289
+:1074D000DB4F0FBBB87E057891504E7576317F0D2E
+:1074E000E0A973DE009A6FE767FCDC65E75772512D
+:1074F0002CFBE82627A797076D3C6EFBE002776818
+:1075000039FA4D17940E41BBE8F37F0B0C8915A790
+:1075100088D8072CDE427B9E16CFC6215FD4F1733C
+:1075200066AC312DD6F9799D1F74FED0F9226D819C
+:107530002B10CB7FF9AE93DB6F9317E44836A4D7BB
+:107540007D12C5784ED5005CE7C06390D50C4478B9
+:107550002A5B3E25FF82A335B61FFAE7785803E978
+:10756000B626B87C02E0EBA7C0D441E4075B6346D3
+:10757000ACFE836C1DF99BE663923B7EE7E07634BC
+:10758000531AD36678904FA65CB912E07C08F80FC6
+:1075900049FE41AB9FE00E2E668CFCAB0AE7FFF480
+:1075A0006BD8A6D551F6568373D23A5CEF754E1E52
+:1075B000EF480AF82584DBFFF7B35EECBFF30B3B23
+:1075C000ADDF00E1E7D1BFFB958E1F97760FD14B62
+:1075D000493209437FC0EB9B07FBFF452D80EF2815
+:1075E0007A8CAC5B90BE4B0C80EC2BC0F38C163AC3
+:1075F000BF82F616DA13954CFF0992F2A9F31F1E0B
+:1076000036C3735ABABC955AA5B007E46681C31D48
+:10761000467F4A6209CC1BE351CCC1FB6B37EAA31E
+:10762000287951EEA20CA07D5AD83BBA1CD6E5773A
+:107630005D029783756B15CAA7DCA87438D17F9C4F
+:10764000A1A99331B52A515129CF615009469C41D6
+:107650003E663D9CD0ADF74C60EC99BFCB31FD1B35
+:107660001F74E32BF02CE26B545BD701549FFC4E4C
+:107670009684EB5D28F49BF127B93CD2F3FB2B8574
+:10768000BD619647BF013A478131FE52BEEF8D3F43
+:10769000E9F623FD74CBA10585B48FE6B5E61FC4DA
+:1076A000FC9CBCB7393F32217FC07A23BC8C6D0B68
+:1076B000CA880FB3DCE94BDEE8F2C4BCCEA05C772D
+:1076C000D731752EBF0DF82C6AFF36CBA9374C7217
+:1076D000EA0C9BD8FF7235424F794BFD07ED51F410
+:1076E000A3CBA9083D85886ECDE348CCD15DF76575
+:1076F000A17C7951463F48E7241E9F0C221FA1BF61
+:10770000E2B3D09538FF75AD573891EE77B64D712D
+:10771000205B2D49E5E7BD94FDD70799209FE8B888
+:10772000AE953954770EE2C542F8907D508F9AD7C6
+:10773000E946499C7754E3AF8F713F825E2E49E55D
+:10774000E7B976B665C6733B334CEBDE4DF7C20F37
+:10775000A1F3854EEF66FAD6F9A19671BF84AE3FCC
+:10776000C852B3B00B8D7E815ADDCF1174529CF894
+:1077700076A10FD6BA87DD85D7DBD48527FB302EDF
+:1077800071BB2793F2996FEFC7F166C6835E567E91
+:1077900001FA6154DE79A5D2457EADCA2F6C86E729
+:1077A0003A5E7BC3878ED74B10AFD23F8ED7B36282
+:1077B0007DCDF8FD47E79DBE645CCC7373FF57E653
+:1077C0003D81057EDB4176173FB7A1D3972E2FC6AB
+:1077D000DEB6218D88A3DD78AE479723E35AAA0E43
+:1077E000A28A68961317B5B2EB104FE3C30A1DB116
+:1077F000ED4B6E7C86BFA4D1F98B592E8073F4F3C8
+:10780000B3CA76C0A3512A4B9A06408D6A57488E58
+:10781000B1F6F38B4335873F4B41FFA2AE979ADB1E
+:10782000E97AA9BEBFE871A0D5AEC0421C5F6A016B
+:10783000BE81F9D7FAB8BDDBE00C94E2F33880D909
+:1078400085B97639E10C6E9F1AF9B2373E8C33F167
+:107850005933E085CE21C03E3754EA09873E7E96F3
+:107860002B81C309D486FA4BFA58C607ABE0F7D987
+:10787000A58F6201DC87F1F826CEB3C1C5F7935519
+:10788000420FD3CB0667F17284DFAAB0A03DEF1F91
+:10789000875BF70BAE7669D52E18C751A4D13C068D
+:1078A000FA981FF5FA814AB3E4073812CB55A9DBE1
+:1078B00059A3EFDF78EE679A3A89CE9765333A1786
+:1078C0003B10F5A018EBF34B17F7572F76741CC637
+:1078D0009079E5B4AA22EF39E2D391FB06FCC24FBE
+:1078E00065CCC3E8DCFBC6208C4BBEF3EF9F7A303F
+:1078F000EEF417A5CB83701E5FF6470F9E377867AF
+:1079000019B7336E32E9333B053E7D71C5DB117F1C
+:107910003757FF7DACE1FCF8521E47591492D1E86D
+:10792000ECA6EFB26D71E49BD3EB8B9B930C759D32
+:107930004E17DB799E9479FEC785FDB468C726DBB8
+:107940004015C70FFC16C73F2EF4B5E3BB3DE4CF8F
+:10795000D0E199BB63B40DF1F09756BB88C3B75B18
+:1079600039FEB569183F0B88A530C379785F1CF5DF
+:1079700037FF7E99F48B3930D652A0EF40EB22B21C
+:10798000B3CDF398FF8E5AD81FD66FFE2A89F452D2
+:107990006CBF0CE821B0B49EE26CE679CE099AE3A4
+:1079A00099CBC84E37E779CC63EA5D133362E47B49
+:1079B000B4F238F9C23EEC9A775C425F18CB2EC61F
+:1079C0007CF4332CF717B96ADF76CDF16A46495A51
+:1079D0001F553BA83C51EDA372BB4BE5F1EC96FD66
+:1079E0008789BE94F6B1C8EF3BDBDE8BBB518DC8F7
+:1079F000EDEF6DFAF4E02FA19ECFB8FF46F78FCFE1
+:107A000016F8BE4CC8EF85421FC8FFE2DCF27B3699
+:107A1000CE77544F7875B93D1BEF938DC2832EC737
+:107A2000CDF838DD9615477EC638731CF8DBE1A526
+:107A3000B7EF16CBB1F30675FED92EE879DE96E9DD
+:107A40002B07C0F8B57B3F18CCEF036647503EE8E4
+:107A5000F469A63FC6AA6CC8CFDD74D67A37E14771
+:107A6000A70BE0A354117F4C45BBCF4C6F7DE513B2
+:107A70009DB2760C463960A6AF53128B79AF68621F
+:107A80001CF797CF53B542B443617B59C9E3745C8B
+:107A9000FE1C571A0FDF89FCB985F3C7E25F373D3B
+:107AA0008B72A7F457F77B51EE7CA834A6E078E5FB
+:107AB0005B577831CE7D5C097AF1FB0F4372CCBC09
+:107AC000C2057192906BC67C05D610BC06F9F6F320
+:107AD000AD561FFA192AB7D9791C7C37C71BD47940
+:107AE000FC7B77EC7C85D227EE4F51797EAA316FF3
+:107AF000618B95F24FD05F86C3F416C7ED8E0B37BE
+:107B00009F3BBE5DB9FBAE9879277A7E80996E6700
+:107B10009AE815F042764C10E021B7B8885BD76E32
+:107B20007F60D43180EBC496FFF04AB9D17E731EDA
+:107B30001F3FDD7CCBA318E2E98D5E4F09FA8EE88A
+:107B40000DA198790CE5D6B017EDF0F24D56B2EBD9
+:107B5000CA9B64E6C07C9637EDB46F9735FDEEF5B1
+:107B60004B00BEB267ACC9D3F834285F415FA7EEC3
+:107B70003C12B12EA5BB7EC7E3BDAAC82711EB53AB
+:107B8000F6CC7E1BE6C598F138A579BFADC3948FBE
+:107B900040EBD47CAC90CEE56D3F6BC3FDF4C37D70
+:107BA00012EB9FD1F3FB924DBFF3A27C403C515CA2
+:107BB0005EAC57EFF942E16B9E2BA076E487EB6D4C
+:107BC000FD2EC6351A43F4FDF473307EC95B76CAC8
+:107BD000572A79FA36CAEFF940A9E274FEF08A14FE
+:107BE000DC5F4BACC1141F95FC79C9233F21FA5BC4
+:107BF000F8CA4F52F8791E2D8DFB6D8269E4CFD8FB
+:107C0000F8039ADF021620FA2B79582E467FC919FD
+:107C100085153D13834FFE2CF8E483CD760CA2B27C
+:107C20000F84DF32F8AA2CEEFD35C793F8BD2B6721
+:107C3000841DBD2BCEA2E7693BA2EDAACA2DF5EDAE
+:107C4000B83E1F0DD2FAFB28AEAF0405BE24D2C742
+:107C50005FB9BCBF9063745F8CAEE74CC1E7D8BE20
+:107C6000DD4AF7C6447D67B8F7E576313EC0ED9250
+:107C70002E823225B63FD3ED9674F878FE8B4E5F98
+:107C8000BDF1FD169E4FF2D9112E57302F86DEB76B
+:107C90005BC3FD0DF93076C3BD22917C0FABE06B69
+:107CA000E37B8093F255BAF1BB4FA238EB82757635
+:107CB000631E5C37DD98EFBB31E6AF2C34E95B7AAD
+:107CC00069960B6FC699E2681BCF2F7FA5DC1AA2BD
+:107CD000BCA3F237ED643F9437598B111F1FEF3867
+:107CE000F8FA8D40E71F37EB7C6B94AF66BE2DD959
+:107CF0003986C5E2DB8FDD7E16936FE1794CBE7568
+:107D000047E2112AFBEEE4EBC25EE4ABC5DD431FA4
+:107D100088C7BCDC8F9E2C1B427E06135E75B96A39
+:107D200096971BE3D45EF2EAF87E1EC977E4F8D397
+:107D3000E9B1F4A9C5344E37DDEA74A9D36D2F79C2
+:107D40005A663C9ADFB7097964F6670427B31CBC0E
+:107D50005FAFD6C672D0FF1CB4B8FC5B3362E4756B
+:107D6000B0AA0B50CFA87167C4CCCFF5BB7D68C655
+:107D7000326BB22AC78A77FBA75862EAF1F96E71B3
+:107D80003F09D202EA936E8EB73A115F014B90F22F
+:107D9000FEE98C36C297E0257EB2C27346E72AFD23
+:107DA000746EDB1F67F9540515ECDA35430A15F4D8
+:107DB000A7E65B6ECB82FA823579850AACB37F8207
+:107DC000655726D44BD6E4F3FA45967C2B90E6E330
+:107DD000C182C2A9D0BE429FE7BC78837F43B11C59
+:107DE0005B8F7117E5392BAB85FA5DC0D78EBC4828
+:107DF000BC37CECE824EA8C7D9A084FACA8C3FAE7B
+:107E00004423F03E7BE06A37C9A3C92AE2F584CF58
+:107E100041F932B7FFE672CACF2C7373BFF1885DA8
+:107E200013E8FEDDEF60FC1FBBC7F43E7E9D95F7B7
+:107E30007362E7882988D71143F8555F3AFEF31437
+:107E4000959E3B9BF1E829F17F2A9EFFA84DB051FA
+:107E50003F65DDEB757E65ADC86B90E3381DC8F1FD
+:107E600096AA67A05C22D6FF36810FFC417BB973CE
+:107E70006FFFCDFCDEA7AEC1B8BEB27CFACFA8378B
+:107E800076FD38CE8FE757DE72717CDD10BFC63AC3
+:107E90001CEA798EC1B72151BF25EDF80996D77834
+:107EA00002FFCEF1CFC2D8DF8D37C9BC3F7795072F
+:107EB000EF519334AE474B4034B3010FB51A536DB5
+:107EC00059C8A2C67C0B59CEEB0AD3B81EC3B82C36
+:107ED0001DF64158A71BC6F375029CD2BEF8C638E2
+:107EE0005E9F15CAACED50098EBB118ED1F6D02025
+:107EF000B47F6E04B588D3B5D1FED6E3F495FF699F
+:107F0000213BB352526BDD50DFF53623B97CCAE515
+:107F100015F907FC7E19DD2F31FEA5B95370C90A8A
+:107F20005ACA781E87F043E971F433AC55C6C9F4D8
+:107F3000F0539BE4E104B686E4645FF1B1C7DD620F
+:107F40009F19C0067CC3F85893FB3CE263E96E5D61
+:107F50009F17F176B1FF9F7E3193F285140573F27E
+:107F600018B3A932A588E8DFED36C95F9D8E471E9C
+:107F7000F1DD8278197984DDCCEDA55EF2238E33B4
+:107F8000CA6B1EDD9143F91156737EC4510B253C1B
+:107F90008D7D215F457CD689B8F1378DDBEB71FF94
+:107FA0007CFEA8471CFF396F11C541F37DB1E3F892
+:107FB00097C8B329EEC05EE4EBA7C7F1999C2B23C9
+:107FC0009C67C28C25219C478CF7C55C9C1C94291E
+:107FD000ADE66DE3F34BCCE7594CEBFD57F37A9FDD
+:107FE0006F1EC487FC7EB5D16C14E54158451EC494
+:107FF000B32C705F741E848EC7BEF24CCC7925E61C
+:108000003C92B480114F034B861BDE0FAACA33D4B7
+:10801000872CBDC4D03E0336C2E87A56C35586F6D7
+:10802000431B6718EA176CB8D1D0FEC2D05CC3FB03
+:1080300011DB4ACFB9EE239B9718DECB96503EDE7C
+:108040000BA9AFFB452D3F8B4917FABAEB795A982C
+:108050006E84F81D03EBFE5006F98FA6486ACFF533
+:10806000F78783B42F7FD3F5CFF6087DE81BF2BBEB
+:108070001F898DF25AB99ED8697537A05E9C00B0F1
+:10808000A1BC35EB1709ADCFFF17FEDD899EF916B0
+:10809000EA72A4A33B646D3CEEF7FD447E649D450B
+:1080A0009C279DEC207DE01E8BE5E6E87B922FF57A
+:1080B000707BE0520FDF5F7E09FB26EE9303E358EF
+:1080C00090F64F0B8BDC6701F3F52631716FF1A64B
+:1080D0009553D3319ED991A326007F637D5044EE02
+:1080E000DF68576B311E305AE6721CE4FB959E7EAA
+:1080F000B8EF2CB372FD2768453C0F74B0A0378FE2
+:10810000F63D8A6B26B06469492E9A5EDDFB8BFAD8
+:108110003510C3C1D211F16807BD8C906090D6E1D3
+:10812000A2FDFF87BADC2BB990E4DE69B79E37A6C3
+:10813000D279C7D3F3B2E8F99B3701D701FFBC6905
+:1081400033DA457DF9A74A36DDE741FFFF9B39CC9D
+:1081500090675026F056861762E2B993D07FA6202A
+:108160005A3AE7FF6D18025D29B5AF44115DBFE1D2
+:10817000D662CADBDD3D3D88FE3FDDEFACF753D96B
+:108180003A8975DF230CFDDDF006F77FDDF037A3BC
+:108190003FF7671E7EEEE86762BC9950F8006F33C8
+:1081A000613D12B07C7E6221F2033C0F4B50BFB6A2
+:1081B0000D543FA0FBE9810C2BC2F347E67F6D0F06
+:1081C000C0B3C2A3D238D7B3622BC2F5FA4D8B3DF0
+:1081D000D8AEBB3FBD9F8178A613F6E984A03505D4
+:1081E000E8A7EB5289F67518CF81CF8B670F5C81BA
+:1081F0005B873EDEEB2C70F23558EF19CC4FFDEA71
+:10820000FD33E632C8C19D25657F49CA44F967211F
+:10821000FFC792BD76927F9DA5679BD6C3FB9B0748
+:10822000760C42FDE2ADD2BF0D43BCFC7083CC5452
+:1082300058FF475D81B59E28BCBD39EF530FBE077F
+:108240003D61EB7ADCE49FB2D339AFB74A9F1A168F
+:10825000AD57FFD233693DD21D1B777EF19E294F6A
+:108260005E48F6B64E5F8B047D2DD97E01E9834BC7
+:108270003CDDF4C5EB5BB3E83CD15889C5B423F1D0
+:10828000DE0FCC4BDF097485E708F77DC1F3C777B4
+:10829000BD98984FE751596047F4BC76BD7CE30820
+:1082A000F2B71E4D3E2F78912783A85F310EE74B22
+:1082B000823F66B526E50BFDAE05FBBFF1B7DB4F90
+:1082C000FE09F1B3F7A9AD77629B82F3C30713FBF5
+:1082D000985FE001F631B27F3A99CB6F8F61FF3C36
+:1082E00023F4AF3B2C1AD925672DC5227F9DDB21B6
+:1082F000B2C59F8A79DCCDAD721CE2CD8B068B2E88
+:108300005F4027F4E23D8CE2FE7C07D8672384FCC3
+:10831000F9C3DD9F16D671FF8E41AF2B38546AD05A
+:10832000E78AE11FCAFB8B37066AF14EEE5EF5BAAB
+:10833000B085ECE17F54BF7BF71F94F7273D9CFF8E
+:108340009B73B8FC6E0EBB42DC6E60F9A8EF35790A
+:10835000F97E7025E68900FE6DD2A91C07FCFEC9D6
+:10836000DD6756364C84E5CEE6F8C03AFDFD95361D
+:108370004EA7DDFADFA1E1FCEFCB8973C005E25C1B
+:10838000B4199E02E02BBEC9BA0CFA63F8F09774D8
+:10839000CEA52951FDC304D4E7414F41BE772A1D24
+:1083A000B68418F37B16E527D0F7382FDF3F1C2D56
+:1083B0003C0EE75035BAF7CCE9F38D467B496FFFA9
+:1083C000B187EBAD8B0FBF35D806EB74D2F2A21795
+:1083D000E308E57B767AD14C1E1517F07A51AEBED4
+:1083E000F9EA581FE55B6D1A8C766D7398C72746BE
+:1083F0002A2CA8C4B8B7B972433E5DFE5DB121898D
+:10840000CA0BD19F008F2AC37C9EA75A6A63DEDB0A
+:1084100059F9FFF60EC0757BAA1F3F2F35B2357F85
+:1084200021CA3F84C50A72EEC92F46507F43BDDC86
+:108430009E87F1157CCE58C882F71D3D25ECB553BB
+:108440005FC8D44EEF7764CB24D9076B991B6E3C81
+:1084500040F661AB5DC575766EE1F7C1395B9D2471
+:10846000F72AF75DC1EDB8041EF76C7275FD599CD3
+:108470006353314FD2E96B6489D07F938DEF8F17AF
+:108480000203EC74479EEBE3395B1FA0A4764736EA
+:10849000BF57CFA934B24BDDD178F710FC8582BE2F
+:1084A0009A5C610BE6ED74E15D950457044E46E37A
+:1084B000EA705E48FA7C93ADEB7D3C7F49E7EB5474
+:1084C0008483C3C95A2F5051AF70FA78FCD6E95350
+:1084D000FD41A9275C95A340CF057EBBA78645FE3D
+:1084E0003E06E6B1B9227507F044532613F761E55D
+:1084F000D4A37ED15D4781342EF2FD8FBC23EAEBFD
+:1085000026929D1394D1AE87D29388F3E4FC85F72D
+:1085100017F4CBE378403F719C83BFEF6E0FF4EE0E
+:108520004EA47B8DA99D3FDE177795C4BAEF35D554
+:10853000FD4EB74BE1F72F43FF56F8C028156029D1
+:108540007FFE39A2DB324BEBFA912A9E4B0CCCF723
+:10855000C278BF7EDB827F53917DB4DD49E79073A3
+:108560007EB389FCD5E6FEEA8FD6DC8B79D99DBF38
+:108570009154CC03EDB47651DCA8A2F5033AAF7860
+:1085800045CB313AB765890F5462BFE35A964F41E4
+:10859000FC8D678DB5E8DF03794871FAE6542E3F0C
+:1085A0004E1F19B6797914BEEFF70ABBB02B300411
+:1085B000F9A655F0E73ED46FA0DC23F4AC3DFB7F79
+:1085C00098157D0E2BC80E903FAC861DA2FC42FD77
+:1085D000796748A17360235E77DCAC45D1DB2F045B
+:1085E000BFFFC2CBF5A0ECF8C00A84B76CFFBB3666
+:1085F000AF8A79ACCD8351EE36831E76AE7CC64A07
+:1086000013DF74E7B71CE7F772C3BAD6C5C33A3DA8
+:10861000F57ACB70FCBB22003FA3FBAADEB493DC4F
+:10862000DC93C1F96FF96B9F8F42B9F5F9DEB22186
+:1086300088AF3BBC3CEE0F743ED985FCF40C23396B
+:10864000A6F3632EF223809EEBE37E945CA473E496
+:108650003F5B3BDD03DAB587DF0B01744E740F74AB
+:10866000EE43FD22D707744FDF5F40FCDCD46EE1A0
+:10867000E7C0418E0FA5FA64CA57696A9FEA237E54
+:10868000B6006AF3902FC307A89F667EE76D81E965
+:108690003ED78F3149634C443EFE9787CBFFE61CA3
+:1086A000351E6D84385936F041D43EC9EB621F95B2
+:1086B000E26FAC5F878946ED625F107AD73EA1E733
+:1086C000B2A35CDEDF26F6B225BFBBE4DA1D30DFE5
+:1086D000252FC95CFE0B3A3920F4E043D5A954C7D5
+:1086E000FD4285751A0325DE773756AB9A82DBCFBC
+:1086F000B8A2C683585E52DC3C058F4C4D9CD57E9B
+:10870000909F61D34620FDED3E70E508CADF7DD322
+:10871000CE304571F7975D7F7E12F351F701FE630E
+:10872000EC4BE89F6514BF29267AEC8D6E3AA58E36
+:108730006B26F8613ADEF22B14D8E82B9030001F3C
+:10874000AF794BEB8300D00FE3B5A3488F77FA02E4
+:108750005476BEF2650ACAF43D47DEF5A2BCDF6D71
+:10876000D346209DEDCE047B20067DFE4ED04F41AA
+:108770002F79155F7A797EFAB020BB0BE9A762B733
+:108780004C7FBFE0E46E59C373D8EF6B8114D47390
+:108790008EB3E0CC09B8BF0BBB763E473B9B8F7ACC
+:1087A000CB28BA2FC3606732799985EE7B6F95C865
+:1087B0003F5162D243CA59E3CA81B86FB46EB2E185
+:1087C0003C4AB718BF2F47FD651496E7B657BFF46C
+:1087D0000AFD258B65A1FE02F443FE89AED764FF36
+:1087E0006646F93D6D98DFF39485E307E425F1A132
+:1087F000AEC73CE1D34EA05E7DC223F613618F76F7
+:10880000354994DF7FE1369E777DC9717513E3F3B7
+:10881000A7BCB01221072F5178FCE2922359140F04
+:108820001DA731F2872C68954288C7125DAF13E708
+:108830002960DB25BD6E3C0BD5E2FD720BB7497498
+:108840000EA36C9BD17F5FBEE195C3681E2E6E3672
+:108850009D8F177831C73776E22F31E21B83E3858E
+:108860003F67301B6C386FD5767EE7AD3E16E7AFBD
+:108870005F15FDEBED26C473BAA910F32D0FC921C6
+:10888000F1F729DD987F7B8BA08F5B047D54B2B01C
+:108890000DF3F717AFE3F3656BAC867B8B17ECBE7C
+:1088A00095CE2398E9A864078FBB010229BE53B275
+:1088B000D1F8BE54E0A3D4848F8A8064828BEBDB32
+:1088C0003DE16A9E89EBBB788795FE4E8719AE33F2
+:1088D0006C36E511FDB3E133AFD375FA3A0D67C3DA
+:1088E0000DEB5474EEFB0922F68D51FF7DE6F0701E
+:1088F000CA7739DD9649FE039D3ECCFD140AFDF989
+:108900008A0D5CCF3CD932256E24DA452F2A7E09A8
+:10891000FAC97FE9332F9EF7C8DB2B338C0B76B671
+:10892000E6DF85E7B477B5655F87F751E4BDA4D08E
+:10893000BE91FF521EDD0B92F7525E5C16E551A808
+:1089400049880FE887F6DDCE17B3FF988BF2B36D39
+:108950006A01A279F98B7971A81FEC62DC1F21BD35
+:108960005490D411B58F94C773FFC0CAD4F7EE41A9
+:10897000FDFD8A67F8DF1FBCC2DAF532E61FEC6A3C
+:1089800053FCCBA15EFED2DC1ABCA7A27CBBE447A1
+:1089900035FB70FB92E41F219DB55A7D7682F72747
+:1089A00007F07D708744F78557EEBD7C4413E67968
+:1089B0006FCAF7479FCBCE4B50EFC3BC4A961647C2
+:1089C000F6F71583ACB49F9E1810F718DDC7A26D9B
+:1089D0002A44397BE2B95D363A37D824B15498C875
+:1089E000E1D4834FD3FD1ECFBE42F90A5376BF4276
+:1089F000F909BDC9FB93219985C9EE6EA47B611667
+:108A00006FD2EB1D740EA258E84D155B8E51BD144C
+:108A1000F57F18AF74A31C52E1D7837B7F4DF90D0E
+:108A2000153B787E03BC27F9538AF1533542E7732F
+:108A300019A783B942FE94317ECF5059233F47A7EF
+:108A4000DF8BA4D3F9FC1D73280FAD47BE19DA974D
+:108A500014876824FAEE79DF10A7EF1EF72499E84F
+:108A6000FB573A7D5FC82E44FAFE7C12CF0FFBFC09
+:108A700015575C2ECCE7F31764CABB3F079DD37E26
+:108A8000FAA2D8FF4F872DB43FE9ED4EB57C4AFBE3
+:108A900048E58BA76DA8AF16B67E42EB30AD75FFEB
+:108AA00054C4F3D52C508E78BBBA35CE877C3EADFE
+:108AB00083CBADAB5AED21F4535FCD9AEB707D3B88
+:108AC000F73D519788F4F238A7175D9E2D14F85C96
+:108AD00028F0B950E1F73D95E6EE5F8F6ACA558CF4
+:108AE000CB9BAB9A85BCD968C46FA7B55921BA197D
+:108AF00029B1C68C9EFB5D19EBA0738F9D6923E89D
+:108B0000EF4906C15E453DAC7C87390ECEEDFA0AD1
+:108B1000D37E7A205EDC67F00DEFC178D7B42ED318
+:108B2000BAF87E7615D013C643DAC235B928F77481
+:108B3000FC98D7A54DCD8A3FD779E79785DEAED78C
+:108B4000AF15F74C34FB1ADDD176F8153EBE9F9475
+:108B50008E9783B8AEDDF64AF6C151AA2562AF8082
+:108B60009DF2657C3F6EB78C86AE9F4F97597272AF
+:108B7000C45EA94FBD6F5A5E32DE1FC1E5C5A97143
+:108B8000D01FE60B288CE454E50E7B08ED0C3C77F7
+:108B90008476C07F03EEF3D8290080000000000037
+:108BA0001F8B080000000000000B8D577F6C14D74E
+:108BB000119E77BBF7C33EFBBC87CD116AE2AECFF7
+:108BC000BF3018B3312636A449D62E6928B8CE193D
+:108BD0001A429BB45C4814D284B351845C242AB1F9
+:108BE000B6898A42AA466AFF88AA28DA448A94A8E3
+:108BF000343A84514C655BE7C424B6532408D0183A
+:108C0000D4B427FEA069656383149C5691E8376F3E
+:108C1000F7B833366ACE92E7DE7BF3E6CD7CF3CD50
+:108C2000BC778F0E5EF7A5EB886283E21182AC2CD5
+:108C30008AFBB4A5441D44DE9246C80161A40872B3
+:108C4000D3755FBC8068BCB2A2280EBD1BAABE4C07
+:108C5000C3F8167F1ECECAAEAF15A262A24E48BDA3
+:108C6000383BDFA9A67DACDF39284C1BB2FFC3FF20
+:108C700094951712CD0CCD953D0DD9A8798896F213
+:108C8000FC0F57AB3877F6929FA2E538D8322FD039
+:108C9000FD44CF91F3D9A3111D5882F1E80B6D5417
+:108CA0008F0971B8949A61D74B460AFB3A2F2A86EE
+:108CB000A563FE9497A889A8E7B33F8F2E2921BA10
+:108CC000F6BE30FCBAB3FF570D18EFB60F2F81FE7A
+:108CD000CDF7846141FDB97B881EC2FC9ED7BD578C
+:108CE000D201E7AC5BF27FF2CA41E8258E05F4576A
+:108CF00030EAA1DE52826E2F1D963241AF5E57429E
+:108D0000B037D0E7635CC8CED91F257AF1DDF9F61C
+:108D100012A466C788EFC0DF5A3A4673D61FD50A39
+:108D20004BAE06F1A5966A6F29EC7FFE5181F36781
+:108D3000C615CD2F246E6F7E27179F3180B19CE71B
+:108D4000F34C429C33E70AEC3CE8FDFB10D66A8802
+:108D5000A60EC1B81F769A158987678323570F7FA0
+:108D600010E57C32FEF135447F1CFE6095C9FE9310
+:108D70004DB49EFD86DECA1CBF93702AC74FF865AE
+:108D8000A4705ED75F1503E6D9AF6A5F49D6AF938B
+:108D90006A3A64E4F063EE90D9315A8574890F65BC
+:108DA000BE3C6254CADBBC39A5C4ECBAEC18F1EC89
+:108DB00032B1FF27CC0BF843EA6C24063F7FA6E9CB
+:108DC00092273D834E7E3D438EC4F93B8871C19806
+:108DD000CF5FB0DE6AEDE5F59BE541B218B7AFAD08
+:108DE000361E7747157A05E3EECF5EA8A19CF3897E
+:108DF000FD447EBBBCB311E66DD7398FF4AFEBDC1D
+:108E00008D4825C65BE8AD4D1AC65B297998D73FDA
+:108E10008E069F675E5B7CEEB2AC9D2F8B14C77F86
+:108E20008E17F62CFABD63D78DB797B6491C7A5DBD
+:108E30005EED2E72E23DA8C5BBB90E67CEFD37824E
+:108E4000B0E9E4852B21CE5726DF77D6DD6DBF71E3
+:108E500002E373B3453FFF2478D030AE5A4588F320
+:108E6000C4649EDDC6B80CEDF9C741CEDB653F7129
+:108E70003D740FEFA921B61B8FAF8DA10E6F0EFFB2
+:108E8000622DE340A257FA65B17FF06B7AE062444D
+:108E9000C77C62E86284D71327D7FFCE82FEBA333D
+:108EA0000D5B79FEC4982AF9D770A651F2EFC45F22
+:108EB0001A8B2BD87132826C3731AEC6189FC478AA
+:108EC000E3A76DD04B9C696D147CCC99C662EE3FD4
+:108ED000EB04C5925817E395729C89E7379A22E311
+:108EE0009919011F302F28EAF0872AE7F1676FFFF1
+:108EF000691FC7B1774031737994D9F796A64A3B79
+:108F0000EF307F806F4F5298921FC71DB977E08472
+:108F10008CEF456F52E6BBE798D759FF9323895EE4
+:108F200093FB2C5A62311E9FF214F2B0C567AF203A
+:108F3000B838514E3B938BF4C3AAB090FB262EC594
+:108F4000BFCB7C996889D768750BF52C6A95F19031
+:108F500070F1EEF76EB617B157E1DA0B15D3AED854
+:108F600022EB5AD8E1CF161FC517F3E78B4C3D1102
+:108F70001DF58017E7DBBC1AF39FC82C588E3EDB2B
+:108F8000EEF6D9ED3FF29ABEB55827ED741ED6DB4A
+:108F900033FDB619FD0C7D21863FEE6FB1D76345D9
+:108FA0002940DA61CEEF73DB28E6A50AD8D93C7FE9
+:108FB000FE71EE97F52C5569E76E7DF022F7C1D56D
+:108FC000F8524DD5DC074929080AF0E6AB31AFA6C7
+:108FD000487FED4AEE0777C697E9331FA3FFE9E81C
+:108FE0007F63E87F2C7B6A3FAF4F038F89914BEF04
+:108FF0008765FFCCA32813F01B5847DC09CD3DFB48
+:109000000E7B3DB7EBF3C7F3F896C9CF34D1E664D6
+:10901000DDC2FC5C77EFB34460CA07B25217ED3B88
+:10902000E2411CAB14877F7E6FDC2C451CDE8196F1
+:109030005429F7D35A7451C437FD88B0B9CFC3CF80
+:10904000327F4E9F9F5E2EE47AF70E615BF83A52B4
+:10905000FBB9BCB713A9B33EE65375FFD32FCBBA08
+:10906000B5E80245B2797C2CE0DC97B7F397899795
+:1090700017758E0F7C96FDB8444AD6E7FBB1DDBD6F
+:109080000F1F6B9E9FBF1A3AFB8352F8F184290C85
+:109090007BB1BCEFBCEFF452FAF6795F158E1787FF
+:1090A00081C7CCD91B3BD6C0DE44ED3FCBF81EEDCB
+:1090B000BC0B7FEF0D3BB8760543F55484EE52A30D
+:1090C000F7A581C7F1C2F80A69C7F34D6815F1FE2B
+:1090D000F49B2F09CE0749FDBBD54B855B2F15614E
+:1090E000CDA98B125AC7BC7A4F73C6135E7B05F7A6
+:1090F00003AAC36366C3FFEFBB3DA73EA9E7BC5C01
+:109100001B19AFF7E5E46FEA25D43DDF23431F4584
+:10911000F4825C7E795C7EA9520AB1CDBD1FE7F373
+:109120006D8AF9C6F93EFE51FB93CC93FEED2542C4
+:10913000CFB93F4F9E0F55E5D89D1E54A43EA9E9D7
+:10914000EAC70B73FD7C59FA399D74EC11A5ABB7D6
+:10915000AFC95DEF73799B96BCFDF5CA7D31AEE377
+:109160000C6F557278DB39D041F23E72E34EFAF063
+:10917000057E59C37EFB1DACCF7867CBC23975F134
+:10918000AC8B73534A483E6E204B61BB4DB0F81414
+:109190008F554AA9900F504ACE13AD20E6F1FD2E0F
+:1091A0008F9BD4D488A8977A960A5E6EA4B352EFA8
+:1091B000219A95D2243478C85632A46C0EA4B67283
+:1091C000FBA84B2615E6532AA286AF828FDC4A16EF
+:1091D000CB5F367E95AE66F809653C6E76C516E9BE
+:1091E000D7BF75EBDCE0B71AE7799AECB731F52019
+:1091F000A5153EE40195362B88E7419502F9F0F775
+:10920000F8A847D6EF705AB7B97F19C5EEBE7F618F
+:109210001FC64DA653A77CD53CD5908DF74E1C3666
+:10922000C25E11EBA974C42B714CC9F31E66C71141
+:10923000770BE92A8F7BC3E56E9F9FFD399FF3FD76
+:1092400041BF7CE7780296C4E3485897790B02CF78
+:1092500010EC6C7C4DD024CE352A9C7833F637E266
+:10926000D557D4C0FA42EA634C93980F069C7D44CC
+:109270009B34C64BA4229E5BC16F8FEB4C84A4DF52
+:10928000A16766AF1D94EF36BFF6365C32063F9994
+:1092900014784F0BD3A403EC4FA020C5EF6BB06341
+:1092A0002AF75DFD4678F71FC2F047E89AC48BE2C3
+:1092B000A4F33B6319BDA1F1BDE161BD6207BE2FFF
+:1092C00081DF136EBFBB9CEFF48D77ED6DBA07F9AC
+:1092D000D8591230381F0D81B27504BBED85716904
+:1092E000F7B23856258DA8F67AB69BE17990CC6610
+:1092F000C659B8F93A1070ECCDE539926B92F91C69
+:10930000443B0FC0AFA3A88B00C656AB936FEBEFE7
+:1093100079761FCE9BF3C424197FA91801C9F76879
+:109320007CB209526D35F57D05FC64471CC16C1C8F
+:109330007D7C0EEE637A160F449061BFE6C4D3576E
+:10934000E059C9BF97FA28DFC0E388F6173A3CDB3B
+:10935000FF459E4DE50BFD1BF1C74738BE398F31E8
+:109360003921EFD17D4DDCEF18A7EF6570F2647104
+:10937000DA6947FBD2BAC4658CFBEB7D7EFBDE1459
+:10938000F6FDD46F57B1FF193C90204952CDC53935
+:10939000838FC6F9631E9BC85F26FFD12C4E47F30F
+:1093A0001D7CF0F3CDC141471ED72C8C3FC3A3FFDA
+:1093B000010A95CE3EB00E00000000000000000043
+:1093C0001F8B080000000000000B7BC9C7C0F0A382
+:1093D0001E81BDD0F8E8B89917BF3CA9588601C1D5
+:1093E000CEE6626008E060600804E2DD40BC078809
+:1093F000A539191842803814882703F95380380793
+:109400008893816A1B981918B6B13130EC05E223B4
+:10941000407C9A8D74FB9F8A3330A4C920F85B800E
+:10942000EC4D72D4F5E3281EBC38C600953F4713B7
+:1094300095BF449B81E12E929AB99AA4992F68C84E
+:10944000C02004C4008B7A89656803000000000016
+:1094500000000000000000001F8B0800000000005A
+:10946000000BED7D0B7854D5B9E8DA7BF6EC994921
+:1094700066263B0FC2248664E70501031D6288400F
+:10948000D14E5244B4D48E685BF478740848781393
+:10949000F09556BCD9900709093058AC81224E107E
+:1094A00011156AA4F8AAB40E88163DB64D5B5BD1BF
+:1094B0005A1B11410139296A9D5AAD67FDFF5A3B7C
+:1094C000B3F7CE4CC0F6DC73BFFBDD1BBF8FE5DA14
+:1094D000EBFDAFFFBDFEB5462645442A20E40BF860
+:1094E000FB1A21B9222164423C254452FB9C901274
+:1094F000ED8B62539E7C613B9FFC67A3CC798D9082
+:1095000061907E9F906C426EE365F42F00F9A93C58
+:10951000A3CF474F895F26D1B2783F5309CBABA287
+:1095200040BE10E0ABB95C1FA7C1E91D47D208F9E6
+:10953000C4C552AD861655D2F42D57A4A9901097E4
+:10954000102A66EBACFF4A702CA61743DA24905918
+:109550003DEE04F320AB195C76E788A42A3E7F6BCE
+:109560003D3D6D6A24243A2A9EB749FE288C4FA6B9
+:1095700010FF8309DA4DA4EB40F8B88904F0903964
+:109580003CDE154213E1BB9D04A2365CAF9FC03C9C
+:109590000F78AA8E84B208E99C22FB1DF079530E45
+:1095A00081797975B8CE2AC0BC0C799590AFC33F4C
+:1095B000B8DE685B319D47AA5F246BE9A7A69C0AC9
+:1095C000271D93AC9FF4575F88A6A9520F512075B1
+:1095D00093404FF9E0790689C8F7F12E723E70B0DA
+:1095E000EE8F1DD680ED6947D9F1F96EB0D379D1F0
+:1095F000F568134402F0595739332D94601FF47401
+:109600000DC0972EBCA5D18969D3C49969A41C7AD1
+:10961000EA9F05705E3F295B5C2BC4E1A2C3E1C0F9
+:10962000A4179D7DB45E3BDF9F4EDF4127B46BE7FF
+:10963000FB6E85DB7A800F2DAF2102CEBB6558CA49
+:10964000AC4802B8D4102F96AF77D176B08E1C12EA
+:1096500079B010E6D3D73587E6BD13950A80B715E4
+:109660007FA60E93B0BEDB4D220EDCDF803B8796DB
+:10967000A71236BE3B8FF8A3743D2EB7DBAFD2BC2A
+:10968000345124511DE6F8EF72D33E7849BD835022
+:109690007A4D9D326F061947F36AFF1118DFF9A65C
+:1096A000C31F800AE532B657E87F5F14D1FDF8DBAF
+:1096B00087584EDE16FC0FC2FC767078296C7C67EA
+:1096C000896C1ACFFEF93541806F47F98A9455426B
+:1096D0007CFDB2719FE9BA6D96BC7DECCC6F15AB89
+:1096E000C9F7D3DEE725D18B6865DB0D43EE7BC37D
+:1096F0009BE32F3D54169FCF8F8827EB3800EB62FA
+:109700007231D2FF39DA7FD2E8BFF4901DD7291A1F
+:10971000F950B2FA6D1CCFF47C7B21C513C4B33E63
+:10972000DFD563E3DF5FE5F841B46AE46F12DFBFC2
+:10973000F64B48BF8DC2B769ACACAEA67090DC7278
+:109740005418C7C6ECAF02BAA67FF0BDBCB557F03F
+:1097500042E636137F6C29BE8A328EE4F393B2CC94
+:10976000FBF365E1F73CC0EFC238FCEC249816052A
+:10977000BC0DFA103E1E7D1E977C478DAA09E0782D
+:1097800031A53B3A9E3D2B42128DABF341BF10F801
+:1097900035F01F9BEC47BE4526CB09F9A05D109123
+:1097A0004FC5E1EC94101F09FFDB1F42B8C30C9DAD
+:1097B000D91C7E8097252FFE0DE027A9249AEAC5A3
+:1097C000EFCD5205A5039568A994FFCB129120FF18
+:1097D00029007B02964F9533804F4CF38780FEED36
+:1097E0007C3C65B6EF6A4F7C3E9FF27D8D97877C0F
+:1097F000DF3695DBD97C3D9C7F28734C7831D03E99
+:109800009DB5B7AEF723C2D6FB29A547863F737C2B
+:10981000410FF4434CEB6E516F08D6AA280F3E85DA
+:10982000FACD5F09F4CC017AE5F2C02A5793F263CE
+:109830008B3CB5FB0C79F84731E05311FC9BA7201A
+:109840007D11AB1CE76960C43F270F69CB4472767A
+:109850009C203039A565E1FA753A225C4FD0F79B20
+:10986000F27593FC90613E94EFB948043B4F25514B
+:10987000CC7B483DE63F9E581115683F0EA9AF0DC1
+:10988000F89783F251AD70F0F81BB83C49B68E0DD5
+:109890009724E6FFF9807C80DFEE7A1242BCBD415E
+:1098A00001BA12B410F902E88B84B9FCF5FB60BF71
+:1098B0005A1B1BC83BA584A41CBC8EA863611FEA6D
+:1098C000038172D04B6815CA824949254B25BF6A6E
+:1098D000C4C7817D24ABF87841A43B8A17970AD08E
+:1098E000BFD38C3703F85142896E12E6D560C2FEB1
+:1098F000F87EF27A49F16760FFF5F5A832E2AB0530
+:109900002F5C958A00A84DB3BD309FE17C36C343E0
+:10991000ADCBC571B02FDAF49174ADC3FB66CF0047
+:10992000D1E979F38AF7415E3597571CAEA1FB94D4
+:10993000E657AE9E4653570911009E6DD0592EF43E
+:10994000F7A2564DD7DB049DD1FCF5AB9E0D686E9A
+:10995000861E66BD5254251D5F8A86D44B842F1CFB
+:1099600083DB275BBFDD22D70859717E7AD00DAC2F
+:109970009D46FF03BA4AB7F4931630F3710F31E4F2
+:109980006979F380DEB4FC7F643C85AC76AA14056B
+:10999000EDAAA844E8D869444997286AB8A64A2499
+:1099A0004AF34A567F4054CFBD2FCD844C677C3C50
+:1099B0004C8C78BC99D3B9AFB6B9B095F6FB71A50C
+:1099C000DB0F743E9CB2C1CC8CC1EBE9B0C8E18E18
+:1099D000F2BB11EF9B88E62C02BDBE5C44FDA54D99
+:1099E000DDAB18E5D0B33A3F19841F4495AA9035F2
+:1099F000207ED85431E0F2FEEBF861D57BCE173FE4
+:109A0000526F30EFC797DDAFC3801F13CE1F3FFEED
+:109A1000D5F1F47D4DC6977CB5B7A25DB1266F68D0
+:109A20003D7EF0BEAE46FEE952492092A0DD2F05F4
+:109A3000C12C7F8C69B6515EDC62DA2FA960DA91A5
+:109A4000EE21E021A91639A8F3B1069B7A2C133A2E
+:109A50005050DE38797FEDEADD1AE8ED1FE7018628
+:109A60005079125E1E1540AF2961F61D742002BDAB
+:109A7000A88108DA212097E8BE38F8FCEC3EB31E36
+:109A80006F5352CC7ADC2C4D30CEDFD520E33C9C9A
+:109A9000301EEDD741ED0518D79647A22E6F1C5FFB
+:109AA000612866AFDF795E78A0E32B8095E1ABB9E2
+:109AB0005DABAF22A15E3768BC6BCDF34DCA97ACEE
+:109AC000EDDC927ADCA06F246F2791E306BDC50719
+:109AD000B2C5B0FFAD76F2B440F5BC26DF77349C5A
+:109AE00037FC9303FC89A03CB3E5D490900A7252F2
+:109AF00065EDD40C265F7709267B5BFF9E7C1E6C90
+:109B0000BCD8CD84F482DC9154D47F93D56F6AF4B1
+:109B10007D55A242C8DEF0C06489EE5FF3AAC0ACF6
+:109B200020ADBFB671D764F8AED7AB11454EBF5468
+:109B30006C56811EC3F196D07A4EFC4ABE00FB885B
+:109B40007266D580472ED233592AC3AF7CFF883046
+:109B50004007B4CB25225BAF833C8DF5A023A847FB
+:109B6000B938CBD386906FB10702414A776BA5888D
+:109B700073054D5B5C3CAFF27C3ACF2B3C5FC8F386
+:109B8000643BE6ED32CDD375A5D8230AE65378BE03
+:109B900090E733783E9DE78B785ED88EF91699F57D
+:109BA000D721F5B0FE53785EE5F90C9E5778BE8854
+:109BB000E7C95E36BE83E553ED3DACFF549E2FE40E
+:109BC000F94C9E4FE7F9629E17F6623E299F2C637F
+:109BD000F08FF305066F1D0F09C0D5E4E78A5AF22E
+:109BE0000C5F32058687B16FEA78E347FE48DCF9FF
+:109BF000486FC3B9BFA1E906E66F20DC3F62F87E7B
+:109C000058057E334BF40F455F8F707EBA8BEBB1F6
+:109C10003B1B15D4BB7734FA30DDDEA8E2F748638E
+:109C200019A6DB1AFDF87D6BE3444CB7340630ED22
+:109C30006A9C8EE9A6C620A61B1B6761FD0D8D21BF
+:109C4000CCAF6B9C8F6947633DA6ED549F85744DE7
+:109C5000A386694B631BA64D8D614C7F7843C54B32
+:109C6000A0D27EEC1651CE279BFF85BB44131F1E4E
+:109C70001D31F3C5515D19A67C6938D754BFB8AD05
+:109C8000C8545EA88D319517345498F223EA279B67
+:109C9000EA5F30BFC694CF095D69AA3F2C38D394E0
+:109CA000CF987ABD29AF4CA935E5BD950B4D797795
+:109CB000F90A53FF2925DF37E59D79AB4DF53B5C6C
+:109CC000A19F8A942FC8596B4DF524F7DD6679352D
+:109CD00023EBBCF816F948CB06BCD2F98795DFDB3D
+:109CE000F2492080728BC99726C05BF0678D209166
+:109CF0000705F0235D7E18FC178E1226771C83E47F
+:109D0000A6B93FD9BDF38846C7A9F61EF6F519E8EE
+:109D10008C18ED4ECAF7FF2C32BFE2DABB989DDCFF
+:109D20007957627B19393BADD7F979623FED9F4492
+:109D30009B452F60764AE75D02D6FF57FBD7CBAD38
+:109D4000FDC6C7A37B5C65B05341EE4F60FFA7190A
+:109D5000F4137B5FFA1CB07B743BD6C6E9BCBACC6B
+:109D6000FF763385778B42FC0E9A6F71D710D02B1C
+:109D70003E5618DD931DF9686FEBF507CFCFA0575E
+:109D800020FF4931D9FB927B26F29796ACA1F532A0
+:109D9000396623512AAF6C3101FD72B2149C5E48C2
+:109DA000E9577ED5E65F45505E26B4DF09B91BE171
+:109DB00060B3E837CD732D7C6FEA085CB75DE76F61
+:109DC0005935F8BD59197A5E0E9817CC87CFCB1E3E
+:109DD0004BC5D41673E17C27C532313F31968EE9ED
+:109DE000C5B10B30AD8AE5603A21568C6965AC107F
+:109DF000D38B621762BB8AD8684CC7C72EC2EFFEEE
+:109E0000D8784CBF12FB2A7E1F179B84E9D8D8D77D
+:109E1000F17B79AC1AD30B63DFC0EF636257603A12
+:109E20003A760D7E2F8B5D8DE9A8D8BF613A3276E8
+:109E30001DA6A5B1399896C466635A1C5B84ED8A49
+:109E4000620B302D8CDD82DFD5D8724C0B627762CD
+:109E50009A1FFB1EA623624D98E6C556617A41AC57
+:109E600003DBE5C6DA31CD89FD00BFFB621B31CDD6
+:109E70008E6DC6343DF600962BB16E4CD3628FE2E8
+:109E8000776FEC614C3DB19FE07777EC714C536399
+:109E9000CFE2F794D83398BA62CFE37767EC00A6A5
+:109EA000E7DA2739CFCCC76D5929A6FCC463663ED3
+:109EB0005EF5A6998F57BE6AE6E315AF98F9B8FF2D
+:109EC00090998F8FDB6FE6E3E5FBCC7C7CCC6E3327
+:109ED0001F2FDB61E6E323B75E6FAA5FB2C9CCC771
+:109EE0008B3A179ACAD566331FCF5FF97D53FDBCF5
+:109EF0005B579BCA7317AF3595FBE69AF97736D94E
+:109F000062B6BFA76E37CB91298F98FA7357EEB51B
+:109F10009C034490CFA494FFD4D4CE597230A15D59
+:109F200063F57F0348244ADF779014FF5A61F07E7F
+:109F300066707E90097447D32C4E77C380EE689A82
+:109F4000F18DC5787EF4C937DB7E416D4392710196
+:109F5000FD673274BBA12640BFB7E6E879A209903D
+:109F60001F4198DF80BC5F8DE5852CDFD574AC5A2E
+:109F70002B477D9EFB154E57835FACD5C5F20FD99D
+:109F80005E59057E858CB440AE9FA63BEC89F9F8FE
+:109F9000633619E1714A0C6CB3D1F5FE6775DFEDDC
+:109FA000E00FFCD411DA6EA3DF173B4305E06AFE35
+:109FB000C01E7A4802BE48020FC0F73412D861436F
+:109FC0007E6DF67B36828140FBF98B187C18CA3394
+:109FD000AFDA857691BEEE56CFD0F3B9CFC6E45254
+:109FE0006B3A41BB51BB4746798A7F55713FD5BD1E
+:109FF000A9DE009477DE236F87F320BB3F9BC9095E
+:10A0000062911F9B5A9783CBD101FB6933FA3D7B49
+:10A0100031F5927EF47F2A441120D5D73FB0EE115E
+:10A020006CDD141E87603D32F84B697E75EA55136E
+:10A03000613D141E2F7078BC681B961C1E044E0ACE
+:10A04000AAB82A01FFEC164CFEC7778550AF8D9D4C
+:10A050005FE27C54CD8F707BC4C6FCDD3AFCE8DF48
+:10A06000AD19BA3F86B53B82FB60E94FEFA7D7C673
+:10A07000C7E7F250C7E34C918412C1BFA591F99F85
+:10A08000C9AEFC2FE5AFFECC2E261CC72E05F19CD9
+:10A090007410DFCBB2D8F5592138D385F38784E724
+:10A0A000A99364EECF900ACEEB3C4AF79790DDF986
+:10A0B000E755FF217DDD70BE908DA063FB74281FE6
+:10A0C000F3A5BC7D31D7EB9EFFD353D125940F74FC
+:10A0D0005230B3F348B33ED7B949C473F4E2114CDC
+:10A0E0003F6CE07A80839A0DAE710639DD69D60B3C
+:10A0F000DB7438EE37C3B19822F44F2BE8FFB80B6E
+:10A10000D8FC14F37A9AF5F55AE6D152EE2746BBFD
+:10A110005B1A1B1421EFD8C4E6611D9FF0F3035DA9
+:10A12000EF75B8B9DF4429C07EF571ADE310DB4AA5
+:10A130003C1F4AAA8F58C7F992E76F174989CF2F5A
+:10A14000E9FE209C4AB87E441AE81FCD8FE4F3D77D
+:10A15000FBD3CFE1F4FCF37FAAC3F3EDD6702DEA75
+:10A1600079AD3E26A7C967B477E88F24C617FD3CB2
+:10A170007C0DD88D60CF95D438B15D568169BF5CB8
+:10A18000A59B9C008F66E56E05D2B565AC5ECAE8FE
+:10A190001DFCFB76FCEEEAAA3F0CFAA28BEAAD129C
+:10A1A000C07BC4AD58AF595981FED9942EE6B74D46
+:10A1B000E1E5B925AB9D10A2911B0E38A11D5125DB
+:10A1C0007F29B4EB0A4F2F027F571BF14B6C0A4ECD
+:10A1D000D8C7ED1C0E7925520DB4CB0B6B9A0BDB57
+:10A1E0009100B4D3EB45F87AF3CBC45570AE901F11
+:10A1F0008E846BC04F574FFCA5F8FD60B4D0507FE4
+:10A200001BEF5709B3F993F9AC9E5EBE95F7E70EC5
+:10A21000D7F756433F9B58B92FAF12D837C9566B63
+:10A220004598CF3A8EB7CE424960E741ACFD161D46
+:10A23000CD2CF45E1A66FE4EBD5E179F870DBE974D
+:10A24000C7E97E0DB7E7F57A3FE4DD8DB4B40FF3CF
+:10A25000EF8E4AD6BE89DBFFFA7E97CACC2FAEE3DB
+:10A2600047327C256D067E060BD452CCF9860C93C2
+:10A270001D47EA73CDF9F945E6FAA131E6FCAC0ACF
+:10A2800073FDC06453F92703FE92880BFD22DC5F47
+:10A290003292D7D9D2C5F03CEE8FEB7319ED8B3CDF
+:10A2A0005E6F5B3D8B7369729F5F5C4918FC16C8DB
+:10A2B0002C981F46D1FB69ECC2EFAD81DA141877F8
+:10A2C00067D7D0FDFD84D3D5E39CAE1EE3FBB787F3
+:10A2D000EFC7A3DC1FF330F7C73CC4FD310F707F1D
+:10A2E0004C37F863E8F7FBC11FE3003F4D10D32D57
+:10A2F000E08F413F0DF3C7FC90FB6336803FC60102
+:10A30000F8D780E9C6F1E1EBC0CFD6C1FD32EDDC74
+:10A310002FE3B5337FE3C6CB02B950BEE3B2C4F638
+:10A32000AED7CEF024171414CABFF389164D01BA64
+:10A33000E82404CE5B9CAF680137CD8FDEC589640D
+:10A34000BF1648A5F9511196CFE3E3809CC0F8A74A
+:10A35000061617E3C8D3C86CD8A73CAAED50F8AED0
+:10A36000E1F8FA9AC4C68372A41B95F88C7CFB0DA5
+:10A370002170449A00FDB2F9B8422101CA86DFDAA1
+:10A38000AFC9B45C59DC1B80ADF2B6F544C17E5652
+:10A39000B528EA1B1BABFD87E13C6BF3EF6D7EE458
+:10A3A0001D59C4841FB4EF8476757E6C1BEAB7AD6B
+:10A3B000F53CBEA892D5CB4F627F8FD96196FF65E1
+:10A3C0005BCD764F6BC3CC21FDC5C36789167F92E9
+:10A3D000E55C608A191F5B036C5EC9FAF3569AE765
+:10A3E000E32E37F7D7EA1E7A3EAED855A8EF27C33B
+:10A3F000F332B1D66D9F10CF17C72EC5FA56FD4E5A
+:10A40000227E543EA4A97200CE79A5A94A00F45A2E
+:10A4100069AACA533FFF1EE0F920CB2B03E7DBB943
+:10A42000F661087FCBF97680C0F9F3C6D184D917DD
+:10A43000DA9CD5812934FF6D82F6C2EBD2B21A2D97
+:10A440008FD2CB0CA768FB0AE01B8B57D0E3BB3243
+:10A45000E5487B21E5E39B378A643BCDEF080F4D50
+:10A46000CF83E218DC01F4CF14772A1520BE93B510
+:10A47000DBD4294E4F14377031A72F728858F5E678
+:10A480008B61BD2D9D33159067D2B57EB40F88CA00
+:10A49000E6AFF3BFCC2D43EF5FBB65BEAE247E9B22
+:10A4A000EFE9F328637C53C7EFCCEF0F8D5FBA7EE3
+:10A4B00016EB114CFE9D61D706ABED142EAD9B89BA
+:10A4C000DF4DFB69FDDCC6FC64FB597C998EBF4DFA
+:10A4D00081A3C8AFF5F1739568B500F50F4C222A3A
+:10A4E000DDD791EE9088F6E001CADF81FE24AA75DF
+:10A4F000D2FACAFC6880FBC905D87FA5DEAF411E31
+:10A50000F603F806D89BBC3ECA8D7003550F29FD93
+:10A5100037815FB330CED7753C68F271FF3AD53BD7
+:10A52000B0F433BA3EDD1EA1FF8CEC62FBDC3A8C4A
+:10A53000F8719965F5C486FDB0382989EB8FAD9E19
+:10A54000DBF11C509BC0F4026A350704A82769445C
+:10A5500084F1E72AFEB5345BDC350EF98AA4680283
+:10A56000E0DB0C21741BEC771CAF7AD83A38DCACFA
+:10A5700070BF96F3D59424FB9922337D3B53F65F4D
+:10A5800009F6E4E67B287E2788779164D6CF039B83
+:10A5900066A68D56E3F4AA973F6253B19F387DCBF0
+:10A5A0002C4E2F6AB63FFE5FD7E377DBCD7174FF89
+:10A5B0005F8FFFBF5B8F5F3780AFE7D2DBD9FAC910
+:10A5C0002C73FF71FD5D53709E5DAC5CB7073A2C38
+:10A5D000FDEB7ABCAEDFEBFABCAEB793C17A3D9728
+:10A5E0007781D5010AD0516E961FD51A58AD419981
+:10A5F000C5CF61A36CCDE8AFF8C042D792DBAC7792
+:10A600009C3F3F9050DE13FF08133FCDCC1D5A6E88
+:10A61000E872F49311BADE1E427D9A949411A37EDF
+:10A62000B5B3A18608743D5B7DC4CF978EE3E4F299
+:10A630007539FB029A884E0D331FDE3AFFA06B94EA
+:10A64000819F3BDC3D01380F77FB7A217CC9C877BD
+:10A650004BE409C08FAB90AF39D530EECF5DA05F32
+:10A660004E180C57E073BE0CE8D1C25F48B017E239
+:10A670003D8AC7138CAB77409414E5030E3FE34F3C
+:10A6800049F9CC79C669E87113F9F40FF8CB2A209F
+:10A6900022D0879E36C7931385E289213E80BCD79E
+:10A6A000448CF17E3ADCADED9A951A2511BF7B43BF
+:10A6B000085D210F8127563F14B1F067AAB08910B9
+:10A6C0007F583C633AFA9706FC5192995F3B227A95
+:10A6D0001CCBFF2CDF9E2327E6DBC9DA0FC43D7FAE
+:10A6E000497F5D3B3F8FD7E97B80AE2DFD88E53DFF
+:10A6F000A42FC1F8EE7233DC534ACC76C53F802ECE
+:10A7000027C0F97186E9BBE4CE4DECFFE77199B53E
+:10A7100013F56D53BFFB478ABF0B0EDB09E827BA61
+:10A720009CD1FDB10B203E93EE4F2DC46BD27D9C8E
+:10A730004B825E28FC8088D341FFF880FCD67B9159
+:10A74000619F36CBCCFF4EDAEC47E11E901E877836
+:10A750007398E5F5F9D47599F3F3C8CC6C388798FC
+:10A76000B7C94E20EE7001918EF6E9F3A7FA4B3B84
+:10A770005C4CA0FDD691FA56E0672DDCDF5EAB1095
+:10A7800009E206973C755FD56C9A8F70FDE72485CA
+:10A79000BF6A882F5BE88EC8709EF0CEBE8BBEF37A
+:10A7A0005502ED23ADB9103F984E307ED00AF739EF
+:10A7B0006DE6F99D6BFED6F9EAF78692CD43DA2570
+:10A7C000248C73FBB1ACC72D6AE7759FE9B760FCB9
+:10A7D000A23FDE7C9FE95CED5EFB27DBBD29AB245D
+:10A7E000D1FDA973B57B3BC9784B9C7D32F08B655D
+:10A7F0005268BA50148FD392EDC1C0051414D2D34D
+:10A80000E3A370A464A8D7769EF50EC379C779D464
+:10A810009B2E0ED1DF194EC7BFD8FD800CF4F9C1B5
+:10A82000236F5F057AF5A2676D54A6D3F2DD1E1281
+:10A83000457B2322831C5BB8CF867E372245ABAE97
+:10A8400031F05F8C90A5FD2F7ACC8371150BF73A10
+:10A85000223368FB854FBE338E50389C59DDFFE2B2
+:10A8600005603F3C22B03842AD6FDC35F4FB4289D5
+:10A87000DC144CC407399E9F7E267516E091B0EB20
+:10A88000C08DD86FCF77ED0EC339DE5F65764F810F
+:10A89000D6C3F325ED6121522AB0F919EF2BE8F167
+:10A8A0009BA71F16D8FC9EB6475C30BF5DDD728843
+:10A8B000D65BB6EB2F88B75F7F6C8F17E0B0EC6983
+:10A8C0009B89BF2CDB658B3AC661FAB603EFB904EE
+:10A8D000DC02E5234B91C5D074DF128CF75EDAD32E
+:10A8E000F1179B17DA9BE987C2C51F05B8BE66F34F
+:10A8F000CF80FC4F1EF2821D78B2F7412FC095F633
+:10A900003B5BA67875E947063A23ACFF58C6E0FEE4
+:10A9100008E99701BF96F5B4B3F12CF47912FE273C
+:10A9200067B05C18E930CB858FC92B55A818EECAE3
+:10A930004C181F3F201738BD2EDAF3F1368D8E7B71
+:10A940007AEFA96D1A9DFFE27F7CB8ED4ED0037FB0
+:10A95000EE5280CF2C7BE4F75E62807BB583D1FB27
+:10A9600099871FDAB985D2CB99D71DA8B79CF9D999
+:10A97000897C95AEFBCCE37FCB867B02B7FEECB245
+:10A98000E100875B9FF8FAF0A1EC7EC0D788C3B8DE
+:10A99000AF11EC5F7D5A60C1F8FB796AD99FE7F788
+:10A9A0003D9F0FF3FCE08803EF152EA3DF1A2A600A
+:10A9B000BF9620DF87FC4A0AE7A5BBD7FCC5362E29
+:10A9C00011BCB50B441FA4946C7CB0DFD77CEB9218
+:10A9D0004A48ED7E15FA23FDC8B7ADED96BD4AF79E
+:10A9E000F52BC9F7F163F2990CF05FB6BB9D8D6B47
+:10A9F000D9C70FE07F260DDEC79B1CE6F3958FC9F4
+:10AA0000E2FB5197DF9799305E4ADFC7254F7C7B89
+:10AA1000483D40E707E782EF7C1EF757EE082C73AE
+:10AA2000005DED4DD57C6C7F233368D9993D1FE7E0
+:10AA3000138A1FEFD9FB6F043ED9FF3387B29D7E87
+:10AA40005FF8B3D790CECE3CF11B5965F79DDC0281
+:10AA5000D513CE9081BF5ED01B96F233E4653B3CAC
+:10AA6000518737BE4F4B23574F57BDF8FD6DFC1E26
+:10AA700061F8BF3472E05A21C1BE3DEC28627C39D6
+:10AA8000320CE1B284F4CA4AB9793F8589B08F6F3C
+:10AA90004F03BC4BB68FFAFA1558FFC586FDDCC1D3
+:10AAA000E8D65A7F29A54FF00B0EEC6B44788D2425
+:10AAB000A0D333DD0E09E27BCFD8CF713FF74BEA4D
+:10AAC0007F0F38929CBF71389C8BCECFB5BE2F0BB9
+:10AAD000BF8DE0B41E36188EA73F4BCCFF9F730886
+:10AAE0007C1EA1E9B9B6C1F2CB4602DA0585F1F9BF
+:10AAF000B6F6D890AF9FDE65C3FBA6563EB1942450
+:10AB00003EA7FEA53ECED307C6013F3B7DF0198E82
+:10AB1000970CEF97EE7E5BD6B83C8818E54112FFA4
+:10AB2000D46B9CDF2DDB9FB8BF65BBFF92B0BF939A
+:10AB300052E0BB30FF93BD76A2D12E4EF6D8A627A9
+:10AB4000D29F0E38EC26FDA9D55375248DB6B37966
+:10AB5000535418BA6975E035B0E7B4DFDAF11C83F5
+:10AB600048FEF71C704FD393A2AEA5F06AF2CE4315
+:10AB7000FFA3DE5FB3054E922FA8815D2A65052BEA
+:10AB8000998ECCE6AD97DB15D1346F2A67F3400E72
+:10AB9000BD35FE841DD6F9678B3EF86789B40EA7D4
+:10ABA000FDFD5913FCABD444F86DEE3FB4D24654CE
+:10ABB000A3FC73F4BF05F321CFB908C495D87EEE8A
+:10ABC000D2809F2CDBE68A38E87A9E7FE2939D0054
+:10ABD000B733F73B88C310275EC7EDAF134F7CB286
+:10ABE000EDEFB4FC0434A6E3D76DA3F5410FDF9D70
+:10ABF0008AC1FAFFB9376D1CA1FCB9EEB93BAF02AF
+:10AC0000FE52073443EBD73D361CF5BAE3C358FE7A
+:10AC1000F89E1111D897C53FF9D95290238B7E9C8D
+:10AC20004AC03479FE89D76E84FC99E73C18D778FE
+:10AC3000E6B91397021D50FD5935CAF105C67704D0
+:10AC400068BF8B20CFCA852F0CF1328B20A57C6387
+:10AC5000D1D36901F0131AEA61BB658EFEDBD151D5
+:10AC60004BB45C116D9C682ED0E1A25DE6F1F29CC4
+:10AC70004C7F5A26F7CF63F5C3B98C5E7BB1DD6894
+:10AC8000A7602AB7B6D7EB8F721659FA61ED973ADB
+:10AC9000487D22FCAFE4FD2EDAF5F928737F1AFF18
+:10ACA0006E1D877DBF4D60F74AC8E32E3C475B2C85
+:10ACB000474766507A7D5226F3816E177BA323D3D4
+:10ACC000E978CF723EB93885E6E9F75C3E0FA80F08
+:10ACD00079E2ECFB31ECEF92A75C04F07DC9731EC6
+:10ACE0003C6F59F2E427C77F44BF9F7E2215E3B42F
+:10ACF000973C7707EEF71247F446F06BF73FEE40CC
+:10AD00003FF2E9C75FCA073DE4B43D9A9F31847DB5
+:10AD1000BEA4070EC107AF83DA0565F5743EDA46B7
+:10AD20001677D64052FCAB68BF0DE0D7003C7ED30F
+:10AD3000C5E2A3F839EE0AEE0F3A3B574DC3F99737
+:10AD400033FFD60A7E4F7DC537D5E1E98679405C71
+:10AD500028B988903BE4FA51C0676DB16F1015FCBB
+:10AD6000EDB1624CF57A3685AA59706E90C5CEC9A0
+:10AD7000ED597E52570EED581C11715F394067BF77
+:10AD8000A65BBC62B33A1CFAFB7727E32F1DAEC06B
+:10AD90004227F21937DEF7C4755286A03DC1D6F5B9
+:10ADA00089C0D6659DEF2776CD01FC3C7EBECDCE19
+:10ADB0004D1A24F53538A72487395F1AB47E4667C3
+:10ADC00067950CA4337D1D1D8D0AF293F6461FA6D0
+:10ADD0006B1ACB888A71F87ECCDB383C1CE51AB143
+:10ADE000C1FD5795CDD5E10E06E05C02FA047FABBC
+:10ADF000CD1D42FC72F8EAD1F677BA991FD2E6D699
+:10AE0000481D4DED6E0627B8770A7092795EEA9A72
+:10AE10008170A5EDF1FB025768A313FD11634C7C13
+:10AE20004ACEAA30E507C14DC78B3DFFD3F02308BA
+:10AE30002FF0D3A8E83F9F88706B690C60FEFF007D
+:10AE4000FC9E61F09B4C5403FDC85935A67C52F81A
+:10AE50006DA6F0CB8AD395150E0D3C1E4DA7A764A9
+:10AE6000F4FBC34682CEBCBB1BBB30D5BF6724916D
+:10AE7000EB392E819FF78756C1F91F51985F856482
+:10AE80006924CFE04F223E0DEF31E19B2650EE6664
+:10AE90007E447D7F6D8A74DCCCFFD4D7603D77BC67
+:10AEA0006C17815FD91A1E20EF641AE87846D0A586
+:10AEB000229CFDE8BF6DE2F2B565603FCDF4D1D1D3
+:10AEC000A862BA8ED3C9064E271B61DFC13FE717C0
+:10AED000714F3BA713949FF7D03CB3EFA3C4E8D7BF
+:10AEE0004EF7F744ED74FF9127A998B2775E8E383C
+:10AEF00022A5B45D6A390900BEA41FF95E84BDDFD6
+:10AF0000D283F7FBD339FCC8FEA2F4EBF0FE34B1D8
+:10AF10003339456C2C0DDBC17EB2C2B7C97FD00975
+:10AF20007677B2F964FB35473E1D2FFB4D07F2EFF4
+:10AF3000AC1B7A8ED4D275B83B53D19ECCF6337C01
+:10AF400074FB43429D61FFB293E87D9B5D57385C83
+:10AF50008087107F4BF9F6DD5DC52E3CBFB0F7F85A
+:10AF6000800F76A43339A3CEA2A35D1C6F7796F32E
+:10AF7000476FA599FE757EAC4CA930E1B1CE6F3319
+:10AF8000A69AF15DE7B76F0EF0DB608E0BCE3563EE
+:10AF90005B911EADF8DF649735E12BF0DE06617E34
+:10AFA000A7B705F60ECB603E80F12867FB0AB7C352
+:10AFB0003B00AB79FCB346E905E50EF77FEA77B9CC
+:10AFC000F690609B5A08EF81500485776328FE0055
+:10AFD0003DACA7F843305EC8CFE96422A63A7E565E
+:10AFE00083F3C4A0B7D94A5E14D9FD0B11640E9146
+:10AFF000A81DE8063FD381494ED00B253B8B53E972
+:10B00000F7883D7036D6E29EE984F86821BD12F7D4
+:10B01000FDAF9EDA82A1CE5508C4F152BC51DC7E50
+:10B020007214C6817BBA40174A05017B728FBB3709
+:10B0300005EC1BBF4B349DE374B842D35C86FC58CF
+:10B04000189DEFDBD770FDAC1FEB783339BD933C17
+:10B050008D9418E85B8F0B25AA46CA0C74BEBA748F
+:10B060001A8173CDC1F49D848F3DF8DFC3C79A0A5E
+:10B0700022B86F762BDFC8A2FCDD8DA9262A30FF0F
+:10B08000BDCDFF361EF1AC0EE041DCDB07F497AF1F
+:10B09000150D9EA7956FC5E5918AFE2A2A8FEE9D14
+:10B0A000087C30893C3AF0A751DF9269F93B2FD9EF
+:10B0B00004A3BF6E7EAC1DE5415D6C1251E97C6B53
+:10B0C000BB7E80E9BCAE6EC4FBF7222D5ED8C7F70D
+:10B0D000DA983DF75EC41EC17884CFBEF8C2067E02
+:10B0E0007DC2FA7F6F6B13D623E07D318CFBDE5679
+:10B0F000D69E54AAA84F9FE56BACDDE008405CF9F2
+:10B100007B5DB4DD10F0AC056328817E8AF7FF21FA
+:10B11000D69FD48F023EA7D3FB1D32E54B0087B7E5
+:10B120001C09FDEC0B5C97AD03782F70053601BF51
+:10B1300021EE8CF37A87E21D91EABD08EF90F76A61
+:10B14000939F95F931DFE17A31712629F7F2F64ABA
+:10B15000E2F2259DA75EBC8BE65ACB434162B0AFBD
+:10B160006D84D9D74B9FAEE6EF7DB0F924C04FA6D2
+:10B17000CF763A900FCDE5FE201D5FE3F812F2F294
+:10B18000FBA0267C5A10DB88FB2D748CBD771285C2
+:10B19000DF87148FC02F27745C321CE868D5DAAFC4
+:10B1A0006EB881F6FFD12B36FC3E3FE6C2FAEFDFE8
+:10B1B000E5BFF706D0D77F69C733F68F0E5F86E706
+:10B1C000B1EFDBCD7E841B5318FDFED1C5EC917928
+:10B1D000B10E937E3CAF6D8E0CFEC779B1F5F87D54
+:10B1E0001E1CCAB07B1B87AA4BE0BC86E0F9E81F97
+:10B1F000DBDF9DBA1AE55905FAB1EAD63912DE232A
+:10B20000F9A34B35F19DBABE4EEC9750FD282B9B10
+:10B21000F767E01F7531B87402FBA311B867308F70
+:10B22000F39181F96DB59BF8C8FBAEC47E925303D0
+:10B23000EBFB2AD2D1E0F55DCAE84B1FB78FD15D99
+:10B240007C3DF74E4AB49EF83AA660FDF7D3138FC3
+:10B250009F91C2C63FDE389F04281FAA75D07A6E20
+:10B2600018FF96D68960676F4DCF100CEBAAEB5A8A
+:10B2700044028675D56D9D2DD71AFA8DEF83ED05A5
+:10B28000E33E64A4FC63EAEA7290DBC17F003DD533
+:10B29000765C322E847636E327EFD8FDF9C0574F1F
+:10B2A00074DD9290BE33522CFBD3C5F787EABD956F
+:10B2B00086FDD1F7C5DAFEF89FEAFE7A17F8013667
+:10B2C00033A52619BC06ED5B6162B89573FC3C4E54
+:10B2D000E56C08E1A63E7904F07A5D2AC6712687FE
+:10B2E000DF85243414FC92E8AF54DF294D9900E344
+:10B2F0001284435D17C38373C12D3E2EC783EAC4F6
+:10B30000EBB97E000F1A884609F6A87C2E3CB8934C
+:10B3100068CE21D6318007A34C7870FDDAFCCB8053
+:10B320001EDF033D65D4E0FD3F2A6BDEC9700EB41D
+:10B33000D686E74C4753B4ECEB597E3CF0E7A3DEEE
+:10B34000F055932BE3F9050F967A671BC63DD1762E
+:10B350008B37919FF5FA64F853A291F2AAFF7DF81A
+:10B36000F34E927B570B5CD537A6005F0E27F6E7AE
+:10B37000EAA9CEBF6D69EE01BB13E4E95177D15F55
+:10B3800023B4F451576801F47387A88E9B2DC4ED44
+:10B39000CF41FA67E3F44B8E9582BF3078C9313BD9
+:10B3A000EA43D81F01BDB290DFDF42FF460ECA0359
+:10B3B000EB79E9FA94C284E7AA2D8DF5171DC30035
+:10B3C000228D28867B6012617AD4A784F9BDF4F5BA
+:10B3D000C8F690E207FB522041C073BB146A833861
+:10B3E00028BB2F6BBC66806B670A8BFF731D3AD43A
+:10B3F0005648DBBBDE7D45C1B8153A0EF8D79C79BF
+:10B40000D259A37FDA9EC5E2124989E17B11C42794
+:10B41000D0BCC9CEA7F31DC24E7D566070D03C0E85
+:10B420007E0F4EB381DCBB4E7FF8024047F1E575DD
+:10B430003D0E446A66E5E97A71332BE7FECB65B5CC
+:10B44000CC3F69DDD7EBF6AFC177F5AEDB9F3307B5
+:10B45000FC58D7B947BD0BE70BCF820F1FF03D9DBE
+:10B46000C9656BBBC7389DFE5BB7A8D9E9BE1CB2E6
+:10B47000F71F84B876ED36F64EE2F5BF3F644FA570
+:10B48000E91BAF1EB5435CD14D10A043D7359BA837
+:10B490003253822308D739A4C7C3F23DC3667A8CDE
+:10B4A000FD515315FA5BCECE79AFFFFDAB9781F816
+:10B4B000A4FDB5407AD32B4486FE67EF535BD9B524
+:10B4C0003BDEDF7EDA9F18EF2F0E4799D9399213B2
+:10B4D000E112879313E1F6FA405CA4867E14039C84
+:10B4E00051DFD0E13C00B7B459579271C9E9E53A50
+:10B4F000F7C877C9B8F8BCAC70FE088A28BD3D9380
+:10B5000012F815D04D2425F06B48173BFBF3A5220C
+:10B51000BC77F83BE0B34B6DA182EC62BC8F386A1C
+:10B5200018C471F5263E5FB5D2E95B402F10CFCD30
+:10B53000E32B6FE4EB7BFE7B273C1837F9C46BF9F8
+:10B54000902EB1F5ADFB2ED0DB7FD850FF3EBB6F08
+:10B55000D49071696F717FC7C914FD3D16B6BE9B4B
+:10B56000B81E77D3BED408BC7B795383CDA4FFDE4D
+:10B57000D4C0E23888D43BEE5A931ED99CB41FB095
+:10B580003BADFDE8EB3B989F7B21D887F74F90556B
+:10B59000F03F1C78E5ECEB75349F32C289E7B2EBE3
+:10B5A000D239FE568BB8EFF7A70752C782DF696D15
+:10B5B000865FA3EB5CFB02E911297C0E8EBE3D5237
+:10B5C00043C75B7F89883EAB0DB107306E522B6756
+:10B5D000EF14295C1FDDD07BB40BF0F1C41107FA26
+:10B5E000FBED1E765F75AD3D980FFAFBBBDD72C2B9
+:10B5F00077EFFEEE96705DDD421FC6BBCD21612761
+:10B60000F08D7DBD3387C37CBC7EA200FA9FD86AD3
+:10B6100013F93D28EEE7884ACCCFAE492C1FE0A9AC
+:10B62000E232C6ABB54F9F8AF114733B7F8371C280
+:10B630005E7E9FC93A8F0B53D97C3DBD1957007C64
+:10B640003D53457CD3C8E3EFC778F182DE1A19DB9E
+:10B65000878521DB17AC54AE00B8427BE0FF05E7DD
+:10B66000D9BE3895C53B6DE47672B7DDDF3A95F605
+:10B67000D3BD2E5D80FDD0EB4D4965FACC89A9BACA
+:10B68000FF268CFE9BFC12C505EFA3E40790B8894A
+:10B69000A7328C71B8DBA11EF36F221CBA473F1989
+:10B6A00085F3E3B5201B609FED0C9FD6AE13D09FB2
+:10B6B00049E1970BF2E2DD7B1CDF807514B4090AC7
+:10B6C000D8DE344D38EF5BDD4E66B774DE8B762006
+:10B6D000B847A1DFFCADBFC3797992AC779B9BC122
+:10B6E000EBDD73E0475AAA9DDD1B6AE8E57652144C
+:10B6F000DF3F0CEBEFC2052AD9BB84524035C6A10F
+:10B70000C4E987D961749D0138DFAA9D2847C00F1D
+:10B7100020B675E33BBF73C20E72395D5FA7D01BC5
+:10B72000007AD12688FCFDADC05B00A7F51B8763BE
+:10B730003CDB1A31908FFE9DFF25E3F9D8C1C0D9BB
+:10B74000CD73687EDB4419E9E26080DD6BBD7F6507
+:10B750005137D8E19E861A7CB737A2E04BB8A4A92E
+:10B7600092BC0CF1A44D2B4545A0F5C341FD7E8153
+:10B7700092027831DEF6E11565707E9623822F897C
+:10B780009C10D8BB202D2B6B14D8D716254B30DA44
+:10B790002DB7A432F9F2ABF4E02DA934F5DD75B77D
+:10B7A0000231DD1B62991782BF506B9355F67E30D4
+:10B7B0007B4F2493EF4B66AF189DE7C5BC7B3E35AE
+:10B7C00091374C617ECA1F5C1962FE453893AC42CA
+:10B7D000FF22FFF3E1BE66F1DCDA312998D9B47AB1
+:10B7E0001ED6877EB2693F999562B48AF6BB3D3D0D
+:10B7F000B00DE5C9654E841391FABA004E91CB7233
+:10B80000FD10D77AF7A491BF8127A5320FF7CF0497
+:10B81000391A1991F24637F0A91659053ACF5C79D1
+:10B82000FC06F89EEEFFE12D906636FFE14E900794
+:10B83000E97D7F69C4EFD365937F2FF3CDF73F8711
+:10B84000F2CCA06CF2139E4E0FFE3095EEFBB6F2DA
+:10B850007018DE3DC51DCD8EAF63CFAADEE9F08E38
+:10B86000F589AB45FF765E8EEBDAA444D632B85547
+:10B87000825CD3E1B646547BE01D65ED2A27E247A2
+:10B8800009E9457E9503A7C8C5F17DC97CB37D391B
+:10B89000C44958E7F308A75BF883772531FE9ECAB1
+:10B8A0003139676A0AE0F5E315BD3ED0E3D7A52735
+:10B8B0008E4F38E966ED1D49EEA71FE7E5C012BBC4
+:10B8C0002A300D8C85D44DB43448F39CF83EE1E326
+:10B8D000A2FA47C4F3BB6D2AEC0FD4B7D3FD3BF0FB
+:10B8E000F249F40F1E08FF0ED317DC657A7FD16C86
+:10B8F000DA7E7DE551F6CEB7C270A4AE8DF18B3AFB
+:10B900005F9F13CE2BEACA89B29DE39BA6C319FCA5
+:10B910005D5C5ED55ECBE09A554EF0BC157C62F066
+:10B920004E5936D4A3F0CB6A5BB51CF791F46AC5C7
+:10B93000B4DE7AE817F6A799DD3B21A4CF89F41B82
+:10B94000B6E17923A5F75FC179626DE7703C6F8737
+:10B95000EBE9D05F061F3783F7D74DFB01FFDF8987
+:10B96000361BD98EFCAD97405E5D497119F1B3BFAE
+:10B97000BA8CF6AB562ACA5A1D0F743E4649632E3E
+:10B98000951700B7B99AB61CF0EFA8537919E6914C
+:10B99000BAC9A1C2FAE76E7AEA0ED05B527D7D6D1C
+:10B9A000C01FEA26B2F96674D2EFA8DFA8BF82FAF8
+:10B9B000759D0E958DC7E157C9F18CC3E1663EEFC9
+:10B9C0009BB7B279A78C8884013FEB5652B8425995
+:10B9D00088E13DB834BF1091AE0EC3FA3D5A36F639
+:10B9E0003B6C96852E2CF8A7AFAB96AFAB76255B5C
+:10B9F00017E1F444A715857E6B2BD93AE712D65E82
+:10BA000084EFB4FF9BF97A6AB52731BDB9CD61EAFD
+:10BA10007F5BD98E5E984F61B9AC0A0867F63E66C7
+:10BA20003E5F577E331B2FBFFC4984176930CC170C
+:10BA3000FDA2863CA5AB132F51C2A27AAE0081FCB9
+:10BA4000B4DFA3DF93F11CA56493795D27DA473D4A
+:10BA5000D009FECF7B643CAF785CF4BF558076A8FC
+:10BA6000AC32FEE3FFDD0CE0D33737E3BDA93DD5B3
+:10BA70000CFE27BE4922800FA587831900EFD2C391
+:10BA8000219ED6E33936DE13AB8AE331359DDA04E5
+:10BA9000E097B1E247E7031FA0FB0CFAE008E3BC24
+:10BAA000E9FC32DBB26B200E296B62468D8C4FFABB
+:10BAB0005ACA0F6F9909EFD7661DDA720B8C934340
+:10BAC0000CEBA1E5459E62A4BBCC43B414EA351C43
+:10BAD000BF0BF6A393BF2F5F0A33CBC0F410A4991A
+:10BAE00094BE3B32609E12995A11E7070FDE533520
+:10BAF0001EF80ADE29A9C0344A2A06F30D43FDD1F7
+:10BB0000BCBE2624A837DAA39AECF207EF99361ABE
+:10BB1000ECF7F5A027D27D6A27CA87101FA3F94545
+:10BB200084FB7A7BD4594EF36BA8DE08FACB86B23D
+:10BB30003F884077EBF7113FE04766F01F0EE33E8A
+:10BB4000CE71A7E3BA25997400FD1F1C7D7C3AECE9
+:10BB500053E48088EF48D4FCC2BD2515F4A1D75921
+:10BB6000FC49F74BF528BF6FCF9713BEC34CCEA14E
+:10BB7000275AEB6794CE443F5EC1A68DD3E13E4E7B
+:10BB8000DD74C97F39AD9DB5A9BA1AF4183548B12D
+:10BB90006B389DF7D6F1AB8008D519ECBC4A9DCE29
+:10BBA000BEAB5359DAD138FF22B0DBC3BB24173CFC
+:10BBB000853CA69DBD57D7517ED619A27A6965F5F9
+:10BBC0005EE737E9F76395540AD2EFC7A69C75C1C3
+:10BBD000F9CCFD95359900CF7D6D66BD8EC0636A49
+:10BBE000D40E1AEB08073C745E9DBF27084F9B23B9
+:10BBF000DA554BF3B6A7DCA0E10CB26FDA3BBB67BA
+:10BC0000019ECE2DC3F0E441EB3DCBE5C59C867E85
+:10BC1000BC5755A811768E1ABE1799F2CD9C6514A3
+:10BC20006ABDC8743C9B987D1296022F025F0E97E6
+:10BC3000876468A2F3B3CED2DA9DC0CFFE067A1D28
+:10BC4000C8B9FAF978FF11E9DF06FA507F7522BB0F
+:10BC500029989A82F33DB1F59AD7C03F3DB781E963
+:10BC6000FB055B3F14703FA8DE9743FB2FA8C4275A
+:10BC70002AC9DC9561E758D89F1291A82ACCA787DA
+:10BC8000809D10A6F2C70807BDDF7FB6FD3AB70357
+:10BC9000DB07C1781E165F8F9BAF27DF4FD793401E
+:10BCA0004E5FC5C7BDEDBE0F0F4C02F8AF64265204
+:10BCB00041F86DC169984781767EF3F816F447E143
+:10BCC000B9D3CDEE437B2AFBF0DE9195BF833A0FCB
+:10BCD00074BB2DF5CC7866DF9BF9E9A03CC72BEB54
+:10BCE000F77C0BBF1AEBE8B912F7770F7BEF9C10CC
+:10BCF0004AB74E7C065465EFC446F477C9EBA1DE23
+:10BD0000188F5B013CE81CFD870A80CF3AAE2FDC20
+:10BD10005C4ED05EBD39AF17F58539CD5C5F90FCC8
+:10BD2000ADC06453B7A693B506FD0143FCE188B1ED
+:10BD300099EB0BBAFCE772BBCED7DB867215F40326
+:10BD4000835CADD5985C2DF031B95ED746C75139CB
+:10BD5000325719F51226C7D54D5C7FE07238938FA4
+:10BD60009BD5C6E45526E8115E083FD0502EE35916
+:10BD70005E765C6F1956CEE46566E7E328D75E0110
+:10BD8000A7CB04E01B4C5E8EF8CDAB1A80C9473FB1
+:10BD900077513EFD142FF729543FCB88EB676B4456
+:10BDA0007ECE44987E88B1F5749E8FF1FAFAF71D25
+:10BDB0007C7E8F1FCAF806F0D707C345E36D06BA2D
+:10BDC00045AF27CDE757B273FAFC06764EEDF1CFBB
+:10BDD000DB69339C3F34BB99BDD9ACE35543D407F1
+:10BDE000FDE2FD40E4E3EC7DA976FE1E946E5F7DEE
+:10BDF0002795FB3538FE2493273A1FF29080B79C95
+:10BE0000C2F7586427F26B8DDA4BB0B663E1A6DC5B
+:10BE10008540EFE1AB2B61FEEB27FD15E32E0A9287
+:10BE2000D88B7F073B93C1E14BF175CFF457991D38
+:10BE3000DA2B26BC2733D123E13C7B24920AF07411
+:10BE400085D9FB84AE8972C2FA177A18DF943DEC6B
+:10BE50001ED1FA493BF17E6352F92C11CD96409EDA
+:10BE6000EAF2B613F6793221D5EE59AD1AF2FD4851
+:10BE7000D086FC95A0DD19E6BFFFA295C9E837EC96
+:10BE8000B4879DB01F1B2AF9BE2ACE6EB88FFEA5BF
+:10BE9000F785C203F6B93D2046E07E793BB554C72D
+:10BEA00032BF0EFE7ECE096ABF1BCF292EF3881C3F
+:10BEB0004EAA08F189056D0CBFD64F92711E6BC753
+:10BEC0006777DB0A8DFC97C12998CAE0B476D28BDC
+:10BED000885FE73BBF790D774E3E6638473CBEF939
+:10BEE000A1228073FC9D96C090F717E635FC66F2A0
+:10BEF0008E04E70303E56047B9C10E8C5C6F3C67B5
+:10BF0000F9770FB3AB431EB3FF0EF8AB1D8D8B4813
+:10BF10002EF897F65C12F1A2FF7E313BAF5DC0CFE9
+:10BF20006B4FEEB806DF53184BD1CA9E60DFDF6F50
+:10BF300034BFA7F0FE830FE532BF46C414E7B160FB
+:10BF4000E73363D8BB661AFF9D0CA26655B177AF85
+:10BF5000514EBFE8D71CF8EE5C10F9900CBF5301AE
+:10BF6000FE76A0E062B8D7DF83A91BE8B778F07B44
+:10BF70006E19540D43BB8B0431CD26F598FA481841
+:10BF8000D35CD283691ED8B9C52017FA31558922EE
+:10BF90001203DF2F227ECC979020A612EC5B66FC6A
+:10BFA0005C42DAE5C4F80B38BF00BAD7CF29F4F306
+:10BFB000FD199EDA4E0F327BF379C5524F609D0713
+:10BFC000E11F45BE3D87B3F0C33F1ED303F77B5649
+:10BFD000AC63F74B74BE8E760DEDFFD10C2607B423
+:10BFE000BB05E45FAB53AFBA14E1D8693F6D3C6F5A
+:10BFF000204E6709FCFE8BDEEF1CEE5F98C3E51F49
+:10C00000B8B7D9FD3B3FDEFF99037E0643391928B7
+:10C0100067F7AAF57EC4D42923873ADF33B4C778FB
+:10C02000E45A8BFE7F4EB96DC9CFB5B6FF8C4E2852
+:10C030003BEE877BF452359F9D3331B94D1149C595
+:10C04000766D8EB7D10E0B5F1630C2E510C77F5DDF
+:10C050009ECCB5F8F5ADE95C89D385A51F2AF9D248
+:10C06000E15E04BE6962A06BFDDD5BFD77D2160464
+:10C0700042720E6BE6C3773DF8BCC3646B4D0E4D48
+:10C08000DF83BCC19F7FD81BFAADC7608728817A48
+:10C0900091BFFF8774388FD3E165B6CE6AE06F2712
+:10C0A00042C40FF6C30252BF1EF431F2AA0DF9DBEF
+:10C0B0000574DE7205D86F44133330AFC1EFF97CDD
+:10C0C000D0C8EEE51CE7EF56EFE4EF249DE2EF5415
+:10C0D0008FEDBAE32AC08393FCBD6A9DFEF571C75C
+:10C0E000F6A4CE06B93FB6E7923AA8377697230A68
+:10C0F000702EDBD71E04BF10BCCF9242C7C9A3E38A
+:10C100003933808F1094B7A73A5322ABE93C4F756F
+:10C11000D9902F7F5C2EE23B23F0CCA58DCF2F2D25
+:10C1200003FAF9FB8DA0879CE47C447FEFF154B5C2
+:10C130008AF6F10B7BD608702FE1D46C15D77D2AD7
+:10C14000A7273F83C2C7E765F1E525BB1DD1223A8A
+:10C150008F858FBC5E540BFCAF28BC30D13973BACD
+:10C1600097F1BF534F108C873BE5E2BF4FE4ECF1F2
+:10C170001AFDACA95EC164179EF2F0DF39CA3B47D5
+:10C180003D1E5F4EDC3D5E46F73D5E388FBA37F5AB
+:10C19000C7787FEDF813EC9CE285CD75F9E08F1A36
+:10C1A000EE55D939FE9E9F60DC38AC03EC683A3F0F
+:10C1B00015E6776FEA5B27C1FF40DBE1FD0CBDDDD3
+:10C1C000F13D75AC7E17ADEF45B8136F05E0038305
+:10C1D0003BD9CDF884AE3F2E8A64E3EF2DC4CB4526
+:10C1E0002C8729BA28FCC7EEBE1ACFB5467B3398F8
+:10C1F0007C507AC6CCC4F987F3611D7B2E09E58398
+:10C200001FEFB8FE7B4E52381FE030C3131AED35D6
+:10C21000F0F7F7DF7E0AF97B9958FFE7BB002FF7AD
+:10C22000B2DF1FB9E3CD8DA2917F4CF432FFFABD8E
+:10C23000A94BBD701E757CE09D9C308BF7D9CFDE7D
+:10C24000615DC469EF7837B59F283CDEDFFD032CC4
+:10C250003F3EF08E4D0FC693BDBFFBF90C486B7986
+:10C260003C3F895C83F445E1D2E64C20AF06EE45C5
+:10C2700045D87DB733027F7FF43E1D6EF5F24CD377
+:10C280007915A3EFBCAD8587505F8E24BE276795D7
+:10C29000F7D6F764CF750FF828A7D363FC9D92A556
+:10C2A0009ED0B7BD09E4486DC7927C80732DDCA990
+:10C2B000C33887AF5E0EF636DE3761EFC946114EE2
+:10C2C000FA7BB1643C2B4F67F9C5DE2BD7804E74E7
+:10C2D0005C7F7F56FB1A2B2F64E56DBCFC254F70ED
+:10C2E0002E1B9FBD2744B9623AFC2E85CEFF92AF2C
+:10C2F000DFFCBB143F029E3C01FB5B8AFD49B4BFDF
+:10C30000B1FF7A7F3ABFF997FB71FEF7F6A3F361AD
+:10C31000A04B08D9237EFF98FF0EF8FDB3EDC9AC02
+:10C3200002133FFF6473712B9C037DCCDF0F71748C
+:10C33000AE2220976EDEB4D1F4BB26D677BD9A78B4
+:10C340003C895C4CE9CC40CFFBBD4C8FDECFF92162
+:10C35000FCB90DEFF9C05F673686DCA0FD378ABFF8
+:10C36000F35E46C2A85F8D213D9896935E4CC791BF
+:10C370007E4CF198B4185C7D7E1B7FAFB70A16BF68
+:10C38000D819BA1F42753F75849E017C82777B0560
+:10C390001BE8454B27C3FC7FEE55F4DFF52496DF01
+:10C3A0004B8BFF0E880A7ACD0CDF507A0D51A4D347
+:10C3B00003F11B45F8EEEF0B5EEC37D9EFBF2DB75D
+:10C3C000BC7FC2EE11EB7058427A300EE285AD2B85
+:10C3D0005E1E4DE1BF70B707E5C1C8ADCDF8FB5F8C
+:10C3E0000B496F36DC2F1DC9DF93205DECF785F418
+:10C3F00077224677394CEFD42DB1FCFED022FE7B5C
+:10C40000618B2CDFF5FB9B1DF021411C81F5FEE7C4
+:10C410003BDE24EF369527FE1D18EBFDCFDD3D22D8
+:10C42000C6F7AC80782121CEF746EFA87798F1AB1C
+:10C43000E7D212C3FB4E4D829FD9D39E94C083C2D4
+:10C44000E071462A0CBFF60842C238B26FA6897C5A
+:10C450001F9AC995B49FA6C59202F666532405CFCC
+:10C46000419B1466175EE0A971829D4ED2457C47C0
+:10C470006E9A6D0AC697CB4BA48BE0DCF3D0F685A1
+:10C48000BD707FA1C927A19FF68274760E4A7244BF
+:10C490007C1FA059D99B3E07F6C9CDCE1947282449
+:10C4A0000271F007BA6F1721DF44CD96E1308E108C
+:10C4B000EAC57B373912E1E7AF33C653FC2BE0F80E
+:10C4C00020914EBC7F3C75C93117C8F502BEEF13F1
+:10C4D000D20A99DF98EFE7B686A3E980A72F75B750
+:10C4E000FE761AEDCF1E9130AEB5ECF3A637A6D18D
+:10C4F000F1FABB658C67D5E190BF5232DD9FCDBBB1
+:10C50000D59C972DF788256228A7F9517C7C78C0A7
+:10C51000296A8CABCA0A3067A1E246FCB8284D20D4
+:10C52000786EC3F3A3214FF174973D5C03EF61EE86
+:10C53000FA93807E8783DDF30A304EFF995001E045
+:10C54000B78E0FD6FDFB1BD7872806B8F8FD6017FE
+:10C550001CD659F1A7B99194823FDA193994722106
+:10C56000ECE3613BBE23D5C2F56F89FF4EAF8E2F42
+:10C57000D6B4C582772D9F5F8378D74FF16EFB10BD
+:10C580007827292AEA09F63CE207F2B767F5E62A96
+:10C59000B4DD854FC97E3705D9B4C7CAD3409FB92A
+:10C5A000F0F9EBF09E2CC00BDF796C904BC1EE776D
+:10C5B000346495C2EF1D4D7BCC8DF878D6CDCE7FFF
+:10C5C000A486543F94377557F954035EB7362AA5AD
+:10C5D0005229BC6FEA2C85DF456A4DF23BCC23D251
+:10C5E000C520F897646EFFCF4B63F39D97968AE959
+:10C5F000CD3C7F9FA4CD84F9DF47F107E2050EDC37
+:10C60000CAF077458E13EF3DAF78A978F8507140A6
+:10C610003B1B7DA500B7ADB7D6A2DFA37AF921D722
+:10C62000E540E71EA702F868F38EBC770AE0FBCB73
+:10C6300076BCF7D5E4A952E718FAB37927A25FC907
+:10C64000266AB96014DD9976E4722907F045DB02A9
+:10C6500092A869C373974B943FEDF268B9022DEF2E
+:10C66000D8F03CCB0FD3B608B4FC071B7EC1EA8FD1
+:10C67000D072E1973F7EB4E13F5879A9B605F20F39
+:10C680006CF835CB836E41F5984737FCEE72B82FC6
+:10C69000DD64F7CF02FFCE8FE9FCCBE9FC7B78BAF3
+:10C6A000278DF973F4F2BDF09DC27B1F4FADE54FAE
+:10C6B000F2764F2729FF292FDF9FA4FF9FF376D122
+:10C6C00024ED0FF2768792B47F91B73B9CA4FC6572
+:10C6D0005EFE4A92FE7FC5DBF52669FF5BDEEED586
+:10C6E00024EDFFC0DB1D4952FE062F7FD3D2FF5B36
+:10C6F000BC7E1FFF9EE7697B43A37897D7CD5EF68C
+:10C700002CF3B4A1FEBEB5BE12F1BF6902D33374DF
+:10C710007CCF83784D9A2F52585C5591C2ECB85F0C
+:10C72000F0FEAB97976C00BC5BF14B1BCA532A47DA
+:10C73000F0F774B5E52CEE65C54BEC3EC88AE51202
+:10C74000BECFAEE3E32F2CF3DFC6E7D7CCE7FB5C2D
+:10C750005A113F6FF195CE30C67B2AE6BC93D213B7
+:10C7600084EC346731F952B6BCC6390AE407952F18
+:10C77000C0375BDC7214EED1B72812963767D52824
+:10C7800050AE2912CA9F96AC1AE71CF4E764A07F4A
+:10C79000A280C7ED352B12DEE397D2A762F9B4C7AA
+:10C7A0006628C0479B497F3ABCCFA7AD94F0BCF642
+:10C7B000407D0D7E2F48FF281DF8F38174B6AE43EF
+:10C7C0009E175DF08EAB749B88F26224C08F8E5BE7
+:10C7D000B4528CA8B4CA21658508F9079A99BCA2FD
+:10C7E0007F9EF186771477DD5EF532C4EF34AD932A
+:10C7F000F077B6E14F32C88312FE3BA5994A8649CD
+:10C800005EDDC7FDB89ACF8971782512F1197FBF17
+:10C810003253E1E769B619F88E5971D82C9F0ADBBB
+:10C82000CCEFD81458E493555E8DA8A7FCD150DF07
+:10C83000E1534CF9CFD3F87B167EE2077D66C5E362
+:10C840002B2E8750769D5FEBF2E5BF005F71521291
+:10C8500000800000000000001F8B080000000000A6
+:10C86000000BDD7D0B7854D5B5F03E67CE3C3349E7
+:10C8700066263393C97B1220040838811023BE2614
+:10C88000216044B403A2E2A338E11920C9044A2B71
+:10C8900056BC4C48C440B186DB8840810E2A8AF5DC
+:10C8A000D1A1458D18EC808878ABBDD1D25ED4D6AD
+:10C8B0008EC855501EA3B648BDB5FC7BADBD7732C2
+:10C8C000E724516CFDEEFDBE3FFDEC619FBDCF7EC8
+:10C8D000ACBDDE6BED3DE7CFD3BF2B09695D19BD64
+:10C8E00062A89E902D2B4DC314FA6CFD72DC4C5245
+:10C8F0004E4822D5E27F482264F54ADB3065182194
+:10C90000E779FB621B7DE92264AB129E4E9CF41911
+:10C9100051484B2121FB96C904CA4BB34C11236DDE
+:10C92000B2F4D5DF5D3D1CCA4B641FF1F67DAF7DCF
+:10C930003EBAD2330CC67F259D60BFFAA034ECD836
+:10C9400038FA6F25E809A41232A443391A3711FCCA
+:10C950003B4FFF2B6CA7E592BEB25E1FB0D9AC84F3
+:10C960001490A476743E8AA6AC771DB6074BA17FBF
+:10C9700005FBD7CE23AF99AE3FA95FA3C7A62AAFC9
+:10C98000969A4BC810FAA47305F8845D7264075D2B
+:10C9900067EEF2BB261CCB2024E7A0A58DC01A3A77
+:10C9A0001E24C44D880EC6A6EB5624BF97E808691E
+:10C9B0002B2CF349F479E8690B83539E15E16490BD
+:10C9C0007C99D7D0A7510ED8A07FFAE787FEEFCD8C
+:10C9D000B36C5F5B08C5A009E090BB9376984D8B64
+:10C9E000E1DC35FEA1749F28B8C904A8EF69F7D32C
+:10C9F000F5EF947ACBB5508E460CAC3D2131F8BFA3
+:10CA00005DB2C4EB895FF110F29424F1FA91B5356F
+:10CA1000B9B4BD621BA5F80899DD31BA5D7F39D480
+:10CA2000CBE27B3FA9A4EB83F17819E0F2C4015E6D
+:10CA30001FBEB4BD86CE6797418C4FC2D07E972C67
+:10CA4000B372B8BCBDE632DA5F35FF3E9CBFC69F0D
+:10CA50008BF3B9466727A4D97665BBF592BEF9B6C4
+:10CA6000D827B5B728849CF2C6D3E87691C6EDC71F
+:10CA7000DC8476B57A6630007024C44702A309F9D5
+:10CA80006FC98BF822F64FBFBB2A9C435F9D39F8D4
+:10CA9000455A297D8674F18329147E8D5D4193BEAC
+:10CAA00088C259EF0FE714F67DD7B87B1A095238C0
+:10CAB00085BACBF039C0778714F99FFACE64B88075
+:10CAC000F14EC5DE6C7A925635EA82EDD621D89EBB
+:10CAD000B0FD1F787DE2FB534FBE79238C77DA1BC4
+:10CAE000774F01BC8C51B80CF09D68DFD4554500E0
+:10CAF000EFFF62F1AFB48D27E4263BA333A234FBF2
+:10CB0000A07DD4D461F3D17AB3BE23E0A3EDE9567E
+:10CB100046E4CABEE72ADB506CAF7DAFA59FA8896B
+:10CB2000644CA5781D6E507C3B0894C329636879DA
+:10CB30005DA332AE854E6955D91FC69642F9192BB1
+:10CB400031D2726BC3014F29D091CF40287B21EBAA
+:10CB50002E8966011DB7351A663E42E7138D2DF505
+:10CB6000CC2BEDEBBFC54E098FCE7FCDCB94CE2E17
+:10CB7000A24F7DD42EC1F7C314027468B6D37DA62C
+:10CB800065739683840BA19D751DD0E31A7DB0B6A5
+:10CB90001ADA65C964071DD73C6C466D359D87C799
+:10CBA000254B3A9C47CD91F9B4BED56600CE467E62
+:10CBB0006B9FBD13E0F484E26B063A7CC26AB585D4
+:10CBC0006905E58D7EA05B6598330265A38E3447C9
+:10CBD000E9FC72CA48206AED9BE76F397FFCADCD56
+:10CBE00080F35D678E4EABA2FD5896CAB6301D6FBE
+:10CBF0004DE3869EC9749C9F363EFB460B7DBFD697
+:10CC0000AD109887D5A9C40C69148FAFA573A4F390
+:10CC10007EAA256003FE997029E4215A6F196A20C3
+:10CC2000DE243E682DA5E524FE94E154FC66FAFD61
+:10CC3000497BF0D7363AFEB8D70F9BE07BCF7859C7
+:10CC400006B2892A6C9FD3CAD5FDD82E53F7E3A824
+:10CC500051D73BA7AAEBDD33D4F59EDBD4E5ECB985
+:10CC6000EA722DE0DB786848E75C41D7C1AA8825E5
+:10CC7000FEC94A9286F0790BE06F29967D001F73FA
+:10CC8000E323C7E7D3FA1CE02774FE640C89ECA009
+:10CC9000FBB93FFF87DE3885B3D1D1ECB597F68776
+:10CCA000474E9EE91AD82FEB50C546687BEB1F4FC5
+:10CCB0007C09FD5B4952BB42808F3F0EFB0B7F1E00
+:10CCC0003A9F54F88717E0DDFCE7BB41EEBDA1F3C6
+:10CCD00001BC731A151CFFBE19DE88AE903527B44F
+:10CCE0007D1A6F9F665AD7A31B439F7F5CB34497FF
+:10CCF000D61FAE6ED22C015D52FC407941EA08CAC3
+:10CD00008B7B65520F7843C995407F36F880F29946
+:10CD1000890E03E2CDE71C7F28A6C950EFB6B13ECD
+:10CD20000D5973CD40CFF71C64F87F8F81F5D3DBAD
+:10CD30009F17074511047C52679755FD6CB0F1367B
+:10CD4000BCECB2B3F2AE038E6B802E37CC708C0588
+:10CD50003C31CA2408FDA5E79AFC23E8FACCAF1AB7
+:10CD6000C212ED345D2107F40EDADE426E0FD07987
+:10CD70006C3A6409EBE87BF3BC7FB711E01B7636B5
+:10CD8000EF5DAB7CBF033E90A853108E6657876D56
+:10CD90006C295B4398CECF01FFA0FCB16A58A70D68
+:10CDA000F6D35CD581F2DB5CD6D10170DA3455461E
+:10CDB0007DC23157467C36E745DF184ADFEBE7C9CD
+:10CDC00036E8CF4105BB8176F293DC8E4000FAA5B0
+:10CDD00030972B18AA40BFB8423A4E0687ABD3B95A
+:10CDE000FB0E89F69301FD8D61ED014E760EA75283
+:10CDF000BB17F1D3C9FBCD184ADB8F61FDB455F4E5
+:10CE0000F523F671532D89C0FCC4B8A29FDEFE89BC
+:10CE10005F02BEAAFF0D851BDD2729DF8493BB6758
+:10CE20001189180B013E81E6ED48D756F210D08BE0
+:10CE300033B71AF028FBD0E6E9F218F8CE82E3E81F
+:10CE4000E79108E071B6424C5738407F09201CB585
+:10CE5000F49A75A0E37A4A23BDFBA2A5DF2C85B422
+:10CE6000EB1CFDE938CBE9AC2E1E33003D6BE82509
+:10CE7000EB50E2FB80F45ABADE9672BA0CE04292B2
+:10CE8000DBEBBEBEACD345DF980C9B9549E50405B2
+:10CE90007DBE663C42FE6184B24464EFF921C0F776
+:10CEA000ED8C7F102AAF28B1EE1A6B9B68053A5DB6
+:10CEB0004210BFAA9F5B77CB6F687F6787196C2092
+:10CEC00057F20E75F4807C245DC1E1B00F5B94E0F5
+:10CED000CF5268FD96239904F8F61A339909F8ADF4
+:10CEE000703CD7CA97164E375E90739E7FFE29F42A
+:10CEF000C1E850F7281BA5BD96F5B14326D7FFA280
+:10CF00009E4586A19E957BA0A7C50AE377F8DB4DD9
+:10CF100014BEE6D759FB302D8715805F4301D0E161
+:10CF2000FEBCF90827E56D23013C1DADF347A04C7D
+:10CF3000DE3113E0BF3B9FB9ADDE0BFCC73DC50B37
+:10CF40007CE8DF81DE29BC3A38DD6BD7AF18FC41C5
+:10CF5000D027B4EFD7027C713F03C7EBE83E8E7E4B
+:10CF6000D840D6D2CA1279767B21D0C51ACA7F6939
+:10CF7000ED6C9DB7E94752DFFE3C61AE8AD8C1EE49
+:10CF800058692241235DD73989042971E639DFAC1C
+:10CF900002FE934F6212C8D9FC66AAF0025E2DB35E
+:10CFA000906012BEE79E53B0FD13667FC4CEF9BFFA
+:10CFB00089F2013DFB2779C21120754EC6A3407F3F
+:10CFC000D13F69790FF80671D6F87BED8D22C05FED
+:10CFD0002AF7E9784FF1F5EB290CF563E97F56392B
+:10CFE000661CD3BFFD2F397C14933506FC52B1BEAD
+:10CFF0007604F98B4D3999DCCE1461F2863490C8F1
+:10D000003089C105CBDFB3613987F25FE358D4FBC8
+:10D01000C34698671AB33F88DFEF75BA815E08028E
+:10D0200039D744DA4DB41D623BA5B72CD26346BD57
+:10D03000F900F1023D5088D93F4841964500AE5B6A
+:10D04000A8884EA603F12CB2B17D5296EBD05E1AA1
+:10D05000F59219E7A36F261133E84330370A6F655D
+:10D06000198928606F2D3760BB229B17BF339066EC
+:10D07000D4679FFAF2DD6CE0D39683541FBB08F6A9
+:10D0800059463E65B1A8E98F62287E17E7F8B17569
+:10D09000A50DF7B9D73E0B1EE6FB1C6F017991BFBA
+:10D0A000CCA1DA5FD12EF75C0E098E4BEE3782FDF4
+:10D0B000E50E3D209152A8CFC7FAAD2BBD5FD37FBF
+:10D0C000D120FD67211E0DDE7F2ED66F8D1DB65F30
+:10D0D0004741B12571C01EF0F6E9D75A38E72E5303
+:10D0E000F3E58BBAD4650117B3DEEF9C46616EFEA3
+:10D0F000BEECDB4EFBBBF888BA5D6DE1EFD1BEED57
+:10D100006B1F735E0FEDA9FDBD9DBEBDF4B8BA7D6A
+:10D11000A0EA653BD0715F7B36BF2BCFA9DB69F7F7
+:10D12000473B5F3A2FD70D49F39A6832AAEA67D690
+:10D13000F59B97EBA6A4795DE551B70FB60C3CAF14
+:10D140006B4A8C5F392FD1EE3B9517D64EBB8EEBD9
+:10D150006B8D83C09DB5BF69E685F57B6BFD57B7C9
+:10D16000BB7DB9769C30F2875AC93FCE41EB67C38D
+:10D170002BD017AD16D47BB5F812E1F26902E87333
+:10D18000F43935D53FC1419F954077F46978FC0F5C
+:10D19000B7007F39F4F4C84CE0EB3920E7109ECC9F
+:10D1A000AFB0ABC1837E8500A7532A4FDA805FEC16
+:10D1B000DA49BF4B63F34AD69F321A985D6123095F
+:10D1C000A467A12F39884D62F638D377061B47DB59
+:10D1D000FFDDDC1E98B37C22799FD2E1B3065B951C
+:10D1E00002F6D93609F58139357E5D2AC58F09EDFC
+:10D1F00012FA8DE6DCF9BD71C0572E39E6ED8AD3FF
+:10D20000F77322761F0CDBD443FC118A5799BA2599
+:10D210006577D3E703FBA9FEC3CB4B00DFAC7E2FC2
+:10D22000D81B753023DACF497D73990DF8E677ADB9
+:10D230007EE09B7533FC6FE17AFF4EB512DA6E1E0D
+:10D240005B3A79AE739AC14BF58CBADBBC95A0F70B
+:10D25000D445CD7E7C9A8862A1EBA8A3FA183C3312
+:10D260000D4431C3D3424CF0AC58C5F4AFB4CA80BE
+:10D27000A18E8E5FD7FDD85FE1BB054A6C1FD32717
+:10D2800023B8EEBAEE57FF06FADA3C7FC000FC6224
+:10D29000D44E03D349393E8C8EAACBC00F92CB65B6
+:10D2A000317579DC2175F92D07C38B3D526414EC7F
+:10D2B000CF1E2AE0C02E0E3F654479B17FAF11F733
+:10D2C00067F1C796EDE07F9AB8D88A7CFDE39F9B13
+:10D2D000D11FB5478E3E0DE5F0D3296857EF7B7B14
+:10D2E0004F8544CB8B7E912A43FD0B5FEA10CEB075
+:10D2F0001C3D7DBFF8E911DBD7D2F78BC7452B6CFE
+:10D30000F4FDB32309E9817A253206D6F7EC3F74A0
+:10D31000D87FE27163E4218A0F1F3FFFD8D377D112
+:10D32000F13F7E3CC721D17DB914E4016D37E16145
+:10D330009305EC8C091F3F3904F8C5E29D46D5BA28
+:10D34000B63A24AE3778D300DF06F3271E5DF31814
+:10D350007E5F72FC08E2DB1E7D58B6C0FAD730FC57
+:10D36000D2B67FC4C1E48D98077C5748F7E7CC0953
+:10D37000CBED7E5A1EBE510DDF111175F949079391
+:10D38000EFB349D2FB42E8AF68B507F4D4ED04F53A
+:10D390009992E37FBCA510F46823D31FB4F3788679
+:10D3A000CFE3E73FA7FD30FEA063FA335D31A5C7A9
+:10D3B000C51C8F5F9098FE4AFF96E550BC5D0C82BD
+:10D3C000BFA8EFFD62CD3C44FF4B1C8C6F38B95DAC
+:10D3D0009D785D87FBF1D1CAFA71C786F59FCF07AB
+:10D3E0002B9B47D4E8FBCAF3372E399845BF6BD83F
+:10D3F000E5423B51BC6F78FC25F7ADF4FDC99D8A31
+:10D400000F54D7869B1FFDF10468F7B82E0AF385E9
+:10D410007AF0479E8CBE9C06EDE66FB18FD525ED68
+:10D42000C3828DDF1F5193C40FBF293D08FA6DE001
+:10D43000F6ED73953D937300BF374A3E68B6387A70
+:10D44000C3F5D782AEB245E71B46EB2B1412D08D45
+:10D4500045D37B063C1B763D73309BD687F68EAF5B
+:10D460008075AD9503D78C06FCDFA6473F96162E38
+:10D47000A7F97ED3EF6332FD7EED8DD6FA8815FBDA
+:10D480003D00E5FD250FE9E2E067394EF9137B7FAA
+:10D4900044A63479BCFB9E31E04FDCA3B7B6039EB3
+:10D4A000EF4965FB107E4A877C9EC4D83A2670BF40
+:10D4B000F1E23F751A14FA3C7E7C555A15A323E419
+:10D4C0002FC0949D747DF50F8F46BA5BB0514D27E8
+:10D4D000A29D98EFC288BA5E8B1F6919C2DF404ACD
+:10D4E00092F14CDB2E636AD80074D5B09CF2E32431
+:10D4F000FDA7E1588701F426ED38A00112B1AF3A3B
+:10D50000C44FE2C5F59AD97AA9CA6AA2EBFD08FE12
+:10D51000C5FCDE12D8E58B245C22593C92D47829D4
+:10D520003C174F27B5F0DC23C57EACE3FC0CFDEFC8
+:10D530004FA5203F3B698B3FFA53C0BF27F37C6167
+:10D540005A95CDFD7227BDB134077D9E01BA00FC0E
+:10D55000B3B1F2A26ECACF297D7F7CCA807CBD2583
+:10D56000FA521AECD7C9A7CDB24CF7E5E35D19D54D
+:10D57000E0CF3919FD4D1AACEBA3684635F8E50646
+:10D58000E3375A3E25E4F97BF0CF4B287FCEF08F6E
+:10D59000C900F8B66580324E32339ACB9A07A07F25
+:10D5A000F19DD3D05CE605BEF15DAB0FE8F3D20C84
+:10D5B0002FBEAF93587FF0E7A7F59F1ECA7808F6F5
+:10D5C000FFD0BEE27490F39F126F3AF0DF29AEC035
+:10D5D0001519948F78AA7BFC3AF0FF4D21BE56FABC
+:10D5E000CDFB3ADF0F6C14CE7309953BF02C0F1A6C
+:10D5F000D05FD2E6C279CD51484CA1783A07E4E237
+:10D60000182C239CE76C9122AD741E73D7A9D739CF
+:10D61000BFD3D8B7BFF4BF8584324620A02D49EDD3
+:10D6200068FF0B41FE51F82D3291580AED77D12356
+:10D63000EAEF169318CEA7E1C9F3C681E0F8570EBA
+:10D64000C7292EFF4D192AFEA547FEB59804AE80C6
+:10D65000711773393BCFB80FE711BAF3CE1173A925
+:10D66000DE7066F95D23E666801F907D47364A8846
+:10D670007F8B6B482C8FCE6B71B7141B0D7AC061FA
+:10D68000B63FA27FB28DB5BB85EB29F3283C40EEB7
+:10D690004F78520AA7523B669E899A60C03FF8BAFB
+:10D6A000A03E9D96EB4907AEA791C4711EDFE3FB38
+:10D6B00007112980E75F0FB37D9B50BF5D07933A49
+:10D6C000B4AF221DF0EF33E2C3FDA3FA04313BFAFD
+:10D6D000E307C0DB9F049FFA2DEA327924A95C049A
+:10D6E000F0A4E5243837ED3E6FF40F00DF077AE54C
+:10D6F0004964C4B4D1A49FBEFA2E87FF0337CCCFB0
+:10D7000002FABF1FF4B76CDE4125F04B22FC113149
+:10D7100013EDDF328EA8FC13542FC272C74F5EB9CF
+:10D720007A632E211BF441F4F3CFD1050E4248EA6F
+:10D73000842BD809F83A47F6E72BC807FCC568A739
+:10D740002E67FBF1E0D8E611CD03D8A762FE1BA43B
+:10D75000684C067EF03C93EFA9E5097D3089BE9EBA
+:10D76000E6FC2D7D7FFC600EE0CD3312FAD3374905
+:10D77000A44DA270F6D06D0139B0497AEF20C88D62
+:10D780004D577B492BAD2FDF3D6DC9CB68E35A7CEC
+:10D79000109F68DC5DA56BB4E2FA999E99D2BC5DDE
+:10D7A000A6F599B7978C05FAA0EBBE7D3A7DFF2BC5
+:10D7B000BEDF5956860F9E55E1C2A5E04FDD1F58CA
+:10D7C000F232D0F5680BFAAD3229AC521DF86C0775
+:10D7D000FDD1435A2468F7401AEBDF25EB6E9F0614
+:10D7E000E5B1ACEC5821F91F42245E8FFD671AA900
+:10D7F000C9E060EF410FA6DDF977617D04F72D7375
+:10D80000627319F49739843D9D86582EF4F39AD8A3
+:10D81000EFEE2C19F8ED322E3797EDAACA74D0EF3F
+:10D820005F3B6952800FBEE6117A5CCC0A7A1C1904
+:10D830005AC2DA73F9B4AC6C6226E0AF335FDDEE46
+:10D840008CDE9F3E0EF8FC1B3A8CB7FCC5EA4FB746
+:10D85000D376971AD83AB4FBF8A70CA6D785CE4949
+:10D86000249264B787669E45FD38744E51BD3FB91A
+:10D87000D2442249767B43FDFEC9D0AE91F4AC067A
+:10D88000BC6A8CA69048129E5F6A19785C81DFA101
+:10D89000733A121E87E89B0BFEC5D7F489D5F300B7
+:10D8A0009FF64AE8070A517B389C3CAF7319249CC9
+:10D8B00031D03CDDEAF7743DAA72D7E7D88E54C662
+:10D8C000D3609CD3B6789A9DAF0FDA09B97526223A
+:10D8D00087F517617C8FC92FF0CF58997E3A0DF6E6
+:10D8E0005749A44D4FEDEB57D4437F8EA4759E9EB0
+:10D8F000692031DC97048E0B700B0F276473F727B8
+:10D90000062FC8F1EE7D0837812FC9F00B27C77BA2
+:10D910005A7B6232A5F9CC4ECBDAD21114F5F673EC
+:10D92000FA0E5BD7827FD1AD9355F49E52DE4BFF4A
+:10D93000C86E1E80E813FA2F53D7429CB9B7CCDBD0
+:10D94000F77E1F4E9B02F5E5A5ECFBC2CEF4FF5817
+:10D950000532887430BD5F49E4075293CA264DD919
+:10D960004ACBA393CA364DBD5353EFD1947359FBA1
+:10D9700093A9B17C9D8FDAB99D195314CA7F4E6665
+:10D98000C566514B94ACD3B9A7D4D072633993AB6D
+:10D990004DDD920F7D6E1C7E4D3EA6EF597D71C30D
+:10D9A0009C528043CF41E00F0D5D924DA274608D7B
+:10D9B000EE8A6119BEF3267D1795F0BB86E87BF8E9
+:10D9C000DDA0FD97C848E76B4B8EB276D10F517E34
+:10D9D000AF6EABC3B8B888FBEA48C09F23F5C57DDE
+:10D9E000059F3C9DE57F4966786D4BB68342D06FBD
+:10D9F00092BF45B47F6774F7EF413D4859F6490B34
+:10DA0000E8A17F6AFC703CE865EF7079B0418A8CD0
+:10DA100080713793E0089077DF6D1CB64FA6EDDE7E
+:10DA2000D5C7B7426C6B71E7A8290A6DF76E6A3CDF
+:10DA30004FA23CA6D15981F07CD715DF0AF07CC9F2
+:10DA400079312BE7C5F3645A5ED259C7DA0F8B6F71
+:10DA500085F226E7B5AC3C3A9EA7B38189731DC217
+:10DA60007F876D607A9EED647C44CCAFABC8FF5D70
+:10DA700027ACA781C991AD546F34517E396BD14722
+:10DA80004FEDA07098F5C314E4633B4E5E3F85E90B
+:10DA9000D5E18052017E53F687720EF9B5827A463F
+:10DAA00016C83647DF7EA4E6F778510E8C6CDE058B
+:10DAB000FA42E6AC529403A519FE0330AE78CECB01
+:10DAC000A64F0ACF034E1BE3CB3A19E3C89977A5BB
+:10DAD000A25E75BF99AD87D20DEEAF95EFC71D4E13
+:10DAE00026B7EE7032BBED868C49D8CFDB927F93A0
+:10DAF00089C2FD6D3D099B81CF2EB4A01E7CEB76C3
+:10DB0000CA3728DFEEE4F3EE5C9F158138F8AD12DA
+:10DB100009005F11FCA3D3EECF7224D9139D65B425
+:10DB20006CEDB31F3BA7F9B32C4E78BA6588970804
+:10DB3000BED459C8BE13F228B3958D9379FF888758
+:10DB4000601D290AF3FBCC9B59FC500BCAF5E9B8C0
+:10DB50007EE2F76781FFE0D8C22219FC41627FDED6
+:10DB60002AF2AF87F5DCC2FDE9629FC47E1E7032E7
+:10DB70007B788E8EEA0574BDFB5C415C3FD513C695
+:10DB800070BF13EA0907404627C19728F1F1F0FE5C
+:10DB9000FF23383DFB6DC0A97139E517F205F00B85
+:10DBA0000EBF0D524C9FC9F805DAC1F01EE4CEA697
+:10DBB0008CE07F3893F25266DDD5887AA19857CAF7
+:10DBC0001DCFD5DE44FAD399566F3B0CFBE5EAD363
+:10DBD0002F7DC27FC8C779F76D13C60BDE35449120
+:10DBE0006FBE4BED9816E02F3CDE5DF1C3C5AF81F3
+:10DBF0001D27FA9DE0D2617F6B247F16AC6F0DDD8F
+:10DC00007713CC7F9A01F57821573BED914D906FBA
+:10DC1000D079432EE61B9C212CAF23BC3C05DB5D59
+:10DC20002A1F25E08F4C5C62C37833C513ACEFBC70
+:10DC3000B918F33E283E84CD504FF109F2E33ACBB8
+:10DC4000E882A0BF9B47623DD8B9689FDE6CC2FEE8
+:10DC500006C013E6DF1DCEF21A3A0B391E2E2C42F7
+:10DC60003C74B7323F2251FC63A625C979B78BF1CA
+:10DC70008194F2F833FF0538BFCE8C7A29C8588CCE
+:10DC8000C57464627F74FFCF3B597C0BF16CEE8FDF
+:10DC900053791E99AF02E07A6F2AC3CB2D661627FF
+:10DCA000DA42F560E48B1C7F45FE5A90EB79F17AFD
+:10DCB000390DF4855457AF9FC00F763BFAA969FD23
+:10DCC000ECB8F41ED85DB3C3BA9811ECA8F649FEBF
+:10DCD00078921D027F1067BB9DF355B291A0FFEEB5
+:10DCE00076F82E0DFAB7A4415CF176F81EFCA42B51
+:10DCF00026A9E2670530E6F8BEF969F97E819857F2
+:10DD0000C783FEE47144FFDAFEA81DE975B910CEA1
+:10DD1000B174B0075A74B88FDA79C637327F737C22
+:10DD20006301E29DE86FB079FE5997F8BE44E5E0E3
+:10DD3000FC89CCBE16F6CB3C6EFF92156AFB0CFC40
+:10DD400023BD655DFFB2D6DE83B8B8BA3DD35B5262
+:10DD50004A13068C977825D5FC05BC0683C3E46F6F
+:10DD6000083721F71E34537EEA00335A42BCDD786F
+:10DD7000670ACA31A7213202F06A9ACB8BFD6E8600
+:10DD8000FC1494ABCCEEFDEC35E1AF50DBBB214B8A
+:10DD9000621BC02B646174747A6F2AD201191A9FB6
+:10DDA00005F95D67F61809E06F93142F06BA3E2D4A
+:10DDB000F9EBB05D4B8A17E8E97DB907E11D020870
+:10DDC000D27985C2FF837945A12EB5FD7B9AFE5796
+:10DDD0004FF1FDB41CAF807E043F00FA47BDA89E02
+:10DDE000C55B9A641206BBEA5279F64294FF376724
+:10DDF0009387F0FD7BC56047093E4FDB1D901C0CEF
+:10DE00006D805E1A38FC9AE4A3D8AE01F283008ECE
+:10DE1000605F815F0B2A93FCB14DEB3EC6FCA4A66C
+:10DE2000DDEA7D6EE8C303E9BC04DF25E105D271BC
+:10DE300098F301C2FC14352C5E9CCACB29B53D98E1
+:10DE4000AF14E27E0BD7FEF864E027A9E551329BC0
+:10DE50003E43C7999E31A17BFB4B600FDB6B7BF28E
+:10DE600000FD43DCAF27F659CCF392EEF5E8A7109E
+:10DE7000FA49929D3962BACA5FB00ABF03BB15C6A0
+:10DE80008BC3AB2CD87E26D73670B946E51FF2D7A8
+:10DE9000791DC351FE817C02BE24EC5EE053C01F9D
+:10DEA0004EB8AAB7009DB6B8AB1F74B9D878A8CF42
+:10DEB00083B174C9E0FE38011FD10EECDFAFF2B7B9
+:10DEC0003DC6F1D569E07C9730FFDAD2575DC2BF1D
+:10DED0008671B4A5923713F0F5035D10FD680B4809
+:10DEE00018FD3B0BC17F459F0D9CCEE773BFD07CD7
+:10DEF000EE0F02FF6C72BC0FFCA4C9E54584E12F54
+:10DF0000D969ECCB8301FF4D0D89A5D2FE1AC1BFA3
+:10DF100004CFA8FABB26926078DF75DEA88A277640
+:10DF2000B275DFCEF7DF5E13D1017FD864667E2540
+:10DF3000C13726AC60FEA7F4B1FEC27B00CF5FD52F
+:10DF4000A35FE2BFF9BE09384D71556F77D1F61660
+:10DF5000B0D3A0DD3D46E497C7A81CDEC5FD21D3A4
+:10DF6000C1FE5C191C0179DC44B1E527DBA7E2B9ED
+:10DF7000768FB91EF0E74D97ACC2AFD52E9677835A
+:10DF80007E22E4C729A86F53B63106F0ABA248C879
+:10DF9000433206FC53EFE9993FB7E9466B10FA8B21
+:10DFA000CB8CCFFC99F3B33FBB58DEE59F7BE515E7
+:10DFB000B7EF38FE88381DF86B92FDE41FF4B65FAA
+:10DFC000CFF36309AE77C3429E87DD8BC732F2A3DE
+:10DFD00094D200F2DD4BE56AE4478913562FC0A5C1
+:10DFE000F6E38685B08E4F675A08C4CBE672BFED64
+:10DFF0005948B873F5F969BF2E8E55BB7604F249BE
+:10E00000D1FE6F3027577F7FEF1ECEC7F61036DF69
+:10E01000709B91F9D7F9FCF71C1F19013CA67A6D8A
+:10E0200018F85C629799C93BAA87027FDDB37B78B9
+:10E0300004D6F39E9EE90B61CA7FD9F7C14DE00774
+:10E04000D9F34B970FF273428B3E1A03FAE39EE328
+:10E050003FFFD56FE1FD5EA30FECBD3DDCBFDE6091
+:10E060008815A3BECCF3121BD262C5E0F77981EF0D
+:10E07000578385964B4179083ADCAEBE38187C0749
+:10E08000EF8F46985E7E94303C08AF63F14A0ADF1A
+:10E090002C9847624D26C6D1605DB00FEFEF1D8D05
+:10E0A000F3DEA0E7EDEF63FADB515E3EFA7C19E6A2
+:10E0B000E99D091830AF36743FD317E7C8DE6DCB42
+:10E0C0008157BE9882FEC2799D6F605C23F4E305A0
+:10E0D00053A13EB468C575E42BFCFD205792FDD4D6
+:10E0E000A749221FEDE0FAA2688C8E7BBA7B848F51
+:10E0F00085ED3C18246AE2F99BC7287C61DE89BD66
+:10E100007A84FF85F60FEB05BB14E41BFAB593E3A5
+:10E110002A280FD47196AF2B9FD6C78BEFA4E3AFFD
+:10E1200070046BDC497A62E8C52CE477EFDFF7799D
+:10E130003EEA131D2C2E704CEF9F057462AF8919B7
+:10E140006627E95FB7B9B9DD61E47A23E583C9746D
+:10E150002FEA2BAAD574269EB7BA19BDA5F2387E30
+:10E16000FF7A91BF7ABD11E427732941BF5EECB7F6
+:10E1700080C7D7261C4FEC837CA8866819C6EF0A97
+:10E1800056C4902E29BC63A0FF1FDB94CAF8095D1A
+:10E1900026F433BF92A0DE3A5FC7F212E61BA91E37
+:10E1A000CCE438B6FF605326C2A16215D3FF12CF6C
+:10E1B00048C817459CB18EB0EF9F6B7B2FACA3ED89
+:10E1C000EB764A6594B592BAB62ACC5B58B4A510E2
+:10E1D000F77F02E7BF738CFEE24D806FCFA522BEB2
+:10E1E000D1F150DF6E80DCACB1C8970C200FEB771B
+:10E1F0004A642D498E8B6AF020A28EAB4C8832FE89
+:10E200000D728324E969420E81BC201AFD518D17DD
+:10E210006195DC6BE77015FC1F21F6157290EAD151
+:10E220006B808E2BAA19BD25764908E746D2CCE231
+:10E23000405C0EF5CE87CBB10F744C6ECE37AEC7B7
+:10E24000E73677218EBB08E225E8FF4F18802F0EB6
+:10E250008617DB06C10B810F3FE3EB68384E6297F0
+:10E26000D3F11A569058E318F64C1D837299C9677A
+:10E270001393CFF0B45C809CD6CA67AD3CD6CAE19C
+:10E280004C0393B7020F92FDF2A08F4C5811D1317D
+:10E29000FF6BAE0DF2F1C4BEDC90E17F227B7C9F70
+:10E2A000BE153A6232792F8272801459C1AF54552B
+:10E2B000914BD71FA2FC1BE82E85C2693B7DBF9501
+:10E2C000EBE54372BD081F0FCFBBD12B0152668512
+:10E2D0007DEA413B3AE12268D70AF86E4DA5DF8D11
+:10E2E00085EF183DF67E6F226D96A4EFABF798513F
+:10E2F0009E9C7D3E15F344A87C28B0D3FEDCEF50F5
+:10E30000FD9C964FEF4945F97E9AF37BA7F0579015
+:10E31000D5D8DF9BB0CF2EC0BAEA1CF0FB12694AF9
+:10E320000EB048A13736DA07F3D3F3FAC29E1B19B1
+:10E330009E1951CE9EB5C77F00653A1FCCEBFD0FED
+:10E34000BEEFA1DD13CBEE82787EC0EA63500D965E
+:10E3500081DE60D42DBB11FC4193752B1277D275F1
+:10E3600034E659315FB8A6E08F7FB899964FECD666
+:10E370001323ECFB8EEBD363F099E2F70C249F1789
+:10E3800046F4AAF3688B77AACB8D5175394492CEA7
+:10E39000AB51102CFF63D9150792F0E43377AA1321
+:10E3A000F7DF4B7C90EF4C74B7A50707E097E2F9D5
+:10E3B000F94ADF1507F4982FF6851BE9C06B00BDFD
+:10E3C0006636E0C300DFED7233BFA8D1D87C1CF203
+:10E3D000CE8D2F187D2DF4AB83EEA02ED305F64AFB
+:10E3E000E220ECA7B1E0E4189083D5057FC738D8C8
+:10E3F000D9BB890FE073D65C85FACDD94D662FD88D
+:10E40000659DF956E6AF78518A484C7F9F3ABE0227
+:10E41000E29EB80612DA78F5097648829864DC5FE5
+:10E420006ABD7880CFF8D19EFA609AC5B68A7E57C9
+:10E43000BF91C9DB06D293067CA03693E15D48F715
+:10E44000A4C144FF59D8E61FD142E7BB3860C1F3ED
+:10E4500031CA974A00F0EB5EE83249FF2FC8647278
+:10E46000A6D1143754C1F87F9F5BEB2AEAF36F19EA
+:10E47000F4CCBFA57495C572E8A70B96CF413BA716
+:10E48000378EBC89E5252DB8B30EDFBFB4C988EB44
+:10E49000FB60AF8478FEC156B6FE051BCD5EC89FFB
+:10E4A000BED2CEECD905F4BB81D77FD50958D7872A
+:10E4B0005BEEF0817FFE43C2C609DB981FEA431B77
+:10E4C0008B77435BE8E7C3DD43508FA9DFB8702A41
+:10E4D000E68B6DD5F9408F207B53D1BFB360EBF74E
+:10E4E0007F7B09F88FA6DF520E70B8D2BECC0DFE2E
+:10E4F00012DA2E10617A31CBC375543E0A7478E576
+:10E5000097137BAE047D692BA5934296E70E7AFAAA
+:10E5100081AD57A15EBA609AC50EEBF26ED9311982
+:10E52000E4C787D3B2655CCF5312B1011CECCBDDDD
+:10E53000F07E81A40406C2A777DDCCCF565560F5E6
+:10E54000C5E0BBDFEB104F285DDD08F2B371AB1EF9
+:10E55000F5DE03D3DFFEC3CDCE3EBA5AA0EBB871D1
+:10E560004292DE13DA72ADC01312AB007B8AC14453
+:10E570004B5FC68215C5301F2D9D2D58D55CCCE252
+:10E5800055DF8CDEC8164A6FA3A8BCCE94985FE313
+:10E59000C2E9AD3EF31BD01BC975A8ECA8FE7C2DCB
+:10E5A0008C7014FE7E938FF8775831AEEB9728DF8E
+:10E5B0005D9FA9603FEB33D9B920E56F4B77BE4E25
+:10E5C000E1E3CE0CFE3013F41FE22F033CF2266C85
+:10E5D000D570E6C7CAF538B285E9CDA0DFC37E6F36
+:10E5E000709147D726F91DEECB64F611A5FF56E8CA
+:10E5F000E7F45B7F3F08FBD3947F720C8B77FE05BB
+:10E60000E383D66E1657B6FA121837D73B03887FC6
+:10E6100082AF877C4CEE68D7753893D97321670237
+:10E62000FBF98587D1A1F0B76F5E6E413FE9666760
+:10E63000C4CCFC0A610272696AA58EC5C5B89E7514
+:10E640002DF73F9ACA5F22100F2397B1FCADD7CBAD
+:10E650005F523268F9B795937C786EAEFCE1F62292
+:10E6600058F7657A5E3F240CEBFE4F7F15D62FF5E9
+:10E67000E8BC40D753CB591E22A94F437FC9EBE5D5
+:10E68000EF3BE726CD3F404C5E2BC593E9D4C8490C
+:10E69000CE9BBBEE32B3D79A845F9F7648B54CDFF2
+:10E6A000F5A6CF18CDFC212887CBD5F058EA31E06C
+:10E6B000B82DEEAAA701CE575EC1F6E3A3A78C1131
+:10E6C000E07F1FF173285AF8EDCDE476E86D25AAB6
+:10E6D000F8BCD310CD07F9F8B1A4FE6E51BB0EE320
+:10E6E000E30BDB2512A1E37DF4F873F9C0C74FEC0F
+:10E6F000782E7F76D27CB4DF89E72B991C5FB91F17
+:10E7000050EBD71DCC9F2BDA9DD94882A6217DEDF9
+:10E71000CFD47F81FEDCD9DDDC1FECF70F75821DC5
+:10E72000C4DB6BFB4B70FC90BA24F477087FE6D116
+:10E73000430F43E4A477FFCCDD857272DEA1784EEF
+:10E74000E0FB763DEC1B5D8AB99D9507DBAFC1E828
+:10E75000711DC89FF17DFB76B47D483AC0D1D0646D
+:10E7600055083B0F56027AFA5662F1013D19B23D47
+:10E7700056E05FCB4D6963E09CCFE766F6745AE8DC
+:10E7800093EA6B79D925F8DD1D7200F3DB3E973BE8
+:10E79000F03CE01DBA66CC9BFE8CCBBB5C5B60D7CB
+:10E7A0007CB44FA298474DDAD5F075B732F991A8ED
+:10E7B00033A09C1270BE74F60FD04E1D607F3602DF
+:10E7C000DE6457B277A59E42AE2FC7314E60AE24AD
+:10E7D00036B0E75B2F09E37CC4FE84587322754B87
+:10E7E000A827437E4A8A03E3A161FE245607E98DE8
+:10E7F0000FA470BB9668E201946D85A19D9827B027
+:10E8000031C873B9DF1EED282EC7782AEA9FD02FB2
+:10E81000BC9F5DAAA03F1DDA19C67E3DBEF5E2256C
+:10E82000CF179C2ADED75B068C3F4C857337B47DAF
+:10E830001E9583A0FF119F5E75EE660BD59BC11ED2
+:10E8400013F15D9D1C2DF3A01DD21307FF88A1C2FB
+:10E85000E405B99AA28B96C0BE69E3BDB45D21CB35
+:10E8600033C8B5835C11E76A9A964F0C40DE7AAFE5
+:10E870009EB197D9474D7756E1FB89DDCC7F1E6A63
+:10E8800037E2B9C0509784F1AAA6802162423F8640
+:10E89000B705F62B4CF530B01B3BED2CCFA9F36A36
+:10E8A0009B2F4C92FDD7F16D77A1FFDA8A71BA7F69
+:10E8B000367E79269502E0A2A4F854BA89C911EEF1
+:10E8C000DF76737C12FB2FE859C43B534B0385A0C2
+:10E8D00071EF76DFFE1BCBF86F901742C6DEF7951F
+:10E8E000792164EFB570AECD04DA3CAF876951B9D8
+:10E8F000D97B4ECEECC5B8566F3DDC6F60EA92F81E
+:10E90000F78BAE9DA4601E282F57AE83BCEEFBCDC7
+:10E9100044355EF2FC144DFF7ADABFD5CBDB876F4E
+:10E92000BE66D2508CEFF272D78FFC747EF7EBD5B7
+:10E93000FD210A8A737DA6BEF12A72E4FBD65DD65C
+:10E9400027BFA93C5FE671F5C9F17BDF9EDA7191C3
+:10E9500017E8EB33CCAB15F238E46479225ABEB534
+:10E96000D22309FD773288D8D533EBF03E80DEF82C
+:10E970006EF7343FDC8B20E2BBA11501CCAF05F96B
+:10E98000EF41F97FF2837D04F4CB8F50FF0F9D534D
+:10E99000983F88EA1112C543537715FA3D216D144B
+:10E9A000E4A6D8FF455C2E81AE0EF81DDA72D30EB8
+:10E9B0001DAD7FC7E35F87FD723B503BDF1D1E66C9
+:10E9C000BF874AAA37013F208F4804E4F6DA924F06
+:10E9D00051CF687A7ED2F8E4FCF0855D0FB0FCE29E
+:10E9E0009DFA01D7BFC3A363F931CF3F83FECC8F1C
+:10E9F00022EC584ABD12593301FC2AF532685AA458
+:10EA00003C527733CAFF99741D745D3FE27227B49C
+:10EA1000F3FA30E4AB87E87F00B2CD81F9A8EF6F5D
+:10EA20009E69B242BC2654327B09D283CDE287F57F
+:10EA30006BE7D91B1FBED382FEC6B55DFA5AD09BC9
+:10EA40002AA89EF42B3ADF3CC7945A1FE54B39BAEB
+:10EA50005D65DFB3425C7D60395C9DCDF6B14D0AEA
+:10EA600084BF538EF98C24394FA7A08BE963DD1E38
+:10EA700083EA5E886E0FD3132F0BF74C049C7B51F7
+:10EA800089A7805E1C22FE4FC0CE2501AB17FA81FC
+:10EA90001B1540CF72AEF4A23FD7E48CFFE822D41E
+:10EAA0009B14B433841D71FA79E6FF1A9E157C1508
+:10EAB000F0B24217FFC977006E3F62E77589C2F86E
+:10EAC0004DFEF5D6B1E0AF323BE33FA9F5627E0DD6
+:10EAD000FA1FD22F6FC37D78D1496C009F89E13A2C
+:10EAE000454A9233826F4CEC3D17E3443F693567EA
+:10EAF0002FC3E86E7D6042146D3B9FD1A7171CFAAF
+:10EB0000FB0C055E0A7D413605D19EA99949ED436E
+:10EB1000C0CBD5898332F8E59D3DA82F3646251C0C
+:10EB2000A7B1E49798FFB698E759F5E63B2971CC71
+:10EB3000FF7ADF93C2E3036D4C6F253D68FF922798
+:10EB400019FCA9DCC4BCB03EBDBD05DB89FE0C3C94
+:10EB50009ED0C8FD351450587FDA23E209AB78FF08
+:10EB6000228F8D8D4B146F45B27F61C3342A49705B
+:10EB70005EDE3498EF13E6C0E7404747EB65E6CF2B
+:10EB80006E4F89C021CF0D528F1FFC8EE1B281CF15
+:10EB9000B358B3181EA5EF4F4C467FFFF383E5BB78
+:10EBA000B2FCD64DE347627E7879D72793013F4880
+:10EBB0002D417AA4FCE282F25DED595E1CEF5BCF41
+:10EBC00077F549FE87E83327CBAECE77F531B88BA2
+:10EBD00038A436CFF574564C617969F16D3B407EAF
+:10EBE000761931DF6D6AD72B47C00F39D544A2188B
+:10EBF00097D5E8012F665C3F348BAEE3CCA90FB606
+:10EC0000DD4320DFF9591FCB9F53CBF5C1F4788C3E
+:10EC10004D24D97B157C1FBE2D3D5EF0DD10B78BDA
+:10EC20003E96123F2E86F5EDD5D9063AA732314BE6
+:10EC3000E0DF20F91ADD03E76B887350B5F1425528
+:10EC40009CE95AB19E6F18B70A802F7980B895C297
+:10EC5000F3B01489B100926750C5AD147BF16071B7
+:10EC6000AB18D63F331CEBEFED17B762F9016D7BA4
+:10EC700033BDA0A737B8128F3EEA85FE0CD84FDB14
+:10EC8000F32911C83B6FE3F06FB8F0B8D5C2AC01FF
+:10EC9000E256DBB91EF67E891C3350B86E276CFE37
+:10ECA000E16E11BF92D11E4DDC9727E68FF567EE1E
+:10ECB0001B857E9F39222EF522F387CDE1F1A7F740
+:10ECC000A71763BED660709ED3AEF6EFDFC5E17CBA
+:10ECD000D65C857EF51FFCFB34F433CD077FFC90BA
+:10ECE000BE730984FBE5BCEDECBCB977A714F1B2A7
+:10ECF000F88849461DCF26C3FBC5941D6E06161A1B
+:10ED0000A65873317D2D51A8D17A6F1B2D53E55D27
+:10ED100059A3843DB4DDF62329E807BBD7E9C5F93B
+:10ED2000DEDBC6E2C4E175526418EB17EFF10AB7F7
+:10ED3000C97EE8E7A7594C5EFF2A8BF921BC9AFBF4
+:10ED400001DAF43CDECBC76B21720C9EB2C49EF795
+:10ED5000DA94DA81F400D15F9BBED95405F0CE631A
+:10ED6000F7859C35F867A29FD8518CF702B5A53678
+:10ED7000B7D7B27AA4D9B3E64400EB2F57986249CB
+:10ED8000BC0E98EFFA2CA6A768E13CAF435DD6C64F
+:10ED900069B4E7A0E690E0F0AC21FDCF09ADCF6209
+:10EDA00072ECECDA42BE2F3E8C7BB4E9BD6F1602EA
+:10EDB000BEAF61F7FEB4E432B8C979EC5964AFC1B3
+:10EDC000FBD9889DEB6384CDBFE872A704F4D066BD
+:10EDD0006778FBAFCE5B3BDF17B28A197CED8C5EA8
+:10EDE000DBD64811062F36EF0BF56FBC25F8D2B7EE
+:10EDF000C417DF977C8FC60AF13BE40BE1FBF448B4
+:10EE00007747492487E53FDA906FCEE6F6EA512E40
+:10EE1000AF36D717A5413C73CEF1D5787FCFC4EB81
+:10EE2000AD38FFA617CD688F35AE88E7033E6BE19E
+:10EE300008B355043F9521EF98B07B5FDAD5F139DF
+:10EE40006DDC7585239000F9D2541D2F86F8CF0311
+:10EE5000F2FBBB5E617C0DE563D38AC4A3E02F0E99
+:10EE600038829F43BB9377BE3D59F2E2E7C8DFCEBD
+:10EE7000EC1D8EE7FD66B7A9CF4F9175EAF81F69C3
+:10EE800077B073629DEAF7705E48F55DBF7820D376
+:10EE90004F36188223407FBCF20A96EF706AA14C6D
+:10EEA000603F4F99098FB30B3EEB2B4E9603CEEC90
+:10EEB000C1E41D6D0770E6F99DA27D23EC2BDDCF2B
+:10EEC00006BEAFA79EB9B818F6F5E4AE8B8B615FAE
+:10EED00037E83BFC4017275C414F36C597639302E8
+:10EEE000A8DF897CD60BC5B7E183CEEB7F470E97B1
+:10EEF00067FF737218FE92FD1E2FFE9DE59D86BB77
+:10EF0000D979D13E7FDB4778EFD59973B2047C780D
+:10EF1000B0FE5EF730BCF7984818FC1C15D571FCA4
+:10EF2000AEE20B99803E27F458EDFCAFE2F09B99DE
+:10EF3000EDFF15E8A3C23F5BCFFB36453E63FAF217
+:10EF40002312FA5F4DDE70DA04B48FE68DD3215FB1
+:10EF5000F9159E6720DD920DEC8C858FB460FDE97C
+:10EF6000AE39582F9B6231B0A71A693D94575FA6FE
+:10EF7000CE4FD6EF2E8B25DBAF741EBF00BB24C552
+:10EF80009930007E36817E4CA7D8A4303F7593938C
+:10EF9000A07FA4BC4B6DEF89F8EBE600BB5765730F
+:10EFA000B784F72BB90DC1C25CD8574D1C765EB63D
+:10EFB000BF0DF04EC4C3A7B8FC0BB259BC3C1FE058
+:10EFC000D494CDE617D78BF373EAF37D87F6DD880B
+:10EFD0007AD05F49207DE0BCB1882A4E3E9F9FBF1A
+:10EFE0009CCFCF5F027F8E69F87372B921296F2C95
+:10EFF0003650FC3F296F2CF9BBE4BCB1988AAF7541
+:10F00000F0F3094B313E1DA278BE7C6C1F1E3610FA
+:10F01000FEB731F13E9E4FD96944BF5803CF170D5B
+:10F02000D51F457B2304E75D183DB2BC6A7EEF40E7
+:10F0300003B5E3306F36AACE2BFD69F6B72B0F442C
+:10F04000BBC1FCDD8F0A7EC0E951AC4BACA3A15B18
+:10F0500062F4A399A7D67ED5FAAD85FD79A17C6926
+:10F06000CFB7BCEE6FCA975EF996F8523FFFFFD05C
+:10F07000449AEF5BF0FF9FF076B8C125D82E317C23
+:10F080009DACB3FA597C51C7F20FB47157EF648C41
+:10F09000270A7FABE9595D645521B6C7786AE3DE7C
+:10F0A00054CC07A8F7D6A39EAD8D332E22BB26C322
+:10F0B00016FC95BC86E7AAFED5B8FEE9ECDEB87E64
+:10F0C000E1378CEBFF35FB1BC4195FB27E96114C08
+:10F0D000C293EA52AAB0970E9E77A5CB61FB9EC25F
+:10F0E000F33F4C4A98D893BE1FECBB941C16677F25
+:10F0F00089E70BDD9F9A82E7E83D06768EC023B351
+:10F10000BCA677A8B69FE30239C0F6F167CFDF440B
+:10F11000204FF067FA289E6B0F375A7D20BF84BFBF
+:10F1200048F4DFCCFD98174A3F4539FFBB7CA33438
+:10F1300047FA6671B28D14064974A5A583C1BE1B3A
+:10F140008CAF5C9E13A8CC41BEE51F83F1860BE417
+:10F150004729E5945F837CDE6DF482BD60E2E75D64
+:10F16000C8BA2C95BD3DE7FE3C945BA7CCCC7E1085
+:10F17000E772C4FA0383C2FB9FD3EFF6B902D3014F
+:10F180004F8E55F931AFFFDE542657128FB3FC1E58
+:10F19000EDF914AD3C11E72BC47873C5FEFC1FF1EB
+:10F1A000D325023EFF223FA5F215FD2B83C653FB5C
+:10F1B0007D1F66F79154F7F8799C09CF2B887985E4
+:10F1C0007A585E5C0B9F5F2FBC38FF3F98E35F056A
+:10F1D000FB70F22D9309E297E5E58C7F3605ACE8EC
+:10F1E000FF6F8AB27C98A61504ED7C710ED59D192F
+:10F1F0005C07F878EFDB56BC07B4A96B7B7B11E6A4
+:10F20000090451AF3BFD167B7FD01DEC80FE432BE4
+:10F21000E2AA3843C5F9CF56D796E37CD14E771A88
+:10F22000D5E77B7E99C3EC6FF1FC452F7CA95D424D
+:10F23000BF3B59CFF2B0434EBFAD0AF303981F3B1B
+:10F24000C5DB83FEE7A6DD282408268542FD5DB9DF
+:10F2500088374DBBABCAF05C7FD45C86F7C1BC631A
+:10F2600045FBEAE49DD9111DF37B3F06EB4A2D8F48
+:10F270005C0DFA65011D07FCD827775D5D86FE40B1
+:10F280000DDD097AEB3DD779AB29D22AF5D1E3061A
+:10F290003D938F42AE3D08CA2CE647F0FCBEEE69B6
+:10F2A000649EB5AF6C75AAF31E67664F7A10E6F3DD
+:10F2B000608EC2E3D32C1E5E68A2D667517F3C2CC1
+:10F2C000E4F1F0693C8F81844D7DF90B455F1F0FA0
+:10F2D00017F31365110F4F39C7F4DB229B01F1229D
+:10F2E000B59DF10D42F102F4EBCB123D13E13CD59B
+:10F2F000D0CED86500AF74003FE691C67F7411C4CC
+:10F300001D3294CB20EEB06DF9D8FD2627F88F7A08
+:10F310002E87ADF176D8AAC1B47467060E039E108D
+:10F32000A5B904F0BFFAF77A966FB82605E57D67B0
+:10F330007E03E61B9E7EDBA83A47A37D86C92A0F83
+:10F34000F8898ADA7F877EFFD4DDD28079A419A07C
+:10F35000F48F67EDC1EF94DADE13AE043FCA7D127D
+:10F36000BB4B91CE5EF280FDAFC8A077CCE962E7DF
+:10F37000B1E774D8AB4DC84F251637B9CC897C524C
+:10F3800059738D0CF699D242F0DE324B2EF35B0F9F
+:10F39000EBB4C9B0EFBFFE5237603CEC6F1CBF212D
+:10F3A0007F0DC0D5684C1C8490BD88E389BCB5C175
+:10F3B000EE0317F248ABC7F6D35FB93CEAD5E335A5
+:10F3C000783CD87702BF053EFF5A4F500FFBB5641B
+:10F3D000C2735A02AFDB441EFE97CC8F5BC0F36250
+:10F3E0008EAEFD9F31EC3E3F110789B07B25F5F1D4
+:10F3F000D53908AFF8156158F76EBBDC548AFEAFFB
+:10F4000026EC670DBB7FACA07DC8AACA7278DA086B
+:10F4100080E0E89EC5054097618A07C306C0832344
+:10F42000392CFF48599382FBA6ACC79B968962771B
+:10F43000E3BE290FB0FD793387AD47C461859FF2E4
+:10F44000604EB004F26B7BCF572DB7B0F355FCDCA8
+:10F450006EEAF2B79F82734BDBB8BF78FF8BA3F0E5
+:10F460007710CEAE5124F01B9DB5D71580BD372E39
+:10F4700097E94BA94A0FB15993F1733FE6BD16EDD9
+:10F4800065F97B0ABFCF4859E3DC0EF02CCD08624A
+:10F490007EEFE56D31FC0981176DC730BE46F52260
+:10F4A0003CC7FCD1F392D08B54F250D86B5A3BEC52
+:10F4B000AADC6F572E7E9D9E343D572D072FD8BE58
+:10F4C000226A3BB3B7BDB01BB57684E6FBC1F41F1F
+:10F4D000E20FABF25BE6E57A851E87F23D9BF346D1
+:10F4E00091F7D27B0E9944CC709E017209C4FD58ED
+:10F4F00090FFB351B2F8404FD2E6FDF4E6E390E658
+:10F50000E12C1FA4F92276BF44F3C5F014794166BB
+:10F51000C80B49CE3F4D65793D66C80BA1EF5B072F
+:10F520003DB7EC6D81F13BEFB68973CBCCCF5E4B31
+:10F53000789CE1213CD79CB82117CFC94CAC65FE23
+:10F540003B47C020035E3EFB0F9D1FF86E82D22D0D
+:10F55000E8578EA1FE2CD0B7CCB41EF24D7ACF2D39
+:10F56000D79101CF2D8BBC2411A7CD1EBE4102F92E
+:10F57000D39B2F12EA3BCF0CE3762EF1A27FB83754
+:10F580007FE9BB04D7592DF88C49BD7F697ED62E03
+:10F590006DA601F50CB71C7C1CE3789B7BCC78BF77
+:10F5A000446E11EE5B6B6504EFB3759476A0FFB506
+:10F5B00025C3BF39D7D5873F627E64235BFF1938E7
+:10F5C000AF25F58D7B66E117F9A04F55771B191E06
+:10F5D0006AE6B1B9F7DE143A0E7DFE2297EDBF4F11
+:10F5E000A3DF8AE72F047D713E2CC61F6C9D021F8E
+:10F5F000BF4E6FD7E257B89AEFCFBBE608CB3B526E
+:10F60000E3D7FE95B5E38E515E726065009F67CCCF
+:10F61000525407F941E6C42CE08077E6CDBF0EEEE8
+:10F62000D338939AC887FB385AF2A77E07EEDF38A3
+:10F63000E34ABC0BE5CEBC7F63E561896D703FC7D3
+:10F64000CFF3145686B1B2097965CBB9EBC2A57870
+:10F65000AFD5EA1E904FE59A3C13CD3D02900F893D
+:10F66000F71E58D97E66F27C5452C3F577882CD1A8
+:10F67000726B56990FF208ACC4BBBB07EA738DECF2
+:10F68000BE01C2F29F5A8715B27C058EEF2497FB0C
+:10F690009F493C0CF8DB5A68C7EF7BF9F56E238F66
+:10F6A0003BB1F1DF78869D131379B684D8F240EF31
+:10F6B000B17A89AA2CEEE1208A2D0FCEDDB70ABFE0
+:10F6C0001E2F1FB1044FE426E9456F4CBAA3147FE7
+:10F6D0008FE3D9BB86C27AAF32A8EF33EEE5A7F944
+:10F6E0008C1F9EE1F7FE7558829F423F4752664D40
+:10F6F00086AB5467665419ECA8A73DAE037EE4E2DE
+:10F7000078619FC1E667AF0948F03B18E2DE3D57DC
+:10F7100050417F000976EA407EBA8E05309FAFC126
+:10F7200094C857287E7D610CFE03E8E16CDD7B3FC9
+:10F73000C03860F61BEF42FEC51BFA8E8969202F88
+:10F740000AF97D0ED4F00B3B41DE15A0DDD77B4FCF
+:10F75000E73009F9C3D419ECFCE9141255D0FF6263
+:10F7600063E7A1269717FA5AE9785379FEC6E4238E
+:10F770008134F0034CBE29AEB0784B4249CE97108D
+:10F780004FE2D17B93E9E06A6F5299C0FDBEEAF285
+:10F79000B53E75F93B955F0E4F2EA7533B206F3C4E
+:10F7A000F0AD389E270E5F426C6C5D2C2FF0E7DCCD
+:10F7B0006E1BE521A602C85B744A61B00B463D97FB
+:10F7C0008D7194E72A0996DD3B4D0F9992D7BF5E64
+:10F7D00066715AEEE716BFE3037520579F7DCB8D08
+:10F7E000F0725B65E4A7E001077CABC8315980BFCC
+:10F7F000EB389F17E7AF27A599F0FED5D625ECFE8D
+:10F800007FEDFD93AD7ADB3ED8C7D613740D749CA3
+:10F8100047520D31390DF68B1083B38F1F0BFC81CE
+:10F82000FEAE00BC1FCF7E678962F9D0E4FBBF5BF0
+:10F830005D6CAEAD772B3C3EC77EEFA1A4F7F71F02
+:10F8400028D9D1F6A05312A413161FCB13EB248A88
+:10F850001FDA67115166E7ACDCBC2CEEBD24A44A6C
+:10F86000C1FB7224D1AE05CB0FF27652F72B7F038A
+:10F87000FC189A46D7439F4BF2189F78587E632313
+:10F88000E28935E8053CF1A50C7CEEE7B63C46374D
+:10F8900093D22A3D9037D09AE5F3805E25E023DEAF
+:10F8A0008B7E45BD18CF973170BF4B78BF517E6EB0
+:10F8B000585BBF388FE96DBDE3EA69BFD6AF18D793
+:10F8C000A51EB7F7BBBC81BF13EF457BFC79A60A29
+:10F8D000A03306B7293C5F9594A8F35348A5CFC43D
+:10F8E000F8BD3A1FE52A694516D0E7D5A6C6EE3819
+:10F8F000FDFE158E2757C9C1BF40BCE19559C5070C
+:10F90000803E6BE18279DACF3524B61A90E54C550A
+:10F91000F067F621C82FDAF2E83A9A74C1E10E5A7C
+:10F920003EA5EF18BAA410E9EB9EBCF1FDE727F065
+:10F93000B0779E14FF60DF05FE69E72DF0805C174D
+:10F94000C5C4BCAD24864F0F61F9D0547EB1BC67ED
+:10F950006F5EDFBA28724E36350F05F9FE4A4B1836
+:10F96000F9CF55F69F60FED78305C1CD30AF99170B
+:10F970007D82F7DD104F1DEA5B74BE3FFDBF9C2FFB
+:10F98000A5AB2C782FF440A1EFF5CB033E6150E5F9
+:10F99000018BF969E958CC2344D83D4613BBB7A382
+:10F9A0007E179A61F5C1798D10E4B79663FC0BF36D
+:10F9B00085F770BB2C2CB1BCDD7EFAE2E0F9C2EC1D
+:10F9C0005C7FA38DDD6723EE45FA7E91B8EF86CD8F
+:10F9D0009BF22F7EDF0D963BEBBC68FFF5EA8DF3C3
+:10F9E000981E7A65B1A50DEE0FEC7FEF0DF3EF9148
+:10F9F000E78C5EAE27A2FCEE4C65E39C32B3FCF4D0
+:10FA0000243E4E2477DF7D5C1BF44C1FFC635E219B
+:10FA1000BB5F44F655C07E6C86B895AEBF1FF284BE
+:10FA20002BF867C0EB79A5FE7CF8898D3906E6676F
+:10FA3000A478B5A587409A5BF32370DFE4D5A4F9D9
+:10FA4000B03C04F1EABFA1FDCC519FB07B28FBF094
+:10FA5000EA0386576164825F47A72F6604CF40FBA5
+:10FA60004E7BF49DA67288331A11FE228F504BBF35
+:10FA700049F339A667F371C23DB7743E9F0F349FB7
+:10FA80000BC1EF643CCA240C8F07C373C8D74F1D4A
+:10FA9000DB87E7E92468C81F9F84EFAB7DEDBA21BF
+:10FAA00003CC5B67C57DBFF166168F09A5303D1598
+:10FAB000E232596EF03FB1F16F5CC3F0E346B3112F
+:10FAC000F1655A7723C65F480D8BA7F8E8FF603EC3
+:10FAD00033897F12FC54C6F5B66978FE72C6547538
+:10FAE000BC65A6E92A8CEFDC40983FEDC6197AD5B3
+:10FAF000EF000A38CC24EB3E817C8E999ADFFFD34D
+:10FB0000C2451BAF11F068ADFC6ABA1F91DF1BD76D
+:10FB100019FE0DE33ABE7C963F7741719D03FA04CE
+:10FB20009EBB7FD9B560CB124A17C37F5A8AF7664E
+:10FB30004F722F7C643D2D3FB67924965F76DFBAF5
+:10FB4000EC0DA8DF568CE51AF99359788F79C5CD5D
+:10FB500053E0BEF10366D68FC712EC84DF8FF08CC2
+:10FB6000291A0B26598D2181EDAEB9A8711CE4C16B
+:10FB7000D45858F9B5B2FF1A8BE5225E1EFBC24875
+:10FB8000281F903E9935505C6854891483DF89AAF8
+:10FB900071B0F653C73E9E0D7E829A6A561EE5AB43
+:10FBA0005A3304EAE54F670D248F67E573FB89EB51
+:10FBB0005B014EEFCFF9DF6B83735E01ABE483FC37
+:10FBC000FE40E57BEC9E2B13CB2308F8CB14B80743
+:10FBD000B1DACFFC7B13AD2D59C0FFAE0B1ACAC1F1
+:10FBE0008F6BB316B6C17DFFE99555E361BF275210
+:10FBF000350CE41FA5ABD9F94057177F929F867A41
+:10FC0000889AAE04DE4E13F454A3A61BCA0FEAD999
+:10FC10003EAAE981F6DB88FD5EAA964BBDFC5D43FA
+:10FC2000B75A7C1C54EE13351FEC954FABA3889745
+:10FC3000B9849DE3D90A78CAE8F7DF607E06B9C7C0
+:10FC40000BEF0B24DF484CAC18447F10F303B5874F
+:10FC50008CED3F2FF85384BEC86660B3B9615C5623
+:10FC60004FBFF3C38F7A8979D1F17F8CF059CDE6FC
+:10FC7000B3556AE6BF13C1F47261F73689F576A908
+:10FC8000D75B6161E7D13D84F21DF4DD978DFCAA5D
+:10FC90007987B89C9D610ADC67A46BB8C13E07F701
+:10FCA000F926127E06F49BD72CC108CC472787F78C
+:10FCB000C625F89D073FC693E93E6ECF4FD217C4C5
+:10FCC000BCB4F0681A84AF6AE7AD8543DFFEF4A0E8
+:10FCD0007E96C57F0FAE775D9AF5B4F2FBE01365B3
+:10FCE00046559EE86B752C0F56CCEB358994A09C3D
+:10FCF000942C1847EDF53B69F9DB20E7D2847C169C
+:10FD0000F3BC839F8BFA5C667CEF0E5D0CE7595069
+:10FD1000DB630638C6F38BD87DC67CFEAD95616C7F
+:10FD20006790A501E3C4F17C59E457A8F65BDC4F6A
+:10FD300026E25C02AE4E833717F33D35F09C6D3200
+:10FD40000E1C57D5C65F07692751F8E538FAC35925
+:10FD5000C4CBAED5FAE1AE66FEA96BB91F6E622DBB
+:10FD600083BF63792ADA6D8EF2371432BAEFFE64FC
+:10FD7000B11F3DCEE049C423253E1EFC04AF8F7F5A
+:10FD80000CE344E29E422D7CCE0D029FC1E861B09F
+:10FD9000F91FB104BE80714F493D789F59C263E39A
+:10FDA000CE836021D08BDD565805FE05CA57CF9F04
+:10FDB000076313AAE8FE2D770565B853EF2612985E
+:10FDC00004B9D78EDAA09EF9E709FA8797723B71DA
+:10FDD0001297EF9F3EC9CEC1D7F8473C7819E89FEC
+:10FDE00087F424E2853C6E069F4FB7E850AE2F782B
+:10FDF000759C07F4F3F739BE0DDF28AB7E2F6E44F8
+:10FE0000C4A2BA2F63D44E87AA3C3A9AAD6A7F51F6
+:10FE10005791AABE2C3652553FEED05855797CCF1B
+:10FE20000455FB8B8F54ABCA97C4A7A8DA5F7A7CC2
+:10FE3000BAAA7C79E216F57D1F617F4F891BEECB54
+:10FE400067F0B8F2DC6C55FB8FD3261F02BA9BBB60
+:10FE50008EE56D5791C5AAEF17EB1A301F9A7430D3
+:10FE60003DA699FE8F9F3757304F8CEAEF1900B7A8
+:10FE70008D6A3DA7BE7BFD6AE0B5FDEE99D0E83303
+:10FE80005AFD65B8B30EAE69269717B0F3EDE4627C
+:10FE90007231FFFD10EDBEE2B9FD4F0FEBD08E5871
+:10FEA000FA2AD3EF973EC5F2E18AC9B0743CCF7508
+:10FEB00048472212DC5FD0BCE132A94F8FD1C2C5C6
+:10FEC000E851EFB3D9ABDEE79412F53EA7FAD4FBC5
+:10FED0009C5EA9DE67BB5FBDCF19B5EA7D7605D410
+:10FEE000FB9C3953BDCF5941F53EE7D4ABF739AF51
+:10FEF00059BDCF05CBD5FB5A185EA4AA177C734811
+:10FF0000FB52D5FB56295A413925991BA8C77B1BA3
+:10FF10008675FC7040FC10FB1FA6FF63F4DC8CF9B7
+:10FF2000F5F3E9FE437EFD5FC9BA83108AD2E24150
+:10FF300053D77A8CAB7D533CB8BB80EBA762FF2FC5
+:10FF4000503FA5F2B015F802D5635617807D3D9C51
+:10FF5000DB1D8181F518C1B792F58664BB7A307ECE
+:10FF6000D64F4E723B7B5039A9B1B3DF82EC26D419
+:10FF7000C7D7A15FEB668ED79FC1AB4BC0AFFA343A
+:10FF8000CAFFB7E8442AE9BCDE8279D371DEB28CBD
+:10FF9000423FC8AD24A6C77802646EEAF0DE4BCCBF
+:10FFA000C3ACA37A393CE770FD601EF7937C610C0B
+:10FFB000EE2C60FE9102378C9BDBC3CE6FBD967139
+:10FFC00041F73BFC0EFE49DBFDA92010857E6A4C03
+:10FFD000DE650FD057FBB9FF894C65F99F44098C4A
+:10FFE0004EBE4FB1AF1F16377D410A06D1CECE327D
+:10FFF000F9C0CE1E95434C5920DF3C91228853FD19
+:020000022000DC
+:10000000BA4016712A942B23398E3C951D5D6A47A0
+:1000100078451C1827F886E3FEA6C07F10F041B48F
+:10002000FFBAF51A0CD125CC9FC07EBFE430DF9714
+:10003000876F34C6C02E1378742465D6419717FD98
+:10004000E187012E336FBA7A3594A5FD19DEA574C8
+:100050007E67EAE268DF53F81F81F11B4C14FE74DF
+:1000600089A7F282C3D301190219DC4919183DD0BE
+:100070007924319F8912C70B4BF03D1867BFDC9381
+:10008000EF0378283D78FE8E5851B921A70C03FB69
+:1000900003051CAA53F26EC3FB748D461FD817D5F7
+:1000A00012DBD76319B7CF82D8E23C39E08EE9542E
+:1000B000F33E03E335D8EA0AB28AC0AFC6E70D3F84
+:1000C000028A70F7960EE827E7F3861C128CEFDEA3
+:1000D0002D89DFCBC1F273613BC6338CF26787E1B8
+:1000E000F7FD12A3658CF76DB1D0AE29BEFF27874F
+:1000F000B7B8EF9CBE67F97916F6BD67838CF1A39C
+:10010000FF07EF54F02D0080000000001F8B080057
+:1001100000000000000BE57D097C94D5B5F8FDE6F4
+:100120009B2DC924992C6421102609598010266121
+:10013000111471588251034E006531E24C12206453
+:100140008100DAC64ACD40D854A8A122A2A20E0846
+:10015000141568B008A8D1372C527CDA8AADB52EB8
+:100160009597002A3B3168A57DBEFA3FE7DC7B33DB
+:10017000F37D244F7CCBEFD7F7FBC7D777B9DFDD13
+:10018000CF39F7DCB3DD3BEE31AF2E6043187B7E19
+:100190009ECDA92A8C7999C3CC54C6CA99CBCC32AE
+:1001A00018FB7CF4BFBFD1EA602CD2E1B13A8632B1
+:1001B000764F9C21F58334067F9E012591908C8C8F
+:1001C000632C99B1EFF1EFA6AB53C67C8CF5C074EC
+:1001D000B5810D636C929DD1DF2C180BDB4D662E23
+:1001E000138E7307F39870DC3F5C34BB5814A4067D
+:1001F000282F606C2AF3D1F7E9CC4FE95D2C40F54C
+:10020000EF66AD947F3F22AF773DCCAFE489EC4CF5
+:10021000066D2E795B8761F9DF2D9E549C6F8DD51D
+:10022000734F3C7CBFD0DBF36522D467EB60322395
+:100230007E78BE25383FA8F7591F779603F2E3ACC6
+:100240008E21F9E98C1D34B0CA661B948DEB41F305
+:1002500067467BE6A4815DF5B3943118FF58475497
+:100260001E1B8479972D19D67F335F3EBBD9555D10
+:100270008CEB2C546D2C1EE07FCCA1FA2D3066D176
+:10028000686F4F5C17FC45FAE2199BE852D9C3002E
+:10029000EFDF2E812F50EFB7F9AABF11EA4DDC3006
+:1002A000FE0CB62F1E3D795934AC7FFC77AD43026E
+:1002B0009016F5329D68CDE1637C0FFFFB866D1CC7
+:1002C0001703E9AD49BB8D0CE67F6B5F6D79712E2D
+:1002D000E4ADC1FC44660C96C3B807100EB18CD5D2
+:1002E000FF257FD4E190768C35A96E58F7AD8EC886
+:1002F000F82F0640B63FEBFF3DCE5B2D8DF6D8BA0A
+:1003000087EFB70DCE51874D304FC55582F861400C
+:100310006F6EA0A33223733577D1EEE94C45D00F31
+:10032000603781B1DBC55C3B8A2F9B2FC17A57397F
+:100330003CA5D8CFC2099FCFC4F53123FBDD608037
+:10034000DBBCDF03DCA0FC4403403E9BB1530D56F5
+:10035000E6B230F645839DF2A71B92283DDBE0A074
+:10036000F47C430E955F6C7052FED70EF72CECB701
+:100370006CD557464F2E632BC3241EF93C16093A01
+:100380005ED97BD89F9D30DECA774D94AF6C6E1AD4
+:100390001F01E9A2DE279646C0F7452F284EFC5ED6
+:1003A000DDE232DB603EB30E7B5620F9CC79B775C7
+:1003B00022808FD55E519807B690A5AF7B11D2D918
+:1003C000D03F9D4A40F87DD9309CE673A6C145F3E5
+:1003D00071B5B41D8983F6E71A8A287FD4E1BE1F60
+:1003E000E7E7625F99B1FE841D6DC614282F74295A
+:1003F0002E06E38E7231BF1FF0B7C1E4F120DD6C31
+:1004000048B63A1B213F7AE0A467EE8571DFE9E345
+:1004100069C4F677C49617C6C1F789C3BD46AC3721
+:10042000F53BC6302FE9FB87F7358747ADC0CB8555
+:10043000371582D385BD036EBF01FA7BF3A8CA547A
+:100440009857C71503CDABE3A3703F5382F516BE93
+:10045000A2125D2F1C68F6B334CC0F4864B9B84EB5
+:10046000E80CD69FA338583DD0DFB99D3F4D423CA4
+:10047000C8F1CFC536FFF513E8AFFD338373338D75
+:10048000DCFCC55390DFD72BC9F930E42E9AD83461
+:10049000DAA7AC2E6212D0D73C33F3F0BC6700E68B
+:1004A000CF85B37BDC901FB62B650CEE231CCF9160
+:1004B0001DE46B59BB9E487FC0111C6F7BF3AC4F92
+:1004C0009E82FC05BFC1678A8694355F7C0DC6F3AA
+:1004D0006DB139B7329CA7311CE7F98889CFCBB70A
+:1004E00035DCB9D581FDF9890F40B919CB6B5E7E3A
+:1004F000B227AEE37580C170C8BFBE3682F8DDEBAF
+:1005000026E7F17A6CF70CEFEF57BFB8FFC47E4CCB
+:10051000D7D416DC0F69C0114BF0AEF8E5DCFED87D
+:100520007E400AA007F8E34BFB9440581E6303D7B4
+:100530001D589A0CE30DDAD866E80969FE16A51174
+:10054000D301BD8B8EAAD0FF118783E63178479AFD
+:100550009A82DBB5A7FF939B3208700AE2AFBFC057
+:100560005FEEBAAFC6F4847467CFE6853150DE5FC4
+:10057000693EBB240DE9FCC3020FC1AF89FA79A51E
+:1005800065F21FEF62B80E5FB215E7ED353BB7A617
+:10059000F1E59A207F614FC6A687618D7B0DBE4D28
+:1005A00088775F99D5B915F1EEF63D89F8AE85FAF1
+:1005B0003EC8D7E6FBA2AE87F2DACFFA3A81A2585C
+:1005C000EF676F2E4278CCDBF3F8F89E50EFC2480D
+:1005D000E604126095AF5C1E8FED586FC690255CE7
+:1005E000D8D3983003DA3D923B6628D2975B6DA64C
+:1005F00071D87C3ECE13B01DAD0032D60AC0491072
+:10060000A40AF51E81CFF83DB625E6400A0BE26745
+:100610007ECB923423B41FE2B13A55DC3769BEE495
+:100620003A58EF7B5865049D7FA7717F269B45BF95
+:10063000F6C9A9EE1F71FE99C57926FB7BC2CC7C59
+:1006400061D04F6FF8AE40BA11FB85F2ADC057EAEA
+:10065000217D46CC1FC6BD82FB14DABB900FA7C01C
+:10066000219D0FF34C79C242E7C0B58E7FC9645B10
+:10067000A500DDCE0FE77C6C8C387FA7C535BED1D9
+:100680000AEB7D35DC634C83716689739F199D0E7F
+:10069000E4EFFE709729AD079EA3EDA9B806385781
+:1006A000C3303F4FF5F449C8A073353B1AF9BEF586
+:1006B000DACED577C35DD1D8FE5AEBEBF9EDA26F58
+:1006C0000C2C1FE860D1E316E2178DC897615D8D91
+:1006D00091C3ACC837D86143CD1138676FE42D3B67
+:1006E000FB5B1459407CA591B12EE1F526EC7F0F00
+:1006F000F09B009C131EE003A3AEB4AB9CDE8F1DE9
+:100700008A1E827C96B922817E6EBA62609E907348
+:1007100050DF0FE02B0FE1389A45304FC8B9EA623D
+:100720003166DCB7CC16FB5F5BB798FF4881BF91A1
+:100730001D1F45301BC203BEDBBA5FD71B625DFFC6
+:1007400082EB82745DA6DB85F0BFF16BBB11D777BE
+:10075000A3B12415E51A98F778FC3EEA6B8376DEA0
+:10076000DF856BF2D73AFFFB14E633E07EFCCAEC80
+:10077000C7FDD882C723C0B1656EAE1FF7FD5E33DB
+:10078000CFFBA2A01CF0D812C97CC8475A4A12FC61
+:10079000BE34E487508E7CA307E3E561A2FDF40438
+:1007A0006ADFD30220457E7057B8E8BFEE9D8158BE
+:1007B000BE2485F848A3C9BF2A1DFBFFB94A7CF8AF
+:1007C00023C1B7D7C504EE52A1DF755F25301CE702
+:1007D000231648998FE3548613DFBDC160B8A7C4C0
+:1007E00086F55CC9B100EFBDFF50E99C58970F79C1
+:1007F0001BF1ED69CDF07D5D892B391CFB2949305A
+:10080000D07C545647DFD378BB4F4CBCDE0C81AF55
+:100810008F057E605FD3BEF74C8C3022DDAE492B56
+:10082000F3A5911CE44A5660BE4F556432E49B33F5
+:10083000AA6E49237A697A82F8D7348103D91F36A0
+:10084000B00E43B999FF4D9FB5350CF17947655806
+:100850001B9CACECA3CAA5910E687F87470D5880FE
+:100860009FB22985AE4EB92E1DC775D1B8B5CDFD45
+:10087000324E85D0739905F804F4FF52986725ED40
+:10088000D3FDF954BE1F849AEF613F9DA8C8DC8553
+:10089000FB8A55C4111D3063A01CF1F066BB95E4C2
+:1008A000D4EEE8A111E13F48D029E26531C73BC849
+:1008B0006B946F9CD6DF8FED9F3371BAF1ED0E23F1
+:1008C000BC164DB2129E3BA6856FB240F93D826FB9
+:1008D000354E0B772950AFF1158BDF807C40E1F46A
+:1008E000E07B2392FAAD31F37CCDCB99444F7BCDA5
+:1008F000FE17B661F99B61440F35517CDC9AD752E3
+:1009000004BDB9D296E3B86F58880E6AC21DD1549F
+:10091000FEAF7144272EAB673BC203E8AE0EE588FD
+:100920001A73202B06E07B5CD0D5716883F8F3D571
+:1009300045D2BC69CB43DED3D87B33E2D363E6E553
+:10094000EC672A951FB7F3F18FAFE6E3973E5AFDA8
+:100950002E03BC1D778F4F9E05F3385E174172E35F
+:100960005FEAD580390AF59EF6F55950EFE2E29339
+:10097000C336C0FC5B977E9A8AF451BAB4B618DBD2
+:1009800095562D9E88E76677FBB2B406367FC83E43
+:100990007E3FCD15C0F55C48F31C423A989FDB3A88
+:1009A0001BE5E78BE663CFA2FE1115E73982DF2F47
+:1009B000BDFAE5362E57B767E17930CFC8E9439ED7
+:1009C000ABF305FDDD97EE7997CE89F0C04C3C3F47
+:1009D00022728F717EB7F8DAF8FCD996AD7B1518C4
+:1009E000A73ABC651EA5AA3F0FFB39A704A2940C29
+:1009F000829F07F7D3797B200AE1EE317079AE7AD6
+:100A0000BB765DF867847955E33FA05D75B3EA0A6C
+:100A1000435C33BF19E75FCDCCC1FA69413C413F2C
+:100A2000842766FBCBCC0700FE552FF42B40FDA19D
+:100A30003A66FF2F6EA07AD04EEE13F5EABC5CCF7B
+:100A4000D5F3E1EB3B2FE8FFBCA4FF6982FEC5F8BC
+:100A5000175F4DA4F1CF95F8B310FE171551EF05B0
+:100A60000BAF07D460C479FE9AD3D37A93CF80FCBE
+:100A7000C7F77346F45C1DD73C0CE122F910CCC1DA
+:100A80006780FAE776A5507DC9B7989B316C57BD52
+:100A90002B793397CF843E8B1385FA552FF1FE3196
+:100AA0008FFBF0EC8B29623C2E4FEBF1A75F6F447C
+:100AB000BA81E4A9F5927F47CA7DEE4C2A01F86716
+:100AC0006F306BEA5F8C34DFE3827EFBF9B5DF6564
+:100AD000FF89E95CFFEBA3C35B4FB5FD8005F7D34E
+:100AE000F38CF6AB7E5EA9A2DD8B2F76E249E5782A
+:100AF000033150D28783CBE12684F3C79DF8B83702
+:100B000005F86A35C2203D089FBDF99E14E4FF1721
+:100B1000318FE7420CE473510EE2F0967909673D9C
+:100B20009D2DFD78764A2BB4BF45C007109A88F4F6
+:100B3000D829BF98401FC9457DB472F0A94CD45341
+:100B4000EBFAC151D0B99ED91BF2ADB89FE66CCC7F
+:100B5000B79685E0A171FBE0A30E80F3F9ED46277F
+:100B6000B2E546A3FF17284F376E579B7D8CCAAD61
+:100B700008DFF3B683BFC77AB337C614A0BC2CDB3B
+:100B8000CFD9705FBF8A10B80FD8AEC5C3C0666D2D
+:100B90007ED07E6D7E32F286A13FBE5D7E409B1F81
+:100BA0007C549B67ED802DC0836AE578DA37DC7969
+:100BB000D40178EAE3579DF8A98F6DD2E409285F44
+:100BC0006C549D9950DE67B1FBB681903FBD719624
+:100BD00013D15CA9FAE63D0038ACFC74FC513C0F23
+:100BE000CFB1E60F27001E66B7AC351B1DB86E2DC2
+:100BF000DDEE35087A7D51213A98EBD7965FBDAF8F
+:100C000097083CB29C507AD2E31DC6BDD30513AA07
+:100C1000A95F34F8141C9995C540E800B311CD6B59
+:100C2000CD28B7FDF0383E2E0FDA5C0E848777387A
+:100C30002FBBBE7E2C3B3918FEB1FAFDF1386FEFA9
+:100C4000230AC90DDEDF641FC673A06DF7F45B29AC
+:100C5000BDB388D62FED79735A944024E4EDC31DBB
+:100C6000FB5BA1DD2CBFE2C479972DB304F919FC1D
+:100C7000AF62B56E1EEB42CA61FE73F61FF89B02AF
+:100C8000FD576ED4B69B0B7C16F957D596EF2DA168
+:100C9000DFA5DE787DCB2615D73D4BCEDF378AE149
+:100CA000BAAEE75559BC906F4E6106CE8D5B7BB8EE
+:100CB000D7A763BB75BC1DB04B2FAEB7D66676E029
+:100CC0007A6BAD2C1001F3381A6976D9E1FBE50D8A
+:100CD0009164479B6D0179B28052165680ED9CD18C
+:100CE000D8EE8BF7B83DAD368EE3BBF63985F4A868
+:100CF0005A347E62FE799E9FCB02B40EA41357E84D
+:100D0000FAFCDA3C6BE2FA578D317000E151C55ABA
+:100D1000B9FE04787449F801BC6A609D1FC5A2BC85
+:100D2000A56BCF9C1E1C77BE8DCB4FF3F77F6F0951
+:100D30002D977AA0D4533786733DF1B92C77388E2E
+:100D4000B35C713D6985792E17F2B56F6D18D1EFDF
+:100D50008C4DFCBC0139360BE1B26E6DB213E58CE3
+:100D600019209787E1BE991B4EF540DE25BB4C3B11
+:100D7000C8D59BD3B07E7300CF8D758FA7911C0D06
+:100D8000F22FC1A57D4D987FB38272309763D6ADA7
+:100D9000CD2639FC75794EADE1725717723195B396
+:100DA000442EC77F824B099183CFF4F07C901EB212
+:100DB000AE8AA5AE643C772A26990D68AF6295711C
+:100DC000D7243F6C1572643BAC1FD7714A711F3139
+:100DD00084C8A39FE37900E30C1BE3DA26EA39B168
+:100DE0005E85A1E4E19B70BCF506078ED7096F977D
+:100DF0002B0BE7716A6D5801D2D9B031DC5E743CBF
+:100E00009FF3F78821CCE587F4A238672E225F0F85
+:100E10004993C281FEA09F5385DC5E1D39C44D7687
+:100E20003A38AB89CFEBD7F177D14F85D9FDAF37C2
+:100E300076311F091F368ECB0BA716289BF9BC00F5
+:100E4000BF901FF6CB30B2EF9D12E78F8433D0CD29
+:100E500050B2D30B7EB556D0CB5A13A703DF5CAE8E
+:100E60003F05E985113DAC137AD60C815FB686CB80
+:100E7000B5402F1CCE6B9205BDC0DC911E0A1D5CD7
+:100E8000CEBE467D09F01E9BD1E36ABD49E29B19A7
+:100E9000FD43D1BED21DBE6BF7EDDCEB83F3B3EAAD
+:100EA000D78F4731A877C6D894E084F6355B97474B
+:100EB000B9203D6DF445D961FC337EB5C8DF05BC72
+:100EC0006FCF907665974D01FE330FFFE94079E7CC
+:100ED0009189B8BEBF6E35D99125CCDF6E21FD69F1
+:100EE000DE9EB9246743BE8DE7577EA5627EBFD6DE
+:100EF0007E5EF5ABC7131C046F5F8A2109D3400ADD
+:100F00008374DE1693338076E90F54270C037273D3
+:100F1000FB0A9C9FBE3DCEE30AE07B7EB3EA3547E9
+:100F20005F5D3E5FF097F97B1EF90AED7AF375F687
+:100F3000FA4AE1B7D0DBEB6FCA888CFF020DD3D73A
+:100F4000B1EB500E02B83803B86F613E994426DC0D
+:100F5000DEDBF8C213796D282F6C79274AC90DDAC8
+:100F6000EBA53FA3A3B9FCB9D71CDDEFC78BC26EBD
+:100F70001BC417E75B8EFD0AF20050D0795A630A52
+:100F800044DD00F0A8D964223E53B3F3F96D4F213C
+:100F90009D7D6CA1F3BC7AE75B1F5E8FF2EE6E5312
+:100FA0007C315F864D4908E269BE83DBC9245EAAB5
+:100FB0007EF396D931907F5F1C1BC44FF5EE03661C
+:100FC00036F06A388E6D3E606EB57581A7E6B6F173
+:100FD00064277AE15B33EE83336F2A2C31EDEAF636
+:100FE000959BDE8A42790CE184E792C45727FE7410
+:100FF000F5A1FF89AF0DA17A76D42BBAC39F03CF99
+:101000000ED4CBF745B21818BFF2138BBF18F1BA44
+:101010006B5114AEE34B631DA7F3679627A05C5793
+:1010200069F225D829E5DF2B9FBD8FE86F8E529797
+:1010300060CF25FA4E3690CCE04BC6F5CDDA780776
+:10104000AD6F36F310FD553EA3BAFD907E63644547
+:10105000BBBBD8276F6770BEF9E566402AACEF4B83
+:10106000B4DB20DFF8832AF4DC05747EDF27D6CAE0
+:10107000D842CA7F23E4B68D1952DE056922445F47
+:101080009CBF65E531C4CFD9DEAE449C27C0C127E3
+:10109000E0A57C0FFDAAEF172672FC3087719868D7
+:1010A00007E7E858FC8EF58F995C68F70E6927F41E
+:1010B000393EFEBD627C987738EAAB5F2670B95D39
+:1010C000BFBE6F3BF9003BC642E9ABBB7DBFE5212C
+:1010D000A2ABAF3FE07C659EBFA488CA8F9902890E
+:1010E00058EE3F304521BE606181AEF6F51693D8CB
+:1010F000D7DA7298A7510985EF9B5C0E9D0D725748
+:1011000020641F07E9C61CFC4EEBFEA558472BF9CF
+:10111000D3A41F6E8EE007FA75EBF9C3211D7F90F3
+:10112000EDD9C6AEFD4041BEE0A3716BE03C413954
+:10113000A3E6630B9D1B353B4D6E84CFB91D873EE7
+:101140009C817A68B3DCC75A7EABDFC7952F0FED61
+:10115000721F9F5B9DDFF53E86EF5DEEE3D50AF1E2
+:10116000B7FF2EBF85938EEC06DDEDD739DDF0DBC2
+:101170000B3A787EC372A36FC042BBB70FE147073B
+:1011800057094F3DFF5C9EE120F8EAF927FC7DC03E
+:1011900042E028E127E993310F8DD349C7924E25CC
+:1011A0001D77D2A97EBD5A38EACB77237F82F9B862
+:1011B0005F3571FB598B42F236B43B923284F6A90B
+:1011C0008B8E3FD67424253E34EFD7E59B75F55DB5
+:1011D000BABC5B57DFA3CBD769EAD7EC3F64E6FA2A
+:1011E000414053CF527F1BE91957CB117EEEF7D9FF
+:1011F000F395D98774D1ABDD8C7CD1B494F92251AD
+:10120000DE7D432579F792A33D0AE592E5615C6EA8
+:10121000BB6417F9189E6FEF615E817C517E6F0F82
+:10122000E376924BEEF6A898103DBDAD458D427B1E
+:101230006CAB9F1575654721CB28C0B5957557CE0A
+:10124000E5B742D5965A8FF6D026D50964C22A96BC
+:101250004C8DA2B887968CDBA7C1F7596FAB143EB3
+:1012600070299CDB1598CF65C4B883728E42769A3C
+:10127000F9D68F847595B7F0F8838AD55AFCCEB627
+:101280004D890E3890EF68E304E6A05E9781FA9EE0
+:10129000F67B155B4DF456A5DB171E61A7D5EF0B4A
+:1012A000775F112F90CFF2853D86FC1C0B05BF2E7A
+:1012B00054736F9F06F0BF74546516C877B4A86C5A
+:1012C00005AE778742FE1E7408E07E9B07FB12E79F
+:1012D00023E1731EF74D76F772C9F9573E1BF600EE
+:1012E000D2C9DE4FF39E86F4FCDE8FB35EC7FCBE30
+:1012F0003FA77ECAAEAE3FF6CDBFCD443E7CE94DA2
+:101300000B43FABEF4E66F53D12E78E9350BE9CBE7
+:1013100097965AB8BDF9CD483FFA232FF5E6726E7D
+:10132000E31BDFE6B5D2B9BB8CF0F5405F33979B8A
+:101330005AFEFD38DAAB3B5A6055284FBC1941FBC9
+:1013400067FE6B61E40FBFF4C6B7C342E326FEBB82
+:10135000EB91FEEE4B916CDACB48B742AE9FFFFAB1
+:1013600088E7D19F5BBBE780B91CCAC7FECB7FE48F
+:1013700021FFBCF43297932E9A5A9F455BE38A2D46
+:10138000CE5F9A92D13E079DF564ACCFD6BA49B8EC
+:101390004FAE860B87C3258003AE0BE052897CBF1E
+:1013A0003B783C83F0E8F1CF088FAF66727E761D04
+:1013B00043FF6F102E0AF723B444FAAD0AAD9F7FA6
+:1013C0007FF3DB3CE4373FB4DED7FF69F1FFBFB307
+:1013D000DE8FFF69F1CBE9DDDBD741F3D4D3FDD557
+:1013E00074BDEF2794DF15E9A4F95EE37EFFDBFF10
+:1013F00067F84ECCFCBF8AEFB705BE23EDE857BCBB
+:10140000F4C67FA4B21FB1EE61FF47D72DE5F531D9
+:10141000AAF3683ED47F87357FE04C23E9A34BB91C
+:10142000A33C5391FA1BE94763193FA7C75AAB493D
+:10143000DE1CDB6B0DC9C58DAC80FC10BE5E2AF9CD
+:101440006328F802E0F0DBA47C3FF9938C815E8B8B
+:10145000203F26A596E2B3F47AE3D8F00945288F19
+:101460001E5A02F3827E0E451AECE82B1ED74B0D56
+:1014700058F2286DC3F448EA6D47516E1967D3EAF4
+:101480004FB7E9F4A15B1CDAF222F6723CFACF8A7C
+:10149000724DCC0FF3198FF543F4C6D199765AE704
+:1014A0002DAC6999DDF6E3E1F49880D3D570F8CFDF
+:1014B000E176159C849E6C14F5F57033DA1E3E8639
+:1014C000ED8C0CF45EBE5ED297A5DEFB43F0644269
+:1014D0009F368AA1257C8DBDB89F34A45F828B8402
+:1014E000FB8F85B7C4931EEE12BE126E7A3CCC46BB
+:1014F00063548F20FC7B19F38DB8EF6E1472FC38A7
+:10150000630CCFF73AA6BA693FFA399D7FED34A252
+:101510007C32DA1643F19ACCD13B06E54C1431BF4C
+:101520004F61AC6C78CC3005D69B62643E0BE89B77
+:10153000E843233BEA4346FFD2341C87DB6B7B1B2B
+:10154000B95D1A76B72FBC80EABBCC90F73E3687E0
+:10155000B9A0BE378539155E9F45C752381A533139
+:101560002E0B526CE78DE6FD7A13997F29C727E190
+:10157000A52FA6E9D4AFCB10CBDB4715507B9F81BD
+:10158000B7771921ED93C1EDEBEDCB2DA47F785703
+:10159000F6CE42FE513C466B378EC8E2766699FE27
+:1015A00024CB41A96A7026A15C5CB6AC1FE9436AF2
+:1015B000B8BBF615B4F7EF8A207AF4AEB87BC25008
+:1015C0009CDFAE38274EEFECC4DDC378FDE9F7FDB4
+:1015D00009BE7BB687D1F7A7B23C473201AE67158B
+:1015E000C7CC57E043D91D87CC493084A7B9E40262
+:1015F000DAFF26FA76FF1EFD8C13A7A8547F22E39C
+:10160000718F6C5904F9A327F8BE3226417F13402D
+:10161000D9C0F2B6307BEA0298BF57D87BFF20F6DC
+:101620008B1ACE3C2F23BF5AD13B2B1DBE4F605D82
+:10163000C701DBB3B89D461DA36C44FF509FB1DCCE
+:101640001E2FEB633FD86F8280C76799DCEE24F3CF
+:101650000057AA5FB1CAD296817ACF2A53201BE3E2
+:10166000A773C6B4E13A8BD3D9F80D08F7FB55B68A
+:1016700099E6DBEE253B77648E03F1E00192A6F854
+:10168000C2A63407DABDDA463707D03FD0F6649AEF
+:10169000B3D14158A6781CA967B58D0EF445BB7C23
+:1016A0007B3EF7331CB7B746A27E586EB3527C8E92
+:1016B0008CEB9965E7FBBC4F63EB9AEB50EF7C5CDE
+:1016C000756E86FCACC7B9DFE5739BD5AFA0BEB61F
+:1016D0008EEF53B65A1BC7C3EC4EB2F794378D3614
+:1016E000A37E59617399719DC9D99EEF715DEC3BE1
+:1016F00080DF308CE364B419BC4D5E8A3351A36043
+:10170000DFE13E313AA250EFD5C701CD17713F322C
+:10171000FF5298C79A05702C8B76EC427A39519F0C
+:101720004176CF9B91EE107E18C788FE09636B321D
+:10173000CEE7D54C4E8FC5B1F62C1BD1731843386C
+:10174000B4990093906F5B1E66403F5BF1524ED799
+:10175000B0CFAC4668FF909185A3DFE043D1BE7463
+:1017600089D1BD09F2BDACCC18198B74954F74FDAD
+:10177000688EE7335CDFE99FB3E1480FE5ABD792B2
+:101780007F45D205331E1B1707E39CDE9A56807CEB
+:1017900053D2D1A33963FA6485D2C31485E800D249
+:1017A0000319440F93FA6279F19840DF85B9A88F45
+:1017B000D630179EEF49CC897242076B27FF6387AB
+:1017C000CDEC403B97E427926F005E5DD684201DF0
+:1017D0006C83F3DE68626C7B8395D2171BECCC08BC
+:1017E0003C6E474312E5773538286D6EC8A1EF2F60
+:1017F000373829BFA76138E5F736B828BFBFA188B9
+:10180000D2D71ADCF45DF225800BF121C957243FB1
+:101810002AB799DBD01F29F9929E6E660278471588
+:10182000507BE27B92DFE13A0C05417E24F19BAED6
+:10183000B87D4969C8C75AA723FE0BD5F33BF7A16A
+:101840005E5E6973929ECE38DFEB007A45B8A49A4B
+:10185000D97EB4BB362E70B5AD4C0BC2FFAE4A85F7
+:101860001943E8EAEEBA30660C3937EEA98FD1E4B5
+:101870004BEBFFF85622F43F2EDE332D0BE671FCC6
+:10188000C12F9EF9337C7FEEC1B399886F98C7D67C
+:101890002770DCC5E19DF388C5FC3213F9A3FA4833
+:1018A0003B08FC215ECA18DF6FCF3DF877DADF6DA9
+:1018B000F51607CAC39F209E00AE7F11782AABB7EA
+:1018C00010FCBCCB4FEEDC87FB7CB199F85CD932C5
+:1018D000B10F57013C43FCBB279219D923409AA66C
+:1018E00078F5133F370722A0FF130ADFBF0A080568
+:1018F000A518F7B7EAB71FE1FE57EA8F92FFDC633E
+:10190000B505480EF099CE87F6A7D41FA17AACB5DD
+:10191000570CDA11E91C43BE3FC46576C0BA91A6E4
+:10192000116F6539075932FA4D9A143B6E990AF1D5
+:10193000BD629542FE498CBB9902729F2F4B253C9C
+:10194000B6641A695FF5CC6242AE6BA2F349D26B02
+:10195000C56A6887FBA229DF3C3B840F9789EFE5C6
+:1019600039064AE5F726EC17FB5B953F0DE5899EA6
+:10197000589E8B69C134846F4FDB78A31282FF8736
+:10198000B3F8F82D997CFC9EB8D9E0FF1ECE4937FC
+:10199000CFCA45FCF0F34B8E539653B002E338CBDD
+:1019A000568F46EECB1A4DCEA478A8F718F643EB27
+:1019B000B17379C1CAE3956BBA393FA4FDEC34FE2B
+:1019C0007304AD9BECBA55BB5EDA8571FC559F5A2A
+:1019D00008BF558344FC54AE7FD86432346AEDD5D9
+:1019E000E35EFA2C8AFC0F7B785C25A4DC9EBAB8F7
+:1019F00092DB5F9DB0AFBAF0FF1CDEF569549776BD
+:101A0000EA3DEA35D9A9E72BDF45A1FC20D753F8F9
+:101A1000C63709340FE50AF97FE6BFB13CA1AB7BBD
+:101A2000377A7B75A73D5BD8EDF4E57A7BDD912CA9
+:101A30009D5FC0C8E81E97B4D73135371AEDFBDF7C
+:101A4000887B1EDDE935D2BE3D7F03741207FBD3D0
+:101A5000E888467FD5A56EE4E9A86C2E1F5C10F6D9
+:101A6000F04B3B54D2732EED88A4FD346FC763470F
+:101A7000D07F386F8B42D3A865C7086E004F660DC4
+:101A80003DC730DE2CEEEA7977F833A3F11CA97E4E
+:101A900029B20EE96C6EB3E2DA0AF3E9B03AA27B3E
+:101AA00084CCE7ACA0D76A4BF33082B3987FAB907D
+:101AB000B764BDB92D8F91FD18EA5D2439E8D711BF
+:101AC0008CDFFF68FF3DCEF3DCC6C14EF4FBCD6D6D
+:101AD000DE3D8FE4881D11761481CE8A3861D9CF1E
+:101AE0005F055DFF358BCB2FE7843FE8DC2E95F853
+:101AF00019CE13F7D759451B8FF79D68F75D1687E9
+:101B00009B1FF7778F60FDB9CD6D517DA1FE97FBCF
+:101B1000FF48A9399BAF6BAEED581E9EBF5FEE89A3
+:101B2000207FD6977B9E1EFF3A8C77A179743CEE7E
+:101B300007D97F7CB689E363A35A84F0627E1EF7DF
+:101B4000528BF01D1C3ACFB84DBEB4D07DC7E37E9A
+:101B5000CEEDF94D94213788CF5AABC79A9C8EFBB6
+:101B6000C7EB46BEF1B9C2E169DA33DA87F798E626
+:101B7000B7E433A467DA77C9547F9521A49ED9E4EA
+:101B800024A668DC5FE24A21388B7B48225E1EEF88
+:101B9000D5D1BDA2122BF927660E724CBD0BF9E40C
+:101BA0003B268E975E8E27507E9BF95E1CC54D2D81
+:101BB0004C734CC5F92F7A5FA578DF9983051F48D0
+:101BC0006A1D8A718B35AB14E68275B6A571B9A111
+:101BD000C6AF320FE47B023DF8001423B3D3053FB8
+:101BE0000D64E17DC0A72A0D2E339C7FC7CDCCA705
+:101BF000A2DDE8651ECF5C93CEE3869F42BA87B430
+:101C00002636901507FD9D17F8AC9914C8C238897F
+:101C10009A9793294EE2BC99FB2DF13BFA496B0A46
+:101C2000A03DD48B17F1B0D83E26847E6ACA9C0EA4
+:101C3000ACA7C63A1DF9369CAFFD22C9B1AF4432FC
+:101C400094630DFB22799CD3AFC2365B42F0E4CEA5
+:101C5000E67272BCC0239BC1E321D78B78ECF55BA5
+:101C600093FDA8BFC9FAEB4D9EE908075C07CAEFD0
+:101C700073CD4D5928DFCAF9CE8D6AA2799E17F42B
+:101C80003D37BC89C74B9B793C25D6C77C9B895186
+:101C90001C77FB0B168A27399B7C6C2F8E7FF68571
+:101CA0007E0CD7DF96E69FBD9FCA417E04BC55BD22
+:101CB0006809E07ACEBCC0EDCD674C5C1E3B539208
+:101CC000E440BC154DDA3093EC315B2C0AE2FD8C1C
+:101CD000C2CC4958BEB587D387ED1BEA294EBA0A54
+:101CE000D804DEC781B408EFD59CD9DA8FE2C3CE21
+:101CF000BCADE28D28FCBE0ABF7B58D3CC9F213CF3
+:101D0000B673FDE9EC8BFFDE2FF41E9A4CABB66880
+:101D1000E3E0249DC8F205D95C7F5920E07C5F3662
+:101D2000B737D44634AF4FA77572B8039E48EF0358
+:101D30000E13F9F4108C83C854906F3C0574F5347D
+:101D4000DA15B673FDEAEC0E13C58557ED8B7451A9
+:101D5000DCD9CAEB0C1407A17239BCCA00E0A35449
+:101D6000A17EAB26E5F81B49FE66A4C7B66F55C534
+:101D7000388CD970DDDB789C6F31CA8A543E90CAAA
+:101D8000CF88FC99BD0349AE83FE5D785FA9EA6701
+:101D90000F70384EAE7C97911DC34AFCB5A6D38F09
+:101DA00033321ACFBBDA953744E33D40F69ECA5032
+:101DB0003ED1C3E9B2D199887CF57036E75FD57B17
+:101DC0009F31233FA816F743AA5F54B83F19F6196D
+:101DD000DE93AC5E71C313449FBF37B14C58CFF94B
+:101DE000E6C7A242F1B14BF4D359DFECA4FAD550C7
+:101DF0001FFBA95EF14E14CD679B89E24CF478BCC1
+:101E0000E6F62FAAD7D4BE933E9AB91DE5AAF5B33C
+:101E1000633FF914FAFF7A4798D3475F9BE95ED98D
+:101E20003953F36C5CFFB99D61C48FCEC570FEF071
+:101E300025F04F5F36CEE3B647292EEB0F93E93EF0
+:101E4000DC1CBFB65F39EE6F906F63BC549C331AD5
+:101E5000E3FA6ADFE3FC0DF0723BB57FCF44EDF5AA
+:101E6000EBF8A568D7B93F7746103D9CEBC9F172F6
+:101E70006E57369D476D319CCE61BEA9787FEEDCF2
+:101E8000CEEC7CBA9786C20DD04395D06FCFC534C7
+:101E9000A7DA43CADB4C424F0B404DA41B6C0372C4
+:101EA0005F553D97ABAAADAB293E04E36A87155059
+:101EB0001AB0C45E1D1F0BF44AFA63780EDF5F0C84
+:101EC000C74B10F1DB24EF349B917F7B845C58B3CC
+:101ED000431F5FCBCBCF6477DA391DF1329E17E910
+:101EE000D0A7509C49F5B2057391CEABEBD6DE85F9
+:101EF000FB4CCEBFDAC88A500F6B53549A475B181D
+:101F0000BB67129E1BA1E384C86D5F07C761F6041F
+:101F10009257E91CBB92EDE074832726DE135DA681
+:101F2000ACA671D2A43ECBD725E104E030635C5F60
+:101F3000DB6851DECDBAE53CF5EB96F3B1E5707E9A
+:101F4000D496E6787424E2F9772ADDA7BDFCDDE0BB
+:101F5000E8D82EE4B2E0B96E0EC6B7C2FC9391F693
+:101F6000D0EE92CDE5F16A8C9F8579666DD4C67509
+:101F7000E76CD1E6FBEFD0E673F768F3792DDABCB6
+:101F8000F3B036AF887151CFC6FBBBA867638A7ABE
+:101F9000B6C3C2F56CCCA39E8D29EAD9F81DF56CA9
+:101FA000CCA39E8D79D4B3312FE18DFA36E651DF83
+:101FB000C6F25B73B83C5623E224110F48EFECD510
+:101FC00030CD7D9F4B6FF07B1C40077CDF4C37D3BF
+:101FD000BE790A6B90DEC1ED4A3D275B1D18EFBB51
+:101FE00038D633246728DEF738B62219F1666CA597
+:101FF000B8D3F9AFF1B8D39A82301BDA375A977F4A
+:10200000B902C339DDB19E1158FF92A97D1BC2B739
+:10201000B6FE10DD7B6F5DE278EF268E3FB2B3B087
+:10202000CA58929BBC78CEC5768F477DDC375BADB6
+:102030008DF3D6C77DEBE3BDF57420E5BDE74CED30
+:10204000C9C8D74FBE605D8DF33F1926EE9F4CB3D4
+:10205000EAFCFD424E5BA36CC6F37A464E2CF79F1A
+:102060001D05F9BC8B7356A6E55706931CDE995FD8
+:10207000AD18E85E5C52029D438BC49C5295F6B647
+:1020800095C8E7E61AE8DCBC0C72198E77F903955F
+:10209000E487EC0D06CD7AFAF9C335F435607BACF4
+:1020A000EE5E434F4DFD41FBD375F71AFA6BE3E843
+:1020B000A72C3980FAFDE4D58335F52ADC37E8E032
+:1020C00028E62DE4D70A383F5CB0BEA7166F484516
+:1020D000FC2E9ADBD1B612E5D357C2E85E5825FE36
+:1020E0003FE08B95D027DE67ACDC23EE03D76BCFC8
+:1020F000E172710E551A99CF1E1BA4C34A3B73C5DA
+:1021000040FBB9FD8FE50550AF78FB8FC3ECE9A824
+:10211000578C4E447E946A72511C6CCDEECC98253F
+:10212000D0EFA20CCF4339B0CF4E351DFA45299ED2
+:1021300087BBB9BE7772F56FA2284E4CD05BAAC997
+:102140001E8E78DFD4C4E3E3D03EA6C606E9625310
+:10215000535C785F5B70BD413AF88EF004F8E1762D
+:102160009CCA83E4F7E86816EB1DADF8509E96EB29
+:102170005B28CE15D697F773AFC89F12FA855CE738
+:10218000F97E07F21C78FFA2617FAA8AFCDCB063AB
+:102190005B32A4B916CF165C4FE5A6CC3F8F847195
+:1021A000AAFEC4D7F3F9BAB1512350FEDC69721606
+:1021B000437E65D3F366D4B3AB8C7E33C557BEB0D4
+:1021C000C98CF1C5376FDF44DF676FF7523CE51C00
+:1021D0005647FAE769F9EE808047E51865A31DE6E2
+:1021E0001DD68FF38FCA70EEBF03F9E82D7CF7E39D
+:1021F000F276251FE378A6B8779BBDF0FD0DC18F61
+:10220000F5FBA4E3DDC9853D081EFCBEC69F18682A
+:10221000F11957EF8BC957D2685F4CB93280F4B2CD
+:102220003B02FDB8FE9BABD37FDFE5EF2E74B4F02D
+:102230007D50690EC44FC67DF2A689E4DC5A386F22
+:102240008617A05ECDD8F590BA47AA1A7A9D3F2E80
+:102250004243CFD358C83E81FEEEC4A09190FC9477
+:10226000E20C4DFDA95306E8E8BF20584E7CE47A05
+:10227000CDFDBADAC53E874272E618ED77C6E304B3
+:1022800081436BDAD7B249C17A48DF5BB81C5CBBCB
+:10229000276633DAFB2A0D5C7F9AE6E1DFE7EDE79C
+:1022A000DFD934A6D9877D329C7FE6E7A289FC027C
+:1022B000D29E3E0DFFDD05FC4112E9BC1F8EF7E208
+:1022C000D11EA1B93F2DFC81386FC443ADB01BD5E1
+:1022D000E670BB51ADEF9819DF1D00F81BE362A952
+:1022E0009E350EE3239B14B22B62BA98E225B5719A
+:1022F00058D81FC631CE3BAA7A719FE8CB81EE78C1
+:102300001CFF6B3CAE74CE067D1CE46AF247CE43E4
+:102310007B5008DE6EE9E710FE38FF8A9E08BF6238
+:10232000259FEE45EE3860C638BB295362F271DF57
+:10233000E8E94BF275D8CFA47F77BC7B88E8ABA3E4
+:10234000D248F4FB437098E7E276543DDDCD66C792
+:10235000CC784F7CF61EC589FA28D64378F4447AA7
+:10236000D4C1232EF66A3848F874C26B8F3ECE8DE6
+:10237000C369CE7EC51FE8024EFA79770737B99E4A
+:10238000D91ECF78E40B725D7370FED83FCC1FFB73
+:10239000977E08365CBF3F33C83E35CFCDE363F54B
+:1023A000F430E90AB7BBDC79C548E99462ED7EC434
+:1023B00076B82FEEB89240E53F965EE6C13CF9FD57
+:1023C000A76BA313B90EC97783FB81DF1BF8A17735
+:1023D00081F476C73BFA09BBE3503654138F2CF8CF
+:1023E000AABEBD3E1E59CA01FAF3C51B69A0B8C9F1
+:1023F0000E5B3AC91792CF7AC4F9E159FE0DD5F3B5
+:10240000403D3E9B04CD79E311F6BF8591E9F41E72
+:1024100043EA92B804C49337CC4EF1F7DE252AC5BF
+:102420003D7BA19E23443E59B12C2315CF8B130F26
+:10243000653FEB03B9FDC4FDF109C3619C93CB4D2E
+:10244000F15647B0DE89E585A918A77172AD659A86
+:10245000BF0B7835F4E3E743ED831FD17976C1F004
+:102460006ED434685FB3FC95280CF3AF5ECECFF129
+:10247000C40CCF83FDC87FBB699B1DE167DF9487D8
+:1024800076DF35701C607B293F542D2F4C44F9A218
+:10249000E61F879EB5E33DEB25A604943FCF7C0065
+:1024A000E7A142E719C90DA7C3A00BF2A745921DEA
+:1024B000E1B4C25CE8573A6F38F0D795A817E63711
+:1024C000670520ADB578D6F443F97FF9F324B75406
+:1024D0003DBC244B55B1DFCCE8AEEC2632DD26CE38
+:1024E0006D94DF3145F91DE364507EC73CCAEF9817
+:1024F000A2FC8EDFE76FD0CA7FCF087FA1B427F799
+:10250000696CCF47FF9D6F0CCBA9A3F3D69683F2DE
+:10251000FA2225DC89FC6811CA4A98FF2C8CF458F1
+:10252000B625999FB702CFF556EE37FA56DCCFBDE8
+:10253000B11D64B210FABCE98A9585DE9B1DCD629F
+:1025400034F9B1D6644DFD427B9AA6FCE6A47E9A8E
+:10255000F25B1CF99AFC6D392334F52738476BF28E
+:10256000B70FBF4553BFC455A2C94F2E9AAEA97F1E
+:1025700087DBAB299F3A6DAEA67CBA6781267F5771
+:10258000E5FD9AFA77D72DD1947F6B008D14E8A5DD
+:1025900005F52E0BBE9F62A5F4A7AADD887C63D14A
+:1025A000EF326D88EF91630D755DD9F73F14741CA0
+:1025B00037C0F53ED24B6FF13E4E6FF1CECD293C88
+:1025C0007786A21F12A88AF4DD63C948BFFA7AFA97
+:1025D000F29111072F3B0087A35E34DF61043E3484
+:1025E000F2BA83833320FFD3176FE4F91B0EFE2664
+:1025F0001DF20D2F2EE5F941072F63B9F9A5313CE6
+:102600003F9991E8F148FF8E29184F32F2A6F4D590
+:102610004E6E27E9F29EB94C110E785F1BE180697E
+:1026200000E817D38340BF981E06FAAD00FE74047D
+:10263000E817D3A3A07FE2F77F05FD13D37741FF0F
+:10264000C4F4F7A077627A0CF44E4CFFD0308DD2F0
+:102650000F1A3CD4EEC3864A4A3F6AA8A3EF9F34C0
+:10266000D453FA97061F7D27473FB74333CDFD006C
+:10267000F433A23F71BFE97CA81F58FA2BA57FB2A3
+:10268000B18EB54620BF6835C67C610DFA1DBBB75B
+:102690000318D91721F258347345F42779A1979D6F
+:1026A000F8B7F8BEB38FC7DE1FE6F5A7B4C99983A4
+:1026B000553CB7EADE42B7EC9FC4FD7A7DBFA784E4
+:1026C000BCFC657F570F6C27FDEBD2BFDD193713BC
+:1026D000E27F3784C4EBD05F48DC8DF483CB389F36
+:1026E0001BADFC9EB1F473CB781ED95FE1D78CF89B
+:1026F000C3A85546925F228D2C80FDCBB89D51D644
+:10270000E67C8C63185563A37BB589F0DD5C40F5EE
+:102710005C2AA45BFE06F5F3827EF544317F28A790
+:10272000F9177EED213BEC28115780EDADBCDC871D
+:10273000ED47A16D6108A5C49F9EC17BBB05413FCC
+:102740003FD68FE0F503D85FDFBFC37851C17DD39B
+:102750003BB6391FF975EF7936BA17BA717480DE56
+:10276000B322A313C065B2D49FAC222FFD79DB1333
+:10277000C98E3456ECF50C87E766C4A7DB62FF2CE4
+:1027800082F659466FB44F9608F9F93FC15B31E2C2
+:102790004DC253E245E251E223247E8AF0D01D5E11
+:1027A000F5F8D4E351E2AFF0EB205E10AE57E32D25
+:1027B0008857B4E7FEB3E06D8891BF5F66A9B1D2D8
+:1027C000BB683F84C77BDAD9F868A872CAE139854B
+:1027D000E7BCF78AE308E6CBD9E8F1885A597EA12D
+:1027E0009B72CFD7EDA6E8107CDF28F01D9F06F581
+:1027F0007B5C5D5FD693EF31C8FE077753FF9D305A
+:102800001977E1B2E50F0BC63F2E2AE4F02F4A53A9
+:1028100009FE6373E7909CCC6C5CCE74C07FC89754
+:10282000C67FE7A6772DBF613BD073CBC6C76BE5EC
+:10283000D3229DDFFA562197DEAA934BF572A5BFEE
+:10284000BF902BD358DA8F7CAFF257FD89AF5EEB88
+:102850007B95FCBDD371629FA5083ACB70A86C2410
+:10286000D211F3D0397918DF3BCDC377417D94BFC6
+:1028700085F929BD8D05E87C9D008C18F3B733469A
+:10288000F7C80F454C2CC5BB7163078FED8BDF4339
+:10289000DE656BC17D3A4FF5FC9B3DE45DB683E39D
+:1028A0001C74BFF2A03583E42FDC87A6107BE0DB2D
+:1028B000703EF585F3E3109C5F98BE05E7575F58BF
+:1028C000EF6FE1FCC2FCAD394B18B61BEFD0C6ED83
+:1028D000C8F6B7D9C78262D23DFC6ECB7BB517C2B2
+:1028E000F79D98EC71683F7F27E6BA71B8DE776292
+:1028F000120D3CB598291DB8AF6F57F2A1DC07C186
+:10290000F1C6D3787AF84A78EAE128E1FB5F80E7FC
+:10291000175DC1F394909F3BAC7F8C4A4A47FF5DA3
+:102920009478C7F277792AE4CFE0D492315EF50645
+:102930009AE7A8FA11CC3898FC36B908D71A2B8731
+:1029400097DE6EC5B6241A42E377BF307BBEC5F171
+:10295000BFDCA8D2BDF10B2F87913DEAB49FDBDB32
+:102960008A14CF77488F35AA6335BE3FCADEE1EFC0
+:102970009CB1EF0EA54E8AFC1174BA85DFB7AFB1DA
+:102980008EEF128F529FFA0F878BF80813EF454A8C
+:10299000B9A29785BF4B20DF2FEC4ECE1816CEF98B
+:1029A000602F8B781741E015DA513E05FA19067C45
+:1029B0002EE5D170D22FEA7BB8E2070C0DDA113A7E
+:1029C0007A45F891DF8E0A0CA077B98A8EAA144F47
+:1029D0007C50C477DD3CA0CE960E78BA29D3933ACA
+:1029E00000D7A57EA7229F7917D61987F687A383DC
+:1029F0006DA43FFE483D346B80E017792C4F735F28
+:102A00004DD29D6AA3F89D8E0FF87DBC856FF3B8FB
+:102A1000CD853D548AFFD7C7C58D62598FA2BD7140
+:102A20006CBCC9E97704F98B7C07C89264608E108E
+:102A3000393BCC11CE1C21F389C889D5E4239D3DB7
+:102A400035F5A387A76BCA635CFD35E57145059A2B
+:102A50007C0FF7F59AFA89D3C668F2C99E5B35F503
+:102A6000532A2769F3B8EF00EEBDEB6668DAF5A9E3
+:102A70002FD3D44BF35569CA99CF752C2701F93858
+:102A8000FFCB58B55053FE7454118F1FB7CDA67BA2
+:102A90008A994D3FD3F427F19B12C7F1CB1CFC7CE4
+:102AA000F0C17FE4B710782E4CD29E1B63EDA30FCC
+:102AB000DB29D5DA35527E200E6ACE7F950E6A99D3
+:102AC000960EE2791C4FE1DB831D28C7E8F18FFEEB
+:102AD00088D075A23F22142EE88F08CDA33F22B4E0
+:102AE0003EFA2342CBD11F115A3EF8A816FF438F5E
+:102AF00069F17FDD4763FE533C8D68D5D2831E4F5D
+:102B0000379CD6D2C7284F38C1652CC86348EF120E
+:102B10004FD3E03F3AE7993B1AED06373117DD0B0B
+:102B2000F89FC2D7333A7C7DC3560FC5772E2F79D5
+:102B3000391FEFEE9C7FA28FEB79E41FEF0B3EAFC6
+:102B4000B703C87852DF188E4FDFF130E257DF1A33
+:102B50005A23F1FCF8A9DA4A76F964D6FE16BE3F8C
+:102B6000638AF7FC1AF95822460F40F95373EFCCE9
+:102B7000C7736EE6BF585251AE99D987BF27C87246
+:102B80005BE99D16399F99293CFE68DF00C1A79D2E
+:102B90003C0EE9B5015CBE8E74DA290EDA9BCB449B
+:102BA0009C274B9D3910E9F0DDB06CA4B375DCCEE9
+:102BB000D56A72505C8B0FE811FD94286FA33CDC42
+:102BC0005BC8A38D1F5BAD9CEE98E67CEFE7B76A10
+:102BD000E270076CB76BF2039B9334F507ED7768EF
+:102BE000CAF303399AF2C1479D9AFCD063C335F505
+:102BF000AFFBC8A5C98F682DD2D4BFE1B45B934F9A
+:102C000061ED4F223CBF1A90CEE3FB156107707057
+:102C1000BCCCFC6902DDA7917A848CCBF6083AD64D
+:102C2000EB237DCC1E8AF36E4C664EBA0F6215FA0A
+:102C300020D3EA291E11572DE579E6D3C655CB7866
+:102C4000EA4E7D46E82F529F0889A776E1FC653C55
+:102C50007527DEC5FB927AFAFC87C0BB7E1D7DCC52
+:102C6000FCFE57E3FD66BAC722E7A79FD7CD221E19
+:102C700070ABB5EBF7876CB9DC6EF068BADB980B1C
+:102C8000F59E85E389E079D578CE561FC0B7F1E788
+:102C900066E752C70F8F3773105F4F29BEAB9A4B51
+:102CA000EF74D2BD35396EAF5C4EDF863CA5CBF5F7
+:102CB000CD8CE6F15D2CDA4CF72EBA1F8FC335C9E7
+:102CC000CC96D13B49E21EC2DDAB9BD7606845A9DB
+:102CD000B9C9C4DFD5F79BD04E543C06E4C07CE0B4
+:102CE000135B77AEB381BCF66CBD91EC3E19B9F1C4
+:102CF000778204D979AFA40FE8694827C5887FE8AF
+:102D000077C3401EEF3C2E97AFAF50FDAEF33E8031
+:102D100045C3E7B9FED705DD113DCA75FC6FDD0F70
+:102D200090F4AB8793D4AF9938BFFA8A7949F87594
+:102D3000DA4F04FCE4FD0CC702937BB38DEE7914EB
+:102D4000615C99C4DF4B03395DFE04E13194D743E4
+:102D50007ED45DBD4235371AEDE01DCC116DFF010B
+:102D60007BF0FFD2BD09827F77F7BDBAE31357F13D
+:102D7000876EEE7F75479FF4F723EE8185F0091E7D
+:102D8000EF23F0E1EF6B20BFFACA48ED3EDE9ACBAD
+:102D9000E17BABD84F706EDBF2B57C82A15DBF7179
+:102DA000B92AF8C4ECCEDF9FC0EFB3969B48BE664D
+:102DB000CCBD1EE30C3E5F67A2B8D8512E46724CC4
+:102DC000D946C5BF49C173746412CEDFEBD39EC729
+:102DD0003731E70AF47F94AFD27E9F63E3BF53316C
+:102DE0004BFF6E8AD0D7E7FC80BEBE3E579CE34EB9
+:102DF000E624B94BF8FF2B451BBDDCD5E1E77E335C
+:102E0000D4B7556E77A2B83179BE3BD07F13F21E8E
+:102E100008C0333C07CFF165C62EE3F93AE1D94D3E
+:102E2000BCC2799B8857B0F1F88C8E3D61DCBF291C
+:102E3000FD4AA2FE79DF652AC7FAD8DB857C1E77BA
+:102E400021FD497A7F5587CD40FE968E3D91E49FC6
+:102E5000473F4E34D0C159C3EE84E169C1F9795A74
+:102E6000558D1F449F7A96BC42FA62628627908BEA
+:102E700071D846A7D509F9876C07E9FDA86261F703
+:102E8000D2CFB753EF1AC9DF77E9F07179B6A388CB
+:102E9000BFC3017C91E13E927108250CB45448BD3A
+:102EA0008111349F1FEBCF997C259FFB31AFDC4014
+:102EB000ED3DAB4650BECFB2350BF01ECC1D8D7331
+:102EC0004CE8C26E7D72716138346DEDED5F1A8E23
+:102ED000781BAD7469976F13E759AB2EBE5EA625BC
+:102EE000821FCD1B28F9B888435AA2D03E58A8307B
+:102EF0001997447C5CE62F37897C21CF2F5ACEF37B
+:102F0000ADE27DFD6DC28E82EBC614D78D7AFF0EC9
+:102F10006167C175638AEBC6EFC8B7308F7C0BF36E
+:102F2000C8B7308F7C0B53E45BF8BD8CB953F355B5
+:102F3000EE871A17BAEFAE58D9B890FD827EA8D0A6
+:102F40003CFAA142EBA31F2AB41CFD50A1E5E8877F
+:102F50000ACDA31F2AB43EFAA142F36CF82DC13C5E
+:102F6000F2395789263F19E4FC7121FB1BFD50A162
+:102F7000FDA31F4AD39F6781A6FD5DAC5ED31EFDF6
+:102F800050A1F5EFA957347EAA7BC43BA7E51BE20D
+:102F9000887E221DEED48180E77F8BF8C77DA674E2
+:102FA000C473CB5CAE97853B399E9B8A38DE0D8C13
+:102FB000E3B97D3AE179B199E70B797CB29E7ED095
+:102FC000DF33CEC4FD3D98A2BF0753F4F7608AFEFD
+:102FD0009E7199DCDF8329FA7BF03BFA7B30457FD9
+:102FE0000FA6E8EFC114FD3D98A2BF0753F4F760A8
+:102FF0003BF4F7608AFE1EFC8EFE1E4CD1DF83DFA1
+:103000008FA3DFC9149C17CAF17D35FA23D0A146DE
+:103010007FB46BF228C787D647393EB41CE5F8D099
+:103020007294E343F328C787D647393E343F33D7FA
+:1030300041FB0BE5F9D07628CF87E60736F9DE426B
+:10304000DBD9848D170F63DA1AA93CAB00CBB867C4
+:10305000E74B771A413E6B0D53526380739A94DDB0
+:10306000778E83BC47C4FFE5B17603E2DB23DE53F2
+:10307000F70418C55B0EFC5B32953F23EF87E11F19
+:10308000E03D7F0FA3DF2591FE62D9DEC9EC2AA6C1
+:10309000B27E30DF753DFDF8B21EF1CF9079E00DC4
+:1030A000608C57C95F6C2BC078CF6D0685E224B663
+:1030B0002DE571C27ABA7A6C20F78B6E33EC3E88BC
+:1030C000F740DABD0ADD07CE32B2A3A60284535D13
+:1030D000019EBF0F0C8C117EBEBAEBF1BE899CB76E
+:1030E000B46F029FA0FB7323DB8F8D8D867E3CBE69
+:1030F000D1F43B29C5662E37603BD42707F814D797
+:10310000E610FA5E3E90F34D8F8F8FFFABE726F20D
+:1031100076E1BCDDAF9E8B22384E5CA650BCD4C895
+:103120001DCC85F7737F21E63D604740C5F1BCCBE0
+:10313000F878B25FEFC654BAB7E865ADE392C84716
+:10314000A230E4DB126EB0BEC3B83E501B8EA27D2F
+:10315000FA5AEFFDDC3824A610E3E8580BA3772CCD
+:10316000270C795FB35E42FB30EA97CEB56C9F4285
+:10317000EF054FF42D598A6431C1B7E0AD1E587F79
+:103180000B73A639E828A27BB1723EFD5DBB0D70C2
+:103190002CB25C76CC10A620BED9A1B810FA819DC5
+:1031A0003F05F19DEF34D1FBBD2546BB89DE8FE89D
+:1031B00026FEE4B24DC69FE8E4055D9C49E3E28F3C
+:1031C00052D19EBC30D240F6DF85AFF0DF03F06C09
+:1031D0005088AF4939C82BE2D42E2F7BABC754841B
+:1031E000FB6E13F527E34F6A33FCA9068CABEFB9EE
+:1031F000292F562539E000F2C373BEDFDC391CEB02
+:103200002DE7EF585E5E764774807AE2FE9A0A01F7
+:10321000AF0A11C7E4C507BDD5E0EF69C9FB1DAC16
+:1032200089CB7BD29EE3FDDDE023885FEF33E25D57
+:10323000E9555EBA97AD8F239ABBCC44714773753D
+:103240007261B5900BAB7F402EFC78A04E2E94BFE0
+:103250009722DA30B5D78718B727EF25969AF8FE68
+:103260002FDDCDC80E5BBA64AC81DE417E85D34DC7
+:10327000E9122EDF94BEEAA2FB85525E7C4FC83174
+:1032800093AEA410DCFF28E4963B30BE12E05BDC7A
+:103290001A26E2B092299D7A85C75B4EB2713ED064
+:1032A000FA067F07A2C367E1F2D461C6DF31D3D14A
+:1032B0006589D16FC00B77CE914097909F80721037
+:1032C000F4370DE5A238A4F3B4428ADF2B52E8DECE
+:1032D0008B9ECE8B4D756F617C68F156E6F4B150D4
+:1032E0003A07FAC5FE7C0ABD0FE0117AADA45F3D36
+:1032F000BDCF8C10F6281BB73775DA255046C54769
+:10330000BA7DA6A918FF3A137D7B3D39C160DC590F
+:10331000642E2F8FDB659ABA0CEF2A7463A7507F57
+:1033200066267878E43B08DDD80DD05E807CF2EE2E
+:103330007BF3CD65217CF2E4A0318307F508E2BB85
+:10334000ACF3BE5F2EBD0BBAF0A14CFA3D9CEEE48F
+:10335000E172802BEE8B99D1ADF7E12FB315E431FB
+:10336000D7B824FC7D41261F210F601CE10C91BFC2
+:10337000272FEFCFAB6C0417CAE7ED8A9B8A712128
+:10338000B5D6D6F14876F3733D45788F31C89FDCCA
+:10339000AE1405F9537E0075C29BB3F83D2FBD3DB9
+:1033A000E29E3C5E5F6F9728CFE57C5BFE2ECA896C
+:1033B00087F6EDC2F34ACEFF4437BFC330358FCB1B
+:1033C000B3FF53F720F4F71F66F5F414E5C17CD77B
+:1033D0001BF87DFE9E6A1313F621F20B4B7EC1C4CF
+:1033E0003B1841BCBBE81DDDC687147BA87DCAB372
+:1033F0004AE1F7E8BBB1E3B09CF627B742BB990DB1
+:1034000066FA1DBFE7B238FD3C07F443BF97623E42
+:10341000F696352D08C74FEB7F69A2DFA561814C79
+:103420007C7F67465D9813F9F1C941EE9938EF88C2
+:103430005C27F1A1C183387D65C4BBBD7978FF6E7F
+:10344000F58167F13D81F92D69F47B25DEFDF92BCE
+:10345000F09D9393833CB3B1DC6BB3D37B1AF396AB
+:10346000C5D0F9353351DC0B65EDE46793F07F305F
+:103470008FEB89D73999F8BD2D71DF01186489A6C2
+:103480009E88EFD6ED0F6927D4DB19F4EF4B7467F4
+:103490005F90F604B41F9843EC8CD23E61CA393178
+:1034A0001DE58652B3F65EA24C7F2DE62FF5C0597E
+:1034B0009DE756EEF844948FD72A767A6FD2E69835
+:1034C0003A02F215474D18D9C98A631D667C7FA060
+:1034D0001DF08BF1D165B05F91CF948A38AD8A0D24
+:1034E0002368BF55F821EDE21D4E99DEB5F650EF89
+:1034F00057917E022EF25B56D85DE6D8907D5FDE56
+:10350000A468DE1D90F9E7F2545A672988E308BFE2
+:10351000BBEF4D33E3DB3EA5204660FCDFAF057D0E
+:10352000C876508FE2418AD3D911FE0E3CCC3B8D38
+:103530008F5710D27F5913BF372DF3509FE49F1739
+:10354000F222A93FAF1DD69D86A99DE609702038BD
+:10355000B5AF81FE1C340EE1A33CE037A1BE5D8A0D
+:103560007128909F61F79B709CB265FC1D13CF6A18
+:103570003E8E67558C7920CA4746BBB937C22F9C0F
+:103580009F57303F92232B002E781F0BEFBBE1D9C2
+:10359000A2878F57CCB7A22986DE51087E5F6B4287
+:1035A0007C4CEFE65D844F05DECB968DA6FBEB15DC
+:1035B0004617DD73F008F87EBE20EC61F40F4C5F17
+:1035C000F784290DFDF882CF7C2AE05A9C1EC8A4FE
+:1035D000F78A168439719ED3ED4DB4BE4EF83E0E77
+:1035E000F050F09D1B37C117E8C287717B15EBB413
+:1035F000F80CCE87C3B7629D97F6DB6CA3C76C0F40
+:103600009DC786039978AF6A3AEC6F7C5782D93DA3
+:10361000745FF28BC7A7A6D23A619E08D748A7630A
+:103620003CBE3F0474C2EFC188F5C87BDD72BCCBE1
+:1036300079FC1EFCE51FDC972E926B1A01BF68F720
+:10364000EE6E5F9A9171C3B8E60AFE3B12FA7D2ACC
+:10365000F7A7DC97729FCAFDFBACC91D4852827C5C
+:1036600006CED9BA97BB80D3E0411C0F33045E016C
+:10367000AE8743EF79F51AC4F15A9AAEDDEFD81F41
+:10368000F66B95E5630299F82E93AC2FC72D8DE567
+:10369000ED90EE91DEAC830C9DF517527DED3D95DE
+:1036A000F24E7EB1637902F28BDD0AF783AE39D434
+:1036B000FBA728BFEEE4F2EBB99AADF3F0BC644689
+:1036C0007F6AE8FBFEB340CE413E315B9CCF158163
+:1036D000AEF9C553599EE44121FBB9E2B19D591E93
+:1036E000CE6F02C86FFEB2F3F53F5DEF089EA77282
+:1036F0003D65ABDE37796DA1F0E37ACEC3391D7439
+:103700001FAFDC667660BC73F9322FF15F960472EE
+:10371000A112127FA6A30BEF3285EE9195D70FF37E
+:10372000ABFF837CBA7C7509BD7B20F126DF6791F6
+:10373000E7AB9CFF4831FF9B06F1F633047DCFA831
+:103740001C6D4E8E27B91BC32CD974F17D7A85F67A
+:103750007B27DE3AFDD7B92B70BFE0FD22D24F5652
+:103760009BB8BD6F07B73F9E5BB8EFF77742BDB31D
+:10377000EB37A532558B379453670B79758EB0FFB5
+:10378000758137F7A090389E39CF71BC95EFFADD7F
+:1037900067F89E5869BAE0776BF83B0065CDBB09C6
+:1037A0008FD357AD35A5213F1A94A6E1E3E575F90E
+:1037B00076B42BCF58B5C9847CC223E1A0DB0FA51A
+:1037C000224E58C219CF2525C4BF21EB237FC4F751
+:1037D000EFEF5D101685F13C729C87049D97D7C56D
+:1037E000C4E278E575DE5FA03E24CF03FD3A4F8644
+:1037F000F1FD5206FDE1BE3D39DA99BA303728CFE6
+:10380000EAEBFBC4BE7BDAC47FA72625A2F9058AB2
+:103810006B981FEE44FED1B76FAB1FC745FAC67950
+:103820009B0DFC776DFAD6B47E85F3E8CB785C0D02
+:10383000A6F83E16FA171220BFD9C0EF6FA5AB3C11
+:10384000DD26E003E5012C67F1ADF4FB1A2171B32D
+:103850001AFA35B32DF4FB89E67846EF9B497A9541
+:10386000FD487A95F4DCDDFA9EBDC6F59D4CE3F08B
+:10387000348BDF4DB9E6F559F8EFE8CA75C9F9811F
+:103880000CEFA2F73D1E1848F69E934B9CA91837E3
+:10389000D9FD7AD7152674B15EFD3AE5BE91B1F037
+:1038A0009DFEAC26EE7738A9C0F906ED4E2E08A392
+:1038B000F836B9AE1F6B0F3F382856D8775A2351C8
+:1038C000CE2C0D0FDE9747F81DAFE7BFAF2BBF4BD8
+:1038D000B940BE3327F9F7A93A716EB2D635B8BFF1
+:1038E000597D06BD7F72BCE96424BEC77272349FE5
+:1038F0009F6C77AF89DF4F66916607DE138BB8F751
+:10390000FDC244F40FAD4BCB57A0DDDDF5838FE353
+:10391000FBE3772F4B24FD7E96CDB102CFC559BE78
+:1039200034F20747ACCBFF02DFD19BB56C00FD6ED4
+:10393000EFBD0A73933E29F484D9ACF38FF4843934
+:1039400082AFCD417E89F7A5EA0FD1BB79B39D61E6
+:10395000F978BECFD9C0F58462035B85FEC43E8D85
+:10396000EEF1C8C7DA9F54F8EF3E6FD4BEC3959C02
+:10397000EDFE0CF98CFEDDBB7B4DCD2E5C07037993
+:1039800004ED4EB36C6E92EB4B05BD1C5FD746BF8A
+:103990009789F0A6DFCBD1D96FFA98F93DE2F648C6
+:1039A00003D9E300EFEFE1EF91E17BEB163A6FB45F
+:1039B000F69B3E0F0EA7DF6B93F7842A84DF49D274
+:1039C0008FF45FCDDA3499EE0FCD427BCDE0E0FD90
+:1039D000A915EBC6D2FB4E156B0BD7E3EFDCA40A9F
+:1039E000389E32B696207E4E6F4A8CC57BB915B58F
+:1039F0008D59785FA862D34ABA37747A5318DD1BA1
+:103A00001A672F1987BF1F327B23BF9F27F7A3CDCC
+:103A1000C9F76355ED58BAF7F3FF00B910AD8C0044
+:103A2000800000001F8B080000000000000BCD5636
+:103A30005B6C1465143EFF3F7BEFECA5ED527AA161
+:103A4000EDB6E5B2EAB69DA51403189834802412A9
+:103A50005D0805368176088114686B4593164364CA
+:103A600061951088711F5AA104CC52A1BEA8D986B5
+:103A70004621AE66A541A236B18117129266FB526D
+:103A80002E11BB564D69A2E039FFCC660997C44799
+:103A9000E7E5ECFFCFB97FDF39B3ED0F473EF1D457
+:103AA00000ECAA02F02C01F82B91178F3080F6431E
+:103AB000972A240E10B06A56650EC03E9EDCBCCC20
+:103AC00007708FC5074B84BE6FAE47067844CFAAF8
+:103AD000A7E5E421009F15A0E3BD9BC2CF7D3EFA80
+:103AE0007A18EDDB3B2EBAC8CFBEBE1B4B3D783FEC
+:103AF000B7462B541AC9EFB9418F0400A7CED5851C
+:103B00006A01BC0AFEC6FBF505A1CD61CC2BF3A36F
+:103B1000A40CF89E1FAFED1226DD903B6F8FBB2DDE
+:103B20001000D05260F190F480A500E51D097A12D2
+:103B300028D75743EB463977BF48417BACF38E3BE0
+:103B40005611C2FB3D83272B7C28EF3AF5F3B6C113
+:103B50002D3F810BF5CF5B2D407626B02868B7331B
+:103B6000C2D4384A682B0028C9C50F2A7922FF3DE4
+:103B7000A730A9C2DC3D405CDCDF35C13ACAA332C4
+:103B80009A09BE85F29629B50BB0CE5B5D7625828B
+:103B900058C88A4FE4732B26ADA5FBC83B0C1630E2
+:103BA0003A5F74CEC7F82D6EE8227BE792448A7B99
+:103BB000B1CFC3F98BA97DF8702802E8F4E8873506
+:103BC00092BCB60CDFEF1F621E2BBADC7FF9EA5AFB
+:103BD000D0CF00ECF9FDDCFB6005F81ECB7BEFF0ED
+:103BE00090C587F1DA3FC77A317E7B62E88752F46D
+:103BF000D3796947831E3706B014F3A09F18A773C3
+:103C000058EF4BC7F084656720E76787BFE0681906
+:103C100062BB29D1B8A50FF576106ECB910F752F29
+:103C20006C3D6C22E911FD0153A622E40438EEBF7D
+:103C30006ED1C8CFFB863FFFF5A3D5A2DE0D85F080
+:103C4000181F9A15B3B0CBDA633F845DAAC3710C19
+:103C5000EA01D44ED94432DA21BB489EE9E27E1310
+:103C6000F655650E45C27EF7D85C75E00698B1EB57
+:103C700032E9D065370F0DEDC61467F8981D90F73F
+:103C8000DD528C915C15E862D869307BB57D341FBC
+:103C9000C59060201A916294F7D4B7B71B28FECA6A
+:103CA000CAF41F802999D9CB5B57233FDE568CFA83
+:103CB00002E906E2F99C2BD04AFC3A6B8663F6C512
+:103CC00054770836D69217FC4DB8CFF2F805CC2FB2
+:103CD000C9529F92FF6CBD9F115FD14FC82A1F63CD
+:103CE00098E79F95DA41CAE30D66AE0D72C2405A5D
+:103CF00040FEA7CCFA7B889D546DC88B269D16503C
+:103D0000CE210248594B69B14CBC66AA0A3D18FF46
+:103D100048E0CA4EE2C7898C0DAC18376AF4A32973
+:103D2000E39860A8575EBA8E431DEAFBBCB00DED68
+:103D3000AF0478C48A799E005B9CF4C1B6464DFB03
+:103D4000F5188FAAD13FB7AB423F796D96A12C935E
+:103D50007E1F71A37E593753A2A8D3323D79F6173F
+:103D600094DB201EA4BEAEF66A7DB40FC6A7D74D65
+:103D70006888EF094FC2467346CFE3F9270FCCBAE4
+:103D80000A782EAFA9CCE4175F2F21695318DA35D2
+:103D900025A594B5EEE97CA68A7D268A837A294EEC
+:103DA000FA328F3346FA233729BF269B9C925C64F4
+:103DB00067FE356DCBD9C15879FEE44B20207E5487
+:103DC000065014D5715B69CC611697CB0A17B85CA5
+:103DD00036F0C9F64F248FF3B1DFA6CFC777F2E0F4
+:103DE00076E24F765EDF34EEA71F54BB69BF4C27E7
+:103DF0006BDC1078FE7CDEC0FD0A8B005EAB52BF30
+:103E0000A77EE1A3DAD07FB3D11FC41BC8AF64F88B
+:103E10006D36FAD42C73BD2F9B9EE88BC1932C0F6B
+:103E2000B2796771CEE207EF8E5D755709DC6A3FA4
+:103E30000281D7CFC4BBF1D9D10F70ACA0545227A7
+:103E4000B4AAFF235E29FB22E475A68F2B03C47F4F
+:103E50006AFC6221558EF5811FC43E68911CCAF12F
+:103E600067EC038DF6413DED839898F3199EB9CA2E
+:103E700019ED832E712E86CC61139EC779DA49F92C
+:103E8000A6EDC87A94EE60B5D8E36534D1353A4EE4
+:103E900034D7670F38078EA37E94A9FD36B48F9A66
+:103EA0008D79DF23C72FE0FD549C47CC18AF373FF7
+:103EB000DEBF1BEF7B9BE72911ECD314187A6D0E44
+:103EC000B11756702ECE9970517CA08AF471AEB1A4
+:103ED000CEDEF08BE23BFED543744E752F00FD7DA8
+:103EE00010169EA2F71BFCC2DF37D93DF3A153F891
+:103EF000EBDDA09638C4FB224EF6870B357BB091E4
+:103F000070D5F5F08F80D03B7D5A2D213C4E6FB49B
+:103F100008BD8F5928BC8BFCD4CACA05F49B0E3B44
+:103F2000BE1CD4E14831BC1FEFD1EBCDF2F7D585F3
+:103F3000FA1EAC8C4CF403B628D204FE2EE4FD38F5
+:103F4000F1B03E870F53118B821C4E593E46CC88F0
+:103F50009757C7EB087B1A2FAF8117EB41DEBA08E2
+:103F6000B784E8FF0CD771E896209D8735495C2916
+:103F7000B6A21CF36AF3F53AC74AE87D8B35DD1823
+:103F80000B109ED09678C61CD6D3929D23EA63343C
+:103F900067AD06CF5BB37C3CF8041FD3F3F227F385
+:103FA0000C3EA2FD4D472848F1EEB31B4BE972F4DD
+:103FB0001F69EBB3E22C0FEA7BE437ABB68CF4E17C
+:103FC000FC5C2EF688479FEBD1E0ED72FACEC0DFA5
+:103FD00023F3E8BBD35F187A85F4ECF333168DFA3C
+:103FE000599231533DE3E17BE5F47FA6B5E79A981A
+:103FF0009BFF9AE7BF3AB4AF4B200A0000000000D5
+:104000000000000000000000000000180000000098
+:104010000000000000000040000000000000000060
+:104020000000002800000000000000000000001058
+:104030000000000000000000000000200000000060
+:104040000000000000000010000000000000000060
+:104050000000000800000000000000000000000058
+:104060000000000000000000000000000000000050
+:104070000000000000000000000000000000000040
+:104080000000000000000000000000000000000030
+:104090000000000000000000000000000000000020
+:1040A0000000000000000000000000000000000010
+:1040B0000000000000000000000000000000000000
+:1040C00000000000000000000000000000000000F0
+:1040D00000000000000000000000000000000000E0
+:1040E00000000000000000000000000000000000D0
+:1040F00000000000000000000000000000000000C0
+:1041000000000000000000000000000000000000AF
+:10411000000000000000000000000000000000009F
+:10412000000000000000000000000000000000008F
+:10413000000000000000000000000000000000007F
+:10414000000000000000000000000000000000006F
+:10415000000000000000000000000000000000005F
+:10416000000000000000000000000000000000004F
+:104170000000332800100000000000080000333069
+:1041800000100000000000020000332800100000B2
+:104190000000001000003A78000000000000000855
+:1041A000000000000000000000000000000000000F
+:1041B00000000000000000000000000000000000FF
+:1041C0000000000000003120000000000000000896
+:1041D00000003360000100040000000100003368AB
+:1041E000000000000000000200003370000000002A
+:1041F000000000080000337400000000000000020E
+:1042000000003A70000000000000000800003A4082
+:10421000000800000000000800003D880040000089
+:104220000000004000003A500008000000000008B4
+:1042300000003A60000800000000000800003A8812
+:1042400000C800000000009800003C180098000022
+:104250000000002800003C580098000000000028E2
+:1042600000003378036000300000036000003EB0BF
+:10427000000800000000000100003EB1000800003E
+:1042800000000001000020080010000000000010E5
+:1042900000002000000000000000000800000000F6
+:1042A000000000000000000000000000000000000E
+:1042B00000000000000000000000000000000000FE
+:1042C00000000000000000000000000000000000EE
+:1042D00000000000000000000000000000000000DE
+:1042E00000000000000000000000000000000000CE
+:1042F00000000000000000000000000000000000BE
+:1043000000000000000000000000000000000000AD
+:10431000000000000000000000000000000000009D
+:10432000000000000000000000000000000000008D
+:10433000000000000000000000000000000000007D
+:10434000000000000000000000000000000000006D
+:10435000000000000000000000000000000000005D
+:10436000000000000000000000000000000000004D
+:10437000000000000000000000000000000000003D
+:10438000000000000000000000000000000000002D
+:10439000000000000000000000000000000000001D
+:1043A000000000000000000000000000000000000D
+:1043B00000000000000000000000000000000000FD
+:1043C00000000000000000000000000000000000ED
+:1043D00000000000000000000000000000000000DD
+:1043E00000000000000000000000000000000000CD
+:1043F00000000000000000000000000000000000BD
+:1044000000000000000000000000000000000000AC
+:10441000000000000000000000000000000000009C
+:10442000000000000000000000000000000000008C
+:10443000000000000000000000000000000000007C
+:10444000000000000000000000000000000012C892
+:10445000008000000000008000000001000000005B
+:1044600000000000000040000490000000000490E4
+:10447000000019C8000000000000000800004948C2
+:1044800000080000000000080000492800080000A3
+:104490000000000800004938000800000000000883
+:1044A00000002008001000000000001000002000A4
+:1044B00000000000000000080000401004900040D0
+:1044C00000000040000049980008000000000001C2
+:1044D00000004999000800000000000100000000F1
+:1044E00000000000000000000000000000000000CC
+:1044F00000000000000000000000000000000000BC
+:1045000000000000000000000000000000000000AB
+:10451000000000000000000000000000000000009B
+:10452000000000000000000000000000000000008B
+:10453000000000000000000000000000000000007B
+:10454000000000000000000000000000000000006B
+:10455000000000000000000000000000000000005B
+:10456000000000000000000000000000000000004B
+:10457000000000000000000000000000000000003B
+:10458000000000000000000000000000000000002B
+:10459000000000000000000000000000000000001B
+:1045A000000000000000000000000000000000000B
+:1045B00000000000000000000000000000000000FB
+:1045C00000000000000000000000000000000000EB
+:1045D00000000000000000000000000000000000DB
+:1045E00000000000000000000000000000000000CB
+:1045F00000000000000000000000000000000000BB
+:104600000000000000000000000040000018000052
+:1046100000000018000043000040000000000040BF
+:1046200000004300004000020000000100004301C0
+:1046300000400002000000000000300000400000C8
+:10464000000000400000000000000000000000002A
+:1046500000003000000800400000000400003004AA
+:10466000000800400000000400004B00002800008B
+:104670000000002800004B50001000000000001057
+:1046800000003800008000000000008000003800BA
+:104690000008008000000002000039000020000037
+:1046A00000000020000020080010000000000010A2
+:1046B0000000200000000000000000080000510879
+:1046C0000008000000000008000051200008000061
+:1046D0000000000800005130000800000000000841
+:1046E000000051C00008000000000001000051C19E
+:1046F0000008000000000001000039400010000424
+:1047000000000004000051D000300018000000102C
+:10471000000051D800300018000000020000000026
+:104720000000000000000000000000000000000089
+:104730000000000000000000000000000000000079
+:104740000000000000000000000000000000000069
+:104750000000000000000000000000000000000059
+:104760000000000000000000000000000000000049
+:104770000000000000000000000000000000000039
+:104780000000000000000000000000000000000029
+:104790000000000000000000000000000000000019
+:1047A0000000000000000000000000000000000009
+:1047B00000000000000000000000000000000000F9
+:1047C00000000000000000000000000000000000E9
+:1047D000000000000000000000000000000023E8CE
+:1047E00000800000000000800000000100000000C8
+:1047F0000000000000002008001000000000001071
+:1048000000002000000000000000000800002DA0B3
+:10481000000800000000000800002DB8000800009B
+:1048200000000008000024E802D00028000002D0A8
+:1048300000002E58000800000000000100002E5962
+:10484000000800000000000100002D90000800009A
+:104850000000000800000000000000000000000050
+:104860000000000000000000000000000000000048
+:104870000000000000000000000000000000000038
+:104880000000000000000000000000000000000028
+:104890000000000000000000000000000000000018
+:1048A0000000000000000000000000000000000008
+:1048B00000000000000000000000000000000000F8
+:1048C00000000000000000000000000000000000E8
+:1048D00000000000000000000000000000000000D8
+:1048E00000000000000000000000000000000000C8
+:1048F00000000000000000000000000000000000B8
+:1049000000000000000000000000000000000000A7
+:104910000000000000000000000000000000000097
+:104920000000000000000000000000000000250062
+:1049300000400000000000080000250800400000C2
+:1049400000000028000009C001200010000000083D
+:104950000000000000000000000000000000000057
+:1049600000000000000000000000402002D00028ED
+:1049700000000008000030000000000000001000EF
+:10498000000050990000000000000001000050B03D
+:104990000000000000000002000045A00090000898
+:1049A00000000008000000000000000000000000FF
+:1049B00000002960000800000000000100002961DB
+:1049C0000008000000000001000029700008000439
+:1049D0000000000200002978000800040000000424
+:1049E00000002FB0000800000000000400002FB4F9
+:1049F000000800000000000400002FC000000000BC
+:104A00000000000800002FC800000000000000089F
+:104A100000003000000000000000001000005040C6
+:104A20000001000100000001000050000000000033
+:104A30000000002000000808001000000000000432
+:104A40000000080C0010000000000001000008B782
+:104A50000000000000000001000008B60000000097
+:104A600000000001000010000030001800000004E9
+:104A700000001004003000180000000400001008BE
+:104A800000300018000000020000100A003000187A
+:104A9000000000020000100C0030001800000001AF
+:104AA0000000100D00300018000000010000100E82
+:104AB0000030001800000001000010100030001845
+:104AC0000000000400001014003000180000000472
+:104AD00000003000010000800008000400003004E5
+:104AE00001000080000800040000000A000000002F
+:104AF000000000000000306801000080000000019C
+:104B00000000306901000080000000010000306CEE
+:104B100001000080000000020000306E01000080F3
+:104B2000000000020000307001000080000000045E
+:104B300000003074010000800000000400003066B6
+:104B400001000080000000020000306401000080CD
+:104B50000000000100003060010000800000000241
+:104B600000003062010000800000000200003050B0
+:104B700001000080000000040000305401000080AB
+:104B80000000000400003058010000800000000414
+:104B90000000305C01000080000000040000307C58
+:104BA00001000080000000010000307D0100008055
+:104BB0000000000100001C180010000000000004AC
+:104BC00000001C30001000000000000400001C3831
+:104BD00000100000000000040000000000000000C1
+:104BE00000000000000000000000000000000000C5
+:104BF00000000000000000000000000000000000B5
+:104C0000000000000000000000004C100008000040
+:104C10000000000200004C1200080000000000022A
+:104C200000004C14000800000000000400004C20AC
+:104C3000000800000000000800004C3000400008A0
+:104C40000000000800004C00000800000000000206
+:104C500000004C02000800000000000100004C04AD
+:104C6000000800000000000200004CD00008000016
+:104C70000000000800004CE00008000000000004F4
+:104C800000004CE4000800000000000100004CF0AF
+:104C9000000800000000000200004CF400080000C2
+:104CA0000000000200004D000008000000000004A9
+:104CB000000050000010000000000004000050043C
+:104CC0000010000000000004000050080010000068
+:104CD00000000004000014000008000000000002B2
+:104CE000000014020008000000000001000014048D
+:104CF000000800000000000200001410000800007E
+:104D0000000000020000141400080000000000026F
+:104D1000000014160008000000000002000019B88E
+:104D20000008000000000008000014200008000037
+:104D3000000000020000142400080000000000022F
+:104D4000000019C8000800000000000800002C1036
+:104D5000000800000000000100002C110008000005
+:104D60000000000100002C120008000000000001FB
+:104D700000002C13000800000000000100002C00BF
+:104D8000000800000000000200002C0200080000E3
+:104D90000000000100002C040008000000000002D8
+:104DA00000002C30000800000000000200002C323F
+:104DB000000800000000000200002C340008000081
+:104DC0000000000200002C2000080000000000018C
+:104DD00000002C21000800000000000100002C222F
+:104DE000000800000000000100002C230008000063
+:104DF0000000000100002C24000800000000000159
+:104E000000002C25000800000000000100002C26F6
+:104E1000000800000000000100001400000800006D
+:104E20000000000200001402000800000000000161
+:104E3000000014040008000000000002000014122A
+:104E400000C00018000000020000141000C000188C
+:104E5000000000020000141C00C000180000000840
+:104E60000000141400C000180000000800001427FF
+:104E700000C00018000000010000142400C0001849
+:104E8000000000020000142600C00018000000010D
+:104E9000000015900008000000000008000015A0A8
+:104EA0000008000000000008000015B00008000025
+:104EB00000000008000000000000000000000000EA
+:104EC00000000000000000000000000000000000E2
+:104ED00000000000000000000000000000000000D2
+:104EE00000000000000000000000000000000000C2
+:104EF00000000000000000000000000000000000B2
+:104F000000000000000000000000000000000000A1
+:104F10000000000000000000000000000000000091
+:104F20000000000000000000000000000000000081
+:104F30000000000000000000000000000000000071
+:104F40000000000000000000000000000000000061
+:104F50000000000000000000000000000000000051
+:104F60000000000000000000000000000000000041
+:104F70000000000000000000000000000000000031
+:104F80000000000000000000000000000000000021
+:104F90000000000000000000000000000000000011
+:104FA0000000000000000000000000000000000001
+:104FB00000000000000000000000000000000000F1
+:104FC00000000000000000000000000000000000E1
+:104FD00000000000000000000000000000000000D1
+:104FE00000000000000000000000000000000000C1
+:104FF00000000000000000000000000000000000B1
+:105000000000000000000000060022000000000078
+:00000001FF
diff --git a/firmware/bnx2x/bnx2x-e1h-6.0.34.0.fw.ihex b/firmware/bnx2x/bnx2x-e1h-6.0.34.0.fw.ihex
new file mode 100644
index 0000000..54f36f1
--- /dev/null
+++ b/firmware/bnx2x/bnx2x-e1h-6.0.34.0.fw.ihex
@@ -0,0 +1,13178 @@
+:1000000000004F48000000680000070C00004FB8D7
+:1000100000001ED4000056C800000094000075A027
+:1000200000009EFC00007638000000CC000115386E
+:100030000000DC6400011608000000940001F2706A
+:10004000000040180001F308000000A4000233285B
+:100050000000F378000233D000000FFC00032750AB
+:100060000000000400033750020400480000000FA5
+:1000700002040054000000450204005C0000000679
+:100080000204007000000004020400780000000078
+:100090000204007C121700000204008022170000F6
+:1000A00002040084321700000604008800000005E6
+:1000B0000204009C12150000020400A0221500009A
+:1000C000020400A432150000060400A80000000489
+:1000D000020400B802100000020400BC001000007E
+:1000E000020400C010100000020400C42010000030
+:1000F000020400C830100000020400CC40100000D0
+:10010000060400D000000003020400DC0010000020
+:10011000020400E012140000020400E422140000B3
+:10012000020400E832140000020400EC4214000053
+:10013000060400F000000003010401240000000098
+:1001400001040128000000000104012C000000004F
+:100150000104013000000000020401D00000890603
+:1001600002040004000000FF02040008000000FF79
+:100170000204000C000000FF02040010000000FF59
+:10018000020400140000007F02040018000000FFB9
+:100190000204001C000000FF02040020000000FF19
+:1001A000020400240000003E0204002800000000B9
+:1001B0000204002C0000003F020400300000003F59
+:1001C000020400340000003F020400380000003F39
+:1001D0000204003C0000003F020400400000003F19
+:1001E000020400440000003F020404CC00000001AF
+:1001F00002042008000002110204200C000002008A
+:10020000020420100000020402042014000002195D
+:100210000204201C0000FFFF020420200000FFFF5A
+:10022000020420240000FFFF020420280000FFFF3A
+:1002300002042038000000200604203C0000001FBB
+:10024000020420B800000001060420BC0000005F8A
+:100250000204223807FFFFFF0204223C0000003F97
+:100260000204224007FFFFFF020422440000000FA7
+:1002700001042248000000000104224C000000009C
+:10028000010422500000000001042254000000007C
+:1002900001042258000000000104225C000000005C
+:1002A000010422600000000001042264000000003C
+:1002B00001042268000000000104226C000000001C
+:1002C00001042270000000000104227400000000FC
+:1002D00001042278000000000104227C00000000DC
+:1002E0000C042000000003E80A04200000000001C4
+:1002F0000B0420000000000A0605400000000D006D
+:100300000205004400000020020500480000003201
+:10031000020500900215002002050094021500203D
+:1003200002050098000000300205009C0810000043
+:10033000020500A000000033020500A40000003008
+:10034000020500A800000031020500AC0000000218
+:10035000020500B000000005020500B40000000620
+:10036000020500B800000002020500BC0000000207
+:10037000020500C000000000020500C400000005E6
+:10038000020500C800000002020500CC00000002C7
+:10039000020500D000000002020500D400000001A8
+:1003A00002050114000000010205011C000000010B
+:1003B0000205012000000002020502040000000105
+:1003C0000205020C0000004002050210000000407F
+:1003D0000205021C0000002002050220000000139C
+:1003E0000205022400000020060502400000000A69
+:1003F00004050280002000000205005000000007F4
+:10040000020500540000000702050058000000002B
+:100410000205005C00000008020500600000000109
+:100420000605006400000003020500D80000000675
+:1004300002050004000000010205000800000001A0
+:100440000205000C00000001020500100000000180
+:100450000205001400000001020500180000000160
+:100460000205001C00000001020500200000000140
+:100470000205002400000001020500280000000120
+:100480000205002C00000001020500300000000100
+:1004900002050034000000010205003800000001E0
+:1004A0000205003C000000010205004000000001C0
+:1004B000020500E00000000D020500E80000000059
+:1004C000020500F000000000020500F80000000036
+:1004D000020500E40000002D020500EC00000020F1
+:1004E000020500F400000020020500FC00000020CE
+:1004F000020500E00000001D020500E800000010F9
+:10050000020500F000000010020500F800000010D5
+:10051000020500E40000003D020500EC0000003090
+:10052000020500F400000030020500FC000000306D
+:10053000020500E00000004D020500E80000004058
+:10054000020500F000000040020500F80000004035
+:10055000020500E40000006D020500EC00000060F0
+:10056000020500F400000060020500FC00000060CD
+:10057000020500E00000005D020500E800000050F8
+:10058000020500F000000050020500F800000050D5
+:10059000020500E40000007D020500EC0000007090
+:1005A000020500F400000070020500FC000000706D
+:1005B0000406100002000020020600DC000000011A
+:1005C000010600D80000000004060200000302201B
+:1005D000020600DC00000000010600B80000000078
+:1005E000010600C8000000000206016C00000000C7
+:1005F000010600BC00000000010600CC0000000065
+:1006000002060170000000000718040000910000BD
+:10061000081807D800050223071C00002BDC000087
+:10062000071C80002DE90AF8071D00002F521673E1
+:10063000071D800015DB2248081DB0B049EA0225DD
+:100640000118000000000000011800040000000074
+:1006500001180008000000000118000C0000000054
+:100660000118001000000000011800140000000034
+:1006700002180020000000010218002400000002FF
+:1006800002180028000000030218002C00000000DF
+:1006900002180030000000040218003400000001BD
+:1006A00002180038000000000218003C00000001A1
+:1006B000021800400000000402180044000000007E
+:1006C00002180048000000010218004C000000035E
+:1006D0000218005000000000021800540000000141
+:1006E00002180058000000040218005C000000001E
+:1006F00002180060000000010218006400000003FE
+:1007000002180068000000000218006C00000001E0
+:1007100002180070000000040218007400000000BD
+:1007200002180078000000040218007C000000039A
+:100730000618008000000002021800A400003FFF1D
+:10074000021800A8000003FF0218022400000000A5
+:1007500002180234000000000218024C00000000E1
+:10076000021802E4000000FF061810000000040058
+:10077000021B8BC000000001021B8000000000343F
+:10078000021B804000000018021B80800000000C4B
+:10079000021B80C0000000200C1B83000007A1206A
+:1007A0000A1B8300000001380B1B83000000138824
+:1007B0000A1B8340000000000C1B8340000001F472
+:1007C0000B1B834000000005021B83800007A12053
+:1007D000021B83C0000001F4021B14800000000112
+:1007E0000A1B148000000000061A1000000003B36A
+:1007F000041A1ECC00010227061A1ED000000008B1
+:10080000061A2008000000C8061A20000000000296
+:10081000041AAF4000100228061A3718000000041E
+:10082000061A371000000002061A500000000002ED
+:10083000061A500800000004061A501800000004B0
+:10084000061A502800000004061A50380000000460
+:10085000061A504800000004061A50580000000410
+:10086000061A506800000004061A507800000002C2
+:10087000041A52C000020238061A40500000000656
+:10088000041A40680002023A041A40400004023C84
+:10089000041A800000010240061A800400000003D0
+:1008A000041A801000010241061A8014000000039F
+:1008B000041A802000010242061A8024000000036E
+:1008C000041A803000010243061A8034000000033D
+:1008D000041A804000010244061A8044000000030C
+:1008E000041A805000010245061A805400000003DB
+:1008F000041A806000010246061A806400000003AA
+:10090000041A807000010247061A80740000000378
+:10091000041A808000010248061A80840000000347
+:10092000041A809000010249061A80940000000316
+:10093000041A80A00001024A061A80A400000003E5
+:10094000041A80B00001024B061A80B400000003B4
+:10095000041A80C00001024C061A80C40000000383
+:10096000041A80D00001024D061A80D40000000352
+:10097000041A80E00001024E061A80E40000000321
+:10098000041A80F00001024F061A80F400000003F0
+:10099000041A810000010250061A810400000003BD
+:1009A000041A811000010251061A8114000000038C
+:1009B000041A812000010252061A8124000000035B
+:1009C000041A813000010253061A8134000000032A
+:1009D000041A814000010254061A814400000003F9
+:1009E000041A815000010255061A815400000003C8
+:1009F000041A816000010256061A81640000000397
+:100A0000041A817000010257061A81740000000365
+:100A1000041A818000010258061A81840000000334
+:100A2000041A819000010259061A81940000000303
+:100A3000041A81A00001025A061A81A400000003D2
+:100A4000041A81B00001025B061A81B400000003A1
+:100A5000041A81C00001025C061A81C40000000370
+:100A6000041A81D00001025D061A81D4000000033F
+:100A7000041A81E00001025E061A81E4000000030E
+:100A8000041A81F00001025F061A81F400000003DD
+:100A9000041A820000010260061A820400000003AA
+:100AA000041A821000010261061A82140000000379
+:100AB000041A822000010262061A82240000000348
+:100AC000041A823000010263061A82340000000317
+:100AD000041A824000010264061A824400000003E6
+:100AE000041A825000010265061A825400000003B5
+:100AF000041A826000010266061A82640000000384
+:100B0000041A827000010267061A82740000000352
+:100B1000041A828000010268061A82840000000321
+:100B2000041A829000010269061A829400000003F0
+:100B3000041A82A00001026A061A82A400000003BF
+:100B4000041A82B00001026B061A82B4000000038E
+:100B5000041A82C00001026C061A82C4000000035D
+:100B6000041A82D00001026D061A82D4000000032C
+:100B7000041A82E00001026E061A82E400000003FB
+:100B8000041A82F00001026F061A82F400000003CA
+:100B9000041A830000010270061A83040000000397
+:100BA000041A831000010271061A83140000000366
+:100BB000041A832000010272061A83240000000335
+:100BC000041A833000010273061A83340000000304
+:100BD000041A834000010274061A834400000003D3
+:100BE000041A835000010275061A835400000003A2
+:100BF000041A836000010276061A83640000000371
+:100C0000041A837000010277061A8374000000033F
+:100C1000041A838000010278061A8384000000030E
+:100C2000041A839000010279061A839400000003DD
+:100C3000041A83A00001027A061A83A400000003AC
+:100C4000041A83B00001027B061A83B4000000037B
+:100C5000041A83C00001027C061A83C4000000034A
+:100C6000041A83D00001027D061A83D40000000319
+:100C7000041A83E00001027E061A83E400000003E8
+:100C8000041A83F00001027F061A83F400000003B7
+:100C9000041A840000010280061A84040000000384
+:100CA000041A841000010281061A84140000000353
+:100CB000041A842000010282061A84240000000322
+:100CC000041A843000010283061A843400000003F1
+:100CD000041A844000010284061A844400000003C0
+:100CE000041A845000010285061A8454000000038F
+:100CF000041A846000010286061A8464000000035E
+:100D0000041A847000010287061A8474000000032C
+:100D1000041A848000010288061A848400000003FB
+:100D2000041A849000010289061A849400000003CA
+:100D3000041A84A00001028A061A84A40000000399
+:100D4000041A84B00001028B061A84B40000000368
+:100D5000041A84C00001028C061A84C40000000337
+:100D6000041A84D00001028D061A84D40000000306
+:100D7000041A84E00001028E061A84E400000003D5
+:100D8000041A84F00001028F061A84F400000003A4
+:100D9000041A850000010290061A85040000000371
+:100DA000041A851000010291061A85140000000340
+:100DB000041A852000010292061A8524000000030F
+:100DC000041A853000010293061A853400000003DE
+:100DD000041A854000010294061A854400000003AD
+:100DE000041A855000010295061A8554000000037C
+:100DF000041A856000010296061A8564000000034B
+:100E0000041A857000010297061A85740000000319
+:100E1000041A858000010298061A858400000003E8
+:100E2000041A859000010299061A859400000003B7
+:100E3000041A85A00001029A061A85A40000000386
+:100E4000041A85B00001029B061A85B40000000355
+:100E5000041A85C00001029C061A85C40000000324
+:100E6000041A85D00001029D061A85D400000003F3
+:100E7000041A85E00001029E061A85E400000003C2
+:100E8000041A85F00001029F061A85F40000000391
+:100E9000041A8600000102A0061A8604000000035E
+:100EA000041A8610000102A1061A8614000000032D
+:100EB000041A8620000102A2061A862400000003FC
+:100EC000041A8630000102A3061A863400000003CB
+:100ED000041A8640000102A4061A8644000000039A
+:100EE000041A8650000102A5061A86540000000369
+:100EF000041A8660000102A6061A86640000000338
+:100F0000041A8670000102A7061A86740000000306
+:100F1000041A8680000102A8061A868400000003D5
+:100F2000041A8690000102A9061A869400000003A4
+:100F3000041A86A0000102AA061A86A40000000373
+:100F4000041A86B0000102AB061A86B40000000342
+:100F5000041A86C0000102AC061A86C40000000311
+:100F6000041A86D0000102AD061A86D400000003E0
+:100F7000041A86E0000102AE061A86E400000003AF
+:100F8000041A86F0000102AF061A86F4000000037E
+:100F9000041A8700000102B0061A8704000000034B
+:100FA000041A8710000102B1061A8714000000031A
+:100FB000041A8720000102B2061A872400000003E9
+:100FC000041A8730000102B3061A873400000003B8
+:100FD000041A8740000102B4061A87440000000387
+:100FE000041A8750000102B5061A87540000000356
+:100FF000041A8760000102B6061A87640000000325
+:10100000041A8770000102B7061A877400000003F3
+:10101000041A8780000102B8061A878400000003C2
+:10102000041A8790000102B9061A87940000000391
+:10103000041A87A0000102BA061A87A40000000360
+:10104000041A87B0000102BB061A87B4000000032F
+:10105000041A87C0000102BC061A87C400000003FE
+:10106000041A87D0000102BD061A87D400000003CD
+:10107000041A87E0000102BE061A87E4000000039C
+:10108000041A87F0000102BF061A87F4000000036B
+:10109000041A8800000102C0061A88040000000338
+:1010A000041A8810000102C1061A88140000000307
+:1010B000041A8820000102C2061A882400000003D6
+:1010C000041A8830000102C3061A883400000003A5
+:1010D000041A8840000102C4061A88440000000374
+:1010E000041A8850000102C5061A88540000000343
+:1010F000041A8860000102C6061A88640000000312
+:10110000041A8870000102C7061A887400000003E0
+:10111000041A8880000102C8061A888400000003AF
+:10112000041A8890000102C9061A8894000000037E
+:10113000041A88A0000102CA061A88A4000000034D
+:10114000041A88B0000102CB061A88B4000000031C
+:10115000041A88C0000102CC061A88C400000003EB
+:10116000041A88D0000102CD061A88D400000003BA
+:10117000041A88E0000102CE061A88E40000000389
+:10118000041A88F0000102CF061A88F40000000358
+:10119000041A8900000102D0061A89040000000325
+:1011A000041A8910000102D1061A891400000003F4
+:1011B000041A8920000102D2061A892400000003C3
+:1011C000041A8930000102D3061A89340000000392
+:1011D000041A8940000102D4061A89440000000361
+:1011E000041A8950000102D5061A89540000000330
+:1011F000041A8960000102D6061A896400000003FF
+:10120000041A8970000102D7061A897400000003CD
+:10121000041A8980000102D8061A8984000000039C
+:10122000041A8990000102D9061A8994000000036B
+:10123000041A89A0000102DA061A89A4000000033A
+:10124000041A89B0000102DB061A89B40000000309
+:10125000041A89C0000102DC061A89C400000003D8
+:10126000041A89D0000102DD061A89D400000003A7
+:10127000041A89E0000102DE061A89E40000000376
+:10128000041A89F0000102DF061A89F40000000345
+:10129000041A8A00000102E0061A8A040000000312
+:1012A000041A8A10000102E1061A8A1400000003E1
+:1012B000041A8A20000102E2061A8A2400000003B0
+:1012C000041A8A30000102E3061A8A34000000037F
+:1012D000041A8A40000102E4061A8A44000000034E
+:1012E000041A8A50000102E5061A8A54000000031D
+:1012F000041A8A60000102E6061A8A6400000003EC
+:10130000041A8A70000102E7061A8A7400000003BA
+:10131000041A8A80000102E8061A8A840000000389
+:10132000041A8A90000102E9061A8A940000000358
+:10133000041A8AA0000102EA061A8AA40000000327
+:10134000041A8AB0000102EB061A8AB400000003F6
+:10135000041A8AC0000102EC061A8AC400000003C5
+:10136000041A8AD0000102ED061A8AD40000000394
+:10137000041A8AE0000102EE061A8AE40000000363
+:10138000041A8AF0000102EF061A8AF40000000332
+:10139000041A8B00000102F0061A8B0400000003FF
+:1013A000041A8B10000102F1061A8B1400000003CE
+:1013B000041A8B20000102F2061A8B24000000039D
+:1013C000041A8B30000102F3061A8B34000000036C
+:1013D000041A8B40000102F4061A8B44000000033B
+:1013E000041A8B50000102F5061A8B54000000030A
+:1013F000041A8B60000102F6061A8B6400000003D9
+:10140000041A8B70000102F7061A8B7400000003A7
+:10141000041A8B80000102F8061A8B840000000376
+:10142000041A8B90000102F9061A8B940000000345
+:10143000041A8BA0000102FA061A8BA40000000314
+:10144000041A8BB0000102FB061A8BB400000003E3
+:10145000041A8BC0000102FC061A8BC400000003B2
+:10146000041A8BD0000102FD061A8BD40000000381
+:10147000041A8BE0000102FE061A8BE40000000350
+:10148000041A8BF0000102FF061A8BF4000000031F
+:10149000041A8C0000010300061A8C0400000003EB
+:1014A000041A8C1000010301061A8C1400000003BA
+:1014B000041A8C2000010302061A8C240000000389
+:1014C000041A8C3000010303061A8C340000000358
+:1014D000041A8C4000010304061A8C440000000327
+:1014E000041A8C5000010305061A8C5400000003F6
+:1014F000041A8C6000010306061A8C6400000003C5
+:10150000041A8C7000010307061A8C740000000393
+:10151000041A8C8000010308061A8C840000000362
+:10152000041A8C9000010309061A8C940000000331
+:10153000041A8CA00001030A061A8CA40000000300
+:10154000041A8CB00001030B061A8CB400000003CF
+:10155000041A8CC00001030C061A8CC4000000039E
+:10156000041A8CD00001030D061A8CD4000000036D
+:10157000041A8CE00001030E061A8CE4000000033C
+:10158000041A8CF00001030F061A8CF4000000030B
+:10159000041A8D0000010310061A8D0400000003D8
+:1015A000041A8D1000010311061A8D1400000003A7
+:1015B000041A8D2000010312061A8D240000000376
+:1015C000041A8D3000010313061A8D340000000345
+:1015D000041A8D4000010314061A8D440000000314
+:1015E000041A8D5000010315061A8D5400000003E3
+:1015F000041A8D6000010316061A8D6400000003B2
+:10160000041A8D7000010317061A8D740000000380
+:10161000041A8D8000010318061A8D84000000034F
+:10162000041A8D9000010319061A8D94000000031E
+:10163000041A8DA00001031A061A8DA400000003ED
+:10164000041A8DB00001031B061A8DB400000003BC
+:10165000041A8DC00001031C061A8DC4000000038B
+:10166000041A8DD00001031D061A8DD4000000035A
+:10167000041A8DE00001031E061A8DE40000000329
+:10168000041A8DF00001031F061A8DF400000003F8
+:10169000041A8E0000010320061A8E0400000003C5
+:1016A000041A8E1000010321061A8E140000000394
+:1016B000041A8E2000010322061A8E240000000363
+:1016C000041A8E3000010323061A8E340000000332
+:1016D000041A8E4000010324061A8E440000000301
+:1016E000041A8E5000010325061A8E5400000003D0
+:1016F000041A8E6000010326061A8E64000000039F
+:10170000041A8E7000010327061A8E74000000036D
+:10171000041A8E8000010328061A8E84000000033C
+:10172000041A8E9000010329061A8E94000000030B
+:10173000041A8EA00001032A061A8EA400000003DA
+:10174000041A8EB00001032B061A8EB400000003A9
+:10175000041A8EC00001032C061A8EC40000000378
+:10176000041A8ED00001032D061A8ED40000000347
+:10177000041A8EE00001032E061A8EE40000000316
+:10178000041A8EF00001032F061A8EF400000003E5
+:10179000041A8F0000010330061A8F0400000003B2
+:1017A000041A8F1000010331061A8F140000000381
+:1017B000041A8F2000010332061A8F240000000350
+:1017C000041A8F3000010333061A8F34000000031F
+:1017D000041A8F4000010334061A8F4400000003EE
+:1017E000041A8F5000010335061A8F5400000003BD
+:1017F000041A8F6000010336061A8F64000000038C
+:10180000041A8F7000010337061A8F74000000035A
+:10181000041A8F8000010338061A8F840000000329
+:10182000041A8F9000010339061A8F9400000003F8
+:10183000041A8FA00001033A061A8FA400000003C7
+:10184000041A8FB00001033B061A8FB40000000396
+:10185000041A8FC00001033C061A8FC40000000365
+:10186000041A8FD00001033D061A8FD40000000334
+:10187000041A8FE00001033E061A8FE400000007FF
+:10188000041A62C00020033F061AD0000000007254
+:10189000061AD24800000010061AD6B00000002038
+:1018A000061AD47000000090061AD46800000002E6
+:1018B000061AA000000001C4061A30000000001043
+:1018C000061A308000000010061A310000000010D7
+:1018D000061A318000000010061A330000000012C2
+:1018E000061A339000000070061AD4580000000257
+:1018F000061AD34800000002061AD3580000002040
+:10190000061AA710000001C4061A3040000000109B
+:10191000061A30C000000010061A31400000001006
+:10192000061A31C000000010061A334800000012E9
+:10193000061A355000000070061AD460000000023C
+:10194000061AD35000000002061AD3D80000002067
+:10195000021AAE2000000000061A5000000000022B
+:10196000061A508000000012041A40000002035FB3
+:10197000041A63C000020361061A7000000000042C
+:10198000061A320000000008021AAE24000000000F
+:10199000061A501000000002061A50C8000000127B
+:1019A000041A400800020363041A63C800020365B6
+:1019B000061A701000000004061A32200000000809
+:1019C000021AAE2800000000061A50200000000293
+:1019D000061A511000000012041A4010000203679A
+:1019E000041A63D000020369061A70200000000484
+:1019F000061A324000000008021AAE2C0000000057
+:101A0000061A503000000002061A51580000001259
+:101A1000041A40180002036B041A63D80002036D15
+:101A2000061A703000000004061A32600000000838
+:101A3000021AAE3000000000061A504000000002FA
+:101A4000061A51A000000012041A40200002036F81
+:101A5000041A63E000020371061A704000000004DB
+:101A6000061A328000000008021AAE34000000009E
+:101A7000061A505000000002061A51E80000001239
+:101A8000041A402800020373041A63E80002037575
+:101A9000061A705000000004061A32A00000000868
+:101AA000021AAE3800000000061A50600000000262
+:101AB000061A523000000012041A40300002037768
+:101AC000041A63F000020379061A70600000000433
+:101AD000061A32C000000008021AAE3C00000000E6
+:101AE000061A507000000002061A52780000001218
+:101AF000041A40380002037B041A63F80002037DD5
+:101B0000061A707000000004061A32E00000000897
+:101B10000200A468000B01C80200A294071D29114D
+:101B20000200A298000000000200A29C009C042475
+:101B30000200A2A0000000000200A2A4000002090E
+:101B40000200A270000000000200A2740000000069
+:101B50000200A270000000000200A2740000000059
+:101B60000200A270000000000200A2740000000049
+:101B70000200A270000000000200A2740000000039
+:101B8000020160A000000001020160A400000262E6
+:101B9000020160A800000002020160AC0000001811
+:101BA0000201620400000001020100B40000000113
+:101BB000020100B800000001020100DC0000000189
+:101BC0000201010000000001020101040000000107
+:101BD0000201007C003000000201008400000028A7
+:101BE0000201008C0000000002010130000000042E
+:101BF0000201025C00000001020103280000000055
+:101C0000020160580000FFFF020160700000000741
+:101C10000201608000000001020105540000003054
+:101C2000020100C400000001020100CC000000011C
+:101C3000020100F800000001020100F000000001B4
+:101C4000020100800030000002010088000000282E
+:101C500002010090000000000201013400000004B5
+:101C6000020102DC000000010201032C0000000060
+:101C70000201605C0000FFFF0201607400000007C9
+:101C800002016084000000010201056400000030D0
+:101C9000020100C800000001020100D000000001A4
+:101CA000020100FC00000001020100F4000000013C
+:101CB000020C100000000028020C20080000021195
+:101CC000020C200C00000200020C20100000020494
+:101CD000020C201C0000FFFF020C20200000FFFF70
+:101CE000020C20240000FFFF020C20280000FFFF50
+:101CF000020C203800000020020C203C00000021D3
+:101D0000020C204000000022020C204400000023AE
+:101D1000020C204800000024020C204C000000258A
+:101D2000020C205000000026020C20540000002766
+:101D3000020C205800000028020C205C0000002942
+:101D4000020C20600000002A020C20640000002B1E
+:101D5000020C20680000002C020C206C0000002DFA
+:101D6000020C20700000002E020C20740000002FD6
+:101D7000020C207800000010060C207C00000007F8
+:101D8000020C209800000011020C209C00000012A0
+:101D9000020C20A000000013060C20A40000001D6F
+:101DA000020C211800000001020C211C000000019F
+:101DB000020C212000000001060C21240000001D5F
+:101DC000020C219800000001060C219C0000000775
+:101DD000020C21B800000001020C21BC000000012F
+:101DE000020C21C000000001020C21C4000000010F
+:101DF000020C21C800000001020C21CC00000001EF
+:101E0000020C21D000000001020C21D400000001CE
+:101E1000020C21D800000001020C21DC00000001AE
+:101E2000020C21E000000001020C21E4000000018E
+:101E3000020C21E800000001020C21EC000000016E
+:101E4000020C21F000000001020C21F4000000014E
+:101E5000020C21F800000001060C21FC0000000724
+:101E6000020C221800000001060C221C00000007D2
+:101E7000020C223807FFFFFF020C223C0000003F4B
+:101E8000020C224007FFFFFF020C22440000000F5B
+:101E9000010C224800000000010C224C0000000050
+:101EA000010C225000000000010C22540000000030
+:101EB000010C225800000000010C225C0000000010
+:101EC000010C226000000000010C226400000000F0
+:101ED000010C226800000000010C226C00000000D0
+:101EE000010C227000000000010C227400000000B0
+:101EF000010C227800000000010C227C0000000090
+:101F00000C0C2000000003E80A0C20000000000177
+:101F10000B0C20000000000A020C40080000101109
+:101F2000020C400C00001000020C401000001004D5
+:101F3000020C401400001021020C401C0000FFFFA6
+:101F4000020C40200000FFFF020C40240000FFFFB5
+:101F5000020C40280000FFFF020C40380000004641
+:101F6000020C403C00000010060C40400000000243
+:101F7000020C404800000018020C404C000000F029
+:101F8000060C40500000001F020C40CC0000000175
+:101F9000060C40D00000003A020C41B800000001DD
+:101FA000060C41BC00000003020C41C80000000107
+:101FB000020C41CC00000001060C41D00000001AC8
+:101FC000020C423807FFFFFF020C423C0000003FBA
+:101FD000020C424007FFFFFF020C42440000000FCA
+:101FE000010C424800000000010C424C00000000BF
+:101FF000010C425000000000010C4254000000009F
+:10200000010C425800000000010C425C000000007E
+:10201000010C426000000000010C4264000000005E
+:10202000010C426800000000010C426C000000003E
+:10203000010C427000000000010C4274000000001E
+:10204000010C427800000000010C427C00000000FE
+:10205000010C4280000000000C0C4000000003E86E
+:102060000A0C4000000000010B0C40000000000AB8
+:10207000060D400000000A00020D0044000000327E
+:10208000020D008C02150020020D009002150020A8
+:10209000020D009408100000020D009800000033AB
+:1020A000020D009C00000002020D00A000000000D4
+:1020B000020D00A400000005020D00A800000005AC
+:1020C000060D00AC00000002020D00B4000000028A
+:1020D000020D00B800000003020D00BC0000000269
+:1020E000020D00C000000001020D00C80000000247
+:1020F000020D00CC00000002020D015C0000000196
+:10210000020D016400000001020D016800000002E0
+:10211000020D020400000001020D020C000000206C
+:10212000020D021000000040020D021400000040E9
+:10213000020D022000000003020D0224000000181E
+:10214000060D028000000012040D03000018037F3A
+:10215000060D03600000000C020D004C00000001A1
+:10216000020D005000000002020D005400000000AB
+:10217000020D005800000008060D005C000000047D
+:10218000020D00C400000004020D00040000000164
+:10219000020D000800000001020D000C000000010B
+:1021A000020D001000000001020D001400000001EB
+:1021B000020D001800000001020D001C00000001CB
+:1021C000020D002000000001020D002400000001AB
+:1021D000020D002800000001020D002C000000018B
+:1021E000020D003000000001020D0034000000016B
+:1021F000020D003800000001020D003C000000014B
+:10220000020D011400000009020D011C0000000A6B
+:10221000020D012400000000020D012C000000004E
+:10222000020D013400000000020D013C0000000B13
+:10223000020D014400000000020D011800000029F9
+:10224000020D01200000002A020D012800000020DC
+:10225000020D013000000020020D013800000020B6
+:10226000020D01400000002B020D0148000000207B
+:10227000020D011400000019020D011C0000001ADB
+:10228000020D012400000010020D012C00000010BE
+:10229000020D013400000010020D013C0000001B83
+:1022A000020D014400000010020D01180000003969
+:1022B000020D01200000003A020D0128000000304C
+:1022C000020D013000000030020D01380000003026
+:1022D000020D01400000003B020D014800000030EB
+:1022E000020D011400000049020D011C0000004A0B
+:1022F000020D012400000040020D012C00000040EE
+:10230000020D013400000040020D013C0000004BB2
+:10231000020D014400000040020D01180000006998
+:10232000020D01200000006A020D0128000000607B
+:10233000020D013000000060020D01380000006055
+:10234000020D01400000006B020D0148000000601A
+:10235000020D011400000059020D011C0000005A7A
+:10236000020D012400000050020D012C000000505D
+:10237000020D013400000050020D013C0000005B22
+:10238000020D014400000050020D01180000007908
+:10239000020D01200000007A020D012800000070EB
+:1023A000020D013000000070020D013800000070C5
+:1023B000020D01400000007B020D0148000000708A
+:1023C000060E200000000800020E004C0000003243
+:1023D000020E009402150020020E00980215002043
+:1023E000020E009C00000030020E00A00810000049
+:1023F000020E00A400000033020E00A8000000300E
+:10240000020E00AC00000031020E00B0000000021D
+:10241000020E00B400000004020E00B8000000002C
+:10242000020E00BC00000002020E00C0000000020C
+:10243000020E00C400000000020E00C800000002EE
+:10244000020E00CC00000007020E00D000000002C7
+:10245000020E00D400000002020E00D800000001AD
+:10246000020E014400000001020E014C00000001B8
+:10247000020E015000000002020E020400000001E2
+:10248000020E020C00000040020E0210000000408C
+:10249000020E021C00000004020E022000000020B8
+:1024A000020E02240000000E020E02280000001B93
+:1024B000060E030000000012040E0280001B0397AA
+:1024C000060E02EC00000005020E00540000000C95
+:1024D000020E00580000000C020E005C000000001C
+:1024E000020E006000000010020E006400000010E8
+:1024F000060E006800000003020E00DC000000036E
+:10250000020E000400000001020E0008000000019D
+:10251000020E000C00000001020E0010000000017D
+:10252000020E001400000001020E0018000000015D
+:10253000020E001C00000001020E0020000000013D
+:10254000020E002400000001020E0028000000011D
+:10255000020E002C00000001020E003000000001FD
+:10256000020E003400000001020E003800000001DD
+:10257000020E003C00000001020E004000000001BD
+:10258000020E004400000001020E01100000000FC6
+:10259000020E011800000000020E012000000000E1
+:1025A000020E012800000000020E01140000002F9E
+:1025B000020E011C00000020020E01240000000099
+:1025C000020E012C00000000020E01100000001F8E
+:1025D000020E011800000010020E01200000000091
+:1025E000020E012800000000020E01140000003F4E
+:1025F000020E011C00000030020E01240000000049
+:10260000020E012C00000000020E01100000004F1D
+:10261000020E011800000040020E01200000000020
+:10262000020E012800000000020E01140000006FDD
+:10263000020E011C00000060020E012400000000D8
+:10264000020E012C00000000020E01100000005FCD
+:10265000020E011800000050020E012000000000D0
+:10266000020E012800000000020E01140000007F8D
+:10267000020E011C00000070020E01240000000088
+:10268000020E012C000000000730040000C800000A
+:10269000083007D8000503B207340000332C0000CF
+:1026A0000734800030AC0CCC07350000353318F807
+:1026B000073580002A7126450736000018DA30E217
+:1026C00008364670373203B40130000000000000C5
+:1026D000013000040000000001300008000000008C
+:1026E0000130000C0000000001300010000000006C
+:1026F0000130001400000000023000200000000142
+:102700000230002400000002023000280000000314
+:102710000230002C000000000230003000000004F5
+:1027200002300034000000010230003800000000D8
+:102730000230003C000000010230004000000004B4
+:102740000230004400000000023000480000000198
+:102750000230004C00000003023000500000000076
+:102760000230005400000001023000580000000454
+:102770000230005C00000000023000600000000138
+:102780000230006400000003023000680000000016
+:102790000230006C000000010230007000000004F4
+:1027A00002300074000000000230007800000004D5
+:1027B0000230007C000000030630008000000002B0
+:1027C000023000A400003FFF023000A8000003FF19
+:1027D0000230022400000000023002340000000039
+:1027E0000230024C00000000023002E40000FFFF53
+:1027F000063020000000080002338BC000000001FA
+:10280000023380000000001A023380400000004EB6
+:102810000233808000000010023380C000000020DE
+:102820000C3383000007A1200A3383000000013825
+:102830000B338300000013880A338340000000003C
+:102840000C338340000001F40B338340000000058B
+:10285000023383800007A120023383C0000001F40B
+:1028600002331480000000010A33148000000000CD
+:10287000063280000000010206322008000000C875
+:10288000063220000000000204328EA0001003B6C1
+:1028900006323EB00000000606323ED800000002BC
+:1028A00006323E800000000A04323EA8000203C641
+:1028B00006323E00000000200632500000000400F6
+:1028C0000632400000000004043274C0000203C855
+:1028D00006324110000000020632D0000000003035
+:1028E0000632DD40000000440632DA00000000D06D
+:1028F0000632DEA0000000020632E0000000080000
+:1029000006328450000001180632100000000188D1
+:102910000632500000000020063251000000002066
+:102920000632520000000020063253000000002052
+:10293000063254000000002006325500000000203E
+:10294000063256000000002006325700000000202A
+:102950000632580000000020063259000000002016
+:1029600006325A000000002006325B000000002002
+:1029700006325C000000002006325D0000000020EE
+:1029800006325E000000002006325F0000000020DA
+:1029900006328DF00000000204328E00000203CAED
+:1029A00006328E08000000020632DE9000000002AF
+:1029B00006321C4000000038063288B000000118C2
+:1029C00006321620000001880632508000000020E8
+:1029D00006325180000000200632528000000020A4
+:1029E0000632538000000020063254800000002090
+:1029F000063255800000002006325680000000207C
+:102A00000632578000000020063258800000002067
+:102A1000063259800000002006325A800000002053
+:102A200006325B800000002006325C80000000203F
+:102A300006325D800000002006325E80000000202B
+:102A400006325F800000002006328DF80000000290
+:102A500004328E10000203CC06328E1800000002F1
+:102A60000632DE980000000206321D200000003809
+:102A700002328D50000000000632401000000002BB
+:102A800002328D5400000000063240200000000297
+:102A900002328D5800000000063240300000000273
+:102AA00002328D5C0000000006324040000000024F
+:102AB00002328D600000000006324050000000022B
+:102AC00002328D6400000000063240600000000207
+:102AD00002328D68000000000632407000000002E3
+:102AE00002328D6C000000000632408000000002BF
+:102AF000072004000091000008200780001003CE8A
+:102B0000072400002B0B00000724800015080AC3CF
+:102B10000824AA10692403D001200000000000004E
+:102B20000120000400000000012000080000000057
+:102B30000120000C00000000012000100000000037
+:102B4000012000140000000002200020000000010D
+:102B500002200024000000020220002800000003E0
+:102B60000220002C000000000220003000000004C1
+:102B700002200034000000010220003800000000A4
+:102B80000220003C00000001022000400000000480
+:102B90000220004400000000022000480000000164
+:102BA0000220004C00000003022000500000000042
+:102BB0000220005400000001022000580000000420
+:102BC0000220005C00000000022000600000000104
+:102BD00002200064000000030220006800000000E2
+:102BE0000220006C000000010220007000000004C0
+:102BF00002200074000000000220007800000004A1
+:102C00000220007C0000000306200080000000027B
+:102C1000022000A400003FFF022000A8000003FFE4
+:102C20000220022400000000022002340000000004
+:102C30000220024C00000000022002E40000FFFF1E
+:102C4000062020000000080002238BC000000001C5
+:102C500002238000000000100223804000000012C8
+:102C60000223808000000030022380C00000000E9C
+:102C70000C2383000007A1200A23830000000138F1
+:102C80000B238300000013880A2383400000000008
+:102C90000C238340000001F40B2383400000000557
+:102CA000022383800007A120022383C0000001F4D7
+:102CB00002231480000000010A2314800000000099
+:102CC000062210000000004206222008000000C872
+:102CD00006222000000000020622B000000000C60C
+:102CE0000422B318000503D20622B32C0000000B07
+:102CF0000422B358000503D70622B36C0000000B72
+:102D00000422B398000503DC0622B3AC0000000BDC
+:102D10000422B3D8000503E10622B3EC0000000B47
+:102D20000422B418000503E60622B42C0000000BB0
+:102D30000422B458000503EB0622B46C0000000B1B
+:102D40000422B498000503F00622B4AC0000000B86
+:102D50000422B4D8000503F50622B4EC0000000BF1
+:102D60000422B518000503FA0622B52C0000000B5A
+:102D70000422B558000503FF0622B56C0000000BC5
+:102D80000422B598000504040622B5AC0000000B2F
+:102D90000422B5D8000504090622B5EC0000000B9A
+:102DA0000422B6180005040E0622B62C0000000B03
+:102DB0000422B658000504130622B66C0000000B6E
+:102DC0000422B698000504180622B6AC0000000BD9
+:102DD0000422B6D80005041D0622B6EC0000000B44
+:102DE0000422B718000504220622B72C0000000BAD
+:102DF0000422B758000504270622B76C0000000B18
+:102E00000422B7980005042C0622B7AC0000000B82
+:102E10000422B7D8000504310622B7EC0000000BED
+:102E20000422B818000504360622B82C0000000B56
+:102E30000422B8580005043B0622B86C0000000BC1
+:102E40000422B898000504400622B8AC0000000B2C
+:102E50000422B8D8000504450622B8EC0000000B97
+:102E60000422B9180005044A0622B92C0000000B00
+:102E70000422B9580005044F0622B96C0000000B6B
+:102E80000422B998000504540622B9AC0000000BD6
+:102E90000422B9D8000504590622B9EC0000000B41
+:102EA0000422BA180005045E0622BA2C0000000BAA
+:102EB0000422BA58000504630622BA6C0000000B15
+:102EC0000422BA98000504680622BAAC0000000B80
+:102ED0000422BAD80005046D0622BAEC00000005F1
+:102EE0000622BB00000000530422BC4C0001047207
+:102EF0000622BC50000000030422BC5C00010473E5
+:102F00000622BC60000000030422BC6C00010474B3
+:102F10000622BC70000000030422BC7C0001047582
+:102F20000622BC80000000030422BC8C0001047651
+:102F30000622BC90000000030422BC9C0001047720
+:102F40000622BCA0000000030422BCAC00010478EF
+:102F50000622BCB0000000030422BCBC00010479BE
+:102F60000622880000000100062280000000020006
+:102F7000042212700010047A06223000000000C003
+:102F800006226700000001000622900000000400F5
+:102F900004226B080020048A022212C0FFFFFFFFF8
+:102FA000062211E800000002062212C800000009F3
+:102FB000062212EC0000000906228C000000000826
+:102FC0000222114800000000062213200000000623
+:102FD000062233000000000206226040000000309C
+:102FE00006228C20000000080222114C0000000084
+:102FF00006221338000000060622330800000002F3
+:10300000062261000000003006228C40000000080B
+:10301000022211500000000006221350000000069A
+:103020000622331000000002062261C000000030BA
+:1030300006228C60000000080222115400000000EB
+:103040000622136800000006062233180000000262
+:10305000062262800000003006228C8000000008FA
+:103060000222115800000000062213800000000612
+:1030700006223320000000020622634000000030D8
+:1030800006228CA0000000080222115C0000000053
+:1030900006221398000000060622332800000002D2
+:1030A000062264000000003006228CC000000008E8
+:1030B0000222116000000000062213B0000000068A
+:1030C0000622333000000002062264C000000030F7
+:1030D00006228CE0000000080222116400000000BB
+:1030E000062213C800000006062233380000000242
+:1030F0000622658000000030021610000000002843
+:1031000002170008000000020217002C0000000354
+:103110000217003C000000040217004800000002F3
+:103120000217004C000000900217005000000090B1
+:103130000217005400800090021700580810000089
+:10314000021700600000008A02170064000000807F
+:1031500002170068000000810217006C0000008068
+:10316000021700700000000602170078000007D068
+:103170000217007C0000076C02170038007C100466
+:10318000021700040000000F061640240000000291
+:10319000021640700000001C0216420800000001E8
+:1031A0000216421000000001021642200000000139
+:1031B0000216422800000001021642300000000101
+:1031C00002164238000000010216426000000002B0
+:1031D0000C16401C0003D0900A16401C0000009CF6
+:1031E0000B16401C000009C4021640300000000805
+:1031F000021640340000000C021640380000001097
+:1032000002164044000000200216400000000001A9
+:10321000021640D80000000102164008000000011C
+:103220000216400C000000010216401000000001D0
+:103230000216424000000000021642480000000052
+:103240000616427000000002021642500000000004
+:1032500002164258000000000616428000000002DC
+:1032600002166008000012240216600C0000121002
+:1032700002166010000012140216601C0000FFFF0E
+:10328000021660200000FFFF021660240000FFFF0E
+:10329000021660280000FFFF0216603800000020C0
+:1032A0000216603C0000002006166040000000028C
+:1032B00002166048000000230216604C0000002443
+:1032C000021660500000002502166054000000261F
+:1032D00002166058000000270216605C00000029FA
+:1032E000021660600000002A021660640000002BD5
+:1032F000021660680000002C0216606C0000002DB1
+:1033000002166070000000EC0216607400000011EC
+:1033100002166078000000120616607C0000000FA4
+:10332000021660B800000001021660BC0000000137
+:10333000061660C00000000C021660F000000001DC
+:10334000061660F400000031021661B800000001AA
+:10335000061661BC0000000D021661F000000001BD
+:10336000061661F4000000110216623807FFFFFF25
+:103370000216623C0000003F0216624007FFFFFF9A
+:10338000021662440000000F0116624800000000AF
+:103390000116624C0000000001166250000000009F
+:1033A000011662540000000001166258000000007F
+:1033B0000116625C0000000001166260000000005F
+:1033C000011662640000000001166268000000003F
+:1033D0000116626C0000000001166270000000001F
+:1033E00001166274000000000116627800000000FF
+:1033F0000116627C000000000C166000000003E86B
+:103400000A166000000000010B1660000000000AB0
+:1034100002168040000000060216804400000005ED
+:10342000021680480000000A0216804C00000005C9
+:103430000216805400000002021680CC0000000436
+:10344000021680D000000004021680D400000004A0
+:10345000021680D800000004021680DC0000000480
+:10346000021680E000000004021680E40000000460
+:10347000021680E800000004021688040000000420
+:10348000021680300000007C021680340000003DEF
+:10349000021680380000003F0216803C0000009CAD
+:1034A000021680F000000007061680F400000005F8
+:1034B0000216880C010101010216810800000000BB
+:1034C0000216810C000000040216811000000004A6
+:1034D0000216811400000002021688100801200460
+:1034E00002168118000000050216811C000000056C
+:1034F000021681200000000502168124000000054C
+:103500000216882C200810010216812800000008ED
+:103510000216812C00000006021681300000000710
+:1035200002168134000000000216883001010120DB
+:1035300006168138000000040216883401010101DA
+:1035400002168148000000000216814C00000004B1
+:10355000021681500000000402168154000000028F
+:103560000216883808012004021681580000000560
+:103570000216815C00000005021681600000000553
+:1035800002168164000000050216883C2008100124
+:1035900002168168000000080216816C0000000617
+:1035A00002168170000000070216817400000001FD
+:1035B00002168840010101200216817800000001F6
+:1035C0000216817C000000010216818000000001CB
+:1035D00002168184000000010216884401010101E5
+:1035E00002168188000000010216818C0000000490
+:1035F000021681900000000402168194000000026F
+:10360000021688480801200402168198000000056F
+:103610000216819C00000005021681A00000000532
+:10362000021681A40000000502168814200810016B
+:10363000021681A800000008021681AC00000006F6
+:10364000021681B000000007021681B400000001DC
+:103650000216881801010120021681B8000000013D
+:10366000021681BC00000001021681C000000001AA
+:10367000021681C4000000010216881C010101012C
+:10368000021681C800000001021681CC000000046F
+:10369000021681D000000004021681D4000000024E
+:1036A0000216882008012004021681D800000005B7
+:1036B000021681DC00000005021681E00000000512
+:1036C000021681E40000000502168824200810017B
+:1036D000021681E800000008021681EC00000006D6
+:1036E000021681F0000000070216E40C0000000042
+:1036F00002168828010101200616E41000000004CB
+:103700000216E000010101010216E42000000000A1
+:103710000216E424000000040216E428000000045D
+:103720000216E42C000000020216E0040801200446
+:103730000216E430000000050216E4340000000523
+:103740000216E438000000050216E43C0000000503
+:103750000216E008200810010216E44000000008EC
+:103760000216E444000000060216E44800000007C8
+:103770000216E44C000000000216E00C01010120DA
+:103780000616E450000000040216E01001010101D9
+:103790000216E460000000000216E4640000000469
+:1037A0000216E468000000040216E46C0000000247
+:1037B0000216E014080120040216E470000000055F
+:1037C0000216E474000000050216E478000000050B
+:1037D0000216E47C000000050216E0182008100123
+:1037E0000216E480000000080216E48400000006CF
+:1037F0000216E488000000070216E48C00000001B5
+:103800000216E01C010101200216E49000000001F4
+:103810000216E494000000010216E4980000000182
+:103820000216E49C000000010216E02001010101E3
+:103830000216E4A0000000010216E4A40000000447
+:103840000216E4A8000000040216E4AC0000000226
+:103850000216E024080120040216E4B0000000056E
+:103860000216E4B4000000050216E4B800000005EA
+:103870000216E4BC000000050216E0282008100132
+:103880000216E4C0000000080216E4C400000006AE
+:103890000216E4C8000000070216E4CC0000000194
+:1038A0000216E02C010101200216E4D00000000104
+:1038B0000216E4D4000000010216E4D80000000162
+:1038C0000216E4DC000000010216E03001010101F3
+:1038D0000216E4E0000000010216E4E40000000427
+:1038E0000216E4E8000000040216E4EC0000000206
+:1038F0000216E034080120040216E4F0000000057E
+:103900000216E4F4000000050216E4F800000005C9
+:103910000216E4FC000000050216E0382008100141
+:103920000216E500000000080216E504000000068B
+:103930000216E508000000070216E03C0101012024
+:1039400002168240003F003F021682440000000041
+:103950000216E524003F003F0216E52800000000A3
+:1039600002168248000000000216824C003F003F11
+:103970000216E52C000000000216E530003F003F73
+:10398000021682500100010002168254010001005B
+:103990000216E534010001000216E53801000100BD
+:1039A00006168258000000020216E53C00000000E6
+:1039B0000216E540000000000216826000C000C050
+:1039C0000216826400C000C00216E54400C000C0B8
+:1039D0000216E54800C000C0021682681E001E00E4
+:1039E0000216826C1E001E000216E54C1E001E0010
+:1039F0000216E5501E001E000216827040004000B4
+:103A000002168274400040000216E5544000400057
+:103A10000216E558400040000216827880008000BF
+:103A20000216827C800080000216E55C8000800027
+:103A30000216E560800080000216828020002000CF
+:103A400002168284200020000216E5642000200077
+:103A50000216E56820002000061682880000000299
+:103A60000216E56C000000000216E5700000000080
+:103A700002168290000000000216829400000000EE
+:103A80000216E574000000000216E5780000000050
+:103A900002168298000000000216829C00000000BE
+:103AA0000216E57C000000000216E5800000000020
+:103AB000021682A000000000021682A4000000018D
+:103AC000061682A80000000A021681F400000C0805
+:103AD000021681F800000040021681FC000001007F
+:103AE0000216820000000020021682040000001767
+:103AF00002168208000000800216820C00000200FC
+:103B000002168210000000000216821801FF01FF59
+:103B10000216821401FF01FF0216E51001FF01FFEA
+:103B20000216E50C01FF01FF0216823C00000013A3
+:103B3000021680900000013F0216806000000140E4
+:103B40000216806400000140061680680000000232
+:103B500002168070000000C0061680740000000786
+:103B60000216809C00000048021680A00000004859
+:103B7000061680A400000002021680AC0000004877
+:103B8000061680B000000007021682380000800090
+:103B900002168234000025E40216809400007FFFA4
+:103BA00002168220000F000F0216821C000F000F69
+:103BB0000216E518000F000F0216E514000F000FA3
+:103BC000021682280000000002168224FFFFFFFF79
+:103BD0000216E520000000000216E51CFFFFFFFFB3
+:103BE0000216E6BC000000000216E6C0000000025B
+:103BF0000216E6C4000000010216E6C80000000339
+:103C00000216E6CC000000040216E6D00000000612
+:103C10000216E6D4000000050216E6D800000007F0
+:103C2000021680EC000000FF0214000000000001FA
+:103C30000214000C0000000102140040000000010A
+:103C40000214004400007FFF0214000C000000007A
+:103C500002140000000000000214006C00000000CC
+:103C600002140004000000010214003000000001F2
+:103C700002140004000000000214005C00000000B8
+:103C800002140008000000010214003400000001CA
+:103C90000214000800000000021400600000000090
+:103CA00006028000000020000202005800000032DE
+:103CB000020200A003150020020200A40315002048
+:103CC000020200A801000030020200AC081000004F
+:103CD000020200B000000033020200B40000003015
+:103CE000020200B800000031020200BC0000000324
+:103CF000020200C000000006020200C4000000032F
+:103D0000020200C800000003020200CC0000000212
+:103D1000020200D000000000020200D400000002F5
+:103D2000020200DC00000000020200E000000006C9
+:103D3000020200E400000004020200E800000002A9
+:103D4000020200EC00000002020200F0000000018C
+:103D5000020200FC00000006020201200000000038
+:103D60000202013400000002020201B00000000162
+:103D70000202020C00000001020202140000000115
+:103D80000202021800000002020204040000000106
+:103D90000202040C00000040020204100000004077
+:103DA0000202041C000000040202042000000020A3
+:103DB0000202042400000002020204280000002085
+:103DC000060205000000001204020480002004AA7C
+:103DD000020200600000000F020200640000000701
+:103DE00002020068000000000202006C0000000EE9
+:103DF000020200700000000E0602007400000003C2
+:103E0000020200F4000000040202000400000001AD
+:103E100002020008000000010202000C0000000184
+:103E20000202001000000001020200140000000164
+:103E300002020018000000010202001C0000000144
+:103E40000202002000000001020200240000000124
+:103E500002020028000000010202002C0000000104
+:103E600002020030000000010202003400000001E4
+:103E700002020038000000010202003C00000001C4
+:103E800002020040000000010202004400000001A4
+:103E900002020048000000010202004C0000000184
+:103EA000020200500000000102020108000000C8E8
+:103EB0000202011800000002020201C4000000001A
+:103EC000020201CC00000000020201D40000000246
+:103ED000020201DC00000002020201E4000000FF17
+:103EE000020201EC000000FF0202010000000000DD
+:103EF0000202010C000000C80202011C00000002C6
+:103F0000020201C800000000020201D0000000000F
+:103F1000020201D800000002020201E000000002DB
+:103F2000020201E8000000FF020201F0000000FFB1
+:103F3000020201040000000002020108000000C8A3
+:103F40000202011800000002020201C40000000089
+:103F5000020201CC00000000020201D400000002B5
+:103F6000020201DC00000002020201E4000000FF86
+:103F7000020201EC000000FF02020100000000004C
+:103F80000202010C000000C80202011C0000000235
+:103F9000020201C800000000020201D0000000007F
+:103FA000020201D800000002020201E0000000024B
+:103FB000020201E8000000FF020201F0000000FF21
+:103FC000020201040000000002020108000000C813
+:103FD0000202011800000002020201C400000000F9
+:103FE000020201CC00000000020201D40000000225
+:103FF000020201DC00000002020201E4000000FFF6
+:10400000020201EC000000FF0202010000000000BB
+:104010000202010C000000C80202011C00000002A4
+:10402000020201C800000000020201D000000000EE
+:10403000020201D800000002020201E000000002BA
+:10404000020201E8000000FF020201F0000000FF90
+:10405000020201040000000002020108000000C882
+:104060000202011800000002020201C40000000068
+:10407000020201CC00000000020201D40000000294
+:10408000020201DC00000002020201E4000000FF65
+:10409000020201EC000000FF02020100000000002B
+:1040A0000202010C000000C80202011C0000000214
+:1040B000020201C800000000020201D0000000005E
+:1040C000020201D800000002020201E0000000022A
+:1040D000020201E8000000FF020201F0000000FF00
+:1040E00002020104000000000728040000A10000F3
+:1040F000082807B8000904CA072C000034F700009C
+:10410000072C800039250D3E072D000037CD1B8878
+:10411000072D80003292297C072E00001AF33621E9
+:10412000082E4390378E04CC0128000000000000C8
+:104130000128000400000000012800080000000021
+:104140000128000C00000000012800100000000001
+:1041500001280014000000000228002000000001D7
+:1041600002280024000000020228002800000003AA
+:104170000228002C0000000002280030000000048B
+:10418000022800340000000102280038000000006E
+:104190000228003C0000000102280040000000044A
+:1041A000022800440000000002280048000000012E
+:1041B0000228004C0000000302280050000000000C
+:1041C00002280054000000010228005800000004EA
+:1041D0000228005C000000000228006000000001CE
+:1041E00002280064000000030228006800000000AC
+:1041F0000228006C0000000102280070000000048A
+:10420000022800740000000002280078000000046A
+:104210000228007C00000003062800800000000245
+:10422000022800A400003FFF022800A8000003FFAE
+:1042300002280224000000000228023400000000CE
+:104240000228024C00000000022802E40000FFFFE8
+:104250000628200000000800022B8BC0000000018F
+:10426000022B800000000000022B8040000000189C
+:10427000022B80800000000C022B80C00000006632
+:104280000C2B83000007A1200A2B830000000138BB
+:104290000B2B8300000013880A2B834000000000D2
+:1042A0000C2B8340000001F40B2B83400000000521
+:1042B000022B83800007A120022B83C0000001F4A1
+:1042C000022B1480000000010A2B14800000000063
+:1042D000062A9AF800000004042A9B08000204CE73
+:1042E000062A9B1000000006062A90800000004865
+:1042F000062A2008000000C8062A2000000000024C
+:10430000062A91A800000086062A900000000020DE
+:10431000062A93C800000003042A93D4000104D0A5
+:10432000062A9DA800000002042A9498000404D1E3
+:10433000042A9D58000104D5062A9D5C0000001146
+:10434000042ACB20001004D6042A3000000204E620
+:10435000062A300800000100062A40400000001034
+:10436000042A4000001004E8042A8408000204F82B
+:10437000062A9DA000000002062AB000000000509E
+:10438000062ABB7000000070062AB150000000022F
+:10439000062ABB6000000004062AD00000000800C6
+:1043A000062AC00000000150062A94A8000000322E
+:1043B000062A502000000002062A503000000002A9
+:1043C000062A500000000002062A501000000002D9
+:1043D000022A520800000001042A9B28000204FA65
+:1043E000062A963800000022042A96C0000104FC28
+:1043F000062A96C400000003062A976800000022DF
+:10440000042A97F0000104FD062A97F40000000337
+:10441000062A989800000022042A9920000104FE30
+:10442000062A992400000003062A99C800000022E9
+:10443000042A9A50000104FF062A9A54000000033F
+:10444000062AB14000000002062AC54000000150C3
+:10445000062A957000000032062A5028000000024B
+:10446000062A503800000002062A50080000000208
+:10447000062A501800000002022A520C0000000117
+:10448000042A9B3000020500062A96D00000002274
+:10449000042A975800010502062A975C00000003D1
+:1044A000062A980000000022042A988800010503CB
+:1044B000062A988C00000003062A9930000000228A
+:1044C000042A99B800010504062A99BC00000003DB
+:1044D000062A9A6000000022042A9AE800010505D5
+:1044E000062A9AEC00000003062AB14800000002E8
+:1044F000022ACA8000000000042A9B38001005062A
+:10450000062A50480000000E022ACA84000000005B
+:10451000042A9B7800100516062A50800000000E21
+:10452000022ACA8800000000042A9BB80010052651
+:10453000062A50B80000000E022ACA8C00000000B3
+:10454000042A9BF800100536062A50F00000000EE1
+:10455000022ACA9000000000042A9C380010054678
+:10456000062A51280000000E022ACA94000000000A
+:10457000042A9C7800100556062A51600000000E9F
+:10458000022ACA9800000000042A9CB800100566A0
+:10459000062A51980000000E022ACA9C0000000062
+:1045A000042A9CF800100576062A51D00000000E5F
+:1045B000021010080000000102101050000000015D
+:1045C000021010000003D000021010040000003D93
+:1045D0000910180002000586091011000010078656
+:1045E0000610114000000008091011600010079625
+:1045F000061011A00000001806102400000000E0C2
+:104600000210201C00000000021020200000000109
+:10461000021020C00000000202102004000000016F
+:10462000021020080000000109103C00000507A648
+:1046300009103800000507AB09103820000507B045
+:1046400006104C000000010002104028000000107D
+:104650000210404400003FFF0210405800280000B4
+:10466000021040840084924A02104058000000006A
+:104670000210800000001080021080AC00000000DA
+:1046800002108038000000100210810000000000BD
+:10469000061081200000000202108008000002B510
+:1046A0000210801000000000061082000000004A86
+:1046B000021081080001FFFF061081400000000287
+:1046C0000210800000001A800610900000000024F4
+:1046D000061091200000004A061093700000004A66
+:1046E000061095C00000004A0210800400001080EF
+:1046F000021080B0000000010210803C0000001099
+:104700000210810400000000061081280000000251
+:104710000210800C000002B502108014000000009E
+:10472000061084000000004A0210810C0001FFFF07
+:1047300006108148000000020210800400001A8068
+:104740000610909000000024061092480000004AD5
+:10475000061094980000004A061096E80000004AEF
+:104760000210800000001080021080AC00000002E7
+:1047700002108038000000100210810000000000CC
+:10478000061081200000000202108008000002B51F
+:104790000210801000000000061082000000004A95
+:1047A000021081080001FFFF061081400000000296
+:1047B0000210800000001A80061090000000002403
+:1047C000061091200000004A061093700000004A75
+:1047D000061095C00000004A0210800400001080FE
+:1047E000021080B0000000030210803C00000010A6
+:1047F0000210810400000000061081280000000261
+:104800000210800C000002B50210801400000000AD
+:10481000061084000000004A0210810C0001FFFF16
+:1048200006108148000000020210800400001A8077
+:104830000610909000000024061092480000004AE4
+:10484000061094980000004A061096E80000004AFE
+:104850000210800000001080021080AC00000004F4
+:1048600002108038000000100210810000000000DB
+:10487000061081200000000202108008000002B52E
+:104880000210801000000000061082000000004AA4
+:10489000021081080001FFFF0610814000000002A5
+:1048A0000210800000001A80061090000000002412
+:1048B000061091200000004A061093700000004A84
+:1048C000061095C00000004A02108004000010800D
+:1048D000021080B0000000050210803C00000010B3
+:1048E0000210810400000000061081280000000270
+:1048F0000210800C000002B50210801400000000BD
+:10490000061084000000004A0210810C0001FFFF25
+:1049100006108148000000020210800400001A8086
+:104920000610909000000024061092480000004AF3
+:10493000061094980000004A061096E80000004A0D
+:104940000210800000001080021080AC0000000601
+:1049500002108038000000100210810000000000EA
+:10496000061081200000000202108008000002B53D
+:104970000210801000000000061082000000004AB3
+:10498000021081080001FFFF0610814000000002B4
+:104990000210800000001A80061090000000002421
+:1049A000061091200000004A061093700000004A93
+:1049B000061095C00000004A02108004000010801C
+:1049C000021080B0000000070210803C00000010C0
+:1049D000021081040000000006108128000000027F
+:1049E0000210800C000002B50210801400000000CC
+:1049F000061084000000004A0210810C0001FFFF35
+:104A000006108148000000020210800400001A8095
+:104A10000610909000000024061092480000004A02
+:104A2000061094980000004A061096E80000004A1C
+:104A3000021205B0000000010212049000E383405E
+:104A40000212051400003C100212066C0000000166
+:104A5000021206700000000002120494FFFFFFFF24
+:104A600002120498FFFFFFFF0212049CFFFFFFFFEA
+:104A7000021204A0FFFFFFFF021204A4FFFFFFFFCA
+:104A8000021204A8FFFFFFFF021204ACFFFFFFFFAA
+:104A9000021204B0FFFFFFFF021204BCFFFFFFFF82
+:104AA000021204C0FFFFFFFF021204C4FFFFFFFF5A
+:104AB000021204C8FFFFFFFF021204CCFFFFFFFF3A
+:104AC000021204D0FFFFFFFF021204D8FFFFFFFF16
+:104AD000021204DCFFFFFFFF021204E0FFFFFFFFF2
+:104AE000021204E4FFFFFFFF021204E8FFFFFFFFD2
+:104AF000021204ECFFFFFFFF021204F0FFFFFFFFB2
+:104B0000021204F4FFFFFFFF021204F8FFFFFFFF91
+:104B1000021204FCFFFFFFFF02120500FFFFFFFF70
+:104B200002120504FFFFFFFF02120508FFFFFFFF4F
+:104B30000212050CFFFFFFFF02120510FFFFFFFF2F
+:104B4000021204D4FF809000021204B4F00050005E
+:104B5000021204B8F00010000212039000000008D6
+:104B60000212039C00000008021203A000000008CB
+:104B7000021203A400000002021203BC00000004A1
+:104B8000021203C000000005021203C4000000046A
+:104B9000021203D0000000000212036C00000001AA
+:104BA000021203680000003F021201BC0000004036
+:104BB000021201C000001808021201C4000008031C
+:104BC000021201C800000803021201CC00000040DC
+:104BD000021201D000000003021201D400000803F9
+:104BE000021201D800000803021201DC00000803D1
+:104BF000021201E000010003021201E400000803B8
+:104C0000021201E800000803021201EC0000000398
+:104C1000021201F000000003021201F40000000380
+:104C2000021201F800000003021201FC0000000360
+:104C3000021202000000000302120204000000033E
+:104C400002120208000000030212020C000000031E
+:104C500002120210000000030212021400000003FE
+:104C600002120218000000030212021C00000003DE
+:104C700002120220000000030212022400000003BE
+:104C800002120228000024030212022C0000002F4E
+:104C90000212023000000009021202340000001962
+:104CA00002120238000001840212023C000001835B
+:104CB0000212024000000306021202440000001922
+:104CC00002120248000000060212024C0000030615
+:104CD00002120250000003060212025400000306F2
+:104CE0000212025800000C860212025C0000030649
+:104CF00002120260000003060212026400000006B5
+:104D000002120268000000060212026C0000000697
+:104D10000212027000000006021202740000000677
+:104D200002120278000000060212027C0000000657
+:104D30000212028000000006021202840000000637
+:104D400002120288000000060212028C0000000617
+:104D500002120290000000060212029400000006F7
+:104D600002120298000000060212029C00000006D7
+:104D7000021202A000000306021202A400000013A7
+:104D8000021202A800000006021202B00000100485
+:104D9000021202B400001004021203240010644046
+:104DA0000212032800106440021205B40000000142
+:104DB000021201B0000000010600A0000000000C7B
+:104DC0000200A050000000000200A05400000000FB
+:104DD0000200A0EC555400000200A0F055555555B6
+:104DE0000200A0F4000055550200A0F8F0000000F9
+:104DF0000200A0FC555400000200A1005555555575
+:104E00000200A104000055550200A108F0000000B6
+:104E10000200A18C555400000200A1905555555533
+:104E20000200A194000055550200A198F000000076
+:104E30000200A19C000000000200A1A000010000EF
+:104E40000200A1A4000050140200A1A8000000006C
+:104E50000200A45C00000C000200A61C000000037D
+:104E60000200A06CFF5C00000200A070FFF55FFF75
+:104E70000200A0740000FFFF0200A078F00003E031
+:104E80000200A07C000000000200A0800000A00042
+:104E90000600A084000000050200A0980FE00000BA
+:104EA0000600A09C000000070200A0B8000004005B
+:104EB0000600A0BC000000030200A0C80000100013
+:104EC0000600A0CC000000030200A0D800004000B3
+:104ED0000600A0DC000000030200A0E800010000C2
+:104EE0000600A22C000000040200A10CFF5C0000E0
+:104EF0000200A110FFF55FFF0200A1140000FFFFF8
+:104F00000200A118F00003E00200A11C0000000054
+:104F10000200A1200000A0000600A124000000055E
+:104F20000200A1380FE000000600A13C00000007CD
+:104F30000200A158000008000600A15C0000000368
+:104F40000200A168000020000600A16C0000000320
+:104F50000200A178000080000600A17C0000000390
+:104F60000200A188000200000600A23C000000042C
+:104F70000200A030000000000200A0340000000089
+:104F80000200A038000000000200A03C0000000069
+:104F90000200A040000000000200A0440000000049
+:104FA0000200A048000000000200A04C0000000029
+:104FB00000000000000000000000003000000000C1
+:104FC00000000000000000000000000000000000E1
+:104FD00000000000000000000000000000000000D1
+:104FE0000000000000300031000000000000000060
+:104FF00000000000000000000000000000000000B1
+:1050000000000000000000000000000000000000A0
+:10501000003100520000000000000000000000000D
+:105020000000000000000000000000000000000080
+:105030000000000000000000000000000052008995
+:1050400000000000000000000089008D008D00912C
+:1050500000910095009500990099009D009D00A188
+:1050600000A100A500A500A900A900AE00AE00B1F6
+:1050700000B100B4000000000000000000000000CB
+:105080000000000000000000000000000000000020
+:105090000000000000B40309030903130313031DF8
+:1050A000031D03240324032B032B03320332033990
+:1050B00003390340034003470347034E034E0355A0
+:1050C00000000000000000000000000000000000E0
+:1050D00000000000000000000000000000000000D0
+:1050E00000000000000000000000000000000000C0
+:1050F00000000000000000000000000000000000B0
+:10510000000000000000000000000000000000009F
+:10511000000000000000000000000000000000008F
+:10512000000000000000000000000000000000007F
+:10513000000000000000000000000000000000006F
+:10514000000000000000000000000000000000005F
+:10515000000000000000000000000000000000004F
+:10516000000000000000000000000000000000003F
+:105170000355035B0000000000000000035B035CBC
+:10518000035C035D035D035E035E035F035F036017
+:1051900003600361036103620362036300000000B4
+:1051A00000000000000000000000000000000000FF
+:1051B00000000000000000000000000000000000EF
+:1051C00000000000000000000363036D036D037B1B
+:1051D000037B0389000000000000000000000000C5
+:1051E00000000000000000000000000000000000BF
+:1051F00000000000000000000000000000000000AF
+:10520000000000000000000000000000000000009E
+:10521000000000000000000000000000000000008E
+:105220000389038A00000000000000000000000065
+:10523000000000000000000000000000000000006E
+:10524000000000000000000000000000038A03D6F8
+:10525000000000000000000000000000000000004E
+:10526000000000000000000000000000000000003E
+:10527000000000000000000003D604010000000050
+:10528000000000000000000000000000000000001E
+:10529000000000000000000000000000000000000E
+:1052A00000000000040104330000000000000000C2
+:1052B0000433043A043A0441044104480448044FC6
+:1052C000044F04560456045D045D04640464046BD6
+:1052D000046B04A4000000000000000004A404A863
+:1052E00004A804AC04AC04B004B004B404B404B81E
+:1052F00004B804BC04BC04C004C004C404C4051342
+:105300000513052A052A05410541054305430545C1
+:1053100005450547054705490549054B054B054D1D
+:10532000054D054F054F0551055105E805E805E90F
+:1053300005E905EA05EA05EF05EF05F405F405F9C9
+:1053400005F905FE05FE0603060306080608060D18
+:10535000060D0612061206130000000000000000F1
+:10536000000000000000000000000000000000003D
+:10537000000000000000000000000000000000002D
+:1053800006130624000000000000000000000000DA
+:10539000000000000000000000000000000000000D
+:1053A0000000000000000000000000000624063994
+:1053B0000639063C063C063F0000000000000000E5
+:1053C00000000000000000000000000000000000DD
+:1053D0000000000000000000063F0675000000000D
+:1053E00000000000000000000000000000000000BD
+:1053F00000000000000000000000000000000000AD
+:1054000000000000067507780000000000000000A2
+:10541000000000000000000000000000000000008C
+:10542000000000000000000000000000000000007C
+:105430000778077F077F078307830787000000003F
+:10544000000000000000000000000000000000005C
+:10545000000000000000000000000000078707C8EF
+:10546000000000000000000007C807D107D107DADC
+:1054700007DA07E307E307EC07EC07F507F507FE94
+:1054800007FE080708070810081008670867087C67
+:10549000087C089108910894089408970897089A3E
+:1054A000089A089D089D08A008A008A308A308A6BC
+:1054B00008A608A908A908B2000000000000000022
+:1054C00000000000000000000000000000000000DC
+:1054D00000000000000000000000000000000000CC
+:1054E00008B208B800000000000000000000000042
+:1054F00000000000000000000000000000000000AC
+:1055000000000000000000000000000008B808BB18
+:10551000000000000000000000000000000000008B
+:10552000000000000000000000000000000000007B
+:10553000000000000000000008BB08C100000000DF
+:10554000000000000000000000000000000000005B
+:10555000000000000000000000000000000000004B
+:10556000000000000000000000000000000000003B
+:1055700008C108D008D008DF08DF08EE08EE08FDF3
+:1055800008FD090C090C091B091B092A092A0939FC
+:10559000093909AA00000000000000000000000016
+:1055A00000000000000000000000000000000000FB
+:1055B00000000000000000000000000009AA09BF70
+:1055C00009BF09D009D009E109E109E209E209E3CB
+:1055D00009E309E409E409E509E509E609E609E75B
+:1055E00009E709E809E809E90000000000000000F7
+:1055F00000000000000000000000000000000000AB
+:10560000000000000000000000000000000000009A
+:10561000000000000000000000000000000000008A
+:10562000000000000000000000000000000000007A
+:10563000000000000000000000000000000000006A
+:10564000000000000000000000000000000000005A
+:10565000000000000000000000000000000000004A
+:10566000000000000000000000000000000000003A
+:10567000000000000000000000000000000000002A
+:10568000000000000000000000000000000000001A
+:10569000000000000000000000000000000000000A
+:1056A00000000000000000000000000000000000FA
+:1056B00000000000000000000000000000000000EA
+:1056C000000000000000000000010000000204C013
+:1056D0000003098000040E4000051300000617C0F7
+:1056E00000071C800008214000092600000A2AC08B
+:1056F000000B2F80000C3440000D3900000E3DC01F
+:10570000000F42800010474000114C00001250C0B2
+:105710000013558000145A4000155F00001663C046
+:105720000017688000186D4000197200001A76C0DA
+:10573000001B7B80001C8040001D8500001E89C06E
+:10574000001F8E80000093400000200000004000F9
+:1057500000006000000080000000A0000000C00009
+:105760000000E000000100000001200000014000F6
+:1057700000016000000180000001A0000001C000E5
+:105780000001E000000200000002200000024000D2
+:1057900000026000000280000002A0000002C000C1
+:1057A0000002E000000300000003200000034000AE
+:1057B00000036000000380000003A0000003C0009D
+:1057C0000003E0000004000000042000000440008A
+:1057D00000046000000480000004A0000004C00079
+:1057E0000004E00000050000000520000005400066
+:1057F00000056000000580000005A0000005C00055
+:105800000005E00000060000000620000006400041
+:1058100000066000000680000006A0000006C00030
+:105820000006E0000007000000072000000740001D
+:1058300000076000000780000007A0000007C0000C
+:105840000007E000000800000008200000084000F9
+:1058500000086000000880000008A0000008C000E8
+:105860000008E000000900000009200000094000D5
+:1058700000096000000980000009A0000009C000C4
+:105880000009E000000A0000000A2000000A4000B1
+:10589000000A6000000A8000000AA000000AC000A0
+:1058A000000AE000000B0000000B2000000B40008D
+:1058B000000B6000000B8000000BA000000BC0007C
+:1058C000000BE000000C0000000C2000000C400069
+:1058D000000C6000000C8000000CA000000CC00058
+:1058E000000CE000000D0000000D2000000D400045
+:1058F000000D6000000D8000000DA000000DC00034
+:10590000000DE000000E0000000E2000000E400020
+:10591000000E6000000E8000000EA000000EC0000F
+:10592000000EE000000F0000000F2000000F4000FC
+:10593000000F6000000F8000000FA000000FC000EB
+:10594000000FE000001000000010200000104000D8
+:1059500000106000001080000010A0000010C000C7
+:105960000010E000001100000011200000114000B4
+:1059700000116000001180000011A0000011C000A3
+:105980000011E00000120000001220000012400090
+:1059900000126000001280000012A0000012C0007F
+:1059A0000012E0000013000000132000001340006C
+:1059B00000136000001380000013A0000013C0005B
+:1059C0000013E00000140000001420000014400048
+:1059D00000146000001480000014A0000014C00037
+:1059E0000014E00000150000001520000015400024
+:1059F00000156000001580000015A0000015C00013
+:105A00000015E000001600000016200000164000FF
+:105A100000166000001680000016A0000016C000EE
+:105A20000016E000001700000017200000174000DB
+:105A300000176000001780000017A0000017C000CA
+:105A40000017E000001800000018200000184000B7
+:105A500000186000001880000018A0000018C000A6
+:105A60000018E00000190000001920000019400093
+:105A700000196000001980000019A0000019C00082
+:105A80000019E000001A0000001A2000001A40006F
+:105A9000001A6000001A8000001AA000001AC0005E
+:105AA000001AE000001B0000001B2000001B40004B
+:105AB000001B6000001B8000001BA000001BC0003A
+:105AC000001BE000001C0000001C2000001C400027
+:105AD000001C6000001C8000001CA000001CC00016
+:105AE000001CE000001D0000001D2000001D400003
+:105AF000001D6000001D8000001DA000001DC000F2
+:105B0000001DE000001E0000001E2000001E4000DE
+:105B1000001E6000001E8000001EA000001EC000CD
+:105B2000001EE000001F0000001F2000001F4000BA
+:105B3000001F6000001F8000001FA000001FC000A9
+:105B4000001FE00000200000002020000020400096
+:105B500000206000002080000020A0000020C00085
+:105B60000020E00000210000002120000021400072
+:105B700000216000002180000021A0000021C00061
+:105B80000021E0000022000000222000002240004E
+:105B900000226000002280000022A0000022C0003D
+:105BA0000022E0000023000000232000002340002A
+:105BB00000236000002380000023A0000023C00019
+:105BC0000023E00000240000002420000024400006
+:105BD00000246000002480000024A0000024C000F5
+:105BE0000024E000002500000025200000254000E2
+:105BF00000256000002580000025A0000025C000D1
+:105C00000025E000002600000026200000264000BD
+:105C100000266000002680000026A0000026C000AC
+:105C20000026E00000270000002720000027400099
+:105C300000276000002780000027A0000027C00088
+:105C40000027E00000280000002820000028400075
+:105C500000286000002880000028A0000028C00064
+:105C60000028E00000290000002920000029400051
+:105C700000296000002980000029A0000029C00040
+:105C80000029E000002A0000002A2000002A40002D
+:105C9000002A6000002A8000002AA000002AC0001C
+:105CA000002AE000002B0000002B2000002B400009
+:105CB000002B6000002B8000002BA000002BC000F8
+:105CC000002BE000002C0000002C2000002C4000E5
+:105CD000002C6000002C8000002CA000002CC000D4
+:105CE000002CE000002D0000002D2000002D4000C1
+:105CF000002D6000002D8000002DA000002DC000B0
+:105D0000002DE000002E0000002E2000002E40009C
+:105D1000002E6000002E8000002EA000002EC0008B
+:105D2000002EE000002F0000002F2000002F400078
+:105D3000002F6000002F8000002FA000002FC00067
+:105D4000002FE00000300000003020000030400054
+:105D500000306000003080000030A0000030C00043
+:105D60000030E00000310000003120000031400030
+:105D700000316000003180000031A0000031C0001F
+:105D80000031E0000032000000322000003240000C
+:105D900000326000003280000032A0000032C000FB
+:105DA0000032E000003300000033200000334000E8
+:105DB00000336000003380000033A0000033C000D7
+:105DC0000033E000003400000034200000344000C4
+:105DD00000346000003480000034A0000034C000B3
+:105DE0000034E000003500000035200000354000A0
+:105DF00000356000003580000035A0000035C0008F
+:105E00000035E0000036000000362000003640007B
+:105E100000366000003680000036A0000036C0006A
+:105E20000036E00000370000003720000037400057
+:105E300000376000003780000037A0000037C00046
+:105E40000037E00000380000003820000038400033
+:105E500000386000003880000038A0000038C00022
+:105E60000038E0000039000000392000003940000F
+:105E700000396000003980000039A0000039C000FE
+:105E80000039E000003A0000003A2000003A4000EB
+:105E9000003A6000003A8000003AA000003AC000DA
+:105EA000003AE000003B0000003B2000003B4000C7
+:105EB000003B6000003B8000003BA000003BC000B6
+:105EC000003BE000003C0000003C2000003C4000A3
+:105ED000003C6000003C8000003CA000003CC00092
+:105EE000003CE000003D0000003D2000003D40007F
+:105EF000003D6000003D8000003DA000003DC0006E
+:105F0000003DE000003E0000003E2000003E40005A
+:105F1000003E6000003E8000003EA000003EC00049
+:105F2000003EE000003F0000003F2000003F400036
+:105F3000003F6000003F8000003FA000003FC00025
+:105F4000003FE000003FE00100000000000001FF12
+:105F50000000020000007FF800007FF80000014010
+:105F600000003500000000010000FF0000000000FC
+:105F70000000FF00000000000000FF000000000023
+:105F80000000FF00000000000000FF000000000013
+:105F90000000FF00000000000000FF000000000003
+:105FA0000000FF000000000000000000140AFF00D5
+:105FB00000000001000000000020100100000000AF
+:105FC0000100900000000100000090020000900419
+:105FD00000009006000090080000900A0000900C5D
+:105FE0000000900E0000901000009012000090142D
+:105FF00000009016000090180000901A0000901CFD
+:106000000000901E000090200000902200009024CC
+:1060100000009026000090280000902A0000902C9C
+:106020000000902E0000903000009032000090346C
+:1060300000009036000090380000903A0000903C3C
+:106040000000903E0000904000009042000090440C
+:1060500000009046000090480000904A0000904CDC
+:106060000000904E000090500000905200009054AC
+:1060700000009056000090580000905A0000905C7C
+:106080000000905E0000906000009062000090644C
+:1060900000009066000090680000906A0000906C1C
+:1060A0000000906E000090700000907200009074EC
+:1060B00000009076000090780000907A0000907CBC
+:1060C0000000907E0000908000009082000090848C
+:1060D00000009086000090880000908A0000908C5C
+:1060E0000000908E0000909000009092000090942C
+:1060F00000009096000090980000909A0000909CFC
+:106100000000909E000090A0000090A2000090A4CB
+:10611000000090A6000090A8000090AA000090AC9B
+:10612000000090AE000090B0000090B2000090B46B
+:10613000000090B6000090B8000090BA000090BC3B
+:10614000000090BE000090C0000090C2000090C40B
+:10615000000090C6000090C8000090CA000090CCDB
+:10616000000090CE000090D0000090D2000090D4AB
+:10617000000090D6000090D8000090DA000090DC7B
+:10618000000090DE000090E0000090E2000090E44B
+:10619000000090E6000090E8000090EA000090EC1B
+:1061A000000090EE000090F0000090F2000090F4EB
+:1061B000000090F6000090F8000090FA000090FCBB
+:1061C000000090FE00009100000091020000910488
+:1061D00000009106000091080000910A0000910C57
+:1061E0000000910E00009110000091120000911427
+:1061F00000009116000091180000911A0000911CF7
+:106200000000911E000091200000912200009124C6
+:1062100000009126000091280000912A0000912C96
+:106220000000912E00009130000091320000913466
+:1062300000009136000091380000913A0000913C36
+:106240000000913E00009140000091420000914406
+:1062500000009146000091480000914A0000914CD6
+:106260000000914E000091500000915200009154A6
+:1062700000009156000091580000915A0000915C76
+:106280000000915E00009160000091620000916446
+:1062900000009166000091680000916A0000916C16
+:1062A0000000916E000091700000917200009174E6
+:1062B00000009176000091780000917A0000917CB6
+:1062C0000000917E00009180000091820000918486
+:1062D00000009186000091880000918A0000918C56
+:1062E0000000918E00009190000091920000919426
+:1062F00000009196000091980000919A0000919CF6
+:106300000000919E000091A0000091A2000091A4C5
+:10631000000091A6000091A8000091AA000091AC95
+:10632000000091AE000091B0000091B2000091B465
+:10633000000091B6000091B8000091BA000091BC35
+:10634000000091BE000091C0000091C2000091C405
+:10635000000091C6000091C8000091CA000091CCD5
+:10636000000091CE000091D0000091D2000091D4A5
+:10637000000091D6000091D8000091DA000091DC75
+:10638000000091DE000091E0000091E2000091E445
+:10639000000091E6000091E8000091EA000091EC15
+:1063A000000091EE000091F0000091F2000091F4E5
+:1063B000000091F6000091F8000091FA000091FCB5
+:1063C000000091FEFFFFFFFFFFFFFFFFFFFFFFFF4A
+:1063D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD
+:1063E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD
+:1063F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD
+:10640000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C
+:10641000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C
+:10642000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C
+:10643000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C
+:10644000FFFFFFFF0000000300BEBC2000000000B3
+:10645000000000050000000300BEBC20000000009A
+:10646000000000050000000300BEBC20000000008A
+:10647000000000050000000300BEBC20000000007A
+:10648000000000050000000300BEBC20000000006A
+:10649000000000050000000300BEBC20000000005A
+:1064A000000000050000000300BEBC20000000004A
+:1064B000000000050000000300BEBC20000000003A
+:1064C0000000000500002000000040C000006180C6
+:1064D000000082400000A3000000C3C00000E48070
+:1064E0000001054000012600000146C00001678050
+:1064F000000188400001A9000001C9C00001EA8034
+:1065000000020B4000022C0000024CC000026D8013
+:1065100000028E400002AF000002CFC00002F080F7
+:10652000000011400000800000010380000187008E
+:1065300000020A8000028E00000311800003950013
+:106540000004188000049C0000051F800005A300C3
+:10655000000626800006AA0000072D800007B10073
+:10656000000834800008B80000093B800009BF0023
+:10657000000A4280000AC600000B4980000BCD00D3
+:10658000000C5080000CD400000D578000005B0010
+:1065900000007FF800007FF8000000D50000150023
+:1065A0000000FF00000000000000FF0000000000ED
+:1065B0000000FF00000000000000FF0000000000DD
+:1065C0000000FF00000000000000FF0000000000CD
+:1065D0000000FF00000000000000FF0000000000BD
+:1065E000000019000000000000000000FFFFFFFF96
+:1065F0000000000003938700000000000393870061
+:1066000000007FF800007FF80000069200001500EF
+:106610000000FF000FFFFFFF0000FF000FFFFFFF64
+:10662000000000FF0000FF000FFFFFFF0000FF0061
+:106630000FFFFFFF000000FF0000FF000FFFFFFF44
+:106640000000FF000FFFFFFF000000FF0000FF0041
+:106650000FFFFFFF0000FF000FFFFFFF000000FF24
+:106660000000FF000FFFFFFF0000FF000FFFFFFF14
+:10667000000000FF0000FF000FFFFFFF0000FF0011
+:106680000FFFFFFF000000FF0000FF000FFFFFFFF4
+:106690000000FF000FFFFFFF000000FF0000FF00F1
+:1066A0000FFFFFFF0000FF000FFFFFFF000000FFD4
+:1066B0000000FF000FFFFFFF0000FF000FFFFFFFC4
+:1066C000000000FF0000FF000FFFFFFF0000FF00C1
+:1066D0000FFFFFFF000000FF0000FF000FFFFFFFA4
+:1066E0000000FF000FFFFFFF000000FF0000FF00A1
+:1066F0000FFFFFFF0000FF000FFFFFFF000000FF84
+:106700000000FF000FFFFFFF0000FF000FFFFFFF73
+:10671000000000FF0000FF000FFFFFFF0000FF0070
+:106720000FFFFFFF000000FF0000FF000FFFFFFF53
+:106730000000FF000FFFFFFF000000FF0000FF0050
+:106740000FFFFFFF0000FF000FFFFFFF000000FF33
+:106750000000FF000FFFFFFF0000FF000FFFFFFF23
+:10676000000000FF0000FF000FFFFFFF0000FF0020
+:106770000FFFFFFF000000FF0000FF000FFFFFFF03
+:106780000000FF000FFFFFFF000000FF0000FF0000
+:106790000FFFFFFF0000FF000FFFFFFF000000FFE3
+:1067A0000000FF000FFFFFFF0000FF000FFFFFFFD3
+:1067B000000000FF0000FF000FFFFFFF0000FF00D0
+:1067C0000FFFFFFF000000FF0000FF000FFFFFFFB3
+:1067D0000000FF000FFFFFFF000000FF0000FF00B0
+:1067E0000FFFFFFF0000FF000FFFFFFF000000FF93
+:1067F0000000FF000FFFFFFF0000FF000FFFFFFF83
+:10680000000000FF0000FF000FFFFFFF0000FF007F
+:106810000FFFFFFF000000FF0000FF000FFFFFFF62
+:106820000000FF000FFFFFFF000000FF0000FF005F
+:106830000FFFFFFF0000FF000FFFFFFF000000FF42
+:106840000000FF000FFFFFFF0000FF000FFFFFFF32
+:10685000000000FF0000FF000FFFFFFF0000FF002F
+:106860000FFFFFFF000000FF0000FF000FFFFFFF12
+:106870000000FF000FFFFFFF000000FF0000FF000F
+:106880000FFFFFFF0000FF000FFFFFFF000000FFF2
+:10689000000000FF000000FF000000FF000000FFFC
+:1068A000000000FF000000FF000000FF000000FFEC
+:1068B0000000FF00000000000000FF0000000000DA
+:1068C0000000FF00000000000000FF0000000000CA
+:1068D0000000FF00000000000000FF0000000000BA
+:1068E0000000FF00000000000000FF0000000000AA
+:1068F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8
+:10690000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97
+:10691000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87
+:10692000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77
+:10693000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67
+:10694000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57
+:10695000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47
+:10696000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37
+:106970000000100000002080000031000000418075
+:10698000000052000000628000007300000083805D
+:10699000000094000000A4800000B5000000C58045
+:1069A0000000D6000000E6800000F700000107802C
+:1069B0000001180000012880000139000001498011
+:1069C00000015A0000016A8000017B0000018B80F9
+:1069D00000019C000001AC800001BD000001CD80E1
+:1069E0000001DE000001EE800001FF0000000F80CA
+:1069F00000007FF800007FF8000003400000150051
+:106A000010000000000028AD000100010022000677
+:106A1000CCCCCCC5FFFFFFFFFFFFFFFF7058103C41
+:106A20000000FF00000000000000FF000000000068
+:106A30000000FF00000000000000FF000000000058
+:106A40000000FF00000000000000FF000000000048
+:106A50000000FF00000000000000FF000000000038
+:106A60000000000000000001CCCC0201CCCCCCCC5A
+:106A7000CCCC0201CCCCCCCCCCCC0201CCCCCCCC80
+:106A8000CCCC0201CCCCCCCCCCCC0201CCCCCCCC70
+:106A9000CCCC0201CCCCCCCCCCCC0201CCCCCCCC60
+:106AA000CCCC0201CCCCCCCC00000000FFFFFFFF1F
+:106AB000000E0000011600D6002625A0002625A005
+:106AC000002625A0002625A000720000012300F367
+:106AD000002625A0002625A0002625A0002625A00A
+:106AE0000000FFFF000000000000FFFF00000000AA
+:106AF0000000FFFF000000000000FFFF000000009A
+:106B00000000FFFF000000000000FFFF0000000089
+:106B10000000FFFF000000000000FFFF0000000079
+:106B20000000FFFF000000000000FFFF0000000069
+:106B30000000FFFF000000000000FFFF0000000059
+:106B40000000FFFF000000000000FFFF0000000049
+:106B50000000FFFF000000000000FFFF0000000039
+:106B60000000FFFF000000000000FFFF0000000029
+:106B70000000FFFF000000000000FFFF0000000019
+:106B80000000FFFF000000000000FFFF0000000009
+:106B90000000FFFF000000000000FFFF00000000F9
+:106BA0000000FFFF000000000000FFFF00000000E9
+:106BB0000000FFFF000000000000FFFF00000000D9
+:106BC0000000FFFF000000000000FFFF00000000C9
+:106BD0000000FFFF000000000000FFFF00000000B9
+:106BE0000000FFFF000000000000FFFF00000000A9
+:106BF0000000FFFF000000000000FFFF0000000099
+:106C00000000FFFF000000000000FFFF0000000088
+:106C10000000FFFF000000000000FFFF0000000078
+:106C20000000FFFF000000000000FFFF0000000068
+:106C30000000FFFF000000000000FFFF0000000058
+:106C40000000FFFF000000000000FFFF0000000048
+:106C50000000FFFF000000000000FFFF0000000038
+:106C60000000FFFF000000000000FFFF0000000028
+:106C70000000FFFF000000000000FFFF0000000018
+:106C80000000FFFF000000000000FFFF0000000008
+:106C90000000FFFF000000000000FFFF00000000F8
+:106CA0000000FFFF000000000000FFFF00000000E8
+:106CB0000000FFFF000000000000FFFF00000000D8
+:106CC0000000FFFF000000000000FFFF00000000C8
+:106CD0000000FFFF000000000000FFFF00000000B8
+:106CE000FFFFFFF3318FFFFF0C30C30CC30C30C329
+:106CF000CF3CF300F3CF3CF30000CF3CCDCDCDCD66
+:106D0000FFFFFFF130EFFFFF0C30C30CC30C30C3AB
+:106D1000CF3CF300F3CF3CF30001CF3CCDCDCDCD44
+:106D2000FFFFFFF6305FFFFF0C30C30CC30C30C316
+:106D3000CF3CF300F3CF3CF30002CF3CCDCDCDCD23
+:106D4000FFFFF4061CBFFFFF0C30C305C30C30C3AC
+:106D5000CF300014F3CF3CF30004CF3CCDCDCDCDEC
+:106D6000FFFFFFF2304FFFFF0C30C30CC30C30C3EA
+:106D7000CF3CF300F3CF3CF30008CF3CCDCDCDCDDD
+:106D8000FFFFFFFA302FFFFF0C30C30CC30C30C3E2
+:106D9000CF3CF300F3CF3CF30010CF3CCDCDCDCDB5
+:106DA000FFFFFFF731EFFFFF0C30C30CC30C30C304
+:106DB000CF3CF300F3CF3CF30020CF3CCDCDCDCD85
+:106DC000FFFFFFF5302FFFFF0C30C30CC30C30C3A7
+:106DD000CF3CF300F3CF3CF30040CF3CCDCDCDCD45
+:106DE000FFFFFFF3318FFFFF0C30C30CC30C30C328
+:106DF000CF3CF300F3CF3CF30000CF3CCDCDCDCD65
+:106E0000FFFFFFF1310FFFFF0C30C30CC30C30C389
+:106E1000CF3CF300F3CF3CF30001CF3CCDCDCDCD43
+:106E2000FFFFFFF6305FFFFF0C30C30CC30C30C315
+:106E3000CF3CF300F3CF3CF30002CF3CCDCDCDCD22
+:106E4000FFFFF4061CBFFFFF0C30C305C30C30C3AB
+:106E5000CF300014F3CF3CF30004CF3CCDCDCDCDEB
+:106E6000FFFFFFF2304FFFFF0C30C30CC30C30C3E9
+:106E7000CF3CF300F3CF3CF30008CF3CCDCDCDCDDC
+:106E8000FFFFFFFA302FFFFF0C30C30CC30C30C3E1
+:106E9000CF3CF300F3CF3CF30010CF3CCDCDCDCDB4
+:106EA000FFFFFFF730EFFFFF0C30C30CC30C30C304
+:106EB000CF3CF300F3CF3CF30020CF3CCDCDCDCD84
+:106EC000FFFFFFF5304FFFFF0C30C30CC30C30C386
+:106ED000CF3CF300F3CF3CF30040CF3CCDCDCDCD44
+:106EE000FFFFFFFF30CFFFFF0C30C30CC30C30C3DC
+:106EF000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD98
+:106F0000FFFFFFFF30CFFFFF0C30C30CC30C30C3BB
+:106F1000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD76
+:106F2000FFFFFFFF30CFFFFF0C30C30CC30C30C39B
+:106F3000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD55
+:106F4000FFFFFFFF30CFFFFF0C30C30CC30C30C37B
+:106F5000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD33
+:106F6000FFFFFFFF30CFFFFF0C30C30CC30C30C35B
+:106F7000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0F
+:106F8000FFFFFFFF30CFFFFF0C30C30CC30C30C33B
+:106F9000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE7
+:106FA000FFFFFFFF30CFFFFF0C30C30CC30C30C31B
+:106FB000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB7
+:106FC000FFFFFFFF30CFFFFF0C30C30CC30C30C3FB
+:106FD000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD77
+:106FE000FFFFFFF3320FFFFF0C30C30CC30C30C3A5
+:106FF000CF3CF300F3CF3CF30000CF3CCDCDCDCD63
+:10700000FFFFFFF1310FFFFF0C30C30CC30C30C387
+:10701000CF3CF300F3CF3CF30001CF3CCDCDCDCD41
+:10702000FFFFFFF6305FFFFF0C30C30CC30C30C313
+:10703000CF3CF300F3CF3CF30002CF3CCDCDCDCD20
+:10704000FFFFF4061CBFFFFF0C30C305C30C30C3A9
+:10705000CF300014F3CF3CF30004CF3CCDCDCDCDE9
+:10706000FFFFFFF2304FFFFF0C30C30CC30C30C3E7
+:10707000CF3CF300F3CF3CF30008CF3CCDCDCDCDDA
+:10708000FFFFFF8A042FFFFF0C30C30CC30C30C37B
+:10709000CF3CC000F3CF3CF30010CF3CCDCDCDCDE5
+:1070A000FFFFFF9705CFFFFF0C30C30CC30C30C3AD
+:1070B000CF3CC000F3CF3CF30020CF3CCDCDCDCDB5
+:1070C000FFFFFFF5310FFFFF0C30C30CC30C30C3C3
+:1070D000CF3CF300F3CF3CF30040CF3CCDCDCDCD42
+:1070E000FFFFFFF3320FFFFF0C30C30CC30C30C3A4
+:1070F000CF3CF300F3CF3CF30000CF3CCDCDCDCD62
+:10710000FFFFFFF1302FFFFF0C30C30CC30C30C367
+:10711000CF3CF300F3CF3CF30001CF3CCDCDCDCD40
+:10712000FFFFFFF6305FFFFF0C30C30CC30C30C312
+:10713000CF3CF300F3CF3CF30002CF3CCDCDCDCD1F
+:10714000FFFFFF061CBFFFFF0C30C30CC30C30C396
+:10715000CF3CC014F3CF3CF30004CF3CCDCDCDCD1C
+:10716000FFFFFFF2304FFFFF0C30C30CC30C30C3E6
+:10717000CF3CF300F3CF3CF30008CF3CCDCDCDCDD9
+:10718000FFFFFFFA302FFFFF0C30C30CC30C30C3DE
+:10719000CF3CF300F3CF3CF30010CF3CCDCDCDCDB1
+:1071A000FFFFFFF731CFFFFF0C30C30CC30C30C320
+:1071B000CF3CF300F3CF3CF30020CF3CCDCDCDCD81
+:1071C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F9
+:1071D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD75
+:1071E000FFFFFFFF30CFFFFF0C30C30CC30C30C3D9
+:1071F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD95
+:10720000FFFFFFFF30CFFFFF0C30C30CC30C30C3B8
+:10721000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD73
+:10722000FFFFFFFF30CFFFFF0C30C30CC30C30C398
+:10723000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD52
+:10724000FFFFFFFF30CFFFFF0C30C30CC30C30C378
+:10725000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD30
+:10726000FFFFFFFF30CFFFFF0C30C30CC30C30C358
+:10727000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0C
+:10728000FFFFFFFF30CFFFFF0C30C30CC30C30C338
+:10729000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE4
+:1072A000FFFFFFFF30CFFFFF0C30C30CC30C30C318
+:1072B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB4
+:1072C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F8
+:1072D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD74
+:1072E000FFFFFFFF30CFFFFF0C30C30CC30C30C3D8
+:1072F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD94
+:10730000FFFFFFFF30CFFFFF0C30C30CC30C30C3B7
+:10731000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD72
+:10732000FFFFFFFF30CFFFFF0C30C30CC30C30C397
+:10733000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD51
+:10734000FFFFFFFF30CFFFFF0C30C30CC30C30C377
+:10735000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD2F
+:10736000FFFFFFFF30CFFFFF0C30C30CC30C30C357
+:10737000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0B
+:10738000FFFFFFFF30CFFFFF0C30C30CC30C30C337
+:10739000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE3
+:1073A000FFFFFFFF30CFFFFF0C30C30CC30C30C317
+:1073B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB3
+:1073C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F7
+:1073D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD73
+:1073E000FFFFFFFF30CFFFFF0C30C30CC30C30C3D7
+:1073F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD93
+:10740000FFFFFFFF30CFFFFF0C30C30CC30C30C3B6
+:10741000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD71
+:10742000FFFFFFFF30CFFFFF0C30C30CC30C30C396
+:10743000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD50
+:10744000FFFFFFFF30CFFFFF0C30C30CC30C30C376
+:10745000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD2E
+:10746000FFFFFFFF30CFFFFF0C30C30CC30C30C356
+:10747000CF3CF3CCF3CF3CF30008CF3CCDCDCDCD0A
+:10748000FFFFFFFF30CFFFFF0C30C30CC30C30C336
+:10749000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDE2
+:1074A000FFFFFFFF30CFFFFF0C30C30CC30C30C316
+:1074B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDB2
+:1074C000FFFFFFFF30CFFFFF0C30C30CC30C30C3F6
+:1074D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD72
+:1074E000000C0000000700C000028130000B815832
+:1074F0000002021000010230000F024000010330C0
+:10750000000C0000000800C000028140000B8168F0
+:10751000000202200001024000070250000202C0E7
+:10752000001000000008010000028180000B81A80B
+:107530000002026000018280000E82980008038031
+:107540000010000000010100000281100009013854
+:10755000000201C8000101E8000E01F8000002D895
+:10756000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC5B
+:1075700000002000CCCCCCCCCCCCCCCCCCCCCCCC5B
+:10758000CCCCCCCC00002000CCCCCCCCCCCCCCCC4B
+:10759000CCCCCCCCCCCCCCCC040020000000000067
+:1075A0001F8B080000000000000BFB51CFC0F00350
+:1075B0008A37B231306CE344F0E98159181818F871
+:1075C00099C8D7BF0668C01620BE0CC47B5848D7E0
+:1075D0007F5E1AC15E20C9C0700488BBC51918EA55
+:1075E000A510E296320C0C3780FCC5503109A09EE4
+:1075F00069D2E4BB79140F1E9C648ACA773586D0A1
+:10760000374D2074329ABC1B545E500F42A79862CB
+:107610003757488F38FB1354D0EC57C1AF3E5D034A
+:10762000951F8EA6DE0FCA0700DCEC914ED8030032
+:1076300000000000000000001F8B08000000000098
+:10764000000BED7D0B7815D5B9E89AC79E3DFB99E7
+:1076500049086127049C8400C1F2D84280A0142705
+:107660001030B6D46E5E12BD081B1F95872411D34F
+:10767000635A39CD401E2401243E4AE92DD50DC55B
+:10768000367A6D1B6D6A698FF66C442D9EDBD303D1
+:10769000942AADE0096A2D58A0B1A71C68BFB6DCDA
+:1076A000F5AF47F6CC64761E3EFAF57CB7F193C988
+:1076B0009A59CFFFBDFEFF5F2B0A2A443957217428
+:1076C000057EAE47C8101042D3534F744F86887260
+:1076D00010FABC8AC8CF255F7832CA40A84EA5CF21
+:1076E000FBFDE17DF06CAB4728391EBE8F4EA0300C
+:1076F0004201848AE56C68E18F3E5100CF9A29B13E
+:1077000049E439139E594844683894F3B57703B473
+:10771000EF2B12FEE764BC0CC693E82B24A3D268BF
+:1077200092B47F00A119A979A09ACF6AB1506ADEFC
+:10773000CEA7A42928C9EA5E817FA41519F160FAB1
+:10774000FA752785EFBE64A93F1685B2C9BC6424CB
+:107750009379B1F60899C83A3F673F97EAD1775FC6
+:107760001ADB176EE9C6E5706BA957C9B3B95E435A
+:10777000492F42B899D139113F83C8D837B16FBB6F
+:10778000722430F8B1F9C0383AAE8FFF4718EE8D49
+:10779000D92811001CA2B80D6E8DC1C5AAE1D21F57
+:1077A0007FA26C0CB76236E7C2BEEBF5C1BC301CE1
+:1077B0007C302F17782E87794DEF3B2F5F91735ECA
+:1077C0006B90153E439D977F024247001FB2811088
+:1077D000C1CB7DB6FE44CD30BB5DFA438C2E649D9B
+:1077E000AD6F90780A148BA9F1010EBADF465FDE07
+:1077F00048969DDE9C740DF020F86A67F0894994E4
+:107800001FCC141EF13350AA0BA890148F00DE2257
+:107810000CEE913B9BEF15315F8551A2651CE6870D
+:1078200048F7EA85C067E193379E459331FCA25340
+:10783000D579784D5A89FED002FC0C4CD404A0D7DF
+:1078400036E0B36BA1BF5BCC325C6E80CEF270D100
+:10785000BCC93009DC0C1BDC30E47419973DF06BBB
+:10786000A10BFC502F1E842BDEBEEDD3C1CF832C89
+:10787000F823FCBCD1469769F11EA7ED4CFC1FE034
+:107880002BCBD18F566EE7F330B294F1F7A7E01708
+:1078900002EF7BFF26E365A27DAA5E82D75B2C6A9E
+:1078A00009A88FF44C1997031532023996998D0E59
+:1078B000628C0C889746842A80FF11EA448B26A5A7
+:1078C000E6F7AF8CBF723FF7E8EA66CC4F174B8301
+:1078D00051E0AF8886D0B0ACBEEBD9CEE44B6F3967
+:1078E000FA2C8A4F84F1122D85785E66548C3E0105
+:1078F000F3297E518B5BF8E574AF7C71D207D2E53A
+:10790000194C1E60F848C5A2E19BFCE1E943FA80EE
+:10791000F4118C2B36BE1C2ABE2E0C913E3EEC7808
+:107920001CAF7DF96A33C36BA30AF2AC455FDCAFD1
+:10793000BEEA8BD77D08EA078A91917069F75F5696
+:107940007DE17C5AE4BB538E4A236654EEED0F6F03
+:10795000D97678F07E7D7592FECE305C9435225FCC
+:1079600015A6075A230F9B08D3DD45903D181E52DC
+:10797000FB354928A32244E810FF24055CF6458C1A
+:10798000441BA18304C10B9F9F57176DF095B3ED66
+:107990007218559A8275FEBE3A85CC4381F1B2C108
+:1079A0002EC01D6250C84194F485A1069D3FA8A435
+:1079B0002B63A06CB7335AF4A9C80D0F32C3AB20A8
+:1079C000707A7D6070F2C539DE52FB7C07DD2E28AF
+:1079D000EBEFF2362E723AD54E46EF72FC6020CEB7
+:1079E000E1761DC3D3560F3A204CC1F220FF66B09A
+:1079F00014D056F8340BDB21F0CCC5E5FCA9442E9D
+:107A0000A00E4186799221311E11D677502F20E8A1
+:107A1000A41F51AD2172450A1AE4C9BFA79F171DC3
+:107A2000BFB7ACC6AB003F6B228ADE86E7B85E32DA
+:107A3000F4CD4017D3B07CD2E1FDB872D0731E8173
+:107A4000CEEB4B422E59879CD59243ECB234F6DDF7
+:107A50001A19F3E454F8BE7D5C7FFC84129E9E6E7E
+:107A60000B3C9DF6E0DD02B6073F817F99896602F7
+:107A70001C7F1F5D9C91EC075FEFD51FD6E4B129F9
+:107A80007BD0F97DBD846ADCE440B3A052BE544D86
+:107A900005EC03BEEEF5982FBC59C0E75BE87AB35E
+:107AA000B3097CD777BCAAC916FE5B8FD58C776AE1
+:107AB000DFF57078F37E7ADB270EDBDA3BDBF5F659
+:107AC000C7E505B68781CE391D0484F83601BFF7B6
+:107AD00046179B7930FED36514FF69E6DF8BAF0F45
+:107AE000387FDE6E20BAFAFDFE8666D04FEF2AEDB3
+:107AF000375D8BE9E837CF48D12DF8EB9A3DE3CBE2
+:107B0000C16E7A97D137C7D3D9FD0D396EF4910E76
+:107B10004FAF0A3E320EA7AF35E28A7EE96120FA06
+:107B2000FA9E93BE3A977C2CF475C4495F0C1EE70D
+:107B30003AE9FAD1EE61142F0C5F4EFCA4C5CB07D5
+:107B40006DD7979E7E2160BEF6762E71A727365F91
+:107B50008EAF0F3BDF81E82847370C0D8F3F02DBEC
+:107B60003102E88F12144DEA60D745A9DE8A52BD72
+:107B7000C5E5126F7F41A0769A8C8E93F6124A9AD1
+:107B80001AB1B7ED76C67C09BFC4FD3416A384973D
+:107B9000EC8B0C95E8A9621951FD67047371FD0C1B
+:107BA000C47EA4D951587706B3FFD16CA67F056C6B
+:107BB0006FE1F5054BECF687DF619F48B05F08BBCE
+:107BC000D85B43DC1FFB44B63F0EA020D1477C7F2F
+:107BD0009C863F7BF7C50CAEC315648878DDCA610F
+:107BE0004F628B00DA0D11FD8C4E0A09EA2F40C559
+:107BF00060376F14F2A2A00FF03EAF27037F7FF72C
+:107C00009B12D10F75919A554DB0EC9BEBC677E363
+:107C1000711FAE47D38A3CA9F11E96DB5580776B66
+:107C2000D146CDBAAEAF09F102D1A2777C11655A27
+:107C3000D134184E7EAB1BC343C48004FEF3071F30
+:107C40008DBCAC03FCE8FB5E3859CB52DF7236D8F2
+:107C50003C79A498043BAE3584A89D8F460A65986C
+:107C60000E5A3DFCFBEB65B0DF6DF5D1F29E2DB3F6
+:107C7000369B501ECEEA9B95F47B2E2DDF273E517E
+:107C800006DF139978CD5380AC13953117FEBE4FA4
+:107C9000A47E95067346EC2E323D6A7F5DC5F7D90A
+:107CA0004B6E8ABE0CBF14E923C07F220563C4BE9D
+:107CB0009198BD266B26D5E36AF4F0780CEF51C796
+:107CC000256462388C6A3F5AE6057A0F723B2D8A2A
+:107CD00096E2F675CC1FA022BA3F06BFCE1542C76A
+:107CE000FA08D8B720B0CF2CFB7689D963BD78725B
+:107CF000E0ED11B986E06D6B7EEDE1023CBEB9505E
+:107D00008C02D96CCD2FCC5C6DC1E3B7D4B9952270
+:107D1000D8318DD9C42EE1FB64601828E792290080
+:107D2000683BCBC078CCC7920F613A1D1DEB29038D
+:107D300014E895DA8B648F8BCAB577895D2509576E
+:107D40003E31783B0AD62D02BD62FA7DC2B2DE61B9
+:107D5000028AB9C9DD157216C1CBB00ABCDE7EFC41
+:107D6000049FC7FA84DA677135164A3F4EBA797EA6
+:107D700008786E01BE188912044E03C1351D3C9B64
+:107D800023CF661279FD11C3355D7B273C870994AB
+:107D90005F56C8A5845F06EBDF6981FD14DEAF3650
+:107DA000811F0E3F1B981FCED9DE27B7A3A80B7EDD
+:107DB0007DBADD3FA458E91EFF5F2BEA541F049DE6
+:107DC0007E228A67A75E58C0F4425304EB052A0F4F
+:107DD00017821E0830F8374511F9AE8450C2C4DF4F
+:107DE00003A00FB09D852652F9AFE2FF80DF465415
+:107DF000DAF58132487DF08E107B99F0174621CC60
+:107E00006FB7D07EE338A09F5C6A8F476E6F89584A
+:107E1000FD05B522D5775C9F3D56D43B6F023F2FC1
+:107E20009BC36358A4023D26F2176710BFDD9D0176
+:107E30009B7C8A7C6931D9FF5AE899EC73DB997F86
+:107E4000341DFE342511779387BA249279858D9E4F
+:107E500024F8FC0821E7309721236B0A7F64DB8735
+:107E600085A7F61C1E83D7FBF83522B11BE5D97216
+:107E7000D283E12B97BE5229E0E7E3B03680C72CCE
+:107E800044E834A82F382B813E96BBD122DC5FB06A
+:107E9000C2B92FB69425E8A76725D1DF563F753FB5
+:107EA000FBB8C13E1B30BCDEB2F03F42B10AD0B3DA
+:107EB0003296E36D88B84BF3605CD9D072805E6413
+:107EC000231A24CFEEB20A5A8EB5C177DFECE8D17F
+:107ED00072E0434D26F23EA152BCF17EE74805B662
+:107EE000FD5BA6E6F08FCA6625D0814F5710D0A75C
+:107EF0002FAE180917FCD48A329377763AE1F4D181
+:107F00008F9CFB5074714AE47E6A3BDE6DF451989D
+:107F1000C22B6F17ECE3A7B2E3D559FEA8F1E99B9A
+:107F20004DF189303E99BFA40DE01C344504761113
+:107F3000AF17900A6DF8095EC61B2B6CE7EC2E4359
+:107F4000956EFA292029A43EE6FB7289DAE502D86B
+:107F5000DBF3A53D06D079A208E306F7DFE2C126F0
+:107F6000112EB76C16395E89BCADDDD252B619D769
+:107F700069392988D214A09BE5049F3EE6F7B9E44D
+:107F8000312B0A71BBB65122DAA783FEE9DFBFD5D8
+:107F9000506FF76F815F01ECEFFC1A6D2A80395D3D
+:107FA000BB5D3562859BFFEB2E89FABF76D41C6BD7
+:107FB0002766E84BF67D876785011408FB8FBBA415
+:107FC000E9A976A112EAD74071BC1E5CDFC3D733A2
+:107FD0001CD3673FF18AFFCDF4092FE7B1788EB348
+:107FE000DE4F2446873A8597CAE8F05241FFF4CF26
+:107FF000E173B9456271901E1F227A7738F1DFE98B
+:108000006C5D9279A40CFA9151F766D887EC12D185
+:108010001AEA578E117D1366E33D5EFA7B1FD4BBCF
+:1080200041A6F27294D1D30A781EB54944E0C77EC6
+:108030004AD249D72356D41CF4E0F7AD9B5134887B
+:108040005F8D867E71BB57C62A44EEABD954EEAB2A
+:10805000B59804703D15EF6B745C6E3DD88A40AFE7
+:1080600087F1C6094C5EBD1489E0E7F6D4759B30F4
+:108070006EB8344AECD0436367907DD583D928EA43
+:10808000D5537281D3D1839B161B40072D781F06D1
+:10809000E596A22D2AF8B12F16CBA48CFE8CE1C355
+:1080A000FD85F81FDDA474D35A40E72B4FEC462220
+:1080B000E15B95E053D6E8FA5B43DF34617EE65A34
+:1080C00044EC23B06F497C468EAA20CFF377CF26AD
+:1080D000FC236BED02D0C346147FCA4A27523049B5
+:1080E000E6DFFA1789D9EF2F6D06FB7D247485CB67
+:1080F000AF4AE7370FC51EE171416E8FB4C99D8449
+:108100000F4DCC63A06FB87DE22BEA24F4F9DF8C2D
+:10811000BE07DBBFAFD8EE4775DA2B4E3BA556D472
+:108120006C76A9735D973CC91B617E6DB998BF0BD6
+:10813000FA8E775CA2FB923D91C5FF51A0A7FAE1B0
+:10814000DFB97DC4CBF9971502EFC1D7C7F20DF6A1
+:108150005E06E5A3D19C4FBFD03F9F723EBA84918B
+:108160007E04F0239B2AE123A398F011E70FA9DBFB
+:108170006C1983E94CAF13C1238DC04CCFC2E5AB62
+:10818000307D2785149D8E62E3CA1313EDE35DE80D
+:10819000ECB15AD120FEEF28EE067F0F9B4788995D
+:1081A000E92F4E70BABA0874C5E92C7FF702B2AE57
+:1081B0005781A0A7835E7597233F62760ED2F61B88
+:1081C000563FAD0F35BAC7CF6B1FEF377EAE167D6A
+:1081D000B8F87948B6FBB3066A3FD4B8B9747918D1
+:1081E000A18FDE32DB873AEBC565265F4FEEB3C168
+:1081F000A50F3CA4EDD1783F74A27E487F3FD159B2
+:10820000838083138E3364E667F998E0E88C6BBF54
+:10821000CCE4FC40F2C06F1849710CF8C510F5DBD6
+:108220000411F3DBD8E9FDF14D94DEFD21712F88B7
+:10823000A870ED11D36B990FA6F725F2F014BDE7E6
+:10824000152793801FA7FE49A7770692B72B55E302
+:1082500036D925CF84EFB3537904988B5DF208D2D9
+:10826000E2B5E6A3C923182CBC7BFD962C2FE0F6C3
+:108270005246B7D8707803C365ED610FB1EFB1FE18
+:1082800093ACF1B2B56C7F773BDB1FDE896261F89E
+:10829000781E8915C02FE7D1B1F0340BDDEF9415AE
+:1082A000CA2F2D9EB7C06FCAE3E077B5D3329FCFF8
+:1082B000DDBBEDE5CFA1C539E0AFFBDCA31EF020AF
+:1082C000A0B50EBF593D10049EFFDDA8A619F0D63B
+:1082D000E4A176E8ED1A92216EBDE1075F9FB11A25
+:1082E000EC13667FBC87E5B26EB19FD605130AE03A
+:1082F000F7EDAE69375F87A07DA2390FE2D7998885
+:10830000EC479D70BEA3C53EBF81E6EF9C2F425B4C
+:10831000FA9D87DC21B8C659F7CBF6386BBA7C29B1
+:108320009E27F5924CF16FCE45C47E32DF0C241AA5
+:10833000883EA1795203B57F15DA4FFFE0ED7F3615
+:10834000C0F81BD49E05C4CECA3663E0EFE1F1BE8F
+:108350002A54638CC4BFCACF2F3281E77AEB45061B
+:1083600059AFA8FF7AE9E67D56534D714A6AFE5F20
+:1083700013E2276597F5DF2FC5ABA07F2FE0418281
+:10838000A74CF04DFCBB18BFD572B045C8803CA6C9
+:108390002EB2CFF3E9B28D1EAAE117906BC554AE91
+:1083A000058AEDDF9D7EDFDFF5E23D49F88F84969B
+:1083B00075B01F824909FC32A5F2B9DEFA78BC2AF1
+:1083C0005817EC93508CC88D5A8DD6AF42FACED93F
+:1083D0002584FFC8BEBBB6750C8997D70ED7A3E01E
+:1083E000879551D4207D38E8AEFAB28012167D58B8
+:1083F0002DF728C067D5D82EB2BEDF18916CFE5776
+:10840000E7D383543D584CFDB9C43FA4E1B265DDC8
+:10841000BF6F17585E8A9EB1B41FBFDCC608F5F364
+:10842000DEDE3A3683FA03EDF2F702DB1FFDE4E904
+:108430006F28E0BF3FFFD4E99B00DEEBFF45422AF7
+:10844000E4653C1D4249628F2514B0C7D67549AE1C
+:10845000FE0392390371CDEF8608BED63DEB4D2C5D
+:10846000C4EDD73DF7F66484E777614BCF2B23C18A
+:108470006E7E4AA07E6BB37BF212FC7E9D8C56B959
+:10848000F9058A3DD44E3DF7C34025F0B7D0717051
+:1084900025E9B773B9C76BD95F5FE5F1F07AD42EE0
+:1084A0007F52488C15DCE647F33ACE3D29D0F91DC2
+:1084B000F0247C30BF8EBD4A1CCFA3BAE37D224F8F
+:1084C000E67DF7DB618043F501C9A607AA3BA4A4BA
+:1084D0007732799E8627C483841940278C5EBA360A
+:1084E00090385055E7B6F7C14F517DC02ED7305C5C
+:1084F000A24980EBEB52742194BFF7ADB08E41F5E9
+:10850000DE9127C20057DCEF6A2503F48D9DBEA1E2
+:10851000FFCB597DFB43A887C4E1AA3B5BE9785DAB
+:108520009FF90DE8956A87FC7C0F7EC9ED6BCFC47F
+:108530003C0EBBB0637071B8F5DFBEF89889C73DDB
+:10854000F7EC6F1F33F1FCEFF9EB7F3DF600F0E73E
+:108550008F7D1AC8FFEAA77E1146167A5CE7A1FC58
+:10856000786114327371BD0BBFF4264CFCEAC20B68
+:10857000BF19ADE3755F78E68F393AAE5FFBC2FC99
+:10858000110087DAEFCF1BD1DF7E1BE835E1B5CED6
+:108590002B41F0AA1F10A811F43C7B3AF073A8EB12
+:1085A000D06898E7F913DE28D83DD5F85DDD54C0D2
+:1085B000D706A28FA1BC09C3B9EAE9ADEF839CE855
+:1085C0000B6F73A4489CF0C991E08CAFEA7A7B01F1
+:1085D000C11BEA217AD459BFFA38C6E794F4F8BB34
+:1085E00088FEAC80BCAB7EBA958ED789F117EE8B36
+:1085F000BFF3F0CBACBEF86B71E0EF22BAE7F15CF1
+:108600004868EB1A668B7FF2672AEE17CB88F52352
+:108610002FB83C1808BE6B043AAF651E63B707F865
+:10862000EAD9402F7E17027EBF7D7134C2F471C635
+:10863000D3B312E466CF0B5E6D1F7EBFEE85D70904
+:108640009F5DF8FE51452779972828E4B0FC2FFA62
+:108650007304E47015DDCBA1EAFDA1A4379CC253DD
+:10866000556251851E26EF4F93F7094AFF558983BE
+:108670004B0517BC1DF314523B2A319CC065C3FE49
+:1086800037146A5FA6F02994023E4F2F80F7E9F075
+:10869000C9D7AFC1FA675AF0BA9FF2ADB37E15E6FB
+:1086A0004FD07B7DF09B105E87E785BD5E19F4DEC1
+:1086B00005B0BF827DF19E823FB57F86BA5FF9A982
+:1086C00093BF795C98C1213D7D98CC0EE87F7D43B6
+:1086D00085DF8F3CBA8D8E381CCFFDD95DFE9F6142
+:1086E00072A30A99157916FB44F560FB04F2C65093
+:1086F000CC1C59909AEF39D84760FA3BF79444E282
+:1087000030CD9D87881C77CA8BAA34FEBF3FF2F11B
+:108710000E1C9C0C72EDDC8B3F24F459F5F46905BA
+:10872000FC63AF747C4FE99E98E207D00F098B7E03
+:1087300038F79D8393A93C70DFFF2A0AEDBFFA79D1
+:108740007BFFD54FBF6FEB7FBDD9A9D0FC84FEC79F
+:10875000794F3696C37ADF3BE241204FDFEB945CE2
+:10876000FDADBF05FD68C9336B3EBAE00D88DF97EC
+:108770001CF3EBA047BBB618237680BD76CC8340B4
+:108780007E23D9F82DC497BB8EFA75C87BE83A765C
+:10879000B3A45BFC133F70C073E671735E08F737D8
+:1087A000B33B56025B28A7DC283D2942CCA277FECA
+:1087B000B5472B4680DC6F047B7E3C8C178D90F890
+:1087C00077784105CD0B14359FABFEA6FD79589CFB
+:1087D000DCA38948B7D223DF6F31BF4F73D0DDFFF1
+:1087E0005CA670FB108F6B9183D856AD74C35B8908
+:1087F00042F741E9BE970EF07DB6C2F200D27CEF9F
+:10880000E56F861F2524C6DCE63D99F5E3F4ABA6AB
+:1088100093071ED6CF144567FDD3F502BC1759F256
+:10882000DD47A2C466F07FA160D019678EA9D63853
+:1088300073E591831057CE5EF27C2EC03F8C1AB543
+:1088400077891D8FA257FAB1639D716567BE61BAC2
+:1088500038B31AAC3A91447DFBEB1B5737485CBDEB
+:1088600031BF5CB5C6D51BB53E71F50D0A1EB729E3
+:108870000D1E3EABCCBD17BE63B333EEF6BD49A1B2
+:10888000FEABEB51F7F756C33CA3342E3FDB01AFF1
+:108890004F3278FD780C5E38563D6548973D18BEDE
+:1088A000F3961A8D2002E7AFE8597F10F88CC7E5E0
+:1088B000CDF1E295C0E0E137D47C8795EAE20795F7
+:1088C00041E43B202DCB552FA4E66132BE89907D3B
+:1088D000128FBF1C3A75B70A724B46F18A024B3CA5
+:1088E0008CE4D1E3FE72923E64E0F92A9A4EECEDFC
+:1088F0009CE4DAAFDE05F1722D9FC41FA4CBD71123
+:10890000FFA1B35F291235499E57502F932CE334B2
+:1089100067D3788CACC55CF381572AF1A761BDD2CF
+:10892000E539A45F51A5F10C141C5C1EEC5796842C
+:10893000097C550C5F908F0464B02E960FF5D09291
+:1089400030D133BEC39EBDF0DD17A4F951F78BFEC5
+:1089500028E44F39F3A3CADEA4F196E6D30289A333
+:1089600070FA6D2EA8B90AE4783FF9512F2B16BF83
+:108970007ABAFC285FF04E921FE5FBC0F951917264
+:10898000B0C79A337919AB133C8F6696EFF42BE599
+:10899000F03CD04FCD2C3F0A99AFCE23F57919D5B5
+:1089A0001C32E03BCBA7CAD9DADC00F5B347A29A68
+:1089B0004EE2CF33D0328B9CF579699CF9CB8AF1AA
+:1089C0009F8A45EE71FCFB7AE96AAB0AFA1B3F49C4
+:1089D000BCB219D315D8ED39C95664D547FCC9E9DD
+:1089E000A8B9A8FF789D7CF91AE2C7E765554B182E
+:1089F000864B7D43A57A82D32FC4D3402FA97AFC1E
+:108A0000AB77013D6707A3014A97244ED61224EEA7
+:108A1000A93EEB6829BA9DC4BD2E6AD4DBCDE9B866
+:108A2000EFFCE7B0F9179A405F1783288A5CE45F90
+:108A30006A1D25641D2B1543F55AE0987D957BBE74
+:108A4000E9762F5D4F536C45EC2E98C91A7BDC9567
+:108A5000E75FF0FA01213E1CFAF564D3B8ABA852E7
+:108A60007E4BE10BAB0A8B7FB301AD308104E41583
+:108A70009DE4C8A2AC2548FD31BEF868AF2D3ED7B5
+:108A80004DE3B88E78E27CE91ECADF03E06F07DBB6
+:108A90009F6C83B8DB7888CF45D8B93D9DC5E90C7C
+:108AA0009A2F94869E5A8AFA8F43B5D74749FB9DE1
+:108AB000F5A5340F4940CCAFFDF506A013704B501F
+:108AC000BADFDF007C1092385F3C45CA0F0AB41C45
+:108AD000DFDA45F8E6D0A9D72BEFC0F4D16CF8095E
+:108AE000FF0FB43E2D3183E075A8E3F45D2F1DB771
+:108AF000C50892FDEE40EBD69274DCC18EC3E3E371
+:108B0000A9F5A9649C667D8071DAE93803CF9FF2EC
+:108B1000C98E836B2B20AEAC62FEF7E1F7EAEC1E48
+:108B2000E4161FCA60FC73E89497C8EB966C9AC76A
+:108B3000EB290E1AD40968EFDF3331672E39C7509D
+:108B40007235C98BDF71B095C81905C6C1553CD1C6
+:108B5000E06ADA2E6EC0F9D970398A825FDF539CE1
+:108B60007307BCAF43EDB1B9A0874BE9B92D4F7185
+:108B7000F15DD04F26F0259EC73495E67D788AAF0B
+:108B8000BD1BEA1F9CFE5ABC01E0544AE9001DCE01
+:108B9000B5C1B1592FE4E771FAE57B4FA93D6E816C
+:108BA00054BF2D6F09C94B49BC1CCB856D5E8BFF33
+:108BB0001BEBC59D50F6A01213ECBD5DB7DC1CB5D8
+:108BC000F2F39795D8C3548EF03C2CCEE7EEF970B3
+:108BD000CDD93CAF2CAE4A2570FEA8374F7A61AE96
+:108BE00035AF8BE54907799E7494C6E1DAF17F6E63
+:108BF0007971CEF3891F559EF477BC6C3F1C40A35E
+:108C0000204FFA471E144DE279B7FD428A421E8C6E
+:108C1000933E9CFD39F3FB7BED9134FCFC6B008EA5
+:108C200045EEE5C61D78BBD347E2737CBC97403E5A
+:108C30004D1C984F47AEB1F733AAC67EEEEAAA3A6A
+:108C40007BBCAAC0CCB3D51FD35268FB3EB6FD6A2D
+:108C5000DBF7F1BBA7DACA1312D7DAEA7FA263AE59
+:108C6000AD3CA9F353B6FA530E2CB695AF49DE6A64
+:108C7000AB3FEDF0EDB6EFD38FACB37D9F7962A340
+:108C8000AD3CABFB8BB6FA75D83C51483E1C8D37DA
+:108C9000A1ED23452B7DB66662BD9281E1988909DD
+:108CA0008626EB937833CD314EE51938DB49458A7A
+:108CB000A161FE95F471E51AC91FBC93F09154941B
+:108CC000335727EF672C00BF132AA1E7AF7CAC3FD7
+:108CD0004F114AC2B94B39E8C0AF232EED91B6937C
+:108CE00078AA72F286C342B82F5E3D11679EE2E019
+:108CF000E2DAB2EE683744BEC854595C7B14E60B26
+:108D0000E247FCB344CE3D9787887D60D9DF1038B9
+:108D1000F2FDCD1C1535024C395F94ADE81949F2CE
+:108D2000D97BF7355E7128F9C67DF58A97D85D5CE9
+:108D3000CE0CA457A4C4345B1E82F389E5DF14155E
+:108D4000F6E1E15B893CEADD17F4CAC7D854F8EED6
+:108D500091A3443EF6CABF8E3C9B5C18AC7DE69462
+:108D6000D36D20F4C9791F77791D863C302C971E6E
+:108D70005C72138983A15A643BE79753195341EFFF
+:108D800061BBAC42B5EC9FC3A5D43EFB7BB353BDE6
+:108D90006CBDBD74CAEC550ED76105353112D70BC9
+:108DA0008908F6550DB3A311F003B64015CB3E6DFF
+:108DB000973A86C8D1C6A02282BFB4F1F07C121FB8
+:108DC000F0FA622AE4D135786215B0AE864C517360
+:108DD000CB77DAA252FF8C521798B6BF1FFA501405
+:108DE000BCEF7759EF3E95FA5D1AB5C58741CF655F
+:108DF00085141D526E9B0FCE5A04E3CA0B650DF607
+:108E0000B5086FE2DEB6C41521DF1711F88B442FC9
+:108E10002A756132FE40F3BD47A57E066F9DAFDF28
+:108E2000F97A15773F45BAF96E85F9660F3C5F6FA1
+:108E300036CD5FF5D605C9F8FF0C1759B8C0DF83EA
+:108E40008C96725CAFE9F40DED458462689EDE237A
+:108E50000BA7123AC582DA46BF7C1F81E937A10E03
+:108E60004FEDDFF939D5BB559A97C0F18A74EA8F77
+:108E7000181697C9BE372B4EF7BF29F941E928CB01
+:108E80001345E45C57BE4CE292E0A6B1FA31FECA4B
+:108E9000F671DE4F4609BE5A3F23A32D406F457839
+:108EA0003D70DEF6308D3BB57AA295B1606A3CDE4E
+:108EB000FE4D860F192DCD20F95BD2C2889BFDD9BE
+:108EC0004BE70C6E4E39FB632E6773512E95B3132F
+:108ED00097C311A174FD38ED0D7EBE67E8E74EDA49
+:108EE000093C5BF31F257634F78FA148C900FE1EAD
+:108EF0001A2F4DE179B99EC478946F9C4A9C7EAD3F
+:108F0000450CCF358EFC5D86678E5FEEB747916C62
+:108F1000C2D71CDF12C0137025CD8EF4A7AF24C6B4
+:108F2000374E789EF91F0ACF9FC31AF0336B145E39
+:108F30003FF0CDA11B11898339F891B7E374EF5C41
+:108F4000BFEAFB9FBD7E4E0FE9EB9BAEFB0F1ED72A
+:108F50000D317A5399DE7CB9F4AD1638272267D3E8
+:108F6000FD6EA8B491DCD322235303FF5A889FCB14
+:108F700061E732793E957FA27DFFC1F30B4919F37A
+:108F8000BB87ED3FFADC9BC2EC2C7E4EDF397F279E
+:108F9000BEE6F8DCF30751BEBBDFD5198FE3F10D58
+:108FA0009E07CBE300040E78FD9E59628CC8BF1269
+:108FB00064EC75914FCB7C542F74BDE8237912A1DA
+:108FC0004A85F863F34A926550CEAB4151D013D72E
+:108FD0009E3982E2B8D3B17E2AF7F34A1202F83DF5
+:108FE000F2CED1BCD85D2C5E99579B10565BC679EA
+:108FF000C047E5ECA553F713F9F8E2289A877E5F9E
+:1090000019B5DF8E446E6F2F83714B693E7908EF7F
+:1090100017216F2C74C24BF26F514937023F2AD689
+:109020000266087F3F538FA6DE3916F2BE54F23C2B
+:1090300057AF91E7A151CAC1EB71BD8D057E1DFAF5
+:109040006D2AF4D373BB2195ECF7FF3BF373C4AFE8
+:109050007AA13E42EAB77CC9207645E3C1B3C46F2A
+:109060001830A645A91FD5905029CCE788017E0E5F
+:109070002447F5C5F0FDD02F493D4989FFD204FBB7
+:10908000E45685ECEF010E104F68F0D17CB9ADBE0F
+:109090009A48263C0BD0AA452EF0BED5C7E34CAA71
+:1090A000A4E4A4F29094D2A49401FEE412D439165C
+:1090B000E46553A20CF4345AABE9304EBE9A28034F
+:1090C000FF71FE1A2D0A3E74A594DE23C2F1E1F170
+:1090D000A1D83341A89714EEC5E316FAA9DECC3B1C
+:1090E0009120F70C5D3A35D3D5FEBFFF6419F9BE68
+:1090F000BDBEE258B9859F8369E2950F14CD7DD43A
+:1091000087FBFD196C7486A7EF973F07DBEFCF7CD9
+:10911000549F1E3A357E04D8977569F2A8250DE351
+:109120006918954FE08FD838561F9119B4F643E16E
+:1091300021BDF8438AD789943E1BBE3F3E03FA7D8A
+:10914000E9D4720DFC7DBFCF2E22FB86F3CF790DC3
+:10915000B05FCE67A13524DFF2B999AFC0FEF0B79A
+:10916000F587B3648B5C3CFF9DA3333CB8BFF3CF62
+:109170001E9D2113E64AD8F6F11BAEFC7C06D809E9
+:10918000E65C545C839FD59A82A0DF6A95AE83E744
+:10919000C9EDCA519AE1393F9049DAE78C101F8432
+:1091A000B2A4FE7CF43BD3C8BA695C81C571F0FA05
+:1091B0001A8284AE35BC018178A1E91D0DF1AC5352
+:1091C0005E427F970A5071C114F00B4AA45DCF5ADA
+:1091D00094807C0A255903EC897C3F4D20E09BC09C
+:1091E00071ED20A13576CF5BABAF90D121CD23DCE3
+:1091F0007CEAFEF1001F2ED7E57988C4337A6E51E0
+:1092000013608F3E2CEB5F590176E06D3299072E8B
+:10921000FB34173C2E0F14DAE092C5E2131CAFE9C1
+:10922000E8645B3D8A166178FFB85E8DC2F8CFD7DF
+:109230006BA4FCA3FA08291FA8D7C9F3B9FA62F2F4
+:10924000ECAA8F92EF1DF5A5E4C9F3FAC8D65E2209
+:10925000F674AC0CF4D032EA87D374D1807C850CE0
+:1092600019A9C3B0A9A29DFC4925ECB741AE64641D
+:1092700011BE17A07D36CBF31B9E3BB7B54C4FC933
+:10928000572E4F1B3C48007964CEA27E8610F4878F
+:10929000DB672F45E82D8B5CBF82FF79AB98AD0F64
+:1092A000CF27C3B07F77D60FCB7801597DDB61B96B
+:1092B00048CAA97EDDE137D427F8CBDFB2D0F7AEBC
+:1092C000E978D5988E7609548E3DC8BEEF983E2336
+:1092D000E37628CF9A9141F27F67215DC370DCA9C4
+:1092E0008BA62723557F4FFDE19CF2B14C07819C53
+:1092F000AAD5F6B659F631F9265A15B3D0CBCE1AFF
+:10930000B9621FB133E2B98B27917C63E6D7DE5790
+:109310006ECC26FD927241DBA17293E915903373F6
+:109320002E533DD4AB7FFE4CDF73BDA730FC6F9F47
+:10933000BD450A039F803C057959124773F13C8370
+:109340009FA4F1EF59EF2411E4F72951FC1EEC51D1
+:1093500085E69BE4451202949FF4C5A6FA613F920C
+:10936000B53BB90FE3FB0F5D5E1DE28D5D2FFE91F6
+:10937000E46748931515F83BEFF9D3246F4912BB06
+:1093800015D8F12E6BBB7ABE0CF62C4C84DC2B80EE
+:109390001535C6B394C3D667763695031CC5F85900
+:1093A0006BFD5DFEF8BD74C78C0C3582F9C1C7DA60
+:1093B0009BE39B8C7C5CF6D0F2B2B6714DE66C28D8
+:1093C000E3FA99B4DC88ED846D999D111197839B24
+:1093D0008B9A0E8F8232AF5FD464E2F631A60F50C3
+:1093E000305E00FCDE5BD670396429CBB48C54FA55
+:1093F000E4EBDD70E88FAF8CC470A87A5EE82421BE
+:10940000BEE7F70AB0EEBC037BE9B9800422FBFE9D
+:10941000BC849080A39B1DF587B546EE5CE378C1C4
+:10942000A2614284DE1BA4243C51D85E4E60F782C8
+:1094300070BA782640F5C084046E6F8D4B3BEE0900
+:1094400099C0EEA1212403F2723B3DE7EBA4F3F1B6
+:10945000ACBF3A64B649A0B79FF668243ECEFCEC98
+:10946000E7B8DDC4FC39F730079E678BE9BF1AE423
+:10947000DF6A99F881D7172436631B0AADFF614173
+:10948000145BACA8C947E9657D6667CE544C2F4D87
+:1094900099F67203CB9F8F649A995913217FE8A1A3
+:1094A000D190DF5385DA577E11E6FB531A0F3F7BCD
+:1094B0007056C675B8BCE1A7348EB1A1EBA802F412
+:1094C000BDC3CFF28EBAAEF914ACAF6ABB48CEC5FD
+:1094D000015F1AE3F1748DF6AB654C2FFF1A383932
+:1094E000DF87F1FD64A1A189D720F4C6B6779BD4AC
+:1094F0004FE2B2A24D00FA7863DBF926A0AFF5B3D4
+:10950000F87D76E75F368A58FE2306DE8EB6D94DA3
+:10951000700E63FFAD159F02732B47A4FC8B09925D
+:10952000C4B5A5CC46727EEF774D22B19FC145BA36
+:1095300009C3BD48468765FCDCA5607C029F35CB2E
+:10954000441EE2F72D1E829776727F086AA1F751BA
+:109550008C7DDEBB1AECECA21A632DB1B7B589C4C1
+:109560000F301AF5FE903C89AB1095BFE3355426B9
+:10957000E37A2501EA2F2FAABC793DB493424BFD33
+:10958000C0EF3952C224FD7F8DCAE15D62A253054E
+:10959000B91C2E24F8DD15A674613E3C91D0C57E21
+:1095A00071EED560173509ABDB5E05BC66169273AC
+:1095B000AEF07E23AC9FE1B3418BAA80BFFD0C9F30
+:1095C000D25ED1847C4DFE7E9B70FB5A80EB3BFECD
+:1095D0008DF3550CD71CAFD1320CE3E16DFFC6A65D
+:1095E000C82C828742157F7FBBEDDE2615E365FF21
+:1095F00066234FB394C7FF054B752207EE257CDD2C
+:10960000187C741D2821FCFD65F07F3C99C5F99EEE
+:109610007E2F2AEC952306D8A50D664AAEA8582FB2
+:109620001459EA9763B9F0CDC72482D7C3783C9028
+:1096300013781D26D07DCF0499D8057E3C173F2E88
+:10964000FB2715927C5BBC6EE407BB61924CF43C3B
+:109650008FE32813446237437DA0077F6E21C99FA3
+:10966000C3F23A06E77CA4088DEB48D21E03F33020
+:109670000AB0FC7D415B44EE17F1155BF20A40FE37
+:109680003AF210244779ACB73B17CE2B659F5C2488
+:109690008CC67839ED6771996CBC8FC5EF7FEDA7EB
+:1096A000E71BEF8F993740BE0CD2BB73693C2A365B
+:1096B000159E236E2B1AD19FFFA5EF7E354AEC979E
+:1096C00047F265D77CB0E702745FE41D5544EECBEA
+:1096D000A84398FF812FF8FD2A4C7E7898BDE03C86
+:1096E00027C0E5892793AEB1B675DE88AC60EA1C69
+:1096F0009C143454900707B5A919608FEA01CAEF8A
+:109700008DC9599F05BB4566F2608F8F9E8FEDC94D
+:10971000449DFB10D8BF5164CD4BE0F2607BBD4A45
+:109720009E4FCC1947E2974FCCC9990BF18A43D78A
+:10973000BE47F6BF17F750FEBD78E465B823095D54
+:1097400034E9F95C202BE2974F3E42EE01F9861C8A
+:10975000DB49F2E5215F074F6967A63D0FF38900FA
+:10976000F59BFE89C927ACB7C9777E3F877CF91383
+:10977000C40FBC95C95D355E4EF695E0C6D3812E0B
+:10978000503BB96789C3C1792F877C793269FF273C
+:109790003F853FCF5F72E629F1F9FC80CDA7EF7DD1
+:1097A000AE767C70BF06C7036F5F2B1823B47EE8CC
+:1097B000A6FAB2841296BC90D4B90D85BCBF00E75E
+:1097C0005D32E05E9578FB7505C007096227FA8275
+:1097D0008DB6FB595144EEB19E2F0938CEBB38F9F6
+:1097E00005EE05063DADE8FD9F6BF935DEE6F2BC02
+:1097F0005C92A72EA3AF825D7B3EF0E60CF0C755CE
+:10980000633101AE72249BE43CE905B62F919FBF02
+:10981000979CE7E1F3E3FE385EAE3AB088F8E9AA38
+:10982000F707C9799EAA0495831B54F3B057B4E691
+:10983000DD1A49C8B7F51CA0FDE980038C8F3F688D
+:109840006B7261FD81BA3133E19C498E5873D568E2
+:10985000808F4CF100FBE56783E49CAE0C7A9C8F13
+:10986000FB4BB60F5CC6EC9100324580A7E48F76C7
+:10987000237A66D190B17D24F5CABDAB9B801F765B
+:1098800039ECAD5D7E5ADEBCEDEAA646AA9F895C46
+:109890005CD6F62FC41E6AF2F1F273444EEE52DA31
+:1098A000932027CDE7BC3AE83DDC9E9C63376F2DC3
+:1098B00026FA432A447900B77270B480FC7BCEBB91
+:1098C0000FFC0C4FFAE231BF65BF733E746234EC9B
+:1098D0002B5DFA336DFD8D1E5A7F78FC2EC003FF81
+:1098E0005E1EDE4DFAC7ED88BF03E51F7913DBBAB4
+:1098F00028E7392F3967B8C763B7B7F97337933398
+:109900002D8E7B39D478A3019B73CE9FCEFB9339E8
+:10991000BFCA9727D8F2A474A69F65D9005725FE21
+:109920003E917CFF939FD2410BCBC7493F4E569A45
+:1099300071EC71BBBEE3CC60720231FE97B5DEFB09
+:1099400036FBC97F75C6179DF28D3FB97CCB0E5093
+:10995000FE8A09F1AE001E675DA273819FF2E76483
+:10996000E0CF3B995E2AEE78E84550EBDF528DF769
+:10997000013F2B55636C60F8D0F9E70D369E8BFCE8
+:10998000A276D91A6AE7D6B64EFB14946B77146A9E
+:10999000A64BBC883FD75C0ED8E4D70EBFCEEE45B1
+:1099A00034891C5B73394CBE7F74E3F96CE7D9FAD8
+:1099B0008E1724DFF978F738E4F3A16BFF6D572990
+:1099C000A6E3DA673CA2D7324EED33EC1C900FCB06
+:1099D0006B3BBF1BC0EF7201EACD5304F9B053617A
+:1099E000651335835DF4A4553E9482DD966A0FF7C6
+:1099F00011EEF4F3F6BEE6F27C97FA0147FD42DE83
+:109A00007F26E9DF391F2E7FA00C769AFC172F9F47
+:109A10001F915F0F898EFEB2F8F879A43F6EAF7F79
+:109A2000A1ADF01553063A4D948DA4FE1D1DEC809A
+:109A30006FC851BFF59EAB2FF8A9DC5C73798C0D14
+:109A4000DF29B88FB3BDFF4D7DC496AF7F77BC963D
+:109A50009CD3F802F327AEC1163D69B767A42D4F1A
+:109A6000FF1FF3F8A0F3B82ECD3CE6FC8DE7516064
+:109A7000E3CFD43C8A6CEF3FE83C7EE0A3F2F805EC
+:109A8000F69CAFD17B01E6EB02F15BCFC7757D9809
+:109A9000D66FC04F153FE7CBC80C92FB6B13B43E9B
+:109AA0002E833FE0B37FB9EF9DEBC97DCF06C9C7D9
+:109AB000E1F74EF1FB1007BA9FC8F9771B9CDF0353
+:109AC00069EE5FFD6290C2E9A129372192BF1E8C29
+:109AD0009338C1C1DC0511B0D3BF32A58A3C1B73DA
+:109AE0006744401E35843E67CB37C77B04D773B0CD
+:109AF000EFB17ED1E51B44EB7994AD701EC5A53E58
+:109B00008F8B6D55F9FD801FCF7A777F4CEB2D0D34
+:109B100051FDB9558D93B86073E4E399FFB3413AB1
+:109B2000CE4353E6203ADF39491AF75174EB796096
+:109B3000FE3C189A11817536642E88003D3766CE3A
+:109B4000B0AD474AB39E957C3DDAC7BB9E7FEFC55B
+:109B5000C7075DCF02D73C5839DBFDDEF9C6101DC3
+:109B60006F6B244EE8ECE35AD7990F8DA7A1AD2B6C
+:109B70008BADEB8E20DD476CD5291F05A4D87F1453
+:109B80000803F3E1407F4F0415E9E260F2F07EC57F
+:109B9000E0958E7F6FF52486C3BC4ED4D3FDF36B66
+:109BA000EC3EA95FAD690811BFB6639CADF9FB42FD
+:109BB000FDF939FED71AFBF9F481E48619A471A0E6
+:109BC0005BE2F676CB2B03AEF79B60F8ED2C2848D2
+:109BD000C1B30FFE3F62B8A5A3C7A1C2AD393234ED
+:109BE000B80DC40777C0253783801BA7B774FDFC69
+:109BF000FF4267BB83D46E1804BC087DFDADE0F561
+:109C0000F74A5FCF0E9EBEFE012FA23707475F5C6B
+:109C10008E7528F49E45673FEF84E83D9BE3859A67
+:109C20006337427CE13312F1F71EDB53BE0189D664
+:109C30007A54BF1CAB98B781E4BBC60208EECF3A9A
+:109C40002E46FFBD04E20E8B693B67FFC7187C5EA2
+:109C50000E65B27DBE3E1CFC08C7634BFA5D1FAAB1
+:109C6000B0AC8BE4655AEEA392FAC2F718D277949F
+:109C700080BF69A1FB3C383ED38D3B547C1E8F7D59
+:109C80006348F81C68BD5DA1C1EAA504C14336EA7A
+:109C9000FD3B1857033C3B449ACF710A5ECD82FBD3
+:109CA000C910A9B4BC7204B9E76C4A98E53D29FA19
+:109CB00006F09379972CDC16C2783BBE2C53B0DEAD
+:109CC0007F2686A9DD326385BB5D9811A674906AF4
+:109CD0002FA0F17ADF7A7F65F6E3B215F45E2A24CD
+:109CE0001BA3165BCED54D08DBBF3BDB47C2613201
+:109CF000CE71C1FD7E583F9BC7F2A5FDB747B5C3E6
+:109D0000D8E16D6D92DBFD829C3FFE4F283E2C8C8E
+:109D1000EBBF26C4BFFE79A0A309411AF7905101F9
+:109D2000C4EB793FD9324A2A18EEEF78B449E0A75C
+:109D300075E927BFBF7ED2C195AF878F03AC08F707
+:109D4000B2E0FD23D92F961808CD867DA2377A2F51
+:109D50003D6C48E9208BE5CFCCAC092436839D27A8
+:109D6000E3755AE6DBF5A7799F86EF5DC7446D4B37
+:109D7000415F380C241FCAC234DE902DC5B7F8C02D
+:109D80003FB64A70BDDFECDA30FDFB23E742BD7120
+:109D9000F55130CEB847E31EB8E7E06696DF845051
+:109DA0007CD422CBF8E7189D38DB654B341E8D5EE2
+:109DB000A7FCDCB16FDD2837FEF939E3D373A1626C
+:109DC0005B1ECED2D8BD1EE0CFA50B1779F4207C48
+:109DD000D729BDB1797428F151D70453704A2B8724
+:109DE000187CBA4EC41BE07E8755750289234DDC72
+:109DF00044E96ED5A683E206FCDCCBF86F91806C5B
+:109E00007990F730BC76ECF38F86F977703F1D744C
+:109E10008CE7B17237227EAF3B1FFCF456B84BB5CE
+:109E20005B40CC4F76A002F20DBA599E8889BF6F75
+:109E300006F8950F27F31DB7E9FD5A90CF5D0A226A
+:109E4000E7E5FEB3D54BFE6E05A7975E39B1E95243
+:109E50003D24DD3DA2242701DD0C6FA8F9BC9B9FAA
+:109E6000FC0136CF3F0463196E762E7F7279CEEBFC
+:109E70002D96758F5BFD25157639C6E73DCC9B3C4D
+:109E8000EF765F432F1D26FAD77BBF60729CE3BD40
+:109E900017DF27DCF7455F6172AF2331773DD15B78
+:109EA000A6570779C8E7C3E1956D5238DDBC54B2B7
+:109EB000C9DB550B038EF34814AE9FF5EA8FC13A08
+:109EC0001ED9F76F93000F4EFDE097E20A7CBF1B8F
+:109ED000253D2027CE483A79BE566FBF47FA351444
+:109EE000DF311DF4679DE4CA57CF32BCBC5679C739
+:109EF0003232FF464983F99F5E31ECA652902F958E
+:109F00009E28E44F9E6EBC2F749765FD5CDF39E799
+:109F1000F5AB3577F4ABB79657DAF1D6A150BBC0A5
+:109F2000FC14E5C3B558DECC26F4D5BD63261EFF70
+:109F30005822EB9A365A1DC1DF695CC27E3F23C6A8
+:109F40001F9C89E5CD5991FAC3CC7FA27263E9A326
+:109F5000B12688F39EAD9BF64237AEF713A607DE17
+:109F6000ACEB5F3F3AE969DCA3F6FB29679C400A4A
+:109F7000B48FD7BAEB835B32034CBE4447837CB9C2
+:109F80006D937BBD7F86E44A0CEFB37F95D6B8E531
+:109F90006D5ED6E87C57C5DCDB5FD642F43BE82536
+:109FA00017387F2F2340E5BCAC8D0639BD2ACD7C08
+:109FB000BF9B1126FDBCDD74FF6D10EF3B23DAE57E
+:109FC000F3DE0C4A17F519543E9FDD77AB6738E096
+:109FD000A959D0801EDECA8C4E007A5BDD789AF8D3
+:109FE00011FE89D5AF0CC67E171E0EFCB278FE702E
+:109FF0008C97AE15282AE8E9E5FF25C63FD912BDA2
+:10A00000C700EBBF7740FFE1A6EF10FB433646DF0A
+:10A0100032895ED90879856745731DC943D9E7A799
+:10A020007947283ADD7ABF8C2783C2EFECFEA1E1A5
+:10A030007B592CD0AF1D7F0CB5579171F707348831
+:10A040003F1EAB9092D7E349BEBB3FB0572AE8CB47
+:10A0500017E9C61FAA1D7876FFD0ECC081D6FD890E
+:10A060008C8241D9F5172B1E79B004F848699FEC12
+:10A07000267FB99C3ECEFC564EFAE1CF998C2ECE6F
+:10A0800024FA9FD7DDBBEDF3B9ADC63E1FCE2F67D7
+:10A09000120D7EC80FC7A34FB2DAA5A87CFA00E75D
+:10A0A0001CA8FF37DD3C3F9D6197134079104F5B43
+:10A0B000CBE4CD9B758F84AD7870AEFFACC8F6074E
+:10A0C0008FD1BCADB1B1D57387EB29FAAC6470F810
+:10A0D000A8E992EB19673F7FEF74C8F5DC4074C8BC
+:10A0E000E582B3FD3988F3E3A5AF963505E232E7A3
+:10A0F000C23A2D236D011C9141A5ECDC32D247C33D
+:10A10000B99BB3FBFC08FECEA6D9E64D8CC52C70DE
+:10A1100066DF7513ACEBF90AC3CFAAA59970AD0D34
+:10A12000A693E88D23487E8144EEEB7AED44D60277
+:10A13000283F724404098D6EAB5D2DC1FA1ECDA07F
+:10A14000FBCE559B8E127B70A874BEAAC6AEFF2FA5
+:10A15000B375F4DA59724F09D04F3A383466503833
+:10A160002C8B2D9A0FF2F98E4D0291B74D193AF5BD
+:10A17000D7CA0691DBA891EA47A462786015721AE3
+:10A180001601F0F832FBFB63724CB19E4FBA6BFBC9
+:10A19000FDF3C13E74F24B0ED34F481399BC8F7F31
+:10A1A0003B637A4A3EBF25D41C1C81AB5C9BA1F16A
+:10A1B000FB61099FF2F55C9B41D787EDB46F93BFBC
+:10A1C000BBC4D687A20E7A13DBAB7E04F09FAB1222
+:10A1D000BBC0EFC5721FF2E6BEE1D768DE1CE52BFF
+:10A1E0006EEF38DBDF2CC76D76E3FF05B9373CBD7A
+:10A1F0001DF20F7DE15EFF7D06B7BF95BEF8CB4730
+:10A20000A42F8E86759B9DC5F5C6FF03C8D629333E
+:10A2100000800000000000001F8B0800000000000C
+:10A22000000BDD7D0D7854D5B5E83E73664E669221
+:10A23000996492CCE41F9C49000324780221444095
+:10A2400098240482609D408060030E081A2584A82B
+:10A250005879AFDCE684440C14BDF1E7AAB55EEF93
+:10A2600010D0F25ABC0D965A54DA8E54507BF53603
+:10A27000F88BFDA2466B292085E8AB57DB8F5BDEB0
+:10A280005AFB2773CEC94C08DAF6F2BDF0F19DEC0B
+:10A29000B3F7D93FEB7FADBDF6CE098B3A3FD34341
+:10A2A00088B655264F10423E3CF65935961FE8B504
+:10A2B000B82528AFD8B84A0E390949C692979013E5
+:10A2C000E1C529583E8F3FB3873E6F7A44269142BD
+:10A2D000427FCEC3FFEB5B920CE513DD890182E385
+:10A2E000CD7285C7FA09D9AF108D9412F2C1B6CCE0
+:10A2F000F0162857DB89E69C4CC8F4141F1DCFB319
+:10A30000F98B56F724984FF77F14937C98DF3D77AD
+:10A31000AE08150D1DF72F6E0B215361009FCF4224
+:10A320003208B9C3CEC65C9D4C02D83F81F19ED0A5
+:10A33000F52FBE7BBB9590C8E5503F06BE2B8B7EAC
+:10A3400067EE7FE975578EC675BF7DDD8CD1AB8A10
+:10A35000A2DFC583C35229F42F4B70DC365945B8B0
+:10A36000EEB937A1B13B06DCBE8D709D3A747CFC22
+:10A37000B1C23A16F3DF976CAEB8CB0520D9923450
+:10A38000EBAA508CF1DF26A17BA6C278DA66369E56
+:10A39000799C6BF8386FD7DFB004E1FFB926BB6555
+:10A3A00080477F839C5C8EDFD5DBD4B1D07FBF76C6
+:10A3B000BB6BAD6E9EBF8D039FDF36DEE08A8507E7
+:10A3C000F15C566FA4830FC8C06BD3709CDDB1E7FE
+:10A3D000B75ED09712BAF74A98DFC9AB655583F9D3
+:10A3E0009CB4C077482F8FC277BEA1DFADE2DF7D7E
+:10A3F000B07978BA5C5C639CCF92638946BAB490BA
+:10A40000C69E18EB59FF15E97E05D2BD3D5ADEA365
+:10A410000C8C72C3F71FEC3CF7DE9DB89E9D89142F
+:10A42000DEE67E9253653ADE49E41384D7F604CE25
+:10A43000275DCDCFC1771F5C93A36E2143F9839035
+:10A44000AE6F4C87FABE6E4BC976A8DAD39DD4188E
+:10A450008E31DFF1A98C0E3CB2963801DA93771871
+:10A460003E90DC906F96707A7377FFB08558A2DFCC
+:10A47000BD83749040C81BAD76FADCE1B6D3F1EB36
+:10A4800016D62A3E1867AD9504107EF407FA754F6C
+:10A49000C8DBB91D867ACBC2CADA6AE03F69E87CBC
+:10A4A000BEC7E9724F78D1B0F0AD6F900DF0AC5BE4
+:10A4B0006884AF993E8F872D35B1D62FE839DE7885
+:10A4C000D7D9C25EC4D331BEDEB7F97A7FDBD8EE0E
+:10A4D000C2F6E671F684BB87E5836F361AE9E2427D
+:10A4E000EB3CE6F653B82E0F19BF5B566F5CEF12CC
+:10A4F000D272150152594A541B3EEB484BF173007E
+:10A50000CAE38F2CA6F3798B909A1E9CEFB9DB8B54
+:10A510006B8BA3FD1FE6F0FEBCEEF66B50ECBCA30C
+:10A52000B414BB63CCE72D0E2781EFB7E2C0F379FB
+:10A530002E77DF413C23BD2E9563E2F96DCE47EFC8
+:10A54000340CCF474BEB86C7F3EFDD6EDE4F7B223B
+:10A55000AEF38418F75136EE89307B2FFAFBFDDF1E
+:10A56000887FFB89760BA5E370A21BF58807C9439A
+:10A57000A7475A53B9FE291C5E8F88E71B42AE9A43
+:10A58000DAD75903363D3E4ADC8CCF45B96EA1710E
+:10A590009EEF27BBD9B8C43D3AE8D2C90DAE5F855E
+:10A5A000BE7BE0C989EFA3FEF471FEAF0B7E6A4368
+:10A5B00078807CBDCB85EB7ADDE246F95A762C605B
+:10A5C000D3C3EFCA1406BF93BB8787DF955C1E5DBC
+:10A5D00048CE9AD7FBC13FDD3D19FBFDE09FBEB0E1
+:10A5E000E9FB5FFA652E89A447CBD7D74B81700C66
+:10A5F0003EBBDDAD8C08EEB79BE078FD97A369FF0D
+:10A600001E99B4F4C45A17CA37E87749B0C2E605B0
+:10A6100078DEB0595225E882A4B27E6E10F2CEEAFE
+:10A620001B5D0B70F7B6B7DC118CD14F3987F79FE4
+:10A630009CC194587C36C81F9C1E44BBA5D6902D47
+:10A64000567BB35EEDE77C6E6EB700E9D13B727A64
+:10A650001CB4834CED473A8FE9298C2FD313227F0A
+:10A660004479448A8C76D805C735B5378F3B1FE1CE
+:10A670003E35FEF827FF2A37C682C3B75319FD8639
+:10A6800082403F31EB5DB4FE75C2F4AB164EA2FAC8
+:10A69000F0C4EE1BEE45F3EDC6F9771C4135F972B7
+:10A6A000B29F8EDF103C5A8D6025E71E988478FF9C
+:10A6B000BCE6817B4B616A279550BB0B3E38B945A0
+:10A6C000A2768B799CD7B93E7913E5E9E5D81F616D
+:10A6D000743B077ACB06B0CB81752854C8B7137C7E
+:10A6E0007A3BD5B3E98B563209ED87E01617BC1FCC
+:10A6F000B7F9D38DA8970909D3EF3FB2A93753789B
+:10A700001366E7F6753B776E8776AF25337C10A22C
+:10A710008E0E16EBE484D54DCB23C5CF1B71F073A1
+:10A72000B1724AAC33DE380079FA7D6D95B353BA15
+:10A7300002ED1DF71D088F816A97BB1BD6539B1036
+:10A740005880EB3BFABAC5D2E6A7DD527B6511FE15
+:10A750000643FBAFF67F17ED99450BE58003CA7DF5
+:10A76000F81EC65B52E9D4A41450116F2CFC11E200
+:10A77000E781BA049F0C24513BDBFD4719DAD7CEA1
+:10A780004BF26D8172596F7E9B07EAEB6A2437F6B4
+:10A79000F7E2C229AE7E585FD226E827073B3B5E30
+:10A7A000533586901FE2AFD3099B30C0E20D22EAF9
+:10A7B000D3B6CD017930C1BBDFE204508F494BDB0A
+:10A7C000668779DED516CC72A742BBFB4E74DAAF32
+:10A7D00022242323D03B5B2524E1FE5335F651B0E0
+:10A7E000CE47797FDA279D8199A04F2D21BF04F5AF
+:10A7F00093EEB7CEB75E09F82F10FD676DC3FA254B
+:10A800007357ACDD0FF5756913E65BA1FFB2063136
+:10A810009F2BE65759E1FD4CD1BED481F3F5248935
+:10A8200032CCB79C105B7E74FED62C183F4D94CB77
+:10A83000E7CF816FDFAA68A9B242FF7BD2666D2B9A
+:10A84000721032ADA6C21D80F53C75FF92F94940E9
+:10A850003FFB09D029D4EFBB7FD97C9CBF47B6B062
+:10A86000FEB57A3ABFB2066D02D64BA4615B0DAC61
+:10A870007BBDBDFF0892EB864D9A3D037E49921841
+:10A880009DD86D2D815C80BBED404524974EA78BF4
+:10A89000D1675EA418F5D860B910CAC5BA72162B74
+:10A8A000EFDF42AE8F256F5BD299DCDB9F18BB5E7A
+:10A8B0004A63F218E046F549CA3112D81B43AF9CEF
+:10A8C0004875D276871389664F8BF2DBB5C0C3E536
+:10A8D000C097C4CEE629FA1942D75CEE10EDDA34FF
+:10A8E00094A70B399D16A812F577494B52782C3A4C
+:10A8F000D824625D8C2248B6D0F97A65E9FA5AE824
+:10A900002F239184F6C1D39B4E6819BE0FEC73467A
+:10A91000FB7B95B116A92E08EEC6FEAA33B34BDA1F
+:10A92000FDD17E60DE1DF6C986795BCBD3B07E514A
+:10A93000C9AD453A7816B175001DD0EF60981FCDAE
+:10A9400006BED8DF3B211FEDF7A7538D7C5DD65B9C
+:10A950006923F0FD92742E4F7CEC7B6F15933F03BF
+:10A96000B72685915F895D2D09EAECCEDC34068F30
+:10A97000AABB173E8CED9A7A6D2401DA6DDC5791F3
+:10A980004986D18B4D5FCE20E129BAB235A2A0DC39
+:10A9900069FA72167D5F75F7AB0AF229F6E38379DF
+:10A9A0006D74043255845B7B6CFC83434EE7DDF4AD
+:10A9B000652AD1A6E8DF333845FBF7D0FA0BAD2B7B
+:10A9C000DA9F4CC2E9C3F5A7D0FA41B85B39DC95F0
+:10A9D000D8F3ACE4F042785B74F575486F4E2AFD0D
+:10A9E000681CA5EF1B45DD28EFA3E36EA1FDEFB7C3
+:10A9F000021ED10EEC4DF4A15D5C6605F9E9C1FEC5
+:10AA0000D2DC9A14A50F411702AFFBD35A2AE87A79
+:10AA1000AF91DCDD31ECF8F9827F16327B2CB3216B
+:10AA200024AFD2D1BFE007E87F3FEFBFB49CF2CFA5
+:10AA3000BF327E00BE5981FC8B760BD2A11A295EF3
+:10AA4000E41A3AFF674076607BC02383FF35CE303F
+:10AA5000CE47C06D28FC732F80CFD1B4BEACF79029
+:10AA600082F4D614876F17A427D3EF328F4592D183
+:10AA7000AF7D8EDB1DFB7BA63866205F2CB41014E7
+:10AA800061B86EB457CB660AF9FDC42B95207F33AD
+:10AA90004519E5AD0FF130287F23767BB4FD550FC6
+:10AAA0003C31BF03E57302E0BF88DAA176A2F32749
+:10AAB00036A53139561E2231ED96DA7466B708781C
+:10AAC0007F6F5315F91DACEF502AE3CBF27E4D5A40
+:10AAD0005514E56BB39C7A98E3F141FEFCC7CB2992
+:10AAE000E90272AA96CB29F6FE3098F9D82E2323D4
+:10AAF000522C814E5CFDCA94B1E8CFDC9625FB3E1A
+:10AB000006BE5A2CA9A39E827EEBEC3E1A27137434
+:10AB10005247EC3E27C21D8CA6F312DA070E5AC626
+:10AB20001FB44B3EEB92181D125F4A5D717C3924B5
+:10AB3000E6715B9642C75BBD6D6C4A483F3FAE27EE
+:10AB4000AE4D883C450A86F2B928C3FCD75B645DEC
+:10AB5000BD93E9B33FB8024FA741F9288F43812243
+:10AB600003A72A3AFEAFB93E31DB4B8B93399FA046
+:10AB70007949F9D8429DD3CCCE8430619F68E8A74B
+:10AB800066F6303ACA6C88589A747470242D8F36E1
+:10AB90006A5806956077D5D8AB021FEBE4D8CB1284
+:10ABA000A9A7710412998A7CFA521A31CCA3410EDA
+:10ABB000E64968B76626A82867004F140E871DC4AB
+:10ABC000EA80715F8227E2AD5ABEF5059B07E94036
+:10ABD00052DB29F47772FB944450DF5C3B3B89DA0B
+:10ABE000ADE4DCED63305EE14D62740BFDD8793F7E
+:10ABF000764A275CEEFD66F4F86ED44F427E0A3C3E
+:10AC0000907332ED4FD41F966AF3DC503EECBDBC1E
+:10AC1000A45D32DA3F680F45EDA7DBB6CDB3A2BD28
+:10AC2000D313B1000BB5691BE7DF897638D84F0E17
+:10AC300058CF47694C0F1EF66B7232F63716D601A5
+:10AC4000AF8E24868A5A9C517C808D1342FC6528E5
+:10AC5000F07432FEC0675B3AE33397873D97F16744
+:10AC600046326B6FA6B79B787D00790F9EDB2B98E1
+:10AC70009C30B7FB6FCEBFEBED5A4D46BEDEBE0A31
+:10AC800012A4432B6176D65F39DE409F517855DDA3
+:10AC9000DD90827AF3F3DE2529A4282A476DF63762
+:10ACA000467F0C72244216FF33F2ABF2964CD05E14
+:10ACB000BECB067400ED94D4903B0D9EE949B1FDE6
+:10ACC000E6317C9DE9E85743BB7BB9DF63FB722229
+:10ACD000F5B733B87D969C5547E53AC2D207704E1A
+:10ACE00021039A5B87C794728BC17FB07D39897EBF
+:10ACF0007FF1F643491CFBA1D4603F8871CD76C437
+:10AD00007BAD5974FEE2FB15596F56135DFB95A49C
+:10AD1000FF2EEC6FE5C65C43BC289EFD319DC3074A
+:10AD2000ED052DE6BC14C3FBF7C05FD4F4E39F60D0
+:10AD3000E347C74D02868B8EFBD7B4C08C741A0FC5
+:10AD40009AE93E3E111E60C39F97A9DE61FA1A9EE2
+:10AD50003B9D542FD5A0DC167E12F2BF3B05F9BBFC
+:10AD6000A22ADDABD393FC3BB33C3AC8E31A07B944
+:10AD7000BE493926ECC6449F2445F5CE50BDC5EDED
+:10AD800062937CBC909D0D74ABE9ED8021FC92FE3A
+:10AD900055EDCB8238F431EE1F625F96CD0CC9C5FC
+:10ADA000283F6B2432161ED3E618F5FDB7D39D74E9
+:10ADB0005DDF0686D3FB2D8B1A8CED5AD399BFD25B
+:10ADC0008AEDBC1786A75E1F4932CA3DD65F33CADB
+:10ADD0001BC0B3FFD4EB8A0FE4F0F3DC1EDAE50905
+:10ADE0006C45BAE8484C9E847AA223717418E31229
+:10ADF0003BFFBBAA7027FAE9AFD9D46EECF600F39B
+:10AE0000F32B966F6CB7C27B5B8FE44E20D1793AFF
+:10AE100037498135404AF7737C3579D87A9A3C11A5
+:10AE2000650C8C9FD3C4E691D7F38264D5C9BBBCB3
+:10AE300046D6EEB1749B41FF8479F9F17411EF08A5
+:10AE4000B7559762FB8015F741727A241A1FCE69B5
+:10AE50000140003DE4A8AC7FA71A966E288AAEB7E1
+:10AE6000D3525B847AA2332349453D71CA137A12C7
+:10AE7000F9A8A92F1241704DEBEBB5A2BD67F506FD
+:10AE80007E807010EBF4C9EE1C94B3497D6C7E5D3E
+:10AE900026BA27E4BB3C3EDBCDE4AF4C5E268817E8
+:10AEA0009421305EC69642AAA744FB8C34AE37325A
+:10AEB00048E8696A67914E42F146E83A32B68CA397
+:10AEC000F6BEC06BD4AE1A3F19EDAA821D11EB6A13
+:10AED000B45B1F8B1DAF3FCCE50FAC2342E5C481B3
+:10AEE00091C565443B5B1CBF5AD07D524D6C7B15B0
+:10AEF0003401ADAF58EEB90ED7DDD4A19004290AC4
+:10AF00007FAB37F806CE27A767A784B031D3594760
+:10AF1000DA0FA55C58E7ED3713B74CE2CFBB699366
+:10AF20001C58A3E7E70E85E265A762DCDF137EC647
+:10AF300069AE8FCABDC1DFE1F8CD07EE5310CF3740
+:10AF4000EFFE50196E5F67A470931A99FFD2546F89
+:10AF50000FE37A2B965B291ED7752861944F4D7BA2
+:10AF6000F7452C68676F262AF27F53CFBE2339003E
+:10AF70009FDCA6C054D9A7F39F9BC212CE2703889B
+:10AF8000B1B788CA4D05F5B699BED14E467BE58866
+:10AF900083F1FFE90AA786F1B4D3B65013B63B9DFF
+:10AFA0009DA46AFE28DC5FDA37EF650958DCF5748A
+:10AFB00042049F9D96EE2C3BB4EB9CA0A8484F56B4
+:10AFC0006FC8EE8175A45983FBF1FB548F4B6D83E1
+:10AFD0006F7D096432D5D72384C334135D4CDBCC39
+:10AFE000F865BA2759D88193512EE57B5CC28EA2B1
+:10AFF000F2EA888DADA383B0F9B6A507323D48B714
+:10B00000EE343A6E4E5344423FC03C6E94AE02A3BF
+:10B010003CDE8B99678F82727E1D973715CB774BFD
+:10B02000BFD3D1419187EDCFE6ECDD29A17F08F5B3
+:10B030006DD51EDA9E24A0BCD9CBFCE27550BF565C
+:10B04000275FC43A62C89929383F675FEF8B4CCEBF
+:10B050004428FD89F99AF139DBC3ECBBB96026D0ED
+:10B06000F78A56E883FE8EE427D2FE04DF9BF9744C
+:10B07000B687D1794EFD6EC95244E382D49E14F353
+:10B0800013ED76792AAB3C140EBD140EEBEBAD2C10
+:10B09000DEC0E753AD04C7A05F56EB61FB5D87964A
+:10B0A000BDAFF443F9C19F1DA5F4B8BE4B0A507F54
+:10B0B000A1EBA8B204E376DAFF91314EBB80992868
+:10B0C000E4A19F1EA57A65C17E168F5FBF7F9FF5A5
+:10B0D0000667944EFDA70EAD443A5BDF93401C1209
+:10B0E000E28FADD74CA7206728DD134DA1FB5C2074
+:10B0F00027352A5749C88F7E8A90C36DE97C5FCE79
+:10B10000C9DEAFE1F316FD46E5A783D2BBFFD4E469
+:10B11000437680E77A5552C174023BDC47DB43FF3C
+:10B12000112A878144D15F13FD9BE1D7E5617A2D18
+:10B13000069E5B3C31F489D0B3FEC72B093E05FE69
+:10B14000AC1CEE83FADDA3D07E5B3D563A9F8E0A9F
+:10B1500016D7EEB0313DD2D1660F235FBF943AF7D8
+:10B160006509E4A52B4D89E0F3B0657513D61FCEB4
+:10B1700061F3E8B46C296C617A4CF350FC2513261A
+:10B180009F983C7AF0274C9E34694EEA3F3685EA18
+:10B19000D6D07D098F43C57D09127A5159E28AD2F2
+:10B1A0008319BFBEA75F507C50BFA087F141146ECA
+:10B1B0004C5F09BA053947F1DE26E2888037842BD7
+:10B1C000F8F56D187F107E7D72435073F986F26B2F
+:10B1D0003AF7EBA772BFDE566EFF9BFAF5EB36FD32
+:10B1E00007F5836EC97A853E05BF80FF68E0ABA78F
+:10B1F000B89F763F7FEEE7FCB9AEB487F2C3BA8F53
+:10B200005B281F396B983C71F619E52021F7F0F5A2
+:10B21000EF60F498D43317F725AAFF4D72B793F86F
+:10B22000F3BE496AF94FCC9321FB78FEC639B0F2E0
+:10B23000CB00AE0E0E03DEEE08E7FBD37B0011C899
+:10B2400097D61665387BF842FD92C89B12E27B1DAB
+:10B2500087F5E9BD5557FE1EE38C7B52683ECB2730
+:10B260007B17FFAFDFC3F7A777CF56514F7BDA834A
+:10B27000947E06BC0E15E3A7203E6B24A087B69EE5
+:10B280005F25CFC0FDB21F5D3119E5E67B7C9EA72F
+:10B290007E226F42F86CF9C18F6761FDBAB0948E5F
+:10B2A000F6E3E93DFFF657D48B8DBB37D0BCB4F63F
+:10B2B0001FFD92DAE596F04EF67E4F0AB5334FEE5B
+:10B2C000BA6F16C2BDBDA79DD69FDAB593960FFD86
+:10B2D000E0C7BFF80BDA1DC16415DB9DFAC97DDF3D
+:10B2E000F90BD2795DB28AEB680A59D97EAEA06FAC
+:10B2F000B3DCDAF702E553412F0B50EF229CEA99B9
+:10B30000FC11F4FC11DF6F5ACDF7B13EDAEE6A8C16
+:10B31000156794BC6CBD188BA172AC5EA271B64E61
+:10B32000A01A8C77742692727C261545945C186757
+:10B3300059C3BE59D4EED13EBC11DB2F3EE020DB19
+:10B34000695C0E83BAD17DB0621083C7C16F86DE9F
+:10B35000779F07BA7D1BE403D53B267F6071E72BFF
+:10B360007F46395A67EF7F0145A178DFC9E337D0BF
+:10B370009EEA9DB28DB1E3A40EAF93EB6DA6377339
+:10B38000F6D7E6F9A89C4850C7EAECD351C75AB69D
+:10B39000637A524E63EF5C5CC7D585ABA650BAC0EA
+:10B3A000F81FEA1FCD49FB5F8FF14BE0BF1C2F93C5
+:10B3B0009F196EE2990EE3575B89C7894F42DEB44D
+:10B3C0005139F204ED17EC0F6A57F97EB9EC09B464
+:10B3D000471EB285B2A7623F9D5C6FED66F386EFB4
+:10B3E000DDB88F0AFDB9A74FA6FDF4DAD2E8F71A47
+:10B3F000FB7EDEEE36293A5FA0D4D1A8B7B0BF52AB
+:10B4000027EA19AD9EE2C7A7D0759DC226D974DD83
+:10B4100093561447F9D71CF7417986FBC3E5DE8ABA
+:10B42000295E6FF429E2416678DE89F5D0CF33DEFC
+:10B43000007D923D467F3B9EBD7268D919A67F9FD5
+:10B44000FF90CA9B66A4631C3FF4B141FFDE20E875
+:10B45000F8D90F291DDF7080E9DFE603250AD2ED58
+:10B4600027AD01F23B30409B2B816E817E1F92FA0B
+:10B470006FA4F92ECF3ADC18D73BC3F5CDBA1D1F08
+:10B480001E97011EF907B2A99F7FE659473DF67343
+:10B49000D862A1F03CDC3D7167BBA49F27F30BC0D1
+:10B4A0000EA6A4DA0C762AB383D7DC877EDAFA46B6
+:10B4B000A222FF379BE8A7F9C0514A2FC20EF63FE0
+:10B4C000BE680DB33F1DAA03FDB839CC1E25608FA1
+:10B4D00062FBD439E13685D2574919D2D7A165BF6D
+:10B4E000D88A7ABC790E7163FF0F8D0A3C9B4BD7CB
+:10B4F0002311CC7379C8D6556985EF1FAAF6B90117
+:10B500009200B7DDD4EE25850AD7736BA8BDDC9C0D
+:10B51000F54D95F299591E3CDB46EDAE665F229DD6
+:10B52000CF8203D26DCC1E7112367F89D2E782F0B2
+:10B530008C30C6CFFEC8E127E078C6D6BB12E171D9
+:10B54000E6A7408850BF600EA3D7D4393D548EBCC7
+:10B55000F4EC3CAAC7055DBA9E49A0FA3CCDEA9638
+:10B5600054AAD71627E8F1DA65637A2995EB998210
+:10B570001D0CBF6D5EA697DABC16FE548CF117B792
+:10B580003609F5EE1F39FEA91841F9CEE5C9FA359D
+:10B5900011CA4F4D7B597F9E8440C9ED3AFAF5544C
+:10B5A00031BD28F603707FA03686BC7892CFC3FFEA
+:10B5B000F8EAFBD05EBE1AF08E2A25A790CB51A0E8
+:10B5C0000B845B4E6390D2C1D59E9B54CC4FF5A6A5
+:10B5D00013EA2F0EB4292456DCE7877C5DDEF46085
+:10B5E00029C6A1BD992E6AE778E50A8B03BF2B9186
+:10B5F000D46E1FDDF7A476DE80375BED36F07BB0CE
+:10B60000D402ED4E64B8189EC3BFB12E2A463EF454
+:10B61000097FDD60F70DF5BB99DDB8B04B9B847EEB
+:10B6200088D8D7107008B725D6EBE5670F976FE17C
+:10B63000F12C9E0AF6BD93C6B5DD300EFAF7DD3368
+:10B640007631FFBE9DB6FB9E97D947D5B03EB4DBA1
+:10B65000BC05C18D4C9FBAD458F028E77AE5D0B22A
+:10B660009525E85736D73955E4B7079F9756537A4B
+:10B67000C66021FADDA135140F04F080FC4042CCF5
+:10B680002F6D6E098663D37B2DE5BF66E43F89D2BB
+:10B690003B8DC303BD8719BD33FD27FC7F948FFA13
+:10B6A000BC432107847C6956FAC7211D0B7E689E26
+:10B6B000D53F0EE136527972C606FC8FFC0370400E
+:10B6C000FE11FCE27A8EF1C9F6365F05D66FAF2621
+:10B6D000EE769D3E32FB4B384FF43B855C3FE509EF
+:10B6E0007E8CF2B7D912D98AF915420E373FB76D61
+:10B6F0005CACFC372187ED5626DFECE1A470BB8EF5
+:10B70000BE70CFCF35993E693E4FD2A6D8F1912F6A
+:10B71000BC4E1EC71F59BE4406EA729437DD493439
+:10B72000AF5DC48BCCFD9EE4F426F022FC16DC77E2
+:10B73000C0F6E9198C5E940CC69F7919223E1B361F
+:10B74000F83D3E4BE843CC338AA7BFC4777FABF8C4
+:10B75000951847E85133FEC5BE09AEA7B6287EBB93
+:10B76000AE17987C32D3E3182E373EC4B5C2FF7FA4
+:10B77000E7FB5C43F1CBFA21A1F186BCB84ECBBE0E
+:10B78000C65871B0175A79BED463E3479477F7EF80
+:10B79000BCFDBD3C2F8CAC196FC8B372AABE368CF1
+:10B7A000A35E71D05722D371591CCB358B7C8A7A1A
+:10B7B00038B9BCAB10CF4D7883C6FD92CCFA44C3E8
+:10B7C0007E447628CD50CE6DCC31B41FD5926FA873
+:10B7D000BF6CD30443BD5F9B6C2817744E37B41FF6
+:10B7E000DB5569285FFEC8D586F6E3C38B0CE5ED13
+:10B7F0006D3DF58897897BAE337C7785B5DF520246
+:10B80000EF8B7B561BF3C74CF0ACFCAB1C930E6F5D
+:10B81000CAF0537C5D71C0088F9472233C305D0E7A
+:10B82000E19C42787F897F5687CB6F4D21D63FF5CB
+:10B830008BEFFD43E981D8DDA5FABC8428FD840D9A
+:10B84000798B9556D9340FED2BD15FBC798AFDB633
+:10B85000B8EB8803B7ED837CCFE062E3CB4A995520
+:10B860003F2C5C6C17820BE957470217F37EDF60B1
+:10B87000DCD9D4DF96A4669A27FC261674F6717F6D
+:10B88000ABF13CCC522D85E9A1E0E20BD8D12C0ED6
+:10B890001C4A60FB95E6FA57B85CFC03C084CE678F
+:10B8A000847CFD3EC7431FCF9F1FC2D79B3E3D9C5C
+:10B8B00089F2BB8650BFD9DDD2F629EAADEBAD11D6
+:10B8C0005202F37E90AFE7212E171E6975D37E1EBC
+:10B8D000E5FB918FB5FAE8FBC75B0BE933DCAAD235
+:10B8E000F7DDADE5F4B91BEC397C3ED95A439F7BBB
+:10B8F0005A83B4DD0F5BEBE9736F6B88CD6B08BEC9
+:10B900004819B57382E931E3A5AB347944782272E2
+:10B910005E4C7D19B71FB961D8FCF24D7DD28F5FA7
+:10B92000D4F1CDBB192E0FDDDF9C46A6E1FEE685E6
+:10B93000BEFFA295FCF8C5B123E723414FE45CFAB2
+:10B94000B8608CF85188E7553E9911FAAEE68C0F35
+:10B95000AF289DC586539DFD4C0E3AEB93D066D023
+:10B960007D2FCE9F88725D2825A6DDE0CD64F45939
+:10B970009FC0F6E3979BF8FB5BBCFE5B994CDFBD79
+:10B980001B47CE38332DC29FB7D1FDC1217C77EF45
+:10B9900055B1E0BB35D367E063F3B915733FEFDA18
+:10B9A000BA46A931F8EC42FD88F599BF5B9AC9E423
+:10B9B000D6C64CC2E4E4FF67FCF9EE5A17F51F1037
+:10B9C0006E5EDDFADF5D9B541F2B2EF39D4C1BF347
+:10B9D000B703A0B3D3A8A9AF29682B16121FDBF7B2
+:10B9E0001DE3C6F890C80B884FAF561A47A2309493
+:10B9F00087C215F0E1530AA07FEBE038112B8EA32C
+:10BA00005AA2FA0D736D88EEFC873C941EE07B4DC4
+:10BA1000A1793DFD3938BF8BA527223F3676B87D09
+:10BA2000BA21DF5FA49CB931F3EF2B67049F9373B6
+:10BA30000F8C8DA527EB51CE4C075193F9289333EA
+:10BA400017E8F762E1572FF7D3FDEB11C3EF8067DB
+:10BA50004471A92F1CC993D0B8DA6467CF3B139304
+:10BA6000BBF1F9856374982413F200CE13DA69955B
+:10BA7000849DDF7A5FF84D2DD3E8FE4A76F05F3281
+:10BA8000A17EB5C2FCC53319818732615D897C5FB7
+:10BA90003891EF0B2B99CA562C9340215DD7247017
+:10BAA00097316EB1D5E21B8DEBFA5852C7A3DFE296
+:10BAB000B684557C26934831CBCF0B87D05F4B9F04
+:10BAC00098E8437F37711C21BD343EAE3A308EA6D4
+:10BAD00024F5BF3E06FDDBE7AD345E3409F351A12A
+:10BAE0003CE97BB9618DCE3348E5453A87E376B4CE
+:10BAF000CBE1FBEF4BA1A770DE27DD76CD02F37A19
+:10BB0000A0738A230DDE47F6C89A9282F931A7EF17
+:10BB10005F00EBBDA257A671E72BC89457C6A09C47
+:10BB2000E9B5D1FDDF7556B203F9281E7C3FF95601
+:10BB3000EC3C30922519F2BBCCF51F703DF0499CCE
+:10BB40007CE3DF70392AF2676C227FC61B18367FD0
+:10BB5000C666CA9FB1598304F7856D83F9330D8496
+:10BB6000E6CF403FFAFC994F2A63CFE31D3E0FDB3F
+:10BB7000974971FA4DA6EF3FC91F7E9DB62F1D86CE
+:10BB80007CECE8F74EFA3E5EFECE001FFF9338F9DC
+:10BB90004BA707FBCF265ABAFE3B46CFD171F268BE
+:10BBA000BDCD940714AD67F93F1DA98C4E5EC872D8
+:10BBB0007B5641D7AB483F3DCF79BDD363C3785265
+:10BBC00090A8FBE8F91EAB6DA05FF0613EB6B37EB6
+:10BBD0008476B705242FDADDD76FB27DD4AF935BBF
+:10BBE000B5016399607B9D1C5E88316CE4A7098573
+:10BBF00034FFEF33E24B710F23471BEC72D0AA5B8B
+:10BC0000475F1C3BA2348BC1A72F3B36FC466559CE
+:10BC10000C79CB43BF4FE6E73ED839B4DBDDC3CB6D
+:10BC20004F846F285DDFBF190F1E5A7F21387BDBE1
+:10BC3000197F0F54482CCFFF6F0EEF549EEFC6CEE6
+:10BC40000FD84CF9EA0BB3CDF366F9EAF7A706CBA8
+:10BC5000B2D02EB3FAC6E9CF0BECB7069226C3B327
+:10BC60008FCB1D335C3667317BCFBCEEFD3CEF3EA6
+:10BC700051262DFB74F037AFB785E351B4EFB0B167
+:10BC8000FD2C147C76907B2B0893B3CBB2F2F93960
+:10BC900097542BE2AB81754156B88FD0FD2501E753
+:10BCA00021F0E37037C331487C2B31BFFB42F05C9D
+:10BCB00075345141B9BFD23E70187DD5FE5ECBDBE5
+:10BCC00063E0F9A173CCF1DD04F7E10A9F39443058
+:10BCD0003EA2B27C0A3287DA3D92962B9F9F387241
+:10BCE000BB676B72A810F9E26389C56B853EDA9A6F
+:10BCF000736A1CE6D7BF9F5651943D95C6DF03E992
+:10BD0000483F3F4F60F4F308F404E50DBF184FCFF0
+:10BD1000C12FC90E4DC8F646F3FB4860601CE623F0
+:10BD20005C2C7CE0C786F47321F8ACCD62FCDD9717
+:10BD30001C9B3E1EE37C7821BEA0E7CF4AFF7E7CA1
+:10BD400021E029F62FC4FC266433392C9E026EE6CE
+:10BD50003CA209D916DE8EE5112DC90E52389F1D61
+:10BD6000F5E97107CCBD4F897DAF434F1CFE30AF65
+:10BD70005FC0FBEF257FFB1263CFEFC5FFE1F91535
+:10BD8000E3FC008E7D9362CFEFDD11CE2F4806DEFF
+:10BD90004FFD3BE82FC07331F21DE918A072B12F9F
+:10BDA0002DF63CBF1CF13C43B6BF879E15F44DB445
+:10BDB000558D74DF3E2B31E6BEFD52F0A3D00F321D
+:10BDC000EFDF8B7D7A901F74BD75F68195E988F75A
+:10BDD000397CDD1924928AFB9ABF48A0FB0043E41A
+:10BDE0001AE77380978DC26BE1008D67F48D8B2D00
+:10BDF000176CD90C5E83ED3BD938F1CE1FB8387F74
+:10BE00005EE8FC01290DD1386085DD1991010FB77D
+:10BE1000717C28B9B7A868175664BD7A0CD709F0A9
+:10BE20003F3D084F5D5EDFA9D697DD636CF1E5F617
+:10BE30003AF9E9B29618EBF167847C280F06DBED3E
+:10BE400079C53D4687AF62D26F61E7A7072C06FF31
+:10BE500038935C947FFC3307E3E7F7D382541FA049
+:10BE60007E40BDB3F5B92B4B1099685F605ECF8003
+:10BE70002B91CAD1F69CE9853E1D3C2BB3855D29EB
+:10BE8000C7B117BFDEB980A8BD2419ECD668FF562C
+:10BE9000FA5EE0A7C2F9EB98F8F06704E6213C3FB0
+:10BEA0004F0BD4E03ACDF0D3EE9E994AFD6584DF86
+:10BEB000EC687F83F88F83E75B33028BB0BF89E93F
+:10BEC0003E16BF10F97C83710BABFBB83D0AEF91B6
+:10BED000E2E55EFC05FCD5DBB2032BB17F2581F3E7
+:10BEE0002371D2F3E3C25E2126BB8694B3FCD21544
+:10BEF00059AFFE19E33E5B9319CB6EFD8E83E6D9F5
+:10BF00005D2FB9155C37D81FEF7D1FDA8748E4BD78
+:10BF10006FD37D2D616724C9E793463E4FE1375FBC
+:10BF200028BFFA10DA61309F4A8B93EE731E02B27B
+:10BF3000C906B951A9B067C53CA02AE8AF52CE3BAB
+:10BF4000D80FF3FA9C9C4EBB0ABE4EE4F1C58D4758
+:10BF5000A73A902E2BADB6537AB9658E7BDC956DE2
+:10BF60008C7B7C4E16FE33DD0B2E64FEFF030B2B09
+:10BF700033F57197C1B8873897A6AD62F2D424E73C
+:10BF8000843CB3D8D93D2324407CEE0C1A3F627028
+:10BF900007E71AEFBDBA4A94D13981F24C8E2409D1
+:10BFA000BF87755FC59F6475280BE50CA6F3E07825
+:10BFB000E0F565E1B3FD4AD587CFD952D0CAE61185
+:10BFC00066F987A4250FDB5BECFD328E2FE214743B
+:10BFD0002619D88F1897955DBCDC51F7D9CAB5BE24
+:10BFE000A1F10CE27451BB57E1F33BE9766A165DAF
+:10BFF0009C23C1193949F356F9D31CEFB853D634F1
+:10C00000CCDB4E243D545E3A9D7FD410186EE296F0
+:10C01000B0FC7D29F433E4B7E34A17F1C3FBB33F27
+:10C02000FF8220FED2F16458013E8DFAC9EBDC4854
+:10C03000F3A1BD41AB492F8524E4A3CC7AF37BA3C4
+:10C04000BEB2933E7A6E488A04B3CEA75F388E1391
+:10C050002F7E63AB64A81FB899D9C36F27B2EFDFF7
+:10C060004E64DF1DE37AA6394D212CBE63B7A33D94
+:10C070007FC675028F6AA23EE9447D62B705285EDD
+:10C08000855E59BFFF5682786B3E504BE1F05B896D
+:10C09000ED8F6A2B249AC7B094E7DFD51791D702AA
+:10C0A00038B59C7CA6CF5E0EAD688272DDABA4383D
+:10C0B00002ED4A6607ABF15E97F662A26E8172BB33
+:10C0C00023F4D44F711D47D93D631BF8795AC0C47E
+:10C0D000BABDD0FFCEEB46A9DB714955035B314FAA
+:10C0E00068601B71635EC910FA3D07FC00F4B00B79
+:10C0F000CB30EF0D6B42FF7A07B4CF7E95A8B40D1D
+:10C10000AF471F05F12771BAC0F7B3E1FD064E47EF
+:10C11000050725B6BFEF61F77FD1CEF17E2E3BFB41
+:10C1200075C3C18A6BA7C2BC0A7AA750F21E03ED81
+:10C1300031FF093310587B6289D57E0CB6F7E17E5A
+:10C140003EC30FC951E8BD4984CBBF69263E9C114F
+:10C15000E5075A5FC2CB1BB89E32F00DF603FE7A9C
+:10C16000A08C6DF7D3EF3C8C3F54227E183F4F27B5
+:10C17000D11FECB72A3A0E95CB7378DDE1E5F36970
+:10C18000DEF7346BE405E4F719FC59C29FC8EF767B
+:10C1900080E3326BCB612FAC27751351DB709406B3
+:10C1A0005F3BF6574A8232C2B9CCBDAD1DE7776519
+:10C1B000C3D174A4AF753905949E66DAD502079091
+:10C1C000487BB9AABA0BF09E3189C26549BD3D8C46
+:10C1D000F96D4B06EFF909F99702FF2C0BB1BC661C
+:10C1E0002C37E8E2B522EF6F6902F8D531E4F7BAEF
+:10C1F0001C662789EF37F07329A2FEA61C96FF71F3
+:10C200004DCEDCD21C9A97C4F2A181FFA76159C818
+:10C21000151897E6AB2C26011BAE6B31E75FC1FF0B
+:10C220004B02B7537B7649D06897FE5662F8D69694
+:10C230004BD44E5C563FBCDD3A3747EC07E7B98F2D
+:10C240002745DF0BBA12F27C11EA7794C335A0CFF1
+:10C25000757673C39DE752E977994FAE3F7F59F4E6
+:10C260001CCC06D33998667E0E66C381365B06D237
+:10C270003B3F07B3E1E0875BF5F97F024E43CFC157
+:10C280000CD0BCC7A54AF8053C1FB4F4165823B41B
+:10C29000FF153F37F1229E9B981CA523D7758E086A
+:10C2A000CBAB0BD0FCBE3C77928AF9289D96C93463
+:10C2B0009FA833D9A5EAF377B6B7B554633B914746
+:10C2C00024CEBD2C8DB35F7C7B0EB3B71F92583E3E
+:10C2D00097B6DC4EE1ED95C931FDF97E6F4190E6F0
+:10C2E000D195E6F8447B1A5FC0BCD329F00C839942
+:10C2F000C6F0C5BE37CB07E8AF03FBAB2A5069FEDB
+:10C300004C550ACB43F3A6074B6E2B8AF65B77900E
+:10C31000E5EDD5053F3DC2F26F6B4B119EF1E4BADE
+:10C32000597F01FD75E6C488D3DF29879A91FE6C99
+:10C3300095C1E56BA1DFB3AF2934CF8E6C0E4836C3
+:10C3400068F79357DC2A9EBFEBA808D656D37A2B02
+:10C350003D1F98514F2209505FFAAAD28DF97D8D69
+:10C36000A44BC17E1A4D7AEC16E78B0AF2E92DBB7D
+:10C370006D51BA249897A816A0C06BDA3B242E42C0
+:10C38000E590904F667A26638C72A844C85D900F42
+:10C390002CAFAF81E93DF2A484F1A1B3AE1332F723
+:10C3A000AFA9DC9B2A849549DE4F3DF812B567049E
+:10C3B0003C6781BC403F4EC2F793D8116EBABFA50F
+:10C3C0004985986F3A8324527A1B6247F0F9950E9B
+:10C3D000CE9FD94D424E56943393D48C1F188FD292
+:10C3E000B9D8E79B8AF7FAC073061FFF0B4BA0284A
+:10C3F000E2477C91B005E0BC556AA17AC78EF99FEF
+:10C40000F0DC2E85A85CFC99A6C908D72B49CBE2A5
+:10C41000857E8AF72339543EF626211E8E2BAA1DCF
+:10C42000EBAB3151903E8DF89AE77CD08AF09A9729
+:10C4300065C68B6645F8CEF70DC1173D571088834A
+:10C44000AF80902BC42857FCE41C3BD7BCEDC81D23
+:10C45000E81F5FC83E793023D48FF2339E9D122FA0
+:10C460001FEF2497C723CDC73B6B637EC574D27F74
+:10C47000E35E69289D9C39BC49CED2D193A0D3E715
+:10C48000787EBEF44B9EEF5BEAA2FA2FAA2F191D0D
+:10C4900094F1D274A42F1D1D5C75C01191619D256E
+:10C4A000FCFBE9480F93A3FA326271FA947CC4BB97
+:10C4B000DA29CB43EDE48C341FC5FF144B80E27FB7
+:10C4C0002A51D3B9DDA9E4C2FACBED3DED561FC523
+:10C4D000FFF7D1BFA9203E8AFF0A93DEA972D65981
+:10C4E000914EAAEC663C0728FEABDD43DE5BBE0A3C
+:10C4F000FE2F43FC0BBD3202FB14F0EFCB1D669FF9
+:10C50000311EFEC7E73A795CE3E2F06FC6BB9003E9
+:10C51000FB1CEE2A27C6831B593EF294D7C6B46390
+:10C520003963BD9F9E93D997AAFE8AD6B7B0FAD237
+:10C53000DE808CF732166C847A28EFF307ABB0BC40
+:10C54000619344E5E8D43743ED581EB399D5976C11
+:10C5500069F915DE6FB64163DF3F77722BBDA72205
+:10C56000BC957F5FD15585E50D9DECFB3FB8EC1A7E
+:10C57000FAE565C7C2EDF87EFC0E360F61F7CDE631
+:10C58000F4B64F7AFA57F4BB2EF6DD4D47EC89CC62
+:10C590005F6276DC2CBECED98FB1757A7E77758DD1
+:10C5A0000FE0BE7640B351B961692AA372348E9F01
+:10C5B000562175E5E1731EC80942F10E749ACFF257
+:10C5C00055BB6188B5B9CC0E11799E986F5EABC32F
+:10C5D000D7DA5CA66F45BB8C34C2F2921F65F7CDEB
+:10C5E0008A3CD4C8C344C2F801AE91EADF3879A9C5
+:10C5F000F30A5AA83E9D7799C847EDB7AE86714BAE
+:10C60000CEFFDFB9B1FCF2263EEE099E3F2FDE37AA
+:10C6100086FD16F44FF621F1D0FB7F7EFE1ADA2D4F
+:10C62000FB701F5977FFC83E3F2BFFEFDC67EFE938
+:10C630000427F7264B8B554325305AA2F7A97CA334
+:10C640009744529287CE7F9E954458DE049BFF8D7F
+:10C65000ED4AF7769D1DBF44888F9963A95EA9E3D3
+:10C660007812726309C717F0793BF2C7527B0BB59A
+:10C670001B9713A6D76F26611ADFB8D9C4E7EB9CC6
+:10C680007F7ADF82F6F31E233FAF87E9B07DF58125
+:10C69000C7DF05F8373EE272A3FE5FDF636CD7F8B1
+:10C6A000C86BC798FD65E4F746C1EF6123BF8341BE
+:10C6B000C1F8FDE10974DF469C0B74D807DED7484A
+:10C6C00074BD837ADFC47F0E3C2758887E8D85E554
+:10C6D00027F2B218F7B32EA69735D0CBDC0FA222E3
+:10C6E000F7B3BE05340FBE44E8512E67043F977080
+:10C6F0003D3F448FD798FD9D07299F4CE125B3FE10
+:10C70000167A5B9C3F847EA9FE067DFD5A00E6DB1F
+:10C710006B718611DE51BD1DA67C34D90EF2DA4252
+:10C72000F1F73CCAE9A91C6FED5CAFC7F50F9C1B84
+:10C7300063FA07E06FD07D84A17E41C460EF9BF176
+:10C7400016CFFE1FC49B03ECA924F4F709E3E31CF6
+:10C7500032A2FC1090DBEFE40EA3B79543ECFDC0D2
+:10C760004E078D2F8838BBE0BFDFE4B1F8C277B346
+:10C7700003EF613F7D7CBC3EDE7FDFADF3E8BEF7BB
+:10C780009F4880EE7B631E536E8CBC0BDCF7EED0B3
+:10C79000C54BFB5263C7C13FE17260621E5BDF198C
+:10C7A0006FE034F2D50985C5D94F24F26732DBA793
+:10C7B000F82297C57B27E6B1A72B8FCB119EDF7D93
+:10C7C00022CD189F17ED52F8F3E3567BB043170FB5
+:10C7D000F73D9CD0827ACC5BC0F3E137323A3EFB26
+:10C7E0006CEA4EFDFD7039791513F3304FA420A08B
+:10C7F00064637CE659A62F9AADFD0ADEEB93E20D49
+:10C80000D9F2302EE32381A7B11F5FBFB218E07DBC
+:10C8100096EFF79FE5F7009D75B0A798574E5EED30
+:10C8200044FCEEECADFD546E0C966BFBA95CC8C9E4
+:10C830000BD271CF2E11F5BC7C0F2B13EE57567017
+:10C840003EA171E31871E2A17161E33D371B94D8F9
+:10C85000FBD424CF6588F7AE38C8E2902BED646B2B
+:10C860002ED45F7F3093FA1B8DC9DA38A487AF1BB3
+:10C87000C73D3BAA97AE6B7BC5C0E8474BE9BE30CE
+:10C880008D17AD3FF812957FEB05DFEC37F2CDB495
+:10C89000BC91EDA798E3EC23E0A78ABC61ECA0670C
+:10C8A000507FD9A278B88DE75155CB4D551857FA1E
+:10C8B0006C0DA1E76B6F7B45A67475DB5312BD6FE2
+:10C8C00042D871EB399CE3AD0BCF27F8747205CFDA
+:10C8D00027F8747E1D9E4FD097F17C82BE3D9E4FFF
+:10C8E000D0D7E3F9047D3D9E4FD0974BC80DED188E
+:10C8F000A7DBD049DC611F3BAFA0FF1ECF2BE8CBED
+:10C90000785E41FF3D9E57D0973F230C6E9F3D269A
+:10C91000D3F83F9E5BD07F7FD32B3F298BE0B21DA6
+:10C920002C3FADDD01F0473AD402BD45009F351CD8
+:10C930003E78AE41DFEF27C9735F46FCACE9BD71BD
+:10C94000213EAF38708BA15FD2C5E4710BFC433838
+:10C95000DE488229E8CF4D26034730DED11C9654AD
+:10C960001CF7A6478C727BF01E93B0F1FD3AA28BA8
+:10C97000FFFA87C6FD3BF25C9EE32CB739471FEFF9
+:10C9800089D283538D201CDE94D558F450422E4F0B
+:10C99000A1719E97658C61903F909687664ABAFD1B
+:10C9A00001133C12B28C74E1F019E922A9D04817A6
+:10C9B0002ED5481729E546BA480D4C1816BEE9355C
+:10C9C000463A59273751BE17702E877F08E7C97836
+:10C9D0003325C217D689F162337C1B0FDEB715ED04
+:10C9E000FE8B856F4F1EDF57E1F0FD9CCCAC72FAD9
+:10C9F00068759DBD2C6AC794BEDC423781CDF1536A
+:10CA000001476147883828E87F6A4F47FD7AE6EF9B
+:10CA1000817DF04B94C3C715E6E72125A1DC5C4B73
+:10CA200042543EAD35D90737391F54D03E18B25E57
+:10CA3000B0CCF0DE42F37AD1DE22BAB894D93E907F
+:10CA40000E4A11D7245CEE4121A743E7A931149087
+:10CA50004622377EE40ABC85720B1D457B99216E08
+:10CA60001CD3EE13F3107011E3279016390BE9B9BC
+:10CA7000D06C9F19FD6BE18F8B78BB886B0B7F5A55
+:10CA8000F8316638CB97F9DB91FEA7B8851FDDFB3F
+:10CA90004D7C2FFC67B3DF3A781E00218BE76D7861
+:10CAA0009CFE6EEF6A3BBB8F8FF19D78BFD5B3289C
+:10CAB00065B83CCCBB5A8DE75F60198161CF13210B
+:10CAC000C83270DF89605085ECB8E6483FDEB1B30C
+:10CAD000E31BBF1E78119EDB8B9FECDF8275E7CED8
+:10CAE000CB08D7C1783E61E78315FE9D92B7F55616
+:10CAF000D4A389AA957CA4A30B3B68AA8F0AF9B892
+:10CB0000A827B206EB7FA3DFD7FF473DBF0BF0F9A5
+:10CB100068EC30F58ADA1833AFD6042F710D86A38E
+:10CB200068EE49B44F1C44B76EAA0F7565390A2FD9
+:10CB3000AA5A657A5E4AD407F0DE92AFBB2EC4FBD8
+:10CB400047367D3972F4639B7EFE619657600D1205
+:10CB5000CCBB553C50AFD72F8374080C55A65BDF78
+:10CB600008D6854C83EE27B34B18BEFF56EBEA3050
+:10CB7000E10BFB0D665CD2F3D32EF1F9452E71FC6F
+:10CB800092DA4B1B7E81DA4B1B7EDA253EBFC8252D
+:10CB90008E5FB2E8D29E5F60D1A58D5FED129F5F80
+:10CBA000E412C72F597C69C32FB0F8D2869F7689CB
+:10CBB000CF2F7269E357A376A0B33C42F05E095FC2
+:10CBC0000751FD3E3059E135FAF3052AA1791A845F
+:10CBD000FB25F9DC2FB96F474B3DBA50BB34C54735
+:10CBE000E341E0DF6741FD78C2EA77752EA271D696
+:10CBF000B651E372F09E2A67E7DC93786E6FBCC68D
+:10CC0000FC71F3DF0BAB0D18FFEEDAB5E5E986F248
+:10CC1000D45EE3BD15DF6C2C30D42F0F4D34FDDD19
+:10CC2000BC29C6BF47169C61BA7FE156A23F0F9947
+:10CC30004F222AC657F2EFB154E2BE99157DE62B7A
+:10CC4000E1FF6E857E17807F7AFF251F3CA1C1FE24
+:10CC5000FD0837C5D0BFD3547FB1E74F9F19CDE34F
+:10CC600031A6F3A7042F978C71DEDC9C8749AC3783
+:10CC7000D3F89CC0D7DDDB2CD4E5FD7C07A1F73BC6
+:10CC800056857D167AFF39C7DB444E7A62DDE15660
+:10CC9000E339F47C8D54223E0B3A8805E36BFEDDCC
+:10CCA000440D101A17A274B24B8B4D27BB88BB12D0
+:10CCB000EFE3DA1526F4EF6309BAB8DBE6CBC17D02
+:10CCC000B5899D8C1E049DF8904E92312FC87CDF53
+:10CCD00080195F647204E6BA6B477E9A3E1F95EC3A
+:10CCE0006570B7C3BFE1F055B8DB882F1FD195BF82
+:10CCF00002BE4E7F4D7C299E6024C583F14CE2C369
+:10CD00003CA9C3A3C659101EFE4E95FAFF35D00CA0
+:10CD1000E1ECEF64F7A8093C89FE76B492C81C9D4B
+:10CD2000FFE75723018473B55C5489F9E73B4B69EE
+:10CD3000C878087E76127722C6BD77765A12E9DD6A
+:10CD4000D407002FC584FCD7B6A5298550DFED2771
+:10CD50008978BF56779B85DE57D6FDAC546FBC4FA4
+:10CD6000399260C9A2EB48B094D3A7953D03FC4922
+:10CD7000ACAC3E226379F4E621F77DC8589F5A6334
+:10CD8000FA7B812420617BEB652C8F332560BCC747
+:10CD9000C6566E940700C6DEAC328CB7707AE7F7E1
+:10CDA000A386AB4918FFCED7655CEE98E928F5AEAF
+:10CDB000459498DA467D8BCAB3EE3685C2DFC6E568
+:10CDC00015D9CCE842837F484FA9263A72A9463A42
+:10CDD000B2C979340F57F095988F18BF6D5446A299
+:10CDE00095CECB4AEFC1B699E584697E4E0C06021A
+:10CDF000EE9C1E120E43BD4D63FC41E43EFADE364E
+:10CE00008D9074FF5798E7D7944F575F16FB7CFCC3
+:10CE1000C5CA2717EFF3EEA96C9D9FABEC3EEBAABA
+:10CE20000E46EFAE1D8CDEF12437CBD70A2CCCD6C4
+:10CE3000EDABEEE772CA0C37576FA00AE979AEFC8A
+:10CE40006A00F323EE7993D17FDBA8B75FC6F28E39
+:10CE50007B18FCFD2AC333D08B1A81A9DF7397930B
+:10CE6000E6054F29057C21FE5F35CA93A9BD4638EA
+:10CE70001698E4863F0E5CCDFC1A0FAE7708B89684
+:10CE8000015C0B2E1EAE8AC6E473EA4C76BFE2E16B
+:10CE9000510AFBBBBC1A83636A40A5F277AE7C2EB5
+:10CEA0009202EDEE0B80BC8179D60418BCDD33858F
+:10CEB0001C37C253C81701FF7C0E7FB7EA7E05FFFF
+:10CEC000BE8B53B3129F84F0FDAF00DA115D538522
+:10CED000BC192088B79400A35B01E7AEAB189CF3A4
+:10CEE000031CCE9D1C6E129110CE667A35CBE79452
+:10CEF000AF09E76E01E70C52F655E07C5F12BB3FCD
+:10CF0000D93686C1D5E61C88A09CEDF45BE9BA5EF3
+:10CF1000F02BB4BEB398D53F9CB4320BF56DA77718
+:10CF20006B16D2659BFFC62C94EF8E2C2E6748C0E3
+:10CF3000995D163D77502DEFA0F78F6EF529143FC0
+:10CF40002E5F6CF995323364A7E31459894CE1F0F4
+:10CF5000981A0B0EF652C5202F731B8DF04D32C15F
+:10CF6000D7F135E5C37F7E4DF9803947D8EEEEB174
+:10CF7000E27E862E3BD54FE5B7D0B879011F6BDB3B
+:10CF80008EFBD97BAED774EF6BF2519E38AD2AC2BF
+:10CF900033DEBC859DF338BF0FE67E7E9F4B17BF07
+:10CFA000CFE55E7E9FCB0E7E9FCB76BCCF059E9D50
+:10CFB000789FCBE5684F07E853BE278DDE3BF839F5
+:10CFC00026B0FBF1DE9C3324D6FD247ECDA8FF2EB7
+:10CFD000DB64BC9F2CBDC6A8E75203463D87FB5EC1
+:10CFE000FA7A976ABCAF2DA9D0785F9BC367BCAFB4
+:10CFF0006DCF6521D907F0FD7FB1B1C61E0080005D
+:10D00000000000001F8B080000000000000BDD7D09
+:10D0100009785445B670DDBEB73B9DA4BBD3095912
+:10D0200081849B950E84D040C0A0416F16302A8326
+:10D030009D088A8A1A013140481075CC3C9D97861C
+:10D0400004081830A0A8332E34EBE0B845272A2A6C
+:10D05000321D04069FBEA1595474D4BF757C0AC802
+:10D06000480417FC9ECBAB73AA6EF7BD371D088A28
+:10D07000FFE77BF1934ADDDACF56E79C3A55313B27
+:10D08000CB88DF4AF0E747F8C7DB4D3C76CC9A48BF
+:10D090003221D9BC6CBCF8B0355840C8B2B6EA38B9
+:10D0A0005200F594402A2D8F85429990A566777F8E
+:10D0B0000FFD1EDB366B227110B2B88910FF604283
+:10D0C0005A9BAC982E4CB7B8FD89846C7853744742
+:10D0D000D12616C5A33869FDAEF42584D0EFCB9CCC
+:10D0E00084A464D2EFCEF984641122D101049A970A
+:10D0F000DA261C2185B4C1D4B9848C09CF67599B29
+:10D10000C9ED2F22242ADEE686F14981F45190965A
+:10D1100039E97F3FD2F63FC2CF45E1348AB0725C35
+:10D12000278C236BF204C6D39737BE273CBD5353DD
+:10D130003E58B6277E028B3D8F9CF7A34853715A09
+:10D140005C8D8DA6AD09848CED39DE374DE4E99D0B
+:10D15000B90850429220AD25004F89F7B934BEDAA4
+:10D160004A6C6138ABDF173B197CA30412B1DF16A0
+:10D17000806B54382F11A274003E061645ACAFA642
+:10D180001403848C26A4ADC9BFEF6373F8BBAD84D0
+:10D19000B6B7F5AC5F298B38EF29B28CED6C929F56
+:10D1A00038693DBB9BB6D7C0C5A69CDDF8F4A7285F
+:10D1B00091AED7C1E9863C214880572BCFC70A35AD
+:10D1C00053E424C09787229BD62B56484D011B4F12
+:10D1D00051DB09904AE42357185FF0E3A4E50CA45F
+:10D1E00090D272ABBE5C4E467861BF52B8BDF2A31E
+:10D1F000D0FBBC7FA914F0F851EE69CA2DEE5AE0BD
+:10D2000027E3F77F974D2A1CBB1329DC44BEDE08B9
+:10D2100070FC772D1C451B83638B90B93548F9CD85
+:10D22000AC38DC1423A43451EE00BE6C516CC897AA
+:10D230002D891D81329A3F5964724357F6DC32E4DE
+:10D24000C796FEBB0FCD04B84EDA737823424D0962
+:10D2500054A8F0A5E5765765A042C50709E32B86DB
+:10D26000FFBE7CD8E6E0229AF6BB7C1A715252B11E
+:10D27000A5588848F1129D5B61ADB185F163815F6E
+:10D28000E8F798C4094744CAF7316E0D1EE1FF1F45
+:10D29000591EE141176F19B8E41601882235546F01
+:10D2A0002FCC47923DE1F991738F2F329002298D57
+:10D2B000A6923B15E4654F7AF732BEE7F57AE70BA5
+:10D2C000566FBC3831F5460A97D637A87C04BE7035
+:10D2D00031B960B6327CB61225F546DA55EB40C955
+:10D2E000ED857CE274941F4B52AB5B417E7E95686A
+:10D2F00022A200DF1759417EC0EFDA71933C26E28B
+:10D30000D7E027656A8C4EEEB7CAD528CF7A9B67DF
+:10D310005A8DBEFD805A7DFBF4F909BABCDA2E3A6B
+:10D32000F5B20315FDC2F96592C70A726471E26A2B
+:10D33000A14643DFF1F93507E5D1E1BC397512B6F5
+:10D340008B4A2F8A382FBF4B3904F5E9FA991CB65E
+:10D350002546943FF7F17DE87EBE0F9D699D0FF253
+:10D36000FA7FE4F51F6E72621AC267CE6C1D5E967C
+:10D370002651794DFBDB0C5534E33F23D71C07FEC8
+:10D380000BE3D914860F306DC11C13F0ABDA4F4B91
+:10D39000D274C49BBA9EDEE6D7CAE5BF5ACF2A79BB
+:10D3A00089BB00F91EE57008EEB21E5F05995C6E40
+:10D3B0006C9CAD1B7767FC84A99994EE961C14496C
+:10D3C00014CA11FDFA7AD2AB7E1D4B12D9FA7BA793
+:10D3D0006FC3BAA94408CD0BF309867C7F43FD2CAB
+:10D3E00043F91043F94843FE7C43FD3243FE524368
+:10D3F000FD6A43FE1A43FDE986F23986F20586FC92
+:10D40000BFE9EB17313CDFAE7E3B8D7C01BC1AEBF4
+:10D410004B9282F8950CF8353BF5F82D4D2F3D3F9A
+:10D4200013F7855A1D7E55FAEC2B7E96521917007C
+:10D430007E926A987E523C8768E961496216EE1FC7
+:10D44000622971B3564C4E5978B998C6C6A3FA9A58
+:10D450008E8EBAD267A1FE481E4C6072F30C742106
+:10D4600090047DB9D23F5C9E05FF9E5BBA38331DA8
+:10D47000FBF8BE7BFA79AB7277CB20CFBC4C901710
+:10D480003EAA4F0F0BC3490EE9D37430CA77EB1392
+:10D49000892F8AEE77EBBD26CC7F954A07027DA5C2
+:10D4A00062B64EFF262428403F4639B00AE4144DA8
+:10D4B000EF013945D3BB9B52315DBAC2943613FAA2
+:10D4C0009B6841FDB8DFF0255E09D2B2E27CD8BF8F
+:10D4D000EF1EB64531D1BCFD9448FCA3A8BE5078E0
+:10D4E0004D312C2776FCF4D49D30DC77749C31C010
+:10D4F0009D04958C7515C4671E4EC88A1D6997BA20
+:10D5000068BF728EE48E86B202F7422911EB79C1B0
+:10D510006C90A5EE3DD9343F28C784FA85B9B8BBD5
+:10D5200009F47775DE2B2EA5844B2B6656BA4D5E1B
+:10D530000A823B07D5DC0B701AD4464C0ACDCB5E71
+:10D540005900B9F666A68CF0DEF02265C86C18A802
+:10D550003B0DF6D9AF575816C13C7BC713114DC5CB
+:10D560003F3D55FB413DB33F7E57402ECB129210BD
+:10D570005DE57FB52B346F1359FE95CC239E459AFC
+:10D58000FCE399479C906F1B9561827564263A1461
+:10D590005F04BADA0FF298AE7BC38A5983B4FBA05A
+:10D5A000319527D27E53685AC053A0B5F300FE3C94
+:10D5B00095F9F754967F0DE046FB951B7979224B40
+:10D5C000CFF538C6FE0F643A55BDB43FB71F0B6C9C
+:10D5D000C9A7D54FF783BC32EAA754D0F5073A5F05
+:10D5E0004BED4913ED7BED0A0BF1529E5A9B4ED049
+:10D5F0004EF42EB3F836017F4872FF2B357A976FC1
+:10D6000059F23580179F40A66AE5E4FD1CCE2BB386
+:10D6100004AE671DF38A947ED7D26D13C4ED5AE22F
+:10D620008C067D24846FEF098FA2C1F78559A5ABC5
+:10D63000BC30AF996CDFCC0AC9B3BC8512ED671D55
+:10D64000F443F3EB5A4D38BFB5DB28FFD2A1BEBA85
+:10D65000EB2313E8CDC388DF04EB1B4A7C98BAC8E0
+:10D660007C1300A583EB191B39FFE651FE467B07AF
+:10D67000441F2DF70CAAF91AF8228EC89897BD4EB0
+:10D68000A4A7FA6DF16591F4039265E27626A99557
+:10D69000C6703B87C199648DEE097F33998F70BF47
+:10D6A000DDE53141B96DEB3EFF005AF4DCDB7ABABF
+:10D6B00005A8546BE44E0A1F27CEED5144DACFB6CD
+:10D6C0008C9A58685F5FFBC5EE64E8DAEBC5F6A399
+:10D6D000B29C58EF1A7FC778E866B83B5806B4305A
+:10D6E000ACB26B0790CC50651D9819C4557CCB8E9D
+:10D6F0007E32CCA326318BD6CF0B044B817C6CB50C
+:10D70000FBFCC9389F0B4D4017D9301F4E1F5548A1
+:10D710005F32D2898A6FA0872A9ABFA68EC1875AA4
+:10D7200083584E24A76EFEEB17533AB1F5A4137B32
+:10D7300016D38F866485EC2B623EBD7D35242B820B
+:10D740007DA5C2A5BAD36D067781E709E762B081EE
+:10D7500026F9BA7746D3EF8B326A4640BBA2073D23
+:10D76000CD407FB66D012FD453E1642B092802D63A
+:10D77000538A00AE6BEF2A2BC37DA19DA0BDD49B25
+:10D780009E6B2E31E9FD38A41DD791DBAED7D3298E
+:10D790001DE37EDE838EEF0AD1718CD62FA1EE3F82
+:10D7A000BE36538C0BEC0C6A7F605FBDC891CD7C9C
+:10D7B0005F52E95AFD9E4322FB19A686E19D2A9EEF
+:10D7C0001EDE5323C1DB01FC918DFC320DCA9DA4EA
+:10D7D0001BCB07DDA5E797FAAD5FEC1E40E76F2B8B
+:10D7E0009247027ED4F167717AA6743C13E9F8C1BE
+:10D7F000EEDDB0AF0DBA8BD1F13CD03592C2F478EA
+:10D80000BB4BB919C651E9CCB89E9B787F8B323C93
+:10D81000F3B0DE831DBBA2B19DA701F2B60703FEE4
+:10D82000681286EF200EDFA8DF87F0EC04F9513D87
+:10D83000D1BD0BF6678FCB391ED24972770BA81674
+:10D84000D7D68A3ABDCF885F4A5FBF877514114F1C
+:10D85000B9208036DB61C6FDB317BA09EF9B5E5570
+:10D860007EDC7506B9BD2C121EFADAFF890C4F3B1F
+:10D87000B44FA8F490D3D96D3DE6D5C77AAADF2C72
+:10D88000ACC7FA747AAC4AF7CB5BABD1DE52F1A0ED
+:10D890007E5FDC5A5D9909746E93DC91EC9FD07EBB
+:10D8A000C3E9FC514EE7ABB9FED5CEF5AF954D328D
+:10D8B000CAF7B62617A6CB9BDCDC1F5A8CE9E226FA
+:10D8C00005EB89CB4E94A2FD7E1741BFD6A2D8426C
+:10D8D00021125D657AF5FAFEA0463DDEFB55EAEDC4
+:10D8E000EF78ADBE4CFF8F2BCED295DBDD4374E5D8
+:10D8F000B1AE91BA7CB47CBEAEFE964135AF015D4F
+:10D900005912CB74F548F00B9D7EABC271BC380D3B
+:10D91000F57D0A4F660F707D562D27A48668ED149D
+:10D92000759D6D063D7639C011E1CBE0D80E70448F
+:10D93000F81673785632BB89DB3D31AADD93BF7A86
+:10D94000EAF444D4A7515E2D4CB7E0FEBC3C93E909
+:10D95000DB3DE82755233F29CF2F5DC6F673551FC2
+:10D96000DF95FE5625E8B5EB534D2827D727EE70F7
+:10D970006DC07C8C9BEDA7DE7617C59FD9C5FDD504
+:10D980009462D3E87AED9C6F969A09FABF9727D9EB
+:10D99000DCE007B3BB664DC47A867109B98568EDD2
+:10D9A0003FF271AD4EEF20D26CDD3A43F32FB2B0AF
+:10D9B0007E0422403F0905161DFEAC4493CF84F936
+:10D9C0005AC278CC84F5723C19F41CA39F421DCF37
+:10D9D0003951BFDF2CCD67EDBBD23723DE8DF0751B
+:10D9E00054E8E97739A78B96A4F5C887C6FAC6FE2E
+:10D9F00049498CCEFE5BEE3ABD9F44B5A7D57A600F
+:10DA0000473B23D437DAD1E7C25E77E278FAFD2EBE
+:10DA100082BDEECED6F893547887F0A0FA17B91DE0
+:10DA2000A6FAADD5FE24C2FAC33CFAB7BD28FF1E44
+:10DA30008875A01D9963B3F84016E6D079001DB72C
+:10DA4000FC21D6B788E657C54EEA8EA3F99C8DA275
+:10DA50008CE5360F9EDB74AD99D03F48C77D48A852
+:10DA6000199FADF1C36D8CFF6D2AD307A48F822E51
+:10DA7000607201ED5CEFAA510105F4F17CE2DE4435
+:10DA8000C00A66E52A3D116D5EEC99FF3C9BEDFBFB
+:10DA9000A9D792F91D11F0DF9CCDF6D1B01CF7C4C7
+:10DAA000A0BCE6723C87C36B537B758C568E6BBEF5
+:10DAB000C745A2AB7325BF5B407E0F8671F62BB8BE
+:10DAC0006F17112EBF9F22BF46F93D27B36621D0A5
+:10DAD0009BD978DE2705517E0F939545501E07F69A
+:10DAE0001EE0E5068A9708EB7881E3EDD78A177583
+:10DAF0005FDDD4FE2CC34B818A97952492FDFB2BCE
+:10DB0000C04B27C0BDC7BE4A82780EDB3D50790EA0
+:10DB1000F8F11959791ED2107EAE8ACC379FFEC219
+:10DB2000F87994DBADAB397EDAB97F7C25C74F1B22
+:10DB3000DFAF9773FCB4F2FD7A09E027EAECF966EF
+:10DB400050A31E3FFD2A630CF8D0E327AE588F1F69
+:10DB5000BB5B8F9F58D710033EF4F889CB91991E79
+:10DB600099AAC7530FBE3983BDE2807E22F83706DB
+:10DB7000D6044AE18CABFFD48E2E3374E2692F8534
+:10DB8000545DEFC306BB544DE372983C4C2D8F8C13
+:10DB9000F7EF38DEFF98A5FCB78E8F2F8ECCC7A687
+:10DBA0001C56FF13591172B4747559E4FA565EFF8E
+:10DBB000E020252A47D33FFDB94F3C8DBD605C7FF7
+:10DBC000ACA0C4E5E03AE4AD418AFB8D0BD939E461
+:10DBD000C668B903CEF3BD0B6DEE4D32F6E4B182EB
+:10DBE0007DC4FB21DE38EC37830F33C8B6E75B38E2
+:10DBF000F7CB9C31B0FFCDB43C7341EAD11A9AE621
+:10DC0000E464239CB26ADD3B00CEA2636A7F767E29
+:10DC10003CCDF9C9504A6AFE7EC28F60703B13FA50
+:10DC2000742E47E520EA817422BE4D944EA324222F
+:10DC3000D91360BD0AAECB0C7AAC08EB6DC77C0C77
+:10DC4000E9C0D44602ECFC9ADBA3A37332115E4E0A
+:10DC5000E2447B3581B83155F9D89A48A4A491D8CB
+:10DC60007F4BD448821BFE0560AFDA06AE5B0E36F2
+:10DC70008D42A130065905E121DCB71BD74F5C442A
+:10DC800066FEB6BB9C189FF01A5DDFD0BEAFAFAF8B
+:10DC9000F5BE8976149238421AAD2CBD23C6B11E4A
+:10DCA000D26FA2337CE0B43A3FBBE63780576F199E
+:10DCB00041FDC3FB41ACAF19273BFF3C661FF4B9E4
+:10DCC0009F2BCF513F379CA37E6A813FCED4CFDDBF
+:10DCD000F0EB5838C7F4D4C1B82DF16350EF54536A
+:10DCE000235CFD2E653EF42B590F647CDC2FACB712
+:10DCF000D9DE13506F6B11FC04FC94DE0F05D4AF1A
+:10DD00004801C3934D26AECCE1E17E6CEEF98398D9
+:10DD1000BF8BF97B16BE7FC760D0BF1F889D148C58
+:10DD2000A3ED37ECA37A1EC4D194BBDFADA5F49468
+:10DD3000D4CFE25E4FE9A71FB793A3568CD95B4BB4
+:10DD40007FFD6C30932F5B9AF6385BA840B24BEEA8
+:10DD50004B46D276367E7E4BC48941D01BED632480
+:10DD600019CE38F2457F25CC97349808F0C5437515
+:10DD7000FAF3DC2579F9D89F9A1FC0CF734991D463
+:10DD80001D8AB3A17AFCEA1C1E57E3200ED00BA516
+:10DD90001F94B848710F6AAACEAF2891EE5B71E06C
+:10DDA00017A49C42D3A2363F067F94B9FD56D06398
+:10DDB000D7F888D742E1F4D874CF6CE8AFADD81368
+:10DDC0000B7AF99A83D5970DA3F30E04253780E0DB
+:10DDD000A5C10938CF8022AE88A5DFB7BE6772C261
+:10DDE000FA36F0F66D1E01F9FFA169C4E7A5F0D877
+:10DDF00050B7C32A82DE1B30915CD473A9C135862B
+:10DE0000BB4E64F0D732BEBF6370127EEC0C2C8820
+:10DE100007B8AC8ABD30A0D0FEAB2A99DF79823832
+:10DE20007017F41B68B3207E9278FC9140AA507F53
+:10DE30004E98A6D197E9FF761E0715B88D60DC5382
+:10DE4000DC681BC6013C1764E7460F5532BFB3833D
+:10DE5000F871FC09E2B66813FDDE592939819EE2AA
+:10DE60000CFAB90DFAA324D7F920EBCF3182F5676C
+:10DE700037C44159D57939E9BC28FE44BB8478764A
+:10DE800056EAE3A71C867636C3787B01CF20970637
+:10DE9000923CC0F349CF6F471DC052B71C297EA2E8
+:10DEA000AD89042A34F116B65EFC875FE431BAB559
+:10DEB000A4EDB4C2BC4E7ADE4A0477D71BDFEFFE76
+:10DEC000F81E487FF88FCE06BAAEFFFCF6D0C6A784
+:10DED000018E8D77EF473AE476550A4C81CE67572D
+:10DEE0009505E1385A61FE0152D4B5D35C84E578DA
+:10DEF000AEB5624734960F2826BE680ACF019292CB
+:10DF00007613F06B40742F94A113C5963686B0A398
+:10DF10002A9A5F713D251C2A1F92A629229C1F8CDC
+:10DF200017DF20768AEF358A20B3F8376117F05370
+:10DF30007A85807658FA414F34D0C3C9C9268C7F80
+:10DF4000595875E525B9B4FF474A25F43754569416
+:10DF50005E0DE5030E327A71DCC6F047E1E4AFA056
+:10DF6000FC907D90F9138A48D0EDA7E503DCC49CB2
+:10DF700008FBC7340A60985F1BC70FF70F1415051D
+:10DF8000BC0054BB5B8F47A7018F46BC5A73391E38
+:10DF9000F3493EB3EB98FE58C5EBACA91885F6EBF8
+:10DFA0004332F19A87F7C4D77EAA3F2A54FF0B5019
+:10DFB000FD11D2BF53FD11D24EAA3F426A574A2FDC
+:10DFC0002BA2F30D24D17E81FF268E5E04E7038F02
+:10DFD0008CBBF9CE7FD174343F67A3949F5046E148
+:10DFE0005A0D5CCCF2AB15BA671E281275F915896B
+:10DFF000927A8EE7853DD59E66E2E73CE5F7427969
+:10E000005BAAC4CFF5583EBB80E8F29D134DBAFC25
+:10E01000053B34FD0F04FC4461BE20F7B9D55E4DCD
+:10E02000F9B23C9AA7E57BB93E5735CFE4591F8139
+:10E030007EE7E432BD4AFA8178058AAF2F7308DAA9
+:10E04000E9A24941F94DF224795384F83442A81CDD
+:10E05000D4DAD73954AE6AFC23FBF3B85FDD53CA78
+:10E06000FC6C24FCF3DD181E6745E07B5B00F48844
+:10E07000256F5FEFF693DEE5AE39553AAAA5934BCF
+:10E08000543AC825B930FE97A4646F29D059FB28AB
+:10E0900009E8A188F301E17A1CAA8A947E5E3871AE
+:10E0A000FFEB8A0C765AABB32517E37EAEC8D5F8E2
+:10E0B0001B1627CD1A05FB991AF7434885F313BAA7
+:10E0C0002EC17BA509F4B6DEF514897CA2814757E1
+:10E0D000D58438D8076C5C8E1BEB2F6EDAFA168C61
+:10E0E000BFB4A903535BA207858C55F2A2FFC6EF0C
+:10E0F000AAA985795907D2728D1CB624D2763A3BEB
+:10E100006020D3BB543C3889491BA7BAA66D644C28
+:10E110001405461BDD2F403EAF095447C3386DEE52
+:10E1200091A7F55F9D894F36541C2089148ECFBF6F
+:10E130003DE9F5C934DD07FC46F7C1E738DFA41730
+:10E140003FF3CEAD3A7E399C5066D3F2CBE1D54A4F
+:10E150008E965F58BE777E29B917CA3B53255D3E20
+:10E160001DF84593DF10E217960FF30BEDBF84CA3D
+:10E1700085372D985F9D7B78B557537E67DE613D6F
+:10E18000BF8C173DEB23E801815C26EFCF35BFDC68
+:10E19000C7F7913EF3CB3FCE8E5F9ECEE57ACECFD2
+:10E1A000E7971773937E397EF1F4915F3C3DF9E573
+:10E1B000EF3F855FDA9C7E8C076C9B6CAAF445C0B0
+:10E1C0007703978FAADF7B34F753944F53AE1E0625
+:10E1D000FA2C8F5B53E369DAA6B1FD7B61D504DCD1
+:10E1E0002F37EC63FBA5BA3FF3A35DCA4FCC8F3149
+:10E1F0003AC0F6CDA46201DB4F52049F4C7F6DA361
+:10E200002A413FD8AF4B04D22EC352E757E50A61EB
+:10E21000BD898E877AD3236E16374B0E327DC74A5F
+:10E22000FF037ABABCD8ACDB57538CFA9721AF9E68
+:10E2300063AAE7978F405C0285C7D72ADD18F65B93
+:10E24000150E6B0E96A11EF2D540CB69CFABDAF856
+:10E250007A43FA5491A734923F6C7A1E8B93B8DDBF
+:10E26000A54879A3613FBE11F75D753F37EECB9DA1
+:10E270001507F472C65BD84F2767BC85F7EAE40C34
+:10E28000CFF72A6748119687F6659E0FEDCB3C1FA6
+:10E29000DA97793E2467A0FF92F0BE3C6873E1BD37
+:10E2A0005A393307F27DD897AFCBFB65E4CC5FCE0C
+:10E2B00056CE9CE5BE5C9277CEE4CC84BC5F50CE5B
+:10E2C00054819C893BB39CA9023953A09333D7E670
+:10E2D000FD043963AFEBF2C2F9FD35BDD0BDC8F521
+:10E2E000A5D939CA0CE89F4CEC5BDCB691AEBAAA52
+:10E2F000362F4E067A71333BAFB7F6F6C6BFBCD5A4
+:10E30000A2898BB64B0176BFA2F179FC7E6DDD3E12
+:10E31000F4979D69BED3F308A6C67DB4AB6AB71562
+:10E32000E9D66DC233F19F3A8FB6C98C2FDFDCF48A
+:10E3300002EAB70F80DF2FA9A79EABE2B5AFFA8F35
+:10E3400071DC865C19D7611CFF4C744BE9F421A089
+:10E35000D393036F1B0A769E68BF2F16E0F52BD868
+:10E360000F3B7E0A9D0672193EFBB0EE977EC97583
+:10E37000FF0CFEDC0BF33ADB755F97D7E775BFF355
+:10E380004BAEFB67D80B9FFF9475CFC9256ADC0D98
+:10E39000DE9771C22F944F567F9FF721F82F56FFBB
+:10E3A00030E4195867FBB7D675E0BF20DFFD283A87
+:10E3B000B5F7A708BB3763E7EDEC1E761FC659A972
+:10E3C000B91F45C2F7A5703DE8DF0895EF8D745F72
+:10E3D000EE974E411FF9C87C9A720BF3DB19BFBF51
+:10E3E0009323B07B6C425534C4C5774DDE81F10672
+:10E3F0006D9347E2B995514F51DB753629E84F6A65
+:10E400006BF260BAB2A932007E93E70F7C20403CE9
+:10E4100058D1813ADCDF568CB97400C6F18D2B8A55
+:10E4200081FC4A839EE2E07ACA90C16FEBF48A8E47
+:10E430003FD5ADF69684FD50F784F417DA4ED6D862
+:10E4400049340FE410B29320AFB393E6A15FA11358
+:10E45000F4175AFFBCC1F356471A678589D482FE68
+:10E46000B2A2CE5419497F793727B25F81E6F1DC39
+:10E470002DDA6EF52DCA047D86D468FD6A67D25FF9
+:10E48000FE34F82CFD0A6769274D1E7C6EF4971048
+:10E49000DF72BD253E5FB91E5CB2E74A4E0CE8A3B1
+:10E4A0009C18D0534EDC3AF827C8897773587CB54E
+:10E4B0004A5F1B6437FA93DB2A09FA1FDB028BFAE7
+:10E4C00015D2FC73752622D0FCED6F32BFF09A6234
+:10E4D000E2837BB46B0612CC07DC8C0E2688B6DF99
+:10E4E000801FBCB382DA4F32F8EDAEA802D8AE8AF4
+:10E4F0009D747734A597AA628980DD34412CC1715F
+:10E50000020A8B0FADB291DF44815D354E228BCE76
+:10E51000C26F6D170B04CA91943FE578E0DBDEFC17
+:10E52000D146FF3311DF70E33D27831FFA6CFDCF27
+:10E530006B07FF6CFF33F2DF179BEBAA311EFC0C5D
+:10E54000F478DD601933C67DCAC8C72A3DF5467F19
+:10E5500036D0934669F2FC1EEEBBFC7CD9067AD21B
+:10E56000A8305D74558D898B147FA5A6B18D2FBE03
+:10E57000A5BD8F172B75607FB18DDBF0FB7D10374C
+:10E5800000EB93DC284F1F2BA37238C2FCB637CDAB
+:10E590003F08F2735B5323A61749DD6202ADFF52B9
+:10E5A00093F720C06D6B532BA6CF37B5637967D334
+:10E5B0008398DED3E4C37445D3164CEF6EEAC0F4FF
+:10E5C000B12C364E89E4C77E2E3A45FBD7D0D1B860
+:10E5D0006E3A8E06DF171CF6EACAC7065B75E5E7DA
+:10E5E0001D6AD7E547071ED4D57796F874E5B3734F
+:10E5F0006A3E01BE74146DD17DB71574E8DAF5D5A5
+:10E600002E38D7F532AC4FC1313989877B1770FF6F
+:10E610000AEE0D513E4E69A4E295E61FB5733F47E1
+:10E62000073B274F25A11FA44BBC7245EB77D95957
+:10E630001C64731A6BDFFC3B967F349D9D1FA97190
+:10E640009AA23544D744480E9FE73F6AE7F7947291
+:10E65000585C6446810F3C12240302D4E03CA48839
+:10E660009D93A9E7DECDDCEFF0A8996C15A83ED903
+:10E670002CB1F9372BC4B790D66B2E60F9872A8856
+:10E68000CF04F357A8144FD69C7337EEFE56280CD0
+:10E690009F9793210A9ED788FC9C3D74EE1DFD4FE9
+:10E6A00082E7FA1C5E8B623FC738DAF8C66E01F863
+:10E6B0002BA5B1BB0BE6F7E8EF2D72247BA8EBF797
+:10E6C0005FA701DFACFDDDD769C0EC6B43F133DD43
+:10E6D000D1DAF8990C0E97B58D5918BFB0B6D6A1FE
+:10E6E000BB07A729C77886AF6AF9FB044442BB6819
+:10E6F00080330C579F1A3F2242DC1D5D7F76F8FE67
+:10E70000E9CF8DAF59DBB880C5D70C243CBE66126B
+:10E71000DA932A1ED6423ABCE7BDDE5F3ABEE68CEB
+:10E7200071358638071DFD42DE6BA46F19F112C5E5
+:10E73000E95BB88BC545A419E8468DBB50E9528DFD
+:10E74000CF50E335D4F80D0B8FEBA0C3F2B8E6C879
+:10E75000F465D9415C70EF4D34C5B8D7679E398EEA
+:10E7600060812B8B6F0EF387B37E59FCC057839566
+:10E770005B5C49E17E07B8945B5DA3C37935DD003E
+:10E78000BF8EA55DB88315A0AFE6172BCD709F2F68
+:10E79000A188E03D9DA26201D3FC832CBFD82562F5
+:10E7A000BB7F77317F939ABF5C515E85F671867629
+:10E7B0009787DA99B1DE932EA6E73DE992D8BC7926
+:10E7C0001CF2244EDF4BC78A2C3EBA426072030E05
+:10E7D00054C7F0FD90C2EF72E29C92A3F1BB5EC100
+:10E7E000B1B5B289C5F7A9F1D07F7F53C478685B12
+:10E7F000B1A71CEE9E8D0E04FC70BE5EB491381362
+:10E8000064985F50017E5C987EFF0E888778EE12D8
+:10E8100076667BF941A62F5C517C33BE37E2F84E19
+:10E82000447FACB3C4EEF6C14013CD6CFF57E3A1F7
+:10E830008BF5FA4295415FB8FC0CEF7F24906E2F68
+:10E84000EC935B5C067F2C7F07A437F91D7E078461
+:10E85000C98722DEA7ADD8190DFEEBFC8326BCEEDE
+:10E86000296E5444BC1FDBC6E23C9E0B784E7B1FD6
+:10E87000753F876380CB89BFF338C94E2E27DEE50D
+:10E8800072E210C8099ABEC5E3240FF23849E37D4D
+:10E8900089B6A6CA035A7DC798DA05BF07E3A04622
+:10E8A0004804EFDFF5F2DE87DD4DFBD1C5312E44A4
+:10E8B000FAD9197F7F29EAA31E13EA95F7952869EB
+:10E8C00091ECBBFBA6949D36FE7065D3D4032DA7B7
+:10E8D00099A7C3A2B767D4F45B977A3FAE1DEF5BED
+:10E8E000A42826027155695619EFFFADEC52CFF7F7
+:10E8F000ADBE68585F9D8DFC5313A7D23E2DE081BD
+:10E90000F2154512DECF51FB8D2BA6F3D1FAF92B70
+:10E910003FC278E995E382A9A0CFDC37F693A9B985
+:10E92000102FB24F2440063DE6ED62FE76755D295C
+:10E93000D27C21529C7A6FEBFA90B757E3C58DF0E9
+:10E94000EF55EF808880D3DFB7B2E427F58CDFEB9B
+:10E95000C33CD16EFD76CBFCC970BFB7AFEF5FC4CF
+:10E96000723A4C9B49A2819FCE448F3673379E1BCF
+:10E97000DD3333F2B951763EC3F73D25FBD9FB2297
+:10E980000591E7D1935ED97C5648B47FDA6F7B4915
+:10E99000E4FEAFC81754BA7E07E4557BA509F50A13
+:10E9A0003B159F10176F1F47F520F0E328EC9DA241
+:10E9B0002F4BD8F98C515EF418BF84C257636F1B7C
+:10E9C000E55071BE4D671F9F1C3839CE1F89AE7848
+:10E9D000AAC25195433DE148F09CA91DE088708A88
+:10E9E000CCD7617C2D540FD16ACE705F6F5224FA60
+:10E9F000E90D0F467A5831D313E70778BDFA2D9108
+:10EA0000C1B955A2E7C7DEE06784D7F5BF30BC8C3B
+:10EA1000E517E773FF481FD7D9E77A542F726AF4D6
+:10EA200062B8142DD1FC389EBFC22B041FA2724BBA
+:10EA3000D8F637D47BC6F1F40A48E9FEB84DF0FFAA
+:10EA4000F31FB4718920A703D2AA5F1A0C1E32B239
+:10EA50004498AFD37F960BEE432FA35FA8BB1FD480
+:10EA60001B4F6A2486641FAEEB6F42B01936AC2B85
+:10EA700089B218D27AD26E8176F59D7F3B04E3D4B9
+:10EA80007746FB45704E6E351FD3FA8D666BEF8F60
+:10EA900064C22B1A1D964C3A9FB95BF4E7A4752407
+:10EAA00080FDCDEBD07F37DE1F11440A18789C2003
+:10EAB00014FF5A82F1BD249A954B439C5CCE75E7B6
+:10EAC00069DF33ABE5F0AAB5DAFCF0BE10F1E9E797
+:10EAD000297139B48BCA31EB48BC0FF3A77CBAEE6D
+:10EAE000234EABD744F5E5E4849A7A80C78D44B6CB
+:10EAF000B094E90DEABA8893E173866DB205E03B04
+:10EB0000A3D5B80EC502F3B9A9FDF4EB53F1FEFF8E
+:10EB1000F209C2BD355FC6745ECCC43D0A14170548
+:10EB200032B4EF4134C0FE00FC35BF9F8E7FDF5012
+:10EB3000E99128625FD6DF13AE39E82753E1DA3B6B
+:10EB40009DEAFD642F44B37953F8ED0539A0C28FD7
+:10EB5000483585D0AFBA9E7F8D0E6CF6C3B9AA9D9D
+:10EB6000BD03F54142CD9B00EFF443C14F043A751C
+:10EB70006293F3609D9F6F3DF29698155E1F21C1D1
+:10EB8000FB213EBA76ABE85C0EEBD9FAEA21A0F79E
+:10EB9000DED6A5C6C7527A40B8D1797D14695E9F8A
+:10EBA000FD96DC007AC978B140E747798EEF276B94
+:10EBB0000A3C87617E4507063A60BEE6AC8EDDFD05
+:10EBC000E93CBA6F1730AE36512415003F351EE1CF
+:10EBD000844D423B3B31D62B3A68BEFB46E25E0F8A
+:10EBE000D370CF7703A988E905EEE5946E926F178D
+:10EBF0003D204FDEBF6D46FC0C9A26DB67C667D30F
+:10EC0000F4A228E28DA6FD250B264F073AA1A6C740
+:10EC10004FA1F3BC2E8ACE93E6337F1BEBCFA6FC2D
+:10EC2000F6570BB102BD26C6D6AC1A0FE3C48B381B
+:10EC30009FA3544F94A81C2BBDFACB51563A5EFFAC
+:10EC4000EF6C23613E698DE5E49F1494FBF3995FBB
+:10EC5000F1B327BF1905F7C0C51F6D6EBC67CEE9BC
+:10EC60002F319BC1C388EFAD9CAEDE8B61F64E7D2C
+:10EC7000926509F8DB3FE7F60F515C682FDCC6EDC3
+:10EC800085F762981DF45E9EEA5FF22769F5DBFA6C
+:10EC90006825EE2A301EA89E04F1CE5F3A95B8781A
+:10ECA000A8473CC8B7B771BBF973422A81CE6F5BE6
+:10ECB000569E9240DB2735333818E7377808DB9FBC
+:10ECC000EB4E5182D6F8CFEA24BF05F486BA53162C
+:10ECD000DDF7F7A91EEDD5DC57BFEEF0C1F130BF6F
+:10ECE000EB497031D4BFFEB658E6B8E7FCDAC9E7A5
+:10ECF000D11B5CEAE325225178D40BC473BA7A2F76
+:10ED0000FF204684EFA421AC3CA93CF2FAC60F6177
+:10ED10007A5FF9D2890F009DD507CCA8CBDFF662C8
+:10ED200069CAE9F4E7FA5317109FC6FF572F051178
+:10ED30001EF5A72EC4EFE54B8F5980EEA11F997EDB
+:10ED4000BF2D5A49017F6D6F70DECAF5A0FA53F1ED
+:10ED5000C4DB4FFB9DF177B8FF442CFF3387DB9F6B
+:10ED6000F7982A23C5772DE0EB1E92247940EF1AFD
+:10ED7000EA27CABA08E3AAF5921322EBC5EABC3A1D
+:10ED8000CB82D7C3BCCFAB204AA4F1667238AAF3BA
+:10ED9000ED4C08CEF2207D76E7C13B13A1BCB33B1E
+:10EDA00043FB8EC4235C1E745E1ACC80FE3FBF24DE
+:10EDB000F2BD1D15CF63B8BEFCB7849A4E901FD329
+:10EDC000AEA2194A1F29D3FC26763F85F15B6FF866
+:10EDD0000EC35924BE51A783B305CBD5FE8EECE7F5
+:10EDE000FC48ED708853BF91CBFF1B37CEC5B827C9
+:10EDF000554E1D795044397504F7169AFA04D45FBC
+:10EE0000A7D7509D8ACA95599BCA77C37670632A43
+:10EE1000211726B0EF7741DA62D6F9FBD5F1661CEF
+:10EE2000F2A09E35B34DBFCFD592B62F403F38B23A
+:10EE30009FC903CADF1690C7B3EED3F753BBF1B235
+:10EE40004F617EB506BB3C99EFCF463DEFA121DC7B
+:10EE5000BF3F868C391BBBBC9E92C510DC173C2281
+:10EE6000CC63B4A47F674B4DE30A199D2CD874D2B0
+:10EE7000E2907BEFF728952339B4DF63D41E87F443
+:10EE8000C521CA934368BBE3FB185C5E1B52F30CBD
+:10EE90008C777C1F5BFF89BA13B3E09D183295E92C
+:10EEA0000D5170F980FE1A75ADD5D74CD7BB948A39
+:10EEB000A968B81714C5F411550F13C55B45072D84
+:10EEC0001FFB5F33E3619D898F5F5C09FD253D1E5C
+:10EED000AB00DC96972A2340DE2FAFB2B9E1BECA61
+:10EEE0003A4A86C5B4BD95F603FB89EFCF6377C078
+:10EEF00071644EC7AA3278F7C5B9ADCB3F80AEABCF
+:10EF0000D5C4DEC968BD90B89B4978BC866D55CF25
+:10EF1000C0BC3226D3FD41807BF4CA08A7A67FC2BD
+:10EF2000F5AB7A8E93E3AF0CBEE702B897B04744D7
+:10EF3000F5F1445D16DAF54308A32735FE1EC60633
+:10EF40003D5285DF31BA5F114D9CDA900EC16FA63C
+:10EF5000EB9AD7F90CBEC751B7C89F7C2DECB78F81
+:10EF6000496C1FE5F34BFC6B5A99EC08EFBFD70ACD
+:10EF70004ED423553DF96AA2FE14A0BF702AE78340
+:10EF8000ABB97E7C6D2C83F374E2CE8076D7588942
+:10EF9000C34461766D79C7E8F9B0EFCE35C7837E9B
+:10EFA000036B8984773535EA412A1FD66FB67BC15A
+:10EFB000EFFAB9D09D079D1C35333EEB7E25CAB7CD
+:10EFC0003E33427F7CFFAACFE37A5D0E51E0FE40E4
+:10EFD000FDF6C1781F2C2A86E27124CA3F2BE0750A
+:10EFE00017ECFF74DDB35F8EF6E3BD30F5BD32275D
+:10EFF000F1DAE9380DDB53D6839E9198AD8C5840F9
+:10F00000FBFBDC1CCC407941E59B40F7D6D4A14BFF
+:10F01000A64894AFEAFB53BD8BE6C73F7EEF148949
+:10F02000D2637D56709689E6E73DFE04CB0F097EDC
+:10F0300002F93B1E7F81D51F199C25D2FCEAC777B8
+:10F04000B17238C3A684B5F6F137A680FD7F349E31
+:10F05000E90FC41DBC1EE8A7FEA5C1A6E59AF5DE12
+:10F060003D94C9D1A3D1ACDED14C724335C0DB1580
+:10F07000CCABD69CCB350C0DF96F589C165FA7DA3C
+:10F080008EA446EE7F306F37BB9CD5BB2896B44626
+:10F09000B3FB755ED0C7766E1B8C70B10D4DE0F082
+:10F0A000A2FD1485FB51E1A8F6A78E3B07F67590EB
+:10F0B000FB662AF73572A66828C31B1DA705C7295A
+:10F0C0005046C03B56F5D5034700DE28BE248E2FA0
+:10F0D000C98A8FABAD63F3A3FDC617E23E330AFCCA
+:10F0E000CA3BBFA3F533C3F336D287C2C799DDCC81
+:10F0F000EEF777C767231D5D14CBF4455244E14713
+:10F10000E5D9EAA16CFFB97B683C5B5F080F290277
+:10F11000F6DFCCE13790D53FDBF556FF42EBD5E08B
+:10F120004901FFCACEADF98827753D84ACD2F5738D
+:10F1300074A1A15D31653C98474236B65B1A4DAC6F
+:10F14000F89DAC0FB5CBA4ED2E2AEF1E05FC308F39
+:10F15000EBC3C47B21C635D4716931AF356001BFC3
+:10F16000F4BC0EE6272739747D401FD5138BF8FABF
+:10F170009C7C7D4EB63E9F8E3EC9C1EE8CC9F69EEC
+:10F18000741B827BA8BF8291BC3F1D3F47EA0FF8EA
+:10F19000A2377CB40C65FBD439C3873A4F033C4398
+:10F1A0007036CC4F8527F031B62BD0F3933ACF3B56
+:10F1B0007AE3E7CC9F385E296B37EF77148FA0FF97
+:10F1C000C87A7A9ED799699A5E106ED7DAB1D00361
+:10F1D000723E5690991FBCB3CA0BFB5FC3B652F484
+:10F1E00053CD7BE1C9E7BDB4FD9CA7D73820B8EA71
+:10F1F00088D49E0C7A70DDA6C50E781FEEB0E4753B
+:10F2000080FC3CE21323FA07FFC1F1A0EA5DF57C24
+:10F21000BF39FAE7BB27013CBEDE64C67B860D5BC7
+:10F22000A2FC51E837998DFA18CD7FC8F24BBF0088
+:10F230003BB661AB5E7F9AF3A735C9E80F23DE01C9
+:10F24000263C04F30F80C3B0FA8D663C4FA93F28DB
+:10F25000BAE930A481742F81F919DBC33C4E51BC4B
+:10F2600037748837427C9FB19C4A12D4C71A3AEF50
+:10F27000463DADA1F3924F41AF6830C453D4F6A2DE
+:10F2800087BD3194EB61FC9D74153EC49784FA4DA3
+:10F29000F3630F147E48E7756CE3EB0EA140BB6F80
+:10F2A0002E423C9DE898B1F625B9F7FDF573D00FD5
+:10F2B000A2B4ED187EE5AD023B18DAC6D23AB3DF50
+:10F2C00001FE81BA756637DD8149DD931B36FF117A
+:10F2D000ECCB77A2DC106A3AF7C95D6F9D4FF373F0
+:10F2E0009F31274E64D3B7C139B78A2788D9003DEB
+:10F2F00045C5CB9CBFECB2C8C3D877D07B55FCCCFE
+:10F300007DA6CB02F7FC8C702CEFE8B2603CAC1110
+:10F310004F1D1F4E0015A4F9B16F2C40DF47B60BEF
+:10F32000F8EEBDB17DEDBA5D0EA0438013D8A12AE1
+:10F33000BE42F8EB8137FFA4978AB01EFA43CE8411
+:10F34000BF270047A391CE9F7A09FC28EF46B90159
+:10F350000EB54FDDEA80F57C2ACD67F4FEC8E26485
+:10F36000782FAFD6EC4D7662CABED73E7A3BD2E15B
+:10F37000CDFB6E4F66EF482869EC1D4D6F1AACF35C
+:10F38000A687A7E03A67911AA4C3DA47987FE32BD0
+:10F3900089543E13815FA614B07DE4D3F551101C4F
+:10F3A000443E8573043837D92FE2BDFB1EEF22910E
+:10F3B0000598FF8AFB17F20B42EF1F5A41BF6BE023
+:10F3C000B51A362E0D009E8EA62B29E0B7A570F03B
+:10F3D00072B809F0EEBBB86F7C0AC31391E13C042C
+:10F3E000DB517DBC1CBE43FD8059892ED4B5E3EFB3
+:10F3F000DBB0F155FF069D770C9CA77F9ACCE2F21B
+:10F400008CEB6BE1EBA33F01A2A5B3DEF87FE33207
+:10F41000A4AF2F0F32FEA9F755556279C0EC4F818A
+:10F42000725FD76401E54394EEFC3C441F1BCD9C06
+:10F43000BFF5E5749E92A085EF7601DFD354E965B0
+:10F44000D67D51BAF3FA30FDE8DF8B52F955B5B3EA
+:10F450006EE6F2C0B86EA37CF01418FE8EC2C349EB
+:10F460007DF27FD7997D9BFF08FC4CF9D72B033F9A
+:10F470009BD13FF0D913AFBE750DA5FBCF3A543EDB
+:10F48000D6CB5B231FD73E3B9A44E2E3CF6C6E1290
+:10F49000918FE9F7887C6C63F7A6FF7FC9DB9B7BC4
+:10F4A00091B7FF56A097B75F9182B80B08EC337302
+:10F4B000F1BD57237C55BBD72847130AE4887294C3
+:10F4C000FE1C241A78AA7054E973CEE3F3709C10E2
+:10F4D0001DAB74AAD271884E8DEBD6C3D3587E2152
+:10F4E000CC5D1307615E44ED18D0735F117DEBE9CD
+:10F4F000D48ED3B92CA1F03FFE4426C61B2DE67650
+:10F50000C07167B703E2C71673BBA31BFC9271E11E
+:10F51000EFDDD14C5F3AEEE976C46BF4A60FB78904
+:10F520000ED0F3823E5219C99F442536CE23487A25
+:10F530002B67E762C7B93FF438F7778E176D198DDF
+:10F54000E0076E677FF764E6C2AB1C702E707C5BD1
+:10F55000F63DC07F37BD26B2773DBD8A04711233B8
+:10F560001808C861E2BDBF84AE73C6B6B918DF60C3
+:10F57000F4A3CCB26DC4F385AFC85D981AFD2773B0
+:10F58000C0CF02F4FEB0E1FBB6CB90BEE618E8AB0C
+:10F5900006E82BAD277DED56F9750419A1BD7FB6A0
+:10F5A00080CBBDF162C13DA0CF1CA7763EC61288BC
+:10F5B000057B61DFFD0AEC7E600C6F12D2EDDC9AF8
+:10F5C000C316FE8E33D2BB4A87467BDF981E7BEE86
+:10F5D000FD3177D22A75CFFFA3F0219A1E7BFE9DC5
+:10F5E000BC9721FFC2DB19FF203DEB976FFF16EDA3
+:10F5F0009BE3DBA3703EC7B7FF2DE34EC8BF148566
+:10F60000E7AFC71745615C9477BBDD07F7F98EA7B5
+:10F6100033BF5DF32BDF1462FC0569617A48818595
+:10F62000A5DBFEFB03889F3EB12D4A063F45C3F68E
+:10F6300058B4DB1B5E8AC6B897E3AF7C3346EB67F2
+:10F64000FAB9EBA9E7E7FCC7ED64EAB340CFF1CC28
+:10F65000BE6B7879EC0688979BD7D96581F381F2E8
+:10F66000BF7E5F0872E9F8B34CFFA0F6FCA3F0D2AE
+:10F67000E1F70575F79B29BC3F071D91DAE17F187B
+:10F68000F6E4956087F7840B83C3710A07581785E2
+:10F690004B2DC8D3DEE09138ECD70A8F2FD0BEA80F
+:10F6A000DB761EF251182E82C2BEDB7D5601D7CF0B
+:10F6B000BE6FFFA610F4A9CF3A16A25E70A6758F92
+:10F6C000FA3FB76EC1DF977557C3BA937E8DEB666D
+:10F6D000F47F88EF57463EE849E72FFC16F34FD9F1
+:10F6E000DD38DF3EF2FF82FF6B787F56C073F9335F
+:10F6F000E17DD5FF5ABCBFC6F16E77427CD9F15788
+:10F70000BECF209AF59F69DD1DFF4BD71DD28F44D8
+:10F710008F159EB86F23FE00DC5F5FDC8B9EF2FED0
+:10F7200030D52FC1EC10357E474C9C837A8698B833
+:10F730001CF586C584BD83EC954DFC3D3616F7DD82
+:10F740003AD0ED43BFA8E4A95D47F3E64175EEE585
+:10F75000D883DE3E13932756829FA579219D17ED0E
+:10F76000A739C9E46C96E19976933FAA10D30F218B
+:10F770005D9A7CE91E1857B2E9DFABB519EC8D989C
+:10F780001C8B3EAE98EC70C27975B45B82B7DCA975
+:10F790002AAB7FDFF6E5612CFE2386F8306EF36C32
+:10F7A000E1642FD4DB6B463819E1A3C2AD079CB8E6
+:10F7B0003DAABEC72F252E0F001F4A84DA936C3D49
+:10F7C0006887C2DF9182F31A73DC2CF772769E226F
+:10F7D00087DEF18738086E6F86DE99954D6897AAA7
+:10F7E00070D6F487EB37C2F96CE1ABE2259A54236B
+:10F7F0009EA307DADC3E3AFFC53283FB620A7778C4
+:10F800005F5C85AF0A37231E8240A34961F88753A6
+:10F810007DBC8EB78CB8E09C65BC5812F482BE5C8F
+:10F820001C8BFAF23181F8056ABF1D2B4D2E03BBEC
+:10F83000E258BA4582745C375D9366BE179DB28606
+:10F84000FE861EE44B49BC2E7F2C3D0FDB975BD31D
+:10F8500074EDF642DC36B5DB8FA5155BF13CD4992F
+:10F86000A96B3729D6B11ECAF7421C378E3F01ED6E
+:10F870009B8B53F375FD4CFAE8D8C337D2742BB782
+:10F88000ABBBC799D11F7FECB5696500C74BE411CD
+:10F89000BAFAFB883309888AAEAF02D677996BAC87
+:10F8A0006EDCBA0F77E4811FE237EE52DDF7CB8BC7
+:10F8B0002FD1F5E3B106FD40DE554A95EE7B5DE3C1
+:10F8C000D744EA47C8058DDF11691455DFFD1DBA1D
+:10F8D0007E46EDD9AAABEF0E38CB41651C79C8FD49
+:10F8E0002AA46A3CBBA59FD56BA2E9B00FCB4438D4
+:10F8F000F71CFD714D33B8A12F38465C4007E791E6
+:10F90000183C0FEC2DEEFD1B93AF06D67987E873FC
+:10F91000411A33605621ACEB486A9B08C7D20F09E5
+:10F92000355714523E1BFBA5AF19F2177DD7218224
+:10F930003DD9BC45C4FB75E3C589B1FF09F2B843A5
+:10F94000C018FF3A9B09FDF09F257414DEAAA13B65
+:10F95000356EC7C8C7FD4795DE5448E9AD255569E2
+:10F96000EF02795AF6FEF56284FBAEC4A97F97AE2A
+:10F97000FF284F2B9CD3AB714931E5220B6EBFD8CA
+:10F980008CFE9225267734170AB8EF3A2798D701CC
+:10F99000BF7FCFE546CCEB44067F504CBF1A11EE3B
+:10F9A000D9917B048C6B51C79B51CCE2ED9714AA83
+:10F9B000EF9B3893AE1B06EDED2C5E007C69D06E9C
+:10F9C000A209F594AE719FA2FD1B73B9291DEEE14A
+:10F9D000398A95D773687E4C607F3ADA59A418E368
+:10F9E0006D16F0389994B6CC077640FB3D668C3B9B
+:10F9F0009E314D399943F32B27B2FB819DC565B1EB
+:10FA0000C334F0739C1288AC892BF8BE50C6793889
+:10FA1000A420DE0F739C92B09C044730FB8F8FE3D1
+:10FA20009826BF7DAB661C22297361DECB87BC277D
+:10FA3000831C731C22FCEF8804F1EFE4413C123E6E
+:10FA400080260553AF8B70EFEEE896D1F16087F713
+:10FA50002B75E33DC17E4F8AA17BB2201657C23F72
+:10FA6000788FB6FAED0A5ABE0564232BF7134ACFF6
+:10FA7000CB2D6A39152D2EFECE2196575F55017874
+:10FA800014F5F5876785EA2BD6D470FFCF1456BFDF
+:10FA9000DD52D013AE5DE3A2707F8EA17400FAE553
+:10FAA00082FC8294D3C5E93B4EC59E01AE0E06D7BB
+:10FAB000EFE82E901CF6277E2CC819405FF7C2F5A0
+:10FAC000006A37AF8EAFD90A741C23FA87C1F7E9F1
+:10FAD0000E25651CA5B74E8B92F13BF48B4463BC9D
+:10FAE00057D52D9F3D0857C41C938EBAA866433A3C
+:10FAF00025257624F8A59C5FA31C50E3DAC270A4E8
+:10FB0000F44BC75C690AE7412E38C27055E06DE0DE
+:10FB1000E51A385B69BE8AC3F5E45333AF4238CD8A
+:10FB2000B4225DDCCA79A8259EB4435CDD49E7E6D2
+:10FB30002B811E4E6E3163F06A2714C2BEE9B2B249
+:10FB4000BFE393184C85BFDB326C9F09FD79EF5101
+:10FB5000FA50803EFC2310EE6A7F274BDE4E80FB7E
+:10FB6000122713A50480CF9CA005E1769D44FCF0EC
+:10FB70005E6A67E2CCF2525ADE7948C6F20EDECFF8
+:10FB80009051CAFB85B88FF3FBBECAF922BC8FDA4D
+:10FB90001BBE8CE7F7E00F3E3FA1773A6829B5E23C
+:10FBA0007B430DC50B0B605F58109F87F1570D15F8
+:10FBB00002EEBB0D8D5F22DCD5FEA553229135717F
+:10FBC000524F80F73049F36EFC290B96D7359E448F
+:10FBD000F94DA793097C738C9F6FB69BC90D553463
+:10FBE000ADFB41BCA1CA86E794ADB07FD4911D9610
+:10FBF000051AF9473ABE08C9FBE11477F74EDC1F36
+:10FC00000372B54A704E8147062EEDF05F05E7F7A7
+:10FC100055D1CE2970DE9FE4FEF355707E5F95EEE0
+:10FC20009C02E7FBB94FC74EC5F234E71AF84BA068
+:10FC3000D5EE5C96CF74BE09F90B8797B1BC9DD108
+:10FC400041CCD31953BDB87FDB102E275A637DA753
+:10FC50007B77E4E6C6977570E9512E0A180785810F
+:10FC60001A947EFEB56C007B073727807159E9C373
+:10FC70000535FE8B142784E37513B38902E7A98940
+:10FC80002F44B3775A3F0E6400FC6E7E21DA0F7E5C
+:10FC9000C8798FBC6A81FD67BA28E7015F8D1F5D57
+:10FCA000933D3C09FC2501CCDFDCB81DE775E74836
+:10FCB000FEF7AC9CDD05E0AFAAE571CEB58678DF36
+:10FCC00039B69DE87F9BB351EF679B4B821F009F26
+:10FCD000D63D71FA38DF8F4C6C1E1287C7743170B5
+:10FCE000BD85CD6BCC70389F49E8C23863C91948CF
+:10FCF000AE41F8D6B9D03E498DC17B344BFABF5BDB
+:10FD000018E97D988E26BADF53967BB6692BA6D26A
+:10FD10000882EB4991821637EDA79ECBE531818FA2
+:10FD20002CDA78C12B385CE3B6B2F36E631CEC15A9
+:10FD3000C3ED3CBE9D9D2BCFAB7EA304F0A2E2F3AE
+:10FD4000A258D281F1AA09C4CDF1E206BCA8F00FF5
+:10FD50009F2FD3769991E842853F61F175314C5ED2
+:10FD6000743F178DFA9471FE757CBEEA3ABCC39954
+:10FD70007DD3DBFCBD30FFA4733F7FEF7059F7DE0E
+:10FD8000ADBA0E958F43F6E0C2C87A8A3AEFB3A7B0
+:10FD9000B380A52F74A6CA997A52E3423F2C972BC1
+:10FDA0002A9CD579AAF0EAEC25BE556A7C51B71E8B
+:10FDB00029508697E31F19CEEE374A1D9760889524
+:10FDC000D4B80DEB9DED7A5479DBDBBA54396B5C1A
+:10FDD0009F2A6FD575AA72575DEF382A48501EC208
+:10FDE0005B0F02D80B353AFDB7146E2868CF7DAC97
+:10FDF000B7E8F2E39DBFD3D5BF3875A1AEFC127949
+:10FE000099AEFC32D72A5DFE37EE3F18F4F875BA8A
+:10FE1000F22AE5315D794930500E7AF6DF9B2A31BE
+:10FE20007EFBC2C3DDAF42DEDFE4C4FC8EA6544CD1
+:10FE30007736C9C8DFBB9B5C98EE6972E3F7FF6851
+:10FE40002AC6F48D2605D340930753A35C98F497F4
+:10FE5000AB24D0D38B03EDA8FF678DA83906F270D1
+:10FE6000AFC9D76CA7703AEF3DA68F139F713FFEC5
+:10FE7000E6833B615F77B27B4D2D5D630539823E42
+:10FE8000E7A0FB9DA2A117C7C42081F36407891CCA
+:10FE900067F9C570768E8BF1799436A75AD93BB63F
+:10FEA00053A70A188F3895B0FB0934F5D7D0F2491B
+:10FEB00012F1C2FE5F6593F0FC89F0FBC253D834A7
+:10FEC000E13D756F14ECDF89FDF07ED264F848E700
+:10FED0002B2A22C6B14E297E1DE3FFAEB1B1BF93DE
+:10FEE00075F59E45FFBA93969316EF6876FF417DB0
+:10FEF00027E45DD3D9E80D5FC09D02380F12DCEC1A
+:10FF0000EFA4C44B6EADFEAFA6BB8633FD7F52336C
+:10FF1000BF1FB08FA01EA7F2235D5F2BCC5FE58BC8
+:10FF20002AA7E41FEC80FD7E5539D4AF3B28235C23
+:10FF300054BE50F940B5FF543E182F3ED10CF54F3A
+:10FF40001C62EF929D77ACE6F05FE838FF03F207A2
+:10FF5000233E0080000000001F8B0800000000000E
+:10FF6000000BB53A09705455B6E7F5EB2DA4937420
+:10FF7000428084CD0E110C64EB74D210B6E1911066
+:10FF8000DC101BD42F20420332614D62C02F8EFE45
+:10FF9000EAC63018F8D69F8C5A7EFDA2D53082CCA6
+:10FFA00068151948303343B0418D30E348545090C0
+:10FFB000882D322CDF848E2C223354F9CF39F73D33
+:10FFC000BA5F2761B1BE49A54EEEF2EE3DFBF61ECB
+:10FFD0005CF95182BE002BAD00E00028EEAC2B4D49
+:10FFE000C27F0B82F560A439FCF911FF0AF7358155
+:10FFF000312B321EF343FDBBB46FB7CF0B4613C09A
+:020000021000EC
+:100000002EDF0C8641DF22300E05D8EBABE2F17B10
+:10001000BE553C6EF1F919EEF3D532FCABAF8ED77D
+:100020003FF4BDC4E38F7C0186ADBEAD3CFF96D3EB
+:100030000ED007E0426B693F6F0E409A3A06EBC460
+:10004000344F0242A38033082117422B9852531198
+:10005000CE909C35C0F37E486118F4E2FAB2B4BF8A
+:1000600080B137A3EFB122BD0F80FA93DADB08230A
+:1000700001EE0741FF03C57FBB2C25D2C09B251590
+:1000800001CC4AEB05EB258087C09F3B0FE18CF24A
+:100090003AD35889D627D94F223F24FF17861FB35A
+:1000A0009127F433A12B4444E1A4C6371960896D2C
+:1000B0008D19860020978E8790BF0690E0C70C8030
+:1000C000C5103403ADBF6E3A1E8AE2F352800CC8ED
+:1000D00044FCDF32F17E6D1EE8F9A873E552198AFF
+:1000E00053886F0EE6D37208F17916F95167958D32
+:1000F000EEAB33D339B1F72EB1BD67C64137F7B692
+:10010000F2F3D7BB57935305C03CDABF264DA9DBAA
+:1001100083E72EEFD536473674C30FBBB1F3EA79C8
+:10012000C887DAE1F8BC1BF14F9864F5229E65B2EE
+:100130000D0C28C770400E58F09C45197589742E17
+:100140002A6622E0FCE26699E50146C5988E722B8C
+:1001500057E5D60EC1CF482EE5E3CAA700CA6FD136
+:10016000063D3D4B6C2798EF176157B7F456C0B367
+:10017000DFC9895DE9AD1877FB293AAF42E51BCFAE
+:10018000235EABDAA46DEF45ED5BEA4C483D198F79
+:10019000FF8C8251C417A4C31944FD397750765A95
+:1001A000A067FD38EB03D6F74B3ED8F61EEAFFD921
+:1001B0002B38D11FEDD159F2927FDCCF273763A1C5
+:1001C00067B593EC09F584EC4893E35AD42140BC1D
+:1001D000D79658037EE467D86D37D2FD61295093D6
+:1001E0004872B90CCED5C8EF89BB3E384C7632D1B7
+:1001F0006A0B12DF9088F668B94E6817D3E34F0494
+:100200006A1270FFD836BF4C663BFAA0B7C686E3C9
+:10021000511F2A2869F433EF796492FB765F13F358
+:10022000A1DE57CF30623FB7B29D413ACE65DEB80E
+:100230009DC1235603F9B5152A4E35C9506740872D
+:1002400075DE36594E403ACE07C149F305071D35D4
+:100250008457619B2227225EEE13DE1AC27B2D8A11
+:100260004141C18D6AF7CB49386F3142D0827EC49B
+:10027000926600258AAFA32F046AC80F6A7EEDED4F
+:1002800038C1C70957EA65F25B76B377EB46E427D6
+:10029000FC39CEB9D9D115EF1D4E03EBFFB114CF08
+:1002A0000E9687CD31CC934BFAD3BEE515D29F86FF
+:1002B00078A7059F83183FADF945ED1C8D6F1A1F78
+:1002C0002BEDE751C6A807ABCEB3DF8BBDB7D2008D
+:1002D000DE7AE4BBABD451588DE7B4AF86B9D370A6
+:1002E0005C674298D375FFBBAE9216C2AF4C1ED767
+:1002F000AA105E76C335F5BA72D5777C7F8FEBEAAC
+:10030000FD95CD6EFB7C5B64DE5820093F0F46FBFC
+:10031000496B449E372AF7F19D3374716BC20F5EAF
+:100320005DDC9A889E367ABDD4FAA86E5C667F4200
+:10033000B7FFF6B4D5BAF53B1DEB74EB7767FD5606
+:1003400037BEC7F9B26EFFBDC51B75EBD394DFEBAB
+:10035000D6A7CAA0486873B952C044763613EA19C2
+:10036000CE86568673A093A1173589E07C70327CC7
+:10037000043C0CE7B8BCFF22B9844D9D7DC9EE3B1F
+:1003800076FE2B87F4A2E31763ED198E485CD6E264
+:10039000F4CDC6E35E66945337FA905860603969CD
+:1003A000FEBE47F9C4F8FB7001FA13C473BDA17314
+:1003B000CE5F508FFCBB2DF6CD51FE0435D240F1FF
+:1003C00058B3DB9EFC4B99115301B4C7AD06E781CE
+:1003D0001574CE47BDA13BFBD2E0D41F90D1A88FAE
+:1003E00049B343C621A86F1753144701E2EF7F6654
+:1003F0005CF2C96CD5BFDC8272F8DAC0FE0F164B16
+:1004000081A14857538318E72E4C0E489C07045986
+:100410001E0F43C84474CC05607F3B0F1C0C178033
+:10042000C272C193E3F3D0CF2C6C30BAD6235EF9FD
+:10043000299D43C8CE72471F4991F0FE3C742FA4FA
+:10044000FFF906A8A53C45C3734181F0074F162864
+:1004500045056E7AAE75FDF3787F67A30136E13905
+:10046000A7463FF14B888AAB2FBB4A46D3BE6D12DD
+:1004700028141FFDCD96C0E60CBABFB32FF9756DD9
+:10048000DF1C57E904DA37B900F87CA87F0788CF6A
+:10049000D3EC82A730A90FF3009F1B4CFEA7AB9DA6
+:1004A000F959DEF9141FFA839828E67B79FC60C1BC
+:1004B000E6196B72981E3FE5632FBBBC1EC6DF8C2E
+:1004C0002E8DF07FD512D8C47953D56009F12C7FD9
+:1004D000CD62A0387E04FD2CDC0670D46765F8A5DB
+:1004E000CFCEF02B5F1AC3AF7D0E86DFF8B2182E89
+:1004F000FC010940391E2E50E692FC7AA2A3677FC8
+:1005000021E8084B30A3DED6757D86AAD7790D2762
+:100510009E8E273D68929D431185DC465438C4FB6E
+:10052000ECAE510139239AAFDE6584475ED3A7CF85
+:100530008D2DA2E78C7609F79F6D3ADF97EC301688
+:10054000BFABFC68360B7EA8F86E4B6E5D4FCF6F6D
+:100550006B1C4218A23F00A187244FA93B3A56B317
+:100560001CF30B44BCB9D7D25964B745E8034A150C
+:10057000305E54ABF1A24CBE9218427CA6D1B9A316
+:1005800049AF6F3D40F7F9F7C93094F513E67AA209
+:10059000ECFC75950F1ACC6D367B0278FEB6E6CF73
+:1005A000A6DF8D7C983AE64EB71C656F2F10136856
+:1005B000DFE8CBFFF37C2AEFB7D355336163991D96
+:1005C000F73D64DDF33EB1E061FBD765C9389E9B22
+:1005D00026B5109CE7C8989CE22074034CCF82ACEF
+:1005E000892DA462539CD3CC94174C24A38AF29FE8
+:1005F000A5564CB274FEBAB76E7C7BDA00DDFE3BCA
+:100600001D99BAF5BBB3B275EBDABD539C85BA7DC3
+:1006100064AF9437231D2C77D82C07864AA407177C
+:10062000BE58CAF4CF2C22FAC3C83F332600A78B8A
+:10063000D7BDF83CB98DC6BD89649FB1F9E9B2E672
+:10064000DFB5288E9EF3D30AF02405A59EF3D29E33
+:10065000F2BA1BCD4FD18F3C477E247FE7FDF61ABF
+:10066000C463DBE8CBFD1D48DFDE02CC5BC9FFC500
+:10067000E4AD61356F8DD5A3ABFA2A3984FEEC97D2
+:10068000D9EF6AF96BAC1E013C2DFC8D0A6FD6DEEA
+:10069000A77E22E2CF3FC8EE7B47EBB70A0305BA3D
+:1006A00078916FC67880F2E9FCBB0C9B68E20AE2A5
+:1006B000A1C92133A2FFF0C8C6F7D38B78DE4FF96A
+:1006C0006905C5073CFF0AE51F84EFB23DEFA7A708
+:1006D00046D661E5D7BAFDF094D4A21BAFC9D08F3E
+:1006E0009F9DD812FD7C4FFEA87CC3A3662FFAE91C
+:1006F000F2172425D08D3FD2F029DB1BA790DF34E1
+:10070000EEB2705D54615740B151F68371A49BF80D
+:10071000ACF98799325475E7E72C2E91674DD91BB8
+:1007200007F24F38F708EA0AE1E37F5BC49B2349ED
+:100730000A78A2EE497109BC3B92EBFEE37BDCD761
+:10074000F1277012EB3B9285DFCD6B38653050FCA2
+:10075000EB25F425CF1E32A4200C2F8AF703DA53A1
+:10076000E5E204BF211FD787747E6645D1F7DF9E7F
+:10077000FCB215E5F685C1A08B3F61F27938CE74E5
+:1007800025CF5C83FFDFBD372E68F809F46462CCA7
+:10079000627F5A22EC7E0EE98DB84701743995BF0D
+:1007A00006ED5E85FC04D14FE3D9DB538FBC407965
+:1007B000EC7EE10770D9165B973E145597C206612F
+:1007C000BF56FCA53CA60202936D54FF07D1FEE183
+:1007D000E7B3FF092E5BC4CE6FEB6AD79ADD571ED5
+:1007E00012767F6ED7C54FC8CF9FC3F8176DF71A23
+:1007F000DF347BAF7C4966BBD4E6CFEE92EF087462
+:10080000C3E7E1AABE81E2647BADB68B7BABC75F79
+:100810009A4E71AEBA19252475BD478395B5323805
+:10082000A2EED9B6DBB228608BD011D6E26BF3C54D
+:1008300094893902AEA6F80B75AAFF11790DC65539
+:10084000532AC5D5699273338243CDFD4A887F8789
+:1008500024083A5C7CC4FD56C4EF3E711CCDDB28F5
+:100860003F83B42C23DD335D95EB7D6A9FE881E601
+:10087000078692BFFFAC61FE21059756B83299CE2C
+:1008800007C1CFF9E1A164CFA01588E7D41AA1E789
+:1008900087923BDBA9AF74687CBC5423F1F96BA24F
+:1008A000F3BF4326CFA02AA64BED2F2923E41FE355
+:1008B0006FA2EE55FD22CAD32F893A8DEDC098FE66
+:1008C0002CF70B1643A045C17B2B9C41CE5397823E
+:1008D000A8EF63F3F48A71DF9A293EC4D695139B7F
+:1008E000F61C96F2BAE947C4E8EDF5FA0FB1F56CDB
+:1008F0004F79FEC514CF8BAEA83E606CBE7E352FFF
+:10090000D5F2AACDF1814D88CFBBE3FFFBEC521CA1
+:10091000AFDC1C6FA7FAF9CC6B163FF9E7339B2CC1
+:100920000109D7CFA474B651DD70667BAE134F803A
+:100930007283E3CDB728CEFFC1C47A01E014F6710B
+:10094000554F1F3F46FEAE7A738204945F7BC5BA53
+:1009500056CBC96F24709EB078477AC02245E20C0E
+:10096000D98703538BD3AFC62994F49FD9775F12ED
+:10097000F5A1DA0D7F1CCC7D2DF9A9634FE0734BF7
+:10098000B724B8289F801C60B92DDA347C23E5C7D2
+:100990002F9ABC4D447FE91BF7F4CBA0F33FED0346
+:1009A000444F78D78EBE941F45F2F6EEF3BD73BB6D
+:1009B00032932027C227AD2F58FBFA6A0FC93D5E3C
+:1009C00072F0BC11AA9401A4174DD380CE75C992C0
+:1009D0004276D9B92E9EF3D458BD3BE01275CA3287
+:1009E000AD8FD01BAC69643F5E603E84D7656F5AA3
+:1009F0008F7C3AE54A51E375E7B0E9B9D1FAD956A7
+:100A000041F5DFB90D16EE6FB4C7E9F3060D1E759B
+:100A100025F3FE72EB055D3FA162D565FD38071435
+:100A2000F23BAE1A47E1A30857A8FCEF18E139E6FC
+:100A3000423C97D4FF76E787CC970DFFFE05DDBBE0
+:100A4000CF26FA2A1F0AFEC5D603E556D1BF00D825
+:100A5000C8F76BF3A75EFD3C8FF4F05463F6309259
+:100A6000E37CB9F5E42B48E7D984D6634F22DCBE9A
+:100A7000EF13964B2CBEB17D987649627A97111D83
+:100A8000385FE6F65C2039A320B88E9BBF3E97F90D
+:100A90005726E724911CC367BAAF57343CB5F335EA
+:100AA000FCB4F3B57D52A190578BDAE7EB30B79EDB
+:100AB00025F976ECCC96A8CF77753EA5352F394A27
+:100AC0005F7EAEFEFA2CB5CF71D8B0FA3133EA634F
+:100AD0007BFDF3266FB4DFBBC9BEFAD57C5001871E
+:100AE000BDAF08251CB79038238EC76B6332061C38
+:100AF0008F53D193081FB4CBF12A8425DE34EE9BAB
+:100B0000D37908E320C0E39A894E07C1099287FB95
+:100B1000175ADD3019AA06121D066B88FB7D6BA8DB
+:100B2000CF8879CB03C96BEFC9C0FBD6F481B594EC
+:100B3000CFAC3109BBF0CF8BE77A4EE3931667C099
+:100B40009EA38B2F6BECE030E239338C506B4A1153
+:100B5000FB6E413E1FDA37FF7DEA9F7E6EACEA43B3
+:100B6000F71EB1BD902B1928CF0B2450CDF8C52707
+:100B70007F70FF1DF71E05653CE515F77F6065BFBB
+:100B80001FDB9F58085E1E9743C874019FFB6AF4E1
+:100B90003F37EF85085D5F8DF9BE91EA8487929FAC
+:100BA00076D3F3FE12C8A2B874292E318FE85965A6
+:100BB00015F0F15E899B089EB1DBFCD45FBD143754
+:100BC0003840F1F415C97B6F611F7E8EEB58FFB181
+:100BD000F800C5BBC7656F05F79393CD20E1FE70A4
+:100BE0001F952F1DC07C099BD4FDDF39785C54EA2A
+:100BF000E27E235C72B05F1E1B13778AB20DA23EA9
+:100C0000FB51EC1FDF69D4C59DA27CB59FF32F0774
+:100C1000E7A9137E305E332E75148A7AB7A8B7A180
+:100C2000AABB7C718DBA5E034159F47944BE30F69B
+:100C3000AA7E2932C9B1421D57505C43BD0A275ACA
+:100C4000FD32D23B7697D0B3B1C6E01E82E8656133
+:100C500015E5174D18F7343CD0AF405A36EBC318A2
+:100C60004D4FF1ACD9B86FAD54C5758C95F21A845F
+:100C7000EBA556C6E317D0C95051E3790938194E90
+:100C8000020F43D4538677401DC3BBA09EE1146876
+:100C900015F17F44B086E31A3C65E7F71877961B99
+:100CA00028EF287AB0FBFA61CB75F9808637F2E637
+:100CB000F93019D0FE32BBE1C7C02CF623B1FC8855
+:100CC000B5D3F11092D94EC9416452FFC0C1F65A52
+:100CD0000A0A8FCB6E900FC521AF91FB37B1FC286C
+:100CE000ED5E2FB6A9FC5840BAD62722A713850E71
+:100CF0001E6BF242FB4AA33C34568EDA7C517CC90F
+:100D00007907BAE2BF157E39D388F1ABA8B0644544
+:100D1000268EBFDCD121C6634B760CC1F15785E12D
+:100D200099C674D2EF92429313AB18A973E6241CB0
+:100D30007BC93EF309A21D923FF38AFA78A59AC7B0
+:100D400078573FE6B4A3BD7807D99C44A71593FD17
+:100D500038E4A39C29DE1F0EBE23B8D784FBBE3225
+:100D6000795BC87E975B83890EE4FFCAD565FDC8B1
+:100D7000753E6316FB2D16D17FD5E8C3797F1C8E97
+:100D8000B76FCF5E210DB93E1E78FE413ADFBB7AC8
+:100D9000A89FECD7DB283985644BFACD401EB6B747
+:100DA0009A80FAA6DA7D4F8DF01EA1FDE070B2FFA9
+:100DB0001EA0E639EDDBB3B3494E270AD5F7C3A928
+:100DC0001985C4C7A3233C27687F3841E8DB098A1B
+:100DD000E5EE9EA1AD48395ED8CD7CF81F88003E77
+:100DE0007FB1D07B9AD62BE3AF70DC3F5BF0E9DAC2
+:100DF0005046446F2514DA6CA4BF46818099E3C342
+:100E000038FBD53C95FCDD423C07F951E4F1D69026
+:100E10008B1B35BB7324F9553CF73C9F6B0E0D2E95
+:100E2000C0E75EB8EF9859E8DD40A177AA5F6ADEB7
+:100E3000BDFFC90162E881283BABDC7DF9FBA3C89B
+:100E4000BFCA7336276D8FD8D7CB2BB8DE049BCEA5
+:100E50008F687637A6C9C2F9F6D85DC317D2BEF13E
+:100E60009FB665125D13DA42FC3E2CDCFCF9008172
+:100E70008756875C927E4A3C3EA5C6895356111719
+:100E8000E8FD2ED77B8DE2FD6EB5DAE7AC6E9602FB
+:100E90007EF63FA27E5EA4D2B77C7F630BF54F1631
+:100EA0006D583085F52820EA0A07FE925F5872587F
+:100EB000D4CD4BB7EAEB8D4AAA9B693F04CDA40F72
+:100EC000CBEB63D6379472DD5C19EDFFBBA99B8732
+:100ED00015A9FDB1413088E992672779BBF187B147
+:100EE00075710528B9459CF77A64BADF6DECBEFFD1
+:100EF000909427E9FAB5E5EADDC4271BF3C5CCF5E4
+:100F000044F5AB2B9C761AAB76BB1175A798F2ED26
+:100F1000DA03DC5FD69ED3EC7871ADC475076CE85C
+:100F2000CD3A98BFC5A210BDF95BFA711D82F512CA
+:100F3000E7871BB7586A695CF3EB5E7E399FFAD08E
+:100F40009DFDA90F531387F9A6E8E783E4E23E0C61
+:100F5000F745E617A97E5FCD032058A0ABE76BD419
+:100F6000F85F9D30AC1F56CE917DFBD275F5498D53
+:100F70009A6F17119E94376EED2FD6E3041D7B3EBA
+:100F8000FEB778CA7B1B8D9E78EA6B9F3B3884EB5B
+:100F9000989EF8EEC63004D778DFE8FE7C4AE6B5C6
+:100FA000E456F49251F04BD5DB3FFB14F8C6149194
+:100FB0008B465F99FC56A999FA228F809DFA24D519
+:100FC000FB7F5763A5BA701D7007E21C087D3E7752
+:100FD000DAC0EFCF4742D66FC6E1D87DDAE80CE041
+:100FE000F30DAA5FA4F7C88E283DB3A8FDDF3847EC
+:100FF0002F7044D5D1F15929BA7182B3BFEEB9A48B
+:10100000E221BA75E4F7263A1FFC4A6BCEC848DEE7
+:101010009BAC8CD03DF74CE2E47D6CF7ADBFE4BEF9
+:1010200054EF3B5C7A7CE45D32F903B820F2A562B0
+:10103000FC257B1B05FE1A92C798767D1E551CAABF
+:10104000E3BA31EEA051D707B05CA72FF59C665FDD
+:101050000361A0F01BB1FCD67F4751BD5FE67CAFBA
+:101060007A1026AA19DDF1FB561DBF357BD4F8DEB8
+:10107000C7A3E77BBF197A7EA77BF5FC1EB048CFDC
+:10108000EF41557A7EDFB24ACFD70CBF9E8F99B51C
+:101090006374FB87D695E8C6B7BD74976EFFF0C042
+:1010A00074DD387BEB2CDDFEDCFAF9BAF5FCA62505
+:1010B0003724FF8260B56E5FACFC0BF7FDEA9AF255
+:1010C000F7E3AF903FB03C8A511E41C7FF9F1E7CA3
+:1010D0001AAB0737E867DF249B15DF2584FCA407DC
+:1010E000C5F1AC2753E385DFF968DFB9830A8E0FBA
+:1010F000380A4D699467A9F98347F5435A3D135B54
+:1011000037DE5B2CC5BCB78FD3BDB7BFDEF771EE42
+:10111000D6A06E5C7010F8FB17D761E7BB04DD2723
+:10112000146E778D3C5DF52EC1D117386C77A957B9
+:10113000B5EFEC62EB2D701E64BF3F5B7B2F434627
+:1011400031B26B7F52ABC7B43A37B6FED5EADEAEEA
+:10115000759AC863BAD61BCE3423E7D15ECEAB3FB7
+:1011600090BCDCE77C65B8D7E67653118075B28118
+:10117000EAE4508D60A602F41E3A4CFF7312F2ECC2
+:101180002CEAC7879381FBE7CAEADA597E1BA36F73
+:101190000F8D14ED23FAB9D5EDEDEB46B91E97ECA2
+:1011A0006B0BF1D98FC67C3B98F29174B7F85ECC8B
+:1011B0002223A7302EF59BAD00CD5F4C51FAD3FD15
+:1011C0005ABFA427BD89FDCEA8C1176468B43BF9F6
+:1011D0003BA4D8FE62C8E0E0FCD4FF2B89BFDFF956
+:1011E00096901B1DC963CED59A388F01B59E7F5846
+:1011F000E5BFD6F798ADD2731C8F588471F9E1A67C
+:101200000F582E4BD3DAD57E4915E7E30B06DA5C8F
+:10121000FC5D9B52E8147D32AD0F3240BE99BCEBB1
+:101220007AF42F4D3BA3EB43C15BBD6FE87D79841E
+:101230006E71FEF175A29F797CDD20EE9F47CE3F57
+:10124000CBFDA887AB3ED6D9C7DC554774F630CF67
+:10125000FFB56E3D94DA69A2FE636867FAE4879091
+:101260007F1D8D9691240FD48307DD51FDB7D0BA31
+:10127000EC4974EFF5E9FC96F168F3B5B27C353AC8
+:101280008FF90EF338E40BC57C6726E8D4FA1C1AF4
+:1012900034EF852C23BD4F947A39A9AFDC53FF433B
+:1012A000B3B3F3EE21AC9F970C8E93A24F54358AC3
+:1012B000F2BFB6897D4B08EFB64166A380C3C43840
+:1012C000BDD82AC693EF201836D96AA92FD226890D
+:1012D000EF82664BCA6BF3F0DEC7867B57917E5771
+:1012E0002EE9CC23FBABCC0FCD91F0FCB37DBC4FF2
+:1012F000127F242C2FD253980EFE7EECB4C19F2770
+:10130000A1A9BCDD787416D58DA77BF9CF5286B222
+:10131000CDFDF92CAA1B4F9B853DBED3189CE5A79C
+:10132000FA090F233AFD7F92447FCA16324FC373E6
+:1013300092FA789FA1F3E9BB307ABF47F3A49F5A92
+:10134000BF346C12796258CD17FFCB2DF2D9DFB8BC
+:10135000C5FB3F0DFE9EDEC1E0DF3B04D95F3F3B96
+:101360008CFAE9E7365880F25BBC5F311445BE5F0A
+:10137000E98BB4501EFBBE59D499AE772C41F25381
+:101380005A5F75933B83CF49CD14FDD2D4FF44BF40
+:101390004576186A1D3C2D210ADF83C07DEC0EEADC
+:1013A0004747F5B137B9453F141E117EAF63DD00E5
+:1013B000EEB72FDF7FFC18F9AF32B7770BD13DDFE7
+:1013C000E018497E6F79E21EEE9B35B91D7C2FE255
+:1013D000CBF4A21F5A43725A6E0D719FED7A7DF5C0
+:1013E0009EE8EF58D8FA620EF7911D79A437DABD5E
+:1013F0008847933BAAFFADE11139E7DA76A0F5877C
+:10140000B5F1A9579F19A6F6F7E77ABA89AF07DCB5
+:1014100022BF6F3375DF8FFF5F559E5DE4731B0046
+:10142000F5FF2DBD30F6236C233ED1FBDF99480F2D
+:10143000F737940292EFF2E93627F1593B1FCFF1CB
+:10144000FEF11AF7748CF07C467ABFA44AF4EFB52B
+:10145000F5B024E4EA5F27FAA9CB771F39F624DE3A
+:10146000B2F88DDC428A07DAF3B17C46FE0EE3EF78
+:10147000E864F1FE0BF9FB0D9D1FDBB7FFA97C0DA6
+:101480000F12EF69C31B2F0F76E0F3CBE9BBB63C1D
+:10149000D20FD1FF82067D5F0BF9E5A7FE46D7F795
+:1014A0005AC0EFC72C6A3CB168CF0F34EA9E7F3335
+:1014B000C1F34FC27FA7EA37707FC080F737A8FE1D
+:1014C000A941ADBB63FB2F0DADA26FDA9066E63C80
+:1014D0009AF21F5AD7F29F951F8BBEE9CA0C9167EB
+:1014E000139E2467E9700BE70B57FBE212C67BE4FF
+:1014F0006382D99B309274D2BB82E3997C0BCA99E8
+:10150000DE87FCF52EB58F20E2A35B8D876E3A87D0
+:10151000F0CA49E23859A4DE8BF505F7EF46835748
+:10152000CD1FD4FEDBBA16EE3FFC1F5946A94AB0C8
+:1015300030000000000000001F8B080000000000C9
+:10154000000BFB51CFC0F0030947B3A3F20FA3F187
+:10155000E7B0A1F233B9D0D4B3A0F283D0F4A3E3BF
+:10156000762606064626FC6AF061116606061920F4
+:101570005601621D66F2CD0161235106866209069D
+:10158000062E20FD5F9C81C10BC82E01625F20BF2B
+:101590001D886700B11450FC029096156360782E88
+:1015A0000AD1670D647F1323CF4E4B5ECADC3C8AA1
+:1015B00029C3E6B2A87C013506064F750686891A4E
+:1015C00010BE1E92FC0AA098A01A847D481E98DEC8
+:1015D000807C5559ECE61E06CAEB02E5776AE0B757
+:1015E0007FBB0E2ADFC10C959F8B26DFE882CAD70E
+:1015F0007043E5EBB84368003560D6A4D80300001B
+:1016000000000000000000001F8B08000000000028
+:10161000000BCD7D0B7C54D599F8B98F99B93399CE
+:1016200099DC241398BCE02604881A6012121E8AE2
+:10163000781302461BC304D1E22EDB1D686B23CF57
+:1016400001ADC6C736139290204482765D162D1DDB
+:101650007C15156B4AB14BBB6A27402B55B70E164C
+:101660001FDDDA6E60FDB76A955F50A9F868F99FD3
+:10167000EF3BE74EEEBD998447BBFBDBF8B839F78B
+:101680009EC777BEF3BDCF774E9CA484A8E30939EB
+:10169000033F5710F21AA13FB9434F427A09A98676
+:1016A000E7801C9E02CF187FCF9E81A57D02ED02B0
+:1016B0008A4932839022C27E8A5A36AE13A71232EA
+:1016C00096847E31B99896079635103F2DBF75D513
+:1016D000BBF0DCB8B8B67EBE4648DE92BE2357D219
+:1016E00067201C1722E584DC474442F2A1BFD25890
+:1016F0008D97900EE8EC5242C6C4F2F45839147437
+:101700005A20E49B0A1F88889A4CCB3EFC75681EC1
+:10171000C693102749946145E18C6B787B7B7DE310
+:10172000E98376469D62F8FF7A02F33B5B3B720BDE
+:101730001B2F46FF3943F15230343EF693D76C2AC3
+:1017400013C08FF5BB9EC2FBBAFF95F1F249A55BB2
+:10175000ABA2F36D10D538D4277D59322D0756C969
+:101760002421D0EF55BD82433BFBBA6C24A4BECFED
+:101770008BF8159A7C43F05D47049CCFB83BDEDEC6
+:10178000D51520E4D4526F08E9432524277BF87C43
+:10179000FEB9959084CB545E5C2B4470BCD02F4A2C
+:1017A00069FBD86231F428C0D3B0280BDE1BF56E7C
+:1017B000E3E30CA70FA2C9148F32A70FB941D4DD00
+:1017C00053FF7AFA902F903E726F31B523E7BF5ED8
+:1017D00088F7EA73A78FBF763C635D87F3551BC21A
+:1017E00031EE8E5237A1EB7F6FFDA2CC489A7A235F
+:1017F000AF6B25F27BA081E8F134ED36C17AE23C93
+:10180000631679834FBA3E526A796FB6AC973476D5
+:10181000C6925DA3E0430A58E76BF4EB6C91B4B752
+:101820007368515645E84FE6FD6D5497C708D02DB3
+:10183000D036C587D45B9120943F4890841EE51034
+:1018400088B4EC54F5F8DD0294E2B82E067C4AA97F
+:101850006819CF51E8B1AC07591213CCF03B5B9C2F
+:1018600008870C6CC2E55D18851B831B8638330125
+:10187000CA775AD65FF692849BCAD54DA595C4BC4B
+:101880000E069D0A8241A7779E9B5CB18FB7D80A4E
+:10189000E739B7F3CADAEF8D3625A3B593C9EF0D53
+:1018A0003C51E4FD0A7E31AD7B9783EC17A611D243
+:1018B0005EB831066FBBE07FB3913E416891AEC226
+:1018C0004A15E889EC166480D36D9047301BEBED28
+:1018D000221AD2534CB895403DC91B463C19DF47EC
+:1018E000868BD35D4CEF2FA5FD5EC3BBBD86EB336E
+:1018F00052E5787BC080BB04E73154A6F3F8E0766C
+:10190000FA3F4A1FB10A21FEA830FC7B03E8432AB4
+:101910008F1AE0BD499EB804AB3C6BE0DF0E3EF38E
+:10192000C6A4E9941E93218980B8DAF08C4BAFA34A
+:10193000FD1FB95C88BB040E2FADDFC8E17C59CF19
+:101940002902FA4CD6B9907E1BAFFC2400E47B62DE
+:10195000FFAFE474FCDA38C7310407FD6FAD797E60
+:10196000F4BF313006F2651DD29101D7EA4A09E190
+:1019700048CE11E230CEA1DFFEE19ECB289C2F574E
+:1019800009219786F0FA081D2FA97F14184D4E10D3
+:10199000637C8DA8804FFBF8A9F550424B802F9BAC
+:1019A00055A776371D6FA5143A0C7A8C8C65FAA171
+:1019B000599D5407EB23098C3EE60979D8AEDDBB6F
+:1019C000610CAEBBB434ADBC6AA68A42AD84EF5B99
+:1019D000268D0A67DC313860A2EB96B78AEF39644E
+:1019E00082738AE00BFC3E83FE3293CC8475FED07A
+:1019F000BB28334146EEEFBD56A54D7610F249ABFC
+:101A000076CF21C7F0EF2B2512ED2B1FFEFE6A418A
+:101A1000E1F88839C13E33E69D9AA73780F4BD12BC
+:101A2000C42F25F595BBDD6DB259FED8E691C2EF06
+:101A300005B65302EB63F91AF05B64A100FDC8F42C
+:101A40009F1943FCB8724F13E33B1BBC9D81BF0D34
+:101A5000BC67E3E30FBD1B3682BDDAEE60F4D291C2
+:101A60002B863690E1F462AC8781C7735D8F2D823F
+:101A70001BF9C3A0A36671E9A8EB7E363ABA15E854
+:101A8000E892FF793ABA0FE8A8FAFF241D6DFFBF6C
+:101A9000484743E52BD15E58C8FBEA1FF8EF6F8338
+:101AA0007C7E5D9750EEBD3E87C9FFD7234C2E2626
+:101AB00049A4A71AF4C15109E554526FF721BCD4C7
+:101AC0002486791C81DFE8F847B9BDF46AAB42127D
+:101AD0009371FE458BE8F757AFFAA410F4D7AB74B7
+:101AE0006DC1FE266450D769FB5752656A8043D9A1
+:101AF000CDCA836DA763609F270556FE69DB693DEC
+:101B000086E36DD97825C5E742F895C271DD1C21C1
+:101B1000AD1DF6A2E06478A92316BD4AD7E545813C
+:101B2000D28BB298DAA188BF3041FFB094DA09268F
+:101B3000FBA2051418C8E57A17EA3F7BFFAFF079DE
+:101B4000DAEDB8EBE6D438405FB8169F940728FC6E
+:101B50000B170B0E660FC5886A825BD4051DF44017
+:101B6000788EEB21D07F619938D434F358A8BB2C00
+:101B700076D749AEC7285E9630BF452B6A9A325455
+:101B8000FFA4A17F6DF319892E8C7918E5C5734EDA
+:101B90001ECAA1709106213451033AD58ABEE233A0
+:101BA000F79F61D8373EC0DBEB4BAECD647410417C
+:101BB000BD6AD0D32F8E7DC33100EFEB72502E5D06
+:101BC00017962CF6E4B5F51996795D3FE7DA51EDF5
+:101BD000701231E1C144F7FE0282744AFE8BDA29A9
+:101BE000944E63B58311B45B8E0B5A3B2D67CE6D5B
+:101BF000190FFDDE2966637D616ECBE401B4B71673
+:101C000020FD67F03E339DD13F94805C9D289287F4
+:101C100034B04747F70B3A016F9387CA8E402426AA
+:101C200050BC6931B5521A05DF715DAC4F47AF1337
+:101C300044B66E9DB1456A290074C82A37B2EAA23B
+:101C400068FF19F5291D4F107361DC18BE4FD17163
+:101C5000379D176DE761B608C9BC78512619651E16
+:101C60001DB6F5A7E25F4F27675772F8C87ED6BF4B
+:101C7000219332B369FF69EA1BCF2EDEFFE990485A
+:101C80009200A71C56001E52564BCCFD10BD02CB35
+:101C90004E5E7405C34A31C5A7AB5C846990CEF231
+:101CA000877459033CC470BD37D3B52D34F1E5E6D4
+:101CB0003F4BE8E7AF144BDA406E6CEEBF89681417
+:101CC0001F9E609C6079CA8D0AE0693375B29230BC
+:101CD000BEDC47008E8C42FA3B1D274325718DF6F2
+:101CE000276B7D099196E57A12D2E9279F1A123C5B
+:101CF000D4FF3E102C6993E9FB8EA504E52301AFC8
+:101D0000DC443F1DC1577509E867090901C01D8101
+:101D1000E538CF8DE5CBBB8BE9FB530D32C60FC841
+:101D200017145EC3AFA77E86A78CE830DEE63C12B0
+:101D3000F7A21DAC237E9D2A5B3F6D7B29494CA7F2
+:101D4000DFB366F4C3F8B17F22A1896C48946B328B
+:101D5000972744A6F407E3B7A8A1BBD3D09F42229C
+:101D60003789D5A67556C3E8C7DAF196E924570333
+:101D70007E3B2A281FA4917BB78A22D2413CB468BB
+:101D800061499A71EE1435944F46593BED44F8473A
+:101D9000AA3F544F26891CE85A17002F241CC0F96B
+:101DA0006593D48F0EE51C3EDF31248AF582B37A29
+:101DB000FB81DFF2F5BE1AC0C53FFBAE3F82EB46AA
+:101DC0001E54C18EA5D0969EC9199217A073607E2D
+:101DD0001F8644F43B7C6242D569073E773288CE49
+:101DE000AF46302E97094D28C077B72A1D6097F867
+:101DF000494880EFBE901C33DBF59984962DF11491
+:101E000072B474069216E30FA2F603EBA865D169CB
+:101E100000CC7D7EFDE7E0376DF145D00FFBC4EDD2
+:101E20009F0A83DDE6F13F04CF4FDCE3E2E89F85C4
+:101E300098BFA5D07F40DE65CE922DFE4D966E2DCB
+:101E4000E7D8FCB0059217E799750DE1FE95DE30F5
+:101E500071CC105C14A226A0976D753201FFDFEBE8
+:101E600065F018F0E54877CD0478291CC7010E8A83
+:101E70001684E314F922014BEC2F23183FA5701DA3
+:101E8000B7C175DC06D771335C2D0A9BAFDD5E8C64
+:101E9000D592B22805EE3991FB1FD46E02BBF11426
+:101EA000795FAF07C2095F8D7AD6AFB2365E2589FA
+:101EB000C10A95A8480776BB91AED38716FF6B166B
+:101EC0002F6B4480795038ADDF4921D20B96259293
+:101ED0008A0B2F9F65E04BFBF26F28FFDD74D84122
+:101EE00080BF281F4BF0DDC1BFDEC4E3C3CBC1BF41
+:101EF000A6F8FB1A09FB01BE0F888871A80FC8ABB2
+:101F0000FEE926397942E4F6092CB1998F4928086F
+:101F1000725CF66E4C4A7E4483416FC2195CC710F6
+:101F200093F35E467731A2B4A13EEC66FEA7114F53
+:101F3000FD7AAFD51FFEC6766BF946B2680CC44B6E
+:101F40006FFCB683C469BF3799FD7BBA4EAF892A4F
+:101F5000C2F70D12DD0876499783D91BCB55224372
+:101F6000FC73F5BF7D67C6323A9F53200FAAC17E2E
+:101F7000A7E09BF4C88A40DCA9970F9F5FBB106A5B
+:101F8000BC4C18797E5D8E6423F8DFB11E07DA99A8
+:101F9000C41E07DD27611CD4D40EE1FD6AB7757E2F
+:101FA000679BBF7DBE84DC8BF35DB17B19DAE723D1
+:101FB000CDC7B99BDA9B69F49D57122C711F83AF73
+:101FC0000D7AB7F37795A4B1B80E558368AFFC2EA0
+:101FD00023DE8EEB1B9D09EB7BB6F6B3A17DEE8570
+:101FE000B79FFB578E3FEF2CED572B830B60BD3710
+:101FF000057AC3C09F461C6B0D89E905F457C7B32A
+:10200000EB6260BAA5EA05CFB15E21AD279D43BD65
+:10201000D2D1FB3BC1ED9217F63CEC043BF5832794
+:102020008E35821DB0F2DF25A2507A38B1C7471233
+:1020300068AFC49D60DFACA07417C77262C6B526D6
+:102040007B985234AEC3CAA77D6847ACD8EB8A37B9
+:10205000D0F62B7EF4DF5309C5C3890D833F2F00D3
+:102060007A7E426071D7D8C0D46BE9FB1532F9C7CC
+:10207000701A3A5A26317E7AFFC7194BC04E147631
+:10208000F77F05FBEDFBB2C365D2C74B24078E4B30
+:10209000EBA11F117B5C884F14187C667FC088778A
+:1020A000BFFFB8C0E0DBEF88BB01BEDDBB9C115AAF
+:1020B0006FEDEE9348D7F39E7ECA0F7858BBDF6A68
+:1020C000A7AFDD2D255C53F1790C9EA041851980C9
+:1020D0004FC6CF6BF6AD46BDB1A66FF349E0E7B58D
+:1020E000FB1D16F94FF1124A005EDF90420D50FEC3
+:1020F000E1F7FC1A45D57BC947FD8057DAEF322757
+:10210000A5AB85B3ACEDA0FFD3D9C3FBA39E21FA49
+:10211000CD6BFB36B1F1F65DF30790B76B09D35386
+:10212000063FBF07BFE40DD7339B246B7CEB1479CC
+:102130007906FA81BB73D2FACF865E31F87AE5531D
+:10214000A776C6E8F8EFEFFDE3CE189DC7AABF7CDF
+:10215000B4F34EF0979E77AB20AFD63EF19A9F989E
+:10216000F0FF88C4F6034E3CFEBDC776503E39F101
+:102170006B17DA81279EFBC3388DCEFFC40F3E1D3F
+:102180000376EA2DCFCD1F0BF8B8E599796347B3F5
+:10219000D7816EE32EF3FAC6B17F6DBF009B20841A
+:1021A0003CCB9FB6753AB84F4A4088E083375D71A3
+:1021B00017C5CF5AFAAEA512D66D35EA2B28DF45E2
+:1021C000F1BD664FD749696A3ABCC70AC4203C13BF
+:1021D000052408EB7EEDC2CBABE0E908694027643B
+:1021E00010F584BDDDDAA3747DA78DBC9ED49E70EE
+:1021F00002FED7EED9C4C6EDA3EBE91FBE9E1FC0F9
+:102200002FB387AFE741C91A673A45567D77077CF8
+:10221000DCC7FCCE91D673F533D78DEADF19F2E136
+:102220006C786E16185C5B25FD5712F0E3DE271FF5
+:10223000DB1160EBDC401173E2A953E36093F71DFF
+:10224000C7E057404E0E3EE752C1AE5EF1DC1BC800
+:1022500077279E39E2D4707F9A7805AA274F90D4C9
+:102260004F12F4E61A8115D63EE24BB8FC43EBB5AB
+:1022700026DE54AFF9F1FD317C1F67FCB026DEBFCE
+:102280005848B37E5EB984E9A7782EE265B59674A6
+:10229000AA5EEBBA0AB3603D8F2D00FA1B693D8D33
+:1022A000F9AB30FF99A6757D84F1F148FC7A62970D
+:1022B0004B163287AFF3096E57AC8D0B6FA45B776B
+:1022C0004236B0F8DE08716FE369A70BA76CE573BF
+:1022D000A3BD31FFB3F1F9D9E7757E783BC5F5B5FC
+:1022E0001D7FEF7F915E0F94C802D75BBDF5F92685
+:1022F0007DE776503D560C76673456503C04EFC669
+:102300003E09E5FBFBBB25B4F7ED7262CD087E7D8F
+:10231000C818677FFF549067EF1FF831A74746EF53
+:102320006BF61C73C6B85E889BF502F497663D2E6B
+:10233000E5FDAD7D367D7F6BF79C4CDBDF7BB2FE30
+:102340006580FFBDA483C46817EFF54969E324A540
+:10235000B2C362676DF4CD783393B693FC1E0DE67D
+:10236000DDBE417F2306F6C8AB0E82F6A31C7AC7FA
+:1023700045BFB7FB3CB8DFD2EEBF916826FDDD61FB
+:10238000C3931C0CA31F2D07C2556C2F346EF1672D
+:102390001DAA68819BC8B142D8E7FC65F11F64E8BB
+:1023A00017E2699A292EF48A4C3A73687FAFE842A3
+:1023B000A88DA4896BD9FA0FCF918866A6337DBC0E
+:1023C000688E2FFA0FDC8E718D16124D40BC891469
+:1023D00092BE474DFD3ED8AAB1B86B78BC688EFF5F
+:1023E000B9A251DD45E128BC452D01FF6DA4F18B5B
+:1023F000A2D67D5F63FCF53C1E41763FF1C413B469
+:102400003C1EBE616A45BCCD09F13795D937F3B89A
+:102410003CFC29B79F0F08E1436087E977C56490CA
+:102420007782D626839D51FF454C5E6EA2C77AED1A
+:10243000641EE8D5EFFE595A928E4EF773BA6AFBC6
+:10244000A71FE541FCEE01F76D85CC990D237C8536
+:102450007C9E878ABEE185EFFDAB6FF44EA6F8291E
+:10246000084A04E2350581655B2A60FE47A5905B5A
+:102470001BDEBFF1DCC9E37A0FB5AA28FF1F690D87
+:1024800062F9318ED7DDAD65F87CA23584DFF7B413
+:10249000CEC2725F6B3D3EF7B686F1BDFF8E17056B
+:1024A000A03BF22DD207F19A7DAD4BF0FB8F5A2362
+:1024B000F87C94CFA71EF0E2B5CC1FE331FB3BAE16
+:1024C000D800F118038F76BCD7D1A962FF9AA0017A
+:1024D0009DDF2E33F962C7EF38574208D3724B9411
+:1024E000E52BECE4716363BEFF2A337B731F87E740
+:1024F000C7EEC8F765D86FAA2F2DE7F1F110C8EF26
+:102500009D42786B05E59F178A6606CD72B8C8179D
+:10251000D9279BE8675C378BF7EC9099BC1A4F4E34
+:10252000F66752BCEB5F100DE8CE98EF811AAD1044
+:10253000E4E40141C0F5D6BF10499989EE8CFEBE96
+:10254000238B7C7F23BDDC1EA263260FB2AF92CB10
+:10255000C0AF3D453C2189C2DB9947F681DFD209F6
+:10256000740976F26F33304E6CF8375BF87A67BBDC
+:10257000D9F7536FF9E2207F46F27B36F2FA1F72E9
+:10258000B856CBE15FC9B8AF1C1758BE4302E398F9
+:10259000056C2A944E976EA56B45EEB9F4BD3721B4
+:1025A0003EF8C1336E0DE0EAA93AEE37E391AC9202
+:1025B000DF37EFEB18EFF34F17203EFF1F891C3377
+:1025C000E339BF79D009ED3B056D5B1DCCEB3509D7
+:1025D000F9AF53885F84F13399A05FD07953300EFF
+:1025E00072CF68E70B59F93BDB1D5EB20CE6DDEC00
+:1025F0000CC5D2C8A7DF666816F9E00A5ADB0741A6
+:102600006756B3B246E9B382303911927509FCB40A
+:102610006A12C1E74CA2E133CF11F90CE6319D8477
+:1026200035807343C6B8CBD8FEC1FF18DE14C7FF90
+:1026300041BC19F41ABCB46C1BE41F903B44DC6F22
+:1026400069874F263A5FE810387E1594E7053CAE5F
+:102650004FE5FF0B4501EC86C549D40C9483057CFE
+:10266000C3A065E024C67783E3088FBBC731DF6969
+:10267000C72A11FDF507DE12E290EC726A55C99186
+:1026800049B47D0DE573589FECAB4A33CDFB0C0686
+:102690007F3CA08433D551E2FC065F18E57F19FF2B
+:1026A000BC007268DBF8E7FB413FE40F08211063D0
+:1026B000F9DEE864904735BF7B3C0FBEFFC6139937
+:1026C000635E9F1DABA3E3014EAF2F3C17DE870B6C
+:1026D000E33780BC3B557F8B0B97D9CBF25E5AEE2C
+:1026E000D2B64DD6465E9F9D2DA3EFDF18F3DA7963
+:1026F0008EF332D6EB54FDE228E8713B9EECFD668A
+:102700005FB578D4F11F04BDE2C2F92F35CFBF30D9
+:10271000AA627E8BD1DE98AFBDBD7DBE43FBC0E714
+:102720009617D4E72039B0DE3FF87CDC0F5F2140FC
+:10273000126109E89FF2E71A806706894A8C1FC276
+:102740001AC87F839E778C792C0FF5821C2F4679CF
+:10275000778EE3759270B806ECB2901832DB2BC618
+:10276000B33D45E7098CABBAB81C1133EE0AA6C3DA
+:1027700073AAFF42CAFFA63CA62D84B078544241FA
+:10278000390F814295961D8749E5DDB4BF66079BE9
+:10279000478DCCE221D30F6BBB241657959A7C262C
+:1027A0003CF2FD0623BEDB49EE22AA067E45453FEC
+:1027B0005437F8F4E7CEC8B71D908717D430DFD36D
+:1027C0001188086C3F8EED0F15717E9D2F2D55C021
+:1027D0002E6921E17AB04BC85189B03C3CC6D72E56
+:1027E000631F8CF3B1CB4D783C38C8F89AF77390DF
+:1027F000FBA53FE5F6C9B3DC3EF909D827B45CF484
+:10280000F1E00180733FD8292EB03742F87D1FB721
+:1028100053FCB77812E01FEE6DD5B1FC706B333E00
+:10282000EFB9F5709B1FFA7FEE4707FD14BEEFB4BA
+:1028300010E4D71692FCC54A80372A627C63576B36
+:1028400014FBCDDF923C007B24BD2D077485BEEFC9
+:102850008AD68A6E5A6F6715C1F8C64E85E21DE4A6
+:10286000631F41F908EE12CA2F2E9F32D79522FF1F
+:10287000F654EDBD0AF051788D88DB2F06BFB9BA4A
+:10288000070656D2F283CD7BDD4086D9B9C9F52F34
+:10289000815E9F43E5AD06EB92EC5E40D7B7A06842
+:1028A00091328F96FD7D1BD7817EF6EFBBFF66F0E0
+:1028B0008FFDCF3EF14D2817D8EC59FFBEFDB7B1C3
+:1028C0007A2FDE0EF50A0ED379D0F653D563FD309C
+:1028D0007F8ABF81CDB49EA3CA9AEFF894613F74FA
+:1028E00012A4ABED3FD82FC2FC0303E11AD8AE19F6
+:1028F000F366B41FC8A7F01D86FF5DAB3A76413F73
+:10290000EF3A8A919E1E6839001175F29D6FBE8E56
+:10291000F47C70D57A02F4E05A25635CB160F52D41
+:10292000E41B2679E16A91D3C699DF75B8907E3BA6
+:10293000572D4E4EE2640A7C38EEF63A05E5C5CBDB
+:10294000D67C07637F781789BCEB40FE62FBC4B27C
+:10295000CAF6932FA148077B89AC15599E5FB8CF63
+:102960006D8E1F16AE16C3E9E0F8D421E3BC3AA27F
+:1029700075EFBC48E72BCFBC15ED52D26B1DDF18AD
+:102980008F8EFFA9C3947F22AB0C2E8D84441F1D14
+:1029900077CF5E4F3E944F470D7D95C0FDD3A72B5B
+:1029A000C4C4780ADFBDBD22E6A11CAC67FAABE760
+:1029B00016B6AFD5C3CB3BFAA801563CC44F863FF1
+:1029C000B023CAF6BFC91767D0BEF0723ECAAE7850
+:1029D00055C1FD8998EEADA1EFA71183DFC4A175A4
+:1029E00007FB658B950EC48E6C4B59A3C6BA39EFA5
+:1029F00018360D5365D4A74715F0274FF5C904ECD9
+:102A000097697C7FC88ECF1D9CAF7742DE0CF81D86
+:102A1000ABF6BA350AF7CF0C3A6989EAA0178BEE04
+:102A20000AC798DF63CDA3868C10C07311DF87229D
+:102A3000D25B15480FCFB23C5A631FD15168CDAB62
+:102A40002EB7E58317D9F2A8CF37EE52EDB4C7E31E
+:102A5000B65C84FA42F3A31CCBE7633D329BBAF920
+:102A6000D386C75F52FDF2F802E9F5E37AE673799F
+:102A700078CF1D5233F80BFE159559E638E9D54E3F
+:102A8000E6C71CFAAD0BE979679DC2F73D59BEA7B1
+:102A900083AF7B9353C37A3B7B6F55009F5D81125D
+:102AA00037F473F0D29FB8315F85E7AD1AF278033F
+:102AB0007D7F13EDEF3BB922EAA4CEC257F360BF8E
+:102AC000FEDE3A05F352FD19037D0769D97BA73372
+:102AD0000479233B6B124BC226B86E7732BDB6D455
+:102AE000C9F787B658F33A285F2C7542DE98378AC3
+:102AF000FB99A2C2F37B6D7EBF810FFF81ABC4E265
+:102B000029EC593205FC54262FE33CDF6A27D70B0A
+:102B1000867DB183FBAD5BB8DF6AEFB7B4593F8008
+:102B2000F6D92AB5124254F6F59DD06D959FC53160
+:102B30002B3F8C6FB1F2435134DF52BFA0B9C4F2C6
+:102B4000DD17BAD866B72498BE236C7DBADCDE09DF
+:102B500020472AA93EE6F607CAB791F47DB343DFC2
+:102B6000E004B9768E76883F231C85789BDDCEBE47
+:102B700087AFCF3FC8FA16E88FFA75F760BF725C6F
+:102B800060E787AC76C93038B99C1B05CE7F719E53
+:102B9000877D76B6FD37FBBEDB6D5278FB2BF439B3
+:102BA0003793E54976FA989FDF09F1555A7E8ECF23
+:102BB000EFFB4E099FFFCECB733368FD34FC6DC431
+:102BC0005D7F0A0939506F6CFAFC4BB08CF07B4189
+:102BD000FAEF3F75B27DEEB9E3471FA79F8FB3C5EC
+:102BE000A13FEB34C5F7BA9CFAF3E6F24127DB9735
+:102BF00036E8C2C8AF34ECB45B1DFA2173FDA1A75F
+:102C00005D5EB2FD915CBE9E3EC2F8EF674B966F73
+:102C10009A48F9D959E845FB277749C73AD10F793E
+:102C2000494915FC845C2EBFC96226378DFDF6EC40
+:102C300006AB5CB59FC372F17C7997FDFC0D97AF35
+:102C4000767A1C49BE1EB3C9D7545C7B04BAB2C79E
+:102C5000B55BE057667F72FB389CB968CAC8F4F868
+:102C6000CBD6C19E431387CAAFC0B99AB474C0F61D
+:102C700019FD07DE6D585C05FB795208645CB235BE
+:102C800031F7ED8943F22B3C27EB67100F0DD76529
+:102C9000A1BC690CFEA9E7500E95CB7AFFDCB74DBD
+:102CA000F34CAA14DA09A3F089EEF8CCCC5FDF0369
+:102CB000590F76111F6F2BC7A7DDBEEE12632EE8EA
+:102CC000F76332A00BC5A3CFBB03F136E0053A1B77
+:102CD00069DED35D4CBEFB67454310BF739D919089
+:102CE0000F5CE30D3B268476CC0C5716A3676F0967
+:102CF000EEEF51FF7DB01FD6C1CBF2FE0DFDF89176
+:102D00001167E57AEFE62C56DEDCCAE2CAAE83B381
+:102D1000DFD0683BDFCB0E0271CC4D54AE437CB0AC
+:102D20009BDAF9F0DD5F354020BEDE4EEB474CFE0E
+:102D3000787BA85685FDC68EF24A05EC0A694A15CD
+:102D400096E5E24AB5968E39A5EBFE79B9101F2FAC
+:102D50001531DF761A2DB79552BA76A938BF5F962E
+:102D6000BDED05FB2C1B82A9D543EBE9A88AE8122F
+:102D700085C711546B214723A5B7399DD1F70F4162
+:102D80007ED1F784C86C179DFF2FF9B9AC2E67B4BC
+:102D90006C3DF84372CC0571C01685ED4F003D7453
+:102DA0004C1F82BB96E3D7CDC74DF9477C3D3F967C
+:102DB000076290F2DA2592E674EBD3E06272AE43DA
+:102DC000D5D551E949953FB3E455CF61FCE40C50AA
+:102DD0007A32F1F548F25A728517BB7287F298E899
+:102DE000C2AAC8A784D981C6B99F3F38F52558CF54
+:102DF000CBF04A0AB3914EE9FBF99EEA0B91FBDA5C
+:102E0000D63ABA6E07E6541DC17856D2817124FFB6
+:102E100004F28F663BE4251706E3E893C52DEFA681
+:102E2000F4119FCCE21504E826832A62D89F2C1265
+:102E3000E30F1503BCBBEA27D0FEBAE489D4521FC6
+:102E4000EAA7A688F9033DB59E66B35FF0C70CB646
+:102E50002F739BB7E619171DA7DC1BAF45F30BB209
+:102E600036C7B0735540C797A8644010410E860915
+:102E7000D39B2185C54DEB543847259008399331B4
+:102E80009A7EB49EB77A428E6FF0003E022C0EE618
+:102E9000DB2E6092A0D4A7273C2012BC8BBA5CA882
+:102EA000C7C365304EFF0C0FF1D2FA7FEA77E23EDE
+:102EB000789FAF4006BC3E2F2EFFAE93CE77F0D763
+:102EC0002ECC7BECFBF3C59897DFE7BB6C01C8ED1C
+:102ED0003E811CA6CA9ED49C2EE049882403F6FF9E
+:102EE000FCF37402FB30833F2368FF39822FCD7DD2
+:102EF0007B3A4E3C439C45DBB949B79BB60B7DE61C
+:102F0000F9E80A4A577BBD95F74D2343F11623CEC6
+:102F1000529711D90974D139E63F9B816FBA299C28
+:102F200012FA137A10E0AECC15312E4972BDF18938
+:102F3000F47DCDE1401DE495D6C8159832EB9FC7CE
+:102F4000D6FB379EC86E986F9DDA549745EB571D98
+:102F5000D550CE2E08AE3B04E5196FB172A793F1A0
+:102F60000BC4918849EED69C1E87F3FB21A7938E54
+:102F7000A09ED48551F9C6761EC19A4767A603C89C
+:102F80007F37D141C461A68359940EA698E94017B2
+:102F9000CE870EDA50595F08FFE86FD40943F1BCC1
+:102FA000E17CB04EC92E1FCE2F061C775765074017
+:102FB0008E1A7CA1CEBC0BE5AA6B99330CFB2D06B7
+:102FC0009F18FCF1A9DB817C48F9A411F87DB15769
+:102FD0009B9F8E4FC00F31F3C3B523F04D23193C97
+:102FE00014A08D1A6512CBA4A2E497B3DF291D6744
+:102FF000E2033BDE1AE708E4B8459EB1B209AF6AC6
+:10300000EADCA374EEF87F55D63A03263EDC48FD91
+:10301000103096BBC51001BD52ED5DFE29D0A5DC78
+:10302000F08320F8830E57B819F36967BE9F7123A8
+:10303000A5CB3F8D1135987CA7B6FC69E4E7373303
+:1030400008D8273D3356603CF84F3745C6839ED895
+:1030500044F17F1CF5727CAC88B9990363D93EBCFE
+:103060001664CF4890BD27FC7B9C97755E6F00EB84
+:10307000D175B6C8C71E37A3F71E37D3179B9CBDA3
+:103080000AF0DB60B1A29AF3A0AF90981D5BA5F0A7
+:103090007DA92FDA35881B5629ACDD7DAD7D687F93
+:1030A0006C6ADD8FCF9C8638813C2B4F594C83FD59
+:1030B00070E52FF30407F0F1C56CDF16DEB799EC6D
+:1030C000AF710AF36395BF4811E04F65434CCB36AF
+:1030D000C959451422E9ECE8AD6E99B5DB40F0BB67
+:1030E00072E05F719F3BA734247C1DCA1B7A49881C
+:1030F000F6E34EB0F781525DF89AA9DF40439F4551
+:10310000CF35D225C8AC44EB09CFC1746A1EDC1799
+:103110006B0CD4BE2B4F1D4E47F073DC440F06FCE6
+:10312000C6FEEC2DDCFFAE2B5190FF3A5B9CBB4002
+:1031300035372ACC2EFA38503BEA3902D897A59673
+:103140001BFAB9F084FDD9D864B63F0B65D89F85CA
+:1031500027ECCFC213F667E13BECCF42F9FBAD3A67
+:1031600096619F16CAB04F1B9BCCF665632EB62F97
+:103170000BCFFDADCDF8FC496B14BF3FDBDA82E528
+:103180002B5CCCBF2165B120D8CBDDB73B75C8BF68
+:10319000E9E47470502FC909D1757507589CC0FDBA
+:1031A000F2BD780EDA1D1471DF7563F05EF255FA28
+:1031B000ECAEF675431E8CF2B4179F6EF93EA2E199
+:1031C000BE6CAC1922A7AB94E97532B5134A83EBF8
+:1031D0006AB36979BD32BB03F21127696DA1E5EAD3
+:1031E0005059F355AEF881A93CBE7C97ECA1F56F20
+:1031F000EBBEAC03E401C001FBC86DCADC3AB0E32E
+:103200001225D45001B956EC8C033D7F0DD66B22AC
+:10321000C0CFFCA92F91F620C435C66BCE4AE0433F
+:103220005A3FC1E8FFDCEA774210387778BBD1EA31
+:103230008955E7548F48A3F407DF85D1FA21ED6A59
+:1032400092C2BE196406D8476EB6FFDBED60FCDFA4
+:10325000ED66CFB739DFFFD85D3BDF4DF968BE9B28
+:10326000F161B73B5C0FE75006A788A18708EE9B8A
+:10327000C4DC7028A1A5F857705EE8D6176502FB7C
+:103280000A0F72BE9D38DEC7F4F49D0AEAE92BC727
+:103290003FD5914DCB131F0E8540EF6E26210FD0E9
+:1032A000496C8B88F9294F564DC86EA2D52FA97E3F
+:1032B000261BF4CFA70AB377E3DCDF68EBBC713CD5
+:1032C000C4FFFE7484C9BF2739BDED7224A3B89E24
+:1032D000D55EB457A8C380F6485B50C6BC22318F78
+:1032E0003D9D0EF5EFA09E932AFC1885C7F9E7993E
+:1032F0000AC63F4EBBF8BD1749B4539CEE889A45A9
+:10330000DFF7C644E4F776D51307BB7AB3B712CF1D
+:103310009BC6CA653C77B2B95C64E7657CD7C7C118
+:103320003ED9DAEF66F2C1AB605E69BC7CDFE1DA00
+:10333000003C4515F83DAE2FAA47BCABA28AF9A9BF
+:10334000F437FCDE1CC0732A1023C7EFCD2CFEDC43
+:1033500039E6B397A641BECED7D510BF8B00F3BFD9
+:10336000D1E412619F68F04006C0F30FC63D06032A
+:103370001B3268FD8EE56A08D661AA5A5B0FF90513
+:103380009D6A2DFA391953EA9465288752E734F07B
+:10339000BE8C8E7219F38BE03BF025E92087E09C10
+:1033A000BCB1FF9C915529807DD5D980613E38C73D
+:1033B00060C937EFC8BE1ACF27498DD9086727D112
+:1033C00015A81F6B9051FF15789504EE3F18E7ED97
+:1033D000E1E88529DE90B3CA7A7E23AF59B69C17FF
+:1033E0001F1BB1967379FC20D776CEE34F8AB16F5D
+:1033F00066C5937DBE398187B200DE1C38E0AB0D17
+:103400009FCF7D81CA26986781EA41B883EA861AF0
+:10341000905F6349B40DE8EEBCE1B5C139B5BC239A
+:1034200009EB3E559389A641BC7D7003F4BB99D34B
+:103430007977B1551F3FA848063F4E75E7429C512A
+:103440002431D3F810878C99C69BD09D6D294FEC01
+:10345000CDB7D49FBCBDC4F2FDA2F8C596EF97ECE2
+:10346000AEB494A7F45D6AA93F6D7FADA55C91B839
+:10347000DA527FFAE145967275F2EF2CF567BEB924
+:10348000DCF27DF6C00ACBF7CBDE596F295F3E78C0
+:1034900087A5BE61AFDBF56299FBC2EC7417DC1F38
+:1034A0006189CB5AFD00BB1DAFFCA55DDB0072CD71
+:1034B000EF44FA96418FD3F2FADB991FA5CC0D6940
+:1034C0002057C671395AE4D3AB418ED6F815D407CC
+:1034D000B297D593BD0BD0FE18B79DCAA3E9606D16
+:1034E00092D4F70C90CBADB1B9A5A678935BEDC59E
+:1034F000335B35FE7A02F179A3BDACEA2402FD40CC
+:103500001004E2E7D44B857A6E8DB637CDEB795156
+:10351000C4A3D183D4DF7BC8E4EF8DE4DFD9FDB948
+:1035200073F5DFC689C483E70D8470149EE5D1234B
+:10353000B590264CFDBA1B807E7B9CE1E65DB4DF36
+:103540009E120FEE5F1A7E5D77711FF2C560B18C1F
+:10355000FA85C85AB9391ED7C1D737437912FD4AFF
+:103560008A7794B706DE370B03F176903BB77B5032
+:103570001E8EFB2FD7ABC05F4A8952A0D0F7A18324
+:103580004E1DF6B7EFE3782D512B6A21A4541A6C27
+:103590003A00CF491AB533E8B3AC6CDB0178DEEA08
+:1035A0006679C217877E500BB24499CBEC3F79AA5B
+:1035B00033BE81F623A9148E347E85F194FCDBD9C9
+:1035C000FE45A9FC7BA037B0EACFD029D4642B7884
+:1035D000FF8C1BE840C027D28F3BE045BDE186430E
+:1035E000AF5096857886C0EC53D89FABC9DE8EEB82
+:1035F0006ED8AD60CF46989FDB01F41568B0AE770A
+:1036000086F27DC45387C0E2DEDD59DACBB574DCC7
+:10361000EEDC926C88B1425CA4C9246F7AB8DEFEFD
+:103620008A47E4F96F4CDEFC05FAAC1EB27728FD40
+:103630006F1727007CBD04E496FBAE5E02F4EE56E5
+:10364000E96AA25D1FD3C2A84F99BD7B3387A9AE9B
+:103650006409EEFB7F14A844FBD6DDF27C5AFCB96A
+:103660000724A24F1F19AFFE493B50DF9312A70654
+:1036700076458BE6D477A59107E5DC0FD934CE38B3
+:10368000E7CACEDB76737C18F1D0549C91C7D38CFB
+:1036900038A3D1CFCDB9956347B3C7DDD4BF8C98DC
+:1036A000E0DD44C701BC747ED1548F7890093BA7FC
+:1036B000FBE7F25D904765F849E5DC7EA9E2F81D7D
+:1036C000E724E827CC83B8490E78B55FAA07BE3453
+:1036D000E22CBF03638BD60BC588C4E26A0E436F2E
+:1036E0008967A621CC9A7306BBE28BE5A332BD465F
+:1036F000FFED87F36413BAADE73527F65ACB93B7DE
+:103700005BCB17C5AD656A351F05BB006C348C5BA0
+:10371000ECB67E6F32F603EAD8F932858E7C86E904
+:103720005FCB7D3984EBFF7CDE4F515FA206C46B1B
+:10373000E12D56BD9ACFF57CBE4D7F56FA248C27DD
+:10374000D41C0E1C02FBD188FBFCC6A359EE7530BD
+:10375000E2377679EE796B1BA15FD02F8FB8581CBA
+:1037600003E2C39F14F17849218F978CE3F19222F1
+:10377000162F7148DA2B4B05CC0B3DE9463B233A1B
+:103780008DC569D839AF0FEBE59F091A1B2F621A57
+:10379000EFB6B2D8950C0DF13CA867C44D8CB8803B
+:1037A000D7A7CF073EDB1C7A357A90D249EDAF5DC3
+:1037B00004FA992FBD7CB815E45B918CF9DCEACC56
+:1037C00055DFF5401C12BED3726DB13616F9E01705
+:1037D0000E8C0F7471BA36CE271A7116BF87D94571
+:1037E0001E8F60EC037978BEBE07ECDD4B76535A32
+:1037F000B4E83B16CF33E27653FAACDFFB8890A3F4
+:10380000D2759CB6242E32FB4AF7D698F21D2FE6CD
+:10381000EB367569E2DEA5B4BC87C42BE11EBA0A9B
+:103820004E1FA143D673B1638880E7A2C61C9542A0
+:10383000715A7FEAB3D6EFE5B673B317DBCFD1DAAF
+:10384000F6857C1239B98C8EB7458B0A2047B72C88
+:10385000A5B63C2D4FF6F0FDA2496412D0E17CC91B
+:103860001B4A007E5F93707FCB756CF21B90C7483C
+:103870008EB07C247502CB8B545F92504FA919A453
+:10388000A2C23BB48F74FF9910817D1123AEF50461
+:103890005D57D02B7BA85F5EEA003F5BC5721FF5CA
+:1038A000CBA1BC97FAE5F0DC47FD72780FF94850E0
+:1038B000DE4FFD7278FE84FAE5F0FE59EA9743F98F
+:1038C000366FCD7C4F2EEC1B9521BD782AF629133F
+:1038D00028BC5D8A4305FAB0CBA19A9A9B95C59402
+:1038E000A4FECEF514EE5FD4CE67F9D3F33D4FCDF1
+:1038F0006B93ADF13573FC7128BE362018F1350895
+:10390000791EE3FB0CA9385B84C5D9CEDE8F6EF43B
+:103910008371CD61FDF0F8E607B7FFE763EDF4D3FF
+:10392000EAEA7BBB3D25709E234ACCFBC7C6390F14
+:10393000637EABF7B5619E8C33EF6814D6755F95E7
+:1039400017EFFA713A222AC85BBB3F67F871767BA2
+:10395000DA78DAF59B8FDB1546DCB4C741307F3A65
+:1039600026507B02EC8BD6F8DCB71D23C7535FF7DC
+:10397000F0734536B9903A37C0E33E2EB066E93C65
+:103980009D02C707CF6747D158C2E27AE6B8AAA717
+:10399000348E87D53D5E1DED3A81DA7B68FFA991B3
+:1039A00020C4D136C2398134F37B98F37B5B9E13FC
+:1039B000ED8D8D790ADA497585A120B46FCF9B1101
+:1039C000349F1B30CE351CF2CD50064CFDADF79523
+:1039D0008CAAFF24AAAFB551F4B5E462E77ADA0FF6
+:1039E000CC56E0BC46B7777912FCE8EE6000E3EF16
+:1039F000FD793330AF27553F380BCF75485E660FE2
+:103A00004B4105ED6119E65F3E54DFA8D7EA6174CA
+:103A100042D919E38B6E6F2FD673C961BC4FC215A3
+:103A20006079772E95EDC7794A45A298E485316E85
+:103A30008B87C5A3BBCB232AC459BA8332E6E97767
+:103A40006B9588E7768EE7F622C39E08A11DF36F7B
+:103A50001CCF463FED3C0ED0DEEC447B2EDC92A525
+:103A6000C2D52F5E5F780FF073B7778302FB92CEDB
+:103A7000BCAA51FB3DC0E5F6C8FD568CA99B8EFD46
+:103A8000FE1BF4EBF42D57A15FC708E7915EE170D0
+:103A90005EA8DD6ADFC7A3D006CDF928F6A78FDBC5
+:103AA0009FF676ABCB079CB0EE9B1EB19E5F761067
+:103AB000769E6BCDFE75C8E73D7212EDA89E2F84F1
+:103AC000B4E7C2C66418FA2CE5DF5BECA002CE4F67
+:103AD00005FC3B901AE88B8A84D56E997ED85AAE45
+:103AE0004E5ACB33DFB4DB41FA6B60072DE6722F01
+:103AF00049E53D4B861994011FE158BC06E06E2252
+:103B00007D6D9027E1E071F2C55CFF2DE4FAD19B59
+:103B1000C1E2BD05CD1E8BFF49F8FD7F85BCFFA22C
+:103B2000BA43EB3A40C8860DBB4A43BFB5E8AABDCD
+:103B300035282E6DF655936E3DDFBFD0663FD9ED2B
+:103B4000AC1A7917E6E9E6DBE21AC67E2ECC13EE54
+:103B500039B08F7FBEE31AFD411E16C837E3FE174A
+:103B6000BC6F98B62F92134288E2291FCEE7507897
+:103B70000A6E21FAAE34747C395FF761788B5D810F
+:103B8000789BC7DFE57BD9BD5DF975525C2B86F369
+:103B90000E7D680F2C5A45E78376F819CC8331EAFD
+:103BA0006767F5F5C3BEE78E0681F9A53182768D8C
+:103BB000B1CE3BBCEC5C61D3E5425C84F6D1121C17
+:103BC0001FE12A195A5F8AA7E30C4F2CCFF0DA7A4B
+:103BD000EBF9C7269BFD62D0C342DBFB010FDB176D
+:103BE00037F8E083D96F4E1A47E1582DF4D6674C69
+:103BF00038777D69E20FC719E043F87D0C4B7D01F2
+:103C0000FE38A0FC50057E7F3E6BE0014249B229A0
+:103C100083C4EA28F1FDD433788940CB4B363FDDAD
+:103C2000D95D04C7BA079F0423CFD5B56F7EBDA960
+:103C3000ECB93B81E5001F07B616D97A9BEE83A14C
+:103C4000A8DB0979F360E7EA649B04B9B6A2BA2D50
+:103C5000543CD42E1BDA09A3B40B936D729A765E92
+:103C6000A31D45D746B8EF89CFCBC3BF8B1C1EF32E
+:103C7000F832E04DD5BC78BE7181AC425EC65F0BB8
+:103C8000C798B3CD3B42B639260C6F47C16E33E0BF
+:103C900017D3C31F87EFE6F11DA3C0FFB7C6C7D96F
+:103CA000FA73F2EFE70D1FADBE61CCC8F305B81C87
+:103CB000780F91E6154DFD6CEDFF14E3E2F20D0473
+:103CC000CF2FCA0E5D85FDBC72F5DBE8DFCB5975E1
+:103CD0002AD8019B6819EC804D7DBD18FF2E2FBDA1
+:103CE000B71B88BE3CE121200FA610356B0FED7786
+:103CF0008A2AC3892B225F7E4884783AB98660DE9F
+:103D00004866BF87DD1B547CE9C3E06F656529B851
+:103D10009F919135E36166F4B238B3017F46CDD10E
+:103D20005A88BFCB4D2424005C429CD400935D4450
+:103D3000707FC3A3EFBB0DCE1B1099E927BC3B07D7
+:103D4000F42A8FB78F652443BA9D6A13E6AFBC2867
+:103D5000631C6B2C5C0D4689B2BC3C7B1BC0531EA4
+:103D6000A11D08003F8B974D8988A104EDBFF22467
+:103D70006B47FE839D2BA1BEC99267BC437835E497
+:103D8000CA581E870F2EB5C6A9C9209D336D5FF98D
+:103D90001F8B1E8538C59861F29BF9ED1E0E67E6F4
+:103DA000491286FE030D56BDE1E179D71EDBBD3217
+:103DB000953E87F53E68BBFFF0AD30EA0117092953
+:103DC0004EB42F96A2DD60F8253BA022D8E34584AF
+:103DD000E5E7DBDBCF60ED4990F9292E0F51944ADE
+:103DE000FA7D8547C77C43172D533C0A4EA2E4D188
+:103DF000F7F9228BB7B4094486F2D07809CC337036
+:103E0000295FEA00FBE580321DEF4B33FCEA763593
+:103E1000847910A4ACD662371BF95EEB2B4AC6C27C
+:103E2000F7CC31A9B8930A74B93EB714ED687FCEC8
+:103E3000C0DF839CFD6CB37F81723995A39087713D
+:103E400029E523AF7B636C0E1DF77401D14CF69905
+:103E50004B8E629CCD757A9CE57DA2D57ABE5AF7D1
+:103E60008A75304E9197F1610D513BA05D0DB19E69
+:103E7000A3769DCEB3D8EB43FD175ADE27A85D632A
+:103E8000BEF767E4FE33885666EE7FC208FD4FB288
+:103E9000F5AFA6ED7FA8DF1C4BBF9D328BBFC602DE
+:103EA0009EB4F750567B6B4BBCD523EF0F5479591A
+:103EB0005CB32B18C5FD815A42199FD2CB155F1CEC
+:103EC00097D8F95E82F61B29B4EE0FD4723A162900
+:103ED00065001D5F215BEF339E4BECF71B5BEDA292
+:103EE0003720B845F125FAAA92B84FF0A957033FF9
+:103EF0006C24BB39D94A303E3D3763E066D807BFF2
+:103F000066CB7867E72CCC67467FFEEFB7542DE091
+:103F1000F781B2BCE680887809D78EC5F35B463F4F
+:103F20006127990872312CB23C08FCA1E32773F396
+:103F3000310FD13EAEFDFC7B932ECC2D35CD2B0920
+:103F40007985E6F1E615EC924CF308BB48358EC74F
+:103F5000EDDDD478632E6CBC233C9E658CD7B4C059
+:103F60003ABF26A78AF36BE27C6C8C7704E697064F
+:103F7000BF671D8FE74DA6C6BBD23ABF26978AF30F
+:103F80006BE2F7EFA6C61B7361E319719D2E6734D0
+:103F90000A7438527CC788EB5CEF7AD212D721E4DE
+:103FA000C97935A5846C1398FCD8E9ADD90874F1AA
+:103FB00051C3FA32D42BDCBEC67B56A93E5E2833F1
+:103FC000781B0BBDF136131EE1BC8D3E19CE49287E
+:103FD0004477B173133A9EA308E2F3216AAFEB98DA
+:103FE0005F5286DF1F6B0D617977EB2C7C1AFD9495
+:103FF000CD62F7815D3447486BB7BFEE65FEECB626
+:104000003CF586AF817EABF1B07CDF599711DD6462
+:104010004753C3FA009C9FEBB99E54808E9CB49D7D
+:10402000C11DA81B1387F5F7541C4AB6421C5476D1
+:104030006898EFAAA5FFFB0647BC4CDFB85CAC3D17
+:10404000B98CDD8BDA983A17D480F9478D0BB330F1
+:104050001F61D162DDA752BC2D1684D74AB9BE8339
+:10406000F350D7F1A5B6FB0B01D03C74BD02BA14D6
+:10407000877BE3AE2B7C798940FB0DFBAE453F236C
+:104080004C1B66D37EAEE3FAB6E6988B403C82CCFE
+:1040900077A2FC5ABCD8EA176C732754B073B65594
+:1040A00004481B6DB7A8C1FADDE5627C15B6DD0BCF
+:1040B000D378967B628C7C5B3B7EEC71D397BCFCA7
+:1040C0009E181E1F3D45CAF1DCB991976B6F6FC4F6
+:1040D000413700AF835C7532F9309C0F183C7FE4A8
+:1040E000727047EB9B184733E0CB97E302C8FB8223
+:1040F000E6372D79EF14B168541BFB0444DA538181
+:104100007AD8369F1DC29EBCD1EE89CA27F2EF072E
+:10411000CAF8DF331086CFFBBD61F39EF34A29490D
+:10412000C73F2C1EDC78580AB569437831F0F0BFE0
+:10413000CD47F773BCBF32EFE32AE607165AFE6E8F
+:1041400080717EEBDA545926B2899E17AE70EACCA4
+:104150005F1D2C07BA3C7A794688FDFD0B6E07255A
+:104160007E2D821DF4D7F7AF1759F29A79BF23AD90
+:10417000973D9FD2740E99A4F68D20FFA52D14446F
+:104180007B609D88FB1FF951968F07DF8F5BED5693
+:104190004B3E5E7BFFE302C40D1F80FC44D339BB62
+:1041A00082E63EA113ECBBB6388B4324683D0A7708
+:1041B000617342E8281FCAFBB2CBF5C255D67CC159
+:1041C000CE398BD53D1AE4D5D4F6C285609BB6B303
+:1041D0003897513F15EFE2E7511D244AE0FC85E492
+:1041E00065F1E620BFAFE36CF9BB9F8831B5B81825
+:1041F000F276E34A0D5DB7077322753E885F062AA3
+:10420000A3BB803EE510E6792F6DB9330C714235C2
+:10421000277D1C7C29B70F16FA585CE52D47A208AC
+:10422000E2E6C99CDA85BEEA34F55BBE85FDCD1DAC
+:10423000E11EFA66DECF03627A79B08C7FFFF26A04
+:1042400011EF1772131F9E577597F6CE027C3CB084
+:10425000664728DD39CB196A246286C75DCAEE0736
+:1042600020A46F36CC73D3E70FF63D4DE79DFDB923
+:1042700017E56CB6C4FA35B56FF6E50E6FFFFCA70F
+:10428000EC1CF2F3FCBE75424AAF04BFB1275526C1
+:1042900031B88FBD278B976302FB9E2AFFFB02F884
+:1042A0007B4A3D40A394F8FEE8FBE54688C3F60848
+:1042B0008413EB2B0B206EDFC3EF773F0CDF69FB22
+:1042C000B957BFFFF056D007339CE86FF6707BC735
+:1042D00080EF031FCBFBF9C0C7F87D247CDECDF156
+:1042E000E9057C06CE0B9F77A7C3C755017D33BC7C
+:1042F0007743260805C1FDB9720BE45BFF6B2B0900
+:104300007F8DCEE181D0BEC7E14C116D7F6FBAF6D3
+:104310003FCED1EF8375F2AE3E8EF3F3957A4380B4
+:104320008A4D3309F693068E07D2F563AC6B288B62
+:10433000C93977267B6673FB5272258390BFA056DE
+:10434000DD7FB34AF97E63717249BA38F1E37E6664
+:10435000F7678D10174F70FC5E991D7E12E0EE50CE
+:10436000EF457FCF299030D4DF346B8008A676FFED
+:10437000E567F8A670FF10E076CE66F756FB28DEFC
+:104380002141CE57C5E0DFA41D2590FFEE0B1EC5D1
+:10439000BC565FD500F23B8AC27C4657E00F2ADC50
+:1043A0007E4BF8FE7B01D04DB664D0DD37BB806E0E
+:1043B000A4A1F29550DE95CDDAFF3FFF37BBC05F79
+:1043C000DCE9A46D400EE63BD1BEB1CFEF250EAFC8
+:1043D000ACEA3F87F90DC3A76BE0E1ADB47DCF44F4
+:1043E000767FCB5C31B9E4AB4097577BD13EA3EFEE
+:1043F0009798EF1F3BCDE9ED34F7E77B3E55F0BBD7
+:104400007D3D46A2D7810BA7D78111E8F5988D5E37
+:104410003F26E9E9F59D74F283D2EBBBD0DE8E171F
+:104420007B5922FA76D857963F5BB01BFA93BF347C
+:1044300067FBD3F4297DB62586AB19122CE7998743
+:10444000E47DE4135FEED03D03C6DF2DFA27208420
+:10445000DC34FDCE9CB11DE4D839F42BFAD3F49BA7
+:10446000F43178E75EED8DA4BB376E8F9FE5C7FF13
+:10447000C8CFEA8DC4376FF9597ECA487C73D09F84
+:10448000E29B6C80E36C7CF311AF4FD721DF7F4E52
+:104490007CF36D7CBA4B19DFE0FC2F1DCE3724B6C0
+:1044A000AC0BE4F1C662C61797DCB306F922C54728
+:1044B000B156FC2E0D95517E1B7CF4E93DAD58DFC5
+:1044C000DEDE3FC23D819529FE0F57C03CF44BD440
+:1044D0000E763E6900CFE1EE2283FD2ECC13667985
+:1044E000B99E584C67E64192C07D1297723CEC042D
+:1044F0001F0DFCA0193C9E2527C922DF707EF655B2
+:1045000025AACCF7BE1CE1ED3D99E11A187F1719D9
+:10451000C0FB9A465AA7051CDE33D9FA027F1A3A25
+:104520003F9B1E5AE967E7E556F27EB23F57A2600D
+:104530009FDAF97DEE9A9FBCFBD828FD34F3F61183
+:104540000EFF05F07FC49F867F29FF2F83F726FE8D
+:10455000AF124AD2F27FB33FBDBEBAC9FFB7E5F78B
+:104560006FA6E3CB463FE3F7B3E17BBF9FE9FDFDD9
+:104570001C4F178AEFFB79FB7B2E1CDFF78C80EF3B
+:10458000ADE788EFFBD3B5A7F8FE173FCAFFBD081C
+:10459000BF4FF362BCBC7B26D92794A485E3BBE65E
+:1045A0007E148DF54379EA6381D2FDDCCFBA43E90D
+:1045B000EE45A2ED1E4BD76E815F3592CFD7E1FD60
+:1045C0005F5FF2E2BE02D58F4FFC8DE9E047E9E87C
+:1045D00060AEC8E490E2BFAC0BF4FD5FD1FF817424
+:1045E000FDDFC5E5FAD9EC82D786EC825FF8AB87B0
+:1045F000CBBF5DFC7CB2AC46927E8CDB0F5C05F2DF
+:104600006AE71DD902C4BB0AF584007EC2CFB91E79
+:10461000BB022E0DAA1E6AB7534E08F0773A7646B3
+:104620005501CE4B99FAFBCFD1FAB3C341E1FBADB3
+:104630001FE59DFE3B782EE0F33B5F3BA93F5BFF10
+:10464000BD1FF54FF81D78EA93AD72DB988718EE21
+:104650006579B6B3D2FF5DCB9FFB64AEC7C227CDF1
+:10466000F2FFDD145DB1FECE57FF50F83EF333BDCF
+:10467000F2453AF8EC78391B9C17F965434F39330A
+:10468000D3E8297B7F869F6DAC135C8B618EFBE446
+:1046900064A6F47736F4E7ED14F11C552397278DC3
+:1046A000B3B2B8DDAE7AA0FF07781CFE8155F7D60D
+:1046B000C0BEFAAEBBD40A40417E33D37BDAAA71C6
+:1046C000185F2DCA142CF933C633D5DED97711FC07
+:1046D000BD083A6E318C7BC51C9200BF3113EC06CD
+:1046E0008C57A8F8778DB35DBD4188CF6E127A974D
+:1046F0002C07BD7A95979D8B092E3ECB7D991B2C5F
+:10470000744B825567A9DF86F5D58C5EBC3FE59C6E
+:10471000EBBB7AD3DA59B599A2E14F5C9E593D0AB9
+:104720005E83018C7B19F81D3E0E5BBF9A705400AE
+:104730007CFBAA041552EF7C944EC05E124B9398FA
+:1047400037754D15A31742FD92D1EF5FD968C0159B
+:104750001E75BDCF112EA3DEC8E3F17AB6F316A9FC
+:10476000BF3FE665720C2BD2F2878773D2EE2B180F
+:10477000CFAE5655872B923F54B54CFCBB1DA9BC00
+:10478000EF507091EF7FBEDED0BCE22C3E6AAB9F53
+:10479000BA7F24A8A0FD877FD7C344479B3299DF07
+:1047A000EACC0A7F2B13E56508EF9FA5E518AC0757
+:1047B0005168D987E50DF85D4D953BB01C64F589CE
+:1047C000AA9E13DE69BBCDD84E4EF5D383656F6AC2
+:1047D000DCAD386E2055DE86E54256FF5CC71976A3
+:1047E000FF4A52C2F97F2CEB99B06F7A7DCB5731DB
+:1047F000BE7443CB4DF8EC6E556B204E67DC4372B4
+:10480000FD0D5F55C19FBEE1EBF7E1BEBED1FF429A
+:10481000F03B80FF35B91EEC2567B1187EC43BC460
+:104820007F43707460B95166F7FC2F9C75B2A7C3C3
+:1048300014BF53E0EFA5437E8D66BA07830CC9C34E
+:10484000EF09FAD399E741CFC3E749C8214ABF1F0F
+:104850007B4BE331A4E75A351DDF18F31DA97F63B5
+:10486000BE23C91B036F297A2AE57F5FD716BF7461
+:104870004FACC3FC9F850287D3C7EF8BE4F51AE9E1
+:10488000387BCB912E34A0DB46EEDFD9F58331EEB9
+:10489000F784C8EB801F8813DF55391CBFE78A37C0
+:1048A000A3FFB19118817BB93CE504F7C5023E63D3
+:1048B0005F9DC9B56F7B8D720C934BC2A5BD28E778
+:1048C000DC9A21F7989E5433FA74B1828EB3F5CCFA
+:1048D00095C18B200F3412848B0869F905B8E7392C
+:1048E0005B6265123BF3C2A142D007EAC54288D29F
+:1048F00043C7E72F1C2E22ECE822FEFDF4CF5F40D9
+:10490000FBC228C385BD65B4EC4995752548CB2508
+:10491000A9720CCA3BB9DD7766EBE72F74A03E0B9A
+:104920007F6696AB355CAE9EAF3CFDFFDA45D4E9C1
+:1049300000800000000000001F8B08000000000045
+:10494000000BE57D0B7854D5B5F03E73E6956426F3
+:1049500099BC278190131E12157012480848DB0974
+:10496000AF862B8FC1074609304978846700AD4E6A
+:104970009596810082628DAD0FBC2A0E16BDB6D50C
+:10498000DE68E92D7F8BFC83A0424B3156AB684536
+:10499000A350A56A4D04B98E56CBBFD6DA7B67CE3D
+:1049A000399909A1DAFFEFFF5DF874B3CFD9673FFA
+:1049B000D67BAFB5F69EB367E1CFB7183B6B2A192C
+:1049C0000B3396CBD80E6D8367FC28A879ADBE213A
+:1049D0001A635BF05541BCDD051E3B63158C3D98A9
+:1049E000197479A09CBEA6CBEA8476CE921C77D0AF
+:1049F000C558B1F79370357C5F3C8E310DBF1D9C5F
+:104A0000C5D818E8D77BBD62CF817218F3288CDE39
+:104A1000ADF740FB1C3763ED50326B84B1618CDD28
+:104A2000E59275980F9481D208EB80E7A91A7F6F01
+:104A3000C13A3C571D6C651BD4D34A993F02758F10
+:104A400083CD0BE0F81E0BAD63844715A542F3CD73
+:104A5000F06E601AB477D658FC112833B074E9D7D9
+:104A6000BF81DA8DF058A994F0989213BCC8837076
+:104A700061ACA60DE7C5A281525847EA853959B7FE
+:104A800042ADBAD47A3D83211F5ACB02F36D8C55C7
+:104A90007A0229081757594E6A7018D5CBF07BD780
+:104AA000464B98015CAA993BA294C4E102334F0D96
+:104AB000B893E3E395B5C1C0445BCFF7B29C758D65
+:104AC0001AD0AF439613110E308F8F6AFF7C0F2ED2
+:104AD00067B9B3CBCE06023E07DF19602AAE47A303
+:104AE000F7CE5D33A3FDE0FD8ADDAB18CE777D5AAE
+:104AF000FA38C4A379DC57BEB8D71380F7299F3999
+:104B0000026D09C65B22E0FCF2DA5AFA0EBAD7ACA3
+:104B1000798CCDC3A50C6484D00E27964C39EBA0BC
+:104B2000E5BD3C18DECF659C18AE0CD44F6300D7B2
+:104B3000865A95A925F85D777B7616EA733BEAA736
+:104B4000B2115009D94EE07327FC3D0BFD0659E622
+:104B5000640F3CAE0FF3E7D41EFE5BC07C9373E1A1
+:104B6000BBC6CDA6E76F4CF90B4BC7F7D6131DA5F7
+:104B7000F1FEAFAEAD0F4C14ED4ED3FF23B49E2B20
+:104B800035E647BC5DE94B8B8461895705AE094C1E
+:104B90002C8DF7F7EA97EA3C848B191EBFEA86470B
+:104BA000203071484F78340414BB473B375CFA0A15
+:104BB000877A6BD9E45CAD271CCCEB0788DD8E705F
+:104BC0005E0070BEB524393CA01DE1E3D56BA01D8D
+:104BD0002C65B23AD566013834CE54984321F8A6F4
+:104BE000B341D8CE3F75926EBE66389AE1D5F8349F
+:104BF000F345A1DFC6BBDD3EA070F607099F280084
+:104C0000AD12E4096FAA5FE73B387F0FFCC5755E04
+:104C10005E55F66C0ECC23B841F131BEDE77F4EB75
+:104C20006B60818CA842EB7E2709DEDFD1AFD33CDD
+:104C30003FF3FC53505881FC0BBD51F28303BA760D
+:104C4000CC1A1D1618CED8E31E77CEBB69501FC1F3
+:104C50007C6781AFCEB0711923F1FDE01CE26F33A8
+:104C60005D7CBA56FBC1019B9ECF399DCD0BCDEC2F
+:104C70001E17FB5758B0BBEE013807AE516FBF0A85
+:104C8000FEFDCAC1EC8DF86CB557D54E6423BC60EF
+:104C9000BD842F3F6392BE1896E17D2AC06F2673B4
+:104CA0006A2EE8E75B20A4CEC25AA6FB5334976E67
+:104CB0001DA75A951A94A380BC8C2B87C7D76B9ECF
+:104CC000F76AAF9DC6037AFC444F8F66B8BC523B6F
+:104CD0002803E5C80B71B88C381FB84C42660678BB
+:104CE00078B25954013C7729CEC8C330A7BAD0CD89
+:104CF000818923112E2C6C07D179C25342F251AE17
+:104D0000DBC6E49F950CE5699D9D05715D6FD858E4
+:104D1000ED932E2CA345E53AB9F55E76F50994D3CB
+:104D2000B25E17FA3EF50F84487428E979AED315C0
+:104D300055391D7ED84D3724CFEA3CEF5E4C786262
+:104D400067619D6AC6320DD7ADA6A58F60198C6DBF
+:104D5000C626B04E7B66A00BE5BF9A362082F4973C
+:104D60007ACD8F37733CFEA866960E8F290B7E1185
+:104D7000A6CEB52C03FCD304FEAA05FE524A9D66BE
+:104D8000FC31E4D370298B3CA2081040FDD4607F35
+:104D900004F93699DE90F84C29B57EDEA1A76BD6D2
+:104DA0004AF097786407467521BF06BD56762BBD3D
+:104DB0002F25F8043D123E5D36D427F342B653FA50
+:104DC0007E8205F323EBF0BB2D0E1F3E6BB068799E
+:104DD000D80EE0E4413DCE4A7D3EE41F1686EF2426
+:104DE0003D215CD198D0F5DF016B2828C7FE407AC1
+:104DF000E2779B75E30CEC396E375F99FB357DA745
+:104E0000AA603F901DE1F3F974F2BB2493DB0FA776
+:104E1000BCA3DA2C0393C3AFC199EDB766C7EBEF20
+:104E200014386B2309F480EC4FEAF32C35E8B5E035
+:104E3000DAC23B0F1E18877AD873114832769BED81
+:104E4000A183078B1892086385F8BF870EFA5D640B
+:104E500077883A1026CC7F476A77DDEFF4427D6091
+:104E6000773D8CF5ED301C1B0B764BE6430737C0C6
+:104E7000F79F1E7390FE3A55931A41E6C90E4D6096
+:104E8000C761DE5630733280D4A00863E90CF5A305
+:104E9000F52856801CC03B5BF32908EFCB3335A2C5
+:104EA00007ABC6A26E985CB6D5A720BC7E68674DDE
+:104EB000426E5C385367BF5C9EC9ED0E398EC3C924
+:104EC000C229E5F17E19F3AD433D629DCA48AF00AA
+:104ED0009F93DD26F95BF6333793EBCF6EFE3C37BD
+:104EE0003FCFCD4CC0CF872D2BDFFA1EDAB3BF5595
+:104EF000D923B09439DEEFD2F359A1462AAF092D58
+:104F0000A6B2498CF767166CC27EDA6B5F9A732380
+:104F1000D06FF32E870FD5F2F21BFEF2830A0DE15C
+:104F20000478C7EF1634DE5D01EFED432C64CF6EDD
+:104F30002E62B5484FF6750AD9475B347BCD2E28D3
+:104F4000EFCDA8BE2733373EAF7B3326529DD568C1
+:104F500016A4F3D54E4EE79F1EBBC5DB8076A5CBCE
+:104F600045FC625F57728705EAEC10CC9BA1FC60A0
+:104F70006467A80E5E6ECEB4123D6D16F415167001
+:104F800077C610C99CAE57C2F84E6B98A19DED8CA8
+:104F900059E9B95D81F925A053D99F33064C3A12DE
+:104FA000C7337F6FA7E7B82EFC5ECD6606BBE7CEA2
+:104FB0004C6E37DFD93D8F343E8F6C733FE9FCB9BF
+:104FC000E03FF33C3EF04CB81BE17F6F86FF9E4C08
+:104FD000B2C33B6C28CFE7BA7E7B5419D11779DC7A
+:104FE000A1A03C9EFE85122D06F8A554AB91F52597
+:104FF000A8D73CD346011DB06A9B0FE1D93E38C704
+:105000003D5037FE6302FF2F5A3D6E9C676012D8F9
+:10501000D544DF2CF74AEC67526325977F6070E92F
+:10502000F4EC8BDACECD0351FE866DB45F9AE70CBB
+:1050300047707E3ABB4D39CBE5B266AD8CDB7FF372
+:1050400026AAFE94F49EF61D6C430E90FD2765790A
+:1050500018EAF0DD9BA2FAD6C4D357E1323A98C7DA
+:105060003E506F0FE26EA912ED1BFE675EC868F737
+:1050700099EDC286AAB2E7000D009748CD28A4B3E7
+:105080000B2D44677DB59701D39C5E26B578705F84
+:10509000F5A09013D3271E9F887263069856D8EF09
+:1050A0008C89AA270AADB7862CCC0F133FE2572371
+:1050B0000AACED4869C7A16F21DCAA6C1AE9AD52B0
+:1050C00076FB1539F87EA407E11C107608B4E7FAE0
+:1050D000CDEB8C0C8167EDFEE3AE461DDD1DA93ADC
+:1050E0007E21EE5740EE3525A227C6D6D1BC0EDC78
+:1050F000944AFDBC75971271C0FC27A95FFC7E34F1
+:10510000DAB3DFB3F91C1A2DCB82789DEA6362E330
+:10511000EA774DD2D901C759A092ECCAB263D50E35
+:10512000B45F372AC4A712FEF342467B33B812ECB1
+:1051300032ADA77D0A9DD9919EFB6A9F9AEDABCFB8
+:1051400033C1AE023A67E5AC5C6F5725D353D2AE9C
+:10515000B232BF92457AA8C38A7A773A3C4824078C
+:10516000AECD5008AF93D40F093FA7AA540DE175F7
+:1051700024F4BE0BF7E347BE50F93ED89F6BB0E373
+:10518000F2B3B85F60BB1D0C32F86E7BA133B20E78
+:10519000BADA77D345F91D841FEDDE7188C7DFDAEF
+:1051A000480E279BAF3BA4B2C14098D3420A951248
+:1051B0007FC5A11466D5E987629678FEA5597CFE65
+:1051C000B96B9845837133C3CC9F687F2CDBC1BE1C
+:1051D00078B29551FB6826CC6FC5600BD1A7DC1F58
+:1051E000A7D8C2FE7EB07EDB9E5561DC2717C3FCCC
+:1051F000701E1ACC0FF56549288DEA0343D9540E69
+:105200000A65523938D48FDE0F090DA2F282500997
+:105210003D1F1ABA98EAA5A191545E182AA3F2A2DA
+:10522000D0A5545E0C7A13DB0D0B5553393C741921
+:105230003D1F11BA82CA4B4233A9F48566D3FBB233
+:10524000502395E5A17A7A3E32B494EAA342D7512D
+:10525000BD22B48ACACAD0CD548E0EB55059155A43
+:1052600047EDC6846EA3FAD8D08FA8BC34742795B6
+:10527000E342F7D37B69B7A40A7EBC4D9BEF417F25
+:105280000750B886749C8CEF1665713DF042A67F7E
+:10529000465645BC9DDD027ADCD5B35D6316D76307
+:1052A0009988D704FDCDCDE2F2F923DF3BF70C65F9
+:1052B00071BC6DF1F6EECF60A589F71B71F9C0D70F
+:1052C000373D4BA372BBB5DDAF22FDAE64BE303CB3
+:1052D0009A36EA4505E5CB0ECD5A93C8BEBB37CB0F
+:1052E00046DF3D98195C81EB4C2B397100E5C98C88
+:1052F000B0E7F7E3915E86E5FC763CF457BCC1422B
+:10530000DB7D8D79F6A17F4D9BC8482E4ABF12D810
+:1053100075067D7A87800B636D0707123F0D2EE7B8
+:10532000FAA7630AF297FDA681B47FDF6E8F2A5633
+:10533000B46F5633A6B7FFB76F6A7814DFC7FBB3F5
+:10534000D33C8B37B367D0C42E69D5C6A740396824
+:105350009BFF9914F8644824383E15EA431F0B3F1D
+:1053600083E5856D91F169505EBC3BFA0C6EE38676
+:10537000473BC6BBA07EC941B61FD9BFAC5D9BE011
+:1053800086FAC8A3FEFD4006ACA22338215DC3F90E
+:10539000445AD2613EDBDF04430FEA551FB6AAB080
+:1053A0001D8AE31FEC38B4DF245EDCA3DA2766C372
+:1053B0003FFB5FEF2953F17B6B474AE6B09EF8D97C
+:1053C00081EBC675821E7904D6D5DF1F553C3A3A6B
+:1053D000F98DE067C0C34328E7A45F72C7862CF24B
+:1053E0004BEE48F554E3905D9398E7610DE9D84A98
+:1053F00070B26F1C48FE384977005F833D7B87A001
+:10540000BBEDDDF66E62F8FE46C8BF7F15F8FE5BA9
+:1054100016E78764F07522AD8C39371F1F167C099B
+:105420007C7C50CFC7E6761F0B3899E1BCC3C20E17
+:1054300082AE8271814E395F31F4A37D28E8FB5C36
+:10544000707DF75F8C6EF70B39910CAE4CCB213928
+:1054500009F47A21FAC792C91BBBD8CF98DFFFADF8
+:10546000A79CE37E5B0FC8B941C9E5DCF302DF49C5
+:10547000E597903376937FC799CDF9A6D213B0679D
+:105480005724F0537B730C7EEAA9AAA71AE50D1BDB
+:10549000CAC88E4E1B1609E33EA538AC95ABD80C96
+:1054A0008532C2B1B094FC0F2560675801FFD0551A
+:1054B000144BA7E6B134A0FF5DF29BA7DEABE73744
+:1054C000A9EFE3FC28E9226BC7ADDC2FA9CD04FBD3
+:1054D000E5DBD9C2AFDFDD0FF7836CFA6EE18E5BDF
+:1054E00075727087D74B75D93E19FD2E10EF776C0A
+:1054F000584FF0748E4B6C375467F3B8C2767B9775
+:105500001FE93CFC4DE6417B2673C33B249F32419F
+:105510003E29249FF8F8FD43A98F86A1EECFCE1334
+:105520007E004FEA2CF7FF3B7ACE459B0AE5D43844
+:10553000CF3E15E334A08734E4D37130F751082F00
+:105540003BE15D631C8FDA381641BB17E016C57D61
+:105550007BD8E2263F93DDDEEA477E66F64C5A7F33
+:10556000A5273823BB17BEF0A4696588D46076DB15
+:105570001417D0DFA6124F2AD6E7407D6B158C9BFF
+:10558000D5C1447D8B6BCC3FEEF708FEE8E787364C
+:10559000C078FBB2FC73919E81AE8358FA877AACD7
+:1055A000E4AFF6F6CD1E90FC19E7274F99E4A7FA71
+:1055B00061240F9760BFB2BF64F6CDE06C2EE76E3A
+:1055C000166532FB46D2FD79DB3762BE8BB37BE7D3
+:1055D000FF570EFE68DB4EA6F33716DED36ED5D02E
+:1055E0009FC1FD3416673BF5E716FE463FFA1B8167
+:1055F0000E9C83791DFF24F21727876384E623FD21
+:105600008CD29F982EE88A599508EAF1F42A8FB532
+:1056100081FAEB6097437FDBB2B9BE917C8D72EB70
+:10562000A9612897B2ACB85F477F923B2BDE3FD68B
+:1056300033CAE3F289897DDC7562CEADEB7D19E872
+:10564000720E1FE17E94D6EF73BE9CD69F45D6A303
+:105650009CF033CD03ED5398FCE337F893A77EAE6F
+:1056600000EF821EFC5CA55219CCA26ED8EF4DF360
+:105670002951DC07DA2DCE08EAD2EA4227C3F8A680
+:105680003DDD12C1F888FD1D85D6692F4F8BA0F036
+:105690009B5858958171CCD387F7BB8209F07F75F1
+:1056A000B0DEE0FF32C3B1BBDD9C673D08C7FBCF76
+:1056B00011A77D3EBB3B4EBB0FF972FAFCAE0D76D7
+:1056C0002D1EA795F1C702EFAE2DD5A8B29671FB9E
+:1056D000B49045D6E9ED2A5D1CF477D8CFFDF138BA
+:1056E00068FB05FA386873E11EB477EFEB8E83062A
+:1056F000F712DF65B79521FDDEEFDBF5933B109EDA
+:105700000E11AF1879CCA5A19FBE627F2EAEE7F730
+:10571000A6F9CB52FAF1CCFBE03F651BE30BA77D6A
+:1057200057644489B6B213F2B7F42FCAFD30FA0FAA
+:105730003D09F9D0086F397E9DC2F7B5CCA670F946
+:1057400027F428C897BF921C8830D29B7E87F230FE
+:10575000EA9BD3BE913E8A7B269137723E00C721D9
+:1057600089E2BF305EC238AB2387EBA93A1BF79BB7
+:105770002AAB2A56E2BCEADC2EC5A1F3F79F16FA43
+:10578000CC1C175233BEA8080ABF77A2F59BE33B97
+:10579000A7515FE47278E9FDE4E782D7515B2BC53E
+:1057A0000F8F2E50D93AEC27383A9F25F85E96AFE6
+:1057B00023DD0C61EC18C2B84287CF24F1A2A36BA1
+:1057C0009B28CE6C8EA775BFAF4FA945FD5D8B7032
+:1057D000D48D5B25E0375394CC11D43CF0DEDE70E1
+:1057E000B78761FC6BC827156137FAC5BA7E89F1A6
+:1057F0000BF63D37F92B6AEBCF54AC1BAE83671524
+:10580000E3F1D9FDF77934785E3B64436ED8951C9B
+:105810008E3373381C6FC30763C81F333287FB375F
+:10582000FBE48F61C3785C88ED4FA1F869CA1F550E
+:105830001FDA0D382ED703DC9F7CBD889B98E37858
+:10584000B5A11506F9921653584417BF48B3B6913F
+:105850007F362D66A5E7667ECBCD31F29B847F3205
+:105860007C4AF89B9FFB72F87A8ED62FD6D06F6851
+:105870004F4D6C07DF22DAC9BA391F2159DC7DBED2
+:10588000C0EBE9E0987CF457D5DAC343FAC2E712DB
+:105890003EE7CA739893C3F5B8FB9A97441C4FDD53
+:1058A00080BD49BD9A66ED3D1EEB37C563D346F515
+:1058B00088E7FD53E2B1EB7284DFF03CE3B15304BF
+:1058C000DD9E2B0FE56ABBD1EE91E52C81C7D3C1DC
+:1058D000141606F9785DB54A7128A00FD28F47EFEC
+:1058E00056C8DE8CD63B482F37D6A7907FB6B14C32
+:1058F000A5F78DB7ABA43FA3201F96817CF8BD9080
+:105900001366FF6C35530CF1F3E9A3520CF56B16DB
+:10591000FCE8F76BD1BF5C65D370BC231AF73787FF
+:10592000FD2AD9AFD0872F8AFEE9BBBEE1437D2691
+:10593000E9E1885F257E0BBFACFA70D876E18F3E37
+:10594000B2B92C82792A4C89C7E9B541D87F23C5E1
+:10595000815FF36EA33867CA97F70602B47F0C6ABB
+:1059600065A43779FC3445F0E984C2AA59A8C7DF99
+:10597000DA6A63E8377A6BCD69E2E78EB52B292FB7
+:1059800042FA97A57FD8EC6736FB977BF8954DFEDA
+:10599000E464F90CCF26A10F29AF92D10788ADC3DB
+:1059A000FF881C93F2E375B1CE0985DB6E5F07704B
+:1059B000489BAF121C245DBEF6C52D0FA21C4E01E4
+:1059C000FA58CF109EFFF12CEE43D86225A11FD9C3
+:1059D0002DE53AE64F94C6F1724D7071771DD97F6F
+:1059E00076D32A43DE8759AF24976BBDCBAD3B728C
+:1059F000B8BFC2AC77CCFCF075EB9DDAFABB4BF1CB
+:105A0000FBDAFA05112CB7143A9B50FE9AE583593C
+:105A10004FCC32C9D9B87E505964A47EDE1AB58BFA
+:105A2000EB093BBDFF3485E73B849CBCBC3135FDB5
+:105A3000612C3F4DE1F90E61340AD14E7D332DD2F8
+:105A400042FBF295A3914E42CCD711C6757A53C949
+:105A50008FD0DA9FB753A7A472BBFC4035AD5795E2
+:105A600086F9866AE29B16B19607B28345B980E74C
+:105A700016BF2505E30B13DCD643E87A691D6F6179
+:105A80000E1687573C2F847914F89EDE29B8FF2C18
+:105A900073DA07919D3A2417F1F17DD81F02DD1FBB
+:105AA0003EACEEDA014B3DEC1B9991C84EEFD603AC
+:105AB000A638F2B1EFBC3A00F9F6CF2CE8CBA5F846
+:105AC00071E3ED181F6EDEAD527C69CE0DAF5D4007
+:105AD00076B7294EA9A63B4BD19FD2A2A4FA509EDD
+:105AE0004838EE73DB49CEB41C4BA3FD44CBDB8AB4
+:105AF000A8BB491E4AB81F807605A33057C94D720E
+:105B000053C21FD6E5C775493C54B3E8E171255F20
+:105B1000695D97F5BEAEFE1EB20F90CED4F83A5432
+:105B2000B795D6D7C9527D38BF90F00FB137D2683C
+:105B3000FF27F1DC2CE851E27985C073E79E333F03
+:105B4000B814DAB7FAB328EAA016318243E71B6E1D
+:105B5000A2130907B96EA08B20CE53AE7BFF9E9196
+:105B60004783F87D7A2AC5F1A5DD2DF30ECCEBAF86
+:105B700013FBF7A5B94AB7DD8BFE8BF6ECF14B733F
+:105B80002B12B417F62EC07B05C2BBDAC33E89B018
+:105B9000F83E2F597EC34DB946BEEB437EC34DB987
+:105BA000B93DC7FD0AF8DC88FDF5159FCD56D766CF
+:105BB00025230E6FB96F2696D67AF2BF99FF243E41
+:105BC000943DFB3EC338BE592EDCA8AE640A8CB3AC
+:105BD0006938E74BB68669941F64E29773C91BC0A6
+:105BE0007F04F1944CEEF415FF3FEB89FF9FF5869F
+:105BF000FFD6ECC013084F1CAA5F39ED0BFF13DB77
+:105C0000A33CB10FA4F1886EBB3219E5B3C9FC18EF
+:105C1000391F9927B317935673757938A53E05F543
+:105C2000441FE863AF7E7E5F037D1CEA9DDFA3C453
+:105C3000A7CB05FE97CBBC8C5DBDE765F4017F4724
+:105C400013E1EF46D5D7152CE93BFE8EF7C4DFF103
+:105C5000DEF1177C17F1D762679F90FD5E55EF4527
+:105C60007AA9F4F82FC77C9DBDEB84DC2901FC9553
+:105C7000A0BDA4925CFB21BB88E4F6372D169A6F79
+:105C800027C8EB87953EADF3BF73C94E095BB3A040
+:105C9000DF1BAF6014DFF36AEB14ACE76BA0A7B5B2
+:105CA000BEAF57C9EBB15E25AF777965CDCB25FA8D
+:105CB000BC1EE9D3A979ACBDC92B4FDE79CB2B4FE4
+:105CC000DED72BAFFAE59D875EED03FC87E0FC9203
+:105CD000C989BEE681029FB27E593DC7879D2EC508
+:105CE000D5AAD39D5C6F3FA9083D5E16A4BADB49D7
+:105CF000C2E280D0F3A776F1F7EAF8C476E588BC73
+:105D00002C9EAFD0B62A6035E49384E9F91DFE538A
+:105D10009EC12AE669BB683DD9D3B81F52AE5FE683
+:105D200069A78BF56417F175671FE379ED125EE9DA
+:105D300062BF91516535EC2324DC6E54030AFAD11D
+:105D4000337318A649C03E6198827EAE4CBFB1BD88
+:105D500084772EDBFAB18A295F35C6F7B9B89F1967
+:105D600081EF75CF13EC5F013FA5983F764D9EF014
+:105D70003FD89917F51153EB7AA523DDFE249847F8
+:105D80007197DEF7270BF364BCDDA8F7DA525842AF
+:105D90003FC327821FC05E217FB32AF4DCC48E126A
+:105DA000CA7759EDD6C8FFA0AA3EE7D4929EDF6716
+:105DB000FA81BD75F0C8AE49659ADEDF12C832D4EB
+:105DC000F36B0B0DED0B82030DEFFB355D64785F1C
+:105DD000B4B2DC502F0E8D35B42F01C0EAEB833600
+:105DE000FF9BA1FD90D6CB0DF5A1DBAE35B4BF3046
+:105DF000D260787FF1634B0CEF87B7AD36D42FD9E3
+:105E00007D93A17D8BF0239BE1F2AB3CBE7F6BB118
+:105E10007239B4CE554EFECD1697D1BF79A7807F8B
+:105E200075C6B852F4ABB7BC53568AF03E903E9656
+:105E3000FCECC9E8C22CD792C953F3F33631DE47E4
+:105E4000CFD82D48D72BF603DF5E0275D7EB9B70BA
+:105E50004D5B86F1F8AC8DF17C2119AF91DF77C7EE
+:105E60006BAC3EEEAF4D77B15B13D0C59D799A51C7
+:105E7000CE0AB929E92819DC243D9E0B6EBB057CAE
+:105E8000BF2ADCDE5078BEAB5E1F3C99605E1FE728
+:105E900059447C39F8873C6E0F8D4A254BDE43FC14
+:105EA00078BEFA40CE03F4C131AE0F8C79BA1FD55B
+:105EB000BEB4F05E0DDB2FE4ED2DBE52C44B327F3D
+:105EC000FAC7026E3A7F7A13F7A7A71AE0F696E4AC
+:105ED00077935FAF25FD73F2A7B7D87DA57DF1A7B6
+:105EE000BF05DF22FC77E771FAE8C6AFF0C727DB12
+:105EF0004785183B84E72198CBAAE9F74DC9F6C737
+:105F0000529EC3FEB814E3B4ADB8FF5212EA414743
+:105F10007E05ED9F491FB4821E74909F801DD2A004
+:105F20007EE3040BBB558BAF5BDAF30EE673DA55F9
+:105F3000C2AB1BBF67DF67D7A7A85FCB3ED39BDF92
+:105F4000EBBEC4AC67CF19EF233B6D1AAC7FBD6EBF
+:105F50007F2DE1638EEF49F84CF3F1F8DD46D08FE9
+:105F600018DFDB97CBF5F446D87F231C3DD901EF32
+:105F700000B4E7E1F9C3888EDC4AE21F0957739C3D
+:105F8000AFAF72676C7E0F3B6E6C7E2F769C5CFFB2
+:105F90006AB17F9EA40E6B433FE6A9989DE0A632AE
+:105FA0009E77D97CD0C62284479EBF2CF1688B6D2A
+:105FB0006A47FD6C63E67C652D03D76F3BC8CF89CC
+:105FC000B11CFE3ECC9CEBD0EEC9A832EAAF4CBF70
+:105FD000517F65D76499F499517FE5D71AF55741F8
+:105FE000D0A8BFFA35959BF499517F1587C69BF4CD
+:105FF00099517F0DDA7CB9499F19F5D7D06D46FDCF
+:106000007561C4A8BF2E7E6CB5499F19F5D725BB15
+:10601000D71BDE97456F35BC1F79F087867A45FB25
+:10602000BF1BDA2F3AF40BCAEB197DF46143BB3185
+:106030001D3F35B40380B763FEF77C420963979E2A
+:106040007CCAF07EBEB0D7BED1F56B433FAC95E7BE
+:106050007187E12FE2EB3D16B4A39162655DCFF548
+:1060600003BCAE8828BE28345BBCFBC94A9CC7076A
+:106070006F4E3988FD2CDA66CCFF5E1C31D69BD979
+:10608000C00C940BCD401711A093A59817AE936F39
+:106090004BD94A712EB06F74B6E8D0158CF249C353
+:1060A000FE76CC7B97EB94F4E617F426E727D7BB74
+:1060B00014ECBFA8165FA71FFEF2FD66871DE976E8
+:1060C000E16E85FDBBD2733D4D7BEEDCD42FC1BAB2
+:1060D000CCEB30DBA13FC937FAC727A92E8A179C22
+:1060E0007A59F5717FA3910F571FE27182D54F281E
+:1060F000E4AF33C343DAA7C9E0A286F9BEA139876A
+:1061000045223AFED3043C1C5E23FF9DC27FE07C07
+:106110001E5023986F94A2A59AE9AD32CA7AC2396B
+:10612000ADD4C8A76638BB7D8509E94A83BF388FDF
+:1061300085E2FCA199AECC705FB1FB4E3BCAC3F3C4
+:1061400085FBD1FCC47109D076A3EC09F2EB245C89
+:1061500061DFFE26CACD64FBD9F7F395F33D5FF40A
+:10616000BE5E0E7F0DFBD933BDE9B94EF4B7817D1C
+:1061700069F6B399F5B0B267FF674A3AF9B53B1CC7
+:10618000C877419F93E7C198F46469A9414F76EFBE
+:106190007BDF5168DFBB2BC36FF5C2FA0E65F86D6C
+:1061A0005EB48732FC76AFCE0E6D01B8D0B91FD089
+:1061B000534F26B013C77BA57D1420BFC9C66ADE26
+:1061C000DEDCEE222F3F27B42FB7D24BF6E7DB659C
+:1061D0005EB23FDD95BDDA9F778838D16D18871C98
+:1061E00012CF0FBA5DC46B80EDFC88B78DB68057B7
+:1061F0009F3FECF666D2BCD2C73CD58E79D42D1E1B
+:106200008B47D1B0E4F9DC1B5CD69A9DE2BB1CC382
+:10621000777C9E2AC21BE06A75593FD7D3ED782F51
+:10622000A3F7C9D639DECBED5E1B0BDE8EF6908C64
+:106230000FDBDEA976A2BC6B617E0F97933E8F3E8B
+:10624000FFC3C6783C78BC880FCBE7AAE71FCBC357
+:106250003A9211AC463C9AF3B06ECCF08FC7E7216E
+:106260006BD8817667C899785F5C23F0AA8AF5823B
+:10627000014A7445F350CF3FFE03F6E61538EE8D24
+:106280006A98F2245BDC95A54157DFFD5C73BD9CE9
+:106290006F75F6D15C3D9D9AF913ECD3CBF11C9947
+:1062A0003FA3D04ADB0EABAF14E1BD19FF3D86FC26
+:1062B000B40BF0FB1E79AFE21C2EECE37ACDE39534
+:1062C000FDECCBF22FF3F27CC3155E9E6FB841D587
+:1062D000F5937E8E7EA49FA30F7EAB35DEC4FED1E8
+:1062E00093A8DFFB0AC75BBC3DECCC5BBCBDD89977
+:1062F0009F1E1B9A81F16CE9EF32B793E722657D0F
+:1063000073A671FC4DE5BCFE4381BF3F8A7B3A1EFC
+:1063100015F3709ACE8B3AA732BAA7439E3395FDF8
+:106320003CEA7553FBB5D9E31FC5F96E2A51681FC6
+:10633000BA295331EC47EBBDD58F225E23A2FF472C
+:1063400005FDEE18C8FD39E63CCC25D8BE024BDE73
+:106350002F9E6B45396657D58470FC9997FB8B2E21
+:10636000878EB07FE9776BBC5B11FB27E3BD08C06C
+:10637000E7AFA481FC39BED546E75E17A8AE4D480D
+:106380008FC9EE39A81F16A0FCA7AF7A7E0CE19941
+:1063900096D553AFEEF776EB55DF799E23FBADF73D
+:1063A0003CE2FD1DA99C4EBBDC2EF29B9BDB9D10AD
+:1063B000F8D92AFC1A28D751BF64A96C65223D730D
+:1063C00042C8D57FFC5C33BFCF23DBE5A2EFCCE72F
+:1063D0009A3BEC1D1BF371BEDF507C787E21BFCE53
+:1063E000B32F3F07CF316AE4E3DB54C2D2ABF07D79
+:1063F0009985DE675EE9D964C3BC6F8D61E63EB303
+:10640000C1386E18C755C0E3385BC357ECCB8776ED
+:10641000195A171B388CCE7B4FF622DFD6F2FC7947
+:10642000F3FABE14FCE1DA08FB0B848796380FFD03
+:106430004B417F206FBE403AAFD6D82E7E2E8BE7E1
+:10644000C1225952BEA28FE76BA761BED3202E6F27
+:1064500048DF644DB014E4C6F94B15F0369FE7767B
+:10646000159CDF79EE197589E73BB480AFEB4F19C6
+:10647000812C1C77C6B875DC1FF6C5D9B36A251AFE
+:10648000C79C4FE07B86FE8A941C2E8753348DE494
+:1064900032F32894E7EAD47C4D584F718DF5A86803
+:1064A000273B785C92CDB730BC5F6582E8C75FCB95
+:1064B00094774BB95F96CB592B7B57D2BF2A805329
+:1064C000897A96FF01FB696B1AAC6782EB30C527AE
+:1064D0005306AFACC6730DCFCEE37DFC30C9B90116
+:1064E00079DEBDFB5C3F7BF8B0E15CFFC6070E1BAD
+:1064F000CEF5871F38FC55CEF54FBCEF81C3FFCCDE
+:1065000073FD529E1D5583476F06F85F0544152A9B
+:10651000C7D2CAEA08DF5E82DB9502CEE1CF01CEA8
+:10652000CE389CAFDA7388E077D406F386F16DE35A
+:1065300039A86D3765445A482E4668DC59CED6498D
+:10654000B8EFECB4778DC0713B9F7EB5280CF2E4B8
+:10655000D8F74EBB19D0DF5BD62E373E3FB9E625C4
+:1065600037C2EBD81A95EC353A17ADCB475A28E825
+:10657000EAD982C01CA4AB796BBFACD4DBE32C940A
+:106580004BFA777144A5D42B29FF963E9626888E28
+:10659000D797B7651BEA522F2F77243EA7FE6001DD
+:1065A00097438B1FDF61EFA7E1F8C1E60298C74967
+:1065B00091DF7072979BF661723E0D8F97D971DFF4
+:1065C000F9D61E078B921FB8DDC6C89FE59FAAE4C7
+:1065D000E13D46FC8F799ECFED4DA3FE16DCAD92DA
+:1065E000DFA91EC60A015C837B16F37DB0691D0B13
+:1065F0008E6993515E2DD8A2B0B0C6DBAFC1FB331C
+:1066000042B7501CC6BC4EB37E5994E4FE9C457BF9
+:106610006EA3EFE733FF6D68CF2E6835BF9FF21E84
+:1066200012F9A273C4737E5820F44E251B7D761098
+:10663000C58F32866BE7D63B27D772267D7FAD9319
+:10664000CA0FD77AA89C53A0111E96EEDEF75C3FC6
+:1066500062F3F64AD44BAF1C6C4CBB568BDBDD951A
+:106660003BAEDB7F3F91BC313FB34EC07DB4C8CB66
+:106670005C24CE3D541CED3D2FB30EE131A2E77CEE
+:10668000A59D5D67F2FB4ABBDB0C8F530727A42156
+:106690007DFC52C26534C045FDEA7049F6DD729555
+:1066A000DF9B667E2EF9688EA0EBF93B676E2A842D
+:1066B000F15B9E7E6F4007D129F75F54087855B88B
+:1066C00036B5E3FA2B98C96F18662F331D3D033D8D
+:1066D000A9A877CC742BE989BDCCBF770ABF463710
+:1066E000BDEEB99DE02BE90A4F3A58D0866351AF11
+:1066F000A5EADCF75C2D6835D63FB2750C4079B25F
+:10670000C8E46FF84849BC7F7BBE60202D76BEE6AA
+:106710009F8CF9170B586013F7CFF3FB714E5A5B40
+:106720009FBB19F97C27E7B3E5BF7AE2BF507E2D06
+:10673000F9CFBBD3517EFDC5DA9A87E32D7B646325
+:10674000BA1FE598359C8EDFFF25A2263C473CB852
+:106750005091F9FA2ECC535B41A406FFCD0F4F4761
+:10676000F9F9DF8FD83CE8876D7ECC1175003C5677
+:10677000ECE27084FADBBC7E0BC1AB79B7912F974A
+:10678000FCC7DD791AF903C2FD04FCFAA1085FB168
+:10679000D34679AD2B5E567D384C33EBA2F599BFCD
+:1067A000C779C4006FCD6D6ABD3DA3E77BB084ECB3
+:1067B000C86FCDBB383E9B77717C359BECD02621D2
+:1067C000B7CDF49F5328E2BA82EE013EE45793F925
+:1067D000B62CC2E577CB4FEE1DF136CCEFC39DBF93
+:1067E0004B5786C5E99F615628C0ED545BE33C7B5F
+:1067F0002FF7F57C24F8A45B2F083DA4ED8689E5EE
+:1068000043750F2F97D9A2E997025C96EDB0F9C2B4
+:10681000F078D913AADF8576D46B0EBA7F62E913BC
+:10682000CFBE3216E6B7F4495BCE54BE0C17CA6F22
+:1068300089AF66A4F3F2387E96FCE2593BE669E242
+:10684000F33559713C2D7D729F1DF33ECDF09CD0E8
+:10685000B6CFCEF9CD84AFB6B727A3DE6EF9C9A700
+:1068600076A487BFEC55587E49CFEF9B763C9B8E34
+:106870007206E184FA45E2AD1B8F3DF0179DFEEBF9
+:1068800051D4CE83719E73E1F1133C835041F4FEE9
+:10689000F35FC33C9A5E77F8100E4D3FBF2E1DD7B5
+:1068A000F39E7525A7FB0737E6A1DE6EB285F33CA4
+:1068B00054F2E74DDBBF43F4B8E8C5EFF0FB9C981A
+:1068C000BF00F919D65B80EB5CF0C055B4CE852CC7
+:1068D00048F4D8F420BFDFF08C95D524DA0F3C249F
+:1068E000F8E6BD871DB47978CFCEF87D217F50C5FD
+:1068F0007D58ABC85EF98E58334868AA9F71727C88
+:10690000AD2E94717F2EDF9A45ABE69DB7907C7BD0
+:10691000BFC89F8FFC0F7030FA675F9C942FE422F2
+:10692000DDEB42DF01FD4DC0E7D8BEDDE64F19616A
+:10693000F84EE4DFF2F1AF17E3C3BC53D1CFF75EFB
+:106940009E719F2BCB2385D2AFC6DA999ECE92C97A
+:10695000819D5B88BE3E7999CB9915919935F4BE9E
+:10696000DD16CDC7F7917D572A2427C00E49C4E70D
+:106970003B6D82CF8DEF619E56450FDFBDFCFC9EC7
+:10698000A4978577417B1D5FC7E9C71E7F5E12E72D
+:106990005799BFB1C864CFC9D22C27EE33C909F9C2
+:1069A0003D7B2037E1F988B87C0813FC96D9228F0B
+:1069B000FE3BF2F56B0E3A17B9EC091BDDEFF3C1A4
+:1069C000E3FB5FB916E8FF8336C9CF46F96BE6E70C
+:1069D000A6A7AE6289F8F9839C004BC8CFF03C2192
+:1069E0003FE7F0F306FFB7E4EFA224F2F740614F70
+:1069F000BBE352A8BEFFD3A5C5B43F33C157C2D530
+:106A00002C4F67A3B190DB539EC29F97990E9E12A5
+:106A10008E924E97FC6C398DD34DCF925E253D778B
+:106A2000D3AB79DD46789ADFDF827BA7DC38FE6D59
+:106A3000EB615F8EF1DAA755CACFEBD4BAD2B3605F
+:106A4000DC8D22BFA7D323EA99BCDE956BDF84F2ED
+:106A5000443EEF4AE1F90E9D81AEF44CDD7EE0ED5F
+:106A60003D6A3A9E07E88824CECBA08C0DF483249F
+:106A7000C9DB90E77E3B53B9BFAF3395FBF926A93D
+:106A8000AE0121DCDFB5F2F8D2FC7557A7E3FEBEFC
+:106A900073CFA019B5B81F38A4F29CA3B0DF5A0079
+:106AA000F06DE44B672759F89E7168BFEF593A15AE
+:106AB000FB99BFD5089785AE9D76ECE70C5B43E567
+:106AC000C2BB6C713A81FF9660BE16D2F903A6E78D
+:106AD0007B2E23BA5A62A2AB20D25582F32419FD31
+:106AE000045D95B132BEDF16F13121F726A9C366E8
+:106AF000D4623EE5417EDEE3D41E956DC2F53E2EA6
+:106B0000E265E15CA2D71540DF7ABFE987487743A9
+:106B100093EBF90F7F79ACF26668B2ECBFFE34E21A
+:106B20007E283FFCAFD72EF80DD67FF5EA803FB127
+:106B30009EED27ECFD6C2EE575EE75D0BDA69D7B18
+:106B40009F1F7033D67FEDA0FB453BD7F37D767852
+:106B5000AF9BF47F6711B7175B9EFE744407E92F64
+:106B60007E6FF0D87EFCBCEDA93D7F7B53C17CBE1F
+:106B70003DB02A948F62FFD6FCEB14DAA7773EFD76
+:106B8000A9617FFA55D7B3429CBBEA74B35A3C273C
+:106B9000DD99C9CFA936FF66CC8FF1DCE5F25DFB4C
+:106BA000EC8DF07EC2FFFE7204CAA1CEA7B8DD0153
+:106BB000F6F076E6033CF46BBDDD06F8FB086D44A9
+:106BC000E09937FBB54FC3F3243DE1C2E1D0097032
+:106BD000C075015C9A507E268347DDBF2C3C3E9EEB
+:106BE0008BE32FDB339AEE198EC345F1F3E76ECAC0
+:106BF000F780F5F3E77B3F1D8176D4B9D67B533F11
+:106C00007EEEE77FCA7AB7FDCBAE97D3BB864E99AF
+:106C10008A9E74DF93AE7F7503D57FEEF6D17CFB41
+:106C2000C8EFBBFF87D1F72BFFDFE2FB90C0B7DBDC
+:106C3000837199CEA7BF1CC0CE63DD67FE65F1DC12
+:106C4000FBBABBED1E8BCF390AE6F73A8B5C55AD2C
+:106C500024CF1F1DD85FFA1FF83E43DEC33D3D67BA
+:106C600021D911D3FDDC1FD3C2CA0FE239BBB05FFB
+:106C7000A5F80525EF001CDAAF2C8B509E98353C0B
+:106C8000E41ECC1B9BB5DCC7EF2B33EEBFA6E7D5CC
+:106C9000D4A03D77641DCC0BDA1D715B3C2DB08414
+:106CA000197E95EC3F28C9EEFBE3F8CB280F65462B
+:106CB00095711F72AD693F7175ADF1FD2CF6702EA7
+:106CC000E6FBCD6AB2517ED255E6FD477F0FADF3AC
+:106CD0006AB67223F7E79C1F9C2EEFCFF7633DE166
+:106CE000D03BDC7AC049EC37297748EB093747902D
+:106CF000EF3F1DF042D85B222F6F759FE0C9C4BEE5
+:106D0000D4218696F075F8F9BDA3BA7E092E12EE4D
+:106D1000E70B6F892733DC257C25DCCC781882E7EC
+:106D20003D2BE2F08F97C67BB599B01BA777DB8D23
+:106D30002E82E30B3BF9798917AA1AB79661FD7188
+:106D40007E1FFC9971239913D67BC4C676535CC809
+:106D5000EFD73C95F1FC19A5EA798A4F60FEA27E37
+:106D6000BF8AF98BFA7561FEA2BE8EF98BFAF6988E
+:106D7000BFA87F8FF98BFAF798BFA8AF63FEA2BEBA
+:106D80003DE62FEAEB98BFA86F8FF98BFA3AE62F12
+:106D9000EADB63FEA2FE3DE62FEADF63FEA2BE8EC3
+:106DA000F98BFAF698BFA87F8FF98BFAF798BFA8EE
+:106DB000AF63FEA2BE3DE62DEADF63DEA2FE3DE646
+:106DC00029EAEB989FA86FFFADD833867A35FB9DF3
+:106DD000A1FD04E74B86FA24CF9F0CEDBFED3D6E7D
+:106DE000783F45FBC0F05EE2FFB2D2D386E718FBE6
+:106DF0000857E23E86FF99E6FB9BA11F2B0B509C98
+:106E0000D4CE5652E9447F2F94A9AC8D4A17B0399D
+:106E100096EF0D0D3EDE1FE9757B781312D7913189
+:106E20009F0E40F9FFC2B82BB85F42C41766E03F1F
+:106E30003520E2B42FFAE33E57C64FD3632A8B8E38
+:106E4000043A8C29547A62692C9A0D74184BA13239
+:106E50002B964DCFB3639954E6C4FAD1F3DC5801B5
+:106E60009579B14154E6C74AA8F4C62EA6B2207659
+:106E7000219585B191F45DBF581995FD6397D2F3C3
+:106E8000A2D8182A07C426D0F3E25835955AEC3216
+:106E90002A4B6253A81C18BB82DA0D8ACDA47270EB
+:106EA0006C363D1F12BB86CA0B628D540E8DD553B6
+:106EB000591A5B4AE585B1C5545E14BB8EBEBB381A
+:106EC000B68ACA61B19BE9F9F0D877A91C116BA108
+:106ED000F292D83A2A7DB1DBA85D596C0B95E5B1E9
+:106EE0001FD1F391B13BA91C15BB9F9E57C4EEA3C4
+:106EF000B232F6632A47C776505915FB199563627B
+:106F00003FA1726CEC17F4DDA5B127A91C17FB0D8E
+:106F10003DFF46EC7F51F9CDD87E7AFEADD83E2AB2
+:106F2000FDB1DFD1F3EAD8212AC7C75EA2E7136219
+:106F30002F523931F6277A3E29F61A959363C7A95D
+:106F4000FC76EC6D2A6B621F503925F6172AFF2D4F
+:106F5000769ABEBB2CF6319553637FA3E7D3629F2D
+:106F600051D9BDFF1F97F477052C6771FFECCAEA72
+:106F7000D37D6577A6A5935C9CBE86CBC57BD33EAF
+:106F80003A4072728C437390F0DB668877D18F48F9
+:106F9000C0BE6FDF98F7FAA3BDB3A9FAF81BD7A15B
+:106FA0003E5BE560429F99E4EE172EE1EF64988F17
+:106FB0003847D0F50B55FB73D18EDA54DEB10CFD9A
+:106FC00026B79774D4615950C4ED098F28F38B7894
+:106FD0005CE9EF43B9FEAD5B3584FFBE404EDFD6C2
+:106FE000374BE8EDEEF6033C5C5FB8BA06D079BDEE
+:106FF0003EF6D3D776E7CAC3FA5BFFE0F0A2047986
+:1070000058F1F3837DEEA7F26BEAE75B7DE9E72DAC
+:1070100081F7878A02138A101E56FF087C3F7E7D07
+:10702000818ABFAB52BF55F120BD346E289B8C784E
+:107030002D677EF24BCE49924FB658E0B561A58DD3
+:10704000A17FB24163E41F6ED8C5F390D19F3A0D82
+:10705000E8A549D0CBF22D1F93DFA969E5229EF761
+:1070600014E1FE29F93B364B5B773C876EBD33EC70
+:1070700030E5C72F7DCCE8BF6A16FEA9E56DA6E70F
+:107080002BBF9DD0EF69F64B3514093FB28FE73D1A
+:1070900031B53FADFB0CAC1BF3498237B89DA83727
+:1070A000001E14879170907E4F090FD6F3DC05E522
+:1070B000AF9E3A3884F2E44E695A3EB60BA6F3DF2F
+:1070C000B352ACC1D1F81CE048F92C5DEBD2281FBB
+:1070D000EA6DD0031A265E7982A3F1FEB88ED78BB3
+:1070E00098B8BFD2188F706EA53CF17A9803E6A5C8
+:1070F000D43F924DE736A1BF11BBD1AFF9888DF2D5
+:1071000091C26CB59755F58C570436DA882E1A76ED
+:1071100067F2FCB4B0FF653C5720F1F2F68641936C
+:1071200031AFA961734919B9EB76DBC83E94715947
+:1071300089AF9EF9DB3C5FA099453661EA12E0EB2E
+:1071400044427CB5EE23BC02DE4E24C1DB89DEF076
+:10715000765F91F027FA64BEDAB08CABF1E59A6CF9
+:10716000E2E7BAF5D1212B75F469F6FFB3F963E9CB
+:10717000DE1399FF5C53287F67CC9787F83DBDB538
+:1071800082F066C657CDDF1B092FEC7537DD3B3C1F
+:1071900067109B77393C9F27FC9E735AA690FDFD94
+:1071A0005411DF17BCB016733F197B71AD93F9C151
+:1071B000F87E69AD87EA7F5CEBA5FAAB6B352A5F99
+:1071C0005B5B4AE5093BCF2B92FC058440F97DBB14
+:1071D000055FED2E92F19FEBBDE8E7AEF9FB4B1595
+:1071E00016127DC7A64F2A22BBDD902F527BA531F8
+:1071F0001FA4C326F2CDB6283EBC4FA62170A9A17C
+:107200003D2B1D19AFA3FE11F92B0D9B33E91EBBBE
+:107210006BA6661BDACFDADCCF506F2FD2F87D6A0F
+:1072200035830CCFAFADBBD850AF17BF1FC1B42A49
+:10723000E21B19FF02CDCDF1E2E16D3F59393AFF72
+:107240004618FF93C3367A6FC6C7097B98F6F3E1F9
+:10725000871D3E8CEF9DC4F36F503FF94795F28B2D
+:107260004EDA58D80322FEA4C23660C9AC9CAFCE19
+:107270001CE57C55F37795E13E9EFDD441F1C1C6F6
+:107280006D0A0BE3DD0C5D007918F7FA9F3868DDB5
+:10729000F3B7A92C48E7ABB4368C935FFFC8501FF7
+:1072A000C647E70C8A16E179C3AE5FA6F8F0DC5753
+:1072B0006307FFFE24ECCF33313F4A29A778C45F30
+:1072C000A7B52EB460BE9D7A3817F9F5AF4FF1DF40
+:1072D000355BBCEA8F951E80F392E7DA5EA9827176
+:1072E0004EB4AA34EE078F3976A8C4F7FE7CBCDF13
+:1072F00036BEEE08F929A614063E43F9FEFEC2C8C2
+:1073000008923F6BB87FBC277C60BD886FA4579DF7
+:107310003C8BEB371E7F0321548072A2D1E6A3B8C9
+:10732000EC89AD368A17823EA07C8313ADD9162E28
+:10733000879E22BA6BB06A76FDB80D5B553FFF7D24
+:107340000CCD8EF36577AA41361AEB3C3F22BC592F
+:1073500009F2F88F11BFD7AD1A4DE7A2CD795CB213
+:10736000FC08782AA88B2B2D799AC77FD9A80EAB59
+:107370003ECF5DFA6758B0CA709FD1B281F7FE6008
+:107380001C94A7FCFCEAC5333BDD24273FB43C53E7
+:107390007923941F4C0BBF6B05BCBCA806870CC09F
+:1073A000BC21CBD6ED0AC5558EFF00E3FEEF3F6151
+:1073B000F3111B8ABCB1253F5D4CF1A9E4F602F341
+:1073C000F2F875344FF1E2EDC48CF24566B336E164
+:1073D0005F88F03C039C04C0C7B38CC7C58E57B808
+:1073E0006FC5F3C38DA6F3C6C7C5398BAA01DC6E82
+:1073F00092FAFAC6015C0E345A387FB2BDFC1E4ABE
+:10740000F97B71528E4B792BE575CD009EC722E535
+:107410002C636D245F168AFB92973DE6E0E78B3480
+:10742000E641382EE668621B0770BE5E627FE21E90
+:1074300024EB45AC9DF4DEFBB6C8C2F612FC7EC759
+:10744000862CFADEE68B201F47E4EFD159498E2CBB
+:10745000627C9ECB5B954854E7EF90BF4FC2504F84
+:10746000E8E44E0FBD60D2070B84FE5BC04CF946CA
+:10747000AD463D154873D3BA96B48A3CECEE79A973
+:10748000EC2CC6BB8291E7A6D3BC155F24C13C1689
+:10749000B1AE28DE8BBCFC717E8EC93C2FF33AFA6C
+:1074A0003ACF85BE9913F17EE5EE714DF396F06605
+:1074B00078B04A870709F785610ECF857B14C2D75C
+:1074C0009F85BD25CF079AF1BF8805A6A39C5B7455
+:1074D00017EC334BE2F420E960F193113A0FF80115
+:1074E0006B4D77013F2CDBF6E4AC31F0FDA2075E7B
+:1074F000B423BDD7654587583261FF199E70474D4B
+:107500005102BD6FD2F35F179C98F05BD177009763
+:10751000053B55CAA3D0B513790461E287A630FFB5
+:107520003DC1A697555F0B3C6DC29F392A3FFFF9BD
+:107530004AB8FDB3E76DB66B760DE8DDAE31CB9B97
+:107540001E768D499FE2790ED49F5DB93C3FFD13B5
+:10755000AB3F238BE4B4490EE796D37DAC520E2F9C
+:10756000147A508EB300F51FD4DFDDF68B74F46708
+:10757000FCF9AE5FE451BE06EA9B61717D73432363
+:107580001FEF865FA550BED45FA7B58F407BB0EEDE
+:10759000C1E7D3F5F7BD7E5010FC03CA5BA91F9766
+:1075A000AB3B06E0EF1A4A397BCE7D5BB275BACFB2
+:1075B000B14EB7719D0DB84EDD399546B1CE7736D7
+:1075C000F3F51DDFCAD73BBFC73AC31457B9E1C7AC
+:1075D0000E5F98EC8E28E9F5934FAA0CF759DD76EB
+:1075E00087C90E38C35AB7233C96AF7EF54D2BD0D2
+:1075F000C5E20B003E400775773A48EF2FFE258F16
+:10760000A7BEAF54E75340FF4034FDBBF07C09D820
+:107610000B686FC4E7D16D077C3E406F07F4117EA5
+:107620002B845F6BC59EE7E977B4143FCFC75C211D
+:10763000EFB5D96DBAD7464319C0CFF93B114FFD0D
+:10764000CDF77171FFEC7F0FF978EE6AA2FFAE0BF8
+:10765000F4E7D89A53A336CC43EE7A52213B69F92A
+:10766000F5D5E9D50CCFB771BF5A7E31D76F8ADF18
+:107670004FF9350EC06B2A8C5758ACF1FBAF340F65
+:10768000CF377F80D13D3A72BEE6E7E86F77A23E02
+:107690007459481F9AD73FA598EBCDE5AA85ECEB26
+:1076A00065766E67778AFB2B868A790C2DE6796082
+:1076B000C38BB99FA113ED4A8C777FC341BF63C4CD
+:1076C000D844F2BB5B19A73FAB849BC7FA51377F05
+:1076D00093FDDCD51FE13497B5D3EF224EAF9AA9C5
+:1076E000E1798637F39C744F14FC09603FB3453F42
+:1076F000476CFCFCC29B3806AC6BB6F04FBF89D719
+:10770000A3C2F86F16D8C9AE0D3FED20BBE1965469
+:10771000EE3F64391956E4876B859C9A33CEE14776
+:10772000B93E7BDC2D012CA1BF300378D539BB36A7
+:1077300096C138EB2C5CDFAFCB62DC2FB0A1A3028B
+:10774000E1770998C998BF0FABDF7536BB373A327E
+:107750009E9F58867E86B18C135815C1D7505F66A0
+:10776000E7EFE73DF41F33EEEACFD81F306B0AF5A1
+:107770000CC208E9A23E83F6BF33F07C4116965650
+:10778000A2B7CBAD2C6CE1E56617DDABE435FC2E82
+:10779000EC55552C9A01EB8B1E329EEFB83A6A8954
+:1077A0000EC5789135BA0FE167716A360F8C13A850
+:1077B00051CA11EECBD6F76DBEAB1F7A6AC65DE338
+:1077C000A08EF779E13CBFAB50BED06C607AA4D3F9
+:1077D000B95676402DE7F8433A6CCED2C2D46E1536
+:1077E000A77379AE44E2A50CBAD7C377B6981FF455
+:1077F000B3391DBFB727F6AB7CBF58C6E3B8BDB6DB
+:1078000054F0ED5249778F1BF935827C83FC84F666
+:1078100021C06DB62893D1FD83822F1E2CE6FBCCB0
+:107820002DC5729FD9B7F1963B5894D6FDB483F01D
+:1078300028C79D21CAFB8BB9DD29E721E977215BA8
+:1078400049F93C0B859FC6029284F2835B7FCCFD95
+:1078500042A6BC23309428BF6DC94EF3739D9F4749
+:1078600035C825F29B2AF6AEF9383FE59B293EA4A0
+:10787000F7D9F636F20F98DBD9F0F75331EEB61997
+:10788000EC2A45C4CBA0EED8AAD0EF5ECCEEDF3513
+:107890001CF53948EBC9742E54D8DB0B057E1DE26C
+:1078A0007EAB85685F615C0DED2B84D7366E575AD1
+:1078B000853DDCB0D5686FCCDEA0B33B7961B81FE5
+:1078C000C061CA53B709BBE32D7BD77094FBE6FBBD
+:1078D00002DEB2F07584F318BF573387BFB70AFBD7
+:1078E00052D2D513C53643DC4D9E3BAD4379C5EF2F
+:1078F0006D30E569B9E8FE983A85DFDF29FD906FC4
+:1079000088F214D8A1745FCEB1348A839BFD939D15
+:10791000D5EEB045E7A79C9371C374844F5DBADD83
+:107920008AE51BDDF78A75D0F8C73C03C9FED95438
+:107930003D721BE627FDF9A153339C45144D11E719
+:10794000A73E7D01F3E9AFFC02D643F5D80C3F8E8C
+:10795000F36CD75C2788EEBF157F36C30A7ABEF377
+:10796000EEAEED58776B9600D56FEF1A80772EBB91
+:1079700023765E5F27FBB307304FB9F33E5E7FFF90
+:10798000217B00F39FEAC4B9A5BAB10AC9DF54C18B
+:107990005FD2CF5467798697E3F9EFA29CAB5D9EE7
+:1079A00016482DCEC5FB504FD0EF2F940CF4A716E0
+:1079B00043BBF401C133582E99A984ED78DEFFE56D
+:1079C000C80542AF25FC9D9054A1A70A4A02F4BD08
+:1079D000F4A3433F7FC7FECFD5CFFF016BCEE90AAB
+:1079E00000800000000000001F8B08000000000065
+:1079F000000BD57D0D5C5455DAF8B973E70B6606BC
+:107A0000464003F9700604B140470545A51A011127
+:107A10003FD041CD2CAD4634454341ABCDDDDC7785
+:107A20000651336B0BABB7DCB2763273ADD75A323B
+:107A3000412C3F06B5D26C6B4C6AA9D4C532BFB29B
+:107A400022D35DFAAFBBFECFF39C739939D7416D5A
+:107A500077DFFDFD5EFCF93B3CF79C7BEE739EEF10
+:107A6000E739E75E2E5DA23F371312D94B43482E0C
+:107A700021BFB7B9227B752764FAC2F46877162153
+:107A800051296E838DC2F3CA24AFBE3F21A4C5978E
+:107A9000E1B210329E1067BD99904BFCFE4BAA7963
+:107AA000EEB35F368FF59F99E74FAA79EE94E8BD64
+:107AB00043E97FE2B0C1FD77A439B360DE7BFE8B82
+:107AC000B8611E52345C43061372AF91E0CF8FD57C
+:107AD0005B338C39B4DD648825763AEEF56D29B3D5
+:107AE000E93C6431BD2981906F9A3FD3DBE83C0BC0
+:107AF0003A64E28C25A4AA43C276C196667D311D04
+:107B00005745DBC210FC2A39BE84B469275A82D794
+:107B100007D828BEDDE1FA6A6CEF79FDB4D64DC70F
+:107B2000DDA3A93FF16C1CBD3C4C72BC6CBB7C9DC1
+:107B300009FCBEA38494D4675DDE3FC426617F5DEB
+:107B4000BA7330AC339ECE01B0AC61EB558FF7F217
+:107B5000F9A64792BB5CB47FE6608BD146E99DDB1A
+:107B6000E2AEB5503C66AFB50F94E91C03520A9CD7
+:107B7000301F99354CA057494F4202B03E6D7B0FE4
+:107B800042DB1FB7E746138AD7F498C07D64002113
+:107B90000FFA32EA8CC9848C7D868EE989B7380960
+:107BA000BDB7C4C061EF8DAEA27C0AFF4346F84E5C
+:107BB000DB903A2F9D671FE043E7B963487624E9DD
+:107BC00047A9673769ACD1F4E6E4190F021E770CB8
+:107BD000B9B118AE8F30583266207D09CA8733D9C3
+:107BE00035C596CBC613BA0EB7DEDFFD56BA0EF713
+:107BF000FBB2C34BD7E1EE6772FBC2D06D32A7C3B5
+:107C000083362BCAD13E0DC57360100FE5F9845839
+:107C1000EF0BD0F98E2F4D18B08ACEF7BBE411BF11
+:107C200082E729CFFF5DB27B4EE8F32946FDE0FAFB
+:107C3000B5E2318BE3F12BE01B9DC7954FE58CD36B
+:107C4000FA12FD3FB1C824C093C7C5126766109EE3
+:107C500032395180A74E4F13C6DF3EEB06A1BFD489
+:107C600010C8A93607E55B8D8FD25246215E559626
+:107C70008D5184A27864FB854FA7513DF97EBDEC00
+:107C80009028AE7377BCFCE9703AEA1C5D702CA5B5
+:107C9000DB392705E87ACF6D917D5E3BC887535B62
+:107CA000DA83900A988A8E9FBFFF4DFD08FA6B45D4
+:107CB000F59C71C0C7B93EDD976D21785E2017F540
+:107CC0002495EAC346F17A1579F407B91F407EBDC1
+:107CD0002B9BCE53AFEAAF1E759244C138ED976D22
+:107CE000CA3AE9F3171FB63FB63764DDCFD92C7116
+:107CF000276EA0BF0C24032FC9F0BCB3EFD215929E
+:107D0000C2A666E453ED7ED901225A9B2C1189AE9E
+:107D100073D416832F82AAD6B7DB8EE96D945E7F6B
+:107D2000F5D81EDBAB03FDAF212416EE3BA66FA3F7
+:107D3000D787DB6C48A705DB7FD013CAF751DB1769
+:107D4000A25E17533B164DE527D04CB2B7D0F9BD14
+:107D5000768BE3653AFF3D2B4713328890E88E69B6
+:107D6000D856D68DC6F9E6774C4278418709E17D31
+:107D700091816242F1D8D7D88DD4523C3E92FD1900
+:107D8000CFC13C060BDA89D2C43B96C2BAF7457A1A
+:107D9000B3EEA5CF2BFDC3A812A0EB822D9213E466
+:107DA000AC5426FBA418C03702E72B953FCE5948A8
+:107DB000AF8F2DB47835D1D84F08ED97075B5611AA
+:107DC0000ACB7A6A2FC2C8E77BDCBEE8DA18DE236A
+:107DD0003BCA703EA5FF8FB654945B05D6755FAF66
+:107DE0002D3707D7A36B93B01DD37103B6555BCA6C
+:107DF000B436FA9CF7335F8A033AD1F1667758BB01
+:107E00003C249A84B15F4A6BE0F6781AD8633AEF63
+:107E1000DE54E757A087E397B4698D604FCD46EBFA
+:107E2000CB540EC6E70DB0CD0E5997BCFB3662A3FE
+:107E30007264886BD739E9FCD3681B6ABFEFEAC26A
+:107E4000DF9CEEB4DF35B85EC52F91CC2584503968
+:107E5000BFD3CAF056F4EA533E5EB93F2031FDF07D
+:107E600036187C2FD3DF8FA4BAFF06F8064690A9F8
+:107E70009BD19E0652CA2CFF3EFC297F8DC0FF2855
+:107E80006D1B89017F6657F0677A7D35FCBFB33182
+:107E9000FFFA914C16835C7C74F3CD0127C5ABF9D6
+:107EA000C14183C03F28CFEB66D7E338626DBF087E
+:107EB000F25AB5D3645B45D7574A790370FB0E83FA
+:107EC0006F9D1DAF13290E5AC33A89F65745B56702
+:107ED00080FF29DC15E107B96DDE15A1053FF24EE3
+:107EE000BABB9BBD3B5CEF532451F9766E376841BA
+:107EF0000E7AD89C3170BD2B7CAF66C7147D54CBF5
+:107F0000997B25D33F37D7C3195C6ECBB91ECED032
+:107F10003AA21FA078DFF5814CC08E972F91B2B79F
+:107F2000E4804DB338D243F450D1371DC8E52090DA
+:107F30004F2697951DDDB87EDBF9BC4C0F4AA9830F
+:107F400006FA94DED0CD07FABDA02316C729FAAAF7
+:107F5000E869629A7B04ACBBB496EA377D8E7B6994
+:107F6000420EE84B504EF45690272A27F1B343E4D3
+:107F7000A0B6F9272DC8892E5F423931D0B63044DA
+:107F80008E5C9D718AB5B807C563FC32BB66150966
+:107F9000F617DB19FFAF55DE0771F92A37FBD3352A
+:107FA000743E5D75846329C5EB5C9C0DEDD8A2879A
+:107FB000294049B048E72A843863D16F2507D85F44
+:107FC000883FC0FE0C6EADD6BB43F0BBADA31FB166
+:107FD000513A4DEAE88DED8014F7647B2EF0670A84
+:107FE000A7633F6C892D4F03F8DC67647EE67CF560
+:107FF0004377C2F3CEFB0C0E781E21798CDF1CDF99
+:108000005CA7E3BA0700BF0F74E4453AFE54845BF3
+:1080100006BD3C954CAC4F521467AEA17CA6F39EB6
+:10802000D211AF95F2731685DD007723CE6E034132
+:10803000EFE83A43FCCA056D5D0A49A3FC5DF4A76D
+:10804000A35A6A0AE76604FAF9E973A78F60FEFF8C
+:10805000EC7A1DFAFFCAE68F076B68FF19BBF33A8B
+:10806000426DEFE89EEE05C0D779137DAFEB287C1B
+:10807000CF6FDE8C1A6A0BD2B35EEB4FD7D2FBEB1D
+:10808000291DBD14AFFA47E5121F8B7B4C65D957EC
+:1080900097EB791D69481FC5DF28F67BAB279E2E1D
+:1080A0002268C7AFE68714F99ECFF5603EE8010964
+:1080B000F53765AE1120879992239D84FA1BA60F90
+:1080C0008A9DA6F28E7A539A96ECA82541BBADF60E
+:1080D000477BE4FA2787D1F52E4D75FB80DF05FF3E
+:1080E000F3B7373FA75D959B5F29023E8DB84122CC
+:1080F000B2742D76F2271DDAC9256504ED246D438F
+:10810000EDA4AE8B38FD65FBCFB3F34FF2F134BE77
+:10811000C5B811EC78E87C47520BB6C23AB6DB25FD
+:1081200036DFBF096FB57DDFDEA9AFD766DF5FE55C
+:10813000785FCDBE7FC4EDBBDA9E133A1FD8F3EF54
+:1081400077F4F581BD3F4AA8FD07FFB6DD647B9952
+:10815000DB7BF40791D1BE2BD9FBBAF4991F756173
+:10816000EF0340B77FD5DE2BF2A5D607B51EA8E5F5
+:108170007EEC2334FE023E6D9508D8D760BC455096
+:108180008EF7A5323956F42624FE423F4FF5C197AB
+:108190006EBF5C2F7FACFE538E0DF2CD1CCB002248
+:1081A00005E55DD11745DED57E644EAA5B4ACD0D4F
+:1081B000EA49E566B51FE84A9EB6E9207FD555FE37
+:1081C000C0FC006D43FD4057F18E3EF5E7E9C179F3
+:1081D000FBB5C50B09A97A9CF77F519E12804E61B1
+:1081E000E4A967EABF204F57E023FA1945CEC61E1F
+:1081F00060F241D258BC4FE505F1DEA74FF6D5DA63
+:10820000C1EE317B38F612A9067ADEC5EB098ABCCD
+:1082100016A5B96F0AE533C4F710B75F6B5C382D4C
+:10822000AE9A38E9F5BB681B6A370CC0BF30F17DE8
+:1082300061EACFF3F30352AF8DCF93399FFF8D7176
+:10824000E15DA961EC047132FF1FE48B6112C8CDBE
+:108250008F7E2D01FDEA8AAFBA358CEE0ABCDCAF09
+:1082600055FC6B2CF8572A2FEED47F21DE2C2DAC39
+:108270003F6FA4A1DF7FAD1B5EA61D4AF3F43CC295
+:10828000EB1FF9AB9D5AB02FF4F7613823D6473E68
+:108290009239ECBDF16011C563EC939DFD5EE81F62
+:1082A000991FDD594F81544219FFEB75C30E3E8A69
+:1082B00078D7313EBADBB4AEEC103887C2961038AE
+:1082C0004F05AF65E3C18F58711E1FB3F7747E6908
+:1082D00020C0CA7C5C0F487B71378817B74856A806
+:1082E00087DC9EFFBD1EF8535AD8F66E225DEFEA7A
+:1082F000754565E6BEF43AD8418AEF8BEBC6ADF61C
+:108300006AF9FD3DB03E863F867AC929533E55E65F
+:1083100049BE54FBE5747C3155F467F0A315EF2793
+:10832000FA9C9F773FE82FDE9F8AF7FB0D3FE3F92A
+:10833000B7E613A72F8C9DFC8362272F5258999F75
+:10834000D26E523DCBC3D5E3B7F2F1018D663EA1AB
+:10835000F4DAB5CEBD1AEA652309938FE6757795F1
+:1083600079991C12A76ABD57C2F7E55431BF831F24
+:108370009B78BFFF4AF4FA9FCBE8C5E5A3429497E8
+:1083800068AD6BEF8F148FE838C90A71ED0257C4DE
+:10839000A310BF97162AF23DAFCC9944D71741845A
+:1083A000FA5F50BEEF292BA274594094F1F3578322
+:1083B0005F72693AC73379DF2E75DE9F49E5074B57
+:1083C00071F4FE2FD655AEF666213FB01F61ED1554
+:1083D000E4BD5E05E7ABF483CB37EA27D86D4A9F4F
+:1083E000F43076A383D3E75B894C05BB172860F193
+:1083F0005E2095B5F1692CBE23696C9C318DF339F3
+:1084000032840E49413ED31F3FE41121EB463ADD51
+:1084100016A7ACFBD1B271745D8118922D513989C8
+:10842000495BB97A59889CC4A53D8A72129C6FD564
+:1084300041A0E36D9C4EF1698F1CE4722481DECD76
+:108440004781A072B045F2CA749DF3410EC2ACF3ED
+:10845000CBCBE5C8ABBADFA9BBC2FDA72EBFDFA956
+:10846000BA9FE8E27ECEFD9C4FE3547C2C51F1B1E3
+:1084700048054F57609F60CF143B57DEB47A798F21
+:1084800038A8374AE026C05EEBA5018464BFF4DF5C
+:1084900065E60490579B2E91DAFC012F3D73D0487E
+:1084A000ED5919D83394DF35AB9DBDA97E83BE232A
+:1084B000FCDB32677F909FEAE5F174FC90979E5D4C
+:1084C0006DA4436F5FB65A0731CDF097D6AED6D2C2
+:1084D000796FCBF9C3BB309FB6E68583E3A42BC885
+:1084E0006B9D6A1D6B55B05735FEA9ABD8F765AAD1
+:1084F000FB97A8FA1F55C16B54F04AF1FE19B3243B
+:10850000D49319947F40B8ABE94D595A679ED1E98D
+:10851000CF2433C64982DC8FAD65F0B4973695AD74
+:108520003487C069AF9781BE2B72AC23EC675A1CAD
+:10853000F182FFD07561CF46A7752147996A7FC741
+:10854000FAFF0CBF26E03E8BE097F7C822DC2C2B0D
+:10855000786F3F785F165C54E0B7CBA07ED1E5BE64
+:1085600007D95606FB1E631FE7B0B7A90CE23465B6
+:108570009DCAF8E2BF5F92E1790BD39ACAD6C3BE17
+:108580004A813F1DEAF5D363584BFD8C0C7EAC8AC3
+:10859000D73B8A77C82EF033D323FDE98BB242D67E
+:1085A00049EA33609DCD0FCAC81F6F2DCB47CA89DA
+:1085B000430FF58AE6E8E8C51BE8F83D0FCA8BC112
+:1085C000AF1D5D1CDB03F289DD692CDFDB13DDAB46
+:1085D000C7DD146E36DDA5877A6DF34323B1DD2D3B
+:1085E0003B57B453397EFCA5F7D0CF379BA2913EC1
+:1085F0008FA4ED29ABA17AF1589A0DEF77C7587B7C
+:108600003441BCBA4A47A05E4D88E305949BDF180D
+:1086100006ACA278CCA8B901F78FCAFFBBAC3881F1
+:108620008E2B5FAEC37D05FAD30FF076AF1AA98704
+:10863000FE59CB78EB1D85EDAE7FBC79A01F1DDF09
+:10864000FEB0EC584707EFEC488D2AA7787D15C19E
+:10865000ECF097677B47019E7D7ABB9F4DA37C9D85
+:1086600011658994C079586D5113E9BCBDD39DCF74
+:10867000A5E506C7EFFA878CFB606F9F2DEF01FC25
+:108680007B99DBEF9D1DE53DCA43FCFDEC6FB548D2
+:10869000E75D7ADB7D105FEE8A4C96BCA8C7F5B12A
+:1086A00050B79DC5E36B2A2F8BDF0CE3F79F4893F0
+:1086B00071DEE386C5E42B2AC4CD8F74CF073C95C9
+:1086C000FB94FD375D926D60681CBDAE57C11BB059
+:1086D0008EA09C1D3D087283713485B7BFF4F96A82
+:1086E0002FF8C23D34FE073CE29CC5E007C8925813
+:1086F000B60F1A5F9F115A8F08C6A94BB93D60E3A8
+:108700008E782D98B71ED914E1837CE688F70B4B41
+:1087100068FD5DD1933951162F38E393168B16E817
+:108720007A54EB39F14BD8377C5E877674F6F3DDFB
+:1087300097B4833DA0FC847A90FAB93D7AEB709EA1
+:10874000AEF707BF11F5847C53E63477AD279FBEA3
+:1087500074A66CBDB96B3D99C3E3F6E2E7752E9044
+:10876000F339B9162DECD3153CFFCECB208F731601
+:10877000460C3450C4E73C6F40FEB6592C5E2BECDF
+:10878000234659B4DD68FB0D9787B69A08CC53E4AD
+:108790001E7AB47BF28A5C1BD0A750265A23F52B95
+:1087A0007294C3E662F032A81B2EB7E4D980BFB141
+:1087B000BD993E74F6474F1D23F50BEE9B9D5EFC65
+:1087C000E4D343287E67886FCA10FBBFBE8F56452F
+:1087D0005CD1507FFCDFDA47D3F6B6C49DA0A97800
+:1087E000701F2D2BFA5610BFC532E22D2F8DF001D0
+:1087F0003DE514E627461109F7D18895AE3F3BB811
+:108800008F26FF6A10D2E7B887CA551F4A972823D8
+:108810008E977F25FB0CF4B985B1ACDE2A3F5D460F
+:10882000605F8DD2D56BA5F0A8B86ADC5FF3829D3E
+:1088300001FD9688AB1EF5DF910279F2ECE72390FB
+:108840008F735E98FBE96F73806FA571A1FAD48B6B
+:10885000CB1F9D8F186382F39CACF9750AE053F827
+:108860003B9A5F42DE29BB9FBE0DEDA609F7DB8870
+:10887000B5ED3743405E6A4C03A04E3EE7F9849461
+:10888000D4ACE0FD73963E98C1EEA7796B14D8ADD9
+:10889000085C4FE51603CACB8C876527FAC9643D8F
+:1088A000FAC92F9745205C999487FA3643C3F6DFBF
+:1088B000684C188FF69D919C549A89F34D33D8FBE0
+:1088C000470332E38F97F34D0FFC19D63B169F7F7A
+:1088D00017D098FAAFDB7B73BA68981C919D12EEA3
+:1088E0003711526D033B305D23A1BD53EBE5D8DE5C
+:1088F0006C9F6F468AE34EB86FFE6306C7523BC358
+:108900004156F0A179D37C4D6036EC43924603D6B4
+:1089100037AAE83A22A2D8B987CD14FF2A2DD1EA86
+:10892000A13E6563764DC1A7CA56360AE495F6B7EF
+:108930006A69FF7C0BB3CBF3BBB1BA0FB1187D2FC3
+:10894000873E0F704E63F7D9A240DF86A2BC80FE3F
+:108950006B68FFF784F51746E5D9DAB270FF7E251C
+:10896000D44B009FBEFD429E4BE1847E208F0BB511
+:10897000A916E043EC94A9F0BCD764B44F54A91EE7
+:10898000CB8338F0357910E4B3331EDE53BC06E0F8
+:10899000370658018519AF1F423F750F97B33688C8
+:1089A000FFC16F51F80DDADEDB9BD907B7CCEA398E
+:1089B000F7F69684FD50A57FFEC33AE4C7FCE54C6C
+:1089C0001EE6D7FC09E79D6F09F4007ECC6FD00D41
+:1089D00006B95EC2ED45794D727E2B958F725DB4FE
+:1089E00055A2972ABDA57A802BEB248495E7CD7FED
+:1089F000F8931E9A2C361FB4062E47C179BBA78068
+:108A00005FFB66536CCA8C10BE7FB36C6B14EC6B4F
+:108A10007F15E14FB7423D666184631DEA29E3C7D4
+:108A200037CBD2D741BD6696356081FDF059F7A5A9
+:108A3000C580BF3B6AF5EBA1FF68BD5D03B0D36A9B
+:108A4000CD07D8A9ED8FF037FC9C0AFE503E2D9043
+:108A500098DC546EDAA34FA5CF7B91D3E7DBD70E1A
+:108A60006540DD607E4A2003FC3095AB8C44E0CB52
+:108A7000AB12C60B0B36C9CE887E41B95A0072457F
+:108A8000F57F1E97AB055BB63E007ABA00E469E05D
+:108A9000E57249F3CBBD787DF38BC584DDBF17E468
+:108AA0004EF1FB145EA683FA9A9EC3F43900AFE33D
+:108AB000F4A7FD45ACDF9B85FE84B4E9212EAE9280
+:108AC00059BC40F5291EE289AA269DB72DC43E2E29
+:108AD00080FEAC607F5772B3A737DF2FAB31A05F4A
+:108AE000DAC3F5AFEDE18628908B6F5FDBF3EE30F4
+:108AF000C8B3364B56B0FB97E921A75B15D0290ABE
+:108B0000D789F15115D0252A48A74E7DE3725145EA
+:108B1000181D14BA5469399D947E7EFF5E4E874AB3
+:108B2000C2E9BAA50FD377AEDF5462D08F28EB73BA
+:108B3000C788E7072EF0F57DCCDB4A2A378E2C94C8
+:108B40002FA77E30CFFF69D7B76FBC88F523859FED
+:108B50000ADE96749B62A79DDD62827C6ED3908A4A
+:108B600070F5EA539C7E3A33B32BC76A12EF5C4C24
+:108B7000E9376F93EC40E241EE15F25C83A6CD82BB
+:108B8000F1E9AF642BACABF07FCAC6C0BA15B9D35C
+:108B90006D94B44DB04F48BA21FD15FC0AAF738DEA
+:108BA000E9C6E4CE0FF828781E93FCC82FEF1B927D
+:108BB00095C5BB6D7AA8232A7AAAC6F702C7578E35
+:108BC000928649FD011F870DF49B503F88F8985B02
+:108BD0001FC4E7798F3C68EF177CCE51AF450BE39C
+:108BE0008E12660714B93CC6EB12C7966FC578584B
+:108BF000798E29FDB2E7B817C75DFE1C65BC9CCE17
+:108C0000F453D18B7D314CFE0B97FD09C7297616A5
+:108C10007EA01EA7D053A15B885E0AF451F44BD10D
+:108C20002785AFFFAC5E9125DD316E7D88AF1B756A
+:108C3000A447D02F807C82BF33E8D939B810BF89D0
+:108C400071CDA8A41FF4EE30D7153AA9AF07F32AC7
+:108C50006B0AD07F94391EF7CBC9B2F8BDBD43E291
+:108C6000B3AFA0EE05F6F415D987F69450AD0CF12C
+:108C7000E74ADC56B370947504C8D72609CF1D297E
+:108C8000FE9BFE3CDA29A774BE8A9C8519104FAC66
+:108C90004C4F65FE2CCE791AEEAF3C15288EB205EE
+:108CA000F3971BCFFBE568A80F6EB10BF943E5D92D
+:108CB000BDA8E7F3496005E4BB331E3E543A04F80F
+:108CC000FF8A0ECF2FCCAAB3A3FF3BBD7EE6204880
+:108CD0006D672C4F4778EECB7733F86116D7CD58B8
+:108CE0009EBB01EAF35F45388B41CEDB574B56C83C
+:108CF000BF86BF9CBBE476DA3FDCD2AB1BE07B6473
+:108D0000FD57A5C3208F582CA3DE38D73F3905FA6D
+:108D10009D4DB20396388B5897DC0E72AE8D46BDD2
+:108D200053CE35D6EA98BCCD4C67FE725A3AB31B87
+:108D3000D3B8FC16D6D666C0B982F617A99F82FDB5
+:108D400075BDADDE0F79E08EEB1CEBE873AA68DA37
+:108D50001A4FE5E994C4E2F10A3D31827CEDD70572
+:108D6000EE07FCF7DF6F19500308C8170797B3BC6D
+:108D70001DED0CCDA3F0B90ABD94E797F3E72AF3F4
+:108D800028F7ED83B80AFC08C7F7F4B257A640BC31
+:108D9000707A637A0C09A1FB695817A5F75C6A1F02
+:108DA0003787C907ABD2957AAB0FDB0A5E47DCAFDA
+:108DB000AB4B82FD5C1AD71F0F8DCF4FBE186104DD
+:108DC000B9A471BD785DC7FC0A8DE785EB547F04BB
+:108DD000B833DF93A747BBC3D823A555C7FB4BD3F5
+:108DE000CDAA73732CDE57F44F7DBF12DF77D65DAB
+:108DF0007AFFBC735D673D9431542186417046EF24
+:108E00002F32FDFD4D387F39BBCE603550FA1E073D
+:108E1000FD827DC10699C58B46A66FC7770CF041D0
+:108E20005D61F661E2F05378768BECB0D1F17B575F
+:108E30003F84E73BEE5E2B91EBA490BCEBA9D553AE
+:108E400040DDCE39DC2B12E8F8731BD97914DA6DCA
+:108E500056E55BEF26D8BACEB7FE5D7996527F52C3
+:108E6000D37F733ACFB71CC421D29FE5EDBBA818BE
+:108E7000E50DBC9CFE673D6ECCABBEF354603BB4CD
+:108E8000FEC5C244BA8EEFA5638F0D073DB24463A1
+:108E9000FDE4ACA71A3707BF6B1A74713CA5D3DB8E
+:108EA000E6682BD88FEF3C8BF17AA7DC7039BD7167
+:108EB0004BB39C4870FCF6E174FC4E73346C7784C1
+:108EC000D987637C569FBFB977E190EBE0BAB2DEF9
+:108ED00033BF64FC56F03FB3716614C4ABCDCFC54D
+:108EE0006E1F0A7C36455B4114E6F0733827D63096
+:108EF0007B74CA18BD611CA5DBA9B5937A407E7846
+:108F0000B7AE5DEFA0F33A769445417DE46B6D5BBF
+:108F100094155A3ADE0F78687D32D8C1612504F77E
+:108F20000787F9B5C466C7AD7B949FA167B53EC8F6
+:108F30009BBF817D43F0E31723D9FE3DDF0FBC7B50
+:108F40001BABB375D655787D61385F6F74468CB2B4
+:108F50000F84D70BF3D8F5936BDF1C0FF39D5EAF37
+:108F6000B302BEDFADD7E1FCF3687EAFA1F2786A51
+:108F7000233B2F306F3BCD93ED60472494DF795432
+:108F80007E8D207F0B754E7DF4E57259B891E5D743
+:108F9000F3EA25CCB715F99CE7F41523DDB99C1A43
+:108FA000E9BF4BD4757423F52B801E5DC9EB3F5B85
+:108FB0000FD06784AF07A8E541A19B22174139254F
+:108FC000289F0AFF63EA078C48C41BBC484F6F0107
+:108FD000C98478A1564F32E13C945713E900BDFF94
+:108FE0006B44543FA8432D36B2F681C8A875D0FE15
+:108FF0003522C50778FF55637D07F2AC5F67D871EE
+:109000009E07649B4EA2BF4E8A6B2B423750A871BD
+:109010006AC00FD61AD08EA8ED505A06F33FDB3344
+:1090200008CAFDCD19EC9CB88E54637CA1B4341EE3
+:109030004886F8A5CC1473018E923B36F49804FB55
+:10904000BD65C363EE4FA39167DE86A4495A2AE744
+:109050006583621A52293C2C2391F5F78FC9D551AB
+:10906000B8A626795211856FCD70F6CB08798E326D
+:109070002FBD3E2083E23132C19D03FD557AF34A74
+:10908000F003DF4BED0B347270FC41891C7D5B0AF1
+:10909000C26D3A9202F1F6CD807FF7AEDB1519CEA4
+:1090A0001B33C25C2F276439D425CABDEFB54A688B
+:1090B000CF88CB48F93981CB5FB9D1EC473BB75268
+:1090C00077B6533E52C14E456B81EFE339DB2768DB
+:1090D000FDCD707F5FB2CC7AC288A1E2DA4BB15D80
+:1090E000DB7FAAA8E484321F5DDFF73ABA5ECA5775
+:1090F000C949794D554CA2449E4EED9DB4FDBD9F8E
+:1091000060DE5A2F698B403E4CB7829F92885B731A
+:1091100089B6F34D542EFA434BE5818E5BD4F0EDC6
+:109120005E508BB94A9CE5CEC378F13E2B5B0F7144
+:109130000F4379BD9FCBEB490FA98652D1844020C4
+:109140000A8EC29E1DEFCF00FB5022BB6703BD4EAF
+:10915000AEAD4D5A44E5E7DBCD06C7383AFE94EF95
+:10916000CD28F0AB953CDE271765FFCDB47F9FBDC2
+:10917000EFBA5521F25595C1FCFE59BB3FE541B010
+:10918000337696AF928B7B521EA4E34B5247E7AEE9
+:10919000422A381766E0BE05DBAF18AF0D7F7E634D
+:1091A00072128B53C87AE68F0D5AE2B5C4604BA297
+:1091B000289D46535CF2E05C2A8565DCCFF7E1F33D
+:1091C000615C14C435B699F16CBF87B8C06E29FCD8
+:1091D00055F876193F29CA10D76B8C4407EBED4B35
+:1091E000D65A41FF15BE9EE4FA78D2C8F470A46C3A
+:1091F000463BB5A881D5F51649CCDE2EDA21B1FA69
+:10920000E665FEB66105D8E48AB533D19E2976CCF1
+:1092100046FF817CCDB3BAA2FDB67FC2EFAE2DBCB6
+:10922000267BE653ECD9003200E4EF6AF19262C784
+:10923000287B7E9F11B29F7C557E01C9E8BAE770FA
+:109240001C47CAD36D5AA04B77A303ECF9A2E7D30E
+:10925000D04F92F36BB08EA28C236B63517E57D8A4
+:1092600065E46B695322B1D14B739B243C273BAE21
+:109270002916E1A88E04844B7F7F5D01ACBB731F70
+:10928000F4F77D103EBDE1408E9BD5698C80878BC5
+:10929000287864D583FF3967A678503ABBCC2BB1C8
+:1092A000EEE8229DF990744902984A0DE89D53E733
+:1092B00065FC31D6A0FEF3752DE27AB5683FF3D791
+:1092C0008B46B0FD42ADB76F34F05FB74F263E0A14
+:1092D000DFB25FCEF5D3A1B5DC9E1BE235C416C26A
+:1092E000B7085B24B185F087789D01C8B7A672796D
+:1092F000792882D97D53668C306EAA7936CA4F2080
+:10930000A5781FACD7E2E829CC4BDC2C3E56E46AAA
+:109310000AAF9B8F27EDCBC04FDE3295F687CCA7E7
+:10932000CBFF01FD862E5F8CAB295D8E5F499ECE03
+:1093300064F0F74EFA92BE284F2AFA50FD407F7F24
+:10934000AE85BD7F42A39267F2293C659F8EF86887
+:10935000FF724E17885B21FF39E7B4A0DE28721731
+:1093600000BF47ED5C749E48B76E4E916EB12522EA
+:109370007DBABB447A5C373555E84F705F2FF427D0
+:10938000560C14E0E4EA61C2F85E8B0B04D8EE1DC3
+:10939000238C4F5B395180D3EB6E17C6F759532E90
+:1093A000F4F7F5CD13FA6FD8B84880B3EB7F258C6E
+:1093B000EFDFB454E81FE05F25F40FDAF78400E72D
+:1093C000069E15C60F695D27F40F6D7B55E81F7E5D
+:1093D0006AB300DFD8FE9630FEE68EDD023C821CCA
+:1093E00010C6171A0F09F048EB17C2F851F15F09C0
+:1093F000FDA36DDF08FD63337F14E0E53CCE2975E6
+:10940000FC4DB82F4096A5831CA725B987F7C1BA94
+:10941000CF292DE85FEB1D128985FC67DF242BEA3D
+:10942000FDCFCC030BFB70BBC8E5F80231DF09E7C9
+:10943000D9AF6617ED3C9E18298FC3F7AACED5B3D6
+:109440007A87DAAF2BF15C3475CBDA90E776731A52
+:1094500069421F84634BAC02DCDD152F8CBF6EAA02
+:109460004DE84F70670AFD89150E014EAECE13C64A
+:10947000F75AEC1460BBB744189FB6D225C0E97503
+:109480005385F17DD6B885FEBEBE0AA1FF868DD577
+:10949000029C5DBF5818DFBFC92BF40FF0AF14FA60
+:1094A00007EDAB13E0DCC01A61FC90569FD03FB4CF
+:1094B0006DA3D03FFC54BD00DFD8DE248CBFB9C300
+:1094C0002FC023C87E617CA1F1A0008FB47E268CC2
+:1094D0001F157F4CE81F6D3B2DF4577EE3F0E3BE74
+:1094E000D4DBEC7D57259E1B9BF983304E1747E359
+:1094F0007DA87F9348079CF7EF2ACE57E2C052C75A
+:109500004FC273FFAA61F1F9AB7DD8FB690FC82C7C
+:109510004EACF5BAF07C5E0C1C78A57A12ED955035
+:10952000FE20C59A8EF5C838F4B7E8326D70DE8D2E
+:10953000C6411488D1D8ED90879882716CD2A5412C
+:10954000D71EC736F52188C7C93EEED7402FE7D5CD
+:10955000BF510C79CE5CE25D017850BF1B0DFB580A
+:109560001F4688F528A51D6DA4740C79DEFE88BA07
+:10957000A48157D0DFD1C6B338BE735E5EAF92E828
+:10958000FA1685CCFF18CDBFB4544FEB3C54CF68CE
+:10959000A2FD84C78AF0539E78849FF6D8B05DE31D
+:1095A000C9C4F6598F03FBD77AF2107EC1E344D8C1
+:1095B000E729C1769DC785D7D77BA622BCC1E3C664
+:1095C00076A3A702DB573DD5D8BFC9B318E1D73D75
+:1095D0005E6CEB3D2BF1FA664F1DC25B3C6B106E6F
+:1095E000F4F8B06DF26CC4F62D4F3DF66FF73421F0
+:1095F000BCD3E347D8EFD987F06E4F00E1BD9E564C
+:1096000084DFF5B461BBCF730ADBF73DEDD8FF8192
+:10961000A703E1B37C3FE1EB3EE2BE9D021352841F
+:10962000F2A0C4BFE321EF01E1C8D37D27E43DAA46
+:10963000FC43CD8F33FC39BA021AFE42FCD33363AC
+:109640005D6D485EF0037FDE4391C41B41F5A1468A
+:10965000C3EA02353104DF0F233C3E9FC3E592C4C9
+:10966000B1B87C36C76B0ED7835C90CF4C94CF0FCC
+:109670007E4E9EA5E4DB51296E2993E2312F59E3FA
+:10968000C5BA8399BD873F20C5AD85EBE7AAEF7EBC
+:10969000179F677564C0434A0DFEEEB7423D69BF30
+:1096A0008C75D8AE9E57C5DF93E8B27FE7E924F00A
+:1096B0004725FF90B15EFFA1CE3215EA2D3D32194C
+:1096C0005D7A646A84F6AD145777C0E7647AF586EC
+:1096D0007BA5E0FBFF132035A77A5E466C3A3C87FA
+:1096E0004B9CEFC0AB37B7D0800FE05B89175B674F
+:1096F000B23B25B33B9C97F421EC1E664809B71E8C
+:10970000353E99992C7ECFCCD408ED9F525C7D00DC
+:109710009FE3E94E011F732F1B3F57DFFE02E0F569
+:10972000971D3F9C90D282F456EA1B2B46F0735A49
+:109730000B25651F9CC58946A2C489D83FFD7E566E
+:10974000EF51FCE5E1CE96D9C373D53AB49BD3A5CE
+:109750004807C4DBE7AAEFEF0FFB8577D07C0FF655
+:109760004F153B3A9DC21A0A4F27ECDCC5F4C316CD
+:109770009433B57DA5F711D8EF9B4E4906F9E3A5C3
+:10978000143BAEE743D70F3A9897C4B5E37BAB548D
+:109790006E4A809EF386CAF8FD860F35BE0C494698
+:1097A00079D14B14FF3971545EC2C40B8A5C2CE032
+:1097B000EFE528D7A9BC4D047A7EB76D4826EED3D5
+:1097C000EC1C6A037AD66AD87B75DEF765762E03C1
+:1097D0004AF9706E243AEB457CBF00820BE0DF5003
+:1097E0000BBE5FD02C93C56F84B1A7F772B9FA3066
+:1097F0005E57E2C379C57DC54ACED74ACEEFD2DDEA
+:10980000FB93E1BDC105FB749817919CB62C57984A
+:109810007355558B1FF945EF1039AF6A3AC6CE63C1
+:1098200091B6ACD073588FF07915F992F516F78B85
+:10983000E650FC3AE57C11D095CAF90988FBC71BB4
+:109840006CD1B7D25BDB2869FCB475FFCE8AE7F92F
+:1098500094737DB3880BDB3994DD20D72EEF6A7CBF
+:10986000AF7E1EA9C7EB0BF266A6005C45DA8BE261
+:10987000E97CB7ACAC79279E6237A96EF548A8732E
+:109880004FF4CD7807DAB2F5D209AF0DF5A416F88A
+:10989000D026552FEF499F77FBA611CBA18E3C5EBA
+:1098A000667C2007181FA83C39E598CBD747F5629E
+:1098B00015E04FF502F157F462FA52E294E282EFBA
+:1098C0008174EA49DE3D7F4E843D166D3B9E43A97F
+:1098D000DA698881FAC93CC2FC76B00EC4FCB5A234
+:1098E0000767748CEF675E93F03D9B3312C1EF39CD
+:1098F00074153728F127D53FA677474D4CFE655E96
+:10990000D74B71C70F4C0BFAE7331ADFE0A834F4DA
+:10991000DF1B801EBA02F7A303E0BCDEEB92A39626
+:10992000E272A69B2F859D13E8F403E49229582741
+:109930007C4CC7EA76EA7857594757781AF4C40B33
+:10994000FB5952DEBB3F411C7239BEEEF8C1942E6A
+:10995000B5C022A84B16B86CE1F058C69FBFEFEF18
+:109960002C1FF726133C17A4A6A76465CFE9AABE4F
+:109970006A8864F8287E4AC1F372BC18BF0E66324A
+:109980007BA1E0478835D34A9FAFD5463A405FCBAD
+:10999000B4EE00C887527F53F2E27DF693E80FC819
+:1099A000C5DA2476FED8DF951F3EDB998FA706FD2A
+:1099B000A452C722F9E1EB912EA315EDD744E24062
+:1099C0007FD1971C56E885752C197608B1CEEBC669
+:1099D0007518C05ED33602EA28E82F7DB82E13E052
+:1099E00085EB0A404584AC3645211D86B512B4D3BB
+:1099F000C3600D74BD3B8E111F9CA76ABE30A5D0FD
+:109A000042FB777CABC53CE819D3EB89F01D891D7F
+:109A1000A73F4D847A4FCD854684079F2D3ECDEAE2
+:109A20006787A7C17C6F9FD7DB0C18072C443A28A7
+:109A300075CAB70971C03E68DE67667CCF38B7A5C6
+:109A4000DE8474E375B57CBEEEFCF3AC1EB213800D
+:109A5000A1340F68D7137F48BCACB38A701E09814C
+:109A6000EDF0480A87D4397E6EFE68EACBEB2043DE
+:109A7000C890D0BA1AE98809FB3E957A1F3147622F
+:109A8000789FC874C5F5C5B86CA2CCE8FD0F19E87D
+:109A900075B3D99700F16DF3DC0D0910EF3E63FA51
+:109AA00007D2F1D9BFEB1380AE7523FE827EA48E60
+:109AB000DE1B80FC57EB8B2058FF9A8F75E09BB91B
+:109AC0009F7DF6E297249ED2B32E8FA0FF24DC0F59
+:109AD0002BFD7517CF55003F2FE41B6D60173278B3
+:109AE0003DB4E6A6FF17DF16428F1D34AEF65306CF
+:109AF000BF4DE36A3F8DFDB7D1B81A6078EF14DA35
+:109B0000061A5743EBA37135B42FD0B81AC6415C7F
+:109B10000DEDB334AE86760D8DABA17D9AC6D530F2
+:109B2000EE291A5743FB048DABE17ADDC5F242C43E
+:109B3000A795E0FBF54B4D511AB0AF14FF48A80BA9
+:109B40007DE41C1809F4B8E9BC46E06FFED9480171
+:109B50001E763C26C85FE0FFE19E42FFE09654A1DE
+:109B6000DFEEBD5E807B2D1E28C0501F0ABD3FB1B9
+:109B7000A2408013DC6384F1D74D9D28C0DD5DB722
+:109B80000BE3634BCA85FEC7A3547CF4556A443E7D
+:109B9000B2EF2B5CC837E3F9CAAEE4F409CE17057F
+:109BA0007EF297F2D47075DBB97D35423ED093E3F7
+:109BB000B6B0AF0DAFEF3D32E4958C1CE087866DFB
+:109BC0009B3ADB4DBD295F329ED410385788270E53
+:109BD000287E567EDF9305E74C20977B4AF511C01F
+:109BE0009F5DCE8248809796EA1342E5A8CEEE1E8E
+:109BF00088EF29B8D9FA94FB1F2F9878C57DF427F0
+:109C000040FEFA5CA17FCCBC54D087CBE8482A70D8
+:109C1000BF3648C789F87D27E2AE10F057EB0581C3
+:109C20004DFA0478AE51A4A733F561A0C3B34F69D0
+:109C3000F11C56E77CFC7E65BE91F245535BD6E590
+:109C4000F8EF72B2F134FE8D00BAD06709F8C5386A
+:109C50006C23803EBFE5FAF6DF5CDF9EE17C853C4D
+:109C600016606265F7297CABAB78627406E84D1E1E
+:109C7000C36BDDE427243037B1C451630DA1EB532E
+:109C80001C8F17F8BAD6C2BC14EE3ED92901FD527A
+:109C900016BB24D0B75E4BDA107E96EB7752753B3D
+:109CA0005E4FBECF8F6DCF8A00F68F9437E13A3A80
+:109CB000E9E010E9A8E6938FAF47993778FFE6FD12
+:109CC000206F179C0CFF28AFD909FE22CA6B75B014
+:109CD000D6C65B8703EC7E94D7C9E1EA2C801BF8DB
+:109CE000BAA2BC5E847D7C5D751571FB37D882CFCE
+:109CF00023B62A4DA8BFE94A9E9A38FD1B399DD448
+:109D0000F735E8BC83AC61F44A69157F3AB44D235A
+:109D1000E8F99056D14E7D04BF303FF0495F881B73
+:109D2000BC2E99EF5F211D2775E64BD3519E569BA4
+:109D3000EE3C00F9F6E41699307F3BFE1DB09787A4
+:109D4000461BD09F368F1E951C2A77CA3AB672BA28
+:109D50000FF53A8FDC47C797B90C8021755FCEE4C9
+:109D6000FBE97CAE71B203F6A15A3AFD89CBC4CEB1
+:109D70003B307F3291E3BC7BDCA447E0F9875AA8F3
+:109D80005DB005F154FA1B4A268DCD063E06181F1C
+:109D9000BBA2CF7B9C5FEF70BCF6707E3573F9DEA3
+:109DA000C5FDC90EEE4FDE067F6200BF93C7D7C365
+:109DB000FC4903F7277F047F42DB03DC9FEC077F2E
+:109DC00042DB9CD169456837E12536F4273441C12F
+:109DD000F3040B847529789524C9027F8AE34C0229
+:109DE000FF8ACCB1427F813651809D175305F8A67A
+:109DF000F3D7ABFC94E857861D1FA6F25305023C2F
+:109E0000B8658C70FFF89C49023C2E6B9A008FE974
+:109E10003D538009DF0FCB65BF93DCC8B532E6B98F
+:109E20007CDF4989A70E95C8B86F33F413D911AAFE
+:109E3000B7B9A4739F4C03FB64347CB16995F952A4
+:109E4000857E8CA35A74AE4438BF575346E590B60E
+:109E5000F92D344EC3E223956B1AF7E6BA46611C1E
+:109E600048E3A541C88776B6DFA4EC5B0D55ED3F0E
+:109E7000B98AC4FDA9DCABEC4FDD747D1771597E46
+:109E8000EC35C56554BF30FE7AC674E71E909B6DF5
+:109E90009FD13815E2DCCF7E81F1D7073094EAEB11
+:109EA000D6AF7F81F1EDD64E7D710BFA92CBF5B630
+:109EB000B125B5A98DEA5B4E37C9C1498DFA92C764
+:109EC000D794736CD1348C775A34187F91922AECE2
+:109ED0001FCCEF6F685D6A12DF5B0A897B306E8F83
+:109EE0000CCA0BE4932446ECB786C8672A635AE889
+:109EF0007842AE57CD3750050F538D2F50C1635464
+:109F0000E327AAE0DB55E3CB85FEA6B689578CBBD9
+:109F100015BBAE8CCBD5BA644718BB3BB8458C0794
+:109F200089AB4A38FFD07C6436DACFC6C32B389F62
+:109F30002A043EED569ED342E99D75F9FD055AAFC0
+:109F4000A91F95878216ADA3C616E4A3C22702797E
+:109F500071C87C854659D0E3A656E61FBB5AE74E2A
+:109F60006EA7B7737FF3962A8E93FF7EFED0042AE6
+:109F7000278D6D1ACCB31A5B0A62F1FDC18BB31049
+:109F8000DFA6560DBE4FB6F1D5F1B7D46883F829D8
+:109F9000F8E47CB2D404E7832E507F047296A37356
+:109FA000C65AC3D05D2D5F5DCDABC82F25542CD0D4
+:109FB0006517F547787E98DB55852EBB8F3C8D74F1
+:109FC000DFD6CAF0BDB943F48737B68BFE70F8A967
+:109FD0001801CE39C6E242EA7F71DE1C7EEEEE6ADF
+:109FE00078ABF502764844B8A738FE1AE3826D5C78
+:109FF0004E1A389FB64538A6867BFFA8E1A8BE2238
+:10A00000F4FB0A27AF67F5B993D7B3B83BE79806D7
+:10A01000F35CAAF7686F875AEBE4EA30F30C3BAEC7
+:10A0200051E52D9102FD7E6EDEFAE5F57CDF53658C
+:10A030001FBBBA5FB18F05CA77541C93C29E930DA4
+:10A04000F2819FAF54D19338C2DBDFCBF9A69C4B92
+:10A0500057F1AF8BFB83F378D579F5A5EB619EB60D
+:10A0600032F43BAB4D0BB85D5F8076FD839FB85DEE
+:10A07000FFA93109AE1F18B03509F4E840AEF23D32
+:10A0800058CABD907C5AD1A3F75B3E3685C6FB63A8
+:10A0900038EE3B320F8DED1FC2CFAEF0DCC7E5E7E7
+:10A0A0005D1EF7ECE57ABE9BC73D7E887BFA803D5E
+:10A0B000C8E4F680E5D16FF1B8A789C73D8D3CEEC5
+:10A0C00039C8F3E88F20EEC13888E5D10D99F7E261
+:10A0D000F7C52E242971CF786D383E8FB689766A00
+:10A0E00054BC4990B7915631DE2934260AE3479093
+:10A0F00034A1FFE68EEB55FA2DC63BC34F8979F4A8
+:10A10000D036318F1ED22AE6D1138BC478C7952F53
+:10A11000C63BCA3EC22EAB84E7B1C6E788F1CF2E5C
+:10A12000F885F63718D9F9AC86CC4957B4C37E6E9A
+:10A1300087FFC8F5FB3DCE9F7778FEB093D37F07AE
+:10A14000D01FE3521667E69E77EF89B6817DA8603F
+:10A15000F9426615E6D537725CB67AAA597C7A411F
+:10A16000637650BEEC32B3386B57E6CCF3F0DEFFCB
+:10A1700005ABC906F599033A37C2BB32251B7C6F84
+:10A18000508D5F6EABCACFF1784191CF5D2D5FA24C
+:10A190007FDBD9716D7E5519F71E998475979B5A8F
+:10A1A000083184A92F5CCDBF5EED39EAF1E0C7C369
+:10A1B000F91FF573C674B86542F577476BE04948F7
+:10A1C0008BC6F8E7CAF05DA8C1ADEE42E0EBDE4C0D
+:10A1D000C90AFBE9745C21EC4BBC77F1E3B1707DFB
+:10A1E000E779ADC680FB4E56C11F7D7091D21FE44A
+:10A1F00025939D4FF2B77EF9487FA8F31A657C7FBF
+:10A2000064D7C58171A1747BFC0619ED4A43964160
+:10A2100003F5E686F35AE20F89F71A3B52CDD036A2
+:10A2200064CAFC7A00EDC37337B073AB3BE87CCCF7
+:10A230005ED8100F451EFCE73525E1BEBFF31C7F3D
+:10A240005EEEC53F9B20BF7CF77CB909ECD3CE56B0
+:10A25000F69CDC256D26A0DB818E7566B8BE2B735F
+:10A2600010CEDF9CFD907920C84DAB86EDE7F0F86D
+:10A270004679DEAEAC398F0E8075B7B2BC6CD7F9BB
+:10A28000CD7BA2402FD64B0E16BF307BA68C6F38ED
+:10A29000CFEB4D3E76CE2D97783FCD06FDE9F17B95
+:10A2A0003DC839F1569250FB576815ED4841ABCA8D
+:10A2B0004FB92B511F143E946A6385FE039F4D9C3A
+:10A2C0005C067C33B3F7DB769E5F1A3711F4C2ACC1
+:10A2D0006371B38FDD3F2E58AFC1F7B594EFB0D4A3
+:10A2E000643F70A814EE6F607CCD358BF81CE85B82
+:10A2F0009BB880CED7B0C5E410D67798E0FA76390F
+:10A30000DE9C8E75ED2C03EA61E185BDE6B6903AE0
+:10A3100051679CD8B2DB3C08E87C5623D04DA1C3E2
+:10A32000A83C317FDC91B907C75F38CBE89E4BAAC8
+:10A330000FF567755873E9E060FE95DBC1EAE373DA
+:10A340007D22DE43378AF9E77C557CA4AE9FE76720
+:10A35000CD1927E4573C6ECAE37193BA4E5EAA3515
+:10A3600088F509559D3C575D27FF67E3249D7B1ABF
+:10A37000BE0F17987C4DF1C3501A6BC6E3F95EEF20
+:10A380009320D76FF1F872A8BEEEDE04AA220DB2B8
+:10A390007B38EE5BF03A9D72FF55E325AB97C40D19
+:10A3A0000EC98789F604E4972B618F13F9E265E7FC
+:10A3B0005955F376156F28FB23F945CCFF3C63FA1A
+:10A3C00010E38BC6AF597C013F6D3D60BF9EA01F5F
+:10A3D0006EFE5A8FFB276F8F66FBDE4ABC328938D0
+:10A3E00071DF667CDE79ED6F6CB09F7367F67CDAA7
+:10A3F000BEFD5923E6996F77E69975429E99CFE5A0
+:10A40000725BBBC61B0BF941ABC14742F6DB95FE45
+:10A41000C6F6F247B2410E031A94C3E66FF504BEC6
+:10A42000BFD7B8DD8078379ED5633CBA6DBB89C98C
+:10A4300035AF3F2BFADACAFDE2A79C9F07B85FDC75
+:10A44000CFFDE27BBC5EF30E8F5BF6F07A4D338F6F
+:10A450005B7681DFA4ED9676AE774B4C1C4F569F12
+:10A4600055F0BCAB4FDB112DE56BD57783D7403D65
+:10A47000EA36B7A80FB74E15E3937159627C32A63E
+:10A48000B7588F29494A13EE2F8EBB41E82F320F60
+:10A4900012ED9676B8003B2F8AF1C984BCB1A23C7C
+:10A4A0003943E213CCAFC57CF796D07CD70E7C62E3
+:10A4B000F9CCB6D627D04F6C3B9E1A1DFA9DE0AD65
+:10A4C0009CCEDB8E33BFBCF5F0394B68BFD29EE229
+:10A4D000E3CE707E9CE5FC9894E0BC238BCACA85D1
+:10A4E000E3E7F470FEA32B3956EE57EE3BE5FB2A6B
+:10A4F0002AD4EF7D0DCC08393FF46DE31719684F6E
+:10A50000AE512F6A2DECBC5B831489EFE15FEDFD4A
+:10A51000962559A95C29ABFBB3FDD1EA21D06ED0B9
+:10A52000B912E13DA806C9356D3EECF3FE561FF6A3
+:10A53000EF4AD46649CA39F426F00B32D76FB249D4
+:10A54000D2827C4570F045E2AECDEA0E45B16A1C80
+:10A55000249B5D04D6B545479AC0BF1327B1597BEC
+:10A5600010B655469FF3976CF7C3404F29C0F6913C
+:10A57000A95BC5EF7EC0112DF8FE16B4B05F663042
+:10A58000B2F70F22B3DC8FC3FCF05DDBE881306FE4
+:10A59000411ADB4FF5A39D9EC6E7D598B627E3B9D0
+:10A5A00055759EC4EDB5A2779D74AD14DF4B51DB9C
+:10A5B00059A5BEBBCDEE9A162E1F7D258BE59F4D6E
+:10A5C0005F8D97E1B939C62827FB3EA45386F7C1B2
+:10A5D000B69D18639A1146CEF6F69BF10AAC4781F8
+:10A5E0007302F532FF7B151AB1CEA5F103BF2F9888
+:10A5F000F5A8D74361C13197CFA7B6CF798755F674
+:10A60000B9739FBF4E8273679DF2040C01FE1F64F5
+:10A61000DFD5B89A3CA9F7EFBFC84AE5EF4D557FA3
+:10A6200001E74CE468339EB3D972D0B84EB65F9E52
+:10A630001F36F0BA9F1AFFE6CF6627621DE993D94D
+:10A64000ACFE07861DBF9B563D05DED3EB8461FD46
+:10A65000D00F1FB4C3EF002D60FDA315B86A0AC464
+:10A66000AB5B47B0F19F6F0A3C0DDF05DB7A07EF6C
+:10A67000278FB1F10AEC5D386504C03A568FB9E511
+:10A680003536FEE2F5CE2F803F9159CEC320A7AFDD
+:10A6900082EED0B6E87AE751B8FE05C8186D3FEEF5
+:10A6A000EB6C837E05EED6D7F965687F6367DE2B9A
+:10A6B000D6FD8728F1E0E1727E5DCD77C5AF5CB94C
+:10A6C000DEFF2197D30FB89CBECFEBFDFB78DEFBFE
+:10A6D0002ECF7BF782FFE803F9B083E7C3793C1FF5
+:10A6E0006679D7769EF7BEC5EBFD4D3CEF6DE479FC
+:10A6F0006FCE271359BD1FBE3B2841DEDB2F6CDE1A
+:10A700003B214FF42BA50ED1AF8CCD14FDCA685B55
+:10A71000A22A4F4E53E5C93708FD85C641AA3C79A8
+:10A72000B82A4F16FDCA8DED635479B2B87FFC4547
+:10A73000968DEF27DDAECA97C57DE4201FBBAA47E3
+:10A740002F0ACBC7AD2D8B0E5CCBBECDBFBB7EF130
+:10A7500021E7E3079C8FEF2BFB369F7C8CF9DD858F
+:10A76000F384F3F175F9FF62FD6242DEA4B07C2C44
+:10A77000754C53C9DBCC2EF8F84FEAA3F9CA75A87B
+:10A78000FF943ED6B6C4307DD42A75A8EFE470F1AC
+:10A79000CCFF357DA471C163D9D7A08F6AFFAEBC51
+:10A7A000B7A8C40D9D71028FC7947C690BA5157C59
+:10A7B00077A22141CFBEBBA175F784B843A1D7EFE3
+:10A7C000B259BCD3F8C502D48BC1E0CFC3D0F55584
+:10A7D0003EEED56C2BB6F09E64E440382DED65F16D
+:10A7E0004FF4382B3B5F4502F01DAA2BC44DAF66DA
+:10A7F000770FC64B5A6B35013ECA068D17BEC34B49
+:10A8000064239EBF6B80380ACE59ABE2A82FB3ED0C
+:10A81000CAF7782598F70B3EAFD4F22E9EF3FE4B85
+:10A82000B6730BCE5FE868877DC8C6237ADC67699C
+:10A830008C60DF4351C75B1F6667F0F79719FDE037
+:10A840003D805F803F850FC6A2FFFD52F49F1048F8
+:10A8500050784324EB0F647F35C59B14F4D79FBF1A
+:10A8600076FE69F8BE6C86B9E74C383F20ADF1C67C
+:10A87000B07D4B3FEA973A6EEB32FE55C5697FCE0D
+:10A88000747E0472720EFC72773C5FE5D40EECFAB3
+:10A89000FE0D91AE7BD877619C323C57A153A7FD4A
+:10A8A000CD6671DC877CBE4EBA287205DFA98909A6
+:10A8B000791F5685BF42AF1507F704E028E3CF5D47
+:10A8C0008FB28E30F2E3BA4ADC7D0EE8A0961F32DA
+:10A8D000CEC1DFD70D1FF7E9781C19CAFF61B82E6A
+:10A8E0009FC27F327220BC07A3BCBFCEECA1F2EEA8
+:10A8F0004C8CB5CE6AA77A74678B8CEF1F12BE1F83
+:10A90000AEEDE467BE04F6495B2C91D890784F5DBC
+:10A910008754C7A9EAF365F9677B0AF04DE75355F9
+:10A9200079E4F5AA3C73902A0F15ED51715CA130C2
+:10A93000BE2469AC2ACFBDF239002DD12ADF1BE23B
+:10A94000FBF6920DBEC3A365140AEDE7DF0362F4C4
+:10A950005ED6451EA49CA3FD4BB60DC775EAC75A2B
+:10A960006263FCF30A7F1F4A1FCFF8FBF860C58FB4
+:10A9700039B0EE6EF0CF657FEFC921BE4FBCCE631C
+:10A98000FCBC4807EFD990CF8BD2F1FC0EB62F78E4
+:10A99000E2B15DEBB161FBAC2713C7ADF138107EBE
+:10A9A000DA9387ED531E275E7FC25382709DC78561
+:10A9B000F0A39EA9D8AEF2B8F17A6FADDB0B7F1F82
+:10A9C000B1F74A82E74BD3EBE8F342E89CB692E258
+:10A9D000114247BBD72AC0BD16C70BE393AB6D42EC
+:10A9E0007F6245A6D09FE07608F07553F384F1DDD1
+:10A9F0005D4E018E2D2911C67773BA04D8E2982ACC
+:10AA00008C3765BA85FEDD370D8B6EBB823E3FE12C
+:10AA1000711E013A3CEA711D29C2F7A44A105EE595
+:10AA2000998AEDDC7EDD50AF62B401CC8F6272ACEE
+:10AA300060B121BFC5FDBF58AD43EA16327F6C0936
+:10AA40009D4FC097CE27D4277D389FC5E13A22E29B
+:10AA50003D55B88F3E0BFDE4043E66A49C64817CAA
+:10AA6000EC607E2C7EB7F5119DB53487EAF1479FE7
+:10AA7000B0EFE4C21626096347BFE6718DA99F11A6
+:10AA8000F3C5094F4998DF11C2EE9FDD92E608FD3C
+:10AA9000BB504AFBD1AFD977874CBBB7D9403E26D4
+:10AAA000E4CF888D08D97F99E0FFA92801E71B3002
+:10AAB0003882CACD843533F433B382EB53C6CD7EAE
+:10AAC0004AACFF06E5DF67E4711CAED3C0C7AC4AF1
+:10AAD0005A87D757655E79BFE60C5FD7291EAF9DB1
+:10AAE000E071F7715E7FFB92C76B6D3C5E3BCAEB1A
+:10AAF0006F8779DCFD39AFBFB5F27DAB4F79BCD63E
+:10AB0000C2E3B58F79DCBD2A7333FE9D980B9BD8C9
+:10AB1000DF25EA0A9F7B368AF1DA5C9F18AFCD59B0
+:10AB200023C66B77D789F1DACC9562BC36C32BC6C6
+:10AB30006B772D16E3B53BAA45FB38ADA250806F6D
+:10AB4000738B75B95BA78A71B7C2A75B5CA29D9C2A
+:10AB50005422C6DD5DADF76DFF68DC7702667E15B9
+:10AB6000E20F43BE0B2F9C7BCCB13A0B61FF2697C3
+:10AB7000B86A61BFE6464DE010EC33914F65FC1EAC
+:10AB80006413DC3194EAEB85C1E326D842FC8E578E
+:10AB9000949FE987C5F311B7DF27D2B5AC52AC77E4
+:10ABA000EA4B44BA3A93C4F36793547E87707FA804
+:10ABB00067BF9322D795FD90C65489EF2DFD5C7F2A
+:10ABC000A427EA7364CC1FE17353857EF447C6FE65
+:10ABD000EC7DA5C1FC7D859A88211FC0BEDDEECF2E
+:10ABE000D87B0694EC81DEF4FE9B08A3B7DE380A1E
+:10ABF000BF23B743C7DE1FD89560762CA55D375DB0
+:10AC000064EF09900E2D9E2373C3FB23A930AF7808
+:10AC10008E2C37A015CE99E955FD89E013AF880F2A
+:10AC20003B4FF79FC3879FE3E84FFAE3F988B6F0FD
+:10AC3000EF1D74C6712AFF1CBCCEE456B147397EA5
+:10AC4000EF213B5D578E2A5E32F075694CD3F1FBE4
+:10AC500063864F09BE7F9FA7F1C6C277B6C8390D7C
+:10AC60007EF7650411EDC2E47157CEC747C58B76F8
+:10AC700061B42D4D95F7DDA0CA0B45BB6020AA3805
+:10AC8000A78D9D4F34B09585F623DD26F78F51DED5
+:10AC9000DF417AD51C5B81E7EFB625F3F751B85C4D
+:10ACA0000DE7EB1D9EC4CE2FE6F17A71DE0F8B64AB
+:10ACB0000BBD6E385ECCCF312E71601C7B96F12BB4
+:10ACC0008FFE037EE69110FE013F0F8BFC34A8FA45
+:10ACD000E7807CE586C387C9D57F1E1F7E8E529193
+:10ACE0002F73CC55F6EDC2CBD788805386F783DE21
+:10ACF000B14AB82FFD4EA03A00DF89FC319ED5271E
+:10AD00001E4A9AA865DF6D719A4752BA17F375E625
+:10AD1000F17DB1460F09405CB2C563C496906A3CB0
+:10AD20001FBD227E512CF8CBC61477229C076CECF9
+:10AD3000DE6D199C1368D0754B0AF71E41B36E087F
+:10AD4000FAD7C6E6042D7C577E84D6AA85FB462416
+:10AD500095CB90278E82F74DE20026B81FB6C5E34B
+:10AD60000F14E1B950379E1FA2EB2884F8B5C83AFA
+:10AD700003FFDE63F32754FE6D101777C37DE3BD39
+:10AD8000DDD9F96B83959D6F2D8E63FBB0390EF67F
+:10AD9000FDBE9C24B3C307D3C5B3EFF854D07F974F
+:10ADA0005283FE81EABBF07D9F212404B6237F04F9
+:10ADB000F839357F54E71157B4F273736DE1F76BCF
+:10ADC000FECCE309E57CFB611E4F7CCEEB3F0779AF
+:10ADD0003CB182C7137E1E4F1CE2F1C45E1E4FBC05
+:10ADE000CBE3897D3C9E789FC7131FF07842910B7F
+:10ADF000C34A6233C07BB4C904EBF2F1CB245F09D0
+:10AE0000ECB3BB196C98C5F64F7B25D5B90AE2A007
+:10AE10005FE718057239D53B12D6113FBDBD02C69A
+:10AE20002524E96D4E3BBC9FB40ADF2B51DE0B9B02
+:10AE3000C5E5E6367731DADD595C4F88BC3617F365
+:10AE4000D33AF1FB71096E5DF0BB49F4FF0C157D3F
+:10AE50006F537D57492F317BF1BE6277079141A136
+:10AE6000748FE7748F98C1E90E2F5D85D197359C5B
+:10AE7000EE0A5D9A6F1A6661EBA810E2C243F963AD
+:10AE80002C206F2D497C3EFEBE8C8B3F6722D70F56
+:10AE9000655E657FF6F1822B9F6FFA888FEB848168
+:10AEA0002FD121F3143CA883EF92DFEAFF6532E84B
+:10AEB00049F07D1A07C6E123E5FC3F423E1DE0EF65
+:10AEC0001F28F6720AE1B4523DEF90E7CAEFED1C7D
+:10AED0002A18AB83EF764FF6FF12FFDE83415B1D2E
+:10AEE0001F7ABEB785E3F750D9BDF877E00229EDA8
+:10AEF000F8BE9AC165B0417CDE2BC9B11CE8179F32
+:10AF0000D456C4EBA12A7FB5B6390EE4AB1FFB368D
+:10AF1000E2FF072D97429600800000001F8B08007B
+:10AF200000000000000BED7D097855D5B9E8DAE79F
+:10AF3000EC3364E484C98326B813A658194E263826
+:10AF40000987B003C1460D7002018284709230C43B
+:10AF50008A367632BD8F363B24246110F03EEB8377
+:10AF60004AF080436B3FEF355AEBEB40FB4544E53D
+:10AF7000BE673128B4D8DB62982CB7AF03566BC7D5
+:10AF80007B7DFFFFAFB5CED97B7312A085567B0BBF
+:10AF90009F2ED65E6BAFF5AF7F58EB9FD63E6DA56B
+:10AFA000255903A98C2D0DAFAB645319FB00FFCCC1
+:10AFB00066CCC354632097E11FC7070AFC3FCA341D
+:10AFC000753A3EC7279676F64136FEBF9985D3E09F
+:10AFD00079E5C7FF83A533B6983507FAE0BDFEC211
+:10AFE000C0281F8CCF6A5C67B17F2EFCFD20273EF6
+:10AFF0008F2C1733F5AC79BC9420F4F78A3AA3F977
+:10B00000E27568EFEA669A671854FE04D08D86F7F9
+:10B01000B14D83E72A4BF34D86792B3FEDD5A1CC7B
+:10B02000C974D47B605D0BB33EB5928D843EF33D15
+:10B03000BE09005757A8E8270550EFD2D769B83C9A
+:10B04000ECB70EFAFDB0ECBE2C6D721CAEAECDAC02
+:10B050003402F374657DCEBF360DFBBDDF1AC17EB1
+:10B060002E56D30BEB3A31E7FF65669BFA3F3DADB9
+:10B07000ECE6C02818B002FE3786B189EE484E6073
+:10B08000F2C5EB65CC600CBAB495263356C8D8E946
+:10B090007A25EA01406ABA017F53B1FD42133E8F1F
+:10B0A000747BB42D0820D353E7C33AD77014B0C8CB
+:10B0B000848EA23E58EF9A6E4E37F6A0EB34E2CF64
+:10B0C0000B7F11BF59CDEA6933FE224C3D6DC66F2F
+:10B0D0000D33B543DD8D7300BCE581B4916FDF0C9A
+:10B0E000FF2E60051F3839FD11BF35A26F52FDE2FA
+:10B0F000610CD6C3FC80BCE28BD7B5FC774ED6374B
+:10B100008211C3B0A2F8F337578F4B8EE07BC8375C
+:10B110005EC157D388669A1BF82A199FE460C9DB81
+:10B1200061692F105FB5B8E27C96836CE63262707D
+:10B13000E758C66308EF52731DDF37F4E3E301FEFF
+:10B14000958CF3C7CA505325F227FB0CE72F2F3CF1
+:10B1500014E3C4F90FC6A90ABBE27526E8355AC044
+:10B16000097F96943FD6FB6F30FE633BF3E7235F86
+:10B170002DF9829339A15E0DDDB05E5DA344A380FD
+:10B18000D3A5A15B889E4B6DFC9D5C6D1DFFAD0D35
+:10B190000534CEAA4A180769B1C1D44EF0ED247C1B
+:10B1A0005631DF26942789D7B7B3D97806787C61E2
+:10B1B000F7BABDC82FE71EF0300FAE1BDF05BCD6B7
+:10B1C000730AB2E3691CAE9F6E56A2FB61FCB3BB6F
+:10B1D0003DC4776FAF51A20CE9CF7C4FA0BC76077E
+:10B1E00032689E734991BD9F87F686AE9480017840
+:10B1F000EB1EDE7C4F18E63D9711A9C3711ABA6E9B
+:10B200007618D83FD9F0E6E0B80DCEC07E9862B986
+:10B210000A381D0E25FCFB0628EBBB4DF482FF8E81
+:10B220000614E2FB050E16E94DBD987F92F2149AC2
+:10B230001F11EE31C1BF20C741F09E78D043F0A668
+:10B24000E469344E7D30494F4A473A325DCD077844
+:10B2500032F5B108E75905E413F8EDCC12C540FC0E
+:10B2600030800BDF77DF70FD3E94A727C43ACFDE36
+:10B270003F632CF2F3990CDE7EDA9F1CC5759DD6D8
+:10B2800078DDF0A7461F477AA891DCA5697C1D0AE6
+:10B29000F0418380AB4173E84940DF860797DD8545
+:10B2A000746EF06FBB17CBE369469A02EFFF74B779
+:10B2B0009321BE111FDE7C6C2F5987ED76BCFC3AC2
+:10B2C0009043EB41FC8D00BCBDBDAB3D2D82FBA688
+:10B2D0008F45DCA3E378A8DFF9BFEF53F07DC6F715
+:10B2E0005FAF90138599F663E0DFE59ADBA8807184
+:10B2F000D8A1F1C4B7CB7D9CFFDDC59B46E5F06EC0
+:10B30000A931FED0A8BE0DF7F70651AF47BE05BC68
+:10B310002E4779998AF8183E1DF79B9AD5D67D79E4
+:10B32000D3C88DF72F8675AE09BA9813DAD7F855BA
+:10B330000B5F57B558F91CD66DA9FBF218D1A17B4C
+:10B34000B8E0CF4ECE9F8C85C786A7C4F9E2CB016B
+:10B3500007E107A1730D817F3B5E3F6A78388DFC62
+:10B360000AE7CD992C6D6F318C77A61EF887C3C57F
+:10B370009C2679A8EFF610DFC3CEEE463C017FBADB
+:10B38000ABA6C4F945E2A77E571BF163BDE0BB86BF
+:10B390006DC03FE9263EB2E10BD7ACCA79C6C5F90C
+:10B3A0008CDA13F0D977021C6E297FF52C5CC79CD0
+:10B3B00017CBB52C89CE2548CFBB6A8C4C1CC52039
+:10B3C000BAEE282D1946FC2EE8A1C6E9E145BAA53A
+:10B3D000CBBAC18EE17E9E26EA192DCA9BE505D027
+:10B3E0005FD0C9533E10ED83A6E12DCE37CB475039
+:10B3F0001F4D85FE23043ED881194F4F1C1D3F6F02
+:10B40000D2C479A03A33C7607B3AB3EA3D236CEBF0
+:10B410006785AA3837F839FB80CB3706F7E364B184
+:10B42000BFAF9B374EC17E0F280AED3F9E0AD5C2A3
+:10B4300027AA4D8FC9C97388FDCE90FC4DE7AD5B3F
+:10B44000E83349631C2417BFC984035589E3C3CD7E
+:10B450008760C3FBB4DE3E68AFF37B035186F0F236
+:10B46000F3A10C88D067E2AFEACA14D66782639E64
+:10B470006F84A5FE71FF0D96FEB76AE32CEDB7E76A
+:10B48000DE6C699F1F28B0D4DDCC74AE239C031CF6
+:10B49000EF6E816753BB3C97FB918E8BC53A76B8B4
+:10B4A00023FE30E06BB17F2DD1A3ADF4137ED44BDE
+:10B4B0003D7E4E57B7D0279326ACF6911E51C9E575
+:10B4C00027087F910EED38C898389FB96DE7AD5DBC
+:10B4D000FEECFA64631EE83D2950F918FB18E93DBB
+:10B4E000A9C313EA3776FD0DCE0807F26BB2A0D7D9
+:10B4F0003C672A9D1B5DD55C9FEBCA5DC4F5A5DC4E
+:10B500004F125D17887ECC7090DEBA54AC5FEA5F54
+:10B51000AFB532D60747F38E12AE672D0D5EA83653
+:10B52000EBE5B2DC82FD26C5EBC9A17DBA9E40CF1A
+:10B530006C13FC95A2F3F6A55EA6E23924DB378AEC
+:10B54000F376A938B717821C23DF86B1349DCFDB91
+:10B55000C538DB63FCCAFAF361DD4E013F7B4A511B
+:10B56000110F49A2BA8F45B6E715219E0DEAE44CAA
+:10B570000D3392EF3F0176A1DF02D1AF2C6F75CF73
+:10B5800067817F3DD56901B42D3CC1FAC7BF54889E
+:10B59000FA514AC0A1C5F99DEC0EA88FCCE5FC5E1E
+:10B5A00093E90D50B3A11F1B0FE3558BF66A21CF12
+:10B5B000A35833C9C145768C97F3E5E0760CDF7F5D
+:10B5C000E47C1EB1AF30E78600F15D98EFFB0EF82A
+:10B5D0008B7CB7A4C6CA57CB2243F3596F9ED0AF1A
+:10B5E00067B019C46791F5C4171ED167C7D88361C6
+:10B5F00092F7A09391BC0BFB46EA9D47822F12FF66
+:10B600001FC91D50F5D438BF487D7C41C8A947B13A
+:10B61000BD9825FBE01C39E21AC87C00FAB954D663
+:10B62000A7E2DE2BF4F2F4E0B2DB7CB0AED78A5FA7
+:10B63000F19D4A6583EAF3767E9F08FFC07D7EF325
+:10B6400084B7FD08C76617345D8FCDBFAA4178B6B1
+:10B6500063BD04FB9FAF2983F6ED49B2FEEE2E6C6D
+:10B660007F2299D77FF5CC1F771921A207F14D8A48
+:10B67000C0778AD4CF279BF00678F68ECCA77DC4FE
+:10B680006BC3A75D6F770A7DDB69937FFBBC67A502
+:10B69000BC0B3A0CB6EE8BE005D6FBD8D07CFF8B0A
+:10B6A0003C3A0F9B2D7C7FF1387DA49FAF10EB7649
+:10B6B000A41CC88A2490DF18FED7BB7E6EB6070094
+:10B6C000CFDF5450AFD5E1EDE99C55701C25F8F261
+:10B6D000EFF17C577619C3118F4EE880E7B80B2C39
+:10B6E000408447CA6312F28113F1DE47ED709E0E6B
+:10B6F00028E370905A1FF2A702FD3F40FC5CEE3E2B
+:10B700005861B513DDB87E18CFDDCDCA3CE9683786
+:10B7100036EEDF5C88E7983B40FA57F78532A41392
+:10B72000B4EB1E2A2FE8747EFB1D9673E585D23F8D
+:10B730009C7F1458B3B3DF19F0C07B1DD800F074A0
+:10B7400086BECD50BF7E77320BE0E2EB22BE796E33
+:10B750000DE5A1EF44C784387C275A597FB92B5E89
+:10B76000EF3F98E4D660B111E35E2FD2E5AD0DED69
+:10B77000539E433B3BE8F1A1DED6BFB1DE40649C63
+:10B780001863F4224EBBD40843FBDDBDE17FCEC37A
+:10B79000FDF384CB080C87B27BE3CEBBF1BCD2B502
+:10B7A000CA8A6C807B7FB75A114D60CF7C229FEF95
+:10B7B000AF475EB873FF66F4378C710792609E01E5
+:10B7C000F45F00FDBA5C46168E7FA2AD3D0BE5A38B
+:10B7D000ABBE2B7010FBB5790234FF6E6F0D8EDBA4
+:10B7E00095B5D6BFD634BEF70677333EEFBFDEED54
+:10B7F0001E47EB7927CD0FEBE8DE50300279B373AB
+:10B800008C7B6C23B637AC631AE8856EBFE142FED1
+:10B81000F2AA6C17EE0337FA2F7C7F06DA439A639D
+:10B82000FAC7A1FF7D8148793ED0B1A6E5D43CD8C6
+:10B830000199BB3C63139E3F9D024EB90F49FA0E1E
+:10B840008C69F062BFCE4823F7B3F81DF548E78551
+:10B85000631C61DC7F3A436BBC13C5F375E917E3E6
+:10B86000A513FD2AD3104E58D714ECF77E6B04FABB
+:10B870000D64B96B12E13122F0E86D5F97D302706D
+:10B8800077EEF6FA103F9D4A64573DE0CBC84E0D67
+:10B890003CAE5DFCDE53E23DC91F402792C34F3CE6
+:10B8A0003B7AB7311EF5514E47C08BD7653A179F8B
+:10B8B0009E56B626DFE4BFB868DE319D741E742A3A
+:10B8C0005CAE9F7A76EA6E03EA8140E46E7CAFABB1
+:10B8D0001B78791AAD732CEAF383C9CF8068EF6CBB
+:10B8E000F3D44413C8FFC06A279B348C97D74139DF
+:10B8F00071A373AC92003F03590D39D9781E40BB38
+:10B9000003C619D8EDE5253CCF81E76F0EC29F53E2
+:10B91000F2F9793E796AB81DE9CF2647C88FF772E8
+:10B920005E7813D5D94E3FDA171F01FEDDF321E112
+:10B930005F3A0F23F937137F31DF708B5E3AD8FE01
+:10B940001916FB715BE91F9AF0FCDF5AECD13C261B
+:10B95000BF9FD4939327737D243CE1B100ECDC6C52
+:10B9600071701D3F2F2BB9FFCF077F13F9FFC23630
+:10B97000FF5FB2AD2EF5CF43F9423F117A70A6B604
+:10B98000333C07ED8B579D8128D03D0B5F1889FE16
+:10B990003125DA976D82F726B78097EB6B0BC57967
+:10B9A000F4A3562F2B9FC06276DB72B18E054DEF4C
+:10B9B0003C8676F402A16732243ECC5F3D999FDF3E
+:10B9C000D26E5B849D814597E772BB002C2B7EDE97
+:10B9D000382B8B901F1632AB7EB788D9F4B9D55C63
+:10B9E0001F93F6DA0A9BFE60B70BAA6DED3B60CEA3
+:10B9F0007ED4FB54B04600CEF782053B0A00EEBA77
+:10BA0000E0A14D0309F69BE378DEC07ADF68D5DF5D
+:10BA1000EC80736753F5D7BD03F0FE56B5D78B7234
+:10BA2000B2B5F2D36928275B6B9D248F475B2BA8A7
+:10BA3000DF6BAD612AFF2B3F23E6FFEA93F601C0DF
+:10BA4000B120A0BF8FFB8AD4D3AA2BCBDEEC30D1A0
+:10BA50007751F9AD967A3854F56687DD7F897CE6B3
+:10BA600064CD89FC6E530BA47F45B7F83999F3A9CF
+:10BA70004024417F59021FBD67C6576A8155BF3DAB
+:10BA8000129C3B6C28BD46AE5BE24BE243B60F0610
+:10BA9000EF6FF2A51DF297C19B7385F0DAE194F088
+:10BAA0000FD63F8C9B5909C2DBB6DC48453A46F2BB
+:10BAB0000B00CFD515192FA14FE20D95CBD31B7AD3
+:10BAC0005AD400785E9ACCEDFD945C16453FAE9D4D
+:10BAD000CE2915F5F3705FBB14BD93430AD9A14B72
+:10BAE0007425AAC33F6F1176E996C98CECD2B6D201
+:10BAF000AF1D4E2BC478878B897DA672BEC98E4A36
+:10BB0000A9E571881D6E16E8C3F7A6A40636C2F330
+:10BB10006A944394CFB0EBB4D90F0276D069B31CCA
+:10BB2000D9F79B145BBCA1AA40E8DFD301EFE3E2A5
+:10BB3000781FCC0E198C4FC07A28C2F3CA8EA77B0F
+:10BB40006CF8B1C723C207AAACED9769FFECEF2EE2
+:10BB50007C6924EA1BE54A6002E0E3756C82F79297
+:10BB6000F56728ECB1B940F0A5B0EBAAA55DB70820
+:10BB7000EC7920C111D40B86515C692CFAA5E3EB5A
+:10BB8000E3765C20A07FBAA06870388E89F7BAAAE5
+:10BB900012EB0BC7505F98C6CBEBA09CB8686E56F3
+:10BBA000227DE1587123D717A01DF58463BB2B7844
+:10BBB00009CFCDFA02AB28B8045EDA68BD49130A92
+:10BBC000872592BBD7A7457622BFCB7A4A6E332B07
+:10BBD00037F149539EFE4001C535B8DF41CE07E736
+:10BBE000FC21B33E669FEF997C1FC773C5083A37A7
+:10BBF000647929FAA9BE66867CB6D5A5D7609CC0B3
+:10BC0000EE377AA680C727BA73F4266C67A9F9972E
+:10BC100018B74DEED7B979A34D7E4B9B5D28EDA8A3
+:10BC20007DD868B20F551FB70F93332F1CF241D345
+:10BC3000DA82C8F388AF5917A286A310E3A90AE9EC
+:10BC4000519E4CE622FFC9E5DA6397D9AF7B23DF2B
+:10BC50007FBA1AB8DFBD2C4FA57A72C4B99FE248EB
+:10BC6000C25F1316CB48D6DF217B6C01E803C23FCD
+:10BC7000437AD509E1D70AB36617DA7DA9AEA8974A
+:10BC8000E2BE36FF4C4DA6A36F22EC1F35C10BD58B
+:10BC90001AC539ADFE9D1A2DE7D028D1EE83724129
+:10BCA00098FB7B96A2BF07C7AF8E76E7E0BE165023
+:10BCB000033AE3F61E9EB7CB1AEF9BF29076F5FCA3
+:10BCC0003DD28F24F546E9AF82F3A57B04D265AE61
+:10BCD000A2910FC0E60FB2FB7FC2C21F63F713D958
+:10BCE000FD42BF2DC8267A483D4CFA6BDE2FB0EAE4
+:10BCF00063FF09E281FDB614C35106F2BDC5C5B2AA
+:10BD000076C2F8E9FAB2DB705F7EADEC151FEA1B74
+:10BD1000FF5960F3675EE6FEF663D887CEA0BEF6F5
+:10BD2000E21817EADD55CDF5E437B4CB89BF90EFC3
+:10BD300073C985A99678717F6B8B783FC9C0F3A6CC
+:10BD40006ABC3B9A046BAAD2F938972B4F1979FA3F
+:10BD5000C8C25164978CC69205C02E99827689908C
+:10BD60007BC1DFAC7C143B638E937AC15E4933C3E5
+:10BD700021D67185F3238DCDF35C0A6F3B4A4BBC12
+:10BD80006EF447002C4ECE57BE989F3E07FD3BEB0E
+:10BD900035B35E5187F18902D43F158A53C8E7262F
+:10BDA0003FB98AFC9B9C19D1C309F6D5E5850E4B9A
+:10BDB0009C34E667CF65141792E3A8CCDF46728007
+:10BDC000B22AE17126F0C70B781B259FB380D78379
+:10BDD00071DE6D4EC6F30FB89CC8B8835A1CAEC84E
+:10BDE000C6F8F02625601014358750BF5F2DE4C8D3
+:10BDF0002DFC70F678D16A2957CEF5A4A735EEB49C
+:10BE0000C6D1EC7131BB7E2EFDFA2A4C82707F5E6A
+:10BE1000D2090E78E7D078D847EBFC3BC583E4C362
+:10BE2000CA82BBFC98BFD29914D9558FF1EB1E2F53
+:10BE3000F945BAB00BCA4B1FFC457F7B4FF0D12DA3
+:10BE4000F05E77A193DEEB54783ECBA1319FA3FD4A
+:10BE500043F259B7E0B39B0A35EAE7C57D09448848
+:10BE60006572BB56E6AFBC3686EBABEE10CFFF7902
+:10BE70002AF3D0EB65042DCF63C90DC5F358CA0072
+:10BE80003F5304FE7227AC263B764A88E7B14C7ECE
+:10BE9000CE6AB7DE9EEBB2D473ED76ABADBEA750E3
+:10BEA000EC7BB6FC95783C6D11E961127EBB5C7D44
+:10BEB000B595C755BE06762B964FB5FAA8FCD75652
+:10BEC0003F95BDAD1AE969CFB6E672BFBBC0FB5660
+:10BED000D7053A17CF65B9290F42FA29A5BFFC3B10
+:10BEE00085DC0FC5421C9E85624DF39C996918E75D
+:10BEF0003A1AE2FAE160FBCCE20A6B3C6F49D81ACD
+:10BF0000CF5B56638DE77D7AAA7EA010F5AAC9BFE4
+:10BF10007BF551E479117F5A23F0B0E3211E5F9243
+:10BF2000E31FFD02A7BFAC9F1378F83EF207C68F50
+:10BF30000E8A7DF4C1AA5B681FF5E55F965E785CAA
+:10BF4000C867CA469F2B00E357F52D77E3386B7619
+:10BF5000C138A9973FCEE609A3B3ACF1864FDE8185
+:10BF6000EF1F8DC51BEEB903E30D4745BCE1FC7324
+:10BF7000CD5F467BEBA642FD27880747A17E12CB0B
+:10BF8000F308CF28AA0FE0B922EBF0E770C6E8214A
+:10BF9000FDFAE70B13F8F59D739584F6E93B85DC14
+:10BFA0009E86F3EB97F81EF3C6FC6A17789D9F53A5
+:10BFB0006A119FBFFD47AC09C769FF366B7A3681AE
+:10BFC0005EFFC742458EF73B3A0FFDF23C0CFF2166
+:10BFD000D1784E4FD558C4F73917CF83B18FA716F4
+:10BFE000B9E5788E227C2733069F5A641A6F07E0E2
+:10BFF000A01FE9A4FAD2288EC9EEA678A7E4A394DC
+:10C000003ADF7CCC53000393E13E93F2BC6F7E2178
+:10C01000E6D9FD605CE07136385D7F26F8EBBC90B8
+:10C02000B3B751CE409ECEA29C41791AE50C9E0F2B
+:10C03000A09C4179B23540CF7FDC1AA4F247AD3ADB
+:10C0400095275A2BA8FC416B98FA1D6BADA1F2F510
+:10C05000D6083D3F5AFEF55B289EF69442795583FB
+:10C06000C173D757ADF27567D42A5FEB7659E56B8C
+:10C07000CD4E6BBCBCB1DB1A2FAF37ACF1F2552DF6
+:10C08000D678F9CAE69996FE2B9AE65AEACB23B7F8
+:10C090005BFA2FAB596CA9EB455C5F5C125E617972
+:10C0A0006F7145A3A55FCA22164944FF8A22CE9F1D
+:10C0B000074305C30686D877DC2DB7FF04F59458EF
+:10C0C0005D8D30D4EBDD2D0BE8F9D6A4705D38C161
+:10C0D000F875457CBFEB2C5F1D9EC3D0FF7B8BD3D7
+:10C0E000ACFFAC9F16595464B273DD7E6E97BD3BB6
+:10C0F000FEBD17F1985854FECE4BD7E139D5CF028B
+:10C100000AF0950E6A9F1FB6EC22A3CD791DD4AB21
+:10C1100033C18E34ADBBF833FBDA47C3F399EB5F21
+:10C12000983B12CAFCBC485D11DA5115A7DAF1FD43
+:10C130003995792A8ACDD60C467AE9B9096EB27753
+:10C14000EC707FAA48B1C4B3AE749FEE6CB5C6E57F
+:10C1500073FC3CFE95E3E7F12EA853BCEBE9699133
+:10C160004F217CF09CE25E5D596B73703F192C8E01
+:10C17000F490A097F42B48B8769472788E8A78C39E
+:10C18000107E852F168D1A1CEE73220ED1F5254FC9
+:10C19000C2F8CB3911873827E3100F2D4E18873896
+:10C1A000374FF815A01DFD09E776D7F0725EE390D2
+:10C1B0007108B93ED88F1EA4FD27168710FABEF06D
+:10C1C000A3BF3E4DFF5FB88EA63C7D17F67B7F8AEE
+:10C1D000BE1BEB474DF150DF68533CB4FC154B3CA4
+:10C1E000F499FCC83E7C6F226E693064BBC1069234
+:10C1F000C6617C367C4F223EFE9722A967F7FD453B
+:10C20000F15A535CD5F1C1CDECB2E30297DD2FC8F2
+:10C21000F350EC7A4E0A620486E8C6AE70CE3E5900
+:10C22000183988EBEFC8785EE3F9568EF8FE8187FF
+:10C230009F7679F3250B3B15CF2B3CB78E81C4E05D
+:10C240003EB33DA399FC2AFD026FF6F28D22414FC9
+:10C25000E61B89F47DB230FC3AD28F3DD7AB511E3C
+:10C260009B78CE722FCF5E7DC21DFE09EEEF9D73CF
+:10C270009C1ACF1B64E4BF9894EB8BA27E2BF5B085
+:10C280005FE27E49F92803E3DDB0CE76FDC554CCEC
+:10C29000FF7E6B8F8A1930EC2B69CC8570877361B8
+:10C2A0007F8375CCF1476E1C6A5FC4041E4790F80B
+:10C2B0004271F8A91CC14B43C1E7F6FEAFED796F9F
+:10C2C00014EAE55FE9E1F1B0493DABBD0DA6F173BC
+:10C2D000A6F37DA73393C35FA72B512D1BE1B9F0C4
+:10C2E000FD19186FD11CE4EF786BC36F8E2F43FFDD
+:10C2F00063C8199840F577A9DEAF390A307EFD96FC
+:10C30000FFD7C7B1FFA42FAC194DB68EC0C7AA0D79
+:10C31000054F203EEE0B4494E9304F7FE8DDB471C9
+:10C32000A678DA2A858513E93163A673BADDA637C4
+:10C33000DF81FBE66DBA87615E737F9987F0FE95BA
+:10C34000598A86F6EE42E475680FEF51C98F0DF8F1
+:10C35000588FEDAF065218CE3B477F46C5FAFB53C8
+:10C360001476DD10E7F015E335F4EE2894C3B790AA
+:10C37000FF12C0FF4BB96F0A399AA882DCE723FE8F
+:10C380000FA59AFD95929FFEA9501F37BD08FD7F0E
+:10C3900091A630E9B98B2EC1871B093F0BBF1AA5A7
+:10C3A0001884E7B1E6EB5982FB0DAF09F9B03F2FD6
+:10C3B0009CCECFC95F0BB998D4F3DEABB7629C7942
+:10C3C000838BF2116E2A0C4F47786276D755DE3791
+:10C3D00064BE5A7F5021FB0DD4699AA71F245005D3
+:10C3E0007A2529C9014E4FEEA7F38AFD0FFAE9C35A
+:10C3F000A0DF2AD6DB87FE3EA6EA3B9DD07F73B145
+:10C400008BE8BD6CA52B0DE9128F9F052CF686BD20
+:10C410001C1071B3CE562FE56BF47738B99E0F7FA1
+:10C42000401387461EB767C6948775F8E713228FB7
+:10C43000F493C15B1FC67C9AE30E5E6F08DE7AC37D
+:10C44000468C7B8F6D3EBE04E3160F2881360DCBE4
+:10C450007DBB1A30CFA345095440BDAEEFF37E74C7
+:10C460008935747848C73FB56912E989EFFA990FA1
+:10C47000F5C46563B8DC34F6B3A8233B6EE79ECC05
+:10C48000E2F113B463E74DC76D97E3E39F5BFB08ED
+:10C490007E4F0B8F9B0C0FF0B86972BF1A884297C2
+:10C4A0008F6F7B87ECE0B0DFAD219E47301E578950
+:10C4B00064A606300E1AF4F3B84AB27EEFF125F006
+:10C4C000DEF07295E7B70D707BB809FEE2391261B4
+:10C4D0008136DC9F465458EDE4425B7C459E6F1EDE
+:10C4E000FB7315EC5178DE36DD7ACF6330FFBD2C5F
+:10C4F0009F033D02D7F7BC88E77E13F475A4D3B73A
+:10C50000415FC7F200E8EBF8FC7BA0AF63D907FA04
+:10C510003A9607415FC7F210E8EB58BE0CFA3A961C
+:10C5200087415FC7F7FE0FE8EB58BE0AFA3A3E7F35
+:10C530006E16DF473AB3DCD18D8067EF9F808B01A9
+:10C540002F9D2EF663E42FA3CCA3F17C7CDEAF2BD2
+:10C550006322EDF3FD4AE4138CE781688F633DEDC0
+:10C56000C21F7F85F54DD964873055FBE600F4EF97
+:10C57000F87C76600B54BBDDFCBC1F38CA7CA83746
+:10C580009C5EA24C45BDE9CC7CA55701FDA67FBEB3
+:10C5900042FAC44414BDFCF83E5AF29EB61FE76B43
+:10C5A0004F63821FF7F5E8C07FA71126E2D7B43AA0
+:10C5B000B48F677B643DB90EDBEB5B1461A7A6EF1C
+:10C5C00045FEED92FD8DEB7AB07F87AD7ECC21EB01
+:10C5D0004D7BB07E3C365FFD0A1CEF788E6C6FA8F9
+:10C5E000D5E1CC184892F3CD5C89FDFB15D93FAF5E
+:10C5F00007EDE43359B2FFDA15D87E2666473FB619
+:10C6000092DA47F1FE93BE3BE211B49BAFF678EDB0
+:10C6100011BE3FC33EA69BE33A2D25DCBF10F39F1E
+:10C62000EA8AC57F2AFDF68E94DAEB30EEE6D9C8A9
+:10C63000F3B406B20275785E0FE64735F9F9C98F93
+:10C640003ABB24767FC0EA2FD5159E47EF6311CB06
+:10C65000FD369127EFCE34F9ED84AC5F8EFF50C6E6
+:10C660004BA4FFB0461FDA7F5833CBEA3F947912D0
+:10C6700083F90FE57D04E93F0CAFB6FA071746AE24
+:10C68000CC7F58CBFA5C686F315D2179A9F5F5BE96
+:10C69000341AEDFAB31AF90F9976381ABB7FA0D184
+:10C6A000309A633ADE23E3F5D3772B7EB41FB6DCF2
+:10C6B000AD8CC6F2E4DDCAF5284767EF567C2857F3
+:10C6C000BF98C1EFB7149D0F1CD6705FF53B021CDD
+:10C6D0001DE12FE03E1C5E9DA16D41BADEAD0CC791
+:10C6E000FE2B3F93E1C6F303F44B21371F3C8C7CB8
+:10C6F000E54C512CF5C2B1924FF73C8C72317B84E2
+:10C70000E4C3C57BB05EE696EF7F710FCAC9F288BD
+:10C7100022FADFBB07E5F0F81CD97F782DF65F32EF
+:10C720004E8EB7770F8E3F3B45D61FA4F6EED878D6
+:10C730005FA3F97E882721D5B7EDD1C7C37C55E229
+:10C74000DC323E46E377D6CAF7EFE92983F1568813
+:10C75000738A191F2739273F33BD0F7A3AD4FF5DFB
+:10C76000EC030D337EBF02E5E68E58FBEF69BDB5E5
+:10C77000A2BE7AC6937B30DFECEF7E7D7FE5F9ECDD
+:10C78000F595AC7FDE758571B9B09F8BCB8BF9BE0B
+:10C79000126C7A068F2756DBBCCF89F2887E001197
+:10C7A0007FAA0E237F7B9D943717F687C9EF691FF9
+:10C7B000E7FD195CCFFECC0C6B3CADD3164F0B6381
+:10C7C0003C2D7BF071EA8AF938DD7312DBB34F4FF1
+:10C7D0009BD33A63545C3F4055D00D6529940E2895
+:10C7E000FF3425B26946115EE6E1FE16E9BF5E2020
+:10C7F000F288DB4ABF1C9E83F7928A5D01E1FEEE60
+:10C8000037C777D56DDCFFBF62CE05CA0B5BD3E9B6
+:10C81000D1F6631E4B87C85373A652FC41BDC1BD00
+:10C820008FF679113F8D60BE710ECE33F4BD0DFBD6
+:10C83000FD1943ACF7DDD01617EEDB35E56A9F5BDB
+:10C84000C48F79BE9835BE2CE3C56579E329AEDC8B
+:10C8500098E9A5BCE22ACC0F41D910F1EE3AD1BF3C
+:10C86000B1E58530E2BD7EA793A11E78A5F1E5FA7A
+:10C87000B091F539787F41791AD7E76CF1E69A865D
+:10C88000277517B41F055C8FC00E225E2EEF85C47E
+:10C89000EE1F883874443C5F1ADBFF2BD371FFF422
+:10C8A00074811D86EF8B38B38C4757D9CE81FAD06F
+:10C8B000DC74F2D70654B21FD54BDCB3CE29E1F9B4
+:10C8C00068321E7D7886351EBDD5C5FD7FDD3956A3
+:10C8D0007E2B29E1F6EC2471EE1E2C4DEE4B42FD31
+:10C8E0009A79C9CED882FE9A61DCDE40FF84DD6F82
+:10C8F000A3B6AC20FF22B62BC07F4AEECBBFC7FB4E
+:10C900006A582F81FE2ADE578175A8A90EBAAF2971
+:10C91000FD3BA886CCCB273FCF49E463B5A58EC6A7
+:10C9200091F7D307F3F3FC6C86D40F7A5DD86F854B
+:10C93000FFE51338DF5FECE7117696EC1FD6789EA3
+:10C94000CBF0199A8C5BBAF8FD3DE65A3485FC2190
+:10C95000EFA17CB2C9BD1AC221F7A345C5CFAEC0B5
+:10C96000FD88E9A3D819D3BD08FBBE20F78BD87C7E
+:10C970007EFE7EDDB7BEBBC2183978BC2227148B81
+:10C980002FA8419C7FA48C2FE82EACC7CF595850BC
+:10C99000D072CED636FD37386763FABD31B616DBB6
+:10C9A0003F6AF0035FCD0E52BE14F7B37DD4E07F33
+:10C9B000A5485F8A7C78ADE7F956517835CEB359F2
+:10C9C000D16B52793030A00C1D17BC0BFBDBE3821E
+:10C9D00097F257FCC33F31B47FE24B416B1CFFC35E
+:10C9E000E29FF867C029EE93204F4F923C85B83CF8
+:10C9F000FDBDEF7FB0DE57B85CF44693C75D7DFFA9
+:10CA0000C09385916388CF895A6A3D9EE3308F86B3
+:10CA1000F217F37B20DC418BDF634FD335F07BC013
+:10CA20003ACF125DCB395DFF0EE8F65F749EEB5C8A
+:10CA30009FF83BE4CBEB8B915EBD7C7D7F83F93F20
+:10CA400046F33FC5F9258E1FAE2799F053DBF4B7A7
+:10CA5000C14F29C1F74D0EDF47809ED5046F80C3BB
+:10CA60007B29FBFBCE193C7E02EFADA0F70A391FF4
+:10CA7000DC85FA35B7CBE762BE80B4CB33F2F45530
+:10CA8000D80FF4DC7A3E4F4CCF6D281E35A4DDBCA8
+:10CA9000B67868BB797DF147C86EDE2DF0168FCF72
+:10CAA00044E93E1C9CE41447AE137DB7B42CBEEDA4
+:10CAB0002680FB37807FAC7B703D4ED37AB254B278
+:10CAC0009FEDF7D48E883C08B92ED5593B0CF5085C
+:10CAD00089CF23E99A1BEF4335E84A272603CE3551
+:10CAE000DEA175BB750FE91F37FA7D9D187F5DAC20
+:10CAF000F3F5BB9B7C74EF45DE7393F74E1AFAC6D1
+:10CB0000BCEC86F7B680FD3206C65F586EBD876204
+:10CB1000D72F545BBDE5C7D9DB0F99FA3F566CCBD5
+:10CB20001F743E5541F94386427A1713F9840D620A
+:10CB30008CB6D23B92FD5C8FD3100F73773ED08FB3
+:10CB40007133B7E1A4EF30FDB655DB7E08442A69A6
+:10CB5000F3BBB4BEDFC0FAC8C8ADE4F1FA4611AF0A
+:10CB600067363F8527F9E72EF44F4B3C26DDCFF3A0
+:10CB70003CDCC153E574AFB1764D7F11EF4BFE073E
+:10CB80009543C6E47735AAC438553ACFAB5CEA770B
+:10CB900058F284EC7E0C95A9B6BCF881974620BF6C
+:10CBA000015EBF8CEC91CBFD10C94CA7EF7024B790
+:10CBB0002D1ED687DDCA5D96EFA12C0CDDCBCCF601
+:10CBC00072B28D2F3D367F839D2FEDF4F8818D1E3F
+:10CBD0008FAB5C2FED3CE6247F79E783ABBBD17F45
+:10CBE0006E3CE8207FC65999070240A23F7F198B0F
+:10CBF000E197F4E5CEE68C28FAE1255D96EDE4F9BF
+:10CC000021D4CBE477672C9399BFCFB14CF817EEC2
+:10CC100060BD74BF61251B70A11CAC4257BA13FDE7
+:10CC2000E21A958DCCD8C4087F91EE6C98EFF1E6AE
+:10CC30001101F46BF75DEFCA783B97DB1189F4D7EC
+:10CC4000785C56656F9BFCFCFFF06B5DAE5FCB695B
+:10CC5000D0F7FDFCEE287EDFEF527EAD97453C42DB
+:10CC6000FAB5CEEEE4DFD5E817F72AFA5DDAD89DFB
+:10CC7000A9D84FE3DFCBE85E761BC2FBDAE6577C30
+:10CC800003B44FB20DA387FE0EC4D4920476E1F72D
+:10CC900067309E17973D9085F999275DD6BC5B5903
+:10CCA000CE0FB9C5BDECC88C12935ECC7CB13CCD27
+:10CCB000E212F257F1FBD9D2CFB4B620528ACF6735
+:10CCC0005D60640F7A2A95A882F919A9CA4B8A1661
+:10CCD0009F9FD9F3E5FF1107E3DFB712F8E94FE2B1
+:10CCE00079B3FDD9ACE6D904F4C99EC5CFCFFEBC5B
+:10CCF000C4F493EDA097DC83F443BB299D33CBCFE1
+:10CD0000DD43FB133E5B9220CF58D2F7C9D9FA7DA1
+:10CD10009CEEBC9E941FF902D6DB23E19FD0F7EB7B
+:10CD2000B639B536C47F9F762488F2F945A70FE35C
+:10CD3000DDD73ABE377C46F665C5F77E81F81D45DE
+:10CD40007C2FF4C67FAA433D708BB4CB84DEB862DF
+:10CD5000B8A90E5B71C931DEFF1B25D3F71AEAE0D3
+:10CD60007AE6FA0377F4A01E29F54CA8AFC4BA7C82
+:10CD70009FB1DBC796815EDBD824E388B7EF453DE2
+:10CD8000373EDF92BDA8079F7559C7977AEA2B25D2
+:10CD9000E57B71BC706CFEF2BD08FF800D7EFADE93
+:10CDA00024D4DF28D1F7A2DE5BCF64BB4EF901713A
+:10CDB0007FE27AB25B8FBB65FB27285F607B361F03
+:10CDC000FFD503EB7BF03B691F3678AEF5F857DAF9
+:10CDD0007F307DFFA48BE7071AA09F615E4890F526
+:10CDE0003AB9F0E96E27F07F89AED07EF4EB109768
+:10CDF000D770AA43CCD3D2437C512AF11AA53C8FD9
+:10CE0000C1F8EECE03DF7818D71D87FB1B2B900EE1
+:10CE100031B88DF575E81792701FC5FE30DE8A7B3C
+:10CE2000EEF4239C2B627E8DB61EECD79921EB93FA
+:10CE3000F6627DB0795786B6F5E0BC2B62F8798052
+:10CE4000DE5F912CDFDF65CD4F317A565AE15A6DA6
+:10CE5000C1E7F70EF4F4205C615F74D368F2073227
+:10CE6000FAFEE71D4D6D94BF1D97A3AD592447FEF3
+:10CE700058BDC72A479F26B8AF365CB09FFA67E215
+:10CE8000F995CBEDC3ABBF6ED82771DDDB145AB774
+:10CE9000E4A35A9F89DFE19C6BD464FD9EBAA6C9C6
+:10CEA00057635E6EE7867FCEE8FC93F2C48C884DB4
+:10CEB0007E2E6FBCF6D41CCA9F00FB4A4F946F7D38
+:10CEC000D70C45FA31E7103E83D26E6652EFB86553
+:10CED000E62893DEA1C5F48E0AEA6FD33B3A451EDD
+:10CEE00055A7B86FA2438BDF94E7337E168FD3B676
+:10CEF0008B3CCDC28DE1B5663BFB89D91C9EC766D4
+:10CF0000733994DFAB3DD3A4501E58FBB611E9989A
+:10CF10003F7B2AD3B700CFB5FE6C4700AF2E9F14DE
+:10CF2000DFCBECFFBC27EB33F0FC44762AD9A927F2
+:10CF30003276A6E13D855301A738679E7B8BFC5D69
+:10CF4000717FA281E78AF417AE9ED94EFEBF3735B6
+:10CF50005E0FCC7EFE2D8AB7E5DAEF7186488F71C1
+:10CF6000DF22BED32BBEB729F5A5AA4D8F7E896CD3
+:10CF700060A1BFC8F3D37EAF13FFB8CCFA57879335
+:10CF8000EB5F7EDECFCF06DA3E30E9DDDE41BEF379
+:10CF90005A23EF11DAF429BB7ECCC4774DA57E9ECF
+:10CFA0003CB281FCFAC94DD67EA73A5EAC0CC2FAFF
+:10CFB000BA024ECAB3BA3DD7AA474B3DECB68E472C
+:10CFC000C90E05BDD0D22EF36B6F67BD1D74FF5B1C
+:10CFD0003B7CC8393A6E77B4FBAA484F69C8851ABA
+:10CFE000ACE7F8FF284B2B42FD609B13BFF0CA73E0
+:10CFF000EB4DEB807E2EC748DAA7038A62CE076A24
+:10D000007B04E5229E0FC4EB713FFC7D8FE07E1018
+:10D01000F317B37B5659FC9BC632EA1FF38719619D
+:10D020006A3FA30AFF97B1EA11DCCFE2FEB11FF617
+:10D0300058FC6346E523C84F32BECA8CFB29AF6F4C
+:10D04000A94FC2F3A31EACB7EBFC3CF9E6773C2733
+:10D05000F17B4057DA1FE4F379944316E6FB9DBD5C
+:10D06000BDE458B43D5DE875F83D0ABB9C27857862
+:10D070007E5DB99ED7314AE37E2B0FD0475FE95CD6
+:10D0800089FC1ACF5329A6EFA2350E9257322FC42E
+:10D09000E5F7F0CC548B3D6ECF4F691471E8C1C6F3
+:10D0A000A92FE571F67EC557CDCF6527C373B9ECBF
+:10D0B0008171A9783D55F62B2DE5FBC19FA6E8C7E8
+:10D0C00071FD763FDA59F4A3A1AC0A7FC722C13BB8
+:10D0D000EA4EEB774BCE64F0EF962CDA26BE935EE9
+:10D0E000F197F9CDCECFB4DEAB1F2CFFA1B894EFF2
+:10D0F0006379A55727FFE189645D477C9D83BEE87E
+:10D1000017BC281F42E439C83C08772887E76D30F0
+:10D110009E0FD16EF0EFF15DF57B2CD22E290CA77E
+:10D1200084F05CA8E1E788E4B3BE991AE7BFF30195
+:10D13000E23FC977D03F23847C5DCDFB979CE7DF3E
+:10D14000B790FA45D281933D6DE3E91CBA2E643E57
+:10D15000875263F71EC784129C4347E7EA37F0E71C
+:10D1600086C86788DC182A4AF87E762881FD3C79D3
+:10D170006A783C3D8FDDD7D42784FE91FF00D3260B
+:10D18000CE3B691C24EF44EA85F5DFFBE94A03FA4C
+:10D190007D30475F1032D9AD31FD7280EB3B31BD40
+:10D1A000D2984AFBE235D01B57854C7935D760FCC5
+:10D1B000BB88EF265BF528B4FFCDCF3F6C761CC053
+:10D1C000B791F022E2267FC6FB5B42A678CD5F01D5
+:10D1D000DE5D2193FEFF21C4E75384CF0F2F7C7DBA
+:10D1E000045F25A7F7CC99313E7D31311F5C36FFB6
+:10D1F000FFDF90296E6E1AF7083DAF1C3A2E07FD2F
+:10D20000DEB0F68BBDFF03F3B843BCFFEF047FAC89
+:10D210005FECFD93F45CF0E75590F3F366FA5E8300
+:10D220007DE43D5AEF783EFEE992D83A7E6B7EFE71
+:10D230000F7FD925F93C6B16E2AB99F3D365E8D99A
+:10D24000E366F1FC9608F7D31A52AF99289E0FE0D7
+:10D25000BDD105C8D7A3E85EDE4D38BECEB89D1B54
+:10D26000B34B8CDD7BAD76090C34D972DEEF35DB48
+:10D270001DFAAC7D7B115EE75CDEBFE8BBE9AB70FD
+:10D28000FDF63AE825336659F3328338FFA5C6C563
+:10D29000F83FBD678BFF9BDAE7CCB2E42F703D16F9
+:10D2A0008E70AF0768FCC35AE7C806A857CEE27A6B
+:10D2B0002CE82109EF6F57CE8AF9132A693E918F26
+:10D2C000712CECA47B80317D8579C9AE8AE953C687
+:10D2D000D7C84F14D7A7FE85F8A954D077D5777B48
+:10D2E000EB049CCBF8FAC53A2EDD7F25F5F7F3FE6B
+:10D2F00009DAEBA93D93C3C9520F9F755AE2156C29
+:10D30000BC6374FC7740CA5C4B668D047DE56007A6
+:10D310008F47D5770BFA1ADFDA6BB513B9FC2D17E7
+:10D32000FCDEFADDBE3AE4FFE5EF49789D7CFD3195
+:10D330007F5F1FADFF4DE19748FB5E9F84EFB30415
+:10D340009FC6E1BB06E3B711DD19C74F0D335CA3E0
+:10D3500087C8B3D82CE80FEF75D37B5E0E574D44CA
+:10D3600071F1B8CB2917F279DD3196D0DFB473961D
+:10D370005BBEBF93DE4F15F66C20F1BDDD87E2F199
+:10D380009387A8BF8FCFE780F31FEBA1C8D1B94027
+:10D390001EFCDE1CD935E17255C7EF2C84831716AD
+:10D3A00031D377E5641CBCECFEF1BD680F269727EE
+:10D3B00071BBD16BFD7D0ACFDCFB721FD4485AE9EB
+:10D3C0003BB54B041354316B5C34419CCBE27791F9
+:10D3D000FE9125B1B85426D9B9EEADFCF7A158B5E8
+:10D3E000358E99DCC2C8CFB5C050A21A8CEFD1AD32
+:10D3F000FE96C8066D3BFABB54D515D0B58BE39AA3
+:10D40000F6DFB998ED657A7A3EE5A37C6FD6A87809
+:10D410001ECAE9EE71A92887763BFAF4607674B7E4
+:10D42000D58EEE9776B47E75ECE8A3B3AC76F4DED9
+:10D4300082F01BC4EFAA4EFBDBC1D29245685FBCF1
+:10D440002BF228061E54D3110FC6367E6FE1948846
+:10D45000F3CB78FF40314BC5DF3B1868F3103E0734
+:10D46000D6644453E0BD74635D25FECE81B4A7113C
+:10D47000F3E80793DF27B6DBDDC941A0E7341233B9
+:10D48000B2B7077C3EBACFBCB0437C4742E40B48FE
+:10D490007B5BDE7B6F2CE7F7A7D17367FE7D8B8507
+:10D4A000C21E977679DFBF31C59C07B08805289FDB
+:10D4B000A09A85A95C2ABE9F58E3639B10A8F7A792
+:10D4C000447E47FCBF87F309DBAED2EF570D6C7B80
+:10D4D000807E1F6AB0FB0C6AA9BCCF60509CF61A14
+:10D4E000D8FB49A5A6FDE332F69B61D45FE572DC6B
+:10D4F00086F77C47C5BF1FD12FFCC2DB33B83F6521
+:10D500007C29F737D94BF97D882B3D3FE0FCBCB136
+:10D51000D46AD76BA597777E4EA4F7C4F7294663E4
+:10D520003C88EF4B379572BD404B27BF0A6CD14307
+:10D53000E703044A8788EBB24BE713044B13E41369
+:10D54000FC42E8236B0B22B370FC591718F1AD3D78
+:10D55000EE2FFB1D473F5582FDB659F8DBCA8045CB
+:10D560001DF917DFDBFF61AB7E1275BCE3AD15540F
+:10D570009E508D34CCDF3A22EEEDC30894CF24F3D5
+:10D58000A2E4B835B56527CF9AF6AB85F31EA33C68
+:10D59000B3F6DCFD871580F394C8F7EA4FF36D47C7
+:10D5A000BFB371947F476A69F5AD27CF9AF60F3BF9
+:10D5B000BC98176580A8DF59CABF5FF76299A76F4B
+:10D5C00036C8E1EA6D5C0E576F3BE5427F665D4B06
+:10D5D0003D8B4CA1BC2915E97B6C26FFCEC2C2A0B5
+:10D5E000931926B832F2F486528A7B845713BDE32E
+:10D5F00079816BB05EE6D2D331AF5DFA2965DCA0EC
+:10D60000B4F467A43FF767309A3FEC67518CBFCF03
+:10D61000D5B3DD03187FF1FBC8AF5A57AAF1DFABD2
+:10D62000EBD847F02487DE2178CA54C0F7F08BF19D
+:10D630002DE5A253E0DBB46EC2F760F2BB709E9A98
+:10D6400086F83D82F4827E9BC43EF09A7A21D5977B
+:10D6500080EEB1F78265167C7BFC1516BAB5EBE35C
+:10D66000D2713D92CEF5A2ED7487F3FB48C7F73037
+:10D67000AF8DE898381FE228D26B12B497727FB44E
+:10D68000A4579DC1E9556794713C056F758FA178CA
+:10D6900080D28BF7251BCBEB19DA0B6E3D83BEFFD7
+:10D6A0002FE9B7A81CE8678217E4F1E15293DEF98D
+:10D6B00067F8D91F2D35E9C1D73A0E00F33D43F382
+:10D6C000D9F372FF4A71888BBFDBC3F7DD3705BF23
+:10D6D000D84BB9EF0E9ADF6C54AE6AFA33E0907211
+:10D6E0008372DBA660FEA4E2423E0BA3FC4E417DAA
+:10D6F000EE3F36615CB4C1CF7A712F7C08E508F04B
+:10D70000E6AEC870A3FCD47767135FA0FD4FF81492
+:10D71000FBF44BA54C9E5327E97913E78BBF75FCAF
+:10D7200007E0B940F0D48AFB051FB2F854564558BB
+:10D730009D8DFE597D1F9D2F7D33E5F79A5816F775
+:10D74000935F593CD4A3F3FC3119174D1007D594BE
+:10D750003F230E6A8FAF0E16174D1007B5E8EB8307
+:10D76000C541992D5E6A8F83DED63182E2D0B765DE
+:10D770003A28FF51EAFD32FEF96AC7D7E97B47AF85
+:10D780004E565846F6C571D26DC23FC650AB33AD4A
+:10D79000FF4416FFDEF596315EFA8E28FE719AF28E
+:10D7A000F1E07CF07A60DE8E794ED24BABB2F7DBE3
+:10D7B000F1EA1676C965E155C6D9DD1D3CCEEEF11C
+:10D7C00033FA3D4D49C7F8F7749FA7DF8B642ACF22
+:10D7D000D3ABCFF5515EAB9D0E9E8EB67BE9779CA9
+:10D7E0007CD3D75129E8EFF15F9C3FA84AF812E4B7
+:10D7F0000FFED9F4BC041DDDCE0D5E14B98BE8A973
+:10D800001D4CC5EF8ADF1670FA342D4E4749D78B71
+:10D81000E9E7A3FD45C6B96F2A0CDF857223BFD3A4
+:10D8200024E97B228BE3F7CC4D2C2ABF4F66A62739
+:10D83000E05FA77B77B96C1FE11FF330A75ECC17C1
+:10D840009E5C837EC7D39D5CE927B992F8D50E1004
+:10D850005DDA9B7D0B507F3A5AEEA2BC9504FC40EA
+:10D86000BF5B7B297EB888EEDBF8EF845E29FDEE96
+:10D87000287E5CCF4EC01FD790AE15C14474C57CC6
+:10D8800086BF80AE278AF4C791AE929E3715EA5FB5
+:10D89000995D64965F83DB312CF1F76D9E16792DCF
+:10D8A00030CEBFE27BBD686391FF50EFC5FAE21B4B
+:10D8B0005973A2EF823D5BC6CFDD5AD6FBD268B466
+:10D8C000FBCE3291B71938ACA19FA6655CC2BCCD26
+:10D8D000E3F86121E8BFD0CFF639C4FEEA30E16950
+:10D8E00040E46FBE89F99B60E7BE3C3B9BD6B10527
+:10D8F000F338E1F92991E7598B63E33CA0CF627CCF
+:10D900009EA91186F7D3FB63DF6769A373379E8FE8
+:10D91000F1EB47ACDF67E1F58599B23D356A898364
+:10D92000327F04EDB6B8FD35356A39EF5830628D77
+:10D9300083F27C1D79BE6DD4E7440C731C9455D0E2
+:10D94000F8276B65FF1DD1B2C9E638E8E2A86E8EF4
+:10D95000731AF3A3E638279CAF54977EE8C7FBEE13
+:10D960008FA05E3F796AE43CD25FDE9B870348C7A5
+:10D97000DF9D73FB7DFBD10E07FB00AFE40FAA57C1
+:10D980007FD8CBFF0F02C2B069008000000000000A
+:10D990001F8B080000000000000BE53C0D7454D5FF
+:10D9A00099F7CD7BF393644226017480A02F01DCAC
+:10D9B0005843187E020109BCF9C94F157480A0B103
+:10D9C000207D842CA55D5A83959676EDE6416248CC
+:10D9D0008240E8D2EDCFE9CF88D03DAEEE69E87164
+:10D9E0002991D20E6229964A634B8EB14B75B0597C
+:10D9F000165BDBA295DAEEF194FDBEEFDE3BF3663B
+:10DA0000323128B4C7EE8EC77373DFBDF7BBDFF7C3
+:10DA1000DDEFFFDDC79DC58CB105F03FF3C60C8D72
+:10DA2000B18110FC3911FB7ED380B1955364BF22C4
+:10DA3000669433B6384FF6AB4C6321639D2EB99E86
+:10DA4000590CE6BFC09CD4DF66844C6B2A63C16569
+:10DA5000AA985F4FF05F5A2DE7EF8E0501DE2A8707
+:10DA6000E85B2B628697B10F31D95F4AFDD5C97E3D
+:10DA700094FAF732BEFF81F84ED382F58FCD894EEE
+:10DA800034C6C3B348AF1E9DFEB787FF3945E233A6
+:10DA9000C5C4F1F73BBEC0EF7AA312C1737EFF0D80
+:10DAA000E0BB86E4E330C7F77D88DFFDC4CF2738CD
+:10DAB0007EEF037CDA099F5EC027FF2FBFDF0F2BAD
+:10DAC0008D3DB8DF5F808EAFD1B997733AAE60FEFF
+:10DAD000A34477809F43E6F8C4A08F311C9FC3E125
+:10DAE000BDE8147264359B28F709D9C77383FE8299
+:10DAF0003372BFCD7A50B3E3BF99F46455119FFFE1
+:10DB0000EBF8A74DAB38D5879F81E72ED7FF06C727
+:10DB1000D3D67F8AD67767ECE712E3CAB1AD846FBC
+:10DB20008A5E8BE6F767CC6F14F4151CEB8C5936C4
+:10DB30007E306B3BF1276997AC9D6497065CB2BF62
+:10DB400083F4665709873FE1D8CE18E20FFC3B45C6
+:10DB5000FC9ECAF9F7FF9D1FBF3584BC94717E48B7
+:10DB6000397C6C8EF13B94B3F71BBE707E6A707C7F
+:10DB70004AFEFF0AFB15D27E429FDEEDFAA43E0A62
+:10DB8000BFCF9624F93B2908CF2784741AAFDA70E7
+:10DB9000307C3DFCB9BAE511D544B830878D632C93
+:10DBA0009A60B16DB0E7AD2CA632F061D180C97C2E
+:10DBB000E536BD665F243C5C5E87E87F83ECDFAAC8
+:10DBC00045E25CD8600CE38B14DEDEB5784E49BCD0
+:10DBD000D9D7D2F05E78CCFB88A03B10B4E9C9B5A8
+:10DBE00086EF0F015F6CF150B22FF8B3EA135F9E1E
+:10DBF0008C7C58552AE17E3386705E2C94700FD24F
+:10DC0000BEAB92FB7C8FF773E5FC1FD1FC145E0367
+:10DC1000661A5ED6CF28EE92783D766C80CECBE544
+:10DC20008B3D74DD1C689B958005E7F1A10D5B556C
+:10DC3000D36E1758AF1E04FF760F4BF649AE5276DF
+:10DC4000A097F6BDD6786D0A0AFE083D4DE29960B0
+:10DC5000018BD9F13BCCCFE71AEF6FB30BF7A3DC05
+:10DC60005E7BBEC79DD7DBF82EF560B52FA9DF061A
+:10DC7000F300DF7509E707E606EFD5EF0B72BED3B9
+:10DC80006E4FAE9E8EFE1AA2E3357E2E29FBF31355
+:10DC900033DDFE5C317E8F046DFEFCDDAEFFB760D0
+:10DCA000BA9ED9ECCFE348779BD7E1423E9B7E6694
+:10DCB000C400DE65FC2D4EB513420AD9A7A47E56DA
+:10DCC000F1F52B76B396DE2CF3AF0F39685EDB539C
+:10DCD0006C432FC00DBA2E36476DF3E2413E7E34C1
+:10DCE000A8500BF41D25FE6FE1F89D0AEAB45F9081
+:10DCF00069CC009D6A5831B918F16BFB398707E987
+:10DD0000125B9E9F827741C093FB1C5B96DF18F3EA
+:10DD1000A6C69F15FB9C0A723AD0FF133F1FE474FE
+:10DD2000A8051BFD085FCD5384FEFC9AF8DAE114C8
+:10DD30007DEB0DF26B03493BF43B92F7956E29970F
+:10DD40006F91FECB78FD8DE0FFC4AC85883F638E7C
+:10DD500059F675BF253B38DABA84F417EDE2BCAC4E
+:10DD6000E4799D43BC475BAF869516E29387C51562
+:10DD7000F01F2EBF6F5F3790525E61BC8A7C3E31D0
+:10DD8000D3F815B6A3C1013E5DA47379203D1FB140
+:10DD90008DBF194CCB072E6E8C221CD8D90DE7F6FF
+:10DDA000C26A755C13F0EDCF783E95941FD4DBCF3B
+:10DDB00045B67F4E9DCB9F8369F17C38BF12F488B6
+:10DDC0004D7004A6E9C3D779438A9433714EDA23A0
+:10DDD00048474752DF787F57211FCF79DAB956E895
+:10DDE000535E08F77952F097F9C6E17EACFC645CAB
+:10DDF0009D0BFE95257F8603FA6BF12FD87F207C43
+:10DE0000CE8972B0A65DB9323DE914F01F4E9EDF97
+:10DE100084D078826BB2B9C27FC06FE0235B096E99
+:10DE20006333C0CDA22F53429C7F5342493E4D21C4
+:10DE3000FC0D0ED731273A0DE1C254E69E9582BF04
+:10DE400046E01D74468F5E0F72D061293ADA557331
+:10DE5000CBDACE12E4ABE60C4C83E626E414ACEB52
+:10DE6000F0977AD1CF3D27F643782E3847F425FE38
+:10DE7000229AC73468E7D66F3A0EE0D8DBD3CD4A92
+:10DE8000C4A32ABA278C642D683C781CDB3BC04CA9
+:10DE9000639CB275D157A221D8A77FBE3380A2065A
+:10DEA000D159FF54C0AB41E0A51975AFB2319045CF
+:10DEB000B958203E07FDBA37B00D9E37347F64094C
+:10DEC000AB803951E750C283C498EC7229C2D58621
+:10DED00012659C6797C1C62DDBE24CF511371CF724
+:10DEE000A4C657DCC8EDD3AA10F0D32677DF17F409
+:10DEF0007D5FF07337E0D05F4E00F219EA0DDBE092
+:10DF000040FE991E8E67BFB5E2B69B81E04B652C43
+:10DF100080A36EA44F4DD19798AC05DC3A898B77DE
+:10DF2000E975B0AF38D7D3AD60EBFE0EC05A9C4E4A
+:10DF30004D5D5D10B7C9F1E931260B60DC56663DD9
+:10DF4000C4404EC2E61E6702F0B8B1F9F50D18F7ED
+:10DF5000AD31DD7A1DA078CF065F0DC6B52B4CC163
+:10DF60009725CE57906E0FFC877C71C55FFD810BA6
+:10DF7000F9BC50611300FE9D113E2EF9E266DA2BCA
+:10DF800076BE6819FD2D674B763D639B7F5F287FCA
+:10DF9000DCF95BE08FD96CF665A093A9DEA588CF8C
+:10DFA000A576C5A796D03407033A5D823F07DA37D6
+:10DFB0003D877ABAC6AF051CC887258CF8D728F6E6
+:10DFC00078AB55DFF50CC4AAE12D7B7A4A00CE3D33
+:10DFD000675486FCEA587D0021E1CF83F034211795
+:10DFE0008EBCAFF66B304FFBACCA703FC947E0B791
+:10DFF0006F2E3C3F3700EB61EA3D55C027D8F70E46
+:10E00000C3ADEB302F77E1EBEDC8A75CD6121F0B49
+:10E01000FDBBFC0E16F7A4E802BA2DC117C7658533
+:10E02000F6D235B9AF236D9CF892FB99306368BB8B
+:10E030002DA37F2ACC5B26E5B61DCE13CE6199C1F8
+:10E04000CF439E2B8B707995E7929B21AFEE2A6789
+:10E050004A3EB3C86BE639C432CEE180C6F52471BE
+:10E0600046A5B822B1571B53057D6BAF83F418F258
+:10E07000B4C34A01FC11579806FCBF5BE04B3FE07C
+:10E08000DB8196C2587749EA3CEE2E3BF127A58208
+:10E09000F159D7A5EC11C32416FA7789DEDD5FB2FA
+:10E0A0008A507E3FC47A9DA8D7F762C60CF87C9848
+:10E0B000F95CD86F62016AE1BC5DC8AF037B9FCE9B
+:10E0C000473B129FE82C3C5F46AAC2EC7632B34530
+:10E0D0004E9C9774C3E4B8B49F1ED34F76D90B2DD2
+:10E0E000D9698361BFB026E231B3F891F86CF38748
+:10E0F0006807655FF3B530C4E3EBB3A3CF72BBCB66
+:10E10000D74FAD307E84FD83B38C53D87E13E33D6F
+:10E11000F00F17430F525EF2F674E334DAB54C3B5E
+:10E12000760EED989E9287E519F220EDD820DA312F
+:10E13000185A8EFA0A7C63F55767C7CE4939F8003A
+:10E14000FB00F207E8F925D97F0DE801BEBC84E7A2
+:10E150003E8361F52DCE8A884CDD07F829023F7C8D
+:10E16000AE807D57B6FCF04FCA18DE5F00F3147125
+:10E17000AE9846D6A0DFF87AC0E39982F6C21C4476
+:10E18000BA33F9028ED9497999FFC420CA8D23EF99
+:10E19000BB93CD2C7E3079AE1B9DAF25E9423D82ED
+:10E1A000481EE95098E9B88CF4F8008909EF241763
+:10E1B00016C941C75285E8EB28618D68CFDB7168CD
+:10E1C0003E63DB972ABDF8FCF170118F97A6F2B879
+:10E1D000707B618B3F00F3B63B613EDAF33293AD67
+:10E1E000989E82FB7858A5F937CF31F2D07141DC87
+:10E1F00047F1928C57E53C5F98C79563C33CCE28A6
+:10E20000AF881685719F7126F11DE2A8B1D4F7C6BB
+:10E21000638EEB445D84FF74872D8E1898D4C2D032
+:10E22000BFBB0DEEDF33E9BC219CF4EB3710BCBD66
+:10E23000D2AF1B37227E8BC7FA1AD0CEB900EF7D42
+:10E2400025297F7D68E9E754D896DD122E21FCAAA6
+:10E250009AF7B45D07E71D0C4EF1A27B8F57B7F814
+:10E26000D1EF6D9FC0F996B9EF9630F783736E10BA
+:10E27000F304BFA4DFF740F8ED847D30CD77601C58
+:10E2800050CCE3807BC3A5B44EC60330DF72C1BC63
+:10E29000E04DA0A718374FE37032F7BB57F033E5D6
+:10E2A0006F030568AF196B217F1115FEE48556E3F6
+:10E2B000A52110CA81D67A6AC1FEF747C0C00D6A8F
+:10E2C000567E200B1D77D63CE041386DC54D1EF4BF
+:10E2D0009F1D4698E036AE0EBE3464B3B7DB8BD9D3
+:10E2E00064C4EFAE860FBE3464D3B7FE7C8E2FFAC3
+:10E2F00019CB9D82BB12E504F03D1E74C717034382
+:10E30000DD7E16739750EBD4314F0CEB341E35D6AF
+:10E310003213F3F1AA731AD5BF0A5972FE5638DACE
+:10E32000703123BF1EF5B7305CE7863ECE8F2E7C62
+:10E330009DE6DF59A532CB8627D89F35145065C49A
+:10E340004BBB51C0006EC77C25B60DF068F0AF27FF
+:10E35000FFB375512E3D877D09BF3BA63593DF92F4
+:10E36000F15547241220FF7495F1547C76F47EC455
+:10E37000CBE54FDAD507485E5376757398DBD54FFA
+:10E38000E173693FF61D7F81ECC77685CBE176E0CE
+:10E39000F7B7B3C8C756A107DB0BB3CBCF9785BC84
+:10E3A000BE3D3DDA86F00DF069FE59EF3DDEEC90A2
+:10E3B000F1A6E0E3D5F207F8F12F619B5D067E7CC4
+:10E3C000313C7E381FE0D78EF64295D6E2094543B0
+:10E3D000F9CF11DD47981943381ED64293546F94F4
+:10E3E000A1BF1B0E27CE70DD2A41DFBBB5C7DF8280
+:10E3F000F086DB35E38930E5853AB7A3C22E33D604
+:10E4000023FCEE7BB3DB671C604FB1DE8D8F6CF3BA
+:10E410008F8A73EEAB348F229D37E9DEB5782E5D9F
+:10E420008AE1F74EC1BAA7D9887ACACA668DB2CF37
+:10E43000568233506A6E88929D5F3ECAFC6D625F61
+:10E4400041675911F911D8F74BB96AAA3F1A5D878C
+:10E45000C2C64F11EF3633FA0BD4BBED650EDD5259
+:10E46000A8253DECAECA8929D0CF9965BE887C0528
+:10E4700011319C00BABBEC0D8A8BDC4B148AD3DCC7
+:10E480001EC8E0B2C8F979E16F20D6A07176D6F047
+:10E49000DBEB1D8511477ADE0B2261D8EB171147A4
+:10E4A00013D6E5A53FC3BAC9B7B3C8C545A14FAA9E
+:10E4B0007B539ABFCC9CF746D845F39488A84B0869
+:10E4C000FFB7D2CDF32BF663C0CFE65FFB2A437FC5
+:10E4D000203DB098A5D8FCA2F48334627BEEC6BA86
+:10E4E00013D279261D8EA4B328C2D2F605797544BD
+:10E4F000781D438D54A6C657AA8CD73DFAD3F9058B
+:10E50000F8782264A7D8D008F8ECCF8ACF603A3EDA
+:10E5100045117E2E7D954611C203FF3C16DBCE10C1
+:10E52000C85F16FE7E6B46E87AC45363566769C9B6
+:10E530003BC6AD37201CD9B7C5AD7A24DDBE9644A5
+:10E54000B87D2D8D907DCDBE6F85E0DBD5DA87F768
+:10E55000AAF73BF0CF2C7AD49D7832AF02F070BB93
+:10E56000AD4F92BE96CF1A45DFB87E7FF886FE4942
+:10E5700048E751219F68DB31DE30741E8F7C22C258
+:10E58000E53878538CE63D3542FC919C078CC1BA46
+:10E59000DC4871C8FCF71887742F1CC8A338E4CD79
+:10E5A0007D79E8EF9F1A0A658D438E16F74CCA16DF
+:10E5B00087F48D1087AC8FF078F5F87FB928AEA876
+:10E5C000BEC0FD7CF5851E15E3898D119DF83E7F4B
+:10E5D000A85F35414EAA310E01387D220EC1F914D3
+:10E5E00087BCD9A3225EF32FF4D3BA6AE8631C3246
+:10E5F0007F843804B05051EE0E5777FF0CCF2D9327
+:10E60000DE5315E666BBDC5625FAE93D895CD75D2D
+:10E61000B62DCFA4734E979BF86C8E6F6A1D97F73B
+:10E62000CC7923C9578DEA2DC3FA4017CB0D201F93
+:10E63000DECA1953C10A785E837171174E05BABBE1
+:10E64000CEE6C52CCCAB3D7CFCD3B963F6612BED9B
+:10E650008F47E8C55B3937C4441E6414C0FA4FAB1A
+:10E66000467C31F8A1AEA99FF7717A36911E6D16DE
+:10E67000BC09EDD1289FBE55C48332FE7A6EA51227
+:10E680007353D2652C590AF3E709F8AE393C3FAC15
+:10E6900055BD346F4719A379B75A17A97E313FE1A9
+:10E6A000D275E8CF4BACE7F9A2FADD937918EFDF2A
+:10E6B000A231159EAF6C8FB6917C9E75513DC38083
+:10E6C000FF503F2BCFF412DFF2865C69758E5CB091
+:10E6D00064715BDCE2CAE833757541363B24DBCC00
+:10E6E0003AC4C188C83F2BD88CCBC0974BECC14EE5
+:10E6F000A4CD3D2D74FC51367CBDAC2F6C9C617C4F
+:10E7000007E563AA33F1EFDF017EF5BDE6A2F73A34
+:10E710007D7BF7DE5E81758B1E8DEABA329F01CA62
+:10E720008A96613E8B3CA0BAF4E92694CB23F9B2D9
+:10E730000F060DF03E82092BF9BD8F3619B6FEA9E2
+:10E74000C843AFA0DF3B325ECE7F95AF977D2BD124
+:10E7500084F7358E4CE0FD4B11F5518BCE37A1512E
+:10E760001EBDE597DE6CF6F1744DBABCDE51B5897D
+:10E77000CBEB28EBC0AEBF18C9B22E67A9B9633A7C
+:10E78000F0E3C89083EA389067C5313ED838C37C3F
+:10E7900019F9B57D90F3F5C86BF7FBF09CDC6313BA
+:10E7A0000F64B3F3BF11FE285E1DA3BCAB7BA6C8EC
+:10E7B00077D990867E6BF7A2A74E55C03EA7E74F4C
+:10E7C0009BA50209C00B0FC6CB72BDBB86E77129A2
+:10E7D000FC9E579BD0FEBCF64A43367DAF8C98BF5B
+:10E7E0008FA4CDE7EF45DB7A34E27FD189BA7D781B
+:10E7F000EF275EDDD3AFC1F9F6FDC6C1304FE99B0F
+:10E80000CEE3FE11F10A005E455784D7DE7959E464
+:10E810000DF072D58C1F8ED74F6A187FEF53617839
+:10E820006A2A87E3C9441D7381B0F739AF7E9EEA37
+:10E830008E7D0907154F2E0DED5351F464FDBB7B02
+:10E84000B0142320B678C9391545CA7C504DD3BBC6
+:10E850007983B969FD7B5BC6A6F5576D9894D24361
+:10E86000F87F79644A5ADFEDFF405A3FC866A7F542
+:10E870001B96DC9A06AFC6174EEBD7F96F4F9BFF7E
+:10E88000417D455AFFF6B25569F39706D6A58D57D7
+:10E89000FBF63C84E5A368F94C6D2C23799C897CBC
+:10E8A000CD3B63903C6E1FBCDF877211AF8E521E52
+:10E8B0003D90DF5F8CF5EBE79CD9EB0B0FD6A8D230
+:10E8C0007F17A3BF3718CFD7E4FC606922AD2EBFF6
+:10E8D000AE86FBE735354AD63A41A63F967E58FAD2
+:10E8E000E5CCFD33FD6EA6BFBDF3E67D1E5EEFE712
+:10E8F0007E7FA59083B6B29F7A13485703AF2374E7
+:10E900001703BD5EBA8F41FA757CE5DD93F1BD5A00
+:10E910006E9939D65D92F2D7E1B218FB258CE7FAF1
+:10E92000626CCA741C8FB175D3A92EAD85CBF9F377
+:10E930009BC4F3F5D8829FAEB5F12DD3FF063D33CE
+:10E940007F50C052F14AC31F8D4801E0775BF3410D
+:10E950006D1CB461EF31CD6E874E57FF6ADC087EC7
+:10E96000FA633519FA84EBFA8696BFA31F78B99536
+:10E97000D7DD0FB57A581CE83BDBEAA3F6E7AD7E9E
+:10E980007AFE7CAB4E6D476B19B5F1D6008DFFACAE
+:10E99000B58ADA675A0D6A4FB4D6537BB2354AF35B
+:10E9A0007ED4DA48ED8F5B4D7ABE4BE8E9FB051F5C
+:10E9B000A34CD615A2C71D0AF1B501AFEA2EB86067
+:10E9C000A8763B0F7CFD4236BEBE577F12AFEE9D50
+:10E9D000847206FE2AAB3EF5D6C8B83E79DE84972F
+:10E9E0008C87317F413991753AC0EF31C4CF8DF5B5
+:10E9F000B9A2ABC7EF88A8DF1C29648DDF1670961B
+:10EA0000E5A33DFF4A3444F67CFC4CB2E77EA6A564
+:10EA1000DBF39261F67C2DE91D3B897552AC2FD258
+:10EA20007B8A8C3A4841AD4EEB641D64D11F791D41
+:10EA30006434FA81EE9368B7A4DDBE52BA879DC7ED
+:10EA40006CE327C83FE99F87F90F7323F98F2AA149
+:10EA5000B34C7B93E2C43C41CFEE579617A07D7137
+:10EA600023823C4F3758159E3393F701F66D281ECD
+:10EA70000EF7E5EA5EF2E73B9271CEEB14C70CF7B6
+:10EA80005FE97CC058C8EEDF810FAFA6FB45CE879B
+:10EA90001AF5BB896DE09F8F2418AF93CDE1EFEBA2
+:10EAA000A41F3C7281D7312E694A8CC1D185584B45
+:10EAB000CF3C680F7F8E8D8BC2395B931D810330F5
+:10EAC00035EFE93EDD03F38209736C0E8C57C57395
+:10EAD000685D68C9CC18F61BA2AF937D0A69E97E10
+:10EAE0001223D4A4DFA1225851467F626ABE8AE76E
+:10EAF0005B9AEA03DCF5B34DAD16CE65F9C516A6F3
+:10EB0000978B7AAA37AB7FDFA8D8EA6C1A0B7422EE
+:10EB10001DDA6776F0F77A19F226F924EB6D320FD9
+:10EB20007F8419BEDA2CF143BB78EF92F9BEE50F72
+:10EB3000D34D7F2DF05DF19DA0F72D6C03E3F723FE
+:10EB40001C909F20FFC6B862074A86CBDDC1591FC3
+:10EB50009C5C4BFA6D29D7266FEF51286F177913FC
+:10EB6000D3EF73D8F318993765E6470F0B3BBB0B10
+:10EB7000ED2CB40F3B19E55B1D4A6E609F92CA975E
+:10EB8000C06FCE40BA16D58AF72FAC651EAF177E80
+:10EB90002E2D5F1A116F91973893E75EEC3B9F978C
+:10EBA0003A77AFABC78FF71CBB667EB5B109F936B4
+:10EBB000D343EF399916D7D1EE64D2C37C161B37F5
+:10EBC0003775DE2AD3CE637DB61382197CDFBB1383
+:10EBD000BF040078F901475ADC5350951EB7DD5D3C
+:10EBE0002BEDECB5A1030580DE6F4B3C5954D45599
+:10EBF00079FCE911CFDB756E2F18DA3BDBFBF5767C
+:10EC0000AFE1F1D9CE7F3B9E8F7B647CD492761F9F
+:10EC1000D6C17BBC0ED2EF4E5DEBC2FB1E9D5E8D5E
+:10EC2000C737BAA33EDBFD95DDB58AA09BE3E513AC
+:10EC300078A9C1E514078DB45FB79017D9CF2D37E8
+:10EC40000DD2473D10C53CB9CD3B4EC1FAA81CFFC3
+:10EC500068AD22E485D797BB445C955BD61B77A053
+:10EC60009C4D583F1BD9E68138E93C3CF794F7525C
+:10EC70005CE59DE832B3E1FDCF025E9733504F79FA
+:10EC80007FBE8361DEDF5592DD8FFE632D8F33DB28
+:10EC9000F459519C6F015FA629C3E77D5CC8C1434D
+:10ECA0004E9043D8BF6BDA5D744FAC6B3223FB5D83
+:10ECB0005A37FDD1ADDE2C72A8DF47E7E7F431F912
+:10ECC000FE3DEDBE449BDED0B816F6D59E6701B47E
+:10ECD0001999FAE69CB0BC712DDEB7A8CA0DE0FC0C
+:10ECE0001AF5C716F2B123C0A8DEA115367BA8EE2F
+:10ECF0005CACD1FD08892FC4EB8FA19D1A4DBE33AA
+:10ED0000F181FD48EE463ADF4CFC28949FF50EF366
+:10ED10000BCDC66816783F4FEA55BA7C394791AF9C
+:10ED2000D1E849F3AFC529FFFA6CEDA675784F6DB0
+:10ED300027E3E3A76A4394EF67F6AF959EB7693D73
+:10ED40008D782E6D535D247F99EBBB4A385EDD27AD
+:10ED5000AAC5BE3E05E57F5755510EDA772F1A6AD0
+:10ED60001B5F9FA930CFD5DAE2A6C2482F8FDB6B9D
+:10ED700019C9AF578FFAA6825C78CFA82053C07705
+:10ED8000C7DB7F3CA7BF773EB21E83E4964C3B9720
+:10ED90005BF636F0A54088F518F6703FBF2FB299A4
+:10EDA000E6497EEDBEF1B781F83BF06DCCC2F4FAD6
+:10EDB000D4BBAD3F2975F9E388CF392C07F97C899D
+:10EDC0003DA890FF8E18A477BEA45DE5F756C6C98E
+:10EDD0002E90837D123925559762F8DE03F5CB64BA
+:10EDE00014DFD0CCEBC42B2FA2DB47EB260930136A
+:10EDF000F1428D8AF2CFEDEE25F61ADF1F96E1BDC6
+:10EE000015C572909FBD11E51AE69530F34FE7B234
+:10EE1000DCE799EC6B3EB80EDA4975A29E26E8193C
+:10EE20008D1F12EFBF94DCCAF820B38E2AEBAC1D05
+:10EE3000A2CE3A5A1D956917896F32FECDACABD27E
+:10EE40008D3AD08FB76ED25837F19DC70BA93CDFF2
+:10EE5000CAE375787EFF6E9EA0EBF0D9A45FA4E7AD
+:10EE6000D26E65D2F9E4287EB1FB4C7B1EC2694BA1
+:10EE700034517DFE907FDB2905E3DC844B67367DD2
+:10EE80003D9C9FEE373A84FDDB5627EAF0E73EA52E
+:10EE9000627D609EDF52F1DE5E5522407EA14DC94B
+:10EEA000FEDEA1BB8EFB9B617E22E3FDCC7FE6787C
+:10EEB00063AE5296F41FAAA053FA57E08F62D7BBF5
+:10EEC00043F2BE9761E8BEB9A9F8B3FBE98F321DE2
+:10EED000E323BFADEE5B9A65FF617163BA5F5006D5
+:10EEE000F9FD30C9D76E9177B7F9F979CC4102B203
+:10EEF000F801887F3F5B07F254D99F6E6FF2CAD248
+:10EF0000ED4D663CECF6302BD7060FE2E1D63A52D7
+:10EF1000DEF478B6B89E91BC1E2EB454ACFF8413B8
+:10EF200006C3F3D08A4D86E7E1F2BFF37934D6F118
+:10EF300078A1A3AC298A7993AC3FEF5E741BD957B3
+:10EF4000F0A33D75B6BC49DE7778B7F52829AF5AEE
+:10EF5000867E66D6A5BA17FE3DD5A1DAFC4D27B14F
+:10EF6000AE7408E411F5ED70BE9987F725ADE7554D
+:10EF700076401F5EBFCAA44BD6A1C6D78B7B2BE7BA
+:10EF80005CF1C5788F7290BFA7D0064DBA7F02F4AE
+:10EF9000D07BA279E23D5166DDC9ED6EA1F773F138
+:10EFA000EA9655F6BAB3E45BA390E797AB4DBA3750
+:10EFB000D43142FD4FCE7333C31A87EFC7AB3F4BFB
+:10EFC000FCC6CFCD302F97752D7D86F9BD3A98E7D9
+:10EFD000BA68AAE375CCE72C3A87BC7F6224642C1C
+:10EFE00057891D80F54F2F7A8AF2CDDF27D8587CBC
+:10EFF0007F92CC37359E6FCA3C56DA8D1AF589CE92
+:10F0000052183F7C46A33838EFE9AE5358770F9E2D
+:10F010005947399FA1ACCCC37DE43D2689F7D5E69D
+:10F02000AB9598AFDADEB748B8DF69ADFF05CAC562
+:10F0300093AD516AFB5A0D6ABB5B1BA9ADD28C30F4
+:10F04000FAA5AA7ECA00D9822118B7E1517516D651
+:10F05000DBCE7F5785F9DFC8B7CAFE68DABCBCB221
+:10F06000C6B479902FFF1AE7697ECE4FD71285EE8E
+:10F0700027DC39C81E52F42C76E1FFAE5DCAAFBF63
+:10F080003676A9A89EF29791EC1223BDAB1A14EF25
+:10F090005DA57D12FAF7789D4E7A91D4437CFF4AA4
+:10F0A000FECDA2F59DF8E77CA067CCC7B81D4BDD6F
+:10F0B000F3A0EF1B83E2BBEB9B4F2EDA8FF7803A76
+:10F0C0005E94E3CBF71BB67166D534E3F726C73001
+:10F0D0005986B873C7C9F1CDF45DB6F8AE26DC58D1
+:10F0E000583CC052F71F33F9B5AB9EC7EBF27E4DCB
+:10F0F00090F1FA9A1CFF64BDC8E3801CACE3C9FB25
+:10F1000013B9237C47F4F17A6E0F3E23F8D4E9E279
+:10F11000F71716677C2F1212FB8EF4BDC836313EEE
+:10F12000DAF721ABC47E4D62BFC7E6446FA3738B91
+:10F13000F2EF329AC5F30567626D633068F4B3ACE1
+:10F1400070960B7BFA6C3DBF97ECF21B1A9E0BC0BE
+:10F150006B20788DFCBEA61C5F702139DE48E30D64
+:10F160007C7CC10593EA4AF23BBDE5F565FBB74EF1
+:10F170004DDDD3E9C0FA8417BF57E1F79FBE26F0F3
+:10F18000CF6CE5F72A77F9C47D1F3675BF81700C07
+:10F19000FE7DE6EDF5B70CE177C7B0FF06DA5F7CE0
+:10F1A0009FB300E9ADA4E7FF40CF33FE9D81F5F5A5
+:10F1B00093F78BEF7AEE433D612D1CEFE4BF9B602C
+:10F1C000CDD96FFF4E6841FDEC66317F33C1DBC0A6
+:10F1D000E7679107218F73F7634DF60AE0B512BC1C
+:10F1E000D51CBF5BEA757EDE19728BDFFF139EE2D2
+:10F1F0007BA133D1751EB4E7C97F07C09A4EFB5D72
+:10F20000019F76121C53EEC7C4BD28AE1752FEA54F
+:10F210003C7C4BC8DFEC7A45CAD517687DF335A333
+:10F22000FF1B042FE3FBA4D1E828AF887E93D6F917
+:10F2300093F793FF95FA57898FFC9E2C532FBE2787
+:10F24000E8877DFF83CE0BE22FC413F63D742DF6C5
+:10F2500005B87182E349C23D762DE032FDCAEE99D0
+:10F26000FC2FBAA2684270460000000000000000B7
+:10F270001F8B080000000000000B93E16660F8514E
+:10F280000FC121486C62F17A76068678160686B937
+:10F29000AC0C0C3540ACC8499AFE5540FD4B81780A
+:10F2A0000110CF06E269403C11887B80B81D88655B
+:10F2B00080E68903B11010F3023107103303F13FE8
+:10F2C0000E06869F1C08736E03C51E93683708DB05
+:10F2D000F220D8E781FEDF02C437C80887513C3CE2
+:10F2E00070163F03439D00822F2C882A9FCD8F608C
+:10F2F000F38A5266971C503F008DFE9C5880030095
+:10F3000000000000000000001F8B0800000000004B
+:10F31000000BE57D0B7854D5B5F03A73CE3C333312
+:10F320003909794C20E049483055C0214004A1F505
+:10F330001010432FD78ED42AF5A2774004E49554B9
+:10F34000B1D2AB6D46264050F4060B0A0A3A50A8DB
+:10F35000D08246C4962A7A07454BFFB6365A6F7D4F
+:10F36000D4F6C6DAEBAB18E28362FBEBEFDD6BEDB4
+:10F37000BD33E79CCC24A0C5DAFB874F77F6D9AF25
+:10F38000B5D76BAFBDF6DA3B1EA884C273013EC68B
+:10F390001F96DEE60180E24C3AEAFAAF2EDA3386B7
+:10F3A000FDFE7F3DD11D46A69E4C4F0305602C2BD4
+:10F3B0000713A004E05C1FFB95D59BFCD323BF3D46
+:10F3C000AB08E020A8E0659FD2DAE401FFCCFA396F
+:10F3D000F82144B1DCF5D360796710DB25A8DD970F
+:10F3E00080B74B5718E5FA70CC800BBF9B3EFA9D57
+:10F3F000F5337473136B7FEC8320B577C22153F818
+:10F40000D00569D1E6E34AEC577BBFB346E42B80D5
+:10F410000D0E02DE29007519780FFDEE7582F77169
+:10F420008DC16B6419DFC7E02FCAC07F10BE9A0F71
+:10F43000C339FC665D06FE938587E6CFF09C6C368B
+:10F440001EA9AA0658DB0C8F54B901D634FB28BF7D
+:10F45000BA59A7FCCAE608A5498D356170247742E0
+:10F460002AC1501F8AB2FAB27FF65FA0CA67CBFBEF
+:10F47000CA755BDE53C4FAA9C9E4B5A061CB278382
+:10F48000F5BE7810C76773F7E2F83E4A1998CF4582
+:10F49000183ECEE455C16F246602A34775D063A41D
+:10F4A000D83CCE0CCE9B0E61AC7719E1CD23F07A1F
+:10F4B00075D98A4E84F77D560F58BD338253DFC409
+:10F4C0007AFFA7E2FB7C1E1B014AD9F7D5DF6EEA63
+:10F4D00054587F2BCB3CC60A36AF7BD9F8ADA75B1F
+:10F4E000F0B85BFB03E2CDC7FE211E6B36F37C66F2
+:10F4F000DEF6FC19C0F272DE15997E4EB6DF61EBC6
+:10F50000FBEEB7DA88D523BFCA7E87417C851EFC17
+:10F51000FCF67B26C3F980DA4CBF729C7EFB65EC5F
+:10F5200010636D876D86545AE93D4EB5116D4820C4
+:10F530003F6CD62055C1BF1731B9A81672D1A2CFE2
+:10F5400008205F39E101EB389519BA54177966BB89
+:10F55000189F54472E5EA4205FADB7B4AB049072E1
+:10F56000F3EFCD3A986C1EB734D750BAA3596F4712
+:10F57000B9B9E5237566FBF0DEF2F8DF425FDDEA3C
+:10F5800006E2BFC42E48ED50B0BFA61766B3FCDA42
+:10F590005125B53719989FE942FDE0177CBC5631DB
+:10F5A0002EA9C4FACFA8807AD0290FB7B8635F46D6
+:10F5B000795833CAA5AC403C577179A876A77D43EA
+:10F5C000D9F7B5EB2B473188616DF4599287EAEA98
+:10F5D00061868AF25025E461ECED3ED4873DF35F0D
+:10F5E0005ED25E3500201FE913CCD04B3F413ED0A8
+:10F5F000275AF0F519CAC3A9E3AFB63EF96B6DB44B
+:10F60000F24D2F2BDF51E53154A5375C85A7A5239B
+:10F61000B1E1BDF9ADBA4AF059B46F3E73A62B9B68
+:10F6200053F02A1BFCF6E608F1DDFA6683D29B054F
+:10F630001F7A91A7C6B3BCE043281F43F99CEB1681
+:10F64000DC487CE92E4A01CAC9EDC89FE7E0702B6F
+:10F650004D7322D3913522CF9648175B03D663F9B9
+:10F6600040CA9B508EFC29CBF7264CD6BEB8869755
+:10F6700037287B13B866DCEEE7E55F56BACDC444A5
+:10F680004BFBC4CDA6599EA9CFF2E97ACDDA1FEB88
+:10F690007FB8051E3844F5657FF39457797F7EDE89
+:10F6A000FE26E52533517EEAFBBF49698B30D30244
+:10F6B000D638FAB9A927BFCE348767C6A9BCF17E70
+:10F6C0003311B496DF6F229E64F938655D22C1EA7A
+:10F6D0006F845895C2E85038B329C24C23F0CF4A02
+:10F6E000996EC30A1FC777667EB713BC812A5E3E38
+:10F6F000E2C6E7CC6455A67CB2F2AB04C2EF2F8A17
+:10F700008321EC055C1FDD9CC5981D547ECD2F1810
+:10F71000DFBB4B3D51B23BCA59A68C7D8FC4C1AAF9
+:10F720000FDC11ED35AB3C4B3E64F09E43F0C69AC6
+:10F7300066E68037618557C2D31FFC128EDCFCCA97
+:10F74000C777F255FDA5E37E3591B1BABFC31D451C
+:10F75000B3014D282864BF7CF85D53615D965CCE93
+:10F76000686010FD66C2D0DEFD96CE1C08298BDCD9
+:10F77000FFADE95B85798EB7D94A7186CE2C7F853E
+:10F78000158FE7887A4E3E94F3F3F49ADF15B6F9B5
+:10F7900081D6168985FA9FDF7A7F7C662CD8BBDEFE
+:10F7A000D38A42E3D7CF18F715E0E381B782962CCE
+:10F7B000136A33E3155D2CC74B651DAF38766AF1CC
+:10F7C000E9944B09AFBF17BCDFB5C17B939BC96FF1
+:10F7D00016FA9F6A78034CBF9E941CD69C981C9E78
+:10F7E000AA7E8BF057C65FEF69903E97E175D98589
+:10F7F0003EB2FBA5FEFBACF15782458C9ECB7E79D9
+:10F80000C52BE7BA30C3F87C4466FC26C520B87324
+:10F81000F17BAEF900A46CFDFCBDE6930BAFA75ADB
+:10F820002F9DA8BE5DF19B00A07CADAE8214DA18BE
+:10F83000AB0F9F970FACBFD5BF985C8A70785BCF3A
+:10F84000047334C0066CC2EC8DD5D2FEB8A8F68421
+:10F85000EC8F9B9AA1BD85D9350F859BC85E5AADAB
+:10F8600000B567FB524831BB66CC33DB7DB311FE7C
+:10F87000E86D94AE76B3F2207E3FA44F66530854F1
+:10F88000178E62E883D57EF9FDB986A1ECFBCD55D4
+:10F89000EC3B638DD521DE1FFB1EC3FA79D5FC7BC3
+:10F8A0002EB8F26A183C16BCFB3DA978367D59EF9C
+:10F8B0007211FCB7A13DE6C5FD8041A93FD01647B6
+:10F8C000A60B0CF118DB2A7AB79BE5E2FB8175D514
+:10F8D0003F4AE3D67A8DB0EB1E3FEFFBD089FAA208
+:10F8E000AACD7461FB28771DDCE6B0BB82C3657EC0
+:10F8F000A03299751070E46FE9B1E32A27A11D17B2
+:10F900001676D0792BCE9D84EB6C4F398CB295CF87
+:10F910005971F624B4DB0A7D4D2F4C64E317327D18
+:10F920009A44D1D10CA509EDFF8B0AB3F2CBBA6989
+:10F93000BE992956BEEEBC61155766D9FF302AD252
+:10F940007C657E40839DAF6F1376EC2DC2AE2D4754
+:10F95000191F2BF88F098B9F57EDD16BFED3B95E22
+:10F960000BD41837225F0E688028DADFEB18FEE22E
+:10F97000163AF96BECFAAD50B3CFEB54CD67239840
+:10F9800097B9C6E6EEDF295F1B217E25D62F14EB43
+:10F9900056A026AAC487F73F7FE77C73CDFB2B02D6
+:10F9A0009F6C9CABB38DF359E1A530C8C619F3B772
+:10F9B0001F2780E358D7B113C43B2CDE6EE27E1BB9
+:10F9C0006510F7737E98124DD33EEF7AF2D35D2B1C
+:10F9D000FA84F8261DED1C82394BBF5A9527E36F38
+:10F9E000C3FFA9B3F2B3D145A6CB5F7EA7E090A534
+:10F9F000FE7657A8E835DCD49F0D677FAC66DA83C6
+:10FA0000F0076A128E60A14D9F1E6FEE2E38C4F46F
+:10FA1000C6CDFA0CD2C7B9C6FB21D3A3692657BB02
+:10FA20009A7D94DEDBAC43DA8B7E8B08A5DF63F234
+:10FA300087DFB7B27D24A6F73447E9FB96E67194D9
+:10FA4000DED56C52BAA9B981D23B9A63546F43F3A5
+:10FA50004C4A7BF0F9211BAF4EAC6FCCCE3A7366AB
+:10FA60002AE1423FEE3E885633FCAEC6EF16F8D789
+:10FA7000B9263D4E7232D34F7E8F02E1F70840CA5D
+:10FA8000ACC276CFA9B00372CF2B29E67581EAE22A
+:10FA9000E36B35347840CACB6EA075AB640A5BB7B4
+:10FAA000185DB582ED85885796A7EF056C3D43FF3D
+:10FAB000A07F0AA4FD23A98986ED8B44FBD6A08BE9
+:10FAC000EAADABD168DD73F2C508D0A75561E59802
+:10FAD0008FFCD4BE90C6EB4FE4E3159CCF143DB32E
+:10FAE000EB5B751775BA6E0C5F3FFD358C5F2C7242
+:10FAF0005130F50F486928572B691EEBC2535E64DD
+:10FB0000DD317ED4CB2A583F77B02D35AE6BBBB6F6
+:10FB1000BFABCFB6D039A8727B7DC4AC773B10BFEA
+:10FB2000233426D76C1C757B2085EB0EA3878AF0C7
+:10FB3000E60B0532C2C7E7ADB6406A9B9229D70BE8
+:10FB400038DE47E85113D7B99EEF7EF1DDE84EABC2
+:10FB5000D82E05D16D46A63C24DB99F67621D92E08
+:10FB6000018A86EDD6B37690290FCB7630CAD62E91
+:10FB70002CDBC1B3268DB7D1DECE5F207026E61F09
+:10FB80001E1775C52DFAC15F65BAB8DCD8E9948B2C
+:10FB90007F8A40D0E1F184F231E2630ACF2B8AAF51
+:10FBA000F56317FAB3EC721D1E63A71B5459F28C50
+:10FBB0007417A1EC16931DD480F6C6B6D6ECF4DA11
+:10FBC000A0C5A655E3FC266AB6F9493A6DF0093A94
+:10FBD000B606B2D269832EE8B8006C7496F4DA20C7
+:10FBE000E9B52C3BBD36E4A0D70649AFE5F67692E1
+:10FBF0005E1B72D06B83A4D7627B3B492F273DC22B
+:10FC0000E3D28A9D6E6D943F55F470EA850E97415C
+:10FC1000DF5DBB4D7D12EA871B34DA57438DAEE0C2
+:10FC20007E00CA4F70FD8026C075612DFE2AED331F
+:10FC3000368F5D788EC5ECAB39C95727A11D1E5490
+:10FC400064F9A14968876FF3F0FC75C9E393D00E9E
+:10FC50007FC4159BAB92BD93021ADF812F6F2C05D9
+:10FC60001B1948A76B4D3F43BE397DBB2B9A3032E1
+:10FC7000F07881E305B7EF1F6759BF72CF43E017F4
+:10FC8000EB0C3D2138BF45706A299A772F382F62D7
+:10FC90007032BBC240FE66FC6BB49E1A38612E5FA8
+:10FCA0002F7AD667C7FED7D9FE8CED2E1BDFD46C1A
+:10FCB0000ED8F866D8FA425BBE6AED405BBEB2A5CC
+:10FCC000D296376E38C3D6DF9065B5B67CF9E2734D
+:10FCD0006CF98173EB6DED7BF10B707ED9A9BE7C65
+:10FCE00023E2B9870E899A7AA283A8BF3B59536F42
+:10FCF000E3A71CE55FF9B666FA18FEB5220FAD431F
+:10FD000000D7107E24BEF275487850BF140553E723
+:10FD1000B3F2806E26D02FA0EA26A01DE1D2E39494
+:10FD20007747ECF275211A4A8CFE5FD9A5816F4C9A
+:10FD30009FFD9B9FA4FFFEE6E5E417B9BEAB457CA3
+:10FD40005DBD836D97D0DF9360FA71071BD7CDCC73
+:10FD50001C7F18F942F00FE367D42B459A22F6175F
+:10FD6000272767D529BBFE19BAD10E7F459B431FB4
+:10FD70009D207F7F56F2DB1FFE364034817ABC3FE8
+:10FD8000FC8DD114A1FF4E4EFE872CB3E3A77CB1AE
+:10FD9000C721277F5FFCB5AA20F8A2A91EF112DABD
+:10FDA0000C705305DA5DCFEAD9EC0AC92F77CCBACB
+:10FDB0002D60B5F7618CC776FE2EC7A1BC9A2DFFCA
+:10FDC00079E313A847FB2394E03EA46DAD39E62FF9
+:10FDD000E8BDE1A2CA80753DFFBCCF3F43E76F9FFE
+:10FDE00054FB480FBCE5FA6B7916F81DFBB2DEED4B
+:10FDF000135C5EE27E97554FB29F1AB4B7821088AB
+:10FE0000229E8FFBC323219FED0F7D3C3DD5FBB68A
+:10FE10005DB3F8FE26F1725EAA1AF189FA1DCF8D44
+:10FE20005F1E9122BA5FE482DBB17CB88BCAAF0B54
+:10FE300084B7215C5F57E3D76BC508EF9014C55FAB
+:10FE400068697D46C8324F6117C9F9E7B28F56B568
+:10FE50005C5B6F5BEFE0E27AF4634A7EBCAB654DBE
+:10FE6000BDB03B5AB5CF957D9413CE2D1AD99B9F2B
+:10FE70004FFB4885ECFDFCA3D847BFD096AEB0DB66
+:10FE8000470F733A88FA1D2D0FD79F48B9B48F02D8
+:10FE9000418FD8D73BEC971A661FE1795250D82F83
+:10FEA0003529B257FC35296EBFD4487BC6BE7E5D6E
+:10FEB0008B066871C63EEAA37FF393F4DFDFBC7262
+:10FEC000ADEFFEA0B48FDAB87DC4708DF1276A0D56
+:10FED000F77BA88EF57D9CFB7FBB7D945D7EFBC38D
+:10FEE000DF0668E3F6513FF89B990B7FFFE0F6D100
+:10FEF0006E0DA47EFFFFC43ECAC527FFBBEDA30C59
+:10FF00009DFF36768ED3AE9176C4A9B66FA47DC21E
+:10FF1000EC981A0DF51EB3B3D08E39EE6AF7DDCE2C
+:10FF2000E6739DCAB03514E356F87EE6062DB6C1D9
+:10FF30004DFE8DB48E76C666D4E763859E45B90FB7
+:10FF40008AB83D2D0A334660FDF866B7E51C420DC0
+:10FF5000A6F59E739BCF111E989D679FBFC08BC453
+:10FF6000C37E7781DCF79C1DE3F3FA31E101D2DC3B
+:10FF7000DED2D23E4CFF43AC6FB41E1759F1C1F133
+:10FF8000A3468D14EA03D6FE3FDCC536BCF86C7878
+:10FF900061EB101F0F546ECFC9EF3C0D8CD115F4DF
+:10FFA00087B36C07F2EF002C3298BC415BC330D6AC
+:10FFB000FF80D8AA6F60FC5CE8E5696F02D3BF03DD
+:10FFC0003A674FC7B46578EDE17A562F3FAA5F389C
+:10FFD000D5C07515C8AFB8063BA3F3505772D270A1
+:10FFE000718EC3E4F9D995C7853C9B60B7CB5D861C
+:10FFF00026FD4995B9E585FD281F7B7BB7CF251FD9
+:020000022000DC
+:100000006EAB5C937C5E7D62F2399DCB7582FD4365
+:100010007D51E0E827DFB4AF1321B0E459F98782BE
+:100020008F01BEF1998CA7C36D3E03E34FAA5C3AE2
+:10003000C64DE6835E80FC1798A201C659EA45DDED
+:100040000974C1F6479716E14747BBFF42CB7EA232
+:10005000C0C3E5B568C6948A95ACDF6363787CFE5F
+:10006000009DC7813AE77333CA97D7921FBE8DCEE2
+:100070004D938C9F2AF9FE86CE6FD654EDD5ADEB0D
+:10008000D4688FF47338F9832DE175C29E66F851F8
+:10009000AB5C26DA019F963FD44FC81F79D31DE78A
+:1000A0004927492F53DCBB3851FEF8B4E349BAF66F
+:1000B00096AB1B894F8B66CCF5A1DDBF2A32A3CF4F
+:1000C00073D4DE74BD8DE81AA8023395A5FFF33C06
+:1000D0004A26AEC0195F6BD91F39ED75B5B46EE60F
+:1000E000D6BEE856E4B4CB78BFFEE5AAF147545E2D
+:1000F0009A4EEB804FF4B7C6B82D81FAF318DA0C9C
+:100100000C1F6ADBA834EA4FA882E80E5E85E23F46
+:10011000FC8649FB703AEFAECBC0E72977D9C6D34E
+:100120008A02F6F3E79909C50ABF7FB987E0F0E1D3
+:1001300078A8A775D6A182F730B87FAFD7FED16176
+:1001400037AC2EAFCD1A67A0FDADF6AB17D9E13DA8
+:10015000E17641CD78CD6247E56EA7C16B167BAAEB
+:100160000DF9DDC207ABDCB05F61EB70327231C4F8
+:100170000D96C7A23280564CC7231FD6F2757DA7B5
+:1001800042E7C324D206FEC7CF892EF318D49FCBF3
+:1001900017273CA94113A8BE7162E748C707F3F8C7
+:1001A000A422056CF5EFF778A85F0D62749E7EFCC3
+:1001B00077E747A85F937DAACBC0E1ECF7324FFC0D
+:1001C0007E4F31B21D87071B903F621CF70BD0DDBD
+:1001D0001CD6EEF8BA19749F28177C9B1CF2B549FF
+:1001E000C465416C4C3FF3E2727C9C8DD981F5B5BE
+:1001F0005880EE2DB5717B68B0187FC7B219F47DB9
+:10020000C7FABEE57C8BB08FEE42FB88EC1C9DF2FA
+:100210003D708978B33B057CF27B8D97C7671D15D0
+:1002200072BFC36706E85EC013D3025F60F255F980
+:100230009C1AC523CCB2356D057D8D3F70AEDD3F78
+:1002400072B2F11D9D9E5011D9D18EF88E5CED6574
+:100250005CC7A7C5CB9D621F53E35D90A4F393F4E5
+:10026000B9249F95428F542E03B2E3062F8694C182
+:10027000EA1ACBDA47A591AF3FFC18AC7C3218A242
+:100280002E20BD600667D7D1BD094EBF36179D53DE
+:100290000FBECA93C290B661C20E838DFC3E83BC72
+:1002A00077B1C3175DE1457DD74A961F5426ECF719
+:1002B000440683E57E04D32383D0AE637A6990E35A
+:1002C000FBA7A54381F7EF43874D5A9B5FB7B42F38
+:1002D0005320966DFD3BDDCBF9B4ECCAF779FCD722
+:1002E0000D417855CEBF12E9D9568074B86BEEB384
+:1002F00093F0DE49A215A2781765C8727B1C449D55
+:10030000378FDFEB00338DF6F2CAD917773E8A7448
+:100310009D0836FD95456FD479E93E08D71B9BE6CD
+:10032000CEE0E9872AF149D53248E13DA3296D4D58
+:1003300007DD2C5FBE1CE8DCBCBC35A1A03FABF2E6
+:100340000688E23083D181C7F255B32065D2FA0521
+:10035000CF45EA68A9A39F0AE4135C775AECF773C8
+:1003600086DC60E78BAA56FB7D9C52C117A50EBEAA
+:1003700070F65369B44D4378872E73F17B3B33EDB0
+:10038000F76BAAA0FDCDEFE37C0E05A3C8EF556B7C
+:10039000EDE33AFBD720FE75C4CB434B374F3B9D73
+:1003A000D5DFB2AC7E00E265872F964FF7A2F01240
+:1003B00051967D712F7E95F6468EFA19FD99B0C53E
+:1003C000333BD3D5D525D7CC61B5D6841240E327AE
+:1003D000BE4E7ADD2DE4F589C1F3E85ED7AAA25AB4
+:1003E0008A0B3B8879B4A7CA87955AF5BD1BE3767B
+:1003F0000764F22B518F66E1F3E5822F5F077339B3
+:10040000E26194B72982E37ACA4BDE9BCDC663CB07
+:100410009F99CAD26EA137C0E7AB6B7FB5DF6F0A79
+:10042000EAAF894B6C24874527E657B8D21BBF1922
+:10043000C74FD4B36D04EE3F0B219544FA36B5098E
+:100440007F7B4FBD36512F81F73B7BEAC5DBC0BABE
+:10045000DF64F536887AA6AD5EAC57BD3B453DB04E
+:100460008D6BF61AF71E091F58FB8BF6EA6FBBB7A8
+:1004700098C307D6FE8C5EFDED92F0D9EAE9BDEA9D
+:10048000DD27FA03DBB8601FB7A77CA44794C72811
+:10049000FEFDF1E2A9C41F878AA736E07DC46B7E0A
+:1004A000E6163AE2725AAF55C1570745BD96602D20
+:1004B000D90DC966685DCCF696AD787FB81AEFF1B4
+:1004C000CEA17DBEFC2EE9C7BEEBD9BF5F4DF77E46
+:1004D000E577ADD54F71E4EC3BEDC35A3E52851F35
+:1004E0006EC0143CA76C8DB884FFFBB5A459C5E45D
+:1004F000BD4CB3E5D794F3F251ADAF2513789F48C7
+:100500008BD1FD146F041E196ED1233DE37F66F07D
+:10051000F3738C0CFCEF3BE07FDF06BFCCFB07F3F3
+:10052000F2B1BE639313ECD795A84BD97E7998AFFF
+:10053000B885D6F3CFEDFC5C2DA6669D1FCF67E690
+:10054000C7F3727E67FBD429FF58F3D31DF3D31D85
+:10055000F3D36DF31BEF2B9882FC78A2F373D6BB19
+:10056000D91D8BA0DDBAB2F84764FFAF1C0CD4EFE5
+:1005700004DF8BC91BB19CC97607F56794A2BE1F27
+:1005800005E6085F71FFED9EC62072DCA786787CC9
+:100590002A147BC439702C82FECDB7BCBA889FE385
+:1005A000707A7C3ADF37897CA523CF7EF92BAE9B0E
+:1005B000189EC8F7910E3DDFDFBA5651321AD7B5F3
+:1005C000D690A958D7354FCFBA7631AD6B2B23D9FA
+:1005D000D735DC36D3BE48AC357734F3F7043688EC
+:1005E000FBB12BCB6BA9DE06793F253195F49B5CE3
+:1005F000371FFFDABC860AA61FDF7D8EBF1F71C0C2
+:10060000C7FD3FAB9BA19DBF87E0A3F431D66F9C94
+:100610005538C0EC3D4C1F66F61EA6FB9B2394FE8E
+:10062000A8D9A0742F1B17D3FB9BA394EE691E4778
+:10063000E95DC25EDC24FCBD5F2A77D1FAF9BD66B4
+:1006400058AB55A39FD747E93DCDFA5ACD8DF665F6
+:1006500084D23F2B3316FAC85FD199CC67F47AE87D
+:10066000D92ABA373EB15C237F076869357F4CE6EB
+:10067000BBC4EB9F95FA461FA3D339868BD7F3A54E
+:1006800092E1ECF59661BD718646F04030A1868B13
+:10069000B2D6FB16C25157C4E1063D9E0C65EFEF82
+:1006A0003BD85F6D9180AFC84806B3F797C4FECEC4
+:1006B0008A08F822DD8FE765AFD78AFD8D8808F8B4
+:1006C000CA3BEAF3B28F7B0BD62B2D6CA37B3BE7A7
+:1006D0002E06E26F6FB9B1957C15A2DEB6C14DE072
+:1006E000627C5B3AA0AD09EB7DB12906952CAD2C5F
+:1006F00089818BF1BFB78895337822A29F097379DE
+:10070000F9362C0F59CA45FBF10B5839CB5796DAFD
+:10071000CBE578DE3690FA24CD8C50F0AE859EFB8A
+:10072000D5982F71F1FC1EDFBF4C41B92F11E74E58
+:100730001D22EF6DB1B72F09F07C1ACBD938256196
+:10074000DEBE53D42F2DE4F3F65FEAA338E17BBE7F
+:10075000FDCDB239C333F33DED3BCBBF30C732BF24
+:100760007BBE731395CBF99CD6BC96CA73C96B64D8
+:10077000960B4C8BDE2A691B4EF6A4B40F479D7670
+:10078000717A36A38B3BC6E1EA6EAD6C5951457068
+:1007900025E85C55C0B5E55A3B5C83BF69876BCBE8
+:1007A00037ED700DBEAE6FB80EF8B85ECB051F1BEF
+:1007B000DFB48E9FBAD13EBEB1C23E7E6A857D7CDB
+:1007C00023F9A9C74F5BE972F7B7ECE30FF937FBE1
+:1007D000F877FF9B7DFC21D77FBAF1FF56F6B8E989
+:1007E0008B7FE413F6AE6AB53B9B1236BB93D57391
+:1007F000F985BDAB5AEDD878C266C7B27A5E51CFE3
+:10080000B4D58BF5AA17F40B7BDC36AED96BDC02C2
+:10081000512FEDB2F617EDD55F8984CF65EDCFE8A6
+:10082000D5DF20D19F69ABA7F7AA6788FEC0362E17
+:10083000D8C70511FF759D88FF2AF070795D1EE706
+:10084000FBEC52882BB8DFD707C0A843B83E0FE5B2
+:10085000EF21154C5D7E1ADA27CAD4E5A7E3FAD753
+:100860005A00B67DDB343FDFAF8DF3AB348E9E078D
+:100870004D580EBE44D98596FBAE5B45BD9EF260D9
+:10088000A2ECAB96F22F8BF6ADE2BEE0F96B3A5AD2
+:1008900050CFE88358FD2CFC375DF627CAA128DA33
+:1008A0006132B8375E3663EC4D601DD7CDE13A4D0D
+:1008B0008C5B9E1DAED60A3E6E4A8CBBD52FED8D4D
+:1008C0004419E151E7A9FC7E7BE89BCA1F197E60B1
+:1008D000BBCFF61E5081A7E9DE0A064772B00BF0C7
+:1008E0007EC2EAF2BEFD392DCD76BFA7A6C7E81EAF
+:1008F000F9C0057AAD0AB9DBDDD9E06AC876EE3019
+:100900005FCCA765417D5B15C277C8EEBF650C0E55
+:10091000D67BC89779E2F391CF7AF96F5B7CB67D8D
+:100920007E4149DFF7BEE4FDA89E79B08EB2D1EDDD
+:1009300056BF38E77A8EF72FEF9B1514BA68DF7928
+:100940006C383F2F80441958EDB18281F53EEBF8A9
+:100950006B1CE3F9618689F6272E53282F9E2A48BF
+:10096000E1FDBA40519B5E81EB42A483CE0141DCA4
+:100970007393FDB64466D07EFC98B8FFAA45DA268C
+:10098000B9487E047CBAD055629C811B354833BD82
+:1009900076C81DBFD55F6CA59BA920FE8EBB53E416
+:1009A0000F4A5630FA2BBDE7BFC9CFEF8FDD69CCB8
+:1009B000F8554516FADEED376CF70D077EE081F449
+:1009C000E8DCF533F5385C3D7C1B61FC3A82F40AC7
+:1009D000F1ED368FB9CD9F2DCE42EA0771FE3D670E
+:1009E0001C881FE392DFB2795C75D80D284FF29E08
+:1009F0008D3C17BA4AF8C7E6083FEC5C8885B1F031
+:100A00006D70D1FDB1B7E1D9F0680BFD1FF3F3F3C1
+:100A10000526E0E4FF92E7BD57B6B96DFEB0F91BBD
+:100A2000EDF97930A304F5D6BCF56E48317C5EE56E
+:100A3000F097DD27E63B1F9A56A11DB0D2CDFDF2FF
+:100A40007374D006B0A565C98FB7D4CD66F92705F4
+:100A5000DEDF627C6358E46D6130E5C1B89B57F717
+:100A60008DBE780260FBD4AA81A86F0B20EB7B704F
+:100A700057B4DAE1EB0F7E27BC002B08DE5C706810
+:100A80003B95ACFEAD5FFBEDE789B9E23B64BCC5CD
+:100A900031E423AB1FE6F779A924F94779DC457FD8
+:100AA000EDFFDA4FFB25BE4E0FCA4FA3D6D4A0B838
+:100AB00032E7525E77DC1CC4E6E9DE3F293D086C74
+:100AC000F55AFBAED73D15485F32C358CDD45B0A0B
+:100AD000AC1ECAE5810B13B67A55ACDED0DCF5BA94
+:100AE000845EFDE9EEEF79701FF7F60F5EB900E561
+:100AF00072D1232AF8D8B85DBB4390A67D4CCA8337
+:100B0000FBB485FBD4ACE7B81429C0F0B0E8FE1004
+:100B1000AD970BF77A53D359FB853F7A7524303C58
+:100B200074ADE87E6A10AEBB3F50F8796AA27324B8
+:100B3000AE6B0B35F8D75896FE2201CE87477E92D2
+:100B400047F78E959D072FA77EDB2F717B2DFA220D
+:100B50003FE0A679B17ADC1FB74B495567D127F240
+:100B6000FCEBC82E85C3B7DF9DF2237C3BB77AE24E
+:100B70000C8EC69DEF105F4DBE7F4F18F1D0B85F51
+:100B8000B59DE736EE54D3DE9194BEE2A57BA9660F
+:100B900050A9437C72FDB874DF12F29F2F6DBFF92C
+:100BA0001D358CEDEDFCCDF0124D235E9F57A3D388
+:100BB00031FFE0BD6183A1EAAD8E1D61C42BEB77EF
+:100BC000B6271FCF7FED7E6FECFF83C2DEFD31CBFA
+:100BD000DD83FCD5D8BE868FB7EF9F5F47FDD2E897
+:100BE00090A3B7F097B2DEE72E66C071EEB273C085
+:100BF00009D9978BF61CBB3BC1C63DB2F74F77278F
+:100C000018FC8BFFDF7B775F8F76D0637E1DF5400E
+:100C1000E30FFE330C9675F3D2005FC7BA76DDFBA7
+:100C2000FD3B997C74BDE8A5F5A3EBD1D787E03BEC
+:100C3000295D0FFCA5C460F5973D7A1EF901963D2C
+:100C400034B9B4AFF513F935E5B5C29522BA1AFB3C
+:100C50001534CE98A12D52077D9ED8A7829FC1F949
+:100C6000F60B5EBA1FD5C8BE2DAF457A2D21BD8CBF
+:100C7000F91B189E97EE5EFD8E3A321BBE13835C05
+:100C800078D90098184690DE5FFDCA17C760EAA6BB
+:100C9000F39546E826BDEA6CD7F81CA3EB59B9E9F1
+:100CA000780C3EF4E0E15FE3EE357CDC7646C7701D
+:100CB0006F3ABE8DBF8CEF4DC76F39E8780C16DFE9
+:100CC000732716EE1B90F53C589E9F2D79E86B7D9F
+:100CD000DA5B522FF487E7050A87EBBC80B92680E0
+:100CE000F2BAF787DFBFB388D3793A434CD79E6314
+:100CF0004380F1C91BEEEECB513F763FEAD571BD83
+:100D00005FF8E8F3246F5D0F3DE331C84E87A0C262
+:100D1000EC8D2EE8F9E940FB63293FAB82C6EDA1DB
+:100D2000B4379CA1D7D2D4850D4698BEBF42DF53BD
+:100D30005C0E96A60E5EA464A1DFC100BFC70DA91C
+:100D400062C2CB92EDBFF540D04E57651CD2F395F1
+:100D5000A9F83D173DE5FC759CFFD916BA6EE7F280
+:100D60009B4B4EBBB67A358C6770D2B94BBC9BD2CD
+:100D700098529ECF4677B90E9EECB9EA01A77C8BBC
+:100D800079F727DFFDCFE7E4F0F5C38061E31B8946
+:100D9000B7231F66D7FBCF0B7DB1149A1A060EED51
+:100DA000BD0E6A6CE339A82203EF118C7364FC76E4
+:100DB000E4076A2AC1BEAF6A7F82F4B7534F2CCDD5
+:100DC0006167BF21C7DB7F7024EAB3238FFF84F8FC
+:100DD00071E9EE573CE8AF796AE7839ECEE119FEF0
+:100DE000C775C1FA7EC691FB0E8E24FD8DFD67A1ED
+:100DF000CF31D17FE3017BFF8DBBDFB1F5BF28D1C0
+:100E0000EE21FF6A3FE3BCA59997E07CDFEA70031F
+:100E1000BE97F456BBDA90CD0E7A29E0B6C553AD35
+:100E20000AD5BD80FE49B5D063A0FE6BB9D17C3E2A
+:100E300081EBE5336EFE8EA566BE80E7D7C9028FD3
+:100E400081FBDE96D0C56058F4789B039F7A913E73
+:100E500009F703FA94D818EBFE4BC25F60BA6CF046
+:100E60002F0B35941A41BE8F33F07D0A2D4AFE694F
+:100E7000353CB581EED5EB2EDD9F75DDE6FDB98302
+:100E800031DA77B975171816FE1A35F9E233D1053C
+:100E9000A78161DB0FAC9BC2CF83E5FCD70D86CD6C
+:100EA000C0F4F03AA5FB30BE439498C6E30BA57D91
+:100EB0000762DF1FC67D7F456F7B0F4CD3407D44AB
+:100EC000EAC8E0E39B96FBCD99F85D305C14C71C43
+:100ED000A54D8006718A13F26194C550DC77B55335
+:100EE0001A64EA0DD373F3B85EF24237E56F6BF81C
+:100EF000039D7394E6C5C6E41563BE50E1F348D381
+:100F00003E4F5EDF77E59597F5A50F608A76C4EAD8
+:100F10004FF2C266DACFA03BF3E30119BCC8383BFD
+:100F2000D9EF3AFF447A1F03E73908DF6BC3C78D57
+:100F30004AF8F9019FB749F96299778C8335F53AF8
+:100F4000B1049368C615F750BCA7D7467E9381D0ED
+:100F50004E693974505AE8D3158DE07B99FC5D2EAB
+:100F6000F8037C9CE780EF04EC78A7FD7D9D6ABECA
+:100F70001867744C8A7DCEFA027B1C523C8FEF13AB
+:100F800096E5B964DC73DCBA6F4BC262C281BF887C
+:100F90003F4B26DB7D372FBE20CFB29F55831D3CB4
+:100FA000AECCB15F3E4FBD81CE455647FA8EE75A73
+:100FB00029E2C27395B715FB666F05829FFBC114CA
+:100FC0001F8FEF36C1D0ADFC88B13D75D67849D3BF
+:100FD000F68E8E1BF950453C2728F5A35CB1340FE3
+:100FE000F98AD1E156C18721E8149D7493FF639B70
+:100FF00027BE0AE71BA96A52F8F7B8C2FD65A68AA0
+:10100000F32D11FDBBF21697C5FB9827CC647C62CB
+:10101000899B592FE8A269A0056A119ECD82FE4ED8
+:10102000FEB4C7BF4ABB2E28725E1187F7E49867EB
+:10103000E97D31AD2848F12FC1312DDF708DC4F924
+:1010400037E9A8578332BE25CAE315E5BEDAF9EEC3
+:101050008BD71117EB16FBF75E71E2623DBE153FB1
+:1010600064B19B9DEBF17D7939DE131A973D1E51DA
+:10107000DA699F94FFE5FE73B1AFE3290242372995
+:101080009E53137E8B4917E9E46F3FBA5BE1EF1182
+:101090003AF8E9E8DEFC91A82F519EF15DF33CF1AE
+:1010A0005DD97DF020DA572D61300B0A49FF192AEE
+:1010B000C3FF2A65944F61E9927DEF3CFD08FAF188
+:1010C0000FA880EFB91D0DCA7350B3008996076B46
+:1010D0006D74FEA4F3EA7D8EC9E5EF6A5DCA5F9088
+:1010E000DABDBB5BA17B622A9C7907BE73D578D839
+:1010F0000D2956FE2EF07EDFDDCCED86F93F7BB06C
+:101100008E49026C14F0E0FA655D67063404C0B0E5
+:10111000F04944AE0B09B303DF7F9E2BF0531C2B29
+:10112000B4D593F3FBD39C86C3E4FF89CF23FB158F
+:10113000DF11B4F60FC23F62B07FC8974E3C1C77F8
+:10114000C53D40EB4A2C3F4D7610DB4FE3FE23A517
+:1011500044116EA73F65E97E85D6B3ABD87A86EF9A
+:101160004B5F9572EC471DEF224BFC3BF9D61D14EB
+:101170007C1B84600E3C47D3FC7C96E4EEEA9FF136
+:10118000B8B4ABF728F48E93DA797A3E10DE55F2D4
+:101190004BBD0E4DB7B31526C3DF0EFC792376BCCD
+:1011A000FB0D3BDEF36AECF80D45ED7874E2397F18
+:1011B0005CA5ADFE2275B187984FE0BB86FD437CF0
+:1011C000333D49F358CAE691367AE373C18175AB72
+:1011D000D05FD22F1E1DF81BE1C0DF313870909711
+:1011E00042CC5742A24FF32ED3D224574E39947893
+:1011F0002AD73B26D1B76888FCD411D1893297B75A
+:101200001BE86BE742551B253994F1C9793DEBEAA0
+:10121000ABF0314BAFB9F0D02B7320B7DCB537FB57
+:10122000A2739950DFD70CD1B9D5785EAE53BA19F5
+:10123000EB9FD5E77A4BE3B921AAD37A22CE4D8E24
+:101240000EE7EF5AB5A7DF2F41FBEFD6DAEE0BD052
+:10125000EE6FBC92C75B7E2FC4D7DF1F8BF4FC9070
+:1012600087F4DD4D311798E82F38A0A614F443E930
+:10127000E6CFCE45BBED80DBA0F54FEF7EFA5FA851
+:101280007CB48EE7CC65AEB651382EAB4FFEFEA3D4
+:10129000075E0D5F61B18FBAF67FF70BB83E6D72D6
+:1012A000C1826CFB80F9413E7E57CD1F4A902D973D
+:1012B000F8BA695FBEBAD3EE67F3ECE37EB8A5FB7C
+:1012C0002F247BF4D03CFE0EE74347F87DD4A9EAF7
+:1012D000AC7F1AC1F2E3FF53E37A15CCE9B34BA814
+:1012E0000AD133E9677866785C8FF19B28177F74A1
+:1012F000A5F0EF1C8CFF227FE769FC8B7812C68A71
+:101300009AF8BBF18F84A71EC674CA0185FC478D6D
+:1013100047F8FA36B6C3EE273A7B0AD30BACFFBACE
+:1013200003DCBF55D7C9CF07CE7EC15E6F7CA73D1A
+:101330003FA11FFE5D1914FBC830949C4C7C6EDAF3
+:101340006DAE0D72BB8AEE9345B5ECFBAF57437C97
+:101350007FC4F041F33FDA0DD1156C1E47E70E9CB8
+:1013600084F7938EBECFCF1B8E7EA83664DB5F6D75
+:101370000D727ED9E4E1E7C79BE6055337B2793CAD
+:101380003E6FE169B8AFFAF3B7E2A7E97DD9254C22
+:1013900045B8684D34F3611CCA470BBFE7066D655D
+:1013A000D9DE51967221E544CA47D9BC403C9B5FC7
+:1013B000B45ACCAF7E5E0DC5E3763DA6D01953D7A7
+:1013C0000A06571F784CC08A41084FE3FEF7C84F02
+:1013D000E13B90DDDF7D3018E67CBB2271E30486C3
+:1013E000AF6F32E14EA03C78DA2AB2F59F80F5E487
+:1013F000BFDA19E4FCDCE5E3FB70D0DACAF0BD88A3
+:10140000AEFD93A7AD6270DEC9E40FD7EF4DEE28B5
+:10141000C19D5802F4EE1F887B85E517C0D69B2C32
+:10142000FBB59F07273D1F64F37C3EC8E39306C4CA
+:10143000A30AC21DFDE87818FB3FFA8197E83750F0
+:10144000F88B64BB7783DC0E5F1D329F217E595081
+:10145000444A311A0F47E78E06386B3FC3779638F8
+:1014600033691715C6990E1C83EF58BAF87918DB43
+:10147000A7E1FEA311E44F828C54297F78D90DEFA8
+:101480008949BDAB1C50D221A63FC7F88269F4CB75
+:10149000142E70E1DB3BCC1EF5F1FE3AEC762B6AA4
+:1014A00060D4BFA80378D03EDF1F497D2CF5784B70
+:1014B00001D77F2DEB34D28F9BB54E3FFAA52B4C35
+:1014C000A35E33E8FD568AB718BC80CB7BDED02DF7
+:1014D000053D76D10480073E52B3FA47CE10FCB4E6
+:1014E0003A14FF0BE27BE4E1EEC7D1BC8AFA61005B
+:1014F000D27BAAB07BC6BFCDF591BC5FD028F625C4
+:101500004E7DB4C92FEC1868FB359EDBFFE48F1AC3
+:10151000DD9FEED13FF3A6D27A0AEAF02790BF26EC
+:10152000FC5C6C0F84FE61BB3DC2CBD9BF88271128
+:101530000EA7BE19074C2F29FDEB1D279D9911DE23
+:1015400093C710BED187999C59DA3BF5D4C0905807
+:1015500067859E3A06134BCF3332FC54BB3CFA846A
+:10156000D7C23F524F65F829457CE81C47015F4FC1
+:101570005E1F8AFAE5172AFA518E4EE27FFFE709CD
+:101580009423468782F753D3901FD61F38DF8F7C72
+:10159000BFF7F0641F8AD5D5117EDF4C3B7851022E
+:1015A00004FB58CF95DDE0338235880F17E141D534
+:1015B00059DE32FEBB6D8AB86F69E45F94E55D6CFD
+:1015C000995E1DE1F7C9F61EAECCE7FBD134D1BD63
+:1015D00087EF85FF42CA85E477277F4B7948B2566B
+:1015E0002E8B1DA12AED62FF68F72324851D91949F
+:1015F000EFCE24CAC83E5C26ECC36470D8CD13D9A4
+:10160000AF2DE97A1DCF3D96852A29BE7A5931C77B
+:101610009F131F326DFC80D98B9638F846AD9BFC2A
+:10162000638D1F786CDF257E73E145E2F71CC4AF44
+:10163000F2C9F17B4EC820FE70E2F9D3CEBFFCEABE
+:101640007159EFF1FDA3CC7F02C41FE9247F2CBFA9
+:101650004F22F94DEA8FBA6B5A937946465FC8FB21
+:101660002052EF48FD72F6E2B627F2B2E80FA7DE8D
+:1016700088BAF52BD632FC459F0CD23B1D4E3DF26D
+:101680003EFE52467EB7BB434C2E1F78EA2D17FA1A
+:101690004D1E7A98CD9D95470F4EE17EC18E133B2E
+:1016A000EF9276ABB4579DF5A4BD2AD71D79DED451
+:1016B000118AEF09317C29FB993C313C2475BE4FDE
+:1016C000FE7930DE8E70E5319803180B5893AEE04A
+:1016D000FB59BBBCE692CF3C87FCB5A7355AFF123D
+:1016E0006CFDAB567AC321C79F1F12EF0930AE4382
+:1016F000BBA6BC0EF8604BF97B01E523218EEB33D2
+:101700005E2BC5793E2DD6995F85F8FA2CD39F07BD
+:10171000633F45F8DD1A24BCB59F1C6EE95FEC08F9
+:10172000994F229E7C0D26CD63900E51B4F7076928
+:10173000ED4A94C151B8D8507A9C3D725D67FD0D59
+:101740009A6E4C42391A84770AB03EDA4759E8F368
+:101750004A88FBC197F83A9F4213BE717A5343B847
+:101760008FF3F5CC3B0851E1E7B2C7811C7DF4F95A
+:10177000C178FEF9BB6FBF17C273ADFFD2BA430881
+:10178000E71B37FC3A84F7217E7703DF7F5CEEB0FE
+:10179000733E10F8BC241C3B8AF3FDD7E68FEA6C3D
+:1017A000EFAF2CE7E73357A554DC94F6F0FBA29D8E
+:1017B00079E4DB93F925ED036C79C9A74BBC3C6E4A
+:1017C000CB39FFB3C2FC1CFDAADD5B3D830C1C3F83
+:1017D000AE84D9F86F083BEE8D7D21F27F4878E624
+:1017E000EC1EE5413CFCD701AF38F7EF7073FC9B72
+:1017F000D3F17C2E2E48E184F3A9C7F2A8BF2B3782
+:10180000A86477CC66632D67FC1D3F7015EDC39D02
+:10181000F3B8F277C6D45246BF2BD72864AF62FD27
+:101820001B183FC497AFA6733CE73C67271CF12306
+:10183000C2AE70C699CC3FC0CFDFE78271F3C48AD5
+:101840002C712707A6D1B9DBFC7EF63D5561B1EFBF
+:10185000A983B3316EFE180CFFF7E146FFFB9E37FC
+:101860009A8182C8DE6AF6517AA459A7F428EA4F11
+:101870003C3FDF7FF029E233ADA30EE57EEFE15779
+:10188000F32E35327AFC4B5BDF7BE22E961F0DDCAC
+:10189000CF23FDEDB304DECF15FA7CBEB017467F33
+:1018A000D0B73E9F85F818D91B5EA9C767E1DF2135
+:1018B000B4E041EA75273EDE3D3C340FF9E3FCB06D
+:1018C000F3BCF9D3E12557BB256AF678462947478B
+:1018D000439CAFE76EBF70D540367EF2D1D7877498
+:1018E000723DF11CEA09C9A7004D1E9463273F4AC7
+:1018F0003EE9E1BB03B7109E247F30B98A8873CEDE
+:1019000008EE0F9DFCD75F7C5397BB7308EA052751
+:101910009F7539EE43CBF4EB61EE7F9F6B9853716B
+:10192000BFCA969B55FC3C90EBA337B4B6A7AE4715
+:1019300079DDCEE565C98FF7FC08F5D0C2FB3784A9
+:10194000510FBDA9B595E0788B77AC0CE3B9FA1BC4
+:101950005A228CEDDF4CA959E31FEF0F2BF2EF75E4
+:10196000DAE224A0357101CAF19F77B8753C076BA4
+:10197000DCE9E5E7EEFB38DE589E9FB7EFCB1E278C
+:10198000B1F0DE0D25068FA7B5C74B6C7793FF022C
+:10199000FD6B384CAEF3E29EF3E7F6BECFD31BF7F8
+:1019A00089389B7DD3B2C64BC8B804271FDFE3E05C
+:1019B0005F861FF2FB25185CE46E17E7E4C95D77CC
+:1019C0008C7C85C17764FBCFC3CA70AB3F9E9FC739
+:1019D000BFDB7EC53D3E576EFEED12FC9EB1275229
+:1019E00059E32716BBD361DC572DDEEAA67DE0E282
+:1019F0003D2AE03B78F0A297D6F3457B9EFCCD399B
+:101A00000CBE450FB88BA6F369509C84A4574F1C9D
+:101A10008BA0CFC2079FE4E7CB86886711745AF486
+:101A2000C0410FC6E538F139B9FDA0A7D311074170
+:101A3000F46A7F652ADD27DC75DC83EBEC9B8F295C
+:101A4000F4F7399DED176C7D328CFA02F144710088
+:101A5000826EB9E396D2173C3C86EA91DFAE3F3AFC
+:101A600036A32C8E257EBFEF6106C78297BC143F3C
+:101A7000B5E0BE6B28CEE875AD89F3FD969525B827
+:101A8000FE2E70274A744AF9F705775F4BFC38FF42
+:101A9000996B4BC47DA432EEEF4994E13CAFDCFC82
+:101AA000359AE73C88133F2ED8A2C6D0CF724C831C
+:101AB0008607B2C8CD17F2B9DCBCBECD8B8FE8C0AB
+:101AC000EBC2CF997856157F3FD2795EC5DF8B394F
+:101AD00026F6DF1F89F5187075B3ECC71AB7AFEE9D
+:101AE000403ABD35D82CD5299E404B08BCD1BBEB24
+:101AF000EA33E7950AFD46EFDC483B68327EC7FAD9
+:101B00001D6E7AEFC6D2CEF65ECD32313E833BA05B
+:101B10009CC5D292EC7ED099F9522F88F81BC967E8
+:101B2000B9F4C0761ECFF2FE735CCF605C0E957781
+:101B3000B8D3A5B6781CAFEDDE7526CEC42DE4DC97
+:101B40005ECEE0A478991EFC3EA6A4F0FD63C92FEA
+:101B5000F3D67BEDF1793DFCE37CAFC71E3F33DF6D
+:101B60006197C9B4D7FA9FEF38AFDB7C62F1338B52
+:101B7000DD298A7F5AFCA297F6278BF7B8638897EE
+:101B80003FED7EE2379732BEFF53BB9463BBDE75F9
+:101B9000CAF182BD63219B1CFF291885AC72CCBEA3
+:101BA0006795E360E65CC38053AF77E7E7D0BB1788
+:101BB00038F0C9EC867C8C237EEB078B4E237F8527
+:101BC00003BF52DF3AF5E86B6183F0DC3BDE8FAF99
+:101BD000FB99784C8E47C99F0B7FB884C6E9E163B7
+:101BE000C9A7928F73C48D39F1E92C2F44DFD9D85E
+:101BF000DE7E91443DD4E0DF674A7A80BFF3E60A97
+:101C000044917FFB3BEF7C36BF42BEFB7616DF176D
+:101C1000F2F3CE6850C7BF5401EE2243CD76CE1EFC
+:101C20009DECCA6AFF27F2F9B9463EFA2318DE1E78
+:101C3000CE37F8BD0735261C79ED748F81CE56114D
+:101C4000CE8230C9995BC4A9B09EE93E7A34CFF503
+:101C50009EC1FAD892FFD4F91AA36F74B4EB9AA17B
+:101C60002CFF50FE4BE76BE8AF9DE07AB092E57F2A
+:101C70009CFF5B9E3FCB35DACD587527BC7CFE14AC
+:101C8000567FA998F752E92769196BF39368AE5705
+:101C90006EC7F31CED61372459FE6626F7BEDACC19
+:101CA00039739E17127E96CFF3B094E55755FC7AA0
+:101CB000156E229F0EC4EFCA277CD51B88E723BA76
+:101CC0008FE27796FDE43C8A237D389FC7BD9FF95C
+:101CD000E004FAFB8EA7108EDDF9C5B9E16871F357
+:101CE0007E8EEC3D7332E2F9CCD3D0A796A147ADFE
+:101CF00066D0773F437B82DBFD11BCDF922CF05036
+:101D00003F0FE74BFA9D582AE35ED43CCE176ABEDC
+:101D1000ABE901961E14FCF0B8C00BFEE0BEFBE878
+:101D2000A3A5DBF8BB56DD4390DEAAFAEEEFD1DEC9
+:101D3000ECBE2C8FFE7EC84B018EB797021C6F97AE
+:101D4000E4AF759FC1BED7FA865C834CFF92B2FBAD
+:101D50005A4CB7EBF15F723C401AFBBDF47295F739
+:101D60001B6C0AE17B718AC9ED708531D32C868F9B
+:101D7000A4098667288AB03DFE43556BBBD3347EE9
+:101D8000C8363E94B37593C9F925E339BD186E6919
+:101D90001D7D7E1CCF4BF866A62A939D06C1F37B62
+:101DA000E48F51DED460DC4F5DCACC2AC8F25E7885
+:101DB00057809F6F7661FB9199F881C6FF76D17E3F
+:101DC000B611E7C0F20F1E01F1770AF9BB3BD2EF63
+:101DD00031FE975793FF7BCCFE453CCE44F8BBE4E5
+:101DE000797EDD217E3EE7F46F4D80B5A44FC73B81
+:101DF000F4E884FDFF44FAB5BFF3B9BF48BD3A101B
+:101E0000069EE4F91CE896F3B9FF01DBE0C6DF00AB
+:101E1000800000001F8B080000000000000BB55A76
+:101E20007B7054559AFF6EDF7E25DDE9F48B100838
+:101E3000869B0448421E36498010706CDE4C8C1222
+:101E400060406418695021E6D56CD6416A748B0EE7
+:101E500041459DB2326A29556BCD5E18DC45496615
+:101E60001B4934BA9D4C0710120437082830AE665F
+:101E7000DC1D44973C645670D42AF6FBCE39977E1D
+:101E80002428F3C790A24E9F7BCF3DF73BBFEFF7CF
+:101E9000BDCEB91E3D7883F900D7E9DF9D91B62A02
+:101EA0005902980EF44F0729000D66FCA5005C3915
+:101EB00091990C385EAF07909D004645865267E4C5
+:101EC000B9B66D38CE14E9BF93ACB0790ACED81F3D
+:101ED000001BB5B00E0AA3E6B5F37917CA568012F7
+:101EE0009CFF12A8A60C8069FD392FCFC1BEA1C7E7
+:101EF000002ABD979EA0FBE7746A00459BD1FBBBFF
+:101F0000E2305EDA91602B84DBF195A93A50CC6C1B
+:101F10005EB88EFF1394445072227D4B8E33A62FF1
+:101F200027DAF64032FE0878FB52518E627E0B9221
+:101F30003CE363E679C7B6A487E42EB66FAC20B95C
+:101F4000934B3363E68113FACFFAB19F837FD73384
+:101F500069A995C96194BF082ABD12CAEBF9183C5A
+:101F600061947FC6193E4E7BCE130EC83EC4B1F4B9
+:101F7000E3D8EB6510D5C779B67EFC95E348943C71
+:101F8000A5F624F7C53CFC311EC65F9747C5D113A3
+:101F9000269CCEC81E540334F4E22037B65F800A74
+:101FA00088DB34284C0686AB0C2AF6DF04DF0B7383
+:101FB000B0BDB66DD8716472044F8737164FD79293
+:101FC000583CC754C6E23976752C6EE37CB138A50F
+:101FD000554D8DB97FDBE6A298FEC4AD6531E33384
+:101FE00002F362FA593BCB63C64F6E5E1ED3CFDE5F
+:101FF000B526667CAEBA21E67EDEBEEA5BD27F41C4
+:10200000B021665CBCFE6FEFF855CCBC65F25A1986
+:1020100032233C08E01FF1A088544CFA473D84610C
+:10202000A4FE67BA03C4F8BF59FF5B49FF9628FDB9
+:10203000CB6B937DD691F6ABB59A5EFF89D63A9D70
+:10204000F48A73A070D748CF786DC860DD2961EB42
+:1020500040EEACC5EB5BCDFCFAA3029F6B09E92A0D
+:10206000ADDF113AF657095B540BB3C3C02716B561
+:102070000979F3A8AC3412AF5E942B254079D25085
+:1020800075BA2CE4910EAAC8AF3CA7D3ADAB8C9225
+:10209000EF793B0E1E43AD8EB5FF6C445BC5F7A6D2
+:1020A0005920602E62CFD1DAE89F1770DD36170312
+:1020B00005FF55EC5C3001EF3BFA731407E02DECA3
+:1020C000DF06702191CB7B2191CBB9C6A434F59367
+:1020D000FF90D5C924CF5EBBEF5FECF89E0BD2E337
+:1020E000067C3318DC0103D95D9A1902367C5F93B4
+:1020F00001D65562DF016EA901DB6478C54EF68515
+:102100006228D7911487ABF392FBF1FAFB24C23813
+:10211000B2318F0E6600DCA7F9C3AA5CE60FAFE010
+:102120001AFB48A17A2519B0BDF26016BB7EFE7E6F
+:10213000B442B4A7F3468E8786C325E127BFDC6689
+:1021400066EDE56DF618BF59B5FB852405E7399FA7
+:10215000034B8251F8750BFCBAED32D3E7A0FAE7D6
+:10216000148267E8A1EFA690D07EA9EF492B0E79E3
+:102170006AD73F5402EAC1D8B62C803A815F18155D
+:10218000365E9BC71F9A0B84033196E6BBF723D8B4
+:102190004CF2DDFB1DB651EFEBB31BD8737DE27D36
+:1021A000ABB0B1236EAB502F0E6A8FCD5944768100
+:1021B000D7C312F697F68081EC61992FC340F29C49
+:1021C00006CFD97694E78F76FEFE9F41A581E4FA8B
+:1021D000F0FEBA241A77633E6D1E14D681F1E42313
+:1021E00047C090827E6BF80EC9B34761EF33D3F5D9
+:1021F000CAB5694F5895C8FB3E04DFC059D4F77281
+:10220000F0B079B5F9D1F262FCE21B55359FBA32D4
+:10221000C91FEAC04CFEB0D3C4FCE150F5B5D69757
+:10222000F0FEBAB4FEDB8CF8DC85EAEFA6102EF7E0
+:10223000ED924141FDFF39C9F739F147C3E3FC8312
+:102240007F49A2FB6B4CEAAB2FA11DC07E93E755E3
+:10225000A0E7F6B3E7B4715FD9E75EB653FC2C454F
+:10226000A066DDDC3E35FCE7BF9E3B9678A6F1EB31
+:1022700061C1AF86D7B2C7129F1A926EF08BF75F1B
+:10228000CD1A4BFC9A21715EC6CFDB85FC52B27130
+:10229000DDC82B0579D5F5CD3C17F98983279CC579
+:1022A00024A71E7C3A47141F0EBEBF268FEEC339EB
+:1022B000F72DC94BB6194039EF052EE749611FAB21
+:1022C00043AE62D23BDA9DCD81E3D6FCC76B037F80
+:1022D000247C3AF7BFFA188D29B9353C34FF7420B5
+:1022E00091C7231071CE2370C13897A3475187201F
+:1022F000D143F9C2CDFCD601F20BC8AB6B3A747C6A
+:1023000059E4AF2A81FC82053C0AB5E865DE9B8D65
+:102310007A6CEAD6C133D8B59153D3FC4F29F66510
+:102320009DF03FE035A7621C11FE29E737EA921DB8
+:10233000CC7EBCD6F533984B6472951CA9AEA0F741
+:10234000421FFA7194B512FF281ECC86CD87135018
+:10235000CE19BB303FC07133CFF1FB9A5F9F15D6CA
+:10236000AD3726D3B85F7F25DB08A2D83830FB48CD
+:10237000F9E734EF6C887A6E94F830C711971FDC58
+:10238000627C584C0100710FE670FF1E0C27AA8179
+:102390000C366D716501BA26B43DBAFFEF6E1E476B
+:1023A0008CD2608E19FDF05DBFD9B373E71CA4C356
+:1023B000248E0BF59BF4844531E3F18DBCF1C854B8
+:1023C000E60FE17B948AF0B20B99E3E42941BBE389
+:1023D000C1D8139377868F7E6BEBC775B43A95FFA0
+:1023E000247D0D635E437E2141DF6F748CB2BE3766
+:1023F000C9BF22FF9F77E898BCE60EC9ABE2FBCDD0
+:102400008A17245C4382DD3E4D9622E3173A78BE5C
+:102410005B77F442BA11F535A03B61CBC7F96BDBB2
+:10242000DFB0E1F2618BCD57457CAE39FFC10C0ABC
+:102430005D00BBD32B9308A7CC64B2A7023D04F484
+:102440004523E5F0EFC2C520E5EB77B9589BDB21CA
+:10245000B1F5F9C37C9D831D4DCE68BF71E3B93FD3
+:10246000748E27BDED1F03ABC91F17848A37118FE8
+:10247000491603EAE2F56FF2D87CDB1C194C2FF801
+:102480007E3D5D075075CB71D07E033E87F30E7E97
+:1024900023B371DABC051D73653BF2283FDC7C88F1
+:1024A000F2C2849049213D27EC058E4B2881F945E5
+:1024B0007FD762A0FC75C8011E09EFB7260E7F42C8
+:1024C000BC18EE34297B24C2AF199C387FAB91C76E
+:1024D000CF5C348437AC91EBDAFB12422F03F92B3B
+:1024E000E48757A5FBFA66B8C31A8D7B12C35D75E6
+:1024F000705EB526867556F2FBC8C93D4CAE889C09
+:10250000C0DEABC999CBEA8056E3F0C5C7DC4C2EE0
+:102510003BF12117B89C10CA565EA5E7ED5EB68E5A
+:1025200004BBE2094823E5F217625E8C76F7DC769D
+:10253000B861E764F7FEC448DF8C36D19AC9F90D5B
+:1025400081B33B17CC89EA93C32A8D3CDFEE38B7C1
+:1025500073C704561F0564E48305DB2427AD93C7C6
+:102560003F340DEF98228E830771B298F9FD1BE37B
+:1025700091EF56EA5BF9384FB2DD522E31BB01B212
+:102580009B7AE1671E91C217EF44D57E1D3E54A889
+:10259000A02CB5C7DE61BCADD1855E2A20FF98E8CE
+:1025A000FB03F9F7B73ED6810DD7FFE56B096A0546
+:1025B000E291F3F6EE14AF75E47C4F9DDBFE7C1ADE
+:1025C000E9FB6D4941A4312F1C4E27F9EA439F1BBB
+:1025D000BDD82EEEF89391E2D32F9CBE5EB283D28B
+:1025E0008EC6F984DF2C686EB25B995FF4114F835D
+:1025F000A9DC7F5C3933654F6314DE43C2BE60D80B
+:102600003791EC2624ECB38BF21F6CDB451ED6DE33
+:102610007D5F965210792E0087D200E7DC0E47D2FC
+:1026200008E71BF3A9FA25C4A7BC0FCDEBBC517C6E
+:10263000FB42D8FB17E27D01A7EF53C2A1A6FB33F3
+:10264000A30DD7E5FF9F603AC5A720E669F61FF006
+:102650008BFE38BBF1EB878D34DE7F09981F41BDBF
+:10266000EE48463DEDFFB063EA7A2B931F9271DD91
+:10267000EDE74DCC6FB66770FB6B3C7BB590FCD63D
+:10268000D5CE9A8984D7298741E3F9BC44B2A70300
+:10269000C0FC98668FF9648F287A3EF1BC84FAB941
+:1026A0006CBE56635F39B3BF761D90FD21CF19EF25
+:1026B00091E776CA3FF2EDC87BF67C36B3E7D63EAB
+:1026C0000C78D80FA01F9FCCFAF35650BFB56F817E
+:1026D0009DD9B30EA12D22BB0C1F62F304B1A6221B
+:1026E000D54950199DA72E74D898BC9A7F5C21ECCF
+:1026F0003498A3247B703D16598EB183A878C9FB0A
+:10270000229EAE759A9E7E71025993880B222FEB02
+:10271000127930F88A99BFFF4711CB1ADE2D5BDAA8
+:1027200082EB6D382973FF2F787248E4C947B6A54C
+:10273000B23EC50B05F5341D5B2FFAD319DECDF380
+:1027400029FC942E693E4C6D596570BE81E2E2EA27
+:10275000BEC3066ECE79C4BFB6433FCDD313DFCF21
+:102760009B2001456CFB76F893D711872D5D88FF80
+:1027700028710997C3F887119DF1F166BC1992FA87
+:10278000EF99EDC1FACF39EEA7FA04B41F2206E2A1
+:1027900071BB73ECD30114A8C3E92D72227E9FB8DC
+:1027A0007CAC1D3AF56D0AF9F4F6339FD9C8DFB752
+:1027B00019BD79C4B3B64CAC1746E1E744A781F91B
+:1027C000FB12536C9EAEB52B9DBCAE9A12806789EE
+:1027D0003FF56DB25D457D0FB4C95E23E65117BD6F
+:1027E000BE143D427A0902AB66537C17F5EF431CD9
+:1027F000767888F2178C331B5F34C4D4A5B5625F3A
+:10280000231BFA9F4C439CFC7B2556D756C5E523DA
+:10281000B594BF14527DB1DB48EBA9DE1B370FE541
+:10282000318534EE87EBDC954E91C7644116E53176
+:10283000C823564F0F9F953D7B2806EAA1C784FC0D
+:10284000DDAFE338A1DF64F6A8E533896EEF22B28D
+:10285000FB450E9EB7B48ABA75B8555299FDEC4344
+:102860003F8FFDB24BCA6EE0389C499D41EBE1BC05
+:102870002CD3F3F165A10C667FA55EACE771DD1B7F
+:10288000B19E5769DD5A9EA71AD8FA31FCB23C6F47
+:1028900016A84D361CB7699FC4F67D6AF61962F218
+:1028A0003CBFC0A776D7A9A3544ED605E3EE0B7C58
+:1028B000FC71F8BC413F668DC4E9574EB11F900EC4
+:1028C000E9D1F91EF43847AD0B347CB43CFB7F0DE5
+:1028D0003CBFF840CCAF8DDBE5E47EB4DE0B6CFF93
+:1028E000A856955595E783D6F5C89707045F1E103F
+:1028F0007CF1031F57B74F52C314AF7ECDF56EC6A0
+:102900003FC2E5A1E0FA4569CA485E550B3CAA5AA8
+:102910000C2CFF05D86C24FBAC7A256E9CC0A53A24
+:102920000E977A9F14271FCFC7FF56F96A0C7CBFFA
+:10293000A606F91550FE7EF2C6EBEF0D8DE753614A
+:102940006A8CFE96B86E497FF179F281A3532DF41B
+:10295000FC959E4CB60FA1F1267E9E4522CF5EBC13
+:102960008BE7A3031DF32D05544F9DD07B249CA71B
+:10297000F8E4FFD90A108FA24E192A708AA150F1EB
+:10298000B3015CE7C19E492B148C0F4527F52CBE83
+:10299000149F2C52A9AE293A5964C94A62C6E3A2CF
+:1029A0007A01E761F179E8C4A4D3F9E4677B16946E
+:1029B00010EC8D278A2C94471C04BEAF219D2C71EE
+:1029C000F547C59BF79C325BD793A9FFFD1CE5F942
+:1029D0008B0F183C948F2C360CBF3FDB4DEFD77B11
+:1029E0001AB15F7B72C3F604D2FB6B9287D2F1A35C
+:1029F0007D0DEE9F937E4306BB89C9FBCB43743F9D
+:102A0000D0227926E3787FE7C2BC56EC17ED2EF68C
+:102A100010CCDAFB8A1CCA0B15942F8EB3B03A7E09
+:102A2000F16D0616772F8FB7FC8EF2A56AEFEE4593
+:102A3000E48F2FBF73D048FE60A85582545CC8D184
+:102A4000D4C3BF0FE03A2FBF79CA4849F9FCB65347
+:102A5000C6FE1FC827065419C2AC7E6F36521D54DD
+:102A6000B75BEBF71B494F9522BFAADFFB27D6AF19
+:102A7000A63A01DF57FD8AAC2AF8F370E75B46C23D
+:102A8000BBBE4582B11951F7F74AECBEC6FB0DC07B
+:102A900079B041F8A71AB10F5943FB90781D7672AF
+:102AA0007FA3F1FEC17DCB8E52F87EA839D60F3DB3
+:102AB0002C78BE89EA52567FFB8CA4D74DBBE2C668
+:102AC000099E3FFC233C4F76093F950BB9C4F3ABFD
+:102AD00073793CB97A2AD1928FEBBADA2B7B007EDC
+:102AE00090EF2CFE9E10F9C295B08EC5336DDC6060
+:102AF000C75F58BCF19FB862A4FC7651E82BA68F43
+:102B00008A50F702C2FB6EF0D5127E77872C76B220
+:102B1000FF8A7EEE0FCA432695F6C1EF86E00ED2FD
+:102B2000F350D7BFED70126FFE95F30684BFDB2420
+:102B300070DD2470DD840EDF852EB63ABFFB252CB8
+:102B400007A01CB81F2A0F0A3FF44A2CCE1879EEB2
+:102B5000277DD5874CF00CDEBF4BF8A3BB5AB83F9E
+:102B60008A8F93F5621F60685CDE52B6DF8AF52EAD
+:102B7000E571B52DB1F8D78B7D81FAB8389CE9E2C3
+:102B800079C28FD5FFF17A5A10A7A78A61CE9F72BA
+:102B90008A7BB8FE9EF0F67CDAB7D3F08AD7538FE3
+:102BA00092953C5A3DABB5EF8BBC5FEB2F057EFE9B
+:102BB00014B4375BA3EBF8D75D3CFE54CF9203A46B
+:102BC000E71BF5CEA4C3858A2E52EF609DB3D635A0
+:102BD0009DD73DD370EA63136470BB23F5CE53A930
+:102BE0002F541451BED2C2FDC86029CE974CF93C77
+:102BF00030FFE56F31A954A7F8913FACCE21DE60DC
+:102C00005B199216126FB07EA872218ECB68EB18FA
+:102C10007158D6C1F39E650BBE627CEB9DC4D77B19
+:102C200045AF8C1DAD9ED0EA88FA6F789EAA5DAF45
+:102C300047BBA7F1F52189D5C56D87FE9A9E81FE18
+:102C400073A8F35AFA7A6C5F76F13C4ECB53873116
+:102C50004FCD14790AE5CF1BB9CA6013A6C35B91A7
+:102C6000871B459C036907B3937A4A76896FED12F7
+:102C7000DFC7791B2FCC44FFFB4122CB63063FE427
+:102C8000E743F4FCE398470D6E081E71E2F8ABAD24
+:102C9000128B7F1B31C7FD49D1487BAF13BC6C84BD
+:102CA000EDA22EDBC1DAF29C039F3D46FEA8C5AC27
+:102CB000907F1DEC6832B2FD6535EAF9CC91F95090
+:102CC0009DE06FDD8FEC6BBD1EC74B5C07CB6F8744
+:102CD0007A65BB4962F8FD767C344E22FF693B94ED
+:102CE000C0F43C74CAAA529EFFA5E0DF65B1EFDED6
+:102CF000582A335C74B3789BD7F55626E995F4E0EF
+:102D0000A37D94AEB7A67AD93E9FCAF858B34FA612
+:102D1000C3BE88FC410BDB0BD5FA1ABE7E812FCADD
+:102D200035C5E88EC8D5AEEFB77946B11B493AC470
+:102D3000F4A69362EB5CFFDB72A51A654FB89E7533
+:102D4000E4DF42821FA01F4E21BF1C76294CBEC665
+:102D500010D7B3AE93B7F8FE557CDFC6C0DE3FE2B6
+:102D6000FEBC402DDDBF9A6101C6936F0215D4DF12
+:102D70009229333FB5E583EA6C887A3F48BC1EF759
+:102D80001B8653583D7C4AC7E4F39FBA9232C94A26
+:102D90007E70F7027B3EF937EE1F8E665AAA88DFF7
+:102DA000017AEFD8C83CE52E7E9E00B4DE54CA6698
+:102DB0005EE4F38AF56E87E50C87ED8267DD221FFE
+:102DC000C5BAE93CD9637CDD74B37C37AA7E6378ED
+:102DD0005D9DAB9CFE39F2A0A8571FA07AFDE0399B
+:102DE000EE271A3B377D4A75B0FF8209C84F6CE960
+:102DF000DA944D71187CBEDB29BFBBDAF5F0ED6CBF
+:102E0000FF52DACEE40A907CA994379D4DA17CA8AC
+:102E1000AEF36C0A8BEBEDD35FA03C09F3A2BBE8E9
+:102E20003AE62B8C7F45274B18FF0E9E2871659143
+:102E3000E0E0B1D0BC75BDFA4AC2A7AEB7E4BD0AA6
+:102E4000CA5F4ECE637992961715533D4E7952EF75
+:102E5000A4983C69D8C5F3A4A1EE04B6FF2141268D
+:102E6000E70F4C8AE14F6DDBBB2C9FA8ED90BDD1E5
+:102E70003CD29ED3BBF57C7FD42DF81394BC8C1F21
+:102E800007785BDB7190ADAFC61064FA6E6C31F001
+:102E9000FBADBC0568E6FB2CE00C101EEFD125D481
+:102EA00043B9519D40FBEBC733787D11AF8F67DD90
+:102EB000FC1CEBF879DF44E2CBF1B9BE6CFB287166
+:102EC0002300F378DD2D09BCDB0C2CAF8C1FF7B48D
+:102ED0009BEF4FD85C1073DEA8B5BF7473FE941BD4
+:102EE000F93E55FCFDB96E614F289A0E7971BAC250
+:102EF000607F46D413E3D0DFDE23FCED8ABB0D2CCC
+:102F0000EF382DCE99EED1FC6E298FDFDA7EFFB23D
+:102F100057E0092CFFE16BC867E760CBBCB17E6F5F
+:102F2000A5C8AF562C89BB2EF2A9953F924FCD7202
+:102F30008BBA610A4CE17583D542FBA25FF718ECAE
+:102F400032935B9D545930729D9ABF392ACE877A4D
+:102F5000D00F52DB98FB11DBA73ADE7DFEF70EE6C1
+:102F600047132093EF3BB2FDFABA9BECD737DEB0A4
+:102F7000D39FC5F04ED3D300E5F9F923F5B452E061
+:102F80005D67BE6C64E796B079A74E8E9C539A0C31
+:102F90003E6F1AAEC3D031374CE7978DB926962FC6
+:102FA0000D2C9454F2F72867BA29CADF0F8CE3F985
+:102FB000D7965512DB17EECEFD88C5F1BA709F91FA
+:102FC0007835A56DFD13CC7E037086EA254D9F4BA9
+:102FD000CD3C7EDED0A3B65EBAA9D0FA9C01EE97B6
+:102FE000DDACA5F1142FEF11F1716969ACFEB2A14E
+:102FF0006F11ED8FDCEB9558BE7433BD2F5F3DED47
+:103000005DA2DBADEABFD9EDDBEAA6FDA2BE2BAB2C
+:10301000687FF778EEE7E9145FEB6FC2E726C177C8
+:10302000BF859F8BF92DFC3CCC93AD34F5233E2618
+:10303000876FBB9BFC87EE7BDB54A079FA7FDB209C
+:10304000917E80E9E56676F4B498F769B79DFB6FE9
+:10305000373F1FB2529FECD9A04E203F01F9B776FF
+:10306000CED7F8F6B142D2D360776FA1314A9F979D
+:103070001BD01F507CE93C9CA258A3F9A6137CD31B
+:10308000B35692968BB819CBBFCBC43FD2FF81C346
+:10309000F7505D38D0B6C22D295171B5FDB46D72AF
+:1030A000D4BC0321998DC77A6CCACAA468399F60C1
+:1030B000720E04F97C00FD53561444DF6F123CEE8F
+:1030C000673C7E2A67333B77D778AC07CEE3FA8E2E
+:1030D00065C0E2945877D0883FA8CEE832A9744EF4
+:1030E00041FBED8E283B392EEC63261607C4CF59E1
+:1030F000109069DE9938E35AEAEB21AC77D2796017
+:1031000058E6E7DD1380783D43F07AA63EDC2D15C6
+:10311000B271EC5CAA0CFAD8B89FC0306BBD60D716
+:10312000533B0F3CAC2D3587EF2277921F0CB2EF4B
+:1031300092C2297AC745333B2A85D1F41759BF1E5D
+:103140002E6A3CC5C198F4B07DFCF8715F0B7FEF2F
+:10315000A11C8EF43C006C1FEE0EE897E925B3F538
+:10316000B084BE27BB430FE64494F7C0111DB3E7FC
+:10317000AE7E45257FE67189E7BEC0E7B03FD3CB81
+:10318000ED9642107DB7A2AD371E87329C8FF605B3
+:1031900067EAB1F2653886D9FBEE24C171DD73416F
+:1031A000D153FF923B437CEFC6EBB4F9A24ED399C7
+:1031B000030C8F418A8F63F8798E0DE7296B96E0B7
+:1031C0001C9DCF64F1F56AF39761284DA67C5AAC3B
+:1031D00097B6C2CF39F9398F8D9DCF2DB0135E527E
+:1031E000384577DD72EBB80EA50093DBF6C0F0E052
+:1031F000632591F32E4FE8D839FA2E47F27AD97722
+:103200003D1EB3354CF939B2E37274DEAD1BB30128
+:10321000C6E0FA24C5CEF0021F28947F8C8D7CEF87
+:1032200002D75D91EF6908C64B2991F37DEDFB9ABA
+:103230007DEA7245877A59ED367B482F45E6F46280
+:10324000AA07F7DA7D30867D67D332994DA657A756
+:10325000572645F86E016F29E1AD9DEB4B427F3754
+:103260003BB7275B259E5BD0EDD37741CFA2BD98BE
+:103270009DA37D7FC4CFF3D10A15FAEE081E9FAF40
+:10328000D077014F3ACC9E67C8CFD1FA2C91F53553
+:1032900099F9F7044D66FE5D00EC98CEF6CF1E114D
+:1032A000E7114D565D0ED55B4D90E8A1925E93F708
+:1032B0009124CEC747FECBC2CE47E3E5FE3ED19771
+:1032C0004FF86AF23F2A7BCE61EE1383E71C0D4F65
+:1032D0005D04CFD56A6653BFC2F02BA1E7A799D48E
+:1032E000DB685F648D897FBFA4E1860A65A4B60BA5
+:1032F0007D68F8D949DFB40E2FEA5BE34B6604BF63
+:103300006713396E06FA72228B3DABB0F3FC385C62
+:1033100034DEFD3FD45368B1102A000000000000E5
+:1033200000000000000000001F8B080000000000EB
+:10333000000B7BCFCFC0F0A31E81FDD1F8E8389100
+:103340000F534C94118257B3E0D78B0D5B3122D8C9
+:103350009EDC0C0CB29C0C0C7240DC01C49D40FC49
+:103360001288B5B81818B4813801C84E04624B20D1
+:1033700076E086E8A96567606805E25E209ECA4E31
+:10338000BAFDBF2518181A6411FC0B4036AF02E9CC
+:10339000E68CE2A1897F1BA2F245B451F9F6BAC0CE
+:1033A000F46184E08B6A9366FE36A0DEED46B8E5F4
+:1033B00079CC51F9CC96A8FC6E3354BEAA3B840656
+:1033C000009B2185B9B80300000000000000000048
+:1033D0001F8B080000000000000BC57D0B7C54D53E
+:1033E00099F8B977EEDC794F260FC20021B9794000
+:1033F00002267188E1A5A013040B886CC017B4AE37
+:103400000EE111DE44B49AAEB8B99010420861B42E
+:10341000A8C18D3841405468830D4A57AB03524BC5
+:103420006DB71B1505772D0D688358A0298A4CFFB1
+:103430006BEBFF7CDF393773EF6426E0BAFFFDA743
+:10344000BF7A38F79C7BEE39DFF79DEF7DCEC8243D
+:1034500087A4DD44C837F0474BBF891032205A9209
+:103460007255206308F9A195E09FD62FB6ACAB2129
+:10347000246C2124B290904E27ED28555949212DD6
+:10348000EF982E92744292E07D85907AA1EA686E60
+:103490002921EA5091ECA28F3664CC4E0A38138F62
+:1034A000BB978FFB931A2B96ED351E2C5FAEF16206
+:1034B000D951A390703E21AFD4146079B0C687CFA4
+:1034C000FFB5661C96AFD7F8B17CA3662A96E19A41
+:1034D000722C0FD7CCC1F2484D00DF7BBB66319612
+:1034E000476BAAF0F93B35D558FEB646C5E7BFABEA
+:1034F00069C0B2B32688E57B352D581EAB0961BF84
+:103500000F6BF66079A2A61D9FFF47CD412C3FAE01
+:1035100009637937494678DE79E725EB3CBADEFC6A
+:10352000671E7C6F5A1A215B468B3E0057FE339F05
+:103530007A0385D1756FF99B694E7B1CB8DC450415
+:103540001C678B8B60FB96431F11A58890E6D15DAD
+:103550005E95D6A7F1EF8CD875CC3AAF30DA2F76DE
+:103560009C3F12131BC74CDB69BFE1DB587FAD7D6D
+:103570001A7C6774B47D77CB7BD6F94E7D3B7BFF9D
+:10358000F9D6F7AC80BFCD11898411EF2A21B4B4EC
+:103590002B3D2D03289E6D272CC4924DF1AFB49383
+:1035A0002E3A4EF3F827C36229AC9B7653609DEF09
+:1035B0001381C2417511A40705C6181BFDCE582200
+:1035C000E23CF29F39C6BE73C7252CDFF8AB4C082E
+:1035D0007DAFF94E21E4A0E3374FBCE8F503BDA968
+:1035E0002F9880DE905C15F84F97B79C8EBD65E2F2
+:1035F000875E95C269F3DFDE9F331FE86F14F1C168
+:10360000F7361FFA3951A0BDA807E157CBD7BD79CE
+:10361000EEBC2C4F6162BAA49444C47174B94EE2FA
+:103620000FC581EF3F0210287C4C9E10AEC94EFBA7
+:10363000C5C3C33F1219FB6D76957F007051EF34FF
+:10364000FB76D179DFEC0B936E6774DE50FF84D686
+:103650009D5F8689C905F33EEB35D1F53BC6C9D7D9
+:10366000D9E86C9C3D3D27E07DE784457E587BF39F
+:10367000A82EEF22DADF5AD089EB253EE21B46C79F
+:10368000B517A8647E21C0C184788D9DCF7C80F75A
+:1036900000C0D3575EC08946871FDCF1BEB542D754
+:1036A000FF798D3E04465FA4296C9DE58AB63FA351
+:1036B000B5DB18FD10ABB17D5B0C1D938C04ED6682
+:1036C0000A68C49718DA2520DCADB38BFACEBB2983
+:1036D000FC6BDC074E5FD81A88B32EBA4FACC077AC
+:1036E000924A451FC0AB7922DD2F85D1755E69DF17
+:1036F0003570B86C2E9DED82F1AFC4B78ADA4512F1
+:103700002EE03C93FEFFDA83763AF3687D5438C5A9
+:1037100050BFEEE86043FFD19D3986F6B127461AC7
+:10372000DAC7779518EA377C76BDA1FFC49E498633
+:10373000FA4D91E986FE65E47643FD66EB0F0CFDDC
+:10374000A778E61BDABFE75D66689FA63C60A8DF46
+:103750005AF088A1FF6DBE5A43FB3F8CDB64689F23
+:10376000E5FFB1A17EFBD47F31F4BFB3FC3943FB4D
+:10377000DD735E32B4CF0DFCCC50AFB4074E027E89
+:103780007EB0F835C37BFF58F596A1FE012153E3C7
+:10379000E197088CCF500AF2745FC3FB5316E70120
+:1037A0009A033A1EC0E8B4A02D019FE4ED2FEC7CF3
+:1037B000CFBAD0C027CD8C8E07B1F63DA1F7E2BFBE
+:1037C0003F94EF13D2699DEDD2B7B3795DF357CA39
+:1037D0005FA15D52BF157F75797CD85FE3AB94BE66
+:1037E00009B99EC2571DA2AAF83D3A1EE59726B612
+:1037F00064524D189F22E4017CAEC97D9241C226DD
+:103800003A6EAD2BA3AD116042C796D2A05EB8034D
+:10381000EAA2E2275D71E06AF2C8063CC5C29738A9
+:10382000532831F7C76755849F3A851448F07DC106
+:10383000EE5B4BD72B91C060813EBF2C06BC30F9AC
+:10384000874DEAAF02D9D1FE6B27D27F42FF5342A8
+:10385000681DF657108EB545C40F72431D24877638
+:1038600065233C2DC04FB4F7E803A58BCD57FD264B
+:10387000D75067F3BD62FDEB7C635D1BF79F8CF057
+:10388000A47086FA7DBCD267DD3E394AB726E8C708
+:10389000EA8A28906F900F1ADBB5EF5CB6B98B49B6
+:1038A00012C5A395950FDBDD3BA0BC6CCB0C11378B
+:1038B00021C562609240E1A04E62F0514F3A42B59C
+:1038C000385ED5D8F222806F7C7D8190756C7F7CCC
+:1038D0003C4DD4AF2311DE3682DE961FADDB32289D
+:1038E0005DC5E1CB77094CFE511A95605C0B61B464
+:1038F000E53005EE8279CAA4DC2F225E7D04E677EE
+:1039000068D893732A28FE9A26C83EEC1BA40A277F
+:10391000D54FA55EB84EC5BA95D7E7090A8EBF3117
+:10392000F9B03587AE77B34FE47A4110C76BC8FE64
+:10393000CA0B7CDC26058907CABCF8727AA52072FE
+:103940003C3E4AAE461F8EC5CF48FA3AE32F04E10B
+:10395000A7CD6FCBD0B03507E8713CD3879BC7F5B7
+:103960002F57D673B8D6727D78B3323B8938A3EB24
+:103970009612CC6B03D7A309E99903786FC84E1749
+:1039800061DF6E1018DF3994FDB615F84793E7B084
+:1039900015C60B08D96CBD31F06D487E0FF5FA5A8B
+:1039A000977D4E280E3E03821BD7D900388375259C
+:1039B000132EB7552FE0CDAA784A1A95BE7434D984
+:1039C000F525CECB594A140BEDEF4C63EFDB3E16D9
+:1039D000420ABEEF770EA2F37070FAB02B46F9BA26
+:1039E00076E22D2AE8910FE71032109FDE6FC09328
+:1039F000A3343003E8DFF457138E4B06B17949A4A2
+:103A0000EA0FF361FC42C6A73CF47FDFD031AC790A
+:103A1000317CEBD834DCBFB2877D9F982674DE44BE
+:103A2000E72BE58B034D74AD2673A71FF4B18D5DB5
+:103A30006D3E55077F594F07C0873E9E769614C34B
+:103A40007775E3C3FBC3666FC9ED879E4C5D6E124D
+:103A5000BE0EBE7B4FBFF4E1FAB8ED9D233AB8BC71
+:103A600021B8D2BA016863C958E4135778FF724D80
+:103A7000E89D23C370BDE2D5D0797DCC3EDF90CDEB
+:103A8000F5398AEF593A3DEDB2C0F439A296211CBE
+:103A9000258EC70D13490FC895CDD9B2B20EF0517E
+:103AA0002A8781849052E9F7CDF00F809B52DFC9BD
+:103AB0009EFFD0C047D70F99E90B2B89E727A5C5F3
+:103AC000E0F10AEBAF06F8E9FA7703FCAE89C2CF62
+:103AD0004CCA93C240DBC1A948BF6E6D1E13EF52A2
+:103AE000F4F3E885E30D6C7F9AD354124F2FADE5C4
+:103AF000F0BB53F45F047E67927D2702409F39320A
+:103B0000DA27B1FD478A8C0F45E16C95004F76C2EC
+:103B1000FF668410EEF4AFDC9ACEE147FFCC196F5C
+:103B2000FF5500BAA366B3A3189FD74925747F79C0
+:103B300089EAA0F2C12E1109EA59C06C4763FB64FF
+:103B40003905F6F12D3ED477CDFC7B9E36AF5E4F26
+:103B5000CF12195EA3ED21EF9D8676338EB7C1C5D6
+:103B6000F51BCF7306BAE87D3F39BEDC192832FD5C
+:103B7000274BF470FA790EED39F3D0BB1A0E517859
+:103B8000D7E5FB7D15B0400F413868F243931754D9
+:103B90008E64890300FE010278973CE558C6CAE3AB
+:103BA000847C3C460E9B0B6403DF217AFD2607FED6
+:103BB0009BE1C1FD4662E53F2FCBA75FD5BEAA8D35
+:103BC000D95726125F2EDD2E32FD91A869B87E6D81
+:103BD0005F11AE5F68F8A7F2C140AF32CC87321CEC
+:103BE0001B09E1E00E6A6641DD45AAB07E695C49C9
+:103BF00058A0E358A4AE06E0CB96712251B3E3D8A7
+:103C0000555C0E255AC79689F1E5C4CDA29BD9C74C
+:103C1000CE2ADC1784DC837AA1A006C837A81F0649
+:103C2000B9BCF479018F1B6BAAC927743F590FCF18
+:103C3000457BDD9CA7FAC1DE075901FA23C9286537
+:103C4000A5E453F4F4D98B47B216C7333919FEE50E
+:103C500034AA17E7207D2C00FA205623FDF4D24920
+:103C6000461AC80A9887521E775C8E57DE2F211D90
+:103C7000F5D281B62E4586F162E9C35E4A2D0E115A
+:103C8000AB9D309F811C7B0303F5F78BC5809FE0C4
+:103C9000D4E1140F03BBE6A13C737179525F38FB8A
+:103CA00028A874493ECFAC5B14B0F3890070DD08DE
+:103CB000835D0FE3CD5D5B46EBEB61B0C1B4BA6EE3
+:103CC0006699EA646462D44B4545D2F430B15FBD75
+:103CD00046F8C6D2F7FD44EBB7C4C83B42565F9DD9
+:103CE0001E750FFB9E4AFF07FB2B39469E26F98D5A
+:103CF000FCDD15F39D17019608DFFBFF57BEE7219A
+:103D00008F5B154A0A963CD113A2B499443CC96012
+:103D100027D92753FB8DD63D193D2A4CE94A78A96E
+:103D2000E7762AA1FB534FCF6F727EE9ADA8CBAEE9
+:103D3000A7E35E2A75FA805E0752F6989AD2773D1D
+:103D40009BB8DED75B2FDC8174BD9ED211E8C36ABD
+:103D5000A188FEA68D792F7BF472F194C657FAD014
+:103D60000751244D2EE7C03E14FDB6E2EF4E1FE68C
+:103D700018385F2D7D38EE31E2E3DBE2EBC2B7A409
+:103D80008FEFFABDFA44FE07CE9F285E51FF6E50BA
+:103D9000FAB703FAE2F571C4AB9DDA2FF1F8ED172B
+:103DA000BDF8548DF288DBFF51B961B4FBA5AC5B63
+:103DB0004EB4F5030F29564FE6E3DAAA4DCAA7A978
+:103DC0003080C760EF6C541E5741FFBE047A34E860
+:103DD0007BC132F4FF923CE68F850144D0FB157F16
+:103DE00008FD0C209F74724DCE30EAFDA634BB5105
+:103DF0001ECF5105FDFC6DD532CEC30ADF4B437F8C
+:103E00006D08BE6BF290B0CD1DA557F814B3F71F27
+:103E1000B92A3A3069EF091ABD1ADFDB905142E244
+:103E2000E1AFCFF7EE30CE37215F8A7DCF2929DD94
+:103E30003ABD23F17B12E9D6E92F376A711D8EA7AF
+:103E40007A33392850FDAFD67B170928489F28C7F9
+:103E50001AA0A4F2B4DE5BE241F9BC4788B1CF15E9
+:103E6000464F4A0AF617AD4CBFD2EA89E7C3BE1BDC
+:103E70008D1329A81F27EA5F5B33EE0989321B7374
+:103E8000F55B5B256AFFD4ADF5CF29A7FD1B6B8ED3
+:103E90006E958645FB2D3169F639159F6340AFE17C
+:103EA000F44B683F849B48BE01FB8972684527E755
+:103EB0006DA473AB84769FC2F14884DEFD4087DC3D
+:103EC000CAD7692127B01F0C84761CE9C271E1456D
+:103ED000A8AF37FBFDE5144E8D52C8BA1AF8B98D5C
+:103EE000D7155E4FE6750FAF67F33AD98175B34CBE
+:103EF000EBB07FCD210FD6EDBC9ECDEB29BC9ECC87
+:103F0000EB39BC2EECC0FA7A998DB7496A67E3DBCE
+:103F1000795DE1F5145EF7F07A0EAF9397D9F72D3E
+:103F2000ACEE30B7B3F11DBC9ECDEBA9BC9ECCEB83
+:103F3000B9BC2EBC8CF584FCB280C13FCA1F18BC32
+:103F4000357A240057831FAB2BA69DD18B49205C6B
+:103F50000FAB42FDFFD0D0BBBCE06F5C7FAAD20BA1
+:103F6000F4537F9B464F01E49F24E356E463662DA0
+:103F7000EE98B67A0EECFFFA0C19ED49C2FD305AF4
+:103F8000FB86E4C0D46CF0577C6022F1EC2EAD6C63
+:103F9000E57CF769D07BA97EDEC2E3914FF278E43D
+:103FA000568847D23208F1485A36F37864138F475F
+:103FB00036F27864038F47FE04E291F910E79C83A0
+:103FC000E58B108FA4CFF7403C9296BB211E499FF2
+:103FD000EF8478242D77403C923E0F413C9296DB53
+:103FE000793CB23EADE428E81D97AA45D40712CD2E
+:103FF0007F6895917F0E596C8C4B0C0A18E3120365
+:10400000E718E31203CA8D718964BF312E9134CE53
+:10401000189770F98C71094781312E61538C718921
+:104020006B0FCE36D48BDABF6FE87FCD9E0A43FB91
+:1040300088D052437B7ECB6A437D58F09F0CFD7342
+:104040001BD619DA9F32E5207D65AB8D867E59D56A
+:104050008F1BEA95767FB709FD946957E5AF265F18
+:10406000AAE97A7E192B1F4C99C4EF4739C7E4118E
+:10407000FA6081FE8632BF94F5E3EF1D057BDD9289
+:10408000C7E4944589B13B63C6939DBB4FA8F43BFD
+:1040900065EEA3DE2EDD7E245EDD7B60EF488C4F77
+:1040A000363ECAECF1265EF65D473DF66BFA5B7C68
+:1040B000BBDC269962F40866D7343D2A60FFEF3AEC
+:1040C000BED61E3B6EF47B141563F4F66D48F3AF59
+:1040D000923A9DBE60EE4A9E4F50CE33FBD7C4F756
+:1040E0007B5981EF541D85F77A0FF159687DBD73B7
+:1040F000929FE925A2824276CD6D68A76BFDB579C6
+:10410000D5396733FE42D947D8C0A7EC063FC1FA7C
+:10411000B4FEF53739622261AA97982202FAF56453
+:10412000A97C6A36D5C7E56326DF5AC067027B9F44
+:1041300090C7193FF48A063AAE5BA0F13F1F9B1F60
+:10414000CFBBD0F85B6DDA247C5EE7E97F5E169822
+:1041500017CC87CFCB1C7160698AD870BEE323A9C6
+:10416000581F1749C6726C640896632283B01C1DE1
+:10417000C9C5B234928DE575916BF0BD92C8082C1B
+:104180004745AEC3E7BEC8282CAF8DDC80CF8B235C
+:10419000E3B12C8ADC8CCF0B2365585E13B9159FD5
+:1041A0008F8C4CC37244E4767C5E109985657EE406
+:1041B00007580E8FCCC57258643E9679917958E6AF
+:1041C0004696E17B3991255866471EC0E74AE47E52
+:1041D0002CB3228F609919F911964323B558664480
+:1041E000D6623924B209DF1B1CD988E5A0C88FF13B
+:1041F000B937F21896E9916D5826479EC3764FA4B9
+:104200000DCBA4C84BF8DC1D79014B57E467F8DCF3
+:1042100019D98FA523F21A3EB7477E8EA52DF21627
+:104220003EB7460E6179253C5D490F1EF7A9918F77
+:104230008FF9D8C8C74B8F19F978C96F8D7CDC7797
+:10424000C4C8C78B5F37F2F1C20E231F1FB9D7C88E
+:10425000C70B761AF9F8F056231FCFDB6AE4E3396F
+:104260004D463EAED419F978E61A231FCF78D0C850
+:10427000C7072F37F26FEF0223FF4E274F1BEDF4D6
+:10428000C93B0CEDEE092F1AC67396BE1C63D7848A
+:1042900090BFD80BFFD5F09E35EF700C5F56197F9D
+:1042A0008AF19F0348207EF930B1FBC0AE89C56713
+:1042B0000AE707A9B0EF6899C6F7DD00D877B44CD4
+:1042C000B97502C6A952678E9B07FEB8CBA7040535
+:1042D00074226166753EE841294308F32790FC9BF0
+:1042E000FDB45E3B48AB135580FA5082FE0588FC56
+:1042F000617B36ABFFB2EE91491007AE35F376B570
+:104300007612F8D56A6DAC7EACAE621DF82352927F
+:10431000FC83215169A7393E3FFF5892113E032586
+:10432000FF6F245AFEB9ACEB21F027FECA1AF877CA
+:1043300089C263B935900521B4F3E6C0F3203A721F
+:10434000047F27F42B12FCEF4AC8CF8D7ED35B404D
+:1043500070D2F6A152F987D09E3A730FDA171A1C61
+:104360006A5DFDCFE79D5EF944504E6AFE8AA71C48
+:104370006EB43F1B9F904310373717A4A37CA84D02
+:10438000262C1E0A71218C0BB3FAAEA14AA891E922
+:104390008B46B9B2B5FE7E884758413EE5EAFDA797
+:1043A0005DE83F4D024B2117FC033D99122D575AF2
+:1043B000C2F52057BE4AEE3C2998102E1761FD0F1A
+:1043C0004D0F61FF758E99E3605D142E5FC07A29F1
+:1043D0005CBE944627860BFD2BF78EE1AA05FC6791
+:1043E000AF60F05F3A4C81BFC3383229C7F115D5B1
+:1043F00087F03B2E79F07D0D8EF4EFC19431D1F82A
+:104400003F7D4F360FE83B9E36CEDF25FE7D2E1FCB
+:1044100035FAAE4E20AFB47825516FFB567EEFC310
+:10442000B218F73B66A91CE3B47DF8619A511E9A55
+:10443000D258DE83498A1F7746C7318CDF3AF3AA08
+:10444000E2D99ABF85D4DD7655FD1BB4FED44084F5
+:10445000FEB91A9E5A6F437A1CC6DFCFE57ADE5B3F
+:10446000BF7F556D02BACC2398CF11ABDF356E15E7
+:10447000911E739399BEA8C15BE2FAA1F65DA9C92A
+:10448000A827BE2673BB78EBD5C17F0F877F2EC5CB
+:10449000F3BF96F49D07D93993ADC7C3AA0545C1AB
+:1044A0007720DF64580BAB4B5BE97C8A13CF87F036
+:1044B000B884B68FA416D69FEC318EDBE7BBA61965
+:1044C000BE78F1B384DFF99671BEF966639C4F7BC9
+:1044D0009FE20BF19DC7F528524DFFE8BCF2891110
+:1044E0008E5ABC4FABBFF5FBB1184FAF0D96B078ED
+:1044F000B993C973F2351D7D0CB8BBE2E3418BA7BC
+:10450000D671FBB2DEBB03F3D9C85E239DCA831606
+:10451000E0F3C6820A0FCB4763FD2C431FC4FCC8DF
+:10452000C682D5E8CF955BFD56B06BE502D107306A
+:10453000979227F3F649D86E69657AA705DA15D000
+:104540005B77AE45D1100C35807F98A4493E086357
+:104550004AAD8106E82735101C8700EBA3F3D9C1CB
+:10456000F198E195D695D17F6604CBC3367C8FF860
+:1045700087E9FA85F87A33331E0F43BFCC6055675D
+:1045800019F8FDAA088E9F99B103CDF2C19ED96298
+:1045900099EEBDED7CFCCD7C3FD9827E0FBE1760CD
+:1045A000F98CB1FB577BAF955786A75594C1B8F6E8
+:1045B000607939BED7CADFE3FD9EE6FD86417B29DF
+:1045C0005227CEA777BFF37E2D7C1EF5DCDE1F1EA3
+:1045D00064799F75DCEED7FA3DC9C7B3589F7B0657
+:1045E000FC8EF941E68FD5DA83BC5DCBBB904B8D59
+:1045F000F9A31D66B65F3F97197FD2E826111D9378
+:10460000061DDF83F8A36A37D6AB530CF61FA91A31
+:104610006CAC2FCE31F60F8C34D6E79418FBFBAF81
+:1046200037B45FEEF5BB846C98EFCDFD2EF97CBFFF
+:104630003CDD5A827647D4DFD765D3DB27197CACC3
+:10464000ED551576787F770BDF27DC3F63D3EC974A
+:10465000BCD5D8AEAD7B3BDF271BC0FF6101BCB42E
+:1046600030BFCAA8AA7746503CEEF9C0E4DBA124CB
+:10467000865B223FCE46C027EE3F9657FE24F7E3E7
+:1046800004B91FA719FC38F9E0CFF1737FCE54AC01
+:104690001FE07E9C9FF1BCF2FDDC8FF3539E57BE62
+:1046A0008FE795BFC4FD382FF0BCF21D3CAFFC2650
+:1046B000CEA71BA6F807835F6DE794F876F14D321D
+:1046C0008BFF4CA7EA1641F9DE23A0FF7C1CD555D1
+:1046D000E87AB3AA7AD6CAB49E7E0F835B56A0A7A7
+:1046E0000CFCE99EC9AC3E83CB55901F204F8897A8
+:1046F000EB3B1974C752786FE1749E59DD13867CC9
+:10470000165B866714B8406DFCBBB4CD8BF9FC9C7E
+:104710008E6DD55561682726BF5D1E00E3B379E530
+:104720001CE99904E14DDF89CEC380CEE2CE76113B
+:10473000FA159606D7510B9B380A4322F0AB86B286
+:1047400040E388B428BEE82C0C7441E788722B53F0
+:10475000E3BF138C742147B6A37E5C5B353B09E94C
+:104760004F61FD8727907303E718EDA664BFD1FF63
+:10477000555B3DBB5F7FB4EF75E3FBC51D46BBAB2F
+:1047800036AFFFF70BF71ADF1FB933E6FD16B68E0B
+:1047900044EFE74466A27DF07C6B7CBEF00FA68AF6
+:1047A000898007ADEE8EDC88FD63F53E09F4B95CC7
+:1047B00070BFCB7ED07F25C5E3C7BC2445E1A58F64
+:1047C0003FF7F37A39D6A97E385D1E8D7831E887B8
+:1047D00026CA902116D23082703BE3EB75FE0C5A4C
+:1047E000BF93A01DE290AD37AB13807F2C34F855FA
+:1047F00052E5AA330AECD7C74494253B83FDF3BBAB
+:104800003E79114E3FC68F729B3C25A638F8D6CA1A
+:10481000AD4DE2D47871B1259CAED737CDF6A05C12
+:1048200038123F8F44EB4FD7BF44D6E5930CB88383
+:10483000E7099C63F96C83392DA52EED9F0EAE36EA
+:10484000BF63AFB6EF9C2C6F44A3FBD4E1FDD389CB
+:10485000A67F464222E9847D2155D9F148C21D3EFA
+:10486000CC770701AADF27B57F7BA011F8A6FA2332
+:1048700011F9C8803BAA443D1EB4790C56C265B0FC
+:104880007F6B0F2D1121DF3EBFA54AC4731387082C
+:10489000FF0E9570B4B42D0EF9999F8CE559DAAAE4
+:1048A00002EBE0F9F016062FB04F797F940F1BABA7
+:1048B00067FB018FBB33888FE7AF18FC75BB9DA2E8
+:1048C0000A7AE625CAAF5051F89ACE4BB3EB28F0DE
+:1048D000F25B996BB676180939A1DD3F15E1A5E5C4
+:1048E000EBD9B65D5471DE031E0AE37993514C0F88
+:1048F0003093CE30C616A4802AD0F1D7073C3EC8EC
+:104900004FCC6D29667E99BC20E651AC16037B80A6
+:10491000EE357898D3DA316FA536C179810D9C9F39
+:104920004B24BEFDD1C9F970AAEC9B0EF6E89E2778
+:1049300028FDC7F10BBCC3C7796EEBECA4114A7418
+:10494000FF6AEDC74169D3CD2B3722B33CC1966FC7
+:10495000A7EFDF6C263CBFCAF89E49F219ECAD21E7
+:104960006605FB6975C969E467573F4F09F9122964
+:104970009C6EC073AABB7FBAD6F6CDE5A1317A474B
+:104980005E01D27354EF10899BC2B5358FD30BA74C
+:10499000274D8EC805414FBED0974E5AAB4BF0BC49
+:1049A000C9A509940EE99FC5D3EE07BF816B4218D4
+:1049B000D237800ECE021D0CCA53D70A4827631087
+:1049C000DEED5CEE593DCCBF123B6F4DAF03BBCA71
+:1049D0009B0223C7D83724F81ED077EE0888190227
+:1049E000DDD0CF51BA960AFAB7EFAE365EADC58FBD
+:1049F00033E91FD8371D806FE0E39FC5F8A93C5409
+:104A00004F1DA393EF9F3D80FB2316FEB1EFD57999
+:104A10002679E2F16D620A782CA313D34BAC3D4D9D
+:104A2000FAE4AD3D88FCC332632ADAC9BD7675EB82
+:104A30004C5CB785DB8BE63C6E47F6B11BEFF1F5BE
+:104A4000274FCC19DF2D3F74A425BEDD98E8FDDE8D
+:104A5000BCD06FE977D8C8F3EC34FBA3D7EE881944
+:104A6000472C6C8F7B0EC3596884BB3DCFA877144D
+:104A70009AD9FEB4788D7E63B367707CFF26CF4FE2
+:104A8000AB18A7E149B9FB3FE97E5B72D44C1AA190
+:104A9000CAED5CCDAFB404F2D4281D5740DE1AC570
+:104AA000D30252EE86C6F344C47C98F3E43DF77516
+:104AB000BA7D1FB0F073010DE6D3709E42CBC75A8A
+:104AC0001864756D3E952DC6FA22323B1DFCAC8BE9
+:104AD000B69A09E45F2D21D2E92E6DFE940F945B06
+:104AE000981E5449AAEA81AFADE7FEC30A0F912090
+:104AF0007F6AC5ABCF8C81F33995166E8751F82B41
+:104B0000BA3C9BA5CE900CFED14F3AAEBBEB060251
+:104B1000EF87EA0797629E3BE651C5C27D7E8371AF
+:104B20007E579A7FEC7CB5731789E621ED11E29EE2
+:104B30003FFCA14530C4E7AE742EE41908820D484D
+:104B40007C2EE44AEFEFF88EEF3FFF1DDFDF6B6155
+:104B5000F49BE8FD15D69E5B30CE9F56558EFE5ACF
+:104B60009ED7B19204FCE03A37BD3E4B1DA2E8FA55
+:104B700079AFB25F06ED67BA8A7E79FD8F7781EFF4
+:104B8000F35FED7D4E86FD7BFEC55333412F58F616
+:104B90009A8958214F6DAF8B9FFF0AC920EF9676F7
+:104BA00098985F410A8FB95D971F082758018ECBEF
+:104BB0007EEAC278F2D2972DA119F4FDA5AF7C52FE
+:104BC0004C281C2EACEB797B08E83F2F0A2CDF4ADF
+:104BD000ED2ABE9D3E5F2A91FBCAE3F9D12D4C4FD1
+:104BE00039F773C71CA03361CFA17B71DCF6BBCD55
+:104BF000169D5C3864316BFDD8F9AA1784D03081DA
+:104C0000CD4F9FEFADE5B99D7B4160F33B680ED979
+:104C1000607E7BDAE400EDB76ACF5F90AE6FFEE9AD
+:104C20003E37C061D5419381FFACDA630A5B8AB13C
+:104C30003C65417EEF770A63009E04E5F7CA8E1556
+:104C40009817BBB27DD35F4C6E78DFB8BF285C7C11
+:104C50006180EB71936F06D47FF6BC1BF2893FEF46
+:104C6000DCE506B8D271E7C994AE6EFC52B70F0905
+:104C70001B3F92D2773C427A64A0AF55ED1BD9F727
+:104C80003A6E3B03FC6D55CC3EFE1CFE31A8AFFCDA
+:104C9000B818233F2E91DF8E017D83EC498D9B67F1
+:104CA000D02B3FF8BE5EB6EFD276381F7CEEE53FE4
+:104CB0006D07BD7EF9DFBFD8FE08F803DEB079804E
+:104CC0001FAD7AF10337D1C1DF65657CE1C20BCF3F
+:104CD000EF7E9AEE930B1F5950CFB9F08B33990AA0
+:104CE0005DFF85FD7F4D07BDFEC15F4C1908F07863
+:104CF000F0C0CD03FBB363806E43163D7E43885FF7
+:104D0000E5A0C092975FE7650C9EDEEA782B13E67C
+:104D100079FE8405CF71ADA2CFAA4B006F2B503E18
+:104D2000407D0D85F7CABD1BFE622A8E0777758808
+:104D3000E885323C847801EFB7FFC3C45228CD3EEA
+:104D400005C6233DC8DF63DF5B758CE2F7DAC4F884
+:104D5000BC44BE9601FEABF66E64DF6DA7F874F737
+:104D6000C5E779F8C7F8BEF82CB4C6E273F9B3E822
+:104D700063EC488D9B17A7E173C5813BFBD51B34C2
+:104D8000FE7025382F16D8BC2216FF042BECB397E3
+:104D90001DAA97E1393483B65DD8772993503AF943
+:104DA000CCDC732FF0C99E5F583C60772CFDC57139
+:104DB000DC77170EBC2B2BECFC8853A07AC505D2F0
+:104DC000FBD7097AC64A815556ED74852DEE28BE6B
+:104DD0005686664D55DCF8FC143E0FB1FDB03274BA
+:104DE000E80E210EFE1EB2E630FD333400E1B28241
+:104DF0005A449E42235E857180CF53B700FD25C281
+:104E0000A7B67E0FAC7FAC0EAF3BD93E8EEDBF9206
+:104E1000EE57E0C37DF01B128E4379A1CD22413EB7
+:104E2000E4057E9E2516EF51F8F3F390DF525FAC58
+:104E3000B226883370385C69BF5F697DDF167EF704
+:104E40005A151C37168EE7BE8E2F0F9A38FF584919
+:104E5000AAA60ED6C9338B99CAB36CD0F7CAD5218E
+:104E60004274BEF5EDECBCDDB93DA610C88B587E92
+:104E7000B132817DFCB495F9BF571E3C540C7CEDDA
+:104E8000DCE19F73BA6474BF72EF2959E5F221A483
+:104E9000970F09FC283BF9BC57BD1E7FBC557BFF13
+:104EA0001277BCCF25FFDD30FFCF3BCD44A5437C3F
+:104EB000DE6E9A1A4FDF6AB69A8D79B5AE312792B7
+:104EC000E87B26B71DCF33D6AEF31F57412F79CFDE
+:104ED0008CFE1522F93EB3E0F969BB02F1E55AF701
+:104EE000223CD7A28D57170327C95B8EFE0929AD37
+:104EF000BC94E9D421833D6DF688867953B99B0132
+:104F000072E9E4A8336658E71F62F4C73F48A47EFD
+:104F1000201DEF0FAAE05BABC4B3178DE307D69853
+:104F200088A29787969E93301FF2A68D40BE9AE97D
+:104F30000D9B0AFC64D5761BC6D5DF3A707937C065
+:104F4000EDC2B3161ECF6479B595DC5E3B73E0F21B
+:104F5000F6FFA2ED67E065FAFDCAEDB43FE8ED7B30
+:104F60001D98E4FCE797938A09E5D3956F3E3213C9
+:104F7000F84B25C4C069FFCA9F0E0C41EE42F700F2
+:104F800056EFDE3734047859FEB35FAC0479B2ECE7
+:104F9000270E0224F9D681E3F742FDC29B2ECCEF07
+:104FA000BAF0E6991B611F507D5BD1CBF525FAF372
+:104FB000DB74DC655067EDC2379CD7811DB30C4AAA
+:104FC0004AEFCB0E26E179075D3F7C6F95A5E7217F
+:104FD000BCC885A88345B489C283611F2EDB63FCEE
+:104FE000DE592BB32B56C93D8B58FFE060B65F3BB3
+:104FF000F1BDAF38DD6BEDB1EF6BFDBFE4FC333AD3
+:105000000E7B7FA58554C5A37FC1C6C65DB6E76F7D
+:10501000F9C6F118BDF6FD0E7BFE4381E5E393FD75
+:10502000368C132C97C3C353E87E7D45268B61DFF6
+:105030002E77878727D3EFBDC6F9E5723BADD3E75F
+:1050400083F93CA03FD489B5EB2780DF15AFDA08A0
+:10505000D0FB8A375DE8575EF1CAE5EE7FA1CFCF7E
+:105060001D70A0DF6FC59B0F23BE5758C2F7829FEC
+:10507000AE67BF85ECA0FDCFEDFF7526E823E7CC3A
+:10508000E1CC947EFC432BDA2DFCF217E33AA85DC9
+:10509000505045E7A33EC6F270AA09BB47A09AE765
+:1050A00079908F6DEC9C328F4BADE67EA28B0B948A
+:1050B000249CFF845BD973EE275A7D9B323059378D
+:1050C0000FC89323D751BB44AECA073E6B8ADC4A54
+:1050D000145A9722B9586AFD4C701F4321E427B037
+:1050E000B8A039CD472A69F9700A09E0F948E7F410
+:1050F000DE7DF6EF14C5ABB7290361BC9136C65F00
+:105100002AEDFEB136E433C67B14D4036C5D97F907
+:10511000FD08B1F3BD6C562DC0CFA3F13A962758C8
+:105120002D29C7C1FF4E8E72BED467FD6C9F5DF402
+:10513000A4E03ED3D6B1A9C683FC04E265506EA8B4
+:1051400029204A3EE47BF8B06EE2F0B014AA04CE07
+:10515000F7C21E843F8BB3DC2FB2F83001FFABC91E
+:105160001940FAB278ABD05760E5F7E9989C2AA9C4
+:10517000A4A5D9C9E004E7F6004E32AF4B2D331099
+:10518000AEF47D7C7E933D702FC0C59A31D2C0A70E
+:10519000E4B41243BD0FDC34BAD8F7BF0D3F82F040
+:1051A00002BF8E8271CC7108B7F5357EACFF7F806F
+:1051B0005F3D83DFF544D1ED1F396D92A19E107ED6
+:1051C000DB28FCD2A2FB2A160ED53C0F47DB4F8909
+:1051D000F6EF933504832F8FD7B460A93D4F492054
+:1051E000D7CFD8985CAF2681B566E0531EE68721FD
+:1051F000692AC9D0F99F8857C5731FE8EB87F68CD9
+:105200005BD17FA9E1D7E491BA8DFC4F390EEB79E0
+:10521000F81DB308FCCA54FD1CF92455B78F6794D8
+:10522000DB1484B30FE303B55CBEAEEFC5A7717F9B
+:105230006CAA51B0DCCCF7C916BE4F1E03BCC37DAF
+:105240000E702F05FD5ED35482F2F3095A67F67E85
+:1052500098E8FDE1C9BEF6B099E21F79928225FA7D
+:10526000ABC9094B685836C455891FE825F9C48F66
+:1052700042B856D28EE72592B57B5D5ECF499E8BB4
+:10528000F11F6266728A98581934831D150BDF5A14
+:10529000DF612BD8E189E65376728900DFBB3C974A
+:1052A000C5CCD2EE693F01F73C389B1C6857A6FB82
+:1052B000AAB23291BF5A905E9DBE8050A9C3637A54
+:1052C00002FDEF21FBB40F801E3F843C445A3EDEBA
+:1052D000926B03386F32B77B811F6EE2E7C5953959
+:1052E000140ABAFBC2DEE47CD25D6AE4031A5FF6FC
+:1052F0004C2831D0B3C67753261BE95EE3BB2FD8C9
+:10530000985FA3D25E7E06E6931A69C57D19BB0F2E
+:105310006ACDB22A5C8BF7CB30FFD32981C5D5FB90
+:10532000F2038CBB5FECCADE01E7A9B5FD13BB7EBF
+:10533000A9611A7EA7571F34C7CF07182230B9DEDC
+:1053400040E98D605E82828868A6744678DE02DB62
+:105350004FE3B0D4E8781D613C44ED10D93CB9BFAF
+:10536000563B7BB3CE5AE2073CAE6F677B68A09D8D
+:10537000C749D344905D44A2F6A4933E920E8DB7E4
+:10538000827E29997D47810FF6B8C47688E3AE778F
+:10539000CEB6421C44482E45FAF9CA5591D55F5CF9
+:1053A00007EE5303FAF3387DE474219E8745BFB0BE
+:1053B000C95342C02EDDE7ECB4633E935D34C49F15
+:1053C0002AED810CBB4E4F2D82AF73BCC3B0FB12D4
+:1053D0009CB72CE0EB21192AC9D3F189DEFB8F148D
+:1053E0009514E8F8C5BA61B7E0FD4A7DF944027E3C
+:1053F000B8EB7F861FD6668510AFE658FE93E6C7EA
+:105400003B9D68A9C2D508263274FD0F92914E27A4
+:10541000023C887347AF1E74534EDF79C6F2BFA8B3
+:105420005C53D00F46E5DA53E3809F26946B55F723
+:10543000211D370D51808E0F353FF22CD43F69B6B8
+:1054400028C0BF1645361285CEB732321ECBC52DC9
+:105450003FC6B2A2A58D6E2242D66EAE6C9E0BFDEB
+:10546000B799D0FFD31DBAEE4235AD773759507F8B
+:10547000EF6E7D200BF4BFEE268702F7AB74B78E7C
+:1054800036B63798709F75B79843261E0F36413C45
+:105490008270FE0E5E20DD7C49A9827AFCC5987878
+:1054A0004BC5168B5F7027867F454B7C7DB216FE01
+:1054B000C9CEA3E5037F2D3BF9A32CA00F8DCF3CD4
+:1054C0009C42F91EC0EFA485C48B0BDC649FB2C460
+:1054D0003E004AFFFD768CEF5FDD3D589F8854EF1C
+:1054E000463C05DCB30C7E5FE657FD84EBE5C49AD1
+:1054F000A0DDCDDFF7C46F5FD1F4A7B71FA5B50D51
+:105500008546BFB609FCD502D8E3B3F8FD196C3E59
+:1055100071E89AE9D34D16E42B0BB83F4AA3F32860
+:105520009D05DCFC9C9E810E97441E43BE276C2A81
+:105530007A6A3C85DF1794FE803E844D1307027C17
+:10554000D736DEB0E51E3AFE97BF35E1F3C5111B35
+:10555000F63FFBA8EFA97BC05EF83733E6917C7974
+:10556000740AC691CF9A8D7E8C1B1C6CDF1FE4FBE6
+:105570007F516493413F5FD4305F063FE8A24833D8
+:105580003E5F044124CC8BBFFB976579105F229866
+:10559000CF72D07EC79475284F4BD08F56B9D91291
+:1055A00037AFFFA05D31F2ABAE261C9750FD2C2D1E
+:1055B0009D8FA7E33B959154DC1FC4A312C8EF5EF7
+:1055C000C4F94FEFFC5ACD06FE73D616DF4F73D4E5
+:1055D000CEE4C2A2C80DB8EFFAAEEF467CBE48FBDF
+:1055E0006E17DBA7D1F53C353EDE7AA2EB9880FD45
+:1055F000CF26C7FFFE9FF9F7BB6B16133FE55F157C
+:1056000016DACF09DF7FA07E1CD8F9ADC929826EDA
+:105610005D952DCB885FB7AECAD679B2FEBEC928DC
+:105620001EEEFF659914C5C39F1B974F595708FA83
+:1056300042F97FC23EAAD834B1388076FE4684F360
+:1056400027665F26F0E3332D0FB8E3E50FFFD9AEF1
+:1056500018FC1C952D1C3F54EF2ED5E147C34BEC95
+:10566000FBDDBFAFFCEA51E053DB5C06BE125BF62C
+:10567000C15B767CB8D91C1ADC0A4800E1A6BC7272
+:1056800002E87AB3C307749D187ED790407FF04B31
+:10569000A03F533D4B748C86EF12665FB6303AB82C
+:1056A00012DCA2DFE57450167F3D63F97EEBAEA9F4
+:1056B000262ADDB0A7E52BD1C12344B5F6B38E5E13
+:1056C0003A78C24007631D9B910E3E03FD27BF2F12
+:1056D000FE4FCBAAFB7AD0771A4D18F73A6D57D305
+:1056E000BFCFEAA3803F9F7607675E5F1AAD2FD9D1
+:1056F00035CCADBFA7F14C0385431CF88D75C4ECC8
+:105700006F8D7EF2545238E6FF1DFD7C92E0DCCBBB
+:105710004DF6B21B009F2418DF9FAC95BDE7AA93FE
+:105720009CBD762FC8D1D3CE9CAF42B4B5C11EF874
+:105730009E83B6D7253F8472FEF46901E5F0DADF77
+:105740003F9C0F7CB88FFE5B1379FAD361E8B7FCFE
+:10575000974FCDA84FE1B884EA3F200730671CED92
+:105760008021E8674914CF5D0197F98E8EC675B523
+:10577000F8EDFA9ACE1FC3F8C4AA128FFEFC00619E
+:10578000FAD8FF8179E8FCF3B239E0F181BD2B90C2
+:1057900072A07BB3C4F2D7CDDEB451AA0ECECB1C1F
+:1057A0004C9FB41D39D2904DDFB72DFC770FF8F91F
+:1057B0002CF43B505A33A48B7A7FB996F745F27498
+:1057C000CF7320BF82D60D7E073ADF7EECE6D7048A
+:1057D000EDBE4F15EF2B9EAB5D5800A0A374F39167
+:1057E00096BF22D5B1F664ADB98EB5733FEAAA0A69
+:1057F000E6277D6B5E12C24F5BD7DCD737E07D6951
+:10580000735F1F341FFC69739DF97F0478BE06899E
+:105810003540F7C94C3EC7D2C566CE7F7ED026AA9A
+:10582000663ADE1173CF6107EC8B1F0A68577FFF62
+:1058300083236620F9FF3876DA0CF723DC078945E5
+:10584000743DF3882233253A84EFCF27ED2E566F2F
+:105850001F00F79946C7A326338C773F8B3F7FFF06
+:10586000836353408CD2F1D64379DF6F890CE3CF49
+:10587000EB50EAD9B1273EDEEB743C313A5E2FFCA7
+:10588000242BC2230A1F2BC2EBA3DE73242AEA17A0
+:105890003AF8A2BEA2C1B716E046E1373769CE7426
+:1058A000529C78BFCC750EFF23298ECE2716BE5F83
+:1058B00042D320385FE67F09F6CD3F3BFC7BA15CFD
+:1058C0006EEDC99472F0BC573BECCB95A640563AAE
+:1058D000A5ABF34303F903E0505067FC386FEC3E8F
+:1058E0003D09FBE55A28E9BE8079F07329F7F27586
+:1058F000BEF5A3332ED897F5078E6742B9C2D4B54B
+:10590000F96ED86FBF31A1FE79B123BFDFBCBA9366
+:10591000DCEF72D4A1DDA3C1D6791FD7E7EEEB701F
+:1059200084D652D2B8AFDAD46B5F015DDF57CDF2C7
+:105930004F88D4597C87419FACE3E7D4FA8E03F6B5
+:1059400042EC38DA3A0F670EBE06ECCB6747CB68FD
+:10595000471CFAEDC58F2A69DD3ED48A76C2E6641B
+:105960004EBF65CC6E7D36D9EF2802FF57638A4F54
+:10597000A5EB6CFC256917299C0E8F782834A91497
+:10598000EE7916D177B625F25C7012BC57C8EE9945
+:10599000F170BD744BE7E916A0C733272C1877F8D0
+:1059A000C465C2F9369ACB33418FFF639B1CF7FE67
+:1059B000B28F5C12CEB74DE8C23CBDF92468057EBB
+:1059C000D1D1397B20CCC7ED231E20FF33AD2691EA
+:1059D000DD6FA6F95BC212F3F7AB12ABFB79E9B14D
+:1059E000E9EF17DB387532E6792C687A17CFB1B951
+:1059F0004BE3DFEB6373B2F9BA3A53A6017C5D93D4
+:105A000045CCC376F97A04782FAB73928CEF078577
+:105A10007EDFCF5AE399067085F781CF675DE5FB9E
+:105A20008293E5693DC6EDEC36B3AF7E321DA76DBE
+:105A300073B200F8D0FA0D7632BE7266B2E64762F3
+:105A400079C299791E5B1E9D77A61F37377195061F
+:105A5000F11CD30EE8C7FCAC0887B611AF84218EC9
+:105A6000DD08FE15C0B399D153E36601FDAA147E8B
+:105A700083414EFCF109CBADB08EAC06C103B63B01
+:105A80002DE3CE7BB6CBCAE8BCE929B40BC14D0BE4
+:105A9000E366B6BE8FF3722558EF1A4E1F7FBC0225
+:105AA0007D9C77303F54667527BFDF2E8CF7D80575
+:105AB000014E50F797F2FBEAFC8A3E3F26BA7FD6AA
+:105AC000723A247E88B3558C9343E047101BDAF07A
+:105AD0009ED4F9410BF91E5D5F93C0EE1D55478BB7
+:105AE000FCFE24FF498053F36303310F6F83E8CF3B
+:105AF0000439ACFEB38C71BAC3FE8BDBE03EF8ED2B
+:105B0000E364DC1787FDEC5CE1B36B72DA204EE9ED
+:105B1000AA9ED4329F8E17F260462CA92D25EFE461
+:105B2000439C728DE81168FF60B996B7EDC17CF2B5
+:105B300051A62FA615401C6F90883EA53302BBA727
+:105B400061FD9A491EC0EB7A4F9AA0B75F66713A21
+:105B50003891523ECB49E1E37DF4710F9C85DB1215
+:105B600049BD06FC886A83ACEC62F142BCDF21953A
+:105B7000E325B5530C2F7263DDB9989ACA5B2630C2
+:105B80007FE98FA707989F1362A363D0CFC9FFBC9B
+:105B900088D7345E6B1C69C7CAD6758BB03F8C93AF
+:105BA0004EC7492D15C363207F2DD9BF1DFD7653E8
+:105BB000AC08272275B5009C425306633EF8E3E328
+:105BC00087BF0BF9E3A9477B66831C0D0DB5FF4723
+:105BD0001BF0A9F5B202FB3C754DF73DF03CD9F73F
+:105BE000E40350A6D67DF808F0E9E4AEBFD4E0F3B4
+:105BF000A9B2C1BF98FAF1D9BF417B6AB96CF05321
+:105C00007E9552FEA093C2677B613058A1B0E7FE3B
+:105C1000F4E83AF6ADED9C0AF7D89F9925B2F33235
+:105C200084F1C3AD5B3DDA39E552900B1ADC36885E
+:105C30004A7B18D635D38AF491473A915F0D826832
+:105C4000766E142FA91F6FBC1FF23562E7D3E014E4
+:105C50007ACF51C3BD80786E3107CE1F4EB6035D3B
+:105C6000EF2FE9F4823EBF39C1FD9D475DEC7D8B8E
+:105C7000C8FCACB1ED47783BB0C496122CFD455042
+:105C80003A899A046586D50FF9CFFB45E53F91CE59
+:105C90001F3729801FE86FA6F83BF4CEE7E85F3C8A
+:105CA000147C1FCBE75C05DA78E174FA7E73E9694E
+:105CB0008CD3347B188D5436307E51E9EDB242DC02
+:105CC000A4B2907876707A53353883BF8CCBAB8A88
+:105CD0003B185CD30A09C67DC11704F74BA5433FA7
+:105CE0000ABFB486B5F7231E49A79A4BFB35C3B844
+:105CF000809F3A91B071BBACB87F83268C7BD2FD7C
+:105D0000FE3BF06B55340DC4B83F1C0F86F152F8C2
+:105D10007753F8786D741CF01F9E6930E1B9004824
+:105D2000BF81BAB286D232D2674F59011D5729F5C9
+:105D3000781A353AD0F818DD1A0BA8BC00B82D50E7
+:105D4000D5FB81FE4E5B3DEFC03C1C5B2D0AAC7F5A
+:105D5000C1D6571F06FDC5E1ED6A00FE50398ECD54
+:105D600037A5893E473D47F91DF4AF6CB228EC7B5F
+:105D70001C7EA59CCE381C16F2792F6C65F3B60FED
+:105D80000D05813E2BD750B8425B80D13DB844BF52
+:105D900011715F1D85F5BBD4741C77C09C987D1173
+:105DA000437FDABA2AF8BA2AD6B07511BE9FE8B492
+:105DB000C2306E45295BE702C2DE17E1391D7F2143
+:105DC0005F4F85FA0A960B1B2C86F1B717ECEC8413
+:105DD000F96417CA8A807066F71B66F27565D6B1DA
+:105DE000EF6516BE82F022D5BAF9A25F5557A7FB20
+:105DF000EACCAFE9C682C3FF70D0808E7BFA47EC55
+:105E00009E81BCADC6759DD998FF1C9CF7FEE40928
+:105E100019E3DEFB45DFC92CB4476585F11FDFFBC5
+:105E200033804F2FACF3011FDF57C6E07FE63612F9
+:105E3000027A1876B43C05E03DEC68809755184F1F
+:105E4000A700117AF91E9D1F35991A04E09791DC7D
+:105E50009716031F18C7CEF70CD5CF9BCE2FB521B1
+:105E60007D12E443A58D4B9924E315DE31ED479F68
+:105E70009E0DF78FA61D79FA01F8CE20A25B0FD0F8
+:105E8000833B979D6739425BA15F75F7A3808F269F
+:105E90007E9FFC3098590A9647A04CA5FB7B530A7D
+:105EA000CC5322934BA2FC60D7136346015FC1948D
+:105EB000A7122CC3A4A42FDFD0F51FC1FBAB429CBB
+:105EC0007E16B762B0CF773D71CB08B0E39B414FF0
+:105ED0004C827B383D5F409E8EEA1311EECDE6B0DA
+:105EE000B5300DEEA51609E82F5B0A3E1461DF35CB
+:105EF00077101FD0476AF9DF2D7A3C96B9D8EFEDBD
+:105F00004832D904FBFFF088EEA980A7D02111AF59
+:105F10001898F42BE7D30ED0873E6279306DBFAE70
+:105F200042F9FD50A61CF73E5D72053D31B67FCAB1
+:105F3000B0D9E8CFCBDAFA18DEE7593955F27D8FC0
+:105F4000F64EDB5A56067A8C524EA96B209D77EBA3
+:105F5000A8B5F83B103358BC4C99CA9E2B9359B93D
+:105F6000A9E6E88FC16E0FEE916C7974BE2337B24B
+:105F70007BC436155EB406A85E5A5AF6B2F536FAF8
+:105F8000FCD3522A05E9F34F275CB4417CE7D9D210
+:105F900049A900CF8E06A35E47E0722B6A0F155900
+:105FA000827E179D57D30704E169B2845B2A68DDBE
+:105FB000F4AA13349C3E76CEC6A6B63940A70B0A87
+:105FC0006474DBC7AEB793CB8BF9D53D53E1DEFCF0
+:105FD0006C9530FF7EF02964CA0B39CBC8563B91D3
+:105FE000E9B8B632FB2428F9DF06BE1C2C0CC8F039
+:105FF0008AC6CF9A8655EC067E76DCC5EF0BA95A89
+:106000008CE7CA70FF9B401FEA298B6737153BED71
+:106010004C9F6DBDFD38F8A91754337D3FABF50B90
+:1060200001F141F5BE4174FCAC52BC5A902C58139E
+:10603000B416017EF244A228309F7602764290CABE
+:106040001F3D1CB471FFBBEF2F7359701DC5A03BE2
+:106050008F8EAEC7C9D793E9A3EB8923A70BE1BB0A
+:1060600090EFF3CC1787C603FCD73013292B784A5F
+:10607000B0EAE691A55EDD3C8AF83AEA5CECBC85C4
+:10608000ABB44BC0FB6B62F83BA8F3B06FB73B2ED1
+:106090008C62F6BD919FF6A973BA8A7D9E19C3AF33
+:1060A0008A2CEDD311BFFBD8BDD584D07D6BC5EB59
+:1060B0001B1576CF6748BB5FBA0AFA8D74393D402D
+:1060C000074D233E2C01F86CE6FAC2C24282F6EA82
+:1060D000C28C4ED417E6D7717D41F2D5039375B4C7
+:1060E0002613ED7E18D01F50550213BA8EEB0B9A73
+:1060F000FCE772BBD2DBD98072B58E9DF7EBD5334E
+:10610000542657B3BC4CAE5736D0EF289C98C7E8FE
+:10611000F51226C795AD5C7FE07238957F37AD816B
+:10612000C9AB54D023DC9006A1A25CC618567A54A1
+:106130006F1950C8E4656AD37E946B2F3A199F4C4F
+:10614000DBCAE4E5D0778FA900262F7DDC42F9F485
+:1061500013BCDDEBA1FA594A543FDB20F2781361FE
+:10616000FA21E6FCD3796EE6FDB5E73BF9FCF61FB4
+:1061700049B915F8EBAE600E9E2BD7F62D7A3F6924
+:106180003D93DF879059CDE2E42EDFA2DDFAF3677D
+:10619000152E76CF50858BDD07EFAA0E7B615CBC98
+:1061A0005701F9B88CFEC58D545F42FF13B7AF4A53
+:1061B0009DFC3E194E3F89E489C6875CC4EF2EA43E
+:1061C000F0FD34B41BF9B54AED2558DBA7C1DAC19F
+:1061D0004B61BF076795C2FC9BC77F85F91F5909B3
+:1061E000ECC58F343BF35BF275D7D463CC0EED1462
+:1061F000E39EEF497733FF43BB441C004F5B90DDC8
+:106200001B671B27C7ED6F7333BBEB53BE1F9BC7C9
+:10621000EFC6F39909E5B34454531C79AAC9DB26A8
+:10622000C0F3F574DDAE5FD5E3EF0849A17213F258
+:10623000578276679074A11DA916C8E8376C32079B
+:10624000AD808F2DA51CAF1E6B1B9CCBFCD678A1FF
+:10625000F0003C6FF48B21211BF01CF21431BF0EB7
+:10626000DEDB7986DAEFFA7845AE5BE47052F087D0
+:10627000F6B21A187D358F97711E8DA3D2DB4CD9DB
+:106280007AFE2B70FEC9E8AB71FCDB485F573BBF61
+:1062900045D52F3DF3A92E9ED8BDEDF91C8073F492
+:1062A000FE0B7FBFE7291655FF65EBCE387182DE06
+:1062B00076B0A39C600786BE6F886BBAD9BC6F743A
+:1062C0001BFD77C05FCD685C8406837F69DFC49067
+:1062D0001BDE236B58DC76098FDB7EBEF3763CAF8A
+:1062E0005E44C9CA1C07EF676B8CE7D5CFEE7A7E98
+:1062F00030F36B840CF1B325BB7F3ED2101FF61335
+:10630000256D0CBBB718E5F4DB3ED5628ADE3F2075
+:10631000C3EF0DE446EFD1B293762C9DB07F69E9CF
+:10632000263D587A401CE5829DE4C3328D946399E2
+:106330004EAAB0F492209683493B961960E7E68214
+:106340005CE8C152211E91E8F87E0EF1613D8F9408
+:10635000632901DE52A37109698F15F337207E018D
+:10636000FB3ED1B9B391EE8A656E8477D5B5E598D9
+:106370004FCEE21533DCFEE56E942F61E4DFF33996
+:106380002B3FFA9391ED70FE68F56676EE45E3EFEC
+:1063900068DFD0EFBC94C2E481FAB8807C6C9D6366
+:1063A000E68D08CF26F3397DBC8158AD79F0FB1E10
+:1063B000DAB8F3B99F613E9783E0EE66E7077D7830
+:1063C0003E693EF81B74EDA4B79DDD4BA38D233AC7
+:1063D000260CEF2FDEA77B1FF3A32B62ED802BC9CA
+:1063E000EF98FA82D8F7BFA6134A8FFAE35EBA5144
+:1063F000C9447AE5F29B129482EF35584EA13D16BE
+:106400009CE2D7C3E539CEE734B9B22026DF23B604
+:106410005C20F1FD11330E9580C970EF1ADE29A1C1
+:10642000DBDFDA7DA4DAEF642DF107E441EC352FF0
+:10643000E0D1C3E71D24AD9306D1F233A8EBFCFBFA
+:10644000BF4B0AEC77EBF68BC7CFEE59203C2EB151
+:106450009CEFC729A6A632E0736702C40776C41270
+:1064600052E5BE01FCF9C7D8FDC443E8BCE512B053
+:10647000E3882AA6605D85DF6B395FC3CE0975F3BB
+:10648000FB6876F37B85FFC4EF112E6A797826D0FE
+:10649000C1E7FC1E9A828E8DE5E0F7296A77CC036E
+:1064A000B95FD43EB112DA8BF658D8EFF0703EA146
+:1064B000CD0B8EB9DBE97732E8F7AC29C04F08CABB
+:1064C000DDF34DF610FC7ECFF97613BB47B550C413
+:1064D00073F770EDA089CF2F2905BEF75FF7823ED5
+:1064E000F239E727DDEE64862F4915D434484B2175
+:1064F0003ED06B1E73ACC473908B9CA1DD4FA74143
+:106500007EB8D5B78E7EFFD0FE5733E1F9538E9516
+:1065100058FE69DBF14CE05BE70F1C97E3D1ED0A15
+:10652000292C837F6A59872042FCA4AC7D9E0CF104
+:1065300091457B0FA15F79852780EDCB5BF6637D6D
+:10654000F2DE77317E323449417C9F1F14403F6F29
+:106550005E8B250C3F59B22F27B8346EDC3E89F193
+:10656000DDC71C6FE0F84F39DE781BE1B2CD82E762
+:106570003F0E6DFB158E7BEEC0AB7CBE04F305CFEA
+:10658000DBDA4FFE13C8AFFDFC3CA6B5D3ADF70771
+:10659000FF9DF375AD7E5EFB1D9D8C2BF4D37E8F2E
+:1065A000C7D9E9667CA9D30D71B345ED0C0E7F32D6
+:1065B0008765D02397B50B0AFC3E5ED9DE363C0FCB
+:1065C000B8ACC38AE72596013C006E145E08979626
+:1065D0004338FF0C80CB6858C7FB988F9FD741E1A9
+:1065E000521C5DF7326700F7ABB65E0A07B6EE7D68
+:1065F00057C253C088A7967765F0CB2CEF10107E5A
+:10660000CBF7B2792CEA60F39ABC771EE2FFDC018B
+:10661000A280BFA57BFFF1CF613DE70F58F1FE5E81
+:106620006D5E944E89BB04F60FA353D2C1F8AAA69F
+:1066300077AF08A5E3EF0CF4B6EF65BF330A20B3DC
+:10664000517A2DEA988571C162205EA0534FFB48B4
+:10665000F67B81C14C80EBBE89E14C98F739ED7730
+:106660004CA56026E065A43B509CA4DBE7674FBDCA
+:106670008A72B140ACFAC3A3B08F5F66BFBBF1F0C2
+:10668000C78F897A784C841F4A1E0D70FB9D1BE1D1
+:10669000D67B7F4B90E54B9100EEC7457C3F9E6FCC
+:1066A000A376275DFFD9969F61FBF941C6FCAA3FFF
+:1066B000B5BC950270ABE0E73148E876E447142EAC
+:1066C0000DD63872BEF75C5B889D57BC2010BC2F7E
+:1066D000537D46835B953CDB10E763FC30A335FBC1
+:1066E00008DA19A1F8E71C63F5A4D8FB5113E503F8
+:1066F0009CE6FCEC537E4F97267767B8033F481A19
+:1067000090F8BC77C5A6159900EF0A381B89F711D8
+:10671000BDF13DC823C57343EC5ED430C0A75BBB5D
+:10672000F79474B0F664565F9DF46F1BE03C58B765
+:10673000768FAA7A98B567B3F666DEBEC75DBE34BB
+:1067400009E53C11D8EFF99893E1771934B991181C
+:106750000EC6DF6568830B3706E0780FE278121DFE
+:10676000AFE8BB8FA7F1E9EF3C8EF57F761C4D7E3D
+:10677000C1FE84D447E2F38DFC9F80DF7FF77D125A
+:106780005C68D85797B7E5D6431CED9297DF03D3E3
+:10679000B496803C5FB8F531C3EF7AC4DEE354CBE6
+:1067A000F372E45CBADF74FBFA7012B3730E27095C
+:1067B000BDF794437C6B3821FC9E29AAE2A5F37BAC
+:1067C00025A9FE91CFEF2D2F2041D44F4792762C53
+:1067D0000B492796C5A4074B0C33E782ABD487E55A
+:1067E0009FCBBAC6C0E2975B03CFDA44CC3B7813A9
+:1067F000F6C9F9A181E7E1DED9758E95D7C3FC8F83
+:106800002479F83CC286DF5721FADFBF50401F9C35
+:10681000E1ED4F1F241EE95C6FDE4B0EDE5BFB9B40
+:1068200024C443A2DF41BB3FE6DE1B762E5C83C35C
+:106830000AB84987F6FF65EB6ABCC76FE95E17EADD
+:10684000C9C35BEBF0F7AF9692CE7438273C9CDF60
+:1068500023425AD8FD2DDAFD20235A2C86FB4B56B5
+:10686000C4FCFECE32FE7B59CB627F8F8A9FC3DD94
+:10687000040FE2E463C49EE33D9B14FF7715496176
+:10688000FCDF3F893DC7BBB75DC4FCA8D59077A5A9
+:10689000B32F46ECACB218E94BF94D9E5957177C13
+:1068A000CC1FE1B2FB77097DBF5394CCF4807D828D
+:1068B00010371FEF760FB7B7491D994EC7F9BFD4F0
+:1068C000AD220900800000001F8B080000000000BE
+:1068D000000BDD7D0B7894C5D5F0BCBBEF5EB349F2
+:1068E0007693CD6673DF4080201737185244AC6F23
+:1068F00042C4886817A48ADAE2060402E406A58A7C
+:106900002D2D1B122120D6F83522D0842E7829581F
+:10691000F5DBB4A848835D3022DEFA87D6B654ADE5
+:10692000DF827C8A88B06A4BEDC5FA9F7366267B4E
+:1069300021116CFDBFEF79FEF4B12FF3CEBC3367AC
+:10694000CE9CDB9C7366B6B55EB56F608CB506AD4C
+:106950009ADE094FBB2EA8143396975A655E0265DE
+:10696000E6D0D94778189BA69F72C853CE98B141FC
+:10697000BDC404E5BE1D4BFA0D506E75ABCCA440F2
+:106980007B878E3128B31C5D700494DBEC3F73CCA5
+:106990001FCBD8481BBC877E0AEC2CE8817EF76FA2
+:1069A000BF5D87E5D666C6B2711CC5DFEFA1EF54A7
+:1069B000F630C33F6D46998BB122FC278CA3B28D74
+:1069C0001FEAD318AB6E386E89D8E07DA476061B1B
+:1069D000CFD86576F87822D4BF79F57B58DEB6F249
+:1069E00098C30FE3BDB87DEDAFA7417F8620C005FA
+:1069F0005D947EDAFAFA34182FBADDC87640F9339E
+:106A0000FCBB82B1C255EAB1889906649FC17FF987
+:106A10002B12CB4606E552512E4638E2EAA13C0E37
+:106A2000C7CFC2D21C167661BD80D7A9310670329D
+:106A3000BBCDF9CE18C62EB52BECB361B1F2C5585B
+:106A40000694EC3474545901CE9D7F54BC2D507D76
+:106A500060FBC2229CDFD967FC457698C74A73DA8F
+:106A600078961E8377E099EE11E3062C3A373EC301
+:106A700016E68EB51FFD50B3C90FFDB4AD66DEE35B
+:106A800023183307FBAC63701D0F19BC50647729C2
+:106A90006C4E08EA551BD34230CE388742FD253F65
+:106AA000EF5AED79B9C4101BF7AE4FAF9F83EB1BC4
+:106AB0004DB56A3B9473E192DFA9764F00D7D7902A
+:106AC000CFBC29309EC1D99F6B87EFC63C6DF4DAED
+:106AD0000065D3FE736C7A04C61DF3DC4DCC93CAFB
+:106AE000F185F0AA2B8DDEE3998C99563ABDEA2503
+:106AF000D8CE46F4F891CD183421FE57DEDD81F56D
+:106B0000ADDB2BDC9EB1B171D7AEB67B5580B36BDC
+:106B1000B5D9ABC204D78AF925C357E0D0F982F0C2
+:106B20009D51C7FC585F0FEB80F4536F4FA1E752A4
+:106B30003B87BF5B0DCC42F8BB817E5A905E57709D
+:106B4000FA5D9E630E229D2F7F7178361B3BC8BA7B
+:106B500088E723ABDDDE1280A36BC53C37834F2B68
+:106B600097F559AE82F92F4F35DB911EF569231F3A
+:106B70009882F4FE9281215FB5A65678E6C7F5A704
+:106B80004F9BE4467CE875815C6667ACC57E4B8DA7
+:106B90009A83F412D8CABC8CADEFA8AA512F857283
+:106BA0006A205781FAFB3AA6F1FAACC05605EAB75B
+:106BB000744CE7F505815C1D94B7775CC7CB230265
+:106BC0005BB1BCAB63162F8F03187219EBE9B8A148
+:106BD0002600E3B71ABC73BC30EE1300FF58803FA9
+:106BE000249E3F177891F53FC3F780EFDDE2995C73
+:106BF000FF94F86ECF10F57B457DEF10FD3F2BBE67
+:106C00000B0FF1FD01F15DDF10DF1F14DF1D1AA274
+:106C1000FE2551FFCA10FDFF4A7CD73FC4F7BF16BF
+:106C2000DFBD36C4F7BF13DF1D19A2FE7551FF6625
+:106C300052FF6F89F611F13E3FB5FDF500D05D3E84
+:106C4000C82DFC2B4D6DCF40BAEB6A2E27FA6F9DF5
+:106C500008743E3646EFF90AF361B9D4A1527FA514
+:106C6000288FE1F9AAE8BF7259C9BD4877CB5FD533
+:106C70007B910E5B15EF113FF41F58A6F3A2DC5D6C
+:106C8000FEA29ED3F93235C8E2F8FBD524F8B70945
+:106C9000F8DA04BCCFDB87517DD14AB77786949769
+:106CA000C8F7F6C4B219F84983F1DB9C5CBF942E97
+:106CB000AB328F42FD01FA05E5E65D3663D804E3A9
+:106CC000DF6557A9BECD5965C7FA805D25FD73976D
+:106CD000B3CA3C1FE5AA0D845D058C67E77DB7D973
+:106CE000D59A20CA0F4735D54FFBCF197694A36D9F
+:106CF0002CEAA8C4F9AD02BD02DFEF6FAEA2F745E2
+:106D00008E3F39503EBF9CC1F9BF2FF5A0A518DAC0
+:106D1000A9DFD691BE186957498F0D5BA50B7AA0E4
+:106D2000499F7DB90ECB0FB6717D057FA965307E79
+:106D3000091F9EEDBCBDE2A552D467F7A85E8F8700
+:106D4000BF53E3F44109EA2BD05F398E0C2E1F8527
+:106D5000BEEA2E671AF61B709B830F43BF252A736A
+:106D60006766C4F09EE3D07339AF9FE145BD36BC82
+:106D700023513F15B7C7E92786FA32513F25EBABC0
+:106D80008266908F71DF9BDCF684B2DE914AFA094D
+:106D9000648CF733187A79CFF2ABAC2C26AF93F52D
+:106DA00051ABD00F52EEB67E7A49827E907239593D
+:106DB0003F9C5FBEFEE6EA51448720AD3CE797B3B7
+:106DC000AF221DC03A1AFC0AE90FA6FADDBED4F3C1
+:106DD000E3CB60F0D9EDB6F3E3CD90F51AD9150603
+:106DE000BF4AFD9FA357CE8357D9CE687EB0FB38EC
+:106DF000E8B53FBD7947290396590BB8A1F5CFD225
+:106E0000051F8679E7AFFC6937F69F77D0DA867879
+:106E100036BAE777B7E17C3A1E600CE8496FE6F4D2
+:106E200064CCA9B2E3F7AA4E73670C87F2AEDFDD3C
+:106E3000AC003DE9339BBD0CD6EDD0132F655C83D0
+:106E4000F87BD5407C6ED2F9EC6C388143F4B6AE59
+:106E5000C0BA7D03D1B1DF8C78CADF69263DC0029C
+:106E6000DBD76B40D4ADB01C6C32D67F7DBD06F84D
+:106E7000D9A90C94AFC6722868E4ED4144E3FFF54C
+:106E8000E81451CF341558F3714511F5FF59533DAE
+:106E900005DAABF6312AE89DFAFB7ED66EB81CEB1C
+:106EA00075F27B8D4D82F9E278A2ACC2FAFCB44F48
+:106EB000D407C2EDD5C0443D46393E0B60FB1E9D54
+:106EC0008E9703CFB463FF8F5789EF030FAED7F2CE
+:106ED000099E6BF40EC6BEE3E86BB75D1A83F7EE4E
+:106EE0008C97DA5B607E1F782269B09CAC61FB7185
+:106EF00017EAE775739A7D8837247C1FE8C414BDB0
+:106F000087E86960DD76CF0CE441ED99837F4B1B08
+:106F10000B554DFAC8C114C05FC39E66B301BE379E
+:106F2000197C81BCE2D8770DBB6BC99E69EA2DA3A1
+:106F3000E720DF1D5287FD4BDF998D1730DE07E11B
+:106F40005F373E06550DFAE6769B9EDA33BEFE832A
+:106F5000CF4F7EFFC163BFBE01C73BED89B8A643DB
+:106F6000EB7561C0CB20DFC9F68D7B66D2F3D729E4
+:106F7000DA7A07F0752DC82E92576AB317DB87CCE3
+:106F80001D762F20DA62E8F0A1DE00D40775936247
+:106F9000CF8D8E126A9FFC3E99BF4266963903E5FB
+:106FA00078BD4A7A2A640EA48C87F246D887B4004A
+:106FB000486BCA7E37612C969FB431DC97B4D6F704
+:106FC000B9C7225F798D0CEDDD8D97867290CFDB8E
+:106FD0001A8C731E027842E1E5EE0571F6D6DD19D2
+:106FE000069AD7FAE781EF2E86A721E450F0FB112D
+:106FF000A03780942D0EBF19F739969C0C1628C621
+:1070000076B68DC89FEB0DFE9A2A6C97A323FD627E
+:107010001931BBA60AE07067E9143DC1517D6421B6
+:10702000EA37BB1135283B9231EF6788A79FAADE6C
+:1070300066E4C39FDA6CF60054808CD450FEA9231A
+:107040009C412C9BF4AC19F5785E19E8F3383BF6BB
+:1070500088909F471C468277A32534B312FAB12E3D
+:10706000D7D90330DEFA864DFDD3609C1F353C75C1
+:10707000B805DE6F70A90CE1B039D5B011F48FE11D
+:107080005A8011E07EBCC56747F91ACD52D90EA8C7
+:10709000B7961899274E5ED9C642394E4E663A5574
+:1070A000CD02DF9FCDF0BFE880712F79F535337EBB
+:1070B000EF9EA8D321DB8454BECE69E589FDD8A715
+:1070C00024F693519D58EF9C9158EF9A9D58EFFEEE
+:1070D000466239F7B6C4F22C496F20736CA08FADAD
+:1070E000BC8A59231FAE467D0BF8F903E2DF3A5202
+:1070F000E745FC581A1E3AB110EAF3509EE07E684C
+:107100003C23BD7BA0F03B1EB40B4C19CD1EC7D851
+:1071100073F1915760BE06D7CB56A2DA19B4B7BD4A
+:10712000F9DEA7D8BF8DC5B52B46FC6827113FF8FF
+:10713000E7067852F11F1EC477F37F7D0FF5E261F9
+:10714000BD17F19DD7A0D2F8F7CCF604F5DC9E7000
+:10715000A33D9326DAA79937F6EB419EA7BDB97EEA
+:1071600019EE7B93F1EA62CD0AF225D007DF6FD7E3
+:1071700032D21FEB74AC0EE906F708D81F994720EE
+:107180002FAECD34129E1461EFA0E6C07A97B09F67
+:107190008C39B759908FEF3AC8E9FF2E23EF67A0DB
+:1071A0003F0F0D8A24CF504EA666E812FAD9641715
+:1071B0006D4439CBC1CB3D7D19D7205F6E9A9D318F
+:1071C00001E9C484FB2EE82F3DDFAC8D86F9595EC2
+:1071D000340614E8345D657D0658CB1E2BBBD507FD
+:1071E000706C39640DE8E1BD65C17FD8D14E1B9F3D
+:1071F000C1E9BE678DF7372807A2B52AE1D192D53C
+:10720000619F3096CF2100F02139A05EAC1CD1499E
+:10721000769EA5B283F4BBA5ACA303F1B465868EBC
+:10722000EC8D8CDB7444CF9682D0E112F4132CD019
+:10723000D9B1BF0C50FC46E8E487F91D3E1FF60BA0
+:1072400038D7557052C17E6986304EA6C0ABD3B9CF
+:10725000FB0E05FAC9C4FEC6F3F6882787C053455E
+:107260008687E0768A7E334BA0FD78DE4F5B45ACA7
+:107270001FB98E5B6A5810E193E3CA7E06FA679ADB
+:107280008272D5F032E00DD64929341370772D6122
+:10729000B43FEE59E36BDE4E7C6D233F47AE33BF08
+:1072A0000AE928F7D0D659BAF1F89D95C6312C6075
+:1072B00041A4E35C9599BF9A81F68D8FF098CCAF8D
+:1072C000397D1DD7A39D2AD725997F7354D6AECF7C
+:1072D00038978F739CCEAA91E307E1E7247EC939E2
+:1072E00014FD36127D325F6F4B395D867861F1EDAA
+:1072F000F5E72FEBF5A1C3E8E761D9A02700F585F5
+:1073000049E331F64F139615A6F37C361CE5BE43D0
+:10731000D031E82B60D69E09F6A936E4D3658CE817
+:10732000ABEAE98D37BF0CFD9D1D61B4A35E293822
+:10733000D4D18FFA91EDF18FC275E852FD3F4E81A5
+:10734000FAAE23D90CE5F67A0BDF8FA982CE93F53E
+:10735000CBDD197C3FE6413DE7FED79FD23E0C9541
+:10736000B8C6D881F7EEFE8F2B5F3467FD0FDA5970
+:10737000ECD1F51A94F3FBFA5B6C38FE7DCFB79B2A
+:1073800001BF965779FB0D500EA888BF7AF2671D92
+:1073900028584878525F3731A4D3717A2D8865F622
+:1073A0008685A1FCDDF9E437EA3C287F5CD33D28E3
+:1073B00087BA04BF6F15CFE4F9AB46CD8FF644F220
+:1073C000FBCE01B9E43B510BEB38EE4123DB0095DA
+:1073D000A5BA79EDB8BF8BAE07F90BB5F3F49EC62D
+:1073E000BBE3F6B7EDD6CA4733E0BBEED566E6079A
+:1073F0008339FF1385F981390B9CBFAE44F953C81B
+:10740000C20AEAD9C266307891AE5658993F8EDEEC
+:10741000F33F51A97DBB557B34238BBF37831C3091
+:10742000F07FB29F66F858AD93CB28B45F0C8F59AC
+:107430008FA2DC60CE6A6D603F320CE917F43E8C9F
+:10744000F7B498B70170689800FFD97461D3F873E6
+:10745000DBF70A79AE9A6D619497AAED9523245FC4
+:10746000ECEAA9F876B8EF262156CFC82F8B78A181
+:10747000F2B7EC54CE03F96B9A40767F00F7DF81C8
+:1074800034BE1F619AE671BA905F182139DFCCDAF9
+:10749000CDD08EA81DF82D87F55BC86EEE631EE477
+:1074A00007F4B0BD9342228B215EBB18AB89E70382
+:1074B000F9947E0975A59EF653639EB3103C8666CB
+:1074C00016B4A03D84B001BED5152CA816C7FC8209
+:1074D000A50E0F7D6764CD64CF3EFEE95BB928A79A
+:1074E000AD07C11EBB18D7594772CA6A4DE43FC6E3
+:1074F0005A084F27057D74AFB6D33A0FECDFFCAFC7
+:1075000089758EB4A0BE285C9191B0BEB25DFE2795
+:1075100079CC7F497CBF41EA2FBFA44F41BF4CFECD
+:10752000278554DFBDDA739EFE870DD17F0ED1D142
+:10753000D0FDE7537D77F835C775808AAE689FC365
+:10754000E789D9D7C978CE5F9128972FDE935896CF
+:1075500078B11834E74CC0B9E5DB3AEF76E8EF2BA9
+:107560004712DBD514FF96F6BFB1F661E7F5D81EDA
+:10757000F6E7DBE1ED652712DBFB2A9F77201FC7CB
+:10758000DA73F8AEF824B15DF2FA24C30B70657DAE
+:107590003D0EAEA9665342FD9CDA73E0CABA310EC5
+:1075A000AEABDC89EDFD2D83C3754DA9E973E19286
+:1075B000EDBE36E9C2DA25CFE3FA1AD31078E7ED4B
+:1075C0006F9C7361FDDE52F7F9ED6E5D993C4E8064
+:1075D000F8A551A75D9E09CF79F80AED459B95EC7A
+:1075E000DE647A7954E8A76A343CA0BF8BD2B4EA4F
+:1075F0004C785649BE137E86434F5C948D723D4F46
+:10760000F8D199F02BF4D4BBC9AF70B3680FFAA4CA
+:107610000DE545CF4EF82E8DC3156F3F65D6F37D32
+:10762000859D45899FA5BD94C1EC0ADF8F737B675B
+:10763000A87192FB5F97C1E19EBF722A7B1BF8F095
+:1076400029A3BD52C5FDD93685EC81F9D59A3E15E1
+:10765000E86372BB427EA5F977FEE687E88FB9F44E
+:10766000B8674F04DECF0F3ABC386C633FD3304E5F
+:1076700090AD5F56F63D78DE7F00EC1F515E86F4DC
+:1076800066D33CB8DFA84588A09F5386E6323BCA44
+:10769000CD6FDA34949BB5B3B53FD07CFF0156096A
+:1076A000B45BC0A7CE9EEE9C69C47847ED373C938F
+:1076B000D0EEA90D59347A9A996A8579D4823D869B
+:1076C000CF6C23532DF8B432333E2BD670FB2B6D89
+:1076D00092CF580BE3D7F6FEE4CFF8DD2235BC9FFE
+:1076E000DB93419A776DEF8B7F457B6D81E633A20B
+:1076F000BC18B3D3C86D52410FE34289659407F1BA
+:10770000E5B27062F9924389E5F771E1607D260B7D
+:107710003FD6817D2692DB4BDFB792FDB917141E51
+:10772000EE93038F9B487F4C5D6AA3F57AFFA475A7
+:107730003BFAF5F6BF6EA5F64B7E6AE1ED75A12723
+:10774000B01C782285F6D94B3343151900F72F3E2C
+:10775000D513BE715A06ECFF89D1DB3760FD25A138
+:107760000A8C8B3D751163FD58AF06C7E33C9FFA49
+:1077700027F75B477799823BA0DFF79FF9C913DFB3
+:10778000C57177E56528B03E97A15E8076931F347A
+:107790005B71BF31F9FDC786A3DC58BAD39430BF03
+:1077A0009D998A88AB79D290EE86F23B1E5BFF13DF
+:1077B000FABEF4C411A2BBBD86800EE37881F59CAD
+:1077C000CEF65AB89F74AFA53088EBF47426D73B39
+:1077D00097E976FCA811EDCB57B91D3254FFA5EE01
+:1077E000F9DDD583F81907EA61DC6258E733EF5910
+:1077F0006FD5008E519B13D7697430B1FC4B31AFFC
+:10780000792CEE7D31C2336CAD1BE1D9CE089ED20E
+:10781000136FDE5C8CF6B889DB21C9E31ECAE4F283
+:10782000E1D147A11F2E67F4DC0E078C015F2F15F5
+:10783000FCF00B85DBC1F0B7220FE87F291A10C3DB
+:1078400062EF9726C121FBFFAEC0D3C7E6B41DA8E7
+:10785000CF9D464EF727571FFA21C63165BB775695
+:107860006B5A759C5F79E1E665077360FDEB7BB24F
+:10787000689F29DFD7EF7ACE750BBC3FB553F5A2D1
+:10788000E95B7FD3233F988CED76E9430827D6A3A5
+:107890003FF354E8F9346CB7B0CB3101FD25F2FB6E
+:1078A000459BAFD4AAE3E4E917E527C9FFF5627F5A
+:1078B000FCF4A4FE697980EFA59B152F365B1AFABC
+:1078C000FAF5D7A2ADD3A5F7627CA342653EFD04CD
+:1078D000DABACFC6677DCF930773A1BE69DFC40A4A
+:1078E0009CD7069DEF9A71C82FDB0CE4074B5E1FF7
+:1078F000E6E4EB0CDF8775F0FD861B6C75181781CD
+:107900007EFBB07CA074871EFDF8692740BEF1F7AE
+:10791000477420334FF4DE351EF62C40C7B676E4AC
+:107920008FBDE8B8C0711ED7939E60613E8FC9C2FB
+:10793000FFBCF48F9D46159E274EAC49ABE4FC4737
+:10794000EB8442DD09F3AB7B701CF1EBA2CD89FC2B
+:1079500025DB4978170713EB93E9C2E394FE0A5637
+:107960001A4F5FC9ED3267048CC88FF52B419EC753
+:10797000F14DFDF10E23DA5DC9E3A005C9E4BAEAD1
+:10798000892E612C9CAF85CF174C5E33CCF724FE3B
+:107990008BFBCD15DCD72F51688A6CE945ACDA0337
+:1079A000F85C3A8BD5E053CAC3539342E3B1FD5E12
+:1079B00043E4911F911C4C257970CA1E4E43BF525F
+:1079C000AEF0EB9DF284D350CE9D11713BACC7F26B
+:1079D000925ED007C0D7EF7F6024BDD0127A2E0D03
+:1079E000D7EBD413169D0ED6E5FD9ECC2AF4079D49
+:1079F0000ABD9C86F33A19CAAC42BFDE50722259C6
+:107A0000BE497BE028FEF352C6AE746A9A13E51DA8
+:107A100006197240DF643697350FC2F7F23BA7B103
+:107A2000B90CF334A2DFB47951CE5EEBF4D0FB5A3B
+:107A300085F7877F18DFFBE850E60E5CFF43FB47C6
+:107A4000A6A39DF011F3A4A3DC9EEBF2F99CB09EDB
+:107A5000EEAA7E8AEBBBA7336F2B7CF3B6DE7BBB33
+:107A60001DF0761B03BD85CF72BF91FC2D6D5904AF
+:107A7000D77C958555A0D3F9A857C75399EC98F9A9
+:107A80005D4AB015E0B86D63E23C17769A62EB0B85
+:107A9000FF2D6620109181BAE2DA41FF8B517F02FF
+:107AA000FE9698593805FA5DF250E2774B5998E006
+:107AB000A97FEC33D36078FCB3C0E35C97B618F1D0
+:107AC000A8CC32135CDF7A5C21FDE6147EC6E8FDAB
+:107AD000E9418C872D15FA7A81693FC1D37467AD6E
+:107AE000761BD0CD9995F3B5DB3279CA08EDCB364C
+:107AF0002B44874BAB59B800E05BDAAB84C7A13DA0
+:107B0000F11A5F27D92FDBC6DBDD2CEC9D05801732
+:107B1000B41F263FA60452417E2E30C3560EE58880
+:107B2000981FD6A743B98E75D0BC1A5884E0588BDD
+:107B3000EBC8FD7904FF9F5FE3EB37B96EBB1E8195
+:107B40003AB4BF82E27F1F332FAD23D825CC927188
+:107B50002E9D20DEB5383CD5752596D94371E5615B
+:107B6000885728C7E1BB71F767266D103CDF3FA03F
+:107B70004F82A3678E63E7D8BD6F8975B8FFEB0BA3
+:107B800073500EDC8BF66BAEE86012CA4D26FD1A00
+:107B90006133F46FBD8425F839C0BEA2F283CE995B
+:107BA000D337E733B6C9E0A778C17CBDEF2086B6EE
+:107BB000FEE9F2FF04D777BE4E2B54491E682369B5
+:107BC000BFBB92AFC703139A47370FB2CF95F06F81
+:107BD0005242611DCA8367B87D905A1E35F8E3F89A
+:107BE0006CBF9073E9072207F3905E9E54C82FBFC5
+:107BF00045616D0AE0D90DCB82FA608B72F420EA00
+:107C00008F2D577B582BD497EF9EB9EC79DA2B5BED
+:107C100029AFA76177A5BEC146F3E7F66A4AF376B6
+:107C20001DD467DF5A3A01F904E67DEB2C787F50CA
+:107C3000F06D8E8DD3837B4DA07839FA650FF89661
+:107C40003D8FFC3DCE4AFEAF6C33FA7AE9D98E7691
+:107C5000A89BB528D8EEFE34DE7F964E7FEB4C2CE9
+:107C60004FE0E58C558AB68388F83EEA3FDBC46A6C
+:107C7000107E7C8FF63474A7F5507D90E69B3DB561
+:107C8000B90CFBCB1ECE9F4E63381FFB796560BDE0
+:107C9000FD3A94BB2B84FE5CB1BD2A1BE5E42BA707
+:107CA000CC2ACAC357DCD20E0CDBD00E6425A5BC8F
+:107CB000BDD0532BCAA66623FD3A0B13DB9D31685A
+:107CC000E997A0BC3FACA7B8CD9F6C5ABA03DA5D68
+:107CD00066E4F3485EC7A8D0AB4D9F282C18B7FFC9
+:107CE0006F9A7396ECECA64FD484F7A7569B593045
+:107CF0006EFF5F5F77601AB66B60FD6B91AE1A42E4
+:107D0000292C1847E79759071F57D277D3277A1698
+:107D100018745C63E2FB4F32592073B076AEC4F73F
+:107D2000308F84F29EBF0CCC03DFB3499134F487CB
+:107D3000CE40BD06E533415DC000F2E41503D757E0
+:107D4000A7ED91047D76DA13E1FA0CFD3D366E6FF6
+:107D5000CFC47556A369B35263E3C87AFC3E236E61
+:107D6000BEA7E7185998D6274A7020FE02A318DB51
+:107D7000DAFBA111F35CEA7BF713FE24DDC4E331E7
+:107D8000101F3F6AED0FEB80F7C7DCDFB961EC68CD
+:107D900058B20382CF039B36605CD8A5D725F07D0F
+:107DA0004AF9801C20B1733F46B3C81FFAC086EA67
+:107DB000FCB8B2683FF07D60F374AC2F1FCBBF9F5F
+:107DC00078FF9697D65032480797A36AB4D0971A8F
+:107DD000573627956D501E1757B627D53B93EADDCA
+:107DE00049E57CDEFE546AB850EF05E0EFEF9E8E69
+:107DF000F95CA772C27331FF6BA33E38BD1ACA0D7E
+:107E0000E55CCF36F62A5EF2E109FC357AB9FD670A
+:107E1000F3468C98779652DE7F10E544FD1EC5AE82
+:107E2000003FD8423D612AE3779EB8EF420A7D5772
+:107E30001F3A4ADF0DD97FA98EF87D43E931DE2E46
+:107E4000F42EE9F3756DCB28CE2EE3C87AE6D7F28F
+:107E500094581C59CACBD339DA73242FF72976E406
+:107E6000CF013AC57EE3FC37B2FD1BE37A7F8BE698
+:107E700042CA8A0F5BD02EFD63C3BB13D14E7B4336
+:107E8000E8854D4A70348EBB95F947A3DEFB66C387
+:107E900088FD3A68F79621D28DB1B2D5F73F49F8FF
+:107EA0007B2B355280F9742D59E1E9984FF75656DE
+:107EB000A41BF1F9FBACFDBCBE205280F97377DD49
+:107EC000FF3EAF1F11E9C6F2E359BFE7F5E3220514
+:107ED0007A3B6E758E4CAF86FA87ED83F3F5ED59DC
+:107EE0005C9E48F8869768CBB2D00EABE7FAA41B2D
+:107EF000F63666909B73979C7CFC61C0C3DCEFA454
+:107F0000903C7BF8D4F5D3B99D1DF0A915E887E521
+:107F10007FA4EF486EABB4FFCD411D97115B8FD4AA
+:107F2000C27E0FE9838B9A7BD06EC89E3B96F4C1CC
+:107F3000579DDA111C573EBF9F074F687F24CBCE59
+:107F4000E5B35E4771E9ECEFA6929D75AF85CF076B
+:107F5000F886D6D726D6E3EE2CAEBFEECEE2FBB740
+:107F600045CE2BA9BF9B855DDCB93EB8CB02F87F1F
+:107F70005DE6BBDCC7EDEC5BB6835C0139DEE9D0C6
+:107F800072509EDC22F2D7A4FCC0F71971FB8BCE95
+:107F90003228DB62FBC8CE995A8ED5894F970EE303
+:107FA0002F521E7516F3EFA45ECA6EE5E366DF3B43
+:107FB0007A07CE2345E57EA4057346EE6821FD3E93
+:107FC0008BE6CD342D4781FE8E2F1EA643FF925C9B
+:107FD0009FEA12ED61ACBF59F8E7E53AC9F53C22DA
+:107FE000E63D5F0FF601CCF3772E3FCD1FEC85F118
+:107FF000C28F45F6C2115CE3AC187E991A9988EFDE
+:10800000FF3FC2D34B5F069E1A5682BCD05D80BC38
+:1080100010F8DBA4840DD95C5ED0BE18DFA3DE7936
+:10802000CCE97F0BFB97E3CFFD6E03D98712AE94AB
+:108030003B9EAEB9919DCB67C9F6DB09B15ED2CE4E
+:10804000F44A7FA418E7ADD7CD147F78CB1822B9B6
+:10805000F916EC6B5A50BE88F879C57796BE82FB4C
+:108060003AD9EF752E9ED76791EBAEF87A16166364
+:108070003E090B98711E338DB4EE52EF763A787E3E
+:1080800048E79D79941F72864518F9352731928FFC
+:108090004007541FBDC945FC0FED03166CBFF82205
+:1080A0006A0F741120F9709395F6219D186FC6FA26
+:1080B0009B4A8398CF82FB5FA2B7C53A1A77107AA2
+:1080C000E17EE3513C5F42D28DAB95FB6798AA8D70
+:1080D0009F19A7E72F72713F514A79E4C9DFA37D49
+:1080E000BAD142F629EA588AED7464533FB0FE993A
+:1080F0002EBEBF273ABBED07A9222FCD5B81785D4D
+:1081000097CAE9B2CBC2E34E5D600F935C14F42BC7
+:10811000F3E2FCC2DE8BD4E9D2D05E28760DF80DF6
+:1081200034DCC793DF1BEAE74594A3B8FF9A17D066
+:10813000874DB89F6ABF528BC4ED47F00FE376B707
+:108140000AB9CA3633F203DE8ADFA561FFD6348C62
+:1081500053DE8ADFA3DF75D59509F1B84B5C9CBF70
+:10816000257CC972FF120957C7035AFC38B2FFE4D5
+:10817000FE605F59EECA223C87D3717D5BF4B47E0A
+:10818000C970463673FF75647311D19DEC6F283842
+:10819000FF4B1FFDB6027A70E154BEDF96FB9805D7
+:1081A000623FCC5625EED3D05F3250D69F5B4EDE79
+:1081B000F7619C3DB13DB75B52C6468DC4B71E25E5
+:1081C000017E89AFA1F070F317C49BD47B0F588058
+:1081D0000F32703BAD10FD6EBE3385F498D3181C82
+:1081E0008D74B5C0E5A1765B31DF85F42ADFFF7EB3
+:1081F000FC8AF45F24EE7B9BACD16D88AF262B23E9
+:108200007E3ABD2F95F8879544E662BED899BD2683
+:1082100086F4DBA84446A2DC3AAD68B5D4AE25C5E9
+:10822000837C24FD036F3FC5FD034D884980AF2942
+:10823000F077CA576ADA93B81F3E0DFFD501DD9F6C
+:10824000D6452AB03F290FC08ED6C83EAAE3719CFE
+:10825000461D0BE03EEB32DDBCC59CCF73D90E7AD8
+:108260007F74E4F2383B1DDAF529199C7C906FEAA3
+:10827000051E1B75C7A85D3DE61D213E71BF85FE2D
+:108280002EAC8CF3CF366E7C9FF29E1A7727AE779A
+:108290007D8C1E94CF14FC2E8E3E889F03421E3090
+:1082A000EEB7A8E671E854514EA9E9A73CA826E12B
+:1082B000C7C83A1099867225B53CC4E6C1B3E90433
+:1082C000B73726F76E7F0EF7C78E9AFE02648326B5
+:1082D000E1EF93EB2DE1BCB4F73EF25B483B256E3A
+:1082E000DF397A5682FF600D7D87FB581C2F82AFE5
+:1082F00072900CB87EDB24F41BE84192B70B3A462F
+:10830000911E443D85F249EE83515EA19CF8A7ABD6
+:10831000AA07F9755376D563AE2C3E1ED9F5B8A9D8
+:10832000BA74683F9DC48F6C87FBE1CFF3C3F5221D
+:10833000DD66C5FCE3045139E64D6749BF1BC5E75F
+:10834000962B9E6CA4DB77F47EF2AF2D6201F2F7E0
+:108350002C46BF163CEB05BF2F147EA285C23F847E
+:108360007EDBF83822FA4FE3CB4B583F971B3B4D4F
+:10837000B1FC1AF4E754B3702AF4D780FE267C8649
+:1083800012BF6B6451FAAE69CF67A6843865279F28
+:10839000F7AD62FD1DD5413DCA892D16EE6792F2FB
+:1083A00063F22AEE8F4A9FA015DF8574FEA281FC3E
+:1083B00014FF2DD66D40CFBBAA9E42BD62D5F3F30C
+:1083C00068D1BB4C24378F833EEE11FE9159B80F14
+:1083D0005DCD34CC5F67AABD307E9F2A9F1BF65AC5
+:1083E000EA907EDE75E912E8EB472E9ECF437E23AE
+:1083F00092CB29A477417C8C47FAAA1826F5221B38
+:108400008FFEAAA362DFDC7883CD8FFD45745CDE2E
+:10841000FCC9C5F7017F72F17C4E591ED8E709FAF5
+:1084200091F13FF4DFC4FBCFFF3ED0FE3E9177CB0E
+:1084300068BE9B168BFCEE013AD6915C4A19EB2381
+:10844000F97B99AE8AE452F43D9B07F152F37EFD2D
+:10845000629CC74773AC748EEF36E1CF4DC976503E
+:10846000BFD27F7BBEB858CD86D1242F65FB34DCCC
+:10847000A0649DEB07DE2BE4D85EC6E10D9CB0F254
+:108480007C13950550AEED0D8D0E22BCB5C2FF805C
+:10849000F60DCAD7E8937C1D99CAEDA1BDBDE38254
+:1084A00048EF470DFE2D0BD09FD36320FF1A538357
+:1084B000BB1EC17E9ECDF162FECF695D74DBAFA0B5
+:1084C000DDDE138FE661BC67AFF0BBD71BC323C9EA
+:1084D0006E16F98EF569E191E807FA8558AF7A2BA7
+:1084E00094E17DAAC53F2A3B2B1617C3EFF0FDB1DF
+:1084F00020B7CB8F314E07818D3CEE09F8CD5980E6
+:10850000F0AECFA6B81AAE0BAEC3DBFBC6D1BC36FD
+:108510001944FB67146AAFCC2A9D4B7A61832913F7
+:10852000F17FC667A47CDDA67BB9DD385FE7D9B6ED
+:108530001265E5B32934BF059D8729DED1F4834553
+:10854000740EB269C9AAEBD8E7C40150AFC4FBAF3F
+:108550004FB36821ED87EB8685C200C7E9DED15EA7
+:108560001EC6E3E76A1A455EE87103D310EEE83EE3
+:108570004370B0F37E43F58FF3C5FD29EA37F273FC
+:10858000C7C75B481F24C65FCE573E6D888CBC139F
+:10859000C65F9BE9BF293BCE5E6C7A3687E4DDDBA4
+:1085A000F7FCA590EC8A0E1E2F386ED0E6229F387D
+:1085B000AAC3C6797176D8B26C6E97CE3709FB1113
+:1085C000E4603CDFCBFA8AAA443E93CFE66C6E8728
+:1085D000A48AFC8073EB65FED9F526D49FDCB584B4
+:1085E000FD72795D24E26E934F44F7639E557DA83A
+:1085F0008CE27A45ABC2C49780EF30DAFFC7B7A4EC
+:10860000727902D3C47E164E6264BF2ED4F37C8787
+:108610008526B087B91EA7F6EF6CC9263C54ACE19D
+:108620007660F44985E4A28C3FD632FEFDD36D47D7
+:10863000037A685FBB532903D1CA6ADB2A291F6208
+:10864000495731ADFF64217FE79BB4915B90DE9E7B
+:10865000E6F12B188FECEE7ACCF99A4072C988FAC1
+:10866000B06EA7C2F0DCB09C7F72BC8F0513E32D07
+:1086700093435C7EA3DE6071F69AD443A82F589290
+:108680001D9948178104BDD78D789D1893FF84B13B
+:10869000CFD183604F6F43FAA9A8E2FC17ED5108D0
+:1086A000CF0DAC99C787841E1A8047E8B177F45C78
+:1086B0006F2E34DD47CF9FE321B02CD48311AE075A
+:1086C00041AFA15C1C8A2E7E3E045D487AD82DE81D
+:1086D000A3FE040B5F0EE3D5AF62E186F1FC993A8D
+:1086E0009EF432D7CF66AE9FF169BD003D9DAC9F31
+:1086F00093F571B21ECE36727D2BE920DE4F8FF6D8
+:10870000C8E455413DF7C3E6DB31CF4FAECB22A7DE
+:10871000D6979715B3B79A8E98CD9E8BB1EC63C35D
+:108720006CE85FAAF415A0FF5CE5E78D53004FDB12
+:1087300071FD847D7E79015F47B7C8E731A83E5659
+:1087400066C375EAA7FD74348B517EB6C46F772A71
+:108750007C3701BFE3FC38F0BD99B559E3BEAFDA11
+:108760006B21FD72F699543A57C6547F9103FA7300
+:10877000BD01763A944FEF4D25FD7E5AC87BA7F494
+:108780005BB0B5B41EEFE23A4F44AAABCA43FF2F29
+:1087900053A6E7313A6FCDEDC606C7507E7B515FD9
+:1087A000DC7F03A73313E9D9B38EC8ED58067828C8
+:1087B0005FF8BF04FD36ED9E5AF65D8CF3FB6C5EF0
+:1087C0008E557F19DA0D26FD8A1BCC7A3C77BF2A9D
+:1087D0007A27CCA3A1C04679C8D5456FFEEE2628DE
+:1087E000BFB7DB40E715173F7C7D7A183F5335F75D
+:1087F00060FA7971D090700E6EE9CEC4724328B1E0
+:10880000DC9474EE7DE59BDB5FEA8BAB37BB539D5D
+:10881000B4FE1EE6C53C6AA6FF46BA7F1079299FC2
+:108820007F591D7CA96F04E5A1A5BB797E8D11ED53
+:108830009A79480F837C77309BDB352653F309CC3C
+:108840006737FDC244E7E3DFC8F6BBDDE85FD64526
+:108850000FE27A9A8A4E8D473D5855F40F8A8B9DC8
+:10886000FD1EF3227ECE5A2AC9BE39BBC5E2C1FD28
+:108870005967A18DE8A0F35925A870FB7DC6C40AED
+:108880008C83D21C58D3E6ABDFE3872F98999FA740
+:1088900087DD8B1BE58C46FBA977665AED6BE0BB49
+:1088A000BACD5CDFD6B3FE349403DF748BF5D33FCF
+:1088B0006634C33F8BDBB4D12D00EF529F95CEDDE4
+:1088C000A89FAA74DE7C1D761967FF97BBB93C6828
+:1088D00030478C9538FE3F56D4A06B4CFAB94C0605
+:1088E000BF86E7BB0C7BCAC279F06AD1CAE7689F32
+:1088F00033104FDEC7E5D6A23BF7D37B65560DCDCF
+:10890000F71D982FE2E5B92D269AEF3B0536DA6779
+:10891000BED3CDF7BF8BECC6A099EC8D4F32F15C86
+:10892000EC3BDD063A8F7E2E3EAEA2F3A9EF76BD7C
+:10893000407EB877191F37B05B4FF6CABBF6684563
+:1089400018F1E8694E437BB76EF3623ADFBAA85B71
+:10895000EF4379B6A8FBDBBFBA14FD47B36E2EC751
+:10896000295DE158E1F2D862F5D24E5533263D82B9
+:108970007C78C5A753FBAF407BA91BF8A498E7CF31
+:10898000A39DDED77D15D9A58B665A1D382F4FD7ED
+:10899000C3D3507FBC3B3397CEE32E7A5C6178051E
+:1089A000C322C74A17BE5FA4A8BEC1E8E9E36C3D75
+:1089B000E1B5B2C8E60DE377BFD5139D005FDD805A
+:1089C000FAB3A1DB40766FDFACD77F779333C6571E
+:1089D000CAACCDD74DC6F63F3150FB017BA7EB5A51
+:1089E000492F2C5C81FB2A8EB7643E3315AD1A8962
+:1089F0007025F3DBA235CD2379FCEA8BF11DEBE288
+:108A0000E773EF70F3FB23BE00DF7DFF8BF01DCB20
+:108A1000CF48D84F9D2BDF02D44EFAFFCD5EA63D46
+:108A20006CA378AFA680FCFD0906AC27E2939F3BC0
+:108A300052FFBA7CE7AB809F316E7F07F26F11D394
+:108A4000CA506F7AA2F62A3C536413F61CEB32C963
+:108A50007D00D9F79BB2D8231BE2FC0F0FBAF93E79
+:108A600009E4C016ECE7F41FFE7110D7A9B1F0D4E9
+:108A700078F4FB367DF2278A17DA7A79BCD9E68D4D
+:108A8000523CDDE0F4111D4AF9DEE4E5FA27795E97
+:108A900027DD061EE77546A99F17723C54EE14F1B8
+:108AA00095AD2BADE44FDDEA0C5AB87F21C0503FA5
+:108AB000CD98A4E77132616F5D2BFC91E6F2E71867
+:108AC000C6C7D8149EDFF56AF9736A26947F35E924
+:108AD0004A2F9DCB2B7FB07D18CE7B8A41D40FA728
+:108AE0007B33FE8F5649F5CBDD7A0FF2F78C729E01
+:108AF000DFC8EAD2C86FF26AF9DBCEDBE2E0F73119
+:108B0000B3C70674330B98353E9FEEBA29168F2DE6
+:108B10008E7E3EEA506AB8DDEB499F3D8EFB4548AC
+:108B20001F9727E263B9DB48E36ECAAEEC43BAB9DC
+:108B3000E2AB7C3D4E3E6E0AA21C3C29CEB924E33A
+:108B4000EF376EE1A7534727C4ED9DC65021EAC910
+:108B5000F795C4EF96B4EB296EBEB85D614118EF8E
+:108B6000E4AEA70B519EBFF7F0D385F3E2E049FED8
+:108B70004E3EFFE816F42AFC82C97EDEA1FCBBB2A1
+:108B8000DD99CDCC6F1E1E6B7FA6EE6FE4DF9DD707
+:108B90002BFCC39A56E2C4FD90689FDC9F3997D3A3
+:108BA00087B24721BF87F46F1E3BF420465206D69A
+:108BB000CFD25BAC8BCF4B94CFC962DDAEC7758390
+:108BC000A958DA7979A8F51A8A1F77083D24D7EDD4
+:108BD00058FBF074C4A3B1D1A6327EDEAC14EDF51F
+:108BE0006E66F5223FFD45E4A73AADF0043BCD9813
+:108BF000EBB6A13C93E7FBEFB0A6EDC0E75F44FE08
+:108C0000AAD30A4FE8A720B794FAFB8BCE47FBBA4A
+:108C10003BF41D740E3145F049360B2B0A8636960F
+:108C20003EA550FE567B22BE5DAD5C8F446B8DA48D
+:108C3000BF24DE2F9B773BED5F0759AFCD4847B987
+:108C400093F8BBEA9C62E1EF88501CC13289D9716C
+:108C50007FDF7A6980E090EBD5C49B33A55721FB79
+:108C600019F3585232285E1A104F66CB6003F18315
+:108C700014B1DF6549F1826CB0BBB19D8413CA9415
+:108C80000F73AF23D43192C75BC92EC57EF1FDBCF3
+:108C9000B12AF9DBB19D71C2F9E96F804E457EE1E1
+:108CA0000CF9BECE3A687C62069EF3C17500FD8861
+:108CB0007621F31A12CEF974813D8DFB3419FFD55C
+:108CC000EB42656EDA9FF447D07F62AC307B50DFB9
+:108CD000A6E843A5B87EC9F1606857CCF310F21D31
+:108CE000A867E4399EC695537D18A702FB2360C68A
+:108CF000F59BC9D7AFF1CE4A7AAFCC2A6D41FA6A5B
+:108D00005AC5E8BE81A9BD3D94EFD454C3EDB1A6C8
+:108D10003D478D0CE8779EF0E730E17F7689753D21
+:108D200026ECEF58BC2BB20DF3B73B17E7D3B9DDF8
+:108D3000E4BC922F1AEF3C930A08B9382E8E956E38
+:108D4000E67A46ACBFE46F19D74A1DEB2B464BFCC5
+:108D5000C507DE7BD99AF545F2469EBDE773F3461B
+:108D6000D8F4EBB0DE8C56BEA84730408F0E9CCBBB
+:108D7000B37828EE35508FF72998F72822EFE4ECE6
+:108D8000B5579650DEA8E8AF6F23E67FDF6B610929
+:108D9000E3C5C3A726F56F80FE6D1ED9FEF83557D3
+:108DA000AA14FF15F04FDD88E7FAEE3524F64724C4
+:108DB00028CF119A63E3F9BA7E70CFC6FC983E07BC
+:108DC000FDBE3167624CAFAF7B7D46C7C51EE4AFC9
+:108DD0008F290F57EAE72627CF234996630FE470C0
+:108DE000790E76F13454B9EBE62CA3FB0706E2BF0B
+:108DF000BDB51ADAC332FEDBB4CA47F9B8600FFC5E
+:108E00002887EC8153EFEC6768779EA47D41D327D8
+:108E10002AF713815D81F7C9987B2BC91F8A69A640
+:108E200023E2D67F89D05368C3233F3475DDF8B081
+:108E30001EEA3FCED11EA27E0D83DF27B52F87DB32
+:108E4000F14DA5555B501EB08714BACF6943E94771
+:108E50006477343E73E5C4F87CF2C57BEEE7F9C86D
+:108E60003B0D83CE7F5F0E8F0B373EF324F93B4FD4
+:108E700006F931983A35B81EEDD0BA3A1D5A5EACB3
+:108E80003C587B13D90373601E30AF0773387E9A4A
+:108E9000765E1FC0FCF626F84F81575B7D0B695F3D
+:108EA000B0758ED986719CA6D279CB88FEED560D11
+:108EB000E79F0C672CCE6CA573C81BF6186AD08E82
+:108EC000AA00BBE9E7006F41C6F41A2FC8A53C7D94
+:108ED0004FD9B76C18771F5C2FDF92C7ED8036C56E
+:108EE00017F85A39F939597C1E4FD11E6E9FBD961D
+:108EF000C3ED43F9FEB51C6E374E09F44F459A7B1E
+:108F0000568DA4A09DDCC4B40F71FFCB7C360FF945
+:108F100077198FB33B577BC8BF6B7646EEBE98EC94
+:108F20002895E2CC727F71FA19EE17BB22D77F1415
+:108F3000D7B1421FF9E1D7106F77ABC24FCCE54CE8
+:108F4000E1F5B609E8C7B238233FACF150FE0DF9A0
+:108F500025D22F6FA37578D6C9EC889FA9815A5561
+:108F600089D333526E4C1D3887E324FF6915176B84
+:108F70006C04ACD63B6622D1B6CF326376C2A17FF9
+:108F8000CC56F1A5B41F74663FED73AAE7C0BE11BD
+:108F9000E9726DF4A00EFDF5CE7EB21F1B420A8D64
+:108FA000D350FA33CA8F5B2AF2B006F2A1D408E597
+:108FB00087FD3D2745E8C7364E0FAC9FF6C5EC311F
+:108FC0008E7FD09B943716B3E35BF8BD67A23FA3B7
+:108FD000883334083F0E208AEA8DB9C2AE137E8DE5
+:108FE000589E1B1F97A99E8A78BFC3A699A04908BF
+:108FF0002E4F1AC2DB6EF5A5E7025CC7EA7484A2A5
+:1090000063ED2974BFD426A55F437F64A08CE7C5B8
+:1090100026D351891837FD40741AEA93E83343E5A3
+:10902000C5F23CD82D132FA27CF2F23D1F4E43FA1D
+:1090300060358CF8B171CF85E5C58E16EBF1A5E7EB
+:10904000C57A156D073C2FC97524E6C57A39DE65EA
+:109050007C32391FF6744E58E5796B916D0FE3FE43
+:109060007B8F89F23D66EC79E108FA276798598889
+:10907000E2B54976C061E7F55310DF673E7867DBFC
+:109080005D0CF3A29FF2F27392897A7D28BB9E62F7
+:109090001671FBBFEBE4FA7F4976BD94BB4D629F2E
+:1090A000F4BE12FDC1489CDF3EBD7DB0732DB7E418
+:1090B000CA38D710F91CBD83E773C8735F3591E2D6
+:1090C00084F8D382017AFE62F1AC3AD48113CF8D59
+:1090D00067A9223F4B55B808600E9EBF23E3596A2B
+:1090E000CF688A539962F1AC301B249EA58AF8D0D0
+:1090F0003A83564BFE967D260FDF0FFB480EB5F5E3
+:109100006479514E352D39F9041ECD571DD3DCA895
+:10911000FFDB04FEEB2F3C9ED5923BF1DC78D6764C
+:10912000617FBD5DAA0B1B01AFDB1997A3815E199F
+:10913000D7D2D1FE347A4F01C1ADCC3213DC6F3FB0
+:109140006BDA817EA6F9325EF52CF793CD1771A903
+:10915000B7678D243FD250789EDF9EE8F7FF21E26B
+:10916000398BFC78E46FBFFD3F66929F7D21FAE961
+:1091700087C7CE2F30E1AFF3B4F3F3ED9E9D0ADD48
+:109180002F8A64A223DBD24EF78C2E0571B81545C9
+:109190006800A8E62BF05AD12968D778DAA00CC667
+:1091A000BBBA5E0DB8A1DDF62329E41F5CE7F488A5
+:1091B000FC331E3F0E6C54822378BF74AF58A04D11
+:1091C000A7613F3FCFE57EA59773B95FC293741F38
+:1091D000419B41C481C5782D0CD61D9E3A853FD751
+:1091E000897BEB92F121FB6B33349BD14F172DE040
+:1091F000F7939C356A73C87F9C3192EE216A4B6D60
+:109200006EAFE1F5C4B3672D511FD55FAE72C39247
+:10921000793210DE5DB922EF2E09CF0B3A12CBC99D
+:10922000F19BE47353F3997F54CEF073CF15ED4265
+:10923000B909FD9FDD502CD6C54BF1903683E7D799
+:10924000C51407E5F70CB5E473BCE90AF87398A3F5
+:109250009AEE8B037EE1F618E3F00FBBDCA920BF8A
+:10926000B43938DDFEBB7027C3FB9BDC91445F6DD6
+:109270000ECEAF6DEB9520C71787FB42FD1D1F4A31
+:10928000B9F425C9C5B715EF23E162FA8EE443E0CE
+:109290001E03F1DD5E0B3F0F29E51525E8E03E5288
+:1092A000EC5BFF2EF4D6FC136BE9BEA0AD75C3D208
+:1092B00030EE39F57A1BCDA3F1597EDEB66155A4A7
+:1092C00010E9BAB12A32B27910BCE200AA94AFD048
+:1092D0006E9E93F17B67DA13E378C9F1D9B5999A59
+:1092E00005E33FF7EBDEEE7901D7BBC7427AB271F7
+:1092F00055F411F403DC9CE9B7E7017D9CBAF3F562
+:10930000698A873E23BBFCCCBE51744E705E5BE223
+:10931000B92BB631313EC8DA33F8F9B2CEC4F7789A
+:10932000BE28E1BB73E285DC4ED964F48F463BF284
+:109330008AAFF27C880F16EB18AEEB0716BEFE81E3
+:109340007B5285BCF68E8CD707E3F2865A5F68376E
+:1093500016E3F23C0F54B66FC0F58575AD17EBFB05
+:10936000C1935F1989EB7BAAE72B23717D37193AEB
+:1093700034E48F7FBAFC6588AFE357FAC8CE93799F
+:10938000AF174A775ADEFFAE3EBE56E2E50BEA6300
+:10939000FC8BF77F3CFB0F7DC042FA859F338DF934
+:1093A000E14ED27D5B673ED129288F87EAEFBF85EA
+:1093B000DFC96D6601F477545445E8BB8ABFE918EC
+:1093C000DA75D29E4D86DF2FE05F96A7BD9C83F3B2
+:1093D000107EDB3AD1B739F831B79B1F52C82F6BDB
+:1093E000F604D226D33E69C1257A922F3FA7730F88
+:1093F000AC57B1E37E63F1432D547F7ACF7CAAD77B
+:1094000099C361DC5735403D96D74D49CC6336EE64
+:10941000E6711DB98F05385E4038529C5123D267E2
+:1094200023DAC90062A3CAFDD78D4EE60D30B46BB6
+:1094300013F77D323EBBD5C7EF73D9DAABD0BD4E43
+:109440002EA3BF381FD735294EFBFD3CAD3B2F2E39
+:109450005E3ED7A505B0EC34B242C4D3BA3C8ECF41
+:1094600088419EBF4A3C0F7868FF0D640FFD99F953
+:10947000D207CF2B0B26C4D1178A739B0BC5B94DCE
+:1094800094D3E124391D5FAE8FCB2B0B0F961F10A9
+:10949000975716FF5D7C5E5938419E7588730CCBDB
+:1094A000297EDD0474BE72428C0EEB99F8DB1C7DC4
+:1094B0009BCEB1EC34917FAC5EE49536D51DA37D97
+:1094C00047139E8BE1FCA8F173D1DC1EAA87FD1C1B
+:1094D000E5D78612F34F770F2937FEDFF8C17F29D2
+:1094E000E581E047392F398FFA5E85F34F129CC929
+:1094F000FBD8647FB6DC875EB0FFFF7F592E4592B4
+:10950000F0F0AFCAA573E20225D134EF97101778B7
+:10951000CFD3E142D7A0CC036EDFC7F380A7E96DBC
+:109520001A8F43EA799E42723CD6338DE28D32FE29
+:109530006B7E4A1F5C534CEDBD98BFD5B02F95F2A2
+:1095400006EA3C75647727C72197B09E69B8147FF7
+:1095500066AFD039AC7F3BFE9F2FEE09F6B0E22F0D
+:109560001AFFCFE7FBAE0B8A433E67FB38D31F479A
+:109570002F5563C1801F3B747E56413E5FFF14919F
+:1095800027625603CC11F7FD50DF8DC8E7795FCF16
+:1095900089BCA27B5353E81CBEDBC8CF1DB8753C09
+:1095A000FFE9E31CDF2884DFECE1EBF9E3676E649D
+:1095B000788EECC786109D8B0F34D8BCA8C7A4FF4B
+:1095C00048F6DF9EC3E1BA503E9A92FFE5F2D1F928
+:1095D000E4C7B47CE58BC5D136030EE2F82B991FA6
+:1095E00086FA6E28F97263BE6F16A70B6D3CC51F15
+:1095F0002E502EA59483DC463DBDDBE4C1FD03FA6D
+:1096000051483F6ECC91FB6F7E4FC0BD05A4BF3E5D
+:10961000B0F0FD843CC73380BF21F1FDAFD979BFE5
+:1096200073F9EAF3D1BEABD4E81CC0BA54AE5FA262
+:10963000BB781E50F2799664BD22CF63C8F1BEFF9D
+:1096400025D3C31795AB77CBF1FF4DB90A7A96F6C0
+:109650002F43C65BCFF93E20F231FB3591F742E74D
+:109660001A245C4DFD3C7FEE47827EE5FBEF09FD51
+:109670001BC9D7BA90AE4EFDC16CC67866793997D2
+:109680009F8D3E1BC5031A433C4FA67115A37DBF9A
+:109690003CB73AC6ED7F04D76FDDEB36BA87B471BD
+:1096A000CFF6F6619447E027FBEEF41FF8FB37B2E4
+:1096B000FD8F62BBA6559184B843C5671FAFAD2926
+:1096C000277869DFEE34259E077A259FEFC7E5F3FB
+:1096D000C501FCC2FE04BE3B55C7F3B59B9C9ABDB9
+:1096E00092F207B85F3BC5D34F7EA0C6DDA4241815
+:1096F000258F62FD77F3896E1A775796D17D002109
+:109700004B19DD27F306BF7FE9D49DB9413DF783AF
+:10971000EF477853CB8357A39D5904E3A0497AAA16
+:10972000E7EA32F20F26F19DE4B78173A0B7988380
+:10973000AD4A8C1F3719B89E94FAAD27DFC3FDCE12
+:109740004E9107D83B932DB0C5CA3667627EE4B20E
+:10975000BC2B7B707D7AF25511BFE6F1F26233ECDF
+:109760003E879D4B87C5225E3E53E439B0803996D3
+:10977000DF30ECFCF172099F2CCB7879CA27E2BE6E
+:109780007FBB91E822B59DCB0D06748176F6946877
+:10979000FF543C7F55D2199E82F84A47F453BE6964
+:1097A000E4EE8B310E91A94EC138C4B695130E600C
+:1097B0007C545DDF7F392E8DA7C35E855BCC316E17
+:1097C000DFE97CB2079B4B91FEAB7E6BE07989EBC6
+:1097D0005348DF7716D6535EE2E9D74D09E76D921D
+:1097E0009F01B6C68D7EA361EDBFA13840EA6E65CC
+:1097F000D07CD371053691B7B8C68D7EA8D4F6FE5D
+:10980000C024F4ABDCA3F0BB1C017AC58DFB7F55F3
+:109810008776C7FC3DFCFCF6FC0E479599E4A9C28F
+:10982000E328539C2427D5F5D7E8709FA6B630BA15
+:1098300037ADA480DF9B3AA2D3AEC375FFE5A7FA8C
+:1098400041E3639905B13C37445783297AD05D1CC5
+:109850008BEBC9FCB6A1EE2397FA28D99E3DC78EA3
+:1098600015FA68C09E4FA2E3A1BE93F42DE9F997C3
+:10987000064676D82F15339DEB9274DD26F3F53F1F
+:10988000E57EDD229137736CC3DFC7F373EB322EB5
+:1098900012E4F7711A226BF3085F91AF0670DEBB1A
+:1098A0001DBAC6B1E40F6BA47ED6F3FBCE8ADA876D
+:1098B000AF99548E4F3B530084637B9716215F060C
+:1098C000800E460C42071FE5F37327EAFA145A3755
+:1098D000F53EBAE999A90E17AD9B7A3F5F9F53F900
+:1098E0007C3E322E2BFD96917C7F55C1C4B87358B7
+:1098F0002BADFC1C9638E79BBAF2F5C7F17CD3364A
+:10990000E13F3EF0EC18FA9D86B3EB5505EDD4B37C
+:109910008E5AFA5DA26B0BB8BD94AAF633BB2D9E8E
+:109920003E0F507EECB07D3CCF4F15E798D5F5CE7D
+:10993000ED88CFAF3AFD94077C795B987ECAE059F9
+:10994000FB718AB7815D44E7554F3EA348BB284170
+:109950001FCA7D5BF27EACB6E07FD64EAA2F48F4DC
+:109960007B5CF03E8B25EE3707DACBFD63F27E227F
+:10997000E9FBA1EC1FA60512F25D568B3C68A9DF3E
+:1099800073856C94793003E79659D082E71EF29183
+:109990002927C6F28198C813DAAC58BD682F0D95F7
+:1099A0000F3490AFC39A2FE6FEC8E6AFE053E6133C
+:1099B000C97C210BE68D649E9B3762C1BC914CFC37
+:1099C0003D0B7EFE59E67DB41A3C944712F81EA367
+:1099D00078A032AB86FC75193E23D1DF1916DC82E4
+:1099E000F7B90766DBE89C379E0B42BA8F2A6EEA0E
+:1099F000776A8D26DBEBB0FDC0BD80B58CEA334ABB
+:109A0000B41CB4C32C508FF7150F9C7B5EC0EF4F76
+:109A10004FCE1B91F94B329E9B3BEA2905FDA2E8F4
+:109A2000F6A73C826F89EF8A793F9DDFF490DC7066
+:109A3000B5F2FCA4E8A5CC8E7EF92A297FCC89EB6F
+:109A4000BA49F117237F6EB2F273FFDDCCDBAE872C
+:109A5000F21D05C3B85F8779F6EB486077D0EF2F2A
+:109A6000743AB5A70AB262F424E1629BF9BCCFE074
+:109A7000392F2536DE99C57F2B44FBAAAAD7C4E926
+:109A80003269FCAD03F7AE042DA84F5E2E6044672B
+:109A9000DE247B573E5F96FC26E4B21C7FA8F94982
+:109AA000FA3C9F1D2FE96F287A0B5489757A2B8514
+:109AB000EC0F496F0756EFA47B01FB5687E879C688
+:109AC000A284F4783ED6129D8B92B17FDB9FAEC309
+:109AD0007B39CEA4460BF15E8F377FFCD7AFE1BD5B
+:109AE0001D67B2A26F61F954E1381FD58F886EC32C
+:109AF0007B3E743FEEE1F5B89EB960BF173CF2B50E
+:109B0000808DEEC95ADB8F7AAB3C291F25E93E8256
+:109B100014F17B3ED93623D993D922AEC7AA855DED
+:109B2000CFF8EFA2B5E694511CCFC63CBBFBB13ECB
+:109B3000DFC4EF2D6040FF583FA298E735303E6FFD
+:109B4000962FFCD32C12A0DFE72B76D0F703727C84
+:109B5000B749C4A7F8F8879FE47144999FCB98BD93
+:109B600000ED219B872594E57D1E4CB517E0F9FD9E
+:109B700056E9F713E52753FCC6C238BD7CF8CA3B4B
+:109B8000C6D2EF843CF5DD12949B571913EF59961A
+:109B9000CFE78B389D9C11F70936A5F8D30B61DD13
+:109BA0008FA4CC9D8657C3CEC9AC343AC87EDBA502
+:109BB00047399525E8C3319BC3E7A8F629F8FB1C74
+:109BC000F23EBF2CBF4A7E02E6EFD4A35ECD3AEE52
+:109BD000A3BCBF7A73B4107F47E505B33F0FE13CE8
+:109BE0005B7BF4768A17E61E7E0BF3340E1B3AA6D7
+:109BF000A6A11E2916F742604016CA07F38A683FDD
+:109C000038201F462814CF9C319B9F5F9DCE422A4F
+:109C1000AEF3343B3F4F35ADBCD8DB0AE3CD107912
+:109C20001ED38EF8D250BE4DBB31A2F27B2BA26A5E
+:109C30007C5E857C32B7C113CF0F577BE2CA0CEF35
+:109C40001D4E2C5FEB4D2C7F6DD2A7A3E2CBE3140E
+:109C5000AD02E7F90B45DCFF00F285CF8BE70F3E45
+:109C60002AF67363DCCC5C84F98D4E2580FB85314C
+:109C70004FE7529CE5E9498CCAAE9DE61DE6F8F92E
+:109C8000DFA7E37168E10797BF338475A86F9FFA78
+:109C9000838BF0E5B281BC7592F4217A3B20F8F613
+:109CA00080E0D38A3CB315E5FF0183A78BE83CD560
+:109CB000EC413FD5FE5423DDE3DABA8CFF4E8192AE
+:109CC000666646E8573F8F97A11DD80650AE3053C1
+:109CD0005EC801916FDDFA3D95FC5C588FF7EBEAA9
+:109CE0007F6025FF76755AE937B05E9F66A4F30E54
+:109CF000FB532BFC623CBA5FFEA15473187FEF202C
+:109D0000F93ECDC30817E20DE07A98C341FCA8AF35
+:109D100030921D2ECF9F433F147FD3E79A69BC0337
+:109D20000EFB7EA4BBD6F7C8D283FA491ECCE392C1
+:109D3000F45D9D36897E3F04B8AF24FEBE74BDCB72
+:109D4000EBE1E766F9EF62940EFC4E060C0BEDF0CA
+:109D5000378518F12D8FE71548BC3355C3F6394CBC
+:109D600096F9B931D740B952A5FB7F14596EA1F2CB
+:109D700003A25EDEFF79A890CB29A5F785BF22DD7F
+:109D800096A4015E609DBC29839F5B7AA090F3ED51
+:109D9000B9EB57E146BFBF82F31C1B9BFF0187D77E
+:109DA000ED8B2B0FB22E41A4B7E4753960F17AD058
+:109DB000CF76FEFE385EE53CF4B91C9F03F3C81C69
+:109DC0007C1E87C43C42E29C7572FDEE426EBF7EF3
+:109DD00089F31C94FEFEE579BA12E7F925C2195100
+:109DE000BE0438F585009F2D061FFD0C5805CA4D91
+:109DF0004E7FD3459E322B4DCC4B6293BC666E2F6B
+:109E000026E6215DA574B5A17E7D40C4B95F107CB6
+:109E10007530E5FB25686FBD3077641FC9DBF496AC
+:109E200036642E299FA5FC3F9B73B402CBA007DEAE
+:109E3000443D73FBB0C373B1F33EC70325A8AF40E5
+:109E40006EFEB170E2B9704AFE1D8017F817F9482E
+:109E5000F26F32FC928FD875214ACCEC66617ABAE7
+:109E600019CF8307BB84EE2B679E82D8FC80C9A7DD
+:109E7000999BF93C5A0204F7558E1F52FEDF598F09
+:109E8000FF23846BCEC51FD27D48CC5D3B0AF5080D
+:109E9000C0FBF1FF26BC209F72F0BDB4F393EDFA36
+:109EA000F3E5834B3893E5A1844799B593ECF82605
+:109EB000B0E379BEB842F2BEA94EC7E5F01E85EC0C
+:109EC000FA46D033A8A7E4FDBA578CB4B6E1BD8FEB
+:109ED0007B0DDC9F1A78D2E449BC2729396F5CECF2
+:109EE000275631B95FE0F74134D8F93D4842CF7485
+:109EF0007E7B98BC2789EB43D05309F724D57A128F
+:109F0000EF491A62BF00FB02B2CF58BA4EEC0BB851
+:109F10009EEEBCD4630F30F23FF3DF7BBCC928EC6C
+:109F200041C0852B768F1BEC03E87EBAAF14158BEE
+:109F30007BB282FCF73584FD9FEC8FFEA7CB3FB947
+:109F400008E87DC158AD107FEA65BE91FB9B81DEBC
+:109F5000BAFA19A63F363F84F7955ECD9A5FD30DC6
+:109F6000277AD3B0FD9C311FF27B4C63F456599491
+:109F7000C5F5122A99F3F1F161A77F7AD144C45F44
+:109F8000E80DBCCF7C6BAF89F02DF34B93F93B0E02
+:109F90009EE3060E8F53AF2778660D06CF85D07DE2
+:109FA0003C5D65334EDF43D13F9EE3489D10A3FFE8
+:109FB000718ABF16C71DE083B57CDF750EDC7A1B86
+:109FC000ADF70D37F1B85C538ADC276B33725CE870
+:109FD00087E4E3DFB09ED3C50DB53C8F68666F03A1
+:109FE000C5E158358FAB79E17F08CF0121DF663BB2
+:109FF000CB0C487A7F66DF30A09F73F68CC4F8DB09
+:10A000001CF35514EFBB61B621E1F72A251EE68843
+:10A01000DFC39E93F43B95C978498EDB0DC80331AD
+:10A02000DF3CFCFD1678E6337E7E2647FCAE585BAF
+:10A03000D1C0F9DE515F30BE7777D11788EFF519BF
+:10A04000A2744FC3F3598BBA9601DF8CFAD158BA78
+:10A050007FFD4AD7E287EE83F24FB65E44E5E75DC7
+:10A06000B7AC388CF5DB4652B95AF7E15CE483D2E1
+:10A070008A9BA6E37DF57D16DE8FDBEAEFC4DF3138
+:10A08000718F1F3601F380AB8D516A77CDC50D9767
+:10A09000603E54B595975F29FBFD042A0F13E5092F
+:10A0A000BFB808CB7DCA8773078B0F8E2955C2F8BE
+:10A0B0007B65D519BCFD8C09BB72D15F545DC5CBE6
+:10A0C00063BC95EB8763BDEEA3B983D923CF140995
+:10A0D000BF91B0AF7D82DF9FD68EB6E179409F4DB4
+:10A0E000F1E2B90FDFA4A3FC7E3433CF2BF1696515
+:10A0F0002ADE9F59A5713FEF545B4B0ECAC5EBFC9E
+:10A10000C672F4E7DB6DC56D6817A74FAA9C88EB94
+:10A110003DD5CC889E80AFF6E13ACCF9CA878569F7
+:10A1200048CCB644BE92743B53F2537522DF803C58
+:10A13000788ECB83447E807E0F11BF5E96A8AF06DB
+:10A14000E47D12DF26D3E39076014B9483313A0D00
+:10A1500029F1F4D98DFCCAF9F70F088751D7EFC15F
+:10A16000F7458AF7224AB419C2BE90F0A1DB924D9E
+:10A1700038172EFC53A53DCE21B0DB5D382EAF87BE
+:10A18000EF34FC713909178CFF1EE1672D87A75B3F
+:10A190006916BF57C2F761D2DFD128E7BB2771BE6E
+:10A1A00015567E7F811BFD3D14C329BBE8F3E06E8D
+:10A1B00012FA77B6D9778F09E6F075C77C5AE71B94
+:10A1C00041033A60FEBB52FC7F4778F4BAC0BE88B8
+:10A1D00082BF37A2513E0CACE33FF83AF275917062
+:10A1E00025E3E3FF02863CEC3E0080000000000017
+:10A1F0001F8B080000000000000BE57D097C54D592
+:10A20000D5F87DF3664B324926098484409824644E
+:10A21000830426611164712004A3020E8B028AF864
+:10A22000C21AB20B5D624B9B81B0A9684345A5166B
+:10A23000754040B0408302A2463A2C2A56ADA94B45
+:10A24000EBD2F22548658718AAE2576BFFE79C7BA3
+:10A250006F66DE4B52A45FBFDFAFDFEF0FB597FB3A
+:10A26000EE7ECEB9E79EEDDEA9B43B02EA00C698C9
+:10A2700087F5ED16CF9802FF642EF8EF80E57C732A
+:10A2800016A33FFF4865ACB7096AC44279E3EB5FA8
+:10A290002B587F5583C2D218EBC59A12314D64D525
+:10A2A000944F60EE35AA8AAD7AC57CD69F31FCE723
+:10A2B0003F6E60AC2E12FED18DB1D63C9B7F330E2B
+:10A2C0006286FF0633F6567186FF7EC85FB238D6C7
+:10A2D00028D19057589619EAF99470F7D614C6BE4B
+:10A2E0000A8B1AC0E07BB7704807323662CE0F2661
+:10A2F000B1A88EF3ADB1F37A3F0C8FDA8CE90D196A
+:10A30000E12B4CD1D83ED98FF5BB85433A2038FF9D
+:10A31000AF4C4CB3C37C7FA8C23A545C47EB32339A
+:10A320008CF704ABA7FC68172C7A08633DDAD7E3F7
+:10A3300053BCB98C594DCADD5E07AC09FFDC104C2B
+:10A3400047BB4C8C752770290CE65529E1E85298DB
+:10A350001DF27344BE52C0BB9BD5D50BFB31C279F5
+:10A360008EDDD642F05D53E869B607BFB3FAC73C4D
+:10A37000A1FD74554F01B826C576843FCC9FE637C2
+:10A38000B1A6C07B320EC717F8B83792F031F1DEB4
+:10A3900031F45D9992A534C3BC0A8A5C94C60EFE62
+:10A3A000BD99E5125E6634E404F174B2BB76B30B7A
+:10A3B000D76B6E1E321970FBF69067F234283F6E31
+:10A3C000622558CF089FDB113E433AC247C2C308FB
+:10A3D00087AEE6BF2FC23BC305FD5C509A8662A1E3
+:10A3E000BDA753C05D4B41FCC43853C6C420DCBF7D
+:10A3F00081718732360D8B00CF0FC66B1AB69BCE9C
+:10A40000BC8566586F6C9166D11C349C09E7B3D843
+:10A41000C9E753A83A882EDB762A7E1BD41BE7C9EE
+:10A420007E6C24E4AB8E59981FCADB18A7DBB68D6F
+:10A43000AADF07F4B2F08DE78706E0D3A7824E3398
+:10A440003798984BE203FECBF68733575630DF7FC1
+:10A450007BAC2E9FDBD053577FE081545D795EA0AB
+:10A460009FAE7CD0B17C5D7E48D3F5BAFAD77D38FB
+:10A4700056971FDE7CB3AEFE88D35374F951AD7787
+:10A48000E8EAD785C1FE1988E0F63465015CE60983
+:10A490003CDD70658EAEDDB9A8F1C7705FCD5BBBEA
+:10A4A0007002EEAB31AC4CD70FABB79C40BAAC8668
+:10A4B000BF88CF05CC1B1D007815B2D6D792007E81
+:10A4C000957EC58D705BB881D793ED161DB8676C0E
+:10A4D0000CA67EFDF732660EE6A19F9A3F6DFAED5F
+:10A4E000D190F271CE6213D2DF465764B7CF2210FB
+:10A4F00010ECBA7FA89DE2D71D40FCBDAFBA6DF04D
+:10A5000069F11B2AED83C5BB143F837E33587A342F
+:10A51000E6AB8EA9CC0FF83FC5AA1F1D09E957B5B8
+:10A52000FEDF1E4D0FC2C796A0C773984B8FE788FA
+:10A530002C3D9E23DD7A3C470FD3E339C6A3C77376
+:10A540005C911ECFDDBD7A3CF798A1C773A2A6C768
+:10A550007352891ECFBDABF578EE53A3C7678AAFA0
+:10A56000548F3F03FE25FF4D5BB35857AF9D0EBC84
+:10A570002513304DAFFF91AEDF32B5DC0A1868A766
+:10A58000071FFC457AC864CC1D003857021E02AE76
+:10A590008E7450D2B86E55D2BF40077F42FCF70F81
+:10A5A000C1BF3A2B5AEB845FCB54E23557F19C4044
+:10A5B0007EF6A54BFB0BA633323F4F3603DF60DE42
+:10A5C000E24C6F6490EF3116606C68907FF5C6B511
+:10A5D000E5333A8FCC4383E751577CADC3393A49D1
+:10A5E0009E3F5D9CA3AEDE413E0800F988F95E699E
+:10A5F000A641D69A701E33055D1F0EE77479198B3C
+:10A6000086433DA8330CE6F511CE1BC6F928BCFFE6
+:10A6100051DCA777B0060BF63F8B35513A9BB5520C
+:10A62000AA31A715D339CC4DE93CE6A5F475BB6634
+:10A630004B017894DB9B873298FF97C5BF3FAEE014
+:10A6400064DE8AC3C9760957C9AFDFC37F42BD91B3
+:10A6500029DEE814E0BFE3ECAEEF3D029F0EE339E4
+:10A6600081FC77421CCD9799BDB953723BEB67399A
+:10A670009D1B2F2B9A867CD79768776F85B5F54FF2
+:10A6800062F6443CE712FCA953003FC929FAF3B72C
+:10A690009FA0895D3D1B16C7201E993F16CF876B73
+:10A6A0001DB75F8A271DD72FEB5F6DBD566BC33D6E
+:10A6B00038CFD60A877B33D0E7FB021F4FDF6E0B04
+:10A6C000A851413AFA3062F66BDD016F5511DA207C
+:10A6D000EC7FC6F49B56615E391CE75A0CF3BB5401
+:10A6E0000CF0E6F0BF8EC35FEB130F4BBCD05BCB1F
+:10A6F0008C46F87B39FCE11FB9DE4EE7CFE753A06B
+:10A70000F0F1F745681EECE7B0A929D98DF0303794
+:10A710000DC576CCD19DFAB960E570E90A0E6323C8
+:10A720007ACFC275CDB3D9DC2AF43956E1783D1918
+:10A7300077F7EC2AF8E77C93373EA0EAE63D09F18B
+:10A740005DEE2CEE93087473C122E66DEF2EE0EE01
+:10A75000CAC17DD5D5BCEBB07F94037FA2F8510E62
+:10A76000A43F907FC117E3BF1FF236D3E5F7A7A23E
+:10A77000FC926B726F86A28DE1D035D0FB3B02DE7E
+:10A780004F58201F4BDFD7E0F78470DE3EE1519336
+:10A79000BF0EDA7BC7BE48787ABAD241EB29662E63
+:10A7A0002B6EB2B9CC4374FF97317F7BA519F05162
+:10A7B0009EA22D44B8DD1D674A7E9FE6A1F547792C
+:10A7C000878DFC6EF42FF7E914275FC27C01B7A9CF
+:10A7D000CC43FBEE36A65970DC772F5A3DC83FDFDD
+:10A7E00015FC643AF3D1F799CC4FE99D2C40F5EF75
+:10A7F00062CD94FF7DC480DE3530BFC98F65A6234E
+:10A800007F0D81FB4F08EE76EDEE6E9C5E4EF540BF
+:10A81000B8AFEFFE9DE877B2A017D8AF2B71DDB0CF
+:10A820005F07E7A586EC9B719C5E98D999FECFF6F1
+:10A830004D531B3F2F80313A1261FD370A14DEE879
+:10A8400029A37302E5AC6E00FF26974A7256D19891
+:10A850001633CE7FDBE79C8FBDBE8C45FAA0FCF59E
+:10A86000312A437C4DDA30FE0CB67B8B05BA0D865F
+:10A87000FA8557B4A3D1B0FE49C0DF8123B3A25EED
+:10A88000704E849C4B3727AC1B8772C4CD7DF5DF9F
+:10A890006F61F52AC26F428EFE5C9984E78AAC072D
+:10A8A000E31D4238C4763C5FB6A708F9A21FEB77D8
+:10A8B0002DE74BA5C9F36BE223406748F773CCCC77
+:10A8C000D3D97E73642A928F91DC72AB18BB6DC2B0
+:10A8D00065EB2558EFA914ED25EC67F1C4BFCC4614
+:10A8E0007E0C7AD4DB83F01CFD9DCAEE87F213B593
+:10A8F0000071385C4FD6DA9907049CCF6A9D943F6B
+:10A900005D9B40E9D95A17A5E76BB3A8FC62AD9BE4
+:10A91000F251A9DE23D8EF9C359F9B518E5A1D26FC
+:10A92000F1C7E7B144D0EFEA30AE472D895CF26160
+:10A93000318CBB840E4038AF1BEAC723584A0F3412
+:10A94000BC86297C571D58BE4E71E3F934FFA8B66A
+:10A950000AC967E15BCD9390ED0CF9E0643CC2ADB0
+:10A96000E28AC234D84A3F48F7BC8BE39FAA1D460F
+:10A97000F33A53EBA179791A5B5E8B83F6E76A8B26
+:10A98000289F99EAFD10E9DBC33EB762FB893B5B78
+:10A99000CC49505EE8513CB8BF477B98DF0FF8DBED
+:10A9A00060E1E7C506382F907EC6E44E79E27B88E9
+:10A9B000B614ED048E735BECDCC238A4AB61C566E3
+:10A9C000AC37FD1B90B95282F47DB57D72E1A04297
+:10A9D000F0B9703086E021E15421F075617FFF5BB2
+:10A9E0004740BF07418E54617E6D574C34BFB60F50
+:10A9F000C3FD282418DB2FDE97D68339709DD0D86D
+:10AA000086F9FE3D18E021C2FEF413A8979DDBF500
+:10AA1000C304C4CBB9D8862F3F46BEF767CEF7181C
+:10AA20006BF8EC71E48BBD12DCF743EEA205F43455
+:10AA3000D26BAA23F05CACB4328DE7B5FE983F1719
+:10AA4000CE487F1DBA3B692CEE271CCF9519E46BCD
+:10AA5000598A8BD500DD67EC7E2CF5C730EFED0D04
+:10AA6000F33F7E1CD20B7E93CF02E7D605D670F162
+:10AA700025E4CB5B1CEEAD0CEB9BC3B1FE03163E95
+:10AA80002FDF56D0DB5DD89F9FF800945BB1BCFCF4
+:10AA9000B95FF4C4F9BF8C7209E45F5E1741FCEE44
+:10AAA000658BFB780DB67B82F7F7CC43F79E388039
+:10AAB000E98315F9F742DA273596E03DEFE78BFA9F
+:10AAC000617B38F75922F0C75FBDA004C2006EB9A0
+:10AAD000EB0F2D4F84F1066E6C31F584346F8B5281
+:10AAE0008769FFDE45C7F0BC4D4F75D13C06ED4C84
+:10AAF00051519EECD7D3FFF10D240FE8E5849CF56E
+:10AB00009F8FEDC982F2423FA5E1EC32A087D5BD0F
+:10AB1000FF90CFF5C47AEA675FE3D4F7EE64B80E2E
+:10AB2000904470DEC556B253E0722D90BFB0376DC1
+:10AB300013DA33F69B7C9BE8FC9AC3E5950B5EDF4A
+:10AB40002F90CE2AA0BE0FF21579BEA8EBA1BCE2D1
+:10AB5000CF7DDD4051ACF7933716213C2AF73E32CA
+:10AB6000BE27D4BB3092B90115AC64DFE5F1D88EB5
+:10AB7000F586B5603F7BEBE2EF80760FE48C1D82BB
+:10AB800074E5551B681C56C5C7794C9C7BAC198075
+:10AB9000132F5809D47B003EE3F7D8C69843492CBD
+:10ABA000889FAAC66529686F19ACD9DD2AEE9B1467
+:10ABB0005F62B523788EC2F977632AD44BB48A7E5C
+:10ABC0009D5393BDD770FE59C57926FB7BCCCA7CBB
+:10ABD00061B15C6E56F07CB6F2737B2BF0979AFCF9
+:10ABE000E0B90DE34E4FE5ED495E4E82433A0FE684
+:10ABF00099F498CD4FB2C1771C5FCA5B55427F91E3
+:10AC000072CB8CB8BA579A61BD8F456873717DF36A
+:10AC1000C5B9CFCC6E17CA453F8DF0CC4B25B9AB2B
+:10AC20003519D700E76A09E62B5590C3D242E430C4
+:10AC3000FB773B577744782AB1FD77AD6FE4BB4B88
+:10AC4000BE30B13CA083258FD8484FAD13F6863A6D
+:10AC500061DFAA8B1C6A477EC18E9ACA5F83F37636
+:10AC600014EFA1BDDF2591F9C44FEA18EB146E076C
+:10AC7000810F68C07702706E68C00F465F695539F2
+:10AC8000DD371D891E8CFC9679225D680730312DD9
+:10AC9000E43C35F603787B08E1398645302DE4DC69
+:10ACA000F4B0182BEE5FE688FD97D63F52E04FAE2A
+:10ACB00063A4B0E78D6CFB3002F9E6922FF2897F36
+:10ACC00076B5BE57C4FA7E83EB83D492E9DD84F86F
+:10ACD00018F557A719D739CA3C3919E51C98FF331D
+:10ACE000F87DF45F4DFAF97F13AECB7FD7757C5FAB
+:10ACF000613E13EECFCFAD7EDC9F8D40DFB89F1B52
+:10AD000017E5F8910FEC87FD6047BD668A95E4DC96
+:10AD10004661276DECEE24FBD2CB169EF7CD14EDE9
+:10AD2000C3189D238D337B52FB9EB6EA3773B1FF68
+:10AD3000BA08E29F8D16FF9A54ECFF27716E1FE050
+:10AD40004BC5F36310E81B827FD7590277AAD8DF7F
+:10AD5000E75686E3AD8F09245541FDF58B7A52FD08
+:10AD60000F419442FBDD0893E9EEC90E2CF724C68F
+:10AD7000427EFFB72A9D1BEBF320EF203E4EF6C02C
+:10AD8000F5933D89E1DD308D37D17C54564DDF534D
+:10AD900078BB8F2DBCDE1D027F1F09FCC03E273E05
+:10ADA000A04D8A30231D5F4C9DD342FB8379121541
+:10ADB00098CFE3F3D219F2D13B4A6F4A21BAA97F67
+:10ADC0008CF8D90C8103D91F36B00F45399AFF99F9
+:10ADD000397F6B18E2F3B69230B28F7E58B23CD214
+:10ADE00005ED6FD3D4800DEDC6D30A3DA1FAF8C5A9
+:10ADF000540F8D5BD1909D763284AEE7D8806F4042
+:10AE0000FF6BC2B5D348CFEC401E951F00E1E61F93
+:10AE1000B0AF4ECC4BDF4D768D79528F0CCC45BC0C
+:10AE20001E6CB533D44FBAA2873AC403F4DB479CF7
+:10AE3000EB44AF88FF19E15CCF3103BD40BEAE21CA
+:10AE40009BF49CA72CCCA320BEF6D908FF4553EC5D
+:10AE50001EB23FCE08DF6483F2BB053FAB9B114EB1
+:10AE6000DFEB5E89F49B14D29F28EFDB63A176E5CC
+:10AE700056FF8E6DD04FF9C16C3A6FF65BC5B82F97
+:10AE800045F0F2284FCACAC158DE83E8E0658B2B33
+:10AE90009ACADF50199587073262008E91615A581D
+:10AEA000DA10A43BC0B303FBE5DF8F0BFA3A0EDDEB
+:10AEB00022FE7CD591D42F6D7DC86B75BD37233EA6
+:10AEC000352B2F673F52A9FCB8D393381FF2C7AB7D
+:10AED00093685ED2CE74DC6B25BA3F5EAE90BCF454
+:10AEE000A71A35600DB5E34FD97E5F06B4FBF4A019
+:10AEF00085EC78B37E56F6167E9FB5BC82EC91B396
+:10AF00004A97929FE0E2D24F876E80F5342FFF245C
+:10AF1000590BB14BCF2A8756A176D5344F6A1AE028
+:10AF2000E7D6342D1DD75795D3BC00E5EB8BD6A6BD
+:10AF300027515F7075D3B2F0FBA5174F6DE37277A1
+:10AF40006B069E1395664E27F2BCAD1274F85F69CE
+:10AF5000DA00EC0FE0361BCF95889C26CEFF967E5C
+:10AF600037FE7FB671EB7E05C6290B6FACA454F596
+:10AF70000FC07ECE298128258DE0A8E1BE3AEF0CD6
+:10AF80004421FC351397F3CAB6EBD7857FCCF16823
+:10AF9000376364072F6B503D61B80F98DF8AF32F3A
+:10AFA00063D660FD9420BEA01FC21773FC69F68FA4
+:10AFB000010FA53BB2F351BF288B39F0D008AA0787
+:10AFC000EDE47E513BE6E57A3ACE87AFEFBCD80799
+:10AFD000E7E18B05E965A74DEAF934FEC5177BD09B
+:10AFE000F8F1629F5C5404BDEE08E374E58675E1F8
+:10AFF0003C7FCDE9EA51C92777F07ECAE27C26E49E
+:10B000004B65B54EA22BC997602EB4BFCEED4EA2B4
+:10B0100076928F312F63547F77E2662EBF097D17BA
+:10B02000270CF54B7FC5C7C13CF2F3B3CF26C971DE
+:10B0300049DE369EC7C6752F49E3F62938A77BFC43
+:10B04000337D312B61EE13F30685AC27D22AF882CB
+:10B050003B61722EFA17ACBA7E2F465AEFF638D003
+:10B06000CFA0FF2EFBAB4DE3FA641F039E7BAAAD7E
+:10B07000876CB80F9F66746E18E7B14AB47BF6D937
+:10B0800076BCAAC29ECE5C929E5C5C9E27FC7D64D0
+:10B0900095F8FB5E12F0E33284556A108EFBF3B430
+:10B0A000243C372E0AFFD0FE18C8E7A03CC5F12289
+:10B0B000F3121F46BA5CFED18224F4473D2FE168AB
+:10B0C00080F732802B96D75940BFC9413DF7D8C38E
+:10B0D00027D383EBF9ACD6E39917925FB021CF8EDB
+:10B0E000FB71E1C63CFB9C107CD46D1F74CC0570D9
+:10B0F0003FBFDDEC46F65E67F63F84727ADD76B5DB
+:10B1000001E908CAED08EFF38EC3BFC37A0B36C658
+:10B11000E4A31C2EDB2FDC50E899178287FEDBF5B9
+:10B1200078C96DD0E7071ED0E75F4119B4FBB5B70A
+:10B13000CB0BE8F3838EE9F3AC15B03714E5018E41
+:10B14000B71786B98FB9006F7DFCAA1B3FF5714C0C
+:10B15000993A11E5888DAA3B1DCAFB2CF5DE827257
+:10B16000C5E98DF3DD88F612D557F963C069C927A3
+:10B17000E38FE1B97A8E35FC6122E06541E33AABB9
+:10B18000D985EBD6D3FB7E93A0DF67B9FD6E915FC7
+:10B190005FDE912F2C93FEC1AC50FA32D2018C7B32
+:10B1A000BB0726545EF3DEC3C8174A2600E1039DA1
+:10B1B0000D6F586745F9EFEAE3F8B87CE9F0B8108D
+:10B1C0001EC5C378D9F53505EC53D8776CEDEFC7BC
+:10B1D000E3BC8B1F5048FE287E3EF328D257CB9EFF
+:10B1E0009937537A7B11AD5FDA0917362A8148C83F
+:10B1F0003B87B90E3443BBF97E6EEF98B3C216E4B9
+:10B20000870CFD648679AC0F2987F92F3C70E86BB9
+:10B2100005FA2FD9A86FB708F8349E3FA55BFE61E9
+:10B220000BFD2EF5D1EB1B37A9B8EEF962FEF2FC4F
+:10B2300064BED1E4A7B89E376127F1FFE0DC991D19
+:10B24000AF297DBB07CFD1EBD7F3F6C0768B71DD8D
+:10B25000150EAB0BD75D6167810898CFB148ABC7BE
+:10B2600009DF2F6F88243BDD021BC8ABF994B23095
+:10B27000F47B3037F9CB3E7B4725B9A7228EE3BD5F
+:10B28000E22985F4B40A34AE62FE699E5FC402B45A
+:10B290001EA4174FE83AFDFA3CABE7FA5DB93970E6
+:10B2A00008E152CA9AB97E06F8F484F8BBCB619DD6
+:10B2B0001FC6A2FC6668CFDC1AF9F11C5C1EAB3A13
+:10B2C000F00F5B68B9D433A51E2CEDC74F6578C36A
+:10B2D000711C8B909BD7DFE7C9C0F9AEB4783210F0
+:10B2E0000EBE7561A4EFDFB1899F5FEB63408EED09
+:10B2F00046F233C9E377285C3E6733393F1C617AF5
+:10B300002E80E74DEB2331EECD2EAA4FE7D8FA077A
+:10B31000B3B9FCFFAD4AF250EB3A1E17B13E8FC3F2
+:10B320006FFD83B95CFE97E75E7746FD7594B73D88
+:10B33000196887600FF3797D8C4B0A91AFBF8DD769
+:10B340006EE81BB23E2997B392EFE6CFD82AE234DB
+:10B350005AD785F9D19F7152F1BE660A916FBD7DB2
+:10B36000F9393174AC679BA8477E8F79A6C9F7DF9E
+:10B3700000F39AF7A8C985F6B776787B3C19787EF2
+:10B380009E5C17968F7436742CB7471DCFE37C3FB5
+:10B390006230F3F8219D29FA9DD9D7A44B13C281BD
+:10B3A000FEA09F9385DC1E1E39D84B76C0AD2ECEF5
+:10B3B000F78DEB982FFA9967F5FE765427F3917085
+:10B3C00061E3B8DC71F21E65339F17E01BF2437F27
+:10B3D0001E46F6C393E25C92F005BAA1B807C9B75E
+:10B3E00062DAE9C5BF230CE8659D85D381D4DB42D1
+:10B3F000E845E0BF37E1F70E815FF66098A01713CC
+:10B40000FB6F8463A193D3C335EA5F80EF9F20BEB7
+:10B410008D7A98C43733FB87FC33BF4BC50BBBF623
+:10B42000FB40CE28FDF523510CEA9D31D7C7BBA1C7
+:10B430007DF9D695511E484F9B7D514E18FF8C5F6C
+:10B440002DF27702EF97FB4AFBB5C7A184F849CFED
+:10B450003EFBC0245CE7975B2D4E640955DB6DA471
+:10B460008F55EE5D44F23AE45B787EF5E7E837AD60
+:10B470003AA0B7CF973EF348BC8BE0ED4B32256046
+:10B480001A486290566EB1B4FB91611890BF5B5739
+:10B49000E1FC8CED711E5700DF550D6AB135BA63C2
+:10B4A0007995E02F557B1FF81CED86557B6F3A850B
+:10B4B000FCBECAE0172811FE11A35FE0577DF571AD
+:10B4C00007001F8A33F0C1BCD2895CB85DB96EC772
+:10B4D00063035A507ED8F266949213F40F48BF4922
+:10B4E0005BC3DCA75E7275BD2F2F0AFB70106F9CCB
+:10B4F0007FB90E2818AC048A3F4FCB2D81A811A824
+:10B50000EF6DB290FC5BBEEBE96D8F239D7D64A374
+:10B51000F3BD6CD7AB7FB81EE5E73D966E13F832EE
+:10B520001C4A485C4E958BDBE3247E4A9F7FD5EA1C
+:10B53000CAE5DF97C606F154B6E79015E3838CF0B1
+:10B540002C6838646D767482AF8696F16487DAF180
+:10B550009515F7C799830AEB91D2B17DC9A657A378
+:10B56000503E4338E1F924F1D68E47437DE87FD23F
+:10B570004B83A99E13F594ABE1F181BE8CE056F1AB
+:10B5800042248B8179947C6CF34F40FCEE5E1285F3
+:10B59000EB3965AEE674FFC4CA7894F74A2CBE78DE
+:10B5A00027A5FC7BC993DF277A5CA854C73B738827
+:10B5B000DE134D244BF812719DF337DE46EB5CC071
+:10B5C00034A2C7922754AF1FD22FCCAC684F27FBB1
+:10B5D000E6BA74BE6F4E6D06E4C23A4F89F82CDFAE
+:10B5E000BBAAD0A3EFA1F3FCFB62CD8C2DA6FC1768
+:10B5F000429E0B4B6F8FAFB287EAA1555B56372146
+:10B600009ECEF6F6F4C079021C7C026ECA3FA05FA3
+:10B61000F5F7853D389E980BE317A81D9CAB05F800
+:10B620001DEB37593C68670F6927F4443EFEF7C4A9
+:10B63000F830EF70D4834FC5771EFFB500D7C7E74A
+:10B64000D7141AFFD5251FD8721FD1D75FDFE77C2B
+:10B65000A6D23FB988CA9B2C811E58EE3F344D219B
+:10B660003E616381CEF6F9168BD8E7FA7298A75936
+:10B670000985EF412E9F4A7A5900725920444E089D
+:10B68000D28F35F89DD6FF73C1E79AC99F27FD80F9
+:10B690000B057F30AEDFC82FF2D23B8F53611B3BCF
+:10B6A000F73F05F9848FC62D87F31DE591F28F6C66
+:10B6B000244794EFB278114EE7761EF9C31DA8DF38
+:10B6C00036C87DADE7C3C67D5DF2DC904EF7F5B9B7
+:10B6D000B5799DEF6BF8DEE9BE5EAB10BFFB9FF264
+:10B6E0006138F9C82E71B5FDBBB00B3E3C2B5DCF68
+:10B6F00087BF6039D123B0D059DC87F06480AF8434
+:10B70000AB91AFB6F57575CA5719867484C053C22C
+:10B7100051D22B631A8DD34ED7926E255DB7D3AD20
+:10B7200071DD7A781ACB9311F73075EF8B1692177B
+:10B73000CA1B797C22B4A378BA2AB4CF53EDFAD7C6
+:10B7400092BA85E6FD867C83A1BEC790F71AEA6BA4
+:10B75000867CB5AE7EF9812356AE3F0474F56C3518
+:10B76000B7903ED251CEF073BFD3DECFAD3EA48FA3
+:10B770005EAD56E49396E5CC1709ED5B5F5149EE5B
+:10B78000B9E46A8D42B965651897EB2E39453E8656
+:10B79000E75BBB5B57219F94DF5BC3B81DE692B7A5
+:10B7A000352A26449F6F6954A3D0FEDBEC67459D84
+:10B7B000C7B7D4115C9B5957E55CBEBB14CEED0DE9
+:10B7C00097C2B9BDA1507524D7A01DB69EC711CE92
+:10B7D0005B363D8AE2301AD36E9D01DFE7BF4161DF
+:10B7E00006184767C6F887B91C95EC34F3513CE15D
+:10B7F000DC461E07316FAD1ECF0B1C5B285EEE0BC7
+:10B80000B694D205EBF5F10BA56C2DD159C946C301
+:10B81000F7C65B689F941AF68926ECC3C67D72480A
+:10B82000F29F3C96A78B9314FCBC50CDB97506E0F3
+:10B83000E3D23195D920DFD6A8B25583795C2CFAB2
+:10B840009F5021C1FD5709FB15E52609AFF3B88FBD
+:10B8500032BB965FCEEFFBF3D01F23DDECFF64C05D
+:10B860002F213DBFFFA38C9731FFC21F933F611D66
+:10B87000EB171CFC7A36F2E94B076D0CE9FDD2C1DF
+:10B88000D793D11E79E9251BE9D99796DBB89DFBA3
+:10B8900060A41F8F984BBDB95C5CF7CA57039AE947
+:10B8A0005C5E41F83B9F6EE5F255E3DF8EA33DBD44
+:10B8B000AD1156857CFF6004EDA7AA97C2C8CE7C67
+:10B8C000E995AF8686DAE7FEA7EB91FEF74B916C20
+:10B8D000C67348C7315C2FA87A79F8D3E85FAED831
+:10B8E0007BC83A17CA0B7EF3F701C8572F3DC7E54F
+:10B8F000A98B96E627D1C6F955FA999F5B86A39D39
+:10B900000F3AEB09BB3B237BAA2FA733B870385CF7
+:10B910000238E0BA002E25781E74058FA88CFF54DB
+:10B92000787C3E9BF3B7EB18FAA38370513CFC7B09
+:10B93000A4DFAED0FAF9F7835F0D40FE73B5F5E6EC
+:10B94000FC7FB6DE9BFF63D7CBE9FD5D5442867476
+:10B95000A4FB8E74FDC20F28BF3BD24DF3FD8EFBBE
+:10B96000BD14D7DFFD3F71FDFF3BF85EF31FBBDE6B
+:10B97000ABE1FB0D81EF4827FA332FBDF2F7647678
+:10B980000DEB7EE6FF289D4B397EACEA3E9607F52F
+:10B99000DF640DEFBB53481AE9540E793F43AF3FC4
+:10B9A00015307E4E17D8CB48FE2CE8F520C9CB7554
+:10B9B0002C9FFC17BE5E2AF975280804E0F07A4235
+:10B9C0001EDDB362E640AF25901F9B5441F16246F5
+:10B9D000BDB2207C6211CAA74796C1BCA09F23912B
+:10B9E0002627FAA8C7F55203B60194B660FA5AF2B0
+:10B9F0002D14F73FCEA1D7AF6E31E84937B9F4E542
+:10BA000045ECB96EE8B72BCAB1D0FD8AF1583F4476
+:10BA1000AF7C2EC349EBBC89D5AF703AAE1D4EE664
+:10BA20004C0EA78E70F8E770EB0027A1479B457D71
+:10BA300023DCCC8EFB9BB09D99815ECCD74BFAB4B6
+:10BA4000D48BAF064F26F46DB3185AC2D7DC8BFBEC
+:10BA50006743FA25B848B85F2BBC259E8C7097F0D9
+:10BA6000957033E2E18F194CE8B71CFEBDCC7966C6
+:10BA7000DC77A3845C3FCE1CC3F3BD9A542FED4703
+:10BA80003FA7F3BFBACD28D78F71C4501CA9F1FED0
+:10BA9000C29C61314315586F9299F96CA087A2EF4F
+:10BAA0008DECAEF799FDCB53701C6EDFED6DE6F6B5
+:10BAB0006BD8DDBEF07CAAEFB142BEF8E185CC03C5
+:10BAC000F58B93985BE1F559742C85C73115E3C468
+:10BAD00020C576C5D1BCDFE21ECCBF9CE393F082CB
+:10BAE000661FB46F40BF1E532C6F1F954FED7D2610
+:10BAF000DEDE6386B44F1A8F53685DC9EDF2C5ABC5
+:10BB00007B6720FF9830566F675E9AC9ED2E323DF5
+:10BB10009DE92278A9267702DDA758914DFA911A5E
+:10BB2000EEADD88776FADD3C4EA778D55D1387E079
+:10BB3000FC76C7B9717A6727ED19CAEBCFFCFE070F
+:10BB4000F05DDB1E46DF1D59DA7599180FA0B86647
+:10BB5000EF830F736E3B624D8021B486C917D04EC0
+:10BB600038C9B7E777E89F9C344DA5FA93188FC37F
+:10BB7000642B22280E73A2EF737302F43711940E14
+:10BB80002C6F097326DF03F32F16F6E102B15FD4A1
+:10BB900070A63DE7C079F5CE4885EF1359E7F1C9A6
+:10BBA000CB447CB23A56D9887EA63E05DC7E2FEB8C
+:10BBB000633FD8EFEA4C6EAF9F24529907B852FD0D
+:10BBC000796B6C2D69A8FFACB10432213D943D76B0
+:10BBD0000AAE73422A1BBF01E17EAFCA36D37C5B3B
+:10BBE0008BC9AF1099E5423C6840D2E45FA94F7120
+:10BBF000A15DAC654C4300FD092DBF4871D7B90864
+:10BC0000CB140F24F5AD963181BE68C76FCDE37EAE
+:10BC100089E3CEE648D417E73AECFCFEA4882B9AD9
+:10BC20002FEED1F4A96B7EF03AD4431F51C95F3394
+:10BC3000FF117E3FEC2F0EBB5F41BD6D3DDFA76C5A
+:10BC4000AD3E8E8839DD64079A5B3FC68AFAE63CD2
+:10BC500087C78AEB5C9BA5556722DF16F711FB218E
+:10BC600012A0CBE2FA628A5751A360DFE13E31BBFA
+:10BC7000A2500F36C6215589B823995F13AEDD8BCC
+:10BC8000709A13EDDA8DF472A2268DECA30704DD11
+:10BC90004DC0B84AF467989B13713EFDF03B8C3F52
+:10BCA00021D699E1207A0E630887168B3303E9BB0E
+:10BCB00065659809FD72139673BA867D663743FBF6
+:10BCC000FBCC2C1CFD0C378A7E672D337B3741BEA5
+:10BCD000979D99236391AEF288AECDFDB449B8BE6D
+:10BCE000D33F61C3901EE6AE5D47FE184917CCDC1A
+:10BCF000342E0EC639BD35251FF9663B9FEE37B68B
+:10BD00001EDBB5D3C33485E800D24369440F531E0C
+:10BD1000217A181BE8BB3807F5D172E6C1F33D81E3
+:10BD2000B9514E6863ADE4AF6C73585D68FF92FC27
+:10BD300044F20D795F56D2C13638EFCD16C6B6D76C
+:10BD4000DA297DB6D6C9CCE98CEDAC4DA0FCEE5A13
+:10BD500017A50DB559F4FDB95A37E5F7D60EA3FC72
+:10BD6000FE5A0FE50FD41651FA52AD97BE4BBE04E2
+:10BD700070213E24F98AE447731DD616F45F4ABE4B
+:10BD800064A49BD900DED1F9D49EF89EE477B80E66
+:10BD9000537E901F49FCA62A5E5F420AF2B1E699E3
+:10BDA00088FF42F5FCAE17502F2F71B8494F679CA2
+:10BDB000EFB501BD225C92ADEC00DA65EBEEF1B4BB
+:10BDC000AC4E09C2FFCE12859943E8EAAEEA30666E
+:10BDD0000E3937EEAE89D1E567D5BCF76A0FE87F3B
+:10BDE0004677ED0DC4DBF19F7EF6C41FE1FB533FA8
+:10BDF0003D9B8EF886796C7D0CC75D1ADE3E8F58B0
+:10BE0000CCAFB0909FAB8FB09FF411F613FC137AB8
+:10BE10009FF9A99FFE37EDF3961A9B0BE5E28F1170
+:10BE20005F00DF3F097CCDA9B1111C8B577EBAEBB7
+:10BE300005DCEF4BADC4EFE6AC10FBD1700FFA445C
+:10BE40002223BB0448D514CF7EE227D64004F47FDA
+:10BE500042E1FB5801E16016C61FAE79FD43E403E1
+:10BE60004ACD31F2BF6B786F0FE7E7B39CD7DDABFC
+:10BE7000AE798DEAB1E65E31685F94F79223067B76
+:10BE8000AC2E583FD236E26F4ED66196887E967AB7
+:10BE9000C589A2DF3CF17DDE1A85FC9A18C7330DF7
+:10BEA000E4BFB64C95F0999B69A6F4018CC127F9C3
+:10BEB000AE9ECE2949B7F3D6423BDC1FF579D605B5
+:10BEC00021FC788EF83E37CB44A9FC6ECAE2FDF621
+:10BED0005C933703E58A9E589E8369FE0C846F4FFE
+:10BEE000C778B3124207DF88F173C5F80FE0A68365
+:10BEF000FFDD9F956A9D9F43F701E91C93E3CCC941
+:10BF0000CA5F85F1A573D68E412ECCEA2CEE846EE5
+:10BF100068BFCB92FD88FBD8761E475DDEC539220F
+:10BF2000ED6AA7F19FC369DD64F72DDDFDABDD7818
+:10BF3000BFA0F4131BE1B774A088DBCAF10F9D4AC0
+:10BF40000648BD3D7BDCAFFE1C457E8ABD3CBE1372
+:10BF5000526E675D5AC2EDB26ED85F9DF88B8EEE61
+:10BF6000FE24AA533BF65EF53BD9B1AB946FA250C9
+:10BF70008E90EB297CE58B789A877285FC4455AFCF
+:10BF8000AC8CEF2CCECB68C76EB7770BBB5ED5D22F
+:10BF9000A24EEDDD46FBDDF02C83FFC0CCE89E9980
+:10BFA000B4DF3135271AFD005F88FB275DE939D200
+:10BFB000FE5DB5013A8903BA34BBA2D1BF75A90BA6
+:10BFC000F97A59163FFF2F087BF9A59D2AE93D977D
+:10BFD0007646D2BEAADCF9F06BE877ACDCA2D034AE
+:10BFE0002A5813C10FE0CAECA1E71AC6B1C5759C67
+:10BFF000779B3F3D1ACF95B25F455623BD2D6A50C2
+:10C000003C5B613E6D765774F790F9DC85F406F47D
+:10C0100053666B184AF016F39F9AC5F9A4ACB7A8FB
+:10C02000F161B22F43BD8B2417FD3A82F1FB29AD9C
+:10C03000BFC3799EDB38C88DFEC2450D7B2A49AE51
+:10C04000D819E144BBC25911B7DCDE8FA0EF4559C6
+:10C050005C8E3927FC47E776F37700709EB8CFCE29
+:10C060002ADC0EDD8E6FD1AE4AC02D368BEF3359F0
+:10C070007F51434B545FA87FEAC07B94DE2BD6B53B
+:10C08000C8D13400CFE3537B23C8FF756AEF2FC7B5
+:10C09000BF0CE35D6818D30DF785EC7F759685EAD4
+:10C0A0005FD8A81621BC989FC7CD54207C0785CEA9
+:10C0B000336E932F2574FFF1F8A1737B9F8F32E5C8
+:10C0C00004F15961AFB6279A701FDDE345FA8E403F
+:10C0D000E2817AD6BD937D78865535E631A46BDA58
+:10C0E0007F89547F8D29A49ECDE2A63853CB8162EF
+:10C0F0000FBF6722EE458938FE423587FC8AB307B9
+:10C10000BAA6DF897CF24D0BE16371B66B3AF2A7F8
+:10C11000CB4D2AC3792E4E6101944F96DC1BB90991
+:10C12000CF3139EFD983383F285FA3300FACAFDC74
+:10C13000AF320DD29E807F1FD25342F3108C936C8E
+:10C1400049E172858C1F7DBCC4E4B1C239B8272B8C
+:10C1500056F059ED17F3D17F36258BF4B9E356E647
+:10C1600053D1AEF41C8F2F2D4FE571CD8F8B78F806
+:10C17000F2D840461CF4775EE0B77C4A2003E32EF9
+:10C18000CA9F4BA4B88BF356EEF7C4EFE8672DCFE8
+:10C1900087F60E7A674393ED6342E8A97C8EDB85D0
+:10C1A000F5D458B72BCF81F3755E2439775F2443DC
+:10C1B00039D7F442248F9B7A266CB32D046FAF0AD3
+:10C1C000FA93EF77B03B789CD1A3161E97FAE8D686
+:10C1D00044BF3F045E8F5AB49908075C07CAF78BC7
+:10C1E000ACF51928FFCAF92E8AAAA7799E17F4BEC2
+:10C1F00028BC9EC7738BFBC0581FF32D220EBD7544
+:10C20000878DE280CE2636EDC7F1CFEEC866B8FE48
+:10C210009614FF8203540EF225E0B3F4595B00D765
+:10C22000736607B7479FB17079EDCCE40417E2B7A6
+:10C2300068CA86D964AFD96253D0CE774661D60436
+:10C240002CDFDA9DE2CF4B6B6B287EBB14D806DE69
+:10C250001F82B408EF019DD99A4DF16667F0DD06A3
+:10C2600085BEAFC1EF1AAB9FFD2384C776AE5F9D3D
+:10C270007DF66FD9A1F1DE322DDDA28FAF9374224E
+:10C28000CB3FCBE2FAD067595C9F3B9BC5ED1115C4
+:10C29000110D8FA6D23A39DC014FFC1D1BD61CF9BB
+:10C2A000CBC1184F91AE201F799C05327E897687CD
+:10C2B000ED5CFF3ABBD34271EBA52F447A288E6D1B
+:10C2C000F575268AA750B99C5E6A02F041AAFC74F3
+:10C2D0003BC597757B362CDF46F239233DB775ABEE
+:10C2E0002AC6015D10D7BD8DC71D4F405992CA7334
+:10C2F000A9FC8CC89FD99F4B721FF4EFC1FB55A5B9
+:10C300003FFA3187E3D492B7B8DC65277E5BDEEE77
+:10C31000E719198DE760C5EA11D1785F91BDA332A5
+:10C32000945B8C70BA6C76F7403E3B3C5BF0DDFD75
+:10C330004F907FAA4CDC23287B56E17E68D8877813
+:10C340009FB36CD588C7883E7F6761E9B09EF30DC7
+:10C350000F4785E2232D9BF3C5F6FA5637D52F8379
+:10C36000FAD84FD9AA37A3683EDB2C14AF62C4E3D6
+:10C37000776EFFACFA9DDAB7D34703B7B374583F73
+:10C380006BFAC127D0FF5F7786B97DF4B581EEC126
+:10C390009DB3342CC0F59FDB15467CEB5C0CE70F9E
+:10C3A000A7809FFA32711EB7FC8CE2BBDE9D4AF774
+:10C3B000F716FAF5FDCA71B3B22D3CFE2ACE1D8DDB
+:10C3C000F18215EF703E0878B995DABF63A1F6C621
+:10C3D00075D8B239FF6FDF9FBB22881ECEF5E47897
+:10C3E00039B73B93CEA796184EE730DF64BCEF77A2
+:10C3F0006E57661EDDA343A107E8A154E8BFE762BC
+:10C400001A929D21E52D16A1C705A026D20DB601D1
+:10C41000FE5E5AC3E5AD32FB5A8A2FC178DDA1F921
+:10C4200094066CB11DE36E815E49BFACCDE6E7209A
+:10C43000C3F1E2459C38C9410D56E4DB9A9017CB15
+:10C44000771AE37679F96CD91EAF64C83861A443D2
+:10C450009F42712A652BEE5944F1F7D5EBEEC47D6E
+:10C4600026E75F666645A8A7B5282ACDA3258CDDFB
+:10C470003D05E5CAD07142E4B945D9EDF656E68CE2
+:10C4800027399684FE8A6C17A71B3C41F19EE20A6D
+:10C49000652D8D9322F55DBE2E0927008715E304D7
+:10C4A0005BC688F22ED62DE7695C77BBDC95CDF9AB
+:10C4B000514B8AEB672311CF6FAB74FFF7F23783D1
+:10C4C000A2633B91D382E7BC35182F0BF37F289BE7
+:10C4D000D1FCA7647339BD0CE371619E191BF5F1A2
+:10C4E000E2595BF4F97E3BF5F99CBDFAFC80467D90
+:10C4F000DE7D549FFF018E3B84EBE178DF18F57001
+:10C500004C510F77D9B81E8E79D4C331453D1CBF2D
+:10C51000A31E8E79D4C3318F7A38E625BC511FC74C
+:10C520003CEAE358FE9B6C7E3E968B784BC403D26C
+:10C530003B7B314C771FE9D22BFC7E09D001DF37E2
+:10C5400033ADB46F1EC71AA48F70BB53CFA9761733
+:10C55000C60FAF8AD3766477C77B284DAB12116FB5
+:10C56000E6668A63AD7A89C7B196E78739D0FED18E
+:10C57000BCF2D42A0C0FBD234EDB8DF52F595AB7D0
+:10C58000217C2B6A8ED07DFDE665AE776EE0F823C8
+:10C590003B0C2B892539AA18CFB9D8AEF1688C2766
+:10C5A000676BF5F1E3C67872631CB9910EA4FCF7D2
+:10C5B00094A53511F9FAA73BEC6B71FE9F8689FBB8
+:10C5C0003033EC86780007F193C50F2A9BF1BC7ECF
+:10C5D000279BDFCB6E3B06F27A27E7AC4CE75E1970
+:10C5E0004472797B7EAD62A2F874CD43E7D01231FC
+:10C5F000A764A5B56535F2B945263A372F83BC4601
+:10C60000F2E0FB2AC90FF8AE56E87AF05DAD50FAB9
+:10C61000C277B5F4F7257AEAEAE3BB5AFAFB12FDD2
+:10C62000F4F1F9D3961D42BD7FEADA41BA7AF3BC40
+:10C63000230C7014F316F2EC3C383F3C285F2EDDDF
+:10C64000908CF85DB2A8AD6535E077C9BE303796FD
+:10C6500097E0FF015F2C813EF1DE65C95E717FB915
+:10C66000467F0ECF15E7508999F99CB1413A2C715C
+:10C67000324F0CB45FD4AF6900BE9FB5E88DF7862A
+:10C680003A5351CF18D303F951B2C54371B5E57B85
+:10C69000D2639641BFCD7DB56F91EE4ED61F7968BE
+:10C6A000169E877BB8FEF7E9DAE7A328BE4CD05B7D
+:10C6B000B2C5198E78DF54CFE3EBD07EA6C606E96B
+:10C6C00062537D5C785F4770BD413AF886F004F8AC
+:10C6D000E1769E92C3E417696B10EB1DA3F850CE70
+:10C6E00096EB93EF6EB115BC9FEF89FC49A16FC823
+:10C6F000759ECF3E34C085F73A6A0F24ABC8CF4D44
+:10C700003BB7A11E72C5A625F61B82F1A0E97FC426
+:10C7100077D84A3FE0EBF9CBFA82A8E1287FEEB266
+:10C72000B827407E75FDD356D42B4ACD7E2BC567E6
+:10C73000EED864C578E51BB76FA2EF0BB617533C74
+:10C74000E642564DFAE869F94E828047C95865A31A
+:10C7500013E65DDB8FF38F9270EEDF03F9E8557C13
+:10C76000A7E4F276250FE37CA679F7588BE17BBE30
+:10C77000A867DC276D6F4D2DEC4EF0E0F7403E6072
+:10C78000A0DDA775DC1753AFA4D0BE9876A53FE90E
+:10C7900069B705B2B93E9C63D087DF52B93DAF910E
+:10C7A000EF83126BA0DB54DC27072D24E75698F9A2
+:10C7B0003B4F15F0EFEB21F58E5475F45A352E42B0
+:10C7C00047CF3358ACEE3ECDED185412929F362130
+:10C7D0004D577FFAB4FE06FACF0F96131FB95E7756
+:10C7E000EFAF62A9CFA5909C3956FF9DF1F842C6E4
+:10C7F0006ED6B5AF605382F590BEB7285CEFD91BFB
+:10C80000B319ED802526AE3FCDD0F8F7CA03FC3B27
+:10C810009BC174FBB04F9AFB8FFC5CB490DF40DA95
+:10C82000DB67E0BF3B813F63E1EDF7D8F11E3FDA04
+:10C830002774F7BB85BF10E78D78A810F6A48A2C63
+:10C840006E4FAAF03559F19D0480BF392E96EAD972
+:10C85000E330AEB25E217B23A64B29CE521FA785C3
+:10C86000FD61FC63E531B518F789B1BC04DF2942ED
+:10C87000FCBEC4E3522BD12E14D5F17DB44AB413BF
+:10C88000A17DCBF01EDAA17E2E211FF957F5443889
+:10C890004E50F2E8DEE6CE43568CCF9B362D260F67
+:10C8A000F78F91CE247F877D4D71856D6F1D213A65
+:10C8B0006B2B31131D5F0D1E951E6E6735D2DF0287
+:10C8C000D664C5FB290BF62A6ED44BB11EC2A52730
+:10C8D000D2A5012E71B11DE121E1D40E3743F942F9
+:10C8E000C6E1B5F080E247FED8014E027EC6F97778
+:10C8F000053FB9AE059A361EF9845CDF425C078EAF
+:10C9000003EBC071A4DF820D33EED734B25F557AEA
+:10C91000799CAD913EA65CE17699DBAF98299D3676
+:10C9200041BF3FB11DEE93DBAEC453F9B5D24F25E5
+:10C93000CC13CF856BA51BB91EC98F83FB84DF4B3E
+:10C94000B8DA3B4746FBE4DBFD847D72081BA28B13
+:10C950006F16FCD6D8DE18DF2CE503E3B9531C694B
+:10C96000A278CB36472AC91D92FF6AE25CD1567E77
+:10C9700041F534A8C767E3D19D439AB0132E8E4C7E
+:10C98000A577249297C5C523BE8AC39C14D75FBCE4
+:10C990004CA538EA62A8E70A915B56AD484BC673CE
+:10C9A000E4C47D994FFA409E3F716FB7F86130CE75
+:10C9B000A72B2DDDECAE60BD132B0B9331BEE3D363
+:10C9C00075B619FE4EE0F59538372A7EFA219D732B
+:10C9D000174C6F45CD80F6E52BF745E1F581B29513
+:10C9E000FC7C5FDE57FBB21FF97D376D7322FC9C28
+:10C9F0009B06A09DD8C261DA2E5794AE2CEC8172B2
+:10CA000047F9B7479E74E2BDF0659678944BCFBC6A
+:10CA10000FE7A442E71CC913A7C3A00BF2C345D27A
+:10CA2000FB67A715E6417FD479D3A12F57A3BE9802
+:10CA3000D7901180F47ABB66E98F7AC1CAA7499E64
+:10CA400029BD7F5906BE43A82D4B8FEECC9E22D325
+:10CA50006DE23C47B91E5394EB31BE06E57ACCA398
+:10CA60005C8F29CAF5F8BD6A835E2E8C127E4A69F6
+:10CA700077EE53D79A877E3FDF5896554DE7B083C0
+:10CA8000DE055EA284BB913F2D41190AF37F8E2003
+:10CA9000BB037BFF261D9EE5BBC1F25DE051AD20CF
+:10CAA000AB85EC931BAED859E83DDD312C46972F72
+:10CAB000B027EAEA173A5374E5372664EBCA6F7277
+:10CAC000E5E9F2B7640DD7D59FE81EA3CBDF3AECBA
+:10CAD000265DFDC99EC9BAFCD4A299BAFAB7798B72
+:10CAE00075E5D3672CD295CFD4EED1E5EF2CB957AD
+:10CAF00057FFAEEA65BA72F94E7223EA63367CFFDD
+:10CB0000C54EA97C2FF9872AA3F7D8461698B89D59
+:10CB1000D1C6CFA3256FA73B42E9E0D6FE5C2FDD4F
+:10CB200095E3B9B9FF90E07B98F29DCBBBFA73BC5B
+:10CB300026B180C2F5E1A644A463633D63F9C888C9
+:10CB4000C3975D80CBD7FA1FB9CD8CEF475E77785E
+:10CB5000501AE4A372C26EA7FC88C3CFA7423E7EE0
+:10CB6000E7AD3C3FF0F0652CF7E744F1FC5446A2FA
+:10CB700049EACEDDB7613CCAC81B52D7BAB91DA578
+:10CB8000D3FBEE324578E03D718407A601A0634CEB
+:10CB90000F031D637A14E8789E05E605748CE9316D
+:10CBA000D04FF1FB6F413FC5F42DD04F31FD1DE853
+:10CBB000A59836815E8AE9BBB533287DBF56A3763A
+:10CBC0007FA82DA1F4C3DA6AFAFE716D0DA57FAAC4
+:10CBD000F5D1F77BFB4BFB4340F7DE6857EF8A4A02
+:10CBE0003FA7F46BD655B3E608E41BCDE698CFEC2F
+:10CBF000417F65D7760233FB2C445ECB553C2BFA44
+:10CC0000D3F8BD9C749F427C77A468F7217FF820FD
+:10CC1000656AFA2015CFB1EA5731D4E60353E7EF3E
+:10CC200047DE25E8C397E37908DB8DB2F3FBC9A3A0
+:10CC3000ECFCFEF12873531DD257DDD7CC85F13FB4
+:10CC40008722F9BB1F75F799FD680755AEF07D3E49
+:10CC5000BA1BA37CDDD7CD745F7994D39D80E79513
+:10CC6000CCB7FBFDF14F489C8FF4C3CBF89E7157B6
+:10CC70009A0A505E18EDB0BA908F84C60DA0BFFD21
+:10CC800050E467723E0CC793FEFD2D5FB380694090
+:10CC9000D08F3FCADE94827683D1DFB3BB43E39665
+:10CCA000A4BF5EB9D2ACA25D55C627C971E47C238E
+:10CCB000CDD05F7E30FE6894B3210FFD1D75150E3B
+:10CCC000EAAF077CB7E6533D8F4AED1AF2D02E3714
+:10CCD000BADC4171B0324EA0875837D4A3758EBBF1
+:10CCE000A2519CC468112781FDD879B90FFB19DDC9
+:10CCF0002D90887160A3ABF93B644F28D03E3F185C
+:10CD0000B780F52342F62DCE13FBEDFBDF305F94A9
+:10CD1000A33C1E82EF54A9D7B9445EFA1DED63C946
+:10CD2000BE552078CDF214ED1DA423AFCDF9E70850
+:10CD3000DADF69BDD16E3A59C8F5FF845EDEFFF7D0
+:10CD4000D08B87E3BB17237B9B916E245E249EBB15
+:10CD5000A22389F7903833C2737BDC98E8C7485F19
+:10CD60005DD195A4A751768E77C42BC6A9493A52B6
+:10CD7000AEF077DD4697DBE9BC937464A4838E74D0
+:10CD8000C4E9B2EEFB76EAAF231D05F18FF0F8D7C8
+:10CD9000E9A85945FFD5B5D2CFDDAD6C7C3414156B
+:10CDA000A46A77215D145F71BD86F9B96CCC7824D3
+:10CDB00029593EA18B72EDAFAD96E8103A1B25E8DC
+:10CDC0006C4917F5653DF9EE85ECFF61ACDFBD639D
+:10CDD000FD3785DCF066988C53F138F28606E34621
+:10CDE000971472FA2A4A5149EE28C8E1EF9F330797
+:10CDF00097B35DF017F9F1CD4C3B1A9D82EF947A11
+:10CE0000E97DD2F1DD0CEF930AF9BCC8E0E7BF3948
+:10CE1000E74692CF6FBECA3BD7C373C43DB71496E3
+:10CE2000728DEF907A72483FFCAEEF90F2F76BC7CD
+:10CE300089FD9E24E829CDA5B291B1F89EBB66C6B6
+:10CE4000C3E528BE5F3B00DF79F551FE26E6A7F477
+:10CE50001616203962221C4498BF154458CC1F89ED
+:10CE600098340BEF1C160C2AE88BDF43DED9BB0D80
+:10CE7000E757A96AFFE50C7967EFF03817DD5F3DEA
+:10CE80006C4F233914F7AB25C45EFA069CCF7D6145
+:10CE90007D47E0FCC6F45538BFFBC239FA3A9CDF47
+:10CEA00098BF396B19C376E35DFAB827D9FE1667C8
+:10CEB00001286A5DC3EF96012FF642F8BE19933937
+:10CEC0000EE9E2CD98EBC6E17ADF8CE961E2A9CD0B
+:10CED0004A69EE0B7D3B9393E57E088E379EC63301
+:10CEE000C257C2D3084709DF7F019EB539433AC212
+:10CEF000F32ED423D07E6B7F2F2A2115FD9B9CCF50
+:10CF00005644248BF748DF1EA0A662BCEF089AE7C0
+:10CF1000E89AE1CC8CFE763B87D3A95AE643F89E8B
+:10CF2000C125A0C1DB60DF63E6B1A6D038E83D369D
+:10CF30006D1DE2F5D44695EEEB5F782E8CEC76A76E
+:10CF4000FDDC2E5969D21EC5F272D5B5D68DF2E63A
+:10CF50009B2A7F47F49B23C95322AF815EB7F077AA
+:10CF60000ECAEDE33BC5A7D42F67A57AEEE2F20D1A
+:10CF7000D3FD1E452F1B7F0F42BE4BD995BC3534C8
+:10CF80009CF3BD5E36CEAF257E375A851C00FD0C66
+:10CF9000053E9BF4B370D2B71E8CF7EC463C801E66
+:10CFA00043EF4FB5F58AA4F3E9B0888B1B1DE84F1A
+:10CFB000EFAD1589DF1D785DBCE77E58C4CB3564C5
+:10CFC000682F62FBD75D877BA1FDE106C6FD403778
+:10CFD00039F8FBF9D7AA9F1FCA11FAF90036E09A6F
+:10CFE0007E27A1BB4AF72946B30CF2C317E07C9118
+:10CFF000CFBD31D78CE764C8EF24D0BAFEAFFD4E69
+:10D000000263AD2AAE2BC9A9B0C753AEFD77135446
+:10D01000A157C9DF4F28E2451D7E37E19751453CB6
+:10D020002EDFB1A0D3DF4D4812EF5A33173F37E45C
+:10D03000EF261426E8CF9102E798A34E4AF5769E94
+:10D04000A4ABC48F29B9E2FCB856FC5730C27F7B31
+:10D050009C69371EFF345AEBF733B4CF1774B3B85B
+:10D06000FDAE8E74F09FF6BB285DE1C9F87B2946C2
+:10D070003C197F3F25492D37D33B90024F33E02F9A
+:10D08000E2E906F1FB16E3F0F72DD8BF0F6FC30CF2
+:10D0900078FB82AD1D82EF965E2AE67CBDAB73FF06
+:10D0A0004B9767742EF0BD9B05DF97F61119976BB0
+:10D0B000FCFD24690790F1BABEB11CDFBEE311E4A8
+:10D0C000BFFAA1DA1C89E7CC7113FFBDA4C4EEDA64
+:10D0D00004ECFFEE9C6A05E191C0BC7B16C0FC67C6
+:10D0E000FFC6968CF9D97DF87B912C87FF5E909CCA
+:10D0F000DFEC241ECF352D57E8BB6E1EBF353D97A4
+:10D10000EB01916E27C59917E730113FCB9267E786
+:10D11000227DBE159689F4B79EDB039BF1BDCA6ED6
+:10D12000C1F72A514E47B9B8B7904BEB3EB2DB3945
+:10D130001D32DDF99FEDB7EBE29CFB6F77EAF2B9A8
+:10D140000D09BAFA030FB874E579812C5DF9A06373
+:10D150006E5D7E48D3305DFDEB3EF4E8F2C39B8B01
+:10D1600074F5479CF6EAF249ACF51708DF8772536D
+:10D17000091E7D14612771717CCCFE613CDD5792E4
+:10D18000FA878C7BD7043D1BF59A3E562ED7D725C0
+:10D1900032AEB7DA857ECAF4FA8D26E2D6A55CCF28
+:10D1A0007CFAB87519AFDEAE07093D47EA1321F1E5
+:10D1B000EA1E9CBF8C576FC7BB783FD448AFBF14E3
+:10D1C0007837AEA38F95DFAFABBBD74AF784E4FCCB
+:10D1D0008CF33A20E298B7DA3B7F0F6A472E971319
+:10D1E000BE4EF36ECA857A4F02BB22787618CFDD29
+:10D1F0008CBF3F50F713AB7BB9EBEAE3CD1EC8D72A
+:10D20000330BDFCDCDA1F757E95EA01CF74541DF19
+:10D210009B060A39C530DEEC681E1FC7A2AD74AF8D
+:10D22000A5EBF1385C13AC6C05BD5B25EE79DCB584
+:10D23000B6E1412C9A65ADB7F08707FC16B4A34D53
+:10D24000180B72621EE886CF2C7AC40172D1933516
+:10D2500066B28B05769DB8DDD737786FA70FE86982
+:10D2600048271310FFD0EFD0813C8EBC2597AFAF7D
+:10D2700050FDA6FDBE854DC7FF19F1FF4EE88EE8B3
+:10D2800051AEE37FEBFE85A45F239CA45ECEC4B9C0
+:10D29000D657CC4BC24FEE0B093F79FFC5758FC5F2
+:10D2A000BBD941F7688A302E4FE2EFA681DC6E1FB2
+:10D2B00087B260775E0FF95157F50AD59C68F4176D
+:10D2C000B43157B4F32A76F3FFA57B2904FFAEEE01
+:10D2D000D375C5273AF0872EEED775459FF4E71A28
+:10D2E000EED985F0091E2F25F0E1EF6BA2B884D5A9
+:10D2F00091FA7D5C3080F38753621FC3F9EDC8D388
+:10D30000F30986FE8FBA95AAE0130BDA7F6F04BF8C
+:10D31000CF5F6921B99B31EFA318A7F197F5167A72
+:10D32000E771B487917C3367A3E2DFA4047FE7ABA6
+:10D33000D86778A745FD86E4C32FD62A4EFCBD8862
+:10D34000B96BF4E50B1DFC774AE61BDFAB91FEB829
+:10D35000ABE8F5830788F3DDCDDC249789388A12A2
+:10D3600051C72897B5F9B9BF11F57295DBB128FE01
+:10D370004E9EFB2EF47785BCC302700DCFC2737C2A
+:10D3800085B9D3B8C876B87611F771DE21E23E1CB4
+:10D390003CCEA56D6F18F70F4B3F9CA87FDE7799A9
+:10D3A000CAB13EF676218FC7AF48FF9BD1BFD7E603
+:10D3B00030917FAA6D6F24C539A0DF2B1AE8E1AC4C
+:10D3C000694FFCB094E0FCB46655E73732A6DAB298
+:10D3D0007DA44F2EEFABCD1E8071FA66B7DD0DF93F
+:10D3E000FB1C87E91DAF09C20E669C6FFBEFFE8D2B
+:10D3F000E4EFEAB4F9B8BCDB56C4DF3B01FEC87009
+:10D400003FC9788EC90CA43B488B03C3693ED7EA59
+:10D41000FF9A7A258FFB7FAF8CA0F6DA9AE194EF22
+:10D42000B3E2C17BF09ED16D750B2D180AD0FC8B39
+:10D43000A585E1D0B4B9B77F7938E26D8CD2A9FF68
+:10D44000A276003F5F9A0DF716647A49EC1BC7403D
+:10D4500026F89388E75AA6D07E58AC3019DF45FCF1
+:10D460005CE62FD78B7C21CF2F59C9F3CDE27715FE
+:10D47000B6097B0BAE1B535C37DA05760A7B0CAE24
+:10D480001B535C377E47FE8579E45F9847FE8579BC
+:10D49000E45F9822FFC2EF739837394FE57EBB7186
+:10D4A00021FB03FD76E342E423F4DB85E6D16F172D
+:10D4B0005A1FFD76A1E5E8B70B2D47BF5D681EFD3D
+:10D4C00076A1F5D16F179A67C36E0AE691DF7926C8
+:10D4D000EBF25341FE1F17B2BFD16F17DA3FFAEDDF
+:10D4E00074FD69F7E8DADFC96A74EDD16F175AFF86
+:10D4F000EE1A45E7D7BB5BBC433B77431CD14F7962
+:10D500008AB711E9FEBF22BEFDBE05F545B5711112
+:10D51000D7DBC2DD1CCFF5451CEF267ECF42699DCF
+:10D5200049785E6AE5F9421EE76DA41FF48B8DB35E
+:10D5300070BF18A6E817C314FD6298A25F6C5C3A2E
+:10D54000F78B618A7E31FC8E7E314CD12F8629FA91
+:10D55000C53045BF18A6E817C314FD62D80EFD629A
+:10D5600098A25F0CBFA35F0C53F48BE1F7E3E89F35
+:10D57000B304E785F27C5F9D5E0974A8D32B9DBA46
+:10D580003CCAF3A1F5519E0F2D47793EB41CE5F935
+:10D59000D03CCAF3A1F5519E0FCDFF2DD745FB0C12
+:10D5A000E5FAD07628D787E673EB7DAFA2ED6CE283
+:10D5B000C68B47316D8E549E548065FC7DF78FA6D7
+:10D5C000A3FFB2394C498E01CE69517CD3C7415E6D
+:10D5D0001371940358AB897EAF0F95478C73083055
+:10D5E0008A5BCDFD3A91CAA3329DED71CB88F7BC21
+:10D5F000BD8C7E8F46FAD7657B3773AA98CAFAC16D
+:10D600007CE7F58CE3CB7AC43F43E68137AD31DE6E
+:10D61000276FA9231FE366B789DFCBDDB69CC75B05
+:10D620001BE92A4FC84BDB4C7B0EE37D9AD6628503
+:10D63000EE5D6798D9314B3EC2A93A1FE588C48197
+:10D6400031625DD5D7E3EF8EC9794B3B28F009BA3B
+:10D650009F38B2B5A9201AFAD17C63E8F771265831
+:10D66000B9FC80ED50AFECEF533C9B43E83B4DC819
+:10D67000E39A8F8FFFCC539378BB70DEEE99A7A20D
+:10D68000088E9356281477367227F3E03DE81C3154
+:10D69000EFFE3B032A8E57BC828F27FB2DDE984C72
+:10D6A000F7428B59F338BCD7C2062B0CF9B6841B52
+:10D6B000ACEF28AE2F03B60ADAB1BFEB7DAA5183D7
+:10D6C000630A311E9135327A5774E2E0DFEBD64BB4
+:10D6D000681F4AFDD2B996E953E81DE749BE65CBFC
+:10D6E000F1589FE8BBE7D5EE587F0B73A7B8E82841
+:10D6F000A2FBC7723EFD3C7B4C702CB21CD6640A68
+:10D700005310DFEC485C08FDC0CE9F86F8CE735BFB
+:10D71000E85DE5C966A785DEE9E8225EE7B243C6B3
+:10D72000EB18E405435C4EDDD20F93D1DEBC38D25A
+:10D73000447693C5FB22486ED03628C4D7A41C5427
+:10D740002CE2FD2EAF78B5FB7484FB1E0BF527E3AE
+:10D75000752AD2FCC926BC9FD073D3805895E4802B
+:10D76000BB07A21CE07BFEF661586F257F57F4F2E1
+:10D770008A7DFC7749857F47FECEE93C11FF559CA9
+:10D78000EB8DC67818F97B6AF29E8CFC1D5369E715
+:10D79000297E7BD06B88DFE227C4BBDF6B8AE9FE82
+:10D7A000BB31EEAA4CC87F8B5658286E6B91413E18
+:10D7B0002C13715957FB7DD39A8106F950FE4E8E7A
+:10D7C000A8C3D45E7F40BBB0BCF739CBC2F9C0ACB4
+:10D7D0003D8CFC55B3961598F0BD6AB68FD3CFAC8F
+:10D7E000655CCE99F5A287EE6F4AB9F11D21CF4C49
+:10D7F000B99244F07F4FC82FB761BC2AC0794273F9
+:10D800009888634BA474FA151EBF3AC5C1F941F359
+:10D810002BFCDD8D369F8DCB5547197F37CE409F32
+:10D8200093CD7E135E68748F04FA84FC449487A0C1
+:10D83000BF19281FC521BDA714523C649142F78827
+:10D840008CF43EC152FD2AC6DB4ED8CADC3E164AD5
+:10D85000EF40C7D89F4FA1F71834A1E74A3A36D214
+:10D86000FDEC08619F7270FB53BB9D0265557A44C5
+:10D87000FD83E9184F3C1B6D863D69191E8CDB8BBF
+:10D88000CCE1E5CF0DFC60FA0ABCFBD185DD42FDA1
+:10D890009195E0A1C97727BAB023A0FD00F9E55D15
+:10D8A000DFCBB3CE09E197CBF3C6BEEBEE1EC4F7D8
+:10D8B0001CC37DCAC5F7A5D3EF1F752517CF05B8C3
+:10D8C000E2FE981DDDFC7DA054F6FB81CC332E01D9
+:10D8D0007F5F52AE8F05301EF30E91FFF6D77FFFAC
+:10D8E000E31A07C185F26F0FFC743ABE3B57616FB4
+:10D8F0001E8F645795535D84F1D9413EA5799252AC
+:10D90000904FE505F0F7F80EC87BE006FBC4B703BF
+:10D910005DDCFF62B053CCCDE1FC9B89F7C64FDCE8
+:10D92000F7C26E3CB7E4FC4F58F4F76A65FAE5407D
+:10D93000D3BFF55E89F13EC94F93B453C83F1E353E
+:10D94000F1F7137AAAF54CD88BC8AF2CF90613EF70
+:10D950008E04F1EEB1F2B804C5196AAFD2D628FC34
+:10D96000BD822EEC3A2CABF5175BA1DDEC5A2BFDFA
+:10D970009EE353199C7E9E02FA41F96C96B5E955D7
+:10D980007B4A108E9FD4FCDCC2F958201DDF3BBAC5
+:10D99000A33ACC8D7C79799EF7EF38EF881C37F16C
+:10D9A000A377DD9CBEAEEBEE656EBCCFB8F6D09330
+:10D9B000F87EC3FF037EDA89FC00800000000000CF
+:10D9C0001F8B080000000000000BED7D0B7454D588
+:10D9D000D5F0B973672693CC244C42200F489800A9
+:10D9E000911401270981800837C82358C081100588
+:10D9F0004DC28467B46023D51A2D2D03493020DA37
+:10DA000080C120F53150A5685163B56DA8D80EE2EC
+:10DA1000BB682948F5FBDB86E18D8FD608B5DAFFB8
+:10DA2000E7ABDFDEFB9C93B9F7662680DAF5757508
+:10DA3000FDE3721DCE3DE79EC73EFBBDF7B9F9F68B
+:10DA40009E1CBB7F1863D5EDF96BD33D8CADC9F738
+:10DA5000DBBC7DA0EE72DB7D2EC66E6948B67BA076
+:10DA6000AC4A63B56DD08FB1CEECD9898C7D81BFC6
+:10DA7000098C657915C6A0FF1FF2A1A988B18F6D29
+:10DA80006C2EEFD76C9B65E867A17EACB95573F43B
+:10DA900065CCCFF82FCBCA029602C606D8FD4C4BF8
+:10DAA00065AC3E8379D7E430D60F9EC715F0F6F803
+:10DAB00014E8EFB21F5592E085C0642D9CC7DFFDCE
+:10DAC00062206376C6340BB4F783D20EFDDB877811
+:10DAD000689E2C6857E1B92DEFD83C06FD2AEC6C06
+:10DAE0003EEE47AE479633C5FAD95C8785C1BA1674
+:10DAF0003BE0DF30C46475D894B4918CADD8A8B83D
+:10DB0000E3E0D12297E7FA31505FF4BA8DAD81FAA4
+:10DB1000F4148F3D03EA9DEB14F776A82FB82DDFA0
+:10DB2000EE817D57C03619AC63D19631CCD31BCA78
+:10DB3000209485DDE795E58D1BF765ED86F958485E
+:10DB4000B3FB005E8BDC9A3D6558A47D61B3A205F2
+:10DB50005DDDEBE3BD2AADBB82B14908BFCADB7214
+:10DB6000EC0B5C587FDDB66218EE8BC341BE07FD3F
+:10DB700042D86FFA40F62AC375C3BEB6E7F0F90A79
+:10DB800074E32FC0F175F343FFF93EA8977A136948
+:10DB9000BC6A37EC3B074B37AD13E04070EABC176B
+:10DBA000C6F3D03C741E0B43419B17D7638579A104
+:10DBB0007E833B68C3791634E4DB1994FE0D7C1E2A
+:10DBC0007F53B27D38D4ABAD6E7B16C22F0160910E
+:10DBD0004AEB0B6E87A35904704971E13C6CFE6CF3
+:10DBE0005777F8548BF52E6A4EB62F363CDF68C354
+:10DBF000F39807EB698B72EE77E1B917E17A4AEC9B
+:10DC00000CDFB76A762FAE47C0F7E4ADF1EB592FC2
+:10DC100078BFA5D59603F59B05FEDE85702D42B82D
+:10DC2000847215DCF7ADF15E5CE73C7733EDAF0B4A
+:10DC3000BE9B011EF07CB1DB47F005BC083080C301
+:10DC4000A216E37946D69348E32E6AA9267A5B6248
+:10DC5000F5DBDDFA756CD99BAB005CE6D5C67B15B0
+:10DC6000803F73FBB3115F4E6DBE3E9BF609EB44E4
+:10DC7000B8267A3D53D247129E101E4B7CA92AE447
+:10DC8000F42BE7DBE4B5D27C9B705F453DD1A5F674
+:10DC90006A3AD2259CEF1A4F6CBAB433180FE6B526
+:10DCA0002F5282F54A773A95F429E952D2A9A4DF96
+:10DCB000476CBE50BA12E13355BD58EDCFA2C0E952
+:10DCC000A038871BC4B9025C5F46B8CAF617043D8A
+:10DCD000570C34D23B8E87E3FE449C7BC5C450EE88
+:10DCE000ADC322FDE5BC1529FC3DC47BC4B79F082C
+:10DCF000F860FF15D4DF62E0170BBBF8C5AEC6BEF7
+:10DD0000C82F9E55BCC82F56DCBB2FEB0E80DB8A7C
+:10DD1000A79C5E84C187CB1EBF2503E0C0AC413AFF
+:10DD200037B9AEC59FE7139F58F2F9959C5F84A25F
+:10DD3000F30B579EBFDD5B14A92FBAFFA9CBFC9C48
+:10DD4000DF8490DFFCE9A9170E8F453EC28236DFE3
+:10DD5000F0C87E1634FDDE56EDD2C38FEF777DDE40
+:10DD6000D96A3CAF852EBB4785470B1BAA89FFB2FA
+:10DD700074E6CD5522E76FC68BEA0645A3F7EA465F
+:10DD800005D5AF914F2FDC300BDE8D9C1B4CCCD8D2
+:10DD900028D827E3F095EBFFA3587F87E06F37087B
+:10DDA000FCBEA1A6C49E918AFBAD2E04CEC8E68916
+:10DDB000E7F316199F779D9BBB8BCFAF457A39DB75
+:10DDC000C6CFEDEC061BF19FB3BB12830CF6F7E157
+:10DDD0008A5FBE7D1DF4FBE0816DD94C359E1B2B07
+:10DDE000E4E786E5523837D63BEAB97DECD5F1E178
+:10DDF000A58FF2735BF8F45B7FFE9587F6CBF9DDB8
+:10DE0000BD7141E4C70BDA9EA5739CD7B4D196834C
+:10DE1000F4EACD21FCEBE2FFB5F96E06F0BDA16995
+:10DE20009B0DF9C417120E267A8052633A3A43B911
+:10DE3000A4A420FE853310FF647FE48FCFC23CB7DB
+:10DE4000DD1A9FC4AE88CC9397CFF17E616D720AC4
+:10DE5000CEB7B0B6FA3E3622220FCCFB3C1ECFE93D
+:10DE600065018C87747BBCC49BBD82F0D31255EED8
+:10DE70000EC8E7E7F82300773CE0433F67DB130871
+:10DE8000877EDF4EF022FF183C381CC47911BF7129
+:10DE9000DD76E09F0EE8377859F8135CC760C03034
+:10DEA0007C0FCBC4142A595FA86F8765174339507C
+:10DEB000E5E5E47CBE7F680F613B4B0D17E1FE2575
+:10DEC0007E9BF1D7CE1E6B1A887C2C9579EB3D1189
+:10DED0007C95E3487C95F81C6B7F575DE4FE8EE7EC
+:10DEE0007078DA13607F2997B03F40D6E294C8BEBD
+:10DEF000E4FA581EAC0BE6A9FADEF06DEB619EE386
+:10DF0000ABBDD9B5AE9EF6DB32B96F94FD9AF72959
+:10DF1000E9669183D334D04DAF30ACFB6CF3A05E97
+:10DF200028778E2B20DFE0BDE3B7C65B70FD725F04
+:10DF30003B56416758EBCE550E2A9F5C05843784CB
+:10DF4000B15DABD2A9FEF42A0F956DABF2E87975FD
+:10DF50007E0A97472C9C887A26E8039C1F84389D6C
+:10DF600074D40DA27DC9E7522FE87087135374FC57
+:10DF7000FB44AD909B2C7C2FD237AB1BC41E87A9D2
+:10DF80003A9A8F275A86217EF2F5C9F76EB3751239
+:10DF90003F648976CFE34072CEDB7E3F390DE65B8E
+:10DFA000DC9293AFC07B9575851D75D05ED990E6E8
+:10DFB00045BEB1D8E5598B72717120C78B72D1D92A
+:10DFC000927F6A0BB42F6EB8DC8BFD6F53980FE90C
+:10DFD0000BF82743B82D615D3FCD017C6DA9E06B47
+:10DFE0004B915F02BC96D4ED1BEC86F79778E3F378
+:10DFF00051BE2FDDA284E290DE2CAC4941395CEFAA
+:10E000009B827CACF341C58BFA267B08F8AB23C21C
+:10E010005F37E4F956E6E3F99F07FC83F187A20C2A
+:10E0200056715F6D1AEE83813EF238C375FB48AFBF
+:10E03000FF7F428FE968399AE819C6E18DFA3AF311
+:10E040006B16E4BB2B845C1B60EF3C7A37EA3389A8
+:10E0500016EF76CE2F7FE7C17DBEA1B2389237A2F0
+:10E06000BFE0A7037E50EC40FEB62271601AE9556E
+:10E070005B54E28F127F6AC49A176F2BEB8B78B3D5
+:10E0800018DA51DE6DC587C042D7B65CDD17F16A7C
+:10E09000D1C6C90F04408E650B389EB08667E1F982
+:10E0A0009CD99696B21AF5C2E5F59731685FB4ED42
+:10E0B000EE6C2CCF6C8B9F8BFC7E927BD6A464D8AD
+:10E0C000EF928792F3559DDCF8A9A0C79B975F9DBF
+:10E0D00086F6C0B27FEE7BC43D08E6075823DC3FDE
+:10E0E0006D730603D065D9AAF66C1568ECF338FF9A
+:10E0F0000E84E7B72C7BAE1B83FC5F09EEC8A0FE45
+:10E100009E3477147A97E529C0770FE0F3F21FBCAD
+:10E1100047E3FCC5B27FE63C787FD9F2E792709C7A
+:10E120006F6D3E34CA0DCFD70CF6FF0CC7FF40D938
+:10E13000B6C38D8269CBB61128B79F1376D4F41479
+:10E14000DF75F310EE6FA804F758F3D5B42B045F16
+:10E1500059AF0CF6227DD61F627637966E46FAF2DC
+:10E160001995D5A13E20F51AF9FCD57CAE0F9DE995
+:10E17000D59C8D7871D38ED66C942BEF27F27AC50F
+:10E180008EEBDF443EE57F2C8EEBED56467AF2C2F5
+:10E1900000D7BB590DD06B4664FE03F94E82F34D98
+:10E1A0005B0A0DF210F4129AE77D2B2BC5750CA8B3
+:10E1B000EFCC47FDEB8FD6D0623CD73F825E1BC8C9
+:10E1C000C173E27CEC8FCDEA147C1E0042427DE4F8
+:10E1D0008FCDCF250E7645F4B8C4916D21E473CB75
+:10E1E0009F4F2E50394A117EDDE296FCC935A55F5E
+:10E1F0002AE9636EC4D315BB5F99C2781D04616CB4
+:10E2000078DE2CF4B0AEFAF3CF925DB76C17D72757
+:10E2100096B53DFB6A268C734BBBD027849EB25CBF
+:10E22000D0F32DCF73B82C7FFEA87DA1DE1EC94B85
+:10E2300059DB0F34C173F9B6B99B518FC2731BCB35
+:10E240005842DBE7735783EA9CE07573FE6DED245B
+:10E25000FD707DDE41B2CB973788F1F20EAE1D48DE
+:10E26000FB9DD55BAF0FFD2DDF467095EF033CE8BE
+:10E27000BDCFE2934620FF0B2D4F6842B9AEDDE2E1
+:10E28000B26259BFDC4572FEA15A4B9E15E0AB2924
+:10E29000095ED4E3EA1CBCFF1D0949DBB1DC93C075
+:10E2A000EB9FC567939CFACCE27B7609F4BB433DB8
+:10E2B00010CF06E19177EEB3403DA38FDF5900F315
+:10E2C000A731A01E15E54748C1F68F5F3C5D88EB7E
+:10E2D000183F207C8EC1D26C4ADCBC49A82215882C
+:10E2E0007D0E0B1722BEF77989F3EB876DAC09E53C
+:10E2F0001DB3FAD86C781E42FE85E7FF0F4B10F96C
+:10E30000F11E25F463BDFE555AC0F1D617E76A52D7
+:10E31000609D6539FEFEB88E6B15DB70545D9847C5
+:10E32000CDC5F13FB6F176A9C74E144C384BD86332
+:10E33000F6CC7417EEAF5EC04BD1345607EB5833B2
+:10E34000ECA585882FF7743A581CCC3FB13381F483
+:10E35000DAACCC52926FF5022E8A2715650E7B69D6
+:10E3600098251007EBBD873982D89F394CFAAF2525
+:10E370005EC3F7943DAFFD03F97D3FF5937DBDA0EE
+:10E380007FBF3B146F3DF4A93A7BEAE1DF31B49FD4
+:10E3900083F908BFB97DFCA30A50CF3D5B7AD40F47
+:10E3A000E77D8FBBCDE11DC6C7D3EF63CF9DFF488F
+:10E3B0004AB144D6F771E7A9A77E39124B07C9A124
+:10E3C000897B549223E6F57C9CEEB1D239753A42B2
+:10E3D00016ECEFB2041505FBEF7B0FD737D1E10A3E
+:10E3E000A9A8C73B6C1FE9E50C3B90957CEA72122B
+:10E3F0002DEC0B5016FAD6F3F31BDFCB685FDE581B
+:10E40000C0EDA41B0B38DF95F09570631E8DE9E518
+:10E41000CCAF5D3B2A992542C7DF16CFCF7E3E9019
+:10E42000F48BB37B40CF88A277CAF210EA19A857C1
+:10E430000CD416161445E46CB994BA420EAB62DCE7
+:10E440007201AF729785C3678E093E026FCC786107
+:10E450003E77799EECAE03AFF4CAA1731CFE43462F
+:10E46000E7770BAEA3E31FFB1B81DC58A6AA1DF5C3
+:10E47000E7FC3B9E5F287E08EA159B2DA457A0DE93
+:10E48000877AA2E41F7EE40357D073AE07E631E239
+:10E490001B556A82777D14BE21F9853F01CA11C8D8
+:10E4A000379A891FDCA176BE6251227C624069786E
+:10E4B00038CAE10E30FDB13D6C69A3E7CF170C24DB
+:10E4C0007CE9CF0E64E073B0578A500F541D3F7E35
+:10E4D000F804889496759C3EEA6DC10797207F28C2
+:10E4E000777951AFFB386809D8609D2DC99C6FB40E
+:10E4F000DC9449F2FC6326F8C85C3BF1912B2D9625
+:10E5000000D95BF332C9DEEAEA9FEB09A2FCF9C548
+:10E510003FD5CBB660FB2C07C9DD1694C7506FB949
+:10E520007738B5BF20F9D24D9C2FB5CCD23212B07E
+:10E530007D565F0BCED792EA7F1AE936530D3E1116
+:10E540008FFAE4B712D8E3F83C47CB4079FB80E27E
+:10E550009BB718DF1FCED71D9E97F0F40E7E3C218F
+:10E56000F42775D4256E5FAF934FED4338BF1C1071
+:10E5700038FA20C22B3091E5A13EDF81F87945E4DD
+:10E58000BCC02A67752991734B359D9BC4D7800DFC
+:10E59000CE2F959FDF1A25F6F9A58AF353EA00BF1F
+:10E5A00089FFF3F3B943E5FC9DFD1A1448284FF4A5
+:10E5B000F1EF473CAFBF15CE850462F87684D7C330
+:10E5C00077266AB88F0E0BAB698B42B7EF1608BF80
+:10E5D000134A63A087F9821EE64BBC5D69C2DB70FB
+:10E5E000FFE4534E81B7F0FECF9DBEFFC279FFA27C
+:10E5F0001C1A850FF7FFB73A37DA3CC7849C78C1FD
+:10E60000E13F4A7CC13AD1A0AFEECF3F9D85728AEF
+:10E610009DDFD71FE5EEAE54DF093CBFF8C19D7604
+:10E62000F447746474DA709F1DF33EC842BD687E7F
+:10E63000DD6B445F17BBCE35CE11361C3FB934DFDE
+:10E640001686F7D34AF35F41FC393823CE131745BA
+:10E650000FD93B637416EABF87A68DCE427E77083A
+:10E660000EF000DA11566F22F241D65E497C6CB68C
+:10E6700098F35069217F2EF866E479598FFCF243B4
+:10E68000E09721D053DF07BB0CCBD3609785807F09
+:10E690009E04BB0CCBE36097E1F3A36097617964C0
+:10E6A00095979E1F2A1DD41E467DB959213B68A10E
+:10E6B000D56B8FA60F2FDBA5B290E457F0FFCD8F5F
+:10E6C000390DF59A877A1BEA4B5A40737044EA8BEE
+:10E6D000360C32D4A5FEB8A0E172C373FFCA424320
+:10E6E000FD3F16DE4D1CDEE827FF778237FE360041
+:10E6F0001CCAF01F80FF878AA6DA508E5B1D2CE0B3
+:10E70000047E928C7406EBB7CE51B85E04BF66A04F
+:10E71000BFD9F80FA02BAB8BB737CC5382C88F5023
+:10E7200017427B02E01A72027D95B92F3B89FCE803
+:10E730007AE45C2ADAF3412A6F6421A2CB4A16A656
+:10E74000FA7CD6996D87F21635B416FD76AF39FC92
+:10E75000558540C77F9FF6FB0E0589D15B3D04E9D7
+:10E760009BB952C8CE8C754EC021B97E8A5D47894F
+:10E770007DC16F0EF27D78EFA073C4EDB7C3397C15
+:10E780005C1D1E85F32F73F81F4DB5D07CCB0A910D
+:10E790001FD9FC437AC3F3B78A466721FF60BE3EA8
+:10E7A00006FB28D67C1B71B30087EA52809382F166
+:10E7B000370E9713E51C2E7B37C6D9D18F71629D1A
+:10E7C0008DFC94ADCEEC6CC4DB138D53B311EF56BE
+:10E7D0006F1C928DF83EBB69EAFBC8B727ABD3AB81
+:10E7E000F0FD63CD1CEF19BB95F4ADDBC5D91DF36E
+:10E7F000306F08DACBA7257A03B01F7F202789D690
+:10E80000CB34573EF45B28F6BDB079E9741C4FEE6B
+:10E810007FC18638C3F95F5B6CAC97337B04CF72E2
+:10E82000F09CED91763C7FB5A297BF07FBB9EE4F08
+:10E83000DBDE7C5937DE038589A9A8AFB0D16CF443
+:10E84000176AE4FD5870FD6C55F0CD9773237095F1
+:10E85000F8746BA1EF513C1F784C7136A0259203E0
+:10E86000B774F9B3F62421FC363A7F7DDF9508971B
+:10E8700077B87FA3D55945FCE3C369004758FFDE4D
+:10E8800069D76785757C41BE1F46FA067A3DFCD480
+:10E89000F5C447F695A7511CE6E0F3DCAF7C44D005
+:10E8A000FDC139D757DE0EF2F1E02E95F4BB83EDB2
+:10E8B000E75E41FFCCC136C52B406ED18F7BB07D6A
+:10E8C000D0BD23A1FD539F8DDAF7EE7A8ED669DE97
+:10E8D000F7FB62FED3380FF11537CD775CF097A3C5
+:10E8E000C85F86E03AF2A83C88FC05DAE7EC06FE51
+:10E8F00082E36FE1F32FB6FA88BF30FF5CC3FEBA44
+:10E90000ECE1C754C379D73CE434F115239F59B4E3
+:10E91000A19FA1BEA06190A1EE5F69E42F65A585CE
+:10E9200086F6C3368EA7070FABE4676301ED405E42
+:10E930005F1D7E9672FC5C5D1E47F472781AE733A9
+:10E94000B3E7001DA07ECF3C45684B7ED85ED6075E
+:10E95000CF856DB01D433DDA0DFFA1BC36C3B19C20
+:10E96000598F8575F8BBEC79E8AF5BDF6C6CD7E14C
+:10E97000B3195F3F427C7546F0F553763EDB3E901F
+:10E98000B71FE81BE17BF8D3F317C9B724FE02DFFA
+:10E99000AA42BE067CE533E463DF2DC87931ACE8DA
+:10E9A000F8CA45F2B18DCE7F921C6C75FE93F0F8DB
+:10E9B00050B9C0E3F22184C707670CC92279169CBD
+:10E9C0004BF4305FD847076DBE44F48F1E5ED93BD1
+:10E9D00009DB8F369411DD497A32CF7744E09FEC22
+:10E9E00037DFDA69F3469187FE9546FC613BE71213
+:10E9F000BEDF6EC2B358E39BFBCB79E69BE2BCE67D
+:10EA000079868C14FA665BE545CD8764D8F53EE9D6
+:10EA1000B50911BC54910F7C9618267B9CD349B93B
+:10EA200080DB91D2D189A447CC39472513F4DCD5BA
+:10EA30003EE7DC5BA391DE4A6D82DE6BE8FD32D1FE
+:10EA40006E5EC769A1379C14FCE3B8A06BD9AE6EAB
+:10EA50006BEC7B03E2FD4AD58BFCEAF0F442C2F397
+:10EA600033C1729AFFC81C95FC4CD3460EB801FD09
+:10EA70004C723D72BEB219E712D18FF629C00BFD60
+:10EA80006265366F9F68FA85191EB1C695F8B3772F
+:10EA9000DA90C3B8CF43C847B1D56F84D3217C1F68
+:10EAA000DA676F5329CE6686D3BE6943882F1DD996
+:10EAB00029F827C015F5EF9A878CE7BAA4C569E253
+:10EAC00037BD0DEDB3CBB95E26F9B55CDFA19583FB
+:10EAD000FA30D7C59FB71CE762F1E566F13E8ACDF3
+:10EAE0002F48FEA618C6030BD134DF4053FB50530A
+:10EAF0007B81B17E91787C54E08F943F47E3BD9554
+:10EB0000D1E27747AE89ABD1E7256C1AC9FD369BB8
+:10EB1000468A78F725CAED7B471AF9E085DE977CAF
+:10EB20006F61A1AF6524D269A88CE2D817CBE774D6
+:10EB300072FEA191B8DEB062C7F7A55E5523F4CF8F
+:10EB400056E77DAF22DEFD45D8037B67C4111EFE6C
+:10EB5000F529AE77FDF5E7A7499FDAB7FB8EA4B09C
+:10EB60000E6F9609BC39DD3E2409F1F0585B7D92A9
+:10EB70009EBE65FB19783E7664445EC75AF7979649
+:10EB8000D7CF0A7B602797D737599BA3DA03FF6A51
+:10EB9000393D595D497A88595E9FF67892DC041FA9
+:10EBA000417742AEC8B8CF5F6D9E24F4171E0B723A
+:10EBB000B922F9FA41131C4E201CE222F224161C41
+:10EBC0008F8BF7651DEC511BCE5FE6F0BE928AFE7F
+:10EBD000970D8A17E35E989E520CE77C604EFE8F7D
+:10EBE000D16F25FBCF2F52492EC8793EDAACB4A1A4
+:10EBF000DFEFB595FBB2BF07FDAB773989AFCAFE32
+:10EC00008BA61BED2CB33CFAA8F193B746C3BC65A9
+:10EC1000CDAAD701EF954D2FE9C3F56AB7118F043F
+:10EC20005D9ADF5F6AAD8D7A9E66BE57367D35E9A7
+:10EC3000EB87C47A0FED1D63F324767FAFCCCAE176
+:10EC4000B014F4CDD530EFD2864F48FE2C9DAE7A6D
+:10EC5000512D79ADA97E26E2FF519FCD82F471A49A
+:10EC6000ADF74C8453608EEACD85FEFB9B06111DEB
+:10EC70001C6BBABA2FCED74BC0EB747B9C05FD4FF3
+:10EC8000A77D3616227B3944E7F9514319D9C7A726
+:10EC9000114E78FE5637D149BF22EEC73A0AE370CB
+:10ECA000FBD9C3F4F1C02341B53418852FF513F314
+:10ECB0001D3FFF43C2AB5783FB08EF8EB6F1798E41
+:10ECC000AF7427619CEBB70D85248F8F4D87F1A121
+:10ECD000DCBB7BE97D98AF777A834AF2E374FBF57E
+:10ECE00033B17E688394BB5C1E558BF957EF1E3D94
+:10ECF000A318DA3FFAB98C6B72BA5E20DAAF9E7550
+:10ED0000F8BE62BD3CDB35D7B0FEC3C1E3646F9D86
+:10ED10006E80B7018ED53306D9D11E5EB4CB786E26
+:10ED2000E51B8C74083F577EDF489ECBA206D06758
+:10ED300081651D9D5E4676F4EC406F93BD6DB4E336
+:10ED4000CADBB8BDB7E0E1B2A210D269E0131B9EE6
+:10ED50005375739C619ED92B8D76DA02935D66B6EE
+:10ED6000DBCCF245C263B9ACB755D23ACC7A4B375B
+:10ED70007963ABAD8A961F5155C4F5B16AA0CB74C7
+:10ED8000F42B33EF0CB4BB8E017CD7C378D576F768
+:10ED9000DF73414F3EA2B2F1E44CF30658B1F41BCD
+:10EDA000E8E65BD0A09AFC1346F882BE7E0AF5F92D
+:10EDB000A6DE420E0740AE24A29CD1FC4528272E99
+:10EDC000D61F70D1FA7695D0B7AB0CFAF641ECA20B
+:10EDD0007B7F6FF9F5E4773A3CE37AD2BF0F77F99E
+:10EDE0009D7C06BF9384EFE1E965067D52F7BC1771
+:10EDF000EB813FC6D21F8F0AFE7A44F89DD60A39AE
+:10EE0000D320E4CCE1E9C22E4C65442F56ABC62E8C
+:10EE1000862F5D481F5BD0D0CF745E4639E32CF15E
+:10EE2000B716015EC4A50F353CB7B90B8C7463C22D
+:10EE3000CF7E8CFBC1EF46DB1EE05E5FCEF347F179
+:10EE400039E6B148BC64D01FE573F986A1C1F5BCB1
+:10EE50003DA01660DA1B43158DFA5B795D53783D52
+:10EE6000E012EDAAC85FB341FD688E772EEA519893
+:10EE70009FE34CE1ED8822FD009F935222F88FFE24
+:10EE8000F9781E220F24C17BFDE7E4BC8CF48D7958
+:10EE90003B9741FD5745398437E9E89A2FA0F14364
+:10EEA000989F13AE9F40745CE648E2717690B33D44
+:10EEB000E3DF6A6EDF94F6A6C9FA5BF97A62E2B321
+:10EEC000E877097AD56B442FCC42FE938DCE11366C
+:10EED000C4DFD92E5F16C201F0BDF276B4D35FB4A1
+:10EEE00093BCDC5BCEFDAA07A78D7EF836783EE2A8
+:10EEF000191791F1C1C580E724173A13F5787B649F
+:10EF0000E5710BE6D3FCA19D79311FF1C8AE8A579C
+:10EF1000DE8471F6AD5C786F11D2D17ECEC7CDFEA6
+:10EF2000D89267C6913CBB6E864A79DA874A55C645
+:10EF3000F97C82C1AE88F86955C28F4FF758A91D78
+:10EF4000F3AAF2308F0AFD95986F552ACE45E81541
+:10EF50006DE21C9F10FEDA1D826E5A04DD6C127485
+:10EF6000B3CEECAF7D88D3CDA1763004404EFE6E9B
+:10EF7000FAC289E487DEC2289E9C334D5D3F12F6BB
+:10EF800077799CD786F02B999ECFE13947B1601CE9
+:10EF9000A6AC34DF86F47E796F8FCD477AD62CAA63
+:10EFA0004F9A934376FBDE95658964BF277AB390C9
+:10EFB0002E074F8F0B5992D00E2C243E71E5198BE2
+:10EFC000815EF2430906BA1BFA588AA17DC8964CA5
+:10EFD00043BD8F6FA0A17FEF52233D260C2E30C979
+:10EFE00025AEE749384F56C791DFEA48445E52BB29
+:10EFF000B4EFA4FF4DF6076819F85A93D0074740BD
+:10F000001DF3E2D6CDA97760FEC3A76D562F1FBFB3
+:10F0100082E4BD23E77907D2098648314FAA49CA5D
+:10F020001FE18F671A33AD6B03C378E9915246F83D
+:10F03000143F9829182F6811E77DBF9817F86A893F
+:10F040008DFC6EFC1C7B4FF7513FE633DAA9E94893
+:10F0500067058827FCFD27C4FB3B04BE1C29FDF186
+:10F060009A04C487B98CFCF793D5656B302E78640D
+:10F070003A233A690BBD9480EBC77130CFEF57B19B
+:10F08000C699F3DC1F6FC1F5ECB4D338658F815C92
+:10F09000043C197AEDD10FDE46F06D71EF8B67DD20
+:10F0A000F5E9118F695E044EDE1916B25119D2903E
+:10F0B000FFE49D39A0615C6FE85F777EF034C3792F
+:10F0C000B95C6812F86DE6AF3F7DFC170BD663B9EB
+:10F0D000636BC17B507E63CD839975503EB1E65B17
+:10F0E0005B6FF344FC9F3B662EDDDE02F521DFFC07
+:10F0F000FE93CF235ECDFCFEFF791ED73BF31F7F2F
+:10F1000076C1FA2FAB4F6448DF727DE679D259930E
+:10F1100082F14DE4A3C497AD01AA57078C7A7759C1
+:10F12000A9D3807FD8DF0AF02BABFB29C589D3C5D3
+:10F13000FB8766DCADA830EF7BD59CAF1C5CD5D9D6
+:10F1400032C946FD43D81FF824E55DF6EB0F6C0588
+:10F15000DFB707148C6F8382E4C5B86D06B4233F14
+:10F16000671E0FE93BD9127F055FC1EB0A8CFC7B60
+:10F1700056C2B33C115744FE8BFCBE6ED440E2CB6A
+:10F18000FD5C4CC3F32D7D618382F966EFFA3D5E31
+:10F19000D20B56B1CD93C0EE1DAAF2FC89BCD2773A
+:10F1A0006FC07381AD5AFD059171778ABCA6D217E5
+:10F1B0005C947FFDEE4ED736F2EB1F9869D1EB835E
+:10F1C000137FFAD1CF7E8BF8551D4FF865D65B0EB5
+:10F1D0000AFAE8AADB3C0FDF86FAFE8B0E6E27697F
+:10F1E0009E2CB2BBBD9E2CCCC3E9EAF77D191FF360
+:10F1F000FE19F9F9EC0A27C50D649C482DFDA411F0
+:10F20000E9717E716D11EAE399780EBD23F1E8F79B
+:10F210006EB253DE404049A0FCF25871E79DA372E4
+:10F2200044FCA5F60A5A07AB1D8DE5B9B9F50FDB0D
+:10F230003DB1E5558338D758ED363BF3478B0FEF9B
+:10F240001CC5F5D07A3C079BEE1C5C7FB801E3BC83
+:10F25000B1CE81598305942FE9700CC67C8E34F1B0
+:10F26000B8D5F983B7505E751CE6F22AADEEB355FA
+:10F27000487FD20F5195CEBAE2601ABC6713EFA552
+:10F2800009FD1B6918F5EF2A11FFE9A86414FF496D
+:10F29000AB3BFDDF089F8D62FCAA77F8F8766B68C0
+:10F2A0002FE24B95CB4372A7A34F9217EF27B1F3F1
+:10F2B0003CCF2493717C4C33EBF7A809E9D69D969B
+:10F2C00050F13B541FE68E672127E28FE2A079338D
+:10F2D00057C6517EAAD4AFD2EAEEBE551D61184F73
+:10F2E00041BDFADD0A6E3FA399DB356E8E41AF2238
+:10F2F0003DCBBC0EF95E878DB5A33DA9D3B3480FB6
+:10F3000063FA790619EAC22F66ACDBD2ED063EF14C
+:10F31000EEF9B25EB55C0E785247717F1CC243EACB
+:10F3200063526FEB36AEA0779D7E19407E21F321AC
+:10F33000BAF4A41A9D1D35B0FB7B32EF4C9E83843A
+:10F3400067ACF79D25DAB951941711A271FC6218C8
+:10F350008BD3954DF035F14B605B3C2F5EE8A1A05F
+:10F36000451AF211A45E29F97387E0BBE19C30F9DC
+:10F370000165BE777F78271BDE8F1F9DDC952F8F61
+:10F380007AD091551F533CBD0AF550983FBCE643D7
+:10F39000C37D92A69292F8D1E46F33E63DE8E2A8ED
+:10F3A000B45EBFE09B935517E59F74B0042FF2AF96
+:10F3B0008E80D0C7FEE4247D4CF20B337F98E1357C
+:10F3C000F2FF6B8B8DFC7F96D6DB144732FAB3CA03
+:10F3D0007DA6F8F63BD30C7C53F29F3B542F6DC2B5
+:10F3E0000A821EE334FB05BF7C5BE88176564BCF77
+:10F3F0001D98F73908F97F1B952E7680CA24D649C7
+:10F40000A59BB9294F268579A94C653E2AFBB25A9E
+:10F410002AD319CF8BCA646D54F66707A8CC669DB2
+:10F42000547A98DB82E540E6A57230F351E9636EC9
+:10F430008A7BBF9318CE3A04F09B7E3D233F3C630A
+:10F440003FB9518373EA2897754020A4ABC94C207B
+:10F45000DFE3376A589F26EB3B78BD84F72FFDE545
+:10F460004F7F141846FC46B43FC1DBBBEA3B6F2C10
+:10F47000213AB5507D0EF687FA8323B569A3015F63
+:10F480002B4733E2A3E70BB56FEAEB0F156A33F4B2
+:10F49000F5978BB46BF5F58F0AB459883FB29E5936
+:10F4A000A895E9EB371769E5BC3FF71FBD63D34863
+:10F4B000DFC50529A338BEE1CFA9FA2B090F7729AB
+:10F4C000563CD738416F763C4715E9C8EB88C3D224
+:10F4D000C7F377C2F1AEB0D3D283FD63A2A330F2FB
+:10F4E00027C0C3E18AFF665C8F999F280191079826
+:10F4F0006A8C8300BE93FF2CBC92DBE98C456F972E
+:10F50000F35E08CF99A6F3DB0E8C8C1B6B1F66FC99
+:10F510003D20F4BC8342CF7B47F899BBF61DB6264D
+:10F520009F7244E838B67D6865A7F4FCB2DBBE3F45
+:10F53000AAB4015D87EBE2DC28EF3AE2D9DB68A7E9
+:10F54000050EAB0CF58C4B5D6F69E1940708EEACD2
+:10F55000BF9BE20A725EC1673AF09FA0E75CDE4B98
+:10F56000DA975E078737B73B92C5BAEA27A55C935F
+:10F5700047F137AED70FB31D983515D699B681FB35
+:10F58000479390BE3114F6CC9FDC18176B9E6C61CC
+:10F59000C8A71A05FF34FBDF364E5AE1D6FBA71B7E
+:10F5A00093820AC6233343F1DC0F91CA82F12847C4
+:10F5B0004BBDA594071350DDA558AF6033F3A0BE33
+:10F5C000A045F594C2BCFB5A9E5B817ED84515765A
+:10F5D0008A4BD8B42914BF96F9182902CF1BD6C577
+:10F5E000794308C73E2EF2CF0E6B2C28457BB7DE41
+:10F5F000959282B89852B184FC87F52EEFEB784F44
+:10F6000023E0B6509E21736B8E32D057B6DD662D47
+:10F61000453E9EF5ECC82455B7EEE30D67E331CFC8
+:10F62000FD51B785DA1F5D39D1B1C485F711C15ECF
+:10F6300080729FFB9886FAFB56E89306E3DD5773CA
+:10F64000ACF9B21ECE31A9D46EC05BA7D7588F33A8
+:10F65000F91F6D26BDE0F06891F7318A8DC273BE47
+:10F66000E2C9F364FFCE7779C83F3EB149A17C97E8
+:10F67000F05E6F36EA9BC7EF1D42FEF0862655F816
+:10F68000A3BDE48F0E67B16CBCB753DDAC90BEAACE
+:10F69000367CB21ADF1B90E7C9C07106783B33DCB9
+:10F6A0003AFA7BF4FBDF8D4779D78017CF088F18A4
+:10F6B0008D23ED55793FBCDA7DB692FCBBCDBFF70B
+:10F6C00021FC93350BD1CC115B301DCF7F7DC96CF4
+:10F6D000A24BBC6F857A4C377DF47358A7EE9E41E0
+:10F6E00063EAC0049C3782BF1AF9CD4F3417927E6B
+:10F6F000B4BD6922E5F59BC7B967156B43BDB5710C
+:10F7000095A32D9AFE7B4FB62F1BEF619FDC58B25D
+:10F7100096C1F99FDC7B533ADE5B5FDC1CC7E23DA0
+:10F72000DDFB9FD8389AE65B8CF7A171DEE659764F
+:10F73000942B535B4AEC08B77B56CD7D563FCFC721
+:10F74000257E6731D09FB3F959C213170B0510AE50
+:10F75000BFB94ACB46FDE2442E8B9A97D9A798C7EA
+:10F76000177F7B958FEE999CCC8ADE2FA398C71FBD
+:10F77000EF2BF6487FF1DB4B53C91E7423BD1E6F80
+:10F780002A4C42BCB5611C1DE4A2ADFDFC2AC4FF9D
+:10F7900073150BDF5B0AED8DD3AE3B83E515F65A8F
+:10F7A000D29BD91F54A207D00BE9BED7DFE638DCC5
+:10F7B000F5BABC40D41F35835FC3C7D0FEB035A9AE
+:10F7C000213BF077DB9E53A48723BE6A3AFCA5DF7A
+:10F7D00028A1CF8B7C8FF451747F8E7E8DD75C17E0
+:10F7E0000C318CA32C74443BC7D8F3EBC645FD7693
+:10F7F00012D3E275F383540C915FDBCFE7EBEA277A
+:10F80000DAC10CD5687D422F37B7CBF50FD962A48A
+:10F81000CF6FE2F91445F4F358EBFD46D0F85E4D96
+:10F8200031137916330DF432546D5B3106CE8DBD34
+:10F83000CBF93FD875CC17255E15E1B3B0F6BE0203
+:10F840007E00CFB5A9B3C93E89B50E7BF080963353
+:10F850002262BF7D23DDB82ED9AF46E05D5C908586
+:10F860006C495886E85E461CBC8FF2FBD38AEFB821
+:10F87000AF894217B234F32DFC79F0BB11F2AC4CD6
+:10F880007C02D160B0D4472CFC7D4DC7E7123773A2
+:10F89000FDF7C41685F4DFF51B795EC4A741A89374
+:10F8A00072C1CF09558B2F84B2E3D2DD1F5CF242C7
+:10F8B000D37D433D06B82D62BA78D29927EF7A1BE3
+:10F8C000DB4F3F7D970F977B77EAA224CEB78E2E32
+:10F8D000C0794E5E6E277F0CFE1C123FA0E3D26003
+:10F8E0009C010FD7EF7E72CB02943BBB1D5E4CAFE9
+:10F8F0005BBCC5D81E97AEDB17E3F81530C0293CBA
+:10F900007016D0D191EFFF84EE792720FF447A5C06
+:10F910001947F7BBCC70FE6074D7F742983E0EC70C
+:10F92000C4BD0E4957C736D49F54619CB52BED1EFC
+:10F93000FA2E82C9FE3AE299A5A5EBE2BDF695FC46
+:10F94000BE25D3DB890323FB97E31E092C74785C67
+:10F95000DDC7EB867731C65B58A2ED2A06845D567B
+:10F96000E27B1ACBE31B16D2BEEBDA571E7913FAF1
+:10F970003425F87F867CF3D88641A314BCF762F562
+:10F98000D0FDBF86064B3CF2FDE6366BFC6084770B
+:10F990008385E47C735B6AC260944B2E0BC549512E
+:10F9A000AEA83AFFFE49C12723F2C397A4D77F121E
+:10F9B000043E9ECC13FACF24AEFF28CFEC21BDA38A
+:10F9C000A191C7A9A4BEE116F8E316F1C858FA0F31
+:10F9D000321E5C7762D12237F2B5C624FE1D8D45FA
+:10F9E00093BC01BC9779B58B91DC1880972350CFDD
+:10F9F00072B1E05498477573FDC6DFCC489F4971DA
+:10FA0000B9BC08EAB4966080D6AD713A73C07F087D
+:10FA1000CF843C8DE1F856935E6137E90DAAA9DEEB
+:10FA2000512CF250841EC184FE2DBFDB90786FCF25
+:10FA3000793DD2AFDB2CFC13A03F05E8FE47310B2C
+:10FA400022DE324DF3A4F68DD801E877C4F6F462D5
+:10FA5000B6AD5E177F52B457C96F20FD92D2FF201A
+:10FA6000FD1C238AC15E4BD2F9237E0DA6A54AF167
+:10FA7000B0CF104F72801D903D398C29FC9AC597EC
+:10FA8000D4D3EB2E2EEEF3A397F83D9F064B82774F
+:10FA90007B4EF77E19E3B8DF2C611FEC0DF5DAEB36
+:10FAA0001D749F66B2BA8BEECFB78EB4F03C65760C
+:10FAB000C08DFA40F218CE776F2FF1B9C7202377A7
+:10FAC000F972106F001E011BDEC3137EDBACDB0777
+:10FAD00026A03EFC5EC6A98DA897071A2DC46F24E8
+:10FAE0001C73565B36211AEAE273216B4124CEB6B1
+:10FAF000DE773680F77ECF5FC9EF1125CC3AB1179C
+:10FB0000FDA0EB065BC8CF7E77A246713BA01F87A6
+:10FB1000CAE375AF63BCADC9939282DFCF793A99DE
+:10FB2000B733718E0F24F6DDA6CF17E9BC92EFFB39
+:10FB30000125BABEB2F74ABECF8EDD00C85EE4D75B
+:10FB4000E2F678607F85E6D2D591F6E0FD1F06B833
+:10FB50003D3D6AF7FE8AC060B29344FBF90AB2E702
+:10FB6000D1C708ED1B776FAE40FBFC919CE8F3DE3C
+:10FB70003E8ECBEB47DEF00F407D36BC1BF0A75727
+:10FB8000B4F30D314B318D9B8D71A9F09D7173A331
+:10FB90007D8FE6CD719C9FB4425B5CAF881EDB5AC3
+:10FBA00061D65383C4AFCED51C7B85D2AE817F1482
+:10FBB000013D24B3E8FCF2C2FAAA371DF5CEFA3BA8
+:10FBC00095B5C83FEA415FC5B8609ADB4EFA6A4313
+:10FBD000F2774BF05CCED53037DE5BDD0E6A1FF27C
+:10FBE0002FF4ABE27DD4A9759CCFF8DDDCCF0A768B
+:10FBF0009CEF6AC4C70C2BE1A3D45FAD159CFF5CDE
+:10FC00001EC7F38B3B925DE4374DAEE3F9C4CE00E3
+:10FC1000E8B3B8BF493C1F5883FF900F49FDD63564
+:10FC2000CC6AC80BB69BF286ADA63CE16F8F31DA89
+:10FC3000338945237BD4AB7E0DF62FAE730FF01FB7
+:10FC40002C43600763F912D8ED58BE0C763BC60D05
+:10FC50005E5D9547E5EBABBCF4FCCD55C5544EC895
+:10FC60000E535C91FCC8E4BF612185FC7812BF5E35
+:10FC7000EE3F11F1BD84B76FFFD5CC4703FDA13D29
+:10FC800055F40FE45422FE75D5D9B595D8BF2A9DF9
+:10FC9000D79D636754223E4E9AACAD1B0378D2C702
+:10FCA000E2AB6EC4BE77C579A3D9F77DC7CAFB5E48
+:10FCB000D1ED77869F3A30FA735A894FC4F0E73C0A
+:10FCC000A0F075EC7D61F343E887EA35CBEA433C6D
+:10FCD000CE1E68F4F37F3E86D3C5D4B19C2EB3DF2D
+:10FCE00004FAE801EE923E62B5D7EF061488425757
+:10FCF000B26C4D64E3E99E75A57D6EB47CA66D8201
+:10FD00006FC61CDFC53C715744E8ADDE65A6B73051
+:10FD1000C577CFD57D672FCACBAF4E6F8CECC37044
+:10FD2000A546F23A0CF486FC5CADE1F4A65AF93D26
+:10FD3000CBAAFDDC3FB21DE90BCED98FF406FF9CA8
+:10FD40001AE0F53413BDD59BE9CD65A4B730D21BBD
+:10FD50008C971CE0FA85B3A2ED6BA5B73F7F457A7F
+:10FD6000FBCD5561CA6BE8C8A9CD40F8B48AEFDA7B
+:10FD70005D2A1DDE35D6CEE5C1708DFC020D388EB4
+:10FD80008BF4F90DF8BD94A9FD575B53007ED35356
+:10FD9000F3E97B023963FB0A7A38E0427FCD024DFA
+:10FDA000FB94E8EBBA33744FB18F85D36FDFB1AFFB
+:10FDB000913CC86A3C386B2AD2DD9D2AC949F3BE02
+:10FDC0006E1A2FE25B0A9F174E2E431FD77308BA95
+:10FDD000F4DC59AF38501FAF66DEDC1CFA3E0C7DF8
+:10FDE000B7E6870D7F73E3B8378D4FA1757956BF9E
+:10FDF00093ECE7FEB574B4DFE86A7241777A845F0A
+:10FE00009BADAF819E93C7F6E09FBD10FFB84FE852
+:10FE10000F78F4A837F8C53D4C19178949CF263F0C
+:10FE20006E4CFFE1700E1FF3FB67855CAD17FE5F44
+:10FE3000B3BE27F73FA4C43F0CF7A7B85EE57EE04A
+:10FE40003DCC83EB9471B3AE3C23A91F0658B01E82
+:10FE5000F56D2BA8327DB9BA81E375E51F093DF137
+:10FE6000C512FF681C771BF3EC45F9E6F2F27C053E
+:10FE70006789564CF0FC927AE086124D1BDB035EDC
+:10FE8000BD38459B34B628763B3B0FA38C8AC4B55E
+:10FE90004A6659395FA853041F70ADB543BD351983
+:10FEA000F89907F576BE6F37F00D0FD919463B620A
+:10FEB0000A3A23916F201F21E06AD3312F32498CF7
+:10FEC0001F91D7E157502F0D036C3741535280CB10
+:10FED000EBFAFD9CAFD881AF505CBA98DB09F29E7B
+:10FEE0008F739897EC2F55EBD97EB09AECFB256376
+:10FEF000051F296023116ED916CFFD63E079E183D8
+:10FF0000930F8D81C7450F2FEE8DE274F4B6C63284
+:10FF1000FC6ED74D8F9FDC867ED231FF15C7C4F7AC
+:10FF2000D128CFE05F2867E85CB6ED79B72260455D
+:10FF30007E151D8F0BAFE2782CE3AC3DE07123E121
+:10FF4000B188735E021EBB2E80C7CD884F51F078FA
+:10FF5000E357C4E307715C0D0F01E34653B41FF58B
+:10FF600084B75B276B8FF6D4AE8B1FF0FC21564312
+:10FF7000F6B38C5F9AD7D388F235B707BFD4BAED02
+:10FF8000F168CFD6D76C7F03BFDF585FC7EDEC8E2B
+:10FF900044AF03F38D03BF57E9BB54B1DE47BB3B0E
+:10FFA00000CC72E8553C0F7ADF9D71A109304EA656
+:10FFB0008BCBDB4C97C630EFDBEA0EDBFC89A8AFBE
+:10FFC000F918DA19F6540B0BE8FC3157D80E905C8F
+:10FFD000EE00398EF401F4C9E92D998F23E5F384FD
+:10FFE0003BEFC7480EBBAA13E4A08E4EDED85D4C93
+:10FFF0007EB8C4A2E757E07B6AA5DD83F83DE173D4
+:020000023000CC
+:10000000909BBA794A4013D1D7AF766418C699EC61
+:10001000CE31B44F4DFF86A1FD1AC0173BC5B1F9D3
+:100020003D3FA9D74CF3E41BFA258B38C737F3C6FD
+:1000300018C6B3AAE7378D46FA177AC438F80FE91D
+:100040005F35E90B667DC2AC3F9C1C6BBCBF32C206
+:100050002AF2D0AC3C3FA29539E8FB12C007E9FB7D
+:100060000555913C01A29311F6F0F67BD0AF32CF4B
+:10007000E10DC0B386DDD7A4578F8CF8CF5AEBB80B
+:10008000DFAFBEDDB10DE961ABA04B495FC3128F9D
+:10009000CD6324D7ED0CE5B1995E65BE93F41748A6
+:1000A0007F8252C3FD0CADE37378DE91E03FAD1566
+:1000B000DCFEFD91128A570671BAF4A444BE339750
+:1000C000CE94C0344EDF5A8A2855918F2AF35E7140
+:1000D0001CB4B3D3F97CEC759E37B9FA7BF8BE9BA0
+:1000E00005FA0B7F46564AC44F81F909CBF87B814C
+:1000F00069E2BD0122DFB2175F7F68B2986F049496
+:100100006AAD26FCD37E2AE3301E0EE540C59B80F7
+:10011000FE8F41AA8F022D4922BE9E29E2E94E257B
+:10012000C499C797E42357001BC5BC0496C2BF13EC
+:1001300032F1A72EA6127DD8B7A33CBAFBA8F77759
+:1001400098AADB90F8DDB726C0F3A6DFAB5EF49388
+:10015000DE9D15780FE9DA0AC81020BF96AF1ACFD6
+:100160004D9DE3704F85F7D4C0B6D518DFBDC21ED4
+:10017000DC4BE7B9268EE83D0CEF213E6C4D043A8E
+:10018000457C454FD7A8483E908C6384C7781D288E
+:1001900047C3D88FFB9B0DFECF28F926E42FB58AE5
+:1001A0007A836B3BE9EF6B53EDF8E54CCCEFC9AECE
+:1001B00043BCEC93C0EFD3321E371880FF18A4E382
+:1001C0005BEEE87E4DD0D7080EE1D54BD37BD2BB9A
+:1001D00062C6515C96903DE9E2E3288D375F170CCB
+:1001E000E9D629F7BDD6B55D59C02E657E668CA3CC
+:1001F000D4302D7E4494384A38A8E03A07D4F038F9
+:10020000CB00E1AFFFB2711475FC978BA3C8FDCE94
+:1002100010FF9E0E882DEE0D533C81CECB12599FC0
+:100220000E7E8F113F22DC102802F56B45FDAD5D7F
+:10023000073F7A12FEB97FE74BBBB0947ADC2CD132
+:100240003E73C8677B30776BD6BA15228E658C3FBC
+:10025000CC00AB4EEFE7C7FBFFFAFA2CD37A265A55
+:100260008D7182492E63FF29A9C6F6D2FE71DDCEBB
+:100270000DFDF2B45FA5FB7EEF76DEC7F877A374C1
+:10028000E7A05EB8EEC0BC398CFB78BAE3893E0EBD
+:10029000E07BD1CA524622BE58482FDD1A58BAB95F
+:1002A0001CE8672DC851CE8B3D06FA8BC43D4A35FC
+:1002B000C427E9EF8F454FC75C03C9FF3FA06E6FAE
+:1002C000DBA4DEAC2B0ED094E0FFC5958037035C39
+:1002D0006715D44306D4BD4CEDD7CD2BEA118F72F0
+:1002E000EBF6B54DD27D0F30D7EAB3A0FD9C5BF79E
+:1002F0002A3D8FA9CF77E72394B7962BF042E605E6
+:100300006EC5BC40807B6E8DF8CE6F4BCFF96F52BF
+:100310001E36E8F2FB2899C1A330FDF852EE75F3C2
+:10032000A733EEF795F375E5059AE6ED927F6E2E0D
+:10033000FF9C25FE0E845FD7BD0C718F03F61D3523
+:100340000FF4E49522DE143B8F8DDB9D735E7F0FEF
+:10035000C7BF64BB33C6B813B2C395D1EE47FD4DDA
+:10036000F8AD3AE2C359E837E8B045D7EB3F9E34E1
+:10037000E51F57F660C761DE2CC232D63ABF6CDE8D
+:100380006CF6180E2F196F95F9B3322FF642F9B3A8
+:100390005FD50F3F44F8033AAF64DCCF6F8A4398D0
+:1003A000D79B33AE2BFEE019D743FC41F67F2FC31A
+:1003B0001ED52F5E3F5EE049F7FB47941F0AEB4DC9
+:1003C000D5DB41F23D99976F1E0FECA2C2713A7FC7
+:1003D000A07F752EF9FB74F696CC8725FA68157EFA
+:1003E000882E3A30EB85221E62D60B657C44A9E04C
+:1003F000FE09A08F89E3FA70BD0BF3D2A59D27F308
+:100400004965DE28E685523CEA4BEA555FBB3DB5BF
+:100410007A32E575D5BB27BEFE55ECA9E5E38DF62E
+:1004200094DFC5FD0E7EB4A78677B7A79A4AFC373E
+:10043000E13999EDAA233FF890F263C10EBD99F01E
+:10044000EAABF209937FCA3186E3B794D3D29FB661
+:1004500077B0C5E0779DA2AEDC4BF9E235DCDF92E8
+:10046000A9B5919D6677D93DE86FB14EE274641BE2
+:10047000C6821A8FF3927F45E695A5B8B83D65F61A
+:10048000CB483B312CEDC400FFAE4AC77E1EB7758A
+:10049000A2BF053B9672B926FD2DB654E16F31E53A
+:1004A000633B4DFE15B3BFA5659CB0BB84BFE51192
+:1004B000C5730F92FA735B26FF1641F1F387163B63
+:1004C000D1D4FF65B0F19BC2DFF2A00BD6B7FB3DE4
+:1004D000A3BFC51CFF8A12F722E7D59BE3B653DC06
+:1004E0004DC257D2ADF46765D6F1EF024C51772972
+:1004F000C85F5A5D1CBE2AFAB35223FE2CE5998FC1
+:10050000BAFC52981FD73D4E5EFB06AED30A0C676D
+:100510007D34FF9680AB391E9554C7FDE35F973F4E
+:100520002B34CEE8CF2A78B0F07EFC3EF1C887CBE2
+:100530000E61396ADB777ADF0065F1E3F79761F9DD
+:10054000F737C239A8779AFD58CFE0C78CFB74877C
+:10055000AF198E124FFD35124F5D76A2DB0A0E47A2
+:10056000339CD2348EA7B980A7A02274E15F4732B2
+:10057000A7CFCC49DED7D1BF3660989545C3636B12
+:100580001DBF0F2DE1B855C031A56609F909CD7819
+:100590003AA0E5D2F0F38C097E3FDB52780FC2ED32
+:1005A000F987CA7E8BE52F82DF7122DCDA1FBBFF61
+:1005B0009B027E19F45D5C13FC26C580DF042FB717
+:1005C000AF274FF4FF1DF9F335C021D01FB2BDA9ED
+:1005D000C0618C0319F969DAD7E49F0A77F153F601
+:1005E00076EE25F0D32D26FF545A80D34D5AE028BD
+:1005F000D16726D0673CFAAB6AB81E09623FE8545F
+:10060000D0E6E6FC55CA35643916103E5BDD3CEE9B
+:100610001CC54F19A2EFF69AF8303A70F4780772B9
+:1006200035FBAA3E1179B7B586C7D15E9BE4F3E0EE
+:1006300073195773966839577D35FFE337AED2F992
+:100640001F014F69FF2AE03B7EA7FC6A902768FFE5
+:100650005B6BC236942B5575B72A7E285F1CCBCFB7
+:100660003F2DDDCF30CEDADD5F174E44BD7DC2E0D9
+:100670002E7C28BE4A870F57DC79EE7EF473C5C204
+:1006800087CC18F94A17C6878906F9DADA850FB5D3
+:10069000EB2E4BBD787C68477CE8A3C30741FF691C
+:1006A00035E107917EAD021FAC6EE063000F15F1DE
+:1006B000605824EE29E9212CF20FCCF0090706C579
+:1006C000C84358A114F7B0BE8BCE3F10F1D07A11B9
+:1006D0000FF5D7F17CD98E3BE3A618F30FBCB4EE2F
+:1006E000A9AE5A459FC71F254FB616CF4FC63965CD
+:1006F0005C73F244DF0AC49F0979FC9CC3B1E34CEC
+:1007000021BCDF0AE8E736E1F9F708CFE5FD03A1F0
+:10071000C7BD36495B89E38EB00729CF19F4BDD533
+:1007200058DFBAFB49FEDD5CE1879479795FD96FC8
+:1007300096640FE27D49E9376B4DB46FC7F3AE663F
+:10074000E1C9F4BD5E8C53A0DFE9DE38CA6B5CA85A
+:1007500080E10DEF7F7BA27F33D11FF3513EAE7F4F
+:100760008EC38D7A7E43F29474E41B556B5592EBE5
+:10077000B1EC1B496F55C06F88DEEA38BF4903FCF6
+:10078000227C0B28C46F3281DF70FEA331D4EBAC26
+:100790004877AEEEFCA6B507F85F24DF790AE11CC6
+:1007A00085EF3C83CF757CA70DEB5F16EE7957196B
+:1007B000F90DC60368FF485FFAFD9BF5D9AE7D1BB6
+:1007C000E94BD2DD7F009DFD19E11A85CE8E209E7A
+:1007D0007D053A3B1383CEDE37D1D95FFF4DE9CC9F
+:1007E00032BEE8C274B659E095CCDF967AC550B5F2
+:1007F000ED6C2ECEFFBF9CBFFD1D915F77A1FC6D00
+:10080000FC5D8CFFD49CCFFDFFFDA9FFB1FE54FF22
+:10081000F83E5FDD9FFAEB2B3DA4E79AFDAA0F8E11
+:10082000D66E1EDF831F4EF269ABE4D3C08F91F703
+:1008300056013F43FE9C56D1F9975F727BD3EBF490
+:1008400090BFE10E1C2F53F06B335F06BDB36EFCFF
+:10085000D7E1978CE16FF857F90D8788BCD20BDD93
+:10086000B71F32CE23FCAED1EFDDD70BFBBE1EC6C9
+:10087000C07B7A5BEFB4071B60C1FF1CCBCF674422
+:10088000CD75D72091FDEE267B42B807BB49FE3DD2
+:1008900088E655FE174EE4EAF7C7A2CAADAEFD9949
+:1008A000F464BDDDE4B904BBE9FF8E37EAC9D61AAA
+:1008B0006EE75A41DE515C5F2B0E21BFCE0C286DD6
+:1008C000981AEC4FAD55500EA6D5F8281FFE52E3EE
+:1008D000FA663C8A15E7FFBAE3FAE6BC817F9738EF
+:1008E000FFB1F1D1E3FCD2FF6A8ECB8FB037979284
+:1008F0007CADB4E05FB2600DBB3FD87E0F9EF73C8D
+:1009000007DDD330E703C48ADB8F48B1879D0363DB
+:10091000C7EFA5BFE0115BED1B68873FB2DA42E786
+:100920006BCE1B1896C8F3C75BC7AF7A98F27FA44B
+:100930003E5C21F84C9D6247FCF7570489CFF8B51F
+:100940009DAB319E9CE6626DA867B58FE7F4A2A6C9
+:100950006BC467AC157EC22B199FA8CAE6F7E6E206
+:10096000057EA9836BDFC2F1930FA85E8C6FDF8BCE
+:100970005D816724A2AC443D628C85F2225A945A70
+:10098000F27B342B1EFA3B1EC9C3DCA41F3D9DEC39
+:10099000FDC35CCA0FE57F6F64DFB4EFA6E3FAEE38
+:1009A0005EBD3A1DF5C08C093C1F71D3B453950848
+:1009B000675B1EE87F0A9586BF4B2BCB8F26F038EE
+:1009C00009F005CA4784756FA1F8FB603BF9D9545B
+:1009D000ED81EF201F502F9B4278DDACB8E72DC092
+:1009E000F3CAB5931ED3903B6AEE22D8D7BA3EFE27
+:1009F000A61C3CD7E4C1B4CF86E4BE49A88FAECBD9
+:100A00001A48FA6793524BED812C0BBDA78AF8FC6C
+:100A1000BADCEFBEBE18FD59D9FCFE674BEEA9D774
+:100A2000B15FCB18FEC76CCCEB55DDC67B52F8E14D
+:100A300023E4DF6A7F0BDD2F54455C5C35C59537B9
+:100A4000C87D8AFB2BF1826F55E5AE994BDF4F488D
+:100A5000B5BB11C91A13C3E5586FBCD3C6304EC716
+:100A6000ACCD063DAD7E95310E617519D7D3D475E9
+:100A70003FE1D5F9C8671A15510FFC82D7B19D9295
+:100A8000FEDAE623BE34C6F3FA35BF79723EC511ED
+:100A9000C5FA6C727D7DF8DF5BF97430A3FB6D5590
+:100AA000B670D4EF0B5F685DDDC7DDA48971D9FF37
+:100AB000E6B84DB93C4E641E57F6339F9B6E1EA69A
+:100AC0005CD23CA7CA09FF0EAB0CF98C793EF3FB54
+:100AD000F2BDAA3EB349DEFDABFAC782EBF2095D77
+:100AE0007FDF8575C52DC43D3B8F2E3E563F651477
+:100AF000DD8B6D556A896E02C996A8F9BFB1E947C9
+:100B0000373E0F8E10BFB5728833B52E9EF2382453
+:100B10003DC93C0F6BBA859E33311EF0E157491F2A
+:100B2000D2BACE8BB9FB46C6552BECD4DF7C8FD81E
+:100B30004CA7323F84DECB89B45BC5BCE6FC109782
+:100B4000C6BFB7D25AF900F9F32F354FE438D22790
+:100B5000C18D915DD8F05FCD942FC5DAF9F3867C15
+:100B6000377DE770BDEC97C828BF499E83539C032F
+:100B7000137691CCBB89969783F65CBA84B9870DBE
+:100B8000C67D36CAF73D3E0DF9E53D578CC8C7EF27
+:100B9000773EB873D313680F6DD9B5E67D2CE38724
+:100BA0008DA0EFA726782D5EBC9FE5BAB1BD1D399B
+:100BB000E4DA618B9BE938F5E74AF75315CD0DFD73
+:100BC0001D2ED776E4BFCCA1D077AFD41FA605D118
+:100BD0006E4D5F64C48356C5DB17FF3E6660A3425B
+:100BE0007A177E6F40DF6EF718EBC7262842BF34B6
+:100BF000DA31CD31EE750DD5B8DEAA9AEEB56EB20A
+:100C000079E8FBB99BD6A9A40F6C1271A5F1DADDC6
+:100C1000F357036DDFDEC8FF9E706B893D88F75385
+:100C20005B13DDD7CDC5BA907F32BEDDFC8DCB82A4
+:100C3000FABFFB9439C14378B8B1A46F06E371F0F1
+:100C40000CDFF0D878F165CBFF0132DEFE59008071
+:100C5000000000001F8B080000000000000BC55BB7
+:100C60000F701CE5757F7BBBB777924EA7BDD3C9CC
+:100C70009C8C6C56B6146490E5B56C9953B0A3BDCA
+:100C8000D3BF9371E9C5FC3333B67BC6C6214D266D
+:100C9000114E494C42AA333A59F21F84AC24953381
+:100CA0006D9AB30999CC8401259DB6860073024ADA
+:100CB000288144492990690684096E483313A7C1E5
+:100CC00089D2A1A5EFBD6F5777BB3A59B6E34ECF96
+:100CD000237FF7ED7E7FDFBFEFF7DEFB6E8DDAFF60
+:100CE00072DB7A007855361ED6B104154C3FF0E71A
+:100CF0000319FFD3F06F09007D857A2AC57B052093
+:100D0000FF810470F57115F2767BFCFB6E4718A02D
+:100D10008D6A63905A8DC5E48D1ED800E0B7DA5C09
+:100D2000234FB6AEA0F95E93E1617ED20FA94AECE3
+:100D30004B9F8E42393480135C2DFA284B6855F84E
+:100D400059017030B2F54734BCBBBD5DAAB969B377
+:100D5000BE85E681FEC966805551E7FAEC76A73A72
+:100D600070F13500BE1CE4BD412AF326B450396D44
+:100D70004A589EDBFE196DB3BEF03C3E281AB79E62
+:100D8000C603DEB75C4C3F7CEE853413EFFE8A96DB
+:100D9000DB01F73D74830AB25482CE8BD455253FD4
+:100DA00025E13AC7EFBDFA468800640EC9D088E352
+:100DB00078A345EDF02FF5D47A9809887564F87911
+:100DC000D2243E053BBCBC5FFAF89730FF0088DFB9
+:100DD000FA8177641CEF4B49553F8CEBFD526AEF6B
+:100DE000576EC17AF625D990F83DFE87FCBBC79AAD
+:100DF00003C626581EAAFCA2FFFE53F7BDF922F136
+:100E000028A9BE457403AD882E2BB830FD1B0AF30C
+:100E10003D183B3DB212E9901D293DFE1DD5FAA7B4
+:100E2000885E369D171AD77E2FEF9F9AEC5A57A8E7
+:100E30008F94A77798C887D180014074D8FF1CBFD2
+:100E400087F52897B50BF31329CAF47993BE62BBD3
+:100E5000AF759A7B4CACCBA770E96B00DEAED46F5C
+:100E6000DC8AAFBA236FED20FAEF097834E2A3DD14
+:100E70007FF0A817F2012204CE8B72B70566766C5C
+:100E8000C576D0E0653997236BF9F9EECA94E2C1D3
+:100E9000F2F3E60A9617BB7F1F7C59D987CFD77824
+:100EA000B557494EB211895684CF9180B8F4CD0A16
+:100EB00098412C7BF5B8BF1EC74D3E491301748481
+:100EC000C623E0016879E2785DBA99B6614E3721B0
+:100ED0007F4216BBAEF54DA73A71BCC19765E37E64
+:100EE000AC87027BB700CA91F4182E969E8720E744
+:100EF00043BE2B819E77E9F9A6B3005D45F2D4315C
+:100F0000EB87AEA6423D8E2317D73BFDB58EF6DDAF
+:100F10005ABDE3BD0CA691473AF5465739DA55B6A6
+:100F2000ADD768BD7DFA5AC7F31B9ADA1DFDA14BF8
+:100F3000393D83F58DF88FF82E83A8F37B5C77A07D
+:100F400019EB45FD1528AAE3FBBF352B2367AEC57A
+:100F5000CA75701DE911F2E5E411B23FDBFC06F140
+:100F600065D00BA7A42A20D5CF402B11DBD4234872
+:100F70003FC992D757CC7A960B29F0FC1F580E9F89
+:100F80009CF148C4D727A0F53036FA1B4D9FF2607C
+:100F9000932B6948EC1F4541D7914F0D385E592B73
+:100FA0003F3757623D0A52A60FEBCBB05D54882203
+:100FB000BC40EDFC70E00BA21D2CA3761A64EAB0D5
+:100FC000AE19504E7CADC3713E19E67E993EABDF43
+:100FD00055A25FA62A2CC66FA179D15C76637902EF
+:100FE0000CF0C9448714C04AB222FD5C5E45ABC216
+:100FF000E70F81D14AF5469861BB84EC97A87E053E
+:101000004C6AC2C8E785DD9E514267FCC2EE97D2AA
+:101010009782DE2870C6E607CDDB61FE80F4EFD64E
+:10102000DBDBAAD28185FB29FB9F75E8AD1AD79936
+:10103000CECAFE5ED61365FFF3FCFEEA78EA551AC7
+:101040008F48EF6F9D4FEF16350F64BFB27130328E
+:101050003844F6F1CDD15DC8DFCCE37EA3112E1F5D
+:101060003F2E960F39D0CA89AE72FFA5F2013FB864
+:10107000AFC029FF89C32C8C269F937F045FFEE7B6
+:1010800052F8E2E607DC570DD0BEB81DFD6B295FB4
+:1010900026AD647A98D1D602FDB19E5965D12B6CEC
+:1010A000F14316655EB69E2BE185F942E355870B49
+:1010B000FC598C2FD114BE6F2DF047EE379978F67E
+:1010C000B9EC83B312952B2483F9B5524E79A85EFF
+:1010D00021E52DD093633B1D048DF9B314FAB98C2F
+:1010E000786776117FB2FB71229447781F4F59C2FF
+:1010F00049D6B9980D24FCF5645F9B14C383F5E6CB
+:101100004A4F2A8774BC52813CEDAF56810CD9738B
+:1011100044063C7EF6713CADF09CC9E231EDA17E07
+:10112000F7FA7359A9307F8B65B77F54F94D6DA6D7
+:10113000B940E7D364BFD6087A78D8FE4CE6A97FD9
+:101140003409C6A03EDF9E61BB8C6CD9292A77D2B8
+:101150008B76A65B26887569E4FB7F209C41E3299A
+:1011600058AF88A77BE3354C770884D92ECD5478C7
+:10117000A0142E300957ECB2E6D9F6117D790AD7C2
+:10118000B96BC4F7168D07599F1317B8FBEB1214F0
+:10119000F7B7FBCDC995BBFF25EA01ECAFB9201C21
+:1011A000107F6C6315D179419C497A525DDC4FF018
+:1011B000498DA41977A8A42FD58B8FE375E1177BF0
+:1011C0001C2F0A2E8DE3B5F08B7D4EED85B35E6549
+:1011D000A5B54EA4D76EB03F11A6E74E8B7E7F46D5
+:1011E000E75590E8A9AB44A43D9052496E3F861064
+:1011F0009A70FC8A437B828C17A04B23FA48F9EB48
+:10120000E50FAEBD083A5A74DA997FD7AB935DDA31
+:101210005F096FDBEF5714DEFF76FB4D8CDBD101EE
+:101220006820FE5658EBAB38F5FE0019F5FB2BFE97
+:10123000F2E50E5CFAD0BFC8865C4FEF11CFE23802
+:101240006520CEEF0AD2535C77C59367FE9BDADB4D
+:10125000EFC17A4F2343D1B89E8AA38C672B82AA11
+:10126000CE38DB2567368E86F7050E0E58D42B1A3E
+:101270005722BC6CFB3D3CAE347FDED5163EC757D3
+:10128000F10F2E00CFBB713ACCE173F13E105085C7
+:101290009E1888738BE9B8809ED9EBB6FBD5A8A9B8
+:1012A0007AA3B9447F8B0FCD685708EF5D5107B91A
+:1012B00003B8DE91917DF10AAC1FAB01DD87AF86EB
+:1012C0007B3E2B11DE4844842885620217D21434F9
+:1012D000BFD79A2FF40BFD7013BEDF5B173070651C
+:1012E00070C5AF4C2D8EE3DC59E7374C7C9005F18F
+:1012F0003E13F3087F3203AF101EDD63F1C7FBA47A
+:10130000C099CC1BD4C399B8C0577B4E7D720BF1EA
+:1013100077347CB391C7767BD03E55131E1BF332D6
+:101320009E435CE7C0FDBE58110EC4BF3B8F7B1DC2
+:1013300075AF0B27BE19471C48CCB470E02FE320D3
+:10134000E6C582CE93CB350F04226C4F572BD31EAC
+:10135000ADC4396BF3C3C6DF4FD5083A7BDF1374D6
+:101360004187791F3DF7BD27FC3134E081B62574F4
+:10137000FA0BFAF9DA903EF4F43D711E604F5EB755
+:1013800089FF68DD6E3CEC73E161F77A6D3EC80958
+:101390000B276F800D441FC4E78C13ECFDB8F7F1E9
+:1013A00024FAE75D28144F0FF8B9CC0F685C3E3380
+:1013B00010E5F2B9011DBA10803D3FD0C4E50B0322
+:1013C000063F7F7120C6A54D87F9F44129C4FD5E13
+:1013D00065AD59699E4ED139BAB4CBC3AA70EC3E03
+:1013E0000FD3ED1CCA27295F10BD2005977855D271
+:1013F0009333692F96FF738525AFD7FACE4EF9B098
+:10140000FD682D18F763FF2B627B59CE369DF514CE
+:10141000F404C8CF2977C409E250EDA877FAAF7475
+:10142000B4EFD6563ADE87E3336CA77AA3D73ADA1D
+:10143000D97CFE3AF959B8BE635DA735A26B9FBE51
+:10144000CED14EB90FF9DF42FECFF58E7141DE628B
+:10145000909D0E6F77CA61D0C557F5AEF3FB41364C
+:101460009FCD84530F16E2AF5B5E6DBA86E7E82A24
+:10147000FCCA2CF99548D7B026E86AEF77D4DAAFE2
+:101480003DAF1213FBBBDCFE6590FCCBFA52FEE5D0
+:10149000CF2D3A2FE25F269DFEA59BAE8BF9977F5D
+:1014A0009E70FA97174ACF9DCB45DC2DFC92CC7EDF
+:1014B0008B9CECE773B07A5A367AC9245AB8AC924E
+:1014C0006C00B6DBD9A6E608671E8399289DE70F56
+:1014D0004A485594B7EA66A396ECCCA321E3D56DB0
+:1014E000841BFB3CC649ECF26CFCD628E18EA103C0
+:1014F00027A27858C103090FCF3B163FC3F10B4514
+:10150000078E5F6069E64AE013BBFD3D435E3E0F18
+:101510001EDCA1E6246CFF60A576EB36AA5BF32007
+:10152000414C7A3FD1F6A11CF929A309DD8A336524
+:10153000A2E4AF7C69C7865A3EAC14ACAFA6E606FF
+:10154000EBC9E1322D487E74768747A37DC9EBFF56
+:10155000EA33241F0F48FD871AC87FABF1009D1F97
+:10156000D9D086DA5DD84EDE893086EA3B36BC4E6D
+:10157000367BA2463FD440FD430D4CBFA18DB7FA48
+:10158000699ED1D0923E8A8F8C767B984732E18CCF
+:10159000208FD3743EBF47D68ACE77E0B805AF53CD
+:1015A0008E78F22A9D57843F82F3E37B87432A3962
+:1015B00005F08F895B4E641AF831DBAF2B2C3F604E
+:1015C000E78E84C9F68AF004D267A777A6A6D4B9B5
+:1015D00070D08A77CE9D3B51E77A4ACCC3B8401190
+:1015E00033F247B7E3B4F8C9DED893A373741C523F
+:1015F00049B29F998087E31D0BED5F0938E7B3C7B8
+:10160000E7F1648AA395996545FBD7ACF8EFCB0960
+:1016100089F1EA0F89EF6D62199125857529490FC6
+:10162000F7B3FD5794DB6D93240F16BDD1AF78BE91
+:10163000F8BC7D2D21E2B2AFCFC911365D52B48E18
+:101640008DAA359EC1718A35AEF8B59B3F171BBF79
+:10165000FEA5B59FD7B6DF745E3F7955CED9CFD7FB
+:101660000962FF56BCDB6BF1FF1A79721FC9E3FFF9
+:1016700077BCDBD77979E3DD6F937D229C8776FE9B
+:1016800061FC9EFD698EF5054E9D7D9BF57AD51218
+:101690000BBF40B4C1C68F2BA874E90F017DE4DFF6
+:1016A000F85AC4A5581FB7EA99D5625C28D6CB155D
+:1016B000E4178838CAB2CE95C2DF227B42CC558C63
+:1016C000E544D780F29D8C86FB280F1C831096BEC4
+:1016D000C8AE0C951DCBF5D118AE6B7C9587CFAB02
+:1016E000F1CAF489215AFFAA4049BD68EE14F66F89
+:1016F00084E495FD24303DA46F92AD1C90F6209FAC
+:101700002640F0D9EC0CF17A146D2C7607CA4DCC3A
+:101710009207DC0FF7778FFF611ABFCD31FE374894
+:101720004EB3D6E034CE2E1C27DE29D97A95A1F708
+:101730007E6B3EBF3E16235C90E8D4C47B65AD4112
+:10174000FA301E2A3D5FC29A0F2814B3A1808FAED3
+:10175000D82EC601BFE8FFA07476DBE9F5CC57D6DA
+:10176000275A07BDAF309CF6C13D7E5993D3BF5178
+:10177000EB9CED5373FB70FA450F48A5D77BB7D5AB
+:10178000BE63B99033928FFB4BC8875BDF558A7B72
+:10179000E2B869E207DB0F617702CA7482FC9D4000
+:1017A0003318834CE029DE6FEAA9865333EBC9CEA8
+:1017B000070DF283143F9ACAD6829FE8DEF7627E55
+:1017C0009EA240C6DB3ADFDFC371CDAA5671CE645C
+:1017D0008AC6FB8C252772B13F584FEE887E23EDD9
+:1017E00073EC90CCF1A5B17B7DDB4A9DD3F726CE7F
+:1017F0009FD7399E423F829CD4C78E1EDA8DF5DF7B
+:101800006A1ECDC76DF492791DCDAACFE57552172A
+:1018100096D719EB0AF7355C4C5E678171E7CEE32A
+:10182000F9799DE39D48A76301915F99CBEBDC1C9F
+:10183000B9A0780E58E772D8B2CB957D961FB15FEC
+:10184000623FE299B67F3FB286E4ACCDCB720047EF
+:1018500027A0584FB66CD7BF5A4DE7CCEB3E681463
+:1018600076CDA4F16CBFD8A69F6A8D9FF8F64B0A7F
+:10187000B51FAFF56CE0F120EFF344793DAA55CAEE
+:1018800054AE51F372158D1B06439C0F79899EC788
+:101890009158C5FEC1E8EC4F3AAB284E1200834C7C
+:1018A000D0685C3B50455F280B4478A75ECF91BD64
+:1018B000EDF45738ECFF689F2AEC6B23FA4BA43FFA
+:1018C00053FA57F760FBE1FD658C9B1EA8F308FDFA
+:1018D000CA4839A99EF0B5D3EF199F5C21F0D851C1
+:1018E000AFD188ED1F9914ED77C737E464C6DD4E9C
+:1018F000BFA84F77FA45BB6B5B5F25BC08435E8E84
+:10190000C76B16AEBDA1C9E92755D6F7BF403865EC
+:10191000E790C0C307A3E125BBD1FEADEDD21D7991
+:10192000B25D437772DE684805CEA78EEE50593F10
+:1019300046BD6F1DDFCDB8B19CE938B143AD4D1741
+:10194000E9CBC7BA7C3CCEC40E813F105EA6274BC4
+:10195000BCFF589765A714E073DC96973FF9B8A0D1
+:1019600073B00E723AE1B8BE7D79F22BC7EB704FBF
+:10197000F87E28DAD03745F3BF2203EDD32D87F761
+:1019800090135CB40F5FCCE3A093D797EAA7F1E183
+:1019900006D0C9AE7525B14E7180ED2A507CC017B6
+:1019A000FD0BDE6F18EB6558F727C7320AD6FD0D21
+:1019B000E975848B9FBDF7B6917884CE3BA1DFBEDD
+:1019C000ED7B533751FBF55E28A3F5812E45697DEC
+:1019D0001909449EDFA90F07B3FFD4457C3A684834
+:1019E000CCA29D7D5BEFA2F59C8B94336E1AF3A67F
+:1019F00076B13DBAC5AF65F80C9C613FC2FB051FCF
+:101A000090DC4DDCFB4E0DE1EFABBA56B0BE95E974
+:101A10004EFFDA0F637C6E6F34A7B753BF8D3195DD
+:101A2000321EF04CFB19E6DB449BCFF0E13A26DA9C
+:101A300025A6F3EFDABC399AE769755AA6799FFEB5
+:101A40001DCE5D5F4ABF4BEB95AD47EEF6A3B1AD42
+:101A50007E928B83307D33D127332BE254EE76DFB9
+:101A6000B0E4E060F6962685E3592AE7DB95B38675
+:101A70005985A3876653DFA2D8EB2B9D0AB7BBA776
+:101A8000D6939170BCE13E95F568B8323D42F23C88
+:101A90008C72CF7E5204EBA467B511E370D17CE366
+:101AA000EDB736913D7BB9AD8CF1FD6BCFD6DE91B4
+:101AB000C12113F2AFFEEE31F2ABEA54E6E7B0B764
+:101AC000FF75F283326D65BCDEE796A9E0277B10D7
+:101AD000B9E321F2B3E191ED502CAF1349A1A71363
+:101AE0007542EFA5C7B6B31F302EC94C67B3E6A445
+:101AF0004478CC97B4E34E22CE14B7CCD9C4F6EFD9
+:101B0000721C6A699F88A3C69356BC490E64582EFE
+:101B1000AF2B7B88F4DF54BC0EFF78D359A7BFBC32
+:101B2000D4E52FBBE3515BBBAC78841577B2E532CB
+:101B300068B5998859767ABD2F27E4B0BF566B9E59
+:101B4000AFDF3FB4F0F3F4801F2502E027031AD77C
+:101B500083E66F0E54139F06A2FCFC4F379E908ABB
+:101B6000FB8DAEBFC5AFB33D9989D2B86E3BE2964F
+:101B70008B373ACB1DE789BDCECAF60410EE3D7710
+:101B8000962D326C0ACC74F2D908D38162BC9FA71F
+:101B900075FA284E26D6F91CADD3477132B1BE175F
+:101BA00006742E5F1C68E2F23B5D20F201B67DB840
+:101BB0000AED03D2A1AB4ED4C91E10FFC3913B382E
+:101BC0004EE68B2A1AE9BBBF6E2C2F15D98789CA1E
+:101BD000FE9FDE4976BF26C0F2E8DED7B1AE397C83
+:101BE000E8D8D7CEF67D6C77CEE13C447FB433772E
+:101BF000B11D42BBC0F36E576FE775986897D82E3A
+:101C0000F47FF536B60B5E203977DB817046E877D6
+:101C10005A17F13BFB9ED09C5DC0797238CF336878
+:101C2000D7A93E8C7680E6196E7FEB1334EFEFFE7A
+:101C3000500E34C4C48E57D92EBC7C0EA0FA32DAB2
+:101C4000055B0FD73DF71F27324A293E6FBDED9444
+:101C5000A0870682AEDB5225FCC48BE5339817863D
+:101C60006372CACCED22EFA8321D16CC3B663C064F
+:101C70008505062795A4957704CA3BDAF9C7A2BC67
+:101C800063B933EFA8E6B28C6F7256DEF1D6CD227F
+:101C9000EFA896CF040AEBB0F38D43F4A8B6909F5B
+:101CA000FF87AEF4CB5D6D853CA32E893CF8D571E2
+:101CB000F387F41C22613EFFDD794A3B1F89F04E19
+:101CC0004A17E5375BF0B93F5CC87FB9F399F6BDB9
+:101CD0008C1675E6E411A4CBE0ED7EC60FF6FA068D
+:101CE0001FFFF0EBE948E13E809DEFB4F39976DE0B
+:101CF00013D7FD4EF1BAE14960BB034FF84FD0F95D
+:101D0000E65E6F453CFD4B6A3F6FDD17985FDC0276
+:101D1000D6F888BB489FDFB4E838D7BE4BF89F6B36
+:101D20005411DF86A0CAFE4EE2DB0190096757AA74
+:101D300027492F76C14C37D1773024705EF6012FBA
+:101D4000DB49E8D6997F35AAC9F7216A3E5F661C50
+:101D5000C0C7D9292D48F1A7AF759AD0DD46EB1839
+:101D6000BB792BAD03713BD9BB371ABF12E17C3F66
+:101D7000DD7BAA22FFCF584E7110BDBBF47DA58E2E
+:101D8000E567B7F2BC951E20FF2C5B66BCA013BDB7
+:101D90009F5278BC3E1CC26CE5FB4B5D6A98C61135
+:101DA0007EF260E034F3ABA3D1B796E37A95A5FD5C
+:101DB000C0A5DD820E9B712C15C7792A9EAEA57534
+:101DC00053AC34CA722CFC3BBD1B6CFB759F674344
+:101DD000210E5621A7F56EB2D78F480A9D8F3E4B34
+:101DE0006E6C3FB13B61D6770B7E9834BF7D0FC8D8
+:101DF0009EFFEA6E61175FE9323F44EDDA681E929A
+:101E00004B2D13273D6C49A33C48AC3FAE3CBC90E6
+:101E10000BB7BCDAF2369787B7E450D244BE16E56A
+:101E2000AA8DF6074FEB531E89F2EDE91347A8EF91
+:101E300025E6BB3F9D3037D1BA77C7531D54BE71DD
+:101E4000EF6DC0799D0BBCC7D1B1BC3F4A79FCE1B5
+:101E500032819B1F8D1B0E7B77B7459FBBBB055EF9
+:101E6000BA1665669AF44031AA80F5F82EC6D1B646
+:101E70007D1A1B487FEFE78D85FED90198A47CD0A1
+:101E800042EBF01EDAC771DDC1BA849FEC0FDAB7FE
+:101E90002AAA0FD799D1E275642B859C679689B8D9
+:101EA00005C5D332BEC2FBBDDD32EFA7B30EF224AF
+:101EB0003BBE80C8BBF95071753C7F7C662CCFB8A7
+:101EC0002600931462F814E90FDDFF8B186092BFAF
+:101ED000599702D26F9F56E84F79D4CEBA7EBE6F23
+:101EE000B9D03872D4EE9FE6FEE3DD1A8FAB463CE4
+:101EF0008E38C0627473D36588E8D6B830DDD40BF1
+:101F0000A69BD03B37BD0E13BD909FCF863ECBFB2B
+:101F100083F73B59CF7C1AEE13CB31CBBEC80113EC
+:101F2000D29564A352882029CEDE0F9487B6E92C7F
+:101F30006B82CEB2D6CFFD7C7506A457135DD24C12
+:101F400017371DD04E00D9897F7EFC7884F0690751
+:101F5000D6A3C27E800FCB5F5BFEA0ADA75BE0C7C0
+:101F60000111FF769E17F3ECA9553E6AC59FDDCFA0
+:101F70006FE92913B84E0707DD2B2BB7323F4E8E82
+:101F8000B4323EC0F33343F7627A6A1BCBA97EB901
+:101F9000F388EEFCA13B4FE8CE0F16E4C6F4D33A2B
+:101FA0007FAB9DCE7CB484BCD8E5114BDF8606FCAC
+:101FB00025F5EE08EA3BF16FB8DDCC50DEE860684D
+:101FC00026CA7233F52EE362E525D9207CA9288242
+:101FD000CF3DCB66988FBD311328DF746460DB770B
+:101FE0008AC7FD753CFD23B26715DAA449E30420D6
+:101FF0009FA1F36773B5D95F0A37FD9B6547BA1395
+:10200000A97F257BD5A10BFEC7E2E6AB6C172FD0CD
+:102010006E2DA44F8A4DBB8BD6A7D3429F62FB582F
+:102020009F46EBFA19678DFE58262455C091963EBF
+:102030008DB69F617DB7F5EA3D4B9F3A63422F28ED
+:102040008E40E777B0CE64BBF15F963E29A827A407
+:102050004F3E4B9F825AA13DC5C73B89CEF85CA934
+:102060009BE17EC198A57FA44F01BA3F0C8C0386EB
+:1020700051EF282EE2D6AF8E06716E6A89B4A7871B
+:10208000F0C5B2AD1C971FAEFBCF6AC62F96FC17EA
+:10209000F06E2B9FE7E7463C06E9430B01E8D6824A
+:1020A0001ED8FBDE382B431E59B36956E2F223B328
+:1020B000155C76CC967169CE5673199F0D719998FF
+:1020C000BD92CBCED95A2EBB66510FD621DF67EB1E
+:1020D000B9EC99BD96CBDED9555C2667D771BBBEEE
+:1020E000D9B55C6E9EBD9ECB1B66DBC53C4D625F69
+:1020F00025F481D26097411F8C0C54921E7CFC7594
+:10210000B6EF9ACA7794B2A10D9C27F22933AC0F8F
+:102110002763C2DEF706049FDCFAD09D48AF25BADC
+:10212000BBF5610EDF2AA011FD55B03E2EFC80F8F4
+:10213000A7BDA7E83EB21A3559CE109F7CB887F4E8
+:10214000E31271C21CCE5CAE321EB571E6E832C439
+:1021500099F5059C39DC2EFCB2EC033EF6DF764B9C
+:10216000E27ED9A713E91B7BD82F1671A2F4CD7E8E
+:102170008D707336D4130D505CEFA00C142F401CDF
+:1021800092E2764A4ADC67BD407D8EC5857ED8EDF9
+:102190005BE0B4A7FF2270CC1BF4B57D61BB10BE21
+:1021A000D473D6DB29EC8226EC42B6AE7F84F3D220
+:1021B0002EBB609FB3480F875DF85C8F854B2C3D2D
+:1021C0000FD789F3324C7601E9F3C51EDB2E38CFE9
+:1021D00059C5C621491B8758762129FA216E779C5B
+:1021E000B3C86E3F14E16294A3C19EB6F9F681CFE5
+:1021F000F3A2736EB0A1314EBF25089D8538896763
+:102200007056DF6C943877B25A2BEBC194D209C563
+:10221000F1958BD6B3907DEE987CEEB8DBD9FA368B
+:102220003CD527F6699D4353B87FB348DF7A3571B3
+:102230001EE1F9F3F59E12E74FC772339D2AB1CE26
+:10224000477B84BFF1834D16EE455C690418DF9728
+:10225000C40D8FF608BB4EBFD37802ED4F77329393
+:102260005574D6F34749CE37764DCB1446F8486CB3
+:10227000EC154A89A09E3EF6C7E8E9D1B895EFDB98
+:102280005F2D2E3B5BE562F26FE3225B0FE6EDA371
+:10229000DEDC568A1E4B7B05BE1F1CF1F4D1853F48
+:1022A0005B2EA694958C7F4AD85BD3B82CF6F6C2E9
+:1022B000F0C7149E83C4F7F3E08F374BD9DB85F06A
+:1022C000C7991E912747FCF10EF5EB6816F8636974
+:1022D0002FFCDFE08AF869A6DBA5E28A0F6CFBB170
+:1022E00000AEF0F6EAE27715DA0CDB8FE025E20AC1
+:1022F000B79D40FC50DE4BF431C4B96BFFDE842F38
+:1023000050169D5F6867AA7A055ECFD3E5B19381C9
+:102310004446623D4885E8F998B982E5E872E903E8
+:10232000E2C42B7B8BEA8BE9C505B79BDCC171400E
+:102330003B9FF9FBB2600BC547F6FB45F9B9F2E0EC
+:10234000492AC707441C7A94E27E588E7B81F307A2
+:102350004352B97152A27ECB7322DEDEBF86E29E6B
+:10236000D7F786AD7872FF75FCBB1BF8A2236FBA56
+:10237000F0BAC43D5F1AEA03BE0F5EA7711CDDA26E
+:102380004B981880F31E5EE5671C78B8EF91E377F1
+:10239000505CA64FC4C140D1EB3F4AE72FC29A58C8
+:1023A000D1B920837286E2F32374B79D41C7367199
+:1023B0000FDA5A4F7512FDF722FFA32A76D7F77E60
+:1023C000EEBC37E429CE231F31B75689CBCA77F14B
+:1023D00038B69E1C094CFAB5227B7374C079FFC9CC
+:1023E0005DCA6DAFF07DC3634D0AE72F1E581F29EC
+:1023F000233D39D42082B4E58D9E54AE843E0FF443
+:102400004A8EB876C83AE7CBBAC5BA169A6F784002
+:10241000C46FEDBA4F4F9924A7E5F56329A26B79F4
+:102420006344A2F8ABFDFEF65E61370E4B46BE0379
+:102430008979B8529C17BEBA0C78080F84F6AE237F
+:102440001AFBEBFAE14C80EE6F64E06D2CC3613552
+:102450005D6ADD83D6BA0F7B7329C2538757299CE7
+:10246000E7444C55324EF609CB4E97378EF3FAA01F
+:1024700051E17C95BBDD0EBB9D3AC6F98E438DDFE5
+:10248000D4695F87E807374B914BC9871F3A40767D
+:102490006600F9EA25794E73597ECDB798FEA32DD3
+:1024A0008A46FBE8969B0FD03CC79260105E71CBCA
+:1024B000C531D0CA687CB77C54AC7E8FE34FE54110
+:1024C000CA8C901CCEF8851D157216B0F8336A8838
+:1024D000BCCF684AE4AF6CFE15DE8BFB06E7520A00
+:1024E000FB2576FE6A0940491C67EBE590158F9F36
+:1024F000F77E799ECF9DA39BF251BA2711D4FC465B
+:1025000092C67DC4B9AE837876F2BAFA44FE62CE42
+:102510003EAF15FEE1FC758AF881F2CCBBC2AE5A23
+:102520007E42B0F93DB6ABF6BDAFDE8D425FABACDF
+:102530007BF755919429E872B7C31E48D7FC224314
+:1025400079A6076BC5DD84F04671AFB65C05234FF5
+:10255000F700FA027CBF6949CCCAD76D13F72BECA0
+:10256000FBE16A4475C41322505427DCE9AA83BCFA
+:10257000FDBCF7E0F6FFECC48BCF15F1FDA55EE7DF
+:102580003DF2C5FAFF7E20F7E27368908E19E7D717
+:10259000479B6F5F1E887169CBA52DA761DA62EB3F
+:1025A000C2FDC743A992799A6052E8C362762DE2D0
+:1025B00033DBDF41BE7BAB81F3675FD9E41CEF37D0
+:1025C00096BEFEC6D22F7539D4129E1A0B093B3027
+:1025D0005606DBBE5B426F972455B61B057D70E245
+:1025E0000A5B8EE6D363115CB1BA4BE00A2D5C4600
+:1025F000B8E898917881F281EF69AA5E2CB7EEB8BD
+:10260000BB8D2BD2493BFEA74A840BB4C00CE3ED33
+:10261000395C60E108372E28F7E6B6917E94AF5218
+:102620006D7BC576E5F3DFFFFB8732BCBF8C547C46
+:102630008E8EE66FE771C3AEB83B449CBF63798B67
+:10264000F017AE27AC4F4E2728FFB84511BF6F1BC0
+:1026500033A1F81ECEB8E7FDD83BD6F7F76D1C5274
+:102660004FEF8F4EF3EF6BE01E289EFFE04D3BF9DE
+:10267000F7148BF1DF5E17DDEB2AD69F8BD50F2386
+:1026800069E9471994917E9C83FB380F0F6349C712
+:10269000F9C41989256C12C407B7A96CB0A082547B
+:1026A000D01BE8B5F2E3E9393BA9503FC3EA564BEA
+:1026B000B72C64CA37E4F9778BB6BD39073FE379A5
+:1026C00033CF48D21CEEBA12DD7FFA3DE44A5A827B
+:1026D000E6A1D2BDFE1560F0F3064871F921E8E7E6
+:1026E000B209C6B8BC0626B96C86692E5BE02C9789
+:1026F0006B419769927560CAC05737D35CBF0E3281
+:102700005CB643BA9DEE970FD5EC5D4BE7D12D2E0D
+:102710003AD9742EA1F78C2B6D7AD8742F27E35DEC
+:10272000B3385FB321618F3B6379F61F0201819B50
+:102730006D7FDB1E67211C7CB9F09A8D33FF17CFAC
+:10274000A588169043000000000000000000000073
+:102750000000001800000000000000000000004021
+:102760000000000000000000000000280000000041
+:102770000000000000000010000000000000000049
+:102780000000002000000000000000000000001019
+:102790000000000000000000000000080000000031
+:1027A0000000000000000000000000000000000029
+:1027B0000000000000000000000000000000000019
+:1027C0000000000000000000000000000000000009
+:1027D00000000000000000000000000000000000F9
+:1027E00000000000000000000000000000000000E9
+:1027F00000000000000000000000000000000000D9
+:1028000000000000000000000000000000000000C8
+:1028100000000000000000000000000000000000B8
+:1028200000000000000000000000000000000000A8
+:102830000000000000000000000000000000000098
+:102840000000000000000000000000000000000088
+:102850000000000000000000000000000000000078
+:102860000000000000000000000000000000000068
+:102870000000000000000000000000000000000058
+:102880000000000000000000000000000000000048
+:102890000000000000000000000000000000000038
+:1028A0000000000000000000000000000000000028
+:1028B0000000000000000000000090000010000078
+:1028C0000000000800009008001000000000000256
+:1028D00000009000001000000000001000009DA803
+:1028E00000000000000000080000000000000000E0
+:1028F00000000000000000000000000000000000D8
+:10290000000000000000000000000000000091A096
+:102910000000000000000008000093C00001000457
+:1029200000000001000093C8000000000000000249
+:10293000000093D00000000000000008000093D4C5
+:102940000000000000000002000094980000000059
+:1029500000000008000093D80008000000000008F4
+:1029600000009B3800400000000000400000941868
+:102970000008000000000008000094580008000053
+:1029800000000008000094A800C8000000000098A3
+:10299000000096380098000000000028000096789B
+:1029A00000980000000000280000C0000540003032
+:1029B000000005400000CB200008000000000001DE
+:1029C0000000CB21000800000000000100002008EA
+:1029D00000100000000000100000200000000000B7
+:1029E0000000000800009D600008000000000002D8
+:1029F00000009DA000000000000000010000000099
+:102A000000000000000000000000000000000000C6
+:102A100000000000000000000000000000000000B6
+:102A200000000000000000000000000000000000A6
+:102A30000000000000000000000000000000000096
+:102A40000000000000000000000000000000000086
+:102A50000000000000000000000000000000000076
+:102A60000000000000000000000000000000000066
+:102A70000000000000000000000000000000000056
+:102A80000000000000000000000000000000000046
+:102A90000000000000000000000000000000000036
+:102AA0000000000000000000000000000000000026
+:102AB0000000000000000000000000000000000016
+:102AC0000000000000000000000000000000000006
+:102AD00000000000000000000000000000000000F6
+:102AE00000000000000000000000000000000000E6
+:102AF00000000000000000000000000000000000D6
+:102B000000000000000000000000000000000000C5
+:102B100000000000000000000000000000000000B5
+:102B200000000000000000000000000000000000A5
+:102B30000000000000000000000000000000000095
+:102B40000000000000000000000000000000000085
+:102B50000000000000000000000000000000000075
+:102B60000000000000000000000000000000000065
+:102B70000000000000000000000000000000000055
+:102B80000000000000000000000000000000000045
+:102B900000000000000012C800800000000000805B
+:102BA0000000000100000000000000000000A00084
+:102BB000071000000000071000001EC80000000001
+:102BC000000000080000AEC000080000000000087F
+:102BD0000000AE4000080000000000080000AE80C9
+:102BE000000800000000000800002008001000009D
+:102BF000000000100000200000000000000000089D
+:102C00000000A01007100040000000400000AF408E
+:102C100000080000000000010000AF4100080000B3
+:102C20000000000100001ED00000000000000001B4
+:102C300000001ED8000000000000000200001EDAA4
+:102C40000000000000000002000012B000080000B8
+:102C5000000000080000000000000000000000006C
+:102C60000000000000000000000000000000000064
+:102C70000000000000000000000000000000000054
+:102C80000000000000000000000000000000000044
+:102C90000000000000000000000000000000000034
+:102CA0000000000000000000000000000000000024
+:102CB0000000000000000000000000000000000014
+:102CC0000000000000000000000000000000000004
+:102CD00000000000000000000000000000000000F4
+:102CE00000000000000000000000000000000000E4
+:102CF00000000000000000000000000000000000D4
+:102D000000000000000000000000000000000000C3
+:102D100000000000000000000000000000000000B3
+:102D200000000000000000000000000000000000A3
+:102D30000000000000000000000000000000000093
+:102D40000000000000000000000000000000000083
+:102D50000000B00000180000000000180000B300E0
+:102D600000400000000000400000B30000400002EE
+:102D7000000000010000B30100400002000000005C
+:102D80000000800000400000000000400000000043
+:102D9000000000000000000000008000000800406B
+:102DA000000000040000800400080040000000044F
+:102DB0000000BB0000280000000000280000BC400C
+:102DC00000100000000000100000880000800000DB
+:102DD0000000008000008800000800800000000261
+:102DE00000008C00002000000000002000002008EF
+:102DF0000010000000000010000020000000000093
+:102E00000000000800001108000800000000000891
+:102E1000000011680008000000000008000011A870
+:102E20000008000000000008000012700008000008
+:102E30000000000100001271000800000000000105
+:102E400000008D00001000040000000400001320AA
+:102E50000030001800000010000013280030001897
+:102E60000000000200000000000000000000000060
+:102E7000000000000000000000000000000011E859
+:102E80000000000000000001000000000000000041
+:102E90000000000000000000000000000000000032
+:102EA0000000000000000000000000000000000022
+:102EB0000000000000000000000000000000000012
+:102EC0000000000000000000000000000000000002
+:102ED00000000000000000000000000000000000F2
+:102EE00000000000000000000000000000000000E2
+:102EF00000000000000000000000000000000000D2
+:102F000000000000000000000000000000000000C1
+:102F100000000000000000000000000000000000B1
+:102F20000000000000008308008000000000008016
+:102F30000000000100000000000000000000200868
+:102F40000010000000000010000020000000000041
+:102F50000000000800008D100008000000000008BC
+:102F600000008D7000080000000000080000845080
+:102F7000046000280000046000008EA0000800002B
+:102F80000000000100008EA1000800000000000108
+:102F900000008408000800000000000800008448C9
+:102FA000000000000000000100008DF40008000097
+:102FB0000000000200008DF6000800000000000282
+:102FC00000008E040010000000000004000000005B
+:102FD00000000000000000000000000000000000F1
+:102FE00000000000000000000000000000000000E1
+:102FF00000000000000000000000000000000000D1
+:1030000000000000000000000000000000000000C0
+:1030100000000000000000000000000000000000B0
+:1030200000000000000000000000000000000000A0
+:103030000000000000000000000000000000000090
+:103040000000000000000000000000000000000080
+:103050000000000000000000000000000000000070
+:103060000000000000000000000000000000000060
+:1030700000000000000030000040000000000008D8
+:1030800000003008004000000000002800003390DD
+:1030900001C0001000000008000032000020000005
+:1030A00000000020000037200000000000000008A1
+:1030B0000000102006200038000000080000A000DA
+:1030C000000000000000200000003EA900000000F9
+:1030D0000000000100003EC80000000000000002E7
+:1030E00000001C4000E00008000000080000000094
+:1030F0000000000000000000000040000008000088
+:103100000000000100004001000800000000000174
+:103110000000404000080004000000020000406081
+:103120000008000400000004000040000008000047
+:10313000000000040000400400080000000000043B
+:10314000000040400000000000000008000040486F
+:1031500000000000000000080000800000000000E7
+:1031600000000010000050400001000400000001B9
+:103170000000500000000000000000200000500887
+:1031800000100000000000040000500C00100000BF
+:1031900000000001000052C7000000000000000114
+:1031A000000052C6000000000000000100003000D6
+:1031B0000030001800000004000030040030001847
+:1031C0000000000400003008003000180000000279
+:1031D0000000300A00300018000000020000300C2F
+:1031E00000300018000000010000300D0030001811
+:1031F000000000010000300E003000180000000147
+:1032000000003010003000180000000400003014EE
+:103210000030001800000004000050000100008091
+:1032200000080004000050040100008000080004B1
+:103230000000000A000000000000000000005068CC
+:1032400001000080000000010000506901000080C2
+:10325000000000010000506C01000080000000022E
+:103260000000506E0100008000000002000050705D
+:103270000100008000000004000050740100008084
+:103280000000000400005066010000800000000201
+:103290000000506401000080000000010000506048
+:1032A0000100008000000002000050620100008068
+:1032B00000000002000050500100008000000004E7
+:1032C000000050540100008000000004000050582D
+:1032D00001000080000000040000505C010000803C
+:1032E000000000040000507C01000080000000018C
+:1032F0000000507D01000080000000010000401827
+:1033000000100000000000040000409000100000C9
+:1033100000000004000040980010000000000004BD
+:1033200000004110000000000000000200004112F7
+:103330000000000000000002000041140000000036
+:103340000000000200004116000000000000000222
+:103350000000604000080000000000020000604221
+:1033600000080000000000020000604400080000A7
+:103370000000000400006080000800000000000859
+:10338000000060C00040000800000008000060006D
+:1033900000080000000000020000600200080000B9
+:1033A00000000001000060040008000000000002AE
+:1033B0000000634000080000000000080000638077
+:1033C0000008000000000004000063840008000002
+:1033D00000000001000063C00008000000000002BF
+:1033E000000063C400080000000000020000640048
+:1033F0000008000000000004000070000010000041
+:103400000000000400007004001000000000000430
+:1034100000007008001000000000000400007000B0
+:103420000008000000000002000070020008000018
+:10343000000000010000700400080000000000020D
+:10344000000070400008000000000002000070440E
+:1034500000080000000000020000704600080000A4
+:10346000000000020000764800080000000000088C
+:10347000000070800008000000000002000070845E
+:10348000000800000000000200007688000800002C
+:10349000000000080000804000080000000000015B
+:1034A0000000804100080000000000010000804290
+:1034B0000008000000000001000080430008000038
+:1034C0000000000100008000000800000000000271
+:1034D00000008002000800000000000100008004DD
+:1034E0000008000000000002000080C0000800008A
+:1034F00000000002000080C200080000000000027E
+:10350000000080C40008000000000002000080806D
+:103510000008000000000001000080810008000099
+:10352000000000010000808200080000000000018F
+:10353000000080830008000000000001000080847B
+:103540000008000000000001000080850008000065
+:10355000000000010000808600080000000000015B
+:10356000000060000008000000000002000060028F
+:1035700000080000000000010000600400080000D6
+:10358000000000020000604200C0001800000002BD
+:103590000000604000C00018000000020000604C05
+:1035A00000C00018000000080000604400C00018BF
+:1035B000000000080000605700C000180000000173
+:1035C0000000605400C000180000000200006056B7
+:1035D00000C0001800000001000066400008000064
+:1035E00000000008000066800008000000000008DD
+:1035F000000066C000080000000000080000D9427A
+:1036000000180000000000020000DE400000000082
+:10361000000000000000E0000000000000000004C6
+:103620000000DD4000000000000000040000DD4458
+:1036300000000000000000040000DD480000000061
+:10364000000000040000DD4C000000000000000449
+:103650000000DD5000000000000000040000DD5408
+:1036600000000000000000040000DD580000000021
+:10367000000000040000DD40000000000000002009
+:103680000000DA0000000000000000040000DA0082
+:1036900000000000000000680000BB6000000000A7
+:1036A000000000000000D000000000000000000446
+:1036B0000000B0C000000000000000040000B0C422
+:1036C00000000000000000040000B0C8000000007E
+:1036D000000000040000B0C0000000000000001066
+:1036E0000000D6B000000000000000040000D6B4C6
+:1036F00000000000000000040000D6B80000000038
+:10370000000000040000D6BC00000000000000041F
+:103710000000D6B000000000000000100000D348F8
+:1037200000000000000000080000D3580000000066
+:1037300000000080000000100000000000000000F9
+:103740000000D35800000000000000080000000046
+:08375000060022000000000049
+:00000001FF
diff --git a/firmware/bnx2x/bnx2x-e2-6.0.34.0.fw.ihex b/firmware/bnx2x/bnx2x-e2-6.0.34.0.fw.ihex
new file mode 100644
index 0000000..78b4161
--- /dev/null
+++ b/firmware/bnx2x/bnx2x-e2-6.0.34.0.fw.ihex
@@ -0,0 +1,15442 @@
+:10000000000052D8000000680000070C00005348B0
+:100010000000318000005A58000000B000008BE062
+:100020000000C14C00008C98000000D800014DE891
+:100030000000F16400014EC800000074000240306E
+:1000400000005250000240A8000000B800029300D7
+:1000500000012110000293C000000FFC0003B4D87F
+:10006000000000040003C4D8020400480000000F90
+:1000700002040054000000450204005C0000000679
+:100080000204007000000004020400780000000078
+:100090000204007C121700000204008022170000F6
+:1000A00002040084321700000604008800000005E6
+:1000B0000204009C12150000020400A0221500009A
+:1000C000020400A432150000060400A80000000489
+:1000D000020400B802100000020400BC001000007E
+:1000E000020400C010100000020400C42010000030
+:1000F000020400C830100000020400CC40100000D0
+:10010000060400D000000003020400DC0010000020
+:10011000020400E012140000020400E422140000B3
+:10012000020400E832140000020400EC4214000053
+:10013000060400F000000003010401240000000098
+:1001400001040128000000000104012C000000004F
+:100150000104013000000000020401D00000890603
+:1001600002040258000000360204025C000000365F
+:10017000020402600810000002040264081000007B
+:1001800002040004000000FF02040008000000FF59
+:100190000204000C000000FF02040010000000FF39
+:1001A000020400140000007F02040018000000FF99
+:1001B0000204001C000000FF02040020000000FFF9
+:1001C000020400240000003E020400280000000099
+:1001D0000204002C0000003F020400300000003F39
+:1001E000020400340000003F020400380000003F19
+:1001F0000204003C0000003F020400400000003FF9
+:10020000020400440000003F020404CC000000018E
+:1002100002042008000002110204200C0000020069
+:10022000020420100000020402042014000002193D
+:100230000204201C0000FFFF020420200000FFFF3A
+:10024000020420240000FFFF020420280000FFFF1A
+:1002500002042038000000200604203C0000000FAB
+:1002600002042078000000210604207C0000000F1A
+:10027000020420B800000001060420BC0000000FAA
+:10028000020420F800000001060420FC0000003FEA
+:10029000020421F800000001060421FC0000000F08
+:1002A0000204223807FFFFFF0204223C0000007F07
+:1002B0000204224007FFFFFF020422440000003F27
+:1002C00001042248000000000104224C000000004C
+:1002D000010422500000000001042254000000002C
+:1002E00001042258000000000104225C000000000C
+:1002F00001042260000000000104226400000000EC
+:1003000001042268000000000104226C00000000CB
+:1003100001042270000000000104227400000000AB
+:1003200001042278000000000104227C000000008B
+:10033000020422C00000FFFF020422C40000FFFFED
+:10034000020422C80000FFFF020422CC0000FFFFCD
+:100350000C042000000003E80A0420000000000153
+:100360000B042000000000030605400000000D0003
+:100370000205004400000020020500480000003291
+:1003800002050090021500200205009402150020CD
+:1003900002050098000000300205009C08100000D3
+:1003A000020500A000000036020500A40000003095
+:1003B000020500A800000031020500B000000004A2
+:1003C000020500B400000005020500C000000000A6
+:1003D000020500C400000004020500D40000000172
+:1003E00002050114000000010205011C00000001CB
+:1003F00002050120000000020205020400000001C5
+:100400000205020C0000004002050210000000403E
+:100410000205021C00000020020502200000001C52
+:100420000205022400000020060502400000000A28
+:1004300004050280002000000205005000000007B3
+:1004400002050054000000070205005800000000EB
+:100450000205005C000000080205006000000001C9
+:100460000605006400000003020500D80000000635
+:100470000205000400000001020500080000000160
+:100480000205000C00000001020500100000000140
+:100490000205001400000001020500180000000120
+:1004A0000205001C00000001020500200000000100
+:1004B00002050024000000010205002800000001E0
+:1004C0000205002C000000010205003000000001C0
+:1004D00002050034000000010205003800000001A0
+:1004E0000205003C00000001020500400000000180
+:1004F000020500E00000000D020500E80000000019
+:10050000020500F000000000020500F800000000F5
+:10051000020500E40000002D020500EC00000020B0
+:10052000020500F400000020020500FC000000208D
+:10053000020500E00000001D020500E800000010B8
+:10054000020500F000000010020500F80000001095
+:10055000020500E40000003D020500EC0000003050
+:10056000020500F400000030020500FC000000302D
+:10057000020500E00000004D020500E80000004018
+:10058000020500F000000040020500F800000040F5
+:10059000020500E40000006D020500EC00000060B0
+:1005A000020500F400000060020500FC000000608D
+:1005B000020500E00000005D020500E800000050B8
+:1005C000020500F000000050020500F80000005095
+:1005D000020500E40000007D020500EC0000007050
+:1005E000020500F400000070020500FC000000702D
+:1005F0000406100002000020020600DC00000001DA
+:100600000406020000030220020600DC00000000D5
+:100610000718040000AC0000081807D800050223E2
+:10062000071C000029B30000071C8000312E0A6D52
+:10063000071D000034A816B9071D80002E6C23E4A6
+:10064000071E0000034B2F80081E07F03F02022503
+:100650000118000000000000011800040000000064
+:1006600001180008000000000118000C0000000044
+:100670000118001000000000011800140000000024
+:1006800002180020000000010218002400000002EF
+:1006900002180028000000030218002C00000000CF
+:1006A00002180030000000040218003400000001AD
+:1006B00002180038000000000218003C0000000191
+:1006C000021800400000000402180044000000006E
+:1006D00002180048000000010218004C000000034E
+:1006E0000218005000000000021800540000000131
+:1006F00002180058000000040218005C000000000E
+:1007000002180060000000010218006400000003ED
+:1007100002180068000000000218006C00000001D0
+:1007200002180070000000040218007400000000AD
+:1007300002180078000000040218007C000000038A
+:100740000618008000000002021800A400007FFFCD
+:10075000021800A8000003FF021802240000000095
+:1007600002180234000000000218024C00000000D1
+:10077000021802E4000000FF061810000000040048
+:10078000021B8BC000000001021B8000000000342F
+:10079000021B804000000018021B80800000000C3B
+:1007A000021B80C0000000200C1B83000008647046
+:1007B0000A1B8300000001570B1B83000000055F2C
+:1007C0000A1B8340000000000C1B8340000002262F
+:1007D0000B1B834000000001021B83800008647033
+:1007E000021B83C000000226021B148000000001CF
+:1007F0000A1B148000000000021B9440000000014E
+:10080000061B944800000002061A1000000002B304
+:10081000041A1ACC00010227061A1AD00000000898
+:10082000061A2008000000C8061A20000000000276
+:10083000041A1BF800900228061A3718000000045A
+:10084000061A371000000002061A500000000002CD
+:10085000061A500800000004061A50180000000490
+:10086000061A502800000004061A50380000000440
+:10087000061A504800000004061A505800000004F0
+:10088000061A506800000004061A507800000002A2
+:10089000041A52C0000202B8061A405000000006B6
+:1008A000041A4068000202BA041A4040000402BC64
+:1008B000041A8000000102C0061A80040000000330
+:1008C000041A8010000102C1061A801400000003FF
+:1008D000041A8020000102C2061A802400000003CE
+:1008E000041A8030000102C3061A8034000000039D
+:1008F000041A8040000102C4061A8044000000036C
+:10090000041A8050000102C5061A8054000000033A
+:10091000041A8060000102C6061A80640000000309
+:10092000041A8070000102C7061A807400000003D8
+:10093000041A8080000102C8061A808400000003A7
+:10094000041A8090000102C9061A80940000000376
+:10095000041A80A0000102CA061A80A40000000345
+:10096000041A80B0000102CB061A80B40000000314
+:10097000041A80C0000102CC061A80C400000003E3
+:10098000041A80D0000102CD061A80D400000003B2
+:10099000041A80E0000102CE061A80E40000000381
+:1009A000041A80F0000102CF061A80F40000000350
+:1009B000041A8100000102D0061A8104000000031D
+:1009C000041A8110000102D1061A811400000003EC
+:1009D000041A8120000102D2061A812400000003BB
+:1009E000041A8130000102D3061A8134000000038A
+:1009F000041A8140000102D4061A81440000000359
+:100A0000041A8150000102D5061A81540000000327
+:100A1000041A8160000102D6061A816400000003F6
+:100A2000041A8170000102D7061A817400000003C5
+:100A3000041A8180000102D8061A81840000000394
+:100A4000041A8190000102D9061A81940000000363
+:100A5000041A81A0000102DA061A81A40000000332
+:100A6000041A81B0000102DB061A81B40000000301
+:100A7000041A81C0000102DC061A81C400000003D0
+:100A8000041A81D0000102DD061A81D4000000039F
+:100A9000041A81E0000102DE061A81E4000000036E
+:100AA000041A81F0000102DF061A81F4000000033D
+:100AB000041A8200000102E0061A8204000000030A
+:100AC000041A8210000102E1061A821400000003D9
+:100AD000041A8220000102E2061A822400000003A8
+:100AE000041A8230000102E3061A82340000000377
+:100AF000041A8240000102E4061A82440000000346
+:100B0000041A8250000102E5061A82540000000314
+:100B1000041A8260000102E6061A826400000003E3
+:100B2000041A8270000102E7061A827400000003B2
+:100B3000041A8280000102E8061A82840000000381
+:100B4000041A8290000102E9061A82940000000350
+:100B5000041A82A0000102EA061A82A4000000031F
+:100B6000041A82B0000102EB061A82B400000003EE
+:100B7000041A82C0000102EC061A82C400000003BD
+:100B8000041A82D0000102ED061A82D4000000038C
+:100B9000041A82E0000102EE061A82E4000000035B
+:100BA000041A82F0000102EF061A82F4000000032A
+:100BB000041A8300000102F0061A830400000003F7
+:100BC000041A8310000102F1061A831400000003C6
+:100BD000041A8320000102F2061A83240000000395
+:100BE000041A8330000102F3061A83340000000364
+:100BF000041A8340000102F4061A83440000000333
+:100C0000041A8350000102F5061A83540000000301
+:100C1000041A8360000102F6061A836400000003D0
+:100C2000041A8370000102F7061A8374000000039F
+:100C3000041A8380000102F8061A8384000000036E
+:100C4000041A8390000102F9061A8394000000033D
+:100C5000041A83A0000102FA061A83A4000000030C
+:100C6000041A83B0000102FB061A83B400000003DB
+:100C7000041A83C0000102FC061A83C400000003AA
+:100C8000041A83D0000102FD061A83D40000000379
+:100C9000041A83E0000102FE061A83E40000000348
+:100CA000041A83F0000102FF061A83F40000000317
+:100CB000041A840000010300061A840400000003E3
+:100CC000041A841000010301061A841400000003B2
+:100CD000041A842000010302061A84240000000381
+:100CE000041A843000010303061A84340000000350
+:100CF000041A844000010304061A8444000000031F
+:100D0000041A845000010305061A845400000003ED
+:100D1000041A846000010306061A846400000003BC
+:100D2000041A847000010307061A8474000000038B
+:100D3000041A848000010308061A8484000000035A
+:100D4000041A849000010309061A84940000000329
+:100D5000041A84A00001030A061A84A400000003F8
+:100D6000041A84B00001030B061A84B400000003C7
+:100D7000041A84C00001030C061A84C40000000396
+:100D8000041A84D00001030D061A84D40000000365
+:100D9000041A84E00001030E061A84E40000000334
+:100DA000041A84F00001030F061A84F40000000303
+:100DB000041A850000010310061A850400000003D0
+:100DC000041A851000010311061A8514000000039F
+:100DD000041A852000010312061A8524000000036E
+:100DE000041A853000010313061A8534000000033D
+:100DF000041A854000010314061A8544000000030C
+:100E0000041A855000010315061A855400000003DA
+:100E1000041A856000010316061A856400000003A9
+:100E2000041A857000010317061A85740000000378
+:100E3000041A858000010318061A85840000000347
+:100E4000041A859000010319061A85940000000316
+:100E5000041A85A00001031A061A85A400000003E5
+:100E6000041A85B00001031B061A85B400000003B4
+:100E7000041A85C00001031C061A85C40000000383
+:100E8000041A85D00001031D061A85D40000000352
+:100E9000041A85E00001031E061A85E40000000321
+:100EA000041A85F00001031F061A85F400000003F0
+:100EB000041A860000010320061A860400000003BD
+:100EC000041A861000010321061A8614000000038C
+:100ED000041A862000010322061A8624000000035B
+:100EE000041A863000010323061A8634000000032A
+:100EF000041A864000010324061A864400000003F9
+:100F0000041A865000010325061A865400000003C7
+:100F1000041A866000010326061A86640000000396
+:100F2000041A867000010327061A86740000000365
+:100F3000041A868000010328061A86840000000334
+:100F4000041A869000010329061A86940000000303
+:100F5000041A86A00001032A061A86A400000003D2
+:100F6000041A86B00001032B061A86B400000003A1
+:100F7000041A86C00001032C061A86C40000000370
+:100F8000041A86D00001032D061A86D4000000033F
+:100F9000041A86E00001032E061A86E4000000030E
+:100FA000041A86F00001032F061A86F400000003DD
+:100FB000041A870000010330061A870400000003AA
+:100FC000041A871000010331061A87140000000379
+:100FD000041A872000010332061A87240000000348
+:100FE000041A873000010333061A87340000000317
+:100FF000041A874000010334061A874400000003E6
+:10100000041A875000010335061A875400000003B4
+:10101000041A876000010336061A87640000000383
+:10102000041A877000010337061A87740000000352
+:10103000041A878000010338061A87840000000321
+:10104000041A879000010339061A879400000003F0
+:10105000041A87A00001033A061A87A400000003BF
+:10106000041A87B00001033B061A87B4000000038E
+:10107000041A87C00001033C061A87C4000000035D
+:10108000041A87D00001033D061A87D4000000032C
+:10109000041A87E00001033E061A87E400000003FB
+:1010A000041A87F00001033F061A87F400000003CA
+:1010B000041A880000010340061A88040000000397
+:1010C000041A881000010341061A88140000000366
+:1010D000041A882000010342061A88240000000335
+:1010E000041A883000010343061A88340000000304
+:1010F000041A884000010344061A884400000003D3
+:10110000041A885000010345061A885400000003A1
+:10111000041A886000010346061A88640000000370
+:10112000041A887000010347061A8874000000033F
+:10113000041A888000010348061A8884000000030E
+:10114000041A889000010349061A889400000003DD
+:10115000041A88A00001034A061A88A400000003AC
+:10116000041A88B00001034B061A88B4000000037B
+:10117000041A88C00001034C061A88C4000000034A
+:10118000041A88D00001034D061A88D40000000319
+:10119000041A88E00001034E061A88E400000003E8
+:1011A000041A88F00001034F061A88F400000003B7
+:1011B000041A890000010350061A89040000000384
+:1011C000041A891000010351061A89140000000353
+:1011D000041A892000010352061A89240000000322
+:1011E000041A893000010353061A893400000003F1
+:1011F000041A894000010354061A894400000003C0
+:10120000041A895000010355061A8954000000038E
+:10121000041A896000010356061A8964000000035D
+:10122000041A897000010357061A8974000000032C
+:10123000041A898000010358061A898400000003FB
+:10124000041A899000010359061A899400000003CA
+:10125000041A89A00001035A061A89A40000000399
+:10126000041A89B00001035B061A89B40000000368
+:10127000041A89C00001035C061A89C40000000337
+:10128000041A89D00001035D061A89D40000000306
+:10129000041A89E00001035E061A89E400000003D5
+:1012A000041A89F00001035F061A89F400000003A4
+:1012B000041A8A0000010360061A8A040000000371
+:1012C000041A8A1000010361061A8A140000000340
+:1012D000041A8A2000010362061A8A24000000030F
+:1012E000041A8A3000010363061A8A3400000003DE
+:1012F000041A8A4000010364061A8A4400000003AD
+:10130000041A8A5000010365061A8A54000000037B
+:10131000041A8A6000010366061A8A64000000034A
+:10132000041A8A7000010367061A8A740000000319
+:10133000041A8A8000010368061A8A8400000003E8
+:10134000041A8A9000010369061A8A9400000003B7
+:10135000041A8AA00001036A061A8AA40000000386
+:10136000041A8AB00001036B061A8AB40000000355
+:10137000041A8AC00001036C061A8AC40000000324
+:10138000041A8AD00001036D061A8AD400000003F3
+:10139000041A8AE00001036E061A8AE400000003C2
+:1013A000041A8AF00001036F061A8AF40000000391
+:1013B000041A8B0000010370061A8B04000000035E
+:1013C000041A8B1000010371061A8B14000000032D
+:1013D000041A8B2000010372061A8B2400000003FC
+:1013E000041A8B3000010373061A8B3400000003CB
+:1013F000041A8B4000010374061A8B44000000039A
+:10140000041A8B5000010375061A8B540000000368
+:10141000041A8B6000010376061A8B640000000337
+:10142000041A8B7000010377061A8B740000000306
+:10143000041A8B8000010378061A8B8400000003D5
+:10144000041A8B9000010379061A8B9400000003A4
+:10145000041A8BA00001037A061A8BA40000000373
+:10146000041A8BB00001037B061A8BB40000000342
+:10147000041A8BC00001037C061A8BC40000000311
+:10148000041A8BD00001037D061A8BD400000003E0
+:10149000041A8BE00001037E061A8BE400000003AF
+:1014A000041A8BF00001037F061A8BF4000000037E
+:1014B000041A8C0000010380061A8C04000000034B
+:1014C000041A8C1000010381061A8C14000000031A
+:1014D000041A8C2000010382061A8C2400000003E9
+:1014E000041A8C3000010383061A8C3400000003B8
+:1014F000041A8C4000010384061A8C440000000387
+:10150000041A8C5000010385061A8C540000000355
+:10151000041A8C6000010386061A8C640000000324
+:10152000041A8C7000010387061A8C7400000003F3
+:10153000041A8C8000010388061A8C8400000003C2
+:10154000041A8C9000010389061A8C940000000391
+:10155000041A8CA00001038A061A8CA40000000360
+:10156000041A8CB00001038B061A8CB4000000032F
+:10157000041A8CC00001038C061A8CC400000003FE
+:10158000041A8CD00001038D061A8CD400000003CD
+:10159000041A8CE00001038E061A8CE4000000039C
+:1015A000041A8CF00001038F061A8CF4000000036B
+:1015B000041A8D0000010390061A8D040000000338
+:1015C000041A8D1000010391061A8D140000000307
+:1015D000041A8D2000010392061A8D2400000003D6
+:1015E000041A8D3000010393061A8D3400000003A5
+:1015F000041A8D4000010394061A8D440000000374
+:10160000041A8D5000010395061A8D540000000342
+:10161000041A8D6000010396061A8D640000000311
+:10162000041A8D7000010397061A8D7400000003E0
+:10163000041A8D8000010398061A8D8400000003AF
+:10164000041A8D9000010399061A8D94000000037E
+:10165000041A8DA00001039A061A8DA4000000034D
+:10166000041A8DB00001039B061A8DB4000000031C
+:10167000041A8DC00001039C061A8DC400000003EB
+:10168000041A8DD00001039D061A8DD400000003BA
+:10169000041A8DE00001039E061A8DE40000000389
+:1016A000041A8DF00001039F061A8DF40000000358
+:1016B000041A8E00000103A0061A8E040000000325
+:1016C000041A8E10000103A1061A8E1400000003F4
+:1016D000041A8E20000103A2061A8E2400000003C3
+:1016E000041A8E30000103A3061A8E340000000392
+:1016F000041A8E40000103A4061A8E440000000361
+:10170000041A8E50000103A5061A8E54000000032F
+:10171000041A8E60000103A6061A8E6400000003FE
+:10172000041A8E70000103A7061A8E7400000003CD
+:10173000041A8E80000103A8061A8E84000000039C
+:10174000041A8E90000103A9061A8E94000000036B
+:10175000041A8EA0000103AA061A8EA4000000033A
+:10176000041A8EB0000103AB061A8EB40000000309
+:10177000041A8EC0000103AC061A8EC400000003D8
+:10178000041A8ED0000103AD061A8ED400000003A7
+:10179000041A8EE0000103AE061A8EE40000000376
+:1017A000041A8EF0000103AF061A8EF40000000345
+:1017B000041A8F00000103B0061A8F040000000312
+:1017C000041A8F10000103B1061A8F1400000003E1
+:1017D000041A8F20000103B2061A8F2400000003B0
+:1017E000041A8F30000103B3061A8F34000000037F
+:1017F000041A8F40000103B4061A8F44000000034E
+:10180000041A8F50000103B5061A8F54000000031C
+:10181000041A8F60000103B6061A8F6400000003EB
+:10182000041A8F70000103B7061A8F7400000003BA
+:10183000041A8F80000103B8061A8F840000000389
+:10184000041A8F90000103B9061A8F940000000358
+:10185000041A8FA0000103BA061A8FA40000000327
+:10186000041A8FB0000103BB061A8FB400000003F6
+:10187000041A8FC0000103BC061A8FC400000003C5
+:10188000041A8FD0000103BD061A8FD40000000394
+:10189000041A8FE0000103BE061A8FE4000000075F
+:1018A000041A62C0002003BF061A1AF000000042AA
+:1018B000061AAF0000000008061AE000000005400C
+:1018C000061AD00000000072061AD248000000106C
+:1018D000061AD6B000000020061AD470000000904E
+:1018E000061AD46800000002061AA000000001C415
+:1018F000061A300000000010061A308000000010A8
+:10190000061A310000000010061A31800000001095
+:10191000061A330000000012061A3390000000700F
+:10192000061AD45800000002061AD348000000022C
+:10193000061AD35800000020061AA710000001C4A0
+:10194000061A304000000010061A30C000000010D7
+:10195000061A314000000010061A31C000000010C5
+:10196000061A334800000012061A355000000070B5
+:10197000061AD46000000002061AD35000000002CC
+:10198000061AD3D800000020021AAE200000000082
+:10199000061A500000000002061A508000000012D3
+:1019A000041A4000000203DF041A63C0000203E1CE
+:1019B000061A700000000004061A32000000000839
+:1019C000021AAE2400000000061A501000000002A7
+:1019D000061A50C800000012041A4008000203E36F
+:1019E000041A63C8000203E5061A70100000000420
+:1019F000061A322000000008021AAE28000000007B
+:101A0000061A502000000002061A511000000012B1
+:101A1000041A4010000203E7041A63D0000203E92D
+:101A2000061A702000000004061A32400000000868
+:101A3000021AAE2C00000000061A5030000000020E
+:101A4000061A515800000012041A4018000203EB55
+:101A5000041A63D8000203ED061A70300000000477
+:101A6000061A326000000008021AAE3000000000C2
+:101A7000061A504000000002061A51A00000001291
+:101A8000041A4020000203EF041A63E0000203F18D
+:101A9000061A704000000004061A32800000000898
+:101AA000021AAE3400000000061A50500000000276
+:101AB000061A51E800000012041A4028000203F33D
+:101AC000041A63E8000203F5061A705000000004CF
+:101AD000061A32A000000008021AAE38000000000A
+:101AE000061A506000000002061A52300000001270
+:101AF000041A4030000203F7041A63F0000203F9ED
+:101B0000061A706000000004061A32C000000008C7
+:101B1000021AAE3C00000000061A507000000002DD
+:101B2000061A527800000012041A4038000203FB23
+:101B3000041A63F8000203FD061A70700000000426
+:101B4000061A32E0000000080200A2A40000020908
+:101B50000200A270000000000200A2740000000059
+:101B60000200A270000000000200A2740000000049
+:101B70000200A270000000000200A2740000000039
+:101B80000200A270000000000200A2740000000029
+:101B9000020100B400000001020100B800000001D1
+:101BA000020100CC00000001020100D00000000191
+:101BB000020100DC00000001020101000000000140
+:101BC00002010104000000010201007C003000005D
+:101BD00002010084000000280201008C00000000C7
+:101BE00002010130000000040201025C000000015B
+:101BF0000201032800000000020160580000FFFFFE
+:101C0000020160700000000702010554000000306E
+:101C1000020100C400000001020100F80000000100
+:101C2000020100F00000000102010080003000000D
+:101C3000020100880000002802010090000000005E
+:101C40000201013400000004020102DC0000000176
+:101C50000201032C000000000201605C0000FFFF95
+:101C600002016074000000070201056400000030FA
+:101C7000020100C800000001020100FC0000000198
+:101C8000020100F400000001020C10000000002816
+:101C9000020C200800000211020C200C00000200BF
+:101CA000020C201000000204020C201C0000FFFFA8
+:101CB000020C20200000FFFF020C20240000FFFF88
+:101CC000020C20280000FFFF020C2038000000005A
+:101CD000020C203C00000037020C204000000021D4
+:101CE000020C204400000020060C20480000001DCB
+:101CF000020C20BC00000001060C20C00000003FC8
+:101D0000020C21BC00000001020C21C000000001F7
+:101D1000020C21C400000001060C21C80000001CB8
+:101D2000020C223807FFFFFF020C223C0000007F5C
+:101D3000020C224007FFFFFF020C22440000003F7C
+:101D4000010C224800000000010C224C00000000A1
+:101D5000010C225000000000010C22540000000081
+:101D6000010C225800000000010C225C0000000061
+:101D7000010C226000000000010C22640000000041
+:101D8000010C226800000000010C226C0000000021
+:101D9000010C227000000000010C22740000000001
+:101DA000010C227800000000010C227C00000000E1
+:101DB000020C22D80000FFFF020C22DC0000FFFF13
+:101DC000020C22E00000FFFF020C22E40000FFFFF3
+:101DD0000C0C2000000003E80A0C200000000001A9
+:101DE0000B0C200000000003020C40080000101142
+:101DF000020C400C00001000020C40100000100407
+:101E0000020C401400001021020C401C0000FFFFD7
+:101E1000020C40200000FFFF020C40240000FFFFE6
+:101E2000020C40280000FFFF020C40380000004672
+:101E3000020C403C0000000C060C40400000000278
+:101E4000020C404800000018020C404C000000F05A
+:101E5000060C40500000001F020C40CC00000001A6
+:101E6000060C40D00000003A020C41B8000000010E
+:101E7000060C41BC00000003020C41C80000000138
+:101E8000020C41CC00000001060C41D00000001AF9
+:101E9000020C423807FFFFFF020C423C0000007FAB
+:101EA000020C424007FFFFFF020C42440000003FCB
+:101EB000010C424800000000010C424C00000000F0
+:101EC000010C425000000000010C425400000000D0
+:101ED000010C425800000000010C425C00000000B0
+:101EE000010C426000000000010C42640000000090
+:101EF000010C426800000000010C426C0000000070
+:101F0000010C427000000000010C4274000000004F
+:101F1000010C427800000000010C427C000000002F
+:101F2000010C428000000000020C42D80000FFFFBC
+:101F3000020C42DC0000FFFF020C42E00000FFFF49
+:101F4000020C42E40000FFFF0C0C4000000003E81C
+:101F50000A0C4000000000010B0C400000000003D0
+:101F6000060D400000000A00020D0044000000328F
+:101F7000020D008C02150020020D009002150020B9
+:101F8000020D009408100000020D009800000036B9
+:101F9000020D00A000000000020D00A400000004DB
+:101FA000020D00A800000004060D00AC00000002B5
+:101FB000020D00B800000002020D00C00000000188
+:101FC000020D00C800000002020D00CC000000025B
+:101FD000020D015C00000001020D0164000000011F
+:101FE000020D016800000002020D02040000000161
+:101FF000020D020C00000020020D02100000004043
+:10200000020D021400000040020D02200000000337
+:10201000020D022400000018060D028000000012CC
+:10202000040D0300001803FF060D03600000000C00
+:10203000020D004C00000001020D005000000002E3
+:10204000020D005400000000020D005800000008BE
+:10205000060D005C00000004020D00C40000000436
+:10206000020D000400000001020D00080000000144
+:10207000020D000C00000001020D00100000000124
+:10208000020D001400000001020D00180000000104
+:10209000020D001C00000001020D002000000001E4
+:1020A000020D002400000001020D002800000001C4
+:1020B000020D002C00000001020D003000000001A4
+:1020C000020D003400000001020D00380000000184
+:1020D000020D003C00000001020D01140000000987
+:1020E000020D011C0000000A020D01240000000086
+:1020F000020D012C00000000020D01340000000060
+:10210000020D013C0000000B020D01440000000024
+:10211000020D011800000029020D01200000002A14
+:10212000020D012800000020020D013000000020F7
+:10213000020D013800000020020D01400000002BBC
+:10214000020D014800000020020D011400000019DA
+:10215000020D011C0000001A020D012400000010F5
+:10216000020D012C00000010020D013400000010CF
+:10217000020D013C0000001B020D01440000001094
+:10218000020D011800000039020D01200000003A84
+:10219000020D012800000030020D01300000003067
+:1021A000020D013800000030020D01400000003B2C
+:1021B000020D014800000030020D0114000000492A
+:1021C000020D011C0000004A020D01240000004025
+:1021D000020D012C00000040020D013400000040FF
+:1021E000020D013C0000004B020D014400000040C4
+:1021F000020D011800000069020D01200000006AB4
+:10220000020D012800000060020D01300000006096
+:10221000020D013800000060020D01400000006B5B
+:10222000020D014800000060020D01140000005979
+:10223000020D011C0000005A020D01240000005094
+:10224000020D012C00000050020D0134000000506E
+:10225000020D013C0000005B020D01440000005033
+:10226000020D011800000079020D01200000007A23
+:10227000020D012800000070020D01300000007006
+:10228000020D013800000070020D01400000007BCB
+:10229000020D014800000070060E2000000008003A
+:1022A000020E004C00000032020E009402150020C5
+:1022B000020E009802150020020E009C0000003063
+:1022C000020E00A008100000020E00A4000000365C
+:1022D000020E00A800000030020E00AC0000003129
+:1022E000020E00B400000003020E00B8000000005F
+:1022F000020E00C400000000020E00CC0000000628
+:10230000020E00D800000001020E0144000000018E
+:10231000020E014C00000001020E015000000002FC
+:10232000020E020400000001020E020C0000004038
+:10233000020E021000000040020E021C0000000409
+:10234000020E022000000020020E02240000000EF7
+:10235000020E02280000001B060E030000000012FF
+:10236000040E0280001B0417060E02EC000000059C
+:10237000020E00540000000C020E00580000000C79
+:10238000020E005C00000000020E00600000001061
+:10239000020E006400000010060E0068000000033A
+:1023A000020E00DC00000003020E00040000000129
+:1023B000020E000800000001020E000C00000001E7
+:1023C000020E001000000001020E001400000001C7
+:1023D000020E001800000001020E001C00000001A7
+:1023E000020E002000000001020E00240000000187
+:1023F000020E002800000001020E002C0000000167
+:10240000020E003000000001020E00340000000146
+:10241000020E003800000001020E003C0000000126
+:10242000020E004000000001020E00440000000106
+:10243000020E01100000000F020E01180000000043
+:10244000020E012000000000020E01280000000022
+:10245000020E01140000002F020E011C00000020DB
+:10246000020E012400000020020E012C00000020BA
+:10247000020E01100000001F020E011800000010E3
+:10248000020E012000000010020E012800000010C2
+:10249000020E01140000003F020E011C000000307B
+:1024A000020E012400000030020E012C000000305A
+:1024B000020E01100000004F020E01180000004043
+:1024C000020E012000000040020E01280000004022
+:1024D000020E01140000006F020E011C00000060DB
+:1024E000020E012400000060020E012C00000060BA
+:1024F000020E01100000005F020E011800000050E3
+:10250000020E012000000050020E012800000050C1
+:10251000020E01140000007F020E011C000000707A
+:10252000020E012400000070020E012C0000007059
+:102530000730040000D60000083007D80005043238
+:10254000073400003222000007348000312C0C894F
+:102550000735000038DD18D5073580002F16270D08
+:1025600007360000261532D30836711031DE0434E8
+:1025700001300000000000000130000400000000F5
+:1025800001300008000000000130000C00000000D5
+:1025900001300010000000000130001400000000B5
+:1025A0000230002000000001023000240000000280
+:1025B00002300028000000030230002C0000000060
+:1025C000023000300000000402300034000000013E
+:1025D00002300038000000000230003C0000000122
+:1025E00002300040000000040230004400000000FF
+:1025F00002300048000000010230004C00000003DF
+:1026000002300050000000000230005400000001C1
+:1026100002300058000000040230005C000000009E
+:10262000023000600000000102300064000000037E
+:1026300002300068000000000230006C0000000161
+:10264000023000700000000402300074000000003E
+:1026500002300078000000040230007C000000031B
+:102660000630008000000002023000A400007FFF5E
+:10267000023000A8000003FF023002240000000026
+:1026800002300234000000000230024C0000000062
+:10269000023002E40000FFFF0630200000000800C6
+:1026A00002338BC000000001023380000000001ADA
+:1026B000023380400000004E023380800000001092
+:1026C000023380C0000000200C33830000086470D7
+:1026D0000A338300000001570B3383000000055FBD
+:1026E0000A338340000000000C33834000000226C0
+:1026F0000B338340000000010233838000086470C4
+:10270000023383C00000022602331480000000015F
+:102710000A3314800000000006328000000001022D
+:1027200006322008000000C8063220000000000227
+:1027300004328520008F04360632875C00000009D1
+:1027400006323EB00000000606323ED00000000215
+:1027500006323E800000000A04323EA8000204C592
+:1027600006323E0000000020063250000000094002
+:102770000632400000000004043294C0000204C786
+:1027800006324110000000020632D0000000007046
+:102790000632DB00000000D40632DEA0000000029A
+:1027A0000632E00000000800063324000000011893
+:1027B00006321000000001880632500000000020A0
+:1027C00006325100000000200632520000000020B6
+:1027D00006325300000000200632540000000020A2
+:1027E000063255000000002006325600000000208E
+:1027F000063257000000002006325800000000207A
+:10280000063259000000002006325A000000002065
+:1028100006325B000000002006325C000000002051
+:1028200006325D000000002006325E00000000203D
+:1028300006325F0000000020063284F00000000233
+:1028400004328500000204C9063285080000000237
+:102850000632DE90000000020633286000000118F6
+:102860000632162000000188063250800000002049
+:102870000632518000000020063252800000002005
+:1028800006325380000000200632548000000020F1
+:1028900006325580000000200632568000000020DD
+:1028A00006325780000000200632588000000020C9
+:1028B000063259800000002006325A8000000020B5
+:1028C00006325B800000002006325C8000000020A1
+:1028D00006325D800000002006325E80000000208D
+:1028E00006325F8000000020063284F800000002FB
+:1028F00004328510000204CB063285180000000265
+:102900000632DE980000000202328450000000000F
+:102910000632401000000002023284540000000021
+:1029200006324020000000020232845800000000FD
+:1029300006324030000000020232845C00000000D9
+:1029400006324040000000020232846000000000B5
+:102950000632405000000002023284640000000091
+:10296000063240600000000202328468000000006D
+:1029700006324070000000020232846C0000000049
+:1029800006324080000000020720040000730000AF
+:1029900008200780001004CD072400002AD500007D
+:1029A0000724800027740AB60824D36063FA04CF92
+:1029B00001200000000000000120000400000000D1
+:1029C00001200008000000000120000C00000000B1
+:1029D0000120001000000000012000140000000091
+:1029E000022000200000000102200024000000025C
+:1029F00002200028000000030220002C000000003C
+:102A00000220003000000004022000340000000119
+:102A100002200038000000000220003C00000001FD
+:102A200002200040000000040220004400000000DA
+:102A300002200048000000010220004C00000003BA
+:102A4000022000500000000002200054000000019D
+:102A500002200058000000040220005C000000007A
+:102A6000022000600000000102200064000000035A
+:102A700002200068000000000220006C000000013D
+:102A8000022000700000000402200074000000001A
+:102A900002200078000000040220007C00000003F7
+:102AA0000620008000000002022000A400007FFF3A
+:102AB000022000A8000003FF022002240000000002
+:102AC00002200234000000000220024C000000003E
+:102AD000022002E40000FFFF0620200000000800A2
+:102AE00002238BC0000000010223800000000010C0
+:102AF000022380400000001202238080000000308A
+:102B0000022380C00000000E0C23830000086470C4
+:102B10000A238300000001570B2383000000055F98
+:102B20000A238340000000000C238340000002269B
+:102B30000B2383400000000102238380000864709F
+:102B4000022383C00000022602231480000000013B
+:102B50000A2314800000000006221000000000423A
+:102B600006222008000000C8062220000000000203
+:102B70000622B000000003300622F40000000053DB
+:102B80000422F54C000104D10622F5500000000398
+:102B90000422F55C000104D20622F5600000000367
+:102BA0000422F56C000104D30622F5700000000336
+:102BB0000422F57C000104D40622F5800000000305
+:102BC0000422F58C000104D50622F59000000003D4
+:102BD0000422F59C000104D60622F5A000000003A3
+:102BE0000422F5AC000104D70622F5B00000000372
+:102BF0000422F5BC000104D80622F5C000000046FE
+:102C00000622E2000000044004221240009004D991
+:102C100006223000000000C006226700000001000C
+:102C2000062290000000040004226B0800200569C1
+:102C3000062211F000000006042212080006058991
+:102C4000062212200000000206224000000005C0FB
+:102C50000622C000000000060422C0180006058FEE
+:102C60000622C0300000000A0422C0580006059564
+:102C70000622C0700000000A0422C0980006059BCE
+:102C80000622C0B00000000A0422C0D8000605A138
+:102C90000622C0F00000000A0422C118000605A7A1
+:102CA0000622C1300000000A0422C158000605AD0A
+:102CB0000622C1700000000A0422C198000605B374
+:102CC0000622C1B00000000A0422C1D8000605B9DE
+:102CD0000622C1F00000000A0422C218000605BF47
+:102CE0000622C2300000000A0422C258000605C5B0
+:102CF0000622C2700000000A0422C298000605CB1A
+:102D00000622C2B00000000A0422C2D8000605D183
+:102D10000622C2F00000000A0422C318000605D7EC
+:102D20000622C3300000000A0422C358000605DD55
+:102D30000622C3700000000A0422C398000605E3BF
+:102D40000622C3B00000000A0422C3D8000605E929
+:102D50000622C3F00000000A0422C418000605EF92
+:102D60000622C4300000000A0422C458000605F5FB
+:102D70000622C4700000000A0422C498000605FB65
+:102D80000622C4B00000000A0422C4D800060601CE
+:102D90000622C4F00000000A0422C5180006060737
+:102DA0000622C5300000000A0422C5580006060DA0
+:102DB0000622C5700000000A0422C598000606130A
+:102DC0000622C5B00000000A0422C5D80006061974
+:102DD0000622C5F00000000A0422C6180006061FDD
+:102DE0000622C6300000000A0422C6580006062546
+:102DF0000622C6700000000A0422C6980006062BB0
+:102E00000622C6B00000000A0422C6D80006063119
+:102E10000622C6F00000000A0422C7180006063782
+:102E20000622C7300000000A0422C7580006063DEB
+:102E30000622C7700000000A0422C7980006064355
+:102E40000622C7B00000000A0422C7D800060649BF
+:102E50000622C7F00000000A0422C8180006064F28
+:102E60000622C8300000000A0422C8580006065591
+:102E70000622C8700000000A0422C8980006065BFB
+:102E80000622C8B00000000A0422C8D80006066165
+:102E90000622C8F00000000A0422C91800060667CE
+:102EA0000622C9300000000A0422C9580006066D37
+:102EB0000622C9700000000A0422C99800060673A1
+:102EC0000622C9B00000000A0422C9D8000606790B
+:102ED0000622C9F00000000A0422CA180006067F74
+:102EE0000622CA300000000A0422CA5800060685DD
+:102EF0000622CA700000000A0422CA980006068B47
+:102F00000622CAB00000000A0422CAD800060691B0
+:102F10000622CAF00000000A0422CB180006069719
+:102F20000622CB300000000A0422CB580006069D82
+:102F30000622CB700000000A0422CB98000606A3EC
+:102F40000622CBB00000000A0422CBD8000606A956
+:102F50000622CBF00000000A0422CC18000606AFBF
+:102F60000622CC300000000A0422CC58000606B528
+:102F70000622CC700000000A0422CC98000606BB92
+:102F80000622CCB00000000A0422CCD8000606C1FC
+:102F90000622CCF00000000A0422CD18000606C765
+:102FA0000622CD300000000A0422CD58000606CDCE
+:102FB0000622CD700000000A0422CD98000606D338
+:102FC0000622CDB00000000A0422CDD8000606D9A2
+:102FD0000622CDF00000000A0422CE18000606DF0B
+:102FE0000622CE300000000A0422CE58000606E574
+:102FF0000622CE700000000A0422CE98000606EBDE
+:103000000622CEB00000000A0422CED8000606F147
+:103010000622CEF00000000A0422CF18000606F7B0
+:103020000622CF300000000A0422CF58000606FD19
+:103030000622CF700000000A0422CF980006070382
+:103040000622CFB00000000A0422CFD800060709EC
+:103050000622CFF00000000A0422D0180006070F55
+:103060000622D0300000000A0422D05800060715BE
+:103070000622D0700000000A0422D0980006071B28
+:103080000622D0B00000000A0422D0D80006072192
+:103090000622D0F00000000A0422D11800060727FB
+:1030A0000622D1300000000A0422D1580006072D64
+:1030B0000622D1700000000A0422D19800060733CE
+:1030C0000622D1B00000000A0422D1D80006073938
+:1030D0000622D1F00000000A0422D2180006073FA1
+:1030E0000622D2300000000A0422D258000607450A
+:1030F0000622D2700000000A0422D2980006074B74
+:103100000622D2B00000000A0422D2D800060751DD
+:103110000622D2F00000000A0422D3180006075746
+:103120000622D3300000000A0422D3580006075DAF
+:103130000622D3700000000A0422D3980006076319
+:103140000622D3B00000000A0422D3D80006076983
+:103150000622D3F00000000A0422D4180006076FEC
+:103160000622D4300000000A0422D4580006077555
+:103170000622D4700000000A0422D4980006077BBF
+:103180000622D4B00000000A0422D4D80006078129
+:103190000622D4F00000000A0422D5180006078792
+:1031A0000622D5300000000A0422D5580006078DFB
+:1031B0000622D5700000000A0422D5980006079365
+:1031C0000622D5B00000000A0422D5D800060799CF
+:1031D0000622D5F00000000A0422D6180006079F38
+:1031E0000622D6300000000A0422D658000607A5A1
+:1031F0000622D6700000000A0422D698000607AB0B
+:103200000622D6B00000000A0422D6D8000607B174
+:103210000622D6F00000000A0422D718000607B7DD
+:103220000622D7300000000A0422D758000607BD46
+:103230000622D7700000000A0422D798000607C3B0
+:103240000622D7B00000000A0422D7D8000607C91A
+:103250000622D7F00000000A0422D818000607CF83
+:103260000622D8300000000A0422D858000607D5EC
+:103270000622D8700000000A0422D898000607DB56
+:103280000622D8B00000000A0422D8D8000607E1C0
+:103290000622D8F00000000A0422D918000607E729
+:1032A0000622D9300000000A0422D958000607ED92
+:1032B0000622D9700000000A0422D998000607F3FC
+:1032C0000622D9B00000000A0422D9D8000607F966
+:1032D0000622D9F00000000A0422DA18000607FFCF
+:1032E0000622DA300000000A0422DA580006080537
+:1032F0000622DA700000000A0422DA980006080BA1
+:103300000622DAB00000000A0422DAD8000608110A
+:103310000622DAF00000000A0422DB180006081773
+:103320000622DB300000000A0422DB580006081DDC
+:103330000622DB700000000A0422DB980006082346
+:103340000622DBB00000000A0422DBD800060829B0
+:103350000622DBF00000000A0422DC180006082F19
+:103360000622DC300000000A0422DC580006083582
+:103370000622DC700000000A0422DC980006083BEC
+:103380000622DCB00000000A0422DCD80006084156
+:103390000622DCF00000000A0422DD1800060847BF
+:1033A0000622DD300000000A0422DD580006084D28
+:1033B0000622DD700000000A0422DD980006085392
+:1033C0000622DDB00000000A0422DDD800060859FC
+:1033D0000622DDF00000000A0422DE180006085F65
+:1033E0000622DE300000000A0422DE5800060865CE
+:1033F0000622DE700000000A0422DE980006086B38
+:103400000622DEB00000000A0422DED800060871A1
+:103410000622DEF00000000A0422DF18000608770A
+:103420000622DF300000000A0422DF580006087D73
+:103430000622DF700000000A0422DF9800060883DD
+:103440000622DFB00000000A0422DFD80006088947
+:103450000622DFF00000000A0422E0180006088FB0
+:103460000622E0300000000A0422E0580006089519
+:103470000622E0700000000A0422E0980006089B83
+:103480000622E0B00000000A0422E0D8000608A1ED
+:103490000622E0F00000000A0422E118000608A756
+:1034A0000622E1300000000A0422E158000608ADBF
+:1034B0000622E1700000000A0422E198000608B329
+:1034C0000622E1B00000000A0422E1D8000608B993
+:1034D0000622E1F000000004062215380000000278
+:1034E000062211E8000000020622F3000000000896
+:1034F00002221148000000000622590000000006C8
+:103500000622330000000002062260400000003066
+:103510000622F320000000080222114C00000000E7
+:103520000622591800000006062233080000000297
+:1035300006226100000000300622F340000000086F
+:10354000022211500000000006225930000000063F
+:103550000622331000000002062261C00000003085
+:103560000622F3600000000802221154000000004F
+:103570000622594800000006062233180000000207
+:1035800006226280000000300622F380000000085E
+:1035900002221158000000000622596000000006B7
+:1035A00006223320000000020622634000000030A3
+:1035B0000622F3A0000000080222115C00000000B7
+:1035C0000622597800000006062233280000000277
+:1035D00006226400000000300622F3C0000000084C
+:1035E000022211600000000006225990000000062F
+:1035F0000622333000000002062264C000000030C2
+:103600000622F3E00000000802221164000000001E
+:10361000062259A8000000060622333800000002E6
+:10362000062265800000003002161000000000280D
+:1036300002170008000000020217002C000000031F
+:103640000217003C000000040217004400000000C4
+:1036500002170048000000020217004C0000009012
+:1036600002170050000000900217005400800090E4
+:103670000217005808100000021700700000000632
+:1036800002170078000009FF0217007C0000076C99
+:10369000021701C4081000000217034400000001D3
+:1036A000021704000000008A0217040400000080D2
+:1036B00002170408000000810217040C00000080BB
+:1036C000021704100000008A021704140000008092
+:1036D00002170418000000810217041C000000807B
+:1036E000021704300000008A021704340000008032
+:1036F00002170438000000810217043C000000801B
+:10370000021704400000008A0217044400000080F1
+:1037100002170448000000810217044C00000080DA
+:10372000021704800000008A021704840000008051
+:1037300002170488000000810217048C000000803A
+:1037400002170038007C1004021700040000000F6C
+:10375000021701EC00000002021701F40000000251
+:10376000021701EC00000002021701F40000000241
+:10377000021701EC00000002021701F40000000231
+:10378000021701EC00000002021701F40000000221
+:10379000021701EC00000002021701F40000000211
+:1037A000021701EC00000002021701F40000000201
+:1037B000021701EC00000002021701F400000002F1
+:1037C000021701EC00000002021701F400000002E1
+:1037D0000616402400000002021640700000001C83
+:1037E000021642080000000102164210000000010B
+:1037F00002164220000000010216422800000001CB
+:10380000021642300000000102164238000000019A
+:1038100002164260000000020C16401C0003D0900B
+:103820000A16401C0000009C0B16401C0000027190
+:103830000216403000000028021640340000002C20
+:1038400002164038000000300216404400000020FC
+:103850000216400000000001021640D800000001DE
+:1038600002164008000000010216400C0000000192
+:103870000216401000000001021642400000000045
+:1038800002164248000000000616427000000002C6
+:1038900002164250000000000216425800000000CC
+:1038A0000616428000000002021660080000121492
+:1038B0000216600C000012000216601000001204D4
+:1038C0000216601C0000FFFF021660200000FFFFD0
+:1038D000021660240000FFFF021660280000FFFFB0
+:1038E00002166038000000200216603C0000001044
+:1038F0000616604000000002021660480000002327
+:103900000216604C000000240216605000000025E2
+:1039100002166054000000260216605800000027BE
+:103920000216605C000000110216606000000000DA
+:10393000021660640000002B021660680000002C74
+:103940000216606C0000002D02166070000000EC92
+:103950000216607400000000021660780000002962
+:103960000216607C0000002A021660800000002F12
+:10397000061660840000000D021660B80000000109
+:10398000061660BC00000008021660DC00000001A2
+:10399000061660E000000004021660F0000000015E
+:1039A000061660F40000000302166100000000012A
+:1039B000061661040000002D021661B80000000127
+:1039C000061661BC00000008021661DC0000000160
+:1039D000061661E000000004021661F0000000011C
+:1039E000061661F4000000030216620000000001E8
+:1039F000061662040000000D0216623807FFFFFF82
+:103A00000216623C0000007F0216624007FFFFFFC3
+:103A1000021662440000003F0116624800000000E8
+:103A20000116624C00000000011662500000000008
+:103A300001166254000000000116625800000000E8
+:103A40000116625C000000000116626000000000C8
+:103A500001166264000000000116626800000000A8
+:103A60000116626C00000000011662700000000088
+:103A70000116627400000000011662780000000068
+:103A80000116627C00000000011662D400000000F4
+:103A9000021662D80000FFFF021662DC0000FFFF82
+:103AA000021662E00000FFFF021662E40000FFFF62
+:103AB0000C166000000003E80A1660000000000118
+:103AC0000B16600000000003021680400000000694
+:103AD0000216804400000005021680480000000A1B
+:103AE0000216804C000000050216805400000002FF
+:103AF000021680CC00000004021680D000000004F2
+:103B0000021680D400000004021680D800000004D1
+:103B1000021680DC00000004021680E000000004B1
+:103B2000021680E400000004021680E80000000491
+:103B30000216880400000006021680300000007C97
+:103B4000021680340000003D021680380000003F5D
+:103B50000216803C0000009C0216E6E800006000AF
+:103B60000216E6EC000060000216E6F000006000BD
+:103B70000216E6F40000600002168234000025E41C
+:103B8000021682380000800002168094000025E3AF
+:103B9000021681F400000C08021681F800000040B3
+:103BA000021681FC000001000216820000000020C5
+:103BB000021682040000001702168208000000802E
+:103BC0000216820C000002000216821000000000A3
+:103BD0000216823C0000001302168220008F008F24
+:103BE0000216821C008F008F021680F00000000772
+:103BF0000216821801FF01FF0216821401FF01FF65
+:103C0000061680F4000000020216811C0000000568
+:103C10000216812000000005021681240000000524
+:103C200002168128000000080216812C0000000600
+:103C300002168130000000070616813400000004DF
+:103C4000021680FC000000000616814400000002FD
+:103C50000216814C00000004021681500000000191
+:103C6000021681540000000202168158000000056F
+:103C70000216815C0000000502168160000000054C
+:103C80000216816400000005021681680000000829
+:103C900002168100000000000216816C0000000680
+:103CA00002168170000000070616817400000006ED
+:103CB0000216818C000000040216819000000001B1
+:103CC0000216810400000000021681940000000228
+:103CD00002168198000000050216819C0000000574
+:103CE000021681A000000005021681A40000000554
+:103CF000021681A800000008021681AC0000000630
+:103D0000021681B000000007061681B40000000210
+:103D10000216810800000000061681BC00000004A5
+:103D2000021681CC00000004021681D000000001C0
+:103D3000021681D400000002021681D8000000059E
+:103D4000021681DC00000005021681E0000000057B
+:103D50000216810C00000004021681E40000000538
+:103D6000021681E800000008021681EC000000063F
+:103D7000021681F000000007021681100000000109
+:103D800002168114000000020216811800000005CE
+:103D90000216809C0000004C021680A00000004C1F
+:103DA000061680C400000002021680A40000000075
+:103DB000021680A800000000021680AC0000004C33
+:103DC000061680B0000000050216E6F800000204A6
+:103DD00002168240003F003F02168244003F003F2F
+:103DE00006168290000000040216824800800080BF
+:103DF0000216824C008000800216825001000100F1
+:103E000002168254010001000616825800000002CA
+:103E100002168260004000400216826400400040AA
+:103E2000021682681E001E000216826C1E001E0012
+:103E3000021682704000400002168274400040006A
+:103E400002168278800080000216827C800080004A
+:103E500002168280200020000216828420002000AA
+:103E60000616828800000002021680900000004BB7
+:103E700002168060000001400216806400000140CC
+:103E8000061680880000000202168068000000000C
+:103E90000216806C0000000002168070000000C056
+:103EA00006168074000000050216880C010101014D
+:103EB000021688100101200402168814200810013F
+:103EC00002168818010101200216881C0101010157
+:103ED00002168820010120040216882420081001FF
+:103EE00002168828010101200216882C20081001E2
+:103EF00002168830010101200216883401010101F7
+:103F000002168838010120040216883C200810019E
+:103F100002168840010101200216884401010101B6
+:103F200002168848010120040216E6BC00000000C9
+:103F30000216E6C0000000020216E6C400000004FB
+:103F40000216E6C8000000060216E7940000000111
+:103F5000021680EC000000FF0214000000000001C7
+:103F60000215C024000000000215C0EC0000000192
+:103F70000215C0F0000000010615C100000000029B
+:103F800002140004000000010214000800000001F7
+:103F90000214000C000000010214003000000001B7
+:103FA000021400340000000102140040000000016F
+:103FB000021400440000FFFF061400040000000388
+:103FC0000214000000000000060280000000200033
+:103FD0000202005800000032020200A00315002077
+:103FE000020200A403150020020200A80100003014
+:103FF000020200AC08100000020200B0000000360F
+:10400000020200B400000030020200B800000031DB
+:10401000020200BC00000002020200C00000000515
+:10402000020200C400000002020200C800000002F8
+:10403000020200D000000007020200DC00000000C5
+:10404000020200E000000005020200E4000000039C
+:10405000020200F000000001020200FC0000000665
+:1040600002020120000000000202013400000002F0
+:10407000020201B0000000010202020C0000000177
+:1040800002020214000000010202021800000002F5
+:1040900002020404000000010202040C00000040BF
+:1040A00002020410000000400202041C0000000490
+:1040B000020204200000002002020424000000028A
+:1040C0000202042800000020060205000000001281
+:1040D00004020480002008BF020200600000000FFC
+:1040E00002020064000000070202006800000000F5
+:1040F0000202006C0000000E020200700000000EC0
+:104100000602007400000003020200F40000000434
+:104110000202000400000001020200080000000189
+:104120000202000C00000001020200100000000169
+:104130000202001400000001020200180000000149
+:104140000202001C00000001020200200000000129
+:104150000202002400000001020200280000000109
+:104160000202002C000000010202003000000001E9
+:1041700002020034000000010202003800000001C9
+:104180000202003C000000010202004000000001A9
+:104190000202004400000001020200480000000189
+:1041A0000202004C00000001020200500000000169
+:1041B00002020108000000C802020118000000020B
+:1041C000020201C400000000020201CC0000000055
+:1041D000020201D400000002020201DC0000000221
+:1041E000020201E4000000FF020201EC000000FFF7
+:1041F00002020100000000000202010C000000C8E1
+:104200000202011C00000002020201C800000000BE
+:10421000020201D000000000020201D800000002EA
+:10422000020201E000000002020201E8000000FFBB
+:10423000020201F0000000FF020201040000002061
+:1042400002020108000000C802020118000000027A
+:10425000020201C400000000020201CC00000000C4
+:10426000020201D400000002020201DC0000000290
+:10427000020201E4000000FF020201EC000000FF66
+:1042800002020100000000100202010C000000C840
+:104290000202011C00000002020201C8000000002E
+:1042A000020201D000000000020201D8000000025A
+:1042B000020201E000000002020201E8000000FF2B
+:1042C000020201F0000000FF0202010400000030C1
+:1042D00002020108000000C80202011800000002EA
+:1042E000020201C400000000020201CC0000000034
+:1042F000020201D400000002020201DC0000000200
+:10430000020201E4000000FF020201EC000000FFD5
+:1043100002020100000000400202010C000000C87F
+:104320000202011C00000002020201C8000000009D
+:10433000020201D000000000020201D800000002C9
+:10434000020201E000000002020201E8000000FF9A
+:10435000020201F0000000FF020201040000006000
+:1043600002020108000000C8020201180000000259
+:10437000020201C400000000020201CC00000000A3
+:10438000020201D400000002020201DC000000026F
+:10439000020201E4000000FF020201EC000000FF45
+:1043A00002020100000000500202010C000000C8DF
+:1043B0000202011C00000002020201C8000000000D
+:1043C000020201D000000000020201D80000000239
+:1043D000020201E000000002020201E8000000FF0A
+:1043E000020201F0000000FF020201040000007060
+:1043F0000728040000B50000082807B8000908DFF6
+:10440000072C000028C30000072C800036720A31F8
+:10441000072D000035B617CE072D80003B00253C48
+:10442000072E0000366D33FD072E80001AA8419933
+:10443000082EBF20281C08E1012800000000000011
+:10444000012800040000000001280008000000000E
+:104450000128000C000000000128001000000000EE
+:1044600001280014000000000228002000000001C4
+:104470000228002400000002022800280000000397
+:104480000228002C00000000022800300000000478
+:10449000022800340000000102280038000000005B
+:1044A0000228003C00000001022800400000000437
+:1044B000022800440000000002280048000000011B
+:1044C0000228004C000000030228005000000000F9
+:1044D00002280054000000010228005800000004D7
+:1044E0000228005C000000000228006000000001BB
+:1044F0000228006400000003022800680000000099
+:104500000228006C00000001022800700000000476
+:104510000228007400000000022800780000000457
+:104520000228007C00000003062800800000000232
+:10453000022800A400007FFF022800A8000003FF5B
+:1045400002280224000000000228023400000000BB
+:104550000228024C00000000022802E40000FFFFD5
+:104560000628200000000800022B8BC0000000017C
+:10457000022B800000000000022B80400000001889
+:10458000022B80800000000C022B80C0000000661F
+:104590000C2B8300000864700A2B83000000015775
+:1045A0000B2B83000000055F0A2B834000000000F6
+:1045B0000C2B8340000002260B2B834000000001DF
+:1045C000022B838000086470022B83C00000022647
+:1045D000022B1480000000010A2B14800000000050
+:1045E000022B944000000001062B944800000002BA
+:1045F000062A9A7000000004042A9A80000408E346
+:10460000062A9A9000000002042A9A98000208E7FD
+:10461000062A900000000048062A2008000000C872
+:10462000062A200000000002062A912800000086C9
+:10463000062AC00000000120062A9348000000035B
+:10464000042A9354000108E9062A9FB000000002E2
+:10465000042A9418000208EA042A9CD0000108ECFD
+:10466000062A9CD400000011042A9D20008F08ED2A
+:10467000062A9F5C00000005042A30000002097C25
+:10468000062A300800000100062A40400000001001
+:10469000042A40000010097E042A84080002098EC2
+:1046A000042ACF4000040990042ACF600002099434
+:1046B000062A9FA000000004062A600000000540B2
+:1046C000062A9D1800000002062AB00000000050D3
+:1046D000062ABB7000000070062ABB6800000002BA
+:1046E000062AB94800000004062AD000000008008D
+:1046F000062AC48000000150062A942000000032DF
+:10470000062A502000000002062A50300000000255
+:10471000062A500000000002062A50100000000285
+:10472000022A520800000001042A9AA000020996F9
+:10473000062A95B000000022042A96380001099844
+:10474000062A963C00000003062A96E0000000229C
+:10475000042A976800010999062A976C0000000353
+:10476000062A981000000022042A98980001099A4D
+:10477000062A989C00000003062A994000000022A7
+:10478000042A99C80001099B062A99CC000000035D
+:10479000062ABB5800000002062AC9C000000150CA
+:1047A000062A94E800000032062A50280000000281
+:1047B000062A503800000002062A500800000002B5
+:1047C000062A501800000002022A520C00000001C4
+:1047D000042A9AA80002099C062A96480000002292
+:1047E000042A96D00001099E062A96D400000003F0
+:1047F000062A977800000022042A98000001099FE9
+:10480000062A980400000003062A98A80000002247
+:10481000042A9930000109A0062A993400000003F7
+:10482000062A99D800000022042A9A60000109A1F2
+:10483000062A9A6400000003062ABB6000000002FA
+:10484000022ACF0000000000042A9AB0001009A23A
+:10485000062A50480000000E022ACF040000000083
+:10486000042A9AF0001009B2062A50800000000EB7
+:10487000022ACF0800000000042A9B30001009C261
+:10488000062A50B80000000E022ACF0C00000000DB
+:10489000042A9B70001009D2062A50F00000000E76
+:1048A000022ACF1000000000042A9BB0001009E289
+:1048B000062A51280000000E022ACF140000000032
+:1048C000042A9BF0001009F2062A51600000000E35
+:1048D000022ACF1800000000042A9C3000100A02AF
+:1048E000062A51980000000E022ACF1C000000008A
+:1048F000042A9C7000100A12062A51D00000000EF3
+:104900000210100800000001021010500000000109
+:10491000021010000003D000021010040000003D3F
+:104920000910180002000A220910110000100C22C0
+:1049300006101140000000080910116000100C3230
+:10494000061011A00000001806102400000000E06E
+:104950000210201C000000000210202000000001B6
+:10496000021020C00000000202102004000000011C
+:104970000210200800000001021030D800000001E1
+:1049800009103C0000050C420910380000050C47D6
+:104990000910392000050C4C09103B0000050C5192
+:1049A00006104C000000010002104028000000101A
+:1049B0000210404400003FFF021040580028000051
+:1049C000021040840084924A021040580000000007
+:1049D00002104138000000010210413800000001BF
+:1049E00002104138000000010210413800000001AF
+:1049F000021041380000000102104138000000019F
+:104A0000021041380000000102104138000000018E
+:104A10000212049001F680400212051400003C10BE
+:104A200002120494FFFFFFFF02120498FFFFFFFF32
+:104A30000212049CFFFFFFFF021204A0FFFFFFFF12
+:104A4000021204A4FFFFFFFF021204A8FFFFFFFFF2
+:104A5000021204ACFFFFFFFF021204B0FFFFFFFFD2
+:104A6000021204B8FFFFFFFF021204BCFFFFFFFFAA
+:104A7000021204C0FFFFFFFF021204C4FFFFFFFF8A
+:104A8000021204C8FFFFFFFF021204CCFFFFFFFF6A
+:104A9000021204D0FFFFFFFF021204D8FFFFFFFF46
+:104AA000021204DCFFFFFFFF021204E0FFFFFFFF22
+:104AB000021204E4FFFFFFFF021204E8FFFFFFFF02
+:104AC000021204ECFFFFFFFF021204F0FFFFFFFFE2
+:104AD000021204F4FFFFFFFF021204F8FFFFFFFFC2
+:104AE000021204FCFFFFFFFF02120500FFFFFFFFA1
+:104AF00002120504FFFFFFFF02120508FFFFFFFF80
+:104B00000212050CFFFFFFFF02120510FFFFFFFF5F
+:104B1000021204D4F800C000021204B4F0005000E5
+:104B200002120390000000080212039C000000081B
+:104B3000021203A000000008021203A400000002F9
+:104B4000021203BC00000004021203C000000005B2
+:104B5000021203C400000004021203D0000000008F
+:104B60000212036C00000001021201BC00000040B0
+:104B7000021201C000001808021201C4000008035C
+:104B8000021201C800000803021201CC000000401C
+:104B9000021201D000000003021201D40000080339
+:104BA000021201D800000803021201DC0000080311
+:104BB000021201E000010003021201E400000803F8
+:104BC000021201E800000803021201EC00000003D9
+:104BD000021201F000000003021201F400000003C1
+:104BE000021201F800000003021201FC00000003A1
+:104BF000021202000000000302120204000000037F
+:104C000002120208000000030212020C000000035E
+:104C1000021202100000000302120214000000033E
+:104C200002120218000000030212021C000000031E
+:104C300002120220000000030212022400000003FE
+:104C400002120228000024030212022C0000002F8E
+:104C500002120230000000090212023400000019A2
+:104C600002120238000001840212023C000001839B
+:104C70000212024000000306021202440000001962
+:104C800002120248000000060212024C0000030655
+:104C90000212025000000306021202540000030632
+:104CA0000212025800000C860212025C0000030689
+:104CB00002120260000003060212026400000006F5
+:104CC00002120268000000060212026C00000006D8
+:104CD00002120270000000060212027400000006B8
+:104CE00002120278000000060212027C0000000698
+:104CF0000212028000000006021202840000000678
+:104D000002120288000000060212028C0000000657
+:104D10000212029000000006021202940000000637
+:104D200002120298000000060212029C0000000617
+:104D3000021202A000000306021202A400000013E7
+:104D4000021202A800000006021202B000001004C5
+:104D5000021202B400001004021203240010644086
+:104D60000212032800106440021205B40000000182
+:104D7000021205F800000040021205FC00000019B4
+:104D800002120600000000010212066C0000000181
+:104D9000021201B000000001021207D80000000357
+:104DA000021207D800000003021207D80000000317
+:104DB000021207D800000003021207D80000000307
+:104DC000021207D800000003021207D800000003F7
+:104DD000021207D8000000030600A0000000000C2B
+:104DE0000200A050000000000200A05400000000DB
+:104DF0000200A0EC555400000200A0F05555555596
+:104E00000200A0F4000055550200A0F8F0000000D8
+:104E10000200A0FC555400000200A1005555555554
+:104E20000200A104000055550200A108F000000096
+:104E30000200A19C000000000200A1A000010000EF
+:104E40000200A1A4000050140200A1A8000000006C
+:104E50000200A6A8000000000200A6AC00000000AE
+:104E60000200A6D0000000000200A45C00000C00BC
+:104E70000200A61C000000030200A070FFF55FFF07
+:104E80000200A0740000FFFF0200A078F00003E021
+:104E90000200A07C000000000200A0800000A00032
+:104EA0000600A084000000050200A0980FE00000AA
+:104EB0000600A09C000000070200A0B8000004004B
+:104EC0000600A0BC000000030200A0C80000100003
+:104ED0000600A0CC000000030200A0D800004000A3
+:104EE0000600A0DC000000030200A0E800010000B2
+:104EF0000600A22C000000040200A688000000FCAE
+:104F00000600A68C000000070200A6F400000000C6
+:104F10000200A10CFF5C00000200A110FFF55FFF82
+:104F20000200A1140000FFFF0200A118F00003E03E
+:104F30000200A11C000000000200A1200000A0004F
+:104F40000600A124000000050200A1380FE00000C7
+:104F50000600A13C000000070200A1580000080064
+:104F60000600A15C000000030200A1680000200010
+:104F70000600A16C000000030200A1780000800080
+:104F80000600A17C000000030200A18800020000CE
+:104F90000600A23C000000040200A6B0000000FCD5
+:104FA0000600A6B4000000070200A6F800000000FA
+:104FB0000200A030000000000200A0340000000049
+:104FC0000200A038000000000200A03C0000000029
+:104FD0000200A040000000000200A0440000000009
+:104FE0000200A048000000000200A04C00000000E9
+:104FF000020090C40000E000020090CC0000F3002A
+:10500000020090D400000003020091A00000000103
+:105010000600917000000003020090EC00006000A8
+:10502000020090F400007300020090FC00000003F6
+:10503000020091A800000001060091880000000312
+:10504000020091000000400002009108000053009F
+:105050000200911000000004020091AC0000000169
+:1050600006009194000000020200919C00000001E3
+:10507000020090D800006000020090E00000730081
+:10508000020090E800000003020091A4000000016B
+:105090000200917C000000010200918000000001EC
+:1050A000020091840000000002009128000003002B
+:1050B0000200916C0003F0080200912C0000030034
+:1050C0000200913000000300020091340000030050
+:1050D00002009138000003000200913C0000030030
+:1050E00002009140000003000200942C0000000127
+:1050F000020094300000000102009434000000011E
+:105100000200942C00000001020094300000000115
+:1051100002009434000000010200942C0000000101
+:1051200002009430000000010200943400000001ED
+:105130000200942C000000010200943000000001E5
+:1051400002009434000000010200942C00000001D1
+:1051500002009430000000010200943400000001BD
+:105160000200942C000000010200943000000001B5
+:1051700002009434000000010200942C00000001A1
+:10518000020094300000000102009434000000018D
+:105190000200942C00000001020094300000000185
+:1051A00002009434000000010213003C000061A8DA
+:1051B00006130108000000030213010400000000B0
+:1051C0000213013400000000061301080000000370
+:1051D000021301040000000002130134000000006B
+:1051E0000613010800000003021301040000000080
+:1051F0000213013400000000061301080000000340
+:10520000021301040000000002130134000000003A
+:10521000061301080000000302130104000000004F
+:10522000021301340000000006130108000000030F
+:10523000021301040000000002130134000000000A
+:10524000061301080000000302130104000000001F
+:1052500002130134000000000613010800000003DF
+:1052600002130104000000000213013400000000DA
+:10527000021100B8000000010216E6E8000020005C
+:105280000216E6EC000020000216E6F0000065556C
+:105290000216E6F400006555021681500000000079
+:1052A00002168174000000010216817800000001DE
+:1052B0000216817C000000010216818000000001BE
+:1052C000021681840000000102168188000000019E
+:1052D000021681B400000001021681B8000000012E
+:1052E000021681BC00000001021681C0000000010E
+:1052F000021681C400000001021681C800000001EE
+:1053000002168110000000000216824000BF00BF9C
+:1053100006168244000000020216824C00BF00BF45
+:105320000216E6C4000000010216E6C800000003F1
+:105330000216E79400000000042ACF40000A0C5631
+:105340000000000000000000000000340000000029
+:10535000000000000000000000000000000000004D
+:10536000000000000000000000000000000000003D
+:1053700000000000003400350000000000000000C4
+:10538000000000000000000000000000000000001D
+:10539000000000000000000000000000000000000D
+:1053A0000035006000000000000000000000000068
+:1053B00000000000000000000000000000000000ED
+:1053C00000000000000000000000000000600091EC
+:1053D0000000000000000000009100950095009979
+:1053E0000099009D009D00A100A100A500A500A9B5
+:1053F00000A900AD00AD00B100B100B50000000093
+:10540000000000000000000000000000000000009C
+:10541000000000000000000000000000000000008C
+:105420000000000000B503100310031A031A032440
+:105430000324032B032B03320332033903390340C4
+:10544000034003470347034E034E03550355035CD4
+:10545000000000000000000000000000000000004C
+:10546000000000000000000000000000000000003C
+:10547000000000000000000000000000000000002C
+:10548000000000000000000000000000000000001C
+:10549000000000000000000000000000000000000C
+:1054A00000000000000000000000000000000000FC
+:1054B00000000000000000000000000000000000EC
+:1054C00000000000000000000000000000000000DC
+:1054D00000000000000000000000000000000000CC
+:1054E00000000000000000000000000000000000BC
+:1054F00000000000000000000000000000000000AC
+:10550000035C035D0000000000000000035D035E1B
+:10551000035E035F035F0360036003610361036273
+:105520000362036303630364036403650000000014
+:10553000000000000000000000000000000000006B
+:10554000000000000000000000000000000000005B
+:1055500000000000000000000365036C036C03788A
+:105560000378038400000000000000000000000039
+:10557000000000000000000000000000000000002B
+:10558000000000000000000000000000000000001B
+:10559000000000000000000000000000000000000B
+:1055A00000000000000000000000000000000000FB
+:1055B00003840385000000000000000000000000DC
+:1055C00000000000000000000000000000000000DB
+:1055D000000000000000000000000000038503B090
+:1055E00000000000000000000000000000000000BB
+:1055F00000000000000000000000000000000000AB
+:10560000000000000000000003B003DF0000000005
+:10561000000000000000000000000000000000008A
+:10562000000000000000000000000000000000007A
+:105630000000000003DF040E000000000000000076
+:10564000040E04150415041C041C04230423042A5A
+:10565000042A0431043104380438043F043F04466A
+:105660000446047900000000000000000479047D75
+:10567000047D048104810485048504890489048DE2
+:10568000048D04910491049504950499049904E807
+:1056900004E804FE04FE0514051405160516051895
+:1056A0000518051A051A051C051C051E051E0520F2
+:1056B000052005220522052405240690000000008F
+:1056C00000000000069006950695069A069A069F29
+:1056D000069F06A406A406A906A906AE06AE06B352
+:1056E00006B306B806B806B90000000000000000C6
+:1056F00000000000000000000000000000000000AA
+:105700000000000000000000000000000000000099
+:1057100006B906DD000000000000000006DD06DF1F
+:1057200006DF06E106E106E306E306E506E506E731
+:1057300006E706E906E906EB06EB06ED06ED0702CD
+:105740000702070507050708000000000000000029
+:105750000000000000000000000000000000000049
+:1057600000000000000000000708074C00000000D7
+:105770000000000000000000000000000000000029
+:105780000000000000000000000000000000000019
+:1057900000000000074C07DE0000000000000000D1
+:1057A00000000000000000000000000000000000F9
+:1057B00000000000000000000000000000000000E9
+:1057C00007DE07EC00000000000000000000000001
+:1057D00000000000000000000000000000000000C9
+:1057E00000000000000000000000000007EC082995
+:1057F0000000000000000000082908320832083BC1
+:10580000083B08440844084D084D08560856085FF0
+:10581000085F086808680871087108D108D108E6AF
+:1058200008E608FB08FB08FE08FE09010901090457
+:10583000090409070907090A090A090D090D0910D0
+:10584000091009130913091C0000000000000000E2
+:105850000000000000000000000000000000000048
+:105860000000000000000000000000000000000038
+:10587000091C0922000000000000000000000000D8
+:105880000000000000000000000000000000000018
+:1058900000000000000000000000000009220927AD
+:1058A00000000000000000000000000000000000F8
+:1058B00000000000000000000000000000000000E8
+:1058C00000000000000000000927092D0000000072
+:1058D00000000000092D092E092E092F092F09307B
+:1058E00009300931093109320932093309330934E0
+:1058F000093409350000000000000000000000002D
+:105900000000000000000000000000000000000097
+:105910000000000000000000000000000000000087
+:10592000093509A6000000000000000009A609A72B
+:1059300009A709A809A809A909A909AA09AA09ABD7
+:1059400009AB09AC09AC09AD09AD09AE09AE09C294
+:1059500009C209D509D509E909E909EA09EA09EB02
+:1059600009EB09EC09EC09ED09ED09EE09EE09EF87
+:1059700009EF09F009F009F109F10A10000000002F
+:10598000000000000A100A130A130A160A160A1960
+:105990000A190A1C0A1C0A1F0A1F0A220A220A25BF
+:1059A0000A250A280A280A29000000000000000031
+:1059B0000A290A2C0A2C0A2F0A2F0A320A320A351F
+:1059C0000A350A380A380A3B0A3B0A3E0A3E0A41AF
+:1059D0000A410A4200000000000000000000000030
+:1059E00000000000000000000000000000000000B7
+:1059F0000000000000000000000000000A420A5AF7
+:105A00000000000000000000000000000000000096
+:105A10000000000000000000000000000000000086
+:105A200000000000000000000A5A0A5B00000000AD
+:105A30000000000000000000000000000000000066
+:105A40000000000000000000000000000000000056
+:105A5000000000000000000000010000000207003C
+:105A600000030E000004150000051C0000062300C2
+:105A700000072A000008310000093800000A3F0032
+:105A8000000B4600000C4D00000D5400000E5B00A2
+:105A9000000F620000106900001170000012770012
+:105AA00000137E000014850000158C000016930082
+:105AB00000179A000018A1000019A800001AAF00F2
+:105AC000001BB600001CBD00001DC400001ECB0062
+:105AD000001FD2000000D90000002000000040009C
+:105AE00000006000000080000000A0000000C00076
+:105AF0000000E00000010000000120000001400063
+:105B000000016000000180000001A0000001C00051
+:105B10000001E0000002000000022000000240003E
+:105B200000026000000280000002A0000002C0002D
+:105B30000002E0000003000000032000000340001A
+:105B400000036000000380000003A0000003C00009
+:105B50000003E000000400000004200000044000F6
+:105B600000046000000480000004A0000004C000E5
+:105B70000004E000000500000005200000054000D2
+:105B800000056000000580000005A0000005C000C1
+:105B90000005E000000600000006200000064000AE
+:105BA00000066000000680000006A0000006C0009D
+:105BB0000006E0000007000000072000000740008A
+:105BC00000076000000780000007A0000007C00079
+:105BD0000007E00000080000000820000008400066
+:105BE00000086000000880000008A0000008C00055
+:105BF0000008E00000090000000920000009400042
+:105C000000096000000980000009A0000009C00030
+:105C10000009E000000A0000000A2000000A40001D
+:105C2000000A6000000A8000000AA000000AC0000C
+:105C3000000AE000000B0000000B2000000B4000F9
+:105C4000000B6000000B8000000BA000000BC000E8
+:105C5000000BE000000C0000000C2000000C4000D5
+:105C6000000C6000000C8000000CA000000CC000C4
+:105C7000000CE000000D0000000D2000000D4000B1
+:105C8000000D6000000D8000000DA000000DC000A0
+:105C9000000DE000000E0000000E2000000E40008D
+:105CA000000E6000000E8000000EA000000EC0007C
+:105CB000000EE000000F0000000F2000000F400069
+:105CC000000F6000000F8000000FA000000FC00058
+:105CD000000FE00000100000001020000010400045
+:105CE00000106000001080000010A0000010C00034
+:105CF0000010E00000110000001120000011400021
+:105D000000116000001180000011A0000011C0000F
+:105D10000011E000001200000012200000124000FC
+:105D200000126000001280000012A0000012C000EB
+:105D30000012E000001300000013200000134000D8
+:105D400000136000001380000013A0000013C000C7
+:105D50000013E000001400000014200000144000B4
+:105D600000146000001480000014A0000014C000A3
+:105D70000014E00000150000001520000015400090
+:105D800000156000001580000015A0000015C0007F
+:105D90000015E0000016000000162000001640006C
+:105DA00000166000001680000016A0000016C0005B
+:105DB0000016E00000170000001720000017400048
+:105DC00000176000001780000017A0000017C00037
+:105DD0000017E00000180000001820000018400024
+:105DE00000186000001880000018A0000018C00013
+:105DF0000018E00000190000001920000019400000
+:105E000000196000001980000019A0000019C000EE
+:105E10000019E000001A0000001A2000001A4000DB
+:105E2000001A6000001A8000001AA000001AC000CA
+:105E3000001AE000001B0000001B2000001B4000B7
+:105E4000001B6000001B8000001BA000001BC000A6
+:105E5000001BE000001C0000001C2000001C400093
+:105E6000001C6000001C8000001CA000001CC00082
+:105E7000001CE000001D0000001D2000001D40006F
+:105E8000001D6000001D8000001DA000001DC0005E
+:105E9000001DE000001E0000001E2000001E40004B
+:105EA000001E6000001E8000001EA000001EC0003A
+:105EB000001EE000001F0000001F2000001F400027
+:105EC000001F6000001F8000001FA000001FC00016
+:105ED000001FE00000200000002020000020400003
+:105EE00000206000002080000020A0000020C000F2
+:105EF0000020E000002100000021200000214000DF
+:105F000000216000002180000021A0000021C000CD
+:105F10000021E000002200000022200000224000BA
+:105F200000226000002280000022A0000022C000A9
+:105F30000022E00000230000002320000023400096
+:105F400000236000002380000023A0000023C00085
+:105F50000023E00000240000002420000024400072
+:105F600000246000002480000024A0000024C00061
+:105F70000024E0000025000000252000002540004E
+:105F800000256000002580000025A0000025C0003D
+:105F90000025E0000026000000262000002640002A
+:105FA00000266000002680000026A0000026C00019
+:105FB0000026E00000270000002720000027400006
+:105FC00000276000002780000027A0000027C000F5
+:105FD0000027E000002800000028200000284000E2
+:105FE00000286000002880000028A0000028C000D1
+:105FF0000028E000002900000029200000294000BE
+:1060000000296000002980000029A0000029C000AC
+:106010000029E000002A0000002A2000002A400099
+:10602000002A6000002A8000002AA000002AC00088
+:10603000002AE000002B0000002B2000002B400075
+:10604000002B6000002B8000002BA000002BC00064
+:10605000002BE000002C0000002C2000002C400051
+:10606000002C6000002C8000002CA000002CC00040
+:10607000002CE000002D0000002D2000002D40002D
+:10608000002D6000002D8000002DA000002DC0001C
+:10609000002DE000002E0000002E2000002E400009
+:1060A000002E6000002E8000002EA000002EC000F8
+:1060B000002EE000002F0000002F2000002F4000E5
+:1060C000002F6000002F8000002FA000002FC000D4
+:1060D000002FE000003000000030200000304000C1
+:1060E00000306000003080000030A0000030C000B0
+:1060F0000030E0000031000000312000003140009D
+:1061000000316000003180000031A0000031C0008B
+:106110000031E00000320000003220000032400078
+:1061200000326000003280000032A0000032C00067
+:106130000032E00000330000003320000033400054
+:1061400000336000003380000033A0000033C00043
+:106150000033E00000340000003420000034400030
+:1061600000346000003480000034A0000034C0001F
+:106170000034E0000035000000352000003540000C
+:1061800000356000003580000035A0000035C000FB
+:106190000035E000003600000036200000364000E8
+:1061A00000366000003680000036A0000036C000D7
+:1061B0000036E000003700000037200000374000C4
+:1061C00000376000003780000037A0000037C000B3
+:1061D0000037E000003800000038200000384000A0
+:1061E00000386000003880000038A0000038C0008F
+:1061F0000038E0000039000000392000003940007C
+:1062000000396000003980000039A0000039C0006A
+:106210000039E000003A0000003A2000003A400057
+:10622000003A6000003A8000003AA000003AC00046
+:10623000003AE000003B0000003B2000003B400033
+:10624000003B6000003B8000003BA000003BC00022
+:10625000003BE000003C0000003C2000003C40000F
+:10626000003C6000003C8000003CA000003CC000FE
+:10627000003CE000003D0000003D2000003D4000EB
+:10628000003D6000003D8000003DA000003DC000DA
+:10629000003DE000003E0000003E2000003E4000C7
+:1062A000003E6000003E8000003EA000003EC000B6
+:1062B000003EE000003F0000003F2000003F4000A3
+:1062C000003F6000003F8000003FA000003FC00092
+:1062D000003FE000003FE00100000000000001FF7F
+:1062E0000000020000007FF800007FF800000A9420
+:1062F00000001500000000010000FF000000000089
+:106300000000FF00000000000000FF00000000008F
+:106310000000FF00000000000000FF00000000007F
+:106320000000FF00000000000000FF00000000006F
+:106330000000FF00000000000000FF00000000005F
+:106340000000FF00000000000000FF00000000004F
+:106350000000FF00000000000000FF00000000003F
+:106360000000FF00000000000000FF00000000002F
+:106370000000FF00000000000000FF00000000001F
+:106380000000FF00000000000000FF00000000000F
+:106390000000FF00000000000000FF0000000000FF
+:1063A0000000FF00000000000000FF0000000000EF
+:1063B0000000FF00000000000000FF0000000000DF
+:1063C0000000FF00000000000000FF0000000000CF
+:1063D0000000FF00000000000000FF0000000000BF
+:1063E0000000FF00000000000000FF0000000000AF
+:1063F0000000FF00000000000000FF00000000009F
+:106400000000FF00000000000000FF00000000008E
+:106410000000FF00000000000000FF00000000007E
+:106420000000FF00000000000000FF00000000006E
+:106430000000FF00000000000000FF00000000005E
+:106440000000FF00000000000000FF00000000004E
+:106450000000FF00000000000000FF00000000003E
+:106460000000FF00000000000000FF00000000002E
+:106470000000FF00000000000000FF00000000001E
+:106480000000FF00000000000000FF00000000000E
+:106490000000FF00000000000000FF0000000000FE
+:1064A0000000FF00000000000000FF0000000000EE
+:1064B0000000FF00000000000000FF0000000000DE
+:1064C0000000FF00000000000000FF0000000000CE
+:1064D0000000FF00000000000000FF0000000000BE
+:1064E0000000FF00000000000000FF0000000000AE
+:1064F0000000FF00000000000000FF00000000009E
+:106500000000FF00000000000000FF00000000008D
+:106510000000FF00000000000000FF00000000007D
+:106520000000FF00000000000000FF00000000006D
+:106530000000FF000000000000000000140AFF003F
+:106540000000000100000000002010010000000019
+:106550000100900000000100000090020000900483
+:1065600000009006000090080000900A0000900CC7
+:106570000000900E00009010000090120000901497
+:1065800000009016000090180000901A0000901C67
+:106590000000901E00009020000090220000902437
+:1065A00000009026000090280000902A0000902C07
+:1065B0000000902E000090300000903200009034D7
+:1065C00000009036000090380000903A0000903CA7
+:1065D0000000903E00009040000090420000904477
+:1065E00000009046000090480000904A0000904C47
+:1065F0000000904E00009050000090520000905417
+:1066000000009056000090580000905A0000905CE6
+:106610000000905E000090600000906200009064B6
+:1066200000009066000090680000906A0000906C86
+:106630000000906E00009070000090720000907456
+:1066400000009076000090780000907A0000907C26
+:106650000000907E000090800000908200009084F6
+:1066600000009086000090880000908A0000908CC6
+:106670000000908E00009090000090920000909496
+:1066800000009096000090980000909A0000909C66
+:106690000000909E000090A0000090A2000090A436
+:1066A000000090A6000090A8000090AA000090AC06
+:1066B000000090AE000090B0000090B2000090B4D6
+:1066C000000090B6000090B8000090BA000090BCA6
+:1066D000000090BE000090C0000090C2000090C476
+:1066E000000090C6000090C8000090CA000090CC46
+:1066F000000090CE000090D0000090D2000090D416
+:10670000000090D6000090D8000090DA000090DCE5
+:10671000000090DE000090E0000090E2000090E4B5
+:10672000000090E6000090E8000090EA000090EC85
+:10673000000090EE000090F0000090F2000090F455
+:10674000000090F6000090F8000090FA000090FC25
+:10675000000090FE000091000000910200009104F2
+:1067600000009106000091080000910A0000910CC1
+:106770000000910E00009110000091120000911491
+:1067800000009116000091180000911A0000911C61
+:106790000000911E00009120000091220000912431
+:1067A00000009126000091280000912A0000912C01
+:1067B0000000912E000091300000913200009134D1
+:1067C00000009136000091380000913A0000913CA1
+:1067D0000000913E00009140000091420000914471
+:1067E00000009146000091480000914A0000914C41
+:1067F0000000914E00009150000091520000915411
+:1068000000009156000091580000915A0000915CE0
+:106810000000915E000091600000916200009164B0
+:1068200000009166000091680000916A0000916C80
+:106830000000916E00009170000091720000917450
+:1068400000009176000091780000917A0000917C20
+:106850000000917E000091800000918200009184F0
+:1068600000009186000091880000918A0000918CC0
+:106870000000918E00009190000091920000919490
+:1068800000009196000091980000919A0000919C60
+:106890000000919E000091A0000091A2000091A430
+:1068A000000091A6000091A8000091AA000091AC00
+:1068B000000091AE000091B0000091B2000091B4D0
+:1068C000000091B6000091B8000091BA000091BCA0
+:1068D000000091BE000091C0000091C2000091C470
+:1068E000000091C6000091C8000091CA000091CC40
+:1068F000000091CE000091D0000091D2000091D410
+:10690000000091D6000091D8000091DA000091DCDF
+:10691000000091DE000091E0000091E2000091E4AF
+:10692000000091E6000091E8000091EA000091EC7F
+:10693000000091EE000091F0000091F2000091F44F
+:10694000000091F6000091F8000091FA000091FC1F
+:10695000000091FEFFFFFFFFFFFFFFFFFFFFFFFFB4
+:10696000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37
+:10697000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27
+:10698000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF17
+:10699000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07
+:1069A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7
+:1069B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7
+:1069C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7
+:1069D000FFFFFFFF0000000300BEBC20000000001E
+:1069E000000000050000000300BEBC200000000005
+:1069F000000000050000000300BEBC2000000000F5
+:106A0000000000050000000300BEBC2000000000E4
+:106A1000000000050000000300BEBC2000000000D4
+:106A2000000000050000000300BEBC2000000000C4
+:106A3000000000050000000300BEBC2000000000B4
+:106A4000000000050000000300BEBC2000000000A4
+:106A50000000000500002000000040C00000618030
+:106A6000000082400000A3000000C3C00000E480DA
+:106A70000001054000012600000146C000016780BA
+:106A8000000188400001A9000001C9C00001EA809E
+:106A900000020B4000022C0000024CC000026D807E
+:106AA00000028E400002AF000002CFC00002F08062
+:106AB00000001140000080000001038000018700F9
+:106AC00000020A8000028E0000031180000395007E
+:106AD0000004188000049C0000051F800005A3002E
+:106AE000000626800006AA0000072D800007B100DE
+:106AF000000834800008B80000093B800009BF008E
+:106B0000000A4280000AC600000B4980000BCD003D
+:106B1000000C5080000CD400000D578000005B007A
+:106B200000007FF800007FF80000022A0000350016
+:106B30000000FF00000000000000FF000000000057
+:106B40000000FF00000000000000FF000000000047
+:106B50000000FF00000000000000FF000000000037
+:106B60000000FF00000000000000FF000000000027
+:106B70000000FF00000000000000FF000000000017
+:106B80000000FF00000000000000FF000000000007
+:106B90000000FF00000000000000FF0000000000F7
+:106BA0000000FF00000000000000FF0000000000E7
+:106BB0000000FF00000000000000FF0000000000D7
+:106BC0000000FF00000000000000FF0000000000C7
+:106BD0000000FF00000000000000FF0000000000B7
+:106BE0000000FF00000000000000FF0000000000A7
+:106BF0000000FF00000000000000FF000000000097
+:106C00000000FF00000000000000FF000000000086
+:106C10000000FF00000000000000FF000000000076
+:106C20000000FF00000000000000FF000000000066
+:106C30000000FF00000000000000FF000000000056
+:106C40000000FF00000000000000FF000000000046
+:106C50000000FF00000000000000FF000000000036
+:106C60000000FF00000000000000FF000000000026
+:106C70000000FF00000000000000FF000000000016
+:106C80000000FF00000000000000FF000000000006
+:106C90000000FF00000000000000FF0000000000F6
+:106CA0000000FF00000000000000FF0000000000E6
+:106CB0000000FF00000000000000FF0000000000D6
+:106CC0000000FF00000000000000FF0000000000C6
+:106CD0000000FF00000000000000FF0000000000B6
+:106CE0000000FF00000000000000FF0000000000A6
+:106CF0000000FF00000000000000FF000000000096
+:106D00000000FF00000000000000FF000000000085
+:106D10000000FF00000000000000FF000000000075
+:106D20000000FF00000000000000FF000000000065
+:106D30000000FF00000000000000FF000000000055
+:106D40000000FF00000000000000FF000000000045
+:106D50000000FF00000000000000FF000000000035
+:106D60000000FF00000000000000FF00000019000C
+:106D70000000000000000000FFFFFFFF0000000017
+:106D800003938700000000000393870000007FF852
+:106D900000007FF800000BA700003500000000FF96
+:106DA000000000FF000000FF000000FF000000FFE7
+:106DB000000000FF000000FF000000FF0000FF00D7
+:106DC000000000000000FF00000000000000FF00C5
+:106DD000000000000000FF00000000000000FF00B5
+:106DE000000000000000FF00000000000000FF00A5
+:106DF000000000000000FF00000000000000FF0095
+:106E0000000000000000FF00000000000000FF0084
+:106E1000000000000000FF00000000000000FF0074
+:106E2000000000000000FF00000000000000FF0064
+:106E3000000000000000FF00000000000000FF0054
+:106E4000000000000000FF00000000000000FF0044
+:106E5000000000000000FF00000000000000FF0034
+:106E6000000000000000FF00000000000000FF0024
+:106E7000000000000000FF00000000000000FF0014
+:106E8000000000000000FF00000000000000FF0004
+:106E9000000000000000FF00000000000000FF00F4
+:106EA000000000000000FF00000000000000FF00E4
+:106EB000000000000000FF00000000000000FF00D4
+:106EC000000000000000FF00000000000000FF00C4
+:106ED000000000000000FF00000000000000FF00B4
+:106EE000000000000000FF00000000000000FF00A4
+:106EF000000000000000FF00000000000000FF0094
+:106F0000000000000000FF00000000000000FF0083
+:106F1000000000000000FF00000000000000FF0073
+:106F2000000000000000FF00000000000000FF0063
+:106F3000000000000000FF00000000000000FF0053
+:106F4000000000000000FF00000000000000FF0043
+:106F5000000000000000FF00000000000000FF0033
+:106F6000000000000000FF00000000000000FF0023
+:106F7000000000000000FF00000000000000FF0013
+:106F8000000000000000FF00000000000000FF0003
+:106F9000000000000000FF00000000000000FF00F3
+:106FA000000000000000FF00000000000000FF00E3
+:106FB000000000000000FF00000000000000FF00D3
+:106FC000000000000000FF00000000000000FF00C3
+:106FD000000000000000FF00000000000000FF00B3
+:106FE000000000000000FF00000000000000FF00A3
+:106FF000000000000000FF0000000000FFFFFFFF96
+:10700000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
+:10701000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80
+:10702000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70
+:10703000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60
+:10704000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50
+:10705000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40
+:10706000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30
+:10707000FFFFFFFFFFFFFFFFFFFFFFFF000000001C
+:10708000000028AD000029180000291900000005A3
+:10709000000000070000FF000FFFFFFF0000FF00DF
+:1070A0000FFFFFFF000000FF0000FF000000FF00D7
+:1070B0000FFFFFFF0000FF000FFFFFFF000000FFBA
+:1070C0000000FF000000FF000FFFFFFF0000FF00B7
+:1070D0000FFFFFFF000000FF0000FF000000FF00A7
+:1070E0000FFFFFFF0000FF000FFFFFFF000000FF8A
+:1070F0000000FF000000FF000FFFFFFF0000FF0087
+:107100000FFFFFFF000000FF0000FF000000FF0076
+:107110000FFFFFFF0000FF000FFFFFFF000000FF59
+:107120000000FF000000FF000FFFFFFF0000FF0056
+:107130000FFFFFFF000000FF0000FF000000FF0046
+:107140000FFFFFFF0000FF000FFFFFFF000000FF29
+:107150000000FF000000FF000FFFFFFF0000FF0026
+:107160000FFFFFFF000000FF0000FF000000FF0016
+:107170000FFFFFFF0000FF000FFFFFFF000000FFF9
+:107180000000FF000000FF000FFFFFFF0000FF00F6
+:107190000FFFFFFF000000FF0000FF000000FF00E6
+:1071A0000FFFFFFF0000FF000FFFFFFF000000FFC9
+:1071B0000000FF000000FF000FFFFFFF0000FF00C6
+:1071C0000FFFFFFF000000FF0000FF000000FF00B6
+:1071D0000FFFFFFF0000FF000FFFFFFF000000FF99
+:1071E0000000FF000000FF000FFFFFFF0000FF0096
+:1071F0000FFFFFFF000000FF0000FF000000FF0086
+:107200000FFFFFFF0000FF000FFFFFFF000000FF68
+:107210000000FF000000FF000FFFFFFF0000FF0065
+:107220000FFFFFFF000000FF0000FF000000FF0055
+:107230000FFFFFFF0000FF000FFFFFFF000000FF38
+:107240000000FF000000FF000FFFFFFF0000FF0035
+:107250000FFFFFFF000000FF0000FF000000FF0025
+:107260000FFFFFFF0000FF000FFFFFFF000000FF08
+:107270000000FF000000FF000FFFFFFF0000FF0005
+:107280000FFFFFFF000000FF0000FF000000FF00F5
+:107290000FFFFFFF0000FF000FFFFFFF000000FFD8
+:1072A0000000FF000000FF000FFFFFFF0000FF00D5
+:1072B0000FFFFFFF000000FF0000FF000000FF00C5
+:1072C0000FFFFFFF0000FF000FFFFFFF000000FFA8
+:1072D0000000FF000000FF000FFFFFFF0000FF00A5
+:1072E0000FFFFFFF000000FF0000FF000000FF0095
+:1072F0000FFFFFFF0000FF000FFFFFFF000000FF78
+:107300000000FF000000FF000FFFFFFF0000FF0074
+:107310000FFFFFFF000000FF0000FF000000FF0064
+:107320000FFFFFFF0000FF000FFFFFFF000000FF47
+:107330000000FF000000FF000FFFFFFF0000FF0044
+:107340000FFFFFFF000000FF0000FF000000FF0034
+:107350000FFFFFFF0000FF000FFFFFFF000000FF17
+:107360000000FF000000FF000FFFFFFF0000FF0014
+:107370000FFFFFFF000000FF0000FF000000FF0004
+:107380000FFFFFFF0000FF000FFFFFFF000000FFE7
+:107390000000FF000000FF000FFFFFFF0000FF00E4
+:1073A0000FFFFFFF000000FF0000FF000000FF00D4
+:1073B0000FFFFFFF0000FF000FFFFFFF000000FFB7
+:1073C0000000FF000000FF000FFFFFFF0000FF00B4
+:1073D0000FFFFFFF000000FF0000FF000000FF00A4
+:1073E0000FFFFFFF0000FF000FFFFFFF000000FF87
+:1073F0000000FF000000FF000FFFFFFF0000FF0084
+:107400000FFFFFFF000000FF0000FF000000FF0073
+:107410000FFFFFFF0000FF000FFFFFFF000000FF56
+:107420000000FF000000FF000FFFFFFF0000FF0053
+:107430000FFFFFFF000000FF0000FF000000FF0043
+:107440000FFFFFFF0000FF000FFFFFFF000000FF26
+:107450000000FF000000FF000FFFFFFF0000FF0023
+:107460000FFFFFFF000000FF0000FF000000FF0013
+:107470000FFFFFFF0000FF000FFFFFFF000000FFF6
+:107480000000FF000000FF000FFFFFFF0000FF00F3
+:107490000FFFFFFF000000FF0000FF000000FF00E3
+:1074A0000FFFFFFF0000FF000FFFFFFF000000FFC6
+:1074B0000000FF000000FF000FFFFFFF0000FF00C3
+:1074C0000FFFFFFF000000FF0000FF000000FF00B3
+:1074D0000FFFFFFF0000FF000FFFFFFF000000FF96
+:1074E0000000FF000000FF000FFFFFFF0000FF0093
+:1074F0000FFFFFFF000000FF0000FF000000FF0083
+:107500000FFFFFFF0000FF000FFFFFFF000000FF65
+:107510000000FF000000FF000FFFFFFF0000FF0062
+:107520000FFFFFFF000000FF0000FF000000FF0052
+:107530000FFFFFFF0000FF000FFFFFFF000000FF35
+:107540000000FF000000FF000FFFFFFF0000FF0032
+:107550000FFFFFFF000000FF0000FF000000FF0022
+:107560000FFFFFFF0000FF000FFFFFFF000000FF05
+:107570000000FF000000FF000FFFFFFF0000FF0002
+:107580000FFFFFFF000000FF0000FF000000FF00F2
+:107590000FFFFFFF0000FF000FFFFFFF000000FFD5
+:1075A0000000FF000000FF000FFFFFFF0000FF00D2
+:1075B0000FFFFFFF000000FF0000FF000000FF00C2
+:1075C0000FFFFFFF0000FF000FFFFFFF000000FFA5
+:1075D0000000FF000000FF000FFFFFFF0000FF00A2
+:1075E0000FFFFFFF000000FF0000FF000000FF0092
+:1075F0000FFFFFFF0000FF000FFFFFFF000000FF75
+:107600000000FF000000FF000FFFFFFF0000FF0071
+:107610000FFFFFFF000000FF0000FF000000FF0061
+:107620000FFFFFFF0000FF000FFFFFFF000000FF44
+:107630000000FF000000FF000FFFFFFF0000FF0041
+:107640000FFFFFFF000000FF0000FF000000FF0031
+:107650000FFFFFFF0000FF000FFFFFFF000000FF14
+:107660000000FF000000FF000FFFFFFF0000FF0011
+:107670000FFFFFFF000000FF0000FF000000FF0001
+:107680000FFFFFFF0000FF000FFFFFFF000000FFE4
+:107690000000FF000000FF000FFFFFFF0000FF00E1
+:1076A0000FFFFFFF000000FF0000FF000000FF00D1
+:1076B0000FFFFFFF0000FF000FFFFFFF000000FFB4
+:1076C0000000FF000000FF000FFFFFFF0000FF00B1
+:1076D0000FFFFFFF000000FF0000FF000000FF00A1
+:1076E0000FFFFFFF0000FF000FFFFFFF000000FF84
+:1076F0000000FF000000FF000FFFFFFF0000FF0081
+:107700000FFFFFFF000000FF0000FF000000FF0070
+:107710000FFFFFFF0000FF000FFFFFFF000000FF53
+:107720000000FF000000FF000FFFFFFF0000FF0050
+:107730000FFFFFFF000000FF0000FF000000FF0040
+:107740000FFFFFFF0000FF000FFFFFFF000000FF23
+:107750000000FF000000FF000FFFFFFF0000FF0020
+:107760000FFFFFFF000000FF0000FF000000FF0010
+:107770000FFFFFFF0000FF000FFFFFFF000000FFF3
+:107780000000FF000000FF000FFFFFFF0000FF00F0
+:107790000FFFFFFF000000FF0000FF000000FF00E0
+:1077A0000FFFFFFF0000FF000FFFFFFF000000FFC3
+:1077B0000000FF000000FF000FFFFFFF0000FF00C0
+:1077C0000FFFFFFF000000FF0000FF000000FF00B0
+:1077D0000FFFFFFF0000FF000FFFFFFF000000FF93
+:1077E0000000FF000000FF000FFFFFFF0000FF0090
+:1077F0000FFFFFFF000000FF0000FF000000FF0080
+:107800000FFFFFFF0000FF000FFFFFFF000000FF62
+:107810000000FF000000FF000FFFFFFF0000FF005F
+:107820000FFFFFFF000000FF0000FF000000FF004F
+:107830000FFFFFFF0000FF000FFFFFFF000000FF32
+:107840000000FF000000FF000FFFFFFF0000FF002F
+:107850000FFFFFFF000000FF0000FF000000FF001F
+:107860000FFFFFFF0000FF000FFFFFFF000000FF02
+:107870000000FF000000FF000FFFFFFF0000FF00FF
+:107880000FFFFFFF000000FF0000FF000000FF00EF
+:107890000FFFFFFF0000FF000FFFFFFF000000FFD2
+:1078A0000000FF000000FF000FFFFFFF0000FF00CF
+:1078B0000FFFFFFF000000FF0000FF000000FF00BF
+:1078C0000FFFFFFF0000FF000FFFFFFF000000FFA2
+:1078D0000000FF000000FF000FFFFFFF0000FF009F
+:1078E0000FFFFFFF000000FF0000FF000000FF008F
+:1078F0000FFFFFFF0000FF000FFFFFFF000000FF72
+:107900000000FF000000FF000FFFFFFF0000FF006E
+:107910000FFFFFFF000000FF0000FF000000FF005E
+:107920000FFFFFFF0000FF000FFFFFFF000000FF41
+:107930000000FF000000FF000FFFFFFF0000FF003E
+:107940000FFFFFFF000000FF0000FF000000FF002E
+:107950000FFFFFFF0000FF000FFFFFFF000000FF11
+:107960000000FF000000FF000FFFFFFF0000FF000E
+:107970000FFFFFFF000000FF0000FF000000FF00FE
+:107980000FFFFFFF0000FF000FFFFFFF000000FFE1
+:107990000000FF000000FF000FFFFFFF0000FF00DE
+:1079A0000FFFFFFF000000FF0000FF000000FF00CE
+:1079B0000FFFFFFF0000FF000FFFFFFF000000FFB1
+:1079C0000000FF000000FF000FFFFFFF0000FF00AE
+:1079D0000FFFFFFF000000FF0000FF000000FF009E
+:1079E0000FFFFFFF0000FF000FFFFFFF000000FF81
+:1079F0000000FF000000FF000FFFFFFF0000FF007E
+:107A00000FFFFFFF000000FF0000FF000000FF006D
+:107A10000FFFFFFF0000FF000FFFFFFF000000FF50
+:107A20000000FF000000FF000FFFFFFF0000FF004D
+:107A30000FFFFFFF000000FF0000FF000000FF003D
+:107A40000FFFFFFF0000FF000FFFFFFF000000FF20
+:107A50000000FF000000FF000FFFFFFF0000FF001D
+:107A60000FFFFFFF000000FF0000FF000000FF000D
+:107A70000FFFFFFF0000FF000FFFFFFF000000FFF0
+:107A80000000FF000000FF000FFFFFFF0000FF00ED
+:107A90000FFFFFFF000000FF0000FF000000FF00DD
+:107AA0000FFFFFFF0000FF000FFFFFFF000000FFC0
+:107AB0000000FF000000FF000FFFFFFF0000FF00BD
+:107AC0000FFFFFFF000000FF0000FF000000FF00AD
+:107AD0000FFFFFFF0000FF000FFFFFFF000000FF90
+:107AE0000000FF000000FF000FFFFFFF0000FF008D
+:107AF0000FFFFFFF000000FF0000FF000000FF007D
+:107B00000FFFFFFF0000FF000FFFFFFF000000FF5F
+:107B10000000FF000000FF000FFFFFFF0000FF005C
+:107B20000FFFFFFF000000FF0000FF000000FF004C
+:107B30000FFFFFFF0000FF000FFFFFFF000000FF2F
+:107B40000000FF000000FF000FFFFFFF0000FF002C
+:107B50000FFFFFFF000000FF0000FF000000FF001C
+:107B60000FFFFFFF0000FF000FFFFFFF000000FFFF
+:107B70000000FF000000FF000FFFFFFF0000FF00FC
+:107B80000FFFFFFF000000FF0000FF000000FF00EC
+:107B90000FFFFFFF0000FF000FFFFFFF000000FFCF
+:107BA0000000FF000000FF000FFFFFFF0000FF00CC
+:107BB0000FFFFFFF000000FF0000FF000000FF00BC
+:107BC0000FFFFFFF0000FF000FFFFFFF000000FF9F
+:107BD0000000FF000000FF000FFFFFFF0000FF009C
+:107BE0000FFFFFFF000000FF0000FF000000FF008C
+:107BF0000FFFFFFF0000FF000FFFFFFF000000FF6F
+:107C00000000FF000000FF000FFFFFFF0000FF006B
+:107C10000FFFFFFF000000FF0000FF000000FF005B
+:107C20000FFFFFFF0000FF000FFFFFFF000000FF3E
+:107C30000000FF000000FF000FFFFFFF0000FF003B
+:107C40000FFFFFFF000000FF0000FF000000FF002B
+:107C50000FFFFFFF0000FF000FFFFFFF000000FF0E
+:107C60000000FF000000FF000FFFFFFF0000FF000B
+:107C70000FFFFFFF000000FF0000FF000000FF00FB
+:107C80000FFFFFFF0000FF000FFFFFFF000000FFDE
+:107C90000000FF000000FF000FFFFFFF0000FF00DB
+:107CA0000FFFFFFF000000FF0000FF000000FF00CB
+:107CB0000FFFFFFF0000FF000FFFFFFF000000FFAE
+:107CC0000000FF000000FF000FFFFFFF0000FF00AB
+:107CD0000FFFFFFF000000FF0000FF000000FF009B
+:107CE0000FFFFFFF0000FF000FFFFFFF000000FF7E
+:107CF0000000FF000000FF000FFFFFFF0000FF007B
+:107D00000FFFFFFF000000FF0000FF000000FF006A
+:107D10000FFFFFFF0000FF000FFFFFFF000000FF4D
+:107D20000000FF000000FF000FFFFFFF0000FF004A
+:107D30000FFFFFFF000000FF0000FF000000FF003A
+:107D40000FFFFFFF0000FF000FFFFFFF000000FF1D
+:107D50000000FF0000001000000020800000310043
+:107D600000004180000052000000628000007300AB
+:107D700000008380000094000000A4800000B50093
+:107D80000000C5800000D6000000E6800000F7007B
+:107D9000000107800001180000012880000139005F
+:107DA0000001498000015A0000016A8000017B0047
+:107DB00000018B8000019C000001AC800001BD002F
+:107DC0000001CD800001DE000001EE800001FF0017
+:107DD00000000F8000007FF800007FF8000005F928
+:107DE0000000350010000000000028AD0000291838
+:107DF0000000291900000005000000060001000134
+:107E000000220006CCCCCCC97058103C0000FF000A
+:107E1000000000000000FF00000000000000FF0064
+:107E2000000000000000FF00000000000000FF0054
+:107E3000000000000000FF00000000000000FF0044
+:107E4000000000000000FF00000000000000FF0034
+:107E5000000000000000FF00000000000000FF0024
+:107E6000000000000000FF00000000000000FF0014
+:107E7000000000000000FF00000000000000FF0004
+:107E8000000000000000FF00000000000000FF00F4
+:107E9000000000000000FF00000000000000FF00E4
+:107EA000000000000000FF00000000000000FF00D4
+:107EB000000000000000FF00000000000000FF00C4
+:107EC000000000000000FF00000000000000FF00B4
+:107ED000000000000000FF00000000000000FF00A4
+:107EE000000000000000FF00000000000000FF0094
+:107EF000000000000000FF00000000000000FF0084
+:107F0000000000000000FF00000000000000FF0073
+:107F1000000000000000FF00000000000000FF0063
+:107F2000000000000000FF00000000000000FF0053
+:107F3000000000000000FF00000000000000FF0043
+:107F4000000000000000FF00000000000000FF0033
+:107F5000000000000000FF00000000000000FF0023
+:107F6000000000000000FF00000000000000FF0013
+:107F7000000000000000FF00000000000000FF0003
+:107F8000000000000000FF00000000000000FF00F3
+:107F9000000000000000FF00000000000000FF00E3
+:107FA000000000000000FF00000000000000FF00D3
+:107FB000000000000000FF00000000000000FF00C3
+:107FC000000000000000FF00000000000000FF00B3
+:107FD000000000000000FF00000000000000FF00A3
+:107FE000000000000000FF00000000000000FF0093
+:107FF000000000000000FF00000000000000FF0083
+:10800000000000000000FF00000000000000FF0072
+:10801000000000000000FF00000000000000FF0062
+:10802000000000000000FF00000000000000FF0052
+:10803000000000000000FF00000000000000FF0042
+:10804000000000000000FF00000000000000000130
+:10805000CCCC0201CCCCCCCCCCCC0201CCCCCCCC8A
+:10806000CCCC0201CCCCCCCCCCCC0201CCCCCCCC7A
+:10807000CCCC0201CCCCCCCCCCCC0201CCCCCCCC6A
+:10808000CCCC0201CCCCCCCCCCCC0201CCCCCCCC5A
+:1080900000000000FFFFFFFF03030303134202027F
+:1080A0005050502070608050020002000604060408
+:1080B000000E0000011600D6002625A0002625A0EF
+:1080C000002625A0002625A000720000012300F351
+:1080D000002625A0002625A0002625A0002625A0F4
+:1080E0000000FFFF000000000000FFFF0000000094
+:1080F0000000FFFF000000000000FFFF0000000084
+:108100000000FFFF000000000000FFFF0000000073
+:108110000000FFFF000000000000FFFF0000000063
+:108120000000FFFF000000000000FFFF0000000053
+:108130000000FFFF000000000000FFFF0000000043
+:108140000000FFFF000000000000FFFF0000000033
+:108150000000FFFF000000000000FFFF0000000023
+:108160000000FFFF000000000000FFFF0000000013
+:108170000000FFFF000000000000FFFF0000000003
+:108180000000FFFF000000000000FFFF00000000F3
+:108190000000FFFF000000000000FFFF00000000E3
+:1081A0000000FFFF000000000000FFFF00000000D3
+:1081B0000000FFFF000000000000FFFF00000000C3
+:1081C0000000FFFF000000000000FFFF00000000B3
+:1081D0000000FFFF000000000000FFFF00000000A3
+:1081E0000000FFFF000000000000FFFF0000000093
+:1081F0000000FFFF000000000000FFFF0000000083
+:108200000000FFFF000000000000FFFF0000000072
+:108210000000FFFF000000000000FFFF0000000062
+:108220000000FFFF000000000000FFFF0000000052
+:108230000000FFFF000000000000FFFF0000000042
+:108240000000FFFF000000000000FFFF0000000032
+:108250000000FFFF000000000000FFFF0000000022
+:108260000000FFFF000000000000FFFF0000000012
+:108270000000FFFF000000000000FFFF0000000002
+:108280000000FFFF000000000000FFFF00000000F2
+:108290000000FFFF000000000000FFFF00000000E2
+:1082A0000000FFFF000000000000FFFF00000000D2
+:1082B0000000FFFF000000000000FFFF00000000C2
+:1082C0000000FFFF000000000000FFFF00000000B2
+:1082D0000000FFFF000000000000FFFF00000000A2
+:1082E000FFFFFFF3318FFFFF0C30C30CC30C30C313
+:1082F000CF3CF300F3CF3CF30000CF3CCDCDCDCD50
+:10830000FFFFFFF130EFFFFF0C30C30CC30C30C395
+:10831000CF3CF300F3CF3CF30001CF3CCDCDCDCD2E
+:10832000FFFFFFF6305FFFFF0C30C30CC30C30C300
+:10833000CF3CF300F3CF3CF30002CF3CCDCDCDCD0D
+:10834000FFFFF4061CBFFFFF0C30C305C30C30C396
+:10835000CF300014F3CF3CF30004CF3CCDCDCDCDD6
+:10836000FFFFFFF2304FFFFF0C30C30CC30C30C3D4
+:10837000CF3CF300F3CF3CF30008CF3CCDCDCDCDC7
+:10838000FFFFFFFA302FFFFF0C30C30CC30C30C3CC
+:10839000CF3CF300F3CF3CF30010CF3CCDCDCDCD9F
+:1083A000FFFFFFF731EFFFFF0C30C30CC30C30C3EE
+:1083B000CF3CF300F3CF3CF30020CF3CCDCDCDCD6F
+:1083C000FFFFFFF5302FFFFF0C30C30CC30C30C391
+:1083D000CF3CF300F3CF3CF30040CF3CCDCDCDCD2F
+:1083E000FFFFFFF3318FFFFF0C30C30CC30C30C312
+:1083F000CF3CF300F3CF3CF30000CF3CCDCDCDCD4F
+:10840000FFFFFFF1310FFFFF0C30C30CC30C30C373
+:10841000CF3CF300F3CF3CF30001CF3CCDCDCDCD2D
+:10842000FFFFFFF6305FFFFF0C30C30CC30C30C3FF
+:10843000CF3CF300F3CF3CF30002CF3CCDCDCDCD0C
+:10844000FFFFF4061CBFFFFF0C30C305C30C30C395
+:10845000CF300014F3CF3CF30004CF3CCDCDCDCDD5
+:10846000FFFFFFF2304FFFFF0C30C30CC30C30C3D3
+:10847000CF3CF300F3CF3CF30008CF3CCDCDCDCDC6
+:10848000FFFFFFFA302FFFFF0C30C30CC30C30C3CB
+:10849000CF3CF300F3CF3CF30010CF3CCDCDCDCD9E
+:1084A000FFFFFFF730EFFFFF0C30C30CC30C30C3EE
+:1084B000CF3CF300F3CF3CF30020CF3CCDCDCDCD6E
+:1084C000FFFFFFF5304FFFFF0C30C30CC30C30C370
+:1084D000CF3CF300F3CF3CF30040CF3CCDCDCDCD2E
+:1084E000FFFFFFFF30CFFFFF0C30C30CC30C30C3C6
+:1084F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD82
+:10850000FFFFFFFF30CFFFFF0C30C30CC30C30C3A5
+:10851000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD60
+:10852000FFFFFFFF30CFFFFF0C30C30CC30C30C385
+:10853000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD3F
+:10854000FFFFFFFF30CFFFFF0C30C30CC30C30C365
+:10855000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD1D
+:10856000FFFFFFFF30CFFFFF0C30C30CC30C30C345
+:10857000CF3CF3CCF3CF3CF30008CF3CCDCDCDCDF9
+:10858000FFFFFFFF30CFFFFF0C30C30CC30C30C325
+:10859000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDD1
+:1085A000FFFFFFFF30CFFFFF0C30C30CC30C30C305
+:1085B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCDA1
+:1085C000FFFFFFFF30CFFFFF0C30C30CC30C30C3E5
+:1085D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD61
+:1085E000FFFFFFF3320FFFFF0C30C30CC30C30C38F
+:1085F000CF3CF300F3CF3CF30000CF3CCDCDCDCD4D
+:10860000FFFFFFF1310FFFFF0C30C30CC30C30C371
+:10861000CF3CF300F3CF3CF30001CF3CCDCDCDCD2B
+:10862000FFFFFFF6305FFFFF0C30C30CC30C30C3FD
+:10863000CF3CF300F3CF3CF30002CF3CCDCDCDCD0A
+:10864000FFFFF4061CBFFFFF0C30C305C30C30C393
+:10865000CF300014F3CF3CF30004CF3CCDCDCDCDD3
+:10866000FFFFFFF2304FFFFF0C30C30CC30C30C3D1
+:10867000CF3CF300F3CF3CF30008CF3CCDCDCDCDC4
+:10868000FFFFFF8A042FFFFF0C30C30CC30C30C365
+:10869000CF3CC000F3CF3CF30010CF3CCDCDCDCDCF
+:1086A000FFFFFF9705CFFFFF0C30C30CC30C30C397
+:1086B000CF3CC000F3CF3CF30020CF3CCDCDCDCD9F
+:1086C000FFFFFFF5310FFFFF0C30C30CC30C30C3AD
+:1086D000CF3CF300F3CF3CF30040CF3CCDCDCDCD2C
+:1086E000FFFFFFF3320FFFFF0C30C30CC30C30C38E
+:1086F000CF3CF300F3CF3CF30000CF3CCDCDCDCD4C
+:10870000FFFFFFF1302FFFFF0C30C30CC30C30C351
+:10871000CF3CF300F3CF3CF30001CF3CCDCDCDCD2A
+:10872000FFFFFFF6305FFFFF0C30C30CC30C30C3FC
+:10873000CF3CF300F3CF3CF30002CF3CCDCDCDCD09
+:10874000FFFFFF061CBFFFFF0C30C30CC30C30C380
+:10875000CF3CC014F3CF3CF30004CF3CCDCDCDCD06
+:10876000FFFFFFF2304FFFFF0C30C30CC30C30C3D0
+:10877000CF3CF300F3CF3CF30008CF3CCDCDCDCDC3
+:10878000FFFFFFFA302FFFFF0C30C30CC30C30C3C8
+:10879000CF3CF300F3CF3CF30010CF3CCDCDCDCD9B
+:1087A000FFFFFFF731CFFFFF0C30C30CC30C30C30A
+:1087B000CF3CF300F3CF3CF30020CF3CCDCDCDCD6B
+:1087C000FFFFFFFF30CFFFFF0C30C30CC30C30C3E3
+:1087D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD5F
+:1087E000FFFFFFFF30CFFFFF0C30C30CC30C30C3C3
+:1087F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD7F
+:10880000FFFFFFFF30CFFFFF0C30C30CC30C30C3A2
+:10881000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD5D
+:10882000FFFFFFFF30CFFFFF0C30C30CC30C30C382
+:10883000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD3C
+:10884000FFFFFFFF30CFFFFF0C30C30CC30C30C362
+:10885000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD1A
+:10886000FFFFFFFF30CFFFFF0C30C30CC30C30C342
+:10887000CF3CF3CCF3CF3CF30008CF3CCDCDCDCDF6
+:10888000FFFFFFFF30CFFFFF0C30C30CC30C30C322
+:10889000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDCE
+:1088A000FFFFFFFF30CFFFFF0C30C30CC30C30C302
+:1088B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCD9E
+:1088C000FFFFFFFF30CFFFFF0C30C30CC30C30C3E2
+:1088D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD5E
+:1088E000FFFFFFFF30CFFFFF0C30C30CC30C30C3C2
+:1088F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD7E
+:10890000FFFFFFFF30CFFFFF0C30C30CC30C30C3A1
+:10891000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD5C
+:10892000FFFFFFFF30CFFFFF0C30C30CC30C30C381
+:10893000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD3B
+:10894000FFFFFFFF30CFFFFF0C30C30CC30C30C361
+:10895000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD19
+:10896000FFFFFFFF30CFFFFF0C30C30CC30C30C341
+:10897000CF3CF3CCF3CF3CF30008CF3CCDCDCDCDF5
+:10898000FFFFFFFF30CFFFFF0C30C30CC30C30C321
+:10899000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDCD
+:1089A000FFFFFFFF30CFFFFF0C30C30CC30C30C301
+:1089B000CF3CF3CCF3CF3CF30020CF3CCDCDCDCD9D
+:1089C000FFFFFFFF30CFFFFF0C30C30CC30C30C3E1
+:1089D000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD5D
+:1089E000FFFFFFFF30CFFFFF0C30C30CC30C30C3C1
+:1089F000CF3CF3CCF3CF3CF30000CF3CCDCDCDCD7D
+:108A0000FFFFFFFF30CFFFFF0C30C30CC30C30C3A0
+:108A1000CF3CF3CCF3CF3CF30001CF3CCDCDCDCD5B
+:108A2000FFFFFFFF30CFFFFF0C30C30CC30C30C380
+:108A3000CF3CF3CCF3CF3CF30002CF3CCDCDCDCD3A
+:108A4000FFFFFFFF30CFFFFF0C30C30CC30C30C360
+:108A5000CF3CF3CCF3CF3CF30004CF3CCDCDCDCD18
+:108A6000FFFFFFFF30CFFFFF0C30C30CC30C30C340
+:108A7000CF3CF3CCF3CF3CF30008CF3CCDCDCDCDF4
+:108A8000FFFFFFFF30CFFFFF0C30C30CC30C30C320
+:108A9000CF3CF3CCF3CF3CF30010CF3CCDCDCDCDCC
+:108AA000FFFFFFFF30CFFFFF0C30C30CC30C30C300
+:108AB000CF3CF3CCF3CF3CF30020CF3CCDCDCDCD9C
+:108AC000FFFFFFFF30CFFFFF0C30C30CC30C30C3E0
+:108AD000CF3CF3CCF3CF3CF30040CF3CCDCDCDCD5C
+:108AE000000C0000000700C000028130000B81581C
+:108AF0000002021000010230000F024000010330AA
+:108B0000000C0000000800C000028140000B8168DA
+:108B1000000202200001024000070250000202C0D1
+:108B2000001000000008010000028180000B81A8F5
+:108B30000002026000018280000E8298000803801B
+:108B4000001000000001010000028110000901383E
+:108B5000000201C8000101E8000E01F8000002D87F
+:108B6000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC45
+:108B700000002000CCCCCCCCCCCCCCCCCCCCCCCC45
+:108B8000CCCCCCCC00002000CCCCCCCCCCCCCCCC35
+:108B9000CCCCCCCCCCCCCCCC04002000CCCCCCCC21
+:108BA000CCCCCCCCCCCCCCCCCCCCCCCC41002000D4
+:108BB00003030303034202025050502070608050B0
+:108BC0001313131313421212505050207060805030
+:108BD000030102000000000000000000000000008F
+:108BE0001F8B080000000000000BFB51CFC0F003FA
+:108BF0008AF7093230288920F8C4E0427606864D8B
+:108C00001C0C0C5BB849D307C32C0C0C0CDA4CE4DD
+:108C1000E905E1DBBC0C0CCF8098810F555C80131B
+:108C200042FF075A20C80AB4830DBBFEE56A08B6A6
+:108C3000A70A0343011033283130E8AB22C445D4DE
+:108C400019182602F99150B1AB403A4C8D7C378F00
+:108C5000E2C1834F1AA3F2971A426807A8F8293491
+:108C6000F96550F9621D087DDA18BBB9253AC4D9F7
+:108C7000BFCB1A953FCD1ABFFA93F6A8FC7568EAE8
+:108C80001741F900B9FAD21DD80300000000000016
+:108C900000000000000000001F8B08000000000022
+:108CA000000BED7D7F7C14D5B5F8999DD9D9D9CD30
+:108CB000EE6608096C20E024861AFAA25D20609016
+:108CC000A843401ABF8FDA15A9A62DED77B5D4E2D7
+:108CD0000F60EBF3097DCF36931092101017B1D5CA
+:108CE00056AB2B0F2DF56B25B5D4D2FAA38B581E9E
+:108CF000B6EFF3BE4869EBD7621B7FE18F228D5A36
+:108D000084B658BFF79C7B273B33D94D36407FFC58
+:108D1000F1C207863B73EEBDE79E73EEB9E79C7B1D
+:108D2000EE8D0A35F0A133003EC09F0B016E0F019E
+:108D30004045EE695C7F7E4F7F03C05188A47BCBAA
+:108D400001D62860022B5B072399FB25C09F3A853B
+:108D50009557C91F8EF75603DC51F2957B117EB5EE
+:108D6000A540803D7BDB00B267B1EFA1E816280586
+:108D70002881D476FCCE7E12F7B3F68E05276720C5
+:108D80009AEBBF027C0033F173957EA884E0E00388
+:108D900099FD73303917C601C860FFAC863ED68E88
+:108DA0007240CE60BFB2BC50FF554DAE1DEF53D6E2
+:108DB00055C86AA23DFC475E529A0C17865F7DB08B
+:108DC0007AFBD37539F8B320527EE89FD87F1450D0
+:108DD000081F7903201D8E86212357176EE7589BA5
+:108DE000B1FD693FD2F133A589B30BC3D974EA69E8
+:108DF000D3E8D9D5A6433600C05036FBEAD9330CA8
+:108E0000E696FAA1F5E68144F4D20C8BF0E90CFB6E
+:108E10003225D588751280D1D78FF491F0FD22CDFF
+:108E2000CC53DF7E4239A38F3D5E46C720F0F680EB
+:108E30008DEF7ED65E10FBCF43AFCBB07F2627C130
+:108E4000DAA1FD5B0D27DF7F682AC0BE30D2DB448C
+:108E50001CC0A7A7202EF8FD51699876049F1583A2
+:108E6000B73312DD4BEA7CB97ED9DFA01172C94954
+:108E70002056E6961BAF5C229D2A905F86F4F29402
+:108E80005CBB2AF22D0FBDAE11F41A989B684D30D1
+:108E90007AAC6D03EB25473D390666260F9D568952
+:108EA0007A767F4A3983CBD33E40BB983F960BBE40
+:108EB00058FCBE7C92F8ADFF1BE1B749C83B409A15
+:108EC0009E03739384A7B7BD7CF38B4DE2C17248B8
+:108ED000C9583E94EF7288DFCF1E7E8DCF33FBFBE7
+:108EE000C3E0A77676A2C661FDAC11F80DCCE5FA19
+:108EF0006FED3435B345227DE4C2F321D45FAC9EDF
+:108F000024097A687D80F257725C01188BF8999079
+:108F10008800ACAB6DD686D33FA02B7FEAB7E5AE19
+:108F200066A8DC7D9875837885C2F9E9F4F0A01E07
+:108F30005D62BDC4DAD182ECFD99D86E79AC6A1657
+:108F4000E0E8E8C72FBE83E4933FC0797B82C1CDC0
+:108F5000127A56A6F6498F401590BE97053CF5C388
+:108F6000E0036C58E674F6C4F775A21F6968BBDEAF
+:108F70007AC7A08CD347E063EB75191EA77606F17C
+:108F80005112442FEF7B3F7BAF874FFDFDA996FD2C
+:108F90004681FED212C9D348F57F23E465887C164A
+:108FA000E0EB7E31CF14E833E1CC9C1CD9F275B2F2
+:108FB0007274CA72C2BAA7F5A2809C5890A279C3F3
+:108FC000C0ACDE69A397973C729275C22F94C6F02D
+:108FD0007128719217868F4272AB737C2AA69753C1
+:108FE0007B12CEF1B3B00551463AB0F15E65D7873A
+:108FF00038CDD710DA398EFA6C7084AF244B42EF3B
+:1090000073B89BC43C3FBFB98AE30FA27D0FBEACCF
+:109010003DCDD99E0C551E39E7786F94B87E63F02C
+:1090200059A2A7B77F45227C6548583E566F8BE80A
+:10903000DFABBFECE70ED1DE06095AFBC27C3E2D4A
+:1090400072AC87CD92D0131A9F675EFDE447B99A40
+:1090500071F27255AC5E5F28E55F77985514BB34AA
+:109060005278DD29F5D9EB413626F8362ABE9F29FC
+:1090700095B9F85E2CBE579D24BE1387E25B949C85
+:109080004D957CA35A276F3A49FC821EFC4E975C93
+:10909000CF1072562CFEF63C182DFEF250FA163503
+:1090A0008F668F12BF2D2749DF0A9F6D2709FC0AA3
+:1090B000CCDBF305BF2DE0F2A1303B1CFD9C62F13F
+:1090C0007B7464FC00CE637FAD172D53217B0D6054
+:1090D00002C0D3ED2F5A9692C3CF04AED747DBFF21
+:1090E0009E91F927FA7FC3326B73FD1F687FC3D54A
+:1090F000BFC2E40785ADD87E7F51ECB8E16DD7B82B
+:109100005F96DE76F57BB2747FB5E8FEFFE81AF76E
+:10911000BBD21FDDE30EB3719F597CBF7F38497905
+:10912000AC16F3A559D25DEB4021FB7D86E0EBDD6B
+:1091300036BC8D6F01F8A902AFCE22E1278AF63F37
+:1091400055247C9F68BF0FE12B46863F53C0A78AFA
+:1091500084977C7C1E165A3FE74A36FDC0E57FACFB
+:10916000D1781CC45CA340F082A17113AB39F5AD7A
+:109170007EC67BAB23A0AF29A7B809C545560324FB
+:10918000306E7217241B7D187FD9F9E57B11EE1D17
+:1091900045D37B75E013927D0F1E8C6CE9ADCEF547
+:1091A000B74A4EB64A284B6BA2FAFD145F49B54A3E
+:1091B000EC596185758CDB1CAB49B45F598EE3308B
+:1091C000748BB5F3FCB2CB7661F9364DD265266A65
+:1091D0005FBD60EAA6CB0D06F7FEAEE7CE40B869EC
+:1091E000E36A3A485FC6259487B171D594CF61CFC1
+:1091F000C58BB97E07E10FB738CACC0EF864EB27F0
+:109200005CDF3F9D74973FD1F289DC7AC2FE5E91AC
+:10921000707FCF8D07B8DF3187EBED6335A9DF7243
+:10922000BC3E546DF1F8028DB7D48AD2F836BCFF3B
+:10923000452A6F68AFD73BD8B83F75CD510BC717DC
+:109240009680C6178DBF97C532B0F1AA8D00B75E64
+:10925000F04CCF2C28EC7F459B16BBF084B87B9C50
+:10926000ADD7E7C75BD5DF9DF00AB3978EED0A9ABD
+:10927000884F74AF9C0956235F07B293B07FAB341D
+:10928000C9F93300B5C8575307E463B399CCC8ECA8
+:109290007D3AA6C5032866D0AF21DD372168257B3E
+:1092A000DFF88E96ACC7F6DFA3F675F1FDD6C69A49
+:1092B000F1181F79BC6DF54485CDF71FB55913150D
+:1092C00066B4EF6CEBA1E7A36D697ABFA3ED4E7AAC
+:1092D000DAE3434D62D8E393B11FB303E5ED989F02
+:1092E00099460CAF8DE7FBC8BFDD20F44897782A7C
+:1092F0004A562EC5EF7198D60B88D7FE79584E374F
+:10930000C0346459BAE929B9948DE3864A988E6DC0
+:10931000EF7AE157FC7B154C0F30F97ACA6CA679CD
+:10932000706BA32F13A8A6E7C5D8DFADA60F98C909
+:10933000039138C3CB41D740CC5DD621B926D2406A
+:10934000FDC77B0DAC7FC36E2CDF3093194A40ED17
+:10935000CB11A223C4B1BF99074CD2E381261FC50C
+:10936000E9D24DBE20D271A47ED248D761E25573B6
+:109370005E77C3CFEE779799C6FBCDA07C70FA3E9F
+:10938000EC637A62F70BE37D5639E141E3674F1EE8
+:10939000478CF9326894DE26E86CD3FD5884EB9D47
+:1093A0008DCC3FC47860217C369E776D6CB8788216
+:1093B000DAD8958073F0994E60BC556DCC88671FE4
+:1093C000BDF7C23F8F46D1CC5CB92B367DCC95F52D
+:1093D000397CBCF0136495E4FF5805FFDE157B4A29
+:1093E000BF32EC6C4FF27ED73E5FEFFCEEA7FE8EF5
+:1093F00055DADFF76B57D6E7A93F897DCFC397A52D
+:1094000032D7C34FBF1068FE1ACAA7A0EFEE175E8F
+:10941000DB7B26D2FB800C280FE97DCD240F287F33
+:10942000A8479E62F2D0CFDA1BDBB2E137CEF91C3F
+:1094300089BBCBE946864003E71B76F55F821F3F79
+:1094400015F1DABD225EBBA72D46CFA7DB0C7A3E15
+:10945000D55647DFB36D712A3FD9D648E5C7DB4CF7
+:109460002AFFA8AD85CA3BDB12547EB4AD959E3B66
+:10947000DA92F4BCAD6D193DD34D7C9E6F684B51B3
+:10948000B9AB6D35D5B3C7FF31A6359CF2F7CF75B3
+:10949000EEF2C5C659B9F9CEFE7E34E62E5FA47F42
+:1094A000D4559EA7B9CB73E10BAEF62E3C7EB5AB7F
+:1094B0007CFE40970B7ECEEBEEF2ECFE075CF0E715
+:1094C0003EE72ECFDCB7C7551EDBE22E47E2875CB6
+:1094D000ED0562EEF256543E5C7F917C74C56AC61F
+:1094E000E495BFC1EFD3839F737D978B949FAB7A35
+:1094F000AA517E5A7C71CB40F9E1F294467D260D4B
+:1095000095139B6F23C9978DC7DF5AAEFE479E8682
+:1095100097A7A2E5A141895B30541EBC7CF7CAC75E
+:10952000103D23E4E57FE4E01F430E607E19EBA4C9
+:10953000F0BA9AC7EE23BB35B015C8EEF3A30D5DA4
+:10954000E95887276793F9F6C1AEF5CD7D4466EDFE
+:1095500004CAA10BF749034A01FF56AC73018D7F82
+:109560000FD6A67D284F1130A6CBD30096FFE096EC
+:109570000957B1F6F709B8AEFBC1923E02306E82D0
+:109580009A44FF2652EBF673F6CA3CEE613FB77D74
+:109590003FD29AA1987F830BEFA1E3E6FB38F2C498
+:1095A00059ADBF66F340DE326BDB5AF60CD5264D63
+:1095B000D9C0FAE544B7A52183E0CCC68CE563AFFA
+:1095C0008255CC6E639FE5B0096887CDF699CFCA06
+:1095D00033C93EDA8F4FDBEED9269E8F8B7978998F
+:1095E000CFFC25D287C1FD6A3838BBDF11F90549A8
+:1095F0004BE271ABF8FD0C457F79DC653FD9E35355
+:10960000948499C8C3AF23B2D8E7D1E3AD3C3EA25E
+:1096100002EA8742F0AFCBEEFD31FB59CAFC0219DA
+:10962000F188F17D2838719971E9D943F150954459
+:1096300012FBC17DEC2DAC9FCE31971B49473F9269
+:1096400022F08999848FAA737C54256E26F2C8D1A2
+:109650009F043E763BF67E9A141B80FE700EBFB5CB
+:10966000C144EB95E8B78E51894E9D11B7FD354B3E
+:10967000E17276967876FAF3DB87001DDC4F1ED711
+:10968000A861FB6B1A9B35B4AF0D886BE87F7786BA
+:1096900017950E676F6F68E3FBE3BDA80F03B84F24
+:1096A000AE8B7DF2183D3BC38FB4E0BC3B5ACFE894
+:1096B000505DB89D48DCBDDF5B5217F2ECEF6608E9
+:1096C000CFA051E6D9079EE0AAE71FA7F8ECFD6EF0
+:1096D0009046C6BF4BE06FC3752B294DCF4BA78C6F
+:1096E000CBEE0EC4DCF8FEF5E8C7EB97F8FBF47C94
+:1096F000789D2EBA15DA9FB59FEA583595E1719697
+:1097000098731E2C11F2A58ED55218C702ADD0F752
+:1097100010AF1F4E50DC4B0B270CA8C9EDD36A3895
+:109720001F1C74BA51D47B41B1F74B5331F4AB25B4
+:1097300023D58AF2A455B179240DAD673F3F27EABE
+:1097400077BFFF2FCFD13CA9D0689E48069B4779B1
+:10975000FA511473A5827151D94C29B86FF3173996
+:10976000996FBEAC10F3595B9830B41ADADAE3792A
+:10977000201E3C36287C1EBF21E0C14A513CAB581C
+:10978000FCFFBD48FCED7E18FEDD02FF1E7C16C20C
+:10979000BF4BE05306463BC5380DAE67012E359CE6
+:1097A000F918AF89FECB849E02F822F1CDFEFE921D
+:1097B000E04BB1E3F96A91E3792DC78FFB900F6C11
+:1097C0003C5B86E34746E0F19AC2D7192D9130629F
+:1097D00035B4D4E795AB1F0B7ABD6BCB95F5C5516E
+:1097E000C9D5C3A2FE48E3F8718E2F3F12E3786C0F
+:1097F00038BEFC50F0252DC3EC5730FE78A65877C4
+:1098000060918B2FC745BBE980CD971B5C7C3932BB
+:109810004ABEEC2D723CC773E33920E4EC17C3F168
+:10982000C501FFBC18FFAFC5F829AE7EBCF39A0E88
+:109830002B4CEBF26F9599B9FE185CBF6897E06E00
+:1098400054CEEDB0EA09EE157C2FB5F07590C1BD90
+:10985000EA84034874A0FDB616F74ACF03F896725F
+:1098600073B368FF77546FE160FB879DF53628F38B
+:109870006C3C06F07DFBBCBFD8706F3BE18E775E21
+:109880006FC31DA5F6128378BCE71CD78F3B9710DA
+:10989000DC907CA45871F6AABF3C49797D651049DB
+:1098A00063DCB14B49519C193721303EB92A10A7CE
+:1098B000149691E2D4158B793D5DD128CE1A80148F
+:1098C000DC89F1B97285F64D3EAE24753FDA11524E
+:1098D000D2A24D57D097B463FB630DCA0BB3F1D935
+:1098E00054F2D91E6A87E183EDDE5112DD8572756F
+:1098F000DB24D540B9DA35E9268AA76F6AE779858E
+:109900009B2E56298EB8F98508ADBF6B95F82711A7
+:10991000DE325503E3C5AB427F796E292BF7B7974B
+:10992000EAD205340EC2DBF241624D83234F91E14E
+:109930001D88539E1DC5E136B5F0FD1EF65389F511
+:1099400057CD3328CE68A01E63DFBB1B55B25F37EF
+:1099500055D5CCC5FE36376A646F6C5E58D34E71F0
+:10996000BCC610C531CBC28684F1F7E8B92A33C032
+:1099700059B9DC68477B33322B0418772AABE2FDF8
+:1099800045CE028A43F9219DA865CF688F0AD9B1D7
+:10999000D8DEA2ECE7D09E690CE832C6FD2D737FBD
+:1099A000FD384A85E33FF27F01E2E39F2803D2DDE1
+:1099B000E66F343D587FD8FCC668A648B86C717015
+:1099C000911E05B2338A804B17099729122ECBE1DD
+:1099D0000270E9B0797E10E7F9851AFBC3F31B1D0D
+:1099E000F986D5DC7E77DA2D7ECFF7D1E68B2EF7A0
+:1099F00047CA695E9E0BE7F27CD1E1EBDB79A223DB
+:109A00008D17C097C3531E197EADB0FB0A7DF78F2B
+:109A1000BB2986FAACBBE2DFC4F366FEAC14EF2BC5
+:109A200057C7CC303EC5F7CA9B5BCD3CFD7DC3CF4D
+:109A3000F5701D2486E54399C0FF10C31DF37EEA2F
+:109A400014061F290CAF96FB86CDBFD414AB99E644
+:109A5000ED421FCDDB002A039C37557C1EFB219570
+:109A6000A8253D63462B1DF3C7DFB487E6CF7F579C
+:109A7000CA2035127FE24847AF9C78E522008E72FB
+:109A8000F5A9CBC9237E91577C9AE5C4DF2317350E
+:109A90007FFCE922E13245C2658B83537BA4A2F4AB
+:109AA0008A9A2E122E53245C96C3AD9DADF2F5DC3E
+:109AB0003AD6817900FEF3345779ED7921F7F739F9
+:109AC0006157B96BA6BBBE3ACB5DBF6B96BBBE7A86
+:109AD0002EAF1F567DF3709FBFD879F2EA49CE931F
+:109AE0003A6D78F848E308F34AD38358BF4C3120E5
+:109AF0005B4EEB5546AC5B79F7C96B543EFFA7F85C
+:109B0000F9BEFD26450FA21FF98F3E4E45E5F8DA56
+:109B1000E31D095F5BFFBE260B7BAB403E38C4F8FC
+:109B2000B9083F84E268E718F3B5E6DF303AFA9FF8
+:109B3000E1F9F0DE765F54930DAAC32F66F619247F
+:109B40001D71988B2B149E87C3F880F6900A891696
+:109B50008C3BAFA9F2913DA284475837AA1C7A2BBF
+:109B60004FBE5E2E2E05269EB3A04F06C0DCD779D1
+:109B7000BFA13810DE11E82767BA1453E8CE0418E5
+:109B80000386C493C1789E0040938EFAAC3C78BAA9
+:109B9000DB5D42ED4AE626F8A06414ED2AFD944709
+:109BA00073DADB1D01DF20DC4DED322FA9FC83B120
+:109BB000B976FDB114BDC4FC59D9914787E7252872
+:109BC0000FC517CF52DEC38428F9656BCB6F70E5E4
+:109BD000897F45AD71C58754BDEB8B12EEE3565DB1
+:109BE0006FF60F23E71D4C5D517CA46AA9D95F571E
+:109BF000186E307F1FF340F3CC832E359941FBDD87
+:109C00009A1CE6FEBC92A27863B75436BDB7210712
+:109C1000A754314DCBF00AC74D0BFDBDEEB1BE3898
+:109C2000DAA90A6CD8279DC3EAC90BE3CEF8A5F7D9
+:109C3000A954296F3AC77387EAB6A7D68C20EF23B9
+:109C4000DA3D6A3C992F2EFAA0CAFD637F28FFF700
+:109C50005742CDDF522B86D2ED47485FF46FC740A5
+:109C60000FC6DBED3C5AA56ACF734887B5150B626A
+:109C7000C38D9739508707F9C258BC2F64EE5067DF
+:109C80000E8BC74E75661EFE858B8B7F03F3D374D8
+:109C9000062A8BF339681F494CDE4383F218874E3E
+:109CA000D457CCFFE8657C0BD5C7612B2BC7E66981
+:109CB0000985D94BB7346C018C5BFB99FD44FE8957
+:109CC000DCC4EDA73A6E0F99EC0F8E23DA34BC5D3D
+:109CD0002D7BCA0754B73DB4A66D2738F3DFBCE728
+:109CE0002DECE7D650F3F3F9E9519C3FBC99C90B31
+:109CF00033EE60539B46CF5BDB747ADED216A3E76C
+:109D0000FA3683F2F33BDBEAA8FC55AC3A1BCF45AD
+:109D1000A57AAA19FD7A625B9F5BCA5E6D46DA522C
+:109D20009C20330FEDE45E2C53BE1F7303B13C89BE
+:109D30007F7FAF2B3D0FE30DBD411B7EED3CD35527
+:109D4000BE73CD5C8417718648F77DF3D0DFDF3CAE
+:109D5000C9CE4333B54F38D6BD9A003FAF42BE2B74
+:109D6000D5EF5883FD0715BBFC3D6A3F570613F13D
+:109D7000096ABCFCD1C00EC2875400EBEFE381EF4F
+:109D80005379F3141EEF87C58B46A0238FEFAF5195
+:109D90000D1EEF5A5C46FB472A939B1AF66AF3188E
+:109DA000817791ED8092E4EB9D38DF5778DE8CB0BF
+:109DB000AE093C469E0F26C5D1ED736BCA2FF2AF9C
+:109DC000D3A7BBDFCDFED1D1456B4A9AD87CB4A5D1
+:109DD0002F8BACFEB19A9C13C07DA4F9FB6859513E
+:109DE00063596E3714D9FFB8809D079924BFC9A65F
+:109DF000B7A273FB6385879FFE72BE6F1714E7538C
+:109E00008AC5FB73AAE847B4030F4DAF1CCECE2A18
+:109E10005FE843636C506F94CD0FB9CA7A539908C9
+:109E2000DAF072B46182AB1CAEAF7195FDFA875D5A
+:109E3000F54F965FADC25EB4E13FE61957B3779C2C
+:109E400045B6FB6269E25F0233314E05752946D79C
+:109E50003B3EF300D13F34385F17749A4D942F2E58
+:109E6000FC8A0B7959B7BF9FD76956B1B2617F9F02
+:109E7000C9BF9BF6F7E9BC6CD9DF3FC2E1D15F6691
+:109E8000E58EEEA99D167E870E8ADF42550A1639A9
+:109E9000F44B787C7317E2377E492666B1F7BDEF45
+:109EA000CB5C6E211D73C2DDA5713FE02753BE164A
+:109EB000C3B8E5BAA90FC480F49E94775FF0D900C7
+:109EC000CF1BAB0C256E4739667A6D00F3050F3D4D
+:109ED000201B7C5D525EC275D167F17C7D15E2FB73
+:109EE0004CB48FEA78DC3A24BE131FAB73F0837C4A
+:109EF000F5943FA2F1F5FDF79864C9C6F3ED52F36E
+:109F00003EEA1732520B9BF755160CE0F92410F677
+:109F1000DF445E15CA13198AF74D62F4C47DF6C991
+:109F20008B07DAFD8CD6C612DD8753A46669DC0781
+:109F3000A4076C7B72ACF4017B7E17F9857AF9CBB0
+:109F400029C0757CEDD4075A912E81EC97C06074BE
+:109F5000FBD749293018BDDF0E70BC024BD2407AC6
+:109F6000BB364D74F6D26BDD20DD332EBAFF4CD4F8
+:109F70008F2579BD413885C19D3D14AE37989EAB84
+:109F8000A21D3785D3D1DBCFD100DF1FF1E261B74E
+:109F9000EB85DF1410FBDB5A86F6397E32F5A61806
+:109FA000C6B7BBA730FED717E6FFA600CFBB324E21
+:109FB0007C99F46FEFA4DB685F735DED16B22B8FB5
+:109FC000327B02F3367BABF3D7EF6EE3793217C205
+:109FD000DD2D358C3FDD07648AD77AE1BE1370DB57
+:109FE000CD5A95DB2F64F2F74A60E6C8F22747B6F0
+:109FF000F279394AB953698AE2BC1BDF89FCF58BD7
+:10A000003273E63A851D40EB6CE5D23438F31E8F8F
+:10A01000097E3D2DF474B08ACB47AFDF929CFC8B58
+:10A02000B1F7731DF50AF1AD903CFC58CC877795DC
+:10A03000782B19014A4ACFE7572BB17FFEF97CC72D
+:10A0400079B04E25A3E9887FDD6D92D3BEFD869958
+:10A050008C6A0E7F3614BBE4E7F3D10F52E279FD30
+:10A06000F5FF659A65DA4CB4B360462D9E5B50AC43
+:10A0700000C2AD57B22DE45FD4FA286EBEAEEA86B8
+:10A08000BDD538EE7A5F1CC1D6543DD582F6C5BA2F
+:10A09000DA4774A4DB2BFAA22A6C27105367D48EFC
+:10A0A000A5FCEF048E3B5CCFDA75F0DBEE3723E4E2
+:10A0B000FC5EDDAC417C993E3853FB1BE883772185
+:10A0C0001EE3C616A3739E7570289D79BE4077D592
+:10A0D000103ACF71D23980749E81EDC6F3C6311823
+:10A0E0009D2F74D119189DCFCED1B9B78AD3B9BBE2
+:10A0F0006E4B4F8D93CE754FEDAD36B07F4EE7076B
+:10A10000357E7E37847476E0E9A57358B2D79FBA5E
+:10A110004EB43FBD72CFE87E29E263BFF769FBC84A
+:10A12000EE0C8F4F7C82F8C0FC6594833BA482EBDD
+:10A13000D227116EA475697D80EF57DEA57139674E
+:10A14000ED5F89FD42B968DF5E6FC57A7899B66BBD
+:10A150001EAE870CEE6AC2434F913F3C0867C1B008
+:10A16000EB28ABB79CDA0F7BDA376154EB316BE746
+:10A17000266A47F3F46FC029ADF3ACDD761A97E297
+:10A1800069F734DB13AC9F8D9AF0375D74F82BDBE5
+:10A1900031B1A4471E94B44BEFD9F250B9D40D5746
+:10A1A000785D4BF3756DA85D4372FB6CF7DEDDE8FF
+:10A1B0009FBDA29BFF07F935DA7960DB8195A1E4A9
+:10A1C000A3482F6607521EA9F58D92CC1A5657F94F
+:10A1D000201DE5FBF0EEF568BC6D0FD5F27520385B
+:10A1E000CA75E98026F204C7301D55CA9EFE446B2D
+:10A1F000BE78C33302CE6B37FF56CC2705121467E7
+:10A20000EB8C5DBEB39FF1CE6C49433E3DBF3494B1
+:10A210007C16E9A3EA29939657112729D46E79C2AF
+:10A22000DAB5B781F4EE803C465418C74D6B8CCB41
+:10A230004519DD0E6914528B639CAD62B13517F57B
+:10A2400058159317841FD7BA4F4AE6DB2717F41E19
+:10A250008B48E4F15FC67D6A5692F2E216368CE0D6
+:10A26000DFF0FC3C663FFC0EC775484D5F32C541D0
+:10A27000779B4F5F9312975E84FAF47CCEA7D251FE
+:10A28000F2E9CFC2AE8685E534F80B4F5C48E77F34
+:10A2900082115F02E3F1417F5A2F73C8D1381F2426
+:10A2A000FB46817F130CECFE00FDBFB08FFCDEDEB1
+:10A2B000F055DFC6FB792C5D8D4F3172FDF6B2F59E
+:10A2C000BECCB1FE78E35683FEB4802FDC2F879B93
+:10A2D000629D4BFBFEB9FB85DC79084CB0EA307F10
+:10A2E0006895CCE3E877947C85F211565B013D508C
+:10A2F0004EEB18D97FEB445E5BB7C86B5B2BF2DA91
+:10A30000FCD6AAED08BF192081F1C9F6F353B4EFCA
+:10A310001F5534BD834E0CA5CEC575225A6ECFCFC6
+:10A32000C7E7A37D3558B6EEEE6C66E38DC6ECF25A
+:10A33000ED347F3BDBB9BEF94CF057F351DF18E247
+:10A340003CD6E6C645A5304C5C325CEFCEA30BD5BF
+:10A35000865C65ADAACC5556CB270CBB7FB10FE30D
+:10A360004515389E7E88239E05F286A70665829352
+:10A37000E5690359CC3B98A3C6B71878CEDA9DCFD0
+:10A38000D913E4F6E08F30303413DD2C21178D7CA7
+:10A390007FB564764D1FEE07C1182E17982FE894ED
+:10A3A000874272F1F7A68FAFE4700CF32F6EE98845
+:10A3B00002E6BBDC32FB97F1AC817AB53F86791AB5
+:10A3C0006B9826E960DF37CEFEA5912FAEDCAF2576
+:10A3D0009705917EE104D95F9186243DFFDEE31A63
+:10A3E000899F7705F93A3755F053417E36E4F8B93D
+:10A3F000AE91F1B32137CFD72969AD187E7E0CFB22
+:10A400009F897AE8F7E4B7AD6FF4B5A01E32A08F4C
+:10A41000F27037D6FB7CD8FEDF8B2E365EE1D94C4E
+:10A420003F129FB2095C1736C6151FEA917F383973
+:10A43000FC4B3FBD2F420E7F984F0E97D9F250B282
+:10A44000AF355FFEDDD4A0E4E2D706E417A74B0BDF
+:10A45000A78BEFEF4297C1F5424BAE40B959165367
+:10A46000C9EF56CA7ABA68DF88AD7BB86F749D6C45
+:10A470001AB8EF04FFE1E7F735E1BAED585FDE0FF8
+:10A4800006793BF2860594FFC186867E192B7F688C
+:10A49000D87DD18C7FC0798F89373FE350D0BDEF15
+:10A4A000F44ED5A252E457A1F6DE6CDBABE3395B88
+:10A4B0003B4FC3FBFD3A1952F9CE2FFAD120263A71
+:10A4C000F4A944879BD95A3B0DE9F1A1F9783EB331
+:10A4D000BBAA631CD931E27CC375DB9ED115079EF4
+:10A4E000D7296CF99B3E743C367DAFC365B2CC5125
+:10A4F0003FB3D755DF5B6FB03D519FD96DC1107B26
+:10A500009A4A6A2FEE3BDBE738D46D73B3B46C160E
+:10A51000C09BF1F194F02EF63CC73B5BD774A1BF12
+:10A520008DF6D7794C4E5EFBAE1CEF605F97DD7DFC
+:10A53000D67C3CE77A08B8BCD8FC7963EB9A71F911
+:10A54000E4A2107F2E0EFD75E46B7AC8235F7D9721
+:10A550009566E1F4CB57A2907C09FA1CEEE3F480F7
+:10A560003BC7E6E553A1F10CF2C9AE27E4CC5BBFD3
+:10A57000503D26578B433351AEB2D139C5C895C033
+:10A58000D7E6DFA9E23B925C69AB6503CF75552B3B
+:10A5900009D29B3DE51D96B8F791F23EE5F4347E75
+:10A5A000BFCC607E3B64D19ED0CA4DB2A343E2FED5
+:10A5B0009E40AD5B6F2A31F7F989586B226BB78BE0
+:10A5C000F14B6DB54AFD0EEE2387211B8C6299EF8E
+:10A5D00097A2FA43BF22007751DC93D5CB1BF7B487
+:10A5E0009F8AC85BC39C5EBAB70D3E3D429E8BBB43
+:10A5F0009FD8E2E1F36CBCF010568C430EBA17AE54
+:10A60000A7C021879F739BB877D4A6BFB9ED4ACA6C
+:10A610002F0F822F4EFE41EC260BFDBE2E319F7B6D
+:10A62000F0399BCEF3EAE4AF197CBFC592AEA638F1
+:10A63000837DFECCEECF3E7766C38DC4FF55389F39
+:10A64000F2CCEF3D21EE8F1DFB4AEAF7E887587FF9
+:10A650000203EFC97CACED38ED575F907D43C6F83F
+:10A66000FE33A1710477C140BF3CCF312F2F10E7DB
+:10A670003900FAE47CE7BDFC56E0299487270F7384
+:10A680007FECC9C3EF901DFEE41F7C1994BB278F9C
+:10A690000F9FFFF098F08B6CB8C7FEC0EDB3C79466
+:10A6A000BE927CF65DAEFF0CF7070FBBE515943E3E
+:10A6B00019E5E5D897F7C9181F78AC4D935E66FA8F
+:10A6C000E77C31CE0B0EF7CBE8378D34AEEF79F85F
+:10A6D0006B8F737B13B747B737BD13C2F8FFF6C74D
+:10A6E000F9788F8A73B285F07DAA8DE7796C7F3C0B
+:10A6F0003F3D9ACFE7FE71B3DF28CF6BD77ACE5BB1
+:10A70000CDD364F739AFD38CDFEE266E77ED56E20A
+:10A71000E193C1C77E5FD2149770BD2B85CCDE0F4D
+:10A72000551339F73BE322A507BFDE7E35E6B75E5A
+:10A730001936A51896EF9226B3B23E41067F0CF368
+:10A7400037DEC9BEC0F05FDB5A42F91B9D0DE5ED57
+:10A75000786E73ECF2DA5DB88FDC8B1115CA5BB8DA
+:10A760006B2DE62174E27F5939B03E7D119D930037
+:10A77000AE0F98456B28E3C4FE469E790EB9FC0ED9
+:10A78000E98340AE5E217AA99E7C90002C1A5E4F30
+:10A790002DE57ACD627F3EA07352EEFCDC312DAA0E
+:10A7A0008B7EA59EF6CF2EE1F23862FEF829F65395
+:10A7B000065B3483D15FADF3E9198487F818CC0FB9
+:10A7C0002C59C80C203C1F10D377F98C91E9BE1688
+:10A7D000A085C7B7FBC039BF9A4BB87D3FE1DADB34
+:10A7E00025F4238EC699144CC3F2F178BE79714BCF
+:10A7F0009BFB3E915B1A1E21BDD809991E5C4FAC94
+:10A80000061FAD67BD75FB7567FD2B4B24911F6659
+:10A81000F31F0C6516DDEB484138A5CE6706A3276C
+:10A82000CF7FC543D791F81F59EAA6FB68F9B21C40
+:10A83000F93F7364FE9F6A3F36DF86CE8F76C1B7DD
+:10A840001B35A0FD9DE1F5FA50BE6DA175AEA42E9D
+:10A850007F5EEE0D2576DCD672E95D0D521077E451
+:10A860007FC9E367B5DE0785FB95CBDDE31B8C3342
+:10A870001A9689FB7FE35919CF7733998E6701CFF9
+:10A88000F198807610337FC85F933DFEDA6D428E7B
+:10A89000343840F5D92CB0745A37785E9A9D877257
+:10A8A000911C8E637CA2470FD3BD48A81F799E0ED2
+:10A8B000CFE72FE528313B600026B37AA14A192C57
+:10A8C0008CEB35097C25267798C77FF08D83E88F40
+:10A8D000841BDCF968CAC192177DE7A09DE6390F99
+:10A8E0007270F972F25F3C7C1E6D7EFFC325229F61
+:10A8F000AD04C2641789FA85F2F46CBBDEA6AF71B1
+:10A90000224279395D0725A247C5E4C47DE87FC1AD
+:10A910002F65E0F99760E23DC6AB7E3693BE0FDD52
+:10A92000374854235FDE3858A27754179317994855
+:10A93000B633F8EA8301F29FAA416FD6B0BF7E8991
+:10A94000F8288DD3282F6BD54FFDF70586C9CBB2DC
+:10A95000F71707CB4A9AF689D7D54ED79CFB979520
+:10A96000A1E4CF4B1CFB9741B19F3874DFFD769279
+:10A97000F3D1EE6F945F76379DEB2F1F0F62FFFDD3
+:10A98000D30BD04E595701AEBCBC7595BCFCEAFA4E
+:10A99000290B701F679DC8BBD337BC73513BE9DBE4
+:10A9A00004C5F95633C1437AC25EBFB84FD2187F8F
+:10A9B000E9307AC34B870DCA3ECA8BFF6678FFC564
+:10A9C00067219FE23E8ABB7DF346BEAF6AC3BDA24C
+:10A9D00037FFA184E6ABDE89FBD0139320F234DD90
+:10A9E000FB1F1370F560E39CC418E467F43863310F
+:10A9F00074A0F8542FE9ABC4F5786DF92363F8F926
+:10AA0000FEF9FA21B2CF65DA872E84AFD71E2F3434
+:10AA10005E7B5FDD5BFFF608BF4FD5BBFFE58DFBBF
+:10AA2000DC87F465703DB8EFF411F6F467F2C6AD5B
+:10AA30005E2DE1F1E84E6341E2F3382EC59CFD2A1C
+:10AA4000A347A63C4A7EA2FFB2FA2BF08A3E1BDE49
+:10AA5000CE5B5384DFE62F4FD1BAA668A656C7C691
+:10AA6000A11D90716681966E277D65DFFF80645D14
+:10AA70007C361F2F8E2B00DCFEC5F3091F38C60D58
+:10AA80003147BC0BF58AF0D34E03BFA787670EE5AD
+:10AA9000EFDC1E9E771E5BC6CF334D54F2F37BFC7A
+:10AAA00012DDC7F7B94E2F9F0BD52FB4BF79FB2D01
+:10AAB000EA02B453A6E8ABF64E62787759A549DCB2
+:10AAC0007739E64FD13D39BDFFEA832D80E31F7E04
+:10AAD0009DEBF4AC738A9EA0FBF4AA52FA749CE638
+:10AAE00085EA7D2DC5FD1CEFFBCF87F97AB329558B
+:10AAF000B609F319CCA753BBFCE857C6B8DF6CFB0B
+:10AB0000D94B43C9CF871DFA68CC7C2E3F5392574F
+:10AB1000D0FC3F5631FC3D0BEB3D789740FEFB5D92
+:10AB20006F8B707CA618AB78BB93868FBBDAF4383A
+:10AB3000DE238BDF8B00E487F8990027187DEF3543
+:10AB4000B87C2806FC14E56CB2E503C3C0EF03ED46
+:10AB5000A877BFE68365F9F0688BF0F935D964A66C
+:10AB6000A7A887F6693A62D0FC1CBF84D3695D351B
+:10AB7000C4C3ECD519D81EEB7FCF1495E492F9BE6F
+:10AB8000742F526035D0BA1DA8838C81FB0ABBBEDE
+:10AB900094457EA9F5100FB27ABBA774D17D2BDD49
+:10ABA0000698786F92FF6636B1F07BAD2F6362BE78
+:10ABB0008975157D5FABF37BFCD6D63603D9B131F1
+:10ABC0005ED60C7EDE65DD5485F0B0EF1F27BB93AB
+:10ABD000AD0FFEFA812C5E5967C0326AC73F9BF306
+:10ABE000B5EACE263A8FB66ECC0374DFBFB51CF83B
+:10ABF0007EA6BDEFAC30B962EF3B97E979E327EF72
+:10AC00008592DF72CA83A2EF2379289407D71DE6C5
+:10AC1000F4BC4DE8B763FE2CDD6FD8BBD647F7B662
+:10AC200078E13F2BE87F77E7A28FD3F5D4629DB11F
+:10AC3000BF1F2A315CF765541D57693C0BE49B41EB
+:10AC40006778DFC3EC24BAE7052F063D931AB8A452
+:10AC5000D2716EE59E781FD945AA6D17D5737BC654
+:10AC60003EDFC8E890FD26FBAE639E3FF303C7B707
+:10AC7000E6B78FBC7E5921FBA8A7C4FC19D2AB4B09
+:10AC8000E4ED7F7DE9227E6F6581BCFD3BC5F8EF79
+:10AC900094ACEA2ED48F93F83D335EB843C25E6421
+:10ACA000F620C9CD3A8BDFC7B58EB93E8FB272CFD1
+:10ACB0008DFC3EBF1ECBC7CF7FD602C54962375D34
+:10ACC000A5E59BAFB61DBD5EDCAF5568DE95A899C6
+:10ACD00064BE75E99F227C5F6D6CA3417E1B51723F
+:10ACE0001C2E279CEEF4C4785E1D5FB7CF007D2E2E
+:10ACF000E6316E5E58534DF77CB275036DE27BAA68
+:10AD000033D9F9289712F4DD8F95948CB59495CFAB
+:10AD1000888F337A1DE7BAF5AA07B278EEFDF627D9
+:10AD200003106864E5F99EDF67E3E40F2AC83AF789
+:10AD3000EF532934BE629FB7327ABDE488370324CB
+:10AD40005B703E85D87A8AF326D894C9D2EFD3B007
+:10AD50008280E3E8D15819F9D21902BC6F36541F2A
+:10AD60000F63DC36D43FB7859EF5895E949FE8EC8F
+:10AD7000AD7ABE73312D916A97DC87EBDCF99A418D
+:10AD800071EE2858A552BE5A30A9E6BDDFF85089A9
+:10AD9000C2ED68D625CEAB1E6B783D7BAA72F1BAA8
+:10ADA0005867F49C7F4C72C14325EC59B5E00DD92E
+:10ADB00071DF66C4EB5F78F9E8299F2A1F7B3D7C31
+:10ADC0000C36713E02E323BF07C4EAA17317860F56
+:10ADD0009CE72EC6476A5CFC508E2B748EF6CEB96B
+:10ADE000F9EFE31C1FE179DD3D25894B2294570BD8
+:10ADF00012E5F70ABD7091BC81EE3162D2C1EF8FCE
+:10AE000067FDDD9F473F8E8F70FF756BC8BC3C525E
+:10AE100051785C8F4985F0E0F50F093FBF783DCB55
+:10AE2000C737C57C2D4871CF2F0DBFEEDBEBF3315B
+:10AE300036B67D686F2B29D23B4ABF019D389F6390
+:10AE4000BE0CAEABDDB145A417EEB1988C4824978B
+:10AE50005086FEADD01350DF1FC4F88B5FCCAB7BA8
+:10AE600056FBE8BED8508542F7D7066E4EB2B510F5
+:10AE7000CF350E6431965F75E702C293AD53372329
+:10AE80009DA3B1BE76D447FEF20CED0BDFADE821F9
+:10AE90005CFF8FA191C8ECB3EF86B777519EBF9945
+:10AEA000C8E29597E81639EFEFCF58EEFED800DAF2
+:10AEB00051EF7436E9646F9F71733F38E72BEB777E
+:10AEC0003DF265625D66AE64E4D647AF3D51C88E23
+:10AED00060EBA8F0CBE675A15F46262C2B3F147ED5
+:10AEE000A40BFDB07B75F3AB11F283F2FB0F4C2E7C
+:10AEF000BE7E3272F1AC98A7B65C0CC647441CF516
+:10AF0000AA46103FC615BF66785FB3D70F38FE0B51
+:10AF10004FDCBBE79B8C1EB23817C734F99E27D88D
+:10AF2000F7A5A696C0F23507CF5631CEFACB093237
+:10AF30009E0146398BA29CBD053E8AFFBC05FBA342
+:10AF4000331CF83C21E60973805EEA77C4173F9F03
+:10AF5000E6655BDF7DE14E77F96A58340EE387578B
+:10AF6000DFEE878C84BF57CAED177F27C2F3C5BFBA
+:10AF700000A92EA4F35A71EFE9F21F9CADA27D74D3
+:10AF8000CD0CBD1AF72F6D3C7E22D6B337991C1B12
+:10AF90000EFBF5DA7046C57CA79777CCB87C0E60BF
+:10AFA0003B99AE09B85E8D81BCEBF4E77ADC788E14
+:10AFB000340E2FDEF679A1427828DBA4BC71AE9F57
+:10AFC0000B7BDAE6E3A9DEBFFE7684EB03FBF7D367
+:10AFD000D97962A7DAEE7BC2AEF6B6BB5CC30BA42E
+:10AFE00001562AE916A926B76F15F4A7CC8968DFA0
+:10AFF000ED9C9BC5DC73075C4F91702DBE61E046F4
+:10B000001ACFAAD03D518C07F5337F3FDF3D3A95EB
+:10B01000A164245A31F43E1D10BF0FE8D06FEC7BC1
+:10B02000EA0716601C2F00CC6FA7A7427240F11DE3
+:10B0300009EDD17416FD80A0A1B8E4A304F74398EC
+:10B040005DBB52D88F2575EEEFDE78CF19512E07F4
+:10B050004DD04FF67D540B6771BD854677FED21DEE
+:10B06000259F253B72C53E3F1D015801C6AD4D0DC4
+:10B07000340F29CE75E3BA33699FF7C60A83EEF918
+:10B0800055206E525D8FDCAD3C2E41C6E1FFAF54C2
+:10B0900006549C6F2BD9FAE17C7F434C365EC9F392
+:10B0A000FB99ECA79F69F5701DD2C1C7CFC5EAAC6B
+:10B0B000EC18E73B69A985EFAB19A58B87F1CB6F3E
+:10B0C00088A9D4CF55EBA694F2B88F5B6F1E11EB15
+:10B0D000D47F3EF41F2AAEBF6F3DF8E2254887EBD0
+:10B0E0001E934163FD1E792802595ABF322AAE5F72
+:10B0F000D7EE90F3DA5598A9447925DB797CF2DA1A
+:10B1000047029985ACFEB58FBE7C0E30FC8E740C68
+:10B11000EC9988F3E0411E3704ABFF9CCBD8FB6B66
+:10B1200015F8DFF9ECA62BA2DC0F38FCC312BA7FAE
+:10B1300054DAB6EBB3D46EDF15FE80637FED92A8D0
+:10B14000DF86E371CE6F4B992979F6DFECB8FAE12F
+:10B150006F4B1CBF9D7EBA8FF5DA6DF7A94986C784
+:10B16000CA6D6F933E99B7FD3B51A4C3CA9DEE7D56
+:10B17000B6EBB6BFDF857924D7C930B010E5593EAC
+:10B1800041E5A3A6362093DEE7E7A557104B18DC70
+:10B19000F75E5BF06BF6FDCD980C41A67ADFDCF72D
+:10B1A000AAFA189693E1147AB02B77BAF5DECA6D35
+:10B1B0002F535E83EE8381AA39B8BFEF966B2F3C85
+:10B1C0009B3F2ADA212BFBD6BD2D33BDB172C75B65
+:10B1D000CFA3FE58E9D19F6FE27F2A87C6A1DBA2E9
+:10B1E0009E7B66B61597FF70DD778EDE63B17E0FAE
+:10B1F0003FF2BB7B304FFEFABFBC7BCFBFA3BDF09D
+:10B20000645047FDBFF2C15F44C1218F5F8F727BE5
+:10B21000EBC824B02A19DC91FF17C8E0FD57479E00
+:10B22000786D329E733BF2DD3F8E3318FC8D4F5CA0
+:10B2300044F7EBDFF8FD79E387B3C7515E330127AD
+:10B240005E197E5E6CA7C48D97C7C5D3C38FC3DF5D
+:10B250003DA6A25DFB9E0403B8CEADE87B5F457FB3
+:10B26000648F0903489FDD3B5EDEF36FACFC16E3A1
+:10B270004F200F7FD8F827FA68FD666A923D57EC99
+:10B28000787901E2BB1206683D1DC2CF038C9F0D89
+:10B29000397E7ABF1F85132AC663573EC4F8770EDE
+:10B2A000F291F1EF9CA1FC7B0BFF337B28FF7E101A
+:10B2B00075E7091D85EBEFADC48DDA1D63F3E6314B
+:10B2C000E4F61186BFCFC4D60723D17799C4F1EA3B
+:10B2D0008C9AFF19C579F548C9207F17227FBF7363
+:10B2E00074323A39AFFB073E8B74187822A0E3EF33
+:10B2F0008FB8F6895FD13C3BF2FD675583F66D2030
+:10B300002ACD626518FCD90FACBC82C7B661F9D6EC
+:10B310003F2F789ED55F8EBF204327BE51790F9B6C
+:10B3200077C487CCA52D06AE9B990A1AF78A0C9F85
+:10B330000F2B32BB16E3BD125EBA4BA5F6BD9E398C
+:10B340007EE27D4F2B76BCB800E5AE103FEDF1EB11
+:10B3500038FE73D9F7ADEEF9EA855FC1E627AD5344
+:10B360005EFE6676FD373E8FDC1750F07CC51171AE
+:10B37000DEDBCBF71CFDC5F9F751EE33FDD93BBF42
+:10B38000ED7D2641A7C2F2C1E7F948E31B2DFDDEA2
+:10B39000881ADCEFF6D0F1F089FCFA7F7C295FB7E0
+:10B3A0005740BA054D67AFBDA240D29A589DC3F72A
+:10B3B00030DA170CDFC30FCA14F7E9EADB4D7ADC89
+:10B3C000AB2F561488BFD6D9FDEDDC750EEAB5C398
+:10B3D0004FFD90E473C5432FAAE877ECD9F63DB54D
+:10B3E000BF3E371F707DC838E87DF8E15DE7707DAE
+:10B3F000903FAE3553B4BFF27177FB2B1F7ADBD58C
+:10B40000FE75561FD90B23F5F3A6625E81E37D73AB
+:10B410009F9FEE137CB34FCE1BE79E50EA77D9C1B6
+:10B420005DCF2EF8359E676DD81FA27B1477749878
+:10B43000E36F41FB6DBF5FEC1F9ABF43BB74C7B3A3
+:10B440002103EDB41DFB2FA77C1EBBBD1F78E8793F
+:10B45000EE016B5E84B5776E7FA201F345BC7AA3E3
+:10B46000F120F3F71C7270E3B32DE351EFA37F6C6F
+:10B47000A0E3ADC4E91C951C5D4079E2B2EED38334
+:10B4800079D76FDE9E3F9CA0FD1C3F134CE7BDECBF
+:10B49000179EF8BFE4BF77C5F3C7FBEF2AB5F7BD2A
+:10B4A000F9EF77B2DF6F90B8DC58CFF07D8E42F3C2
+:10B4B0006B5B5B2C5ECB4879575B631CF77396978D
+:10B4C000F2F8C7D4572C1F9E0D99DD6F4CC7F14F72
+:10B4D000843EC0F3FA3BDA74821FE4FF4266519760
+:10B4E000E37DF3104738EC17FDB5D1F67B73A17EF1
+:10B4F000EBFB882EC5F4AB9D44BFEB4BF979E953C8
+:10B50000E9377C127406DC1D2A62BCDE3C296FFF21
+:10B51000EA349EF7E5ED6F4929B733EDFD039A7ADA
+:10B52000C3C4D5FCA29DCF941A2E7902254BF74FA8
+:10B53000E7F22A32527703EECB0D9E174E688EF358
+:10B54000C2EC3B9D175E63F23C56568FE6418F88F6
+:10B550004FE03EE5550E7C9F15FA2350958AA1FDDC
+:10B56000D58DFB0D79F4D8F342CEBB23CD943FB2F9
+:10B570004B9F5EDA3FCCBAA1ACBE6B86F35CB1A246
+:10B580006725D7FEB0F932DD8355A8BE77DFD0C678
+:10B59000BF7BD797A006F35CCB13D09107CF3E219A
+:10B5A000C708578D70B124B43BE0D4181FA75DEED7
+:10B5B0007E9FDF73FBFCAD07BB515F16A2D30EC1AC
+:10B5C000CF6731116426B96F1AE663F6447CA4276D
+:10B5D0007B82F9EFA3FF45CE2EA0FA2A9E5FA478C6
+:10B5E000EB3EF21B8D132F9878BFD1ADF52AED0BF2
+:10B5F000459AF653F9A8E923EBBF107DECFB08064A
+:10B60000CB05E24F8D3AE7EF6EF311CA6FBDE16CE7
+:10B61000D5182E9F22B47A5A1CCFB36BABE7C43136
+:10B620003F2254C77F9FC2C6F3793C6D6301F998EE
+:10B63000A573F958FF453B2E992539D938CD17C444
+:10B64000E7FF075094EC5E00800000001F8B0800AD
+:10B6500000000000000BED7D0B5C14D7B9F899DDFC
+:10B66000D9D92730C002CBF21A10140D268B226ACA
+:10B6700035664134F8885915A326185763521201CC
+:10B6800037D636B4B5611010C447486349DADA7664
+:10B69000A5D892366D31A58D491F77D5E8B58FDBDA
+:10B6A000A2318937571B34DE5C494D2F7DA4F5DE6E
+:10B6B0006BEBFF7CDF996167965D3069DA5FEFFFC6
+:10B6C00077C92F999C39E77CE73BDFF9DEE7CCD9D6
+:10B6D000A3DE6909830E426EC0DF1DA39FE6862F9D
+:10B6E0004EAF981E2EB7E5C473FE224276E63C4E5E
+:10B6F00006E9D37CBD91F8687F334FBC7DF499E8AF
+:10B700002547139CB4EC9D986BCEA54F0749379401
+:10B71000D07E6513B91DB9A3E11FCDFA84EB12EDFC
+:10B7200097E625E9F06C2B13D20D1A7C3A3F1320D3
+:10B730003E3A4E6B99B016F034873E49A4384DBD61
+:10B74000682064067D5FDDE9F5D276F42FDD47EBF6
+:10B75000094FD25768DB71644D5FD1E8F1F78B1C5C
+:10B76000212984EC56EAF7CD7EFB990728FEA257E3
+:10B770002A365230FB8E0E91BCA9B41C1AF27230DC
+:10B780002F27996625A3E140BB5CDA2EDEE5271B57
+:10B7900000CFCC41E2A7E3C7170E1298BF4D22920B
+:10B7A000414238887FC2AC6122D3760973075DF2CB
+:10B7B000540D9C3F1BA3E27923C18078DA1A4A3CDE
+:10B7C000F9C984581AE679F2E9BAC4F10344A470BD
+:10B7D000E22446FFC87E6F2530FAA874E92C9B98B6
+:10B7E000E08F065F5DDFC653A9BC49532EEB5C03B7
+:10B7F000F43739FD32CC3F7E16A38B5A1F2F0D1222
+:10B800002F1D379EB0799212E23D441F712532817F
+:10B8100071E8905EED7C362AF4DE28B2F9C09F37DD
+:10B8200015DB11425FC579170E196F85324F2E1542
+:10B83000B2FA1BB90417F49245291B479763CD67E9
+:10B84000BCE7AE46422E69E66BC9A4F357E1D27F4E
+:10B850003B4D241DE8FB41E926B806911FD4F701B2
+:10B8600065FE26E720D26714FD8A18FDEC458C7E24
+:10B87000F608FAED52FAEFFA07A3DF089D38C31A6B
+:10B88000E0C3483AAAEDE78DE02DE393F623E423E5
+:10B89000505E5609F2DB6965E5FDE25D9572119334
+:10B8A000AB71E485103721A59D37DAA0BD5B14117B
+:10B8B000AE7913D5070E4DD9AFEA0736AE23D7536D
+:10B8C00049283F935C03394449DA3E5776C17A757B
+:10B8D000A0A484E1BF2A4EC0F66D9260E06EA3CFB3
+:10B8E000530BD20885DB6CE9B4C07CDB4D9D08A707
+:10B8F00039CB207647D16FC794F91A1BECD37BA6BE
+:10B90000C7A6A35120FE6872FFA6D2BFF9E8E74F91
+:10B9100019297FF092205929BE20F46FA9EB9B478B
+:10B92000FB93BE81DC5C18271EC7712878390A0C8E
+:10B93000A429777C3CBFA5F015DF601D134F1EF0D6
+:10B940008CA267543C5B004F676C3CED59E5C8A77F
+:10B950007C8303C7F99128A17E729802968D747E2C
+:10B960008EA604A9893E77F181F66A780E98884CF4
+:10B970009B9888F75439C59B9F3A8D100AA7F5E22A
+:10B980004CCB04E0FD864EE2D3E8F94D36FF05913D
+:10B99000C2E3453FF1533C7947C00B68F42A7CA0D1
+:10B9A000AE1B294C2264361DCFCF4F077D6AF70BA3
+:10B9B000F854E1A87C623779895804700CDE207D48
+:10B9C0005A00D8EC70BB8F2432BA35CF0DF908D8A5
+:10B9D000B9629E809D6B33794F6DA0E50E3A9F6EE4
+:10B9E000FA6C51F846EDE74E4C647CA88C6F2355F9
+:10B9F0000921806D7CCEE51FC31EDB806EB47DC344
+:10BA0000F9DCEFBCACD295FEFB3F629CF3ED5B90A2
+:10BA100077D3419EDF2345AB0D86D870FED4287DB9
+:10BA2000E7658DBE6A20CC7E1022A52D9F1ABBDF54
+:10BA3000EE46323DBF205CDEC3072C409F36C7D6A2
+:10BA400053B9749EB2C7E02990004C898E4E914F35
+:10BA5000429A70DD4DC403CC4B9A33CB4F954BB01B
+:10BA6000BE2B5C8F43B5D1C1535B4B4C1349D008FF
+:10BA700074919C3AB9DC64637C13B9CED6113A1E3A
+:10BA800018938E56454E22E9989FF8BF938E2265F3
+:10BA900027E4D7B8150921E8779CFA49747C92A964
+:10BAA000973FB59FCAEF91F3AFF85F3EFF483E194D
+:10BAB000DD5E56ED267F9436CDF093600787659F57
+:10BAC0002515BB5218543E2DA126304D59D57DE980
+:10BAD0002708D8E716F16D0BAA2ECF8DE4B1E0F35D
+:10BAE000E46D959EC6F0785AFA18C0EE9C32050FA8
+:10BAF00071613AC589F7BB8E920F4EA7B6CCE7C5E8
+:10BB00000D1AFB71592CDF9E48E9B213FCDA28723A
+:10BB1000B03EB15C4EA4780986E8FA7C3FE835F483
+:10BB20001B457E011DE78E613D9D6E57E8342FED6C
+:10BB3000ED4FC334A996E40955C8E53E4F05D0AD95
+:10BB4000628D0FD8820819D76FF1233F54884017B0
+:10BB50004E9E64B861BF79FAC5A2978323BE687808
+:10BB60007F455CF1259897A388D24DE37F50411023
+:10BB7000DFB66BD6C5E11C87AFD8BA1DBF90669003
+:10BB800069D336972108F18C8904DA81EEE4AC910F
+:10BB9000809F961A4AC77AB32B2F08F62E35642554
+:10BBA0005E8C13C4A095B6EF5A7B8F07F5D3B539D9
+:10BBB0002444F906751965323ED31B027F9A17A5F6
+:10BBC00032A304E33C6681F8A6CDB52281307F9B89
+:10BBD00044D35F7589FE17615DF96BF3109EC1E276
+:10BBE000453FF166E7F3F4CA78027E80F53C1734EE
+:10BBF000535C9E5C39AF7D90CEC742E23ACDF4D91A
+:10BC0000CCCB21B063F279AB04F4DE5A20DF69A01B
+:10BC1000CFB25F590B79FABE9DB379800EED0574F2
+:10BC2000C9299C3F7DDE1E24B4BC73E5B2E10480CB
+:10BC3000D36394A07EFF8DC06DE04F59AE3F81F17C
+:10BC4000A145890F091F9809EB67FD807A6237DFEC
+:10BC500089FCBF2B7F9A45EB8FA7DBFCE7812E6A1F
+:10BC6000D9EAA2FA6D3AF2D3A541CA4F0699233711
+:10BC7000287F5A1CDB5C2724982F7DAFF2476EB8D3
+:10BC80005D586EF56527A535F89994C316815FD97F
+:10BC900006FA06FD562273504E67F5BF7DF2EE455B
+:10BCA000E087B659D5FAE58BBCDAB2FC3FA7B0BF46
+:10BCB000E2F7162525ED82F6CE0C1260F4F19155CF
+:10BCC0001A7F464AE2510E7B12BD7F4C9C319A2F5F
+:10BCD000DBF3195F1EBFD05699077C4AF9D22C01BD
+:10BCE0001FEED2C5C9EA53E5C3B67CC667B1E86E9C
+:10BCF000BA564C421A3FD0E4EC447EB4387DE84753
+:10BD000047B6BF2B99E90B95FF2D2E82F26091FC6F
+:10BD10009F7F10E5C3E101F133E7070847F9C42429
+:10BD2000B27878BC79C4C24FE5FFB6FC3C19F8F58F
+:10BD30003D913A1263B4375D2BC1F9D4257A7392E1
+:10BD400034F1873387D23DCA7CBE98C4E6D3EAABD0
+:10BD5000F63D48E17A6B2419E5C6453C1D609728FD
+:10BD6000FB83DF49FDCD5B9252B4740A307954E015
+:10BD7000CB5CE0A809E4DC49FBD1B72DE487322C89
+:10BD8000BDC919D4C9F7BE647F4992867F7991C530
+:10BD9000870B8C0E03F900F47982C665A14984EC07
+:10BDA0006D14F1B9A7D185CFF646099F1D8D5E129E
+:10BDB00032D3F0875C3BF700F8D90E1BE2371E5FE9
+:10BDC000B4367AB07F4BE32C068753F9BC7017F07A
+:10BDD000B5CDA0CAC9AD584E30AAF525BB30BEE3DB
+:10BDE00058FDD6A4DB514EE87C50EFB58F33AE3111
+:10BDF000588AEBF7FEE12BFA5BA1DF13B77FA23283
+:10BE00000FF8EF7523D1E63146F14B888D77B3F00B
+:10BE1000DB330DA84F9FB87DE7A95CF05B5FA3F013
+:10BE2000C7E2C74E063F263C15DFA3BB105F335D5C
+:10BE30006F2B85671699BE8F250F91F3A54F82F260
+:10BE4000E124A8A79F38BA961C07F9A4C35A4590C5
+:10BE5000539F17F25D420BA5B107ECAD2FF455B01F
+:10BE6000B734D03944CB822237D4ECCBC7291CC19C
+:10BE70006B211DB4DFD1DBEF21D0AFED650BC589A0
+:10BE8000DA87E43CE4776B411569A6ED76565A896A
+:10BE900091BE4F98B78600BC9DBFB022FCDC539387
+:10BEA000515E77894C8EC6D5432E030969EDB8C51E
+:10BEB000162EE781BEDC447C5351AEBF90A4D18FD7
+:10BEC000D44E7E19CA02A990090776F8210FF343D0
+:10BED000587D4FA2EF206BEFC3FE61BF304044900E
+:10BEE000D7B3C66007C49BC65A74FA161A0F580611
+:10BEF00051AEBDCBD24B09713014C82E4F886403AC
+:10BF00005DD28DD417A32F3C020951BBD149FF014B
+:10BF1000FCF8F343E7C9AD84A4AD1174F3E0CFDBC3
+:10BF20002F1A6E05FC587BD50EF1E7EBEAA03D4FCA
+:10BF300034EDC13E19AB13C68A6722FDF81F2529CF
+:10BF40007EBC9D6481DD6B693C42DE3285E1F0118F
+:10BF50007925F5A9FAF39B930D7AFF4762FCFD1250
+:10BF60008DD3811F5B5F3592EE28FCFD87A45C9D1D
+:10BF7000BF9BEE3784E747FF7DF982B9BC4BC79F73
+:10BF800063AF7F468DBE7F56C0A6A3634E4392AE7D
+:10BF90009C2BBB75ED27B4E7E9EA0B3AA7E8EA2743
+:10BFA0003D334D579E1CFC88AEFD2DBDE5BAF2D445
+:10BFB000BEC5BAF6B71D59A12B1787EED5B59F7E22
+:10BFC0006AA3AE7EC6C023BAFA99E7B6EACAB30737
+:10BFD0003FA56BEFF28BC78E807C527E34527AED98
+:10BFE0004A979F01FB39D84CFDB879CC3F067B4B73
+:10BFF0003289E21F53C3940A7CC5FE5AC00E809E4C
+:10C00000DFF3E9D067D04E1A3C20BF7CFE42EF46FA
+:10C01000E8D7221A884BA347A48504DE97EF49C4CA
+:10C02000F7DE9226940F819A0D6B3CD86DFD7A1045
+:10C03000E376D207F8BDCEF0E34539AA7E1232F599
+:10C04000FC6F26F725F8C6F0FB4C92BEFDFBE5FF22
+:10C05000AC64CAFFE0706451FE378EDF5FE5FB47DA
+:10C060000CDE09C92C5F5E71D6A98B7B90AE237163
+:10C070008F85B4803895550F679C60CD95F8C66C58
+:10C08000B871CBCDC73791F2459F94E6749D5C4C57
+:10C090005FABFEFD687B385DE79F453E9BE31F413C
+:10C0A0007D47F5E2EDC93ABDE8F32643DCC77B5195
+:10C0B0002FAAEF737BA7A05E6E17999FD22651B966
+:10C0C0001C835E917AF9F34912D39F31F4B340F5A2
+:10C0D0002C18DC9D2BEF6F07BA79B711B44BD4063F
+:10C0E000A19E8D844FFDAA7B006FC1C5FC29351E22
+:10C0F00052E32D0BD51F105F592482F432537AD9A5
+:10C10000D13F7A0CFD4B3A0F09FC23B393FA9F60A1
+:10C11000EFA9FFC9FCCD0FD7BFCC56E63D4217C5EE
+:10C120005EF6D8BCB5C929B1E1FF20C67ED4CB49A3
+:10C130006ADCFDBF93FFE6264B887F241FAA7C663E
+:10C1400006A6A3E3BD27B175A7D38AE7D4FD0B09E3
+:10C15000FEE3477E3931EB8C3C1FD6CDEFF09AA938
+:10C160005DDD376B05F61326F004F44CDCE086A5A4
+:10C1700060274909D31332FD07F8CD56A4D71B9683
+:10C18000083B2A803D8E1F6D7755FDA0C6E7E3E989
+:10C19000976755FD3293CCD4EA975871B8AA5F548B
+:10C1A0003ADC71BD5144BFE33AAD57FD090AC7946B
+:10C1B000C5FB20CF2C7888F76014F9FB27C52EEF3C
+:10C1C0003D66C5F8DBB146C038CBED0995019FBA95
+:10C1D00003C403F4993518227E0AFF0527E34FB7FD
+:10C1E00027C881FFEABE1CE400CF2E13CB0BB9B7E2
+:10C1F00005396DDEE8DF93593EFB4F171EF3C0BAD9
+:10C2000097E738504E3FF620417B3DE0DAD859069B
+:10C21000E3CE221E334E97276E289F3307519F7817
+:10C2200006BD024BC1C97174E82B8D64DA261ABFB2
+:10C23000BFD368C1E7D546119FF3730E1CBD83C2FF
+:10C24000DD9A6BC37C416B9E0DC769CB16900FFFC7
+:10C2500098F5480EF805BF697461FBF6C703859031
+:10C260004F683BC6F68332BCD3711F14A9E6027C2B
+:10C27000426C7F870FB860DF37E3F84FB05D9BC932
+:10C28000FFAF1B283EF25AC17348627480F9B6585A
+:10C29000D9FCCDF680279196CD13C8FAE5D1E451AB
+:10C2A000A107E524A3900A7940C6A7C22CA909F2E8
+:10C2B00021542BF451F488A935C8C1BE077958948C
+:10C2C000202F9469091EA5311FC9AC113DCD04DA98
+:10C2D000136FD0115E0F9395F80E3BA05D887B9491
+:10C2E0008EDBEF64FB13EE736C7D7E7FFECEA35975
+:10C2F00024B61CEF69AC3C53A1C9BB3A48F4FDDF3E
+:10C300007373CAFF027A087D045CD79963DAC19B14
+:10C3100085EB75323D75FCC2A434F08B1BF8E8FE4A
+:10C32000A45154D7494A8378796B819496E8D0C256
+:10C3300061FAC278EC455C2F7B5110CF17347FEF48
+:10C34000F5FA4F53FAFE8E7684BCD4CB173E8A7131
+:10C35000E2BB49D213105FC93F351258CF77BF3FB8
+:10C36000F32449183DEEAF1B4F25F19ABCD1BBDF3A
+:10C370003E5D6AA2F0DF7DFE74298FCA26A8D353E2
+:10C3800075375E29853C95D0F07BF7658AAF5C4EAA
+:10C390000A0350A68E32C69B72DD92D01874EB4A07
+:10C3A0007DE851C80B069B1D2247FDB2A7ED7F110A
+:10C3B00080EF1A007FFADC6219DEC9D125FEEFAEEC
+:10C3C000B71757D078722B27CB0E0EE8269B217E0D
+:10C3D00020E7CD1EE09BAD05CC2E6E7D580CCAA08B
+:10C3E000AF42012FA6852CAFB82F537D6BFD79107E
+:10C3F000F6FA490BE79B1F0779BAA904F97ACED55B
+:10C40000400EEC1F2712210FF8D06430229CE10B64
+:10C41000F66037EAD9C04CD0374D171E9B04EBF5B8
+:10C42000FB64762E40CDAFA51A024F56E7427ECD73
+:10C4300083F9B5DD7C1FEE93C59AAFDDC5F60FF825
+:10C44000F944898F7FDB119A1BE60755BE22FBED6D
+:10C450006F249E7CCA5F2F355A3C30EE671B457CAB
+:10C460001E6974E1F38946099FDF6F2CC4767B1B3C
+:10C470003D58DEDD380BCBAD26B2DEA7E1B34F3839
+:10C48000D93C5627947DC2499FFD14EE65DAAE97DC
+:10C49000F687E79CB341631CA5C79C2B542F4A50D9
+:10C4A000DFEEB94CE17D91C283E7E87A4B31BC2FD6
+:10C4B0000DF685044ABFD222F6BEB7B157E977041C
+:10C4C000E1D27AA47FE955566FAF6570EC57D4F688
+:10C4D00085C5CA38C5D09E8E5BACF48B848BEF29A2
+:10C4E000DCE268F844B6A7DEBC91942AFB1410D7AE
+:10C4F00099FA38F067648E840EC17EC6F9A7CBC066
+:10C500002EEC29267906DAC894D2CF41B9B78188B2
+:10C51000C644420AD3A7759401FF98BCF85EDECBEF
+:10C52000070FE5A21D42B8AA1DCAA80D79817FE2B6
+:10C530003D24CF584CD741BA84F686D035B6CFA12A
+:10C540004353F1B9A4B1B337E87FE0BC01AE0BEDC2
+:10C550009F5EABAF1FAF3DB52711F5D1F9EE833E1E
+:10C56000BFD8A83FE7D15547B538D51B5D8A1F76A0
+:10C5700000EA61BDEA4A133642F9D187D2416E7FA3
+:10C580004F5C1CECBB8FF48BF0DB0E349E4AAD2865
+:10C590006078037D32B78907B5FE6CA64CF9552348
+:10C5A000077B037C6537E611FCE92B34F14FABC9FF
+:10C5B0009F4E8597FCF6A9D717817E00BB0C7AFAAF
+:10C5C0002357981D1FB1DF57997E54FD064159AF7F
+:10C5D000CF95FC2E04722F833D02FBE4F19372DAB7
+:10C5E0003F658681033B448AF5EF9D02C3CBED0A8C
+:10C5F00072504E76FA5E06F9E1939E21C0477FE8BD
+:10C60000374BC06F7B8FAD2D04FF790B8997ACF44E
+:10C61000BDFB871705C0A3D5302810AACF86F66FBB
+:10C620005BCC537FA75550F4243838741D5B5315E9
+:10C63000BD20FFB1A302FC0D837F08B67AD5F65D5D
+:10C6400036FFA350A67F5E0BB5DFFBADAA9E0D742F
+:10C6500078298FED37B1F2D0FE2D1D329669FB623D
+:10C66000566E4987FD296FBA81D22BBEA9AEE3541D
+:10C670001694D5F6751D72265D4BC59E12873F1721
+:10C68000F4DE4859A4E5384D9967656261CFBDC7AE
+:10C69000FE4B807DD3D6D4E1931940CF1F737DA08C
+:10C6A0005FEB8E3F7B14CAF53544823C9CFBC8414E
+:10C6B0005C87678D6543CE1490E353223AE4F0A77C
+:10C6C000AE0BF54727BB08E68D852017CC033FADA1
+:10C6D000A8D3807EDA76EA5B1703BDDB53619DE762
+:10C6E000A4323F637290C2D1C8C1649E86EFD3C0AA
+:10C6F0005C998607B57115F118005F2439FEE7DCF7
+:10C70000E210C5A777966C9B42C7DBBC81F7344922
+:10C71000607F824DE08F91231CDA89DC53E93BBEB8
+:10C7200041CB57FB92BB21AE30ED607CB039B72FC7
+:10C73000751A7DB65A997EDD9CA89413F5E516C549
+:10C740006F7425CA8949F47DFD9127B3658AC7D0E6
+:10C75000A199182FD6ABF8C87B1783BD1C3A3A3B7A
+:10C76000610E9D6FDDCF59FEB2AEBF7831CCBF6E8A
+:10C770008F8140BC56DF4FF9492B1F540EBD93E803
+:10C780003CBC9D5378CA1F8B52739758E9FA3E9B65
+:10C79000E715815E1BBAA6ECB6D020E859419C0C87
+:10C7A000F2B2A1CBB31BF869F38C4BC88F96CF794B
+:10C7B0007E569944E3AF7B2B17835A4B3530B9A48F
+:10C7C0000C877ACE98B80DE9FF9F6564D89C88E401
+:10C7D000C4FDCC1CF83F8ADF24D15B0EEDC5A53427
+:10C7E000F4013E157CC7C00F91CB2D980F2D1797E4
+:10C7F000627DF61A62E8A0F81C9492929A68576BD0
+:10C80000BED7007E4A9ECF86794E635CC50E909B54
+:10C8100043675939BC4EBFC275B21506FB2C14CE06
+:10C8200044072F42CC916AF45A60DDA82C0F1C2AD1
+:10C8300001792168BFE5CF16615EA72B9ED43C4FDE
+:10C84000E9D463D8D8F113DAAE27C949C0AF6CE593
+:10C85000B8F52BF07DF994AD146E8FB27EC6448F7F
+:10C8600008EBD593A82FEFE7363E0C72B4E5732F93
+:10C870002C86F9A59ABD9DC914BFFACFBDD0E19A07
+:10C880008D74CEB350BAD4A7BCD061A174EF69F255
+:10C89000BA454D79D29FA9B6C679BC8072CA277EA7
+:10C8A000F61190635AFF530BE5DF6793547F80D5F1
+:10C8B000E7E7A9651ABF521D6F6C1A29CB16AAFFAC
+:10C8C000F335ED2BA8DC7EEDCB46A2C20FD1B26DC5
+:10C8D000769FC566C479101BF8335379F4676C8969
+:10C8E0006C5D6D93F3D04FEAB1327A0D6719B07E6B
+:10C8F000A1F13911F200E6C9BCC18CF173C0672AFD
+:10C90000817D579EB0BCEE01EF6409D2A36C1F90ED
+:10C91000EB5C8E71A0B550B3EF47205ED5EF13F2FC
+:10C9200011E502F360BA81DA61E7F9E55C36855713
+:10C930009BA2C4854E920E79D7400AD3338FF9E477
+:10C940003B4D12F0D8203B9F4A7CD3E099B62E3F56
+:10C950006DAC7385A3F7FF43E897ED711814BA49DE
+:10C96000BB43D4476D763C2F821EA1667EC701F083
+:10C97000279D3CF24D01C83F2D6F4B64F9F6DCDE7C
+:10C98000C54FCF02FFF0748101E49F173D229CA7A1
+:10C990002B8B2B4900BF8D1FE1D357507E8D4767EE
+:10C9A000DF0DF19E00F24BDF1EB0B273A0C3E9A40D
+:10C9B0000FF2BFBCCB4BB4FB81AAFCEE6CB4E073AE
+:10C9C0006FC98A6FC03EC1D7DB09EE07082E1F96DC
+:10C9D000A516C2815C1C2FBD17C7FD2AEF4B580757
+:10C9E000FAF62CF3EB815D309F117A8A837CC67B4B
+:10C9F000165F02CC7B5FA2DE9EDE96CAE2613985BD
+:10CA0000E9CF3625DF295CBB05F337AD26551F5925
+:10CA100096807F2AF07E3C2F6BF66FF382BEB210B9
+:10CA2000591635F9704BA63EAF255CBB15E1C829F8
+:10CA30006C9CC873050E4E854FD7610C7F597D469F
+:10CA40009E4368203ED44764809D6FD8B66B7E5A63
+:10CA50009206CE36CE9B268EC11F5BAE194950730F
+:10CA60001E650B3F2CC07CB65C13F03D710DC637C4
+:10CA7000C1FE0B65B80E58C717BF8B76C9463A433F
+:10CA80007060CA0CF908CDF94FE2E28747F83F2FF2
+:10CA90002C1FB87FCE45910F495F8EDC370F808DFC
+:10CAA000A57EC50EFB6F0498E7BBF3C930F89384ED
+:10CAB0000C2E04F9AD9B6FC37CF416D269B1401EF5
+:10CAC00085EF14B579E1BAFE8BF1708E8E2EA90434
+:10CAD000FECD961F96E9F251EA3930B55C7F6403CA
+:10CAE000E609B7F45C15A694201A03261A8FD559C7
+:10CAF0003A4F99F3C2EDAD26BF9C01FCFFC347BD81
+:10CB000019F4D5D7004F383FD5306126C47F7F1048
+:10CB10006BD2814E765EB11F6B2C683F5AAC345E8F
+:10CB2000033EBD3009ED29ADE6C13EABE32F56E231
+:10CB3000E221F02F6640D73EF4D35B6DBE2B609FA1
+:10CB400080B179EAEFB426A97CB3AD03E4A74B0822
+:10CB5000EB45F09FBA6CAC6CEFDAD6D1C2EC30F397
+:10CB60006F9CDC6EF06F5A157F6968FF75F48FBAA1
+:10CB7000844EE6FF7DDF2C019E5D369F07E2417902
+:10CB8000C76409EC49459A03E7617AC1DC0DFA30C4
+:10CB9000D9E9BF047E0B7132FFE8DD94F3D9200F91
+:10CBA00051E00C733703C7A587639DCBC67F9733CE
+:10CBB000FA769484DBD1FE21DCFFBFCF82791EB5EB
+:10CBC000FD01935EAED5675E2AA327E813906BF54F
+:10CBD000BDE0DF84F26B2601945FB34BBF2FA4CA84
+:10CBE000B3706DB22E4FF9B514B63FA5EA01E15A04
+:10CBF00011D6CB0A9FEE84FDF231C7498A31CE743B
+:10CC0000D413B1C72955F40851F2BB3C9E2753E514
+:10CC100024B6BED0E76B23F59FFA54F5DF17143E18
+:10CC20003E6DF5CF4BA5E33C12EC5B68C3DEFE5BCB
+:10CC3000617DFEA4F06561EF93C780FD2E8BDE4F12
+:10CC4000A5CC807353DE6FA4A4BC7FB9D990CAE68B
+:10CC5000335A8FB1FCC3B68725B4CF5FE53D364F5D
+:10CC6000143D5673CDAED35F19296C9C1A5E463DB8
+:10CC700056732D1EEB3F387C2B094E1F0BBE03EB6A
+:10CC800047E0F731F8C74B7FDA350BE01F3619CC98
+:10CC90009A786EDBE105699097DC66A57AD9A19355
+:10CCA0005B2FC82D9F4B46E22090F37D23F5F37751
+:10CCB000837FF3AC56CE6781FF15EECFD375DEA729
+:10CCC000C83D9197446F6F8F683FE25F5561FB48A5
+:10CCD0007C543D0265F0B7F83F9B55FC500F3D6911
+:10CCE0008880A7FA637235C2DB3C83F919969407F2
+:10CCF0007F26E703FF05CB200E1A7E9848DD6434BB
+:10CD0000DD2D0A1FD65C9BA05BD730BD27EADEFF76
+:10CD100047A38B0435F2F651FFB6856897619D00F5
+:10CD20000E917762BF031924A891BBFFC3E383E28E
+:10CD30003127061EF3FECE78E4EAE4328C47BEEEDD
+:10CD4000FD07C5C368B9E6BEAC299B4492A12D1767
+:10CD5000872C1997357ECBF453A2AE3C63C0A56BEC
+:10CD60003FF39CA4AB9F3D58A8AB9F73C5A32BDF9B
+:10CD70003E3C4BD7FE8E6B5E5DB98C2CD2B59F6F5F
+:10CD800059AE2B2F10D7EADA4F54F2E477BA36E8CF
+:10CD9000DA2D921ED6B5131A92BF03FECB1DD7EF24
+:10CDA000B0407CB1D361A8847D879DBCDF921445DF
+:10CDB0003FDEA6C01DB177AE54ECBF400CB4803E40
+:10CDC0005C4043E166EAAFA555FB5AC0EE578A2C9A
+:10CDD0008FA8E6CFC9F59515F0FEEE4544EC480C5A
+:10CDE00097EFFC14215036677AF1FC9AB5C880E7BA
+:10CDF000037617AD1873FF619FE2BFEF89B0F7EAC2
+:10CE000033C1C8CE4946BE2F48637EC29377EC2318
+:10CE1000B04F607104F17B9EA39377BAA0FCF41D20
+:10CE2000DF76419CD13EF9132EE09FB6ACAFE9CE40
+:10CE3000DFD9F2097EDF110977BF0237FFDA631607
+:10CE4000B09FBB33193D23DBA9E7D0775B58DEFCED
+:10CE50006F35CFF234263F1FF63C2F2870775B8268
+:10CE600098FFEF28FCDBE05F3D82FFE384E1FB38C5
+:10CE70009E376ECF1224AD9D559FF07D28CCA72DF7
+:10CE800077A70BEC6E7BEE2774FEBF399FEDAB45A9
+:10CE9000F6E35C6CDD768B7FDBF93CF657CF67679A
+:10CEA000D4FD754B8C7915A8F3720591CFFE56F31E
+:10CEB000FAEC883CFD7DE6F5A2325E7C1AF34F77F2
+:10CEC0004B4C8E128CBE5FE6E5C696BF8459FAF3D2
+:10CED00048711E7D1C9097EF1BF39CD139853EB1A4
+:10CEE000E4758D494E013C5E6B64E769CF021DE934
+:10CEF000F39C7F42397C97F01A9CCBE2A0FF8EB85E
+:10CF0000B1D661ADDFA8C3733CFD30258D9DA75C14
+:10CF1000BD46DF6F95CFAE3F17A59C27A0747A0260
+:10CF2000F2CB2ADD46ADF38744A758FC76B374EA0A
+:10CF3000287C7F741A8FBFE3D398FD1A8F4E2A1F67
+:10CF4000C582F3FF2B1F95037D6E828F54FEF95B24
+:10CF5000D3E71F8D7FAAFF8F3E63D2E7B19BA48FDB
+:10CF6000AA877A055213ED1C48934B40399DC4059E
+:10CF7000CE2C8238FB2E239E773873A0A78EE469CF
+:10CF8000DB317B7AA6F2AB7578EEAEC68EE7BDDEFE
+:10CF90003078FEA504F2528F1831EF1609FF8C424B
+:10CFA000BF4DAE44E5BC8E9402F47EA366E598F3D3
+:10CFB00023959A79E1BE9A2D5C3652B84442FACA5A
+:10CFC00094BE90173853393D2E9A5D53D72FD6789B
+:10CFD00037BB7E6FD434BFAFF51B6F7E2B5D7937C7
+:10CFE000A51FE1C43ACB4BB17301BD8F33FFBDD751
+:10CFF00040D793C2BF0FF2DCB3210E2098FF5BBD78
+:10D0000026ED20E0FB2F2E76FEA25F90EAF01E9028
+:10D01000954B77C3B988B3AB1239486DA8787C4576
+:10D0200059D7D2EAE8FEE7734A7DB83F472645590B
+:10D03000E72F2AFECFAA6A0EFD08C27BB3B4F77CA5
+:10D04000FC73447D64FFEFBBE2B1FE6C8CF3975F31
+:10D0500057FAAFAE1ABB3FA94D510E618853B5DFE9
+:10D060009F8FF095220F8B5DFE3E176DFF1AE7FF35
+:10D07000D2C7818F263B90EF094F7261FF7F040E6C
+:10D08000EFC5731B97EB18DD23E16AE0BD3416BCD6
+:10D0900058F455E7A58E57427C18DF914A223E315D
+:10D0A0001BC737C279B6BBE793008ECF4B884FF2D0
+:10D0B0009B34AECB0DF3C7798358871FCE2870FA07
+:10D0C000FF7BFE1280D37FC620EEC88D8D772CBDEE
+:10D0D000F0A6C23F4EA37F079C2F20EBB9A8F27D9C
+:10D0E000CE65C576BB5CCC3F24BC3F0BC699B8DF90
+:10D0F0006F9228DC7B94F36784F8B3966BC6DFA548
+:10D10000CC3BB29FD3C8F6C9C9EB4C0FF5763F9222
+:10D11000154D8E5E51FCE65DAE42DD39DF2ADFA3A0
+:10D1200026D003554B979B2407D44B8CEF143C7AA5
+:10D13000057F56B1234CA798FA47A14FFF397F339B
+:10D140009CFB59DFC0E139E3A2ED8CFFD66F3F6A4B
+:10D15000A8A3CF838A1C2E57E450ED6F4F6772D37C
+:10D16000DB6DCB06FC7BB5E730281EF73F43307FF5
+:10D170006748FFE21E99276490234ABEEFC65DB060
+:10D18000EF30A8EC8FE5D0FA26C0B782E1BB7EFB7A
+:10D19000728CF72756B278BF5F20781EE8CDDBE3AC
+:10D1A000823B0086C57BF4315ABEF4E704D2E10924
+:10D1B000F3C75342682AF0474AB3EFE3BE28EBEDCA
+:10D1C00056F0FD8383EDE7C5A28BAACFD5762B78E9
+:10D1D000C914ADFDCA4ABD5E53F14F3687DE2551F5
+:10D1E000F2EA23FC181CDBEEBDAAE8E95722E2A60E
+:10D1F000AA73D1E397D274C6C7BDC1F2CD78BE5928
+:10D20000364B789658C1C729AF467ADE5842442833
+:10D21000DF6D96BE0CF8DD53658CD0C34184B37EC0
+:10D22000A95D37AFA7BA7F3A15BE43CACB67FAF7F5
+:10D23000BD42079E0B7F880404D85FAA26F23C9467
+:10D240004B229980BFCF2AF453F13B4BBC71334042
+:10D250005F3444B79FBE742627677DF357A1DD6D09
+:10D2600031E2B9848B55C9CB200F2EFB4C1E38E61A
+:10D2700074B16565DC839A7555ED9EEADF9CF3CF4A
+:10D280001FD37EADF2E9D7AB57E8C47D40B99C040B
+:10D290000E513E9BF4A5CB7B67D2F299A001EF190A
+:10D2A000C23F2C67A8E7E0099F4AD75DA91A320C54
+:10D2B000627BF90B6C5EEBAA830B606BECBE673A8A
+:10D2C000F7CDA4E587D2993FB0C33EEF7690D75F04
+:10D2D000358C632F23F869E27E9BAE5C7A8E08D092
+:10D2E000DFBF2DBA7DF88F0CBB72AEC8930DEBB0CB
+:10D2F0006E7BF476F64C07DB27FC8BB1265AFCBD1F
+:10D300003B83C9C9FA1A2EAA3EDF9D11C7EA6BA357
+:10D31000C3BFDBADE22166C3BAAC8F81EF1237B376
+:10D32000676FB5AE5E07FAE08A41AFA7E7BA195F4B
+:10D33000B8DD6CFF7BA8FBA5D654E0879D9C08E771
+:10D34000C92E257A2603FF6D68B988F17EA2D2DE48
+:10D3500098E6DB974EDBDF7BEEF913D0BEBF9A7801
+:10D360003829B61DE84A57ED80FA1DB46A0F3BAD67
+:10D37000608FE07F619F15B6FA139260DDE547F09C
+:10D380007C4CB74D64DF3D796668FDEB1E45CF0CE4
+:10D39000F5BCBFF5BEAF46EF1745FA7F4382B4B781
+:10D3A000848E3B44F9AD89CE875C7FEA56ADBD5192
+:10D3B000E521D6B837EB070EF5BC3F3F70BC799E30
+:10D3C0004ACFBD293FF0BDCAA7F6954830CFCE5B06
+:10D3D000A3E95B552FBFA1E8C5487E19D1378A3E26
+:10D3E000B9121C1BAF8F3EA3C7675D408F8F2A1FEA
+:10D3F0005782CD36B8478B8E3E15D659F54B49C569
+:10D400008C9BBA1F24169E57143C7FD560E451EFC5
+:10D41000F57098A7FE55C353F1D1FCFCC8F90F195C
+:10D42000283F007F7C9947FD5350B3E158AA14E68A
+:10D43000C7F714F87F2D1FAAFA55B52791FDFF51A4
+:10D44000F94EB567E3F19D33461E7277BA05FB6F5F
+:10D45000E04501F69176A74BAC4CC4852EF05F6792
+:10D46000B1F3EFD4EE65C33D1243DD36FCFE4BEE67
+:10D4700030070BE83A5EE99E3359BB8ED3DC8A5EF7
+:10D48000AD4DDC095BD7570C9E4569B07E2BD87D2E
+:10D490001E67CF252D4CA3FD9F1A30C08D5864DD2B
+:10D4A000B60D4698DF6DEE446697B79F46BFEFFD19
+:10D4B000F2F5FA80DE9E3F9DAE9E3F657EF8DDD49C
+:10D4C0002F80F384B1E890E3B660FBFB6A0EA33EC5
+:10D4D0007D603B87FA54724BF8FE013E887A99B41E
+:10D4E00030FF9958283DA85EBA0893007A7C8E6375
+:10D4F000E7BC799FA0BD6FE3C13DAB17C0F9CB4836
+:10D50000F9F88EA2C73FEF3628FADCBFC88DF1A12B
+:10D510008F0378973EC9F05DBFFD513CA7FC7ABAF6
+:10D52000E25F2BF2F9BAB24EEAFC9295F99DB70D83
+:10D530006F037B41E5C680E74C5E33225E435FFBB1
+:10D540006600DA89531C18EFA31F4BCBBDCBE282D8
+:10D550004D9ABC9DEAD7E479983C54F15E9D5FF802
+:10D56000903B57E7A747FA1BFF670FD8B3C3FDF7F8
+:10D57000B5075DEE0FC71E04D219BF47DA85113912
+:10D58000DEC9E4F8E2B9DF2D8072A41C7F5D91FF53
+:10D59000BF567EAF74DF8B7C2D2F2662812E3ECA54
+:10D5A0000A421C3CC2FFE1388983736E4F75FF6CE1
+:10D5B0002AE4BB2EEE5DBD2EDAF87B33989FB531A1
+:10D5C0005E32E07D90AF313E8BD41391FD46E42274
+:10D5D000469EB16AC56C8C0FCFAE98930DDFBF45E8
+:10D5E000C607A3DA73DE9455101F3729F1F13E7395
+:10D5F0004D77147C93143F352F7FF804D0FBBD5A30
+:10D600000EBF1F863FAD9F7EEF39CF8F06A5D1F8A5
+:10D610008E94D5F8643B1B2F729CCBEE88F844A601
+:10D62000F109A5F36095311ECEB3AAF1C9A0FCE1C2
+:10D63000C6276F92E17F9909EBDC131D2F3E43E172
+:10D640006BC1BF6F36C56368B1D12383BC18683F17
+:10D650004D5C12D9EF9AC2876F6E7F9FFAE89C3EAD
+:10D66000AF1C4BDE46F0FA2BE5AD5718CE02B97F62
+:10D67000F3E0F50B8FC17C0EDAF0BEB1483807330A
+:10D680008C4A7C60433950ED6FBFD059FF12EDF7E3
+:10D69000E65D6ECF0EA2910B42E582BE3FFF172AD8
+:10D6A000171ED46F28C7BDDDF69A6871CA0F143EE5
+:10D6B0008BCCDB88DDDF08405CEC251E9336EFF475
+:10D6C000BAB2EEAF2A7A292F83D9CF7BAA960B90D4
+:10D6D0002F7A70245F4430B810A7641E84F8F215C6
+:10D6E000E57B0179631CCA5D241EB729741D2F7F59
+:10D6F000B0A65A1FD7DF53A5D71F6F07F346EC48D4
+:10D70000C118FB522AFFC61AEF66ED476FF0FDED18
+:10D710000B8C37BFBA8CDC9BDA17584502B7639E77
+:10D7200083AE0F3CAB4860EA4B149FB79F59897991
+:10D73000F45709A9443FFEFAC7A66AFD927B95F506
+:10D740007EAFEA637701BBBC2E04A646B33F917956
+:10D750009A5783D1CF67F814BDFABAFA5DC53DC6B2
+:10D76000A8EBBB5959DFD7ABC7969BC8BC4DD55268
+:10D77000FDBC3F95212A709A6D7E1657B371BFC0CC
+:10D78000C605BBA5F54B3FF521C9EB20E4EF619C35
+:10D79000ED84403EA55790A768CF5FC565323AE457
+:10D7A000158EBD1FF58A4257B55DA49FF513B7A42A
+:10D7B0003B3754B5548FD76746FC4111F320436083
+:10D7C0002F9D617B79B7D9F330F001714858FFBCC8
+:10D7D000B2DEF7D6FCD604F3A7FAB315F2A1F2191C
+:10D7E0008308FAB3F45CD0A4A5CB6B3719DFBFA6CE
+:10D7F000F80BE3E9D1BCC261D46FEF051DF89DC4FD
+:10D800009B9FF993291ADCAA6B19BAF3C4EB7DD15B
+:10D81000F32AB60CB6DF158BCEB60C49E7A7AEBF20
+:10D82000968DE78363F9FF9FCD6071D07D35075BEF
+:10D83000B5FEFF530A9C07547DC633BF3F56FEF525
+:10D84000A71937977F55EDB3DA2E72FDD567A4BDC2
+:10D850001C54E439B2DDBF65DC1CDF8DF83131F8D2
+:10D860002ED6B86AFCA1E67DF38A68FF28FB32A3B6
+:10D87000C651DA458EF3AF197AFE1E1547C4C8DBD0
+:10D880005933991CFB63E4EDAC9971587F8630BB2A
+:10D890002807ED68C7AEF43CB00FDCBD87167DFCF1
+:10D8A0002498B78F2AF99AEA9AD327204E55E38A0B
+:10D8B000B03FEE6F867DB2A11D1CFA1B91E344FAC6
+:10D8C000E51F853D269047257F5068F4629E9A7C2F
+:10D8D0009A9DF37736AC46FF52CD4FF70ABE1D71C5
+:10D8E000F4FDC4EDBFDD06F6558DE32F993C0FB373
+:10D8F0003C33F377CF773BF07BD7DA1179F760BE13
+:10D900007144FE95FCE378EB31A26F62ACC778FA04
+:10D9100026565E447D8EECB308E28C97E17C2A1794
+:10D92000EF817B99979B09E67D962FE130CE5C6E67
+:10D93000F6E27ED6E9330603947317E7EE067F63BB
+:10D94000C552A3D74A51F83700359BAAF257AA0B04
+:10D9500000CE5374C210C7F6BF21BE07CF5717C4FD
+:10D9600049E0FF9F9E27353969F9F4624EDC41FB9F
+:10D97000BDBCF401E3545A7E8586CF70EF8CBD8127
+:10D9800028DF7FDCB26C7E3E21DF00B89AEF3F5E7D
+:10D99000216AFD3DFB2A281F4D49E937382849BF38
+:10D9A00075E09E7D160ABFB5C9E782EFF2EECFBCE7
+:10D9B000751F7C0F999AEA1DB883FA519D999E654F
+:10D9C000F09D5EFF175478C5FBE03BBC1F18FCB907
+:10D9D0001CAD7F2173D1321EF62326A8F0ABB17E99
+:10D9E000D5C2750FF6D3FA0B07EA97C119F6D26ABA
+:10D9F000A5BFFCB165F3794AEFB96AFB8678283B8D
+:10DA0000ED24BCCF348B1053F83B3F3CF7DE3F7224
+:10DA10008E7CFBB20ADAF7D5B2C07CF89ED3F3A5B0
+:10DA20001DFB8AAC84CCAC2C13BD743EA5595F5849
+:10DA300066877521941F69FD47B20E2C83F9388DD6
+:10DA40000605FE9710BFD26A790AD47372705F65BB
+:10DA5000227C97307812D8724B43A72555F77D4228
+:10DA6000C00BAE8970A42C9481E828FBDA99A1A997
+:10DA7000ECBB3BA55CC8F2142365172BF7EF88FEBF
+:10DA80007DC57F6531FDD56F8B5EDF91A9DFDF4EF0
+:10DA90003847BCCF4591FF8F29797F559E4E403E38
+:10DAA000C48957CC059A601FD6C2F08CB58FDBAE07
+:10DAB000E897FCA604BC976869C08EF7E84CF03084
+:10DAC0007D43A5885F09FADF68403C538C1CDE6B00
+:10DAD000926A23FEC3F49992CCEE39594AE517EEC7
+:10DAE0001F5930C1D783E77CD3D28B9BE19C5DD398
+:10DAF0002F79F0C3D4FEA3F1141F053C538C2B8A5D
+:10DB00001F2DD2D0AF88E14DD75DE9E7FDE61D209E
+:10DB1000170353F2C0AFBE3D536FEF4A07CA4DB073
+:10DB20003FF9AB2C250F26B1FE29F3995E197E54DF
+:10DB3000B9B7C2E229D6E5F5153ACF6F5BFA34B42E
+:10DB4000AB1D3011388FB8ED7099EE7EF5C8672D9A
+:10DB50009C7BD7D8ED5A3E84E7CD6BE1DCFB74802B
+:10DB6000F77301CE39021C880FE0FB0EF09B529A2E
+:10DB7000A3AFB79A57AEBD9648E4E9DAF78C5E6179
+:10DB8000F84EAC1F6F5E6178FAEFF946C353BEEBF7
+:10DB900053E9CE2B7417A2E3F933952F29BDB5BFF6
+:10DBA000AB52554D94F313EC1EDFF3CB8ABAB5F7A5
+:10DBB0001610B2839DEBE0E93A823F3960C3FB80E7
+:10DBC0004B79AA1F9D002F4994B9D17CA1AE6B7FE0
+:10DBD0005200EF231ABE8B13BBA3F8D967143E2E55
+:10DBE0005DCAF836ADDA6FDCA0E17795FFC3F007C8
+:10DBF0003EA3CAC73A94DBBD0C3FF037800F3DA16E
+:10DC0000A9DA73202AFE659904E74FD791D1FF2E38
+:10DC100047B09B0BD36D34FD33C659CF6CAC2F1D71
+:10DC2000382600BFD5C690D3B359F1386EDAB95053
+:10DC30003C9C0F58A0F07F7FDF74EB1C908BA506F7
+:10DC4000C2496CDEE06796CE55F5E73BBF28A7F6E4
+:10DC5000206DA44CF5AB04EB30A26F43164BB8FD1E
+:10DC6000C9AC7796B5803E36B3EFBCA9FF68219A60
+:10DC7000EF11B92C96BF9DE58FBE6FFD4616F34799
+:10DC8000547A7FBE613E798BCEEFAE4C66BF670D96
+:10DC9000CA785F922AD7917A29278BAD634616E31B
+:10DCA000B3BFBD5EE2C6D14BCB15BDC4EA89D35725
+:10DCB0000BF5A906E5FB0491ADFBC69F4C2F803CFC
+:10DCC000DC56975182EF1D56729EAC6FD171AA2C13
+:10DCD000526B9C14E68F2A62911C406F3A027CFFC3
+:10DCE000BA62A915CBF0077EC7EF3A39C67F444A1E
+:10DCF000A81AC3AF55F1D9EA1270BC8DBB0A12FC49
+:10DD00005A3C79DF7398DFB32B785A22EC15AF2F8A
+:10DD1000A7A686EA0C464DBD83D9AF1697774E1657
+:10DD20002D9F56F242A43659E717AD52E42ED22F5A
+:10DD3000FAAD8B287A6205C68F69347E847B02D265
+:10DD4000FA7C781E0C2E322AC0EF76D97DC6970E4B
+:10DD500093B91027A9707C59453AFD5EBD1A364D1E
+:10DD6000A8705AE67B2F6BF4D929E53E7ACA0F33A7
+:10DD7000405E9767117D3FA32F13BE2F2769660F63
+:10DD8000E89B1382EF00AEAF4812617D17181F3D6C
+:10DD9000807C612489CD784EEA20F6AFAC1E2E41FE
+:10DDA0003FF5BA310476E797D9E998CF49B133BE48
+:10DDB0003D610D603F9E4849A84714BDF7CBECC9B3
+:10DDC000780F86AA3FC3DFB5A87058FD096E792683
+:10DDD000DC0B7B2265527133A7F777C0FF09FB4B41
+:10DDE000DFDF77673EF8377D218A33D52A2F2E7BF8
+:10DDF0008CB6DF9C25317ECDF5F5C3B82712890896
+:10DE0000F8CF1AF43F07E5452E3BDEDBA6AE47AA66
+:10DE100081FD1E4CAAF27B2B2027F0B4653339EB31
+:10DE2000529E83D96C3D53E3A3FF7ECCB0D26EBF2C
+:10DE30008DD1B9A34C7F7F92FADCA9C8719DA5B39F
+:10DE4000123EA9D77CEF89DF87F384FA551C7C4FFB
+:10DE500042F03DB56748AFF96DD5F8FB61EF0DAC09
+:10DE6000C27B5C477ED703EEABA2EB1E222B9F004A
+:10DE7000BA0BAF1AF16EBD56133B772724FA45F85B
+:10DE80001E29D91E3DDEFD96824FB291DDCFAD7EBB
+:10DE9000C76052BEEBFF8AE28FC5BBAAD83D45944E
+:10DEA0008612A55F0219C6EF74D5758C3C976B522C
+:10DEB000BEE77FFFFE43710CFFA144E73FA8E346A6
+:10DEC000FA1117E0FE6D4DBE7B9DEBEC02A2697F5F
+:10DED0003F196C0578F76FCBD0E52562F91FC715A0
+:10DEE0007D0BFE821C152F41F7FE028D0365EDF8B8
+:10DEF00057D8F8E171ED44D68CDB96E57D390BFD02
+:10DF0000D4B922DE234C7D76380F4BED0EB3D77398
+:10DF1000D9FD84D42E5582FE56E322907B3101E454
+:10DF2000BAECE759291A3BA9F48BD447772AFAE8C7
+:10DF30004EC5DE249C53FD469BC47161BB33DA6E33
+:10DF4000718A1F1DA91F23ED82DEAFA67C2B6BFDFE
+:10DF50008051F292F541FDCB0931F863E2DFC5BF94
+:10DF60002C9DEBC7F892547204F6416656E8ED3DDD
+:10DF70009FEDC079F1D9769DBD5F51AD6F6751DAE4
+:10DF8000599476E3D1536B8F3823E83D06AF9E63F7
+:10DF9000FC90FBCE19BC4FA9229BF943B7E4781340
+:10DFA000B269FB837F9EDF0BBF3B31DCC4936E27DE
+:10DFB000F4F3F60E3A615E1611E2D4B2B515850798
+:10DFC00069BDE9E7260FC4CBE448F4F8DED1C07997
+:10DFD000375196CA54F460AD93CDABD61912F229DD
+:10DFE0001EEE5A864F66DF518ED7E8BDCC1AD66E2C
+:10DFF00062B649677FA628E5C26C252E21C126F8A6
+:10E00000FD93CC1A2F0FF6CEDDC711E59E4DBC1F38
+:10E01000D5ED61F01D9E20F7405178DEED86E54597
+:10E02000602FDA53ED1EB0175B72FC9E6C90D7F335
+:10E03000A110906DE6F9011EFCBE5D39DE62A0877D
+:10E040003A3FC928BA617FDC7E9EE1D719C1FF84BF
+:10E05000EC56D6A59BE1E7F015033EA9F112DE4789
+:10E0600044FFF2C0AEA62629762395F8E1DE2062B1
+:10E07000A1EDC00FB2D176DAEF3789AF04F609828D
+:10E080002953A7819D5B60F31CB3807D9D963B0D5A
+:10E09000EE177AE940F47CFA32C5AE50FC1769F10C
+:10E0A0008F251F23F7AB2BED4C31E26895EFED95F3
+:10E0B000D1FD556A09985FBFD6792FCCA7B6452008
+:10E0C000708F844AF75D39BE6AC0C7DD77900379E7
+:10E0D00075F795215FB9659E805FD162CB0EC2BD99
+:10E0E000B12D491F4903FAC7C2BBB6C1E8DDA495EB
+:10E0F000E71601D7E360C4F93535CEF87836F3B3C7
+:10E100004339BE5A58E7FA234FE239C1877B2E0ABA
+:10E1100063DDEF73B374E36A58FC52BB86DD9B5139
+:10E12000B696473EDCDC22E0BDACB5CF1D0EE17EED
+:10E13000F17682FBA0B57D874FC2BDAC19B5DE1963
+:10E14000DADF21C8A865F7C7A5521E192842BD29E4
+:10E1500080DD76F72DAF45BE168948908FFCE877B5
+:10E16000655A983FAAD2F7A410CA7E99B63B692097
+:10E170009E665A7FD52417C24F345DCDB579E01E17
+:10E18000867F3EFCBAF469A033E4C55CB01EFE276E
+:10E19000811E1D4DEC3C79C702EAF7D0760BEC648A
+:10E1A0002B9417343B08C8C7CDD26166045FCCDC22
+:10E1B000CEE4E4B8A25FE81FDEABF4CD6C16D7A4C2
+:10E1C0001AFCD5E8BFD279B4CD46BC701EB66C6FD0
+:10E1D00010F02262128EEBAE0D71DAEF50D4679818
+:10E1E000AFBC5FCB4E793F78F6E13EE36645CF9416
+:10E1F000ADEDE1DED2F0C1F7B2D97EA9FBB9831C47
+:10E20000C487B4BE698113DB637ED0FD1C8B9B3653
+:10E21000D3FA07757A6503CEA7DDC6FC47AA577EF9
+:10E2200008FC7EC2F0E871D82F39318DE07DB377DC
+:10E230009D0F9D44F5ACE07B4260EBC9533A34D16D
+:10E24000F2A96CE6DF9D14FC9B60DD4FBAD977DE46
+:10E25000ED861D78EFA92AF791727A4AE173F79A51
+:10E260001ECE50847940F42755FCD476B7E494FF51
+:10E270003C1BE9308074A85BC3B37C8382CF02C1AE
+:10E28000970F71DA1B0ABC63ABBF6D7C86E25757F0
+:10E29000C4213FEF7FE134F2655D27C77E27A8F3F5
+:10E2A000B4B04A135F757DEF34DA9525FD6CFFA598
+:10E2B000AEFF30FF8003ECCD31E4CF3ACA7FD612F7
+:10E2C000583709E97CD514CA067B19C99FF64AA6B6
+:10E2D0001721E75AC0EE83C3FDDFE05A0BFAFDAA0F
+:10E2E000FEB5652BBF5BE9F0E7827E7D5729ABF079
+:10E2F000C3F1AAD503FC9DFBCEB46370BF5B9D87C1
+:10E30000F3C079E4E1117BC2F4B544D915F4B50A40
+:10E310003F927EAE1C66CFA2D891FF8A6647543BDF
+:10E320009BFBE572FCDD3775FD7885EE23F63D87B6
+:10E33000ED4B597278051FAF0BF2D81295E78E128C
+:10E34000B8DFCF57043FA1D69262F7407EE79F1314
+:10E350005F933668E87552A0F24ECB27F36C880FB6
+:10E36000950B6B8E66FD6A8BD8EF4AEDFFEE72A4BB
+:10E370006B2DAC1DA56BAD7FD326A4B38B888740D6
+:10E38000BFF899FEAA5D730FBB075CB57FCF7348DA
+:10E39000FF5AD981F75A2FE95B8EFC499C564F01F1
+:10E3A000877A0DD7599533DB085DD9FD4334AE6FBD
+:10E3B000827C891AD7C757FBE43869B49C262B7135
+:10E3C000FD0C25AE37CDB27CA871FDE6869F61FCC1
+:10E3D000F388EB27F854E584C68D3A799AA1ACB35B
+:10E3E0003B87D9D3B9394C2E3797F421FF6FBE1C28
+:10E3F00040F97154323DE238AFD77F6A1E8C903DB0
+:10E400008C0FED7D0B611F62C1573811F4402CBC9D
+:10E410003FCA057E01E755C861768EE28EEBBF8C60
+:10E42000D7DE47BA3487F1F7D55E230901BDF980FD
+:10E430003096FF1B0B5E56A862F6BFD3F5FB756FD7
+:10E44000029E0BBAFADCCA4F4259EE49C0732459F6
+:10E45000A12AE48BABCED91EE0036733A3D3D5BE8C
+:10E46000F9C83FEFA44906B82FACA9EFA979F0FB92
+:10E47000D01B15BCDEF9AEB101E8B0E3EBDF9907C4
+:10E48000F74B6E0E72C9F0BDD9D5DEAFFC05EC5E60
+:10E490004DCF163CF7D5FCCD7F42BFDB103CC8DE2C
+:10E4A000F72688D06EE8AB4FCE03FA36F73563FD1A
+:10E4B0003B5F3D88E5635FFF8EF19992301FBFF3AC
+:10E4C000DD833FFE6F28FBE2F1BB9C5AFFFEC7A134
+:10E4D0004CAAE2D97757FE9705EDEF75751D3E8A78
+:10E4E00072A8F2C5923E4EB93F4CC0731E2AFF5E21
+:10E4F0002A2F2A05B9831B768DF368B923AE265AD5
+:10E500001E71A732DF5AE04518770D1704396817D6
+:10E51000E45ED4E7625F36E8737B5148807B5756F0
+:10E52000571F9EC77E76B009EB575AD879B1A954C8
+:10E530005EE01E290AADE706F56B56B63FBC0EE05D
+:10E540001D3012D1981EC6B75E90303EAA5FC179C9
+:10E55000A884118E6C3B9102FB5F0D4439D7C5DA5C
+:10E56000B5D3F0D29284768858E9B3745BF43CE872
+:10E57000BE1C87229F4C5EDDFDCB33417F10A7D9A7
+:10E5800053901B8697752ED001D7F9BB6B0616C228
+:10E590003C16176E980EF37042BE0FEC8BEC40F8F1
+:10E5A00075909FA4F21454E42655F4E17D2316AF30
+:10E5B0002F057E834D32FB703F4F5AEF3335819EDE
+:10E5C000E187B357A1213CA4CB7B7599FCE93300CB
+:10E5D0005EBB629F7A18FEB43FC293E67B9DD09FDC
+:10E5E000C24778966A2F8FBFF16661EBF09F3FBA02
+:10E5F000F3903E5F1E1C05BFC401F6455E83EB260B
+:10E600000938DF77A029D25BBE559BC78ECCF78037
+:10E610003E83FDDE504ED90F7266849F6A1E28929B
+:10E62000CE7F817AD01F92179FA437F9A67E0F5014
+:10E63000D5DBF57B14BBFB838BA877EAFD3CB3BB32
+:10E64000FECB68777FDDE8256F51C7B2EBC58BC87D
+:10E65000DF0F1C6176B7FE48B100FCACDE8B5C5F5F
+:10E660007E15EDAF6C24C8D7F542DF4917C0EF2007
+:10E6700089D4B327F5F3062782FEFBCD8BD635D0A0
+:10E68000FF84C180FC76A2FB9683CD9C163F1607C3
+:10E6900070354194C77AC52F285BBBE94988C7EA22
+:10E6A0006A08C685F5FD8A7CD1780CE85B7FE43486
+:10E6B000F28FEAF7E67E7905F25B22E537FC9D846E
+:10E6C0008A01C48FFE790AE833B182DD8FBBB8B00E
+:10E6D000B814F8EDD8EA1FEF04BB5D5F414480DF5A
+:10E6E00095E57D11EF017E91C37B29BB4C9DE5F043
+:10E6F0009D64D7024904F9A8F7578DD8273C5FEDF0
+:10E70000AFEA47F971AEF380FFD0D1E447BFBA2337
+:10E71000DD8E7E41D78B4D683FEB259B077EBF6426
+:10E72000C9116E2BF6971D84E1CFA19FBF24380736
+:10E73000CF6DA9F458523198CDF405C3FB37A681AB
+:10E74000FB61DEBFF99E19EEFE1EE1BFC48AC00167
+:10E75000B8AF768938CD03F76B26F1037EF077A842
+:10E7600009F634C1FEB0C967F640DCBD97C37DA889
+:10E77000FF076B233BDE0080000000001F8B0800BA
+:10E7800000000000000BDD7D0B7854D5D5E83E730A
+:10E79000CE3C924C26274F1208F14C123040124EBC
+:10E7A00020BC114F88416CA90ECA2354C4E11D201E
+:10E7B000242362C55F6F33381023BFD71BAB156AA4
+:10E7C000A91DF0516A45A38D354AE01F10107BD575
+:10E7D000466B11FDD18E4A798964E451E957AA77D5
+:10E7E000ADB5CF49E64C263C5A7B3FBF1F3FD9EC25
+:10E7F000B3DF6BAFF75E7B4FEA64A6058B192B780E
+:10E8000040D0824EC6EC8AC05826A6163DB5313699
+:10E8100082C19F669ECAFE524F09635F3468ECB3A3
+:10E82000018CFE28598C2DA37F30B67C41C8A640B0
+:10E830007FB5CFF2FE32EC5AD9ED907E837FAE8663
+:10E840007C25BBD503E599A270EB544A2D941AE5BB
+:10E85000465AACCFC3FDF8BC87AA3218FB5E0D53F5
+:10E86000136088BE45F01DF2CCC78203DC90AFF187
+:10E87000E42A589EB15815219F99CE7E88E591D5FE
+:10E8800036B659E8D9AF8AEB1A81F53CE502D4CB0C
+:10E89000EC93AC067028B1C29280EDCA0475B382C5
+:10E8A000F91B9F64E590CFCC51B11FC6823A1C3C46
+:10E8B000E516A877342B595D87DF837F906E047847
+:10E8C0008C5764A3BC0CDB292EC6D69575B7AB2A32
+:10E8D000F0507F557D12D400CC734AB3BF94E573DA
+:10E8E00038789CDD7008AE4EAC0E46C16324C20180
+:10E8F000DA0707B1EA966284BFA716FBC9B2A8E996
+:10E90000EB5221EFF497DE948CE304085E57E03C71
+:10E9100020AD82F5F9B0DF02CF4A824766B21A0F06
+:10E920001EA12B383C76CD7C4EDC00F5EA8A85A012
+:10E930001DE6F7C8B6A965B8CEBA694E9541BECEF8
+:10E940002BCDC37199DFC19E823CF32E78A80AF2C9
+:10E9500075351E759D42EB5E80E5B91909EA3A28C6
+:10E960007FF41541C37C9DDF194C80FCF7DB383EFA
+:10E97000D4B5BD20CD873409F1CE89EDFCA5534B2C
+:10E98000BAE7C3D86A9A4FDDC41379BBA1BD5F64EF
+:10E99000AA3801F2B6F04015D65F37213C10E17578
+:10E9A000F295846A6CBFC762F1E3387B360FD914E5
+:10E9B000107AF673D2EA69C5F59F84F5FBA1FCF5E0
+:10E9C00057DE0FDE0DF935800A6236ECD16AA502FA
+:10E9D000CBD7553119F7C5D8AFBD367F11E2D5DE9B
+:10E9E000FC44C20F9CA707E07C1CFF99C358FD158F
+:10E9F0009E250ACED3126A94B0DD9674C6C640FE38
+:10EA0000D5FB077A9D3DE10CED695F1C1223FC7577
+:10EA10000493828128BC7238184B1E46A9DF09690D
+:10EA2000D22A0E9FD87EEE519C547FB923BC177614
+:10EA30008ED5AF6A7664011E2D4854E87B82D5A737
+:10EA4000F583F9D8DA2A42FDA03C2B0DFEC27DDB0E
+:10EA50009C14C47DCBCA62DE17E3F45BA7D39BB1E1
+:10EA60002FCD698CF032CBC5EBFF4CA79B07F47A16
+:10EA70009BF5348A2ECC78EFF4BA914F6425326F2F
+:10EA80004B9CF18CF6303F2A37E6C51CD04F06B6BA
+:10EA9000532C84DF317417CC2C1986745795A8EE4B
+:10EAA00072203D0D730F0BB0EE710031DD53937B7F
+:10EAB000E201AE03E907D78574D65BBDE69D9C3FB6
+:10EAC000C5E2E5B33A9D2C425C87793F27003DC6FD
+:10EAD000DD67DE4F93C56D7914E6FB9FFBC5E066ED
+:10EAE00077CF7A46FA6003D0A09DB1FC8DB3523C3B
+:10EAF00025BDD7DB89F5AE84711B1C54DFA92AAB79
+:10EB000025E87FA2C35D26321C4F9988E3F9613C5A
+:10EB1000DCE7E409EC4B11E053DAD65C74AF1BF18F
+:10EB2000BCA51AD7355192A532E40B1E0B0B1571FB
+:10EB3000FEFD0DFCDFA73A91851CDDF91C6F9A29BB
+:10EB4000DFAFA6AFA97E7F5FBEA9FC8A55834DE5E6
+:10EB50006EFF3053BEA069ACA9FE80E689A6FC9585
+:10EB60001BBE67AA3F2878A3293F64CB0F4DF54B06
+:10EB70005AE699CA53BE2ED8F533C4735C7F1C3E47
+:10EB800067A4C71537EDCF444934F537B4CDBC7E03
+:10EB900089852D48EF29138E0E8B47CF465ACAA47C
+:10EBA0003361A31DF20187627914E6E17A5F0CAE4E
+:10EBB0008BB3EF063E1BF994D1E67D30F8C4C5F067
+:10EBC0002BDF7B617C31F0AAB7F294AFC5B87499A2
+:10EBD000E8E67429310FE3EBAF562FB47E6BECFA05
+:10EBE000994278FFAFAE3FDF3BA82D0CFD9CAD16E0
+:10EBF00048BEBC8745637AF6F751CC3A67AC4C21E6
+:10EC00007D86796E8A5BBF7B1EF7D23C6EB1335F27
+:10EC10003C384C7273B93BCFCDE9FD62F4F9893EC3
+:10EC20008F3F1BF4B9C64DF4C8DE138303A0AB7944
+:10EC30004DC2CE3E8017695EA72AAA909742AC2C9F
+:10EC40004ACE3FA2D3F7A3D81ED20D0D32F5F3580A
+:10EC50004336A51B1B14FAFE784311A5C10695BEC9
+:10EC60006F6E184DE993A08F61FA74C3644AB7348C
+:10EC700078A8DE330DD5943EDBE0A5EFC6FEDCA21E
+:10EC8000EF0FF3A4933C8B5DCF9C9566FA30F6852D
+:10EC900089C5D47E0ED0997801BED6A3BD383BE598
+:10ECA0004278B4EAA0FBF9DD517830DD9D9C7178A3
+:10ECB00008FC63141BF58D78F1F65F3528CFEFB6AD
+:10ECC0005E9C2E0C7C61E73F1B10AFDE2D49503659
+:10ECD00016F893FB97CD7E67EFF0E9C6A3187CF595
+:10ECE00000BEC2D75294ED39581EEE1B3DCE9FF4A4
+:10ECF0007D36F2D3A6717C8DEDF7419D0EA7237E64
+:10ED000042F98C187AFD422FFFC2CDF5F4FDBDF01B
+:10ED10008B46B745979F7CDFA7033EA2FCBC3769B3
+:10ED2000CE55DE38E3FEDDAD98E873C634F33EEE33
+:10ED3000B772FEB6FF4F6270759CFDBF587B633D96
+:10ED4000B1EDFEA0AFE773C4C911FF73E86DFFAC6E
+:10ED500064D2E7F75BBDFD33A3F667FFACA4EA78A6
+:10ED6000FB7EC66DE57456243394EF2C8D69A8079D
+:10ED7000C192FC36D4E558A17C18E9048C21A48BFF
+:10ED8000DEF15262870D7A12119E09A48F9F9D9623
+:10ED90004CFBCFBCB2C6A2FA67924C7AE9733F0033
+:10EDA0005D01C793603CD043996AE9DEBF7CFC3BC0
+:10EDB000B19B5F8BBDD3DBC5F0C0E02333908F5C8C
+:10EDC000405EF76C77797CE4E37F131F31E8989D10
+:10EDD0009F3FC093DCB37C3AF291BE8C3DECDE4F9A
+:10EDE0007CE49F869341B7EF73BA8DE527BDB66B80
+:10EDF000CBB888FCD3F9B9E46B0A035EDC2926376B
+:10EE0000AF8326F749BE5F62DEEF97D85390DA579B
+:10EE10009DEE7B6838755B2451BDC164DFD925DF69
+:10EE2000AFC2640FDA65ACB73EE9C7CF637E157039
+:10EE30004C3BA45F25E40519D80243F2397F121D2B
+:10EE4000E7FA1E8A9A9F5566FDA2F3652147BF43E4
+:10EE500051FB367C9F6CCA8FE8C836D51F75403190
+:10EE6000958F091799CAC71D554DF9AB22A34DF5CA
+:10EE7000AF3EA799F215EC3A53FD4AC75453BE4A28
+:10EE80009E65AA7F6DF65C53F975CA1253F9D84294
+:10EE90004F493EEA0F36679390C2D812B7569A0F81
+:10EEA00070484CACF3CD453B69B54B6613B076303A
+:10EEB00088706BB439E475C0A73E15B43C0678FA87
+:10EEC000B005ACEE02A82F8619A6072D6A19A6F97F
+:10EED000DA162FD269E9A04405F1217120631D28BB
+:10EEE000A7243581013FB12585DF2D44BADE06FB1D
+:10EEF00007A8559A0A8A3EDA013F480BA2FD9B9368
+:10EF0000E8ADC479ADB334BB56E33E5B98E729ACBA
+:10EF1000CFD4FB47437AF87A8B05F7B7B5C3F9C06E
+:10EF200058C80F85EE19A59FFDE4FBB8DF1DA28A26
+:10EF30006E9F87A7BC3809BFAFBC8E896259EF7836
+:10EF4000F6F98FB83D15FB7D7D3ED7AF322BB99DCD
+:10EF5000195B7E875EFEB92D7EF9C27C2E2F2AEFCB
+:10EF60009BB21ED767EDB032F45BACCCD4FAB00BD9
+:10EF7000E9ABE70A587078545EF230D989DF07D2DE
+:10EF8000F7CAFB66B3B093F7837EAC95095A1FF4BA
+:10EF90003B7C3E31FE3C96EBF3B49E4BEAA55F17FB
+:10EFA0007DFF3CFFC2EBB49E4B60C1F478ED9DF455
+:10EFB0003D3310BF7DA301A7B4F8E5F7EA70B29E18
+:10EFC000CB61FEF4E8769CEF748F934BE5D673A982
+:10EFD000CC1F771D19F49D656BD988373B81CE9185
+:10EFE0005F54A466D91890F81C16D9A301FCA7A2F7
+:10EFF000490078CA1C6A19F22926592361832E40D8
+:10F000007ECC65D2A7682F580019BF81A9DDBACA86
+:10F01000FA69388A8EA66AE63CC3FA51F2E630F6FF
+:10F020000DF34E1C5C9482F87E8A2929721CFC32F6
+:10F03000D2D90ED12345ADE7602F7AD2EF75381DB6
+:10F04000CC890FC7DFE6733D6AE46C16575FFB7D22
+:10F05000BE8BEB81456A9F0BC90D84AF373DBADF8C
+:10F06000D87DC8A0F24B8533E005C9F5C80F9C4197
+:10F07000F2537EEBF036F0A79F092F0E1728FC7B8A
+:10F08000D7BCF3A83C2FD7F3663EC9156520CAC587
+:10F09000569D7E5B252D699813F918AB8907FF8C67
+:10F0A000025D4F8D59772BD3B2E7A25F43B2AA4FCF
+:10F0B00031E487CCF7421CF8C7AEDBA1CF1BDA578F
+:10F0C00087B03D73A99CCF318F230BF47CFC172CA8
+:10F0D000A1C2FF8E15FB9FED73A9EB40053AA9CBAA
+:10F0E000ABB92C6C453EDC037ECE0C2BFA6D63E194
+:10F0F000E861CA1CA1E0E2F0B438E4ACADB0BE39BE
+:10F100007E1743FFCCADB399AB04E6E1FD41DADBFA
+:10F110001AD49977FDE0D235980E19DF2852AB6BDF
+:10F1200048DF13FCFDC46F865CBABED7E8F2162137
+:10F130005D1C129445B47E01D68F72A6EFF18173E7
+:10F14000A3E0B7B87FC5DE02F47B5999968E7EE2C4
+:10F15000ED76F257B10D8CF4CFFA1D8336A19CE900
+:10F160002CF0EEC67AA3AED1FDB65A64E08DC997F5
+:10F170000F27F86345FAB8189CCEE7733A3FE88A40
+:10F180008F2FE5057C9F2E954E320A381C22008772
+:10F19000CDE5DF3E9D00FC4C7C63B78E7F466AC0A8
+:10F1A0006DD464B35F77B7BE8EDD059C7F7416782F
+:10F1B00008CE9DFDBF3C9C8072DF06EB8F83EFD7AE
+:10F1C0005DE6FA7BA3936F8B1F1F4C8C3FCF39DF1B
+:10F1D0009179BE6ECCB334FE3C6FBFCC79C2FE2CAD
+:10F1E00072147CFBF3EC2CD05E2F403994167F9E7A
+:10F1F0003FB9CC7902935B14827A3380FF61BD6F93
+:10F200007BBECC3FB70AE5CF4D5EEEF72F014E8BAC
+:10F210007C08A6F2E437C351AF55D76E40BEB3C2E7
+:10F22000A5FA65E223AF237E031F641ACC67DA6474
+:10F2300081FC489D23BE5C2421BE67B1502AF2ABFD
+:10F240001D76F263C7AEFF67BA9C003AF925C28902
+:10F250004D890C447E7270607C3EF1CBD8FA4D1122
+:10F26000924BEB2AE2EBA5BFD2E975B9A37972966E
+:10F2700025FA5C0516282297F569FD50CE96CB6BD2
+:10F28000909FD8401E215C6DFD06F7C1FD80BC47F4
+:10F2900080B422FBCD03828BE07DA20B7EF9DDE3FF
+:10F2A0001C6FD827175A7BE7E7CBC41747FAE2ACA5
+:10F2B000E7578AF7D582287B71D99637E4C268BFB1
+:10F2C000380B5B18098E08F9AFBBFC057DD865F9D2
+:10F2D0000B0622AE64A27CF0907C40B9817673E389
+:10F2E000AB63CA707341EF6022F2D3E4449217819A
+:10F2F000BE638B9428781EECD21BC45EF4499BE954
+:10F30000FB470D0E3025BBF3B71C7DAF0AF5F8396E
+:10F310002CBC16EBCF599984478F5DEBECEAEF9C40
+:10F3200060D26BBBFB97E87B85C31912C188A970BB
+:10F33000FE3EEE7EFC4AD13EC1F5FDB8BFF629A6E1
+:10F34000B1F0F3DF373E95FC0708BFAB7BEE7B6F78
+:10F35000FB7C5AD14E607FADFD65C39FA3D2395C63
+:10F36000A2712E2CC9871DDDF0BED47D7910FF015E
+:10F37000767D52A1760EFBD758AD0FE733DBA0EFB9
+:10F3800018FD868D4E233F64A3AB63EDCE283ABCB7
+:10F39000D512C9E4723BBC169D4B7FDE9E40FCA398
+:10F3A00073FBEBFDBD748E66E81D49E23749973E5D
+:10F3B0003FC3AF604D8CAF471BE717BBACC585A4FF
+:10F3C00097E0F9EE68C80BCA02B4272599A90198FD
+:10F3D0006FC5B5804DD0DF4431B73D0CEB38CB4E17
+:10F3E000A45D85E0D3FDAA2BDF199180F39C2859F9
+:10F3F0008F47F3A758FF4F5EA1D9FF738ACD4E09FF
+:10F40000215C8AB87FA4F4956B52D00FFAF09489EE
+:10F410007D30DDD9D0244BD66E3F50ECFC2B7AB139
+:10F42000478714727CEF48D48614C2FA2A7A59BFEF
+:10F43000AAD73B94A8A98599DDFD61FD7871106F6D
+:10F440005CA9F37B1DAE37F9E792BE6571005F459D
+:10F45000FE097AAB28A37FB0D04AF4AE3145CE2264
+:10F460007F21DF7FE0EB12E4AFD2F342D307016CE0
+:10F47000B7F176179D7F33AFC2503E0060E83CA0E5
+:10F4800051F091BFC181F11E90AE13D40D22A4A200
+:10F490002592CEE922C8E3199857C2FCEB42388086
+:10F4A000F1016B1C3FFE25FABFB580C41226405EF9
+:10F4B00062E45FF41F4CA6F3389A19CCC36ECC4BB0
+:10F4C000CF27EBF9CEE993260F80F4CEC4C75D8831
+:10F4D000A76101F828F4F355E28F434437BE44D5C1
+:10F4E000DA17FD4A1F535E5891A80AD9E8777215BA
+:10F4F000A19EBA8A25AA7618477396F8715C9BC2BA
+:10F50000C80F9FC85A681D4EE7177E048ACC640155
+:10F51000F33989DEF98564A7303A1F3FFC71F26642
+:10F520005C7F827C2A74377C4A671AD54B8F918F17
+:10F5300099CE9502C56D78A418B9E81510FE7DAA7C
+:10F5400063BF9BE5A5831D94111F859027FB1BE0DE
+:10F550004F1D08B7F26EB87548DC9E33E0E69FE8B1
+:10F56000FB15C2D57FAF5D0E64F4EE6703008D42DC
+:10F570007DBC435EB415EB83C1C42CD85F365F9F5E
+:10F58000BFC6CEF741F26EC5F61F5AB365B4770C0D
+:10F590003C6B1EA8FB217AF1733C58C8F1B02EEDEC
+:10F5A000701DCA3906835AF2C05E4A3E3A12F90605
+:10F5B000C8CB26949709568DE06DC8CDE5ADB7311F
+:10F5C000A4ABBAB6B90CE9F543C13B6037D9238C7B
+:10F5D000ECB19993FD7B2C0AFAB0A6AD75427AB8CE
+:10F5E000309F9F67EC99B487D890E82CC176655717
+:10F5F0007BAA3261DC400953EF857A8104EFD6970C
+:10F60000705DEF882AFAB9EA5755B2CF86EBC80485
+:10F61000DF37CD48277F694665A411E30422F7331D
+:10F6200019E37A7AD0C77958DF48C69EA0B1A09F67
+:10F63000057208F12707F04D90BBCB9FC4F2029EE4
+:10F64000BF1AF2F57C4B59417BC50D23B85F8CA1E5
+:10F650005FACBE5D207F5BC1B4E1A4D71462794684
+:10F660007479EAB267215F587D958AE4A458BCBFDB
+:10F67000B803CBDF66B40EA6F3EF5131F43BAE9B7B
+:10F680006EA8BCAC2BEFABC4F9EEB98D91FD5AAFAF
+:10F69000CB5B13BDE162A14C1B89F8D7D50FC37EAC
+:10F6A0002AF5FC3849A67E727D4CE70B9E8D3FA55E
+:10F6B000F3018B8A7EC946A199E0C3FC3ED2F730A4
+:10F6C0005E06E9256FF6CE5D561C2C83D39DBA8F5E
+:10F6D000D35D39F38808AF91F2FD011C7FE66C37EA
+:10F6E000F199314719C185280FF257A50AB44FB9CE
+:10F6F000030A68DFC73BD42611F04814CB0A126016
+:10F70000BCEAD9029D4B4CAF760405F8E774A00F14
+:10F710008A8392BCEE1980EF33BD023FEF85FCEC8B
+:10F72000283F3C68C3745E36C3CE7C2FC4C1E7DC7F
+:10F73000019C0F1BEDEBD7D84C7E9DEC014E2AFFB0
+:10F74000BA70D261E2138CC7B3E4247A8E217F674A
+:10F750005233F1A9C316D0BF51FF651AE9DB37E96F
+:10F76000F46EF08BE9DAED64074FF798F5E80F7166
+:10F770004F900E6609A4E7CEACBEB09E7DAE50D0D1
+:10F78000CFF172E5C349DDDF15A6903D7D23EA394F
+:10F79000A5F07132E82151FAFDEC3BCFA752FD3EB6
+:10F7A0004F2FFFE60A40851ACE5FEA019EC82F2B35
+:10F7B0006649442F756B6C14F755DFB6DA9A85F8F5
+:10F7C0007C0F5339BE7ED2D80FE6D9AF561B212A03
+:10F7D000DDF0E9571B1490AEB390E710FC2336F42C
+:10F7E000C7CDB0A9B5B8AE19694CF6A7025ECEBABE
+:10F7F0006E23F6BFC6C16411E46DDFF677828857C9
+:10F80000C0CA55C449C01C8A67CB9593E85CA1C99E
+:10F81000328CE2B59A5CC96A747CD4BAD5DD78873B
+:10F82000715A8A9D0D93F5FD8D6727150CE0FCEA52
+:10F83000518191BCF0CF72109C330B789C52668A38
+:10F840006A0BA422BFE17CEA5181C7D73D6AF5E685
+:10F850000CC7383C502BF9FEF076B1749F99AEF787
+:10F8600093A4080120C669ED65E516849B3359C54C
+:10F87000B844A3DFCA44CD8A7CAB72B0302240F0DA
+:10F88000DC242D40FD34C1CCF7AD56BE2FEC23CE89
+:10F89000F763E520C801E2FBE8AF0F9493FC1A3F41
+:10F8A0006004C903EA6795E490ED2AEB21CF323C6E
+:10F8B0002C19FD5BC30064A8AF77647BA662DC9E55
+:10F8C000FF4D89FC69E5D5EACD0BA3F6F5E7037595
+:10F8D000BD7D62640EC541DDA3F6C338A83515DDD4
+:10F8E000798C77AC61CD36C4F79A18F9B8D4B99B46
+:10F8F000F4C8A54F5ABBF197617CA85A80FCA3F6C7
+:10F90000D91EFE20E253DDFC2CC6BE64F26BB89E0D
+:10F9100011C08F910F6985C922F995D96C2E47D9ED
+:10F92000D302FAC544D7AA26947B9D4272B358DE0F
+:10F93000CD2747E8FB759FE479ED6E5C37E84B4FC8
+:10F94000C9ACA71C603ED25F2680DC443D5A689F4C
+:10F9500029E2B81B1743DF788E2F852B317FE762B2
+:10F960007E3ECAFCB7D1F9D738BF5D46FAFF2A31CF
+:10F970006F8D3EAECF0ACCFA987C0FF5C7605F5012
+:10F980006F11901F4279DFC9D014E8605CFB11EA67
+:10F990006F633AA78B583D66B7C519B45890EFFA14
+:10F9A00049EE24B06036C24F2BE47CB6FC00E7B3CE
+:10F9B0002FFB4183165195F5DD34C54D7A20958F87
+:10F9C0008D308A9BD9CEBC75BABEE31F908951A2F7
+:10F9D0003ECEC7757DC1D0E3AA62F6F15AE7231285
+:10F9E000F2AD6BB37BEC9788FD4F6602E98BD729AC
+:10F9F00017E65B9AC19798992FB9D979DA3F76FFC4
+:10FA0000DE3BD04F1088D1830297A907A5BBBD1B51
+:10FA1000911E62F5A1DEE2289FD2F9FBA5C65182B4
+:10FA2000063107E5D758C3CE8AC19FBABDC7E73CA8
+:10FA3000C0BAF1AE0B9FFD9B6EC675803C97D1EEB0
+:10FA400013FE6B3DD1F51AA8278E47681E0CFC1CCF
+:10FA5000F2210BF3619C02F3CAA7114F0DB90B9C65
+:10FA600088F0A47121C7BB5112CFE782228B78198D
+:10FA7000181DABAF7BDDE887D6CA4B282ED690C7C2
+:10FA8000C32D1AE1C908A6A6633D034F46867939FE
+:10FA9000E0C76EC48F7193015FF231BE76543FD4DC
+:10FAA000BB2A9842F8511123D72A9DD324A4F34AA4
+:10FAB00047ECFE6B16ECF71A1D3FAAE47F0E3FAE33
+:10FAC00040FC30E416E8C9F7C5D817F7C5D8179732
+:10FAD000801F615CDFA5E2C7B101971767DB69BDD5
+:10FAE000E7637F39D9B33E31AF277E08ED772E7AB1
+:10FAF00000E93D90CC70DF5F48902B9D30CFFA1A23
+:10FB00001E6F3EFCADC200E6B396BB492F7C21556B
+:10FB10007D8DCA7DBCBCBC431393215FB012CA214A
+:10FB2000FF82DB5389F9FA55500EF547BCE70D60AB
+:10FB3000BEF01E5E5E76AFEFB56494F37EDEFED55A
+:10FB4000638DA20BCA838D7AFB8AE64ACCD737F144
+:10FB5000F6230F0403981FF4001FDFD03BAFD6F944
+:10FB6000E70BC2A9D7EEC2FE807F6E06FE39EE8497
+:10FB700056F61CE417C8160BE2EDC288DF8AF8704F
+:10FB8000D8523B12F187CDF366239ED9D16E15BBB7
+:10FB9000F997059D3AD06E826425BDEF0DC12761AE
+:10FBA000BDC94812286747AB0EE4EF1887BC19E4BB
+:10FBB000CD005D1E1971BB787F606AD47E0D18C8B8
+:10FBC000E5BC512F2B8DE3057B8CE38511571C5A27
+:10FBD000CF04F4B7E0DAC80FD123CED847F23BD830
+:10FBE000BF6418E2EDB5185F0CE5D78EE5F1C56589
+:10FBF000DF9C9E14CF2E2AD6C73DAADF8730BED702
+:10FC000004DD16A49F171079FA62FFFDFF88FAD26F
+:10FC10000B38D65802A99F8DC67DE4F9B103731E37
+:10FC20006E02BC586CF14988472C4F5071FED77753
+:10FC3000F8AEA1F5D43276434E9C75E8F27E51C001
+:10FC4000B699C78770FE335DDFB763F2EC3D7791FD
+:10FC5000FDEC52AD30CEC4F10388EEA7550B06DDA6
+:10FC6000570E443D184F30C89FEDA538F7252C6836
+:10FC7000C34196C4D0FD32E7998F512E2DDB62A689
+:10FC8000EBE52C64E3FEE6C8E31F40FF351B9265FD
+:10FC9000943FCB5BCCF56A36BC754028EDC9076A4A
+:10FCA0000C3E1034F3015038381F583F98CEBF56E1
+:10FCB000648BCAA174F47FF848DE27302EEFEF93EF
+:10FCC000D430D15FBB9DDB51BA7E7EA7C8F5F3046B
+:10FCD000E6509C45C8872D7A9C2ACF1BE3B398F841
+:10FCE0009653CDB711BF31E260008024EF4FF9AFDA
+:10FCF00095A3FD6C5D7C3E86DECBDAFB84F09E81B5
+:10FD0000E16701FD80EC2BB60038DD38E243B46FCB
+:10FD1000C252F87F0CAECB46EB5A9F9447FC7D1540
+:10FD20001084BD0CED62A924847D0EE6F4E4403A13
+:10FD300042FE3ED96C6F2530AEC70FEFE07E9C11BE
+:10FD4000DD72BF01F7D7CE540797FBCD0CE9AB5757
+:10FD50007BC5B932AEBD42120AFA9F3199F3F58BD9
+:10FD6000D92BBDD9235DFB99007A1BA4D3BC09CF45
+:10FD7000E3BAAF3E9F921C2F8E6A5A85E841BB6C56
+:10FD80009A55CB4C8B1727897A7666547DAF93FAB8
+:10FD900093BCE9CF63DC12F41B42FEDFF1A62D6EAB
+:10FDA0003CB2A4F72F5935395EFFD7A2532ACADFD8
+:10FDB0002E79B3A8DF6F415F7971601C7DC5B62BCA
+:10FDC000E69C92F90746C7133CA3FB0347166A6DEE
+:10FDD000D8FE60421EF13BA50CECA97E94A7FE0E56
+:10FDE000DE762DC5479C61DA45E323D644F9CF0F73
+:10FDF000A6C63F17795DE773368C7983716F57B468
+:10FE00007D8857476DFCDCE568A29EBAF8B9D51F1E
+:10FE1000BBEAF3F498C1272DBCFC689AF9BCC6A8CC
+:10FE2000F7B9EE873AD4E0F0AC89F2BF2AEBED3EA9
+:10FE300094D39905FAFD8D958CECE7CE5752374552
+:10FE4000EFEBD98115B62B33B19E66CB4138BEC2DC
+:10FE5000E55F9D14B6E1FE3E7285F7139C779DC267
+:10FE6000B417B11F256CBBA904ED061E17D269E5B6
+:10FE7000766067024F8D799D1D38D576259E23DDEE
+:10FE80001626BED8959F1A26BE7776A087C6ED9C0B
+:10FE90006E94EBF9FFCDF30A93559C6F8543B71F22
+:10FEA0008AE435E47705BD0FFD36B1E7078C8DE7B1
+:10FEB000FAB11EE7A9E5FE83CEF17AF3F35B1C1DD0
+:10FEC0007B7E0EDFE7E8FE606FDB977BEE56087FF8
+:10FED0000EE3B87383098CE2BDFF45BF7E67FF0E5A
+:10FEE0005ACFBA8A48DE63E5142F407EB5E5EDAF00
+:10FEF000135F5F6ED07DAB99EED3AEBCB473B5D853
+:10FF0000F3966F81CEAEB8320E9DFD0EE535E0570B
+:10FF1000953885F8DAA95681FC210AEB684438AF98
+:10FF200010F8BEAC78637EA50DF30B994C7CBE3502
+:10FF3000969F7903A8272C6B6224EFCA58410AC206
+:10FF4000BB7E9F883E04BA67A344F149BC67A344C3
+:10FF5000D9C578CF263A8FF76CA2EBE33D9BE872C8
+:10FF6000BC67135D8EF76CA2F378CF26BA3EDEB382
+:10FF700089CEE33D9BE8FA78CF263A8FF76CA2EB67
+:10FF80001F61BE47C70B08D7091B10AEADABED32E2
+:10FF9000C295F9B5778BB3489C11FEE17D9CE87E54
+:10FFA00096B926D996031CF6668B4C188DF76B967E
+:10FFB0009AFA5D26D6929F00D40E92233EF88FE0E7
+:10FFC0002916939D7CB64D80BD037D68438CFED081
+:10FFD000FE5023EADB4B82E6EFCB5894DFDDDDF306
+:10FFE0001CE8D62BF573A0BEAC2FE27395E85471D4
+:10FFF0009F4FBD27AA76A6BB00709FB7727F64197A
+:020000021000EC
+:10000000BB72FD78DA472B0B2A783CC2CB4F6D14BC
+:10001000837E77F7F9D0A97DBF3DEC857A8B734459
+:1000200019E9CE9E6DDEEF04C5BCDF4945E6FD4E05
+:1000300056CDFB9D32DABCDFB1704ED5CCFBCFC4C0
+:100040002904E765FDC0BC83F1D3279BF1C180EF94
+:1000500068F88FE3AB42F05D04F07D4CC073B507E8
+:10006000F6F6537AC2B9AEED211BEAAF970BE7075C
+:1000700010CE49DD703ECBC6573A09B86C9A63641E
+:10008000B7BE54BECF474102C7E4DC4AFD3E2F3F16
+:10009000DFD1E10AFA0BD90B51E7504DA248FACC57
+:1000A00063C857B58C64E203EA8624DAAF610EDEDA
+:1000B000DF42E625FEB43046AF59EC7CC4867A4D6B
+:1000C000EC3A7136E877A969E77A4DEC7A7BF8A3C8
+:1000D0008AE4503FCEB75B1E537199ED069FF6A29E
+:1000E0001F238375D8508FE98D0F7E2F5B7B1EF900
+:1000F00011703186F0E0A600FD89AB4FD6771573FD
+:10010000FFBCDDC7FDFCCC9F4AF318C5F83CA851E5
+:1001100094BF7F941424BF432EE3FE25C31E8B851A
+:1001200027CB15D6BC0BFD8AAF311D8EAA2858BA35
+:10013000FDF760056AA85F8F3CC3F5A7D18E968056
+:10014000A4F4B4CF0F17E8E7DC921EF77991734857
+:100150009C3FFA396ED2E3EEAE6A1FB507F35DE756
+:10016000923BDEE887FB357EC75BE998BE2B284FC4
+:10017000DD0DE3DF2870BC88B52B03DBC729B8FF92
+:10018000570B1EF2574C62BE5C6E8F0449CE4C700A
+:100190007849AFB538342B9D47E9FE4BC6C2935022
+:1001A0004F5FAADA681E6BE44F27A13F6619D3FDA3
+:1001B000316DE6FDEB610FC5D841B5B0FFD86FAC2E
+:1001C000DD13078F62E201CCF2FE87453A3C198FBE
+:1001D000575118BFF75DA3FB916A1C1B5DFC1C0EF9
+:1001E000E45C2EEB61374908F831745EF135E25B6F
+:1001F000561AD80374DEAFD8E2C5EB313983CED5B9
+:10020000E73BA7115F9EDFD4C3AF4378BDB0F922AF
+:10021000EBD2F58411F80DC6FDF3950AF7A3244E31
+:10022000D9A7617179475EB43E5B6FE3F772992F8E
+:10023000DD745F21BF88EBB9E5BADE54E3D0E15449
+:10024000E46F44FDB84B6FEA612FFE73F7638C785F
+:100250001780D78022FD7C677546F7F98EB18E2F07
+:1002600046743C1D027889C9D738903F2EEEEF1DA9
+:100270005204EDFA1F081F46BA614E85F4F5936DDE
+:10028000C7F68BF9DDEB023C7B741CAEA34D94F9F1
+:100290007D797FE338E8B7B38CE35DEFF6AFDF98A5
+:1002A000D7E878F332E2EBABC4E2947094DEEED49C
+:1002B000E17774B06702B62BFF63AE0BE76BCD6FCF
+:1002C000D9DB17F5E23BB85E0CFB4A7E10D1CA04BD
+:1002D000D44BABC4F3B763FE543693D1FECC48F293
+:1002E0008B2ED4F3E632F21331D5A722AA88FD8BE8
+:1002F000C94ECEBA03EC27E8F7A395F353F15E7F1E
+:1003000056F282D40227C637C15407405EB078F84F
+:10031000BDEC173FFE8F722C9F4D7EE95BECFC9C81
+:10032000D9FDA3BF2F233A604A9A7D0C8EE7A577AB
+:100330000522A922CDAF62D699E1A85FF53DEF1C59
+:1003400086FA590E9EF302488B74FAB8BA3232DC40
+:10035000E7EC865346417CFB254587C7C1C49333F0
+:10036000F03CC4B87FB13EE96D3A0F3FA99F9FE4CE
+:100370006B935310CF0F0E34CEB54299E8B2AA4B0F
+:10038000D05266E23CDF11199E9B9C91B594542893
+:100390003FC9F8FD0A7F8795CE8956DE5FD927CD04
+:1003A000D97BBCFE7F1471FBA636262EAA560AD92D
+:1003B000F03CABF65F8C8B6A058B3BDE7998B1FE27
+:1003C000BA54894943211598E742F5B67D2DC68573
+:1003D000E3A622CB05EF6D6CD0D767DCCBA8C37B3F
+:1003E00019F069E52B157DD805ECD0BA73E34CF70D
+:1003F0001FD05EC3F5D59D9B40DF2BEF3B6143FCD7
+:10040000C67EF00904E35E466F704E29E2F6461D93
+:10041000DE67488FFEAEF0EF5DFD6750F9333ADCE2
+:100420009ED96799BC39CE3CF7E870199C2991BFD9
+:10043000604888699BE28C6BD433DE35E86D5EAD35
+:1004400013C37370DE18171C6FBC97F57AC67C5BFC
+:10045000D3C28B3CFC9C7520BE5BD095972379372B
+:1004600046F1D3B3BA7FA0F57BE13C7A27E33A6E3D
+:10047000C7F6B6CF53FB7B93903F8C944277ECC981
+:1004800020B38BA11FADCFEC9005E5A44157BDED86
+:1004900077379C45D3FD979E70B65179D7BD33A66B
+:1004A000B9842C94438CF481F57F2CB5D960FC631E
+:1004B000161641BE5325E64E7A15F3603F205D1EA9
+:1004C00023D901E90691EE311D7BB2C08676D9A20F
+:1004D0000A1611816F1D7B37AF11E32E95B9A04924
+:1004E0008E0375678DF9FCB186697B93A1DDFC03F2
+:1004F0009E9410E4173C609663C7DE7DD086F6803C
+:1005000030CFE9C3B82298E7A45721BFB0CD46F752
+:10051000B2163D12DB9F590FCED2E56DAC3E7CB2D8
+:1005200048B73B46B29128675E6D68E3EFE6E8F7AF
+:100530001041FFD3E2E189A1073F9938F1AF4504AB
+:10054000AF1611F9D238297EFD5B8B39DDAD78EA23
+:10055000B4CDA5F44E67C7819F14C2F8271A644A28
+:100560005D83346110F49F37C86B1B04ED45259201
+:10057000F705F939F93928E01BE5EBF17E1ACADBFA
+:100580006AAE27D8C5DB6A481FEDC7E400E92F3EF5
+:100590001FF9D32DA09FA462FCC6EDA28BFC0DFC1D
+:1005A000DDA0317F59908AEBCDF8CDCC1710AE7815
+:1005B000C781E1FB2B155A19F2F775539D74DEBF05
+:1005C000C9E2A77E3050EB3E8067F09931BBD07D09
+:1005D0005ED8F2D044B4FBE4F69D21B4579A2C5F68
+:1005E000EEC5B884A6094C0D10B483344E7DFBD4FF
+:1005F00017B07DDE34A78AF74AD7B9B53239AA7F5A
+:1006000085453E463DF364AD85FCA6A7DA9EA0F382
+:100610002AB0EF22A87C9FAACD27BF9911F7436784
+:100620007F71FC862740BEB1A87BDCCB5B3759507D
+:100630001F1F821B15155765CCABF6DE50D6CD2893
+:10064000777F2D911CCDF8AFEB287EC02D2902C2FB
+:10065000F36641E6FAA8AE27CF62C69FE63DA89FA3
+:10066000CE433D19F0F0332148F19A16D6FE12B66A
+:10067000AFCEE6FA20535A46A0FF3A5CABBF4BB46C
+:10068000CC9A8AFA8D714ED01B3EF4E6E7819E1615
+:100690007D08E39E1418F99BEA2D913C9CDF716B59
+:1006A0007CF93A7D10C7BFBA81BE20C9F334263F1A
+:1006B00085F32AF4BA912EEB2CCA0AF27BBDE7A18E
+:1006C000F8904E414E33BDEF2237FF0EF5EE7A8B98
+:1006D000CCED9B035A199EC7744E2DA6F75E4E5A59
+:1006E000C379C44780EF615C56DDA017A649F8DEE8
+:1006F0004E5FD0BB20FFF3413B783E3FBCC802F9C0
+:100700005DBF7E7F9A0470AD1B1C3E8CF937077D60
+:10071000CAF3C3C28B707F8E0C8AF03C1A60806073
+:1007200067067D35CD0FEB3AAEFB3F991A9E83F3FA
+:10073000AC7BF54A4BB47F313C88F3CDE309BCDE9A
+:100740007137BBF546D43F8AC2741FC6A8B77B90E9
+:1007500011B7C9F17FC9B68410C6091BED5876FCE4
+:10076000FEEFD1DB2DD1DFC902FAFB2DD6DB9DAD2B
+:10077000A4D13E1F051E85707965109DF7CC1B9492
+:10078000A6BF7314CE4B2BEE39DE5294F32807AC80
+:10079000E67B6FF70FE27C9B15F3FEEBFACAA9B874
+:1007A0001F5969DCCE800D49BD8FDE2FD8A4EB55D3
+:1007B0007C7F3244B92C2093DC198E76F3EEF3B9AA
+:1007C00065643757C6C78B4775BC5812E0E344725F
+:1007D000147933DD37671AC6A3EC6E4BA07518F594
+:1007E0008F0CE2FA4578502AC78BAE7DE823D038CB
+:1007F000011D2EB900EF926EFC31DA5F6CDD5BFEFD
+:100800004DEBEEB14FE57C7EC67A187B88EF2BCCA2
+:100810002F15F4FCE3ABF576A38D7928440F4BB686
+:10082000DDB581F33F258DEC76F6133E5F87316EA3
+:10083000319D4F2ED7F560D1FFB60DED8DE54D1DE5
+:10084000F4EEDAF216FECE5637DD692BA3E92CA3BF
+:1008500080AF3343D43202448FB03EA2474D8F372E
+:1008600030E34F17BC63E9B8477F4A9AB93F85FA2E
+:10087000EB6D1F3EF8B6F721101F9E5DFC25067E2E
+:100880005DF4E8D6DB15039E95F7A4C737BBF62FBA
+:10089000868EDDFFE478FABD93E577E9F1AA8A193F
+:1008A0008F97B7BA2DF38ABBEBDFDFF290273A9E22
+:1008B000D6DE3AD78FF2AFBEBD82E26A97BFBCF5F3
+:1008C000777E68BFF4F99FBA3098FA98D49C857AFD
+:1008D00071ED536B5D1A9EB3487E17F2CD63417183
+:1008E00072BC7BABEA60415F1FD7C7EAF09FD0FFC5
+:1008F000F167FEDEF81F30FFBF0AA05F21BF6DFD6C
+:100900005B23DA6F7B354704E5F651293C09E5E8BE
+:1009100092B94EDF6A15E306CDFAD4D25FFD344BAF
+:10092000A1E06E7F3F0BE953A17ED8AEEE49AB8AC2
+:10093000F67BDD7BA20AC3B07A1669C4F9C5B6AFEF
+:100940006FF9CC867095411FCC1DD7B31C3809E1D7
+:100950007D7DEB7F7E29BA303DF6212BC5FEA2FCC2
+:100960001100F79A5EF432F760DD4FA9DF0B30E03B
+:10097000C38299A4DF047EBDBEF41398D78927FFF4
+:10098000AF4B288E9697F712BC4EB5CCFFE5AB4A1D
+:10099000EF72F524EA07F69E7A80D2267025BB9D79
+:1009A000A7B5D6900BFD02B59BACAA1F3ED76E7DB6
+:1009B000E2693C57611FD8553C7AACDD7ADA86EFA4
+:1009C0009ED50A5A44203D8BB98491DDFBB46CEB73
+:1009D0005FB8BF2A476453609F96FEF62CAFAFB155
+:1009E0004802D45FF6C227E4DFAAF53A7D8E38FBD1
+:1009F00054D9B2D31676C6D9A7964F26A11E14F89D
+:100A0000F557B40FC77608AC8FBB67FB9A4D7FB123
+:100A100021DD9C800D494FE5F042FBB4BE459C6B47
+:100A20004B89B76FA1EB51FF8372F2835C6CFF843B
+:100A3000C18CD3C5CB5B9F437BA0E643BB3A05C7C4
+:100A40007DEE761743FE2AF938BEFF626D9606E307
+:100A5000D658FD5932A5FC7BCDE377101E2E7EE7DC
+:100A60008E2CD2EB989663194DEBCDC1752EDC38E8
+:100A70009DD6B98879090F6B7EC1FD196725363976
+:100A8000DE3DE32D8339DFB2B3DB4A913ECE424FE8
+:100A9000E8873962633C9EF75DFEFE989DDD981203
+:100AA000FDBEDCDD83391FF1B3E0C7F8EE643DD84D
+:100AB000C5C817C477CE4EC27E56BA259F5DA6F52F
+:100AC000FB757809DFF0780E4532E24EF361BFDE48
+:100AD000A9EA8376B09D9DB2DD528EE7BB4C41FF03
+:100AE0006F543B82DB91CDF64401ECFC2359F1EFCE
+:100AF00011BEDF45F7EC5D16854FF55B8E103E317C
+:100B0000B0BB52B279FE31A443B08B52006E67DEA7
+:100B1000FBCCD617FD1D19163600E7DBF117CA33DB
+:100B20003553C1FA46FFF56D76D37B24F54FFE258C
+:100B3000869EED31EF9CF8089EF52C45417DF388AB
+:100B40002D32691B8E03E362BCE6A247ECA677C296
+:100B5000BAF1C5D6FDDDDD4D9F867DB558A7FFD81E
+:100B6000F5C7F2832762F801DB987949EF3ED55A41
+:100B7000834F237C6A815EFD44AF9CFE40478F0C0F
+:100B8000007AF8FCD9D7F6FF10FD742DD68C2934E5
+:100B90009A99CFD6BC08F48BFE348077828A7CF693
+:100BA0002B1BEABDD9956007C3BC3F77AA7829AD56
+:100BB00027DDC2F7B874EB6474AEF5FF8BBF2EEE81
+:100BC00085BFBE35D87CEFEA2C2B4EC13B0CC79FAE
+:100BD000597605F91562E06BD8BBB17C73F160857D
+:100BE000E01CCB37E1CF7E1605C7A5BFF982F0F632
+:100BF000AF39FC1CACEEC9BF91FC02B046EC80B72B
+:100C000075C12F29BF16E517E5774EC3F3EA9EEBB2
+:100C100036C333B6FC219D1F75DD73BB97F931EEEA
+:100C20002EB25DA4F7173A612E8DA89F3FEBA673F5
+:100C3000C2B5BABEDF29475CA89FAF4D35F2EC566E
+:100C40007C07A6D35F2AFBB17D821E7FE089B85264
+:100C5000A3F4A44FDA4517EA75E1209B1CFF3DC0C1
+:100C600000CD23CC7A2B5FCDEF6B89E79F0BEB7622
+:100C7000BD1DC60BAFFEEA393C373F2439E8DC72B4
+:100C8000C1EA992EBAFFD75EF07F102F16BE017011
+:100C9000447AF26BB61C80F37C0E02303FFC741E6B
+:100CA0002C2697EFDD06F5160180F19C24D69FB225
+:100CB00094795242EE9E7E1390833694FF8B411EB0
+:100CC00091DF7BA3B97C69FBE784674B63F0CC8B36
+:100CD0007896D313CFFA0ED1E9B68C95E9E7BA64CA
+:100CE000CF77EE13E93CFF948391BE81E7BCB063FC
+:100CF000EC54BB48FB73EA592148F186FE4CFE6E6A
+:100D00002BE03BEA59061EC6DAF7B1E989973E1A8D
+:100D100089F7C46A7FF7DFA53F87F4C4EF3E18B8B0
+:100D20000DF32FBF9FF7DFAC67FDCA1D7F233BA6E6
+:100D300073879DFCA19D3B5ECF43B9DCF9AA5D455D
+:100D4000FCEDBCD7CEE31A7624D3FB659DFDB9DF5D
+:100D50002EB0FDABD230C9AD357C1F87D868BF4FF0
+:100D6000B5FF9DE4C8A976BB82EBA8DF9144FEB134
+:100D7000FA571382E81FE8DCFED5C8E877AEFED547
+:100D8000F5D4E9F7693A935935C6CD74A6F238CB54
+:100D9000FA6D639E588DF648EB4E1BFAFF2BFFEB66
+:100DA0001FA5C8973A5FDC6943BE0576E9E30CF0FE
+:100DB000C3F39B9FFED49A83F7C518D9DB277EB374
+:100DC0007F3ABE8BD5132E1C0E9D00075C17C0A565
+:100DD00006F5B2DEE0B1F83B0B8F2FC99EA86D1F60
+:100DE0004574D40D1741E3DF93830E01D7FF8A0BBF
+:100DF000FD469DF920FF555CF757A5A83F5D6CDDCA
+:100E00008DFF53D66D6197B5EEA786F0F7C8BF7B0F
+:100E1000EBE6F83F64089757B174D013CF5FFE112B
+:100E2000E59F4B5669BE9748FF7BBEB3EBBFE47DA1
+:100E30002F45BFEDE5EEFBA1EFECBA2FB6EF6FE863
+:100E4000FB9E2CE3FDBACEEDFFC8A3F55EE2BAC56A
+:100E5000E2EF2A9D5F78DD5DFA91E871E0D35A0FE9
+:100E6000B0508702E9DA5EF414B5D86C8F88BABE48
+:100E7000B1960DD336A15D057A06DA016B3378BEE3
+:100E800009F40791EE0F52B00A6BCA55F97BB6927E
+:100E90008FC990B7BE3F9FE259D6667D8FE597E335
+:100EA0007905F7630456ABDE9DD03E906A51022A65
+:100EB0003E53B5C2BB09CAE5BEA28CF6CD5AE54683
+:100EC00047F43B1692D366B2539C31F64662A1CDED
+:100ED000649724B05D32FAE1135489E2FFEC2CAA46
+:100EE0003DD47715F373EB4416F4CBCECB87D32DDB
+:100EF000C5BADFECF2E1E4A07B95B20E27A669B893
+:100F00006EBB22911E2631B01FF93AB8DD0970542C
+:100F1000A2E0C8743B54D2412E29C3088E604028F9
+:100F20001347235C7D04C7408E28135CBBFBA3756D
+:100F3000C7EEC35A6522CBD7F57141FDF6E13CBC43
+:100F400098FF1E432C9C8DB4C05BB11AF5DF95ABA6
+:100F5000F939D78BBFFF1EE55BADA00FC37CC6A7D9
+:100F6000781715A3DFD1A30948A72BA7F27705CBE4
+:100F7000F11E58069AFA3C0E37C391CB24F25782E1
+:100F80009D41FE4A99A1FD274E642DE40FF448319E
+:100F900071BD32C53D056EE3714FAC8829FC9D16CD
+:100FA00073FC8F7F222BC2B8862AB1B619E7758AE7
+:100FB000253763DCA5CD1ACA23FF707F9085E86FC3
+:100FC000A9F8EB462C77835ECFF03E9914FA18E32C
+:100FD0001BEE145318C55545E05314DCAE3EE760D4
+:100FE00052149C2B58AA297FA2FFE156B413F2FD9C
+:100FF000761983C72A1D39A6F62772CED17801BB90
+:101000004346FBA84A769BDA8BAE7D1FA35DF37641
+:101010009A85EC826BB30799DA5FFFE9898D737566
+:101020009CC575DCF011BFA70AF6D6E36F42BB770B
+:101030001E610CFDC6D72965A6766DBA7F2552655F
+:10104000A5F766BE5F34C6346E5B7817C1A53693CC
+:1010500009781E5C6B0192807A3F502B4CF56E181C
+:101060007D9DA9DFA9DA5453BE76D55F9994CED879
+:10107000B855E719BE1B58166A31B51FBEAFCD541F
+:10108000DFF52698429096BDA704301D7590DF23AA
+:101090001D0EFB81E71B6DE1792AC6EB94E005D0BC
+:1010A000723C16F0546218F2C8A3BED730BD58FC8B
+:1010B00032D3DF634DD4CF5FD759822D73DD18FF54
+:1010C000D3FCE04E81E221B7158F40377473650A77
+:1010D000541F7BAEE5354C5B3BC6378D2DA76B436C
+:1010E0001D247F9D163A17A812DB4B05B27F92860E
+:1010F000DBA3CE5D7A7BA7F3EEB28AB7900ED664FF
+:101100006BCD3B91EF4FFC688E98DFB31E93A548E3
+:10111000349EDF5DE6F933C69D197152899522FF31
+:101120001D8A6B799C4CA3454DD09917E907F22491
+:101130002BC5F1CF2DE1726064C7E6166739DA9DE1
+:101140000E05F73531DD7CCF7BFE687E6FEF8B625D
+:10115000DD3F2FC999B79460FB64DE1E7D7C38DECD
+:10116000140BE9533BAF3A42767AE20D96FE2041EA
+:10117000996BB46A41BB7BE4BE3FD17B04AD53F2B3
+:10118000D7EF82FAADFBFEC40428EFF340D95E2B03
+:10119000D2D9688B8CC7F5ADA3279E2EC4F229EF58
+:1011A000524CA3310FD739812951710F734B141A47
+:1011B000DF2585E91D22D73989CA5DB3554B1EF657
+:1011C000B7CF4ABF5BB3E22AAEEFAD1894B815F1C2
+:1011D000D47540E37150454E6500D143389BF88289
+:1011E00014CEBE2599C753291778CFFFF89611A9B9
+:1011F00028B7D22BD454F47BA66F15BBEE99E17CB3
+:101200001FC4BFF020DDBF76FF3550BE0563D57823
+:10121000790878105B67D3CB9105413E5DD0CBFD5B
+:101220006B675CE3A477174DF587E677D5D71CD9B4
+:10123000DDFDF7D9BA76FF9A6284F7280BC69124B0
+:10124000FE5F2BBD2BB0629093F4871540BF4CE836
+:101250007D1DAE73491781A78BCA0F094ACC3BB9D4
+:10126000A112CCE7E57AF34A005FAF389F42F7FE60
+:10127000CF342590BCBBE2FC0DF42E67AB4DCBBB4D
+:101280008BFC3509145F36F5B6CF37AC423ABEFE5B
+:101290007811C62418EF54D6CB7F25FA37E2EABA84
+:1012A000E087F80A78FEA0A53B8FFCC0D50D4F0D56
+:1012B000DFE35A17055FFC6D97A93A3C676E5D3F07
+:1012C00003E1A32C989C8D74789A39298EEFB4FC95
+:1012D000F40C9CEFE92D560A9A6DD5F9A3BF487F0F
+:1012E0007F20239C8DF7F04BDEB150FCD141C0072D
+:1012F0000DF0A120F44E5A09B6CB90D2309EE1F405
+:10130000F8F7E99D84D3F7300A265E1AB611BC5A65
+:1013100033165456A07C3BA0A4A1BFC1806F8BDEC6
+:10132000CFBA326D6209C947FD7E8836F6B2DE9BC0
+:10133000DC79D557740EB0C60D7A7D2A86189F6B5E
+:10134000C4F72457B8AD248756A4FE755206E27B35
+:10135000852382EF3ED4AF3A43F0856EDCD1F7BEF1
+:10136000A4732253A2E2B5FA0CE5FB2F491AEDBF94
+:1013700074CE46E5B5AB4E139F36DA9FD0CF53F10E
+:101380001D46BC1F54FBB548F74481FF3509C330E7
+:10139000DD655B117D8ED3F265175F1F6AC1F79F14
+:1013A000DE4D44BFE454419E8EF3FB6DE99919185C
+:1013B0001F3035419E8EF105FFABF4239EEF2F4F7A
+:1013C000C77882755BAF9E89F1065373E49F5A40DC
+:1013D0005E6D7B6ED64C2A77CB7FC2FC132577F2ED
+:1013E000F264BEEF752537CDC4F8822A91D3C1A926
+:1013F000A6A4A0FD0274B078D53616FD6E6D8F726E
+:10140000FD77A35835E7735FDCDF8FDEE964851D68
+:10141000141FB6BA44D0E3D08CF35426E3796A465D
+:1014200001D3D0BF9CF17202FFFDA1431D7908BF1B
+:10143000231B6FFF11FA4F970B8CDECBAF65CA48A9
+:10144000A4AB7996F0C798FE66B8B789E34707C59D
+:10145000B72E5EB583E6F789AAC729CB9162CF3F45
+:10146000F52E04F41FF75D08735CF1A7166520F6EE
+:101470002BE970992776CCB1F179FDBC04CF87D2E6
+:1014800076525CB324776479B9DE5444F6527622FE
+:10149000BD0BDDD8F7C3D278BF77D0D200F21D489C
+:1014A000EEC586364AEB87325A4F1F296C53A19FEF
+:1014B000BA035CCE8CECF8D4161DBFF88A2EA75266
+:1014C000F4DFB58A8DBF7D459743C6F9F6F2BEA11C
+:1014D0005CD4078D7DEDDE9750AEBE2F0CE79B915F
+:1014E000FEDAB3F8BE09C6B5DE83E7172F2784D02E
+:1014F0004FDD3B9E18FBC068BCD644CE37222F255B
+:10150000909E14BB8E3F76C957BE9E233A9EF4B67A
+:101510008E23B88ECC7FDF3A8E207FCFECB91E832E
+:10152000BE8DEF067DF76CCFE77FF978C7EFB15D31
+:101530000CEF0CFE53C7BC45FC7E34E73706BC8D70
+:10154000791A706BED25FE565AF58A693D52C744EB
+:10155000347298AD349FF3B796EB18EE87B4AA9D1A
+:10156000EAF5B61E31F90C9DDB2C55980FF5DCD849
+:1015700075D5B2166AD7735D11E2C7CB15CE8F7BD6
+:10158000C6ED47883FD7813D86FAB7B1EE2E3E0DB6
+:10159000EB47FABE0A180EF14DBC3B28A03DE135E1
+:1015A000E9C315784322FA9CCA719B295F25DF6540
+:1015B000AA7F6DF66A53F975CAFDA6F2EF173D646E
+:1015C000CAFF40FD598C3EBF29469FFFB5A97C7CD0
+:1015D000B883F4EDB71B26533CFA84A311D2BB4366
+:1015E0000D32E577356453BABB4121FADFDB504455
+:1015F000E9BE0695BEFFBE6134A56F3668947634A9
+:1016000078288DE51BE51DE172F4E78FCE48A1F344
+:10161000A707867AA795E2D1C27B9162C4BFB107C2
+:101620005A5E43515010FCF263AC775AB651FCE15C
+:101630009A9D63FE703BE4D3DF1459827221BD484A
+:10164000645A14FEB8A684199E77BB187F0F2BB678
+:10165000FEAC521E4756CDC2FCFD805574E2CDAAA9
+:101660001DF21E2D83C44604EDF46AE6233DD4B278
+:101670008ABF4B53CD54568EF6AB97F91EA0F82374
+:10168000F37B021E6DEADADF42F90CBC670AED7FDC
+:10169000E86CA17BE42FEE4BBBA60CBECFF208F4A6
+:1016A0007B1E0776DC778783EC5DE3BEE98796CB0C
+:1016B000D127669572FAEA14D40E9CAF3F95BF57B6
+:1016C00014DBAE545FE7F58108E91F11D03F30BE4F
+:1016D000CCA0CBA9F2217DFD8A25650CD2C76ABAC0
+:1016E000CF50DBA1A80180F798439C2E46005DE017
+:1016F000BE8D3DCAE96024D001C941DD1E34E80039
+:10170000ECA7D7B0FDA9834C453BA271C27F8A6884
+:101710006F8D39130C607AF5F9C8CE6FA07C5C0729
+:10172000FF7DA48BD98F865EDADE504D78B4A3C1DD
+:101730004B69A8A146C74F1FE57737ACA2FCDE0670
+:101740003FA5FB1A9A74FC6CA6F2371B3650FEEDCF
+:1017500086A08EA75BE87B1F5D9EF94B653D2EA999
+:1017600042B72B78EAD1565BE95E3F7C427E528DD0
+:101770007345FCA81182C8BF1BD3FC56CC3726E2A8
+:101780001EE0ACFD54FF66270BA11CA8CDDEC6F5FC
+:10179000B0183CA9C8B889F0649A1EB77A20ADF198
+:1017A0000E1BE0C3899687ADE6F7452F0F2F963ABB
+:1017B000D7D03DBE58BEB804DF9F107BF243C6545D
+:1017C000B5BC9CDFE7C2B8BC4BE5F7B2A543BF1F71
+:1017D000C6EFBBD4E53A29AEF6DF2767645DCEB02D
+:1017E000B958BFCBDE4E3C3807DFC3EB0197187BFF
+:1017F000FBCF57F2F686BD0D7A26F9A13A8322D99E
+:101800005F35EE6617D9DBA3232EDCCF25DB4546FB
+:10181000FAA2C4CF771763470AC6F184F68F23393B
+:10182000B3722FF2A5A5FAF96EEC396D1D9EEF0A81
+:10183000F1E01DA638FA65FAF96EECBAEBC61FA105
+:10184000F3DDBA8BDC23FD53A9391E23F6BE6E6F80
+:10185000F882F103D1EFB79E3CDF4076DAC7A57777
+:10186000AEF78FFFF7EDDFC232CFE7A53C6E9AEE01
+:10187000C919FBD9A8FFFE66E34407DD5BE81C211C
+:10188000D37B379D027F6FA7F36F4C5DADE07B3A52
+:10189000F26E940B57AB36E2ABA3C3FC7D80F178BC
+:1018A0000F31CEFB00571D0A0692B1DD413FF99F73
+:1018B000C6BCE70DE03DDB516F6A229257D96E8FAF
+:1018C000887860C827435E75D3957E4F0E63300AD3
+:1018D0002E9DFE9405A3B351BFEBB25B9D93E85DD3
+:1018E000A2D32146D1A3861F6CF8414DC47B0823A7
+:1018F0000E7903286F1B753B73D409BF9802DFAFC5
+:101900003AE3233B680CD8A9F8FB31786F5A8B82F5
+:10191000AFE1C732F89CC1D78C7B7AB2CDBB05FD55
+:10192000CDECD5047AEF2576DE7943B95F68717F17
+:101930004FDE50E47BFABDBC2AF1FCCE6FD02EE81E
+:10194000E0F101579CEF7C1AED9E952F25D1BDB497
+:101950008BDA07F2E9B8FAA991D65BF8B9C9B04AAF
+:101960006538DA9BA8B7A21D6AD8A5B1F50BCB26BE
+:10197000960DCDC4798DEFD010BF65CB05F1BB7E40
+:10198000D59717B40B8DF1EBB78F90E7459D1FD41A
+:101990000F35CE57FEB977A7AF8A549BE4D8775D51
+:1019A000EF033A2C47FC429B15E5D40F7107601DED
+:1019B00037B310E92BB7E8BF5B712BA8E0D1F76212
+:1019C000E7338DF8C31ED5BB08F765218BCCC17CEE
+:1019D000BD10A9DD0620FC62C238D9ADF494D797BA
+:1019E0002B9F13F57BAFB170BF6B28D7670CFEDF61
+:1019F000EBFEC4F0FFCE3299EE3D77BE34CE82E7E7
+:101A0000369D6F89F45EEA3A0BE72BFE6136F529C5
+:101A100015DF1F997D8DE10FC0F8B258BEB2C5A287
+:101A2000FEE17628F7BF9DCEE2D195915E8FFA2830
+:101A3000E061CAECB094EFA4F7D3D721BCBADEEFD3
+:101A400040BE7205C0FF137E3EC79608E4F76C6B7C
+:101A5000E5F99285A934BF4BDD0FE839A914D6B159
+:101A6000B0551A86743A342D928FF45532E6833489
+:101A7000C189BFC3CAEF4501F89A585AF73CDFD273
+:101A8000E1F997A1DAE338BFA1691DEB1E463DF1EC
+:101A9000250B43FFDF9131772D6251F2F56B75E233
+:101AA00013C82F9E17F4F7E5B6F3DF21801659D13E
+:101AB0007EAA3D6AE5AFB15E0BEA5748579E57E8EC
+:101AC000FEFD5499C3925D93A9FFFE63242FDEEFC0
+:101AD0000119E75043513E703F22BD07F6BCEE6747
+:101AE000DC39F4C3996B90918722F9388F2309FC74
+:101AF000FEF3D7AAF7555A07FA6B711DBFE076FEC1
+:101B000091541FDDFFF800F82C9EFBFE778383D2F3
+:101B10008FC0CEC1F4CF60E760FA09D839987E064D
+:101B2000760EA60BCF41A7B08F15AAF6C6D00BAC88
+:101B3000A3773EC1D7D1D9CBEF2AEDD2E15FDA7AD4
+:101B4000E8DE24C4833691E29A4B5E9248CF3CD9BA
+:101B50003ECAF43BA24077FB711EA56D7FFC09DEF7
+:101B60008F2E6D956441C1FBD4A7B3286E30667E7D
+:101B700008073C27886CB7F1DF3FD2E7FB7C6AC7D8
+:101B80003A6CFFFC4BF938433C7FE178B8DD1EF737
+:101B9000F7818D38B99FE972FB067BA43CFADC30F3
+:101BA00036AE8CFCB963109F0BFF80E3F8F7896CAD
+:101BB00000E1A5D94F91AC723964A425DB6D145FA7
+:101BC000FCFCF6FD377E1FFABB7EEC75A67775FF31
+:101BD000819B9B8978FDB7C71ECEA0FA320E358B4C
+:101BE0006DAA92A1DECD8E9D7B70E9B7C89F54A5EA
+:101BF00042FED66C612FA67315F7A43405E71BA42B
+:101C000071E61755EC45D49AA24EB5F1771C453CC8
+:101C10006BECE28F958E247A0CFAFF01C9CDB6AA3F
+:101C200000800000000000001F8B08000000000082
+:101C3000000BED7D7B7C54D5B5F09A39F34A329395
+:101C40004CC2041220709200060830249390902019
+:101C50002721D088944E225A54D4915A44E53122F7
+:101C6000AD694B9B13122084A04191624518285AFC
+:101C7000EDF5ABA9052FF6AA77824AD55A1B149F1A
+:101C8000A576A4D66AAB9282D87A6BCB5D6BED73E6
+:101C900032732693F010BE8F3FBEF0D39D7DF63E8B
+:101CA000FBB1DE8F7D7600004EE27F33DD83001CCA
+:101CB000C03F54FF4AD630808268FD1239DFD07EA3
+:101CC00069C178433B4008A004608EB7D8D06F52FA
+:101CD000464F5ED00930E1A9CFEEA8F4E0031384AB
+:101CE00047633961EFA76FDF82E5DCA957FA241952
+:101CF000E043E8B862BC09E083B2F55BEEA6972D3D
+:101D00008A2D7B30C08DF43BB67F04E1D72BB05DCC
+:101D100072AD3C701BBE77739604921760F136EB80
+:101D20009148CC3A96813F2D8CFD6EDE6D7C0E1075
+:101D3000B1857D00B7049CC13637C09247B0DD61E4
+:101D400068E77197EEB3B9A97D1958A2EDB9000DF6
+:101D500087731F7D3666BC4919DD77DD8DE34D7ACB
+:101D60007C9EBB19D7F768F9E74365DC67A1D7E527
+:101D7000793F053B4C812927252C25A719B0DF8900
+:101D8000E7A59084EB9A297D911A29C4E73599003B
+:101D9000D9F89E49FE6D05B6AB2F48F0008EF3F7DB
+:101DA00046F9D167AD343E5CE7C77E27E9673ACD97
+:101DB000BA9AE1AB976F35E2AF1701FCAED1C1E53E
+:101DC000EF1BDD5CFEA1318BCB771B652EFFD85856
+:101DD000C0E5DC5720D089E3FDE91F930106D13827
+:101DE0002A4066B49C64F39A87E23A7A7E23857629
+:101DF000E17E8F574E49035AE717387FA98607249B
+:101E0000813ADC0394E37F37EC7C2EDBC7CF551798
+:101E10004EB5EC1F122838EE0D5E9358E792AEE7F0
+:101E2000B23DD17658F9AEA13FAC321D30D45B72D1
+:101E30008DF5F6AA03B1EFEB70882F6FDC76AB2D32
+:101E4000E0C272B3490939FBB6EBEB99B93F4931AE
+:101E5000E1789627ED213BEE6F995B0105FB5B0076
+:101E600094CEC2BEEF0134F17B574A10EC4C30EEF9
+:101E7000721A17E136677F12486731EE5B481BB470
+:101E80001EF53FEDA107F0BDB7D214F0C7CCF35D4E
+:101E90006DDD1FA7777CFF33ECF7F113404FB00ED9
+:101EA000F3693D13F7FCD96CC67252B2A09389EE68
+:101EB000883903CBA38BFFB9E5750F93A9DF743184
+:101EC000B6E7F5BCEE4094AFEE9CB9D581787BDBEC
+:101ED0006C06180A02F165D81FC7A0FA06EFCCF904
+:101EE0002DF8FBA5FB93C2E6B3D8CF06E4452A271D
+:101EF000550B7EBF96E846CCA300F2C3F235A0CFC7
+:101F0000AB907CA0FD53FD99CEDA3737D31AA0678A
+:101F10000BC9878F00C26DBC7E253596FF973FF5B4
+:101F20002DE6CF25D9C8F748EAB04DF0AF03FF9DA5
+:101F3000CC237E0DCD72E27A6F0A23FFC3F9E7FF4F
+:101F400087BDCE289F5F9490CF5FB914EBCB9F9055
+:101F5000BC766C3EF6E468C14F1ADFEB7CDE4B4F7B
+:101F60005B25E64BBDFEC993526D2801BC376974F1
+:101F700091AFF4D4D37C2B9EB2401BAE6FC5B48B13
+:101F800086C48EDF875E5B259063C67FF469FB6243
+:101F9000E217197A06D721FF4C7AEA444655A12860
+:101FA0009B681CE8D0E44DCF08FF0494D726FFEFD0
+:101FB000BF87F301E2F101844F75D6FC1C9ABFDEA6
+:101FC000094ADB6406CB3C07CA89CB0488E0B2B27D
+:101FD000AB7300E1B90DD12521DDCD53EA5EBB1A0B
+:101FE000F178B939F05592F36F79F379FC2B5C2BCA
+:101FF000AD606672CD31E178F3E7D98B693F739BB1
+:10200000055DBF96DEF3113D7F6D5A8AA919DF7B0E
+:10201000CD042D9011DDC76B567F4E90E9A7C6FD0C
+:102020003EE2C7A48C934EA6F42F2F8892DFD7F1FF
+:102030002845E5DF4CC9A9D23CC7DC66A67B4B76B8
+:10204000BB8DD67513840E2838EF326FD846F2EF69
+:1020500016705BA8C4A2A7973E88FE2AFFD9751206
+:10206000DF5FD62D854CD8BFB3B1132C88DFC71ADC
+:10207000F77139F28B912DC3101E2B27DBBC6DA499
+:10208000B734FA32AB263899405FF5A54F4BB41DF3
+:10209000D75DE57086A5547A6CFD28761D3FC85142
+:1020A000FEE945B8AAEB2AD3DF4715CDB43032BAE2
+:1020B000CF49360027C9F9075258CE7FF874A9993D
+:1020C000F0F4E18BD69089EADB2F7AE3361FD781D3
+:1020D000E4CD87195EB38DDA33F2422AB6DF6806A3
+:1020E00095E432EC1272EB9969B7BF43726CE50369
+:1020F0002E93DD24E858461340FAC9C677EEC57121
+:102100006E4266B57BA37A63C9F49F6C7904E9607B
+:1021100089B9E38E4A7C7602C213DD08CFBF9A3AB2
+:10212000C790DEFEF3FDF6B099DEFBF1D85D128EAE
+:10213000FF5C6A207B32E9A92C65482E3E5FFC4A91
+:1021400026B4E1FB337EF2AF97496FDEF46826F3E5
+:10215000974EF733890F713D47910F693DC79ECC6C
+:1021600067BE8BE25FC06129CA034038AEDFBDC9DC
+:102170004FF8BC2159667AB440501946F8DE773DD5
+:102180000490AE8A24934274DEB31EE165EA4B4F9D
+:10219000DEC9667E6F8919F52BD161402E26781C29
+:1021A00035C9451A5F00ADE7C8D36377B5E1FBB524
+:1021B0005AFF28DD1D5EF65F4477DBEC5E3B2EE1C7
+:1021C000A324A3DED7CBCAC9E9DCFF46C7A7602991
+:1021D0008E3E5FD6F0B9B15E080AC98DA266B9F825
+:1021E000562C6FD3E03E63AC7F3AC1F1E6CE4D8F03
+:1021F000BF24D3BCDBBEFD36CDFBBC93E785970483
+:10220000FC8E9A847EE9D5AF8EBFF1F8003B797ED3
+:10221000FDF99FEF7F636200C7FFF3DEF16300E922
+:102220006EA1D4FDFE7D88AF4F5CDDEF7C0FCBC788
+:102230009E7F6530C12F7EBD4B1A8E8325460E7D55
+:102240006432F17E97D03EF0F97F14FB2F9F5CC281
+:102250006CAA10DC16B64DD845F260A654984676A6
+:10226000D3D10F8DEB8B5FA73EBEBE3E7D7CBDDF25
+:1022700042823FEE63F22437971FDBBA3F21FC7E98
+:10228000FCF87813B262F47946F7C4F4C2289EFCD5
+:102290004A9395FA5D41A21E5131DF21F03A7FB198
+:1022A00029D49CCBFDB8FD6A7C4E78AFF234737DA7
+:1022B0009E13F519F65F92F55FBC2E12740ED46B67
+:1022C0009783FE53B7E617D8EFCD15A92C17E6DF95
+:1022D000D861253BB7579EA96F9B4F8E3F73798678
+:1022E000D093DD83817998F427E0E62C589FA6D51A
+:1022F0004D65BF6BFE05C9E7DB52BD129A8CB05825
+:102300008630F1F5310811BCD79A826CEF39480F4D
+:1023100060D966F26659B094CC3D8380E70909BB69
+:102320000A0216AAFFCA1469067C6F8DA73A8BE8C9
+:10233000FF4D70FAC92EBA3C7DED0492A3D5EE395B
+:10234000F3E979BD9AEA6EC3FDB658E50D8564FFE1
+:102350005C2E79C9EED5E1A2EB8FF916AF95E03B83
+:1023600038287B55A4DFE297148789E1EF5069DCB8
+:10237000372CC14C5AD75BCECD134C66B2D342AE8C
+:1023800009B8D9B75FF969C96FF0FDDF81328DEC0B
+:102390008179BF72B01CBF1E64E6F76F80C272FC09
+:1023A0009B10E0FA8D10B17E8AEFFDA1FC7F1ED854
+:1023B0000FD17DFD61EA677BC9AE9F2F7566E6622E
+:1023C000BB5A0D05A4677EE9F8C18E08AE4369B615
+:1023D0004012DA57BF243A25FBFDB02BF400F6BBC0
+:1023E0003D797B6A17D62326617FA9D5C147A9BF4E
+:1023F0006A067F3396D9C9815F101FFE30458CD3A2
+:102400006071B8493E928145E3BCFF8E8BE99DF433
+:10241000EEF558AF406C11BC8E660A7A53FF062C5D
+:10242000778F5ABDDD0A8D7B42F63E40AFCE30F34A
+:10243000FB7052E67554C4E917DF7833BF0FFF9481
+:10244000F9FD693D16837EF14D32071FC3FD4DFF37
+:10245000876540BD737991905FBE41E660227BF055
+:102460002F1A7F2184245A4FF33E53A88D8950D8C8
+:1024700007153A3D42642DD15B254090E81EF6A138
+:102480001ED3E7C9E3FD7FA2FA880EB19DEDC1CE50
+:1024900067484EDA83824FB03E83F6E3088297ECBA
+:1024A0003554C860C17A12BE28E4AE1BC88E6DAB2D
+:1024B000824EAA4F838844F89E4E9046FC5781CCAA
+:1024C000743B0314AEEB74FC1550B9BC04425C5E63
+:1024D0000A61A1EF416EF939CEFFD50F40EC675C80
+:1024E00098E91D1D1937DB8197DC6826BBC3F7F51A
+:1024F000C4FE426A910E174488E7F4E1320B025998
+:10250000627E010F3B3DF745E1E188834712C1C37D
+:102510001B8507CE21E0D107BE023ED314840FCA2B
+:10252000A78BA147A27914CDBEA9062F9735E0E766
+:102530007200B83CDBE4E90B97B248C012284C00AB
+:102540009F1989E966884657BF2E022E75F933BB5D
+:102550004866B8E97208F9338BECD178F9A43FF7F3
+:10256000A5541F97911E7C45E9575A509FF98AAB95
+:102570006FCBC7FA8CC76451AFA8FE451ED667164D
+:10258000E589FAA4EA622BC2ABC9947F650DCA99AA
+:10259000FC80690BF1E5CA26B4AB715F81A43B8274
+:1025A00044C7A60C709BB07FA0A9C45B84F500D281
+:1025B0002520DCEC526E13C1D9FE3DF036E32A52E1
+:1025C000D302138B70FD850BBAD70A7C560F998FF7
+:1025D000FD3FEAB6B2DDB2CE160C129E90DDDD4DA7
+:1025E000E5D1FD7DF4D8F716D3F3C786829BF40BB3
+:1025F00078E462BFABEF7ACC0EE0FA52941B14FF82
+:10260000C0F92A69BE00AA2799D6F5732944F05F5C
+:10261000D93493FD81DF16F8A717C58E8FFB90265E
+:10262000D3BC42CF8127B798E03679AC7F368D7323
+:10263000D485F2358DDA051EFA2B571629B5346E7E
+:10264000FC7373CA17D72EC37996238D909CBEA6B0
+:1026500028F0351A77B93932A2189FAD4E79C7C61E
+:1026600074A1207D927C207EA5FD2E467A24BADEC0
+:102670002FF81539C0DD6BBF227E3DFE9E6B17F92A
+:10268000848893F07FA5F383CFA0594DE35FCDE31A
+:102690004B3D8B882E3F497FD5F627E6CBE182EE76
+:1026A00034B9B5FCE9CF997F9E324350D2FC6388A0
+:1026B000E1BBE54F2759C83F5CFE1708A5E0FB15B5
+:1026C0004F3EDC4CFE4E39FAFFE4272FDDF373E674
+:1026D000B727495F22E896FFF753CFDC477C7A693A
+:1026E00012C7A1A6BD7A389FECA0E98723CD883612
+:1026F00038FAD41BC304FDEB7EC9DF4D67A3C7675F
+:102700004AABEE207CAF40FCDB71BE15A6A0A85BF7
+:102710001D6E95E59EF093176BFBF818BAB72C6009
+:10272000B9A21E28A7FD6449C0F23124FC0919FF93
+:1027300011FFDF7238B496D609D21736923727D0F8
+:102740002FA67DDDF250BCDFD173A09CFC6EF28B16
+:10275000719F4B3B8DEDCB63F543023FF98E222DEC
+:102760001E960339B4AF5FA23FF4C7D134EF823471
+:10277000B20FA7525C2181BCD4FDE3DDC9D55B8AD1
+:10278000D85EEE94881F2A2C89FB5F57A8C5793440
+:10279000FB7FC5FD12FB712BEE1F348EFD648D5F38
+:1027A00021EC65FE7D94F40AD199FC021A19643F6C
+:1027B0008A35C3B6414C7337B59AD88FB14BB77AC7
+:1027C00049EF4F7A70C8CDDF65BA49754316D5A772
+:1027D000CC7FC8C3F655908435FA556C673E9ADEB7
+:1027E0009347F33F9A2E838AF33527F5E4919C555E
+:1027F0009F727849EFC6AFFB454DEEE587276F8D99
+:1028000078049E89CF739F2FDF4A783E867C4EF8EE
+:102810005BE11A33049C64375C9C15C1B259B3D395
+:10282000731F1A97568F70F1D17A63ECEAAE835713
+:10283000A490BDBCD7E24F7163BF6387F20C7E509A
+:102840007C591246E4140FD0FEC69CFC4002B8EB43
+:10285000A56FAB85E1A5D3ED2F1B15F8A395F0511E
+:1028600029F6A1DADD761FD15F6806F9932BBE0940
+:10287000EE36ECBDE2851F373BA8BE1E989A8FD17D
+:10288000FFA8FF07E610D9E33F4C99786725D6F7F4
+:102890007C68117E8AAABC521863C7DAB3CC201BAD
+:1028A000E8B55B5A4AF298E81EE935494E06398682
+:1028B0001E530A320C759777A8E1FDB4B23C437BF6
+:1028C000BA32CED05E0A0D9100AEA7244B7287704B
+:1028D000C5836A8B0CED76A4EB30ADF3536147955D
+:1028E000E13FA16F836C0F5544007E847430F52363
+:1028F000A39D5516E9607F33E990C51007B09F226C
+:102900000EF53F3A7F0D87E1C45F48FF5E9263C7D3
+:102910000E89B893ACC173458ED0CF2B5E90D80E84
+:102920005CF1A199F5C431F0F6E287E4A3CE77F12A
+:1029300070CFF41BE13C64BE11AED901235C872D3E
+:1029400036C235276884EBC806235C7355231CF315
+:102950005BA71AFA8FEEA836D42FDA3ADBD07F6C59
+:10296000A8DE501FFFD05586FE133A171ADA27ED5E
+:10297000BBD9D01E4F5793C32B0CEDF6D4D799AECD
+:102980000E205D99501F143FFFDD38BAB030DC4B8C
+:10299000863BBDA118FCABF88FF05FA1E525A680B2
+:1029A000DA4CFC78AEF03FB518F13F3E8A7F5DAE61
+:1029B000F6C7A73A7E0769FA1AF93342783F569666
+:1029C000C2F4F2F2F3C70E2940F84F8522DCEFDCA7
+:1029D000E9228E22C9C156A2936E707590FDB9CEC0
+:1029E0001264FF4545B3F00152CA71FEE6D7CAD062
+:1029F000DF8C59679D92049698FD4E0E771AEAC5B2
+:102A0000CFEF33F42FE90E1BEA930F8144FAAAE8C3
+:102A10004DEF335496BCA770F8ABF483E033549673
+:102A20007F1ABC9DF46FBC9F7B99DA24A5E1A2A616
+:102A3000FEA3F319346BD03F1BA192DF1BB935D530
+:102A40006B1A8AF0487EA799FC6F403BDA8ACA0865
+:102A5000BA7F43C884050EF1FEDF932E5E43FD4D21
+:102A6000E89F13DE112E0564EF3540B297E0427601
+:102A70000BF961305BD8F36B4D2ADBA349688F9269
+:102A80003DD25CE5677B79160487D3F32B4059432D
+:102A90007C2799D17EC5E7C72F0AAC2C2E118B2538
+:102AA000FAB9FDB8CCFEF774F2A719980A90DE3B8C
+:102AB0004ABFD3FA207CA5427110D265B8FECD6D15
+:102AC0004F5EA952DCC903EE08AE3B204006EDC5BF
+:102AD000811F14A31C3E6272AF2DC6775F9EFAD78A
+:102AE00011648F34150BBBCF2E21A49006862C5079
+:102AF000809EFF2047595D9C198DB3F4473F7A3C77
+:102B0000538F6FEE690C7369717B25A2BBF8B863B4
+:102B1000C4ECAE994CFA6F8589FDCEBFD2E2CA797A
+:102B20009E5496F30EE8B6A7F392D9FFBF46C39B17
+:102B3000D9D1BDE67BF8DEB541616F2D3479D95F1F
+:102B4000BF25EB238EA3D82513F8C81F4A2BDC25FD
+:102B5000E22F7ABC6498742676D6A9F67B4BD6878A
+:102B60008678153C3228617C3D3ABECAF08DD9E7A3
+:102B7000F6AD1EA1D7C8CF3FB23EA71A5213CDF370
+:102B800009C7AFAE091E34F0C5750D6F19F8E07AAC
+:102B9000F55D437BC4D363A57865E4F1EC59145F1C
+:102BA000FF78AFBD94F080F87FBA38265E17593FA2
+:102BB000BE06269ECE7EFFCAEB38DCD8CD78D5F790
+:102BC000FB4EE39B5C8F3446B88CDFAF1E1FD14BAE
+:102BD0001487AD64CFDC2EA1BC207F97E485274607
+:102BE0005E001490FD7FBB34CE4BF46EDB1FFC09FE
+:102BF000B5F734D9DDBB7C1C1FE1B84903D205D938
+:102C00000DE014EF2FB439D80EBDDE27FCE9C35513
+:102C10009F5D4BF66B2EA47A5106127FFC9EE22636
+:102C20000B4C69ACFFD7661FE0FA7BEB41E48D16D5
+:102C300087EF277F75796AAAB08B15EC8FF5A319FA
+:102C400066AEFFFAA2C0FBCC8F8561CE6F2C1F222F
+:102C5000E279E0898C203EBC4DF67F58CC7EBC3BAF
+:102C600040ED8B33D0DF46FAFDC0AC4E34E1FBA320
+:102C7000F7645C6541BC7F90AC7E42164D8E2FF5AB
+:102C80002AF2333FB009FE9DB0E7EFCCAFEF9924B5
+:102C9000F6CFD5274C1CAF0167C456877ED8E69186
+:102CA0008113347F8715ED49A7785E3F211A973D40
+:102CB0006AC592F83F49945F148B3CE4BF8A85FD56
+:102CC000AB97430866F87C8256CE94DAC750FCED89
+:102CD000D8363B90DCC2F915F2B7D4A7441C7F70FC
+:102CE000867F0908BCB8D7E17A3DF9F271E23F8FDF
+:102CF000847E2DEEC3EDCBE571F5782E39B0A9D8E1
+:102D00007EE471FB4EC25FEF7A0F8978D8C7EBC7BC
+:102D100073BC5BA713B7862FB80140B40FDB49ED36
+:102D20004B5F38F20EC5E7FEA338E0F1E1F80BCDBA
+:102D30007229C9C9A5A95D1CA71BE393F93D5C2FA6
+:102D4000EF17E5560BFAE2B0D411E1B8DEA9E2F7CD
+:102D5000FDEDFFE36F766F29E478B53C91E48A3EA0
+:102D60002FAE638C2F26CEAEAF233ACEC0FCA3C7C6
+:102D7000A1F5FA9FEF5F3746CB235CE74FA097A7FB
+:102D8000E9746C4D1CF79FEF13F88DC74FD145C107
+:102D900010C7F3DCE06EC6FA6C0D4E1F5F89FBE1D5
+:102DA00078883299F0BBB4DEE92538EBE30FCE80AA
+:102DB000C0CF079867C6587F0DEDFFE6A0C813E89F
+:102DC000ED487F22CEB93E85E975E9D36FBDF33D6D
+:102DD0009CE5A69F4C2826FDA1BF1F0F6784EF1816
+:102DE0005ACF4249E4CF10BE75347E7C7EE06CE160
+:102DF0007A34A79BF5C2D19DDF09D1FA8E6683DBB9
+:102E000084FCB8F4C95FBD699A4874E20C4B58C29F
+:102E10001E63FC2B5E4FB9217035C9113BCA11B23C
+:102E20006FECFA7BC32D86F766672937FA585F2B5C
+:102E30001B481ED955E1AFE507AAB8BED22AFCB59A
+:102E40003DDD6699F87B8F0542A4C7571ECC50C95B
+:102E50007E5C8976077B3A05415E2F24A31F949EF2
+:102E6000C06E307965AA57A6056E277849DF98713C
+:102E7000DF23B9517F54D797259ABE570AAF6BA667
+:102E8000F17D5A3C10ED4C8E77964340B323B43815
+:102E9000DCFA031C87D0E5B60DE63B28FEB32E73A3
+:102EA000A183FC431987E5F89AA73E0D06B023D706
+:102EB00034A2A4BD285AB7F6E3C7EBE703788D83A5
+:102EC00069BB40C21ADABF7A20D24276CADC177BCD
+:102ED0009EC5B26DC28391D5D4F6C54989EC4887A9
+:102EE0006607703198D629DEB30D5F7BAB09F567B5
+:102EF000B2D7024762F4A00339FF4881362FD903C5
+:102F000059BDEDBF25BCF5B78FF3556E40F81C19C0
+:102F10003D40BBCDBB3811BFC7C32B49C36F52E186
+:102F2000AC0FC9E04D82987DB3DD135397A2F02218
+:102F3000D54DF8B746DB959309F297675A12DE8FA5
+:102F40005863EBE183EF19EC8110AFDF6AF183176F
+:102F5000F767F360BBE11C86AAC5C191804B357A47
+:102F6000603638F5BEC82EFFBFB52F1AD73FF8829E
+:102F70005E9F7A81AF2F7C81E317EA2E6CF829756A
+:102F80001736FCD40B7C7DE10B1CBF507F61AF4F2B
+:102F9000A9BFB0F1AB5EE0EB0B5FE0F885CB2E6C28
+:102FA000F829975DD8F0532FF0F5852F6CFCAA6CAB
+:102FB000073A2B81CFCDA6B7984374CE46AA0973A2
+:102FC000DE384F058E47A7AE07CE57ECF20A3F4AD0
+:102FD0008FD38FA52164F45BACEE6CF2AB77B5DCDC
+:102FE000557D038E73220B174FF9FC9CD7151A677A
+:102FF000E74CE0FC85B3E5FDC314FFCA85B0379C00
+:103000004B713509C23176E935C11408C7F813751B
+:10301000CA2043BDA47BA8A1FF8D5BF30DEDDFECBF
+:10302000186F68FF466BB1A17EBD5A61E86F87DCFF
+:10303000B602CABBB658BC9407B3D0DECAFBC20DF9
+:1030400076DBF83D05FF911F938B9E50EFB8B88F4C
+:1030500074D56618D719D77EAA7C407C3EA1A654A9
+:10306000CB27F47EBF20DE07B72761DC53CF27E8EC
+:10307000F81C6349627C6D5245BE69DD4CE147CE68
+:1030800068719B286FA9E36F3CE83F6E33F99B0F93
+:10309000350A7F5287437A48AD667F74B7A08FB1F7
+:1030A00035E6109DC39D293993699C1092B41BDBB2
+:1030B0004335F59CD7D4E9607CCDA239145F6DCA45
+:1030C000199C4DF184DC1A81F7E5FB8CF8A6B42D30
+:1030D0006D29FD90C4EB4C6FCA28A2BC5D1FF83F60
+:1030E00022E0A99F334F8F83EFD89011FEF1F8397A
+:1030F00053F8AFFC92F0B7D5CA5D69140F5541A6DD
+:10310000F8CB733963CC0C87562FE3A116BB113C67
+:10311000735B81F33AF174D7DE08E19A183ECDF57E
+:10312000861582EF4CA9B09AF909DF1D027C1A942A
+:10313000F3EC3B5B459E16CB641A1FF6C943099F0F
+:1031400021B59ED7BD6BBD2D99CEED7DD664063AD7
+:1031500017BF2B571E4AF9AF5D4F98E6C79E034233
+:10316000ECDBCD59BC0FBBB98C4B8B2815AD048B58
+:10317000680F4B541FB1CA1C874F55A2F6F4DAE40E
+:10318000B8E78A89FA6F28CD63BF344DC930E0CBE8
+:103190005A66E46B04E32B85280747D2EF32D195BA
+:1031A000A093D06B526835C7517A4C8B896EB4733B
+:1031B00015E96BEA81F24E4D39DF9ECF72AAC9C67E
+:1031C000708755822EF4FC9FB555D0613CFDB8BC8C
+:1031D00046FAB14AC34D228F25F8445FC74E459B3E
+:1031E000375B0295E59B6D28F181356E3C3B0949C3
+:1031F000922B1EC17F4EA8077ACF5966E77C3548CF
+:103200008719FFD629008362CE23C4AFF794EBFC65
+:1032100092747EF01CC9999D35E2BCEABA35E27C15
+:10322000E389E7859E98D1EA36B3BC0199E50BD2D4
+:10323000C1DCEC52717E88E0D9AEC91B3BD4A551EC
+:10324000BB4EE7B3A4E155B1748E72E44517C9B320
+:10325000172C1CCF5C6795AB6FA0F672BB7B35C398
+:10326000B3B088D6ED6B41B943F1C26E01275D5E04
+:10327000C4C3AD0862EAB9443A89E1D89F3EE893F5
+:10328000FFD7E1588A70CC3F7338DABC42DFA6978B
+:10329000097DFB5CCEB7F955F721717E265D0106ED
+:1032A000DA7155C07596F45198E4CB2605E50BB656
+:1032B000D76AEDEE32214F7438E78925F6CA934D6F
+:1032C0000B2083F8DE4D7076125CDF67FDDC512247
+:1032D000E00C10E13C67AA22F8649D15BC148FED48
+:1032E00028777A292E98A768F06DD5E065025322D9
+:1032F000F8CA71F04D8DAB9F297CC74CD1E03B18CB
+:103300004ACF06BE9B525205BF8D12F0B13A237CC4
+:103310007EB935D7E25D8D74D8958BF0C6F6D6D7D9
+:1033200004BC7FA8F55F3301B8DE9AB9368BE1950E
+:10333000BB288BE478ABB543A57C552BD11F9FF3FD
+:1033400014E7BF5C1A5DCF44FE5E88EFAF45F944D9
+:10335000F9C6D4B28083C66B2DB480C4FBDFE64DC2
+:10336000B47F87CF669083C3161BE19A1207C7A468
+:103370002FC9FF7553BE1CFFDF49BF62BF75A39104
+:10338000E538DF1872109C6C657F71101DB595EDE6
+:10339000E2BA0CA1D63CDCFF1D4E6167B595D50F96
+:1033A000780E6A972617428D0E2EB737BA51330121
+:1033B000DCD598C5F58E4699CBF6C6022EDB1ABD34
+:1033C0005CB6369671B9A651E1FE527951157F0F60
+:1033D00036876915DC8E4FC061EE3B5F7EAB518F47
+:1033E000E5AAC906B88F6C30EAAB41B5467D95AE0B
+:1033F000E419DA5DDE7186F694822243BD704AA03C
+:10340000794A099D8B9A6A78CFE6A936F4D3CFD151
+:10341000B59589EFA174B8E97AC9A9F1F73A6B2497
+:103420008BE2D8CE32C19FEB35F8B56AF04B5680AF
+:10343000CFC5D80E49DE1010DFAF65FABE03713874
+:1034400004E1D295738542F6419B2CEC742B887372
+:10345000BDB62CBFFA0D7C9E847A8BF2B6B6F929E4
+:103460002C0FEEF038BD748EB6AD6C859BD7E3158E
+:10347000E765DCF82F519C3FFEFC8C6394F1DC8DFA
+:10348000F514E7171F9C12FF3DAF46A7951909E5F4
+:10349000471FF9DA9B5FD96FC8AFB46BF9157B3F53
+:1034A0007248D74F7ADDA9E55760B82F61FFA81D94
+:1034B00025F2071B292E1F937F705526FE7EF3B938
+:1034C0002912AFF3E01499DF7359BA81E474AACFDB
+:1034D00018B7772967363FFEF83C8349FE02CBA533
+:1034E0001B92030789EE9447847D92345CE86D1B40
+:1034F000282ACB2510F90EEE6FA252E4737AE50B61
+:10350000898618BA73F6F16745DE833EA320FAB1C7
+:1035100044DF3F27FEEB99962D8D03E77F5AFAC9CA
+:10352000FF7C3E45FF3E0C7A3CA500BA6B8EF0FB5B
+:10353000BC1FF885095E2DA64DB57964E7F92C5EB0
+:10354000C4005479E57D948F5CA3A4B25E5FE395DB
+:103550003B890F8F2B4E2FE16363610D59F090343F
+:10356000FA59D63F2D74BC26060F7ADE0914A5BB86
+:10357000468733E9DB82DAEE9A18BA583F610BE7E7
+:10358000EDDABEFA20E7F3DAE6FE94F3796BB3677F
+:1035900015505E38C93BEB43CEA3424C5E8AF447DC
+:1035A00081317F77F2A4A8331C28FEA0E5F9C0631F
+:1035B000CCE359647F743D70EEF104C385FE018B4A
+:1035C000C2DF13F4A56FC1D77ABFFEF940D5BF2B78
+:1035D0005D4DE77F5B3D428EB682F7CD00D55F92B1
+:1035E000BCAA4CCF8BDEA4F3A46B875B182F6BB304
+:1035F000EA5B85FD2EFCA556CF6A961BF1FA9ACEA2
+:1036000063C6CA6B3A8F192BCF5BE5FA01F5717669
+:10361000C01CA7EF8DEFE7048D7A477F2F29EBD2EF
+:10362000576B62CE43ADB7F81D242FD678EE320526
+:1036300062E8F9474A606E5949B46ECD9ACBEFD92A
+:10364000737C09D7355B51EACB3279FF03DA019BF2
+:1036500035B9B845D32FA7DAE756ADFF8FB4FEDBF7
+:10366000489F5F14C5CF98516393583E5F22E43161
+:10367000C13C76DEC2B2C0E2D87D10D3F4C205E907
+:10368000744CE1B824B2379A2F294A223CDD3D67B9
+:10369000E0F5E87973BD9F9E278DCF9FDB3C6603E5
+:1036A000FC7795897322CFBA1655FF08417377AD21
+:1036B000A0A7E64B845E1EF388D8475F3A34AEF786
+:1036C000EEDA81ED9FF8FE1439ECA513AE67C4D590
+:1036D00087C6F5CF8B6B1F17D75E14579F1AD7BFBE
+:1036E0003AAE3E3BAE7F7D5CFDAAB8FE0BE3DA6FDF
+:1036F0008E6B5F1157FFAE119FBEABD212C1311E50
+:103700007F7ABFD3C5DF6F7D553F23FA1E03054C7B
+:103710002F3ABD9D2E1EA276AE97E9CC56366E1F6F
+:103720009D8FBB0BED2BB287EEAEAD760BFB22B0BF
+:103730007AAF461FA41F2C5F15F374E59426B13FA2
+:10374000ECF418E4C8A9F06D820C63BB12637FE649
+:103750009D7B7C9F9A3E439A7E1C78DD3A1F174ED4
+:10376000F1BF43708790F02F75BB76A72AF867A743
+:10377000BAB07A33C9DB56B3882F6BF79D64D0405B
+:103780001C070F684A3862227CB712FEEDE4070876
+:1037900079B25193271BC83FC0E749A3825B29AE8A
+:1037A0009B7C888FDFC07A5FD1DF16127ECA4B7791
+:1037B000D2F7611B26943DFC63ACBBFE2141B818D7
+:1037C000EDF3896D0AD92C1D4A46129D174A3139ED
+:1037D0003AC93F5C53DCE11F85FD36EEFFB0F319BB
+:1037E000C4B39C65F326615DB6F49888DEA0D0CBA7
+:1037F000DF9DE13A55F2FDAC953D8D89CE956E9CED
+:10380000ED369173985E2B9B557A6F4AC0548EF0BB
+:103810001BD90A663A479CA186F9AC4D75B9CCF222
+:1038200065D713C850BCDF9E6C82D767EB6DFBA9D0
+:10383000DA3F3E40D2E2736755EAE3A409D2A01F03
+:103840008EC3C816ADAE6EDB46F78F3825511FFF0D
+:10385000C48E05AB0BA3F5EC27760CA77A7BF10899
+:1038600013C9D3744F6AC27B60A6970BF9B96BFD7D
+:10387000A2918101E84B267F6D0896855A4934351F
+:1038800005CB515A296BCFB3447D0AC10DE12937CD
+:1038900068ED1E519EEB79E2C757CADDBA9D38D458
+:1038A000CFCE3F143A071BECC5E9E599FDDB8B68E9
+:1038B0001E739C7687551E4AE70477ACB701DDEF8F
+:1038C000B02307C477C66B6C7C2E142CEEA157B8BE
+:1038D000A2EB0EAD19CCE7CF432630C46F2DE5C265
+:1038E0006E3D5E6ED2EC9E2FC2F49DDE0E2D8FB328
+:1038F00003226E8AD747F1FCF0022506CF0F957F91
+:10390000BA8DE8B32B6751F5167C6F538B99E3257D
+:103910009B5AF298CE691CB28F4EAC7AC54CC1A5A9
+:1039200042E834939D3F8EBEACCEA72B8E025C76D0
+:103930006AF2F967C49F38F16850F8F908E861E065
+:10394000BC511AB89EE0924FA24D22FE91CD0E9C22
+:1039500067D993E95589F4F62DE5BDF6F8624BA9D0
+:10396000E65FC80CDF5BCA13D8E374029FE38D8A5D
+:103970007F29B53BF71D0C0FC3EADE378CF449787D
+:10398000AB8FD133AB35FA747BFD0AE1707669E019
+:10399000DBF4FEB2AD7F3B40E6A8ACBACDF4FEFD51
+:1039A0001ADE178583B3689809DE7035F51FDFB01E
+:1039B000733FC5D10A82B7560FC1F58D51EAAA3DB2
+:1039C00044434AA091C619D51DA97261DDB9F560BD
+:1039D000389BD73391C7CBD3D783F450C774E41641
+:1039E000F17B0DBF847F3A97BC689B800FB667F36D
+:1039F000FE2CEEECD8F5EF9C8974E1EC4B170DDA58
+:103A0000BE3647E10856A35FB339111C753AD5E1BC
+:103A100071ED233D6B2897B920D4FD1CC941FF5699
+:103A2000F74C2ADDA581FBE87D5F87BF99F37C7B9E
+:103A3000BAE9BAA15EF838956E4A1B613F653BE171
+:103A40007DC7AA23D51C97D907C2DF89D3877A6996
+:103A500055E2F30BE23E9C49FB8C7632D2ABB2C509
+:103A6000134BAF66CE5785347D126A45FAA5F956D9
+:103A700009FA0DA92BDC89E8EC414DAFECD6E856EC
+:103A80007F3EAA9F73954F97EBDF9343966484E73D
+:103A9000D303F17D1A78991F900FF653BF0CE20300
+:103AA000AC8F5C25333DE87CB06CDFDF0E0C637FB0
+:103AB000522EA2FBD9F4795FD2E645FA7C91DE5F03
+:103AC000B6B5E700F98A235709FA7C95EE06CB8C48
+:103AD000D219FA8FBFA17E3AFDC4EFE3D71A5DB8C1
+:103AE0004BFDAF121E176D0DF278C83FAF31FF6C62
+:103AF000ED0E2731CB29D5B49F1D1DE0A6FDD8BF03
+:103B00005FD44572E1448389E17A5D61788D19CB98
+:103B10006B468195AE13AACB42B2C9A33CAD31EF3F
+:103B200037BAC3883FA49F3FD23C259E804D04AD49
+:103B3000833696A7FDD04554EFA93AFC57C5C9DD99
+:103B40004F0694BBA739EE774B954F699CD35EC760
+:103B500069F6D3E34D7DE3A6E39289AFDB5AEBF53B
+:103B600038552DDDB7B38BE2A608D735AD03DBABF7
+:103B7000218D7EB76BF47B971637EDD0ECA23B4ED0
+:103B8000376EBAFE5815FBBFAB80E340AB53269AA5
+:103B900012D14DAE6AE4CF910DC9717152A3FF9A53
+:103BA000AE18E3A6F49DE799C44DE3E3A58553025F
+:103BB000E3A796F48D9B42E45D839DB9A655C805A5
+:103BC0001D7E636A6EE2F8E72E8F3914FB7D845EFA
+:103BD000B66B70D3EDC936821BC3B3408B3F7B35C8
+:103BE000789669F0ABE5FA18B2E23C1C471579F714
+:103BF000B177CD5F4870CC02CE1234E53C9895E8A1
+:103C00007C3D64C5D8D148FFEBD66B79B42CE0EF8E
+:103C1000439FCB79BD369FF29A59668ECFEEF2EC78
+:103C20002FF831D79399EFACA07614E07C63DE9B3C
+:103C3000AFD27CBBCAEC6E711F07A4521E48CF4B9B
+:103C4000E8F99CB64C91CF711568F99CB8F9ED7004
+:103C50007D7507CD5F20FC977EE9D9A7E523B43CAD
+:103C60005046A1315FE188CB57C4E72BD7AD5FB891
+:103C70007F9788B3B09C1E73C3D864BFABEF3CEE94
+:103C800039463F6EDD58DD9F7AD091089EA93546B2
+:103C9000BA6CD3F0DE9C29F211A71A1F2A930DFEED
+:103CA000555BC1E9C513F47EE48FBA13F48FF7476F
+:103CB000CFC6CF75F3F8C63872023F77C354115799
+:103CC0006179B26EBDD87F6F5C4DF3AFF47346FA85
+:103CD0003856CD9FE37A6E545EE9F9B0516E1BFB06
+:103CE0006BA3B47BA19AEF4D09ADCEA5FCDADC1E27
+:103CF000CA478EDA2D71DE7D94D33F94E2AA5DF738
+:103D0000CCE2FC78767260C7D498EFE076BBBE9DBB
+:103D1000C579032DEECFF7E3A0FE533715772B645B
+:103D2000F78E05BE4F27392E2F107F0F4E9FFBD8E1
+:103D30002A841ECBBA1A12DE6FF2BBA9426F46E587
+:103D4000AE3F59F8F1B3194E0F74D4270BB9ABE855
+:103D5000F501FDE073256F1FE87885BFEB39E103BE
+:103D60004DDEFE0C2E4479FBBBB2C05B09E5ADA570
+:103D700087E5ED235394B709CFD7D3851E8487EB0E
+:103D800012DFC3E3AAB850F1F098C043A18E873B7D
+:103D90002091FF7801E021B922111ED0BF2278A91D
+:103DA0003E25A52293E2A68A93FAF5E2E3EB89F990
+:103DB000A2E23CE36393868F3BB5FCED460D1F1BEF
+:103DC000081F76CA570A7CACEB838F23021F653A23
+:103DD0003E9E3E2B7C64D46418DADD95467CA4FAC2
+:103DE000F20C7567A1111FC9A38A0CE35D5F218BDB
+:103DF000FB90864F35F4EB8B0FA35F10A0F706F016
+:103E0000B38607BAABE81BABA1F33BBB483667F9F7
+:103E10003BAAA8D4F7B92DCEAFD3CBEB35FC65CDFB
+:103E2000488CDFAF69EDFF2E57E656C4F2E7571214
+:103E3000F3E7E59A1C0D9429F30CF47369E2FE573D
+:103E40006BE37F7D8A72556C7FFCD92CC5D8E5FD6C
+:103E5000EDFB8664E57A7A2F6B86CCF1D4DD4DA933
+:103E60009C3FDB9D24F2656A93D3703FDD48FA0DD9
+:103E7000EB59DFF8A24BA57376741F105A583B6FAD
+:103E80001D9CB70E9B76668C594D70FC56453EAF17
+:103E90002B7F89FF6DCAF328EA51933887B480EFEE
+:103EA0003532850799E83E2C70679C561E09E599C6
+:103EB000B8BF6D2488EF8521C87A50F2433A7D9FC0
+:103EC0006C01BFC89B537FF11D216F3E05C25C771B
+:103ED0004184EB699ABFB7AE2297C74D07D92480BA
+:103EE000E435911CD5F9D4E10932FD7B1ADCA6D565
+:103EF000E4D3599057C91F740EE7EF76A11A54CA3C
+:103F00006B99C0C1F6A669F381CF395FA77F67F8C7
+:103F1000C220F19DE169EEEF74FBB5D0FD7B9EE818
+:103F2000FD7B2D9A3DA0DFBFA75607F93B7275B503
+:103F3000DDDDECE9FB1DF9E6A9819D44877F4F1A81
+:103F40001112C9E6E0947AD7391DFFFF9CE7F19F73
+:103F500038CFE33F47FCD0DFF81BE8D772CAEFF950
+:103F60005FA07ECDAE52B63BF5321E6FB3D1FFA738
+:103F7000F54A8E5787BE37286ACF390F9BD82F6AEC
+:103F80003689F367EABB26B6BBA050D08153868240
+:103F9000DC49D1719CDEE048117F127198A6DFDF09
+:103FA0007E11D9DF3F4C991B49C3F15E3E28EC3F9F
+:103FB000CB8CC836BAC779489ACDBB0BF9EE0E6DDB
+:103FC000BDF6F22977DE86BFD64F376BE71CBC976C
+:103FD00014F1B9A53911B21F5DA516997206CEB8B4
+:103FE000FC66BBA583CF19B7EFBEAB6A1CD039E521
+:103FF000E7DD2DD6BEFB746AF9CDB1526239F89770
+:104000006949422EF98CF7061FABD0CE41A5422A52
+:10401000D991967F2B6989CE05E8A53E7F892752E5
+:1040200043DF5947E8B236C47349595D52B287CF6E
+:104030004774137CABBD6107D9BF0F2F0CDE14FB97
+:10404000DD797B19B8C88ECF9D2ECEC3DEA3482E56
+:10405000BA47E3BE8885EF17BF6FC963EB53B0BEA5
+:10406000EFB0D94DF068F7BFEB4CC6FAC3382EC994
+:10407000BB97778B7B26D505101A8DF06B27EF1237
+:10408000EB7B15E073C0EC90956A57F221FCDFB929
+:104090003853C01B8275743FE7A6948BF9DECA9C27
+:1040A00079222E3C4B3ADC45EFDF576667FCE56B27
+:1040B000E7754C6A1DDF5B99B9C0785EE7BE95DD98
+:1040C0002AE1D75D6E77D33958909CAE89F8BEEB64
+:1040D0002766905835F6F0E4B324A75897579CA369
+:1040E0007B580EAB74AF7126BED7E4E6DB110DE74B
+:1040F00082F66E15FE69DA64A717291DD71B776E45
+:10410000485F5707AE8BEE37768DE2B844C63CE386
+:10411000FAD2E2FC06675CDD5BD97B5FCF18C2F7A1
+:1041200071FFB78B5FE556AF9CC8FF6C6F84EE9A4A
+:1041300098F309CE7EE281975F2CE8DA96FDAC8396
+:10414000EC94E3FED73D848397FE75E03D3A2BF770
+:10415000D2BF5FDCB31CE1F39BCFDFDCFD28EDAF0A
+:1041600061C32B44AFBA3FC66730713DCFD5D91874
+:104170006EFE5AED3CA7AFEB59AB8FDB39CFB47174
+:104180007F12B78FAD845012B68FB528D9DF24BA0D
+:10419000EB96BC4D320D22CE23EAF8DF78ADDF047A
+:1041A00013088F7E89EEBD9829BDA4B8F0FD7B96DB
+:1041B000804CF8B72DE9E4F3EABE95E2BCBA4FA90A
+:1041C0004BE2F3A6F3CC7C4EA4A9EE8A4B46637D6A
+:1041D000CF25E21EAADA95CA953CBF22E825ADBBE1
+:1041E000D4BC92E8325BDCCBA49F372D811EFECE7F
+:1041F00063ACB7B3CB46F266010298D6D7AEE14BBB
+:104200008B1B94F8BA55B2275D5E231E33E2F0167D
+:104210008FD79B743C8E85B18447193A92491FDE33
+:104220000FD049F707DCB3F2B12BE95CDB71358DB8
+:10423000E1D51F3FBF83F6AA7211DDB7E2E0B21BE2
+:10424000ED552AF7A0BD4AA52B5875F54A5CF7E352
+:104250006FBCFCFCD771BAB94ADDA57C544BCB7F4F
+:10426000012C1A518D70BD96B857D4B72BA300FE00
+:10427000E0930CF58D1E4BF4DE7FFCD595ADFD1D56
+:1042800000F5C4764A40B66759B47C9BA8CF253F59
+:1042900024A67DEF1C63FF8AFD31E357E27A97DAAB
+:1042A000B87D63E5A2EDEAA868FBC7D3B03E1CE089
+:1042B000A0663F5EF380D9BF2B817C7BA952D87169
+:1042C000967F834A72ED5319D8BF97CC0ACB77C833
+:1042D000B3C889EECF03407918EB97CB46F95AAAB9
+:1042E000F185C55F055A9E0CBED0E30FF8F3F8EFD9
+:1042F000E6F2BD4B6BF22D7CCF10EA03EF40793B29
+:104300008BC7F297D8FBB97EAAD3C168184DF37F4B
+:104310000A95BFAD623E88B99F01D73DA3E399617D
+:10432000CB711EDFE1648EA74AAECD29344F4B63BB
+:104330002BCBF31F29813D9531718A96F445C52415
+:104340005FF4F332D1FB8DAE309FC9FDF65D75078A
+:1043500080F4C2A7485AF601E8B0A571DFEBB48E2D
+:10436000B58D9D5C3ADD0A0B1BBB25C8719FD94AF0
+:10437000E0C5CA12BA570FDB63F8C4EAC6F70C7E71
+:1043800087F1DE4DD91D7112DCEF29FBA393E66F97
+:104390003F24F8FA9E43F57C8EA1DDFB4A12F1CD55
+:1043A00071BAE0F14BF0894F39C8326CEF1BA9D7D5
+:1043B00010FD3CDE9CC676C5CB2BEFBE8AF8E7BA73
+:1043C000EF5FCEF0EEE51BF5DE11D585317CA3DE87
+:1043D000CB74DDCB375ABD7FBEF944F0452FDF8863
+:1043E000BAAF100CF597E718FBF7F20D8D8F7CF143
+:1043F00070959DDB3F7DF25E03DFFCE1A97B8D7C48
+:10440000F32DE49B0472BF789A46DFE7986FFE3184
+:104410004DE3C7F3C437E9D3B473B55F9E6F864DE0
+:104420002B391F7CF3B8E96CF866585FBE993CEDF8
+:104430002CF8A6DD1DE67375EDF3CC09FF0E487769
+:10444000A5C0FB8C0581EA0EB26B14714FDF4C697D
+:104450004EB6CF437C26D15DD1A83F853E7FF99AE9
+:10446000DEEF33583FFB353C6E2684929DB454D02A
+:10447000CDAB8D22EE3B5372CE5C4A7A97BE23A021
+:104480002BE3E698B8DF65A8F765B20BA1D3948952
+:10449000F3DC83EABD43A62D07EB46F3F861B6CF04
+:1044A000F2B53C80532A14DF3329E2EF5BE8DFC525
+:1044B000CC9B63BC4776C829EC261C2085FC18776A
+:1044C00099F87B2757EAF4D3AB7FD10EC1F5750F6E
+:1044D000B7319DDCA35C36609CA8CFF96A5F306180
+:1044E0007EF2C0349320464559342D93E4CBF664D4
+:1044F0003A2FF1B8047C4E6741F0E75712DFB95408
+:10450000216FDA57FD89D292B067E6D78D7A5A8D3E
+:1045100018F5B41A31EA69ADDEAFBC81F78D7A5A6D
+:10452000ABF7EA69ADDEABA7B57A54DE440C7A7A14
+:10453000F55391ED6A4CFBCB54AF3CB59EEE9A76A9
+:104540007EF4F490F3ACA7779C3B79F3F0F99137C4
+:10455000AF9F95BCC9E92B6FFEFB6CE48D6B5B973D
+:104560004AE99945FDF0C137353D73A042F9158DF3
+:104570000F65A717AF89A7AFAEBA456BE9EFC77C48
+:10458000EA15FE5F7FEFBB1A7EF17A4B8C1FAE7F80
+:1045900097E06A789C9FDFB8ED20C7634FB95EBA99
+:1045A0000834B3AF5E45BBC8C1F4EB35734EFC6C49
+:1045B000D7D13E4FF05BD9B4C5CC4F7FD7E28FF156
+:1045C000F66F579DCDCCF3950939DD9F3DD4DFBC07
+:1045D000DD95B2E1FB0C7DFE78FA45FAFC37C9297E
+:1045E000A4470BDDFF7DBC1BF8EF51FDE7B12DBFEC
+:1045F00056E40B4A2F7A283470A6745AACE133C1C2
+:10460000BE732E2E399FFB3E67FC597C36FBEE9A1B
+:10461000067A5C3B7EDF95E777DFE7CC7FA8BFF8C3
+:104620002CE4D24B95BDFBE6EF5232B47DDFF3AF05
+:104630002BDEA5B8C63DFFBEEAE714D7B8EBF38280
+:104640009D14D7D0EF8F4B83E88FAC7F1F8970719B
+:10465000F9C5772519F362BE2F02F6EFA3DF9F900D
+:10466000BDE1EB6DFF7F727F1CD9274712C4197B18
+:10467000DB6DC6B89E5E4EA53FAA85F4D56EDAC442
+:10468000F1887BD0AF6A42BC75CD13F18876B45304
+:1046900058EECC2B1AD03EDAD3A870DCA9BDD1CF0E
+:1046A000E59D8DB55CEE79755905C95DDFAB4B585D
+:1046B000EFF9BCFEAB7F8C407257BDE7A4E7777A79
+:1046C00074FB44D82F6964BF60BDE3E9B61DB1FE39
+:1046D000CD90E939AC0FF4785547568CDD23C7F8F7
+:1046E00051582772E9F5A3A83E2AD6AEC9613F6AA0
+:1046F0002FD93558BFFFE91C835DA3CFB3D10C8BF5
+:10470000C9AED9B8DB5C9BC8AEA9A84CEC47619D8B
+:10471000F3200E9783BFFF97B4BFF315E59781EDA4
+:104720009AB4E9E7D78FFAE5C5E726FED0CBC79A5A
+:104730003DF323457956932B5F527E6C3153FCF841
+:104740004CE5C758921F8506F9F1F6D9C88F8A4AF9
+:10475000B7212EFAB2AC0E9A4876FA6E3334C99A63
+:10476000FEF5907E05FEFB77DFAA92D8CFB9C70B86
+:10477000FC77FC66490B5E207AD8BBC4CCDFBBDF7C
+:10478000A7887322F7CF13E7AA7EBCB2A89E3E2764
+:10479000DA9472ED86248A6B575A80FACD922A39C0
+:1047A000CE7D5FADB073729C9D97D0FE5FAEB200C0
+:1047B000D1D5A9E2DC146EE778B57E9E4ADAC67ED2
+:1047C00087EBEB16379D5B8D8F5F3BCBFECCDFCD50
+:1047D00083F4127FDF7DAAF8F599C6ADEDD37BFF98
+:1047E000CEC0D9C6AD991F2FBF38E75AFE0E218E15
+:1047F0003E9FB958E64A7F7A2C9E9FBBEA66A54544
+:10480000063817E524FB29E6BE58A725CC7454A129
+:10481000D9514EB29F8AA374D155573AE0FDB329BE
+:104820000D4FBC1E9B174AB174F278290D4FF2F35D
+:10483000CD747E81F665F1B25C7DB81AE57382F1C4
+:104840009E6C0C1E22B8FCB2B1E110C5A9A759BAE2
+:1048500025FABBADFB1A55AE3FDED8CAE59EC60EA3
+:10486000EEB7B9712B97773586F8F99D8D0F717D6D
+:10487000436327D71FCE13F34CB584789C693D382A
+:104880007E0C3F547C80F3C4E0B93CA21ADAA7BC8A
+:10489000D96A682FE9EE30D433FD5B0DFD07D5866C
+:1048A0000CED072A025F9D9E49E71A1E32F473162B
+:1048B000761AEAA7EB2F9CEB7EAB53522DFF447E7A
+:1048C0001D11407A423A4B6F9055CE9B2F167C3982
+:1048D000A4C11BA6FA76978DF95BA74B3EBB6C1261
+:1048E000EB37C5DC47DBE5B2B1BC68CE14F194E62A
+:1048F000EF88FAF66C715E724C8DC88F340F17E733
+:1049000030F53CFC7697C89B9DF0897B3446144675
+:10491000F8928C11DADF7D73568AFC991BDC9C9F20
+:104920006F6E04ED3BC508E73B32C0EC15F7A82BD2
+:1049300032FFDD240B849A70BEE642B77A23C99910
+:1049400060AAD7ECE53F211B32531E91C4132761A7
+:104950003A35BDA3E5E593FE087CEEA0173E9F889F
+:10496000EF121A7AF87EA6210D3D9C8FDBFE7D7139
+:104970008F4D3C5CBBBEFF19DFABB4E33B9F6513BF
+:1049800053EFE83DB7D363F82E6DFBE254BE6F6181
+:1049900047431E9FA3D8B1587C772C83D8EFF625C8
+:1049A000363E87B1A3C16C263979628925A4C33B01
+:1049B000A49F5BA1FF158041BEE8DF73DEA59DEFDC
+:1049C000E9D0BEBFBA433B6FD5AE9D976DD3CE5BEA
+:1049D000B56AE765D7D2F91E3BE919859FEF68589C
+:1049E00021CEF70C07ED7CCF270C670BC299E2387C
+:1049F0003BACB0CF3409E80F1732FCE2BF971D542F
+:104A00009B1C77CECA78EE2A2DEE5E2197D778EEE2
+:104A10002AA5605CDC392BE3B92B7B96F1DC95D5BC
+:104A20005D6D3C271A4BA70854D3AA2D4D4407BDF2
+:104A30007FCF911E0EE6BF17C7FB53280F85FBCA19
+:104A4000AA15743948FBFE259DCE85E493FC0F33EF
+:104A5000BC5D44AFF9746E44E57A92F6FD9B7EBE70
+:104A6000A43F3A3ADBFBFEA5D589EFFBD7CF1FBCAD
+:104A7000A1D94F0BA62BAF4F2F89CEA74E57DE8C57
+:104A8000ADEB657FF2E0FF9789CBFF0532DED6778D
+:104A900000800000000000001F8B080000000000E4
+:104AA000000BB555CF6B134114FE36BB69923669C6
+:104AB0001649B5211536C668031122A6A59588D3D7
+:104AC0001A24875AA2F4E0C1430E39F9E3EE6D537C
+:104AD000158A92D218C173840A160AEDA17F40AAE2
+:104AE000C1736AAB281609B5F42CA87829C437B36A
+:104AF000D9264D36B5170792973733EFCDFBBEF762
+:104B000023CF41CB0F4462EC9AAC0123895AC549AB
+:104B10003214072B4581E92A4937ED2F1A526532A5
+:104B200029808BD98434F574AAA62864A7B6D9A5A0
+:104B30000FECECE2DE18B71BE05211F2DCAE13F022
+:104B4000016B49A9F42C08CC6DD0791CF83D269551
+:104B500010E4C1EDD7EBA3C21490F917EBF79F0453
+:104B600066F84F7AAF7FDC379021FF0B3A503ECF8B
+:104B7000EFDCF172DD9D284C6A144764AB0A85FCBA
+:104B80008D54A19E00C7F78381F6674F5F97157A12
+:104B900077691E3845FB73F65AF22EDD5B1B77A84A
+:104BA0008F62DCCF94FD019D4F0764C85C4FDB77BB
+:104BB0006A142A2448F533C44F4231745A75FADC1A
+:104BC000448B4E714F737DB8A97BF743132AC5F50B
+:104BD000703BB852196EDA852814BE7F89797C7BC8
+:104BE0007DB41141A42E3771D4F9BADA29FFE8DA7D
+:104BF0004AC5CE71C2C6F98A6FD94A417AA7FF6306
+:104C0000B197E393AB69B946F64812EA71C2B99518
+:104C1000F6E2087FDF387F0E605B770A59D55521B1
+:104C2000D7F44121F7744DC85D7D58C81D3D2664F9
+:104C30004D1F1312C8897C3A2488F7DEE8A9CD6499
+:104C4000B8FB7B1129778BE71DAF14BCE6791E8A70
+:104C50000BBB8E7B25F2D3C217D1258AA1E279390D
+:104C6000C1ED5FA46C70907D31A1F9D3D14EFBE210
+:104C70008D492F2CF64D99D76F6F3EB1773F77F75F
+:104C800020B36A61FFB851C74041C41148D8C0EB96
+:104C9000D7EF844BA5FBF97597A8EB50CC597271EF
+:104CA0007C7937BE9B38A87E16EE1704FEA54545D5
+:104CB000A59A3AF0EB89513C2D7515606F0779DEA6
+:104CC000F257CA836992C58BEF3F9F25BBDC868C68
+:104CD000303AE37ACA241197892BA0AC4AAA45DE60
+:104CE000BBE1BAD7B0C790CF980B6DFCB7DF37F3F5
+:104CF000CE112AA38D16A595EDCD2C30DA67CB9277
+:104D0000E0C13504D1DF3D60658EF718F101978968
+:104D1000E7F24826E76EC6D32D4F661C7D8DFAF369
+:104D200067355786E7E11F75E8B61BF92A646DA958
+:104D300092451CCB8D3957601F9CBC1F11B58EC38B
+:104D4000136BAF53239E7985FCF3BC31F26FC1F72F
+:104D500057CEB751CF5F646A81E2944DE33DE421C1
+:104D60006E183DE59940291714751E2BD3F92FD6DF
+:104D70001313EEDBE643C7FBACA58ECE74CE9D7558
+:104D8000E636E64D18613E6F7E0ECD78CB16F96D96
+:104D9000F689C1A339773A79D40C9C590327A2D656
+:104DA000FDDCCCD76C63A823231FAE9B4F47D54DAA
+:104DB00037FEDBEB603E9BF696E9FF01EF5C9276F7
+:104DC00081F371B8FFBAF1D6CED3DE7FE6A9FDBC80
+:104DD0006ACE9563E23CEE3D53FF0BC81D4E69F071
+:104DE00007000000000000001F8B0800000000000A
+:104DF000000BFB51CFC0F0030977F3A0F2BFA3F182
+:104E000057F1A3F2CBB851F99E68FC2634FDE7D1E7
+:104E1000E4591820B4033BAA38B15888838141165D
+:104E200088353850C5F3A1E656012DE805E265AC9A
+:104E300084CD7A27C5C0F05F9681E12890AE06E266
+:104E40004B4036931C0303AF34038307104703F131
+:104E50003B190686A940FA25106F9086E8E3048A7C
+:104E60009D9421CFFD6D42E4E91BC5D4C1B7955097
+:104E7000F993B51918AEE93030A8E941F8E791E4A3
+:104E80009D806253B421EC70550686BDBA0C0C8728
+:104E900095B09B1B0194DF07948FD0C36FBF831124
+:104EA0002A7F8B352AFF8B212AFF9A272ABFC11B15
+:104EB000955FE103A10157D509D0D8030000000098
+:104EC00000000000000000001F8B08000000000030
+:104ED000000BCD7D0B7815D5B5F09AC79933E799BE
+:104EE0004972028710601283440D3884F0147512E1
+:104EF00082C6368503A2E6B7B61EA955449023D2D2
+:104F00009AF6573379125E6D406FE5F779A0DA5261
+:104F1000AB357AB1F5B66A9340BD784B21526B6DD3
+:104F20004BDBA05EB55EB5D18ADA5E947FAFB56724
+:104F30009299C34988B5FD6CBCBD9B3DB367EFB585
+:104F4000D75E6BEDF5DAFB285002FA2480E3F877A0
+:104F50002EC0E92200CC1C2AA373A04CAE04D8209A
+:104F6000048D70312B3F94EABBC2EC1D58F1A55360
+:104F700087BEBB04046AFFB3E2F6783F7BDF31F9FA
+:104F80005B712867ED2708D4DE69E79457820450E7
+:104F90000050DAB95C4DB07E368C6B56B17D87BE61
+:104FA000AD1ED878474B159070BCE2ECDFB73702E6
+:104FB000744F01381736AB2531567F4E323642B624
+:104FC000718A691CA7EE8F8BD05D06F4779CFD6F0C
+:104FD000C3CD4948B071DB267FAB1EE156BAAF01A5
+:104FE0003D02F0957149D0D9F3E920D2BC9439162D
+:104FF00098ACAEEA56DC9A7AE2381D889772ECB526
+:1050000033BE3432F47C898317868F0CBC00CC030A
+:10501000D0A0A2DBC27A00E8FBCC7E4D7B7C2D3E8B
+:10502000BAF14F9C3F1F7F1AE88407503BE389C8C1
+:10503000103C1B7C03DD12C3B7550CC6FDAC490EFA
+:105040001BA7CAD54FE67883F3943B3DEB3F15E1B0
+:105050002CA07908B2ABBF4C7866D9ED66B19963E4
+:10506000E9CC2B673E1FE764FD7F06515C80ED3B7A
+:10507000E356C4458FB2E5C17BD06EAF99DE76C3EF
+:10508000E12784F89989F8B1E2488F0E1D4B61BD84
+:10509000A996CDA7C082012997C8C6843100F9F826
+:1050A0002FF689ACE95548AF634CD696BD1F1BB3AC
+:1050B0009A24F67CDCFCB420B332027769AF84001A
+:1050C000A1293D4E1F599CEEBB6674F433BA3D0ACC
+:1050D00091CE8DAC6C9159BF88B7C391F4FD0CA4EF
+:1050E000A6B353F7F6B37AC492A1B992C6253EBCD3
+:1050F000513ADDD8C8487AA34DFF1D8D2A95ED8D14
+:105100001A74FB015A1BE354DE1EBAE5BBD87F8339
+:10511000E5D7FCAC94BB6E7818EB2D00091C2F1260
+:10512000E3FD83AC6AF76B580713F11E29E5E5B37D
+:10513000881706E7B71826112F3FB6F1A44337F1B9
+:105140006B8BB13407B2E0D32943655E3E0BE84177
+:10515000F6E550DD1FCFF3D47D5AA1A73D4011E104
+:105160008DEA4C54AC10B83C8AC87D60209C0C5F22
+:1051700059E5822D572469FA40379B5F78B662EC77
+:10518000649F6E11BCFC354EE0F4512EA854C660ED
+:1051900060CF71C48B21A637B2B182D34BBABA6348
+:1051A00038A6624C66EB18F4A5B5BC2CFC0595F24C
+:1051B0001BFD0EDC259F3E7E24A92795C832EEBB41
+:1051C000F6FA9D7BECA08AFCAF4E1713E97284D7E8
+:1051D0004AB0C9C3665D1671DE9F1EDC23AFD711CE
+:1051E0009B9FDB41A5F632AE57E5D07A75186CBDB2
+:1051F000907F2AF97A75C8963A9AF57A00C0839713
+:10520000D0205EBA385ECA3F65BCB4F4D627B2CCB3
+:10521000A3DD5E4F190CA38CF0A0E808E7E6264E4C
+:10522000B716A3DB6CF277383C483987E3C9F21331
+:10523000F17EB1C0C75960F38983A70D86589B0ED4
+:10524000239E3A6B516E6D2E1545944B9F169E1CF6
+:10525000B8360EC295E670957DBA7049A1EEFA6C2B
+:10526000FCD89EC18F9B106E4E77B59CEEC44F95B7
+:10527000EE1CB802C80F7C9D137C9DE57F89756E7E
+:105280001F5CE7245FE7F8A7B3CECE7E0EAA518F4E
+:10529000EBB642637CC8E0B856B2942B707F0D0920
+:1052A00070BFC1E800E11FC7F4CC70F3F3BA0E7011
+:1052B0009B10E0FA8674594ED205EF0A99E92C1535
+:1052C000F87CF3A9C911E60169DF40BF0327E3DFDA
+:1052D00086C34DEBF7BAE0BC5988C408CED9301B61
+:1052E000E17C27BC34A71B86EFEFF546B549F601F4
+:1052F000BCDF68ADDFEB3BF1FDB512A4B2E99777F7
+:10530000DA7201D42E85E67F13E3C1E98887536BF7
+:1053100020CAD623DC3C06E70161F6722EEB675704
+:10532000A04976E177B8F90CE2D5F98EA93BFEBC2D
+:1053300013BF1FEEBBBF09C97B0586DFB698588334
+:1053400070A9A590C635F0EF5AD25D08C3C3DB162D
+:10535000FBC7C03BECBAD9EDDE0937B733D30B5AE4
+:105360007CC63E9DD1496B816834C3101C0EBD388C
+:10537000EBE2E071B4EBF2C741FADA7C1E909E09D1
+:10538000BA34FD93D3D53EA4AB33FEF974F5CABF4E
+:105390002E5DBD2E14FCEBD295D220E92F333BA31A
+:1053A0005836B99CD4965BB4FE3836934B52E7F42A
+:1053B0006E94971067F6191F064456573493EBBD49
+:1053C0006000EAAF6AA9574EFA8ABC72325E6F7605
+:1053D0003BFD6ED4715C85C645F308C795C3D01DEF
+:1053E00088625DA17E909C8F9FC2F00477D696F074
+:1053F000EF0CFC6EB8F9C8F81D1B0FD58FE3C5F88C
+:10540000DDE7731259ECDEA1F97BC7892F4BE42449
+:1054100022A36F0F61597FC585F7E1BF93E115079F
+:105420002F8CFECBD04F5230847F73D7F5E4BF086A
+:105430008068905D57D46EE1DBF5F8FFE6E2BECF01
+:10544000F97A7D518586FA16B0FD069F5BC2570139
+:10545000EB7F1374E25B673C299C00A21BBBDDC998
+:10546000D6FF46E4A72CFC7D99C8F58DF76F49FD62
+:1054700019ED416BA3A0DFCFF07AA0F1037889F199
+:10548000E5F2EED314F47B5C2E8EA176CBE7172BDE
+:105490000B5CFD2C076E1702F4CB4B22EE719BB810
+:1054A0001EDA25F5E2BC5F9C23A571FF7B71CE5F00
+:1054B000483F7FD194D288E4173B2ECC1949EE1C8B
+:1054C00068E4F6ACD3EE8029D1FE7E40EE0F67D3C0
+:1054D000E387C64FD3F88BE748DE7D5AEE9771FD20
+:1054E000DFBF197CA83F1F685485972633E317E771
+:1054F000C9E868F99C6205FD0E279BD705B61FCC4D
+:10550000C1AF33CFD6B048F36C0D5793DFAA557BAC
+:1055100087ECC7A3EC39CA83E1E075FC56ADDAD25B
+:10552000ACF850225CDF527CC9ECF6A63D5FA79E2A
+:10553000E9CFFAA4F0B565C0D71EE67A56BB9CCC7D
+:105540006E4F65C0A3C4448F9C885DD625E03E376E
+:10555000168C67A614131A0FA1FF64822D7BC61E3A
+:10556000FE4DD3D50CDE0357844D218EF5DF091394
+:10557000199C5AA1043E56FFB7656B7B7E8FFEBD1A
+:10558000FA10481A836BD96D4D8C5C61FCCDF7091C
+:1055900058DE8A76210A5EEBCB4DE8B76AC54EE746
+:1055A00001DC257EBE0AFD6A327039C0A49C2E8FB4
+:1055B000417F0C9033663879C0FE84E3FEA1EF860C
+:1055C000C353C4964F344F924F4B47964FEB78FFDF
+:1055D00016FB0FE5CBF8A1F1E8FB712B14CF3A8E47
+:1055E000CD78DF6BD3A11F96FC53C729848A00EACC
+:1055F00023913A514B637BE8CA45BF536C950CDD50
+:105600008C6E0A2B3B059F7E72BC333957CBFDC491
+:10561000A6E0E6AB5FDB7268E2D79F1304F4F31AEF
+:105620004C859F8EF586E9D9F8E1DF901EFDAEFA34
+:10563000B26A01DBB5327A2A4539B64C243BF7D63B
+:10564000BAA5B9EEEFDF131DFBD8597FD0E5595845
+:10565000E7EB2FD7896660DADFBFFEF2C75CFF8217
+:10566000758A872F3EEEBA88686B149C7CFD3FE9F3
+:1056700038CEBA9DC81F4DF6BA9506509E6CABCD7C
+:105680002EBF865FB70A01F7B7581D98E92CDFF9DE
+:1056900025C123679D528514186C9DA5E724D24F20
+:1056A000A4B1B3EA77C0F0E34A3125C35EB3FBB3DC
+:1056B000CC3DA56CFD3F07CE5F9F8C72A62E2EC100
+:1056C00046669F41A5EF65B73F84ADF0509DE1FE72
+:1056D000CDAFEDD97B37FA97E6FAC95F9AF9BE0EDE
+:1056E000EB2E7AA891B8FFB4F7B15F9F2AB0710E84
+:1056F0001A7EDDCF1EED17FA5E213F6F9544FB2F1A
+:10570000C2A7CEC2EF81949183A664D6B0F67D95F0
+:1057100002ED9B7E78F68BFF97BE0F517CA36FFE48
+:105720004BDF388B7DFFB9B37DC8391C13F83D932F
+:1057300095807ACCB1FE6F9CC5DAEF3F3B7F44FD8C
+:10574000AA0EE7EBA293C54F78EB9722BDB1F5E81F
+:10575000FDFDAB7577B2F10E424EC28FE51C0EDF38
+:1057600041840FE9BEFFB7AFA01E78C014C8FF7414
+:1057700070CE2F63687F579902E9878BE60B697FAC
+:1057800096792E9A7FFDA489ACBF8411D202ECFDDC
+:10579000FEAAB7379FC5E05DFC1FD2162CDF7A5CEE
+:1057A0002A48960F0FAFF37CB1E97D3EA80743D29C
+:1057B00042BC83C6E310BE981177D3EBA0DE22274C
+:1057C000CC6CFEB59512F7370A9A41FA9C1C56002C
+:1057D000E7315CFB2B87A1DF1C18E896100E47DF32
+:1057E0003E76A1BE64EA897028722289E3489A0253
+:1057F0003B71DFCEBD5877CFFF66079EB849F028D2
+:105800001A8747910D339B7FE9AB363C4E3F009D95
+:105810005417E203D01F1E82AF2D90A8473F8595F5
+:10582000CBFD85AD11AFFFEF519B8EBF6D97AD3EA8
+:10583000C81A470168A6FEABC7CC51B1FF96395CC8
+:10584000EFD0C1207F782BB31361043D6EB3AD77E9
+:105850006CC478861FE31A9A1DD788737D24FC28B0
+:10586000F9C58E968B64C70CD74FC4F0EA43A132BA
+:10587000AFDDE2E82B013D2FC3EFE3F5F3F8C6C837
+:10588000A2A34721BD9E0CFE41BDCE6EB75E4EA9C0
+:105890005A563CA547D4DFFE79F8E3DF877C5D5A92
+:1058A00036B8FE517873E82AB37F255F49A5294EA3
+:1058B0009788BBE9FFD7365D29F96A0AFD9FA00EDC
+:1058C000F73EC8BF0FB3F718BF082774D42B25E0E5
+:1058D000712015F9C0859F3FDBF45F2F8B363FA603
+:1058E00028EE29E829F2D3A9458C7F8413BF73CA17
+:1058F0003FD8E3AEFFF08617883F0A54E20F4167B6
+:10590000FC93651C4B325F9758FB5592F93F58FA50
+:105910003E9292D9F8E44F128FE7AA75095D2DA146
+:105920003822D91F9970F8653EFE950EFC568AE222
+:1059300092A385FFBD51C2EF8CC3E017E59904BF68
+:1059400084E570F00B363C79A037C928D7742E5FF8
+:105950000196E86EBD64B9DD6F9E2D9F00AE8FBBD2
+:10596000F5C02FD8FD8C763E9A3CBAF92C1F9A4F81
+:10597000913D9F0923CD67BCCCD763B9CCF73BB52C
+:1059800026A1C7D9BAE40E4357F364BEDED70DAEE5
+:10599000CBF51F8BAE4E1BE53C9C71D83C66CA9C78
+:1059A000AE668D348F4A1B9E4E09E6BE8C7AF12975
+:1059B0008E7F67A9675D6EB0C7EFF43BEBB2D6B3DD
+:1059C0002ED7D8F818ED7C168C723E370CADCB6212
+:1059D0007B5D1223CDC7D5FE227BFE17DBEDC9EE22
+:1059E000B8419ED28C768625252E95670E8DC7DA16
+:1059F0007D5E2E186AF7E796779BAC30B5BB9CDAD4
+:105A0000D5F2FD8FB54BBAFB032BD28CFE8036B49A
+:105A100015981D53D23AB7DAEEFF2AFAAE6EB0FFF0
+:105A2000ABDDFDFB5BA1D9EEFF5A7CDEB4E023A722
+:105A3000DD2A2FBCA73BED52D84EA81984E37A7714
+:105A4000BB797221CDEB8438C328FD3FBE58B20329
+:105A5000E3FA7910E9C4BC8E7639752FC6FD2D4B5B
+:105A600086FB317FC06F08E8538BCE497D17DBE59D
+:105A70005A7E8DF23FAA530F63DD1221D15249F9AC
+:105A800003941FD020AB9ADFC07C0B03B6B3BA16C9
+:105A900093D39897D326242DDC177F2E2537CB243C
+:105AA0005FB5CB9AB0FF7C9DEBE9D04FFB9603D757
+:105AB000D6D01729DF2197C185FEA7B60CB86E0F87
+:105AC0004DECC1FDF6D60285F464666095A17CB903
+:105AD000510A1AD85F4FC15709DE6D4D3C9F61DBFB
+:105AE000E7BE4AF0DE2600C5696FF3F17C86AD3E65
+:105AF000556BD6B0BFE8B82F53FE438EE6AFB4E186
+:105B000040F83E5B42F0E5835675A540E2AB07EDF9
+:105B1000DBB6390AE9CBDB621555D4DF1C95F4D42A
+:105B2000DB12154DA477CC09924F3E3F6C90DD1AE5
+:105B30009DAD8085F598D1847A66645610735E2099
+:105B4000BF083099002253208D751F747696B232AB
+:105B5000DAC1EC927CEC6F295C8976EF1C8677B415
+:105B6000232CF310DA2561B0FFA4FD26CEDB375ECF
+:105B700002C9185ADF68E7E0F723DA5DD1F428DBC1
+:105B8000758FAE5DA483D9FD3346D1AE7394EDD24B
+:105B9000A36CD7CDDB9DD4DF61707B4F65FFA1DDAA
+:105BA00016C8B067516FF7C4F332DE67C6DF32CB79
+:105BB000CCF8C76BB237AE76B2EF9DB8C7C9E68BEB
+:105BC0004E894138A593B777F4CDE1DE2B8517C711
+:105BD0004DF67DDBB84BE324D7C65DC6CB09F6F3A3
+:105BE00009F576FD52BB7E59BD9945BE17F8F83EC2
+:105BF0005486FE9011D6211FB8FEF80A83FDB880A6
+:105C0000C94A23FB4F32F5DE4C79A7CA5635F2EB71
+:105C1000B604CFEFF02333221F1601F9357D90EA49
+:105C20002C4539016674E19821FEF1994F9BC8CF4C
+:105C300007C64920CCA1F531C87F9E41279974E160
+:105C4000CFF0E77C523A99EAF3C6C9FE5174A274C8
+:105C500048A3E21FA57394EDD2A36CD73DBA76FE9C
+:105C60000E6174ED3A47D92E3DCA76DDBC5DFB5C12
+:105C700085EFE7F058B359CAE09EA77AEAEDF382C0
+:105C8000DEF767853DF5F53315DAFF9DBA7F96EAB5
+:105C9000A9AF6772DEF37E7698EAEBDB7E5ACDB66B
+:105CA000B251F3C97FFF9D7C52A69EC42F3D47CCC5
+:105CB000B0DB32F84AD503F87DBEAC03E64BE5C74E
+:105CC000F83EC5CAAC7EB9BB6DFE4FCB1A95DB64FE
+:105CD0003D80F6E3BFFA3C1B7D1C5E67BE2783D781
+:105CE00091BFAF4AB6BE355C9E470DCFC3942148E5
+:105CF0007998A53566B5C9E492FC0C8F7B65F67B77
+:105D000099927CD8E7B2F7652DC9E379767F1714AD
+:105D1000C8A497C84CAEA1DEA340A2B698E28622E2
+:105D2000F9FBE4F049F68D2297DC2A19016E3B6FEE
+:105D3000955EE90055AFF1718306907C8D403F1967
+:105D4000D339A8F59C827A9A2E007D6F08DC7F3EBD
+:105D50005F4379160BFCA3FBBD8CFA15CCAD703CF0
+:105D6000F431FA95FBC9DFF90FEFF724F006309F05
+:105D7000F70C0A21C4DCF9BCBE788A1EC2B1E3C7A5
+:105D8000A559C03FA1BF24C5D365D1207F281446A3
+:105D9000C92E6B8BAD55DDEBFA575F89378EA6B5F3
+:105DA0005F2F445959B4CAEC1F81CE3FC42018FA62
+:105DB000478AAE34FB47D84F07E397189FCFC207F7
+:105DC000ED4A328DFABB3531CCED7939457EC6F5D9
+:105DD000425EC5C64A17FD1629DD0857D8302DB4D6
+:105DE000F7D6E78B06EAA9326CEE13A6B1EFA43A18
+:105DF0002399458F18FA5E7EDD3D9F3CC5BB4FB6AB
+:105E00009C84DE9DF8E470EF7D8A91CCE60F9DAC1A
+:105E100070BBD617CCFEFEEB62758932F344BCE151
+:105E20007680DFADCF850EE14C4E3E94DF50F4F42A
+:105E30000B8887B682F3E223CD17346F9EE555A217
+:105E400079A65230221C33B2C131DAFC0F8014B370
+:105E5000D186E225A81F096330AFC3F933A015ED41
+:105E60000B667F60DC23586EC07DAC1E5FA026648D
+:105E7000A62F6DA9DC09E8AFF631FD89EC13693E68
+:105E8000D79FCAB83E64B2FF701ED1F923EBD5523A
+:105E9000467DB1E2D59B5B1A1F078CC73BF03B7E6A
+:105EA000BCCC79CD13AB2F520AB2E16374F6F0ADDE
+:105EB0008C5E9872075B1B552ABFD9A851B9A531D2
+:105EC0004EE5A64646ECE81F6D2CA3FABFE1A7738A
+:105ED00091CF531DC50C7F1DF1FB5EB812D02E056E
+:105EE000DB4FF08505A82F6FC43AE901CC0CC4FA4A
+:105EF00004FEFE7A65D102B4F337069CF6D50B504A
+:105F0000AF1EAA5FD45285EF6D3F43877239B5BF8C
+:105F10007502D8E7184CF522D7BE77B7E2A379E02F
+:105F2000DEC2BF3FB705FB0BC84E3D45F00CD63176
+:105F3000E08A7595D77BDBAFA7FE4904B0F1FEABD5
+:105F40007DED02F42FDC3A99FBF961D9D293E0910F
+:105F5000FBF53FC2A02FD2E5B23CCA5F5118DD94D9
+:105F6000B047B7E6DA708FB21F90937CBF7B2EFBF1
+:105F70007E39C43727D9D76C384ECE0FA6ED874867
+:105F80008285E3FE8AF3C53F7BDC5B7D1F0F2FEA32
+:105F9000FCA489DD476BBBBA71A9E729C91F22DDC3
+:105FA000E7D4F4D1B6A2C4BBB9DE30CAF1B72A9A9D
+:105FB0001D8F4A92DDE4E0DBD13FFE94B19EBE9896
+:105FC00049F9478130E7C3D1C2FD071F3FC7E3F45A
+:105FD000030F568C1B49CF8AD589A88C0DCA8DBC5E
+:105FE0009AA0A7AECDCF43236DB01EAD2CF4D4C381
+:105FF000E5259EBA4F3BDDF3FDDFBB5EBFB4F54543
+:10600000A7FDBE8CFA9399F31C65BF4EBDA77F8197
+:1060100058C6D6E1F9F912C5439F9FFFD26D3318D8
+:106020003D3E6FE2EEC9ECDAFA161FC633FA980A63
+:106030005289FB7052B2FDEA3001F1F92BFC171BBB
+:10604000EF97F6FEF7AC7DEE876DBC13F09CD4B3F2
+:106050000BDF2FC2F57BD607B65CEA24B97070B0AF
+:10606000CEE5C2C100AF9FE9DFDE8272A04FE075CE
+:10607000D1BF7D01F73B6E6E3F9FE92F8BF19F6C87
+:10608000FC65F305339D657F0BFB15271F32EC671D
+:1060900078326B4C5F01E6BDE9407AAB1F12A49FDA
+:1060A00035805525A2DEC3E88FE2DDB236211B7DA7
+:1060B0001C6CE4F9027EB890F4FE65F3A7FBD0A84F
+:1060C000F727DE96D14FBA3821F8C0D69B35177C1A
+:1060D000A2299848DF89F9FE9DA83F2764461259F6
+:1060E000F691C5A6DFB35F196C2C84BF4FB0F914CD
+:1060F000B409EEB893E1E7764FBC7464BBC181DBB1
+:10610000A95F38FFEDBDF9E86FAC158CC9D8ADAA11
+:106110004DF862C4DD6FC8891347B0DFE7EBBFC439
+:10612000FD1A8C2ED0AFFACC91AB7D149F5D96EF0B
+:10613000E1BF6575DEFCB6A535214FFDE2F923E729
+:10614000D741D29F21D72CFBFCA548F278E361818F
+:10615000E443CEC48134E667C2F312703DD0F1C38C
+:10616000CE233F6C74FC808EF9A2F0C79076BF4BB3
+:106170008EB666E021B37CC2CFF55B39AF96E2DC28
+:10618000EF1F1174F4A70A790D5370BEB26236E3A3
+:10619000B8ADC5621AE3DF37966C5371BD37947E94
+:1061A0003C7DD017E3717FDDD22A90FD87FB2E6DF9
+:1061B000F2BCB6CCE7D7FA79DCA1CD5AAA9522D3A6
+:1061C000ECD5AA70FE8122C87ABE94D1FFB57EF2CA
+:1061D000BB5BC0E3EC09D2AF4BD5E5947F2B178EA8
+:1061E0001CB7CDC49B6CC70333DB3D68D363E99C0C
+:1061F0009DD4EFFBA78DDCAF83970F0C11FA102E07
+:10620000A657607B15D87C18FE3795F1FCDBD6F2DB
+:106210004709CF9259457AAD4F4B99D86E53F972D1
+:10622000A2CB36D6269F0D9D5BD345E733377DC87D
+:10623000E3140FFAF7B6A05EB1A9E71AC07CCA60F2
+:106240003C0D283F364DBD4A453C6CDAC1788BF495
+:10625000992E72CE856CBF78488334B3A840D6BBE4
+:10626000BA512EC8B56098EC556FBC1A70DD365522
+:1062700072D6CC4FA79A3004B4297EC8C4F8446BB8
+:106280003D50BE4BB0CCAC2D46F8C789240E7448A7
+:106290007660BDB54EA6F9B46B1C2F68871D77F2EA
+:1062A000BD302FA694DB61A5E8EF67E32837F3F94B
+:1062B000EBDB4BC96FB42957A9473967DAF611D31D
+:1062C000532CF4F3B7366859D77DB3987CC0EF925E
+:1062D000EFB296A0FCA64CFCBCEF83CFE0BC5BA762
+:1062E0008BB0338BDEF1233FB74BD2C6D2C52559D5
+:1062F000C679C2AF7BF611FD0385E01DAEFD503BB4
+:1063000099FCFB68805CC0E65150CBFDA690717E85
+:10631000350649B273C782D584FCE89C5B1D5F9348
+:10632000F84D9295526419E5D50D778ED5C9E75C85
+:106330003E07EC3FFD92DFB1F95EB3CF0788B7733C
+:106340008FDDFB34E64D39F606DB979E7E92BDBFAE
+:1063500092A96558BFE6F05405F3809E2F9430470C
+:1063600006F9278A74F826889487F6261C8ACE7048
+:10637000D1F9FFD8FB0E4A5694232DB97C5E72B832
+:10638000BD4F8AE27ACB56BF93C747F60FCF6787D8
+:10639000307BAE52165213C9BF0E9E37E4E4497EDD
+:1063A000B9D39B4774F5766FFD2A583A06F9E6AAE9
+:1063B000DB7C9066FD5EE3CEFF62E3FFD2CFF58328
+:1063C000AB21D58EFBCF7A5BFF5BFDA3A90AD2F58B
+:1063D0003533B4623C7FE1CCE32FF6BABFCEF8543C
+:1063E00077F1FFCA589AF29233E7F7E6EE05DD49F6
+:1063F000567F499753DCDEF6CE73BDAF6F11E67D55
+:10640000595B7C8EDEE0C9775CB9ABCAC4BC31860F
+:106410003D3DDFFB3DC1FFA50EEF7C4F868FCCF9E4
+:106420003BFAE070F3517665D72382AA376FAA450D
+:10643000E57147B34586C039279E8BB6AA5374AE23
+:10644000D96AF66B2D318A53521CB081110EC6F9F0
+:1064500066A83ACF730F4C4C039D3F48CDC673E1FD
+:106460009FB4DF392AE7C37F74BF670FD3EF6AB5E4
+:106470005F41FE5C2377D60A2543E702023ECB1C30
+:10648000CFF0ED7F7C49F778F0B4EB1865BB7D78F1
+:10649000F47914ED6AC511FA7BCBDEB7FEF3C16F58
+:1064A0002BB87FBFF9C0914528E7AEFD89042A6B60
+:1064B000F7D68311E8A67D27ADA03C5EB95BA2F5B7
+:1064C00007B97BD6859E3CFB169AFFB50F47687FC0
+:1064D00058F9A83F5DC7BE5FF9C397A601E3DBB7D4
+:1064E0009A079E1E8FF87B40E0F90C56FFB40BD93B
+:1064F000F395325C9E2D1F21A972BE7AE33F42F5CF
+:10650000B8BF0BBB7ABE48FD765DE2F3BBE4EF2576
+:10651000AACF6947FAA3F53D213D59E0F065CBCFFD
+:106520007BE37B3CFEB4F2715F1AF31557EEDAA100
+:106530002459BB35BBDE26FA5EF0F04351C4C39A42
+:10654000C7BD7ADAB50F7FD83EAF92CE390DD4A150
+:10655000FC938E51FDA8A90E70CD9FFB67AE238ED4
+:1065600065EDFEFDD5F37EC7DEBF1E9720C044CA91
+:10657000EB7DFFADFC04EBC9708A8932D6BFEF45D5
+:10658000371FAED9F5129D37D24418283A0BCF41A8
+:1065900064BCCF680F30A0A03C5CD3B5E16D94978C
+:1065A0006B76BFF95BA4BB3520BFE8E6E7D7F11FE8
+:1065B000E34E8C6B75A85E3FCE51D83F0BED16D8DD
+:1065C000959FD55E74E25A0E7F5FFBD0D17B508FD2
+:1065D00078E3D1FFB907EF6558F5D15FEEC1FC56FE
+:1065E000782AA0A1DC5AF3C0AFA2E0C2FFB76DF9D0
+:1065F000F0D6F7BEFB9D3B181EDEFA8D9FB0F6D697
+:1066000093AF4EC4FB39DE7AE4AF6350FF58F7E432
+:10661000C2B14867EB1E5B3076A4F39F48B769BFF1
+:106620007B7DD3FC5E83C705DC04D9866B9719EBB1
+:1066300002FB0714D47BDF136060632E7BDEF5A1C1
+:1066400082FACBD3260C209EF6EC7EE9E9AFB3FAB2
+:106650009B6C9DFC59D689CD7FBC48FB1B631F56A4
+:106660005EB7FBC2C5675762E933B0FB353040FB0C
+:10667000C609EBFB1C5BDFCAA1F5CD7C7F148E291C
+:1066800088FF350FB2F59C86EBCAD673DA89EBF931
+:1066900026FE63EE89EBD9AB7AFDAF4761D5BD77B6
+:1066A000E0CBDDF959ED5B673D573F76D1887AB98C
+:1066B000231F4E86673AD7CBE0FA866A1E520B90AC
+:1066C0002EBEFF9D3B627C9DEB1862DE7AE8E844BB
+:1066D0003CB4F19A6FE08B88878127FD1AEA512B31
+:1066E0009FFC35F1DD5B8F3D4BE779D85F5460FB54
+:1066F000DD5B30F8770858FD3A815756EB03E7FD2C
+:1067000096F5BB9A756119B47EE7FDB612D74F1D99
+:10671000A0F5482FA9D551FEA60B68DED7A5397F75
+:106720005C97EE59867EED4CBC87034E5EE1D0BA95
+:1067300062BCF9BADD47CE43FA1B6E3D9DF96B385A
+:10674000FFD9ECFD7D5EFE1D965FEDF57D6BC7FB11
+:106750000AEA57DD3F513491D9ED6FF9069442DCD6
+:106760006F1E91343C679CB9EE43F86FCE7ADE38E9
+:10677000B3CCA40F25903D8EEDE0E964FC7EF2F9E8
+:106780007D3CFCBD6BEF9799787CE358F6FDA02427
+:10679000C0EDB9EBA0B31655CCCCFDCC07296B7C72
+:1067A000F110BCED5D12C9F9377649148FCB9417FF
+:1067B000D70D639F19CE388FF74C43B9F646EF7F5C
+:1067C000D874C9E9FEBA078F2896BD3FA45DF85D6D
+:1067D000339CDFDBEE6FCD13D9FB5BF3E0DB59FBC2
+:1067E0007B5D362F41F85FEFF3517ED2EB5D525661
+:1067F0003BB734E0F3E85DED91592FE460DC201AFB
+:10680000A4FCAB9666F3D7E82FB50EF96C3F80F188
+:106810001AE65DB5448274BEBD257A15DD93E4F4B5
+:10682000D79A8127399E20FB498E252A792C2CED79
+:10683000896FF91841B8E106D92A42BDFF40F1AB92
+:1068400032F68B7E15DD65D71F94A10DFD2A074D0D
+:10685000C168822CFE8D8CFE13F325D0DD7EC2EE46
+:1068600071E2BBEC7BFF73521A51DB00A96E3A1F39
+:1068700050045DF767E9EFAE469DECE7E2C4E5E45E
+:10688000FFF1A75226EA6B45EBB412511F7EDC09DB
+:10689000296F1CBB9051FEBB38CE3E1FE983B0EB85
+:1068A00081071E18C3B714D4CB9FC692C9BF7357B4
+:1068B000E84558BFCB9E37E3013ABF38C14AC828E4
+:1068C000E784D812F2832D4C25E4E5AEF55C18136D
+:1068D0000A713F4D0F73FFD30F037CFF6C6ABA98A8
+:1068E000F2D9EFBC5924BABE33707E11F2D9DEDC86
+:1068F000D961CC57EC593D6BFF1406E7F8B004683A
+:1069000072EE098FEC4FBAC7F62FECB4EF1DBACF79
+:10691000CE33FF8E8DB75D8D65543ED068D0FB07BA
+:106920001BE750BDABB196CA471B13F43CFAF560A8
+:1069300012E97377633D3D1F0F6F0BB8FE3F6C4C40
+:1069400052FDDB815C827FD24D2026D9F385888F72
+:10695000F0D0BC1D78D2B6DDFDC30D4FB5A21F62CD
+:10696000108F19F83E17FA0415FD573141C775BF4E
+:1069700031C0E549267E27FA07048CCF35DCC4F305
+:1069800022EE11BCE71EBE65CBFF476D3E7D3B9AF4
+:106990007C30C0E07CA7765919E943A09523DDDC63
+:1069A00023240E1AC58467CFF9939579C947032E1E
+:1069B000BA99D8C1EDFADB035C3EE9EB40447A9B1F
+:1069C00090021DE9CD99776F955E8472B15710687A
+:1069D000BD91DECA5CF4E6F4776780EBC110CFBEF0
+:1069E0008F0FD12FE7FFF8BCB2AD358897B522F9EC
+:1069F0002D5BF095EBBBBFDAF364768B68213DAF7E
+:106A000010C99F3BE9F0116122834FD7BE1F403F61
+:106A1000747C22D8FEA6AE00D2D79D2BB87FF1EEB3
+:106A2000C3FC3CD3D175254BA6B0F68B187E30281D
+:106A3000957741698E3B7EEA9C63B85B4DE46823A1
+:106A4000F8B732F3DF6E9F74CB07396C9CF1874344
+:106A50003AFAD7B74E7AAA4761F5C27E81FC4985DA
+:106A6000E1D4145CCFAA3F7C6F5CBF6B1DEE589DD8
+:106A70009A847A63FBA41F08C80785C77E2AE03E74
+:106A800032494BBE1228C0FC70FB7CB09C9A8D76BC
+:106A9000C1A57989D770DD1245E9FF83F474B47616
+:106AA000DD7F62FF4E3CB2A141CF9DE2920F99E79C
+:106AB0002AEE4A8DECCF74E67F17CE7F8476CEFC2B
+:106AC0009DF53B5A1B5B857231139F99FDE65DB0C6
+:106AD0006CC4F1EFB2EF0F63F357822EFA2C4AF534
+:106AE000CBF89DF3FD70F1D7CCF90EFA894619AFBA
+:106AF000EDF2413ED2C523FF3BF1DF0F02924E4241
+:106B000042FF544F20190F16E0BD7129AA33E948FE
+:106B100079ED67E472FEBD63CC77C611DFC9E96227
+:106B2000CAFF18E5786D904854E13E678846B67D07
+:106B3000A03CC8E5E77C48917F540CDD3472BCBFB3
+:106B4000C81BEFDF0C3409B0BA553BFE01B286FE1C
+:106B5000B07D5081FEC7BC2087BF4AE6F6E58C7D3C
+:106B6000FA0E89FBADA4251117FE6CBF9D8F77CD62
+:106B7000E0BE09341DCF7F4DEF115CFCFA7E287911
+:106B800036E24989EB744ED6174B925F72A1141608
+:106B9000C99FDBC9E57F0324D4D3785C0670DE3A55
+:106BA000C445DCEFEF5AC7CF8DEB5A88E0BE2BA669
+:106BB00053BDC1D6531EB1F5FA876CB9FF7D5BEEAC
+:106BC0007FCF96FBA55DA9056106D7776DF97FBFDD
+:106BD0002DFF77A2FC67E569F7F5C3F72A491E1B6D
+:106BE000985FF08D6DF16644C13D8D26BD7FA27129
+:106BF00005957B7EFF7C7588C177DF73DC1F7CDFAA
+:106C0000E1319FC1F859DA140D81B5BFCBCA131F0A
+:106C100067F51DEBC49D28577EDC98A2EF76A8DDB2
+:106C200012EA314799B56C2119BC66B68458FBC885
+:106C3000BB035A2D2B77B41E0AE0BCF33E2702DEBD
+:106C4000D3E7F051F40F5FED8EA21C9B290691ADA6
+:106C5000F20ABAD553D04E5F27523FDFFCD565EA22
+:106C600002C07B1B5E84D5ECFB095784293FA2E858
+:106C7000FA97CDD5ACDD9697C394AF5DB1AFBFFBAE
+:106C800021F67ED68A08D5CBBBFACD2DAC5EFA06AE
+:106C9000AF4FB0BCFC71FAAE7EF321F67D712A4A8B
+:106CA000EF67EEEE6BC2F9FA2ABDE7AF72FED031A4
+:106CB0006E0B836F22187B826C3D1E1352BD01F454
+:106CC0005B2CE1E73C0AD2C92ADC3AC66EEFEAA1A6
+:106CD000D07F0754235EE3BF7D217E0D2BB7E147B4
+:106CE0008C2E66EFE5F8B8BBF5C50BCE67EDF6ACBC
+:106CF0005B4BE715FCEBD6717D88E10DE5FF84AFBA
+:106D0000EC15AE76C989A25639ABFF6E5BD04FFC4D
+:106D1000D1B66E59620A07776F18F5BE52EEB72CDE
+:106D20006EABF1E439397192BF09C96D41D23F7937
+:106D3000BC44D652F47C06E37DF4B3C28D22D797CF
+:106D4000127D01B73F46FF0ABF9F2D138E9D4199CB
+:106D50009F77B46A5EDBCFE6B765A62207108E295F
+:106D6000F6FD2C763CD269CFC6DFE9966FB2C6E15C
+:106D70009AC00C2505E15ED537EE21D6CF072967ED
+:106D80003F3383B89FFD68AB48FBDFE64A7E2E7039
+:106D90008FF14E37DE73E1F0559B21121F6FEB83AD
+:106DA000349EB3D85659927B1AD2510C77719AAF50
+:106DB0008A782EED93C1CECFE945FFB81FFDE38C55
+:106DC0009E4A0F878E88E407F4E683175B5E7A108D
+:106DD0001BBCE7F02630E5C79DBFCC2C9F213AA312
+:106DE0007DB6A617EF51388AF728A007C532A355FC
+:106DF00063C874E2CA917493847EF8D28C73077767
+:106E0000D8FC7E8F7DAE108E5D0F28BFEEB0F38B69
+:106E1000EE5825067586979F598768FF9CD0D05DF0
+:106E2000458199C33C8FC2C9B7F6DFA435E33E5B09
+:106E30009CF2E60D5566E45D977EC2BCEBC341AFA4
+:106E40007FAAF7C74103EFC34B3F2719A8D77EE3BB
+:106E5000EB33480E5A2BB9FE925E917707C697F234
+:106E60000530F0B9D3AF63C7BE13CC23BE49CF659D
+:106E7000EF7398FC88745DB002D70B72B4E6189E6D
+:106E80008FBE117E80FDAFE0EB5F550474BF4E51A5
+:106E90000C28CECFCA8DA7227FAF1331360EC76D17
+:106EA000790F6ADF33F83CF73322DD9F53DC6A9DAC
+:106EB00086F3EC9D575888F4B139CCCFC1B4083C67
+:106EC0009FCB2AE0FCB023D24DF9A15B6A4568C68E
+:106ED0007563B833B09FE5C19D94D782F0CE24BAD4
+:106EE00023FD0B6315C88FD61541BEFF1CB34E435F
+:106EF000FF7234D4DFB587F5135EAF183B512E56C1
+:106F000079EFA99B1CE2FA5E20C4F73FC62F8110DF
+:106F1000C6F93703E531B2B9107F33BEB280F60748
+:106F20008DEC2B27CE1FEDBD402C9ECACB1217FF38
+:106F3000EEB4E56DDACE5FB8C7DE471CBDE30E7B6D
+:106F40001FD96CEF1FC5E6E26605E976054C473CA4
+:106F500095AEEA129667E1FF533ABC7235935F260D
+:106F600065F24BCA7B6E75FC8A12CFFB8871BAE75B
+:106F70003D856470DDD93E8E785E1F289750FF9B5B
+:106F80000109D32D5786D303F282E634C4DF68F5B6
+:106F900092682891423D34530F3FCB5E972F0412E5
+:106FA00073B1BFE8BC7ACAE75915489C45FDCB6967
+:106FB00001E5E97CFC2E96155E4A061B05BC351FD3
+:106FC000075E900D3ADF75A3E4DC67EB3DDF051942
+:106FD000F7D766DE4F7BCEFFDE44F7D3B6094CE130
+:106FE000C37A8E7D3FAD9FDF4FDB16E1F6579B8F57
+:106FF000E7AD5D67E3E1F210BFEF75954DA7E7845C
+:10700000B2DF7FE4F8BF52281BB0DDD8ECF78EA1C9
+:107010006685FD9D333EFBFB5448E1DF4F1A799CAA
+:10702000B5380EEB6766D05C1D2A18C2D38C90B9B8
+:10703000C65DBF2164E715C909D22F4D99EF877A44
+:10704000D05CE76EE794791754D2F9BEA3F6F93E07
+:10705000F6DD7681F02A69A3C1BB6307B409FA564D
+:107060009283BF62FA5F96F5783F18B5C49CA1B8C9
+:1070700094A327ED0A71BB97D1DB06A20F266110FE
+:10708000EE30E85BF15E88F1780FB78EF6E7E17BD2
+:10709000BE8DF2F6ECBE5AD4A356FF58A2FBED4EBD
+:1070A000C0D72A4677AEBC14E779E107E3C91E9E34
+:1070B00020256F0FB9F6E9C215030AD23BC25FC3A0
+:1070C000E1E7F9D442FA346E1700C573DAAE897B72
+:1070D000F20B33ED923CBCF780E48A42FA5D265C09
+:1070E0008E5DE1D433CF271CB0E908FFF431784F2F
+:1070F0003870A5563625E4AF9990A47236E854321C
+:10710000FBA50BD793F19F8E703687269E85F3F8EB
+:1071100027E2EDA950C1BF1EDE1C3A2E4E9E3B4811
+:10712000C7D9EEBFBE3D142579DB7038B2D34FFB13
+:10713000C9D788AE2546D7A8F73A79330D60E7D589
+:1071400087A10BFD94C5C9463A277A94D131F62B15
+:1071500069FC5CAB0C5A02E337528CF3874F2ED399
+:10716000440DE3B3961FF51EAB040C94B5E8977479
+:10717000C35B194EBEEAA6BF1B0F6F2579FB854086
+:10718000F275C4EF8DA5961F353B971C7EC32D87E6
+:107190000508EBC87FE71CE3FB65555297911E1667
+:1071A000304E47BC2F8424D5CF078BCA0B204DE52A
+:1071B00067F18A23D2E3EC730CDD9788EE730C83BE
+:1071C000E7E12A9DBC0E1EAF2AB0E9106C7BF56783
+:1071D000F54B9B16B2F1D9E29B1897FA563DCFEBCF
+:1071E000F1CF96E93C6B41FF1575182F82655C0F56
+:1071F00073F221F2EABC7ADA09F75D1DFED361FC75
+:107200002EF3DC9CA3AF65EE5B4E99A9AFE58587B5
+:10721000892F0CB3EF64C6171AF09FDC8EB5EDEB27
+:10722000448EFBDEF8CCF240E340EB5E57DEF941E2
+:10723000BCEF28EB3EC0E3BED1DE3FD52DABA4FBB7
+:10724000E50C4C9DEC6BEC3EE7E5C943F670627EC5
+:10725000EECFD02F9DA8C9AD407B7251FCBDD6BDED
+:10726000F9004BCC9E735E76CDB34F63D066D113DD
+:1072700006C7337D7F73EFBF6FE0B903F44FD8E3E8
+:1072800045EC38D97AD1F213BFDA7EB8778BB8BD26
+:10729000EED8F9D9E6DB4AF8EA0F233D0C37DF2FA9
+:1072A00085F97E3AA6DEA0FBF25BECFBF25B2638AA
+:1072B000795C8686FAE45561EE8F5D1F2EA5386BEA
+:1072C0004BCF5CF22B17ECF7915F7DCCB2A460B989
+:1072D000F645CCBF473FEC37997EA753BE7D19D505
+:1072E0007BAB66A9682FDC10A9A0B8EDC646C39396
+:1072F00037E2942DECFBA4CBCFD792A8D630EEDBAF
+:107300005A57A1A2DD217DAE92EAF269159DD58C76
+:107310009FBFB079DA7905189F28E7F7935DCEEA29
+:107320004DA500D561BECF1E305E0E239EAAC3BA06
+:10733000433FB48EBE6549D3877221AE5563CE8C70
+:10734000F31C6CFA62CF49BF7E43495E13C67EECE4
+:107350007BB2D62BA9B2B5E5784E9E091CF417ABCB
+:10736000DC5F8874D03A6308EEB5367EE7D9E33245
+:1073700081243EE25A3F25CED76FBD082BB2ADCF58
+:107380004D61AEDFB46AA636221D69F2DF3CF78795
+:1073900056C678BE7E8CD1918B9F4FA477CE4F95E9
+:1073A000E1442BCECFAA86B214CD3F4CF287BE93D8
+:1073B00086EEB18C87CD0E6CF78B5C3B4FBA88E7BD
+:1073C00043B3E7ED3924FF5224DF1D7D70BDCCF5BA
+:1073D000B9D1EA837917AC237DF01DC65A649F7D2D
+:1073E0006E1DC9ED753E5543FBB477BE4C71ADE8DB
+:1073F0002970B9DB6E91225C1F9422DCFF8DBF9354
+:10740000909EC2F51E3CE7110D4137EE0303137841
+:107410009EE97AD8517B0AC1375973EF675513B883
+:107420009F614B757085DBDF303797C7CDF6E65629
+:10743000FD29CCCAF270BA1A59F30C0DFA31AF0615
+:10744000AAF97932A1889F27F381A1727EADD1F08C
+:10745000DE500192741E6DD8F503EFFDA20FC8E94E
+:10746000E620E22DC6EF59896C1728794FEA32BB26
+:10747000F14C4F73EED21F8709DF0903F9BB675642
+:1074800090ECBDF77A14B23FDFBB067ED785755FFF
+:107490000E586CA99E12C5DF3DCCE63BC0987527FF
+:1074A000E68169FCFDF4CD02F9B39EFA5B703CD233
+:1074B000BB1105117FCF6211D32778B22084304EE3
+:1074C0001B5D00DDE7E2F73D61C29F2FFEF3735EB7
+:1074D0009E41FB4F489C83E7B7C43B71FE8FC6219A
+:1074E0000FBF9FF1D76A094A86F4A1AD5AF210C2C4
+:1074F0003B1BAC153DECFB2D0AE7AF2D794A1AE397
+:1075000095150522E921E00BA527B3F78BF6BD5CA5
+:1075100083F99D8BE64CC796383EADF7242D79183C
+:10752000E9AF465B5293CBDA573EA793FC3D2F7EE3
+:10753000FD5EACCF3ACCEB3E3FD7E3518F719F134A
+:1075400058F4C1449AD7AB61AECFB6C6CD3E5318FE
+:1075500091AF32EEE5F59E3370E8806DEB3AE6A729
+:10756000D3BF75A28BA44F1CF23FC11CC33E8FE258
+:10757000D083297C1C7AD88D3C89F217F3CE6243E4
+:107580007967EB6DFD6DB4796799FC9477814CEB6D
+:10759000F00ED3B7300FFD443EB99EEEFFCCE4278A
+:1075A00007CE8D95793194C30EDF68B36F22B9ECA5
+:1075B000BF42A1FB4C1D3E72F86756CE201F7D13C3
+:1075C000E5C5B2B0BE90A76A98E0E6930B4FC257EC
+:1075D0008B60606F8CD517C960E530117460EE6BFD
+:1075E000A5135D7C9289CF45F30578D1230779DD1A
+:1075F000856F6DF01EE02C76F270EB7248D6DB6280
+:107600002E3E6DB7CF99758806E07ED49CBBDC8892
+:10761000CCC47B277357213F6C121229E487C8EC36
+:1076200037425731BCBF37866991E83FD4973F4C0A
+:10763000FCFE4288ECB22DB356527CEABD6B9293AD
+:10764000707FD9C0F0FE22EDE7E9B122E5DCF68FCC
+:10765000E5F9137A9C97C9387F0EF6FBB45D37EDD8
+:1076600076FDD48EADAF476EEE8B723ED817E5FB3C
+:10767000D406A553457A1828563577DEF2B9F6FDBB
+:10768000C2D746ECFC97632D3AC629AE8D08F67931
+:10769000BB2ED25736343E4E657E5D1A304F2E5883
+:1076A00066E9A857A81F2D10709F85D379DC1D9F10
+:1076B00037B9F4B58B6CB9ADE2BD406CDE6AB3A5E9
+:1076C000BBEF9D554521EB7D41FF15E5FE5FB519EB
+:1076D000E8BDDAFBFF283F21BFD410BE8CF5E64E93
+:1076E000FADD9840377F1E2B35852B5DFDC6EABA43
+:1076F0003CFBA32AF6CB640F358066A17127F7D730
+:10770000A0DFAD6369B013F39633E908FF5E74D16F
+:1077100083FAD185A417C121AE97D694A844BF6D32
+:107720000DCA0EF4EBBD1BABA63CF5161B6F99F30F
+:10773000C1F83AD3F4C84F66F9799CDD9AC2E3ECFC
+:1077400058C7383B961867C712E3ECF81EE3EC58AD
+:10775000FF41A349758CB7631DE3ED58C7383BD68D
+:1077600031BE8EE5E38D2BA8C4F809BE7FA2B1819E
+:10777000EAE7DA7213CAF8EF7C757C4D31313FEAE3
+:1077800027F6FAEC3197AEF825FA01216AE07E1D62
+:10779000D8DFFCC27FD975BAFF3A5E928F7E4988E6
+:1077A0008980F184F6F836A6630ECD2F20DF0A3AE1
+:1077B000C5D5AD1598D7B83372E03C99E90FA5F15E
+:1077C000EBABF3587D57E4B976CC233D556FAADF78
+:1077D000E1AAEB918A958F6843F549E53BE4207B6C
+:1077E000FFD096E7DB510E04625CEFFB51E437E714
+:1077F000353192E82E618A0DCAB162258D748C678D
+:10780000395F9C8CF3E07ACB67A1258E797C9374E9
+:10781000A502F98FB5EFE6743FBAF63F89E8F43C6C
+:10782000F3BB91DA8995A36A47E770876B87EF8589
+:1078300011FA698316AD8FC1BEC9C7F757AB80FB7C
+:107840007F3B7C9CEF3B02BC9C98E3E42F54DF120F
+:1078500065E52D51BEBE1D017E0FC1C054917E8FC6
+:10786000071A84CF633F5F2D040DF31F2BA696E408
+:10787000A3FE7FC8A687C993227CDFFEBF2AEDDB6B
+:10788000E74F7AA8358FD5277FDB30701FDE04469F
+:1078900010EF71B5368B944FF4FDCA53F296B0E6F3
+:1078A00067CC7C2C0FF5DE0A5BEEA46DFBA4A9ED82
+:1078B000AA49681FBCF72C977B47EC7176F8FA52FF
+:1078C000B49E33C3749E02A093F492A6B84CC10C2C
+:1078D000711C2F159F7629DD93D9A6D0BD4CCA8780
+:1078E000B355F2A77EE0B7EF25EE237D450924B519
+:1078F0005CF6BCD312C9FFD0A205296EB3295C4146
+:10790000BFCB6095CB140FDB54CEE33AA1C8C5744E
+:107910004EEB9B3D016ADF1656291F385DBE7B5F2B
+:10792000750C4B51C37D3F6D2EA5FB2A2D4DD428E0
+:10793000AF98FD8BDEAF8A919F6713D8EBB28AC7F1
+:10794000217C63F753BDE5228DFA073B7F9F542FBF
+:10795000117F2722D1E3BD7F76E0E767A21F642570
+:107960003F9F324D5BDAF3247BDF6AAA8912C60F90
+:107970006DDA3BBD21AC5F06142F0D4D7DB919E3C7
+:10798000A9AD576A06CFC7E2E721C0BEEFB8B57C04
+:1079900059CFEFB1FFFA104C36B07D8D8AFC0AAD9D
+:1079A000F034DE4F5564EB33A1DC0A01F5B1B63A91
+:1079B000BA8693C1E73D47D09AF71915E9465A941C
+:1079C00047E3B481A9627BAB4EA67DB128AC76A318
+:1079D000DFA0C8F63B38F2203FE53A4FC0FE57B86B
+:1079E0004AF69C37187BA5B75E9071DFEE9936FD9D
+:1079F00064E22D739EF9B14773119EFC557432E217
+:107A000004F86F8D552CC1798DD37A851D9564D27C
+:107A100068BA86A986A926773EC62785775A796BE4
+:107A20001FD2C3345D069DE1E54C1868C6FE37D908
+:107A3000F4DF51ECDD9F0FD9760DE3D3ABA3980FA4
+:107A4000D52082E5EA1FE31D960B9E533AF23CF5E2
+:107A5000C99D859EF653B69778DE9F963EDDF3FE70
+:107A60008C5D159EFAD4AE799EF6673E5EEDA94F09
+:107A7000EFFE8CA7FD8C7D4B3DF5997D977ADACF93
+:107A80007E61B9E7FDDCFE959EF767BDB6D6533F34
+:107A90007BE0EB9EF68E5E9FB96F5E11FDFBF47985
+:107AA000FCDD1FF7B9E24C7BE1847B743E6AD13187
+:107AB000FE07517E6FAE8CFB3BABAFFD1AB7BBD45C
+:107AC000730C1DE5CD25365DAECC33AF43F95A15A9
+:107AD00055699F90C3BC9D1C3E8FF49189DB999C96
+:107AE0009A41F6D8E0FB10CAEB46EB9C5297BF2AAE
+:107AF000A07502E68155456BE9FE40E77B593301ED
+:107B0000F3E32EC12486023C766A51BB80CEBE7759
+:107B1000CD8BD97F7495C400B30F51AF1FB4FFE470
+:107B20001C8AFB32FB8FEC4323C8ED413826D17B06
+:107B3000E39B02607C9AD977641F3E1A66F6E17473
+:107B4000B4C7FA37A11C1AF8854C7144F647F65FA2
+:107B500025B3FF36E6BAFDE0FDC558A6412B247FCC
+:107B6000B8D22D8E2D267BF036A4E72FAC7B760580
+:107B7000F63BB592DFB3D731A62E8E7A72477117D6
+:107B8000F1C940B1CCF7213951E6F6EFFDD45EEFF3
+:107B900090FA7DB243D93A905C76D66193D09FC675
+:107BA000FB0CADAF05C9DF3DF18FFE43C86F6A899D
+:107BB0003A1EF3008D3D8A89E3DD6AE3B9449B5E9A
+:107BC0008D3FF3581A5FD28BE5A93AD347585956DF
+:107BD000B6B517CB47A22534DEE9C623D52863D432
+:107BE00073B8DF5A9EA6A49B05F4373338B2D81D6C
+:107BF00083FE89E8767E8EBF547E05E90FB5FEE3ED
+:107C00006C0A55792AC58D0348170295444F0139EE
+:107C100044FB4B000FA3627D8E90C65017EAAF98CD
+:107C2000175A95B79DE8C0D16B51DF4D72FBF8A78D
+:107C300088D7589D77FD43EA0F084FADF6EFBC7526
+:107C4000E4EAFBABD9B81D052579E8B3457FCA1234
+:107C500097FCD963EFBBF7E6881EF9331B731466F4
+:107C60000EE9458C1FB68BA720BC098AAF07F64BDF
+:107C700064CF076EEAA4DF570D68960EA4FF5B3A47
+:107C8000F65B53524FFEBFBFC42A480F0E343C95DB
+:107C9000156F817E09CC19C3E3337AEA1DA40FC0A6
+:107CA00098A08EFB6C432C68EEC8621F7C29C2FD35
+:107CB000671B263AFECC049D7B6D437F5B18B7366D
+:107CC000557C84F573C32F0A76BAEF87B8A180FB81
+:107CD00027871B3FC0ECCCA40BBE0DAC5F94E36DBB
+:107CE000C796D4D2FDAAB8CD54E2B9D0F21DE4A70C
+:107CF000B7EDA52FD978BD36C2F1385181053B507B
+:107D00009EE431FD88A1B4CAF6AB38FE97780E8F99
+:107D1000EB1B1648DC2FE773F62DF138DE4BA383FF
+:107D2000AECCB2AF00211598EF6BECFF7AF07CE09F
+:107D3000291DAE7D0E703FF0D6A76CF7D64F4B7B5A
+:107D4000EB4C8B7E1EF5806500DCAFB1CBFB3E0CAF
+:107D5000A60FE32885CE7DFA097E5E506510207D52
+:107D60009777A57BEE66F34B38F75E66DC9F3F7531
+:107D7000779AF497C54C7FC1F799F7BA171E5EBD85
+:107D80001AF585C28C7DB4C22791BF01FD4486CB14
+:107D90004F3449D33D7695E3EFC994EBC1C35B8182
+:107DA000BD217B3DE9C7FB51B572F42BB417DDF261
+:107DB000C7239543FE957639F5EA11F25F32FD2B24
+:107DC000C6FD1FE897BEE1175FF9F311979FF2ED2B
+:107DD00068721AFA336E9FC4BF77EE4F75CEF5BD49
+:107DE000532BFF4CD0391C49171C379659E7737534
+:107DF000254DF76738FE15C78F70699E790BF2DD48
+:107E000026E3506A0FEBB7FA377EC07E164AFBF7BF
+:107E100035A2BC9B2053BE88367BD5BD41F467E2BA
+:107E20007B56AF2ED6C7127F3CE3237FC27A9BEFEF
+:107E30009DF3A98E3FE6B3B61D707E8EA3475941D0
+:107E4000FB5C4610F5E43376B135F4EC87DC1FE8D3
+:107E5000F8FDA67679DF9F8E47BDC9EFB983F29B07
+:107E60008CB93CBF694C7DBA17D7F94C7B9D316EFC
+:107E700055356B287E3AF6B2742FEAA1D3EC3CA5B7
+:107E8000F2677E463FE50B5211E5279D3E9EDF4B94
+:107E900064EC953DE742C68040793E639E938C3406
+:107EA000EB67DA13DEF7E5E0AA17237CDE7A665C7F
+:107EB0008AA95B6F5F21E0EFA2A60494679B2F6302
+:107EC0003602ABAFC8B1F38B4E8553916E174A6142
+:107ED00003EFD15BFB2B89F214FD47A6FC1AE3A349
+:107EE000F02CCFABD44EE1F156EDE792C1242068DF
+:107EF00021983E3D3C14C7FAD67103EFD41FF48F8E
+:107F00003DC0D61DF7A10799DD5FEA433B5EA37A2A
+:107F100017B3FBB1FE28B3FBB1DCCDEC7E7CFE4396
+:107F200066F763FD7166F763F96366F7E3F3279815
+:107F3000DD8FF5BDB955E48FEFC3FB8DA6E0EFDA19
+:107F4000EEA6BCC6F5AA4F43FAC99467555537A8A3
+:107F5000CB187E378617521CA57A21CFAB6FCF592D
+:107F600048F6F4A09F2EC3CF39E4B7EB171CBF1D12
+:107F70001E718EDBF6ECA0FF3369D0FD0527EFC73D
+:107F800074FA21FFE909FDD87ED437BFF6DBEFB4E0
+:107F9000B057AB676EEB0896E0B99E147F6FE7159C
+:107FA00066FE9ED6EADD4D94E7A78C7B2E85EBBA64
+:107FB000BB324CFA06FEDE12CAED4C3BD1B10F3398
+:107FC000F571A7CCDC0F33F36022B65E72B2BC8CC5
+:107FD0002DBE14C5ADAD26265F70BF684C9FF3B2B1
+:107FE000EF44BF6DA1969771BE99E75DF9F7F17CFB
+:107FF000BC0E486AEEF93BE71FC8E62BE1FE43B72B
+:10800000DF36589AA6FB19826193F44581E991A461
+:10801000576A498A03B60FF3BBD9AFDA72A269DC9B
+:10802000C5B4DFB73FE3237DABC6CE7F6B19A75244
+:10803000BD65DCAC389D3389CC52FBB3F4B336520A
+:1080400032E2FE2AB1FD5F1F61FF97FCFCDC574B5B
+:10805000EF5C15CF47758497F7A1DDDE118F91FF97
+:10806000BF67DC2CCF3DE4527C0EDD572185B99EE5
+:108070002DC555D2B3659C7FF9507BA7DD9E1CBEF4
+:108080008F3036273F6620DC49EDFC72C2447F8B7F
+:108090003FC6F38CFD1A8F17064B4550B39CC7782B
+:1080A0002287DFE3D5519ED4D0AFD31197E95C4747
+:1080B000875E315CBC95F4A2FFCD113CF4DB62FB22
+:1080C0001D5A5628A417261A72B59A7C3A97308002
+:1080D0007CDE116E5631FEAA8CAB1CB15F45E3FD10
+:1080E000FE7FA3B2F95D0080000000001F8B080036
+:1080F00000000000000BCD7D0D6014D5B5F09D9DF6
+:10810000D99F24BBC924BB9BECE68F09241A34E019
+:1081100026240134E224048A167111D0D052D98069
+:10812000282A48405B57ABCD8604842035F853A9F4
+:1081300058BAB160ED57ADD1D296D7222F28F2FCB4
+:10814000414DD52A58D400D66A6B6D0469A9FA3E10
+:10815000BE73CE9D497626B34950FBBE872DC39D85
+:10816000B93FE79E7BFEEFB9774F9D823F1730D630
+:10817000BA27456595F05CEA88A71431168E966794
+:10818000D74F60EC1B59E1CF32FC8C393C8BE49823
+:108190009B313B636A173C4F69EDF4A75716188370
+:1081A0007AA2FCF329EF7A077FD79F62FA661681DD
+:1081B000F6AC587AAFD7C5984D61C2291B94995B2C
+:1081C0007EEF6C467F4E89F8774F20EC49DE8FC7F3
+:1081D000F58B29EF4E18DC6E7959AF4354185BBF0D
+:1081E000AD23CCA0FCA900852A843BA6E6C1BCAE89
+:1081F000DFB99245CA18DB28F5B8648063E3E7C2AB
+:10820000C270D9E0FE17E37CAAB057298670C21F5E
+:10821000DBA973E06F85298E6AC6F2F0CD687CF227
+:10822000EF30CA9E53D07F7937944B3578E0FF13F7
+:108230009E3596AB7A8CE589078C65C642F6F03898
+:10824000C65E6B864ECF646CCEA10F0EB174C6E6CF
+:10825000C642CF3CE9632C577585E33263F358E897
+:1082600099B7A09CD790C6BA4330B88D2DC57581FB
+:1082700069BE510CF035308295E52D4D65CC35D079
+:10828000FF7C3993D6A9A1B771261BCFD8F76F69A8
+:10829000650CFA89D509F1ED00FFECFA6DB3C7C0A2
+:1082A000F3FE4A5BC143D828627F17E7E782CE4ED0
+:1082B000C17C336D2B478D86FAE1A969422BD4FB33
+:1082C000FEB967AD2F8672CFF49210E21DF0F56E05
+:1082D000FF7C00FFF3C2BCBD3EFECB95C7E68E819E
+:1082E000E796CA2766E3734E627DE86FD6A4CE1682
+:1082F00007F477C932A502FB0BD71BDBE7D518CBF8
+:1083000000399F0FFCCB9B3518DEE1E0318FAFF7D2
+:10831000777FB342F8679F033D003EC3F809DA87D1
+:10832000A53E290478CEAD11D438D04D9E2AA89D03
+:1083300016FCD0AEF18319FF622C83219FD5CD139B
+:10834000E3ED5025D76527FCE7CE14E20A8C9FBBEE
+:10835000B4AFFB14942F73D9E3227CCFCAEC12F094
+:10836000FBFDCB18EB2822F0D26B13D6F77ED71A81
+:108370007B217C9F1714990DE880D58CA1F1088E84
+:10838000D1848F231C1F2EC247DEB2D0333F82F12F
+:108390002F9FE49445A87F7903FFAEC3B751023AFB
+:1083A00083EF1B81CE624467D29144FCCC39B47C0C
+:1083B00039D2E31CD3FB62A88BF3FDDBE403671423
+:1083C000025CCB858E1969004A8ABD89315C68C020
+:1083D00020D2B5CE8F3A9E96EF68217E4CE033FBDB
+:1083E00029E467FC7736A186F8EC29D72F65941B22
+:1083F000BB337BB73020E1AD328BD5E733F69FA995
+:108400007D670B50DE2E5FB66EDDF9F03DA5EFE720
+:10841000AC9C31A7F39B336624945353AFA6B24F61
+:108420001B07A610E3EBDD3F2ED1C75F650EDF060D
+:10843000956D12A12CD9E44DA1A2817659D84E1880
+:10844000A25D986D922CDAB9F57680A7B5B07EA9B9
+:10845000DABC52B5EF360D9EC4F125C49BACB8050D
+:10846000580F69BA2423BD7C5938B2879B77846D35
+:10847000B28F19DC0EC06ED1E1B759C31FC7EF89A7
+:10848000E3DB8780FFABC6C770FD39B4EFA70D1FD4
+:10849000545F9D9D7CBE08971DF595A2B86D09FDA2
+:1084A000DCB9E75F2F9C03C42BCD67A114E843B26E
+:1084B000AB7208E8BC4CBEC7859D4B99F57204F8B9
+:1084C000613D945578BFBEABC3A5C0FBB2E2BBD63D
+:1084D00021D19775A7329407E3989CF908F43B4E95
+:1084E000965837AEDAF97B6D69506617B35009F4C8
+:1084F0009BB12795E44966D1B93F1160DCCC4C971C
+:108500008AEDD332AB7FC2883E982225E023ADF6B8
+:10851000B5BA34846B360B212B4A429CD522938DFD
+:10852000051E8272E6B46DAC1ECA157FF32822F2D6
+:10853000B4C4F55D3BB6473DDDC6F6A17E096AF2DF
+:10854000679D43DE44FAE35A89A1FE481B778F807A
+:10855000F0DC0F5D89C097656559B3EBA15CB6DFB0
+:108560001652149C4F875088F30988A4B7747CEA8C
+:1085700072A4E2E36ECEF463597C3BC0DF668F7772
+:10858000A3BC8A4DBE5CDE0EF0E45E9920AFF1AF75
+:108590003EC001C2FBE2A5DBDB8B90BEA57713FBDF
+:1085A000CBF838DE8DF28CD53684B1BD6FA66490E1
+:1085B000FFA99A3C4B35E981E62C3BC9335D1F305E
+:1085C00055526498B7A0CD9B7D2F4CFAC0C9422E5E
+:1085D00007D92B0BC80E1158AF702A0DE68F151155
+:1085E000EE023E8F41EDAB797B1608B9D0CE71A675
+:1085F0003635617DF898D502C815AE4D55513F0B03
+:108600000EE60A56C0BC6D2CD20574D2223009CBBE
+:1086100003E375331CCFE94A6B43BBEB2957AB0D22
+:10862000F1D7FA2CE80F98C7ED76D6807641AB1CCF
+:10863000726541FBA866BFAD2A1F9D83E50CA0EDC6
+:108640001EB41BA4B08C74B9CA5F9CC3E07DBAB7DA
+:10865000F79B2867BF96F9AB19AE0290A37550E758
+:108660005C90FB9B1E5B17AB81F14EE63125C1CEC2
+:10867000734A4D0CED29E7C942C3FBEE6698D199C8
+:108680000365D56DABC771AECD5408AFB54C6EC3A5
+:1086900076B5800C25615D9C27834C9960D57FBEA3
+:1086A000E17D37D8498A7324FDA731A534B1FF3164
+:1086B00049FA3FC3D4BF6CD9FF40BF5E43BF6B24B0
+:1086C000467674CCE7A67537DB05AB33EB5664A270
+:1086D0003DEA644D5D1676674BA68DE0BE3DD0D475
+:1086E000A342FB3A068C0F7472C1E7474446F60C6E
+:1086F000AC14D00BCB97FAFAE97834D6E3F46B8B51
+:10870000090CE5D20592DDC0275398B16CB68B4AAF
+:1087100060AD715C9BA7B207E967953F55715AC080
+:10872000AF3F7B9AD994E212986F6A7829033EBED4
+:108730003F739F6B4D00CAE99C4E1ECEFCE30CF4C8
+:10874000177A044E7F6B7C36C24BB82EA7534CE889
+:1087500037EC60252817C348DF6E0E0F8EDFE3CF9E
+:108760007FB0DD627C10BB06FB61B62A4C294E98B7
+:10877000578F6607F78F3735AF13F9A07F3C27ABCC
+:10878000A2F144C07FE278D95F6CBCDFE3FCCA068B
+:10879000C69B3DDD38BFD90E99E6375BE35F7DBCF4
+:1087A000DFE3FC8ABEC07838BFC4F1BE669CDF6CD4
+:1087B000A74CF39B2D72FAEA1F2FFB8B8DD7D35C4E
+:1087C0004A76F0ED0E904F4027A9E53B5C6360DCF4
+:1087D000DB5D76595006DAD5D6DEE09A8BBAD73D06
+:1087E00075BA1FC6A99B069573B197A9D36B8B1950
+:1087F000DB2470BAF8EBA63FAF43BA383E73552975
+:10880000E913CDBEBE04AB823EBE44E2F0CECA77D1
+:10881000C75B12F0783FC81115E07800F85D057E5F
+:10882000DC0A7C89E57873809E0F82BD8ECF6D0057
+:108830002F7E7FA83944E5879B27D153EFA7741279
+:10884000B7DBC7D658DBED676471BF6F53509E7FAF
+:1088500025EAB5DAD410EA4536E93CA626DAD5ACE5
+:10886000E9A914F8BEF132568EBAF18CCD1C6E5FB8
+:108870007D36D9EDA9E57B7B9AA17CBB6457502F4F
+:10888000DFAEB019567E7311EA992AB457797B7618
+:108890001EF7C37CE1DEBDA8F7E6A09D0E78F5CFFC
+:1088A000EDDD8BFEDFA56097935E6687F7BE05DF83
+:1088B0005F03FFAF1DCBA29BC9509E35C74FE3C3DB
+:1088C0009FF4DA6CB4DFF99FBB671E23BF229CC202
+:1088D000F5828FCD7E660FC21B722871EA8FDD1B79
+:1088E000463E50ED4A3B8982B01DF5B41FF5347CFD
+:1088F000AF3DEC6436846F9A83E4DADCB946BF613D
+:10890000534AB78CF6CFA6721F6B81FE2F9D69FC70
+:10891000EE74727E0B9BFC8659A6324848EE778B2C
+:108920000B32D0DEBF1D5F4D1E8CB7E8A196DBF782
+:1089300026D0695E96C747718033D81928CF4EB0CC
+:10894000B23BEBF1637E16192BE6F6FF6C8EDDBEB3
+:108950001750FF32CABD2AA46F2E3706F307876768
+:10896000B256EFFEE69E29EF960CC0972BC505D4B4
+:1089700003794BE17DC27C255F5C407F87898F94C2
+:10898000A37F639EC7FDC2234166319EFECC65D2A4
+:108990007B88175C4A94E7E6F94E1E34DF9A978B82
+:1089A00099153F299BD09E9BF5AC186A5106F0A102
+:1089B000CFFF7F9AAF8E6A7A86A93ED60DF4F23247
+:1089C000D07B3BF76318DAA93ABD4205B29F2EB9B6
+:1089D00004BE235DA86A01E2F3E5D17DDBAEC27679
+:1089E000203B5AD1DFD5EDA0EE8336B483BE68BFFD
+:1089F000975CEB207B8BB17AF9BDD281FE92AD0FF3
+:108A0000F6FB5E82FEECB713F14FB526FA10C69660
+:108A10005080EC819BC13E467F3F5AFF8194CEBF80
+:108A20001F49B053F1CF9184FE5AF7FC4C5000AE71
+:108A3000CEE6AE29EFDA13E4C552D9B606EDB99603
+:108A4000B84071886EA807F6C0E8A58AAD0DF07F22
+:108A500025F683F46992EBA3DBA09F443BA566AEA9
+:108A6000FC08D0435B595D47089EEB37F378995E6D
+:108A7000BF3F6EE68B917F6E674D4C00381D29DF3E
+:108A8000FB712FCC476D9558CA1428DBB9BDC3DEE6
+:108A9000F2905C10DD4D3FC5EF8118C82D9C775DCD
+:108AA000D363588ED958B8159EF7A5F1F651C9254C
+:108AB0003B431827699B81D3CF0C46EECD02FCAD1A
+:108AC000C94E2539E878DBF320CA294766C552B478
+:108AD0007B1644BF1BC678A4EC650BC316F4B540E7
+:108AE000B31FE2593CEE72C8DE5D900970D706EB09
+:108AF000E2D8EFA0FAD1EF517F53446B3B6CA7D67D
+:108B0000CF169BB55C785CFB7EF9F2273E7808E6D1
+:108B10009356EC0E21B9AD3F87ED106C83EBEFF26D
+:108B200047BA12E1482996258A83B2AEC968CFAD0B
+:108B3000FFEC81AEC700E5599FB949CE66899EB862
+:108B4000506468BF33AB6A70FBDDFF7A3D80EBB3E6
+:108B50003B85917E65EC850BD19FDCD85F6631014A
+:108B6000E39C995A39F6F085AAA1BCF8C25A2C2385
+:108B7000ED02514EBEFBDBEB63D85EE06516FB0EEB
+:108B8000AF6FE7F573B4EF532EFAF02777A23EA844
+:108B900076901FBA51B38374F8CEF38A443FE779D5
+:108BA00087C6E3414D2EB8468EC7835678DC1D54E8
+:108BB000DFC4F729AC4B403A4EF9CC7523B6FF61C0
+:108BC000330B5F09B06F5176FCEC4E85DA1FB6C2ED
+:108BD000E35941F508B6772D3FF2933B010E8F0E16
+:108BE000C74476631238FE32D47AEEC8E6726E9EBF
+:108BF0008FEB8D2CCDDE74387A02B3E12957FEE07D
+:108C00000619E4CDDAA2AE06ABF8F309AF8DDA654A
+:108C10002689B7677839DE76E5843F4538DAE42778
+:108C20005C387EAAC0C2587FC3A45E2624F47BB6FB
+:108C30008FAF03C06DF342BBD4C94C453AF3304FFC
+:108C40009C019D792A39FC1B02AF3105DA794AE192
+:108C5000E9C6F7BDC4FFE87270A106820ECA0E8D88
+:108C60003E32EE6EBF10E9214BD4E92DAF1DE9C5B0
+:108C700061D3EBE75D84E5CE2C5E2EF7E5B5C7F258
+:108C800041CF38A00DCA855C07D93BE6F9E568F00D
+:108C9000B6FB55BFD76F814F672FADD3C6718E50CE
+:108CA0000CD6758AADA761317EBBC84DF61ABC6F74
+:108CB0008827CC7FBA4687D3BDDCDEDAF82F57434E
+:108CC000DC623D92D1E978EF69D3E978AF359D9EBA
+:108CD00083F84FA0D34F98359D565BB5073A9D68F2
+:108CE000850F735964EAE6460050FA74FAC377A216
+:108CF000B6FA7ACDE6C7E039E533B7E4853AE2194A
+:108D00008CEC449B8BCBF701B91F9986FD4B7213FA
+:108D1000BD17DD61DAAF79318BF73FA8DF89D59BCD
+:108D2000516E8DA0DF30CEDBDCEF282F8777CA4570
+:108D3000EE48DC02EF27BD12F74B7D7CFC64FC5251
+:108D4000EAE37E73527ED1E93F271C413886E397E0
+:108D50000B06F865E9C8F86507F14B5A19E797B4AF
+:108D600024FCC2624EE28FB545BC7CF3DD3EE28757
+:108D70007EFE899518F9275662E09F69F794507D29
+:108D800073FB749CB7055E625E7D1EE1669C877A0C
+:108D9000B6DC2692BDD1CB504E75B2BE3D4EE4C37B
+:108DA0001A21B41DDECE8AF5D4BB14FCDEC3668363
+:108DB000FDB14EA3FBAD080FFA43D55A3C4BEA6117
+:108DC000977A06F3B1A7B2BB349280FF020D8F975A
+:108DD000F9C277E2F89DAC772CDAA5C9D6E91E0D69
+:108DE000DE1B03EA3D56743E9CDED9897AC78F4F5D
+:108DF0000E77D667AE269403663E9F72FD6F3F786E
+:108E000068887E7EA5C1F1A8F63C0DBE7FD46BA517
+:108E1000A783EA2F4C7C5F298CB6E4FB5F59B5072A
+:108E2000BEFFB5153EBE049F3F65C5E70F7879FFCD
+:108E3000C3E159F2713C4BBE2F87E723DA3ABD7983
+:108E4000FA787E33099EFFE8F58F08CF4792C8D79E
+:108E5000A35E82C316C37D01E477F4DFD74D8CF5A2
+:108E6000E17EA8051C7F4DECC7A5F07EC0B4FF4491
+:108E7000003A9FF2E9BA50C4822FA1DDB144F8F55F
+:108E800076F77865CD8F5056A25DBDE5EB6EDA4F73
+:108E9000003DF80FEF572BE76D3E0B793CC5C6E55B
+:108EA000D065771F5E8F719A2FD17FBA55FFCF693A
+:108EB000F4359CFE2F4AD0FFD88F59DE75321E4FF5
+:108EC00069F747F27D84AFDE0B513E6DBD254B4007
+:108ED000BF2E5FED16D0FEF76BFA65A397FB337AD2
+:108EE000BBAD52B72061FD2659880986FECE18AA6F
+:108EF0003F331C00DF5884EF329F7A163EEFF1F6C5
+:108F0000DB7BA7650F5507D40A6C0F72BA12C757DF
+:108F1000CF34CA697D1EB67017EB45FD02EE77DCD3
+:108F200082AEFC9ABE847ECEA77E34795FE5D3E91B
+:108F30008AF777BAFA06E09BAEC137039F66F8CC92
+:108F400078190ECE9B104EDEDFA5897026EB4FF709
+:108F5000AFF575227D9A10D75938A0AFAFC0FE5C2F
+:108F60006B6C31E61BE05F5D5F83644AC5FEB7381A
+:108F7000781C75CBB2BB6A31DFA0F356B91C519295
+:108F8000BB94EB39655921C555AFD1FA35C3DFDF45
+:108F9000DED1357642198DBB1CC7BDA08675A3DC1A
+:108FA000C8403B81E20FB284F1852C674700E3B2F1
+:108FB000EB858E8645A8472F7493BE6581B996F1DF
+:108FC00029FDA9C79FF479B340E530F55BA8BE9CA5
+:108FD000D6D18476D288EB3B3B2CEDAAEF6B76158D
+:108FE000CC6FFD90780DF828BEA5E377F0387CFDB6
+:108FF0006AC34D02E23BB50C8604964C0D77D066F1
+:10900000ABAD38CE7AD17E2A057AA1FE5EB38CFB59
+:109010000DF4B75687EB01A4C72F0B975E2FF97895
+:10902000BC1EEE9F51BCC3CDE5167D80F2B167BD7D
+:1090300096FB07FAF3F666599540FF1C93950C8C46
+:1090400017DEAEE941C642814B3DFFFE7A03F3884D
+:10905000F378A7A97E9471BA670117D97718864F5C
+:10906000A49B577DDC1F6DCF0E3FCBE56328847436
+:109070000DE5E711FFCC05650F95F75359EE2FBFAE
+:1090800044F503BC3E93E511E119DAFD81DA49FDAF
+:10909000FDBC41FDBAFBC73D48DF7DFDE53FD2F792
+:1090A0007C5E7FA4E324AC2B9F7F8F48F3FF445268
+:1090B00033707FF4B2E8628A13CD8F5E43CF75CDF3
+:1090C000722DC6E35E6AEE6B6B83E765F317CB68C0
+:1090D000F7CF5F7237EDDFEBFD5F827E05F2BB22DB
+:1090E000CD20BBA8C816DEE61EE0B70138DAB43CD6
+:1090F000B3DE7AA42397CAFADACBA1FDA48FDBDA18
+:109100000C794E1D943F93A2489F26C6D57539F819
+:10911000A143FD94E63F723A36CD97B1BD30FE27AC
+:10912000EEE2788CE8BA4EB6E2177DDEC9FAD7E7F0
+:109130009D4CCEE8F8D3DFAF2FAE9079FE4FDC80A8
+:109140009794927ACAF7B944D0E0F4B8347EE3F544
+:1091500066C1384F94117D2848BFB3343FCEAC1759
+:10916000F4713F74448AFCD80EDEDC5A6181DF1151
+:10917000E2ED40F3D270BD1DE571570AEDDF339982
+:10918000E2FC7ABD8624F33FDFCFF50873AA349F53
+:109190000DB765C4D1EED8D0F82B19832B69E33E07
+:1091A000A98AE153E83BB108E5CB6D1ECAC76868E0
+:1091B0003C51D592D0FFC2A7FFC385F1DE8671ABCB
+:1091C000FD187759C8A44F12F31DCCE33644AF27DE
+:1091D000BA8DB5080D56FED61BD99CAF17628A8C86
+:1091E00048FD1D49DC476E542A1C189F688C19F7EE
+:1091F0007340433A903E16AF33BF4FD8CF11B17F83
+:1092000046F38EE1661EEABD3536A2B72D8037F4EF
+:10921000030B415DE2F38DEC2C8D1F7B089FFF6EED
+:1092200078DEC896F9BE9B8BC5D2B206E82627D257
+:10923000C1503F792A05DADFF479F4FC882ED25345
+:10924000F7B8F532E82DC07FB84CB3738AF9771BB5
+:1092500096D1FF49EBD96B033E5E73EF531705C6FA
+:10926000427F6591804DA6F2F3921FED2F5E66B1AD
+:10927000A79EDF4BF6AC7C961002FE6FDBFDFCB3C5
+:1092800005E4CF6BF6D8EEE7C91ED3CB8C753398C7
+:109290004F676A7F597505A03CBABF1CC3F256CD13
+:1092A0008E5F73EFEEE7DBC83E09C7FC097AB29622
+:1092B000F1F8F257AD1F3B035776603E51ACD846EC
+:1092C000FE5EAA891F1FF13BA85E514EE42EE2C745
+:1092D0005BFB248C373882AFF9500E8C2A3EA68E69
+:1092E00006FA1F55C3D36458291FB7B37815D90D93
+:1092F0009DDABAC0FF56A3DE1B589F1ED3FAF0F5C5
+:109300000857F6D0FA78CA7A68BD6C58A6B81FDF3D
+:109310008FBFB892DB1BB293EF2B6CF7737ED8E153
+:10932000E7FEED0E3FF74F338AEFA2F84ECA0C1B53
+:10933000D5CFD09E6639BEC32F69F29CE3637730E8
+:10934000D2E54FB05BE17DB8B412E59B2F0BF75926
+:109350006B8BA51B919E7FACF9A7B04E77D23A15C7
+:10936000F952237CDD7EE3F75BAC5BE9C8D6EDF513
+:10937000E608C9AB64EB76D97C316C15777B5EC3AC
+:10938000C3470D7FFA014E67B9ABCF81FB30EB8B42
+:109390003719F2AA5D3B6677632EB49E57BD3A2D0E
+:1093A000BD06E5B679DCD73FFF2F1FE277E6BF9C0D
+:1093B00096F2F1634D3EBED6DC40ED608115299BEF
+:1093C000E400E3792FFD7962C229274DEF75CC4384
+:1093D000BB82589FB1B9E1C3B45FBD282032DC1F06
+:1093E0005FC88C79652CAAE705F33CD8D725704D6A
+:1093F0000185AFC78410608A354AB375B962C80F5A
+:109400009B3777F63EDC875FACEDC3837C317C5FB6
+:1094100062CA1BBBBCA1315CAF7D3F4E7FC7094F09
+:1094200073156E37CE75BB49BFCE0BCF0FD727EC68
+:10943000C7BDF1DFA2651EFAF9D93A5EC2E1FA9220
+:10944000C1785914161CB2323C7ECCF8A89538BEAF
+:109450001A357C99F163C6C3E2B9B369FDCDF37FD8
+:10946000DD1526FCBC0EF8C17C61333E188B5C8C8C
+:1094700074FBC67C91A17D3C5D9C69C73C81C5B3F2
+:109480000586F9454B58289DE707ABB3A625C06B69
+:10949000C6A3195F8B9F64A16EE877F1BD1E5ABF0A
+:1094A0005734FC88DD7FA77985615EED7C5E477867
+:1094B000FEAA4CF3BA542D7FC607DF236D206D152D
+:1094C0002B3DC2E7B308E6D32E0FD62727584D13FE
+:1094D000D2C91253DE82193E33FC33510E4E1EBCEC
+:1094E0008F5F91ADEDE38F67216D1F3F838E3584D4
+:1094F000FC43E62D0CF039A7AF85D1D9FDE361BF60
+:10950000028BF49765C0EFCCE7BC1BE7C1BF5705E2
+:109510004405F30467CF1FB306E71F66E18CEE2214
+:10952000B4F7FBEC28472E6560C642BB0B6092A8DF
+:109530006FC3F52954D6FB3DD6F1B19DF47884353F
+:109540006DA7FD772563EEB8E4F26555C041E39958
+:10955000ED9499E52519282FCCF8D0F1340FF1922C
+:109560004678197F3A7879017515FAB318478375EB
+:10957000ECBB86B107CB07F68F59BECAEDC96C4666
+:10958000FBFFD764676A764713C51D16687AE190BA
+:109590009D353CEEE6FBC81509F2F11BC1DA6BB252
+:1095A00013EC547D1FD9CD7A097F57B8DCDDE27802
+:1095B000A2BB0FFBE983E4979EAF19A17C4D3163F9
+:1095C000994271B1B4F4F12C03EC62C6E70D7ECC84
+:1095D0008DD97E7C5F18472360E6733F59374F195A
+:1095E00058B7F5576EEF40799CB2E49731EA5CE1E9
+:1095F000F91C69DABAD56AEBD66F4797C2FB04FC4F
+:109600001EEBD0ECB0522D8E8F7FA07CAC588D0F0E
+:10961000E5BFEAEB98520AFE87218FB083F0ADAF29
+:109620002738117DC89791804439C336E622FF3828
+:109630007233CFC758C894AD981FB4306A3F96D8DC
+:109640004F2428111C91F5295ADC2444FD2C0AF2E0
+:109650007E5829F7F3FAE93E06ED13F21F6D2E301E
+:1096600025B17D260BA1FF04FD65A3BE67EB12C6E5
+:10967000193D78DC64FD99DB89DAFEADE80C8542A2
+:1096800009727ABB663F1F0B5476D94627C7DF2283
+:1096900097579512F2628F045D0D567131BD3F5D93
+:1096A0007FF7DB89ECEA1712ED44B7A3F18567CFAA
+:1096B0004FB01359E30BB8EFFF45EDC497B21B5FF2
+:1096C0006883F9FDF3ADAF51FEF8B12610988047DD
+:1096D0006F742A3BEA45F92093FE2A6C008F0A93A7
+:1096E000BF25652CD27B4A344F9512F265DFC856F0
+:1096F000087E6FB14AFB65D0B40B5D71AF141210D8
+:109700006F7769713320DCB1B33D89EDF8BCF5F1B9
+:109710009C2E99E070E8E3B1500BE5D7CF64A447E5
+:10972000F43C109DAFF57E8E661BE37523E0E7A346
+:10973000D9FEC1FC2C8A4DEFDC8672E20591FCB0AB
+:109740006F056EA6F7E678C0DFB2B97D582046FEF9
+:1097500086FDF434BCFAAD9BA0DD8A1DCE10AAE1D3
+:10976000E5DFF9E0FB550AE289AFFFFC258BEFADA1
+:10977000C279954832ED6F14F0388CA34520FF353F
+:10978000A5C811DE01CFC3BEDADC9C04B80EFBEA2B
+:10979000A93C7A0687EB18F4D9AE60BB4D0DE42FD7
+:1097A0007AF8BEF73145C960245718D913A2933F00
+:1097B000DD393C2EECCEE1F13C2987E3DB7552A08C
+:1097C0004542BA6EC27D0B294679D0AE9312BD7761
+:1097D0000882A5BDA6F7E73A09C219F195666EEFB2
+:1097E000A0F7381F6C2F7A99C1BEF1E7703BD9DF23
+:1097F0000F471A87C36BEE279DBFD7F8CF0CC78AD8
+:10980000ECA941C4CB619F9A9BC3E3285C0EBB9F2C
+:109810003F208C1F893CE6F9FA17072517C5F56E1E
+:1098200013E225209FDA4B8FAD21B955E46AC2734C
+:109830005209F693C0CFDDF0731503F669DFB43932
+:109840009518BD66CAFDA1C1F6D63B9527E6CDC1E8
+:1098500082767EE20A5DF6C6A00CF6DCDB5AB151D8
+:1098600019BD1643FD97D470FB6C31DA6721925B0A
+:1098700006BBCB6C9FB941DFCF01BA58129064A4EC
+:109880000BB39DD65E398FEC9A76B06B305F7BB0B0
+:109890009DC6E5CD1D511B53A1DE4B3522F9192F75
+:1098A00095F63E7701EA8B497685F44569DF1D73AD
+:1098B000E8FB041AC7ADF977509F9F7708A5C54B01
+:1098C000E0DDCB3547DD8B13D6FBA54947C7A25F4B
+:1098D000B035497E851EA7D97B0BCFFF7AE71E21C5
+:1098E000EE44BCDD2ADAB0DF85E51ECA5B9D26BAF0
+:1098F000699CC51BC5B89370A8A64FCB1EB01B9919
+:109900005893FD2AE2E14E3BC3F3830537F61AEC88
+:10991000DC8551A33D176902FB47397D3BD06CFFC5
+:1099200099ED98E5399AFD52C12AD07E79A9792717
+:109930003B5A3260C7CC4AB2FFADDB31E7DAEABE50
+:10994000ADD133ED1FCC92ACF7F72FD6FC5316E216
+:10995000FEE034F1435AAF63214941FCB96F7E9E6A
+:10996000CE75B8FF5B0C5B8D77478E43DF8F237915
+:10997000BBB5228DF2AEF7DC72564E2FAD97725FFB
+:109980000DAEFFF3769283C9F45B4A5464C530315F
+:109990004F54A0A7BE9EA3A2292C513F8C4A92A748
+:1099A000F0A31C3E0FFFADCC867E76668CA9567E5A
+:1099B000A95E0FFCD1E918A386FADD9900DFF5C591
+:1099C000368AFBEB7E698A9D9FF7B5EF5A1943FFF4
+:1099D0007414C0877028001FCAE1A2681A9547470F
+:1099E000BDF41C13CDA46771348FBE9744C7D0F368
+:1099F0008C6811BD3F337A36954BA313E839365A3C
+:109A00004ECFB3A2E7D1F36CD05B58AF2C5A4BCFFB
+:109A100071D1AFD3FBF1D139F43C273A9B9EA1E839
+:109A200037E97B7974313D2BA28DF47E42F43A2ADA
+:109A300057466FA0725574253DABA3DFA5E7C468F8
+:109A40002B3D27455BA8DEE4E8062A9F1BBD9B9EB5
+:109A5000E74537D1B326BA85BEEBFC9CA6D9D32FF8
+:109A600006B6C9946FCFBACB503E26E3C3439A3CA7
+:109A7000AECB51F722FDE9F5F66BE70ECCF50EE41F
+:109A80000C9D77F3AAB65E1F858EFC008FD3EAEBA0
+:109A9000B63E30741C8195F986D9B7E2F37B3A471C
+:109AA000E1F42B7590BDB1B589513E98A7B24740FE
+:109AB00079D319906658D1913BC0F3C08A7222477E
+:109AC000517FB883EFEEC5FDA84B623DBEA9482F7C
+:109AD000215FEA54E86F549B8DDC6B85C902969533
+:109AE0007A2677B381780ED85706BD260574FBAD6C
+:109AF00067E60484E7ACE20AB25FB5FDE4FDB78C2B
+:109B000066E8776C75740B12CACB558C25DAE15B6D
+:109B1000D72E7A28F19C8614E0FC396A1D7B0AE373
+:109B200064451D4A1D9E271CB3597D0A533C4BE2D8
+:109B300091BA54289FF970EC297C8EED8AD7A5C183
+:109B4000F3EC9DDD4FA1F819D7DD5BE786F239CF45
+:109B5000B2A731FC54DEA34CF54079C201F569DCB3
+:109B600026A9EA8D4C4D57109E786B3AC0B3F56D1F
+:109B700030B4A03CE9C30E11DC9281F507BBEDF1D6
+:109B800084754929EE5145F867FE8D7239CAD9AD01
+:109B9000526F4A66D9E0F5E9C479E33C41AF6CD72E
+:109BA000F6D1E584F50805043D1EE80B24C4033B0B
+:109BB000DB5EA1786067AA5C8BA1AEBE694C7E506B
+:109BC000413AE67E42EA9AD1A49F74BA03FC1AECA9
+:109BD0004929C0E96E6BBFBD698DDF10E2B7EA7F2E
+:109BE0000F7EFF3347935F49F0FB22CE23383C1FA3
+:109BF000D706385F021F9F1FA84A5EEF2A0DFF6637
+:109C00003C6F95E4B3085F6E668B950FAC5BA34623
+:109C1000DFC3E1F59BFFCBE876526068BCB24A2F08
+:109C20008F336BF969C9E4CDFE24E7449A0283E4DB
+:109C30001C8F97CA20E7C6249773358161E4579239
+:109C40007C87DB027ABE43F8BB8111C4F5EFB0C953
+:109C5000B598EF121BCFC84F00FBB20DF37746C586
+:109C6000940ADAC642A18C78AC389BFCF422B03757
+:109C7000A40A86A98EDDF8BCB832D3B6A80CF31AB4
+:109C8000347E931B0389FCA6EBFB017ED4E922AB57
+:109C900093CE5900BD623EE12E0D4F03FDF078C416
+:109CA000DA9B733BDB13E46067288FCA7AFD64F4A8
+:109CB000FBA6F61DE405EDF75F5C639D6FF2EB809C
+:109CC000A8D9397D2AD2796C0A93E9BC73DB119249
+:109CD0004F99209F84221E1EC2F1F3A3A90F619CFD
+:109CE000F657816C4D9ECBA99779FEFFD1733BF857
+:109CF000EAC44F35F21E3C57310AF4908272B20624
+:109D000060AF443DE7A07557185F47A586C5BB0502
+:109D1000C25B37FACD311B3F9FB1DFD1A592DE7117
+:109D200064CA987FB2CB1FD91BF027E70B394D29A6
+:109D3000C745FDC3E66B67BA83989723A762F915F9
+:109D400028DF3109F3847A9956BEC33DF98BC71FCA
+:109D5000FE10B8663FEE535507D457919E81AEFF73
+:109D60008070A967CA12C58747B8FFA4F3E7003F10
+:109D7000C9E53A3F3596913C7C2790B04F9ECCBECA
+:109D8000F9A1263FFB0243DB373ADD9FB67DA3C135
+:109D9000FBF630FC3FF3B957376F6303F13F4FEEEB
+:109DA000EB3D9282F6F654767402C6BD7A38DD3306
+:109DB0001EE75331FE07749052E932C56D85195A7A
+:109DC000DC65C878AD1E4FD6E37D7A5C2F5DA32B92
+:109DD000BC3000F578FA24595A44FDF5B24BA13F46
+:109DE0004F90E349E76B945BB83FEF5A93258D2E74
+:109DF0001BE8172425C9A9CE0626B767F2FDD70CA4
+:109E0000902F1DAB19F979B19744EAFFB86AFBC0EE
+:109E100009F58E570202512EA84C91B3B573084430
+:109E2000E432D1AB93B12EF4B7D9F7422E07C6B9BD
+:109E30003F15980A70EFFF54A4A784116E687471DF
+:109E4000A83C848D6B336A42B81F281E8532C059E6
+:109E50009F519381E5FDFB27849845FCEEF248A3D2
+:109E600021BE64C6537FBD6FADA17C852DC3EC7F41
+:109E70004E0A3A74BBB32288F6CE957D6D0E6560AE
+:109E8000FF53DFD70B163F7121DEB3135CC6EDCF56
+:109E90005C166F49B49B12F6176BB09F2D03FB8BBA
+:109EA0003D6724EE2FAEC8BD158FEEFFB07F7F312A
+:109EB000720ED657BD5DE5489F7A3EEC7E07DF0700
+:109EC00060135EF02916F4B1A0FC193FD1A3E64F50
+:109ED0000CFAAEC5CDCC7EF0ACA0318E7F3C3427E1
+:109EE000A31B3F2689E3EBF13CDD0FC6789D6CC9CF
+:109EF0007746FCEBE32F10B81FCBEC02C93B5D6F3C
+:109F0000823C8904FDD48CE2D1AA53A07CADE3A1AC
+:109F1000C50AF94549E44BFFBE01EB2EB1DA675D96
+:109F2000A0E59D98DFDF1CE4FA79819DC72985951E
+:109F30004B2238EE82A04B7026D8495705B9FED285
+:109F4000F75F1CB927AB10CF0E4744B19AB7791F02
+:109F5000E5AA20EB3FEF16B2D07BC9F074C0DE411A
+:109F6000FB72079688745EF7786422DDFB904C2EB6
+:109F7000BC89F453C25838978F37B08ED678D3F354
+:109F800064CCFB55FDDF1B53E8FC8D395FE6510DBA
+:109F90006FFB34BCFCBBF365F669F87B518BCFE8F3
+:109FA000F1AC8B93C8FB736D750F131D0D139739AF
+:109FB00043CFF7D1F0C39E1E4BF7726CE8B1C75385
+:109FC0000484C746FB970D7F1043687FE9EDDC26CC
+:109FD00079A1E7EFE8E5B493028B27EC23A4495D70
+:109FE00014274D3B29D17B33FFDD6EE23F7D5D922F
+:109FF000ADB3BE2EE6F79DDABA1C68FC8F009E77E3
+:10A00000D990C22CF3893E0B1AE3EFE63C8064FB47
+:10A01000DC07B576C7239373502E3738622523E1CA
+:10A020007B1D3FAF7FFE1B17F2D98693CE1956EBEF
+:10A03000F14A90FB2DA04FD725EE837AE6BFDA8652
+:10A04000BDA649C67D505D9FEAFBA06995E67D34BB
+:10A05000EB7DD00DCC5A3E26DB071DB4FFA9E9DB12
+:10A0600013C124FB9F65439F67DFADD1F370791F58
+:10A07000973BF87959F3FB17FAD7617DC10F80AF91
+:10A080006E6874D2EE5377A393F87071630AC56556
+:10A090001797F378EFE27B056DBFCE18877D11E44B
+:10A0A000C5323C5FAFE99DA32C5C8DF6E8AC4AC19C
+:10A0B000B04F1EAE493194E72FB9FB45BC37E1A53F
+:10A0C000497685E2CFD0570CED821A9EA7C894BE80
+:10A0D0003B30CEADC79FF5F57FA9E628DD8316039B
+:10A0E0003BBF2484F16791F8EBA5D726F07BE98488
+:10A0F00081FD7005EC840DE78EA17C8F8365DFA068
+:10A1000038EF068C8BC34C377CFE9B194447A094D8
+:10A1100063C8AFE3B3E2281F178FABC846BA7C7A97
+:10A12000FCA71E8C8BBE73EB713FAE536F7313E5B0
+:10A130001D98D7DD1C6736C7974F379E3C31B73F18
+:10A140004F80E8E145533C59975766F991104FBE4F
+:10A15000207704F1645D6EE97242975F07CBDADF26
+:10A160007A10FE7930E22498DED4E6DDCF971A5DCE
+:10A170001ED4F9F07327D9234F8FFF2DE55BE9F546
+:10A180009A8399C487DF288BDB697F16F3144A070B
+:10A19000D6657EE49AFE3276FBCDA52B0DF4D12F49
+:10A1A000A786956343CB293197C72792E56BEA7C55
+:10A1B0003058FF94909D9AF67B7BDC55F4C5F550A2
+:10A1C00043E3AF146C07CFCDD47EBC2312B7D04F7E
+:10A1D0006678D24E8A2C3E21F1BDC2DFF7EB010733
+:10A1E0007D8FD529AB57FBB83DDD4AFC1973D2FEF4
+:10A1F000B94F6DCE85FA3EBF1A437A78C8A7B6E448
+:10A2000026C8D3563BDF8F146D2CF2B8055E9ECC6A
+:10A21000D5F4320B07B0BF35B5C6F35CFA737B2EAD
+:10A22000DFDFDBE3AF0EA07DDD7AB83C80FCB3D787
+:10A23000534DF676B275BB53E727945F2503FEC4F2
+:10A24000466DBD814555DCC75D630F0712E38DEB9D
+:10A2500072791E47FAE4277AD06E6E956D9427D8EE
+:10A260002AF3FCEB36B734639BD6CE676827E9E761
+:10A27000A8E8BE0CC96DCCAF7E52B37792CDF3C9BE
+:10A280005C9B76BF68F73D35C2805EB11FA975D172
+:10A29000FD0F4C95797E53C8904F6DD7F44B9D2997
+:10A2A0005F4394BF98DF16F44776E55AF86D7B7CE0
+:10A2B000EA93B8DE5129E644FA88BAACF9FE696D32
+:10A2C0005DBFA7CDD77CAFAA68BAF74134DDFB10DC
+:10A2D000AB6BFA692FD2DB6AA7DCEAA37B1EE8DE50
+:10A2E00087285EB904CF7FA6F07C16F0FF26F2F334
+:10A2F00006A15E94AF2CE0A2785447BEAAE643596B
+:10A30000F4D81E5C0DFDB5AA752A1E5DE970DB3A16
+:10A31000719F2F33183988F398EA9148EF745C9451
+:10A320004A7A08BEA77039C264A19AFC41BA3405C2
+:10A330007D703C5F660F38289ED51A61BDCE31FC1A
+:10A34000FC3FF653CBBAF7D714A1BDEDAA443CEDC0
+:10A350000F4DC88858C809FD69DEFF7FEBDB6F141D
+:10A3600062BB0231F221E2BDA761F146DCD75FB1E9
+:10A37000530CE13EC2B7BE73F00C7EDEC8B8CF7C92
+:10A380005FDA945ED46751B783EAEDF15477209E8B
+:10A390005A054F07FABBAD8757FE18F1D8DAC2E36A
+:10A3A000DC663CEFF57C87EED7380ECB89F5CDF730
+:10A3B0006BB08E957C9D9C2EDAB784F9B2BC2ABE18
+:10A3C0008E141F3CE4A17BA08EEF7FDA8DF07D8997
+:10A3D00079A7E5F9879A77BE4CF68B463F4C0AAFD2
+:10A3E000C379DD247A3ADA7D784F1AAC37C2BDCB17
+:10A3F0004EFEFE7D69E9B4AE51800FD755F4D4AB63
+:10A40000E892FD7DA748EB1C959A685E2C26B1ED7D
+:10A41000F87ED789EF9F8774A066D1AE9658D04456
+:10A4200078F93BE065B5055E807E8A10DEA777DDB2
+:10A4300040FD74385C325A36AD9E6A3AAF3CD2FB6E
+:10A4400045CAF2389F24DC2F52965765515FF3B30B
+:10A45000D0DFC6716B65F6499C0DE03D59FECA79A7
+:10A460005AFFFDFD0C9FBF725EE2F8FAB85F625DB5
+:10A47000A79FCEBAB6BAFEEF74B4B354313D94522E
+:10A4800008655C27C43FAE13AE9716B72115A4200C
+:10A490001DC8DD79480737A487903E87931B12E3D8
+:10A4A000EB6E97809EC1AE73CA91037476518BF7A1
+:10A4B000E8F2C4CC67AD2EA3BC6AD5EFE53B3432DD
+:10A4C0007905F47215E2C12CB7464A272BF304F341
+:10A4D0003D342BF3FCC9E9C41E0CDF80EB8878CA3D
+:10A4E000ABA078C5B7B1FEFEFDE20EC7681C8FC7F2
+:10A4F000CDFA824C7E30212F4B87A70D37BB799C3C
+:10A500009AE21F5203639807E72D0D0972D988E874
+:10A51000A82D11BEAF808EEE1C8A8EDCAC87CE6B70
+:10A520002CD7F373760C9D9FF365F50FAC6727E28C
+:10A53000B7D5F31DA2CFB57697CCEF513BBD757D56
+:10A5400064F0BA3E32F4BA461EC3EF6A5E35DD638C
+:10A55000C4263592DDB4CBAFBE8179A44C0A19E490
+:10A56000E220FED1E4F64D672A94AFBABB4593735F
+:10A570002D4E19EDF1677C373C86F5EF624A18E302
+:10A58000A1536CAB084F7F87F93D1822B95A8AFB5B
+:10A590003E51961AD2F4E8538887194A8B9005EFFA
+:10A5A0007D0B141B5D43AA6C62B6B291E3E1C5C199
+:10A5B00072F0C561E4608F46CF37223DEBE7ED9343
+:10A5C000C9C143A72F070F7DC572F0CF79A7A1D7C7
+:10A5D000BF0279F3098E6796376E8D9FAF08B11071
+:10A5E000C6CB479ACF06F6A682FC559BEE22FA69A7
+:10A5F0007D5CA07C29B0C32354F6B848D8ECF5386C
+:10A6000078FEEF0EFE5DACE37836E3E9F3BC2C9EFA
+:10A6100077D3B5322C19F2A462C40F77AAC7E462CB
+:10A6200011F3FB6B889EBD9A3DA3E7F5A76BF2BFC4
+:10A630005FCFCFB4D178DE022EDFBD60EFA05DC466
+:10A64000A45E867EFC4D793C7F1FF881E81B46099D
+:10A65000233F644C924C795A9C5FFC12B777327D51
+:10A660004C205D837962F0FE04D813783F41A66ADE
+:10A670006C7753EA1502EAADDE46779340E7F4C300
+:10A680007B7E04E52CCCF702BEF1CE30D6F7B38446
+:10A69000B2857F1EAB63A598B75896AFF9E90E1641
+:10A6A00020FDA8F9E9FA7D81E2F0795F95F9238828
+:10A6B0002F9E9BAFE79918F571570AB38CAFFD57E2
+:10A6C0003E975BF5BDB5756857AFF230B2AB56A19A
+:10A6D000EEC472A683EEB509EDA97459DD5791A9B0
+:10A6E000DA0CF7F37A67A41AEEBDF587B30CE59C94
+:10A6F000865C43FD6064B4E17BDED2B30CDF0B9A71
+:10A700002A0CE551D1730DF58B00C189E531EB2E93
+:10A7100032D42FE9B8D4503E73F3370CF5C7C617BF
+:10A7200019BE9FFDF0B586EFE3BA5619CAE7ECBC37
+:10A73000C550BF9559DFDFB9219FCB29E0779263E0
+:10A740002DEEBA06FA1D0DD96188F32FD1EAEDC9B5
+:10A75000AC2EC57848EB91F252F287D3CF1DD21FB1
+:10A7600036CBC564F2D8FCBE4D1BEFA3A7DEAB5EB3
+:10A7700086748E421EE4D247EE37D7E29CD697F11C
+:10A78000BC04FD7731CCF7F2F7EF534A2ACD67418D
+:10A790009683599D0F5892AF58EE2FB4092117EEAA
+:10A7A0001525C39B4E8FC3E1ED0EADDE97C5DB21B2
+:10A7B000C11807427DF2B8055C7BF3FBEF3B7828BC
+:10A7C0009FEBABCA54F230F83D0EA7AB4F74384044
+:10A7D0009F3C9EEF1F9C1FFE51C3AB57DDA760FD42
+:10A7E000AB787D5BA814D725D9BED2DE7CF3BE52F0
+:10A7F000D55294730B3CA942E27DCDBFD4EAE9F176
+:10A80000ECD6F44F695FA9D5112A1DC9BED22FF12C
+:10A81000CE8D2AC4BFC2C7D3D7D5AE06644BFFCEF8
+:10A820006CC7B0E7F01E8C985BA2BC61B37F17D5F4
+:10A83000E4B6EECF497B6BC9DF6F758FA6BC8F5630
+:10A840007515E9CB8E247E2EE8CB3FE657613CE0C0
+:10A8500046833F37100F50693C684B76536B82FF3D
+:10A860008FEBA0DEC7EFD5FE0AFCE00FF34FC34E1F
+:10A870005018F7838F338EA7E3AA8DEC84E360270B
+:10A88000A0FC5D2331DAF78E550A8A955FDCB15A58
+:10A89000B30F5773BC99F7BBCD76C6C5A19584B7E6
+:10A8A00035404FAE4A8CC771FB778D9DDFBF297B4A
+:10A8B000C301D4B77D7E077B10A0DDEBE7F1391D26
+:10A8C0002F5F541E65160CB293330B86B093A78985
+:10A8D000655D786FEBB1933C2EA2E051441FDE43DF
+:10A8E000CED76FD57373622B504F15494D98BF2E3D
+:10A8F000322503F1B2E25991C5059463C6FC7C3B55
+:10A900006BFA01C6E3988FBF8F31570BDA49199361
+:10A910008C7A2C5335EA31EF8C2C935E33EAB19C60
+:10A9200006A31E0B468C7A2C6F698549AF19F5D8A2
+:10A93000A8689D49AF19F5D89875979AF49A518FE0
+:10A940009DB9D9A8C7C6C68D7AECEC875799F49AF9
+:10A95000518F9DB373B5E17B7977BBE1FB8467EFE2
+:10A960003294AB7AEE37D49F78E041C3F7C9BDFF8C
+:10A97000C7F01D10FD0A9E67C07B687111CF7BFF79
+:10A9800009E377A63A301FFF3A3C9F09EB787EDF58
+:10A990006F0DFDB10E7E6E2106FFE17AFD9945E84F
+:10A9A0001E009063FBF2A0DDF57121D4CD503F3D38
+:10A9B000FE1EEEDB5C1310C98F5B81C156A4874776
+:10A9C0003C71A487AB371BCF3F5C13379663403F86
+:10A9D0000AC615807E90BEAE33FD6E04D883446FE8
+:10A9E000D7295213DA9566FAFAB34E5F31F5153C62
+:10A9F000CFA1CF579F9F5D3F7FAAD19FAAD11F13A1
+:10AA00007711DCD7E589F4FB3BFA7C55F88F7FFFA3
+:10AA1000D081F338B153605EDCDF67B17D7916F326
+:10AA2000B97EE72607F2A7795EE6790CB2530B8C64
+:10AA3000FB8AD3447788F8EE3591F4114D01F9EC97
+:10AA4000517E5E6FD573229D8B413E447F418C3594
+:10AA5000105E56005EF0DE70DD6E3DA6B53BF68002
+:10AA600048E79B87E34745C3873360E4C71425D590
+:10AA7000444F46FCA6951AF9F3BAB72F74A0FCDA36
+:10AA800007F8162631E60919F9F53A7119EDF3E9D7
+:10AA90007856E03F1C57025317E77D3DCCBB5B194E
+:10AAA0008CDFA5BB36ADCDB3A09BE1F0FB48817137
+:10AAB0009F4EDF9FAB05EC382CF24A75FCEDF2ABF4
+:10AAC0004FA07C4CE60FEF2E30EEAB8FC01FDE9D0B
+:10AAD000286FBF027FF8B98221F55CDF2CF4A79CB8
+:10AAE0002C3DD46E11F79398DC8DF15A7B138FFBBC
+:10AAF0000DC4EFBEF238CF3B08A724733D9922E97D
+:10AB0000719ED08108DA27196785302F6AA4718E6B
+:10AB1000BF140C8A73FCA560E838C71B780E50CDB3
+:10AB2000C8ADB7213349A152BADF1941E079481FB6
+:10AB3000E3BA0CCAD72DCED2F28F9521F38F2FD640
+:10AB4000F677AB03EA498403FAFB149FFDF7B1558E
+:10AB5000FAA99FF461FA89D5717B2D66F374B472FA
+:10AB60007B8DF699BE8238467A21FAA56E8EFF5605
+:10AB7000078FDB9E6E9C2D583808EFC1C221F0FE76
+:10AB8000CFB772F8B9D5105807E5C9E95B3F87A977
+:10AB900097D7671AFDE5B5151CAE126DFC6F66738D
+:10ABA0007F607221E73F3DEF12F316532AA03C93DA
+:10ABB0009F53D2CFB5EAFD4C2EF450FD4F02759352
+:10ABC0000BFD9837CBEFDF599B69BC87E76F05B565
+:10ABD00093715E13B4FE2717329ECF3C9AC365CEA5
+:10ABE0003BFD8756FF1F0575F4C473B4E8973844DE
+:10ABF000D1129F530A799C40BFF766BA7E7EEE5E03
+:10AC00007EBECE7CEF02F0C9EBF8FB5047EFB0936D
+:10AC1000BF07FA88CECF2DC9E3E710CDF729444A04
+:10AC2000E57D285E4FB032CB7B7906E5391CBA99B9
+:10AC3000F2EF5E9ACC6421387CDEC36585C6FB11D9
+:10AC4000BEC039BA2B0A4790F7B0503B47D79BCAD2
+:10AC5000F5585FD0157FD0C2DF8D6AEB7487E6D7D9
+:10AC6000E2FE34EE93E3FDDE56FBE5D1424E3F2398
+:10AC70003D577D97231241BE359FAB4E769EBAD786
+:10AC8000D1BB2607E11DCB4268BFE72C90F7E4401B
+:10AC9000BDD47A85CE3FAE2D62E993F07BB92D8489
+:10ACA000E73A32E7CA6BEDC8A7C52C4B80726F6CD0
+:10ACB0000E8D7F4703934580ABB390EFA32FBCF578
+:10ACC000631ACF5F035353E8DCF974F4CF620D8C41
+:10ACD000EE2D34CFF32E8D5F5C6BF83D3919C5D660
+:10ACE00079F87769F408726B13F2456D31DBC1CFE7
+:10ACF000CFF2730A782D3DE56F8652695FF01258E6
+:10AD000037BE7FDE43EB776360EA7DB89E3ABF399A
+:10AD1000B43C05F379F2CEC2D33B4F9EBAC01ADEE3
+:10AD2000DF69EBDDE80FFF14E14D2DEDE0BF5FFAC9
+:10AD3000F9A95362B5F6D38E0AB68F4450FFA580A9
+:10AD4000FE13F0A9C8748E96B9043A0FEB529A8894
+:10AD5000AE522685BCF8BB68EC4A1BC37B5CA66A76
+:10AD6000EDD50626E0EF49502E20C969D3EF4BA858
+:10AD7000A1B616683F0DF7CD4298F71D5A8AFDD54A
+:10AD8000BB53658C6FA61437D5E27A3DB390F7714B
+:10AD90005792F312FA39FB81FBA796BDBCB726E1A7
+:10ADA0005E81B557BD6CBC7FEAAA97BFCCFD530747
+:10ADB000B75EF5F2FFC4BD02BA7C03356447BBFE43
+:10ADC00080C8EFD1FBFB9397DB711DD6D6B22EC4A2
+:10ADD0007BEC53C0B36B00CFF6BAF0335BD02E5987
+:10ADE000951EE2BF2712FB16C2F9761A93B1BD9EDB
+:10ADF0006F28B052D2D7731B04B21F98D4773D96F8
+:10AE0000E7EF4A93D17FF8FB936F14C4803EDFBA1B
+:10AE1000EDB807F353DF91FA3C08D7FBB7BEEA4120
+:10AE2000FCBD75AB48792874EE3B214FEC738DBEA9
+:10AE3000168C0A1F47FA5AD8FCDFD589F6198BFA07
+:10AE400049DF5F13078813EDDE87D30CBF2BBABC35
+:10AE5000CB6B28EB7A7EB9D3FADC7CE5282E97AE53
+:10AE600079A4D391A7E0F811FB2898E7FBDA39A081
+:10AE7000F77778C88ED7E159F448B903EDE17776D2
+:10AE8000395937C5057BECCCCDF507E65D44F8D0E4
+:10AE900083E0DCB73BCF817CB644607D4E626EB60A
+:10AEA0000FF1FD27CDFF33CF63C95BB203D77749DD
+:10AEB0002DEBC373678B6E14D6DE04F51745DCE407
+:10AEC000F79BE769D63757E37D3682D53D704DFB5A
+:10AED0007E07FD5C09FDA0FDB9A4C3F8FDD8B3371A
+:10AEE000ECDB02E3EED8E9207BF1EA61E2FD6347A7
+:10AEF000697AA99A4D3C3586F45FC63825B9DDA13B
+:10AF0000EBA3F79B1925A9FC057FDF179E1F36CB06
+:10AF1000F43C5EA8D07A5CB773CF3EFA6D61A9A706
+:10AF20001AE5DDCCE716A77D830DE4155577DEF035
+:10AF3000F41662053D5FB59BE27B13B5FB5FAED6B1
+:10AF4000CE7F541D30E7ABEE79E67768B7C1FC4F92
+:10AF5000E7DE9E0523BCB7E7D8B353D3E87C808EE9
+:10AF600097898017F1CBE32559BBE5497EB745E7C3
+:10AF7000A7E39ADEBD72DBECB5B9307EEB937F2E92
+:10AF8000C4F8718C71FAAE7A80FFFE4F953B9BE856
+:10AF9000CD85F41944BC9AEE7988B1D759027D5F0A
+:10AFA000BD2B8DE82400F6907312BEE1F45A85F7AC
+:10AFB00076227DBFC6DBBB34FF36B2EB365EFF7751
+:10AFC0000ED91920BE0CD8E8D91DB04DB2B867CB48
+:10AFD0007CBF5887B1FC91BDB710E5CAD5263FF4B8
+:10AFE00023C13A3FED8A51A3497E5DA9A8D3310F11
+:10AFF00060090BAFE5F15B7E6FCFFB52C7BEEF225E
+:10B00000BF6F13580CF0B4FC378FFE1AE5D8B58F1C
+:10B01000DD9B8E72EC03A9231BC75BB67D4D3ADE28
+:10B020002FF3BE144BC7F61FC4B93C1BA42F47090E
+:10B03000DABE949A2E804CBE9E480DFE7F65DFDA04
+:10B040005B609C7F009E91EFAFDFF12F2AEF535D95
+:10B050007D2C80FDF64E4738AE697437B584D0BF7D
+:10B0600034F2E7B53FBD375BA13C8F589E86BF3CAD
+:10B070006C77FD363BE5F9A21F8FC3AC607D343F92
+:10B0800073FB155D471D28AF651BEBCB3F6FF0775A
+:10B09000B0901CC86F2B766CF8584CC7E7076FE26E
+:10B0A000EF41AD30D9A74B35F96DA6FF9F9BE81E48
+:10B0B000F043F18518C0C57F8E89CBF1D69FDD376F
+:10B0C000FE30C0F7E1B617D2F1F72674FAD7EF7960
+:10B0D0003ED6B578A163887B843ED2F8A45F3F68F2
+:10B0E000FA49D90980E54071177F2EB377A79F07EA
+:10B0F000F35DD6690F21CD2F7B5454DD68571D7445
+:10B10000923DB2ECD1E344B7CB04B54F203DC7D25A
+:10B11000518EEBEB75DDA37F9A8E72FABAA0C866EA
+:10B12000022B5EFBCB13BC3ED0790AD4BFEEF1C339
+:10B13000D3BF8B6590272E8BF59ADAB5C7D1EBB6C6
+:10B1400058AFAEC3D3313EDFFAB37FD27A7CB05B67
+:10B1500060394583DB2FEDFC13C5C13E8485F16664
+:10B16000727CA1BE59D125363A32ACD6AF7BD66FB0
+:10B170002BE93BE5850FB78E1B4631AE1F7FF3E809
+:10B180002F7E0B702C7DD3199A89E3FEE28674061C
+:10B1900074F067A989D3FD8FD664A3FE5E6A8F65BC
+:10B1A000CBF4E4EF976EFD36D1E3D5BFFF76B6B6AC
+:10B1B000DF10B4913C8805719E4B1E9847F3BC8A02
+:10B1C00045881E97FE88DFB37802FC6C2B3FA152A6
+:10B1D000E172CBC9568EBFC5877213EF6C01381C64
+:10B1E0008CDFD7F50ACF7F77B24B3312ED5C87C285
+:10B1F000EDB9188BBF8D76E70A50CB28D7C4DF9FF7
+:10B20000988EFDDC58243539293E6A7D7FCDFF03B9
+:10B2100074C90FBA00800000000000001F8B0800F6
+:10B2200000000000000BE57D0B7854C5F5F8DCBD8F
+:10B23000FB0A792D79404220DCBC1309718104128C
+:10B2400040DD10C020AF0D444589B0040C0112123E
+:10B250009116ACFE9A1B0208946A50AA54D02E088C
+:10B260008ACF0604C18AB01145A8FD300AB5F8A2FC
+:10B270008B206F6441A8EBBF54FEE79CB9377BEF8E
+:10B28000261168FD7D5FFFDF3FFDEA70EECC9D3B40
+:10B2900073DE7366E66C0D83BF64C68A3E1ED6D528
+:10B2A0009BCD98855D34DF97CBD825C6A467EC8C01
+:10B2B000D530A3ECB532FABB9AC4D88975964EC284
+:10B2C000CD507661954DD0FE2AFEDD1628A74A02A4
+:10B2D0006379D4FC13D69FB1D9F82F09FAD97862D3
+:10B2E000F86AE897C5892C328EC3CFC430662B0F1D
+:10B2F000AB8DCC87EF1D3C6AEE06F5728C81A5D92B
+:10B30000A0BEE51B82993D56C2F66AFF35DB2DCC07
+:10B31000A38E07FE5FB3FE1B33C37E0CCCD77D50DC
+:10B32000DB7AC66A737E1583F38894964179C2EC02
+:10B330001BFE367E07BEBB01BE53B112DA676AFA46
+:10B34000DB72EA739683EDCD81E749F8DF057C5E19
+:10B350006259A42B8CB1E9304D56D076FEF3BFACC8
+:10B360007FF43D4D7F395278CCF150F8C70036E07C
+:10B37000AA18789FAD89652CBEEDFBDFD7C98FBEBB
+:10B3800067C2B765C6A04995C9FD02E2A9EA338B39
+:10B390005D063C56BD76D96C009809CC97D699B11C
+:10B3A00033AFEEFEF45E98CF992653CC28FAAA2349
+:10B3B00042E812C07BE5E66F86AF86F626C07B08C2
+:10B3C000D073F696EFCD06681F57C47C1618FF9908
+:10B3D000182763BD116FA6AFBD1ABC15C1736F18D6
+:10B3E0008D23C11087A5278141393B86D93DF0FEC9
+:10B3F000EC83A25D427C31DF625B58DBF76B9A8E97
+:10B4000006D1455FCF98CFECC4EF6EF9CD05314240
+:10B410008B77E3D75E0DDE553C07E3F59E20BC5EDF
+:10B4200066D991F01976FAE5593D5DD96DF1ABE237
+:10B43000F5DB3A864CDEFAFC624F89F02C6D870F03
+:10B440007585BA1D4AC9D8A74C83C799AF9C23FEFE
+:10B45000FD47BCC844E09BD9EB7F588C7C0568F560
+:10B4600059807F67BB2F10BCC861F531829B4B852B
+:10B470009CF6E6ADC767707D77446A5E80FEA605E0
+:10B480004C0E877E7DEF88EE7530B4F3922F220A42
+:10B49000E6B728844D764279DEA6C09D55984D9E2C
+:10B4A00002E33C2FE7D8647C2F844D6802FA9C7736
+:10B4B000FA223A8705E67D64871821417BAF9B1508
+:10B4C0003785B5E543C61AE8FB5ED6517D3D8D73E1
+:10B4D0009878E5752F7CEFA26C6416F89EB7FEFB9A
+:10B4E000D7BD501E335A6D88A769F5774730037C66
+:10B4F0007F47CAD809D0EEFE7D803F9A9EC31C0FBD
+:10B50000F89DCAA7CE4E32F9A9C1303F313C77CF62
+:10B51000DBF07E052056047E9DB65C8F9F99CC198A
+:10B52000E94942B93505F884FEEB367BE0BDE9AE6A
+:10B53000B0DA65F0DDCA35FAFA993BCE107FCD0C52
+:10B54000E22F17F2577C5BFEDAA0F2571FD607F9FD
+:10B550006B981866407E3EBF57745BE09D8B0B4D29
+:10B560006C31C0175F15DC0CFAB9B8031A21BC9D09
+:10B57000C34C8E25BE55F95CC5DB59E4BF8CB6F8CB
+:10B580006CADDFFA55FF87A149D59B5FE4AC86F22D
+:10B59000EC9B9FA5BF8DF0B6BF257EC1DAB62FDA32
+:10B5A000F9C3241AD74E0BC3719DDFF941E2C308DA
+:10B5B000FFC96247BE3DBFC0E260A8EF7686BBD33D
+:10B5C000B0BE07F003D0BDE19DEF7350DF33B690FE
+:10B5D000E8D82299A9BCB8E39F87059CC70E8B8445
+:10B5E000F3A8D9094880F76BFE14E266F8FE3BDF4A
+:10B5F000F77785FD7CF3996D662EE2CF7036613367
+:10B60000F26F67E6C0F9D4BC5DF07C3D7CBF7A4B3D
+:10B61000B3792AD417EDFA570EEAA3F39B9BCDA872
+:10B62000AFBE35799F63C01F5F48131B4D80E76F26
+:10B63000C3A1B36E8CCD4D5AED94C3DAC30BC7C30F
+:10B6400079C003CE0BF052E9CEEE181F17FF6BF155
+:10B650007161127EBF6AC700262669F12238F8F3AD
+:10B6600070B755A0F9F3E73BBFCF6161D79EAF2D0F
+:10B67000C94CF2FEFFCB7C7392FE5BE9CBF9FD4D2A
+:10B6800089DBA560BE6FCBD7DB7E49F0EBE1761A94
+:10B69000EF75CAFB98FFDAF9FFEFD0BBEABF76BEC1
+:10B6A000D7A2F73E85DEE1360BEAAD77FE95C86E90
+:10B6B00060DEBFF97F74DEADFE8FC16ECD85F17D9A
+:10B6C000CEDC77160AE495B4EB8F6C4F12A83D538D
+:10B6D000D61D6314BFA2817D3D740A7C57067F028C
+:10B6E000FDFD86B0AF8D07016E013F01FD0B86CEDB
+:10B6F00009E0A1A5B48F7B19DA6D632DB3016CFA53
+:10B70000742AC113CA7F30E642FB3BC1CFC3F6FBAC
+:10B71000EBBDD3EAA17E7F6783D400F058C7F8B4AD
+:10B720002D00DBBA89365CC73438FA5925CDF8C606
+:10B73000E6EBD723F706AD2BEE9EA0AFBF8BAD8B0C
+:10B7400035427F77559A981BA6746750FBA7926C79
+:10B7500034CFBB59ED225BD88DE3E978125F9F357A
+:10B76000B0BE7B25C48B43B46F606DF1C6106F888B
+:10B7700097B87E6C991DBFE2351E04D8A2F857F029
+:10B7800047F278678CF505C49385CD61BF84FE2EA2
+:10B790004BC65A6C6F61B06EE4E316AE0A6DF106EB
+:10B7A0007F92B13FB9E24482B18E0719E2199FF747
+:10B7B0008CD3BD4FF30EC6F38DE37541DA5388D7B2
+:10B7C000D270BB1BF9C2F17CAC11BED700781684D5
+:10B7D000003E553C05E3FD6DE40D8D5FAE96D9CC82
+:10B7E0003709FDCE0816615F06FD4758BB33239F1E
+:10B7F00087CF128F858DE17A4D1CC29A96C17A8DC2
+:10B80000E51BCFB6CE2B99EA3D0FC37B0D0FC0FBD6
+:10B8100088D7EE4C7212FF97D98EF7C2659E8B5D6A
+:10B820000D0DF89F1FE583FF994425F1ED47EBB916
+:10B83000BF7979F01B8BFB80283198B3DC1FFD5C4E
+:10B84000E54FF696E17B2233D871FDCB1C0EC9D6AD
+:10B850001FFB65B4AE89CC37E8D6BF9D1D9D7478BB
+:10B860008B2E8ED2C1B1CE6EBAF65D2724EBEAE301
+:10B870005D37E9EA132AFBEAE01EB50375ED7BCEDE
+:10B880001FA28393E43B74ED53968CD3C1698DF76B
+:10B89000EADA67AC2AD7D567B967EAEA7B6D9CA379
+:10B8A000837B37FD4AD7FEE6ED0B74F57D3CCB7408
+:10B8B000F5FDF63EA183F35A9ED1B51F70689DAE8B
+:10B8C000BEC0FBB2AE7ED0C9CD3AF816DF9F74ED94
+:10B8D0006FF3BFAB830BD987BAF645D6033A789896
+:10B8E000ED0B5DFBDBE38E06C53B6CF283B9A8C6AE
+:10B8F000809F40CE46486774ED618556867C6352D2
+:10B90000F86164E677BAFAD1F67FEAFA33B35A20DF
+:10B9100002B25523959D58139561AC85CA877ABBB1
+:10B920004626A33C3C272F46A6DA5FF07D22DA911B
+:10B930008F063F2823DF5D8E6336B10F8C87F98C2D
+:10B94000C8D786D02BDD5D9AB851845F649E7EC0D7
+:10B95000877E814A9B3F9479A2810FFD215446F94D
+:10B96000A3E979B4BF339531FE047A1EEB8FA7B2F9
+:10B970008B3F85CAAEFE242AE3FCBDA88CF7675135
+:10B98000D9CDDF8FDE4BF0F7A1B2BB7F103DEFE1E9
+:10B990002FA032D15F44CF7BFA0BA994FC23A94C92
+:10B9A000F28FA032D93F9EDAA5F84BA84CF54FA4F0
+:10B9B000E769FE7BA84CF74FA532C33F85CA4CFF11
+:10B9C0002C2AB3FC33A8BCC9FF20BDD7CBFF009500
+:10B9D000D9FE87E9796FFF4354E6F81BA8BCD95F0D
+:10B9E0004FA5DDFF1B6AD7C7BF94CABEFE27E97902
+:10B9F0003FFF0A2A73FDABE9799EFFF754F6F73F44
+:10BA00004FE500FF5A2AF3FDAF5059E07F89CA8104
+:10BA1000FE37E8BD41FE4D540EF6BF4DCF6FF1BF6E
+:10BA200045E5ADFEDDF4FC367F33950EFF87F4BCB3
+:10BA3000D0BF8FCA21FE03F4BCC8FF319543FD5F20
+:10BA4000D0F361FECFA81CEE3F4AE5EDFE2354166D
+:10BA5000FBCF5039C27F8ACA3BFCDFD17B23FD1765
+:10BA6000A81CE5FF273D1FEDFF81CAD678C26053B1
+:10BA7000905E6CD57F86AB50B2B0A876E36DADEF2B
+:10BA80002BFA7845E8730CE31E636A055AA73F1D3D
+:10BA9000FAED7BA4270B2C12C28BB0693CFF8EAD54
+:10BAA0000B63F7E13F24C69A0B2CB47EDFFF3FFC0B
+:10BAB000BDC58547BF7C10EDE3031686F63158FF00
+:10BAC000AADFFD287F772CFA618BFB7AAB30FEF280
+:10BAD000DB246F1996DB92B93FF27A32B7B75B93EA
+:10BAE0000D543EDEDB4665D903699114A78AB9BEC1
+:10BAF000795D56ECBEDAFEF7A90A1CE64B247B7191
+:10BB00009DFD5C6FBB45D65FFF01E33A8E06230BBC
+:10BB1000B9156023B7F7F297E1EE0D30257948EDBE
+:10BB20008B18E79117586C0D3188E75FFF11DBCF59
+:10BB300067CC6981F29964D77ED40BDF8724BAC1C0
+:10BB400038C25FED8071E13F6BFF9FFF2FF77FFCF5
+:10BB5000A7FAFFBBC247B7A7384F27A35F6074E4BB
+:10BB6000201D862C881763E0FD29CB051BF2D1D45C
+:10BB7000857D86237FF4650E8A93DE17CD263BDB19
+:10BB8000F1CBA2520C8A7F2199EF86F19C63CC8382
+:10BB9000FE44B9C4882FCB77086E99E2D08E88D145
+:10BBA00060BF2B15BE2D5F526F9E07EDAAE379BCD7
+:10BBB0008CB979BCCC0AFF43399AD5B8760F851B6E
+:10BBC000C52B141FBB8C7E2FB0CEAC8D6DE3B1F3B3
+:10BBD00030CEBCDD6C43BB51DD1414CF0D8A9B0508
+:10BBE000C7CB4253C263505E999DD9799C3BACE26E
+:10BBF0006FF83D16218931D7C68B1A9F9598D415B9
+:10BC0000F1384CCC8EC475CCC5BD69910C4B49EA5A
+:10BC10008AED5C408B162805A36B003E077CCA4862
+:10BC2000575F7DA87B1D8CEB08D813A91F0AB76B43
+:10BC30008019E3919FF760CB04A21AF96135EB45B7
+:10BC4000F2EBBD0BFEB918E3D833928CB40E988298
+:10BC500031771CDF5B9DDDB240FD12DE7DAF091444
+:10BC60007795D99C388CEB6AF643C8AF752E8A1D40
+:10BC7000938F745AD2B9AF0569253B3E4DEDA2A111
+:10BC8000CFC206C26B795C34A7CF7613F9B5409F5B
+:10BC90007AA4CF0CB7E99816CF97D91533EEC7948D
+:10BCA0002FB940F49A19A097AE5D756333D115E8AA
+:10BCB000A47B5E537B428DA31FFB297A15A628F136
+:10BCC0004D855E183FBF1B2B1F8926FD50B6C093C4
+:10BCD00056ABE1D3E07D89D46903239D200FC5DDF8
+:10BCE000383D98D1DE05E9F9DDF23CA257309D8A56
+:10BCF0007F9C4AF4609F87B30D309EFB52D8E4715D
+:10BD0000F07CB2127FBDAF614431C6CBEF49E1FA9E
+:10BD1000F223587F3A60FDF9719D953940351FA88F
+:10BD2000B311FCD7BA3882FF562751F9595D2695D1
+:10BD3000C7CCACB249235FC000661CDF6445AE26A9
+:10BD4000A7A8FB5273E330EE5EFCE3813C03AA50EC
+:10BD5000B9A964D82DB8BE002468F033A134947C0E
+:10BD60006915F69A6CC3E3507F2C15EC1B90AECE90
+:10BD700041BAF62CB35F0046FB65E4FC047CB10ECF
+:10BD8000F9EF9E51D1BAF6772D49D0C1F352241A5A
+:10BD90005F49718AEEF9BD65BD74F0143FACE7E10F
+:10BDA00053A952B14186FE2FFDC544FC7CA97640C3
+:10BDB000D7791C26BE0BC6FF31B34C7104799DC5E3
+:10BDC0008EFAEF6408E7EF937F15DD0DB4EE952949
+:10BDD000EE72D96A93709DF2CBA97222D6FF32140B
+:10BDE0005CF23E882F9161FC80BD6C21FD39759518
+:10BDF000C06494111FA3F5F2DC972C34CF69AB44D7
+:10BE0000E6EA477C9288EDE7C64AD4DF7D295213E3
+:10BE1000F2B36F83C5BE0E6AA77A95F785BEB40FDD
+:10BE2000523DE76F878D280FE92D3918DF2F4BF230
+:10BE3000C4A21E3CBBDE44FB5ED5E2DA8A3020D1D0
+:10BE4000ACDFBE11512091F8117E4F7F1CBB16E76D
+:10BE50001F98AF9BE222DE9ECE6753009FA72BDC8C
+:10BE600039B44E7E84C7E3DBE285919E920D11D2F8
+:10BE7000069CEF54D7005BB6D61EF27DBFA9267B89
+:10BE8000177B36727F6E3CEA8163CB4DC518770114
+:10BE9000BD3F06F174AC31DAB08C16559B89BFCA30
+:10BEA0008D9259FBDDF2E5A283DA837E2F417BBDC3
+:10BEB0004274B101083752FFF212C185FB4EA92C22
+:10BEC000BF2BF2ED830F0CE88AF398D4C13EE3B7A1
+:10BED00020332ECD3ED6CC7744A71BBF97EB3596AB
+:10BEE000F6D68E9FC781525D4BBACF413A6D0AB1EB
+:10BEF0002F9350AFA644E23AF5D441B01BF08D1910
+:10BF00000DCD3912B05ED583DB880E95639AD23D94
+:10BF1000F0BCC5EAFA00F17832BEE9A9411827DA87
+:10BF2000F17CA28C76703EDF5F9BF9F28C9E5A7F8B
+:10BF3000BEAD3FC1E20CF95878BA08801797C486A5
+:10BF4000237E27B226257EE1A6F149A874011FB6FB
+:10BF50002ABEFF36D5609F742017D11F6E43BAA842
+:10BF6000FD1D35F138D7E72982CE0EC7A672F99E9E
+:10BF70006AE072C7760AC4A740B04F5335F6B2865E
+:10BF80002D277B19972032DCB73B9512A5E8056E6B
+:10BF9000FF66A1FDC37D619B40F251B5D1E27603FE
+:10BFA0007FA5A472F99C697EEDA9BED83CA9D68C68
+:10BFB000DF99B14560CF40D3D32677450BEE4BD9FF
+:10BFC000D62E8CA2F74C7637F2A9A2DFADA0105086
+:10BFD0002F4CC77F427DF54AC1ED217E71921D9A9B
+:10BFE0008671135CFFA39ED7E89136FA3D48AFDF18
+:10BFF000CFF4F68835EAED8B3334DC8AE39CB992D2
+:10C00000FBB581F188EC2AE0AAC2E5DE3386C62BB7
+:10C01000505C24F8FBD3717C385E189FC77EE3E345
+:10C02000A9B07339AD6A14DCEE76C6A7E23572307A
+:10C0300093D03ECF5A2FB8911F87C53C40F89D0939
+:10C04000F88D46BCCACE88BB01AE004672537C85D3
+:10C05000E3BF660DC73FD0F913ADDDFD26C66746C9
+:10C06000BC7E03F653C6FDC0DAEF89EE7B80BE28A6
+:10C07000BF3336B9CDB811798635468421DFAFFAA2
+:10C08000780F2E0BBE59F946175CBF964579D20C36
+:10C09000A0B7A2E5A8278A6F09F05FB0BD6E6397CD
+:10C0A00083F0233327D9A13678B22E6FC17DEF36C6
+:10C0B000F453E262F7E3BF003FF7AF171D2139BA2F
+:10C0C00076CA790499F8BF52F6919F5009F36CB083
+:10C0D000E1537938E2E57E3B23BD7BA3E30D1E27C8
+:10C0E00013CB883F31AE877EC8BF3BDE60FFA32401
+:10C0F000F5A7FD8F603D12EC7F7C69721816A0DFFA
+:10C10000F731DF17BF64F4F440F9BD14936C871660
+:10C11000013D1ADBB72BEA79558F5628764BEDF7A0
+:10C120007EB457001F5FF54604D25DA5FF74B413BB
+:10C13000D9013BF1CBA9D03F7CEF97DB42A8FF733D
+:10C14000A3C14E419F65CF7E10C134FA6F414F5756
+:10C15000752AEA13D5AE896B136DC05FAABEBCD633
+:10C16000BAABC3798505CD2B5C3FAF729C57BF40FE
+:10C170007F5395797DBD84CFE7E8723EBF696DE658
+:10C18000C5EDFE2F9FB7D865F20B3CB12887273746
+:10C1900089AC81E8CBFD86CB56E0A73E18BF594E4F
+:10C1A00076FD542C9330AED3A1FD5E6121BF60C6F5
+:10C1B00056BEDF7A5A28EC4A1BFFEF79221E42B99D
+:10C1C000DE2C32B44381F1B4DAED95A9B11ABB7D0E
+:10C1D0009D78C3382BDAB3D9803AE4FBD93BBA3225
+:10C1E0003CE7B2BC903589B40FEF253D062C44F1F5
+:10C1F00069F0C375F1060BB35BAD48A70EE2AFFF64
+:10C2000048BB30690EE1C3978EF857BF5FD3C9634F
+:10C21000EA8A7ECD2681FC9AEAB98511850CBFC3D6
+:10C22000E3669B53B99DDAAAE839C1514B7131F0ED
+:10C23000696C8FE3B8D6F0F8307B9735217E11A674
+:10C24000F8B181CF43906CACAC2F8FCB5BD1AE8576
+:10C2500019C8AE05E3E16BE53BD5A281FCDF2A33CB
+:10C26000F783CF0BFCFCC7BB8A7D7C3795FBC31FD4
+:10C27000A4F238C479F403A1DFF3B758DCF502BAAD
+:10C28000AD465A271B075BDCE8CF18AD611E3107AE
+:10C29000D16BFCB6559E015F93588B09E93926FF97
+:10C2A000818D389FC3DD984DEC4CD54EDC479848C6
+:10C2B0009A81B1FDA62FDFC778A40C6D45582B4C91
+:10C2C000CC3FD103DBAF4118E67F38A4E97D8CB3C6
+:10C2D0001C4E3232DC1790DFB190FD370DF1F6A025
+:10C2E000386527C61AFA603C66F722E4A33D71D18F
+:10C2F0009936683FD9D8C92E72FD33F4028EB752F1
+:10C30000E0FB370BBD79489F9BD942DB712B6D2D2C
+:10C310006CB91AFD53FC6364C7553E8031550D81DD
+:10C320007F0C649CB1F2099F3A18F04AF0F7A973A8
+:10C33000C7ADEC8E9B26526FA47355B2CF88FB29F4
+:10C340003E81F9D6011EEECCF7191D482F076B1A56
+:10C350000BFCEBD9C704FC0E8A007EF76E4FF2305F
+:10C36000C403CB945824D48F354A04772F6651A246
+:10C37000B26F8071AC438304A283C12A9970DECE70
+:10C3800062A12FEE8B562DB8BE71866CF8F5B8956C
+:10C3900083013618F87AF621BE9E9D281F19467E25
+:10C3A000D26026201FD6443599681D0DF282E3EF36
+:10C3B00003DD68F137D1E8E5E3AB84F115A05CA4B7
+:10C3C000121FDF5B2B903F59636E3FAE119BA6EEB1
+:10C3D000CBD9246C3F0BFE857C3D6BC7B634FCDEAD
+:10C3E0007281F3C12C95CF5ED5CBE58034467CDAE3
+:10C3F000115FE72AFDE7A619F839AED6EF3591DDD2
+:10C400009DB5E38343B8AEECA8FF6A0BF3105EDE84
+:10C41000B150FC4030F852892E8848A0C344F4271C
+:10C42000C145EC9BC6FD44953F2BD0FF48C192C748
+:10C43000450CA03CD11E56363E6F46A4059F3F02D8
+:10C44000C787CE01CD5C1FFC5C135711757A87E25C
+:10C450009E82D9370DC723DC1A62477D3CD1DC446C
+:10C46000EBF2E076A646EE679996703F8BF6D50024
+:10C47000B62CE77EE6C4EEBEDE8CF49C6DB890C4AC
+:10C480005AFDE20AFE69785EA5F38B2D1847C0B805
+:10C49000D72AEE0F1A15FFB57CB9DE5F98B850E3C6
+:10C4A0002F52B7BE6A1CAFE991508ABB58D09FD0BB
+:10C4B000F8017F3794C8A887E564239DBF34B16035
+:10C4C0007FC2C9783C933F372A7EE2D034936EDF37
+:10C4D0004D1EC232110F65A8875250D53897603C67
+:10C4E000EF220B6FC4B8D930F1118AFF95D5F373E1
+:10C4F00069C1F1BF8BB5EF3F8BEDB11E9FCFEBF460
+:10C500006322EE6FC2B2D429DC0AF2DDE9F06517CE
+:10C51000CA07282A13CA7BC8FE6F10160C914CC894
+:10C52000C7EF7B9EC5FE65B3D5867AEBE9D008EAF6
+:10C5300067FE7C81E2C30B6D5CDEBEFA327C1DEAD5
+:10C540002935DEBBB8B0DF2A3CB7F4EBB45DE3AC11
+:10C550003D503D303AB70486F11307CCA7F40AC822
+:10C560000DC1EF8F7344029FBFEF9B64053CADDCB0
+:10C57000F0FE3823F0E3F9DFF99E43F8850DFB392F
+:10C58000FC5B5F6208C26907C619418ECED7ABFD5E
+:10C590001D18E7C07DF7DF73B801EA6580CB50BF97
+:10C5A000E1BC070AB4EEDF8076293610EF2933BCF0
+:10C5B000CBCB21CC83F6F35AEDFE98E6DC80F65A1D
+:10C5C0000C3F168EFEC5960C07C19B539C8FA5A1F0
+:10C5D0001F74D0DD2516E35806D68274013BE66849
+:10C5E0006F5F7A432A97DF4DE9BC3F155FD0CFD309
+:10C5F00069B137DECF6D6DFB71FF3BE3E99401FD5F
+:10C60000E4E9FA79E9DFE9A72AA81FD56F030758FB
+:10C61000423D7526D3F11ECE73D6AF1D43B6A0FEA4
+:10C62000D92F129F7E57BB2D1DEDFE77AF5AA2D199
+:10C63000FECD7AFDADC40A8C23287ED199E6CFCCFD
+:10C6400012BC3FDB2F3207E8E91ABF40E5EC2DCDE5
+:10C65000E6E1D978AEB6D95CA4195795324EE074AC
+:10C66000E3388D1FB32F4D8D3FAFA0F1CE7AFD94EF
+:10C6700011E939CBD0741CCF1FB3813CEE153CBF00
+:10C68000CDCA7B87F1BC413B71808FD2B8DF11D717
+:10C69000CBB11FE7B709F539F28B819F0F096EDF28
+:10C6A000359DF757D689EBF9BC83F68A03B4EECBF8
+:10C6B000318850F63F546B2E87E70752861C4A6B31
+:10C6C000370EE9E371C81D3C0E5916D532178C1987
+:10C6D0008B4ABFF804CADBC8A755F900D103FD5245
+:10C6E0006C51E190F14307F33817C29737189EC495
+:10C6F00073847B3BB5FCE200DA87A5E16C1DC8D9E9
+:10C700007D03C21337C338A6CA9102D84E566809B2
+:10C710004F9F02ED4E241746A5F3F327E41F9E48D2
+:10C72000769EC3F17993420DE08C309799C7B35C44
+:10C730007F16299EE5CA0975B9DBC1D719059F5136
+:10C74000E9DC3FDB6B8071F6C571F0F3BDF097B8A3
+:10C7500019E34D0B7A0AC877EAF76F4F29EC9C9ED4
+:10C7600017F8FEED29CE1FD362B5ED2319B6BFDE53
+:10C7700071FC53B1A79DD339BD9C8381BF347A7FAF
+:10C78000DCD0501D5C3A2A9A39B4F1CDD2041D3C5C
+:10C79000A12C45D7FEDE69BD74F5A32D2DB9B537A3
+:10C7A000E0EF8B119991B4FECFE3EB90AF765CFE96
+:10C7B0007422FAB1EB45BB00F39AF1CE864F0751D4
+:10C7C000EF12C5B94EEF15C91E817B6BD6EE9F9C4B
+:10C7D000632D74EED8D87921D9BF5971FC7CF70C40
+:10C7E000B77EFF438DCBB7B76F82F6AC0ACFC5B427
+:10C7F000B76F1288C7FFE4FE49BF74653DDC97F54B
+:10C80000E5EBE1B37B60A6AC687B33D1AB619F689D
+:10C8100047566DE8213001C679FB168B3B04C67D77
+:10C82000EEAD236649B37F52E30703108DEF1D3150
+:10C83000E379AA03695C6FCFDE71C1CC902F763C9F
+:10C840004072DDD2EC8A8945FB05FEEAD65CE4AF96
+:10C85000A65CB47F7B0D3627EE87CD5A3282E2CCC0
+:10C8600091FE895456358EA07EABFDE3099EED0FF7
+:10C8700025F823B165CBC7D8CFD39136B4E7D546D9
+:10C88000F955A44BB514DA0FF7AB666FF9F8D2AFD0
+:10C89000D08EDAF8BD8ED1E227B9583FBAA7CDD0F5
+:10C8A000D019C71B42FDB40CF92217ED5231AE0B63
+:10C8B000E079D5E60217CA7D6143B80DE55EC4F3A1
+:10C8C00064EDF0E9E474AE5F4C5E3EDE61FE12EAB8
+:10C8D000AF757D9F9E4CF3576153EC7A23EA0F7539
+:10C8E0001E2630F858DEE1EF4565CD9612239E8B6B
+:10C8F000FF73E6F3318827681F8665EAD041A46795
+:10C90000BEAB1D10C9DAD15B6A6951F4F044D4C3DF
+:10C91000D05F69A6E3572897631EF11AADA847C3F5
+:10C92000AC36DCFF1893DF47AAD0CC477CF71E5CFF
+:10C930004980AFE233A11F30114AADDE9EDC817D1C
+:10C9400091D30D8A5F54CFCF75AAFA7DE5130CD72A
+:10C950006193F859AD56B9AA56DAABEFB708DC1FA8
+:10C9600090B7F2B87E75A6EB491C6F4B219BB0992E
+:10C97000F4694B6249F8CF37FE08630BD139C22600
+:10C9800019705F41AD5FD53A0F2EDFD79AC722A548
+:10C99000FD47229B8F7CF1D16DB7B538A0DFE687CC
+:10C9A000FBF5133576EAA5747EAE99D97C57485FBE
+:10C9B000EC0C95500F8CC6BD87DC80DF8FE72131F2
+:10C9C000AE51B3D3B20ECF83D544C03A1FBE3FAAF7
+:10C9D00097EB25C447F3AE824B788FC6810B33901B
+:10C9E00073C78E0197F09CBDC30ADAC68E7E90E3B2
+:10C9F00065D2FF1D8CF75AFA2C75E8AC18F427BEE7
+:10CA00008321A1BD05BB9F7B90C34EC4976B099743
+:10CA10003F9722875314FE2D57E4708A91CBE1E4AF
+:10CA20009591368C77963F22F4C6F3724C0AB7A3E1
+:10CA30000A30215FF643FEE47C59E5EFACC87392FF
+:10CA4000D20FE7FF60F99CED8FA676AA9CBE9CE909
+:10CA50003AC4ED5C4BEE7C18D71D20D7A8F75C0BD1
+:10CA6000E273514E027C62B6213F019FC45568F8C3
+:10CA7000A0A1F90723F28969B0407C6281B248C362
+:10CA800047CE56FFC436BC0BFA550B930CCB58A0BF
+:10CA9000FEAB74D54FB93E7EFFB3D2BE3C0CFC0852
+:10CAA0008AFF44308CAF5D8C91284E3A67290C1276
+:10CAB0005030C7E449C338CC9C0742280E5671B0A9
+:10CAC0007671B8D4965EF7F873687F79BC3F95CAE3
+:10CAD0000329AE33888F29FEBB143CE65CD7FE5C8D
+:10CAE0009E83C7DD4C6E8B7D6D12C6DD5C22EDC76B
+:10CAF000F560B627C94EA9FB713CEE86F13C8CEF80
+:10CB000005EFAF611C0ED7D39618836E9FB04D3CD6
+:10CB1000AE50BF9F56D5FC497F03D49F4E72505CE8
+:10CB2000CEDBD365CC8079CC1CE77EDDA4DD6753FA
+:10CB3000F0D864F4A4A11D6DAAE5F8695A2E16D3A5
+:10CB40007E1363A1259AF3BAD7E2E399FE14C28F4C
+:10CB50006A5F54BDBDAD8E0E7DB6EAEF6BD99D6A9E
+:10CB600085DFAB91DFED6DED8CCAAFC1FCACEA6740
+:10CB700053EC41D24377C02BE83FA8FABAB868D04B
+:10CB800060B4F3835E4AD9F227987F74A62B3703EB
+:10CB9000F8E7B6577AE4AE06F80EA3DB680BBB1EC7
+:10CBA0007DF88389F4E123258CF421945A7D68EA89
+:10CBB000C00F2FC8B8317D9EA1B4073F96FB87A058
+:10CBC000AFB5FD55670E1985E32FC9E076F2E71A78
+:10CBD00077477ABC244395CFEBD3E3B72AEDAFA5D3
+:10CBE000C7A765703D1EACB7411B93DE3EFF4E16D6
+:10CBF000C5C90E33D0F368CF76844A1B9234E7DC84
+:10CC00003B45BAB57A3DAED7D469C8EFD7A1D7EFC7
+:10CC100047FCFDBB7A7D78C926F2ABE0CF39F656EA
+:10CC2000587FFC06D677087F04EBBBA4B6F2102C25
+:10CC300007C17C0FEB912D1FC3F8F63ED593E20E92
+:10CC40002007C4F7D5C0F72807AABCCCDED227122C
+:10CC5000F70DD85F4486FA3F580E8A8B5E31629C8E
+:10CC60000AF538E26B37C83CEA99603BE1CF70AD1A
+:10CC7000C4F9ABF2A0CAC1B5F9E82D13AE4B4D55BE
+:10CC800017B89E8752ABE73BF2677E7F83FCFF6855
+:10CC9000C6F5F901AF66F07B103F23FFBC9A717DAA
+:10CCA0007EC16B19FF915FF036F10FEA4F5CBF8DCB
+:10CCB000FCD01E398FF30F9D4B047EC8C5B8F3DE40
+:10CCC000FE3DEC18A7197995FBF5A0D3C9AF0FF677
+:10CCD000AB272AFA6FB212273890E96CC9E0F24A02
+:10CCE0007E7B614A681FB457D7EBEF4D8CA965185E
+:10CCF000679A0CA5564F58906EEDF8EB7FCDB83182
+:10CD0000FBBDFB3AE97B3CE33FF6F37CD7A30F5234
+:10CD10001DD6F188CFEF3C468678BAD67AC0B48A61
+:10CD2000E3598517798CAADD8C46BB09FC71E13F7C
+:10CD3000E18FD1454D97AC40D7C84C6329C603EF6E
+:10CD4000C2B31614CF30AD74A4A2BE61EABE00C552
+:10CD50003B3E1255D87C70288C63E4932CB06F0056
+:10CD6000F5C30647B6C6470416681F91291E5C4ED8
+:10CD7000E3E6E75598CB6BE4FB640A9C0B70B806BE
+:10CD8000CE0F82D7F0F611462FB369FB51F4CF18BE
+:10CD90001BDF1708ECE7F9867746FF6F8B60C3FD52
+:10CDA000857B079F37633C677491774F02B44BCA0A
+:10CDB0000C2F0D03137FEF1681C6DB6763CC4A3956
+:10CDC000958E6C39F0BC61553EDF37B134350F7745
+:10CDD000B4C3877D32F5760AFF8C5D283E467F9688
+:10CDE00026819973793FC949D7F73ED28FDE4FA686
+:10CDF000F73D9698EB7FFFEEC1CCE16E878F6ECB4F
+:10CE000054F421C685D5FE8126E39B04477B719BA4
+:10CE1000DB95F62D064335033C8DDD98B912E35EB4
+:10CE2000C318E78B928D19A532E73FE6089AEF4FBA
+:10CE30008D372F53BF3EC33F49FFBEE7A7F035A84C
+:10CE40000DBE14FA57EAF924D2E87CEF3B18476488
+:10CE50008C60433F75B63364398B44BA2B7C2DF715
+:10CE60002D750C86F985305D1CAF95AFE57EA5C8A4
+:10CE7000D7B399DA3E6F25D2DF69686DCFF97C8729
+:10CE8000D0FA7EA691E127E8FD591B7357629C1CDE
+:10CE9000E841F5041B7F82CF9B82E0C14172C1381B
+:10CEA0004C72897A19F093D6CEFEED1205BFE704D5
+:10CEB0007EBEA96508F7E75A9279F96226F7DF1E68
+:10CEC00057F0F8B452B674D2E0A17B80CEF0E7C13F
+:10CED000F58066DE84A77B629479CBE34B47C1BCC7
+:10CEE0005AA2586F01F864EDC6B12B176AF8E4F93D
+:10CEF0008DE34B110FADFDC92507118FF728787A07
+:10CF000071E3B883C84778E404E5AD3A9FEFBF5AB0
+:10CF1000B67CDCAEBCCD69CB3F32E657A82646C214
+:10CF2000F704872997F793DC0E7EE6B77DDF11F4CF
+:10CF30003E33C5DCC8FB0A7D4605D1AF38887E4349
+:10CF400083E0323D1CF083A167F09FCAB7AF58D48D
+:10CF500005E3671B05BA6305FAD92CC0F31D99F7E1
+:10CF60009586C5239F4AA60468EBC99C7CD09A0588
+:10CF7000F288FA8BF4AF8BF4F578947382A7943A25
+:10CF80006E46BEA95D1407EDF76496AFC47BAFF79C
+:10CF90002E5C6142A4FF3973DA4A23F47B4FEE1F03
+:10CFA000F7607F46A1E2E028E127F8B431681E6B04
+:10CFB000826039A8FDCA6BE8F38541EF3F1254BF88
+:10CFC0003C085E15042FD1BF3F651ADFBF9C02F4F9
+:10CFD00043C45D4B5EBC99ADEB8656FB25A03DFB83
+:10CFE00050CFEF231B387C6AE383A54BC23470E635
+:10CFF0002F4AB5FC6B52ECC5C418A7A33DFE3DD427
+:10D0000011FF6406DB3559772EF130633AFBBB5BC9
+:10D01000D4C3CDA22A5F0B0ECECDD6EC07CAF5A5A0
+:10D02000184FE978BF422EC5FD8A918FABEDEB4AD0
+:10D030001D9AF9A9ED87FFEBAA88DFBB9A5957BA69
+:10D040009EF6FF94FDBB285EDE76E56A04D2653865
+:10D050009E1FC5FA4E9EB439D99AF9B1A6749C5F49
+:10D06000F3C3FCBEA1DC00F400392F6776DAFF6E53
+:10D070008E8C9CFF02B4DFFDB0381FEDD7E1F9D1F3
+:10D0800074DE686C16F7B77747F6EC723FC0CDA137
+:10D0900093CD18576D7E741895EF8A8EC53E407EED
+:10D0A000F7ACC74AC3B2B03E92F012F7D2D2D27AEE
+:10D0B0009083842C89DE7745D9BA6C473F7499896F
+:10D0C000E1FE1363F6E7884F7E6B213F754A7D2FA3
+:10D0D000DAEF29FF5DC9F0786857BEC844F17FF8E0
+:10D0E000A3FB18AE65C3CC583F6DA152CAB753B964
+:10D0F000EBC7373ECCA17D1D91CEEDECF4471D076B
+:10D1000049665FCBBDE9BEC25125BFCA962C5746C2
+:10D11000168CE3EBB3A9942F85D9A48871E8B7DD09
+:10D12000E4C8CC8A0DB4DBF5A348FB556F9F2DEF07
+:10D1300082FB7B7DB338BFECF4977729D7D8F58A8B
+:10D140007346C2F32EB33417F5C6AE4E3D0499E4D0
+:10D15000B6291AE3ACD314BF19F864FE1BEDF061D5
+:10D16000CF2C91F072CC321FCFC2B2E6DFC40EC614
+:10D1700071A9EFE51D743560BE185377A9AFD63F8E
+:10D180002E481B722B8E37C05FEB499F937F0CF0AC
+:10D1900088ACB52B65B01F6C37F8F5388E18C770A2
+:10D1A000E427F53C1E8B6B4AD7C615027EE8024584
+:10D1B000FE79BBAFF070307CFFAB5743E8DCD7574C
+:10D1C000F217E15AFF58958FE911FF73B885D6C55C
+:10D1D000919290087C63AC3BFE10BC57F1AC89F493
+:10D1E00066C5B3B18FF8B01EE8895B86C1DF7D3EAE
+:10D1F0008B9F07E8583E36970EEDAE958F4DA538BC
+:10D20000DF8EE4636AD6A60EE4A3AE0BF2D1F0671C
+:10D210004D74BEBAAC53ED5D18472C33DCCC1A60AC
+:10D220007C439EFD4517DC6799FEAC85E8EA0D0F4F
+:10D230003FCEE7D53309E7D56A7FB2B8BEF2D6173D
+:10D2400090BD100DE09D81FE16179B683D22763142
+:10D2500093DE1323ECBCBE134B5A0076795178BE93
+:10D2600084F4752BF200F512F25951E4843BF05C22
+:10D27000CBE1F929B40F762A97EF83CD78E8F90846
+:10D28000F43FBF9ACBCF77CFC47C3BB8CEFD37F706
+:10D29000BD6A947C3BFF5BFB5E4F6429F7865AF7BF
+:10D2A000BDF839D0DDF3FBE572BC30C982784AECB9
+:10D2B0004378B9DDCAA410C08B18C5D251FFA8FBB2
+:10D2C0005EE2AFB87E120D02ADD38FD5C994BFA078
+:10D2D00028C2CA9FFF8ADFDB139F2A61B40F16534F
+:10D2E0004BFB60E188578CDF0ACC89F27334C49E13
+:10D2F000F84036F25F08D173FA73333EFD7D2ED2CB
+:10D300006D748C2E9EA0F09FFAFE89FA5B687C27D4
+:10D310000466437B5FF4878CA1489F66D1F5D43DBA
+:10D32000A4374369FF9CD9BCBF1D00F0F47A58674D
+:10D3300033E49BF8C4E4EC403FD3173C9C8EF42EBE
+:10D34000FA438807CFDF4C5B18B20ACF6154EDE097
+:10D35000F7BCA72CFD8ECEE3B224632DC639BF5E89
+:10D3600018C2CFA96F1940FC33C5C0CFB9B0443340
+:10D37000C597AAC214B87B3EC19AFB4B66A4877AB4
+:10D38000FF660FEA15F8FE71151FE837A2DE55CFCC
+:10D39000D1B35A09E5BFCC20B47BCEEB6F59DC3F4B
+:10D3A0009D9268A7F3A2D58F59EC0B92389DC5FECC
+:10D3B000F85D46EBA26A836FF82AECD7C0A4AD36BD
+:10D3C0005C3FB454E07A9B6DC9A03C04354666349A
+:10D3D00047C17389EB33753C3552C9EDC44F46766E
+:10D3E000C81885786CF9B405F96341B8847191EA7D
+:10D3F000CE7617F51B6EB5713BA17C17C79E827C5C
+:10D40000E03747211F7C2A182C3CFF80C300F5E73A
+:10D4100019AF6FFDCEC2A5D9346FABCD30241EF944
+:10D42000EEC2F055F0DEED4C4A8EC77B624BA3EFA7
+:10D430009A80F5AF89A49740981ECB477FEF35B10E
+:10D440001FAE53A72CDD4DF39BB5A90FDE20605313
+:10D450005E3F40F66996C25F5EE5DC5A39C09B10BC
+:10D460008F8A5E7089AC96E2610A1E5BF1ABD4577D
+:10D470002F35113DAA175988CED5F57FA37EABC3B2
+:10D480005BBA203DAAB79A287F87F5263E8FF2FA2D
+:10D490001E830FC1B8CB4D9136011E55C9A3CD08CF
+:10D4A00057350A04ABDFAB5EFAD72E866CDE1F96CB
+:10D4B0001603DF670DF41B9B88F6ECCCABD18953C8
+:10D4C00034743FB3705B04EE3B1F0DF1A4E1395F90
+:10D4D000DF0321763C57A8C6D3CE2C4CE3F7816CF2
+:10D4E0002DE1B85F3D6D6E4A14DAB9C3368F19EB82
+:10D4F0000F3725E19139E6B0D90623EC30DE4CF048
+:10D5000019E51C09FD61FE4081F34DD5ABBBCDC9CA
+:10D51000F0BDDE3771FC9C7BEDE89E81880FE02337
+:10D520001BEA9FC49674B4C3D58696F404A4CFCBEB
+:10D5300002F90BB03E7560FE91D9C8577D411F2A94
+:10D540007C357BCBB679289FD56F9E1A8E783D3778
+:10D550009A99313E56ADCC1FD68FEF19A17DF5E6D5
+:10D56000B5C3197FFF3DE43BD5DE03BCD004F05EBC
+:10D570003387736EE2FA79AFD94B79EFF6DEC518CF
+:10D58000ED9F19D9506C0794E7F7004451B99F56A5
+:10D590001B378EE7DD93B5E7E766637D76A0BE2394
+:10D5A000BE197B9341A1B385ECD258C40BC0DEA554
+:10D5B0005B23902FCEBDB67BCF40948BCD828D69FF
+:10D5C000E54195C3441FAF07FC3D81F8DB7C613822
+:10D5D000E6A19879365C421AAA7852E54DC54B0D02
+:10D5E000E37850F1526354F0A4D43B153C54311FFE
+:10D5F000F5C7CEF6963660FF6FFE40FB6DE7A630AE
+:10D60000819F13E679D1D4F9B9A2F4FBFBF5377108
+:10D61000BE9FA4CCB3CAC6ED62550C93EAFB109F23
+:10D6200039CC6A7E4968726ED311DDF8572972D001
+:10D630004A6F9C078CD36BE0F70483F5D75C85AF0A
+:10D640008ED44FF4A05E9929433FB9280FB649B84C
+:10D65000CFC95E1715FD0D3653F3DDA2578E101F8F
+:10D6600082EE92A260CD62DA08E340FFEB6C0F8A93
+:10D67000171675F5D2BC378CB23103E89323823785
+:10D680007C3BDA838744D253EA381DF287440F4744
+:10D6900013974FE4178C0FB6EA85A0F1D62BE3B5AC
+:10D6A00018EC5E3C17CC1608747F4D5C702EFC1095
+:10D6B000B77714490CF47FCB7BB81FE9B814210964
+:10D6C00054633762BBD9972292D17E1F51E20E4735
+:10D6D000166D8B28D7D0E1A98EBEB3788084F42F45
+:10D6E0000A3BF430CAD1634ABBBD66FBD0F9A80F30
+:10D6F0002E4748785E6A6F949C8D7ED45E035BC231
+:10D70000A2381F1ABB04F007F242F8837AE9495B9A
+:10D71000402ED57103DD3C483768EFE07264A77D89
+:10D720008CD9317C5FF4DAF2D4CF4BFAA95E90D673
+:10D73000E506DAA9F7F21E55E64D32D225600F90C4
+:10D740003FD1DE59943C46C179506FEFDE3911F17B
+:10D7500057136635E0122EB83E180EACA76A8DE856
+:10D76000E7B385717BB4F7D28E86C874FFCC172FD0
+:10D77000B275408FFA073EE0E77977F07B5BAA9DB0
+:10D7800086BFE5ADFC07EF55E65E188EFAF5C502DB
+:10D790000BDD6BEADC2B99BE739A35990BD1FE9F9A
+:10D7A0006C191E2105D627B75CF28891E42F24E975
+:10D7B000D6075567DF2379AE662D741F7BCAD20367
+:10D7C000A30720BD5F32D1F981698D4964E74EAD71
+:10D7D0009FDA0FE73B65511AC13336DCCFE1A53C38
+:10D7E000FFE19445792FA0FF7534C4311CF9D9B7F6
+:10D7F00042B0E1FA6AD086BC47EE85FA41E13D3B92
+:10D80000E3B8BF5A7F7434D2FDABF922E927C7FAD7
+:10D8100027EFC27AC776116F8CC17AC6F608E63553
+:10D8200065C6481BFA05EAF9C20613D7B76715BDE6
+:10D83000704CD113C714FE2B6A6848477FC9B716CE
+:10D84000EC11EE7B9B7D1574BE5BB0D9D701BF9CFC
+:10D8500014648299CD965C5F80F759D6507E9CF314
+:10D8600069161BFAC9F759981DFDDAFB76F5E88BA6
+:10D870004B0587B2AE1A1DCDBFABE24BFDFE19E5DD
+:10D88000BB4C5C5E41FB0ED15232EAB7BDCAB9F166
+:10D89000A3CA784F2D7CE92EF40B4E6D4C8B621A87
+:10D8A000BC9F52F234CD003DB8B99DF59EFF2635A0
+:10D8B000EEE0A6EF542AF1C07DA6C6EE98F733F845
+:10D8C0007ED789B52156CCCF1B7CCFEB8489DB8FEB
+:10D8D00036F7BDB6EBE1E03CB7C1E3695DCF04DFED
+:10D8E000FFEF15D6AE1FAFCA59F0FB6DEE93A75EE2
+:10D8F000DFF92ACC4B86F7BD77DFC4E8BDA1A1FFD5
+:10D900007A03F57545A3C586F7EF8F8548B41E9257
+:10D91000F398B401ED8C558AC4F5FCB17DFDE8FCAB
+:10D920005FC5978CE4AA628BE8C654C5EFADC87892
+:10D930007C30C0F76F31D9F1FD532B57DCC5C54C96
+:10D940009F67219F71F99C0EEB248F2DB02E0A5EEC
+:10D950002FCD5CB589EE11FE5CEB25358E148CEF76
+:10D96000825EFA7C0BC1F7E77601DBE4F76D8BEFA3
+:10D97000B3752E5A177D5B57496541D3DAA2040966
+:10D98000EF531C796C10CA4D7824C543CED6D5D23E
+:10D9900026DEB7DBFB5DC1FBA16F8745DA505F7CFC
+:10D9A0005B375FB95CA0F089C297B76C6916131832
+:10D9B000B5DF3108DAEF0C8BA4BB2EA98EFC48B47E
+:10D9C000F32A5D83EF37ABF33BFD10A7AB3ADED311
+:10D9D0001BA746A0DFD9BC3A7A4701F4278746DA6D
+:10D9E000D0DF9EAE9C7F39BE8AEB9B93D6C817468C
+:10D9F000E1F99935E3BBE0BAEE7E93CF6C877EED1B
+:10DA0000EF9444E07AFF1BA33702EF1B7F03ED3D49
+:10DA100068278C6E11F5DCC06246FB78033D462614
+:10DA200025D19639F145C159A31BE97AC67369F727
+:10DA300055E4A3B3068A770166765F85F6F6F09E15
+:10DA40001427BCFF2DBEDE64FFEAC4EB83EE2D3E3F
+:10DA5000D18BEBA5136BDE1843EBF3F5261B8EF38E
+:10DA6000DBF57FED82E77066327EBEFEE44681E63E
+:10DA70003113F8312409F5038F83CE04BD6F15DA15
+:10DA8000F261D1C67AE2C399C08716F4D31C3C1F59
+:10DA9000F34CCCC72CB136F93F3A2B7C370BF80E40
+:10DAA000EFEFFEDC793F96F50A3EB7CAF950A5BB09
+:10DAB0008A1795FE013E64BAFC82514D7D0A1358C7
+:10DAC000401FA8F73B98D1BB1CEF69CC13C31B3197
+:10DAD0005FD57E63ED1F286F8B6C641BC89EB34CB3
+:10DAE000CC97374FBCC98EF1C006736D6B5E17AC17
+:10DAF0000FCEEB2286F1F74B303F31CC372C3B89F0
+:10DB0000BE37CE661F86E836C578292E2016191C2A
+:10DB1000742FAFC142EBE6603DF48A42DF3BD07721
+:10DB200040BFA7173FAFADDEFB534B30343D90DF16
+:10DB30004B42A32E4BD064FB2B9FDF89FBB4258384
+:10DB4000A27E9102DF6FEE75E44EBCB751D22F6A10
+:10DB50006B32C0BB5FF93BAFBF392ACF847E80F008
+:10DB6000F59D43D16FECE578B397E63B6ABFF0FCD7
+:10DB70002D7CFE79A2EB9D5E7CDFB402E97D5E88A0
+:10DB8000E0F9DE527D140755DFFB586087DF16028F
+:10DB9000B0D7C41231AFC1DE5E5C9F7654C6643B21
+:10DBA000F6F0EFEB9F2385BEC375A6B2FF63B04AC4
+:10DBB00066F4FF9C76B39DE757644E2BF8556315CA
+:10DBC000FE2DB75E194AF6B796D92D98C06489FE26
+:10DBD0003E5656E0DEDE9A1BB9B7C7649E87AF415A
+:10DBE000C9C3D7D13D4A61C7073FA07F197C7FAA2F
+:10DBF000DF5F5ADE443E19037C85F622B785C36396
+:10DC0000153EA9DE369AF23DCFF9D8E4463F61864B
+:10DC1000E28FA5BA3A3109DA5D06F945BD70768C16
+:10DC2000271DF5C7893AD6989A86F12A970FE9B247
+:10DC300037E903CA8B76624D4304FA3DE7603D3114
+:10DC40000ABAA852FC7B7645F4DC867E7052D6BABE
+:10DC5000651A7EFBA117B7FF67933C89B8BE919305
+:10DC60002C3C5FE395DD94E7B93879441EC691F604
+:10DC7000D76D6747D302EF75741F65A06108CBD6D7
+:10DC8000EC4B8E31B67F4EE3A49A4F733DB7DF164F
+:10DC90006323E5D10252D6D613ECA4B8521CF22865
+:10DCA000C687A507095E3C83D9E81E6B609F8EEE90
+:10DCB00083AAF477D8AF0EC5766380FEA86F0C56A2
+:10DCC0009F116167313F9F920584437DA2D27F9867
+:10DCD000F8C863488739CA3DAE39422D874D563A58
+:10DCE000E71AAC1F31AE59467A53DE5380FE18E86E
+:10DCF00049CAABA0E84509FE477991F2D79AA9D95C
+:10DD0000B5F322ED29F80FF4634EB63E8FB84A27DB
+:10DD1000D5BFEA884EAA9E047AF5BF117AA979CABE
+:10DD2000E63CCBE39D739E9D1AD797F0061287FEC3
+:10DD300050DC1F29AE325D99035B134D7C6C1AE2F7
+:10DD40009450DF8EDE9EC024783463BB40E75B478F
+:10DD50006D8F2638C21FCFF32A29F67EF48B5D879C
+:10DD6000607CF2D40B5FCCC5BCF7A37EC3287E6C6D
+:10DD7000080DA37C13E210258F8318F63EDE63BDE9
+:10DD800028196BD15E39599BFC0106A2FF5E7E4EBD
+:10DD900016567932A713BFF737671FB7F3730AF91F
+:10DDA000BEE0457C03DA5F2C15294FD3D3A139E4BB
+:10DDB000BF35DC69A2FB114C767C82EBAA090A3FD5
+:10DDC00058E26061A9A1578804F2AAA1CFA3218FCC
+:10DDD000BDEF82FEBDB0EE12BA811F9B19A5AB3715
+:10DDE000CA21DF60FE58539C6873C3F8C3EDDD742D
+:10DDF000FD39C52A13C653988BFBD12A7F31F1AC6C
+:10DE000091EECD0FE6F92BEE9CA0BF27691A7C613D
+:10DE100028D99BC17AFFDB798DBC4DF3557ECA6250
+:10DE2000594A5E7AB2FF170FF2FB211273AE52E528
+:10DE300005F53F78374F237EEEDA6B626E89F0F797
+:10DE40001AD65F942D368C07B4FAE1A9F05E0C1A4D
+:10DE5000492BF139E605D5CE13F3826AF182794177
+:10DE6000B530E605D5B6C7BCA0DA7ACC0BAAADC7EB
+:10DE7000BCA05A18F3826ADB635E502D8C7941B5E1
+:10DE8000ED312FA816C6BCA0DAF69817545B8F792F
+:10DE900041B5F59817540B635E506D7BCC0BAAAD62
+:10DEA000C7BCA0DA7ACC0BAA85312FA8B63DE6050F
+:10DEB000D5D6635E506D3DE605D5C2981754DB1E7E
+:10DEC000F3826A61CC0BAA6D8F7941B530E605D536
+:10DED000B6C7BCA0DA7ACC03AAADC7BC9F5A18F368
+:10DEE0007E6ADBB7B0856968C7DE4A72EDCD8EC544
+:10DEF0007DA793C4CF87EE037E4639DC3BDE46F92F
+:10DF00000B6F709DD892ADAC5B14FEBDCCC226E108
+:10DF100039F48EDE57F9F3257C278FECC112E25FCE
+:10DF200016DE88FEDCA34607DD87929BF8FD44667B
+:10DF3000E47EC03C51F17F94BC10F34489FC00CCDA
+:10DF40001D6CD48CA7B3C3CA8C1A3C4417DB747005
+:10DF5000AC334ED7BEEB0449571FEFCAD4D5275474
+:10DF6000DA75708FDA7C5DFB9EF31D3A38492ED648
+:10DF7000B54F59E2D4C1698D1374ED3356B974F5B8
+:10DF800059EE4A5D7DAF8DB53AB877D37C5DFB9B8A
+:10DF9000B7CBBAFA3E9E25BAFA7E7B1B75705ECB74
+:10DFA0002A5DFB0187DCBAFA02EF465DFDA0934DC6
+:10DFB0003AF816DF765DFBDBFC1E1D5CC8F6E9DA7D
+:10DFC00017593FD6C1C36C9FE9DADF1E7744573F2C
+:10DFD000423AA5ABAF3AC3FD7BD600EB038C538628
+:10DFE000F1FC1AB33DAC09FD8B91991774ED4D31DD
+:10DFF000B05E00FEA9067D887EDFF79D12291F33E3
+:10E00000AB8DB0E3BD6F7948ED1FB4F7BC47DB7F44
+:10E01000D07DFFE9D0084F08AD2FAC646F6FE9CD1C
+:10E02000EF9BB5E61351EFB3331F8B8BA190900F8D
+:10E03000FD23017F6109E00807CF0B0D7E10F94F2A
+:10E0400036F08BD0DF6C5D17199292D02E8706FCCC
+:10E05000E2EE5735795EAEE5178FC46FE7519E5EED
+:10E06000476F2867366D1A8EEBAC194C5E8CFB89B6
+:10E070006A9EC5FD21FAF8965A8EB0027E35DFDB26
+:10E0800017D2D8BDEF4FC8FB08EB596ADFDAAF12E1
+:10E09000FF1260B27334FD3F06EB3F23C875631D6A
+:10E0A000C81FF8434FD4D9085E591747F05375126B
+:10E0B00095ABEA32A97CA6CE4EF56BEAF2097EAEAC
+:10E0C000CE41B0BBAE98CA75754E7ABEBE6E02C167
+:10E0D0002FD4B9A8DC585749E5CB75B554FF6ADD94
+:10E0E0007C825FAF93A96CAA5B42CF37D73512BC55
+:10E0F000A56E15C16FD6B9A9DC5EB791CA3FD535FB
+:10E1000051FD0EF0DF10DE59E721D853B797E077C5
+:10E11000EB5A087EAFEE10C17BEABC54EEAD3B4932
+:10E12000E59FEB7C54FF973A3FC167957D8879BDA9
+:10E1300005DD7D3C1536B263DCDFC3BC1598872155
+:10E14000DFF4ED4FE5C70DA6C369A57FD310709727
+:10E15000308EDC2D7D5D83665DD1D09BC72DEB0DB0
+:10E160003C7F4B7D37666B20BFDDC1F8392DEEB7A4
+:10E170004FC77F49F034A66E0FAE372A6A799EF2F8
+:10E180003CE4C74CE2C7BFDCD03A4D59176C4E7126
+:10E190003E81FCC8C2DC9F26E506EED11F4871FD1A
+:10E1A0000E9F5FACBD7F0FB69E6EB3A7E347465B85
+:10E1B0003CB198FFCBB74FB4AF933AFE5E8D72FF80
+:10E1C000A1C3FA9DA7BAA3BD2AFE51A4B8FE7E53EF
+:10E1D000F804DCE77F51C1C78BBD0DBAF2EE54E7FE
+:10E1E0000BBD717F3FADF6850785C0FDFDB1B8C49D
+:10E1F00007F92E6112E5C119CF1CEFA30B7E27385A
+:10E200008208DFCD642A4F24BBFE88F3B9071620AD
+:10E2100008BB065A12DB9B4FF078DE52C6F39632EB
+:10E220000EB59C93EADC8EFD1D4B73E8C6F3A292FB
+:10E230005F680CF33D87E3FAC73B178E0B29017C1F
+:10E24000B7C653582DE5C928633C9EF228E6C58819
+:10E2500009E4C550D70F65FBF8EF1CD11FDACF7961
+:10E2600049B4BE0DCE9BB1B87037CF8301EB31BC42
+:10E27000FF5BF6C02F48FFE2EF41E1BDDD799D0E67
+:10E28000539E19EF0CE0D504CAABC1F3DEB8008190
+:10E2900009945783EA859BE0FFF1382E6BA691C65F
+:10E2A000D789F29D3C1DBA9FF2D2604CC1D219F3BE
+:10E2B0001E27D13CF73B2F70BF3BC647F75337A70C
+:10E2C000B8BEEACDE3E44FF5C33811F2137EC7E6DA
+:10E2D000A6F36BC04F660150343D06F8A91D7F437D
+:10E2E000E59BD9CA3D1CF539F0E309C4F7B76F0DBA
+:10E2F000C844BEA9D9592021BE1B0CFC3E9DFC6719
+:10E30000655F50F93D0431327B2DDD3B40671CE9F0
+:10E310005B104EF70E9A45367F533BFAD59AC3E908
+:10E32000BC3F8EE7936C08DA9F147238DD05A5DDDB
+:10E33000E877F7511EB2D97B79BC9AE57AB39DEDA7
+:10E340009CCBAA99FF9BA75235F3A8D97E849FE75F
+:10E3500062DE6CED392E49E957E53FD11CEE5A1BC0
+:10E36000A61D5FAB1C5872F2480E8EE3BDEE31164F
+:10E3700029F26E817E1FEC5BCC2FE3FA838DCE03F6
+:10E38000AAE702A7312795D3C17222DF3BE51574B6
+:10E390007F7E266BA2E7B3F3A726225CC37C43E310
+:10E3A000707DB4A4FE7D0C078D6F5C312C1EE635AC
+:10E3B000CE3DE57D2C4BD60BC76589E4280EBFEF1B
+:10E3C000156A177583EFDDFB6AE1228C5B8F1139CB
+:10E3D0001DD8879C0E65C0CF6254DBF981DCF4CC7C
+:10E3E0008925B9A1F1AB7253B68039F0FC817A3F2F
+:10E3F000A4558EF267FD3D01F770C09F447EADD9F4
+:10E400006989A2F529E699417DA5C8CF2223F72F76
+:10E41000654C6D4AFA93FB1B268792CF8B717F6404
+:10E4200096CCD763A74D5CDE4E7F15EE46FE9ED799
+:10E43000E9F544920F932A1F3F4EA2F33D0CFC8F47
+:10E440005BDBFA1FAD7966BA33F23758A22BAE6F99
+:10E450004AC09E9F36B8FB47F0BCFC0EC4D79E381E
+:10E46000BE7E9E857968B0BEB353C278E9E9582B69
+:10E47000DD170ACE73C6989DE66752E607239B8098
+:10E48000FEB44589AB3504CDF7FB90449AAF54C830
+:10E490009A183A16469B3C15E5FE416E27E675FA3A
+:10E4A000B50BBFEF0D61366110CD87E2B1B2813996
+:10E4B0001B787C96E637DF68B5E1B99CC55344AF5D
+:10E4C000407602C689F1BC18AB9DE75555F36F073E
+:10E4D0008FD7A11F9F3591E1FC1C22F3850CE2E34D
+:10E4E000C5F1C9400FA20FC05334E3837EDD94FF12
+:10E4F0002754B2A11FB6F75F0FF2F8723DF71F6104
+:10E50000FC1B893EF130FE846B8FDF842C0AE39F75
+:10E5100093C3F55403EE208A68673B93FE2D09717F
+:10E520003E807C98EA5AD67D0EC6350A2C768CDF62
+:10E53000B12B0DDD514F853189F26A8D71F0BC5AD6
+:10E54000D0DD42E48712CC5B67233FE0AC360F1B83
+:10E550000B8AAF015928BE3A0EE36BFC2ED17B1813
+:10E560009F1DAF9C6FCE625FAAF8A3F89A88E3A3C1
+:10E5700078B58BC66941CA421982711EA2839BE697
+:10E5800011CA3C4A3CBB85FC83150A1F0E3AC4F9EC
+:10E59000705018D7773B8F30379EFB6AFEE1AEA2F2
+:10E5A00070842F18494F019E281FE0DB7FE571A979
+:10E5B0009DE78E27E03E4CFD0F7B12D04FDC697249
+:10E5C000893530EE9D0516DB027B20AEB1E3501895
+:10E5D0008FEB2871BE5B9479EE602D0D35509F1F37
+:10E5E0002F328C03E61DF484A23C0F54E2B2C1FA30
+:10E5F00070F025B3EE772D4C363D9CCF34701286EB
+:10E60000C8827EFFF306D7B9AFE574F0BB9F2763DE
+:10E61000AE6B3F147FCB87CE27E438DFCC21BB36EF
+:10E620004E54F02E20BE400F34239D9FA936D3EFC9
+:10E630001A34579BE3BD9AF135CEF847029D73FE1D
+:10E64000D73FC86EEDCA53F3E33485E073B31C4E75
+:10E6500071B767AE1828EEB6BAF26B5A9F34E6333C
+:10E66000FA1DB1C62BE5E4075C2E66B889C4EA6FD3
+:10E67000FD3F95083F7E8B95BE173CFE6DE0CF7B3E
+:10E6800080505BC19FC7D20DFEBC2703FDF4382A22
+:10E69000D7803F8FE533E0CF63FD2AF0E7117E0A94
+:10E6A000FC792C57823F8FCF9F007F1EE177C09F60
+:10E6B00047F86DF0E7117E0BFC792C1BAF7C5248BC
+:10E6C000E39ACBE8DEFE82D088A5E8677493C3C9DD
+:10E6D000DFF8C8D1B793576367F3BF34E8E8DCFFCE
+:10E6E0006027DDEF9D24C95141BF47D32DE8F76A6C
+:10E6F000F4BF6F9350A9FF7D9B7857DFA0DFC3194C
+:10E7000018F47B3943827E4F47FFFB36B75E1AA76A
+:10E71000AB1F7C56FFFB36038F95EBE0C7957C99CA
+:10E720002A1DD3A5D742902F56578E8B64EDF8172C
+:10E730006A89EB2B8F667FF5C987C409EDC59123E4
+:10E740006FE6F6FEDDAF2CFBD6033E77B14827C659
+:10E75000DD77390CA4979E59154671588B77E029BF
+:10E76000E49F5D0E2621FF3C736548271C4F2190D6
+:10E77000119F275472BDD0ED6689F839A1D227E2E6
+:10E780007DD1DBAEF8ECC88F4F46F0DFD9827EDD5D
+:10E790000BA0BF7747F7CFC238CE3361C0CF286F09
+:10E7A0001E5F682AC091570D0CF523D84ACAF32F73
+:10E7B000FF3E4C398F7A95EEC345A24E07BDB4ABF0
+:10E7C000927F3FDD7B2554EB0F3DFEE3B5F0C28821
+:10E7D000AF3AACBF6366328E378077508D50A6B3A8
+:10E7E0004AF618E2A38ACB4F63A581E4E932C81345
+:10E7F000E207664D74617838215EFB3DAB9E0E5595
+:10E80000C94B719ECFAC34D26ED930F1D57D37C3B0
+:10E810002BAB0F8AB4CD2ED97CA1EDF977EAB8578E
+:10E820003BF8FCA2ECCC80762E0AF0E9A6FD6C7BCE
+:10E83000BDF6F7AC7EAFC8E7EFF0FBF0DED30A3FE2
+:10E84000AC54E47398B866443A8E239FEB6BA0A750
+:10E8500080F7B12E4F63F43BA2BF2B4DEED45E9EEA
+:10E86000EF95CA389E53E6B54691FB67B05FBCC7CB
+:10E870002E9615623FAB9D8CF4F86AC7D7F518B792
+:10E88000BB5CCAFBEDF9885740FC76AFF509D87F31
+:10E890008FB91E2ADDCA38BB55B650BDDA9F6477E2
+:10E8A000737EAFFA9AED85F9E2215B91ECC559CA06
+:10E8B0008FBADA68646887519F217CD96AC43312A1
+:10E8C000ACDB8C630CEF33378619699F62F5ECD3B0
+:10E8D00004AFB0713842AECDC6F3176F29F38990FB
+:10E8E0006582DD41F3499726476A7FCFF55A7AF072
+:10E8F0002D93CB7011C631E06F22FD7E4747EFA903
+:10E9000076F65AFAEA4FF88F78B20B0FDD8CEB6788
+:10E91000D94976415DB76D1DC5D76D2B42277D88DE
+:10E92000EBFE52858F9E0E1DF33ED61F18C17F074A
+:10E93000A779C4ED3DB47A72BB32EE6D0ADE0B8E60
+:10E9400039BE9A0BEF8F745A189EFB18293B7AFC3C
+:10E9500002E15122E5351FC01A1BF05CC5C13C55D0
+:10E960002E9CA1287FEF8E9ACA0EE1778AB99DDF8F
+:10E970005A3C9E9E4BCC39B237BCFF498B91FC1A56
+:10E9800078FE9372B94F19CF070A1EDF57E8B05BC4
+:10E99000A14333DA132877A13D217B6157EC05B7FA
+:10E9A00027DBD09E64201DB83D69417B9281FB6FBF
+:10E9B00013A8DD5FD09E40993BA288F6232F232326
+:10E9C000913D99CD16035C08E317DBA1D71DA9A2E1
+:10E9D0008E3EC5DD4375F4191E13AD83878625E889
+:10E9E000E021C6141DECB87253903DE81B640FF48F
+:10E9F000F624FFCB21BAF6FD0FDEA1AB2F718CD729
+:10EA0000D58FCD9FA8AB1F6D9FAAAB9759635104BB
+:10EA1000CC37EF4B467E685EA73522ADAB957D3493
+:10EA2000D5DF027A923F56F05791E456C5471E6BE8
+:10EA3000DDCF33D07E9ECC243CDF495B96C9BA7AC9
+:10EA4000F2A30E9A9C09780EB1BE04F80FCF231ED4
+:10EA5000AC18C5683F1EF818E42ACF79E24BCA3BD0
+:10EA60002A96F5237FE99251B7AF5610B43F36206E
+:10EA70005BBF7F96778DFD33EFCDCAFE431BBFACE6
+:10EA8000FDDF450AF6CB40AE441CF7D3A1937623B5
+:10EA9000DF7CF819B757CD9F3DD51D9F7F824DA1D3
+:10EAA0009F7DBD9FEE8E7CBFAF553E5CA15ABF6B74
+:10EAB0006B26FF1D9A370F266FC7F546AE4920FD1E
+:10EAC0009F9BF5249D47BC7CD040BFD3995E5C13CF
+:10EAD0008A78D97A685D98FE1E95464F909FAED190
+:10EAE0001322FAF751FA7A6342004EE6C4C1F6FFE8
+:10EAF0001710600A2E008000000000001F8B080025
+:10EB000000000000000BED7D0B7C14D5BDF0D99DFD
+:10EB10007D259BC08604DD400293F030228F0D7965
+:10EB20006D42122621D0A03C36801004E384A0D090
+:10EB3000566DEA137B6933493089014B546AC1FA37
+:10EB400058B1DAC7E7FD9A5A0950B15D9E55A1B296
+:10EB500048B051515779685BDA0F155AEFFDF17DD6
+:10EB60007EFFFFFF9C4976864D88BD7DD97B939FB4
+:10EB70004ECECC9933E7FCDFAF73608CB1CF24F875
+:10EB80001F9BC0422E463FBC3DD5D42E62A1ACE8AF
+:10EB900076B9A97DB5A9FF0253FB3A53FF1586E765
+:10EBA000AF642D1CAA26C0DFF833FDE2EBB606C623
+:10EBB0004257F4F5CBB30524DFC48BFBE5775BFB51
+:10EBC000C685FF768F5B653D9FC25857B714746644
+:10EBD000C075EC2AA6E5C238DDD620B3D0D5CAE090
+:10EBE000F92B3DBCED64C10D53E1F9B66E9BAF5DF1
+:10EBF00066EC45FCAE93B1F1811B860612192BB170
+:10EC000085637EB7F49CF1BBAFF42C18CA62F4D3D1
+:10EC1000AFBF10E3BED0E0A275ED6CF0505B7F2E6D
+:10EC2000FDDF7347E7E3BCB3241FDC86F997273386
+:10EC300058F72F2FAC74E3B8305FC6463036A33395
+:10EC4000ADBA712C63320B2658A1FFB62C89B5C31F
+:10EC50003A738FF1EFE7DA95644F0CB8326635C23C
+:10EC6000FFA2F1E007E174C11AC4F1F68C5BF2D0A7
+:10EC70005418FF60B7C4703E0E75B53B3009DA3DDD
+:10EC80007C5EFAB8D33FB5F6E119FE2B3E136F80D8
+:10EC90004BD1C96186E7B9572E1C8AEF3BE4F9C90D
+:10ECA00008DF4BCD93B178131D0D33B54718FA8F9C
+:10ECB00097016F93FAC7C37681876D8807B86E8F07
+:10ECC000F3550762E06DDB78E7EA60D43A1B7C40DD
+:10ECD0002C7978B5D235F74AC91702F89CEFB6FA05
+:10ECE0001078059E7AA93E06DCFDC78D7492DF1D63
+:10ECF0006F800793960FC8076B8E37B6EE8BEAFFCF
+:10ED00000D5F62CA6937FC51C00A68FD9778FFCF72
+:10ED10000D5AEB3E3BD031634A27AC93552E64AC81
+:10ED2000B0FFFE8C35D1FA7438B2CA64C65207837C
+:10ED3000A70E7AEF227CF5F37EDF381A63C3019EBB
+:10ED4000005E9C57EBE4C0C33E1C275225E1F71F31
+:10ED500070DF2A45607DDF75DFBA17E9F3D07B0EDF
+:10ED600019F97AF77B5D6978FF60F6F634A4FB83C6
+:10ED7000F04E18DACC065883B643BBDE8DF4F54A64
+:10ED8000F76DC43F32AB3F3889CB015F3B74DB9EEC
+:10ED9000C5E9B0BF79BD24E4CF01C1AFFB04BFEE2C
+:10EDA00069F0523BD420D3F5170D59747F57838FE8
+:10EDB000DA3F6FF0537B478342EDAE864ABA1E6955
+:10EDC00008D0FDC30DD5D4FE75834AD76D59B7570A
+:10EDD000A03C3A9F0600807535B9E7D962E173B669
+:10EDE0002C19E8E64B5EB781AE667A920DED19AE4E
+:10EDF0009186FE656C8CE1F9F44F27189E979C9DD7
+:10EE00006A684FFBB0C8D0BF30526E6817F45C6DB3
+:10EE1000E8BFA062A1E179A07899717E5202C997FA
+:10EE20009D6719C9E579B97586E73BF10F94C31F52
+:10EE3000B2A09681705938A03CD5E5F45E819FDD83
+:10EE4000023FBF14F8E942F8139F571AE09D7FBCB8
+:10EE5000F39A29C0AFBF6A584DCF1D5943CF49F02F
+:10EE6000DDED67E365947BFB1BEAA9DFC1B71F24D7
+:10EE7000BAD929E671D0CECE4929D8B6C84D968BDD
+:10EE8000E793D763E4F3F1953790BCDCD9DDE44632
+:10EE90003ADB115930287DA7F7FBD5B90533902E01
+:10EEA000FCDDA0A3322EADF7747D75A9F1F57EA827
+:10EEB0004F63E909F3B857475489C13AB6F7D43FCD
+:10EEC0009488EDD0972519DAF93DEA0CC4D7AE2C19
+:10EED0008B47B250BF190ACEFBE46DD7E0FD1DC7CA
+:10EEE0006D569CF72190FFB88E9DA06F9DA87FCF97
+:10EEF0006D754F06F8BFD8F3E03593A19F76C6E64F
+:10EF00001BC72E9EC7A86C89E4C2B6894EAB650AA2
+:10EF10005C8FDB5808E5974D25787645B6D215F518
+:10EF20001FBF5F4FF8BA32DB43EF6D3FF95C32B67B
+:10EF3000ADAC9EE4C08BC7AD95C118EBBD12BF034D
+:10EF4000B223EF4283DB03FD0F1C5FE146B9B2A39E
+:10EF5000878F9FB75673239C0E46B626E0FD9D59BA
+:10EF60003FA371774FE276C5CEE356A2E79D13AF7C
+:10EF7000D8E0CBA575FA1076703F01DBDB7A6CD454
+:10EF80009699CAC2292877A460BB05D7B382BD066B
+:10EF9000CFCFFBA420F27D1ED31CC0A26CDBFF6B85
+:10EFA000599CCDC1CF6C9731760B7F994D3B6BD47B
+:10EFB000B3453D463DE2885C383A1FC6EB3AC3E5AF
+:10EFC000DB8C4F8D7AF7E01B999B028897337C3E50
+:10EFD0003B8E2F58548572E77989DA8D93563DFA26
+:10EFE000757CBECDED73C2F7BE9CFB644B327F7D5A
+:10EFF000C85C9847B19853DE19E33C0E5E59C73E92
+:10F00000C6759EB4D13AB61DE7F6D5F92CBEAE9DB5
+:10F01000BE3AF66DE42F617FCD78FBFBD74C4A41B9
+:10F02000BAB0925DF182EF67C939289F3C9281EEB8
+:10F03000004E4437E7BB198D031245BA15C629F0B7
+:10F040003B3DED1EE4C70EA29F836FDB7C4DF8585D
+:10F050003AB4F736E89F375262B8A22F074DF2F262
+:10F06000876E43FB16D9282F9DAC6A40BB61DA59E5
+:10F070008751BE7EEA308C57C0A29E133EA39E6786
+:10F08000FC0576895D5D8676090B2F1A94BE66AC09
+:10F090009EE4C50EC67CED404085574A0AC1EFB8D4
+:10F0A0008BE057F0DDAA698CF4B43A0DF981883110
+:10F0B0004A2F5FD24EF1682C255F7C0AE980D94E39
+:10F0C00047A07F1B10C967A8BB851E378FDB9FBE7B
+:10F0D0007FC03D84E47D718585F8E7BBEE5749BF6D
+:10F0E000779DE2FA1D7F224077D7E21FA8EF4F39C4
+:10F0F000881E5E986D2139A2DB0B0B996247BE9981
+:10F10000E73F67BB1FE836E0AA99740B5C5F78A302
+:10F110006B24F2EF0B6817907CE8207E7668895AA2
+:10F12000328CB3ABC7497CB813F8CA85DFDDE52460
+:10F13000FA043E5D8F76C2AE30E7A3AEB3566EE7FB
+:10F14000ED72139FECFE8383E6DDB5D6CDFD8B33E8
+:10F150000E05EDF09D6B13E9FDF17262C88676FC39
+:10F160001A3E7E8FC0EBEB02AF07859E7A19F594AD
+:10F1700013F5904CD7FDC28ED88B768413F5995F2A
+:10F18000E833AEC79E3FFBDC5B48FFE777C591BD28
+:10F19000399E6575E2BC762538689E66382F558D98
+:10F1A000F4BFA4DA682FCC9968A4FFABC78E34B43F
+:10F1B0002BD3C618DE9F957295E17945428EE17991
+:10F1C000B96D9AA1AD5C30DA0BF3FDD718E9498926
+:10F1D000B21732F1FF467FF1DA687F11E5C8D90531
+:10F1E00064AFEDEC117AF964E65075E2C5FCB3F357
+:10F1F00024D79FDB8F7F9CA8C6B01F3E14FD7E27BF
+:10F20000F07146E0E3B7A39493D94097E74F7EECC3
+:10F2100000A5D12F1DEBEFEBEF7D183C31245AAF49
+:10F22000A74B32D1B7DEFE43D75BE3F1F960F902B9
+:10F23000F4585B04F07CB794D8D10EAFB4DAEA9FEF
+:10F24000C0B6A6D9D8D3B9048E2C1B3D9FE0437B12
+:10F25000A539B1FE07F87C5BA3D3B33505F9E85BAC
+:10F260003FC1F61A6005275CFF1C372AC880D51CF1
+:10F2700053B9DFF28C3D30D2877AD31258760BF433
+:10F28000D7B6387C4FCB17CF2761AA4567F61DA8A4
+:10F290008724C1F7FF695113A6C27DE5590BF163BD
+:10F2A0001C38A2380F270B8490FED96A6519F20723
+:10F2B000B302FFC0F51B39EA30ECCF14267B601C8B
+:10F2C0001215F03D4BF8C07F58605E7656AFE138BE
+:10F2D000CED52061809F1FC85653A9BF6D018DFFF9
+:10F2E000FC5CC6DA492106A89D7B17F3B427C1FC54
+:10F2F000986AFD18DACBC0CFC7EF5BDD37931E7A73
+:10F30000EBB7D6A014C35EEA85F3CDF633119DCEDC
+:10F3100032FBEEEF1078ED1274B12323B02C965F20
+:10F320003815E182F6C5BBF324A4AF5CD71005ED18
+:10F330000A58A05405F27DC7FB57BB6B63BC37333B
+:10F34000B776EAD428BAC80D774AB509080A4DC27B
+:10F35000756D83BF715D3FEFB68610BFE7131C2448
+:10F36000B7FB5B4761C4A8870B7A8C7E3763CB3DC4
+:10F37000A7AF427877583EBB2A9ABE94F5D1F4F5F0
+:10F38000FCC5F44570BEFB6816C1B5D9C2E94B0394
+:10F39000FAC2E75A793DD197666581E65CA2377A71
+:10F3A0007F8DCDE57182845C353593E8A62B71CED7
+:10F3B0005B2199BE376601F97135C28FAB2139FFE8
+:10F3C000F23190F331ECE8DDC7168F8C00FCB68D7E
+:10F3D0005B3212F9BC0B15C0089C7EFE52B42F7B29
+:10F3E000DB802EB20367320C55C1F3DCA50AF69F11
+:10F3F000ADB7F378FF32DEFFA6A99BB668F8FC7ABA
+:10F40000F19C2DE4FDF5B656B0B40CFBDBADD47E1B
+:10F410005BF47FC8A7AC42BC3D90ADACC66B361A5E
+:10F420002B703D3D45F90AD2E9AAA98CD67BD714A9
+:10F43000E5E6E8F6CF262BB746B7B7F5FAA71DC223
+:10F440003FBD85ECD2977B16905E9259E01AD43B73
+:10F450002F87791C6ADBD881FD9F5F097B7EBFF017
+:10F460007FF6A23C223F88FB3FBF147AE545A157B7
+:10F470005E107A65A7D02BDB857FAAFB47AFA27F02
+:10F480000AD743C23F7D05FD25E8973BEE04D91519
+:10F49000E73F65C4BC4DEE5F48B1E46A659AD17E32
+:10F4A0009B9562B4B72A128CFAA6DC66D437CA855B
+:10F4B0004C43BBF4DC0443BBF88CD13F2D3A596478
+:10F4C00068FB8F971BDAF9DD579BF4CF42C3F355E6
+:10F4D0005365C2E35C9FD14FBD26ABCED0AF0F6F5B
+:10F4E00001613F3C968076DCB6B175026FDC5ED080
+:10F4F000F1D6F54F83B7BDE49F9D3FCB445CE171EE
+:10F500002996FFF9AF8FB74BF05B02B7F32EC56FAB
+:10F5100007847ED827F4C31EA1FF43C28EFB8588D3
+:10F5200007ED42BC511C88C7837620DEA2E211CFD2
+:10F5300023DE9CFDE3AD79EC439CDF4EEA78BB35DE
+:10F5400026DEBEE435DA77333D46FB6E86CB88B7E0
+:10F5500032668C074DFFD488B792B3C678D0B40F0B
+:10F560008D782B8C18E341053D46FB2E2F6C8C07C4
+:10F5700099F10676404ACE20F0067E924274EB1353
+:10F580007A3FB890F451CB5CAE1F810FC9FE7EE686
+:10F590004EB003B2FBE0F1BCC97F7ABE1FFD3D3E19
+:10F5A00087DB355D6FD5105CF3507FC7E8972DFA88
+:10F5B00065E778E8EAB4312D7E2A4D73DF08988F2D
+:10F5C0006D2CB77B6C891B18D98B406ED6FC3E3BEB
+:10F5D000494A08301C1FECA5EC9CBCBE716D9E7A9C
+:10F5E00086F253723EB81CD7C524AB8FF4AEC93E29
+:10F5F00062AB3DCA6D78FFB621BE7680C54D3949F4
+:10F60000340F2FEBB4A39DF18D1CA508C795667030
+:10F61000786C4B071F1EE0B12D8EB73580D7D3D045
+:10F6200096862E27F87501BCA46C1C3F85DD05F37A
+:10F630005A98E3E07058CA843E7DDAA80FD1608002
+:10F64000F633F1BC7D6DCE334BB5B43EFD5BF3B309
+:10F65000AE2D1A8C333E61441D9B0CE36ED686A101
+:10F660009D3911E687F2D1EADE951E4B4FF467878C
+:10F6700069939545481F7709FD3A1E20629BDAFF82
+:10F68000FBCFC407BE8AF8CD457844C5BDE6E67019
+:10F69000FB6C218E9347F6A5126D5FB2F0426AB7FC
+:10F6A0006473FA7A6AC302A2B70480979484F3E77A
+:10F6B000F05B7607A7AFCFBB0E7DFE03D04920DA03
+:10F6C0009E8EA293BB62D1099BE3F392BFDE9F3D66
+:10F6D000A7F1F9360BFB51B7939D69BADD1C147085
+:10F6E00060A1A26174653301AEC33C8CE234351E67
+:10F6F0006B3008208B4B9A6A21B95361619E0C1CB8
+:10F700005D611C8F73E468F9638E0FFA8FC79BE409
+:10F71000BB31EE547C6684A15D7A2ED3E4274E3053
+:10F72000F99139263F739A493FCD30F4AF4CBBC6AF
+:10F73000E4C72E34F9B946796363364DE0CB4A719C
+:10F740000BCD22DBF2F13E23FC443D27BFB317CEA5
+:10F750008F2AD5C4AFC2AF31F3EB37726482B3C521
+:10F76000C3FD1A9D1FF4F775F839BC1AE17563BE25
+:10F77000AE9F7CA4775CA12F338CABBA7C3C4FA3AB
+:10F78000F7DFDAE07AAB621C63DF6F606F5500F27F
+:10F79000820D1EBA3EDEE0A5EBA30D325D1F69C8E7
+:10F7A000A27E9B1B7CD47EB8C14FD74D0D0ADD7F56
+:10F7B000B0A192DA1D0D016A6F68A8A66B7B834A1F
+:10F7C000F7C7DA540DE32063DB984F83A58CEB80F9
+:10F7D000EF45C16D4C1BCC230AEE199AC7D01EBD54
+:10F7E000C66BE89F5E2F1B9E8F5C9D65789EAAFA74
+:10F7F0000CEDCBABFD86FEC3038AA19D5C5969E885
+:10F800009FA4040CED445FB5A1BF3B4B353CDF53D7
+:10F810005A343432001F773484C20887F686305D4C
+:10F820003734BC44D796869E30C2E90CCA5FC0A369
+:10F83000C7D649F2C333D1C3304FE17201BE008F46
+:10F8400049368F25296AFC2405C6CB8A9E1F8C6702
+:10F85000F0CF82442FEEACB0E1BED3DB63786FA66D
+:10F8600094508EF98923C512C5BD8E142727A2FD99
+:10F87000B2DEEE999B0BF3387C4CF26DC5F5E20BD2
+:10F8800031E4E529616FBA27BB482ECCDF64D92A61
+:10F89000115DF3F76FEA1E13337E74F89BAC1AD731
+:10F8A000E5DEB35346BA985F5C9B1C17E5AFCD0FFE
+:10F8B000FD47452A8D979D1F07F4327F73ADA36ED8
+:10F8C00062DFBAF47E376D32DA977D741F74E13AE5
+:10F8D000C66BDF74A17C6B4FDB4AEDF6AC81F32481
+:10F8E000BF13EBF950D8CFA7851D7652D861EF0B27
+:10F8F0003B2C22ECB07784FD7C5CD8CF6F0A3BAC0C
+:10F9000047D861AF0B3BAC5BD861AF093BAC3DEB7B
+:10F91000B959240F9FB53029869FAA5FBFFA43A328
+:10F920001DF6E5A0D10E5BB5D96887DDD861B4C3FB
+:10F93000EADA8C79B95AED2AC3F31BD618E36CD7EF
+:10F94000D71BE5E1B2D5330CEDA5AA31CEB6A4DACA
+:10F950006887E9F8B93660948B0B2B8D76587FEB6E
+:10F960007D21349BF23F88C413517AAF378F8B7A55
+:10F9700005E825F702E8158A83079A317FB203BBB1
+:10F9800080FE2DB1868F4E41F9F9BAC430EEB4E74E
+:10F990007CFE9CF9F2C5DFC9D78C74B3FCB831BECC
+:10F9A00071DD1D46B856DD6CF44B1C9546B82A69CE
+:10F9B00046BF64A159CF048C700529CD902ECDFA95
+:10F9C000C6EABE5946F9FD79F58E83815EE16D8305
+:10F9D000DE71E09D4CC373D23B6DB93C5E970FF373
+:10F9E0004063A131AEE010E693F6BC61A3FA109833
+:10F9F000E06B6341FF94E2DF00BF17EDAA560FF4FE
+:10FA0000FACB42A7A7094C56269DD9FB35E8EF1043
+:10FA1000F910F6A9ED248EAFC22FE22B9F413B4A8D
+:10FA2000CFE585F9F3A8F91A9E7F0F7136E07C9433
+:10FA3000D7C6E6FF3DE7939882F6109BC2A6509D7D
+:10FA40004164D8A0E2ABE6FBB9216E07E5A6713BA5
+:10FA5000C89FBE40127927E6C1B695B9289E398A5B
+:10FA6000059FC63867FC21F73C6836E390A9E85744
+:10FA700019F97FD19C81F3F25FF21AF97FB63CC687
+:10FA8000E40F19F97FAECFC8FF4E66B25F224C4635
+:10FA90007B927060353C2738BD26E8A8F1BD96659D
+:10FAA00094874DE771379D7EA6097C31D6B9B7168C
+:10FAB000F3CDE057A2BFE1645AF214AC2B0AD72B66
+:10FAC0007ADE8DF026ADF5915D7A86E3C70FBF88AB
+:10FAD0003F3F8BC217E2EFB8117F4ED3F3D3829E24
+:10FAE0002E9E17A7A37FDCBC4C749530EC12F9B79F
+:10FAF000D874551656A44498DF7E8F85F2A9FBC3AF
+:10FB0000F5E132687FE2E5F542AD690B6C345FA642
+:10FB10000C9909789825D6EB1779ADAE064676C7CD
+:10FB2000F30D2EBA32562FA13C6AF1DE968CFAB153
+:10FB30006B943A12EBD2BA8627ADC3FCFC367B52EB
+:10FB40005AAC7A96DDF602D2A75DBB536D32BC5F2C
+:10FB500066F3D8F0BDB2B41512FA7B5FEA616417A0
+:10FB600094A5F1BA8CE71B4247F8F754AABF8175F8
+:10FB7000CC40FBB4C2533B233105E3B3608BC9686F
+:10FB8000E72691FFBA6FB893F0E6F4ACAAC0FCF197
+:10FB9000ABA912B3F8013F3EE60BA11E484BF0059E
+:10FBA0007138AFFD7D84F36AF8FD2CB34F2F009FB1
+:10FBB000BF1F8D8F0216D5A6BC82B13D224FD43F08
+:10FBC00009FCC84CA53A8B961E9E1F6291D8799667
+:10FBD0007785DDA0C7F78F0BBBE14D11773B22EC9A
+:10FBE000861661378484DD7054D80DFB84DD704047
+:10FBF000D80D2F09BBE11561371C127643AFBFC08A
+:10FC0000EAC99EAE65AE08C6D95F05FF1CE58877D8
+:10FC1000A5255809EB98A17604CAA1ED5C6727F9E0
+:10FC2000393A4D6BC4F8B8B35A9B89EBF02E3FBB01
+:10FC30001AFBA7A6396405FA3796B6A746789E61DF
+:10FC4000C85CE08F95825E96AAB30E207FE870674D
+:10FC5000D2A379946FEAE0F076C12FC23B55857646
+:10FC6000941CA935C17529B6A3E48603E910E058B0
+:10FC70009927F82187E570786B7108EFB85A016F02
+:10FC80006F4A4CFED82CE0ADC36377E957AC1A74C9
+:10FC90003D9AC6EB258E167FC5FA2AACAF5B91283C
+:10FCA0006FDA9DC6C75B20E8DF3C9E9E47DD583E6D
+:10FCB000709CEEB0E8D7DB6E63B27368D438E5FFB2
+:10FCC0006697E1FD25A17BD2911F360ED1F3C33E8D
+:10FCD000B2AB674AC5BFCE80798645DDA32E271714
+:10FCE00033011BD3F78E8A75F6379FA3E5D7D86506
+:10FCF000187751E81E86DF73DAEABDD1F5A4DD621C
+:10FD00007EAD55B733E4C7F028C03BFAEF01A78CAE
+:10FD1000F6F6E834DFBD88776F9A6ABF13EECF033B
+:10FD200039287B705A1DBB53B01FBCF30843FA98A7
+:10FD3000D089FC7634DD45F2A6BFF95CA43F828C05
+:10FD4000EC90FEF407D031D941CE391F1C477F76A5
+:10FD500021ABF785E0BD70AE6F38F22FABB6935E86
+:10FD6000CE82DFE87C9A7E5D68D2DB6EBF7D40F993
+:10FD70003BFA42431BF2CD51C137AD3696887539F7
+:10FD8000E139B7BB103EF3D333F7207E58992B32BD
+:10FD90000EE0D05A7CE7F508AFD639AB3C16A4ABE1
+:10FDA0009231F43C5CE63A8D9538BF29BB3B5D8EC1
+:10FDB0008277EB7DAC544578A7DFE5BD09D69599F0
+:10FDC000F6A7067532F4B3737FA7A7FCF76919513C
+:10FDD000FD27E595FD200FF9B97238F1C378879AB0
+:10FDE00019AB1E58A7F3C6D278E2F3F76B799D02E0
+:10FDF000DCBF770DCC47C5BA155F1FFFDE28E829A9
+:10FE00006EDC39E273F53EA78C7E069396B7AC8123
+:10FE10007635DA4968376DE27CABF3717ABD515EB5
+:10FE2000AA26BEAD36F1B5CEC7BB75B9D9C7C7894D
+:10FE300088D7B85ACE4FFDF1F1D24FC1BEA142A032
+:10FE4000A0C1AF7B63E59878AEBFA2ECDA2924931A
+:10FE500064473E568132B26BE3C57320C9DD389FDB
+:10FE6000F03D3973115F5A23D8FF38B735F63E7A23
+:10FE7000CBC475B2217E587FFC5A291BF329ACDE16
+:10FE8000DE6717671ABE4775028BA3DB48AF9AF28D
+:10FE90001BB41F308C891FFDF37B47F637C3F7DA9D
+:10FEA0004724B34684E71D9CFE5CF010C703353D34
+:10FEB000C48FCFBF352E1B53F72C9A5E61FC88C6CA
+:10FEC0009FBFB36678369999A25D73CF98A9D8AED3
+:10FED0000AD84F46CB55566123FC5FBBD6B215E31B
+:10FEE0007EE3A58FCEEE85FEF157397CCD30FEB591
+:10FEF0000FACB0235C1669EAFE3AB8BF08E822E806
+:10FF0000A37518F8E4A8CD63C7718E56585807B486
+:10FF1000E31719BF53B3D6C847663BE458A23ACAA1
+:10FF20000AEF7F6071B2AD70DDBD65D5E338DEA943
+:10FF3000079C544FC870AC7CD4034CC42595C7EFC4
+:10FF400081E72B363B19C603960A3B3F313F83C6F8
+:10FF5000B5BA97D3FBB5ED89E40F9FDE72F964C49F
+:10FF60007FDBB0FA5B03C037A792D41AC4EB8AD602
+:10FF7000ABAC1A3C6F8BEF9889FD3FB032CFD66C9B
+:10FF800068CB0FDA713E3D6017609C559F676D5BD3
+:10FF9000147EE1BFEA7C1E779F67656A670C7BA6CB
+:10FFA00023DFA2C7573567D4FC1FCA97E9FEBCCC34
+:10FFB000612D0FE17700FB1E9F800BAE7B268F87A4
+:10FFC000B6A5F96A8643FBA485799A52F0AABC8348
+:10FFD000FCA9DDEF644F13FA19F5778C1CF1647BF3
+:10FFE00094DF3F497CF744127FFEBE373E88EB7CAE
+:10FFF0005FE66DCD9B10247AB6A9598B13F97A2C44
+:020000022000DC
+:1000000097E1AE073EBF6389B22393F0C1E4E76096
+:100010005E2B367D97F0BB0DE083FCD9E3915B76D8
+:10002000C33C4E83F2D6F0B9F7919908CFDBA70213
+:10003000A1A65E0CA77BF287F13CF4E6E644D2F77A
+:100040001EA63A2EEB83476DC7F6BB2D9349CF6BA7
+:100050005C7E70FEB3B028F90EF89D57F81DFB0AC0
+:100060005C6F1CEB40BC58F7AD73E13C97D6DA29C6
+:100070002E94C00295284F6B3759A80D3F1B505F37
+:10008000AC10FCD5260F3B5087F0403B9CFCBC4796
+:10009000F7635D40AD905FD52B8D747AA3D766A0D2
+:1000A000E3AA3546BA86751ADA9BF379FEA5C77FAF
+:1000B0002A05F5731B2C1BE1F2418B25B895E46BE7
+:1000C0006054745D9D9C6FD5EB56647B14FC5700A7
+:1000D000FDAD40BDE1621DE5A9B8EE71B390DE1D36
+:1000E000C7E2699E66F8FEB3C3E144BA5C331CE61E
+:1000F0007302E818EB7EDEDFD24CF60BFE4806BE3C
+:10010000F6B4207DDF04B37CC443F4E9C0FC914E17
+:100110002F3A7C6A37671CC07EDEFF932883D3C4E6
+:100120006ABD45AB30AFD34B4726F8E09A6DFA77FE
+:10013000C6F4D1193D8F4167E5D097E345237EA9E9
+:10014000ADE8CDE78D1AA86E99F05D049FEB9ABCDF
+:100150004C2B16EF03DD6F2C7D85E8E0130F0B4A67
+:10016000DC9F7D1DE57EA2989BC69410CAD721A274
+:100170005E14F512FAC9C962BD496B2C6F56E430A2
+:10018000366C8DF46605DC4CAA0887504F38BD42AA
+:10019000EFEE2AF8C9F8CBFAF4D890F839BE10ADD2
+:1001A000C6934AFB12EC9E54B47F1EB058AA315E2F
+:1001B0003F8419EDAA64133C58AEED64B43D1E2F84
+:1001C000E4FDAA99632CE4E7541AFD529BC92EFA68
+:1001D00011D2F5F0BEF5CBF827C0B105FC3694532B
+:1001E000C3421D1D489F3560B70669FD3ECAE7380A
+:1001F000407F3C62E98B5BFDA3E21617C5BF44DC80
+:10020000A2BFF8971E0758C86FB18D0ED58BF9BEE7
+:1002100085DE9BE6A01DDA58FA152FF94BDED36474
+:10022000973A845D1A376EA587E7CD38FFE87100ED
+:10023000335D99E34966FE33DBA5BFCD17F6D304E2
+:1002400036E1F3C405F4F87D6B16F77B5AB35634E8
+:1002500061DDDA79E1F778342BE171F1220BE151BC
+:10026000B7D716FBCF2E42FE7B55F81797F27BDAF5
+:100270004D7E48BCFF494589A13FED055C3EBA8BE8
+:10028000F9F3C52E667345E50D1C055CFF2E063D92
+:10029000E88225CE633CBF319F19F35249621CFDB1
+:1002A0000A3FE1A9F9863AC1A4027E9FF2A04E91CD
+:1002B0000775893AC1B2EC737B3FC3FB0AAFFF7588
+:1002C0002AB58FDD8976DFA2449F95E8577DFA3BFA
+:1002D000E81F2F7293BC4DC992A9DEB53ACDE52334
+:1002E000DAD794D7D12F5BC488B701D40AC9DB25EC
+:1002F0005817E119C0DF710D1C2F4BD0FD9D624EC8
+:1003000057BD71A50097DF56F8457ABAB6DA482F7F
+:100310004BD481E927BB40F8D162DFD6F8C885DD30
+:100320009F115D70FEDD388AE7A1CFCF813E98B77F
+:10033000EDC71ED7FDDB043BF8450968BFEE257A03
+:100340000F67317B34BE03C592A1AE215CC8E23D8C
+:1003500043713641C257D8CED21F80FE87CB3E6054
+:1003600077C0A712BE33CC82F57BFD7DD74CD7F783
+:100370008DBB89E2FCDF9E0D2082F9DE878965AAAC
+:1003800023F8E9329CC7B7B14D75753F5A8675752C
+:10039000DF8ED3DBCF7F4F89AA2BF87AC1AEEFA1D6
+:1003A0005C575DA05F613CB7CCA88E8AB14E92C706
+:1003B00012C6FD501E4F8C8227F90946F89AED7639
+:1003C00009F13719E9D1C8E7E6EFAE32E1A5BF750B
+:1003D0009BDF839FEA09467AFF5AC10075B1E6F7B1
+:1003E00013B04E22F1F3D71780E0A43CB4C4AC3E66
+:1003F000F48F5939A3EF593C9C8E50A2A0DEB3D79D
+:100400000FF111DCA01D877A20E8D6E3A734E93884
+:10041000A40309F38621D2DF309588650CF6D7EB6B
+:100420000C54F6997BF0720EE42F8D2357F23CF2B8
+:100430001B0A8BE0F7C63FB239908FFEF931D0AB83
+:1004400032EAEDAF682E689F5BCB280FE0F6A8D4A8
+:10045000864F459A61BE5E95B76B0046A8879D5E44
+:10046000639DEBEED247CA1CF0BCA582C7550F377F
+:1004700084DE588779DAE222928FEBB063D47CC3B2
+:100480007BE21C187751B5AFBBD04E7E77ADE4C090
+:100490006BB8A956C345BF91AA755A648C33A80C92
+:1004A000FD7AC7DAE69948BF6FD835DF30B8BE8726
+:1004B000715818BFAD49BB05FD1C459E539901728B
+:1004C000616B9B8DF613BD57FEFB34398AEF7E5B63
+:1004D000C0FD845777C77D1BE1D06A7145E2F06AA1
+:1004E00057B7DE9782DF73F81A618A6F343E948EB5
+:1004F000DF69BDB1D5B7079F373A7187296BDDE258
+:10050000AAC6715BD36FF2DE1435AE6BA4A31EEFE7
+:100510008747B450FE59ADF439E292705D1F257AD9
+:10052000E1FDB6B539C9488B2DA98E5175D8EFA616
+:100530003FFFBA00F12E5BF391F51CDE0E3BAE7B64
+:10054000B457D5300F7E214FDD87F4BA74CD7B339D
+:10055000A93EAE22E95EBC8EBEF0B53684FF1B22FA
+:10056000FE12495D4179D99695752E9CEFFCD4CC4D
+:10057000A6E8F84B4BF18DAEF1F05EA6D75ABB6AF8
+:10058000C8C5F4D182F19629382F58CF24ECF7A7AB
+:100590000615FA45D21DD5B1F663BD2BE0E76A5EBC
+:1005A00095897190962D2E4CC3B0168BBA19E39C89
+:1005B0005A4642CC7AF5097EFE5E8DEA99E99009A9
+:1005C0003FC46FBFDDFEFAF7B4B1684772FCB96C87
+:1005D000CC658FD27793F2CA4E1644F9CD177D378A
+:1005E000B585E47F8B85F3EF04FF1FBF87754FCF81
+:1005F000E605CE20FC5ADBD4CD082FA6B9D890D280
+:10060000FEF924721F1BC540FEB6343AAB63D59B7E
+:1006100045564AF3904F8083DE1B322A4ADE37D597
+:1006200065623C24D2780571776FFF2DAE77100F8D
+:10063000912D5949A8FF22E92B3233916E055D9A1D
+:10064000C7FFF7026E3FFE242760F5A35E9EC8F346
+:100650009BB30B02366AB30E2FDAB55F00BA1DE901
+:100660001FFE0FA55BD273EF6EFF1DD115F30C2E8D
+:10067000EF1810F2B6B1F43F29BEBBBE90E74DF4BF
+:1006800078A06EE7C68DFB7E08FDF140A19ED72ABB
+:10069000BEF7768C1FE979D3393C1EE881DF58F12B
+:1006A000C080291E18DF4F5C7F865FE83D61CFA6C2
+:1006B000C91D817294BB87241FFA0F98AEC079566A
+:1006C000052CC110E51FE25D34EF1211D714FED6E0
+:1006D0005231EF371B5C0CF3461B1DCA7E9C7FBB5F
+:1006E000C8FB5EB7FA817BD1EFC6B835CE7F1EE37B
+:1006F000761C2B8EF351BC05892095F5FA670BF01B
+:100700001EFAADD29CBC68BD083320BB653E33DA0F
+:10071000730B98C9CF5AC9ED30DDCF5A66B213CCEE
+:1007200076FE22D3F3BE7C0078174037E7FC391BF6
+:10073000B1B4ABC6BFEFDE480CB9734CE4E98E36FA
+:10074000286FA21EBA77D1CF5C48A7EB6D9D2ED43F
+:1007500027EBE7DC9E88F4B77EB9447C79A4A192AC
+:10076000FA1D6E08D0F55BFEA4DE785648CF33C084
+:100770003C5EC953EE423AD7EDB14573CADE5C1711
+:1007800085E70515B30DED4071D59BEBA2E3903ADB
+:10079000DD49AC3E561CED593FB7DB6D4097545FC9
+:1007A000283DEB1BA8EE06E8E85C349CD6FB8DE701
+:1007B00010BCEA9F3174203B465FAF0E271D0EFA36
+:1007C000F3FEE679A79FCBADBF749EC1CF394FF33F
+:1007D000FCF479F7D73F2071BD70A7BF6C39EE17D5
+:1007E00079254FED4479BAA832693FC61A8EDA38B6
+:1007F0001F1D5512695FFBFE89566ABBB378BED5D3
+:100800008C5777652DC9B54BE137BED8C2E3CCE034
+:100810003F29F0E72CB1BFBE7D2223FE6C2CFDF1F9
+:100820004B987FFE4D999D0939336F6E94BFB4D1BB
+:10083000D119BA338A4F81DFEE45BE75EB798780D7
+:10084000317F08FE8E217F6896336E53DEE1B00E55
+:10085000F77C80FB983EB8F7EFD7C4A60F407C1E0C
+:10086000E2DD0CA75B4DF031E72702BBAA8CCF0776
+:10087000E9D76C6DCBDD8F79350DECCB7100A7D747
+:10088000F011BC17AFFC94D220AE42CE37E3236701
+:1008900036A09EEC069580FA66E382DB3763FB3C6C
+:1008A000D80188DFFEF980FB6FCFE6291FFB63D4F8
+:1008B0000DE8D76EB417A6605E30B6BDD0BD72C667
+:1008C000DC98F6C282BACC3C9C5795D15EE8DE52E9
+:1008D000F9580EDE477B017EBA0BEB0CF602ABCC6F
+:1008E000B9047CB8FC8D1B971BB33E6F7E9E3AB457
+:1008F000306A3DEEAC7A165DC7F8C77CC55308EF89
+:1009000057F59E43C2BF07F6D83E7B8CBA45FD7BA8
+:1009100053FC7C3FBF7E8EC860CF13D1EBA7D7DBE3
+:10092000956AB4FBF4B897DE6F4A218F73B4652AD9
+:10093000ABF1394B987A89711BF5384756F665A2A9
+:100940005E5866BDFED17F5A647A1EC3FF639897D6
+:100950008C4F3BBBCF035D4EFAD55C8443C9D9A015
+:1009600086F910E71C0BD94FCE344676CE60FDAD2C
+:10097000C1F66B6BE2F2A775058F979765DBA81D33
+:10098000AF4A5B51FE4CBF30D4827223A04A4FE283
+:100990007CE3958F3E7C0AF535D801188709B07A3B
+:1009A000DA5F9D600F507CA27D0E8C9C8D71982625
+:1009B0007B26C5D3337E9AE8C5AF05DB305EEEF407
+:1009C000F17D50D57EED5E3C2F637EC9380B83E709
+:1009D000F3025CEF2FC6F80D8EBBE8EC6E8CFF5C6B
+:1009E000EBE7F20BFD38F4B396D4DD3DE961F92F66
+:1009F00089DB04DB9273299E2453FCC0141F7216FA
+:100A0000CFA2F8905E271128E6E7F7B0B4043A7F4A
+:100A1000C21CDF31C773CCF11E737CA7BE90EB7193
+:100A2000DDBEFA5AA1D1BEBA0BF71E0C47790B2ACC
+:100A30000AF8BADDCED23B2646C75FAC0CE32F776F
+:100A4000159AE28C83945B61902B2770217B5FB6B3
+:100A5000A3BFBB5CA9A5F89E99EE1F10F2ABB930FD
+:100A6000C150D7116E5823DE8FD310CFCBC73A8237
+:100A700071197DE30C963FB6E42BF717723F6323A1
+:100A80005E994FA57D04B30B3C06BA65F5C3D989C1
+:100A9000E8BCAEE9BBFA7CF4F13FEF3C3608780FD6
+:100AA000964F369616B91CF0FD4F00C7BC3E1A0C87
+:100AB000ECA8F8B41E3FD7DFABC1BC410EDA9316E9
+:100AC000CA1FE8F7A3E2D836A4DBF8345509C4906E
+:100AD00097E1C2DEB829E531F5EF308B4A72A14EBD
+:100AE000E46BF4F16CCCDB487C80B4ADCF4B8A1165
+:100AF00037673E97134866C50689613C2881291DE2
+:100B0000187F76B4D9A9CDB4EA0363A3EA871CC5DC
+:100B1000B30E609C4DE70B73DEC621A5CDC261EB21
+:100B20003A8CF92B737ECA6C57EBF1751B7C04E78A
+:100B3000F507C4075F6F501ADC7A9FA4F57C41D794
+:100B4000ABD3D59C9CAF7AB1FEA4254EDD5C0BF3F4
+:100B5000D21E7351FCC28D73439884E017E5E463A1
+:100B6000FEA750FE5E28E4E7D1B458783DCABED453
+:100B70003FA544EF5BB850C8EDE1A70A651E27B159
+:100B8000B110EE93621353882FF4FA93C3A9DCBE1D
+:100B90009C5F7263E87668FF2F51277955C9D37A35
+:100BA000BE7F48593EA3D20F6E0FF27AB4C357F6F8
+:100BB0009EA7B207FD4EBD5EF7AA4EA39F794D9644
+:100BC000DDD0BEC8CF34B5938ACC7564AA8BEAC891
+:100BD00052451D9998BF994F7ED8C0F31A3F16F51C
+:100BE000FECF8AFDB2FF5BD4ED758AFDB2CF89FDE1
+:100BF000B23ADCD7DB558A4F9F9A0D365D765F5C43
+:100C00007063E937BCC8C7938B2C7A7E660FEAA95C
+:100C1000BEFD15039F0BB6B0D29837BB3660CC9B98
+:100C20002DA936E6CDFE94A34C29C27CCBE4D54D4C
+:100C3000783E41D52689CE27D8F8F0271F3E85F685
+:100C400062313F7FC7FC9D2362FF85BE7F43BF5F4C
+:100C500056C4E9C3BD27D58E75F8559BAA66613C7D
+:100C60009D79A60ECA7E9B8D317858B7BBC963C7E4
+:100C70007320AA424B1D38CE8D9B619C84C18F731B
+:100C8000DFB8CB286EDD1BF7D7AEBC1EDF3FA2C797
+:100C9000FD59D6F565F0FC8888FB2FFBF984C7D099
+:100CA0003F7AAA50A94278FC5BA1B200AFCBC47CCA
+:100CB000A0BD28BA0D3F2F2519CF9D585634407C32
+:100CC0005D9A6189E93FAE2CE27216F4516D118E86
+:100CD000EBEA8D7BD5E178CCD541FBEBEE2EE2F251
+:100CE000A9F94DB61AC769FE395BFD5C0CBBFBD692
+:100CF000228B3EDE57693CAFAEDF02B7F0F18DE3E9
+:100D000049CEAA5108E753585F1663BCBB8B1CFA47
+:100D10007877D2FB69BDF3BB3B7A7E7DFB663C896D
+:100D2000C8B4EE1AD5DA03F4C31E96A82EDDDDE5AD
+:100D3000995B88ED5963A88EE548C5C0E76BFEBD99
+:100D4000F6D11CA9F8D9BFE43E9AE78A3206B58FDE
+:100D5000C6BD80A9B1F0FE7341977B8A73864606B3
+:100D6000C09363CDC130DA19BD6D9BCA30EFE7582F
+:100D7000F32ADD5F1F17A889B5CF392CE8B4A56227
+:100D800065005344ADE9B30CE736FC3E57DD57141C
+:100D9000E52F3BBCDC5FFA64ECB9BDA89A16545849
+:100DA0006C9614B2B77D16306D73D756495E993183
+:100DB0007FFD03332E87E78BD2C0BF8B5A77D1EAF2
+:100DC0009FEE057665C515479A53A0DFCE7C358C1E
+:100DD000E3977AE57DD85E14C8A67AF7F5498CECDE
+:100DE000BC53E31CE48F98E77D42CC1BE47293ED87
+:100DF00073C8E516939C6C4D1FDF84F31F5FCE22F2
+:100E0000286133BD67CB301F38294F3D817C96E97F
+:100E1000658A7332DD5758543EC73CAE6B1AD7B75C
+:100E2000E32369F7637CF9B0EEEF977E6E7FFF6C8A
+:100E3000D100FEFE29911F68FD8E33665EE4D4CAA0
+:100E400085B1F3030FD7AD40BE3FF51DA3BF7F6A49
+:100E50004B750DEEEF3B25F203A766D60D981FD01C
+:100E6000D70972C8310DE5506F7E40D8ED22CE3DD6
+:100E70003F4F89C3E7E0CFC74FCBA37DE86EBC32BD
+:100E8000CD733DED4366B1F7C7B2473D0AFA39FA73
+:100E90007EF6297E3505C7D1F7C98E47D1368CF647
+:100EA00075DF1A8B9E478BF9FDE579D3DEBCA695DD
+:100EB000F64F0F326E3FD87EB2BF93D7E3D8789DFE
+:100EC000615C6AB917F355E727BA48BFB7E1FFA2DB
+:100ED000F46A7A919A376D78F438A6F354E5C17DB7
+:100EE000375EF89BA8AF506F75335689F2E6DB4941
+:100EF000F514F79821E066BECE9A26F0CA3C290880
+:100F0000CFF4A2C04CC2E3F39D329DFB2AEEB3ACFA
+:100F1000C1F99FCF38026FD3BEFA7249E675798C5A
+:100F2000F8E28A2C0FE969DDFEAA9DC6E5A6934585
+:100F3000C63A609DCDCADE841CE8F7EEA3B66C7C91
+:100F4000ED0789CC8EF30E64819C8375947BD5D19B
+:100F500003C9473C89C88AFB1E58C862F5D2359937
+:100F60005F350BDEBF881F1F3D371CEDF11F3CC6F0
+:100F7000F355573CB6D2B5226AFC87A709B999C682
+:100F8000E75FA358827206CEE72CE5A5AA64AB4FB3
+:100F90006198473E7F6C09C609C17E1B47ED4FA88B
+:100FA0001D96AD3998E77ED7FBF131EC7FC5376FE1
+:100FB000BC8CE85FC0E386B539CF909D9FA7DE81EA
+:100FC000F80F177F92386622D9F19B91FE6FB0B06F
+:100FD000402C3B6683C0DBD54AFD754867572B4ED6
+:100FE00086FBD5C2654E82FB0F4A2C32DA95F3910F
+:100FF000E6319EF3A88DE2CD008F9BF1F9219F9BF6
+:10100000CE892E577E6AC3F69F2659D8E503E8E3BA
+:10101000CF0DD7E24F86233FBE8BF41763FEB56238
+:10102000FE3A3F01DCCB695E0AAF1FE98FAEFE5886
+:10103000A87C17E1D496A9AEA6F3103D0B06751E49
+:10104000E2FC1F06A976CFF9FDFA112C46FDD76107
+:10105000C127E6FB3F9CC6FD821BA7F17ACB2B1E66
+:101060003B776836F2F55ABB07F1FA5461E0C7D313
+:10107000A2FDAEBFB21C99292D27FC85E7C0DCF983
+:1010800041A089D89E37D646F8D3CAC5F91E773114
+:101090004F7312BD456DD75A0BF1993BA1A31A8D21
+:1010A000665B61FDB16BF1BD3289F6F347ED7319F3
+:1010B000B08E2C22F2592DB8EF0C6CF9F03A493F62
+:1010C0006F8B5940B6852B6CC2BEFFE031652CF0AA
+:1010D000BDA8CF3CFEA2F571AC6B3966E5EDF08B97
+:1010E000D6514D400791517C1EED0F587C8D325EDC
+:1010F0009FDC8C7906758DC55709ED9AD03D5E0C45
+:1011000071AD58E764E82ABC77EF15642F7EE2657D
+:1011100074AEEC9254CE37756116B466F4F9B7EF3D
+:10112000A4B3A09E3FC5FD737EA1671EC4FD6B30B6
+:10113000EF2F6DF8BA7637BC1700BF17E36AC37C90
+:101140003CBF191FB6F9820CFD5D5E1FD9D26861E4
+:101150000FE238D28666F4CF9D22FF11AFD492FF02
+:10116000380CE853C68879C466D8BFA63295E837EC
+:10117000B91238231BAF46FF38F712FBD8965C3FF5
+:101180003C09F9E5DC34A35FDC5F7C5DBFE2393705
+:10119000889F2E916FDD01763BAEF7E760B7E37570
+:1011A00017D8ED781FCFA5C62BEE63C3EB1EB0DBBF
+:1011B000F18AFBD8F08AFBD8F08AFBD8F03DDCC777
+:1011C0008657DCC746FB0E4BB4D050844F593CC306
+:1011D000FC508B9DD39996EEA03AF75009A37C7EE4
+:1011E00038DDB1B509E375168E272D893F0F27AA83
+:1011F0005FA176C64499D7C5B351B87F709D65A2EB
+:101200008CF6539B43A63AFC534D36DA9F7062AE80
+:10121000E56DCCBB308BD527817DF3CBCF6E25F828
+:10122000D72ACC8AF2A109CF0B4579FC2113E71705
+:1012300084253C57AE3991097ABC2EA880CC7E1FFC
+:10124000BF45F47A4045BF78BA536FEF55F179ED59
+:101250001A8BE8FFAB20D26FABDE5F3BF404FAAF32
+:10126000EB4CED6EABFEFE686A1FEBFDDEC81A05A7
+:10127000E93D537F9E7A03B62371FAFB7FBC01FBE5
+:10128000135CA8EEEDD413389F13E97A7FB986DAA0
+:10129000BD7573D7ABD8FFC470DE7FCB9E834F6222
+:1012A0009DC95F7BBC6655A338BEB688B1A7932E97
+:1012B000A6AF77A74BC678A86231C443F5F8BBD573
+:1012C000BDFC72DA7FD6E424B91849F7D5A0DEEE6A
+:1012D0002F2E1A15AFA7B8E88FA6EBF5CCA6F827E6
+:1012E00070168E5B8DF1401F7D558DDE9FC62CF5EF
+:1012F00021AC530F9C4994D18E74A445C5EF840C46
+:1013000018285ED85CCFE38361D54EE777E875FD9A
+:101310008E6251D72FE2857A5D83A3F86143DEC0E8
+:101320001C2F64D2CD948F0EAC34C603E7AB9F2F35
+:101330005EB89C85EC9723FD2B16AA8B58EE91DFA7
+:10134000B90CED6836819FCB28BF14ECADEB9769E3
+:101350001819CF9BAA16EDF65BDE7B1BFB079BE201
+:1013600064DC84BFECE6B2772E23D32D81617C6BE5
+:1013700059093F9731EF43DF4B32CA53AFD5C7CD41
+:10138000B4C03751FE06562651DEE4FA3B2CF4DD9C
+:101390005ACDCD104E60570A7AEF7A1CE94B725B3A
+:1013A0000CEDDC513ABD5DFB38D2FFF464BD1DFF8E
+:1013B00004F25B99437F3F8FDA4B558B789EF5841F
+:1013C00002AAE458B94EDF2FD7E0F36BC7F48E477B
+:1013D000F43DDDADB7AFB9019FB7F58E5747DFFBE1
+:1013E0000D9E6844ED194F203F9755097DA5BDF727
+:1013F000388EDFB25C1F7F7C10EB509759F5F759A0
+:1014000010C7AF63BD6D05F5E25B82FFBB8B3B6B25
+:10141000305E755DEFF34E5AEF72D17EBD587D029E
+:10142000F9E95F7E7D7FE7EF99DBD7B3F0CCCB7333
+:10143000FBF8C22CAF7E55CAE5887FF54F91CCD919
+:10144000F2FA27E95C378C07F07C56EAA200D2B7A3
+:101450004BF20167B08037302B565DFCCA123ECE8E
+:10146000E962635EACC594170B88FC547FE31C2AC9
+:10147000E5719DB6F2D87EECA4BCF28F8A319EC095
+:10148000CE4A389E470550823DDB98A3FE19EF03F4
+:10149000EB56903DC7980FEF835FACA19D390FC00D
+:1014A0008979D8C6D247284E7FA2D06E380744CF5C
+:1014B000736E7428241FDFC3BA0E908FCBCA959920
+:1014C00058CF78E308896DA57AB204CA37D8463A6E
+:1014D0009E24B92EF29EFA391CF32EB12FC2BC2FD6
+:1014E000E58F62BD9F14B7DB513E6B4C9B59914B0E
+:1014F000F23A8CF5C756F706CA033B4BED9447D03A
+:10150000F3CF75E2DC6F3DEF3BFDC250AEDFB3F4CD
+:10151000B8EEC0F9DFBA35BB03641F7448CC9A71CA
+:10152000713EB836A0A5DF85F66F4522ED17A85E9F
+:10153000F1328D7F6414A3F87BFCA27ADA1F640376
+:10154000FB50C17A17912FD6F7798FBEF035DA3775
+:10155000AAEAF5E7D29C2128279DADE067D1801C3F
+:101560002E7ABEB8CA24EF6B8BF939730CECF87184
+:1015700049F89D81F73DDF3F9D9FEF77B283D7F319
+:10158000179418F3C7EBED3CCED79669A4ABEF4F99
+:10159000E7FEEA83D3453CB1F4C7D508974F98D509
+:1015A000877931F6283F0F0E632CB4DFCA7C0E73A7
+:1015B000D662B2EB1E1D0D4B045BDBB6E62D8A2B0B
+:1015C0005A36F3F73E9CCCEAD16FB1D9781B2E1A6C
+:1015D000E6FFA7F8D53925583FB6E61DEADFACF19E
+:1015E000FAEFFEE237D525BABEE7F19B65DE033D93
+:1015F000B8AFECBF1CC731ED7B0DC8BCBE645DB19C
+:10160000ACDB17741E2110AE1DEDC5F4A2C00A9C00
+:10161000379BD829E33C7479132AFD6A0DCA1BA6AF
+:10162000C4CE4BEB7CDF62CA4B07BCFCFD43BFB8AA
+:10163000AB06FF3D88FEF2109BCA7AF306B795E031
+:10164000BC52F4BC81723BB6FBF4282CC86FD0A30B
+:1016500037ACFE6FA0477BED76ED580DCAD52FDA7B
+:10166000FC81AEFE9DE8AA92C7CFBE68F32F9AA672
+:10167000ECC3F9FFADBF73D5B4C06BF89DFB2C4A2A
+:1016800075024FEEF92CC63C5F4FC90079BE4BC5C1
+:101690001FFE27DE3070BCC15AFACF196FB0E39E2F
+:1016A000AA3CE2A3CB4A918F8A391FFDABCB3D58B0
+:1016B0006F6E29F14367307ECC5FDFDF4F2F52CB57
+:1016C0004B490FAAD63D403FF795B9B83D13E2F01C
+:1016D000ED8B67C0FCFD8678C613ABFF06F10C5896
+:1016E000EF02C26F85F8FE171F7F37137C156E4F10
+:1016F000FC0BD2671BADAF93AFEF1FF0FDCD442FB6
+:10170000CF727AE9830FB793A2E073C3EA7F0C7CB0
+:101710009E25F8ECE0F3FB02E0730FC1D3C7E77B33
+:1017200029FFFAAD629E0F81F75EA675E6723A78E0
+:101730005BD8D7E077CFB85CEEF3BBB7E42BBF2E16
+:10174000E579E4C3A586FA4F258CED01FCE2EED2E3
+:10175000D87EF19B38DF2F9A5FEC2EE170EBCBBB8C
+:1017600004F979B7ACFAEA2BE13BEF00BC31DED6E5
+:10177000BE4622FBE27C1AA3F300747BE34412AF63
+:10178000DFBB787F584508E7ED2CE4E78CE8E703FA
+:10179000D8A4E54343F2C5707D7588ECC07D482B25
+:1017A000144B0B9E133843FB88F69F391427FD3BDF
+:1017B0005BA3BD3EFB1DE847839FFB25ACBF5CEDF3
+:1017C000A1FD27FA3E337DFFC78A50EA01DC77DBB3
+:1017D0000EF4900ADF995F61DC0F62B6376CA6B633
+:1017E000F9DF314D9E6E3C8F0AE04FF6CFF9365E41
+:1017F0001FD76E637BB0FE43DD2005C164624F6B73
+:10180000163A877325C0C90AED191D19544FEE48C1
+:10181000E3E79DE9FFCE29D041079DE7744C62784C
+:101820009F897D65FAF9DE7173F9B97A11583F9E87
+:10183000DFA39F335125E8448767DCFDC90497F394
+:1018400000178671663FB747E7ADE1F9E096E537E7
+:1018500086918D6A8A3F5A17AB2E65B1D7784EBAFA
+:10186000399E613E67DCC60243F1FC8AF9C5651A00
+:10187000DAAB4E51AF19CF143AD722A23DC5CFB53E
+:10188000A8B01BCE11317F37DE44A74E53DCC14CCC
+:10189000A766BCCC32E1E5691B3FC7B1A55BF26925
+:1018A00070BB65D3CA36DCA7AF6DB2F2BA79A6D0E9
+:1018B000B94F2D60F1D27E74982CC6EB970878EA68
+:1018C00078C183BCEE49413921F6A55BEBEFC5FD3C
+:1018D000A54BC5BEF4EB5827ED33B89E45ECE80C9C
+:1018E000DC80217209E3DDB2833B071E86F3A8ABDF
+:1018F000E6E76458710D9827D864257E6DF1EEA156
+:101900007FEF2B34C29E743A8BFB13B1ECD9DEB857
+:101910000240E274541CFF7FE257FFB5F8555E09A0
+:101920003F8FAA252EE429CCE0E74DE03E87BC128C
+:10193000599C37218FEA003E397CDF071ACA617D46
+:10194000BF03FCACBDCC788EC2E6E903F87FC525A9
+:101950008C7F2723928E7595EF8873FBCCF8FD253D
+:101960003A0E5C0F3D399DF2EF60FFE6A2DCE3F634
+:10197000EFEC82C053D3A91E9DEF7BD6E34827FD31
+:10198000EA0FF17E09FEBB39B9B43F2788FB77E641
+:101990002758F65BE4BEEF33731DFB7FD3BCD5ED58
+:1019A000C51C1EE1385EDF1ACE60D5CFC5C0C74367
+:1019B000E55C1F86B363E34B7F0E76C6EB882FF49E
+:1019C000878670A238E330C6078E0F441F3A1E93F5
+:1019D000672AEF10DEF57AF002F524B69BD5C0DB5E
+:1019E000747EDB06496E44FD1A925FC5FDF5F3BEB9
+:1019F0002579108E7FEB3CDCBAE28C41E5E1962143
+:101A00009DE5F52FBFFED2EBFF0742E7FBCB008041
+:101A1000000000001F8B080000000000000BED7D9F
+:101A20000B7855D595F03EF79CFBC8931B08F42224
+:101A3000014F0268D4602FEF04089E9B9B272470FF
+:101A400041C0280F4F08626CD1466514289D9C90B8
+:101A5000104244C119ABAD75F4120CFE7FC7AFA69E
+:101A6000FDAD15E9E38268A9851A6DA8B1551A90F4
+:101A70005AFA8F9DC10A63EBE8386BADBDCFBDE765
+:101A8000DCDCCBCBD8A1DF4CF8F4649FFD5A7BEDB6
+:101A9000B5D65EAF7D72D4C9189B01FF1993EBB424
+:101AA00002C63AB07C19C31F8D4179E9504B390702
+:101AB0009AF6F2F65768FF1636C63156CF447FD1F4
+:101AC000FE37126F7F34302C6CA4337693A887B224
+:101AD0008E65B33F634A6E4081FE0D9259DEA9299F
+:101AE000D6F932776A30DF09A77DFC6562BC42ED2A
+:101AF000131A3F149DFF93B006E5FE38F897335E46
+:101B00002ED5FE42EDEB9859FF171DD77B5C32CBEB
+:101B1000E375EC7FC46596C7D6E1FC0FE4F2F1678C
+:101B2000978C0F1B97203C9FF7F817DAFEED592A88
+:101B300063C3011F0DDF0D7E017E5DD6B853D6A1B4
+:101B4000DF5167E86D960D64F6A0A476419F42D6FA
+:101B50002D3399C076C95360084D621D30D7AA1243
+:101B6000F8DF54C063BA83CF63F8C31AD0D9D2D98F
+:101B7000269DD68671DE6474F79B7D773C8EEB8E56
+:101B8000C26DDCB1C206B731BE4E9B15833BB81F98
+:101B9000DAC3784BEFB8CD87702ECD33D73783E6D5
+:101BA00069CB32FBF59F75DE57F79512BE9746E776
+:101BB000A9A2F64B53CDF1168471DE183E97D07E64
+:101BC000C4E01A6DC3A7BF6409E133E40D6F1E01C1
+:101BD000F809F998DF007CDED4D02CEB05163E32F4
+:101BE000822AF1912F5A0EDBF9A880F868B0E11A29
+:101BF0003D23B455837D62F9DD6A68C2E7B1EE88A2
+:101C0000F30BB8EE6D12ADDBA4A3655E0BBD7B607C
+:101C1000DDAA59BEB2AE217D30E6ED29A379DF03FE
+:101C20007CB3183F3163649D967EE1E3B5A4E7B9C8
+:101C300070BF566A921686FE9FE2CF75B1E7DBB39E
+:101C400024E217C0E7FF237C16023E33F03D233E1B
+:101C5000786672E8071AD4335577EC07B85C9A8730
+:101C600075000EAAA687F6507BB6C387F8070068F2
+:101C70009CB6D798827C06BCE577CC84B293D576A7
+:101C8000170C9CF7E11207B56F61ACB21BE09AB27A
+:101C900029B43A6469E72DE370658AE7918CFEE523
+:101CA000C361FE77A06A138CDFB20D98179EC71A26
+:101CB000A4B0044D8EE578E715427D4FAEC3BF0951
+:101CC000A6EF59EF1EBD16CA7DB9E97E84AE2F6B13
+:101CD000478617E639E697059DDE761CF9FA4846F1
+:101CE000949F0C3C5F7A245EFE9556D489FCF4A642
+:101CF000CACBDF2AFDF271A300E98D79D908C003B0
+:101D0000F6005E75A4CDF2B8010E57398813ECEBDE
+:101D100065BA0BEADD580F4B5CB079D7D7AFA7D1C6
+:101D20006B5F1E378DB15AFC5DC5FE8AD1EFA1797C
+:101D3000954F257A32E7B4D8B8AED696975A108F19
+:101D40003E9995206FF9787B1FEB6FFED481E343BA
+:101D5000399F2109EEFB14F65C1265FCF914969884
+:101D6000CE4295B908573EF377C07C0B74E789687B
+:101D70003D7F6C53A60938111E79636521FC9ADA00
+:101D8000606F37371FCA9E58794E6B7D0903BCCEF2
+:101D9000D1A0DB44C60EB5D647EA619E43856EAF3F
+:101DA000049876E528B6F67359772BE29DA9070FBC
+:101DB000C880971562BE16EF82B7719C95F95002E4
+:101DC000F88F7C359031351BF94DF63B441B8789E4
+:101DD0000F46ED9C8E6C92D37EDCEF9617CC7D9BEC
+:101DE000DE897C20A749B672C065D64FE8443E3CE8
+:101DF0001295ABE3566279F158936F323A91AFAED8
+:101E00004B33CBAE95C847EF284E4127C33B914E8D
+:101E1000DACDF18CED245FDE6066BD83EA4351F9D3
+:101E200057BE13CB4BBC021EE31F481EB668FC3CDA
+:101E3000B96A5FA4DFB888F6C09F570690DF425C9E
+:101E4000DEC5D7CFE80DB76422BD007EC6AB03F96F
+:101E50006D4340263E0A69EFCBC837A58D8033D845
+:101E6000BF60ADD43B15695C61A391EFDB9A60ED77
+:101E7000E3A1FC62914BCD40B91E2AD712C88D1F39
+:101E80000438FFCE08A467BF8BB89BCC2623DDB5F2
+:101E900035AD13FD530CDCDFFA71AE704A6EF27192
+:101EA0005E0D3A48CEF448DE45FC7C96199ECF8103
+:101EB00007C7A617B158BBA783FC5C6E9EAC550440
+:101EC00060DE79207E19EC61F3EC47432530CF8941
+:101ED00022A7DF8DEB30B4D791CF160A1ADAEED2F3
+:101EE000D87A941B456EEF2694DD72C14BEBA0AC03
+:101EF0008C027EC57225A76F1DFE7D9A87E32A316D
+:101F0000FA073816ACB3F383C22CF40DF53705325B
+:101F1000B2DFBD060A57B3AB71FDF739432B508EC4
+:101F2000B5E785EEB0CAB3A7825C8E85C57AF7CFD8
+:101F3000FE762DE2E703E6F0A3FCD89D1A2279F69F
+:101F4000BB4CC63A27E23E32D53B02F99AAF43CAB0
+:101F50005FC2B0FD6397C31246021CEB7ED3533AB7
+:101F600019DE7F83F73B792D6B64F85EE1657818A5
+:101F7000C6446C7794DADD1BC8A379D9E37E8F075A
+:101F8000691F9AE37EA7B36E273E1D693F1CAD27EC
+:101F900090D3E693AD71BE17C503F2129C84B86E60
+:101FA00089E98E4F71FD42FE039D6EC4FD01A94F6C
+:101FB000E7C88C93A76CF43629A0121CF17407FDB6
+:101FC0005AA8DF22B31F73EA167D7D43E09170F3B8
+:101FD000383A8FB652BB74388FB26DE7D17D810429
+:101FE000E7D19555DAFDFC3D2F43FF0793F4FFC77A
+:101FF00044FDA1FDC3F4DEA313BEAAA66B8F6079D6
+:10200000CA18539E4043109CD70D33CBA93737E4F1
+:1020100058E5CFD427505EDCA84BA23EFF09E4EF81
+:102020002325A6BCF9D90AAC8FCA23B6F809945F58
+:102030005179C4E6DE8CF551F9C3EA1F47F91595CD
+:102040003F2CF804CA8FC002598C77EC711CBF6D0D
+:102050009939FE15E100EA250EB33F0BE3F8C9F408
+:10206000C8DE59DD2BF09CBB295ADFFDB866B133C1
+:102070007E354B7F02CF45B66D387BC7E483BC818C
+:10208000FC6ECA01937E4CFDF0D517C3BA01ED1664
+:10209000566A11EBBE44F5CC7EAEF7C4F4CBDF73C9
+:1020A000FD7BF0F5C7D768FE024E6F9FC3F86F5BEC
+:1020B000C737F52978DF4FF427DE5F6AF61CC07753
+:1020C0009AE09BC2E1BB88FE1FD3BAFDFC9CFA2BB1
+:1020D000C09B5A62B1032E417C8EB9C4E19B5482ED
+:1020E000FB5DCDF7FB698D99727C2AC13D800ECED8
+:1020F0009BFE8B69DC52BE6ECBB89A75BE64F63A15
+:10210000B42BB3B78BF24F25C125C63D4BFF1A7BCD
+:10211000BB68FF5089853E0781CF6FB2EEEFE720A5
+:102120004756D3F8E3F8F8D7C7F0789BF5FDFFFAE8
+:10213000CDCE49E7DB899E1A393D9D87BEFD75C42A
+:10214000EF56A95BCF243F9161E2FD1B380EBCEF37
+:1021500077C1FB88D88F5D45A16FE17B2CFA2659AA
+:10216000EC1363E14E842F669FC04005D6F3FE86D4
+:102170009DD6F3FE7B2537ED34804EE4206FFFD4EF
+:10218000FE97EB70FDF165D04BFE2FED7F36E82515
+:1021900013482FF936CE7FAE7101FE6EC2C3F39C99
+:1021A0006E12D43F4BE33ECDEBDB5D5C8F7D63D99C
+:1021B00007A4C76977AA0ED4E3CC73FD27255C9FDB
+:1021C000057DA432917FE127C29F06E3FE84E6ED00
+:1021D000E6F8EF0DC919A86F46F51616213B28A69B
+:1021E00057AD223A8AE955B75279B6D8E7D74BBEF0
+:1021F0005427E07D85E341ACE7DCED7B080E1F6FE3
+:102200009FA0BE97C6CBE170B2F48327D06E257A2B
+:10221000E53FE31C505E89BFA900BF73717136E8CA
+:102220002DFB5B255586725DBBB9CF77135FC4F478
+:1022300036CE87370ABAFF53C906DAC71B4F9BFC55
+:10224000BF97DA4F89DAA91B08FE37857FE26BC199
+:102250000D267C27093E95C3F7398C7F9AF0C33849
+:102260007E6A99E144BD0CEDCA2E36707F3F167E22
+:102270001CE8F71FD4CFC3E1AAD525D2DF43AB8E2C
+:102280003991DE57F4B284FE2739E832FBCB41D2D4
+:10229000CB857DEBE77EA1F8F629C1283DA5507BD3
+:1022A0002F9FEFAB45A1B420BC9FA5BF161CC1F763
+:1022B000C983FA68A8540A77E4A27D935E560AE5BA
+:1022C000050ED64F761F639BD1EFEBFEA1C23AFC01
+:1022D000D45A552C7E1DE0D25FA11DB9586CFA026C
+:1022E00016F5AF38D05F63F1DF901DE80EDE9BFF7F
+:1022F000904A7E97975AD04FE693C9AE08DCBF2A22
+:10230000520FE5D442B7D78DF3C83964E7BAEE036C
+:10231000FB1365D4226E5F3AE01FEAD1A9EB18D90E
+:102320006FF30C29ACC23C6ECDEE7FD1379E6A2193
+:10233000FB6E15F36A59F02CB4D7BBE2ECD7E6C9B3
+:10234000BA1FF174BCBDDE81F80854713BEC78FB18
+:10235000D874E4BF783BFA78723BDA40BBB92766A1
+:10236000473BD70EA21D1D0CDAEDE8D145A132DCAA
+:102370004FA66824DFF6CF9EB190EC6543666E6889
+:10238000DFFF909289FE3E639BE24777C331A7B699
+:1023900082FC07604FCB63689B18FAB7E60BF8FB2B
+:1023A0008B4E9522FCDADD63FC48EFFDCD6EC273E7
+:1023B000FF2D59E134182FD3F8B03505EA5F0E8FA1
+:1023C00042275BD4BE8EB7C3C17C32906EFAD96807
+:1023D000D681FBA078D97A7C3666FA0D7FCCDE9E5A
+:1023E0009FEF3570BCFA701AC37D8FFC8C49EFE605
+:1023F000330A39201D2F60AA130BD733CD89F85F1C
+:10240000CC742ADF00FC268DC5F9F20DA203E03B57
+:10241000F4DF6D98ACDF46F8788CD3077B40D98920
+:10242000F18AFE6D0F66209FED4EB5FB1BCCE75A7F
+:10243000E16FF0A09D3F6150EDFCF5048F9013E734
+:1024400021579AF87E727E3D8DF6EF703A271B90E9
+:10245000CF7B841FF8812CEE3F7928C8E54AFC1316
+:10246000183E1BFB5FE83901E7E5F6A0DD8EDF8152
+:10247000E5F3382F1F2639F32C5F675B9099F2E75D
+:102480009B41AE07A899E44F01513C8DEF2FFE7C94
+:1024900024E94FE0F8DAD312ED578ACA480EB95949
+:1024A00028C289C910EB611B47D8FBED3E5BBF9B7F
+:1024B000037CFE1385FA3FE3FCC5A78042A19DBBC8
+:1024C0005A0A4BD06E7EBAF492A4C6DA1D413F542C
+:1024D00002397A54C85168167180BEB23D13F600B5
+:1024E000FDDB8A7F08CAEB379AB4A3A8C31D69AA8B
+:1024F000A4679FD248F2A3AF5D0E37C33CBF6862AA
+:102500003DA5E3078E5BBB2C70F484451ECD2F7B6D
+:10251000D2034291B5E4771E94D05FAFB955E4DFA2
+:102520009E0CEF0385C8AFAFC9AC0BE05DB2A8EA63
+:10253000E8098B7C881F17E66306B0EC1B41EEC7E9
+:102540007C31E08E5C07F0ACDA268571BC55DB8E01
+:1025500039D15FB9625D1DD3619F5C85C714DCCF43
+:10256000F28097D639BF50668605AE6F4ED37A8219
+:10257000DCBFF33AEDAF3FAA47FD12CB01A796E9C6
+:102580002D88F921CDB8C0D3C15DA48FF664319AEE
+:102590003FE463848FA096EBEAC7388BCF4B7ED3A2
+:1025A000434195E6AD6BDD49F0A4CE7A9FE001DDB5
+:1025B00039E2183A10DF261FBC26F0DE26F09E0C0A
+:1025C000CF7F0A727F9E599E5FA664209E5F5754FC
+:1025D0008A7324E3EF85A5F6FD71FB2A6DE516ED00
+:1025E0006E07D2D3F15639EC96E87918F7ED34EC52
+:1025F0001BFAE9CD717A3258ADF57C36F76756A9EA
+:102600004C7099FBB3C2E0FBB3C208105E569456FF
+:10261000B946F2B85A37D036AB2FAC6388179776E5
+:102620004C4139966CBF80DFDCA516FDF122FCE73A
+:10263000434A2D7AEDE7EDDF87F946D37C717AF6D0
+:102640005F2BBE60D2532FCAD582985C2D2BE5E755
+:1026500041FCD394AB167D92FC9A163856365C0436
+:102660001C269F209F3643D3E00EC9897C12427EF0
+:102670009D80FAD91F367F211BF98675A7C0308E41
+:1026800052CE37AE59592EA48BBAF6F7153CAF008F
+:102690009F15844F2187279632F31C9A4374D1C02B
+:1026A000E9E2BF3BAE03F02C23389771382FB5B861
+:1026B000D3ED35A146842FA4815C4A477FBC57ECFB
+:1026C0003F1BCDFDDE1716DF3CD67A37433D70C188
+:1026D0001F3354D4036F2AEAD272D584F14D55B218
+:1026E000C537EB4B488FD1182B19C9CE19DF8C8F0A
+:1026F0009F0E8C771A142F35F5EEF878677C5C9373
+:1027000025897F0E8C77BE588D7AE61CBFEC55D597
+:10271000583CD335EBDDB7D8B503E39D9FC07A04B1
+:102720003EB39965BD7DA3D5EE08C0D731D2E3EFA6
+:10273000E4CD993C2D864738073C6E98A7B50CE050
+:10274000477D39B793E2C6163CBA080F1788478A07
+:102750006F235E5AA5F026DC07A5D140795EC7BC81
+:10276000EAA3DED87E46C7CBBF47F341FD57EBD384
+:10277000990310B239FB2E5607E5D443294C063D88
+:10278000F6907A17EDF7A1F732548CF7BA7D967D63
+:1027900010B8544CF8E48176D25F611F3D7989F618
+:1027A00051ED2CC573F67CF76F5751E808CA150F29
+:1027B0009CD7CAA4D8FBBED11C9FEF5CC5C29DD2DA
+:1027C000C07D047C6B6477E6B39D846FD6C8D03F30
+:1027D000D02A31F551FF40BA70A46D341C682FAE79
+:1027E0004C273BAAA5B191F0FD1AE0DBF072FEC2C6
+:1027F00038D559F8CBA40B268D387FBA88DF778C73
+:10280000E3AFCBBEA4F735097FEEBAA07D9D3B5365
+:102810001B5236DCBACF5A56D9542BDF1A222FC599
+:10282000A07D341631D69535508FBA4CE4A5C078CA
+:1028300023B1FFA83226FC80DA282C5F7F396B4C4D
+:1028400094F7E2ACE076CC3250C1C9AF62A4B2AE2C
+:10285000296865ED787B04EE9771958A65A61E0C54
+:10286000235DD589F51FD9B2B30FDBCF074C621EAC
+:1028700004BE7558F0E32FCBA5718BD61C3BAC5230
+:10288000B5F7288EE702E18F76EA327C89E382BED3
+:102890008AF175A6E86C21C8FBE56BA5B771DC5A17
+:1028A000238DA15D1BCBAB782A2EAF8297E7E788FB
+:1028B0007AE3FB74FEC4E298FBE2CEB7373A6D715F
+:1028C0004CE3D84A7B1C93E7DB98E7D99197FE65E8
+:1028D000A5A158E398EFD3F8479799F315EEB2C73F
+:1028E000313FA1F14D3F35631F765AE3946049D1E2
+:1028F000F96AFA91FF5C36BD9EFB4DF585B83F72D3
+:10290000506A44FD080E184D227F8DB713ED69D033
+:10291000FFAFC7FABFF575821E727B9925FEF1B72E
+:1029200006FF31D3BF6F1C5AA9155CFAF002BEBF77
+:1029300045F8AEE4F8FE1B80F7BB6509E20097108E
+:102940007C2F117CD138C47F3B3C6F9459ECCFCFA6
+:102950007BBE1933B51338DFE7B08E536596FC8321
+:10296000F368FFEFD45EC44BE3EB6F2FF7723F9633
+:102970008813BF198DE365D6C7C5F528EE158B23DF
+:102980005E3E3630CE0AFFE5BBB0BD19479C5D9E6A
+:102990005B4F79D149E2981AD62BD6FE2AF5EF88FB
+:1029A0009BCF25EA17955F536FD8F07335B5EF8944
+:1029B0006B5F2BD6B7B27CD22EC3820FB038A97D05
+:1029C000542EB1E9F5F6B8E3D47A6BDC714DF9F425
+:1029D0005D66FCBF1CF1336E403EC4FF487C04CAF8
+:1029E00085BD29E2E5261D8E9EA195944FBDF4E09C
+:1029F00085FD5B526EA1FFBFC27CABCA2D79171754
+:102A0000DA3FCA8FE2DC37F32700BF77E03A6EAFD8
+:102A10005009FFF1F912A69D18EA676427CE646198
+:102A200019E31221BFCED00F1AE56B43AB277F5DB0
+:102A3000F47E44E52EFBFD88E65DA85FC4CEEFE79B
+:102A4000EAED790EE536B8B7BFFC9CB9EE96724B4D
+:102A50003EC3608FBFA6C28E976859E067E91DDF4D
+:102A60001C6DBF7F11DA45718CE8FD8B9B68DE58C9
+:102A70007EC7ADBBECF91D6BA91CDBAFA6B8FDFA98
+:102A80009A0DAE8FCB9B082E97C87B73AD9292DCCC
+:102A9000AFB891E48219D785B24D2E50F97380EB0F
+:102AA000804947824FA3700EC8CFABDB857EA6C19D
+:102AB0009EDF22175E42BA187CBCF3FB1D26DE9314
+:102AC000DDEFB85135CB5FA96F28F8ECF362FE5FFC
+:102AD00079C2FCA38B5D07BF2FE28ABF2FC2D6D776
+:102AE000DBE5CF79C3773AB1FC39BFFE9F24973F2E
+:102AF000FF89F2A725DDE1423CEB3EA68513D8C74E
+:102B0000B757F0B854943FC57D94EBB727B6A7BF2D
+:102B10005CC1FDD7A6BF3BE03AB5CA1A071D26EA3D
+:102B2000BD15D1BC016F058EBB8EC33706E521C62E
+:102B30007B98C234E0A945D78FCE41F85A7ECDC7E5
+:102B4000633EB0933362E3CD14E399F3EC5B9051B1
+:102B50006BCD6BC811F38CA9904CFFF4980AC4E7B5
+:102B600046BE0E79C81ABAE715B5AB8D87487EB553
+:102B7000394D3BFBB15D24CFA272E89B44178BDD3E
+:102B800026FD877759FDC6653FDDC5CF5528621CF8
+:102B90002FD6EF1BF564E79DA3DF6413CFAD62BFB3
+:102BA0008CE87E4D41B8CFD5DF624747A4EC981D35
+:102BB000FDCC646D16E219ECE9E2F31907F014A4F8
+:102BC0007D596BB7472CF51515B6BCA4536B30AEC9
+:102BD000992C2F6961C5D9F39216C6E86161854DBC
+:102BE000AF0F664C453FC94847C27B14BAD8D75887
+:102BF0007ED77768BFDA4CBE13E507B278FDF29F47
+:102C00003E532FE0BFB9C212BF30E32DACE06004E9
+:102C1000FD3C96FC22CD61F5FB048F3971BC15ADEE
+:102C2000D2F9F14BBB187F5B741F6FAFE0FE681DDC
+:102C3000FD8E378A498EDCDA4CE3D6AEE2F7C2E28B
+:102C4000F9E65EE1A7BA3746C7F7D2385A34DF66ED
+:102C50003DE20D5306DC9362E39BF77B02CED08FFF
+:102C600030AED366482ACA577D5D1DC51559256308
+:102C7000E3619F0223F3B6A1E830E7BBBC92EF17F4
+:102C8000FC5A8AED7C20218D9198275E4771E76977
+:102C90001ACF5B995EDD2C0F5729AFA503E72F5A9A
+:102CA000B4B305977DC3B2EFCA89F2597A309F0554
+:102CB0006132D8EBE346007F0BF8F05EC85A98E724
+:102CC000CD683E4B75D93DD67C96D067CB6731FD3C
+:102CD0007F4B4B00AF16FACBAAE478CDAAE4788DEF
+:102CE000C58119C56FAF60B573AEC2BC14BCB70562
+:102CF000AF7B0C7ECFED4C0E0B63FCBF79762AF9CF
+:102D0000F1FAB318C5556143326BA6611E09FF493C
+:102D1000195FCA30CFC50DEBC275605C3672250CE9
+:102D20002F2F1B124940CFBFC8D4993F1DFDFEC6AF
+:102D300066067413D41FA4F8DCE5ABDE6FC07957C8
+:102D4000E86E1549E0C6066F19E571ADF13BEF81FC
+:102D5000F7F37D32D3D09F5DED3CCEE3341EC2D37A
+:102D6000FC525E36F1E266CA712B5E94B8F2BAB7D5
+:102D70009AB71CB0B477455232302EF85285C80746
+:102D800012F78A989C4E7470C6E708631CAA4761C4
+:102D9000FB158C63E832C515BB5AEF3C8C7CBBC27B
+:102DA000A7F81DB0CEE03A89F2BF6EF4723C7DD830
+:102DB000646C39003A6CCAC83C8AC39CF17AC81B5F
+:102DC000DFB6AC8BFCF6402F3D0AB43FB69EE7174A
+:102DD00099F94F0B04BD98784CA9FB80F07206E37B
+:102DE000E18897C22CCA839A07F850BD14E76F4553
+:102DF0003CA5B2C6C830186789CFC122163F34AC93
+:102E0000DF9647066353DE99426F6CF5849FD4F5D5
+:102E1000419E8F26576BE89F3F53C8F715CA7EA483
+:102E20007756CAE9D4C47F6A1C9DBAE3F2C3E2E9CB
+:102E3000341EFFA711EF96FB5C5D0AF34790DE7A24
+:102E400065D22FA279570F3928EF8AB130DD63EAB6
+:102E50006243FD1D28372312C5096E107833F1CE69
+:102E600058E3E695E8E76ECCF4A3FF9F391A376381
+:102E70007ED48DE134CABFBB8975531ED472B49021
+:102E800061DE9B99D785E595CC4F4F8915D0FD9292
+:102E900025BA447CA1B348CD5580BFC865CE2C6B04
+:102EA0005E55D2BC2658F9BB9678C4D04A212F3D36
+:102EB000BA8FE779EAE2DE8F46F9415965A51E3DF2
+:102EC000C1B931BB481F5969C9BB50BC8D8CE2D315
+:102ED00045A151955363FD9F9AACE554C2F85F2C10
+:102EE000D446E37337EA79701E040F8E7F12CF83C6
+:102EF000E6C99A8AEDE3E5D5B1E4F9771AF2751FD0
+:102F0000CA2BCA232C203E1CACFCBBC99503F2EF94
+:102F1000A6565AF2EF8E3AF9BD32CA459EC906DE70
+:102F20004F5B7703D59BF7D3E2EFA5B1C7781916AE
+:102F30006474801C6F311A69DD26DEE3F1C3C4BD01
+:102F4000B4A5BE97FBA46B07216FCD0BCADDC8B338
+:102F5000D187C1EF2FD7DCD987F13A83299447D89D
+:102F600096CBEF2FCFC385E23AC6717D9055F1F332
+:102F70006A4B56A3CF0FF55B9C3C1F86E5EBECFA42
+:102F8000099671AB64332EB402F1097A1FE94BA69E
+:102F9000BE6AB6AB17E7C26A712E3C3339740BE1D7
+:102FA0003F96DFBD1AE988A547C20E336EC77F285A
+:102FB0000E64EA0F474635523E8D3BC97DEF3B2BF1
+:102FC000A3E7F99D34FE43E679AEDD85E35F37CCB8
+:102FD000BB08F9CC159459279E63F36F27B9FB1CE6
+:102FE000E68D824E335D6F0E8E80FD6EAA14F1A6C3
+:102FF000862C4417EBD1783E69A4B8D187E7DD96DB
+:103000009189EF7DBF2AD63965CC2919C7DD028A9F
+:10301000CEA689883F83F2D88CC5204BA00CE6FE53
+:10302000018CCB78500F28C27391B7F736401BD86C
+:10303000876EA12F04AE00FA41FD6BBC3D1FC97C19
+:103040009AEDE2F3AD409467E0BAE3F3DCCC7CABFD
+:103050003EC5C8F027807F7ED95A0FE56BE5ACF4FA
+:10306000E039D9A60569BCF8BCB72D396C34C21556
+:103070009FD766E64D99F952E6B8FFA7D29ED7E6EC
+:10308000F6F1730B9E9427F39D4A957F9742B3E721
+:10309000B799F935D89EF26B7218CFAFF13532EC93
+:1030A000E78632B60F89FCB3F8BC2A9043DFC57DB2
+:1030B000BF50BDA92DA6376DAE1B44BDE93CE4EF62
+:1030C000CF10DE04F2F7E7C41F31F97B08E91BE4F7
+:1030D000EF617C9AF2E5CF959B48BE6C91387D6E8E
+:1030E00081FDF85E8279FA049F6CC94A4C57A704A7
+:1030F0001D374F0EFD1AE7D5B2F9BD8F4B058F80F6
+:103100008F3F5AE537E0E35F13E1017E5A519E5845
+:10311000F24FFF9DD69324FF34BEFFC5DE1F5640FD
+:103120009EF0EF4B685215D989AAB0F751A8602BD1
+:10313000F31E6E9C1C17F5E792E3BD0E90AF000FD7
+:10314000EA0A56B93FAC8AEFEB3533F56155442FA7
+:10315000FC1EF0D600BF07CC221AE9034732F45A0E
+:10316000E45F963FE91CE746B3C8B3D51B4224FF92
+:10317000179EA3FD266A7FCD4C55F8C187D27AB63B
+:103180004ADA3752E558F95CEB4BABD2F2ABD0EFF1
+:10319000A187E83B0A5BF21DAA014BBB6FBA7E2DEB
+:1031A000BEDF92BF89F6AF03084E02793ACF71EACB
+:1031B000FE3C89F2849F9786C0D303965C02BA9E38
+:1031C00029F0033A08D5B3B7349FD5FFB1BA2AEA3C
+:1031D0006F11F6EFB79FB4E6092CFED9D3AB0CCB39
+:1031E000F9867E94EF25A08BB22ACE3FB2FB4EDB50
+:1031F000F919DFAEA28ADF0F595225E206E23C5CE4
+:10320000ECE6F6153B04F059CEDB6B6696CCC5F5C3
+:10321000039A0CC9724E9AE722D558DEBB7DFC5E3C
+:103220000AEBB58F63AEF35641A7E6BC40AF3770EB
+:103230007AD56AF169D62F9619F783F4D8F105F09B
+:103240002CE774C64E2481E7C984F0F4D9E1B9357E
+:103250004AB7DAADB83E38AF1B70DCF612A0BB043B
+:10326000F89D30B5640DD62BCC68CFCB3DAB3CBDC3
+:10327000BB2AB13CFDBB2ABB3E7B4F1597A7F75637
+:10328000911C493CEF2681B741FBAEC079EA6DF74E
+:10329000E1AF09F8A6A3FFD9B46B81D5DC6EE36E6C
+:1032A000E2CF8249E7E02FCECF378F69243BFB473F
+:1032B000423FF99193299877033CE64F940FF462CB
+:1032C00095A98F8447215E5E48A28F44DB25C9BB48
+:1032D000BF92ED48BB18BDA463D69134D24B4E7754
+:1032E000A6E1F9FFC28992847AC98F72768C4AA4CA
+:1032F00097EC49A297EC15FAEB8BBF73919E517C2A
+:1033000092EB25C52777C8A85FECABE272BBE84417
+:103310008FAC03DCC5A897C0387B845E82ED492F53
+:1033200039BD4346B88A4EF650BF6228A35E529418
+:10333000442F012864C4C3F3C51DBFC4FD8B5F6F58
+:10334000F514FD152BDD16F6F790FFC7ECD791BFEE
+:10335000294DA7FDB6D3CFEC22D596375FD8CFE95C
+:103360003DBE5D323A2B93ABDBFB615D5B59C60E14
+:10337000CAD7541A9FC0B2612894C7851FDE40BACD
+:10338000B9773EC09085ED1A9FEAC7F3C5707BF10F
+:10339000BB071FA6AEE076D05AE675CE8CC9235A7D
+:1033A0003A80669488F15C1E6F0BD8798FA4651201
+:1033B0001ED7794D7FCF8ECA3CE87FEF95E3E85E5C
+:1033C00050C98330109467F6CA546FFA870E8F6421
+:1033D00094BF0FFC3BAF06C69F2EC687F34EBB1BA8
+:1033E000DA2F2E747BD1EE2E97D3A9FD7DF9BCFD8B
+:1033F0004CE35403968BFA5D2ADE3F63F246F90EE6
+:10340000F4EBA25E02EDEFFB61A8CC03F5A9470047
+:10341000121CEF2D17F93734F887FC3BB5B79BF03A
+:103420009976C265F37BA482848B58F417575C9914
+:10343000C9CB8624924FE633DE4F913247F829AE4E
+:10344000655FFC14F4AD336C633BAED13DBEE4C5A7
+:103450005D6C607FD30FF12F53B42173601FC739A8
+:1034600075B26BF65402AE619FF63CF4D0DC6B1182
+:10347000EF3B14F2FB1EDD9046FBB4F7416527FAE3
+:103480009B8E029F72FFEEFA5B905EF76630334EC2
+:103490001441BFDDDEE87DE7E1B76896F2D8572634
+:1034A000FE0ECFC3BDC3CDF60FF3FE66D9D8760BA3
+:1034B000E675EC1DC9CB35AF3CD365101DF72B6409
+:1034C00077AF7B273D91FCCC9FCBF9CE2CCF2BBC8B
+:1034D00093D3F139FA81BC9F382741BF941A6E7F8C
+:1034E000ED5D06204D443CE9D3E6009FECE9BBAB23
+:1034F0007D024C3565D6861E92A3C3FAD72692FB71
+:103500006573F8F914290E933D06363EB787997214
+:1035100000F35BE7317512DAFDDB67BFF0F36B6137
+:103520009E5F148D9F2427E06B7D4E5EDCBA5E9318
+:1035300057A25C7AEFF8A24472606B953ED7BE1E2C
+:103540001E3F6DD9A110FEBF3CF7F49398F71E29DA
+:10355000DE41FEBD3D7F74B04D406F7B2670FD1F88
+:103560006FF0C9D98302DF43D313D01DC077732214
+:10357000F8AE9ACB689CEA295A1DD6C7C3ABA21FE6
+:103580001CE00535CB8F7224E50FFFD083FECE3DC6
+:10359000FD0E72BA9C39D129230976F4E595A2DA99
+:1035A0007A5DF5311949AAD8FBE0660C0DEB1B6575
+:1035B0001BFF4DEF4BB59597370EB39597368C8A19
+:1035C000F123C37B42636D65B7EF6A5B39C026DBCD
+:1035D000CA8BAA67DAC62BF3066DE50ADF5C5BFBD4
+:1035E0002AF57A5B796EFE525BFB1A7FBDAD3E54C5
+:1035F0003051C12B7E40975B115F69BD1AF1F9967E
+:10360000BEBBBC481791E210D9DB47327A72D09F1B
+:103610007D38C977E77E394716E73BA8462827E17A
+:103620003CDF94156B1FC8EBB7F9EB5F98C3F5D47B
+:10363000EFCF89F7D727BB27C7CFE7F3BD1F177F8A
+:103640000ECFBFEA2E924B1D8BE430DEB76AC97FE6
+:103650003DBD1FD7B388FB193A72609DE994AF4115
+:10366000FCF5E2E21B4663DC2D355F1F86F2DF3C92
+:10367000BF83F961F60ED4A77AC36C2CDE3F837248
+:10368000BDB887162CE0EFAF10EF57E313CEED7205
+:103690000BBEE2CFE38067E24B6036B0D97FF6D253
+:1036A000F7FD1615707F50E9E97029DEB79EABED86
+:1036B0003BC0AF5573F9F38BE2FF9F9DE4DCDE372F
+:1036C00067AA9D7F901FF69C587856F9FFDB26EE7F
+:1036D0007F7FAEC9C322B0BEB79ABCF4FC75938F8E
+:1036E000DEBFD6A4D2B3AD299F9E91263FD5FFB2AF
+:1036F000A9909E079A347ABEDC5449CF834D216A43
+:10370000F74A532D3D0F35E9F4FE777318D1C7A55D
+:10371000028F966FFA15422F3A24C2EB224CE59D98
+:10372000715293ADF21DF0FA5E22BC5EEC391229A3
+:10373000EE1E15E2E756423EF2CC35EF8D713D7933
+:103740009E4E323F0A9F0BFD77D931FF9D1B559A44
+:10375000A104A73477F8E0C1B957F871F666B1DA79
+:10376000EF717BAA55A2F3C63B91CBF347432524C7
+:10377000CF874F4C2CCF7307C8F33A3AB7D841F4F0
+:10378000AB62DA110AE3069C7F6A42BF883124F7F4
+:10379000AC78A078A68907CB7EE5CDBD88FD8A5F91
+:1037A000FFEC22ED2AC427DE53710E1D788E5CD10A
+:1037B000FFB186BEA9E70B38BCDB8F2F1C82FA8ACB
+:1037C0001B9D52A4AF80E25688FBCD843EF2685721
+:1037D000C3AC81E3FCB6B89BCEF5FBA27ACE3F9199
+:1037E0009E13DF0E7E0E101EF0DCB2E021811C283D
+:1037F00049B4FE32F987FD9BA0FFDE7E467E33157D
+:10380000756A80FF05857FC761EF4907E1F98C473D
+:1038100022F9E85E7FB7077DDFCF7F8DB7336A245B
+:10382000BADF90B67F8F8A7A6AA05F1F86DF232B6C
+:103830008C5439F1FBA125B326FA532C7450A2D82D
+:10384000CF49D454A3E70E39C586C6952F8BB597BB
+:1038500071FFF362E55CBA97BD1CD7B5F0542353F2
+:103860000B84FF35319ED64816BF9BC2FCEDD37347
+:1038700049EF3C7019C675C6B3307D1F02CC8390EA
+:10388000C59F20A787E8DE9E69A77F2469B7E17CF2
+:1038900003C66FD0282EC71C0E8ACB6D98ACDF896B
+:1038A0007432206EE37DF92F129C69ED0E1641FDF6
+:1038B000C2C87411FEE2F7EB8B8555F7E03CBECF32
+:1038C0006CD7EF90ACDF11B842BD8EECA933604FDE
+:1038D000E13D951685DF9F32DECA087711902C1FD7
+:1038E000F5B67BE5ABFDB8FF8FA4FD3DD947EBC036
+:1038F000DE42FB6B9B90C30FA01C86E73627B7B751
+:10390000DA9ADDDECE6CB4B7320D071C5C1FA68CD4
+:10391000093358E723426EB9D9F221A10967815FC3
+:10392000D827CEE8BEE778C9DE10E57497EEF81325
+:10393000DA7547E430FADDB64E7CAC7625E26FA24C
+:1039400087C7459588BA001534AFC1B22DF7FB651E
+:10395000A6BC8B7EDA76506630FE7BBFB89F9BE1BB
+:1039600077D8F49D2185767DED3B8304B70B251137
+:10397000DAADD9AE30E6E9A828B700EE769F83F835
+:10398000AB55E5F2A1355DF37813ECEF16C4B73B08
+:10399000F9FC726EAB17FDDE3BD21DC4BFEDAAB2BF
+:1039A0003517CAEDE90AFFEEABEAA84C94C7F2CE90
+:1039B0005C9EC7024D52284F2AB090F49D64F37468
+:1039C000887D37CBA905BA467CA6FA43B89E96F403
+:1039D0006C09F7C5ACFFF15C497C6F81FB95B70AB8
+:1039E000FD2935BF3B827E9DB691AB2723BA3CA013
+:1039F0000FBD0BEF3D05DDA43FA55FE6D213C1FB74
+:103A00007B31DE56A7BF12F1B935C3C10CC0DFD67A
+:103A1000DC2471AFB95C8F6C51278588BE011FE330
+:103A2000A581EDF68B7DDEECDCE1C3FB6C5BC72F83
+:103A3000A17CB1ADA3B97CFE4A755F577301F2CD8D
+:103A400057D89F906FB215DA3795F93D78CEB57992
+:103A5000152FFA05A664DFE30958E45C3C9F38475C
+:103A60002EACADA37C82543F22BD4C3E44DF1B698B
+:103A7000F383DCCDC57CA646AFF53B02A0777F84FF
+:103A8000F2E35C74AA32DD83F885F1898E92ED5FF2
+:103A90003C3CE92899269DA57D965E9BE83B16F95E
+:103AA000D50E1BDD38CF4137E782DF762EE6C4CE58
+:103AB00045DF21DF6A8C77DCCF78FD65D5EF75A116
+:103AC0005D1F5FFEACFCD9A2EC20B9DD32CE45F41F
+:103AD00014DF7F6B2E87E7E8CF7F4FF3A1FB01F761
+:103AE0002DCBC3FD4D0F140E4D492497CBA6E8FEF8
+:103AF0006A8B9E9355DA4DE76D4A3523BA4C57438E
+:103B0000DE71304E7AAF0C340AF8767CFCE763EA5B
+:103B1000C5E351D9D1C842305E66AF4CF4893F1F2E
+:103B2000831C1C22E4E096CBFF95615EC9F6B18A46
+:103B30009FE7B3BCE73FDB799239CBEE4FBA507FBA
+:103B4000D1FC6A91DF90C252783E51758942793C2E
+:103B50000E7ECE6AF0DF08212224B1FF2378C89FB1
+:103B6000CE49C6FD64D9CB18C9CD685E0B7E9706D9
+:103B7000C7D119E92378B116DB5DB686EB5B39ACAA
+:103B80005FC278E0E598DD2323BD73F97986E538D7
+:103B900028AF07A6C1BC14C970D0B9F8F0E547A595
+:103BA00000BC7DA068F544C447FC3A1A06ACE3ECBF
+:103BB0007830E11C6C3A35CFEF160F3F8F3538B8AF
+:103BC0005350598EF37F96C91BF9796CB8BD785E56
+:103BD000B7288DCF60197A87C85F1AE7FFFC308558
+:103BE000FB47A57B98572A22FF673EEED33A96EA19
+:103BF00047FFE41045F7607DDA3885FE5E03E8DDB7
+:103C0000D331DE12B3CBD5749E47B78EF20D7F82CF
+:103C1000E71AB4DBFFF1D9E5D1B3E738D73A7AC771
+:103C2000A5937FDD539F86F6F873BEBC4368DF9C87
+:103C3000F1F03C30B3DDFEB8EFA2B40939F76AB554
+:103C4000F0A3A77C2863FFEB7CAA82F976259E89E6
+:103C500024DF5BA4C4F18237847CBB427D95D3D939
+:103C60001AF37B666B48FEFF2643D06F83BE94FC3D
+:103C7000CA42DF639AA67AA7C5F43CF3BCF4295E76
+:103C8000E3761C47E4610D58E7FEDB187EA785F953
+:103C90002CFED93C9C7F4834FF8EF8394EBF4B86B2
+:103CA000CF0E611FB7F84A287FE30CCAAC04F113AA
+:103CB000F3097AEA4F514E4DEDB1CB97B47CBB7C02
+:103CC000697734523E987135F362BE08ABF6FBACAF
+:103CD0007A32E8AB87AAC93EB5EB9D6B6A18FFFE46
+:103CE0007696AAA09F26E809308C4B28393AC3FD66
+:103CF00070F9FC67DD8FAE6AAEA7B4E5AF0CA15DCD
+:103D0000B37DF697082F532A797EAAD90ECECBA37E
+:103D1000D516FBC6E5E3FAFA797F67C9EBB8A0EFE1
+:103D20002C75CCBA857F67C9B792BEB3F41CD02579
+:103D3000F2CBFE0C3D0DF5AF0BFDCED22D35E23BA7
+:103D40003E293C1F45E9E3F107A54FA7BC1297EFB9
+:103D500014C56FAE137928F1FE22B7BB91E26D91C5
+:103D6000E2C6A5567FB189BF2E41D7BF2DD6295FA8
+:103D700028D9DF8930DB21C6705D6EE10FDD52BCD2
+:103D800081F0BFB0328BFC518AF047B94EE9941FE5
+:103D90001C9EA267D658F0EFCE31E8BC4BFB7BC629
+:103DA000EFC17FC4EFC1A76D622578EFBDE4E349A1
+:103DB00014A72A89A4109FCD3EEDA7EF5897C94FAD
+:103DC000B7E741FDFE5E85F2F2F6CF4ECDC673ED4C
+:103DD000835EAEDFA6EDBFEAD017A15CDC5B8F3E51
+:103DE00001903B00CBD081EB987DDAF199ECCCA926
+:103DF00068675AE225E6B83F683A48F4F16C530F19
+:103E00003DF73445E8D9D1D447CF42450BE27A0A91
+:103E10007B2876C9669C807A0B1C856F417F0B3DA1
+:103E200078A7E8D36B88FF7A6CEDD2F2FB6CEDC01B
+:103E3000CE9D89F8557C1C9FAE6AFE7738E6F7B1B7
+:103E4000CD92FA3F4A5E2D473C0C82BC5A597356BC
+:103E500079C5E3A9257DE27B63A6DC12FCF8976AAD
+:103E6000957F37C9E44B115735CFE976FC15CED392
+:103E700096CC2F71F966E66F887B8CE6F7EAD7D788
+:103E80009CDC8DDFBD6B7BD3ACFF78B766A967C6C2
+:103E9000BFADC6FB28FBD0B8053DF4B7353F5E8DFE
+:103EA000FE8625B5598A06F00531009B15BB476390
+:103EB000E63BC6E3ED780DB7878EE479C90FDF06E0
+:103EC0007BD29900CF2FD708BB4DB5FF3D90D424AE
+:103ED000F7872262DC43026FED2E9EA790EC9EC80E
+:103EE000D745FB64F7447E5523E2F5E7B817F21D8A
+:103EF000D1EEFB38EF70CAAFFC27E423F3EF75FC7B
+:103F000040C013FD3B1D3E96709C2E217747CFE3AA
+:103F1000F9C92E9F46DF4583F19EA2F1C4DF5530DB
+:103F2000EB679C8CD6FF33D547FF7E824E7E22F313
+:103F30009E5ED7E1D776372BB1BC9CB6E8F71679F1
+:103F40009ED3FB02FEF8A7794F25F65DA9C3BB35CA
+:103F5000CB77A51E3FDCFBAEF8EED55EA25F713FCE
+:103F6000675B0C0F3FA6F771DF19D853F3F26EF1C0
+:103F70007DC5FD047763DCF7BBD8D1DDD6EF266CB9
+:103F80003BFCD66AD1FE20B517DFFB4A4017826E94
+:103F9000FB77E3BDD1F318EF75824F7CAF6B630DF8
+:103FA000E7A364F40CEDFBA87DF43BC6F51E3C577B
+:103FB00062DF317E83F0731EF83A46E3E8E6BC4CDC
+:103FC000E443717E31F3C94CBA90E7713ADD5C236A
+:103FD00099F796FE407858356878F880E089BB9F5D
+:103FE00074AE753C3339F411F5F345F394FF83CA8D
+:103FF0009F111EF35E593C7F0C9D2799F9D129F33F
+:10400000709E9CE8F73C53E725961317342F8C9B42
+:104010004DE3C6BE133A7CDE20AC87A9E7975FF27A
+:104020005FBC10FE351071000000000000000000B1
+:104030001F8B080000000000000B0B146060F8519B
+:104040008FC0DC687C5AE3BF4C0C0CFACC0C0C978C
+:10405000D81818DC38191844F8C833E7329ABE87E4
+:1040600040B366F130302C636560D809C4865CD8F3
+:10407000F5D90922D8C7817E5F05C497E91C06A33C
+:1040800078F0E03A11068629A208BE8118AA7CBD04
+:104090000882AD2745995D2E40FD00C5F694E2806B
+:1040A00003000000000000001F8B0800000000005B
+:1040B000000BD57D0D7854D5B5E83A3367CE9CF921
+:1040C0004B4E92012721E0991031D840074C145AE9
+:1040D0005A27116D14D4887FD17A7B07DB228ACAD4
+:1040E000D47A956BB199FC4F4280008A142D8C3F95
+:1040F00054B0FA9A2A5AACB577A2146DF55DD15A2C
+:10410000ABBDB42F566BAB551B5B29F415E5EDB574
+:10411000F63E99734E66328348DB173FBFCD3EFBB8
+:104120006FEDF5B7D75E7BED3D0A5441D569008749
+:10413000F18FA5F7F900A03E93CEFAC605CB1EACD1
+:1041400063FFF6B923DB5832EBE97995B1DA4CFD20
+:104150007A90002600343E7DF91F81D5FB2F70EA4E
+:104160006EF6E9C9C0882FC2F209C909D8CE0D0D73
+:1041700065E70459F94147A48FE5D3871C7E60FDAC
+:10418000CC04278DA383E66F9EC1BECB171483A9F1
+:104190007F7BFAF94D32A4CB009EBA05E46656AF98
+:1041A0002B70EAE5C37E80E75BD37F7DE304806804
+:1041B0007ABAACB37E76B73E43F91FB7EEFDEB1B80
+:1041C0002E801894D0388DF3DE9717B3764FB9A0B0
+:1041D0006590B56B8C4AAEC5A6F162623E4F7944DC
+:1041E000B9D620672D0FB072F6BD31787ED6F218A1
+:1041F0009B11D52B11FD1C1C76623D1D467C34CFD6
+:10420000438BB2CEF338D1CEC8D70DF3F93EF9EBDC
+:10421000030B900E69286E76637AA86A1FE27B48CA
+:1042200095740833FC0E9F4DF84D237E5917075E99
+:10423000E3F87EEA4347A48DE1BB51D5FC11960714
+:1042400099D1839537FA214A70C92C65702C10706A
+:104250005F2AD24598125D74A2CB90CAE8E2CF0FD4
+:10426000EF699B1482D798E710CEB38076065DD9AC
+:10427000577F7380B583EC7C30163F6CBC938F1CEA
+:104280004E03AFCDF386FEFA860AF47798FD7F865B
+:10429000F6D3BFBE5193C99F7670AF25CF381AD4DD
+:1042A0005318BCF84F1D53F98361A33CCCCB719CD0
+:1042B00064ABFE4135E3BF8156F8A09AF1DF9A5610
+:1042C00095F2FDAD1AE5FB5A43944FCAAC09A363BE
+:1042D000B21F5209D6BE24CAEA9BC62B9EC3DA99E6
+:1042E000E00B44344BDE5713B2D4F7E8BAA53CA92F
+:1042F0005FEF4831BAF7D63A524E09E16032722286
+:10430000C2A152CAC07D39C4E653CD9BC06A97FE94
+:10431000CB2A84E70527B4B37C911E755CC1F253A8
+:10432000424E4845D8F8452300ACBFE42D00EB5978
+:104330007FFDB34E715CC1F27D73DD9A530348B1CA
+:10434000FE936ED6CF4769BD03FB99A144B01F18F9
+:10435000907F8B7852D97F87AB00A6EACA6B8E22FA
+:104360008070827D37CFCF9D08A15C17CFB17E9F33
+:10437000AA2FB91658FDA960FA1ECED0D318D7C8F7
+:10438000DBC7B38F73FC0A5BFFB67EA7E8C30D5A89
+:104390006DA6DFE361A44DF3FF2BF71B6D94904EE8
+:1043A00011D053B38E1DDCFE157F2979E3E40C9EFA
+:1043B000FB5D5C0FDAE56D181CA43F409E005106C2
+:1043C00097AE3B527DAC9FBEB083F847EF8214EAB4
+:1043D000ADD593F7C631DF1756F476960FD7EC6953
+:1043E000916602AC9AAC11DFF53DE186F6088723B1
+:1043F000C8F8748AC1A71F0D3754211F4A1059CF1E
+:10440000CAC3FA9B6D585F7BD9ABBBE68C9D1FACD2
+:10441000E0F3A73C9BFF08FEA37E6CBF3FAB57A217
+:10442000CDC8B70948B9193CBDD5ED4D0936CE9672
+:10443000840C283F7DB70CBE82784E9EC0E1B5CF7C
+:104440007B8AAE2C46BE06F3F86CBC29D5172FC369
+:1044500079D9E130F4C59DAD1A4419BD36B7D6906F
+:104460005C6E69D506514F6CFED09915BF0B24AE1A
+:104470009FEF70353B12B8CE4E77A4B649D85F6C2B
+:10448000F3550CDED5F51367E33A70FD748EEF0F2C
+:10449000FA05BEA5D4A540F5159DEADBE47F8B1C8B
+:1044A0006D47795E1D2A8304C3EB14D7DEA6A99855
+:1044B0005F51352B8178AFBBFB35EC6FCAF4693A9D
+:1044C000E2636ACD9BFB502E377F9422B99D5AC37D
+:1044D000E49ACD73CA8A8983D58C4F2AF5D4D7A89C
+:1044E0007E8DA2A7A40C5F4E86483BD2EBF8161F28
+:1044F000A4B5FCFC39393E3E7F1E3B3DF08F91ABAD
+:104500004936B9BA23875C2D941CC42FA37255C3B6
+:10451000E48AE175C74956B9DA3C39F55631CACF54
+:104520000CCEA7763E0FD7BCD98074ED67F2531A34
+:1045300002A8700FFC5942399CC5EA4B542E7D9954
+:10454000E5FFF40BAF0E284FB59CAEF9E4CAE0E7E7
+:104550004C6A1D774B9DA3B19981FAB3AB36BEED82
+:10456000C6F16A151DE5AC4FDEF467C4B35EAFE873
+:1045700009C9244FB55C9EA6D431F9C92257F9C6A2
+:104580004FB6A6E0752647EB5A43245F6B5B7592E6
+:10459000AF5542CED660D5B92C2FE40CE6CCA67C24
+:1045A0002EFB13A08DE44ED5F702DAC1EB58DF5095
+:1045B00081DFD3D1E83C80D23A230F69075BDBD798
+:1045C0008E9643142A09DF009F41F0FE9888B2F6C8
+:1045D0005A1DCF3FDEF6C7440713C2751E5EFF09A2
+:1045E000A9A62131CFDC7E0FF56FD467F97463B5CE
+:1045F000A93FECDF028FA301EB1BFDBDDA56D19082
+:1046000060E3AF1579A5BD84E78F71FF4CDF841897
+:10461000D3439FAD9FD592E827F16C34EACF8C73DA
+:10462000BBF456346129FF4314F164947FB7EDD98C
+:104630004482D57F1F9ABF25313A4C9F1FAB605BE8
+:1046400018F036ED0534A5D6D9F09D99DF0B34BFAF
+:10465000400DCFDFDDF66114F16D943F2A05DA10CD
+:10466000DFC837FE89CCAEC27FB23157FDE4474B7D
+:104670009FC37FCF29052867E3E803CCD264B3AF9B
+:104680004E01EE3B7C35F29BA3FC0719BE63F03D67
+:1046900028B174FABCD865B81466812F6186CF182A
+:1046A0003F1FBC061CB9F9938F6FE7A3C633E73CE5
+:1046B0003F8FC99B77AF2BC2C480CD4393701D2819
+:1046C00045A0985E2BF9E8E721DC8A81CCF478607C
+:1046D0006CBFA5F32B206592FB4F9A9EDFC23CC7AF
+:1046E000DB4B66BAB2FCCB663C3E88F5EAC7F29D6E
+:1046F000313F8F989F67CCFCEE69C1F9E5C29B7D85
+:104700007E6B3D032DCD59F6119F7788FDEEE7E7CF
+:104710009C87FDB3F100F597471F213B5EC3F1D89D
+:1047200056B3F8A39FB720DFE71A4F9BC7C6AB3934
+:1047300076F8CCC7C701A6BF888FEB181FD7E6E66F
+:1047400063BB3C1BF3F68A797B73CC9BAD9421DC75
+:104750008FFDFF3AEFBFC87C5E37B03E127C5E5CD7
+:104760003EFE49F3FACB736512AEEF088F93F373F5
+:10477000281B7FBD2EE9967DAE9DAF73CDEB9FC507
+:10478000A763E7353E9E8FB51E2A54BFB6BFEC2502
+:104790003CF6D5B27D02EE0B9E3983FC157DCF9D94
+:1047A0007E1CFA1FBCC94F41B40C601AF6CFEC89CD
+:1047B0003EB42FB0FF4D7505D917FDAD30D8790245
+:1047C000C023450C0F7E9A27B5DFCCECCF14537075
+:1047D000752FEC5617637EE9432AFA95FA84BD5883
+:1047E000F7C2BDEBCE64F8F4CF289DE564ACD0E70A
+:1047F00031BEEFFCE934B4E36BD977C45B80F7C713
+:10480000BEBF80F50333F8F75C70F994540CEDFBF0
+:104810004084C165E207A3FC6107B74B77A09D7593
+:1048200022C2A993BDE5F30EC690BEDECD8A7E7787
+:1048300096FDD2FF16FA74FB8C3D092FC285F61A3D
+:104840009BF7937775575CCDDAF9EE04D2E7BE9A01
+:1048500054C2C150E7AB03DA0DEE7099E85E4970BF
+:1048600009BA2E924E67EBA4CF96DF3C5AFF8B64B9
+:10487000B74CAAE5E58FB6FF4743876C2A4F5CD952
+:1048800010ADCC943FDF7E6D03AEBBD3D5D8AFE681
+:10489000B1F1A733BDD7C1F03A5D1E70C4899EC186
+:1048A000ACFCB27D9BDA92627D6CBF6B63D557B373
+:1048B000AC238C8A4467237FD2BD56BEDE21F0B77D
+:1048C00059E0B39FA117EBFB6A07DA119F27DD0BB5
+:1048D000116738B7BECB49C73BADFA6EBA6C9DD7EE
+:1048E000B19ACFFBA0F1FDB6E89FADEB2F3AF87C73
+:1048F0001C284727311A384B8E7E3E69C413B723D4
+:104900007E93ADFF7FD47CA7FBD938C14F7E1C9F1F
+:104910006D9C5CFDDAF555A2112419F7FD151041C7
+:10492000784AE6C769FFE2F4EF0D25989E95B561D8
+:104930004A5DC1915082D97F4A482FC7D45D192959
+:10494000C7EFAB3F740A79EA6943BDBA6634DFDB6F
+:10495000867A742DE6497E5651F9FAD1FC6ACA6FFF
+:1049600098CCE5EB78E76D43A887AB503931B85662
+:104970000FBDDAF2650657D96E7F044D8D327F0484
+:10498000500F1BE56B86DE0AA968C7EDF68387F139
+:1049900043A9160573FBB5437F0BE19EC52FCAFDE6
+:1049A000C1664BF9FAA1E9E521D43FA2DC1B8A518B
+:1049B000F986A1B9E53AEA93DD7E0DBFFB2AE3341F
+:1049C000EEE94F5F43FC925CE820BD6EE031B970C8
+:1049D00036F9952F9762D39D8C1E0D4FF7AB68FF6C
+:1049E0002777D792BEA7358BFC49F2FF457E245D21
+:1049F0004AEB985F7BF353825ECE0C3DFAF1BC82AA
+:104A0000FCC0FC9C2229CE29128DE934F9678A3832
+:104A10009D184767FCCFD4FE998CBF9AF27B2DF985
+:104A200080968AE23E5E0E32FDC0DAFBA28928D271
+:104A30005DA9E479A73F9246FD71C75510F1EB4897
+:104A4000F72860FDB57379DE156CA6F6BDF53CAFB1
+:104A5000846209CC2767F1BCBB329EC6FCAAE93C44
+:104A60007F874167D861E503F813D1BD7734EF69DB
+:104A7000C7F2A4C137E06BC7F2559FE37AB6426E26
+:104A80007812F17FC7D063AF2E61FD17233FB0FED0
+:104A90008B97462C74D9AC5BE9B259E7749955CC25
+:104AA0003081749075A2C7ACE3AF776878DEF129E6
+:104AB000EE176B7CFA471EB4F7EEA8994DE55364E8
+:104AC000A7F00F707FF836E10FA862D285FB9F6DCB
+:104AD000C21FF0E46DD38AB1DD939B7F48F4FE3CA6
+:104AE0002A11D66E550D3FBF7990ADD3E8C7FF6E42
+:104AF000AB4AFEBA5DACBF18D3DB8FB6AA943ED4E6
+:104B0000AA418CF5FB3DA6C7313FC0CAD36E3A0F10
+:104B10008034FBFED84E47538AF5BBA9959966AC05
+:104B20009F8DAD2AA5B7B66A7F91597FEB5B439401
+:104B3000BFD2B1688593FC1A030B66B2793DF2626D
+:104B400035F9F7E63EE868C6F6A00D5C706E5DE6E6
+:104B5000BB819F2B1D8DB720BFFE60A7DC847A062A
+:104B6000E4F8B333B2D76BC77AA73E283753BD609A
+:104B7000FCE7E704B3D6EBC17A0FEFE270831A7952
+:104B8000B6367B7FFD08EFC9DF77F0FE42919F2F9D
+:104B9000CCDEDF3AAC37B84BE6FDF999CACE5E6F92
+:104BA000238E1BF9BE80AF12CA16661FF70EEC4F9C
+:104BB0002DE5F6CA9C28905F6CD235FA5D92896F1C
+:104BC0006EBF765072303AAB65A938D63B657E4AE7
+:104BD000AA62E97157A72407D3779396B272068F1A
+:104BE00007FB61E9EC39BCFC762C0F98CAB13D4B50
+:104BF0003F3D8F95B3F4B865D67263BC495F815170
+:104C0000BF103A5B27C5C0B05F283FCDC1F38F3BD3
+:104C10007FDB80FA699AC2EBFF19F3AC9F492DD66E
+:104C2000F6D3BC3CFF5BA37E116FEF90795E6566A7
+:104C30002CEDD336AB29B4BB6E3DBF3B74853F33FF
+:104C4000DFE0A264CD15A6F9DDBA6873E88ADACC94
+:104C50007C8217DC5983F95CEB8A477740D4B40E29
+:104C60004D1BA8257BF75F5DBF5C645A37705DA95B
+:104C7000C07581E1A782310A9633BC25B8BDCAF15F
+:104C8000B6FE2C2BDE4ACFB6E26DFDD956BC952E72
+:104C9000181F6F3F13E3E7C21F1B3F6A1EFFB68B4F
+:104CA000ACE34FB8D83AFE6D175BC79F70C9518F00
+:104CB0009F36F3CD8673ACE3979D6B1D7FC3B9D64A
+:104CC000F1CBCE3BBAF10DFAF40E7DCBBAAED735AF
+:104CD00083997EC9A1DE90655D8FF075DD285F3513
+:104CE000F45808D7770FAEEFE89FA9E1EBFBACD7FC
+:104CF000DF0FA1DF7EEDE7F6846298B2BA7B6B33FB
+:104D0000EBC6939FBBD1713FEBF7EBD31D74FE3322
+:104D1000F4B94755D4FFAB6A6693BE4F8AF3DCBE45
+:104D2000D6F4FE6B5C997905921E889AFCF7A3F67F
+:104D300012FCAE01F93059E310F652797B94D9A2F6
+:104D4000EA74D992EFADE5E5377796B727D0972289
+:104D50000F96E33AE4AB810F6A4D7832FA37C637E3
+:104D6000E0C93D3EDF1767C69F6A1B7FAA657C23AB
+:104D7000EF99C1CB13727523C27387D827DF20FF49
+:104D80008EF4CBB1836F467BB4DA0C1FCF67E0E3C0
+:104D90007903BE6FCA331B13D5FF48F84EB5E1EF58
+:104DA000541BFE4EB5E06F853CE788F067AFD76FC8
+:104DB000E3CF6510BD499E807204646FC6654D9C4B
+:104DC00007F1FEEA64215F383EFAF2AF55522784BC
+:104DD00079F922B6AE5D2E8B7D98A8DF64CB1BF6E9
+:104DE0002B2E4787C98F97DD7E5580EB6DB6AD8B37
+:104DF0006C23BD1E2179CAEC3BB81F43969BA3CD03
+:104E000059F4C146999F0F4B5AA405E194FD0AF944
+:104E10001373D51F9025615F272CE73BC530927631
+:104E2000221C21A0F8243874817EFE8CB170287277
+:104E3000730CC7716A0AA05EEB2CB95837C731ED05
+:104E400030E00945091E45E3F02872249ACD0F7C15
+:104E5000B7CCFD16463F0C42D17E84CE050CF8BA85
+:104E60003CCD2D8BD19E2F51084F9D01EBB9DE6FAC
+:104E7000C4BC9E1769A7884BB28F07188D81F14B70
+:104E800013E7901DDA31A75145BED421A2A29FACF1
+:104E9000D39F3D9EC848FBD1EE3C11F95E25FB3304
+:104EA000C9EC52CC7733BB14D34EFF434DB8EEEC74
+:104EB000473ECEE2A719D5731107A44DFB6D5F8D58
+:104EC00017D2E6FDA8D8AF7AF452CB7777A8C2D232
+:104ED000CE3551267BBED3EF48E13E3F1FFCDD02BD
+:104EE0007EA35E8F1C57B502F6CBEE9015DE63876E
+:104EF0003FDEDEE71AD4B2C1F549E1CDE02B7BFFFE
+:104F00004A991227FB596E0E99F9DFE9E27CAA94BF
+:104F1000A971B29BD55CE55EDEDECFCAD12EF63735
+:104F2000EB78FEC2449EE2C4549403137E26897635
+:104F30009D2E711E0D713A3792F4780BF2915AC979
+:104F4000E4471ADBCE48BDA27DCF875F7F85E4634F
+:104F5000824AF221E923E497B78FF3801C9DE8622F
+:104F6000E926397A1CA6AE8F9CB16C7232C1C5E5B8
+:104F7000586D6ED6557E249E15FE9345BF0306FCE4
+:104F80008938F99B0B85BFAA40F84FCEC03FD35557
+:104F90004FF07F1AD35CF0CF10F094416408F7ED26
+:104FA000C8A0D82FC0F9BAD91FBE46F45B26E003CB
+:104FB000F81AD1CD28EF157828743EF30A9CCF9AC1
+:104FC000CC7C9AC47CCE1A6F3E5F10F359E3E2EBBF
+:104FD00095DAD4AC87185F95E6A0CB12D1FFE651E5
+:104FE000BA7CED88F8EAA202E7B124338FC582AF1C
+:104FF000AE186F1E3101CF8013E6BE11443349ACA9
+:1050000037B0C84297AD065FB9F9BA0170BD852EB9
+:10501000B7897E0A9DCFF202E7B335339F6F08BA96
+:10502000AC1C6F3EA6FA6DA27EBB902BB25BB6BAEB
+:105030009E6847FBE301B9B9DB559F198FD5EB316A
+:10504000D79BD4D567D45B85DFA585A3F5FAC5F8D2
+:10505000C22EBA87F6635D686330FBE6DCAEE71B01
+:10506000D11E67EDD653FFCD7CDD64ED3698FB3F56
+:10507000B96B63BBA8773BD66B3BFD23A3FF4DE623
+:10508000FEB7BAD2061C77121C4DA3FD7DDB5C6F08
+:10509000896BB09D9F13566A6FFA4C764DA834CF3A
+:1050A000B90CD7BBAE602C398CFE4A080CA0DDD100
+:1050B0002DC7B70E233F30236F1BFB7E933B2A493E
+:1050C0006CFDD4A2F1FBB05E69C2AD39916E8DF179
+:1050D000EF613EE180668C8BBCDDF7CDAD985F2142
+:1050E000AB9A3B82F6964E47436B8232C5C97549EF
+:1050F000B104AE8B07E4D82E17D93DAC4B36CE4D5C
+:10510000653AC5FB94CC0789DB1D1CAE75BE2F2507
+:10511000110E37830BE383BB6C70B1F1685FDE3B2C
+:1051200081C7DB800C3532F6E7F446B0BFA1093702
+:1051300012BCC936B786ED9327DC48F0B2B2668A56
+:10514000CF73C509DE1E97AA613CDEEDBEEB36616A
+:10515000FCD68A4431D5273870FE53AB087E0FC485
+:10516000D38BC3A8BE06A2786ED3B550A1B8E464B1
+:10517000703DED6FFB16AAE4DFEFAB599FC076FBE5
+:10518000177A29BECEE31F008C032A5BA000C6C39A
+:105190007A82036467969EEDE5F94AA0714A3FCB97
+:1051A000E3655D30AC55B1B42CC9E38EFB6A1625BE
+:1051B00016A31D3387C7A34222FA22C6B79580F8EB
+:1051C00073560E61FFAE494E704632F42D1B186DBA
+:1051D0005F1CCB222FA3F55205D64B1756AF3429AF
+:1051E00017566FA0C07AA902EBA5793D379C5F9C4A
+:1051F000ED9C7594EFE72B647F18F16D45CCF21FA1
+:10520000B54FC2DC6E37DB2B2E5032F60AF299F323
+:10521000F271E158B1AF2DB8DB64DF04954090F630
+:105220001BA7C2A9249779DA1F684D0477BBF2CF78
+:1052300017252C6DF293E7ABBFAA95FB697395FB1D
+:10524000665E1C227D36E332915ECED359EC7B2D17
+:10525000A62D227F99C85FDE12CD325E83C2F57023
+:105260000D348F4B078F80FF4D3CAB674D6A645602
+:105270003F4B9C8E91FA6B1D36BBD1AAEF5439D1AE
+:1052800048E71C353C2ED78DC288721301D22F2ED1
+:10529000486B55B8178568D1E28919F9718526924E
+:1052A000FCFC77B913A439449F08E2D1CE2776BE1F
+:1052B000F0DBF8E268F9E4D263C427BEA4B320F9B6
+:1052C000F10D14582F5560BD7461F5FC49A9B07AF1
+:1052D0000305D64B15582FCDEBAD3A4711FED60539
+:1052E0001DE887F19DAB5AF2ABCEF55ACBCFF35BFD
+:1052F000F2FD6759DBFBCFB6B6EF3FDBDADEBF80EE
+:10530000B77FB8FBA2D3D1CF53A89CFCEE63CA49A8
+:105310008D3A7EFDD28579E44A4DD07ED223EB9042
+:105320000EE2FAC5D62989D2682A8B7DF75321FF70
+:10533000CFB9B81F272927685FFBAF3ECFEF2ADC24
+:105340006F64CC371FBC86FEFDBD53D85B76FB6B0C
+:10535000D4AF73E8F0E153508F00064B83A6B3A996
+:10536000A11F17BC110C15F1540FD0F9B4BDFF5E8D
+:1053700023BE0612A14526389E7373BFCA4FC2DDF5
+:10538000213AAF3D616308F7E9BD93A5AC7E968FE6
+:10539000147E2E5815F3919DD1A3ABA40F7B27F358
+:1053A0007B4CBDAE01F21FF786ADED55613F7CA48D
+:1053B000F0F17A6F8903DAFF5D276C6CC171DDE96A
+:1053C000FF049DC1FD1F93E3A0E3F86EBE0F70477D
+:1053D0001380EB82AA27E8FCDD0E4FD2884B868132
+:1053E000D022D3BC2F32E6C5E653C8BC5E57141A90
+:1053F0004F8B72FCE5C257FA08F1B5D4ADF07B6271
+:10540000210FE16BFF3CBE7E20219D8C8EE452D4A7
+:10541000292F99F9CDBE1E037805BF1DA6BC2E5FAE
+:105420003A2E3FAD12E7A7BDE88761EBB47EE76592
+:10543000E3F2738F58CFDDF045EAD7ADC7A3A8EFED
+:105440007CB569403BDE53ADCD767270A23051F031
+:105450001FC1DD197504291E25B299B1BC6F426FB9
+:10546000242DE51E47AD55AC727384EB5A9DDBBA13
+:10547000AEED877E72C6AE76C0D26CF7018C754DEC
+:105480000F5E3AEEFC57D9E6EFA88D0B3FE54A1EBA
+:1054900057C5742BDECB84502FD9EB3E89CD3752C4
+:1054A000F83C5F75733DA687C687636D2BF7A3AD88
+:1054B00016F4CB556F353AA031BED7BDAD03F76BAF
+:1054C00025F3B97C8CCA833C60E1DB830AF777F46F
+:1054D0007AF4368A730973BFC9987E057FDBE52DA0
+:1054E00099E39E8D21CF7F5374AE9FD401F247186C
+:1054F00072A7EBFF49FAAF7772BB8AFA21A9AF27EF
+:10550000FFF1FE6A05303ECBAE278CB44FE0E134AC
+:10551000E857F11E53DF4B4EBA176BAFE7C1CD9A78
+:10552000C9DFE7ABB1EAE57C7A66B39BE3E5E3EA82
+:10553000991F0ABA66D133B42E2FEDE97C0AE9D35C
+:105540002BE20C4B9B12B0D834DFB542CFFDBB5BD6
+:10555000AC17951C8E5E97D660A65309FBDE60D60D
+:10556000A739E8938BEE976190E0840C1CF6F9ED77
+:10557000107828C5F16BF3E3612C1D381F74BBB3A1
+:10558000F3C127359F2E81AF7C7CBC55CC67ABC067
+:10559000AB31AF7C7262F4FF30E2AB1EEBDBD603C3
+:1055A0003961A1BFD3C05B93AD9E6AAD67E047761A
+:1055B000733BC6583FF2F5FF6B85C363EF3F971C03
+:1055C000FE66540E13E4AF35C671C3E3E457D8CF7B
+:1055D000F474DF2C80623F48E837706A3CEE291093
+:1055E0006C06F3798F5D7F197A31973EB2EF67F2DF
+:1055F000D55782CAB8F69361EF948A7B5FAA881365
+:105600005E2F653FFFF9BBA01B53F405C5FB61F896
+:1056100008E2039A21B58DE244A3436D2C3F31A2E9
+:10562000E87DE81791CF18BA8BE527FCC80D7D11EE
+:1056300074C5CC1F1A62FCB62AAA366379851A1E75
+:10564000BD1F39700AFABBB83D06CE95AFE0FDE04C
+:105650008997C8807875C35C8ADFDEBF02EF8E8DC4
+:105660008567A20C30A994A5C26F40E78AB8D5BC63
+:10567000D08A4F5868CAB3FDE304D5B6BF2B70DE9D
+:10568000767872B5CB0B4F667FFA068EEF86F1D730
+:10569000B5239DDFA8BD5BE0BC686D36D50B1F74DC
+:1056A000828EF7DE0F4A941E7FD047E994831E4A0C
+:1056B000271F2C039D11ADF26009A5930E4EA2EF9A
+:1056C0001507CB292D3F3895D2D0C130A525073FEE
+:1056D00045A976703AA5EB841C161F3C99F250330D
+:1056E0009BC62F3A388BF281839FA5D47F702E2FD3
+:1056F00017E7ACEB6E8901FAB1155C87987C749D55
+:10570000B184D625FBBC6E55F9BAD22DE2D6BB6D5D
+:105710007AFB6151FEA048D709B900390E667F7A3D
+:105720004AE57A615D558CECF26E633D2C5F6259FF
+:105730000FEDF5BB73DCAF7CCC804BC003358BF237
+:10574000D0879FCBBA8331BA4F001023BD0472CCEF
+:10575000A277BB0DF8051E73F727F078C6A3C4C760
+:105760001E85C72D7BBE7067CBBDA877CEBC71E907
+:105770006E267723EED8CD2AF2FB17AE26A6BBE322
+:10578000BA9B43741FF18C8D74EF09CD72BC4FD15D
+:1057900073E6CAF8BDC4758C2E33A85D9B6A3A1FA8
+:1057A000ED5D7273CB77587F7AA7037413BF4E59A0
+:1057B000E905DDACBF0E959563FBCA1B4A2DDF2BB7
+:1057C000AEA9B0B4831AEE470F7DA5CA524F9B7F96
+:1057D00092A55ED1BCD9D676E2FCDC5FF7194B3BD3
+:1057E000B7DFC02B3F5F64F4B7AC1F3D52763A7E03
+:1057F0005D758CCB3797AAC22EF21746B75CFD1B9E
+:10580000F3CDAB978279E741F6EED7D573E7E3396D
+:10581000865B8BD1FD9523AF7F6CE751683DBBBEA6
+:105820002A427D5586FA44A2D48FFAAA0CF58887BD
+:1058300052A3DE6AC36E29504E56A3BEF19BF44DAF
+:105840003D93FB2CFC50EC195FDFCC14E535225D59
+:105850002DF8CACE37938C72D437B5F9F5CD24DB49
+:10586000B876B8EA3C421FFD93F54DEFEC8DB12FB1
+:10587000B39CE7D43B5BEE6169CFAC1B29CFF485C9
+:10588000DBC3CA7B4E5919BFC7A447E0D0CF395FED
+:105890000A7E289E63D51F46FF81884D8F18F2F03F
+:1058A00031E55AF270B9CD459FDF1FA55C1BFD7F26
+:1058B000D2722DF5AE3A22B91E5BFFD8CEA3D07AB4
+:1058C0008946489F86FB9269DE5407FAE31C031160
+:1058D0007EDF3346F13CBD3F75D17902AB41FBE23F
+:1058E0007A357A0EF24FBDDA7C1EA6D787F5E370C3
+:1058F0009D66F9F36DF90B3C132CF98B6CF94B6C2D
+:10590000F52FB5957FD15C9ED4F5E3D08F917CC601
+:1059100045E78649DDD194F53D0581A767D5E62F9A
+:1059200063FB1353271D877461F9AF527F1EDE1F7F
+:10593000CB5F49E365F257D9CA97D9CAAFB5E597A6
+:10594000DBEA7FCD9CEFFD68EAEDB8DE277EE682DC
+:105950006D59FC4BAF083DD273C2CDB1762E97374F
+:10596000935C4E5B19BF02882F00E176FA6DFB3F16
+:10597000C667667E7956E89B9F4CBE91F64D3D6C9E
+:10598000FF44F18DE8DFCB829FDF78C4FB5CFA55E2
+:10599000742F22597E3DF9397A2ADB297E61BFAE08
+:1059A000D0B96D329CBD7D6F2BF773F454663F5FA9
+:1059B000F88D276C89D7826AEE17443138ECC077AE
+:1059C00086B87EEF0A77937E55D25771FF46798C61
+:1059D000FC1BDB3C7CFD52FC71F22BB82BE359F72E
+:1059E000F53DA3F8B0FA3B7F22F06AEC234DF82096
+:1059F00039ECF2FC6937FA37929EEC72B6538CEFB1
+:105A00000A1536FED8F9F3F1EFC6CB2E28AFB67DD6
+:105A10006DD2C5E3E71393B91F4066E398FD0AF61C
+:105A2000F146E769DB67DF25F83CE9E1F1F7467FFE
+:105A30007678EE17F3B9DFA359E6256B7C9C7CFDE5
+:105A4000FF182F71A11F40B3FB21AC7AAE55D4775C
+:105A500005ADF572E127318A1F1EA765F06F3E7E06
+:105A600037C67916E1A2F385ECFB70FDD01C8AEBFA
+:105A7000D80F81813EDC37CBDA2BE817BE896D93D6
+:105A8000D09FDD2127C8BF90D041E3EFECF07389B0
+:105A90009B9C274550DFA922DE0230DE22688A5710
+:105AA000147ECEDB7DDFBC0FCB5724DC1ABE7BF22D
+:105AB00077CF543E9F432B28CEA297EDD471DC03C1
+:105AC0009E29297C4FC759DC4FF6BCD3392B9E2D1C
+:105AD000FED4EDE5727CDAA1B5A467BB997EC3F371
+:105AE000A56E39A696D6A2EB3A41F2DAAB8F1FD754
+:105AF000688F8F7469F6B8442BBE225E4EDFA458BF
+:105B00007F939E488B252ED0EBA1F2BF7BACF0F5A6
+:105B1000E8FCBE900E718A334D563A1C88B7630577
+:105B20009F31AE12E6F78F8210A338163524D3B812
+:105B30000E1FC76FAE714197DF31BF2B73ACF039C9
+:105B4000BAFEC6383FC9E0257ED2E7AB8DDB31FF18
+:105B50005327ADA7F6717EEF8D7DC66BD29BB21633
+:105B6000033A8717FD9D3581C77FCB95FC7EBA022E
+:105B7000CD4D6136FF8E4AFEFEA2ECCF132F516948
+:105B8000F757E43AAFE3E72554C444B4E10F7C5C33
+:105B9000AF882308C030059116A34A9F8A7104BAC2
+:105BA000C4EFF747241E6F3E8FE2CB839E4FBADFD0
+:105BB000CBA95F29BA0E0EFB8EA05F7998FC5C9F83
+:105BC00078BF79E0F5C09DD42F86AC1E2ECBF48B28
+:105BD000FA979C4A870E1FC6F334714605861D2E20
+:105BE0003BF87D2BA828A278C4AEE0F5AA99AE9D1B
+:105BF000DE2ACBFAAA68DD5FC3779494CA6BA2C38E
+:105C0000E3F06552C89152F995E870017E4C994DC8
+:105C10003F9B3FB45B89A5DAD05E9CE2E771AC7232
+:105C20009CCE477AA4D2D97D7526FEAD54D2089772
+:105C30003F124D609C634F992382F15932F4EFA5D6
+:105C400077D39C0B23E3C9AB5C29BF6D9ECFB7BD57
+:105C50008120C129FC871D79F8BD4BE8EB5CE52E5E
+:105C60002512CBA68707BD621DF3662F3FE06B7C34
+:105C7000D09B65DD490BFCF6943055FA69CE3EC8E1
+:105C80000772E59E57100F5D13CE1C5F3F6956FDEE
+:105C9000F4BA2FFA43EFF870FCD85B9F857EFE6064
+:105CA00061FB038803DEA775BEE414E7BBD122695C
+:105CB000229EDA1A7F11E864E5AE396E0DFDC9DE69
+:105CC000DA08DCCBF2A1D3D566790EBD1B47E7AC71
+:105CD000AE7227505C9E731E8F1BAAE17ED628FBF6
+:105CE0008FE2CBE68D1F4FE6B4E57F65A773EB2E01
+:105CF0007A3FC280DF885FB7CFEB07BEC6E1ECF822
+:105D0000286C1FB481F10BB8F15D3195D2B5AD1A95
+:105D1000A5AB5B4394AE6A65CC4EEB7F0DE56FC3DC
+:105D2000A673312E249E0CE37E2474EF2B78257409
+:105D300003E296EE19DD7306DA597D98E7F7421310
+:105D400012E627F3F2437D1BCEC0FD609FC7A89FDC
+:105D5000E4F547F37774A15DD827E26BCB56DD7B82
+:105D600006DAAD1B261BFEAFA87A91C9FEAAF1B9CF
+:105D7000B89F266CB4EFEAC27DAC4736F28F9E61C5
+:105D8000CD4314E1F1A83C7F8EEF07040FA9003644
+:105D9000DE45BE5D94DF7082D8975FB8280F1EB9CC
+:105DA0001FA3D7AB733BE842FEEE8AC2F8A68A7DFA
+:105DB000DA20DECD2DB41FDCFFD07AF752F6F532B3
+:105DC000233779D6B50B0B7BFF85A183EC0BD4C3AE
+:105DD000F8FEA2FC0B2E17C77ADC0DAE23C38B3A5C
+:105DE0002F16C5EE8B9A06D348EA9F78630D3ED6F0
+:105DF0004FF1FCBDB4AC28A134B71B0A1CBFD2279D
+:105E0000EE9BB179E3BA63E0DBB03F6E407A4EC8F7
+:105E1000F4E70A46E9DCCD23DE1B2E14EEABBC9A78
+:105E2000A51F786076F978E76DC1850E0C421AD50A
+:105E30001BA5F3BD96BC36AF540475F07C515D854F
+:105E400025EFAFADB2E45DDA4996F61F975E5FF2DB
+:105E50006A16FEBEC036AF26FB3C0BECD7B3C2A918
+:105E6000BFC1EC84B06CD8A5EBE9DEF27EC431EAA8
+:105E7000C98159748F17AA8D7B0A40712C1E3D4A27
+:105E80007CEA65FA9AECE34AABBD2A07ADF66AA84C
+:105E9000259136FAC5F86DCF0A85C61D5DAFFC9019
+:105EA000F6E0DD73A19769DF3E1555DE379E09F3F5
+:105EB0007611F3FD7C7B2A8B7333BA9B1FCE7FAEAA
+:105EC0006A1F2774E1F8716CF6FAE097F5374D72A6
+:105ED00098BB9D0C6F9ADEDDD886B49F90C17F740D
+:105EE000FB62F27FB881D9D30CCF1DA18B21C6E60E
+:105EF000D98D5518FD9298323EEF0ECDD6284E5FC3
+:105F0000E77475A85C4E6EF2E916BBCCE9E77262E5
+:105F1000D4CB47FF9B9C10CFB6AEBDEAE3FBE503B5
+:105F2000DF8CFF09F799891741C7F3DFC1D683F4E6
+:105F30000E665DFA2C27FA4FF6F92652BDBADD51EE
+:105F4000E7E9A67EEA80BF07CEFE9C66BFAAE127EE
+:105F500086432AC50DEF4CF3B8E19DE93F3F751824
+:105F6000F3CF38E8DDD19D7BC7B7B306859D65D4F7
+:105F70001B7C86EF5B0765F0958E67EF88FB71B33E
+:105F8000D2B6B844199C48FF03B7E84EB47B065B11
+:105F90005509D7FFD9629E75E9A813D7B17CF3DA0A
+:105FA00063A3AF314FBC9F88F3ECF4F3FB829D1ADF
+:105FB0009B2FF1357F4F3B17BCA3FB7F2D3B3E94BE
+:105FC000007FB74371C5B46CF3CE778FF168E1EB16
+:105FD000B2C1D7EDE7FB73C37F900F1E25E8B0E891
+:105FE000096F9D26E182128081A6696142E38BB828
+:105FF0001F2255C1583DB06FAEB404E3C617FBA3D2
+:106000005208F39F95A63038B50A27DBE3307BA909
+:10601000F6C5F4AF713E2D3EBA97D151FB01C517BD
+:10602000947C556EC375AA173B27BBA8BABB81C128
+:10603000D781FF642ABCBCBFFC4CB43B64E07A80CF
+:1060400049982E4F44BB11F031979CFA80FD498747
+:10605000DD9976B9F064B73FDDB0687CFD24CEF9F8
+:1060600013EC3FD42F25B6F6C551AB7D1BB0DDA791
+:10607000380DF5777D01F7328E721C0DD6AB187A8C
+:10608000E0AA766829AC0F5A09DE07F2CE9701E341
+:106090001BB5E048C2A1E7C77B275BC2B85CA52C53
+:1060A000E73017FAB9FF2774451DC5E1EC8F302E94
+:1060B0009885F957B2EEE3ECF72D56D5DE4D7AB25E
+:1060C00083F113C69B246A1DB47FECAD7E4833CBAD
+:1060D000D3D7C53819FA832E1BFB64BCBF5AED8891
+:1060E0007A667E7CFADBF71BF9E8EF5B688DFB399B
+:1060F00052BAB4FA41C4B18C4FFFA31DC7A0DB58FC
+:10610000F9681374FB0AE993EED091DD935955BBFE
+:106110009EE8E6ADCE1EEFDEE997AC7A56A42ADB08
+:106120005F464CFB4BE771A7B4DC05E3D0654C7CC4
+:1061300015EFC7E9E77EB4D592378243ADCEE1577C
+:106140009E1630E018E6717C73F784F0DCB8BFFE71
+:10615000CD109E6FACF930FBF9E382008F0FD7A30F
+:10616000AF92FDBFA69EFB03F10FF5CE4DFC9F50F5
+:1061700095786B13BE6BB67A9FCF62FF18EB42AE79
+:106180007929154BE9BDC403AF49F4BEBA54B1E255
+:1061900044846B68EE127A87A4BBEE493A7FE98F9C
+:1061A0008C4F1723BEB45BDC571F1D3FC779E1DF5F
+:1061B000045DAA12CBC89E5C53FE228DB3BA6EFC5E
+:1061C000719236FADB53D50131F213DBCE73F70946
+:1061D000B9DDE717E712AEE6F3A686318E2A4EFE4A
+:1061E000B10935D121D4FB170662AFF859F99AB934
+:1061F0004BCA691FA15BD7C15B73CC2714E0FD1AA2
+:1062000076D281AAF8FFB9A50E7FAF62DAAC848995
+:106210001EFD39E2DA6B03C6B99787F639DD780FD0
+:1062200080C1D75F5E18FE0D3A9F06CFA9F8CE7ADF
+:10623000778EF85E23B5AFEFF9F06EC7C31AD7308B
+:10624000C53FAD91B2CF674180E37BCD2D697E9E86
+:1062500036F74D3A4FF3A75FA5B889FFA8DF4BE7A4
+:10626000697A809FFF04FCC3144F5A3487BF0F988C
+:106270004B8E527E5E5FD6ACF5401EB69E0FF98DFA
+:10628000F39EF1FB33E00475989FF38C954B5A7F96
+:10629000EEEBDFB687DE5181349D2774FFC2496F74
+:1062A000C11A7818235749FE3B316B241EB7BC2016
+:1062B000D0DA8DFE9135C6F9DA2CBE4F92EBD2744E
+:1062C000BEE60DE8167BC71F31DE492C6C9E45B833
+:1062D00016D573B580EB2AFAE111BECE5917933F5C
+:1062E00037175D6FF2C5EA03F5667F3EDF67FDABEA
+:1062F000F1E1DFFCBA252EDDCE8F6EF8B723DAC7C9
+:10630000E5F22B1F10F269BCA36BB45F1C50B2E323
+:10631000F7D797E4C3EFE2C0846CF83DCB4BFB8822
+:1063200075E39FEF6CB2E9EF4D469C8D78D797F5FA
+:10633000577E7E167BC258570F048CF77C9ABD3867
+:106340004E55A2D68B78DA965C44F96DB78E4F4FD6
+:1063500063FC2D42AF6F15EF9018E55B055FA66CEF
+:10636000FAF66521D75B857C6D53A35E8C5F82A7AF
+:10637000CEF24E67F80B33BE4057E2F15D2325E3C2
+:106380008DAFAFB4DAFD477ABF652060F5D7167AD6
+:106390006FF368F1921271352F07D224F7CE743162
+:1063A000C9537829903C85632369DC37550D3852F1
+:1063B0003AC5AF347BA733928696CA3AC5B2897B79
+:1063C000B0278AF51D9C2B1DB87F09897BE48C853D
+:1063D0002FA338983BADBF07B24D8D342A78AEDC81
+:1063E00049118E104E9A7EAF8240B2FE1E4868DF81
+:1063F0005BF47B2A2130D50B1F3DDEFF2BF0F1EE45
+:10640000CB1E353FCA231EB33E3E5E82E66C7AFF4A
+:1064100017C21E3BFE969D12C9E5357E78DDE4A7C6
+:106420004949232588DF2D2BDB25C467A2132227AA
+:1064300064D1636F047C865ED88DEF2EB82A397DD7
+:10644000BBFEEDE2E12798CADAB2A211B2ED3F98A5
+:106450005E782340EB13D70B5B572EE2E92127F13F
+:1064600049751252F83B2AF307626D2EA4FB52FEC7
+:106470002E75A8333E84F9F03510D159FF55E8D474
+:1064800067E356B7402A4A7C042F8726E2EFDDF007
+:10649000BFC9C38B87BECDEAEF99E3D6F07755E04D
+:1064A000062BBF545C63FD7D95EA4E2BBF4CB4F1C7
+:1064B0008BBD7D581F390BE19D9A7400EEEB82175E
+:1064C000DAFA83E11DF7E17C76FB2369066F75BF7D
+:1064D000B5DCDEBF0C317711A3CB23371FEAAD61EA
+:1064E000F5EF4E3696215EB6A9C0EF5B342B74BF34
+:1064F00035D73BC463F8D6B0FB0B7CB7D858F77AD6
+:10650000F649FCDD8B29DA6B61F46BBECC7FC72EBC
+:10651000F38EC567E81D8BE320C6ED478852DA2964
+:10652000EC53EDF4CA30FA3F93BFF669782F4B2B4A
+:10653000B3FACFE4D2267A1F6CD4EE2E6576372BD1
+:106540004F9658EDCBD38B389FCE2EE2F6A1E6E3E3
+:10655000FD801A2F37BFABB4B148B296FBE3E51705
+:1065600098CAE71789F767C5BBE30D450B7A502F2B
+:10657000699358FD2CFC79A618D7288760642FBE34
+:106580000772FBA58BEACDFB8B8D45FC5C473B5E20
+:106590008C5B991DAE64988F7B9B18776391F10E8D
+:1065A0005C9CBF03A7F1D4F87E5B6089F406FB7C9A
+:1065B000C0058D18A7D231C141EF43DE34D1880721
+:1065C0001B5F4F187418C5B7C6E3902A96F27B97E5
+:1065D000B9DA6D6EE2FE41FBF7989847E7D2C681C3
+:1065E0006A36FFE86E203E710721EBF90F93EF58F2
+:1065F0005136BBAAB389F671074AB2FF4EA1917614
+:10660000D8D67D59F813C7D41374D25F0A118B778B
+:1066100086B87FEE4089234AF7026B81DE3B3B5010
+:10662000CEFD75F6F6BDB6713CB0288AEB349EB34C
+:10663000623CA3520D293CC8F10607B4B08EF101AB
+:106640007BC94FA303C3272BEF8E00D9779D216E03
+:10665000C7C8A1810607AE1FD0A499EDB10AF17B8E
+:106660008B1E7FACA3C812479220FD7BC095223DB4
+:10667000D21176C0DD59FC886B8AB89DBB595FF496
+:106680007C380BFD3614E916FBB9E220B7BF73D591
+:10669000CFD4E3708DF263284EE73EA0737EBC300A
+:1066A00010BDBD689C382EC3EF78C51CA17041BFDA
+:1066B000E47FD83CAE7AC64531E9A71DDABAE7DBFC
+:1066C0000C4F4E714ECD56E53D4FB0F2AFE0BD27B9
+:1066D00096BF6ADF0C650A2B7FB9C2898B30FB6BD2
+:1066E0002EC271DF054713CAD3BBF062D1C926BAE7
+:1066F0003D5224ECD0A48BF4A6E18FFBEA80CBA220
+:1067000057AFDC64CD2F814513D14FB1E45617D973
+:106710002657D9D6FB6D62FE5742BC1BD7CF2E1130
+:106720003F7EED0F66282837579DAC859DA6FB560A
+:106730004F087ABCCDF84737C9D9D5FE9482FBB84B
+:10674000D7779E7CF16701FB497557E0FA59923D76
+:10675000FEEFCB492B9CF9E66187DB38BFCB058781
+:10676000BC5D8AA6B2C8D9B34556BF5087CADF47B9
+:106770008A76C8E0F93CC6DF01C94F625F80DEF36C
+:106780004E34C6299E2ED1EED63A82145F477174DC
+:106790002B18C1F03DA23F08FE33E2E900E2A7E278
+:1067A0003EED5A7558417FF47239DE843FA5669CF0
+:1067B000C3B85DB1E82406BF6B57437A1258EA2587
+:1067C0000BACF78C545550BD26C738FDBD27F4E4FB
+:1067D000D30FDCA3E0FAF3EEFDAF9D8B72B8EC7142
+:1067E00027E095BCF71E08409AF60F2905E5FBEA5D
+:1067F0009DCEAC7E36F2D4323C2EFB5E80F4E2D5E8
+:106800000FB9530B59FBAB1F7D7D2630797AAF7DD5
+:1068100064CF24C4DFFD123F1F4C0CCFC4F5E96ADE
+:1068200019FE3DDB3B64BE62CE5FEF3CE66B41FA96
+:1068300049DB87BE44FD0E5EE232BFC7EE28E6EBC1
+:106840000FABC7E3257748A913B2E80F633FF4CE37
+:106850000E89C3B7CB95C250E0ABB7DFA5C4181CF7
+:10686000CBB7BF4FFC72FAF71E2C423C2CDFE5B4CD
+:10687000EC2F977DEFC3EECF303A2F73C2C842940E
+:1068800063E721CAEF8FAA234E926B1E9F721DA948
+:106890000056EFE1DF9FF93FACFCED901330B4F50B
+:1068A000EDBDBF531EC77CCC1FC75F1459BECBCAFA
+:1068B000D7CBB7BFAE205C9A03462A3F8BE79C56E6
+:1068C0003BC95E1F6044413DB57CB0F77D27E3B70F
+:1068D000E53BDFFD15F2DD729B7CBC8DFF281F6B55
+:1068E0009F9F5C6CB3CFB797151487B2ECC1FD5B6B
+:1068F000D01FF1CE437FDC82F767AFF9E82F5BBE94
+:1069000081F1603FF66828DFCBEFFF451198F4FE78
+:1069100039C55CCEDEDB71DF7736B3F9BFF7AA9BF2
+:10692000B0F5DE13BF9F82FE9FF7BEFFB789E80F69
+:10693000BAE189338E43FEBAE111FE7B36B9E040FD
+:106940007E4D997F6F519C13E9BBC81803F891489D
+:106950006DF480811105D7B3BF4A30D257C2BE0F44
+:106960007EA8A07DB6270A23889FA776BEBEE766CD
+:10697000967F97D1C79D853E6CFE931CA49F99D8A6
+:10698000B0F4BA9D179CF7B93A4C5D11EC7E398C86
+:1069900090DE1C43D797185DEB3274B597EF8743B1
+:1069A0000A9E1B2C7F80D17126D293D171E6583A72
+:1069B000BE8BFF983B968ED714DBDF6FB866EB6615
+:1069C0002CDC5996D5DE35F659D73E72D1B8F69300
+:1069D000A117F2E179A9F093CC298EAE2C46397C2F
+:1069E000E8BBDFD91CE4745EC810F3DE83FBA7E0CC
+:1069F000A31C7F708D7C09F130F2845BC3F5FDEA46
+:106A0000277E49F2F6DE232F283AC5B54091740A55
+:106A1000CBC3E8DF8BC0F2D7493C73EDBD7F3FF3BA
+:106A200057ACFDB5F853AA1AD18FF27B98FC113DF3
+:106A300052E737E9A877531368DED7A5B85C5C97AF
+:106A40001ABA10E3F9EC787F44E817335DF17DA9B9
+:106A5000EB76BE7626F25F2E7A1AF3D770FEA7B2D7
+:106A6000F27BAD729B534E057DDFBBEB8082F6411E
+:106A7000FA714573307BF83DD78842EBE3F79DDA36
+:106A8000B6C858BA67F02FE28E8E701F3E586CF36E
+:106A90007F08FCE493F3FCF33A32BC6D29D62DFC5D
+:106AA00063E0EF9D43D9F5FFB3C5DCDEBE0EE24DDA
+:106AB0001553C7AE5F323427268533F0BE8371632A
+:106AC0000CDE77EE77D23B7DDD834F911EB7EB8BEB
+:106AD000EB72D8D1FB8CF1760DCD44BDF6CE938F01
+:106AE000115F5EF7C06B0AEE57F66C7F5819AECD9A
+:106AF000C801AE0FE6DF297BE77F0DCD44FDB53C35
+:106B000047FCDF5BA2FFE53FB2F6BFFC81F72DFD3E
+:106B10002F4B0C2AF43BAF79C6795B8E5E82F37DF6
+:106B20007BAF0B703FFCF6A0B3299B9DF3DF627D2A
+:106B300034F0D41D38E595623CF72AE5EF3276B69D
+:106B4000457F89BF379C78C125F6B7D157D09EE9DC
+:106B50002851E81E4267E062F2D71BFD0DD8F0A96C
+:106B600005B506DC0768F39BEBCCFB2A03FE92A875
+:106B7000C302FFFF03C228CF4D00800000000000C9
+:106B80001F8B080000000000000BD57C0B7C54D547
+:106B9000B5F73A73CE3C42269393D7E4693C4978E3
+:106BA0004AC02109101ED58120A6986A50AA5CEB24
+:106BB000D50121444832292A5AEB779990885EF012
+:106BC000B3B1D28296B60317AA95C40E1034B6811B
+:106BD0000E606950B4019F7851A3D68A15C8180574
+:106BE0006DAFD6BBD6DAE730332783D0EFFEBEEFEA
+:106BF000F7FBC2CFDF769FB3CF3E7BAFF55FCFBD54
+:106C0000CEDC91529DAD3901DA560268A30040F105
+:106C1000E4D4A600C8AED9D59089AD6A519324803A
+:106C2000AFE9EFF2680B100498086075D6820F9FE9
+:106C3000B7AA16D01CC07F5F03CFD3DE8FCFDF256E
+:106C4000A7B4AFA179ACCDBFA43EB428B0B58287BC
+:106C50008D562AE8FE259E354500EB93FFED71BA6F
+:106C60007F77C0AEDAB16D4D59F11BEAFF4A825A07
+:106C700019C7B5D2F3D806AC0E75AB8AD7D3607EF0
+:106C8000C8195D4FBE2AF17AC6E33AA8C53F1F4C2A
+:106C9000C2F78A25412B34008E80A4CC60805AE351
+:106CA000B97F577D25EAC4685F76F681AF14E00AA4
+:106CB000D969A1FDDF9F6309DA8BA8BD36154A8724
+:106CC000D2C168EF5B590BE151E7BEDF9EE558B0DA
+:106CD0000978DD010BCE1B901CC1ADB4102F68AA42
+:106CE0001B786DA0E17F484347CCBA718097F6A12D
+:106CF000E8F7ADB82DBA698700B749C4076C93218E
+:106D00000C500270A55A0C90059002FDFA2411A8AF
+:106D10001D07302FC5E7A57D660FF749342E0BBC44
+:106D2000DC5640AD44F72DC937E5FABE617F304FE0
+:106D300039D13F5AE72FBEE25756417F450165588A
+:106D400019AD63A3FA97B1380FDDCFA051015EC72B
+:106D500084AAEBC7B6111C68F131747E78D6CC0CCE
+:106D6000C28D31AED551785442BA78E52435A91098
+:106D7000FB0A5286F87D2C85E9F4A3E93833DEFF5F
+:106D8000F1B194CD32F2E36149E0294078225C41CF
+:106D9000F3E3840F17E2670D3D37B3F9378C170B18
+:106DA000D4B656E8947413FDC41FE28DF174B7E2B3
+:106DB00050ED1EA2AD5753681E1B04D748B45E1F8A
+:106DC000D3D301EDDC0E8310B74EE8E37605D1791D
+:106DD00022F1C1C3FD54E86F1F8ECFD5A8B50D2A8F
+:106DE000EEE7C7D5E912EDCF09AA4EDF825C9FF32B
+:106DF0001BE83B0BE9EB88D2D74EF44C1E4A4F07F9
+:106E0000A84C87340F78D64CE079218CFB78780633
+:106E1000046506910A2AE2255BDF6786CE67C20F0A
+:106E2000ED2F6BBED89FF97D39D0CEE3F220C46D33
+:106E300001F4719BEE502585D7734CE7EF7BF0751D
+:106E400072743D466B2704E3FCA70B70FE22A6B6C6
+:106E50004B72D3FE8DBF5AC6E11F2AF679AB709CE8
+:106E6000E2737AEDB895FF5D31934008D68B15201B
+:106E7000BE3AFB17D4800B877B6C101E4DB307788E
+:106E80007D49A345DFD02F766454D8583F3E673DF7
+:106E9000F6D1317ACE0A31E3681DF24DA944F78765
+:106EA000E8C294A174BFFB584BE67331F36E5153A3
+:106EB00032699F3019267F2D479F87CA7480DCA1D5
+:106EC000CF7FBE3290F99C354A8736C7BF312EBD81
+:106ED00008E0A4CBB04F38CE8CE21871C97A2EB03E
+:106EE000CAAEB666320E19A7772381ECD87E9E54BF
+:106EF00018E4FD43F3E46B510F5B1C5E49C2EB0DDC
+:106F0000AA2B48F469748666B39E30E98D19F3D4D0
+:106F1000701E8E1B68060FD175FDCE6B8E135D073C
+:106F2000DCA0D9D3042EBC93484F187A043419F945
+:106F3000BB5A9AE090B06DECFAE4A5DFE1F8A41E2C
+:106F40001964BC3F807BEEA37D2BDE346262323C51
+:106F50001827DFAD0E213FC63ECDF2FACFEE133932
+:106F6000CFF3331F64D2BF0FFE3B3D3F0829ED3402
+:106F70007E8382AFA6F97BADC1AD4887E50765C6C4
+:106F8000DBF24E2908C467454BA5FE5D2FC820F0F3
+:106F9000077CFFAE5F96301E6518FBA3E9F8BC7F47
+:106FA000A3D5831A13D2BCF1F62AA37A1868313814
+:106FB0008080F7480ED26B914EAFF5C90F6DA2F5E8
+:106FC0006C6811F629AB363D6EFCE74957DBEA7079
+:106FD0007E2D17D7359570D3337235F697E5CBAA4A
+:106FE0008C2A227B7E5EBC7D6CB7BE47F2A7E13F58
+:106FF000C2B7A1BFEA487F911E92EF65FB771AE9FD
+:107000002593BC80B07F4DA8AFC238DF920DE279E6
+:1070100063BEFA9E8757E7637B5B30FEFA3250A26D
+:107020007DB6B3AED1A407EE86611EBB3414FF4A11
+:107030001AE29F40E204A7E083D343FA65F015D932
+:107040006317A4607925BA931E91FB47AD9F8EF319
+:10705000F97BAD10D4885FE2FEE0463918288ACA71
+:10706000C760EF4EA6C7925CA407E2D39E134FFF02
+:10707000242D9EFEC9A3D3BF911F291E133DE51ADF
+:10708000A63FD21B68FED4CAE2F8E7757A8FC67FA6
+:1070900082DE5E5E675DB7048F4944E7070FE46BED
+:1070A00043E9DAD4FDB08DE4FF7C7435D3715C9A8A
+:1070B000AE47743A9E869EBD3A2A6B1D6E5625BC1D
+:1070C0000F456D9F41382D40B9259C98E5DAA09F6A
+:1070D0003553F5DA70DC45340EF797E7080961F4AB
+:1070E00080F232E165A1D0BBADAA97ED91A16F937B
+:1070F000CFEAEDF7E16B6C33E7563C4038BA5D4AB6
+:107100006967BFCA24B76BC7AD60FD55B00AF531DA
+:10711000DBD5783F2DB4D2E15984EB796A25781616
+:107120008D00D8B152E5D6ECBF19F2BE11FD37BBC8
+:10713000B0CF3CAF82F85DA392FEF1A8B4CE876CCD
+:10714000C0723A500AC1CDF8FE50F83337F9A30F98
+:107150009545AEAE457FC4BF186A43D86E4DB7B0F3
+:107160007E7D365DF877D5E9366ED7D45AC08BEF81
+:1071700039D52307255CDF29D57BF072D23B3D56FC
+:107180008DFD2B35F2D2F7F87EB9BA06E9996B6915
+:107190009F40EFC5F1D5419C77A0E77DD7AD317613
+:1071A000F954F72363C80F7AD402F5A104FE5063A3
+:1071B0009A78FFA9D1EFB971DBD0E888D800F174D3
+:1071C0007F7F732DF95B77256B7CDFD635239CCFD2
+:1071D000F899CBFEF17375C3186FBB4E4090E46E07
+:1071E000B67CD355E3B03FE555C56367A1F25EBDFC
+:1071F00060120F61BEAFFBB27C03D1CF8FF45CC5D0
+:1072000017DB5F267E3DFB670548EE2A9A9F7EDFEF
+:1072100087FB3C908368A80498E40D958771D4ACF3
+:107220009EB41924DFFE63C0F23AB14F89C32DC862
+:107230000DFBF349AFBC21DCC3C96F98EE43402678
+:10724000FF7F4A7FFCF569E7C1FB5A03EF2E7013FD
+:10725000DE1F5BD90DEF935DD4ED671E6E30113DDF
+:107260000D7C3F933CF39134F6274026DC7A94C49E
+:10727000E3FF9C2E310ED67D294B84CB81087856B6
+:1072800021BD0616E5F1BE073E23870CDB2FE5EA9C
+:1072900050027FEB89341B3FFFA84DE0FED13A67D7
+:1072A000B005F7B3AF6EE9C5FDF8BE333FF05DAC96
+:1072B0007E931F8CAAC552C9FC4A25BADF3EB74D42
+:1072C000623984F65CA29B79BC212786DC18F29295
+:1072D0005B37CC174CF09ED1FAFE66D68D966C8447
+:1072E000DB3D12101F4FADC2757D83FF188055F92D
+:1072F000B41E7FF7A736B2D78E1EC91B4C30BE37DF
+:10730000CD25F0BB2AD0320DE9B562213E4B72612A
+:107310006B2F4A347F00D6E5A37308BF49D3785D4D
+:10732000A71C700BC92528EDB964B74F75577D9B15
+:10733000F4FA632887E4373C6AF5F0BA038D28B382
+:107340004416723CB15F70356C5A1313471E499B4B
+:10735000F1761AAEE3ED3495E7CDF079245AB7E72C
+:10736000ABCF5D34FFC01776E65F1EC9708CDF7649
+:10737000264DD0E78174EF1B8C97FA4C56A61E9FC2
+:10738000CBB3A81CE0D26EA4770C2EA37C0BF073B9
+:10739000E9BE00AF27BD0F03278EBFBC1AF9CB7E15
+:1073A0005D394358026552543F57380AC2F9227E6C
+:1073B0000865237DD3EB7FCCFA3A09F530B9E2D0EA
+:1073C000171F17B146C6E749F6492FB4AAC2CF6ABC
+:1073D0004B137AAEED6125D88AEFDDA8F4278DC076
+:1073E000B6C8ABCD5434D2F7A53C6FCE1DC0F26DFC
+:1073F000710425D243C9253F4F3BEB774D03D8FE9F
+:1074000095CCF437F3695CBA4117DF574497F1BD67
+:10741000917DE4BE79922083F83A5B76F2BEA79C18
+:1074200014FAC7AC6FE4F02F1F257D33A0C74F09B6
+:10743000F4CDAD645F0D7D0372E97EC2CFB417F465
+:107440003053D733187D301D261FF2B53A13E89715
+:107450004AA84D45129F57BF98F988CEFED97E01A4
+:1074600012A3BC17E528E679B33EBA283D5E1F9DFE
+:1074700086E9D9576851BC94DDEDD96F8FC187A1DA
+:1074800087A27809B29C98DF2381E36C5F2D21FDF0
+:1074900071484E25BD3303F98EF33FAFCB49DA6710
+:1074A000C16F13FFD7F55C9944B8DED15BE520B11D
+:1074B000599E236B7F46FF59D93B2F003A5C48DF2A
+:1074C00019EFB58243738E267A58980EB28AFD98CA
+:1074D000F70FB64BD5A4179169A9F3C69D5B1F2C76
+:1074E000CFB1F17B76F416A7128E9C80F12DF2AF0E
+:1074F000A247623FC18C6B338E5BF105168E1B6B0E
+:10750000D99F90A5909E77888F4B8B0253D84EDDE4
+:10751000817138F9AD83BD68B7B0DD81769EFC948A
+:1075200056E76CDEB7B15F637D77A4CCCC86D2A181
+:10753000FB375AFF1732043362FA4AC44638F67FE3
+:10754000618BBB6ED0F35C7430E83995E829FD9F00
+:10755000D3F35BE91AE3C14CD7FFE9FE0B96574220
+:10756000A2BCC0FF2FFB9F06BEDFF58B78EBB51CDE
+:1075700077549F142CAF9697201D26913FEE89EAF1
+:107580000707FE237C8DEF6E677D5389FA86FCCC5E
+:10759000FC8610EB97C939225E32EB8D4B7BE03ACB
+:1075A000D28F53C2E8975E80FEF88CFE2797F3389F
+:1075B000C174CA43FD71FEB20EBC345E838C1A7C6A
+:1075C000CFF83EC543760FFA3212E605CC76C3F00B
+:1075D0004B0D7FD43CCEF0470D7BD2A4D3E170BAE3
+:1075E0002F44EF07550D90BCA15C851EF330EC35A0
+:1075F000F2178EA4D5EEE4FBA343018E038A41A5C6
+:10760000BC0ECA2BFB61150E67581E3F543E934DAE
+:10761000721842BA509E20E0B404474843D781EE26
+:107620007680FC3E7C80DF5F9F2EF2A50538869930
+:10763000D604ECFF178C071FD9DD82326C719F7F57
+:10764000D2ED4A9F3EDE6871DD07D329FFAB40C013
+:107650005EF6CFAF9796985F46F4F1FE91E67154CF
+:107660007B79FDF92A78C88FCF57429207DF9FDEDA
+:10767000A049679348869DC6F9F26B34B697F9C363
+:10768000B14FE3C9DF49C097F7D2ADBCDE4647FF33
+:10769000011BD2C15FD35CEDB244FD74BBD5E7CD15
+:1076A000A7FC51B7F0D781F27D9C3FF648B41F6527
+:1076B000A6A08F5F15F1951354D69B153A1F2B1C6E
+:1076C000359CDF219B689F3274DF92E6E5C179F338
+:1076D000400B4C89EA5523FEC16980DE63D6AB03BB
+:1076E000BB5FBF2880F2F8D6FFFA3405F0FE3B4AB4
+:1076F0002485E871FCDE9753BC488FB7EE15F1CBBB
+:10770000CD26FFC89621F8539751FB15D1F59695D4
+:107710005F4D8AD52F707716CBC56D419982E1B345
+:10772000F2B3EC8964CE3D1BFDC650465CDF90830E
+:10773000463B3427F2AB2FCB10F1D96D1D9B6C1457
+:1077400047D765F85233F0FDC775FFEF78570AE762
+:10775000038CF52CEC9860237ABFD36387302BC859
+:107760003EABE0B3F76A691225EFC59F799D07F636
+:10777000E4DB2C38DF62092222AF05077E86FD0F8D
+:10778000726458E319BA8FC56FA936CAB72F9E0124
+:107790009100CAD5C23BA4D577E1F8853E27797020
+:1077A00043F6B920101FE72FD1FD955B1FB09AE279
+:1077B000A4E603942F5B84F3503CBBB83DFEFE600F
+:1077C000EFED077E4676A0DBC67660C979E2A7F2C8
+:1077D0000C3DEF3209267F5D42FE4AE98F4AB573C0
+:1077E000EB25C35F39BE12083CF0D7950E6E4FAC47
+:1077F00054B9FD4AD7D7CBBAF71E605C2B7D93C82E
+:10780000CEEEE87D3FF9462D6A372EDBF4E9FE9F88
+:1078100061BF9CF65944FA326C253C5EAEDB8D2587
+:10782000BA1F52FE85D96EECFDC3EF28CEC6FD6FA0
+:10783000E588EBC2FC919B40F92C960E861D31D356
+:1078400063B0B724997072BD41173D1FFB3FA5CBB4
+:10785000B99E6B9411D709F487214F5FE979874569
+:107860005BE6AECEC3F7B7EEFEB0B05FE8A5D7C01B
+:107870001DC52B2A7AC6DB1280C81AC4A7AFE7073A
+:1078800007884E07086F95D4BF88EFE754217E51D3
+:107890006E97F47CF4268C67F9CAB1E4501BCEA134
+:1078A000F8D28C4333FECC783B65ED2F24FD60C6C7
+:1078B000D92909E627DA577D8638BF58A479675356
+:1078C000BC8B666DB5CAFB11FAEFB8D27EE0872497
+:1078D000B75B248E0F1B9FE97C9AF4D1D2DFFCC4E6
+:1078E00045FAE823A5DD4DEF6BD87A9FCB4B7A495B
+:1078F00009B8E8F98F82422F99DFB747A7A3712E05
+:1079000070D62E3D10597D0FD2E30CCA33C96F5388
+:10791000D7DF56DF437186D711A1B8F3B8D23F9BAA
+:10792000D671DB0267738B87E2DBF87D2F7DFC2746
+:107930006E8DF3C7817C9D7E1CAF366DB17AC238E7
+:107940006FD32BB2875EE38708EFCFFCBC3FF4BE5A
+:107950008DF4B76A8148C1B4A1F7918D36921B7F2F
+:10796000D7DA4F6417B5825F7EA273CC3943BDAEC0
+:1079700087CD387E2A23FE3C01E9C3F9D400AE8BC3
+:10798000F2471014FAB8F5D7EBC7BF8BEB3BB1E564
+:107990000597541A7BAEB08AE93618BAF5970ECB24
+:1079A000B9F17B4AC77BD46F09F2735AB7240E83AF
+:1079B0007A44DB600DBB286E6BD864F504F072432B
+:1079C000A70C0EB25F47EDEC3734747ECAF86C90AA
+:1079D000BC1169026FC325C5F811CB3A3F984DFA27
+:1079E0007659AE0C3528524B779E16E3BD1049C22E
+:1079F000F1CBB6BF3BFB87D447BC3B12F0AB2AB4FC
+:107A0000D726E4C6C4AFD0BBB3C91F6EFDF5E7CC23
+:107A10008F8FF648905D34F4F9FA4D1FD8C89E9CBC
+:107A200040C664A4097A91DDF087E405B6D444FC2D
+:107A30000B5FFDDB0ABECFF9BFF3F1F1213A6BCB4F
+:107A400062BC3FF55B5C47FD9B764F0DBDF7A9DB44
+:107A50005D8038F8506916B8FFF97D6EB2C3F5D66F
+:107A6000805BE5565CAFFFC59D8CC72587EF748BA7
+:107A7000F8C69B2BF245815CDAE7E28DDFE57DD627
+:107A8000818FF158FF73B996F234A715A8DE9E4096
+:107A90006E26654AFAF9DAF7C7DF23CE0380E2F3F0
+:107AA0000FF5BC69E088CC7E9B1DAE4D9D1B937F7E
+:107AB0004ACA14F63800C1B7E95CD58FE695CF41C4
+:107AC0000E9F9E4DF3DC51A434D33911EE3FA0D369
+:107AD0004BFA9AF302A029317E56D5E12BB2292F19
+:107AE000668741DBBF56B05FAD91DF13F31CD3ED6A
+:107AF000C3CDF661D2A5D8BA13E74D17EBFBC0BFD3
+:107B000023108327FF131F329E00ED776A8EE83F14
+:107B100046F2B8D0D99C8A74FBEC95F76D74AE151B
+:107B2000C0FD8CA0F5F67DC07DF0646934DE98DF81
+:107B3000DF6D8F9E07925C6FF9C024D7F1F7D17E7D
+:107B4000333DFD90AA51DCF6A12D329BEC7900DF8C
+:107B50004BF50575EBEC71E78D51BC98CE1775F9B7
+:107B600034F29C4B4CFE98D19AF5C284CC78BB067B
+:107B70001BB3129E2F9AE390066BF057449F86A387
+:107B8000768E5F1A3A85FCA1431D1981F2F071C708
+:107B9000FED76EC47D7C1CB266D6F0DBE2F56DFDCF
+:107BA0000E945F1C2F23BD9358DF7ECEFE94618F11
+:107BB0003E76E2C57109E416AF27945B27B03EFB21
+:107BC0007FA567979C43CF7E2F73889F908AAF8154
+:107BD000BF3EB9EC62F22FCCF435F4AB596F9ECEB8
+:107BE000D012EA4DD0EDBC41C7A5DB4E326ECFE4DA
+:107BF0008AF3A6A62D7F633B86648DD811B74DC14D
+:107C00004FB87F1FD931EEEF9D278D4FB4EF787AB3
+:107C10009AEF5F4CBC65B989DC4C74962D2E8FC8E9
+:107C2000CFA97C9EDF4A7693F4B4A602F111664296
+:107C300088FC0EA9E78F7FA3F799E38AC04C18DD73
+:107C4000CCE7BAB036B63E27A4E8F51481C4F539BE
+:107C5000ADB6E8792EDD3FD779EE715DCE3D4E951C
+:107C6000CB11AC999A9CA8AEC45365491847ACCFC8
+:107C7000147ED608DA33B67FCAD4C4B9BA5CAB274F
+:107C80001A45BC443954D67F692E3E0FB6EAF51921
+:107C900038730E9F1F245B3E4592C0CE7573E72854
+:107CA000941F2EB7DC5E82FDE7D72D9AA3207E3C81
+:107CB000D32C3B8BB17F68DD6271FF524BB915A1AC
+:107CC000FF78A06ECE2CCA1B58DEFD29ED4F59A5BA
+:107CD00000D58F94B47DC0FD3BACE2FCAAE9D95D30
+:107CE000F5F4FE26091981F46F73859AB98E210780
+:107CF000D455943CD676FAE8FEEA5C8CE7911FFBFB
+:107D0000527DDB33C9AE38C22EAD98E24AEFFAEFAE
+:107D1000E17DE588956242DCA7C8838FDD392D8738
+:107D2000F4EEFF85F7EFCD9C78EEF79FD871D57C08
+:107D30001A3F560655C6F9CA14AD8AFA768CAF2991
+:107D40006E33F850A608BA973A6D1CCFB5A5797373
+:107D5000084F7FCA34F875616DAB55F8A572B2C093
+:107D6000819C6A69DE8EED6B3AFF5FD7E9417F94B3
+:107D70001718D89DBD99EB56205248FC95E5CD9D2E
+:107D8000448F488B029B29FFBAFBF14EC2E7EB36CA
+:107D900007E78F6E487DD07A092EB9CC51783B81A8
+:107DA000FF4DA9E34E6A7F9FE57B2F53D4878569FA
+:107DB000DE1B6F96C5BCCEE614B29FE045B91279C2
+:107DC0001AF6DFC18772456BDE8772358154417CBC
+:107DD0009D93791D726A07AFE306BB58C7FC6071BB
+:107DE0006B3FAE63823D7811C557F8FE41C2C18D2D
+:107DF000E86E119E0305D04B7C7BFD964B3789FDC9
+:107E000015B0BCB2FCF3F9FB89A7683E3FCE4FE743
+:107E1000A87EA99FFB3B15871A50857E5F1093773C
+:107E20007B16DA5F2E15F9FD568A3BA6E971B191F2
+:107E30007F33EA0D26F7FAAA9CA4B0E51E99F4CA8E
+:107E400069F4D7488F99F36E534CFA775AF7C7AC59
+:107E500097CF771E9892A5FBBD799047FB08D17903
+:107E60002039BCBA9DF4D0796002F98F390FCCCAA1
+:107E7000BA80F3C03B33455CA1519D1CEE631027D3
+:107E800026BE0D1E5A0865155C8FD00C69E7B6AB8F
+:107E90005D26FD6FE07CDC2BEAADA4CFC6BD02B74A
+:107EA000D07EAFD0CF4F068F03D7034EE877707DDB
+:107EB000A0B5D71A0C4A31F528472D5C8F32089EA1
+:107EC00020D7AF04EC6A80F5E578AE3F693BAA9F06
+:107ED000F7EAF50CE58264FF743D84B9FE61AAAB54
+:107EE000525E50C1E73320550EAD7F982ADF2493B0
+:107EF0005E8143829F67EB20E45299F6753A0C400D
+:107F000021DAA45762F88DFF4DCE0CC85CFE742CAC
+:107F1000FEFA54132ECCFCFF4E966E8F75FE9FB367
+:107F20008EE42391579B00E3B98EC46AAE2379C3D4
+:107F3000C2059BD13A92F220C9DBA41691373E5F6D
+:107F40001D8FB94EC75C8793EB8BA7537EFD2571C0
+:107F5000F72F6A2E8BEB5F7CF7D4B8F1456850633E
+:107F6000FB250FCC891B3FA2FDDAB8FEA80D37C652
+:107F70008D1F135C18777FEC134B13D6BD1838197F
+:107F8000175A1E777F7DF253EF13BEDA726595FCA8
+:107F9000F94BBBEF31D5C54C675C4C35F2F03AFF7D
+:107FA0008DBA3A2A03233A4F44FE3F56447ED3BD4E
+:107FB00055923614079E7080EDF83F8B83874C38BE
+:107FC00030E4FF7CF99B75BADF2327154AE4E77894
+:107FD000D1AF4A9A4675C4E2DC1EDE12F52A9F270D
+:107FE000FD83FD224D7279E0327AAB2A911F7457DE
+:107FF00095C67ED05DC30AF752FEA0FFFB2E8F947C
+:1080000037B42ED45C079AEEF04E012EA115759070
+:108010006DA8E8B95E77A683FD8C872C965B6A63B2
+:10802000D6DF9125F44F4796B05B3FB385B6931EDC
+:10803000501CA0B6E48AE7A9F801A8B207F9E2CA81
+:1080400000511F0647D7CC9A4EF6B37FB49646F53B
+:10805000B3D8BF082F2B41B62737B62A1CE7AD4A45
+:108060007E8AED499922ECC90459D80DB423BFCDBD
+:108070009A4876ED5EABF0B30256E24FBE0302AE15
+:1080800032B6AF7C4E9C0699D2F252AA4F3D6BB7E6
+:10809000B4AF114CFB974EB3109D0617C97C1EFC64
+:1080A000122D09D73B583F86EB9C07CFD6FF69A915
+:1080B000145F0F2E7AE4E49D1551B93C6A4B1CE71E
+:1080C0009D2FEF56BFE991143A47393A1AE2EA3345
+:1080D0008E6509BFF158962CEA13821FB8894C03AC
+:1080E0008BFF6B242DDA2FF5AD76E290FB377CBF4A
+:1080F00096F862EB9A1BA0BCA691C73F1B07F6CC73
+:10810000E0FA6D235EBAE17591D7BBE1BFE2F3D629
+:1081100027B3AC7CFF24BD8FFC9A5EDF44E2DB35E5
+:1081200024109C57F64D24FFA056058DECFE7CDFF5
+:10813000823B0F617FEE8312FBFB749FC65F5B8007
+:10814000F606EFBF0C9E5777E1FAFE9E25D6330F59
+:108150006AADB4CED76E6E4C213CBD9E26C6472478
+:10816000D036C7CC778D3EDFEB372FDB45713ABD7C
+:108170008FDE4FEBA1F7CF55A198FAAF81EFE4ABBB
+:108180004543DF7B1D78AD7ABD9795EC6409043BD0
+:108190009F26BD7AD0E25903DC8633D82ED9D92E5A
+:1081A0000DB4449E5A81EB7C67E9DF764948D7B726
+:1081B00017447EF5345EFF970D3268888B4FD37D70
+:1081C000567756944E47177D9A42F4447F65EB4F9D
+:1081D00049EEB6D93D54D7F1E6D26D2363FDFA548A
+:1081E000F78C616EF2AB2A2FEC3CADEAC9298CBF4B
+:1081F000E55B05FE96FF7A5436E16C79CA59DC8955
+:10820000FED6123E279D2441C2F878CF4AF1DDC246
+:108210000EC4998638DBF385A82BDF7928BD9CD660
+:10822000A780EFE2D8FDEC7CE9C6B15CCFFB46E667
+:1082300005AD93643680FAF7065695002FEA723240
+:10824000BF27A35CF727C7D2FC37FEEED727FF93E3
+:10825000E8B27BDBD61FB28C5C181D86D6D1AADBB8
+:10826000583F197118D5BD529CB6DFC276F20AF993
+:108270005E8EC3A84E83E3AE61853C1E158E6A15E3
+:10828000FA4D7C27817E70AB87EB3D595EEF5685BA
+:10829000DF62C449B2C593A3888F0C5E98C6F317FA
+:1082A00003E5C75C145819FA0AFD08976CD1F51557
+:1082B000781D189F8ED5F559B57BC2556DE2BC2649
+:1082C000CEFFC47E554702BFB316FFB1DFB9D1D789
+:1082D0009AC47669A35C4A7E87D711263B6EF63B2B
+:1082E000A7C1839C0718E27F3EF7D70BF23FFFD56B
+:1082F0001DEF7F5EA8DDA9776BE2BC77B4D073A1D8
+:10830000F0308E73F0AF9CE46B64B6B04B7D1463B9
+:10831000519D9F746AB403E5B3C15DBEF6019449F3
+:10832000C770411FEAB7E2FF97689FEEFF9AFCC053
+:108330003E85F937F8DC25DFF81D4905CA2119FB10
+:10834000F081A95CEF3CD02BE4A3335DFBD3348AEE
+:1083500033D0CFDC8C4B4C52FA6D6909F6F334E91B
+:108360005F9207B7B0478E6E712EEAD0BC40FA25F7
+:1083700049552750606E8CAF730BFBD578E0CD422A
+:108380001BF2E7A4E5908BCE571A76ED70E176E10B
+:10839000BE0CDFFD84EF65478F4C52B9CE6D532183
+:1083A000C5DFA1F09199EC9F552369279C7B3FFE87
+:1083B0000DE5F41102346DC8E0760CE555F0923FFE
+:1083C0002CF679AABB353D517EC0FFFBB7F6D17EB6
+:1083D000B7BD98C47ECBB6AC3E9683C05C80AD483A
+:1083E000EF27BF18CBF32127781D97D46A12D9FB4A
+:1083F0005FEAFBD9A6C797A7BE90799C31EFB8EE8C
+:1084000019B28AB82A0DB7EFE33AAE1EBB46FC4D4F
+:10841000DA02823E3D495C17E6DF73A5883BD3C490
+:108420007974E7B0C8DBF49EC86EBB4675AA496A8A
+:108430003BA4E3FC9D366167C720F07738A3D78D56
+:10844000F725F5ACE78F2010175C8F97A4B4C3B75E
+:108450009CB1F44FE1F586DD02579DC3C21627D9C2
+:10846000098C9536F3BAA2EB047EAFB1CE31EC178E
+:1084700077DA227FA17C3BAE4B255C8C01B14EE8C4
+:1084800019A591BF92A48A73F52455F304A4A1EB16
+:10849000F28F87203A07F0D02A382BE75C47382C38
+:1084A000DA77A02C7416EB7E4C60F1DA5905317D39
+:1084B000526495D1E75F75D7AF6D2BA07D093BA8BE
+:1084C00028213E1F77CD0795CEBF93142FC749496A
+:1084D000F3406B417E253BBC7CDF8D73B44CE17E69
+:1084E00098D6AFD27DCACBA4AAC97370DDA95FA606
+:1084F000F2734D7D56AE3B6FF8C775A9A5B8BF1393
+:10850000967D2B3AB0FD784168249DD356A6FADEBD
+:1085100021BC3E736CE1DA7138FEAF9D564F0DE918
+:10852000A5FEC08FE9DC7EE993568DECE2FD6F0C71
+:1085300086BF26FE3E2BB15E1CB08AFBD8D75AF010
+:108540007E53CF87363AD7BAB2FB5D1BE5BFEFC982
+:10855000F61D27FB56D9DD5245749B02EDAD94E71D
+:10856000447DC8F512A11CA12F065F19B9B9258653
+:10857000CEAE6CFDDC2BE2BB98E4A64797CF3DE482
+:108580001F61BB4BF7D376EDFD97122DE6FC34004F
+:10859000FB381FB80A9EE3BA4EE3FA4050A9261CE6
+:1085A0008D7DCD718B3706678E6C5DDEF5F7FD3CFA
+:1085B000DBF70F96DBBDEFD95CB87FFF9F43856487
+:1085C000AF42E8CF7D531DA9DF242F67EB8E8E03CA
+:1085D000EB916DAF75B3FFBDED1E358DE41ED70F6A
+:1085E000A9D8DF85FE05C9D1AE2221772DAF9E190E
+:1085F0004FF9E233BB975D4CF48AB8AD06BE670E07
+:108600002339DA0EACC70C392C2539C4A597AA2218
+:10861000DF534AF826B9B3F5CD61B9DB6501923B6A
+:10862000C437E31DF1AD921F52AA22DEF9F9512C95
+:10863000C79D7D472EE17A7624EF8809D4B730BEF6
+:108640003AC37382123E5F610DEFA3E72BF0FD2D5D
+:108650005A542E2BA4F8BA9E3AB7A89335F4E3EDFA
+:108660006EA1EF43A3B5540F8E4F96E538FCC7D8E3
+:1086700049D1D7EDE80FD6FF74ED3A9487126FB960
+:108680006512F93B2FCA6C07F6E87EF2F23F4CBD4B
+:10869000A6435C67FB19D671B14FF79B9F5B99C3EB
+:1086A0007DB20B1AF26522B6DE72AAF76EAEA25444
+:1086B0005C6575FB7E6AA7D686AAE8B870FAFCBE30
+:1086C000FDE21B37EF58C25BD7BE6F8FE53AE9A3D7
+:1086D00076A0EF38BBFE1E79FB49DCFF8A3D486F70
+:1086E00048E89730DED06233FECE859301A9FFEAD9
+:1086F00069A897AF59FFF8550A1AF4260202EEBF8F
+:1087000066FDD6B5E8BAC0ABD9DE6BB291DF5FE5E6
+:10871000F8AEC946BA0D1CFEBB9BECC9AE57DE7362
+:10872000911DEEB279C712AEBA8A318E4880C7E980
+:10873000D9A26EA7E21CF526CBB3C5F9D6C800AC0A
+:1087400025BC3475C96A90ECB4B7EF6AB21B7F419F
+:1087500052525EBB6E46C045F152FDAEFD5CA76F46
+:10876000C4D38B41FF936F9A4DF43F9D23E2E3BA4C
+:1087700075D6B8F87614846D748EECF7399BC3C83F
+:10878000927A93DF715BF726FE6E64E996F8E71A3A
+:10879000C84F4108359C273E5E9EADFB29255042BF
+:1087A0007E0AE286F324915765CF66E0FAAA5EAAB4
+:1087B000AFDA6611744A76405B6A7AD45F1993EB3C
+:1087C0005D4272BE44C767A75EAF14E994F87B8A26
+:1087D000314F887879EA716D137F2715F0729D5EAD
+:1087E0003D2D00D73D5509F0FEA7E6944000F75F08
+:1087F00089EA99E4A5AE470A323DF5EF5E14FC27FD
+:10880000F2451B65FECE6FA3041945346F84E9B3AE
+:1088100054CF1F2E7B22FEFCA261C3E103E42A3564
+:10882000864CE7413A7DCCE73B3BE87F129CEFACBE
+:10883000CFD6F308855018F75D5EEF857D97F7B1C9
+:10884000FEBDEA117D7E63DC2E5D6F36E9FB6E08AE
+:10885000CA62DFC80AAA8FBE5587891F3C4CA7464B
+:10886000C409E1001E14FC36EA199742AD8DEAC82E
+:108870001ABB5A0ED0F95B9DEED79AF18404657A43
+:108880002DD1EB86EA37C6DF5FAAD365A9892E4DC5
+:108890003EC9B43EE1775FE8FA50735D4F3858DA6D
+:1088A00061E57AEED37013D75F35766DE2F5D4E9E2
+:1088B000FC1BBADE00EF6709EE87E4E942D76BE6FE
+:1088C000DF9F0C9C5F0297C4F1AF3AE382F8570236
+:1088D000EA32DADF60AF886B077B8B392F61E0C546
+:1088E000FCFC6CDD8FBE7283F0374F765725933FCB
+:1088F000307048F14888FBF2173F73D1F73765BBFA
+:1089000065A073D2819EF2B501D4973B7B875FA7A8
+:10891000A11D287B5161BB51FE625930A988FA65BF
+:10892000C9255C67A265501C80F3B01D1E3834FC5D
+:10893000E552F6D367555088DA72A82C99FC859DCC
+:1089400020F21BD28B1519FD3176E5C36C91DF58EF
+:108950009DF3FE43A4A7AEDC6EE57CF095D6C84B34
+:108960001487EDEC553C2DD86F7871E1AA24E2F71D
+:10897000AF250FB9DD07FA9667D2794D638F55B5EC
+:10898000F37AEFDC47F7031D9267048EF7EFBE62C0
+:108990006C27E58936957B88BCC6FBCAD2B447A84C
+:1089A000DE157293396EBFF2222BDBD71379C9FF24
+:1089B0005183FB5AEADD349BF4F089DFEEE4BA8A96
+:1089C000814E097224CA23EF7F8AEA7D4E3C7DD80E
+:1089D00046E7C1555D87B96EE35CF6E0641071C788
+:1089E000717BBB8DE29BC64D46BF9FBF47A9D5FD9E
+:1089F000A8A62DEF727F29C50184C78D7250C3FFD1
+:108A0000DDBFFB193E1F6EEA10751F67EF6F91F80F
+:108A1000BE81F785BADE5A061AE37D998177BD3E9D
+:108A2000CAC0FB69A8E13AAD651D0F33BE17EBF86C
+:108A300036D74D0134DB4A3385BC52BECDFCFDDF59
+:108A40006D3ABE6F3B0FBEC7E6E8F81E036308DF52
+:108A50006766887ABA33878725D3FC670E72F6F586
+:108A60009B70CE76F790EE170C862D5EDBA5D1714C
+:108A7000A7BA3FE5EF10FD87066D547732BBE713C9
+:108A8000E6474DCFDE5944EFEF80AF81E8F79D9E7A
+:108A90006495FCE09A7EA1CFE6F4D8F97CE23B1025
+:108AA0006A233E0FEC79BC2D9D70F32B811B43CFC5
+:108AB0002DD1E97A55E9F76753FCBE54B78783BDDA
+:108AC000B7CF66BD33018AC8DF9BA37FE73D27A4EC
+:108AD000EBA18DF174A7736AE25B538F9DEB4DAEF2
+:108AE000827E1BD9B3AB74FB69B69303B9C9CCE7DB
+:108AF00000DAAB1138BEA1C35447A9F4F37A06BB20
+:108B00006D7CDED564B2BF97E508BFF27CF1BD99FC
+:108B10005F0B72747BA2F3AB2622EA18E6BC227BC1
+:108B2000E8FCA137BCAA94FC05836E667EF56A2535
+:108B3000A9DFF47B092FE97EBED1BF46FFFE2DA43D
+:108B4000B63B63E3F6833916FD9C33F8D372DCE75A
+:108B50001D12F4110E31BEB9A64C4A18DFDC938306
+:108B6000FAE38F05B73E382136BEF16E1A49FEDEB4
+:108B7000FDA857CA2BB87EA78FCF0B95F61A3A07D8
+:108B8000F377583D14D7F8BB65F607FC1DF6A00532
+:108B9000E7BD927084EBAAED91AE201C61DCB09A27
+:108BA000E69F4B29651C37B71BFD117C6EEEAC4F61
+:108BB000187F07878B7D0F2A5A76A238C2881F9AA2
+:108BC000BE10FEAA71BD09F5008D6FD2BF4BEBDA66
+:108BD000F7B7C2A2143AB7FDBC7001B64FE7083B25
+:108BE0006CF8AB11F4578B757F85EA2EEA04EBA085
+:108BF000EEB97B6CA4BF0ED00F5B50FDA4EA5B4DB9
+:108C0000F1B0EA83E61F91A321B5B11C35914C1157
+:108C10000E7749227FF3AC956A43A0E5C830AE0BCE
+:108C20003CF59A388732CBFBA9857DAC2FCE2C70D2
+:108C30003613DE96956E5A9D4EF2BDE775D63763B4
+:108C40007F6B532D6A745F2DF4DD1DC7696D71FE56
+:108C5000F2A9EE561BE7A163BF1B2E1EEA1F359E2D
+:108C6000278F75D0A45770FDECEF0E1C9455CA0BDE
+:108C7000211D7F91174B2FDD1FEADA97C4F66BE0B9
+:108C8000B033487EFF5F753C9ED0F3F22D9532D312
+:108C9000C33245B463F73C534CFC257EF850DF6F7C
+:108CA000DBF3CC255ECEA307451DF113F175D88DFE
+:108CB000A1F83A6B83AE7E9DAEB8AE91F4BDB2B171
+:108CC000AE5D4ABFCB93408E24691FF3CB22C5C74C
+:108CD000B9FE67E5DAD83A52DCCF2DA4F7FED3907F
+:108CE0001725E2263BFC4E8EC6EB6BE911FCB5EC7A
+:108CF000162DBEFF7A91AFB1F2FB87DC9F1968A0F9
+:108D0000FB678A92B9BE01BE08D4507F45B1F8FD19
+:108D1000801547968E8ACDD38124E271BF35C2F586
+:108D20007EFEC3165E9FFFF0A07BB893F4E2A659C7
+:108D300054477B95AE2F0E1427D713CE03F4DEECE9
+:108D4000E83C4B72C47903D07E73A2DF571AFB5DF7
+:108D500005D7321D56E9B87A4B8F73308EFA222729
+:108D6000411C752EFFF7ECBA75FFE9CC0CEDE5EF71
+:108D7000210ECA0E2A018AD777BE911424FBDFB2D6
+:108D80007BC93B140FFBDFB403F9212BF62C19C56B
+:108D900075F83EDFA5A44FCEECB9ED52AE6394C496
+:108DA000F7A5015A5F0EF953AFBAC94F6ADCFD2A25
+:108DB000D73936EE9AF808F94FE82F5D45D7D18FAD
+:108DC00061FC95BD58C1F8DB79A822A384160E9EDC
+:108DD000649AB7F1A0C2758F8D072B5EA821BFE6FC
+:108DE000C599EC3F19FE5239C5E3E43F1D1C1EE74F
+:108DF0003FA5E60AFA0DEC4DE2FC8704C5023F30C0
+:108E00003C0E3F0D5D7F603FA301F55D2C8E8CE72E
+:108E10004A72159E6754AE8E9F90E4657C6C176D08
+:108E200043F74EDEDF326B88F9DDD26115F73B4543
+:108E30006BD44907203D40F478812E211FE6D8826B
+:108E400005146F3E5F14FFFB4446DB912BF209CF04
+:108E50001F15DF193F3FC3372AD1F7C6019829E212
+:108E60007049A77797B53AD1F7BC4FEAF3B93220EA
+:108E7000EE5CD2687F922BF4EA1C9BC85399EF2FCB
+:108E8000CC35EC0FACA5F398976BACAAF1FB2DB9E0
+:108E9000A877AF06E3CFF3EABC4C3AE7127135404E
+:108EA000FF2CD287DFA53C3FF95F95C2AE1B79FE50
+:108EB000B91BE13E91E7BFC94A7AC1A82F99EB35AA
+:108EC000FB5FB557D03CD7A27DA779AEAB8EBFFF75
+:108ED000DDF3F85D37E6EA767C248C1471853399EE
+:108EE000ECC1E95EAB2AF33E82C3137D5F68E89F65
+:108EF000032BC5F9512FEA456A5BC6BCCE79ABE7B7
+:108F0000F71E7D2A8DF56A121423892FFFF21D7733
+:108F1000A2795ACECAEBBC38FC19FC3A497140E937
+:108F2000507EDDA9D3BDD171C2C6E79BD0FC804580
+:108F30003EF777492D633E6F23793AA97FF782EB9D
+:108F40002BB4C7E8FD93B99FF0FD15332112C0FB88
+:108F50007BC7D8D9FE35CE92F8FCA0312CEC61E36A
+:108F60003C610F4776CD65BE5C8F7CF17A584DBC75
+:108F70004675B906BF2FFF726096114FD2394E0B5E
+:108F8000E19CF57426B78D5DEFB6F17925DA5DF2D7
+:108F90000BAFA98CE7DB28F0DD9785F76FA8963C2F
+:108FA000684186F0FD869BE632DFAFD3BF8F391F65
+:108FB000DFB7E7FA36E492DCF70D5E3F0E49F4FCCA
+:108FC000980F0BC9BE369D03D75B0C5C0F8F3C4DD1
+:108FD000E7659EB3E7E9FF783AF63C7DB8DBF71F1B
+:108FE000B9A4572D5FBA2E019AAFFF17CB25E21314
+:108FF000F0F3E792AB2775B97A325715F9DD4C716A
+:109000003E3456EF3F6F0D16F0F714A517760ED8C5
+:10901000F2EC1FC7939E3BB5F7E0785B0C5F4F2CDB
+:1090200047FD40F666F77EFEFE308A3B8B8E3B8521
+:109030005B49BA56B7A3F1383C413824FDBC7DFFEB
+:10904000D5143F9EECBA2E53D262ECECAE975D2362
+:1090500062E63DA9FF2E06C66D23BF9B12BBCEFB69
+:10906000C4797948CC87F23FF2BA71B1F75B753CAD
+:10907000F7339EEF1FDDCCE7F4069E151078367EA1
+:109080000FE3EC779536E0EF1E037BEC5C5F31601D
+:109090008D14A6C5C8CBC73A9D314E930B32999417
+:1090A0005CEF3A19D655F1390106EF6BA7D0E77797
+:1090B0002159D4873673DDE2F466F0106E25D8C8E6
+:1090C000FD49D5E2BC7C2AF4C9B4AECB20C2AD17B1
+:1090D0005485DA995461866DA52324933AE9ECDA34
+:1090E000974CF80ABB95B4BF3844E96922FE45F7AE
+:1090F000AFC05F0CBCE2607482127EA7EFCE137526
+:109100000E9E64218F9193E2774FBE05FDBCFE69F0
+:109110004A1FAF3745D3D2E9BC64FB73CB65AA7F46
+:10912000D9035A84E4CC93D1CCF9B7C80C086D4E5E
+:109130008BEEB792F6AB46FB53E78385F62B418760
+:10914000D87F33A4D3F9D81408F37B2EA705E37E88
+:109150006780A650DF9157A4D359C46F557AFC6637
+:109160007104B8EE27354FE03A5909CAB9159CDAAF
+:109170000E3D4CE73325629F93F13A9FE3348B75A4
+:109180009FB5D77942DF4D8510F319EA417D817F84
+:109190005C61964AF492C26E0BFD9ED885D275C072
+:1091A0000DBC7ED7AD91533FAC889E7B797AB2B926
+:1091B0001EFA41C91291695D8E02510F1D86107F02
+:1091C00097198EFFBDB392BC6B8BF268BF3EF11D49
+:1091D000AEB9AEF389E066AEBB991F40F2D03C0554
+:1091E00000C7DDD13A006B7190EF5BE99C5DE53A19
+:1091F000D3728A177F9FE52BCACBE27AD3113C99B1
+:10920000129C589B12C53BAE8C7F7F271952DA49BE
+:109210001FB5EAF5B401D5A5D73315F23E34D4F322
+:10922000FC23128AA8EBBEAB4AD49FDE356C0FD765
+:10923000F9F64BA04AF974FEBF87EB80E987E1ACF1
+:10924000F9DF70FE9FA9FFEE43B1EF8DC925BA92F9
+:10925000C7E75A8FA570FDAB32D3AB511DAFB95ED6
+:10926000BCA46DE203FD1C971AEB35D5892B1EBEFD
+:109270007F97AE5F5B1DE27780A45576559A4EDFEF
+:10928000BF2FE7DFB16A25D7A082BE7B5FCECF5369
+:109290001D33158146527DDF257A997F970AE13586
+:1092A000F83CCD9B3A92F37D89F831DDE087656823
+:1092B0009D14F2E166E2AF51776BD4DB122068DFD8
+:1092C000C95EF13B782AE2847FF70F9762275C7AC8
+:1092D000CDBFE721EA7FDB74FAE3BA9EE0BA4F879D
+:1092E000F84EDBF89ED74C3703BFFF0D047C0BCE46
+:1092F00060530000000000000000000000000000BB
+:109300001F8B080000000000000B9B29C3C0F0A3C6
+:109310001E8145A451F9E8F82C9A3C0B0303C34F76
+:10932000209EC7835F1F2E1CCD82607B8A3330183E
+:109330008932301803F14C209E05C43F80D8408C00
+:1093400081C110888B80EC6220F6016207A0DA2FC1
+:109350001C0C0C138419186603F1326154739F328C
+:109360004268252E06065320FEC784DDFEC96A0C1E
+:109370000CDB7510FC385D068635FAE4F965140FD0
+:109380003DBCCD1195BFC70A95FFDC8681C1DE09C2
+:10939000C1DF6B459AF9D540BD354EB8E58FB9A10F
+:1093A000F2F779A0F22DD1E41787416800E6955CC9
+:1093B000CAB8030000000000000000000000000028
+:1093C0001F8B080000000000000BED7D0D981C5560
+:1093D00095E8ADAEEAEAEAEEEA9E9A494FD293CC1E
+:1093E00040CDA443069884CAFF04265033C130AC54
+:1093F000A84D94ECA0A89D1F312ACB6B780A01C11F
+:10940000A9F9EF9924A4F3F342F89134D12CA0AE3A
+:109410000EC87323B2CF4E88BCE0DBA711D12F6AF0
+:10942000F01B621E4FD45D67D92F4BBB06F3EE399C
+:10943000F7D64C574DFF4D02ABDF7EAFF3E1F5544D
+:10944000DD9F73CE3DF7DC73CE3D7547264D247608
+:109450000D21E7E047CB3F780921CB264BABC3C8B2
+:1094600092A5B4FC0A31FAE8A3CBB56C8740CB05D2
+:10947000EA9847D009B9229226C443486CF431E2F5
+:10948000A1F552F532196924C4AFAFAD22EA64BF29
+:10949000EEB2AF9B90ECFCE2EFC523C3513D44FB21
+:1094A0007B6A799749FB493DDDDA65B64CBEAF83EF
+:1094B00041297E4D8462534BC840C35EE28910321D
+:1094C00044C79E4FFF53EE4B90386D27678789BE88
+:1094D00000EA55637DE5D9E39EF5F4F99097748D24
+:1094E000D2523964658314EF85CF6B8B454A8F5F09
+:1094F000323DBFA5B03FEAC95840477417F67B8696
+:10950000D20543BD5BF42C017A281D6D15D2D356CC
+:109510008C9EE72D0BE8B9E290BE289F1EA59ED138
+:10952000A3D4F7E23C9D89527A1A2F849E7B909EA9
+:10953000214ECF908B9EF7717AD6D9F4D40D223D6F
+:10954000830D941EFAC8779F45E2B4BE02F484A04E
+:109550009E939E41A0A7A5003DCA9F879E4F72790A
+:109560004B023DCBCAD393047A6A2BA0474D138D8F
+:109570003EF713C11C6D998A979FF371C1B3E9A897
+:1095800045FB1D7E5BC479A62B32BA76C164BD3122
+:109590008ED7F71A07A363205FF3F64609ED6FB87D
+:1095A00041C0FAEE7E1F2232D6AFAD377BA0FFCB93
+:1095B0009E74F63FDCC0F0B5EBFF139FC77F2222FD
+:1095C000B6AB51E3C3000FCFFB1649C038DE74546D
+:1095D00083768DACDDC0BCE55D636AA1F68C9EE14F
+:1095E000FB2D9467257B0FF2EB730D69A253D8FF17
+:1095F000648200FFE528C3C76E4FF122E44A20FBD6
+:109600002ED364F811329BCE937557D6A2E3C5D200
+:10961000B72B71CA8FE1BA5E05E84EE9BBBA406F5D
+:109620009D89C9446C04BC0AF3C1968B6BC836A5EE
+:1096300089CE67DF2BA23142A6D6B340B86A276134
+:1096400049F5906C33C1DF3902F42470FE07E6ED72
+:1096500045BA65A06B01D095243A7DFE1C971FDFAB
+:10966000B31601B952742B6A2D983A4E0AF8DF02EC
+:10967000BDA6A36BF3E8FFB93DBF745E5DF38B7CC1
+:10968000798898590BF8E277CE9B5DBEC4F97E4588
+:10969000BD85FC2D37FE54FAD9F87F4F74EC87282E
+:1096A000E9683C3489CFB077AC17E49AAE49E3203F
+:1096B000ADB2908ED39EC76FF77813744A69871C3A
+:1096C0007F8BF369D83F7E24BF3F373EDFE5F5BE91
+:1096D0004B342C6DBA161E62E394EBFFC7C0E25AFE
+:1096E000A8EF5A5792E5E0FBBDBCFE15CF3BEB154A
+:1096F000E3CFE727F86345411EEDF5083F732621C8
+:109700005C64F0A72E27E452F83FB4C9EFD78FDD91
+:10971000054BEB1791C419E8E73692B8383097AE8D
+:10972000176FE20928AF95CC7F83E7B495F6FAE589
+:109730005CEE44D4036C3CDA3DA1FD87787F92D087
+:10974000490895675F2BC98C50D4DE239ECC0A94C0
+:109750009FBB0831666979FBFA29B6AFAFD432AB4B
+:10976000613FBF4AA284D0F1AA88E68712EA6769FE
+:10977000BDF032D5A023111FF94855BC80DCF89705
+:1097800012CB5F45C76F951DEBC26F2608E8855069
+:109790009464FD614234211441FC5790150C7F5DA7
+:1097A00080FE6A24BD47A2E388318F71803EAD6A96
+:1097B000232B37E4C9A12E30F9ED89793C40D7201D
+:1097C000D5FF3EBA24C30D74BDC37A88527BA380F3
+:1097D000DC4EE8F79C48B23368BF39816497505833
+:1097E000252B13B45DDA47569EC6718971A0809C03
+:1097F000AD13D8BC0AB1F173E7D02E2099EBD02E6F
+:1098000048E33A96636913F601C50C1B3E98F6B31C
+:109810003B985E93880972521D4B67ABE0BD7E4951
+:1098200023E03B2B9624AFB5B0F2541EBE8A6A45A6
+:10983000D17E6ABC44E8CDDBC70E53F93995276F5A
+:10984000A9FB991D30D038C8F5CCA7507FDAEF3F7F
+:10985000C6F9248F5164802E5DCE340953E53A2534
+:1098600014D6131B39BDF0BB76B9535EA5995C5E67
+:10987000E9103E89A07C0D3D4532802FE5E491F54D
+:1098800014BEFCA84246A87CB590E31E909F856458
+:109890001C4B836822948B8981E55212C7F2F7ED45
+:1098A00054EE69799B49E5BD09E5FF2601F68986F5
+:1098B000C4FC307DEE8F5957C2FE42E57F1D3CA7A8
+:1098C0007222803CD598A4E07E592DB0F5BA53D2CF
+:1098D000FC506FA749503FEE11FA2CD82752DC4EAE
+:1098E0004AF989631D3FC0E94EF1B23A96206330D0
+:1098F000BF745E40AF1F6EBC15D7B14F62F0209DA4
+:109900001794BB556C1F73E3A1C0BC2C38FF79586A
+:10991000F7E79F87416159C179188279582730FD4F
+:1099200029FF9A8D5F823EDCA737F63C8EFC974F6D
+:109930004FAFBE4DFF7297DE5CC1F5DC5564FC2273
+:1099400089EA91DB7D59591210EF2F02DEFFF6B341
+:10995000E31F037AC858623EEC5314EFC704E46770
+:10996000921CA7E34BAF8819F0533CC11B944409E8
+:109970003F8568549F295C9F35C1FFD66BAF07A711
+:10998000EADF4B463F7902ED0DA22446403FAD4A47
+:109990002A20177DF56B1590A3A17A0A83DC446514
+:1099A00045B882962AE904F9B3ED8F17A21B14D0AB
+:1099B000CF723431C397B7FE574713E457B0CEB5D3
+:1099C0004454A474C899EB14A067405BABE4FB5704
+:1099D000B29A88CA54DE86A05F18C79B5404D493F9
+:1099E00064462FE5CBEAFA24F67338DA81F80C687E
+:1099F0001BB0BD4EE26837BD50BFA1B311F68B5707
+:109A00003612D063C5F8E1B6A37D6A92C879FB81AE
+:109A10004F4B12316F3E7D52320B7888D1C2FAF52E
+:109A20000497738F1EC77D85A41F34152ADF5E3E01
+:109A3000D7DE28F999B0306F3E2279FB0B9D8F411C
+:109A4000BFD15568FDD19DC2D9AF21106579E5FD23
+:109A50004EEEAB7C7ED32B526338BFA134CC6F1F4C
+:109A6000D5EFB87F9E0C650E52127A5625F7C37B50
+:109A7000AF2591DE0876D30CFBD9DDE26506C8D9A7
+:109A800003C037CAD86DDD0A9623DD1A96A9EE28E1
+:109A9000960F06BFF0C4186DB7C5F2693E5ACAE901
+:109AA000BBBF01FD51EF3A3E02FD4668FFD0AFA4B7
+:109AB00068073580D9FEE28DB1F2660FE3A3EA09AB
+:109AC00020BE8B3CCCDED68989F292D64AFBE35588
+:109AD000AD4E7B36640426E59EFE176CAE71C07EEB
+:109AE0007DB6A3BE7B5DFC80EA26C0C72BC589D1AD
+:109AF0000265617D7D5610114F515C340E768634BF
+:109B00004BC6FD7F4070EAE7473C6C5FCB7814ECB6
+:109B1000374AC65F3847F9E1D53C68DF84AB9B46DE
+:109B2000B3C09F5AD998478BB0774CAB29301E8968
+:109B300048BF1BCB5BCF4F0966A3E72F804F53E88D
+:109B4000EFE970C875CAC3F6B5B37CBD883EB30BE8
+:109B5000F449948A2141F9D01F073E78826D46333B
+:109B6000E5C340B5AC83DFD3DFE329B8BFB8F92044
+:109B700056DD12053DE8E6FBF35C8E9EE27CBFE617
+:109B8000EC07505F6CD73C9D19D41FC73B419FF732
+:109B90002FF57840CEFF62F8E7A2E3735C7ECE0A31
+:109BA000137420DFFA23CC3EDEA651F981F51C6147
+:109BB000F2A3936C27BE37285DC254BADCFC7BB796
+:109BC000E9B3F95E55ED89675A00BFF138E2D7264F
+:109BD00015C4EF3F8AEF365EEA045E598697F19727
+:109BE00081D7534262BF87C20F70797D401A5340BC
+:109BF0002F34423DD03B41B68EA6EA25C1DDCF933E
+:109C0000A02776403FB4FE0E69DCD18F5D2F047C27
+:109C100060EB22CED685F4675D17365E231C6F9D00
+:109C200064985C371796EB771B2F7B3FED0D5E4DED
+:109C300040DF54AB71B4B367A9F12CF0ABAF56D68B
+:109C4000C1FEA10E11EED7D854CFF3876AD745D104
+:109C50007E09AD43FB7BC01B477BFC58EDB7CCF5C1
+:109C600094AEBEB355C46750BB3F78F5311DF4E2E6
+:109C70003111FDB2BEB37367250BCC7310E26014D3
+:109C8000FF00E087F6B33C616C03BE7D2A557CB4CF
+:109C90009F375B4806F4A95735A3605FF72D508CBA
+:109CA0005EAC1527C0DFDEE0C75A132D53DB07D5A6
+:109CB000C13BC48593E3D09F700E6C5CBA8783BFB1
+:109CC0008EF4098EF705F128077B27610DFBA7B0FD
+:109CD000AE40D782796EEE24DF292DCD12EC9B2485
+:109CE00060C0FCC7E29DBD7F043EBD24A21E74F38C
+:109CF000E75931E113F3E25EDE4802E7CDEEEFFA19
+:109D00005A09F5A8544F323E01468DA31DD957EF8D
+:109D1000C1389AA4AEAD2A695FD757665F131EDFBC
+:109D2000B0E5A1FDD76CDC80C1F477888C11889FE9
+:109D3000541116BFA826BA40B0BD21C43128D2861E
+:109D4000719388FF9DEEF716EC5730779273C169D7
+:109D5000F42BD17EE7BE0BFD96C1D74F1EC57EA961
+:109D60007A889C9B31D9AF379AC487E4ECB973E207
+:109D700072C29AE02F81F22D790C5C9F6476D838FC
+:109D8000488B81C89D0EBFE946B1C9111F95B5C169
+:109D90003B84302DEB6F33C7F2F4837B7E6F82817F
+:109DA0009641BD4DE658057A03CCEE42F1A7413904
+:109DB00091E981FDFB2215E385444A62FC7748A8BE
+:109DC000590CF6B35D4FAA97B380976A9816E88B43
+:109DD000A1191E4334A0DF6DC7C11F20E20D46A2AA
+:109DE000441C49AA977E934FCFA745673CABAF8CE5
+:109DF000BC0F74973E87F0CA46A2903F73BFC8EC71
+:109E0000176FA0F0FBEBE58E7BC56553F9B69DF3AC
+:109E100077A89ABAD65730F1013990EA5F3C017CB5
+:109E200018A85D132D452FD1A89D93E7172D93CD2D
+:109E300021B1341E5BC5DA02F3A752E15959629C85
+:109E400009F94E120DFCC557983EA2F88685994C2B
+:109E50003FB39F01361BF1B6FAB4113A6F811683F6
+:109E60007C99C2D1D54A5C6AA5F42E3D4044785F06
+:109E700027121174ACD866A0BE6A66FE9D49FF0128
+:109E80001DE136D9B16F81FE9CD8B71A41FE9DF015
+:109E90001330CFC1BC79EE3E447E356F127FFAC8D5
+:109EA0002C1417F6CB1D7F57981F3515F163379586
+:109EB0001770C87752BF11CA1DD46F84723BF51B4F
+:109EC000A1DCDA4D859DCA537F7733C2FF0D9AAE70
+:109ED0008473B264AAB111E2A25F3EB1893EDA0D89
+:109EE00038CC866EFD1D10271F01F84A44C71200AA
+:109EF000E6E7292F89FFDE0E719711BF5DFF9FDB1B
+:109F0000B1FE042CF4425C7F24C4DA8F89C10EA810
+:109F1000BFBB81F0F8B9A9DC94E7FF9F11BD287F92
+:109F20006003B1F6BFED81FEFC920DD777401C7542
+:109F300002A67C047CFC0A8367F73774C0B906AAC2
+:109F4000003A5E53FF456CBC792C6E463EB4B60CAD
+:109F50001F7B71FC7570D806347FA8060E8F894C64
+:109F6000E5A6893EDA5DCDF1AEB01F2225D87EC7C9
+:109F7000E347C5D74D997D8DE3517E3D9868BF81FC
+:109F80001EB660DC9F14DEA7DFE971777BA7C717D9
+:109F9000A52D6142F7E1CED12C4CF52E31119668FA
+:109FA0003F55D71EC76D458E6699DD50E1F86F8825
+:109FB0001A8F7F26305E68F35BD298FDD1EE9A4F00
+:109FC0006FC4C47348BFCAD661A5782F8771F2FAEF
+:109FD000215F5B5C57687FB1CBC80D9E49BB8BFE90
+:109FE00057736DC0016B6D3593761CF063E96C0798
+:109FF000ACB6343960AF7699A3FDF9CED7E52E3AE9
+:10A00000749B7F1CAE75C195CB9FA4F3FDCE627689
+:10A01000E404CCF7E572F0D9F94E98F5EB231FAEC6
+:10A0200062760EB3673E4E781D371E469E1E16A101
+:10A030001E83758F406C3B37DB3CB5FF3EE50B184C
+:10A040008F33FB24E2BF7A6ABCCEEA4862BCCDEA19
+:10A05000F5697D118CBF61BC6D0B35E87DB4BCDD4D
+:10A060009BB855A2FC7ACB7F518684A1DFE40A8895
+:10A0700053F7B9E20A6E798A3D7A73C1F331BBECCA
+:10A08000EF6671401B96EA0B9FFB6F9164A4E3257A
+:10A090006F620BAC2349234731CE43ED6C11ED6C5D
+:10A0A00013EDC7C3D56BA260C7A44C19FD1C297D55
+:10A0B0003BAE9707DA3CB85E7A241DF1EA5FD97BA4
+:10A0C0006C2EF8A3BA87737A0CED801DABE43A5876
+:10A0D00037616A8FC27949382614DCC7B64BFCFC5D
+:10A0E0009A7CB4247DEEF9F838CF234A3708786E8D
+:10A0F00067853CC8FF94EA413DBABD4D7E1CFC9F7C
+:10A10000ED4B3D37C3FB336DB2472CA1DF06B9FDE4
+:10A11000B415E2A8B0EFA91BB09F33862753497E40
+:10A12000CEE1556B30FEDD2798CA5C3C5FF690832C
+:10A13000C8B71F60FC6FC7A20ECC1FB02416F7DA99
+:10A14000BA20D09529741E2E85F1FD8EC6F6230FF8
+:10A15000015D542F1F44BF6DFCC4C6089C5F6A8B11
+:10A160004774A0DBF4BC01E3ACF4E0FB7463F20AD7
+:10A1700003E2B66D1E87FD915EC9F8B12342908E51
+:10A18000336DA7206909F653F321387F8D2C9DB0DC
+:10A1900087EAF2ECA1706B724522EF1CC1B69F8A70
+:10A1A000ED4FA26C8C59F4BD7AD287FEAB107E9233
+:10A1B0008810A79E2DA2DF7CED82A3088B6382E12D
+:10A1C000D3216E6F9904FD3D93C5F1EB0979983E5B
+:10A1D0000FFE41C4736112E2F636B7AF34FA0FF6E0
+:10A1E0001D9FEE3C079E625F9D7CE324AC2BF164D7
+:10A1F000F0350F94AD89BF21E027BFFD4D8C1F3D89
+:10A20000D07A67A047986A879D59FA4C7A6E013DCB
+:10A210006197C1B1309EF312F1969276B87AF253FB
+:10A220003F3C9A87DFAF24971DCFED3BBB9F62F683
+:10A23000DD5BDD9B7F7894CAF8062F8B17F965F3F9
+:10A24000B7A0374EF1FD330DF93779F2B3C1CBD654
+:10A25000D11FF8FA8619067F1CFC6798DFFEF67599
+:10A2600038EFC5F0A6FAE00F4C1FD87E38B3E77779
+:10A27000B495F63B26F35CCEA21E2896E7F20129A0
+:10A28000217B97E5E927579E8BBD9E075799244A66
+:10A29000E7695B35C9C0F912B9C6241B417E056266
+:10A2A000F41AACFEF872BED5417E14794F16D6C5AD
+:10A2B000195D32E05C3235EBFDD4A12C8EAFE49217
+:10A2C0009F72F3B9C5359F0D5EE77C8A245E0586D3
+:10A2D000492CAED46D02BDA3CA06AC4FEA1FE8F903
+:10A2E000FE8F3D9F64058B8B896A86141A7788EBF5
+:10A2F000F1A4D7BCD40BFB8D377902F4B0B54A4634
+:10A30000FFD85DFFE35EE6BF0D3612C962792DA866
+:10A310000749A769C2B95F4AD0920F6B887E1CCEED
+:10A32000BF4097837FEF8BBE6EC2BA7B5424C9199E
+:10A330006DD45FF63622FF77ACBA8BD9A1EF2582B8
+:10A34000580DF52DDCDFEA4C4DB0EA26F3CD88D66A
+:10A3500013BD314F5FDFE4657A6DF2BD15BDC9F104
+:10A360009ED9EB83216EFF697DD11B4305DA571718
+:10A370003EB77E1FA7F3262FB747AC3ECC83494597
+:10A380006E3804269B74CD607A3D2D4D2D89725B0D
+:10A3900040BE6F02F9F352F9663B15936FDB5E28FE
+:10A3A00036FF6E3BC1AD7F2A3DC78DEDB9B9E438AC
+:10A3B0006EFF7D90E7BB516977F0C9C7D7F942BE00
+:10A3C0005E26EDA934870DE48B0FFC7D3817075905
+:10A3D000C8B3C776733EFA02ECBD1B0FEA676F0184
+:10A3E000B9F385991F8E8B11EC3AC970CCF7047FB5
+:10A3F000F879E8418E4F2C7D358B0B87EC7CB94A80
+:10A40000F547E93C39AA3F1E28A53F4894C5016C91
+:10A41000FAA7E2C9F814E5F33ED430EDF8C42330CE
+:10A420007E09BEED3F1FBE8DF03CBBEE811F1FE1DC
+:10A4300079094EBD7DE93A8C9F15C393CAF5A8B73B
+:10A4400080DE7E17E7E1BBDEDA0B9F07BB5E51FEC5
+:10A45000F37AFE2DA27E9AEEBB8D928576D4B0BEA5
+:10A46000CB427B0E6885FD3EBD08F3CD488CA07EB7
+:10A4700084869037E5D74DE45F801818D793EB9D1D
+:10A48000784A11E77943B4CBCADAFD82FEF66F91C0
+:10A4900071DC89B896CAF2CC6C3B149615F82D3E47
+:10A4A000F2F9638DAC1DEAFD62F44884E90938FED7
+:10A4B000017BA358BEDB24FDCE71A21F8A97D65321
+:10A4C000AEFA4495F4D70B9C234E6D2791D7F3F445
+:10A4D000DB5BB08EF3F213CC27D77761BE1FF11888
+:10A4E00010EFEC8BAE23094AE720617A2505E54A97
+:10A4F000C83F59ACE13985CEFC3F8FC2E4F125AFAE
+:10A50000EE88DF8A2AF3A7ED7AE5E6FF6EBA3F15FB
+:10A51000B28F2E97D97EF1D61792BF87BC066B44B7
+:10A52000D0C10E3EDD9D43FB6A43F65219F2D716A9
+:10A53000CA33B1DE863D8DF2EA7C7B89B0BC018AEC
+:10A54000889CBF3EED7529A77D4780EE536916179D
+:10A550003995FE57CC0B38B54F443BFA54EA832566
+:10A56000D7D369BE8FDBF54EEF134DF453524266DD
+:10A570001E6D7F5A32C305F308A8994EF2F4DC270A
+:10A58000D2A2436EDFBA3F2183FE39DDAD08BFA200
+:10A5900073752BD049F1DF906E9421FE558E2E48B5
+:10A5A00067CFDF376C3AFB55E6D7F5ABCC4FE9D731
+:10A5B000DE447ACFD0E7A5FCA614A7B35F2BAC5F2F
+:10A5C00094103BBF55BC56E1BC0917BD7EDDB94EAA
+:10A5D000DF69FC8655765E3B2CA595F3C127645A4E
+:10A5E00002D8D11AC9A6203F9FB2F165883360888E
+:10A5F000918ABA76F229E19314AF1FAC574D210A24
+:10A60000F057858B28AC513FC81B05FFC373F85525
+:10A61000BA8E86BB8218471E6CDD7418CC84E83D68
+:10A620009FC5D0D33650F6183F7D5F5F7B0B5F67C9
+:10A63000B4F3CF0C76AC8678A544E23CBEE1D125DC
+:10A64000DB5F2BB0BEF3FC65E19C6FB25D313E0574
+:10A650005CFE908FAC2DAD9F36337D66D17FA05FC1
+:10A66000A2AEF6336F71C6C1359207D3F73B65C210
+:10A67000E33537BEABE3CC2247141DCFB13C5A06BD
+:10A68000EA13AB1AF2A742098980DD3EAB39D10E3D
+:10A69000FC2FC7F761C2F2EA08394EF2D7D5DF7254
+:10A6A0003D547FE79705B0A7CF18540A1601AC2C8C
+:10A6B0002A645FD8F95A1370EBCBA80F0729D61874
+:10A6C0003768F5A0DFBBCD38A5E5AFA7EFF1712660
+:10A6D000E79FE8D2723CADC5F9970D8FE95F78FE30
+:10A6E000F32F4F73FEC39B9D76F074E7E5475C0F35
+:10A6F000959BFF0B1DC79EB7A9EB83E9C3FA3B9F50
+:10A70000C57CC5AD2DA5EDA3A9F37604F7B790419F
+:10A71000CC4C81763F9505977DCE4A8524899177EB
+:10A720000E255EBE7C1FE415151B574CB8FC0DDED4
+:10A730004FEE135412F15C442FF33DDCE81E89EE1A
+:10A7400087C12D57ED919640DE9689F95FC3DD26CE
+:10A750003E9F987F9F87E32B108FED5FEB782EBA9B
+:10A760004742BBC243CE2D21C861DD963B02F53A7C
+:10A77000F7480A3EE5F905B4EA4C6847D06E5D0437
+:10A78000C19E5A3CBFC77EA023A827912E06D38620
+:10A79000006FF59A669CEBE53BE97AD8EAE7B0CE24
+:10A7A000E16A0E6B1C6EE430D9857050A630C4E9A6
+:10A7B000BD690DE100871B395CC3E16A0E37715832
+:10A7C000D885F05699F537226558FF010EEB1CAE7F
+:10A7D000E1B0C6E1260E93036C7C1F8303DE0CEB15
+:10A7E0003FC8E1460ECFE0703587E7725838807079
+:10A7F00051BD1C3391BF93F3DFC9F84608F72FE32F
+:10A800002EB86BB27E9EFF39D0AD0BF9E78ADE22FF
+:10A8100071A7C53EA667C6DBE398BF44FD52EB5463
+:10A82000FE792475A00AC52D4DDE6EE23C3D5278BE
+:10A830005DD8EBCEBD2E2AC56FCD79E2F7A1FF2002
+:10A84000FC3EECB3D73DF3C7C7DB0DC4D3DD9FBBE4
+:10A85000DD08D52F24CFFF0F48190BBEDBA0B60FA4
+:10A86000FA355EC599E77AB7CFCBBE5BF1B13CD77D
+:10A870003E8EDF783B3B8F189817C81C10A6C61772
+:10A880003FE763FEFFF76D3C9551F48F8239BA6262
+:10A89000F3FC9DE1584799FC75E9DFF3F314DD7192
+:10A8A0008F7F8577749C805A984F774FE89B5BAC7D
+:10A8B00053B4AEE2A7CFC16FD122D1FAFC7C6AFEBD
+:10A8C0009E081E11F5CB595ACFCE2311B17F3C976C
+:10A8D00020F52CEE25F2FA384E23FB8EC15C0CFBE2
+:10A8E0000C7DDECCC711A6F6EB6E97F5D5B0F9E27C
+:10A8F000F8D8792B22791EFB99C0478A23BFDCCF79
+:10A90000213F59532FFCF985C25EBDC87869763E58
+:10A9100054AEFD135C5EA6C86791797DC467DB29E0
+:10A92000A3269C23D97264CBD7F9CAD105CB096C75
+:10A93000484B8BCB894592B86E247025174D5F5ECE
+:10A940000AC84936BF7EAD52CDCFF90D94178A8F14
+:10A950008472AB317C6A1747B03F01D6389EB7701E
+:10A9600018F840E9BD5CA9E67C60F18C009C3BE6F0
+:10A97000B5A7C421BE02758698DE67F5AE51D83AF8
+:10A980005FD551CFF027BC7F17BEB43F25BF3F91A5
+:10A99000D4BBE49CE1FDD70A9B5F5A9FC55DDCE315
+:10A9A0004B02E22B92B8E5A1ED3EC3EBBBF5975D00
+:10A9B000DECFF11BF690CD2CCF234EF2BFAB0C2A8D
+:10A9C0001EFEDD235B676EFDE405B95A72FE72550B
+:10A9D000A95EAF550AEF3B54CF37437CB6D8BE7360
+:10A9E0004299D80F9AF9BC4D6BDE7F077A68D9E49B
+:10A9F0007C568AEFE57CDCE9E27B7A2ABE15C9D970
+:10AA00009B5C4F548ADF35E789DFCB2EFCDE29B90A
+:10AA10003ECBF7A34AF1FFEBF394877F9CCADF8A12
+:10AA2000D69147991E7F3F739EF8FDD28D5F917539
+:10AA30002B2B8C5F1661F221A904E33395E2D75DDD
+:10AA40001E3FEE8FAFE9376368AFA13FBE5D59D3BC
+:10AA50006F4993F89984E9F5E98EBFA3E2F1DFDF4E
+:10AA60006F4A93E37F5179BF637C89CA0F085BA566
+:10AA7000E33E56E9B8D64D0EBABF96BAC931EEF9E3
+:10AA8000F2FDEB158FFF5107DDCFA73EEAA45B3542
+:10AA9000304FA4D271FFE13CD7FB6F38BE41457304
+:10AAA000EC03C5ECF7B3DCAEFD84A239E4B858FD85
+:10AAB00037B9BDF2BE0AEB9FE6FDCFB5F12953FFD2
+:10AAC0001E8EFF3D15D6FF1DC7676585F87C9FAFBD
+:10AAD000C362FB6780F33D083A32CFAFB9D03CA6E2
+:10AAE0004DBE84E08773CD67BBF1FBC1372545833D
+:10AAF000F377D249D01EF79F0C1DC0DC4C3BCE4CE7
+:10AB00001296C0F430C6B7BC11239AEF5FD87E9777
+:10AB100024C5CD42E76BD57EA6FF04CDE862EB5D90
+:10AB200026F03D47B1FA417FE1F84B1519CF421E9F
+:10AB30002F89F2F3A2B31FD40BC6FFA57802BFAFD3
+:10AB4000D6647200E2CED5EB1CE7F9311B9FA889D1
+:10AB5000F8C81AC347960CB350FE72839FCDABDD85
+:10AB60008FED1F0AD171C2EE7160F80DF8E35D78C8
+:10AB7000DE5F2D239FFA43CEF3F09B793F7FC5E93B
+:10AB8000EBF796CE1BEB98D9AA40FF7DAD2C6EAEAD
+:10AB90001303CF05FBD5D2F71A6CEB66E78123FCD4
+:10ABA000BBD2147C573A1FF2A4A23C3FEA19FC3EE8
+:10ABB000EF4C8BA7E4FD3821C3193F0F363BCFDDA7
+:10ABC000EC78BB5F777EEFE38B3ABFF7F1CE943C36
+:10ABD000F87D91CAF2B1CAE16FE773D9F586A4A4F2
+:10ABE000A215E453C611EFF7459DF8BE7BFC63ED5B
+:10ABF00083DE51AD105EEF14DF8AC51B26E8AD92EF
+:10AC00009319A6371CE7D4DD5CBE7C554A12F4329A
+:10AC1000D5BB45DE07587B358E790A4A34AE633C96
+:10AC20009AEF030AAC873C3E3D68AFCB80C7CE436A
+:10AC3000C6FB5E04DDC4734605D69130B5DDC4BCE9
+:10AC4000DA72FFF66ACC4FB46A155C27823E8EDF5B
+:10AC50007BB9C799EF3777F96939C36FEE86D2FBB5
+:10AC600027315168BDECF4333DAADC10D79526742A
+:10AC700055D1EE71E3F10DBEFE541B7FCBC473EED4
+:10AC80004AF17FAC42FCED7128FE5F013D4BF1FFC4
+:10AC90002A94C5F07F8AEBA31AA2F7E09EAD333D5C
+:10ACA0004BC88D7A7E7C3D1060FDD6703D4548BB1B
+:10ACB00023BFC4CBE9AA949E43B65E2B438F3D2E9F
+:10ACC000A5E7289F8FEF959A8F17383D8100DBB756
+:10ACD000947D719D2E4D7249917939C5F19819E095
+:10ACE0007125AB7D5A72F5A30AE93835392FAFF2D9
+:10ACF00079F965293A4E72B94A8B64E569D84FE70C
+:10AD0000DA790A6B1DF33287F327EDB3E7A5C33178
+:10AD10002FD5D39C97DF5648CF9CC979798BCF4BE1
+:10AD2000AE949CE5D57F9BD7FF13AF8F76E29CC096
+:10AD30001FFBE1BC6CBE3FEE09D44EEE6FB49E1813
+:10AD4000583659EFC1E163763D1FD6EB9CA8A704A6
+:10AD5000F2FA23D66BFD70AE3DC0BF0BF9FE70E872
+:10AD60003DBC5D18DBDDC0E8A1EDAAF2FBFFC6F03B
+:10AD70002B76FF33A05ECFEA3FD9F522F9F5E60442
+:10AD8000FE64D78BC27361DF447F75F9789CF2FF54
+:10AD9000733FCBCF71E5776995E531782309BCE73F
+:10ADA000A18684D290073B28B17B172C6A541F845C
+:10ADB0003C595F224B2AB0BB3C0A6BE7A3F6167CDA
+:10ADC0005F36432387FD3AB82006D907F9AD11094C
+:10ADD000FD813BFD89A5815A8627C8CBC0ABCC1E1F
+:10ADE000EB5197F2380AC36B67F06329E84FA378F9
+:10ADF00041FF0F06C387A1FEAE065907F93ADC7082
+:10AE000017DA893B7B2402EF775E2FA39DB8FBD531
+:10AE100010EEC3039281F9D59629EB6037DE1DF859
+:10AE2000D3894D141EEBA9D284AB911EC4DFF290DE
+:10AE3000781FF6CFECCE2D147FC80BC6AD0BFAED04
+:10AE4000647E0CFDD541FBBB57EB984FA313767F77
+:10AE5000D350AB8CF9483BEB9BDA61BCDDAD0ADA31
+:10AE60001DBB6F68EAC13CEDD600813C801A5517C6
+:10AE700020EF31BC422616C011BD07ECCED0F20047
+:10AE8000E446929A7A365E683EC17BFEBC241D8FF2
+:10AE9000D1329C9231BF77F70D6B593E69AB4FC3EE
+:10AEA000EFBC2CF3E5D872C25295E127FE23017C5A
+:10AEB000BC734402FCB7E7399C9E685FF21C319C6E
+:10AEC000A9B05EB6B27AA19484F74E95AD97AEB0B4
+:10AED0005EA6C27A5956AFECF93DCF9F54E83F8841
+:10AEE000C3F95DE7B760C797FA5E6EBAF9B93B037D
+:10AEF000CEEFE9CAB5B7F372CBD10B879913788A35
+:10AF0000E5EB97FD1E73E65D51F83E6DA8F65E5EBB
+:10AF1000DEC7CA3AFEBC6E4B14EF8BACE3EFEBEE30
+:10AF2000C3FB23DDFDFC0FAE8F9B49BCE43CD4701A
+:10AF3000FC5FA7B8433CBB592A930F10F1B8EC4D06
+:10AF4000A7DE5324AB03D7ED0D2C2FC707CA00D6BD
+:10AF50004D3D5BC75E928CC7309E658617CD9C5C6D
+:10AF60003FDEB61771FDFCA04E24422BCE0FFB8EA8
+:10AF7000D225276EB9F0B9CEF52F544E7EFA2EC9E0
+:10AF800089372556B47EBCE90AEB652AAC97ADAC8F
+:10AF90009E9C122AD22B72BAC27A990AEB6559BDCD
+:10AFA000819532DFD7870720BEE5BD5271C00357B8
+:10AFB000069CEFAF521DF0E032677B79B9B3FDE03C
+:10AFC00072677B79056B6F04F7BCC78A55BE4EFE6E
+:10AFD000CF79AE9366A574FD506B9975A5687E68B0
+:10AFE0005F23E904EE1DA2FB5586EF5B05E33F6B93
+:10AFF000826CFD5F1FD01CF7D3FDA5D3D91C64F86C
+:10B00000DAF496C3D7D6BFFF57E47657913CFB6A74
+:10B01000D03990774DB275D0EFE13BBE550776E55C
+:10B0200023AFADC07B3DFADE67E7CD1898F7239DCF
+:10B03000F8FECDA0C71E49CA04F2711EAD368E5D62
+:10B0400012C1EFC908D8CBD48DC2FB3E1ED92CA1AA
+:10B05000FDD1775BE97B4DBED1CDF284FE8EFBFD49
+:10B060005FE5F7713DC5EFE37AA25BC7F260773326
+:10B07000965FEA36B07CBCBB15CBFDDD26EE1B5FD0
+:10B08000ECEEC4725F771CCBBDDD5D58EEE84E6020
+:10B09000B9BD7B33FF5E2D89E570F7162C87BA2D7D
+:10B0A0002C07BA5358F675A7B19CFD3707862F5960
+:10B0B0008AF99290A156147FE37967DC61E1B301CC
+:10B0C00007DCF23567BCE1B22FCF76CAC5A34D8E3F
+:10B0D000FA97ECB9CCF13EB66DB1E37D53FF950E16
+:10B0E00058BFAFC3015FF4D9BF72B4AF4BAC75BCEE
+:10B0F0009FD5F56167FE57DB06C7FBF0D24F3B607B
+:10B10000B5E54E47FD40EC5E070CF73EE7D7BF3193
+:10B11000D8C4E2819111473D49DDE5A8F7A999E638
+:10B12000FE20C443D361B42F1F3929E03E38E32207
+:10B13000E3359027F25311E5895CCBF2DE673425C5
+:10B14000AF80FBCB88945CF1C150F97BA4ED788F84
+:10B15000186E4DC03EFBD66B820EF6AE10DE323F4F
+:10B16000DF9FB3CBCD67926414E2923CCF4C9B4DF2
+:10B170004C13FC46AA4F08DAD9C9ECFD18B7F4E025
+:10B180007753692181F74E539BD9F8EF1AE4CBBB73
+:10B19000F7DF20DAE5673482EBA0BD4369ECA7ED69
+:10B1A000B72F90F17BBE29F8BABE8B7923C8FCD7A4
+:10B1B000ADF7B378A576C4DFA82C85FB321233C077
+:10B1C00055B5DBA9D997F0DE5335662C87AB01D492
+:10B1D000E60CD9A842BD2CDEBF40EB7F1396FD44A0
+:10B1E000FD4D594BA6CFEB3627E6C2773DDB79FF05
+:10B1F000DB0FFF8C5C42F91A5A7A9CDC8AFECE5E29
+:10B20000E45FA8758CACC95BBFDBDF2EFCBDD12F22
+:10B21000832CAF667B8F85F7CC29D96FE37DA8F6A9
+:10B220003C045B8E9304F4DF368EF7036FBF9F7D83
+:10B230008FB75DF85134CAE9EA71D285F8001DB7BD
+:10B24000523DA7DE9214D6B4B0E773F3FA85F71B2C
+:10B25000E17DC212205FBD127EC9F07C13E5179D0F
+:10B260000775734628C9AF58967D1FD15C845F94DB
+:10B270003FB7A29F3BE8881BDA7CDADE739C2C6F19
+:10B2800001FB9FD59FE02BE5C3AD797C9CE0C7B265
+:10B290009F627E6BC8FA1159A2B276406F88D2B70E
+:10B2A000B100DF29FFB07F9B1FF63821CA2F869798
+:10B2B000657FDF88F775DAF91F767DF8752EE7F977
+:10B2C00087941FDEB1EA8DF03D687B4B02BF131EF1
+:10B2D000503D789FD080FA4CD6C3E519EA4992D9FF
+:10B2E000FB639E67DE2B145A7F4EFB1F32A6F3BF13
+:10B2F0000BEB57D9BD990391327610BF2F58E4F765
+:10B3000005CB52BCB391AD53A3874CC64DA78EBF9E
+:10B310000BE916A3CE7DB57F93733F8B691FC6F8EB
+:10B32000745FA403E16279F976E9CB31BB51E6F8A9
+:10B33000787341768F71CE8F789AB919585E93AB36
+:10B34000C6F2EADC1C7CBF2A5787705B6E2EC257A0
+:10B35000E51AB1BC3277393E5F99BB14E1D6DC12F5
+:10B360002C57E416E1F3E5B9AB105E965B89F0D299
+:10B37000DC6A2C97E4DAB15C9C7B2FBE5F94BB1E29
+:10B380006123F7412C2FCDDD886573EE23F87E7E97
+:10B39000EE66842FC96D44785E6E3DC2B1DC6710E5
+:10B3A0009E9BFB14964DB9FF8A6563EE0E7CAFE75A
+:10B3B0003E8FF0C5B97B10BE28D7877043AE07E13A
+:10B3C000FADC5684E7E486B19C9DDB8D655D6E27D3
+:10B3D000BE9F957B08CB99B92FE1F3EADCE3586A6D
+:10B3E000B9AFF27BA09FC2329CFB2696A1DCD3F8BA
+:10B3F0005ECD7D07E160EEDB5806722F60A9E40E9A
+:10B4000063596E9EDCDF2F8911E7BE7C0D99E190B8
+:10B410008B5539E7BE7CD57893035EF96BE7BEBCEC
+:10B42000626CB1035E76C2B92F2F39DEE178BFE8D6
+:10B4300098735FBE34EBDC97E7673EEC80E7EDDBAB
+:10B44000E0A83F37FD6907DC98BAD351FF62CBB95A
+:10B450002F376C71EECB7392230EB86EF32E47FD2F
+:10B4600059E461877F58DD75C051BFCAFC8AA37E4D
+:10B47000A8F519D7B94986E979E339C773A5F94819
+:10B48000C1F395D89EEB3D6F803ED13DFC7B7A7E2B
+:10B490004F2BBF0FCD3D9F355C0FCCC831BF28C2AD
+:10B4A000D75D2DACBBBC7C266A3F3436417E08B7E5
+:10B4B0001F6634E94F1FA5F05B4DB2D14361DB7EBF
+:10B4C000B0EB97FD7B14FC3B7D1F7CA7AFA3FD80F9
+:10B4D000F7B7DF7D4AC07B1E6AE6107EFEDFD90922
+:10B4E000FB5A0A6C69767F0EDEE7936AE0EFC9FAD1
+:10B4F000EBF07D23835FD876EF1A88A3A6BC76FB9A
+:10B50000AF5E07718B949FC12F6F5B3F08EF6BAAF3
+:10B510001275B09FEE2D726EF973957DBFAEAAE6DF
+:10B520004B6AEDE4FDD1BF8824FE37C0B729898B73
+:10B53000E12A6EB8BF1EEE67BE56327F00CF3F20B5
+:10B54000993F54715F70FA05EB20A7B516FFAEC4A2
+:10B550002B2ADA4F87703FAA79EF36FCFE3315A20B
+:10B56000F8A8C5F139A68A13FB0DB1F79B268C9379
+:10B57000A29D37D840F0BEF85475DC82FBFBACEFDF
+:10B5800029E4A00174A7591212CF3B4C5DAADB72CB
+:10B59000E1D89FE09EBF0DF47D30A1EA6087A9E469
+:10B5A00038E65584C938961AD104C73DDA36FD0D00
+:10B5B0008C7ECA9771A04B26E6A1317EDECEEFA528
+:10B5C000FE17CE9737D565C5F9F21EF13EA2D1F12F
+:10B5D000F7533B11F6C5FD5081D2F17494FA9D02E8
+:10B5E000E09988B760BFEC7E08FB7E38E9E4B7F1EC
+:10B5F000DE063B8E23896D9DB83DB730BBAF93FE11
+:10B6000003BBAF36EEB423DDDF9948AEB8CE74E3AA
+:10B61000385521771C47C573E2335D1EBC57B158BE
+:10B620003F763CE7E9AED2FEDCD7F97AFA1ABF17CB
+:10B63000E42BFC1CF7497E8EFBB7E0CFD1F2CBE0C8
+:10B64000CFD1F200F873B4CC803F47CBC7C09FCBBB
+:10B65000FB6EE4B122F7BC5C526DE72B6C41BB3D45
+:10B66000C8EFD9206414ED7409EC742A574F1FED0C
+:10B670009D19A37CA7BE06D2B7F9FA0EFC8E9F0EC9
+:10B6800061C077FEB7BFF1FACCFF1281AF6FD9F777
+:10B69000C3B43EE6494A2DEEEF48CA8C2399A81759
+:10B6A00082D41F481BC5F933ED7E1513AF6C9B7E0A
+:10B6B000BFEC3E9FC975D389F924414EB78F7C07F3
+:10B6C000C739C3FD1922D6FF2FCC8FBA4222A5BE9F
+:10B6D0000F9C32CE34E5EFE365E40FEECA44BB3392
+:10B6E000C9E663E173C7EA0ADD0B61CB61CF6B3E4C
+:10B6F0008CAB0E7D8FFD1D8AA30DF21C885F8C1E06
+:10B700007EB111BF5FE4F2D877D4997F509F244275
+:10B710007EBF0F75B338445F84F5ABAB2C6FC14D62
+:10B720008FFD5D53AA4C3EC3837CDCAF07CDFB424B
+:10B73000A80FB378EFE3C2E7948F00BE8FDEA114A9
+:10B74000E4F3D78389FE50ED543CF3DBE33D14C5AD
+:10B75000DB6F0B2D2BDEBEE519E517A474FB3DA5B1
+:10B76000DA5FF615E59132F83F5A187F6B3FB4ABBC
+:10B770008FB2BF4BD653F7FA81AD14DE7B07F38748
+:10B780008FDEBC0EFFAEC3402D9BB702FD3E510ABB
+:10B79000AF85CF757595C1EB1BA5F9DAD55586AF89
+:10B7A0007F5FAA7DCB335D27CAF0F5BBA5F9DAB57B
+:10B7B000AF0CFEFFB3707BEB62D03BF53A8BC7F565
+:10B7C0003452BE523C866CBEBAD643817E5F2E2771
+:10B7D0006F65F0FA79E979292BAFA74AF3B5ACBCCC
+:10B7E000FEE602E5F5CD227CDD0F785F80BCBE7DF4
+:10B7F00081F2EA0D5F98BC86C225F5405979AD2DDE
+:10B80000D5BE02796D2884BF8F044DB0A7CFB4B0E8
+:10B8100073AFCDED1EF6F79134A6EF8327AFC37D4E
+:10B82000B49FEE53335A61BF3EB5F7F6A593FBB311
+:10B830007BFF71F7E7DE3F6FFF973544A5F022BE2F
+:10B84000EFD9F80462EE7E4ADF2F31DD7125FE77F5
+:10B8500096ECF6B337BDD3E339F777E9281B9FD0D1
+:10B86000F157E33921BB3FB7AAD51D979CEEB8A588
+:10B87000EB476FB9307B607DD8793FD49C2DDFDCFE
+:10B880007F3AEFDEB039FC3B2F2FF910DECF446E4C
+:10B8900063F940E296A7F79F5E92774F141915F26D
+:10B8A000F37FC4DB46F79FCEA33B07711F8C1F5B62
+:10B8B000989718D3AEC4FDBDDC3EFE28DFEF1FE62F
+:10B8C000F6EC3E7E3EB1979F4FA4B93DFB003F9FF3
+:10B8D000D8C6EDD9117E3E91E2E71303FC7CE279F4
+:10B8E0007EBEF05CF73E7C7FA83B83E5B7BA9FC481
+:10B8F000F2D9EE517CFF4CF7218447BBB3CC2EBE6E
+:10B90000E756CC839DA4C3E474DC8BF7BCF4D797D3
+:10B91000B6CB1B92CE78C89CCD01D73981F39C62FF
+:10B920005697332FB2DA74C643AA5A2F73DD47EF06
+:10B930003CA708365FE9BA8FDE190F9123CE78C88D
+:10B9400015879CF19005A3CE738ACB9F749E535CA0
+:10B950009A71C643E6EF739E53CC4BDFEBA83F379B
+:10B96000D5EB8C9F58CE78C8AA71E7F9C455BF7E35
+:10B97000D819FF1973C643569C70C643961D7FC6DF
+:10B98000012F39E68C837C2098C8823E5C9475C771
+:10B990004332A84F7FA2B2F33DDBCFA6F55F0CA3E5
+:10B9A000BFA966AFA2EBBE6F33BBD7BD8F687E0D5C
+:10B9B000F5F067D16FF04EDCCF1CCFDE1F99D43F7E
+:10B9C0003BAF3DF553F06BBC21764FE5EDC27559A9
+:10B9D00092EFF778DF12F2CF23A588534F94ED5FF3
+:10B9E00062F7107AC12FD18ACBDDD47EDD7EC9B556
+:10B9F00059C893F2025E06EA1B1C27CF2F1946BFD7
+:10BA00006496444AF9A753C699A61E7AD3A58726F9
+:10BA1000FC9228BB2F4597482FE0B1F7A8A7E0BDBF
+:10BA2000BFB61EDA192DBD0EED3C979D5D95E56301
+:10BA3000EF3C5ABA9E1DBFD2F97DEC5EADF0B9F76E
+:10BA40008B619657F9C12AC2FDE6FF2F3FEFA4FC98
+:10BA50005C59F59F467E78FC72E3107CCF24BB6076
+:10BA600091C3E1AA4FAF81EF9BB610760E445E61A1
+:10BA7000F7AE961B27D6F6D1CAEEF5D398BCC65AB8
+:10BA80005761FE24DE33562A2EE1BA57CDAB5AF069
+:10BA900047F726FEFEA3BBFECF6B58FC28D6F5B1B8
+:10BAA00092F6CD41BEFF7F89EFFF31B3F4BDBB8F6E
+:10BAB00071FC5F787516DAB57B6F637A5BEAFA879B
+:10BAC000C3609F8D72F9F791CFF85B80AEDB2402E3
+:10BAD000E7C373419669FD8B55928173D02DC440A5
+:10BAE000B9A63F3C5FB6FB176F73DA5B7FB0F91402
+:10BAF0002FCD57FB9E4CF7731FF94E3BF25727C9CA
+:10BB000087ABE15AF52FC4FD149E534B10AFD41EE2
+:10BB100003ED2E99E2A11558A76E7CECF5697F4FD5
+:10BB20002A6DBADA82F673043BEE1434204FE78CA8
+:10BB3000AA96BCFF6D4ABFD35C8F5F9BB21E6FE8B5
+:10BB4000FD4964F2FE2BB285FE964FDEEF596C3D47
+:10BB5000DAF00BAF0EE1772D29D5BE1FD0BE4F8B8B
+:10BB6000948C9B6EE57C1FE6F92D5B5B3A7A5F87D0
+:10BB70007353BA5EF2DB05173C8B71C77EED19BCBF
+:10BB8000C7689BC1BED756171D55C01EE8D78EE0AB
+:10BB90007D71C1FA7427DC3718A472043AD03F6F64
+:10BBA0000F7FBF0BDFABF599149C7FA8F09ED235B9
+:10BBB000D2FCCA61F89C3B50FDE6E10EA85F3F7ADB
+:10BBC0000CDEFB3582ED2575F47807C8D966827FD7
+:10BBD0006FCBE2F72A356435CC5BB858653049D075
+:10BBE000F73ABED756537876177B6FA819F4D74823
+:10BBF0003331597B8A1F85A347359CDF996A3A8E7A
+:10BC0000FD4758FB99C6B326E0311C637FCF47ED53
+:10BC1000228F031F16A90C6FF8CE8C8DC3E988B153
+:10BC200071BC6A26DD017AA6DEC693C210378DB0DC
+:10BC30007164957D0F49C7C7FBA67C2ADB0727F4F3
+:10BC40004E5718C73B13218F97FA7B01F67A7F9CDA
+:10BC5000DBF9FBB99D2F2973BE783AEF3E867EFE55
+:10BC6000F7421B55E777987FAC62EBF1C51A9667F0
+:10BC700056EE1E49F259763EFDFF00D7C62C0E0047
+:10BC8000800000001F8B080000000000000BC53D75
+:10BC90000B7854D59967EEDC796526E126992493D3
+:10BCA000D7E426241021E0000141B19D445454D42E
+:10BCB00088B6069F43409E01026A89169B9B172403
+:10BCC00021C0A02E445E99605154D0C18252ABEE87
+:10BCD0008029C5D6B6A9F54195DA08181501532A69
+:10BCE000CAEEEABAFFFF9F7B93B9934982B5BB9B2B
+:10BCF000EFD3C3B9E7FDBFCF7FFE738631C6BECD9C
+:10BD000081FFCD8B61212BA33FCAFB1258283F2C0A
+:10BD10005F9AA6CF7B72F4F98211FA7CEE587D7F90
+:10BD2000CE4B75E55F5DCF58870332A2D7CA0A2094
+:10BD300039F2A0B52496B1BA8C1A2B83EFE7EFD174
+:10BD4000CA991DF3B9528CC09C8CB5960A81260302
+:10BD500063C115350D79858CADCC10189321754DC7
+:10BD60001FE2837ADFE2DF0FFBA6DBAB180B0D6768
+:10BD7000ACA9CA4F6963550B0B59185B953170BB61
+:10BD800000B6837ADBAAAC946EA992A8FDA62A1706
+:10BD9000E55BAA644A3754E553EAAFF2505A573587
+:10BDA00091EAADADF252DA5C3595D2BD552554FE1F
+:10BDB0007C5529E583553E4A9FAD9A47DF77555517
+:10BDC00050FEE9AA4ACAAF1E23DD5E02F0D959A58A
+:10BDD00050FE89AA064AAB2558F77828BFD2E3C29D
+:10BDE000F2DA2B596930CA3AAA2503D55B23012C14
+:10BDF0009318B3318F6006B831C8EF00B80D553CC9
+:10BE00003516C827DFC1088E432B3C356680B33416
+:10BE100085E7D7E138D0AE92312FC376B92CB02365
+:10BE20009BB19C06F69601F2AE7CA9CD98DD3BDE77
+:10BE3000F5EA7850EE12A89C05B0FCB8D97B839443
+:10BE400084FD312A1F16EA1400DDECE2B742350EFC
+:10BE50001867D41B811A23E4474E56044C630BFD2C
+:10BE600082AF00F12A14E338E75608D48F5CC80487
+:10BE700001E61774713A585D04F0095BB7EDFC36C2
+:10BE8000161AC758C38AE943D800784D29157AE9AC
+:10BE900011FE8BF786D13FFCD710120E1A619C73EE
+:10BEA000406F2CBBFF7E2EDEAFEF675430A29FD2D7
+:10BEB00081E73172A7BEFD458188F640D7C81FFDD6
+:10BEC000B51F76FE065A6F7F747CCA5C56258DEFCF
+:10BED000CD8BE77FC042898CBDED90080F09D73527
+:10BEE000BB10CEF03705D72B6630822BA03B540613
+:10BEF0007913FCAB09AA8A0592978DC65456538FC5
+:10BF000097C561EA55F325947FDDE45B83781625B8
+:10BF10001FC3F920D9205FAFBE08FE9986F9AC0691
+:10BF2000EF64C8FF08FE792963374A23A62A90FFE9
+:10BF3000CAE4132A61BC3DD942603BC07B79CE582C
+:10BF40009203B58E81F9B34EE5CF9EF549255E0388
+:10BF5000F4935E2E8D453AEAAFDDA3E5CFBF3E0CEC
+:10BF6000EA294EC19327F72DDFA5D2F1A325C214EC
+:10BF700007C22193D3B1B69EC8FAB0EE5DB86E93F6
+:10BF800093AF3BE996124A73775D632D1905EB8BEE
+:10BF90001F980EB644AC2303060A46C1FB499C1702
+:10BFA0008C93FBC67C1BF53B63E07E1B55B9773E4B
+:10BFB00020B00EC4B35841F236E9161FCB85753553
+:10BFC000A40A0107ACABE19B7B1BB2111E070492D4
+:10BFD0000B49B754305F41DF71C5DCEE6A01E9F20D
+:10BFE000C07C26C3F8165705530A30AFC96B9F01B2
+:10BFF000E7932C495750CA025EEC3F79854FC171D7
+:10C00000CD2E3FC1A521B5A7BE0DBF6F080924DF06
+:10C0100057CAC06F064A9903F9BE82513E23F561A3
+:10C020001A977D0DF39900FDE0BF01C1960CBF1773
+:10C03000E541C345CC8372C496CF8ACCD928A60EDD
+:10C040001B50AED91E609E269C6FEA130ACA23E5D8
+:10C050007246F80605C7107E30BEF526C0677ACB5B
+:10C0600068E20B5B6EC880EBBEDDECEB427C6AEBFA
+:10C0700037BB3A091E0DDF184BA3E1E537AA9CCC6C
+:10C0800044BC45C1476C3C97D75F9982D7A01CDD63
+:10C090009324B0ED86BEF52C6ABDCDCEE97F94E544
+:10C0A0005EFED4CADFC64586F173FA7933CD3BF71D
+:10C0B000963B87E07AFAA383552A7DAD1BC2F540F3
+:10C0C000EEE43BBD08EF73F05F5394792C182253D4
+:10C0D000BD9EF53B059D5CBAF0F989249F724F35F2
+:10C0E000927EFF2A7B607A6D50E7F955A6DE3E10FE
+:10C0F000725B08CFAB5C804F19ED0481C5011C5BFE
+:10C1000055FA804F84DF20E8A726C07FEB8AB3B6BC
+:10C1100002C867BC6D4432017A98A7A01EB15DC405
+:10C12000E941923BBD0CEC9098FC6EA2C78C8A4E04
+:10C1300003A680F7BCF8F1480F1374F47046D59F3E
+:10C14000F057E79AA08A3299F8BE201EBE7B77C1CD
+:10C15000249CC80F7C7C13F32A669217952C08E365
+:10C16000DADF32D2779861E8A142945382A7C903FB
+:10C1700074D05E938C7C684FE2F265DE35C524BFD7
+:10C1800000049E4D30E6E24FBB929740DEE3E27240
+:10C1900019EA5B719E628159A737061D47F48670C4
+:10C1A000FD7603F3F83DFDC3FF3BF76BF532948F4B
+:10C1B000DFBD5F10A4C968DE7138323655C175DB4A
+:10C1C000D5755BD8AF689C73380EC2DE98F13B849E
+:10C1D000AF78B1C88C51E8B5DF718C770CA83F2AD5
+:10C1E0008FCEFF637B58FDD9F1B1CE2E9804BB846E
+:10C1F0005DF22D128ED12120BFA21D40F607F20064
+:10C20000CCA3BE82E363F44B8753C3E9FFABAA79A7
+:10C210007F6C07A5B947D5FBD51F5A8AB1FDAA5F28
+:10C220000B010BB46FCF34A777C2F7E08143D93845
+:10C230002F4D3ED7B6EBF57C46053384F7FB98CA05
+:10C2400017B54EDEAFECF058A3F1FB5AB55E836331
+:10C2500060BB61A33AEEB3766F753CD175C880FCC4
+:10C2600039FA25EBED38DF2D4BAD51E1FCACDDD7D4
+:10C27000189FD4779EE1ED118F03B45F3F50FB828E
+:10C28000E7ADEFB381DB3F163FBEFFF6239EB66EF0
+:10C290001E64FE6DD1C7575AB15D86CBCC90CEAB34
+:10C2A00053BBB6AF86FC86A5668F05E8B37DC68F07
+:10C2B0005D88B7FA248EB728FDEE1A685EA35F2A60
+:10C2C0002D1D645E7B076B3F085C5F1E18AEA547A3
+:10C2D00006816BFB40ED473C5DDA32C8FCDF883EEF
+:10C2E0007F250BE54E866C263D539D0D704539AE7E
+:10C2F000C135821FA2F4FBEEC07019945EFFF63DBB
+:10C30000E9F5E381C6BF007AFD7C60B80E4AAF5FF5
+:10C31000F547AF38EFEF41AF42C2807019945E63CA
+:10C3200012BE1FBD260CD4FE02E8356DA0F95F00D9
+:10C33000BDE6441BDFC2EC5E05EDA202AEC7E71509
+:10C34000095CAF4B5CDEDB8F5E4D7AB40EF454E2D9
+:10C3500044D4D7C7362C2EECD5CF91FA27B2BF489C
+:10C36000FDB9F8EF57919D3B46D57BDA7C6272238D
+:10C37000FBB97D40FBEEBB8E2BBA58C816D7DB3E0F
+:10C380006DF6BF7A3CBD7E17DBF9F80CC6BF6222A2
+:10C39000EAD5691E84F79089669D5DF9DDC71DB8F1
+:10C3A000BEEB8EEF670FCC49007B6064AF3D905EC3
+:10C3B000F98BD61389BDFDA48B254C72A0BD778B5C
+:10C3C00017E9829533CF0E2CAEDCD37A625CAF3D99
+:10C3D00000F037DC14B66F3496075B4F84ADFBFC7E
+:10C3E0006CA6EECF14B27773A54B49BF0FA6C7B5A5
+:10C3F0007DE326F44F0D477F94A4FAA35CAA3F4A3D
+:10C4000056FD50DC3FD58CFE29F2834DE47682EA5E
+:10C410009FAA57FD532FABFEB19754FFD8FEAA0039
+:10C42000A52F54EDA4746F5590CA9FAFDA4FF960F1
+:10C430005588F2DB1E9823233E7BD7E155D7A1F91F
+:10C44000F506B6FB332BF47E90F4797A3F482AFA4E
+:10C4500023C3F229E1FE4886FE9B1C5DF9908923E7
+:10C4600074E5B19EB1BABC3DFF525D7D9B5CACCB27
+:10C470009B9DD7EAF217EF9F1EE1E7B94D573E7239
+:10C480006759841F6781AE7C78CB325D3ECFFFA0B9
+:10C49000AEFED0861A5D79B6D2A42BBFBCFB615D1F
+:10C4A000FEB24F36E9EA4FEADCAE2BBFE4C8D3BA9E
+:10C4B000F2F11DCFEBF2E30EBFA4AB7FA3DDF76B70
+:10C4C000948763420723ECF400C9D310C80ADCFF49
+:10C4D000B857485778A3E0F1BF86F07D2BD8ED45DB
+:10C4E000642F833C6B1A83ED95121BE4D37F0D34CC
+:10C4F00027E396DD676043216DD7CB1F63F977E3B0
+:10C500006BF400607D37FC215FFE97B6AFDD6953A9
+:10C510007E80E3FBB83C56A4008BD64FAD6AFFE6A5
+:10C52000EE9C3184E8532A96A2C985E366DF27E1B1
+:10C530007A4674E8E934D71BCBBC385EB9E637E3FA
+:10C5400072CFC8ABB0F4A3571F36A09FACF4D57818
+:10C550009CC73675DC06955F57229F0EC7F55E16A1
+:10C56000B2A870DB04F29919277B06925391F0FA76
+:10C57000AE72CD90A8976B208F431FA1FC2E17039E
+:10C5800003EDAF347996FBD6DD03E24783AF8647F0
+:10C59000A3245D81F2C196ABB032475F3819654E76
+:10C5A0000FFFDBEB9623D67D8EBD5CE4C5F309E679
+:10C5B000894A273DEB2DBD8BD6A1E133B2DE0E5566
+:10C5C0000E3FAEE2B54D95C342B347403BAC5595E7
+:10C5D000C7C2A3DE1A84731EECA7713F686EAE0853
+:10C5E0005901EFA60C467AD2E804388CEEED77D8E4
+:10C5F000A37ABF4B6EB35E2EE6D425E8E021AF48A8
+:10C60000FB4EFAB42FDF5D46F68D468783F11F920D
+:10C61000FCB743FF99712E8CBFDB672753FF0FAA2E
+:10C62000FC0D1CCD5385BD89F4533651252026DFE2
+:10C63000FA3EC075FE611343FFCE0FBF6E3DB415C9
+:10C64000D6619C6891D0DE014D78E815289FEDB544
+:10C6500096607EFED151663794BF930644E0C2F2E5
+:10C6600092389403A7993015FD77A7D99B71E3C23F
+:10C67000F4EEB244331FB7C174ACD38AC32B748EAB
+:10C68000758F9FE7B575CD6DD1E7E7B0E9C9228C0D
+:10C6900033E751134852189789C73A353800FECB13
+:10C6A0001225EA772EAB58897644BD89917F71D1E6
+:10C6B0008BA3CC683FCF1F27651BC7F4CEE3C144D3
+:10C6C000EE673C09F42687F98B173802662FB43BD6
+:10C6D000BE77DC8F2F63D84F60651AFA3BE3C11E2B
+:10C6E00091FBC27756837E9E83AD2372DE8CD590FC
+:10C6F000BCEF6F1EE24E833710852F1B12B95F5DB2
+:10C70000C363ADF567AD9D304F6FADC86C3F80BC66
+:10C71000C8CF9994A3B1811D28BF8B2B9EEC44BF39
+:10C72000748D45AA8574A3FD67CF61FD4A4018CA80
+:10C73000CB3D8932F7ABDADC013C7F60ACE292E9B9
+:10C74000B1DFBFDF17B0DFA47F7DBFBFEA67BE8B5D
+:10C75000AC9D66E4FF2562C55483807E453EBEC520
+:10C76000E4F3A6A33F717F51289DE9EA355C60BDE3
+:10C77000C3869C0BAA375518A0BF33AA7CFBCDAE4D
+:10C78000C7CD28CF4E3FFDE10DB82F5AF82B23B36C
+:10C7900042BD33BB625988ECBE8019EDBE057B8D6E
+:10C7A000DE00E543136E8E0DE7EB5AEA7FE173B1CD
+:10C7B000B4AF5AF0BC25300DDA2F78E1F86806F2F4
+:10C7C000E04C4DF7A17484DFD306B2A399D239FAB5
+:10C7D00066F8BE4064779744B1833F48E476C7A9C2
+:10C7E0005FDA4B91DE0C3B0FDC45FD066F3559C21D
+:10C7F000F4D8DB8926AD1EF9BD95A70C813C039FBB
+:10C80000DF4DA3C2E757CDEB3DC5FDB90BF69B024B
+:10C81000369CDFCE36B30FEA2DD9F977A2EF2B9EE7
+:10C82000DB1D877058B2DFA8936B0B9FFB66E5A5F5
+:10C8300080E78546D63D8DF4F8D7943FE7B5761B63
+:10C84000490E79E30C20B71693C8827ABFF8F8AA8C
+:10C85000F7A1FCA4CBC86C200A4E767C64FE15E6DA
+:10C860007D8E0A5049D0BF9E0F97EC3C6EC6794929
+:10C8700002EBCE0046FFC117617CC9FAD667ACDB7C
+:10C880008C727649B0F1EF46A0B7257B4FBF877415
+:10C89000B724829F4FE23F52FBEA4BB333525FBE55
+:10C8A0003101FDE66C276C8226F5AF2F35FE5EB8B0
+:10C8B000FBDC3605C63FF5FC67DB144079F97FFFEA
+:10C8C00063DB4F61FEEC559B847269C9D36FC7B1BE
+:10C8D00030F8673BF939D399A79E7C6213C0E1CC4D
+:10C8E0005F2C04B533AF7CEC96D10FBFE73F92F1DC
+:10C8F000DCE9BE57AE4C413ABB6FDF152903ED2B87
+:10C90000906E039670FC0608BFF27E182705B22FC2
+:10C91000AB69045E4EEDF9CA8CE7095F1A5837CA55
+:10C92000DFC5C16FCC78FE70C8CBBA114EAFED3DFC
+:10C930007EE841C89F063C59A2E009D69F2E905E32
+:10C9400001F68174F1DE9B6FBCBC10539347463CEB
+:10C95000B16E92F77DF0FB16E0B7B017BF91E5E737
+:10C96000D8D76684FF925D80CFD18857C0E7E8BEF4
+:10C97000F83C8DFF98D4179F5EA7DEBF7D8E95B7DC
+:10C980006EC2C2BD8984FFFEF0B968DF8F06B4B302
+:10C9900034F930189CE719F8BC1C4E6F893309E94B
+:10C9A000C2AEB8389E03D3A0ECCCEE736E0674F220
+:10C9B00089A9FB2E8443F72B1609CFC916BCF22E8A
+:10C9C000F1DD997D7F3223FEE12FCE3001F2ACE71D
+:10C9D000EF4D06F9C5DC06678B58F755EF1562CAAF
+:10C9E000BA150FE18FF287800F091F819BA6CA2815
+:10C9F0007F0349B4EEC501CE1F8B03076E318CEE69
+:10CA00000BF726A7A0E9AD1EBC1A26223E3FBC0AA2
+:10CA1000E9AF3F7C6AEB9770FD9740F9CFF5FC1BBF
+:10CA2000597F31F02BEE8FFAE03770E00F989E6956
+:10CA3000B38806B085CE9878BC4724DE7BE1CFF57D
+:10CA4000F377B58FEB9C91FB02DE5E83D360FC3EF7
+:10CA5000D8FABE2BFC963965EA37128EA7BE8EAE89
+:10CA60000F02AAFC58CC2AA6A60DEDABCF4456A2C5
+:10CA7000A467F7CE7765D04872FED44EB0C70D7D5F
+:10CA8000E5C5E27ECEE19F75723B66F1FE03A351E0
+:10CA9000AE9D3AF84B952E39DD2FDEF5A15951F5B3
+:10CAA00043205C3EF7733EBC5F9DF79297A3F7B7B8
+:10CAB00064D7DFA3F67752F4DE8AF33FD961620AC6
+:10CAC000747132689C1ACDEEDAEE34E9ECE795B178
+:10CAD000138E0C8176C6B81819D75D5BE37D57417C
+:10CAE0003BE64D139DFF33D1F38905CA6B63636445
+:10CAF000F4E7D5C6CD6172981EAF8B8093E82AA16A
+:10CB0000F355D15952C8F77401DD39B00908227CB8
+:10CB1000DEA07733502F7D30E66313AEF36F1176CE
+:10CB2000E4DF44B63205FAFB9B62F054CBD1F60742
+:10CB3000FAFE7D2B8C4C0EEB7FB1A5FB03F2C7FDFB
+:10CB4000BB8DA15D667CD5664079B2649B89F65D3C
+:10CB50004B601B8570FB78AB2DA0407EE32FAAEEC7
+:10CB600042BDF4F9360B9EBDB2D7F62DEF7A00E543
+:10CB7000D26603437FFAE7BFACFA12F5F2FC2D460A
+:10CB8000DC2AB2B9F6EE27B0FDDCE7D2592DB4FFAE
+:10CB9000CC109C809BD9AEA4D004DC8774ED4EF5FC
+:10CBA00028D4CF8B8BB1DF33CFD9A9DF33FFFE2E53
+:10CBB0008D73E6DF6349AF69F3077B5B0ED7E360F4
+:10CBC0006FCB3D7C40F41A96877116629ED7377CF6
+:10CBD000ABCA3C947F0B3105BA5FB87F8817F791D9
+:10CBE00061F5A89F2596EE9F7868FFADA409B477FC
+:10CBF0000AA5213F2EDCA91FFFBF5579B7C4DC3D34
+:10CC000087D7F7A771BEEDA076F624955ED5F2C85A
+:10CC1000F65A7D5B528EAE9ED67EB1855544E38337
+:10CC200064B5DF853BBF19AEEF4F51BF478EC3BF21
+:10CC3000DF6F600AEA67B6C746F169E5E6D0B0047F
+:10CC4000E0DB17CC6C1EF26F795C68583C8CF72BDC
+:10CC5000556E96C7401EBEA7A9F3C0FA9867D6CEF8
+:10CC60003388D7452FDAE85C65D10BEF7E89F83C35
+:10CC70008530068C9D4AEAF8F2A74007A7B61A99B4
+:10CC800002F6DA224BC8BD19F5D41E0BDB8EFCFD73
+:10CC9000EAEBA4B74E3F6F11C2E3E222D34541A0B5
+:10CCA000066BDF7528C52CBF02E6A3ACF70A6DB88A
+:10CCB0006F386C0C54C3D895A2B7E6395CDF6113AA
+:10CCC000ED33CECE66F9B8AF3CCBD23C0AE15F7E05
+:10CCD0005784F2E5BF35199AA28C6B3A0F4A7F1C34
+:10CCE000F0C1F9EB983C0EE3C08652BADC5C311C13
+:10CCF000E5AE5182C51590FF81EC7693D3C3E64231
+:10CD0000BA3C81F9107ECC716D0F7FFD1150BAECE9
+:10CD1000313905DBFD2089DBD5F393BDD726917E24
+:10CD20007448A43F543A55F6F1797E6588F154630E
+:10CD30005CCEF907EF46F82EFBD02087C79DF4C6DE
+:10CD4000837A28EEAB5294DF950B69BD248F72A5D0
+:10CD50001886703D2B0974BE7076B63C243E4C2E6E
+:10CD6000AFAE92487E3456B9285D5595CF64F26BCC
+:10CD70007B286F54D76F29509811FA419EC63F8B7C
+:10CD8000A3C48B761ECE09E3828C0E1FD111C6354B
+:10CD9000A11CB33A18ED638D0E85CD453FBF83C30B
+:10CDA000C7E82821F898D5BCD8328DE009EDE9FB19
+:10CDB00094645F4512E0D39A31422797CCCEB1BA42
+:10CDC0007C1F7869F8DFFD7F053746706AACB25288
+:10CDD000BAAA6A22C1ABBECA4BF9FF07B86DE470AC
+:10CDE000BB94C75AF4C0AD5897EF176E8F01DF3868
+:10CDF000C3F906E0887CC3623C3BA2AC3F32DD5005
+:10CE0000C528F8E6E1AA164AB5EF09FDE8ED2F932B
+:10CE1000B81D50C97CD5261C47E2FE16E65458C6FC
+:10CE2000845EFF2673294CC63CF22AE2E5480CC119
+:10CE30006ED95F6DE437364A6257B85C5B76BD9C4D
+:10CE400082F2CB58F9383B9E18E6479B566293090D
+:10CE5000AE1E3AAFAC55F5667D0FFEF47CB0BA4A13
+:10CE6000A6748DCA0FEB547E588F78C6B8130F3F47
+:10CE7000DF6C9ECA482FFE1BE4F93E3EC4C2CF9D24
+:10CE8000E23DC19009F04D3252A63444F1C0472C26
+:10CE9000813C68672F605EA48FF8230F90FF1823F2
+:10CEA00074D19F16AFC28DBD9C133F23969667E247
+:10CEB0007A871979EA37A13D1E09D75ACF412BEE5F
+:10CEC000AFFB9B4FD107F30D38DE5733084DCC79BC
+:10CED00047F008C6AB3A9AEDA457933D1559E8DFE1
+:10CEE00063472D449F0E8FCF30370C7FC9FDD87517
+:10CEF00095C9D79C40FAFB086D25C0EBC32D436D47
+:10CF000008E7D5A6A00BE5DDEA78AE3FE45280C283
+:10CF100025BDEDFEA0CAC1B8423DBF6BF2559A3C9B
+:10CF20005647BF9A5C4D98A2A7734DAEEE4FE2F6FE
+:10CF3000DAFCE4922F51AE269EDF427C1849F7B905
+:10CF4000D2A5A53E27EA01E669427B0D6D46B4E312
+:10CF50003E340438BD73FFD4D9CEECED68E7C0AEE3
+:10CF600080E48A82FC4078EA7EED5B68B75B950FCF
+:10CF700035D6E9568A73043A6214B72E1380F1FC51
+:10CF800090A9F1ED9C3F2652AAD1676672B62E5E3B
+:10CF9000D0987B48407CD5831D4171C5B0BF73E0FC
+:10CFA000F9F8814956B4F74493E730CAA9EE5821FD
+:10CFB000887AB3DE31DD8AE74A86F842C2FB97B150
+:10CFC0006559039D7B82DD427E5BC9E161C7701CB0
+:10CFD000C6C86F6B94C632DC27EE7674C4E0BEC55B
+:10CFE000912CE8ECC4F9C9BE9CE4B0FC281C5DC5DA
+:10CFF0001776BB5BED2772BCD1C9AADF324361DE75
+:10D00000B0738B4A8DBE65854D09E3EF9ABCAB5872
+:10D0100067415FBEEE576EEDF87E72AB362B40F87F
+:10D020003245CA0B27C87107A58A0028352A59AB93
+:10D030006F1F4374558C70608EED3D76C80F73A2E0
+:10D04000D0D791112914B7D9A36760D75C407A660D
+:10D05000E3446E8FA87A86EBA7B3CD76D24F67678D
+:10D0600057503CD5D9E61419E9EEC0DACB46233C3B
+:10D07000E69C6F6432CC6FEEF94994CE6B7984D222
+:10D08000B296362072C6AAD7CC5D3B03DA1D7FCCA0
+:10D09000E841BEEE0A8C3B5309F9AE660B9E11B116
+:10D0A000AE2DF766A15FBC0BC641FBAA6B4B1ED130
+:10D0B0005717C08DF20DFAFA182F6C04BC9431A6E4
+:10D0C000C619CA5EAC3FE775635B343BA96C9DC56E
+:10D0D0001BED7CA7A7BC25BADD568BFF4CC5FF55C1
+:10D0E0000C4778157DF04016AE57E3FFE509208F19
+:10D0F000105E1F5858347FFC94E42B17223EA62460
+:10D100007BEFE5784988EA5FEBA57F3EEE7101ECA5
+:10D110005BC28B2FEE269D9F95FB318FABF62FB315
+:10D12000F6531EA7B697A2972F6AFEECD043905BEA
+:10D130005550518244AFEDA745C6F7D38BF7DFA416
+:10D14000C6F9F3F9809D4A74CC001F285F66ABFED8
+:10D150001E80FB8D78AFE4F8EB4603D2472F3DF9F4
+:10D16000E2D06E31ACBEBE663794FFE330DF9FCDB8
+:10D170003FBF9EE49D61F5A88D93E0FBBDAF9B484A
+:10D18000CE57375DB6EE0EC0EF176F18293FEFBCD4
+:10D190008DEA7DFA9067E31D50AFFBF726B2C3BF5F
+:10D1A000387C25C54D7C6AD2FB092E4BE17CBC5FE7
+:10D1B000E5E739E75793FDA195CF69986596894EC4
+:10D1C000D7D2F739786883C1BECAADBF2B12F13C04
+:10D1D00087D1BD85FDC9B75C57437A6D2CD9FB73E8
+:10D1E000D7583CD1E2A8F727CB3AF933B7B399FA2D
+:10D1F0006560173993D5FEC2E4C8DCF389C4074CD7
+:10D200005218C619CF51E549CFFCB69874F2E453D1
+:10D210005B743FC8E164BE8F9A73FE32E2AFBEEB2F
+:10D22000FB017D9FA38DDBC9F9B1773D1B27455BD2
+:10D230004FEF3A2653FD4FE3A38FFFB93A7E57D500
+:10D240003CE605B95466817A0E1CFFDE95130B711E
+:10D250001DF10986B075CD6D59C8BC61EB9ABB65EF
+:10D26000A6B92CACDF5E3C2CFD5D516E2F1E3EDF5F
+:10D27000507E5D0DCAA3E492F7916FCA565F3E1AC5
+:10D28000E9716E4B23C1F9B8C9E346F9FA71CBBD18
+:10D2900071BEA8F394757A6B6E8B8A1FB0770BC33F
+:10D2A000F0A3E125B27DD75FE77EF910CA9FC7B82A
+:10D2B00071D31FBCFAE02D3B3ADC6C291ADCF299E1
+:10D2C0008FE026BF7004E97A8DDD8374DD3FFC4674
+:10D2D00032DF40F0EBC77E057B474849C27119D168
+:10D2E000E9DC164E0783C1AD775C950E8AA2AFE7E5
+:10D2F0001295DFBAAA2A99020C7BCC3C181DFC942B
+:10D3000029D601D6D14307FFA6A3834B52D6101DC1
+:10D310007C82F6CAF0BEF83F6656E22EC5739F26A1
+:10D32000239D2B1D8B51926FE3F931288F8FC5F907
+:10D330006FC0731A2D3F7F475EDCCCB0713F6E002B
+:10D34000384481DF252911FCADD14FAEC20A26FC3D
+:10D35000EFD1CF71F59C38B2DE94E4A2CB52507F6E
+:10D36000F8A3FB6BB55493D7C6218E9E7D26EACFDA
+:10D37000638E9C2F0350DA94ECBB1AFBA98BFFC978
+:10D38000DD280F8E1D3390BEADFEEBF2E1A8D72253
+:10D39000ED04D87F36E0B9E77263AC9FEC50B1A2E0
+:10D3A00095CE411591ED28C47D4AC5A61379E8377D
+:10D3B000ACA494A976E872E3080FEA6123AB781273
+:10D3C000CF49814824AC2FB20A3A3705415882F937
+:10D3D0008D767EEE5A295A254B585CC252955FEAEB
+:10D3E000AB4A1E39817E68ABC2A4F0B843C6EDAF2C
+:10D3F000FFC47986E97BB3C92779701F6A6025C8A5
+:10D400001726D1D7900DFD9B5CCE314A181E96A4ED
+:10D41000F0F3765B7B7B4336B4B7DDF37B89EE1D9F
+:10D42000C138E867B3668867C3FDD5266790EE0903
+:10D43000B1DCB0EF6057390A20AFF303C07C07B00E
+:10D440000B7F65F0B8BE447AACE6F098882082F491
+:10D450002FB387B6A15C9E28D61931EE68C63D79F8
+:10D4600094DF38EBDB619D51E861C6CBAB3AD09ECF
+:10D4700099F172EA2C3C3F98E118F611A6B05DB024
+:10D48000C640FBD70C2CD804E914EBE314D7F89A68
+:10D49000EA1F6BC77C985E6C57E90DEC9CA97B205A
+:10D4A0009D61F59B9616F4FAD322C7DDA0E2A5DDB7
+:10D4B000144C1A817400E3E03AEE7C39F02350FDFD
+:10D4C000EC8E60E0FA51809FBB58B709E1E8631227
+:10D4D0009D7B687EDD32E651F38CF6A7EF979BB615
+:10D4E000239D44F6774788F777673BF407E95D8724
+:10D4F000BB7F8D6AD91794AEB2B3B0FEF67B0ED95E
+:10D5000059DFFE22E1EC11AD46250CAE8022211C34
+:10D51000EE7DE03BA4F45A36BA7F3EEB85379F4759
+:10D52000243EBEC022E0D3408AF77994C35529DE59
+:10D530005F605A6EED768B4037EF3B7D2F221F2EBA
+:10D5400036FAB292011EA7337DC393102E1DD1CFA0
+:10D550005F23F93BB7F4F456E49BBBAA4586785E9B
+:10D56000B9EFE3ADC897A74DC047B01F78ED818FE5
+:10D5700063916E16010386CB930F2AF3C87E3ABBE4
+:10D5800077F880F1A71FA8FE923FAA7CA2ADF36EA8
+:10D59000644018EFEEBD76DACFDC5D69ECD9672127
+:10D5A000BDDF5DC9E34398D831FA169DDD59A79ECA
+:10D5B000B3F5ED07F71191FD7455F95A89EF45DF81
+:10D5C00004B4BB8F57CD6B45F91239CF3C97EF1898
+:10D5D000C2756ECB4C5DDCEDECE6F9ADE17CA8D517
+:10D5E000AFED47BEBE344C5DA7958FC7E48B8B1C57
+:10D5F00013F05E35FFB385AC1F1AC2E861B0F15875
+:10D60000EE146F8F5CA07BF702EC59FBF617594FB5
+:10D61000EBDF5579053B3E0ED7E7FDCF94F183CF85
+:10D62000DFE452E599DA4EFB6EF3F919DA85B6AF0D
+:10D6300087909DF0D230EECFF80FD52E600E582F88
+:10D6400032987FA3F7FF63BD3030C5E7D9B658A243
+:10D65000C615A5B9443ECFE0A1226B94F9F5E92F98
+:10D6600024B20BA9F7D230BE7E749391BF6B580CD5
+:10D67000ED6BCA2A6B699FDD08F203F541E47C8EED
+:10D68000356DA678689BD92FA35FB4715872760D5B
+:10D69000B403A9467E1F5B8C5F16C3BFABFE205B45
+:10D6A0008D5FC6FD6D635E1A7DD7FA6B347039AB42
+:10D6B000F14523ECFB9E27BF98C7351DE0D2F856F5
+:10D6C000606A2CB4DBBE92858C6EC60EBAD346E27D
+:10D6D0003ED75F6FA6F3BDC67C217536E4E332AD5D
+:10D6E000E41F6B8B0FCDC07B078A4124FDEA8F9727
+:10D6F000AF8945FF6E4D4A07CABF834BCDB4DED517
+:10D7000093F8BD35CBA527FC5760FFF7310FEAD55D
+:10D71000EDE77FD182F7FE9423B09F45BF21760AC3
+:10D72000F268FBD4B336DCCFA5605C1DD0D91653AC
+:10D7300090E6B5A9DA42FD6E6A339746C3DFC95455
+:10D7400091EA070C9D141F9CC8823684EBC353A733
+:10D750006FCC8576D9B94CC2FDFCEA82B3DABD72D2
+:10D76000233F8FD2FC88CCA69E6759D5732ADDFD56
+:10D77000B8CDFEBDE43FB44F0BF274AA40FEE7C83B
+:10D7800079DCEBE27E37FBE48EA9A827EC85023337
+:10D79000A07F3397D1BD66692A58E19066E7B37ED2
+:10D7A000DAF3754B5E685FC8DBA34F48BAC0F60B6F
+:10D7B0005D3CCE700DFAA1A03C60F218AE817904F8
+:10D7C000AE970C8ADC5BAFCEC5F56B2BF41F22390C
+:10D7D0001AA075B9F38321A43777B940785A33F189
+:10D7E000189D0B3C5CA8F9513D348F2DD5EF1C40A2
+:10D7F000FB6BCBFD8CECA42D2843A1DD96EB59806F
+:10D800009F27B134946F9BE69BAFA3F3FC0280BFCC
+:10D8100081D2A8F3F6A55A892EDD2B1E0EE13DFE1E
+:10D82000180FA37713208D5ABF2195C369932990B0
+:10D830008AFE91FEE8E256151FEE4AD5AE627E17CB
+:10D84000E275AD0A1F76CB58EE5F10BD72781C579B
+:10D85000AF3EE17E0C581FDDAB4DAC33933E12A6BC
+:10D860008566E0BA12F2CDECEA6CE42F0E376594CF
+:10D87000C0E3CE58A005F9B3EDA2648A275D250464
+:10D880005CE86F568ACD749E7C70A230631E94AFA4
+:10D89000AB33931F02F2C42F7E6F4E1BF29B7D723F
+:10D8A00071E93CC8AF97CC12C2B7B640B2211DD7C0
+:10D8B0007A05C900F9B525DA3D091683781B63346A
+:10D8C000DAF2A1BC3555401F2D6B351888DFEBBD52
+:10D8D000C5FEA1F0BD5E721AC2FD002FB9F8BEAA46
+:10D8E00022ABE42517F28DF761FF5099E3529C407B
+:10D8F00024467FB12C340F636EDAEA9FA0FB546B91
+:10D90000C65819DAF199F7F9E97E57EC456619F12D
+:10D91000BAFD7CE2485A5F9D59467E5E6F085C8383
+:10D920007CBF65E92105FDEAB68F1CCC08F682A311
+:10D93000F3EF55183FE62834479C633101E5B836CC
+:10D94000AEE3AD10D153A7C1F7E758F2FF1434E5A9
+:10D950003BF11E46CC0484E7DA4BDFCB9F13852EC8
+:10D96000C8653B16ED6521346134CA29AEC79828D5
+:10D97000A586E3777D66DA5FD0CFB4AD08E68FE3A6
+:10D980005576DD41F3F2BEF353B4AB1C473FFD26A1
+:10D99000FA3CDF243D127BD41E124663BA681AD9C2
+:10D9A00067E1F540EEAFCDF29E70017C775773B919
+:10D9B000DF7C0FA37729F02F3F0CBECD0520A5E912
+:10D9C0006102803CD62B90C88FBE4A90832184E7A9
+:10D9D000682BD1538A7AEF2172BDF6A38D4B31EEBD
+:10D9E000C8EED1CFF32B15BFF82726D379055AA25D
+:10D9F000CC9C3ADB86F26FCF583915F7DB0FC7475F
+:10DA0000D7F3EFA572F9B0DB10DD3EFF22D5C6FBE0
+:10DA10000759199A40A86214D707792199CE6DF851
+:10DA2000FB0A02970BEC5A467A2F6E4CA7CD1336A1
+:10DA30005E501D87FEA09F216A3B267587AA61FD67
+:10DA40006D40B578AF2D2E93C3D1A1F4C211EB4B2D
+:10DA5000EABA800FAA8717221025AACF4ACC742EC3
+:10DA600002D250F956E88543AC5A7FD344D1608541
+:10DA700079E500300C503F7EAA59778E22D5BDA3A0
+:10DA800060F94F8D4C4E98D83BFED6312C5003E3B5
+:10DA90000FF1EAE11D7BDF0BCBD12E8FA4039C415C
+:10DAA0004FBF182A3E5BDF2EF98E3E7C40F0A479F2
+:10DAB00002689ADF62DBCD0094E69DA2161F4BF24E
+:10DAC00077BCB143417F28C0AA641FCC7FC4536F89
+:10DAD000797741BED9C7F92C36FF85E54897521AA8
+:10DAE000C7D311F42D039C3733E91F18B7A3540A89
+:10DAF00032E2635B2887F47823134B104F8D15EFC8
+:10DB00000828D757EF651E8301E9FFBF2DE1F39B7E
+:10DB100091CACF69982893FC13DDFCFEE8EA02C1A4
+:10DB20008EF2F5E0D21748EF6D3D2030E4FFE2DFE2
+:10DB30001C7DCC8E74FD170BE59B5FAF20B9F113F4
+:10DB400068A744F19F0FA69723EBE72EDA6EC0F388
+:10DB500089AC79417A8F25D12F7AAE467CCCEBF017
+:10DB6000D23DF7427ECEE6981652288F5A0D6C525F
+:10DB7000D9AFA6CDBC9CDD9240FBA85196CE866B5A
+:10DB8000617E9B9F1219EA4BA325983A17FA35BE7E
+:10DB9000E8404DD0677FB4795A2815E5784C058563
+:10DBA00041F7B5E352391FBAA7C9BF1D06FDC64FDD
+:10DBB000E6B0B4F9530EA0BC449B19EF35D915AEAD
+:10DBC000E7D68A012FC679AFBDCF67C6F199BA7F74
+:10DBD000695C54F604C2F91355EFB18A79F48E8961
+:10DBE0005BE5177B252B8AB6CFDAE88AE1F12D0FAA
+:10DBF0000907903FDC5E46FA43AA0C8686AB7A1989
+:10DC0000272EAD78BE11F58BA35CA075AC153BAA91
+:10DC1000F15D89B5F731A95AEEDBDF3FDB7E79AAEA
+:10DC200085E0B1D1C574EBA0F73040BEB9E7455FE0
+:10DC3000C7BFE1B8E37BD711A3AD23BF93F2DA3CB2
+:10DC40005ABDC10B9AC706B53F7F2A7FC7C85EC0C1
+:10DC5000DFEF8894F735F60FE85D9900D8EA46BA09
+:10DC60008F16BC16F3F27302E3F7B5F4FCDD27AFB1
+:10DC7000D255E47799858D938D74C7F10C74A7DA2A
+:10DC80004FC07756140182FC2DF931FC34CF487A0D
+:10DC9000FC5F978BE1F386FE631B9841BDA72A17B3
+:10DCA000A7F6958B4C958B56A68450FEFD5FCB4511
+:10DCB000908324179B61A589B053896D6F5A8A7A26
+:10DCC0005C9387E31127976227D6EB8B0B685F4441
+:10DCD000F909A9BF6FC6F8C855827ADEA5C205DD6D
+:10DCE000500897AF5D728F9EC2EF1BF01F39F89EF0
+:10DCF0004AC2750530DEC6D29C31B8BFB0F95F2488
+:10DD0000FBC05DC0E357DC95FCFCDC9E3BE789F083
+:10DD10007B714B52B99DBE44A3BF4ABF0BC7598B01
+:10DD2000FDA27CCE3593BEDCCC825C1FAAF6E95600
+:10DD3000971A47ACD255249F44CAA771BF7716A340
+:10DD40007C4F355824DCCFA17E3E98ACD7D7482FE6
+:10DD50009ABE6EE9A889477F58B6EAEFCFB6EAE3E4
+:10DD60001C26A4717926A6723FC02AA182F69B4A7E
+:10DD7000B140FB388DFE7AF478041C23E18784BA25
+:10DD80007202C5C7503EAEA89B21FF6E03925D8F05
+:10DD90007A2C5583BB44706EBB53188BF2724F7B49
+:10DDA000990DFDEB06B7F51ADC1FAE3330BAFFB89C
+:10DDB000AEE84D8A2B69AA849E61518E7C61A6795A
+:10DDC000745F3C031FD37ED5AE583AD0AF150C6DAF
+:10DDD000A7B885A6C0A1198CDBB10CE3529AF26BEF
+:10DDE000D216A07CCF2F2944FCB6D59B296E46CAFB
+:10DDF0006751FD0827711F43F3FD6E7ACCAEED2FFE
+:10DE0000CBA3EF2B6F4CE3FBDBA008A20AE69391B8
+:10DE10002F7890FF33EACC51E751ACE2292D8DDF0A
+:10DE20000F6BAB3F44EFCC00BE026C207CC1F46BA7
+:10DE300092C3F031A91F7CB8347C881A3EE2671285
+:10DE40001F7676085CDE925E5BCBA4DB503F2A1522
+:10DE500066B2631B4D7C5FBEBD40E50BC9DA86C46C
+:10DE6000F65DE93A6E9140F7703227F2F7F5ECE58E
+:10DE7000CF535CD366D6FD3ACA3BA580DFA38F6C37
+:10DE80007F679AA0C2513678683FCDF10878A5F92E
+:10DE90006CC94B6E0BE7D38DAA1DBDD1C5F9744B70
+:10DEA000FD06E2D30B9DA726B76B553B7ABED7671D
+:10DEB0004675A0184AAE4A45FDF973FE1E15333A61
+:10DEC000C82EFF049B84F9652B337C4BD2C2FC72B5
+:10DED00092B742C07A57E2BB42D0FEE320BF07FAB6
+:10DEE00071F01745F41E978F1133CF671D066272CC
+:10DEF00090A13B20EF128354EE9A077389A7DB9120
+:10DF000094B75A412FC2844E57F1FB175DF8BEE417
+:10DF1000707C2792BF2FF999FA9EE4A89655C59B6D
+:10DF2000713C59F4A1CC3889EF4BE2FDE789EF5100
+:10DF30005CF42990B54DF1180FC3EF6F4B0F3249C8
+:10DF40009884F935C518F77CEFAB16F59E64470D3C
+:10DF5000DE7B795C60F48EC46A11F4FD502C6A306B
+:10DF60005484D1F1EECB3BE2F09CEF74F0E601FD7E
+:10DF7000C7787F10E7B143A5F7F5F6C574BF6C8E7F
+:10DF800023E4C6F607F63CF9C42618EFB37D567AAB
+:10DF9000D764A37DB11BCB3F7BEC5D37EA8BD3FB12
+:10DFA000DE35473B9F5C2406AFC27B64E5CA105652
+:10DFB00003F32F0ACE3453FCC9AE03743F6D91E4D2
+:10DFC0003363FFE52D7B283F65D79FDC587E348D7A
+:10DFD000F3C7E9549F1BFD12B92D969000FA67779D
+:10DFE0008E7F41D47376951ED7DB5FA5FE37DA5F4F
+:10DFF0003D847839FD9885FC6E071EFB0DF57B6A24
+:10E00000DF8B34DFCF76BF7B17DAD3E58C79509E78
+:10E010009FB6A97E3D6B475CF8FEF615151E5AFEAD
+:10E0200074ACBA0FCE18A49E7A1EC31C007FBA3FF0
+:10E03000D01187F70B3F33F9CC088F85080F488B39
+:10E04000000E28F717060D34CF852D6D74DF6AE1B9
+:10E050005EEE1F5C08F022B8B41CA0F9BF8F7019E7
+:10E060008FEBF8B39BDE75D86BA1FDB3B6EE850ED2
+:10E070009F1BE1A3AD17E0C0D7BDFBC2F03447C37F
+:10E0800053CB9F685EE57BF9BCCA77F179CCD90B9D
+:10E090007872209E6612FE4FED6332DE83E9DAF37A
+:10E0A000EE49B4674EEFB3CA685768F3CA00711BF4
+:10E0B0003716F988EB63B6D740FA98891D749EB37A
+:10E0C0004892247C9FA0A73C600E7079DA519C0E88
+:10E0D000E5CF3C0AF62142420A8E40FFEAE934EDE0
+:10E0E000FE4F871BFD62BB2FF7137D7E1AABC25B11
+:10E0F000EC7063FCCC8674DFE9B4B07882D31FBEC9
+:10E100003802D7BDDC58F19B4C1CE7491E1FFA555D
+:10E110004EC5DF1EA2790FD59D3746A600B7383C05
+:10E12000FFCE17988FEE25EF7D2D26FC1C5A48E771
+:10E130007EB78DF60FE83EE2697CE791E613A438DE
+:10E14000AD61DE32379EF37DCA1C3E3C97FDECE7A5
+:10E15000AF51BC4D57AAE67FEAA07AA7F6BE9680DB
+:10E1600069991A0FCF0237931C03383658C7469364
+:10E170008FEAFDA200BF3776C6000213F5C4560D24
+:10E18000CE15E6E9BA731D2E4733B664B793BF25A3
+:10E1900010FDBE59A4FCCD7D74129D2B9F63D1CF81
+:10E1A00095991A27B7DC1843F1371BED3FA3FBB74E
+:10E1B000958A45C2FB2BC754B97842BD97FF554C91
+:10E1C0009C2200DDEC4FF7E5A48FEF7B0FB76CF5D9
+:10E1D0002237C2B70CCF3D28CEA0ED7A8C27EC4A6F
+:10E1E00062AADDC942043F9356BE9197C7F3FCA4CF
+:10E1F000CDC135F81E26C297D77F829767F3F21FED
+:10E20000A9E573D24AC6A473FF0EBDAFC19829BE5B
+:10E21000CBCA55783478F4C245645D9A5D0D95E7B4
+:10E22000E1E5DC24EAEF32EA4F84FE467DFFFE00A2
+:10E23000EF8A35E15FD08FF55FD54F90F492E0C360
+:10E24000B7AEE09B87EBBFC78B99D414FFFDFBFFF4
+:10E2500067DB2F377A854F910E870844F71A5F776F
+:10E260003D367C0CEEFFCD0D4B43A836BB628BCD0B
+:10E27000A9F0FD9CCCCF4FEE79743D8B164FA2BD1B
+:10E280009BD19357CFF1CC43F5E7B3ABD3B9DE596C
+:10E290009DDEEB7FC373393CAEA28D33FC35275333
+:10E2A000280CB7D3598580F187F9ED567ACFF7223C
+:10E2B000068202E63F928504D4DFA35827E52F4665
+:10E2C000100CC5F7A8647A38731CEB768B43F1FC0D
+:10E2D00039B412EDB4F79DBEC67418EFCBC73A3E01
+:10E2E0003040F94FD27C2F75A25F289DDB570EF589
+:10E2F0007D5C0953A043C13ECD154DEEF7C05312CE
+:10E300004F859FB7DD287A1F49A7F564485DF65E03
+:10E31000386BF26081FAFE92D6FEE4534FE2563734
+:10E32000ECBD70EF80F781E754CE7FF4E7E3062879
+:10E3300057E5ECEEEAC06DE1FAFEC974AE679F4E98
+:10E34000177476218C4A76DCD33771FB69F7E5DEEA
+:10E350009AC751DEB618693FFD69CB9FE9FDC773C7
+:10E36000258CECBAFEC6FD3402EF9FEE78328D9F0D
+:10E370007704F4F1CB4FFC724478BC258059764E7B
+:10E38000E0EF7010DE0F79148B91EE39923FC6CC1E
+:10E390002A789C0ACE17D218DC8F0E453C75501A8D
+:10E3A000C7BA29959844FEE904E6A1D4C94A284D84
+:10E3B0006615066EDFF9294D63414A33D03E457F2D
+:10E3C0000FEBA654C61B9F61F11B3978623A14DF2C
+:10E3D0005D2DE1DF23E28344C4E3B828F23C222E22
+:10E3E00048DC5949F21CE382F29C7DDF53D0E4F70C
+:10E3F00086F4E2F7906EF6A77BDFC7F4F0B3BFE5D3
+:10E40000F72BD618C8BE3E6E9B66960175CF247852
+:10E41000E91D104560253B40BFCFD6FCFFF8A7C5DE
+:10E420000923309B4DA7C2E37798D5918FE7C5B3F9
+:10E43000D4AAB3D4739059AA1F248631F59E9E871F
+:10E44000EEDBCF52CF1F6645F85F98DFA2F3A3281B
+:10E45000F80F58C72CBF81CE0D66C54C7BB593F520
+:10E460004F2761FDD1BDBFB2083FD4A0FEAC88FCF0
+:10E47000ECC8F65603B326E3774E4FCFFC4026BBDD
+:10E480004EF36701C1C9D4AEC1F221F985FC577AB8
+:10E49000C3E19490C1F9C4E6BF3A2EDA3BD95A3AA7
+:10E4A0001BEC335342DFF6B0238C47BED7E4B046B3
+:10E4B000E7D9B8B1453ECA3707068A4B5DADEAFBDE
+:10E4C000A687FC0CE76D0B3D40EF54DF9FA990AF92
+:10E4D000D65A10A0FB0131F9019712657E4DF8BEA6
+:10E4E00033F05753ACFEDC64A9BAAEA519DC7F7BD0
+:10E4F000E8A2E4623CCF5E250B746F7895BC8CCEAD
+:10E500005907FB3D815AF57704B4FCCAC46D0CED84
+:10E5100036DBD7AD0CED499B18FD5ECA0C75FCF5DA
+:10E520006AFD8D89DBC84FD290C7CFF723EB1FC898
+:10E53000DBE042FBBB311BF6BB983EA450FFF579F4
+:10E540001B4AB1BD35D4A8BBCFEBCBE0F6AD752FE0
+:10E55000A74763AE399083F420FA29BE40ABD7D8E1
+:10E56000CF79D2F56AFB265380EEC934A9F6D0D212
+:10E570002DB16BC92F97B1FD08BD6F95CBE8BCD10C
+:10E58000167A8ACE11ACF9666683BC55F6337C5F89
+:10E59000C3561024FCA0B329A4A3DB98DE77368CE5
+:10E5A0007DFBAFFBD6EFC2F53566FB69FCC1D65BE0
+:10E5B000ACC2B351D5AF8D36FD39DAC20CAE57AF10
+:10E5C000CDE0F2DEFA32237932005CC8DEBB3E23B6
+:10E5D000EF06B4EFACFB0785A3AE7E362B1D128D84
+:10E5E0005F22E5BFA340887847C940F33AB7D7A078
+:10E5F000BEBBC8DFB1E8B5038266ECF7D75BCA0ED5
+:10E600005E03F359E07378317EF2C92DDBE99EFE9B
+:10E61000C2174D149F30AC732697832DFC3D46EDF9
+:10E620007DA38B5A2CBAF7A416B1B0F71A61BC853A
+:10E63000473F3DCAE89EB1FEBBF66EC06AFC10259E
+:10E640004E2DF2DD81473222DF5D56DF1D2888EE38
+:10E65000A7897C7760575020BDB10CE358691FB083
+:10E66000AD18F73D95470DE437E8CB87F2D65C53FC
+:10E6700058DEE0217A546263BC3BA2F0D37B999CC4
+:10E680005E76E3A11AD9FD3F5B1BC237BB581DC3A1
+:10E69000F3A6DAFB4409CFB56B033174BFA456125D
+:10E6A00002183792195B6C45FF238B1724BC8776C1
+:10E6B000957132DD7B32DF2F8EA3775AB72FE8C0FA
+:10E6C0007B75B52E91211F67C6F33802962AD0FBC1
+:10E6D0003475D29BF1B3701FE7E0F7F4B2241690C3
+:10E6E0000D68D779199E2FC366A52204A657A6C127
+:10E6F0001BC2F7AED8248BB483BF3373C39809E42D
+:10E7000007A6BF036D57855EC171BCD612C4FF94C6
+:10E71000FB9D640F065C467CDB947D9CC1CF05CDE0
+:10E72000B1C5A1BFE2FC66D8C9B71B508404C4C3FD
+:10E73000EB6D2BA75F0DDF4D0191E21DF2BFA9BD6F
+:10E74000ED6A68DFDD66A6FB161A9CE43A51F77E97
+:10E75000837B853E6F8E78AF426461E5903FA2CEA9
+:10E7600083B152160A8FE3757AF9A1BBE4A0F729A9
+:10E770003E02FEA4F30F35FF9E9ADF69F213DE77A7
+:10E78000FED540FED5836D73B2485EDA17B7DA71F5
+:10E790005F78849F63F6279F7766C8DA3B0936F572
+:10E7A0009D0A1BFABD22E9A9AE8A7930CED01A683B
+:10E7B0008F1989F83D6CF2605873BD2A1F45079781
+:10E7C000E31ADD44A6F511F4576FF2E4FBA17EFDD8
+:10E7D000374675DF78FA86D0640C7B90695F6DCA26
+:10E7E000601E640F93B3234D82798C7CD1ECC1DF22
+:10E7F00055B8EAB9822128E747BE3683E41BC289AF
+:10E80000DE87AF347BD04EB6543A3DE238ACE720D9
+:10E81000BA3CEB30933D2456DAFD647FB54D70C9A8
+:10E8200061726F6595E4114DF47B3794AEEC47DE71
+:10E8300067C50B25E87735ABF672B2BAAEE44C3B50
+:10E84000A5496ABE5554A6233DB702DD60DCCD81E3
+:10E85000159CBE97A55A496F2E7B7D68CA40FEC1A4
+:10E8600027AA5C9E5C00ECB61565E4B72D7AE044FF
+:10E8700023D2DDB258AB8474688C1BB67132D2FDE2
+:10E880006F4D74CFB33676823C2BAC3F63DC4417BC
+:10E89000C2C328286948CF233383378893904E9486
+:10E8A0004D789F7FDCD68D3788205F76C62A6978C1
+:10E8B0005E76D9D6CDBC3C49D96480F22BB6B6F28F
+:10E8C000F24C254D80FC755B1FE7E579CA26CCDF4D
+:10E8D000BCF5495E3E8AEBA3DBB73E7303EAA35A5D
+:10E8E00093A714FDD3CFC2FC0BF2F09D549EDEA97A
+:10E8F000C2452B7F1EBF9BF05D559E4696BFA0B6BE
+:10E90000DBDF4FF94B6AF9CBFDF4FFAADA2ED44FC7
+:10E91000FB836ABBF67EDA1F52DB1DEEA7FCB76AEB
+:10E92000F91BFDF4FF07B55D473FEDDF54DBBDD5B7
+:10E930004FFB77D47647FA297F4F2D3F1AD1FF0737
+:10E940006AFD4EF5BB3BB6E13DB4D7DC20AF509E2F
+:10E95000E4C73690BF6B5B6521D17FED78AEFF35A4
+:10E960007A77ABF702DECEE471A56F6772FB66794A
+:10E9700026B70B8A1EC85D3719E9F0F7FC9E22E81E
+:10E980008F23780F57794020FFDEB2D7F9BB32CB07
+:10E990001E1075BF1FA4B5D7E61F50E759A7A64B99
+:10E9A0003273689C6CC5E59916A61F4D923E6F05A3
+:10E9B0007EC2F8FF3A27D733F90F1437E0B9492D53
+:10E9C000E8195C5FBDC31C42FF57BD2452799DB35B
+:10E9D000D88FE7FD8A24921EAA772684F0BDE6BA76
+:10E9E000BA42DD7B9F759248EFC788F153ACB31CE8
+:10E9F0002837A649283FEB98945044E76AB04F4324
+:10EA00007D52592CA1DCC98E7726A05C9E95C5E16C
+:10EA1000DE1EDB65C37B14E24302BD15304C128958
+:10EA2000DF73EB84800CF368979691FF7547B37A98
+:10EA3000A6C8F879A226E777FEEC2AD263B5A0C76C
+:10EA400064D2636CC898E4DEFB9BE2D19166D45B30
+:10EA5000529A9199402E1FCA4CA071773CCAF55624
+:10EA60001EE82D7C67ADB590F177DE5C56F2EB9633
+:10EA700089CC9518E6C73C946954DF47E2EF50E72C
+:10EA8000E17B8861F01DEAD7EBADEC41F4565625E9
+:10EA9000C8CBB0FA1697A4CB3F97A9BEABE4611ED2
+:10EAA000B46FAE7A6E0BE993B3A84F18EA973FC4E0
+:10EAB0008C44FD027AC4C2FACA414D1E6B768B2685
+:10EAC000A76B55BD511BA1370697BBFF787D38D189
+:10EAD000A7A07B87A63FF9BB1CE304005E269F81AD
+:10EAE000F40A137D74BF7F30B8994C2512DAE383A2
+:10EAF000C1CF94F4453CCA69934FF49C88724F6A25
+:10EB000030F86AF5CCD6F4ADA8D7BE38BA3C1FFDB4
+:10EB10005E2B4D1D337721DD1A86D0FD0E59F53B56
+:10EB20006CABDACF8EE7E1EFFABCBFA56E1CDE1F3F
+:10EB3000F74AE42F492D96B19D0DF6E98964C7F196
+:10EB4000FD26937CFE0568CFBF6896F15CE0F0B3CC
+:10EB5000EAFB0D990E82E7BD7BEEA3762643858BFB
+:10EB60009FF73382F7AAB404B2CBE59D56D56E3C2D
+:10EB7000BDCE0B65B542A701F5CF5BAD817556D40F
+:10EB800027EA7E8029811B71FF130C98D5A01ABC3F
+:10EB9000E8CED81EC1A0F99FBDA22BDC0E35DD3812
+:10EBA00065329E874A2345E82FD56D5B67CAC472DC
+:10EBB000416BEFC5CB4328BEB4BC087878A65D2B6B
+:10EBC0004F593705E6B3C7CCB4FE15ACBF071F835A
+:10EBD000A4BCB40EFBDF5DACB6573E5F87BFDF055C
+:10EBE000F3B9CE087BB0E1DBD2D639527BE79BD3B9
+:10EBF0002AAFABCE052A943BE3701BB7A8ED443295
+:10EC0000EAED55A5FCFEB0F6FB59DA3DE21EBCED7F
+:10EC1000BD494157ECE787FE33AE008A96183B0F9B
+:10EC2000D9016E8BF657584D02BEDFC5DFEDD2DA43
+:10EC30002DDA3B93EC9C252F17515C70947687F16D
+:10EC4000FECC3FD1CE6ABE80F14E87DE5CBC4BC6A7
+:10EC50007B33150D0E23D567DCFF157D7D5AFBD365
+:10EC6000BBDEFC318E7746EE4CBE166AAF0A015C05
+:10EC7000A2B4D3EA6BF7AB27B9BC13DCF0FD3FDCE1
+:10EC80009C0F9958E1413F53D0EAA77B6C3693BF64
+:10EC900004F509803E80710A5A3AC99D4BF523BF9D
+:10ECA00047F257D0CA12A7A1BCBC4FA473F7A05516
+:10ECB000B18F867C33EC53AA614A3563DE198BF140
+:10ECC00002CDFB1C24D76BEF6B77E1EF2B291E33B2
+:10ECD00043BBB7F9F28E5409E65177BFB9F4E74860
+:10ECE000BFA165AE7BC2ECB09C2C1EC79D19EF2F57
+:10ECF000457EB4013FA23E6E34F9ACF86E8A922A8A
+:10ED0000505CB50DCADFA0F24CB5DC33F56ADA977A
+:10ED10000912CEAB3E77F6D462D46BAE04D207B6FE
+:10ED2000BC29A573A13C20992524AF8AACB2BB11A4
+:10ED30004ECF889E0AE4BF671C0E09E3B14056928D
+:10ED40003E10F39C149F6551EF3B658EE17ABE67E0
+:10ED50005FEE56FD026E1EDFD31CDB715311B48BC8
+:10ED600079509014E8BFF1FE0D25189FB8F5FE7795
+:10ED7000FE84F1AD4DC922BD33B0BB3AE4C57ADDA6
+:10ED800006D6B11DECC83595D33B703FBA86C93263
+:10ED9000DAEBBB0DD3FDA89FBB9344B65DE6BFEF96
+:10EDA000101EAFEA28D0C74B6594EBF36BB37C0F12
+:10EDB000BAC7633C5061118E936490657C3AB8B0D9
+:10EDC00083517C7E726EAE8471DD71851171B0935A
+:10EDD000F5FD244CD1973BA745C46DDDA22FC7DFBD
+:10EDE0004F08CFE3EF4484E74F223D523C093F7F79
+:10EDF00088E145009F2718EAE9C6AF87503C2BC23F
+:10EE000011EDF69861A207CF4532CD1D33300E8E3D
+:10EE10008D88217BE9A03B86C990B72C66244F2DB5
+:10EE200009C103B85FB5085289421A2A78E0AF5089
+:10EE30006E87FD2ACADF48F8656672FFA043FD3D74
+:10EE4000B0A018223BC2F6C010A9DA835BC7083F06
+:10EE50006C79589EC77B6F77ABE7282E2D4E8DF0CF
+:10EE60000A2B43BC4D62017C8732F3FE134A08E64D
+:10EE7000B146CEAD403B6395D049E328650E1FEE09
+:10EE8000BB9330CEDB88F1DE0AA591F8D8E3E6F635
+:10EE90009FCC66FB118FAE9902C58FD41F8AA9C380
+:10EEA000C3977AF5BD062D8E4DA3CB97DCDCFEDC37
+:10EEB000D32E085EF483DF91BB1DF1ADE55B7C4E84
+:10EEC000FA1DCECC31159D4897EC7A6E87821EA034
+:10EED0007BD95A9C981657F85196999FE767093D38
+:10EEE000F80B6971446171E0747467C4A30BBF844B
+:10EEF000E73D99634A2494338F68F72F18EF179FE3
+:10EF00002FA473836982F722D59F8E765DA23A5E25
+:10EF1000A253F4D2FBEE302701EA3FCA78FDC4DCED
+:10EF2000BDCBF1DED51E241CE49F7B389C23E93643
+:10EF3000B5DD5F320AE165007D98D1978E0DEE1642
+:10EF40003A0FAC7F902558C6F4A5EBF1466EFF74DE
+:10EF5000CF9729CE72303AFFC41DCFFDD8499B24EC
+:10EF6000B46FD3721FADA67B300F3209F55D5A7BAB
+:10EF7000C74DE8F78AE487803D6E2C8F93FB6E7E49
+:10EF800078A391F3074B11096F91F1A591F1A43981
+:10EF900059F1AA9F02F4402CDE0790AEC038C1EEB2
+:10EFA0000718BD1350FC62F36DBF83FEBECC334B1C
+:10EFB00028AFB3DEF23D6987797DF94B5F16CAE968
+:10EFC0006D62A72D3ECCEF290AFCFE59A4BCCEC928
+:10EFD000E27427A3DE70FDF36926D2F710FC7DBE34
+:10EFE000E4919284FDAEFFA335E9FFD06E61563FF8
+:10EFF000DA2DEE762D9F417658D65B3C7F893B63B8
+:10F000009D928B702B277FD1C1CC39E42F12DFE387
+:10F01000FEA251466F00F3EC7D1BC5DDEDDC77C72A
+:10F020003C8C57AB4FBE5646FD3C4EDDFF8CC9D2E3
+:10F03000F85BBF7ED1ECF521DF447E1F99A5C59515
+:10F04000947C3213F037EA7133C5DDE50B65F47B50
+:10F050009CDD8D46C26799515EBC3A6C9FD6945C2C
+:10F06000549495C47F97D8071B06F9BC81F980D9C1
+:10F07000DCCE634548AF59C066285FB2146E406667
+:10F0800055C6305F189DCAE745AADF94EC2DCAE249
+:10F09000710874EE635259FA9984123613F5327C72
+:10F0A00043BD6BDA15C3CF7B9CFAFB9146238F17C8
+:10F0B000B9415DBF09CF75C6E27B6F42C832BA6FF6
+:10F0C000FD9BD57AA2D511320E413FD91B47E8DE10
+:10F0D00065C43930EE6F292EA79C911F14E142F9C7
+:10F0E0007B25FE6E77258F07A85DC10C781650AB87
+:10F0F000DE5351EEE2BF4FCCBC5E19DF57A12DA607
+:10F100008CFF0B11FFBAAC2C01EBA7B20E8A636423
+:10F11000ED4CE6F112FA73A76DFDBC03A5F901C42D
+:10F120004A23ED5346BE66A3714D958CDE09A73781
+:10F130009B70FFBB82054443AF1FEEED4C99DA692B
+:10F14000E7B1BBBFF9200DE572BEB0DDF706D90D02
+:10F15000B1D276D48F317A3ED4EEAFD5A874B2ADA9
+:10F160004A227C6BE56EE518C5DB67B1EE6ADC67A9
+:10F17000655526E8F0DCE3973D9FCE7CE3C2FB0DAE
+:10F1800070BECE15E99D2EF9BC9BCAB755C983F454
+:10F190009FD34FFFA9444FFDF79F41E5ADA12FE25B
+:10F1A0006F00506CEB3E115F22F7DAAD917076AFD5
+:10F1B000D0CBEF8BF747C69373B8D84C5EE74D00C2
+:10F1C00037DB4382A78DE1EFDEE8EB4DCD3E17CF75
+:10F1D000CFCBB5FA21E7CD581FF6BD6D32FE8E8E2E
+:10F1E000BE7E49D147F1FCDC5DABCFE7F7C3F3FA54
+:10F1F0007A91F8899C2FCC2BE94761F3BAC26AD186
+:10F200009597CEEC33AFA45BC3E675B54B5FDF5784
+:10F210001D7D5ED7E55B069C9756EFC68917562F76
+:10F22000721D374FB5F403775EFFD6D20BEBF7F6BE
+:10F230007903D7BBBB32721C85DF53377BDF46397E
+:10F2400057C6E495F84E3873C4448D0B2E52F9E33B
+:10F25000EFE8A748C27800EF516CF779268F4B3959
+:10F26000FCEC023F9EC32CDB6796F1BC2353F55B9D
+:10F2700083E05988FCBBC72AC5633CA0C52DABFB06
+:10F28000AB8E6C8CE7DBB3F39DDB48EE31BD3DC349
+:10F2900098A708F5358830BA97F1276C97141E4760
+:10F2A000E125FBAF5EF0FC99F6553FE6FB2A2D7E8B
+:10F2B0003FDCCE62137AED2C2D7E7BBD3ACE3759E2
+:10F2C000DC1F08763EFD3E6A72AE48F1CD8F583B9A
+:10F2D000D6E3FDA3479CCE78DCCFFC469DB76637CE
+:10F2E0006AF71A5266E68E3146819796FE0F29DC40
+:10F2F000A2280080000000001F8B08000000000012
+:10F30000000BDD7D0B7814559AE8A9AEEA57D2DDE3
+:10F31000A90E9D178F509D7720840A8418909126FE
+:10F3200009195486E9A022E80C360908485E181F1E
+:10F330006165C7CA431E51C7384604046CA228BE83
+:10F34000669A59D488C16DA3C3E82E8E61D7191D62
+:10F35000C7CBB6C05506105ADD41BDABC33DFF7FDC
+:10F36000AA92EE4AB7C2E8CEDDEF663EA73875EA4C
+:10F37000BCFEF3BFFFFF9CBE2B81AC0C1411FCE361
+:10F380004A0971E6E4F476B9091957E215A7D0F7EE
+:10F39000BFCD3410328D900DF44168BD9227F877BF
+:10F3A00073F4DF2221EBCBE8F7D0308B9007C44118
+:10F3B000A740EB1F7009A2C2413B09DBED7DCD6088
+:10F3C000F0B80879E82739BDBC7BB8BCC5E7DA05D9
+:10F3D000E57106E20BD8A0137135A1EFF75A446727
+:10F3E00057092D0A83EE1A3B2DEFF9C3759C8390C4
+:10F3F000CCF1F45D0A2175AD95E4D854429E378571
+:10F400005F3D0FF3D9CCF977D37E5EE829A9166862
+:10F41000FBE52708B1D24FEBD65EF5C0F151844C25
+:10F420003F2ECE86F775DB9D324FDF370E3657C342
+:10F4300038A499C8B9322169FC6CDE4EFB49BBFB8C
+:10F44000B0DC41A7FCE080D417A2E5F02E4EEE958B
+:10F45000A07E4DC91A808FCD23D9E87A97C254F186
+:10F46000BDB3DA08EDAE32C99DB49FD346B208E011
+:10F47000781EFE660D3F97FE442A2774FE4B036BF1
+:10F4800097E2B8220559062D5B449C87451293DB11
+:10F4900068392D8158AC5308296B170FDE01E3AF93
+:10F4A000B28BBD14C68E72F1E0C3B0AEE64C91973C
+:10F4B00061703FC255EB7FB9C76B2274DC897B4C0E
+:10F4C000B433B68FE7E97F9302D1E5C97DD1E592E8
+:10F4D000607479EAEBD1E57D1283F70CCB981DC7F8
+:10F4E00029BC070E9809CC77F5A904BF99C27BBF48
+:10F4F000911058BFF2AC19F1A172B5CD03F871EAC1
+:10F5000064C22E332DBFF25E027E7FD3D356F6BD8A
+:10F5100021F04B282BBF4C24F0FDEA5181B2643A14
+:10F52000EF97BEE66FF016B16519A1FF5F16EEEA20
+:10F5300082FAA9813291BE7F7E022183502FF88BFF
+:10F54000619DCFFF95C77EC34F9AFDBDB4DF532F9A
+:10F550003EF14B80D7A927C7247374CE971A7AA798
+:10F5600076417D9B5DEAA5EF679C7A26DB17B12F7C
+:10F57000ABF798A3D6D92C71B8CE56C1D3FE28ECE0
+:10F58000CF2123E253CB727F5D90B66FE1326505E8
+:10F59000FA31513C2D82B29CE6A4F83AC3C1F0B6D0
+:10F5A000C54ACB31F65D7BD66EE1896FEA70F9E82A
+:10F5B000A627703E0527DE45BCDE6F540C0900C748
+:10F5C0004D9CBC9BCE7FBFD5514C92E099E907BCC6
+:10F5D000B95332E0FCE8BA1E6E04BC7893977B49BD
+:10F5E000FCF10AD2FFB4BD6AEA37D4D371DDC58419
+:10F5F0009CFD73C20D1E3A8FFC2DD1FB5EE88F2E51
+:10F600006F00F8507CAB2511EFDD309FACF5E94879
+:10F610002704E75370E2FDEBDC74BEA3CDA419E030
+:10F62000A21FB75B627CE4A9A7683F05D80D7F9E47
+:10F6300067FD49A9745F54BA7A89637444FF6E19EF
+:10F6400043E96D35C7F88BF67EB56E1E5AFFD3D5EC
+:10F65000FE5D26F9BE10EEBF5984FD3F79E7DC0759
+:10F660008E1B47CEE7C33B3D9EAA88F7376E597382
+:10F670003083B6ABDF9B32858F806FFD93AFA65E84
+:10F680004FDF9FDE23C8C002EB173FFEF319F0DD0A
+:10F69000937C00E60BF51EBADED381DF38E0BB1B9E
+:10F6A000B73BA7F0D270FB155BE678AA0A86E17932
+:10F6B000B174FA4239E373AB0346BF05E822F0FBAD
+:10F6C000EA3180A75B3839978E5326F878A03B7BC8
+:10F6D000A9C7A84C2764D657FF7C7034AD6F3A3069
+:10F6E000ADAC8BD67719BC57FD08E86E272FEFA677
+:10F6F000CD9E7BFBE6545FC4FEFC56C5FFAE85F590
+:10F70000D88F4271239732F58182DA4A28CF282296
+:10F710009C99F263C709E2F1DB603CF2AE2199905B
+:10F7200013FD77150B06E447D7039D9C220E19E8BD
+:10F730006EBFBDF9DF71BC678D38DEAC601207FCAF
+:10F7400077FF639CDC45001ED1F477E244BB63364F
+:10F75000A3EB1BBC28070CC445FB5BF9E824E403BE
+:10F76000DA7BFDFEADF247F7A3C78B132ADE026AF0
+:10F7700046E297FEBB51F31413D0637D2B9517110E
+:10F7800074537FBCDB446C23C72164087F09E02FDE
+:10F79000C54B22E17AADC837E81F67A1787B12FE1E
+:10F7A00095CDCA848E7F13874B23AB2704F280CF7D
+:10F7B000718258D19931CC5F49B91FF9FC69FACFF0
+:10F7C0002E19F842E008D03BC8D2DD205FC4E09992
+:10F7D0006D50AF8CF7003F1A0D484A9FE45789C817
+:10F7E0007F4F4BA1C7B1FD33936485BE3E0BF462DE
+:10F7F000C3768EE408FED41678D511A2E5537B4774
+:10F8000055F00EC0DB7F75C03A4F064655981CF187
+:10F81000F9869E6FD29921DE7C00FFA47897E4F6EA
+:10F8200024B869997452A10BF26C547349738C7D9E
+:10F83000D3DAB94CCD2512F08F9FDA64E0E3C99694
+:10F84000BA47405EC39F87BEFFF4F551BDB0FFBF0E
+:10F8500050E5EA528E8DA3F533DACDE8FDF557F287
+:10F860009242749C4F899404F2E2E96CEF38377D40
+:10F870009F5E31E8E1293CD2AF2072076D7A8C9708
+:10F880006F13E97E2C23545EC2B3D46702BE423AA2
+:10F890005370BE84C8D500CF15F328FC4B5819E42B
+:10F8A000DB2AAF49EEA272B84E60F0AEDBC3F93B83
+:10F8B000E85C96DD130D8F1B7BCCC37801FFB73D51
+:10F8C000A29E8EB34AF0AF07B935968A9C51E514D3
+:10F8D0001F1E8BFE7E3509E2BCEA9F396F8E05E75D
+:10F8E000BFA8707E3ADB7309AC8F5B60C1F9B43C92
+:10F8F000CBA17C759902A84F84D7507E4CE74BDE94
+:10F9000066FB709DAA2F35AD5DEA59469F675BEB9C
+:10F910003CCB6815921AF0919E24C49FD5558183E3
+:10F92000C85788F8EBEBD3A13FE211A1BCD9CEF4C4
+:10F930003DF2D8ABC057FE42C400E0E18C951CB646
+:10F940009FF136DF4B319C5C37B47F5E8463BD44EE
+:10F950004480E37B462FAE5B5945C4DD94AFD45B56
+:10F96000BC9AFE25FE90AEE746D28CEB5EE8CEC296
+:10F97000FD5C49BAB1DC404226C2C3FE962501BEF9
+:10F980007E4664DC5FAA27116BF248BC02F87B223A
+:10F99000E0B6727B74993C1651CE0238D37204FCE7
+:10F9A0001BF79D377B62C0FDC12179E42FAC991410
+:10F9B00089C76D38DF23EABE3C78CD8D19C047EE8C
+:10F9C000038578B4DA4139F05FFAAF19580E5A68F6
+:10F9D000FF095387CA585FD6CECA2DEE17BD5B28E4
+:10F9E000726C36FA3244BA3975BCF7A081C27561BF
+:10F9F0008EEF76D8EF3A832753407EE2C9F3D2796F
+:10FA00009056B6BF0F4D692E6C8EA17F68F3DFCC88
+:10FA1000058206E0232F32FDC25E1A3646F2FFFB56
+:10FA2000DD8C4F260D8470FFC3CF7104F4DEADDC96
+:10FA3000FD19B08F5B3324AE83AEA9745FDB6CE439
+:10FA4000379417E5D27D6DD8F7C1C131B45C3A77F0
+:10FA500010B689AEDBBBE63740CFD31298DE9CD818
+:10FA6000BCCB40FB4BBBA1604A07C5CFCD6E09E7BD
+:10FA70009330B5FB15E827BC46127B693FE9ED8A58
+:10FA8000FBE62218BFB90DF1B786E0FB946BD7B542
+:10FA9000C177778F26C93C7C47DA38F8EE410741B9
+:10FAA0007D31C5C0DF5003E529AC9CBC8EF3F42248
+:10FAB00052DF8FE3A499C95C2E99BDF71721297AEB
+:10FAC000F662BD1FD79B56D95C02FDA565B3A7CBD7
+:10FAD000E433E4D0F10E1D36FADBE97C0FA9FB7E9E
+:10FAE000CBAE8AB448FE79E8B4453050FDEC50BA4C
+:10FAF000A697066DA097DE52529906449595333726
+:10FB000009F6C795195D7FD6E8499A0A7470982757
+:10FB1000B00FFF69F324811E79A989CD5FBF7FFFF4
+:10FB2000ACEE4BD3171CF147C8A5A645E750DF6FD5
+:10FB3000FA42887A7FFA4E0B01513524BF560E5493
+:10FB4000C3770D64703DE053432091F823F0FBD25E
+:10FB500084D8E36A78DDF4054F9498E39AA2DF7FB6
+:10FB6000318A28A3627D971AFD9EAE23AADCF7F99D
+:10FB7000D03AE03D290F39BCD4DE9B07F29096CFF6
+:10FB8000FA0D8A7132A8E34C8E9D11430ED0B3A9B1
+:10FB9000DC6B867D39238550AE9D25642ED45F6A4B
+:10FBA00030DC5003FB2B841D0BECC3E368F5D03E27
+:10FBB000721FCF2C329120EE4F18E701F053F2095B
+:10FBC000D9D6FF8949027DA0FF15849F862F9170A9
+:10FBD0005422F8466AC760D040E9E3FFB8BFEA2E76
+:10FBE0002AA4A837A0D1F75FBB3D33693D6F88A237
+:10FBF000F7C4D221FA4776F3A08157F9C5F9EEAAE6
+:10FC0000999165F67D44FB9A2ACA1F4A8B587B213D
+:10FC10008B3BDC9E03AFBB999E238433017E4365FF
+:10FC20008BAE6CA3E54911655157EFD2D5A7EBCA4E
+:10FC300063D9F7A7EDC14CB04393B28C3502E57B95
+:10FC4000A733824B385ABEA7C35C5345CB0DA54C96
+:10FC5000EE36F673328A0D157E8D32D31F6D72C863
+:10FC600054570470183C08FCA1BE8F13394A0FB6D4
+:10FC7000C0DE2096A19D14D12EC061BBFAC007D86A
+:10FC80002E6EFF0506A4F3AE82A3ECBBC04728DFAF
+:10FC90003774AEF102837AC3C8F88F407C9E3194EA
+:10FCA000BE1BFB6A88CF36CC27CF64785E453E7991
+:10FCB0008013813E87F014FAB50DD385F6FD9F269B
+:10FCC000F5FF1ED487C45B3E6913E8F7FFABE1A3E1
+:10FCD00069A0DFFD4995079B397F218CBB8DF80A10
+:10FCE000419EFDB421F71503FDEE8831B40378E899
+:10FCF0008FB3C6D508947F1FB187C671545ED76491
+:10FD000015B0724A6807C0F3C9AC42561E171A678D
+:10FD1000A0E56B7AAF46781FC90DED80F2CF7A6708
+:10FD2000B1FA49A1713C6D9FAD7810FEBBC5D87486
+:10FD30003D278BF1136D7EFF36D5E3C982F5D433B1
+:10FD400039B2E4A6F71603FF5D622022A1FC76F724
+:10FD5000E963CFEEA6F0D8DD9A487A193A7A05AA77
+:10FD6000D7A631D4A7FCBE1BF973D84DF9353A811B
+:10FD70000643E03F4A9C6691BADCC3FBA28D9F36E6
+:10FD8000A1792FF49FB6A408E581C5ED790AC6D7FD
+:10FD90009E6F15B2E7535922E3DFBCC183DFDF61F9
+:10FDA000F7C3F7F759D9BA28FDE03EDBD47DB95E39
+:10FDB0005DD7F5594C1F9CE69EF354560AE823AADA
+:10FDC0005EBD31903281CEAB872301B04FDE33125E
+:10FDD000C58AFA4802EA353D3077A8BF3FC3AFD0A5
+:10FDE00071AEE78817F88BC64F7A9C9E8CE408FBAF
+:10FDF000A4A784966DC3F6684F8D2723C105CF5401
+:10FE000003E8EA1A7FEA71B3769A7C4AEB60E3A4CE
+:10FE1000DD57D80BEB491408FA4B962FCAEB6D430C
+:10FE200039BF00E74D3C9E0C8EF6777C559601E07D
+:10FE3000A8EDD767533DB7017CAEE3997DADED9B4F
+:10FE400006DFA7B2989FA08EA77A02C5BBE21C1F4F
+:10FE5000C293EA0DC528A055BDE12940DA08381340
+:10FE600021340DDEFF7F08AFED8807DF115E0DAD99
+:10FE7000948F182E808FA870DCCC058D698C8FA094
+:10FE8000FD0BEF411EAD73FB025911F4B0E48E0679
+:10FE9000D417B57925DEFEC2DC6B09D0E149A4BBDD
+:10FEA00025FF9088F6AA5E9FD3EC244DEFFC451CFD
+:10FEB000BFE3CBEAFA64CDBFAACE23B128F4ECBDF0
+:10FEC000145EC9C42E021F3D620A4D9269FB2306CF
+:10FED000DFA32FC0BC47F322E52123FABB2D9B47AC
+:10FEE000BCB16A7842C28E09AE613CD944F1C40209
+:10FEF000ED6B4C6807F738FD5B6F043CB966ACAC42
+:10FF0000482887919E95D644ACBFD4709480BF3862
+:10FF10003C5D14415FA47885F53D8BF3FC0AB3FB8F
+:10FF2000152BFA4113FCBD8077251400D0DFE209C0
+:10FF3000580F7637FA2B165BD87823F18AD9C7F990
+:10FF400084D5BB55BC5D9585789BDA4198BF41F05F
+:10FF500014D744E80B85D90C6E89A5A1E7DE013BD7
+:10FF6000E51EAB9C4B9829077E0CD29D86FD517CEB
+:10FF70003995C5FC0B8897CB7E6EDFC5F89E5C0675
+:10FF800070DE60EF266BD10F65C4F96FB706519F25
+:10FF900036582427F87B97F064731EF4D761140158
+:10FFA0004FF4F0B667C7F34B866E8DF44B2E312BB2
+:10FFB000E64CA8BFD38AFABDE69F5C92C4E84AF338
+:10FFC0004F027DC6920B9A7FF20615AF46D4777D1D
+:10FFD000995B4BFBFB0F15CFE4812F7297DAD8BAF0
+:10FFE000C1CF510BFFA2E3D6AEB37E00FECC5AC503
+:10FFF00018343B808FCCF18422EC2DB285ADC3F751
+:020000023000CC
+:10000000A6D10F706A15C8E6C7617F14B6FE96E5E3
+:10001000FE5591EBDA6662EB52FEC11EB5AE6D0E77
+:1000200016AFF8EEEBFAF3B4E8759D98A6AE8B58D0
+:1000300052693B55CEDDD06AFF802BA64F58177D05
+:100040009275745D05C3EB9A93CDF8E912958F8D87
+:1000500090BB71F7F17FC87ABB1FF2C45AAF7E9D87
+:100060004F677BAAB353906E8262E9305EFBB6D2D3
+:100070007595C2BEA6F8DB705F197E12E290818F83
+:10008000B52CA7EB82675B1AFAA59698A53EF0CF30
+:10009000928793D47512E4032D5BC7215D52BC6532
+:1000A00074FB108BEBB45899BFA0658D282B22AC44
+:1000B000FFD768CF86297F45BDA4359AAF7F3B1C0B
+:1000C000AC99B5459170B0642E2D8AB1EF8A19F1C3
+:1000D00039DEBEFF071FBE95CB8EEF2F23EBA2FDAF
+:1000E0000DE0371C2AF323CB7AFF05B51FCCD1DFF7
+:1000F0002BF1F8C14F23F1E88851C5A3B556943FC1
+:100100001A1E1DB1B3F5EAF188502D1AE8585BB7F5
+:100110001E8E4B008E31E209149F72018E4754FBF4
+:100120008CE2532EC051A3831B5A193FD0C3ED89D3
+:10013000F87CEDBBAD4387C7DF751D5A7DBC756884
+:10014000FAED166ECD56C0CF2D1944EC403D383433
+:1001500009EC2497C95F08F3DA66A2F44BFBAD55AE
+:10016000C707CD01F0FBB343CCBF79541D573FAF58
+:10017000E75539A4F77F3539C23B410F694A60F230
+:10018000F0CC013BD20DC9092D01FDFBEC7E330102
+:10019000FEDAC885F2E0BB339C67297ED7962881BA
+:1001A0005CD4FC86C79E677E438550FB17FC753E7A
+:1001B000E6F76C52FE753DECC3F96CA119ECCFA6C5
+:1001C000BE683F195D9F03D67BC64006E1FB46DE55
+:1001D000BF0A4CD6CD26A60F6C369000ECDFB05D82
+:1001E0007E340FED840C91805FA7D1F041DECD11FC
+:1001F000767CA35ADF98C9FC4C1057467F390CE532
+:100200001E0997C67B4E7D0D71B1C67D7A7A89A68F
+:10021000A7FAE132779E83FE22EADDC3F484F63842
+:10022000E06115F1E772E01F63E5C4B9837E884F92
+:1002300037A9FED394815035E80BF6D200013EDA9F
+:100240007482D92133FA77BD0A7E33E7DCC171A00D
+:100250009234A97104BDFD33BDFF7E1EFC439AFD9F
+:1002600012E18F2A5C10E5576CC776E0DF82F1421D
+:10027000F00AFCD302D37337AB7A2ED587916F2E59
+:10028000EFCE477D18F455D03B34FF18E821A08FFE
+:100290002ECCA91072E83ABFCCA9380FFC1BC6437C
+:1002A000BB1F9C2ED3BF817FA9F0D1BE033FD9379E
+:1002B000FBF3993E3543E7C7BFF98D14C4F3FD71D5
+:1002C000F4D45139437EFC34F0E3DFCC496980E754
+:1002D0001FF23EF4D7AF200AFA8157817F1CF960E4
+:1002E00010FDCB373513B90BE3E1BEF5506E58491D
+:1002F000C42EF02F57F9B01EFCCB574E67F12629BC
+:10030000027F219E1359267B68398A4F0FA2BFBAFC
+:1003100091F6B04D063F42F4F74DC45F29005EF4FC
+:100320009D3747F5D3C3E074838A2F5BADCC4F3D37
+:1003300063DD2E9E44F81992A678DC77013DBC61FE
+:10034000443FE9FF56F75783C7D3D915D61C0A8F08
+:1003500004F0FBC077779951CE1E379095802FF728
+:1003600039C90D0BC09F7527F1E418012FC4CC4883
+:100370007F97F6ECDA6F5D0978362B87F111EDFD8A
+:10038000996C2396D1EF8CFA6922C6D1295B2A0693
+:100390003C2CCBD2F462520CFEEE0F54FED4B8D0FB
+:1003A000E683FE4206C6CFE6E530BB7B5E8E09FBE8
+:1003B000D3CA43FE2215CFE838D85FC2541215C7FE
+:1003C000BB2A87C901CD5F4BD4F8CAE655094C8FCB
+:1003D0001EC27703F2B3C422AFC987FCA402F95945
+:1003E000F8CF3609E032F754FD2A58C7A78B120818
+:1003F000E41D2C53E3448D394EEC578B0BC5D0BF15
+:10040000AE0FBA86E58D869F9A9CD96F67EBBED8F2
+:10041000F8BEFE39B7AB10F9B7368F193ABD241EB6
+:100420005DDC364C1751F12D0AD744E0B3FB0DCCFF
+:10043000EEDA4F110BFD560135FE48ED649003FBDB
+:10044000F7E5A39EBD54F5A7523989F65598CA0B16
+:10045000B6DFBEADCBE1BB402EC6653F30FA9F7C18
+:100460001CE4ED01664768FBB17FFF183FD0EF8CBD
+:10047000535F6502FCF79F786A0CC4BBF7ABF1C50C
+:100480007A53300FED7D13D353EB1DC13C80DF4B0E
+:100490002ADED427D0327D9F95E2EB063EA4E50705
+:1004A000403B27AE477280BFE1986A471EA576257C
+:1004B000CC8B52CB20C43DE97E674039BC298DE905
+:1004C0007B745E8017C70E4CC2F56D36323C565EAB
+:1004D000E4D03F71D418FEB0957E7F34632A69134F
+:1004E00041DE7DF1F841E87F274FCC22E45F7C7E3E
+:1004F000AE8F7E7F96DAB9E037AB3378AB33805F6F
+:100500003CCFEC75FD3E80FC8B8CC79D21E14CF40B
+:10051000EBADCC0A00FE9CE92FC4BC22E21289425A
+:10052000CB4D2F32FB461F273E6E8CC67F7DBFB062
+:100530002EF0AF35C1BF41BE47B68FD1DFB795CFE3
+:100540001843796B293CAA245F302785B163D8CF43
+:10055000A69733901F1FBBF773DC4FD2CDE29FC726
+:100560008D9E25303F6755D0541B818FEFA8FCA38B
+:10057000CECCE435E5BFA6487EA3D59755909871BB
+:10058000FA3FA87CC13EC8E4DEC87A86E7B7924746
+:1005900079E017EFE448D8DF7835DFE056F2D92B61
+:1005A00066D04F022598CF307E5D10F9009D2FE276
+:1005B000E7F1AD49C81FC93D0C5F6F7CD88CFCE3E7
+:1005C000462A3F98BDCDF2ABC83D2C8FE2C3BBDCC1
+:1005D00088CF65EDC132A4072791412F79A1F3039C
+:1005E00085A7F54BF77025903FB6B4D38D76CA4DED
+:1005F000FBDCB8BF3354BE5E67F660BE187984C5B5
+:10060000D396FD62158ED390489C3CEA7F7E13C83A
+:10061000E5957B3802743523C0F87FBD107C05F466
+:10062000487DFE03F147C789411E91083D13E40F41
+:10063000D1D905D1FBAE5C94FCD5CB1B3E37B6FCC3
+:10064000A5F69E90CBF695C989BD1CE31BAAFC6D4F
+:1006500000F90BBA9A2AF734B9B942959B1FF24CAC
+:100660006EDF68BE1F9F19B96E1CE72688EB621CFF
+:10067000336C02FD241E5E64E432BCD2F062746E00
+:10068000345ED49F081E34A39D293F0FF1EAFA750A
+:100690002468A776DA8D4233CA87D1221131AFAEF2
+:1006A000D287F34A6BA1FA39DDE71B21063BE5E26D
+:1006B000F582117A804EFE6BF3D6F044AFFFCD5831
+:1006C000E7E7219E74328FE07BED29924009CCB799
+:1006D000C6C2F4EF1A8B2DC883BD59653C1D696FE6
+:1006E000FC58F094E5A25C1DEBFC7022B20802FD00
+:1006F0004E737B664D9836AC57269686D7DF4BFBFC
+:1007000033926203F0496D7C8B7BF692220ABF26FE
+:100710006110ED15924EC4DD74BC2B8B249C4722D6
+:10072000DD875D14AE464141F8192DA2B3CD09FB1A
+:100730003F887199700A413F9DB65F3BEC44817CD4
+:10074000C52B8B187D5F5924E293B6C738AEB180B4
+:10075000B6A7FD57ECB7225D9E7BD1EE07F94CE5BD
+:10076000CE7827AD4FFD13B55368F9CC7E3BEA290F
+:10077000675479E1D2FCB5643DEEF722156F14524F
+:100780003106EC11C25D3186CE9D687A7283335E8C
+:100790001C53AD770F2E64F86B467DE19C33741BC0
+:1007A00094E97C30B7C69BCBD6DFB4AFB2E40EE0A1
+:1007B000DF5E9BCCA0EE2B01FDC7CCDFB2D0428127
+:1007C0005DCDAF0BAF05BC1F6713CDB449D5F8F7AE
+:1007D000FFB09896FFBCCF48CC803FBBAF4A0A42DF
+:1007E00033C193EE9D34723EABFCC6A3A1083A5EC2
+:1007F000BD27BADC10882E3711E1682882FFB7BE0A
+:10080000BFEAADD722F06D6DAEDD05784024229FA2
+:10081000A7F474FCCE3E720C6421FF9324E08FCBCE
+:1008200028F9C7D22B3EBF73E55BAFD1EFACA68AE8
+:10083000B65C940B9209E8AB96EA0DB1ECD0C9B95D
+:100840004C4F339B9B4FECA2F031BF6496DB68ABFF
+:1008500079B9BE2EC0C74643F820ECAB79FCE962FB
+:10086000F067578CFF0AF302CEFD2391014EE7ACEF
+:10087000B3119FCE6DB54A60A7F664DA981FF6658E
+:10088000CECF31BB65FEB454C8FBC0B5503E165E3A
+:10089000BF15F8F474B3D82EE2722D06DC6F6ABD72
+:1008A000D1678F49590F7ED51E6A40B6C960E70DE2
+:1008B0003A80180655FED0C43F63B2D07FBA3B3DA4
+:1008C000856DF4BBD5DE0402F978C2D78217F06CCF
+:1008D00003741561F73CAEF2BF46F1EDF5307ED3FF
+:1008E00057B7CC4D310CFBF9CD46E6E737F6CD0EC8
+:1008F0008EA14D57B456A27D47F92DE38B07185FA3
+:100900005CB17636BEE716CCC5F57E48D70B70795C
+:1009100075AB19D7FBE1381BDADB1FEEE0B0BC4248
+:1009200034613E1FD54F46CD76C17BA3682623E1B7
+:10093000D1B465C3FAADB4FE77193CE128FE7FB4AB
+:10094000FDB7188FF888B0F1957D3CEA3D1F89E12D
+:10095000B220C0536A7644DA932B76F05EE0972B90
+:1009600076DCFABBE900B705D795023C66396F49DA
+:10097000956CC3F59ABE2724973F0E7439EBEBCAEA
+:10098000C159A077EDA07443E72D18880FEC8FD7DD
+:1009900076FC10F5ED1535094E589FB47D7735C8B6
+:1009A000B78F6A461B705DCF72440478385B53E1A1
+:1009B000FD0A4EF0C6C2AB65B92C9E307BBC4D061D
+:1009C0007FC38ADFF3882F94CE16421CA161871162
+:1009D000F5F9D716BCF787C5AE613AE3166C993FB7
+:1009E00003BE7FC288DF0FE953DB3F7E1FFC02F0AE
+:1009F00047253BC821849F9EEECCE3D7E5C1BCF4DC
+:100A0000F4B7A2BD398FC5F72F8E0EC9764687275A
+:100A1000299D9C37FC4D74F829E3EB174687646CDD
+:100A20007294FC1EC9F714FC4E8B8F5A64E2D96D88
+:100A3000C37C180F47F9F5983C01E13E268FD96D2C
+:100A4000C29737EF7993C26947AE4FC8A3EFC71378
+:100A50004F09C867292C56802BD6A6EA8D643BCB5C
+:100A6000F306FB02F67F730A79BC2BC23F93A6F60E
+:100A700047F9821DFA39F3C7AF0EC27E35669E2E46
+:100A800006BDBAE98BFFC4BC0A5B3FCBC7B1C961E5
+:100A9000CC3732BABC888F1ADF6F92991CD2AFABB9
+:100AA0003D8FD9AD4DAE30F6F3423EA34F2D1EB96A
+:100AB000AD3501E342DB5C7E2BF3B3507D8FF63F17
+:100AC000AF94473E6329ED2020C748398FF19C59E8
+:100AD0005FBD4520FEF5BB999532E895B6D25785A6
+:100AE00051B0CE72A35AFFAB8D59B4FEAD9973D0FD
+:100AF0003EBA399D9740AF9A579AADA0FCF4B0FC2E
+:100B0000DB595F25211DCE5F351FF54A6DBE5E6244
+:100B1000916C144F1650628DCC539E3FD32AD9222C
+:100B2000F0EBD36E6E2ED3ABA5A4AB2731BF50A094
+:100B300088C9F34838DC9C6EC2F1BFCC997D09C0EE
+:100B400077D6656C1F4E3E6BF6B7D3714F5A63DB99
+:100B500091D5790C6FB284CB912FDDF2AC19E3F310
+:100B6000A7B8D8DFDFB491C7BCA2551B39E2A7E311
+:100B70009D7CF2854CE0EB7FDEFD42666DC47CE23D
+:100B8000B5AFCB63FAC0487B3BB82CD2DE9E676220
+:100B9000710132C51CE5DF9DE750F3EC2F30DEF12B
+:100BA000A3B87EFE37C6C27CDF1CF2F3BF3E3632EE
+:100BB000DE3114B792999F5F1FAFCA29FF1775BE28
+:100BC0002CAFB95550E72B9B59DC62398B8BB71C86
+:100BD00018857837CF14FE39C6B35EE64535AEE1E9
+:100BE000B160FB74561F675DC4E3C97195A1BF096D
+:100BF000E7C3F57141BBE33BAC8FB038867E7DB572
+:100C0000FD7CCCB8DC97F92C0F20B1288C76D5D19F
+:100C1000D71F85C8FB10BE5BFBDD86C87CF8217D35
+:100C200056C5EFAB00BFE9FAAC1B59391E5EC7E3EE
+:100C300057A9798C8E35FC3EBA313B09F0ED2E4B2D
+:100C400063E820859F874F22D6D1B4ACC6FF95F7C5
+:100C5000593E2A1F61E7001DEC78DF8E764E87B182
+:100C6000F91138BFA3B40964377DEF4A68F4B7D1EE
+:100C7000B264B463DED4ED09F377815D17A20A2E66
+:100C800047CB9F271CD9057A02B12411231D47A900
+:100C900050DB9B2C6207D52F1E4A74207F695D466E
+:100CA000507EA79120C75180ECCF63F9AA29AB9F52
+:100CB000E7308F98523CE87D72766C7DF4572A5D60
+:100CC000BC0B0934F42957C6FE6E7F9EE617137CD1
+:100CD000A1083B6F03274BC877E85FDB74D0EF07B1
+:100CE00017235FA67AFC5B541E8CE17F8DFED963CF
+:100CF00077FA1E8975DE6148EE56C6B6D35F55E7B2
+:100D000057D0CDF98D0EA45FC3AE28FA55E378F61F
+:100D100054994A1888DFB2385D0ED1F2DEB780DF11
+:100D20007E74399BA3C31322A05FA4775F4E7CA37C
+:100D3000809E66A4817C6B591EED4F4BAFDD988180
+:100D40007EBDDADBE683FCDE62B46DE492E019ED91
+:100D50008FDBA2F3C77D1B5F488F4B37D3D3C1BF57
+:100D6000B16538FE87F8D3B154F4F31CAE8244C6A3
+:100D7000B5533BA4833ED083665BE45E7924FD904B
+:100D800072391DFD9CF9EABEA9F4DCA4A226D7CFD6
+:100D9000A15D3A921FAAF06C188BF0B476DF8E76C4
+:100DA000536209F36327AEAAF501FF49A4FC07ECDF
+:100DB0003893A999C3FD9FC1ECB6168E955B668BDF
+:100DC000A242BF37399A6763FD152CCFBAC5EAF343
+:100DD00045C6D32E35DC3C3B32BF5624B43DF0E152
+:100DE000456CBC7996752CBFD74775A48C61385675
+:100DF000A870CC294F60F9E6B75AD0BFB5DDDA8DBF
+:100E0000F33548CCCEAEEDB222BF1BC31760DC6415
+:100E1000C0C8F043B15B905EE58177313F6CCC2573
+:100E2000E912EF8EC09F5B58BD861744975760321A
+:100E30004907C17F472722435E4A0B271DACC07577
+:100E40008961458675AB7CB93881C9116A6EA63354
+:100E5000B8B2B8986EBF28DE30BFFA241BF31B115E
+:100E60009F847A976EBD23F1E6C502E0B70343780D
+:100E7000D357108BDFDEE7940EF646E20B91D68354
+:100E80005FF56E030977C5C21F39DACED7E7C9E926
+:100E9000EDFDC6D64AAF6A7F2816DC4F13DA1F8DE8
+:100EA0006B677B99FD51D006FEA7A6755452D136CB
+:100EB00095FD9C05FA6B5AE440FBBBA96F2FC6CF8A
+:100EC0001BE71219A651ABFA87B5751E35B2381E4D
+:100ED00095590188DFF738433BE17C5DCF2A2D8FA0
+:100EE00087E5B5287D9C9AC7A3E57D858F80FFB3F4
+:100EF0008793D00F3A744E8FEE3FCBDFB9B83C30BA
+:100F00007B91D70D96F8F4DCDE7F4B98763179B47F
+:100F10001FF5409E6CDC3C5A25780DD45B602FD4C5
+:100F20007A4003AA2F6B658F5582FC9DE17A81DAA6
+:100F30009D963E4E1DAFFA9A393978BE46EDAFFF09
+:100F4000013847779F95448D17393F41D73F989691
+:100F50003649FB7EFB02E8EFC1296A59F9FA17907E
+:100F6000377C9F31BA3F4419B53D14B4F1D29E7E0F
+:100F7000ACE79E99C37A3BD5E3FF317FDAB0FEBE82
+:100F8000E1BD79DD93E95889E267789E49D3C39B37
+:100F90005C2CAF568FE71B553ED6600955836ABD62
+:100FA00061D11A2FF43B94F7D6BFD40376B096F7ED
+:100FB000D6B4CE8BE79AA8DE7F4F3EE4D1FEF1F4A3
+:100FC00087AF10B0334FA23FA0E90B81F99DA9FD77
+:100FD000C0517CB1F4DF8FF843F618FDE0DAE97117
+:100FE0002A04F0B1E700370DF08B90E6CC6B28ECCB
+:100FF0008FE77B7A601D67E2C4C79FCD67767B531E
+:1010000041C5D63C80F5631C017DBCABE053B42BDD
+:101010001A5F9C332DF21CDEAABE07D979AE3DC6FD
+:1010200098EB7E369FC7F535BEF81CC64F4EFA3991
+:10103000A4B995827F13D89B2B571AC0B222A5FE64
+:10104000A598274B169908CCFF01D50E69DA739540
+:1010500002E7029BE87F9404C836EF8DA86F6F5BB0
+:1010600064B1411CBBA9A0760DF23B31C103A69C23
+:101070007E9E43F96F6B13308FA6ABCF3817ECA46D
+:10108000324A17FF6403BE7AD8BD0BF8E7A8297C63
+:1010900087087986B1F5EF670A991CEFE4BCCA8F1F
+:1010A0004B312E4222F399C7F731FBEBB57C5354F9
+:1010B0005CF0B57C6617CE54062B01D75E164289CC
+:1010C000600F3711CF27E0F7225E9B847121124019
+:1010D0007FA0EB4E09ED268B2B74F764A89F29A007
+:1010E000DDA4F911CEBC9886FA584981EF30E0456D
+:1010F000191F7AE0C700B7BB0535BEC4F84AE655EC
+:10110000B629605F195D4C9FB1527D06CE7B5CB6FF
+:10111000E9F8BF56026F7579518F2054C8C1B9F1F3
+:101120004A0BC7E22B3ABD99887215B4AF56FDD26F
+:10113000B974B73EB4206A769E1F05FE0C9702F084
+:101140007E9D2E6014AD9F433C9DB02F5FAAFBB7E0
+:10115000D9C4F4F5CD060BEAEB9A3E9CE81A443B61
+:10116000B121C0E1380D05BFC6F302ABD5BCF4A177
+:10117000FC702184F9F2A7F313D5F86727C34F3227
+:1011800088FE30F20CDB07AA79621EBD06772DAF10
+:101190005CEBCFA4C64B1B547F2E0518D67F9EAFA9
+:1011A000C557DBA3E3ACEAB84490CA22FD8E9B6B23
+:1011B0000819C479490E986F57AA9714D0EF8F5227
+:1011C0003C063C3BBA31D10FE7B63673831E887BB1
+:1011D00028252C9EA1C7A794024E3D1F14AEC6BC65
+:1011E000AB17E39C0FEA8B3E1F44F9C39ADFD07123
+:1011F0004A4BDF9301BFEF73AAED2F27984FAE3F05
+:101200001F34BA40C271FEDBCE07C99CA7973E735C
+:101210000A9CECFC8F763E486670D7F231F4E78288
+:10122000CE64040596C71FDAB91BE59E19EDBB977E
+:101230003E3ED809FEE2B3252619CE43A45EF77AD6
+:1012400027E6C5704233C415F5727D97BBB218E02E
+:10125000FFE035CFCB98F7AB93EBF1EC798C794687
+:10126000F87B3CEA7E7C5FF6BCB5FB7307E0CD29DA
+:101270002EFC73C847550EF031F3516F28E0E2E4BD
+:101280006D791645EA999D5ADE9633212A8FB1333E
+:101290004EDE563CFD5D889BAF7539EA619D43F992
+:1012A0005A73353D2C3A1F554CF846BB571B7F6E81
+:1012B000C81D155FBFE582D7A9DA2371D617CFFE07
+:1012C000BAD87C013D1C3AE3C8C37505F1F2053C70
+:1012D00022C4D73B21BE4E9F024714F483ED1DCAA2
+:1012E0001708A2DFF7B97CF45F99E3E60BB03C3254
+:1012F000E140BE04DF6D307A3D6097287B8D2A3F48
+:10130000F73F09FE8FCE0319E82F2305A162E07392
+:1013100082B33A1DF4A34E153FEB2F3C5F6073413F
+:101320008C7C815DFE293FCF6276F06022D5AF765E
+:1013300011266F947EE69FA4F346FF5CF8DE71A849
+:1013400077720B2CB88E632F9B7BCDA84FCB18FFE9
+:10135000AF4DE74590133D35651F821C3A46155049
+:10136000A0E3BA9BD6A11D1A6F7FEA3646C763B5C4
+:10137000F717BA4FCFA9FB7414EC7414980AFA7DCE
+:10138000576EE45EC1BC5B5D3CF805E021C8EFA38D
+:10139000E3FBE7ACB331AE7ADB2F6A309EAA9DA3A4
+:1013A000D5CECF12356E226D1490DF4B7B38BFE463
+:1013B000666462401B5D34E07D1E544C6D03D1A613
+:1013C00050AAB984BEE60C1CE89B52272DA7D17504
+:1013D0006D129474FADDAE7713D18FBAC125A9E7E7
+:1013E00021981DA5DCC3A11E47FB453B58E9A47805
+:1013F00043FB79A780F9F7CF16303D83A2881FE71A
+:10140000A33E3BD57C086DBC366208C2D3C0B1E7B1
+:101410000651981B4B4FD3FAEB34365B206E121EED
+:1014200067C0B8E439936711C6F592F308D87D9D7B
+:10143000F6E68D73593DF2D073D6B017EB7F2030AE
+:10144000859F48C930DF37D5FDD0EFEBF2EEE8B22B
+:101450003E6EAFBF17A08EF8F233B2479E937F5314
+:10146000956BE7BADCEABEC818F7EE344AFFE60629
+:1014700039B7494079DA3696C1CD308E3DB39C55A7
+:101480008B509E3AA99E89F365F3CFFA818B03FABC
+:10149000EB7432FCFAAEF3D6CFF7F3823CA63F8270
+:1014A000F24FC7EBDCC4F919BCD8BC2FD4EF9C5267
+:1014B000F8FDFA9D8F71F2E341C0339BFF61F0DFCD
+:1014C000D5B59945E067A73895FE37F1C8CFB6ADD9
+:1014D0004CC6F2D18DB9E8CF19A2DB13EBD7C07D92
+:1014E00007179A7F955FC8F0E2773A7F5A6D397790
+:1014F00018FAD1C31D104AD0E40F6D5A79555135F1
+:10150000F0C7460391D2401FD8A8CBF3D0D1739532
+:10151000E49B5608FAA269F020E353A13C01F56868
+:10152000AB0C707BD0706CEF6F015FF65A316FB00F
+:10153000715DF871F03BA64ABE998514CEA7D7BE5F
+:1015400057CD49D81DDA5B670FE4E3FD19B59DBAA5
+:101550007B09EE89CE2F211B9359FE464FF47B3831
+:101560003F1FD56E44DE09D33F379B7C856027CC77
+:10157000BA8CE5EB7DBCCA40002F3EB632FC51EE82
+:10158000B5AB7246CE8BD44F1717EAF4987BAD8873
+:101590001F75EA7925FD7E34007ED07DAB57F1E3DF
+:1015A000E3E72EC903FC38BDF7923CC08FCDC66E71
+:1015B0000FDE2390E3FB29C0F1F81CEF4103E34B5E
+:1015C000791783B7F5FA79FD9DF4ABBB0BE3C54DF5
+:1015D000A49F44C64D068CCCDFA558A3CFFB0C5C62
+:1015E000A47F34BE9FAB3027DACF55901353BFB2E0
+:1015F00058BF51BFBAF875103CEFA5C55306ECE1D2
+:101600009F3F1E01AF162BCB2B69291445A504D68D
+:10161000579B8DE7C7FE68917BB9EF759D51FEBC66
+:1016200097BFCA5EDF0DF3F030FFE3CB8274F05258
+:101630003AEECB84F91FF5EBFE7D3ECB83D1EC6710
+:10164000CD9ED38FBF57DDEF8142CF4B601FCFFAC6
+:10165000EA3CFA034EC03D39745C8BFF9FD02E23C9
+:10166000FD9C88E7CF2416CF6C7C71F9A3E03F5D29
+:10167000E557E390FB38B4BB573DF609D69FE9AB7D
+:10168000C37A5B3F17847866D35803CA6D2D8F41A8
+:10169000F3E334F5CF2680A79A1F87CEE30598475A
+:1016A000A22B6C42BE0576226DD728B0386DA38B75
+:1016B000C80AB0DABE68FF8796E7B4CD6B427ADF1E
+:1016C000D6CFF9C1AE4E35F9DC63119E63C50F1359
+:1016D00087F9C65B859ECF805F6979684F677B0E0F
+:1016E00003BDBA4C2413F3DDD5FDF00DC577D879D1
+:1016F00089BFBCCDCE4B84E2F0EBF70BB5F3120BF8
+:10170000517FFE0BF126C5CE23F7B33CF2A1BC35C9
+:10171000962F5E3F8FDAC84E56867B5F1AE0DE1743
+:1017200099C9CFA04E7E4696214F2C18C137EB8524
+:1017300041CC47D7EE7981BCB1C8EF1BE1BC45363F
+:10174000CB1F8BEA47E5A769FCCD18C789113FFD80
+:1017500049A4FD7148B3B34AB4F3316113F8695A2F
+:10176000DA5C6188071CB2ABE776D5BCD8166BF89B
+:1017700018F8315A9E4CC3732043FAFDB366D50F57
+:10178000CEF0BE9EFD9334AD3C8AF67A139CCFE733
+:1017900086E9695E5CBBEC8D1C88AB1C1AB2CB5E23
+:1017A000CF8173341A9FAD9719BFA8EFE3D879AAF8
+:1017B00040F4799A3113BE5FBEAB7D17AFFDF409DB
+:1017C000F1F8EDB7C199F1DB43F1CE21A97C528349
+:1017D000A39E1F5D2CFC86E492063F4AD7C86F7516
+:1017E000F0D3FBC334BF16E914D1EF45759200E482
+:1017F000656A7EAD0B9587F3BFE77DB95079D83028
+:10180000219E1DFEDDF6279E9CB8D87D19210F6113
+:101810007F8AE3CBC39CF27F51E7ADCF2750E7AD82
+:10182000CB2738640CCF67F75150F8B847E613C49C
+:10183000C5BF6FC927F81BD6A9CB27F8E675EAF311
+:10184000091E39F09003426E70EE0CFC0E03BB8D46
+:101850001847AFE66D1E96E7C5B3BC50E2C1FB3139
+:101860009B2C56F42FE8F3E028A75ADF0CFA6539D1
+:10187000D5FBE15CCE8E0E94CB0D193CFA1C21EF0A
+:101880004F9462E4590A3549416964BE17E4B1E3F3
+:10189000F9FE8BCCF7DA336128EFD2FD37E65D062F
+:1018A000265C40BE57712EA3BB576D9F8D8ABCBF6F
+:1018B000B2A2881AEA45F1F3ED5F56E93551CDD36E
+:1018C000B5080A89F447C56B777002B3775E358532
+:1018D000DF0D805E45BB81F865BA895AD3A5C3E7A1
+:1018E000D68FE77B5F87F9537D04F7F7CC8BEFA0AA
+:1018F000DFFE910C2242FEFB234605F75949218861
+:10190000D75A5E8236CE5AD58F7DA1FCE7C8DF5903
+:101910002EFCD7FF74BE33227F89D1E3DFC06F90E6
+:10192000FE86F88991C575B47B2BBE55CE7DDF7CD4
+:10193000469777116F5D5FE613C487F113BD1913E6
+:10194000918E3CE867BC58F997584AF52180C73E0C
+:10195000B304A46651EFA720F764687E5176DFDFF9
+:101960007DE350EFFCD8CAE6ABDDBBA1AD67CAC4CE
+:10197000EFD78E2DCEF1964EA4F33E3EDB83E77774
+:1019800037D899DE167E92E5AFEBEF91A074C3EEE7
+:10199000D550EFE1D59F87AFD6CFEFEF24BF974F5C
+:1019A000FC1F4E471729BF2F7E1DD1F6EC213BCBE4
+:1019B0000F1CB667FFDBD67551F25ACB172EAB184A
+:1019C00054FDFD1C017FBF364ED3203B6FB351DD6C
+:1019D0004FEDFDEF54FFDEA1899E4D4087A5A5C1C7
+:1019E0009D70EEA49138F01EF1C6C0ED7BDE74B19F
+:1019F00073B4582E607147E2B5E139EB1DB9BE07EB
+:101A000018FD86D6037D8E779132881B74152C20A5
+:101A10007536CC277808E860FCBAD0CE374B319FBA
+:101A2000AA19E855CB272E3BFFD9FAB9A5385FF4A0
+:101A3000FFBACCD1F76FF44D64F6A0F67C4EA50347
+:101A4000BAED19309FD32BD9B9D2269747043FB2AC
+:101A500016BF4E940631FEDFB88F194565602B42E4
+:101A6000FD1D6391BE1AF7CD2E81B82609584BF0A3
+:101A7000FEDD3FB17BAF4FAF1D8DFEC69202DF2F63
+:101A8000615DF652FFE560478FA7E340FCF3F4DEAB
+:101A9000CB4B7C31F8661A9FAC407C388D27810790
+:101AA000C461BE45EDE7C5E82F5E1F463FD6CE892F
+:101AB000128B27BB985C6FEAAF21CB6DC3659B2B64
+:101AC000FA1CD540E19C9D308F9D13595C5FCBE79C
+:101AD0007453350CFC867A7C72ABF99C356ABE3245
+:101AE000512CC379CA59DF9ECFA9CD4F2B6BF99CDE
+:101AF000895F30FB3D4B3461FE877D23E3AB641D82
+:101B0000C1B8C1CCF060651285534E4F7026C02914
+:101B100009C08EF7B186EE9E4CDFBB460933C11F6C
+:101B2000B2B375CA00E8BFC2A6C11FC09648DD6245
+:101B300005B81877E47ADF033C21427301F0A58AE7
+:101B4000DF1BD979A34D89A857F664D6E379A3336F
+:101B5000EF9963DE27A03D15D29E0E7187AC8DFFF5
+:101B60008EF17DFB3E2EE6B9B44B8B6CEA79A4F680
+:101B7000748863D8370E2AE5B4FFAC7B39A29AD1BA
+:101B8000195C3AF8870503C8D7BA3E764F5D5DB752
+:101B9000B3C282F286F96BC84C17CA1161D395069D
+:101BA000E013421BD562E93AA714B1F8746E8F684E
+:101BB0000039F5CF5FF331E348E755BC6EB0844C94
+:101BC00000AE0673F860BA7B385F473BAFA2F97B83
+:101BD00086E4CFBEA5E8EFB9F8FCECF0F598FFF786
+:101BE000752AC657E639983D4205917A4F4B74FBEA
+:101BF00011F7B4A87A8B6617EBE9409FEF9C533E30
+:101C00001AE982F2D1C036318AEFC5CC7B6E1598C5
+:101C1000DE4DD7616A8179CC4E97C13F77A179E6D5
+:101C20007A7B7A48CF51F5126DDE7F6B5EB6565FD8
+:101C30000FF9D831FC1F9A5ED3A99D67FE9ADDA3E8
+:101C4000355EB5278E76FD5731BBAF50CBFFF0E345
+:101C5000533052FE89F813BA4C013CD8E73434169D
+:101C6000617CA911FBD9C4EEDB1FBF31BBBDBC1425
+:101C70009E22E128BC8FEE5F3D1EE3B7942E726377
+:101C8000D0C5918946D6FFA644C463E17E82D98C33
+:101C9000823315F1587890E1EBBB13197E69F9672F
+:101CA0005A1CF0D0449F17CE1B0EDDAFD19AC0EE68
+:101CB000D750F3B8EDADEF3D0BF756EC54E3C0034E
+:101CC0002F4F5C80F1B94D0207F6E139E7D2F1E020
+:101CD000BFBBBE88E1B95D1824A22D925E07F01C3F
+:101CE00060D601767E4950F34D854DAE5D809F16DE
+:101CF000B70FCF3BFEA033C8633E9378FC81B91287
+:101D0000D81D6113E49F9D6C13C2ED4ED49FA2FCBD
+:101D1000647ABF171102985FD354F4F7B543EE2DE0
+:101D20008AEB9FFA4EE728C8B7F8A7BE2B5EC7F329
+:101D30004F5DFC3AF4E727987D425E66794A31D6DA
+:101D400015E5BFFCDED7A5F92DF5796723E898F9ED
+:101D50003F347B488B3F108F1295173E601483A051
+:101D6000F7409EED7332E8D54F5823F3C29E57F1EA
+:101D70007EE8FE3EE2B7C2B9FB8FE1DC30CA3B79B8
+:101D800023C4416FE7EDDD60DF7540BE3EE897009C
+:101D90005F2EE2DCC2FB76CC7B6815D8B906A2B018
+:101DA00073112DCB9B9F80F62D6D6922C05FA968B2
+:101DB000FE159E7B30106F077D7EAEFEFE84361FC3
+:101DC0002D8F3F9EFC1C91C7FF2DE71032E29C43F4
+:101DD000785BC5FB826504CF21908D9E5D30AF9E00
+:101DE000368140BC37792E2B8F172CF87B2856C8AC
+:101DF000871E85E746316F394CE109F9D756C88708
+:101E00001E05E744D87D85DC82B9887FC9143EA0D1
+:101E1000177418D9FD84CA3536C4A7CAB92C7E995F
+:101E2000EC3521FF394B64CC9F57E01E3317E05946
+:101E30003BE267D89E8AF1D7E41CA6475ABD2683A9
+:101E4000C58DF9CE88AF614ECB77667CAF67A9842C
+:101E500079E843F7152E27B83F9B72AB33E0770044
+:101E6000465F65E2205EA3C9990A153F7A76A9ED1F
+:101E70001B587BB8CF10E6475A58FBA1FB0C7FCA12
+:101E8000EA5B8510DE07447518F53E3D56DFB23833
+:101E900015E98757CFAB92EBD47C7B8EDD1FD5B293
+:101EA0007834AB77303E486E4A50E5B9DAFED664F6
+:101EB000BF1A2F6079F3AB0CEA3D00DD24329EABF4
+:101EC000D159F2B79CBBF8C570FE3CD273C7E5226E
+:101ED000E6076AF73156D84CEC3C96259AAE9E2917
+:101EE0004A66785F2E5B60DC656E4FFAA498FCD181
+:101EF000BF3492AF8CD6F8CA4D269D5D96C6E0EAF7
+:101F000008EF64E7B6CC176597C58F2B3E99111D76
+:101F100057DC93111957D4F6B762A509F94A8F53C4
+:101F20007A0DF28FB651D0C2FD76FA756F1BBAA743
+:101F3000DA6F05BD546F0F1E8A9367B46812F3E71A
+:101F4000C971FC108B26C5932F71E2B425E6FFA65C
+:101F50007833E3BF0371CEE90DC14BD39B2CFAB8A4
+:101F60008772517E9F01CBCF900F7A3A0462BD8C6D
+:101F70009675E7CA281F44BEA8B49BC50E17F0D1BA
+:101F80009F215F6CA596AB39822F5273F412E0C784
+:101F9000037716E0EFCBBC76A78CCFB3562EC04F9D
+:101FA00086677809684C4B8A0F2C847B9BCFDAC3F9
+:101FB0009970CFF3BAC96F5C8BE594F01128DF51AB
+:101FC0004C16613937BC13EE7DBEBFB8FD5AB8D789
+:101FD000F92CD0D868426E7DF6B66B9522FC3D8414
+:101FE000F583A0DF97EAF2F175F7D0C2B951584FE7
+:101FF0009ACD8471DF34F5BC2EA952FD4390E905DA
+:1020000074975182797A3622ED1B84FAB14CEED264
+:10201000FA36B8E7B423D7CDE2D084F1013256CDF9
+:10202000E3202105FC511D6E27B61FD2EFF699D58E
+:102030003C3036FEE1E7D8FD3CDA396442C47160D9
+:1020400037DA241255D6EE752682380EEE61ED5041
+:10205000F1402BF7A7F91E9A1461571E9E737B114E
+:10206000ACF3E3E7EFC8017DEA87EAEF32E9F1EA92
+:10207000C6C90CBFDB13FFBA04F8F8BBBC4306FFAC
+:10208000414B9A6F17F4B7DCD536CD49F1A74A9C7E
+:102090008DBFFF324359CC015F715ECDE6E7ACF2F4
+:1020A00072CB8B867F1726C527A09F9EF87A78D0A3
+:1020B000B7538E7B45804FBD259C29D07EFEE4F230
+:1020C0003D03FD9E5BFAC16D989737FAF011B81F7A
+:1020D000F2B0B1BBD201F8E456EF03A63B06E763CA
+:1020E0000E8E19DFABFEBE0D3B2793CBA971D860D6
+:1020F00015C8852B08C35B2843FD95EA7D67D5226B
+:10210000BB3FB3BAD48DBF57369F8405C087EA77EB
+:10211000BD0E02F471B5AF34D6FD13DA93A41BA53E
+:1021200048FAB95C8A28D3FFAE2C882EFF488E2E41
+:10213000FFB8FCEBFCA8B2E07963520AC837267FEF
+:1021400094E94CFE8824D00EF2F1A966710AC6D536
+:102150005D9C02E5892F8CC6BC2492CEF2192638EC
+:10216000B2FC0C0ED9DB615D612AE77B5DF0BB47F9
+:10217000EC1EABD4774DBBE09E042249DB810E9F61
+:10218000371660DE66AAADF69FDA509FB1935CE425
+:1021900053D276C46BBB4582DF6F78C5CEF2113A5D
+:1021A000EE3760BC8973580C1EFA1DDF2B30F96FB7
+:1021B0005F5909F57C19DD102AAB079CEC77943A3E
+:1021C000A611637B09EC9BFC2EEA45760BE6ED57E6
+:1021D000390A7E02F5BCC384F73ABC622FF3A9E347
+:1021E00011E8FF31FB4A6C0F3CDA48E977C0CAFCC2
+:1021F000EB3CB58FDBD9F8F87B69FCCD441DDF42A1
+:102200004C50AE2598873FE014D97C6F35603C0474
+:10221000EA2FC3F959B05EBB8770F8DCEB6C01EFB5
+:1022200063E7881A1F6BC3F2432A1FEC308AAF00A2
+:102230009E2A7F2604F6A3CAF105D2016F70C878E2
+:102240006F8E87E4B85209F359D0EFF9543108F989
+:10225000ECFCCD0EB49B41F3817AF02110A46BC14C
+:1022600043CA54D70C8EE7390A783C9E235ED88F38
+:102270006B8BB3901F3D6A38BC05F32B6C5EB34C7F
+:10228000C7315D47707FE5C4D8E75DF38A199D8E3D
+:10229000DCBFB274C8E3E01CE5123C3BECE5129CE9
+:1022A000DF1970CAE9DE88728C7DF103DE0CEF8BDA
+:1022B00025682886FD9025D02FBEBD3F5A6F83F537
+:1022C00048382F7EB42C811D9AE3A0FD50BE2F8F7D
+:1022D0008ABD8E6BD57504D4FBF1F4F595C586EFF8
+:1022E0007B9D3AFCFB8EEB4C8D5EE7F738CF10F709
+:1022F0003DCC93CFA4F3B30DCF8FFE13EFEBBAC257
+:102300006640FCBA42BB37A920FADC85FE9C0595E5
+:10231000C05B81CFFC50CD1FAD48FC47F4E35F4E5E
+:10232000F57C906B07137F9603F99BD5496D9D8CC7
+:10233000389A4F2F077E6CE190EF5C4982EBE1FD0C
+:10234000D9D9BE479CD9C8F75717C3B931DE979F73
+:102350004CCB1F1BBB73D6B8912FD6C37B1B092355
+:10236000DD5D01BF8F067437CFDF09653A4633DE86
+:102370009F45E910E856A3C391F3A77449BF1FD343
+:10238000ECC0734D3B48100FA6A5936E8EF95B9A77
+:10239000516E1169DCF03A29D1565B9A711DBF6DFF
+:1023A00053503EFCD0F98000E587655F1BCC6BD1B4
+:1023B000E44FF0DE7B92BE341FEC4E3ADFF6FF971F
+:1023C000F31D79DEFC9BCF51FCBDECD1C78B599C32
+:1023D00043B3475D09549FA0F39438874CA8FE3857
+:1023E000649F1A2D9897307C3E375C87E780B9242C
+:1023F0002FC833ED7CAE9EEFCEBA8CF1DD8FD7388F
+:10240000E476BCAF700FDAA54D57DBB4F3BBA87F01
+:1024100035AD34A8E77739942B8DC482F7070DFDCD
+:102420007E1CFDE352877F9F633F9CE32DFDA673D7
+:10243000BC129E1356D6B138FD907DD72032FB5585
+:10244000FB9D875BB3B4FBF8999EB2865C907D1BC5
+:10245000E37C2FEA8D24C9A0DAAF4C5FE8992E897E
+:102460000AC1F82AD3C3179BB07E73821F7F37A59A
+:102470008EEF4624F963B153BD17C16FC5DF5732E4
+:10248000C979C027B438EBC21CDFFB80BFCB8B3CC3
+:10249000991C5D4A9D89C54F291D6C1FA4ADE6920C
+:1024A000E6C7E0F7B32E27CD6F1BB2910E8E221D2B
+:1024B0004CFC84FDAED6301D1C2B86FC06C2FC01F4
+:1024C00057A871A2973E7EBC13F6FD2C47D8F9AEF3
+:1024D00002FDF92EEFA9629C5F48FD5D9D68BE1369
+:1024E000318FE346360F17CFE33C3E8B358F1174A7
+:1024F00048FC383EDDDF663C47AEC323FD7CB8FEBA
+:10250000DBF1BCFFF6EB89C84F07393E6805788ED2
+:10251000058CC88675FA0C93A7A13CF7C1FD669A95
+:102520005D3D62DEBC0DF775E1E2A13C9DF91965E8
+:10253000102762E33E94D8F820F83D9AAE37227F08
+:10254000AFE99F847ADA41C52C421224A962F93599
+:1025500032FD1FCC6B11F1CC71D27EAE126BF0BE8E
+:10256000B4ABE7E9F37294BB9A69FB6BD43C9F85EB
+:10257000571B8F46EA9B678DF718010E4A9DAD9950
+:102580009F01FD09C3EDDD23E132E2BEA64EC69FE9
+:1025900008D573A0FF8EF200F2A7787C2A6FF25064
+:1025A000BE4FFEDF98EF533C19F1E29BF37D64359B
+:1025B000DFE7356318EFE1FC4DCA8AED6BE83AF3CB
+:1025C0001F2EC2DF139D93BAEAB1FB69F9896D131F
+:1025D000B0FC9BD4EB6F390CF53BF3B05C65F86451
+:1025E00009D04341D9E22BE077585FB3B27ED213D2
+:1025F0007C3D35F4BBF4E2AC2970B14B95298CDFFE
+:102600005D39B9612AF863AA1258F950C93B53B031
+:102610009CA596A7BC3401CAAF719F2C89C517270A
+:102620001670C1422A6FAB92D9F7F3A63C391AEC67
+:10263000F8AA0A569E28CFDE940DF5864F97C4D28D
+:1026400097AE9FCCF8EAACAFCE768E72415898FD2B
+:102650003EE80B9E0FF07736BC54DEC2397C6F39F2
+:102660008BC3793D2502FCAE538587952B6D6D1983
+:10267000C007E7FB4CA51077156DEE4EF8BDC2A460
+:10268000F2D9D360DF2BA9BA0D714E4A5F37009E95
+:102690002FBAE4934C07EAA51A7D8946787EC37D5C
+:1026A0008BCBD8BE45D303ED6F15F67769B4FC1C10
+:1026B00041AF3A3CBCC23296E11D958BE6F291F4F3
+:1026C000AAE7DF647D808BA4D71D80973CD2ED5AAA
+:1026D00018DF641894E0FD784E9E207E03FD9E3541
+:1026E000BEEFC638107DC15F1A836FD03F41D3F370
+:1026F000D92C443115F397595E4FFF3BD81E8E837A
+:10270000F01938FE26189FAC67F3D901F790F060F6
+:10271000EFF91E053ED198CE7EF711E2FA40A7E907
+:102720001ABFEA8B5E6F47B97C93931F395F83852D
+:10273000C1F16A551FFB7DAB37A5844E7621693602
+:10274000C27A1F4A742810CF6DAA65F74906D27C59
+:102750000FC33EF106E540889697138F89F137CF76
+:102760007698A7B62F8DEABE345ADEC77C36F8833A
+:102770007B4E46C0A34FCF47A3D73FBC2F8319F052
+:10278000CC807B54B2619DF2463EC67A88D0BC298B
+:10279000D24FFFD0B7FAE909F3B7C866F55E94F0F7
+:1027A00092487F5C87BDF991483B999A65789FD1A3
+:1027B000A1B61C120BEF343DE910A7FAB5A8DE0B49
+:1027C000FAC0E7097F45FD84528CD798097EADF9A0
+:1027D000A8C770268B08F1EBF4DA74C4D72D542FF8
+:1027E000013FBB5211C8467FF94E9EC0FD03C37026
+:1027F000A033710FE3E7F1C9CC0E4C1B8287827CBA
+:10280000D464E062EA57C7271BD47B50D9F9D2467B
+:102810008B99E57FAABF4BA1E5B1345A8AD637E33D
+:10282000FA2C8C7E74FB3422AF459F27674943FD09
+:10283000429C4264908723F360F4768282EBF8D165
+:10284000507C8130FD67AD1DF59F1FA9F1056EC15C
+:1028500017B83FC914BFCC2E8823481CD82BC9A554
+:1028600087053269F87724E1F797C09FF57C96EFEA
+:1028700093C911F1F837A73D817921470C2C0EAA95
+:1028800087CF5743F00961BE6AA3C6AFF4EB8F331D
+:10289000FFFE34EF5F61BC8FB9C132A8D4E253545C
+:1028A000ECBBA1BFFF0B8F9234BF00800000000083
+:1028B0001F8B080000000000000BE57D097C5445DB
+:1028C000B677DDBEBD25E9249D859010960E3B129E
+:1028D000B03B21618726408651C000A2A008371076
+:1028E000D6AC82CEA0E3980E0144079D38A2328A6E
+:1028F000DA202028308D02A246A70544FC74346EED
+:10290000E3FA98C40551B61844719E6FFCCEFFD40B
+:10291000BDA46F13467CCBEF37EFFBF0375339B7CD
+:10292000EADEAA3AE7D4D9EA5475923B6B5492474F
+:1029300008F1C38F3FFE982FC495F4A7E82644639F
+:1029400037CDEECD13E26A5134D6AA08913C4EB38E
+:10295000692E21C6AAF47F038468D9A6041DF47CDD
+:102960008C3FC6225285A83C640B06095EFC8A2A6D
+:10297000002F7E480D0A825B84776D23DA071CEEF8
+:102980000095F7C7F5FFFD302A3F7DC8E675A0DF4B
+:1029900080FFADDED46F09FA25B8D75A8BF0380521
+:1029A000FFFB91FED727182B3CBD5BE1BE5B924D30
+:1029B00070BF500753FB4BF77635D5FBC29798EAAB
+:1029C000730FE598E0BC8621A6F603DF2F30C183A4
+:1029D0001B2F33B51F7A74B2091EDE7C8DA9FDC88A
+:1029E000B3B34DF5A509850797D27C0FA6AB421965
+:1029F00024C428516A6A5FAA96D98585FEA8B37D4A
+:102A0000D248EF55D17F3F7625589D61059ECFEC8A
+:102A100055444A9610F3D7CA7AE3BD05F577AFCC93
+:102A2000A47261D0FCBC54585B617A6FE9C70BDFBC
+:102A30003810D15FAFD4624B1295A3BCF1A947FA0D
+:102A400062C262E08F2AD3D51B069DDE51BD0E49BE
+:102A50000AA6F3E2ED4AF00EA2634FD1E37ED08DD9
+:102A6000E82C821ED055D6B7AC538301EAE7BBEA07
+:102A7000056F1CB0117C28776D23D17F7E8DC3AD8F
+:102A800052BD23DD4CCF188F999E71BDCDF48CF7CC
+:102A90009AE99938C84CCF24BF999E29E3CCF46CAD
+:102AA0005764A667FB69667A6668667A662E30D3D5
+:102AB000B35395999E5D969AE999155864AA8FE645
+:102AC000DF6EAB169BEAEF8F7BE188467848EDA07E
+:102AD000BA1D6E217AD4DD6CFA9E50C7DB5710BE4A
+:102AE0004A3355A1BA5BF92040FF311F882A5E5F47
+:102AF000F3880F1E203A9C11AB0F667ACEE7878AC7
+:102B0000BD77DBB13E7F2E3F2C8BE203E2BB447CE2
+:102B1000E747FC1B797E69D0F90AAB7F95B79D101A
+:102B20000F7AB5DFA19CD6EBEBCE56921BA2A8B8CC
+:102B30005751BC102ED13C13FC542112BC77A07409
+:102B40007E9C057EC13F4706FD9F5F74B712DE1471
+:102B50001D6F62AFED78A3312E9AB752FF5E16E675
+:102B6000BD8E985145FB892145D0F83A8A860CC81C
+:102B7000A70C51A5A04C17DE552AC6EDE99484791F
+:102B8000E0CF1F3399309630BDFF41898DF97759D9
+:102B90005CFF6DE0CBF76B255F9E4693C1425C23E3
+:102BA00042367CE783D8073BA1BF0242B832189572
+:102BB00075D761FC33307EAF10D789461B3E3E4B44
+:102BC000083BCA62E1E1728EF0DBF1FE5C115E89C6
+:102BD000C97C94AA6D073E2A54AD4B1AF0D1B1A11D
+:102BE00073513F2A5F4BC1A02F8857505CD07B6F39
+:102BF000E34F6AF789B76837BE33DAE9B9E15EC2F5
+:102C0000CF3E8B581022BA88F1293C6E612DEA37ED
+:102C1000B95F5BDF5946424D88E7144D03BE031987
+:102C20004EEF2620393DF4A442F3BB24D9937347D9
+:102C3000526BFB035E0BB727D60B28D4FEF15DB1B8
+:102C40008CAFBEEDD727635E3FB7DF06AFFF558C75
+:102C5000DB68FF53F3B5DBBD8B6EA47E9B1551B5CE
+:102C60008106F18E4E974C07F10F8D37534DF0D6FC
+:102C7000826E71330FB6233C2C69AF7D00BD34EDFD
+:102C8000EA5FAE04ACEC4BF12CA6F19D2A6ECCC7EA
+:102C90007809FFFF86FA3227E19FA676A293D62B0A
+:102CA000114C5124F14F7FF42B6A73FC723C077472
+:102CB000FCD7B7D78EE03BFB2C0D9DBDA0A3B52163
+:102CC0009FE9E896F33A619778B9101E0AE23ACD87
+:102CD00000FE4B1C0EAF4AF82C50E4773F4B9C355E
+:102CE000B392C63DD7529416564DE3FE06782B7329
+:102CF0001577C9C0B86DFAB89DED74BC7BB2B1AEA2
+:102D00002E34EE5A7C9FF014F8AD12DC9485E7E186
+:102D1000AD809F166EF71D3E5A7316A9979B6B9454
+:102D2000E006AA7F43C7F343366A8775E914C935BD
+:102D300034BE2B86AF588F76BFD39C3CEE4DC27B02
+:102D4000C99A2CD043B0BCCFBC4D09D6123C5B789D
+:102D500099EF4B4451E75DB00F7C5ABC8FC6F1B779
+:102D6000B87FE465597819E7BD43DFD9B3ACBDF747
+:102D70000E40C32E8EFF7B93E440FF932748BD3364
+:102D800057C7DB95A288D7E955A28A4B5AF0272A64
+:102D9000A8DD34FA0BEB93E07E18DF74C0BED67565
+:102DA0003D4334703953B89F6FA46FBD55D3FEC6F1
+:102DB0009BA8CD644B7367BB8A754AEB368BF1DFFA
+:102DC0001DE3FF76EC9B8715E0FD169263A0F79A52
+:102DD0007617C5C79314894F5AB7D9BE3C5EB7035F
+:102DE0007C9688F533A69DE43FABBBC73F5B3F2491
+:102DF000181332D284F8851485E2FED3092295E6B1
+:102E0000D9D0550D3AB2A0A76FB1EEA27936903D58
+:102E1000E1C0BCFDC51D4E51FD38D2B77748F91A47
+:102E20001F2078A25F1577301F342E5F48CF5F1BBD
+:102E300044F5D4FEE51A113F80E0977D366F2DF101
+:102E4000E1D8B3DA81442A2792DC0F53EBCBD2EFDF
+:102E50001E03FB605C47D223117AE2B2EE6698163D
+:102E60004247D0E9721DDFE3B3CD7A6722F48ED1F9
+:102E7000BE0DBD43F255057E27FB74FD7389B80472
+:102E8000FA677FF55EF129E917430F8DA61986B21F
+:102E90002FAC8762EC05D7806E447F3BD6C76C2B86
+:102EA000B507BEDD5A874911EB656FBEC274F2905B
+:102EB000E2B1D0FCDF38A406811FAB3F3C14F85BC5
+:102EC000FCBCC27CFA079F3617DF3B696B9C07BED0
+:102ED0006918969B28A8FF4FAA6920BD68FD563B3C
+:102EE000859FD6C2916A37C347ABD3B9FCAADAC370
+:102EF000E5F1EADE5C7FB2DACBF0B3BEA20AF0C342
+:102F0000EC555F5BB56CF45FC5F6D1921AAB00BDB2
+:102F100096C42F96B0CDE98610BEADD3414B1CC1EF
+:102F2000B705152FF4E2C25DC1957134AED27ABFF8
+:102F3000DD05F9D72979B40BEDEF5598EBE71DAA1C
+:102F40003A88E99E7CE793AB2688D6F9969F55840C
+:102F5000464BAE5B9EFFB798CF17D583785C5F5624
+:102F6000FB795CFEFAA68329F4BD63D5E3187EC71E
+:102F700057548B767EF135DB1113B6355961678C6A
+:102F8000F52B7ED079845F048384AFB536A957D6FC
+:102F9000925E811C18D56FF2433708C87DED4ECC88
+:102FA000736AF29CB1B057270E2A66FBF5EA1F043C
+:102FB000DBAF06FFFFD43AF288869399D4DF89808D
+:102FC000C44FCBAEB7196EB1127E68C62FEC2A2D56
+:102FD00015641FB49C7D4B3EA7766CA7EE96ED164C
+:102FE000DB64BBC5BB7F97CCCF15A55944E8BB6359
+:102FF000444741788873663EF419E1E7D8F65FA745
+:103000006B11FC752C39F4ED879093FF66F16E60BF
+:103010003ED53E7D167274B99BE5CC495BE8C8038A
+:1030200090B39D48AF727D55DC64E2B30ABBD09883
+:10303000EF84D617F0B15831ABC825FBF3F492CF2B
+:10304000C18F3D77DCDFF5379ED6FEB684E67EF88D
+:1030500000E8B0E3A3844B68BC7D541152317F215A
+:10306000C711D818CBFD943D797BB29FE0AD8A683B
+:1030700051594E04595EFCCE26A6A1DFDE8AD5BE8C
+:103080003499FCAA3B9FCEC4BC7BA9A24AA5753942
+:10309000E7AE67329FA1F71E2359A4D2F89FB379F8
+:1030A0004FEEC5771FA2F153BF8FDD599E037958AC
+:1030B000F2878597000F7F81D0223A3CF1F44EB61B
+:1030C000178827BDA349AEF55BF3E2B20C6A7FE92E
+:1030D000BA264B072A7D1B955A94A5DB76BE55432D
+:1030E000FDE5BA2D55B05FDFF279785C39A1F51BAB
+:1030F00014E8811F1EED807599BDE6EB820EE2C2D9
+:1031000076C6139DDF6F29F6B05CE0F777D74F796D
+:10311000FB5A013B862C188CB7D8EE65BD46D3B65A
+:10312000013FBBBAADC7FB7B2C01D65781D9D2CEAC
+:10313000395114F823E65F4EED030497FB1A9A6E9B
+:10314000A2FAF2A4AE2240F33F1A5C321DF5031539
+:10315000E1067E2A76DD5BD881E013C38457A1FEA9
+:1031600017EC3E5DC8FAB013D9EAF8DEAEDAB46BFC
+:10317000A00FB30BF254AA2F5243DC9FA894FD5525
+:10318000D6EF740226D427ABC46749F5A3F6677A55
+:103190005AE96369BC2BCB4ADF6B47FA14E35D9BAA
+:1031A00015C8A872B5EADF645FD169AC1BE1BEA7A0
+:1031B00018DFF99CC605FBEC62F5A5DD52B590C79A
+:1031C000932EDC81C1ADDFED64092FC43C6875B876
+:1031D00003F49D4DEE86E9DC8EE0DF73BF9A9A938F
+:1031E00007FB8AB09E2AF57B2DFA754FE90C7A5DB4
+:1031F0006CFFF7C7FD83EDB44A4B82D731A0D5CE23
+:10320000999652FB7C23D12BD85E4BCC6907FB5897
+:10321000DAC9C2EAF540EE57B7F7BB73D84E233D83
+:103220006C61FD9B9A1361379FB3DB9C17A77F43AB
+:10323000EDFD1DF0BD8B6DEFD1E312E7E4F0991CBD
+:10324000931CAE8DB70B1F3DAF5DE3E03886386051
+:10325000293B48FECA707CC2D2FABD25F139EDA1E6
+:103260001F6A8568135F2FD0FAD708B761D21B1A7F
+:10327000C98111679B558DE544C3FEC40190B7C257
+:103280001FEF41DCC022B408FD18FD1DA2D760CCA1
+:103290006F9488135A849EF58B243BD6AD70255FBE
+:1032A000E4BCC38F9AF5CFBE4723E73DACE5FD38BC
+:1032B0009860848FF6282F34AFE7F579FD19F3A2D3
+:1032C00072677ED1E5A0DFF06FDC56CC6FB8755227
+:1032D000675F571EF7243C1FF18DC53CEE1F624D02
+:1032E000F0C58EFF46851C3BF0F1D7F620D65F3D3A
+:1032F0006C059A47FDC2EC20D6FB1EBB0838E1F7EF
+:103300004CB6B31D5C1F1F88875CAD57DC21C49F82
+:103310009EB3354C977E91706FF2817F5F7F10FC7A
+:103320007F4D8B5D413CAB83431C817D25D444B1F3
+:103330002935E2FBEDDC1CE750A13772091EAC3FDA
+:103340009F6EE7E7B536C17A32303D96C7B526A9FC
+:10335000EAD57E54BFA626D34B2317EF8BE0AAAE47
+:10336000A8BF4565793ED4B261D37DF07B26A5B375
+:103370009E599314CEAC44FB85977803C40F7BFE13
+:10338000A1B2FE58E3F36724BB200749CE139DD7B3
+:103390004CF267C4A6A24CB360BE1D48CEF3F32C1A
+:1033A0006A47E58736D9EE039D6E84E90CC8DB07D2
+:1033B0004A7A08963F390577F03AA10A27F1F35483
+:1033C0004902317DEEBDE226B4D3D4A09A05BCDC1F
+:1033D00075674F82AF99ADBA11A79BBA20A649E98C
+:1033E0004FA5A6861D09F4C29563FD91FEFADA1C6D
+:1033F000FF1DA07379A84FB7CF22F878FADC1EBF63
+:10340000827CF884FC68F8DD77A4697FE0FEF7FA37
+:10341000B8DD5E326E7E849E707AFAB3BD5D62F86E
+:1034200099E139C0EF0BCD4EB6632FC40F42789DA2
+:1034300097D0F7EFB38810F8B98BAED76B110000B7
+:103440009D4331CC07E3263BFD1CAF725936C08E3D
+:103450007E84E805FD16D8ED607A91A064FADDF768
+:103460004227D64BB37439563B2D96DFABDD690B43
+:103470005A406725B87533DE7B3E86F567995DB0A7
+:10348000BF52F66C5FE6833D767FD60AF4FB82433B
+:10349000EAED044F22D7FF9F1481FAE7747D5D1691
+:1034A0001BEE994474EADA4E7B0A7823BEABE2E75E
+:1034B00076F9FC70B0603DD6A520FB266E04C1C233
+:1034C000BF1EF22A4076D026AFA41FC6A5D576DA55
+:1034D00080F16A340ED059DCACF27C0ED35AC6FCB3
+:1034E0000E5775E2712993C765CCA5FA4F17C771BE
+:1034F000DCF570D1C133B0030EA7ABBCEE4942DDA1
+:103500003990EA49E736DC4170E5C24F5E1F484F0B
+:103510002B6A3FE8BCD7D38AF719CBCAC70BE28323
+:10352000198B6E9928122EBC5E679439E053B6AEA3
+:103530006F618773276192EB4D39FE06F0C17FE41E
+:10354000686FA3ACCC267B9BF8E8A4BDE161C455B1
+:103550008E7AB4BF022FA79EF962339E0B6B734F16
+:10356000E60F676321E23265161957BA2B57FB380D
+:1035700087F56C02D3AF32E460FAC5653748B97895
+:10358000CBC5E983AFEA37ED51A89FD2D8FA0A2E0E
+:10359000D5607FE8AB634A3841E9C6F8D5B0AE8E56
+:1035A000BBC309A08F6691F65EE996E879D250D345
+:1035B00010771342FAA921FB501AD72212BD0FB877
+:1035C000F1DCDEDA3EAB958EF41DA6A3707D3CF3F4
+:1035D0003768BFB54FCE1D84F7D2A4BD770DCD3A65
+:1035E0001F7FD1B0319FF3C7A3AF93A27002D6C99A
+:1035F0003145AE93E342CAAFC096183D5E20C77115
+:10360000F299F63C8E347D1D9D54F4765B1DB21DFF
+:10361000F11EEC99D23F49BEBBCFE665BD19207DB6
+:103620000279599A22E15247BA1BF656073560894A
+:10363000055F560B5E2F34365E97C77664F2FB86C5
+:103640005C13454240AE95EEC8D820ED3ADD6FC61A
+:1036500004A8FDA227647F8021FFBF7A3C53EF5F5F
+:10366000AEA768BA46E3A15BAE8C73D5C6E7B7FFD9
+:1036700067F1CDDEE91FAD8308BACF26D775205E8E
+:10368000EA11B25BD227F5C3FE84DDF4DD93F1F6D7
+:10369000597E17F629CCCF8DEF5D9AAB70BF5DA236
+:1036A000E8DE416D7E11F6927854B09C881E477E0C
+:1036B000AEF4571F7FFC1C9D554977622483BF3CA5
+:1036C0008C3F61037D3EB01B74BC2193E47A29706A
+:1036D000D5B5158F7B7C5A26F4C849C084EF3D4987
+:1036E0000467C3DE92FAC3800D7A44F3E9B20FE6B1
+:1036F0006536D2FB7372A57F501B93D05F24A2EC7A
+:103700001C841CA821BCA29EF4E0ACA26CF8C3E30C
+:10371000EEF9CCD63A9F23D57E3FA9A073F0BCB575
+:103720003E27D6E7FC753EE7EC087AD46EC93DE447
+:1037300021BC1FDF62456452D45A83770D49C5739B
+:103740003514105CEF04BE8FBBF6BD8E76F3D62524
+:10375000E5A811F269FEDAB1FE92083AF4DD62A63C
+:103760004BBF9019BE74AF192E27DD8EF9FDDCF723
+:103770007C61339C7BC80C3F3DA859FD11FAC9659B
+:10378000093A15942DEA8F90EF4135083FA3CB2DD0
+:10379000455326107C74DD1C2FC83CFFDD65F9A065
+:1037A000DF89DDB7ED29A7F78E265BBCF0AF8E89E8
+:1037B000D05F27103DE6D5DF6DB77A305F339FEFDE
+:1037C000B1E87CFBB88C032E0C9AEBCF970F357ABF
+:1037D000DC49F48EE4AB68FA53BF57F96960654B76
+:1037E000A7DC03FB67C17862781ADFE0D0DD76E101
+:1037F000BA987E028C576B8208A7D3F89A6E8BE733
+:10380000F8CB90A5A3C5A7F4BD72AB3BFF3734CF6F
+:10381000D94EC51D70B7C6D59B766654409F6E7253
+:103820005BBCE4E308F7A0AA839903E04F8890DB30
+:103830008BB8FEAD2BE1F72FA84A60FC2C14418E0B
+:10384000CBCF5EEE68958FF4BF92D551E3591351FB
+:103850004FF358B0CEDC7ED1C61F1D91B0E1970E5C
+:10386000A95FAF62BE73F571AB8189AC9787E8F150
+:103870008ACFD094F4CD13DD8A76E4D27C87AC195C
+:1038800025EBAD4E5DCFFAD9CF2B77D93D2CCFAC00
+:103890006FAEE4FD1D5A87D00F87E2E7FD0AF2EE16
+:1038A000B453B81D3EB4D7183E9222FD42DEB7A0F5
+:1038B000F6A7D729ACD7CB53245CFEA812440CB88A
+:1038C0001C415BC08FC9386D998E0FF0893F623EF5
+:1038D000A057242CEA8CF87898FDDF8A2AE1851D10
+:1038E00020888E7E036FBC1F15B61F859E0D28A1F4
+:1038F000077CB0F7CCDFA9DCFBA323123E175F26C1
+:10390000D2D5F0F7838C47D52EFC90E3EAADB16CAD
+:10391000B7930288857EB7E9F6B558156C077DB573
+:1039200006FA8ACA15BA1D1EB85BEAAB3549FE9E77
+:103930006ED4DF9DE1051EAE5174FF16767D12EC4C
+:10394000EB7DDC6FB3E2766F48427B11884965FB03
+:103950005AFA09FF5059DF3593FDBE01F6BA2F140C
+:10396000C678D6DC9BC5F6FA7386DEBB3346DAF33F
+:10397000E7DBDD6C5F897BA4FDF8A1E0BEC555DD0A
+:10398000B593B934BF396A116F46952CF367E0BB24
+:103990002593ED16D0432CB8B87D914D56D97F3381
+:1039A000CD17F1FACF94A28396483B58D70FF9056B
+:1039B000FECD7A3B2FDA9558DE643C9458841BFE8A
+:1039C000FCA6B3AAB012BCA9CE115C46AF9474F5A4
+:1039D000F75C9C8DF7647CEAB04FCAFBB801C21F4C
+:1039E000A4D239407ED739C0622AC5181967F92C8C
+:1039F00046F2E10C5154C8FB031E29EFA3E7913AAC
+:103A000040EABD127B83793C1FEF67BA90CE732FDB
+:103A1000037F8F9176C767D72BACCF693E3DDD041E
+:103A2000E7FF2186E38B9FE9FAC8C02FF14F1EE222
+:103A30006886DC4AD2F965CDEDC1AD3184EFBB6D4E
+:103A4000C437A01BF1CDA6014C77B60BD74C4F6302
+:103A5000BA5FA3D355DC19CF741B6AB1483CDF9918
+:103A6000C178A6F6E2EF786FAC47DAF317E9871171
+:103A7000DDB307E49DEF8F19F416D660DE3FDBBFA0
+:103A8000297F7AFB9E00F1FFA23FDD9B20A8DD97F6
+:103A9000D6BA342FBD5FB66945829FCAA3D640828D
+:103AA0009BFAFF32A88E0BB681EF453ABEB17FA0DC
+:103AB000A461DF55CAF1AF1EFFF79537D338BF5564
+:103AC0004433E463C5AEEF57DE4CF33BE87736434F
+:103AD0009E1EB5361642EE2E2C7655D578B17ECD8B
+:103AE00071FC458FDD9BE6617C07322DE9BCFE331E
+:103AF000F15EC5469B177E5DC53BAAD783752F9A9D
+:103B000057627CD1EF57863EB503FF6E8B68EE3867
+:103B1000B48D7AD1C872BE72D7EFBE5613507EF9FB
+:103B200021FC8BCAA8FD8305FAFE4AF43EC2350388
+:103B3000E2538F2040AEEF5F137E388F2140E3EADF
+:103B4000C1EC22E3CEB55BEFEFDF04BB61E3AB0971
+:103B50004A76EBFE81B1EFD2129AF3C8B39E0BAF57
+:103B6000CB937ADCB8956E528E79F6D2C0DA0B041C
+:103B700018B82CB3851360EF97ADB7B11C29DBFEE5
+:103B8000E8E607C06F1F38BC3D3C804FDB210FCA01
+:103B9000147FB3C2F25D2428F9ADF42ADDFE79E189
+:103BA00083B0AF3354319EE8B5E8A933B2BD5F347A
+:103BB000C750FBD29D4D85F00FCA345795B30D7A8F
+:103BC0008D0EBD686F74B541AF505321C7A9B67E45
+:103BD000C7F4F8F20545B4CF3AFFFD05EB3FB70B4C
+:103BE000E91F34A724497C41DF5586D4627BE2F982
+:103BF000EDE9FB139F1DC0F56EF82B3F45C721C0B3
+:103C000005F37BBC4882DEFED0111C0FFAEE589201
+:103C10002088FFBFB05649BE7F68451AECBC05B688
+:103C2000409A9B4BF97CC1C337323FCE57AAD2DCB6
+:103C3000D9CCEF1996413CDF0CCC73EEBAA93CCF3E
+:103C40007942637E5CF0905A14A4F28C558CDBD9D7
+:103C5000C6BAF94C5F370E717D7FAC9333F425E81B
+:103C6000F12F74BF3EF096F4A71D627262E47ED21B
+:103C70006E5D2E0644F030F44065838DE314EA9BBC
+:103C8000670AF19D1BB2AC55C8F7A0F907747C29EF
+:103C90003F4AFFC583BC874AFC45FA74F49B63DB4B
+:103CA0003766E3FB2DF6EBA8DF6FE0277A4DEF31A7
+:103CB000DEBED8E088552EA5324DDAEFD1F348C9E3
+:103CC00033D6BF784B44F053E5962F989F44BA2AD9
+:103CD00012D3258CFD0BF76C575522E1ED9B773EF7
+:103CE000B523FE1D48B5881E186FC3E70C0B6F3B4C
+:103CF0000FDA1BDFAFDCEB10E1C875BBF1F3A87581
+:103D00006DAE17A28AF15929123DD0DF5FD89B0B07
+:103D10009F433FD4EF26EA671ED95F61937DD55C50
+:103D2000F820E4C95EBB9BE30F647F8623F8E6DCE2
+:103D3000FEA8BE2F385F9707D17888960F87A3E437
+:103D400083F1BE58D7F67E54AB5C08307DCB6C2235
+:103D5000003BA3EC0307EB8FB2ED723D0A92A73D47
+:103D6000687D1CDBB6FFAFD7C09F0DD952C773AFBC
+:103D700066F9BBE0C9CF795E7308FF315EC8DFEF3B
+:103D8000ECF07FD3478B66078DFFD86A9F1D7C7F41
+:103D9000DE3AA6E76DAEE3D50ACBB7FFAADC257CF9
+:103DA000DB616FFDD47A9D7F01B91B9367CE1B3A0F
+:103DB00023B21387A2D25DDC85F70FA2F06BE0354A
+:103DC0005A8EAE1FE09171E928394AFFFE2A22F08F
+:103DD000284423F3F1B72417B10F57B1F17BD66B09
+:103DE00084D66607F17145F06B865740AF31FCE22F
+:103DF0009588579E3F6F333EA3EB5F05EF139F15EA
+:103E00003D6363BBA0AC5EE639D27BEC7754225EA7
+:103E1000CFADEB0E66A646C2C1283814D5DE1F050D
+:103E20001745B5D7A2E02A53FBB2BDFBD9CFA2718B
+:103E30009BDA39965ECE7EC8F9764590E751B9EBAC
+:103E40006B7B00FCD1B1D90EB9685B2602F1F47E20
+:103E5000F3F32ADBBDA73CCD09B05356C4483BEE73
+:103E6000945B87930C58CC2AA6719C0AF47723AFF5
+:103E7000A03946C65B4E1535272445F8ED4DF56A49
+:103E80008287DA3706C5B8B6F3626A99CE8DE24208
+:103E9000F5D29E1BABFEB043E68B5A8583FA6BAC22
+:103EA000F96E07E2499F91FF04FBA5A4E6EA04EC42
+:103EB000BF9CAAEF76C534F881AFA89CF325027E9B
+:103EC0003BF226E648528AA32270DF309A9F1A3FBF
+:103ED000E0E073F0AF8851B0FF59B23ACABE114565
+:103EE0008961F8D36BA2F31B8276D837F349CF42AE
+:103EF0001E2D5867AE5F547F8CD7CBA2A8F5A2E9E0
+:103F000071E3E8F55269AC179FF0E9F9969CD77711
+:103F1000EA90CAFCD5B2DC2656A6CABC5AE4A3B4C1
+:103F2000D4CB7C9D96BD1216013D0F485FB706DECF
+:103F30008E633DF5BAB0DD727CF7BFE5FF06FCB3DA
+:103F4000E7A3FE0F52797CCF073D9F03FCF47B9DD6
+:103F50003F12E7B71FFDC2F733795C2F3804C675EF
+:103F6000EA85973BC3DE38F5AC83F3114E2D73B071
+:103F7000BD1E78219EE316A73A497BB8F6F9EFFA01
+:103F800037B23E5ECE747C20CF2EEDAAFA7F67FD5D
+:103F9000D852EFF0601E952FC4F1BAAA7C3686F78E
+:103FA000D54E3DFF5D7E643CEEBF3A1F631FFE545D
+:103FB000BC98F624F857B7FF2B9F1BFC680DFCE557
+:103FC0005D2FDAE720AFE4CFFFD11FF2F5D4932FB6
+:103FD000B2FC3D696B7C18B1CD4D79E1076C831162
+:103FE000D7A38F75106244BEB83690DD165E241ECE
+:103FF0004E111E302FC2CB02D8E517C2473DF0D17B
+:10400000EE5F111F5FCF94726EA0C0BE4F2B5E1487
+:10401000BF7C1ECFF12A9ABF7CFEC277FD21877E2E
+:104020006ABE1FFE7F36DFB3FFB2F395FC1EC8F3F6
+:10403000F038A3F9FE7CBE7EFA570CEF88F7F278D1
+:104040002F72BDA7E7FFABAEF7FF197AE7FFCBCE24
+:10405000F7A7E8FD8A4EEF7837F6414F3DFF1F9DE9
+:10406000C5CF98F7D4FFA5F336ECF902D57BC84746
+:10407000ED5F15A177BC596C95B4698F2CD3F3050E
+:1040800085EE4F8DC65F1EB4CF591EC27A207B02CB
+:104090007E4CAD2BE7C09B04BF4C7682CAFBB2328C
+:1040A0009EF472BA2F28E3BB5502F1AC82F7E630DA
+:1040B000FC9AEF1707905752A8CA78CCFE1AEFC6A1
+:1040C000069AC7FE248BA796E0311DE77CB693EADB
+:1040D000DD1D5437FCB3DA8EB94E4FC4F8C6B8CCE8
+:1040E0007ED6E5517ED22F3DE6FA71E2C954ECD777
+:1040F0008DCBB6099CCF2944FB08BF52CB77F33C4C
+:104100007F29EA96BB5D3F1F4FA17CE977125E785D
+:10411000DF26D051D5F3E2CC7813C05B2AF092CBE6
+:10412000F67B40780FBC49B055B7AF84BEFF58E866
+:104130008CDF0C3FDA210AC24182CF78AC55686F20
+:1041400015E40FCB79B21F1D8D37A1FBD5569D0409
+:10415000633A8E0E03CF78DE25DDF43ECF3B1ACFD7
+:104160003F1FAFFB3A2E015ED3E3BD41F045C7A729
+:10417000521167AD253C2B4A2B3E0D3C45E37D0596
+:104180008D55F297C47747ABCF8A75365CB7E7C7D2
+:10419000589324DCB1412DE2F517947CFD8DD70AAC
+:1041A0007B7E942B89F349857ECE42D5F7C39161FE
+:1041B000C7E320FF1479B95758B5703EFCE6F16E9D
+:1041C0005100BFB5408410BF55EA5FFE1EFE11CE00
+:1041D0009714F1BEE6C1F701F772BAC2F007C53A0B
+:1041E000EBF1737632E2FE51E72B260EDA390AF450
+:1041F0009ABD949E218EE5F61CC47A2CBEC7E101BF
+:10420000FD3A5A1BB89E7C2D77CD60EC5687188EF0
+:104210002D214B3F03ED5E1EC5ED9708B7928474C8
+:10422000BB9002D8E596F96AE4BC7E0BD8BE3CDEB2
+:10423000532BE32602FCD41D65577C5FB64F1F430A
+:10424000DF43BE9BD0D85E8EEDCE9120D15529E2C2
+:10425000FDF72EDD645E44F30A07FB3BC5B775EA44
+:1042600009B934BEC01CB7CE1D28F7878D3238502F
+:10427000CA11D5E24DC777662FEFC3FE971A5B547C
+:10428000BE1B78DC11C77C5EBCF2BA0979F4FDE292
+:104290001D295E0CF3AB893BF365FBE937BE4BCFC1
+:1042A000B52D31FC7CFF40AD391F79068A67E66E7B
+:1042B0007A307BEA7E7B3A75A185269D40DC71626F
+:1042C00060E7EBD8E79C78A5CAED27EAF99F627909
+:1042D0001CEF9B4F087C6D4DA7EF4D20A706F54DB9
+:1042E00031EECED7D3F88BF578F30FBABC52638595
+:1042F000F6A40BE3EAD4B32B3D9F20643E74F4BADA
+:104300001D3450B6EF32DAEB49057E9418F786017A
+:10431000ADEDF11D7C77C44019E772E8A501135E8D
+:10432000392E5EB2CAD1D42D01A52DDC8BCA5F0D0A
+:104330002E881B48F5E3BB8AC2B5F8EE4DAAD8C05B
+:10434000E36D2EE6387B7C6F0FE8A0893ACE3712FA
+:104350006B7AF07E4ED328C1FCD3747796416FCE32
+:104360004F32FCB9A651DE83C8DF6A1EE5F46EF059
+:1043700022BF2514461CE5F05AB95FD3A536DC1DD3
+:1043800072B6D927F7413E5F9AEB019FCCBD774AC1
+:1043900002E4E79C356AD8017E5F6DCE5B126E2F1A
+:1043A000E78DCFA91B6587FF5AE2F2DB312FFF2093
+:1043B000AD17E6619C8BBC0463C2B99FBAE2D7E03B
+:1043C000F7A909B49EB1FEAC9E04F8D5D1794F95FA
+:1043D0007A7E9301DF91A679F1BDD9899E1DE08F88
+:1043E0004F9676E3B86AD540297F8535DC1DF8798C
+:1043F00098D602D6E7A7F992FFC627BB7BBA987F6B
+:104400006304E6D56473F7043F37AD88B1004FE32A
+:1044100097493EBEDD2AD757D0EFB10490C7A9F324
+:10442000EF8C1A6BD17AEAA7A35358E39385786A85
+:10443000B0E6C03826046A0EC3BF9EA3EBAB39AB0F
+:10444000E5F9B12EA3255D85B5614C0A3D3FBA293A
+:104450002B0779F106DF3C35B8E01703F35AE93F43
+:10446000BEC05FD88EBE33DEE269811C2EB95279A0
+:10447000B19BE483F1E867AC5ACFEBBC85E48423BD
+:1044800009E7061B248C7C55C88DBAFBFDCE08BFFE
+:10449000DD2E7671BDBD44E6A376B1876B38FFEAA9
+:1044A0007AE15E46F066B223AC3621B6543BB97C65
+:1044B000BC9AE45D0F21B655A733BCA3DAC365A847
+:1044C000BA373F7FB2DACBF0AEEA410CEFA9F63350
+:1044D000BCB77A1C97CF5617F1F368F933C7358FFD
+:1044E000E589BB27D17AF0F97C33D343E382FC71B1
+:1044F0000AF76D38AF24A4BC4BEA2DE58FD0E55107
+:10450000D73E82CFDF54811E840FDBAA51163EEFC7
+:10451000696DCC00DF8D558F6F7F1AF18E052ECE21
+:10452000CB6A118DBC4E5A84C51B1820E58F83F8C9
+:10453000AECBADE3B222F3D4AF5DA0086B047F5DD8
+:10454000571523AC11FA69D6D224133C63E9DB2F4B
+:10455000B5A7EFF7EAAAD5802E876F3DF2D07BF49E
+:10456000FC915BBFEA21CFF5FEB03E32EED2229A3B
+:10457000256C75F27EFC233767A4A57495DF03BD17
+:1045800066E30F0FE8D3FCE56358872B54EF3282C4
+:104590003F047D089F1FEBF4295ED16DE5AFB1AEFE
+:1045A000FD4EAF42DF397C73DFC241D4FE117D3F47
+:1045B0004AAC22BC46EA9974A9BF3E81FE4A92FAEF
+:1045C000AC0072342CF5D627BF4D0BDC86FAEB130A
+:1045D000BC3801A1AD6A1F984FF06A9FDDAB22AED7
+:1045E000572F56226E4338967645C066D6638D1D8A
+:1045F00093100F663D3612FB9E41279FD3A28EB0CB
+:104600001F33BBF73E9101B954A7B8B15F83739DC7
+:10461000CE64C83785F74791077425E9CBC707AA49
+:104620004CCF23F95679DE0BC97204C7082FC76730
+:104630004A56537BC8C73A9F7D5E84FC9DAD3F9F21
+:10464000D3DBC2A5F1FC197C0FFB87AB7CD3C01F69
+:104650001D509F8D32671AC6D7C155685522F67F07
+:104660009F1A68D5FB97FD1680A8F4FE1DBDBBDA26
+:10467000E766F3F92CD65B463FB37BE7ACEC0A7DEB
+:10468000BD7A14B0236A6DDEF4546A577FEE3B6E38
+:10469000195F77CAFCECB20BE80D234E77147FCA82
+:1046A00073923CDF453B9ED88173128B3E72B0FE05
+:1046B0005A74A9D44B223B983F85039AE6B8F898E0
+:1046C000274E1CBC8DC67302E79810EFDFF5A91DBD
+:1046D000F9A1B46CAA123300AB4DC8338D8ECF1E36
+:1046E000D8F151429B71F15DEAC5C5C5951F12A075
+:1046F000178CF98C7DFE4C1AECAC4AE52CEF335547
+:104700003EBF22ADADFCB0E8B8F8B9F8B958FDB578
+:104710008A38F32D47DB8C9F47C7019B0746EF473D
+:10472000B80A2027CE1C5283D84F6F09F648146D63
+:10473000F46FC4CF2BD7D24B2958979E44EC879D5A
+:10474000BA805D9E3748DAE527F478FBA96D2AFB2D
+:104750004BA7B6C507619F566CBBE720F6292B36E1
+:104760002A6C9E978B06C617E1513823F518F2DDA7
+:1047700052605C7B1221AF8CF1953E115F05BE5AF1
+:104780001852FC9B681C2D4E4F62BB8871240D9201
+:10479000EBA2D411CA67BCEAE3760C9272D068B778
+:1047A000B0FE1E8E4B53BB936CEFFC294E709EA047
+:1047B000687E1DE33BB62ED78B7DC585A19D159CDC
+:1047C000DFB12DCE8D38C4577A9EB3F19D4E7A7FDE
+:1047D0009D0649FBED98BE7F776C873C9F8E71628A
+:1047E0003D7DA598F305BB0D92FCDF6D90B4875E0F
+:1047F000D1D7B1D17E61A829A13BB5FF62EFDB5CC7
+:10480000F6D3FB59E86AE80FBDFBC5AE38DE8FFF73
+:1048100062D7838588339F088D4A05FF1BDF1F3AC7
+:10482000C826E9B04E1D077C89A0CCB329075E736A
+:1048300023C799B23E9015B9CE64BED1B15D4F2564
+:1048400058B25BE958EEAC72E27C68E5AEEB8BC027
+:10485000C7AFD8243EEDBB260570ECB992D42DF439
+:1048600004AFB30C6EBFCA12D1CE61F3B3F0B3ED97
+:104870002DF6A3BD11875EBCDBC6E70B675EEAB908
+:10488000FA5AACC3576D4C87C57D3C57733E528373
+:10489000CAF9CB8BB34418F6C7929BE2D7633FCCDF
+:1048A00018EFCC5CB9DECB5629C24FF32A0BAA42D3
+:1048B000A3B203D13D801CA5F4C63CE44F36650588
+:1048C0006FEF99CAE77DC31B525BF34C691DF7C4B8
+:1048D000B9C89241C93CEFFBA617B2BE3B6C1701A9
+:1048E000C885C093320FA7ACABCC8F7E007C8FFE07
+:1048F00092C33D5308AFC775BA964D0EF7445E4656
+:10490000D993199C9771DC2EF74BF11CFBC56539C7
+:10491000F43EB54BD5F379F17E52041F95CDF67A6E
+:10492000D04E4DF67A7C2E8CD77D92EDD6DDF102FD
+:1049300076ABE5E9783DBF2A86F3C88DF796EA7C29
+:1049400097AAD3535C23F331EFB3C97CD5FB36650B
+:10495000F0FD1846FBFB6CDA74D84F9807ECF58530
+:10496000F6BA9ED87731C6BB30A18EC7795CE7F323
+:1049700085B175322F5C3F778CF6809BF43CF6E670
+:10498000AD0ECE5FF92AA3E15B8CF7ABAD7D900352
+:10499000037CCFDBCBF5643F123D173DEE08A3FE51
+:1049A000CBAD326EFDA52DF82DE4F0970FA5F0F9F3
+:1049B000A82FDB05F3393F40715B609F7DA9E8B00C
+:1049C000CDCD7665173BC1D43E35565890BF336E7A
+:1049D000F2DA99C86F68D9E8007B8AAF36DF9FC6E4
+:1049E0007E8DF024729ECD2155806E5F3DFEEF7D61
+:1049F00022ED17A35CB4D19C77D79425ED4AA37E12
+:104A0000ADBE2ED70E927EC7BA41524F95C785EEE6
+:104A1000EBCAF393F826FAB07F470A3E9EF327B617
+:104A2000F75020371E10C15F7D3480BD6C0FF2E659
+:104A3000CB9EDCFA3AF66BBFB28806D81FCAAD5BD4
+:104A40007E85FB3952EF4A643D24C4469EDF976E53
+:104A500079AE95162CCF7F617B092F9AB2A527E0FE
+:104A600083A473145A5F8B2C0AF7BF684F3FCEB7ED
+:104A7000237A58789F6CA7AA8F876C4AE06FB3CCD3
+:104A8000571E9F1CDC0C7BAFF9A16E02E7DDC7AAA5
+:104A9000EBFA837EA737C659C04FE5B70D4D1C0A08
+:104AA000BCBDA10AD81FA7ADDEF6917184687C4514
+:104AB000E7819FD0E55319AD3B9CFF2CDDF310DF60
+:104AC0002F520ABE045E1E57781FBB74E5D0FB99B7
+:104AD0004F5FB7891ED4EFF1D03D0991F4792FFAD9
+:104AE0003B762FB72FA5F6F2FD5713789C9B6D9C54
+:104AF000D7124DD78B7EFF71F5A2DE3F37FF10D95D
+:104B000005FDCFC7C369D1F0AB8FE8FBDF6C8B61CC
+:104B10007F903C003EC776CC169A87791FDB1EC378
+:104B2000F2EB589294135F903C0DF4C2382EFF3D87
+:104B3000F3E95B53F8BCDFFCA0F9BB46BF1FEB7287
+:104B4000BC3CC59B08BFB3FC0D290F895E57F0FB29
+:104B50006FD8F8FDE8793C87F7DA45ACD3ED71CC36
+:104B600017C73A487A1CDBD18BF55353925B30DF81
+:104B70006CB5C97A5BA833ECE063DB7BF96A23BED2
+:104B80007B2C29D4D91DF1BCC9165C3950CAD36617
+:104B9000F8C5228C583CF28B04C73F8CF74A9DAB7A
+:104BA0001B60A720BF373F87CBB023F9FC3CDDF16A
+:104BB000C9D29F1C3058DA0F9CB39AA6E793B3DD95
+:104BC00013B2438E6BBA7D58B62D3ACF57D6A7187D
+:104BD000EFD3BA4B35F28A2D186FC89ECEF106E19D
+:104BE0007992C65BBAFCFA85C81F2FADBAFB5AD8BA
+:104BF0004FA55631CE4EE36A52541E47538C98351A
+:104C0000197664643F11F65BE7C1E7E2B4C29DC662
+:104C1000762BEBB7AE83A5BE035C47DF2B5BAEAC58
+:104C2000C6F70DF9C281C2B4563C21AF15F93D4D0E
+:104C3000A3F4FA0BCCBBC926EBA3E76D8C277FB09E
+:104C400094534D599EDF0F035DFEA2F2F9AED33FA0
+:104C5000E42626B761A7B5EA7B7B6B9E2D8D1F6787
+:104C60006E595F0F96F2AE94C68771F65C67CE2BD5
+:104C7000EFBDD10C5FB2CD0C67EF32C3FDEBCDB011
+:104C8000F78019EE8B7EF3A49F8D73CBF0B351C2E6
+:104C9000CFF638A49F0D187E364AF8D9780E3F1B00
+:104CA00030FC6CC0F0B3011BF886BF0D18FE36EA6D
+:104CB0006FD0F124FCE134E46B5658649E2FD1C3CD
+:104CC000CFE798A6DB4DE7524E3D2FCFA5103F48CA
+:104CD00079BFD0C5EBE401B4180CBD24D753EAB3B7
+:104CE0008EE032C4773DDACCC158AF6BBF9E07BEB1
+:104CF000ABE8DAC879AF4D2B5EEE790FB56B54E2B5
+:104D000005EC8A8AB55FCF841D95E6D14A06D37833
+:104D10002A631B560EE4B87D98E547638DE78D91B5
+:104D2000928E1C7F2956715306D52F486E337F28EB
+:104D30003AEF5CAC36E799FF54DE79341F1876E021
+:104D400023B6E60C37FBE9C31E469C77B112EF860B
+:104D50009FFE698C5886FB8302AFC83CB5964336EC
+:104D60009937B05AD92022EC93653ABE0D78CED946
+:104D70005CB6C7CFC1AB158BB85488EE5A7313FC21
+:104D8000EBD30B2C6C779F5E5050D80EF61FF96555
+:104D90005813B89F2B72BCB89FCBC43F5B92A3CE75
+:104DA0004D7430B5C7FD5CE673139798EAA7ACCE97
+:104DB00035D597140D35D57717727C4B16CAF195FA
+:104DC000907EF0A7005EC6798B4B403BB2533A2BE6
+:104DD00081952C97D72B7C6EDCB3745521F0729C97
+:104DE000D8197104836FE6E8FA45580376F0DD9927
+:104DF0005459FFA5D270E4367AEF84AF6E33AE4ECD
+:104E000039615977DF300FF2EBD77776D33ABC416F
+:104E100009A541F4FC7E80B61D7CF399B57112EFB3
+:104E200027EE6C975C03BBF350DEEB83D0DF369547
+:104E3000F3260C7EE96C9371BAF5838866644FACF7
+:104E4000AF93F9BCEBEB5262BB47ECBF18F36C01BC
+:104E50001D04CA6569A91C17120D9807D9EDCB600E
+:104E6000B79D3E24ED76633EDD97873B2EA1FA1B6E
+:104E700076C6307E3ED3FD86E37D5EECEFC1F98DD4
+:104E8000EABD9D55D803966D9BE147B852B597B0E2
+:104E90004E16ACEFF11EEEF75AF4AE2A709EE6F312
+:104EA00035A31306D377BEDA6EF38E27F8B6BA476A
+:104EB000EDF09317598376CEC3DCBADE8EBCE45F87
+:104EC0006C59CFCFE76D29E6BCCBF9A28AFDC8A308
+:104ED000FAB92C63DE0B0A94756EE2AF5E43241FB1
+:104EE0002E8895FB79C4CF2F615EA7B7283ED88F57
+:104EF0005716EDB417D3F3C33ABF7AA64D1B0BFE7A
+:104F00006B09C9FB395A5E53E5BD6357AA322FE6D8
+:104F100002F7F94C399BC5FC7DE5D9BEEC674D0D18
+:104F2000F7917E6CB6941F2DF52AEFC7B5BCB63F3E
+:104F3000750ABE576FE3DDBB05F60679FEDF22AAD0
+:104F4000708EC033AD41F25596A882FDB7E42F6F45
+:104F50001FC4BA5B92E5F4603D140D534DFC593902
+:104F600026CEC4BFD344B2E91CCD55482A8980AFB0
+:104F70001CDFCDD4FEEA2BFB46C9839CD67A96076C
+:104F800043A2CE011698E0722A6F817C129799DEB7
+:104F90002B17935BDBC11FDE28EDD6F25D491BB0FA
+:104FA0002FBEC022FDA1699A7C5EB1573E1722F642
+:104FB000DCB9749CC7477CC0746E5BDFE743BF1CE1
+:104FC0000FECD6C0719DE60C929784D1F2DE8D76FF
+:104FD000C4D3C85C6E469CB43C4030FAF58BE65AAC
+:104FE0009C1FB14AFCBABCEEAECB325AF9A2629712
+:104FF00039DFAAE2D0DBDCCEC8678CAE273B7D650B
+:10500000078C7BBCE2E37393DB9AEC88075DA975A0
+:10501000E47B29A2EF4B2B0B35F138A7EE4D7363E0
+:10502000DFB622EA9EB485433C523FE9F17FDC3390
+:1050300024ED8406BB8CDBBAF65978FDC97B79CEAA
+:10504000F1E5028BBC2F200A2FE37DEF727F1D322A
+:10505000641E1AF0628DC04B341F014FD6083CCD40
+:1050600013124FF3489A0409EE003E8BC4CFCFC40D
+:10507000D77CFC41F5F3F72A41E4BF45E3679ED6B0
+:10508000C8F89BA7B9AA82EEF3E75371CBFB0721BF
+:105090009F7664C87B0DA3F1375F34AC84DF3B9F00
+:1050A000F4463889F9C2EE643F4DF1426F7B063514
+:1050B000DA6D529E719CB7E5B5B779DDB578695563
+:1050C000832F04D5537B97DFD3BCAC8D3CDFC967FE
+:1050D00065FCE4AAB3562EAF1C6F5E7753CFA6F1E2
+:1050E000F39F8B970AE0197C8EB85E421BF7EC2188
+:1050F000CE9770FE7C8DFD10430EB7DA75E6BCE5E9
+:105100000BD97FD171C21B87E871C23C9167CA5B22
+:10511000BE80DD119DB76CE8F11697D49363D5EC92
+:10512000373C34EFE25754F6D33DD3C659F8FCF878
+:105130002BF27E3C6DC59926F0A7166F6139B83801
+:10514000BE2BDF6BA1E971BB73F6764D4A1AE27F85
+:10515000C5316ECEC72FAE518BA0BF8AA99D27A2A5
+:10516000DDCAE5DD3A432F7C727BAF8703B45E3E38
+:10517000B929350D71FF4F57D85249729E6BF7C947
+:105180008AB19D919FF1E9DD8E69C136F0F3D010AF
+:10519000195729BFF57DD65B272CAF254CA3F7CB3C
+:1051A00056EC4E40DA7FE98AB7F3DD6452F80668C0
+:1051B000EB86E421BEB77EB31BF872AFE7FB04B603
+:1051C00093B8043E8A57AC60BA2F52E47EF50D4A7C
+:1051D000F8C8486A773CE6EE8469443F8DFE87FD57
+:1051E000C3331BE3F5F368359C37743C96EC016AD6
+:1051F0007F3446E2F3E8CE782FDF89E10D7466FF55
+:10520000AD9DDCDF29B5D45F85F14C4CD5B60FE1FF
+:105210007DDEE0E67495DBF1B975ADA647625BF122
+:105220000FA3DCACEB69D8DB28616F235F06F63691
+:1052300060D8DB28616FE379E55AB3FDF6B2BE5F53
+:1052400068C483BBD436FB60EF060A44EF2AD6B3AA
+:10525000E30BFE08BDF58AB4179628DE558D6C2F3A
+:10526000C5D7C1EFACB54A3B3BF0B13C1745FF7A1F
+:10527000433EFD5ABDC48BFDFCFBE36E7D04ED9700
+:10528000627F6800EE3D25DB2B825F479E758AC8F2
+:1052900073B7A3C8088B84473B334CEDC7BAB34CF4
+:1052A000F5BF48EF63AAFFA5C767822FEF3DD8D4AB
+:1052B0007E82779409BE62D02F4DED27F92799E0C1
+:1052C00029E3A69BDA4F2D2A36D55F3D6DA1A97E35
+:1052D000BA76BD09BE76C14DA6F6D755D598EA85F2
+:1052E000A87A0CF8F107E43D6CF5F09F1CB8FFC5F7
+:1052F000C925D5FF0979CCA348D4F3BD2B7FB9F1DB
+:1053000011C0FB90D74C2B6ED8684B555B71FC1FBE
+:10531000747BE9EA61FE6F87B03FDDC0F7682276F3
+:105320000BBE8B1BEAD1FD5FF9BCA3D5885B35644E
+:10533000F07D0951ED2FD46E58DCBED31E62B92525
+:10534000431FB8CE4AF26BD8C07DB9DD08DEFDDC64
+:10535000C7121EBAEFA9AE043F3FB4C74C862FDD7B
+:10536000771AF5970F6B92F553049B262F3FB7E200
+:105370003AE4A70C1BD975B557C645DA3CDF6E94E5
+:10538000C013CE85034F28C3C4F728F711DFA33C11
+:10539000407C5F4272ED20F13DCA43E467E2F9FFD1
+:1053A000213F13E56BE467A27C9DFC4B940DE45F09
+:1053B000A27CAB7A1A97EF546BFCDE5FAB1770F9E7
+:1053C0007E75153FFFB07A29971F5707F879CFA14F
+:1053D000328EE022BD03FD5E813C18E40B44DD4BC0
+:1053E0002AAADC7CFF41ADAEB744BD9E57B38FFC0B
+:1053F00057E0B3D19A74C4D9BABF78617FDF2A8EDF
+:1054000044D86D5758FD3943998E1DDD2CF7F5E7CB
+:105410004F7AB5814389EEEF664DE991AB42DF5596
+:10542000BD944875EF5ADABE7F326EA8E497DEC3AA
+:10543000FCC3F0DE70E761DE4FF76490B53A94612B
+:1054400005F4577264FC72B8B5A116F5B5DF0B0F01
+:10545000FCE617E3FFCAFBE0B5642EE3FCB172562D
+:10546000FA2B23F4FDFBDAEFE5FEFD088C9DEA87BD
+:10547000BB657DED5CD2743ED487F8FB2370DA59AE
+:105480009E6F33E5ED8C39DB309AEB5D760FF24D94
+:105490004738C3F27B4EE1467CF9C5F83DB2FFB117
+:1054A000B2FF8DDF87F9FBF03E91973DDCD93A9E44
+:1054B000653CBE06793F5DB66C5FABB71FA151FF7F
+:1054C00049185F951C5F31B597E367393702DF4CA8
+:1054D00082B72DEB63D3E5F9E43167F57AAF9C6FC2
+:1054E0007BAB8471A604F599299AF0537F9999C2F0
+:1054F0008BF8DB88D4860C6EAFE733C45BE5F7121C
+:10550000BDF23EAEEE7FD7E47E002100E337F2929B
+:105510008C75DB29399C013BAFD3623B7F2F53DD78
+:10552000E983BCEEE3D37E0D7EB03A2D3CBF5ABF7B
+:105530003C2FFFE6F39E4EB88F74926EAFFF13FAC6
+:10554000DF82F7873B5F90F4C7256F99ADB0328F4C
+:10555000FE37B84DFA4B7C11BF60FE447FA607E8CA
+:10556000A9D35F31F0A3D3FF1CBD9645D6EBFC71E8
+:105570003EFD4392DE3A3F8D70CABC09B407FD87F9
+:105580005B253FD4C6C87C8F17E30B1FC03D5984F1
+:105590009B22C4E7871BFC5225CF0FFF6FA5FF009E
+:1055A000ABBC47CE51E6E47BEA7E8A1F66358B4270
+:1055B000DCD379CAA7C5615D179FF51C043C478CF5
+:1055C0002A84796ED49FBD40BDF64DB30DB0F1BCB9
+:1055D0004B8E6C67D45B9D6FC541EE19DF31DA8D60
+:1055E00038AF5D8E13FA62C9D8D03AE8AF7135563C
+:1055F0008E5B9365C2F021D267329FD39FE04B8BC5
+:10560000CCFFF41E583C00F78BCAF35BC225ED6A51
+:105610000FFD07B95AF843D172F427D46D56F81D1F
+:1056200067904F4BDF294C35DBE7E3A2F6D72FCB52
+:10563000FE82EDF1CB7EE29EEBBF0DD5CFDF64891C
+:10564000ACFFE43DA35F48F97C71F78CF616F5CC0E
+:1056500007638A653E17CDDF9283B88D5F54012EB4
+:10566000145556F0C1385167957EA5FF78C500F6F0
+:10567000DA193F978B303F9F400A05CAE40A621F40
+:10568000C0FBE326CEC0FDC1A3734777C7F388FBF9
+:10569000F37EC0F82A54ED6FEE88FBF3F68D91EBA4
+:1056A0006DF154196FDAE7ECD6A61DFA0AE9DBEEC4
+:1056B0003D8017C1E54BA48FBBD3BC5F267D0CF8A2
+:1056C000B2DE35BCAF5CE831E71D19EF5FEE1E2D91
+:1056D000AC2917D67797F77FA623F0FC6A52AF3133
+:1056E000A0D7AB4903C7201EFF6A527B8B2C1D76C7
+:1056F0002EFB3DDDBDADF119EBA3B5BF42EECFB83A
+:105700002F784C3B795F70345E2F1321137EC7EBEB
+:10571000F8FD1978ED352CEF7CBCC6E1B0631EF0C6
+:10572000F9F61E236F0AF1E4EECB1B18BEC126D793
+:1057300041F9D3130A9017BDF85D99DFF125860270
+:10574000BDBB74288F7FC4D2C1C29ACBFB5101E08C
+:10575000BBCC29F17822F0627FDC6BFE528A3608DE
+:10576000FD7FB14EE5F3F6279E8CE178DCD1E05366
+:1057700009C0A7C1C765AA67B517EBF05555DEB3D9
+:10578000F4C3FECEB887F4427C4DFC3C6A585E1BE5
+:10579000FCEC227EEE773E3F8B8DF21E83326761FA
+:1057A0009B7436FC4E678E3F0E7CE816E1EBC1FF22
+:1057B0001542FA4715CED7E43D9504E3DC6BB45DA2
+:1057C000951F4BEDA9DEEE94F9C206BD331DF21E06
+:1057D000CBCC38E1461C4468B997705CBE9B7F1AFD
+:1057E000C64F7EEDB6C8BCB511E1BEBCEF3CEE9035
+:1057F000CAF9EE2FC7CA7BDF1B891E0AD9A7BFE8EB
+:105800005BE5EA4A749C99AFCD198679A93FA8E86F
+:10581000F7B51E8A48E1F879AE8BFDEC9FE9AF97AA
+:105820000ED3FDF5FEA2FF3FFD3D8576F2DEE1C51C
+:10583000AFE40631EEC535A4D552F97731F89EB8FC
+:105840005AF8E759AD726784E8C9BF97313AD5C6AF
+:1058500079E6FFDB7E4F215368BCFEFEB3BFAB3061
+:105860004E3E3AEF77153213561DD0525B7F5723C9
+:10587000FA771532F5FBAC8547EA0FE3F714460AD1
+:105880003FE7E58F4D37EB95D1EE5107DC5C9AE3AE
+:105890003D993F91CFF5F8305DAFFC14DDCB854EDF
+:1058A0007779AE137CA0FF3E4A10FC69FC3E8A412A
+:1058B00077E377526ADBC9DF49F957FB5D9468FAF1
+:1058C00044FF4E4A347DA27F37658416CB781A5D3B
+:1058D000E662BE36E8348DFE637B00E77295FF7E9C
+:1058E0007A3546ADD33362751EEE293D552CE5FA67
+:1058F00085F4FF835EFF11C88B6F114FC27917A724
+:105900008C87F86BAD226684C0FD849C2FFBEB5A1C
+:10591000790F54AD55C603024457DC8BF75DEC3F5D
+:10592000E47D8E641FD93A202E53C5EF07EC4E77E5
+:10593000AD17F44E603E59BA549E073E6CA9E3DFA2
+:10594000BB98955DA560FFF268967616FDA78BA2C1
+:105950009DF3382E5F3510F27DE69F1D9D513FB3BC
+:105960008BBC3F526437E645DA233333F53CCCE158
+:10597000FA7EBC57E661A9C3655C2DDEEBE6730DCC
+:10598000C5D942CF6F159D67F6031F7FCC767C8B00
+:1059900047DAD58D36798F65E01599CFB3AEEA2D0C
+:1059A000B6FB37915DAB4AFB66ED9D1C674810D88E
+:1059B000C77D24A63909E3EFB55698EC853E41A78B
+:1059C000292FB9EF16B709EE174A37B5BF74AFC71D
+:1059D00054EF0BF736D5E71EF29AE0BC8641A6F6E7
+:1059E00003DFF79BE0C18DE34CED871E2D32C3C36F
+:1059F000BB4A3C8127693E3397B883F21E7D192745
+:105A0000E96297F654ED4DD29F30F2D7357D1D44B3
+:105A1000E7AF77B2CAFC757B95D46B9A4BFAB7EEB9
+:105A200064E156F95C4C03C3B81B82F3C603E63C41
+:105A3000F38E4EE95F59C648FFC3AEE799C7F696A5
+:105A4000E75E8CBC72F22BFCC07777D1389D7FEF7C
+:105A500040BF4F349A9F7FA1D33D7ADC5DECF23C8E
+:105A60005DED4D76DE3FD75CF62625E1FCF1540D69
+:105A700094FCBFC9D9F6BD4F53753E7B2CB768C2A5
+:105A8000702A1F26B5C5F6D779FD791B21EF6A7FED
+:105A90006BE7BCF19FEA6FE6A5723E332C965993F3
+:105AA000B2D91FE4738046BF73F57E7F39526973A4
+:105AB0007E33139BF9DE359168F7807F35D74A86B0
+:105AC000DDB122496D03EFADE732649EFE75AB4355
+:105AD00077F6A271CEB0D7D9E48503411BF8617C7B
+:105AE00001D991B43E5EDE33FC2117D1E3E1A55626
+:105AF0008E83950D7F6666A03BECCC66E60724A2FC
+:105B0000603F11F6A79AD33AEEA611328FFC4E5C95
+:105B10002CCDE7257EE071B5E8F19116113A777E3C
+:105B200022D006BF69AE837C0EC1BD58F253A78850
+:105B30007356F03FFFA7CE4B08EC90523FB63A2188
+:105B4000CF39FE04FE8C732A9EEB6D451B5C382F0B
+:105B500022C6291178F866848C5BFC79B8A437DA00
+:105B6000411E5DA81DD97D89D85F68119E44F74FFD
+:105B7000C4D5FF27E69F69957186CE4E795EA493C2
+:105B800055637961EFADDF73771EBFEB72438F937F
+:105B900075B4CA75DFD12BD7F5F972E1007FDFAE9E
+:105BA000C97BD3A2F1CBFF22E22AC6F995D83152A4
+:105BB0008E1872E1DC39941ED20FB5E9F221D8DDDE
+:105BC000C27907B7C59BD771B32E1FEE31F445805C
+:105BD000FCF87C939C10D8D7AB5DA1B29C2039799E
+:105BE00050A37116E35E1677EBEFC3CDBD57EAB154
+:105BF00011FEA2FBB06F327B8D4DACE77D05793F86
+:105C0000EC7C3D4E5E1C88BA9F45B7C7CFAC56DCD6
+:105C1000F8DD8839ABCCF5F35D473E86FF3837FABF
+:105C20009E1A63BFEE27E2008DC3757BCD2BBC7A35
+:105C3000FEFD328CEF4C50DE7B7DEEBC921EFF6988
+:105C4000093E25E15B8488FC1D09C32E30600FF6F8
+:105C5000C922EE6121FCC6F6867E5F6E6D33BFD130
+:105C6000C0EFB93C0F7D9F8ECA652BD89F91F90D6F
+:105C7000240F785FEE38D5C30E3C1E38CDED8FEF84
+:105C80008AE1BC9213BE86FED8BF35F6E9BA6B72C4
+:105C90001FAB6557BCCC6F705924BC45DE63BFE8B1
+:105CA000EFC1FEF0631B034F99CE39688DE67DBED0
+:105CB000E852ABD9CDFEA66F80163382F8EA98D5AC
+:105CC000EBF4127CBB6B1FDFD3359EFC47C835E479
+:105CD000A5AC4895E367F915382DF15725F17705FF
+:105CE000197A909FEF0A929E88630AF26AA92C0E95
+:105CF0000FE6FE7FEE3ED894B33EB9FF7B7628BF19
+:105D0000AFAD1ACC70EF60F3A8F7A9DFAB349707FB
+:105D100071A4A9B5BF1E1B0BFAFFD1B582CB4EE60D
+:105D2000F30346D97B84A44BA3ADEDFA3F8E90EBF1
+:105D300063CF08A1DF5723F97D718DC2FB6A8BC148
+:105D4000E380EF94F7731AF0E93A1D1E2BE1252B3F
+:105D5000240CD5043B78B6FE3B699BF5F80BE68F27
+:105D600012F3475C609B1E9FC1FC5162FE780E7966
+:105D70000518F20A30E41560C82B94905778FE7924
+:105D8000D268DED7C6BEDD9888F5847DBB3111EBC5
+:105D900003FB769130F6ED22DB63DF2EB21EFB763D
+:105DA00091F5D8B78B84B16F17D91EFB7691B018D7
+:105DB000F4CB561872CD3FC9044F217F604CC47A92
+:105DC000C6BE5DE4F7B16F67FA9E76BDE9FD6BC5AF
+:105DD00052D3FBD8B78B6C3F6BA962DAD72309C8C3
+:105DE0007A7DCEDA14E6A3645FD1BC1179FCBB5690
+:105DF00037DABAB27CE038C6E2F258AFA477DD38C1
+:105E0000497F8B3C1FA134F3EF0B9CBEC52EE1B143
+:105E1000E6FC6DA3C4BED7189BDCF742897D2F94A6
+:105E2000D8F742897DAF313DE4BE174AEC7BE139BA
+:105E3000F6BD5062DF0B25F6BD5062DF0B25F6BDC7
+:105E40005062DF0BEF61DF0B25F6BDF01CFB5E2817
+:105E5000B1EF85E787691C2511720CF67A77939F5D
+:105E6000497C68F233DD2618F67A647BD8EB91F52D
+:105E7000B0D723EB61AF47C2B0D723DBC35E8F84BB
+:105E80001F1BEE613D06BB3DF23DD8ED9170BFBAE0
+:105E9000C04B88AD4D5877F200CAC678E5619C3793
+:105EA0007CEC852B6659491F36C6289D9348A6DB96
+:105EB00094A9B3C640DFEAF98FFD45B305F24783E5
+:105EC000333980CF19725E69BFEF33B8FE65E35C8A
+:105ED0001CFE11DD7DBB04FFEE8CB1DF6EBCEF2537
+:105EE000B58DD268DF0AB7DD2EBA7FA31DE7564510
+:105EF0008C03279A9137E3BBC595033F64B345E113
+:105F00003C93CDCB645E74345F7DACDB479B2D3B13
+:105F1000F7E11C4C73B1E2C5B98FEE751A9F33EBF4
+:105F2000374358545FEB7C7A3D92C079B50746C839
+:105F3000389F317E233E4AF282CF0F0E6B6E189D42
+:105F400048EDB5C028FE1D9CF176693790A5310457
+:105F5000FE64DF80E2DF10C1E7AFEBDFD302721C2B
+:105F60008F3D3251BE172BDF7BEC9104EE7FE27246
+:105F700085F3CC866D137E9C537E4F97AF7DB7859E
+:105F800055F457BC5CF6677CB7785D673BCE731BF6
+:105F9000F82A168D63709FB418A0E04E59D1D3AA89
+:105FA000B15DDA7E86DB023BE862CF410D1F9034A3
+:105FB000167988A25EF0BDA11306BC699A2FA32BA7
+:105FC0001FBF832AD837D402D75BD0EF4442400AA0
+:105FD000E2C904633E9A26AAB208BF574D2B667CDD
+:105FE000F79E2114E0BBCF8CF596547AAFAFF6A2A2
+:105FF00005F65ABFBA462E8D79788725A980C7DB6A
+:10600000DC6331FEF16315961FD1793CB00F185E49
+:106010006E637D6ED80F8BE3CFE5F9BC873C9FD3D1
+:10602000876C9CE7737AF919AE2FDE1DC3793DDAD0
+:106030005A85E59A613718793B65D7BF9B0FFC7C81
+:106040009515DC9CD48DF5BC7D24F269BAEE4CC06C
+:10605000119CE3CB775F85A37BA797EF96BF57ABE8
+:10606000EFEF18BF7B2AB2FD9C0F66D88142ADB717
+:1060700047EEE318BF9F46F293DB9DDE6B77F3EFAD
+:10608000D7E9BF776AC47D8AFF927B10782D7E485E
+:10609000FEFED9EC5577174E23789EDF19C6EF62C6
+:1060A00045E7632D8CB2037FEAF74E3D23F5F84FA9
+:1060B000ABFDC7FC72E63569FF15FF65FF5469AF9C
+:1060C000D838EF7F468D8CD7899D82EF3F9A513328
+:1060D000DA827BA467ECF67B154FAB1DF8866EB7B2
+:1060E0004C3E9BC9F87D5BB753A622FF94F03BBEA4
+:1060F0003146CF57CBE0F2EAB3321F75B24BAEF761
+:10610000C66704DBD32D0187CC23AC177A7EAB990D
+:10611000EF7C82F883E873895FD98FB4E509B07B9F
+:10612000E87BD36007A5808F8B57205F96DE66BB28
+:10613000339A8F275BC357E2FB93BD36E6AF7FC62A
+:10614000C7B897E39C5C12552FE19CBFD8287FC746
+:10615000619A26F9BBAFCEDF33E3F4F8934BC697D1
+:10616000CEC59F3048C4CCC4D659C8179E89E48593
+:106170000E3C2D3FF2F5E2B365FD3523B7CE5A0E46
+:1061800067E6027109F5663BDF5FADB99CFC3B3405
+:10619000178A13203E00F978DD0D3EFBEC08F95814
+:1061A00030AA608D3F2FE2BCE3ED320F6AF1ED3D86
+:1061B000DAB775DED628E7107EB13E662636DE8871
+:1061C000F3E64B470AFF9841F27726E5BC4418797D
+:1061D00098D7E8F0C63F37FC6D958BF1C1F00D7F85
+:1061E000DE330BF7C7953B1B0BC16E95D955E3907A
+:1061F00077DD2A87347F6616E4D0A830E4D085E2C4
+:106200000E1B474A3A44C71FE6644BF92CF4FBC205
+:106210003FB9FDE91D90E7C6F83FB9C0EF63AC1B7D
+:10622000A9EB89EAFF9E731ED1E73BDEE8A3DD35CB
+:10623000B21D7E97C7DF843CFA0E6A9D9E3F2BEF0E
+:10624000F530E81B53F71DC73B4AF4FBF0499EB0FD
+:106250003F39DBEFF4D6408EF4162B715E68A62A28
+:106260009A79DFF83CBA4B3C3E32FDEF0B918FFB45
+:10627000C86F63E5791D1D7F33EC0D2F39B35AF1DB
+:10628000F7D1D23FD8A4FC0AF7C0BEDC3555319C0B
+:10629000DF5630AAE851C8BBB86C2FDF83B1C62FD8
+:1062A000F9C9DEB568339E97AF7EF161DC9750592E
+:1062B0009FC5BF2B53BCD7B712E71C0B46694F6075
+:1062C0009EC52E37DF1B52B13C89F5D3CCF67ADC64
+:1062D0005534F33E9C81F7037A7CEA9E51F2FBA78A
+:1062E000743F03827092A9DD85E27432FF06F939AA
+:1062F000883F6AAE3D1C2770DF2CEFA9B08B776416
+:10630000FC31BDEDB841A61E6FCCF0CAF89081BF3C
+:106310003B7ACF66396733E2B9E7F0673E8F69941D
+:106320006EBFD4EFB36F50D85F2D59A3F2B9F2B15D
+:10633000EA78BEC765F1DD8A87D7D7BDDD38DF7B58
+:10634000F1ED648D7970BECC53D87E00EE5B57DCE6
+:10635000B04B66801611F19D92B58379BD9504A965
+:106360006CE35E53A3BCF6EEFD9D9EF1808C7EDE59
+:10637000BF2C71FBEDC911EB7D4E9D62BA5FC180F0
+:10638000855FC6DB66085290348E19DD3D0AF6152E
+:10639000DD7E8987EB6EC8B2E3F74866D0972D396A
+:1063A00017EEFFFF95F2FF02371C2052008000001D
+:1063B000000000001F8B080000000000000BE57DBE
+:1063C000097854E5B9F077E6CC99992433E1640172
+:1063D0009200F1241088803861A72E1C1202130845
+:1063E000305940F086308120A1456F0497D04699FE
+:1063F0009085104143890D52D461F3564B352ED709
+:1064000042C57600EB525131486B1793617169DDDB
+:106410005228B5BD0FF7FABFEFFB9D93CC39990415
+:10642000B4F6FEFD9F3F3E78F29D6F7FBF777FDF22
+:10643000EF243F9DBDCC2632D6B54D90F7A4315602
+:106440002EABB6F14EC6BEC49FE98C2D6F16D4C0DC
+:10645000D89E727E3A5BE68572B4EA626C1263651E
+:10646000B2624B4EC3A76C8B87F7CBEF3822B14497
+:10647000C6568C604CC882F6F16E9B13C75F0DE365
+:106480000B8CDD2C0773B1FEE6B10AAB8983F67580
+:10649000593606F3F9B6F0797C8D71B66BA05C665F
+:1064A000956DC3A05C12CD18B687F505B07F795005
+:1064B000B5C53B715CB6ACD0C9D71B1FB6BE326D3B
+:1064C000BDE5CD71B69586F7DB2405CA4B1853DBC5
+:1064D000C2F6A73FA7AB02ED67795D416A2BACB767
+:1064E000DCEF9271DE72AB6A73E3BA705CE8B7A45A
+:1064F000A5554A0BEB7F8D6AA17ED355859EF9E9A0
+:10650000C10C01F77B7B941BD7BB446E96109EF9A0
+:106510003A9C1FE4705829073370FC950E0E077DD6
+:10652000BCF2163E4FEFF5717897B794D914A8BF17
+:10653000C5EA4D6D85FEB7C03AFDF05CB2E3488612
+:1065400080CFCA28B700E7C1645FAAD7D5D3FF833D
+:10655000076F4AA5FDC3FA11DE2EB7322B09D6B359
+:10656000A21916A3D093E62D9DC02ADBC2E0769334
+:106570006A656C203E2DF464CDADAA6310C083F132
+:106580009FAB6C2766E03E6AAF666C23ECC3E77C8A
+:106590007E06EE53FE2E63E23458EF96B7A97E4591
+:1065A000129305A8B7B1E704ACB795431F28337F12
+:1065B000AE1ACAE4637D99CED8301C19DA3B017F4C
+:1065C000FCC98C554E5168DE252CB4840D8771B6FC
+:1065D00014C01CB0CEC17C9DA50358E53311E0D595
+:1065E000A2ADF766EDBC4B2CEC2516DF537FAF76E2
+:1065F000DE2588CF61FD713C1C778D5E9F1DCCB878
+:106600007D6C4F7B7DDE9278DE0FE901F1708D8627
+:1066100007D87E2DB5E7E55CD1B9B11EF6B376ABF0
+:1066200018B00BF8DC5B3F08CB4F0B6E84FBC76BDD
+:106630007FFAE62278FEE907BB4B717FFA3A56FEF5
+:106640002D8B290970BE7FBB8E9EE5C1694C99D008
+:106650007B9FC7A6F8BEA74E0AC39FED3F19E983EB
+:10666000F93F7EF2F50C84F31F00074480F3BFFD71
+:1066700064AFC4D27BD6BFBCF16DA9CC190E2F81FB
+:10668000E0D594D94EE7B72293F75B51F7E7323C58
+:106690000FE6B4291969BDCFBFACEE69DEBECA4DA5
+:1066A000ED7DCE5FF3F34F61B2987CF9F3D6CFD78F
+:1066B0007CEE8F48DE609280E7D36CA07FF3FE1FF4
+:1066C000D6D61DD0E8EF660D8F6FAED846FD963753
+:1066D00096ED1561DD4B74FA2D37BED7CFE7FC166A
+:1066E00089CEE7FC968C86242CB7F1F3F98ED83648
+:1066F000EE6E68F7F19AFDB725A7E3AA03A9DE6B52
+:10670000F8F9B009FC7CF0B90ACE8725443C9FA774
+:10671000C2CF67D5A3FC7C563CF9C67B3F5308FF2C
+:10672000F8FEB6DA03C87F97B73D7DEA5BF07E4995
+:10673000E336290DDAFD424DA37DE9FD575466C9C4
+:106740002C16F6D7B85B423EF00B558988E73A5CC9
+:106750009995F399472438DB38AA67427C4FFB258B
+:106760004C1D8C7C84F987B2FD89BDD7FF278D8EA7
+:10677000F2D3DDB6C1C8BFEA63D81E19D751763F40
+:106780001BD7BBBDFE3C1BC5E96239CC83F47976CF
+:10679000863B15E9A2C46231D09BFE3CADD1D790B7
+:1067A00098B625B8DE21094CAE0510FF305ACDB69B
+:1067B000C0BC3FFC9643AE75637F9F82F57607931E
+:1067C000FD00F23D16653CE1276C795332C232344C
+:1067D00009F9DE8835A13FE3FA109DA2C6F3A70BA5
+:1067E000F66D9FC1F104CA6C107F1FC4E7306B1BAC
+:1067F000F1A9E82A8E7F36F60E956DC0B7106FF5B9
+:106800007E43D80901DF27C35A70FEA6CCE5747E0B
+:10681000D2084E2F7DEDEFCB2BDCDFD9345F80E447
+:10682000441493F7C4D1FED662B97B7F994CB5402E
+:10683000FFD2EF5DB3BB09863C5BA31EB541FDD91A
+:10684000F54EEAFF4DEDD7BCCF25E565867D76D3C5
+:106850004D33F0B5347C4E48C5759E77C044507FAB
+:10686000F6F6280BC2FF6C1AD717180BB90AE15CB1
+:106870001EDB00BFDA19FBD106073D9FD800C834E4
+:106880008AB1031B92A8FCE406859E6D1B32E97D4C
+:10689000FA0C8E7F25D16A2CCAE5AE1A97BC07E1A7
+:1068A00011E474D351359CE0007A02E7C79A5ED0B8
+:1068B00021875CF1617C1AE4C7569477AC6A38DBB7
+:1068C0000F5374349F7559C6225EF2F5E9EDEF90CF
+:1068D0009AD97A6CF79010D80FE3C6DCF176EE60A7
+:1068E00094D32D695902F45B5A7581F8E152E7207F
+:1068F00085A11C77FA1AA660FD8E347923748B6902
+:10690000C9EAA882FE2BEB46B9B1FD1D82D240F345
+:10691000D6086E9C177E54C764E003F81B94573961
+:106920005F1EA1F14B0BF2CB15F7AF6F4886F269F2
+:106930000BEB120134F996825958CEDF19E7AE45B8
+:10694000795BCBF7C376011F75F4F05175AAF7FA9E
+:106950001970CEEC12E01B8C3F1AD6C644DC4F9B5C
+:106960008AEB67A077EC67B85EAF0DFBBFA0F1CBF9
+:106970008E96D32E453B9F02A41B5FD7E94D78AE80
+:106980004E8BBB4941F9AEBCA520DC5F13D91E0577
+:10699000F187D7AF75F17A786EAC87FAB5BBC500D1
+:1069A000C223572C191442FD6B87487C71E5EEA277
+:1069B00041A86FAC8432CAAF9D3815E053434B0EEB
+:1069C0006FB72DF7077EE0A7A902F3223F3A670DC4
+:1069D00015203C3EDA3D38BE06F5BD5B6B4732A85C
+:1069E0002FDFBD29159F1FED8E5A8C7C7CA65C3055
+:1069F000330EF59F5D7159A2D243671533389D7DE3
+:106A0000FBD69CC128EFD6FCCFB1476490AB2B01DD
+:106A1000476518F7625B4CC00F4DD66C38982A0258
+:106A20006A39137D2B106EDFB11C5E340DE5B0109A
+:106A3000782C99DA2B83E54874ACEB5380C70AE0D5
+:106A4000E9ADF7BE4BE37C6A393E7F09F45F73EB37
+:106A5000B3B138CE771E3C395986F759137DFF8E76
+:106A6000E3FF49D8FD980C20613B768F43F95139FB
+:106A70008371BE1AEF5DB484C3D7BD47E97BBE8A7C
+:106A80008302C1532F2F0D0CB031D44B83CC26E39E
+:106A90005366A4077F24B22A94EFBA5EA2BFAFD593
+:106AA000E0F2D180E6543CFFD58FB5A6A2FCF8A356
+:106AB0008B977DFB5E59F95D5887AFC52233C03B8C
+:106AC0009F9591DEBBC2CFF5695601CC24B967FE14
+:106AD000AD336268FDAB774C30C83D908F34CF1F2B
+:106AE000ADCC83EBB8AAB62B0BF5A7DF5B832BF1FC
+:106AF0005C7F0FFAA93F0DCF89E3DFEF9BC559F803
+:106B0000DE7F87C032042C3FEB1AE1243DCC427C6F
+:106B1000FD0529B01FDABB26B60591EFDDFA5CDC76
+:106B2000780463AE387630E2CFDA43D2AC215C9F92
+:106B30009271F635D6A02DD2B97D5BD3A3BACBCF57
+:106B40003D6D43BC5F7300F401A4CFE78400EA37D6
+:106B50006BDA9E7E3905C6BBED60D9049C476F7F1A
+:106B6000DB731C0E512C642B0AD3ABCB32E31B8698
+:106B7000008F7C72C6BBCB1E842D95E1397D0BF84E
+:106B8000D7F45FFB6A46E053A67D326B17E9E3A0BA
+:106B90005FD950FEDF5AC7C7BB35B3BD219DF6553F
+:106BA00090C0C2CEFFA91912F5D3FBC3BEA95FAD39
+:106BB000E3DE4743B05EB5D6CAA26E84B295FDE16E
+:106BC00031841F8B95F7E33EACECDCCBF0BC5B1C57
+:106BD000C09AE0B9AB72ED7F50FB1ABB2CC2B3F682
+:106BE000D6EAA742309F22322F83FEFEEC4A1ACF0C
+:106BF0006FE3F2A735E6C9876E817255B1D30DE810
+:106C00000DE55882CFE1BB2CC4E79359D7310B3C3B
+:106C10000733A02200D04769BEE3C47718E7C777DF
+:106C2000AF5302C88F61E502E2F9E72F7E3801D742
+:106C30007DE355A10B885752CD87BE9940FFEFCC1D
+:106C400090B97E32363401DB0D3CAAF135EB099266
+:106C50008F5292128FFA4A10C7C2F5FDDD4278704A
+:106C60005808EEC5797538456573FDEFEF6EDF7B2B
+:106C7000B80E5590EE0C42FB0542AC1BF77B225E32
+:106C8000CC180FF4FCB9F487341CD70F682B0EE92D
+:106C9000D163B3B5A5DB52A6EE40B8CC0080B2EB11
+:106CA000C196191BCFAC50BE8F59BAECB08EECAE6A
+:106CB000DFEDAE81B2FCFD014C0451551B95CAB20B
+:106CC000617CE1286C14F67374ECD115B8CEFBBA74
+:106CD0001C0CE1C41C463DD766490E7E0FF1B9324B
+:106CE000D6CD92500EB565213F62B739DD4DD07ECD
+:106CF000E9A550C6BFA35CFAFB71D2D347A5FBBE82
+:106D00009801FB4A11D5D33EA8BF4F0E0E7F00C796
+:106D1000AF8A71D77039C2C2D77F78FDDF6313A005
+:106D2000DFE75D23AD4F41BBCF55871B3458D6F10C
+:106D3000DD312F5D07E5EB3579625ED7E7498A15CE
+:106D4000ED8ECFBB1C41D4433E775A02028034FB08
+:106D5000F0B1770590DFD90E67508CC57ED227E160
+:106D6000F2869D1816F7C1181231EC4B80E7204DC2
+:106D70002EDD38C0683FA664733B28259BF31FAB0C
+:106D8000E226389FF75B5913E2218332CE6B75C838
+:106D90004DB0BE9F3B1F5B0A94CFCEFF2D7D00CA36
+:106DA0008DF387870F6063FBE68B27519F003D6162
+:106DB000D178352D7B528F7C5DA8C125AAF9260993
+:106DC000E1510BF06802782C745A8276D8172B3672
+:106DD000C28155759522DE304BAC1BE906CF17CF2B
+:106DE0005F112C5DECBADEE73DFD921CFC1E949712
+:106DF000C279225C4BCF7F70CD038CCEED1A5C073D
+:106E00009C63FDB5ACE7FCFED5CE8B59DD8D780ECD
+:106E1000778BAE663C875A2BD7F7FC805BFBE3A8E9
+:106E2000DB63782E77D78EA0731A540B7C02ED9417
+:106E30001A2BDB93887CA59DDAEFD7F4419659494C
+:106E40007CA6B4D62E23FCBE888EA5FE0CCE554A59
+:106E500089C467385FA92A67C457968DAD14F0DCE2
+:106E6000937006D84F8725E4C27D86A2408B84E7C5
+:106E7000FAEC74A2F321C81186F373C6FE0FAF7744
+:106E8000ED417E233A863C7C0E44116BEC8A1D0D4D
+:106E9000EB6A11581BED4BD2F8C76A27E9732D71C5
+:106EA00001E26F2D0B87BA71AF9F33ADBE229AF806
+:106EB000CB75160B95BB960C227BAC250E582B8EF2
+:106EC000B76434E90DCFFF8FC8EDB50CC6EBB3D86E
+:106ED000C81D585F9049E3BDA0F3ABAD2E1AAFA516
+:106EE000404D8EA6FA4116EC5F9EE65B87F8912234
+:106EF000F276A07850BB9D3BD5643CCF9D85366A29
+:106F0000F703C1BB64258E738D93F4C6D092E82736
+:106F10001FE3C71944FF524715DFB74E0795533893
+:106F20003FBDCA7FFA21E41FFE6C381127CA8BCF00
+:106F300096225EAB62AC1B50B8D7397FD18DE7ACDF
+:106F40000B80CB12A33BC85E573218021BCE4F6694
+:106F5000D98827C7009ED0DE2FC13927F273DE986B
+:106F600088E73C7F77F839C378FEBBE1BDB036D601
+:106F70002D4CA573CEC4F1AB58B41BEDEBEEF3FB77
+:106F800079200B9FA2C59D6407583C9FEE7B307B08
+:106F9000608F1C79F83DD81FC0A5D41E9AD48CFAF6
+:106FA000B98555B445E0038F6673FB40665D12CA30
+:106FB000D7653AFE579BF03F3434EE83180DFFA19E
+:106FC000DFE1C1DEDD780E9F0A2727E3CBE3FF2D4B
+:106FD0002E8E34FEE39A7C792BD1FB235CDF08EB09
+:106FE000D1A1EB50DF586F27FD975D3A3614E7AD1E
+:106FF0004EF3FE18C78B1AD16543FF54477297842E
+:10700000FBEB58F2A761A8672DAB7A85E8F34AD766
+:10701000B731669C847233CE932585A0FF604FD62E
+:107020002FF15CDAE7D9157B043FC891795386A12B
+:107030003E74326FCA30E497278701C9933C75BB11
+:10704000908F4A07AF71E13A4F7A265059618A56BC
+:107050002EEA97BF7E0CFC35088AC01FC15EC3E7CD
+:107060008760AF0581DFBE0FF61A3ECF82BD86EF87
+:107070004F83BD86CFCE0D6E7A7FD233FC20E2C522
+:10708000C566EE4759617547D4CBD61C105950E7F9
+:107090006FF0EFDBFB620CE58A5D0986F22D2D8037
+:1070A000418E9E72F996E186B2AE7F2EAF1B637859
+:1070B000EFAB9E60286F8C2995F09CE28AD3387CD8
+:1070C0008BD308BEA7F2FA806FDE28826FFBC25115
+:1070D000C3107EED085FD48BAD8A0BE1271D5CEAFF
+:1070E000423DA6BD78389501BE5B27E2789A1DD552
+:1070F0005EDC3F9CFF88701E85F07568F095099EE8
+:107100006735389F46388F42F866D2B31DE10CF5DB
+:10711000B5C50067C0C78B7E941E805FD62E29A29E
+:10712000FEBB4F34ECBF62578C09AE4638976F19DF
+:1071300062282FAF1B6E28EB70F6551BE15CE499BB
+:10714000606AC7D816907B45F80BE0F91B9366136D
+:107150003F3D29B0CA0478C6C99C0F5ABD02F9DF69
+:10716000F0A719E47721FE02F463752AF5585F074A
+:10717000EDBF0F6DD106463B8431B75406EF177A49
+:10718000A26494EB8B5825D1DB62D64CCF9B591B64
+:107190003D4BD8097A96324E8F9F978526E3F3F7B9
+:1071A00089BEF41CA0E7350EDFA38968BF0DF38DFF
+:1071B0004A40BEE48C27FBB4AF73424D9B697CCA46
+:1071C0003959DB17FC14E3DAA15F7BCCB83BEF54F1
+:1071D0007AE6D1C787F9DC38DFA7129FE78D4953DC
+:1071E0008621FE31EF40835DD5D77CDB347959E6CB
+:1071F000E17042DF2D96CF2D14021BA17C649BDD34
+:10720000867E86739B254D6FBF97ECDDD3A7B87F35
+:10721000E65CFDEC54C4BF9A6DA35211DFCF494A1E
+:107220007D15C0FFDC34E0E36EF2E7B8514E9CF10F
+:10723000B8A83F488CD82C38B715DAFECE286EDBBC
+:107240007A68BF3059647E68EFF3A7C5E2FAF57D2E
+:107250009BD7BD7C8BDD80170BA61ACB0B99AD0796
+:107260004FD2F0BC6D3DF5A82F8925037CFDD8DFFA
+:10727000557F58FDD64B6178F66F39AE44D46FD840
+:107280001436E54BB1A77F5FF0FD6243C55B2F4924
+:107290003DF0D5F16A528EB71CCF095EDB903F02FC
+:1072A0005C2C28974F1EE470DC1673E3D6EB000EBF
+:1072B00085EF888CC3B9D4FF7BC4E743DCBF6F9EE6
+:1072C00027A4D175A7C63FCBEADE263B6E597501D0
+:1072D000F19F4267D730F43F1DB907F80BF295795B
+:1072E0009CBF1CCB1BF5F01D306E67BEE8B6033E9D
+:1072F0001DC9BFB015CB27AB4519E7ED3C7841E37D
+:10730000E35D6F4C81F57DE69188CF741EFCE7F05C
+:10731000F3C2431A9F09707EBECAEA650D30EF2A98
+:10732000800BDAF3FF6CBE7E397EDE2E7973072286
+:10733000BC6A0437FAE16AF2ECA447B4037DD83999
+:107340003ED5DF81F2682AD8C132E29B7712DA9605
+:10735000270F0E1F88F0627EB53D73720FBEAFA877
+:107360005E958F7E76B6453A83FA373A45504E178A
+:1073700032EB9950189EFA9E937ACA84D7D633A1DD
+:1073800030BC36E3699B094F2FB24BA9B6745E7FC0
+:1073900062500FDFC39F70FE729B186C60693D786E
+:1073A000FBD7BCB74B515900BEF202E2EB5DE3D311
+:1073B0005E0C09617CE50AF918E033C9BFD6981B59
+:1073C000B97EB190CBBF230B6F3AFA3B80DFC7F396
+:1073D000385E7F9CF753E21F1F839685F87A2A3F19
+:1073E0002116F1EF745D11D1994E3FE679DA357CC3
+:1073F000D3DB155A15C91D013F8B3C467CC9786EFD
+:10740000E90094A77DAD5F1F576FA78F5B88718DD3
+:10741000B17D8FFB610EB74733F695F43B3E188282
+:107420003DF885FC8445F78C03E5233FB98961DC91
+:10743000F5643187CFC903A3881EDB8B75FDCA476E
+:10744000F5A73C6200F5D893C513DE9888F4E39560
+:10745000484EF735EF396D5F67343DA053D303F4E1
+:107460007AF1C1858B96E0B81A5F38E5E1F8FB7ECA
+:10747000CB42D23B603DE47FB2CDFC9F32F43F81F2
+:107480007DED42FED59E2F325C47615E11D9D585D8
+:10749000923230929E60DEB779BC233FB1935F0E8B
+:1074A000C623BA2A9E57C41A705FC5DCFFDB8EED77
+:1074B00061BEE20779F918B69F688013F19176E012
+:1074C00023283AA4833790DEB4B2D9784E2B1A63BE
+:1074D0004CF46EE417C50B399F6BCFCF191889DFB9
+:1074E0005DEEFCF4FE577AFE15D81FCAB8E62F49A8
+:1074F0004F89378C07169D69BE7453FD6853FD781C
+:1075000043F972F8D8A9C991761D2FA294A5DE0877
+:10751000EB6F7FD25E119EAF317726B75FE6CED498
+:10752000E2F75F51AECE9A09FC2A86F592AB7DF563
+:10753000D7F9D3A81CEFBC99385FB048C27D5D294C
+:107540003F0A93C30BA97F48B061FF6D9A9CAD6859
+:10755000E378D41A73FFCB88879F6AF6D091799C21
+:10756000DF7FA6F1FBCFFE532BFF440820DF3C76E4
+:10757000E8EE58D4DF3F3C382A16EDB1336DB5B193
+:107580005C4FF7C77E0BF0F313A0CB2698EEA3B6A3
+:107590007F8E9E5EFCB4660FFD88EBE9ABADCD91AE
+:1075A000FDD4DFB09E6ED6CF73C592A3BF83757C2A
+:1075B00018E07034EBEB1F2A4AAC4CF0E170F84C49
+:1075C0005262D1AF7726C0F97D5FF8A8C3E11CC233
+:1075D000218CDFF705C7B35A7FBD0CF621D92D45A5
+:1075E0000EF72F13D19FB0457063BC8A59199B0ABF
+:1075F000E778A2386B6F53989E11972B12BE9CAE02
+:107600003B569A8CFC070C5DF4F7BE527D2C15FDA1
+:10761000AC650762883F9AE72DCF37F2994FEA0BA6
+:10762000B27F0FFD8ADE11030E84477E1CE75F4F99
+:107630008B0111CA9DD539B1E1FBF8D02477565999
+:107640002B239E63C52EE33916E5D7D038271F14A8
+:10765000DA8401F03C324D525CBDFB1559F9FE57FE
+:107660001D10C9CFBBAAEECF6F607C7115F07B54A3
+:10767000135E69AC9D8F787DDA2B5910CF3BDB12FE
+:10768000E6237CFCC5A23B03DA1F6F1C4E787EA666
+:10769000316710CEF7CB9922C9BB0F0FDA2DC2B5D7
+:1076A000F0F44A2C487E81209DE727754524AF3EA3
+:1076B00044B8903D2B135D9C98C9E30EA7611CACA8
+:1076C000B7009DA03EDC19103D8108F47162263F91
+:1076D0008FB3971E20FC7939702C16F58AD36D7CF8
+:1076E000FCB3D5722CC6A95EAF9BE0A2F5E5C3B88A
+:1076F000A8F71EE272F4C33A8E8FB84EB20F1BB9D0
+:10770000FC3859B7E2FE69008F4FB788A4777EDA5C
+:1077100058347F1A9EF71689CA39050B29CE713263
+:10772000C0E5D1A9C0D9523CBF0FEBE0F4A15C7316
+:10773000680AC9DD4FEA25C287F203C67359B82526
+:10774000C66CAFC66681DE558EBF29F83F7516DA66
+:1077500049CB93407E02E59ECE2F92D04F59E84F01
+:10776000308C63670512E21DEA97D86EF9C3459322
+:1077700082487F7E81E4DFB2E7009F603DD2BEEBAE
+:1077800049DE9535DB0DF316561BEDA3E5267BC8C8
+:107790006C2F5D4E5E9CD6F054B73B4E4B95A59139
+:1077A000F212E45C4D2E307916C2FD0C18D64D59FC
+:1077B00000CFE74415CB17EBA2887F962D3B7F8344
+:1077C000A697DE8878C0DC7E3655B7D3C3E86C79DF
+:1077D0009D6892DB46F882FEFC01EAC78D099A1C7F
+:1077E000F51791DF6E548E1A9F8BEBB852FBFB8A14
+:1077F000F5DB524DBF2D25FDF624EAB7B09F766C20
+:1078000012D61FF45DF2EF9C9A7713D95FA7BAFDE9
+:10781000675ECD7FC6F59453F9459A7FC7AD97074C
+:10782000B07EF89CCE2FDED7CEE1ACC6274F6B7C66
+:10783000B253B3B71A347951A7C98B53F99ABD958E
+:10784000C8485E58AD2ABB123E734B4B8C493E2450
+:1078500098ECA821A6F331CA8BED5EDF6C3C077B68
+:10786000D268C37B491E6FD4CFF71D263FF24585F2
+:10787000E7156D429CC0B8C9429EA7C51C6DE44780
+:107880005EE856A87E08C60BA13D9A54984FA2E325
+:10789000A7FE5E4EE4EFF5723CECBA06DBA5B551EF
+:1078A000B9762163980F33421F07C051037AC21083
+:1078B000F467C33C4960A0617B1DDF87166FA37628
+:1078C000D9154C16A0DDEADC34C28724A6127F1934
+:1078D000B486A998F7C202CF52BBBDF7C23E00EFF3
+:1078E00043B5D3C92E2F72C4F2B837C8C7FEF1AC66
+:1078F00086C7773D09A4B70CB572D4EC136FB57683
+:1079000097C3DB303DE82EA20B66217FC4B6987189
+:1079100012E269A1D34B7E03C0EBA577A27EFFA242
+:107920008DFB0916723F707BDE9487D1DE1DF794C4
+:10793000937CCAED2B757F6517E1736775911FE521
+:10794000DEAF3D5CCE8D79EA130BE6BD751E646E2D
+:107950002C1FAB7EF6FCAF486F17C81F74B23A8776
+:10796000F365C6BC98C779D293B391CA53C130CEE0
+:10797000427A50375A711D00D726AA5FB17512EAB4
+:107980003BC745C2DF242DDF48C6734DEE2927AA29
+:107990005A991DA472523ECF13FC99A61FB469E7F1
+:1079A000F9B8E6A7784CA39B168D6EBEAFD1CD6615
+:1079B000B3DF7917A79B9156F7D618288FF4BB48E9
+:1079C000CEBC957F96D60DF42F635C372D4F6C9A05
+:1079D00008701B630F119F2E02B1B711F63323BF3E
+:1079E00086F2188B7C8CE21685C535B4BE10C6981D
+:1079F000AE43BDA94610B57AE48F631282D4BED0DF
+:107A0000C164EC5FE479FA08E6E32EF40168A03C77
+:107A1000B3B84620F894C178D0FE48F5761AEF54F2
+:107A2000055F47BB8BF73F59C6643F943398E7E83F
+:107A30001D7C9D5E8C8B9EAA7EF608C1BB98C3FB05
+:107A4000BA8F2C067ACC0A461BE87AF4BE7843FD3E
+:107A5000A81D2986F2406FBAA17D82C748EFD123C5
+:107A6000C61BEA4F7A8A2C2867753B4FF78B757ACD
+:107A7000B8DC9DF194D382F058A4F90B1061D920A1
+:107A8000B4BA18F97D1B353D91350F6798C7B1F72A
+:107A9000BB16CA13D85C5CEBC0FC878B6D563A2FC3
+:107AA0001897F8C8A9C3561AD7915627A01FF33EB6
+:107AB00080B318A6FF35EAF24D8B5FE07AAC61EB3C
+:107AC000895718668E75B76FD1F069BBB60EE0DBCB
+:107AD0003324B2C7399E24E4338B04FD071673396F
+:107AE0006DA6CB36ADFFE35AFFC7347CECF4ECDD7A
+:107AF000188D7059CC481FC915D76C8CC275E433EA
+:107B0000A2C7B6E0D1E870FDF1677D8D533C2197A7
+:107B1000C6F1733E3A7A81501B85E7BA2BF4A7373A
+:107B2000E1F9C2A70D1B6361BD4F08AC0D294AE7FF
+:107B30009FBAFE7DDD678D543F7A3C986850FFC246
+:107B4000674DBCFD64A6A0BFEB679ADC69D4E8274B
+:107B500063DF58F22F5EDC6123BBE7B1F9ABF6B40B
+:107B6000C07A47CDBDE789E7105FE6DFF3BBE79456
+:107B70001E3DBF687E7207E6F18FDCE062C81FF42D
+:107B80007933F67D924DEB96AD0CF1F4C7FB9F5F18
+:107B90008EE33DFE58B44585F17FBCC74AFCE5EA5B
+:107BA000FB1EDEB383E48D492FF618EDFCC737B713
+:107BB0003E7110DF573DFBE8B9B07C9D93F3360D65
+:107BC00043BF69FB868A9699197DF3CF221BF3A1E7
+:107BD000FFC7F3C227CFBC0EF3FFC677F5F8703BA3
+:107BE00060D42CEEFF69DF50D53213ECD4D122CF14
+:107BF000576056FF4684C7E89F0E52507F0352B02D
+:107C0000FA00969E39511615F6F79B807537F1816B
+:107C1000399B33F03CB37F9C7FF4233CE7531ABE7F
+:107C2000F7A18FE87EAAEEB2A410DCFD2F3AB87D52
+:107C3000A32AC3C83E762BC30AC3F4B9F67BF43833
+:107C40009EFB3DE4E3852531145FD6E32EA2E7CF0A
+:107C5000F5C8E7974DAD9C24D3FA8DF1FC1484DF71
+:107C6000048CF7F2B8BDDF6F65941F045B433AB92B
+:107C70005B1C4D7927EFAEBE8BE2F6FE1ABB9C91E2
+:107C8000487183A7B05C057CC73E91E2B901CA3751
+:107C90009EC5F3372E2CAE7DD8A6F40DFFBACB9C33
+:107CA0008FA49D8FF9FDCDDAB9D4E2B96418CEE581
+:107CB000A86F6284738975107EE9E722C636D2B94F
+:107CC00030873313F33F067394C2FDBC8172A8E37F
+:107CD000944872EC3725EB6AEE86F2F94B0318D222
+:107CE000851E57294DE279087424C0B724ADFF6082
+:107CF0004DEF463E867A77A91677E958CA28EEA254
+:107D00008F77B16A80CCC7BB8DF4E6D24AA07F944E
+:107D100025313F27FDA27E38CF932875762DA5BC4F
+:107D200055C1E2C6F8F960935EEF6795B4DEC1EF26
+:107D300088E4CFB7C46CA1FE83013C6216B6B211D1
+:107D400010A83D0A76305A31AF24055F28617A9633
+:107D500096B73BB8EAA75C3FCA819EC986F9842FD3
+:107D600069FDB5EF8BC807AAEC0AF23DCCD142BE43
+:107D70004DF04B433C6AA5FEF2B7998CF73998CA8F
+:107D800094C4C9DC0F86F399D70FE371BD10F433A7
+:107D9000DCAF50CDE7DF3597DF07618799126EB70B
+:107DA000B0F0F50C3794353F99B12C25D90C72EA17
+:107DB00037978A0654F6EBC733F6B728DEFEFDBECA
+:107DC000156176577A4F7B3D5F4C87734A95FDB4BA
+:107DD00010DB77BFED5EF5C02CC06727F366FF0AA6
+:107DE000E0E17B4724796789394EF0084571F874E2
+:107DF000EBB38BB9BE0BDA790DE55D83BCC3F3C37E
+:107E00007CED9180EFCC6FCC17D0E7D5E34B1D1AFA
+:107E10003F0EA58522FA058F69F4DBB9E173CA2B01
+:107E20002845FD167039B4F163C33D900105338ECA
+:107E3000E1BACDF908BA5E8A7296F0D7CFE56C87C1
+:107E40007F02F19D8BCCD54CFABF99DF5819E57FA5
+:107E5000DC2D46BB9BC86F772FE58F54F9EDB21D23
+:107E60009EF3DC467FCC82A9467950A02698E48513
+:107E7000D1DFB5D06B8C138D68594FFCEB22EA4DE6
+:107E8000C4EFF87AAC5A7E9984F74C44B4D7FDF429
+:107E90003CAEF1E737353D330AF92BBC8FC1047393
+:107EA000C047170B517900A2FC704C6D5728EF3179
+:107EB00081A9541EC87C54D6F3219359809E7A9E82
+:107EC000CB3016A2F255A80F8948520A3D87A31D50
+:107ED000321CF53C7777BC87F22773D2285E50C0FE
+:107EE000D4F7B05DFE844F49EEE5DFC4C80FCFFC88
+:107EF000F52B5428772CD4CA98098FF926B98C23EE
+:107F0000A7BF96D7E7E9E5BA152AD6CFE0EDA5D900
+:107F10004D7BFD4EE25F5AFD265EDF5D6E583103FC
+:107F2000CB9285CA715AFBC299AA6D36E62DCD66F1
+:107F30008407C11CD5317B604FB92C478D0E2FAF04
+:107F4000CB559DE1E567B3D5D8F07267B62A879720
+:107F500087E6AAF1BCCCFD4EEF48EA30B477E1E702
+:107F600047C2648E87F8F39AE44BC176EA0181E058
+:107F70006507BE8DF092981A44A60464E3C07C2283
+:107F8000E033B63BA19E8DB751DE9F25C699DA9F9F
+:107F90003FD24C5F21891D443FDD02AB2F13F76DAB
+:107FA000E67B82FF95BF633E0FD04336EAF9A16AB4
+:107FB000AE0784AAB93F40A713FDBD79BECBE13D12
+:107FC00053C3FCBCE93DE3F6B57E331E9FD0F4BD40
+:107FD000764DDF7B47F34B77EF37648DFBC0D143A2
+:107FE000DF7DF34F2BFB208C7FF6DEEFD9A51297B8
+:107FF0001F32CA8B8E28B638D2FDCABED6E7CC99BE
+:1080000055309BECDBA132C51998CEF739BFE9C0DA
+:108010005F810F8E19A0DBAF6E07C2218325CDC90A
+:108020008479B77918E9AFB5338F1622FFB95802B2
+:10803000120CD675F68E7348714C788ADB13CDC35B
+:1080400018ADD7952647A1BE54AFF14D3B8BCB1B46
+:1080500081EB1F6A25796B5E777D6C40C0B8624A00
+:10806000308AFB371259200AC649F1B83D94B7E26D
+:1080700017650F964BD8FC4C282F6F11150F8C737A
+:10808000ACA58895C3B8E55381CF51663ACFA78890
+:10809000D7F0788C9D51BE45EB4027C5ABEB368FB2
+:1080A0003AB212F966B2C832A0FDD8FAF11EF47BDA
+:1080B000D63AE3E329E6A4ADA7D6E97E15EF63F847
+:1080C000650BBF4F22AB0ECC47DF7D87D583FC7C91
+:1080D000D8D31363C530F89FAD3B1F8579EE8FCAA7
+:1080E00016AA7FB43ADB718B13EF130655CA33908F
+:1080F000CFA84E987727B4190CE3DD5F71A67924D9
+:10810000EB1B1F623D36039EC6B86D263FA8D16F9C
+:108110002999F483E6D95AFC7B329B8CE77CED13DA
+:108120009724D473973915F2A367370A949F123AAC
+:10813000E24EC5733ABB7514F9CDEB1A45CD6FED20
+:1081400026BF7568184BC57B3665CD02E9C562DD73
+:108150009F6BB0DF55994A328E73D5C4AEE4707F01
+:10816000D9A3F7DC15857CB4AEC4A2F9B9198DA3E7
+:1081700028AA230DF6FF7E9DC0F3272459C0FBCC0F
+:10818000AE07C5285C57A7C4FD144DC04FF19E6EC5
+:10819000D38CC27EE950FA1BAC33CC6EA94F4C8F06
+:1081A000C6797BF05725FFFAB9E609141FD9D39891
+:1081B0004DF920E671EEDBC0DAD03EA9DFE0A06722
+:1081C000AFFA546FAA1BFABFBF6D46030829F6FE2B
+:1081D00091D549784F6865B39D4545C0E373DBA6EB
+:1081E000D07C2BF13E33CEDB5C60433931BB6586FE
+:1081F0000DE176DF06F5E9F079EE2CF0BD8C7C2FF1
+:10820000A6F969C213270BFA119EBFB8414D45FD6F
+:10821000E25C068B982F796236D7335EBFC14BF78D
+:108220004ADE1F16B9DD3BB3B9DF792E120BCA0F38
+:108230002B7B7315C0B90CE8A9065E9D6D9C108B55
+:10824000782BB135C4A47E5352E4477BEE02EAEDAD
+:10825000C0CF1BEE59B4A31CDAD5DF3BF22D64CF9F
+:10826000D7DAB8DECC7E2D125D805E5886F4F997A1
+:1082700062875C1BC67F517F540DF9825E86FA9D32
+:10828000D428066DC0CFA5C31FFC37DA3B88B76A78
+:10829000181ED3CF64CD2ED0F235922693364E3FA2
+:1082A000F5731605820CE32E2B1C789E663DBD17D8
+:1082B0009EF45A47D8F8A8E7CE646A54D83A802585
+:1082C00004C95FEEE3F376B7D3EAADC060BE0CD36A
+:1082D000DFCDF5FA3E46ED30D2ABC3C3CF0BE0DBCA
+:1082E0006FBCEEEA80B1DF480FA3731B2DAA473F96
+:1082F0004039DB2A527EF598561EFFBF3894919F75
+:10830000A8AFF174FE8B3FD6411A1C01AE0D8985D2
+:10831000749E7DF5B3054EA869E37AECC3AB938CEC
+:10832000EBD2DB8DECDED73A16CDF5C136B4CFEC0F
+:1083300001E07BE3F0794245F99DB9FB0EB9BF7DC1
+:108340009BF9D94A5669437D4D51427BEE43BED1DC
+:10835000E222F983E83062325D5D24B983FDD430D6
+:10836000BEE77A706FD36858C7B95DDC1FDAB46DA9
+:10837000EF134FA0DCD915E3E671267E4EE3982E6D
+:10838000FF78FECF2DACE74719A48D0FED3FD2E467
+:1083900029C350D5A09E78D50707967FF604FCFA2E
+:1083A0003EAB9C8A7C4CDA5DE4B819CAE36C81244C
+:1083B000E4A7B7ECB2F7AC0BFED95B8C65699FBD47
+:1083C000175E3A747C82F19A0E3DB16339CAA943B3
+:1083D0000E37A688237EF90D74124A2F007AEABC64
+:1083E000E73FE89E7EB47C7E29E5B957DBE97E97BE
+:1083F00019BEFB6673BB9F69F736747A8A6A1EC51D
+:10840000D0BF7846B39BCE6C013B15CA0DD536055F
+:10841000BF6FD0E92E5093228C67ABB69DC67365B3
+:10842000E176627ACF3EF4F13BFDDC0FD900E30B3D
+:1084300011FC7D971BEF4F5EB5C203F87FC1EBFDCA
+:10844000B607D67F76CB0ADA6FD5C1EACE5FE1F9FF
+:108450000EF2DD86F567B60C9F2CA023D2AAD0BD04
+:10846000BFBABA67489E344F857760CF37B759A3F4
+:1084700050FFF0D759287EDBDC96183D02E594D3F7
+:108480001231CE1AF070BED9234FBCB1E1FA50D3ED
+:108490004CAE0F094F95DC9F0EF0AA3BC5F3147547
+:1084A000FD43D6F0648C5D26FE2CD7F13CB71E7DD3
+:1084B00088EBD51751AF467D6952B91C2E9FEA63F0
+:1084C000F9F730CA67BAFD781F33C7C9487E5C85A3
+:1084D0009716D06FE16481D969F8BD0C37C3FCDC15
+:1084E00078D07F14C0F8C12D5CDF89763ADD2AE2AE
+:1084F000BBCAE9CA01FF213CA3335586F3584DFAA4
+:1085000085CDA43F88A6F24E8F519F50983B16E12F
+:10851000ECDADA7F1E87EECF05BD89EE9BF919C034
+:108520001FF1D4E1A7F389054302ED0AA6AA4AE2A6
+:10853000A01EBD1FEFB571FF8A4CF122416D20BF17
+:10854000FDAE09DCBF91CC78DC2B45E5F6FCB8A983
+:108550007E2A83FD407128F673168D7C79BBD7F790
+:108560000CE24D9A1020FB2F7E2C1388ECBFA65EE8
+:10857000CEAAAE2CAEF4C3A3DCFF576B897647FAC4
+:108580009EC2A1B99C1EA38FC1DEA09D789383E2F9
+:1085900079B9E28146C4A79D132DE4D7DEC94EC840
+:1085A000C84F8E7B787ED125AFF7750FC565BD6945
+:1085B00008FF242B5854A0ECDA343FEEB03BD3A391
+:1085C00051D4BF9BFC3CC1C30FB0CB807FBBAB126F
+:1085D000E333E1FD23551B09AECA40EE27D3EF9FDD
+:1085E00027C8FC9E7F93F7BC1FEFF9FE702EBF07D4
+:1085F000145D609D930EE5ABAA4302D2DD26977B06
+:1086000031E273A3F20C9D475A9662417FD9102B39
+:108610007BD53E9EB127E3783D0A4AACFFC1D241EB
+:10862000BBC3F3491ED0F6FD0321B2BEB27C2E9728
+:10863000271D87009003D03E669AFDFD7839D9CF7B
+:10864000DD65801BF47FC0CFEDE73F7B1E2FF75B1E
+:10865000C92ED2ECF7F672B2CF315E0AF573F2D6BC
+:1086600095FBA1FC485AE47913F2397C1F794DDD62
+:108670001103F0F86B0D8F63F57DCEAA6001DE5219
+:108680003B90A5E23AEB5CB6C591BE27B3329FEFB3
+:10869000B723B18DE0C5409EC75E47F7E94DFA6A42
+:1086A00080F4E00B15E3FD536877958CE2FFC04F33
+:1086B000264DA6ABFEF4E39AC4E5A8596FD5F52B79
+:1086C0007DDEFB522B9351FF6C75A9C43F5A416F5D
+:1086D000453C2BADE67A6BA9B5EB3DBC3F94729C53
+:1086E000E7BF084F8D6DC2EF1B00BC14C4BBD94E51
+:1086F0009521BF1963F7D23DA35ACC5F977BF457FE
+:10870000260E3DE283F7D21091F4C418B98DF457C8
+:108710003693E7E5AAF01FF21B5D9F758EB51AF23E
+:1087200077EDA6FC5EC994CF9B99A7E5C369FCC60B
+:10873000356962BF7AD3CFC1DEC5751D067E83CF92
+:1087400020D8BDF83C0A76393E5F02BB1CFDDD2F08
+:108750006FC8A4E7AB1BDCF4FE571BA6D2737A6A82
+:1087600048427D9BFCCEE47C644181FC773A3E0527
+:1087700046648FC5FBC7BC7EE69C94FFF05F0FF597
+:10878000895A7BFF17849FDD65A6ACC4F6A549BC5A
+:108790007C302F7525FA775E2B56B3F300CF065A3F
+:1087A000BC65F85D07F65D3BC527CCFB3996A7CBCA
+:1087B000EBC8F63AC34F1618FD35DEBC7EFC353FDC
+:1087C00010F83A96CF5DB70FD731A0C0EA457C4D7F
+:1087D0004D37C609F6E769F107ED99FAABCA878804
+:1087E0001E04A08789FDD14390213DEC74B11B91FB
+:1087F0001E5A5747A6871BF2B95C6D75727B8FCDE9
+:10880000017A1802E512B3FD16A2FC8F0B557B8F7F
+:10881000647C23F4A026A13CAD5B0DF214C6A93BF9
+:10882000B2FA5D92A3480FD07A30D203D247183DF6
+:10883000E077585AE3347A900302C681801E82782A
+:108840005FB04EBBCF11460F02CAE16E7AA8F86640
+:10885000E9A129CF287FBF2A3DFCE28610E53174CB
+:10886000A40592110E3B25EE3FFAAA74326C8E8D50
+:10887000FB8BAE7127217FA995383F9D3DF434F9DC
+:10888000E1F21D6E11E58A47E178983B71027DFFA8
+:10889000E7CD3C1BFF5EC102750FE1FFA28FC8DF71
+:1088A0003AD0C2E9EBD86B7BCB112F87D5B717CC69
+:1088B00046BC582F92DEDB6B7FF334FC11F8FA4193
+:1088C000034A0E8FE7FD671EAF57D69FE4FC368E36
+:1088D000C919B09E24BF5CE8C1F8CCF516FABEC732
+:1088E0008082F6389493FA78CC5A998CF8852AA825
+:1088F000637C6F7A819F36699081DE7EDE1FBD5D6D
+:108900008EBE676BF4053F9477EBD3EE2D7E55FF5B
+:10891000699FFEBC6B22FB07B76872AE55E27918FF
+:10892000D05AC67BFA4F797DBFCD23FFAB490F3BB1
+:108930002C07D15FC6D6C6927F37C9CAF5AE24854B
+:10894000E78F0C617E82B31E07D3F53645E5793E8D
+:10895000B905BEB338EE6EA61CC1EF1938DD6C3117
+:10896000C5B9407FC578F576AF7A8EE6FD9AFA589C
+:108970004281FA497FF874FD22B50BC7EFAB7E4602
+:10898000C15F8E7D89718B6A9ECF6CADBE9DEE738B
+:108990008960AF5830DEE969A3EF02C9B24D51C812
+:1089A000EE52E763DE62AC069F59E227A47FB7264A
+:1089B00081FEEFEEF183EE4CE6714E113DDCA077C7
+:1089C000B61E77FB6F81796CC037FC788F3D1FF442
+:1089D0007428C7A09E8E634DE5FAB87EFF2566AC6D
+:1089E000A6A7ABC638DCE5F4F4017334B9399E4D63
+:1089F00044F8A45A94EDD3E0FD8487724FE2F14C21
+:108A00007A7865028AB329BBEB8BF0FB57ABF7BFD3
+:108A1000BF1BFD92D37E6B6748A7AD87B89EA22E81
+:108A200060742FF90AF83CD1C90DF94F97FB472024
+:108A30007F898C77AF6B78D781789768C0BBCC394A
+:108A40000323E29D1FF9F13F8077E3E718F12EDF62
+:108A5000847713E6FC6378771DAEFB138CFFC03878
+:108A6000EF2D546F98D30F1EA62E5467CCE9070F35
+:108A7000C3FCEE644F8D645551E1DF15D49F0D2882
+:108A8000E7FA89FBDB379F21B9595B95E340FDADE0
+:108A9000AEE4CC1B1847F84B955D09F713819E6730
+:108AA000D083615CE60703F6683ECF633EB6DE1E08
+:108AB0009C0EFD4A65EECF2F95DD0CF3A845679718
+:108AC000E4037EB52CC9C750BFB627597AFC12F013
+:108AD000EF5AE9843707E0DC097214CE984DBF677E
+:108AE0007B22FA9B5E3B3495FC4E3A7D74C4F17157
+:108AF0006FE802F914D67FFADF406E85E1FB0C6067
+:108B0000E0E1E51C47B2A17DAE9C66A89F9D74B5CF
+:108B1000A1DE3569DF4CC40BB14C8BEB6BF7CF7426
+:108B2000FD618C5D253C6BD5F4DB3C25CBD01FF57E
+:108B30005CE47F5694EB503F37739A613E5DBE5FB5
+:108B40000FFF21DD8A26B96D96F356939CEFACBEDC
+:108B5000108FFCBE618EF1BEDA666B289BF808E3CD
+:108B6000796A575DFA05E17FA7C2F1BB4EE2F8EEE4
+:108B70009FAA7D67C5443FE36CDC6F56BBC4417E52
+:108B8000FBDA43DF7AD717E64F622CF01ADE671C58
+:108B9000171BAFA03F7E8895DBCFB2CAEDC0B1AE48
+:108BA000EFD3F86C35979F82CCBF37B90BF8027EB4
+:108BB0003F8B1D0E913DCFBE6BA3FB4EE3E6C7116D
+:108BC000DEECACB0501ED60F856094301CE9562503
+:108BD00039C392985C47F9876FF3EF1432E6DE9C55
+:108BE0008CA6B44A79826CAAA3EB352D2F15ED948F
+:108BF000280F736F9C867C90EF337E223F3FA79BAC
+:108C000097E5EB7959B75FE3925833E6990EC1F1D6
+:108C1000A06D6215936BC94F10A4FAA11E76A2969F
+:108C2000E6E7FD0797336F2394C54A55F3DFFAB49F
+:108C3000787517C591D3057734F2EDE1A297E2C8B4
+:108C4000B14CA638730AABA4678C10E44CE36BF20A
+:108C50008F6B010018AF67B136F2E766FFD8C9D055
+:108C6000EFD6EAB2EDA1FC9890427EB94DA7F8BDCF
+:108C7000B6DAA577BD3109DA37BEC1F3F3370DF3A4
+:108C8000BF8B748D3889F742456725D50F7E5574A3
+:108C9000CF56F07D33C37BC4CB9C9600860AAEB51D
+:108CA00075FD12F3EE58BC8DA13E5207FDCBA0BE60
+:108CB00073A905793143CDB4DBFF88F53778FDAF73
+:108CC000A39EFBDF03E81E3233F90D5B7D5C5F6E14
+:108CD0004DB4119DD7966427E1780D89D174DF6C6E
+:108CE000F18D956F20FFA87D5B746F14781FF4A73A
+:108CF00013EE613CDFE64D433DD4E6B4517E87D9A7
+:108D0000EF6763DEB726C1BEEAE26E49EA4F1FEAAB
+:108D100033CE506209DA62AF3CCE507FEF4D14572C
+:108D2000D0D7A9EFB3A1E4BCB45CC1DFFEC1384326
+:108D3000B51039CE10E2DFD3C8C0FA71081FEECFEC
+:108D4000FEBA71861DF3BE5E9C41DFF73CEDF77CF9
+:108D5000406C2D5F82FCED746E969EF585C1711F8F
+:108D6000AEAF147F53F87BF49F2FD0CA6F1C68FFFF
+:108D700004FDE4C77F74F4003EA75F7AB4642DE07D
+:108D800045C154EECF7FEB7B710FF2E18C7EF97918
+:108D90006EA3BF1C7F103F691D02BFE71E5E5F60B0
+:108DA0005A57B6D5E85F9FE934B69F9568ACF70C83
+:108DB0003596F5BC15F37E37C6DC4F79679BD63107
+:108DC000FA1E110B3F0FF1F265BBD21B4FC2FDE53E
+:108DD000CC9D4674DFF90EA77BEF8B7F71915D9977
+:108DE0006491D10EBDB0B87ED3EB4A783CC0A322CB
+:108DF0001E7DF193B16FA25F9BC9BE20E6F12DCF1E
+:108E0000E1DF61EAE59FD7FCE3195547DA6686C5DD
+:108E10004F9B06F96E9A0BFA4B4649A105F5878CD4
+:108E2000AA97A87ED19249FDE291AFEA98611CFC15
+:108E30009E1DDAB7BEAA97E97D5FFA8E45F1F37CF5
+:108E4000B86ABB42FE5FD3F76E7D98CF867C3E9DAD
+:108E5000CB9B5A89CB273815265EC7485909DF971F
+:108E600045E17CFDE2547E4F820117427EA58F676B
+:108E7000968FBA1C70AA5C7FF4559BF2EF4CE36F9F
+:108E8000F7FAEE990B7425381B789E5D8ED6EE307E
+:108E9000D74BD91C26A35C867D46CCBBAC9BABD9FB
+:108EA000997DE47B31DD0E2C7EF55DE4875FD90E84
+:108EB000EC63DCE9A9A1A591EE23EDCED3F4F1A8F2
+:108EC000D030E4C31D5264BDFDF6E2593BE6F6A383
+:108ED000D7629E6A78DE44AF7D7FCD3CD5DF7AB81D
+:108EE000FF4B8F3FEAF9AACC1A188FDFCFCC74FE64
+:108EF000FA668A2BF691A7BAC9E50EA1BFAAB62CCD
+:108F00008ABEF7F875FDD56734BFFB037319F78781
+:108F10009BFCF5E6751FD1FCD797BCDE20E24B5FCA
+:108F20007E7ABDFDBBC991FD64C9F3F5FBF3DAFDA3
+:108F30001F0FD7FB54C9CD22D9057A7EA2F93DD89F
+:108F400041EDB80EBD5C569F417EB65689E32DE5D6
+:108F5000740CE9C96775A2FE477A5433D5C75670B9
+:108F60007D50D7B3642D4E60A627A08FD3441F2514
+:108F70003CEED0A3276AF4B108E803E87228E37452
+:108F80006CD1F230873A784AF7D7D5A37ADB4D1EF9
+:108F900047A4BCD3CBDA4DF5931C643739C7BF8ADD
+:108FA0007A556715BFBFD6E1EA7261DE8AFF6D911F
+:108FB000BE67DB577FDD7E12E71BEDA76525DCCEA4
+:108FC0005956A2DB4F21C9E742BF30D84FE487F59D
+:108FD000D9F307F6B6A3305F14CF09EC4C47FE3740
+:108FE000C11F4C7EA263985700EB3C32E23CF93F34
+:108FF000065771FFC7E02AEEFF4841FF471AFA37CC
+:10900000B8BD56EBE6FE0CDD7EABD3F2BC747FC878
+:10901000551A1E8CB157727F88664FD51EEF22FB02
+:10902000C9A97DCF06E3758847B66A21802E4226FE
+:109030005ECA453DD83E983E6FCA58B5D10F62CE44
+:1090400043769AFC1DE6BC816BF3353B4AF37F3CCB
+:109050002228F74D83799EDD91FB3AA2ED7FEE5AEF
+:109060001983FE8F9F06EAE76AFE8F87F0BEC5A1CF
+:1090700077B9FFA3EE10F74BFB5081B92E12FEF526
+:109080008AFB90FF6365BE9FFC1FBA3F6999533B03
+:109090007727DF2FC297BEE7E9E165F4432804CFC5
+:1090A0004F7E8971C2BA6B782EB89D6511FCF4FBB6
+:1090B000AD3AFC772619E1ADFB9FC6D803AFE1FAC4
+:1090C0003B92AD6C23CA51F1138AD7889A1FFA9B41
+:1090D000F22BDD9C6FF42B8D7F68C276FC0EEFC403
+:1090E000878B4EE273F2EE750937C373EAFEED45E6
+:1090F000F864AF7238FE751EE75B98311DCEB796E7
+:10910000E729C44F7BE0CAFD4A3A3EF6F8E378BC53
+:10911000BBB482913FAE54ADA43B8C98E78DF8A3CD
+:10912000C3A7D5849FB5C3783965666510EDDE0C9D
+:1091300080A72AF7C6D7D6E36D6B89EFADB6297E37
+:1091400082DFA51AF4D3D9357BDF8C8F197EE3FD3E
+:10915000E1CBE1638D096ECFEC98701FC2EBB95D76
+:1091600045AFE3F3F9C0BA1884D7C17DDBE7F60158
+:10917000B764431E3FC26D526F7C3C5EE06BCE878E
+:10918000F7D3DD012BF1DB0A8CD961DEDBDA286352
+:109190005C45E7933F8AFA5A7C72F379BAD7585BF9
+:1091A0007D81FC4A7555FCBB101D2EB571E4C42BA6
+:1091B000E793D7CEE3F7D8753E99A2F99952E41018
+:1091C000D1E332A047CCFF5C56CDE30A78CC310026
+:1091D0000F31890563C87FE0207ADA89F9C3D7F6B1
+:1091E000E04F27B4B30F60BDE49399BF825C7C1E4F
+:1091F000E1D5599D407ED93DDAF74555AB9BECC78B
+:10920000D9C5DE8358AFC7A5B67BD543C487BFBEDB
+:10921000BFF0487E98BFB0238E75FBD76A601F39B8
+:1092200055590CE34BA2DC2529E85FABDE2DA09C51
+:10923000583A87D349CAD04A9217BDFD6D5D396847
+:109240002F74E04DF12CC283B771DD1D557B090FE2
+:10925000AE5DCDFD241D55171222E3C1DF5C5FCF4B
+:10926000CF389EF2837579B9B31B0F02AF4DF90A5F
+:10927000F272FE3CA3BC4CD1E83EA5FAF443E89759
+:1092800016353C109DDC2F8DFC13F160701FFE47DE
+:109290001D0FEA1056801775B239AEC8EFE55EA80B
+:1092A000DE4B7FBEA5AFF55D3E2F548BAF633C9187
+:1092B000C7D7DF453CB556F17862C7FAD964275E57
+:1092C000A81664F437EFA9BE5DC0F39B5D1210428F
+:1092D000CEF0797AE5833AE60DEC891FEAF1C2E334
+:1092E00005DE687C3F1D702A291EFD7F9A1F7D6860
+:1092F00064FF1FE077FC3CD43F0FCB244F743F3A10
+:109300009374FC561370BC71B6AE6132E1B72F098D
+:10931000DB771EFA2FCA0BE8F113F23CB37FD8CFEC
+:10932000556AF473ED5C6ADB43DFD763A15C8A8F17
+:10933000601C01F9F6363BE533960B0AE5FFFDB5F7
+:10934000C03796F6C1BC9467EA2B76C8E40F734D1C
+:109350004E42FC286D10496EF7659FF4A6B3D3C446
+:109360005F5200AF347E437044391D158774271057
+:109370007F1181BFC4A01C44BA1B1BCE5F024B8867
+:10938000BF328B3B36F58AF84C0EC2B91F3E933B79
+:10939000CFC86766CDFB07E212C17CC6ED3A6DDF30
+:1093A000A87FD2BE357AEADE77099733A287EFBB72
+:1093B0005B2FD5F88C998ECCFBFA7F90AED6F54119
+:1093C000577722BCBF025DDD7319BABA17EBC3E849
+:1093D000AA96CEFF5F8FAE5AAF84AEC6CE63C6FCF0
+:1093E00063ED3BCA63BE63E1F98BFF97F38F13E72D
+:1093F00072FBDC9C7F8CF92258CE87B3A1F3D1CAD3
+:10940000F3273205EFA7D977BFB465B4C2C70BF70E
+:109410007B3293BF9399FC9B66FD2E823FD4E0FF85
+:109420003CFEC4EF8E8F865F7FFCE47F915EFBC6BF
+:109430002C81E28FF3477D7118F5FD82CD6BB53C31
+:10944000F7FEFD9FFF6C7F27FE84FB57CDFBDA14F0
+:1094500073BF068FAFE6EF64EE1AFA7E7867257366
+:1094600013DC2FE3FFEC94471AF285BD2F963FB82B
+:1094700010FD9FC7F977F8CC7E4F3D0FB8B5643922
+:10948000E9F96754875B8CE0F75C9EA0DC46FEDC64
+:10949000DE7ECFBF221DFCA37ECF657315C243B312
+:1094A000FFB318D8D5FC7EE2BE1D719502F2BB9CBD
+:1094B0001237E5DBB14BEBE8EF39882521D2034BBE
+:1094C000ABB81E38A0C0E7C2715286B27107D13E58
+:1094D000A912DC16A5375F063D33767E785EC93764
+:1094E000EC2FF867F9FB5E99FBD5EEA5BF82F09EE5
+:1094F000D4CFFD7425F430E6AD3D52E3A2EF563DE6
+:10950000A2E9D11D929A84DF397F2BEE030BF2EF93
+:10951000408B85E1BD31B35EDCF7FEB8FCEACBCF12
+:1095200024A17D34B6C73EAAEDF623B91DE17EA481
+:10953000FA0D9E43E722C049D78BB7CD37DA47A54E
+:1095400025DC9E2D2D51C98F549AE861387E8A936F
+:10955000B5A15C1493BA24D4539655F8C8BE37C746
+:10956000E1CD78628ECB9BE3F0E638FDFFAF71F979
+:10957000F5F38DDF651CA7E5A1206FC7EFE998E340
+:10958000F09BADDC4ED9A9C23BDCCC578CCB5F75D0
+:10959000E9011EE757B9BF3499713D2D259FFB4B5B
+:1095A000CD7AC723526033DADD8FD458F4EF5618E2
+:1095B000E2FA635D3C3F7ADCFC05FB293F47D70BB1
+:1095C0002B402F14482FA4EF1C9556540A1CAFAA09
+:1095D0008EE03DD36532C7ABF9F339DD5887BA4920
+:1095E0000F16AB6F67FCDE959FDE97A6F2FB60D18E
+:1095F0008867D054CCE4715FF984E8C6FB095BB19D
+:10960000E934BC0FCAB81F679A85FEBE438B5099D8
+:109610008CFCF80141A627E84A748FF0C93875D050
+:1096200012F2DF58C86F7F2CB72109D7D758B32D56
+:1096300009F336DB34BFF8B6DC0FE8FB0EE2582640
+:10964000A39E02CF887FCFF39E0582F67781DA92C0
+:10965000E8FB02AC99F44931D3C6F8DFCF71075764
+:10966000201E9D73929EF08010E0F76E5C0EBADFB4
+:10967000D67CB52DB91CD6D3E4B291165177F5AC92
+:109680001369F0BE69A01C8B7180BAB474D94F7194
+:10969000EA865791BE9BD2D219E6CF37964CA67B6D
+:1096A000748D9780B140CFDAD123DF9A04EF370B66
+:1096B00021FA0E8F7F9A85E2F02D57CF4A0EBFE731
+:1096C00028CA3653DC93EB95A262A17B73A216CF16
+:1096D000167BC5B38DF1E9AB1670BD4861CD8BE942
+:1096E0005EA5D326E37E4BAF1E4F79AF179D36CADA
+:1096F000072A9518FF8EC6D58CCE2502BF337C571E
+:109700004532AD6F3306A629FFF98155A887E31DC1
+:10971000409E9F5FC3CBDDF5DF5B85F8431FDB8198
+:10972000F2D937EF5A85F9F80AE37FF7A33693E7C2
+:109730004F96BA0A89FF964AA188DFCDBDDC7A141C
+:109740001650B5F1D8FFE6789BAFB62DC67B44978F
+:109750001BAFE75C02C4BFBFEAB87A3BF3B8E67E52
+:10976000FF5BEDFBDAA76581FEBD43467910A41AC5
+:109770006AF7C3503FB66AFCB0367B7220A8603EE1
+:10978000AF9FD3459C2562BE6CDFF411363E4FCEB1
+:10979000257E4BE3E3B75CAAF2826913F9FBC2A40E
+:1097A0001EBAE9CEBFD0C683AA97514E6CD2F90536
+:1097B000560DEA19F7372513280F16EC0B25C11D96
+:1097C00081FEB43C0D6A9F46F7647F8B79E26C346E
+:1097D000233EA2B7B76AF39AF336B66BF37ED5BCD5
+:1097E0008D73B88789246BC80EACFB6D33E52F31C0
+:1097F000FCB813FA67B364BA5F769F10A07B91FE42
+:10980000951CBEFA3944B1EE1FB27BF47C9848F93E
+:109810003268BF25E9ADC3CF219DCE7204EAED9B2E
+:10982000478DA3BF136965CD8F3F01CF1D0736FE5E
+:1098300011F33EA2478CBB7FEA44BCC76E71E3F2D2
+:109840009CFFB6E36FA80A378C5DD98CC3ACD822D5
+:10985000A8E8D7B7CBCE3D681F318740768375FB2C
+:1098600060E20B49E5C6736F15D45FE377F4FC5BE8
+:1098700005E2A3516EA35D611B6A6CBF4EA33BB3AF
+:109880007DF2801039EEFDCC022E67AC686F84E962
+:109890000DDB2485BE0BBB6DB388914CB66DBD9DB1
+:1098A000F8D9CB6F15AEC2EF76DF592F11DC5B6FA5
+:1098B000B0D1DF8B6A75C98B16635993677A9CF9AF
+:1098C000816B4606C2FFAED0D39A9C6DBEC146F2F4
+:1098D0008059BB92D02F6BBE6FDDCBBE32E1DDE590
+:1098E000F02C7741BC86DF01922BDD76FD280BBF83
+:1098F000573CCAF22F71AF786E373D7CB3F78AE7D9
+:10990000A2613EB027DFCFDA2BBF2795FC7BF5B3F2
+:109910006DF4FDB5AF6AEF6E5BBF8AE485FF76E656
+:10992000CE70F7CE0BF3BE3882F0476C14C90F2708
+:109930009AECD9FDF3A56EFEE308E3937A5ED07648
+:10994000ED9EEE766F03E5CFD479F83DDDA8E655C0
+:1099500064276F033D0CF3AA74BBF8CCD4F4C9029E
+:10996000E5FDA87EFC4EC6996C2D2F48367E4789B2
+:1099700069F97DFA7CDBA6A6D37C756887F7830737
+:10998000568F766FD7345E37BF467B3BECEF6982EC
+:10999000BD7D6E01C0FF7EA71B9D7050FF12D5B329
+:1099A00089F15774AFB2137F85761945EAC7384EEF
+:1099B0005EC6243FDA7967D80086F038E772CF4276
+:1099C000B5BB43723BC2FFFE416DB3A47D8F02E67F
+:1099D0001D4BF96D4B0B11EF4748C43FC4C42C7AA3
+:1099E0005FEEF25A2DB02EC19B6E884FE6B116EB9A
+:1099F0005AB2AB023329FE5DCE648CB794B99A2972
+:109A0000CE928B0B8489672B33C8CEF31CE6DF59CB
+:109A10009C1EF7FD449443FF0700378FAE00800083
+:109A2000000000001F8B080000000000000BAD3B91
+:109A30006B705BD599DFD5BDBA926C49BEB2652318
+:109A40001313AEED189CC43137217165089BEB47A9
+:109A5000880D29556CC749769C548140C3B4D36A9C
+:109A60005BBA4D76682DC772E2386014D3D661CBED
+:109A7000B622C0B6BB74C0A52FC8D08E1CB29467E6
+:109A8000715BDAC2B643454ABDA5D31FEE23E0EEB3
+:109A90006427FB7DDFB93796642571D28881C3B90D
+:109AA000E79CEF9CF3BD1FC78DC78E54451B00205C
+:109AB0006EFEB4BE092000E2B7DC3515695B0D30DF
+:109AC000F89A6CECE32FDA643408A084641831004F
+:109AD000A4A7D686325EEC7BA77F0D7E809B6600B6
+:109AE000DADD62ED19FC77DDAC1BDAEBE7FA2D0865
+:109AF00039BBDFE6AECC99BF5EABCE1997C134D28D
+:109B000012C086D0D29C79BE35AB353A6FA7BE3233
+:109B1000E7FBADF5CD39EBA15D3999C1FE5AFCE704
+:109B20004C0DC1137D1EAF06F036603F6BBD025970
+:109B30007D1CAF8BF882D3C5D8F9107CE88C0CB0B3
+:109B4000118CAD10A45187F138E2A5E2983B53EC9B
+:109B5000C0AE69EAC10AC4070DE9007D115CBC060C
+:109B6000FBDE6907E0BC8711865C09D0A8651C9FF5
+:109B7000263C6B13127F0798184164871493E741C2
+:109B800008B404CE5B047149C3BE2F0449EA5F05E3
+:109B9000499E8FBFE483CD004BDC62BDBF0B8C07B9
+:109BA00070BCB8212E49D82FED004346785E634A39
+:109BB000A2736AB85E5E09500969EE5775C0D42079
+:109BC000C337F7D1FACA3DA00D5512D8388FA7FA7E
+:109BD000204EE779040C70C9848F08402D800A312B
+:109BE0006EAF06BD1491088F82B18AFA759021A4D8
+:109BF00022555312F5AF80098DFA006988ACC02652
+:109C0000A304A6DD3C05CEACC37FE957A0A59DA665
+:109C10006DBAE0E4AFDC667647107FBDDBD69444D6
+:109C2000BDE75EA7EC797EA2FDFAB9FE6804915FFC
+:109C30004EDF37003450FB028F3F1589EC88E0F788
+:109C40004684EF5E75F1F86F54053E131218719C4F
+:109C50009F78F696D04E1C8F3FEB36EA80F08BF85B
+:109C600024BE08BB675E6A16EB891E41A407E1BBF0
+:109C7000B40124C2C1554407FCAE221D0E321D930F
+:109C80000C77710C8C016B5FEA57221D882E29D04E
+:109C90008A08AF72ECE2E8C03F8473C533EE4746F2
+:109CA00024C22ED2A5F6B2D0653FE1F162E9924F0F
+:109CB0000FB8B70CA0F97CFBC6998E5F91D21EA994
+:109CC00096C882F4C1FB48481FC26708043D54008F
+:109CD00083F05408FFD4F7AC067D1FF7C57CA2675C
+:109CE000BC798EFF4B90FF455FC85700E920FA8290
+:109CF0004E419217EC872213BCBE741744EEAF247A
+:109D00007A988C3C2744B975C18C446D8D6430BD04
+:109D10006AE58883FAC5525A20192949FAC00F1AF0
+:109D2000D3E74A88711B74CE4C9EC17D125E472AD0
+:109D30005E4DEDD32DB4CFE046D43028B70DBEB183
+:109D400016E6CBBB41AB43BE5BAC9AEE6AE29765CD
+:109D50008A11D7B3F1B58FE1836E1E29A671870FE3
+:109D60004656CFED9B701AA124D2EB75DFF4F12893
+:109D70007E2FAA94C165CCE1F9A453DC8F60CA8B15
+:109D8000481E847C84C27896C07CFD165204DF7A1B
+:109D90007723FE101F3B6800F1240D7F9FBF3FDC3F
+:109DA00026F4DD8391E8EB24C7A49F187F2668A4DE
+:109DB0009F3403586F3AF4F8EF64FC7E6AD8A51319
+:109DC0009F4272DC74E33E3BAD7D760EBBDE91FCC0
+:109DD00059F74CB8206DEBE71A5A1F29617E3624DB
+:109DE00070372D7CDDA5F23FEC292766BB20DFB65E
+:109DF0003CB5B624D370EE792AC94759F63A4127C3
+:109E00003588FCE4A5F11778FC42709C7B2673E44E
+:109E1000CC86E30C45188E73CF09216F64B7909EF2
+:109E200077A1DD1A417C7FD4D454C19733FF45F626
+:109E3000FCF698DF207BCE28C2797724A5D408F2DF
+:109E4000E39D1053894F25581227FAED884BC60819
+:109E50004EA939B8CBCFFE02B46B841F297DA37CF9
+:109E600066F945E0D1C2D38EF47B4EDD4778F5C16B
+:109E70006FEDF19AB9F1BFF4D5BEBE4627A5EDADA1
+:109E800027FA165BF445B51D7F05CFE93C5D02233B
+:109E90001A727FF1175E5B87E71BFA996CC8D5349D
+:109EA0004F0513E11581B0E3C524A7B5C42F13E90D
+:109EB0008F13BFED29D1E8BEF63CB0E6C5216AD2CA
+:109EC0003D8B510F105C47F17DCC9FC57E55979916
+:109ED000F951E364DFC38D7C57C1A8E65FB99A4EA0
+:109EE000937C95B7BA8D815CF8D2195A8F30A1C294
+:109EF000BA87347FFF15D477F350CB196B3FD39DCE
+:109F0000B55F5EDF19CAEA83188F67CF3754486799
+:109F1000E1F5ACBC5872669FDBEB5573E5256F9D90
+:109F20004D8F06A7E08F4008520378DEE1E1D2961C
+:109F300062EC8F064077E1D0FE1B2A2440B96ED533
+:109F4000C43C7F15A45C12EDA38FD4B3DFE865FE9B
+:109F5000F1FFDE4C7F9CF831ECD274C453E08FC625
+:109F60009489FD3B436EC3C4F1419A4FF6B50AFD97
+:109F70002C9DB7FF05F9A57758E7BD82708372F86D
+:109F8000B14DC2CF927DABF7BF82F00F5C29834CFD
+:109F90007BCB1B0DE2CF3B1480B252ECDFE764BFFA
+:109FA0000FFD3BBE8F5A95EBF7DD79C439E717C239
+:109FB0007C3FF0AE4DB97E606C13F0BE749EB2551E
+:109FC0007F3F7CE80BB2FE5CA14C39B40276D5C66B
+:109FD000BFF49497F1FA8372C42BAD8388F929EC0E
+:109FE000BB108FC4AFA8A8FD6B104F84439213DF42
+:109FF0009AEF7C9AE6BB4E21FFD27CD9DBFE29DCAE
+:10A00000CAB908F1C4FADFC9E730F11F3A77BE3F99
+:10A01000ECCA3BA733CF7F962D3A8C107E50FEA121
+:10A02000099A083FE89FB37F00DE60413BFF5C3F39
+:10A030006A0EE4A51FF6BBB94DF76BDC1EEF0F717E
+:10A040007BA25F877674AC5EE8AFE7F6C57E83BF20
+:10A05000BFDC1FE6D6C6C7B9F48DAFDCC1FEC2E1D6
+:10A060007B1D291226A5417BE95AC4C3956FC8AC54
+:10A070003EFCA07B14D4077EC48182F3AEEE505226
+:10A0800026DDC58A7FAEB0F86CB96B66D245FC5D43
+:10A0900009C63E5A08B1813B56CFC53F37CD38E699
+:10A0A000E40428DE299AB33340F14E594EBFCDBDAA
+:10A0B0002867FE7AAD3667DCA6EFD79A85DC6C0898
+:10A0C0002DCF997FB8BD35FD313CAFBFD9A5119FCC
+:10A0D00077EAD7E78CDF5A7F630E3C5B0E4AFB942E
+:10A0E0001CFEF3E7D155DD7DFE38C8A6F38F6C3A30
+:10A0F0005B72702EFAE6F3AD8DD7D2B37815716529
+:10A1000082E24A9DEEDD20ED0C129E6DBFC4848874
+:10A110008FF480D85709637CD978F9E34B3FC59712
+:10A12000D585E2CB7735E2DF0BC6971DB9F1653EE9
+:10A130005E2F145FFE691E3E4B1784CF1D8B63AFED
+:10A14000ADA178EF5599FD40B923C6F6AF6C4A36FC
+:10A150003620DC72CB1FF391CCE3BC1D6B54F62F81
+:10A160000F43264476FF0109B18AFC5FD660549202
+:10A17000BE793260566CA338BFD3611CC525CFB7FA
+:10A180007C39447EC7C1814742689420D8E5607D10
+:10A19000976C99DE4E72A5E8E8C749DC9AA902FEE1
+:10A1A000893DFFB3434E8E431ED8AEA6249CFF804C
+:10A1B0004FEBDD4A7D6B1F4408DBDBF135D7A4C8CC
+:10A1C000FF2BEFD205BF403C44F47F707B53251B2F
+:10A1D0002905FB2B68BAC1767CC46798248789DF80
+:10A1E00079218E9FEE9734BF44FEEB7687F638DEFA
+:10A1F00073BC63D55BBBB07FD0AB1A24F0894053EE
+:10A2000025F197BC03DD1EEC8F758CBDC8725CE731
+:10A21000E07E62FB35AF93FB3C5EAE75D6509CB7DB
+:10A22000BE86300DF233A7FB29AF91084C8768FD3D
+:10A23000E00D62FDB9E8236B59F61C387FC1E79544
+:10A240009738D22AC2919F9BFE3F822767DB71D647
+:10A25000E3B97EC54840A52001CCAE2BFF23BE84C8
+:10A2600054B969121DC751E6094F3BB67795503C6A
+:10A27000B5C399292F642F8650BFA6AFCDF237837F
+:10A28000B97E423E7CFE35117EF1E7105DBDC20A0B
+:10A290005DF097B8EDE6549AF006C98E1AB2CB5E1F
+:10A2A000B4CB709EF8CF9B8B071B3EC3C3FFC87B0C
+:10A2B0003CA6270B0F78AD34F93BBD5D12F3CD966C
+:10A2C000B37C001C77D8E7523A1CBCCED60FC8C767
+:10A2D0005B27883F2CBC87D064901CDAE7885AF053
+:10A2E00076CEC103AD22EB1C6B550B9EC171F1758F
+:10A2F000AA902BF885CC7EC73C3A59FE1BAFAF9E87
+:10A300001B57ACF35F7B44CDD1BF9FA1FD71DF5FD5
+:10A31000F6759F375E5E9ACA5D77B80BF8DCCB6442
+:10A32000F3F834C5B5D73A528F23A8E5D73A589EEB
+:10A330004FA15F4576ED5CF06CFAB388553077A19C
+:10A34000D38EFE59B08BF9FC5CEBD4D49459DD4824
+:10A35000FB426C02F96B6928F75CF6BCC367EFF54A
+:10A360001928A2F3A0434EF6C8954A9BA4A75D08FE
+:10A3700047C2B6FE917BB4F3DDDB0559F0119FEFC8
+:10A380004A425FC503C0F74DBC9562F98167667E9E
+:10A390004BF29D585AA18FB0BC40684913F923E293
+:10A3A0005ECE3C3A8D78049CB195C24F1DB3FAF154
+:10A3B00015022E64CB29AEF7587995AF77D5F2BD4B
+:10A3C00054D2334464C55C4C7CE155BE15D7901F14
+:10A3D0008ABC872180AD2BB8334EEDBAC5FA681818
+:10A3E000CF35B6D4C1766CCC177D6488F4D0526F6B
+:10A3F00041F9F81EE945843F4C7CCBF113980E924D
+:10A400003BC91612883A905EE3CCF9002F750544DB
+:10A410003E4B4B866F473C1EB7F802EFC3EBF3E1B0
+:10A420009F980FFF31E2D784059CE0EC44382F5B06
+:10A43000720164502AACB80FF773EBC930F90BAF57
+:10A440007469425E949506DD7F2C5078BF57ACFD51
+:10A450004C474CA27957F489F5E016EB1E9066B68E
+:10A460009E14F46479A2FD69BCD8C8D50FF9703D7B
+:10A47000F5B9FA4AADCA9DFF96C57FF9F1D0FD52F4
+:10A48000E173FEAF75DF758B81ED11F1C5BE027C06
+:10A49000912FEF2AE53F11EE7B4407C697D03B5E34
+:10A4A00065AA95E21E6F0318ECA328937CDF7DC597
+:10A4B000B7719C3C74ABC873A88AD0DB555B110C98
+:10A4C000DAE3C80FDAE3D497EF01CD15988F878BC5
+:10A4D0008DF7C8DEC4B3D69F26FE2817F78867DD40
+:10A4E00023E9D46FA37D930765203F20B9D7B5B585
+:10A4F00090DD862EE7593DE9B6F52ED20D8C6A70B7
+:10A50000E0FA236FC89C173812DECF717122A2EADD
+:10A510005235E5291E86BD38FE17D3C17EEB9E67F6
+:10A52000EEFDCDCBB8EC647B4D93E46039823B719A
+:10A53000FE498C8BC96F26F9CBC9C72062DD4D73EC
+:10A54000FB25DB6B78BF04EE279D47CF29118C5B81
+:10A550001BE7C33B6B8FF3F223231551BD1BEF7732
+:10A56000D86B703E52B6F3233DC105E5757448A61D
+:10A57000F7905EE903C683AF730CF6523E2124E2E6
+:10A580008CE36B5C82BFF64A567C06ED60EB29FCDF
+:10A590006DECD31F2A23FBF2A60BEA70BCF589579A
+:10A5A00015EA8F553A9A287EBE4ECD1CBA8EC69BB0
+:10A5B0009CAC3F5A9092E91CFE48BB1C213E8F6A1E
+:10A5C000B5B268D312B56DEEE21C7DBD5ECB8D3F9A
+:10A5D00046678FCB25C49F1A1812E279B4C5304B59
+:10A5E00048F7189941FA3EBA5E374674F28773E32A
+:10A5F00094D14E55E8D36A6177C626F587C8BF3A2D
+:10A60000B0C7C3FEE7FD550E71EF2590227EE8D45A
+:10A6100073E39AB1899A834B48CE924ECE977F735B
+:10A6200042CCDF35B0324571A966F9ABBB2A5BD9A4
+:10A630000F852131EFD6FAE579F79FD2882F927BEB
+:10A640009D40F83F5075FB30E543DF4938AF277137
+:10A65000F96EB7CE726AD36DE7D09D5C271A52614E
+:10A660001B9D7F74BBCAFC3F5AFECE913B484F975F
+:10A6700017319EC7B7AB95D12C7978AFDBC570C6C3
+:10A68000B70BFFA2DC01D18902E3EF750BBDF2E14C
+:10A69000BB81EF43F90E1D3FE94A2CED227C5401AA
+:10A6A000FC2B5D27F4EE97F8FE1D0EA8C3238E0544
+:10A6B000FBD87FCBE7B30FBAEB72CEEF0A3B72F059
+:10A6C000E87445629CE7BE1574D257ED1DD8A7F813
+:10A6D000BE4F05E23757E81EBE6729F63DD87777AB
+:10A6E00024E30AF6DD4BA2D793DFFAFCDE2DC32D5F
+:10A6F00041B25F0E8DF8CDD57757A49BE6AF768239
+:10A7000007C78740974274CEB804A4AF7588769087
+:10A71000BF3E16726894B7D998D8BC9BF6DF182C48
+:10A7200002A2F38E4E07EF77CA543969554E8E0652
+:10A73000E5BF2ABC6C77DF76C61EDA82F3DF467A85
+:10A74000C561EE5E8F76D7F03D3D7A6EFCEC8624D7
+:10A75000DBE1B5E6541FEDB336AC5245038E374FFF
+:10A760001F217F7D7C8DCB70E1B9C69B25C6F7FB91
+:10A770006B9C293C2AFC509D9269DF1FBE8FBC5107
+:10A780005D487ECF2F37F9F347C35D6EE287FD301A
+:10A79000D543F889CF8A3C54FEBC253D82FEFB118F
+:10A7A0002F84E7389EB78EE2A219942B841E988DD1
+:10A7B0007C837244DBBA15D61F9FAD74C4A92E7476
+:10A7C000A053653939E08B0E57531FF99DE3A16003
+:10A7D00094F979AC32C87268EF33D6DC5B4FFCF287
+:10A7E000DA1A0FFBED7D3FFBD5DDE4B7B7CA7FFC7E
+:10A7F000F653143F55A94CCF03CE48FA65E2EB4E11
+:10A80000E12F9EB8EA9F59EE86FA6E07C21BC46319
+:10A810006F52DD6A687533C3B7F30D6357897CD215
+:10A8200050F0D3F15DD84F87457EC12C3F2A01EB14
+:10A830006791576AB1F4D87257ECA53A5A77B722A4
+:10A84000EAC2725582F4816B91C8BF998A3327EEB0
+:10A85000BD6926370EBE322F0ECECF33817B6A49BB
+:10A8600037DAD39F775B79372BAF445760395EED8A
+:10A87000E278713C2CE2A0A43356A935CC97E31FB3
+:10A880005B7EF054BF1B3900E0A7FD1AF7FDE69F81
+:10A8900006CA10D41BFD21FEFE91B58F48D9EB46A8
+:10A8A000576F76EBAC373221829BAF2FF2F9E08EF7
+:10A8B000EE22E6038CD380E83B3A038C5F5FF3AA79
+:10A8C00034F1E9A9BF02C7A1FFD03EE5859AF9EBB3
+:10A8D000D3744E17E5BFC4394FD0395D94FF12E7EA
+:10A8E0007BB15FE7F6E5FE7A6E57F680C8F3DBFAD8
+:10A8F000E06AD40788B7F62AD127F9273B5C1ABC4F
+:10A900003D42FCE50A291AC9B7BB2A9996B2F4C19F
+:10A91000B82FF616D9E503E55EE6BFFC73057A1C91
+:10A92000D6BD62DB08EE28C225BC3FBFF77FBE5410
+:10A930004BFBBC21335F95F6F5EE66BD837AC1C350
+:10A94000FE86D087C9722FE71DC6F7D64921ECEFE6
+:10A9500018108EEE05E51EF749E1BAE3A8AFA97F0E
+:10A9600000E59CEE73A0F99D8FD33EEFFFAD882AE2
+:10A970007C48EF5FB0DCBF860148D965947B5BCE35
+:10A98000BEDFFDA4157F47B63C23EECF7A70DC37DF
+:10A9900095A4FB1FF8B90C85F076A9740573617E48
+:10A9A000484A99993C132C50373445DD7070E23B8E
+:10A9B000DC8F6F04A8C3FE579DA69BF8E0AB038E07
+:10A9C000F3D60DBF3A70FEBA61EA8B0E706973E779
+:10A9D000580419CEB352084F75C0211AC2B6A92720
+:10A9E0007A5B0FFBCBA2AEA83753CE81FA5A11F98E
+:10A9F000CF4F45CC8FF4909F1914F9AE9032912629
+:10AA0000BB1EA27AB94EEF17E25CF7D4280C5B3973
+:10AA1000FFFE83CE4C2BDF0FA750BD32BF3E2979FE
+:10AA2000BF27EAFBB5A20E69D7271BD5CCD143843B
+:10AA3000A76D6EC6C3E0B337BC49F52FBB8E1FB2FE
+:10AA4000EAC0DA6ED006C43D3EC6E77C4ED443E190
+:10AA500006BCC74ADA2453B36905D7373F41E31729
+:10AA60003AFF42EB861B2DFD86CC9D2279FE8D851B
+:10AA70004F7BDE80258FD7A9226F0D7E95F57CEB6D
+:10AA8000135E90C95FF6A947494E7642663DC9D329
+:10AA90006040F86D89C34EF6DBF6F5E8BCBE5C3568
+:10AAA000F9FD42F9BF788C01049398D4FC9447AA2D
+:10AAB000EB36F7F5F039923D5D748E6199F5DDDB8B
+:10AAC00075EBE3C41F9D5209CBA3A2998BB3F5E5A7
+:10AAD000A33D3539F9F84EF8A242EF5CD62D9EE938
+:10AAE000E2FD7D0EA0782BE1315ED409DF3F5018E6
+:10AAF0006E27A4DAF9BEBB346918EF39E83DC9F412
+:10AB00005957E75A49FAE951CBBE267C85E3BA7F0B
+:10AB1000EB11F1E7FA4DD187E9DCB7C04C1BE937FF
+:10AB2000146D23CEEF5A445EE751D29722AEB9D7C7
+:10AB3000D13497D77AC9197D94D699DF14FE842B26
+:10AB400024FC7A279869C2D7AB9BCCC7888F371271
+:10AB50009FAF6645058FAF9C7F8E27AC73F4F69848
+:10AB6000FF49F08E59FAB95133B9EEDA080E633065
+:10AB7000985557D717565797B4EF897AFA8D828F21
+:10AB8000E1B9B8E0C356D0489E90FF8ED1F9ECF7FA
+:10AB9000258DC7765773DDE512EBDBEF6F328F1330
+:10ABA000BC3F442227E81E6FEFDD020C6F81EF35BA
+:10ABB000D62DCE8422642F3DC26F7EB2C5D81AC96D
+:10ABC000CAFF9CB2F8F79445D7E5C84E53942F506E
+:10ABD0000CB6E3D740D84DFA211F7EA21F26A8EE5F
+:10ABE00073AEFD9D074FBA294F3C186E75D37BB4E9
+:10ABF00084B7B584FAA3556688F61FEAEF78F6DDC8
+:10AC00003AE223C1F7F166918FD88FFA39EE9A8331
+:10AC1000F3871E99CFD5168634E5D3FD5EE117F98B
+:10AC2000315ED4918FFCC130DB73FC3E41A9833F80
+:10AC3000933C51BC1D32C0A478321C05920BBF3628
+:10AC4000B79E4C5E5B380374AE73C191AB70BD9719
+:10AC5000D6C718DFE59B353E872BE4988BE361E18F
+:10AC6000F8DA4FF8AA3B4FDE8DF0D5706E7C9DC5AB
+:10AC7000BB2577F978F26D96F9DECF07A6F95E70FD
+:10AC8000BA8DF3227E547854CF2FDB2CF48CEC3524
+:10AC900021EAA37A5994EF970864C06898C32FFA01
+:10ACA0008A8C5F59CBF03A7FD880E80AC2478CF192
+:10ACB000997FFFC663DF6827BCBDB453E8D5758AAA
+:10ACC000A53F627817E4CF7FB2F41B5876A9D3234F
+:10ACD000ECCE46F88957E4B5059F36A23BEE2E9D93
+:10ACE000AF5FEDF6492BAF9CFFFDE79B3D220FA028
+:10ACF0004FB07E1FEC10F07D3EE1871E1D5EC5FE4D
+:10AD0000C3CD957545D9FAF172D709F3EB8217AA2D
+:10AD100003CEF18DC974FF8B7632BE493F377F1C5D
+:10AD2000B2E46DA8DF5D50EE0E2D8E840C92AB6602
+:10AD3000330E48B7FD814C88F86768F23DF693956D
+:10AD4000576583FC4D458900CDBBB93CC3F4DF108A
+:10AD50003681EA4A87FACD6F65C3FDECA668F766CF
+:10AD60007A27A44D9804C70BE938D9A35BCACC58FD
+:10AD7000A4001D3EBA59E4FF5EDD14D9B699F40E65
+:10AD8000E9CE55E86B45CC7FA4FE42F5D57C79EA47
+:10AD90007093BDB87479EA72D3FD46AB22FC4E6B5A
+:10ADA000F42732795873FEA5254FA3CDD3AC276C79
+:10ADB000B9FADCE63CBD13B4F44ED064B9F8FC66D5
+:10ADC000DDCA0347583E9C244FD97A2668EB199375
+:10ADD000E55109DAF264C91FC9137EBFCE39D346E3
+:10ADE0007ECA1088778CF9F235BE299A203A5C57D2
+:10ADF000FEE7EE6A7DEEFDA7AE0B791AADB2F8BDA7
+:10AE0000F969E6FF53C8FFF45878D05B93C3EF7637
+:10AE1000BB7656863492E2A65989DB7F982DE6767A
+:10AE2000DDAC875B73B68CDB96D900B7ADB38BB85E
+:10AE30006D9BADE4B67D16F9FE7AE4FFD96A6E6FBC
+:10AE40009E5DCEED86D9A5DC76CC5ECFF33A675712
+:10AE5000727BCBEC8DDCDE3ADB2CF6A19A5069419B
+:10AE6000FEA772D665E07F234EF5D1A1C9BBDF24D2
+:10AE7000FC383595F328894013D77B9C4A86F9FF27
+:10AE80006858D8870D5E419F7CFE7F7553F4DB8543
+:10AE9000F87FD009CF90CB95EF27A0BFF32CF1B965
+:10AEA000E47DE16F9CFF740A3F07FD8F63CCFF9741
+:10AEB00068FFCFFA9515B97EE56879AE5F39D46C35
+:10AEC000FB95AE14D5C176493ABF137B7F53F4C7C7
+:10AED0009B59FF4676D278B4C7AD913F9508DC1CEC
+:10AEE000F2627FC77E1928DF87FEC514CF43FD407D
+:10AEF0007663A1F29AB6DEF7DAF31BE1A4237611AA
+:10AF0000FEC9DBF4BFCD85E4BEDE734976D4D92615
+:10AF1000E45E13729FA88A0C53BE259127F7B61DD5
+:10AF2000453CE4C8FDFBB6DC5B725C1A14EF3E4A9C
+:10AF300049EE919EA7CFCA7DAE1D55ACF9CE0E51FC
+:10AF4000DF6A0B0ABDAA74087DA168B97614F905F9
+:10AF50007A0BF8137145F04D67DD77CFDA33B2AB7A
+:10AF6000A5C18054825B6B7FCDC489FD26955A961E
+:10AF7000EF7C394A68AB98CF2795362824FF0B968B
+:10AF8000A3806D474CB623F9F36C791A9AEC64BC34
+:10AF9000D8766512EF6D66D9930D9AC003DA93AB3C
+:10AFA0007A0BC8D3BAC5663452E09C2B7A85FFFE73
+:10AFB000CA4D11E12FA29F487E4AC259D80F58D1DD
+:10AFC0002BE856DA9154086FEB758895A11EECE8D2
+:10AFD00048B7510D03E579452FC2BBC9CC0C920C83
+:10AFE0000E7AC782747E94CF463AD7A5CA67D9260F
+:10AFF000AB2EB7A78CFD16BBBD10DFDBFE8ECDFFE1
+:10B00000F9F39EAC36B716C2CB915EE1AF1F1D7E41
+:10B010003A873F924AED2D865E50AF9AC665D1AB16
+:10B020000BF32B26D1CEB15E3DB75FB183E8B050B4
+:10B03000BFE2CEDEB37EC52EA2D3BA06E1571CE92D
+:10B0400085CBEB2FB4D8F1CAA5F90B9FEF3DBFBF5D
+:10B0500030D8ABF3B8827E35E90DBFA5372ED65F69
+:10B0600028E01F1CECE5387A46A6FA1FA2DA10F990
+:10B07000105117453D733FE10DE378F6178E7A05C1
+:10B08000BF988A6D9F220FD078D214FEC2E592033A
+:10B09000F4FB1EEA2D5FB83C2C745EDD636B8733D6
+:10B0A000E4E7802F49EFA607E9BD12C58FBFF689F7
+:10B0B000770400F594F7FF9CBCCC203B375EFC8501
+:10B0C000AFD1FC3D7105E8DDE083FD22FF374AF991
+:10B0D000BF6BB1EF8C7D9DC6F70FB8B4A308EF83AB
+:10B0E000227FDC813CF58167718ADE051DB3E4CDEA
+:10B0F00005DB4B0AF1D5DCF9C4FB5C7ABA7286FF3A
+:10B10000AEA34AE33CB98D1F350271843FB2C2C180
+:10B11000F591910F7FF3C8ED74EE0FBB0DAA3F714F
+:10B12000A115FB65CB429C47476F10C25979111995
+:10B130009469CAC70FD31BF5ACFA6B7023C6D159FB
+:10B140007146493892D3D721CAFB1E0E3A18EEA198
+:10B150007611171DF24EB8B502FAE5BEFEDC774A4D
+:10B16000F9ADBCE60D7E273856AF70DDE7FED54B56
+:10B170003A494E0E2EE14A3114D53922A902727C89
+:10B18000DA92631D740FE1D1D3D95552C8AED8ED10
+:10B1900060DE39642D6A92BE2EAA4E46888F8BEAF5
+:10B1A00082523C0B0FBFB4E08F48F1F43A7E8F26F9
+:10B1B000EC04C5BBF44E65A8FC2EAE47BA31DE9F49
+:10B1C000C6EF6EB44BBFC5B6AC428D163A2F6C11AC
+:10B1D000F99011672A42741959AA709D1279AA60D0
+:10B1E000DEEBF796BD2AAA1BE3F3419DC275A7FCCF
+:10B1F00079BFB2E7A949AE631CACFB779DE4EEE0F2
+:10B2000055C0F9EDFFFEE5AE270648BFF4231D9DAE
+:10B21000C4AF1DDC162DFB06E37DB451D1E81EEB57
+:10B22000E5B5035C27DA0806F927F97C50BC62898A
+:10B2300087F39D1D0EF6EFF2F9A20819758AFC340A
+:10B2400025C376C2092FB2DE1C3544DCA463B42AC0
+:10B25000FA825FEC7A53D0E2C7FC7B8D5A72B5DF7D
+:10B26000CAAB97587F8733D6F167AEF78E2E4EB3B1
+:10B270001DB9AF251DA2BAA13FE836285439D01C0C
+:10B28000E1FCF6E84A07FBADF3E0AE147A39FF3C87
+:10B29000CEE3EF09FDA888FC85BF4191C8EE7CC9CB
+:10B2A0003AC70653C8931616FE9BD613030D0F5FBD
+:10B2B000FE869CD2711F69D9EFE34E1C4F6E136F4F
+:10B2C0008B8B54912753CD9B07C8AEFDB8520629EE
+:10B2D0004C82F70983F36D1121DFF6BBEC8A1E3532
+:10B2E00027BE2F81AC3EBF53C9ED83DC77DEF76606
+:10B2F0007B7E7DF7EB27B2E0B56EC9ADB35D68FD2F
+:10B3000007FDBB5F3F817C32669C5FAE6CFA24FB1D
+:10B31000C342FF59FC65F31B8580F428F85CEB1FE2
+:10B320000C440BFA25FBB6083D79217DA4B9A23166
+:10B330005A7FF8A65C387759F2769705C7B558ABAF
+:10B34000E479D63BA7C31ED8FA74817B8D6C517902
+:10B35000FE1C3FDB7EC08B9796875BD123E2876024
+:10B360008D87EC30E2F345D21F7F0DAA7A367F0E2F
+:10B37000F972FD50DB0FF8E9162B0F575E21D1FA59
+:10B38000806EDBF1DC3C41BE1D2F72A6382F5DB410
+:10B3900054B5F50CEB830F7AEF79224EF2933EC849
+:10B3A000FE9E8AFC4BF5BC32328805E804A1DCBF66
+:10B3B00013D9B205183F65FAC4542BDEA32CA27032
+:10B3C0003D4449829126781B8BF8EF3FE877BA8994
+:10B3D000EC1C70509B6CFB24A471FE03B58AC1EF7A
+:10B3E00008C1D9FC2ED9DD2A3FD7516DB9B810BD9F
+:10B3F000ED73D17BB1DC77F017270F8F6DB1DE6570
+:10B400007BC023E461A36388F31D8E14BF85477955
+:10B41000579AAC9202D5FB4908703C48EF8224ABA6
+:10B420008E543B272770ABF56E73B7783FC37F5FB1
+:10B43000584B7F0F9AE1BF1BBC9A5EB7CA82AE24FD
+:10B4400027A7A0CA4175E2F871493AEB1F2DA2A7C0
+:10B450008E8683D62D8108B7F9E7BE0662FCBD1E35
+:10B4600092DC2E83096E1B608ADB4698E196D41528
+:10B470009DC73821EA1DABC090E9FB6A8870DB04E8
+:10B48000316EC390E4F6CB6D9FFCD64EA4C38FE61D
+:10B49000E145E0B5805CA711E8D9FBDB78FEC21678
+:10B4A0007D41723B14107993B6709AFD7AAF1EE11C
+:10B4B000B8CF19147C6DC3719E234FFCF7FA4FF976
+:10B4C0007F5FF2FF519E9355203F00000000000077
+:10B4D0000000000000000000000000180000000054
+:10B4E000000000000000004000000000000000001C
+:10B4F0000000002800000000000000000000001014
+:10B50000000000000000000000000020000000001B
+:10B51000000000000000001000000000000000001B
+:10B520000000000800000000000000000000000013
+:10B5300000000000000000000000003900000000D2
+:10B5400000000000000000380000000000000000C3
+:10B5500000000000000000000000000000000008E3
+:10B5600000000000000000000000000000000000DB
+:10B57000000000000000000C0000000000000000BF
+:10B580000000000E000000000000000000000004A9
+:10B590000000000000000000000000180000000093
+:10B5A000000000000000001C00000000000000007F
+:10B5B0000000001C0000000000000000000000135C
+:10B5C00000000000000000000000003A0000000041
+:10B5D000000000000000000100000000000000006A
+:10B5E0000000000200000000000000000000000158
+:10B5F000000000000000000000000010000000003B
+:10B6000000000000000000500000000000000000EA
+:10B610000000000000000000000000000000000327
+:10B620000000000000000000000000AB000000006F
+:10B630000000000000000008000000000000000002
+:10B640000000C00000100000000000080000C0085A
+:10B6500000100000000000020000C0000010000008
+:10B660000000001000009FB0000000000000000873
+:10B670000000C08000100000000000040000C0882E
+:10B6800000100000000000020000C0800010000058
+:10B6900000000010000091200000000000000008E1
+:10B6A00000009340000100040000000100009348E6
+:10B6B00000000000000000020000935000000000A5
+:10B6C0000000000800009354000000000000000289
+:10B6D00000009418000000000000000800009358CB
+:10B6E000000800000000000800009AB000400000C0
+:10B6F00000000040000093980008000000000008CF
+:10B70000000093D80008000000000008000094200A
+:10B7100000C8000000000098000095B000980000EC
+:10B7200000000028000095F00098000000000028AC
+:10B730000000C480054000300000054000009D204E
+:10B74000000800000000000100009D21000800002A
+:10B7500000000001000020080010000000000010A0
+:10B7600000002000000000000000000800009CD83D
+:10B77000000800000000000200009D18000000000A
+:10B7800000000001000000010000000000000000B7
+:10B79000000000090000000000000000000000029E
+:10B7A00000000000000000000000CF2000000000AA
+:10B7B000000000200000CF46000000000000000153
+:10B7C0000000600000200000000000200000730066
+:10B7D000000800000000000800009FA0000000001A
+:10B7E0000000000100009FA8000000000000000110
+:10B7F00000009F60000000000000001000009F6338
+:10B80000000000000000000100009F610000000037
+:10B810000000000100009F66000000000000000121
+:10B8200000009F67000000000000000000009F680B
+:10B83000000000000000000400009F6C00000000F9
+:10B8400000000004000000520000000000000000A2
+:10B8500000000003000000000000000000000003E2
+:10B8600000000000000000000000000500000000D3
+:10B8700000000000000000020000000000000000C6
+:10B8800000060000000000000000002000009F7083
+:10B89000000000000000000100009F900000000078
+:10B8A000000000080000005300000000000000003D
+:10B8B00000009F98000000000000000200009F9C14
+:10B8C000000000000000000100009F9D000000003B
+:10B8D000000000010000000900000000000000005E
+:10B8E0000000000100000000000000000000004413
+:10B8F0000000000000000000000000010000000047
+:10B9000000000000000000500000000000000000E7
+:10B91000000000890000000000000000000012C8C4
+:10B920000080000000000080000000010000000016
+:10B93000000000000000A000071000000000071039
+:10B9400000001AC800000000000000080000AEC09F
+:10B9500000080000000000080000AE4000080000E1
+:10B96000000000080000AE80000800000000000891
+:10B97000000020080010000000000010000020005F
+:10B9800000000000000000080000A01007100040A8
+:10B990000000004000001BF800080000000000014B
+:10B9A00000001BF9000800000000000100001AD090
+:10B9B000000000000000000100001AD80000000094
+:10B9C0000000000200001ADA00000000000000027F
+:10B9D0000000000000000000000000000000AF00B8
+:10B9E000000000000000002000001B78002800007C
+:10B9F000000000040000E000002000000000002023
+:10BA00000000F300000800000000000800001AF029
+:10BA1000000000000000010800001B3700000000CB
+:10BA20000000000100001B0F0000000000000001EA
+:10BA300000001B70000000000000000400001B74E8
+:10BA400000000000000000040000005000000000A2
+:10BA500000000000000000030000000000000000E3
+:10BA600000000005000000000000000000000006CB
+:10BA700000000000000000000000000700000000BF
+:10BA80000000000000001BC80000000000000001D2
+:10BA900000001BE80000000000000008000000514A
+:10BAA000000000000000000000001BD000000000AB
+:10BAB0000000000400001BD400000000000000048F
+:10BAC00000001BD8000000000000000400001BDC88
+:10BAD00000000000000000080000B0000018000096
+:10BAE000000000180000C0000040000000000040FE
+:10BAF0000000C00000400002000000010000C00182
+:10BB000000400002000000000000E20000200000F1
+:10BB1000000000200000E2040002000800200002F3
+:10BB20000000000000000000000000000000E20033
+:10BB300000080020000000040000F40000280000BD
+:10BB4000000000280000F540001000000000001078
+:10BB50000000F5C000200000000000200000F5C03B
+:10BB600000020020000000020000F300002000009E
+:10BB7000000000200000200800100000000000105D
+:10BB80000000200000000000000000080000110874
+:10BB90000008000000000008000011680008000014
+:10BBA00000000008000011A80008000000000008C4
+:10BBB00000001240000800000000000100001241D7
+:10BBC0000008000000000001000040000020000408
+:10BBD00000000010000059000030001800000010A4
+:10BBE0000000590800300018000000020000570053
+:10BBF00000080000000000010000570100080000DC
+:10BC000000000001000011E8000000000000000139
+:10BC1000000011F00000000000000001000011F819
+:10BC200000000000000000100000124400080000A6
+:10BC30000000000400004000002000000000002080
+:10BC40000000530000100000000000100000153834
+:10BC500000000000000000010000000300000000E0
+:10BC600000000000000000000000000000000000D4
+:10BC700000000001000000000000000000000004BF
+:10BC80000000000000000000000015080000000097
+:10BC9000000000010000152800000000000000085E
+:10BCA00000000050000000000000000000008308B9
+:10BCB0000080000000000080000000010000000083
+:10BCC000000000000000200800100000000000102C
+:10BCD00000002000000000000000000800008410A8
+:10BCE0000008000000000008000084700008000048
+:10BCF0000000000800060000046000280000046046
+:10BD000000008520000800000000000100008521DF
+:10BD1000000800000000000100000000000000001A
+:10BD20000000000000008408000000000000000186
+:10BD3000000084F40008000000000002000084F607
+:10BD40000008000000000002000085040010000050
+:10BD500000000004000087600000000000000020D8
+:10BD600000006000002000000000002000007300C0
+:10BD700000080000000000080000000300000000B0
+:10BD800000000000000000050000000000000000AE
+:10BD90000000000600000000000000000000000796
+:10BDA0000000000000000000000088080000000003
+:10BDB00000000001000088280000000000000008CA
+:10BDC000000000500000000000000000000088108B
+:10BDD00000000000000000040000881400000000C3
+:10BDE00000000004000088180000000000000004AB
+:10BDF0000000881C00000000000000080000300067
+:10BE00000040000000000008000030080040000072
+:10BE1000000000280000339001C00010000000085E
+:10BE20000000320000200000000000200000372049
+:10BE3000000000000000000800001020062000386C
+:10BE4000000000080000A00000000000000020002A
+:10BE500000003EA9000000000000000100003EC8F4
+:10BE600000000000000000020000000000000000D0
+:10BE7000000000000000600000200000000000083A
+:10BE80000000400000080000000000010000400128
+:10BE9000000800000000000100004040000800040D
+:10BEA00000000002000040600008000400000004E0
+:10BEB00000004000000800000000000400004004F2
+:10BEC00000080000000000040000404000000000E6
+:10BED00000000008000040480000000000000008CA
+:10BEE0000000800000000000000000100000504032
+:10BEF00000010004000000010000500000000000EC
+:10BF000000000020000050080010000000000004A5
+:10BF10000000500C0010000000000001000052C79B
+:10BF20000000000000000001000052C600000000F8
+:10BF30000000000100003000003000180000000484
+:10BF40000000300400300018000000040000300839
+:10BF500000300018000000020000300A0030001815
+:10BF6000000000020000300C00300018000000014A
+:10BF70000000300D00300018000000010000300EFD
+:10BF800000300018000000010000301000300018E0
+:10BF9000000000040000301400300018000000040D
+:10BFA0000000500001000080000800040000500460
+:10BFB00001000080000800040000000A00000000EA
+:10BFC0000000000000005068010000800000000137
+:10BFD0000000506901000080000000010000506C6A
+:10BFE00001000080000000020000506E010000808F
+:10BFF00000000002000050700100008000000004FA
+:10C000000000507401000080000000040000506631
+:10C010000100008000000002000050640100008068
+:10C0200000000001000050600100008000000002DC
+:10C03000000050620100008000000002000050502B
+:10C040000100008000000004000050540100008046
+:10C0500000000004000050580100008000000004AF
+:10C060000000505C01000080000000040000507CD3
+:10C0700001000080000000010000507D01000080F0
+:10C080000000000100004018001000000000000443
+:10C0900000004090001000000000000400004098E4
+:10C0A000001000000000000400004110000000002B
+:10C0B0000000000200004112000000000000000229
+:10C0C00000004114000000000000000200004116C2
+:10C0D00000000000000000020000604000080000B6
+:10C0E00000000002000060420008000000000002A2
+:10C0F00000006044000800000000000400006080B0
+:10C100000008000000000008000060C000400008B7
+:10C1100000000008000060000008000000000002AD
+:10C120000000600200080000000000010000600440
+:10C13000000800000000000200006340000800004A
+:10C1400000000008000063800008000000000004F8
+:10C15000000063840008000000000001000063C0CC
+:10C160000008000000000002000063C40008000096
+:10C17000000000020000640000080000000000044D
+:10C1800000007000001000000000000400007004B7
+:10C190000010000000000004000070080010000003
+:10C1A00000000004000090000008000000000002F1
+:10C1B0000000900200080000000000010000900450
+:10C1C000000800000000000200009040000800008D
+:10C1D000000000020000904400080000000000027F
+:10C1E0000000904600080000000000020000964891
+:10C1F0000008000000000008000090800008000017
+:10C20000000000020000908400080000000000020E
+:10C210000000968800080000000000080000804030
+:10C22000000800000000000100008041000800003C
+:10C230000000000100008042000800000000000132
+:10C2400000008043000800000000000100008000A2
+:10C25000000800000000000200008002000800004A
+:10C26000000000010000800400080000000000023F
+:10C27000000080C00008000000000002000080C232
+:10C280000008000000000002000080C40008000058
+:10C290000000000200008080000800000000000193
+:10C2A0000000808100080000000000010000808282
+:10C2B000000800000000000100008083000800006A
+:10C2C0000000000100008084000800000000000160
+:10C2D000000080850008000000000001000080864A
+:10C2E00000080000000000010000600000080000DD
+:10C2F00000000002000060020008000000000001D1
+:10C30000000060040008000000000002000060421D
+:10C3100000C00018000000020000604000C00018CB
+:10C32000000000020000604C00C00018000000087F
+:10C330000000604400C000180000000800006057C2
+:10C3400000C00018000000010000605400C0001888
+:10C35000000000020000605600C00018000000014C
+:10C360000000664000080000000000080000668031
+:10C370000008000000000008000066C0000800007F
+:10C38000000000080000DA4200180000000000026F
+:10C390000000DE4000000000000000000000E0009F
+:10C3A00000000000000000040000D0C000000000F9
+:10C3B000000000040000D0C40000000000000004E1
+:10C3C0000000D0C800000000000000040000D0CC35
+:10C3D00000000000000000040000D0D000000000B9
+:10C3E000000000040000D0D40000000000000004A1
+:10C3F0000000D0D800000000000000040000D0C001
+:10C4000000000000000000200000DB000000000031
+:10C41000000000040000DB000000000000000068D5
+:10C420000000B94800000000000000000000D0003B
+:10C4300000000000000000040000B0C00000000088
+:10C44000000000040000B0C4000000000000000470
+:10C450000000B0C800000000000000040000B0C0F0
+:10C4600000000000000000100000D6B00000000036
+:10C47000000000040000D6B400000000000000042A
+:10C480000000D6B800000000000000040000D6BC88
+:10C4900000000000000000040000D6B00000000012
+:10C4A000000000100000D348000000000000000859
+:10C4B0000000D358000000000000008000000010C1
+:10C4C00000000000000000000000D3580000000041
+:10C4D000000000080000000006002200000000002C
+:00000001FF
diff --git a/fs/Kconfig b/fs/Kconfig
index 3d18530..65781de 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -50,6 +50,7 @@
 config FILE_LOCKING
 	bool "Enable POSIX file locking API" if EMBEDDED
 	default y
+	select BKL # while lockd still uses it.
 	help
 	  This option enables standard file locking support, required
           for filesystems like NFS and for the flock() system
diff --git a/fs/adfs/Kconfig b/fs/adfs/Kconfig
index e55182a..1dd5f34 100644
--- a/fs/adfs/Kconfig
+++ b/fs/adfs/Kconfig
@@ -1,6 +1,7 @@
 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/super.c b/fs/adfs/super.c
index 4a3af70..d9803f7 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -352,11 +352,15 @@
 	struct adfs_sb_info *asb;
 	struct inode *root;
 
+	lock_kernel();
+
 	sb->s_flags |= MS_NODIRATIME;
 
 	asb = kzalloc(sizeof(*asb), GFP_KERNEL);
-	if (!asb)
+	if (!asb) {
+		unlock_kernel();
 		return -ENOMEM;
+	}
 	sb->s_fs_info = asb;
 
 	/* set default options */
@@ -474,6 +478,7 @@
 		goto error;
 	} else
 		sb->s_root->d_op = &adfs_dentry_operations;
+	unlock_kernel();
 	return 0;
 
 error_free_bh:
@@ -481,6 +486,7 @@
 error:
 	sb->s_fs_info = NULL;
 	kfree(asb);
+	unlock_kernel();
 	return -EINVAL;
 }
 
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 33c4e7e..fa4fbe1 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -16,7 +16,6 @@
 #include <linux/parser.h>
 #include <linux/magic.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include "affs.h"
 
@@ -46,8 +45,6 @@
 	struct affs_sb_info *sbi = AFFS_SB(sb);
 	pr_debug("AFFS: put_super()\n");
 
-	lock_kernel();
-
 	if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt)
 		affs_commit_super(sb, 1, 1);
 
@@ -56,8 +53,6 @@
 	affs_brelse(sbi->s_root_bh);
 	kfree(sbi);
 	sb->s_fs_info = NULL;
-
-	unlock_kernel();
 }
 
 static void
@@ -109,8 +104,8 @@
 {
 	struct affs_inode_info *ei = (struct affs_inode_info *) foo;
 
-	init_MUTEX(&ei->i_link_lock);
-	init_MUTEX(&ei->i_ext_lock);
+	sema_init(&ei->i_link_lock, 1);
+	sema_init(&ei->i_ext_lock, 1);
 	inode_init_once(&ei->vfs_inode);
 }
 
@@ -302,6 +297,7 @@
 	sbi = kzalloc(sizeof(struct affs_sb_info), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
+
 	sb->s_fs_info = sbi;
 	mutex_init(&sbi->s_bmlock);
 	spin_lock_init(&sbi->symlink_lock);
@@ -527,7 +523,7 @@
 		kfree(new_opts);
 		return -EINVAL;
 	}
-	lock_kernel();
+
 	replace_mount_options(sb, new_opts);
 
 	sbi->s_flags = mount_flags;
@@ -543,17 +539,15 @@
 	memcpy(sbi->s_volume, volume, 32);
 	spin_unlock(&sbi->symlink_lock);
 
-	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
-		unlock_kernel();
+	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
 		return 0;
-	}
+
 	if (*flags & MS_RDONLY) {
 		affs_write_super(sb);
 		affs_free_bitmap(sb);
 	} else
 		res = affs_init_bitmap(sb, flags);
 
-	unlock_kernel();
 	return res;
 }
 
diff --git a/fs/afs/flock.c b/fs/afs/flock.c
index 0931bc1..757d6645 100644
--- a/fs/afs/flock.c
+++ b/fs/afs/flock.c
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/smp_lock.h>
 #include "internal.h"
 
 #define AFS_LOCK_GRANTED	0
@@ -274,7 +273,7 @@
 
 	type = (fl->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
 
-	lock_kernel();
+	lock_flocks();
 
 	/* make sure we've got a callback on this file and that our view of the
 	 * data version is up to date */
@@ -421,7 +420,7 @@
 	afs_vnode_fetch_status(vnode, NULL, key);
 
 error:
-	unlock_kernel();
+	unlock_flocks();
 	_leave(" = %d", ret);
 	return ret;
 
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 6d55268..6153417 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -29,6 +29,7 @@
 
 const struct file_operations afs_mntpt_file_operations = {
 	.open		= afs_mntpt_open,
+	.llseek		= noop_llseek,
 };
 
 const struct inode_operations afs_mntpt_inode_operations = {
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 77e1e5a..eacf76d 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -19,7 +19,6 @@
 #include <linux/mount.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/parser.h>
@@ -453,12 +452,8 @@
 
 	_enter("");
 
-	lock_kernel();
-
 	afs_put_volume(as->volume);
 
-	unlock_kernel();
-
 	_leave("");
 }
 
diff --git a/fs/autofs/Kconfig b/fs/autofs/Kconfig
index 5f3bea9..480e210 100644
--- a/fs/autofs/Kconfig
+++ b/fs/autofs/Kconfig
@@ -1,5 +1,6 @@
 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
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index 11b1ea7..0c4ca81 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -27,7 +27,9 @@
 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,
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index ba4a38b..eff9a41 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -724,6 +724,7 @@
 	.unlocked_ioctl	 = autofs_dev_ioctl,
 	.compat_ioctl = autofs_dev_ioctl_compat,
 	.owner	 = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice _autofs_dev_ioctl_misc = {
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index cb1bd38..d5c1401 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -19,7 +19,7 @@
 #include <linux/param.h>
 #include <linux/time.h>
 #include <linux/compat.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include "autofs_i.h"
 
@@ -28,7 +28,9 @@
 static int autofs4_dir_rmdir(struct inode *,struct dentry *);
 static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
 static long autofs4_root_ioctl(struct file *,unsigned int,unsigned long);
+#ifdef CONFIG_COMPAT
 static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long);
+#endif
 static int autofs4_dir_open(struct inode *inode, struct file *file);
 static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
 static void *autofs4_follow_link(struct dentry *, struct nameidata *);
@@ -978,15 +980,17 @@
 	}
 }
 
+static DEFINE_MUTEX(autofs4_ioctl_mutex);
+
 static long autofs4_root_ioctl(struct file *filp,
 			       unsigned int cmd, unsigned long arg)
 {
 	long ret;
 	struct inode *inode = filp->f_dentry->d_inode;
 
-	lock_kernel();
+	mutex_lock(&autofs4_ioctl_mutex);
 	ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&autofs4_ioctl_mutex);
 
 	return ret;
 }
@@ -998,13 +1002,13 @@
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&autofs4_ioctl_mutex);
 	if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL)
 		ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
 	else
 		ret = autofs4_root_ioctl_unlocked(inode, filp, cmd,
 			(unsigned long)compat_ptr(arg));
-	unlock_kernel();
+	mutex_unlock(&autofs4_ioctl_mutex);
 
 	return ret;
 }
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index c4daf0f..883e77a 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -12,7 +12,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/writeback.h>
@@ -215,14 +214,10 @@
 	if (!info)
 		return;
 
-	lock_kernel();
-
 	mutex_destroy(&info->bfs_lock);
 	kfree(info->si_imap);
 	kfree(info);
 	s->s_fs_info = NULL;
-
-	unlock_kernel();
 }
 
 static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf)
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index f96eff0..a6395bd 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -134,10 +134,6 @@
 		if (!dump_write(file, dump_start, dump_size))
 			goto end_coredump;
 	}
-/* Finally dump the task struct.  Not be used by gdb, but could be useful */
-	set_fs(KERNEL_DS);
-	if (!dump_write(file, current, sizeof(*current)))
-		goto end_coredump;
 end_coredump:
 	set_fs(fs);
 	return has_dumped;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 535e763..6884e19 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -800,7 +800,7 @@
 			 * default mmap base, as well as whatever program they
 			 * might try to exec.  This is because the brk will
 			 * follow the loader, and is not movable.  */
-#ifdef CONFIG_X86
+#if defined(CONFIG_X86) || defined(CONFIG_ARM)
 			load_bias = 0;
 #else
 			load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index fd0cc0b..139fc80 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -576,6 +576,7 @@
 static const struct file_operations bm_entry_operations = {
 	.read		= bm_entry_read,
 	.write		= bm_entry_write,
+	.llseek		= default_llseek,
 };
 
 /* /register */
@@ -643,6 +644,7 @@
 
 static const struct file_operations bm_register_operations = {
 	.write		= bm_register_write,
+	.llseek		= noop_llseek,
 };
 
 /* /status */
@@ -680,6 +682,7 @@
 static const struct file_operations bm_status_operations = {
 	.read		= bm_status_read,
 	.write		= bm_status_write,
+	.llseek		= default_llseek,
 };
 
 /* Superblock handling */
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 50e8c85..b737451 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -370,7 +370,7 @@
 	 */
 	mutex_unlock(&bd_inode->i_mutex);
 
-	error = blkdev_issue_flush(bdev, GFP_KERNEL, NULL, BLKDEV_IFL_WAIT);
+	error = blkdev_issue_flush(bdev, GFP_KERNEL, NULL);
 	if (error == -EOPNOTSUPP)
 		error = 0;
 
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 64f1008..5e789f4 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2063,7 +2063,7 @@
 	if (uptodate) {
 		set_buffer_uptodate(bh);
 	} else {
-		if (!buffer_eopnotsupp(bh) && printk_ratelimit()) {
+		if (printk_ratelimit()) {
 			printk(KERN_WARNING "lost page write due to "
 					"I/O error on %s\n",
 				       bdevname(bh->b_bdev, b));
@@ -2200,21 +2200,10 @@
 			bh->b_end_io = btrfs_end_buffer_write_sync;
 		}
 
-		if (i == last_barrier && do_barriers && device->barriers) {
-			ret = submit_bh(WRITE_BARRIER, bh);
-			if (ret == -EOPNOTSUPP) {
-				printk("btrfs: disabling barriers on dev %s\n",
-				       device->name);
-				set_buffer_uptodate(bh);
-				device->barriers = 0;
-				/* one reference for submit_bh */
-				get_bh(bh);
-				lock_buffer(bh);
-				ret = submit_bh(WRITE_SYNC, bh);
-			}
-		} else {
+		if (i == last_barrier && do_barriers)
+			ret = submit_bh(WRITE_FLUSH_FUA, bh);
+		else
 			ret = submit_bh(WRITE_SYNC, bh);
-		}
 
 		if (ret)
 			errors++;
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 32d0940..0b81ecd 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1695,8 +1695,7 @@
 static void btrfs_issue_discard(struct block_device *bdev,
 				u64 start, u64 len)
 {
-	blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL,
-			BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+	blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL, 0);
 }
 
 static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 1776dbd..144f8a5 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -815,6 +815,7 @@
 	.unlocked_ioctl	 = btrfs_control_ioctl,
 	.compat_ioctl = btrfs_control_ioctl,
 	.owner	 = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice btrfs_misc = {
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index dd318ff..e25e46a 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -398,7 +398,6 @@
 		device->work.func = pending_bios_fn;
 		memcpy(device->uuid, disk_super->dev_item.uuid,
 		       BTRFS_UUID_SIZE);
-		device->barriers = 1;
 		spin_lock_init(&device->io_lock);
 		device->name = kstrdup(path, GFP_NOFS);
 		if (!device->name) {
@@ -462,7 +461,6 @@
 		device->devid = orig_dev->devid;
 		device->work.func = pending_bios_fn;
 		memcpy(device->uuid, orig_dev->uuid, sizeof(device->uuid));
-		device->barriers = 1;
 		spin_lock_init(&device->io_lock);
 		INIT_LIST_HEAD(&device->dev_list);
 		INIT_LIST_HEAD(&device->dev_alloc_list);
@@ -1489,7 +1487,6 @@
 	trans = btrfs_start_transaction(root, 0);
 	lock_chunks(root);
 
-	device->barriers = 1;
 	device->writeable = 1;
 	device->work.func = pending_bios_fn;
 	generate_random_uuid(device->uuid);
@@ -3084,7 +3081,6 @@
 		return NULL;
 	list_add(&device->dev_list,
 		 &fs_devices->devices);
-	device->barriers = 1;
 	device->dev_root = root->fs_info->dev_root;
 	device->devid = devid;
 	device->work.func = pending_bios_fn;
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 31b0fab..2b638b6 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -42,7 +42,6 @@
 	int running_pending;
 	u64 generation;
 
-	int barriers;
 	int writeable;
 	int in_fs_metadata;
 
diff --git a/fs/buffer.c b/fs/buffer.c
index 3e7dca2..7f0b9b0 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -156,7 +156,7 @@
 	if (uptodate) {
 		set_buffer_uptodate(bh);
 	} else {
-		if (!buffer_eopnotsupp(bh) && !quiet_error(bh)) {
+		if (!quiet_error(bh)) {
 			buffer_io_error(bh);
 			printk(KERN_WARNING "lost page write due to "
 					"I/O error on %s\n",
@@ -2891,7 +2891,6 @@
 
 	if (err == -EOPNOTSUPP) {
 		set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
-		set_bit(BH_Eopnotsupp, &bh->b_state);
 	}
 
 	if (unlikely (test_bit(BIO_QUIET,&bio->bi_flags)))
@@ -3031,10 +3030,6 @@
 		bh->b_end_io = end_buffer_write_sync;
 		ret = submit_bh(rw, bh);
 		wait_on_buffer(bh);
-		if (buffer_eopnotsupp(bh)) {
-			clear_buffer_eopnotsupp(bh);
-			ret = -EOPNOTSUPP;
-		}
 		if (!ret && !buffer_uptodate(bh))
 			ret = -EIO;
 	} else {
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c
index 727caed..0a1467b 100644
--- a/fs/cachefiles/daemon.c
+++ b/fs/cachefiles/daemon.c
@@ -55,6 +55,7 @@
 	.read		= cachefiles_daemon_read,
 	.write		= cachefiles_daemon_write,
 	.poll		= cachefiles_daemon_poll,
+	.llseek		= noop_llseek,
 };
 
 struct cachefiles_daemon_cmd {
diff --git a/fs/ceph/Kconfig b/fs/ceph/Kconfig
index 0fcd264..9eb134e 100644
--- a/fs/ceph/Kconfig
+++ b/fs/ceph/Kconfig
@@ -1,9 +1,11 @@
 config CEPH_FS
         tristate "Ceph distributed file system (EXPERIMENTAL)"
 	depends on INET && EXPERIMENTAL
+	select CEPH_LIB
 	select LIBCRC32C
 	select CRYPTO_AES
 	select CRYPTO
+	default n
 	help
 	  Choose Y or M here to include support for mounting the
 	  experimental Ceph distributed file system.  Ceph is an extremely
@@ -14,15 +16,3 @@
 
 	  If unsure, say N.
 
-config CEPH_FS_PRETTYDEBUG
-	bool "Include file:line in ceph debug output"
-	depends on CEPH_FS
-	default n
-	help
-	  If you say Y here, debug output will include a filename and
-	  line to aid debugging.  This icnreases kernel size and slows
-	  execution slightly when debug call sites are enabled (e.g.,
-	  via CONFIG_DYNAMIC_DEBUG).
-
-	  If unsure, say N.
-
diff --git a/fs/ceph/Makefile b/fs/ceph/Makefile
index 278e117..9e6c4f2 100644
--- a/fs/ceph/Makefile
+++ b/fs/ceph/Makefile
@@ -8,15 +8,8 @@
 
 ceph-objs := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \
 	export.o caps.o snap.o xattr.o \
-	messenger.o msgpool.o buffer.o pagelist.o \
-	mds_client.o mdsmap.o \
-	mon_client.o \
-	osd_client.o osdmap.o crush/crush.o crush/mapper.o crush/hash.o \
-	debugfs.o \
-	auth.o auth_none.o \
-	crypto.o armor.o \
-	auth_x.o \
-	ceph_fs.o ceph_strings.o ceph_hash.o ceph_frag.o
+	mds_client.o mdsmap.o strings.o ceph_frag.o \
+	debugfs.o
 
 else
 #Otherwise we were called directly from the command
diff --git a/fs/ceph/README b/fs/ceph/README
deleted file mode 100644
index 18352fa..0000000
--- a/fs/ceph/README
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# The following files are shared by (and manually synchronized
-# between) the Ceph userland and kernel client.
-#
-# userland                  kernel
-src/include/ceph_fs.h	    fs/ceph/ceph_fs.h
-src/include/ceph_fs.cc	    fs/ceph/ceph_fs.c
-src/include/msgr.h	    fs/ceph/msgr.h
-src/include/rados.h	    fs/ceph/rados.h
-src/include/ceph_strings.cc fs/ceph/ceph_strings.c
-src/include/ceph_frag.h	    fs/ceph/ceph_frag.h
-src/include/ceph_frag.cc    fs/ceph/ceph_frag.c
-src/include/ceph_hash.h	    fs/ceph/ceph_hash.h
-src/include/ceph_hash.cc    fs/ceph/ceph_hash.c
-src/crush/crush.c	    fs/ceph/crush/crush.c
-src/crush/crush.h	    fs/ceph/crush/crush.h
-src/crush/mapper.c	    fs/ceph/crush/mapper.c
-src/crush/mapper.h	    fs/ceph/crush/mapper.h
-src/crush/hash.h	    fs/ceph/crush/hash.h
-src/crush/hash.c	    fs/ceph/crush/hash.c
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index efbc604..51bcc5c 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/backing-dev.h>
 #include <linux/fs.h>
@@ -10,7 +10,8 @@
 #include <linux/task_io_accounting_ops.h>
 
 #include "super.h"
-#include "osd_client.h"
+#include "mds_client.h"
+#include <linux/ceph/osd_client.h>
 
 /*
  * Ceph address space ops.
@@ -193,7 +194,8 @@
 {
 	struct inode *inode = filp->f_dentry->d_inode;
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct ceph_osd_client *osdc = &ceph_inode_to_client(inode)->osdc;
+	struct ceph_osd_client *osdc = 
+		&ceph_inode_to_client(inode)->client->osdc;
 	int err = 0;
 	u64 len = PAGE_CACHE_SIZE;
 
@@ -265,7 +267,8 @@
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct ceph_osd_client *osdc = &ceph_inode_to_client(inode)->osdc;
+	struct ceph_osd_client *osdc =
+		&ceph_inode_to_client(inode)->client->osdc;
 	int rc = 0;
 	struct page **pages;
 	loff_t offset;
@@ -365,7 +368,7 @@
 {
 	struct inode *inode;
 	struct ceph_inode_info *ci;
-	struct ceph_client *client;
+	struct ceph_fs_client *fsc;
 	struct ceph_osd_client *osdc;
 	loff_t page_off = page->index << PAGE_CACHE_SHIFT;
 	int len = PAGE_CACHE_SIZE;
@@ -383,8 +386,8 @@
 	}
 	inode = page->mapping->host;
 	ci = ceph_inode(inode);
-	client = ceph_inode_to_client(inode);
-	osdc = &client->osdc;
+	fsc = ceph_inode_to_client(inode);
+	osdc = &fsc->client->osdc;
 
 	/* verify this is a writeable snap context */
 	snapc = (void *)page->private;
@@ -414,10 +417,10 @@
 	dout("writepage %p page %p index %lu on %llu~%u snapc %p\n",
 	     inode, page, page->index, page_off, len, snapc);
 
-	writeback_stat = atomic_long_inc_return(&client->writeback_count);
+	writeback_stat = atomic_long_inc_return(&fsc->writeback_count);
 	if (writeback_stat >
-	    CONGESTION_ON_THRESH(client->mount_args->congestion_kb))
-		set_bdi_congested(&client->backing_dev_info, BLK_RW_ASYNC);
+	    CONGESTION_ON_THRESH(fsc->mount_options->congestion_kb))
+		set_bdi_congested(&fsc->backing_dev_info, BLK_RW_ASYNC);
 
 	set_page_writeback(page);
 	err = ceph_osdc_writepages(osdc, ceph_vino(inode),
@@ -496,7 +499,7 @@
 	struct address_space *mapping = inode->i_mapping;
 	__s32 rc = -EIO;
 	u64 bytes = 0;
-	struct ceph_client *client = ceph_inode_to_client(inode);
+	struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
 	long writeback_stat;
 	unsigned issued = ceph_caps_issued(ci);
 
@@ -529,10 +532,10 @@
 		WARN_ON(!PageUptodate(page));
 
 		writeback_stat =
-			atomic_long_dec_return(&client->writeback_count);
+			atomic_long_dec_return(&fsc->writeback_count);
 		if (writeback_stat <
-		    CONGESTION_OFF_THRESH(client->mount_args->congestion_kb))
-			clear_bdi_congested(&client->backing_dev_info,
+		    CONGESTION_OFF_THRESH(fsc->mount_options->congestion_kb))
+			clear_bdi_congested(&fsc->backing_dev_info,
 					    BLK_RW_ASYNC);
 
 		ceph_put_snap_context((void *)page->private);
@@ -569,13 +572,13 @@
  * mempool.  we avoid the mempool if we can because req->r_num_pages
  * may be less than the maximum write size.
  */
-static void alloc_page_vec(struct ceph_client *client,
+static void alloc_page_vec(struct ceph_fs_client *fsc,
 			   struct ceph_osd_request *req)
 {
 	req->r_pages = kmalloc(sizeof(struct page *) * req->r_num_pages,
 			       GFP_NOFS);
 	if (!req->r_pages) {
-		req->r_pages = mempool_alloc(client->wb_pagevec_pool, GFP_NOFS);
+		req->r_pages = mempool_alloc(fsc->wb_pagevec_pool, GFP_NOFS);
 		req->r_pages_from_pool = 1;
 		WARN_ON(!req->r_pages);
 	}
@@ -590,7 +593,7 @@
 	struct inode *inode = mapping->host;
 	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct ceph_client *client;
+	struct ceph_fs_client *fsc;
 	pgoff_t index, start, end;
 	int range_whole = 0;
 	int should_loop = 1;
@@ -617,13 +620,13 @@
 	     wbc->sync_mode == WB_SYNC_NONE ? "NONE" :
 	     (wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD"));
 
-	client = ceph_inode_to_client(inode);
-	if (client->mount_state == CEPH_MOUNT_SHUTDOWN) {
+	fsc = ceph_inode_to_client(inode);
+	if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) {
 		pr_warning("writepage_start %p on forced umount\n", inode);
 		return -EIO; /* we're in a forced umount, don't write! */
 	}
-	if (client->mount_args->wsize && client->mount_args->wsize < wsize)
-		wsize = client->mount_args->wsize;
+	if (fsc->mount_options->wsize && fsc->mount_options->wsize < wsize)
+		wsize = fsc->mount_options->wsize;
 	if (wsize < PAGE_CACHE_SIZE)
 		wsize = PAGE_CACHE_SIZE;
 	max_pages_ever = wsize >> PAGE_CACHE_SHIFT;
@@ -769,7 +772,7 @@
 				offset = (unsigned long long)page->index
 					<< PAGE_CACHE_SHIFT;
 				len = wsize;
-				req = ceph_osdc_new_request(&client->osdc,
+				req = ceph_osdc_new_request(&fsc->client->osdc,
 					    &ci->i_layout,
 					    ceph_vino(inode),
 					    offset, &len,
@@ -782,7 +785,7 @@
 					    &inode->i_mtime, true, 1);
 				max_pages = req->r_num_pages;
 
-				alloc_page_vec(client, req);
+				alloc_page_vec(fsc, req);
 				req->r_callback = writepages_finish;
 				req->r_inode = inode;
 			}
@@ -794,10 +797,10 @@
 			     inode, page, page->index);
 
 			writeback_stat =
-			       atomic_long_inc_return(&client->writeback_count);
+			       atomic_long_inc_return(&fsc->writeback_count);
 			if (writeback_stat > CONGESTION_ON_THRESH(
-				    client->mount_args->congestion_kb)) {
-				set_bdi_congested(&client->backing_dev_info,
+				    fsc->mount_options->congestion_kb)) {
+				set_bdi_congested(&fsc->backing_dev_info,
 						  BLK_RW_ASYNC);
 			}
 
@@ -846,7 +849,7 @@
 		op->payload_len = cpu_to_le32(len);
 		req->r_request->hdr.data_len = cpu_to_le32(len);
 
-		ceph_osdc_start_request(&client->osdc, req, true);
+		ceph_osdc_start_request(&fsc->client->osdc, req, true);
 		req = NULL;
 
 		/* continue? */
@@ -915,7 +918,7 @@
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc;
+	struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
 	loff_t page_off = pos & PAGE_CACHE_MASK;
 	int pos_in_page = pos & ~PAGE_CACHE_MASK;
 	int end_in_page = pos_in_page + len;
@@ -1053,8 +1056,8 @@
 			  struct page *page, void *fsdata)
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	struct ceph_client *client = ceph_inode_to_client(inode);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	unsigned from = pos & (PAGE_CACHE_SIZE - 1);
 	int check_cap = 0;
 
@@ -1123,7 +1126,7 @@
 {
 	struct inode *inode = vma->vm_file->f_dentry->d_inode;
 	struct page *page = vmf->page;
-	struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc;
+	struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
 	loff_t off = page->index << PAGE_CACHE_SHIFT;
 	loff_t size, len;
 	int ret;
diff --git a/fs/ceph/auth.c b/fs/ceph/auth.c
deleted file mode 100644
index 6d2e306..0000000
--- a/fs/ceph/auth.c
+++ /dev/null
@@ -1,259 +0,0 @@
-#include "ceph_debug.h"
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-#include "types.h"
-#include "auth_none.h"
-#include "auth_x.h"
-#include "decode.h"
-#include "super.h"
-
-#include "messenger.h"
-
-/*
- * get protocol handler
- */
-static u32 supported_protocols[] = {
-	CEPH_AUTH_NONE,
-	CEPH_AUTH_CEPHX
-};
-
-static int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol)
-{
-	switch (protocol) {
-	case CEPH_AUTH_NONE:
-		return ceph_auth_none_init(ac);
-	case CEPH_AUTH_CEPHX:
-		return ceph_x_init(ac);
-	default:
-		return -ENOENT;
-	}
-}
-
-/*
- * setup, teardown.
- */
-struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret)
-{
-	struct ceph_auth_client *ac;
-	int ret;
-
-	dout("auth_init name '%s' secret '%s'\n", name, secret);
-
-	ret = -ENOMEM;
-	ac = kzalloc(sizeof(*ac), GFP_NOFS);
-	if (!ac)
-		goto out;
-
-	ac->negotiating = true;
-	if (name)
-		ac->name = name;
-	else
-		ac->name = CEPH_AUTH_NAME_DEFAULT;
-	dout("auth_init name %s secret %s\n", ac->name, secret);
-	ac->secret = secret;
-	return ac;
-
-out:
-	return ERR_PTR(ret);
-}
-
-void ceph_auth_destroy(struct ceph_auth_client *ac)
-{
-	dout("auth_destroy %p\n", ac);
-	if (ac->ops)
-		ac->ops->destroy(ac);
-	kfree(ac);
-}
-
-/*
- * Reset occurs when reconnecting to the monitor.
- */
-void ceph_auth_reset(struct ceph_auth_client *ac)
-{
-	dout("auth_reset %p\n", ac);
-	if (ac->ops && !ac->negotiating)
-		ac->ops->reset(ac);
-	ac->negotiating = true;
-}
-
-int ceph_entity_name_encode(const char *name, void **p, void *end)
-{
-	int len = strlen(name);
-
-	if (*p + 2*sizeof(u32) + len > end)
-		return -ERANGE;
-	ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT);
-	ceph_encode_32(p, len);
-	ceph_encode_copy(p, name, len);
-	return 0;
-}
-
-/*
- * Initiate protocol negotiation with monitor.  Include entity name
- * and list supported protocols.
- */
-int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len)
-{
-	struct ceph_mon_request_header *monhdr = buf;
-	void *p = monhdr + 1, *end = buf + len, *lenp;
-	int i, num;
-	int ret;
-
-	dout("auth_build_hello\n");
-	monhdr->have_version = 0;
-	monhdr->session_mon = cpu_to_le16(-1);
-	monhdr->session_mon_tid = 0;
-
-	ceph_encode_32(&p, 0);  /* no protocol, yet */
-
-	lenp = p;
-	p += sizeof(u32);
-
-	ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
-	ceph_encode_8(&p, 1);
-	num = ARRAY_SIZE(supported_protocols);
-	ceph_encode_32(&p, num);
-	ceph_decode_need(&p, end, num * sizeof(u32), bad);
-	for (i = 0; i < num; i++)
-		ceph_encode_32(&p, supported_protocols[i]);
-
-	ret = ceph_entity_name_encode(ac->name, &p, end);
-	if (ret < 0)
-		return ret;
-	ceph_decode_need(&p, end, sizeof(u64), bad);
-	ceph_encode_64(&p, ac->global_id);
-
-	ceph_encode_32(&lenp, p - lenp - sizeof(u32));
-	return p - buf;
-
-bad:
-	return -ERANGE;
-}
-
-static int ceph_build_auth_request(struct ceph_auth_client *ac,
-				   void *msg_buf, size_t msg_len)
-{
-	struct ceph_mon_request_header *monhdr = msg_buf;
-	void *p = monhdr + 1;
-	void *end = msg_buf + msg_len;
-	int ret;
-
-	monhdr->have_version = 0;
-	monhdr->session_mon = cpu_to_le16(-1);
-	monhdr->session_mon_tid = 0;
-
-	ceph_encode_32(&p, ac->protocol);
-
-	ret = ac->ops->build_request(ac, p + sizeof(u32), end);
-	if (ret < 0) {
-		pr_err("error %d building auth method %s request\n", ret,
-		       ac->ops->name);
-		return ret;
-	}
-	dout(" built request %d bytes\n", ret);
-	ceph_encode_32(&p, ret);
-	return p + ret - msg_buf;
-}
-
-/*
- * Handle auth message from monitor.
- */
-int ceph_handle_auth_reply(struct ceph_auth_client *ac,
-			   void *buf, size_t len,
-			   void *reply_buf, size_t reply_len)
-{
-	void *p = buf;
-	void *end = buf + len;
-	int protocol;
-	s32 result;
-	u64 global_id;
-	void *payload, *payload_end;
-	int payload_len;
-	char *result_msg;
-	int result_msg_len;
-	int ret = -EINVAL;
-
-	dout("handle_auth_reply %p %p\n", p, end);
-	ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
-	protocol = ceph_decode_32(&p);
-	result = ceph_decode_32(&p);
-	global_id = ceph_decode_64(&p);
-	payload_len = ceph_decode_32(&p);
-	payload = p;
-	p += payload_len;
-	ceph_decode_need(&p, end, sizeof(u32), bad);
-	result_msg_len = ceph_decode_32(&p);
-	result_msg = p;
-	p += result_msg_len;
-	if (p != end)
-		goto bad;
-
-	dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len,
-	     result_msg, global_id, payload_len);
-
-	payload_end = payload + payload_len;
-
-	if (global_id && ac->global_id != global_id) {
-		dout(" set global_id %lld -> %lld\n", ac->global_id, global_id);
-		ac->global_id = global_id;
-	}
-
-	if (ac->negotiating) {
-		/* server does not support our protocols? */
-		if (!protocol && result < 0) {
-			ret = result;
-			goto out;
-		}
-		/* set up (new) protocol handler? */
-		if (ac->protocol && ac->protocol != protocol) {
-			ac->ops->destroy(ac);
-			ac->protocol = 0;
-			ac->ops = NULL;
-		}
-		if (ac->protocol != protocol) {
-			ret = ceph_auth_init_protocol(ac, protocol);
-			if (ret) {
-				pr_err("error %d on auth protocol %d init\n",
-				       ret, protocol);
-				goto out;
-			}
-		}
-
-		ac->negotiating = false;
-	}
-
-	ret = ac->ops->handle_reply(ac, result, payload, payload_end);
-	if (ret == -EAGAIN) {
-		return ceph_build_auth_request(ac, reply_buf, reply_len);
-	} else if (ret) {
-		pr_err("auth method '%s' error %d\n", ac->ops->name, ret);
-		return ret;
-	}
-	return 0;
-
-bad:
-	pr_err("failed to decode auth msg\n");
-out:
-	return ret;
-}
-
-int ceph_build_auth(struct ceph_auth_client *ac,
-		    void *msg_buf, size_t msg_len)
-{
-	if (!ac->protocol)
-		return ceph_auth_build_hello(ac, msg_buf, msg_len);
-	BUG_ON(!ac->ops);
-	if (ac->ops->should_authenticate(ac))
-		return ceph_build_auth_request(ac, msg_buf, msg_len);
-	return 0;
-}
-
-int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
-{
-	if (!ac->ops)
-		return 0;
-	return ac->ops->is_authenticated(ac);
-}
diff --git a/fs/ceph/auth.h b/fs/ceph/auth.h
deleted file mode 100644
index d38a2fb..0000000
--- a/fs/ceph/auth.h
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef _FS_CEPH_AUTH_H
-#define _FS_CEPH_AUTH_H
-
-#include "types.h"
-#include "buffer.h"
-
-/*
- * Abstract interface for communicating with the authenticate module.
- * There is some handshake that takes place between us and the monitor
- * to acquire the necessary keys.  These are used to generate an
- * 'authorizer' that we use when connecting to a service (mds, osd).
- */
-
-struct ceph_auth_client;
-struct ceph_authorizer;
-
-struct ceph_auth_client_ops {
-	const char *name;
-
-	/*
-	 * true if we are authenticated and can connect to
-	 * services.
-	 */
-	int (*is_authenticated)(struct ceph_auth_client *ac);
-
-	/*
-	 * true if we should (re)authenticate, e.g., when our tickets
-	 * are getting old and crusty.
-	 */
-	int (*should_authenticate)(struct ceph_auth_client *ac);
-
-	/*
-	 * build requests and process replies during monitor
-	 * handshake.  if handle_reply returns -EAGAIN, we build
-	 * another request.
-	 */
-	int (*build_request)(struct ceph_auth_client *ac, void *buf, void *end);
-	int (*handle_reply)(struct ceph_auth_client *ac, int result,
-			    void *buf, void *end);
-
-	/*
-	 * Create authorizer for connecting to a service, and verify
-	 * the response to authenticate the service.
-	 */
-	int (*create_authorizer)(struct ceph_auth_client *ac, int peer_type,
-				 struct ceph_authorizer **a,
-				 void **buf, size_t *len,
-				 void **reply_buf, size_t *reply_len);
-	int (*verify_authorizer_reply)(struct ceph_auth_client *ac,
-				       struct ceph_authorizer *a, size_t len);
-	void (*destroy_authorizer)(struct ceph_auth_client *ac,
-				   struct ceph_authorizer *a);
-	void (*invalidate_authorizer)(struct ceph_auth_client *ac,
-				      int peer_type);
-
-	/* reset when we (re)connect to a monitor */
-	void (*reset)(struct ceph_auth_client *ac);
-
-	void (*destroy)(struct ceph_auth_client *ac);
-};
-
-struct ceph_auth_client {
-	u32 protocol;           /* CEPH_AUTH_* */
-	void *private;          /* for use by protocol implementation */
-	const struct ceph_auth_client_ops *ops;  /* null iff protocol==0 */
-
-	bool negotiating;       /* true if negotiating protocol */
-	const char *name;       /* entity name */
-	u64 global_id;          /* our unique id in system */
-	const char *secret;     /* our secret key */
-	unsigned want_keys;     /* which services we want */
-};
-
-extern struct ceph_auth_client *ceph_auth_init(const char *name,
-					       const char *secret);
-extern void ceph_auth_destroy(struct ceph_auth_client *ac);
-
-extern void ceph_auth_reset(struct ceph_auth_client *ac);
-
-extern int ceph_auth_build_hello(struct ceph_auth_client *ac,
-				 void *buf, size_t len);
-extern int ceph_handle_auth_reply(struct ceph_auth_client *ac,
-				  void *buf, size_t len,
-				  void *reply_buf, size_t reply_len);
-extern int ceph_entity_name_encode(const char *name, void **p, void *end);
-
-extern int ceph_build_auth(struct ceph_auth_client *ac,
-		    void *msg_buf, size_t msg_len);
-
-extern int ceph_auth_is_authenticated(struct ceph_auth_client *ac);
-
-#endif
diff --git a/fs/ceph/auth_none.c b/fs/ceph/auth_none.c
deleted file mode 100644
index ad1dc21..0000000
--- a/fs/ceph/auth_none.c
+++ /dev/null
@@ -1,131 +0,0 @@
-
-#include "ceph_debug.h"
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-
-#include "auth_none.h"
-#include "auth.h"
-#include "decode.h"
-
-static void reset(struct ceph_auth_client *ac)
-{
-	struct ceph_auth_none_info *xi = ac->private;
-
-	xi->starting = true;
-	xi->built_authorizer = false;
-}
-
-static void destroy(struct ceph_auth_client *ac)
-{
-	kfree(ac->private);
-	ac->private = NULL;
-}
-
-static int is_authenticated(struct ceph_auth_client *ac)
-{
-	struct ceph_auth_none_info *xi = ac->private;
-
-	return !xi->starting;
-}
-
-static int should_authenticate(struct ceph_auth_client *ac)
-{
-	struct ceph_auth_none_info *xi = ac->private;
-
-	return xi->starting;
-}
-
-/*
- * the generic auth code decode the global_id, and we carry no actual
- * authenticate state, so nothing happens here.
- */
-static int handle_reply(struct ceph_auth_client *ac, int result,
-			void *buf, void *end)
-{
-	struct ceph_auth_none_info *xi = ac->private;
-
-	xi->starting = false;
-	return result;
-}
-
-/*
- * build an 'authorizer' with our entity_name and global_id.  we can
- * reuse a single static copy since it is identical for all services
- * we connect to.
- */
-static int ceph_auth_none_create_authorizer(
-	struct ceph_auth_client *ac, int peer_type,
-	struct ceph_authorizer **a,
-	void **buf, size_t *len,
-	void **reply_buf, size_t *reply_len)
-{
-	struct ceph_auth_none_info *ai = ac->private;
-	struct ceph_none_authorizer *au = &ai->au;
-	void *p, *end;
-	int ret;
-
-	if (!ai->built_authorizer) {
-		p = au->buf;
-		end = p + sizeof(au->buf);
-		ceph_encode_8(&p, 1);
-		ret = ceph_entity_name_encode(ac->name, &p, end - 8);
-		if (ret < 0)
-			goto bad;
-		ceph_decode_need(&p, end, sizeof(u64), bad2);
-		ceph_encode_64(&p, ac->global_id);
-		au->buf_len = p - (void *)au->buf;
-		ai->built_authorizer = true;
-		dout("built authorizer len %d\n", au->buf_len);
-	}
-
-	*a = (struct ceph_authorizer *)au;
-	*buf = au->buf;
-	*len = au->buf_len;
-	*reply_buf = au->reply_buf;
-	*reply_len = sizeof(au->reply_buf);
-	return 0;
-
-bad2:
-	ret = -ERANGE;
-bad:
-	return ret;
-}
-
-static void ceph_auth_none_destroy_authorizer(struct ceph_auth_client *ac,
-				      struct ceph_authorizer *a)
-{
-	/* nothing to do */
-}
-
-static const struct ceph_auth_client_ops ceph_auth_none_ops = {
-	.name = "none",
-	.reset = reset,
-	.destroy = destroy,
-	.is_authenticated = is_authenticated,
-	.should_authenticate = should_authenticate,
-	.handle_reply = handle_reply,
-	.create_authorizer = ceph_auth_none_create_authorizer,
-	.destroy_authorizer = ceph_auth_none_destroy_authorizer,
-};
-
-int ceph_auth_none_init(struct ceph_auth_client *ac)
-{
-	struct ceph_auth_none_info *xi;
-
-	dout("ceph_auth_none_init %p\n", ac);
-	xi = kzalloc(sizeof(*xi), GFP_NOFS);
-	if (!xi)
-		return -ENOMEM;
-
-	xi->starting = true;
-	xi->built_authorizer = false;
-
-	ac->protocol = CEPH_AUTH_NONE;
-	ac->private = xi;
-	ac->ops = &ceph_auth_none_ops;
-	return 0;
-}
-
diff --git a/fs/ceph/auth_none.h b/fs/ceph/auth_none.h
deleted file mode 100644
index 8164df1..0000000
--- a/fs/ceph/auth_none.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef _FS_CEPH_AUTH_NONE_H
-#define _FS_CEPH_AUTH_NONE_H
-
-#include <linux/slab.h>
-
-#include "auth.h"
-
-/*
- * null security mode.
- *
- * we use a single static authorizer that simply encodes our entity name
- * and global id.
- */
-
-struct ceph_none_authorizer {
-	char buf[128];
-	int buf_len;
-	char reply_buf[0];
-};
-
-struct ceph_auth_none_info {
-	bool starting;
-	bool built_authorizer;
-	struct ceph_none_authorizer au;   /* we only need one; it's static */
-};
-
-extern int ceph_auth_none_init(struct ceph_auth_client *ac);
-
-#endif
-
diff --git a/fs/ceph/auth_x.c b/fs/ceph/auth_x.c
deleted file mode 100644
index a2d002c..0000000
--- a/fs/ceph/auth_x.c
+++ /dev/null
@@ -1,687 +0,0 @@
-
-#include "ceph_debug.h"
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-
-#include "auth_x.h"
-#include "auth_x_protocol.h"
-#include "crypto.h"
-#include "auth.h"
-#include "decode.h"
-
-#define TEMP_TICKET_BUF_LEN	256
-
-static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);
-
-static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
-{
-	struct ceph_x_info *xi = ac->private;
-	int need;
-
-	ceph_x_validate_tickets(ac, &need);
-	dout("ceph_x_is_authenticated want=%d need=%d have=%d\n",
-	     ac->want_keys, need, xi->have_keys);
-	return (ac->want_keys & xi->have_keys) == ac->want_keys;
-}
-
-static int ceph_x_should_authenticate(struct ceph_auth_client *ac)
-{
-	struct ceph_x_info *xi = ac->private;
-	int need;
-
-	ceph_x_validate_tickets(ac, &need);
-	dout("ceph_x_should_authenticate want=%d need=%d have=%d\n",
-	     ac->want_keys, need, xi->have_keys);
-	return need != 0;
-}
-
-static int ceph_x_encrypt_buflen(int ilen)
-{
-	return sizeof(struct ceph_x_encrypt_header) + ilen + 16 +
-		sizeof(u32);
-}
-
-static int ceph_x_encrypt(struct ceph_crypto_key *secret,
-			  void *ibuf, int ilen, void *obuf, size_t olen)
-{
-	struct ceph_x_encrypt_header head = {
-		.struct_v = 1,
-		.magic = cpu_to_le64(CEPHX_ENC_MAGIC)
-	};
-	size_t len = olen - sizeof(u32);
-	int ret;
-
-	ret = ceph_encrypt2(secret, obuf + sizeof(u32), &len,
-			    &head, sizeof(head), ibuf, ilen);
-	if (ret)
-		return ret;
-	ceph_encode_32(&obuf, len);
-	return len + sizeof(u32);
-}
-
-static int ceph_x_decrypt(struct ceph_crypto_key *secret,
-			  void **p, void *end, void *obuf, size_t olen)
-{
-	struct ceph_x_encrypt_header head;
-	size_t head_len = sizeof(head);
-	int len, ret;
-
-	len = ceph_decode_32(p);
-	if (*p + len > end)
-		return -EINVAL;
-
-	dout("ceph_x_decrypt len %d\n", len);
-	ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen,
-			    *p, len);
-	if (ret)
-		return ret;
-	if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
-		return -EPERM;
-	*p += len;
-	return olen;
-}
-
-/*
- * get existing (or insert new) ticket handler
- */
-static struct ceph_x_ticket_handler *
-get_ticket_handler(struct ceph_auth_client *ac, int service)
-{
-	struct ceph_x_ticket_handler *th;
-	struct ceph_x_info *xi = ac->private;
-	struct rb_node *parent = NULL, **p = &xi->ticket_handlers.rb_node;
-
-	while (*p) {
-		parent = *p;
-		th = rb_entry(parent, struct ceph_x_ticket_handler, node);
-		if (service < th->service)
-			p = &(*p)->rb_left;
-		else if (service > th->service)
-			p = &(*p)->rb_right;
-		else
-			return th;
-	}
-
-	/* add it */
-	th = kzalloc(sizeof(*th), GFP_NOFS);
-	if (!th)
-		return ERR_PTR(-ENOMEM);
-	th->service = service;
-	rb_link_node(&th->node, parent, p);
-	rb_insert_color(&th->node, &xi->ticket_handlers);
-	return th;
-}
-
-static void remove_ticket_handler(struct ceph_auth_client *ac,
-				  struct ceph_x_ticket_handler *th)
-{
-	struct ceph_x_info *xi = ac->private;
-
-	dout("remove_ticket_handler %p %d\n", th, th->service);
-	rb_erase(&th->node, &xi->ticket_handlers);
-	ceph_crypto_key_destroy(&th->session_key);
-	if (th->ticket_blob)
-		ceph_buffer_put(th->ticket_blob);
-	kfree(th);
-}
-
-static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
-				    struct ceph_crypto_key *secret,
-				    void *buf, void *end)
-{
-	struct ceph_x_info *xi = ac->private;
-	int num;
-	void *p = buf;
-	int ret;
-	char *dbuf;
-	char *ticket_buf;
-	u8 reply_struct_v;
-
-	dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
-	if (!dbuf)
-		return -ENOMEM;
-
-	ret = -ENOMEM;
-	ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
-	if (!ticket_buf)
-		goto out_dbuf;
-
-	ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
-	reply_struct_v = ceph_decode_8(&p);
-	if (reply_struct_v != 1)
-		goto bad;
-	num = ceph_decode_32(&p);
-	dout("%d tickets\n", num);
-	while (num--) {
-		int type;
-		u8 tkt_struct_v, blob_struct_v;
-		struct ceph_x_ticket_handler *th;
-		void *dp, *dend;
-		int dlen;
-		char is_enc;
-		struct timespec validity;
-		struct ceph_crypto_key old_key;
-		void *tp, *tpend;
-		struct ceph_timespec new_validity;
-		struct ceph_crypto_key new_session_key;
-		struct ceph_buffer *new_ticket_blob;
-		unsigned long new_expires, new_renew_after;
-		u64 new_secret_id;
-
-		ceph_decode_need(&p, end, sizeof(u32) + 1, bad);
-
-		type = ceph_decode_32(&p);
-		dout(" ticket type %d %s\n", type, ceph_entity_type_name(type));
-
-		tkt_struct_v = ceph_decode_8(&p);
-		if (tkt_struct_v != 1)
-			goto bad;
-
-		th = get_ticket_handler(ac, type);
-		if (IS_ERR(th)) {
-			ret = PTR_ERR(th);
-			goto out;
-		}
-
-		/* blob for me */
-		dlen = ceph_x_decrypt(secret, &p, end, dbuf,
-				      TEMP_TICKET_BUF_LEN);
-		if (dlen <= 0) {
-			ret = dlen;
-			goto out;
-		}
-		dout(" decrypted %d bytes\n", dlen);
-		dend = dbuf + dlen;
-		dp = dbuf;
-
-		tkt_struct_v = ceph_decode_8(&dp);
-		if (tkt_struct_v != 1)
-			goto bad;
-
-		memcpy(&old_key, &th->session_key, sizeof(old_key));
-		ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
-		if (ret)
-			goto out;
-
-		ceph_decode_copy(&dp, &new_validity, sizeof(new_validity));
-		ceph_decode_timespec(&validity, &new_validity);
-		new_expires = get_seconds() + validity.tv_sec;
-		new_renew_after = new_expires - (validity.tv_sec / 4);
-		dout(" expires=%lu renew_after=%lu\n", new_expires,
-		     new_renew_after);
-
-		/* ticket blob for service */
-		ceph_decode_8_safe(&p, end, is_enc, bad);
-		tp = ticket_buf;
-		if (is_enc) {
-			/* encrypted */
-			dout(" encrypted ticket\n");
-			dlen = ceph_x_decrypt(&old_key, &p, end, ticket_buf,
-					      TEMP_TICKET_BUF_LEN);
-			if (dlen < 0) {
-				ret = dlen;
-				goto out;
-			}
-			dlen = ceph_decode_32(&tp);
-		} else {
-			/* unencrypted */
-			ceph_decode_32_safe(&p, end, dlen, bad);
-			ceph_decode_need(&p, end, dlen, bad);
-			ceph_decode_copy(&p, ticket_buf, dlen);
-		}
-		tpend = tp + dlen;
-		dout(" ticket blob is %d bytes\n", dlen);
-		ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
-		blob_struct_v = ceph_decode_8(&tp);
-		new_secret_id = ceph_decode_64(&tp);
-		ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
-		if (ret)
-			goto out;
-
-		/* all is well, update our ticket */
-		ceph_crypto_key_destroy(&th->session_key);
-		if (th->ticket_blob)
-			ceph_buffer_put(th->ticket_blob);
-		th->session_key = new_session_key;
-		th->ticket_blob = new_ticket_blob;
-		th->validity = new_validity;
-		th->secret_id = new_secret_id;
-		th->expires = new_expires;
-		th->renew_after = new_renew_after;
-		dout(" got ticket service %d (%s) secret_id %lld len %d\n",
-		     type, ceph_entity_type_name(type), th->secret_id,
-		     (int)th->ticket_blob->vec.iov_len);
-		xi->have_keys |= th->service;
-	}
-
-	ret = 0;
-out:
-	kfree(ticket_buf);
-out_dbuf:
-	kfree(dbuf);
-	return ret;
-
-bad:
-	ret = -EINVAL;
-	goto out;
-}
-
-static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
-				   struct ceph_x_ticket_handler *th,
-				   struct ceph_x_authorizer *au)
-{
-	int maxlen;
-	struct ceph_x_authorize_a *msg_a;
-	struct ceph_x_authorize_b msg_b;
-	void *p, *end;
-	int ret;
-	int ticket_blob_len =
-		(th->ticket_blob ? th->ticket_blob->vec.iov_len : 0);
-
-	dout("build_authorizer for %s %p\n",
-	     ceph_entity_type_name(th->service), au);
-
-	maxlen = sizeof(*msg_a) + sizeof(msg_b) +
-		ceph_x_encrypt_buflen(ticket_blob_len);
-	dout("  need len %d\n", maxlen);
-	if (au->buf && au->buf->alloc_len < maxlen) {
-		ceph_buffer_put(au->buf);
-		au->buf = NULL;
-	}
-	if (!au->buf) {
-		au->buf = ceph_buffer_new(maxlen, GFP_NOFS);
-		if (!au->buf)
-			return -ENOMEM;
-	}
-	au->service = th->service;
-
-	msg_a = au->buf->vec.iov_base;
-	msg_a->struct_v = 1;
-	msg_a->global_id = cpu_to_le64(ac->global_id);
-	msg_a->service_id = cpu_to_le32(th->service);
-	msg_a->ticket_blob.struct_v = 1;
-	msg_a->ticket_blob.secret_id = cpu_to_le64(th->secret_id);
-	msg_a->ticket_blob.blob_len = cpu_to_le32(ticket_blob_len);
-	if (ticket_blob_len) {
-		memcpy(msg_a->ticket_blob.blob, th->ticket_blob->vec.iov_base,
-		       th->ticket_blob->vec.iov_len);
-	}
-	dout(" th %p secret_id %lld %lld\n", th, th->secret_id,
-	     le64_to_cpu(msg_a->ticket_blob.secret_id));
-
-	p = msg_a + 1;
-	p += ticket_blob_len;
-	end = au->buf->vec.iov_base + au->buf->vec.iov_len;
-
-	get_random_bytes(&au->nonce, sizeof(au->nonce));
-	msg_b.struct_v = 1;
-	msg_b.nonce = cpu_to_le64(au->nonce);
-	ret = ceph_x_encrypt(&th->session_key, &msg_b, sizeof(msg_b),
-			     p, end - p);
-	if (ret < 0)
-		goto out_buf;
-	p += ret;
-	au->buf->vec.iov_len = p - au->buf->vec.iov_base;
-	dout(" built authorizer nonce %llx len %d\n", au->nonce,
-	     (int)au->buf->vec.iov_len);
-	BUG_ON(au->buf->vec.iov_len > maxlen);
-	return 0;
-
-out_buf:
-	ceph_buffer_put(au->buf);
-	au->buf = NULL;
-	return ret;
-}
-
-static int ceph_x_encode_ticket(struct ceph_x_ticket_handler *th,
-				void **p, void *end)
-{
-	ceph_decode_need(p, end, 1 + sizeof(u64), bad);
-	ceph_encode_8(p, 1);
-	ceph_encode_64(p, th->secret_id);
-	if (th->ticket_blob) {
-		const char *buf = th->ticket_blob->vec.iov_base;
-		u32 len = th->ticket_blob->vec.iov_len;
-
-		ceph_encode_32_safe(p, end, len, bad);
-		ceph_encode_copy_safe(p, end, buf, len, bad);
-	} else {
-		ceph_encode_32_safe(p, end, 0, bad);
-	}
-
-	return 0;
-bad:
-	return -ERANGE;
-}
-
-static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed)
-{
-	int want = ac->want_keys;
-	struct ceph_x_info *xi = ac->private;
-	int service;
-
-	*pneed = ac->want_keys & ~(xi->have_keys);
-
-	for (service = 1; service <= want; service <<= 1) {
-		struct ceph_x_ticket_handler *th;
-
-		if (!(ac->want_keys & service))
-			continue;
-
-		if (*pneed & service)
-			continue;
-
-		th = get_ticket_handler(ac, service);
-
-		if (IS_ERR(th)) {
-			*pneed |= service;
-			continue;
-		}
-
-		if (get_seconds() >= th->renew_after)
-			*pneed |= service;
-		if (get_seconds() >= th->expires)
-			xi->have_keys &= ~service;
-	}
-}
-
-
-static int ceph_x_build_request(struct ceph_auth_client *ac,
-				void *buf, void *end)
-{
-	struct ceph_x_info *xi = ac->private;
-	int need;
-	struct ceph_x_request_header *head = buf;
-	int ret;
-	struct ceph_x_ticket_handler *th =
-		get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH);
-
-	if (IS_ERR(th))
-		return PTR_ERR(th);
-
-	ceph_x_validate_tickets(ac, &need);
-
-	dout("build_request want %x have %x need %x\n",
-	     ac->want_keys, xi->have_keys, need);
-
-	if (need & CEPH_ENTITY_TYPE_AUTH) {
-		struct ceph_x_authenticate *auth = (void *)(head + 1);
-		void *p = auth + 1;
-		struct ceph_x_challenge_blob tmp;
-		char tmp_enc[40];
-		u64 *u;
-
-		if (p > end)
-			return -ERANGE;
-
-		dout(" get_auth_session_key\n");
-		head->op = cpu_to_le16(CEPHX_GET_AUTH_SESSION_KEY);
-
-		/* encrypt and hash */
-		get_random_bytes(&auth->client_challenge, sizeof(u64));
-		tmp.client_challenge = auth->client_challenge;
-		tmp.server_challenge = cpu_to_le64(xi->server_challenge);
-		ret = ceph_x_encrypt(&xi->secret, &tmp, sizeof(tmp),
-				     tmp_enc, sizeof(tmp_enc));
-		if (ret < 0)
-			return ret;
-
-		auth->struct_v = 1;
-		auth->key = 0;
-		for (u = (u64 *)tmp_enc; u + 1 <= (u64 *)(tmp_enc + ret); u++)
-			auth->key ^= *(__le64 *)u;
-		dout(" server_challenge %llx client_challenge %llx key %llx\n",
-		     xi->server_challenge, le64_to_cpu(auth->client_challenge),
-		     le64_to_cpu(auth->key));
-
-		/* now encode the old ticket if exists */
-		ret = ceph_x_encode_ticket(th, &p, end);
-		if (ret < 0)
-			return ret;
-
-		return p - buf;
-	}
-
-	if (need) {
-		void *p = head + 1;
-		struct ceph_x_service_ticket_request *req;
-
-		if (p > end)
-			return -ERANGE;
-		head->op = cpu_to_le16(CEPHX_GET_PRINCIPAL_SESSION_KEY);
-
-		ret = ceph_x_build_authorizer(ac, th, &xi->auth_authorizer);
-		if (ret)
-			return ret;
-		ceph_encode_copy(&p, xi->auth_authorizer.buf->vec.iov_base,
-				 xi->auth_authorizer.buf->vec.iov_len);
-
-		req = p;
-		req->keys = cpu_to_le32(need);
-		p += sizeof(*req);
-		return p - buf;
-	}
-
-	return 0;
-}
-
-static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result,
-			       void *buf, void *end)
-{
-	struct ceph_x_info *xi = ac->private;
-	struct ceph_x_reply_header *head = buf;
-	struct ceph_x_ticket_handler *th;
-	int len = end - buf;
-	int op;
-	int ret;
-
-	if (result)
-		return result;  /* XXX hmm? */
-
-	if (xi->starting) {
-		/* it's a hello */
-		struct ceph_x_server_challenge *sc = buf;
-
-		if (len != sizeof(*sc))
-			return -EINVAL;
-		xi->server_challenge = le64_to_cpu(sc->server_challenge);
-		dout("handle_reply got server challenge %llx\n",
-		     xi->server_challenge);
-		xi->starting = false;
-		xi->have_keys &= ~CEPH_ENTITY_TYPE_AUTH;
-		return -EAGAIN;
-	}
-
-	op = le16_to_cpu(head->op);
-	result = le32_to_cpu(head->result);
-	dout("handle_reply op %d result %d\n", op, result);
-	switch (op) {
-	case CEPHX_GET_AUTH_SESSION_KEY:
-		/* verify auth key */
-		ret = ceph_x_proc_ticket_reply(ac, &xi->secret,
-					       buf + sizeof(*head), end);
-		break;
-
-	case CEPHX_GET_PRINCIPAL_SESSION_KEY:
-		th = get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH);
-		if (IS_ERR(th))
-			return PTR_ERR(th);
-		ret = ceph_x_proc_ticket_reply(ac, &th->session_key,
-					       buf + sizeof(*head), end);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	if (ret)
-		return ret;
-	if (ac->want_keys == xi->have_keys)
-		return 0;
-	return -EAGAIN;
-}
-
-static int ceph_x_create_authorizer(
-	struct ceph_auth_client *ac, int peer_type,
-	struct ceph_authorizer **a,
-	void **buf, size_t *len,
-	void **reply_buf, size_t *reply_len)
-{
-	struct ceph_x_authorizer *au;
-	struct ceph_x_ticket_handler *th;
-	int ret;
-
-	th = get_ticket_handler(ac, peer_type);
-	if (IS_ERR(th))
-		return PTR_ERR(th);
-
-	au = kzalloc(sizeof(*au), GFP_NOFS);
-	if (!au)
-		return -ENOMEM;
-
-	ret = ceph_x_build_authorizer(ac, th, au);
-	if (ret) {
-		kfree(au);
-		return ret;
-	}
-
-	*a = (struct ceph_authorizer *)au;
-	*buf = au->buf->vec.iov_base;
-	*len = au->buf->vec.iov_len;
-	*reply_buf = au->reply_buf;
-	*reply_len = sizeof(au->reply_buf);
-	return 0;
-}
-
-static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
-					  struct ceph_authorizer *a, size_t len)
-{
-	struct ceph_x_authorizer *au = (void *)a;
-	struct ceph_x_ticket_handler *th;
-	int ret = 0;
-	struct ceph_x_authorize_reply reply;
-	void *p = au->reply_buf;
-	void *end = p + sizeof(au->reply_buf);
-
-	th = get_ticket_handler(ac, au->service);
-	if (IS_ERR(th))
-		return PTR_ERR(th);
-	ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply));
-	if (ret < 0)
-		return ret;
-	if (ret != sizeof(reply))
-		return -EPERM;
-
-	if (au->nonce + 1 != le64_to_cpu(reply.nonce_plus_one))
-		ret = -EPERM;
-	else
-		ret = 0;
-	dout("verify_authorizer_reply nonce %llx got %llx ret %d\n",
-	     au->nonce, le64_to_cpu(reply.nonce_plus_one), ret);
-	return ret;
-}
-
-static void ceph_x_destroy_authorizer(struct ceph_auth_client *ac,
-				      struct ceph_authorizer *a)
-{
-	struct ceph_x_authorizer *au = (void *)a;
-
-	ceph_buffer_put(au->buf);
-	kfree(au);
-}
-
-
-static void ceph_x_reset(struct ceph_auth_client *ac)
-{
-	struct ceph_x_info *xi = ac->private;
-
-	dout("reset\n");
-	xi->starting = true;
-	xi->server_challenge = 0;
-}
-
-static void ceph_x_destroy(struct ceph_auth_client *ac)
-{
-	struct ceph_x_info *xi = ac->private;
-	struct rb_node *p;
-
-	dout("ceph_x_destroy %p\n", ac);
-	ceph_crypto_key_destroy(&xi->secret);
-
-	while ((p = rb_first(&xi->ticket_handlers)) != NULL) {
-		struct ceph_x_ticket_handler *th =
-			rb_entry(p, struct ceph_x_ticket_handler, node);
-		remove_ticket_handler(ac, th);
-	}
-
-	if (xi->auth_authorizer.buf)
-		ceph_buffer_put(xi->auth_authorizer.buf);
-
-	kfree(ac->private);
-	ac->private = NULL;
-}
-
-static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac,
-				   int peer_type)
-{
-	struct ceph_x_ticket_handler *th;
-
-	th = get_ticket_handler(ac, peer_type);
-	if (!IS_ERR(th))
-		remove_ticket_handler(ac, th);
-}
-
-
-static const struct ceph_auth_client_ops ceph_x_ops = {
-	.name = "x",
-	.is_authenticated = ceph_x_is_authenticated,
-	.should_authenticate = ceph_x_should_authenticate,
-	.build_request = ceph_x_build_request,
-	.handle_reply = ceph_x_handle_reply,
-	.create_authorizer = ceph_x_create_authorizer,
-	.verify_authorizer_reply = ceph_x_verify_authorizer_reply,
-	.destroy_authorizer = ceph_x_destroy_authorizer,
-	.invalidate_authorizer = ceph_x_invalidate_authorizer,
-	.reset =  ceph_x_reset,
-	.destroy = ceph_x_destroy,
-};
-
-
-int ceph_x_init(struct ceph_auth_client *ac)
-{
-	struct ceph_x_info *xi;
-	int ret;
-
-	dout("ceph_x_init %p\n", ac);
-	ret = -ENOMEM;
-	xi = kzalloc(sizeof(*xi), GFP_NOFS);
-	if (!xi)
-		goto out;
-
-	ret = -EINVAL;
-	if (!ac->secret) {
-		pr_err("no secret set (for auth_x protocol)\n");
-		goto out_nomem;
-	}
-
-	ret = ceph_crypto_key_unarmor(&xi->secret, ac->secret);
-	if (ret)
-		goto out_nomem;
-
-	xi->starting = true;
-	xi->ticket_handlers = RB_ROOT;
-
-	ac->protocol = CEPH_AUTH_CEPHX;
-	ac->private = xi;
-	ac->ops = &ceph_x_ops;
-	return 0;
-
-out_nomem:
-	kfree(xi);
-out:
-	return ret;
-}
-
-
diff --git a/fs/ceph/auth_x.h b/fs/ceph/auth_x.h
deleted file mode 100644
index ff6f818..0000000
--- a/fs/ceph/auth_x.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef _FS_CEPH_AUTH_X_H
-#define _FS_CEPH_AUTH_X_H
-
-#include <linux/rbtree.h>
-
-#include "crypto.h"
-#include "auth.h"
-#include "auth_x_protocol.h"
-
-/*
- * Handle ticket for a single service.
- */
-struct ceph_x_ticket_handler {
-	struct rb_node node;
-	unsigned service;
-
-	struct ceph_crypto_key session_key;
-	struct ceph_timespec validity;
-
-	u64 secret_id;
-	struct ceph_buffer *ticket_blob;
-
-	unsigned long renew_after, expires;
-};
-
-
-struct ceph_x_authorizer {
-	struct ceph_buffer *buf;
-	unsigned service;
-	u64 nonce;
-	char reply_buf[128];  /* big enough for encrypted blob */
-};
-
-struct ceph_x_info {
-	struct ceph_crypto_key secret;
-
-	bool starting;
-	u64 server_challenge;
-
-	unsigned have_keys;
-	struct rb_root ticket_handlers;
-
-	struct ceph_x_authorizer auth_authorizer;
-};
-
-extern int ceph_x_init(struct ceph_auth_client *ac);
-
-#endif
-
diff --git a/fs/ceph/buffer.c b/fs/ceph/buffer.c
deleted file mode 100644
index cd39f17..0000000
--- a/fs/ceph/buffer.c
+++ /dev/null
@@ -1,65 +0,0 @@
-
-#include "ceph_debug.h"
-
-#include <linux/slab.h>
-
-#include "buffer.h"
-#include "decode.h"
-
-struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
-{
-	struct ceph_buffer *b;
-
-	b = kmalloc(sizeof(*b), gfp);
-	if (!b)
-		return NULL;
-
-	b->vec.iov_base = kmalloc(len, gfp | __GFP_NOWARN);
-	if (b->vec.iov_base) {
-		b->is_vmalloc = false;
-	} else {
-		b->vec.iov_base = __vmalloc(len, gfp, PAGE_KERNEL);
-		if (!b->vec.iov_base) {
-			kfree(b);
-			return NULL;
-		}
-		b->is_vmalloc = true;
-	}
-
-	kref_init(&b->kref);
-	b->alloc_len = len;
-	b->vec.iov_len = len;
-	dout("buffer_new %p\n", b);
-	return b;
-}
-
-void ceph_buffer_release(struct kref *kref)
-{
-	struct ceph_buffer *b = container_of(kref, struct ceph_buffer, kref);
-
-	dout("buffer_release %p\n", b);
-	if (b->vec.iov_base) {
-		if (b->is_vmalloc)
-			vfree(b->vec.iov_base);
-		else
-			kfree(b->vec.iov_base);
-	}
-	kfree(b);
-}
-
-int ceph_decode_buffer(struct ceph_buffer **b, void **p, void *end)
-{
-	size_t len;
-
-	ceph_decode_need(p, end, sizeof(u32), bad);
-	len = ceph_decode_32(p);
-	dout("decode_buffer len %d\n", (int)len);
-	ceph_decode_need(p, end, len, bad);
-	*b = ceph_buffer_new(len, GFP_NOFS);
-	if (!*b)
-		return -ENOMEM;
-	ceph_decode_copy(p, (*b)->vec.iov_base, len);
-	return 0;
-bad:
-	return -EINVAL;
-}
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 73c1530..98ab13e 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/fs.h>
 #include <linux/kernel.h>
@@ -9,8 +9,9 @@
 #include <linux/writeback.h>
 
 #include "super.h"
-#include "decode.h"
-#include "messenger.h"
+#include "mds_client.h"
+#include <linux/ceph/decode.h>
+#include <linux/ceph/messenger.h>
 
 /*
  * Capability management
@@ -287,11 +288,11 @@
 	spin_unlock(&mdsc->caps_list_lock);
 }
 
-void ceph_reservation_status(struct ceph_client *client,
+void ceph_reservation_status(struct ceph_fs_client *fsc,
 			     int *total, int *avail, int *used, int *reserved,
 			     int *min)
 {
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 
 	if (total)
 		*total = mdsc->caps_total_count;
@@ -399,7 +400,7 @@
 static void __cap_set_timeouts(struct ceph_mds_client *mdsc,
 			       struct ceph_inode_info *ci)
 {
-	struct ceph_mount_args *ma = mdsc->client->mount_args;
+	struct ceph_mount_options *ma = mdsc->fsc->mount_options;
 
 	ci->i_hold_caps_min = round_jiffies(jiffies +
 					    ma->caps_wanted_delay_min * HZ);
@@ -515,7 +516,7 @@
 		 unsigned seq, unsigned mseq, u64 realmino, int flags,
 		 struct ceph_cap_reservation *caps_reservation)
 {
-	struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc;
+	struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	struct ceph_cap *new_cap = NULL;
 	struct ceph_cap *cap;
@@ -873,7 +874,7 @@
 	struct ceph_mds_session *session = cap->session;
 	struct ceph_inode_info *ci = cap->ci;
 	struct ceph_mds_client *mdsc =
-		&ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
+		ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
 	int removed = 0;
 
 	dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode);
@@ -1210,7 +1211,7 @@
 	int mds;
 	struct ceph_cap_snap *capsnap;
 	u32 mseq;
-	struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc;
+	struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
 	struct ceph_mds_session *session = NULL; /* if session != NULL, we hold
 						    session->s_mutex */
 	u64 next_follows = 0;  /* keep track of how far we've gotten through the
@@ -1336,7 +1337,7 @@
 void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
 {
 	struct ceph_mds_client *mdsc =
-		&ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
+		ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
 	struct inode *inode = &ci->vfs_inode;
 	int was = ci->i_dirty_caps;
 	int dirty = 0;
@@ -1378,7 +1379,7 @@
 static int __mark_caps_flushing(struct inode *inode,
 				 struct ceph_mds_session *session)
 {
-	struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc;
+	struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	int flushing;
 
@@ -1416,17 +1417,6 @@
 /*
  * try to invalidate mapping pages without blocking.
  */
-static int mapping_is_empty(struct address_space *mapping)
-{
-	struct page *page = find_get_page(mapping, 0);
-
-	if (!page)
-		return 1;
-
-	put_page(page);
-	return 0;
-}
-
 static int try_nonblocking_invalidate(struct inode *inode)
 {
 	struct ceph_inode_info *ci = ceph_inode(inode);
@@ -1436,7 +1426,7 @@
 	invalidate_mapping_pages(&inode->i_data, 0, -1);
 	spin_lock(&inode->i_lock);
 
-	if (mapping_is_empty(&inode->i_data) &&
+	if (inode->i_data.nrpages == 0 &&
 	    invalidating_gen == ci->i_rdcache_gen) {
 		/* success. */
 		dout("try_nonblocking_invalidate %p success\n", inode);
@@ -1462,8 +1452,8 @@
 void ceph_check_caps(struct ceph_inode_info *ci, int flags,
 		     struct ceph_mds_session *session)
 {
-	struct ceph_client *client = ceph_inode_to_client(&ci->vfs_inode);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_inode_to_client(&ci->vfs_inode);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct inode *inode = &ci->vfs_inode;
 	struct ceph_cap *cap;
 	int file_wanted, used;
@@ -1533,7 +1523,7 @@
 	 */
 	if ((!is_delayed || mdsc->stopping) &&
 	    ci->i_wrbuffer_ref == 0 &&               /* no dirty pages... */
-	    ci->i_rdcache_gen &&                     /* may have cached pages */
+	    inode->i_data.nrpages &&                 /* have cached pages */
 	    (file_wanted == 0 ||                     /* no open files */
 	     (revoking & (CEPH_CAP_FILE_CACHE|
 			  CEPH_CAP_FILE_LAZYIO))) && /*  or revoking cache */
@@ -1706,7 +1696,7 @@
 static int try_flush_caps(struct inode *inode, struct ceph_mds_session *session,
 			  unsigned *flush_tid)
 {
-	struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc;
+	struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	int unlock_session = session ? 0 : 1;
 	int flushing = 0;
@@ -1872,7 +1862,7 @@
 				       caps_are_flushed(inode, flush_tid));
 	} else {
 		struct ceph_mds_client *mdsc =
-			&ceph_sb_to_client(inode->i_sb)->mdsc;
+			ceph_sb_to_client(inode->i_sb)->mdsc;
 
 		spin_lock(&inode->i_lock);
 		if (__ceph_caps_dirty(ci))
@@ -2283,7 +2273,8 @@
 {
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	int mds = session->s_mds;
-	int seq = le32_to_cpu(grant->seq);
+	unsigned seq = le32_to_cpu(grant->seq);
+	unsigned issue_seq = le32_to_cpu(grant->issue_seq);
 	int newcaps = le32_to_cpu(grant->caps);
 	int issued, implemented, used, wanted, dirty;
 	u64 size = le64_to_cpu(grant->size);
@@ -2295,8 +2286,8 @@
 	int revoked_rdcache = 0;
 	int queue_invalidate = 0;
 
-	dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
-	     inode, cap, mds, seq, ceph_cap_string(newcaps));
+	dout("handle_cap_grant inode %p cap %p mds%d seq %u/%u %s\n",
+	     inode, cap, mds, seq, issue_seq, ceph_cap_string(newcaps));
 	dout(" size %llu max_size %llu, i_size %llu\n", size, max_size,
 		inode->i_size);
 
@@ -2392,6 +2383,7 @@
 	}
 
 	cap->seq = seq;
+	cap->issue_seq = issue_seq;
 
 	/* file layout may have changed */
 	ci->i_layout = grant->layout;
@@ -2463,7 +2455,7 @@
 	__releases(inode->i_lock)
 {
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc;
+	struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
 	unsigned seq = le32_to_cpu(m->seq);
 	int dirty = le32_to_cpu(m->dirty);
 	int cleaned = 0;
@@ -2711,7 +2703,7 @@
 		      struct ceph_msg *msg)
 {
 	struct ceph_mds_client *mdsc = session->s_mdsc;
-	struct super_block *sb = mdsc->client->sb;
+	struct super_block *sb = mdsc->fsc->sb;
 	struct inode *inode;
 	struct ceph_cap *cap;
 	struct ceph_mds_caps *h;
@@ -2774,15 +2766,7 @@
 		if (op == CEPH_CAP_OP_IMPORT)
 			__queue_cap_release(session, vino.ino, cap_id,
 					    mseq, seq);
-
-		/*
-		 * send any full release message to try to move things
-		 * along for the mds (who clearly thinks we still have this
-		 * cap).
-		 */
-		ceph_add_cap_releases(mdsc, session);
-		ceph_send_cap_releases(mdsc, session);
-		goto done;
+		goto flush_cap_releases;
 	}
 
 	/* these will work even if we don't have a cap yet */
@@ -2810,7 +2794,7 @@
 		dout(" no cap on %p ino %llx.%llx from mds%d\n",
 		     inode, ceph_ino(inode), ceph_snap(inode), mds);
 		spin_unlock(&inode->i_lock);
-		goto done;
+		goto flush_cap_releases;
 	}
 
 	/* note that each of these drops i_lock for us */
@@ -2834,6 +2818,17 @@
 		       ceph_cap_op_name(op));
 	}
 
+	goto done;
+
+flush_cap_releases:
+	/*
+	 * send any full release message to try to move things
+	 * along for the mds (who clearly thinks we still have this
+	 * cap).
+	 */
+	ceph_add_cap_releases(mdsc, session);
+	ceph_send_cap_releases(mdsc, session);
+
 done:
 	mutex_unlock(&session->s_mutex);
 done_unlocked:
diff --git a/fs/ceph/ceph_debug.h b/fs/ceph/ceph_debug.h
deleted file mode 100644
index 1818c23..0000000
--- a/fs/ceph/ceph_debug.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _FS_CEPH_DEBUG_H
-#define _FS_CEPH_DEBUG_H
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#ifdef CONFIG_CEPH_FS_PRETTYDEBUG
-
-/*
- * wrap pr_debug to include a filename:lineno prefix on each line.
- * this incurs some overhead (kernel size and execution time) due to
- * the extra function call at each call site.
- */
-
-# if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
-extern const char *ceph_file_part(const char *s, int len);
-#  define dout(fmt, ...)						\
-	pr_debug(" %12.12s:%-4d : " fmt,				\
-		 ceph_file_part(__FILE__, sizeof(__FILE__)),		\
-		 __LINE__, ##__VA_ARGS__)
-# else
-/* faux printk call just to see any compiler warnings. */
-#  define dout(fmt, ...)	do {				\
-		if (0)						\
-			printk(KERN_DEBUG fmt, ##__VA_ARGS__);	\
-	} while (0)
-# endif
-
-#else
-
-/*
- * or, just wrap pr_debug
- */
-# define dout(fmt, ...)	pr_debug(" " fmt, ##__VA_ARGS__)
-
-#endif
-
-#endif
diff --git a/fs/ceph/ceph_frag.c b/fs/ceph/ceph_frag.c
index ab6cf35..bdce8b1 100644
--- a/fs/ceph/ceph_frag.c
+++ b/fs/ceph/ceph_frag.c
@@ -1,7 +1,8 @@
 /*
  * Ceph 'frag' type
  */
-#include "types.h"
+#include <linux/module.h>
+#include <linux/ceph/types.h>
 
 int ceph_frag_compare(__u32 a, __u32 b)
 {
diff --git a/fs/ceph/ceph_fs.c b/fs/ceph/ceph_fs.c
deleted file mode 100644
index 3ac6cc7..0000000
--- a/fs/ceph/ceph_fs.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Some non-inline ceph helpers
- */
-#include "types.h"
-
-/*
- * return true if @layout appears to be valid
- */
-int ceph_file_layout_is_valid(const struct ceph_file_layout *layout)
-{
-	__u32 su = le32_to_cpu(layout->fl_stripe_unit);
-	__u32 sc = le32_to_cpu(layout->fl_stripe_count);
-	__u32 os = le32_to_cpu(layout->fl_object_size);
-
-	/* stripe unit, object size must be non-zero, 64k increment */
-	if (!su || (su & (CEPH_MIN_STRIPE_UNIT-1)))
-		return 0;
-	if (!os || (os & (CEPH_MIN_STRIPE_UNIT-1)))
-		return 0;
-	/* object size must be a multiple of stripe unit */
-	if (os < su || os % su)
-		return 0;
-	/* stripe count must be non-zero */
-	if (!sc)
-		return 0;
-	return 1;
-}
-
-
-int ceph_flags_to_mode(int flags)
-{
-	int mode;
-
-#ifdef O_DIRECTORY  /* fixme */
-	if ((flags & O_DIRECTORY) == O_DIRECTORY)
-		return CEPH_FILE_MODE_PIN;
-#endif
-	if ((flags & O_APPEND) == O_APPEND)
-		flags |= O_WRONLY;
-
-	if ((flags & O_ACCMODE) == O_RDWR)
-		mode = CEPH_FILE_MODE_RDWR;
-	else if ((flags & O_ACCMODE) == O_WRONLY)
-		mode = CEPH_FILE_MODE_WR;
-	else
-		mode = CEPH_FILE_MODE_RD;
-
-#ifdef O_LAZY
-	if (flags & O_LAZY)
-		mode |= CEPH_FILE_MODE_LAZY;
-#endif
-
-	return mode;
-}
-
-int ceph_caps_for_mode(int mode)
-{
-	int caps = CEPH_CAP_PIN;
-
-	if (mode & CEPH_FILE_MODE_RD)
-		caps |= CEPH_CAP_FILE_SHARED |
-			CEPH_CAP_FILE_RD | CEPH_CAP_FILE_CACHE;
-	if (mode & CEPH_FILE_MODE_WR)
-		caps |= CEPH_CAP_FILE_EXCL |
-			CEPH_CAP_FILE_WR | CEPH_CAP_FILE_BUFFER |
-			CEPH_CAP_AUTH_SHARED | CEPH_CAP_AUTH_EXCL |
-			CEPH_CAP_XATTR_SHARED | CEPH_CAP_XATTR_EXCL;
-	if (mode & CEPH_FILE_MODE_LAZY)
-		caps |= CEPH_CAP_FILE_LAZYIO;
-
-	return caps;
-}
diff --git a/fs/ceph/ceph_fs.h b/fs/ceph/ceph_fs.h
deleted file mode 100644
index d5619ac..0000000
--- a/fs/ceph/ceph_fs.h
+++ /dev/null
@@ -1,728 +0,0 @@
-/*
- * ceph_fs.h - Ceph constants and data types to share between kernel and
- * user space.
- *
- * Most types in this file are defined as little-endian, and are
- * primarily intended to describe data structures that pass over the
- * wire or that are stored on disk.
- *
- * LGPL2
- */
-
-#ifndef CEPH_FS_H
-#define CEPH_FS_H
-
-#include "msgr.h"
-#include "rados.h"
-
-/*
- * subprotocol versions.  when specific messages types or high-level
- * protocols change, bump the affected components.  we keep rev
- * internal cluster protocols separately from the public,
- * client-facing protocol.
- */
-#define CEPH_OSD_PROTOCOL     8 /* cluster internal */
-#define CEPH_MDS_PROTOCOL    12 /* cluster internal */
-#define CEPH_MON_PROTOCOL     5 /* cluster internal */
-#define CEPH_OSDC_PROTOCOL   24 /* server/client */
-#define CEPH_MDSC_PROTOCOL   32 /* server/client */
-#define CEPH_MONC_PROTOCOL   15 /* server/client */
-
-
-#define CEPH_INO_ROOT  1
-#define CEPH_INO_CEPH  2        /* hidden .ceph dir */
-
-/* arbitrary limit on max # of monitors (cluster of 3 is typical) */
-#define CEPH_MAX_MON   31
-
-
-/*
- * feature bits
- */
-#define CEPH_FEATURE_UID            (1<<0)
-#define CEPH_FEATURE_NOSRCADDR      (1<<1)
-#define CEPH_FEATURE_MONCLOCKCHECK  (1<<2)
-#define CEPH_FEATURE_FLOCK          (1<<3)
-
-
-/*
- * ceph_file_layout - describe data layout for a file/inode
- */
-struct ceph_file_layout {
-	/* file -> object mapping */
-	__le32 fl_stripe_unit;     /* stripe unit, in bytes.  must be multiple
-				      of page size. */
-	__le32 fl_stripe_count;    /* over this many objects */
-	__le32 fl_object_size;     /* until objects are this big, then move to
-				      new objects */
-	__le32 fl_cas_hash;        /* 0 = none; 1 = sha256 */
-
-	/* pg -> disk layout */
-	__le32 fl_object_stripe_unit;  /* for per-object parity, if any */
-
-	/* object -> pg layout */
-	__le32 fl_pg_preferred; /* preferred primary for pg (-1 for none) */
-	__le32 fl_pg_pool;      /* namespace, crush ruleset, rep level */
-} __attribute__ ((packed));
-
-#define CEPH_MIN_STRIPE_UNIT 65536
-
-int ceph_file_layout_is_valid(const struct ceph_file_layout *layout);
-
-
-/* crypto algorithms */
-#define CEPH_CRYPTO_NONE 0x0
-#define CEPH_CRYPTO_AES  0x1
-
-#define CEPH_AES_IV "cephsageyudagreg"
-
-/* security/authentication protocols */
-#define CEPH_AUTH_UNKNOWN	0x0
-#define CEPH_AUTH_NONE	 	0x1
-#define CEPH_AUTH_CEPHX	 	0x2
-
-#define CEPH_AUTH_UID_DEFAULT ((__u64) -1)
-
-
-/*********************************************
- * message layer
- */
-
-/*
- * message types
- */
-
-/* misc */
-#define CEPH_MSG_SHUTDOWN               1
-#define CEPH_MSG_PING                   2
-
-/* client <-> monitor */
-#define CEPH_MSG_MON_MAP                4
-#define CEPH_MSG_MON_GET_MAP            5
-#define CEPH_MSG_STATFS                 13
-#define CEPH_MSG_STATFS_REPLY           14
-#define CEPH_MSG_MON_SUBSCRIBE          15
-#define CEPH_MSG_MON_SUBSCRIBE_ACK      16
-#define CEPH_MSG_AUTH			17
-#define CEPH_MSG_AUTH_REPLY		18
-
-/* client <-> mds */
-#define CEPH_MSG_MDS_MAP                21
-
-#define CEPH_MSG_CLIENT_SESSION         22
-#define CEPH_MSG_CLIENT_RECONNECT       23
-
-#define CEPH_MSG_CLIENT_REQUEST         24
-#define CEPH_MSG_CLIENT_REQUEST_FORWARD 25
-#define CEPH_MSG_CLIENT_REPLY           26
-#define CEPH_MSG_CLIENT_CAPS            0x310
-#define CEPH_MSG_CLIENT_LEASE           0x311
-#define CEPH_MSG_CLIENT_SNAP            0x312
-#define CEPH_MSG_CLIENT_CAPRELEASE      0x313
-
-/* pool ops */
-#define CEPH_MSG_POOLOP_REPLY           48
-#define CEPH_MSG_POOLOP                 49
-
-
-/* osd */
-#define CEPH_MSG_OSD_MAP          41
-#define CEPH_MSG_OSD_OP           42
-#define CEPH_MSG_OSD_OPREPLY      43
-
-/* pool operations */
-enum {
-  POOL_OP_CREATE			= 0x01,
-  POOL_OP_DELETE			= 0x02,
-  POOL_OP_AUID_CHANGE			= 0x03,
-  POOL_OP_CREATE_SNAP			= 0x11,
-  POOL_OP_DELETE_SNAP			= 0x12,
-  POOL_OP_CREATE_UNMANAGED_SNAP		= 0x21,
-  POOL_OP_DELETE_UNMANAGED_SNAP		= 0x22,
-};
-
-struct ceph_mon_request_header {
-	__le64 have_version;
-	__le16 session_mon;
-	__le64 session_mon_tid;
-} __attribute__ ((packed));
-
-struct ceph_mon_statfs {
-	struct ceph_mon_request_header monhdr;
-	struct ceph_fsid fsid;
-} __attribute__ ((packed));
-
-struct ceph_statfs {
-	__le64 kb, kb_used, kb_avail;
-	__le64 num_objects;
-} __attribute__ ((packed));
-
-struct ceph_mon_statfs_reply {
-	struct ceph_fsid fsid;
-	__le64 version;
-	struct ceph_statfs st;
-} __attribute__ ((packed));
-
-const char *ceph_pool_op_name(int op);
-
-struct ceph_mon_poolop {
-	struct ceph_mon_request_header monhdr;
-	struct ceph_fsid fsid;
-	__le32 pool;
-	__le32 op;
-	__le64 auid;
-	__le64 snapid;
-	__le32 name_len;
-} __attribute__ ((packed));
-
-struct ceph_mon_poolop_reply {
-	struct ceph_mon_request_header monhdr;
-	struct ceph_fsid fsid;
-	__le32 reply_code;
-	__le32 epoch;
-	char has_data;
-	char data[0];
-} __attribute__ ((packed));
-
-struct ceph_mon_unmanaged_snap {
-	__le64 snapid;
-} __attribute__ ((packed));
-
-struct ceph_osd_getmap {
-	struct ceph_mon_request_header monhdr;
-	struct ceph_fsid fsid;
-	__le32 start;
-} __attribute__ ((packed));
-
-struct ceph_mds_getmap {
-	struct ceph_mon_request_header monhdr;
-	struct ceph_fsid fsid;
-} __attribute__ ((packed));
-
-struct ceph_client_mount {
-	struct ceph_mon_request_header monhdr;
-} __attribute__ ((packed));
-
-struct ceph_mon_subscribe_item {
-	__le64 have_version;	__le64 have;
-	__u8 onetime;
-} __attribute__ ((packed));
-
-struct ceph_mon_subscribe_ack {
-	__le32 duration;         /* seconds */
-	struct ceph_fsid fsid;
-} __attribute__ ((packed));
-
-/*
- * mds states
- *   > 0 -> in
- *  <= 0 -> out
- */
-#define CEPH_MDS_STATE_DNE          0  /* down, does not exist. */
-#define CEPH_MDS_STATE_STOPPED     -1  /* down, once existed, but no subtrees.
-					  empty log. */
-#define CEPH_MDS_STATE_BOOT        -4  /* up, boot announcement. */
-#define CEPH_MDS_STATE_STANDBY     -5  /* up, idle.  waiting for assignment. */
-#define CEPH_MDS_STATE_CREATING    -6  /* up, creating MDS instance. */
-#define CEPH_MDS_STATE_STARTING    -7  /* up, starting previously stopped mds */
-#define CEPH_MDS_STATE_STANDBY_REPLAY -8 /* up, tailing active node's journal */
-
-#define CEPH_MDS_STATE_REPLAY       8  /* up, replaying journal. */
-#define CEPH_MDS_STATE_RESOLVE      9  /* up, disambiguating distributed
-					  operations (import, rename, etc.) */
-#define CEPH_MDS_STATE_RECONNECT    10 /* up, reconnect to clients */
-#define CEPH_MDS_STATE_REJOIN       11 /* up, rejoining distributed cache */
-#define CEPH_MDS_STATE_CLIENTREPLAY 12 /* up, replaying client operations */
-#define CEPH_MDS_STATE_ACTIVE       13 /* up, active */
-#define CEPH_MDS_STATE_STOPPING     14 /* up, but exporting metadata */
-
-extern const char *ceph_mds_state_name(int s);
-
-
-/*
- * metadata lock types.
- *  - these are bitmasks.. we can compose them
- *  - they also define the lock ordering by the MDS
- *  - a few of these are internal to the mds
- */
-#define CEPH_LOCK_DVERSION    1
-#define CEPH_LOCK_DN          2
-#define CEPH_LOCK_ISNAP       16
-#define CEPH_LOCK_IVERSION    32    /* mds internal */
-#define CEPH_LOCK_IFILE       64
-#define CEPH_LOCK_IAUTH       128
-#define CEPH_LOCK_ILINK       256
-#define CEPH_LOCK_IDFT        512   /* dir frag tree */
-#define CEPH_LOCK_INEST       1024  /* mds internal */
-#define CEPH_LOCK_IXATTR      2048
-#define CEPH_LOCK_IFLOCK      4096  /* advisory file locks */
-#define CEPH_LOCK_INO         8192  /* immutable inode bits; not a lock */
-
-/* client_session ops */
-enum {
-	CEPH_SESSION_REQUEST_OPEN,
-	CEPH_SESSION_OPEN,
-	CEPH_SESSION_REQUEST_CLOSE,
-	CEPH_SESSION_CLOSE,
-	CEPH_SESSION_REQUEST_RENEWCAPS,
-	CEPH_SESSION_RENEWCAPS,
-	CEPH_SESSION_STALE,
-	CEPH_SESSION_RECALL_STATE,
-};
-
-extern const char *ceph_session_op_name(int op);
-
-struct ceph_mds_session_head {
-	__le32 op;
-	__le64 seq;
-	struct ceph_timespec stamp;
-	__le32 max_caps, max_leases;
-} __attribute__ ((packed));
-
-/* client_request */
-/*
- * metadata ops.
- *  & 0x001000 -> write op
- *  & 0x010000 -> follow symlink (e.g. stat(), not lstat()).
- &  & 0x100000 -> use weird ino/path trace
- */
-#define CEPH_MDS_OP_WRITE        0x001000
-enum {
-	CEPH_MDS_OP_LOOKUP     = 0x00100,
-	CEPH_MDS_OP_GETATTR    = 0x00101,
-	CEPH_MDS_OP_LOOKUPHASH = 0x00102,
-	CEPH_MDS_OP_LOOKUPPARENT = 0x00103,
-
-	CEPH_MDS_OP_SETXATTR   = 0x01105,
-	CEPH_MDS_OP_RMXATTR    = 0x01106,
-	CEPH_MDS_OP_SETLAYOUT  = 0x01107,
-	CEPH_MDS_OP_SETATTR    = 0x01108,
-	CEPH_MDS_OP_SETFILELOCK= 0x01109,
-	CEPH_MDS_OP_GETFILELOCK= 0x00110,
-
-	CEPH_MDS_OP_MKNOD      = 0x01201,
-	CEPH_MDS_OP_LINK       = 0x01202,
-	CEPH_MDS_OP_UNLINK     = 0x01203,
-	CEPH_MDS_OP_RENAME     = 0x01204,
-	CEPH_MDS_OP_MKDIR      = 0x01220,
-	CEPH_MDS_OP_RMDIR      = 0x01221,
-	CEPH_MDS_OP_SYMLINK    = 0x01222,
-
-	CEPH_MDS_OP_CREATE     = 0x01301,
-	CEPH_MDS_OP_OPEN       = 0x00302,
-	CEPH_MDS_OP_READDIR    = 0x00305,
-
-	CEPH_MDS_OP_LOOKUPSNAP = 0x00400,
-	CEPH_MDS_OP_MKSNAP     = 0x01400,
-	CEPH_MDS_OP_RMSNAP     = 0x01401,
-	CEPH_MDS_OP_LSSNAP     = 0x00402,
-};
-
-extern const char *ceph_mds_op_name(int op);
-
-
-#define CEPH_SETATTR_MODE   1
-#define CEPH_SETATTR_UID    2
-#define CEPH_SETATTR_GID    4
-#define CEPH_SETATTR_MTIME  8
-#define CEPH_SETATTR_ATIME 16
-#define CEPH_SETATTR_SIZE  32
-#define CEPH_SETATTR_CTIME 64
-
-union ceph_mds_request_args {
-	struct {
-		__le32 mask;                 /* CEPH_CAP_* */
-	} __attribute__ ((packed)) getattr;
-	struct {
-		__le32 mode;
-		__le32 uid;
-		__le32 gid;
-		struct ceph_timespec mtime;
-		struct ceph_timespec atime;
-		__le64 size, old_size;       /* old_size needed by truncate */
-		__le32 mask;                 /* CEPH_SETATTR_* */
-	} __attribute__ ((packed)) setattr;
-	struct {
-		__le32 frag;                 /* which dir fragment */
-		__le32 max_entries;          /* how many dentries to grab */
-		__le32 max_bytes;
-	} __attribute__ ((packed)) readdir;
-	struct {
-		__le32 mode;
-		__le32 rdev;
-	} __attribute__ ((packed)) mknod;
-	struct {
-		__le32 mode;
-	} __attribute__ ((packed)) mkdir;
-	struct {
-		__le32 flags;
-		__le32 mode;
-		__le32 stripe_unit;          /* layout for newly created file */
-		__le32 stripe_count;         /* ... */
-		__le32 object_size;
-		__le32 file_replication;
-		__le32 preferred;
-	} __attribute__ ((packed)) open;
-	struct {
-		__le32 flags;
-	} __attribute__ ((packed)) setxattr;
-	struct {
-		struct ceph_file_layout layout;
-	} __attribute__ ((packed)) setlayout;
-	struct {
-		__u8 rule; /* currently fcntl or flock */
-		__u8 type; /* shared, exclusive, remove*/
-		__le64 pid; /* process id requesting the lock */
-		__le64 pid_namespace;
-		__le64 start; /* initial location to lock */
-		__le64 length; /* num bytes to lock from start */
-		__u8 wait; /* will caller wait for lock to become available? */
-	} __attribute__ ((packed)) filelock_change;
-} __attribute__ ((packed));
-
-#define CEPH_MDS_FLAG_REPLAY        1  /* this is a replayed op */
-#define CEPH_MDS_FLAG_WANT_DENTRY   2  /* want dentry in reply */
-
-struct ceph_mds_request_head {
-	__le64 oldest_client_tid;
-	__le32 mdsmap_epoch;           /* on client */
-	__le32 flags;                  /* CEPH_MDS_FLAG_* */
-	__u8 num_retry, num_fwd;       /* count retry, fwd attempts */
-	__le16 num_releases;           /* # include cap/lease release records */
-	__le32 op;                     /* mds op code */
-	__le32 caller_uid, caller_gid;
-	__le64 ino;                    /* use this ino for openc, mkdir, mknod,
-					  etc. (if replaying) */
-	union ceph_mds_request_args args;
-} __attribute__ ((packed));
-
-/* cap/lease release record */
-struct ceph_mds_request_release {
-	__le64 ino, cap_id;            /* ino and unique cap id */
-	__le32 caps, wanted;           /* new issued, wanted */
-	__le32 seq, issue_seq, mseq;
-	__le32 dname_seq;              /* if releasing a dentry lease, a */
-	__le32 dname_len;              /* string follows. */
-} __attribute__ ((packed));
-
-/* client reply */
-struct ceph_mds_reply_head {
-	__le32 op;
-	__le32 result;
-	__le32 mdsmap_epoch;
-	__u8 safe;                     /* true if committed to disk */
-	__u8 is_dentry, is_target;     /* true if dentry, target inode records
-					  are included with reply */
-} __attribute__ ((packed));
-
-/* one for each node split */
-struct ceph_frag_tree_split {
-	__le32 frag;                   /* this frag splits... */
-	__le32 by;                     /* ...by this many bits */
-} __attribute__ ((packed));
-
-struct ceph_frag_tree_head {
-	__le32 nsplits;                /* num ceph_frag_tree_split records */
-	struct ceph_frag_tree_split splits[];
-} __attribute__ ((packed));
-
-/* capability issue, for bundling with mds reply */
-struct ceph_mds_reply_cap {
-	__le32 caps, wanted;           /* caps issued, wanted */
-	__le64 cap_id;
-	__le32 seq, mseq;
-	__le64 realm;                  /* snap realm */
-	__u8 flags;                    /* CEPH_CAP_FLAG_* */
-} __attribute__ ((packed));
-
-#define CEPH_CAP_FLAG_AUTH  1          /* cap is issued by auth mds */
-
-/* inode record, for bundling with mds reply */
-struct ceph_mds_reply_inode {
-	__le64 ino;
-	__le64 snapid;
-	__le32 rdev;
-	__le64 version;                /* inode version */
-	__le64 xattr_version;          /* version for xattr blob */
-	struct ceph_mds_reply_cap cap; /* caps issued for this inode */
-	struct ceph_file_layout layout;
-	struct ceph_timespec ctime, mtime, atime;
-	__le32 time_warp_seq;
-	__le64 size, max_size, truncate_size;
-	__le32 truncate_seq;
-	__le32 mode, uid, gid;
-	__le32 nlink;
-	__le64 files, subdirs, rbytes, rfiles, rsubdirs;  /* dir stats */
-	struct ceph_timespec rctime;
-	struct ceph_frag_tree_head fragtree;  /* (must be at end of struct) */
-} __attribute__ ((packed));
-/* followed by frag array, then symlink string, then xattr blob */
-
-/* reply_lease follows dname, and reply_inode */
-struct ceph_mds_reply_lease {
-	__le16 mask;            /* lease type(s) */
-	__le32 duration_ms;     /* lease duration */
-	__le32 seq;
-} __attribute__ ((packed));
-
-struct ceph_mds_reply_dirfrag {
-	__le32 frag;            /* fragment */
-	__le32 auth;            /* auth mds, if this is a delegation point */
-	__le32 ndist;           /* number of mds' this is replicated on */
-	__le32 dist[];
-} __attribute__ ((packed));
-
-#define CEPH_LOCK_FCNTL    1
-#define CEPH_LOCK_FLOCK    2
-
-#define CEPH_LOCK_SHARED   1
-#define CEPH_LOCK_EXCL     2
-#define CEPH_LOCK_UNLOCK   4
-
-struct ceph_filelock {
-	__le64 start;/* file offset to start lock at */
-	__le64 length; /* num bytes to lock; 0 for all following start */
-	__le64 client; /* which client holds the lock */
-	__le64 pid; /* process id holding the lock on the client */
-	__le64 pid_namespace;
-	__u8 type; /* shared lock, exclusive lock, or unlock */
-} __attribute__ ((packed));
-
-
-/* file access modes */
-#define CEPH_FILE_MODE_PIN        0
-#define CEPH_FILE_MODE_RD         1
-#define CEPH_FILE_MODE_WR         2
-#define CEPH_FILE_MODE_RDWR       3  /* RD | WR */
-#define CEPH_FILE_MODE_LAZY       4  /* lazy io */
-#define CEPH_FILE_MODE_NUM        8  /* bc these are bit fields.. mostly */
-
-int ceph_flags_to_mode(int flags);
-
-
-/* capability bits */
-#define CEPH_CAP_PIN         1  /* no specific capabilities beyond the pin */
-
-/* generic cap bits */
-#define CEPH_CAP_GSHARED     1  /* client can reads */
-#define CEPH_CAP_GEXCL       2  /* client can read and update */
-#define CEPH_CAP_GCACHE      4  /* (file) client can cache reads */
-#define CEPH_CAP_GRD         8  /* (file) client can read */
-#define CEPH_CAP_GWR        16  /* (file) client can write */
-#define CEPH_CAP_GBUFFER    32  /* (file) client can buffer writes */
-#define CEPH_CAP_GWREXTEND  64  /* (file) client can extend EOF */
-#define CEPH_CAP_GLAZYIO   128  /* (file) client can perform lazy io */
-
-/* per-lock shift */
-#define CEPH_CAP_SAUTH      2
-#define CEPH_CAP_SLINK      4
-#define CEPH_CAP_SXATTR     6
-#define CEPH_CAP_SFILE      8
-#define CEPH_CAP_SFLOCK    20 
-
-#define CEPH_CAP_BITS       22
-
-/* composed values */
-#define CEPH_CAP_AUTH_SHARED  (CEPH_CAP_GSHARED  << CEPH_CAP_SAUTH)
-#define CEPH_CAP_AUTH_EXCL     (CEPH_CAP_GEXCL     << CEPH_CAP_SAUTH)
-#define CEPH_CAP_LINK_SHARED  (CEPH_CAP_GSHARED  << CEPH_CAP_SLINK)
-#define CEPH_CAP_LINK_EXCL     (CEPH_CAP_GEXCL     << CEPH_CAP_SLINK)
-#define CEPH_CAP_XATTR_SHARED (CEPH_CAP_GSHARED  << CEPH_CAP_SXATTR)
-#define CEPH_CAP_XATTR_EXCL    (CEPH_CAP_GEXCL     << CEPH_CAP_SXATTR)
-#define CEPH_CAP_FILE(x)    (x << CEPH_CAP_SFILE)
-#define CEPH_CAP_FILE_SHARED   (CEPH_CAP_GSHARED   << CEPH_CAP_SFILE)
-#define CEPH_CAP_FILE_EXCL     (CEPH_CAP_GEXCL     << CEPH_CAP_SFILE)
-#define CEPH_CAP_FILE_CACHE    (CEPH_CAP_GCACHE    << CEPH_CAP_SFILE)
-#define CEPH_CAP_FILE_RD       (CEPH_CAP_GRD       << CEPH_CAP_SFILE)
-#define CEPH_CAP_FILE_WR       (CEPH_CAP_GWR       << CEPH_CAP_SFILE)
-#define CEPH_CAP_FILE_BUFFER   (CEPH_CAP_GBUFFER   << CEPH_CAP_SFILE)
-#define CEPH_CAP_FILE_WREXTEND (CEPH_CAP_GWREXTEND << CEPH_CAP_SFILE)
-#define CEPH_CAP_FILE_LAZYIO   (CEPH_CAP_GLAZYIO   << CEPH_CAP_SFILE)
-#define CEPH_CAP_FLOCK_SHARED  (CEPH_CAP_GSHARED   << CEPH_CAP_SFLOCK)
-#define CEPH_CAP_FLOCK_EXCL    (CEPH_CAP_GEXCL     << CEPH_CAP_SFLOCK)
-
-
-/* cap masks (for getattr) */
-#define CEPH_STAT_CAP_INODE    CEPH_CAP_PIN
-#define CEPH_STAT_CAP_TYPE     CEPH_CAP_PIN  /* mode >> 12 */
-#define CEPH_STAT_CAP_SYMLINK  CEPH_CAP_PIN
-#define CEPH_STAT_CAP_UID      CEPH_CAP_AUTH_SHARED
-#define CEPH_STAT_CAP_GID      CEPH_CAP_AUTH_SHARED
-#define CEPH_STAT_CAP_MODE     CEPH_CAP_AUTH_SHARED
-#define CEPH_STAT_CAP_NLINK    CEPH_CAP_LINK_SHARED
-#define CEPH_STAT_CAP_LAYOUT   CEPH_CAP_FILE_SHARED
-#define CEPH_STAT_CAP_MTIME    CEPH_CAP_FILE_SHARED
-#define CEPH_STAT_CAP_SIZE     CEPH_CAP_FILE_SHARED
-#define CEPH_STAT_CAP_ATIME    CEPH_CAP_FILE_SHARED  /* fixme */
-#define CEPH_STAT_CAP_XATTR    CEPH_CAP_XATTR_SHARED
-#define CEPH_STAT_CAP_INODE_ALL (CEPH_CAP_PIN |			\
-				 CEPH_CAP_AUTH_SHARED |	\
-				 CEPH_CAP_LINK_SHARED |	\
-				 CEPH_CAP_FILE_SHARED |	\
-				 CEPH_CAP_XATTR_SHARED)
-
-#define CEPH_CAP_ANY_SHARED (CEPH_CAP_AUTH_SHARED |			\
-			      CEPH_CAP_LINK_SHARED |			\
-			      CEPH_CAP_XATTR_SHARED |			\
-			      CEPH_CAP_FILE_SHARED)
-#define CEPH_CAP_ANY_RD   (CEPH_CAP_ANY_SHARED | CEPH_CAP_FILE_RD |	\
-			   CEPH_CAP_FILE_CACHE)
-
-#define CEPH_CAP_ANY_EXCL (CEPH_CAP_AUTH_EXCL |		\
-			   CEPH_CAP_LINK_EXCL |		\
-			   CEPH_CAP_XATTR_EXCL |	\
-			   CEPH_CAP_FILE_EXCL)
-#define CEPH_CAP_ANY_FILE_WR (CEPH_CAP_FILE_WR | CEPH_CAP_FILE_BUFFER |	\
-			      CEPH_CAP_FILE_EXCL)
-#define CEPH_CAP_ANY_WR   (CEPH_CAP_ANY_EXCL | CEPH_CAP_ANY_FILE_WR)
-#define CEPH_CAP_ANY      (CEPH_CAP_ANY_RD | CEPH_CAP_ANY_EXCL | \
-			   CEPH_CAP_ANY_FILE_WR | CEPH_CAP_FILE_LAZYIO | \
-			   CEPH_CAP_PIN)
-
-#define CEPH_CAP_LOCKS (CEPH_LOCK_IFILE | CEPH_LOCK_IAUTH | CEPH_LOCK_ILINK | \
-			CEPH_LOCK_IXATTR)
-
-int ceph_caps_for_mode(int mode);
-
-enum {
-	CEPH_CAP_OP_GRANT,         /* mds->client grant */
-	CEPH_CAP_OP_REVOKE,        /* mds->client revoke */
-	CEPH_CAP_OP_TRUNC,         /* mds->client trunc notify */
-	CEPH_CAP_OP_EXPORT,        /* mds has exported the cap */
-	CEPH_CAP_OP_IMPORT,        /* mds has imported the cap */
-	CEPH_CAP_OP_UPDATE,        /* client->mds update */
-	CEPH_CAP_OP_DROP,          /* client->mds drop cap bits */
-	CEPH_CAP_OP_FLUSH,         /* client->mds cap writeback */
-	CEPH_CAP_OP_FLUSH_ACK,     /* mds->client flushed */
-	CEPH_CAP_OP_FLUSHSNAP,     /* client->mds flush snapped metadata */
-	CEPH_CAP_OP_FLUSHSNAP_ACK, /* mds->client flushed snapped metadata */
-	CEPH_CAP_OP_RELEASE,       /* client->mds release (clean) cap */
-	CEPH_CAP_OP_RENEW,         /* client->mds renewal request */
-};
-
-extern const char *ceph_cap_op_name(int op);
-
-/*
- * caps message, used for capability callbacks, acks, requests, etc.
- */
-struct ceph_mds_caps {
-	__le32 op;                  /* CEPH_CAP_OP_* */
-	__le64 ino, realm;
-	__le64 cap_id;
-	__le32 seq, issue_seq;
-	__le32 caps, wanted, dirty; /* latest issued/wanted/dirty */
-	__le32 migrate_seq;
-	__le64 snap_follows;
-	__le32 snap_trace_len;
-
-	/* authlock */
-	__le32 uid, gid, mode;
-
-	/* linklock */
-	__le32 nlink;
-
-	/* xattrlock */
-	__le32 xattr_len;
-	__le64 xattr_version;
-
-	/* filelock */
-	__le64 size, max_size, truncate_size;
-	__le32 truncate_seq;
-	struct ceph_timespec mtime, atime, ctime;
-	struct ceph_file_layout layout;
-	__le32 time_warp_seq;
-} __attribute__ ((packed));
-
-/* cap release msg head */
-struct ceph_mds_cap_release {
-	__le32 num;                /* number of cap_items that follow */
-} __attribute__ ((packed));
-
-struct ceph_mds_cap_item {
-	__le64 ino;
-	__le64 cap_id;
-	__le32 migrate_seq, seq;
-} __attribute__ ((packed));
-
-#define CEPH_MDS_LEASE_REVOKE           1  /*    mds  -> client */
-#define CEPH_MDS_LEASE_RELEASE          2  /* client  -> mds    */
-#define CEPH_MDS_LEASE_RENEW            3  /* client <-> mds    */
-#define CEPH_MDS_LEASE_REVOKE_ACK       4  /* client  -> mds    */
-
-extern const char *ceph_lease_op_name(int o);
-
-/* lease msg header */
-struct ceph_mds_lease {
-	__u8 action;            /* CEPH_MDS_LEASE_* */
-	__le16 mask;            /* which lease */
-	__le64 ino;
-	__le64 first, last;     /* snap range */
-	__le32 seq;
-	__le32 duration_ms;     /* duration of renewal */
-} __attribute__ ((packed));
-/* followed by a __le32+string for dname */
-
-/* client reconnect */
-struct ceph_mds_cap_reconnect {
-	__le64 cap_id;
-	__le32 wanted;
-	__le32 issued;
-	__le64 snaprealm;
-	__le64 pathbase;        /* base ino for our path to this ino */
-	__le32 flock_len;       /* size of flock state blob, if any */
-} __attribute__ ((packed));
-/* followed by flock blob */
-
-struct ceph_mds_cap_reconnect_v1 {
-	__le64 cap_id;
-	__le32 wanted;
-	__le32 issued;
-	__le64 size;
-	struct ceph_timespec mtime, atime;
-	__le64 snaprealm;
-	__le64 pathbase;        /* base ino for our path to this ino */
-} __attribute__ ((packed));
-
-struct ceph_mds_snaprealm_reconnect {
-	__le64 ino;     /* snap realm base */
-	__le64 seq;     /* snap seq for this snap realm */
-	__le64 parent;  /* parent realm */
-} __attribute__ ((packed));
-
-/*
- * snaps
- */
-enum {
-	CEPH_SNAP_OP_UPDATE,  /* CREATE or DESTROY */
-	CEPH_SNAP_OP_CREATE,
-	CEPH_SNAP_OP_DESTROY,
-	CEPH_SNAP_OP_SPLIT,
-};
-
-extern const char *ceph_snap_op_name(int o);
-
-/* snap msg header */
-struct ceph_mds_snap_head {
-	__le32 op;                /* CEPH_SNAP_OP_* */
-	__le64 split;             /* ino to split off, if any */
-	__le32 num_split_inos;    /* # inos belonging to new child realm */
-	__le32 num_split_realms;  /* # child realms udner new child realm */
-	__le32 trace_len;         /* size of snap trace blob */
-} __attribute__ ((packed));
-/* followed by split ino list, then split realms, then the trace blob */
-
-/*
- * encode info about a snaprealm, as viewed by a client
- */
-struct ceph_mds_snap_realm {
-	__le64 ino;           /* ino */
-	__le64 created;       /* snap: when created */
-	__le64 parent;        /* ino: parent realm */
-	__le64 parent_since;  /* snap: same parent since */
-	__le64 seq;           /* snap: version */
-	__le32 num_snaps;
-	__le32 num_prior_parent_snaps;
-} __attribute__ ((packed));
-/* followed by my snap list, then prior parent snap list */
-
-#endif
diff --git a/fs/ceph/ceph_hash.c b/fs/ceph/ceph_hash.c
deleted file mode 100644
index bd57001..0000000
--- a/fs/ceph/ceph_hash.c
+++ /dev/null
@@ -1,118 +0,0 @@
-
-#include "types.h"
-
-/*
- * Robert Jenkin's hash function.
- * http://burtleburtle.net/bob/hash/evahash.html
- * This is in the public domain.
- */
-#define mix(a, b, c)						\
-	do {							\
-		a = a - b;  a = a - c;  a = a ^ (c >> 13);	\
-		b = b - c;  b = b - a;  b = b ^ (a << 8);	\
-		c = c - a;  c = c - b;  c = c ^ (b >> 13);	\
-		a = a - b;  a = a - c;  a = a ^ (c >> 12);	\
-		b = b - c;  b = b - a;  b = b ^ (a << 16);	\
-		c = c - a;  c = c - b;  c = c ^ (b >> 5);	\
-		a = a - b;  a = a - c;  a = a ^ (c >> 3);	\
-		b = b - c;  b = b - a;  b = b ^ (a << 10);	\
-		c = c - a;  c = c - b;  c = c ^ (b >> 15);	\
-	} while (0)
-
-unsigned ceph_str_hash_rjenkins(const char *str, unsigned length)
-{
-	const unsigned char *k = (const unsigned char *)str;
-	__u32 a, b, c;  /* the internal state */
-	__u32 len;      /* how many key bytes still need mixing */
-
-	/* Set up the internal state */
-	len = length;
-	a = 0x9e3779b9;      /* the golden ratio; an arbitrary value */
-	b = a;
-	c = 0;               /* variable initialization of internal state */
-
-	/* handle most of the key */
-	while (len >= 12) {
-		a = a + (k[0] + ((__u32)k[1] << 8) + ((__u32)k[2] << 16) +
-			 ((__u32)k[3] << 24));
-		b = b + (k[4] + ((__u32)k[5] << 8) + ((__u32)k[6] << 16) +
-			 ((__u32)k[7] << 24));
-		c = c + (k[8] + ((__u32)k[9] << 8) + ((__u32)k[10] << 16) +
-			 ((__u32)k[11] << 24));
-		mix(a, b, c);
-		k = k + 12;
-		len = len - 12;
-	}
-
-	/* handle the last 11 bytes */
-	c = c + length;
-	switch (len) {            /* all the case statements fall through */
-	case 11:
-		c = c + ((__u32)k[10] << 24);
-	case 10:
-		c = c + ((__u32)k[9] << 16);
-	case 9:
-		c = c + ((__u32)k[8] << 8);
-		/* the first byte of c is reserved for the length */
-	case 8:
-		b = b + ((__u32)k[7] << 24);
-	case 7:
-		b = b + ((__u32)k[6] << 16);
-	case 6:
-		b = b + ((__u32)k[5] << 8);
-	case 5:
-		b = b + k[4];
-	case 4:
-		a = a + ((__u32)k[3] << 24);
-	case 3:
-		a = a + ((__u32)k[2] << 16);
-	case 2:
-		a = a + ((__u32)k[1] << 8);
-	case 1:
-		a = a + k[0];
-		/* case 0: nothing left to add */
-	}
-	mix(a, b, c);
-
-	return c;
-}
-
-/*
- * linux dcache hash
- */
-unsigned ceph_str_hash_linux(const char *str, unsigned length)
-{
-	unsigned long hash = 0;
-	unsigned char c;
-
-	while (length--) {
-		c = *str++;
-		hash = (hash + (c << 4) + (c >> 4)) * 11;
-	}
-	return hash;
-}
-
-
-unsigned ceph_str_hash(int type, const char *s, unsigned len)
-{
-	switch (type) {
-	case CEPH_STR_HASH_LINUX:
-		return ceph_str_hash_linux(s, len);
-	case CEPH_STR_HASH_RJENKINS:
-		return ceph_str_hash_rjenkins(s, len);
-	default:
-		return -1;
-	}
-}
-
-const char *ceph_str_hash_name(int type)
-{
-	switch (type) {
-	case CEPH_STR_HASH_LINUX:
-		return "linux";
-	case CEPH_STR_HASH_RJENKINS:
-		return "rjenkins";
-	default:
-		return "unknown";
-	}
-}
diff --git a/fs/ceph/ceph_strings.c b/fs/ceph/ceph_strings.c
deleted file mode 100644
index c6179d3..0000000
--- a/fs/ceph/ceph_strings.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Ceph string constants
- */
-#include "types.h"
-
-const char *ceph_entity_type_name(int type)
-{
-	switch (type) {
-	case CEPH_ENTITY_TYPE_MDS: return "mds";
-	case CEPH_ENTITY_TYPE_OSD: return "osd";
-	case CEPH_ENTITY_TYPE_MON: return "mon";
-	case CEPH_ENTITY_TYPE_CLIENT: return "client";
-	case CEPH_ENTITY_TYPE_AUTH: return "auth";
-	default: return "unknown";
-	}
-}
-
-const char *ceph_osd_op_name(int op)
-{
-	switch (op) {
-	case CEPH_OSD_OP_READ: return "read";
-	case CEPH_OSD_OP_STAT: return "stat";
-
-	case CEPH_OSD_OP_MASKTRUNC: return "masktrunc";
-
-	case CEPH_OSD_OP_WRITE: return "write";
-	case CEPH_OSD_OP_DELETE: return "delete";
-	case CEPH_OSD_OP_TRUNCATE: return "truncate";
-	case CEPH_OSD_OP_ZERO: return "zero";
-	case CEPH_OSD_OP_WRITEFULL: return "writefull";
-	case CEPH_OSD_OP_ROLLBACK: return "rollback";
-
-	case CEPH_OSD_OP_APPEND: return "append";
-	case CEPH_OSD_OP_STARTSYNC: return "startsync";
-	case CEPH_OSD_OP_SETTRUNC: return "settrunc";
-	case CEPH_OSD_OP_TRIMTRUNC: return "trimtrunc";
-
-	case CEPH_OSD_OP_TMAPUP: return "tmapup";
-	case CEPH_OSD_OP_TMAPGET: return "tmapget";
-	case CEPH_OSD_OP_TMAPPUT: return "tmapput";
-
-	case CEPH_OSD_OP_GETXATTR: return "getxattr";
-	case CEPH_OSD_OP_GETXATTRS: return "getxattrs";
-	case CEPH_OSD_OP_SETXATTR: return "setxattr";
-	case CEPH_OSD_OP_SETXATTRS: return "setxattrs";
-	case CEPH_OSD_OP_RESETXATTRS: return "resetxattrs";
-	case CEPH_OSD_OP_RMXATTR: return "rmxattr";
-	case CEPH_OSD_OP_CMPXATTR: return "cmpxattr";
-
-	case CEPH_OSD_OP_PULL: return "pull";
-	case CEPH_OSD_OP_PUSH: return "push";
-	case CEPH_OSD_OP_BALANCEREADS: return "balance-reads";
-	case CEPH_OSD_OP_UNBALANCEREADS: return "unbalance-reads";
-	case CEPH_OSD_OP_SCRUB: return "scrub";
-
-	case CEPH_OSD_OP_WRLOCK: return "wrlock";
-	case CEPH_OSD_OP_WRUNLOCK: return "wrunlock";
-	case CEPH_OSD_OP_RDLOCK: return "rdlock";
-	case CEPH_OSD_OP_RDUNLOCK: return "rdunlock";
-	case CEPH_OSD_OP_UPLOCK: return "uplock";
-	case CEPH_OSD_OP_DNLOCK: return "dnlock";
-
-	case CEPH_OSD_OP_CALL: return "call";
-
-	case CEPH_OSD_OP_PGLS: return "pgls";
-	}
-	return "???";
-}
-
-const char *ceph_mds_state_name(int s)
-{
-	switch (s) {
-		/* down and out */
-	case CEPH_MDS_STATE_DNE:        return "down:dne";
-	case CEPH_MDS_STATE_STOPPED:    return "down:stopped";
-		/* up and out */
-	case CEPH_MDS_STATE_BOOT:       return "up:boot";
-	case CEPH_MDS_STATE_STANDBY:    return "up:standby";
-	case CEPH_MDS_STATE_STANDBY_REPLAY:    return "up:standby-replay";
-	case CEPH_MDS_STATE_CREATING:   return "up:creating";
-	case CEPH_MDS_STATE_STARTING:   return "up:starting";
-		/* up and in */
-	case CEPH_MDS_STATE_REPLAY:     return "up:replay";
-	case CEPH_MDS_STATE_RESOLVE:    return "up:resolve";
-	case CEPH_MDS_STATE_RECONNECT:  return "up:reconnect";
-	case CEPH_MDS_STATE_REJOIN:     return "up:rejoin";
-	case CEPH_MDS_STATE_CLIENTREPLAY: return "up:clientreplay";
-	case CEPH_MDS_STATE_ACTIVE:     return "up:active";
-	case CEPH_MDS_STATE_STOPPING:   return "up:stopping";
-	}
-	return "???";
-}
-
-const char *ceph_session_op_name(int op)
-{
-	switch (op) {
-	case CEPH_SESSION_REQUEST_OPEN: return "request_open";
-	case CEPH_SESSION_OPEN: return "open";
-	case CEPH_SESSION_REQUEST_CLOSE: return "request_close";
-	case CEPH_SESSION_CLOSE: return "close";
-	case CEPH_SESSION_REQUEST_RENEWCAPS: return "request_renewcaps";
-	case CEPH_SESSION_RENEWCAPS: return "renewcaps";
-	case CEPH_SESSION_STALE: return "stale";
-	case CEPH_SESSION_RECALL_STATE: return "recall_state";
-	}
-	return "???";
-}
-
-const char *ceph_mds_op_name(int op)
-{
-	switch (op) {
-	case CEPH_MDS_OP_LOOKUP:  return "lookup";
-	case CEPH_MDS_OP_LOOKUPHASH:  return "lookuphash";
-	case CEPH_MDS_OP_LOOKUPPARENT:  return "lookupparent";
-	case CEPH_MDS_OP_GETATTR:  return "getattr";
-	case CEPH_MDS_OP_SETXATTR: return "setxattr";
-	case CEPH_MDS_OP_SETATTR: return "setattr";
-	case CEPH_MDS_OP_RMXATTR: return "rmxattr";
-	case CEPH_MDS_OP_READDIR: return "readdir";
-	case CEPH_MDS_OP_MKNOD: return "mknod";
-	case CEPH_MDS_OP_LINK: return "link";
-	case CEPH_MDS_OP_UNLINK: return "unlink";
-	case CEPH_MDS_OP_RENAME: return "rename";
-	case CEPH_MDS_OP_MKDIR: return "mkdir";
-	case CEPH_MDS_OP_RMDIR: return "rmdir";
-	case CEPH_MDS_OP_SYMLINK: return "symlink";
-	case CEPH_MDS_OP_CREATE: return "create";
-	case CEPH_MDS_OP_OPEN: return "open";
-	case CEPH_MDS_OP_LOOKUPSNAP: return "lookupsnap";
-	case CEPH_MDS_OP_LSSNAP: return "lssnap";
-	case CEPH_MDS_OP_MKSNAP: return "mksnap";
-	case CEPH_MDS_OP_RMSNAP: return "rmsnap";
-	case CEPH_MDS_OP_SETFILELOCK: return "setfilelock";
-	case CEPH_MDS_OP_GETFILELOCK: return "getfilelock";
-	}
-	return "???";
-}
-
-const char *ceph_cap_op_name(int op)
-{
-	switch (op) {
-	case CEPH_CAP_OP_GRANT: return "grant";
-	case CEPH_CAP_OP_REVOKE: return "revoke";
-	case CEPH_CAP_OP_TRUNC: return "trunc";
-	case CEPH_CAP_OP_EXPORT: return "export";
-	case CEPH_CAP_OP_IMPORT: return "import";
-	case CEPH_CAP_OP_UPDATE: return "update";
-	case CEPH_CAP_OP_DROP: return "drop";
-	case CEPH_CAP_OP_FLUSH: return "flush";
-	case CEPH_CAP_OP_FLUSH_ACK: return "flush_ack";
-	case CEPH_CAP_OP_FLUSHSNAP: return "flushsnap";
-	case CEPH_CAP_OP_FLUSHSNAP_ACK: return "flushsnap_ack";
-	case CEPH_CAP_OP_RELEASE: return "release";
-	case CEPH_CAP_OP_RENEW: return "renew";
-	}
-	return "???";
-}
-
-const char *ceph_lease_op_name(int o)
-{
-	switch (o) {
-	case CEPH_MDS_LEASE_REVOKE: return "revoke";
-	case CEPH_MDS_LEASE_RELEASE: return "release";
-	case CEPH_MDS_LEASE_RENEW: return "renew";
-	case CEPH_MDS_LEASE_REVOKE_ACK: return "revoke_ack";
-	}
-	return "???";
-}
-
-const char *ceph_snap_op_name(int o)
-{
-	switch (o) {
-	case CEPH_SNAP_OP_UPDATE: return "update";
-	case CEPH_SNAP_OP_CREATE: return "create";
-	case CEPH_SNAP_OP_DESTROY: return "destroy";
-	case CEPH_SNAP_OP_SPLIT: return "split";
-	}
-	return "???";
-}
-
-const char *ceph_pool_op_name(int op)
-{
-	switch (op) {
-	case POOL_OP_CREATE: return "create";
-	case POOL_OP_DELETE: return "delete";
-	case POOL_OP_AUID_CHANGE: return "auid change";
-	case POOL_OP_CREATE_SNAP: return "create snap";
-	case POOL_OP_DELETE_SNAP: return "delete snap";
-	case POOL_OP_CREATE_UNMANAGED_SNAP: return "create unmanaged snap";
-	case POOL_OP_DELETE_UNMANAGED_SNAP: return "delete unmanaged snap";
-	}
-	return "???";
-}
diff --git a/fs/ceph/crush/crush.c b/fs/ceph/crush/crush.c
deleted file mode 100644
index fabd302..0000000
--- a/fs/ceph/crush/crush.c
+++ /dev/null
@@ -1,151 +0,0 @@
-
-#ifdef __KERNEL__
-# include <linux/slab.h>
-#else
-# include <stdlib.h>
-# include <assert.h>
-# define kfree(x) do { if (x) free(x); } while (0)
-# define BUG_ON(x) assert(!(x))
-#endif
-
-#include "crush.h"
-
-const char *crush_bucket_alg_name(int alg)
-{
-	switch (alg) {
-	case CRUSH_BUCKET_UNIFORM: return "uniform";
-	case CRUSH_BUCKET_LIST: return "list";
-	case CRUSH_BUCKET_TREE: return "tree";
-	case CRUSH_BUCKET_STRAW: return "straw";
-	default: return "unknown";
-	}
-}
-
-/**
- * crush_get_bucket_item_weight - Get weight of an item in given bucket
- * @b: bucket pointer
- * @p: item index in bucket
- */
-int crush_get_bucket_item_weight(struct crush_bucket *b, int p)
-{
-	if (p >= b->size)
-		return 0;
-
-	switch (b->alg) {
-	case CRUSH_BUCKET_UNIFORM:
-		return ((struct crush_bucket_uniform *)b)->item_weight;
-	case CRUSH_BUCKET_LIST:
-		return ((struct crush_bucket_list *)b)->item_weights[p];
-	case CRUSH_BUCKET_TREE:
-		if (p & 1)
-			return ((struct crush_bucket_tree *)b)->node_weights[p];
-		return 0;
-	case CRUSH_BUCKET_STRAW:
-		return ((struct crush_bucket_straw *)b)->item_weights[p];
-	}
-	return 0;
-}
-
-/**
- * crush_calc_parents - Calculate parent vectors for the given crush map.
- * @map: crush_map pointer
- */
-void crush_calc_parents(struct crush_map *map)
-{
-	int i, b, c;
-
-	for (b = 0; b < map->max_buckets; b++) {
-		if (map->buckets[b] == NULL)
-			continue;
-		for (i = 0; i < map->buckets[b]->size; i++) {
-			c = map->buckets[b]->items[i];
-			BUG_ON(c >= map->max_devices ||
-			       c < -map->max_buckets);
-			if (c >= 0)
-				map->device_parents[c] = map->buckets[b]->id;
-			else
-				map->bucket_parents[-1-c] = map->buckets[b]->id;
-		}
-	}
-}
-
-void crush_destroy_bucket_uniform(struct crush_bucket_uniform *b)
-{
-	kfree(b->h.perm);
-	kfree(b->h.items);
-	kfree(b);
-}
-
-void crush_destroy_bucket_list(struct crush_bucket_list *b)
-{
-	kfree(b->item_weights);
-	kfree(b->sum_weights);
-	kfree(b->h.perm);
-	kfree(b->h.items);
-	kfree(b);
-}
-
-void crush_destroy_bucket_tree(struct crush_bucket_tree *b)
-{
-	kfree(b->node_weights);
-	kfree(b);
-}
-
-void crush_destroy_bucket_straw(struct crush_bucket_straw *b)
-{
-	kfree(b->straws);
-	kfree(b->item_weights);
-	kfree(b->h.perm);
-	kfree(b->h.items);
-	kfree(b);
-}
-
-void crush_destroy_bucket(struct crush_bucket *b)
-{
-	switch (b->alg) {
-	case CRUSH_BUCKET_UNIFORM:
-		crush_destroy_bucket_uniform((struct crush_bucket_uniform *)b);
-		break;
-	case CRUSH_BUCKET_LIST:
-		crush_destroy_bucket_list((struct crush_bucket_list *)b);
-		break;
-	case CRUSH_BUCKET_TREE:
-		crush_destroy_bucket_tree((struct crush_bucket_tree *)b);
-		break;
-	case CRUSH_BUCKET_STRAW:
-		crush_destroy_bucket_straw((struct crush_bucket_straw *)b);
-		break;
-	}
-}
-
-/**
- * crush_destroy - Destroy a crush_map
- * @map: crush_map pointer
- */
-void crush_destroy(struct crush_map *map)
-{
-	int b;
-
-	/* buckets */
-	if (map->buckets) {
-		for (b = 0; b < map->max_buckets; b++) {
-			if (map->buckets[b] == NULL)
-				continue;
-			crush_destroy_bucket(map->buckets[b]);
-		}
-		kfree(map->buckets);
-	}
-
-	/* rules */
-	if (map->rules) {
-		for (b = 0; b < map->max_rules; b++)
-			kfree(map->rules[b]);
-		kfree(map->rules);
-	}
-
-	kfree(map->bucket_parents);
-	kfree(map->device_parents);
-	kfree(map);
-}
-
-
diff --git a/fs/ceph/crush/hash.c b/fs/ceph/crush/hash.c
deleted file mode 100644
index 5873aed..0000000
--- a/fs/ceph/crush/hash.c
+++ /dev/null
@@ -1,149 +0,0 @@
-
-#include <linux/types.h>
-#include "hash.h"
-
-/*
- * Robert Jenkins' function for mixing 32-bit values
- * http://burtleburtle.net/bob/hash/evahash.html
- * a, b = random bits, c = input and output
- */
-#define crush_hashmix(a, b, c) do {			\
-		a = a-b;  a = a-c;  a = a^(c>>13);	\
-		b = b-c;  b = b-a;  b = b^(a<<8);	\
-		c = c-a;  c = c-b;  c = c^(b>>13);	\
-		a = a-b;  a = a-c;  a = a^(c>>12);	\
-		b = b-c;  b = b-a;  b = b^(a<<16);	\
-		c = c-a;  c = c-b;  c = c^(b>>5);	\
-		a = a-b;  a = a-c;  a = a^(c>>3);	\
-		b = b-c;  b = b-a;  b = b^(a<<10);	\
-		c = c-a;  c = c-b;  c = c^(b>>15);	\
-	} while (0)
-
-#define crush_hash_seed 1315423911
-
-static __u32 crush_hash32_rjenkins1(__u32 a)
-{
-	__u32 hash = crush_hash_seed ^ a;
-	__u32 b = a;
-	__u32 x = 231232;
-	__u32 y = 1232;
-	crush_hashmix(b, x, hash);
-	crush_hashmix(y, a, hash);
-	return hash;
-}
-
-static __u32 crush_hash32_rjenkins1_2(__u32 a, __u32 b)
-{
-	__u32 hash = crush_hash_seed ^ a ^ b;
-	__u32 x = 231232;
-	__u32 y = 1232;
-	crush_hashmix(a, b, hash);
-	crush_hashmix(x, a, hash);
-	crush_hashmix(b, y, hash);
-	return hash;
-}
-
-static __u32 crush_hash32_rjenkins1_3(__u32 a, __u32 b, __u32 c)
-{
-	__u32 hash = crush_hash_seed ^ a ^ b ^ c;
-	__u32 x = 231232;
-	__u32 y = 1232;
-	crush_hashmix(a, b, hash);
-	crush_hashmix(c, x, hash);
-	crush_hashmix(y, a, hash);
-	crush_hashmix(b, x, hash);
-	crush_hashmix(y, c, hash);
-	return hash;
-}
-
-static __u32 crush_hash32_rjenkins1_4(__u32 a, __u32 b, __u32 c, __u32 d)
-{
-	__u32 hash = crush_hash_seed ^ a ^ b ^ c ^ d;
-	__u32 x = 231232;
-	__u32 y = 1232;
-	crush_hashmix(a, b, hash);
-	crush_hashmix(c, d, hash);
-	crush_hashmix(a, x, hash);
-	crush_hashmix(y, b, hash);
-	crush_hashmix(c, x, hash);
-	crush_hashmix(y, d, hash);
-	return hash;
-}
-
-static __u32 crush_hash32_rjenkins1_5(__u32 a, __u32 b, __u32 c, __u32 d,
-				      __u32 e)
-{
-	__u32 hash = crush_hash_seed ^ a ^ b ^ c ^ d ^ e;
-	__u32 x = 231232;
-	__u32 y = 1232;
-	crush_hashmix(a, b, hash);
-	crush_hashmix(c, d, hash);
-	crush_hashmix(e, x, hash);
-	crush_hashmix(y, a, hash);
-	crush_hashmix(b, x, hash);
-	crush_hashmix(y, c, hash);
-	crush_hashmix(d, x, hash);
-	crush_hashmix(y, e, hash);
-	return hash;
-}
-
-
-__u32 crush_hash32(int type, __u32 a)
-{
-	switch (type) {
-	case CRUSH_HASH_RJENKINS1:
-		return crush_hash32_rjenkins1(a);
-	default:
-		return 0;
-	}
-}
-
-__u32 crush_hash32_2(int type, __u32 a, __u32 b)
-{
-	switch (type) {
-	case CRUSH_HASH_RJENKINS1:
-		return crush_hash32_rjenkins1_2(a, b);
-	default:
-		return 0;
-	}
-}
-
-__u32 crush_hash32_3(int type, __u32 a, __u32 b, __u32 c)
-{
-	switch (type) {
-	case CRUSH_HASH_RJENKINS1:
-		return crush_hash32_rjenkins1_3(a, b, c);
-	default:
-		return 0;
-	}
-}
-
-__u32 crush_hash32_4(int type, __u32 a, __u32 b, __u32 c, __u32 d)
-{
-	switch (type) {
-	case CRUSH_HASH_RJENKINS1:
-		return crush_hash32_rjenkins1_4(a, b, c, d);
-	default:
-		return 0;
-	}
-}
-
-__u32 crush_hash32_5(int type, __u32 a, __u32 b, __u32 c, __u32 d, __u32 e)
-{
-	switch (type) {
-	case CRUSH_HASH_RJENKINS1:
-		return crush_hash32_rjenkins1_5(a, b, c, d, e);
-	default:
-		return 0;
-	}
-}
-
-const char *crush_hash_name(int type)
-{
-	switch (type) {
-	case CRUSH_HASH_RJENKINS1:
-		return "rjenkins1";
-	default:
-		return "unknown";
-	}
-}
diff --git a/fs/ceph/crush/mapper.c b/fs/ceph/crush/mapper.c
deleted file mode 100644
index a4eec13..0000000
--- a/fs/ceph/crush/mapper.c
+++ /dev/null
@@ -1,609 +0,0 @@
-
-#ifdef __KERNEL__
-# include <linux/string.h>
-# include <linux/slab.h>
-# include <linux/bug.h>
-# include <linux/kernel.h>
-# ifndef dprintk
-#  define dprintk(args...)
-# endif
-#else
-# include <string.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <assert.h>
-# define BUG_ON(x) assert(!(x))
-# define dprintk(args...) /* printf(args) */
-# define kmalloc(x, f) malloc(x)
-# define kfree(x) free(x)
-#endif
-
-#include "crush.h"
-#include "hash.h"
-
-/*
- * Implement the core CRUSH mapping algorithm.
- */
-
-/**
- * crush_find_rule - find a crush_rule id for a given ruleset, type, and size.
- * @map: the crush_map
- * @ruleset: the storage ruleset id (user defined)
- * @type: storage ruleset type (user defined)
- * @size: output set size
- */
-int crush_find_rule(struct crush_map *map, int ruleset, int type, int size)
-{
-	int i;
-
-	for (i = 0; i < map->max_rules; i++) {
-		if (map->rules[i] &&
-		    map->rules[i]->mask.ruleset == ruleset &&
-		    map->rules[i]->mask.type == type &&
-		    map->rules[i]->mask.min_size <= size &&
-		    map->rules[i]->mask.max_size >= size)
-			return i;
-	}
-	return -1;
-}
-
-
-/*
- * bucket choose methods
- *
- * For each bucket algorithm, we have a "choose" method that, given a
- * crush input @x and replica position (usually, position in output set) @r,
- * will produce an item in the bucket.
- */
-
-/*
- * Choose based on a random permutation of the bucket.
- *
- * We used to use some prime number arithmetic to do this, but it
- * wasn't very random, and had some other bad behaviors.  Instead, we
- * calculate an actual random permutation of the bucket members.
- * Since this is expensive, we optimize for the r=0 case, which
- * captures the vast majority of calls.
- */
-static int bucket_perm_choose(struct crush_bucket *bucket,
-			      int x, int r)
-{
-	unsigned pr = r % bucket->size;
-	unsigned i, s;
-
-	/* start a new permutation if @x has changed */
-	if (bucket->perm_x != x || bucket->perm_n == 0) {
-		dprintk("bucket %d new x=%d\n", bucket->id, x);
-		bucket->perm_x = x;
-
-		/* optimize common r=0 case */
-		if (pr == 0) {
-			s = crush_hash32_3(bucket->hash, x, bucket->id, 0) %
-				bucket->size;
-			bucket->perm[0] = s;
-			bucket->perm_n = 0xffff;   /* magic value, see below */
-			goto out;
-		}
-
-		for (i = 0; i < bucket->size; i++)
-			bucket->perm[i] = i;
-		bucket->perm_n = 0;
-	} else if (bucket->perm_n == 0xffff) {
-		/* clean up after the r=0 case above */
-		for (i = 1; i < bucket->size; i++)
-			bucket->perm[i] = i;
-		bucket->perm[bucket->perm[0]] = 0;
-		bucket->perm_n = 1;
-	}
-
-	/* calculate permutation up to pr */
-	for (i = 0; i < bucket->perm_n; i++)
-		dprintk(" perm_choose have %d: %d\n", i, bucket->perm[i]);
-	while (bucket->perm_n <= pr) {
-		unsigned p = bucket->perm_n;
-		/* no point in swapping the final entry */
-		if (p < bucket->size - 1) {
-			i = crush_hash32_3(bucket->hash, x, bucket->id, p) %
-				(bucket->size - p);
-			if (i) {
-				unsigned t = bucket->perm[p + i];
-				bucket->perm[p + i] = bucket->perm[p];
-				bucket->perm[p] = t;
-			}
-			dprintk(" perm_choose swap %d with %d\n", p, p+i);
-		}
-		bucket->perm_n++;
-	}
-	for (i = 0; i < bucket->size; i++)
-		dprintk(" perm_choose  %d: %d\n", i, bucket->perm[i]);
-
-	s = bucket->perm[pr];
-out:
-	dprintk(" perm_choose %d sz=%d x=%d r=%d (%d) s=%d\n", bucket->id,
-		bucket->size, x, r, pr, s);
-	return bucket->items[s];
-}
-
-/* uniform */
-static int bucket_uniform_choose(struct crush_bucket_uniform *bucket,
-				 int x, int r)
-{
-	return bucket_perm_choose(&bucket->h, x, r);
-}
-
-/* list */
-static int bucket_list_choose(struct crush_bucket_list *bucket,
-			      int x, int r)
-{
-	int i;
-
-	for (i = bucket->h.size-1; i >= 0; i--) {
-		__u64 w = crush_hash32_4(bucket->h.hash,x, bucket->h.items[i],
-					 r, bucket->h.id);
-		w &= 0xffff;
-		dprintk("list_choose i=%d x=%d r=%d item %d weight %x "
-			"sw %x rand %llx",
-			i, x, r, bucket->h.items[i], bucket->item_weights[i],
-			bucket->sum_weights[i], w);
-		w *= bucket->sum_weights[i];
-		w = w >> 16;
-		/*dprintk(" scaled %llx\n", w);*/
-		if (w < bucket->item_weights[i])
-			return bucket->h.items[i];
-	}
-
-	BUG_ON(1);
-	return 0;
-}
-
-
-/* (binary) tree */
-static int height(int n)
-{
-	int h = 0;
-	while ((n & 1) == 0) {
-		h++;
-		n = n >> 1;
-	}
-	return h;
-}
-
-static int left(int x)
-{
-	int h = height(x);
-	return x - (1 << (h-1));
-}
-
-static int right(int x)
-{
-	int h = height(x);
-	return x + (1 << (h-1));
-}
-
-static int terminal(int x)
-{
-	return x & 1;
-}
-
-static int bucket_tree_choose(struct crush_bucket_tree *bucket,
-			      int x, int r)
-{
-	int n, l;
-	__u32 w;
-	__u64 t;
-
-	/* start at root */
-	n = bucket->num_nodes >> 1;
-
-	while (!terminal(n)) {
-		/* pick point in [0, w) */
-		w = bucket->node_weights[n];
-		t = (__u64)crush_hash32_4(bucket->h.hash, x, n, r,
-					  bucket->h.id) * (__u64)w;
-		t = t >> 32;
-
-		/* descend to the left or right? */
-		l = left(n);
-		if (t < bucket->node_weights[l])
-			n = l;
-		else
-			n = right(n);
-	}
-
-	return bucket->h.items[n >> 1];
-}
-
-
-/* straw */
-
-static int bucket_straw_choose(struct crush_bucket_straw *bucket,
-			       int x, int r)
-{
-	int i;
-	int high = 0;
-	__u64 high_draw = 0;
-	__u64 draw;
-
-	for (i = 0; i < bucket->h.size; i++) {
-		draw = crush_hash32_3(bucket->h.hash, x, bucket->h.items[i], r);
-		draw &= 0xffff;
-		draw *= bucket->straws[i];
-		if (i == 0 || draw > high_draw) {
-			high = i;
-			high_draw = draw;
-		}
-	}
-	return bucket->h.items[high];
-}
-
-static int crush_bucket_choose(struct crush_bucket *in, int x, int r)
-{
-	dprintk(" crush_bucket_choose %d x=%d r=%d\n", in->id, x, r);
-	switch (in->alg) {
-	case CRUSH_BUCKET_UNIFORM:
-		return bucket_uniform_choose((struct crush_bucket_uniform *)in,
-					  x, r);
-	case CRUSH_BUCKET_LIST:
-		return bucket_list_choose((struct crush_bucket_list *)in,
-					  x, r);
-	case CRUSH_BUCKET_TREE:
-		return bucket_tree_choose((struct crush_bucket_tree *)in,
-					  x, r);
-	case CRUSH_BUCKET_STRAW:
-		return bucket_straw_choose((struct crush_bucket_straw *)in,
-					   x, r);
-	default:
-		BUG_ON(1);
-		return in->items[0];
-	}
-}
-
-/*
- * true if device is marked "out" (failed, fully offloaded)
- * of the cluster
- */
-static int is_out(struct crush_map *map, __u32 *weight, int item, int x)
-{
-	if (weight[item] >= 0x10000)
-		return 0;
-	if (weight[item] == 0)
-		return 1;
-	if ((crush_hash32_2(CRUSH_HASH_RJENKINS1, x, item) & 0xffff)
-	    < weight[item])
-		return 0;
-	return 1;
-}
-
-/**
- * crush_choose - choose numrep distinct items of given type
- * @map: the crush_map
- * @bucket: the bucket we are choose an item from
- * @x: crush input value
- * @numrep: the number of items to choose
- * @type: the type of item to choose
- * @out: pointer to output vector
- * @outpos: our position in that vector
- * @firstn: true if choosing "first n" items, false if choosing "indep"
- * @recurse_to_leaf: true if we want one device under each item of given type
- * @out2: second output vector for leaf items (if @recurse_to_leaf)
- */
-static int crush_choose(struct crush_map *map,
-			struct crush_bucket *bucket,
-			__u32 *weight,
-			int x, int numrep, int type,
-			int *out, int outpos,
-			int firstn, int recurse_to_leaf,
-			int *out2)
-{
-	int rep;
-	int ftotal, flocal;
-	int retry_descent, retry_bucket, skip_rep;
-	struct crush_bucket *in = bucket;
-	int r;
-	int i;
-	int item = 0;
-	int itemtype;
-	int collide, reject;
-	const int orig_tries = 5; /* attempts before we fall back to search */
-
-	dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "",
-		bucket->id, x, outpos, numrep);
-
-	for (rep = outpos; rep < numrep; rep++) {
-		/* keep trying until we get a non-out, non-colliding item */
-		ftotal = 0;
-		skip_rep = 0;
-		do {
-			retry_descent = 0;
-			in = bucket;               /* initial bucket */
-
-			/* choose through intervening buckets */
-			flocal = 0;
-			do {
-				collide = 0;
-				retry_bucket = 0;
-				r = rep;
-				if (in->alg == CRUSH_BUCKET_UNIFORM) {
-					/* be careful */
-					if (firstn || numrep >= in->size)
-						/* r' = r + f_total */
-						r += ftotal;
-					else if (in->size % numrep == 0)
-						/* r'=r+(n+1)*f_local */
-						r += (numrep+1) *
-							(flocal+ftotal);
-					else
-						/* r' = r + n*f_local */
-						r += numrep * (flocal+ftotal);
-				} else {
-					if (firstn)
-						/* r' = r + f_total */
-						r += ftotal;
-					else
-						/* r' = r + n*f_local */
-						r += numrep * (flocal+ftotal);
-				}
-
-				/* bucket choose */
-				if (in->size == 0) {
-					reject = 1;
-					goto reject;
-				}
-				if (flocal >= (in->size>>1) &&
-				    flocal > orig_tries)
-					item = bucket_perm_choose(in, x, r);
-				else
-					item = crush_bucket_choose(in, x, r);
-				BUG_ON(item >= map->max_devices);
-
-				/* desired type? */
-				if (item < 0)
-					itemtype = map->buckets[-1-item]->type;
-				else
-					itemtype = 0;
-				dprintk("  item %d type %d\n", item, itemtype);
-
-				/* keep going? */
-				if (itemtype != type) {
-					BUG_ON(item >= 0 ||
-					       (-1-item) >= map->max_buckets);
-					in = map->buckets[-1-item];
-					retry_bucket = 1;
-					continue;
-				}
-
-				/* collision? */
-				for (i = 0; i < outpos; i++) {
-					if (out[i] == item) {
-						collide = 1;
-						break;
-					}
-				}
-
-				reject = 0;
-				if (recurse_to_leaf) {
-					if (item < 0) {
-						if (crush_choose(map,
-							 map->buckets[-1-item],
-							 weight,
-							 x, outpos+1, 0,
-							 out2, outpos,
-							 firstn, 0,
-							 NULL) <= outpos)
-							/* didn't get leaf */
-							reject = 1;
-					} else {
-						/* we already have a leaf! */
-						out2[outpos] = item;
-					}
-				}
-
-				if (!reject) {
-					/* out? */
-					if (itemtype == 0)
-						reject = is_out(map, weight,
-								item, x);
-					else
-						reject = 0;
-				}
-
-reject:
-				if (reject || collide) {
-					ftotal++;
-					flocal++;
-
-					if (collide && flocal < 3)
-						/* retry locally a few times */
-						retry_bucket = 1;
-					else if (flocal < in->size + orig_tries)
-						/* exhaustive bucket search */
-						retry_bucket = 1;
-					else if (ftotal < 20)
-						/* then retry descent */
-						retry_descent = 1;
-					else
-						/* else give up */
-						skip_rep = 1;
-					dprintk("  reject %d  collide %d  "
-						"ftotal %d  flocal %d\n",
-						reject, collide, ftotal,
-						flocal);
-				}
-			} while (retry_bucket);
-		} while (retry_descent);
-
-		if (skip_rep) {
-			dprintk("skip rep\n");
-			continue;
-		}
-
-		dprintk("CHOOSE got %d\n", item);
-		out[outpos] = item;
-		outpos++;
-	}
-
-	dprintk("CHOOSE returns %d\n", outpos);
-	return outpos;
-}
-
-
-/**
- * crush_do_rule - calculate a mapping with the given input and rule
- * @map: the crush_map
- * @ruleno: the rule id
- * @x: hash input
- * @result: pointer to result vector
- * @result_max: maximum result size
- * @force: force initial replica choice; -1 for none
- */
-int crush_do_rule(struct crush_map *map,
-		  int ruleno, int x, int *result, int result_max,
-		  int force, __u32 *weight)
-{
-	int result_len;
-	int force_context[CRUSH_MAX_DEPTH];
-	int force_pos = -1;
-	int a[CRUSH_MAX_SET];
-	int b[CRUSH_MAX_SET];
-	int c[CRUSH_MAX_SET];
-	int recurse_to_leaf;
-	int *w;
-	int wsize = 0;
-	int *o;
-	int osize;
-	int *tmp;
-	struct crush_rule *rule;
-	int step;
-	int i, j;
-	int numrep;
-	int firstn;
-	int rc = -1;
-
-	BUG_ON(ruleno >= map->max_rules);
-
-	rule = map->rules[ruleno];
-	result_len = 0;
-	w = a;
-	o = b;
-
-	/*
-	 * determine hierarchical context of force, if any.  note
-	 * that this may or may not correspond to the specific types
-	 * referenced by the crush rule.
-	 */
-	if (force >= 0) {
-		if (force >= map->max_devices ||
-		    map->device_parents[force] == 0) {
-			/*dprintk("CRUSH: forcefed device dne\n");*/
-			rc = -1;  /* force fed device dne */
-			goto out;
-		}
-		if (!is_out(map, weight, force, x)) {
-			while (1) {
-				force_context[++force_pos] = force;
-				if (force >= 0)
-					force = map->device_parents[force];
-				else
-					force = map->bucket_parents[-1-force];
-				if (force == 0)
-					break;
-			}
-		}
-	}
-
-	for (step = 0; step < rule->len; step++) {
-		firstn = 0;
-		switch (rule->steps[step].op) {
-		case CRUSH_RULE_TAKE:
-			w[0] = rule->steps[step].arg1;
-			if (force_pos >= 0) {
-				BUG_ON(force_context[force_pos] != w[0]);
-				force_pos--;
-			}
-			wsize = 1;
-			break;
-
-		case CRUSH_RULE_CHOOSE_LEAF_FIRSTN:
-		case CRUSH_RULE_CHOOSE_FIRSTN:
-			firstn = 1;
-		case CRUSH_RULE_CHOOSE_LEAF_INDEP:
-		case CRUSH_RULE_CHOOSE_INDEP:
-			BUG_ON(wsize == 0);
-
-			recurse_to_leaf =
-				rule->steps[step].op ==
-				 CRUSH_RULE_CHOOSE_LEAF_FIRSTN ||
-				rule->steps[step].op ==
-				CRUSH_RULE_CHOOSE_LEAF_INDEP;
-
-			/* reset output */
-			osize = 0;
-
-			for (i = 0; i < wsize; i++) {
-				/*
-				 * see CRUSH_N, CRUSH_N_MINUS macros.
-				 * basically, numrep <= 0 means relative to
-				 * the provided result_max
-				 */
-				numrep = rule->steps[step].arg1;
-				if (numrep <= 0) {
-					numrep += result_max;
-					if (numrep <= 0)
-						continue;
-				}
-				j = 0;
-				if (osize == 0 && force_pos >= 0) {
-					/* skip any intermediate types */
-					while (force_pos &&
-					       force_context[force_pos] < 0 &&
-					       rule->steps[step].arg2 !=
-					       map->buckets[-1 -
-					       force_context[force_pos]]->type)
-						force_pos--;
-					o[osize] = force_context[force_pos];
-					if (recurse_to_leaf)
-						c[osize] = force_context[0];
-					j++;
-					force_pos--;
-				}
-				osize += crush_choose(map,
-						      map->buckets[-1-w[i]],
-						      weight,
-						      x, numrep,
-						      rule->steps[step].arg2,
-						      o+osize, j,
-						      firstn,
-						      recurse_to_leaf, c+osize);
-			}
-
-			if (recurse_to_leaf)
-				/* copy final _leaf_ values to output set */
-				memcpy(o, c, osize*sizeof(*o));
-
-			/* swap t and w arrays */
-			tmp = o;
-			o = w;
-			w = tmp;
-			wsize = osize;
-			break;
-
-
-		case CRUSH_RULE_EMIT:
-			for (i = 0; i < wsize && result_len < result_max; i++) {
-				result[result_len] = w[i];
-				result_len++;
-			}
-			wsize = 0;
-			break;
-
-		default:
-			BUG_ON(1);
-		}
-	}
-	rc = result_len;
-
-out:
-	return rc;
-}
-
-
diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c
deleted file mode 100644
index a3e627f..0000000
--- a/fs/ceph/crypto.c
+++ /dev/null
@@ -1,412 +0,0 @@
-
-#include "ceph_debug.h"
-
-#include <linux/err.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-#include <crypto/hash.h>
-
-#include "crypto.h"
-#include "decode.h"
-
-int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end)
-{
-	if (*p + sizeof(u16) + sizeof(key->created) +
-	    sizeof(u16) + key->len > end)
-		return -ERANGE;
-	ceph_encode_16(p, key->type);
-	ceph_encode_copy(p, &key->created, sizeof(key->created));
-	ceph_encode_16(p, key->len);
-	ceph_encode_copy(p, key->key, key->len);
-	return 0;
-}
-
-int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end)
-{
-	ceph_decode_need(p, end, 2*sizeof(u16) + sizeof(key->created), bad);
-	key->type = ceph_decode_16(p);
-	ceph_decode_copy(p, &key->created, sizeof(key->created));
-	key->len = ceph_decode_16(p);
-	ceph_decode_need(p, end, key->len, bad);
-	key->key = kmalloc(key->len, GFP_NOFS);
-	if (!key->key)
-		return -ENOMEM;
-	ceph_decode_copy(p, key->key, key->len);
-	return 0;
-
-bad:
-	dout("failed to decode crypto key\n");
-	return -EINVAL;
-}
-
-int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *inkey)
-{
-	int inlen = strlen(inkey);
-	int blen = inlen * 3 / 4;
-	void *buf, *p;
-	int ret;
-
-	dout("crypto_key_unarmor %s\n", inkey);
-	buf = kmalloc(blen, GFP_NOFS);
-	if (!buf)
-		return -ENOMEM;
-	blen = ceph_unarmor(buf, inkey, inkey+inlen);
-	if (blen < 0) {
-		kfree(buf);
-		return blen;
-	}
-
-	p = buf;
-	ret = ceph_crypto_key_decode(key, &p, p + blen);
-	kfree(buf);
-	if (ret)
-		return ret;
-	dout("crypto_key_unarmor key %p type %d len %d\n", key,
-	     key->type, key->len);
-	return 0;
-}
-
-
-
-#define AES_KEY_SIZE 16
-
-static struct crypto_blkcipher *ceph_crypto_alloc_cipher(void)
-{
-	return crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
-}
-
-static const u8 *aes_iv = (u8 *)CEPH_AES_IV;
-
-static int ceph_aes_encrypt(const void *key, int key_len,
-			    void *dst, size_t *dst_len,
-			    const void *src, size_t src_len)
-{
-	struct scatterlist sg_in[2], sg_out[1];
-	struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
-	struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
-	int ret;
-	void *iv;
-	int ivsize;
-	size_t zero_padding = (0x10 - (src_len & 0x0f));
-	char pad[16];
-
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
-
-	memset(pad, zero_padding, zero_padding);
-
-	*dst_len = src_len + zero_padding;
-
-	crypto_blkcipher_setkey((void *)tfm, key, key_len);
-	sg_init_table(sg_in, 2);
-	sg_set_buf(&sg_in[0], src, src_len);
-	sg_set_buf(&sg_in[1], pad, zero_padding);
-	sg_init_table(sg_out, 1);
-	sg_set_buf(sg_out, dst, *dst_len);
-	iv = crypto_blkcipher_crt(tfm)->iv;
-	ivsize = crypto_blkcipher_ivsize(tfm);
-
-	memcpy(iv, aes_iv, ivsize);
-	/*
-	print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1,
-		       key, key_len, 1);
-	print_hex_dump(KERN_ERR, "enc src: ", DUMP_PREFIX_NONE, 16, 1,
-			src, src_len, 1);
-	print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1,
-			pad, zero_padding, 1);
-	*/
-	ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
-				     src_len + zero_padding);
-	crypto_free_blkcipher(tfm);
-	if (ret < 0)
-		pr_err("ceph_aes_crypt failed %d\n", ret);
-	/*
-	print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1,
-		       dst, *dst_len, 1);
-	*/
-	return 0;
-}
-
-static int ceph_aes_encrypt2(const void *key, int key_len, void *dst,
-			     size_t *dst_len,
-			     const void *src1, size_t src1_len,
-			     const void *src2, size_t src2_len)
-{
-	struct scatterlist sg_in[3], sg_out[1];
-	struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
-	struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
-	int ret;
-	void *iv;
-	int ivsize;
-	size_t zero_padding = (0x10 - ((src1_len + src2_len) & 0x0f));
-	char pad[16];
-
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
-
-	memset(pad, zero_padding, zero_padding);
-
-	*dst_len = src1_len + src2_len + zero_padding;
-
-	crypto_blkcipher_setkey((void *)tfm, key, key_len);
-	sg_init_table(sg_in, 3);
-	sg_set_buf(&sg_in[0], src1, src1_len);
-	sg_set_buf(&sg_in[1], src2, src2_len);
-	sg_set_buf(&sg_in[2], pad, zero_padding);
-	sg_init_table(sg_out, 1);
-	sg_set_buf(sg_out, dst, *dst_len);
-	iv = crypto_blkcipher_crt(tfm)->iv;
-	ivsize = crypto_blkcipher_ivsize(tfm);
-
-	memcpy(iv, aes_iv, ivsize);
-	/*
-	print_hex_dump(KERN_ERR, "enc  key: ", DUMP_PREFIX_NONE, 16, 1,
-		       key, key_len, 1);
-	print_hex_dump(KERN_ERR, "enc src1: ", DUMP_PREFIX_NONE, 16, 1,
-			src1, src1_len, 1);
-	print_hex_dump(KERN_ERR, "enc src2: ", DUMP_PREFIX_NONE, 16, 1,
-			src2, src2_len, 1);
-	print_hex_dump(KERN_ERR, "enc  pad: ", DUMP_PREFIX_NONE, 16, 1,
-			pad, zero_padding, 1);
-	*/
-	ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
-				     src1_len + src2_len + zero_padding);
-	crypto_free_blkcipher(tfm);
-	if (ret < 0)
-		pr_err("ceph_aes_crypt2 failed %d\n", ret);
-	/*
-	print_hex_dump(KERN_ERR, "enc  out: ", DUMP_PREFIX_NONE, 16, 1,
-		       dst, *dst_len, 1);
-	*/
-	return 0;
-}
-
-static int ceph_aes_decrypt(const void *key, int key_len,
-			    void *dst, size_t *dst_len,
-			    const void *src, size_t src_len)
-{
-	struct scatterlist sg_in[1], sg_out[2];
-	struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
-	struct blkcipher_desc desc = { .tfm = tfm };
-	char pad[16];
-	void *iv;
-	int ivsize;
-	int ret;
-	int last_byte;
-
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
-
-	crypto_blkcipher_setkey((void *)tfm, key, key_len);
-	sg_init_table(sg_in, 1);
-	sg_init_table(sg_out, 2);
-	sg_set_buf(sg_in, src, src_len);
-	sg_set_buf(&sg_out[0], dst, *dst_len);
-	sg_set_buf(&sg_out[1], pad, sizeof(pad));
-
-	iv = crypto_blkcipher_crt(tfm)->iv;
-	ivsize = crypto_blkcipher_ivsize(tfm);
-
-	memcpy(iv, aes_iv, ivsize);
-
-	/*
-	print_hex_dump(KERN_ERR, "dec key: ", DUMP_PREFIX_NONE, 16, 1,
-		       key, key_len, 1);
-	print_hex_dump(KERN_ERR, "dec  in: ", DUMP_PREFIX_NONE, 16, 1,
-		       src, src_len, 1);
-	*/
-
-	ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
-	crypto_free_blkcipher(tfm);
-	if (ret < 0) {
-		pr_err("ceph_aes_decrypt failed %d\n", ret);
-		return ret;
-	}
-
-	if (src_len <= *dst_len)
-		last_byte = ((char *)dst)[src_len - 1];
-	else
-		last_byte = pad[src_len - *dst_len - 1];
-	if (last_byte <= 16 && src_len >= last_byte) {
-		*dst_len = src_len - last_byte;
-	} else {
-		pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n",
-		       last_byte, (int)src_len);
-		return -EPERM;  /* bad padding */
-	}
-	/*
-	print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1,
-		       dst, *dst_len, 1);
-	*/
-	return 0;
-}
-
-static int ceph_aes_decrypt2(const void *key, int key_len,
-			     void *dst1, size_t *dst1_len,
-			     void *dst2, size_t *dst2_len,
-			     const void *src, size_t src_len)
-{
-	struct scatterlist sg_in[1], sg_out[3];
-	struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
-	struct blkcipher_desc desc = { .tfm = tfm };
-	char pad[16];
-	void *iv;
-	int ivsize;
-	int ret;
-	int last_byte;
-
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
-
-	sg_init_table(sg_in, 1);
-	sg_set_buf(sg_in, src, src_len);
-	sg_init_table(sg_out, 3);
-	sg_set_buf(&sg_out[0], dst1, *dst1_len);
-	sg_set_buf(&sg_out[1], dst2, *dst2_len);
-	sg_set_buf(&sg_out[2], pad, sizeof(pad));
-
-	crypto_blkcipher_setkey((void *)tfm, key, key_len);
-	iv = crypto_blkcipher_crt(tfm)->iv;
-	ivsize = crypto_blkcipher_ivsize(tfm);
-
-	memcpy(iv, aes_iv, ivsize);
-
-	/*
-	print_hex_dump(KERN_ERR, "dec  key: ", DUMP_PREFIX_NONE, 16, 1,
-		       key, key_len, 1);
-	print_hex_dump(KERN_ERR, "dec   in: ", DUMP_PREFIX_NONE, 16, 1,
-		       src, src_len, 1);
-	*/
-
-	ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
-	crypto_free_blkcipher(tfm);
-	if (ret < 0) {
-		pr_err("ceph_aes_decrypt failed %d\n", ret);
-		return ret;
-	}
-
-	if (src_len <= *dst1_len)
-		last_byte = ((char *)dst1)[src_len - 1];
-	else if (src_len <= *dst1_len + *dst2_len)
-		last_byte = ((char *)dst2)[src_len - *dst1_len - 1];
-	else
-		last_byte = pad[src_len - *dst1_len - *dst2_len - 1];
-	if (last_byte <= 16 && src_len >= last_byte) {
-		src_len -= last_byte;
-	} else {
-		pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n",
-		       last_byte, (int)src_len);
-		return -EPERM;  /* bad padding */
-	}
-
-	if (src_len < *dst1_len) {
-		*dst1_len = src_len;
-		*dst2_len = 0;
-	} else {
-		*dst2_len = src_len - *dst1_len;
-	}
-	/*
-	print_hex_dump(KERN_ERR, "dec  out1: ", DUMP_PREFIX_NONE, 16, 1,
-		       dst1, *dst1_len, 1);
-	print_hex_dump(KERN_ERR, "dec  out2: ", DUMP_PREFIX_NONE, 16, 1,
-		       dst2, *dst2_len, 1);
-	*/
-
-	return 0;
-}
-
-
-int ceph_decrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
-		 const void *src, size_t src_len)
-{
-	switch (secret->type) {
-	case CEPH_CRYPTO_NONE:
-		if (*dst_len < src_len)
-			return -ERANGE;
-		memcpy(dst, src, src_len);
-		*dst_len = src_len;
-		return 0;
-
-	case CEPH_CRYPTO_AES:
-		return ceph_aes_decrypt(secret->key, secret->len, dst,
-					dst_len, src, src_len);
-
-	default:
-		return -EINVAL;
-	}
-}
-
-int ceph_decrypt2(struct ceph_crypto_key *secret,
-			void *dst1, size_t *dst1_len,
-			void *dst2, size_t *dst2_len,
-			const void *src, size_t src_len)
-{
-	size_t t;
-
-	switch (secret->type) {
-	case CEPH_CRYPTO_NONE:
-		if (*dst1_len + *dst2_len < src_len)
-			return -ERANGE;
-		t = min(*dst1_len, src_len);
-		memcpy(dst1, src, t);
-		*dst1_len = t;
-		src += t;
-		src_len -= t;
-		if (src_len) {
-			t = min(*dst2_len, src_len);
-			memcpy(dst2, src, t);
-			*dst2_len = t;
-		}
-		return 0;
-
-	case CEPH_CRYPTO_AES:
-		return ceph_aes_decrypt2(secret->key, secret->len,
-					 dst1, dst1_len, dst2, dst2_len,
-					 src, src_len);
-
-	default:
-		return -EINVAL;
-	}
-}
-
-int ceph_encrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
-		 const void *src, size_t src_len)
-{
-	switch (secret->type) {
-	case CEPH_CRYPTO_NONE:
-		if (*dst_len < src_len)
-			return -ERANGE;
-		memcpy(dst, src, src_len);
-		*dst_len = src_len;
-		return 0;
-
-	case CEPH_CRYPTO_AES:
-		return ceph_aes_encrypt(secret->key, secret->len, dst,
-					dst_len, src, src_len);
-
-	default:
-		return -EINVAL;
-	}
-}
-
-int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
-		  const void *src1, size_t src1_len,
-		  const void *src2, size_t src2_len)
-{
-	switch (secret->type) {
-	case CEPH_CRYPTO_NONE:
-		if (*dst_len < src1_len + src2_len)
-			return -ERANGE;
-		memcpy(dst, src1, src1_len);
-		memcpy(dst + src1_len, src2, src2_len);
-		*dst_len = src1_len + src2_len;
-		return 0;
-
-	case CEPH_CRYPTO_AES:
-		return ceph_aes_encrypt2(secret->key, secret->len, dst, dst_len,
-					 src1, src1_len, src2, src2_len);
-
-	default:
-		return -EINVAL;
-	}
-}
diff --git a/fs/ceph/crypto.h b/fs/ceph/crypto.h
deleted file mode 100644
index bdf3860..0000000
--- a/fs/ceph/crypto.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef _FS_CEPH_CRYPTO_H
-#define _FS_CEPH_CRYPTO_H
-
-#include "types.h"
-#include "buffer.h"
-
-/*
- * cryptographic secret
- */
-struct ceph_crypto_key {
-	int type;
-	struct ceph_timespec created;
-	int len;
-	void *key;
-};
-
-static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
-{
-	kfree(key->key);
-}
-
-extern int ceph_crypto_key_encode(struct ceph_crypto_key *key,
-				  void **p, void *end);
-extern int ceph_crypto_key_decode(struct ceph_crypto_key *key,
-				  void **p, void *end);
-extern int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *in);
-
-/* crypto.c */
-extern int ceph_decrypt(struct ceph_crypto_key *secret,
-			void *dst, size_t *dst_len,
-			const void *src, size_t src_len);
-extern int ceph_encrypt(struct ceph_crypto_key *secret,
-			void *dst, size_t *dst_len,
-			const void *src, size_t src_len);
-extern int ceph_decrypt2(struct ceph_crypto_key *secret,
-			void *dst1, size_t *dst1_len,
-			void *dst2, size_t *dst2_len,
-			const void *src, size_t src_len);
-extern int ceph_encrypt2(struct ceph_crypto_key *secret,
-			 void *dst, size_t *dst_len,
-			 const void *src1, size_t src1_len,
-			 const void *src2, size_t src2_len);
-
-/* armor.c */
-extern int ceph_armor(char *dst, const char *src, const char *end);
-extern int ceph_unarmor(char *dst, const char *src, const char *end);
-
-#endif
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c
index 6fd8b20..7ae1b3d 100644
--- a/fs/ceph/debugfs.c
+++ b/fs/ceph/debugfs.c
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/device.h>
 #include <linux/slab.h>
@@ -7,143 +7,49 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/auth.h>
+#include <linux/ceph/debugfs.h>
+
 #include "super.h"
-#include "mds_client.h"
-#include "mon_client.h"
-#include "auth.h"
 
 #ifdef CONFIG_DEBUG_FS
 
-/*
- * Implement /sys/kernel/debug/ceph fun
- *
- * /sys/kernel/debug/ceph/client*  - an instance of the ceph client
- *      .../osdmap      - current osdmap
- *      .../mdsmap      - current mdsmap
- *      .../monmap      - current monmap
- *      .../osdc        - active osd requests
- *      .../mdsc        - active mds requests
- *      .../monc        - mon client state
- *      .../dentry_lru  - dump contents of dentry lru
- *      .../caps        - expose cap (reservation) stats
- *      .../bdi         - symlink to ../../bdi/something
- */
-
-static struct dentry *ceph_debugfs_dir;
-
-static int monmap_show(struct seq_file *s, void *p)
-{
-	int i;
-	struct ceph_client *client = s->private;
-
-	if (client->monc.monmap == NULL)
-		return 0;
-
-	seq_printf(s, "epoch %d\n", client->monc.monmap->epoch);
-	for (i = 0; i < client->monc.monmap->num_mon; i++) {
-		struct ceph_entity_inst *inst =
-			&client->monc.monmap->mon_inst[i];
-
-		seq_printf(s, "\t%s%lld\t%s\n",
-			   ENTITY_NAME(inst->name),
-			   pr_addr(&inst->addr.in_addr));
-	}
-	return 0;
-}
+#include "mds_client.h"
 
 static int mdsmap_show(struct seq_file *s, void *p)
 {
 	int i;
-	struct ceph_client *client = s->private;
+	struct ceph_fs_client *fsc = s->private;
 
-	if (client->mdsc.mdsmap == NULL)
+	if (fsc->mdsc == NULL || fsc->mdsc->mdsmap == NULL)
 		return 0;
-	seq_printf(s, "epoch %d\n", client->mdsc.mdsmap->m_epoch);
-	seq_printf(s, "root %d\n", client->mdsc.mdsmap->m_root);
+	seq_printf(s, "epoch %d\n", fsc->mdsc->mdsmap->m_epoch);
+	seq_printf(s, "root %d\n", fsc->mdsc->mdsmap->m_root);
 	seq_printf(s, "session_timeout %d\n",
-		       client->mdsc.mdsmap->m_session_timeout);
+		       fsc->mdsc->mdsmap->m_session_timeout);
 	seq_printf(s, "session_autoclose %d\n",
-		       client->mdsc.mdsmap->m_session_autoclose);
-	for (i = 0; i < client->mdsc.mdsmap->m_max_mds; i++) {
+		       fsc->mdsc->mdsmap->m_session_autoclose);
+	for (i = 0; i < fsc->mdsc->mdsmap->m_max_mds; i++) {
 		struct ceph_entity_addr *addr =
-			&client->mdsc.mdsmap->m_info[i].addr;
-		int state = client->mdsc.mdsmap->m_info[i].state;
+			&fsc->mdsc->mdsmap->m_info[i].addr;
+		int state = fsc->mdsc->mdsmap->m_info[i].state;
 
-		seq_printf(s, "\tmds%d\t%s\t(%s)\n", i, pr_addr(&addr->in_addr),
+		seq_printf(s, "\tmds%d\t%s\t(%s)\n", i,
+			       ceph_pr_addr(&addr->in_addr),
 			       ceph_mds_state_name(state));
 	}
 	return 0;
 }
 
-static int osdmap_show(struct seq_file *s, void *p)
-{
-	int i;
-	struct ceph_client *client = s->private;
-	struct rb_node *n;
-
-	if (client->osdc.osdmap == NULL)
-		return 0;
-	seq_printf(s, "epoch %d\n", client->osdc.osdmap->epoch);
-	seq_printf(s, "flags%s%s\n",
-		   (client->osdc.osdmap->flags & CEPH_OSDMAP_NEARFULL) ?
-		   " NEARFULL" : "",
-		   (client->osdc.osdmap->flags & CEPH_OSDMAP_FULL) ?
-		   " FULL" : "");
-	for (n = rb_first(&client->osdc.osdmap->pg_pools); n; n = rb_next(n)) {
-		struct ceph_pg_pool_info *pool =
-			rb_entry(n, struct ceph_pg_pool_info, node);
-		seq_printf(s, "pg_pool %d pg_num %d / %d, lpg_num %d / %d\n",
-			   pool->id, pool->v.pg_num, pool->pg_num_mask,
-			   pool->v.lpg_num, pool->lpg_num_mask);
-	}
-	for (i = 0; i < client->osdc.osdmap->max_osd; i++) {
-		struct ceph_entity_addr *addr =
-			&client->osdc.osdmap->osd_addr[i];
-		int state = client->osdc.osdmap->osd_state[i];
-		char sb[64];
-
-		seq_printf(s, "\tosd%d\t%s\t%3d%%\t(%s)\n",
-			   i, pr_addr(&addr->in_addr),
-			   ((client->osdc.osdmap->osd_weight[i]*100) >> 16),
-			   ceph_osdmap_state_str(sb, sizeof(sb), state));
-	}
-	return 0;
-}
-
-static int monc_show(struct seq_file *s, void *p)
-{
-	struct ceph_client *client = s->private;
-	struct ceph_mon_generic_request *req;
-	struct ceph_mon_client *monc = &client->monc;
-	struct rb_node *rp;
-
-	mutex_lock(&monc->mutex);
-
-	if (monc->have_mdsmap)
-		seq_printf(s, "have mdsmap %u\n", (unsigned)monc->have_mdsmap);
-	if (monc->have_osdmap)
-		seq_printf(s, "have osdmap %u\n", (unsigned)monc->have_osdmap);
-	if (monc->want_next_osdmap)
-		seq_printf(s, "want next osdmap\n");
-
-	for (rp = rb_first(&monc->generic_request_tree); rp; rp = rb_next(rp)) {
-		__u16 op;
-		req = rb_entry(rp, struct ceph_mon_generic_request, node);
-		op = le16_to_cpu(req->request->hdr.type);
-		if (op == CEPH_MSG_STATFS)
-			seq_printf(s, "%lld statfs\n", req->tid);
-		else
-			seq_printf(s, "%lld unknown\n", req->tid);
-	}
-
-	mutex_unlock(&monc->mutex);
-	return 0;
-}
-
+/*
+ * mdsc debugfs
+ */
 static int mdsc_show(struct seq_file *s, void *p)
 {
-	struct ceph_client *client = s->private;
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = s->private;
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req;
 	struct rb_node *rp;
 	int pathlen;
@@ -214,61 +120,12 @@
 	return 0;
 }
 
-static int osdc_show(struct seq_file *s, void *pp)
-{
-	struct ceph_client *client = s->private;
-	struct ceph_osd_client *osdc = &client->osdc;
-	struct rb_node *p;
-
-	mutex_lock(&osdc->request_mutex);
-	for (p = rb_first(&osdc->requests); p; p = rb_next(p)) {
-		struct ceph_osd_request *req;
-		struct ceph_osd_request_head *head;
-		struct ceph_osd_op *op;
-		int num_ops;
-		int opcode, olen;
-		int i;
-
-		req = rb_entry(p, struct ceph_osd_request, r_node);
-
-		seq_printf(s, "%lld\tosd%d\t%d.%x\t", req->r_tid,
-			   req->r_osd ? req->r_osd->o_osd : -1,
-			   le32_to_cpu(req->r_pgid.pool),
-			   le16_to_cpu(req->r_pgid.ps));
-
-		head = req->r_request->front.iov_base;
-		op = (void *)(head + 1);
-
-		num_ops = le16_to_cpu(head->num_ops);
-		olen = le32_to_cpu(head->object_len);
-		seq_printf(s, "%.*s", olen,
-			   (const char *)(head->ops + num_ops));
-
-		if (req->r_reassert_version.epoch)
-			seq_printf(s, "\t%u'%llu",
-			   (unsigned)le32_to_cpu(req->r_reassert_version.epoch),
-			   le64_to_cpu(req->r_reassert_version.version));
-		else
-			seq_printf(s, "\t");
-
-		for (i = 0; i < num_ops; i++) {
-			opcode = le16_to_cpu(op->op);
-			seq_printf(s, "\t%s", ceph_osd_op_name(opcode));
-			op++;
-		}
-
-		seq_printf(s, "\n");
-	}
-	mutex_unlock(&osdc->request_mutex);
-	return 0;
-}
-
 static int caps_show(struct seq_file *s, void *p)
 {
-	struct ceph_client *client = s->private;
+	struct ceph_fs_client *fsc = s->private;
 	int total, avail, used, reserved, min;
 
-	ceph_reservation_status(client, &total, &avail, &used, &reserved, &min);
+	ceph_reservation_status(fsc, &total, &avail, &used, &reserved, &min);
 	seq_printf(s, "total\t\t%d\n"
 		   "avail\t\t%d\n"
 		   "used\t\t%d\n"
@@ -280,8 +137,8 @@
 
 static int dentry_lru_show(struct seq_file *s, void *ptr)
 {
-	struct ceph_client *client = s->private;
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = s->private;
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_dentry_info *di;
 
 	spin_lock(&mdsc->dentry_lru_lock);
@@ -295,199 +152,124 @@
 	return 0;
 }
 
-#define DEFINE_SHOW_FUNC(name)						\
-static int name##_open(struct inode *inode, struct file *file)		\
-{									\
-	struct seq_file *sf;						\
-	int ret;							\
-									\
-	ret = single_open(file, name, NULL);				\
-	sf = file->private_data;					\
-	sf->private = inode->i_private;					\
-	return ret;							\
-}									\
-									\
-static const struct file_operations name##_fops = {			\
-	.open		= name##_open,					\
-	.read		= seq_read,					\
-	.llseek		= seq_lseek,					\
-	.release	= single_release,				\
-};
+CEPH_DEFINE_SHOW_FUNC(mdsmap_show)
+CEPH_DEFINE_SHOW_FUNC(mdsc_show)
+CEPH_DEFINE_SHOW_FUNC(caps_show)
+CEPH_DEFINE_SHOW_FUNC(dentry_lru_show)
 
-DEFINE_SHOW_FUNC(monmap_show)
-DEFINE_SHOW_FUNC(mdsmap_show)
-DEFINE_SHOW_FUNC(osdmap_show)
-DEFINE_SHOW_FUNC(monc_show)
-DEFINE_SHOW_FUNC(mdsc_show)
-DEFINE_SHOW_FUNC(osdc_show)
-DEFINE_SHOW_FUNC(dentry_lru_show)
-DEFINE_SHOW_FUNC(caps_show)
 
+/*
+ * debugfs
+ */
 static int congestion_kb_set(void *data, u64 val)
 {
-	struct ceph_client *client = (struct ceph_client *)data;
+	struct ceph_fs_client *fsc = (struct ceph_fs_client *)data;
 
-	if (client)
-		client->mount_args->congestion_kb = (int)val;
-
+	fsc->mount_options->congestion_kb = (int)val;
 	return 0;
 }
 
 static int congestion_kb_get(void *data, u64 *val)
 {
-	struct ceph_client *client = (struct ceph_client *)data;
+	struct ceph_fs_client *fsc = (struct ceph_fs_client *)data;
 
-	if (client)
-		*val = (u64)client->mount_args->congestion_kb;
-
+	*val = (u64)fsc->mount_options->congestion_kb;
 	return 0;
 }
 
-
 DEFINE_SIMPLE_ATTRIBUTE(congestion_kb_fops, congestion_kb_get,
 			congestion_kb_set, "%llu\n");
 
-int __init ceph_debugfs_init(void)
+
+void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
 {
-	ceph_debugfs_dir = debugfs_create_dir("ceph", NULL);
-	if (!ceph_debugfs_dir)
-		return -ENOMEM;
-	return 0;
+	dout("ceph_fs_debugfs_cleanup\n");
+	debugfs_remove(fsc->debugfs_bdi);
+	debugfs_remove(fsc->debugfs_congestion_kb);
+	debugfs_remove(fsc->debugfs_mdsmap);
+	debugfs_remove(fsc->debugfs_caps);
+	debugfs_remove(fsc->debugfs_mdsc);
+	debugfs_remove(fsc->debugfs_dentry_lru);
 }
 
-void ceph_debugfs_cleanup(void)
+int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 {
-	debugfs_remove(ceph_debugfs_dir);
-}
+	char name[100];
+	int err = -ENOMEM;
 
-int ceph_debugfs_client_init(struct ceph_client *client)
-{
-	int ret = 0;
-	char name[80];
-
-	snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid,
-		 client->monc.auth->global_id);
-
-	client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir);
-	if (!client->debugfs_dir)
-		goto out;
-
-	client->monc.debugfs_file = debugfs_create_file("monc",
-						      0600,
-						      client->debugfs_dir,
-						      client,
-						      &monc_show_fops);
-	if (!client->monc.debugfs_file)
-		goto out;
-
-	client->mdsc.debugfs_file = debugfs_create_file("mdsc",
-						      0600,
-						      client->debugfs_dir,
-						      client,
-						      &mdsc_show_fops);
-	if (!client->mdsc.debugfs_file)
-		goto out;
-
-	client->osdc.debugfs_file = debugfs_create_file("osdc",
-						      0600,
-						      client->debugfs_dir,
-						      client,
-						      &osdc_show_fops);
-	if (!client->osdc.debugfs_file)
-		goto out;
-
-	client->debugfs_monmap = debugfs_create_file("monmap",
-					0600,
-					client->debugfs_dir,
-					client,
-					&monmap_show_fops);
-	if (!client->debugfs_monmap)
-		goto out;
-
-	client->debugfs_mdsmap = debugfs_create_file("mdsmap",
-					0600,
-					client->debugfs_dir,
-					client,
-					&mdsmap_show_fops);
-	if (!client->debugfs_mdsmap)
-		goto out;
-
-	client->debugfs_osdmap = debugfs_create_file("osdmap",
-					0600,
-					client->debugfs_dir,
-					client,
-					&osdmap_show_fops);
-	if (!client->debugfs_osdmap)
-		goto out;
-
-	client->debugfs_dentry_lru = debugfs_create_file("dentry_lru",
-					0600,
-					client->debugfs_dir,
-					client,
-					&dentry_lru_show_fops);
-	if (!client->debugfs_dentry_lru)
-		goto out;
-
-	client->debugfs_caps = debugfs_create_file("caps",
-						   0400,
-						   client->debugfs_dir,
-						   client,
-						   &caps_show_fops);
-	if (!client->debugfs_caps)
-		goto out;
-
-	client->debugfs_congestion_kb =
+	dout("ceph_fs_debugfs_init\n");
+	fsc->debugfs_congestion_kb =
 		debugfs_create_file("writeback_congestion_kb",
 				    0600,
-				    client->debugfs_dir,
-				    client,
+				    fsc->client->debugfs_dir,
+				    fsc,
 				    &congestion_kb_fops);
-	if (!client->debugfs_congestion_kb)
+	if (!fsc->debugfs_congestion_kb)
 		goto out;
 
-	sprintf(name, "../../bdi/%s", dev_name(client->sb->s_bdi->dev));
-	client->debugfs_bdi = debugfs_create_symlink("bdi", client->debugfs_dir,
-						     name);
+	dout("a\n");
+
+	snprintf(name, sizeof(name), "../../bdi/%s",
+		 dev_name(fsc->backing_dev_info.dev));
+	fsc->debugfs_bdi =
+		debugfs_create_symlink("bdi",
+				       fsc->client->debugfs_dir,
+				       name);
+	if (!fsc->debugfs_bdi)
+		goto out;
+
+	dout("b\n");
+	fsc->debugfs_mdsmap = debugfs_create_file("mdsmap",
+					0600,
+					fsc->client->debugfs_dir,
+					fsc,
+					&mdsmap_show_fops);
+	if (!fsc->debugfs_mdsmap)
+		goto out;
+
+	dout("ca\n");
+	fsc->debugfs_mdsc = debugfs_create_file("mdsc",
+						0600,
+						fsc->client->debugfs_dir,
+						fsc,
+						&mdsc_show_fops);
+	if (!fsc->debugfs_mdsc)
+		goto out;
+
+	dout("da\n");
+	fsc->debugfs_caps = debugfs_create_file("caps",
+						   0400,
+						   fsc->client->debugfs_dir,
+						   fsc,
+						   &caps_show_fops);
+	if (!fsc->debugfs_caps)
+		goto out;
+
+	dout("ea\n");
+	fsc->debugfs_dentry_lru = debugfs_create_file("dentry_lru",
+					0600,
+					fsc->client->debugfs_dir,
+					fsc,
+					&dentry_lru_show_fops);
+	if (!fsc->debugfs_dentry_lru)
+		goto out;
 
 	return 0;
 
 out:
-	ceph_debugfs_client_cleanup(client);
-	return ret;
+	ceph_fs_debugfs_cleanup(fsc);
+	return err;
 }
 
-void ceph_debugfs_client_cleanup(struct ceph_client *client)
-{
-	debugfs_remove(client->debugfs_bdi);
-	debugfs_remove(client->debugfs_caps);
-	debugfs_remove(client->debugfs_dentry_lru);
-	debugfs_remove(client->debugfs_osdmap);
-	debugfs_remove(client->debugfs_mdsmap);
-	debugfs_remove(client->debugfs_monmap);
-	debugfs_remove(client->osdc.debugfs_file);
-	debugfs_remove(client->mdsc.debugfs_file);
-	debugfs_remove(client->monc.debugfs_file);
-	debugfs_remove(client->debugfs_congestion_kb);
-	debugfs_remove(client->debugfs_dir);
-}
 
 #else  /* CONFIG_DEBUG_FS */
 
-int __init ceph_debugfs_init(void)
+int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 {
 	return 0;
 }
 
-void ceph_debugfs_cleanup(void)
-{
-}
-
-int ceph_debugfs_client_init(struct ceph_client *client)
-{
-	return 0;
-}
-
-void ceph_debugfs_client_cleanup(struct ceph_client *client)
+void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
 {
 }
 
diff --git a/fs/ceph/decode.h b/fs/ceph/decode.h
deleted file mode 100644
index 3d25415..0000000
--- a/fs/ceph/decode.h
+++ /dev/null
@@ -1,196 +0,0 @@
-#ifndef __CEPH_DECODE_H
-#define __CEPH_DECODE_H
-
-#include <asm/unaligned.h>
-#include <linux/time.h>
-
-#include "types.h"
-
-/*
- * in all cases,
- *   void **p     pointer to position pointer
- *   void *end    pointer to end of buffer (last byte + 1)
- */
-
-static inline u64 ceph_decode_64(void **p)
-{
-	u64 v = get_unaligned_le64(*p);
-	*p += sizeof(u64);
-	return v;
-}
-static inline u32 ceph_decode_32(void **p)
-{
-	u32 v = get_unaligned_le32(*p);
-	*p += sizeof(u32);
-	return v;
-}
-static inline u16 ceph_decode_16(void **p)
-{
-	u16 v = get_unaligned_le16(*p);
-	*p += sizeof(u16);
-	return v;
-}
-static inline u8 ceph_decode_8(void **p)
-{
-	u8 v = *(u8 *)*p;
-	(*p)++;
-	return v;
-}
-static inline void ceph_decode_copy(void **p, void *pv, size_t n)
-{
-	memcpy(pv, *p, n);
-	*p += n;
-}
-
-/*
- * bounds check input.
- */
-#define ceph_decode_need(p, end, n, bad)		\
-	do {						\
-		if (unlikely(*(p) + (n) > (end))) 	\
-			goto bad;			\
-	} while (0)
-
-#define ceph_decode_64_safe(p, end, v, bad)			\
-	do {							\
-		ceph_decode_need(p, end, sizeof(u64), bad);	\
-		v = ceph_decode_64(p);				\
-	} while (0)
-#define ceph_decode_32_safe(p, end, v, bad)			\
-	do {							\
-		ceph_decode_need(p, end, sizeof(u32), bad);	\
-		v = ceph_decode_32(p);				\
-	} while (0)
-#define ceph_decode_16_safe(p, end, v, bad)			\
-	do {							\
-		ceph_decode_need(p, end, sizeof(u16), bad);	\
-		v = ceph_decode_16(p);				\
-	} while (0)
-#define ceph_decode_8_safe(p, end, v, bad)			\
-	do {							\
-		ceph_decode_need(p, end, sizeof(u8), bad);	\
-		v = ceph_decode_8(p);				\
-	} while (0)
-
-#define ceph_decode_copy_safe(p, end, pv, n, bad)		\
-	do {							\
-		ceph_decode_need(p, end, n, bad);		\
-		ceph_decode_copy(p, pv, n);			\
-	} while (0)
-
-/*
- * struct ceph_timespec <-> struct timespec
- */
-static inline void ceph_decode_timespec(struct timespec *ts,
-					const struct ceph_timespec *tv)
-{
-	ts->tv_sec = le32_to_cpu(tv->tv_sec);
-	ts->tv_nsec = le32_to_cpu(tv->tv_nsec);
-}
-static inline void ceph_encode_timespec(struct ceph_timespec *tv,
-					const struct timespec *ts)
-{
-	tv->tv_sec = cpu_to_le32(ts->tv_sec);
-	tv->tv_nsec = cpu_to_le32(ts->tv_nsec);
-}
-
-/*
- * sockaddr_storage <-> ceph_sockaddr
- */
-static inline void ceph_encode_addr(struct ceph_entity_addr *a)
-{
-	__be16 ss_family = htons(a->in_addr.ss_family);
-	a->in_addr.ss_family = *(__u16 *)&ss_family;
-}
-static inline void ceph_decode_addr(struct ceph_entity_addr *a)
-{
-	__be16 ss_family = *(__be16 *)&a->in_addr.ss_family;
-	a->in_addr.ss_family = ntohs(ss_family);
-	WARN_ON(a->in_addr.ss_family == 512);
-}
-
-/*
- * encoders
- */
-static inline void ceph_encode_64(void **p, u64 v)
-{
-	put_unaligned_le64(v, (__le64 *)*p);
-	*p += sizeof(u64);
-}
-static inline void ceph_encode_32(void **p, u32 v)
-{
-	put_unaligned_le32(v, (__le32 *)*p);
-	*p += sizeof(u32);
-}
-static inline void ceph_encode_16(void **p, u16 v)
-{
-	put_unaligned_le16(v, (__le16 *)*p);
-	*p += sizeof(u16);
-}
-static inline void ceph_encode_8(void **p, u8 v)
-{
-	*(u8 *)*p = v;
-	(*p)++;
-}
-static inline void ceph_encode_copy(void **p, const void *s, int len)
-{
-	memcpy(*p, s, len);
-	*p += len;
-}
-
-/*
- * filepath, string encoders
- */
-static inline void ceph_encode_filepath(void **p, void *end,
-					u64 ino, const char *path)
-{
-	u32 len = path ? strlen(path) : 0;
-	BUG_ON(*p + sizeof(ino) + sizeof(len) + len > end);
-	ceph_encode_8(p, 1);
-	ceph_encode_64(p, ino);
-	ceph_encode_32(p, len);
-	if (len)
-		memcpy(*p, path, len);
-	*p += len;
-}
-
-static inline void ceph_encode_string(void **p, void *end,
-				      const char *s, u32 len)
-{
-	BUG_ON(*p + sizeof(len) + len > end);
-	ceph_encode_32(p, len);
-	if (len)
-		memcpy(*p, s, len);
-	*p += len;
-}
-
-#define ceph_encode_need(p, end, n, bad)		\
-	do {						\
-		if (unlikely(*(p) + (n) > (end))) 	\
-			goto bad;			\
-	} while (0)
-
-#define ceph_encode_64_safe(p, end, v, bad)			\
-	do {							\
-		ceph_encode_need(p, end, sizeof(u64), bad);	\
-		ceph_encode_64(p, v);				\
-	} while (0)
-#define ceph_encode_32_safe(p, end, v, bad)			\
-	do {							\
-		ceph_encode_need(p, end, sizeof(u32), bad);	\
-		ceph_encode_32(p, v);			\
-	} while (0)
-#define ceph_encode_16_safe(p, end, v, bad)			\
-	do {							\
-		ceph_encode_need(p, end, sizeof(u16), bad);	\
-		ceph_encode_16(p, v);			\
-	} while (0)
-
-#define ceph_encode_copy_safe(p, end, pv, n, bad)		\
-	do {							\
-		ceph_encode_need(p, end, n, bad);		\
-		ceph_encode_copy(p, pv, n);			\
-	} while (0)
-
-
-#endif
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index a1986eb..e0a2dc6 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/spinlock.h>
 #include <linux/fs_struct.h>
@@ -7,6 +7,7 @@
 #include <linux/sched.h>
 
 #include "super.h"
+#include "mds_client.h"
 
 /*
  * Directory operations: readdir, lookup, create, link, unlink,
@@ -94,10 +95,7 @@
  */
 static int __dcache_readdir(struct file *filp,
 			    void *dirent, filldir_t filldir)
-		__releases(inode->i_lock)
-		__acquires(inode->i_lock)
 {
-	struct inode *inode = filp->f_dentry->d_inode;
 	struct ceph_file_info *fi = filp->private_data;
 	struct dentry *parent = filp->f_dentry;
 	struct inode *dir = parent->d_inode;
@@ -153,7 +151,6 @@
 
 	atomic_inc(&dentry->d_count);
 	spin_unlock(&dcache_lock);
-	spin_unlock(&inode->i_lock);
 
 	dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos,
 	     dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
@@ -171,35 +168,30 @@
 		} else {
 			dput(last);
 		}
-		last = NULL;
 	}
-
-	spin_lock(&inode->i_lock);
-	spin_lock(&dcache_lock);
-
 	last = dentry;
 
 	if (err < 0)
-		goto out_unlock;
+		goto out;
 
-	p = p->prev;
 	filp->f_pos++;
 
 	/* make sure a dentry wasn't dropped while we didn't have dcache_lock */
-	if ((ceph_inode(dir)->i_ceph_flags & CEPH_I_COMPLETE))
-		goto more;
-	dout(" lost I_COMPLETE on %p; falling back to mds\n", dir);
-	err = -EAGAIN;
+	if (!ceph_i_test(dir, CEPH_I_COMPLETE)) {
+		dout(" lost I_COMPLETE on %p; falling back to mds\n", dir);
+		err = -EAGAIN;
+		goto out;
+	}
+
+	spin_lock(&dcache_lock);
+	p = p->prev;	/* advance to next dentry */
+	goto more;
 
 out_unlock:
 	spin_unlock(&dcache_lock);
-
-	if (last) {
-		spin_unlock(&inode->i_lock);
+out:
+	if (last)
 		dput(last);
-		spin_lock(&inode->i_lock);
-	}
-
 	return err;
 }
 
@@ -227,15 +219,15 @@
 	struct ceph_file_info *fi = filp->private_data;
 	struct inode *inode = filp->f_dentry->d_inode;
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct ceph_client *client = ceph_inode_to_client(inode);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	unsigned frag = fpos_frag(filp->f_pos);
 	int off = fpos_off(filp->f_pos);
 	int err;
 	u32 ftype;
 	struct ceph_mds_reply_info_parsed *rinfo;
-	const int max_entries = client->mount_args->max_readdir;
-	const int max_bytes = client->mount_args->max_readdir_bytes;
+	const int max_entries = fsc->mount_options->max_readdir;
+	const int max_bytes = fsc->mount_options->max_readdir_bytes;
 
 	dout("readdir %p filp %p frag %u off %u\n", inode, filp, frag, off);
 	if (fi->at_end)
@@ -267,17 +259,17 @@
 	/* can we use the dcache? */
 	spin_lock(&inode->i_lock);
 	if ((filp->f_pos == 2 || fi->dentry) &&
-	    !ceph_test_opt(client, NOASYNCREADDIR) &&
+	    !ceph_test_mount_opt(fsc, NOASYNCREADDIR) &&
 	    ceph_snap(inode) != CEPH_SNAPDIR &&
 	    (ci->i_ceph_flags & CEPH_I_COMPLETE) &&
 	    __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) {
+		spin_unlock(&inode->i_lock);
 		err = __dcache_readdir(filp, dirent, filldir);
-		if (err != -EAGAIN) {
-			spin_unlock(&inode->i_lock);
+		if (err != -EAGAIN)
 			return err;
-		}
+	} else {
+		spin_unlock(&inode->i_lock);
 	}
-	spin_unlock(&inode->i_lock);
 	if (fi->dentry) {
 		err = note_last_dentry(fi, fi->dentry->d_name.name,
 				       fi->dentry->d_name.len);
@@ -487,14 +479,13 @@
 struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
 				  struct dentry *dentry, int err)
 {
-	struct ceph_client *client = ceph_sb_to_client(dentry->d_sb);
+	struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
 	struct inode *parent = dentry->d_parent->d_inode;
 
 	/* .snap dir? */
 	if (err == -ENOENT &&
-	    ceph_vino(parent).ino != CEPH_INO_ROOT && /* no .snap in root dir */
 	    strcmp(dentry->d_name.name,
-		   client->mount_args->snapdir_name) == 0) {
+		   fsc->mount_options->snapdir_name) == 0) {
 		struct inode *inode = ceph_get_snapdir(parent);
 		dout("ENOENT on snapdir %p '%.*s', linking to snapdir %p\n",
 		     dentry, dentry->d_name.len, dentry->d_name.name, inode);
@@ -539,8 +530,8 @@
 static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
 				  struct nameidata *nd)
 {
-	struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req;
 	int op;
 	int err;
@@ -572,7 +563,7 @@
 		spin_lock(&dir->i_lock);
 		dout(" dir %p flags are %d\n", dir, ci->i_ceph_flags);
 		if (strncmp(dentry->d_name.name,
-			    client->mount_args->snapdir_name,
+			    fsc->mount_options->snapdir_name,
 			    dentry->d_name.len) &&
 		    !is_root_ceph_dentry(dir, dentry) &&
 		    (ci->i_ceph_flags & CEPH_I_COMPLETE) &&
@@ -629,8 +620,8 @@
 static int ceph_mknod(struct inode *dir, struct dentry *dentry,
 		      int mode, dev_t rdev)
 {
-	struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req;
 	int err;
 
@@ -685,8 +676,8 @@
 static int ceph_symlink(struct inode *dir, struct dentry *dentry,
 			    const char *dest)
 {
-	struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req;
 	int err;
 
@@ -716,8 +707,8 @@
 
 static int ceph_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-	struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req;
 	int err = -EROFS;
 	int op;
@@ -758,8 +749,8 @@
 static int ceph_link(struct dentry *old_dentry, struct inode *dir,
 		     struct dentry *dentry)
 {
-	struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req;
 	int err;
 
@@ -813,8 +804,8 @@
  */
 static int ceph_unlink(struct inode *dir, struct dentry *dentry)
 {
-	struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct inode *inode = dentry->d_inode;
 	struct ceph_mds_request *req;
 	int err = -EROFS;
@@ -854,8 +845,8 @@
 static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
 		       struct inode *new_dir, struct dentry *new_dentry)
 {
-	struct ceph_client *client = ceph_sb_to_client(old_dir->i_sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(old_dir->i_sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req;
 	int err;
 
@@ -1076,7 +1067,7 @@
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	int left;
 
-	if (!ceph_test_opt(ceph_sb_to_client(inode->i_sb), DIRSTAT))
+	if (!ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), DIRSTAT))
 		return -EISDIR;
 
 	if (!cf->dir_info) {
@@ -1177,7 +1168,7 @@
 	dout("dentry_lru_add %p %p '%.*s'\n", di, dn,
 	     dn->d_name.len, dn->d_name.name);
 	if (di) {
-		mdsc = &ceph_sb_to_client(dn->d_sb)->mdsc;
+		mdsc = ceph_sb_to_client(dn->d_sb)->mdsc;
 		spin_lock(&mdsc->dentry_lru_lock);
 		list_add_tail(&di->lru, &mdsc->dentry_lru);
 		mdsc->num_dentry++;
@@ -1193,7 +1184,7 @@
 	dout("dentry_lru_touch %p %p '%.*s' (offset %lld)\n", di, dn,
 	     dn->d_name.len, dn->d_name.name, di->offset);
 	if (di) {
-		mdsc = &ceph_sb_to_client(dn->d_sb)->mdsc;
+		mdsc = ceph_sb_to_client(dn->d_sb)->mdsc;
 		spin_lock(&mdsc->dentry_lru_lock);
 		list_move_tail(&di->lru, &mdsc->dentry_lru);
 		spin_unlock(&mdsc->dentry_lru_lock);
@@ -1208,7 +1199,7 @@
 	dout("dentry_lru_del %p %p '%.*s'\n", di, dn,
 	     dn->d_name.len, dn->d_name.name);
 	if (di) {
-		mdsc = &ceph_sb_to_client(dn->d_sb)->mdsc;
+		mdsc = ceph_sb_to_client(dn->d_sb)->mdsc;
 		spin_lock(&mdsc->dentry_lru_lock);
 		list_del_init(&di->lru);
 		mdsc->num_dentry--;
diff --git a/fs/ceph/export.c b/fs/ceph/export.c
index 4480cb1..2297d94 100644
--- a/fs/ceph/export.c
+++ b/fs/ceph/export.c
@@ -1,10 +1,11 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/exportfs.h>
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
 #include "super.h"
+#include "mds_client.h"
 
 /*
  * NFS export support
@@ -42,32 +43,37 @@
 static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len,
 			  int connectable)
 {
+	int type;
 	struct ceph_nfs_fh *fh = (void *)rawfh;
 	struct ceph_nfs_confh *cfh = (void *)rawfh;
 	struct dentry *parent = dentry->d_parent;
 	struct inode *inode = dentry->d_inode;
-	int type;
+	int connected_handle_length = sizeof(*cfh)/4;
+	int handle_length = sizeof(*fh)/4;
 
 	/* don't re-export snaps */
 	if (ceph_snap(inode) != CEPH_NOSNAP)
 		return -EINVAL;
 
-	if (*max_len >= sizeof(*cfh)) {
+	if (*max_len >= connected_handle_length) {
 		dout("encode_fh %p connectable\n", dentry);
 		cfh->ino = ceph_ino(dentry->d_inode);
 		cfh->parent_ino = ceph_ino(parent->d_inode);
 		cfh->parent_name_hash = parent->d_name.hash;
-		*max_len = sizeof(*cfh);
+		*max_len = connected_handle_length;
 		type = 2;
-	} else if (*max_len > sizeof(*fh)) {
-		if (connectable)
-			return -ENOSPC;
+	} else if (*max_len >= handle_length) {
+		if (connectable) {
+			*max_len = connected_handle_length;
+			return 255;
+		}
 		dout("encode_fh %p\n", dentry);
 		fh->ino = ceph_ino(dentry->d_inode);
-		*max_len = sizeof(*fh);
+		*max_len = handle_length;
 		type = 1;
 	} else {
-		return -ENOSPC;
+		*max_len = handle_length;
+		return 255;
 	}
 	return type;
 }
@@ -115,7 +121,7 @@
 static struct dentry *__cfh_to_dentry(struct super_block *sb,
 				      struct ceph_nfs_confh *cfh)
 {
-	struct ceph_mds_client *mdsc = &ceph_sb_to_client(sb)->mdsc;
+	struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
 	struct inode *inode;
 	struct dentry *dentry;
 	struct ceph_vino vino;
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 8c044a4..e77c28c 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -1,5 +1,6 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/file.h>
@@ -38,8 +39,8 @@
 static struct ceph_mds_request *
 prepare_open_request(struct super_block *sb, int flags, int create_mode)
 {
-	struct ceph_client *client = ceph_sb_to_client(sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req;
 	int want_auth = USE_ANY_MDS;
 	int op = (flags & O_CREAT) ? CEPH_MDS_OP_CREATE : CEPH_MDS_OP_OPEN;
@@ -117,8 +118,8 @@
 int ceph_open(struct inode *inode, struct file *file)
 {
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct ceph_client *client = ceph_sb_to_client(inode->i_sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req;
 	struct ceph_file_info *cf = file->private_data;
 	struct inode *parent_inode = file->f_dentry->d_parent->d_inode;
@@ -216,8 +217,8 @@
 				struct nameidata *nd, int mode,
 				int locked_dir)
 {
-	struct ceph_client *client = ceph_sb_to_client(dir->i_sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct file *file = nd->intent.open.file;
 	struct inode *parent_inode = get_dentry_parent_inode(file->f_dentry);
 	struct ceph_mds_request *req;
@@ -270,163 +271,6 @@
 }
 
 /*
- * build a vector of user pages
- */
-static struct page **get_direct_page_vector(const char __user *data,
-					    int num_pages,
-					    loff_t off, size_t len)
-{
-	struct page **pages;
-	int rc;
-
-	pages = kmalloc(sizeof(*pages) * num_pages, GFP_NOFS);
-	if (!pages)
-		return ERR_PTR(-ENOMEM);
-
-	down_read(&current->mm->mmap_sem);
-	rc = get_user_pages(current, current->mm, (unsigned long)data,
-			    num_pages, 0, 0, pages, NULL);
-	up_read(&current->mm->mmap_sem);
-	if (rc < 0)
-		goto fail;
-	return pages;
-
-fail:
-	kfree(pages);
-	return ERR_PTR(rc);
-}
-
-static void put_page_vector(struct page **pages, int num_pages)
-{
-	int i;
-
-	for (i = 0; i < num_pages; i++)
-		put_page(pages[i]);
-	kfree(pages);
-}
-
-void ceph_release_page_vector(struct page **pages, int num_pages)
-{
-	int i;
-
-	for (i = 0; i < num_pages; i++)
-		__free_pages(pages[i], 0);
-	kfree(pages);
-}
-
-/*
- * allocate a vector new pages
- */
-static struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags)
-{
-	struct page **pages;
-	int i;
-
-	pages = kmalloc(sizeof(*pages) * num_pages, flags);
-	if (!pages)
-		return ERR_PTR(-ENOMEM);
-	for (i = 0; i < num_pages; i++) {
-		pages[i] = __page_cache_alloc(flags);
-		if (pages[i] == NULL) {
-			ceph_release_page_vector(pages, i);
-			return ERR_PTR(-ENOMEM);
-		}
-	}
-	return pages;
-}
-
-/*
- * copy user data into a page vector
- */
-static int copy_user_to_page_vector(struct page **pages,
-				    const char __user *data,
-				    loff_t off, size_t len)
-{
-	int i = 0;
-	int po = off & ~PAGE_CACHE_MASK;
-	int left = len;
-	int l, bad;
-
-	while (left > 0) {
-		l = min_t(int, PAGE_CACHE_SIZE-po, left);
-		bad = copy_from_user(page_address(pages[i]) + po, data, l);
-		if (bad == l)
-			return -EFAULT;
-		data += l - bad;
-		left -= l - bad;
-		po += l - bad;
-		if (po == PAGE_CACHE_SIZE) {
-			po = 0;
-			i++;
-		}
-	}
-	return len;
-}
-
-/*
- * copy user data from a page vector into a user pointer
- */
-static int copy_page_vector_to_user(struct page **pages, char __user *data,
-				    loff_t off, size_t len)
-{
-	int i = 0;
-	int po = off & ~PAGE_CACHE_MASK;
-	int left = len;
-	int l, bad;
-
-	while (left > 0) {
-		l = min_t(int, left, PAGE_CACHE_SIZE-po);
-		bad = copy_to_user(data, page_address(pages[i]) + po, l);
-		if (bad == l)
-			return -EFAULT;
-		data += l - bad;
-		left -= l - bad;
-		if (po) {
-			po += l - bad;
-			if (po == PAGE_CACHE_SIZE)
-				po = 0;
-		}
-		i++;
-	}
-	return len;
-}
-
-/*
- * Zero an extent within a page vector.  Offset is relative to the
- * start of the first page.
- */
-static void zero_page_vector_range(int off, int len, struct page **pages)
-{
-	int i = off >> PAGE_CACHE_SHIFT;
-
-	off &= ~PAGE_CACHE_MASK;
-
-	dout("zero_page_vector_page %u~%u\n", off, len);
-
-	/* leading partial page? */
-	if (off) {
-		int end = min((int)PAGE_CACHE_SIZE, off + len);
-		dout("zeroing %d %p head from %d\n", i, pages[i],
-		     (int)off);
-		zero_user_segment(pages[i], off, end);
-		len -= (end - off);
-		i++;
-	}
-	while (len >= PAGE_CACHE_SIZE) {
-		dout("zeroing %d %p len=%d\n", i, pages[i], len);
-		zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE);
-		len -= PAGE_CACHE_SIZE;
-		i++;
-	}
-	/* trailing partial page? */
-	if (len) {
-		dout("zeroing %d %p tail to %d\n", i, pages[i], (int)len);
-		zero_user_segment(pages[i], 0, len);
-	}
-}
-
-
-/*
  * Read a range of bytes striped over one or more objects.  Iterate over
  * objects we stripe over.  (That's not atomic, but good enough for now.)
  *
@@ -438,7 +282,7 @@
 			struct page **pages, int num_pages,
 			int *checkeof)
 {
-	struct ceph_client *client = ceph_inode_to_client(inode);
+	struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	u64 pos, this_len;
 	int page_off = off & ~PAGE_CACHE_MASK; /* first byte's offset in page */
@@ -459,7 +303,7 @@
 
 more:
 	this_len = left;
-	ret = ceph_osdc_readpages(&client->osdc, ceph_vino(inode),
+	ret = ceph_osdc_readpages(&fsc->client->osdc, ceph_vino(inode),
 				  &ci->i_layout, pos, &this_len,
 				  ci->i_truncate_seq,
 				  ci->i_truncate_size,
@@ -477,8 +321,8 @@
 
 		if (read < pos - off) {
 			dout(" zero gap %llu to %llu\n", off + read, pos);
-			zero_page_vector_range(page_off + read,
-					       pos - off - read, pages);
+			ceph_zero_page_vector_range(page_off + read,
+						    pos - off - read, pages);
 		}
 		pos += ret;
 		read = pos - off;
@@ -495,8 +339,8 @@
 		/* was original extent fully inside i_size? */
 		if (pos + left <= inode->i_size) {
 			dout("zero tail\n");
-			zero_page_vector_range(page_off + read, len - read,
-					       pages);
+			ceph_zero_page_vector_range(page_off + read, len - read,
+						    pages);
 			read = len;
 			goto out;
 		}
@@ -531,7 +375,7 @@
 	     (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
 
 	if (file->f_flags & O_DIRECT) {
-		pages = get_direct_page_vector(data, num_pages, off, len);
+		pages = ceph_get_direct_page_vector(data, num_pages, off, len);
 
 		/*
 		 * flush any page cache pages in this range.  this
@@ -552,13 +396,13 @@
 	ret = striped_read(inode, off, len, pages, num_pages, checkeof);
 
 	if (ret >= 0 && (file->f_flags & O_DIRECT) == 0)
-		ret = copy_page_vector_to_user(pages, data, off, ret);
+		ret = ceph_copy_page_vector_to_user(pages, data, off, ret);
 	if (ret >= 0)
 		*poff = off + ret;
 
 done:
 	if (file->f_flags & O_DIRECT)
-		put_page_vector(pages, num_pages);
+		ceph_put_page_vector(pages, num_pages);
 	else
 		ceph_release_page_vector(pages, num_pages);
 	dout("sync_read result %d\n", ret);
@@ -594,7 +438,7 @@
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct ceph_client *client = ceph_inode_to_client(inode);
+	struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
 	struct ceph_osd_request *req;
 	struct page **pages;
 	int num_pages;
@@ -642,7 +486,7 @@
 	 */
 more:
 	len = left;
-	req = ceph_osdc_new_request(&client->osdc, &ci->i_layout,
+	req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
 				    ceph_vino(inode), pos, &len,
 				    CEPH_OSD_OP_WRITE, flags,
 				    ci->i_snap_realm->cached_context,
@@ -655,7 +499,7 @@
 	num_pages = calc_pages_for(pos, len);
 
 	if (file->f_flags & O_DIRECT) {
-		pages = get_direct_page_vector(data, num_pages, pos, len);
+		pages = ceph_get_direct_page_vector(data, num_pages, pos, len);
 		if (IS_ERR(pages)) {
 			ret = PTR_ERR(pages);
 			goto out;
@@ -673,7 +517,7 @@
 			ret = PTR_ERR(pages);
 			goto out;
 		}
-		ret = copy_user_to_page_vector(pages, data, pos, len);
+		ret = ceph_copy_user_to_page_vector(pages, data, pos, len);
 		if (ret < 0) {
 			ceph_release_page_vector(pages, num_pages);
 			goto out;
@@ -689,7 +533,7 @@
 	req->r_num_pages = num_pages;
 	req->r_inode = inode;
 
-	ret = ceph_osdc_start_request(&client->osdc, req, false);
+	ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
 	if (!ret) {
 		if (req->r_safe_callback) {
 			/*
@@ -697,15 +541,15 @@
 			 * start_request so that a tid has been assigned.
 			 */
 			spin_lock(&ci->i_unsafe_lock);
-			list_add(&ci->i_unsafe_writes, &req->r_unsafe_item);
+			list_add(&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(&client->osdc, req);
+		ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
 	}
 
 	if (file->f_flags & O_DIRECT)
-		put_page_vector(pages, num_pages);
+		ceph_put_page_vector(pages, num_pages);
 	else if (file->f_flags & O_SYNC)
 		ceph_release_page_vector(pages, num_pages);
 
@@ -814,7 +658,8 @@
 	struct ceph_file_info *fi = file->private_data;
 	struct inode *inode = file->f_dentry->d_inode;
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct ceph_osd_client *osdc = &ceph_sb_to_client(inode->i_sb)->osdc;
+	struct ceph_osd_client *osdc =
+		&ceph_sb_to_client(inode->i_sb)->client->osdc;
 	loff_t endoff = pos + iov->iov_len;
 	int want, got = 0;
 	int ret, err;
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 62377ec..1d6a45b 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -13,7 +13,8 @@
 #include <linux/pagevec.h>
 
 #include "super.h"
-#include "decode.h"
+#include "mds_client.h"
+#include <linux/ceph/decode.h>
 
 /*
  * Ceph inode operations
@@ -384,7 +385,7 @@
 	 */
 	if (ci->i_snap_realm) {
 		struct ceph_mds_client *mdsc =
-			&ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
+			ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
 		struct ceph_snap_realm *realm = ci->i_snap_realm;
 
 		dout(" dropping residual ref to snap realm %p\n", realm);
@@ -685,7 +686,7 @@
 		}
 
 		/* it may be better to set st_size in getattr instead? */
-		if (ceph_test_opt(ceph_sb_to_client(inode->i_sb), RBYTES))
+		if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), RBYTES))
 			inode->i_size = ci->i_rbytes;
 		break;
 	default:
@@ -901,7 +902,7 @@
 	struct inode *in = NULL;
 	struct ceph_mds_reply_inode *ininfo;
 	struct ceph_vino vino;
-	struct ceph_client *client = ceph_sb_to_client(sb);
+	struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
 	int i = 0;
 	int err = 0;
 
@@ -965,7 +966,7 @@
 	 */
 	if (rinfo->head->is_dentry && !req->r_aborted &&
 	    (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name,
-					       client->mount_args->snapdir_name,
+					       fsc->mount_options->snapdir_name,
 					       req->r_dentry->d_name.len))) {
 		/*
 		 * lookup link rename   : null -> possibly existing inode
@@ -1533,7 +1534,7 @@
 	struct inode *parent_inode = dentry->d_parent->d_inode;
 	const unsigned int ia_valid = attr->ia_valid;
 	struct ceph_mds_request *req;
-	struct ceph_mds_client *mdsc = &ceph_sb_to_client(dentry->d_sb)->mdsc;
+	struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc;
 	int issued;
 	int release = 0, dirtied = 0;
 	int mask = 0;
@@ -1728,8 +1729,8 @@
  */
 int ceph_do_getattr(struct inode *inode, int mask)
 {
-	struct ceph_client *client = ceph_sb_to_client(inode->i_sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req;
 	int err;
 
diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c
index 76e307d..8888c9ba 100644
--- a/fs/ceph/ioctl.c
+++ b/fs/ceph/ioctl.c
@@ -1,8 +1,10 @@
 #include <linux/in.h>
 
-#include "ioctl.h"
 #include "super.h"
-#include "ceph_debug.h"
+#include "mds_client.h"
+#include <linux/ceph/ceph_debug.h>
+
+#include "ioctl.h"
 
 
 /*
@@ -37,7 +39,7 @@
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct inode *parent_inode = file->f_dentry->d_parent->d_inode;
-	struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc;
+	struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
 	struct ceph_mds_request *req;
 	struct ceph_ioctl_layout l;
 	int err, i;
@@ -90,6 +92,68 @@
 }
 
 /*
+ * Set a layout policy on a directory inode. All items in the tree
+ * rooted at this inode will inherit this layout on creation,
+ * (It doesn't apply retroactively )
+ * unless a subdirectory has its own layout policy.
+ */
+static long ceph_ioctl_set_layout_policy (struct file *file, void __user *arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct ceph_mds_request *req;
+	struct ceph_ioctl_layout l;
+	int err, i;
+	struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+
+	/* copy and validate */
+	if (copy_from_user(&l, arg, sizeof(l)))
+		return -EFAULT;
+
+	if ((l.object_size & ~PAGE_MASK) ||
+	    (l.stripe_unit & ~PAGE_MASK) ||
+	    !l.stripe_unit ||
+	    (l.object_size &&
+	        (unsigned)l.object_size % (unsigned)l.stripe_unit))
+		return -EINVAL;
+
+	/* make sure it's a valid data pool */
+	if (l.data_pool > 0) {
+		mutex_lock(&mdsc->mutex);
+		err = -EINVAL;
+		for (i = 0; i < mdsc->mdsmap->m_num_data_pg_pools; i++)
+			if (mdsc->mdsmap->m_data_pg_pools[i] == l.data_pool) {
+				err = 0;
+				break;
+			}
+		mutex_unlock(&mdsc->mutex);
+		if (err)
+			return err;
+	}
+
+	req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETDIRLAYOUT,
+				       USE_AUTH_MDS);
+
+	if (IS_ERR(req))
+		return PTR_ERR(req);
+	req->r_inode = igrab(inode);
+
+	req->r_args.setlayout.layout.fl_stripe_unit =
+			cpu_to_le32(l.stripe_unit);
+	req->r_args.setlayout.layout.fl_stripe_count =
+			cpu_to_le32(l.stripe_count);
+	req->r_args.setlayout.layout.fl_object_size =
+			cpu_to_le32(l.object_size);
+	req->r_args.setlayout.layout.fl_pg_pool =
+			cpu_to_le32(l.data_pool);
+	req->r_args.setlayout.layout.fl_pg_preferred =
+			cpu_to_le32(l.preferred_osd);
+
+	err = ceph_mdsc_do_request(mdsc, inode, req);
+	ceph_mdsc_put_request(req);
+	return err;
+}
+
+/*
  * Return object name, size/offset information, and location (OSD
  * number, network address) for a given file offset.
  */
@@ -98,7 +162,8 @@
 	struct ceph_ioctl_dataloc dl;
 	struct inode *inode = file->f_dentry->d_inode;
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct ceph_osd_client *osdc = &ceph_sb_to_client(inode->i_sb)->osdc;
+	struct ceph_osd_client *osdc =
+		&ceph_sb_to_client(inode->i_sb)->client->osdc;
 	u64 len = 1, olen;
 	u64 tmp;
 	struct ceph_object_layout ol;
@@ -174,11 +239,15 @@
 	case CEPH_IOC_SET_LAYOUT:
 		return ceph_ioctl_set_layout(file, (void __user *)arg);
 
+	case CEPH_IOC_SET_LAYOUT_POLICY:
+		return ceph_ioctl_set_layout_policy(file, (void __user *)arg);
+
 	case CEPH_IOC_GET_DATALOC:
 		return ceph_ioctl_get_dataloc(file, (void __user *)arg);
 
 	case CEPH_IOC_LAZYIO:
 		return ceph_ioctl_lazyio(file);
 	}
+
 	return -ENOTTY;
 }
diff --git a/fs/ceph/ioctl.h b/fs/ceph/ioctl.h
index 88451a3..a6ce54e 100644
--- a/fs/ceph/ioctl.h
+++ b/fs/ceph/ioctl.h
@@ -4,7 +4,7 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
-#define CEPH_IOCTL_MAGIC 0x97
+#define CEPH_IOCTL_MAGIC 0x98
 
 /* just use u64 to align sanely on all archs */
 struct ceph_ioctl_layout {
@@ -17,6 +17,8 @@
 				   struct ceph_ioctl_layout)
 #define CEPH_IOC_SET_LAYOUT _IOW(CEPH_IOCTL_MAGIC, 2,		\
 				   struct ceph_ioctl_layout)
+#define CEPH_IOC_SET_LAYOUT_POLICY _IOW(CEPH_IOCTL_MAGIC, 5,	\
+				   struct ceph_ioctl_layout)
 
 /*
  * Extract identity, address of the OSD and object storing a given
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c
index ff4e753..40abde9 100644
--- a/fs/ceph/locks.c
+++ b/fs/ceph/locks.c
@@ -1,11 +1,11 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/file.h>
 #include <linux/namei.h>
 
 #include "super.h"
 #include "mds_client.h"
-#include "pagelist.h"
+#include <linux/ceph/pagelist.h>
 
 /**
  * Implement fcntl and flock locking functions.
@@ -16,7 +16,7 @@
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct ceph_mds_client *mdsc =
-		&ceph_sb_to_client(inode->i_sb)->mdsc;
+		ceph_sb_to_client(inode->i_sb)->mdsc;
 	struct ceph_mds_request *req;
 	int err;
 
@@ -181,8 +181,9 @@
  * Encode the flock and fcntl locks for the given inode into the pagelist.
  * Format is: #fcntl locks, sequential fcntl locks, #flock locks,
  * sequential flock locks.
- * Must be called with BLK already held, and the lock numbers should have
- * been gathered under the same lock holding window.
+ * Must be called with lock_flocks() already held.
+ * If we encounter more of a specific lock type than expected,
+ * we return the value 1.
  */
 int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
 		      int num_fcntl_locks, int num_flock_locks)
@@ -190,6 +191,8 @@
 	struct file_lock *lock;
 	struct ceph_filelock cephlock;
 	int err = 0;
+	int seen_fcntl = 0;
+	int seen_flock = 0;
 
 	dout("encoding %d flock and %d fcntl locks", num_flock_locks,
 	     num_fcntl_locks);
@@ -198,6 +201,11 @@
 		goto fail;
 	for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
 		if (lock->fl_flags & FL_POSIX) {
+			++seen_fcntl;
+			if (seen_fcntl > num_fcntl_locks) {
+				err = -ENOSPC;
+				goto fail;
+			}
 			err = lock_to_ceph_filelock(lock, &cephlock);
 			if (err)
 				goto fail;
@@ -213,6 +221,11 @@
 		goto fail;
 	for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
 		if (lock->fl_flags & FL_FLOCK) {
+			++seen_flock;
+			if (seen_flock > num_flock_locks) {
+				err = -ENOSPC;
+				goto fail;
+			}
 			err = lock_to_ceph_filelock(lock, &cephlock);
 			if (err)
 				goto fail;
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index fad95f8..3142b15 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1,17 +1,21 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
+#include <linux/fs.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/smp_lock.h>
 
-#include "mds_client.h"
-#include "mon_client.h"
 #include "super.h"
-#include "messenger.h"
-#include "decode.h"
-#include "auth.h"
-#include "pagelist.h"
+#include "mds_client.h"
+
+#include <linux/ceph/messenger.h>
+#include <linux/ceph/decode.h>
+#include <linux/ceph/pagelist.h>
+#include <linux/ceph/auth.h>
+#include <linux/ceph/debugfs.h>
 
 /*
  * A cluster of MDS (metadata server) daemons is responsible for
@@ -286,8 +290,9 @@
 	     atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1);
 	if (atomic_dec_and_test(&s->s_ref)) {
 		if (s->s_authorizer)
-			s->s_mdsc->client->monc.auth->ops->destroy_authorizer(
-				s->s_mdsc->client->monc.auth, s->s_authorizer);
+		     s->s_mdsc->fsc->client->monc.auth->ops->destroy_authorizer(
+			     s->s_mdsc->fsc->client->monc.auth,
+			     s->s_authorizer);
 		kfree(s);
 	}
 }
@@ -344,7 +349,7 @@
 	s->s_seq = 0;
 	mutex_init(&s->s_mutex);
 
-	ceph_con_init(mdsc->client->msgr, &s->s_con);
+	ceph_con_init(mdsc->fsc->client->msgr, &s->s_con);
 	s->s_con.private = s;
 	s->s_con.ops = &mds_con_ops;
 	s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS;
@@ -599,7 +604,7 @@
 	} else if (req->r_dentry) {
 		struct inode *dir = req->r_dentry->d_parent->d_inode;
 
-		if (dir->i_sb != mdsc->client->sb) {
+		if (dir->i_sb != mdsc->fsc->sb) {
 			/* not this fs! */
 			inode = req->r_dentry->d_inode;
 		} else if (ceph_snap(dir) != CEPH_NOSNAP) {
@@ -884,7 +889,7 @@
 	__ceph_remove_cap(cap);
 	if (!__ceph_is_any_real_caps(ci)) {
 		struct ceph_mds_client *mdsc =
-			&ceph_sb_to_client(inode->i_sb)->mdsc;
+			ceph_sb_to_client(inode->i_sb)->mdsc;
 
 		spin_lock(&mdsc->cap_dirty_lock);
 		if (!list_empty(&ci->i_dirty_item)) {
@@ -1146,7 +1151,7 @@
 	struct ceph_msg *msg, *partial = NULL;
 	struct ceph_mds_cap_release *head;
 	int err = -ENOMEM;
-	int extra = mdsc->client->mount_args->cap_release_safety;
+	int extra = mdsc->fsc->mount_options->cap_release_safety;
 	int num;
 
 	dout("add_cap_releases %p mds%d extra %d\n", session, session->s_mds,
@@ -2085,7 +2090,7 @@
 
 	/* insert trace into our cache */
 	mutex_lock(&req->r_fill_mutex);
-	err = ceph_fill_trace(mdsc->client->sb, req, req->r_session);
+	err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session);
 	if (err == 0) {
 		if (result == 0 && rinfo->dir_nr)
 			ceph_readdir_prepopulate(req, req->r_session);
@@ -2361,19 +2366,35 @@
 
 	if (recon_state->flock) {
 		int num_fcntl_locks, num_flock_locks;
+		struct ceph_pagelist_cursor trunc_point;
 
-		lock_kernel();
-		ceph_count_locks(inode, &num_fcntl_locks, &num_flock_locks);
-		rec.v2.flock_len = (2*sizeof(u32) +
-				    (num_fcntl_locks+num_flock_locks) *
-				    sizeof(struct ceph_filelock));
+		ceph_pagelist_set_cursor(pagelist, &trunc_point);
+		do {
+			lock_flocks();
+			ceph_count_locks(inode, &num_fcntl_locks,
+					 &num_flock_locks);
+			rec.v2.flock_len = (2*sizeof(u32) +
+					    (num_fcntl_locks+num_flock_locks) *
+					    sizeof(struct ceph_filelock));
+			unlock_flocks();
 
-		err = ceph_pagelist_append(pagelist, &rec, reclen);
-		if (!err)
-			err = ceph_encode_locks(inode, pagelist,
-						num_fcntl_locks,
-						num_flock_locks);
-		unlock_kernel();
+			/* pre-alloc pagelist */
+			ceph_pagelist_truncate(pagelist, &trunc_point);
+			err = ceph_pagelist_append(pagelist, &rec, reclen);
+			if (!err)
+				err = ceph_pagelist_reserve(pagelist,
+							    rec.v2.flock_len);
+
+			/* encode locks */
+			if (!err) {
+				lock_flocks();
+				err = ceph_encode_locks(inode,
+							pagelist,
+							num_fcntl_locks,
+							num_flock_locks);
+				unlock_flocks();
+			}
+		} while (err == -ENOSPC);
 	} else {
 		err = ceph_pagelist_append(pagelist, &rec, reclen);
 	}
@@ -2613,7 +2634,7 @@
 			 struct ceph_mds_session *session,
 			 struct ceph_msg *msg)
 {
-	struct super_block *sb = mdsc->client->sb;
+	struct super_block *sb = mdsc->fsc->sb;
 	struct inode *inode;
 	struct ceph_inode_info *ci;
 	struct dentry *parent, *dentry;
@@ -2891,10 +2912,16 @@
 	schedule_delayed(mdsc);
 }
 
+int ceph_mdsc_init(struct ceph_fs_client *fsc)
 
-int ceph_mdsc_init(struct ceph_mds_client *mdsc, struct ceph_client *client)
 {
-	mdsc->client = client;
+	struct ceph_mds_client *mdsc;
+
+	mdsc = kzalloc(sizeof(struct ceph_mds_client), GFP_NOFS);
+	if (!mdsc)
+		return -ENOMEM;
+	mdsc->fsc = fsc;
+	fsc->mdsc = mdsc;
 	mutex_init(&mdsc->mutex);
 	mdsc->mdsmap = kzalloc(sizeof(*mdsc->mdsmap), GFP_NOFS);
 	if (mdsc->mdsmap == NULL)
@@ -2927,7 +2954,7 @@
 	INIT_LIST_HEAD(&mdsc->dentry_lru);
 
 	ceph_caps_init(mdsc);
-	ceph_adjust_min_caps(mdsc, client->min_caps);
+	ceph_adjust_min_caps(mdsc, fsc->min_caps);
 
 	return 0;
 }
@@ -2939,7 +2966,7 @@
 static void wait_requests(struct ceph_mds_client *mdsc)
 {
 	struct ceph_mds_request *req;
-	struct ceph_client *client = mdsc->client;
+	struct ceph_fs_client *fsc = mdsc->fsc;
 
 	mutex_lock(&mdsc->mutex);
 	if (__get_oldest_req(mdsc)) {
@@ -2947,7 +2974,7 @@
 
 		dout("wait_requests waiting for requests\n");
 		wait_for_completion_timeout(&mdsc->safe_umount_waiters,
-				    client->mount_args->mount_timeout * HZ);
+				    fsc->client->options->mount_timeout * HZ);
 
 		/* tear down remaining requests */
 		mutex_lock(&mdsc->mutex);
@@ -3030,7 +3057,7 @@
 {
 	u64 want_tid, want_flush;
 
-	if (mdsc->client->mount_state == CEPH_MOUNT_SHUTDOWN)
+	if (mdsc->fsc->mount_state == CEPH_MOUNT_SHUTDOWN)
 		return;
 
 	dout("sync\n");
@@ -3053,7 +3080,7 @@
 {
 	int i, n = 0;
 
-	if (mdsc->client->mount_state == CEPH_MOUNT_SHUTDOWN)
+	if (mdsc->fsc->mount_state == CEPH_MOUNT_SHUTDOWN)
 		return true;
 
 	mutex_lock(&mdsc->mutex);
@@ -3071,8 +3098,8 @@
 {
 	struct ceph_mds_session *session;
 	int i;
-	struct ceph_client *client = mdsc->client;
-	unsigned long timeout = client->mount_args->mount_timeout * HZ;
+	struct ceph_fs_client *fsc = mdsc->fsc;
+	unsigned long timeout = fsc->client->options->mount_timeout * HZ;
 
 	dout("close_sessions\n");
 
@@ -3119,7 +3146,7 @@
 	dout("stopped\n");
 }
 
-void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
+static void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
 {
 	dout("stop\n");
 	cancel_delayed_work_sync(&mdsc->delayed_work); /* cancel timer */
@@ -3129,6 +3156,15 @@
 	ceph_caps_finalize(mdsc);
 }
 
+void ceph_mdsc_destroy(struct ceph_fs_client *fsc)
+{
+	struct ceph_mds_client *mdsc = fsc->mdsc;
+
+	ceph_mdsc_stop(mdsc);
+	fsc->mdsc = NULL;
+	kfree(mdsc);
+}
+
 
 /*
  * handle mds map update.
@@ -3145,14 +3181,14 @@
 
 	ceph_decode_need(&p, end, sizeof(fsid)+2*sizeof(u32), bad);
 	ceph_decode_copy(&p, &fsid, sizeof(fsid));
-	if (ceph_check_fsid(mdsc->client, &fsid) < 0)
+	if (ceph_check_fsid(mdsc->fsc->client, &fsid) < 0)
 		return;
 	epoch = ceph_decode_32(&p);
 	maplen = ceph_decode_32(&p);
 	dout("handle_map epoch %u len %d\n", epoch, (int)maplen);
 
 	/* do we need it? */
-	ceph_monc_got_mdsmap(&mdsc->client->monc, epoch);
+	ceph_monc_got_mdsmap(&mdsc->fsc->client->monc, epoch);
 	mutex_lock(&mdsc->mutex);
 	if (mdsc->mdsmap && epoch <= mdsc->mdsmap->m_epoch) {
 		dout("handle_map epoch %u <= our %u\n",
@@ -3176,7 +3212,7 @@
 	} else {
 		mdsc->mdsmap = newmap;  /* first mds map */
 	}
-	mdsc->client->sb->s_maxbytes = mdsc->mdsmap->m_max_file_size;
+	mdsc->fsc->sb->s_maxbytes = mdsc->mdsmap->m_max_file_size;
 
 	__wake_requests(mdsc, &mdsc->waiting_for_map);
 
@@ -3277,7 +3313,7 @@
 {
 	struct ceph_mds_session *s = con->private;
 	struct ceph_mds_client *mdsc = s->s_mdsc;
-	struct ceph_auth_client *ac = mdsc->client->monc.auth;
+	struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
 	int ret = 0;
 
 	if (force_new && s->s_authorizer) {
@@ -3311,7 +3347,7 @@
 {
 	struct ceph_mds_session *s = con->private;
 	struct ceph_mds_client *mdsc = s->s_mdsc;
-	struct ceph_auth_client *ac = mdsc->client->monc.auth;
+	struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
 
 	return ac->ops->verify_authorizer_reply(ac, s->s_authorizer, len);
 }
@@ -3320,12 +3356,12 @@
 {
 	struct ceph_mds_session *s = con->private;
 	struct ceph_mds_client *mdsc = s->s_mdsc;
-	struct ceph_auth_client *ac = mdsc->client->monc.auth;
+	struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
 
 	if (ac->ops->invalidate_authorizer)
 		ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_MDS);
 
-	return ceph_monc_validate_auth(&mdsc->client->monc);
+	return ceph_monc_validate_auth(&mdsc->fsc->client->monc);
 }
 
 static const struct ceph_connection_operations mds_con_ops = {
@@ -3338,7 +3374,4 @@
 	.peer_reset = peer_reset,
 };
 
-
-
-
 /* eof */
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index c98267c..d66d63c 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -8,9 +8,9 @@
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
 
-#include "types.h"
-#include "messenger.h"
-#include "mdsmap.h"
+#include <linux/ceph/types.h>
+#include <linux/ceph/messenger.h>
+#include <linux/ceph/mdsmap.h>
 
 /*
  * Some lock dependencies:
@@ -26,7 +26,7 @@
  *
  */
 
-struct ceph_client;
+struct ceph_fs_client;
 struct ceph_cap;
 
 /*
@@ -230,7 +230,7 @@
  * mds client state
  */
 struct ceph_mds_client {
-	struct ceph_client      *client;
+	struct ceph_fs_client  *fsc;
 	struct mutex            mutex;         /* all nested structures */
 
 	struct ceph_mdsmap      *mdsmap;
@@ -289,11 +289,6 @@
 	int		caps_avail_count;    /* unused, unreserved */
 	int		caps_min_count;      /* keep at least this many
 						(unreserved) */
-
-#ifdef CONFIG_DEBUG_FS
-	struct dentry 	  *debugfs_file;
-#endif
-
 	spinlock_t	  dentry_lru_lock;
 	struct list_head  dentry_lru;
 	int		  num_dentry;
@@ -316,10 +311,9 @@
 extern int ceph_send_msg_mds(struct ceph_mds_client *mdsc,
 			     struct ceph_msg *msg, int mds);
 
-extern int ceph_mdsc_init(struct ceph_mds_client *mdsc,
-			   struct ceph_client *client);
+extern int ceph_mdsc_init(struct ceph_fs_client *fsc);
 extern void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc);
-extern void ceph_mdsc_stop(struct ceph_mds_client *mdsc);
+extern void ceph_mdsc_destroy(struct ceph_fs_client *fsc);
 
 extern void ceph_mdsc_sync(struct ceph_mds_client *mdsc);
 
diff --git a/fs/ceph/mdsmap.c b/fs/ceph/mdsmap.c
index 040be6d..73b7d44 100644
--- a/fs/ceph/mdsmap.c
+++ b/fs/ceph/mdsmap.c
@@ -1,4 +1,4 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/bug.h>
 #include <linux/err.h>
@@ -6,9 +6,9 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 
-#include "mdsmap.h"
-#include "messenger.h"
-#include "decode.h"
+#include <linux/ceph/mdsmap.h>
+#include <linux/ceph/messenger.h>
+#include <linux/ceph/decode.h>
 
 #include "super.h"
 
@@ -117,7 +117,8 @@
 		}
 
 		dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s\n",
-		     i+1, n, global_id, mds, inc, pr_addr(&addr.in_addr),
+		     i+1, n, global_id, mds, inc,
+		     ceph_pr_addr(&addr.in_addr),
 		     ceph_mds_state_name(state));
 		if (mds >= 0 && mds < m->m_max_mds && state > 0) {
 			m->m_info[mds].global_id = global_id;
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c
deleted file mode 100644
index 2502d76..0000000
--- a/fs/ceph/messenger.c
+++ /dev/null
@@ -1,2277 +0,0 @@
-#include "ceph_debug.h"
-
-#include <linux/crc32c.h>
-#include <linux/ctype.h>
-#include <linux/highmem.h>
-#include <linux/inet.h>
-#include <linux/kthread.h>
-#include <linux/net.h>
-#include <linux/slab.h>
-#include <linux/socket.h>
-#include <linux/string.h>
-#include <net/tcp.h>
-
-#include "super.h"
-#include "messenger.h"
-#include "decode.h"
-#include "pagelist.h"
-
-/*
- * Ceph uses the messenger to exchange ceph_msg messages with other
- * hosts in the system.  The messenger provides ordered and reliable
- * delivery.  We tolerate TCP disconnects by reconnecting (with
- * exponential backoff) in the case of a fault (disconnection, bad
- * crc, protocol error).  Acks allow sent messages to be discarded by
- * the sender.
- */
-
-/* static tag bytes (protocol control messages) */
-static char tag_msg = CEPH_MSGR_TAG_MSG;
-static char tag_ack = CEPH_MSGR_TAG_ACK;
-static char tag_keepalive = CEPH_MSGR_TAG_KEEPALIVE;
-
-#ifdef CONFIG_LOCKDEP
-static struct lock_class_key socket_class;
-#endif
-
-
-static void queue_con(struct ceph_connection *con);
-static void con_work(struct work_struct *);
-static void ceph_fault(struct ceph_connection *con);
-
-/*
- * nicely render a sockaddr as a string.
- */
-#define MAX_ADDR_STR 20
-#define MAX_ADDR_STR_LEN 60
-static char addr_str[MAX_ADDR_STR][MAX_ADDR_STR_LEN];
-static DEFINE_SPINLOCK(addr_str_lock);
-static int last_addr_str;
-
-const char *pr_addr(const struct sockaddr_storage *ss)
-{
-	int i;
-	char *s;
-	struct sockaddr_in *in4 = (void *)ss;
-	struct sockaddr_in6 *in6 = (void *)ss;
-
-	spin_lock(&addr_str_lock);
-	i = last_addr_str++;
-	if (last_addr_str == MAX_ADDR_STR)
-		last_addr_str = 0;
-	spin_unlock(&addr_str_lock);
-	s = addr_str[i];
-
-	switch (ss->ss_family) {
-	case AF_INET:
-		snprintf(s, MAX_ADDR_STR_LEN, "%pI4:%u", &in4->sin_addr,
-			 (unsigned int)ntohs(in4->sin_port));
-		break;
-
-	case AF_INET6:
-		snprintf(s, MAX_ADDR_STR_LEN, "[%pI6c]:%u", &in6->sin6_addr,
-			 (unsigned int)ntohs(in6->sin6_port));
-		break;
-
-	default:
-		sprintf(s, "(unknown sockaddr family %d)", (int)ss->ss_family);
-	}
-
-	return s;
-}
-
-static void encode_my_addr(struct ceph_messenger *msgr)
-{
-	memcpy(&msgr->my_enc_addr, &msgr->inst.addr, sizeof(msgr->my_enc_addr));
-	ceph_encode_addr(&msgr->my_enc_addr);
-}
-
-/*
- * work queue for all reading and writing to/from the socket.
- */
-struct workqueue_struct *ceph_msgr_wq;
-
-int __init ceph_msgr_init(void)
-{
-	ceph_msgr_wq = create_workqueue("ceph-msgr");
-	if (IS_ERR(ceph_msgr_wq)) {
-		int ret = PTR_ERR(ceph_msgr_wq);
-		pr_err("msgr_init failed to create workqueue: %d\n", ret);
-		ceph_msgr_wq = NULL;
-		return ret;
-	}
-	return 0;
-}
-
-void ceph_msgr_exit(void)
-{
-	destroy_workqueue(ceph_msgr_wq);
-}
-
-void ceph_msgr_flush(void)
-{
-	flush_workqueue(ceph_msgr_wq);
-}
-
-
-/*
- * socket callback functions
- */
-
-/* data available on socket, or listen socket received a connect */
-static void ceph_data_ready(struct sock *sk, int count_unused)
-{
-	struct ceph_connection *con =
-		(struct ceph_connection *)sk->sk_user_data;
-	if (sk->sk_state != TCP_CLOSE_WAIT) {
-		dout("ceph_data_ready on %p state = %lu, queueing work\n",
-		     con, con->state);
-		queue_con(con);
-	}
-}
-
-/* socket has buffer space for writing */
-static void ceph_write_space(struct sock *sk)
-{
-	struct ceph_connection *con =
-		(struct ceph_connection *)sk->sk_user_data;
-
-	/* only queue to workqueue if there is data we want to write. */
-	if (test_bit(WRITE_PENDING, &con->state)) {
-		dout("ceph_write_space %p queueing write work\n", con);
-		queue_con(con);
-	} else {
-		dout("ceph_write_space %p nothing to write\n", con);
-	}
-
-	/* since we have our own write_space, clear the SOCK_NOSPACE flag */
-	clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
-}
-
-/* socket's state has changed */
-static void ceph_state_change(struct sock *sk)
-{
-	struct ceph_connection *con =
-		(struct ceph_connection *)sk->sk_user_data;
-
-	dout("ceph_state_change %p state = %lu sk_state = %u\n",
-	     con, con->state, sk->sk_state);
-
-	if (test_bit(CLOSED, &con->state))
-		return;
-
-	switch (sk->sk_state) {
-	case TCP_CLOSE:
-		dout("ceph_state_change TCP_CLOSE\n");
-	case TCP_CLOSE_WAIT:
-		dout("ceph_state_change TCP_CLOSE_WAIT\n");
-		if (test_and_set_bit(SOCK_CLOSED, &con->state) == 0) {
-			if (test_bit(CONNECTING, &con->state))
-				con->error_msg = "connection failed";
-			else
-				con->error_msg = "socket closed";
-			queue_con(con);
-		}
-		break;
-	case TCP_ESTABLISHED:
-		dout("ceph_state_change TCP_ESTABLISHED\n");
-		queue_con(con);
-		break;
-	}
-}
-
-/*
- * set up socket callbacks
- */
-static void set_sock_callbacks(struct socket *sock,
-			       struct ceph_connection *con)
-{
-	struct sock *sk = sock->sk;
-	sk->sk_user_data = (void *)con;
-	sk->sk_data_ready = ceph_data_ready;
-	sk->sk_write_space = ceph_write_space;
-	sk->sk_state_change = ceph_state_change;
-}
-
-
-/*
- * socket helpers
- */
-
-/*
- * initiate connection to a remote socket.
- */
-static struct socket *ceph_tcp_connect(struct ceph_connection *con)
-{
-	struct sockaddr_storage *paddr = &con->peer_addr.in_addr;
-	struct socket *sock;
-	int ret;
-
-	BUG_ON(con->sock);
-	ret = sock_create_kern(con->peer_addr.in_addr.ss_family, SOCK_STREAM,
-			       IPPROTO_TCP, &sock);
-	if (ret)
-		return ERR_PTR(ret);
-	con->sock = sock;
-	sock->sk->sk_allocation = GFP_NOFS;
-
-#ifdef CONFIG_LOCKDEP
-	lockdep_set_class(&sock->sk->sk_lock, &socket_class);
-#endif
-
-	set_sock_callbacks(sock, con);
-
-	dout("connect %s\n", pr_addr(&con->peer_addr.in_addr));
-
-	ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr),
-				 O_NONBLOCK);
-	if (ret == -EINPROGRESS) {
-		dout("connect %s EINPROGRESS sk_state = %u\n",
-		     pr_addr(&con->peer_addr.in_addr),
-		     sock->sk->sk_state);
-		ret = 0;
-	}
-	if (ret < 0) {
-		pr_err("connect %s error %d\n",
-		       pr_addr(&con->peer_addr.in_addr), ret);
-		sock_release(sock);
-		con->sock = NULL;
-		con->error_msg = "connect error";
-	}
-
-	if (ret < 0)
-		return ERR_PTR(ret);
-	return sock;
-}
-
-static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len)
-{
-	struct kvec iov = {buf, len};
-	struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL };
-
-	return kernel_recvmsg(sock, &msg, &iov, 1, len, msg.msg_flags);
-}
-
-/*
- * write something.  @more is true if caller will be sending more data
- * shortly.
- */
-static int ceph_tcp_sendmsg(struct socket *sock, struct kvec *iov,
-		     size_t kvlen, size_t len, int more)
-{
-	struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL };
-
-	if (more)
-		msg.msg_flags |= MSG_MORE;
-	else
-		msg.msg_flags |= MSG_EOR;  /* superfluous, but what the hell */
-
-	return kernel_sendmsg(sock, &msg, iov, kvlen, len);
-}
-
-
-/*
- * Shutdown/close the socket for the given connection.
- */
-static int con_close_socket(struct ceph_connection *con)
-{
-	int rc;
-
-	dout("con_close_socket on %p sock %p\n", con, con->sock);
-	if (!con->sock)
-		return 0;
-	set_bit(SOCK_CLOSED, &con->state);
-	rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR);
-	sock_release(con->sock);
-	con->sock = NULL;
-	clear_bit(SOCK_CLOSED, &con->state);
-	return rc;
-}
-
-/*
- * Reset a connection.  Discard all incoming and outgoing messages
- * and clear *_seq state.
- */
-static void ceph_msg_remove(struct ceph_msg *msg)
-{
-	list_del_init(&msg->list_head);
-	ceph_msg_put(msg);
-}
-static void ceph_msg_remove_list(struct list_head *head)
-{
-	while (!list_empty(head)) {
-		struct ceph_msg *msg = list_first_entry(head, struct ceph_msg,
-							list_head);
-		ceph_msg_remove(msg);
-	}
-}
-
-static void reset_connection(struct ceph_connection *con)
-{
-	/* reset connection, out_queue, msg_ and connect_seq */
-	/* discard existing out_queue and msg_seq */
-	ceph_msg_remove_list(&con->out_queue);
-	ceph_msg_remove_list(&con->out_sent);
-
-	if (con->in_msg) {
-		ceph_msg_put(con->in_msg);
-		con->in_msg = NULL;
-	}
-
-	con->connect_seq = 0;
-	con->out_seq = 0;
-	if (con->out_msg) {
-		ceph_msg_put(con->out_msg);
-		con->out_msg = NULL;
-	}
-	con->out_keepalive_pending = false;
-	con->in_seq = 0;
-	con->in_seq_acked = 0;
-}
-
-/*
- * mark a peer down.  drop any open connections.
- */
-void ceph_con_close(struct ceph_connection *con)
-{
-	dout("con_close %p peer %s\n", con, pr_addr(&con->peer_addr.in_addr));
-	set_bit(CLOSED, &con->state);  /* in case there's queued work */
-	clear_bit(STANDBY, &con->state);  /* avoid connect_seq bump */
-	clear_bit(LOSSYTX, &con->state);  /* so we retry next connect */
-	clear_bit(KEEPALIVE_PENDING, &con->state);
-	clear_bit(WRITE_PENDING, &con->state);
-	mutex_lock(&con->mutex);
-	reset_connection(con);
-	con->peer_global_seq = 0;
-	cancel_delayed_work(&con->work);
-	mutex_unlock(&con->mutex);
-	queue_con(con);
-}
-
-/*
- * Reopen a closed connection, with a new peer address.
- */
-void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr)
-{
-	dout("con_open %p %s\n", con, pr_addr(&addr->in_addr));
-	set_bit(OPENING, &con->state);
-	clear_bit(CLOSED, &con->state);
-	memcpy(&con->peer_addr, addr, sizeof(*addr));
-	con->delay = 0;      /* reset backoff memory */
-	queue_con(con);
-}
-
-/*
- * return true if this connection ever successfully opened
- */
-bool ceph_con_opened(struct ceph_connection *con)
-{
-	return con->connect_seq > 0;
-}
-
-/*
- * generic get/put
- */
-struct ceph_connection *ceph_con_get(struct ceph_connection *con)
-{
-	dout("con_get %p nref = %d -> %d\n", con,
-	     atomic_read(&con->nref), atomic_read(&con->nref) + 1);
-	if (atomic_inc_not_zero(&con->nref))
-		return con;
-	return NULL;
-}
-
-void ceph_con_put(struct ceph_connection *con)
-{
-	dout("con_put %p nref = %d -> %d\n", con,
-	     atomic_read(&con->nref), atomic_read(&con->nref) - 1);
-	BUG_ON(atomic_read(&con->nref) == 0);
-	if (atomic_dec_and_test(&con->nref)) {
-		BUG_ON(con->sock);
-		kfree(con);
-	}
-}
-
-/*
- * initialize a new connection.
- */
-void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con)
-{
-	dout("con_init %p\n", con);
-	memset(con, 0, sizeof(*con));
-	atomic_set(&con->nref, 1);
-	con->msgr = msgr;
-	mutex_init(&con->mutex);
-	INIT_LIST_HEAD(&con->out_queue);
-	INIT_LIST_HEAD(&con->out_sent);
-	INIT_DELAYED_WORK(&con->work, con_work);
-}
-
-
-/*
- * We maintain a global counter to order connection attempts.  Get
- * a unique seq greater than @gt.
- */
-static u32 get_global_seq(struct ceph_messenger *msgr, u32 gt)
-{
-	u32 ret;
-
-	spin_lock(&msgr->global_seq_lock);
-	if (msgr->global_seq < gt)
-		msgr->global_seq = gt;
-	ret = ++msgr->global_seq;
-	spin_unlock(&msgr->global_seq_lock);
-	return ret;
-}
-
-
-/*
- * Prepare footer for currently outgoing message, and finish things
- * off.  Assumes out_kvec* are already valid.. we just add on to the end.
- */
-static void prepare_write_message_footer(struct ceph_connection *con, int v)
-{
-	struct ceph_msg *m = con->out_msg;
-
-	dout("prepare_write_message_footer %p\n", con);
-	con->out_kvec_is_msg = true;
-	con->out_kvec[v].iov_base = &m->footer;
-	con->out_kvec[v].iov_len = sizeof(m->footer);
-	con->out_kvec_bytes += sizeof(m->footer);
-	con->out_kvec_left++;
-	con->out_more = m->more_to_follow;
-	con->out_msg_done = true;
-}
-
-/*
- * Prepare headers for the next outgoing message.
- */
-static void prepare_write_message(struct ceph_connection *con)
-{
-	struct ceph_msg *m;
-	int v = 0;
-
-	con->out_kvec_bytes = 0;
-	con->out_kvec_is_msg = true;
-	con->out_msg_done = false;
-
-	/* Sneak an ack in there first?  If we can get it into the same
-	 * TCP packet that's a good thing. */
-	if (con->in_seq > con->in_seq_acked) {
-		con->in_seq_acked = con->in_seq;
-		con->out_kvec[v].iov_base = &tag_ack;
-		con->out_kvec[v++].iov_len = 1;
-		con->out_temp_ack = cpu_to_le64(con->in_seq_acked);
-		con->out_kvec[v].iov_base = &con->out_temp_ack;
-		con->out_kvec[v++].iov_len = sizeof(con->out_temp_ack);
-		con->out_kvec_bytes = 1 + sizeof(con->out_temp_ack);
-	}
-
-	m = list_first_entry(&con->out_queue,
-		       struct ceph_msg, list_head);
-	con->out_msg = m;
-	if (test_bit(LOSSYTX, &con->state)) {
-		list_del_init(&m->list_head);
-	} else {
-		/* put message on sent list */
-		ceph_msg_get(m);
-		list_move_tail(&m->list_head, &con->out_sent);
-	}
-
-	/*
-	 * only assign outgoing seq # if we haven't sent this message
-	 * yet.  if it is requeued, resend with it's original seq.
-	 */
-	if (m->needs_out_seq) {
-		m->hdr.seq = cpu_to_le64(++con->out_seq);
-		m->needs_out_seq = false;
-	}
-
-	dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n",
-	     m, con->out_seq, le16_to_cpu(m->hdr.type),
-	     le32_to_cpu(m->hdr.front_len), le32_to_cpu(m->hdr.middle_len),
-	     le32_to_cpu(m->hdr.data_len),
-	     m->nr_pages);
-	BUG_ON(le32_to_cpu(m->hdr.front_len) != m->front.iov_len);
-
-	/* tag + hdr + front + middle */
-	con->out_kvec[v].iov_base = &tag_msg;
-	con->out_kvec[v++].iov_len = 1;
-	con->out_kvec[v].iov_base = &m->hdr;
-	con->out_kvec[v++].iov_len = sizeof(m->hdr);
-	con->out_kvec[v++] = m->front;
-	if (m->middle)
-		con->out_kvec[v++] = m->middle->vec;
-	con->out_kvec_left = v;
-	con->out_kvec_bytes += 1 + sizeof(m->hdr) + m->front.iov_len +
-		(m->middle ? m->middle->vec.iov_len : 0);
-	con->out_kvec_cur = con->out_kvec;
-
-	/* fill in crc (except data pages), footer */
-	con->out_msg->hdr.crc =
-		cpu_to_le32(crc32c(0, (void *)&m->hdr,
-				      sizeof(m->hdr) - sizeof(m->hdr.crc)));
-	con->out_msg->footer.flags = CEPH_MSG_FOOTER_COMPLETE;
-	con->out_msg->footer.front_crc =
-		cpu_to_le32(crc32c(0, m->front.iov_base, m->front.iov_len));
-	if (m->middle)
-		con->out_msg->footer.middle_crc =
-			cpu_to_le32(crc32c(0, m->middle->vec.iov_base,
-					   m->middle->vec.iov_len));
-	else
-		con->out_msg->footer.middle_crc = 0;
-	con->out_msg->footer.data_crc = 0;
-	dout("prepare_write_message front_crc %u data_crc %u\n",
-	     le32_to_cpu(con->out_msg->footer.front_crc),
-	     le32_to_cpu(con->out_msg->footer.middle_crc));
-
-	/* is there a data payload? */
-	if (le32_to_cpu(m->hdr.data_len) > 0) {
-		/* initialize page iterator */
-		con->out_msg_pos.page = 0;
-		con->out_msg_pos.page_pos =
-			le16_to_cpu(m->hdr.data_off) & ~PAGE_MASK;
-		con->out_msg_pos.data_pos = 0;
-		con->out_msg_pos.did_page_crc = 0;
-		con->out_more = 1;  /* data + footer will follow */
-	} else {
-		/* no, queue up footer too and be done */
-		prepare_write_message_footer(con, v);
-	}
-
-	set_bit(WRITE_PENDING, &con->state);
-}
-
-/*
- * Prepare an ack.
- */
-static void prepare_write_ack(struct ceph_connection *con)
-{
-	dout("prepare_write_ack %p %llu -> %llu\n", con,
-	     con->in_seq_acked, con->in_seq);
-	con->in_seq_acked = con->in_seq;
-
-	con->out_kvec[0].iov_base = &tag_ack;
-	con->out_kvec[0].iov_len = 1;
-	con->out_temp_ack = cpu_to_le64(con->in_seq_acked);
-	con->out_kvec[1].iov_base = &con->out_temp_ack;
-	con->out_kvec[1].iov_len = sizeof(con->out_temp_ack);
-	con->out_kvec_left = 2;
-	con->out_kvec_bytes = 1 + sizeof(con->out_temp_ack);
-	con->out_kvec_cur = con->out_kvec;
-	con->out_more = 1;  /* more will follow.. eventually.. */
-	set_bit(WRITE_PENDING, &con->state);
-}
-
-/*
- * Prepare to write keepalive byte.
- */
-static void prepare_write_keepalive(struct ceph_connection *con)
-{
-	dout("prepare_write_keepalive %p\n", con);
-	con->out_kvec[0].iov_base = &tag_keepalive;
-	con->out_kvec[0].iov_len = 1;
-	con->out_kvec_left = 1;
-	con->out_kvec_bytes = 1;
-	con->out_kvec_cur = con->out_kvec;
-	set_bit(WRITE_PENDING, &con->state);
-}
-
-/*
- * Connection negotiation.
- */
-
-static void prepare_connect_authorizer(struct ceph_connection *con)
-{
-	void *auth_buf;
-	int auth_len = 0;
-	int auth_protocol = 0;
-
-	mutex_unlock(&con->mutex);
-	if (con->ops->get_authorizer)
-		con->ops->get_authorizer(con, &auth_buf, &auth_len,
-					 &auth_protocol, &con->auth_reply_buf,
-					 &con->auth_reply_buf_len,
-					 con->auth_retry);
-	mutex_lock(&con->mutex);
-
-	con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol);
-	con->out_connect.authorizer_len = cpu_to_le32(auth_len);
-
-	con->out_kvec[con->out_kvec_left].iov_base = auth_buf;
-	con->out_kvec[con->out_kvec_left].iov_len = auth_len;
-	con->out_kvec_left++;
-	con->out_kvec_bytes += auth_len;
-}
-
-/*
- * We connected to a peer and are saying hello.
- */
-static void prepare_write_banner(struct ceph_messenger *msgr,
-				 struct ceph_connection *con)
-{
-	int len = strlen(CEPH_BANNER);
-
-	con->out_kvec[0].iov_base = CEPH_BANNER;
-	con->out_kvec[0].iov_len = len;
-	con->out_kvec[1].iov_base = &msgr->my_enc_addr;
-	con->out_kvec[1].iov_len = sizeof(msgr->my_enc_addr);
-	con->out_kvec_left = 2;
-	con->out_kvec_bytes = len + sizeof(msgr->my_enc_addr);
-	con->out_kvec_cur = con->out_kvec;
-	con->out_more = 0;
-	set_bit(WRITE_PENDING, &con->state);
-}
-
-static void prepare_write_connect(struct ceph_messenger *msgr,
-				  struct ceph_connection *con,
-				  int after_banner)
-{
-	unsigned global_seq = get_global_seq(con->msgr, 0);
-	int proto;
-
-	switch (con->peer_name.type) {
-	case CEPH_ENTITY_TYPE_MON:
-		proto = CEPH_MONC_PROTOCOL;
-		break;
-	case CEPH_ENTITY_TYPE_OSD:
-		proto = CEPH_OSDC_PROTOCOL;
-		break;
-	case CEPH_ENTITY_TYPE_MDS:
-		proto = CEPH_MDSC_PROTOCOL;
-		break;
-	default:
-		BUG();
-	}
-
-	dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con,
-	     con->connect_seq, global_seq, proto);
-
-	con->out_connect.features = cpu_to_le64(CEPH_FEATURE_SUPPORTED);
-	con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT);
-	con->out_connect.connect_seq = cpu_to_le32(con->connect_seq);
-	con->out_connect.global_seq = cpu_to_le32(global_seq);
-	con->out_connect.protocol_version = cpu_to_le32(proto);
-	con->out_connect.flags = 0;
-
-	if (!after_banner) {
-		con->out_kvec_left = 0;
-		con->out_kvec_bytes = 0;
-	}
-	con->out_kvec[con->out_kvec_left].iov_base = &con->out_connect;
-	con->out_kvec[con->out_kvec_left].iov_len = sizeof(con->out_connect);
-	con->out_kvec_left++;
-	con->out_kvec_bytes += sizeof(con->out_connect);
-	con->out_kvec_cur = con->out_kvec;
-	con->out_more = 0;
-	set_bit(WRITE_PENDING, &con->state);
-
-	prepare_connect_authorizer(con);
-}
-
-
-/*
- * write as much of pending kvecs to the socket as we can.
- *  1 -> done
- *  0 -> socket full, but more to do
- * <0 -> error
- */
-static int write_partial_kvec(struct ceph_connection *con)
-{
-	int ret;
-
-	dout("write_partial_kvec %p %d left\n", con, con->out_kvec_bytes);
-	while (con->out_kvec_bytes > 0) {
-		ret = ceph_tcp_sendmsg(con->sock, con->out_kvec_cur,
-				       con->out_kvec_left, con->out_kvec_bytes,
-				       con->out_more);
-		if (ret <= 0)
-			goto out;
-		con->out_kvec_bytes -= ret;
-		if (con->out_kvec_bytes == 0)
-			break;            /* done */
-		while (ret > 0) {
-			if (ret >= con->out_kvec_cur->iov_len) {
-				ret -= con->out_kvec_cur->iov_len;
-				con->out_kvec_cur++;
-				con->out_kvec_left--;
-			} else {
-				con->out_kvec_cur->iov_len -= ret;
-				con->out_kvec_cur->iov_base += ret;
-				ret = 0;
-				break;
-			}
-		}
-	}
-	con->out_kvec_left = 0;
-	con->out_kvec_is_msg = false;
-	ret = 1;
-out:
-	dout("write_partial_kvec %p %d left in %d kvecs ret = %d\n", con,
-	     con->out_kvec_bytes, con->out_kvec_left, ret);
-	return ret;  /* done! */
-}
-
-/*
- * Write as much message data payload as we can.  If we finish, queue
- * up the footer.
- *  1 -> done, footer is now queued in out_kvec[].
- *  0 -> socket full, but more to do
- * <0 -> error
- */
-static int write_partial_msg_pages(struct ceph_connection *con)
-{
-	struct ceph_msg *msg = con->out_msg;
-	unsigned data_len = le32_to_cpu(msg->hdr.data_len);
-	size_t len;
-	int crc = con->msgr->nocrc;
-	int ret;
-
-	dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n",
-	     con, con->out_msg, con->out_msg_pos.page, con->out_msg->nr_pages,
-	     con->out_msg_pos.page_pos);
-
-	while (con->out_msg_pos.page < con->out_msg->nr_pages) {
-		struct page *page = NULL;
-		void *kaddr = NULL;
-
-		/*
-		 * if we are calculating the data crc (the default), we need
-		 * to map the page.  if our pages[] has been revoked, use the
-		 * zero page.
-		 */
-		if (msg->pages) {
-			page = msg->pages[con->out_msg_pos.page];
-			if (crc)
-				kaddr = kmap(page);
-		} else if (msg->pagelist) {
-			page = list_first_entry(&msg->pagelist->head,
-						struct page, lru);
-			if (crc)
-				kaddr = kmap(page);
-		} else {
-			page = con->msgr->zero_page;
-			if (crc)
-				kaddr = page_address(con->msgr->zero_page);
-		}
-		len = min((int)(PAGE_SIZE - con->out_msg_pos.page_pos),
-			  (int)(data_len - con->out_msg_pos.data_pos));
-		if (crc && !con->out_msg_pos.did_page_crc) {
-			void *base = kaddr + con->out_msg_pos.page_pos;
-			u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc);
-
-			BUG_ON(kaddr == NULL);
-			con->out_msg->footer.data_crc =
-				cpu_to_le32(crc32c(tmpcrc, base, len));
-			con->out_msg_pos.did_page_crc = 1;
-		}
-
-		ret = kernel_sendpage(con->sock, page,
-				      con->out_msg_pos.page_pos, len,
-				      MSG_DONTWAIT | MSG_NOSIGNAL |
-				      MSG_MORE);
-
-		if (crc && (msg->pages || msg->pagelist))
-			kunmap(page);
-
-		if (ret <= 0)
-			goto out;
-
-		con->out_msg_pos.data_pos += ret;
-		con->out_msg_pos.page_pos += ret;
-		if (ret == len) {
-			con->out_msg_pos.page_pos = 0;
-			con->out_msg_pos.page++;
-			con->out_msg_pos.did_page_crc = 0;
-			if (msg->pagelist)
-				list_move_tail(&page->lru,
-					       &msg->pagelist->head);
-		}
-	}
-
-	dout("write_partial_msg_pages %p msg %p done\n", con, msg);
-
-	/* prepare and queue up footer, too */
-	if (!crc)
-		con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC;
-	con->out_kvec_bytes = 0;
-	con->out_kvec_left = 0;
-	con->out_kvec_cur = con->out_kvec;
-	prepare_write_message_footer(con, 0);
-	ret = 1;
-out:
-	return ret;
-}
-
-/*
- * write some zeros
- */
-static int write_partial_skip(struct ceph_connection *con)
-{
-	int ret;
-
-	while (con->out_skip > 0) {
-		struct kvec iov = {
-			.iov_base = page_address(con->msgr->zero_page),
-			.iov_len = min(con->out_skip, (int)PAGE_CACHE_SIZE)
-		};
-
-		ret = ceph_tcp_sendmsg(con->sock, &iov, 1, iov.iov_len, 1);
-		if (ret <= 0)
-			goto out;
-		con->out_skip -= ret;
-	}
-	ret = 1;
-out:
-	return ret;
-}
-
-/*
- * Prepare to read connection handshake, or an ack.
- */
-static void prepare_read_banner(struct ceph_connection *con)
-{
-	dout("prepare_read_banner %p\n", con);
-	con->in_base_pos = 0;
-}
-
-static void prepare_read_connect(struct ceph_connection *con)
-{
-	dout("prepare_read_connect %p\n", con);
-	con->in_base_pos = 0;
-}
-
-static void prepare_read_ack(struct ceph_connection *con)
-{
-	dout("prepare_read_ack %p\n", con);
-	con->in_base_pos = 0;
-}
-
-static void prepare_read_tag(struct ceph_connection *con)
-{
-	dout("prepare_read_tag %p\n", con);
-	con->in_base_pos = 0;
-	con->in_tag = CEPH_MSGR_TAG_READY;
-}
-
-/*
- * Prepare to read a message.
- */
-static int prepare_read_message(struct ceph_connection *con)
-{
-	dout("prepare_read_message %p\n", con);
-	BUG_ON(con->in_msg != NULL);
-	con->in_base_pos = 0;
-	con->in_front_crc = con->in_middle_crc = con->in_data_crc = 0;
-	return 0;
-}
-
-
-static int read_partial(struct ceph_connection *con,
-			int *to, int size, void *object)
-{
-	*to += size;
-	while (con->in_base_pos < *to) {
-		int left = *to - con->in_base_pos;
-		int have = size - left;
-		int ret = ceph_tcp_recvmsg(con->sock, object + have, left);
-		if (ret <= 0)
-			return ret;
-		con->in_base_pos += ret;
-	}
-	return 1;
-}
-
-
-/*
- * Read all or part of the connect-side handshake on a new connection
- */
-static int read_partial_banner(struct ceph_connection *con)
-{
-	int ret, to = 0;
-
-	dout("read_partial_banner %p at %d\n", con, con->in_base_pos);
-
-	/* peer's banner */
-	ret = read_partial(con, &to, strlen(CEPH_BANNER), con->in_banner);
-	if (ret <= 0)
-		goto out;
-	ret = read_partial(con, &to, sizeof(con->actual_peer_addr),
-			   &con->actual_peer_addr);
-	if (ret <= 0)
-		goto out;
-	ret = read_partial(con, &to, sizeof(con->peer_addr_for_me),
-			   &con->peer_addr_for_me);
-	if (ret <= 0)
-		goto out;
-out:
-	return ret;
-}
-
-static int read_partial_connect(struct ceph_connection *con)
-{
-	int ret, to = 0;
-
-	dout("read_partial_connect %p at %d\n", con, con->in_base_pos);
-
-	ret = read_partial(con, &to, sizeof(con->in_reply), &con->in_reply);
-	if (ret <= 0)
-		goto out;
-	ret = read_partial(con, &to, le32_to_cpu(con->in_reply.authorizer_len),
-			   con->auth_reply_buf);
-	if (ret <= 0)
-		goto out;
-
-	dout("read_partial_connect %p tag %d, con_seq = %u, g_seq = %u\n",
-	     con, (int)con->in_reply.tag,
-	     le32_to_cpu(con->in_reply.connect_seq),
-	     le32_to_cpu(con->in_reply.global_seq));
-out:
-	return ret;
-
-}
-
-/*
- * Verify the hello banner looks okay.
- */
-static int verify_hello(struct ceph_connection *con)
-{
-	if (memcmp(con->in_banner, CEPH_BANNER, strlen(CEPH_BANNER))) {
-		pr_err("connect to %s got bad banner\n",
-		       pr_addr(&con->peer_addr.in_addr));
-		con->error_msg = "protocol error, bad banner";
-		return -1;
-	}
-	return 0;
-}
-
-static bool addr_is_blank(struct sockaddr_storage *ss)
-{
-	switch (ss->ss_family) {
-	case AF_INET:
-		return ((struct sockaddr_in *)ss)->sin_addr.s_addr == 0;
-	case AF_INET6:
-		return
-		     ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[0] == 0 &&
-		     ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[1] == 0 &&
-		     ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[2] == 0 &&
-		     ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[3] == 0;
-	}
-	return false;
-}
-
-static int addr_port(struct sockaddr_storage *ss)
-{
-	switch (ss->ss_family) {
-	case AF_INET:
-		return ntohs(((struct sockaddr_in *)ss)->sin_port);
-	case AF_INET6:
-		return ntohs(((struct sockaddr_in6 *)ss)->sin6_port);
-	}
-	return 0;
-}
-
-static void addr_set_port(struct sockaddr_storage *ss, int p)
-{
-	switch (ss->ss_family) {
-	case AF_INET:
-		((struct sockaddr_in *)ss)->sin_port = htons(p);
-	case AF_INET6:
-		((struct sockaddr_in6 *)ss)->sin6_port = htons(p);
-	}
-}
-
-/*
- * Parse an ip[:port] list into an addr array.  Use the default
- * monitor port if a port isn't specified.
- */
-int ceph_parse_ips(const char *c, const char *end,
-		   struct ceph_entity_addr *addr,
-		   int max_count, int *count)
-{
-	int i;
-	const char *p = c;
-
-	dout("parse_ips on '%.*s'\n", (int)(end-c), c);
-	for (i = 0; i < max_count; i++) {
-		const char *ipend;
-		struct sockaddr_storage *ss = &addr[i].in_addr;
-		struct sockaddr_in *in4 = (void *)ss;
-		struct sockaddr_in6 *in6 = (void *)ss;
-		int port;
-		char delim = ',';
-
-		if (*p == '[') {
-			delim = ']';
-			p++;
-		}
-
-		memset(ss, 0, sizeof(*ss));
-		if (in4_pton(p, end - p, (u8 *)&in4->sin_addr.s_addr,
-			     delim, &ipend))
-			ss->ss_family = AF_INET;
-		else if (in6_pton(p, end - p, (u8 *)&in6->sin6_addr.s6_addr,
-				  delim, &ipend))
-			ss->ss_family = AF_INET6;
-		else
-			goto bad;
-		p = ipend;
-
-		if (delim == ']') {
-			if (*p != ']') {
-				dout("missing matching ']'\n");
-				goto bad;
-			}
-			p++;
-		}
-
-		/* port? */
-		if (p < end && *p == ':') {
-			port = 0;
-			p++;
-			while (p < end && *p >= '0' && *p <= '9') {
-				port = (port * 10) + (*p - '0');
-				p++;
-			}
-			if (port > 65535 || port == 0)
-				goto bad;
-		} else {
-			port = CEPH_MON_PORT;
-		}
-
-		addr_set_port(ss, port);
-
-		dout("parse_ips got %s\n", pr_addr(ss));
-
-		if (p == end)
-			break;
-		if (*p != ',')
-			goto bad;
-		p++;
-	}
-
-	if (p != end)
-		goto bad;
-
-	if (count)
-		*count = i + 1;
-	return 0;
-
-bad:
-	pr_err("parse_ips bad ip '%.*s'\n", (int)(end - c), c);
-	return -EINVAL;
-}
-
-static int process_banner(struct ceph_connection *con)
-{
-	dout("process_banner on %p\n", con);
-
-	if (verify_hello(con) < 0)
-		return -1;
-
-	ceph_decode_addr(&con->actual_peer_addr);
-	ceph_decode_addr(&con->peer_addr_for_me);
-
-	/*
-	 * Make sure the other end is who we wanted.  note that the other
-	 * end may not yet know their ip address, so if it's 0.0.0.0, give
-	 * them the benefit of the doubt.
-	 */
-	if (memcmp(&con->peer_addr, &con->actual_peer_addr,
-		   sizeof(con->peer_addr)) != 0 &&
-	    !(addr_is_blank(&con->actual_peer_addr.in_addr) &&
-	      con->actual_peer_addr.nonce == con->peer_addr.nonce)) {
-		pr_warning("wrong peer, want %s/%d, got %s/%d\n",
-			   pr_addr(&con->peer_addr.in_addr),
-			   (int)le32_to_cpu(con->peer_addr.nonce),
-			   pr_addr(&con->actual_peer_addr.in_addr),
-			   (int)le32_to_cpu(con->actual_peer_addr.nonce));
-		con->error_msg = "wrong peer at address";
-		return -1;
-	}
-
-	/*
-	 * did we learn our address?
-	 */
-	if (addr_is_blank(&con->msgr->inst.addr.in_addr)) {
-		int port = addr_port(&con->msgr->inst.addr.in_addr);
-
-		memcpy(&con->msgr->inst.addr.in_addr,
-		       &con->peer_addr_for_me.in_addr,
-		       sizeof(con->peer_addr_for_me.in_addr));
-		addr_set_port(&con->msgr->inst.addr.in_addr, port);
-		encode_my_addr(con->msgr);
-		dout("process_banner learned my addr is %s\n",
-		     pr_addr(&con->msgr->inst.addr.in_addr));
-	}
-
-	set_bit(NEGOTIATING, &con->state);
-	prepare_read_connect(con);
-	return 0;
-}
-
-static void fail_protocol(struct ceph_connection *con)
-{
-	reset_connection(con);
-	set_bit(CLOSED, &con->state);  /* in case there's queued work */
-
-	mutex_unlock(&con->mutex);
-	if (con->ops->bad_proto)
-		con->ops->bad_proto(con);
-	mutex_lock(&con->mutex);
-}
-
-static int process_connect(struct ceph_connection *con)
-{
-	u64 sup_feat = CEPH_FEATURE_SUPPORTED;
-	u64 req_feat = CEPH_FEATURE_REQUIRED;
-	u64 server_feat = le64_to_cpu(con->in_reply.features);
-
-	dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
-
-	switch (con->in_reply.tag) {
-	case CEPH_MSGR_TAG_FEATURES:
-		pr_err("%s%lld %s feature set mismatch,"
-		       " my %llx < server's %llx, missing %llx\n",
-		       ENTITY_NAME(con->peer_name),
-		       pr_addr(&con->peer_addr.in_addr),
-		       sup_feat, server_feat, server_feat & ~sup_feat);
-		con->error_msg = "missing required protocol features";
-		fail_protocol(con);
-		return -1;
-
-	case CEPH_MSGR_TAG_BADPROTOVER:
-		pr_err("%s%lld %s protocol version mismatch,"
-		       " my %d != server's %d\n",
-		       ENTITY_NAME(con->peer_name),
-		       pr_addr(&con->peer_addr.in_addr),
-		       le32_to_cpu(con->out_connect.protocol_version),
-		       le32_to_cpu(con->in_reply.protocol_version));
-		con->error_msg = "protocol version mismatch";
-		fail_protocol(con);
-		return -1;
-
-	case CEPH_MSGR_TAG_BADAUTHORIZER:
-		con->auth_retry++;
-		dout("process_connect %p got BADAUTHORIZER attempt %d\n", con,
-		     con->auth_retry);
-		if (con->auth_retry == 2) {
-			con->error_msg = "connect authorization failure";
-			reset_connection(con);
-			set_bit(CLOSED, &con->state);
-			return -1;
-		}
-		con->auth_retry = 1;
-		prepare_write_connect(con->msgr, con, 0);
-		prepare_read_connect(con);
-		break;
-
-	case CEPH_MSGR_TAG_RESETSESSION:
-		/*
-		 * If we connected with a large connect_seq but the peer
-		 * has no record of a session with us (no connection, or
-		 * connect_seq == 0), they will send RESETSESION to indicate
-		 * that they must have reset their session, and may have
-		 * dropped messages.
-		 */
-		dout("process_connect got RESET peer seq %u\n",
-		     le32_to_cpu(con->in_connect.connect_seq));
-		pr_err("%s%lld %s connection reset\n",
-		       ENTITY_NAME(con->peer_name),
-		       pr_addr(&con->peer_addr.in_addr));
-		reset_connection(con);
-		prepare_write_connect(con->msgr, con, 0);
-		prepare_read_connect(con);
-
-		/* Tell ceph about it. */
-		mutex_unlock(&con->mutex);
-		pr_info("reset on %s%lld\n", ENTITY_NAME(con->peer_name));
-		if (con->ops->peer_reset)
-			con->ops->peer_reset(con);
-		mutex_lock(&con->mutex);
-		break;
-
-	case CEPH_MSGR_TAG_RETRY_SESSION:
-		/*
-		 * If we sent a smaller connect_seq than the peer has, try
-		 * again with a larger value.
-		 */
-		dout("process_connect got RETRY my seq = %u, peer_seq = %u\n",
-		     le32_to_cpu(con->out_connect.connect_seq),
-		     le32_to_cpu(con->in_connect.connect_seq));
-		con->connect_seq = le32_to_cpu(con->in_connect.connect_seq);
-		prepare_write_connect(con->msgr, con, 0);
-		prepare_read_connect(con);
-		break;
-
-	case CEPH_MSGR_TAG_RETRY_GLOBAL:
-		/*
-		 * If we sent a smaller global_seq than the peer has, try
-		 * again with a larger value.
-		 */
-		dout("process_connect got RETRY_GLOBAL my %u peer_gseq %u\n",
-		     con->peer_global_seq,
-		     le32_to_cpu(con->in_connect.global_seq));
-		get_global_seq(con->msgr,
-			       le32_to_cpu(con->in_connect.global_seq));
-		prepare_write_connect(con->msgr, con, 0);
-		prepare_read_connect(con);
-		break;
-
-	case CEPH_MSGR_TAG_READY:
-		if (req_feat & ~server_feat) {
-			pr_err("%s%lld %s protocol feature mismatch,"
-			       " my required %llx > server's %llx, need %llx\n",
-			       ENTITY_NAME(con->peer_name),
-			       pr_addr(&con->peer_addr.in_addr),
-			       req_feat, server_feat, req_feat & ~server_feat);
-			con->error_msg = "missing required protocol features";
-			fail_protocol(con);
-			return -1;
-		}
-		clear_bit(CONNECTING, &con->state);
-		con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq);
-		con->connect_seq++;
-		con->peer_features = server_feat;
-		dout("process_connect got READY gseq %d cseq %d (%d)\n",
-		     con->peer_global_seq,
-		     le32_to_cpu(con->in_reply.connect_seq),
-		     con->connect_seq);
-		WARN_ON(con->connect_seq !=
-			le32_to_cpu(con->in_reply.connect_seq));
-
-		if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY)
-			set_bit(LOSSYTX, &con->state);
-
-		prepare_read_tag(con);
-		break;
-
-	case CEPH_MSGR_TAG_WAIT:
-		/*
-		 * If there is a connection race (we are opening
-		 * connections to each other), one of us may just have
-		 * to WAIT.  This shouldn't happen if we are the
-		 * client.
-		 */
-		pr_err("process_connect peer connecting WAIT\n");
-
-	default:
-		pr_err("connect protocol error, will retry\n");
-		con->error_msg = "protocol error, garbage tag during connect";
-		return -1;
-	}
-	return 0;
-}
-
-
-/*
- * read (part of) an ack
- */
-static int read_partial_ack(struct ceph_connection *con)
-{
-	int to = 0;
-
-	return read_partial(con, &to, sizeof(con->in_temp_ack),
-			    &con->in_temp_ack);
-}
-
-
-/*
- * We can finally discard anything that's been acked.
- */
-static void process_ack(struct ceph_connection *con)
-{
-	struct ceph_msg *m;
-	u64 ack = le64_to_cpu(con->in_temp_ack);
-	u64 seq;
-
-	while (!list_empty(&con->out_sent)) {
-		m = list_first_entry(&con->out_sent, struct ceph_msg,
-				     list_head);
-		seq = le64_to_cpu(m->hdr.seq);
-		if (seq > ack)
-			break;
-		dout("got ack for seq %llu type %d at %p\n", seq,
-		     le16_to_cpu(m->hdr.type), m);
-		ceph_msg_remove(m);
-	}
-	prepare_read_tag(con);
-}
-
-
-
-
-static int read_partial_message_section(struct ceph_connection *con,
-					struct kvec *section,
-					unsigned int sec_len, u32 *crc)
-{
-	int left;
-	int ret;
-
-	BUG_ON(!section);
-
-	while (section->iov_len < sec_len) {
-		BUG_ON(section->iov_base == NULL);
-		left = sec_len - section->iov_len;
-		ret = ceph_tcp_recvmsg(con->sock, (char *)section->iov_base +
-				       section->iov_len, left);
-		if (ret <= 0)
-			return ret;
-		section->iov_len += ret;
-		if (section->iov_len == sec_len)
-			*crc = crc32c(0, section->iov_base,
-				      section->iov_len);
-	}
-
-	return 1;
-}
-
-static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con,
-				struct ceph_msg_header *hdr,
-				int *skip);
-/*
- * read (part of) a message.
- */
-static int read_partial_message(struct ceph_connection *con)
-{
-	struct ceph_msg *m = con->in_msg;
-	void *p;
-	int ret;
-	int to, left;
-	unsigned front_len, middle_len, data_len, data_off;
-	int datacrc = con->msgr->nocrc;
-	int skip;
-	u64 seq;
-
-	dout("read_partial_message con %p msg %p\n", con, m);
-
-	/* header */
-	while (con->in_base_pos < sizeof(con->in_hdr)) {
-		left = sizeof(con->in_hdr) - con->in_base_pos;
-		ret = ceph_tcp_recvmsg(con->sock,
-				       (char *)&con->in_hdr + con->in_base_pos,
-				       left);
-		if (ret <= 0)
-			return ret;
-		con->in_base_pos += ret;
-		if (con->in_base_pos == sizeof(con->in_hdr)) {
-			u32 crc = crc32c(0, (void *)&con->in_hdr,
-				 sizeof(con->in_hdr) - sizeof(con->in_hdr.crc));
-			if (crc != le32_to_cpu(con->in_hdr.crc)) {
-				pr_err("read_partial_message bad hdr "
-				       " crc %u != expected %u\n",
-				       crc, con->in_hdr.crc);
-				return -EBADMSG;
-			}
-		}
-	}
-	front_len = le32_to_cpu(con->in_hdr.front_len);
-	if (front_len > CEPH_MSG_MAX_FRONT_LEN)
-		return -EIO;
-	middle_len = le32_to_cpu(con->in_hdr.middle_len);
-	if (middle_len > CEPH_MSG_MAX_DATA_LEN)
-		return -EIO;
-	data_len = le32_to_cpu(con->in_hdr.data_len);
-	if (data_len > CEPH_MSG_MAX_DATA_LEN)
-		return -EIO;
-	data_off = le16_to_cpu(con->in_hdr.data_off);
-
-	/* verify seq# */
-	seq = le64_to_cpu(con->in_hdr.seq);
-	if ((s64)seq - (s64)con->in_seq < 1) {
-		pr_info("skipping %s%lld %s seq %lld, expected %lld\n",
-			ENTITY_NAME(con->peer_name),
-			pr_addr(&con->peer_addr.in_addr),
-			seq, con->in_seq + 1);
-		con->in_base_pos = -front_len - middle_len - data_len -
-			sizeof(m->footer);
-		con->in_tag = CEPH_MSGR_TAG_READY;
-		con->in_seq++;
-		return 0;
-	} else if ((s64)seq - (s64)con->in_seq > 1) {
-		pr_err("read_partial_message bad seq %lld expected %lld\n",
-		       seq, con->in_seq + 1);
-		con->error_msg = "bad message sequence # for incoming message";
-		return -EBADMSG;
-	}
-
-	/* allocate message? */
-	if (!con->in_msg) {
-		dout("got hdr type %d front %d data %d\n", con->in_hdr.type,
-		     con->in_hdr.front_len, con->in_hdr.data_len);
-		skip = 0;
-		con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip);
-		if (skip) {
-			/* skip this message */
-			dout("alloc_msg said skip message\n");
-			BUG_ON(con->in_msg);
-			con->in_base_pos = -front_len - middle_len - data_len -
-				sizeof(m->footer);
-			con->in_tag = CEPH_MSGR_TAG_READY;
-			con->in_seq++;
-			return 0;
-		}
-		if (!con->in_msg) {
-			con->error_msg =
-				"error allocating memory for incoming message";
-			return -ENOMEM;
-		}
-		m = con->in_msg;
-		m->front.iov_len = 0;    /* haven't read it yet */
-		if (m->middle)
-			m->middle->vec.iov_len = 0;
-
-		con->in_msg_pos.page = 0;
-		con->in_msg_pos.page_pos = data_off & ~PAGE_MASK;
-		con->in_msg_pos.data_pos = 0;
-	}
-
-	/* front */
-	ret = read_partial_message_section(con, &m->front, front_len,
-					   &con->in_front_crc);
-	if (ret <= 0)
-		return ret;
-
-	/* middle */
-	if (m->middle) {
-		ret = read_partial_message_section(con, &m->middle->vec,
-						   middle_len,
-						   &con->in_middle_crc);
-		if (ret <= 0)
-			return ret;
-	}
-
-	/* (page) data */
-	while (con->in_msg_pos.data_pos < data_len) {
-		left = min((int)(data_len - con->in_msg_pos.data_pos),
-			   (int)(PAGE_SIZE - con->in_msg_pos.page_pos));
-		BUG_ON(m->pages == NULL);
-		p = kmap(m->pages[con->in_msg_pos.page]);
-		ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos,
-				       left);
-		if (ret > 0 && datacrc)
-			con->in_data_crc =
-				crc32c(con->in_data_crc,
-					  p + con->in_msg_pos.page_pos, ret);
-		kunmap(m->pages[con->in_msg_pos.page]);
-		if (ret <= 0)
-			return ret;
-		con->in_msg_pos.data_pos += ret;
-		con->in_msg_pos.page_pos += ret;
-		if (con->in_msg_pos.page_pos == PAGE_SIZE) {
-			con->in_msg_pos.page_pos = 0;
-			con->in_msg_pos.page++;
-		}
-	}
-
-	/* footer */
-	to = sizeof(m->hdr) + sizeof(m->footer);
-	while (con->in_base_pos < to) {
-		left = to - con->in_base_pos;
-		ret = ceph_tcp_recvmsg(con->sock, (char *)&m->footer +
-				       (con->in_base_pos - sizeof(m->hdr)),
-				       left);
-		if (ret <= 0)
-			return ret;
-		con->in_base_pos += ret;
-	}
-	dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n",
-	     m, front_len, m->footer.front_crc, middle_len,
-	     m->footer.middle_crc, data_len, m->footer.data_crc);
-
-	/* crc ok? */
-	if (con->in_front_crc != le32_to_cpu(m->footer.front_crc)) {
-		pr_err("read_partial_message %p front crc %u != exp. %u\n",
-		       m, con->in_front_crc, m->footer.front_crc);
-		return -EBADMSG;
-	}
-	if (con->in_middle_crc != le32_to_cpu(m->footer.middle_crc)) {
-		pr_err("read_partial_message %p middle crc %u != exp %u\n",
-		       m, con->in_middle_crc, m->footer.middle_crc);
-		return -EBADMSG;
-	}
-	if (datacrc &&
-	    (m->footer.flags & CEPH_MSG_FOOTER_NOCRC) == 0 &&
-	    con->in_data_crc != le32_to_cpu(m->footer.data_crc)) {
-		pr_err("read_partial_message %p data crc %u != exp. %u\n", m,
-		       con->in_data_crc, le32_to_cpu(m->footer.data_crc));
-		return -EBADMSG;
-	}
-
-	return 1; /* done! */
-}
-
-/*
- * Process message.  This happens in the worker thread.  The callback should
- * be careful not to do anything that waits on other incoming messages or it
- * may deadlock.
- */
-static void process_message(struct ceph_connection *con)
-{
-	struct ceph_msg *msg;
-
-	msg = con->in_msg;
-	con->in_msg = NULL;
-
-	/* if first message, set peer_name */
-	if (con->peer_name.type == 0)
-		con->peer_name = msg->hdr.src;
-
-	con->in_seq++;
-	mutex_unlock(&con->mutex);
-
-	dout("===== %p %llu from %s%lld %d=%s len %d+%d (%u %u %u) =====\n",
-	     msg, le64_to_cpu(msg->hdr.seq),
-	     ENTITY_NAME(msg->hdr.src),
-	     le16_to_cpu(msg->hdr.type),
-	     ceph_msg_type_name(le16_to_cpu(msg->hdr.type)),
-	     le32_to_cpu(msg->hdr.front_len),
-	     le32_to_cpu(msg->hdr.data_len),
-	     con->in_front_crc, con->in_middle_crc, con->in_data_crc);
-	con->ops->dispatch(con, msg);
-
-	mutex_lock(&con->mutex);
-	prepare_read_tag(con);
-}
-
-
-/*
- * Write something to the socket.  Called in a worker thread when the
- * socket appears to be writeable and we have something ready to send.
- */
-static int try_write(struct ceph_connection *con)
-{
-	struct ceph_messenger *msgr = con->msgr;
-	int ret = 1;
-
-	dout("try_write start %p state %lu nref %d\n", con, con->state,
-	     atomic_read(&con->nref));
-
-more:
-	dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes);
-
-	/* open the socket first? */
-	if (con->sock == NULL) {
-		/*
-		 * if we were STANDBY and are reconnecting _this_
-		 * connection, bump connect_seq now.  Always bump
-		 * global_seq.
-		 */
-		if (test_and_clear_bit(STANDBY, &con->state))
-			con->connect_seq++;
-
-		prepare_write_banner(msgr, con);
-		prepare_write_connect(msgr, con, 1);
-		prepare_read_banner(con);
-		set_bit(CONNECTING, &con->state);
-		clear_bit(NEGOTIATING, &con->state);
-
-		BUG_ON(con->in_msg);
-		con->in_tag = CEPH_MSGR_TAG_READY;
-		dout("try_write initiating connect on %p new state %lu\n",
-		     con, con->state);
-		con->sock = ceph_tcp_connect(con);
-		if (IS_ERR(con->sock)) {
-			con->sock = NULL;
-			con->error_msg = "connect error";
-			ret = -1;
-			goto out;
-		}
-	}
-
-more_kvec:
-	/* kvec data queued? */
-	if (con->out_skip) {
-		ret = write_partial_skip(con);
-		if (ret <= 0)
-			goto done;
-		if (ret < 0) {
-			dout("try_write write_partial_skip err %d\n", ret);
-			goto done;
-		}
-	}
-	if (con->out_kvec_left) {
-		ret = write_partial_kvec(con);
-		if (ret <= 0)
-			goto done;
-	}
-
-	/* msg pages? */
-	if (con->out_msg) {
-		if (con->out_msg_done) {
-			ceph_msg_put(con->out_msg);
-			con->out_msg = NULL;   /* we're done with this one */
-			goto do_next;
-		}
-
-		ret = write_partial_msg_pages(con);
-		if (ret == 1)
-			goto more_kvec;  /* we need to send the footer, too! */
-		if (ret == 0)
-			goto done;
-		if (ret < 0) {
-			dout("try_write write_partial_msg_pages err %d\n",
-			     ret);
-			goto done;
-		}
-	}
-
-do_next:
-	if (!test_bit(CONNECTING, &con->state)) {
-		/* is anything else pending? */
-		if (!list_empty(&con->out_queue)) {
-			prepare_write_message(con);
-			goto more;
-		}
-		if (con->in_seq > con->in_seq_acked) {
-			prepare_write_ack(con);
-			goto more;
-		}
-		if (test_and_clear_bit(KEEPALIVE_PENDING, &con->state)) {
-			prepare_write_keepalive(con);
-			goto more;
-		}
-	}
-
-	/* Nothing to do! */
-	clear_bit(WRITE_PENDING, &con->state);
-	dout("try_write nothing else to write.\n");
-done:
-	ret = 0;
-out:
-	dout("try_write done on %p\n", con);
-	return ret;
-}
-
-
-
-/*
- * Read what we can from the socket.
- */
-static int try_read(struct ceph_connection *con)
-{
-	int ret = -1;
-
-	if (!con->sock)
-		return 0;
-
-	if (test_bit(STANDBY, &con->state))
-		return 0;
-
-	dout("try_read start on %p\n", con);
-
-more:
-	dout("try_read tag %d in_base_pos %d\n", (int)con->in_tag,
-	     con->in_base_pos);
-	if (test_bit(CONNECTING, &con->state)) {
-		if (!test_bit(NEGOTIATING, &con->state)) {
-			dout("try_read connecting\n");
-			ret = read_partial_banner(con);
-			if (ret <= 0)
-				goto done;
-			if (process_banner(con) < 0) {
-				ret = -1;
-				goto out;
-			}
-		}
-		ret = read_partial_connect(con);
-		if (ret <= 0)
-			goto done;
-		if (process_connect(con) < 0) {
-			ret = -1;
-			goto out;
-		}
-		goto more;
-	}
-
-	if (con->in_base_pos < 0) {
-		/*
-		 * skipping + discarding content.
-		 *
-		 * FIXME: there must be a better way to do this!
-		 */
-		static char buf[1024];
-		int skip = min(1024, -con->in_base_pos);
-		dout("skipping %d / %d bytes\n", skip, -con->in_base_pos);
-		ret = ceph_tcp_recvmsg(con->sock, buf, skip);
-		if (ret <= 0)
-			goto done;
-		con->in_base_pos += ret;
-		if (con->in_base_pos)
-			goto more;
-	}
-	if (con->in_tag == CEPH_MSGR_TAG_READY) {
-		/*
-		 * what's next?
-		 */
-		ret = ceph_tcp_recvmsg(con->sock, &con->in_tag, 1);
-		if (ret <= 0)
-			goto done;
-		dout("try_read got tag %d\n", (int)con->in_tag);
-		switch (con->in_tag) {
-		case CEPH_MSGR_TAG_MSG:
-			prepare_read_message(con);
-			break;
-		case CEPH_MSGR_TAG_ACK:
-			prepare_read_ack(con);
-			break;
-		case CEPH_MSGR_TAG_CLOSE:
-			set_bit(CLOSED, &con->state);   /* fixme */
-			goto done;
-		default:
-			goto bad_tag;
-		}
-	}
-	if (con->in_tag == CEPH_MSGR_TAG_MSG) {
-		ret = read_partial_message(con);
-		if (ret <= 0) {
-			switch (ret) {
-			case -EBADMSG:
-				con->error_msg = "bad crc";
-				ret = -EIO;
-				goto out;
-			case -EIO:
-				con->error_msg = "io error";
-				goto out;
-			default:
-				goto done;
-			}
-		}
-		if (con->in_tag == CEPH_MSGR_TAG_READY)
-			goto more;
-		process_message(con);
-		goto more;
-	}
-	if (con->in_tag == CEPH_MSGR_TAG_ACK) {
-		ret = read_partial_ack(con);
-		if (ret <= 0)
-			goto done;
-		process_ack(con);
-		goto more;
-	}
-
-done:
-	ret = 0;
-out:
-	dout("try_read done on %p\n", con);
-	return ret;
-
-bad_tag:
-	pr_err("try_read bad con->in_tag = %d\n", (int)con->in_tag);
-	con->error_msg = "protocol error, garbage tag";
-	ret = -1;
-	goto out;
-}
-
-
-/*
- * Atomically queue work on a connection.  Bump @con reference to
- * avoid races with connection teardown.
- *
- * There is some trickery going on with QUEUED and BUSY because we
- * only want a _single_ thread operating on each connection at any
- * point in time, but we want to use all available CPUs.
- *
- * The worker thread only proceeds if it can atomically set BUSY.  It
- * clears QUEUED and does it's thing.  When it thinks it's done, it
- * clears BUSY, then rechecks QUEUED.. if it's set again, it loops
- * (tries again to set BUSY).
- *
- * To queue work, we first set QUEUED, _then_ if BUSY isn't set, we
- * try to queue work.  If that fails (work is already queued, or BUSY)
- * we give up (work also already being done or is queued) but leave QUEUED
- * set so that the worker thread will loop if necessary.
- */
-static void queue_con(struct ceph_connection *con)
-{
-	if (test_bit(DEAD, &con->state)) {
-		dout("queue_con %p ignoring: DEAD\n",
-		     con);
-		return;
-	}
-
-	if (!con->ops->get(con)) {
-		dout("queue_con %p ref count 0\n", con);
-		return;
-	}
-
-	set_bit(QUEUED, &con->state);
-	if (test_bit(BUSY, &con->state)) {
-		dout("queue_con %p - already BUSY\n", con);
-		con->ops->put(con);
-	} else if (!queue_work(ceph_msgr_wq, &con->work.work)) {
-		dout("queue_con %p - already queued\n", con);
-		con->ops->put(con);
-	} else {
-		dout("queue_con %p\n", con);
-	}
-}
-
-/*
- * Do some work on a connection.  Drop a connection ref when we're done.
- */
-static void con_work(struct work_struct *work)
-{
-	struct ceph_connection *con = container_of(work, struct ceph_connection,
-						   work.work);
-	int backoff = 0;
-
-more:
-	if (test_and_set_bit(BUSY, &con->state) != 0) {
-		dout("con_work %p BUSY already set\n", con);
-		goto out;
-	}
-	dout("con_work %p start, clearing QUEUED\n", con);
-	clear_bit(QUEUED, &con->state);
-
-	mutex_lock(&con->mutex);
-
-	if (test_bit(CLOSED, &con->state)) { /* e.g. if we are replaced */
-		dout("con_work CLOSED\n");
-		con_close_socket(con);
-		goto done;
-	}
-	if (test_and_clear_bit(OPENING, &con->state)) {
-		/* reopen w/ new peer */
-		dout("con_work OPENING\n");
-		con_close_socket(con);
-	}
-
-	if (test_and_clear_bit(SOCK_CLOSED, &con->state) ||
-	    try_read(con) < 0 ||
-	    try_write(con) < 0) {
-		mutex_unlock(&con->mutex);
-		backoff = 1;
-		ceph_fault(con);     /* error/fault path */
-		goto done_unlocked;
-	}
-
-done:
-	mutex_unlock(&con->mutex);
-
-done_unlocked:
-	clear_bit(BUSY, &con->state);
-	dout("con->state=%lu\n", con->state);
-	if (test_bit(QUEUED, &con->state)) {
-		if (!backoff || test_bit(OPENING, &con->state)) {
-			dout("con_work %p QUEUED reset, looping\n", con);
-			goto more;
-		}
-		dout("con_work %p QUEUED reset, but just faulted\n", con);
-		clear_bit(QUEUED, &con->state);
-	}
-	dout("con_work %p done\n", con);
-
-out:
-	con->ops->put(con);
-}
-
-
-/*
- * Generic error/fault handler.  A retry mechanism is used with
- * exponential backoff
- */
-static void ceph_fault(struct ceph_connection *con)
-{
-	pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
-	       pr_addr(&con->peer_addr.in_addr), con->error_msg);
-	dout("fault %p state %lu to peer %s\n",
-	     con, con->state, pr_addr(&con->peer_addr.in_addr));
-
-	if (test_bit(LOSSYTX, &con->state)) {
-		dout("fault on LOSSYTX channel\n");
-		goto out;
-	}
-
-	mutex_lock(&con->mutex);
-	if (test_bit(CLOSED, &con->state))
-		goto out_unlock;
-
-	con_close_socket(con);
-
-	if (con->in_msg) {
-		ceph_msg_put(con->in_msg);
-		con->in_msg = NULL;
-	}
-
-	/* Requeue anything that hasn't been acked */
-	list_splice_init(&con->out_sent, &con->out_queue);
-
-	/* If there are no messages in the queue, place the connection
-	 * in a STANDBY state (i.e., don't try to reconnect just yet). */
-	if (list_empty(&con->out_queue) && !con->out_keepalive_pending) {
-		dout("fault setting STANDBY\n");
-		set_bit(STANDBY, &con->state);
-	} else {
-		/* retry after a delay. */
-		if (con->delay == 0)
-			con->delay = BASE_DELAY_INTERVAL;
-		else if (con->delay < MAX_DELAY_INTERVAL)
-			con->delay *= 2;
-		dout("fault queueing %p delay %lu\n", con, con->delay);
-		con->ops->get(con);
-		if (queue_delayed_work(ceph_msgr_wq, &con->work,
-				       round_jiffies_relative(con->delay)) == 0)
-			con->ops->put(con);
-	}
-
-out_unlock:
-	mutex_unlock(&con->mutex);
-out:
-	/*
-	 * in case we faulted due to authentication, invalidate our
-	 * current tickets so that we can get new ones.
-	 */
-	if (con->auth_retry && con->ops->invalidate_authorizer) {
-		dout("calling invalidate_authorizer()\n");
-		con->ops->invalidate_authorizer(con);
-	}
-
-	if (con->ops->fault)
-		con->ops->fault(con);
-}
-
-
-
-/*
- * create a new messenger instance
- */
-struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr)
-{
-	struct ceph_messenger *msgr;
-
-	msgr = kzalloc(sizeof(*msgr), GFP_KERNEL);
-	if (msgr == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	spin_lock_init(&msgr->global_seq_lock);
-
-	/* the zero page is needed if a request is "canceled" while the message
-	 * is being written over the socket */
-	msgr->zero_page = __page_cache_alloc(GFP_KERNEL | __GFP_ZERO);
-	if (!msgr->zero_page) {
-		kfree(msgr);
-		return ERR_PTR(-ENOMEM);
-	}
-	kmap(msgr->zero_page);
-
-	if (myaddr)
-		msgr->inst.addr = *myaddr;
-
-	/* select a random nonce */
-	msgr->inst.addr.type = 0;
-	get_random_bytes(&msgr->inst.addr.nonce, sizeof(msgr->inst.addr.nonce));
-	encode_my_addr(msgr);
-
-	dout("messenger_create %p\n", msgr);
-	return msgr;
-}
-
-void ceph_messenger_destroy(struct ceph_messenger *msgr)
-{
-	dout("destroy %p\n", msgr);
-	kunmap(msgr->zero_page);
-	__free_page(msgr->zero_page);
-	kfree(msgr);
-	dout("destroyed messenger %p\n", msgr);
-}
-
-/*
- * Queue up an outgoing message on the given connection.
- */
-void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg)
-{
-	if (test_bit(CLOSED, &con->state)) {
-		dout("con_send %p closed, dropping %p\n", con, msg);
-		ceph_msg_put(msg);
-		return;
-	}
-
-	/* set src+dst */
-	msg->hdr.src = con->msgr->inst.name;
-
-	BUG_ON(msg->front.iov_len != le32_to_cpu(msg->hdr.front_len));
-
-	msg->needs_out_seq = true;
-
-	/* queue */
-	mutex_lock(&con->mutex);
-	BUG_ON(!list_empty(&msg->list_head));
-	list_add_tail(&msg->list_head, &con->out_queue);
-	dout("----- %p to %s%lld %d=%s len %d+%d+%d -----\n", msg,
-	     ENTITY_NAME(con->peer_name), le16_to_cpu(msg->hdr.type),
-	     ceph_msg_type_name(le16_to_cpu(msg->hdr.type)),
-	     le32_to_cpu(msg->hdr.front_len),
-	     le32_to_cpu(msg->hdr.middle_len),
-	     le32_to_cpu(msg->hdr.data_len));
-	mutex_unlock(&con->mutex);
-
-	/* if there wasn't anything waiting to send before, queue
-	 * new work */
-	if (test_and_set_bit(WRITE_PENDING, &con->state) == 0)
-		queue_con(con);
-}
-
-/*
- * Revoke a message that was previously queued for send
- */
-void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg)
-{
-	mutex_lock(&con->mutex);
-	if (!list_empty(&msg->list_head)) {
-		dout("con_revoke %p msg %p - was on queue\n", con, msg);
-		list_del_init(&msg->list_head);
-		ceph_msg_put(msg);
-		msg->hdr.seq = 0;
-	}
-	if (con->out_msg == msg) {
-		dout("con_revoke %p msg %p - was sending\n", con, msg);
-		con->out_msg = NULL;
-		if (con->out_kvec_is_msg) {
-			con->out_skip = con->out_kvec_bytes;
-			con->out_kvec_is_msg = false;
-		}
-		ceph_msg_put(msg);
-		msg->hdr.seq = 0;
-	}
-	mutex_unlock(&con->mutex);
-}
-
-/*
- * Revoke a message that we may be reading data into
- */
-void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg)
-{
-	mutex_lock(&con->mutex);
-	if (con->in_msg && con->in_msg == msg) {
-		unsigned front_len = le32_to_cpu(con->in_hdr.front_len);
-		unsigned middle_len = le32_to_cpu(con->in_hdr.middle_len);
-		unsigned data_len = le32_to_cpu(con->in_hdr.data_len);
-
-		/* skip rest of message */
-		dout("con_revoke_pages %p msg %p revoked\n", con, msg);
-			con->in_base_pos = con->in_base_pos -
-				sizeof(struct ceph_msg_header) -
-				front_len -
-				middle_len -
-				data_len -
-				sizeof(struct ceph_msg_footer);
-		ceph_msg_put(con->in_msg);
-		con->in_msg = NULL;
-		con->in_tag = CEPH_MSGR_TAG_READY;
-		con->in_seq++;
-	} else {
-		dout("con_revoke_pages %p msg %p pages %p no-op\n",
-		     con, con->in_msg, msg);
-	}
-	mutex_unlock(&con->mutex);
-}
-
-/*
- * Queue a keepalive byte to ensure the tcp connection is alive.
- */
-void ceph_con_keepalive(struct ceph_connection *con)
-{
-	if (test_and_set_bit(KEEPALIVE_PENDING, &con->state) == 0 &&
-	    test_and_set_bit(WRITE_PENDING, &con->state) == 0)
-		queue_con(con);
-}
-
-
-/*
- * construct a new message with given type, size
- * the new msg has a ref count of 1.
- */
-struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags)
-{
-	struct ceph_msg *m;
-
-	m = kmalloc(sizeof(*m), flags);
-	if (m == NULL)
-		goto out;
-	kref_init(&m->kref);
-	INIT_LIST_HEAD(&m->list_head);
-
-	m->hdr.tid = 0;
-	m->hdr.type = cpu_to_le16(type);
-	m->hdr.priority = cpu_to_le16(CEPH_MSG_PRIO_DEFAULT);
-	m->hdr.version = 0;
-	m->hdr.front_len = cpu_to_le32(front_len);
-	m->hdr.middle_len = 0;
-	m->hdr.data_len = 0;
-	m->hdr.data_off = 0;
-	m->hdr.reserved = 0;
-	m->footer.front_crc = 0;
-	m->footer.middle_crc = 0;
-	m->footer.data_crc = 0;
-	m->footer.flags = 0;
-	m->front_max = front_len;
-	m->front_is_vmalloc = false;
-	m->more_to_follow = false;
-	m->pool = NULL;
-
-	/* front */
-	if (front_len) {
-		if (front_len > PAGE_CACHE_SIZE) {
-			m->front.iov_base = __vmalloc(front_len, flags,
-						      PAGE_KERNEL);
-			m->front_is_vmalloc = true;
-		} else {
-			m->front.iov_base = kmalloc(front_len, flags);
-		}
-		if (m->front.iov_base == NULL) {
-			pr_err("msg_new can't allocate %d bytes\n",
-			     front_len);
-			goto out2;
-		}
-	} else {
-		m->front.iov_base = NULL;
-	}
-	m->front.iov_len = front_len;
-
-	/* middle */
-	m->middle = NULL;
-
-	/* data */
-	m->nr_pages = 0;
-	m->pages = NULL;
-	m->pagelist = NULL;
-
-	dout("ceph_msg_new %p front %d\n", m, front_len);
-	return m;
-
-out2:
-	ceph_msg_put(m);
-out:
-	pr_err("msg_new can't create type %d front %d\n", type, front_len);
-	return NULL;
-}
-
-/*
- * Allocate "middle" portion of a message, if it is needed and wasn't
- * allocated by alloc_msg.  This allows us to read a small fixed-size
- * per-type header in the front and then gracefully fail (i.e.,
- * propagate the error to the caller based on info in the front) when
- * the middle is too large.
- */
-static int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg)
-{
-	int type = le16_to_cpu(msg->hdr.type);
-	int middle_len = le32_to_cpu(msg->hdr.middle_len);
-
-	dout("alloc_middle %p type %d %s middle_len %d\n", msg, type,
-	     ceph_msg_type_name(type), middle_len);
-	BUG_ON(!middle_len);
-	BUG_ON(msg->middle);
-
-	msg->middle = ceph_buffer_new(middle_len, GFP_NOFS);
-	if (!msg->middle)
-		return -ENOMEM;
-	return 0;
-}
-
-/*
- * Generic message allocator, for incoming messages.
- */
-static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con,
-				struct ceph_msg_header *hdr,
-				int *skip)
-{
-	int type = le16_to_cpu(hdr->type);
-	int front_len = le32_to_cpu(hdr->front_len);
-	int middle_len = le32_to_cpu(hdr->middle_len);
-	struct ceph_msg *msg = NULL;
-	int ret;
-
-	if (con->ops->alloc_msg) {
-		mutex_unlock(&con->mutex);
-		msg = con->ops->alloc_msg(con, hdr, skip);
-		mutex_lock(&con->mutex);
-		if (!msg || *skip)
-			return NULL;
-	}
-	if (!msg) {
-		*skip = 0;
-		msg = ceph_msg_new(type, front_len, GFP_NOFS);
-		if (!msg) {
-			pr_err("unable to allocate msg type %d len %d\n",
-			       type, front_len);
-			return NULL;
-		}
-	}
-	memcpy(&msg->hdr, &con->in_hdr, sizeof(con->in_hdr));
-
-	if (middle_len && !msg->middle) {
-		ret = ceph_alloc_middle(con, msg);
-		if (ret < 0) {
-			ceph_msg_put(msg);
-			return NULL;
-		}
-	}
-
-	return msg;
-}
-
-
-/*
- * Free a generically kmalloc'd message.
- */
-void ceph_msg_kfree(struct ceph_msg *m)
-{
-	dout("msg_kfree %p\n", m);
-	if (m->front_is_vmalloc)
-		vfree(m->front.iov_base);
-	else
-		kfree(m->front.iov_base);
-	kfree(m);
-}
-
-/*
- * Drop a msg ref.  Destroy as needed.
- */
-void ceph_msg_last_put(struct kref *kref)
-{
-	struct ceph_msg *m = container_of(kref, struct ceph_msg, kref);
-
-	dout("ceph_msg_put last one on %p\n", m);
-	WARN_ON(!list_empty(&m->list_head));
-
-	/* drop middle, data, if any */
-	if (m->middle) {
-		ceph_buffer_put(m->middle);
-		m->middle = NULL;
-	}
-	m->nr_pages = 0;
-	m->pages = NULL;
-
-	if (m->pagelist) {
-		ceph_pagelist_release(m->pagelist);
-		kfree(m->pagelist);
-		m->pagelist = NULL;
-	}
-
-	if (m->pool)
-		ceph_msgpool_put(m->pool, m);
-	else
-		ceph_msg_kfree(m);
-}
-
-void ceph_msg_dump(struct ceph_msg *msg)
-{
-	pr_debug("msg_dump %p (front_max %d nr_pages %d)\n", msg,
-		 msg->front_max, msg->nr_pages);
-	print_hex_dump(KERN_DEBUG, "header: ",
-		       DUMP_PREFIX_OFFSET, 16, 1,
-		       &msg->hdr, sizeof(msg->hdr), true);
-	print_hex_dump(KERN_DEBUG, " front: ",
-		       DUMP_PREFIX_OFFSET, 16, 1,
-		       msg->front.iov_base, msg->front.iov_len, true);
-	if (msg->middle)
-		print_hex_dump(KERN_DEBUG, "middle: ",
-			       DUMP_PREFIX_OFFSET, 16, 1,
-			       msg->middle->vec.iov_base,
-			       msg->middle->vec.iov_len, true);
-	print_hex_dump(KERN_DEBUG, "footer: ",
-		       DUMP_PREFIX_OFFSET, 16, 1,
-		       &msg->footer, sizeof(msg->footer), true);
-}
diff --git a/fs/ceph/messenger.h b/fs/ceph/messenger.h
deleted file mode 100644
index 76fbc95..0000000
--- a/fs/ceph/messenger.h
+++ /dev/null
@@ -1,253 +0,0 @@
-#ifndef __FS_CEPH_MESSENGER_H
-#define __FS_CEPH_MESSENGER_H
-
-#include <linux/kref.h>
-#include <linux/mutex.h>
-#include <linux/net.h>
-#include <linux/radix-tree.h>
-#include <linux/uio.h>
-#include <linux/version.h>
-#include <linux/workqueue.h>
-
-#include "types.h"
-#include "buffer.h"
-
-struct ceph_msg;
-struct ceph_connection;
-
-extern struct workqueue_struct *ceph_msgr_wq;       /* receive work queue */
-
-/*
- * Ceph defines these callbacks for handling connection events.
- */
-struct ceph_connection_operations {
-	struct ceph_connection *(*get)(struct ceph_connection *);
-	void (*put)(struct ceph_connection *);
-
-	/* handle an incoming message. */
-	void (*dispatch) (struct ceph_connection *con, struct ceph_msg *m);
-
-	/* authorize an outgoing connection */
-	int (*get_authorizer) (struct ceph_connection *con,
-			       void **buf, int *len, int *proto,
-			       void **reply_buf, int *reply_len, int force_new);
-	int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
-	int (*invalidate_authorizer)(struct ceph_connection *con);
-
-	/* protocol version mismatch */
-	void (*bad_proto) (struct ceph_connection *con);
-
-	/* there was some error on the socket (disconnect, whatever) */
-	void (*fault) (struct ceph_connection *con);
-
-	/* a remote host as terminated a message exchange session, and messages
-	 * we sent (or they tried to send us) may be lost. */
-	void (*peer_reset) (struct ceph_connection *con);
-
-	struct ceph_msg * (*alloc_msg) (struct ceph_connection *con,
-					struct ceph_msg_header *hdr,
-					int *skip);
-};
-
-/* use format string %s%d */
-#define ENTITY_NAME(n) ceph_entity_type_name((n).type), le64_to_cpu((n).num)
-
-struct ceph_messenger {
-	struct ceph_entity_inst inst;    /* my name+address */
-	struct ceph_entity_addr my_enc_addr;
-	struct page *zero_page;          /* used in certain error cases */
-
-	bool nocrc;
-
-	/*
-	 * the global_seq counts connections i (attempt to) initiate
-	 * in order to disambiguate certain connect race conditions.
-	 */
-	u32 global_seq;
-	spinlock_t global_seq_lock;
-};
-
-/*
- * a single message.  it contains a header (src, dest, message type, etc.),
- * footer (crc values, mainly), a "front" message body, and possibly a
- * data payload (stored in some number of pages).
- */
-struct ceph_msg {
-	struct ceph_msg_header hdr;	/* header */
-	struct ceph_msg_footer footer;	/* footer */
-	struct kvec front;              /* unaligned blobs of message */
-	struct ceph_buffer *middle;
-	struct page **pages;            /* data payload.  NOT OWNER. */
-	unsigned nr_pages;              /* size of page array */
-	struct ceph_pagelist *pagelist; /* instead of pages */
-	struct list_head list_head;
-	struct kref kref;
-	bool front_is_vmalloc;
-	bool more_to_follow;
-	bool needs_out_seq;
-	int front_max;
-
-	struct ceph_msgpool *pool;
-};
-
-struct ceph_msg_pos {
-	int page, page_pos;  /* which page; offset in page */
-	int data_pos;        /* offset in data payload */
-	int did_page_crc;    /* true if we've calculated crc for current page */
-};
-
-/* ceph connection fault delay defaults, for exponential backoff */
-#define BASE_DELAY_INTERVAL	(HZ/2)
-#define MAX_DELAY_INTERVAL	(5 * 60 * HZ)
-
-/*
- * ceph_connection state bit flags
- *
- * QUEUED and BUSY are used together to ensure that only a single
- * thread is currently opening, reading or writing data to the socket.
- */
-#define LOSSYTX         0  /* we can close channel or drop messages on errors */
-#define CONNECTING	1
-#define NEGOTIATING	2
-#define KEEPALIVE_PENDING      3
-#define WRITE_PENDING	4  /* we have data ready to send */
-#define QUEUED          5  /* there is work queued on this connection */
-#define BUSY            6  /* work is being done */
-#define STANDBY		8  /* no outgoing messages, socket closed.  we keep
-			    * the ceph_connection around to maintain shared
-			    * state with the peer. */
-#define CLOSED		10 /* we've closed the connection */
-#define SOCK_CLOSED	11 /* socket state changed to closed */
-#define OPENING         13 /* open connection w/ (possibly new) peer */
-#define DEAD            14 /* dead, about to kfree */
-
-/*
- * A single connection with another host.
- *
- * We maintain a queue of outgoing messages, and some session state to
- * ensure that we can preserve the lossless, ordered delivery of
- * messages in the case of a TCP disconnect.
- */
-struct ceph_connection {
-	void *private;
-	atomic_t nref;
-
-	const struct ceph_connection_operations *ops;
-
-	struct ceph_messenger *msgr;
-	struct socket *sock;
-	unsigned long state;	/* connection state (see flags above) */
-	const char *error_msg;  /* error message, if any */
-
-	struct ceph_entity_addr peer_addr; /* peer address */
-	struct ceph_entity_name peer_name; /* peer name */
-	struct ceph_entity_addr peer_addr_for_me;
-	unsigned peer_features;
-	u32 connect_seq;      /* identify the most recent connection
-				 attempt for this connection, client */
-	u32 peer_global_seq;  /* peer's global seq for this connection */
-
-	int auth_retry;       /* true if we need a newer authorizer */
-	void *auth_reply_buf;   /* where to put the authorizer reply */
-	int auth_reply_buf_len;
-
-	struct mutex mutex;
-
-	/* out queue */
-	struct list_head out_queue;
-	struct list_head out_sent;   /* sending or sent but unacked */
-	u64 out_seq;		     /* last message queued for send */
-	bool out_keepalive_pending;
-
-	u64 in_seq, in_seq_acked;  /* last message received, acked */
-
-	/* connection negotiation temps */
-	char in_banner[CEPH_BANNER_MAX_LEN];
-	union {
-		struct {  /* outgoing connection */
-			struct ceph_msg_connect out_connect;
-			struct ceph_msg_connect_reply in_reply;
-		};
-		struct {  /* incoming */
-			struct ceph_msg_connect in_connect;
-			struct ceph_msg_connect_reply out_reply;
-		};
-	};
-	struct ceph_entity_addr actual_peer_addr;
-
-	/* message out temps */
-	struct ceph_msg *out_msg;        /* sending message (== tail of
-					    out_sent) */
-	bool out_msg_done;
-	struct ceph_msg_pos out_msg_pos;
-
-	struct kvec out_kvec[8],         /* sending header/footer data */
-		*out_kvec_cur;
-	int out_kvec_left;   /* kvec's left in out_kvec */
-	int out_skip;        /* skip this many bytes */
-	int out_kvec_bytes;  /* total bytes left */
-	bool out_kvec_is_msg; /* kvec refers to out_msg */
-	int out_more;        /* there is more data after the kvecs */
-	__le64 out_temp_ack; /* for writing an ack */
-
-	/* message in temps */
-	struct ceph_msg_header in_hdr;
-	struct ceph_msg *in_msg;
-	struct ceph_msg_pos in_msg_pos;
-	u32 in_front_crc, in_middle_crc, in_data_crc;  /* calculated crc */
-
-	char in_tag;         /* protocol control byte */
-	int in_base_pos;     /* bytes read */
-	__le64 in_temp_ack;  /* for reading an ack */
-
-	struct delayed_work work;	    /* send|recv work */
-	unsigned long       delay;          /* current delay interval */
-};
-
-
-extern const char *pr_addr(const struct sockaddr_storage *ss);
-extern int ceph_parse_ips(const char *c, const char *end,
-			  struct ceph_entity_addr *addr,
-			  int max_count, int *count);
-
-
-extern int ceph_msgr_init(void);
-extern void ceph_msgr_exit(void);
-extern void ceph_msgr_flush(void);
-
-extern struct ceph_messenger *ceph_messenger_create(
-	struct ceph_entity_addr *myaddr);
-extern void ceph_messenger_destroy(struct ceph_messenger *);
-
-extern void ceph_con_init(struct ceph_messenger *msgr,
-			  struct ceph_connection *con);
-extern void ceph_con_open(struct ceph_connection *con,
-			  struct ceph_entity_addr *addr);
-extern bool ceph_con_opened(struct ceph_connection *con);
-extern void ceph_con_close(struct ceph_connection *con);
-extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg);
-extern void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg);
-extern void ceph_con_revoke_message(struct ceph_connection *con,
-				  struct ceph_msg *msg);
-extern void ceph_con_keepalive(struct ceph_connection *con);
-extern struct ceph_connection *ceph_con_get(struct ceph_connection *con);
-extern void ceph_con_put(struct ceph_connection *con);
-
-extern struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags);
-extern void ceph_msg_kfree(struct ceph_msg *m);
-
-
-static inline struct ceph_msg *ceph_msg_get(struct ceph_msg *msg)
-{
-	kref_get(&msg->kref);
-	return msg;
-}
-extern void ceph_msg_last_put(struct kref *kref);
-static inline void ceph_msg_put(struct ceph_msg *msg)
-{
-	kref_put(&msg->kref, ceph_msg_last_put);
-}
-
-extern void ceph_msg_dump(struct ceph_msg *msg);
-
-#endif
diff --git a/fs/ceph/mon_client.c b/fs/ceph/mon_client.c
deleted file mode 100644
index b2a5a3e..0000000
--- a/fs/ceph/mon_client.c
+++ /dev/null
@@ -1,1018 +0,0 @@
-#include "ceph_debug.h"
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/sched.h>
-
-#include "mon_client.h"
-#include "super.h"
-#include "auth.h"
-#include "decode.h"
-
-/*
- * Interact with Ceph monitor cluster.  Handle requests for new map
- * versions, and periodically resend as needed.  Also implement
- * statfs() and umount().
- *
- * A small cluster of Ceph "monitors" are responsible for managing critical
- * cluster configuration and state information.  An odd number (e.g., 3, 5)
- * of cmon daemons use a modified version of the Paxos part-time parliament
- * algorithm to manage the MDS map (mds cluster membership), OSD map, and
- * list of clients who have mounted the file system.
- *
- * We maintain an open, active session with a monitor at all times in order to
- * receive timely MDSMap updates.  We periodically send a keepalive byte on the
- * TCP socket to ensure we detect a failure.  If the connection does break, we
- * randomly hunt for a new monitor.  Once the connection is reestablished, we
- * resend any outstanding requests.
- */
-
-static const struct ceph_connection_operations mon_con_ops;
-
-static int __validate_auth(struct ceph_mon_client *monc);
-
-/*
- * Decode a monmap blob (e.g., during mount).
- */
-struct ceph_monmap *ceph_monmap_decode(void *p, void *end)
-{
-	struct ceph_monmap *m = NULL;
-	int i, err = -EINVAL;
-	struct ceph_fsid fsid;
-	u32 epoch, num_mon;
-	u16 version;
-	u32 len;
-
-	ceph_decode_32_safe(&p, end, len, bad);
-	ceph_decode_need(&p, end, len, bad);
-
-	dout("monmap_decode %p %p len %d\n", p, end, (int)(end-p));
-
-	ceph_decode_16_safe(&p, end, version, bad);
-
-	ceph_decode_need(&p, end, sizeof(fsid) + 2*sizeof(u32), bad);
-	ceph_decode_copy(&p, &fsid, sizeof(fsid));
-	epoch = ceph_decode_32(&p);
-
-	num_mon = ceph_decode_32(&p);
-	ceph_decode_need(&p, end, num_mon*sizeof(m->mon_inst[0]), bad);
-
-	if (num_mon >= CEPH_MAX_MON)
-		goto bad;
-	m = kmalloc(sizeof(*m) + sizeof(m->mon_inst[0])*num_mon, GFP_NOFS);
-	if (m == NULL)
-		return ERR_PTR(-ENOMEM);
-	m->fsid = fsid;
-	m->epoch = epoch;
-	m->num_mon = num_mon;
-	ceph_decode_copy(&p, m->mon_inst, num_mon*sizeof(m->mon_inst[0]));
-	for (i = 0; i < num_mon; i++)
-		ceph_decode_addr(&m->mon_inst[i].addr);
-
-	dout("monmap_decode epoch %d, num_mon %d\n", m->epoch,
-	     m->num_mon);
-	for (i = 0; i < m->num_mon; i++)
-		dout("monmap_decode  mon%d is %s\n", i,
-		     pr_addr(&m->mon_inst[i].addr.in_addr));
-	return m;
-
-bad:
-	dout("monmap_decode failed with %d\n", err);
-	kfree(m);
-	return ERR_PTR(err);
-}
-
-/*
- * return true if *addr is included in the monmap.
- */
-int ceph_monmap_contains(struct ceph_monmap *m, struct ceph_entity_addr *addr)
-{
-	int i;
-
-	for (i = 0; i < m->num_mon; i++)
-		if (memcmp(addr, &m->mon_inst[i].addr, sizeof(*addr)) == 0)
-			return 1;
-	return 0;
-}
-
-/*
- * Send an auth request.
- */
-static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len)
-{
-	monc->pending_auth = 1;
-	monc->m_auth->front.iov_len = len;
-	monc->m_auth->hdr.front_len = cpu_to_le32(len);
-	ceph_con_revoke(monc->con, monc->m_auth);
-	ceph_msg_get(monc->m_auth);  /* keep our ref */
-	ceph_con_send(monc->con, monc->m_auth);
-}
-
-/*
- * Close monitor session, if any.
- */
-static void __close_session(struct ceph_mon_client *monc)
-{
-	if (monc->con) {
-		dout("__close_session closing mon%d\n", monc->cur_mon);
-		ceph_con_revoke(monc->con, monc->m_auth);
-		ceph_con_close(monc->con);
-		monc->cur_mon = -1;
-		monc->pending_auth = 0;
-		ceph_auth_reset(monc->auth);
-	}
-}
-
-/*
- * Open a session with a (new) monitor.
- */
-static int __open_session(struct ceph_mon_client *monc)
-{
-	char r;
-	int ret;
-
-	if (monc->cur_mon < 0) {
-		get_random_bytes(&r, 1);
-		monc->cur_mon = r % monc->monmap->num_mon;
-		dout("open_session num=%d r=%d -> mon%d\n",
-		     monc->monmap->num_mon, r, monc->cur_mon);
-		monc->sub_sent = 0;
-		monc->sub_renew_after = jiffies;  /* i.e., expired */
-		monc->want_next_osdmap = !!monc->want_next_osdmap;
-
-		dout("open_session mon%d opening\n", monc->cur_mon);
-		monc->con->peer_name.type = CEPH_ENTITY_TYPE_MON;
-		monc->con->peer_name.num = cpu_to_le64(monc->cur_mon);
-		ceph_con_open(monc->con,
-			      &monc->monmap->mon_inst[monc->cur_mon].addr);
-
-		/* initiatiate authentication handshake */
-		ret = ceph_auth_build_hello(monc->auth,
-					    monc->m_auth->front.iov_base,
-					    monc->m_auth->front_max);
-		__send_prepared_auth_request(monc, ret);
-	} else {
-		dout("open_session mon%d already open\n", monc->cur_mon);
-	}
-	return 0;
-}
-
-static bool __sub_expired(struct ceph_mon_client *monc)
-{
-	return time_after_eq(jiffies, monc->sub_renew_after);
-}
-
-/*
- * Reschedule delayed work timer.
- */
-static void __schedule_delayed(struct ceph_mon_client *monc)
-{
-	unsigned delay;
-
-	if (monc->cur_mon < 0 || __sub_expired(monc))
-		delay = 10 * HZ;
-	else
-		delay = 20 * HZ;
-	dout("__schedule_delayed after %u\n", delay);
-	schedule_delayed_work(&monc->delayed_work, delay);
-}
-
-/*
- * Send subscribe request for mdsmap and/or osdmap.
- */
-static void __send_subscribe(struct ceph_mon_client *monc)
-{
-	dout("__send_subscribe sub_sent=%u exp=%u want_osd=%d\n",
-	     (unsigned)monc->sub_sent, __sub_expired(monc),
-	     monc->want_next_osdmap);
-	if ((__sub_expired(monc) && !monc->sub_sent) ||
-	    monc->want_next_osdmap == 1) {
-		struct ceph_msg *msg = monc->m_subscribe;
-		struct ceph_mon_subscribe_item *i;
-		void *p, *end;
-
-		p = msg->front.iov_base;
-		end = p + msg->front_max;
-
-		dout("__send_subscribe to 'mdsmap' %u+\n",
-		     (unsigned)monc->have_mdsmap);
-		if (monc->want_next_osdmap) {
-			dout("__send_subscribe to 'osdmap' %u\n",
-			     (unsigned)monc->have_osdmap);
-			ceph_encode_32(&p, 3);
-			ceph_encode_string(&p, end, "osdmap", 6);
-			i = p;
-			i->have = cpu_to_le64(monc->have_osdmap);
-			i->onetime = 1;
-			p += sizeof(*i);
-			monc->want_next_osdmap = 2;  /* requested */
-		} else {
-			ceph_encode_32(&p, 2);
-		}
-		ceph_encode_string(&p, end, "mdsmap", 6);
-		i = p;
-		i->have = cpu_to_le64(monc->have_mdsmap);
-		i->onetime = 0;
-		p += sizeof(*i);
-		ceph_encode_string(&p, end, "monmap", 6);
-		i = p;
-		i->have = 0;
-		i->onetime = 0;
-		p += sizeof(*i);
-
-		msg->front.iov_len = p - msg->front.iov_base;
-		msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
-		ceph_con_revoke(monc->con, msg);
-		ceph_con_send(monc->con, ceph_msg_get(msg));
-
-		monc->sub_sent = jiffies | 1;  /* never 0 */
-	}
-}
-
-static void handle_subscribe_ack(struct ceph_mon_client *monc,
-				 struct ceph_msg *msg)
-{
-	unsigned seconds;
-	struct ceph_mon_subscribe_ack *h = msg->front.iov_base;
-
-	if (msg->front.iov_len < sizeof(*h))
-		goto bad;
-	seconds = le32_to_cpu(h->duration);
-
-	mutex_lock(&monc->mutex);
-	if (monc->hunting) {
-		pr_info("mon%d %s session established\n",
-			monc->cur_mon, pr_addr(&monc->con->peer_addr.in_addr));
-		monc->hunting = false;
-	}
-	dout("handle_subscribe_ack after %d seconds\n", seconds);
-	monc->sub_renew_after = monc->sub_sent + (seconds >> 1)*HZ - 1;
-	monc->sub_sent = 0;
-	mutex_unlock(&monc->mutex);
-	return;
-bad:
-	pr_err("got corrupt subscribe-ack msg\n");
-	ceph_msg_dump(msg);
-}
-
-/*
- * Keep track of which maps we have
- */
-int ceph_monc_got_mdsmap(struct ceph_mon_client *monc, u32 got)
-{
-	mutex_lock(&monc->mutex);
-	monc->have_mdsmap = got;
-	mutex_unlock(&monc->mutex);
-	return 0;
-}
-
-int ceph_monc_got_osdmap(struct ceph_mon_client *monc, u32 got)
-{
-	mutex_lock(&monc->mutex);
-	monc->have_osdmap = got;
-	monc->want_next_osdmap = 0;
-	mutex_unlock(&monc->mutex);
-	return 0;
-}
-
-/*
- * Register interest in the next osdmap
- */
-void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc)
-{
-	dout("request_next_osdmap have %u\n", monc->have_osdmap);
-	mutex_lock(&monc->mutex);
-	if (!monc->want_next_osdmap)
-		monc->want_next_osdmap = 1;
-	if (monc->want_next_osdmap < 2)
-		__send_subscribe(monc);
-	mutex_unlock(&monc->mutex);
-}
-
-/*
- *
- */
-int ceph_monc_open_session(struct ceph_mon_client *monc)
-{
-	if (!monc->con) {
-		monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL);
-		if (!monc->con)
-			return -ENOMEM;
-		ceph_con_init(monc->client->msgr, monc->con);
-		monc->con->private = monc;
-		monc->con->ops = &mon_con_ops;
-	}
-
-	mutex_lock(&monc->mutex);
-	__open_session(monc);
-	__schedule_delayed(monc);
-	mutex_unlock(&monc->mutex);
-	return 0;
-}
-
-/*
- * The monitor responds with mount ack indicate mount success.  The
- * included client ticket allows the client to talk to MDSs and OSDs.
- */
-static void ceph_monc_handle_map(struct ceph_mon_client *monc,
-				 struct ceph_msg *msg)
-{
-	struct ceph_client *client = monc->client;
-	struct ceph_monmap *monmap = NULL, *old = monc->monmap;
-	void *p, *end;
-
-	mutex_lock(&monc->mutex);
-
-	dout("handle_monmap\n");
-	p = msg->front.iov_base;
-	end = p + msg->front.iov_len;
-
-	monmap = ceph_monmap_decode(p, end);
-	if (IS_ERR(monmap)) {
-		pr_err("problem decoding monmap, %d\n",
-		       (int)PTR_ERR(monmap));
-		goto out;
-	}
-
-	if (ceph_check_fsid(monc->client, &monmap->fsid) < 0) {
-		kfree(monmap);
-		goto out;
-	}
-
-	client->monc.monmap = monmap;
-	kfree(old);
-
-out:
-	mutex_unlock(&monc->mutex);
-	wake_up_all(&client->auth_wq);
-}
-
-/*
- * generic requests (e.g., statfs, poolop)
- */
-static struct ceph_mon_generic_request *__lookup_generic_req(
-	struct ceph_mon_client *monc, u64 tid)
-{
-	struct ceph_mon_generic_request *req;
-	struct rb_node *n = monc->generic_request_tree.rb_node;
-
-	while (n) {
-		req = rb_entry(n, struct ceph_mon_generic_request, node);
-		if (tid < req->tid)
-			n = n->rb_left;
-		else if (tid > req->tid)
-			n = n->rb_right;
-		else
-			return req;
-	}
-	return NULL;
-}
-
-static void __insert_generic_request(struct ceph_mon_client *monc,
-			    struct ceph_mon_generic_request *new)
-{
-	struct rb_node **p = &monc->generic_request_tree.rb_node;
-	struct rb_node *parent = NULL;
-	struct ceph_mon_generic_request *req = NULL;
-
-	while (*p) {
-		parent = *p;
-		req = rb_entry(parent, struct ceph_mon_generic_request, node);
-		if (new->tid < req->tid)
-			p = &(*p)->rb_left;
-		else if (new->tid > req->tid)
-			p = &(*p)->rb_right;
-		else
-			BUG();
-	}
-
-	rb_link_node(&new->node, parent, p);
-	rb_insert_color(&new->node, &monc->generic_request_tree);
-}
-
-static void release_generic_request(struct kref *kref)
-{
-	struct ceph_mon_generic_request *req =
-		container_of(kref, struct ceph_mon_generic_request, kref);
-
-	if (req->reply)
-		ceph_msg_put(req->reply);
-	if (req->request)
-		ceph_msg_put(req->request);
-
-	kfree(req);
-}
-
-static void put_generic_request(struct ceph_mon_generic_request *req)
-{
-	kref_put(&req->kref, release_generic_request);
-}
-
-static void get_generic_request(struct ceph_mon_generic_request *req)
-{
-	kref_get(&req->kref);
-}
-
-static struct ceph_msg *get_generic_reply(struct ceph_connection *con,
-					 struct ceph_msg_header *hdr,
-					 int *skip)
-{
-	struct ceph_mon_client *monc = con->private;
-	struct ceph_mon_generic_request *req;
-	u64 tid = le64_to_cpu(hdr->tid);
-	struct ceph_msg *m;
-
-	mutex_lock(&monc->mutex);
-	req = __lookup_generic_req(monc, tid);
-	if (!req) {
-		dout("get_generic_reply %lld dne\n", tid);
-		*skip = 1;
-		m = NULL;
-	} else {
-		dout("get_generic_reply %lld got %p\n", tid, req->reply);
-		m = ceph_msg_get(req->reply);
-		/*
-		 * we don't need to track the connection reading into
-		 * this reply because we only have one open connection
-		 * at a time, ever.
-		 */
-	}
-	mutex_unlock(&monc->mutex);
-	return m;
-}
-
-static int do_generic_request(struct ceph_mon_client *monc,
-			      struct ceph_mon_generic_request *req)
-{
-	int err;
-
-	/* register request */
-	mutex_lock(&monc->mutex);
-	req->tid = ++monc->last_tid;
-	req->request->hdr.tid = cpu_to_le64(req->tid);
-	__insert_generic_request(monc, req);
-	monc->num_generic_requests++;
-	ceph_con_send(monc->con, ceph_msg_get(req->request));
-	mutex_unlock(&monc->mutex);
-
-	err = wait_for_completion_interruptible(&req->completion);
-
-	mutex_lock(&monc->mutex);
-	rb_erase(&req->node, &monc->generic_request_tree);
-	monc->num_generic_requests--;
-	mutex_unlock(&monc->mutex);
-
-	if (!err)
-		err = req->result;
-	return err;
-}
-
-/*
- * statfs
- */
-static void handle_statfs_reply(struct ceph_mon_client *monc,
-				struct ceph_msg *msg)
-{
-	struct ceph_mon_generic_request *req;
-	struct ceph_mon_statfs_reply *reply = msg->front.iov_base;
-	u64 tid = le64_to_cpu(msg->hdr.tid);
-
-	if (msg->front.iov_len != sizeof(*reply))
-		goto bad;
-	dout("handle_statfs_reply %p tid %llu\n", msg, tid);
-
-	mutex_lock(&monc->mutex);
-	req = __lookup_generic_req(monc, tid);
-	if (req) {
-		*(struct ceph_statfs *)req->buf = reply->st;
-		req->result = 0;
-		get_generic_request(req);
-	}
-	mutex_unlock(&monc->mutex);
-	if (req) {
-		complete_all(&req->completion);
-		put_generic_request(req);
-	}
-	return;
-
-bad:
-	pr_err("corrupt generic reply, tid %llu\n", tid);
-	ceph_msg_dump(msg);
-}
-
-/*
- * Do a synchronous statfs().
- */
-int ceph_monc_do_statfs(struct ceph_mon_client *monc, struct ceph_statfs *buf)
-{
-	struct ceph_mon_generic_request *req;
-	struct ceph_mon_statfs *h;
-	int err;
-
-	req = kzalloc(sizeof(*req), GFP_NOFS);
-	if (!req)
-		return -ENOMEM;
-
-	kref_init(&req->kref);
-	req->buf = buf;
-	req->buf_len = sizeof(*buf);
-	init_completion(&req->completion);
-
-	err = -ENOMEM;
-	req->request = ceph_msg_new(CEPH_MSG_STATFS, sizeof(*h), GFP_NOFS);
-	if (!req->request)
-		goto out;
-	req->reply = ceph_msg_new(CEPH_MSG_STATFS_REPLY, 1024, GFP_NOFS);
-	if (!req->reply)
-		goto out;
-
-	/* fill out request */
-	h = req->request->front.iov_base;
-	h->monhdr.have_version = 0;
-	h->monhdr.session_mon = cpu_to_le16(-1);
-	h->monhdr.session_mon_tid = 0;
-	h->fsid = monc->monmap->fsid;
-
-	err = do_generic_request(monc, req);
-
-out:
-	kref_put(&req->kref, release_generic_request);
-	return err;
-}
-
-/*
- * pool ops
- */
-static int get_poolop_reply_buf(const char *src, size_t src_len,
-				char *dst, size_t dst_len)
-{
-	u32 buf_len;
-
-	if (src_len != sizeof(u32) + dst_len)
-		return -EINVAL;
-
-	buf_len = le32_to_cpu(*(u32 *)src);
-	if (buf_len != dst_len)
-		return -EINVAL;
-
-	memcpy(dst, src + sizeof(u32), dst_len);
-	return 0;
-}
-
-static void handle_poolop_reply(struct ceph_mon_client *monc,
-				struct ceph_msg *msg)
-{
-	struct ceph_mon_generic_request *req;
-	struct ceph_mon_poolop_reply *reply = msg->front.iov_base;
-	u64 tid = le64_to_cpu(msg->hdr.tid);
-
-	if (msg->front.iov_len < sizeof(*reply))
-		goto bad;
-	dout("handle_poolop_reply %p tid %llu\n", msg, tid);
-
-	mutex_lock(&monc->mutex);
-	req = __lookup_generic_req(monc, tid);
-	if (req) {
-		if (req->buf_len &&
-		    get_poolop_reply_buf(msg->front.iov_base + sizeof(*reply),
-				     msg->front.iov_len - sizeof(*reply),
-				     req->buf, req->buf_len) < 0) {
-			mutex_unlock(&monc->mutex);
-			goto bad;
-		}
-		req->result = le32_to_cpu(reply->reply_code);
-		get_generic_request(req);
-	}
-	mutex_unlock(&monc->mutex);
-	if (req) {
-		complete(&req->completion);
-		put_generic_request(req);
-	}
-	return;
-
-bad:
-	pr_err("corrupt generic reply, tid %llu\n", tid);
-	ceph_msg_dump(msg);
-}
-
-/*
- * Do a synchronous pool op.
- */
-int ceph_monc_do_poolop(struct ceph_mon_client *monc, u32 op,
-			u32 pool, u64 snapid,
-			char *buf, int len)
-{
-	struct ceph_mon_generic_request *req;
-	struct ceph_mon_poolop *h;
-	int err;
-
-	req = kzalloc(sizeof(*req), GFP_NOFS);
-	if (!req)
-		return -ENOMEM;
-
-	kref_init(&req->kref);
-	req->buf = buf;
-	req->buf_len = len;
-	init_completion(&req->completion);
-
-	err = -ENOMEM;
-	req->request = ceph_msg_new(CEPH_MSG_POOLOP, sizeof(*h), GFP_NOFS);
-	if (!req->request)
-		goto out;
-	req->reply = ceph_msg_new(CEPH_MSG_POOLOP_REPLY, 1024, GFP_NOFS);
-	if (!req->reply)
-		goto out;
-
-	/* fill out request */
-	req->request->hdr.version = cpu_to_le16(2);
-	h = req->request->front.iov_base;
-	h->monhdr.have_version = 0;
-	h->monhdr.session_mon = cpu_to_le16(-1);
-	h->monhdr.session_mon_tid = 0;
-	h->fsid = monc->monmap->fsid;
-	h->pool = cpu_to_le32(pool);
-	h->op = cpu_to_le32(op);
-	h->auid = 0;
-	h->snapid = cpu_to_le64(snapid);
-	h->name_len = 0;
-
-	err = do_generic_request(monc, req);
-
-out:
-	kref_put(&req->kref, release_generic_request);
-	return err;
-}
-
-int ceph_monc_create_snapid(struct ceph_mon_client *monc,
-			    u32 pool, u64 *snapid)
-{
-	return ceph_monc_do_poolop(monc,  POOL_OP_CREATE_UNMANAGED_SNAP,
-				   pool, 0, (char *)snapid, sizeof(*snapid));
-
-}
-
-int ceph_monc_delete_snapid(struct ceph_mon_client *monc,
-			    u32 pool, u64 snapid)
-{
-	return ceph_monc_do_poolop(monc,  POOL_OP_CREATE_UNMANAGED_SNAP,
-				   pool, snapid, 0, 0);
-
-}
-
-/*
- * Resend pending generic requests.
- */
-static void __resend_generic_request(struct ceph_mon_client *monc)
-{
-	struct ceph_mon_generic_request *req;
-	struct rb_node *p;
-
-	for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) {
-		req = rb_entry(p, struct ceph_mon_generic_request, node);
-		ceph_con_revoke(monc->con, req->request);
-		ceph_con_send(monc->con, ceph_msg_get(req->request));
-	}
-}
-
-/*
- * Delayed work.  If we haven't mounted yet, retry.  Otherwise,
- * renew/retry subscription as needed (in case it is timing out, or we
- * got an ENOMEM).  And keep the monitor connection alive.
- */
-static void delayed_work(struct work_struct *work)
-{
-	struct ceph_mon_client *monc =
-		container_of(work, struct ceph_mon_client, delayed_work.work);
-
-	dout("monc delayed_work\n");
-	mutex_lock(&monc->mutex);
-	if (monc->hunting) {
-		__close_session(monc);
-		__open_session(monc);  /* continue hunting */
-	} else {
-		ceph_con_keepalive(monc->con);
-
-		__validate_auth(monc);
-
-		if (monc->auth->ops->is_authenticated(monc->auth))
-			__send_subscribe(monc);
-	}
-	__schedule_delayed(monc);
-	mutex_unlock(&monc->mutex);
-}
-
-/*
- * On startup, we build a temporary monmap populated with the IPs
- * provided by mount(2).
- */
-static int build_initial_monmap(struct ceph_mon_client *monc)
-{
-	struct ceph_mount_args *args = monc->client->mount_args;
-	struct ceph_entity_addr *mon_addr = args->mon_addr;
-	int num_mon = args->num_mon;
-	int i;
-
-	/* build initial monmap */
-	monc->monmap = kzalloc(sizeof(*monc->monmap) +
-			       num_mon*sizeof(monc->monmap->mon_inst[0]),
-			       GFP_KERNEL);
-	if (!monc->monmap)
-		return -ENOMEM;
-	for (i = 0; i < num_mon; i++) {
-		monc->monmap->mon_inst[i].addr = mon_addr[i];
-		monc->monmap->mon_inst[i].addr.nonce = 0;
-		monc->monmap->mon_inst[i].name.type =
-			CEPH_ENTITY_TYPE_MON;
-		monc->monmap->mon_inst[i].name.num = cpu_to_le64(i);
-	}
-	monc->monmap->num_mon = num_mon;
-	monc->have_fsid = false;
-
-	/* release addr memory */
-	kfree(args->mon_addr);
-	args->mon_addr = NULL;
-	args->num_mon = 0;
-	return 0;
-}
-
-int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
-{
-	int err = 0;
-
-	dout("init\n");
-	memset(monc, 0, sizeof(*monc));
-	monc->client = cl;
-	monc->monmap = NULL;
-	mutex_init(&monc->mutex);
-
-	err = build_initial_monmap(monc);
-	if (err)
-		goto out;
-
-	monc->con = NULL;
-
-	/* authentication */
-	monc->auth = ceph_auth_init(cl->mount_args->name,
-				    cl->mount_args->secret);
-	if (IS_ERR(monc->auth))
-		return PTR_ERR(monc->auth);
-	monc->auth->want_keys =
-		CEPH_ENTITY_TYPE_AUTH | CEPH_ENTITY_TYPE_MON |
-		CEPH_ENTITY_TYPE_OSD | CEPH_ENTITY_TYPE_MDS;
-
-	/* msgs */
-	err = -ENOMEM;
-	monc->m_subscribe_ack = ceph_msg_new(CEPH_MSG_MON_SUBSCRIBE_ACK,
-				     sizeof(struct ceph_mon_subscribe_ack),
-				     GFP_NOFS);
-	if (!monc->m_subscribe_ack)
-		goto out_monmap;
-
-	monc->m_subscribe = ceph_msg_new(CEPH_MSG_MON_SUBSCRIBE, 96, GFP_NOFS);
-	if (!monc->m_subscribe)
-		goto out_subscribe_ack;
-
-	monc->m_auth_reply = ceph_msg_new(CEPH_MSG_AUTH_REPLY, 4096, GFP_NOFS);
-	if (!monc->m_auth_reply)
-		goto out_subscribe;
-
-	monc->m_auth = ceph_msg_new(CEPH_MSG_AUTH, 4096, GFP_NOFS);
-	monc->pending_auth = 0;
-	if (!monc->m_auth)
-		goto out_auth_reply;
-
-	monc->cur_mon = -1;
-	monc->hunting = true;
-	monc->sub_renew_after = jiffies;
-	monc->sub_sent = 0;
-
-	INIT_DELAYED_WORK(&monc->delayed_work, delayed_work);
-	monc->generic_request_tree = RB_ROOT;
-	monc->num_generic_requests = 0;
-	monc->last_tid = 0;
-
-	monc->have_mdsmap = 0;
-	monc->have_osdmap = 0;
-	monc->want_next_osdmap = 1;
-	return 0;
-
-out_auth_reply:
-	ceph_msg_put(monc->m_auth_reply);
-out_subscribe:
-	ceph_msg_put(monc->m_subscribe);
-out_subscribe_ack:
-	ceph_msg_put(monc->m_subscribe_ack);
-out_monmap:
-	kfree(monc->monmap);
-out:
-	return err;
-}
-
-void ceph_monc_stop(struct ceph_mon_client *monc)
-{
-	dout("stop\n");
-	cancel_delayed_work_sync(&monc->delayed_work);
-
-	mutex_lock(&monc->mutex);
-	__close_session(monc);
-	if (monc->con) {
-		monc->con->private = NULL;
-		monc->con->ops->put(monc->con);
-		monc->con = NULL;
-	}
-	mutex_unlock(&monc->mutex);
-
-	ceph_auth_destroy(monc->auth);
-
-	ceph_msg_put(monc->m_auth);
-	ceph_msg_put(monc->m_auth_reply);
-	ceph_msg_put(monc->m_subscribe);
-	ceph_msg_put(monc->m_subscribe_ack);
-
-	kfree(monc->monmap);
-}
-
-static void handle_auth_reply(struct ceph_mon_client *monc,
-			      struct ceph_msg *msg)
-{
-	int ret;
-	int was_auth = 0;
-
-	mutex_lock(&monc->mutex);
-	if (monc->auth->ops)
-		was_auth = monc->auth->ops->is_authenticated(monc->auth);
-	monc->pending_auth = 0;
-	ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base,
-				     msg->front.iov_len,
-				     monc->m_auth->front.iov_base,
-				     monc->m_auth->front_max);
-	if (ret < 0) {
-		monc->client->auth_err = ret;
-		wake_up_all(&monc->client->auth_wq);
-	} else if (ret > 0) {
-		__send_prepared_auth_request(monc, ret);
-	} else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) {
-		dout("authenticated, starting session\n");
-
-		monc->client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT;
-		monc->client->msgr->inst.name.num =
-					cpu_to_le64(monc->auth->global_id);
-
-		__send_subscribe(monc);
-		__resend_generic_request(monc);
-	}
-	mutex_unlock(&monc->mutex);
-}
-
-static int __validate_auth(struct ceph_mon_client *monc)
-{
-	int ret;
-
-	if (monc->pending_auth)
-		return 0;
-
-	ret = ceph_build_auth(monc->auth, monc->m_auth->front.iov_base,
-			      monc->m_auth->front_max);
-	if (ret <= 0)
-		return ret; /* either an error, or no need to authenticate */
-	__send_prepared_auth_request(monc, ret);
-	return 0;
-}
-
-int ceph_monc_validate_auth(struct ceph_mon_client *monc)
-{
-	int ret;
-
-	mutex_lock(&monc->mutex);
-	ret = __validate_auth(monc);
-	mutex_unlock(&monc->mutex);
-	return ret;
-}
-
-/*
- * handle incoming message
- */
-static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
-{
-	struct ceph_mon_client *monc = con->private;
-	int type = le16_to_cpu(msg->hdr.type);
-
-	if (!monc)
-		return;
-
-	switch (type) {
-	case CEPH_MSG_AUTH_REPLY:
-		handle_auth_reply(monc, msg);
-		break;
-
-	case CEPH_MSG_MON_SUBSCRIBE_ACK:
-		handle_subscribe_ack(monc, msg);
-		break;
-
-	case CEPH_MSG_STATFS_REPLY:
-		handle_statfs_reply(monc, msg);
-		break;
-
-	case CEPH_MSG_POOLOP_REPLY:
-		handle_poolop_reply(monc, msg);
-		break;
-
-	case CEPH_MSG_MON_MAP:
-		ceph_monc_handle_map(monc, msg);
-		break;
-
-	case CEPH_MSG_MDS_MAP:
-		ceph_mdsc_handle_map(&monc->client->mdsc, msg);
-		break;
-
-	case CEPH_MSG_OSD_MAP:
-		ceph_osdc_handle_map(&monc->client->osdc, msg);
-		break;
-
-	default:
-		pr_err("received unknown message type %d %s\n", type,
-		       ceph_msg_type_name(type));
-	}
-	ceph_msg_put(msg);
-}
-
-/*
- * Allocate memory for incoming message
- */
-static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con,
-				      struct ceph_msg_header *hdr,
-				      int *skip)
-{
-	struct ceph_mon_client *monc = con->private;
-	int type = le16_to_cpu(hdr->type);
-	int front_len = le32_to_cpu(hdr->front_len);
-	struct ceph_msg *m = NULL;
-
-	*skip = 0;
-
-	switch (type) {
-	case CEPH_MSG_MON_SUBSCRIBE_ACK:
-		m = ceph_msg_get(monc->m_subscribe_ack);
-		break;
-	case CEPH_MSG_POOLOP_REPLY:
-	case CEPH_MSG_STATFS_REPLY:
-		return get_generic_reply(con, hdr, skip);
-	case CEPH_MSG_AUTH_REPLY:
-		m = ceph_msg_get(monc->m_auth_reply);
-		break;
-	case CEPH_MSG_MON_MAP:
-	case CEPH_MSG_MDS_MAP:
-	case CEPH_MSG_OSD_MAP:
-		m = ceph_msg_new(type, front_len, GFP_NOFS);
-		break;
-	}
-
-	if (!m) {
-		pr_info("alloc_msg unknown type %d\n", type);
-		*skip = 1;
-	}
-	return m;
-}
-
-/*
- * If the monitor connection resets, pick a new monitor and resubmit
- * any pending requests.
- */
-static void mon_fault(struct ceph_connection *con)
-{
-	struct ceph_mon_client *monc = con->private;
-
-	if (!monc)
-		return;
-
-	dout("mon_fault\n");
-	mutex_lock(&monc->mutex);
-	if (!con->private)
-		goto out;
-
-	if (monc->con && !monc->hunting)
-		pr_info("mon%d %s session lost, "
-			"hunting for new mon\n", monc->cur_mon,
-			pr_addr(&monc->con->peer_addr.in_addr));
-
-	__close_session(monc);
-	if (!monc->hunting) {
-		/* start hunting */
-		monc->hunting = true;
-		__open_session(monc);
-	} else {
-		/* already hunting, let's wait a bit */
-		__schedule_delayed(monc);
-	}
-out:
-	mutex_unlock(&monc->mutex);
-}
-
-static const struct ceph_connection_operations mon_con_ops = {
-	.get = ceph_con_get,
-	.put = ceph_con_put,
-	.dispatch = dispatch,
-	.fault = mon_fault,
-	.alloc_msg = mon_alloc_msg,
-};
diff --git a/fs/ceph/mon_client.h b/fs/ceph/mon_client.h
deleted file mode 100644
index 8e396f2..0000000
--- a/fs/ceph/mon_client.h
+++ /dev/null
@@ -1,121 +0,0 @@
-#ifndef _FS_CEPH_MON_CLIENT_H
-#define _FS_CEPH_MON_CLIENT_H
-
-#include <linux/completion.h>
-#include <linux/kref.h>
-#include <linux/rbtree.h>
-
-#include "messenger.h"
-
-struct ceph_client;
-struct ceph_mount_args;
-struct ceph_auth_client;
-
-/*
- * The monitor map enumerates the set of all monitors.
- */
-struct ceph_monmap {
-	struct ceph_fsid fsid;
-	u32 epoch;
-	u32 num_mon;
-	struct ceph_entity_inst mon_inst[0];
-};
-
-struct ceph_mon_client;
-struct ceph_mon_generic_request;
-
-
-/*
- * Generic mechanism for resending monitor requests.
- */
-typedef void (*ceph_monc_request_func_t)(struct ceph_mon_client *monc,
-					 int newmon);
-
-/* a pending monitor request */
-struct ceph_mon_request {
-	struct ceph_mon_client *monc;
-	struct delayed_work delayed_work;
-	unsigned long delay;
-	ceph_monc_request_func_t do_request;
-};
-
-/*
- * ceph_mon_generic_request is being used for the statfs and poolop requests
- * which are bening done a bit differently because we need to get data back
- * to the caller
- */
-struct ceph_mon_generic_request {
-	struct kref kref;
-	u64 tid;
-	struct rb_node node;
-	int result;
-	void *buf;
-	int buf_len;
-	struct completion completion;
-	struct ceph_msg *request;  /* original request */
-	struct ceph_msg *reply;    /* and reply */
-};
-
-struct ceph_mon_client {
-	struct ceph_client *client;
-	struct ceph_monmap *monmap;
-
-	struct mutex mutex;
-	struct delayed_work delayed_work;
-
-	struct ceph_auth_client *auth;
-	struct ceph_msg *m_auth, *m_auth_reply, *m_subscribe, *m_subscribe_ack;
-	int pending_auth;
-
-	bool hunting;
-	int cur_mon;                       /* last monitor i contacted */
-	unsigned long sub_sent, sub_renew_after;
-	struct ceph_connection *con;
-	bool have_fsid;
-
-	/* pending generic requests */
-	struct rb_root generic_request_tree;
-	int num_generic_requests;
-	u64 last_tid;
-
-	/* mds/osd map */
-	int want_next_osdmap; /* 1 = want, 2 = want+asked */
-	u32 have_osdmap, have_mdsmap;
-
-#ifdef CONFIG_DEBUG_FS
-	struct dentry *debugfs_file;
-#endif
-};
-
-extern struct ceph_monmap *ceph_monmap_decode(void *p, void *end);
-extern int ceph_monmap_contains(struct ceph_monmap *m,
-				struct ceph_entity_addr *addr);
-
-extern int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl);
-extern void ceph_monc_stop(struct ceph_mon_client *monc);
-
-/*
- * The model here is to indicate that we need a new map of at least
- * epoch @want, and also call in when we receive a map.  We will
- * periodically rerequest the map from the monitor cluster until we
- * get what we want.
- */
-extern int ceph_monc_got_mdsmap(struct ceph_mon_client *monc, u32 have);
-extern int ceph_monc_got_osdmap(struct ceph_mon_client *monc, u32 have);
-
-extern void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc);
-
-extern int ceph_monc_do_statfs(struct ceph_mon_client *monc,
-			       struct ceph_statfs *buf);
-
-extern int ceph_monc_open_session(struct ceph_mon_client *monc);
-
-extern int ceph_monc_validate_auth(struct ceph_mon_client *monc);
-
-extern int ceph_monc_create_snapid(struct ceph_mon_client *monc,
-				   u32 pool, u64 *snapid);
-
-extern int ceph_monc_delete_snapid(struct ceph_mon_client *monc,
-				   u32 pool, u64 snapid);
-
-#endif
diff --git a/fs/ceph/msgpool.c b/fs/ceph/msgpool.c
deleted file mode 100644
index dd65a64..0000000
--- a/fs/ceph/msgpool.c
+++ /dev/null
@@ -1,64 +0,0 @@
-#include "ceph_debug.h"
-
-#include <linux/err.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-
-#include "msgpool.h"
-
-static void *alloc_fn(gfp_t gfp_mask, void *arg)
-{
-	struct ceph_msgpool *pool = arg;
-	void *p;
-
-	p = ceph_msg_new(0, pool->front_len, gfp_mask);
-	if (!p)
-		pr_err("msgpool %s alloc failed\n", pool->name);
-	return p;
-}
-
-static void free_fn(void *element, void *arg)
-{
-	ceph_msg_put(element);
-}
-
-int ceph_msgpool_init(struct ceph_msgpool *pool,
-		      int front_len, int size, bool blocking, const char *name)
-{
-	pool->front_len = front_len;
-	pool->pool = mempool_create(size, alloc_fn, free_fn, pool);
-	if (!pool->pool)
-		return -ENOMEM;
-	pool->name = name;
-	return 0;
-}
-
-void ceph_msgpool_destroy(struct ceph_msgpool *pool)
-{
-	mempool_destroy(pool->pool);
-}
-
-struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool,
-				  int front_len)
-{
-	if (front_len > pool->front_len) {
-		pr_err("msgpool_get pool %s need front %d, pool size is %d\n",
-		       pool->name, front_len, pool->front_len);
-		WARN_ON(1);
-
-		/* try to alloc a fresh message */
-		return ceph_msg_new(0, front_len, GFP_NOFS);
-	}
-
-	return mempool_alloc(pool->pool, GFP_NOFS);
-}
-
-void ceph_msgpool_put(struct ceph_msgpool *pool, struct ceph_msg *msg)
-{
-	/* reset msg front_len; user may have changed it */
-	msg->front.iov_len = pool->front_len;
-	msg->hdr.front_len = cpu_to_le32(pool->front_len);
-
-	kref_init(&msg->kref);  /* retake single ref */
-}
diff --git a/fs/ceph/osd_client.c b/fs/ceph/osd_client.c
deleted file mode 100644
index dfced1d..0000000
--- a/fs/ceph/osd_client.c
+++ /dev/null
@@ -1,1539 +0,0 @@
-#include "ceph_debug.h"
-
-#include <linux/err.h>
-#include <linux/highmem.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include "super.h"
-#include "osd_client.h"
-#include "messenger.h"
-#include "decode.h"
-#include "auth.h"
-
-#define OSD_OP_FRONT_LEN	4096
-#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);
-
-/*
- * Implement client access to distributed object storage cluster.
- *
- * All data objects are stored within a cluster/cloud of OSDs, or
- * "object storage devices."  (Note that Ceph OSDs have _nothing_ to
- * do with the T10 OSD extensions to SCSI.)  Ceph OSDs are simply
- * remote daemons serving up and coordinating consistent and safe
- * access to storage.
- *
- * Cluster membership and the mapping of data objects onto storage devices
- * are described by the osd map.
- *
- * We keep track of pending OSD requests (read, write), resubmit
- * requests to different OSDs when the cluster topology/data layout
- * change, or retry the affected requests when the communications
- * channel with an OSD is reset.
- */
-
-/*
- * calculate the mapping of a file extent onto an object, and fill out the
- * request accordingly.  shorten extent as necessary if it crosses an
- * object boundary.
- *
- * fill osd op in request message.
- */
-static void calc_layout(struct ceph_osd_client *osdc,
-			struct ceph_vino vino, struct ceph_file_layout *layout,
-			u64 off, u64 *plen,
-			struct ceph_osd_request *req)
-{
-	struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
-	struct ceph_osd_op *op = (void *)(reqhead + 1);
-	u64 orig_len = *plen;
-	u64 objoff, objlen;    /* extent in object */
-	u64 bno;
-
-	reqhead->snapid = cpu_to_le64(vino.snap);
-
-	/* object extent? */
-	ceph_calc_file_object_mapping(layout, off, plen, &bno,
-				      &objoff, &objlen);
-	if (*plen < orig_len)
-		dout(" skipping last %llu, final file extent %llu~%llu\n",
-		     orig_len - *plen, off, *plen);
-
-	sprintf(req->r_oid, "%llx.%08llx", vino.ino, bno);
-	req->r_oid_len = strlen(req->r_oid);
-
-	op->extent.offset = cpu_to_le64(objoff);
-	op->extent.length = cpu_to_le64(objlen);
-	req->r_num_pages = calc_pages_for(off, *plen);
-
-	dout("calc_layout %s (%d) %llu~%llu (%d pages)\n",
-	     req->r_oid, req->r_oid_len, objoff, objlen, req->r_num_pages);
-}
-
-/*
- * requests
- */
-void ceph_osdc_release_request(struct kref *kref)
-{
-	struct ceph_osd_request *req = container_of(kref,
-						    struct ceph_osd_request,
-						    r_kref);
-
-	if (req->r_request)
-		ceph_msg_put(req->r_request);
-	if (req->r_reply)
-		ceph_msg_put(req->r_reply);
-	if (req->r_con_filling_msg) {
-		dout("release_request revoking pages %p from con %p\n",
-		     req->r_pages, req->r_con_filling_msg);
-		ceph_con_revoke_message(req->r_con_filling_msg,
-				      req->r_reply);
-		ceph_con_put(req->r_con_filling_msg);
-	}
-	if (req->r_own_pages)
-		ceph_release_page_vector(req->r_pages,
-					 req->r_num_pages);
-	ceph_put_snap_context(req->r_snapc);
-	if (req->r_mempool)
-		mempool_free(req, req->r_osdc->req_mempool);
-	else
-		kfree(req);
-}
-
-/*
- * build new request AND message, calculate layout, and adjust file
- * extent as needed.
- *
- * if the file was recently truncated, we include information about its
- * old and new size so that the object can be updated appropriately.  (we
- * avoid synchronously deleting truncated objects because it's slow.)
- *
- * if @do_sync, include a 'startsync' command so that the osd will flush
- * data quickly.
- */
-struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
-					       struct ceph_file_layout *layout,
-					       struct ceph_vino vino,
-					       u64 off, u64 *plen,
-					       int opcode, int flags,
-					       struct ceph_snap_context *snapc,
-					       int do_sync,
-					       u32 truncate_seq,
-					       u64 truncate_size,
-					       struct timespec *mtime,
-					       bool use_mempool, int num_reply)
-{
-	struct ceph_osd_request *req;
-	struct ceph_msg *msg;
-	struct ceph_osd_request_head *head;
-	struct ceph_osd_op *op;
-	void *p;
-	int num_op = 1 + do_sync;
-	size_t msg_size = sizeof(*head) + num_op*sizeof(*op);
-	int i;
-
-	if (use_mempool) {
-		req = mempool_alloc(osdc->req_mempool, GFP_NOFS);
-		memset(req, 0, sizeof(*req));
-	} else {
-		req = kzalloc(sizeof(*req), GFP_NOFS);
-	}
-	if (req == NULL)
-		return NULL;
-
-	req->r_osdc = osdc;
-	req->r_mempool = use_mempool;
-	kref_init(&req->r_kref);
-	init_completion(&req->r_completion);
-	init_completion(&req->r_safe_completion);
-	INIT_LIST_HEAD(&req->r_unsafe_item);
-	req->r_flags = flags;
-
-	WARN_ON((flags & (CEPH_OSD_FLAG_READ|CEPH_OSD_FLAG_WRITE)) == 0);
-
-	/* create reply message */
-	if (use_mempool)
-		msg = ceph_msgpool_get(&osdc->msgpool_op_reply, 0);
-	else
-		msg = ceph_msg_new(CEPH_MSG_OSD_OPREPLY,
-				   OSD_OPREPLY_FRONT_LEN, GFP_NOFS);
-	if (!msg) {
-		ceph_osdc_put_request(req);
-		return NULL;
-	}
-	req->r_reply = msg;
-
-	/* create request message; allow space for oid */
-	msg_size += 40;
-	if (snapc)
-		msg_size += sizeof(u64) * snapc->num_snaps;
-	if (use_mempool)
-		msg = ceph_msgpool_get(&osdc->msgpool_op, 0);
-	else
-		msg = ceph_msg_new(CEPH_MSG_OSD_OP, msg_size, GFP_NOFS);
-	if (!msg) {
-		ceph_osdc_put_request(req);
-		return NULL;
-	}
-	msg->hdr.type = cpu_to_le16(CEPH_MSG_OSD_OP);
-	memset(msg->front.iov_base, 0, msg->front.iov_len);
-	head = msg->front.iov_base;
-	op = (void *)(head + 1);
-	p = (void *)(op + num_op);
-
-	req->r_request = msg;
-	req->r_snapc = ceph_get_snap_context(snapc);
-
-	head->client_inc = cpu_to_le32(1); /* always, for now. */
-	head->flags = cpu_to_le32(flags);
-	if (flags & CEPH_OSD_FLAG_WRITE)
-		ceph_encode_timespec(&head->mtime, mtime);
-	head->num_ops = cpu_to_le16(num_op);
-	op->op = cpu_to_le16(opcode);
-
-	/* calculate max write size */
-	calc_layout(osdc, vino, layout, off, plen, req);
-	req->r_file_layout = *layout;  /* keep a copy */
-
-	if (flags & CEPH_OSD_FLAG_WRITE) {
-		req->r_request->hdr.data_off = cpu_to_le16(off);
-		req->r_request->hdr.data_len = cpu_to_le32(*plen);
-		op->payload_len = cpu_to_le32(*plen);
-	}
-	op->extent.truncate_size = cpu_to_le64(truncate_size);
-	op->extent.truncate_seq = cpu_to_le32(truncate_seq);
-
-	/* fill in oid */
-	head->object_len = cpu_to_le32(req->r_oid_len);
-	memcpy(p, req->r_oid, req->r_oid_len);
-	p += req->r_oid_len;
-
-	if (do_sync) {
-		op++;
-		op->op = cpu_to_le16(CEPH_OSD_OP_STARTSYNC);
-	}
-	if (snapc) {
-		head->snap_seq = cpu_to_le64(snapc->seq);
-		head->num_snaps = cpu_to_le32(snapc->num_snaps);
-		for (i = 0; i < snapc->num_snaps; i++) {
-			put_unaligned_le64(snapc->snaps[i], p);
-			p += sizeof(u64);
-		}
-	}
-
-	BUG_ON(p > msg->front.iov_base + msg->front.iov_len);
-	msg_size = p - msg->front.iov_base;
-	msg->front.iov_len = msg_size;
-	msg->hdr.front_len = cpu_to_le32(msg_size);
-	return req;
-}
-
-/*
- * We keep osd requests in an rbtree, sorted by ->r_tid.
- */
-static void __insert_request(struct ceph_osd_client *osdc,
-			     struct ceph_osd_request *new)
-{
-	struct rb_node **p = &osdc->requests.rb_node;
-	struct rb_node *parent = NULL;
-	struct ceph_osd_request *req = NULL;
-
-	while (*p) {
-		parent = *p;
-		req = rb_entry(parent, struct ceph_osd_request, r_node);
-		if (new->r_tid < req->r_tid)
-			p = &(*p)->rb_left;
-		else if (new->r_tid > req->r_tid)
-			p = &(*p)->rb_right;
-		else
-			BUG();
-	}
-
-	rb_link_node(&new->r_node, parent, p);
-	rb_insert_color(&new->r_node, &osdc->requests);
-}
-
-static struct ceph_osd_request *__lookup_request(struct ceph_osd_client *osdc,
-						 u64 tid)
-{
-	struct ceph_osd_request *req;
-	struct rb_node *n = osdc->requests.rb_node;
-
-	while (n) {
-		req = rb_entry(n, struct ceph_osd_request, r_node);
-		if (tid < req->r_tid)
-			n = n->rb_left;
-		else if (tid > req->r_tid)
-			n = n->rb_right;
-		else
-			return req;
-	}
-	return NULL;
-}
-
-static struct ceph_osd_request *
-__lookup_request_ge(struct ceph_osd_client *osdc,
-		    u64 tid)
-{
-	struct ceph_osd_request *req;
-	struct rb_node *n = osdc->requests.rb_node;
-
-	while (n) {
-		req = rb_entry(n, struct ceph_osd_request, r_node);
-		if (tid < req->r_tid) {
-			if (!n->rb_left)
-				return req;
-			n = n->rb_left;
-		} else if (tid > req->r_tid) {
-			n = n->rb_right;
-		} else {
-			return req;
-		}
-	}
-	return NULL;
-}
-
-
-/*
- * If the osd connection drops, we need to resubmit all requests.
- */
-static void osd_reset(struct ceph_connection *con)
-{
-	struct ceph_osd *osd = con->private;
-	struct ceph_osd_client *osdc;
-
-	if (!osd)
-		return;
-	dout("osd_reset osd%d\n", osd->o_osd);
-	osdc = osd->o_osdc;
-	down_read(&osdc->map_sem);
-	kick_requests(osdc, osd);
-	up_read(&osdc->map_sem);
-}
-
-/*
- * Track open sessions with osds.
- */
-static struct ceph_osd *create_osd(struct ceph_osd_client *osdc)
-{
-	struct ceph_osd *osd;
-
-	osd = kzalloc(sizeof(*osd), GFP_NOFS);
-	if (!osd)
-		return NULL;
-
-	atomic_set(&osd->o_ref, 1);
-	osd->o_osdc = osdc;
-	INIT_LIST_HEAD(&osd->o_requests);
-	INIT_LIST_HEAD(&osd->o_osd_lru);
-	osd->o_incarnation = 1;
-
-	ceph_con_init(osdc->client->msgr, &osd->o_con);
-	osd->o_con.private = osd;
-	osd->o_con.ops = &osd_con_ops;
-	osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD;
-
-	INIT_LIST_HEAD(&osd->o_keepalive_item);
-	return osd;
-}
-
-static struct ceph_osd *get_osd(struct ceph_osd *osd)
-{
-	if (atomic_inc_not_zero(&osd->o_ref)) {
-		dout("get_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref)-1,
-		     atomic_read(&osd->o_ref));
-		return osd;
-	} else {
-		dout("get_osd %p FAIL\n", osd);
-		return NULL;
-	}
-}
-
-static void put_osd(struct ceph_osd *osd)
-{
-	dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref),
-	     atomic_read(&osd->o_ref) - 1);
-	if (atomic_dec_and_test(&osd->o_ref)) {
-		struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth;
-
-		if (osd->o_authorizer)
-			ac->ops->destroy_authorizer(ac, osd->o_authorizer);
-		kfree(osd);
-	}
-}
-
-/*
- * remove an osd from our map
- */
-static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
-{
-	dout("__remove_osd %p\n", osd);
-	BUG_ON(!list_empty(&osd->o_requests));
-	rb_erase(&osd->o_node, &osdc->osds);
-	list_del_init(&osd->o_osd_lru);
-	ceph_con_close(&osd->o_con);
-	put_osd(osd);
-}
-
-static void __move_osd_to_lru(struct ceph_osd_client *osdc,
-			      struct ceph_osd *osd)
-{
-	dout("__move_osd_to_lru %p\n", osd);
-	BUG_ON(!list_empty(&osd->o_osd_lru));
-	list_add_tail(&osd->o_osd_lru, &osdc->osd_lru);
-	osd->lru_ttl = jiffies + osdc->client->mount_args->osd_idle_ttl * HZ;
-}
-
-static void __remove_osd_from_lru(struct ceph_osd *osd)
-{
-	dout("__remove_osd_from_lru %p\n", osd);
-	if (!list_empty(&osd->o_osd_lru))
-		list_del_init(&osd->o_osd_lru);
-}
-
-static void remove_old_osds(struct ceph_osd_client *osdc, int remove_all)
-{
-	struct ceph_osd *osd, *nosd;
-
-	dout("__remove_old_osds %p\n", osdc);
-	mutex_lock(&osdc->request_mutex);
-	list_for_each_entry_safe(osd, nosd, &osdc->osd_lru, o_osd_lru) {
-		if (!remove_all && time_before(jiffies, osd->lru_ttl))
-			break;
-		__remove_osd(osdc, osd);
-	}
-	mutex_unlock(&osdc->request_mutex);
-}
-
-/*
- * reset osd connect
- */
-static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
-{
-	struct ceph_osd_request *req;
-	int ret = 0;
-
-	dout("__reset_osd %p osd%d\n", osd, osd->o_osd);
-	if (list_empty(&osd->o_requests)) {
-		__remove_osd(osdc, osd);
-	} else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd],
-			  &osd->o_con.peer_addr,
-			  sizeof(osd->o_con.peer_addr)) == 0 &&
-		   !ceph_con_opened(&osd->o_con)) {
-		dout(" osd addr hasn't changed and connection never opened,"
-		     " letting msgr retry");
-		/* touch each r_stamp for handle_timeout()'s benfit */
-		list_for_each_entry(req, &osd->o_requests, r_osd_item)
-			req->r_stamp = jiffies;
-		ret = -EAGAIN;
-	} else {
-		ceph_con_close(&osd->o_con);
-		ceph_con_open(&osd->o_con, &osdc->osdmap->osd_addr[osd->o_osd]);
-		osd->o_incarnation++;
-	}
-	return ret;
-}
-
-static void __insert_osd(struct ceph_osd_client *osdc, struct ceph_osd *new)
-{
-	struct rb_node **p = &osdc->osds.rb_node;
-	struct rb_node *parent = NULL;
-	struct ceph_osd *osd = NULL;
-
-	while (*p) {
-		parent = *p;
-		osd = rb_entry(parent, struct ceph_osd, o_node);
-		if (new->o_osd < osd->o_osd)
-			p = &(*p)->rb_left;
-		else if (new->o_osd > osd->o_osd)
-			p = &(*p)->rb_right;
-		else
-			BUG();
-	}
-
-	rb_link_node(&new->o_node, parent, p);
-	rb_insert_color(&new->o_node, &osdc->osds);
-}
-
-static struct ceph_osd *__lookup_osd(struct ceph_osd_client *osdc, int o)
-{
-	struct ceph_osd *osd;
-	struct rb_node *n = osdc->osds.rb_node;
-
-	while (n) {
-		osd = rb_entry(n, struct ceph_osd, o_node);
-		if (o < osd->o_osd)
-			n = n->rb_left;
-		else if (o > osd->o_osd)
-			n = n->rb_right;
-		else
-			return osd;
-	}
-	return NULL;
-}
-
-static void __schedule_osd_timeout(struct ceph_osd_client *osdc)
-{
-	schedule_delayed_work(&osdc->timeout_work,
-			osdc->client->mount_args->osd_keepalive_timeout * HZ);
-}
-
-static void __cancel_osd_timeout(struct ceph_osd_client *osdc)
-{
-	cancel_delayed_work(&osdc->timeout_work);
-}
-
-/*
- * 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)
-{
-	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);
-
-	dout("register_request %p tid %lld\n", req, req->r_tid);
-	__insert_request(osdc, req);
-	ceph_osdc_get_request(req);
-	osdc->num_requests++;
-
-	if (osdc->num_requests == 1) {
-		dout(" first request, scheduling timeout\n");
-		__schedule_osd_timeout(osdc);
-	}
-	mutex_unlock(&osdc->request_mutex);
-}
-
-/*
- * called under osdc->request_mutex
- */
-static void __unregister_request(struct ceph_osd_client *osdc,
-				 struct ceph_osd_request *req)
-{
-	dout("__unregister_request %p tid %lld\n", req, req->r_tid);
-	rb_erase(&req->r_node, &osdc->requests);
-	osdc->num_requests--;
-
-	if (req->r_osd) {
-		/* make sure the original request isn't in flight. */
-		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))
-			__move_osd_to_lru(osdc, req->r_osd);
-		req->r_osd = NULL;
-	}
-
-	ceph_osdc_put_request(req);
-
-	list_del_init(&req->r_req_lru_item);
-	if (osdc->num_requests == 0) {
-		dout(" no requests, canceling timeout\n");
-		__cancel_osd_timeout(osdc);
-	}
-}
-
-/*
- * Cancel a previously queued request message
- */
-static void __cancel_request(struct ceph_osd_request *req)
-{
-	if (req->r_sent) {
-		ceph_con_revoke(&req->r_osd->o_con, req->r_request);
-		req->r_sent = 0;
-	}
-	list_del_init(&req->r_req_lru_item);
-}
-
-/*
- * 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.
- *
- * 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)
-{
-	struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
-	struct ceph_pg pgid;
-	int acting[CEPH_PG_MAX_SIZE];
-	int o = -1, num = 0;
-	int err;
-
-	dout("map_osds %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)
-		return err;
-	pgid = reqhead->layout.ol_pgid;
-	req->r_pgid = pgid;
-
-	err = ceph_calc_pg_acting(osdc->osdmap, pgid, acting);
-	if (err > 0) {
-		o = acting[0];
-		num = err;
-	}
-
-	if ((req->r_osd && req->r_osd->o_osd == o &&
-	     req->r_sent >= req->r_osd->o_incarnation &&
-	     req->r_num_pg_osds == num &&
-	     memcmp(req->r_pg_osds, acting, sizeof(acting[0])*num) == 0) ||
-	    (req->r_osd == NULL && o == -1))
-		return 0;  /* no change */
-
-	dout("map_osds 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);
-
-	/* record full pg acting set */
-	memcpy(req->r_pg_osds, acting, sizeof(acting[0]) * num);
-	req->r_num_pg_osds = num;
-
-	if (req->r_osd) {
-		__cancel_request(req);
-		list_del_init(&req->r_osd_item);
-		req->r_osd = NULL;
-	}
-
-	req->r_osd = __lookup_osd(osdc, o);
-	if (!req->r_osd && o >= 0) {
-		err = -ENOMEM;
-		req->r_osd = create_osd(osdc);
-		if (!req->r_osd)
-			goto out;
-
-		dout("map_osds 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);
-
-		ceph_con_open(&req->r_osd->o_con, &osdc->osdmap->osd_addr[o]);
-	}
-
-	if (req->r_osd) {
-		__remove_osd_from_lru(req->r_osd);
-		list_add(&req->r_osd_item, &req->r_osd->o_requests);
-	}
-	err = 1;   /* osd or pg changed */
-
-out:
-	return err;
-}
-
-/*
- * caller should hold map_sem (for read) and request_mutex
- */
-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);
-
-	reqhead = req->r_request->front.iov_base;
-	reqhead->osdmap_epoch = cpu_to_le32(osdc->osdmap->epoch);
-	reqhead->flags |= cpu_to_le32(req->r_flags);  /* e.g., RETRY */
-	reqhead->reassert_version = req->r_reassert_version;
-
-	req->r_stamp = jiffies;
-	list_move_tail(&req->r_req_lru_item, &osdc->req_lru);
-
-	ceph_msg_get(req->r_request); /* send consumes a ref */
-	ceph_con_send(&req->r_osd->o_con, req->r_request);
-	req->r_sent = req->r_osd->o_incarnation;
-	return 0;
-}
-
-/*
- * 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
- * ensure any communications channel reset is detected.  Reset the
- * request timeouts another N seconds in the future as we go.
- * Reschedule the timeout event another N seconds in future (unless
- * there are no open requests).
- */
-static void handle_timeout(struct work_struct *work)
-{
-	struct ceph_osd_client *osdc =
-		container_of(work, struct ceph_osd_client, timeout_work.work);
-	struct ceph_osd_request *req, *last_req = NULL;
-	struct ceph_osd *osd;
-	unsigned long timeout = osdc->client->mount_args->osd_timeout * HZ;
-	unsigned long keepalive =
-		osdc->client->mount_args->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
-	 * is a failsafe measure.. we really shouldn't be getting to
-	 * this point if the system is working properly.  the monitors
-	 * should mark the osd as failed and we should find out about
-	 * it from an updated osd map.
-	 */
-	while (timeout && !list_empty(&osdc->req_lru)) {
-		req = list_entry(osdc->req_lru.next, struct ceph_osd_request,
-				 r_req_lru_item);
-
-		if (time_before(jiffies, req->r_stamp + timeout))
-			break;
-
-		BUG_ON(req == last_req && req->r_stamp == last_stamp);
-		last_req = req;
-		last_stamp = req->r_stamp;
-
-		osd = req->r_osd;
-		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);
-	}
-
-	/*
-	 * ping osds that are a bit slow.  this ensures that if there
-	 * is a break in the TCP connection we will notice, and reopen
-	 * a connection with that osd (from the fault callback).
-	 */
-	INIT_LIST_HEAD(&slow_osds);
-	list_for_each_entry(req, &osdc->req_lru, r_req_lru_item) {
-		if (time_before(jiffies, req->r_stamp + keepalive))
-			break;
-
-		osd = req->r_osd;
-		BUG_ON(!osd);
-		dout(" tid %llu is slow, will send keepalive on osd%d\n",
-		     req->r_tid, osd->o_osd);
-		list_move_tail(&osd->o_keepalive_item, &slow_osds);
-	}
-	while (!list_empty(&slow_osds)) {
-		osd = list_entry(slow_osds.next, struct ceph_osd,
-				 o_keepalive_item);
-		list_del_init(&osd->o_keepalive_item);
-		ceph_con_keepalive(&osd->o_con);
-	}
-
-	__schedule_osd_timeout(osdc);
-	mutex_unlock(&osdc->request_mutex);
-
-	up_read(&osdc->map_sem);
-}
-
-static void handle_osds_timeout(struct work_struct *work)
-{
-	struct ceph_osd_client *osdc =
-		container_of(work, struct ceph_osd_client,
-			     osds_timeout_work.work);
-	unsigned long delay =
-		osdc->client->mount_args->osd_idle_ttl * HZ >> 2;
-
-	dout("osds timeout\n");
-	down_read(&osdc->map_sem);
-	remove_old_osds(osdc, 0);
-	up_read(&osdc->map_sem);
-
-	schedule_delayed_work(&osdc->osds_timeout_work,
-			      round_jiffies_relative(delay));
-}
-
-/*
- * handle osd op reply.  either call the callback if it is specified,
- * or do the completion to wake up the waiting thread.
- */
-static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
-			 struct ceph_connection *con)
-{
-	struct ceph_osd_reply_head *rhead = msg->front.iov_base;
-	struct ceph_osd_request *req;
-	u64 tid;
-	int numops, object_len, flags;
-	s32 result;
-
-	tid = le64_to_cpu(msg->hdr.tid);
-	if (msg->front.iov_len < sizeof(*rhead))
-		goto bad;
-	numops = le32_to_cpu(rhead->num_ops);
-	object_len = le32_to_cpu(rhead->object_len);
-	result = le32_to_cpu(rhead->result);
-	if (msg->front.iov_len != sizeof(*rhead) + object_len +
-	    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);
-	if (req == NULL) {
-		dout("handle_reply tid %llu dne\n", tid);
-		mutex_unlock(&osdc->request_mutex);
-		return;
-	}
-	ceph_osdc_get_request(req);
-	flags = le32_to_cpu(rhead->flags);
-
-	/*
-	 * if this connection filled our message, drop our reference now, to
-	 * avoid a (safe but slower) revoke later.
-	 */
-	if (req->r_con_filling_msg == con && req->r_reply == msg) {
-		dout(" dropping con_filling_msg ref %p\n", con);
-		req->r_con_filling_msg = NULL;
-		ceph_con_put(con);
-	}
-
-	if (!req->r_got_reply) {
-		unsigned bytes;
-
-		req->r_result = le32_to_cpu(rhead->result);
-		bytes = le32_to_cpu(msg->hdr.data_len);
-		dout("handle_reply result %d bytes %d\n", req->r_result,
-		     bytes);
-		if (req->r_result == 0)
-			req->r_result = bytes;
-
-		/* in case this is a write and we need to replay, */
-		req->r_reassert_version = rhead->reassert_version;
-
-		req->r_got_reply = 1;
-	} else if ((flags & CEPH_OSD_FLAG_ONDISK) == 0) {
-		dout("handle_reply tid %llu dup ack\n", tid);
-		mutex_unlock(&osdc->request_mutex);
-		goto done;
-	}
-
-	dout("handle_reply tid %llu flags %d\n", tid, flags);
-
-	/* either this is a read, or we got the safe response */
-	if (result < 0 ||
-	    (flags & CEPH_OSD_FLAG_ONDISK) ||
-	    ((flags & CEPH_OSD_FLAG_WRITE) == 0))
-		__unregister_request(osdc, req);
-
-	mutex_unlock(&osdc->request_mutex);
-
-	if (req->r_callback)
-		req->r_callback(req, msg);
-	else
-		complete_all(&req->r_completion);
-
-	if (flags & CEPH_OSD_FLAG_ONDISK) {
-		if (req->r_safe_callback)
-			req->r_safe_callback(req, msg);
-		complete_all(&req->r_safe_completion);  /* fsync waiter */
-	}
-
-done:
-	ceph_osdc_put_request(req);
-	return;
-
-bad:
-	pr_err("corrupt osd_op_reply got %d %d expected %d\n",
-	       (int)msg->front.iov_len, le32_to_cpu(msg->hdr.front_len),
-	       (int)sizeof(*rhead));
-	ceph_msg_dump(msg);
-}
-
-
-static int __kick_requests(struct ceph_osd_client *osdc,
-			  struct ceph_osd *kickosd)
-{
-	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->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_osds(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;
-		}
-		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,
-		     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;
-		}
-	}
-
-	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.
- *
- * The message contains any number of incremental and full maps, normally
- * indicating some sort of topology change in the cluster.  Kick requests
- * off to different OSDs as needed.
- */
-void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
-{
-	void *p, *end, *next;
-	u32 nr_maps, maplen;
-	u32 epoch;
-	struct ceph_osdmap *newmap = NULL, *oldmap;
-	int err;
-	struct ceph_fsid fsid;
-
-	dout("handle_map have %u\n", osdc->osdmap ? osdc->osdmap->epoch : 0);
-	p = msg->front.iov_base;
-	end = p + msg->front.iov_len;
-
-	/* verify fsid */
-	ceph_decode_need(&p, end, sizeof(fsid), bad);
-	ceph_decode_copy(&p, &fsid, sizeof(fsid));
-	if (ceph_check_fsid(osdc->client, &fsid) < 0)
-		return;
-
-	down_write(&osdc->map_sem);
-
-	/* incremental maps */
-	ceph_decode_32_safe(&p, end, nr_maps, bad);
-	dout(" %d inc maps\n", nr_maps);
-	while (nr_maps > 0) {
-		ceph_decode_need(&p, end, 2*sizeof(u32), bad);
-		epoch = ceph_decode_32(&p);
-		maplen = ceph_decode_32(&p);
-		ceph_decode_need(&p, end, maplen, bad);
-		next = p + maplen;
-		if (osdc->osdmap && osdc->osdmap->epoch+1 == epoch) {
-			dout("applying incremental map %u len %d\n",
-			     epoch, maplen);
-			newmap = osdmap_apply_incremental(&p, next,
-							  osdc->osdmap,
-							  osdc->client->msgr);
-			if (IS_ERR(newmap)) {
-				err = PTR_ERR(newmap);
-				goto bad;
-			}
-			BUG_ON(!newmap);
-			if (newmap != osdc->osdmap) {
-				ceph_osdmap_destroy(osdc->osdmap);
-				osdc->osdmap = newmap;
-			}
-		} else {
-			dout("ignoring incremental map %u len %d\n",
-			     epoch, maplen);
-		}
-		p = next;
-		nr_maps--;
-	}
-	if (newmap)
-		goto done;
-
-	/* full maps */
-	ceph_decode_32_safe(&p, end, nr_maps, bad);
-	dout(" %d full maps\n", nr_maps);
-	while (nr_maps) {
-		ceph_decode_need(&p, end, 2*sizeof(u32), bad);
-		epoch = ceph_decode_32(&p);
-		maplen = ceph_decode_32(&p);
-		ceph_decode_need(&p, end, maplen, bad);
-		if (nr_maps > 1) {
-			dout("skipping non-latest full map %u len %d\n",
-			     epoch, maplen);
-		} else if (osdc->osdmap && osdc->osdmap->epoch >= epoch) {
-			dout("skipping full map %u len %d, "
-			     "older than our %u\n", epoch, maplen,
-			     osdc->osdmap->epoch);
-		} else {
-			dout("taking full map %u len %d\n", epoch, maplen);
-			newmap = osdmap_decode(&p, p+maplen);
-			if (IS_ERR(newmap)) {
-				err = PTR_ERR(newmap);
-				goto bad;
-			}
-			BUG_ON(!newmap);
-			oldmap = osdc->osdmap;
-			osdc->osdmap = newmap;
-			if (oldmap)
-				ceph_osdmap_destroy(oldmap);
-		}
-		p += maplen;
-		nr_maps--;
-	}
-
-done:
-	downgrade_write(&osdc->map_sem);
-	ceph_monc_got_osdmap(&osdc->client->monc, osdc->osdmap->epoch);
-	if (newmap)
-		kick_requests(osdc, NULL);
-	up_read(&osdc->map_sem);
-	wake_up_all(&osdc->client->auth_wq);
-	return;
-
-bad:
-	pr_err("osdc handle_map corrupt msg\n");
-	ceph_msg_dump(msg);
-	up_write(&osdc->map_sem);
-	return;
-}
-
-/*
- * Register request, send initial attempt.
- */
-int ceph_osdc_start_request(struct ceph_osd_client *osdc,
-			    struct ceph_osd_request *req,
-			    bool nofail)
-{
-	int rc = 0;
-
-	req->r_request->pages = req->r_pages;
-	req->r_request->nr_pages = req->r_num_pages;
-
-	register_request(osdc, req);
-
-	down_read(&osdc->map_sem);
-	mutex_lock(&osdc->request_mutex);
-	/*
-	 * a racing kick_requests() may have sent the message for us
-	 * while we dropped request_mutex above, so only send now if
-	 * 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);
-			}
-		}
-	}
-	mutex_unlock(&osdc->request_mutex);
-	up_read(&osdc->map_sem);
-	return rc;
-}
-
-/*
- * wait for a request to complete
- */
-int ceph_osdc_wait_request(struct ceph_osd_client *osdc,
-			   struct ceph_osd_request *req)
-{
-	int rc;
-
-	rc = wait_for_completion_interruptible(&req->r_completion);
-	if (rc < 0) {
-		mutex_lock(&osdc->request_mutex);
-		__cancel_request(req);
-		__unregister_request(osdc, req);
-		mutex_unlock(&osdc->request_mutex);
-		dout("wait_request tid %llu canceled/timed out\n", req->r_tid);
-		return rc;
-	}
-
-	dout("wait_request tid %llu result %d\n", req->r_tid, req->r_result);
-	return req->r_result;
-}
-
-/*
- * sync - wait for all in-flight requests to flush.  avoid starvation.
- */
-void ceph_osdc_sync(struct ceph_osd_client *osdc)
-{
-	struct ceph_osd_request *req;
-	u64 last_tid, next_tid = 0;
-
-	mutex_lock(&osdc->request_mutex);
-	last_tid = osdc->last_tid;
-	while (1) {
-		req = __lookup_request_ge(osdc, next_tid);
-		if (!req)
-			break;
-		if (req->r_tid > last_tid)
-			break;
-
-		next_tid = req->r_tid + 1;
-		if ((req->r_flags & CEPH_OSD_FLAG_WRITE) == 0)
-			continue;
-
-		ceph_osdc_get_request(req);
-		mutex_unlock(&osdc->request_mutex);
-		dout("sync waiting on tid %llu (last is %llu)\n",
-		     req->r_tid, last_tid);
-		wait_for_completion(&req->r_safe_completion);
-		mutex_lock(&osdc->request_mutex);
-		ceph_osdc_put_request(req);
-	}
-	mutex_unlock(&osdc->request_mutex);
-	dout("sync done (thru tid %llu)\n", last_tid);
-}
-
-/*
- * init, shutdown
- */
-int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client)
-{
-	int err;
-
-	dout("init\n");
-	osdc->client = client;
-	osdc->osdmap = NULL;
-	init_rwsem(&osdc->map_sem);
-	init_completion(&osdc->map_waiters);
-	osdc->last_requested_map = 0;
-	mutex_init(&osdc->request_mutex);
-	osdc->last_tid = 0;
-	osdc->osds = RB_ROOT;
-	INIT_LIST_HEAD(&osdc->osd_lru);
-	osdc->requests = RB_ROOT;
-	INIT_LIST_HEAD(&osdc->req_lru);
-	osdc->num_requests = 0;
-	INIT_DELAYED_WORK(&osdc->timeout_work, handle_timeout);
-	INIT_DELAYED_WORK(&osdc->osds_timeout_work, handle_osds_timeout);
-
-	schedule_delayed_work(&osdc->osds_timeout_work,
-	   round_jiffies_relative(osdc->client->mount_args->osd_idle_ttl * HZ));
-
-	err = -ENOMEM;
-	osdc->req_mempool = mempool_create_kmalloc_pool(10,
-					sizeof(struct ceph_osd_request));
-	if (!osdc->req_mempool)
-		goto out;
-
-	err = ceph_msgpool_init(&osdc->msgpool_op, OSD_OP_FRONT_LEN, 10, true,
-				"osd_op");
-	if (err < 0)
-		goto out_mempool;
-	err = ceph_msgpool_init(&osdc->msgpool_op_reply,
-				OSD_OPREPLY_FRONT_LEN, 10, true,
-				"osd_op_reply");
-	if (err < 0)
-		goto out_msgpool;
-	return 0;
-
-out_msgpool:
-	ceph_msgpool_destroy(&osdc->msgpool_op);
-out_mempool:
-	mempool_destroy(osdc->req_mempool);
-out:
-	return err;
-}
-
-void ceph_osdc_stop(struct ceph_osd_client *osdc)
-{
-	cancel_delayed_work_sync(&osdc->timeout_work);
-	cancel_delayed_work_sync(&osdc->osds_timeout_work);
-	if (osdc->osdmap) {
-		ceph_osdmap_destroy(osdc->osdmap);
-		osdc->osdmap = NULL;
-	}
-	remove_old_osds(osdc, 1);
-	mempool_destroy(osdc->req_mempool);
-	ceph_msgpool_destroy(&osdc->msgpool_op);
-	ceph_msgpool_destroy(&osdc->msgpool_op_reply);
-}
-
-/*
- * Read some contiguous pages.  If we cross a stripe boundary, shorten
- * *plen.  Return number of bytes read, or error.
- */
-int ceph_osdc_readpages(struct ceph_osd_client *osdc,
-			struct ceph_vino vino, struct ceph_file_layout *layout,
-			u64 off, u64 *plen,
-			u32 truncate_seq, u64 truncate_size,
-			struct page **pages, int num_pages)
-{
-	struct ceph_osd_request *req;
-	int rc = 0;
-
-	dout("readpages on ino %llx.%llx on %llu~%llu\n", vino.ino,
-	     vino.snap, off, *plen);
-	req = ceph_osdc_new_request(osdc, layout, vino, off, plen,
-				    CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ,
-				    NULL, 0, truncate_seq, truncate_size, NULL,
-				    false, 1);
-	if (!req)
-		return -ENOMEM;
-
-	/* it may be a short read due to an object boundary */
-	req->r_pages = pages;
-
-	dout("readpages  final extent is %llu~%llu (%d pages)\n",
-	     off, *plen, req->r_num_pages);
-
-	rc = ceph_osdc_start_request(osdc, req, false);
-	if (!rc)
-		rc = ceph_osdc_wait_request(osdc, req);
-
-	ceph_osdc_put_request(req);
-	dout("readpages result %d\n", rc);
-	return rc;
-}
-
-/*
- * do a synchronous write on N pages
- */
-int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino,
-			 struct ceph_file_layout *layout,
-			 struct ceph_snap_context *snapc,
-			 u64 off, u64 len,
-			 u32 truncate_seq, u64 truncate_size,
-			 struct timespec *mtime,
-			 struct page **pages, int num_pages,
-			 int flags, int do_sync, bool nofail)
-{
-	struct ceph_osd_request *req;
-	int rc = 0;
-
-	BUG_ON(vino.snap != CEPH_NOSNAP);
-	req = ceph_osdc_new_request(osdc, layout, vino, off, &len,
-				    CEPH_OSD_OP_WRITE,
-				    flags | CEPH_OSD_FLAG_ONDISK |
-					    CEPH_OSD_FLAG_WRITE,
-				    snapc, do_sync,
-				    truncate_seq, truncate_size, mtime,
-				    nofail, 1);
-	if (!req)
-		return -ENOMEM;
-
-	/* it may be a short write due to an object boundary */
-	req->r_pages = pages;
-	dout("writepages %llu~%llu (%d pages)\n", off, len,
-	     req->r_num_pages);
-
-	rc = ceph_osdc_start_request(osdc, req, nofail);
-	if (!rc)
-		rc = ceph_osdc_wait_request(osdc, req);
-
-	ceph_osdc_put_request(req);
-	if (rc == 0)
-		rc = len;
-	dout("writepages result %d\n", rc);
-	return rc;
-}
-
-/*
- * handle incoming message
- */
-static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
-{
-	struct ceph_osd *osd = con->private;
-	struct ceph_osd_client *osdc;
-	int type = le16_to_cpu(msg->hdr.type);
-
-	if (!osd)
-		goto out;
-	osdc = osd->o_osdc;
-
-	switch (type) {
-	case CEPH_MSG_OSD_MAP:
-		ceph_osdc_handle_map(osdc, msg);
-		break;
-	case CEPH_MSG_OSD_OPREPLY:
-		handle_reply(osdc, msg, con);
-		break;
-
-	default:
-		pr_err("received unknown message type %d %s\n", type,
-		       ceph_msg_type_name(type));
-	}
-out:
-	ceph_msg_put(msg);
-}
-
-/*
- * lookup and return message for incoming reply.  set up reply message
- * pages.
- */
-static struct ceph_msg *get_reply(struct ceph_connection *con,
-				  struct ceph_msg_header *hdr,
-				  int *skip)
-{
-	struct ceph_osd *osd = con->private;
-	struct ceph_osd_client *osdc = osd->o_osdc;
-	struct ceph_msg *m;
-	struct ceph_osd_request *req;
-	int front = le32_to_cpu(hdr->front_len);
-	int data_len = le32_to_cpu(hdr->data_len);
-	u64 tid;
-
-	tid = le64_to_cpu(hdr->tid);
-	mutex_lock(&osdc->request_mutex);
-	req = __lookup_request(osdc, tid);
-	if (!req) {
-		*skip = 1;
-		m = NULL;
-		pr_info("get_reply unknown tid %llu from osd%d\n", tid,
-			osd->o_osd);
-		goto out;
-	}
-
-	if (req->r_con_filling_msg) {
-		dout("get_reply revoking msg %p from old con %p\n",
-		     req->r_reply, req->r_con_filling_msg);
-		ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply);
-		ceph_con_put(req->r_con_filling_msg);
-		req->r_con_filling_msg = NULL;
-	}
-
-	if (front > req->r_reply->front.iov_len) {
-		pr_warning("get_reply front %d > preallocated %d\n",
-			   front, (int)req->r_reply->front.iov_len);
-		m = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, front, GFP_NOFS);
-		if (!m)
-			goto out;
-		ceph_msg_put(req->r_reply);
-		req->r_reply = m;
-	}
-	m = ceph_msg_get(req->r_reply);
-
-	if (data_len > 0) {
-		unsigned data_off = le16_to_cpu(hdr->data_off);
-		int want = calc_pages_for(data_off & ~PAGE_MASK, data_len);
-
-		if (unlikely(req->r_num_pages < want)) {
-			pr_warning("tid %lld reply %d > expected %d pages\n",
-				   tid, want, m->nr_pages);
-			*skip = 1;
-			ceph_msg_put(m);
-			m = NULL;
-			goto out;
-		}
-		m->pages = req->r_pages;
-		m->nr_pages = req->r_num_pages;
-	}
-	*skip = 0;
-	req->r_con_filling_msg = ceph_con_get(con);
-	dout("get_reply tid %lld %p\n", tid, m);
-
-out:
-	mutex_unlock(&osdc->request_mutex);
-	return m;
-
-}
-
-static struct ceph_msg *alloc_msg(struct ceph_connection *con,
-				  struct ceph_msg_header *hdr,
-				  int *skip)
-{
-	struct ceph_osd *osd = con->private;
-	int type = le16_to_cpu(hdr->type);
-	int front = le32_to_cpu(hdr->front_len);
-
-	switch (type) {
-	case CEPH_MSG_OSD_MAP:
-		return ceph_msg_new(type, front, GFP_NOFS);
-	case CEPH_MSG_OSD_OPREPLY:
-		return get_reply(con, hdr, skip);
-	default:
-		pr_info("alloc_msg unexpected msg type %d from osd%d\n", type,
-			osd->o_osd);
-		*skip = 1;
-		return NULL;
-	}
-}
-
-/*
- * Wrappers to refcount containing ceph_osd struct
- */
-static struct ceph_connection *get_osd_con(struct ceph_connection *con)
-{
-	struct ceph_osd *osd = con->private;
-	if (get_osd(osd))
-		return con;
-	return NULL;
-}
-
-static void put_osd_con(struct ceph_connection *con)
-{
-	struct ceph_osd *osd = con->private;
-	put_osd(osd);
-}
-
-/*
- * authentication
- */
-static int get_authorizer(struct ceph_connection *con,
-			  void **buf, int *len, int *proto,
-			  void **reply_buf, int *reply_len, int force_new)
-{
-	struct ceph_osd *o = con->private;
-	struct ceph_osd_client *osdc = o->o_osdc;
-	struct ceph_auth_client *ac = osdc->client->monc.auth;
-	int ret = 0;
-
-	if (force_new && o->o_authorizer) {
-		ac->ops->destroy_authorizer(ac, o->o_authorizer);
-		o->o_authorizer = NULL;
-	}
-	if (o->o_authorizer == NULL) {
-		ret = ac->ops->create_authorizer(
-			ac, CEPH_ENTITY_TYPE_OSD,
-			&o->o_authorizer,
-			&o->o_authorizer_buf,
-			&o->o_authorizer_buf_len,
-			&o->o_authorizer_reply_buf,
-			&o->o_authorizer_reply_buf_len);
-		if (ret)
-			return ret;
-	}
-
-	*proto = ac->protocol;
-	*buf = o->o_authorizer_buf;
-	*len = o->o_authorizer_buf_len;
-	*reply_buf = o->o_authorizer_reply_buf;
-	*reply_len = o->o_authorizer_reply_buf_len;
-	return 0;
-}
-
-
-static int verify_authorizer_reply(struct ceph_connection *con, int len)
-{
-	struct ceph_osd *o = con->private;
-	struct ceph_osd_client *osdc = o->o_osdc;
-	struct ceph_auth_client *ac = osdc->client->monc.auth;
-
-	return ac->ops->verify_authorizer_reply(ac, o->o_authorizer, len);
-}
-
-static int invalidate_authorizer(struct ceph_connection *con)
-{
-	struct ceph_osd *o = con->private;
-	struct ceph_osd_client *osdc = o->o_osdc;
-	struct ceph_auth_client *ac = osdc->client->monc.auth;
-
-	if (ac->ops->invalidate_authorizer)
-		ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD);
-
-	return ceph_monc_validate_auth(&osdc->client->monc);
-}
-
-static const struct ceph_connection_operations osd_con_ops = {
-	.get = get_osd_con,
-	.put = put_osd_con,
-	.dispatch = dispatch,
-	.get_authorizer = get_authorizer,
-	.verify_authorizer_reply = verify_authorizer_reply,
-	.invalidate_authorizer = invalidate_authorizer,
-	.alloc_msg = alloc_msg,
-	.fault = osd_reset,
-};
diff --git a/fs/ceph/osd_client.h b/fs/ceph/osd_client.h
deleted file mode 100644
index ce77698..0000000
--- a/fs/ceph/osd_client.h
+++ /dev/null
@@ -1,167 +0,0 @@
-#ifndef _FS_CEPH_OSD_CLIENT_H
-#define _FS_CEPH_OSD_CLIENT_H
-
-#include <linux/completion.h>
-#include <linux/kref.h>
-#include <linux/mempool.h>
-#include <linux/rbtree.h>
-
-#include "types.h"
-#include "osdmap.h"
-#include "messenger.h"
-
-struct ceph_msg;
-struct ceph_snap_context;
-struct ceph_osd_request;
-struct ceph_osd_client;
-struct ceph_authorizer;
-
-/*
- * completion callback for async writepages
- */
-typedef void (*ceph_osdc_callback_t)(struct ceph_osd_request *,
-				     struct ceph_msg *);
-
-/* a given osd we're communicating with */
-struct ceph_osd {
-	atomic_t o_ref;
-	struct ceph_osd_client *o_osdc;
-	int o_osd;
-	int o_incarnation;
-	struct rb_node o_node;
-	struct ceph_connection o_con;
-	struct list_head o_requests;
-	struct list_head o_osd_lru;
-	struct ceph_authorizer *o_authorizer;
-	void *o_authorizer_buf, *o_authorizer_reply_buf;
-	size_t o_authorizer_buf_len, o_authorizer_reply_buf_len;
-	unsigned long lru_ttl;
-	int o_marked_for_keepalive;
-	struct list_head o_keepalive_item;
-};
-
-/* an in-flight request */
-struct ceph_osd_request {
-	u64             r_tid;              /* unique for this client */
-	struct rb_node  r_node;
-	struct list_head r_req_lru_item;
-	struct list_head r_osd_item;
-	struct ceph_osd *r_osd;
-	struct ceph_pg   r_pgid;
-	int              r_pg_osds[CEPH_PG_MAX_SIZE];
-	int              r_num_pg_osds;
-
-	struct ceph_connection *r_con_filling_msg;
-
-	struct ceph_msg  *r_request, *r_reply;
-	int               r_result;
-	int               r_flags;     /* any additional flags for the osd */
-	u32               r_sent;      /* >0 if r_request is sending/sent */
-	int               r_got_reply;
-
-	struct ceph_osd_client *r_osdc;
-	struct kref       r_kref;
-	bool              r_mempool;
-	struct completion r_completion, r_safe_completion;
-	ceph_osdc_callback_t r_callback, r_safe_callback;
-	struct ceph_eversion r_reassert_version;
-	struct list_head  r_unsafe_item;
-
-	struct inode *r_inode;         	      /* for use by callbacks */
-
-	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 */
-	unsigned          r_num_pages;        /* size of page array (follows) */
-	struct page     **r_pages;            /* pages for data payload */
-	int               r_pages_from_pool;
-	int               r_own_pages;        /* if true, i own page list */
-};
-
-struct ceph_osd_client {
-	struct ceph_client     *client;
-
-	struct ceph_osdmap     *osdmap;       /* current map */
-	struct rw_semaphore    map_sem;
-	struct completion      map_waiters;
-	u64                    last_requested_map;
-
-	struct mutex           request_mutex;
-	struct rb_root         osds;          /* osds */
-	struct list_head       osd_lru;       /* idle osds */
-	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 */
-	int                    num_requests;
-	struct delayed_work    timeout_work;
-	struct delayed_work    osds_timeout_work;
-#ifdef CONFIG_DEBUG_FS
-	struct dentry 	       *debugfs_file;
-#endif
-
-	mempool_t              *req_mempool;
-
-	struct ceph_msgpool	msgpool_op;
-	struct ceph_msgpool	msgpool_op_reply;
-};
-
-extern int ceph_osdc_init(struct ceph_osd_client *osdc,
-			  struct ceph_client *client);
-extern void ceph_osdc_stop(struct ceph_osd_client *osdc);
-
-extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc,
-				   struct ceph_msg *msg);
-extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc,
-				 struct ceph_msg *msg);
-
-extern struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *,
-				      struct ceph_file_layout *layout,
-				      struct ceph_vino vino,
-				      u64 offset, u64 *len, int op, int flags,
-				      struct ceph_snap_context *snapc,
-				      int do_sync, u32 truncate_seq,
-				      u64 truncate_size,
-				      struct timespec *mtime,
-				      bool use_mempool, int num_reply);
-
-static inline void ceph_osdc_get_request(struct ceph_osd_request *req)
-{
-	kref_get(&req->r_kref);
-}
-extern void ceph_osdc_release_request(struct kref *kref);
-static inline void ceph_osdc_put_request(struct ceph_osd_request *req)
-{
-	kref_put(&req->r_kref, ceph_osdc_release_request);
-}
-
-extern int ceph_osdc_start_request(struct ceph_osd_client *osdc,
-				   struct ceph_osd_request *req,
-				   bool nofail);
-extern int ceph_osdc_wait_request(struct ceph_osd_client *osdc,
-				  struct ceph_osd_request *req);
-extern void ceph_osdc_sync(struct ceph_osd_client *osdc);
-
-extern int ceph_osdc_readpages(struct ceph_osd_client *osdc,
-			       struct ceph_vino vino,
-			       struct ceph_file_layout *layout,
-			       u64 off, u64 *plen,
-			       u32 truncate_seq, u64 truncate_size,
-			       struct page **pages, int nr_pages);
-
-extern int ceph_osdc_writepages(struct ceph_osd_client *osdc,
-				struct ceph_vino vino,
-				struct ceph_file_layout *layout,
-				struct ceph_snap_context *sc,
-				u64 off, u64 len,
-				u32 truncate_seq, u64 truncate_size,
-				struct timespec *mtime,
-				struct page **pages, int nr_pages,
-				int flags, int do_sync, bool nofail);
-
-#endif
-
diff --git a/fs/ceph/osdmap.c b/fs/ceph/osdmap.c
deleted file mode 100644
index e31f118..0000000
--- a/fs/ceph/osdmap.c
+++ /dev/null
@@ -1,1110 +0,0 @@
-
-#include "ceph_debug.h"
-
-#include <linux/slab.h>
-#include <asm/div64.h>
-
-#include "super.h"
-#include "osdmap.h"
-#include "crush/hash.h"
-#include "crush/mapper.h"
-#include "decode.h"
-
-char *ceph_osdmap_state_str(char *str, int len, int state)
-{
-	int flag = 0;
-
-	if (!len)
-		goto done;
-
-	*str = '\0';
-	if (state) {
-		if (state & CEPH_OSD_EXISTS) {
-			snprintf(str, len, "exists");
-			flag = 1;
-		}
-		if (state & CEPH_OSD_UP) {
-			snprintf(str, len, "%s%s%s", str, (flag ? ", " : ""),
-				 "up");
-			flag = 1;
-		}
-	} else {
-		snprintf(str, len, "doesn't exist");
-	}
-done:
-	return str;
-}
-
-/* maps */
-
-static int calc_bits_of(unsigned t)
-{
-	int b = 0;
-	while (t) {
-		t = t >> 1;
-		b++;
-	}
-	return b;
-}
-
-/*
- * the foo_mask is the smallest value 2^n-1 that is >= foo.
- */
-static void calc_pg_masks(struct ceph_pg_pool_info *pi)
-{
-	pi->pg_num_mask = (1 << calc_bits_of(le32_to_cpu(pi->v.pg_num)-1)) - 1;
-	pi->pgp_num_mask =
-		(1 << calc_bits_of(le32_to_cpu(pi->v.pgp_num)-1)) - 1;
-	pi->lpg_num_mask =
-		(1 << calc_bits_of(le32_to_cpu(pi->v.lpg_num)-1)) - 1;
-	pi->lpgp_num_mask =
-		(1 << calc_bits_of(le32_to_cpu(pi->v.lpgp_num)-1)) - 1;
-}
-
-/*
- * decode crush map
- */
-static int crush_decode_uniform_bucket(void **p, void *end,
-				       struct crush_bucket_uniform *b)
-{
-	dout("crush_decode_uniform_bucket %p to %p\n", *p, end);
-	ceph_decode_need(p, end, (1+b->h.size) * sizeof(u32), bad);
-	b->item_weight = ceph_decode_32(p);
-	return 0;
-bad:
-	return -EINVAL;
-}
-
-static int crush_decode_list_bucket(void **p, void *end,
-				    struct crush_bucket_list *b)
-{
-	int j;
-	dout("crush_decode_list_bucket %p to %p\n", *p, end);
-	b->item_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS);
-	if (b->item_weights == NULL)
-		return -ENOMEM;
-	b->sum_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS);
-	if (b->sum_weights == NULL)
-		return -ENOMEM;
-	ceph_decode_need(p, end, 2 * b->h.size * sizeof(u32), bad);
-	for (j = 0; j < b->h.size; j++) {
-		b->item_weights[j] = ceph_decode_32(p);
-		b->sum_weights[j] = ceph_decode_32(p);
-	}
-	return 0;
-bad:
-	return -EINVAL;
-}
-
-static int crush_decode_tree_bucket(void **p, void *end,
-				    struct crush_bucket_tree *b)
-{
-	int j;
-	dout("crush_decode_tree_bucket %p to %p\n", *p, end);
-	ceph_decode_32_safe(p, end, b->num_nodes, bad);
-	b->node_weights = kcalloc(b->num_nodes, sizeof(u32), GFP_NOFS);
-	if (b->node_weights == NULL)
-		return -ENOMEM;
-	ceph_decode_need(p, end, b->num_nodes * sizeof(u32), bad);
-	for (j = 0; j < b->num_nodes; j++)
-		b->node_weights[j] = ceph_decode_32(p);
-	return 0;
-bad:
-	return -EINVAL;
-}
-
-static int crush_decode_straw_bucket(void **p, void *end,
-				     struct crush_bucket_straw *b)
-{
-	int j;
-	dout("crush_decode_straw_bucket %p to %p\n", *p, end);
-	b->item_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS);
-	if (b->item_weights == NULL)
-		return -ENOMEM;
-	b->straws = kcalloc(b->h.size, sizeof(u32), GFP_NOFS);
-	if (b->straws == NULL)
-		return -ENOMEM;
-	ceph_decode_need(p, end, 2 * b->h.size * sizeof(u32), bad);
-	for (j = 0; j < b->h.size; j++) {
-		b->item_weights[j] = ceph_decode_32(p);
-		b->straws[j] = ceph_decode_32(p);
-	}
-	return 0;
-bad:
-	return -EINVAL;
-}
-
-static struct crush_map *crush_decode(void *pbyval, void *end)
-{
-	struct crush_map *c;
-	int err = -EINVAL;
-	int i, j;
-	void **p = &pbyval;
-	void *start = pbyval;
-	u32 magic;
-
-	dout("crush_decode %p to %p len %d\n", *p, end, (int)(end - *p));
-
-	c = kzalloc(sizeof(*c), GFP_NOFS);
-	if (c == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	ceph_decode_need(p, end, 4*sizeof(u32), bad);
-	magic = ceph_decode_32(p);
-	if (magic != CRUSH_MAGIC) {
-		pr_err("crush_decode magic %x != current %x\n",
-		       (unsigned)magic, (unsigned)CRUSH_MAGIC);
-		goto bad;
-	}
-	c->max_buckets = ceph_decode_32(p);
-	c->max_rules = ceph_decode_32(p);
-	c->max_devices = ceph_decode_32(p);
-
-	c->device_parents = kcalloc(c->max_devices, sizeof(u32), GFP_NOFS);
-	if (c->device_parents == NULL)
-		goto badmem;
-	c->bucket_parents = kcalloc(c->max_buckets, sizeof(u32), GFP_NOFS);
-	if (c->bucket_parents == NULL)
-		goto badmem;
-
-	c->buckets = kcalloc(c->max_buckets, sizeof(*c->buckets), GFP_NOFS);
-	if (c->buckets == NULL)
-		goto badmem;
-	c->rules = kcalloc(c->max_rules, sizeof(*c->rules), GFP_NOFS);
-	if (c->rules == NULL)
-		goto badmem;
-
-	/* buckets */
-	for (i = 0; i < c->max_buckets; i++) {
-		int size = 0;
-		u32 alg;
-		struct crush_bucket *b;
-
-		ceph_decode_32_safe(p, end, alg, bad);
-		if (alg == 0) {
-			c->buckets[i] = NULL;
-			continue;
-		}
-		dout("crush_decode bucket %d off %x %p to %p\n",
-		     i, (int)(*p-start), *p, end);
-
-		switch (alg) {
-		case CRUSH_BUCKET_UNIFORM:
-			size = sizeof(struct crush_bucket_uniform);
-			break;
-		case CRUSH_BUCKET_LIST:
-			size = sizeof(struct crush_bucket_list);
-			break;
-		case CRUSH_BUCKET_TREE:
-			size = sizeof(struct crush_bucket_tree);
-			break;
-		case CRUSH_BUCKET_STRAW:
-			size = sizeof(struct crush_bucket_straw);
-			break;
-		default:
-			err = -EINVAL;
-			goto bad;
-		}
-		BUG_ON(size == 0);
-		b = c->buckets[i] = kzalloc(size, GFP_NOFS);
-		if (b == NULL)
-			goto badmem;
-
-		ceph_decode_need(p, end, 4*sizeof(u32), bad);
-		b->id = ceph_decode_32(p);
-		b->type = ceph_decode_16(p);
-		b->alg = ceph_decode_8(p);
-		b->hash = ceph_decode_8(p);
-		b->weight = ceph_decode_32(p);
-		b->size = ceph_decode_32(p);
-
-		dout("crush_decode bucket size %d off %x %p to %p\n",
-		     b->size, (int)(*p-start), *p, end);
-
-		b->items = kcalloc(b->size, sizeof(__s32), GFP_NOFS);
-		if (b->items == NULL)
-			goto badmem;
-		b->perm = kcalloc(b->size, sizeof(u32), GFP_NOFS);
-		if (b->perm == NULL)
-			goto badmem;
-		b->perm_n = 0;
-
-		ceph_decode_need(p, end, b->size*sizeof(u32), bad);
-		for (j = 0; j < b->size; j++)
-			b->items[j] = ceph_decode_32(p);
-
-		switch (b->alg) {
-		case CRUSH_BUCKET_UNIFORM:
-			err = crush_decode_uniform_bucket(p, end,
-				  (struct crush_bucket_uniform *)b);
-			if (err < 0)
-				goto bad;
-			break;
-		case CRUSH_BUCKET_LIST:
-			err = crush_decode_list_bucket(p, end,
-			       (struct crush_bucket_list *)b);
-			if (err < 0)
-				goto bad;
-			break;
-		case CRUSH_BUCKET_TREE:
-			err = crush_decode_tree_bucket(p, end,
-				(struct crush_bucket_tree *)b);
-			if (err < 0)
-				goto bad;
-			break;
-		case CRUSH_BUCKET_STRAW:
-			err = crush_decode_straw_bucket(p, end,
-				(struct crush_bucket_straw *)b);
-			if (err < 0)
-				goto bad;
-			break;
-		}
-	}
-
-	/* rules */
-	dout("rule vec is %p\n", c->rules);
-	for (i = 0; i < c->max_rules; i++) {
-		u32 yes;
-		struct crush_rule *r;
-
-		ceph_decode_32_safe(p, end, yes, bad);
-		if (!yes) {
-			dout("crush_decode NO rule %d off %x %p to %p\n",
-			     i, (int)(*p-start), *p, end);
-			c->rules[i] = NULL;
-			continue;
-		}
-
-		dout("crush_decode rule %d off %x %p to %p\n",
-		     i, (int)(*p-start), *p, end);
-
-		/* len */
-		ceph_decode_32_safe(p, end, yes, bad);
-#if BITS_PER_LONG == 32
-		err = -EINVAL;
-		if (yes > ULONG_MAX / sizeof(struct crush_rule_step))
-			goto bad;
-#endif
-		r = c->rules[i] = kmalloc(sizeof(*r) +
-					  yes*sizeof(struct crush_rule_step),
-					  GFP_NOFS);
-		if (r == NULL)
-			goto badmem;
-		dout(" rule %d is at %p\n", i, r);
-		r->len = yes;
-		ceph_decode_copy_safe(p, end, &r->mask, 4, bad); /* 4 u8's */
-		ceph_decode_need(p, end, r->len*3*sizeof(u32), bad);
-		for (j = 0; j < r->len; j++) {
-			r->steps[j].op = ceph_decode_32(p);
-			r->steps[j].arg1 = ceph_decode_32(p);
-			r->steps[j].arg2 = ceph_decode_32(p);
-		}
-	}
-
-	/* ignore trailing name maps. */
-
-	dout("crush_decode success\n");
-	return c;
-
-badmem:
-	err = -ENOMEM;
-bad:
-	dout("crush_decode fail %d\n", err);
-	crush_destroy(c);
-	return ERR_PTR(err);
-}
-
-/*
- * rbtree of pg_mapping for handling pg_temp (explicit mapping of pgid
- * to a set of osds)
- */
-static int pgid_cmp(struct ceph_pg l, struct ceph_pg r)
-{
-	u64 a = *(u64 *)&l;
-	u64 b = *(u64 *)&r;
-
-	if (a < b)
-		return -1;
-	if (a > b)
-		return 1;
-	return 0;
-}
-
-static int __insert_pg_mapping(struct ceph_pg_mapping *new,
-			       struct rb_root *root)
-{
-	struct rb_node **p = &root->rb_node;
-	struct rb_node *parent = NULL;
-	struct ceph_pg_mapping *pg = NULL;
-	int c;
-
-	while (*p) {
-		parent = *p;
-		pg = rb_entry(parent, struct ceph_pg_mapping, node);
-		c = pgid_cmp(new->pgid, pg->pgid);
-		if (c < 0)
-			p = &(*p)->rb_left;
-		else if (c > 0)
-			p = &(*p)->rb_right;
-		else
-			return -EEXIST;
-	}
-
-	rb_link_node(&new->node, parent, p);
-	rb_insert_color(&new->node, root);
-	return 0;
-}
-
-static struct ceph_pg_mapping *__lookup_pg_mapping(struct rb_root *root,
-						   struct ceph_pg pgid)
-{
-	struct rb_node *n = root->rb_node;
-	struct ceph_pg_mapping *pg;
-	int c;
-
-	while (n) {
-		pg = rb_entry(n, struct ceph_pg_mapping, node);
-		c = pgid_cmp(pgid, pg->pgid);
-		if (c < 0)
-			n = n->rb_left;
-		else if (c > 0)
-			n = n->rb_right;
-		else
-			return pg;
-	}
-	return NULL;
-}
-
-/*
- * rbtree of pg pool info
- */
-static int __insert_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *new)
-{
-	struct rb_node **p = &root->rb_node;
-	struct rb_node *parent = NULL;
-	struct ceph_pg_pool_info *pi = NULL;
-
-	while (*p) {
-		parent = *p;
-		pi = rb_entry(parent, struct ceph_pg_pool_info, node);
-		if (new->id < pi->id)
-			p = &(*p)->rb_left;
-		else if (new->id > pi->id)
-			p = &(*p)->rb_right;
-		else
-			return -EEXIST;
-	}
-
-	rb_link_node(&new->node, parent, p);
-	rb_insert_color(&new->node, root);
-	return 0;
-}
-
-static struct ceph_pg_pool_info *__lookup_pg_pool(struct rb_root *root, int id)
-{
-	struct ceph_pg_pool_info *pi;
-	struct rb_node *n = root->rb_node;
-
-	while (n) {
-		pi = rb_entry(n, struct ceph_pg_pool_info, node);
-		if (id < pi->id)
-			n = n->rb_left;
-		else if (id > pi->id)
-			n = n->rb_right;
-		else
-			return pi;
-	}
-	return NULL;
-}
-
-static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi)
-{
-	rb_erase(&pi->node, root);
-	kfree(pi->name);
-	kfree(pi);
-}
-
-static int __decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi)
-{
-	unsigned n, m;
-
-	ceph_decode_copy(p, &pi->v, sizeof(pi->v));
-	calc_pg_masks(pi);
-
-	/* num_snaps * snap_info_t */
-	n = le32_to_cpu(pi->v.num_snaps);
-	while (n--) {
-		ceph_decode_need(p, end, sizeof(u64) + 1 + sizeof(u64) +
-				 sizeof(struct ceph_timespec), bad);
-		*p += sizeof(u64) +       /* key */
-			1 + sizeof(u64) + /* u8, snapid */
-			sizeof(struct ceph_timespec);
-		m = ceph_decode_32(p);    /* snap name */
-		*p += m;
-	}
-
-	*p += le32_to_cpu(pi->v.num_removed_snap_intervals) * sizeof(u64) * 2;
-	return 0;
-
-bad:
-	return -EINVAL;
-}
-
-static int __decode_pool_names(void **p, void *end, struct ceph_osdmap *map)
-{
-	struct ceph_pg_pool_info *pi;
-	u32 num, len, pool;
-
-	ceph_decode_32_safe(p, end, num, bad);
-	dout(" %d pool names\n", num);
-	while (num--) {
-		ceph_decode_32_safe(p, end, pool, bad);
-		ceph_decode_32_safe(p, end, len, bad);
-		dout("  pool %d len %d\n", pool, len);
-		pi = __lookup_pg_pool(&map->pg_pools, pool);
-		if (pi) {
-			kfree(pi->name);
-			pi->name = kmalloc(len + 1, GFP_NOFS);
-			if (pi->name) {
-				memcpy(pi->name, *p, len);
-				pi->name[len] = '\0';
-				dout("  name is %s\n", pi->name);
-			}
-		}
-		*p += len;
-	}
-	return 0;
-
-bad:
-	return -EINVAL;
-}
-
-/*
- * osd map
- */
-void ceph_osdmap_destroy(struct ceph_osdmap *map)
-{
-	dout("osdmap_destroy %p\n", map);
-	if (map->crush)
-		crush_destroy(map->crush);
-	while (!RB_EMPTY_ROOT(&map->pg_temp)) {
-		struct ceph_pg_mapping *pg =
-			rb_entry(rb_first(&map->pg_temp),
-				 struct ceph_pg_mapping, node);
-		rb_erase(&pg->node, &map->pg_temp);
-		kfree(pg);
-	}
-	while (!RB_EMPTY_ROOT(&map->pg_pools)) {
-		struct ceph_pg_pool_info *pi =
-			rb_entry(rb_first(&map->pg_pools),
-				 struct ceph_pg_pool_info, node);
-		__remove_pg_pool(&map->pg_pools, pi);
-	}
-	kfree(map->osd_state);
-	kfree(map->osd_weight);
-	kfree(map->osd_addr);
-	kfree(map);
-}
-
-/*
- * adjust max osd value.  reallocate arrays.
- */
-static int osdmap_set_max_osd(struct ceph_osdmap *map, int max)
-{
-	u8 *state;
-	struct ceph_entity_addr *addr;
-	u32 *weight;
-
-	state = kcalloc(max, sizeof(*state), GFP_NOFS);
-	addr = kcalloc(max, sizeof(*addr), GFP_NOFS);
-	weight = kcalloc(max, sizeof(*weight), GFP_NOFS);
-	if (state == NULL || addr == NULL || weight == NULL) {
-		kfree(state);
-		kfree(addr);
-		kfree(weight);
-		return -ENOMEM;
-	}
-
-	/* copy old? */
-	if (map->osd_state) {
-		memcpy(state, map->osd_state, map->max_osd*sizeof(*state));
-		memcpy(addr, map->osd_addr, map->max_osd*sizeof(*addr));
-		memcpy(weight, map->osd_weight, map->max_osd*sizeof(*weight));
-		kfree(map->osd_state);
-		kfree(map->osd_addr);
-		kfree(map->osd_weight);
-	}
-
-	map->osd_state = state;
-	map->osd_weight = weight;
-	map->osd_addr = addr;
-	map->max_osd = max;
-	return 0;
-}
-
-/*
- * decode a full map.
- */
-struct ceph_osdmap *osdmap_decode(void **p, void *end)
-{
-	struct ceph_osdmap *map;
-	u16 version;
-	u32 len, max, i;
-	u8 ev;
-	int err = -EINVAL;
-	void *start = *p;
-	struct ceph_pg_pool_info *pi;
-
-	dout("osdmap_decode %p to %p len %d\n", *p, end, (int)(end - *p));
-
-	map = kzalloc(sizeof(*map), GFP_NOFS);
-	if (map == NULL)
-		return ERR_PTR(-ENOMEM);
-	map->pg_temp = RB_ROOT;
-
-	ceph_decode_16_safe(p, end, version, bad);
-	if (version > CEPH_OSDMAP_VERSION) {
-		pr_warning("got unknown v %d > %d of osdmap\n", version,
-			   CEPH_OSDMAP_VERSION);
-		goto bad;
-	}
-
-	ceph_decode_need(p, end, 2*sizeof(u64)+6*sizeof(u32), bad);
-	ceph_decode_copy(p, &map->fsid, sizeof(map->fsid));
-	map->epoch = ceph_decode_32(p);
-	ceph_decode_copy(p, &map->created, sizeof(map->created));
-	ceph_decode_copy(p, &map->modified, sizeof(map->modified));
-
-	ceph_decode_32_safe(p, end, max, bad);
-	while (max--) {
-		ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad);
-		pi = kzalloc(sizeof(*pi), GFP_NOFS);
-		if (!pi)
-			goto bad;
-		pi->id = ceph_decode_32(p);
-		ev = ceph_decode_8(p); /* encoding version */
-		if (ev > CEPH_PG_POOL_VERSION) {
-			pr_warning("got unknown v %d > %d of ceph_pg_pool\n",
-				   ev, CEPH_PG_POOL_VERSION);
-			kfree(pi);
-			goto bad;
-		}
-		err = __decode_pool(p, end, pi);
-		if (err < 0)
-			goto bad;
-		__insert_pg_pool(&map->pg_pools, pi);
-	}
-
-	if (version >= 5 && __decode_pool_names(p, end, map) < 0)
-		goto bad;
-
-	ceph_decode_32_safe(p, end, map->pool_max, bad);
-
-	ceph_decode_32_safe(p, end, map->flags, bad);
-
-	max = ceph_decode_32(p);
-
-	/* (re)alloc osd arrays */
-	err = osdmap_set_max_osd(map, max);
-	if (err < 0)
-		goto bad;
-	dout("osdmap_decode max_osd = %d\n", map->max_osd);
-
-	/* osds */
-	err = -EINVAL;
-	ceph_decode_need(p, end, 3*sizeof(u32) +
-			 map->max_osd*(1 + sizeof(*map->osd_weight) +
-				       sizeof(*map->osd_addr)), bad);
-	*p += 4; /* skip length field (should match max) */
-	ceph_decode_copy(p, map->osd_state, map->max_osd);
-
-	*p += 4; /* skip length field (should match max) */
-	for (i = 0; i < map->max_osd; i++)
-		map->osd_weight[i] = ceph_decode_32(p);
-
-	*p += 4; /* skip length field (should match max) */
-	ceph_decode_copy(p, map->osd_addr, map->max_osd*sizeof(*map->osd_addr));
-	for (i = 0; i < map->max_osd; i++)
-		ceph_decode_addr(&map->osd_addr[i]);
-
-	/* pg_temp */
-	ceph_decode_32_safe(p, end, len, bad);
-	for (i = 0; i < len; i++) {
-		int n, j;
-		struct ceph_pg pgid;
-		struct ceph_pg_mapping *pg;
-
-		ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad);
-		ceph_decode_copy(p, &pgid, sizeof(pgid));
-		n = ceph_decode_32(p);
-		ceph_decode_need(p, end, n * sizeof(u32), bad);
-		err = -ENOMEM;
-		pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS);
-		if (!pg)
-			goto bad;
-		pg->pgid = pgid;
-		pg->len = n;
-		for (j = 0; j < n; j++)
-			pg->osds[j] = ceph_decode_32(p);
-
-		err = __insert_pg_mapping(pg, &map->pg_temp);
-		if (err)
-			goto bad;
-		dout(" added pg_temp %llx len %d\n", *(u64 *)&pgid, len);
-	}
-
-	/* crush */
-	ceph_decode_32_safe(p, end, len, bad);
-	dout("osdmap_decode crush len %d from off 0x%x\n", len,
-	     (int)(*p - start));
-	ceph_decode_need(p, end, len, bad);
-	map->crush = crush_decode(*p, end);
-	*p += len;
-	if (IS_ERR(map->crush)) {
-		err = PTR_ERR(map->crush);
-		map->crush = NULL;
-		goto bad;
-	}
-
-	/* ignore the rest of the map */
-	*p = end;
-
-	dout("osdmap_decode done %p %p\n", *p, end);
-	return map;
-
-bad:
-	dout("osdmap_decode fail\n");
-	ceph_osdmap_destroy(map);
-	return ERR_PTR(err);
-}
-
-/*
- * decode and apply an incremental map update.
- */
-struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
-					     struct ceph_osdmap *map,
-					     struct ceph_messenger *msgr)
-{
-	struct crush_map *newcrush = NULL;
-	struct ceph_fsid fsid;
-	u32 epoch = 0;
-	struct ceph_timespec modified;
-	u32 len, pool;
-	__s32 new_pool_max, new_flags, max;
-	void *start = *p;
-	int err = -EINVAL;
-	u16 version;
-	struct rb_node *rbp;
-
-	ceph_decode_16_safe(p, end, version, bad);
-	if (version > CEPH_OSDMAP_INC_VERSION) {
-		pr_warning("got unknown v %d > %d of inc osdmap\n", version,
-			   CEPH_OSDMAP_INC_VERSION);
-		goto bad;
-	}
-
-	ceph_decode_need(p, end, sizeof(fsid)+sizeof(modified)+2*sizeof(u32),
-			 bad);
-	ceph_decode_copy(p, &fsid, sizeof(fsid));
-	epoch = ceph_decode_32(p);
-	BUG_ON(epoch != map->epoch+1);
-	ceph_decode_copy(p, &modified, sizeof(modified));
-	new_pool_max = ceph_decode_32(p);
-	new_flags = ceph_decode_32(p);
-
-	/* full map? */
-	ceph_decode_32_safe(p, end, len, bad);
-	if (len > 0) {
-		dout("apply_incremental full map len %d, %p to %p\n",
-		     len, *p, end);
-		return osdmap_decode(p, min(*p+len, end));
-	}
-
-	/* new crush? */
-	ceph_decode_32_safe(p, end, len, bad);
-	if (len > 0) {
-		dout("apply_incremental new crush map len %d, %p to %p\n",
-		     len, *p, end);
-		newcrush = crush_decode(*p, min(*p+len, end));
-		if (IS_ERR(newcrush))
-			return ERR_CAST(newcrush);
-		*p += len;
-	}
-
-	/* new flags? */
-	if (new_flags >= 0)
-		map->flags = new_flags;
-	if (new_pool_max >= 0)
-		map->pool_max = new_pool_max;
-
-	ceph_decode_need(p, end, 5*sizeof(u32), bad);
-
-	/* new max? */
-	max = ceph_decode_32(p);
-	if (max >= 0) {
-		err = osdmap_set_max_osd(map, max);
-		if (err < 0)
-			goto bad;
-	}
-
-	map->epoch++;
-	map->modified = map->modified;
-	if (newcrush) {
-		if (map->crush)
-			crush_destroy(map->crush);
-		map->crush = newcrush;
-		newcrush = NULL;
-	}
-
-	/* new_pool */
-	ceph_decode_32_safe(p, end, len, bad);
-	while (len--) {
-		__u8 ev;
-		struct ceph_pg_pool_info *pi;
-
-		ceph_decode_32_safe(p, end, pool, bad);
-		ceph_decode_need(p, end, 1 + sizeof(pi->v), bad);
-		ev = ceph_decode_8(p);  /* encoding version */
-		if (ev > CEPH_PG_POOL_VERSION) {
-			pr_warning("got unknown v %d > %d of ceph_pg_pool\n",
-				   ev, CEPH_PG_POOL_VERSION);
-			goto bad;
-		}
-		pi = __lookup_pg_pool(&map->pg_pools, pool);
-		if (!pi) {
-			pi = kzalloc(sizeof(*pi), GFP_NOFS);
-			if (!pi) {
-				err = -ENOMEM;
-				goto bad;
-			}
-			pi->id = pool;
-			__insert_pg_pool(&map->pg_pools, pi);
-		}
-		err = __decode_pool(p, end, pi);
-		if (err < 0)
-			goto bad;
-	}
-	if (version >= 5 && __decode_pool_names(p, end, map) < 0)
-		goto bad;
-
-	/* old_pool */
-	ceph_decode_32_safe(p, end, len, bad);
-	while (len--) {
-		struct ceph_pg_pool_info *pi;
-
-		ceph_decode_32_safe(p, end, pool, bad);
-		pi = __lookup_pg_pool(&map->pg_pools, pool);
-		if (pi)
-			__remove_pg_pool(&map->pg_pools, pi);
-	}
-
-	/* new_up */
-	err = -EINVAL;
-	ceph_decode_32_safe(p, end, len, bad);
-	while (len--) {
-		u32 osd;
-		struct ceph_entity_addr addr;
-		ceph_decode_32_safe(p, end, osd, bad);
-		ceph_decode_copy_safe(p, end, &addr, sizeof(addr), bad);
-		ceph_decode_addr(&addr);
-		pr_info("osd%d up\n", osd);
-		BUG_ON(osd >= map->max_osd);
-		map->osd_state[osd] |= CEPH_OSD_UP;
-		map->osd_addr[osd] = addr;
-	}
-
-	/* new_down */
-	ceph_decode_32_safe(p, end, len, bad);
-	while (len--) {
-		u32 osd;
-		ceph_decode_32_safe(p, end, osd, bad);
-		(*p)++;  /* clean flag */
-		pr_info("osd%d down\n", osd);
-		if (osd < map->max_osd)
-			map->osd_state[osd] &= ~CEPH_OSD_UP;
-	}
-
-	/* new_weight */
-	ceph_decode_32_safe(p, end, len, bad);
-	while (len--) {
-		u32 osd, off;
-		ceph_decode_need(p, end, sizeof(u32)*2, bad);
-		osd = ceph_decode_32(p);
-		off = ceph_decode_32(p);
-		pr_info("osd%d weight 0x%x %s\n", osd, off,
-		     off == CEPH_OSD_IN ? "(in)" :
-		     (off == CEPH_OSD_OUT ? "(out)" : ""));
-		if (osd < map->max_osd)
-			map->osd_weight[osd] = off;
-	}
-
-	/* new_pg_temp */
-	rbp = rb_first(&map->pg_temp);
-	ceph_decode_32_safe(p, end, len, bad);
-	while (len--) {
-		struct ceph_pg_mapping *pg;
-		int j;
-		struct ceph_pg pgid;
-		u32 pglen;
-		ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad);
-		ceph_decode_copy(p, &pgid, sizeof(pgid));
-		pglen = ceph_decode_32(p);
-
-		/* remove any? */
-		while (rbp && pgid_cmp(rb_entry(rbp, struct ceph_pg_mapping,
-						node)->pgid, pgid) <= 0) {
-			struct ceph_pg_mapping *cur =
-				rb_entry(rbp, struct ceph_pg_mapping, node);
-
-			rbp = rb_next(rbp);
-			dout(" removed pg_temp %llx\n", *(u64 *)&cur->pgid);
-			rb_erase(&cur->node, &map->pg_temp);
-			kfree(cur);
-		}
-
-		if (pglen) {
-			/* insert */
-			ceph_decode_need(p, end, pglen*sizeof(u32), bad);
-			pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS);
-			if (!pg) {
-				err = -ENOMEM;
-				goto bad;
-			}
-			pg->pgid = pgid;
-			pg->len = pglen;
-			for (j = 0; j < pglen; j++)
-				pg->osds[j] = ceph_decode_32(p);
-			err = __insert_pg_mapping(pg, &map->pg_temp);
-			if (err) {
-				kfree(pg);
-				goto bad;
-			}
-			dout(" added pg_temp %llx len %d\n", *(u64 *)&pgid,
-			     pglen);
-		}
-	}
-	while (rbp) {
-		struct ceph_pg_mapping *cur =
-			rb_entry(rbp, struct ceph_pg_mapping, node);
-
-		rbp = rb_next(rbp);
-		dout(" removed pg_temp %llx\n", *(u64 *)&cur->pgid);
-		rb_erase(&cur->node, &map->pg_temp);
-		kfree(cur);
-	}
-
-	/* ignore the rest */
-	*p = end;
-	return map;
-
-bad:
-	pr_err("corrupt inc osdmap epoch %d off %d (%p of %p-%p)\n",
-	       epoch, (int)(*p - start), *p, start, end);
-	print_hex_dump(KERN_DEBUG, "osdmap: ",
-		       DUMP_PREFIX_OFFSET, 16, 1,
-		       start, end - start, true);
-	if (newcrush)
-		crush_destroy(newcrush);
-	return ERR_PTR(err);
-}
-
-
-
-
-/*
- * calculate file layout from given offset, length.
- * fill in correct oid, logical length, and object extent
- * offset, length.
- *
- * for now, we write only a single su, until we can
- * pass a stride back to the caller.
- */
-void ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
-				   u64 off, u64 *plen,
-				   u64 *ono,
-				   u64 *oxoff, u64 *oxlen)
-{
-	u32 osize = le32_to_cpu(layout->fl_object_size);
-	u32 su = le32_to_cpu(layout->fl_stripe_unit);
-	u32 sc = le32_to_cpu(layout->fl_stripe_count);
-	u32 bl, stripeno, stripepos, objsetno;
-	u32 su_per_object;
-	u64 t, su_offset;
-
-	dout("mapping %llu~%llu  osize %u fl_su %u\n", off, *plen,
-	     osize, su);
-	su_per_object = osize / su;
-	dout("osize %u / su %u = su_per_object %u\n", osize, su,
-	     su_per_object);
-
-	BUG_ON((su & ~PAGE_MASK) != 0);
-	/* bl = *off / su; */
-	t = off;
-	do_div(t, su);
-	bl = t;
-	dout("off %llu / su %u = bl %u\n", off, su, bl);
-
-	stripeno = bl / sc;
-	stripepos = bl % sc;
-	objsetno = stripeno / su_per_object;
-
-	*ono = objsetno * sc + stripepos;
-	dout("objset %u * sc %u = ono %u\n", objsetno, sc, (unsigned)*ono);
-
-	/* *oxoff = *off % layout->fl_stripe_unit;  # offset in su */
-	t = off;
-	su_offset = do_div(t, su);
-	*oxoff = su_offset + (stripeno % su_per_object) * su;
-
-	/*
-	 * Calculate the length of the extent being written to the selected
-	 * object. This is the minimum of the full length requested (plen) or
-	 * the remainder of the current stripe being written to.
-	 */
-	*oxlen = min_t(u64, *plen, su - su_offset);
-	*plen = *oxlen;
-
-	dout(" obj extent %llu~%llu\n", *oxoff, *oxlen);
-}
-
-/*
- * calculate an object layout (i.e. pgid) from an oid,
- * file_layout, and osdmap
- */
-int ceph_calc_object_layout(struct ceph_object_layout *ol,
-			    const char *oid,
-			    struct ceph_file_layout *fl,
-			    struct ceph_osdmap *osdmap)
-{
-	unsigned num, num_mask;
-	struct ceph_pg pgid;
-	s32 preferred = (s32)le32_to_cpu(fl->fl_pg_preferred);
-	int poolid = le32_to_cpu(fl->fl_pg_pool);
-	struct ceph_pg_pool_info *pool;
-	unsigned ps;
-
-	BUG_ON(!osdmap);
-
-	pool = __lookup_pg_pool(&osdmap->pg_pools, poolid);
-	if (!pool)
-		return -EIO;
-	ps = ceph_str_hash(pool->v.object_hash, oid, strlen(oid));
-	if (preferred >= 0) {
-		ps += preferred;
-		num = le32_to_cpu(pool->v.lpg_num);
-		num_mask = pool->lpg_num_mask;
-	} else {
-		num = le32_to_cpu(pool->v.pg_num);
-		num_mask = pool->pg_num_mask;
-	}
-
-	pgid.ps = cpu_to_le16(ps);
-	pgid.preferred = cpu_to_le16(preferred);
-	pgid.pool = fl->fl_pg_pool;
-	if (preferred >= 0)
-		dout("calc_object_layout '%s' pgid %d.%xp%d\n", oid, poolid, ps,
-		     (int)preferred);
-	else
-		dout("calc_object_layout '%s' pgid %d.%x\n", oid, poolid, ps);
-
-	ol->ol_pgid = pgid;
-	ol->ol_stripe_unit = fl->fl_object_stripe_unit;
-	return 0;
-}
-
-/*
- * Calculate raw osd vector for the given pgid.  Return pointer to osd
- * array, or NULL on failure.
- */
-static int *calc_pg_raw(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
-			int *osds, int *num)
-{
-	struct ceph_pg_mapping *pg;
-	struct ceph_pg_pool_info *pool;
-	int ruleno;
-	unsigned poolid, ps, pps;
-	int preferred;
-
-	/* pg_temp? */
-	pg = __lookup_pg_mapping(&osdmap->pg_temp, pgid);
-	if (pg) {
-		*num = pg->len;
-		return pg->osds;
-	}
-
-	/* crush */
-	poolid = le32_to_cpu(pgid.pool);
-	ps = le16_to_cpu(pgid.ps);
-	preferred = (s16)le16_to_cpu(pgid.preferred);
-
-	/* don't forcefeed bad device ids to crush */
-	if (preferred >= osdmap->max_osd ||
-	    preferred >= osdmap->crush->max_devices)
-		preferred = -1;
-
-	pool = __lookup_pg_pool(&osdmap->pg_pools, poolid);
-	if (!pool)
-		return NULL;
-	ruleno = crush_find_rule(osdmap->crush, pool->v.crush_ruleset,
-				 pool->v.type, pool->v.size);
-	if (ruleno < 0) {
-		pr_err("no crush rule pool %d ruleset %d type %d size %d\n",
-		       poolid, pool->v.crush_ruleset, pool->v.type,
-		       pool->v.size);
-		return NULL;
-	}
-
-	if (preferred >= 0)
-		pps = ceph_stable_mod(ps,
-				      le32_to_cpu(pool->v.lpgp_num),
-				      pool->lpgp_num_mask);
-	else
-		pps = ceph_stable_mod(ps,
-				      le32_to_cpu(pool->v.pgp_num),
-				      pool->pgp_num_mask);
-	pps += poolid;
-	*num = crush_do_rule(osdmap->crush, ruleno, pps, osds,
-			     min_t(int, pool->v.size, *num),
-			     preferred, osdmap->osd_weight);
-	return osds;
-}
-
-/*
- * Return acting set for given pgid.
- */
-int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
-			int *acting)
-{
-	int rawosds[CEPH_PG_MAX_SIZE], *osds;
-	int i, o, num = CEPH_PG_MAX_SIZE;
-
-	osds = calc_pg_raw(osdmap, pgid, rawosds, &num);
-	if (!osds)
-		return -1;
-
-	/* primary is first up osd */
-	o = 0;
-	for (i = 0; i < num; i++)
-		if (ceph_osd_is_up(osdmap, osds[i]))
-			acting[o++] = osds[i];
-	return o;
-}
-
-/*
- * Return primary osd for given pgid, or -1 if none.
- */
-int ceph_calc_pg_primary(struct ceph_osdmap *osdmap, struct ceph_pg pgid)
-{
-	int rawosds[CEPH_PG_MAX_SIZE], *osds;
-	int i, num = CEPH_PG_MAX_SIZE;
-
-	osds = calc_pg_raw(osdmap, pgid, rawosds, &num);
-	if (!osds)
-		return -1;
-
-	/* primary is first up osd */
-	for (i = 0; i < num; i++)
-		if (ceph_osd_is_up(osdmap, osds[i]))
-			return osds[i];
-	return -1;
-}
diff --git a/fs/ceph/osdmap.h b/fs/ceph/osdmap.h
deleted file mode 100644
index 970b547..0000000
--- a/fs/ceph/osdmap.h
+++ /dev/null
@@ -1,128 +0,0 @@
-#ifndef _FS_CEPH_OSDMAP_H
-#define _FS_CEPH_OSDMAP_H
-
-#include <linux/rbtree.h>
-#include "types.h"
-#include "ceph_fs.h"
-#include "crush/crush.h"
-
-/*
- * The osd map describes the current membership of the osd cluster and
- * specifies the mapping of objects to placement groups and placement
- * groups to (sets of) osds.  That is, it completely specifies the
- * (desired) distribution of all data objects in the system at some
- * point in time.
- *
- * Each map version is identified by an epoch, which increases monotonically.
- *
- * The map can be updated either via an incremental map (diff) describing
- * the change between two successive epochs, or as a fully encoded map.
- */
-struct ceph_pg_pool_info {
-	struct rb_node node;
-	int id;
-	struct ceph_pg_pool v;
-	int pg_num_mask, pgp_num_mask, lpg_num_mask, lpgp_num_mask;
-	char *name;
-};
-
-struct ceph_pg_mapping {
-	struct rb_node node;
-	struct ceph_pg pgid;
-	int len;
-	int osds[];
-};
-
-struct ceph_osdmap {
-	struct ceph_fsid fsid;
-	u32 epoch;
-	u32 mkfs_epoch;
-	struct ceph_timespec created, modified;
-
-	u32 flags;         /* CEPH_OSDMAP_* */
-
-	u32 max_osd;       /* size of osd_state, _offload, _addr arrays */
-	u8 *osd_state;     /* CEPH_OSD_* */
-	u32 *osd_weight;   /* 0 = failed, 0x10000 = 100% normal */
-	struct ceph_entity_addr *osd_addr;
-
-	struct rb_root pg_temp;
-	struct rb_root pg_pools;
-	u32 pool_max;
-
-	/* the CRUSH map specifies the mapping of placement groups to
-	 * the list of osds that store+replicate them. */
-	struct crush_map *crush;
-};
-
-/*
- * file layout helpers
- */
-#define ceph_file_layout_su(l) ((__s32)le32_to_cpu((l).fl_stripe_unit))
-#define ceph_file_layout_stripe_count(l) \
-	((__s32)le32_to_cpu((l).fl_stripe_count))
-#define ceph_file_layout_object_size(l) ((__s32)le32_to_cpu((l).fl_object_size))
-#define ceph_file_layout_cas_hash(l) ((__s32)le32_to_cpu((l).fl_cas_hash))
-#define ceph_file_layout_object_su(l) \
-	((__s32)le32_to_cpu((l).fl_object_stripe_unit))
-#define ceph_file_layout_pg_preferred(l) \
-	((__s32)le32_to_cpu((l).fl_pg_preferred))
-#define ceph_file_layout_pg_pool(l) \
-	((__s32)le32_to_cpu((l).fl_pg_pool))
-
-static inline unsigned ceph_file_layout_stripe_width(struct ceph_file_layout *l)
-{
-	return le32_to_cpu(l->fl_stripe_unit) *
-		le32_to_cpu(l->fl_stripe_count);
-}
-
-/* "period" == bytes before i start on a new set of objects */
-static inline unsigned ceph_file_layout_period(struct ceph_file_layout *l)
-{
-	return le32_to_cpu(l->fl_object_size) *
-		le32_to_cpu(l->fl_stripe_count);
-}
-
-
-static inline int ceph_osd_is_up(struct ceph_osdmap *map, int osd)
-{
-	return (osd < map->max_osd) && (map->osd_state[osd] & CEPH_OSD_UP);
-}
-
-static inline bool ceph_osdmap_flag(struct ceph_osdmap *map, int flag)
-{
-	return map && (map->flags & flag);
-}
-
-extern char *ceph_osdmap_state_str(char *str, int len, int state);
-
-static inline struct ceph_entity_addr *ceph_osd_addr(struct ceph_osdmap *map,
-						     int osd)
-{
-	if (osd >= map->max_osd)
-		return NULL;
-	return &map->osd_addr[osd];
-}
-
-extern struct ceph_osdmap *osdmap_decode(void **p, void *end);
-extern struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
-					    struct ceph_osdmap *map,
-					    struct ceph_messenger *msgr);
-extern void ceph_osdmap_destroy(struct ceph_osdmap *map);
-
-/* calculate mapping of a file extent to an object */
-extern void ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
-					  u64 off, u64 *plen,
-					  u64 *bno, u64 *oxoff, u64 *oxlen);
-
-/* calculate mapping of object to a placement group */
-extern int ceph_calc_object_layout(struct ceph_object_layout *ol,
-				   const char *oid,
-				   struct ceph_file_layout *fl,
-				   struct ceph_osdmap *osdmap);
-extern int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
-			       int *acting);
-extern int ceph_calc_pg_primary(struct ceph_osdmap *osdmap,
-				struct ceph_pg pgid);
-
-#endif
diff --git a/fs/ceph/pagelist.c b/fs/ceph/pagelist.c
deleted file mode 100644
index 46a368b..0000000
--- a/fs/ceph/pagelist.c
+++ /dev/null
@@ -1,63 +0,0 @@
-
-#include <linux/gfp.h>
-#include <linux/pagemap.h>
-#include <linux/highmem.h>
-
-#include "pagelist.h"
-
-static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl)
-{
-	struct page *page = list_entry(pl->head.prev, struct page,
-				       lru);
-	kunmap(page);
-}
-
-int ceph_pagelist_release(struct ceph_pagelist *pl)
-{
-	if (pl->mapped_tail)
-		ceph_pagelist_unmap_tail(pl);
-
-	while (!list_empty(&pl->head)) {
-		struct page *page = list_first_entry(&pl->head, struct page,
-						     lru);
-		list_del(&page->lru);
-		__free_page(page);
-	}
-	return 0;
-}
-
-static int ceph_pagelist_addpage(struct ceph_pagelist *pl)
-{
-	struct page *page = __page_cache_alloc(GFP_NOFS);
-	if (!page)
-		return -ENOMEM;
-	pl->room += PAGE_SIZE;
-	list_add_tail(&page->lru, &pl->head);
-	if (pl->mapped_tail)
-		ceph_pagelist_unmap_tail(pl);
-	pl->mapped_tail = kmap(page);
-	return 0;
-}
-
-int ceph_pagelist_append(struct ceph_pagelist *pl, void *buf, size_t len)
-{
-	while (pl->room < len) {
-		size_t bit = pl->room;
-		int ret;
-
-		memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK),
-		       buf, bit);
-		pl->length += bit;
-		pl->room -= bit;
-		buf += bit;
-		len -= bit;
-		ret = ceph_pagelist_addpage(pl);
-		if (ret)
-			return ret;
-	}
-
-	memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK), buf, len);
-	pl->length += len;
-	pl->room -= len;
-	return 0;
-}
diff --git a/fs/ceph/pagelist.h b/fs/ceph/pagelist.h
deleted file mode 100644
index e8a4187..0000000
--- a/fs/ceph/pagelist.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef __FS_CEPH_PAGELIST_H
-#define __FS_CEPH_PAGELIST_H
-
-#include <linux/list.h>
-
-struct ceph_pagelist {
-	struct list_head head;
-	void *mapped_tail;
-	size_t length;
-	size_t room;
-};
-
-static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
-{
-	INIT_LIST_HEAD(&pl->head);
-	pl->mapped_tail = NULL;
-	pl->length = 0;
-	pl->room = 0;
-}
-extern int ceph_pagelist_release(struct ceph_pagelist *pl);
-
-extern int ceph_pagelist_append(struct ceph_pagelist *pl, void *d, size_t l);
-
-static inline int ceph_pagelist_encode_64(struct ceph_pagelist *pl, u64 v)
-{
-	__le64 ev = cpu_to_le64(v);
-	return ceph_pagelist_append(pl, &ev, sizeof(ev));
-}
-static inline int ceph_pagelist_encode_32(struct ceph_pagelist *pl, u32 v)
-{
-	__le32 ev = cpu_to_le32(v);
-	return ceph_pagelist_append(pl, &ev, sizeof(ev));
-}
-static inline int ceph_pagelist_encode_16(struct ceph_pagelist *pl, u16 v)
-{
-	__le16 ev = cpu_to_le16(v);
-	return ceph_pagelist_append(pl, &ev, sizeof(ev));
-}
-static inline int ceph_pagelist_encode_8(struct ceph_pagelist *pl, u8 v)
-{
-	return ceph_pagelist_append(pl, &v, 1);
-}
-static inline int ceph_pagelist_encode_string(struct ceph_pagelist *pl,
-					      char *s, size_t len)
-{
-	int ret = ceph_pagelist_encode_32(pl, len);
-	if (ret)
-		return ret;
-	if (len)
-		return ceph_pagelist_append(pl, s, len);
-	return 0;
-}
-
-#endif
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 190b6c4..39c243a 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -1,10 +1,12 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/sort.h>
 #include <linux/slab.h>
 
 #include "super.h"
-#include "decode.h"
+#include "mds_client.h"
+
+#include <linux/ceph/decode.h>
 
 /*
  * Snapshots in ceph are driven in large part by cooperation from the
@@ -526,7 +528,7 @@
 			    struct ceph_cap_snap *capsnap)
 {
 	struct inode *inode = &ci->vfs_inode;
-	struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc;
+	struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
 
 	BUG_ON(capsnap->writing);
 	capsnap->size = inode->i_size;
@@ -747,7 +749,7 @@
 		      struct ceph_mds_session *session,
 		      struct ceph_msg *msg)
 {
-	struct super_block *sb = mdsc->client->sb;
+	struct super_block *sb = mdsc->fsc->sb;
 	int mds = session->s_mds;
 	u64 split;
 	int op;
diff --git a/fs/ceph/strings.c b/fs/ceph/strings.c
new file mode 100644
index 0000000..cd5097d
--- /dev/null
+++ b/fs/ceph/strings.c
@@ -0,0 +1,117 @@
+/*
+ * Ceph fs string constants
+ */
+#include <linux/module.h>
+#include <linux/ceph/types.h>
+
+
+const char *ceph_mds_state_name(int s)
+{
+	switch (s) {
+		/* down and out */
+	case CEPH_MDS_STATE_DNE:        return "down:dne";
+	case CEPH_MDS_STATE_STOPPED:    return "down:stopped";
+		/* up and out */
+	case CEPH_MDS_STATE_BOOT:       return "up:boot";
+	case CEPH_MDS_STATE_STANDBY:    return "up:standby";
+	case CEPH_MDS_STATE_STANDBY_REPLAY:    return "up:standby-replay";
+	case CEPH_MDS_STATE_CREATING:   return "up:creating";
+	case CEPH_MDS_STATE_STARTING:   return "up:starting";
+		/* up and in */
+	case CEPH_MDS_STATE_REPLAY:     return "up:replay";
+	case CEPH_MDS_STATE_RESOLVE:    return "up:resolve";
+	case CEPH_MDS_STATE_RECONNECT:  return "up:reconnect";
+	case CEPH_MDS_STATE_REJOIN:     return "up:rejoin";
+	case CEPH_MDS_STATE_CLIENTREPLAY: return "up:clientreplay";
+	case CEPH_MDS_STATE_ACTIVE:     return "up:active";
+	case CEPH_MDS_STATE_STOPPING:   return "up:stopping";
+	}
+	return "???";
+}
+
+const char *ceph_session_op_name(int op)
+{
+	switch (op) {
+	case CEPH_SESSION_REQUEST_OPEN: return "request_open";
+	case CEPH_SESSION_OPEN: return "open";
+	case CEPH_SESSION_REQUEST_CLOSE: return "request_close";
+	case CEPH_SESSION_CLOSE: return "close";
+	case CEPH_SESSION_REQUEST_RENEWCAPS: return "request_renewcaps";
+	case CEPH_SESSION_RENEWCAPS: return "renewcaps";
+	case CEPH_SESSION_STALE: return "stale";
+	case CEPH_SESSION_RECALL_STATE: return "recall_state";
+	}
+	return "???";
+}
+
+const char *ceph_mds_op_name(int op)
+{
+	switch (op) {
+	case CEPH_MDS_OP_LOOKUP:  return "lookup";
+	case CEPH_MDS_OP_LOOKUPHASH:  return "lookuphash";
+	case CEPH_MDS_OP_LOOKUPPARENT:  return "lookupparent";
+	case CEPH_MDS_OP_GETATTR:  return "getattr";
+	case CEPH_MDS_OP_SETXATTR: return "setxattr";
+	case CEPH_MDS_OP_SETATTR: return "setattr";
+	case CEPH_MDS_OP_RMXATTR: return "rmxattr";
+	case CEPH_MDS_OP_READDIR: return "readdir";
+	case CEPH_MDS_OP_MKNOD: return "mknod";
+	case CEPH_MDS_OP_LINK: return "link";
+	case CEPH_MDS_OP_UNLINK: return "unlink";
+	case CEPH_MDS_OP_RENAME: return "rename";
+	case CEPH_MDS_OP_MKDIR: return "mkdir";
+	case CEPH_MDS_OP_RMDIR: return "rmdir";
+	case CEPH_MDS_OP_SYMLINK: return "symlink";
+	case CEPH_MDS_OP_CREATE: return "create";
+	case CEPH_MDS_OP_OPEN: return "open";
+	case CEPH_MDS_OP_LOOKUPSNAP: return "lookupsnap";
+	case CEPH_MDS_OP_LSSNAP: return "lssnap";
+	case CEPH_MDS_OP_MKSNAP: return "mksnap";
+	case CEPH_MDS_OP_RMSNAP: return "rmsnap";
+	case CEPH_MDS_OP_SETFILELOCK: return "setfilelock";
+	case CEPH_MDS_OP_GETFILELOCK: return "getfilelock";
+	}
+	return "???";
+}
+
+const char *ceph_cap_op_name(int op)
+{
+	switch (op) {
+	case CEPH_CAP_OP_GRANT: return "grant";
+	case CEPH_CAP_OP_REVOKE: return "revoke";
+	case CEPH_CAP_OP_TRUNC: return "trunc";
+	case CEPH_CAP_OP_EXPORT: return "export";
+	case CEPH_CAP_OP_IMPORT: return "import";
+	case CEPH_CAP_OP_UPDATE: return "update";
+	case CEPH_CAP_OP_DROP: return "drop";
+	case CEPH_CAP_OP_FLUSH: return "flush";
+	case CEPH_CAP_OP_FLUSH_ACK: return "flush_ack";
+	case CEPH_CAP_OP_FLUSHSNAP: return "flushsnap";
+	case CEPH_CAP_OP_FLUSHSNAP_ACK: return "flushsnap_ack";
+	case CEPH_CAP_OP_RELEASE: return "release";
+	case CEPH_CAP_OP_RENEW: return "renew";
+	}
+	return "???";
+}
+
+const char *ceph_lease_op_name(int o)
+{
+	switch (o) {
+	case CEPH_MDS_LEASE_REVOKE: return "revoke";
+	case CEPH_MDS_LEASE_RELEASE: return "release";
+	case CEPH_MDS_LEASE_RENEW: return "renew";
+	case CEPH_MDS_LEASE_REVOKE_ACK: return "revoke_ack";
+	}
+	return "???";
+}
+
+const char *ceph_snap_op_name(int o)
+{
+	switch (o) {
+	case CEPH_SNAP_OP_UPDATE: return "update";
+	case CEPH_SNAP_OP_CREATE: return "create";
+	case CEPH_SNAP_OP_DESTROY: return "destroy";
+	case CEPH_SNAP_OP_SPLIT: return "split";
+	}
+	return "???";
+}
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 9922628..d6e0e04 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -1,5 +1,5 @@
 
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <linux/backing-dev.h>
 #include <linux/ctype.h>
@@ -15,10 +15,13 @@
 #include <linux/statfs.h>
 #include <linux/string.h>
 
-#include "decode.h"
 #include "super.h"
-#include "mon_client.h"
-#include "auth.h"
+#include "mds_client.h"
+
+#include <linux/ceph/decode.h>
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/auth.h>
+#include <linux/ceph/debugfs.h>
 
 /*
  * Ceph superblock operations
@@ -26,36 +29,22 @@
  * Handle the basics of mounting, unmounting.
  */
 
-
-/*
- * find filename portion of a path (/foo/bar/baz -> baz)
- */
-const char *ceph_file_part(const char *s, int len)
-{
-	const char *e = s + len;
-
-	while (e != s && *(e-1) != '/')
-		e--;
-	return e;
-}
-
-
 /*
  * super ops
  */
 static void ceph_put_super(struct super_block *s)
 {
-	struct ceph_client *client = ceph_sb_to_client(s);
+	struct ceph_fs_client *fsc = ceph_sb_to_client(s);
 
 	dout("put_super\n");
-	ceph_mdsc_close_sessions(&client->mdsc);
+	ceph_mdsc_close_sessions(fsc->mdsc);
 
 	/*
 	 * ensure we release the bdi before put_anon_super releases
 	 * the device name.
 	 */
-	if (s->s_bdi == &client->backing_dev_info) {
-		bdi_unregister(&client->backing_dev_info);
+	if (s->s_bdi == &fsc->backing_dev_info) {
+		bdi_unregister(&fsc->backing_dev_info);
 		s->s_bdi = NULL;
 	}
 
@@ -64,14 +53,14 @@
 
 static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	struct ceph_client *client = ceph_inode_to_client(dentry->d_inode);
-	struct ceph_monmap *monmap = client->monc.monmap;
+	struct ceph_fs_client *fsc = ceph_inode_to_client(dentry->d_inode);
+	struct ceph_monmap *monmap = fsc->client->monc.monmap;
 	struct ceph_statfs st;
 	u64 fsid;
 	int err;
 
 	dout("statfs\n");
-	err = ceph_monc_do_statfs(&client->monc, &st);
+	err = ceph_monc_do_statfs(&fsc->client->monc, &st);
 	if (err < 0)
 		return err;
 
@@ -104,49 +93,237 @@
 
 static int ceph_sync_fs(struct super_block *sb, int wait)
 {
-	struct ceph_client *client = ceph_sb_to_client(sb);
+	struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
 
 	if (!wait) {
 		dout("sync_fs (non-blocking)\n");
-		ceph_flush_dirty_caps(&client->mdsc);
+		ceph_flush_dirty_caps(fsc->mdsc);
 		dout("sync_fs (non-blocking) done\n");
 		return 0;
 	}
 
 	dout("sync_fs (blocking)\n");
-	ceph_osdc_sync(&ceph_sb_to_client(sb)->osdc);
-	ceph_mdsc_sync(&ceph_sb_to_client(sb)->mdsc);
+	ceph_osdc_sync(&fsc->client->osdc);
+	ceph_mdsc_sync(fsc->mdsc);
 	dout("sync_fs (blocking) done\n");
 	return 0;
 }
 
-static int default_congestion_kb(void)
+/*
+ * mount options
+ */
+enum {
+	Opt_wsize,
+	Opt_rsize,
+	Opt_caps_wanted_delay_min,
+	Opt_caps_wanted_delay_max,
+	Opt_cap_release_safety,
+	Opt_readdir_max_entries,
+	Opt_readdir_max_bytes,
+	Opt_congestion_kb,
+	Opt_last_int,
+	/* int args above */
+	Opt_snapdirname,
+	Opt_last_string,
+	/* string args above */
+	Opt_dirstat,
+	Opt_nodirstat,
+	Opt_rbytes,
+	Opt_norbytes,
+	Opt_noasyncreaddir,
+};
+
+static match_table_t fsopt_tokens = {
+	{Opt_wsize, "wsize=%d"},
+	{Opt_rsize, "rsize=%d"},
+	{Opt_caps_wanted_delay_min, "caps_wanted_delay_min=%d"},
+	{Opt_caps_wanted_delay_max, "caps_wanted_delay_max=%d"},
+	{Opt_cap_release_safety, "cap_release_safety=%d"},
+	{Opt_readdir_max_entries, "readdir_max_entries=%d"},
+	{Opt_readdir_max_bytes, "readdir_max_bytes=%d"},
+	{Opt_congestion_kb, "write_congestion_kb=%d"},
+	/* int args above */
+	{Opt_snapdirname, "snapdirname=%s"},
+	/* string args above */
+	{Opt_dirstat, "dirstat"},
+	{Opt_nodirstat, "nodirstat"},
+	{Opt_rbytes, "rbytes"},
+	{Opt_norbytes, "norbytes"},
+	{Opt_noasyncreaddir, "noasyncreaddir"},
+	{-1, NULL}
+};
+
+static int parse_fsopt_token(char *c, void *private)
 {
-	int congestion_kb;
+	struct ceph_mount_options *fsopt = private;
+	substring_t argstr[MAX_OPT_ARGS];
+	int token, intval, ret;
 
-	/*
-	 * Copied from NFS
-	 *
-	 * congestion size, scale with available memory.
-	 *
-	 *  64MB:    8192k
-	 * 128MB:   11585k
-	 * 256MB:   16384k
-	 * 512MB:   23170k
-	 *   1GB:   32768k
-	 *   2GB:   46340k
-	 *   4GB:   65536k
-	 *   8GB:   92681k
-	 *  16GB:  131072k
-	 *
-	 * This allows larger machines to have larger/more transfers.
-	 * Limit the default to 256M
-	 */
-	congestion_kb = (16*int_sqrt(totalram_pages)) << (PAGE_SHIFT-10);
-	if (congestion_kb > 256*1024)
-		congestion_kb = 256*1024;
+	token = match_token((char *)c, fsopt_tokens, argstr);
+	if (token < 0)
+		return -EINVAL;
 
-	return congestion_kb;
+	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_snapdirname:
+		kfree(fsopt->snapdir_name);
+		fsopt->snapdir_name = kstrndup(argstr[0].from,
+					       argstr[0].to-argstr[0].from,
+					       GFP_KERNEL);
+		if (!fsopt->snapdir_name)
+			return -ENOMEM;
+		break;
+
+		/* misc */
+	case Opt_wsize:
+		fsopt->wsize = intval;
+		break;
+	case Opt_rsize:
+		fsopt->rsize = intval;
+		break;
+	case Opt_caps_wanted_delay_min:
+		fsopt->caps_wanted_delay_min = intval;
+		break;
+	case Opt_caps_wanted_delay_max:
+		fsopt->caps_wanted_delay_max = intval;
+		break;
+	case Opt_readdir_max_entries:
+		fsopt->max_readdir = intval;
+		break;
+	case Opt_readdir_max_bytes:
+		fsopt->max_readdir_bytes = intval;
+		break;
+	case Opt_congestion_kb:
+		fsopt->congestion_kb = intval;
+		break;
+	case Opt_dirstat:
+		fsopt->flags |= CEPH_MOUNT_OPT_DIRSTAT;
+		break;
+	case Opt_nodirstat:
+		fsopt->flags &= ~CEPH_MOUNT_OPT_DIRSTAT;
+		break;
+	case Opt_rbytes:
+		fsopt->flags |= CEPH_MOUNT_OPT_RBYTES;
+		break;
+	case Opt_norbytes:
+		fsopt->flags &= ~CEPH_MOUNT_OPT_RBYTES;
+		break;
+	case Opt_noasyncreaddir:
+		fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR;
+		break;
+	default:
+		BUG_ON(token);
+	}
+	return 0;
+}
+
+static void destroy_mount_options(struct ceph_mount_options *args)
+{
+	dout("destroy_mount_options %p\n", args);
+	kfree(args->snapdir_name);
+	kfree(args);
+}
+
+static int strcmp_null(const char *s1, const char *s2)
+{
+	if (!s1 && !s2)
+		return 0;
+	if (s1 && !s2)
+		return -1;
+	if (!s1 && s2)
+		return 1;
+	return strcmp(s1, s2);
+}
+
+static int compare_mount_options(struct ceph_mount_options *new_fsopt,
+				 struct ceph_options *new_opt,
+				 struct ceph_fs_client *fsc)
+{
+	struct ceph_mount_options *fsopt1 = new_fsopt;
+	struct ceph_mount_options *fsopt2 = fsc->mount_options;
+	int ofs = offsetof(struct ceph_mount_options, snapdir_name);
+	int ret;
+
+	ret = memcmp(fsopt1, fsopt2, ofs);
+	if (ret)
+		return ret;
+
+	ret = strcmp_null(fsopt1->snapdir_name, fsopt2->snapdir_name);
+	if (ret)
+		return ret;
+
+	return ceph_compare_options(new_opt, fsc->client);
+}
+
+static int parse_mount_options(struct ceph_mount_options **pfsopt,
+			       struct ceph_options **popt,
+			       int flags, char *options,
+			       const char *dev_name,
+			       const char **path)
+{
+	struct ceph_mount_options *fsopt;
+	const char *dev_name_end;
+	int err = -ENOMEM;
+
+	fsopt = kzalloc(sizeof(*fsopt), GFP_KERNEL);
+	if (!fsopt)
+		return -ENOMEM;
+
+	dout("parse_mount_options %p, dev_name '%s'\n", fsopt, dev_name);
+
+        fsopt->sb_flags = flags;
+        fsopt->flags = CEPH_MOUNT_OPT_DEFAULT;
+
+        fsopt->rsize = CEPH_MOUNT_RSIZE_DEFAULT;
+        fsopt->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL);
+        fsopt->cap_release_safety = CEPH_CAP_RELEASE_SAFETY_DEFAULT;
+        fsopt->max_readdir = CEPH_MAX_READDIR_DEFAULT;
+        fsopt->max_readdir_bytes = CEPH_MAX_READDIR_BYTES_DEFAULT;
+        fsopt->congestion_kb = default_congestion_kb();
+	
+        /* ip1[:port1][,ip2[:port2]...]:/subdir/in/fs */
+        err = -EINVAL;
+        if (!dev_name)
+                goto out;
+        *path = strstr(dev_name, ":/");
+        if (*path == NULL) {
+                pr_err("device name is missing path (no :/ in %s)\n",
+                       dev_name);
+                goto out;
+        }
+	dev_name_end = *path;
+	dout("device name '%.*s'\n", (int)(dev_name_end - dev_name), dev_name);
+
+	/* path on server */
+	*path += 2;
+	dout("server path '%s'\n", *path);
+
+	err = ceph_parse_options(popt, options, dev_name, dev_name_end,
+				 parse_fsopt_token, (void *)fsopt);
+	if (err)
+		goto out;
+
+	/* success */
+	*pfsopt = fsopt;
+	return 0;
+
+out:
+	destroy_mount_options(fsopt);
+	return err;
 }
 
 /**
@@ -156,60 +333,176 @@
  */
 static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt)
 {
-	struct ceph_client *client = ceph_sb_to_client(mnt->mnt_sb);
-	struct ceph_mount_args *args = client->mount_args;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(mnt->mnt_sb);
+	struct ceph_mount_options *fsopt = fsc->mount_options;
+	struct ceph_options *opt = fsc->client->options;
 
-	if (args->flags & CEPH_OPT_FSID)
-		seq_printf(m, ",fsid=%pU", &args->fsid);
-	if (args->flags & CEPH_OPT_NOSHARE)
+	if (opt->flags & CEPH_OPT_FSID)
+		seq_printf(m, ",fsid=%pU", &opt->fsid);
+	if (opt->flags & CEPH_OPT_NOSHARE)
 		seq_puts(m, ",noshare");
-	if (args->flags & CEPH_OPT_DIRSTAT)
-		seq_puts(m, ",dirstat");
-	if ((args->flags & CEPH_OPT_RBYTES) == 0)
-		seq_puts(m, ",norbytes");
-	if (args->flags & CEPH_OPT_NOCRC)
+	if (opt->flags & CEPH_OPT_NOCRC)
 		seq_puts(m, ",nocrc");
-	if (args->flags & CEPH_OPT_NOASYNCREADDIR)
+
+	if (opt->name)
+		seq_printf(m, ",name=%s", opt->name);
+	if (opt->secret)
+		seq_puts(m, ",secret=<hidden>");
+
+	if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
+		seq_printf(m, ",mount_timeout=%d", opt->mount_timeout);
+	if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
+		seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl);
+	if (opt->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT)
+		seq_printf(m, ",osdtimeout=%d", opt->osd_timeout);
+	if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
+		seq_printf(m, ",osdkeepalivetimeout=%d",
+			   opt->osd_keepalive_timeout);
+
+	if (fsopt->flags & CEPH_MOUNT_OPT_DIRSTAT)
+		seq_puts(m, ",dirstat");
+	if ((fsopt->flags & CEPH_MOUNT_OPT_RBYTES) == 0)
+		seq_puts(m, ",norbytes");
+	if (fsopt->flags & CEPH_MOUNT_OPT_NOASYNCREADDIR)
 		seq_puts(m, ",noasyncreaddir");
 
-	if (args->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
-		seq_printf(m, ",mount_timeout=%d", args->mount_timeout);
-	if (args->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
-		seq_printf(m, ",osd_idle_ttl=%d", args->osd_idle_ttl);
-	if (args->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT)
-		seq_printf(m, ",osdtimeout=%d", args->osd_timeout);
-	if (args->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
-		seq_printf(m, ",osdkeepalivetimeout=%d",
-			 args->osd_keepalive_timeout);
-	if (args->wsize)
-		seq_printf(m, ",wsize=%d", args->wsize);
-	if (args->rsize != CEPH_MOUNT_RSIZE_DEFAULT)
-		seq_printf(m, ",rsize=%d", args->rsize);
-	if (args->congestion_kb != default_congestion_kb())
-		seq_printf(m, ",write_congestion_kb=%d", args->congestion_kb);
-	if (args->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT)
+	if (fsopt->wsize)
+		seq_printf(m, ",wsize=%d", fsopt->wsize);
+	if (fsopt->rsize != CEPH_MOUNT_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);
+	if (fsopt->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT)
 		seq_printf(m, ",caps_wanted_delay_min=%d",
-			 args->caps_wanted_delay_min);
-	if (args->caps_wanted_delay_max != CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT)
+			 fsopt->caps_wanted_delay_min);
+	if (fsopt->caps_wanted_delay_max != CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT)
 		seq_printf(m, ",caps_wanted_delay_max=%d",
-			   args->caps_wanted_delay_max);
-	if (args->cap_release_safety != CEPH_CAP_RELEASE_SAFETY_DEFAULT)
+			   fsopt->caps_wanted_delay_max);
+	if (fsopt->cap_release_safety != CEPH_CAP_RELEASE_SAFETY_DEFAULT)
 		seq_printf(m, ",cap_release_safety=%d",
-			   args->cap_release_safety);
-	if (args->max_readdir != CEPH_MAX_READDIR_DEFAULT)
-		seq_printf(m, ",readdir_max_entries=%d", args->max_readdir);
-	if (args->max_readdir_bytes != CEPH_MAX_READDIR_BYTES_DEFAULT)
-		seq_printf(m, ",readdir_max_bytes=%d", args->max_readdir_bytes);
-	if (strcmp(args->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT))
-		seq_printf(m, ",snapdirname=%s", args->snapdir_name);
-	if (args->name)
-		seq_printf(m, ",name=%s", args->name);
-	if (args->secret)
-		seq_puts(m, ",secret=<hidden>");
+			   fsopt->cap_release_safety);
+	if (fsopt->max_readdir != CEPH_MAX_READDIR_DEFAULT)
+		seq_printf(m, ",readdir_max_entries=%d", fsopt->max_readdir);
+	if (fsopt->max_readdir_bytes != CEPH_MAX_READDIR_BYTES_DEFAULT)
+		seq_printf(m, ",readdir_max_bytes=%d", fsopt->max_readdir_bytes);
+	if (strcmp(fsopt->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT))
+		seq_printf(m, ",snapdirname=%s", fsopt->snapdir_name);
 	return 0;
 }
 
 /*
+ * handle any mon messages the standard library doesn't understand.
+ * return error if we don't either.
+ */
+static int extra_mon_dispatch(struct ceph_client *client, struct ceph_msg *msg)
+{
+	struct ceph_fs_client *fsc = client->private;
+	int type = le16_to_cpu(msg->hdr.type);
+
+	switch (type) {
+	case CEPH_MSG_MDS_MAP:
+		ceph_mdsc_handle_map(fsc->mdsc, msg);
+		return 0;
+
+	default:
+		return -1;
+	}
+}
+
+/*
+ * create a new fs client
+ */
+struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
+					struct ceph_options *opt)
+{
+	struct ceph_fs_client *fsc;
+	int err = -ENOMEM;
+
+	fsc = kzalloc(sizeof(*fsc), GFP_KERNEL);
+	if (!fsc)
+		return ERR_PTR(-ENOMEM);
+
+	fsc->client = ceph_create_client(opt, fsc);
+	if (IS_ERR(fsc->client)) {
+		err = PTR_ERR(fsc->client);
+		goto fail;
+	}
+	fsc->client->extra_mon_dispatch = extra_mon_dispatch;
+	fsc->client->supported_features |= CEPH_FEATURE_FLOCK;
+	fsc->client->monc.want_mdsmap = 1;
+
+	fsc->mount_options = fsopt;
+
+	fsc->sb = NULL;
+	fsc->mount_state = CEPH_MOUNT_MOUNTING;
+
+	atomic_long_set(&fsc->writeback_count, 0);
+
+	err = bdi_init(&fsc->backing_dev_info);
+	if (err < 0)
+		goto fail_client;
+
+	err = -ENOMEM;
+	fsc->wb_wq = create_workqueue("ceph-writeback");
+	if (fsc->wb_wq == NULL)
+		goto fail_bdi;
+	fsc->pg_inv_wq = create_singlethread_workqueue("ceph-pg-invalid");
+	if (fsc->pg_inv_wq == NULL)
+		goto fail_wb_wq;
+	fsc->trunc_wq = create_singlethread_workqueue("ceph-trunc");
+	if (fsc->trunc_wq == NULL)
+		goto fail_pg_inv_wq;
+
+	/* set up mempools */
+	err = -ENOMEM;
+	fsc->wb_pagevec_pool = mempool_create_kmalloc_pool(10,
+			      fsc->mount_options->wsize >> PAGE_CACHE_SHIFT);
+	if (!fsc->wb_pagevec_pool)
+		goto fail_trunc_wq;
+
+	/* caps */
+	fsc->min_caps = fsopt->max_readdir;
+
+	return fsc;
+
+fail_trunc_wq:
+	destroy_workqueue(fsc->trunc_wq);
+fail_pg_inv_wq:
+	destroy_workqueue(fsc->pg_inv_wq);
+fail_wb_wq:
+	destroy_workqueue(fsc->wb_wq);
+fail_bdi:
+	bdi_destroy(&fsc->backing_dev_info);
+fail_client:
+	ceph_destroy_client(fsc->client);
+fail:
+	kfree(fsc);
+	return ERR_PTR(err);
+}
+
+void destroy_fs_client(struct ceph_fs_client *fsc)
+{
+	dout("destroy_fs_client %p\n", fsc);
+
+	destroy_workqueue(fsc->wb_wq);
+	destroy_workqueue(fsc->pg_inv_wq);
+	destroy_workqueue(fsc->trunc_wq);
+
+	bdi_destroy(&fsc->backing_dev_info);
+
+	mempool_destroy(fsc->wb_pagevec_pool);
+
+	destroy_mount_options(fsc->mount_options);
+
+	ceph_fs_debugfs_cleanup(fsc);
+
+	ceph_destroy_client(fsc->client);
+
+	kfree(fsc);
+	dout("destroy_fs_client %p done\n", fsc);
+}
+
+/*
  * caches
  */
 struct kmem_cache *ceph_inode_cachep;
@@ -274,12 +567,12 @@
  */
 static void ceph_umount_begin(struct super_block *sb)
 {
-	struct ceph_client *client = ceph_sb_to_client(sb);
+	struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
 
 	dout("ceph_umount_begin - starting forced umount\n");
-	if (!client)
+	if (!fsc)
 		return;
-	client->mount_state = CEPH_MOUNT_SHUTDOWN;
+	fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
 	return;
 }
 
@@ -294,483 +587,15 @@
 	.umount_begin   = ceph_umount_begin,
 };
 
-
-const char *ceph_msg_type_name(int type)
-{
-	switch (type) {
-	case CEPH_MSG_SHUTDOWN: return "shutdown";
-	case CEPH_MSG_PING: return "ping";
-	case CEPH_MSG_AUTH: return "auth";
-	case CEPH_MSG_AUTH_REPLY: return "auth_reply";
-	case CEPH_MSG_MON_MAP: return "mon_map";
-	case CEPH_MSG_MON_GET_MAP: return "mon_get_map";
-	case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe";
-	case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack";
-	case CEPH_MSG_STATFS: return "statfs";
-	case CEPH_MSG_STATFS_REPLY: return "statfs_reply";
-	case CEPH_MSG_MDS_MAP: return "mds_map";
-	case CEPH_MSG_CLIENT_SESSION: return "client_session";
-	case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect";
-	case CEPH_MSG_CLIENT_REQUEST: return "client_request";
-	case CEPH_MSG_CLIENT_REQUEST_FORWARD: return "client_request_forward";
-	case CEPH_MSG_CLIENT_REPLY: return "client_reply";
-	case CEPH_MSG_CLIENT_CAPS: return "client_caps";
-	case CEPH_MSG_CLIENT_CAPRELEASE: return "client_cap_release";
-	case CEPH_MSG_CLIENT_SNAP: return "client_snap";
-	case CEPH_MSG_CLIENT_LEASE: return "client_lease";
-	case CEPH_MSG_OSD_MAP: return "osd_map";
-	case CEPH_MSG_OSD_OP: return "osd_op";
-	case CEPH_MSG_OSD_OPREPLY: return "osd_opreply";
-	default: return "unknown";
-	}
-}
-
-
-/*
- * mount options
- */
-enum {
-	Opt_wsize,
-	Opt_rsize,
-	Opt_osdtimeout,
-	Opt_osdkeepalivetimeout,
-	Opt_mount_timeout,
-	Opt_osd_idle_ttl,
-	Opt_caps_wanted_delay_min,
-	Opt_caps_wanted_delay_max,
-	Opt_cap_release_safety,
-	Opt_readdir_max_entries,
-	Opt_readdir_max_bytes,
-	Opt_congestion_kb,
-	Opt_last_int,
-	/* int args above */
-	Opt_fsid,
-	Opt_snapdirname,
-	Opt_name,
-	Opt_secret,
-	Opt_last_string,
-	/* string args above */
-	Opt_ip,
-	Opt_noshare,
-	Opt_dirstat,
-	Opt_nodirstat,
-	Opt_rbytes,
-	Opt_norbytes,
-	Opt_nocrc,
-	Opt_noasyncreaddir,
-};
-
-static match_table_t arg_tokens = {
-	{Opt_wsize, "wsize=%d"},
-	{Opt_rsize, "rsize=%d"},
-	{Opt_osdtimeout, "osdtimeout=%d"},
-	{Opt_osdkeepalivetimeout, "osdkeepalive=%d"},
-	{Opt_mount_timeout, "mount_timeout=%d"},
-	{Opt_osd_idle_ttl, "osd_idle_ttl=%d"},
-	{Opt_caps_wanted_delay_min, "caps_wanted_delay_min=%d"},
-	{Opt_caps_wanted_delay_max, "caps_wanted_delay_max=%d"},
-	{Opt_cap_release_safety, "cap_release_safety=%d"},
-	{Opt_readdir_max_entries, "readdir_max_entries=%d"},
-	{Opt_readdir_max_bytes, "readdir_max_bytes=%d"},
-	{Opt_congestion_kb, "write_congestion_kb=%d"},
-	/* int args above */
-	{Opt_fsid, "fsid=%s"},
-	{Opt_snapdirname, "snapdirname=%s"},
-	{Opt_name, "name=%s"},
-	{Opt_secret, "secret=%s"},
-	/* string args above */
-	{Opt_ip, "ip=%s"},
-	{Opt_noshare, "noshare"},
-	{Opt_dirstat, "dirstat"},
-	{Opt_nodirstat, "nodirstat"},
-	{Opt_rbytes, "rbytes"},
-	{Opt_norbytes, "norbytes"},
-	{Opt_nocrc, "nocrc"},
-	{Opt_noasyncreaddir, "noasyncreaddir"},
-	{-1, NULL}
-};
-
-static int parse_fsid(const char *str, struct ceph_fsid *fsid)
-{
-	int i = 0;
-	char tmp[3];
-	int err = -EINVAL;
-	int d;
-
-	dout("parse_fsid '%s'\n", str);
-	tmp[2] = 0;
-	while (*str && i < 16) {
-		if (ispunct(*str)) {
-			str++;
-			continue;
-		}
-		if (!isxdigit(str[0]) || !isxdigit(str[1]))
-			break;
-		tmp[0] = str[0];
-		tmp[1] = str[1];
-		if (sscanf(tmp, "%x", &d) < 1)
-			break;
-		fsid->fsid[i] = d & 0xff;
-		i++;
-		str += 2;
-	}
-
-	if (i == 16)
-		err = 0;
-	dout("parse_fsid ret %d got fsid %pU", err, fsid);
-	return err;
-}
-
-static struct ceph_mount_args *parse_mount_args(int flags, char *options,
-						const char *dev_name,
-						const char **path)
-{
-	struct ceph_mount_args *args;
-	const char *c;
-	int err = -ENOMEM;
-	substring_t argstr[MAX_OPT_ARGS];
-
-	args = kzalloc(sizeof(*args), GFP_KERNEL);
-	if (!args)
-		return ERR_PTR(-ENOMEM);
-	args->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*args->mon_addr),
-				 GFP_KERNEL);
-	if (!args->mon_addr)
-		goto out;
-
-	dout("parse_mount_args %p, dev_name '%s'\n", args, dev_name);
-
-	/* start with defaults */
-	args->sb_flags = flags;
-	args->flags = CEPH_OPT_DEFAULT;
-	args->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT;
-	args->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
-	args->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */
-	args->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;   /* seconds */
-	args->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT;
-	args->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT;
-	args->rsize = CEPH_MOUNT_RSIZE_DEFAULT;
-	args->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL);
-	args->cap_release_safety = CEPH_CAP_RELEASE_SAFETY_DEFAULT;
-	args->max_readdir = CEPH_MAX_READDIR_DEFAULT;
-	args->max_readdir_bytes = CEPH_MAX_READDIR_BYTES_DEFAULT;
-	args->congestion_kb = default_congestion_kb();
-
-	/* ip1[:port1][,ip2[:port2]...]:/subdir/in/fs */
-	err = -EINVAL;
-	if (!dev_name)
-		goto out;
-	*path = strstr(dev_name, ":/");
-	if (*path == NULL) {
-		pr_err("device name is missing path (no :/ in %s)\n",
-		       dev_name);
-		goto out;
-	}
-
-	/* get mon ip(s) */
-	err = ceph_parse_ips(dev_name, *path, args->mon_addr,
-			     CEPH_MAX_MON, &args->num_mon);
-	if (err < 0)
-		goto out;
-
-	/* path on server */
-	*path += 2;
-	dout("server path '%s'\n", *path);
-
-	/* parse mount options */
-	while ((c = strsep(&options, ",")) != NULL) {
-		int token, intval, ret;
-		if (!*c)
-			continue;
-		err = -EINVAL;
-		token = match_token((char *)c, arg_tokens, argstr);
-		if (token < 0) {
-			pr_err("bad mount option at '%s'\n", c);
-			goto out;
-		}
-		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);
-				continue;
-			}
-			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_ip:
-			err = ceph_parse_ips(argstr[0].from,
-					     argstr[0].to,
-					     &args->my_addr,
-					     1, NULL);
-			if (err < 0)
-				goto out;
-			args->flags |= CEPH_OPT_MYIP;
-			break;
-
-		case Opt_fsid:
-			err = parse_fsid(argstr[0].from, &args->fsid);
-			if (err == 0)
-				args->flags |= CEPH_OPT_FSID;
-			break;
-		case Opt_snapdirname:
-			kfree(args->snapdir_name);
-			args->snapdir_name = kstrndup(argstr[0].from,
-					      argstr[0].to-argstr[0].from,
-					      GFP_KERNEL);
-			break;
-		case Opt_name:
-			args->name = kstrndup(argstr[0].from,
-					      argstr[0].to-argstr[0].from,
-					      GFP_KERNEL);
-			break;
-		case Opt_secret:
-			args->secret = kstrndup(argstr[0].from,
-						argstr[0].to-argstr[0].from,
-						GFP_KERNEL);
-			break;
-
-			/* misc */
-		case Opt_wsize:
-			args->wsize = intval;
-			break;
-		case Opt_rsize:
-			args->rsize = intval;
-			break;
-		case Opt_osdtimeout:
-			args->osd_timeout = intval;
-			break;
-		case Opt_osdkeepalivetimeout:
-			args->osd_keepalive_timeout = intval;
-			break;
-		case Opt_osd_idle_ttl:
-			args->osd_idle_ttl = intval;
-			break;
-		case Opt_mount_timeout:
-			args->mount_timeout = intval;
-			break;
-		case Opt_caps_wanted_delay_min:
-			args->caps_wanted_delay_min = intval;
-			break;
-		case Opt_caps_wanted_delay_max:
-			args->caps_wanted_delay_max = intval;
-			break;
-		case Opt_readdir_max_entries:
-			args->max_readdir = intval;
-			break;
-		case Opt_readdir_max_bytes:
-			args->max_readdir_bytes = intval;
-			break;
-		case Opt_congestion_kb:
-			args->congestion_kb = intval;
-			break;
-
-		case Opt_noshare:
-			args->flags |= CEPH_OPT_NOSHARE;
-			break;
-
-		case Opt_dirstat:
-			args->flags |= CEPH_OPT_DIRSTAT;
-			break;
-		case Opt_nodirstat:
-			args->flags &= ~CEPH_OPT_DIRSTAT;
-			break;
-		case Opt_rbytes:
-			args->flags |= CEPH_OPT_RBYTES;
-			break;
-		case Opt_norbytes:
-			args->flags &= ~CEPH_OPT_RBYTES;
-			break;
-		case Opt_nocrc:
-			args->flags |= CEPH_OPT_NOCRC;
-			break;
-		case Opt_noasyncreaddir:
-			args->flags |= CEPH_OPT_NOASYNCREADDIR;
-			break;
-
-		default:
-			BUG_ON(token);
-		}
-	}
-	return args;
-
-out:
-	kfree(args->mon_addr);
-	kfree(args);
-	return ERR_PTR(err);
-}
-
-static void destroy_mount_args(struct ceph_mount_args *args)
-{
-	dout("destroy_mount_args %p\n", args);
-	kfree(args->snapdir_name);
-	args->snapdir_name = NULL;
-	kfree(args->name);
-	args->name = NULL;
-	kfree(args->secret);
-	args->secret = NULL;
-	kfree(args);
-}
-
-/*
- * create a fresh client instance
- */
-static struct ceph_client *ceph_create_client(struct ceph_mount_args *args)
-{
-	struct ceph_client *client;
-	int err = -ENOMEM;
-
-	client = kzalloc(sizeof(*client), GFP_KERNEL);
-	if (client == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	mutex_init(&client->mount_mutex);
-
-	init_waitqueue_head(&client->auth_wq);
-
-	client->sb = NULL;
-	client->mount_state = CEPH_MOUNT_MOUNTING;
-	client->mount_args = args;
-
-	client->msgr = NULL;
-
-	client->auth_err = 0;
-	atomic_long_set(&client->writeback_count, 0);
-
-	err = bdi_init(&client->backing_dev_info);
-	if (err < 0)
-		goto fail;
-
-	err = -ENOMEM;
-	client->wb_wq = create_workqueue("ceph-writeback");
-	if (client->wb_wq == NULL)
-		goto fail_bdi;
-	client->pg_inv_wq = create_singlethread_workqueue("ceph-pg-invalid");
-	if (client->pg_inv_wq == NULL)
-		goto fail_wb_wq;
-	client->trunc_wq = create_singlethread_workqueue("ceph-trunc");
-	if (client->trunc_wq == NULL)
-		goto fail_pg_inv_wq;
-
-	/* set up mempools */
-	err = -ENOMEM;
-	client->wb_pagevec_pool = mempool_create_kmalloc_pool(10,
-			      client->mount_args->wsize >> PAGE_CACHE_SHIFT);
-	if (!client->wb_pagevec_pool)
-		goto fail_trunc_wq;
-
-	/* caps */
-	client->min_caps = args->max_readdir;
-
-	/* subsystems */
-	err = ceph_monc_init(&client->monc, client);
-	if (err < 0)
-		goto fail_mempool;
-	err = ceph_osdc_init(&client->osdc, client);
-	if (err < 0)
-		goto fail_monc;
-	err = ceph_mdsc_init(&client->mdsc, client);
-	if (err < 0)
-		goto fail_osdc;
-	return client;
-
-fail_osdc:
-	ceph_osdc_stop(&client->osdc);
-fail_monc:
-	ceph_monc_stop(&client->monc);
-fail_mempool:
-	mempool_destroy(client->wb_pagevec_pool);
-fail_trunc_wq:
-	destroy_workqueue(client->trunc_wq);
-fail_pg_inv_wq:
-	destroy_workqueue(client->pg_inv_wq);
-fail_wb_wq:
-	destroy_workqueue(client->wb_wq);
-fail_bdi:
-	bdi_destroy(&client->backing_dev_info);
-fail:
-	kfree(client);
-	return ERR_PTR(err);
-}
-
-static void ceph_destroy_client(struct ceph_client *client)
-{
-	dout("destroy_client %p\n", client);
-
-	/* unmount */
-	ceph_mdsc_stop(&client->mdsc);
-	ceph_osdc_stop(&client->osdc);
-
-	/*
-	 * make sure mds and osd connections close out before destroying
-	 * the auth module, which is needed to free those connections'
-	 * ceph_authorizers.
-	 */
-	ceph_msgr_flush();
-
-	ceph_monc_stop(&client->monc);
-
-	ceph_debugfs_client_cleanup(client);
-	destroy_workqueue(client->wb_wq);
-	destroy_workqueue(client->pg_inv_wq);
-	destroy_workqueue(client->trunc_wq);
-
-	bdi_destroy(&client->backing_dev_info);
-
-	if (client->msgr)
-		ceph_messenger_destroy(client->msgr);
-	mempool_destroy(client->wb_pagevec_pool);
-
-	destroy_mount_args(client->mount_args);
-
-	kfree(client);
-	dout("destroy_client %p done\n", client);
-}
-
-/*
- * Initially learn our fsid, or verify an fsid matches.
- */
-int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
-{
-	if (client->have_fsid) {
-		if (ceph_fsid_compare(&client->fsid, fsid)) {
-			pr_err("bad fsid, had %pU got %pU",
-			       &client->fsid, fsid);
-			return -1;
-		}
-	} else {
-		pr_info("client%lld fsid %pU\n", client->monc.auth->global_id,
-			fsid);
-		memcpy(&client->fsid, fsid, sizeof(*fsid));
-		ceph_debugfs_client_init(client);
-		client->have_fsid = true;
-	}
-	return 0;
-}
-
-/*
- * true if we have the mon map (and have thus joined the cluster)
- */
-static int have_mon_and_osd_map(struct ceph_client *client)
-{
-	return client->monc.monmap && client->monc.monmap->epoch &&
-	       client->osdc.osdmap && client->osdc.osdmap->epoch;
-}
-
 /*
  * Bootstrap mount by opening the root directory.  Note the mount
  * @started time from caller, and time out if this takes too long.
  */
-static struct dentry *open_root_dentry(struct ceph_client *client,
+static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
 				       const char *path,
 				       unsigned long started)
 {
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req = NULL;
 	int err;
 	struct dentry *root;
@@ -784,14 +609,14 @@
 	req->r_ino1.ino = CEPH_INO_ROOT;
 	req->r_ino1.snap = CEPH_NOSNAP;
 	req->r_started = started;
-	req->r_timeout = client->mount_args->mount_timeout * HZ;
+	req->r_timeout = fsc->client->options->mount_timeout * HZ;
 	req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE);
 	req->r_num_caps = 2;
 	err = ceph_mdsc_do_request(mdsc, NULL, req);
 	if (err == 0) {
 		dout("open_root_inode success\n");
 		if (ceph_ino(req->r_target_inode) == CEPH_INO_ROOT &&
-		    client->sb->s_root == NULL)
+		    fsc->sb->s_root == NULL)
 			root = d_alloc_root(req->r_target_inode);
 		else
 			root = d_obtain_alias(req->r_target_inode);
@@ -804,105 +629,86 @@
 	return root;
 }
 
+
+
+
 /*
  * mount: join the ceph cluster, and open root directory.
  */
-static int ceph_mount(struct ceph_client *client, struct vfsmount *mnt,
+static int ceph_mount(struct ceph_fs_client *fsc, struct vfsmount *mnt,
 		      const char *path)
 {
-	struct ceph_entity_addr *myaddr = NULL;
 	int err;
-	unsigned long timeout = client->mount_args->mount_timeout * HZ;
 	unsigned long started = jiffies;  /* note the start time */
 	struct dentry *root;
+	int first = 0;   /* first vfsmount for this super_block */
 
 	dout("mount start\n");
-	mutex_lock(&client->mount_mutex);
+	mutex_lock(&fsc->client->mount_mutex);
 
-	/* initialize the messenger */
-	if (client->msgr == NULL) {
-		if (ceph_test_opt(client, MYIP))
-			myaddr = &client->mount_args->my_addr;
-		client->msgr = ceph_messenger_create(myaddr);
-		if (IS_ERR(client->msgr)) {
-			err = PTR_ERR(client->msgr);
-			client->msgr = NULL;
-			goto out;
-		}
-		client->msgr->nocrc = ceph_test_opt(client, NOCRC);
-	}
-
-	/* open session, and wait for mon, mds, and osd maps */
-	err = ceph_monc_open_session(&client->monc);
+	err = __ceph_open_session(fsc->client, started);
 	if (err < 0)
 		goto out;
 
-	while (!have_mon_and_osd_map(client)) {
-		err = -EIO;
-		if (timeout && time_after_eq(jiffies, started + timeout))
-			goto out;
-
-		/* wait */
-		dout("mount waiting for mon_map\n");
-		err = wait_event_interruptible_timeout(client->auth_wq,
-		       have_mon_and_osd_map(client) || (client->auth_err < 0),
-		       timeout);
-		if (err == -EINTR || err == -ERESTARTSYS)
-			goto out;
-		if (client->auth_err < 0) {
-			err = client->auth_err;
-			goto out;
-		}
-	}
-
 	dout("mount opening root\n");
-	root = open_root_dentry(client, "", started);
+	root = open_root_dentry(fsc, "", started);
 	if (IS_ERR(root)) {
 		err = PTR_ERR(root);
 		goto out;
 	}
-	if (client->sb->s_root)
+	if (fsc->sb->s_root) {
 		dput(root);
-	else
-		client->sb->s_root = root;
+	} else {
+		fsc->sb->s_root = root;
+		first = 1;
+
+		err = ceph_fs_debugfs_init(fsc);
+		if (err < 0)
+			goto fail;
+	}
 
 	if (path[0] == 0) {
 		dget(root);
 	} else {
 		dout("mount opening base mountpoint\n");
-		root = open_root_dentry(client, path, started);
+		root = open_root_dentry(fsc, path, started);
 		if (IS_ERR(root)) {
 			err = PTR_ERR(root);
-			dput(client->sb->s_root);
-			client->sb->s_root = NULL;
-			goto out;
+			goto fail;
 		}
 	}
 
 	mnt->mnt_root = root;
-	mnt->mnt_sb = client->sb;
+	mnt->mnt_sb = fsc->sb;
 
-	client->mount_state = CEPH_MOUNT_MOUNTED;
+	fsc->mount_state = CEPH_MOUNT_MOUNTED;
 	dout("mount success\n");
 	err = 0;
 
 out:
-	mutex_unlock(&client->mount_mutex);
+	mutex_unlock(&fsc->client->mount_mutex);
 	return err;
+
+fail:
+	if (first) {
+		dput(fsc->sb->s_root);
+		fsc->sb->s_root = NULL;
+	}
+	goto out;
 }
 
 static int ceph_set_super(struct super_block *s, void *data)
 {
-	struct ceph_client *client = data;
+	struct ceph_fs_client *fsc = data;
 	int ret;
 
 	dout("set_super %p data %p\n", s, data);
 
-	s->s_flags = client->mount_args->sb_flags;
+	s->s_flags = fsc->mount_options->sb_flags;
 	s->s_maxbytes = 1ULL << 40;  /* temp value until we get mdsmap */
 
-	s->s_fs_info = client;
-	client->sb = s;
+	s->s_fs_info = fsc;
+	fsc->sb = s;
 
 	s->s_op = &ceph_super_ops;
 	s->s_export_op = &ceph_export_ops;
@@ -917,7 +723,7 @@
 
 fail:
 	s->s_fs_info = NULL;
-	client->sb = NULL;
+	fsc->sb = NULL;
 	return ret;
 }
 
@@ -926,30 +732,23 @@
  */
 static int ceph_compare_super(struct super_block *sb, void *data)
 {
-	struct ceph_client *new = data;
-	struct ceph_mount_args *args = new->mount_args;
-	struct ceph_client *other = ceph_sb_to_client(sb);
-	int i;
+	struct ceph_fs_client *new = data;
+	struct ceph_mount_options *fsopt = new->mount_options;
+	struct ceph_options *opt = new->client->options;
+	struct ceph_fs_client *other = ceph_sb_to_client(sb);
 
 	dout("ceph_compare_super %p\n", sb);
-	if (args->flags & CEPH_OPT_FSID) {
-		if (ceph_fsid_compare(&args->fsid, &other->fsid)) {
-			dout("fsid doesn't match\n");
-			return 0;
-		}
-	} else {
-		/* do we share (a) monitor? */
-		for (i = 0; i < new->monc.monmap->num_mon; i++)
-			if (ceph_monmap_contains(other->monc.monmap,
-					 &new->monc.monmap->mon_inst[i].addr))
-				break;
-		if (i == new->monc.monmap->num_mon) {
-			dout("mon ip not part of monmap\n");
-			return 0;
-		}
-		dout("mon ip matches existing sb %p\n", sb);
+
+	if (compare_mount_options(fsopt, opt, other)) {
+		dout("monitor(s)/mount options don't match\n");
+		return 0;
 	}
-	if (args->sb_flags != other->mount_args->sb_flags) {
+	if ((opt->flags & CEPH_OPT_FSID) &&
+	    ceph_fsid_compare(&opt->fsid, &other->client->fsid)) {
+		dout("fsid doesn't match\n");
+		return 0;
+	}
+	if (fsopt->sb_flags != other->mount_options->sb_flags) {
 		dout("flags differ\n");
 		return 0;
 	}
@@ -961,19 +760,20 @@
  */
 static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
 
-static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client)
+static int ceph_register_bdi(struct super_block *sb,
+			     struct ceph_fs_client *fsc)
 {
 	int err;
 
 	/* set ra_pages based on rsize mount option? */
-	if (client->mount_args->rsize >= PAGE_CACHE_SIZE)
-		client->backing_dev_info.ra_pages =
-			(client->mount_args->rsize + PAGE_CACHE_SIZE - 1)
+	if (fsc->mount_options->rsize >= PAGE_CACHE_SIZE)
+		fsc->backing_dev_info.ra_pages =
+			(fsc->mount_options->rsize + PAGE_CACHE_SIZE - 1)
 			>> PAGE_SHIFT;
-	err = bdi_register(&client->backing_dev_info, NULL, "ceph-%d",
+	err = bdi_register(&fsc->backing_dev_info, NULL, "ceph-%d",
 			   atomic_long_inc_return(&bdi_seq));
 	if (!err)
-		sb->s_bdi = &client->backing_dev_info;
+		sb->s_bdi = &fsc->backing_dev_info;
 	return err;
 }
 
@@ -982,46 +782,52 @@
 		       struct vfsmount *mnt)
 {
 	struct super_block *sb;
-	struct ceph_client *client;
+	struct ceph_fs_client *fsc;
 	int err;
 	int (*compare_super)(struct super_block *, void *) = ceph_compare_super;
 	const char *path = NULL;
-	struct ceph_mount_args *args;
+	struct ceph_mount_options *fsopt = NULL;
+	struct ceph_options *opt = NULL;
 
 	dout("ceph_get_sb\n");
-	args = parse_mount_args(flags, data, dev_name, &path);
-	if (IS_ERR(args)) {
-		err = PTR_ERR(args);
+	err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path);
+	if (err < 0)
 		goto out_final;
-	}
 
 	/* create client (which we may/may not use) */
-	client = ceph_create_client(args);
-	if (IS_ERR(client)) {
-		err = PTR_ERR(client);
+	fsc = create_fs_client(fsopt, opt);
+	if (IS_ERR(fsc)) {
+		err = PTR_ERR(fsc);
+		kfree(fsopt);
+		kfree(opt);
 		goto out_final;
 	}
 
-	if (client->mount_args->flags & CEPH_OPT_NOSHARE)
+	err = ceph_mdsc_init(fsc);
+	if (err < 0)
+		goto out;
+
+	if (ceph_test_opt(fsc->client, NOSHARE))
 		compare_super = NULL;
-	sb = sget(fs_type, compare_super, ceph_set_super, client);
+	sb = sget(fs_type, compare_super, ceph_set_super, fsc);
 	if (IS_ERR(sb)) {
 		err = PTR_ERR(sb);
 		goto out;
 	}
 
-	if (ceph_sb_to_client(sb) != client) {
-		ceph_destroy_client(client);
-		client = ceph_sb_to_client(sb);
-		dout("get_sb got existing client %p\n", client);
+	if (ceph_sb_to_client(sb) != fsc) {
+		ceph_mdsc_destroy(fsc);
+		destroy_fs_client(fsc);
+		fsc = ceph_sb_to_client(sb);
+		dout("get_sb got existing client %p\n", fsc);
 	} else {
-		dout("get_sb using new client %p\n", client);
-		err = ceph_register_bdi(sb, client);
+		dout("get_sb using new client %p\n", fsc);
+		err = ceph_register_bdi(sb, fsc);
 		if (err < 0)
 			goto out_splat;
 	}
 
-	err = ceph_mount(client, mnt, path);
+	err = ceph_mount(fsc, mnt, path);
 	if (err < 0)
 		goto out_splat;
 	dout("root %p inode %p ino %llx.%llx\n", mnt->mnt_root,
@@ -1029,12 +835,13 @@
 	return 0;
 
 out_splat:
-	ceph_mdsc_close_sessions(&client->mdsc);
+	ceph_mdsc_close_sessions(fsc->mdsc);
 	deactivate_locked_super(sb);
 	goto out_final;
 
 out:
-	ceph_destroy_client(client);
+	ceph_mdsc_destroy(fsc);
+	destroy_fs_client(fsc);
 out_final:
 	dout("ceph_get_sb fail %d\n", err);
 	return err;
@@ -1042,11 +849,12 @@
 
 static void ceph_kill_sb(struct super_block *s)
 {
-	struct ceph_client *client = ceph_sb_to_client(s);
+	struct ceph_fs_client *fsc = ceph_sb_to_client(s);
 	dout("kill_sb %p\n", s);
-	ceph_mdsc_pre_umount(&client->mdsc);
+	ceph_mdsc_pre_umount(fsc->mdsc);
 	kill_anon_super(s);    /* will call put_super after sb is r/o */
-	ceph_destroy_client(client);
+	ceph_mdsc_destroy(fsc);
+	destroy_fs_client(fsc);
 }
 
 static struct file_system_type ceph_fs_type = {
@@ -1062,36 +870,20 @@
 
 static int __init init_ceph(void)
 {
-	int ret = 0;
-
-	ret = ceph_debugfs_init();
-	if (ret < 0)
-		goto out;
-
-	ret = ceph_msgr_init();
-	if (ret < 0)
-		goto out_debugfs;
-
-	ret = init_caches();
+	int ret = init_caches();
 	if (ret)
-		goto out_msgr;
+		goto out;
 
 	ret = register_filesystem(&ceph_fs_type);
 	if (ret)
 		goto out_icache;
 
-	pr_info("loaded (mon/mds/osd proto %d/%d/%d, osdmap %d/%d %d/%d)\n",
-		CEPH_MONC_PROTOCOL, CEPH_MDSC_PROTOCOL, CEPH_OSDC_PROTOCOL,
-		CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT,
-		CEPH_OSDMAP_INC_VERSION, CEPH_OSDMAP_INC_VERSION_EXT);
+	pr_info("loaded (mds proto %d)\n", CEPH_MDSC_PROTOCOL);
+
 	return 0;
 
 out_icache:
 	destroy_caches();
-out_msgr:
-	ceph_msgr_exit();
-out_debugfs:
-	ceph_debugfs_cleanup();
 out:
 	return ret;
 }
@@ -1101,8 +893,6 @@
 	dout("exit_ceph\n");
 	unregister_filesystem(&ceph_fs_type);
 	destroy_caches();
-	ceph_msgr_exit();
-	ceph_debugfs_cleanup();
 }
 
 module_init(init_ceph);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index b87638e..1886294 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -1,7 +1,7 @@
 #ifndef _FS_CEPH_SUPER_H
 #define _FS_CEPH_SUPER_H
 
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
 
 #include <asm/unaligned.h>
 #include <linux/backing-dev.h>
@@ -14,13 +14,7 @@
 #include <linux/writeback.h>
 #include <linux/slab.h>
 
-#include "types.h"
-#include "messenger.h"
-#include "msgpool.h"
-#include "mon_client.h"
-#include "mds_client.h"
-#include "osd_client.h"
-#include "ceph_fs.h"
+#include <linux/ceph/libceph.h>
 
 /* f_type in struct statfs */
 #define CEPH_SUPER_MAGIC 0x00c36400
@@ -30,42 +24,25 @@
 #define CEPH_BLOCK_SHIFT   20  /* 1 MB */
 #define CEPH_BLOCK         (1 << CEPH_BLOCK_SHIFT)
 
-/*
- * Supported features
- */
-#define CEPH_FEATURE_SUPPORTED CEPH_FEATURE_NOSRCADDR | CEPH_FEATURE_FLOCK
-#define CEPH_FEATURE_REQUIRED  CEPH_FEATURE_NOSRCADDR
+#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 */
 
-/*
- * mount options
- */
-#define CEPH_OPT_FSID             (1<<0)
-#define CEPH_OPT_NOSHARE          (1<<1) /* don't share client with other sbs */
-#define CEPH_OPT_MYIP             (1<<2) /* specified my ip */
-#define CEPH_OPT_DIRSTAT          (1<<4) /* funky `cat dirname` for stats */
-#define CEPH_OPT_RBYTES           (1<<5) /* dir st_bytes = rbytes */
-#define CEPH_OPT_NOCRC            (1<<6) /* no data crc on writes */
-#define CEPH_OPT_NOASYNCREADDIR   (1<<7) /* no dcache readdir */
+#define CEPH_MOUNT_OPT_DEFAULT    (CEPH_MOUNT_OPT_RBYTES)
 
-#define CEPH_OPT_DEFAULT   (CEPH_OPT_RBYTES)
+#define ceph_set_mount_opt(fsc, opt) \
+	(fsc)->mount_options->flags |= CEPH_MOUNT_OPT_##opt;
+#define ceph_test_mount_opt(fsc, opt) \
+	(!!((fsc)->mount_options->flags & CEPH_MOUNT_OPT_##opt))
 
-#define ceph_set_opt(client, opt) \
-	(client)->mount_args->flags |= CEPH_OPT_##opt;
-#define ceph_test_opt(client, opt) \
-	(!!((client)->mount_args->flags & CEPH_OPT_##opt))
+#define CEPH_MAX_READDIR_DEFAULT        1024
+#define CEPH_MAX_READDIR_BYTES_DEFAULT  (512*1024)
+#define CEPH_SNAPDIRNAME_DEFAULT        ".snap"
 
-
-struct ceph_mount_args {
-	int sb_flags;
+struct ceph_mount_options {
 	int flags;
-	struct ceph_fsid fsid;
-	struct ceph_entity_addr my_addr;
-	int num_mon;
-	struct ceph_entity_addr *mon_addr;
-	int mount_timeout;
-	int osd_idle_ttl;
-	int osd_timeout;
-	int osd_keepalive_timeout;
+	int sb_flags;
+
 	int wsize;
 	int rsize;            /* max readahead */
 	int congestion_kb;    /* max writeback in flight */
@@ -73,82 +50,25 @@
 	int cap_release_safety;
 	int max_readdir;       /* max readdir result (entires) */
 	int max_readdir_bytes; /* max readdir result (bytes) */
+
+	/*
+	 * everything above this point can be memcmp'd; everything below
+	 * is handled in compare_mount_options()
+	 */
+
 	char *snapdir_name;   /* default ".snap" */
-	char *name;
-	char *secret;
 };
 
-/*
- * defaults
- */
-#define CEPH_MOUNT_TIMEOUT_DEFAULT  60
-#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_MAX_READDIR_DEFAULT    1024
-#define CEPH_MAX_READDIR_BYTES_DEFAULT    (512*1024)
-
-#define CEPH_MSG_MAX_FRONT_LEN	(16*1024*1024)
-#define CEPH_MSG_MAX_DATA_LEN	(16*1024*1024)
-
-#define CEPH_SNAPDIRNAME_DEFAULT ".snap"
-#define CEPH_AUTH_NAME_DEFAULT   "guest"
-/*
- * Delay telling the MDS we no longer want caps, in case we reopen
- * the file.  Delay a minimum amount of time, even if we send a cap
- * message for some other reason.  Otherwise, take the oppotunity to
- * update the mds to avoid sending another message later.
- */
-#define CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT      5  /* cap release delay */
-#define CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT     60  /* cap release delay */
-
-#define CEPH_CAP_RELEASE_SAFETY_DEFAULT        (CEPH_CAPS_PER_RELEASE * 4)
-
-/* mount state */
-enum {
-	CEPH_MOUNT_MOUNTING,
-	CEPH_MOUNT_MOUNTED,
-	CEPH_MOUNT_UNMOUNTING,
-	CEPH_MOUNT_UNMOUNTED,
-	CEPH_MOUNT_SHUTDOWN,
-};
-
-/*
- * subtract jiffies
- */
-static inline unsigned long time_sub(unsigned long a, unsigned long b)
-{
-	BUG_ON(time_after(b, a));
-	return (long)a - (long)b;
-}
-
-/*
- * per-filesystem client state
- *
- * possibly shared by multiple mount points, if they are
- * mounting the same ceph filesystem/cluster.
- */
-struct ceph_client {
-	struct ceph_fsid fsid;
-	bool have_fsid;
-
-	struct mutex mount_mutex;       /* serialize mount attempts */
-	struct ceph_mount_args *mount_args;
-
+struct ceph_fs_client {
 	struct super_block *sb;
 
+	struct ceph_mount_options *mount_options;
+	struct ceph_client *client;
+
 	unsigned long mount_state;
-	wait_queue_head_t auth_wq;
-
-	int auth_err;
-
 	int min_caps;                  /* min caps i added */
 
-	struct ceph_messenger *msgr;   /* messenger instance */
-	struct ceph_mon_client monc;
-	struct ceph_mds_client mdsc;
-	struct ceph_osd_client osdc;
+	struct ceph_mds_client *mdsc;
 
 	/* writeback */
 	mempool_t *wb_pagevec_pool;
@@ -160,14 +80,14 @@
 	struct backing_dev_info backing_dev_info;
 
 #ifdef CONFIG_DEBUG_FS
-	struct dentry *debugfs_monmap;
-	struct dentry *debugfs_mdsmap, *debugfs_osdmap;
-	struct dentry *debugfs_dir, *debugfs_dentry_lru, *debugfs_caps;
+	struct dentry *debugfs_dentry_lru, *debugfs_caps;
 	struct dentry *debugfs_congestion_kb;
 	struct dentry *debugfs_bdi;
+	struct dentry *debugfs_mdsc, *debugfs_mdsmap;
 #endif
 };
 
+
 /*
  * File i/o capability.  This tracks shared state with the metadata
  * server that allows us to cache or writeback attributes or to read
@@ -275,6 +195,20 @@
 	int should_free_val;
 };
 
+/*
+ * Ceph dentry state
+ */
+struct ceph_dentry_info {
+	struct ceph_mds_session *lease_session;
+	u32 lease_gen, lease_shared_gen;
+	u32 lease_seq;
+	unsigned long lease_renew_after, lease_renew_from;
+	struct list_head lru;
+	struct dentry *dentry;
+	u64 time;
+	u64 offset;
+};
+
 struct ceph_inode_xattrs_info {
 	/*
 	 * (still encoded) xattr blob. we avoid the overhead of parsing
@@ -296,11 +230,6 @@
 /*
  * Ceph inode.
  */
-#define CEPH_I_COMPLETE  1  /* we have complete directory cached */
-#define CEPH_I_NODELAY   4  /* do not delay cap release */
-#define CEPH_I_FLUSH     8  /* do not delay flush of dirty metadata */
-#define CEPH_I_NOFLUSH  16  /* do not flush dirty caps */
-
 struct ceph_inode_info {
 	struct ceph_vino i_vino;   /* ceph ino + snap */
 
@@ -391,69 +320,9 @@
 	return container_of(inode, struct ceph_inode_info, vfs_inode);
 }
 
-static inline void ceph_i_clear(struct inode *inode, unsigned mask)
+static inline struct ceph_vino ceph_vino(struct inode *inode)
 {
-	struct ceph_inode_info *ci = ceph_inode(inode);
-
-	spin_lock(&inode->i_lock);
-	ci->i_ceph_flags &= ~mask;
-	spin_unlock(&inode->i_lock);
-}
-
-static inline void ceph_i_set(struct inode *inode, unsigned mask)
-{
-	struct ceph_inode_info *ci = ceph_inode(inode);
-
-	spin_lock(&inode->i_lock);
-	ci->i_ceph_flags |= mask;
-	spin_unlock(&inode->i_lock);
-}
-
-static inline bool ceph_i_test(struct inode *inode, unsigned mask)
-{
-	struct ceph_inode_info *ci = ceph_inode(inode);
-	bool r;
-
-	smp_mb();
-	r = (ci->i_ceph_flags & mask) == mask;
-	return r;
-}
-
-
-/* find a specific frag @f */
-extern struct ceph_inode_frag *__ceph_find_frag(struct ceph_inode_info *ci,
-						u32 f);
-
-/*
- * choose fragment for value @v.  copy frag content to pfrag, if leaf
- * exists
- */
-extern u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
-			    struct ceph_inode_frag *pfrag,
-			    int *found);
-
-/*
- * Ceph dentry state
- */
-struct ceph_dentry_info {
-	struct ceph_mds_session *lease_session;
-	u32 lease_gen, lease_shared_gen;
-	u32 lease_seq;
-	unsigned long lease_renew_after, lease_renew_from;
-	struct list_head lru;
-	struct dentry *dentry;
-	u64 time;
-	u64 offset;
-};
-
-static inline struct ceph_dentry_info *ceph_dentry(struct dentry *dentry)
-{
-	return (struct ceph_dentry_info *)dentry->d_fsdata;
-}
-
-static inline loff_t ceph_make_fpos(unsigned frag, unsigned off)
-{
-	return ((loff_t)frag << 32) | (loff_t)off;
+	return ceph_inode(inode)->i_vino;
 }
 
 /*
@@ -472,18 +341,6 @@
 	return ino;
 }
 
-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;
-}
-
-static inline struct ceph_vino ceph_vino(struct inode *inode)
-{
-	return ceph_inode(inode)->i_vino;
-}
-
 /* for printf-style formatting */
 #define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap
 
@@ -513,6 +370,73 @@
 
 
 /*
+ * Ceph inode.
+ */
+#define CEPH_I_COMPLETE  1  /* we have complete directory cached */
+#define CEPH_I_NODELAY   4  /* do not delay cap release */
+#define CEPH_I_FLUSH     8  /* do not delay flush of dirty metadata */
+#define CEPH_I_NOFLUSH  16  /* do not flush dirty caps */
+
+static inline void ceph_i_clear(struct inode *inode, unsigned mask)
+{
+	struct ceph_inode_info *ci = ceph_inode(inode);
+
+	spin_lock(&inode->i_lock);
+	ci->i_ceph_flags &= ~mask;
+	spin_unlock(&inode->i_lock);
+}
+
+static inline void ceph_i_set(struct inode *inode, unsigned mask)
+{
+	struct ceph_inode_info *ci = ceph_inode(inode);
+
+	spin_lock(&inode->i_lock);
+	ci->i_ceph_flags |= mask;
+	spin_unlock(&inode->i_lock);
+}
+
+static inline bool ceph_i_test(struct inode *inode, unsigned mask)
+{
+	struct ceph_inode_info *ci = ceph_inode(inode);
+	bool r;
+
+	spin_lock(&inode->i_lock);
+	r = (ci->i_ceph_flags & mask) == mask;
+	spin_unlock(&inode->i_lock);
+	return r;
+}
+
+
+/* find a specific frag @f */
+extern struct ceph_inode_frag *__ceph_find_frag(struct ceph_inode_info *ci,
+						u32 f);
+
+/*
+ * choose fragment for value @v.  copy frag content to pfrag, if leaf
+ * exists
+ */
+extern u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
+			    struct ceph_inode_frag *pfrag,
+			    int *found);
+
+static inline struct ceph_dentry_info *ceph_dentry(struct dentry *dentry)
+{
+	return (struct ceph_dentry_info *)dentry->d_fsdata;
+}
+
+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
  */
 static inline bool __ceph_is_any_real_caps(struct ceph_inode_info *ci)
@@ -576,18 +500,18 @@
 			     struct ceph_cap_reservation *ctx, int need);
 extern int ceph_unreserve_caps(struct ceph_mds_client *mdsc,
 			       struct ceph_cap_reservation *ctx);
-extern void ceph_reservation_status(struct ceph_client *client,
+extern void ceph_reservation_status(struct ceph_fs_client *client,
 				    int *total, int *avail, int *used,
 				    int *reserved, int *min);
 
-static inline struct ceph_client *ceph_inode_to_client(struct inode *inode)
+static inline struct ceph_fs_client *ceph_inode_to_client(struct inode *inode)
 {
-	return (struct ceph_client *)inode->i_sb->s_fs_info;
+	return (struct ceph_fs_client *)inode->i_sb->s_fs_info;
 }
 
-static inline struct ceph_client *ceph_sb_to_client(struct super_block *sb)
+static inline struct ceph_fs_client *ceph_sb_to_client(struct super_block *sb)
 {
-	return (struct ceph_client *)sb->s_fs_info;
+	return (struct ceph_fs_client *)sb->s_fs_info;
 }
 
 
@@ -617,51 +541,6 @@
 
 
 /*
- * snapshots
- */
-
-/*
- * A "snap context" is the set of existing snapshots when we
- * write data.  It is used by the OSD to guide its COW behavior.
- *
- * The ceph_snap_context is refcounted, and attached to each dirty
- * page, indicating which context the dirty data belonged when it was
- * dirtied.
- */
-struct ceph_snap_context {
-	atomic_t nref;
-	u64 seq;
-	int num_snaps;
-	u64 snaps[];
-};
-
-static inline struct ceph_snap_context *
-ceph_get_snap_context(struct ceph_snap_context *sc)
-{
-	/*
-	printk("get_snap_context %p %d -> %d\n", sc, atomic_read(&sc->nref),
-	       atomic_read(&sc->nref)+1);
-	*/
-	if (sc)
-		atomic_inc(&sc->nref);
-	return sc;
-}
-
-static inline void ceph_put_snap_context(struct ceph_snap_context *sc)
-{
-	if (!sc)
-		return;
-	/*
-	printk("put_snap_context %p %d -> %d\n", sc, atomic_read(&sc->nref),
-	       atomic_read(&sc->nref)-1);
-	*/
-	if (atomic_dec_and_test(&sc->nref)) {
-		/*printk(" deleting snap_context %p\n", sc);*/
-		kfree(sc);
-	}
-}
-
-/*
  * A "snap realm" describes a subset of the file hierarchy sharing
  * the same set of snapshots that apply to it.  The realms themselves
  * are organized into a hierarchy, such that children inherit (some of)
@@ -699,16 +578,33 @@
 	spinlock_t inodes_with_caps_lock;
 };
 
-
-
-/*
- * calculate the number of pages a given length and offset map onto,
- * if we align the data.
- */
-static inline int calc_pages_for(u64 off, u64 len)
+static inline int default_congestion_kb(void)
 {
-	return ((off+len+PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT) -
-		(off >> PAGE_CACHE_SHIFT);
+	int congestion_kb;
+
+	/*
+	 * Copied from NFS
+	 *
+	 * congestion size, scale with available memory.
+	 *
+	 *  64MB:    8192k
+	 * 128MB:   11585k
+	 * 256MB:   16384k
+	 * 512MB:   23170k
+	 *   1GB:   32768k
+	 *   2GB:   46340k
+	 *   4GB:   65536k
+	 *   8GB:   92681k
+	 *  16GB:  131072k
+	 *
+	 * This allows larger machines to have larger/more transfers.
+	 * Limit the default to 256M
+	 */
+	congestion_kb = (16*int_sqrt(totalram_pages)) << (PAGE_SHIFT-10);
+	if (congestion_kb > 256*1024)
+		congestion_kb = 256*1024;
+
+	return congestion_kb;
 }
 
 
@@ -741,16 +637,6 @@
 			   ci_item)->writing;
 }
 
-
-/* super.c */
-extern struct kmem_cache *ceph_inode_cachep;
-extern struct kmem_cache *ceph_cap_cachep;
-extern struct kmem_cache *ceph_dentry_cachep;
-extern struct kmem_cache *ceph_file_cachep;
-
-extern const char *ceph_msg_type_name(int type);
-extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
-
 /* inode.c */
 extern const struct inode_operations ceph_file_iops;
 
@@ -857,12 +743,18 @@
 /* file.c */
 extern const struct file_operations ceph_file_fops;
 extern const struct address_space_operations ceph_aops;
+extern int ceph_copy_to_page_vector(struct page **pages,
+				    const char *data,
+				    loff_t off, size_t len);
+extern int ceph_copy_from_page_vector(struct page **pages,
+				    char *data,
+				    loff_t off, size_t len);
+extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
 extern int ceph_open(struct inode *inode, struct file *file);
 extern struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
 				       struct nameidata *nd, int mode,
 				       int locked_dir);
 extern int ceph_release(struct inode *inode, struct file *filp);
-extern void ceph_release_page_vector(struct page **pages, int num_pages);
 
 /* dir.c */
 extern const struct file_operations ceph_dir_fops;
@@ -892,12 +784,6 @@
 /* export.c */
 extern const struct export_operations ceph_export_ops;
 
-/* debugfs.c */
-extern int ceph_debugfs_init(void);
-extern void ceph_debugfs_cleanup(void);
-extern int ceph_debugfs_client_init(struct ceph_client *client);
-extern void ceph_debugfs_client_cleanup(struct ceph_client *client);
-
 /* locks.c */
 extern int ceph_lock(struct file *file, int cmd, struct file_lock *fl);
 extern int ceph_flock(struct file *file, int cmd, struct file_lock *fl);
@@ -914,4 +800,8 @@
 	return NULL;
 }
 
+/* debugfs.c */
+extern int ceph_fs_debugfs_init(struct ceph_fs_client *client);
+extern void ceph_fs_debugfs_cleanup(struct ceph_fs_client *client);
+
 #endif /* _FS_CEPH_SUPER_H */
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 9578af6..6e12a6b 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -1,6 +1,9 @@
-#include "ceph_debug.h"
+#include <linux/ceph/ceph_debug.h>
+
 #include "super.h"
-#include "decode.h"
+#include "mds_client.h"
+
+#include <linux/ceph/decode.h>
 
 #include <linux/xattr.h>
 #include <linux/slab.h>
@@ -620,12 +623,12 @@
 static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
 			      const char *value, size_t size, int flags)
 {
-	struct ceph_client *client = ceph_sb_to_client(dentry->d_sb);
+	struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
 	struct inode *inode = dentry->d_inode;
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	struct inode *parent_inode = dentry->d_parent->d_inode;
 	struct ceph_mds_request *req;
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	int err;
 	int i, nr_pages;
 	struct page **pages = NULL;
@@ -713,10 +716,9 @@
 
 	/* preallocate memory for xattr name, value, index node */
 	err = -ENOMEM;
-	newname = kmalloc(name_len + 1, GFP_NOFS);
+	newname = kmemdup(name, name_len + 1, GFP_NOFS);
 	if (!newname)
 		goto out;
-	memcpy(newname, name, name_len + 1);
 
 	if (val_len) {
 		newval = kmalloc(val_len + 1, GFP_NOFS);
@@ -777,8 +779,8 @@
 
 static int ceph_send_removexattr(struct dentry *dentry, const char *name)
 {
-	struct ceph_client *client = ceph_sb_to_client(dentry->d_sb);
-	struct ceph_mds_client *mdsc = &client->mdsc;
+	struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
+	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct inode *inode = dentry->d_inode;
 	struct inode *parent_inode = dentry->d_parent->d_inode;
 	struct ceph_mds_request *req;
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 143d393..e5b9df9 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -456,6 +456,7 @@
  */
 const struct file_operations def_chr_fops = {
 	.open = chrdev_open,
+	.llseek = noop_llseek,
 };
 
 static struct kobject *exact_match(dev_t dev, int *part, void *data)
diff --git a/fs/cifs/README b/fs/cifs/README
index 7099a52..ee68d10 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -527,6 +527,11 @@
 		SFU does).  In the future the bottom 9 bits of the
 		mode also will be emulated using queries of the security
 		descriptor (ACL).
+ mfsymlinks     Enable support for Minshall+French symlinks
+		(see http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks)
+		This option is ignored when specified together with the
+		'sfu' option. Minshall+French symlinks are used even if
+		the server supports the CIFS Unix Extensions.
  sign           Must use packet signing (helps avoid unwanted data modification
 		by intermediate systems in the route).  Note that signing
 		does not work with lanman or plaintext authentication.
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index eb1ba49..103ab8b 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -148,7 +148,7 @@
 	seq_printf(m, "Servers:");
 
 	i = 0;
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp1, &cifs_tcp_ses_list) {
 		server = list_entry(tmp1, struct TCP_Server_Info,
 				    tcp_ses_list);
@@ -230,7 +230,7 @@
 			spin_unlock(&GlobalMid_Lock);
 		}
 	}
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	seq_putc(m, '\n');
 
 	/* BB add code to dump additional info such as TCP session info now */
@@ -270,7 +270,7 @@
 		atomic_set(&totBufAllocCount, 0);
 		atomic_set(&totSmBufAllocCount, 0);
 #endif /* CONFIG_CIFS_STATS2 */
-		read_lock(&cifs_tcp_ses_lock);
+		spin_lock(&cifs_tcp_ses_lock);
 		list_for_each(tmp1, &cifs_tcp_ses_list) {
 			server = list_entry(tmp1, struct TCP_Server_Info,
 					    tcp_ses_list);
@@ -303,7 +303,7 @@
 				}
 			}
 		}
-		read_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 	}
 
 	return count;
@@ -343,7 +343,7 @@
 		GlobalCurrentXid, GlobalMaxActiveXid);
 
 	i = 0;
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp1, &cifs_tcp_ses_list) {
 		server = list_entry(tmp1, struct TCP_Server_Info,
 				    tcp_ses_list);
@@ -397,7 +397,7 @@
 			}
 		}
 	}
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	seq_putc(m, '\n');
 	return 0;
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index aa31689..8942b28 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -34,7 +34,7 @@
 extern int traceSMB;		/* flag which enables the function below */
 void dump_smb(struct smb_hdr *, int);
 #define CIFS_INFO	0x01
-#define CIFS_RC  	0x02
+#define CIFS_RC		0x02
 #define CIFS_TIMER	0x04
 
 /*
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index d6ced7a..c68a056 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -44,8 +44,7 @@
 void cifs_dfs_release_automount_timer(void)
 {
 	BUG_ON(!list_empty(&cifs_dfs_automount_list));
-	cancel_delayed_work(&cifs_dfs_automount_task);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&cifs_dfs_automount_task);
 }
 
 /**
@@ -306,6 +305,7 @@
 	int xid, i;
 	int rc = 0;
 	struct vfsmount *mnt = ERR_PTR(-ENOENT);
+	struct tcon_link *tlink;
 
 	cFYI(1, "in %s", __func__);
 	BUG_ON(IS_ROOT(dentry));
@@ -315,14 +315,6 @@
 	dput(nd->path.dentry);
 	nd->path.dentry = dget(dentry);
 
-	cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
-	ses = cifs_sb->tcon->ses;
-
-	if (!ses) {
-		rc = -EINVAL;
-		goto out_err;
-	}
-
 	/*
 	 * The MSDFS spec states that paths in DFS referral requests and
 	 * responses must be prefixed by a single '\' character instead of
@@ -335,10 +327,20 @@
 		goto out_err;
 	}
 
-	rc = get_dfs_path(xid, ses , full_path + 1, cifs_sb->local_nls,
+	cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		goto out_err;
+	}
+	ses = tlink_tcon(tlink)->ses;
+
+	rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls,
 		&num_referrals, &referrals,
 		cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 
+	cifs_put_tlink(tlink);
+
 	for (i = 0; i < num_referrals; i++) {
 		int len;
 		dump_referral(referrals+i);
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 9e77145..525ba59 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -15,6 +15,8 @@
  *   the GNU Lesser General Public License for more details.
  *
  */
+#include <linux/radix-tree.h>
+
 #ifndef _CIFS_FS_SB_H
 #define _CIFS_FS_SB_H
 
@@ -36,23 +38,28 @@
 #define CIFS_MOUNT_NOPOSIXBRL   0x2000 /* mandatory not posix byte range lock */
 #define CIFS_MOUNT_NOSSYNC      0x4000 /* don't do slow SMBflush on every sync*/
 #define CIFS_MOUNT_FSCACHE	0x8000 /* local caching enabled */
+#define CIFS_MOUNT_MF_SYMLINKS	0x10000 /* Minshall+French Symlinks enabled */
+#define CIFS_MOUNT_MULTIUSER	0x20000 /* multiuser mount */
 
 struct cifs_sb_info {
-	struct cifsTconInfo *tcon;	/* primary mount */
-	struct list_head nested_tcon_q;
+	struct radix_tree_root tlink_tree;
+#define CIFS_TLINK_MASTER_TAG		0	/* is "master" (mount) tcon */
+	spinlock_t tlink_tree_lock;
 	struct nls_table *local_nls;
 	unsigned int rsize;
 	unsigned int wsize;
+	atomic_t active;
 	uid_t	mnt_uid;
 	gid_t	mnt_gid;
 	mode_t	mnt_file_mode;
 	mode_t	mnt_dir_mode;
-	int     mnt_cifs_flags;
+	unsigned int mnt_cifs_flags;
 	int	prepathlen;
 	char   *prepath; /* relative path under the share to mount to */
 #ifdef CONFIG_CIFS_DFS_UPCALL
 	char   *mountdata; /* mount options received at mount time */
 #endif
 	struct backing_dev_info bdi;
+	struct delayed_work prune_tlinks;
 };
 #endif				/* _CIFS_FS_SB_H */
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 85d7cf7..c9b4792 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -557,11 +557,16 @@
 {
 	struct cifs_ntsd *pntsd = NULL;
 	int xid, rc;
+	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+
+	if (IS_ERR(tlink))
+		return NULL;
 
 	xid = GetXid();
-	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
+	rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
 	FreeXid(xid);
 
+	cifs_put_tlink(tlink);
 
 	cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
 	return pntsd;
@@ -574,10 +579,16 @@
 	int oplock = 0;
 	int xid, rc;
 	__u16 fid;
+	struct cifsTconInfo *tcon;
+	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 
+	if (IS_ERR(tlink))
+		return NULL;
+
+	tcon = tlink_tcon(tlink);
 	xid = GetXid();
 
-	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0,
+	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
 			 &fid, &oplock, NULL, cifs_sb->local_nls,
 			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc) {
@@ -585,11 +596,12 @@
 		goto out;
 	}
 
-	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
+	rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
 	cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
 
-	CIFSSMBClose(xid, cifs_sb->tcon, fid);
+	CIFSSMBClose(xid, tcon, fid);
  out:
+	cifs_put_tlink(tlink);
 	FreeXid(xid);
 	return pntsd;
 }
@@ -603,7 +615,7 @@
 	struct cifsFileInfo *open_file = NULL;
 
 	if (inode)
-		open_file = find_readable_file(CIFS_I(inode));
+		open_file = find_readable_file(CIFS_I(inode), true);
 	if (!open_file)
 		return get_cifs_acl_by_path(cifs_sb, path, pacllen);
 
@@ -616,10 +628,15 @@
 		struct cifs_ntsd *pnntsd, u32 acllen)
 {
 	int xid, rc;
+	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
 
 	xid = GetXid();
-	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
+	rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 
 	cFYI(DBG2, "SetCIFSACL rc = %d", rc);
 	return rc;
@@ -631,10 +648,16 @@
 	int oplock = 0;
 	int xid, rc;
 	__u16 fid;
+	struct cifsTconInfo *tcon;
+	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+
+	tcon = tlink_tcon(tlink);
 	xid = GetXid();
 
-	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0,
+	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0,
 			 &fid, &oplock, NULL, cifs_sb->local_nls,
 			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc) {
@@ -642,12 +665,13 @@
 		goto out;
 	}
 
-	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
+	rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
 	cFYI(DBG2, "SetCIFSACL rc = %d", rc);
 
-	CIFSSMBClose(xid, cifs_sb->tcon, fid);
- out:
+	CIFSSMBClose(xid, tcon, fid);
+out:
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -661,7 +685,7 @@
 
 	cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
 
-	open_file = find_readable_file(CIFS_I(inode));
+	open_file = find_readable_file(CIFS_I(inode), true);
 	if (!open_file)
 		return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
 
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 35042d8..7ac0056 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -27,6 +27,7 @@
 #include "md5.h"
 #include "cifs_unicode.h"
 #include "cifsproto.h"
+#include "ntlmssp.h"
 #include <linux/ctype.h>
 #include <linux/random.h>
 
@@ -42,7 +43,7 @@
 		       unsigned char *p24);
 
 static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
-				    const struct mac_key *key, char *signature)
+				const struct session_key *key, char *signature)
 {
 	struct	MD5Context context;
 
@@ -78,7 +79,7 @@
 	server->sequence_number++;
 	spin_unlock(&GlobalMid_Lock);
 
-	rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key,
+	rc = cifs_calculate_signature(cifs_pdu, &server->session_key,
 				      smb_signature);
 	if (rc)
 		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
@@ -89,7 +90,7 @@
 }
 
 static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
-				const struct mac_key *key, char *signature)
+				const struct session_key *key, char *signature)
 {
 	struct  MD5Context context;
 	int i;
@@ -145,7 +146,7 @@
 	server->sequence_number++;
 	spin_unlock(&GlobalMid_Lock);
 
-	rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key,
+	rc = cifs_calc_signature2(iov, n_vec, &server->session_key,
 				      smb_signature);
 	if (rc)
 		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
@@ -156,14 +157,14 @@
 }
 
 int cifs_verify_signature(struct smb_hdr *cifs_pdu,
-			  const struct mac_key *mac_key,
+			  const struct session_key *session_key,
 			  __u32 expected_sequence_number)
 {
 	unsigned int rc;
 	char server_response_sig[8];
 	char what_we_think_sig_should_be[20];
 
-	if ((cifs_pdu == NULL) || (mac_key == NULL))
+	if (cifs_pdu == NULL || session_key == NULL)
 		return -EINVAL;
 
 	if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
@@ -192,7 +193,7 @@
 					cpu_to_le32(expected_sequence_number);
 	cifs_pdu->Signature.Sequence.Reserved = 0;
 
-	rc = cifs_calculate_signature(cifs_pdu, mac_key,
+	rc = cifs_calculate_signature(cifs_pdu, session_key,
 		what_we_think_sig_should_be);
 
 	if (rc)
@@ -209,7 +210,7 @@
 }
 
 /* We fill in key by putting in 40 byte array which was allocated by caller */
-int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
+int cifs_calculate_session_key(struct session_key *key, const char *rn,
 			   const char *password)
 {
 	char temp_key[16];
@@ -262,6 +263,148 @@
 }
 #endif /* CIFS_WEAK_PW_HASH */
 
+/* Build a proper attribute value/target info pairs blob.
+ * Fill in netbios and dns domain name and workstation name
+ * and client time (total five av pairs and + one end of fields indicator.
+ * Allocate domain name which gets freed when session struct is deallocated.
+ */
+static int
+build_avpair_blob(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
+{
+	unsigned int dlen;
+	unsigned int wlen;
+	unsigned int size = 6 * sizeof(struct ntlmssp2_name);
+	__le64  curtime;
+	char *defdmname = "WORKGROUP";
+	unsigned char *blobptr;
+	struct ntlmssp2_name *attrptr;
+
+	if (!ses->domainName) {
+		ses->domainName = kstrdup(defdmname, GFP_KERNEL);
+		if (!ses->domainName)
+			return -ENOMEM;
+	}
+
+	dlen = strlen(ses->domainName);
+	wlen = strlen(ses->server->hostname);
+
+	/* The length of this blob is a size which is
+	 * six times the size of a structure which holds name/size +
+	 * two times the unicode length of a domain name +
+	 * two times the unicode length of a server name +
+	 * size of a timestamp (which is 8 bytes).
+	 */
+	ses->tilen = size + 2 * (2 * dlen) + 2 * (2 * wlen) + 8;
+	ses->tiblob = kzalloc(ses->tilen, GFP_KERNEL);
+	if (!ses->tiblob) {
+		ses->tilen = 0;
+		cERROR(1, "Challenge target info allocation failure");
+		return -ENOMEM;
+	}
+
+	blobptr = ses->tiblob;
+	attrptr = (struct ntlmssp2_name *) blobptr;
+
+	attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
+	attrptr->length = cpu_to_le16(2 * dlen);
+	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
+	cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
+
+	blobptr += 2 * dlen;
+	attrptr = (struct ntlmssp2_name *) blobptr;
+
+	attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_COMPUTER_NAME);
+	attrptr->length = cpu_to_le16(2 * wlen);
+	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
+	cifs_strtoUCS((__le16 *)blobptr, ses->server->hostname, wlen, nls_cp);
+
+	blobptr += 2 * wlen;
+	attrptr = (struct ntlmssp2_name *) blobptr;
+
+	attrptr->type = cpu_to_le16(NTLMSSP_AV_DNS_DOMAIN_NAME);
+	attrptr->length = cpu_to_le16(2 * dlen);
+	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
+	cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
+
+	blobptr += 2 * dlen;
+	attrptr = (struct ntlmssp2_name *) blobptr;
+
+	attrptr->type = cpu_to_le16(NTLMSSP_AV_DNS_COMPUTER_NAME);
+	attrptr->length = cpu_to_le16(2 * wlen);
+	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
+	cifs_strtoUCS((__le16 *)blobptr, ses->server->hostname, wlen, nls_cp);
+
+	blobptr += 2 * wlen;
+	attrptr = (struct ntlmssp2_name *) blobptr;
+
+	attrptr->type = cpu_to_le16(NTLMSSP_AV_TIMESTAMP);
+	attrptr->length = cpu_to_le16(sizeof(__le64));
+	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
+	curtime = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+	memcpy(blobptr, &curtime, sizeof(__le64));
+
+	return 0;
+}
+
+/* Server has provided av pairs/target info in the type 2 challenge
+ * packet and we have plucked it and stored within smb session.
+ * We parse that blob here to find netbios domain name to be used
+ * as part of ntlmv2 authentication (in Target String), if not already
+ * specified on the command line.
+ * If this function returns without any error but without fetching
+ * domain name, authentication may fail against some server but
+ * may not fail against other (those who are not very particular
+ * about target string i.e. for some, just user name might suffice.
+ */
+static int
+find_domain_name(struct cifsSesInfo *ses)
+{
+	unsigned int attrsize;
+	unsigned int type;
+	unsigned int onesize = sizeof(struct ntlmssp2_name);
+	unsigned char *blobptr;
+	unsigned char *blobend;
+	struct ntlmssp2_name *attrptr;
+
+	if (!ses->tilen || !ses->tiblob)
+		return 0;
+
+	blobptr = ses->tiblob;
+	blobend = ses->tiblob + ses->tilen;
+
+	while (blobptr + onesize < blobend) {
+		attrptr = (struct ntlmssp2_name *) blobptr;
+		type = le16_to_cpu(attrptr->type);
+		if (type == NTLMSSP_AV_EOL)
+			break;
+		blobptr += 2; /* advance attr type */
+		attrsize = le16_to_cpu(attrptr->length);
+		blobptr += 2; /* advance attr size */
+		if (blobptr + attrsize > blobend)
+			break;
+		if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
+			if (!attrsize)
+				break;
+			if (!ses->domainName) {
+				struct nls_table *default_nls;
+				ses->domainName =
+					kmalloc(attrsize + 1, GFP_KERNEL);
+				if (!ses->domainName)
+						return -ENOMEM;
+				default_nls = load_nls_default();
+				cifs_from_ucs2(ses->domainName,
+					(__le16 *)blobptr, attrsize, attrsize,
+					default_nls, false);
+				unload_nls(default_nls);
+				break;
+			}
+		}
+		blobptr += attrsize; /* advance attr  value */
+	}
+
+	return 0;
+}
+
 static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
 			    const struct nls_table *nls_cp)
 {
@@ -315,13 +458,14 @@
 calc_exit_2:
 	/* BB FIXME what about bytes 24 through 40 of the signing key?
 	   compare with the NTLM example */
-	hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
+	hmac_md5_final(ses->ntlmv2_hash, pctxt);
 
 	kfree(pctxt);
 	return rc;
 }
 
-void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
+int
+setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
 		      const struct nls_table *nls_cp)
 {
 	int rc;
@@ -333,25 +477,48 @@
 	buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
 	get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
 	buf->reserved2 = 0;
-	buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
-	buf->names[0].length = 0;
-	buf->names[1].type = 0;
-	buf->names[1].length = 0;
+
+	if (ses->server->secType == RawNTLMSSP) {
+		if (!ses->domainName) {
+			rc = find_domain_name(ses);
+			if (rc) {
+				cERROR(1, "error %d finding domain name", rc);
+				goto setup_ntlmv2_rsp_ret;
+			}
+		}
+	} else {
+		rc = build_avpair_blob(ses, nls_cp);
+		if (rc) {
+			cERROR(1, "error %d building av pair blob", rc);
+			return rc;
+		}
+	}
 
 	/* calculate buf->ntlmv2_hash */
 	rc = calc_ntlmv2_hash(ses, nls_cp);
-	if (rc)
+	if (rc) {
 		cERROR(1, "could not get v2 hash rc %d", rc);
+		goto setup_ntlmv2_rsp_ret;
+	}
 	CalcNTLMv2_response(ses, resp_buf);
 
-	/* now calculate the MAC key for NTLMv2 */
-	hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
+	/* now calculate the session key for NTLMv2 */
+	hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context);
 	hmac_md5_update(resp_buf, 16, &context);
-	hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context);
+	hmac_md5_final(ses->auth_key.data.ntlmv2.key, &context);
 
-	memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf,
+	memcpy(&ses->auth_key.data.ntlmv2.resp, resp_buf,
 	       sizeof(struct ntlmv2_resp));
-	ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp);
+	ses->auth_key.len = 16 + sizeof(struct ntlmv2_resp);
+
+	return 0;
+
+setup_ntlmv2_rsp_ret:
+	kfree(ses->tiblob);
+	ses->tiblob = NULL;
+	ses->tilen = 0;
+
+	return rc;
 }
 
 void CalcNTLMv2_response(const struct cifsSesInfo *ses,
@@ -359,12 +526,15 @@
 {
 	struct HMACMD5Context context;
 	/* rest of v2 struct already generated */
-	memcpy(v2_session_response + 8, ses->server->cryptKey, 8);
-	hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
+	memcpy(v2_session_response + 8, ses->cryptKey, 8);
+	hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context);
 
 	hmac_md5_update(v2_session_response+8,
 			sizeof(struct ntlmv2_resp) - 8, &context);
 
+	if (ses->tilen)
+		hmac_md5_update(ses->tiblob, ses->tilen, &context);
+
 	hmac_md5_final(v2_session_response, &context);
 /*	cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
 }
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index b7431af..3437163 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -35,7 +35,7 @@
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
-#include <linux/smp_lock.h>
+#include <net/ipv6.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #define DECLARE_GLOBALS_HERE
@@ -82,6 +82,24 @@
 extern mempool_t *cifs_req_poolp;
 extern mempool_t *cifs_mid_poolp;
 
+void
+cifs_sb_active(struct super_block *sb)
+{
+	struct cifs_sb_info *server = CIFS_SB(sb);
+
+	if (atomic_inc_return(&server->active) == 1)
+		atomic_inc(&sb->s_active);
+}
+
+void
+cifs_sb_deactive(struct super_block *sb)
+{
+	struct cifs_sb_info *server = CIFS_SB(sb);
+
+	if (atomic_dec_and_test(&server->active))
+		deactivate_super(sb);
+}
+
 static int
 cifs_read_super(struct super_block *sb, void *data,
 		const char *devname, int silent)
@@ -97,6 +115,9 @@
 	if (cifs_sb == NULL)
 		return -ENOMEM;
 
+	spin_lock_init(&cifs_sb->tlink_tree_lock);
+	INIT_RADIX_TREE(&cifs_sb->tlink_tree, GFP_KERNEL);
+
 	rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
 	if (rc) {
 		kfree(cifs_sb);
@@ -136,9 +157,6 @@
 	sb->s_magic = CIFS_MAGIC_NUMBER;
 	sb->s_op = &cifs_super_ops;
 	sb->s_bdi = &cifs_sb->bdi;
-/*	if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
-	    sb->s_blocksize =
-		cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
 	sb->s_blocksize = CIFS_MAX_MSGSIZE;
 	sb->s_blocksize_bits = 14;	/* default 2**14 = CIFS_MAX_MSGSIZE */
 	inode = cifs_root_iget(sb, ROOT_I);
@@ -200,8 +218,6 @@
 		return;
 	}
 
-	lock_kernel();
-
 	rc = cifs_umount(sb, cifs_sb);
 	if (rc)
 		cERROR(1, "cifs_umount failed with return code %d", rc);
@@ -215,8 +231,6 @@
 	unload_nls(cifs_sb->local_nls);
 	bdi_destroy(&cifs_sb->bdi);
 	kfree(cifs_sb);
-
-	unlock_kernel();
 }
 
 static int
@@ -224,7 +238,7 @@
 {
 	struct super_block *sb = dentry->d_sb;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 	int rc = -EOPNOTSUPP;
 	int xid;
 
@@ -366,14 +380,36 @@
 cifs_show_options(struct seq_file *s, struct vfsmount *m)
 {
 	struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
+	struct sockaddr *srcaddr;
+	srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;
 
 	seq_printf(s, ",unc=%s", tcon->treeName);
-	if (tcon->ses->userName)
+
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
+		seq_printf(s, ",multiuser");
+	else if (tcon->ses->userName)
 		seq_printf(s, ",username=%s", tcon->ses->userName);
+
 	if (tcon->ses->domainName)
 		seq_printf(s, ",domain=%s", tcon->ses->domainName);
 
+	if (srcaddr->sa_family != AF_UNSPEC) {
+		struct sockaddr_in *saddr4;
+		struct sockaddr_in6 *saddr6;
+		saddr4 = (struct sockaddr_in *)srcaddr;
+		saddr6 = (struct sockaddr_in6 *)srcaddr;
+		if (srcaddr->sa_family == AF_INET6)
+			seq_printf(s, ",srcaddr=%pI6c",
+				   &saddr6->sin6_addr);
+		else if (srcaddr->sa_family == AF_INET)
+			seq_printf(s, ",srcaddr=%pI4",
+				   &saddr4->sin_addr.s_addr);
+		else
+			seq_printf(s, ",srcaddr=BAD-AF:%i",
+				   (int)(srcaddr->sa_family));
+	}
+
 	seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
 		seq_printf(s, ",forceuid");
@@ -422,6 +458,8 @@
 		seq_printf(s, ",dynperm");
 	if (m->mnt_sb->s_flags & MS_POSIXACL)
 		seq_printf(s, ",acl");
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+		seq_printf(s, ",mfsymlinks");
 
 	seq_printf(s, ",rsize=%d", cifs_sb->rsize);
 	seq_printf(s, ",wsize=%d", cifs_sb->wsize);
@@ -437,20 +475,18 @@
 	if (cifs_sb == NULL)
 		return;
 
-	tcon = cifs_sb->tcon;
-	if (tcon == NULL)
-		return;
+	tcon = cifs_sb_master_tcon(cifs_sb);
 
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) {
 		/* we have other mounts to same share or we have
 		   already tried to force umount this and woken up
 		   all waiting network requests, nothing to do */
-		read_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return;
 	} else if (tcon->tc_count == 1)
 		tcon->tidStatus = CifsExiting;
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
 	/* cancel_notify_requests(tcon); */
@@ -514,7 +550,9 @@
 	    int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
 	int rc;
-	struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
+	struct super_block *sb;
+
+	sb = sget(fs_type, NULL, set_anon_super, NULL);
 
 	cFYI(1, "Devname: %s flags: %d ", dev_name, flags);
 
@@ -565,9 +603,10 @@
 
 static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
 {
-	/* note that this is called by vfs setlease with the BKL held
-	   although I doubt that BKL is needed here in cifs */
+	/* note that this is called by vfs setlease with lock_flocks held
+	   to protect *lease from going away */
 	struct inode *inode = file->f_path.dentry->d_inode;
+	struct cifsFileInfo *cfile = file->private_data;
 
 	if (!(S_ISREG(inode->i_mode)))
 		return -EINVAL;
@@ -578,8 +617,8 @@
 	    ((arg == F_WRLCK) &&
 		(CIFS_I(inode)->clientCanCacheAll)))
 		return generic_setlease(file, arg, lease);
-	else if (CIFS_SB(inode->i_sb)->tcon->local_lease &&
-			!CIFS_I(inode)->clientCanCacheRead)
+	else if (tlink_tcon(cfile->tlink)->local_lease &&
+		 !CIFS_I(inode)->clientCanCacheRead)
 		/* If the server claims to support oplock on this
 		   file, then we still need to check oplock even
 		   if the local_lease mount option is set, but there
@@ -898,8 +937,8 @@
 	GlobalTotalActiveXid = 0;
 	GlobalMaxActiveXid = 0;
 	memset(Local_System_Name, 0, 15);
-	rwlock_init(&GlobalSMBSeslock);
-	rwlock_init(&cifs_tcp_ses_lock);
+	spin_lock_init(&cifs_tcp_ses_lock);
+	spin_lock_init(&cifs_file_list_lock);
 	spin_lock_init(&GlobalMid_Lock);
 
 	if (cifs_max_pending < 2) {
@@ -912,11 +951,11 @@
 
 	rc = cifs_fscache_register();
 	if (rc)
-		goto out;
+		goto out_clean_proc;
 
 	rc = cifs_init_inodecache();
 	if (rc)
-		goto out_clean_proc;
+		goto out_unreg_fscache;
 
 	rc = cifs_init_mids();
 	if (rc)
@@ -938,19 +977,19 @@
 	return 0;
 
 #ifdef CONFIG_CIFS_UPCALL
- out_unregister_filesystem:
+out_unregister_filesystem:
 	unregister_filesystem(&cifs_fs_type);
 #endif
- out_destroy_request_bufs:
+out_destroy_request_bufs:
 	cifs_destroy_request_bufs();
- out_destroy_mids:
+out_destroy_mids:
 	cifs_destroy_mids();
- out_destroy_inodecache:
+out_destroy_inodecache:
 	cifs_destroy_inodecache();
- out_clean_proc:
-	cifs_proc_clean();
+out_unreg_fscache:
 	cifs_fscache_unregister();
- out:
+out_clean_proc:
+	cifs_proc_clean();
 	return rc;
 }
 
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index d82f5fb..f35795a 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -42,10 +42,8 @@
 extern const struct address_space_operations cifs_addr_ops_smallbuf;
 
 /* Functions related to super block operations */
-/* extern const struct super_operations cifs_super_ops;*/
-extern void cifs_read_inode(struct inode *);
-/*extern void cifs_delete_inode(struct inode *);*/  /* BB not needed yet */
-/* extern void cifs_write_inode(struct inode *); */ /* BB not needed yet */
+extern void cifs_sb_active(struct super_block *sb);
+extern void cifs_sb_deactive(struct super_block *sb);
 
 /* Functions related to inodes */
 extern const struct inode_operations cifs_dir_inode_ops;
@@ -104,7 +102,7 @@
 extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
 			const char *symname);
 extern int	cifs_removexattr(struct dentry *, const char *);
-extern int 	cifs_setxattr(struct dentry *, const char *, const void *,
+extern int	cifs_setxattr(struct dentry *, const char *, const void *,
 			size_t, int);
 extern ssize_t	cifs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
@@ -114,5 +112,5 @@
 extern const struct export_operations cifs_export_ops;
 #endif /* EXPERIMENTAL */
 
-#define CIFS_VERSION   "1.65"
+#define CIFS_VERSION   "1.67"
 #endif				/* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 0cdfb8c..3365e77f 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -97,7 +97,7 @@
 	/* Netbios frames protocol not supported at this time */
 };
 
-struct mac_key {
+struct session_key {
 	unsigned int len;
 	union {
 		char ntlm[CIFS_SESS_KEY_SIZE + 16];
@@ -139,6 +139,7 @@
 		struct sockaddr_in sockAddr;
 		struct sockaddr_in6 sockAddr6;
 	} addr;
+	struct sockaddr_storage srcaddr; /* locally bind to this IP */
 	wait_queue_head_t response_q;
 	wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
 	struct list_head pending_mid_q;
@@ -178,12 +179,10 @@
 	int capabilities; /* allow selective disabling of caps by smb sess */
 	int timeAdj;  /* Adjust for difference in server time zone in sec */
 	__u16 CurrentMid;         /* multiplex id - rotating counter */
-	char cryptKey[CIFS_CRYPTO_KEY_SIZE];
 	/* 16th byte of RFC1001 workstation name is always null */
 	char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
 	__u32 sequence_number; /* needed for CIFS PDU signature */
-	struct mac_key mac_signing_key;
-	char ntlmv2_hash[16];
+	struct session_key session_key;
 	unsigned long lstrp; /* when we got last response from this server */
 	u16 dialect; /* dialect index that server chose */
 	/* extended security flavors that server supports */
@@ -191,6 +190,7 @@
 	bool	sec_mskerberos;		/* supports legacy MS Kerberos */
 	bool	sec_kerberosu2u;	/* supports U2U Kerberos */
 	bool	sec_ntlmssp;		/* supports NTLMSSP */
+	bool session_estab; /* mark when very first sess is established */
 #ifdef CONFIG_CIFS_FSCACHE
 	struct fscache_cookie   *fscache; /* client index cache cookie */
 #endif
@@ -222,6 +222,11 @@
 	char userName[MAX_USERNAME_SIZE + 1];
 	char *domainName;
 	char *password;
+	char cryptKey[CIFS_CRYPTO_KEY_SIZE];
+	struct session_key auth_key;
+	char ntlmv2_hash[16];
+	unsigned int tilen; /* length of the target info blob */
+	unsigned char *tiblob; /* target info blob in challenge response */
 	bool need_reconnect:1; /* connection reset, uid now invalid */
 };
 /* no more than one of the following three session flags may be set */
@@ -308,6 +313,44 @@
 };
 
 /*
+ * This is a refcounted and timestamped container for a tcon pointer. The
+ * container holds a tcon reference. It is considered safe to free one of
+ * these when the tl_count goes to 0. The tl_time is the time of the last
+ * "get" on the container.
+ */
+struct tcon_link {
+	unsigned long		tl_index;
+	unsigned long		tl_flags;
+#define TCON_LINK_MASTER	0
+#define TCON_LINK_PENDING	1
+#define TCON_LINK_IN_TREE	2
+	unsigned long		tl_time;
+	atomic_t		tl_count;
+	struct cifsTconInfo	*tl_tcon;
+};
+
+extern struct tcon_link *cifs_sb_tlink(struct cifs_sb_info *cifs_sb);
+
+static inline struct cifsTconInfo *
+tlink_tcon(struct tcon_link *tlink)
+{
+	return tlink->tl_tcon;
+}
+
+extern void cifs_put_tlink(struct tcon_link *tlink);
+
+static inline struct tcon_link *
+cifs_get_tlink(struct tcon_link *tlink)
+{
+	if (tlink && !IS_ERR(tlink))
+		atomic_inc(&tlink->tl_count);
+	return tlink;
+}
+
+/* This function is always expected to succeed */
+extern struct cifsTconInfo *cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb);
+
+/*
  * This info hangs off the cifsFileInfo structure, pointed to by llist.
  * This is used to track byte stream locks on the file
  */
@@ -345,12 +388,11 @@
 	__u16 netfid;		/* file id from remote */
 	/* BB add lock scope info here if needed */ ;
 	/* lock scope id (0 if none) */
-	struct file *pfile; /* needed for writepage */
-	struct inode *pInode; /* needed for oplock break */
-	struct vfsmount *mnt;
+	struct dentry *dentry;
+	unsigned int f_flags;
+	struct tcon_link *tlink;
 	struct mutex lock_mutex;
 	struct list_head llist; /* list of byte range locks we have. */
-	bool closePend:1;	/* file is marked to close */
 	bool invalidHandle:1;	/* file closed via session abend */
 	bool oplock_break_cancelled:1;
 	atomic_t count;		/* reference count */
@@ -365,14 +407,7 @@
 	atomic_inc(&cifs_file->count);
 }
 
-/* Release a reference on the file private data */
-static inline void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
-{
-	if (atomic_dec_and_test(&cifs_file->count)) {
-		iput(cifs_file->pInode);
-		kfree(cifs_file);
-	}
-}
+void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
 
 /*
  * One of these for each file inode
@@ -474,16 +509,16 @@
 
 /* for pending dnotify requests */
 struct dir_notify_req {
-       struct list_head lhead;
-       __le16 Pid;
-       __le16 PidHigh;
-       __u16 Mid;
-       __u16 Tid;
-       __u16 Uid;
-       __u16 netfid;
-       __u32 filter; /* CompletionFilter (for multishot) */
-       int multishot;
-       struct file *pfile;
+	struct list_head lhead;
+	__le16 Pid;
+	__le16 PidHigh;
+	__u16 Mid;
+	__u16 Tid;
+	__u16 Uid;
+	__u16 netfid;
+	__u32 filter; /* CompletionFilter (for multishot) */
+	int multishot;
+	struct file *pfile;
 };
 
 struct dfs_info3_param {
@@ -667,7 +702,7 @@
  * the reference counters for the server, smb session, and tcon. Finally,
  * changes to the tcon->tidStatus should be done while holding this lock.
  */
-GLOBAL_EXTERN rwlock_t		cifs_tcp_ses_lock;
+GLOBAL_EXTERN spinlock_t		cifs_tcp_ses_lock;
 
 /*
  * This lock protects the cifs_file->llist and cifs_file->flist
@@ -676,7 +711,7 @@
  * If cifs_tcp_ses_lock and the lock below are both needed to be held, then
  * the cifs_tcp_ses_lock must be grabbed first and released last.
  */
-GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
+GLOBAL_EXTERN spinlock_t	cifs_file_list_lock;
 
 /* Outstanding dir notify requests */
 GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 14d036d..b0f4b56 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -663,7 +663,6 @@
 	__le64  time;
 	__u64  client_chal; /* random */
 	__u32  reserved2;
-	struct ntlmssp2_name names[2];
 	/* array of name entries could follow ending in minimum 4 byte struct */
 } __attribute__((packed));
 
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1d60c65..e593c40 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -78,9 +78,9 @@
 extern bool is_valid_oplock_break(struct smb_hdr *smb,
 				  struct TCP_Server_Info *);
 extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
-extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
+extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *);
+extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
 #endif
 extern unsigned int smbCalcSize(struct smb_hdr *ptr);
 extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
@@ -105,12 +105,12 @@
 extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
 				      int offset);
 
-extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
-				__u16 fileHandle, struct file *file,
-				struct vfsmount *mnt, unsigned int oflags);
+extern struct cifsFileInfo *cifs_new_fileinfo(__u16 fileHandle,
+				struct file *file, struct tcon_link *tlink,
+				__u32 oplock);
 extern int cifs_posix_open(char *full_path, struct inode **pinode,
 				struct super_block *sb,
-				int mode, int oflags,
+				int mode, unsigned int f_flags,
 				__u32 *poplock, __u16 *pnetfid, int xid);
 void cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr);
 extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
@@ -362,12 +362,12 @@
 extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
 			  __u32 *);
 extern int cifs_verify_signature(struct smb_hdr *,
-				 const struct mac_key *mac_key,
+				 const struct session_key *session_key,
 				__u32 expected_sequence_number);
-extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
+extern int cifs_calculate_session_key(struct session_key *key, const char *rn,
 				 const char *pass);
 extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
-extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
+extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
 			     const struct nls_table *);
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 extern void calc_lanman_hash(const char *password, const char *cryptkey,
@@ -408,4 +408,8 @@
 extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
 			const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
 extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
+extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr);
+extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
+		const unsigned char *path,
+		struct cifs_sb_info *cifs_sb, int xid);
 #endif			/* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index c65c341..e98f1f3 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -91,13 +91,13 @@
 	struct list_head *tmp1;
 
 /* list all files open on tree connection and mark them invalid */
-	write_lock(&GlobalSMBSeslock);
+	spin_lock(&cifs_file_list_lock);
 	list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
 		open_file = list_entry(tmp, struct cifsFileInfo, tlist);
 		open_file->invalidHandle = true;
 		open_file->oplock_break_cancelled = true;
 	}
-	write_unlock(&GlobalSMBSeslock);
+	spin_unlock(&cifs_file_list_lock);
 	/* BB Add call to invalidate_inodes(sb) for all superblocks mounted
 	   to this tcon */
 }
@@ -232,7 +232,7 @@
 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
 		void **request_buf)
 {
-	int rc = 0;
+	int rc;
 
 	rc = cifs_reconnect_tcon(tcon, smb_command);
 	if (rc)
@@ -250,7 +250,7 @@
 	if (tcon != NULL)
 		cifs_stats_inc(&tcon->num_smbs_sent);
 
-	return rc;
+	return 0;
 }
 
 int
@@ -281,16 +281,9 @@
 
 /* If the return code is zero, this function must fill in request_buf pointer */
 static int
-smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
-	 void **request_buf /* returned */ ,
-	 void **response_buf /* returned */ )
+__smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+			void **request_buf, void **response_buf)
 {
-	int rc = 0;
-
-	rc = cifs_reconnect_tcon(tcon, smb_command);
-	if (rc)
-		return rc;
-
 	*request_buf = cifs_buf_get();
 	if (*request_buf == NULL) {
 		/* BB should we add a retry in here if not a writepage? */
@@ -309,7 +302,31 @@
 	if (tcon != NULL)
 		cifs_stats_inc(&tcon->num_smbs_sent);
 
-	return rc;
+	return 0;
+}
+
+/* If the return code is zero, this function must fill in request_buf pointer */
+static int
+smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+	 void **request_buf, void **response_buf)
+{
+	int rc;
+
+	rc = cifs_reconnect_tcon(tcon, smb_command);
+	if (rc)
+		return rc;
+
+	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
+}
+
+static int
+smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon,
+			void **request_buf, void **response_buf)
+{
+	if (tcon->ses->need_reconnect || tcon->need_reconnect)
+		return -EHOSTDOWN;
+
+	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
 }
 
 static int validate_t2(struct smb_t2_rsp *pSMB)
@@ -486,7 +503,7 @@
 
 		if (rsp->EncryptionKeyLength ==
 				cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
-			memcpy(server->cryptKey, rsp->EncryptionKey,
+			memcpy(ses->cryptKey, rsp->EncryptionKey,
 				CIFS_CRYPTO_KEY_SIZE);
 		} else if (server->secMode & SECMODE_PW_ENCRYPT) {
 			rc = -EIO; /* need cryptkey unless plain text */
@@ -557,7 +574,7 @@
 	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
 	server->timeAdj *= 60;
 	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
-		memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
+		memcpy(ses->cryptKey, pSMBr->u.EncryptionKey,
 		       CIFS_CRYPTO_KEY_SIZE);
 	} else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
 			&& (pSMBr->EncryptionKeyLength == 0)) {
@@ -576,9 +593,9 @@
 			rc = -EIO;
 			goto neg_err_exit;
 		}
-		read_lock(&cifs_tcp_ses_lock);
+		spin_lock(&cifs_tcp_ses_lock);
 		if (server->srv_count > 1) {
-			read_unlock(&cifs_tcp_ses_lock);
+			spin_unlock(&cifs_tcp_ses_lock);
 			if (memcmp(server->server_GUID,
 				   pSMBr->u.extended_response.
 				   GUID, 16) != 0) {
@@ -588,7 +605,7 @@
 					16);
 			}
 		} else {
-			read_unlock(&cifs_tcp_ses_lock);
+			spin_unlock(&cifs_tcp_ses_lock);
 			memcpy(server->server_GUID,
 			       pSMBr->u.extended_response.GUID, 16);
 		}
@@ -603,13 +620,15 @@
 				rc = 0;
 			else
 				rc = -EINVAL;
-
-			if (server->sec_kerberos || server->sec_mskerberos)
-				server->secType = Kerberos;
-			else if (server->sec_ntlmssp)
-				server->secType = RawNTLMSSP;
-			else
-				rc = -EOPNOTSUPP;
+			if (server->secType == Kerberos) {
+				if (!server->sec_kerberos &&
+						!server->sec_mskerberos)
+					rc = -EOPNOTSUPP;
+			} else if (server->secType == RawNTLMSSP) {
+				if (!server->sec_ntlmssp)
+					rc = -EOPNOTSUPP;
+			} else
+					rc = -EOPNOTSUPP;
 		}
 	} else
 		server->capabilities &= ~CAP_EXTENDED_SECURITY;
@@ -4534,8 +4553,8 @@
 
 	cFYI(1, "In QFSUnixInfo");
 QFSUnixRetry:
-	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-		      (void **) &pSMBr);
+	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
+				   (void **) &pSMB, (void **) &pSMBr);
 	if (rc)
 		return rc;
 
@@ -4604,8 +4623,8 @@
 	cFYI(1, "In SETFSUnixInfo");
 SETFSUnixRetry:
 	/* BB switch to small buf init to save memory */
-	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-		      (void **) &pSMBr);
+	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
+					(void **) &pSMB, (void **) &pSMBr);
 	if (rc)
 		return rc;
 
diff --git a/fs/cifs/cn_cifs.h b/fs/cifs/cn_cifs.h
deleted file mode 100644
index ea59cca..0000000
--- a/fs/cifs/cn_cifs.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *   fs/cifs/cn_cifs.h
- *
- *   Copyright (c) International Business Machines  Corp., 2002
- *   Author(s): Steve French (sfrench@us.ibm.com)
- *
- *   This library is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU Lesser General Public License as published
- *   by the Free Software Foundation; either version 2.1 of the License, or
- *   (at your option) any later version.
- *
- *   This library is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU Lesser General Public License for more details.
- *
- *   You should have received a copy of the GNU Lesser General Public License
- *   along with this library; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _CN_CIFS_H
-#define _CN_CIFS_H
-#ifdef CONFIG_CIFS_UPCALL
-#include <linux/types.h>
-#include <linux/connector.h>
-
-struct cifs_upcall {
-	char signature[4]; /* CIFS */
-	enum command {
-		CIFS_GET_IP = 0x00000001,   /* get ip address for hostname */
-		CIFS_GET_SECBLOB = 0x00000002, /* get SPNEGO wrapped blob */
-	} command;
-	/* union cifs upcall data follows */
-};
-#endif /* CIFS_UPCALL */
-#endif /* _CN_CIFS_H */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 88c84a3..7e73176 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -47,7 +47,6 @@
 #include "ntlmssp.h"
 #include "nterr.h"
 #include "rfc1002pdu.h"
-#include "cn_cifs.h"
 #include "fscache.h"
 
 #define CIFS_PORT 445
@@ -100,16 +99,24 @@
 	bool noautotune:1;
 	bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
 	bool fsc:1;	/* enable fscache */
+	bool mfsymlinks:1; /* use Minshall+French Symlinks */
+	bool multiuser:1;
 	unsigned int rsize;
 	unsigned int wsize;
 	bool sockopt_tcp_nodelay:1;
 	unsigned short int port;
 	char *prepath;
+	struct sockaddr_storage srcaddr; /* allow binding to a local IP */
 	struct nls_table *local_nls;
 };
 
+/* FIXME: should these be tunable? */
+#define TLINK_ERROR_EXPIRE	(1 * HZ)
+#define TLINK_IDLE_EXPIRE	(600 * HZ)
+
 static int ipv4_connect(struct TCP_Server_Info *server);
 static int ipv6_connect(struct TCP_Server_Info *server);
+static void cifs_prune_tlinks(struct work_struct *work);
 
 /*
  * cifs tcp session reconnection
@@ -143,7 +150,7 @@
 
 	/* before reconnecting the tcp session, mark the smb session (uid)
 		and the tid bad so they are not used until reconnected */
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp, &server->smb_ses_list) {
 		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
 		ses->need_reconnect = true;
@@ -153,7 +160,7 @@
 			tcon->need_reconnect = true;
 		}
 	}
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	/* do not want to be sending data on a socket we are freeing */
 	mutex_lock(&server->srv_mutex);
 	if (server->ssocket) {
@@ -166,6 +173,8 @@
 		sock_release(server->ssocket);
 		server->ssocket = NULL;
 	}
+	server->sequence_number = 0;
+	server->session_estab = false;
 
 	spin_lock(&GlobalMid_Lock);
 	list_for_each(tmp, &server->pending_mid_q) {
@@ -198,7 +207,6 @@
 			spin_lock(&GlobalMid_Lock);
 			if (server->tcpStatus != CifsExiting)
 				server->tcpStatus = CifsGood;
-			server->sequence_number = 0;
 			spin_unlock(&GlobalMid_Lock);
 	/*		atomic_set(&server->inFlight,0);*/
 			wake_up(&server->response_q);
@@ -629,9 +637,9 @@
 	} /* end while !EXITING */
 
 	/* take it off the list, if it's not already */
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_del_init(&server->tcp_ses_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	spin_lock(&GlobalMid_Lock);
 	server->tcpStatus = CifsExiting;
@@ -669,7 +677,7 @@
 	 * BB: we shouldn't have to do any of this. It shouldn't be
 	 * possible to exit from the thread with active SMB sessions
 	 */
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if (list_empty(&server->pending_mid_q)) {
 		/* loop through server session structures attached to this and
 		    mark them dead */
@@ -679,7 +687,7 @@
 			ses->status = CifsExiting;
 			ses->server = NULL;
 		}
-		read_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 	} else {
 		/* although we can not zero the server struct pointer yet,
 		since there are active requests which may depnd on them,
@@ -702,7 +710,7 @@
 			}
 		}
 		spin_unlock(&GlobalMid_Lock);
-		read_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		/* 1/8th of sec is more than enough time for them to exit */
 		msleep(125);
 	}
@@ -725,12 +733,12 @@
 	if a crazy root user tried to kill cifsd
 	kernel thread explicitly this might happen) */
 	/* BB: This shouldn't be necessary, see above */
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp, &server->smb_ses_list) {
 		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
 		ses->server = NULL;
 	}
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	kfree(server->hostname);
 	task_to_wake = xchg(&server->tsk, NULL);
@@ -1046,6 +1054,22 @@
 						    "long\n");
 				return 1;
 			}
+		} else if (strnicmp(data, "srcaddr", 7) == 0) {
+			vol->srcaddr.ss_family = AF_UNSPEC;
+
+			if (!value || !*value) {
+				printk(KERN_WARNING "CIFS: srcaddr value"
+				       " not specified.\n");
+				return 1;	/* needs_arg; */
+			}
+			i = cifs_convert_address((struct sockaddr *)&vol->srcaddr,
+						 value, strlen(value));
+			if (i < 0) {
+				printk(KERN_WARNING "CIFS:  Could not parse"
+				       " srcaddr: %s\n",
+				       value);
+				return 1;
+			}
 		} else if (strnicmp(data, "prefixpath", 10) == 0) {
 			if (!value || !*value) {
 				printk(KERN_WARNING
@@ -1325,6 +1349,10 @@
 				"/proc/fs/cifs/LookupCacheEnabled to 0\n");
 		} else if (strnicmp(data, "fsc", 3) == 0) {
 			vol->fsc = true;
+		} else if (strnicmp(data, "mfsymlinks", 10) == 0) {
+			vol->mfsymlinks = true;
+		} else if (strnicmp(data, "multiuser", 8) == 0) {
+			vol->multiuser = true;
 		} else
 			printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
 						data);
@@ -1356,6 +1384,13 @@
 			return 1;
 		}
 	}
+
+	if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) {
+		cERROR(1, "Multiuser mounts currently require krb5 "
+			  "authentication!");
+		return 1;
+	}
+
 	if (vol->UNCip == NULL)
 		vol->UNCip = &vol->UNC[2];
 
@@ -1374,8 +1409,36 @@
 	return 0;
 }
 
+/** Returns true if srcaddr isn't specified and rhs isn't
+ * specified, or if srcaddr is specified and
+ * matches the IP address of the rhs argument.
+ */
 static bool
-match_address(struct TCP_Server_Info *server, struct sockaddr *addr)
+srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
+{
+	switch (srcaddr->sa_family) {
+	case AF_UNSPEC:
+		return (rhs->sa_family == AF_UNSPEC);
+	case AF_INET: {
+		struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
+		struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
+		return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
+	}
+	case AF_INET6: {
+		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
+		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
+		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
+	}
+	default:
+		WARN_ON(1);
+		return false; /* don't expect to be here */
+	}
+}
+
+
+static bool
+match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
+	      struct sockaddr *srcaddr)
 {
 	struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
 	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
@@ -1402,6 +1465,9 @@
 		break;
 	}
 
+	if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
+		return false;
+
 	return true;
 }
 
@@ -1458,29 +1524,21 @@
 {
 	struct TCP_Server_Info *server;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
-		/*
-		 * the demux thread can exit on its own while still in CifsNew
-		 * so don't accept any sockets in that state. Since the
-		 * tcpStatus never changes back to CifsNew it's safe to check
-		 * for this without a lock.
-		 */
-		if (server->tcpStatus == CifsNew)
-			continue;
-
-		if (!match_address(server, addr))
+		if (!match_address(server, addr,
+				   (struct sockaddr *)&vol->srcaddr))
 			continue;
 
 		if (!match_security(server, vol))
 			continue;
 
 		++server->srv_count;
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		cFYI(1, "Existing tcp session with server found");
 		return server;
 	}
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	return NULL;
 }
 
@@ -1489,14 +1547,14 @@
 {
 	struct task_struct *task;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if (--server->srv_count > 0) {
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return;
 	}
 
 	list_del_init(&server->tcp_ses_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	spin_lock(&GlobalMid_Lock);
 	server->tcpStatus = CifsExiting;
@@ -1574,6 +1632,7 @@
 		volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
 	memcpy(tcp_ses->server_RFC1001_name,
 		volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
+	tcp_ses->session_estab = false;
 	tcp_ses->sequence_number = 0;
 	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
 	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
@@ -1584,6 +1643,8 @@
 	 * no need to spinlock this init of tcpStatus or srv_count
 	 */
 	tcp_ses->tcpStatus = CifsNew;
+	memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
+	       sizeof(tcp_ses->srcaddr));
 	++tcp_ses->srv_count;
 
 	if (addr.ss_family == AF_INET6) {
@@ -1618,9 +1679,9 @@
 	}
 
 	/* thread spawned, put it on the list */
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	cifs_fscache_get_client_cookie(tcp_ses);
 
@@ -1642,7 +1703,7 @@
 {
 	struct cifsSesInfo *ses;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
 		switch (server->secType) {
 		case Kerberos:
@@ -1662,10 +1723,10 @@
 				continue;
 		}
 		++ses->ses_count;
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return ses;
 	}
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	return NULL;
 }
 
@@ -1676,14 +1737,14 @@
 	struct TCP_Server_Info *server = ses->server;
 
 	cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if (--ses->ses_count > 0) {
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return;
 	}
 
 	list_del_init(&ses->smb_ses_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	if (ses->status == CifsGood) {
 		xid = GetXid();
@@ -1740,6 +1801,8 @@
 	if (ses == NULL)
 		goto get_ses_fail;
 
+	ses->tilen = 0;
+	ses->tiblob = NULL;
 	/* new SMB session uses our server ref */
 	ses->server = server;
 	if (server->addr.sockAddr6.sin6_family == AF_INET6)
@@ -1778,9 +1841,9 @@
 		goto get_ses_fail;
 
 	/* success, put it on the list */
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_add(&ses->smb_ses_list, &server->smb_ses_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	FreeXid(xid);
 	return ses;
@@ -1797,7 +1860,7 @@
 	struct list_head *tmp;
 	struct cifsTconInfo *tcon;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp, &ses->tcon_list) {
 		tcon = list_entry(tmp, struct cifsTconInfo, tcon_list);
 		if (tcon->tidStatus == CifsExiting)
@@ -1806,10 +1869,10 @@
 			continue;
 
 		++tcon->tc_count;
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return tcon;
 	}
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	return NULL;
 }
 
@@ -1820,14 +1883,14 @@
 	struct cifsSesInfo *ses = tcon->ses;
 
 	cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if (--tcon->tc_count > 0) {
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return;
 	}
 
 	list_del_init(&tcon->tcon_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	xid = GetXid();
 	CIFSSMBTDis(xid, tcon);
@@ -1900,9 +1963,9 @@
 	tcon->nocase = volume_info->nocase;
 	tcon->local_lease = volume_info->local_lease;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_add(&tcon->tcon_list, &ses->tcon_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	cifs_fscache_get_super_cookie(tcon);
 
@@ -1913,6 +1976,23 @@
 	return ERR_PTR(rc);
 }
 
+void
+cifs_put_tlink(struct tcon_link *tlink)
+{
+	if (!tlink || IS_ERR(tlink))
+		return;
+
+	if (!atomic_dec_and_test(&tlink->tl_count) ||
+	    test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
+		tlink->tl_time = jiffies;
+		return;
+	}
+
+	if (!IS_ERR(tlink_tcon(tlink)))
+		cifs_put_tcon(tlink_tcon(tlink));
+	kfree(tlink);
+	return;
+}
 
 int
 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
@@ -1997,6 +2077,33 @@
 
 }
 
+static int
+bind_socket(struct TCP_Server_Info *server)
+{
+	int rc = 0;
+	if (server->srcaddr.ss_family != AF_UNSPEC) {
+		/* Bind to the specified local IP address */
+		struct socket *socket = server->ssocket;
+		rc = socket->ops->bind(socket,
+				       (struct sockaddr *) &server->srcaddr,
+				       sizeof(server->srcaddr));
+		if (rc < 0) {
+			struct sockaddr_in *saddr4;
+			struct sockaddr_in6 *saddr6;
+			saddr4 = (struct sockaddr_in *)&server->srcaddr;
+			saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
+			if (saddr6->sin6_family == AF_INET6)
+				cERROR(1, "cifs: "
+				       "Failed to bind to: %pI6c, error: %d\n",
+				       &saddr6->sin6_addr, rc);
+			else
+				cERROR(1, "cifs: "
+				       "Failed to bind to: %pI4, error: %d\n",
+				       &saddr4->sin_addr.s_addr, rc);
+		}
+	}
+	return rc;
+}
 
 static int
 ipv4_connect(struct TCP_Server_Info *server)
@@ -2022,6 +2129,10 @@
 		cifs_reclassify_socket4(socket);
 	}
 
+	rc = bind_socket(server);
+	if (rc < 0)
+		return rc;
+
 	/* user overrode default port */
 	if (server->addr.sockAddr.sin_port) {
 		rc = socket->ops->connect(socket, (struct sockaddr *)
@@ -2184,6 +2295,10 @@
 		cifs_reclassify_socket6(socket);
 	}
 
+	rc = bind_socket(server);
+	if (rc < 0)
+		return rc;
+
 	/* user overrode default port */
 	if (server->addr.sockAddr6.sin6_port) {
 		rc = socket->ops->connect(socket,
@@ -2383,6 +2498,8 @@
 static void setup_cifs_sb(struct smb_vol *pvolume_info,
 			  struct cifs_sb_info *cifs_sb)
 {
+	INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
+
 	if (pvolume_info->rsize > CIFSMaxBufSize) {
 		cERROR(1, "rsize %d too large, using MaxBufSize",
 			pvolume_info->rsize);
@@ -2462,10 +2579,21 @@
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
 	if (pvolume_info->fsc)
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
+	if (pvolume_info->multiuser)
+		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
+					    CIFS_MOUNT_NO_PERM);
 	if (pvolume_info->direct_io) {
 		cFYI(1, "mounting share using direct i/o");
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
 	}
+	if (pvolume_info->mfsymlinks) {
+		if (pvolume_info->sfu_emul) {
+			cERROR(1,  "mount option mfsymlinks ignored if sfu "
+				   "mount option is used");
+		} else {
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
+		}
+	}
 
 	if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
 		cERROR(1, "mount option dynperm ignored if cifsacl "
@@ -2552,6 +2680,7 @@
 	struct TCP_Server_Info *srvTcp;
 	char   *full_path;
 	char *mount_data = mount_data_global;
+	struct tcon_link *tlink;
 #ifdef CONFIG_CIFS_DFS_UPCALL
 	struct dfs_info3_param *referrals = NULL;
 	unsigned int num_referrals = 0;
@@ -2563,6 +2692,7 @@
 	pSesInfo = NULL;
 	srvTcp = NULL;
 	full_path = NULL;
+	tlink = NULL;
 
 	xid = GetXid();
 
@@ -2638,8 +2768,6 @@
 		goto remote_path_check;
 	}
 
-	cifs_sb->tcon = tcon;
-
 	/* do not care if following two calls succeed - informational */
 	if (!tcon->ipc) {
 		CIFSSMBQFSDeviceInfo(xid, tcon);
@@ -2748,6 +2876,38 @@
 #endif
 	}
 
+	if (rc)
+		goto mount_fail_check;
+
+	/* now, hang the tcon off of the superblock */
+	tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
+	if (tlink == NULL) {
+		rc = -ENOMEM;
+		goto mount_fail_check;
+	}
+
+	tlink->tl_index = pSesInfo->linux_uid;
+	tlink->tl_tcon = tcon;
+	tlink->tl_time = jiffies;
+	set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
+	set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
+
+	rc = radix_tree_preload(GFP_KERNEL);
+	if (rc == -ENOMEM) {
+		kfree(tlink);
+		goto mount_fail_check;
+	}
+
+	spin_lock(&cifs_sb->tlink_tree_lock);
+	radix_tree_insert(&cifs_sb->tlink_tree, pSesInfo->linux_uid, tlink);
+	radix_tree_tag_set(&cifs_sb->tlink_tree, pSesInfo->linux_uid,
+			   CIFS_TLINK_MASTER_TAG);
+	spin_unlock(&cifs_sb->tlink_tree_lock);
+	radix_tree_preload_end();
+
+	queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks,
+				TLINK_IDLE_EXPIRE);
+
 mount_fail_check:
 	/* on error free sesinfo and tcon struct if needed */
 	if (rc) {
@@ -2825,14 +2985,13 @@
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 		if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
 		    (ses->server->secType == LANMAN))
-			calc_lanman_hash(tcon->password, ses->server->cryptKey,
+			calc_lanman_hash(tcon->password, ses->cryptKey,
 					 ses->server->secMode &
 					    SECMODE_PW_ENCRYPT ? true : false,
 					 bcc_ptr);
 		else
 #endif /* CIFS_WEAK_PW_HASH */
-		SMBNTencrypt(tcon->password, ses->server->cryptKey,
-			     bcc_ptr);
+		SMBNTencrypt(tcon->password, ses->cryptKey, bcc_ptr);
 
 		bcc_ptr += CIFS_SESS_KEY_SIZE;
 		if (ses->capabilities & CAP_UNICODE) {
@@ -2934,19 +3093,39 @@
 int
 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
 {
-	int rc = 0;
+	int i, ret;
 	char *tmp;
+	struct tcon_link *tlink[8];
+	unsigned long index = 0;
 
-	if (cifs_sb->tcon)
-		cifs_put_tcon(cifs_sb->tcon);
+	cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
 
-	cifs_sb->tcon = NULL;
+	do {
+		spin_lock(&cifs_sb->tlink_tree_lock);
+		ret = radix_tree_gang_lookup(&cifs_sb->tlink_tree,
+					     (void **)tlink, index,
+					     ARRAY_SIZE(tlink));
+		/* increment index for next pass */
+		if (ret > 0)
+			index = tlink[ret - 1]->tl_index + 1;
+		for (i = 0; i < ret; i++) {
+			cifs_get_tlink(tlink[i]);
+			clear_bit(TCON_LINK_IN_TREE, &tlink[i]->tl_flags);
+			radix_tree_delete(&cifs_sb->tlink_tree,
+							tlink[i]->tl_index);
+		}
+		spin_unlock(&cifs_sb->tlink_tree_lock);
+
+		for (i = 0; i < ret; i++)
+			cifs_put_tlink(tlink[i]);
+	} while (ret != 0);
+
 	tmp = cifs_sb->prepath;
 	cifs_sb->prepathlen = 0;
 	cifs_sb->prepath = NULL;
 	kfree(tmp);
 
-	return rc;
+	return 0;
 }
 
 int cifs_negotiate_protocol(unsigned int xid, struct cifsSesInfo *ses)
@@ -2997,6 +3176,15 @@
 	if (rc) {
 		cERROR(1, "Send error in SessSetup = %d", rc);
 	} else {
+		mutex_lock(&ses->server->srv_mutex);
+		if (!server->session_estab) {
+			memcpy(&server->session_key.data,
+				&ses->auth_key.data, ses->auth_key.len);
+			server->session_key.len = ses->auth_key.len;
+			ses->server->session_estab = true;
+		}
+		mutex_unlock(&server->srv_mutex);
+
 		cFYI(1, "CIFS Session Established successfully");
 		spin_lock(&GlobalMid_Lock);
 		ses->status = CifsGood;
@@ -3007,3 +3195,237 @@
 	return rc;
 }
 
+static struct cifsTconInfo *
+cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
+{
+	struct cifsTconInfo *master_tcon = cifs_sb_master_tcon(cifs_sb);
+	struct cifsSesInfo *ses;
+	struct cifsTconInfo *tcon = NULL;
+	struct smb_vol *vol_info;
+	char username[MAX_USERNAME_SIZE + 1];
+
+	vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
+	if (vol_info == NULL) {
+		tcon = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+	snprintf(username, MAX_USERNAME_SIZE, "krb50x%x", fsuid);
+	vol_info->username = username;
+	vol_info->local_nls = cifs_sb->local_nls;
+	vol_info->linux_uid = fsuid;
+	vol_info->cred_uid = fsuid;
+	vol_info->UNC = master_tcon->treeName;
+	vol_info->retry = master_tcon->retry;
+	vol_info->nocase = master_tcon->nocase;
+	vol_info->local_lease = master_tcon->local_lease;
+	vol_info->no_linux_ext = !master_tcon->unix_ext;
+
+	/* FIXME: allow for other secFlg settings */
+	vol_info->secFlg = CIFSSEC_MUST_KRB5;
+
+	/* get a reference for the same TCP session */
+	spin_lock(&cifs_tcp_ses_lock);
+	++master_tcon->ses->server->srv_count;
+	spin_unlock(&cifs_tcp_ses_lock);
+
+	ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
+	if (IS_ERR(ses)) {
+		tcon = (struct cifsTconInfo *)ses;
+		cifs_put_tcp_session(master_tcon->ses->server);
+		goto out;
+	}
+
+	tcon = cifs_get_tcon(ses, vol_info);
+	if (IS_ERR(tcon)) {
+		cifs_put_smb_ses(ses);
+		goto out;
+	}
+
+	if (ses->capabilities & CAP_UNIX)
+		reset_cifs_unix_caps(0, tcon, NULL, vol_info);
+out:
+	kfree(vol_info);
+
+	return tcon;
+}
+
+static struct tcon_link *
+cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
+{
+	struct tcon_link *tlink;
+	unsigned int ret;
+
+	spin_lock(&cifs_sb->tlink_tree_lock);
+	ret = radix_tree_gang_lookup_tag(&cifs_sb->tlink_tree, (void **)&tlink,
+					0, 1, CIFS_TLINK_MASTER_TAG);
+	spin_unlock(&cifs_sb->tlink_tree_lock);
+
+	/* the master tcon should always be present */
+	if (ret == 0)
+		BUG();
+
+	return tlink;
+}
+
+struct cifsTconInfo *
+cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
+{
+	return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
+}
+
+static int
+cifs_sb_tcon_pending_wait(void *unused)
+{
+	schedule();
+	return signal_pending(current) ? -ERESTARTSYS : 0;
+}
+
+/*
+ * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
+ * current task.
+ *
+ * If the superblock doesn't refer to a multiuser mount, then just return
+ * the master tcon for the mount.
+ *
+ * First, search the radix tree for an existing tcon for this fsuid. If one
+ * exists, then check to see if it's pending construction. If it is then wait
+ * for construction to complete. Once it's no longer pending, check to see if
+ * it failed and either return an error or retry construction, depending on
+ * the timeout.
+ *
+ * If one doesn't exist then insert a new tcon_link struct into the tree and
+ * try to construct a new one.
+ */
+struct tcon_link *
+cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
+{
+	int ret;
+	unsigned long fsuid = (unsigned long) current_fsuid();
+	struct tcon_link *tlink, *newtlink;
+
+	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
+		return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
+
+	spin_lock(&cifs_sb->tlink_tree_lock);
+	tlink = radix_tree_lookup(&cifs_sb->tlink_tree, fsuid);
+	if (tlink)
+		cifs_get_tlink(tlink);
+	spin_unlock(&cifs_sb->tlink_tree_lock);
+
+	if (tlink == NULL) {
+		newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
+		if (newtlink == NULL)
+			return ERR_PTR(-ENOMEM);
+		newtlink->tl_index = fsuid;
+		newtlink->tl_tcon = ERR_PTR(-EACCES);
+		set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
+		set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
+		cifs_get_tlink(newtlink);
+
+		ret = radix_tree_preload(GFP_KERNEL);
+		if (ret != 0) {
+			kfree(newtlink);
+			return ERR_PTR(ret);
+		}
+
+		spin_lock(&cifs_sb->tlink_tree_lock);
+		/* was one inserted after previous search? */
+		tlink = radix_tree_lookup(&cifs_sb->tlink_tree, fsuid);
+		if (tlink) {
+			cifs_get_tlink(tlink);
+			spin_unlock(&cifs_sb->tlink_tree_lock);
+			radix_tree_preload_end();
+			kfree(newtlink);
+			goto wait_for_construction;
+		}
+		ret = radix_tree_insert(&cifs_sb->tlink_tree, fsuid, newtlink);
+		spin_unlock(&cifs_sb->tlink_tree_lock);
+		radix_tree_preload_end();
+		if (ret) {
+			kfree(newtlink);
+			return ERR_PTR(ret);
+		}
+		tlink = newtlink;
+	} else {
+wait_for_construction:
+		ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
+				  cifs_sb_tcon_pending_wait,
+				  TASK_INTERRUPTIBLE);
+		if (ret) {
+			cifs_put_tlink(tlink);
+			return ERR_PTR(ret);
+		}
+
+		/* if it's good, return it */
+		if (!IS_ERR(tlink->tl_tcon))
+			return tlink;
+
+		/* return error if we tried this already recently */
+		if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
+			cifs_put_tlink(tlink);
+			return ERR_PTR(-EACCES);
+		}
+
+		if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
+			goto wait_for_construction;
+	}
+
+	tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
+	clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
+	wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
+
+	if (IS_ERR(tlink->tl_tcon)) {
+		cifs_put_tlink(tlink);
+		return ERR_PTR(-EACCES);
+	}
+
+	return tlink;
+}
+
+/*
+ * periodic workqueue job that scans tcon_tree for a superblock and closes
+ * out tcons.
+ */
+static void
+cifs_prune_tlinks(struct work_struct *work)
+{
+	struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
+						    prune_tlinks.work);
+	struct tcon_link *tlink[8];
+	unsigned long now = jiffies;
+	unsigned long index = 0;
+	int i, ret;
+
+	do {
+		spin_lock(&cifs_sb->tlink_tree_lock);
+		ret = radix_tree_gang_lookup(&cifs_sb->tlink_tree,
+					     (void **)tlink, index,
+					     ARRAY_SIZE(tlink));
+		/* increment index for next pass */
+		if (ret > 0)
+			index = tlink[ret - 1]->tl_index + 1;
+		for (i = 0; i < ret; i++) {
+			if (test_bit(TCON_LINK_MASTER, &tlink[i]->tl_flags) ||
+			    atomic_read(&tlink[i]->tl_count) != 0 ||
+			    time_after(tlink[i]->tl_time + TLINK_IDLE_EXPIRE,
+				       now)) {
+				tlink[i] = NULL;
+				continue;
+			}
+			cifs_get_tlink(tlink[i]);
+			clear_bit(TCON_LINK_IN_TREE, &tlink[i]->tl_flags);
+			radix_tree_delete(&cifs_sb->tlink_tree,
+					  tlink[i]->tl_index);
+		}
+		spin_unlock(&cifs_sb->tlink_tree_lock);
+
+		for (i = 0; i < ret; i++) {
+			if (tlink[i] != NULL)
+				cifs_put_tlink(tlink[i]);
+		}
+	} while (ret != 0);
+
+	queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks,
+				TLINK_IDLE_EXPIRE);
+}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index f9ed075..3840edd 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -54,18 +54,18 @@
 	int dfsplen;
 	char *full_path;
 	char dirsep;
-	struct cifs_sb_info *cifs_sb;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
 	if (direntry == NULL)
 		return NULL;  /* not much we can do if dentry is freed and
 		we need to reopen the file after it was closed implicitly
 		when the server crashed */
 
-	cifs_sb = CIFS_SB(direntry->d_sb);
 	dirsep = CIFS_DIR_SEP(cifs_sb);
 	pplen = cifs_sb->prepathlen;
-	if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
-		dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
+	if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
+		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
 	else
 		dfsplen = 0;
 cifs_bp_rename_retry:
@@ -117,7 +117,7 @@
 	/* BB test paths to Windows with '/' in the midst of prepath */
 
 	if (dfsplen) {
-		strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
+		strncpy(full_path, tcon->treeName, dfsplen);
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
 			int i;
 			for (i = 0; i < dfsplen; i++) {
@@ -130,135 +130,6 @@
 	return full_path;
 }
 
-struct cifsFileInfo *
-cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
-		  struct file *file, struct vfsmount *mnt, unsigned int oflags)
-{
-	int oplock = 0;
-	struct cifsFileInfo *pCifsFile;
-	struct cifsInodeInfo *pCifsInode;
-	struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
-
-	pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
-	if (pCifsFile == NULL)
-		return pCifsFile;
-
-	if (oplockEnabled)
-		oplock = REQ_OPLOCK;
-
-	pCifsFile->netfid = fileHandle;
-	pCifsFile->pid = current->tgid;
-	pCifsFile->pInode = igrab(newinode);
-	pCifsFile->mnt = mnt;
-	pCifsFile->pfile = file;
-	pCifsFile->invalidHandle = false;
-	pCifsFile->closePend = false;
-	mutex_init(&pCifsFile->fh_mutex);
-	mutex_init(&pCifsFile->lock_mutex);
-	INIT_LIST_HEAD(&pCifsFile->llist);
-	atomic_set(&pCifsFile->count, 1);
-	INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
-
-	write_lock(&GlobalSMBSeslock);
-	list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
-	pCifsInode = CIFS_I(newinode);
-	if (pCifsInode) {
-		/* if readable file instance put first in list*/
-		if (oflags & FMODE_READ)
-			list_add(&pCifsFile->flist, &pCifsInode->openFileList);
-		else
-			list_add_tail(&pCifsFile->flist,
-				      &pCifsInode->openFileList);
-
-		if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
-			pCifsInode->clientCanCacheAll = true;
-			pCifsInode->clientCanCacheRead = true;
-			cFYI(1, "Exclusive Oplock inode %p", newinode);
-		} else if ((oplock & 0xF) == OPLOCK_READ)
-				pCifsInode->clientCanCacheRead = true;
-	}
-	write_unlock(&GlobalSMBSeslock);
-
-	file->private_data = pCifsFile;
-
-	return pCifsFile;
-}
-
-int cifs_posix_open(char *full_path, struct inode **pinode,
-			struct super_block *sb, int mode, int oflags,
-			__u32 *poplock, __u16 *pnetfid, int xid)
-{
-	int rc;
-	FILE_UNIX_BASIC_INFO *presp_data;
-	__u32 posix_flags = 0;
-	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-	struct cifs_fattr fattr;
-
-	cFYI(1, "posix open %s", full_path);
-
-	presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
-	if (presp_data == NULL)
-		return -ENOMEM;
-
-/* So far cifs posix extensions can only map the following flags.
-   There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
-   so far we do not seem to need them, and we can treat them as local only */
-	if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
-		(FMODE_READ | FMODE_WRITE))
-		posix_flags = SMB_O_RDWR;
-	else if (oflags & FMODE_READ)
-		posix_flags = SMB_O_RDONLY;
-	else if (oflags & FMODE_WRITE)
-		posix_flags = SMB_O_WRONLY;
-	if (oflags & O_CREAT)
-		posix_flags |= SMB_O_CREAT;
-	if (oflags & O_EXCL)
-		posix_flags |= SMB_O_EXCL;
-	if (oflags & O_TRUNC)
-		posix_flags |= SMB_O_TRUNC;
-	/* be safe and imply O_SYNC for O_DSYNC */
-	if (oflags & O_DSYNC)
-		posix_flags |= SMB_O_SYNC;
-	if (oflags & O_DIRECTORY)
-		posix_flags |= SMB_O_DIRECTORY;
-	if (oflags & O_NOFOLLOW)
-		posix_flags |= SMB_O_NOFOLLOW;
-	if (oflags & O_DIRECT)
-		posix_flags |= SMB_O_DIRECT;
-
-	mode &= ~current_umask();
-	rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
-			pnetfid, presp_data, poplock, full_path,
-			cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
-					CIFS_MOUNT_MAP_SPECIAL_CHR);
-	if (rc)
-		goto posix_open_ret;
-
-	if (presp_data->Type == cpu_to_le32(-1))
-		goto posix_open_ret; /* open ok, caller does qpathinfo */
-
-	if (!pinode)
-		goto posix_open_ret; /* caller does not need info */
-
-	cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
-
-	/* get new inode and set it up */
-	if (*pinode == NULL) {
-		cifs_fill_uniqueid(sb, &fattr);
-		*pinode = cifs_iget(sb, &fattr);
-		if (!*pinode) {
-			rc = -ENOMEM;
-			goto posix_open_ret;
-		}
-	} else {
-		cifs_fattr_to_inode(*pinode, &fattr);
-	}
-
-posix_open_ret:
-	kfree(presp_data);
-	return rc;
-}
-
 static void setup_cifs_dentry(struct cifsTconInfo *tcon,
 			      struct dentry *direntry,
 			      struct inode *newinode)
@@ -291,6 +162,7 @@
 	int desiredAccess = GENERIC_READ | GENERIC_WRITE;
 	__u16 fileHandle;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *tcon;
 	char *full_path = NULL;
 	FILE_ALL_INFO *buf = NULL;
@@ -300,7 +172,20 @@
 	xid = GetXid();
 
 	cifs_sb = CIFS_SB(inode->i_sb);
-	tcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		FreeXid(xid);
+		return PTR_ERR(tlink);
+	}
+	tcon = tlink_tcon(tlink);
+
+	if (oplockEnabled)
+		oplock = REQ_OPLOCK;
+
+	if (nd && (nd->flags & LOOKUP_OPEN))
+		oflags = nd->intent.open.file->f_flags;
+	else
+		oflags = O_RDONLY | O_CREAT;
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
@@ -308,14 +193,6 @@
 		goto cifs_create_out;
 	}
 
-	if (oplockEnabled)
-		oplock = REQ_OPLOCK;
-
-	if (nd && (nd->flags & LOOKUP_OPEN))
-		oflags = nd->intent.open.flags;
-	else
-		oflags = FMODE_READ | SMB_O_CREAT;
-
 	if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
 	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
 			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
@@ -344,9 +221,9 @@
 		/* if the file is going to stay open, then we
 		   need to set the desired access properly */
 		desiredAccess = 0;
-		if (oflags & FMODE_READ)
+		if (OPEN_FMODE(oflags) & FMODE_READ)
 			desiredAccess |= GENERIC_READ; /* is this too little? */
-		if (oflags & FMODE_WRITE)
+		if (OPEN_FMODE(oflags) & FMODE_WRITE)
 			desiredAccess |= GENERIC_WRITE;
 
 		if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
@@ -375,7 +252,7 @@
 	if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
 		create_options |= CREATE_OPTION_READONLY;
 
-	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
+	if (tcon->ses->capabilities & CAP_NT_SMBS)
 		rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
 			 desiredAccess, create_options,
 			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
@@ -467,8 +344,7 @@
 			goto cifs_create_out;
 		}
 
-		pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
-					       nd->path.mnt, oflags);
+		pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock);
 		if (pfile_info == NULL) {
 			fput(filp);
 			CIFSSMBClose(xid, tcon, fileHandle);
@@ -481,6 +357,7 @@
 cifs_create_out:
 	kfree(buf);
 	kfree(full_path);
+	cifs_put_tlink(tlink);
 	FreeXid(xid);
 	return rc;
 }
@@ -491,6 +368,7 @@
 	int rc = -EPERM;
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	char *full_path = NULL;
 	struct inode *newinode = NULL;
@@ -503,10 +381,14 @@
 	if (!old_valid_dev(device_number))
 		return -EINVAL;
 
-	xid = GetXid();
-
 	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+
+	pTcon = tlink_tcon(tlink);
+
+	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
@@ -606,6 +488,7 @@
 	kfree(full_path);
 	kfree(buf);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -619,6 +502,7 @@
 	__u16 fileHandle = 0;
 	bool posix_open = false;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct cifsFileInfo *cfile;
 	struct inode *newInode = NULL;
@@ -633,7 +517,12 @@
 	/* check whether path exists */
 
 	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		FreeXid(xid);
+		return (struct dentry *)tlink;
+	}
+	pTcon = tlink_tcon(tlink);
 
 	/*
 	 * Don't allow the separator character in a path component.
@@ -644,8 +533,8 @@
 		for (i = 0; i < direntry->d_name.len; i++)
 			if (direntry->d_name.name[i] == '\\') {
 				cFYI(1, "Invalid file name");
-				FreeXid(xid);
-				return ERR_PTR(-EINVAL);
+				rc = -EINVAL;
+				goto lookup_out;
 			}
 	}
 
@@ -655,7 +544,8 @@
 	 */
 	if (nd && (nd->flags & LOOKUP_EXCL)) {
 		d_instantiate(direntry, NULL);
-		return NULL;
+		rc = 0;
+		goto lookup_out;
 	}
 
 	/* can not grab the rename sem here since it would
@@ -663,8 +553,8 @@
 	in which we already have the sb rename sem */
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
-		FreeXid(xid);
-		return ERR_PTR(-ENOMEM);
+		rc = -ENOMEM;
+		goto lookup_out;
 	}
 
 	if (direntry->d_inode != NULL) {
@@ -687,11 +577,11 @@
 	if (pTcon->unix_ext) {
 		if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
 		     (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
-		     (nd->intent.open.flags & O_CREAT)) {
+		     (nd->intent.open.file->f_flags & O_CREAT)) {
 			rc = cifs_posix_open(full_path, &newInode,
 					parent_dir_inode->i_sb,
 					nd->intent.open.create_mode,
-					nd->intent.open.flags, &oplock,
+					nd->intent.open.file->f_flags, &oplock,
 					&fileHandle, xid);
 			/*
 			 * The check below works around a bug in POSIX
@@ -727,9 +617,8 @@
 				goto lookup_out;
 			}
 
-			cfile = cifs_new_fileinfo(newInode, fileHandle, filp,
-						  nd->path.mnt,
-						  nd->intent.open.flags);
+			cfile = cifs_new_fileinfo(fileHandle, filp, tlink,
+						  oplock);
 			if (cfile == NULL) {
 				fput(filp);
 				CIFSSMBClose(xid, pTcon, fileHandle);
@@ -759,6 +648,7 @@
 
 lookup_out:
 	kfree(full_path);
+	cifs_put_tlink(tlink);
 	FreeXid(xid);
 	return ERR_PTR(rc);
 }
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index de748c6..8c81e7b 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -60,34 +60,32 @@
 		FILE_READ_DATA);
 }
 
-static inline fmode_t cifs_posix_convert_flags(unsigned int flags)
+static u32 cifs_posix_convert_flags(unsigned int flags)
 {
-	fmode_t posix_flags = 0;
+	u32 posix_flags = 0;
 
 	if ((flags & O_ACCMODE) == O_RDONLY)
-		posix_flags = FMODE_READ;
+		posix_flags = SMB_O_RDONLY;
 	else if ((flags & O_ACCMODE) == O_WRONLY)
-		posix_flags = FMODE_WRITE;
-	else if ((flags & O_ACCMODE) == O_RDWR) {
-		/* GENERIC_ALL is too much permission to request
-		   can cause unnecessary access denied on create */
-		/* return GENERIC_ALL; */
-		posix_flags = FMODE_READ | FMODE_WRITE;
-	}
-	/* can not map O_CREAT or O_EXCL or O_TRUNC flags when
-	   reopening a file.  They had their effect on the original open */
-	if (flags & O_APPEND)
-		posix_flags |= (fmode_t)O_APPEND;
+		posix_flags = SMB_O_WRONLY;
+	else if ((flags & O_ACCMODE) == O_RDWR)
+		posix_flags = SMB_O_RDWR;
+
+	if (flags & O_CREAT)
+		posix_flags |= SMB_O_CREAT;
+	if (flags & O_EXCL)
+		posix_flags |= SMB_O_EXCL;
+	if (flags & O_TRUNC)
+		posix_flags |= SMB_O_TRUNC;
+	/* be safe and imply O_SYNC for O_DSYNC */
 	if (flags & O_DSYNC)
-		posix_flags |= (fmode_t)O_DSYNC;
-	if (flags & __O_SYNC)
-		posix_flags |= (fmode_t)__O_SYNC;
+		posix_flags |= SMB_O_SYNC;
 	if (flags & O_DIRECTORY)
-		posix_flags |= (fmode_t)O_DIRECTORY;
+		posix_flags |= SMB_O_DIRECTORY;
 	if (flags & O_NOFOLLOW)
-		posix_flags |= (fmode_t)O_NOFOLLOW;
+		posix_flags |= SMB_O_NOFOLLOW;
 	if (flags & O_DIRECT)
-		posix_flags |= (fmode_t)O_DIRECT;
+		posix_flags |= SMB_O_DIRECT;
 
 	return posix_flags;
 }
@@ -106,66 +104,8 @@
 		return FILE_OPEN;
 }
 
-/* all arguments to this function must be checked for validity in caller */
-static inline int
-cifs_posix_open_inode_helper(struct inode *inode, struct file *file,
-			     struct cifsInodeInfo *pCifsInode, __u32 oplock,
-			     u16 netfid)
-{
-
-	write_lock(&GlobalSMBSeslock);
-
-	pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
-	if (pCifsInode == NULL) {
-		write_unlock(&GlobalSMBSeslock);
-		return -EINVAL;
-	}
-
-	if (pCifsInode->clientCanCacheRead) {
-		/* we have the inode open somewhere else
-		   no need to discard cache data */
-		goto psx_client_can_cache;
-	}
-
-	/* BB FIXME need to fix this check to move it earlier into posix_open
-	   BB  fIX following section BB FIXME */
-
-	/* if not oplocked, invalidate inode pages if mtime or file
-	   size changed */
-/*	temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
-	if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
-			   (file->f_path.dentry->d_inode->i_size ==
-			    (loff_t)le64_to_cpu(buf->EndOfFile))) {
-		cFYI(1, "inode unchanged on server");
-	} else {
-		if (file->f_path.dentry->d_inode->i_mapping) {
-			rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
-			if (rc != 0)
-				CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
-		}
-		cFYI(1, "invalidating remote inode since open detected it "
-			 "changed");
-		invalidate_remote_inode(file->f_path.dentry->d_inode);
-	} */
-
-psx_client_can_cache:
-	if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
-		pCifsInode->clientCanCacheAll = true;
-		pCifsInode->clientCanCacheRead = true;
-		cFYI(1, "Exclusive Oplock granted on inode %p",
-			 file->f_path.dentry->d_inode);
-	} else if ((oplock & 0xF) == OPLOCK_READ)
-		pCifsInode->clientCanCacheRead = true;
-
-	/* will have to change the unlock if we reenable the
-	   filemap_fdatawrite (which does not seem necessary */
-	write_unlock(&GlobalSMBSeslock);
-	return 0;
-}
-
-/* all arguments to this function must be checked for validity in caller */
 static inline int cifs_open_inode_helper(struct inode *inode,
-	struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
+	struct cifsTconInfo *pTcon, __u32 oplock, FILE_ALL_INFO *buf,
 	char *full_path, int xid)
 {
 	struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
@@ -207,16 +147,175 @@
 		rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
 					 xid, NULL);
 
-	if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+	if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
 		pCifsInode->clientCanCacheAll = true;
 		pCifsInode->clientCanCacheRead = true;
 		cFYI(1, "Exclusive Oplock granted on inode %p", inode);
-	} else if ((*oplock & 0xF) == OPLOCK_READ)
+	} else if ((oplock & 0xF) == OPLOCK_READ)
 		pCifsInode->clientCanCacheRead = true;
 
 	return rc;
 }
 
+int cifs_posix_open(char *full_path, struct inode **pinode,
+			struct super_block *sb, int mode, unsigned int f_flags,
+			__u32 *poplock, __u16 *pnetfid, int xid)
+{
+	int rc;
+	FILE_UNIX_BASIC_INFO *presp_data;
+	__u32 posix_flags = 0;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+	struct cifs_fattr fattr;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *tcon;
+
+	cFYI(1, "posix open %s", full_path);
+
+	presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
+	if (presp_data == NULL)
+		return -ENOMEM;
+
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		goto posix_open_ret;
+	}
+
+	tcon = tlink_tcon(tlink);
+	mode &= ~current_umask();
+
+	posix_flags = cifs_posix_convert_flags(f_flags);
+	rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
+			     poplock, full_path, cifs_sb->local_nls,
+			     cifs_sb->mnt_cifs_flags &
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
+	cifs_put_tlink(tlink);
+
+	if (rc)
+		goto posix_open_ret;
+
+	if (presp_data->Type == cpu_to_le32(-1))
+		goto posix_open_ret; /* open ok, caller does qpathinfo */
+
+	if (!pinode)
+		goto posix_open_ret; /* caller does not need info */
+
+	cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
+
+	/* get new inode and set it up */
+	if (*pinode == NULL) {
+		cifs_fill_uniqueid(sb, &fattr);
+		*pinode = cifs_iget(sb, &fattr);
+		if (!*pinode) {
+			rc = -ENOMEM;
+			goto posix_open_ret;
+		}
+	} else {
+		cifs_fattr_to_inode(*pinode, &fattr);
+	}
+
+posix_open_ret:
+	kfree(presp_data);
+	return rc;
+}
+
+struct cifsFileInfo *
+cifs_new_fileinfo(__u16 fileHandle, struct file *file,
+		  struct tcon_link *tlink, __u32 oplock)
+{
+	struct dentry *dentry = file->f_path.dentry;
+	struct inode *inode = dentry->d_inode;
+	struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
+	struct cifsFileInfo *pCifsFile;
+
+	pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+	if (pCifsFile == NULL)
+		return pCifsFile;
+
+	pCifsFile->netfid = fileHandle;
+	pCifsFile->pid = current->tgid;
+	pCifsFile->uid = current_fsuid();
+	pCifsFile->dentry = dget(dentry);
+	pCifsFile->f_flags = file->f_flags;
+	pCifsFile->invalidHandle = false;
+	pCifsFile->tlink = cifs_get_tlink(tlink);
+	mutex_init(&pCifsFile->fh_mutex);
+	mutex_init(&pCifsFile->lock_mutex);
+	INIT_LIST_HEAD(&pCifsFile->llist);
+	atomic_set(&pCifsFile->count, 1);
+	INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
+
+	spin_lock(&cifs_file_list_lock);
+	list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
+	/* if readable file instance put first in list*/
+	if (file->f_mode & FMODE_READ)
+		list_add(&pCifsFile->flist, &pCifsInode->openFileList);
+	else
+		list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList);
+	spin_unlock(&cifs_file_list_lock);
+
+	if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+		pCifsInode->clientCanCacheAll = true;
+		pCifsInode->clientCanCacheRead = true;
+		cFYI(1, "Exclusive Oplock inode %p", inode);
+	} else if ((oplock & 0xF) == OPLOCK_READ)
+		pCifsInode->clientCanCacheRead = true;
+
+	file->private_data = pCifsFile;
+	return pCifsFile;
+}
+
+/*
+ * Release a reference on the file private data. This may involve closing
+ * the filehandle out on the server.
+ */
+void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
+{
+	struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink);
+	struct cifsInodeInfo *cifsi = CIFS_I(cifs_file->dentry->d_inode);
+	struct cifsLockInfo *li, *tmp;
+
+	spin_lock(&cifs_file_list_lock);
+	if (!atomic_dec_and_test(&cifs_file->count)) {
+		spin_unlock(&cifs_file_list_lock);
+		return;
+	}
+
+	/* remove it from the lists */
+	list_del(&cifs_file->flist);
+	list_del(&cifs_file->tlist);
+
+	if (list_empty(&cifsi->openFileList)) {
+		cFYI(1, "closing last open instance for inode %p",
+			cifs_file->dentry->d_inode);
+		cifsi->clientCanCacheRead = false;
+		cifsi->clientCanCacheAll  = false;
+	}
+	spin_unlock(&cifs_file_list_lock);
+
+	if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
+		int xid, rc;
+
+		xid = GetXid();
+		rc = CIFSSMBClose(xid, tcon, cifs_file->netfid);
+		FreeXid(xid);
+	}
+
+	/* Delete any outstanding lock records. We'll lose them when the file
+	 * is closed anyway.
+	 */
+	mutex_lock(&cifs_file->lock_mutex);
+	list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) {
+		list_del(&li->llist);
+		kfree(li);
+	}
+	mutex_unlock(&cifs_file->lock_mutex);
+
+	cifs_put_tlink(cifs_file->tlink);
+	dput(cifs_file->dentry);
+	kfree(cifs_file);
+}
+
 int cifs_open(struct inode *inode, struct file *file)
 {
 	int rc = -EACCES;
@@ -224,6 +323,7 @@
 	__u32 oplock;
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *tcon;
+	struct tcon_link *tlink;
 	struct cifsFileInfo *pCifsFile = NULL;
 	struct cifsInodeInfo *pCifsInode;
 	char *full_path = NULL;
@@ -235,7 +335,12 @@
 	xid = GetXid();
 
 	cifs_sb = CIFS_SB(inode->i_sb);
-	tcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		FreeXid(xid);
+		return PTR_ERR(tlink);
+	}
+	tcon = tlink_tcon(tlink);
 
 	pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
 
@@ -257,27 +362,15 @@
 	    (tcon->ses->capabilities & CAP_UNIX) &&
 	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
 			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
-		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
-		oflags |= SMB_O_CREAT;
 		/* can not refresh inode info since size could be stale */
 		rc = cifs_posix_open(full_path, &inode, inode->i_sb,
 				cifs_sb->mnt_file_mode /* ignored */,
-				oflags, &oplock, &netfid, xid);
+				file->f_flags, &oplock, &netfid, xid);
 		if (rc == 0) {
 			cFYI(1, "posix open succeeded");
-			/* no need for special case handling of setting mode
-			   on read only files needed here */
 
-			rc = cifs_posix_open_inode_helper(inode, file,
-					pCifsInode, oplock, netfid);
-			if (rc != 0) {
-				CIFSSMBClose(xid, tcon, netfid);
-				goto out;
-			}
-
-			pCifsFile = cifs_new_fileinfo(inode, netfid, file,
-							file->f_path.mnt,
-							oflags);
+			pCifsFile = cifs_new_fileinfo(netfid, file, tlink,
+						      oplock);
 			if (pCifsFile == NULL) {
 				CIFSSMBClose(xid, tcon, netfid);
 				rc = -ENOMEM;
@@ -345,7 +438,7 @@
 		goto out;
 	}
 
-	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
+	if (tcon->ses->capabilities & CAP_NT_SMBS)
 		rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
 			 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
 			 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
@@ -365,12 +458,11 @@
 		goto out;
 	}
 
-	rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid);
+	rc = cifs_open_inode_helper(inode, tcon, oplock, buf, full_path, xid);
 	if (rc != 0)
 		goto out;
 
-	pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
-					file->f_flags);
+	pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
 	if (pCifsFile == NULL) {
 		rc = -ENOMEM;
 		goto out;
@@ -402,6 +494,7 @@
 	kfree(buf);
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -416,14 +509,13 @@
 	return rc;
 }
 
-static int cifs_reopen_file(struct file *file, bool can_flush)
+static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
 {
 	int rc = -EACCES;
 	int xid;
 	__u32 oplock;
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *tcon;
-	struct cifsFileInfo *pCifsFile;
 	struct cifsInodeInfo *pCifsInode;
 	struct inode *inode;
 	char *full_path = NULL;
@@ -431,11 +523,6 @@
 	int disposition = FILE_OPEN;
 	__u16 netfid;
 
-	if (file->private_data)
-		pCifsFile = file->private_data;
-	else
-		return -EBADF;
-
 	xid = GetXid();
 	mutex_lock(&pCifsFile->fh_mutex);
 	if (!pCifsFile->invalidHandle) {
@@ -445,39 +532,24 @@
 		return rc;
 	}
 
-	if (file->f_path.dentry == NULL) {
-		cERROR(1, "no valid name if dentry freed");
-		dump_stack();
-		rc = -EBADF;
-		goto reopen_error_exit;
-	}
-
-	inode = file->f_path.dentry->d_inode;
-	if (inode == NULL) {
-		cERROR(1, "inode not valid");
-		dump_stack();
-		rc = -EBADF;
-		goto reopen_error_exit;
-	}
-
+	inode = pCifsFile->dentry->d_inode;
 	cifs_sb = CIFS_SB(inode->i_sb);
-	tcon = cifs_sb->tcon;
+	tcon = tlink_tcon(pCifsFile->tlink);
 
 /* can not grab rename sem here because various ops, including
    those that already have the rename sem can end up causing writepage
    to get called and if the server was down that means we end up here,
    and we can never tell if the caller already has the rename_sem */
-	full_path = build_path_from_dentry(file->f_path.dentry);
+	full_path = build_path_from_dentry(pCifsFile->dentry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-reopen_error_exit:
 		mutex_unlock(&pCifsFile->fh_mutex);
 		FreeXid(xid);
 		return rc;
 	}
 
 	cFYI(1, "inode = 0x%p file flags 0x%x for %s",
-		 inode, file->f_flags, full_path);
+		 inode, pCifsFile->f_flags, full_path);
 
 	if (oplockEnabled)
 		oplock = REQ_OPLOCK;
@@ -487,8 +559,14 @@
 	if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
 	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
 			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
-		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
-		/* can not refresh inode info since size could be stale */
+
+		/*
+		 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
+		 * original open. Must mask them off for a reopen.
+		 */
+		unsigned int oflags = pCifsFile->f_flags &
+						~(O_CREAT | O_EXCL | O_TRUNC);
+
 		rc = cifs_posix_open(full_path, NULL, inode->i_sb,
 				cifs_sb->mnt_file_mode /* ignored */,
 				oflags, &oplock, &netfid, xid);
@@ -500,7 +578,7 @@
 		   in the reconnect path it is important to retry hard */
 	}
 
-	desiredAccess = cifs_convert_flags(file->f_flags);
+	desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
 
 	/* Can not refresh inode by passing in file_info buf to be returned
 	   by SMBOpen and then calling get_inode_info with returned buf
@@ -516,49 +594,50 @@
 		mutex_unlock(&pCifsFile->fh_mutex);
 		cFYI(1, "cifs_open returned 0x%x", rc);
 		cFYI(1, "oplock: %d", oplock);
-	} else {
-reopen_success:
-		pCifsFile->netfid = netfid;
-		pCifsFile->invalidHandle = false;
-		mutex_unlock(&pCifsFile->fh_mutex);
-		pCifsInode = CIFS_I(inode);
-		if (pCifsInode) {
-			if (can_flush) {
-				rc = filemap_write_and_wait(inode->i_mapping);
-				if (rc != 0)
-					CIFS_I(inode)->write_behind_rc = rc;
-			/* temporarily disable caching while we
-			   go to server to get inode info */
-				pCifsInode->clientCanCacheAll = false;
-				pCifsInode->clientCanCacheRead = false;
-				if (tcon->unix_ext)
-					rc = cifs_get_inode_info_unix(&inode,
-						full_path, inode->i_sb, xid);
-				else
-					rc = cifs_get_inode_info(&inode,
-						full_path, NULL, inode->i_sb,
-						xid, NULL);
-			} /* else we are writing out data to server already
-			     and could deadlock if we tried to flush data, and
-			     since we do not know if we have data that would
-			     invalidate the current end of file on the server
-			     we can not go to the server to get the new inod
-			     info */
-			if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
-				pCifsInode->clientCanCacheAll = true;
-				pCifsInode->clientCanCacheRead = true;
-				cFYI(1, "Exclusive Oplock granted on inode %p",
-					 file->f_path.dentry->d_inode);
-			} else if ((oplock & 0xF) == OPLOCK_READ) {
-				pCifsInode->clientCanCacheRead = true;
-				pCifsInode->clientCanCacheAll = false;
-			} else {
-				pCifsInode->clientCanCacheRead = false;
-				pCifsInode->clientCanCacheAll = false;
-			}
-			cifs_relock_file(pCifsFile);
-		}
+		goto reopen_error_exit;
 	}
+
+reopen_success:
+	pCifsFile->netfid = netfid;
+	pCifsFile->invalidHandle = false;
+	mutex_unlock(&pCifsFile->fh_mutex);
+	pCifsInode = CIFS_I(inode);
+
+	if (can_flush) {
+		rc = filemap_write_and_wait(inode->i_mapping);
+		if (rc != 0)
+			CIFS_I(inode)->write_behind_rc = rc;
+
+		pCifsInode->clientCanCacheAll = false;
+		pCifsInode->clientCanCacheRead = false;
+		if (tcon->unix_ext)
+			rc = cifs_get_inode_info_unix(&inode,
+				full_path, inode->i_sb, xid);
+		else
+			rc = cifs_get_inode_info(&inode,
+				full_path, NULL, inode->i_sb,
+				xid, NULL);
+	} /* else we are writing out data to server already
+	     and could deadlock if we tried to flush data, and
+	     since we do not know if we have data that would
+	     invalidate the current end of file on the server
+	     we can not go to the server to get the new inod
+	     info */
+	if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+		pCifsInode->clientCanCacheAll = true;
+		pCifsInode->clientCanCacheRead = true;
+		cFYI(1, "Exclusive Oplock granted on inode %p",
+			 pCifsFile->dentry->d_inode);
+	} else if ((oplock & 0xF) == OPLOCK_READ) {
+		pCifsInode->clientCanCacheRead = true;
+		pCifsInode->clientCanCacheAll = false;
+	} else {
+		pCifsInode->clientCanCacheRead = false;
+		pCifsInode->clientCanCacheAll = false;
+	}
+	cifs_relock_file(pCifsFile);
+
+reopen_error_exit:
 	kfree(full_path);
 	FreeXid(xid);
 	return rc;
@@ -566,79 +645,11 @@
 
 int cifs_close(struct inode *inode, struct file *file)
 {
-	int rc = 0;
-	int xid, timeout;
-	struct cifs_sb_info *cifs_sb;
-	struct cifsTconInfo *pTcon;
-	struct cifsFileInfo *pSMBFile = file->private_data;
+	cifsFileInfo_put(file->private_data);
+	file->private_data = NULL;
 
-	xid = GetXid();
-
-	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
-	if (pSMBFile) {
-		struct cifsLockInfo *li, *tmp;
-		write_lock(&GlobalSMBSeslock);
-		pSMBFile->closePend = true;
-		if (pTcon) {
-			/* no sense reconnecting to close a file that is
-			   already closed */
-			if (!pTcon->need_reconnect) {
-				write_unlock(&GlobalSMBSeslock);
-				timeout = 2;
-				while ((atomic_read(&pSMBFile->count) != 1)
-					&& (timeout <= 2048)) {
-					/* Give write a better chance to get to
-					server ahead of the close.  We do not
-					want to add a wait_q here as it would
-					increase the memory utilization as
-					the struct would be in each open file,
-					but this should give enough time to
-					clear the socket */
-					cFYI(DBG2, "close delay, write pending");
-					msleep(timeout);
-					timeout *= 4;
-				}
-				if (!pTcon->need_reconnect &&
-				    !pSMBFile->invalidHandle)
-					rc = CIFSSMBClose(xid, pTcon,
-						  pSMBFile->netfid);
-			} else
-				write_unlock(&GlobalSMBSeslock);
-		} else
-			write_unlock(&GlobalSMBSeslock);
-
-		/* Delete any outstanding lock records.
-		   We'll lose them when the file is closed anyway. */
-		mutex_lock(&pSMBFile->lock_mutex);
-		list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
-			list_del(&li->llist);
-			kfree(li);
-		}
-		mutex_unlock(&pSMBFile->lock_mutex);
-
-		write_lock(&GlobalSMBSeslock);
-		list_del(&pSMBFile->flist);
-		list_del(&pSMBFile->tlist);
-		write_unlock(&GlobalSMBSeslock);
-		cifsFileInfo_put(file->private_data);
-		file->private_data = NULL;
-	} else
-		rc = -EBADF;
-
-	read_lock(&GlobalSMBSeslock);
-	if (list_empty(&(CIFS_I(inode)->openFileList))) {
-		cFYI(1, "closing last open instance for inode %p", inode);
-		/* if the file is not open we do not know if we can cache info
-		   on this inode, much less write behind and read ahead */
-		CIFS_I(inode)->clientCanCacheRead = false;
-		CIFS_I(inode)->clientCanCacheAll  = false;
-	}
-	read_unlock(&GlobalSMBSeslock);
-	if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
-		rc = CIFS_I(inode)->write_behind_rc;
-	FreeXid(xid);
-	return rc;
+	/* return code from the ->release op is always ignored */
+	return 0;
 }
 
 int cifs_closedir(struct inode *inode, struct file *file)
@@ -653,25 +664,21 @@
 	xid = GetXid();
 
 	if (pCFileStruct) {
-		struct cifsTconInfo *pTcon;
-		struct cifs_sb_info *cifs_sb =
-			CIFS_SB(file->f_path.dentry->d_sb);
-
-		pTcon = cifs_sb->tcon;
+		struct cifsTconInfo *pTcon = tlink_tcon(pCFileStruct->tlink);
 
 		cFYI(1, "Freeing private data in close dir");
-		write_lock(&GlobalSMBSeslock);
+		spin_lock(&cifs_file_list_lock);
 		if (!pCFileStruct->srch_inf.endOfSearch &&
 		    !pCFileStruct->invalidHandle) {
 			pCFileStruct->invalidHandle = true;
-			write_unlock(&GlobalSMBSeslock);
+			spin_unlock(&cifs_file_list_lock);
 			rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
 			cFYI(1, "Closing uncompleted readdir with rc %d",
 				 rc);
 			/* not much we can do if it fails anyway, ignore rc */
 			rc = 0;
 		} else
-			write_unlock(&GlobalSMBSeslock);
+			spin_unlock(&cifs_file_list_lock);
 		ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
 		if (ptmp) {
 			cFYI(1, "closedir free smb buf in srch struct");
@@ -681,6 +688,7 @@
 			else
 				cifs_buf_release(ptmp);
 		}
+		cifs_put_tlink(pCFileStruct->tlink);
 		kfree(file->private_data);
 		file->private_data = NULL;
 	}
@@ -767,7 +775,7 @@
 		cFYI(1, "Unknown type of lock");
 
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	tcon = cifs_sb->tcon;
+	tcon = tlink_tcon(((struct cifsFileInfo *)file->private_data)->tlink);
 
 	if (file->private_data == NULL) {
 		rc = -EBADF;
@@ -960,14 +968,14 @@
 
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
 
-	pTcon = cifs_sb->tcon;
-
 	/* cFYI(1, " write %d bytes to offset %lld of %s", write_size,
 	   *poffset, file->f_path.dentry->d_name.name); */
 
 	if (file->private_data == NULL)
 		return -EBADF;
+
 	open_file = file->private_data;
+	pTcon = tlink_tcon(open_file->tlink);
 
 	rc = generic_write_checks(file, poffset, &write_size, 0);
 	if (rc)
@@ -988,19 +996,12 @@
 			   we blocked so return what we managed to write */
 				return total_written;
 			}
-			if (open_file->closePend) {
-				FreeXid(xid);
-				if (total_written)
-					return total_written;
-				else
-					return -EBADF;
-			}
 			if (open_file->invalidHandle) {
 				/* we could deadlock if we called
 				   filemap_fdatawait from here so tell
 				   reopen_file not to flush data to server
 				   now */
-				rc = cifs_reopen_file(file, false);
+				rc = cifs_reopen_file(open_file, false);
 				if (rc != 0)
 					break;
 			}
@@ -1048,8 +1049,9 @@
 	return total_written;
 }
 
-static ssize_t cifs_write(struct file *file, const char *write_data,
-			  size_t write_size, loff_t *poffset)
+static ssize_t cifs_write(struct cifsFileInfo *open_file,
+			  const char *write_data, size_t write_size,
+			  loff_t *poffset)
 {
 	int rc = 0;
 	unsigned int bytes_written = 0;
@@ -1057,19 +1059,15 @@
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
 	int xid, long_op;
-	struct cifsFileInfo *open_file;
-	struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);
+	struct dentry *dentry = open_file->dentry;
+	struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
 
-	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-
-	pTcon = cifs_sb->tcon;
+	cifs_sb = CIFS_SB(dentry->d_sb);
 
 	cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
-	   *poffset, file->f_path.dentry->d_name.name);
+	   *poffset, dentry->d_name.name);
 
-	if (file->private_data == NULL)
-		return -EBADF;
-	open_file = file->private_data;
+	pTcon = tlink_tcon(open_file->tlink);
 
 	xid = GetXid();
 
@@ -1078,28 +1076,12 @@
 	     total_written += bytes_written) {
 		rc = -EAGAIN;
 		while (rc == -EAGAIN) {
-			if (file->private_data == NULL) {
-				/* file has been closed on us */
-				FreeXid(xid);
-			/* if we have gotten here we have written some data
-			   and blocked, and the file has been freed on us
-			   while we blocked so return what we managed to
-			   write */
-				return total_written;
-			}
-			if (open_file->closePend) {
-				FreeXid(xid);
-				if (total_written)
-					return total_written;
-				else
-					return -EBADF;
-			}
 			if (open_file->invalidHandle) {
 				/* we could deadlock if we called
 				   filemap_fdatawait from here so tell
 				   reopen_file not to flush data to
 				   server now */
-				rc = cifs_reopen_file(file, false);
+				rc = cifs_reopen_file(open_file, false);
 				if (rc != 0)
 					break;
 			}
@@ -1146,43 +1128,41 @@
 
 	cifs_stats_bytes_written(pTcon, total_written);
 
-	/* since the write may have blocked check these pointers again */
-	if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) {
-/*BB We could make this contingent on superblock ATIME flag too */
-/*		file->f_path.dentry->d_inode->i_ctime =
-		file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/
-		if (total_written > 0) {
-			spin_lock(&file->f_path.dentry->d_inode->i_lock);
-			if (*poffset > file->f_path.dentry->d_inode->i_size)
-				i_size_write(file->f_path.dentry->d_inode,
-					     *poffset);
-			spin_unlock(&file->f_path.dentry->d_inode->i_lock);
-		}
-		mark_inode_dirty_sync(file->f_path.dentry->d_inode);
+	if (total_written > 0) {
+		spin_lock(&dentry->d_inode->i_lock);
+		if (*poffset > dentry->d_inode->i_size)
+			i_size_write(dentry->d_inode, *poffset);
+		spin_unlock(&dentry->d_inode->i_lock);
 	}
+	mark_inode_dirty_sync(dentry->d_inode);
 	FreeXid(xid);
 	return total_written;
 }
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
+struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
+					bool fsuid_only)
 {
 	struct cifsFileInfo *open_file = NULL;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
 
-	read_lock(&GlobalSMBSeslock);
+	/* only filter by fsuid on multiuser mounts */
+	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
+		fsuid_only = false;
+
+	spin_lock(&cifs_file_list_lock);
 	/* we could simply get the first_list_entry since write-only entries
 	   are always at the end of the list but since the first entry might
 	   have a close pending, we go through the whole list */
 	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
-		if (open_file->closePend)
+		if (fsuid_only && open_file->uid != current_fsuid())
 			continue;
-		if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
-		    (open_file->pfile->f_flags & O_RDONLY))) {
+		if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
 			if (!open_file->invalidHandle) {
 				/* found a good file */
 				/* lock it so it will not be closed on us */
 				cifsFileInfo_get(open_file);
-				read_unlock(&GlobalSMBSeslock);
+				spin_unlock(&cifs_file_list_lock);
 				return open_file;
 			} /* else might as well continue, and look for
 			     another, or simply have the caller reopen it
@@ -1190,14 +1170,16 @@
 		} else /* write only file */
 			break; /* write only files are last so must be done */
 	}
-	read_unlock(&GlobalSMBSeslock);
+	spin_unlock(&cifs_file_list_lock);
 	return NULL;
 }
 #endif
 
-struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
+struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
+					bool fsuid_only)
 {
 	struct cifsFileInfo *open_file;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
 	bool any_available = false;
 	int rc;
 
@@ -1211,53 +1193,39 @@
 		return NULL;
 	}
 
-	read_lock(&GlobalSMBSeslock);
+	/* only filter by fsuid on multiuser mounts */
+	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
+		fsuid_only = false;
+
+	spin_lock(&cifs_file_list_lock);
 refind_writable:
 	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
-		if (open_file->closePend ||
-		    (!any_available && open_file->pid != current->tgid))
+		if (!any_available && open_file->pid != current->tgid)
 			continue;
-
-		if (open_file->pfile &&
-		    ((open_file->pfile->f_flags & O_RDWR) ||
-		     (open_file->pfile->f_flags & O_WRONLY))) {
+		if (fsuid_only && open_file->uid != current_fsuid())
+			continue;
+		if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
 			cifsFileInfo_get(open_file);
 
 			if (!open_file->invalidHandle) {
 				/* found a good writable file */
-				read_unlock(&GlobalSMBSeslock);
+				spin_unlock(&cifs_file_list_lock);
 				return open_file;
 			}
 
-			read_unlock(&GlobalSMBSeslock);
-			/* Had to unlock since following call can block */
-			rc = cifs_reopen_file(open_file->pfile, false);
-			if (!rc) {
-				if (!open_file->closePend)
-					return open_file;
-				else { /* start over in case this was deleted */
-				       /* since the list could be modified */
-					read_lock(&GlobalSMBSeslock);
-					cifsFileInfo_put(open_file);
-					goto refind_writable;
-				}
-			}
+			spin_unlock(&cifs_file_list_lock);
 
-			/* if it fails, try another handle if possible -
-			(we can not do this if closePending since
-			loop could be modified - in which case we
-			have to start at the beginning of the list
-			again. Note that it would be bad
-			to hold up writepages here (rather than
-			in caller) with continuous retries */
+			/* Had to unlock since following call can block */
+			rc = cifs_reopen_file(open_file, false);
+			if (!rc)
+				return open_file;
+
+			/* if it fails, try another handle if possible */
 			cFYI(1, "wp failed on reopen file");
-			read_lock(&GlobalSMBSeslock);
-			/* can not use this handle, no write
-			   pending on this one after all */
 			cifsFileInfo_put(open_file);
 
-			if (open_file->closePend) /* list could have changed */
-				goto refind_writable;
+			spin_lock(&cifs_file_list_lock);
+
 			/* else we simply continue to the next entry. Thus
 			   we do not loop on reopen errors.  If we
 			   can not reopen the file, for example if we
@@ -1272,7 +1240,7 @@
 		any_available = true;
 		goto refind_writable;
 	}
-	read_unlock(&GlobalSMBSeslock);
+	spin_unlock(&cifs_file_list_lock);
 	return NULL;
 }
 
@@ -1284,7 +1252,6 @@
 	int rc = -EFAULT;
 	int bytes_written = 0;
 	struct cifs_sb_info *cifs_sb;
-	struct cifsTconInfo *pTcon;
 	struct inode *inode;
 	struct cifsFileInfo *open_file;
 
@@ -1293,7 +1260,6 @@
 
 	inode = page->mapping->host;
 	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
 
 	offset += (loff_t)from;
 	write_data = kmap(page);
@@ -1314,10 +1280,10 @@
 	if (mapping->host->i_size - offset < (loff_t)to)
 		to = (unsigned)(mapping->host->i_size - offset);
 
-	open_file = find_writable_file(CIFS_I(mapping->host));
+	open_file = find_writable_file(CIFS_I(mapping->host), false);
 	if (open_file) {
-		bytes_written = cifs_write(open_file->pfile, write_data,
-					   to-from, &offset);
+		bytes_written = cifs_write(open_file, write_data,
+					   to - from, &offset);
 		cifsFileInfo_put(open_file);
 		/* Does mm or vfs already set times? */
 		inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
@@ -1352,6 +1318,7 @@
 	int nr_pages;
 	__u64 offset = 0;
 	struct cifsFileInfo *open_file;
+	struct cifsTconInfo *tcon;
 	struct cifsInodeInfo *cifsi = CIFS_I(mapping->host);
 	struct page *page;
 	struct pagevec pvec;
@@ -1359,6 +1326,15 @@
 	int scanned = 0;
 	int xid, long_op;
 
+	/*
+	 * BB: Is this meaningful for a non-block-device file system?
+	 * If it is, we should test it again after we do I/O
+	 */
+	if (wbc->nonblocking && bdi_write_congested(bdi)) {
+		wbc->encountered_congestion = 1;
+		return 0;
+	}
+
 	cifs_sb = CIFS_SB(mapping->host->i_sb);
 
 	/*
@@ -1368,27 +1344,29 @@
 	if (cifs_sb->wsize < PAGE_CACHE_SIZE)
 		return generic_writepages(mapping, wbc);
 
-	if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
-		if (cifs_sb->tcon->ses->server->secMode &
-				(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-			if (!experimEnabled)
-				return generic_writepages(mapping, wbc);
-
 	iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
 	if (iov == NULL)
 		return generic_writepages(mapping, wbc);
 
-
 	/*
-	 * BB: Is this meaningful for a non-block-device file system?
-	 * If it is, we should test it again after we do I/O
+	 * if there's no open file, then this is likely to fail too,
+	 * but it'll at least handle the return. Maybe it should be
+	 * a BUG() instead?
 	 */
-	if (wbc->nonblocking && bdi_write_congested(bdi)) {
-		wbc->encountered_congestion = 1;
+	open_file = find_writable_file(CIFS_I(mapping->host), false);
+	if (!open_file) {
 		kfree(iov);
-		return 0;
+		return generic_writepages(mapping, wbc);
 	}
 
+	tcon = tlink_tcon(open_file->tlink);
+	if (!experimEnabled && tcon->ses->server->secMode &
+			(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
+		cifsFileInfo_put(open_file);
+		return generic_writepages(mapping, wbc);
+	}
+	cifsFileInfo_put(open_file);
+
 	xid = GetXid();
 
 	pagevec_init(&pvec, 0);
@@ -1492,38 +1470,34 @@
 				break;
 		}
 		if (n_iov) {
-			/* Search for a writable handle every time we call
-			 * CIFSSMBWrite2.  We can't rely on the last handle
-			 * we used to still be valid
-			 */
-			open_file = find_writable_file(CIFS_I(mapping->host));
+			open_file = find_writable_file(CIFS_I(mapping->host),
+							false);
 			if (!open_file) {
 				cERROR(1, "No writable handles for inode");
 				rc = -EBADF;
 			} else {
 				long_op = cifs_write_timeout(cifsi, offset);
-				rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
-						   open_file->netfid,
+				rc = CIFSSMBWrite2(xid, tcon, open_file->netfid,
 						   bytes_to_write, offset,
 						   &bytes_written, iov, n_iov,
 						   long_op);
 				cifsFileInfo_put(open_file);
 				cifs_update_eof(cifsi, offset, bytes_written);
-
-				if (rc || bytes_written < bytes_to_write) {
-					cERROR(1, "Write2 ret %d, wrote %d",
-						  rc, bytes_written);
-					/* BB what if continued retry is
-					   requested via mount flags? */
-					if (rc == -ENOSPC)
-						set_bit(AS_ENOSPC, &mapping->flags);
-					else
-						set_bit(AS_EIO, &mapping->flags);
-				} else {
-					cifs_stats_bytes_written(cifs_sb->tcon,
-								 bytes_written);
-				}
 			}
+
+			if (rc || bytes_written < bytes_to_write) {
+				cERROR(1, "Write2 ret %d, wrote %d",
+					  rc, bytes_written);
+				/* BB what if continued retry is
+				   requested via mount flags? */
+				if (rc == -ENOSPC)
+					set_bit(AS_ENOSPC, &mapping->flags);
+				else
+					set_bit(AS_EIO, &mapping->flags);
+			} else {
+				cifs_stats_bytes_written(tcon, bytes_written);
+			}
+
 			for (i = 0; i < n_iov; i++) {
 				page = pvec.pages[first + i];
 				/* Should we also set page error on
@@ -1624,7 +1598,8 @@
 		/* BB check if anything else missing out of ppw
 		   such as updating last write time */
 		page_data = kmap(page);
-		rc = cifs_write(file, page_data + offset, copied, &pos);
+		rc = cifs_write(file->private_data, page_data + offset,
+				copied, &pos);
 		/* if (rc < 0) should we set writebehind rc? */
 		kunmap(page);
 
@@ -1665,7 +1640,7 @@
 	if (rc == 0) {
 		rc = CIFS_I(inode)->write_behind_rc;
 		CIFS_I(inode)->write_behind_rc = 0;
-		tcon = CIFS_SB(inode->i_sb)->tcon;
+		tcon = tlink_tcon(smbfile->tlink);
 		if (!rc && tcon && smbfile &&
 		   !(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
 			rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
@@ -1750,7 +1725,6 @@
 
 	xid = GetXid();
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	pTcon = cifs_sb->tcon;
 
 	if (file->private_data == NULL) {
 		rc = -EBADF;
@@ -1758,6 +1732,7 @@
 		return rc;
 	}
 	open_file = file->private_data;
+	pTcon = tlink_tcon(open_file->tlink);
 
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 		cFYI(1, "attempting read on write only file instance");
@@ -1771,9 +1746,8 @@
 		smb_read_data = NULL;
 		while (rc == -EAGAIN) {
 			int buf_type = CIFS_NO_BUFFER;
-			if ((open_file->invalidHandle) &&
-			    (!open_file->closePend)) {
-				rc = cifs_reopen_file(file, true);
+			if (open_file->invalidHandle) {
+				rc = cifs_reopen_file(open_file, true);
 				if (rc != 0)
 					break;
 			}
@@ -1831,7 +1805,6 @@
 
 	xid = GetXid();
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	pTcon = cifs_sb->tcon;
 
 	if (file->private_data == NULL) {
 		rc = -EBADF;
@@ -1839,6 +1812,7 @@
 		return rc;
 	}
 	open_file = file->private_data;
+	pTcon = tlink_tcon(open_file->tlink);
 
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 		cFYI(1, "attempting read on write only file instance");
@@ -1857,9 +1831,8 @@
 		}
 		rc = -EAGAIN;
 		while (rc == -EAGAIN) {
-			if ((open_file->invalidHandle) &&
-			    (!open_file->closePend)) {
-				rc = cifs_reopen_file(file, true);
+			if (open_file->invalidHandle) {
+				rc = cifs_reopen_file(open_file, true);
 				if (rc != 0)
 					break;
 			}
@@ -1974,7 +1947,7 @@
 	}
 	open_file = file->private_data;
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	pTcon = cifs_sb->tcon;
+	pTcon = tlink_tcon(open_file->tlink);
 
 	/*
 	 * Reads as many pages as possible from fscache. Returns -ENOBUFS
@@ -2022,9 +1995,8 @@
 				read_size, contig_pages);
 		rc = -EAGAIN;
 		while (rc == -EAGAIN) {
-			if ((open_file->invalidHandle) &&
-			    (!open_file->closePend)) {
-				rc = cifs_reopen_file(file, true);
+			if (open_file->invalidHandle) {
+				rc = cifs_reopen_file(open_file, true);
 				if (rc != 0)
 					break;
 			}
@@ -2173,18 +2145,14 @@
 {
 	struct cifsFileInfo *open_file;
 
-	read_lock(&GlobalSMBSeslock);
+	spin_lock(&cifs_file_list_lock);
 	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
-		if (open_file->closePend)
-			continue;
-		if (open_file->pfile &&
-		    ((open_file->pfile->f_flags & O_RDWR) ||
-		     (open_file->pfile->f_flags & O_WRONLY))) {
-			read_unlock(&GlobalSMBSeslock);
+		if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
+			spin_unlock(&cifs_file_list_lock);
 			return 1;
 		}
 	}
-	read_unlock(&GlobalSMBSeslock);
+	spin_unlock(&cifs_file_list_lock);
 	return 0;
 }
 
@@ -2310,9 +2278,8 @@
 {
 	struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
 						  oplock_break);
-	struct inode *inode = cfile->pInode;
+	struct inode *inode = cfile->dentry->d_inode;
 	struct cifsInodeInfo *cinode = CIFS_I(inode);
-	struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->mnt->mnt_sb);
 	int rc, waitrc = 0;
 
 	if (inode && S_ISREG(inode->i_mode)) {
@@ -2338,9 +2305,9 @@
 	 * not bother sending an oplock release if session to server still is
 	 * disconnected since oplock already released by the server
 	 */
-	if (!cfile->closePend && !cfile->oplock_break_cancelled) {
-		rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0,
-				 LOCKING_ANDX_OPLOCK_RELEASE, false);
+	if (!cfile->oplock_break_cancelled) {
+		rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0,
+				 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false);
 		cFYI(1, "Oplock release rc = %d", rc);
 	}
 
@@ -2349,22 +2316,22 @@
 	 * finished grabbing reference for us.  Make sure it's done by
 	 * waiting for GlobalSMSSeslock.
 	 */
-	write_lock(&GlobalSMBSeslock);
-	write_unlock(&GlobalSMBSeslock);
+	spin_lock(&cifs_file_list_lock);
+	spin_unlock(&cifs_file_list_lock);
 
 	cifs_oplock_break_put(cfile);
 }
 
 void cifs_oplock_break_get(struct cifsFileInfo *cfile)
 {
-	mntget(cfile->mnt);
+	cifs_sb_active(cfile->dentry->d_sb);
 	cifsFileInfo_get(cfile);
 }
 
 void cifs_oplock_break_put(struct cifsFileInfo *cfile)
 {
-	mntput(cfile->mnt);
 	cifsFileInfo_put(cfile);
+	cifs_sb_deactive(cfile->dentry->d_sb);
 }
 
 const struct address_space_operations cifs_addr_ops = {
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index 9f3f5c4..a2ad94e 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -62,15 +62,15 @@
 {
 	struct cifsInodeInfo *cifsi = CIFS_I(inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
 	if (cifsi->fscache)
 		return;
 
-	cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
-				&cifs_fscache_inode_object_def,
-				cifsi);
-	cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)",
-			cifs_sb->tcon->fscache, cifsi->fscache);
+	cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
+				&cifs_fscache_inode_object_def, cifsi);
+	cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache,
+				cifsi->fscache);
 }
 
 void cifs_fscache_release_inode_cookie(struct inode *inode)
@@ -117,7 +117,8 @@
 		/* retire the current fscache cache and get a new one */
 		fscache_relinquish_cookie(cifsi->fscache, 1);
 
-		cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
+		cifsi->fscache = fscache_acquire_cookie(
+					cifs_sb_master_tcon(cifs_sb)->fscache,
 					&cifs_fscache_inode_object_def,
 					cifsi);
 		cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p",
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 93f77d4..9497930 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -52,7 +52,7 @@
 
 
 		/* check if server can support readpages */
-		if (cifs_sb->tcon->ses->server->maxBuf <
+		if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
 				PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
 			inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
 		else
@@ -288,8 +288,8 @@
 	struct cifs_fattr fattr;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
 	struct cifsFileInfo *cfile = filp->private_data;
+	struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink);
 
 	xid = GetXid();
 	rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data);
@@ -313,15 +313,21 @@
 	FILE_UNIX_BASIC_INFO find_data;
 	struct cifs_fattr fattr;
 	struct cifsTconInfo *tcon;
+	struct tcon_link *tlink;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 
-	tcon = cifs_sb->tcon;
 	cFYI(1, "Getting info on %s", full_path);
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
+
 	/* could have done a find first instead but this returns more info */
 	rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
 				  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
+	cifs_put_tlink(tlink);
 
 	if (!rc) {
 		cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
@@ -332,6 +338,13 @@
 		return rc;
 	}
 
+	/* check for Minshall+French symlinks */
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
+		int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+		if (tmprc)
+			cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
+	}
+
 	if (*pinode == NULL) {
 		/* get new inode */
 		cifs_fill_uniqueid(sb, &fattr);
@@ -353,7 +366,8 @@
 	int rc;
 	int oplock = 0;
 	__u16 netfid;
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *tcon;
 	char buf[24];
 	unsigned int bytes_read;
 	char *pbuf;
@@ -372,7 +386,12 @@
 		return -EINVAL;	 /* EOPNOTSUPP? */
 	}
 
-	rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
+
+	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
 			 CREATE_NOT_DIR, &netfid, &oplock, NULL,
 			 cifs_sb->local_nls,
 			 cifs_sb->mnt_cifs_flags &
@@ -380,7 +399,7 @@
 	if (rc == 0) {
 		int buf_type = CIFS_NO_BUFFER;
 			/* Read header */
-		rc = CIFSSMBRead(xid, pTcon, netfid,
+		rc = CIFSSMBRead(xid, tcon, netfid,
 				 24 /* length */, 0 /* offset */,
 				 &bytes_read, &pbuf, &buf_type);
 		if ((rc == 0) && (bytes_read >= 8)) {
@@ -422,8 +441,9 @@
 			fattr->cf_dtype = DT_REG;
 			rc = -EOPNOTSUPP; /* or some unknown SFU type */
 		}
-		CIFSSMBClose(xid, pTcon, netfid);
+		CIFSSMBClose(xid, tcon, netfid);
 	}
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -441,11 +461,19 @@
 	ssize_t rc;
 	char ea_value[4];
 	__u32 mode;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *tcon;
 
-	rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS",
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
+
+	rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
 			    ea_value, 4 /* size of buf */, cifs_sb->local_nls,
 			    cifs_sb->mnt_cifs_flags &
 				CIFS_MOUNT_MAP_SPECIAL_CHR);
+	cifs_put_tlink(tlink);
 	if (rc < 0)
 		return (int)rc;
 	else if (rc > 3) {
@@ -468,6 +496,8 @@
 cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
 		       struct cifs_sb_info *cifs_sb, bool adjust_tz)
 {
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
+
 	memset(fattr, 0, sizeof(*fattr));
 	fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
 	if (info->DeletePending)
@@ -482,8 +512,8 @@
 	fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
 
 	if (adjust_tz) {
-		fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
-		fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
+		fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
+		fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
 	}
 
 	fattr->cf_eof = le64_to_cpu(info->EndOfFile);
@@ -515,8 +545,8 @@
 	struct cifs_fattr fattr;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
 	struct cifsFileInfo *cfile = filp->private_data;
+	struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink);
 
 	xid = GetXid();
 	rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
@@ -554,26 +584,33 @@
 {
 	int rc = 0, tmprc;
 	struct cifsTconInfo *pTcon;
+	struct tcon_link *tlink;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 	char *buf = NULL;
 	bool adjustTZ = false;
 	struct cifs_fattr fattr;
 
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
 	cFYI(1, "Getting info on %s", full_path);
 
 	if ((pfindData == NULL) && (*pinode != NULL)) {
 		if (CIFS_I(*pinode)->clientCanCacheRead) {
 			cFYI(1, "No need to revalidate cached inode sizes");
-			return rc;
+			goto cgii_exit;
 		}
 	}
 
 	/* if file info not passed in then get it from server */
 	if (pfindData == NULL) {
 		buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
-		if (buf == NULL)
-			return -ENOMEM;
+		if (buf == NULL) {
+			rc = -ENOMEM;
+			goto cgii_exit;
+		}
 		pfindData = (FILE_ALL_INFO *)buf;
 
 		/* could do find first instead but this returns more info */
@@ -661,6 +698,13 @@
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
 		cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
 
+	/* check for Minshall+French symlinks */
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
+		tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+		if (tmprc)
+			cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
+	}
+
 	if (!*pinode) {
 		*pinode = cifs_iget(sb, &fattr);
 		if (!*pinode)
@@ -671,6 +715,7 @@
 
 cgii_exit:
 	kfree(buf);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -683,6 +728,7 @@
 	int pplen = cifs_sb->prepathlen;
 	int dfsplen;
 	char *full_path = NULL;
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
 	/* if no prefix path, simply set path to the root of share to "" */
 	if (pplen == 0) {
@@ -692,8 +738,8 @@
 		return full_path;
 	}
 
-	if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
-		dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
+	if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
+		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
 	else
 		dfsplen = 0;
 
@@ -702,7 +748,7 @@
 		return full_path;
 
 	if (dfsplen) {
-		strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
+		strncpy(full_path, tcon->treeName, dfsplen);
 		/* switch slash direction in prepath depending on whether
 		 * windows or posix style path names
 		 */
@@ -801,6 +847,8 @@
 			inode->i_flags |= S_NOATIME | S_NOCMTIME;
 		if (inode->i_state & I_NEW) {
 			inode->i_ino = hash;
+			if (S_ISREG(inode->i_mode))
+				inode->i_data.backing_dev_info = sb->s_bdi;
 #ifdef CONFIG_CIFS_FSCACHE
 			/* initialize per-inode cache cookie pointer */
 			CIFS_I(inode)->fscache = NULL;
@@ -816,18 +864,18 @@
 struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
 {
 	int xid;
-	struct cifs_sb_info *cifs_sb;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 	struct inode *inode = NULL;
 	long rc;
 	char *full_path;
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
-	cifs_sb = CIFS_SB(sb);
 	full_path = cifs_build_path_to_root(cifs_sb);
 	if (full_path == NULL)
 		return ERR_PTR(-ENOMEM);
 
 	xid = GetXid();
-	if (cifs_sb->tcon->unix_ext)
+	if (tcon->unix_ext)
 		rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
 	else
 		rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
@@ -838,10 +886,10 @@
 
 #ifdef CONFIG_CIFS_FSCACHE
 	/* populate tcon->resource_id */
-	cifs_sb->tcon->resource_id = CIFS_I(inode)->uniqueid;
+	tcon->resource_id = CIFS_I(inode)->uniqueid;
 #endif
 
-	if (rc && cifs_sb->tcon->ipc) {
+	if (rc && tcon->ipc) {
 		cFYI(1, "ipc connection - fake read inode");
 		inode->i_mode |= S_IFDIR;
 		inode->i_nlink = 2;
@@ -877,7 +925,8 @@
 	struct cifsFileInfo *open_file;
 	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct tcon_link *tlink = NULL;
+	struct cifsTconInfo *pTcon;
 	FILE_BASIC_INFO	info_buf;
 
 	if (attrs == NULL)
@@ -916,13 +965,22 @@
 	/*
 	 * If the file is already open for write, just use that fileid
 	 */
-	open_file = find_writable_file(cifsInode);
+	open_file = find_writable_file(cifsInode, true);
 	if (open_file) {
 		netfid = open_file->netfid;
 		netpid = open_file->pid;
+		pTcon = tlink_tcon(open_file->tlink);
 		goto set_via_filehandle;
 	}
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		tlink = NULL;
+		goto out;
+	}
+	pTcon = tlink_tcon(tlink);
+
 	/*
 	 * NT4 apparently returns success on this call, but it doesn't
 	 * really work.
@@ -966,6 +1024,8 @@
 	else
 		cifsFileInfo_put(open_file);
 out:
+	if (tlink != NULL)
+		cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -983,10 +1043,16 @@
 	struct inode *inode = dentry->d_inode;
 	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *tcon;
 	__u32 dosattr, origattr;
 	FILE_BASIC_INFO *info_buf = NULL;
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
+
 	rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
 			 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
 			 &netfid, &oplock, NULL, cifs_sb->local_nls,
@@ -1055,6 +1121,7 @@
 	CIFSSMBClose(xid, tcon, netfid);
 out:
 	kfree(info_buf);
+	cifs_put_tlink(tlink);
 	return rc;
 
 	/*
@@ -1094,12 +1161,18 @@
 	struct cifsInodeInfo *cifs_inode;
 	struct super_block *sb = dir->i_sb;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *tcon;
 	struct iattr *attrs = NULL;
 	__u32 dosattr = 0, origattr = 0;
 
 	cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry);
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
+
 	xid = GetXid();
 
 	/* Unlink can be called from rename so we can not take the
@@ -1107,8 +1180,7 @@
 	full_path = build_path_from_dentry(dentry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto unlink_out;
 	}
 
 	if ((tcon->ses->capabilities & CAP_UNIX) &&
@@ -1174,10 +1246,11 @@
 	dir->i_ctime = dir->i_mtime = current_fs_time(sb);
 	cifs_inode = CIFS_I(dir);
 	CIFS_I(dir)->time = 0;	/* force revalidate of dir as well */
-
+unlink_out:
 	kfree(full_path);
 	kfree(attrs);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -1186,6 +1259,7 @@
 	int rc = 0, tmprc;
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	char *full_path = NULL;
 	struct inode *newinode = NULL;
@@ -1193,16 +1267,18 @@
 
 	cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode);
 
-	xid = GetXid();
-
 	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
+	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto mkdir_out;
 	}
 
 	if ((pTcon->ses->capabilities & CAP_UNIX) &&
@@ -1360,6 +1436,7 @@
 mkdir_out:
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -1368,6 +1445,7 @@
 	int rc = 0;
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	char *full_path = NULL;
 	struct cifsInodeInfo *cifsInode;
@@ -1376,18 +1454,23 @@
 
 	xid = GetXid();
 
-	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
-
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto rmdir_exit;
 	}
 
+	cifs_sb = CIFS_SB(inode->i_sb);
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		goto rmdir_exit;
+	}
+	pTcon = tlink_tcon(tlink);
+
 	rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
 			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+	cifs_put_tlink(tlink);
 
 	if (!rc) {
 		drop_nlink(inode);
@@ -1408,6 +1491,7 @@
 	direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
 		current_fs_time(inode->i_sb);
 
+rmdir_exit:
 	kfree(full_path);
 	FreeXid(xid);
 	return rc;
@@ -1418,10 +1502,16 @@
 		struct dentry *to_dentry, const char *toPath)
 {
 	struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *pTcon;
 	__u16 srcfid;
 	int oplock, rc;
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
 	/* try path-based rename first */
 	rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
 			   cifs_sb->mnt_cifs_flags &
@@ -1433,11 +1523,11 @@
 	 * rename by filehandle to various Windows servers.
 	 */
 	if (rc == 0 || rc != -ETXTBSY)
-		return rc;
+		goto do_rename_exit;
 
 	/* open-file renames don't work across directories */
 	if (to_dentry->d_parent != from_dentry->d_parent)
-		return rc;
+		goto do_rename_exit;
 
 	/* open the file to be renamed -- we need DELETE perms */
 	rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
@@ -1453,7 +1543,8 @@
 
 		CIFSSMBClose(xid, pTcon, srcfid);
 	}
-
+do_rename_exit:
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -1463,13 +1554,17 @@
 	char *fromName = NULL;
 	char *toName = NULL;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *tcon;
 	FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
 	FILE_UNIX_BASIC_INFO *info_buf_target;
 	int xid, rc, tmprc;
 
 	cifs_sb = CIFS_SB(source_dir->i_sb);
-	tcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
 
 	xid = GetXid();
 
@@ -1545,6 +1640,7 @@
 	kfree(fromName);
 	kfree(toName);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -1597,11 +1693,12 @@
 {
 	int rc = 0;
 	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
 
 	if (!cifs_inode_needs_reval(inode))
 		goto check_inval;
 
-	if (CIFS_SB(inode->i_sb)->tcon->unix_ext)
+	if (tlink_tcon(cfile->tlink)->unix_ext)
 		rc = cifs_get_file_info_unix(filp);
 	else
 		rc = cifs_get_file_info(filp);
@@ -1642,7 +1739,7 @@
 		 "jiffies %ld", full_path, inode, inode->i_count.counter,
 		 dentry, dentry->d_time, jiffies);
 
-	if (CIFS_SB(sb)->tcon->unix_ext)
+	if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
 		rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
 	else
 		rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
@@ -1658,13 +1755,29 @@
 }
 
 int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
-	struct kstat *stat)
+		 struct kstat *stat)
 {
+	struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 	int err = cifs_revalidate_dentry(dentry);
+
 	if (!err) {
 		generic_fillattr(dentry->d_inode, stat);
 		stat->blksize = CIFS_MAX_MSGSIZE;
 		stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
+
+		/*
+		 * If on a multiuser mount without unix extensions, and the
+		 * admin hasn't overridden them, set the ownership to the
+		 * fsuid/fsgid of the current process.
+		 */
+		if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
+		    !tcon->unix_ext) {
+			if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
+				stat->uid = current_fsuid();
+			if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
+				stat->gid = current_fsgid();
+		}
 	}
 	return err;
 }
@@ -1706,7 +1819,8 @@
 	struct cifsFileInfo *open_file;
 	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct tcon_link *tlink = NULL;
+	struct cifsTconInfo *pTcon = NULL;
 
 	/*
 	 * To avoid spurious oplock breaks from server, in the case of
@@ -1717,10 +1831,11 @@
 	 * writebehind data than the SMB timeout for the SetPathInfo
 	 * request would allow
 	 */
-	open_file = find_writable_file(cifsInode);
+	open_file = find_writable_file(cifsInode, true);
 	if (open_file) {
 		__u16 nfid = open_file->netfid;
 		__u32 npid = open_file->pid;
+		pTcon = tlink_tcon(open_file->tlink);
 		rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
 					npid, false);
 		cifsFileInfo_put(open_file);
@@ -1735,6 +1850,13 @@
 		rc = -EINVAL;
 
 	if (rc != 0) {
+		if (pTcon == NULL) {
+			tlink = cifs_sb_tlink(cifs_sb);
+			if (IS_ERR(tlink))
+				return PTR_ERR(tlink);
+			pTcon = tlink_tcon(tlink);
+		}
+
 		/* Set file size by pathname rather than by handle
 		   either because no valid, writeable file handle for
 		   it was found or because there was an error setting
@@ -1764,6 +1886,8 @@
 				CIFSSMBClose(xid, pTcon, netfid);
 			}
 		}
+		if (tlink)
+			cifs_put_tlink(tlink);
 	}
 
 	if (rc == 0) {
@@ -1784,7 +1908,8 @@
 	struct inode *inode = direntry->d_inode;
 	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *pTcon;
 	struct cifs_unix_set_info_args *args = NULL;
 	struct cifsFileInfo *open_file;
 
@@ -1871,17 +1996,25 @@
 		args->ctime = NO_CHANGE_64;
 
 	args->device = 0;
-	open_file = find_writable_file(cifsInode);
+	open_file = find_writable_file(cifsInode, true);
 	if (open_file) {
 		u16 nfid = open_file->netfid;
 		u32 npid = open_file->pid;
+		pTcon = tlink_tcon(open_file->tlink);
 		rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
 		cifsFileInfo_put(open_file);
 	} else {
+		tlink = cifs_sb_tlink(cifs_sb);
+		if (IS_ERR(tlink)) {
+			rc = PTR_ERR(tlink);
+			goto out;
+		}
+		pTcon = tlink_tcon(tlink);
 		rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
 				    cifs_sb->local_nls,
 				    cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
+		cifs_put_tlink(tlink);
 	}
 
 	if (rc)
@@ -2062,7 +2195,7 @@
 {
 	struct inode *inode = direntry->d_inode;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct cifsTconInfo *pTcon = cifs_sb_master_tcon(cifs_sb);
 
 	if (pTcon->unix_ext)
 		return cifs_setattr_unix(direntry, attrs);
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 9d38a71..077bf75 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -37,11 +37,11 @@
 	int xid;
 	struct cifs_sb_info *cifs_sb;
 #ifdef CONFIG_CIFS_POSIX
+	struct cifsFileInfo *pSMBFile = filep->private_data;
+	struct cifsTconInfo *tcon = tlink_tcon(pSMBFile->tlink);
 	__u64	ExtAttrBits = 0;
 	__u64	ExtAttrMask = 0;
-	__u64   caps;
-	struct cifsTconInfo *tcon;
-	struct cifsFileInfo *pSMBFile = filep->private_data;
+	__u64   caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
 #endif /* CONFIG_CIFS_POSIX */
 
 	xid = GetXid();
@@ -50,17 +50,6 @@
 
 	cifs_sb = CIFS_SB(inode->i_sb);
 
-#ifdef CONFIG_CIFS_POSIX
-	tcon = cifs_sb->tcon;
-	if (tcon)
-		caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
-	else {
-		rc = -EIO;
-		FreeXid(xid);
-		return -EIO;
-	}
-#endif /* CONFIG_CIFS_POSIX */
-
 	switch (command) {
 		case CIFS_IOC_CHECKUMOUNT:
 			cFYI(1, "User unmount attempted");
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 473ca80..85cdbf8 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -28,6 +28,296 @@
 #include "cifsproto.h"
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
+#include "md5.h"
+
+#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
+#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
+#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
+#define CIFS_MF_SYMLINK_LINK_MAXLEN (1024)
+#define CIFS_MF_SYMLINK_FILE_SIZE \
+	(CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
+
+#define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
+#define CIFS_MF_SYMLINK_MD5_FORMAT \
+	"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
+#define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) \
+	md5_hash[0],  md5_hash[1],  md5_hash[2],  md5_hash[3], \
+	md5_hash[4],  md5_hash[5],  md5_hash[6],  md5_hash[7], \
+	md5_hash[8],  md5_hash[9],  md5_hash[10], md5_hash[11],\
+	md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15]
+
+static int
+CIFSParseMFSymlink(const u8 *buf,
+		   unsigned int buf_len,
+		   unsigned int *_link_len,
+		   char **_link_str)
+{
+	int rc;
+	unsigned int link_len;
+	const char *md5_str1;
+	const char *link_str;
+	struct MD5Context md5_ctx;
+	u8 md5_hash[16];
+	char md5_str2[34];
+
+	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
+		return -EINVAL;
+
+	md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET];
+	link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET];
+
+	rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len);
+	if (rc != 1)
+		return -EINVAL;
+
+	cifs_MD5_init(&md5_ctx);
+	cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len);
+	cifs_MD5_final(md5_hash, &md5_ctx);
+
+	snprintf(md5_str2, sizeof(md5_str2),
+		 CIFS_MF_SYMLINK_MD5_FORMAT,
+		 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
+
+	if (strncmp(md5_str1, md5_str2, 17) != 0)
+		return -EINVAL;
+
+	if (_link_str) {
+		*_link_str = kstrndup(link_str, link_len, GFP_KERNEL);
+		if (!*_link_str)
+			return -ENOMEM;
+	}
+
+	*_link_len = link_len;
+	return 0;
+}
+
+static int
+CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
+{
+	unsigned int link_len;
+	unsigned int ofs;
+	struct MD5Context md5_ctx;
+	u8 md5_hash[16];
+
+	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
+		return -EINVAL;
+
+	link_len = strlen(link_str);
+
+	if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
+		return -ENAMETOOLONG;
+
+	cifs_MD5_init(&md5_ctx);
+	cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len);
+	cifs_MD5_final(md5_hash, &md5_ctx);
+
+	snprintf(buf, buf_len,
+		 CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT,
+		 link_len,
+		 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
+
+	ofs = CIFS_MF_SYMLINK_LINK_OFFSET;
+	memcpy(buf + ofs, link_str, link_len);
+
+	ofs += link_len;
+	if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
+		buf[ofs] = '\n';
+		ofs++;
+	}
+
+	while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
+		buf[ofs] = ' ';
+		ofs++;
+	}
+
+	return 0;
+}
+
+static int
+CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
+		    const char *fromName, const char *toName,
+		    const struct nls_table *nls_codepage, int remap)
+{
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	u8 *buf;
+	unsigned int bytes_written = 0;
+
+	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
+			 CREATE_NOT_DIR, &netfid, &oplock, NULL,
+			 nls_codepage, remap);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	rc = CIFSSMBWrite(xid, tcon, netfid,
+			  CIFS_MF_SYMLINK_FILE_SIZE /* length */,
+			  0 /* offset */,
+			  &bytes_written, buf, NULL, 0);
+	CIFSSMBClose(xid, tcon, netfid);
+	kfree(buf);
+	if (rc != 0)
+		return rc;
+
+	if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
+		return -EIO;
+
+	return 0;
+}
+
+static int
+CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
+		   const unsigned char *searchName, char **symlinkinfo,
+		   const struct nls_table *nls_codepage, int remap)
+{
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	u8 *buf;
+	char *pbuf;
+	unsigned int bytes_read = 0;
+	int buf_type = CIFS_NO_BUFFER;
+	unsigned int link_len = 0;
+	FILE_ALL_INFO file_info;
+
+	rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ,
+			 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
+			 nls_codepage, remap);
+	if (rc != 0)
+		return rc;
+
+	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
+		CIFSSMBClose(xid, tcon, netfid);
+		/* it's not a symlink */
+		return -EINVAL;
+	}
+
+	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	pbuf = buf;
+
+	rc = CIFSSMBRead(xid, tcon, netfid,
+			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
+			 0 /* offset */,
+			 &bytes_read, &pbuf, &buf_type);
+	CIFSSMBClose(xid, tcon, netfid);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo);
+	kfree(buf);
+	if (rc != 0)
+		return rc;
+
+	return 0;
+}
+
+bool
+CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr)
+{
+	if (!(fattr->cf_mode & S_IFREG))
+		/* it's not a symlink */
+		return false;
+
+	if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
+		/* it's not a symlink */
+		return false;
+
+	return true;
+}
+
+int
+CIFSCheckMFSymlink(struct cifs_fattr *fattr,
+		   const unsigned char *path,
+		   struct cifs_sb_info *cifs_sb, int xid)
+{
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *pTcon;
+	u8 *buf;
+	char *pbuf;
+	unsigned int bytes_read = 0;
+	int buf_type = CIFS_NO_BUFFER;
+	unsigned int link_len = 0;
+	FILE_ALL_INFO file_info;
+
+	if (!CIFSCouldBeMFSymlink(fattr))
+		/* it's not a symlink */
+		return 0;
+
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
+	rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
+			 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
+			 cifs_sb->local_nls,
+			 cifs_sb->mnt_cifs_flags &
+				CIFS_MOUNT_MAP_SPECIAL_CHR);
+	if (rc != 0)
+		goto out;
+
+	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
+		CIFSSMBClose(xid, pTcon, netfid);
+		/* it's not a symlink */
+		goto out;
+	}
+
+	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+	if (!buf) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	pbuf = buf;
+
+	rc = CIFSSMBRead(xid, pTcon, netfid,
+			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
+			 0 /* offset */,
+			 &bytes_read, &pbuf, &buf_type);
+	CIFSSMBClose(xid, pTcon, netfid);
+	if (rc != 0) {
+		kfree(buf);
+		goto out;
+	}
+
+	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
+	kfree(buf);
+	if (rc == -EINVAL) {
+		/* it's not a symlink */
+		rc = 0;
+		goto out;
+	}
+
+	if (rc != 0)
+		goto out;
+
+	/* it is a symlink */
+	fattr->cf_eof = link_len;
+	fattr->cf_mode &= ~S_IFMT;
+	fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
+	fattr->cf_dtype = DT_LNK;
+out:
+	cifs_put_tlink(tlink);
+	return rc;
+}
 
 int
 cifs_hardlink(struct dentry *old_file, struct inode *inode,
@@ -37,18 +327,18 @@
 	int xid;
 	char *fromName = NULL;
 	char *toName = NULL;
-	struct cifs_sb_info *cifs_sb_target;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct cifsInodeInfo *cifsInode;
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
 	xid = GetXid();
 
-	cifs_sb_target = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb_target->tcon;
-
-/* No need to check for cross device links since server will do that
-   BB note DFS case in future though (when we may have to check) */
-
 	fromName = build_path_from_dentry(old_file);
 	toName = build_path_from_dentry(direntry);
 	if ((fromName == NULL) || (toName == NULL)) {
@@ -56,16 +346,15 @@
 		goto cifs_hl_exit;
 	}
 
-/*	if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/
 	if (pTcon->unix_ext)
 		rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
-					    cifs_sb_target->local_nls,
-					    cifs_sb_target->mnt_cifs_flags &
+					    cifs_sb->local_nls,
+					    cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 	else {
 		rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
-					cifs_sb_target->local_nls,
-					cifs_sb_target->mnt_cifs_flags &
+					cifs_sb->local_nls,
+					cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 		if ((rc == -EIO) || (rc == -EINVAL))
 			rc = -EOPNOTSUPP;
@@ -101,6 +390,7 @@
 	kfree(fromName);
 	kfree(toName);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -113,10 +403,19 @@
 	char *full_path = NULL;
 	char *target_path = NULL;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
+	struct tcon_link *tlink = NULL;
+	struct cifsTconInfo *tcon;
 
 	xid = GetXid();
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		tlink = NULL;
+		goto out;
+	}
+	tcon = tlink_tcon(tlink);
+
 	/*
 	 * For now, we just handle symlinks with unix extensions enabled.
 	 * Eventually we should handle NTFS reparse points, and MacOS
@@ -130,7 +429,8 @@
 	 * but there doesn't seem to be any harm in allowing the client to
 	 * read them.
 	 */
-	if (!(tcon->ses->capabilities & CAP_UNIX)) {
+	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+	    && !(tcon->ses->capabilities & CAP_UNIX)) {
 		rc = -EACCES;
 		goto out;
 	}
@@ -141,8 +441,21 @@
 
 	cFYI(1, "Full path: %s inode = 0x%p", full_path, inode);
 
-	rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
-				     cifs_sb->local_nls);
+	rc = -EACCES;
+	/*
+	 * First try Minshall+French Symlinks, if configured
+	 * and fallback to UNIX Extensions Symlinks.
+	 */
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+		rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path,
+					cifs_sb->local_nls,
+					cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
+
+	if ((rc != 0) && (tcon->ses->capabilities & CAP_UNIX))
+		rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
+					     cifs_sb->local_nls);
+
 	kfree(full_path);
 out:
 	if (rc != 0) {
@@ -151,6 +464,8 @@
 	}
 
 	FreeXid(xid);
+	if (tlink)
+		cifs_put_tlink(tlink);
 	nd_set_link(nd, target_path);
 	return NULL;
 }
@@ -160,29 +475,37 @@
 {
 	int rc = -EOPNOTSUPP;
 	int xid;
-	struct cifs_sb_info *cifs_sb;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	char *full_path = NULL;
 	struct inode *newinode = NULL;
 
 	xid = GetXid();
 
-	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		goto symlink_exit;
+	}
+	pTcon = tlink_tcon(tlink);
 
 	full_path = build_path_from_dentry(direntry);
-
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto symlink_exit;
 	}
 
 	cFYI(1, "Full path: %s", full_path);
 	cFYI(1, "symname is %s", symname);
 
 	/* BB what if DFS and this volume is on different share? BB */
-	if (pTcon->unix_ext)
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+		rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname,
+					 cifs_sb->local_nls,
+					 cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
+	else if (pTcon->unix_ext)
 		rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
 					   cifs_sb->local_nls);
 	/* else
@@ -208,8 +531,9 @@
 			d_instantiate(direntry, newinode);
 		}
 	}
-
+symlink_exit:
 	kfree(full_path);
+	cifs_put_tlink(tlink);
 	FreeXid(xid);
 	return rc;
 }
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 3ccadc1..1c681f6 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -347,7 +347,7 @@
 				if (current_fsuid() != treeCon->ses->linux_uid) {
 					cFYI(1, "Multiuser mode and UID "
 						 "did not match tcon uid");
-					read_lock(&cifs_tcp_ses_lock);
+					spin_lock(&cifs_tcp_ses_lock);
 					list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
 						ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
 						if (ses->linux_uid == current_fsuid()) {
@@ -361,7 +361,7 @@
 							}
 						}
 					}
-					read_unlock(&cifs_tcp_ses_lock);
+					spin_unlock(&cifs_tcp_ses_lock);
 				}
 			}
 		}
@@ -551,7 +551,7 @@
 		return false;
 
 	/* look up tcon based on tid & uid */
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp, &srv->smb_ses_list) {
 		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
 		list_for_each(tmp1, &ses->tcon_list) {
@@ -560,25 +560,15 @@
 				continue;
 
 			cifs_stats_inc(&tcon->num_oplock_brks);
-			read_lock(&GlobalSMBSeslock);
+			spin_lock(&cifs_file_list_lock);
 			list_for_each(tmp2, &tcon->openFileList) {
 				netfile = list_entry(tmp2, struct cifsFileInfo,
 						     tlist);
 				if (pSMB->Fid != netfile->netfid)
 					continue;
 
-				/*
-				 * don't do anything if file is about to be
-				 * closed anyway.
-				 */
-				if (netfile->closePend) {
-					read_unlock(&GlobalSMBSeslock);
-					read_unlock(&cifs_tcp_ses_lock);
-					return true;
-				}
-
 				cFYI(1, "file id match, oplock break");
-				pCifsInode = CIFS_I(netfile->pInode);
+				pCifsInode = CIFS_I(netfile->dentry->d_inode);
 				pCifsInode->clientCanCacheAll = false;
 				if (pSMB->OplockLevel == 0)
 					pCifsInode->clientCanCacheRead = false;
@@ -594,17 +584,17 @@
 					cifs_oplock_break_get(netfile);
 				netfile->oplock_break_cancelled = false;
 
-				read_unlock(&GlobalSMBSeslock);
-				read_unlock(&cifs_tcp_ses_lock);
+				spin_unlock(&cifs_file_list_lock);
+				spin_unlock(&cifs_tcp_ses_lock);
 				return true;
 			}
-			read_unlock(&GlobalSMBSeslock);
-			read_unlock(&cifs_tcp_ses_lock);
+			spin_unlock(&cifs_file_list_lock);
+			spin_unlock(&cifs_tcp_ses_lock);
 			cFYI(1, "No matching file for oplock break");
 			return true;
 		}
 	}
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	cFYI(1, "Can not process oplock break for non-existent connection");
 	return true;
 }
@@ -729,6 +719,6 @@
 			   "properly. Hardlinks will not be recognized on this "
 			   "mount. Consider mounting with the \"noserverino\" "
 			   "option to silence this message.",
-			   cifs_sb->tcon->treeName);
+			   cifs_sb_master_tcon(cifs_sb)->treeName);
 	}
 }
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 49c9a4e..5d52e4a 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -61,6 +61,21 @@
 #define NTLMSSP_NEGOTIATE_KEY_XCH   0x40000000
 #define NTLMSSP_NEGOTIATE_56        0x80000000
 
+/* Define AV Pair Field IDs */
+enum av_field_type {
+	NTLMSSP_AV_EOL = 0,
+	NTLMSSP_AV_NB_COMPUTER_NAME,
+	NTLMSSP_AV_NB_DOMAIN_NAME,
+	NTLMSSP_AV_DNS_COMPUTER_NAME,
+	NTLMSSP_AV_DNS_DOMAIN_NAME,
+	NTLMSSP_AV_DNS_TREE_NAME,
+	NTLMSSP_AV_FLAGS,
+	NTLMSSP_AV_TIMESTAMP,
+	NTLMSSP_AV_RESTRICTION,
+	NTLMSSP_AV_TARGET_NAME,
+	NTLMSSP_AV_CHANNEL_BINDINGS
+};
+
 /* Although typedefs are not commonly used for structure definitions */
 /* in the Linux kernel, in this particular case they are useful      */
 /* to more closely match the standards document for NTLMSSP from     */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index d5e591f..ef7bb7b 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -102,7 +102,7 @@
 		return NULL;
 	}
 
-	if (CIFS_SB(sb)->tcon->nocase)
+	if (cifs_sb_master_tcon(CIFS_SB(sb))->nocase)
 		dentry->d_op = &cifs_ci_dentry_ops;
 	else
 		dentry->d_op = &cifs_dentry_ops;
@@ -171,7 +171,7 @@
 cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
 		       struct cifs_sb_info *cifs_sb)
 {
-	int offset = cifs_sb->tcon->ses->server->timeAdj;
+	int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj;
 
 	memset(fattr, 0, sizeof(*fattr));
 	fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
@@ -199,7 +199,7 @@
 	int len;
 	int oplock = 0;
 	int rc;
-	struct cifsTconInfo *ptcon = cifs_sb->tcon;
+	struct cifsTconInfo *ptcon = cifs_sb_tcon(cifs_sb);
 	char *tmpbuffer;
 
 	rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
@@ -223,34 +223,35 @@
 static int initiate_cifs_search(const int xid, struct file *file)
 {
 	int rc = 0;
-	char *full_path;
+	char *full_path = NULL;
 	struct cifsFileInfo *cifsFile;
-	struct cifs_sb_info *cifs_sb;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 
-	if (file->private_data == NULL) {
-		file->private_data =
-			kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
-	}
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
 
 	if (file->private_data == NULL)
-		return -ENOMEM;
+		file->private_data =
+			kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+	if (file->private_data == NULL) {
+		rc = -ENOMEM;
+		goto error_exit;
+	}
+
 	cifsFile = file->private_data;
 	cifsFile->invalidHandle = true;
 	cifsFile->srch_inf.endOfSearch = false;
-
-	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	if (cifs_sb == NULL)
-		return -EINVAL;
-
-	pTcon = cifs_sb->tcon;
-	if (pTcon == NULL)
-		return -EINVAL;
+	cifsFile->tlink = cifs_get_tlink(tlink);
 
 	full_path = build_path_from_dentry(file->f_path.dentry);
-
-	if (full_path == NULL)
-		return -ENOMEM;
+	if (full_path == NULL) {
+		rc = -ENOMEM;
+		goto error_exit;
+	}
 
 	cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos);
 
@@ -283,7 +284,9 @@
 		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
 		goto ffirst_retry;
 	}
+error_exit:
 	kfree(full_path);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -525,14 +528,14 @@
 	   (index_to_find < first_entry_in_buffer)) {
 		/* close and restart search */
 		cFYI(1, "search backing up - close and restart search");
-		write_lock(&GlobalSMBSeslock);
+		spin_lock(&cifs_file_list_lock);
 		if (!cifsFile->srch_inf.endOfSearch &&
 		    !cifsFile->invalidHandle) {
 			cifsFile->invalidHandle = true;
-			write_unlock(&GlobalSMBSeslock);
+			spin_unlock(&cifs_file_list_lock);
 			CIFSFindClose(xid, pTcon, cifsFile->netfid);
 		} else
-			write_unlock(&GlobalSMBSeslock);
+			spin_unlock(&cifs_file_list_lock);
 		if (cifsFile->srch_inf.ntwrk_buf_start) {
 			cFYI(1, "freeing SMB ff cache buf on search rewind");
 			if (cifsFile->srch_inf.smallBuf)
@@ -738,6 +741,15 @@
 		cifs_autodisable_serverino(cifs_sb);
 	}
 
+	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
+	    CIFSCouldBeMFSymlink(&fattr))
+		/*
+		 * trying to get the type and mode can be slow,
+		 * so just call those regular files for now, and mark
+		 * for reval
+		 */
+		fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
+
 	ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
 	tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);
 
@@ -777,9 +789,17 @@
 	xid = GetXid();
 
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	pTcon = cifs_sb->tcon;
-	if (pTcon == NULL)
-		return -EINVAL;
+
+	/*
+	 * Ensure FindFirst doesn't fail before doing filldir() for '.' and
+	 * '..'. Otherwise we won't be able to notify VFS in case of failure.
+	 */
+	if (file->private_data == NULL) {
+		rc = initiate_cifs_search(xid, file);
+		cFYI(1, "initiate cifs search rc %d", rc);
+		if (rc)
+			goto rddir2_exit;
+	}
 
 	switch ((int) file->f_pos) {
 	case 0:
@@ -805,14 +825,6 @@
 			if after then keep searching till find it */
 
 		if (file->private_data == NULL) {
-			rc = initiate_cifs_search(xid, file);
-			cFYI(1, "initiate cifs search rc %d", rc);
-			if (rc) {
-				FreeXid(xid);
-				return rc;
-			}
-		}
-		if (file->private_data == NULL) {
 			rc = -EINVAL;
 			FreeXid(xid);
 			return rc;
@@ -829,6 +841,7 @@
 			CIFSFindClose(xid, pTcon, cifsFile->netfid);
 		} */
 
+		pTcon = tlink_tcon(cifsFile->tlink);
 		rc = find_cifs_entry(xid, pTcon, file,
 				&current_entry, &num_to_fill);
 		if (rc) {
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 0a57cb7..2a11efd 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -80,7 +80,7 @@
 	if (max_vcs < 2)
 		max_vcs = 0xFFFF;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if ((ses->need_reconnect) && is_first_ses_reconnect(ses))
 			goto get_vc_num_exit;  /* vcnum will be zero */
 	for (i = ses->server->srv_count - 1; i < max_vcs; i++) {
@@ -112,7 +112,7 @@
 		vcnum = i;
 	ses->vcnum = vcnum;
 get_vc_num_exit:
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	return cpu_to_le16(vcnum);
 }
@@ -383,6 +383,9 @@
 static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
 				    struct cifsSesInfo *ses)
 {
+	unsigned int tioffset; /* challenge message target info area */
+	unsigned int tilen; /* challenge message target info area length  */
+
 	CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
 
 	if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
@@ -399,12 +402,25 @@
 		return -EINVAL;
 	}
 
-	memcpy(ses->server->cryptKey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
+	memcpy(ses->cryptKey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
 	/* BB we could decode pblob->NegotiateFlags; some may be useful */
 	/* In particular we can examine sign flags */
 	/* BB spec says that if AvId field of MsvAvTimestamp is populated then
 		we must set the MIC field of the AUTHENTICATE_MESSAGE */
 
+	tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
+	tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
+	ses->tilen = tilen;
+	if (ses->tilen) {
+		ses->tiblob = kmalloc(tilen, GFP_KERNEL);
+		if (!ses->tiblob) {
+			cERROR(1, "Challenge target info allocation failure");
+			ses->tilen = 0;
+			return -ENOMEM;
+		}
+		memcpy(ses->tiblob,  bcc_ptr + tioffset, ses->tilen);
+	}
+
 	return 0;
 }
 
@@ -425,7 +441,7 @@
 	/* BB is NTLMV2 session security format easier to use here? */
 	flags = NTLMSSP_NEGOTIATE_56 |	NTLMSSP_REQUEST_TARGET |
 		NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
-		NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
+		NTLMSSP_NEGOTIATE_NTLM;
 	if (ses->server->secMode &
 	   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		flags |= NTLMSSP_NEGOTIATE_SIGN;
@@ -448,13 +464,16 @@
    maximum possible size is fixed and small, making this approach cleaner.
    This function returns the length of the data in the blob */
 static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
+					u16 *buflen,
 				   struct cifsSesInfo *ses,
-				   const struct nls_table *nls_cp, bool first)
+				   const struct nls_table *nls_cp)
 {
+	int rc;
+	unsigned int size;
 	AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
 	__u32 flags;
 	unsigned char *tmp;
-	char ntlm_session_key[CIFS_SESS_KEY_SIZE];
+	struct ntlmv2_resp ntlmv2_response = {};
 
 	memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
 	sec_blob->MessageType = NtLmAuthenticate;
@@ -462,7 +481,7 @@
 	flags = NTLMSSP_NEGOTIATE_56 |
 		NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
 		NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
-		NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
+		NTLMSSP_NEGOTIATE_NTLM;
 	if (ses->server->secMode &
 	   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		flags |= NTLMSSP_NEGOTIATE_SIGN;
@@ -477,19 +496,26 @@
 	sec_blob->LmChallengeResponse.Length = 0;
 	sec_blob->LmChallengeResponse.MaximumLength = 0;
 
-	/* calculate session key,  BB what about adding similar ntlmv2 path? */
-	SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key);
-	if (first)
-		cifs_calculate_mac_key(&ses->server->mac_signing_key,
-				       ntlm_session_key, ses->password);
-
-	memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE);
 	sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
-	sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE);
-	sec_blob->NtChallengeResponse.MaximumLength =
-				cpu_to_le16(CIFS_SESS_KEY_SIZE);
+	rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp);
+	if (rc) {
+		cERROR(1, "Error %d during NTLMSSP authentication", rc);
+		goto setup_ntlmv2_ret;
+	}
+	size =  sizeof(struct ntlmv2_resp);
+	memcpy(tmp, (char *)&ntlmv2_response, size);
+	tmp += size;
+	if (ses->tilen > 0) {
+		memcpy(tmp, ses->tiblob, ses->tilen);
+		tmp += ses->tilen;
+	}
 
-	tmp += CIFS_SESS_KEY_SIZE;
+	sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + ses->tilen);
+	sec_blob->NtChallengeResponse.MaximumLength =
+				cpu_to_le16(size + ses->tilen);
+	kfree(ses->tiblob);
+	ses->tiblob = NULL;
+	ses->tilen = 0;
 
 	if (ses->domainName == NULL) {
 		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
@@ -501,7 +527,6 @@
 		len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
 				    MAX_USERNAME_SIZE, nls_cp);
 		len *= 2; /* unicode is 2 bytes each */
-		len += 2; /* trailing null */
 		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
 		sec_blob->DomainName.Length = cpu_to_le16(len);
 		sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
@@ -518,7 +543,6 @@
 		len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
 				    MAX_USERNAME_SIZE, nls_cp);
 		len *= 2; /* unicode is 2 bytes each */
-		len += 2; /* trailing null */
 		sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
 		sec_blob->UserName.Length = cpu_to_le16(len);
 		sec_blob->UserName.MaximumLength = cpu_to_le16(len);
@@ -533,7 +557,10 @@
 	sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
 	sec_blob->SessionKey.Length = 0;
 	sec_blob->SessionKey.MaximumLength = 0;
-	return tmp - pbuffer;
+
+setup_ntlmv2_ret:
+	*buflen = tmp - pbuffer;
+	return rc;
 }
 
 
@@ -545,19 +572,6 @@
 
 	return;
 }
-
-static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB,
-				  struct cifsSesInfo *ses,
-				  const struct nls_table *nls, bool first_time)
-{
-	int bloblen;
-
-	bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls,
-					  first_time);
-	pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
-
-	return bloblen;
-}
 #endif
 
 int
@@ -579,15 +593,12 @@
 	int bytes_remaining;
 	struct key *spnego_key = NULL;
 	__le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
-	bool first_time;
+	u16 blob_len;
+	char *ntlmsspblob = NULL;
 
 	if (ses == NULL)
 		return -EINVAL;
 
-	read_lock(&cifs_tcp_ses_lock);
-	first_time = is_first_ses_reconnect(ses);
-	read_unlock(&cifs_tcp_ses_lock);
-
 	type = ses->server->secType;
 
 	cFYI(1, "sess setup type %d", type);
@@ -658,7 +669,7 @@
 		/* BB calculate hash with password */
 		/* and copy into bcc */
 
-		calc_lanman_hash(ses->password, ses->server->cryptKey,
+		calc_lanman_hash(ses->password, ses->cryptKey,
 				 ses->server->secMode & SECMODE_PW_ENCRYPT ?
 					true : false, lnm_session_key);
 
@@ -685,15 +696,11 @@
 			cpu_to_le16(CIFS_SESS_KEY_SIZE);
 
 		/* calculate session key */
-		SMBNTencrypt(ses->password, ses->server->cryptKey,
-			     ntlm_session_key);
+		SMBNTencrypt(ses->password, ses->cryptKey, ntlm_session_key);
 
-		if (first_time) /* should this be moved into common code
-				  with similar ntlmv2 path? */
-			cifs_calculate_mac_key(&ses->server->mac_signing_key,
-				ntlm_session_key, ses->password);
+		cifs_calculate_session_key(&ses->auth_key,
+					ntlm_session_key, ses->password);
 		/* copy session key */
-
 		memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
 		bcc_ptr += CIFS_SESS_KEY_SIZE;
 		memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
@@ -725,16 +732,31 @@
 		pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
 		/*	cpu_to_le16(LM2_SESS_KEY_SIZE); */
 
-		pSMB->req_no_secext.CaseSensitivePasswordLength =
-			cpu_to_le16(sizeof(struct ntlmv2_resp));
-
 		/* calculate session key */
-		setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
-		/* FIXME: calculate MAC key */
+		rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
+		if (rc) {
+			cERROR(1, "Error %d during NTLMv2 authentication", rc);
+			kfree(v2_sess_key);
+			goto ssetup_exit;
+		}
 		memcpy(bcc_ptr, (char *)v2_sess_key,
-		       sizeof(struct ntlmv2_resp));
+				sizeof(struct ntlmv2_resp));
 		bcc_ptr += sizeof(struct ntlmv2_resp);
 		kfree(v2_sess_key);
+		/* set case sensitive password length after tilen may get
+		 * assigned, tilen is 0 otherwise.
+		 */
+		pSMB->req_no_secext.CaseSensitivePasswordLength =
+			cpu_to_le16(sizeof(struct ntlmv2_resp) + ses->tilen);
+		if (ses->tilen > 0) {
+			memcpy(bcc_ptr, ses->tiblob, ses->tilen);
+			bcc_ptr += ses->tilen;
+			/* we never did allocate ses->domainName to free */
+			kfree(ses->tiblob);
+			ses->tiblob = NULL;
+			ses->tilen = 0;
+		}
+
 		if (ses->capabilities & CAP_UNICODE) {
 			if (iov[0].iov_len % 2) {
 				*bcc_ptr = 0;
@@ -765,17 +787,14 @@
 		}
 		/* bail out if key is too long */
 		if (msg->sesskey_len >
-		    sizeof(ses->server->mac_signing_key.data.krb5)) {
+		    sizeof(ses->auth_key.data.krb5)) {
 			cERROR(1, "Kerberos signing key too long (%u bytes)",
 				msg->sesskey_len);
 			rc = -EOVERFLOW;
 			goto ssetup_exit;
 		}
-		if (first_time) {
-			ses->server->mac_signing_key.len = msg->sesskey_len;
-			memcpy(ses->server->mac_signing_key.data.krb5,
-				msg->data, msg->sesskey_len);
-		}
+		ses->auth_key.len = msg->sesskey_len;
+		memcpy(ses->auth_key.data.krb5, msg->data, msg->sesskey_len);
 		pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
 		capabilities |= CAP_EXTENDED_SECURITY;
 		pSMB->req.Capabilities = cpu_to_le32(capabilities);
@@ -815,12 +834,30 @@
 			if (phase == NtLmNegotiate) {
 				setup_ntlmssp_neg_req(pSMB, ses);
 				iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
+				iov[1].iov_base = &pSMB->req.SecurityBlob[0];
 			} else if (phase == NtLmAuthenticate) {
-				int blob_len;
-				blob_len = setup_ntlmssp_auth_req(pSMB, ses,
-								  nls_cp,
-								  first_time);
+				/* 5 is an empirical value, large enought to
+				 * hold authenticate message, max 10 of
+				 * av paris, doamin,user,workstation mames,
+				 * flags etc..
+				 */
+				ntlmsspblob = kmalloc(
+					5*sizeof(struct _AUTHENTICATE_MESSAGE),
+					GFP_KERNEL);
+				if (!ntlmsspblob) {
+					cERROR(1, "Can't allocate NTLMSSP");
+					rc = -ENOMEM;
+					goto ssetup_exit;
+				}
+
+				rc = build_ntlmssp_auth_blob(ntlmsspblob,
+							&blob_len, ses, nls_cp);
+				if (rc)
+					goto ssetup_exit;
 				iov[1].iov_len = blob_len;
+				iov[1].iov_base = ntlmsspblob;
+				pSMB->req.SecurityBlobLength =
+					cpu_to_le16(blob_len);
 				/* Make sure that we tell the server that we
 				   are using the uid that it just gave us back
 				   on the response (challenge) */
@@ -830,7 +867,6 @@
 				rc = -ENOSYS;
 				goto ssetup_exit;
 			}
-			iov[1].iov_base = &pSMB->req.SecurityBlob[0];
 			/* unicode strings must be word aligned */
 			if ((iov[0].iov_len + iov[1].iov_len) % 2) {
 				*bcc_ptr = 0;
@@ -895,7 +931,6 @@
 	bcc_ptr = pByteArea(smb_buf);
 
 	if (smb_buf->WordCount == 4) {
-		__u16 blob_len;
 		blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
 		if (blob_len > bytes_remaining) {
 			cERROR(1, "bad security blob length %d", blob_len);
@@ -931,6 +966,8 @@
 		key_put(spnego_key);
 	}
 	kfree(str_area);
+	kfree(ntlmsspblob);
+	ntlmsspblob = NULL;
 	if (resp_buf_type == CIFS_SMALL_BUFFER) {
 		cFYI(1, "ssetup freeing small buf %p", iov[0].iov_base);
 		cifs_small_buf_release(iov[0].iov_base);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 82f78c4..a66c91e 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -543,7 +543,7 @@
 		    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
 					     SECMODE_SIGN_ENABLED))) {
 			rc = cifs_verify_signature(midQ->resp_buf,
-						&ses->server->mac_signing_key,
+						&ses->server->session_key,
 						midQ->sequence_number+1);
 			if (rc) {
 				cERROR(1, "Unexpected SMB signature");
@@ -731,7 +731,7 @@
 		    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
 					     SECMODE_SIGN_ENABLED))) {
 			rc = cifs_verify_signature(out_buf,
-						&ses->server->mac_signing_key,
+						&ses->server->session_key,
 						midQ->sequence_number+1);
 			if (rc) {
 				cERROR(1, "Unexpected SMB signature");
@@ -981,7 +981,7 @@
 	    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
 				     SECMODE_SIGN_ENABLED))) {
 		rc = cifs_verify_signature(out_buf,
-					   &ses->server->mac_signing_key,
+					   &ses->server->session_key,
 					   midQ->sequence_number+1);
 		if (rc) {
 			cERROR(1, "Unexpected SMB signature");
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index a150920..a264b74 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -47,9 +47,10 @@
 #ifdef CONFIG_CIFS_XATTR
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct super_block *sb;
-	char *full_path;
+	char *full_path = NULL;
 
 	if (direntry == NULL)
 		return -EIO;
@@ -58,16 +59,19 @@
 	sb = direntry->d_inode->i_sb;
 	if (sb == NULL)
 		return -EIO;
-	xid = GetXid();
 
 	cifs_sb = CIFS_SB(sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
+	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto remove_ea_exit;
 	}
 	if (ea_name == NULL) {
 		cFYI(1, "Null xattr names not supported");
@@ -91,6 +95,7 @@
 remove_ea_exit:
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 #endif
 	return rc;
 }
@@ -102,6 +107,7 @@
 #ifdef CONFIG_CIFS_XATTR
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct super_block *sb;
 	char *full_path;
@@ -113,16 +119,19 @@
 	sb = direntry->d_inode->i_sb;
 	if (sb == NULL)
 		return -EIO;
-	xid = GetXid();
 
 	cifs_sb = CIFS_SB(sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
+	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto set_ea_exit;
 	}
 	/* return dos attributes as pseudo xattr */
 	/* return alt name if available as pseudo attr */
@@ -132,9 +141,8 @@
 		returns as xattrs */
 	if (value_size > MAX_EA_VALUE_SIZE) {
 		cFYI(1, "size of EA value too large");
-		kfree(full_path);
-		FreeXid(xid);
-		return -EOPNOTSUPP;
+		rc = -EOPNOTSUPP;
+		goto set_ea_exit;
 	}
 
 	if (ea_name == NULL) {
@@ -198,6 +206,7 @@
 set_ea_exit:
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 #endif
 	return rc;
 }
@@ -209,6 +218,7 @@
 #ifdef CONFIG_CIFS_XATTR
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct super_block *sb;
 	char *full_path;
@@ -221,16 +231,18 @@
 	if (sb == NULL)
 		return -EIO;
 
-	xid = GetXid();
-
 	cifs_sb = CIFS_SB(sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
+	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto get_ea_exit;
 	}
 	/* return dos attributes as pseudo xattr */
 	/* return alt name if available as pseudo attr */
@@ -323,6 +335,7 @@
 get_ea_exit:
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 #endif
 	return rc;
 }
@@ -333,6 +346,7 @@
 #ifdef CONFIG_CIFS_XATTR
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct super_block *sb;
 	char *full_path;
@@ -346,18 +360,20 @@
 		return -EIO;
 
 	cifs_sb = CIFS_SB(sb);
-	pTcon = cifs_sb->tcon;
-
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
 		return -EOPNOTSUPP;
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
 	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto list_ea_exit;
 	}
 	/* return dos attributes as pseudo xattr */
 	/* return alt name if available as pseudo attr */
@@ -370,8 +386,10 @@
 				cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
 
+list_ea_exit:
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 #endif
 	return rc;
 }
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 6526e6f..bfe8179 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -148,6 +148,8 @@
 	int error;
 	int idx;
 
+	lock_kernel();
+
 	idx = get_device_index((struct coda_mount_data *) data);
 
 	/* Ignore errors in data, for backward compatibility */
@@ -159,11 +161,13 @@
 	vc = &coda_comms[idx];
 	if (!vc->vc_inuse) {
 		printk("coda_read_super: No pseudo device\n");
+		unlock_kernel();
 		return -EINVAL;
 	}
 
         if ( vc->vc_sb ) {
 		printk("coda_read_super: Device already mounted\n");
+		unlock_kernel();
 		return -EBUSY;
 	}
 
@@ -202,7 +206,8 @@
 	sb->s_root = d_alloc_root(root);
 	if (!sb->s_root)
 		goto error;
-        return 0;
+	unlock_kernel();
+	return 0;
 
  error:
 	bdi_destroy(&vc->bdi);
@@ -212,6 +217,7 @@
 	if (vc)
 		vc->vc_sb = NULL;
 
+	unlock_kernel();
 	return -EINVAL;
 }
 
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index ca25d96..028a9a0 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -39,6 +39,7 @@
 const struct file_operations coda_ioctl_operations = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= coda_pioctl,
+	.llseek		= noop_llseek,
 };
 
 /* the coda pioctl inode ops */
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 116af75..fdc2f3e 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -346,6 +346,7 @@
 	.unlocked_ioctl	= coda_psdev_ioctl,
 	.open		= coda_psdev_open,
 	.release	= coda_psdev_release,
+	.llseek		= noop_llseek,
 };
 
 static int init_coda_psdev(void)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 03e59aa..d0ad09d 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -599,69 +599,6 @@
 #define HIDPGETCONNLIST	_IOR('H', 210, int)
 #define HIDPGETCONNINFO	_IOR('H', 211, int)
 
-#ifdef CONFIG_BLOCK
-struct raw32_config_request
-{
-        compat_int_t    raw_minor;
-        __u64   block_major;
-        __u64   block_minor;
-} __attribute__((packed));
-
-static int get_raw32_request(struct raw_config_request *req, struct raw32_config_request __user *user_req)
-{
-        int ret;
-
-        if (!access_ok(VERIFY_READ, user_req, sizeof(struct raw32_config_request)))
-                return -EFAULT;
-
-        ret = __get_user(req->raw_minor, &user_req->raw_minor);
-        ret |= __get_user(req->block_major, &user_req->block_major);
-        ret |= __get_user(req->block_minor, &user_req->block_minor);
-
-        return ret ? -EFAULT : 0;
-}
-
-static int set_raw32_request(struct raw_config_request *req, struct raw32_config_request __user *user_req)
-{
-	int ret;
-
-        if (!access_ok(VERIFY_WRITE, user_req, sizeof(struct raw32_config_request)))
-                return -EFAULT;
-
-        ret = __put_user(req->raw_minor, &user_req->raw_minor);
-        ret |= __put_user(req->block_major, &user_req->block_major);
-        ret |= __put_user(req->block_minor, &user_req->block_minor);
-
-        return ret ? -EFAULT : 0;
-}
-
-static int raw_ioctl(unsigned fd, unsigned cmd,
-		struct raw32_config_request __user *user_req)
-{
-        int ret;
-
-        switch (cmd) {
-        case RAW_SETBIND:
-	default: {	/* RAW_GETBIND */
-                struct raw_config_request req;
-                mm_segment_t oldfs = get_fs();
-
-                if ((ret = get_raw32_request(&req, user_req)))
-                        return ret;
-
-                set_fs(KERNEL_DS);
-                ret = sys_ioctl(fd,cmd,(unsigned long)&req);
-                set_fs(oldfs);
-
-                if ((!ret) && (cmd == RAW_GETBIND)) {
-                        ret = set_raw32_request(&req, user_req);
-                }
-                break;
-        }
-        }
-        return ret;
-}
-#endif /* CONFIG_BLOCK */
 
 struct serial_struct32 {
         compat_int_t    type;
@@ -1262,9 +1199,6 @@
 COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS)
 COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS)
 COMPATIBLE_IOCTL(OSS_GETVERSION)
-/* Raw devices */
-COMPATIBLE_IOCTL(RAW_SETBIND)
-COMPATIBLE_IOCTL(RAW_GETBIND)
 /* SMB ioctls which do not need any translations */
 COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
 /* Watchdog */
@@ -1523,10 +1457,6 @@
 	case MTIOCGET32:
 	case MTIOCPOS32:
 		return mt_ioctl_trans(fd, cmd, argp);
-	/* Raw devices */
-	case RAW_SETBIND:
-	case RAW_GETBIND:
-		return raw_ioctl(fd, cmd, argp);
 #endif
 	/* One SMB ioctl needs translations. */
 #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 0210898..89d394d 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -43,6 +43,7 @@
 	.read =		default_read_file,
 	.write =	default_write_file,
 	.open =		default_open,
+	.llseek =	noop_llseek,
 };
 
 static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd)
@@ -454,6 +455,7 @@
 	.read =		read_file_bool,
 	.write =	write_file_bool,
 	.open =		default_open,
+	.llseek =	default_llseek,
 };
 
 /**
@@ -498,6 +500,7 @@
 static const struct file_operations fops_blob = {
 	.read =		read_file_blob,
 	.open =		default_open,
+	.llseek =	default_llseek,
 };
 
 /**
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index c6cf251..6b42ba8 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -643,7 +643,8 @@
 static const struct file_operations waiters_fops = {
 	.owner   = THIS_MODULE,
 	.open    = waiters_open,
-	.read    = waiters_read
+	.read    = waiters_read,
+	.llseek  = default_llseek,
 };
 
 void dlm_delete_debug_file(struct dlm_ls *ls)
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 031dbe3..64e5f3e 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -1846,6 +1846,9 @@
 	struct dlm_lkb *gr;
 
 	list_for_each_entry(gr, head, lkb_statequeue) {
+		/* skip self when sending basts to convertqueue */
+		if (gr == lkb)
+			continue;
 		if (gr->lkb_bastfn && modes_require_bast(gr, lkb)) {
 			queue_bast(r, gr, lkb->lkb_rqmode);
 			gr->lkb_highbast = lkb->lkb_rqmode;
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
index d45c02d..30d8b85 100644
--- a/fs/dlm/plock.c
+++ b/fs/dlm/plock.c
@@ -412,7 +412,8 @@
 	.read    = dev_read,
 	.write   = dev_write,
 	.poll    = dev_poll,
-	.owner   = THIS_MODULE
+	.owner   = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice plock_dev_misc = {
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index b627285..66d6c16 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -1009,6 +1009,7 @@
 	.write   = device_write,
 	.poll    = device_poll,
 	.owner   = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static const struct file_operations ctl_device_fops = {
@@ -1017,6 +1018,7 @@
 	.read    = device_read,
 	.write   = device_write,
 	.owner   = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice ctl_device = {
@@ -1029,6 +1031,7 @@
 	.open    = monitor_device_open,
 	.release = monitor_device_close,
 	.owner   = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice monitor_device = {
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 622c9514..91da029 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -31,7 +31,6 @@
 #include <linux/security.h>
 #include <linux/compat.h>
 #include <linux/fs_stack.h>
-#include <linux/smp_lock.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -284,11 +283,9 @@
 	int rc = 0;
 	struct file *lower_file = NULL;
 
-	lock_kernel();
 	lower_file = ecryptfs_file_to_lower(file);
 	if (lower_file->f_op && lower_file->f_op->fasync)
 		rc = lower_file->f_op->fasync(fd, lower_file, flag);
-	unlock_kernel();
 	return rc;
 }
 
@@ -332,6 +329,7 @@
 	.fsync = ecryptfs_fsync,
 	.fasync = ecryptfs_fasync,
 	.splice_read = generic_file_splice_read,
+	.llseek = default_llseek,
 };
 
 const struct file_operations ecryptfs_main_fops = {
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 00208c3..940a82e 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -482,6 +482,7 @@
 	.read    = ecryptfs_miscdev_read,
 	.write   = ecryptfs_miscdev_write,
 	.release = ecryptfs_miscdev_release,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice ecryptfs_miscdev = {
diff --git a/fs/eventfd.c b/fs/eventfd.c
index 6bd3f76..e0194b3 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -293,6 +293,7 @@
 	.poll		= eventfd_poll,
 	.read		= eventfd_read,
 	.write		= eventfd_write,
+	.llseek		= noop_llseek,
 };
 
 /**
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 3817149..256bb7b 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -674,7 +674,8 @@
 /* File callbacks that implement the eventpoll file behaviour */
 static const struct file_operations eventpoll_fops = {
 	.release	= ep_eventpoll_release,
-	.poll		= ep_eventpoll_poll
+	.poll		= ep_eventpoll_poll,
+	.llseek		= noop_llseek,
 };
 
 /* Fast test to see if the file is an evenpoll file */
diff --git a/fs/exec.c b/fs/exec.c
index 828dd24..6d2b6f9 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -2014,3 +2014,43 @@
 fail:
 	return;
 }
+
+/*
+ * Core dumping helper functions.  These are the only things you should
+ * do on a core-file: use only these functions to write out all the
+ * necessary info.
+ */
+int dump_write(struct file *file, const void *addr, int nr)
+{
+	return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+}
+EXPORT_SYMBOL(dump_write);
+
+int dump_seek(struct file *file, loff_t off)
+{
+	int ret = 1;
+
+	if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
+		if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
+			return 0;
+	} else {
+		char *buf = (char *)get_zeroed_page(GFP_KERNEL);
+
+		if (!buf)
+			return 0;
+		while (off > 0) {
+			unsigned long n = off;
+
+			if (n > PAGE_SIZE)
+				n = PAGE_SIZE;
+			if (!dump_write(file, buf, n)) {
+				ret = 0;
+				break;
+			}
+			off -= n;
+		}
+		free_page((unsigned long)buf);
+	}
+	return ret;
+}
+EXPORT_SYMBOL(dump_seek);
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index eb7368e..3eadd97 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -54,6 +54,9 @@
 	unsigned nr_pages;
 	unsigned long length;
 	loff_t pg_first; /* keep 64bit also in 32-arches */
+	bool read_4_write; /* This means two things: that the read is sync
+			    * And the pages should not be unlocked.
+			    */
 };
 
 static void _pcol_init(struct page_collect *pcol, unsigned expected_pages,
@@ -71,6 +74,7 @@
 	pcol->nr_pages = 0;
 	pcol->length = 0;
 	pcol->pg_first = -1;
+	pcol->read_4_write = false;
 }
 
 static void _pcol_reset(struct page_collect *pcol)
@@ -347,7 +351,8 @@
 		if (PageError(page))
 			ClearPageError(page);
 
-		unlock_page(page);
+		if (!pcol->read_4_write)
+			unlock_page(page);
 		EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page,"
 			     " splitting\n", inode->i_ino, page->index);
 
@@ -428,6 +433,7 @@
 	/* readpage_strip might call read_exec(,is_sync==false) at several
 	 * places but not if we have a single page.
 	 */
+	pcol.read_4_write = is_sync;
 	ret = readpage_strip(&pcol, page);
 	if (ret) {
 		EXOFS_ERR("_readpage => %d\n", ret);
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 1ec6026..85df87d 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -747,15 +747,16 @@
 	__le32 features;
 	int err;
 
+	err = -ENOMEM;
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
-		return -ENOMEM;
+		goto failed_unlock;
 
 	sbi->s_blockgroup_lock =
 		kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
 	if (!sbi->s_blockgroup_lock) {
 		kfree(sbi);
-		return -ENOMEM;
+		goto failed_unlock;
 	}
 	sb->s_fs_info = sbi;
 	sbi->s_sb_block = sb_block;
@@ -1107,6 +1108,7 @@
 	sb->s_fs_info = NULL;
 	kfree(sbi->s_blockgroup_lock);
 	kfree(sbi);
+failed_unlock:
 	return ret;
 }
 
diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
index d7e9f74..09b13bb 100644
--- a/fs/ext3/fsync.c
+++ b/fs/ext3/fsync.c
@@ -90,7 +90,6 @@
 	 * storage
 	 */
 	if (needs_barrier)
-		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL,
-				BLKDEV_IFL_WAIT);
+		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 	return ret;
 }
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 5dbf4db..3777680 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -411,9 +411,6 @@
 	int i, err;
 
 	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
-
-	lock_kernel();
-
 	ext3_xattr_put_super(sb);
 	err = journal_destroy(sbi->s_journal);
 	sbi->s_journal = NULL;
@@ -462,8 +459,6 @@
 	sb->s_fs_info = NULL;
 	kfree(sbi->s_blockgroup_lock);
 	kfree(sbi);
-
-	unlock_kernel();
 }
 
 static struct kmem_cache *ext3_inode_cachep;
@@ -1627,8 +1622,6 @@
 	sbi->s_resgid = EXT3_DEF_RESGID;
 	sbi->s_sb_block = sb_block;
 
-	unlock_kernel();
-
 	blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE);
 	if (!blocksize) {
 		ext3_msg(sb, KERN_ERR, "error: unable to set blocksize");
@@ -1849,8 +1842,8 @@
 		goto failed_mount;
 	}
 
-	if (le32_to_cpu(es->s_blocks_count) >
-		    (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
+	if (generic_check_addressable(sb->s_blocksize_bits,
+				      le32_to_cpu(es->s_blocks_count))) {
 		ext3_msg(sb, KERN_ERR,
 			"error: filesystem is too large to mount safely");
 		if (sizeof(sector_t) < 8)
@@ -2025,7 +2018,6 @@
 		test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
 		"writeback");
 
-	lock_kernel();
 	return 0;
 
 cantfind_ext3:
@@ -2055,7 +2047,6 @@
 	sb->s_fs_info = NULL;
 	kfree(sbi->s_blockgroup_lock);
 	kfree(sbi);
-	lock_kernel();
 	return ret;
 }
 
@@ -2538,8 +2529,6 @@
 	int i;
 #endif
 
-	lock_kernel();
-
 	/* Store the original options */
 	lock_super(sb);
 	old_sb_flags = sb->s_flags;
@@ -2648,7 +2637,6 @@
 			kfree(old_opts.s_qf_names[i]);
 #endif
 	unlock_super(sb);
-	unlock_kernel();
 
 	if (enable_quota)
 		dquot_resume(sb, -1);
@@ -2669,7 +2657,6 @@
 	}
 #endif
 	unlock_super(sb);
-	unlock_kernel();
 	return err;
 }
 
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
index 592adf2..3f3ff5e 100644
--- a/fs/ext4/fsync.c
+++ b/fs/ext4/fsync.c
@@ -128,10 +128,9 @@
 		    (journal->j_fs_dev != journal->j_dev) &&
 		    (journal->j_flags & JBD2_BARRIER))
 			blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL,
-					NULL, BLKDEV_IFL_WAIT);
+					NULL);
 		ret = jbd2_log_wait_commit(journal, commit_tid);
 	} else if (journal->j_flags & JBD2_BARRIER)
-		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL,
-			BLKDEV_IFL_WAIT);
+		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 	return ret;
 }
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 4b4ad4b..19aa0d4 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2566,7 +2566,7 @@
 	discard_block = block + ext4_group_first_block_no(sb, block_group);
 	trace_ext4_discard_blocks(sb,
 			(unsigned long long) discard_block, count);
-	ret = sb_issue_discard(sb, discard_block, count);
+	ret = sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0);
 	if (ret == EOPNOTSUPP) {
 		ext4_warning(sb, "discard not supported, disabling");
 		clear_opt(EXT4_SB(sb)->s_mount_opt, DISCARD);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2614774..8ecc1e5 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/parser.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/exportfs.h>
 #include <linux/vfs.h>
@@ -708,7 +707,6 @@
 	destroy_workqueue(sbi->dio_unwritten_wq);
 
 	lock_super(sb);
-	lock_kernel();
 	if (sb->s_dirt)
 		ext4_commit_super(sb, 1);
 
@@ -775,7 +773,6 @@
 	 * Now that we are completely done shutting down the
 	 * superblock, we need to actually destroy the kobject.
 	 */
-	unlock_kernel();
 	unlock_super(sb);
 	kobject_put(&sbi->s_kobj);
 	wait_for_completion(&sbi->s_kobj_unregister);
@@ -2588,8 +2585,6 @@
 		sbi->s_sectors_written_start =
 			part_stat_read(sb->s_bdev->bd_part, sectors[1]);
 
-	unlock_kernel();
-
 	/* Cleanup superblock name */
 	for (cp = sb->s_id; (cp = strchr(cp, '/'));)
 		*cp = '!';
@@ -2831,15 +2826,13 @@
 	 * Test whether we have more sectors than will fit in sector_t,
 	 * and whether the max offset is addressable by the page cache.
 	 */
-	if ((ext4_blocks_count(es) >
-	     (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) ||
-	    (ext4_blocks_count(es) >
-	     (pgoff_t)(~0ULL) >> (PAGE_CACHE_SHIFT - sb->s_blocksize_bits))) {
+	ret = generic_check_addressable(sb->s_blocksize_bits,
+					ext4_blocks_count(es));
+	if (ret) {
 		ext4_msg(sb, KERN_ERR, "filesystem"
 			 " too large to mount safely on this system");
 		if (sizeof(sector_t) < 8)
 			ext4_msg(sb, KERN_WARNING, "CONFIG_LBDAF not enabled");
-		ret = -EFBIG;
 		goto failed_mount;
 	}
 
@@ -3166,7 +3159,6 @@
 	if (es->s_error_count)
 		mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
 
-	lock_kernel();
 	kfree(orig_data);
 	return 0;
 
@@ -3213,7 +3205,6 @@
 	sb->s_fs_info = NULL;
 	kfree(sbi->s_blockgroup_lock);
 	kfree(sbi);
-	lock_kernel();
 out_free_orig:
 	kfree(orig_data);
 	return ret;
@@ -3722,8 +3713,6 @@
 #endif
 	char *orig_data = kstrdup(data, GFP_KERNEL);
 
-	lock_kernel();
-
 	/* Store the original options */
 	lock_super(sb);
 	old_sb_flags = sb->s_flags;
@@ -3858,7 +3847,6 @@
 			kfree(old_opts.s_qf_names[i]);
 #endif
 	unlock_super(sb);
-	unlock_kernel();
 	if (enable_quota)
 		dquot_resume(sb, -1);
 
@@ -3884,7 +3872,6 @@
 	}
 #endif
 	unlock_super(sb);
-	unlock_kernel();
 	kfree(orig_data);
 	return err;
 }
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index 81184d3..b47d2c9 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -577,7 +577,8 @@
 
 				sb_issue_discard(sb,
 					fat_clus_to_blknr(sbi, first_cl),
-					nr_clus * sbi->sec_per_clus);
+					nr_clus * sbi->sec_per_clus,
+					GFP_NOFS, 0);
 
 				first_cl = cluster;
 			}
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 8300580..ad6998a 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/time.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/seq_file.h>
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
@@ -489,8 +488,6 @@
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 
-	lock_kernel();
-
 	if (sb->s_dirt)
 		fat_write_super(sb);
 
@@ -504,8 +501,6 @@
 
 	sb->s_fs_info = NULL;
 	kfree(sbi);
-
-	unlock_kernel();
 }
 
 static struct kmem_cache *fat_inode_cachep;
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 1736f23..970e682 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -255,10 +255,7 @@
 
 	for (i = 0; i < nr_bhs; i++) {
 		wait_on_buffer(bhs[i]);
-		if (buffer_eopnotsupp(bhs[i])) {
-			clear_buffer_eopnotsupp(bhs[i]);
-			err = -EOPNOTSUPP;
-		} else if (!err && !buffer_uptodate(bhs[i]))
+		if (!err && !buffer_uptodate(bhs[i]))
 			err = -EIO;
 	}
 	return err;
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index bbc94ae..bbca5c1 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -662,12 +662,16 @@
 {
 	int res;
 
+	lock_super(sb);
 	res = fat_fill_super(sb, data, silent, &msdos_dir_inode_operations, 0);
-	if (res)
+	if (res) {
+		unlock_super(sb);
 		return res;
+	}
 
 	sb->s_flags |= MS_NOATIME;
 	sb->s_root->d_op = &msdos_dentry_operations;
+	unlock_super(sb);
 	return 0;
 }
 
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 6fcc7e7..6f0f6c9 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -1055,15 +1055,19 @@
 {
 	int res;
 
+	lock_super(sb);
 	res = fat_fill_super(sb, data, silent, &vfat_dir_inode_operations, 1);
-	if (res)
+	if (res) {
+		unlock_super(sb);
 		return res;
+	}
 
 	if (MSDOS_SB(sb)->options.name_check != 's')
 		sb->s_root->d_op = &vfat_ci_dentry_ops;
 	else
 		sb->s_root->d_op = &vfat_dentry_ops;
 
+	unlock_super(sb);
 	return 0;
 }
 
diff --git a/fs/fifo.c b/fs/fifo.c
index 5d6606f..4e303c2 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -151,4 +151,5 @@
  */
 const struct file_operations def_fifo_fops = {
 	.open		= fifo_open,	/* will set read_ or write_pipefifo_fops */
+	.llseek		= noop_llseek,
 };
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 0ec7bb2..6c5131d 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -36,7 +36,6 @@
 #include <linux/highmem.h>
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 #include "vxfs.h"
 #include "vxfs_dir.h"
@@ -212,16 +211,12 @@
 	if (dp->d_name.len > VXFS_NAMELEN)
 		return ERR_PTR(-ENAMETOOLONG);
 				 
-	lock_kernel();
 	ino = vxfs_inode_by_name(dip, dp);
 	if (ino) {
 		ip = vxfs_iget(dip->i_sb, ino);
-		if (IS_ERR(ip)) {
-			unlock_kernel();
+		if (IS_ERR(ip))
 			return ERR_CAST(ip);
-		}
 	}
-	unlock_kernel();
 	d_add(dp, ip);
 	return NULL;
 }
@@ -248,8 +243,6 @@
 	u_long			page, npages, block, pblocks, nblocks, offset;
 	loff_t			pos;
 
-	lock_kernel();
-
 	switch ((long)fp->f_pos) {
 	case 0:
 		if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0)
@@ -265,10 +258,8 @@
 
 	pos = fp->f_pos - 2;
 	
-	if (pos > VXFS_DIRROUND(ip->i_size)) {
-		unlock_kernel();
+	if (pos > VXFS_DIRROUND(ip->i_size))
 		return 0;
-	}
 
 	npages = dir_pages(ip);
 	nblocks = dir_blocks(ip);
@@ -327,6 +318,5 @@
 done:
 	fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
 out:
-	unlock_kernel();
 	return 0;
 }
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index dc0c041..71b0148 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -38,7 +38,6 @@
 #include <linux/buffer_head.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/stat.h>
 #include <linux/vfs.h>
 #include <linux/mount.h>
@@ -81,16 +80,12 @@
 {
 	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);
 
-	lock_kernel();
-
 	vxfs_put_fake_inode(infp->vsi_fship);
 	vxfs_put_fake_inode(infp->vsi_ilist);
 	vxfs_put_fake_inode(infp->vsi_stilist);
 
 	brelse(infp->vsi_bp);
 	kfree(infp);
-
-	unlock_kernel();
 }
 
 /**
@@ -148,7 +143,7 @@
  *   The superblock on success, else %NULL.
  *
  * Locking:
- *   We are under the bkl and @sbp->s_lock.
+ *   We are under @sbp->s_lock.
  */
 static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 {
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 5581122..ab38fef 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -72,22 +72,11 @@
 static inline struct backing_dev_info *inode_to_bdi(struct inode *inode)
 {
 	struct super_block *sb = inode->i_sb;
-	struct backing_dev_info *bdi = inode->i_mapping->backing_dev_info;
 
-	/*
-	 * For inodes on standard filesystems, we use superblock's bdi. For
-	 * inodes on virtual filesystems, we want to use inode mapping's bdi
-	 * because they can possibly point to something useful (think about
-	 * block_dev filesystem).
-	 */
-	if (sb->s_bdi && sb->s_bdi != &noop_backing_dev_info) {
-		/* Some device inodes could play dirty tricks. Catch them... */
-		WARN(bdi != sb->s_bdi && bdi_cap_writeback_dirty(bdi),
-			"Dirtiable inode bdi %s != sb bdi %s\n",
-			bdi->name, sb->s_bdi->name);
-		return sb->s_bdi;
-	}
-	return bdi;
+	if (strcmp(sb->s_type->name, "bdev") == 0)
+		return inode->i_mapping->backing_dev_info;
+
+	return sb->s_bdi;
 }
 
 static void bdi_queue_work(struct backing_dev_info *bdi,
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 3773fd6..7367e17 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -179,23 +179,27 @@
 static const struct file_operations fuse_ctl_abort_ops = {
 	.open = nonseekable_open,
 	.write = fuse_conn_abort_write,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations fuse_ctl_waiting_ops = {
 	.open = nonseekable_open,
 	.read = fuse_conn_waiting_read,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations fuse_conn_max_background_ops = {
 	.open = nonseekable_open,
 	.read = fuse_conn_max_background_read,
 	.write = fuse_conn_max_background_write,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations fuse_conn_congestion_threshold_ops = {
 	.open = nonseekable_open,
 	.read = fuse_conn_congestion_threshold_read,
 	.write = fuse_conn_congestion_threshold_write,
+	.llseek = no_llseek,
 };
 
 static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index e1f8171..3e87cce 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -182,6 +182,7 @@
 	.unlocked_ioctl		= cuse_file_ioctl,
 	.compat_ioctl		= cuse_file_compat_ioctl,
 	.poll			= fuse_file_poll,
+	.llseek		= noop_llseek,
 };
 
 
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index d367af1..cde755c 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1354,7 +1354,7 @@
 	loff_t file_size;
 	unsigned int num;
 	unsigned int offset;
-	size_t total_len;
+	size_t total_len = 0;
 
 	req = fuse_get_req(fc);
 	if (IS_ERR(req))
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
index cc96655..c465ae0 100644
--- a/fs/gfs2/Kconfig
+++ b/fs/gfs2/Kconfig
@@ -1,6 +1,6 @@
 config GFS2_FS
 	tristate "GFS2 file system support"
-	depends on EXPERIMENTAL && (64BIT || LBDAF)
+	depends on (64BIT || LBDAF)
 	select DLM if GFS2_FS_LOCKING_DLM
 	select CONFIGFS_FS if GFS2_FS_LOCKING_DLM
 	select SYSFS if GFS2_FS_LOCKING_DLM
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 194fe16..6b24afb 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -36,8 +36,8 @@
 #include "glops.h"
 
 
-static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
-				   unsigned int from, unsigned int to)
+void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
+			    unsigned int from, unsigned int to)
 {
 	struct buffer_head *head = page_buffers(page);
 	unsigned int bsize = head->b_size;
@@ -615,7 +615,7 @@
 	unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
 	int alloc_required;
 	int error = 0;
-	struct gfs2_alloc *al;
+	struct gfs2_alloc *al = NULL;
 	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
 	unsigned from = pos & (PAGE_CACHE_SIZE - 1);
 	unsigned to = from + len;
@@ -663,6 +663,8 @@
 		rblocks += RES_STATFS + RES_QUOTA;
 	if (&ip->i_inode == sdp->sd_rindex)
 		rblocks += 2 * RES_STATFS;
+	if (alloc_required)
+		rblocks += gfs2_rg_blocks(al);
 
 	error = gfs2_trans_begin(sdp, rblocks,
 				 PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize);
@@ -696,13 +698,11 @@
 
 	page_cache_release(page);
 
-	/*
-	 * XXX(truncate): the call below should probably be replaced with
-	 * a call to the gfs2-specific truncate blocks helper to actually
-	 * release disk blocks..
-	 */
+	gfs2_trans_end(sdp);
 	if (pos + len > ip->i_inode.i_size)
-		truncate_setsize(&ip->i_inode, ip->i_inode.i_size);
+		gfs2_trim_blocks(&ip->i_inode);
+	goto out_trans_fail;
+
 out_endtrans:
 	gfs2_trans_end(sdp);
 out_trans_fail:
@@ -802,10 +802,8 @@
 	page_cache_release(page);
 
 	if (copied) {
-		if (inode->i_size < to) {
+		if (inode->i_size < to)
 			i_size_write(inode, to);
-			ip->i_disksize = inode->i_size;
-		}
 		gfs2_dinode_out(ip, di);
 		mark_inode_dirty(inode);
 	}
@@ -876,8 +874,6 @@
 
 	ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
 	if (ret > 0) {
-		if (inode->i_size > ip->i_disksize)
-			ip->i_disksize = inode->i_size;
 		gfs2_dinode_out(ip, dibh->b_data);
 		mark_inode_dirty(inode);
 	}
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 6f48280..5476c06 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -50,7 +50,7 @@
  * @ip: the inode
  * @dibh: the dinode buffer
  * @block: the block number that was allocated
- * @private: any locked page held by the caller process
+ * @page: The (optional) page. This is looked up if @page is NULL
  *
  * Returns: errno
  */
@@ -109,8 +109,7 @@
 /**
  * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big
  * @ip: The GFS2 inode to unstuff
- * @unstuffer: the routine that handles unstuffing a non-zero length file
- * @private: private data for the unstuffer
+ * @page: The (optional) page. This is looked up if the @page is NULL
  *
  * This routine unstuffs a dinode and returns it to a "normal" state such
  * that the height can be grown in the traditional way.
@@ -132,7 +131,7 @@
 	if (error)
 		goto out;
 
-	if (ip->i_disksize) {
+	if (i_size_read(&ip->i_inode)) {
 		/* Get a free block, fill it with the stuffed data,
 		   and write it out to disk */
 
@@ -161,7 +160,7 @@
 	di = (struct gfs2_dinode *)dibh->b_data;
 	gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
 
-	if (ip->i_disksize) {
+	if (i_size_read(&ip->i_inode)) {
 		*(__be64 *)(di + 1) = cpu_to_be64(block);
 		gfs2_add_inode_blocks(&ip->i_inode, 1);
 		di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
@@ -885,83 +884,14 @@
 }
 
 /**
- * do_grow - Make a file look bigger than it is
- * @ip: the inode
- * @size: the size to set the file to
- *
- * Called with an exclusive lock on @ip.
- *
- * Returns: errno
- */
-
-static int do_grow(struct gfs2_inode *ip, u64 size)
-{
-	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-	struct gfs2_alloc *al;
-	struct buffer_head *dibh;
-	int error;
-
-	al = gfs2_alloc_get(ip);
-	if (!al)
-		return -ENOMEM;
-
-	error = gfs2_quota_lock_check(ip);
-	if (error)
-		goto out;
-
-	al->al_requested = sdp->sd_max_height + RES_DATA;
-
-	error = gfs2_inplace_reserve(ip);
-	if (error)
-		goto out_gunlock_q;
-
-	error = gfs2_trans_begin(sdp,
-			sdp->sd_max_height + al->al_rgd->rd_length +
-			RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0);
-	if (error)
-		goto out_ipres;
-
-	error = gfs2_meta_inode_buffer(ip, &dibh);
-	if (error)
-		goto out_end_trans;
-
-	if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
-		if (gfs2_is_stuffed(ip)) {
-			error = gfs2_unstuff_dinode(ip, NULL);
-			if (error)
-				goto out_brelse;
-		}
-	}
-
-	ip->i_disksize = size;
-	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
-	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-	gfs2_dinode_out(ip, dibh->b_data);
-
-out_brelse:
-	brelse(dibh);
-out_end_trans:
-	gfs2_trans_end(sdp);
-out_ipres:
-	gfs2_inplace_release(ip);
-out_gunlock_q:
-	gfs2_quota_unlock(ip);
-out:
-	gfs2_alloc_put(ip);
-	return error;
-}
-
-
-/**
  * gfs2_block_truncate_page - Deal with zeroing out data for truncate
  *
  * This is partly borrowed from ext3.
  */
-static int gfs2_block_truncate_page(struct address_space *mapping)
+static int gfs2_block_truncate_page(struct address_space *mapping, loff_t from)
 {
 	struct inode *inode = mapping->host;
 	struct gfs2_inode *ip = GFS2_I(inode);
-	loff_t from = inode->i_size;
 	unsigned long index = from >> PAGE_CACHE_SHIFT;
 	unsigned offset = from & (PAGE_CACHE_SIZE-1);
 	unsigned blocksize, iblock, length, pos;
@@ -1023,9 +953,11 @@
 	return err;
 }
 
-static int trunc_start(struct gfs2_inode *ip, u64 size)
+static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
 {
-	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_sbd *sdp = GFS2_SB(inode);
+	struct address_space *mapping = inode->i_mapping;
 	struct buffer_head *dibh;
 	int journaled = gfs2_is_jdata(ip);
 	int error;
@@ -1039,31 +971,26 @@
 	if (error)
 		goto out;
 
-	if (gfs2_is_stuffed(ip)) {
-		u64 dsize = size + sizeof(struct gfs2_dinode);
-		ip->i_disksize = size;
-		ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
-		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-		gfs2_dinode_out(ip, dibh->b_data);
-		if (dsize > dibh->b_size)
-			dsize = dibh->b_size;
-		gfs2_buffer_clear_tail(dibh, dsize);
-		error = 1;
-	} else {
-		if (size & (u64)(sdp->sd_sb.sb_bsize - 1))
-			error = gfs2_block_truncate_page(ip->i_inode.i_mapping);
+	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 
-		if (!error) {
-			ip->i_disksize = size;
-			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
-			ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
-			gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-			gfs2_dinode_out(ip, dibh->b_data);
+	if (gfs2_is_stuffed(ip)) {
+		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + newsize);
+	} else {
+		if (newsize & (u64)(sdp->sd_sb.sb_bsize - 1)) {
+			error = gfs2_block_truncate_page(mapping, newsize);
+			if (error)
+				goto out_brelse;
 		}
+		ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
 	}
 
-	brelse(dibh);
+	i_size_write(inode, newsize);
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+	gfs2_dinode_out(ip, dibh->b_data);
 
+	truncate_pagecache(inode, oldsize, newsize);
+out_brelse:
+	brelse(dibh);
 out:
 	gfs2_trans_end(sdp);
 	return error;
@@ -1123,7 +1050,7 @@
 	if (error)
 		goto out;
 
-	if (!ip->i_disksize) {
+	if (!i_size_read(&ip->i_inode)) {
 		ip->i_height = 0;
 		ip->i_goal = ip->i_no_addr;
 		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
@@ -1143,92 +1070,154 @@
 
 /**
  * do_shrink - make a file smaller
- * @ip: the inode
- * @size: the size to make the file
- * @truncator: function to truncate the last partial block
+ * @inode: the inode
+ * @oldsize: the current inode size
+ * @newsize: the size to make the file
  *
- * Called with an exclusive lock on @ip.
+ * Called with an exclusive lock on @inode. The @size must
+ * be equal to or smaller than the current inode size.
  *
  * Returns: errno
  */
 
-static int do_shrink(struct gfs2_inode *ip, u64 size)
+static int do_shrink(struct inode *inode, u64 oldsize, u64 newsize)
 {
+	struct gfs2_inode *ip = GFS2_I(inode);
 	int error;
 
-	error = trunc_start(ip, size);
+	error = trunc_start(inode, oldsize, newsize);
 	if (error < 0)
 		return error;
-	if (error > 0)
+	if (gfs2_is_stuffed(ip))
 		return 0;
 
-	error = trunc_dealloc(ip, size);
-	if (!error)
+	error = trunc_dealloc(ip, newsize);
+	if (error == 0)
 		error = trunc_end(ip);
 
 	return error;
 }
 
-static int do_touch(struct gfs2_inode *ip, u64 size)
+void gfs2_trim_blocks(struct inode *inode)
 {
-	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+	u64 size = inode->i_size;
+	int ret;
+
+	ret = do_shrink(inode, size, size);
+	WARN_ON(ret != 0);
+}
+
+/**
+ * do_grow - Touch and update inode size
+ * @inode: The inode
+ * @size: The new size
+ *
+ * This function updates the timestamps on the inode and
+ * may also increase the size of the inode. This function
+ * must not be called with @size any smaller than the current
+ * inode size.
+ *
+ * Although it is not strictly required to unstuff files here,
+ * earlier versions of GFS2 have a bug in the stuffed file reading
+ * code which will result in a buffer overrun if the size is larger
+ * than the max stuffed file size. In order to prevent this from
+ * occuring, such files are unstuffed, but in other cases we can
+ * just update the inode size directly.
+ *
+ * Returns: 0 on success, or -ve on error
+ */
+
+static int do_grow(struct inode *inode, u64 size)
+{
+	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_sbd *sdp = GFS2_SB(inode);
 	struct buffer_head *dibh;
+	struct gfs2_alloc *al = NULL;
 	int error;
 
-	error = gfs2_trans_begin(sdp, RES_DINODE, 0);
-	if (error)
-		return error;
+	if (gfs2_is_stuffed(ip) &&
+	    (size > (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)))) {
+		al = gfs2_alloc_get(ip);
+		if (al == NULL)
+			return -ENOMEM;
 
-	down_write(&ip->i_rw_mutex);
+		error = gfs2_quota_lock_check(ip);
+		if (error)
+			goto do_grow_alloc_put;
+
+		al->al_requested = 1;
+		error = gfs2_inplace_reserve(ip);
+		if (error)
+			goto do_grow_qunlock;
+	}
+
+	error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT, 0);
+	if (error)
+		goto do_grow_release;
+
+	if (al) {
+		error = gfs2_unstuff_dinode(ip, NULL);
+		if (error)
+			goto do_end_trans;
+	}
 
 	error = gfs2_meta_inode_buffer(ip, &dibh);
 	if (error)
-		goto do_touch_out;
+		goto do_end_trans;
 
+	i_size_write(inode, size);
 	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
 	brelse(dibh);
 
-do_touch_out:
-	up_write(&ip->i_rw_mutex);
+do_end_trans:
 	gfs2_trans_end(sdp);
+do_grow_release:
+	if (al) {
+		gfs2_inplace_release(ip);
+do_grow_qunlock:
+		gfs2_quota_unlock(ip);
+do_grow_alloc_put:
+		gfs2_alloc_put(ip);
+	}
 	return error;
 }
 
 /**
- * gfs2_truncatei - make a file a given size
- * @ip: the inode
- * @size: the size to make the file
- * @truncator: function to truncate the last partial block
+ * gfs2_setattr_size - make a file a given size
+ * @inode: the inode
+ * @newsize: the size to make the file
  *
- * The file size can grow, shrink, or stay the same size.
+ * The file size can grow, shrink, or stay the same size. This
+ * is called holding i_mutex and an exclusive glock on the inode
+ * in question.
  *
  * Returns: errno
  */
 
-int gfs2_truncatei(struct gfs2_inode *ip, u64 size)
+int gfs2_setattr_size(struct inode *inode, u64 newsize)
 {
-	int error;
+	int ret;
+	u64 oldsize;
 
-	if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_inode.i_mode)))
-		return -EINVAL;
+	BUG_ON(!S_ISREG(inode->i_mode));
 
-	if (size > ip->i_disksize)
-		error = do_grow(ip, size);
-	else if (size < ip->i_disksize)
-		error = do_shrink(ip, size);
-	else
-		/* update time stamps */
-		error = do_touch(ip, size);
+	ret = inode_newsize_ok(inode, newsize);
+	if (ret)
+		return ret;
 
-	return error;
+	oldsize = inode->i_size;
+	if (newsize >= oldsize)
+		return do_grow(inode, newsize);
+
+	return do_shrink(inode, oldsize, newsize);
 }
 
 int gfs2_truncatei_resume(struct gfs2_inode *ip)
 {
 	int error;
-	error = trunc_dealloc(ip, ip->i_disksize);
+	error = trunc_dealloc(ip, i_size_read(&ip->i_inode));
 	if (!error)
 		error = trunc_end(ip);
 	return error;
@@ -1269,7 +1258,7 @@
 
 	shift = sdp->sd_sb.sb_bsize_shift;
 	BUG_ON(gfs2_is_dir(ip));
-	end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift;
+	end_of_file = (i_size_read(&ip->i_inode) + sdp->sd_sb.sb_bsize - 1) >> shift;
 	lblock = offset >> shift;
 	lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
 	if (lblock_stop > end_of_file)
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h
index a20a521..42fea03 100644
--- a/fs/gfs2/bmap.h
+++ b/fs/gfs2/bmap.h
@@ -44,14 +44,16 @@
 	}
 }
 
-int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
-int gfs2_block_map(struct inode *inode, sector_t lblock, struct buffer_head *bh, int create);
-int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen);
-
-int gfs2_truncatei(struct gfs2_inode *ip, u64 size);
-int gfs2_truncatei_resume(struct gfs2_inode *ip);
-int gfs2_file_dealloc(struct gfs2_inode *ip);
-int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
-			      unsigned int len);
+extern int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
+extern int gfs2_block_map(struct inode *inode, sector_t lblock,
+			  struct buffer_head *bh, int create);
+extern int gfs2_extent_map(struct inode *inode, u64 lblock, int *new,
+			   u64 *dblock, unsigned *extlen);
+extern int gfs2_setattr_size(struct inode *inode, u64 size);
+extern void gfs2_trim_blocks(struct inode *inode);
+extern int gfs2_truncatei_resume(struct gfs2_inode *ip);
+extern int gfs2_file_dealloc(struct gfs2_inode *ip);
+extern int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
+				     unsigned int len);
 
 #endif /* __BMAP_DOT_H__ */
diff --git a/fs/gfs2/dentry.c b/fs/gfs2/dentry.c
index bb7907b..6798755 100644
--- a/fs/gfs2/dentry.c
+++ b/fs/gfs2/dentry.c
@@ -49,7 +49,7 @@
 		ip = GFS2_I(inode);
 	}
 
-	if (sdp->sd_args.ar_localcaching)
+	if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
 		goto valid;
 
 	had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index b9dd88a..5c356d0 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -79,6 +79,9 @@
 #define gfs2_disk_hash2offset(h) (((u64)(h)) >> 1)
 #define gfs2_dir_offset2hash(p) ((u32)(((u64)(p)) << 1))
 
+struct qstr gfs2_qdot __read_mostly;
+struct qstr gfs2_qdotdot __read_mostly;
+
 typedef int (*leaf_call_t) (struct gfs2_inode *dip, u32 index, u32 len,
 			    u64 leaf_no, void *data);
 typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent,
@@ -127,8 +130,8 @@
 
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
-	if (ip->i_disksize < offset + size)
-		ip->i_disksize = offset + size;
+	if (ip->i_inode.i_size < offset + size)
+		i_size_write(&ip->i_inode, offset + size);
 	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 	gfs2_dinode_out(ip, dibh->b_data);
 
@@ -225,8 +228,8 @@
 	if (error)
 		return error;
 
-	if (ip->i_disksize < offset + copied)
-		ip->i_disksize = offset + copied;
+	if (ip->i_inode.i_size < offset + copied)
+		i_size_write(&ip->i_inode, offset + copied);
 	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
@@ -275,12 +278,13 @@
 	unsigned int o;
 	int copied = 0;
 	int error = 0;
+	u64 disksize = i_size_read(&ip->i_inode);
 
-	if (offset >= ip->i_disksize)
+	if (offset >= disksize)
 		return 0;
 
-	if (offset + size > ip->i_disksize)
-		size = ip->i_disksize - offset;
+	if (offset + size > disksize)
+		size = disksize - offset;
 
 	if (!size)
 		return 0;
@@ -727,7 +731,7 @@
 		unsigned hsize = 1 << ip->i_depth;
 		unsigned index;
 		u64 ln;
-		if (hsize * sizeof(u64) != ip->i_disksize) {
+		if (hsize * sizeof(u64) != i_size_read(inode)) {
 			gfs2_consist_inode(ip);
 			return ERR_PTR(-EIO);
 		}
@@ -879,7 +883,7 @@
 	for (x = sdp->sd_hash_ptrs; x--; lp++)
 		*lp = cpu_to_be64(bn);
 
-	dip->i_disksize = sdp->sd_sb.sb_bsize / 2;
+	i_size_write(inode, sdp->sd_sb.sb_bsize / 2);
 	gfs2_add_inode_blocks(&dip->i_inode, 1);
 	dip->i_diskflags |= GFS2_DIF_EXHASH;
 
@@ -1057,11 +1061,12 @@
 	u64 *buf;
 	u64 *from, *to;
 	u64 block;
+	u64 disksize = i_size_read(&dip->i_inode);
 	int x;
 	int error = 0;
 
 	hsize = 1 << dip->i_depth;
-	if (hsize * sizeof(u64) != dip->i_disksize) {
+	if (hsize * sizeof(u64) != disksize) {
 		gfs2_consist_inode(dip);
 		return -EIO;
 	}
@@ -1072,7 +1077,7 @@
 	if (!buf)
 		return -ENOMEM;
 
-	for (block = dip->i_disksize >> sdp->sd_hash_bsize_shift; block--;) {
+	for (block = disksize >> sdp->sd_hash_bsize_shift; block--;) {
 		error = gfs2_dir_read_data(dip, (char *)buf,
 					    block * sdp->sd_hash_bsize,
 					    sdp->sd_hash_bsize, 1);
@@ -1370,7 +1375,7 @@
 	unsigned depth = 0;
 
 	hsize = 1 << dip->i_depth;
-	if (hsize * sizeof(u64) != dip->i_disksize) {
+	if (hsize * sizeof(u64) != i_size_read(inode)) {
 		gfs2_consist_inode(dip);
 		return -EIO;
 	}
@@ -1784,7 +1789,7 @@
 	int error = 0;
 
 	hsize = 1 << dip->i_depth;
-	if (hsize * sizeof(u64) != dip->i_disksize) {
+	if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) {
 		gfs2_consist_inode(dip);
 		return -EIO;
 	}
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index 4f91944..a98f644 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -17,23 +17,24 @@
 struct gfs2_inode;
 struct gfs2_inum;
 
-struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *filename);
-int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
-		   const struct gfs2_inode *ip);
-int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
-		 const struct gfs2_inode *ip, unsigned int type);
-int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
-int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
-		  filldir_t filldir);
-int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
-		   const struct gfs2_inode *nip, unsigned int new_type);
+extern struct inode *gfs2_dir_search(struct inode *dir,
+				     const struct qstr *filename);
+extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
+			  const struct gfs2_inode *ip);
+extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
+			const struct gfs2_inode *ip, unsigned int type);
+extern int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
+extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
+			 filldir_t filldir);
+extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
+			  const struct gfs2_inode *nip, unsigned int new_type);
 
-int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
+extern int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
 
-int gfs2_diradd_alloc_required(struct inode *dir,
-			       const struct qstr *filename);
-int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
-			    struct buffer_head **bhp);
+extern int gfs2_diradd_alloc_required(struct inode *dir,
+				      const struct qstr *filename);
+extern int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
+				   struct buffer_head **bhp);
 
 static inline u32 gfs2_disk_hash(const char *data, int len)
 {
@@ -61,4 +62,7 @@
 	memcpy(dent + 1, name->name, name->len);
 }
 
+extern struct qstr gfs2_qdot;
+extern struct qstr gfs2_qdotdot;
+
 #endif /* __DIR_DOT_H__ */
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c
index dfe237a..06d5827 100644
--- a/fs/gfs2/export.c
+++ b/fs/gfs2/export.c
@@ -126,16 +126,9 @@
 
 static struct dentry *gfs2_get_parent(struct dentry *child)
 {
-	struct qstr dotdot;
 	struct dentry *dentry;
 
-	/*
-	 * XXX(hch): it would be a good idea to keep this around as a
-	 *	     static variable.
-	 */
-	gfs2_str2qstr(&dotdot, "..");
-
-	dentry = d_obtain_alias(gfs2_lookupi(child->d_inode, &dotdot, 1));
+	dentry = d_obtain_alias(gfs2_lookupi(child->d_inode, &gfs2_qdotdot, 1));
 	if (!IS_ERR(dentry))
 		dentry->d_op = &gfs2_dops;
 	return dentry;
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 4edd662..aa99647 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -382,8 +382,10 @@
 	rblocks = RES_DINODE + ind_blocks;
 	if (gfs2_is_jdata(ip))
 		rblocks += data_blocks ? data_blocks : 1;
-	if (ind_blocks || data_blocks)
+	if (ind_blocks || data_blocks) {
 		rblocks += RES_STATFS + RES_QUOTA;
+		rblocks += gfs2_rg_blocks(al);
+	}
 	ret = gfs2_trans_begin(sdp, rblocks, 0);
 	if (ret)
 		goto out_trans_fail;
@@ -491,7 +493,7 @@
 			goto fail;
 
 		if (!(file->f_flags & O_LARGEFILE) &&
-		    ip->i_disksize > MAX_NON_LFS) {
+		    i_size_read(inode) > MAX_NON_LFS) {
 			error = -EOVERFLOW;
 			goto fail_gunlock;
 		}
@@ -620,6 +622,8 @@
  * cluster; until we do, disable leases (by just returning -EINVAL),
  * unless the administrator has requested purely local locking.
  *
+ * Locking: called under lock_flocks
+ *
  * Returns: errno
  */
 
@@ -771,6 +775,7 @@
 	.fsync		= gfs2_fsync,
 	.lock		= gfs2_lock,
 	.flock		= gfs2_flock,
+	.llseek		= default_llseek,
 };
 
 #endif /* CONFIG_GFS2_FS_LOCKING_DLM */
@@ -797,5 +802,6 @@
 	.open		= gfs2_open,
 	.release	= gfs2_close,
 	.fsync		= gfs2_fsync,
+	.llseek		= default_llseek,
 };
 
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 9adf8f9..8777885 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -441,6 +441,8 @@
 		else
 			gfs2_glock_put_nolock(gl);
 	}
+	if (held1 && held2 && list_empty(&gl->gl_holders))
+		clear_bit(GLF_QUEUED, &gl->gl_flags);
 
 	gl->gl_state = new_state;
 	gl->gl_tchange = jiffies;
@@ -1012,6 +1014,7 @@
 		if (unlikely((gh->gh_flags & LM_FLAG_PRIORITY) && !insert_pt))
 			insert_pt = &gh2->gh_list;
 	}
+	set_bit(GLF_QUEUED, &gl->gl_flags);
 	if (likely(insert_pt == NULL)) {
 		list_add_tail(&gh->gh_list, &gl->gl_holders);
 		if (unlikely(gh->gh_flags & LM_FLAG_PRIORITY))
@@ -1310,10 +1313,12 @@
 
 	gfs2_glock_hold(gl);
 	holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time;
-	if (time_before(now, holdtime))
-		delay = holdtime - now;
-	if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
-		delay = gl->gl_ops->go_min_hold_time;
+	if (test_bit(GLF_QUEUED, &gl->gl_flags)) {
+		if (time_before(now, holdtime))
+			delay = holdtime - now;
+		if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
+			delay = gl->gl_ops->go_min_hold_time;
+	}
 
 	spin_lock(&gl->gl_spin);
 	handle_callback(gl, state, delay);
@@ -1512,7 +1517,7 @@
 	spin_unlock(&lru_lock);
 
 	spin_lock(&gl->gl_spin);
-	if (find_first_holder(gl) == NULL && gl->gl_state != LM_ST_UNLOCKED)
+	if (gl->gl_state != LM_ST_UNLOCKED)
 		handle_callback(gl, LM_ST_UNLOCKED, 0);
 	spin_unlock(&gl->gl_spin);
 	gfs2_glock_hold(gl);
@@ -1660,6 +1665,8 @@
 		*p++ = 'I';
 	if (test_bit(GLF_FROZEN, gflags))
 		*p++ = 'F';
+	if (test_bit(GLF_QUEUED, gflags))
+		*p++ = 'q';
 	*p = 0;
 	return buf;
 }
@@ -1776,10 +1783,12 @@
 	}
 #endif
 
-	glock_workqueue = create_workqueue("glock_workqueue");
+	glock_workqueue = alloc_workqueue("glock_workqueue", WQ_RESCUER |
+					  WQ_HIGHPRI | WQ_FREEZEABLE, 0);
 	if (IS_ERR(glock_workqueue))
 		return PTR_ERR(glock_workqueue);
-	gfs2_delete_workqueue = create_workqueue("delete_workqueue");
+	gfs2_delete_workqueue = alloc_workqueue("delete_workqueue", WQ_RESCUER |
+						WQ_FREEZEABLE, 0);
 	if (IS_ERR(gfs2_delete_workqueue)) {
 		destroy_workqueue(glock_workqueue);
 		return PTR_ERR(gfs2_delete_workqueue);
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 2bda191..db1c26d 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -215,7 +215,7 @@
 void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...);
 
 /**
- * gfs2_glock_nq_init - intialize a holder and enqueue it on a glock
+ * gfs2_glock_nq_init - initialize a holder and enqueue it on a glock
  * @gl: the glock
  * @state: the state we're requesting
  * @flags: the modifier flags
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 49f97d3..0d149dc 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -262,13 +262,12 @@
 	const struct gfs2_inode *ip = gl->gl_object;
 	if (ip == NULL)
 		return 0;
-	gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%02lx d:0x%08x s:%llu/%llu\n",
+	gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%02lx d:0x%08x s:%llu\n",
 		  (unsigned long long)ip->i_no_formal_ino,
 		  (unsigned long long)ip->i_no_addr,
 		  IF2DT(ip->i_inode.i_mode), ip->i_flags,
 		  (unsigned int)ip->i_diskflags,
-		  (unsigned long long)ip->i_inode.i_size,
-		  (unsigned long long)ip->i_disksize);
+		  (unsigned long long)i_size_read(&ip->i_inode));
 	return 0;
 }
 
@@ -453,7 +452,6 @@
 	[LM_TYPE_META] = &gfs2_meta_glops,
 	[LM_TYPE_INODE] = &gfs2_inode_glops,
 	[LM_TYPE_RGRP] = &gfs2_rgrp_glops,
-	[LM_TYPE_NONDISK] = &gfs2_trans_glops,
 	[LM_TYPE_IOPEN] = &gfs2_iopen_glops,
 	[LM_TYPE_FLOCK] = &gfs2_flock_glops,
 	[LM_TYPE_NONDISK] = &gfs2_nondisk_glops,
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index fdbf4b3..764fbb4 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -196,6 +196,7 @@
 	GLF_REPLY_PENDING		= 9,
 	GLF_INITIAL			= 10,
 	GLF_FROZEN			= 11,
+	GLF_QUEUED			= 12,
 };
 
 struct gfs2_glock {
@@ -267,7 +268,6 @@
 	u64 i_no_formal_ino;
 	u64 i_generation;
 	u64 i_eattr;
-	loff_t i_disksize;
 	unsigned long i_flags;		/* GIF_... */
 	struct gfs2_glock *i_gl; /* Move into i_gh? */
 	struct gfs2_holder i_iopen_gh;
@@ -416,11 +416,8 @@
 	char ar_locktable[GFS2_LOCKNAME_LEN];	/* Name of the Lock Table */
 	char ar_hostdata[GFS2_LOCKNAME_LEN];	/* Host specific data */
 	unsigned int ar_spectator:1;		/* Don't get a journal */
-	unsigned int ar_ignore_local_fs:1;	/* Ignore optimisations */
 	unsigned int ar_localflocks:1;		/* Let the VFS do flock|fcntl */
-	unsigned int ar_localcaching:1;		/* Local caching */
 	unsigned int ar_debug:1;		/* Oops on errors */
-	unsigned int ar_upgrade:1;		/* Upgrade ondisk format */
 	unsigned int ar_posix_acl:1;		/* Enable posix acls */
 	unsigned int ar_quota:2;		/* off/account/on */
 	unsigned int ar_suiddir:1;		/* suiddir support */
@@ -497,7 +494,7 @@
  */
 
 struct lm_lockstruct {
-	unsigned int ls_jid;
+	int ls_jid;
 	unsigned int ls_first;
 	unsigned int ls_first_done;
 	unsigned int ls_nodir;
@@ -572,6 +569,7 @@
 	struct list_head sd_rindex_mru_list;
 	struct gfs2_rgrpd *sd_rindex_forward;
 	unsigned int sd_rgrps;
+	unsigned int sd_max_rg_data;
 
 	/* Journal index stuff */
 
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 08140f1..06370f8 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -359,8 +359,7 @@
 	 * to do that.
 	 */
 	ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink);
-	ip->i_disksize = be64_to_cpu(str->di_size);
-	i_size_write(&ip->i_inode, ip->i_disksize);
+	i_size_write(&ip->i_inode, be64_to_cpu(str->di_size));
 	gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
 	atime.tv_sec = be64_to_cpu(str->di_atime);
 	atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
@@ -1055,7 +1054,7 @@
 	str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
 	str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
 	str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
-	str->di_size = cpu_to_be64(ip->i_disksize);
+	str->di_size = cpu_to_be64(i_size_read(&ip->i_inode));
 	str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
 	str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
 	str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
@@ -1085,8 +1084,8 @@
 	       (unsigned long long)ip->i_no_formal_ino);
 	printk(KERN_INFO "  no_addr = %llu\n",
 	       (unsigned long long)ip->i_no_addr);
-	printk(KERN_INFO "  i_disksize = %llu\n",
-	       (unsigned long long)ip->i_disksize);
+	printk(KERN_INFO "  i_size = %llu\n",
+	       (unsigned long long)i_size_read(&ip->i_inode));
 	printk(KERN_INFO "  blocks = %llu\n",
 	       (unsigned long long)gfs2_get_inode_blocks(&ip->i_inode));
 	printk(KERN_INFO "  i_goal = %llu\n",
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index 300ada3..6720d7d 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -19,6 +19,8 @@
 extern int gfs2_internal_read(struct gfs2_inode *ip,
 			      struct file_ra_state *ra_state,
 			      char *buf, loff_t *pos, unsigned size);
+extern void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
+				   unsigned int from, unsigned int to);
 extern void gfs2_set_aops(struct inode *inode);
 
 static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
@@ -80,6 +82,19 @@
 	dent->de_inum.no_addr = cpu_to_be64(ip->i_no_addr);
 }
 
+static inline int gfs2_check_internal_file_size(struct inode *inode,
+						u64 minsize, u64 maxsize)
+{
+	u64 size = i_size_read(inode);
+	if (size < minsize || size > maxsize)
+		goto err;
+	if (size & ((1 << inode->i_blkbits) - 1))
+		goto err;
+	return 0;
+err:
+	gfs2_consist_inode(GFS2_I(inode));
+	return -EIO;
+}
 
 extern void gfs2_set_iop(struct inode *inode);
 extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, 
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index 0e0470e..1c09425 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -42,9 +42,9 @@
 		ret |= LM_OUT_CANCELED;
 		goto out;
 	case -EAGAIN: /* Try lock fails */
+	case -EDEADLK: /* Deadlock detected */
 		goto out;
-	case -EINVAL: /* Invalid */
-	case -ENOMEM: /* Out of memory */
+	case -ETIMEDOUT: /* Canceled due to timeout */
 		ret |= LM_OUT_ERROR;
 		goto out;
 	case 0: /* Success */
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index ac750bd..eb01f35 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -592,22 +592,13 @@
 	lh->lh_hash = cpu_to_be32(hash);
 
 	bh->b_end_io = end_buffer_write_sync;
-	if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags))
-		goto skip_barrier;
 	get_bh(bh);
-	submit_bh(WRITE_BARRIER | REQ_META, bh);
-	wait_on_buffer(bh);
-	if (buffer_eopnotsupp(bh)) {
-		clear_buffer_eopnotsupp(bh);
-		set_buffer_uptodate(bh);
-		fs_info(sdp, "barrier sync failed - disabling barriers\n");
-		set_bit(SDF_NOBARRIERS, &sdp->sd_flags);
-		lock_buffer(bh);
-skip_barrier:
-		get_bh(bh);
+	if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags))
 		submit_bh(WRITE_SYNC | REQ_META, bh);
-		wait_on_buffer(bh);
-	}
+	else
+		submit_bh(WRITE_FLUSH_FUA | REQ_META, bh);
+	wait_on_buffer(bh);
+
 	if (!buffer_uptodate(bh))
 		gfs2_io_error_bh(sdp, bh);
 	brelse(bh);
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index b1e9630..ebef7ab 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -24,6 +24,7 @@
 #include "glock.h"
 #include "quota.h"
 #include "recovery.h"
+#include "dir.h"
 
 static struct shrinker qd_shrinker = {
 	.shrink = gfs2_shrink_qd_memory,
@@ -78,6 +79,9 @@
 {
 	int error;
 
+	gfs2_str2qstr(&gfs2_qdot, ".");
+	gfs2_str2qstr(&gfs2_qdotdot, "..");
+
 	error = gfs2_sys_init();
 	if (error)
 		return error;
@@ -140,7 +144,7 @@
 
 	error = -ENOMEM;
 	gfs_recovery_wq = alloc_workqueue("gfs_recovery",
-					  WQ_NON_REENTRANT | WQ_RESCUER, 0);
+					  WQ_MEM_RECLAIM | WQ_FREEZEABLE, 0);
 	if (!gfs_recovery_wq)
 		goto fail_wq;
 
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 4d4b1e8..aeafc23 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -38,14 +38,6 @@
 #define DO 0
 #define UNDO 1
 
-static const u32 gfs2_old_fs_formats[] = {
-        0
-};
-
-static const u32 gfs2_old_multihost_formats[] = {
-        0
-};
-
 /**
  * gfs2_tune_init - Fill a gfs2_tune structure with default values
  * @gt: tune
@@ -135,8 +127,6 @@
 
 static int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent)
 {
-	unsigned int x;
-
 	if (sb->sb_magic != GFS2_MAGIC ||
 	    sb->sb_type != GFS2_METATYPE_SB) {
 		if (!silent)
@@ -150,55 +140,9 @@
 	    sb->sb_multihost_format == GFS2_FORMAT_MULTI)
 		return 0;
 
-	if (sb->sb_fs_format != GFS2_FORMAT_FS) {
-		for (x = 0; gfs2_old_fs_formats[x]; x++)
-			if (gfs2_old_fs_formats[x] == sb->sb_fs_format)
-				break;
+	fs_warn(sdp, "Unknown on-disk format, unable to mount\n");
 
-		if (!gfs2_old_fs_formats[x]) {
-			printk(KERN_WARNING
-			       "GFS2: code version (%u, %u) is incompatible "
-			       "with ondisk format (%u, %u)\n",
-			       GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
-			       sb->sb_fs_format, sb->sb_multihost_format);
-			printk(KERN_WARNING
-			       "GFS2: I don't know how to upgrade this FS\n");
-			return -EINVAL;
-		}
-	}
-
-	if (sb->sb_multihost_format != GFS2_FORMAT_MULTI) {
-		for (x = 0; gfs2_old_multihost_formats[x]; x++)
-			if (gfs2_old_multihost_formats[x] ==
-			    sb->sb_multihost_format)
-				break;
-
-		if (!gfs2_old_multihost_formats[x]) {
-			printk(KERN_WARNING
-			       "GFS2: code version (%u, %u) is incompatible "
-			       "with ondisk format (%u, %u)\n",
-			       GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
-			       sb->sb_fs_format, sb->sb_multihost_format);
-			printk(KERN_WARNING
-			       "GFS2: I don't know how to upgrade this FS\n");
-			return -EINVAL;
-		}
-	}
-
-	if (!sdp->sd_args.ar_upgrade) {
-		printk(KERN_WARNING
-		       "GFS2: code version (%u, %u) is incompatible "
-		       "with ondisk format (%u, %u)\n",
-		       GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
-		       sb->sb_fs_format, sb->sb_multihost_format);
-		printk(KERN_INFO
-		       "GFS2: Use the \"upgrade\" mount option to upgrade "
-		       "the FS\n");
-		printk(KERN_INFO "GFS2: See the manual for more details\n");
-		return -EINVAL;
-	}
-
-	return 0;
+	return -EINVAL;
 }
 
 static void end_bio_io_page(struct bio *bio, int error)
@@ -586,7 +530,7 @@
 
 	prev_db = 0;
 
-	for (lb = 0; lb < ip->i_disksize >> sdp->sd_sb.sb_bsize_shift; lb++) {
+	for (lb = 0; lb < i_size_read(jd->jd_inode) >> sdp->sd_sb.sb_bsize_shift; lb++) {
 		bh.b_state = 0;
 		bh.b_blocknr = 0;
 		bh.b_size = 1 << ip->i_inode.i_blkbits;
@@ -1022,7 +966,6 @@
 	if (!strcmp("lock_nolock", proto)) {
 		lm = &nolock_ops;
 		sdp->sd_args.ar_localflocks = 1;
-		sdp->sd_args.ar_localcaching = 1;
 #ifdef CONFIG_GFS2_FS_LOCKING_DLM
 	} else if (!strcmp("lock_dlm", proto)) {
 		lm = &gfs2_dlm_ops;
@@ -1113,8 +1056,6 @@
 
 static int wait_on_journal(struct gfs2_sbd *sdp)
 {
-	if (sdp->sd_args.ar_spectator)
-		return 0;
 	if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
 		return 0;
 
@@ -1217,6 +1158,20 @@
 	if (error)
 		goto fail_sb;
 
+	/*
+	 * If user space has failed to join the cluster or some similar
+	 * failure has occurred, then the journal id will contain a
+	 * negative (error) number. This will then be returned to the
+	 * caller (of the mount syscall). We do this even for spectator
+	 * mounts (which just write a jid of 0 to indicate "ok" even though
+	 * the jid is unused in the spectator case)
+	 */
+	if (sdp->sd_lockstruct.ls_jid < 0) {
+		error = sdp->sd_lockstruct.ls_jid;
+		sdp->sd_lockstruct.ls_jid = 0;
+		goto fail_sb;
+	}
+
 	error = init_inodes(sdp, DO);
 	if (error)
 		goto fail_sb;
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index 1009be2..0534510 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -18,6 +18,8 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
 #include <linux/fiemap.h>
+#include <linux/swap.h>
+#include <linux/falloc.h>
 #include <asm/uaccess.h>
 
 #include "gfs2.h"
@@ -217,7 +219,7 @@
 			goto out_gunlock_q;
 
 		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
-					 al->al_rgd->rd_length +
+					 gfs2_rg_blocks(al) +
 					 2 * RES_DINODE + RES_STATFS +
 					 RES_QUOTA, 0);
 		if (error)
@@ -406,7 +408,6 @@
 
 	ip = ghs[1].gh_gl->gl_object;
 
-	ip->i_disksize = size;
 	i_size_write(inode, size);
 
 	error = gfs2_meta_inode_buffer(ip, &dibh);
@@ -461,7 +462,7 @@
 	ip = ghs[1].gh_gl->gl_object;
 
 	ip->i_inode.i_nlink = 2;
-	ip->i_disksize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
+	i_size_write(inode, sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode));
 	ip->i_diskflags |= GFS2_DIF_JDATA;
 	ip->i_entries = 2;
 
@@ -470,18 +471,15 @@
 	if (!gfs2_assert_withdraw(sdp, !error)) {
 		struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
 		struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1);
-		struct qstr str;
 
-		gfs2_str2qstr(&str, ".");
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-		gfs2_qstr2dirent(&str, GFS2_DIRENT_SIZE(str.len), dent);
+		gfs2_qstr2dirent(&gfs2_qdot, GFS2_DIRENT_SIZE(gfs2_qdot.len), dent);
 		dent->de_inum = di->di_num; /* already GFS2 endian */
 		dent->de_type = cpu_to_be16(DT_DIR);
 		di->di_entries = cpu_to_be32(1);
 
-		gfs2_str2qstr(&str, "..");
 		dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
-		gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
+		gfs2_qstr2dirent(&gfs2_qdotdot, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
 
 		gfs2_inum_out(dip, dent);
 		dent->de_type = cpu_to_be16(DT_DIR);
@@ -522,7 +520,6 @@
 static int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
 		       struct gfs2_inode *ip)
 {
-	struct qstr dotname;
 	int error;
 
 	if (ip->i_entries != 2) {
@@ -539,13 +536,11 @@
 	if (error)
 		return error;
 
-	gfs2_str2qstr(&dotname, ".");
-	error = gfs2_dir_del(ip, &dotname);
+	error = gfs2_dir_del(ip, &gfs2_qdot);
 	if (error)
 		return error;
 
-	gfs2_str2qstr(&dotname, "..");
-	error = gfs2_dir_del(ip, &dotname);
+	error = gfs2_dir_del(ip, &gfs2_qdotdot);
 	if (error)
 		return error;
 
@@ -694,11 +689,8 @@
 	struct inode *dir = &to->i_inode;
 	struct super_block *sb = dir->i_sb;
 	struct inode *tmp;
-	struct qstr dotdot;
 	int error = 0;
 
-	gfs2_str2qstr(&dotdot, "..");
-
 	igrab(dir);
 
 	for (;;) {
@@ -711,7 +703,7 @@
 			break;
 		}
 
-		tmp = gfs2_lookupi(dir, &dotdot, 1);
+		tmp = gfs2_lookupi(dir, &gfs2_qdotdot, 1);
 		if (IS_ERR(tmp)) {
 			error = PTR_ERR(tmp);
 			break;
@@ -744,7 +736,7 @@
 	struct gfs2_inode *ip = GFS2_I(odentry->d_inode);
 	struct gfs2_inode *nip = NULL;
 	struct gfs2_sbd *sdp = GFS2_SB(odir);
-	struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, };
+	struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, }, ri_gh;
 	struct gfs2_rgrpd *nrgd;
 	unsigned int num_gh;
 	int dir_rename = 0;
@@ -758,6 +750,9 @@
 			return 0;
 	}
 
+	error = gfs2_rindex_hold(sdp, &ri_gh);
+	if (error)
+		return error;
 
 	if (odip != ndip) {
 		error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE,
@@ -887,12 +882,12 @@
 
 		al->al_requested = sdp->sd_max_dirres;
 
-		error = gfs2_inplace_reserve(ndip);
+		error = gfs2_inplace_reserve_ri(ndip);
 		if (error)
 			goto out_gunlock_q;
 
 		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
-					 al->al_rgd->rd_length +
+					 gfs2_rg_blocks(al) +
 					 4 * RES_DINODE + 4 * RES_LEAF +
 					 RES_STATFS + RES_QUOTA + 4, 0);
 		if (error)
@@ -920,9 +915,6 @@
 	}
 
 	if (dir_rename) {
-		struct qstr name;
-		gfs2_str2qstr(&name, "..");
-
 		error = gfs2_change_nlink(ndip, +1);
 		if (error)
 			goto out_end_trans;
@@ -930,7 +922,7 @@
 		if (error)
 			goto out_end_trans;
 
-		error = gfs2_dir_mvino(ip, &name, ndip, DT_DIR);
+		error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR);
 		if (error)
 			goto out_end_trans;
 	} else {
@@ -972,6 +964,7 @@
 	if (r_gh.gh_gl)
 		gfs2_glock_dq_uninit(&r_gh);
 out:
+	gfs2_glock_dq_uninit(&ri_gh);
 	return error;
 }
 
@@ -990,7 +983,7 @@
 	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
 	struct gfs2_holder i_gh;
 	struct buffer_head *dibh;
-	unsigned int x;
+	unsigned int x, size;
 	char *buf;
 	int error;
 
@@ -1002,7 +995,8 @@
 		return NULL;
 	}
 
-	if (!ip->i_disksize) {
+	size = (unsigned int)i_size_read(&ip->i_inode);
+	if (size == 0) {
 		gfs2_consist_inode(ip);
 		buf = ERR_PTR(-EIO);
 		goto out;
@@ -1014,7 +1008,7 @@
 		goto out;
 	}
 
-	x = ip->i_disksize + 1;
+	x = size + 1;
 	buf = kmalloc(x, GFP_NOFS);
 	if (!buf)
 		buf = ERR_PTR(-ENOMEM);
@@ -1071,30 +1065,6 @@
 	return error;
 }
 
-/*
- * XXX(truncate): the truncate_setsize calls should be moved to the end.
- */
-static int setattr_size(struct inode *inode, struct iattr *attr)
-{
-	struct gfs2_inode *ip = GFS2_I(inode);
-	struct gfs2_sbd *sdp = GFS2_SB(inode);
-	int error;
-
-	if (attr->ia_size != ip->i_disksize) {
-		error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
-		if (error)
-			return error;
-		truncate_setsize(inode, attr->ia_size);
-		gfs2_trans_end(sdp);
-	}
-
-	error = gfs2_truncatei(ip, attr->ia_size);
-	if (error && (inode->i_size != ip->i_disksize))
-		i_size_write(inode, ip->i_disksize);
-
-	return error;
-}
-
 static int setattr_chown(struct inode *inode, struct iattr *attr)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
@@ -1195,7 +1165,7 @@
 		goto out;
 
 	if (attr->ia_valid & ATTR_SIZE)
-		error = setattr_size(inode, attr);
+		error = gfs2_setattr_size(inode, attr->ia_size);
 	else if (attr->ia_valid & (ATTR_UID | ATTR_GID))
 		error = setattr_chown(inode, attr);
 	else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode))
@@ -1301,6 +1271,257 @@
 	return ret;
 }
 
+static void empty_write_end(struct page *page, unsigned from,
+			   unsigned to)
+{
+	struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+
+	page_zero_new_buffers(page, from, to);
+	flush_dcache_page(page);
+	mark_page_accessed(page);
+
+	if (!gfs2_is_writeback(ip))
+		gfs2_page_add_databufs(ip, page, from, to);
+
+	block_commit_write(page, from, to);
+}
+
+
+static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
+{
+	unsigned start, end, next;
+	struct buffer_head *bh, *head;
+	int error;
+
+	if (!page_has_buffers(page)) {
+		error = block_prepare_write(page, from, to, gfs2_block_map);
+		if (unlikely(error))
+			return error;
+
+		empty_write_end(page, from, to);
+		return 0;
+	}
+
+	bh = head = page_buffers(page);
+	next = end = 0;
+	while (next < from) {
+		next += bh->b_size;
+		bh = bh->b_this_page;
+	}
+	start = next;
+	do {
+		next += bh->b_size;
+		if (buffer_mapped(bh)) {
+			if (end) {
+				error = block_prepare_write(page, start, end,
+							    gfs2_block_map);
+				if (unlikely(error))
+					return error;
+				empty_write_end(page, start, end);
+				end = 0;
+			}
+			start = next;
+		}
+		else
+			end = next;
+		bh = bh->b_this_page;
+	} while (next < to);
+
+	if (end) {
+		error = block_prepare_write(page, start, end, gfs2_block_map);
+		if (unlikely(error))
+			return error;
+		empty_write_end(page, start, end);
+	}
+
+	return 0;
+}
+
+static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
+			   int mode)
+{
+	struct gfs2_inode *ip = GFS2_I(inode);
+	struct buffer_head *dibh;
+	int error;
+	u64 start = offset >> PAGE_CACHE_SHIFT;
+	unsigned int start_offset = offset & ~PAGE_CACHE_MASK;
+	u64 end = (offset + len - 1) >> PAGE_CACHE_SHIFT;
+	pgoff_t curr;
+	struct page *page;
+	unsigned int end_offset = (offset + len) & ~PAGE_CACHE_MASK;
+	unsigned int from, to;
+
+	if (!end_offset)
+		end_offset = PAGE_CACHE_SIZE;
+
+	error = gfs2_meta_inode_buffer(ip, &dibh);
+	if (unlikely(error))
+		goto out;
+
+	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+
+	if (gfs2_is_stuffed(ip)) {
+		error = gfs2_unstuff_dinode(ip, NULL);
+		if (unlikely(error))
+			goto out;
+	}
+
+	curr = start;
+	offset = start << PAGE_CACHE_SHIFT;
+	from = start_offset;
+	to = PAGE_CACHE_SIZE;
+	while (curr <= end) {
+		page = grab_cache_page_write_begin(inode->i_mapping, curr,
+						   AOP_FLAG_NOFS);
+		if (unlikely(!page)) {
+			error = -ENOMEM;
+			goto out;
+		}
+
+		if (curr == end)
+			to = end_offset;
+		error = write_empty_blocks(page, from, to);
+		if (!error && offset + to > inode->i_size &&
+		    !(mode & FALLOC_FL_KEEP_SIZE)) {
+			i_size_write(inode, offset + to);
+		}
+		unlock_page(page);
+		page_cache_release(page);
+		if (error)
+			goto out;
+		curr++;
+		offset += PAGE_CACHE_SIZE;
+		from = 0;
+	}
+
+	gfs2_dinode_out(ip, dibh->b_data);
+	mark_inode_dirty(inode);
+
+	brelse(dibh);
+
+out:
+	return error;
+}
+
+static void calc_max_reserv(struct gfs2_inode *ip, loff_t max, loff_t *len,
+			    unsigned int *data_blocks, unsigned int *ind_blocks)
+{
+	const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+	unsigned int max_blocks = ip->i_alloc->al_rgd->rd_free_clone;
+	unsigned int tmp, max_data = max_blocks - 3 * (sdp->sd_max_height - 1);
+
+	for (tmp = max_data; tmp > sdp->sd_diptrs;) {
+		tmp = DIV_ROUND_UP(tmp, sdp->sd_inptrs);
+		max_data -= tmp;
+	}
+	/* This calculation isn't the exact reverse of gfs2_write_calc_reserve,
+	   so it might end up with fewer data blocks */
+	if (max_data <= *data_blocks)
+		return;
+	*data_blocks = max_data;
+	*ind_blocks = max_blocks - max_data;
+	*len = ((loff_t)max_data - 3) << sdp->sd_sb.sb_bsize_shift;
+	if (*len > max) {
+		*len = max;
+		gfs2_write_calc_reserv(ip, max, data_blocks, ind_blocks);
+	}
+}
+
+static long gfs2_fallocate(struct inode *inode, int mode, loff_t offset,
+			   loff_t len)
+{
+	struct gfs2_sbd *sdp = GFS2_SB(inode);
+	struct gfs2_inode *ip = GFS2_I(inode);
+	unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
+	loff_t bytes, max_bytes;
+	struct gfs2_alloc *al;
+	int error;
+	loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift;
+	next = (next + 1) << sdp->sd_sb.sb_bsize_shift;
+
+	offset = (offset >> sdp->sd_sb.sb_bsize_shift) <<
+		 sdp->sd_sb.sb_bsize_shift;
+
+	len = next - offset;
+	bytes = sdp->sd_max_rg_data * sdp->sd_sb.sb_bsize / 2;
+	if (!bytes)
+		bytes = UINT_MAX;
+
+	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
+	error = gfs2_glock_nq(&ip->i_gh);
+	if (unlikely(error))
+		goto out_uninit;
+
+	if (!gfs2_write_alloc_required(ip, offset, len))
+		goto out_unlock;
+
+	while (len > 0) {
+		if (len < bytes)
+			bytes = len;
+		al = gfs2_alloc_get(ip);
+		if (!al) {
+			error = -ENOMEM;
+			goto out_unlock;
+		}
+
+		error = gfs2_quota_lock_check(ip);
+		if (error)
+			goto out_alloc_put;
+
+retry:
+		gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
+
+		al->al_requested = data_blocks + ind_blocks;
+		error = gfs2_inplace_reserve(ip);
+		if (error) {
+			if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) {
+				bytes >>= 1;
+				goto retry;
+			}
+			goto out_qunlock;
+		}
+		max_bytes = bytes;
+		calc_max_reserv(ip, len, &max_bytes, &data_blocks, &ind_blocks);
+		al->al_requested = data_blocks + ind_blocks;
+
+		rblocks = RES_DINODE + ind_blocks + RES_STATFS + RES_QUOTA +
+			  RES_RG_HDR + gfs2_rg_blocks(al);
+		if (gfs2_is_jdata(ip))
+			rblocks += data_blocks ? data_blocks : 1;
+
+		error = gfs2_trans_begin(sdp, rblocks,
+					 PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize);
+		if (error)
+			goto out_trans_fail;
+
+		error = fallocate_chunk(inode, offset, max_bytes, mode);
+		gfs2_trans_end(sdp);
+
+		if (error)
+			goto out_trans_fail;
+
+		len -= max_bytes;
+		offset += max_bytes;
+		gfs2_inplace_release(ip);
+		gfs2_quota_unlock(ip);
+		gfs2_alloc_put(ip);
+	}
+	goto out_unlock;
+
+out_trans_fail:
+	gfs2_inplace_release(ip);
+out_qunlock:
+	gfs2_quota_unlock(ip);
+out_alloc_put:
+	gfs2_alloc_put(ip);
+out_unlock:
+	gfs2_glock_dq(&ip->i_gh);
+out_uninit:
+	gfs2_holder_uninit(&ip->i_gh);
+	return error;
+}
+
+
 static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 		       u64 start, u64 len)
 {
@@ -1351,6 +1572,7 @@
 	.getxattr = gfs2_getxattr,
 	.listxattr = gfs2_listxattr,
 	.removexattr = gfs2_removexattr,
+	.fallocate = gfs2_fallocate,
 	.fiemap = gfs2_fiemap,
 };
 
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 1bc6b56..58a9b99 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -735,10 +735,8 @@
 		goto out;
 
 	size = loc + sizeof(struct gfs2_quota);
-	if (size > inode->i_size) {
-		ip->i_disksize = size;
+	if (size > inode->i_size)
 		i_size_write(inode, size);
-	}
 	inode->i_mtime = inode->i_atime = CURRENT_TIME;
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
@@ -817,7 +815,7 @@
 		goto out_alloc;
 
 	if (nalloc)
-		blocks += al->al_rgd->rd_length + nalloc * ind_blocks + RES_STATFS;
+		blocks += gfs2_rg_blocks(al) + nalloc * ind_blocks + RES_STATFS;
 
 	error = gfs2_trans_begin(sdp, blocks, 0);
 	if (error)
@@ -1190,18 +1188,17 @@
 int gfs2_quota_init(struct gfs2_sbd *sdp)
 {
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
-	unsigned int blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift;
+	u64 size = i_size_read(sdp->sd_qc_inode);
+	unsigned int blocks = size >> sdp->sd_sb.sb_bsize_shift;
 	unsigned int x, slot = 0;
 	unsigned int found = 0;
 	u64 dblock;
 	u32 extlen = 0;
 	int error;
 
-	if (!ip->i_disksize || ip->i_disksize > (64 << 20) ||
-	    ip->i_disksize & (sdp->sd_sb.sb_bsize - 1)) {
-		gfs2_consist_inode(ip);
+	if (gfs2_check_internal_file_size(sdp->sd_qc_inode, 1, 64 << 20))
 		return -EIO;
-	}
+
 	sdp->sd_quota_slots = blocks * sdp->sd_qc_per_block;
 	sdp->sd_quota_chunks = DIV_ROUND_UP(sdp->sd_quota_slots, 8 * PAGE_SIZE);
 
@@ -1589,6 +1586,7 @@
 		error = gfs2_inplace_reserve(ip);
 		if (error)
 			goto out_alloc;
+		blocks += gfs2_rg_blocks(al);
 	}
 
 	error = gfs2_trans_begin(sdp, blocks + RES_DINODE + 1, 0);
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index f7f89a9..f2a02ed 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -455,11 +455,13 @@
 	int ro = 0;
 	unsigned int pass;
 	int error;
+	int jlocked = 0;
 
-	if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) {
+	if (sdp->sd_args.ar_spectator ||
+	    (jd->jd_jid != sdp->sd_lockstruct.ls_jid)) {
 		fs_info(sdp, "jid=%u: Trying to acquire journal lock...\n",
 			jd->jd_jid);
-
+		jlocked = 1;
 		/* Acquire the journal lock so we can do recovery */
 
 		error = gfs2_glock_nq_num(sdp, jd->jd_jid, &gfs2_journal_glops,
@@ -554,13 +556,12 @@
 			jd->jd_jid, t);
 	}
 
-	if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
-		gfs2_glock_dq_uninit(&ji_gh);
-
 	gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS);
 
-	if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
+	if (jlocked) {
+		gfs2_glock_dq_uninit(&ji_gh);
 		gfs2_glock_dq_uninit(&j_gh);
+	}
 
 	fs_info(sdp, "jid=%u: Done\n", jd->jd_jid);
 	goto done;
@@ -568,7 +569,7 @@
 fail_gunlock_tr:
 	gfs2_glock_dq_uninit(&t_gh);
 fail_gunlock_ji:
-	if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) {
+	if (jlocked) {
 		gfs2_glock_dq_uninit(&ji_gh);
 fail_gunlock_j:
 		gfs2_glock_dq_uninit(&j_gh);
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 171a744..bef3ab6 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -500,7 +500,7 @@
 	for (rgrps = 0;; rgrps++) {
 		loff_t pos = rgrps * sizeof(struct gfs2_rindex);
 
-		if (pos + sizeof(struct gfs2_rindex) >= ip->i_disksize)
+		if (pos + sizeof(struct gfs2_rindex) >= i_size_read(inode))
 			break;
 		error = gfs2_internal_read(ip, &ra_state, buf, &pos,
 					   sizeof(struct gfs2_rindex));
@@ -588,7 +588,9 @@
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct inode *inode = &ip->i_inode;
 	struct file_ra_state ra_state;
-	u64 rgrp_count = ip->i_disksize;
+	u64 rgrp_count = i_size_read(inode);
+	struct gfs2_rgrpd *rgd;
+	unsigned int max_data = 0;
 	int error;
 
 	do_div(rgrp_count, sizeof(struct gfs2_rindex));
@@ -603,6 +605,10 @@
 		}
 	}
 
+	list_for_each_entry(rgd, &sdp->sd_rindex_list, rd_list)
+		if (rgd->rd_data > max_data)
+			max_data = rgd->rd_data;
+	sdp->sd_max_rg_data = max_data;
 	sdp->sd_rindex_uptodate = 1;
 	return 0;
 }
@@ -622,13 +628,15 @@
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct inode *inode = &ip->i_inode;
 	struct file_ra_state ra_state;
+	struct gfs2_rgrpd *rgd;
+	unsigned int max_data = 0;
 	int error;
 
 	file_ra_state_init(&ra_state, inode->i_mapping);
 	for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
 		/* Ignore partials */
 		if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
-		    ip->i_disksize)
+		    i_size_read(inode))
 			break;
 		error = read_rindex_entry(ip, &ra_state);
 		if (error) {
@@ -636,6 +644,10 @@
 			return error;
 		}
 	}
+	list_for_each_entry(rgd, &sdp->sd_rindex_list, rd_list)
+		if (rgd->rd_data > max_data)
+			max_data = rgd->rd_data;
+	sdp->sd_max_rg_data = max_data;
 
 	sdp->sd_rindex_uptodate = 1;
 	return 0;
@@ -854,8 +866,7 @@
 				if ((start + nr_sects) != blk) {
 					rv = blkdev_issue_discard(bdev, start,
 							    nr_sects, GFP_NOFS,
-							    BLKDEV_IFL_WAIT |
-							    BLKDEV_IFL_BARRIER);
+							    0);
 					if (rv)
 						goto fail;
 					nr_sects = 0;
@@ -869,8 +880,7 @@
 		}
 	}
 	if (nr_sects) {
-		rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS,
-					 BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+		rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS, 0);
 		if (rv)
 			goto fail;
 	}
@@ -1188,7 +1198,8 @@
  * Returns: errno
  */
 
-int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
+int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex,
+			   char *file, unsigned int line)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_alloc *al = ip->i_alloc;
@@ -1199,12 +1210,15 @@
 		return -EINVAL;
 
 try_again:
-	/* We need to hold the rindex unless the inode we're using is
-	   the rindex itself, in which case it's already held. */
-	if (ip != GFS2_I(sdp->sd_rindex))
-		error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
-	else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */
-		error = gfs2_ri_update_special(ip);
+	if (hold_rindex) {
+		/* We need to hold the rindex unless the inode we're using is
+		   the rindex itself, in which case it's already held. */
+		if (ip != GFS2_I(sdp->sd_rindex))
+			error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
+		else if (!sdp->sd_rgrps) /* We may not have the rindex read
+					    in, so: */
+			error = gfs2_ri_update_special(ip);
+	}
 
 	if (error)
 		return error;
@@ -1215,7 +1229,7 @@
 	   try to free it, and try the allocation again. */
 	error = get_local_rgrp(ip, &unlinked, &last_unlinked);
 	if (error) {
-		if (ip != GFS2_I(sdp->sd_rindex))
+		if (hold_rindex && ip != GFS2_I(sdp->sd_rindex))
 			gfs2_glock_dq_uninit(&al->al_ri_gh);
 		if (error != -EAGAIN)
 			return error;
@@ -1257,7 +1271,7 @@
 	al->al_rgd = NULL;
 	if (al->al_rgd_gh.gh_gl)
 		gfs2_glock_dq_uninit(&al->al_rgd_gh);
-	if (ip != GFS2_I(sdp->sd_rindex))
+	if (ip != GFS2_I(sdp->sd_rindex) && al->al_ri_gh.gh_gl)
 		gfs2_glock_dq_uninit(&al->al_ri_gh);
 }
 
@@ -1496,11 +1510,19 @@
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct buffer_head *dibh;
 	struct gfs2_alloc *al = ip->i_alloc;
-	struct gfs2_rgrpd *rgd = al->al_rgd;
+	struct gfs2_rgrpd *rgd;
 	u32 goal, blk;
 	u64 block;
 	int error;
 
+	/* Only happens if there is a bug in gfs2, return something distinctive
+	 * to ensure that it is noticed.
+	 */
+	if (al == NULL)
+		return -ECANCELED;
+
+	rgd = al->al_rgd;
+
 	if (rgrp_contains_block(rgd, ip->i_goal))
 		goal = ip->i_goal - rgd->rd_data0;
 	else
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index f07119d..0e35c04 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -39,10 +39,12 @@
 	ip->i_alloc = NULL;
 }
 
-extern int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file,
-				  unsigned int line);
+extern int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex,
+				  char *file, unsigned int line);
 #define gfs2_inplace_reserve(ip) \
-gfs2_inplace_reserve_i((ip), __FILE__, __LINE__)
+	gfs2_inplace_reserve_i((ip), 1, __FILE__, __LINE__)
+#define gfs2_inplace_reserve_ri(ip) \
+	gfs2_inplace_reserve_i((ip), 0, __FILE__, __LINE__)
 
 extern void gfs2_inplace_release(struct gfs2_inode *ip);
 
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 77cb9f8..047d117 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -85,6 +85,7 @@
 	{Opt_locktable, "locktable=%s"},
 	{Opt_hostdata, "hostdata=%s"},
 	{Opt_spectator, "spectator"},
+	{Opt_spectator, "norecovery"},
 	{Opt_ignore_local_fs, "ignore_local_fs"},
 	{Opt_localflocks, "localflocks"},
 	{Opt_localcaching, "localcaching"},
@@ -159,13 +160,13 @@
 			args->ar_spectator = 1;
 			break;
 		case Opt_ignore_local_fs:
-			args->ar_ignore_local_fs = 1;
+			/* Retained for backwards compat only */
 			break;
 		case Opt_localflocks:
 			args->ar_localflocks = 1;
 			break;
 		case Opt_localcaching:
-			args->ar_localcaching = 1;
+			/* Retained for backwards compat only */
 			break;
 		case Opt_debug:
 			if (args->ar_errors == GFS2_ERRORS_PANIC) {
@@ -179,7 +180,7 @@
 			args->ar_debug = 0;
 			break;
 		case Opt_upgrade:
-			args->ar_upgrade = 1;
+			/* Retained for backwards compat only */
 			break;
 		case Opt_acl:
 			args->ar_posix_acl = 1;
@@ -342,15 +343,14 @@
 {
 	struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
 	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
+	u64 size = i_size_read(jd->jd_inode);
 
-	if (ip->i_disksize < (8 << 20) || ip->i_disksize > (1 << 30) ||
-	    (ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) {
-		gfs2_consist_inode(ip);
+	if (gfs2_check_internal_file_size(jd->jd_inode, 8 << 20, 1 << 30))
 		return -EIO;
-	}
-	jd->jd_blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift;
 
-	if (gfs2_write_alloc_required(ip, 0, ip->i_disksize)) {
+	jd->jd_blocks = size >> sdp->sd_sb.sb_bsize_shift;
+
+	if (gfs2_write_alloc_required(ip, 0, size)) {
 		gfs2_consist_inode(ip);
 		return -EIO;
 	}
@@ -1129,9 +1129,7 @@
 
 	/* Some flags must not be changed */
 	if (args_neq(&args, &sdp->sd_args, spectator) ||
-	    args_neq(&args, &sdp->sd_args, ignore_local_fs) ||
 	    args_neq(&args, &sdp->sd_args, localflocks) ||
-	    args_neq(&args, &sdp->sd_args, localcaching) ||
 	    args_neq(&args, &sdp->sd_args, meta))
 		return -EINVAL;
 
@@ -1234,16 +1232,10 @@
 		seq_printf(s, ",hostdata=%s", args->ar_hostdata);
 	if (args->ar_spectator)
 		seq_printf(s, ",spectator");
-	if (args->ar_ignore_local_fs)
-		seq_printf(s, ",ignore_local_fs");
 	if (args->ar_localflocks)
 		seq_printf(s, ",localflocks");
-	if (args->ar_localcaching)
-		seq_printf(s, ",localcaching");
 	if (args->ar_debug)
 		seq_printf(s, ",debug");
-	if (args->ar_upgrade)
-		seq_printf(s, ",upgrade");
 	if (args->ar_posix_acl)
 		seq_printf(s, ",acl");
 	if (args->ar_quota != GFS2_QUOTA_DEFAULT) {
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index ccacffd2..748ccb5 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -230,7 +230,10 @@
 
 	if (gltype > LM_TYPE_JOURNAL)
 		return -EINVAL;
-	glops = gfs2_glops_list[gltype];
+	if (gltype == LM_TYPE_NONDISK && glnum == GFS2_TRANS_LOCK)
+		glops = &gfs2_trans_glops;
+	else
+		glops = gfs2_glops_list[gltype];
 	if (glops == NULL)
 		return -EINVAL;
 	if (!test_and_set_bit(SDF_DEMOTE, &sdp->sd_flags))
@@ -399,31 +402,32 @@
 
 static ssize_t jid_show(struct gfs2_sbd *sdp, char *buf)
 {
-	return sprintf(buf, "%u\n", sdp->sd_lockstruct.ls_jid);
+	return sprintf(buf, "%d\n", sdp->sd_lockstruct.ls_jid);
 }
 
 static ssize_t jid_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
 {
-        unsigned jid;
+        int jid;
 	int rv;
 
-	rv = sscanf(buf, "%u", &jid);
+	rv = sscanf(buf, "%d", &jid);
 	if (rv != 1)
 		return -EINVAL;
 
 	spin_lock(&sdp->sd_jindex_spin);
 	rv = -EINVAL;
-	if (sdp->sd_args.ar_spectator)
-		goto out;
 	if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
 		goto out;
 	rv = -EBUSY;
-	if (test_and_clear_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
+	if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
 		goto out;
+	rv = 0;
+	if (sdp->sd_args.ar_spectator && jid > 0)
+		rv = jid = -EINVAL;
 	sdp->sd_lockstruct.ls_jid = jid;
+	clear_bit(SDF_NOJOURNALID, &sdp->sd_flags);
 	smp_mb__after_clear_bit();
 	wake_up_bit(&sdp->sd_flags, SDF_NOJOURNALID);
-	rv = 0;
 out:
 	spin_unlock(&sdp->sd_jindex_spin);
 	return rv ? rv : len;
@@ -617,7 +621,7 @@
 	add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name);
 	add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name);
 	if (!test_bit(SDF_NOJOURNALID, &sdp->sd_flags))
-		add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid);
+		add_uevent_var(env, "JOURNALID=%d", sdp->sd_lockstruct.ls_jid);
 	if (gfs2_uuid_valid(uuid))
 		add_uevent_var(env, "UUID=%pUB", uuid);
 	return 0;
diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h
index 148d55c..cedb0bb 100644
--- a/fs/gfs2/trace_gfs2.h
+++ b/fs/gfs2/trace_gfs2.h
@@ -39,7 +39,8 @@
 	{(1UL << GLF_INVALIDATE_IN_PROGRESS),	"i" },		\
 	{(1UL << GLF_REPLY_PENDING),		"r" },		\
 	{(1UL << GLF_INITIAL),			"I" },		\
-	{(1UL << GLF_FROZEN),			"F" })
+	{(1UL << GLF_FROZEN),			"F" },		\
+	{(1UL << GLF_QUEUED),			"q" })
 
 #ifndef NUMPTY
 #define NUMPTY
diff --git a/fs/gfs2/trans.h b/fs/gfs2/trans.h
index edf9d4b..fb56b78 100644
--- a/fs/gfs2/trans.h
+++ b/fs/gfs2/trans.h
@@ -20,11 +20,20 @@
 #define RES_JDATA	1
 #define RES_DATA	1
 #define RES_LEAF	1
+#define RES_RG_HDR	1
 #define RES_RG_BIT	2
 #define RES_EATTR	1
 #define RES_STATFS	1
 #define RES_QUOTA	2
 
+/* reserve either the number of blocks to be allocated plus the rg header
+ * block, or all of the blocks in the rg, whichever is smaller */
+static inline unsigned int gfs2_rg_blocks(const struct gfs2_alloc *al)
+{
+	return (al->al_requested < al->al_rgd->rd_length)?
+	       al->al_requested + 1 : al->al_rgd->rd_length;
+}
+
 int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
 		     unsigned int revokes);
 
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 776af6e..30b58f07 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -734,7 +734,7 @@
 		goto out_gunlock_q;
 
 	error = gfs2_trans_begin(GFS2_SB(&ip->i_inode),
-				 blks + al->al_rgd->rd_length +
+				 blks + gfs2_rg_blocks(al) +
 				 RES_DINODE + RES_STATFS + RES_QUOTA, 0);
 	if (error)
 		goto out_ipres;
diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c
index 4129cdb..571abe9 100644
--- a/fs/hfs/bfind.c
+++ b/fs/hfs/bfind.c
@@ -23,7 +23,7 @@
 	fd->search_key = ptr;
 	fd->key = ptr + tree->max_key_len + 2;
 	dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0));
-	down(&tree->tree_lock);
+	mutex_lock(&tree->tree_lock);
 	return 0;
 }
 
@@ -32,7 +32,7 @@
 	hfs_bnode_put(fd->bnode);
 	kfree(fd->search_key);
 	dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0));
-	up(&fd->tree->tree_lock);
+	mutex_unlock(&fd->tree->tree_lock);
 	fd->tree = NULL;
 }
 
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 38a0a99..3ebc437 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -27,7 +27,7 @@
 	if (!tree)
 		return NULL;
 
-	init_MUTEX(&tree->tree_lock);
+	mutex_init(&tree->tree_lock);
 	spin_lock_init(&tree->hash_lock);
 	/* Set the correct compare function */
 	tree->sb = sb;
diff --git a/fs/hfs/btree.h b/fs/hfs/btree.h
index cc51905..2a1d712 100644
--- a/fs/hfs/btree.h
+++ b/fs/hfs/btree.h
@@ -33,7 +33,7 @@
 	unsigned int depth;
 
 	//unsigned int map1_size, map_size;
-	struct semaphore tree_lock;
+	struct mutex tree_lock;
 
 	unsigned int pages_per_bnode;
 	spinlock_t hash_lock;
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 34235d4..33254160 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -20,7 +20,6 @@
 #include <linux/parser.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 
 #include "hfs_fs.h"
@@ -79,15 +78,11 @@
  */
 static void hfs_put_super(struct super_block *sb)
 {
-	lock_kernel();
-
 	if (sb->s_dirt)
 		hfs_write_super(sb);
 	hfs_mdb_close(sb);
 	/* release the MDB's resources */
 	hfs_mdb_put(sb);
-
-	unlock_kernel();
 }
 
 /*
@@ -385,6 +380,7 @@
 	sbi = kzalloc(sizeof(struct hfs_sb_info), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
+
 	sb->s_fs_info = sbi;
 	INIT_HLIST_HEAD(&sbi->rsrc_inodes);
 
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 5007a41..d182438 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -23,7 +23,7 @@
 	fd->search_key = ptr;
 	fd->key = ptr + tree->max_key_len + 2;
 	dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0));
-	down(&tree->tree_lock);
+	mutex_lock(&tree->tree_lock);
 	return 0;
 }
 
@@ -32,7 +32,7 @@
 	hfs_bnode_put(fd->bnode);
 	kfree(fd->search_key);
 	dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0));
-	up(&fd->tree->tree_lock);
+	mutex_unlock(&fd->tree->tree_lock);
 	fd->tree = NULL;
 }
 
@@ -52,6 +52,10 @@
 		rec = (e + b) / 2;
 		len = hfs_brec_lenoff(bnode, rec, &off);
 		keylen = hfs_brec_keylen(bnode, rec);
+		if (keylen == 0) {
+			res = -EINVAL;
+			goto fail;
+		}
 		hfs_bnode_read(bnode, fd->key, off, keylen);
 		cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
 		if (!cmpval) {
@@ -67,6 +71,10 @@
 	if (rec != e && e >= 0) {
 		len = hfs_brec_lenoff(bnode, e, &off);
 		keylen = hfs_brec_keylen(bnode, e);
+		if (keylen == 0) {
+			res = -EINVAL;
+			goto fail;
+		}
 		hfs_bnode_read(bnode, fd->key, off, keylen);
 	}
 done:
@@ -75,6 +83,7 @@
 	fd->keylength = keylen;
 	fd->entryoffset = off + keylen;
 	fd->entrylength = len - keylen;
+fail:
 	return res;
 }
 
@@ -198,6 +207,10 @@
 
 	len = hfs_brec_lenoff(bnode, fd->record, &off);
 	keylen = hfs_brec_keylen(bnode, fd->record);
+	if (keylen == 0) {
+		res = -EINVAL;
+		goto out;
+	}
 	fd->keyoffset = off;
 	fd->keylength = keylen;
 	fd->entryoffset = off + keylen;
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c
index ea30afc..ad57f59 100644
--- a/fs/hfsplus/bitmap.c
+++ b/fs/hfsplus/bitmap.c
@@ -17,6 +17,7 @@
 
 int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max)
 {
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
 	struct page *page;
 	struct address_space *mapping;
 	__be32 *pptr, *curr, *end;
@@ -29,8 +30,8 @@
 		return size;
 
 	dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len);
-	mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
-	mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
+	mutex_lock(&sbi->alloc_mutex);
+	mapping = sbi->alloc_file->i_mapping;
 	page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL);
 	if (IS_ERR(page)) {
 		start = size;
@@ -150,16 +151,17 @@
 	set_page_dirty(page);
 	kunmap(page);
 	*max = offset + (curr - pptr) * 32 + i - start;
-	HFSPLUS_SB(sb).free_blocks -= *max;
+	sbi->free_blocks -= *max;
 	sb->s_dirt = 1;
 	dprint(DBG_BITMAP, "-> %u,%u\n", start, *max);
 out:
-	mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
+	mutex_unlock(&sbi->alloc_mutex);
 	return start;
 }
 
 int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
 {
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
 	struct page *page;
 	struct address_space *mapping;
 	__be32 *pptr, *curr, *end;
@@ -172,11 +174,11 @@
 
 	dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count);
 	/* are all of the bits in range? */
-	if ((offset + count) > HFSPLUS_SB(sb).total_blocks)
+	if ((offset + count) > sbi->total_blocks)
 		return -2;
 
-	mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
-	mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
+	mutex_lock(&sbi->alloc_mutex);
+	mapping = sbi->alloc_file->i_mapping;
 	pnr = offset / PAGE_CACHE_BITS;
 	page = read_mapping_page(mapping, pnr, NULL);
 	pptr = kmap(page);
@@ -224,9 +226,9 @@
 out:
 	set_page_dirty(page);
 	kunmap(page);
-	HFSPLUS_SB(sb).free_blocks += len;
+	sbi->free_blocks += len;
 	sb->s_dirt = 1;
-	mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
+	mutex_unlock(&sbi->alloc_mutex);
 
 	return 0;
 }
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index c88e5d7..2f39d05 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -42,10 +42,13 @@
 		recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2);
 		if (!recoff)
 			return 0;
-		if (node->tree->attributes & HFS_TREE_BIGKEYS)
-			retval = hfs_bnode_read_u16(node, recoff) + 2;
-		else
-			retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1;
+
+		retval = hfs_bnode_read_u16(node, recoff) + 2;
+		if (retval > node->tree->max_key_len + 2) {
+			printk(KERN_ERR "hfs: keylen %d too large\n",
+				retval);
+			retval = 0;
+		}
 	}
 	return retval;
 }
@@ -216,7 +219,7 @@
 static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
 {
 	struct hfs_btree *tree;
-	struct hfs_bnode *node, *new_node;
+	struct hfs_bnode *node, *new_node, *next_node;
 	struct hfs_bnode_desc node_desc;
 	int num_recs, new_rec_off, new_off, old_rec_off;
 	int data_start, data_end, size;
@@ -235,6 +238,17 @@
 	new_node->type = node->type;
 	new_node->height = node->height;
 
+	if (node->next)
+		next_node = hfs_bnode_find(tree, node->next);
+	else
+		next_node = NULL;
+
+	if (IS_ERR(next_node)) {
+		hfs_bnode_put(node);
+		hfs_bnode_put(new_node);
+		return next_node;
+	}
+
 	size = tree->node_size / 2 - node->num_recs * 2 - 14;
 	old_rec_off = tree->node_size - 4;
 	num_recs = 1;
@@ -248,6 +262,8 @@
 		/* panic? */
 		hfs_bnode_put(node);
 		hfs_bnode_put(new_node);
+		if (next_node)
+			hfs_bnode_put(next_node);
 		return ERR_PTR(-ENOSPC);
 	}
 
@@ -302,8 +318,7 @@
 	hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc));
 
 	/* update next bnode header */
-	if (new_node->next) {
-		struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next);
+	if (next_node) {
 		next_node->prev = new_node->this;
 		hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc));
 		node_desc.prev = cpu_to_be32(next_node->prev);
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index e49fcee..22e4d4e 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -30,7 +30,7 @@
 	if (!tree)
 		return NULL;
 
-	init_MUTEX(&tree->tree_lock);
+	mutex_init(&tree->tree_lock);
 	spin_lock_init(&tree->hash_lock);
 	tree->sb = sb;
 	tree->cnid = id;
@@ -39,10 +39,16 @@
 		goto free_tree;
 	tree->inode = inode;
 
+	if (!HFSPLUS_I(tree->inode)->first_blocks) {
+		printk(KERN_ERR
+		       "hfs: invalid btree extent records (0 size).\n");
+		goto free_inode;
+	}
+
 	mapping = tree->inode->i_mapping;
 	page = read_mapping_page(mapping, 0, NULL);
 	if (IS_ERR(page))
-		goto free_tree;
+		goto free_inode;
 
 	/* Load the header */
 	head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
@@ -57,27 +63,56 @@
 	tree->max_key_len = be16_to_cpu(head->max_key_len);
 	tree->depth = be16_to_cpu(head->depth);
 
-	/* Set the correct compare function */
-	if (id == HFSPLUS_EXT_CNID) {
+	/* Verify the tree and set the correct compare function */
+	switch (id) {
+	case HFSPLUS_EXT_CNID:
+		if (tree->max_key_len != HFSPLUS_EXT_KEYLEN - sizeof(u16)) {
+			printk(KERN_ERR "hfs: invalid extent max_key_len %d\n",
+				tree->max_key_len);
+			goto fail_page;
+		}
+		if (tree->attributes & HFS_TREE_VARIDXKEYS) {
+			printk(KERN_ERR "hfs: invalid extent btree flag\n");
+			goto fail_page;
+		}
+
 		tree->keycmp = hfsplus_ext_cmp_key;
-	} else if (id == HFSPLUS_CAT_CNID) {
-		if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
+		break;
+	case HFSPLUS_CAT_CNID:
+		if (tree->max_key_len != HFSPLUS_CAT_KEYLEN - sizeof(u16)) {
+			printk(KERN_ERR "hfs: invalid catalog max_key_len %d\n",
+				tree->max_key_len);
+			goto fail_page;
+		}
+		if (!(tree->attributes & HFS_TREE_VARIDXKEYS)) {
+			printk(KERN_ERR "hfs: invalid catalog btree flag\n");
+			goto fail_page;
+		}
+
+		if (test_bit(HFSPLUS_SB_HFSX, &HFSPLUS_SB(sb)->flags) &&
 		    (head->key_type == HFSPLUS_KEY_BINARY))
 			tree->keycmp = hfsplus_cat_bin_cmp_key;
 		else {
 			tree->keycmp = hfsplus_cat_case_cmp_key;
-			HFSPLUS_SB(sb).flags |= HFSPLUS_SB_CASEFOLD;
+			set_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
 		}
-	} else {
+		break;
+	default:
 		printk(KERN_ERR "hfs: unknown B*Tree requested\n");
 		goto fail_page;
 	}
 
+	if (!(tree->attributes & HFS_TREE_BIGKEYS)) {
+		printk(KERN_ERR "hfs: invalid btree flag\n");
+		goto fail_page;
+	}
+
 	size = tree->node_size;
 	if (!is_power_of_2(size))
 		goto fail_page;
 	if (!tree->node_count)
 		goto fail_page;
+
 	tree->node_size_shift = ffs(size) - 1;
 
 	tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
@@ -87,10 +122,11 @@
 	return tree;
 
  fail_page:
-	tree->inode->i_mapping->a_ops = &hfsplus_aops;
 	page_cache_release(page);
- free_tree:
+ free_inode:
+	tree->inode->i_mapping->a_ops = &hfsplus_aops;
 	iput(tree->inode);
+ free_tree:
 	kfree(tree);
 	return NULL;
 }
@@ -192,17 +228,18 @@
 
 	while (!tree->free_nodes) {
 		struct inode *inode = tree->inode;
+		struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 		u32 count;
 		int res;
 
 		res = hfsplus_file_extend(inode);
 		if (res)
 			return ERR_PTR(res);
-		HFSPLUS_I(inode).phys_size = inode->i_size =
-				(loff_t)HFSPLUS_I(inode).alloc_blocks <<
-				HFSPLUS_SB(tree->sb).alloc_blksz_shift;
-		HFSPLUS_I(inode).fs_blocks = HFSPLUS_I(inode).alloc_blocks <<
-					     HFSPLUS_SB(tree->sb).fs_shift;
+		hip->phys_size = inode->i_size =
+			(loff_t)hip->alloc_blocks <<
+				HFSPLUS_SB(tree->sb)->alloc_blksz_shift;
+		hip->fs_blocks =
+			hip->alloc_blocks << HFSPLUS_SB(tree->sb)->fs_shift;
 		inode_set_bytes(inode, inode->i_size);
 		count = inode->i_size >> tree->node_size_shift;
 		tree->free_nodes = count - tree->node_count;
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index f6874ac..8af45fc 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -67,7 +67,7 @@
 	key->key_len = cpu_to_be16(6 + ustrlen);
 }
 
-static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
+void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms)
 {
 	if (inode->i_flags & S_IMMUTABLE)
 		perms->rootflags |= HFSPLUS_FLG_IMMUTABLE;
@@ -77,15 +77,24 @@
 		perms->rootflags |= HFSPLUS_FLG_APPEND;
 	else
 		perms->rootflags &= ~HFSPLUS_FLG_APPEND;
-	HFSPLUS_I(inode).rootflags = perms->rootflags;
-	HFSPLUS_I(inode).userflags = perms->userflags;
+
+	perms->userflags = HFSPLUS_I(inode)->userflags;
 	perms->mode = cpu_to_be16(inode->i_mode);
 	perms->owner = cpu_to_be32(inode->i_uid);
 	perms->group = cpu_to_be32(inode->i_gid);
+
+	if (S_ISREG(inode->i_mode))
+		perms->dev = cpu_to_be32(inode->i_nlink);
+	else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode))
+		perms->dev = cpu_to_be32(inode->i_rdev);
+	else
+		perms->dev = 0;
 }
 
 static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode)
 {
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
+
 	if (S_ISDIR(inode->i_mode)) {
 		struct hfsplus_cat_folder *folder;
 
@@ -93,13 +102,13 @@
 		memset(folder, 0, sizeof(*folder));
 		folder->type = cpu_to_be16(HFSPLUS_FOLDER);
 		folder->id = cpu_to_be32(inode->i_ino);
-		HFSPLUS_I(inode).create_date =
+		HFSPLUS_I(inode)->create_date =
 			folder->create_date =
 			folder->content_mod_date =
 			folder->attribute_mod_date =
 			folder->access_date = hfsp_now2mt();
-		hfsplus_set_perms(inode, &folder->permissions);
-		if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir)
+		hfsplus_cat_set_perms(inode, &folder->permissions);
+		if (inode == sbi->hidden_dir)
 			/* invisible and namelocked */
 			folder->user_info.frFlags = cpu_to_be16(0x5000);
 		return sizeof(*folder);
@@ -111,19 +120,19 @@
 		file->type = cpu_to_be16(HFSPLUS_FILE);
 		file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS);
 		file->id = cpu_to_be32(cnid);
-		HFSPLUS_I(inode).create_date =
+		HFSPLUS_I(inode)->create_date =
 			file->create_date =
 			file->content_mod_date =
 			file->attribute_mod_date =
 			file->access_date = hfsp_now2mt();
 		if (cnid == inode->i_ino) {
-			hfsplus_set_perms(inode, &file->permissions);
+			hfsplus_cat_set_perms(inode, &file->permissions);
 			if (S_ISLNK(inode->i_mode)) {
 				file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE);
 				file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR);
 			} else {
-				file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
-				file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
+				file->user_info.fdType = cpu_to_be32(sbi->type);
+				file->user_info.fdCreator = cpu_to_be32(sbi->creator);
 			}
 			if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
 				file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
@@ -131,8 +140,8 @@
 			file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE);
 			file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
 			file->user_info.fdFlags = cpu_to_be16(0x100);
-			file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date;
-			file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev);
+			file->create_date = HFSPLUS_I(sbi->hidden_dir)->create_date;
+			file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode)->linkid);
 		}
 		return sizeof(*file);
 	}
@@ -180,15 +189,14 @@
 
 int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode)
 {
+	struct super_block *sb = dir->i_sb;
 	struct hfs_find_data fd;
-	struct super_block *sb;
 	hfsplus_cat_entry entry;
 	int entry_size;
 	int err;
 
 	dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink);
-	sb = dir->i_sb;
-	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 
 	hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
 	entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ?
@@ -234,7 +242,7 @@
 
 int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
 {
-	struct super_block *sb;
+	struct super_block *sb = dir->i_sb;
 	struct hfs_find_data fd;
 	struct hfsplus_fork_raw fork;
 	struct list_head *pos;
@@ -242,8 +250,7 @@
 	u16 type;
 
 	dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid);
-	sb = dir->i_sb;
-	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 
 	if (!str) {
 		int len;
@@ -279,7 +286,7 @@
 		hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC);
 	}
 
-	list_for_each(pos, &HFSPLUS_I(dir).open_dir_list) {
+	list_for_each(pos, &HFSPLUS_I(dir)->open_dir_list) {
 		struct hfsplus_readdir_data *rd =
 			list_entry(pos, struct hfsplus_readdir_data, list);
 		if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
@@ -312,7 +319,7 @@
 		       struct inode *src_dir, struct qstr *src_name,
 		       struct inode *dst_dir, struct qstr *dst_name)
 {
-	struct super_block *sb;
+	struct super_block *sb = src_dir->i_sb;
 	struct hfs_find_data src_fd, dst_fd;
 	hfsplus_cat_entry entry;
 	int entry_size, type;
@@ -320,8 +327,7 @@
 
 	dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name,
 		dst_dir->i_ino, dst_name->name);
-	sb = src_dir->i_sb;
-	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &src_fd);
+	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &src_fd);
 	dst_fd = src_fd;
 
 	/* find the old dir entry and read the data */
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 764fd1b..d236d85 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -39,7 +39,7 @@
 
 	dentry->d_op = &hfsplus_dentry_operations;
 	dentry->d_fsdata = NULL;
-	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 	hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name);
 again:
 	err = hfs_brec_read(&fd, &entry, sizeof(entry));
@@ -68,9 +68,9 @@
 		cnid = be32_to_cpu(entry.file.id);
 		if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) &&
 		    entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
-		    (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date ||
-		     entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) &&
-		    HFSPLUS_SB(sb).hidden_dir) {
+		    (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)->create_date ||
+		     entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode)->create_date) &&
+		    HFSPLUS_SB(sb)->hidden_dir) {
 			struct qstr str;
 			char name[32];
 
@@ -86,7 +86,8 @@
 				linkid = be32_to_cpu(entry.file.permissions.dev);
 				str.len = sprintf(name, "iNode%d", linkid);
 				str.name = name;
-				hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
+				hfsplus_cat_build_key(sb, fd.search_key,
+					HFSPLUS_SB(sb)->hidden_dir->i_ino, &str);
 				goto again;
 			}
 		} else if (!dentry->d_fsdata)
@@ -101,7 +102,7 @@
 	if (IS_ERR(inode))
 		return ERR_CAST(inode);
 	if (S_ISREG(inode->i_mode))
-		HFSPLUS_I(inode).dev = linkid;
+		HFSPLUS_I(inode)->linkid = linkid;
 out:
 	d_add(dentry, inode);
 	return NULL;
@@ -124,7 +125,7 @@
 	if (filp->f_pos >= inode->i_size)
 		return 0;
 
-	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 	hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL);
 	err = hfs_brec_find(&fd);
 	if (err)
@@ -180,8 +181,9 @@
 				err = -EIO;
 				goto out;
 			}
-			if (HFSPLUS_SB(sb).hidden_dir &&
-			    HFSPLUS_SB(sb).hidden_dir->i_ino == be32_to_cpu(entry.folder.id))
+			if (HFSPLUS_SB(sb)->hidden_dir &&
+			    HFSPLUS_SB(sb)->hidden_dir->i_ino ==
+					be32_to_cpu(entry.folder.id))
 				goto next;
 			if (filldir(dirent, strbuf, len, filp->f_pos,
 				    be32_to_cpu(entry.folder.id), DT_DIR))
@@ -217,7 +219,7 @@
 		}
 		filp->private_data = rd;
 		rd->file = filp;
-		list_add(&rd->list, &HFSPLUS_I(inode).open_dir_list);
+		list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list);
 	}
 	memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key));
 out:
@@ -229,38 +231,18 @@
 {
 	struct hfsplus_readdir_data *rd = file->private_data;
 	if (rd) {
+		mutex_lock(&inode->i_mutex);
 		list_del(&rd->list);
+		mutex_unlock(&inode->i_mutex);
 		kfree(rd);
 	}
 	return 0;
 }
 
-static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,
-			  struct nameidata *nd)
-{
-	struct inode *inode;
-	int res;
-
-	inode = hfsplus_new_inode(dir->i_sb, mode);
-	if (!inode)
-		return -ENOSPC;
-
-	res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
-	if (res) {
-		inode->i_nlink = 0;
-		hfsplus_delete_inode(inode);
-		iput(inode);
-		return res;
-	}
-	hfsplus_instantiate(dentry, inode, inode->i_ino);
-	mark_inode_dirty(inode);
-	return 0;
-}
-
 static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
 			struct dentry *dst_dentry)
 {
-	struct super_block *sb = dst_dir->i_sb;
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dst_dir->i_sb);
 	struct inode *inode = src_dentry->d_inode;
 	struct inode *src_dir = src_dentry->d_parent->d_inode;
 	struct qstr str;
@@ -270,7 +252,10 @@
 
 	if (HFSPLUS_IS_RSRC(inode))
 		return -EPERM;
+	if (!S_ISREG(inode->i_mode))
+		return -EPERM;
 
+	mutex_lock(&sbi->vh_mutex);
 	if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) {
 		for (;;) {
 			get_random_bytes(&id, sizeof(cnid));
@@ -279,40 +264,41 @@
 			str.len = sprintf(name, "iNode%d", id);
 			res = hfsplus_rename_cat(inode->i_ino,
 						 src_dir, &src_dentry->d_name,
-						 HFSPLUS_SB(sb).hidden_dir, &str);
+						 sbi->hidden_dir, &str);
 			if (!res)
 				break;
 			if (res != -EEXIST)
-				return res;
+				goto out;
 		}
-		HFSPLUS_I(inode).dev = id;
-		cnid = HFSPLUS_SB(sb).next_cnid++;
+		HFSPLUS_I(inode)->linkid = id;
+		cnid = sbi->next_cnid++;
 		src_dentry->d_fsdata = (void *)(unsigned long)cnid;
 		res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode);
 		if (res)
 			/* panic? */
-			return res;
-		HFSPLUS_SB(sb).file_count++;
+			goto out;
+		sbi->file_count++;
 	}
-	cnid = HFSPLUS_SB(sb).next_cnid++;
+	cnid = sbi->next_cnid++;
 	res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode);
 	if (res)
-		return res;
+		goto out;
 
 	inc_nlink(inode);
 	hfsplus_instantiate(dst_dentry, inode, cnid);
 	atomic_inc(&inode->i_count);
 	inode->i_ctime = CURRENT_TIME_SEC;
 	mark_inode_dirty(inode);
-	HFSPLUS_SB(sb).file_count++;
-	sb->s_dirt = 1;
-
-	return 0;
+	sbi->file_count++;
+	dst_dir->i_sb->s_dirt = 1;
+out:
+	mutex_unlock(&sbi->vh_mutex);
+	return res;
 }
 
 static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
 {
-	struct super_block *sb = dir->i_sb;
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
 	struct inode *inode = dentry->d_inode;
 	struct qstr str;
 	char name[32];
@@ -322,21 +308,22 @@
 	if (HFSPLUS_IS_RSRC(inode))
 		return -EPERM;
 
+	mutex_lock(&sbi->vh_mutex);
 	cnid = (u32)(unsigned long)dentry->d_fsdata;
 	if (inode->i_ino == cnid &&
-	    atomic_read(&HFSPLUS_I(inode).opencnt)) {
+	    atomic_read(&HFSPLUS_I(inode)->opencnt)) {
 		str.name = name;
 		str.len = sprintf(name, "temp%lu", inode->i_ino);
 		res = hfsplus_rename_cat(inode->i_ino,
 					 dir, &dentry->d_name,
-					 HFSPLUS_SB(sb).hidden_dir, &str);
+					 sbi->hidden_dir, &str);
 		if (!res)
 			inode->i_flags |= S_DEAD;
-		return res;
+		goto out;
 	}
 	res = hfsplus_delete_cat(cnid, dir, &dentry->d_name);
 	if (res)
-		return res;
+		goto out;
 
 	if (inode->i_nlink > 0)
 		drop_nlink(inode);
@@ -344,10 +331,10 @@
 		clear_nlink(inode);
 	if (!inode->i_nlink) {
 		if (inode->i_ino != cnid) {
-			HFSPLUS_SB(sb).file_count--;
-			if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
+			sbi->file_count--;
+			if (!atomic_read(&HFSPLUS_I(inode)->opencnt)) {
 				res = hfsplus_delete_cat(inode->i_ino,
-							 HFSPLUS_SB(sb).hidden_dir,
+							 sbi->hidden_dir,
 							 NULL);
 				if (!res)
 					hfsplus_delete_inode(inode);
@@ -356,107 +343,108 @@
 		} else
 			hfsplus_delete_inode(inode);
 	} else
-		HFSPLUS_SB(sb).file_count--;
+		sbi->file_count--;
 	inode->i_ctime = CURRENT_TIME_SEC;
 	mark_inode_dirty(inode);
-
+out:
+	mutex_unlock(&sbi->vh_mutex);
 	return res;
 }
 
-static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
-	struct inode *inode;
-	int res;
-
-	inode = hfsplus_new_inode(dir->i_sb, S_IFDIR | mode);
-	if (!inode)
-		return -ENOSPC;
-
-	res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
-	if (res) {
-		inode->i_nlink = 0;
-		hfsplus_delete_inode(inode);
-		iput(inode);
-		return res;
-	}
-	hfsplus_instantiate(dentry, inode, inode->i_ino);
-	mark_inode_dirty(inode);
-	return 0;
-}
-
 static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
 {
-	struct inode *inode;
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
+	struct inode *inode = dentry->d_inode;
 	int res;
 
-	inode = dentry->d_inode;
 	if (inode->i_size != 2)
 		return -ENOTEMPTY;
+
+	mutex_lock(&sbi->vh_mutex);
 	res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
 	if (res)
-		return res;
+		goto out;
 	clear_nlink(inode);
 	inode->i_ctime = CURRENT_TIME_SEC;
 	hfsplus_delete_inode(inode);
 	mark_inode_dirty(inode);
-	return 0;
+out:
+	mutex_unlock(&sbi->vh_mutex);
+	return res;
 }
 
 static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
 			   const char *symname)
 {
-	struct super_block *sb;
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
 	struct inode *inode;
-	int res;
+	int res = -ENOSPC;
 
-	sb = dir->i_sb;
-	inode = hfsplus_new_inode(sb, S_IFLNK | S_IRWXUGO);
+	mutex_lock(&sbi->vh_mutex);
+	inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO);
 	if (!inode)
-		return -ENOSPC;
+		goto out;
 
 	res = page_symlink(inode, symname, strlen(symname) + 1);
-	if (res) {
-		inode->i_nlink = 0;
-		hfsplus_delete_inode(inode);
-		iput(inode);
-		return res;
-	}
+	if (res)
+		goto out_err;
 
-	mark_inode_dirty(inode);
 	res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
+	if (res)
+		goto out_err;
 
-	if (!res) {
-		hfsplus_instantiate(dentry, inode, inode->i_ino);
-		mark_inode_dirty(inode);
-	}
+	hfsplus_instantiate(dentry, inode, inode->i_ino);
+	mark_inode_dirty(inode);
+	goto out;
 
+out_err:
+	inode->i_nlink = 0;
+	hfsplus_delete_inode(inode);
+	iput(inode);
+out:
+	mutex_unlock(&sbi->vh_mutex);
 	return res;
 }
 
 static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
 			 int mode, dev_t rdev)
 {
-	struct super_block *sb;
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
 	struct inode *inode;
-	int res;
+	int res = -ENOSPC;
 
-	sb = dir->i_sb;
-	inode = hfsplus_new_inode(sb, mode);
+	mutex_lock(&sbi->vh_mutex);
+	inode = hfsplus_new_inode(dir->i_sb, mode);
 	if (!inode)
-		return -ENOSPC;
+		goto out;
+
+	if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode))
+		init_special_inode(inode, mode, rdev);
 
 	res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
 	if (res) {
 		inode->i_nlink = 0;
 		hfsplus_delete_inode(inode);
 		iput(inode);
-		return res;
+		goto out;
 	}
-	init_special_inode(inode, mode, rdev);
+
 	hfsplus_instantiate(dentry, inode, inode->i_ino);
 	mark_inode_dirty(inode);
+out:
+	mutex_unlock(&sbi->vh_mutex);
+	return res;
+}
 
-	return 0;
+static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,
+			  struct nameidata *nd)
+{
+	return hfsplus_mknod(dir, dentry, mode, 0);
+}
+
+static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	return hfsplus_mknod(dir, dentry, mode | S_IFDIR, 0);
 }
 
 static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -466,7 +454,10 @@
 
 	/* Unlink destination if it already exists */
 	if (new_dentry->d_inode) {
-		res = hfsplus_unlink(new_dir, new_dentry);
+		if (S_ISDIR(new_dentry->d_inode->i_mode))
+			res = hfsplus_rmdir(new_dir, new_dentry);
+		else
+			res = hfsplus_unlink(new_dir, new_dentry);
 		if (res)
 			return res;
 	}
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index 0022eec..0c9cb18 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -85,33 +85,47 @@
 
 static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data *fd)
 {
+	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	int res;
 
-	hfsplus_ext_build_key(fd->search_key, inode->i_ino, HFSPLUS_I(inode).cached_start,
-			      HFSPLUS_IS_RSRC(inode) ?  HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
+	WARN_ON(!mutex_is_locked(&hip->extents_lock));
+
+	hfsplus_ext_build_key(fd->search_key, inode->i_ino, hip->cached_start,
+			      HFSPLUS_IS_RSRC(inode) ?
+				HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
+
 	res = hfs_brec_find(fd);
-	if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_NEW) {
+	if (hip->flags & HFSPLUS_FLG_EXT_NEW) {
 		if (res != -ENOENT)
 			return;
-		hfs_brec_insert(fd, HFSPLUS_I(inode).cached_extents, sizeof(hfsplus_extent_rec));
-		HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+		hfs_brec_insert(fd, hip->cached_extents,
+				sizeof(hfsplus_extent_rec));
+		hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
 	} else {
 		if (res)
 			return;
-		hfs_bnode_write(fd->bnode, HFSPLUS_I(inode).cached_extents, fd->entryoffset, fd->entrylength);
-		HFSPLUS_I(inode).flags &= ~HFSPLUS_FLG_EXT_DIRTY;
+		hfs_bnode_write(fd->bnode, hip->cached_extents,
+				fd->entryoffset, fd->entrylength);
+		hip->flags &= ~HFSPLUS_FLG_EXT_DIRTY;
+	}
+}
+
+static void hfsplus_ext_write_extent_locked(struct inode *inode)
+{
+	if (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_EXT_DIRTY) {
+		struct hfs_find_data fd;
+
+		hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd);
+		__hfsplus_ext_write_extent(inode, &fd);
+		hfs_find_exit(&fd);
 	}
 }
 
 void hfsplus_ext_write_extent(struct inode *inode)
 {
-	if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) {
-		struct hfs_find_data fd;
-
-		hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd);
-		__hfsplus_ext_write_extent(inode, &fd);
-		hfs_find_exit(&fd);
-	}
+	mutex_lock(&HFSPLUS_I(inode)->extents_lock);
+	hfsplus_ext_write_extent_locked(inode);
+	mutex_unlock(&HFSPLUS_I(inode)->extents_lock);
 }
 
 static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd,
@@ -136,33 +150,39 @@
 
 static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block)
 {
+	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	int res;
 
-	if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY)
+	WARN_ON(!mutex_is_locked(&hip->extents_lock));
+
+	if (hip->flags & HFSPLUS_FLG_EXT_DIRTY)
 		__hfsplus_ext_write_extent(inode, fd);
 
-	res = __hfsplus_ext_read_extent(fd, HFSPLUS_I(inode).cached_extents, inode->i_ino,
-					block, HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
+	res = __hfsplus_ext_read_extent(fd, hip->cached_extents, inode->i_ino,
+					block, HFSPLUS_IS_RSRC(inode) ?
+						HFSPLUS_TYPE_RSRC :
+						HFSPLUS_TYPE_DATA);
 	if (!res) {
-		HFSPLUS_I(inode).cached_start = be32_to_cpu(fd->key->ext.start_block);
-		HFSPLUS_I(inode).cached_blocks = hfsplus_ext_block_count(HFSPLUS_I(inode).cached_extents);
+		hip->cached_start = be32_to_cpu(fd->key->ext.start_block);
+		hip->cached_blocks = hfsplus_ext_block_count(hip->cached_extents);
 	} else {
-		HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0;
-		HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+		hip->cached_start = hip->cached_blocks = 0;
+		hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
 	}
 	return res;
 }
 
 static int hfsplus_ext_read_extent(struct inode *inode, u32 block)
 {
+	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	struct hfs_find_data fd;
 	int res;
 
-	if (block >= HFSPLUS_I(inode).cached_start &&
-	    block < HFSPLUS_I(inode).cached_start + HFSPLUS_I(inode).cached_blocks)
+	if (block >= hip->cached_start &&
+	    block < hip->cached_start + hip->cached_blocks)
 		return 0;
 
-	hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd);
+	hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd);
 	res = __hfsplus_ext_cache_extent(&fd, inode, block);
 	hfs_find_exit(&fd);
 	return res;
@@ -172,21 +192,21 @@
 int hfsplus_get_block(struct inode *inode, sector_t iblock,
 		      struct buffer_head *bh_result, int create)
 {
-	struct super_block *sb;
+	struct super_block *sb = inode->i_sb;
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	int res = -EIO;
 	u32 ablock, dblock, mask;
 	int shift;
 
-	sb = inode->i_sb;
-
 	/* Convert inode block to disk allocation block */
-	shift = HFSPLUS_SB(sb).alloc_blksz_shift - sb->s_blocksize_bits;
-	ablock = iblock >> HFSPLUS_SB(sb).fs_shift;
+	shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits;
+	ablock = iblock >> sbi->fs_shift;
 
-	if (iblock >= HFSPLUS_I(inode).fs_blocks) {
-		if (iblock > HFSPLUS_I(inode).fs_blocks || !create)
+	if (iblock >= hip->fs_blocks) {
+		if (iblock > hip->fs_blocks || !create)
 			return -EIO;
-		if (ablock >= HFSPLUS_I(inode).alloc_blocks) {
+		if (ablock >= hip->alloc_blocks) {
 			res = hfsplus_file_extend(inode);
 			if (res)
 				return res;
@@ -194,33 +214,33 @@
 	} else
 		create = 0;
 
-	if (ablock < HFSPLUS_I(inode).first_blocks) {
-		dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).first_extents, ablock);
+	if (ablock < hip->first_blocks) {
+		dblock = hfsplus_ext_find_block(hip->first_extents, ablock);
 		goto done;
 	}
 
 	if (inode->i_ino == HFSPLUS_EXT_CNID)
 		return -EIO;
 
-	mutex_lock(&HFSPLUS_I(inode).extents_lock);
+	mutex_lock(&hip->extents_lock);
 	res = hfsplus_ext_read_extent(inode, ablock);
 	if (!res) {
-		dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock -
-					     HFSPLUS_I(inode).cached_start);
+		dblock = hfsplus_ext_find_block(hip->cached_extents,
+						ablock - hip->cached_start);
 	} else {
-		mutex_unlock(&HFSPLUS_I(inode).extents_lock);
+		mutex_unlock(&hip->extents_lock);
 		return -EIO;
 	}
-	mutex_unlock(&HFSPLUS_I(inode).extents_lock);
+	mutex_unlock(&hip->extents_lock);
 
 done:
 	dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock);
-	mask = (1 << HFSPLUS_SB(sb).fs_shift) - 1;
-	map_bh(bh_result, sb, (dblock << HFSPLUS_SB(sb).fs_shift) + HFSPLUS_SB(sb).blockoffset + (iblock & mask));
+	mask = (1 << sbi->fs_shift) - 1;
+	map_bh(bh_result, sb, (dblock << sbi->fs_shift) + sbi->blockoffset + (iblock & mask));
 	if (create) {
 		set_buffer_new(bh_result);
-		HFSPLUS_I(inode).phys_size += sb->s_blocksize;
-		HFSPLUS_I(inode).fs_blocks++;
+		hip->phys_size += sb->s_blocksize;
+		hip->fs_blocks++;
 		inode_add_bytes(inode, sb->s_blocksize);
 		mark_inode_dirty(inode);
 	}
@@ -327,7 +347,7 @@
 	if (total_blocks == blocks)
 		return 0;
 
-	hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd);
+	hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
 	do {
 		res = __hfsplus_ext_read_extent(&fd, ext_entry, cnid,
 						total_blocks, type);
@@ -348,29 +368,33 @@
 int hfsplus_file_extend(struct inode *inode)
 {
 	struct super_block *sb = inode->i_sb;
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	u32 start, len, goal;
 	int res;
 
-	if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) {
+	if (sbi->alloc_file->i_size * 8 <
+	    sbi->total_blocks - sbi->free_blocks + 8) {
 		// extend alloc file
-		printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8,
-			HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks);
+		printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n",
+				sbi->alloc_file->i_size * 8,
+				sbi->total_blocks, sbi->free_blocks);
 		return -ENOSPC;
 	}
 
-	mutex_lock(&HFSPLUS_I(inode).extents_lock);
-	if (HFSPLUS_I(inode).alloc_blocks == HFSPLUS_I(inode).first_blocks)
-		goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).first_extents);
+	mutex_lock(&hip->extents_lock);
+	if (hip->alloc_blocks == hip->first_blocks)
+		goal = hfsplus_ext_lastblock(hip->first_extents);
 	else {
-		res = hfsplus_ext_read_extent(inode, HFSPLUS_I(inode).alloc_blocks);
+		res = hfsplus_ext_read_extent(inode, hip->alloc_blocks);
 		if (res)
 			goto out;
-		goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).cached_extents);
+		goal = hfsplus_ext_lastblock(hip->cached_extents);
 	}
 
-	len = HFSPLUS_I(inode).clump_blocks;
-	start = hfsplus_block_allocate(sb, HFSPLUS_SB(sb).total_blocks, goal, &len);
-	if (start >= HFSPLUS_SB(sb).total_blocks) {
+	len = hip->clump_blocks;
+	start = hfsplus_block_allocate(sb, sbi->total_blocks, goal, &len);
+	if (start >= sbi->total_blocks) {
 		start = hfsplus_block_allocate(sb, goal, 0, &len);
 		if (start >= goal) {
 			res = -ENOSPC;
@@ -379,56 +403,56 @@
 	}
 
 	dprint(DBG_EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len);
-	if (HFSPLUS_I(inode).alloc_blocks <= HFSPLUS_I(inode).first_blocks) {
-		if (!HFSPLUS_I(inode).first_blocks) {
+
+	if (hip->alloc_blocks <= hip->first_blocks) {
+		if (!hip->first_blocks) {
 			dprint(DBG_EXTENT, "first extents\n");
 			/* no extents yet */
-			HFSPLUS_I(inode).first_extents[0].start_block = cpu_to_be32(start);
-			HFSPLUS_I(inode).first_extents[0].block_count = cpu_to_be32(len);
+			hip->first_extents[0].start_block = cpu_to_be32(start);
+			hip->first_extents[0].block_count = cpu_to_be32(len);
 			res = 0;
 		} else {
 			/* try to append to extents in inode */
-			res = hfsplus_add_extent(HFSPLUS_I(inode).first_extents,
-						 HFSPLUS_I(inode).alloc_blocks,
+			res = hfsplus_add_extent(hip->first_extents,
+						 hip->alloc_blocks,
 						 start, len);
 			if (res == -ENOSPC)
 				goto insert_extent;
 		}
 		if (!res) {
-			hfsplus_dump_extent(HFSPLUS_I(inode).first_extents);
-			HFSPLUS_I(inode).first_blocks += len;
+			hfsplus_dump_extent(hip->first_extents);
+			hip->first_blocks += len;
 		}
 	} else {
-		res = hfsplus_add_extent(HFSPLUS_I(inode).cached_extents,
-					 HFSPLUS_I(inode).alloc_blocks -
-					 HFSPLUS_I(inode).cached_start,
+		res = hfsplus_add_extent(hip->cached_extents,
+					 hip->alloc_blocks - hip->cached_start,
 					 start, len);
 		if (!res) {
-			hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents);
-			HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY;
-			HFSPLUS_I(inode).cached_blocks += len;
+			hfsplus_dump_extent(hip->cached_extents);
+			hip->flags |= HFSPLUS_FLG_EXT_DIRTY;
+			hip->cached_blocks += len;
 		} else if (res == -ENOSPC)
 			goto insert_extent;
 	}
 out:
-	mutex_unlock(&HFSPLUS_I(inode).extents_lock);
+	mutex_unlock(&hip->extents_lock);
 	if (!res) {
-		HFSPLUS_I(inode).alloc_blocks += len;
+		hip->alloc_blocks += len;
 		mark_inode_dirty(inode);
 	}
 	return res;
 
 insert_extent:
 	dprint(DBG_EXTENT, "insert new extent\n");
-	hfsplus_ext_write_extent(inode);
+	hfsplus_ext_write_extent_locked(inode);
 
-	memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec));
-	HFSPLUS_I(inode).cached_extents[0].start_block = cpu_to_be32(start);
-	HFSPLUS_I(inode).cached_extents[0].block_count = cpu_to_be32(len);
-	hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents);
-	HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW;
-	HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).alloc_blocks;
-	HFSPLUS_I(inode).cached_blocks = len;
+	memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
+	hip->cached_extents[0].start_block = cpu_to_be32(start);
+	hip->cached_extents[0].block_count = cpu_to_be32(len);
+	hfsplus_dump_extent(hip->cached_extents);
+	hip->flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW;
+	hip->cached_start = hip->alloc_blocks;
+	hip->cached_blocks = len;
 
 	res = 0;
 	goto out;
@@ -437,13 +461,15 @@
 void hfsplus_file_truncate(struct inode *inode)
 {
 	struct super_block *sb = inode->i_sb;
+	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	struct hfs_find_data fd;
 	u32 alloc_cnt, blk_cnt, start;
 	int res;
 
-	dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n", inode->i_ino,
-	       (long long)HFSPLUS_I(inode).phys_size, inode->i_size);
-	if (inode->i_size > HFSPLUS_I(inode).phys_size) {
+	dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n",
+		inode->i_ino, (long long)hip->phys_size, inode->i_size);
+
+	if (inode->i_size > hip->phys_size) {
 		struct address_space *mapping = inode->i_mapping;
 		struct page *page;
 		void *fsdata;
@@ -460,47 +486,48 @@
 			return;
 		mark_inode_dirty(inode);
 		return;
-	} else if (inode->i_size == HFSPLUS_I(inode).phys_size)
+	} else if (inode->i_size == hip->phys_size)
 		return;
 
-	blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift;
-	alloc_cnt = HFSPLUS_I(inode).alloc_blocks;
+	blk_cnt = (inode->i_size + HFSPLUS_SB(sb)->alloc_blksz - 1) >>
+			HFSPLUS_SB(sb)->alloc_blksz_shift;
+	alloc_cnt = hip->alloc_blocks;
 	if (blk_cnt == alloc_cnt)
 		goto out;
 
-	mutex_lock(&HFSPLUS_I(inode).extents_lock);
-	hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd);
+	mutex_lock(&hip->extents_lock);
+	hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
 	while (1) {
-		if (alloc_cnt == HFSPLUS_I(inode).first_blocks) {
-			hfsplus_free_extents(sb, HFSPLUS_I(inode).first_extents,
+		if (alloc_cnt == hip->first_blocks) {
+			hfsplus_free_extents(sb, hip->first_extents,
 					     alloc_cnt, alloc_cnt - blk_cnt);
-			hfsplus_dump_extent(HFSPLUS_I(inode).first_extents);
-			HFSPLUS_I(inode).first_blocks = blk_cnt;
+			hfsplus_dump_extent(hip->first_extents);
+			hip->first_blocks = blk_cnt;
 			break;
 		}
 		res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt);
 		if (res)
 			break;
-		start = HFSPLUS_I(inode).cached_start;
-		hfsplus_free_extents(sb, HFSPLUS_I(inode).cached_extents,
+		start = hip->cached_start;
+		hfsplus_free_extents(sb, hip->cached_extents,
 				     alloc_cnt - start, alloc_cnt - blk_cnt);
-		hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents);
+		hfsplus_dump_extent(hip->cached_extents);
 		if (blk_cnt > start) {
-			HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY;
+			hip->flags |= HFSPLUS_FLG_EXT_DIRTY;
 			break;
 		}
 		alloc_cnt = start;
-		HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0;
-		HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+		hip->cached_start = hip->cached_blocks = 0;
+		hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
 		hfs_brec_remove(&fd);
 	}
 	hfs_find_exit(&fd);
-	mutex_unlock(&HFSPLUS_I(inode).extents_lock);
+	mutex_unlock(&hip->extents_lock);
 
-	HFSPLUS_I(inode).alloc_blocks = blk_cnt;
+	hip->alloc_blocks = blk_cnt;
 out:
-	HFSPLUS_I(inode).phys_size = inode->i_size;
-	HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
-	inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits);
+	hip->phys_size = inode->i_size;
+	hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits);
 	mark_inode_dirty(inode);
 }
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index dc856be..cb3653e 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -62,7 +62,7 @@
 	unsigned int depth;
 
 	//unsigned int map1_size, map_size;
-	struct semaphore tree_lock;
+	struct mutex tree_lock;
 
 	unsigned int pages_per_bnode;
 	spinlock_t hash_lock;
@@ -121,16 +121,21 @@
 	u32 sect_count;
 	int fs_shift;
 
-	/* Stuff in host order from Vol Header */
+	/* immutable data from the volume header */
 	u32 alloc_blksz;
 	int alloc_blksz_shift;
 	u32 total_blocks;
+	u32 data_clump_blocks, rsrc_clump_blocks;
+
+	/* mutable data from the volume header, protected by alloc_mutex */
 	u32 free_blocks;
-	u32 next_alloc;
+	struct mutex alloc_mutex;
+
+	/* mutable data from the volume header, protected by vh_mutex */
 	u32 next_cnid;
 	u32 file_count;
 	u32 folder_count;
-	u32 data_clump_blocks, rsrc_clump_blocks;
+	struct mutex vh_mutex;
 
 	/* Config options */
 	u32 creator;
@@ -143,40 +148,50 @@
 	int part, session;
 
 	unsigned long flags;
-
-	struct hlist_head rsrc_inodes;
 };
 
-#define HFSPLUS_SB_WRITEBACKUP	0x0001
-#define HFSPLUS_SB_NODECOMPOSE	0x0002
-#define HFSPLUS_SB_FORCE	0x0004
-#define HFSPLUS_SB_HFSX		0x0008
-#define HFSPLUS_SB_CASEFOLD	0x0010
+#define HFSPLUS_SB_WRITEBACKUP	0
+#define HFSPLUS_SB_NODECOMPOSE	1
+#define HFSPLUS_SB_FORCE	2
+#define HFSPLUS_SB_HFSX		3
+#define HFSPLUS_SB_CASEFOLD	4
 
 
 struct hfsplus_inode_info {
-	struct mutex extents_lock;
-	u32 clump_blocks, alloc_blocks;
-	sector_t fs_blocks;
-	/* Allocation extents from catalog record or volume header */
-	hfsplus_extent_rec first_extents;
-	u32 first_blocks;
-	hfsplus_extent_rec cached_extents;
-	u32 cached_start, cached_blocks;
 	atomic_t opencnt;
 
-	struct inode *rsrc_inode;
+	/*
+	 * Extent allocation information, protected by extents_lock.
+	 */
+	u32 first_blocks;
+	u32 clump_blocks;
+	u32 alloc_blocks;
+	u32 cached_start;
+	u32 cached_blocks;
+	hfsplus_extent_rec first_extents;
+	hfsplus_extent_rec cached_extents;
 	unsigned long flags;
+	struct mutex extents_lock;
 
+	/*
+	 * Immutable data.
+	 */
+	struct inode *rsrc_inode;
 	__be32 create_date;
-	/* Device number in hfsplus_permissions in catalog */
-	u32 dev;
-	/* BSD system and user file flags */
-	u8 rootflags;
-	u8 userflags;
 
+	/*
+	 * Protected by sbi->vh_mutex.
+	 */
+	u32 linkid;
+
+	/*
+	 * Protected by i_mutex.
+	 */
+	sector_t fs_blocks;
+	u8 userflags;		/* BSD user file flags */
 	struct list_head open_dir_list;
 	loff_t phys_size;
+
 	struct inode vfs_inode;
 };
 
@@ -184,8 +199,8 @@
 #define HFSPLUS_FLG_EXT_DIRTY	0x0002
 #define HFSPLUS_FLG_EXT_NEW	0x0004
 
-#define HFSPLUS_IS_DATA(inode)   (!(HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC))
-#define HFSPLUS_IS_RSRC(inode)   (HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC)
+#define HFSPLUS_IS_DATA(inode)   (!(HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC))
+#define HFSPLUS_IS_RSRC(inode)   (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC)
 
 struct hfs_find_data {
 	/* filled by caller */
@@ -311,6 +326,7 @@
 int hfsplus_delete_cat(u32, struct inode *, struct qstr *);
 int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
 		       struct inode *, struct qstr *);
+void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms);
 
 /* dir.c */
 extern const struct inode_operations hfsplus_dir_inode_operations;
@@ -372,26 +388,15 @@
 int hfs_part_find(struct super_block *, sector_t *, sector_t *);
 
 /* access macros */
-/*
 static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
 {
 	return sb->s_fs_info;
 }
+
 static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode)
 {
 	return list_entry(inode, struct hfsplus_inode_info, vfs_inode);
 }
-*/
-#define HFSPLUS_SB(super)	(*(struct hfsplus_sb_info *)(super)->s_fs_info)
-#define HFSPLUS_I(inode)	(*list_entry(inode, struct hfsplus_inode_info, vfs_inode))
-
-#if 1
-#define hfsplus_kmap(p)		({ struct page *__p = (p); kmap(__p); })
-#define hfsplus_kunmap(p)	({ struct page *__p = (p); kunmap(__p); __p; })
-#else
-#define hfsplus_kmap(p)		kmap(p)
-#define hfsplus_kunmap(p)	kunmap(p)
-#endif
 
 #define sb_bread512(sb, sec, data) ({			\
 	struct buffer_head *__bh;			\
@@ -419,6 +424,4 @@
 #define hfsp_ut2mt(t)		__hfsp_ut2mt((t).tv_sec)
 #define hfsp_now2mt()		__hfsp_ut2mt(get_seconds())
 
-#define kdev_t_to_nr(x)		(x)
-
 #endif
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index fe99fe8..6892899 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -200,6 +200,7 @@
 	struct hfsplus_unistr name;
 } __packed;
 
+#define HFSPLUS_CAT_KEYLEN	(sizeof(struct hfsplus_cat_key))
 
 /* Structs from hfs.h */
 struct hfsp_point {
@@ -323,7 +324,7 @@
 	__be32 start_block;
 } __packed;
 
-#define HFSPLUS_EXT_KEYLEN 12
+#define HFSPLUS_EXT_KEYLEN	sizeof(struct hfsplus_ext_key)
 
 /* HFS+ generic BTree key */
 typedef union {
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index c5a979d..7844928 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -36,7 +36,7 @@
 	*pagep = NULL;
 	ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
 				hfsplus_get_block,
-				&HFSPLUS_I(mapping->host).phys_size);
+				&HFSPLUS_I(mapping->host)->phys_size);
 	if (unlikely(ret)) {
 		loff_t isize = mapping->host->i_size;
 		if (pos + len > isize)
@@ -62,13 +62,13 @@
 
 	switch (inode->i_ino) {
 	case HFSPLUS_EXT_CNID:
-		tree = HFSPLUS_SB(sb).ext_tree;
+		tree = HFSPLUS_SB(sb)->ext_tree;
 		break;
 	case HFSPLUS_CAT_CNID:
-		tree = HFSPLUS_SB(sb).cat_tree;
+		tree = HFSPLUS_SB(sb)->cat_tree;
 		break;
 	case HFSPLUS_ATTR_CNID:
-		tree = HFSPLUS_SB(sb).attr_tree;
+		tree = HFSPLUS_SB(sb)->attr_tree;
 		break;
 	default:
 		BUG();
@@ -172,12 +172,13 @@
 	struct hfs_find_data fd;
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode = NULL;
+	struct hfsplus_inode_info *hip;
 	int err;
 
 	if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc"))
 		goto out;
 
-	inode = HFSPLUS_I(dir).rsrc_inode;
+	inode = HFSPLUS_I(dir)->rsrc_inode;
 	if (inode)
 		goto out;
 
@@ -185,12 +186,13 @@
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
 
+	hip = HFSPLUS_I(inode);
 	inode->i_ino = dir->i_ino;
-	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
-	mutex_init(&HFSPLUS_I(inode).extents_lock);
-	HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC;
+	INIT_LIST_HEAD(&hip->open_dir_list);
+	mutex_init(&hip->extents_lock);
+	hip->flags = HFSPLUS_FLG_RSRC;
 
-	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 	err = hfsplus_find_cat(sb, dir->i_ino, &fd);
 	if (!err)
 		err = hfsplus_cat_read_inode(inode, &fd);
@@ -199,10 +201,18 @@
 		iput(inode);
 		return ERR_PTR(err);
 	}
-	HFSPLUS_I(inode).rsrc_inode = dir;
-	HFSPLUS_I(dir).rsrc_inode = inode;
+	hip->rsrc_inode = dir;
+	HFSPLUS_I(dir)->rsrc_inode = inode;
 	igrab(dir);
-	hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes);
+
+	/*
+	 * __mark_inode_dirty expects inodes to be hashed.  Since we don't
+	 * want resource fork inodes in the regular inode space, we make them
+	 * appear hashed, but do not put on any lists.  hlist_del()
+	 * will work fine and require no locking.
+	 */
+	inode->i_hash.pprev = &inode->i_hash.next;
+
 	mark_inode_dirty(inode);
 out:
 	d_add(dentry, inode);
@@ -211,30 +221,27 @@
 
 static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir)
 {
-	struct super_block *sb = inode->i_sb;
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
 	u16 mode;
 
 	mode = be16_to_cpu(perms->mode);
 
 	inode->i_uid = be32_to_cpu(perms->owner);
 	if (!inode->i_uid && !mode)
-		inode->i_uid = HFSPLUS_SB(sb).uid;
+		inode->i_uid = sbi->uid;
 
 	inode->i_gid = be32_to_cpu(perms->group);
 	if (!inode->i_gid && !mode)
-		inode->i_gid = HFSPLUS_SB(sb).gid;
+		inode->i_gid = sbi->gid;
 
 	if (dir) {
-		mode = mode ? (mode & S_IALLUGO) :
-			(S_IRWXUGO & ~(HFSPLUS_SB(sb).umask));
+		mode = mode ? (mode & S_IALLUGO) : (S_IRWXUGO & ~(sbi->umask));
 		mode |= S_IFDIR;
 	} else if (!mode)
-		mode = S_IFREG | ((S_IRUGO|S_IWUGO) &
-			~(HFSPLUS_SB(sb).umask));
+		mode = S_IFREG | ((S_IRUGO|S_IWUGO) & ~(sbi->umask));
 	inode->i_mode = mode;
 
-	HFSPLUS_I(inode).rootflags = perms->rootflags;
-	HFSPLUS_I(inode).userflags = perms->userflags;
+	HFSPLUS_I(inode)->userflags = perms->userflags;
 	if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE)
 		inode->i_flags |= S_IMMUTABLE;
 	else
@@ -245,30 +252,13 @@
 		inode->i_flags &= ~S_APPEND;
 }
 
-static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
-{
-	if (inode->i_flags & S_IMMUTABLE)
-		perms->rootflags |= HFSPLUS_FLG_IMMUTABLE;
-	else
-		perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE;
-	if (inode->i_flags & S_APPEND)
-		perms->rootflags |= HFSPLUS_FLG_APPEND;
-	else
-		perms->rootflags &= ~HFSPLUS_FLG_APPEND;
-	perms->userflags = HFSPLUS_I(inode).userflags;
-	perms->mode = cpu_to_be16(inode->i_mode);
-	perms->owner = cpu_to_be32(inode->i_uid);
-	perms->group = cpu_to_be32(inode->i_gid);
-	perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev);
-}
-
 static int hfsplus_file_open(struct inode *inode, struct file *file)
 {
 	if (HFSPLUS_IS_RSRC(inode))
-		inode = HFSPLUS_I(inode).rsrc_inode;
+		inode = HFSPLUS_I(inode)->rsrc_inode;
 	if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
 		return -EOVERFLOW;
-	atomic_inc(&HFSPLUS_I(inode).opencnt);
+	atomic_inc(&HFSPLUS_I(inode)->opencnt);
 	return 0;
 }
 
@@ -277,12 +267,13 @@
 	struct super_block *sb = inode->i_sb;
 
 	if (HFSPLUS_IS_RSRC(inode))
-		inode = HFSPLUS_I(inode).rsrc_inode;
-	if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) {
+		inode = HFSPLUS_I(inode)->rsrc_inode;
+	if (atomic_dec_and_test(&HFSPLUS_I(inode)->opencnt)) {
 		mutex_lock(&inode->i_mutex);
 		hfsplus_file_truncate(inode);
 		if (inode->i_flags & S_DEAD) {
-			hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL);
+			hfsplus_delete_cat(inode->i_ino,
+					   HFSPLUS_SB(sb)->hidden_dir, NULL);
 			hfsplus_delete_inode(inode);
 		}
 		mutex_unlock(&inode->i_mutex);
@@ -361,47 +352,52 @@
 
 struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
 {
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
 	struct inode *inode = new_inode(sb);
+	struct hfsplus_inode_info *hip;
+
 	if (!inode)
 		return NULL;
 
-	inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
+	inode->i_ino = sbi->next_cnid++;
 	inode->i_mode = mode;
 	inode->i_uid = current_fsuid();
 	inode->i_gid = current_fsgid();
 	inode->i_nlink = 1;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
-	mutex_init(&HFSPLUS_I(inode).extents_lock);
-	atomic_set(&HFSPLUS_I(inode).opencnt, 0);
-	HFSPLUS_I(inode).flags = 0;
-	memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec));
-	memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec));
-	HFSPLUS_I(inode).alloc_blocks = 0;
-	HFSPLUS_I(inode).first_blocks = 0;
-	HFSPLUS_I(inode).cached_start = 0;
-	HFSPLUS_I(inode).cached_blocks = 0;
-	HFSPLUS_I(inode).phys_size = 0;
-	HFSPLUS_I(inode).fs_blocks = 0;
-	HFSPLUS_I(inode).rsrc_inode = NULL;
+
+	hip = HFSPLUS_I(inode);
+	INIT_LIST_HEAD(&hip->open_dir_list);
+	mutex_init(&hip->extents_lock);
+	atomic_set(&hip->opencnt, 0);
+	hip->flags = 0;
+	memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec));
+	memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
+	hip->alloc_blocks = 0;
+	hip->first_blocks = 0;
+	hip->cached_start = 0;
+	hip->cached_blocks = 0;
+	hip->phys_size = 0;
+	hip->fs_blocks = 0;
+	hip->rsrc_inode = NULL;
 	if (S_ISDIR(inode->i_mode)) {
 		inode->i_size = 2;
-		HFSPLUS_SB(sb).folder_count++;
+		sbi->folder_count++;
 		inode->i_op = &hfsplus_dir_inode_operations;
 		inode->i_fop = &hfsplus_dir_operations;
 	} else if (S_ISREG(inode->i_mode)) {
-		HFSPLUS_SB(sb).file_count++;
+		sbi->file_count++;
 		inode->i_op = &hfsplus_file_inode_operations;
 		inode->i_fop = &hfsplus_file_operations;
 		inode->i_mapping->a_ops = &hfsplus_aops;
-		HFSPLUS_I(inode).clump_blocks = HFSPLUS_SB(sb).data_clump_blocks;
+		hip->clump_blocks = sbi->data_clump_blocks;
 	} else if (S_ISLNK(inode->i_mode)) {
-		HFSPLUS_SB(sb).file_count++;
+		sbi->file_count++;
 		inode->i_op = &page_symlink_inode_operations;
 		inode->i_mapping->a_ops = &hfsplus_aops;
-		HFSPLUS_I(inode).clump_blocks = 1;
+		hip->clump_blocks = 1;
 	} else
-		HFSPLUS_SB(sb).file_count++;
+		sbi->file_count++;
 	insert_inode_hash(inode);
 	mark_inode_dirty(inode);
 	sb->s_dirt = 1;
@@ -414,11 +410,11 @@
 	struct super_block *sb = inode->i_sb;
 
 	if (S_ISDIR(inode->i_mode)) {
-		HFSPLUS_SB(sb).folder_count--;
+		HFSPLUS_SB(sb)->folder_count--;
 		sb->s_dirt = 1;
 		return;
 	}
-	HFSPLUS_SB(sb).file_count--;
+	HFSPLUS_SB(sb)->file_count--;
 	if (S_ISREG(inode->i_mode)) {
 		if (!inode->i_nlink) {
 			inode->i_size = 0;
@@ -434,34 +430,39 @@
 void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
 {
 	struct super_block *sb = inode->i_sb;
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	u32 count;
 	int i;
 
-	memcpy(&HFSPLUS_I(inode).first_extents, &fork->extents,
-	       sizeof(hfsplus_extent_rec));
+	memcpy(&hip->first_extents, &fork->extents, sizeof(hfsplus_extent_rec));
 	for (count = 0, i = 0; i < 8; i++)
 		count += be32_to_cpu(fork->extents[i].block_count);
-	HFSPLUS_I(inode).first_blocks = count;
-	memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec));
-	HFSPLUS_I(inode).cached_start = 0;
-	HFSPLUS_I(inode).cached_blocks = 0;
+	hip->first_blocks = count;
+	memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
+	hip->cached_start = 0;
+	hip->cached_blocks = 0;
 
-	HFSPLUS_I(inode).alloc_blocks = be32_to_cpu(fork->total_blocks);
-	inode->i_size = HFSPLUS_I(inode).phys_size = be64_to_cpu(fork->total_size);
-	HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
-	inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits);
-	HFSPLUS_I(inode).clump_blocks = be32_to_cpu(fork->clump_size) >> HFSPLUS_SB(sb).alloc_blksz_shift;
-	if (!HFSPLUS_I(inode).clump_blocks)
-		HFSPLUS_I(inode).clump_blocks = HFSPLUS_IS_RSRC(inode) ? HFSPLUS_SB(sb).rsrc_clump_blocks :
-				HFSPLUS_SB(sb).data_clump_blocks;
+	hip->alloc_blocks = be32_to_cpu(fork->total_blocks);
+	hip->phys_size = inode->i_size = be64_to_cpu(fork->total_size);
+	hip->fs_blocks =
+		(inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits);
+	hip->clump_blocks =
+		be32_to_cpu(fork->clump_size) >> sbi->alloc_blksz_shift;
+	if (!hip->clump_blocks) {
+		hip->clump_blocks = HFSPLUS_IS_RSRC(inode) ?
+			sbi->rsrc_clump_blocks :
+			sbi->data_clump_blocks;
+	}
 }
 
 void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
 {
-	memcpy(&fork->extents, &HFSPLUS_I(inode).first_extents,
+	memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents,
 	       sizeof(hfsplus_extent_rec));
 	fork->total_size = cpu_to_be64(inode->i_size);
-	fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode).alloc_blocks);
+	fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode)->alloc_blocks);
 }
 
 int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
@@ -472,7 +473,7 @@
 
 	type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
 
-	HFSPLUS_I(inode).dev = 0;
+	HFSPLUS_I(inode)->linkid = 0;
 	if (type == HFSPLUS_FOLDER) {
 		struct hfsplus_cat_folder *folder = &entry.folder;
 
@@ -486,8 +487,8 @@
 		inode->i_atime = hfsp_mt2ut(folder->access_date);
 		inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
 		inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
-		HFSPLUS_I(inode).create_date = folder->create_date;
-		HFSPLUS_I(inode).fs_blocks = 0;
+		HFSPLUS_I(inode)->create_date = folder->create_date;
+		HFSPLUS_I(inode)->fs_blocks = 0;
 		inode->i_op = &hfsplus_dir_inode_operations;
 		inode->i_fop = &hfsplus_dir_operations;
 	} else if (type == HFSPLUS_FILE) {
@@ -518,7 +519,7 @@
 		inode->i_atime = hfsp_mt2ut(file->access_date);
 		inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
 		inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
-		HFSPLUS_I(inode).create_date = file->create_date;
+		HFSPLUS_I(inode)->create_date = file->create_date;
 	} else {
 		printk(KERN_ERR "hfs: bad catalog entry used to create inode\n");
 		res = -EIO;
@@ -533,12 +534,12 @@
 	hfsplus_cat_entry entry;
 
 	if (HFSPLUS_IS_RSRC(inode))
-		main_inode = HFSPLUS_I(inode).rsrc_inode;
+		main_inode = HFSPLUS_I(inode)->rsrc_inode;
 
 	if (!main_inode->i_nlink)
 		return 0;
 
-	if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb).cat_tree, &fd))
+	if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb)->cat_tree, &fd))
 		/* panic? */
 		return -EIO;
 
@@ -554,7 +555,7 @@
 		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
 					sizeof(struct hfsplus_cat_folder));
 		/* simple node checks? */
-		hfsplus_set_perms(inode, &folder->permissions);
+		hfsplus_cat_set_perms(inode, &folder->permissions);
 		folder->access_date = hfsp_ut2mt(inode->i_atime);
 		folder->content_mod_date = hfsp_ut2mt(inode->i_mtime);
 		folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime);
@@ -576,11 +577,7 @@
 		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
 					sizeof(struct hfsplus_cat_file));
 		hfsplus_inode_write_fork(inode, &file->data_fork);
-		if (S_ISREG(inode->i_mode))
-			HFSPLUS_I(inode).dev = inode->i_nlink;
-		if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-			HFSPLUS_I(inode).dev = kdev_t_to_nr(inode->i_rdev);
-		hfsplus_set_perms(inode, &file->permissions);
+		hfsplus_cat_set_perms(inode, &file->permissions);
 		if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
 			file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
 		else
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
index ac405f0..5b4667e 100644
--- a/fs/hfsplus/ioctl.c
+++ b/fs/hfsplus/ioctl.c
@@ -17,83 +17,98 @@
 #include <linux/mount.h>
 #include <linux/sched.h>
 #include <linux/xattr.h>
-#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include "hfsplus_fs.h"
 
-long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
 {
-	struct inode *inode = filp->f_path.dentry->d_inode;
-	unsigned int flags;
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
+	unsigned int flags = 0;
 
-	lock_kernel();
+	if (inode->i_flags & S_IMMUTABLE)
+		flags |= FS_IMMUTABLE_FL;
+	if (inode->i_flags |= S_APPEND)
+		flags |= FS_APPEND_FL;
+	if (hip->userflags & HFSPLUS_FLG_NODUMP)
+		flags |= FS_NODUMP_FL;
+
+	return put_user(flags, user_flags);
+}
+
+static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
+	unsigned int flags;
+	int err = 0;
+
+	err = mnt_want_write(file->f_path.mnt);
+	if (err)
+		goto out;
+
+	if (!is_owner_or_cap(inode)) {
+		err = -EACCES;
+		goto out_drop_write;
+	}
+
+	if (get_user(flags, user_flags)) {
+		err = -EFAULT;
+		goto out_drop_write;
+	}
+
+	mutex_lock(&inode->i_mutex);
+
+	if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
+	    inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
+		if (!capable(CAP_LINUX_IMMUTABLE)) {
+			err = -EPERM;
+			goto out_unlock_inode;
+		}
+	}
+
+	/* don't silently ignore unsupported ext2 flags */
+	if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
+		err = -EOPNOTSUPP;
+		goto out_unlock_inode;
+	}
+
+	if (flags & FS_IMMUTABLE_FL)
+		inode->i_flags |= S_IMMUTABLE;
+	else
+		inode->i_flags &= ~S_IMMUTABLE;
+
+	if (flags & FS_APPEND_FL)
+		inode->i_flags |= S_APPEND;
+	else
+		inode->i_flags &= ~S_APPEND;
+
+	if (flags & FS_NODUMP_FL)
+		hip->userflags |= HFSPLUS_FLG_NODUMP;
+	else
+		hip->userflags &= ~HFSPLUS_FLG_NODUMP;
+
+	inode->i_ctime = CURRENT_TIME_SEC;
+	mark_inode_dirty(inode);
+
+out_unlock_inode:
+	mutex_lock(&inode->i_mutex);
+out_drop_write:
+	mnt_drop_write(file->f_path.mnt);
+out:
+	return err;
+}
+
+long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+
 	switch (cmd) {
 	case HFSPLUS_IOC_EXT2_GETFLAGS:
-		flags = 0;
-		if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_IMMUTABLE)
-			flags |= FS_IMMUTABLE_FL; /* EXT2_IMMUTABLE_FL */
-		if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_APPEND)
-			flags |= FS_APPEND_FL; /* EXT2_APPEND_FL */
-		if (HFSPLUS_I(inode).userflags & HFSPLUS_FLG_NODUMP)
-			flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */
-		return put_user(flags, (int __user *)arg);
-	case HFSPLUS_IOC_EXT2_SETFLAGS: {
-		int err = 0;
-		err = mnt_want_write(filp->f_path.mnt);
-		if (err) {
-			unlock_kernel();
-			return err;
-		}
-
-		if (!is_owner_or_cap(inode)) {
-			err = -EACCES;
-			goto setflags_out;
-		}
-		if (get_user(flags, (int __user *)arg)) {
-			err = -EFAULT;
-			goto setflags_out;
-		}
-		if (flags & (FS_IMMUTABLE_FL|FS_APPEND_FL) ||
-		    HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) {
-			if (!capable(CAP_LINUX_IMMUTABLE)) {
-				err = -EPERM;
-				goto setflags_out;
-			}
-		}
-
-		/* don't silently ignore unsupported ext2 flags */
-		if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
-			err = -EOPNOTSUPP;
-			goto setflags_out;
-		}
-		if (flags & FS_IMMUTABLE_FL) { /* EXT2_IMMUTABLE_FL */
-			inode->i_flags |= S_IMMUTABLE;
-			HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE;
-		} else {
-			inode->i_flags &= ~S_IMMUTABLE;
-			HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_IMMUTABLE;
-		}
-		if (flags & FS_APPEND_FL) { /* EXT2_APPEND_FL */
-			inode->i_flags |= S_APPEND;
-			HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_APPEND;
-		} else {
-			inode->i_flags &= ~S_APPEND;
-			HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_APPEND;
-		}
-		if (flags & FS_NODUMP_FL) /* EXT2_NODUMP_FL */
-			HFSPLUS_I(inode).userflags |= HFSPLUS_FLG_NODUMP;
-		else
-			HFSPLUS_I(inode).userflags &= ~HFSPLUS_FLG_NODUMP;
-
-		inode->i_ctime = CURRENT_TIME_SEC;
-		mark_inode_dirty(inode);
-setflags_out:
-		mnt_drop_write(filp->f_path.mnt);
-		unlock_kernel();
-		return err;
-	}
+		return hfsplus_ioctl_getflags(file, argp);
+	case HFSPLUS_IOC_EXT2_SETFLAGS:
+		return hfsplus_ioctl_setflags(file, argp);
 	default:
-		unlock_kernel();
 		return -ENOTTY;
 	}
 }
@@ -110,7 +125,7 @@
 	if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
 		return -EOPNOTSUPP;
 
-	res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd);
+	res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
 	if (res)
 		return res;
 	res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
@@ -153,7 +168,7 @@
 		return -EOPNOTSUPP;
 
 	if (size) {
-		res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd);
+		res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
 		if (res)
 			return res;
 		res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
@@ -177,7 +192,7 @@
 		} else
 			res = size ? -ERANGE : 4;
 	} else
-		res = -ENODATA;
+		res = -EOPNOTSUPP;
 out:
 	if (size)
 		hfs_find_exit(&fd);
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index 572628b..f9ab276 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -143,13 +143,13 @@
 			kfree(p);
 			break;
 		case opt_decompose:
-			sbi->flags &= ~HFSPLUS_SB_NODECOMPOSE;
+			clear_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags);
 			break;
 		case opt_nodecompose:
-			sbi->flags |= HFSPLUS_SB_NODECOMPOSE;
+			set_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags);
 			break;
 		case opt_force:
-			sbi->flags |= HFSPLUS_SB_FORCE;
+			set_bit(HFSPLUS_SB_FORCE, &sbi->flags);
 			break;
 		default:
 			return 0;
@@ -171,7 +171,7 @@
 
 int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt)
 {
-	struct hfsplus_sb_info *sbi = &HFSPLUS_SB(mnt->mnt_sb);
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(mnt->mnt_sb);
 
 	if (sbi->creator != HFSPLUS_DEF_CR_TYPE)
 		seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator);
@@ -184,7 +184,7 @@
 		seq_printf(seq, ",session=%u", sbi->session);
 	if (sbi->nls)
 		seq_printf(seq, ",nls=%s", sbi->nls->charset);
-	if (sbi->flags & HFSPLUS_SB_NODECOMPOSE)
+	if (test_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags))
 		seq_printf(seq, ",nodecompose");
 	return 0;
 }
diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c
index 1528a6f..208b16c 100644
--- a/fs/hfsplus/part_tbl.c
+++ b/fs/hfsplus/part_tbl.c
@@ -74,6 +74,7 @@
 int hfs_part_find(struct super_block *sb,
 		  sector_t *part_start, sector_t *part_size)
 {
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
 	struct buffer_head *bh;
 	__be16 *data;
 	int i, size, res;
@@ -95,7 +96,7 @@
 		for (i = 0; i < size; p++, i++) {
 			if (p->pdStart && p->pdSize &&
 			    p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
-			    (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) {
+			    (sbi->part < 0 || sbi->part == i)) {
 				*part_start += be32_to_cpu(p->pdStart);
 				*part_size = be32_to_cpu(p->pdSize);
 				res = 0;
@@ -111,7 +112,7 @@
 		size = be32_to_cpu(pm->pmMapBlkCnt);
 		for (i = 0; i < size;) {
 			if (!memcmp(pm->pmPartType,"Apple_HFS", 9) &&
-			    (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) {
+			    (sbi->part < 0 || sbi->part == i)) {
 				*part_start += be32_to_cpu(pm->pmPyPartStart);
 				*part_size = be32_to_cpu(pm->pmPartBlkCnt);
 				res = 0;
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 3b55c05..9a88d75 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -12,7 +12,6 @@
 #include <linux/pagemap.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 #include <linux/nls.h>
 
@@ -21,40 +20,11 @@
 
 #include "hfsplus_fs.h"
 
-struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino)
+static int hfsplus_system_read_inode(struct inode *inode)
 {
-	struct hfs_find_data fd;
-	struct hfsplus_vh *vhdr;
-	struct inode *inode;
-	long err = -EIO;
+	struct hfsplus_vh *vhdr = HFSPLUS_SB(inode->i_sb)->s_vhdr;
 
-	inode = iget_locked(sb, ino);
-	if (!inode)
-		return ERR_PTR(-ENOMEM);
-	if (!(inode->i_state & I_NEW))
-		return inode;
-
-	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
-	mutex_init(&HFSPLUS_I(inode).extents_lock);
-	HFSPLUS_I(inode).flags = 0;
-	HFSPLUS_I(inode).rsrc_inode = NULL;
-	atomic_set(&HFSPLUS_I(inode).opencnt, 0);
-
-	if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) {
-	read_inode:
-		hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd);
-		err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
-		if (!err)
-			err = hfsplus_cat_read_inode(inode, &fd);
-		hfs_find_exit(&fd);
-		if (err)
-			goto bad_inode;
-		goto done;
-	}
-	vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr;
-	switch(inode->i_ino) {
-	case HFSPLUS_ROOT_CNID:
-		goto read_inode;
+	switch (inode->i_ino) {
 	case HFSPLUS_EXT_CNID:
 		hfsplus_inode_read_fork(inode, &vhdr->ext_file);
 		inode->i_mapping->a_ops = &hfsplus_btree_aops;
@@ -75,74 +45,101 @@
 		inode->i_mapping->a_ops = &hfsplus_btree_aops;
 		break;
 	default:
-		goto bad_inode;
+		return -EIO;
 	}
 
-done:
+	return 0;
+}
+
+struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino)
+{
+	struct hfs_find_data fd;
+	struct inode *inode;
+	int err;
+
+	inode = iget_locked(sb, ino);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+	if (!(inode->i_state & I_NEW))
+		return inode;
+
+	INIT_LIST_HEAD(&HFSPLUS_I(inode)->open_dir_list);
+	mutex_init(&HFSPLUS_I(inode)->extents_lock);
+	HFSPLUS_I(inode)->flags = 0;
+	HFSPLUS_I(inode)->rsrc_inode = NULL;
+	atomic_set(&HFSPLUS_I(inode)->opencnt, 0);
+
+	if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID ||
+	    inode->i_ino == HFSPLUS_ROOT_CNID) {
+		hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
+		err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
+		if (!err)
+			err = hfsplus_cat_read_inode(inode, &fd);
+		hfs_find_exit(&fd);
+	} else {
+		err = hfsplus_system_read_inode(inode);
+	}
+
+	if (err) {
+		iget_failed(inode);
+		return ERR_PTR(err);
+	}
+
 	unlock_new_inode(inode);
 	return inode;
+}
 
-bad_inode:
-	iget_failed(inode);
-	return ERR_PTR(err);
+static int hfsplus_system_write_inode(struct inode *inode)
+{
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
+	struct hfsplus_vh *vhdr = sbi->s_vhdr;
+	struct hfsplus_fork_raw *fork;
+	struct hfs_btree *tree = NULL;
+
+	switch (inode->i_ino) {
+	case HFSPLUS_EXT_CNID:
+		fork = &vhdr->ext_file;
+		tree = sbi->ext_tree;
+		break;
+	case HFSPLUS_CAT_CNID:
+		fork = &vhdr->cat_file;
+		tree = sbi->cat_tree;
+		break;
+	case HFSPLUS_ALLOC_CNID:
+		fork = &vhdr->alloc_file;
+		break;
+	case HFSPLUS_START_CNID:
+		fork = &vhdr->start_file;
+		break;
+	case HFSPLUS_ATTR_CNID:
+		fork = &vhdr->attr_file;
+		tree = sbi->attr_tree;
+	default:
+		return -EIO;
+	}
+
+	if (fork->total_size != cpu_to_be64(inode->i_size)) {
+		set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags);
+		inode->i_sb->s_dirt = 1;
+	}
+	hfsplus_inode_write_fork(inode, fork);
+	if (tree)
+		hfs_btree_write(tree);
+	return 0;
 }
 
 static int hfsplus_write_inode(struct inode *inode,
 		struct writeback_control *wbc)
 {
-	struct hfsplus_vh *vhdr;
-	int ret = 0;
-
 	dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino);
+
 	hfsplus_ext_write_extent(inode);
-	if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) {
+
+	if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID ||
+	    inode->i_ino == HFSPLUS_ROOT_CNID)
 		return hfsplus_cat_write_inode(inode);
-	}
-	vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr;
-	switch (inode->i_ino) {
-	case HFSPLUS_ROOT_CNID:
-		ret = hfsplus_cat_write_inode(inode);
-		break;
-	case HFSPLUS_EXT_CNID:
-		if (vhdr->ext_file.total_size != cpu_to_be64(inode->i_size)) {
-			HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
-			inode->i_sb->s_dirt = 1;
-		}
-		hfsplus_inode_write_fork(inode, &vhdr->ext_file);
-		hfs_btree_write(HFSPLUS_SB(inode->i_sb).ext_tree);
-		break;
-	case HFSPLUS_CAT_CNID:
-		if (vhdr->cat_file.total_size != cpu_to_be64(inode->i_size)) {
-			HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
-			inode->i_sb->s_dirt = 1;
-		}
-		hfsplus_inode_write_fork(inode, &vhdr->cat_file);
-		hfs_btree_write(HFSPLUS_SB(inode->i_sb).cat_tree);
-		break;
-	case HFSPLUS_ALLOC_CNID:
-		if (vhdr->alloc_file.total_size != cpu_to_be64(inode->i_size)) {
-			HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
-			inode->i_sb->s_dirt = 1;
-		}
-		hfsplus_inode_write_fork(inode, &vhdr->alloc_file);
-		break;
-	case HFSPLUS_START_CNID:
-		if (vhdr->start_file.total_size != cpu_to_be64(inode->i_size)) {
-			HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
-			inode->i_sb->s_dirt = 1;
-		}
-		hfsplus_inode_write_fork(inode, &vhdr->start_file);
-		break;
-	case HFSPLUS_ATTR_CNID:
-		if (vhdr->attr_file.total_size != cpu_to_be64(inode->i_size)) {
-			HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP;
-			inode->i_sb->s_dirt = 1;
-		}
-		hfsplus_inode_write_fork(inode, &vhdr->attr_file);
-		hfs_btree_write(HFSPLUS_SB(inode->i_sb).attr_tree);
-		break;
-	}
-	return ret;
+	else
+		return hfsplus_system_write_inode(inode);
 }
 
 static void hfsplus_evict_inode(struct inode *inode)
@@ -151,51 +148,53 @@
 	truncate_inode_pages(&inode->i_data, 0);
 	end_writeback(inode);
 	if (HFSPLUS_IS_RSRC(inode)) {
-		HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL;
-		iput(HFSPLUS_I(inode).rsrc_inode);
+		HFSPLUS_I(HFSPLUS_I(inode)->rsrc_inode)->rsrc_inode = NULL;
+		iput(HFSPLUS_I(inode)->rsrc_inode);
 	}
 }
 
 int hfsplus_sync_fs(struct super_block *sb, int wait)
 {
-	struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+	struct hfsplus_vh *vhdr = sbi->s_vhdr;
 
 	dprint(DBG_SUPER, "hfsplus_write_super\n");
 
-	lock_super(sb);
+	mutex_lock(&sbi->vh_mutex);
+	mutex_lock(&sbi->alloc_mutex);
 	sb->s_dirt = 0;
 
-	vhdr->free_blocks = cpu_to_be32(HFSPLUS_SB(sb).free_blocks);
-	vhdr->next_alloc = cpu_to_be32(HFSPLUS_SB(sb).next_alloc);
-	vhdr->next_cnid = cpu_to_be32(HFSPLUS_SB(sb).next_cnid);
-	vhdr->folder_count = cpu_to_be32(HFSPLUS_SB(sb).folder_count);
-	vhdr->file_count = cpu_to_be32(HFSPLUS_SB(sb).file_count);
+	vhdr->free_blocks = cpu_to_be32(sbi->free_blocks);
+	vhdr->next_cnid = cpu_to_be32(sbi->next_cnid);
+	vhdr->folder_count = cpu_to_be32(sbi->folder_count);
+	vhdr->file_count = cpu_to_be32(sbi->file_count);
 
-	mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
-	if (HFSPLUS_SB(sb).flags & HFSPLUS_SB_WRITEBACKUP) {
-		if (HFSPLUS_SB(sb).sect_count) {
+	mark_buffer_dirty(sbi->s_vhbh);
+	if (test_and_clear_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags)) {
+		if (sbi->sect_count) {
 			struct buffer_head *bh;
 			u32 block, offset;
 
-			block = HFSPLUS_SB(sb).blockoffset;
-			block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9);
-			offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1);
-			printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset,
-				HFSPLUS_SB(sb).sect_count, block, offset);
+			block = sbi->blockoffset;
+			block += (sbi->sect_count - 2) >> (sb->s_blocksize_bits - 9);
+			offset = ((sbi->sect_count - 2) << 9) & (sb->s_blocksize - 1);
+			printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n",
+					  sbi->blockoffset, sbi->sect_count,
+					  block, offset);
 			bh = sb_bread(sb, block);
 			if (bh) {
 				vhdr = (struct hfsplus_vh *)(bh->b_data + offset);
 				if (be16_to_cpu(vhdr->signature) == HFSPLUS_VOLHEAD_SIG) {
-					memcpy(vhdr, HFSPLUS_SB(sb).s_vhdr, sizeof(*vhdr));
+					memcpy(vhdr, sbi->s_vhdr, sizeof(*vhdr));
 					mark_buffer_dirty(bh);
 					brelse(bh);
 				} else
 					printk(KERN_WARNING "hfs: backup not found!\n");
 			}
 		}
-		HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP;
 	}
-	unlock_super(sb);
+	mutex_unlock(&sbi->alloc_mutex);
+	mutex_unlock(&sbi->vh_mutex);
 	return 0;
 }
 
@@ -209,48 +208,48 @@
 
 static void hfsplus_put_super(struct super_block *sb)
 {
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+
 	dprint(DBG_SUPER, "hfsplus_put_super\n");
+
 	if (!sb->s_fs_info)
 		return;
 
-	lock_kernel();
-
 	if (sb->s_dirt)
 		hfsplus_write_super(sb);
-	if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) {
-		struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
+	if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) {
+		struct hfsplus_vh *vhdr = sbi->s_vhdr;
 
 		vhdr->modify_date = hfsp_now2mt();
 		vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT);
 		vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT);
-		mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
-		sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
+		mark_buffer_dirty(sbi->s_vhbh);
+		sync_dirty_buffer(sbi->s_vhbh);
 	}
 
-	hfs_btree_close(HFSPLUS_SB(sb).cat_tree);
-	hfs_btree_close(HFSPLUS_SB(sb).ext_tree);
-	iput(HFSPLUS_SB(sb).alloc_file);
-	iput(HFSPLUS_SB(sb).hidden_dir);
-	brelse(HFSPLUS_SB(sb).s_vhbh);
-	unload_nls(HFSPLUS_SB(sb).nls);
+	hfs_btree_close(sbi->cat_tree);
+	hfs_btree_close(sbi->ext_tree);
+	iput(sbi->alloc_file);
+	iput(sbi->hidden_dir);
+	brelse(sbi->s_vhbh);
+	unload_nls(sbi->nls);
 	kfree(sb->s_fs_info);
 	sb->s_fs_info = NULL;
-
-	unlock_kernel();
 }
 
 static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct super_block *sb = dentry->d_sb;
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
 	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
 	buf->f_type = HFSPLUS_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
-	buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift;
-	buf->f_bfree = HFSPLUS_SB(sb).free_blocks << HFSPLUS_SB(sb).fs_shift;
+	buf->f_blocks = sbi->total_blocks << sbi->fs_shift;
+	buf->f_bfree = sbi->free_blocks << sbi->fs_shift;
 	buf->f_bavail = buf->f_bfree;
 	buf->f_files = 0xFFFFFFFF;
-	buf->f_ffree = 0xFFFFFFFF - HFSPLUS_SB(sb).next_cnid;
+	buf->f_ffree = 0xFFFFFFFF - sbi->next_cnid;
 	buf->f_fsid.val[0] = (u32)id;
 	buf->f_fsid.val[1] = (u32)(id >> 32);
 	buf->f_namelen = HFSPLUS_MAX_STRLEN;
@@ -263,11 +262,11 @@
 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
 		return 0;
 	if (!(*flags & MS_RDONLY)) {
-		struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
+		struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr;
 		struct hfsplus_sb_info sbi;
 
 		memset(&sbi, 0, sizeof(struct hfsplus_sb_info));
-		sbi.nls = HFSPLUS_SB(sb).nls;
+		sbi.nls = HFSPLUS_SB(sb)->nls;
 		if (!hfsplus_parse_options(data, &sbi))
 			return -EINVAL;
 
@@ -276,7 +275,7 @@
 			       "running fsck.hfsplus is recommended.  leaving read-only.\n");
 			sb->s_flags |= MS_RDONLY;
 			*flags |= MS_RDONLY;
-		} else if (sbi.flags & HFSPLUS_SB_FORCE) {
+		} else if (test_bit(HFSPLUS_SB_FORCE, &sbi.flags)) {
 			/* nothing */
 		} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
 			printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n");
@@ -320,7 +319,8 @@
 		return -ENOMEM;
 
 	sb->s_fs_info = sbi;
-	INIT_HLIST_HEAD(&sbi->rsrc_inodes);
+	mutex_init(&sbi->alloc_mutex);
+	mutex_init(&sbi->vh_mutex);
 	hfsplus_fill_defaults(sbi);
 	if (!hfsplus_parse_options(data, sbi)) {
 		printk(KERN_ERR "hfs: unable to parse mount options\n");
@@ -344,7 +344,7 @@
 		err = -EINVAL;
 		goto cleanup;
 	}
-	vhdr = HFSPLUS_SB(sb).s_vhdr;
+	vhdr = sbi->s_vhdr;
 
 	/* Copy parts of the volume header into the superblock */
 	sb->s_magic = HFSPLUS_VOLHEAD_SIG;
@@ -353,18 +353,19 @@
 		printk(KERN_ERR "hfs: wrong filesystem version\n");
 		goto cleanup;
 	}
-	HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks);
-	HFSPLUS_SB(sb).free_blocks = be32_to_cpu(vhdr->free_blocks);
-	HFSPLUS_SB(sb).next_alloc = be32_to_cpu(vhdr->next_alloc);
-	HFSPLUS_SB(sb).next_cnid = be32_to_cpu(vhdr->next_cnid);
-	HFSPLUS_SB(sb).file_count = be32_to_cpu(vhdr->file_count);
-	HFSPLUS_SB(sb).folder_count = be32_to_cpu(vhdr->folder_count);
-	HFSPLUS_SB(sb).data_clump_blocks = be32_to_cpu(vhdr->data_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift;
-	if (!HFSPLUS_SB(sb).data_clump_blocks)
-		HFSPLUS_SB(sb).data_clump_blocks = 1;
-	HFSPLUS_SB(sb).rsrc_clump_blocks = be32_to_cpu(vhdr->rsrc_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift;
-	if (!HFSPLUS_SB(sb).rsrc_clump_blocks)
-		HFSPLUS_SB(sb).rsrc_clump_blocks = 1;
+	sbi->total_blocks = be32_to_cpu(vhdr->total_blocks);
+	sbi->free_blocks = be32_to_cpu(vhdr->free_blocks);
+	sbi->next_cnid = be32_to_cpu(vhdr->next_cnid);
+	sbi->file_count = be32_to_cpu(vhdr->file_count);
+	sbi->folder_count = be32_to_cpu(vhdr->folder_count);
+	sbi->data_clump_blocks =
+		be32_to_cpu(vhdr->data_clump_sz) >> sbi->alloc_blksz_shift;
+	if (!sbi->data_clump_blocks)
+		sbi->data_clump_blocks = 1;
+	sbi->rsrc_clump_blocks =
+		be32_to_cpu(vhdr->rsrc_clump_sz) >> sbi->alloc_blksz_shift;
+	if (!sbi->rsrc_clump_blocks)
+		sbi->rsrc_clump_blocks = 1;
 
 	/* Set up operations so we can load metadata */
 	sb->s_op = &hfsplus_sops;
@@ -374,7 +375,7 @@
 		printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, "
 		       "running fsck.hfsplus is recommended.  mounting read-only.\n");
 		sb->s_flags |= MS_RDONLY;
-	} else if (sbi->flags & HFSPLUS_SB_FORCE) {
+	} else if (test_and_clear_bit(HFSPLUS_SB_FORCE, &sbi->flags)) {
 		/* nothing */
 	} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
 		printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n");
@@ -384,16 +385,15 @@
 		       "use the force option at your own risk, mounting read-only.\n");
 		sb->s_flags |= MS_RDONLY;
 	}
-	sbi->flags &= ~HFSPLUS_SB_FORCE;
 
 	/* Load metadata objects (B*Trees) */
-	HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
-	if (!HFSPLUS_SB(sb).ext_tree) {
+	sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
+	if (!sbi->ext_tree) {
 		printk(KERN_ERR "hfs: failed to load extents file\n");
 		goto cleanup;
 	}
-	HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID);
-	if (!HFSPLUS_SB(sb).cat_tree) {
+	sbi->cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID);
+	if (!sbi->cat_tree) {
 		printk(KERN_ERR "hfs: failed to load catalog file\n");
 		goto cleanup;
 	}
@@ -404,7 +404,7 @@
 		err = PTR_ERR(inode);
 		goto cleanup;
 	}
-	HFSPLUS_SB(sb).alloc_file = inode;
+	sbi->alloc_file = inode;
 
 	/* Load the root directory */
 	root = hfsplus_iget(sb, HFSPLUS_ROOT_CNID);
@@ -423,7 +423,7 @@
 
 	str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1;
 	str.name = HFSP_HIDDENDIR_NAME;
-	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+	hfs_find_init(sbi->cat_tree, &fd);
 	hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str);
 	if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
 		hfs_find_exit(&fd);
@@ -434,7 +434,7 @@
 			err = PTR_ERR(inode);
 			goto cleanup;
 		}
-		HFSPLUS_SB(sb).hidden_dir = inode;
+		sbi->hidden_dir = inode;
 	} else
 		hfs_find_exit(&fd);
 
@@ -449,15 +449,19 @@
 	be32_add_cpu(&vhdr->write_count, 1);
 	vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT);
 	vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT);
-	mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
-	sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
+	mark_buffer_dirty(sbi->s_vhbh);
+	sync_dirty_buffer(sbi->s_vhbh);
 
-	if (!HFSPLUS_SB(sb).hidden_dir) {
+	if (!sbi->hidden_dir) {
 		printk(KERN_DEBUG "hfs: create hidden dir...\n");
-		HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR);
-		hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode,
-				   &str, HFSPLUS_SB(sb).hidden_dir);
-		mark_inode_dirty(HFSPLUS_SB(sb).hidden_dir);
+
+		mutex_lock(&sbi->vh_mutex);
+		sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR);
+		hfsplus_create_cat(sbi->hidden_dir->i_ino, sb->s_root->d_inode,
+				   &str, sbi->hidden_dir);
+		mutex_unlock(&sbi->vh_mutex);
+
+		mark_inode_dirty(sbi->hidden_dir);
 	}
 out:
 	unload_nls(sbi->nls);
@@ -486,7 +490,7 @@
 
 static void hfsplus_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(hfsplus_inode_cachep, &HFSPLUS_I(inode));
+	kmem_cache_free(hfsplus_inode_cachep, HFSPLUS_I(inode));
 }
 
 #define HFSPLUS_INODE_SIZE	sizeof(struct hfsplus_inode_info)
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index 628ccf6..b66d67d 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -121,7 +121,7 @@
 int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, char *astr, int *len_p)
 {
 	const hfsplus_unichr *ip;
-	struct nls_table *nls = HFSPLUS_SB(sb).nls;
+	struct nls_table *nls = HFSPLUS_SB(sb)->nls;
 	u8 *op;
 	u16 cc, c0, c1;
 	u16 *ce1, *ce2;
@@ -132,7 +132,7 @@
 	ustrlen = be16_to_cpu(ustr->length);
 	len = *len_p;
 	ce1 = NULL;
-	compose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+	compose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
 
 	while (ustrlen > 0) {
 		c0 = be16_to_cpu(*ip++);
@@ -246,7 +246,7 @@
 static inline int asc2unichar(struct super_block *sb, const char *astr, int len,
 			      wchar_t *uc)
 {
-	int size = HFSPLUS_SB(sb).nls->char2uni(astr, len, uc);
+	int size = HFSPLUS_SB(sb)->nls->char2uni(astr, len, uc);
 	if (size <= 0) {
 		*uc = '?';
 		size = 1;
@@ -293,7 +293,7 @@
 	u16 *dstr, outlen = 0;
 	wchar_t c;
 
-	decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+	decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
 	while (outlen < HFSPLUS_MAX_STRLEN && len > 0) {
 		size = asc2unichar(sb, astr, len, &c);
 
@@ -330,8 +330,8 @@
 	wchar_t c;
 	u16 c2;
 
-	casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD);
-	decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+	casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
+	decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
 	hash = init_name_hash();
 	astr = str->name;
 	len = str->len;
@@ -373,8 +373,8 @@
 	u16 c1, c2;
 	wchar_t c;
 
-	casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD);
-	decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+	casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
+	decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
 	astr1 = s1->name;
 	len1 = s1->len;
 	astr2 = s2->name;
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index bed78ac8..8972c20 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -65,8 +65,8 @@
 	*start = 0;
 	*size = sb->s_bdev->bd_inode->i_size >> 9;
 
-	if (HFSPLUS_SB(sb).session >= 0) {
-		te.cdte_track = HFSPLUS_SB(sb).session;
+	if (HFSPLUS_SB(sb)->session >= 0) {
+		te.cdte_track = HFSPLUS_SB(sb)->session;
 		te.cdte_format = CDROM_LBA;
 		res = ioctl_by_bdev(sb->s_bdev, CDROMREADTOCENTRY, (unsigned long)&te);
 		if (!res && (te.cdte_ctrl & CDROM_DATA_TRACK) == 4) {
@@ -87,6 +87,7 @@
 /* Takes in super block, returns true if good data read */
 int hfsplus_read_wrapper(struct super_block *sb)
 {
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
 	struct buffer_head *bh;
 	struct hfsplus_vh *vhdr;
 	struct hfsplus_wd wd;
@@ -122,7 +123,7 @@
 		if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
 			break;
 		if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) {
-			HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX;
+			set_bit(HFSPLUS_SB_HFSX, &sbi->flags);
 			break;
 		}
 		brelse(bh);
@@ -143,11 +144,11 @@
 	if (blocksize < HFSPLUS_SECTOR_SIZE ||
 	    ((blocksize - 1) & blocksize))
 		return -EINVAL;
-	HFSPLUS_SB(sb).alloc_blksz = blocksize;
-	HFSPLUS_SB(sb).alloc_blksz_shift = 0;
+	sbi->alloc_blksz = blocksize;
+	sbi->alloc_blksz_shift = 0;
 	while ((blocksize >>= 1) != 0)
-		HFSPLUS_SB(sb).alloc_blksz_shift++;
-	blocksize = min(HFSPLUS_SB(sb).alloc_blksz, (u32)PAGE_SIZE);
+		sbi->alloc_blksz_shift++;
+	blocksize = min(sbi->alloc_blksz, (u32)PAGE_SIZE);
 
 	/* align block size to block offset */
 	while (part_start & ((blocksize >> HFSPLUS_SECTOR_SHIFT) - 1))
@@ -158,23 +159,26 @@
 		return -EINVAL;
 	}
 
-	HFSPLUS_SB(sb).blockoffset = part_start >>
-			(sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT);
-	HFSPLUS_SB(sb).sect_count = part_size;
-	HFSPLUS_SB(sb).fs_shift = HFSPLUS_SB(sb).alloc_blksz_shift -
-			sb->s_blocksize_bits;
+	sbi->blockoffset =
+		part_start >> (sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT);
+	sbi->sect_count = part_size;
+	sbi->fs_shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits;
 
 	bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr);
 	if (!bh)
 		return -EIO;
 
 	/* should still be the same... */
-	if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ?
-				cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) :
-				cpu_to_be16(HFSPLUS_VOLHEAD_SIG)))
-		goto error;
-	HFSPLUS_SB(sb).s_vhbh = bh;
-	HFSPLUS_SB(sb).s_vhdr = vhdr;
+	if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) {
+		if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX))
+			goto error;
+	} else {
+		if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
+			goto error;
+	}
+
+	sbi->s_vhbh = bh;
+	sbi->s_vhdr = vhdr;
 
 	return 0;
  error:
diff --git a/fs/hpfs/Kconfig b/fs/hpfs/Kconfig
index 56bd15c..63b6f56 100644
--- a/fs/hpfs/Kconfig
+++ b/fs/hpfs/Kconfig
@@ -1,6 +1,7 @@
 config HPFS_FS
 	tristate "OS/2 HPFS file system support"
 	depends on BLOCK
+	depends on BKL # nontrivial to fix
 	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/super.c b/fs/hpfs/super.c
index 2607010..c969a1a 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -477,11 +477,15 @@
 
 	int o;
 
+	lock_kernel();
+
 	save_mount_options(s, options);
 
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-	if (!sbi)
+	if (!sbi) {
+		unlock_kernel();
 		return -ENOMEM;
+	}
 	s->s_fs_info = sbi;
 
 	sbi->sb_bmp_dir = NULL;
@@ -666,6 +670,7 @@
 			root->i_blocks = 5;
 		hpfs_brelse4(&qbh);
 	}
+	unlock_kernel();
 	return 0;
 
 bail4:	brelse(bh2);
@@ -677,6 +682,7 @@
 	kfree(sbi->sb_cp_table);
 	s->s_fs_info = NULL;
 	kfree(sbi);
+	unlock_kernel();
 	return -EINVAL;
 }
 
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c
index 7b02772..4e2a45e 100644
--- a/fs/hppfs/hppfs.c
+++ b/fs/hppfs/hppfs.c
@@ -598,6 +598,7 @@
 	.readdir	= hppfs_readdir,
 	.open		= hppfs_dir_open,
 	.fsync		= hppfs_fsync,
+	.llseek		= default_llseek,
 };
 
 static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 6e5bd42..113eba3 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -674,6 +674,7 @@
 	.mmap			= hugetlbfs_file_mmap,
 	.fsync			= noop_fsync,
 	.get_unmapped_area	= hugetlb_get_unmapped_area,
+	.llseek		= default_llseek,
 };
 
 static const struct inode_operations hugetlbfs_dir_inode_operations = {
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index e0aca9a..0542b6e 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -10,7 +10,6 @@
  *
  *  isofs directory handling functions
  */
-#include <linux/smp_lock.h>
 #include <linux/gfp.h>
 #include "isofs.h"
 
@@ -255,18 +254,19 @@
 	char *tmpname;
 	struct iso_directory_record *tmpde;
 	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
 
 	tmpname = (char *)__get_free_page(GFP_KERNEL);
 	if (tmpname == NULL)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&sbi->s_mutex);
 	tmpde = (struct iso_directory_record *) (tmpname+1024);
 
 	result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
 
 	free_page((unsigned long) tmpname);
-	unlock_kernel();
+	mutex_unlock(&sbi->s_mutex);
 	return result;
 }
 
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 5a44811..09ff41a 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/nls.h>
 #include <linux/ctype.h>
-#include <linux/smp_lock.h>
 #include <linux/statfs.h>
 #include <linux/cdrom.h>
 #include <linux/parser.h>
@@ -44,11 +43,7 @@
 	struct isofs_sb_info *sbi = ISOFS_SB(sb);
 
 #ifdef CONFIG_JOLIET
-	lock_kernel();
-
 	unload_nls(sbi->s_nls_iocharset);
-
-	unlock_kernel();
 #endif
 
 	kfree(sbi);
@@ -823,6 +818,7 @@
 	sbi->s_utf8 = opt.utf8;
 	sbi->s_nocompress = opt.nocompress;
 	sbi->s_overriderockperm = opt.overriderockperm;
+	mutex_init(&sbi->s_mutex);
 	/*
 	 * It would be incredibly stupid to allow people to mark every file
 	 * on the disk as suid, so we merely allow them to set the default
@@ -977,8 +973,6 @@
 	int section, rv, error;
 	struct iso_inode_info *ei = ISOFS_I(inode);
 
-	lock_kernel();
-
 	error = -EIO;
 	rv = 0;
 	if (iblock < 0 || iblock != iblock_s) {
@@ -1054,7 +1048,6 @@
 
 	error = 0;
 abort:
-	unlock_kernel();
 	return rv != 0 ? rv : error;
 }
 
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index 7d33de8..2882dc0 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -55,6 +55,7 @@
 	gid_t s_gid;
 	uid_t s_uid;
 	struct nls_table *s_nls_iocharset; /* Native language support table */
+	struct mutex s_mutex; /* replaces BKL, please remove if possible */
 };
 
 #define ISOFS_INVALID_MODE ((mode_t) -1)
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index ab438be..0d23abf 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -6,7 +6,6 @@
  *  (C) 1991  Linus Torvalds - minix filesystem
  */
 
-#include <linux/smp_lock.h>
 #include <linux/gfp.h>
 #include "isofs.h"
 
@@ -168,6 +167,7 @@
 	int found;
 	unsigned long uninitialized_var(block);
 	unsigned long uninitialized_var(offset);
+	struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
 	struct inode *inode;
 	struct page *page;
 
@@ -177,7 +177,7 @@
 	if (!page)
 		return ERR_PTR(-ENOMEM);
 
-	lock_kernel();
+	mutex_lock(&sbi->s_mutex);
 	found = isofs_find_entry(dir, dentry,
 				&block, &offset,
 				page_address(page),
@@ -188,10 +188,10 @@
 	if (found) {
 		inode = isofs_iget(dir->i_sb, block, offset);
 		if (IS_ERR(inode)) {
-			unlock_kernel();
+			mutex_unlock(&sbi->s_mutex);
 			return ERR_CAST(inode);
 		}
 	}
-	unlock_kernel();
+	mutex_unlock(&sbi->s_mutex);
 	return d_splice_alias(inode, dentry);
 }
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 96a685c..f9cd04d 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -8,7 +8,6 @@
 
 #include <linux/slab.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 #include "isofs.h"
 #include "rock.h"
@@ -661,6 +660,7 @@
 {
 	struct inode *inode = page->mapping->host;
 	struct iso_inode_info *ei = ISOFS_I(inode);
+	struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
 	char *link = kmap(page);
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	struct buffer_head *bh;
@@ -673,12 +673,12 @@
 	struct rock_state rs;
 	int ret;
 
-	if (!ISOFS_SB(inode->i_sb)->s_rock)
+	if (!sbi->s_rock)
 		goto error;
 
 	init_rock_state(&rs, inode);
 	block = ei->i_iget5_block;
-	lock_kernel();
+	mutex_lock(&sbi->s_mutex);
 	bh = sb_bread(inode->i_sb, block);
 	if (!bh)
 		goto out_noread;
@@ -748,7 +748,7 @@
 		goto fail;
 	brelse(bh);
 	*rpnt = '\0';
-	unlock_kernel();
+	mutex_unlock(&sbi->s_mutex);
 	SetPageUptodate(page);
 	kunmap(page);
 	unlock_page(page);
@@ -765,7 +765,7 @@
 	printk("symlink spans iso9660 blocks\n");
 fail:
 	brelse(bh);
-	unlock_kernel();
+	mutex_unlock(&sbi->s_mutex);
 error:
 	SetPageError(page);
 	kunmap(page);
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 95d8c11..85a6883 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -137,34 +137,10 @@
 	JBUFFER_TRACE(descriptor, "write commit block");
 	set_buffer_dirty(bh);
 
-	if (journal->j_flags & JFS_BARRIER) {
-		ret = __sync_dirty_buffer(bh, WRITE_SYNC | WRITE_BARRIER);
-
-		/*
-		 * Is it possible for another commit to fail at roughly
-		 * the same time as this one?  If so, we don't want to
-		 * trust the barrier flag in the super, but instead want
-		 * to remember if we sent a barrier request
-		 */
-		if (ret == -EOPNOTSUPP) {
-			char b[BDEVNAME_SIZE];
-
-			printk(KERN_WARNING
-				"JBD: barrier-based sync failed on %s - "
-				"disabling barriers\n",
-				bdevname(journal->j_dev, b));
-			spin_lock(&journal->j_state_lock);
-			journal->j_flags &= ~JFS_BARRIER;
-			spin_unlock(&journal->j_state_lock);
-
-			/* And try again, without the barrier */
-			set_buffer_uptodate(bh);
-			set_buffer_dirty(bh);
-			ret = sync_dirty_buffer(bh);
-		}
-	} else {
+	if (journal->j_flags & JFS_BARRIER)
+		ret = __sync_dirty_buffer(bh, WRITE_SYNC | WRITE_FLUSH_FUA);
+	else
 		ret = sync_dirty_buffer(bh);
-	}
 
 	put_bh(bh);		/* One for getblk() */
 	journal_put_journal_head(descriptor);
@@ -318,7 +294,7 @@
 	int first_tag = 0;
 	int tag_flag;
 	int i;
-	int write_op = WRITE;
+	int write_op = WRITE_SYNC;
 
 	/*
 	 * First job: lock down the current transaction and wait for
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index 5247e7f..6571a05 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -532,8 +532,7 @@
 	 */
 	if ((journal->j_fs_dev != journal->j_dev) &&
 	    (journal->j_flags & JBD2_BARRIER))
-		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL,
-			BLKDEV_IFL_WAIT);
+		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
 	if (!(journal->j_flags & JBD2_ABORT))
 		jbd2_journal_update_superblock(journal, 1);
 	return 0;
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 7c068c1..bc6be8b 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -134,25 +134,11 @@
 
 	if (journal->j_flags & JBD2_BARRIER &&
 	    !JBD2_HAS_INCOMPAT_FEATURE(journal,
-				       JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
-		ret = submit_bh(WRITE_SYNC_PLUG | WRITE_BARRIER, bh);
-		if (ret == -EOPNOTSUPP) {
-			printk(KERN_WARNING
-			       "JBD2: Disabling barriers on %s, "
-			       "not supported by device\n", journal->j_devname);
-			write_lock(&journal->j_state_lock);
-			journal->j_flags &= ~JBD2_BARRIER;
-			write_unlock(&journal->j_state_lock);
-
-			/* And try again, without the barrier */
-			lock_buffer(bh);
-			set_buffer_uptodate(bh);
-			clear_buffer_dirty(bh);
-			ret = submit_bh(WRITE_SYNC_PLUG, bh);
-		}
-	} else {
+				       JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT))
+		ret = submit_bh(WRITE_SYNC_PLUG | WRITE_FLUSH_FUA, bh);
+	else
 		ret = submit_bh(WRITE_SYNC_PLUG, bh);
-	}
+
 	*cbh = bh;
 	return ret;
 }
@@ -166,29 +152,8 @@
 {
 	int ret = 0;
 
-retry:
 	clear_buffer_dirty(bh);
 	wait_on_buffer(bh);
-	if (buffer_eopnotsupp(bh) && (journal->j_flags & JBD2_BARRIER)) {
-		printk(KERN_WARNING
-		       "JBD2: %s: disabling barries on %s - not supported "
-		       "by device\n", __func__, journal->j_devname);
-		write_lock(&journal->j_state_lock);
-		journal->j_flags &= ~JBD2_BARRIER;
-		write_unlock(&journal->j_state_lock);
-
-		lock_buffer(bh);
-		clear_buffer_dirty(bh);
-		set_buffer_uptodate(bh);
-		bh->b_end_io = journal_end_buffer_io_sync;
-
-		ret = submit_bh(WRITE_SYNC_PLUG, bh);
-		if (ret) {
-			unlock_buffer(bh);
-			return ret;
-		}
-		goto retry;
-	}
 
 	if (unlikely(!buffer_uptodate(bh)))
 		ret = -EIO;
@@ -360,7 +325,7 @@
 	int tag_bytes = journal_tag_bytes(journal);
 	struct buffer_head *cbh = NULL; /* For transactional checksums */
 	__u32 crc32_sum = ~0;
-	int write_op = WRITE;
+	int write_op = WRITE_SYNC;
 
 	/*
 	 * First job: lock down the current transaction and wait for
@@ -701,29 +666,6 @@
 		}
 	}
 
-	/* 
-	 * If the journal is not located on the file system device,
-	 * then we must flush the file system device before we issue
-	 * the commit record
-	 */
-	if (commit_transaction->t_flushed_data_blocks &&
-	    (journal->j_fs_dev != journal->j_dev) &&
-	    (journal->j_flags & JBD2_BARRIER))
-		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL,
-			BLKDEV_IFL_WAIT);
-
-	/* Done it all: now write the commit record asynchronously. */
-	if (JBD2_HAS_INCOMPAT_FEATURE(journal,
-				      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
-		err = journal_submit_commit_record(journal, commit_transaction,
-						 &cbh, crc32_sum);
-		if (err)
-			__jbd2_journal_abort_hard(journal);
-		if (journal->j_flags & JBD2_BARRIER)
-			blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL,
-				BLKDEV_IFL_WAIT);
-	}
-
 	err = journal_finish_inode_data_buffers(journal, commit_transaction);
 	if (err) {
 		printk(KERN_WARNING
@@ -734,6 +676,25 @@
 		err = 0;
 	}
 
+	/* 
+	 * If the journal is not located on the file system device,
+	 * then we must flush the file system device before we issue
+	 * the commit record
+	 */
+	if (commit_transaction->t_flushed_data_blocks &&
+	    (journal->j_fs_dev != journal->j_dev) &&
+	    (journal->j_flags & JBD2_BARRIER))
+		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
+
+	/* Done it all: now write the commit record asynchronously. */
+	if (JBD2_HAS_INCOMPAT_FEATURE(journal,
+				      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
+		err = journal_submit_commit_record(journal, commit_transaction,
+						 &cbh, crc32_sum);
+		if (err)
+			__jbd2_journal_abort_hard(journal);
+	}
+
 	/* Lo and behold: we have just managed to send a transaction to
            the log.  Before we can commit it, wait for the IO so far to
            complete.  Control buffers being written are on the
@@ -845,6 +806,11 @@
 	}
 	if (!err && !is_journal_aborted(journal))
 		err = journal_wait_on_commit_record(journal, cbh);
+	if (JBD2_HAS_INCOMPAT_FEATURE(journal,
+				      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) &&
+	    journal->j_flags & JBD2_BARRIER) {
+		blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL);
+	}
 
 	if (err)
 		jbd2_journal_abort(journal, err);
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 0e8014e..262419f 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1371,6 +1371,10 @@
 
 	if (!compat && !ro && !incompat)
 		return 1;
+	/* Load journal superblock if it is not loaded yet. */
+	if (journal->j_format_version == 0 &&
+	    journal_get_superblock(journal) != 0)
+		return 0;
 	if (journal->j_format_version == 1)
 		return 0;
 
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 6b2964a..d9beb06 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -21,7 +21,6 @@
 #include <linux/vmalloc.h>
 #include <linux/vfs.h>
 #include <linux/crc32.h>
-#include <linux/smp_lock.h>
 #include "nodelist.h"
 
 static int jffs2_flash_setup(struct jffs2_sb_info *c);
@@ -391,7 +390,6 @@
 	   This also catches the case where it was stopped and this
 	   is just a remount to restart it.
 	   Flush the writebuffer, if neccecary, else we loose it */
-	lock_kernel();
 	if (!(sb->s_flags & MS_RDONLY)) {
 		jffs2_stop_garbage_collect_thread(c);
 		mutex_lock(&c->alloc_sem);
@@ -403,8 +401,6 @@
 		jffs2_start_garbage_collect_thread(c);
 
 	*flags |= MS_NOATIME;
-
-	unlock_kernel();
 	return 0;
 }
 
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 662bba0..d1ae5df 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/fs.h>
@@ -146,6 +145,7 @@
 static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct jffs2_sb_info *c;
+	int ret;
 
 	D1(printk(KERN_DEBUG "jffs2_get_sb_mtd():"
 		  " New superblock for device %d (\"%s\")\n",
@@ -175,7 +175,8 @@
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
 	sb->s_flags |= MS_POSIXACL;
 #endif
-	return jffs2_do_fill_super(sb, data, silent);
+	ret = jffs2_do_fill_super(sb, data, silent);
+	return ret;
 }
 
 static int jffs2_get_sb(struct file_system_type *fs_type,
@@ -192,8 +193,6 @@
 
 	D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));
 
-	lock_kernel();
-
 	if (sb->s_dirt)
 		jffs2_write_super(sb);
 
@@ -215,8 +214,6 @@
 	if (c->mtd->sync)
 		c->mtd->sync(c->mtd);
 
-	unlock_kernel();
-
 	D1(printk(KERN_DEBUG "jffs2_put_super returning\n"));
 }
 
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index ec8c3e4..68eee2b 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -33,7 +33,6 @@
 #include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
@@ -176,8 +175,6 @@
 
 	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
 
-	lock_kernel();
-
 	rc = jfs_umount(sb);
 	if (rc)
 		jfs_err("jfs_umount failed with return code %d", rc);
@@ -188,8 +185,6 @@
 	iput(sbi->direct_inode);
 
 	kfree(sbi);
-
-	unlock_kernel();
 }
 
 enum {
@@ -369,19 +364,16 @@
 	if (!parse_options(data, sb, &newLVSize, &flag)) {
 		return -EINVAL;
 	}
-	lock_kernel();
+
 	if (newLVSize) {
 		if (sb->s_flags & MS_RDONLY) {
 			printk(KERN_ERR
 		  "JFS: resize requires volume to be mounted read-write\n");
-			unlock_kernel();
 			return -EROFS;
 		}
 		rc = jfs_extendfs(sb, newLVSize, 0);
-		if (rc) {
-			unlock_kernel();
+		if (rc)
 			return rc;
-		}
 	}
 
 	if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
@@ -397,36 +389,30 @@
 		/* mark the fs r/w for quota activity */
 		sb->s_flags &= ~MS_RDONLY;
 
-		unlock_kernel();
 		dquot_resume(sb, -1);
 		return ret;
 	}
 	if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY)) {
 		rc = dquot_suspend(sb, -1);
 		if (rc < 0) {
-			unlock_kernel();
 			return rc;
 		}
 		rc = jfs_umount_rw(sb);
 		JFS_SBI(sb)->flag = flag;
-		unlock_kernel();
 		return rc;
 	}
 	if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY))
 		if (!(sb->s_flags & MS_RDONLY)) {
 			rc = jfs_umount_rw(sb);
-			if (rc) {
-				unlock_kernel();
+			if (rc)
 				return rc;
-			}
+
 			JFS_SBI(sb)->flag = flag;
 			ret = jfs_mount_rw(sb, 1);
-			unlock_kernel();
 			return ret;
 		}
 	JFS_SBI(sb)->flag = flag;
 
-	unlock_kernel();
 	return 0;
 }
 
@@ -446,6 +432,7 @@
 	sbi = kzalloc(sizeof (struct jfs_sb_info), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
+
 	sb->s_fs_info = sbi;
 	sbi->sb = sb;
 	sbi->uid = sbi->gid = sbi->umask = -1;
diff --git a/fs/libfs.c b/fs/libfs.c
index 0a9da95..62baa03 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -913,6 +913,35 @@
 }
 EXPORT_SYMBOL(generic_file_fsync);
 
+/**
+ * generic_check_addressable - Check addressability of file system
+ * @blocksize_bits:	log of file system block size
+ * @num_blocks:		number of blocks in file system
+ *
+ * Determine whether a file system with @num_blocks blocks (and a
+ * block size of 2**@blocksize_bits) is addressable by the sector_t
+ * and page cache of the system.  Return 0 if so and -EFBIG otherwise.
+ */
+int generic_check_addressable(unsigned blocksize_bits, u64 num_blocks)
+{
+	u64 last_fs_block = num_blocks - 1;
+	u64 last_fs_page =
+		last_fs_block >> (PAGE_CACHE_SHIFT - blocksize_bits);
+
+	if (unlikely(num_blocks == 0))
+		return 0;
+
+	if ((blocksize_bits < 9) || (blocksize_bits > PAGE_CACHE_SHIFT))
+		return -EINVAL;
+
+	if ((last_fs_block > (sector_t)(~0ULL) >> (blocksize_bits - 9)) ||
+	    (last_fs_page > (pgoff_t)(~0ULL))) {
+		return -EFBIG;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(generic_check_addressable);
+
 /*
  * No-op implementation of ->fsync for in-memory filesystems.
  */
diff --git a/fs/locks.c b/fs/locks.c
index ab24d49..8b2b6ad 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -143,6 +143,22 @@
 static LIST_HEAD(file_lock_list);
 static LIST_HEAD(blocked_list);
 
+/*
+ * 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)
+{
+	lock_kernel();
+}
+EXPORT_SYMBOL_GPL(lock_flocks);
+
+void unlock_flocks(void)
+{
+	unlock_kernel();
+}
+EXPORT_SYMBOL_GPL(unlock_flocks);
+
 static struct kmem_cache *filelock_cache __read_mostly;
 
 /* Allocate an empty lock structure. */
@@ -511,9 +527,9 @@
  */
 static void locks_delete_block(struct file_lock *waiter)
 {
-	lock_kernel();
+	lock_flocks();
 	__locks_delete_block(waiter);
-	unlock_kernel();
+	unlock_flocks();
 }
 
 /* Insert waiter into blocker's block list.
@@ -644,7 +660,7 @@
 {
 	struct file_lock *cfl;
 
-	lock_kernel();
+	lock_flocks();
 	for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
 		if (!IS_POSIX(cfl))
 			continue;
@@ -657,7 +673,7 @@
 			fl->fl_pid = pid_vnr(cfl->fl_nspid);
 	} else
 		fl->fl_type = F_UNLCK;
-	unlock_kernel();
+	unlock_flocks();
 	return;
 }
 EXPORT_SYMBOL(posix_test_lock);
@@ -730,18 +746,16 @@
 	int error = 0;
 	int found = 0;
 
-	lock_kernel();
+	if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) {
+		new_fl = locks_alloc_lock();
+		if (!new_fl)
+			return -ENOMEM;
+	}
+
+	lock_flocks();
 	if (request->fl_flags & FL_ACCESS)
 		goto find_conflict;
 
-	if (request->fl_type != F_UNLCK) {
-		error = -ENOMEM;
-		new_fl = locks_alloc_lock();
-		if (new_fl == NULL)
-			goto out;
-		error = 0;
-	}
-
 	for_each_lock(inode, before) {
 		struct file_lock *fl = *before;
 		if (IS_POSIX(fl))
@@ -767,8 +781,11 @@
 	 * If a higher-priority process was blocked on the old file lock,
 	 * give it the opportunity to lock the file.
 	 */
-	if (found)
+	if (found) {
+		unlock_flocks();
 		cond_resched();
+		lock_flocks();
+	}
 
 find_conflict:
 	for_each_lock(inode, before) {
@@ -794,7 +811,7 @@
 	error = 0;
 
 out:
-	unlock_kernel();
+	unlock_flocks();
 	if (new_fl)
 		locks_free_lock(new_fl);
 	return error;
@@ -823,7 +840,7 @@
 		new_fl2 = locks_alloc_lock();
 	}
 
-	lock_kernel();
+	lock_flocks();
 	if (request->fl_type != F_UNLCK) {
 		for_each_lock(inode, before) {
 			fl = *before;
@@ -991,7 +1008,7 @@
 		locks_wake_up_blocks(left);
 	}
  out:
-	unlock_kernel();
+	unlock_flocks();
 	/*
 	 * Free any unused locks.
 	 */
@@ -1066,14 +1083,14 @@
 	/*
 	 * Search the lock list for this inode for any POSIX locks.
 	 */
-	lock_kernel();
+	lock_flocks();
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
 		if (!IS_POSIX(fl))
 			continue;
 		if (fl->fl_owner != owner)
 			break;
 	}
-	unlock_kernel();
+	unlock_flocks();
 	return fl ? -EAGAIN : 0;
 }
 
@@ -1186,7 +1203,7 @@
 
 	new_fl = lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK);
 
-	lock_kernel();
+	lock_flocks();
 
 	time_out_leases(inode);
 
@@ -1247,8 +1264,10 @@
 			break_time++;
 	}
 	locks_insert_block(flock, new_fl);
+	unlock_flocks();
 	error = wait_event_interruptible_timeout(new_fl->fl_wait,
 						!new_fl->fl_next, break_time);
+	lock_flocks();
 	__locks_delete_block(new_fl);
 	if (error >= 0) {
 		if (error == 0)
@@ -1263,7 +1282,7 @@
 	}
 
 out:
-	unlock_kernel();
+	unlock_flocks();
 	if (!IS_ERR(new_fl))
 		locks_free_lock(new_fl);
 	return error;
@@ -1319,7 +1338,7 @@
 	struct file_lock *fl;
 	int type = F_UNLCK;
 
-	lock_kernel();
+	lock_flocks();
 	time_out_leases(filp->f_path.dentry->d_inode);
 	for (fl = filp->f_path.dentry->d_inode->i_flock; fl && IS_LEASE(fl);
 			fl = fl->fl_next) {
@@ -1328,7 +1347,7 @@
 			break;
 		}
 	}
-	unlock_kernel();
+	unlock_flocks();
 	return type;
 }
 
@@ -1341,7 +1360,7 @@
  *	The (input) flp->fl_lmops->fl_break function is required
  *	by break_lease().
  *
- *	Called with kernel lock held.
+ *	Called with file_lock_lock held.
  */
 int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 {
@@ -1436,7 +1455,15 @@
 }
 EXPORT_SYMBOL(generic_setlease);
 
- /**
+static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
+{
+	if (filp->f_op && filp->f_op->setlease)
+		return filp->f_op->setlease(filp, arg, lease);
+	else
+		return generic_setlease(filp, arg, lease);
+}
+
+/**
  *	vfs_setlease        -       sets a lease on an open file
  *	@filp: file pointer
  *	@arg: type of lease to obtain
@@ -1467,12 +1494,9 @@
 {
 	int error;
 
-	lock_kernel();
-	if (filp->f_op && filp->f_op->setlease)
-		error = filp->f_op->setlease(filp, arg, lease);
-	else
-		error = generic_setlease(filp, arg, lease);
-	unlock_kernel();
+	lock_flocks();
+	error = __vfs_setlease(filp, arg, lease);
+	unlock_flocks();
 
 	return error;
 }
@@ -1499,9 +1523,9 @@
 	if (error)
 		return error;
 
-	lock_kernel();
+	lock_flocks();
 
-	error = vfs_setlease(filp, arg, &flp);
+	error = __vfs_setlease(filp, arg, &flp);
 	if (error || arg == F_UNLCK)
 		goto out_unlock;
 
@@ -1516,7 +1540,7 @@
 
 	error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
 out_unlock:
-	unlock_kernel();
+	unlock_flocks();
 	return error;
 }
 
@@ -2020,7 +2044,7 @@
 			fl.fl_ops->fl_release_private(&fl);
 	}
 
-	lock_kernel();
+	lock_flocks();
 	before = &inode->i_flock;
 
 	while ((fl = *before) != NULL) {
@@ -2038,7 +2062,7 @@
  		}
 		before = &fl->fl_next;
 	}
-	unlock_kernel();
+	unlock_flocks();
 }
 
 /**
@@ -2053,12 +2077,12 @@
 {
 	int status = 0;
 
-	lock_kernel();
+	lock_flocks();
 	if (waiter->fl_next)
 		__locks_delete_block(waiter);
 	else
 		status = -ENOENT;
-	unlock_kernel();
+	unlock_flocks();
 	return status;
 }
 
@@ -2172,7 +2196,7 @@
 
 static void *locks_start(struct seq_file *f, loff_t *pos)
 {
-	lock_kernel();
+	lock_flocks();
 	f->private = (void *)1;
 	return seq_list_start(&file_lock_list, *pos);
 }
@@ -2184,7 +2208,7 @@
 
 static void locks_stop(struct seq_file *f, void *v)
 {
-	unlock_kernel();
+	unlock_flocks();
 }
 
 static const struct seq_operations locks_seq_operations = {
@@ -2231,7 +2255,7 @@
 {
 	struct file_lock *fl;
 	int result = 1;
-	lock_kernel();
+	lock_flocks();
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
 		if (IS_POSIX(fl)) {
 			if (fl->fl_type == F_RDLCK)
@@ -2248,7 +2272,7 @@
 		result = 0;
 		break;
 	}
-	unlock_kernel();
+	unlock_flocks();
 	return result;
 }
 
@@ -2271,7 +2295,7 @@
 {
 	struct file_lock *fl;
 	int result = 1;
-	lock_kernel();
+	lock_flocks();
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
 		if (IS_POSIX(fl)) {
 			if ((fl->fl_end < start) || (fl->fl_start > (start + len)))
@@ -2286,7 +2310,7 @@
 		result = 0;
 		break;
 	}
-	unlock_kernel();
+	unlock_flocks();
 	return result;
 }
 
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index 9777eb5..1eb4e89 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -827,4 +827,5 @@
 	.unlocked_ioctl	= logfs_ioctl,
 	.readdir	= logfs_readdir,
 	.read		= generic_read_dir,
+	.llseek		= default_llseek,
 };
diff --git a/fs/namespace.c b/fs/namespace.c
index a72eaab..7ca5182 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1744,9 +1744,7 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	lock_kernel();
 	mnt = do_kern_mount(type, flags, name, data);
-	unlock_kernel();
 	if (IS_ERR(mnt))
 		return PTR_ERR(mnt);
 
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 9578cbe..aac8832e 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -95,6 +95,34 @@
 };
 
 
+#define ncp_namespace(i)	(NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
+
+static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
+{
+#ifdef CONFIG_NCPFS_SMALLDOS
+	int ns = ncp_namespace(i);
+
+	if ((ns == NW_NS_DOS)
+#ifdef CONFIG_NCPFS_OS2_NS
+		|| ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
+#endif /* CONFIG_NCPFS_OS2_NS */
+	   )
+		return 0;
+#endif /* CONFIG_NCPFS_SMALLDOS */
+	return 1;
+}
+
+#define ncp_preserve_case(i)	(ncp_namespace(i) != NW_NS_DOS)
+
+static inline int ncp_case_sensitive(struct dentry *dentry)
+{
+#ifdef CONFIG_NCPFS_NFS_NS
+	return ncp_namespace(dentry->d_inode) == NW_NS_NFS;
+#else
+	return 0;
+#endif /* CONFIG_NCPFS_NFS_NS */
+}
+
 /*
  * Note: leave the hash unchanged if the directory
  * is case-sensitive.
@@ -102,13 +130,12 @@
 static int 
 ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
 {
-	struct nls_table *t;
-	unsigned long hash;
-	int i;
+	if (!ncp_case_sensitive(dentry)) {
+		struct nls_table *t;
+		unsigned long hash;
+		int i;
 
-	t = NCP_IO_TABLE(dentry);
-
-	if (!ncp_case_sensitive(dentry->d_inode)) {
+		t = NCP_IO_TABLE(dentry);
 		hash = init_name_hash();
 		for (i=0; i<this->len ; i++)
 			hash = partial_name_hash(ncp_tolower(t, this->name[i]),
@@ -124,7 +151,7 @@
 	if (a->len != b->len)
 		return 1;
 
-	if (ncp_case_sensitive(dentry->d_inode))
+	if (ncp_case_sensitive(dentry))
 		return strncmp(a->name, b->name, a->len);
 
 	return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
@@ -266,7 +293,7 @@
 
 
 static int
-__ncp_lookup_validate(struct dentry *dentry)
+ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
 {
 	struct ncp_server *server;
 	struct dentry *parent;
@@ -283,9 +310,6 @@
 
 	server = NCP_SERVER(dir);
 
-	if (!ncp_conn_valid(server))
-		goto finished;
-
 	/*
 	 * Inspired by smbfs:
 	 * The default validation is based on dentry age:
@@ -304,8 +328,11 @@
 	if (ncp_is_server_root(dir)) {
 		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 				 dentry->d_name.len, 1);
-		if (!res)
+		if (!res) {
 			res = ncp_lookup_volume(server, __name, &(finfo.i));
+			if (!res)
+				ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
+		}
 	} else {
 		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 				 dentry->d_name.len, !ncp_preserve_case(dir));
@@ -320,13 +347,17 @@
 	 * what we remember, it's not valid any more.
 	 */
 	if (!res) {
-		if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) {
+		struct inode *inode = dentry->d_inode;
+
+		mutex_lock(&inode->i_mutex);
+		if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
 			ncp_new_dentry(dentry);
 			val=1;
 		} else
 			DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
 
-		ncp_update_inode2(dentry->d_inode, &finfo);
+		ncp_update_inode2(inode, &finfo);
+		mutex_unlock(&inode->i_mutex);
 	}
 
 finished:
@@ -335,16 +366,6 @@
 	return val;
 }
 
-static int
-ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
-{
-	int res;
-	lock_kernel();
-	res = __ncp_lookup_validate(dentry);
-	unlock_kernel();
-	return res;
-}
-
 static struct dentry *
 ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
 {
@@ -411,8 +432,6 @@
 	int result, mtime_valid = 0;
 	time_t mtime = 0;
 
-	lock_kernel();
-
 	ctl.page  = NULL;
 	ctl.cache = NULL;
 
@@ -421,6 +440,7 @@
 		(int) filp->f_pos);
 
 	result = -EIO;
+	/* Do not generate '.' and '..' when server is dead. */
 	if (!ncp_conn_valid(server))
 		goto out;
 
@@ -532,6 +552,12 @@
 	ctl.head.end = ctl.fpos - 1;
 	ctl.head.eof = ctl.valid;
 finished:
+	if (ctl.page) {
+		kunmap(ctl.page);
+		SetPageUptodate(ctl.page);
+		unlock_page(ctl.page);
+		page_cache_release(ctl.page);
+	}
 	if (page) {
 		cache->head = ctl.head;
 		kunmap(page);
@@ -539,23 +565,17 @@
 		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
 ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
-		struct ncp_cache_control *ctrl, struct ncp_entry_info *entry)
+		struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
+		int inval_childs)
 {
 	struct dentry *newdent, *dentry = filp->f_path.dentry;
-	struct inode *newino, *inode = dentry->d_inode;
+	struct inode *dir = dentry->d_inode;
 	struct ncp_cache_control ctl = *ctrl;
 	struct qstr qname;
 	int valid = 0;
@@ -564,9 +584,9 @@
 	__u8 __name[NCP_MAXPATHLEN + 1];
 
 	qname.len = sizeof(__name);
-	if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len,
+	if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
 			entry->i.entryName, entry->i.nameLen,
-			!ncp_preserve_entry_case(inode, entry->i.NSCreator)))
+			!ncp_preserve_entry_case(dir, entry->i.NSCreator)))
 		return 1; /* I'm not sure */
 
 	qname.name = __name;
@@ -584,22 +604,64 @@
 			goto end_advance;
 	} else {
 		hashed = 1;
-		memcpy((char *) newdent->d_name.name, qname.name,
-							newdent->d_name.len);
+
+		/* If case sensitivity changed for this volume, all entries below this one
+		   should be thrown away.  This entry itself is not affected, as its case
+		   sensitivity is controlled by its own parent. */
+		if (inval_childs)
+			shrink_dcache_parent(newdent);
+
+		/*
+		 * It is not as dangerous as it looks.  NetWare's OS2 namespace is
+		 * case preserving yet case insensitive.  So we update dentry's name
+		 * as received from server.  We found dentry via d_lookup with our
+		 * hash, so we know that hash does not change, and so replacing name
+		 * should be reasonably safe.
+		 */
+		if (qname.len == newdent->d_name.len &&
+		    memcmp(newdent->d_name.name, qname.name, newdent->d_name.len)) {
+			struct inode *inode = newdent->d_inode;
+
+			/*
+			 * Inside ncpfs all uses of d_name are either for debugging,
+			 * or on functions which acquire inode mutex (mknod, creat,
+			 * lookup).  So grab i_mutex here, to be sure.  d_path
+			 * uses dcache_lock when generating path, so we should too.
+			 * And finally d_compare is protected by dentry's d_lock, so
+			 * here we go.
+			 */
+			if (inode)
+				mutex_lock(&inode->i_mutex);
+			spin_lock(&dcache_lock);
+			spin_lock(&newdent->d_lock);
+			memcpy((char *) newdent->d_name.name, qname.name,
+								newdent->d_name.len);
+			spin_unlock(&newdent->d_lock);
+			spin_unlock(&dcache_lock);
+			if (inode)
+				mutex_unlock(&inode->i_mutex);
+		}
 	}
 
 	if (!newdent->d_inode) {
+		struct inode *inode;
+
 		entry->opened = 0;
-		entry->ino = iunique(inode->i_sb, 2);
-		newino = ncp_iget(inode->i_sb, entry);
-		if (newino) {
+		entry->ino = iunique(dir->i_sb, 2);
+		inode = ncp_iget(dir->i_sb, entry);
+		if (inode) {
 			newdent->d_op = &ncp_dentry_operations;
-			d_instantiate(newdent, newino);
+			d_instantiate(newdent, inode);
 			if (!hashed)
 				d_rehash(newdent);
 		}
-	} else
-		ncp_update_inode2(newdent->d_inode, entry);
+	} else {
+		struct inode *inode = newdent->d_inode;
+
+		mutex_lock(&inode->i_mutex);
+		ncp_update_inode2(inode, entry);
+		mutex_unlock(&inode->i_mutex);
+	}
 
 	if (newdent->d_inode) {
 		ino = newdent->d_inode->i_ino;
@@ -617,7 +679,7 @@
 		ctl.cache = NULL;
 		ctl.idx  -= NCP_DIRCACHE_SIZE;
 		ctl.ofs  += 1;
-		ctl.page  = grab_cache_page(&inode->i_data, ctl.ofs);
+		ctl.page  = grab_cache_page(&dir->i_data, ctl.ofs);
 		if (ctl.page)
 			ctl.cache = kmap(ctl.page);
 	}
@@ -633,7 +695,7 @@
 		if (!ino)
 			ino = find_inode_number(dentry, &qname);
 		if (!ino)
-			ino = iunique(inode->i_sb, 2);
+			ino = iunique(dir->i_sb, 2);
 		ctl.filled = filldir(dirent, qname.name, qname.len,
 				     filp->f_pos, ino, DT_UNKNOWN);
 		if (!ctl.filled)
@@ -660,6 +722,7 @@
 			(unsigned long) filp->f_pos);
 
 	for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
+		int inval_dentry;
 
 		if (ncp_get_volume_info_with_number(server, i, &info) != 0)
 			return;
@@ -675,8 +738,9 @@
 				info.volume_name);
 			continue;
 		}
+		inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
 		entry.volume = entry.i.volNumber;
-		if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
+		if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry))
 			return;
 	}
 }
@@ -739,7 +803,7 @@
 			rpl += onerpl;
 			rpls -= onerpl;
 			entry.volume = entry.i.volNumber;
-			if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
+			if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0))
 				break;
 		}
 	} while (more);
@@ -775,17 +839,19 @@
 		if (dent) {
 			struct inode* ino = dent->d_inode;
 			if (ino) {
+				ncp_update_known_namespace(server, volNumber, NULL);
 				NCP_FINFO(ino)->volNumber = volNumber;
 				NCP_FINFO(ino)->dirEntNum = dirEntNum;
 				NCP_FINFO(ino)->DosDirNum = DosDirNum;
+				result = 0;
 			} else {
 				DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
 			}
 		} else {
 			DPRINTK("ncpfs: sb->s_root == NULL!\n");
 		}
-	}
-	result = 0;
+	} else
+		result = 0;
 
 out:
 	return result;
@@ -799,7 +865,6 @@
 	int error, res, len;
 	__u8 __name[NCP_MAXPATHLEN + 1];
 
-	lock_kernel();
 	error = -EIO;
 	if (!ncp_conn_valid(server))
 		goto finished;
@@ -813,6 +878,8 @@
 				 dentry->d_name.len, 1);
 		if (!res)
 			res = ncp_lookup_volume(server, __name, &(finfo.i));
+			if (!res)
+				ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
 	} else {
 		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 				 dentry->d_name.len, !ncp_preserve_case(dir));
@@ -846,7 +913,6 @@
 
 finished:
 	PPRINTK("ncp_lookup: result=%d\n", error);
-	unlock_kernel();
 	return ERR_PTR(error);
 }
 
@@ -887,11 +953,6 @@
 	PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name, mode);
 
-	error = -EIO;
-	lock_kernel();
-	if (!ncp_conn_valid(server))
-		goto out;
-
 	ncp_age_dentry(server, dentry);
 	len = sizeof(__name);
 	error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -917,6 +978,8 @@
 		if (result) {
 			if (result == 0x87)
 				error = -ENAMETOOLONG;
+			else if (result < 0)
+				error = result;
 			DPRINTK("ncp_create: %s/%s failed\n",
 				dentry->d_parent->d_name.name, dentry->d_name.name);
 			goto out;
@@ -935,7 +998,6 @@
 
 	error = ncp_instantiate(dir, dentry, &finfo);
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -955,11 +1017,6 @@
 	DPRINTK("ncp_mkdir: making %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
-	error = -EIO;
-	lock_kernel();
-	if (!ncp_conn_valid(server))
-		goto out;
-
 	ncp_age_dentry(server, dentry);
 	len = sizeof(__name);
 	error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -967,12 +1024,11 @@
 	if (error)
 		goto out;
 
-	error = -EACCES;
-	if (ncp_open_create_file_or_subdir(server, dir, __name,
+	error = ncp_open_create_file_or_subdir(server, dir, __name,
 					   OC_MODE_CREATE, aDIR,
 					   cpu_to_le16(0xffff),
-					   &finfo) == 0)
-	{
+					   &finfo);
+	if (error == 0) {
 		if (ncp_is_nfs_extras(server, finfo.volume)) {
 			mode |= S_IFDIR;
 			finfo.i.nfs.mode = mode;
@@ -983,9 +1039,10 @@
 				goto out;
 		}
 		error = ncp_instantiate(dir, dentry, &finfo);
+	} else if (error > 0) {
+		error = -EACCES;
 	}
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -998,11 +1055,6 @@
 	DPRINTK("ncp_rmdir: removing %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
-	error = -EIO;
-	lock_kernel();
-	if (!ncp_conn_valid(server))
-		goto out;
-
 	error = -EBUSY;
 	if (!d_unhashed(dentry))
 		goto out;
@@ -1036,11 +1088,10 @@
 			error = -ENOENT;
 			break;
 		default:
-			error = -EACCES;
+			error = result < 0 ? result : -EACCES;
 			break;
        	}
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -1050,15 +1101,10 @@
 	struct ncp_server *server;
 	int error;
 
-	lock_kernel();
 	server = NCP_SERVER(dir);
 	DPRINTK("ncp_unlink: unlinking %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 	
-	error = -EIO;
-	if (!ncp_conn_valid(server))
-		goto out;
-
 	/*
 	 * Check whether to close the file ...
 	 */
@@ -1097,12 +1143,9 @@
 			error = -ENOENT;
 			break;
 		default:
-			error = -EACCES;
+			error = error < 0 ? error : -EACCES;
 			break;
 	}
-		
-out:
-	unlock_kernel();
 	return error;
 }
 
@@ -1118,11 +1161,6 @@
 		old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
 		new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
 
-	error = -EIO;
-	lock_kernel();
-	if (!ncp_conn_valid(server))
-		goto out;
-
 	ncp_age_dentry(server, old_dentry);
 	ncp_age_dentry(server, new_dentry);
 
@@ -1161,11 +1199,10 @@
 			error = -ENOENT;
 			break;
 		default:
-			error = -EACCES;
+			error = error < 0 ? error : -EACCES;
 			break;
 	}
 out:
-	unlock_kernel();
 	return error;
 }
 
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 3639cc5..6c754f7 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -113,9 +113,6 @@
 	DPRINTK("ncp_file_read: enter %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
-	if (!ncp_conn_valid(NCP_SERVER(inode)))
-		return -EIO;
-
 	pos = *ppos;
 
 	if ((ssize_t) count < 0) {
@@ -192,13 +189,11 @@
 
 	DPRINTK("ncp_file_write: enter %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
-	if (!ncp_conn_valid(NCP_SERVER(inode)))
-		return -EIO;
 	if ((ssize_t) count < 0)
 		return -EINVAL;
 	pos = *ppos;
 	if (file->f_flags & O_APPEND) {
-		pos = inode->i_size;
+		pos = i_size_read(inode);
 	}
 
 	if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
@@ -264,8 +259,11 @@
 
 	*ppos = pos;
 
-	if (pos > inode->i_size) {
-		inode->i_size = pos;
+	if (pos > i_size_read(inode)) {
+		mutex_lock(&inode->i_mutex);
+		if (pos > i_size_read(inode))
+			i_size_write(inode, pos);
+		mutex_unlock(&inode->i_mutex);
 	}
 	DPRINTK("ncp_file_write: exit %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -281,18 +279,9 @@
 	return 0;
 }
 
-static loff_t ncp_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 ncp_file_operations =
 {
-	.llseek 	= ncp_remote_llseek,
+	.llseek		= generic_file_llseek,
 	.read		= ncp_file_read,
 	.write		= ncp_file_write,
 	.unlocked_ioctl	= ncp_ioctl,
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index b4de38c..985fabb 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -139,7 +139,7 @@
 		inode->i_mode = nwi->nfs.mode;
 	}
 
-	inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
+	inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
 
 	inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
 	inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
@@ -158,18 +158,21 @@
 		inode->i_mode = server->m.dir_mode;
 		/* for directories dataStreamSize seems to be some
 		   Object ID ??? */
-		inode->i_size = NCP_BLOCK_SIZE;
+		i_size_write(inode, NCP_BLOCK_SIZE);
 	} else {
+		u32 size;
+
 		inode->i_mode = server->m.file_mode;
-		inode->i_size = le32_to_cpu(nwi->dataStreamSize);
+		size = le32_to_cpu(nwi->dataStreamSize);
+		i_size_write(inode, size);
 #ifdef CONFIG_NCPFS_EXTRAS
 		if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
 		 && (nwi->attributes & aSHARED)) {
 			switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
 				case aHIDDEN:
 					if (server->m.flags & NCP_MOUNT_SYMLINKS) {
-						if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
-						 && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+						if (/* (size >= NCP_MIN_SYMLINK_SIZE)
+						 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
 							inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
 							NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
 							break;
@@ -208,7 +211,7 @@
 }
 
 /*
- * Fill in the inode based on the ncp_entry_info structure.
+ * Fill in the inode based on the ncp_entry_info structure.  Used only for brand new inodes.
  */
 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
 {
@@ -254,6 +257,7 @@
 	if (inode) {
 		atomic_set(&NCP_FINFO(inode)->opened, info->opened);
 
+		inode->i_mapping->backing_dev_info = sb->s_bdi;
 		inode->i_ino = info->ino;
 		ncp_set_attr(inode, info);
 		if (S_ISREG(inode->i_mode)) {
@@ -299,10 +303,12 @@
 
 static void ncp_stop_tasks(struct ncp_server *server) {
 	struct sock* sk = server->ncp_sock->sk;
-		
+
+	lock_sock(sk);
 	sk->sk_error_report = server->error_report;
 	sk->sk_data_ready   = server->data_ready;
 	sk->sk_write_space  = server->write_space;
+	release_sock(sk);
 	del_timer_sync(&server->timeout_tm);
 	flush_scheduled_work();
 }
@@ -565,10 +571,12 @@
 /*	server->conn_status = 0;	*/
 /*	server->root_dentry = NULL;	*/
 /*	server->root_setuped = 0;	*/
+	mutex_init(&server->root_setup_lock);
 #ifdef CONFIG_NCPFS_PACKET_SIGNING
 /*	server->sign_wanted = 0;	*/
 /*	server->sign_active = 0;	*/
 #endif
+	init_rwsem(&server->auth_rwsem);
 	server->auth.auth_type = NCP_AUTH_NONE;
 /*	server->auth.object_name_len = 0;	*/
 /*	server->auth.object_name = NULL;	*/
@@ -593,16 +601,12 @@
 	server->nls_io = load_nls_default();
 #endif /* CONFIG_NCPFS_NLS */
 
-	server->dentry_ttl = 0;	/* no caching */
+	atomic_set(&server->dentry_ttl, 0);	/* no caching */
 
 	INIT_LIST_HEAD(&server->tx.requests);
 	mutex_init(&server->rcv.creq_mutex);
 	server->tx.creq		= NULL;
 	server->rcv.creq	= NULL;
-	server->data_ready	= sock->sk->sk_data_ready;
-	server->write_space	= sock->sk->sk_write_space;
-	server->error_report	= sock->sk->sk_error_report;
-	sock->sk->sk_user_data	= server;
 
 	init_timer(&server->timeout_tm);
 #undef NCP_PACKET_SIZE
@@ -619,6 +623,11 @@
 	if (server->rxbuf == NULL)
 		goto out_txbuf;
 
+	lock_sock(sock->sk);
+	server->data_ready	= sock->sk->sk_data_ready;
+	server->write_space	= sock->sk->sk_write_space;
+	server->error_report	= sock->sk->sk_error_report;
+	sock->sk->sk_user_data	= server;
 	sock->sk->sk_data_ready	  = ncp_tcp_data_ready;
 	sock->sk->sk_error_report = ncp_tcp_error_report;
 	if (sock->type == SOCK_STREAM) {
@@ -634,6 +643,7 @@
 		server->timeout_tm.data = (unsigned long)server;
 		server->timeout_tm.function = ncpdgram_timeout_call;
 	}
+	release_sock(sock->sk);
 
 	ncp_lock_server(server);
 	error = ncp_connect(server);
@@ -658,8 +668,10 @@
 				goto out_disconnect;
 			}
 		}
+		ncp_lock_server(server);
 		if (options & 2)
 			server->sign_wanted = 1;
+		ncp_unlock_server(server);
 	}
 	else 
 #endif	/* CONFIG_NCPFS_PACKET_SIGNING */
@@ -720,6 +732,9 @@
 	unload_nls(server->nls_io);
 	unload_nls(server->nls_vol);
 #endif
+	mutex_destroy(&server->rcv.creq_mutex);
+	mutex_destroy(&server->root_setup_lock);
+	mutex_destroy(&server->mutex);
 out_fput2:
 	if (server->info_filp)
 		fput(server->info_filp);
@@ -743,8 +758,6 @@
 {
 	struct ncp_server *server = NCP_SBP(sb);
 
-	lock_kernel();
-
 	ncp_lock_server(server);
 	ncp_disconnect(server);
 	ncp_unlock_server(server);
@@ -756,6 +769,9 @@
 	unload_nls(server->nls_vol);
 	unload_nls(server->nls_io);
 #endif /* CONFIG_NCPFS_NLS */
+	mutex_destroy(&server->rcv.creq_mutex);
+	mutex_destroy(&server->root_setup_lock);
+	mutex_destroy(&server->mutex);
 
 	if (server->info_filp)
 		fput(server->info_filp);
@@ -771,8 +787,6 @@
 	vfree(server->packet);
 	sb->s_fs_info = NULL;
 	kfree(server);
-
-	unlock_kernel();
 }
 
 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -851,10 +865,8 @@
 
 	result = -EIO;
 
-	lock_kernel();	
-
 	server = NCP_SERVER(inode);
-	if ((!server) || !ncp_conn_valid(server))
+	if (!server)	/* How this could happen? */
 		goto out;
 
 	/* ageing the dentry to force validation */
@@ -981,8 +993,6 @@
 		result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
 				      inode, info_mask, &info);
 		if (result != 0) {
-			result = -EACCES;
-
 			if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
 				/* NetWare seems not to allow this. I
 				   do not know why. So, just tell the
@@ -1005,7 +1015,8 @@
 	mark_inode_dirty(inode);
 
 out:
-	unlock_kernel();
+	if (result > 0)
+		result = -EACCES;
 	return result;
 }
 
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 84a8cfc..c2a1f9a 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -35,16 +35,11 @@
 #define NCP_PACKET_SIZE_INTERNAL 65536
 
 static int
-ncp_get_fs_info(struct ncp_server * server, struct file *file,
+ncp_get_fs_info(struct ncp_server * server, struct inode *inode,
 		struct ncp_fs_info __user *arg)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
 	struct ncp_fs_info info;
 
-	if (file_permission(file, MAY_WRITE) != 0
-	    && current_uid() != server->m.mounted_uid)
-		return -EACCES;
-
 	if (copy_from_user(&info, arg, sizeof(info)))
 		return -EFAULT;
 
@@ -65,16 +60,11 @@
 }
 
 static int
-ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
+ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode,
 		   struct ncp_fs_info_v2 __user * arg)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
 	struct ncp_fs_info_v2 info2;
 
-	if (file_permission(file, MAY_WRITE) != 0
-	    && current_uid() != server->m.mounted_uid)
-		return -EACCES;
-
 	if (copy_from_user(&info2, arg, sizeof(info2)))
 		return -EFAULT;
 
@@ -136,16 +126,11 @@
 #define NCP_IOC_SETPRIVATEDATA_32	_IOR('n', 10, struct compat_ncp_privatedata_ioctl)
 
 static int
-ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
+ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode,
 		   struct compat_ncp_fs_info_v2 __user * arg)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
 	struct compat_ncp_fs_info_v2 info2;
 
-	if (file_permission(file, MAY_WRITE) != 0
-	    && current_uid() != server->m.mounted_uid)
-		return -EACCES;
-
 	if (copy_from_user(&info2, arg, sizeof(info2)))
 		return -EFAULT;
 
@@ -182,11 +167,8 @@
 	struct nls_table *iocharset;
 	struct nls_table *oldset_io;
 	struct nls_table *oldset_cp;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-	if (server->root_setuped)
-		return -EBUSY;
+	int utf8;
+	int err;
 
 	if (copy_from_user(&user, arg, sizeof(user)))
 		return -EFAULT;
@@ -206,28 +188,40 @@
 	user.iocharset[NCP_IOCSNAME_LEN] = 0;
 	if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) {
 		iocharset = load_nls_default();
-		NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+		utf8 = 0;
 	} else if (!strcmp(user.iocharset, "utf8")) {
 		iocharset = load_nls_default();
-		NCP_SET_FLAG(server, NCP_FLAG_UTF8);
+		utf8 = 1;
 	} else {
 		iocharset = load_nls(user.iocharset);
 		if (!iocharset) {
 			unload_nls(codepage);
 			return -EBADRQC;
 		}
-		NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+		utf8 = 0;
 	}
 
-	oldset_cp = server->nls_vol;
-	server->nls_vol = codepage;
-	oldset_io = server->nls_io;
-	server->nls_io = iocharset;
-
+	mutex_lock(&server->root_setup_lock);
+	if (server->root_setuped) {
+		oldset_cp = codepage;
+		oldset_io = iocharset;
+		err = -EBUSY;
+	} else {
+		if (utf8)
+			NCP_SET_FLAG(server, NCP_FLAG_UTF8);
+		else
+			NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+		oldset_cp = server->nls_vol;
+		server->nls_vol = codepage;
+		oldset_io = server->nls_io;
+		server->nls_io = iocharset;
+		err = 0;
+	}
+	mutex_unlock(&server->root_setup_lock);
 	unload_nls(oldset_cp);
 	unload_nls(oldset_io);
 
-	return 0;
+	return err;
 }
 
 static int
@@ -237,6 +231,7 @@
 	int len;
 
 	memset(&user, 0, sizeof(user));
+	mutex_lock(&server->root_setup_lock);
 	if (server->nls_vol && server->nls_vol->charset) {
 		len = strlen(server->nls_vol->charset);
 		if (len > NCP_IOCSNAME_LEN)
@@ -254,6 +249,7 @@
 		strncpy(user.iocharset,	server->nls_io->charset, len);
 		user.iocharset[len] = 0;
 	}
+	mutex_unlock(&server->root_setup_lock);
 
 	if (copy_to_user(arg, &user, sizeof(user)))
 		return -EFAULT;
@@ -261,25 +257,19 @@
 }
 #endif /* CONFIG_NCPFS_NLS */
 
-static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg)
 {
-	struct inode *inode = filp->f_dentry->d_inode;
 	struct ncp_server *server = NCP_SERVER(inode);
 	int result;
 	struct ncp_ioctl_request request;
 	char* bouncebuffer;
 	void __user *argp = (void __user *)arg;
-	uid_t uid = current_uid();
 
 	switch (cmd) {
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_NCPREQUEST_32:
 #endif
 	case NCP_IOC_NCPREQUEST:
-		if (file_permission(filp, MAY_WRITE) != 0
-		    && uid != server->m.mounted_uid)
-			return -EACCES;
-
 #ifdef CONFIG_COMPAT
 		if (cmd == NCP_IOC_NCPREQUEST_32) {
 			struct compat_ncp_ioctl_request request32;
@@ -314,7 +304,7 @@
 		server->current_size = request.size;
 		memcpy(server->packet, bouncebuffer, request.size);
 
-		result = ncp_request2(server, request.function, 
+		result = ncp_request2(server, request.function,
 			bouncebuffer, NCP_PACKET_SIZE_INTERNAL);
 		if (result < 0)
 			result = -EIO;
@@ -331,69 +321,69 @@
 
 	case NCP_IOC_CONN_LOGGED_IN:
 
-		if (!capable(CAP_SYS_ADMIN))
-			return -EACCES;
 		if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE))
 			return -EINVAL;
+		mutex_lock(&server->root_setup_lock);
 		if (server->root_setuped)
-			return -EBUSY;
-		server->root_setuped = 1;
-		return ncp_conn_logged_in(inode->i_sb);
+			result = -EBUSY;
+		else {
+			result = ncp_conn_logged_in(inode->i_sb);
+			if (result == 0)
+				server->root_setuped = 1;
+		}
+		mutex_unlock(&server->root_setup_lock);
+		return result;
 
 	case NCP_IOC_GET_FS_INFO:
-		return ncp_get_fs_info(server, filp, argp);
+		return ncp_get_fs_info(server, inode, argp);
 
 	case NCP_IOC_GET_FS_INFO_V2:
-		return ncp_get_fs_info_v2(server, filp, argp);
+		return ncp_get_fs_info_v2(server, inode, argp);
 
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_GET_FS_INFO_V2_32:
-		return ncp_get_compat_fs_info_v2(server, filp, argp);
+		return ncp_get_compat_fs_info_v2(server, inode, argp);
 #endif
 	/* we have too many combinations of CONFIG_COMPAT,
 	 * CONFIG_64BIT and CONFIG_UID16, so just handle
 	 * any of the possible ioctls */
 	case NCP_IOC_GETMOUNTUID16:
-	case NCP_IOC_GETMOUNTUID32:
-	case NCP_IOC_GETMOUNTUID64:
-		if (file_permission(filp, MAY_READ) != 0
-			&& uid != server->m.mounted_uid)
-			return -EACCES;
-
-		if (cmd == NCP_IOC_GETMOUNTUID16) {
+		{
 			u16 uid;
+
 			SET_UID(uid, server->m.mounted_uid);
 			if (put_user(uid, (u16 __user *)argp))
 				return -EFAULT;
-		} else if (cmd == NCP_IOC_GETMOUNTUID32) {
-			if (put_user(server->m.mounted_uid,
-						(u32 __user *)argp))
-				return -EFAULT;
-		} else {
-			if (put_user(server->m.mounted_uid,
-						(u64 __user *)argp))
-				return -EFAULT;
+			return 0;
 		}
+	case NCP_IOC_GETMOUNTUID32:
+		if (put_user(server->m.mounted_uid,
+			     (u32 __user *)argp))
+			return -EFAULT;
+		return 0;
+	case NCP_IOC_GETMOUNTUID64:
+		if (put_user(server->m.mounted_uid,
+			     (u64 __user *)argp))
+			return -EFAULT;
 		return 0;
 
 	case NCP_IOC_GETROOT:
 		{
 			struct ncp_setroot_ioctl sr;
 
-			if (file_permission(filp, MAY_READ) != 0
-			    && uid != server->m.mounted_uid)
-				return -EACCES;
-
+			result = -EACCES;
+			mutex_lock(&server->root_setup_lock);
 			if (server->m.mounted_vol[0]) {
 				struct dentry* dentry = inode->i_sb->s_root;
 
 				if (dentry) {
 					struct inode* s_inode = dentry->d_inode;
-				
+
 					if (s_inode) {
 						sr.volNumber = NCP_FINFO(s_inode)->volNumber;
 						sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum;
 						sr.namespace = server->name_space[sr.volNumber];
+						result = 0;
 					} else
 						DPRINTK("ncpfs: s_root->d_inode==NULL\n");
 				} else
@@ -402,10 +392,12 @@
 				sr.volNumber = -1;
 				sr.namespace = 0;
 				sr.dirEntNum = 0;
+				result = 0;
 			}
-			if (copy_to_user(argp, &sr, sizeof(sr)))
-				return -EFAULT;
-			return 0;
+			mutex_unlock(&server->root_setup_lock);
+			if (!result && copy_to_user(argp, &sr, sizeof(sr)))
+				result = -EFAULT;
+			return result;
 		}
 
 	case NCP_IOC_SETROOT:
@@ -416,103 +408,114 @@
 			__le32 dosde;
 			struct dentry* dentry;
 
-			if (!capable(CAP_SYS_ADMIN))
-			{
-				return -EACCES;
-			}
-			if (server->root_setuped) return -EBUSY;
 			if (copy_from_user(&sr, argp, sizeof(sr)))
 				return -EFAULT;
-			if (sr.volNumber < 0) {
-				server->m.mounted_vol[0] = 0;
-				vnum = NCP_NUMBER_OF_VOLUMES;
-				de = 0;
-				dosde = 0;
-			} else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
-				return -EINVAL;
-			} else if (ncp_mount_subdir(server, sr.volNumber,
-						sr.namespace, sr.dirEntNum,
-						&vnum, &de, &dosde)) {
-				return -ENOENT;
-			}
-			
-			dentry = inode->i_sb->s_root;
-			server->root_setuped = 1;
-			if (dentry) {
-				struct inode* s_inode = dentry->d_inode;
-				
-				if (s_inode) {
-					NCP_FINFO(s_inode)->volNumber = vnum;
-					NCP_FINFO(s_inode)->dirEntNum = de;
-					NCP_FINFO(s_inode)->DosDirNum = dosde;
+			mutex_lock(&server->root_setup_lock);
+			if (server->root_setuped)
+				result = -EBUSY;
+			else {
+				if (sr.volNumber < 0) {
+					server->m.mounted_vol[0] = 0;
+					vnum = NCP_NUMBER_OF_VOLUMES;
+					de = 0;
+					dosde = 0;
+					result = 0;
+				} else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
+					result = -EINVAL;
+				} else if (ncp_mount_subdir(server, sr.volNumber,
+							sr.namespace, sr.dirEntNum,
+							&vnum, &de, &dosde)) {
+					result = -ENOENT;
 				} else
-					DPRINTK("ncpfs: s_root->d_inode==NULL\n");
-			} else
-				DPRINTK("ncpfs: s_root==NULL\n");
+					result = 0;
 
+				if (result == 0) {
+					dentry = inode->i_sb->s_root;
+					if (dentry) {
+						struct inode* s_inode = dentry->d_inode;
+
+						if (s_inode) {
+							NCP_FINFO(s_inode)->volNumber = vnum;
+							NCP_FINFO(s_inode)->dirEntNum = de;
+							NCP_FINFO(s_inode)->DosDirNum = dosde;
+							server->root_setuped = 1;
+						} else {
+							DPRINTK("ncpfs: s_root->d_inode==NULL\n");
+							result = -EIO;
+						}
+					} else {
+						DPRINTK("ncpfs: s_root==NULL\n");
+						result = -EIO;
+					}
+				}
+				result = 0;
+			}
+			mutex_unlock(&server->root_setup_lock);
+
+			return result;
+		}
+
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+	case NCP_IOC_SIGN_INIT:
+		{
+			struct ncp_sign_init sign;
+
+			if (argp)
+				if (copy_from_user(&sign, argp, sizeof(sign)))
+					return -EFAULT;
+			ncp_lock_server(server);
+			mutex_lock(&server->rcv.creq_mutex);
+			if (argp) {
+				if (server->sign_wanted) {
+					memcpy(server->sign_root,sign.sign_root,8);
+					memcpy(server->sign_last,sign.sign_last,16);
+					server->sign_active = 1;
+				}
+				/* ignore when signatures not wanted */
+			} else {
+				server->sign_active = 0;
+			}
+			mutex_unlock(&server->rcv.creq_mutex);
+			ncp_unlock_server(server);
 			return 0;
 		}
 
-#ifdef CONFIG_NCPFS_PACKET_SIGNING	
-	case NCP_IOC_SIGN_INIT:
-		if (file_permission(filp, MAY_WRITE) != 0
-		    && uid != server->m.mounted_uid)
-			return -EACCES;
-
-		if (argp) {
-			if (server->sign_wanted)
-			{
-				struct ncp_sign_init sign;
-
-				if (copy_from_user(&sign, argp, sizeof(sign)))
-					return -EFAULT;
-				memcpy(server->sign_root,sign.sign_root,8);
-				memcpy(server->sign_last,sign.sign_last,16);
-				server->sign_active = 1;
-			}
-			/* ignore when signatures not wanted */
-		} else {
-			server->sign_active = 0;
-		}
-		return 0;		
-		
         case NCP_IOC_SIGN_WANTED:
-		if (file_permission(filp, MAY_READ) != 0
-		    && uid != server->m.mounted_uid)
-			return -EACCES;
-		
-                if (put_user(server->sign_wanted, (int __user *)argp))
-			return -EFAULT;
-                return 0;
+		{
+			int state;
+
+			ncp_lock_server(server);
+			state = server->sign_wanted;
+			ncp_unlock_server(server);
+			if (put_user(state, (int __user *)argp))
+				return -EFAULT;
+			return 0;
+		}
 
 	case NCP_IOC_SET_SIGN_WANTED:
 		{
 			int newstate;
 
-			if (file_permission(filp, MAY_WRITE) != 0
-			    && uid != server->m.mounted_uid)
-				return -EACCES;
-
 			/* get only low 8 bits... */
 			if (get_user(newstate, (unsigned char __user *)argp))
 				return -EFAULT;
+			result = 0;
+			ncp_lock_server(server);
 			if (server->sign_active) {
 				/* cannot turn signatures OFF when active */
-				if (!newstate) return -EINVAL;
+				if (!newstate)
+					result = -EINVAL;
 			} else {
 				server->sign_wanted = newstate != 0;
 			}
-			return 0;
+			ncp_unlock_server(server);
+			return result;
 		}
 
 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
 
 #ifdef CONFIG_NCPFS_IOCTL_LOCKING
 	case NCP_IOC_LOCKUNLOCK:
-		if (file_permission(filp, MAY_WRITE) != 0
-		    && uid != server->m.mounted_uid)
-			return -EACCES;
-
 		{
 			struct ncp_lock_ioctl	 rqdata;
 
@@ -541,16 +544,13 @@
 			{
 				return result;
 			}
-			result = -EIO;
-			if (!ncp_conn_valid(server))
-				goto outrel;
 			result = -EISDIR;
 			if (!S_ISREG(inode->i_mode))
 				goto outrel;
 			if (rqdata.cmd == NCP_LOCK_CLEAR)
 			{
 				result = ncp_ClearPhysicalRecord(NCP_SERVER(inode),
-							NCP_FINFO(inode)->file_handle, 
+							NCP_FINFO(inode)->file_handle,
 							rqdata.offset,
 							rqdata.length);
 				if (result > 0) result = 0;	/* no such lock */
@@ -573,7 +573,7 @@
 							rqdata.timeout);
 				if (result > 0) result = -EAGAIN;
 			}
-outrel:			
+outrel:
 			ncp_inode_close(inode);
 			return result;
 		}
@@ -581,60 +581,62 @@
 
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_GETOBJECTNAME_32:
-		if (uid != server->m.mounted_uid)
-			return -EACCES;
 		{
 			struct compat_ncp_objectname_ioctl user;
 			size_t outl;
 
 			if (copy_from_user(&user, argp, sizeof(user)))
 				return -EFAULT;
+			down_read(&server->auth_rwsem);
 			user.auth_type = server->auth.auth_type;
 			outl = user.object_name_len;
 			user.object_name_len = server->auth.object_name_len;
 			if (outl > user.object_name_len)
 				outl = user.object_name_len;
+			result = 0;
 			if (outl) {
 				if (copy_to_user(compat_ptr(user.object_name),
 						 server->auth.object_name,
-						 outl)) return -EFAULT;
+						 outl))
+					result = -EFAULT;
 			}
-			if (copy_to_user(argp, &user, sizeof(user)))
-				return -EFAULT;
-			return 0;
+			up_read(&server->auth_rwsem);
+			if (!result && copy_to_user(argp, &user, sizeof(user)))
+				result = -EFAULT;
+			return result;
 		}
 #endif
 
 	case NCP_IOC_GETOBJECTNAME:
-		if (uid != server->m.mounted_uid)
-			return -EACCES;
 		{
 			struct ncp_objectname_ioctl user;
 			size_t outl;
 
 			if (copy_from_user(&user, argp, sizeof(user)))
 				return -EFAULT;
+			down_read(&server->auth_rwsem);
 			user.auth_type = server->auth.auth_type;
 			outl = user.object_name_len;
 			user.object_name_len = server->auth.object_name_len;
 			if (outl > user.object_name_len)
 				outl = user.object_name_len;
+			result = 0;
 			if (outl) {
 				if (copy_to_user(user.object_name,
 						 server->auth.object_name,
-						 outl)) return -EFAULT;
+						 outl))
+					result = -EFAULT;
 			}
-			if (copy_to_user(argp, &user, sizeof(user)))
-				return -EFAULT;
-			return 0;
+			up_read(&server->auth_rwsem);
+			if (!result && copy_to_user(argp, &user, sizeof(user)))
+				result = -EFAULT;
+			return result;
 		}
 
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_SETOBJECTNAME_32:
 #endif
 	case NCP_IOC_SETOBJECTNAME:
-		if (uid != server->m.mounted_uid)
-			return -EACCES;
 		{
 			struct ncp_objectname_ioctl user;
 			void* newname;
@@ -666,9 +668,7 @@
 			} else {
 				newname = NULL;
 			}
-			/* enter critical section */
-			/* maybe that kfree can sleep so do that this way */
-			/* it is at least more SMP friendly (in future...) */
+			down_write(&server->auth_rwsem);
 			oldname = server->auth.object_name;
 			oldnamelen = server->auth.object_name_len;
 			oldprivate = server->priv.data;
@@ -678,7 +678,7 @@
 			server->auth.object_name = newname;
 			server->priv.len = 0;
 			server->priv.data = NULL;
-			/* leave critical section */
+			up_write(&server->auth_rwsem);
 			kfree(oldprivate);
 			kfree(oldname);
 			return 0;
@@ -688,8 +688,6 @@
 	case NCP_IOC_GETPRIVATEDATA_32:
 #endif
 	case NCP_IOC_GETPRIVATEDATA:
-		if (uid != server->m.mounted_uid)
-			return -EACCES;
 		{
 			struct ncp_privatedata_ioctl user;
 			size_t outl;
@@ -706,14 +704,20 @@
 			if (copy_from_user(&user, argp, sizeof(user)))
 				return -EFAULT;
 
+			down_read(&server->auth_rwsem);
 			outl = user.len;
 			user.len = server->priv.len;
 			if (outl > user.len) outl = user.len;
+			result = 0;
 			if (outl) {
 				if (copy_to_user(user.data,
 						 server->priv.data,
-						 outl)) return -EFAULT;
+						 outl))
+					result = -EFAULT;
 			}
+			up_read(&server->auth_rwsem);
+			if (result)
+				return result;
 #ifdef CONFIG_COMPAT
 			if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
 				struct compat_ncp_privatedata_ioctl user32;
@@ -733,8 +737,6 @@
 	case NCP_IOC_SETPRIVATEDATA_32:
 #endif
 	case NCP_IOC_SETPRIVATEDATA:
-		if (uid != server->m.mounted_uid)
-			return -EACCES;
 		{
 			struct ncp_privatedata_ioctl user;
 			void* new;
@@ -762,12 +764,12 @@
 			} else {
 				new = NULL;
 			}
-			/* enter critical section */
+			down_write(&server->auth_rwsem);
 			old = server->priv.data;
 			oldlen = server->priv.len;
 			server->priv.len = user.len;
 			server->priv.data = new;
-			/* leave critical section */
+			up_write(&server->auth_rwsem);
 			kfree(old);
 			return 0;
 		}
@@ -775,17 +777,13 @@
 #ifdef CONFIG_NCPFS_NLS
 	case NCP_IOC_SETCHARSETS:
 		return ncp_set_charsets(server, argp);
-		
+
 	case NCP_IOC_GETCHARSETS:
 		return ncp_get_charsets(server, argp);
 
 #endif /* CONFIG_NCPFS_NLS */
 
 	case NCP_IOC_SETDENTRYTTL:
-		if (file_permission(filp, MAY_WRITE) != 0 &&
-		    uid != server->m.mounted_uid)
-			return -EACCES;
-
 		{
 			u_int32_t user;
 
@@ -795,13 +793,13 @@
 			if (user > 20000)
 				return -EINVAL;
 			user = (user * HZ) / 1000;
-			server->dentry_ttl = user;
+			atomic_set(&server->dentry_ttl, user);
 			return 0;
 		}
-		
+
 	case NCP_IOC_GETDENTRYTTL:
 		{
-			u_int32_t user = (server->dentry_ttl * 1000) / HZ;
+			u_int32_t user = (atomic_read(&server->dentry_ttl) * 1000) / HZ;
 			if (copy_to_user(argp, &user, sizeof(user)))
 				return -EFAULT;
 			return 0;
@@ -811,59 +809,103 @@
 	return -EINVAL;
 }
 
-static int ncp_ioctl_need_write(unsigned int cmd)
-{
-	switch (cmd) {
-	case NCP_IOC_GET_FS_INFO:
-	case NCP_IOC_GET_FS_INFO_V2:
-	case NCP_IOC_NCPREQUEST:
-	case NCP_IOC_SETDENTRYTTL:
-	case NCP_IOC_SIGN_INIT:
-	case NCP_IOC_LOCKUNLOCK:
-	case NCP_IOC_SET_SIGN_WANTED:
-		return 1;
-	case NCP_IOC_GETOBJECTNAME:
-	case NCP_IOC_SETOBJECTNAME:
-	case NCP_IOC_GETPRIVATEDATA:
-	case NCP_IOC_SETPRIVATEDATA:
-	case NCP_IOC_SETCHARSETS:
-	case NCP_IOC_GETCHARSETS:
-	case NCP_IOC_CONN_LOGGED_IN:
-	case NCP_IOC_GETDENTRYTTL:
-	case NCP_IOC_GETMOUNTUID2:
-	case NCP_IOC_SIGN_WANTED:
-	case NCP_IOC_GETROOT:
-	case NCP_IOC_SETROOT:
-		return 0;
-	default:
-		/* unknown IOCTL command, assume write */
-		return 1;
-	}
-}
-
 long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct ncp_server *server = NCP_SERVER(inode);
+	uid_t uid = current_uid();
+	int need_drop_write = 0;
 	long ret;
 
-	lock_kernel();
-	if (ncp_ioctl_need_write(cmd)) {
-		/*
-		 * inside the ioctl(), any failures which
-		 * are because of file_permission() are
-		 * -EACCESS, so it seems consistent to keep
-		 *  that here.
-		 */
-		if (mnt_want_write(filp->f_path.mnt)) {
+	switch (cmd) {
+	case NCP_IOC_SETCHARSETS:
+	case NCP_IOC_CONN_LOGGED_IN:
+	case NCP_IOC_SETROOT:
+		if (!capable(CAP_SYS_ADMIN)) {
 			ret = -EACCES;
 			goto out;
 		}
+		break;
 	}
-	ret = __ncp_ioctl(filp, cmd, arg);
-	if (ncp_ioctl_need_write(cmd))
+	if (server->m.mounted_uid != uid) {
+		switch (cmd) {
+		/*
+		 * Only mount owner can issue these ioctls.  Information
+		 * necessary to authenticate to other NDS servers are
+		 * stored here.
+		 */
+		case NCP_IOC_GETOBJECTNAME:
+		case NCP_IOC_SETOBJECTNAME:
+		case NCP_IOC_GETPRIVATEDATA:
+		case NCP_IOC_SETPRIVATEDATA:
+#ifdef CONFIG_COMPAT
+		case NCP_IOC_GETOBJECTNAME_32:
+		case NCP_IOC_SETOBJECTNAME_32:
+		case NCP_IOC_GETPRIVATEDATA_32:
+		case NCP_IOC_SETPRIVATEDATA_32:
+#endif
+			ret = -EACCES;
+			goto out;
+		/*
+		 * These require write access on the inode if user id
+		 * does not match.  Note that they do not write to the
+		 * file...  But old code did mnt_want_write, so I keep
+		 * it as is.  Of course not for mountpoint owner, as
+		 * that breaks read-only mounts altogether as ncpmount
+		 * needs working NCP_IOC_NCPREQUEST and
+		 * NCP_IOC_GET_FS_INFO.  Some of these codes (setdentryttl,
+		 * signinit, setsignwanted) should be probably restricted
+		 * to owner only, or even more to CAP_SYS_ADMIN).
+		 */
+		case NCP_IOC_GET_FS_INFO:
+		case NCP_IOC_GET_FS_INFO_V2:
+		case NCP_IOC_NCPREQUEST:
+		case NCP_IOC_SETDENTRYTTL:
+		case NCP_IOC_SIGN_INIT:
+		case NCP_IOC_LOCKUNLOCK:
+		case NCP_IOC_SET_SIGN_WANTED:
+#ifdef CONFIG_COMPAT
+		case NCP_IOC_GET_FS_INFO_V2_32:
+		case NCP_IOC_NCPREQUEST_32:
+#endif
+			ret = mnt_want_write_file(filp);
+			if (ret)
+				goto out;
+			need_drop_write = 1;
+			ret = inode_permission(inode, MAY_WRITE);
+			if (ret)
+				goto outDropWrite;
+			break;
+		/*
+		 * Read access required.
+		 */
+		case NCP_IOC_GETMOUNTUID16:
+		case NCP_IOC_GETMOUNTUID32:
+		case NCP_IOC_GETMOUNTUID64:
+		case NCP_IOC_GETROOT:
+		case NCP_IOC_SIGN_WANTED:
+			ret = inode_permission(inode, MAY_READ);
+			if (ret)
+				goto out;
+			break;
+		/*
+		 * Anybody can read these.
+		 */
+		case NCP_IOC_GETCHARSETS:
+		case NCP_IOC_GETDENTRYTTL:
+		default:
+		/* Three codes below are protected by CAP_SYS_ADMIN above. */
+		case NCP_IOC_SETCHARSETS:
+		case NCP_IOC_CONN_LOGGED_IN:
+		case NCP_IOC_SETROOT:
+			break;
+		}
+	}
+	ret = __ncp_ioctl(inode, cmd, arg);
+outDropWrite:
+	if (need_drop_write)
 		mnt_drop_write(filp->f_path.mnt);
-
 out:
-	unlock_kernel();
 	return ret;
 }
 
@@ -872,10 +914,8 @@
 {
 	long ret;
 
-	lock_kernel();
 	arg = (unsigned long) compat_ptr(arg);
 	ret = ncp_ioctl(file, cmd, arg);
-	unlock_kernel();
 	return ret;
 }
 #endif
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index 0ec6237..a95615a 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -107,17 +107,17 @@
 	return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
 }
 
-static inline u8 BVAL(void *data)
+static inline u8 BVAL(const void *data)
 {
-	return *(u8 *)data;
+	return *(const u8 *)data;
 }
 
 static u8 ncp_reply_byte(struct ncp_server *server, int offset)
 {
-	return *(u8 *)ncp_reply_data(server, offset);
+	return *(const u8 *)ncp_reply_data(server, offset);
 }
 
-static inline u16 WVAL_LH(void *data)
+static inline u16 WVAL_LH(const void *data)
 {
 	return get_unaligned_le16(data);
 }
@@ -134,7 +134,7 @@
 	return get_unaligned_be16(ncp_reply_data(server, offset));
 }
 
-static inline u32 DVAL_LH(void *data)
+static inline u32 DVAL_LH(const void *data)
 {
 	return get_unaligned_le32(data);
 }
@@ -349,9 +349,9 @@
 	return result;
 }
 
-void ncp_extract_file_info(void *structure, struct nw_info_struct *target)
+void ncp_extract_file_info(const void *structure, struct nw_info_struct *target)
 {
-	__u8 *name_len;
+	const __u8 *name_len;
 	const int info_struct_size = offsetof(struct nw_info_struct, nameLen);
 
 	memcpy(target, structure, info_struct_size);
@@ -364,7 +364,7 @@
 }
 
 #ifdef CONFIG_NCPFS_NFS_NS
-static inline void ncp_extract_nfs_info(unsigned char *structure,
+static inline void ncp_extract_nfs_info(const unsigned char *structure,
 				 struct nw_nfs_info *target)
 {
 	target->mode = DVAL_LH(structure);
@@ -417,7 +417,7 @@
  * Returns information for a (one-component) name relative to
  * the specified directory.
  */
-int ncp_obtain_info(struct ncp_server *server, struct inode *dir, char *path,
+int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path,
 			struct nw_info_struct *target)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
@@ -452,16 +452,16 @@
 #ifdef CONFIG_NCPFS_NFS_NS
 static int
 ncp_obtain_DOS_dir_base(struct ncp_server *server,
-		__u8 volnum, __le32 dirent,
-		char *path, /* At most 1 component */
+		__u8 ns, __u8 volnum, __le32 dirent,
+		const char *path, /* At most 1 component */
 		__le32 *DOS_dir_base)
 {
 	int result;
 
 	ncp_init_request(server);
 	ncp_add_byte(server, 6); /* subfunction */
-	ncp_add_byte(server, server->name_space[volnum]);
-	ncp_add_byte(server, server->name_space[volnum]);
+	ncp_add_byte(server, ns);
+	ncp_add_byte(server, ns);
 	ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
 	ncp_add_dword(server, RIM_DIRECTORY);
 	ncp_add_handle_path(server, volnum, dirent, 1, path);
@@ -523,10 +523,27 @@
 #endif	/* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */
 }
 
+int
+ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns)
+{
+	int ns = ncp_get_known_namespace(server, volume);
+
+	if (ret_ns)
+		*ret_ns = ns;
+
+	DPRINTK("lookup_vol: namespace[%d] = %d\n",
+		volume, server->name_space[volume]);
+
+	if (server->name_space[volume] == ns)
+		return 0;
+	server->name_space[volume] = ns;
+	return 1;
+}
+
 static int
 ncp_ObtainSpecificDirBase(struct ncp_server *server,
 		__u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base,
-		char *path, /* At most 1 component */
+		const char *path, /* At most 1 component */
 		__le32 *dirEntNum, __le32 *DosDirNum)
 {
 	int result;
@@ -560,14 +577,13 @@
 {
 	int dstNS;
 	int result;
-	
-	dstNS = ncp_get_known_namespace(server, volNumber);
+
+	ncp_update_known_namespace(server, volNumber, &dstNS);
 	if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, 
 				      dirEntNum, NULL, newDirEnt, newDosEnt)) != 0)
 	{
 		return result;
 	}
-	server->name_space[volNumber] = dstNS;
 	*volume = volNumber;
 	server->m.mounted_vol[1] = 0;
 	server->m.mounted_vol[0] = 'X';
@@ -575,11 +591,10 @@
 }
 
 int 
-ncp_get_volume_root(struct ncp_server *server, const char *volname,
-		    __u32* volume, __le32* dirent, __le32* dosdirent)
+ncp_get_volume_root(struct ncp_server *server,
+		    const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent)
 {
 	int result;
-	__u8 volnum;
 
 	DPRINTK("ncp_get_volume_root: looking up vol %s\n", volname);
 
@@ -601,21 +616,14 @@
 		return result;
 	}
 	*dirent = *dosdirent = ncp_reply_dword(server, 4);
-	volnum = ncp_reply_byte(server, 8);
+	*volume = ncp_reply_byte(server, 8);
 	ncp_unlock_server(server);
-	*volume = volnum;
-
-	server->name_space[volnum] = ncp_get_known_namespace(server, volnum);
-
-	DPRINTK("lookup_vol: namespace[%d] = %d\n",
-		volnum, server->name_space[volnum]);
-
 	return 0;
 }
 
 int
-ncp_lookup_volume(struct ncp_server *server, const char *volname,
-		  struct nw_info_struct *target)
+ncp_lookup_volume(struct ncp_server *server,
+		  const char *volname, struct nw_info_struct *target)
 {
 	int result;
 
@@ -625,6 +633,7 @@
 	if (result) {
 		return result;
 	}
+	ncp_update_known_namespace(server, target->volNumber, NULL);
 	target->nameLen = strlen(volname);
 	memcpy(target->entryName, volname, target->nameLen+1);
 	target->attributes = aDIR;
@@ -676,8 +685,8 @@
 {
 	int result = 0;
 
+	ncp_init_request(server);
 	if (server->name_space[volnum] == NW_NS_NFS) {
-		ncp_init_request(server);
 		ncp_add_byte(server, 25);	/* subfunction */
 		ncp_add_byte(server, server->name_space[volnum]);
 		ncp_add_byte(server, NW_NS_NFS);
@@ -690,8 +699,8 @@
 		ncp_add_dword_lh(server, 1);	/* nlinks */
 		ncp_add_dword_lh(server, rdev);
 		result = ncp_request(server, 87);
-		ncp_unlock_server(server);
 	}
+	ncp_unlock_server(server);
 	return result;
 }
 #endif
@@ -700,7 +709,7 @@
 static int
 ncp_DeleteNSEntry(struct ncp_server *server,
 		  __u8 have_dir_base, __u8 volnum, __le32 dirent,
-		  char* name, __u8 ns, __le16 attr)
+		  const char* name, __u8 ns, __le16 attr)
 {
 	int result;
 
@@ -734,23 +743,25 @@
 
 int
 ncp_del_file_or_subdir(struct ncp_server *server,
-		       struct inode *dir, char *name)
+		       struct inode *dir, const char *name)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
 	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
+	int name_space;
 
+	name_space = server->name_space[volnum];
 #ifdef CONFIG_NCPFS_NFS_NS
-	if (server->name_space[volnum]==NW_NS_NFS)
+	if (name_space == NW_NS_NFS)
  	{
  		int result;
  
- 		result=ncp_obtain_DOS_dir_base(server, volnum, dirent, name, &dirent);
+		result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent);
  		if (result) return result;
- 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006));
+		name = NULL;
+		name_space = NW_NS_DOS;
  	}
- 	else
 #endif	/* CONFIG_NCPFS_NFS_NS */
- 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, server->name_space[volnum], cpu_to_le16(0x8006));
+	return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006));
 }
 
 static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
@@ -765,7 +776,7 @@
 /* If both dir and name are NULL, then in target there's already a
    looked-up entry that wants to be opened. */
 int ncp_open_create_file_or_subdir(struct ncp_server *server,
-				   struct inode *dir, char *name,
+				   struct inode *dir, const char *name,
 				   int open_create_mode,
 				   __le32 create_attributes,
 				   __le16 desired_acc_rights,
@@ -890,8 +901,8 @@
 
 static int
 ncp_RenameNSEntry(struct ncp_server *server,
-		  struct inode *old_dir, char *old_name, __le16 old_type,
-		  struct inode *new_dir, char *new_name)
+		  struct inode *old_dir, const char *old_name, __le16 old_type,
+		  struct inode *new_dir, const char *new_name)
 {
 	int result = -EINVAL;
 
@@ -929,8 +940,8 @@
 }
 
 int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
-				struct inode *old_dir, char *old_name,
-				struct inode *new_dir, char *new_name)
+				struct inode *old_dir, const char *old_name,
+				struct inode *new_dir, const char *new_name)
 {
         int result;
         __le16 old_type = cpu_to_le16(0x06);
@@ -958,7 +969,7 @@
 ncp_read_kernel(struct ncp_server *server, const char *file_id,
 	     __u32 offset, __u16 to_read, char *target, int *bytes_read)
 {
-	char *source;
+	const char *source;
 	int result;
 
 	ncp_init_request(server);
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 2441d1a..3c57eca 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -65,10 +65,11 @@
 	atomic_dec(&NCP_FINFO(inode)->opened);
 }
 
-void ncp_extract_file_info(void* src, struct nw_info_struct* target);
-int ncp_obtain_info(struct ncp_server *server, struct inode *, char *,
+void ncp_extract_file_info(const void* src, struct nw_info_struct* target);
+int ncp_obtain_info(struct ncp_server *server, struct inode *, const char *,
 		struct nw_info_struct *target);
 int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target);
+int ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns);
 int ncp_get_volume_root(struct ncp_server *server, const char *volname,
 			__u32 *volume, __le32 *dirent, __le32 *dosdirent);
 int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *);
@@ -80,8 +81,8 @@
 			__u32 mode, __u32 rdev);
 
 int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*);
-int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *);
-int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, char *,
+int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, const char *);
+int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, const char *,
 				int, __le32, __le16, struct ncp_entry_info *);
 
 int ncp_initialize_search(struct ncp_server *, struct inode *,
@@ -93,7 +94,7 @@
 			   char** rbuf, size_t* rsize);
 
 int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
-			      struct inode *, char *, struct inode *, char *);
+			      struct inode *, const char *, struct inode *, const char *);
 
 
 int
@@ -170,13 +171,13 @@
 #endif /* CONFIG_NCPFS_NLS */
 
 #define NCP_GET_AGE(dentry)	(jiffies - (dentry)->d_time)
-#define NCP_MAX_AGE(server)	((server)->dentry_ttl)
+#define NCP_MAX_AGE(server)	atomic_read(&(server)->dentry_ttl)
 #define NCP_TEST_AGE(server,dentry)	(NCP_GET_AGE(dentry) < NCP_MAX_AGE(server))
 
 static inline void
 ncp_age_dentry(struct ncp_server* server, struct dentry* dentry)
 {
-	dentry->d_time = jiffies - server->dentry_ttl;
+	dentry->d_time = jiffies - NCP_MAX_AGE(server);
 }
 
 static inline void
diff --git a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c
index 7c0b5c2..d8b2d7e 100644
--- a/fs/ncpfs/ncpsign_kernel.c
+++ b/fs/ncpfs/ncpsign_kernel.c
@@ -15,21 +15,21 @@
 
 /* i386: 32-bit, little endian, handles mis-alignment */
 #ifdef __i386__
-#define GET_LE32(p) (*(int *)(p))
+#define GET_LE32(p) (*(const int *)(p))
 #define PUT_LE32(p,v) { *(int *)(p)=v; }
 #else
 /* from include/ncplib.h */
-#define BVAL(buf,pos) (((__u8 *)(buf))[pos])
+#define BVAL(buf,pos) (((const __u8 *)(buf))[pos])
 #define PVAL(buf,pos) ((unsigned)BVAL(buf,pos))
-#define BSET(buf,pos,val) (BVAL(buf,pos) = (val))
+#define BSET(buf,pos,val) (((__u8 *)(buf))[pos] = (val))
 
 static inline __u16
-WVAL_LH(__u8 * buf, int pos)
+WVAL_LH(const __u8 * buf, int pos)
 {
 	return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8;
 }
 static inline __u32
-DVAL_LH(__u8 * buf, int pos)
+DVAL_LH(const __u8 * buf, int pos)
 {
 	return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16;
 }
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
index c7ff6c7..668bd26 100644
--- a/fs/ncpfs/sock.c
+++ b/fs/ncpfs/sock.c
@@ -746,7 +746,6 @@
 		return -EIO;
 	}
 	if (!ncp_conn_valid(server)) {
-		printk(KERN_ERR "ncpfs: Connection invalid!\n");
 		return -EIO;
 	}
 	{
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index f7e13db..b950415 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -1,6 +1,7 @@
 config NFS_FS
 	tristate "NFS client support"
 	depends on INET && FILE_LOCKING
+	depends on BKL # fix as soon as lockd is done
 	select LOCKD
 	select SUNRPC
 	select NFS_ACL_SUPPORT if NFS_V3_ACL
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index b9c3c43..232a7ee 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -71,20 +71,20 @@
 	if (inode->i_flock == NULL)
 		goto out;
 
-	/* Protect inode->i_flock using the BKL */
-	lock_kernel();
+	/* Protect inode->i_flock using the file locks lock */
+	lock_flocks();
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
 		if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
 			continue;
 		if (nfs_file_open_context(fl->fl_file) != ctx)
 			continue;
-		unlock_kernel();
+		unlock_flocks();
 		status = nfs4_lock_delegation_recall(state, fl);
 		if (status < 0)
 			goto out;
-		lock_kernel();
+		lock_flocks();
 	}
-	unlock_kernel();
+	unlock_flocks();
 out:
 	return status;
 }
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 3e2f19b..96524c5 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -40,7 +40,7 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/fs.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_idmap.h>
 #include <linux/kthread.h>
@@ -970,13 +970,13 @@
 	/* Guard against delegation returns and new lock/unlock calls */
 	down_write(&nfsi->rwsem);
 	/* Protect inode->i_flock using the BKL */
-	lock_kernel();
+	lock_flocks();
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
 		if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
 			continue;
 		if (nfs_file_open_context(fl->fl_file)->state != state)
 			continue;
-		unlock_kernel();
+		unlock_flocks();
 		status = ops->recover_lock(state, fl);
 		switch (status) {
 			case 0:
@@ -1003,9 +1003,9 @@
 				/* kill_proc(fl->fl_pid, SIGLOST, 1); */
 				status = 0;
 		}
-		lock_kernel();
+		lock_flocks();
 	}
-	unlock_kernel();
+	unlock_flocks();
 out:
 	up_write(&nfsi->rwsem);
 	return status;
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index 4264377..7cf4dda 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -2,6 +2,7 @@
 	tristate "NFS server support"
 	depends on INET
 	depends on FILE_LOCKING
+	depends on BKL # fix as soon as lockd is done
 	select LOCKD
 	select SUNRPC
 	select EXPORTFS
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index cf0d2ff..a7292fc 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -33,7 +33,7 @@
 */
 
 #include <linux/file.h>
-#include <linux/smp_lock.h>
+#include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/namei.h>
 #include <linux/swap.h>
@@ -3895,7 +3895,7 @@
 	struct inode *inode = filp->fi_inode;
 	int status = 0;
 
-	lock_kernel();
+	lock_flocks();
 	for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
 		if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
 			status = 1;
@@ -3903,7 +3903,7 @@
 		}
 	}
 out:
-	unlock_kernel();
+	unlock_flocks();
 	return status;
 }
 
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index b53b1d0..06fa87e 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -137,6 +137,7 @@
 	.write		= nfsctl_transaction_write,
 	.read		= nfsctl_transaction_read,
 	.release	= simple_transaction_release,
+	.llseek		= default_llseek,
 };
 
 static int exports_open(struct inode *inode, struct file *file)
diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h
index cdfb8c6..c16f8d8 100644
--- a/fs/nfsd/nfsfh.h
+++ b/fs/nfsd/nfsfh.h
@@ -196,8 +196,6 @@
 static inline void
 fh_unlock(struct svc_fh *fhp)
 {
-	BUG_ON(!fhp->fh_dentry);
-
 	if (fhp->fh_locked) {
 		fill_post_wcc(fhp);
 		mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
diff --git a/fs/nilfs2/Makefile b/fs/nilfs2/Makefile
index df3e62c..85c9873 100644
--- a/fs/nilfs2/Makefile
+++ b/fs/nilfs2/Makefile
@@ -2,4 +2,4 @@
 nilfs2-y := inode.o file.o dir.o super.o namei.o page.o mdt.o \
 	btnode.o bmap.o btree.o direct.o dat.o recovery.o \
 	the_nilfs.o segbuf.o segment.o cpfile.o sufile.o \
-	ifile.o alloc.o gcinode.o ioctl.o gcdat.o
+	ifile.o alloc.o gcinode.o ioctl.o
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c
index 3dbdc1d..8b782b0 100644
--- a/fs/nilfs2/bmap.c
+++ b/fs/nilfs2/bmap.c
@@ -533,18 +533,20 @@
 	nilfs_btree_init_gc(bmap);
 }
 
-void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap)
+void nilfs_bmap_save(const struct nilfs_bmap *bmap,
+		     struct nilfs_bmap_store *store)
 {
-	memcpy(gcbmap, bmap, sizeof(*bmap));
-	init_rwsem(&gcbmap->b_sem);
-	lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
-	gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode;
+	memcpy(store->data, bmap->b_u.u_data, sizeof(store->data));
+	store->last_allocated_key = bmap->b_last_allocated_key;
+	store->last_allocated_ptr = bmap->b_last_allocated_ptr;
+	store->state = bmap->b_state;
 }
 
-void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap)
+void nilfs_bmap_restore(struct nilfs_bmap *bmap,
+			const struct nilfs_bmap_store *store)
 {
-	memcpy(bmap, gcbmap, sizeof(*bmap));
-	init_rwsem(&bmap->b_sem);
-	lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
-	bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
+	memcpy(bmap->b_u.u_data, store->data, sizeof(store->data));
+	bmap->b_last_allocated_key = store->last_allocated_key;
+	bmap->b_last_allocated_ptr = store->last_allocated_ptr;
+	bmap->b_state = store->state;
 }
diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h
index a20569b..bde1c0aa2 100644
--- a/fs/nilfs2/bmap.h
+++ b/fs/nilfs2/bmap.h
@@ -135,6 +135,12 @@
 /* state */
 #define NILFS_BMAP_DIRTY	0x00000001
 
+struct nilfs_bmap_store {
+	__le64 data[NILFS_BMAP_SIZE / sizeof(__le64)];
+	__u64 last_allocated_key;
+	__u64 last_allocated_ptr;
+	int state;
+};
 
 int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *);
 int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *);
@@ -153,9 +159,9 @@
 int nilfs_bmap_mark(struct nilfs_bmap *, __u64, int);
 
 void nilfs_bmap_init_gc(struct nilfs_bmap *);
-void nilfs_bmap_init_gcdat(struct nilfs_bmap *, struct nilfs_bmap *);
-void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *);
 
+void nilfs_bmap_save(const struct nilfs_bmap *, struct nilfs_bmap_store *);
+void nilfs_bmap_restore(struct nilfs_bmap *, const struct nilfs_bmap_store *);
 
 static inline int nilfs_bmap_lookup(struct nilfs_bmap *bmap, __u64 key,
 				    __u64 *ptr)
diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c
index f78ab10..5115814c 100644
--- a/fs/nilfs2/btnode.c
+++ b/fs/nilfs2/btnode.c
@@ -37,15 +37,7 @@
 
 void nilfs_btnode_cache_init_once(struct address_space *btnc)
 {
-	memset(btnc, 0, sizeof(*btnc));
-	INIT_RADIX_TREE(&btnc->page_tree, GFP_ATOMIC);
-	spin_lock_init(&btnc->tree_lock);
-	INIT_LIST_HEAD(&btnc->private_list);
-	spin_lock_init(&btnc->private_lock);
-
-	spin_lock_init(&btnc->i_mmap_lock);
-	INIT_RAW_PRIO_TREE_ROOT(&btnc->i_mmap);
-	INIT_LIST_HEAD(&btnc->i_mmap_nonlinear);
+	nilfs_mapping_init_once(btnc);
 }
 
 static const struct address_space_operations def_btnode_aops = {
@@ -55,12 +47,7 @@
 void nilfs_btnode_cache_init(struct address_space *btnc,
 			     struct backing_dev_info *bdi)
 {
-	btnc->host = NULL;  /* can safely set to host inode ? */
-	btnc->flags = 0;
-	mapping_set_gfp_mask(btnc, GFP_NOFS);
-	btnc->assoc_mapping = NULL;
-	btnc->backing_dev_info = bdi;
-	btnc->a_ops = &def_btnode_aops;
+	nilfs_mapping_init(btnc, bdi, &def_btnode_aops);
 }
 
 void nilfs_btnode_cache_clear(struct address_space *btnc)
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c
index 1873781..5ff15a8 100644
--- a/fs/nilfs2/cpfile.c
+++ b/fs/nilfs2/cpfile.c
@@ -863,26 +863,19 @@
  */
 int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode)
 {
-	struct the_nilfs *nilfs;
 	int ret;
 
-	nilfs = NILFS_MDT(cpfile)->mi_nilfs;
-
 	switch (mode) {
 	case NILFS_CHECKPOINT:
-		/*
-		 * Check for protecting existing snapshot mounts:
-		 * ns_mount_mutex is used to make this operation atomic and
-		 * exclusive with a new mount job.  Though it doesn't cover
-		 * umount, it's enough for the purpose.
-		 */
-		if (nilfs_checkpoint_is_mounted(nilfs, cno, 1)) {
-			/* Current implementation does not have to protect
-			   plain read-only mounts since they are exclusive
-			   with a read/write mount and are protected from the
-			   cleaner. */
+		if (nilfs_checkpoint_is_mounted(cpfile->i_sb, cno))
+			/*
+			 * Current implementation does not have to protect
+			 * plain read-only mounts since they are exclusive
+			 * with a read/write mount and are protected from the
+			 * cleaner.
+			 */
 			ret = -EBUSY;
-		} else
+		else
 			ret = nilfs_cpfile_clear_snapshot(cpfile, cno);
 		return ret;
 	case NILFS_SNAPSHOT:
@@ -933,27 +926,40 @@
 }
 
 /**
- * nilfs_cpfile_read - read cpfile inode
- * @cpfile: cpfile inode
- * @raw_inode: on-disk cpfile inode
- */
-int nilfs_cpfile_read(struct inode *cpfile, struct nilfs_inode *raw_inode)
-{
-	return nilfs_read_inode_common(cpfile, raw_inode);
-}
-
-/**
- * nilfs_cpfile_new - create cpfile
- * @nilfs: nilfs object
+ * nilfs_cpfile_read - read or get cpfile inode
+ * @sb: super block instance
  * @cpsize: size of a checkpoint entry
+ * @raw_inode: on-disk cpfile inode
+ * @inodep: buffer to store the inode
  */
-struct inode *nilfs_cpfile_new(struct the_nilfs *nilfs, size_t cpsize)
+int nilfs_cpfile_read(struct super_block *sb, size_t cpsize,
+		      struct nilfs_inode *raw_inode, struct inode **inodep)
 {
 	struct inode *cpfile;
+	int err;
 
-	cpfile = nilfs_mdt_new(nilfs, NULL, NILFS_CPFILE_INO, 0);
-	if (cpfile)
-		nilfs_mdt_set_entry_size(cpfile, cpsize,
-					 sizeof(struct nilfs_cpfile_header));
-	return cpfile;
+	cpfile = nilfs_iget_locked(sb, NULL, NILFS_CPFILE_INO);
+	if (unlikely(!cpfile))
+		return -ENOMEM;
+	if (!(cpfile->i_state & I_NEW))
+		goto out;
+
+	err = nilfs_mdt_init(cpfile, NILFS_MDT_GFP, 0);
+	if (err)
+		goto failed;
+
+	nilfs_mdt_set_entry_size(cpfile, cpsize,
+				 sizeof(struct nilfs_cpfile_header));
+
+	err = nilfs_read_inode_common(cpfile, raw_inode);
+	if (err)
+		goto failed;
+
+	unlock_new_inode(cpfile);
+ out:
+	*inodep = cpfile;
+	return 0;
+ failed:
+	iget_failed(cpfile);
+	return err;
 }
diff --git a/fs/nilfs2/cpfile.h b/fs/nilfs2/cpfile.h
index bc0809e..a242b9a 100644
--- a/fs/nilfs2/cpfile.h
+++ b/fs/nilfs2/cpfile.h
@@ -40,7 +40,7 @@
 ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int, void *, unsigned,
 				size_t);
 
-int nilfs_cpfile_read(struct inode *cpfile, struct nilfs_inode *raw_inode);
-struct inode *nilfs_cpfile_new(struct the_nilfs *nilfs, size_t cpsize);
+int nilfs_cpfile_read(struct super_block *sb, size_t cpsize,
+		      struct nilfs_inode *raw_inode, struct inode **inodep);
 
 #endif	/* _NILFS_CPFILE_H */
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
index 0131467..49c844d 100644
--- a/fs/nilfs2/dat.c
+++ b/fs/nilfs2/dat.c
@@ -36,6 +36,7 @@
 struct nilfs_dat_info {
 	struct nilfs_mdt_info mi;
 	struct nilfs_palloc_cache palloc_cache;
+	struct nilfs_shadow_map shadow;
 };
 
 static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat)
@@ -102,7 +103,8 @@
 	nilfs_palloc_abort_alloc_entry(dat, req);
 }
 
-void nilfs_dat_commit_free(struct inode *dat, struct nilfs_palloc_req *req)
+static void nilfs_dat_commit_free(struct inode *dat,
+				  struct nilfs_palloc_req *req)
 {
 	struct nilfs_dat_entry *entry;
 	void *kaddr;
@@ -327,6 +329,23 @@
 	ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh);
 	if (ret < 0)
 		return ret;
+
+	/*
+	 * The given disk block number (blocknr) is not yet written to
+	 * the device at this point.
+	 *
+	 * To prevent nilfs_dat_translate() from returning the
+	 * uncommited block number, this makes a copy of the entry
+	 * buffer and redirects nilfs_dat_translate() to the copy.
+	 */
+	if (!buffer_nilfs_redirected(entry_bh)) {
+		ret = nilfs_mdt_freeze_buffer(dat, entry_bh);
+		if (ret) {
+			brelse(entry_bh);
+			return ret;
+		}
+	}
+
 	kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
 	entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
 	if (unlikely(entry->de_blocknr == cpu_to_le64(0))) {
@@ -371,7 +390,7 @@
  */
 int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
 {
-	struct buffer_head *entry_bh;
+	struct buffer_head *entry_bh, *bh;
 	struct nilfs_dat_entry *entry;
 	sector_t blocknr;
 	void *kaddr;
@@ -381,6 +400,15 @@
 	if (ret < 0)
 		return ret;
 
+	if (!nilfs_doing_gc() && buffer_nilfs_redirected(entry_bh)) {
+		bh = nilfs_mdt_get_frozen_buffer(dat, entry_bh);
+		if (bh) {
+			WARN_ON(!buffer_uptodate(bh));
+			brelse(entry_bh);
+			entry_bh = bh;
+		}
+	}
+
 	kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
 	entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
 	blocknr = le64_to_cpu(entry->de_blocknr);
@@ -436,38 +464,48 @@
 }
 
 /**
- * nilfs_dat_read - read dat inode
- * @dat: dat inode
- * @raw_inode: on-disk dat inode
- */
-int nilfs_dat_read(struct inode *dat, struct nilfs_inode *raw_inode)
-{
-	return nilfs_read_inode_common(dat, raw_inode);
-}
-
-/**
- * nilfs_dat_new - create dat file
- * @nilfs: nilfs object
+ * nilfs_dat_read - read or get dat inode
+ * @sb: super block instance
  * @entry_size: size of a dat entry
+ * @raw_inode: on-disk dat inode
+ * @inodep: buffer to store the inode
  */
-struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size)
+int nilfs_dat_read(struct super_block *sb, size_t entry_size,
+		   struct nilfs_inode *raw_inode, struct inode **inodep)
 {
 	static struct lock_class_key dat_lock_key;
 	struct inode *dat;
 	struct nilfs_dat_info *di;
 	int err;
 
-	dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO, sizeof(*di));
-	if (dat) {
-		err = nilfs_palloc_init_blockgroup(dat, entry_size);
-		if (unlikely(err)) {
-			nilfs_mdt_destroy(dat);
-			return NULL;
-		}
+	dat = nilfs_iget_locked(sb, NULL, NILFS_DAT_INO);
+	if (unlikely(!dat))
+		return -ENOMEM;
+	if (!(dat->i_state & I_NEW))
+		goto out;
 
-		di = NILFS_DAT_I(dat);
-		lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
-		nilfs_palloc_setup_cache(dat, &di->palloc_cache);
-	}
-	return dat;
+	err = nilfs_mdt_init(dat, NILFS_MDT_GFP, sizeof(*di));
+	if (err)
+		goto failed;
+
+	err = nilfs_palloc_init_blockgroup(dat, entry_size);
+	if (err)
+		goto failed;
+
+	di = NILFS_DAT_I(dat);
+	lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
+	nilfs_palloc_setup_cache(dat, &di->palloc_cache);
+	nilfs_mdt_setup_shadow_map(dat, &di->shadow);
+
+	err = nilfs_read_inode_common(dat, raw_inode);
+	if (err)
+		goto failed;
+
+	unlock_new_inode(dat);
+ out:
+	*inodep = dat;
+	return 0;
+ failed:
+	iget_failed(dat);
+	return err;
 }
diff --git a/fs/nilfs2/dat.h b/fs/nilfs2/dat.h
index d31c3aa..cbd8e97 100644
--- a/fs/nilfs2/dat.h
+++ b/fs/nilfs2/dat.h
@@ -53,7 +53,7 @@
 int nilfs_dat_move(struct inode *, __u64, sector_t);
 ssize_t nilfs_dat_get_vinfo(struct inode *, void *, unsigned, size_t);
 
-int nilfs_dat_read(struct inode *dat, struct nilfs_inode *raw_inode);
-struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size);
+int nilfs_dat_read(struct super_block *sb, size_t entry_size,
+		   struct nilfs_inode *raw_inode, struct inode **inodep);
 
 #endif	/* _NILFS_DAT_H */
diff --git a/fs/nilfs2/export.h b/fs/nilfs2/export.h
new file mode 100644
index 0000000..a71cc41
--- /dev/null
+++ b/fs/nilfs2/export.h
@@ -0,0 +1,17 @@
+#ifndef NILFS_EXPORT_H
+#define NILFS_EXPORT_H
+
+#include <linux/exportfs.h>
+
+extern const struct export_operations nilfs_export_ops;
+
+struct nilfs_fid {
+	u64 cno;
+	u64 ino;
+	u32 gen;
+
+	u32 parent_gen;
+	u64 parent_ino;
+} __attribute__ ((packed));
+
+#endif
diff --git a/fs/nilfs2/gcdat.c b/fs/nilfs2/gcdat.c
deleted file mode 100644
index 84a45d1..0000000
--- a/fs/nilfs2/gcdat.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * gcdat.c - NILFS shadow DAT inode for GC
- *
- * 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 Seiji Kihara <kihara@osrg.net>, Amagai Yoshiji <amagai@osrg.net>,
- *            and Ryusuke Konishi <ryusuke@osrg.net>.
- *
- */
-
-#include <linux/buffer_head.h>
-#include "nilfs.h"
-#include "page.h"
-#include "mdt.h"
-
-int nilfs_init_gcdat_inode(struct the_nilfs *nilfs)
-{
-	struct inode *dat = nilfs->ns_dat, *gcdat = nilfs->ns_gc_dat;
-	struct nilfs_inode_info *dii = NILFS_I(dat), *gii = NILFS_I(gcdat);
-	int err;
-
-	gcdat->i_state = 0;
-	gcdat->i_blocks = dat->i_blocks;
-	gii->i_flags = dii->i_flags;
-	gii->i_state = dii->i_state | (1 << NILFS_I_GCDAT);
-	gii->i_cno = 0;
-	nilfs_bmap_init_gcdat(gii->i_bmap, dii->i_bmap);
-	err = nilfs_copy_dirty_pages(gcdat->i_mapping, dat->i_mapping);
-	if (unlikely(err))
-		return err;
-
-	return nilfs_copy_dirty_pages(&gii->i_btnode_cache,
-				      &dii->i_btnode_cache);
-}
-
-void nilfs_commit_gcdat_inode(struct the_nilfs *nilfs)
-{
-	struct inode *dat = nilfs->ns_dat, *gcdat = nilfs->ns_gc_dat;
-	struct nilfs_inode_info *dii = NILFS_I(dat), *gii = NILFS_I(gcdat);
-	struct address_space *mapping = dat->i_mapping;
-	struct address_space *gmapping = gcdat->i_mapping;
-
-	down_write(&NILFS_MDT(dat)->mi_sem);
-	dat->i_blocks = gcdat->i_blocks;
-	dii->i_flags = gii->i_flags;
-	dii->i_state = gii->i_state & ~(1 << NILFS_I_GCDAT);
-
-	nilfs_bmap_commit_gcdat(gii->i_bmap, dii->i_bmap);
-
-	nilfs_palloc_clear_cache(dat);
-	nilfs_palloc_clear_cache(gcdat);
-	nilfs_clear_dirty_pages(mapping);
-	nilfs_copy_back_pages(mapping, gmapping);
-	/* note: mdt dirty flags should be cleared by segctor. */
-
-	nilfs_clear_dirty_pages(&dii->i_btnode_cache);
-	nilfs_copy_back_pages(&dii->i_btnode_cache, &gii->i_btnode_cache);
-
-	up_write(&NILFS_MDT(dat)->mi_sem);
-}
-
-void nilfs_clear_gcdat_inode(struct the_nilfs *nilfs)
-{
-	struct inode *gcdat = nilfs->ns_gc_dat;
-	struct nilfs_inode_info *gii = NILFS_I(gcdat);
-
-	gcdat->i_state = I_FREEING | I_CLEAR;
-	gii->i_flags = 0;
-
-	nilfs_palloc_clear_cache(gcdat);
-	truncate_inode_pages(gcdat->i_mapping, 0);
-	truncate_inode_pages(&gii->i_btnode_cache, 0);
-}
diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c
index bed3a78..33ad25d 100644
--- a/fs/nilfs2/gcinode.c
+++ b/fs/nilfs2/gcinode.c
@@ -28,13 +28,6 @@
  * gcinodes), and this file provides lookup function of the dummy
  * inodes and their buffer read function.
  *
- * Since NILFS2 keeps up multiple checkpoints/snapshots across GC, it
- * has to treat blocks that belong to a same file but have different
- * checkpoint numbers.  To avoid interference among generations, dummy
- * inodes are managed separately from actual inodes, and their lookup
- * function (nilfs_gc_iget) is designed to be specified with a
- * checkpoint number argument as well as an inode number.
- *
  * Buffers and pages held by the dummy inodes will be released each
  * time after they are copied to a new log.  Dirty blocks made on the
  * current generation and the blocks to be moved by GC never overlap
@@ -175,125 +168,46 @@
 		}
 		nilfs_btnode_mark_dirty(bh);
 	} else {
-		nilfs_mdt_mark_buffer_dirty(bh);
+		nilfs_mark_buffer_dirty(bh);
 	}
 	return 0;
 }
 
-/*
- * nilfs_init_gccache() - allocate and initialize gc_inode hash table
- * @nilfs - the_nilfs
- *
- * Return Value: On success, 0.
- * On error, a negative error code is returned.
- */
-int nilfs_init_gccache(struct the_nilfs *nilfs)
+int nilfs_init_gcinode(struct inode *inode)
 {
-	int loop;
+	struct nilfs_inode_info *ii = NILFS_I(inode);
+	struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
 
-	BUG_ON(nilfs->ns_gc_inodes_h);
-
-	INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
-
-	nilfs->ns_gc_inodes_h =
-		kmalloc(sizeof(struct hlist_head) * NILFS_GCINODE_HASH_SIZE,
-			GFP_NOFS);
-	if (nilfs->ns_gc_inodes_h == NULL)
-		return -ENOMEM;
-
-	for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++)
-		INIT_HLIST_HEAD(&nilfs->ns_gc_inodes_h[loop]);
-	return 0;
-}
-
-/*
- * nilfs_destroy_gccache() - free gc_inode hash table
- * @nilfs - the nilfs
- */
-void nilfs_destroy_gccache(struct the_nilfs *nilfs)
-{
-	if (nilfs->ns_gc_inodes_h) {
-		nilfs_remove_all_gcinode(nilfs);
-		kfree(nilfs->ns_gc_inodes_h);
-		nilfs->ns_gc_inodes_h = NULL;
-	}
-}
-
-static struct inode *alloc_gcinode(struct the_nilfs *nilfs, ino_t ino,
-				   __u64 cno)
-{
-	struct inode *inode;
-	struct nilfs_inode_info *ii;
-
-	inode = nilfs_mdt_new_common(nilfs, NULL, ino, GFP_NOFS, 0);
-	if (!inode)
-		return NULL;
-
-	inode->i_op = NULL;
-	inode->i_fop = NULL;
+	inode->i_mode = S_IFREG;
+	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
 	inode->i_mapping->a_ops = &def_gcinode_aops;
+	inode->i_mapping->backing_dev_info = inode->i_sb->s_bdi;
 
-	ii = NILFS_I(inode);
-	ii->i_cno = cno;
 	ii->i_flags = 0;
-	ii->i_state = 1 << NILFS_I_GCINODE;
-	ii->i_bh = NULL;
 	nilfs_bmap_init_gc(ii->i_bmap);
 
-	return inode;
+	/*
+	 * Add the inode to GC inode list. Garbage Collection
+	 * is serialized and no two processes manipulate the
+	 * list simultaneously.
+	 */
+	igrab(inode);
+	list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes);
+
+	return 0;
 }
 
-static unsigned long ihash(ino_t ino, __u64 cno)
-{
-	return hash_long((unsigned long)((ino << 2) + cno),
-			 NILFS_GCINODE_HASH_BITS);
-}
-
-/*
- * nilfs_gc_iget() - find or create gc inode with specified (ino,cno)
+/**
+ * nilfs_remove_all_gcinodes() - remove all unprocessed gc inodes
  */
-struct inode *nilfs_gc_iget(struct the_nilfs *nilfs, ino_t ino, __u64 cno)
+void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs)
 {
-	struct hlist_head *head = nilfs->ns_gc_inodes_h + ihash(ino, cno);
-	struct hlist_node *node;
-	struct inode *inode;
+	struct list_head *head = &nilfs->ns_gc_inodes;
+	struct nilfs_inode_info *ii;
 
-	hlist_for_each_entry(inode, node, head, i_hash) {
-		if (inode->i_ino == ino && NILFS_I(inode)->i_cno == cno)
-			return inode;
-	}
-
-	inode = alloc_gcinode(nilfs, ino, cno);
-	if (likely(inode)) {
-		hlist_add_head(&inode->i_hash, head);
-		list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes);
-	}
-	return inode;
-}
-
-/*
- * nilfs_clear_gcinode() - clear and free a gc inode
- */
-void nilfs_clear_gcinode(struct inode *inode)
-{
-	nilfs_mdt_destroy(inode);
-}
-
-/*
- * nilfs_remove_all_gcinode() - remove all inodes from the_nilfs
- */
-void nilfs_remove_all_gcinode(struct the_nilfs *nilfs)
-{
-	struct hlist_head *head = nilfs->ns_gc_inodes_h;
-	struct hlist_node *node, *n;
-	struct inode *inode;
-	int loop;
-
-	for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++, head++) {
-		hlist_for_each_entry_safe(inode, node, n, head, i_hash) {
-			hlist_del_init(&inode->i_hash);
-			list_del_init(&NILFS_I(inode)->i_dirty);
-			nilfs_clear_gcinode(inode); /* might sleep */
-		}
+	while (!list_empty(head)) {
+		ii = list_first_entry(head, struct nilfs_inode_info, i_dirty);
+		list_del_init(&ii->i_dirty);
+		iput(&ii->vfs_inode);
 	}
 }
diff --git a/fs/nilfs2/ifile.c b/fs/nilfs2/ifile.c
index 922d9dd..9f8a2da 100644
--- a/fs/nilfs2/ifile.c
+++ b/fs/nilfs2/ifile.c
@@ -161,25 +161,46 @@
 }
 
 /**
- * nilfs_ifile_new - create inode file
- * @sbi: nilfs_sb_info struct
+ * nilfs_ifile_read - read or get ifile inode
+ * @sb: super block instance
+ * @root: root object
  * @inode_size: size of an inode
+ * @raw_inode: on-disk ifile inode
+ * @inodep: buffer to store the inode
  */
-struct inode *nilfs_ifile_new(struct nilfs_sb_info *sbi, size_t inode_size)
+int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root,
+		     size_t inode_size, struct nilfs_inode *raw_inode,
+		     struct inode **inodep)
 {
 	struct inode *ifile;
 	int err;
 
-	ifile = nilfs_mdt_new(sbi->s_nilfs, sbi->s_super, NILFS_IFILE_INO,
-			      sizeof(struct nilfs_ifile_info));
-	if (ifile) {
-		err = nilfs_palloc_init_blockgroup(ifile, inode_size);
-		if (unlikely(err)) {
-			nilfs_mdt_destroy(ifile);
-			return NULL;
-		}
-		nilfs_palloc_setup_cache(ifile,
-					 &NILFS_IFILE_I(ifile)->palloc_cache);
-	}
-	return ifile;
+	ifile = nilfs_iget_locked(sb, root, NILFS_IFILE_INO);
+	if (unlikely(!ifile))
+		return -ENOMEM;
+	if (!(ifile->i_state & I_NEW))
+		goto out;
+
+	err = nilfs_mdt_init(ifile, NILFS_MDT_GFP,
+			     sizeof(struct nilfs_ifile_info));
+	if (err)
+		goto failed;
+
+	err = nilfs_palloc_init_blockgroup(ifile, inode_size);
+	if (err)
+		goto failed;
+
+	nilfs_palloc_setup_cache(ifile, &NILFS_IFILE_I(ifile)->palloc_cache);
+
+	err = nilfs_read_inode_common(ifile, raw_inode);
+	if (err)
+		goto failed;
+
+	unlock_new_inode(ifile);
+ out:
+	*inodep = ifile;
+	return 0;
+ failed:
+	iget_failed(ifile);
+	return err;
 }
diff --git a/fs/nilfs2/ifile.h b/fs/nilfs2/ifile.h
index cbca32e..59b6f2b 100644
--- a/fs/nilfs2/ifile.h
+++ b/fs/nilfs2/ifile.h
@@ -49,6 +49,8 @@
 int nilfs_ifile_delete_inode(struct inode *, ino_t);
 int nilfs_ifile_get_inode_block(struct inode *, ino_t, struct buffer_head **);
 
-struct inode *nilfs_ifile_new(struct nilfs_sb_info *sbi, size_t inode_size);
+int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root,
+		     size_t inode_size, struct nilfs_inode *raw_inode,
+		     struct inode **inodep);
 
 #endif	/* _NILFS_IFILE_H */
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index eccb2f2..71d4bc8 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -34,6 +34,12 @@
 #include "cpfile.h"
 #include "ifile.h"
 
+struct nilfs_iget_args {
+	u64 ino;
+	__u64 cno;
+	struct nilfs_root *root;
+	int for_gc;
+};
 
 /**
  * nilfs_get_block() - get a file block on the filesystem (callback function)
@@ -279,6 +285,7 @@
 	struct nilfs_sb_info *sbi = NILFS_SB(sb);
 	struct inode *inode;
 	struct nilfs_inode_info *ii;
+	struct nilfs_root *root;
 	int err = -ENOMEM;
 	ino_t ino;
 
@@ -289,15 +296,17 @@
 	mapping_set_gfp_mask(inode->i_mapping,
 			     mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
 
+	root = NILFS_I(dir)->i_root;
 	ii = NILFS_I(inode);
 	ii->i_state = 1 << NILFS_I_NEW;
+	ii->i_root = root;
 
-	err = nilfs_ifile_create_inode(sbi->s_ifile, &ino, &ii->i_bh);
+	err = nilfs_ifile_create_inode(root->ifile, &ino, &ii->i_bh);
 	if (unlikely(err))
 		goto failed_ifile_create_inode;
 	/* reference count of i_bh inherits from nilfs_mdt_read_block() */
 
-	atomic_inc(&sbi->s_inodes_count);
+	atomic_inc(&root->inodes_count);
 	inode_init_owner(inode, dir, mode);
 	inode->i_ino = ino;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
@@ -320,7 +329,6 @@
 	/* ii->i_file_acl = 0; */
 	/* ii->i_dir_acl = 0; */
 	ii->i_dir_start_lookup = 0;
-	ii->i_cno = 0;
 	nilfs_set_inode_flags(inode);
 	spin_lock(&sbi->s_next_gen_lock);
 	inode->i_generation = sbi->s_next_generation++;
@@ -350,16 +358,6 @@
 	return ERR_PTR(err);
 }
 
-void nilfs_free_inode(struct inode *inode)
-{
-	struct super_block *sb = inode->i_sb;
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-
-	/* XXX: check error code? Is there any thing I can do? */
-	(void) nilfs_ifile_delete_inode(sbi->s_ifile, inode->i_ino);
-	atomic_dec(&sbi->s_inodes_count);
-}
-
 void nilfs_set_inode_flags(struct inode *inode)
 {
 	unsigned int flags = NILFS_I(inode)->i_flags;
@@ -410,7 +408,6 @@
 		0 : le32_to_cpu(raw_inode->i_dir_acl);
 #endif
 	ii->i_dir_start_lookup = 0;
-	ii->i_cno = 0;
 	inode->i_generation = le32_to_cpu(raw_inode->i_generation);
 
 	if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
@@ -424,7 +421,8 @@
 	return 0;
 }
 
-static int __nilfs_read_inode(struct super_block *sb, unsigned long ino,
+static int __nilfs_read_inode(struct super_block *sb,
+			      struct nilfs_root *root, unsigned long ino,
 			      struct inode *inode)
 {
 	struct nilfs_sb_info *sbi = NILFS_SB(sb);
@@ -434,11 +432,11 @@
 	int err;
 
 	down_read(&NILFS_MDT(dat)->mi_sem);	/* XXX */
-	err = nilfs_ifile_get_inode_block(sbi->s_ifile, ino, &bh);
+	err = nilfs_ifile_get_inode_block(root->ifile, ino, &bh);
 	if (unlikely(err))
 		goto bad_inode;
 
-	raw_inode = nilfs_ifile_map_inode(sbi->s_ifile, ino, bh);
+	raw_inode = nilfs_ifile_map_inode(root->ifile, ino, bh);
 
 	err = nilfs_read_inode_common(inode, raw_inode);
 	if (err)
@@ -461,14 +459,14 @@
 			inode, inode->i_mode,
 			huge_decode_dev(le64_to_cpu(raw_inode->i_device_code)));
 	}
-	nilfs_ifile_unmap_inode(sbi->s_ifile, ino, bh);
+	nilfs_ifile_unmap_inode(root->ifile, ino, bh);
 	brelse(bh);
 	up_read(&NILFS_MDT(dat)->mi_sem);	/* XXX */
 	nilfs_set_inode_flags(inode);
 	return 0;
 
  failed_unmap:
-	nilfs_ifile_unmap_inode(sbi->s_ifile, ino, bh);
+	nilfs_ifile_unmap_inode(root->ifile, ino, bh);
 	brelse(bh);
 
  bad_inode:
@@ -476,18 +474,95 @@
 	return err;
 }
 
-struct inode *nilfs_iget(struct super_block *sb, unsigned long ino)
+static int nilfs_iget_test(struct inode *inode, void *opaque)
+{
+	struct nilfs_iget_args *args = opaque;
+	struct nilfs_inode_info *ii;
+
+	if (args->ino != inode->i_ino || args->root != NILFS_I(inode)->i_root)
+		return 0;
+
+	ii = NILFS_I(inode);
+	if (!test_bit(NILFS_I_GCINODE, &ii->i_state))
+		return !args->for_gc;
+
+	return args->for_gc && args->cno == ii->i_cno;
+}
+
+static int nilfs_iget_set(struct inode *inode, void *opaque)
+{
+	struct nilfs_iget_args *args = opaque;
+
+	inode->i_ino = args->ino;
+	if (args->for_gc) {
+		NILFS_I(inode)->i_state = 1 << NILFS_I_GCINODE;
+		NILFS_I(inode)->i_cno = args->cno;
+		NILFS_I(inode)->i_root = NULL;
+	} else {
+		if (args->root && args->ino == NILFS_ROOT_INO)
+			nilfs_get_root(args->root);
+		NILFS_I(inode)->i_root = args->root;
+	}
+	return 0;
+}
+
+struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root,
+			    unsigned long ino)
+{
+	struct nilfs_iget_args args = {
+		.ino = ino, .root = root, .cno = 0, .for_gc = 0
+	};
+
+	return ilookup5(sb, ino, nilfs_iget_test, &args);
+}
+
+struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root,
+				unsigned long ino)
+{
+	struct nilfs_iget_args args = {
+		.ino = ino, .root = root, .cno = 0, .for_gc = 0
+	};
+
+	return iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args);
+}
+
+struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
+			 unsigned long ino)
 {
 	struct inode *inode;
 	int err;
 
-	inode = iget_locked(sb, ino);
+	inode = nilfs_iget_locked(sb, root, ino);
 	if (unlikely(!inode))
 		return ERR_PTR(-ENOMEM);
 	if (!(inode->i_state & I_NEW))
 		return inode;
 
-	err = __nilfs_read_inode(sb, ino, inode);
+	err = __nilfs_read_inode(sb, root, ino, inode);
+	if (unlikely(err)) {
+		iget_failed(inode);
+		return ERR_PTR(err);
+	}
+	unlock_new_inode(inode);
+	return inode;
+}
+
+struct inode *nilfs_iget_for_gc(struct super_block *sb, unsigned long ino,
+				__u64 cno)
+{
+	struct nilfs_iget_args args = {
+		.ino = ino, .root = NULL, .cno = cno, .for_gc = 1
+	};
+	struct inode *inode;
+	int err;
+
+	inode = iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args);
+	if (unlikely(!inode))
+		return ERR_PTR(-ENOMEM);
+	if (!(inode->i_state & I_NEW))
+		return inode;
+
+	err = nilfs_init_gcinode(inode);
 	if (unlikely(err)) {
 		iget_failed(inode);
 		return ERR_PTR(err);
@@ -528,21 +603,20 @@
 {
 	ino_t ino = inode->i_ino;
 	struct nilfs_inode_info *ii = NILFS_I(inode);
-	struct super_block *sb = inode->i_sb;
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
+	struct inode *ifile = ii->i_root->ifile;
 	struct nilfs_inode *raw_inode;
 
-	raw_inode = nilfs_ifile_map_inode(sbi->s_ifile, ino, ibh);
+	raw_inode = nilfs_ifile_map_inode(ifile, ino, ibh);
 
 	if (test_and_clear_bit(NILFS_I_NEW, &ii->i_state))
-		memset(raw_inode, 0, NILFS_MDT(sbi->s_ifile)->mi_entry_size);
+		memset(raw_inode, 0, NILFS_MDT(ifile)->mi_entry_size);
 	set_bit(NILFS_I_INODE_DIRTY, &ii->i_state);
 
 	nilfs_write_inode_common(inode, raw_inode, 0);
 		/* XXX: call with has_bmap = 0 is a workaround to avoid
 		   deadlock of bmap. This delays update of i_bmap to just
 		   before writing */
-	nilfs_ifile_unmap_inode(sbi->s_ifile, ino, ibh);
+	nilfs_ifile_unmap_inode(ifile, ino, ibh);
 }
 
 #define NILFS_MAX_TRUNCATE_BLOCKS	16384  /* 64MB for 4KB block */
@@ -617,6 +691,7 @@
 static void nilfs_clear_inode(struct inode *inode)
 {
 	struct nilfs_inode_info *ii = NILFS_I(inode);
+	struct nilfs_mdt_info *mdi = NILFS_MDT(inode);
 
 	/*
 	 * Free resources allocated in nilfs_read_inode(), here.
@@ -625,10 +700,16 @@
 	brelse(ii->i_bh);
 	ii->i_bh = NULL;
 
+	if (mdi && mdi->mi_palloc_cache)
+		nilfs_palloc_destroy_cache(inode);
+
 	if (test_bit(NILFS_I_BMAP, &ii->i_state))
 		nilfs_bmap_clear(ii->i_bmap);
 
 	nilfs_btnode_cache_clear(&ii->i_btnode_cache);
+
+	if (ii->i_root && inode->i_ino == NILFS_ROOT_INO)
+		nilfs_put_root(ii->i_root);
 }
 
 void nilfs_evict_inode(struct inode *inode)
@@ -637,7 +718,7 @@
 	struct super_block *sb = inode->i_sb;
 	struct nilfs_inode_info *ii = NILFS_I(inode);
 
-	if (inode->i_nlink || unlikely(is_bad_inode(inode))) {
+	if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) {
 		if (inode->i_data.nrpages)
 			truncate_inode_pages(&inode->i_data, 0);
 		end_writeback(inode);
@@ -649,12 +730,16 @@
 	if (inode->i_data.nrpages)
 		truncate_inode_pages(&inode->i_data, 0);
 
+	/* TODO: some of the following operations may fail.  */
 	nilfs_truncate_bmap(ii, 0);
 	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);
+
 	nilfs_clear_inode(inode);
-	nilfs_free_inode(inode);
-	/* nilfs_free_inode() marks inode buffer dirty */
+
 	if (IS_SYNC(inode))
 		nilfs_set_transaction_flag(NILFS_TI_SYNC);
 	nilfs_transaction_commit(sb);
@@ -700,6 +785,17 @@
 	return err;
 }
 
+int nilfs_permission(struct inode *inode, int mask)
+{
+	struct nilfs_root *root = NILFS_I(inode)->i_root;
+
+	if ((mask & MAY_WRITE) && root &&
+	    root->cno != NILFS_CPTREE_CURRENT_CNO)
+		return -EROFS; /* snapshot is not writable */
+
+	return generic_permission(inode, mask, NULL);
+}
+
 int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode,
 			   struct buffer_head **pbh)
 {
@@ -709,8 +805,8 @@
 	spin_lock(&sbi->s_inode_lock);
 	if (ii->i_bh == NULL) {
 		spin_unlock(&sbi->s_inode_lock);
-		err = nilfs_ifile_get_inode_block(sbi->s_ifile, inode->i_ino,
-						  pbh);
+		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);
@@ -790,7 +886,7 @@
 	}
 	nilfs_update_inode(inode, ibh);
 	nilfs_mdt_mark_buffer_dirty(ibh);
-	nilfs_mdt_mark_dirty(sbi->s_ifile);
+	nilfs_mdt_mark_dirty(NILFS_I(inode)->i_root->ifile);
 	brelse(ibh);
 	return 0;
 }
@@ -808,6 +904,7 @@
 void nilfs_dirty_inode(struct inode *inode)
 {
 	struct nilfs_transaction_info ti;
+	struct nilfs_mdt_info *mdi = NILFS_MDT(inode);
 
 	if (is_bad_inode(inode)) {
 		nilfs_warning(inode->i_sb, __func__,
@@ -815,6 +912,10 @@
 		dump_stack();
 		return;
 	}
+	if (mdi) {
+		nilfs_mdt_mark_dirty(inode);
+		return;
+	}
 	nilfs_transaction_begin(inode->i_sb, &ti, 0);
 	nilfs_mark_inode_dirty(inode);
 	nilfs_transaction_commit(inode->i_sb); /* never fails */
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index f90a33d..3e90f86 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -22,7 +22,6 @@
 
 #include <linux/fs.h>
 #include <linux/wait.h>
-#include <linux/smp_lock.h>	/* lock_kernel(), unlock_kernel() */
 #include <linux/slab.h>
 #include <linux/capability.h>	/* capable() */
 #include <linux/uaccess.h>	/* copy_from_user(), copy_to_user() */
@@ -118,7 +117,7 @@
 	if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
 		goto out;
 
-	mutex_lock(&nilfs->ns_mount_mutex);
+	down_read(&inode->i_sb->s_umount);
 
 	nilfs_transaction_begin(inode->i_sb, &ti, 0);
 	ret = nilfs_cpfile_change_cpmode(
@@ -128,7 +127,7 @@
 	else
 		nilfs_transaction_commit(inode->i_sb); /* never fails */
 
-	mutex_unlock(&nilfs->ns_mount_mutex);
+	up_read(&inode->i_sb->s_umount);
 out:
 	mnt_drop_write(filp->f_path.mnt);
 	return ret;
@@ -334,7 +333,7 @@
 	return 0;
 }
 
-static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs,
+static int nilfs_ioctl_move_blocks(struct super_block *sb,
 				   struct nilfs_argv *argv, void *buf)
 {
 	size_t nmembs = argv->v_nmembs;
@@ -349,7 +348,7 @@
 	for (i = 0, vdesc = buf; i < nmembs; ) {
 		ino = vdesc->vd_ino;
 		cno = vdesc->vd_cno;
-		inode = nilfs_gc_iget(nilfs, ino, cno);
+		inode = nilfs_iget_for_gc(sb, ino, cno);
 		if (unlikely(inode == NULL)) {
 			ret = -ENOMEM;
 			goto failed;
@@ -357,11 +356,15 @@
 		do {
 			ret = nilfs_ioctl_move_inode_block(inode, vdesc,
 							   &buffers);
-			if (unlikely(ret < 0))
+			if (unlikely(ret < 0)) {
+				iput(inode);
 				goto failed;
+			}
 			vdesc++;
 		} while (++i < nmembs &&
 			 vdesc->vd_ino == ino && vdesc->vd_cno == cno);
+
+		iput(inode); /* The inode still remains in GC inode list */
 	}
 
 	list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
@@ -567,7 +570,7 @@
 	}
 
 	/*
-	 * nilfs_ioctl_move_blocks() will call nilfs_gc_iget(),
+	 * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(),
 	 * which will operates an inode list without blocking.
 	 * To protect the list from concurrent operations,
 	 * nilfs_ioctl_move_blocks should be atomic operation.
@@ -577,15 +580,16 @@
 		goto out_free;
 	}
 
-	ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]);
+	vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
+
+	ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]);
 	if (ret < 0)
 		printk(KERN_ERR "NILFS: GC failed during preparation: "
 			"cannot read source blocks: err=%d\n", ret);
 	else
 		ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
 
-	if (ret < 0)
-		nilfs_remove_all_gcinode(nilfs);
+	nilfs_remove_all_gcinodes(nilfs);
 	clear_nilfs_gc_running(nilfs);
 
 out_free:
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index d01aff4..39a5b84 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -36,7 +36,6 @@
 
 #define NILFS_MDT_MAX_RA_BLOCKS		(16 - 1)
 
-#define INIT_UNUSED_INODE_FIELDS
 
 static int
 nilfs_mdt_insert_new_block(struct inode *inode, unsigned long block,
@@ -78,25 +77,11 @@
 						     struct buffer_head *,
 						     void *))
 {
-	struct the_nilfs *nilfs = NILFS_MDT(inode)->mi_nilfs;
 	struct super_block *sb = inode->i_sb;
 	struct nilfs_transaction_info ti;
 	struct buffer_head *bh;
 	int err;
 
-	if (!sb) {
-		/*
-		 * Make sure this function is not called from any
-		 * read-only context.
-		 */
-		if (!nilfs->ns_writer) {
-			WARN_ON(1);
-			err = -EROFS;
-			goto out;
-		}
-		sb = nilfs->ns_writer->s_super;
-	}
-
 	nilfs_transaction_begin(sb, &ti, 0);
 
 	err = -ENOMEM;
@@ -112,7 +97,7 @@
 	if (buffer_uptodate(bh))
 		goto failed_bh;
 
-	bh->b_bdev = nilfs->ns_bdev;
+	bh->b_bdev = sb->s_bdev;
 	err = nilfs_mdt_insert_new_block(inode, block, bh, init_block);
 	if (likely(!err)) {
 		get_bh(bh);
@@ -129,7 +114,7 @@
 		err = nilfs_transaction_commit(sb);
 	else
 		nilfs_transaction_abort(sb);
- out:
+
 	return err;
 }
 
@@ -167,9 +152,7 @@
 		unlock_buffer(bh);
 		goto failed_bh;
 	}
-	bh->b_bdev = NILFS_MDT(inode)->mi_nilfs->ns_bdev;
-	bh->b_blocknr = (sector_t)blknum;
-	set_buffer_mapped(bh);
+	map_bh(bh, inode->i_sb, (sector_t)blknum);
 
 	bh->b_end_io = end_buffer_read_sync;
 	get_bh(bh);
@@ -398,35 +381,24 @@
 static int
 nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc)
 {
-	struct inode *inode = container_of(page->mapping,
-					   struct inode, i_data);
-	struct super_block *sb = inode->i_sb;
-	struct the_nilfs *nilfs = NILFS_MDT(inode)->mi_nilfs;
-	struct nilfs_sb_info *writer = NULL;
+	struct inode *inode;
+	struct super_block *sb;
 	int err = 0;
 
 	redirty_page_for_writepage(wbc, page);
 	unlock_page(page);
 
-	if (page->mapping->assoc_mapping)
-		return 0; /* Do not request flush for shadow page cache */
-	if (!sb) {
-		down_read(&nilfs->ns_writer_sem);
-		writer = nilfs->ns_writer;
-		if (!writer) {
-			up_read(&nilfs->ns_writer_sem);
-			return -EROFS;
-		}
-		sb = writer->s_super;
-	}
+	inode = page->mapping->host;
+	if (!inode)
+		return 0;
+
+	sb = inode->i_sb;
 
 	if (wbc->sync_mode == WB_SYNC_ALL)
 		err = nilfs_construct_segment(sb);
 	else if (wbc->for_reclaim)
 		nilfs_flush_segment(sb, inode->i_ino);
 
-	if (writer)
-		up_read(&nilfs->ns_writer_sem);
 	return err;
 }
 
@@ -439,105 +411,27 @@
 static const struct inode_operations def_mdt_iops;
 static const struct file_operations def_mdt_fops;
 
-/*
- * NILFS2 uses pseudo inodes for meta data files such as DAT, cpfile, sufile,
- * ifile, or gcinodes.  This allows the B-tree code and segment constructor
- * to treat them like regular files, and this helps to simplify the
- * implementation.
- *   On the other hand, some of the pseudo inodes have an irregular point:
- * They don't have valid inode->i_sb pointer because their lifetimes are
- * longer than those of the super block structs; they may continue for
- * several consecutive mounts/umounts.  This would need discussions.
- */
-/**
- * nilfs_mdt_new_common - allocate a pseudo inode for metadata file
- * @nilfs: nilfs object
- * @sb: super block instance the metadata file belongs to
- * @ino: inode number
- * @gfp_mask: gfp mask for data pages
- * @objsz: size of the private object attached to inode->i_private
- */
-struct inode *
-nilfs_mdt_new_common(struct the_nilfs *nilfs, struct super_block *sb,
-		     ino_t ino, gfp_t gfp_mask, size_t objsz)
+
+int nilfs_mdt_init(struct inode *inode, gfp_t gfp_mask, size_t objsz)
 {
-	struct inode *inode = nilfs_alloc_inode_common(nilfs);
+	struct nilfs_mdt_info *mi;
 
-	if (!inode)
-		return NULL;
-	else {
-		struct address_space * const mapping = &inode->i_data;
-		struct nilfs_mdt_info *mi;
+	mi = kzalloc(max(sizeof(*mi), objsz), GFP_NOFS);
+	if (!mi)
+		return -ENOMEM;
 
-		mi = kzalloc(max(sizeof(*mi), objsz), GFP_NOFS);
-		if (!mi) {
-			nilfs_destroy_inode(inode);
-			return NULL;
-		}
-		mi->mi_nilfs = nilfs;
-		init_rwsem(&mi->mi_sem);
+	init_rwsem(&mi->mi_sem);
+	inode->i_private = mi;
 
-		inode->i_sb = sb; /* sb may be NULL for some meta data files */
-		inode->i_blkbits = nilfs->ns_blocksize_bits;
-		inode->i_flags = 0;
-		atomic_set(&inode->i_count, 1);
-		inode->i_nlink = 1;
-		inode->i_ino = ino;
-		inode->i_mode = S_IFREG;
-		inode->i_private = mi;
-
-#ifdef INIT_UNUSED_INODE_FIELDS
-		atomic_set(&inode->i_writecount, 0);
-		inode->i_size = 0;
-		inode->i_blocks = 0;
-		inode->i_bytes = 0;
-		inode->i_generation = 0;
-#ifdef CONFIG_QUOTA
-		memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
-#endif
-		inode->i_pipe = NULL;
-		inode->i_bdev = NULL;
-		inode->i_cdev = NULL;
-		inode->i_rdev = 0;
-#ifdef CONFIG_SECURITY
-		inode->i_security = NULL;
-#endif
-		inode->dirtied_when = 0;
-
-		INIT_LIST_HEAD(&inode->i_list);
-		INIT_LIST_HEAD(&inode->i_sb_list);
-		inode->i_state = 0;
-#endif
-
-		spin_lock_init(&inode->i_lock);
-		mutex_init(&inode->i_mutex);
-		init_rwsem(&inode->i_alloc_sem);
-
-		mapping->host = NULL;  /* instead of inode */
-		mapping->flags = 0;
-		mapping_set_gfp_mask(mapping, gfp_mask);
-		mapping->assoc_mapping = NULL;
-		mapping->backing_dev_info = nilfs->ns_bdi;
-
-		inode->i_mapping = mapping;
-	}
-
-	return inode;
-}
-
-struct inode *nilfs_mdt_new(struct the_nilfs *nilfs, struct super_block *sb,
-			    ino_t ino, size_t objsz)
-{
-	struct inode *inode;
-
-	inode = nilfs_mdt_new_common(nilfs, sb, ino, NILFS_MDT_GFP, objsz);
-	if (!inode)
-		return NULL;
+	inode->i_mode = S_IFREG;
+	mapping_set_gfp_mask(inode->i_mapping, gfp_mask);
+	inode->i_mapping->backing_dev_info = inode->i_sb->s_bdi;
 
 	inode->i_op = &def_mdt_iops;
 	inode->i_fop = &def_mdt_fops;
 	inode->i_mapping->a_ops = &def_mdt_aops;
-	return inode;
+
+	return 0;
 }
 
 void nilfs_mdt_set_entry_size(struct inode *inode, unsigned entry_size,
@@ -550,34 +444,159 @@
 	mi->mi_first_entry_offset = DIV_ROUND_UP(header_size, entry_size);
 }
 
-void nilfs_mdt_set_shadow(struct inode *orig, struct inode *shadow)
+static const struct address_space_operations shadow_map_aops = {
+	.sync_page		= block_sync_page,
+};
+
+/**
+ * nilfs_mdt_setup_shadow_map - setup shadow map and bind it to metadata file
+ * @inode: inode of the metadata file
+ * @shadow: shadow mapping
+ */
+int nilfs_mdt_setup_shadow_map(struct inode *inode,
+			       struct nilfs_shadow_map *shadow)
 {
-	shadow->i_mapping->assoc_mapping = orig->i_mapping;
-	NILFS_I(shadow)->i_btnode_cache.assoc_mapping =
-		&NILFS_I(orig)->i_btnode_cache;
+	struct nilfs_mdt_info *mi = NILFS_MDT(inode);
+	struct backing_dev_info *bdi = inode->i_sb->s_bdi;
+
+	INIT_LIST_HEAD(&shadow->frozen_buffers);
+	nilfs_mapping_init_once(&shadow->frozen_data);
+	nilfs_mapping_init(&shadow->frozen_data, bdi, &shadow_map_aops);
+	nilfs_mapping_init_once(&shadow->frozen_btnodes);
+	nilfs_mapping_init(&shadow->frozen_btnodes, bdi, &shadow_map_aops);
+	mi->mi_shadow = shadow;
+	return 0;
 }
 
-static void nilfs_mdt_clear(struct inode *inode)
+/**
+ * nilfs_mdt_save_to_shadow_map - copy bmap and dirty pages to shadow map
+ * @inode: inode of the metadata file
+ */
+int nilfs_mdt_save_to_shadow_map(struct inode *inode)
 {
+	struct nilfs_mdt_info *mi = NILFS_MDT(inode);
 	struct nilfs_inode_info *ii = NILFS_I(inode);
+	struct nilfs_shadow_map *shadow = mi->mi_shadow;
+	int ret;
 
-	invalidate_mapping_pages(inode->i_mapping, 0, -1);
-	truncate_inode_pages(inode->i_mapping, 0);
+	ret = nilfs_copy_dirty_pages(&shadow->frozen_data, inode->i_mapping);
+	if (ret)
+		goto out;
 
-	if (test_bit(NILFS_I_BMAP, &ii->i_state))
-		nilfs_bmap_clear(ii->i_bmap);
-	nilfs_btnode_cache_clear(&ii->i_btnode_cache);
+	ret = nilfs_copy_dirty_pages(&shadow->frozen_btnodes,
+				     &ii->i_btnode_cache);
+	if (ret)
+		goto out;
+
+	nilfs_bmap_save(ii->i_bmap, &shadow->bmap_store);
+ out:
+	return ret;
 }
 
-void nilfs_mdt_destroy(struct inode *inode)
+int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh)
 {
-	struct nilfs_mdt_info *mdi = NILFS_MDT(inode);
+	struct nilfs_shadow_map *shadow = NILFS_MDT(inode)->mi_shadow;
+	struct buffer_head *bh_frozen;
+	struct page *page;
+	int blkbits = inode->i_blkbits;
+	int ret = -ENOMEM;
 
-	if (mdi->mi_palloc_cache)
-		nilfs_palloc_destroy_cache(inode);
-	nilfs_mdt_clear(inode);
+	page = grab_cache_page(&shadow->frozen_data, bh->b_page->index);
+	if (!page)
+		return ret;
 
-	kfree(mdi->mi_bgl); /* kfree(NULL) is safe */
-	kfree(mdi);
-	nilfs_destroy_inode(inode);
+	if (!page_has_buffers(page))
+		create_empty_buffers(page, 1 << blkbits, 0);
+
+	bh_frozen = nilfs_page_get_nth_block(page, bh_offset(bh) >> blkbits);
+	if (bh_frozen) {
+		if (!buffer_uptodate(bh_frozen))
+			nilfs_copy_buffer(bh_frozen, bh);
+		if (list_empty(&bh_frozen->b_assoc_buffers)) {
+			list_add_tail(&bh_frozen->b_assoc_buffers,
+				      &shadow->frozen_buffers);
+			set_buffer_nilfs_redirected(bh);
+		} else {
+			brelse(bh_frozen); /* already frozen */
+		}
+		ret = 0;
+	}
+	unlock_page(page);
+	page_cache_release(page);
+	return ret;
+}
+
+struct buffer_head *
+nilfs_mdt_get_frozen_buffer(struct inode *inode, struct buffer_head *bh)
+{
+	struct nilfs_shadow_map *shadow = NILFS_MDT(inode)->mi_shadow;
+	struct buffer_head *bh_frozen = NULL;
+	struct page *page;
+	int n;
+
+	page = find_lock_page(&shadow->frozen_data, bh->b_page->index);
+	if (page) {
+		if (page_has_buffers(page)) {
+			n = bh_offset(bh) >> inode->i_blkbits;
+			bh_frozen = nilfs_page_get_nth_block(page, n);
+		}
+		unlock_page(page);
+		page_cache_release(page);
+	}
+	return bh_frozen;
+}
+
+static void nilfs_release_frozen_buffers(struct nilfs_shadow_map *shadow)
+{
+	struct list_head *head = &shadow->frozen_buffers;
+	struct buffer_head *bh;
+
+	while (!list_empty(head)) {
+		bh = list_first_entry(head, struct buffer_head,
+				      b_assoc_buffers);
+		list_del_init(&bh->b_assoc_buffers);
+		brelse(bh); /* drop ref-count to make it releasable */
+	}
+}
+
+/**
+ * nilfs_mdt_restore_from_shadow_map - restore dirty pages and bmap state
+ * @inode: inode of the metadata file
+ */
+void nilfs_mdt_restore_from_shadow_map(struct inode *inode)
+{
+	struct nilfs_mdt_info *mi = NILFS_MDT(inode);
+	struct nilfs_inode_info *ii = NILFS_I(inode);
+	struct nilfs_shadow_map *shadow = mi->mi_shadow;
+
+	down_write(&mi->mi_sem);
+
+	if (mi->mi_palloc_cache)
+		nilfs_palloc_clear_cache(inode);
+
+	nilfs_clear_dirty_pages(inode->i_mapping);
+	nilfs_copy_back_pages(inode->i_mapping, &shadow->frozen_data);
+
+	nilfs_clear_dirty_pages(&ii->i_btnode_cache);
+	nilfs_copy_back_pages(&ii->i_btnode_cache, &shadow->frozen_btnodes);
+
+	nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store);
+
+	up_write(&mi->mi_sem);
+}
+
+/**
+ * nilfs_mdt_clear_shadow_map - truncate pages in shadow map caches
+ * @inode: inode of the metadata file
+ */
+void nilfs_mdt_clear_shadow_map(struct inode *inode)
+{
+	struct nilfs_mdt_info *mi = NILFS_MDT(inode);
+	struct nilfs_shadow_map *shadow = mi->mi_shadow;
+
+	down_write(&mi->mi_sem);
+	nilfs_release_frozen_buffers(shadow);
+	truncate_inode_pages(&shadow->frozen_data, 0);
+	truncate_inode_pages(&shadow->frozen_btnodes, 0);
+	up_write(&mi->mi_sem);
 }
diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h
index 6c4bbb0..b13734b 100644
--- a/fs/nilfs2/mdt.h
+++ b/fs/nilfs2/mdt.h
@@ -28,26 +28,33 @@
 #include "nilfs.h"
 #include "page.h"
 
+struct nilfs_shadow_map {
+	struct nilfs_bmap_store bmap_store;
+	struct address_space frozen_data;
+	struct address_space frozen_btnodes;
+	struct list_head frozen_buffers;
+};
+
 /**
  * struct nilfs_mdt_info - on-memory private data of meta data files
- * @mi_nilfs: back pointer to the_nilfs struct
  * @mi_sem: reader/writer semaphore for meta data operations
  * @mi_bgl: per-blockgroup locking
  * @mi_entry_size: size of an entry
  * @mi_first_entry_offset: offset to the first entry
  * @mi_entries_per_block: number of entries in a block
  * @mi_palloc_cache: persistent object allocator cache
+ * @mi_shadow: shadow of bmap and page caches
  * @mi_blocks_per_group: number of blocks in a group
  * @mi_blocks_per_desc_block: number of blocks per descriptor block
  */
 struct nilfs_mdt_info {
-	struct the_nilfs       *mi_nilfs;
 	struct rw_semaphore	mi_sem;
 	struct blockgroup_lock *mi_bgl;
 	unsigned		mi_entry_size;
 	unsigned		mi_first_entry_offset;
 	unsigned long		mi_entries_per_block;
 	struct nilfs_palloc_cache *mi_palloc_cache;
+	struct nilfs_shadow_map *mi_shadow;
 	unsigned long		mi_blocks_per_group;
 	unsigned long		mi_blocks_per_desc_block;
 };
@@ -59,9 +66,7 @@
 
 static inline struct the_nilfs *NILFS_I_NILFS(struct inode *inode)
 {
-	struct super_block *sb = inode->i_sb;
-
-	return sb ? NILFS_SB(sb)->s_nilfs : NILFS_MDT(inode)->mi_nilfs;
+	return NILFS_SB(inode->i_sb)->s_nilfs;
 }
 
 /* Default GFP flags using highmem */
@@ -76,14 +81,17 @@
 int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long);
 int nilfs_mdt_fetch_dirty(struct inode *);
 
-struct inode *nilfs_mdt_new(struct the_nilfs *, struct super_block *, ino_t,
-			    size_t);
-struct inode *nilfs_mdt_new_common(struct the_nilfs *, struct super_block *,
-				   ino_t, gfp_t, size_t);
-void nilfs_mdt_destroy(struct inode *);
+int nilfs_mdt_init(struct inode *inode, gfp_t gfp_mask, size_t objsz);
 void nilfs_mdt_set_entry_size(struct inode *, unsigned, unsigned);
-void nilfs_mdt_set_shadow(struct inode *, struct inode *);
 
+int nilfs_mdt_setup_shadow_map(struct inode *inode,
+			       struct nilfs_shadow_map *shadow);
+int nilfs_mdt_save_to_shadow_map(struct inode *inode);
+void nilfs_mdt_restore_from_shadow_map(struct inode *inode);
+void nilfs_mdt_clear_shadow_map(struct inode *inode);
+int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh);
+struct buffer_head *nilfs_mdt_get_frozen_buffer(struct inode *inode,
+						struct buffer_head *bh);
 
 #define nilfs_mdt_mark_buffer_dirty(bh)	nilfs_mark_buffer_dirty(bh)
 
@@ -100,7 +108,7 @@
 
 static inline __u64 nilfs_mdt_cno(struct inode *inode)
 {
-	return NILFS_MDT(inode)->mi_nilfs->ns_cno;
+	return NILFS_I_NILFS(inode)->ns_cno;
 }
 
 #define nilfs_mdt_bgl_lock(inode, bg) \
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index ad6ed2c..185d160 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -40,7 +40,11 @@
 
 #include <linux/pagemap.h>
 #include "nilfs.h"
+#include "export.h"
 
+#define NILFS_FID_SIZE_NON_CONNECTABLE \
+	(offsetof(struct nilfs_fid, parent_gen) / 4)
+#define NILFS_FID_SIZE_CONNECTABLE	(sizeof(struct nilfs_fid) / 4)
 
 static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode)
 {
@@ -70,29 +74,13 @@
 	ino = nilfs_inode_by_name(dir, &dentry->d_name);
 	inode = NULL;
 	if (ino) {
-		inode = nilfs_iget(dir->i_sb, ino);
+		inode = nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino);
 		if (IS_ERR(inode))
 			return ERR_CAST(inode);
 	}
 	return d_splice_alias(inode, dentry);
 }
 
-struct dentry *nilfs_get_parent(struct dentry *child)
-{
-	unsigned long ino;
-	struct inode *inode;
-	struct qstr dotdot = {.name = "..", .len = 2};
-
-	ino = nilfs_inode_by_name(child->d_inode, &dotdot);
-	if (!ino)
-		return ERR_PTR(-ENOENT);
-
-	inode = nilfs_iget(child->d_inode->i_sb, ino);
-	if (IS_ERR(inode))
-		return ERR_CAST(inode);
-	return d_obtain_alias(inode);
-}
-
 /*
  * By the time this is called, we already have created
  * the directory cache entry for the new file, but it
@@ -468,6 +456,115 @@
 	return err;
 }
 
+/*
+ * Export operations
+ */
+static struct dentry *nilfs_get_parent(struct dentry *child)
+{
+	unsigned long ino;
+	struct inode *inode;
+	struct qstr dotdot = {.name = "..", .len = 2};
+	struct nilfs_root *root;
+
+	ino = nilfs_inode_by_name(child->d_inode, &dotdot);
+	if (!ino)
+		return ERR_PTR(-ENOENT);
+
+	root = NILFS_I(child->d_inode)->i_root;
+
+	inode = nilfs_iget(child->d_inode->i_sb, root, ino);
+	if (IS_ERR(inode))
+		return ERR_CAST(inode);
+
+	return d_obtain_alias(inode);
+}
+
+static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno,
+				       u64 ino, u32 gen)
+{
+	struct nilfs_root *root;
+	struct inode *inode;
+
+	if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO)
+		return ERR_PTR(-ESTALE);
+
+	root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno);
+	if (!root)
+		return ERR_PTR(-ESTALE);
+
+	inode = nilfs_iget(sb, root, ino);
+	nilfs_put_root(root);
+
+	if (IS_ERR(inode))
+		return ERR_CAST(inode);
+	if (gen && inode->i_generation != gen) {
+		iput(inode);
+		return ERR_PTR(-ESTALE);
+	}
+	return d_obtain_alias(inode);
+}
+
+static struct dentry *nilfs_fh_to_dentry(struct super_block *sb, struct fid *fh,
+					 int fh_len, int fh_type)
+{
+	struct nilfs_fid *fid = (struct nilfs_fid *)fh;
+
+	if ((fh_len != NILFS_FID_SIZE_NON_CONNECTABLE &&
+	     fh_len != NILFS_FID_SIZE_CONNECTABLE) ||
+	    (fh_type != FILEID_NILFS_WITH_PARENT &&
+	     fh_type != FILEID_NILFS_WITHOUT_PARENT))
+		return NULL;
+
+	return nilfs_get_dentry(sb, fid->cno, fid->ino, fid->gen);
+}
+
+static struct dentry *nilfs_fh_to_parent(struct super_block *sb, struct fid *fh,
+					 int fh_len, int fh_type)
+{
+	struct nilfs_fid *fid = (struct nilfs_fid *)fh;
+
+	if (fh_len != NILFS_FID_SIZE_CONNECTABLE ||
+	    fh_type != FILEID_NILFS_WITH_PARENT)
+		return NULL;
+
+	return nilfs_get_dentry(sb, fid->cno, fid->parent_ino, fid->parent_gen);
+}
+
+static int nilfs_encode_fh(struct dentry *dentry, __u32 *fh, int *lenp,
+			   int connectable)
+{
+	struct nilfs_fid *fid = (struct nilfs_fid *)fh;
+	struct inode *inode = dentry->d_inode;
+	struct nilfs_root *root = NILFS_I(inode)->i_root;
+	int type;
+
+	if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE ||
+	    (connectable && *lenp < NILFS_FID_SIZE_CONNECTABLE))
+		return 255;
+
+	fid->cno = root->cno;
+	fid->ino = inode->i_ino;
+	fid->gen = inode->i_generation;
+
+	if (connectable && !S_ISDIR(inode->i_mode)) {
+		struct inode *parent;
+
+		spin_lock(&dentry->d_lock);
+		parent = dentry->d_parent->d_inode;
+		fid->parent_ino = parent->i_ino;
+		fid->parent_gen = parent->i_generation;
+		spin_unlock(&dentry->d_lock);
+
+		type = FILEID_NILFS_WITH_PARENT;
+		*lenp = NILFS_FID_SIZE_CONNECTABLE;
+	} else {
+		type = FILEID_NILFS_WITHOUT_PARENT;
+		*lenp = NILFS_FID_SIZE_NON_CONNECTABLE;
+	}
+
+	return type;
+}
+
 const struct inode_operations nilfs_dir_inode_operations = {
 	.create		= nilfs_create,
 	.lookup		= nilfs_lookup,
@@ -491,4 +588,12 @@
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
+	.permission     = nilfs_permission,
+};
+
+const struct export_operations nilfs_export_ops = {
+	.encode_fh = nilfs_encode_fh,
+	.fh_to_dentry = nilfs_fh_to_dentry,
+	.fh_to_parent = nilfs_fh_to_parent,
+	.get_parent = nilfs_get_parent,
 };
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index d3d5404..f7560da 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -59,6 +59,7 @@
 #endif
 	struct buffer_head *i_bh;	/* i_bh contains a new or dirty
 					   disk inode */
+	struct nilfs_root *i_root;
 	struct inode vfs_inode;
 };
 
@@ -100,7 +101,6 @@
 	NILFS_I_INODE_DIRTY,		/* write_inode is requested */
 	NILFS_I_BMAP,			/* has bmap and btnode_cache */
 	NILFS_I_GCINODE,		/* inode for GC, on memory only */
-	NILFS_I_GCDAT,			/* shadow DAT, on memory only */
 };
 
 /*
@@ -192,7 +192,7 @@
 
 static inline struct inode *nilfs_dat_inode(const struct the_nilfs *nilfs)
 {
-	return nilfs_doing_gc() ? nilfs->ns_gc_dat : nilfs->ns_dat;
+	return nilfs->ns_dat;
 }
 
 /*
@@ -200,12 +200,9 @@
  */
 #ifdef CONFIG_NILFS_POSIX_ACL
 #error "NILFS: not yet supported POSIX ACL"
-extern int nilfs_permission(struct inode *, int, struct nameidata *);
 extern int nilfs_acl_chmod(struct inode *);
 extern int nilfs_init_acl(struct inode *, struct inode *);
 #else
-#define nilfs_permission   NULL
-
 static inline int nilfs_acl_chmod(struct inode *inode)
 {
 	return 0;
@@ -247,11 +244,19 @@
 extern void nilfs_set_inode_flags(struct inode *);
 extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *);
 extern void nilfs_write_inode_common(struct inode *, struct nilfs_inode *, int);
-extern struct inode *nilfs_iget(struct super_block *, unsigned long);
+struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root,
+			    unsigned long ino);
+struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root,
+				unsigned long ino);
+struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
+			 unsigned long ino);
+extern struct inode *nilfs_iget_for_gc(struct super_block *sb,
+				       unsigned long ino, __u64 cno);
 extern void nilfs_update_inode(struct inode *, struct buffer_head *);
 extern void nilfs_truncate(struct inode *);
 extern void nilfs_evict_inode(struct inode *);
 extern int nilfs_setattr(struct dentry *, struct iattr *);
+int nilfs_permission(struct inode *inode, int mask);
 extern int nilfs_load_inode_block(struct nilfs_sb_info *, struct inode *,
 				  struct buffer_head **);
 extern int nilfs_inode_dirty(struct inode *);
@@ -260,11 +265,7 @@
 extern int nilfs_mark_inode_dirty(struct inode *);
 extern void nilfs_dirty_inode(struct inode *);
 
-/* namei.c */
-extern struct dentry *nilfs_get_parent(struct dentry *);
-
 /* super.c */
-extern struct inode *nilfs_alloc_inode_common(struct the_nilfs *);
 extern struct inode *nilfs_alloc_inode(struct super_block *);
 extern void nilfs_destroy_inode(struct inode *);
 extern void nilfs_error(struct super_block *, const char *, const char *, ...)
@@ -283,8 +284,9 @@
 						      int flip);
 extern int nilfs_commit_super(struct nilfs_sb_info *, int);
 extern int nilfs_cleanup_super(struct nilfs_sb_info *);
-extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64);
-extern void nilfs_detach_checkpoint(struct nilfs_sb_info *);
+int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
+			    struct nilfs_root **root);
+int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno);
 
 /* gcinode.c */
 int nilfs_gccache_submit_read_data(struct inode *, sector_t, sector_t, __u64,
@@ -292,16 +294,8 @@
 int nilfs_gccache_submit_read_node(struct inode *, sector_t, __u64,
 				   struct buffer_head **);
 int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *);
-int nilfs_init_gccache(struct the_nilfs *);
-void nilfs_destroy_gccache(struct the_nilfs *);
-void nilfs_clear_gcinode(struct inode *);
-struct inode *nilfs_gc_iget(struct the_nilfs *, ino_t, __u64);
-void nilfs_remove_all_gcinode(struct the_nilfs *);
-
-/* gcdat.c */
-int nilfs_init_gcdat_inode(struct the_nilfs *);
-void nilfs_commit_gcdat_inode(struct the_nilfs *);
-void nilfs_clear_gcdat_inode(struct the_nilfs *);
+int nilfs_init_gcinode(struct inode *inode);
+void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs);
 
 /*
  * Inodes and files operations
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index aab11db..a6c3c2e8 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -79,8 +79,8 @@
 {
 	int blkbits = inode->i_blkbits;
 	pgoff_t index = blkoff >> (PAGE_CACHE_SHIFT - blkbits);
-	struct page *page, *opage;
-	struct buffer_head *bh, *obh;
+	struct page *page;
+	struct buffer_head *bh;
 
 	page = grab_cache_page(mapping, index);
 	if (unlikely(!page))
@@ -92,30 +92,6 @@
 		page_cache_release(page);
 		return NULL;
 	}
-	if (!buffer_uptodate(bh) && mapping->assoc_mapping != NULL) {
-		/*
-		 * Shadow page cache uses assoc_mapping to point its original
-		 * page cache.  The following code tries the original cache
-		 * if the given cache is a shadow and it didn't hit.
-		 */
-		opage = find_lock_page(mapping->assoc_mapping, index);
-		if (!opage)
-			return bh;
-
-		obh = __nilfs_get_page_block(opage, blkoff, index, blkbits,
-					     b_state);
-		if (buffer_uptodate(obh)) {
-			nilfs_copy_buffer(bh, obh);
-			if (buffer_dirty(obh)) {
-				nilfs_mark_buffer_dirty(bh);
-				if (!buffer_nilfs_node(bh) && NILFS_MDT(inode))
-					nilfs_mdt_mark_dirty(inode);
-			}
-		}
-		brelse(obh);
-		unlock_page(opage);
-		page_cache_release(opage);
-	}
 	return bh;
 }
 
@@ -131,6 +107,7 @@
 	lock_buffer(bh);
 	clear_buffer_nilfs_volatile(bh);
 	clear_buffer_nilfs_checked(bh);
+	clear_buffer_nilfs_redirected(bh);
 	clear_buffer_dirty(bh);
 	if (nilfs_page_buffers_clean(page))
 		__nilfs_clear_page_dirty(page);
@@ -483,6 +460,7 @@
 				clear_buffer_dirty(bh);
 				clear_buffer_nilfs_volatile(bh);
 				clear_buffer_nilfs_checked(bh);
+				clear_buffer_nilfs_redirected(bh);
 				clear_buffer_uptodate(bh);
 				clear_buffer_mapped(bh);
 				unlock_buffer(bh);
@@ -513,6 +491,31 @@
 	}
 	return nc;
 }
+ 
+void nilfs_mapping_init_once(struct address_space *mapping)
+{
+	memset(mapping, 0, sizeof(*mapping));
+	INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC);
+	spin_lock_init(&mapping->tree_lock);
+	INIT_LIST_HEAD(&mapping->private_list);
+	spin_lock_init(&mapping->private_lock);
+
+	spin_lock_init(&mapping->i_mmap_lock);
+	INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap);
+	INIT_LIST_HEAD(&mapping->i_mmap_nonlinear);
+}
+
+void nilfs_mapping_init(struct address_space *mapping,
+			struct backing_dev_info *bdi,
+			const struct address_space_operations *aops)
+{
+	mapping->host = NULL;
+	mapping->flags = 0;
+	mapping_set_gfp_mask(mapping, GFP_NOFS);
+	mapping->assoc_mapping = NULL;
+	mapping->backing_dev_info = bdi;
+	mapping->a_ops = aops;
+}
 
 /*
  * NILFS2 needs clear_page_dirty() in the following two cases:
diff --git a/fs/nilfs2/page.h b/fs/nilfs2/page.h
index f53d8da..fb9e8a8 100644
--- a/fs/nilfs2/page.h
+++ b/fs/nilfs2/page.h
@@ -35,12 +35,14 @@
 	BH_NILFS_Node,
 	BH_NILFS_Volatile,
 	BH_NILFS_Checked,
+	BH_NILFS_Redirected,
 };
 
 BUFFER_FNS(NILFS_Allocated, nilfs_allocated)	/* nilfs private buffers */
 BUFFER_FNS(NILFS_Node, nilfs_node)		/* nilfs node buffers */
 BUFFER_FNS(NILFS_Volatile, nilfs_volatile)
 BUFFER_FNS(NILFS_Checked, nilfs_checked)	/* buffer is verified */
+BUFFER_FNS(NILFS_Redirected, nilfs_redirected)	/* redirected to a copy */
 
 
 void nilfs_mark_buffer_dirty(struct buffer_head *bh);
@@ -59,6 +61,10 @@
 int nilfs_copy_dirty_pages(struct address_space *, struct address_space *);
 void nilfs_copy_back_pages(struct address_space *, struct address_space *);
 void nilfs_clear_dirty_pages(struct address_space *);
+void nilfs_mapping_init_once(struct address_space *mapping);
+void nilfs_mapping_init(struct address_space *mapping,
+			struct backing_dev_info *bdi,
+			const struct address_space_operations *aops);
 unsigned nilfs_page_count_clean_buffers(struct page *, unsigned, unsigned);
 
 #define NILFS_PAGE_BUG(page, m, a...) \
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index d0c35ef..5d2711c2 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -440,7 +440,6 @@
 	segnum[2] = ri->ri_segnum;
 	segnum[3] = ri->ri_nextnum;
 
-	nilfs_attach_writer(nilfs, sbi);
 	/*
 	 * Releasing the next segment of the latest super root.
 	 * The next segment is invalidated by this recovery.
@@ -480,7 +479,6 @@
 
  failed:
 	/* No need to recover sufile because it will be destroyed on error */
-	nilfs_detach_writer(nilfs, sbi);
 	return err;
 }
 
@@ -504,6 +502,7 @@
 
 static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
 				      struct nilfs_sb_info *sbi,
+				      struct nilfs_root *root,
 				      struct list_head *head,
 				      unsigned long *nr_salvaged_blocks)
 {
@@ -515,7 +514,7 @@
 	int err = 0, err2 = 0;
 
 	list_for_each_entry_safe(rb, n, head, list) {
-		inode = nilfs_iget(sbi->s_super, rb->ino);
+		inode = nilfs_iget(sbi->s_super, root, rb->ino);
 		if (IS_ERR(inode)) {
 			err = PTR_ERR(inode);
 			inode = NULL;
@@ -578,6 +577,7 @@
  */
 static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
 				 struct nilfs_sb_info *sbi,
+				 struct nilfs_root *root,
 				 struct nilfs_recovery_info *ri)
 {
 	struct buffer_head *bh_sum = NULL;
@@ -597,7 +597,6 @@
 	};
 	int state = RF_INIT_ST;
 
-	nilfs_attach_writer(nilfs, sbi);
 	pseg_start = ri->ri_lsegs_start;
 	seg_seq = ri->ri_lsegs_start_seq;
 	segnum = nilfs_get_segnum_of_block(nilfs, pseg_start);
@@ -649,7 +648,7 @@
 				goto failed;
 			if (flags & NILFS_SS_LOGEND) {
 				err = nilfs_recover_dsync_blocks(
-					nilfs, sbi, &dsync_blocks,
+					nilfs, sbi, root, &dsync_blocks,
 					&nsalvaged_blocks);
 				if (unlikely(err))
 					goto failed;
@@ -688,7 +687,6 @@
  out:
 	brelse(bh_sum);
 	dispose_recovery_list(&dsync_blocks);
-	nilfs_detach_writer(nilfs, sbi);
 	return err;
 
  confused:
@@ -746,19 +744,20 @@
 			      struct nilfs_sb_info *sbi,
 			      struct nilfs_recovery_info *ri)
 {
+	struct nilfs_root *root;
 	int err;
 
 	if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0)
 		return 0;
 
-	err = nilfs_attach_checkpoint(sbi, ri->ri_cno);
+	err = nilfs_attach_checkpoint(sbi, 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, ri);
+	err = nilfs_do_roll_forward(nilfs, sbi, root, ri);
 	if (unlikely(err))
 		goto failed;
 
@@ -770,7 +769,7 @@
 			goto failed;
 		}
 
-		err = nilfs_attach_segment_constructor(sbi);
+		err = nilfs_attach_segment_constructor(sbi, root);
 		if (unlikely(err))
 			goto failed;
 
@@ -788,7 +787,7 @@
 	}
 
  failed:
-	nilfs_detach_checkpoint(sbi);
+	nilfs_put_root(root);
 	return err;
 }
 
diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h
index 0776ccc..35a0715 100644
--- a/fs/nilfs2/sb.h
+++ b/fs/nilfs2/sb.h
@@ -42,11 +42,6 @@
  * NILFS super-block data in memory
  */
 struct nilfs_sb_info {
-	/* Snapshot status */
-	__u64 s_snapshot_cno;		/* Checkpoint number */
-	atomic_t s_inodes_count;
-	atomic_t s_blocks_count;	/* Reserved (might be deleted) */
-
 	/* Mount options */
 	unsigned long s_mount_opt;
 	uid_t s_resuid;
@@ -59,8 +54,6 @@
 	/* Fundamental members */
 	struct super_block *s_super;	/* reverse pointer to super_block */
 	struct the_nilfs *s_nilfs;
-	struct list_head s_list;	/* list head for nilfs->ns_supers */
-	atomic_t s_count;		/* reference count */
 
 	/* Segment constructor */
 	struct list_head s_dirty_files;	/* dirty files list */
@@ -68,9 +61,6 @@
 	spinlock_t s_inode_lock;	/* Lock for the nilfs inode.
 					   It covers s_dirty_files list */
 
-	/* Metadata files */
-	struct inode *s_ifile;		/* index file inode */
-
 	/* Inode allocator */
 	spinlock_t s_next_gen_lock;
 	u32 s_next_generation;
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c
index 4588fb9..0f83e93 100644
--- a/fs/nilfs2/segbuf.c
+++ b/fs/nilfs2/segbuf.c
@@ -371,7 +371,8 @@
 	struct bio *bio = wi->bio;
 	int err;
 
-	if (segbuf->sb_nbio > 0 && bdi_write_congested(wi->nilfs->ns_bdi)) {
+	if (segbuf->sb_nbio > 0 &&
+	    bdi_write_congested(segbuf->sb_super->s_bdi)) {
 		wait_for_completion(&segbuf->sb_bio_event);
 		segbuf->sb_nbio--;
 		if (unlikely(atomic_read(&segbuf->sb_err))) {
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 9fd051a..d926af6 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -191,6 +191,8 @@
 	if (ret > 0)
 		return 0;
 
+	vfs_check_frozen(sb, SB_FREEZE_WRITE);
+
 	sbi = NILFS_SB(sb);
 	nilfs = sbi->s_nilfs;
 	down_read(&nilfs->ns_segctor_sem);
@@ -366,8 +368,7 @@
 
 	if (nilfs_doing_gc())
 		flags = NILFS_SS_GC;
-	err = nilfs_segbuf_reset(segbuf, flags, sci->sc_seg_ctime,
-				 sci->sc_sbi->s_nilfs->ns_cno);
+	err = nilfs_segbuf_reset(segbuf, flags, sci->sc_seg_ctime, sci->sc_cno);
 	if (unlikely(err))
 		return err;
 
@@ -440,17 +441,26 @@
 	struct nilfs_finfo *finfo;
 	struct nilfs_inode_info *ii;
 	struct nilfs_segment_buffer *segbuf;
+	__u64 cno;
 
 	if (sci->sc_blk_cnt == 0)
 		return;
 
 	ii = NILFS_I(inode);
+
+	if (test_bit(NILFS_I_GCINODE, &ii->i_state))
+		cno = ii->i_cno;
+	else if (NILFS_ROOT_METADATA_FILE(inode->i_ino))
+		cno = 0;
+	else
+		cno = sci->sc_cno;
+
 	finfo = nilfs_segctor_map_segsum_entry(sci, &sci->sc_finfo_ptr,
 						 sizeof(*finfo));
 	finfo->fi_ino = cpu_to_le64(inode->i_ino);
 	finfo->fi_nblocks = cpu_to_le32(sci->sc_blk_cnt);
 	finfo->fi_ndatablk = cpu_to_le32(sci->sc_datablk_cnt);
-	finfo->fi_cno = cpu_to_le64(ii->i_cno);
+	finfo->fi_cno = cpu_to_le64(cno);
 
 	segbuf = sci->sc_curseg;
 	segbuf->sb_sum.sumbytes = sci->sc_binfo_ptr.offset +
@@ -755,12 +765,12 @@
 	}
 }
 
-static int nilfs_test_metadata_dirty(struct nilfs_sb_info *sbi)
+static int nilfs_test_metadata_dirty(struct the_nilfs *nilfs,
+				     struct nilfs_root *root)
 {
-	struct the_nilfs *nilfs = sbi->s_nilfs;
 	int ret = 0;
 
-	if (nilfs_mdt_fetch_dirty(sbi->s_ifile))
+	if (nilfs_mdt_fetch_dirty(root->ifile))
 		ret++;
 	if (nilfs_mdt_fetch_dirty(nilfs->ns_cpfile))
 		ret++;
@@ -785,7 +795,7 @@
 	struct nilfs_sb_info *sbi = sci->sc_sbi;
 	int ret = 0;
 
-	if (nilfs_test_metadata_dirty(sbi))
+	if (nilfs_test_metadata_dirty(sbi->s_nilfs, sci->sc_root))
 		set_bit(NILFS_SC_DIRTY, &sci->sc_flags);
 
 	spin_lock(&sbi->s_inode_lock);
@@ -801,7 +811,7 @@
 	struct nilfs_sb_info *sbi = sci->sc_sbi;
 	struct the_nilfs *nilfs = sbi->s_nilfs;
 
-	nilfs_mdt_clear_dirty(sbi->s_ifile);
+	nilfs_mdt_clear_dirty(sci->sc_root->ifile);
 	nilfs_mdt_clear_dirty(nilfs->ns_cpfile);
 	nilfs_mdt_clear_dirty(nilfs->ns_sufile);
 	nilfs_mdt_clear_dirty(nilfs_dat_inode(nilfs));
@@ -848,9 +858,9 @@
 	raw_cp->cp_snapshot_list.ssl_next = 0;
 	raw_cp->cp_snapshot_list.ssl_prev = 0;
 	raw_cp->cp_inodes_count =
-		cpu_to_le64(atomic_read(&sbi->s_inodes_count));
+		cpu_to_le64(atomic_read(&sci->sc_root->inodes_count));
 	raw_cp->cp_blocks_count =
-		cpu_to_le64(atomic_read(&sbi->s_blocks_count));
+		cpu_to_le64(atomic_read(&sci->sc_root->blocks_count));
 	raw_cp->cp_nblk_inc =
 		cpu_to_le64(sci->sc_nblk_inc + sci->sc_nblk_this_inc);
 	raw_cp->cp_create = cpu_to_le64(sci->sc_seg_ctime);
@@ -861,7 +871,8 @@
 	else
 		nilfs_checkpoint_set_minor(raw_cp);
 
-	nilfs_write_inode_common(sbi->s_ifile, &raw_cp->cp_ifile_inode, 1);
+	nilfs_write_inode_common(sci->sc_root->ifile,
+				 &raw_cp->cp_ifile_inode, 1);
 	nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, nilfs->ns_cno, bh_cp);
 	return 0;
 
@@ -886,13 +897,12 @@
 	}
 }
 
-static void nilfs_segctor_fill_in_file_bmap(struct nilfs_sc_info *sci,
-					    struct inode *ifile)
+static void nilfs_segctor_fill_in_file_bmap(struct nilfs_sc_info *sci)
 {
 	struct nilfs_inode_info *ii;
 
 	list_for_each_entry(ii, &sci->sc_dirty_files, i_dirty) {
-		nilfs_fill_in_file_bmap(ifile, ii);
+		nilfs_fill_in_file_bmap(sci->sc_root->ifile, ii);
 		set_bit(NILFS_I_COLLECTED, &ii->i_state);
 	}
 }
@@ -1135,7 +1145,7 @@
 		sci->sc_stage.flags |= NILFS_CF_IFILE_STARTED;
 		/* Fall through */
 	case NILFS_ST_IFILE:
-		err = nilfs_segctor_scan_file(sci, sbi->s_ifile,
+		err = nilfs_segctor_scan_file(sci, sci->sc_root->ifile,
 					      &nilfs_sc_file_ops);
 		if (unlikely(err))
 			break;
@@ -1900,6 +1910,7 @@
 			set_buffer_uptodate(bh);
 			clear_buffer_dirty(bh);
 			clear_buffer_nilfs_volatile(bh);
+			clear_buffer_nilfs_redirected(bh);
 			if (bh == segbuf->sb_super_root) {
 				if (bh->b_page != bd_page) {
 					end_page_writeback(bd_page);
@@ -1936,11 +1947,9 @@
 
 	nilfs_drop_collected_inodes(&sci->sc_dirty_files);
 
-	if (nilfs_doing_gc()) {
+	if (nilfs_doing_gc())
 		nilfs_drop_collected_inodes(&sci->sc_gc_inodes);
-		if (update_sr)
-			nilfs_commit_gcdat_inode(nilfs);
-	} else
+	else
 		nilfs->ns_nongc_ctime = sci->sc_seg_ctime;
 
 	sci->sc_nblk_inc += sci->sc_nblk_this_inc;
@@ -1976,7 +1985,7 @@
 					struct nilfs_sb_info *sbi)
 {
 	struct nilfs_inode_info *ii, *n;
-	__u64 cno = sbi->s_nilfs->ns_cno;
+	struct inode *ifile = sci->sc_root->ifile;
 
 	spin_lock(&sbi->s_inode_lock);
  retry:
@@ -1987,14 +1996,14 @@
 
 			spin_unlock(&sbi->s_inode_lock);
 			err = nilfs_ifile_get_inode_block(
-				sbi->s_ifile, ii->vfs_inode.i_ino, &ibh);
+				ifile, ii->vfs_inode.i_ino, &ibh);
 			if (unlikely(err)) {
 				nilfs_warning(sbi->s_super, __func__,
 					      "failed to get inode block.\n");
 				return err;
 			}
 			nilfs_mdt_mark_buffer_dirty(ibh);
-			nilfs_mdt_mark_dirty(sbi->s_ifile);
+			nilfs_mdt_mark_dirty(ifile);
 			spin_lock(&sbi->s_inode_lock);
 			if (likely(!ii->i_bh))
 				ii->i_bh = ibh;
@@ -2002,7 +2011,6 @@
 				brelse(ibh);
 			goto retry;
 		}
-		ii->i_cno = cno;
 
 		clear_bit(NILFS_I_QUEUED, &ii->i_state);
 		set_bit(NILFS_I_BUSY, &ii->i_state);
@@ -2011,8 +2019,6 @@
 	}
 	spin_unlock(&sbi->s_inode_lock);
 
-	NILFS_I(sbi->s_ifile)->i_cno = cno;
-
 	return 0;
 }
 
@@ -2021,19 +2027,13 @@
 {
 	struct nilfs_transaction_info *ti = current->journal_info;
 	struct nilfs_inode_info *ii, *n;
-	__u64 cno = sbi->s_nilfs->ns_cno;
 
 	spin_lock(&sbi->s_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)) {
-			/* The current checkpoint number (=nilfs->ns_cno) is
-			   changed between check-in and check-out only if the
-			   super root is written out.  So, we can update i_cno
-			   for the inodes that remain in the dirty list. */
-			ii->i_cno = cno;
+		    test_bit(NILFS_I_DIRTY, &ii->i_state))
 			continue;
-		}
+
 		clear_bit(NILFS_I_BUSY, &ii->i_state);
 		brelse(ii->i_bh);
 		ii->i_bh = NULL;
@@ -2054,12 +2054,13 @@
 	int err;
 
 	sci->sc_stage.scnt = NILFS_ST_INIT;
+	sci->sc_cno = nilfs->ns_cno;
 
 	err = nilfs_segctor_check_in_files(sci, sbi);
 	if (unlikely(err))
 		goto out;
 
-	if (nilfs_test_metadata_dirty(sbi))
+	if (nilfs_test_metadata_dirty(nilfs, sci->sc_root))
 		set_bit(NILFS_SC_DIRTY, &sci->sc_flags);
 
 	if (nilfs_segctor_clean(sci))
@@ -2091,7 +2092,7 @@
 			goto failed;
 
 		if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED)
-			nilfs_segctor_fill_in_file_bmap(sci, sbi->s_ifile);
+			nilfs_segctor_fill_in_file_bmap(sci);
 
 		if (mode == SC_LSEG_SR &&
 		    sci->sc_stage.scnt >= NILFS_ST_CPFILE) {
@@ -2452,9 +2453,8 @@
 	list_for_each_entry_safe(ii, n, head, i_dirty) {
 		if (!test_bit(NILFS_I_UPDATED, &ii->i_state))
 			continue;
-		hlist_del_init(&ii->vfs_inode.i_hash);
 		list_del_init(&ii->i_dirty);
-		nilfs_clear_gcinode(&ii->vfs_inode);
+		iput(&ii->vfs_inode);
 	}
 }
 
@@ -2472,13 +2472,15 @@
 
 	nilfs_transaction_lock(sbi, &ti, 1);
 
-	err = nilfs_init_gcdat_inode(nilfs);
+	err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);
 	if (unlikely(err))
 		goto out_unlock;
 
 	err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs);
-	if (unlikely(err))
+	if (unlikely(err)) {
+		nilfs_mdt_restore_from_shadow_map(nilfs->ns_dat);
 		goto out_unlock;
+	}
 
 	sci->sc_freesegs = kbufs[4];
 	sci->sc_nfreesegs = argv[4].v_nmembs;
@@ -2510,7 +2512,7 @@
  out_unlock:
 	sci->sc_freesegs = NULL;
 	sci->sc_nfreesegs = 0;
-	nilfs_clear_gcdat_inode(nilfs);
+	nilfs_mdt_clear_shadow_map(nilfs->ns_dat);
 	nilfs_transaction_unlock(sbi);
 	return err;
 }
@@ -2672,6 +2674,8 @@
 }
 
 static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci)
+	__acquires(&sci->sc_state_lock)
+	__releases(&sci->sc_state_lock)
 {
 	sci->sc_state |= NILFS_SEGCTOR_QUIT;
 
@@ -2686,7 +2690,8 @@
 /*
  * 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 nilfs_sb_info *sbi,
+					       struct nilfs_root *root)
 {
 	struct nilfs_sc_info *sci;
 
@@ -2697,6 +2702,9 @@
 	sci->sc_sbi = sbi;
 	sci->sc_super = sbi->s_super;
 
+	nilfs_get_root(root);
+	sci->sc_root = root;
+
 	init_waitqueue_head(&sci->sc_wait_request);
 	init_waitqueue_head(&sci->sc_wait_daemon);
 	init_waitqueue_head(&sci->sc_wait_task);
@@ -2771,6 +2779,8 @@
 	WARN_ON(!list_empty(&sci->sc_segbufs));
 	WARN_ON(!list_empty(&sci->sc_write_logs));
 
+	nilfs_put_root(sci->sc_root);
+
 	down_write(&sbi->s_nilfs->ns_segctor_sem);
 
 	del_timer_sync(&sci->sc_timer);
@@ -2780,6 +2790,7 @@
 /**
  * nilfs_attach_segment_constructor - attach a segment constructor
  * @sbi: nilfs_sb_info
+ * @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.
@@ -2789,9 +2800,9 @@
  *
  * %-ENOMEM - Insufficient memory available.
  */
-int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi)
+int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi,
+				     struct nilfs_root *root)
 {
-	struct the_nilfs *nilfs = sbi->s_nilfs;
 	int err;
 
 	if (NILFS_SC(sbi)) {
@@ -2803,14 +2814,12 @@
 		nilfs_detach_segment_constructor(sbi);
 	}
 
-	sbi->s_sc_info = nilfs_segctor_new(sbi);
+	sbi->s_sc_info = nilfs_segctor_new(sbi, root);
 	if (!sbi->s_sc_info)
 		return -ENOMEM;
 
-	nilfs_attach_writer(nilfs, sbi);
 	err = nilfs_segctor_start_thread(NILFS_SC(sbi));
 	if (err) {
-		nilfs_detach_writer(nilfs, sbi);
 		kfree(sbi->s_sc_info);
 		sbi->s_sc_info = NULL;
 	}
@@ -2847,5 +2856,4 @@
 	up_write(&nilfs->ns_segctor_sem);
 
 	nilfs_dispose_list(sbi, &garbage_list, 1);
-	nilfs_detach_writer(nilfs, sbi);
 }
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h
index 17c487b..cd8056e 100644
--- a/fs/nilfs2/segment.h
+++ b/fs/nilfs2/segment.h
@@ -29,6 +29,8 @@
 #include <linux/nilfs2_fs.h>
 #include "sb.h"
 
+struct nilfs_root;
+
 /**
  * struct nilfs_recovery_info - Recovery information
  * @ri_need_recovery: Recovery status
@@ -87,6 +89,7 @@
  * 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
  * @sc_gc_inodes: List of GC inodes having blocks to be written
@@ -107,6 +110,7 @@
  * @sc_datablk_cnt: Data block count of a file
  * @sc_nblk_this_inc: Number of blocks included in the current logical segment
  * @sc_seg_ctime: Creation time
+ * @sc_cno: checkpoint number of current log
  * @sc_flags: Internal flags
  * @sc_state_lock: spinlock for sc_state and so on
  * @sc_state: Segctord state flags
@@ -128,6 +132,7 @@
 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;
 
@@ -156,7 +161,7 @@
 	unsigned long		sc_datablk_cnt;
 	unsigned long		sc_nblk_this_inc;
 	time_t			sc_seg_ctime;
-
+	__u64			sc_cno;
 	unsigned long		sc_flags;
 
 	spinlock_t		sc_state_lock;
@@ -230,7 +235,8 @@
 extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *,
 				void **);
 
-extern int nilfs_attach_segment_constructor(struct nilfs_sb_info *);
+int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi,
+				     struct nilfs_root *root);
 extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *);
 
 /* recovery.c */
diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c
index 3c6cc60..1d6f488 100644
--- a/fs/nilfs2/sufile.c
+++ b/fs/nilfs2/sufile.c
@@ -505,7 +505,7 @@
 {
 	struct buffer_head *header_bh;
 	struct nilfs_sufile_header *header;
-	struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs;
+	struct the_nilfs *nilfs = NILFS_I_NILFS(sufile);
 	void *kaddr;
 	int ret;
 
@@ -583,7 +583,7 @@
 	struct nilfs_segment_usage *su;
 	struct nilfs_suinfo *si = buf;
 	size_t susz = NILFS_MDT(sufile)->mi_entry_size;
-	struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs;
+	struct the_nilfs *nilfs = NILFS_I_NILFS(sufile);
 	void *kaddr;
 	unsigned long nsegs, segusages_per_block;
 	ssize_t n;
@@ -635,46 +635,55 @@
 }
 
 /**
- * nilfs_sufile_read - read sufile inode
- * @sufile: sufile inode
+ * nilfs_sufile_read - read or get sufile inode
+ * @sb: super block instance
+ * @susize: size of a segment usage entry
  * @raw_inode: on-disk sufile inode
+ * @inodep: buffer to store the inode
  */
-int nilfs_sufile_read(struct inode *sufile, struct nilfs_inode *raw_inode)
+int nilfs_sufile_read(struct super_block *sb, size_t susize,
+		      struct nilfs_inode *raw_inode, struct inode **inodep)
 {
-	struct nilfs_sufile_info *sui = NILFS_SUI(sufile);
+	struct inode *sufile;
+	struct nilfs_sufile_info *sui;
 	struct buffer_head *header_bh;
 	struct nilfs_sufile_header *header;
 	void *kaddr;
-	int ret;
+	int err;
 
-	ret = nilfs_read_inode_common(sufile, raw_inode);
-	if (ret < 0)
-		return ret;
+	sufile = nilfs_iget_locked(sb, NULL, NILFS_SUFILE_INO);
+	if (unlikely(!sufile))
+		return -ENOMEM;
+	if (!(sufile->i_state & I_NEW))
+		goto out;
 
-	ret = nilfs_sufile_get_header_block(sufile, &header_bh);
-	if (!ret) {
-		kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
-		header = kaddr + bh_offset(header_bh);
-		sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs);
-		kunmap_atomic(kaddr, KM_USER0);
-		brelse(header_bh);
-	}
-	return ret;
-}
+	err = nilfs_mdt_init(sufile, NILFS_MDT_GFP, sizeof(*sui));
+	if (err)
+		goto failed;
 
-/**
- * nilfs_sufile_new - create sufile
- * @nilfs: nilfs object
- * @susize: size of a segment usage entry
- */
-struct inode *nilfs_sufile_new(struct the_nilfs *nilfs, size_t susize)
-{
-	struct inode *sufile;
+	nilfs_mdt_set_entry_size(sufile, susize,
+				 sizeof(struct nilfs_sufile_header));
 
-	sufile = nilfs_mdt_new(nilfs, NULL, NILFS_SUFILE_INO,
-			       sizeof(struct nilfs_sufile_info));
-	if (sufile)
-		nilfs_mdt_set_entry_size(sufile, susize,
-					 sizeof(struct nilfs_sufile_header));
-	return sufile;
+	err = nilfs_read_inode_common(sufile, raw_inode);
+	if (err)
+		goto failed;
+
+	err = nilfs_sufile_get_header_block(sufile, &header_bh);
+	if (err)
+		goto failed;
+
+	sui = NILFS_SUI(sufile);
+	kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+	header = kaddr + bh_offset(header_bh);
+	sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs);
+	kunmap_atomic(kaddr, KM_USER0);
+	brelse(header_bh);
+
+	unlock_new_inode(sufile);
+ out:
+	*inodep = sufile;
+	return 0;
+ failed:
+	iget_failed(sufile);
+	return err;
 }
diff --git a/fs/nilfs2/sufile.h b/fs/nilfs2/sufile.h
index 15163b8..a943fba 100644
--- a/fs/nilfs2/sufile.h
+++ b/fs/nilfs2/sufile.h
@@ -31,7 +31,7 @@
 
 static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile)
 {
-	return NILFS_MDT(sufile)->mi_nilfs->ns_nsegments;
+	return NILFS_I_NILFS(sufile)->ns_nsegments;
 }
 
 unsigned long nilfs_sufile_get_ncleansegs(struct inode *sufile);
@@ -61,8 +61,8 @@
 void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *,
 			       struct buffer_head *);
 
-int nilfs_sufile_read(struct inode *sufile, struct nilfs_inode *raw_inode);
-struct inode *nilfs_sufile_new(struct the_nilfs *nilfs, size_t susize);
+int nilfs_sufile_read(struct super_block *sb, size_t susize,
+		      struct nilfs_inode *raw_inode, struct inode **inodep);
 
 /**
  * nilfs_sufile_scrap - make a segment garbage
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 9222633..35ae03c 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -45,14 +45,13 @@
 #include <linux/parser.h>
 #include <linux/random.h>
 #include <linux/crc32.h>
-#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 #include <linux/writeback.h>
 #include <linux/kobject.h>
-#include <linux/exportfs.h>
 #include <linux/seq_file.h>
 #include <linux/mount.h>
 #include "nilfs.h"
+#include "export.h"
 #include "mdt.h"
 #include "alloc.h"
 #include "btree.h"
@@ -69,11 +68,12 @@
 		   "(NILFS)");
 MODULE_LICENSE("GPL");
 
-struct kmem_cache *nilfs_inode_cachep;
+static struct kmem_cache *nilfs_inode_cachep;
 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_remount(struct super_block *sb, int *flags, char *data);
 
 static void nilfs_set_error(struct nilfs_sb_info *sbi)
@@ -147,7 +147,7 @@
 }
 
 
-struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs)
+struct inode *nilfs_alloc_inode(struct super_block *sb)
 {
 	struct nilfs_inode_info *ii;
 
@@ -156,18 +156,20 @@
 		return NULL;
 	ii->i_bh = NULL;
 	ii->i_state = 0;
+	ii->i_cno = 0;
 	ii->vfs_inode.i_version = 1;
-	nilfs_btnode_cache_init(&ii->i_btnode_cache, nilfs->ns_bdi);
+	nilfs_btnode_cache_init(&ii->i_btnode_cache, sb->s_bdi);
 	return &ii->vfs_inode;
 }
 
-struct inode *nilfs_alloc_inode(struct super_block *sb)
-{
-	return nilfs_alloc_inode_common(NILFS_SB(sb)->s_nilfs);
-}
-
 void nilfs_destroy_inode(struct inode *inode)
 {
+	struct nilfs_mdt_info *mdi = NILFS_MDT(inode);
+
+	if (mdi) {
+		kfree(mdi->mi_bgl); /* kfree(NULL) is safe */
+		kfree(mdi);
+	}
 	kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode));
 }
 
@@ -178,17 +180,9 @@
 
  retry:
 	set_buffer_dirty(nilfs->ns_sbh[0]);
-
 	if (nilfs_test_opt(sbi, BARRIER)) {
 		err = __sync_dirty_buffer(nilfs->ns_sbh[0],
-					  WRITE_SYNC | WRITE_BARRIER);
-		if (err == -EOPNOTSUPP) {
-			nilfs_warning(sbi->s_super, __func__,
-				      "barrier-based sync failed. "
-				      "disabling barriers\n");
-			nilfs_clear_opt(sbi, BARRIER);
-			goto retry;
-		}
+					  WRITE_SYNC | WRITE_FLUSH_FUA);
 	} else {
 		err = sync_dirty_buffer(nilfs->ns_sbh[0]);
 	}
@@ -342,8 +336,6 @@
 	struct nilfs_sb_info *sbi = NILFS_SB(sb);
 	struct the_nilfs *nilfs = sbi->s_nilfs;
 
-	lock_kernel();
-
 	nilfs_detach_segment_constructor(sbi);
 
 	if (!(sb->s_flags & MS_RDONLY)) {
@@ -351,18 +343,15 @@
 		nilfs_cleanup_super(sbi);
 		up_write(&nilfs->ns_sem);
 	}
-	down_write(&nilfs->ns_super_sem);
-	if (nilfs->ns_current == sbi)
-		nilfs->ns_current = NULL;
-	up_write(&nilfs->ns_super_sem);
 
-	nilfs_detach_checkpoint(sbi);
-	put_nilfs(sbi->s_nilfs);
+	iput(nilfs->ns_sufile);
+	iput(nilfs->ns_cpfile);
+	iput(nilfs->ns_dat);
+
+	destroy_nilfs(nilfs);
 	sbi->s_super = NULL;
 	sb->s_fs_info = NULL;
-	nilfs_put_sbinfo(sbi);
-
-	unlock_kernel();
+	kfree(sbi);
 }
 
 static int nilfs_sync_fs(struct super_block *sb, int wait)
@@ -389,21 +378,22 @@
 	return err;
 }
 
-int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno)
+int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
+			    struct nilfs_root **rootp)
 {
 	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct nilfs_root *root;
 	struct nilfs_checkpoint *raw_cp;
 	struct buffer_head *bh_cp;
-	int err;
+	int err = -ENOMEM;
 
-	down_write(&nilfs->ns_super_sem);
-	list_add(&sbi->s_list, &nilfs->ns_supers);
-	up_write(&nilfs->ns_super_sem);
+	root = nilfs_find_or_create_root(
+		nilfs, curr_mnt ? NILFS_CPTREE_CURRENT_CNO : cno);
+	if (!root)
+		return err;
 
-	err = -ENOMEM;
-	sbi->s_ifile = nilfs_ifile_new(sbi, nilfs->ns_inode_size);
-	if (!sbi->s_ifile)
-		goto delist;
+	if (root->ifile)
+		goto reuse; /* already attached checkpoint */
 
 	down_read(&nilfs->ns_segctor_sem);
 	err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp,
@@ -419,45 +409,64 @@
 		}
 		goto failed;
 	}
-	err = nilfs_read_inode_common(sbi->s_ifile, &raw_cp->cp_ifile_inode);
-	if (unlikely(err))
+
+	err = nilfs_ifile_read(sbi->s_super, root, nilfs->ns_inode_size,
+			       &raw_cp->cp_ifile_inode, &root->ifile);
+	if (err)
 		goto failed_bh;
-	atomic_set(&sbi->s_inodes_count, le64_to_cpu(raw_cp->cp_inodes_count));
-	atomic_set(&sbi->s_blocks_count, le64_to_cpu(raw_cp->cp_blocks_count));
+
+	atomic_set(&root->inodes_count, le64_to_cpu(raw_cp->cp_inodes_count));
+	atomic_set(&root->blocks_count, le64_to_cpu(raw_cp->cp_blocks_count));
 
 	nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp);
+
+ reuse:
+	*rootp = root;
 	return 0;
 
  failed_bh:
 	nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp);
  failed:
-	nilfs_mdt_destroy(sbi->s_ifile);
-	sbi->s_ifile = NULL;
-
- delist:
-	down_write(&nilfs->ns_super_sem);
-	list_del_init(&sbi->s_list);
-	up_write(&nilfs->ns_super_sem);
+	nilfs_put_root(root);
 
 	return err;
 }
 
-void nilfs_detach_checkpoint(struct nilfs_sb_info *sbi)
+static int nilfs_freeze(struct super_block *sb)
 {
+	struct nilfs_sb_info *sbi = NILFS_SB(sb);
+	struct the_nilfs *nilfs = sbi->s_nilfs;
+	int err;
+
+	if (sb->s_flags & MS_RDONLY)
+		return 0;
+
+	/* Mark super block clean */
+	down_write(&nilfs->ns_sem);
+	err = nilfs_cleanup_super(sbi);
+	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;
 
-	nilfs_mdt_destroy(sbi->s_ifile);
-	sbi->s_ifile = NULL;
-	down_write(&nilfs->ns_super_sem);
-	list_del_init(&sbi->s_list);
-	up_write(&nilfs->ns_super_sem);
+	if (sb->s_flags & MS_RDONLY)
+		return 0;
+
+	down_write(&nilfs->ns_sem);
+	nilfs_setup_super(sbi, false);
+	up_write(&nilfs->ns_sem);
+	return 0;
 }
 
 static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct super_block *sb = dentry->d_sb;
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct nilfs_root *root = NILFS_I(dentry->d_inode)->i_root;
+	struct the_nilfs *nilfs = root->nilfs;
 	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 	unsigned long long blocks;
 	unsigned long overhead;
@@ -493,7 +502,7 @@
 	buf->f_bfree = nfreeblocks;
 	buf->f_bavail = (buf->f_bfree >= nrsvblocks) ?
 		(buf->f_bfree - nrsvblocks) : 0;
-	buf->f_files = atomic_read(&sbi->s_inodes_count);
+	buf->f_files = atomic_read(&root->inodes_count);
 	buf->f_ffree = 0; /* nilfs_count_free_inodes(sb); */
 	buf->f_namelen = NILFS_NAME_LEN;
 	buf->f_fsid.val[0] = (u32)id;
@@ -506,12 +515,12 @@
 {
 	struct super_block *sb = vfs->mnt_sb;
 	struct nilfs_sb_info *sbi = NILFS_SB(sb);
+	struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root;
 
 	if (!nilfs_test_opt(sbi, BARRIER))
 		seq_puts(seq, ",nobarrier");
-	if (nilfs_test_opt(sbi, SNAPSHOT))
-		seq_printf(seq, ",cp=%llu",
-			   (unsigned long long int)sbi->s_snapshot_cno);
+	if (root->cno != NILFS_CPTREE_CURRENT_CNO)
+		seq_printf(seq, ",cp=%llu", (unsigned long long)root->cno);
 	if (nilfs_test_opt(sbi, ERRORS_PANIC))
 		seq_puts(seq, ",errors=panic");
 	if (nilfs_test_opt(sbi, ERRORS_CONT))
@@ -537,6 +546,8 @@
 	.put_super      = nilfs_put_super,
 	/* .write_super    = nilfs_write_super, */
 	.sync_fs        = nilfs_sync_fs,
+	.freeze_fs	= nilfs_freeze,
+	.unfreeze_fs	= nilfs_unfreeze,
 	/* .write_super_lockfs */
 	/* .unlockfs */
 	.statfs         = nilfs_statfs,
@@ -545,48 +556,6 @@
 	.show_options = nilfs_show_options
 };
 
-static struct inode *
-nilfs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation)
-{
-	struct inode *inode;
-
-	if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO &&
-	    ino != NILFS_SKETCH_INO)
-		return ERR_PTR(-ESTALE);
-
-	inode = nilfs_iget(sb, ino);
-	if (IS_ERR(inode))
-		return ERR_CAST(inode);
-	if (generation && inode->i_generation != generation) {
-		iput(inode);
-		return ERR_PTR(-ESTALE);
-	}
-
-	return inode;
-}
-
-static struct dentry *
-nilfs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
-		   int fh_type)
-{
-	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
-				    nilfs_nfs_get_inode);
-}
-
-static struct dentry *
-nilfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len,
-		   int fh_type)
-{
-	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
-				    nilfs_nfs_get_inode);
-}
-
-static const struct export_operations nilfs_export_ops = {
-	.fh_to_dentry = nilfs_fh_to_dentry,
-	.fh_to_parent = nilfs_fh_to_parent,
-	.get_parent = nilfs_get_parent,
-};
-
 enum {
 	Opt_err_cont, Opt_err_panic, Opt_err_ro,
 	Opt_barrier, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery,
@@ -612,7 +581,6 @@
 	struct nilfs_sb_info *sbi = NILFS_SB(sb);
 	char *p;
 	substring_t args[MAX_OPT_ARGS];
-	int option;
 
 	if (!options)
 		return 1;
@@ -650,30 +618,12 @@
 			nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT);
 			break;
 		case Opt_snapshot:
-			if (match_int(&args[0], &option) || option <= 0)
-				return 0;
 			if (is_remount) {
-				if (!nilfs_test_opt(sbi, SNAPSHOT)) {
-					printk(KERN_ERR
-					       "NILFS: cannot change regular "
-					       "mount to snapshot.\n");
-					return 0;
-				} else if (option != sbi->s_snapshot_cno) {
-					printk(KERN_ERR
-					       "NILFS: cannot remount to a "
-					       "different snapshot.\n");
-					return 0;
-				}
-				break;
-			}
-			if (!(sb->s_flags & MS_RDONLY)) {
-				printk(KERN_ERR "NILFS: cannot mount snapshot "
-				       "read/write.  A read-only option is "
-				       "required.\n");
+				printk(KERN_ERR
+				       "NILFS: \"%s\" option is invalid "
+				       "for remount.\n", p);
 				return 0;
 			}
-			sbi->s_snapshot_cno = option;
-			nilfs_set_opt(sbi, SNAPSHOT);
 			break;
 		case Opt_norecovery:
 			nilfs_set_opt(sbi, NORECOVERY);
@@ -701,7 +651,7 @@
 		NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER;
 }
 
-static int nilfs_setup_super(struct nilfs_sb_info *sbi)
+static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount)
 {
 	struct the_nilfs *nilfs = sbi->s_nilfs;
 	struct nilfs_super_block **sbp;
@@ -713,6 +663,9 @@
 	if (!sbp)
 		return -EIO;
 
+	if (!is_mount)
+		goto skip_mount_setup;
+
 	max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count);
 	mnt_count = le16_to_cpu(sbp[0]->s_mnt_count);
 
@@ -729,9 +682,11 @@
 		sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT);
 
 	sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1);
+	sbp[0]->s_mtime = cpu_to_le64(get_seconds());
+
+skip_mount_setup:
 	sbp[0]->s_state =
 		cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS);
-	sbp[0]->s_mtime = cpu_to_le64(get_seconds());
 	/* synchronize sbp[1] with sbp[0] */
 	memcpy(sbp[1], sbp[0], nilfs->ns_sbsize);
 	return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL);
@@ -798,22 +753,156 @@
 	return 0;
 }
 
+static int nilfs_get_root_dentry(struct super_block *sb,
+				 struct nilfs_root *root,
+				 struct dentry **root_dentry)
+{
+	struct inode *inode;
+	struct dentry *dentry;
+	int ret = 0;
+
+	inode = nilfs_iget(sb, root, NILFS_ROOT_INO);
+	if (IS_ERR(inode)) {
+		printk(KERN_ERR "NILFS: get root inode failed\n");
+		ret = PTR_ERR(inode);
+		goto out;
+	}
+	if (!S_ISDIR(inode->i_mode) || !inode->i_blocks || !inode->i_size) {
+		iput(inode);
+		printk(KERN_ERR "NILFS: corrupt root inode.\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (root->cno == NILFS_CPTREE_CURRENT_CNO) {
+		dentry = d_find_alias(inode);
+		if (!dentry) {
+			dentry = d_alloc_root(inode);
+			if (!dentry) {
+				iput(inode);
+				ret = -ENOMEM;
+				goto failed_dentry;
+			}
+		} else {
+			iput(inode);
+		}
+	} else {
+		dentry = d_obtain_alias(inode);
+		if (IS_ERR(dentry)) {
+			ret = PTR_ERR(dentry);
+			goto failed_dentry;
+		}
+	}
+	*root_dentry = dentry;
+ out:
+	return ret;
+
+ failed_dentry:
+	printk(KERN_ERR "NILFS: get root dentry failed\n");
+	goto out;
+}
+
+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 nilfs_root *root;
+	int ret;
+
+	down_read(&nilfs->ns_segctor_sem);
+	ret = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, cno);
+	up_read(&nilfs->ns_segctor_sem);
+	if (ret < 0) {
+		ret = (ret == -ENOENT) ? -EINVAL : ret;
+		goto out;
+	} else if (!ret) {
+		printk(KERN_ERR "NILFS: The specified checkpoint is "
+		       "not a snapshot (checkpoint number=%llu).\n",
+		       (unsigned long long)cno);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = nilfs_attach_checkpoint(NILFS_SB(s), cno, false, &root);
+	if (ret) {
+		printk(KERN_ERR "NILFS: error loading snapshot "
+		       "(checkpoint number=%llu).\n",
+	       (unsigned long long)cno);
+		goto out;
+	}
+	ret = nilfs_get_root_dentry(s, root, root_dentry);
+	nilfs_put_root(root);
+ out:
+	return ret;
+}
+
+static int nilfs_tree_was_touched(struct dentry *root_dentry)
+{
+	return atomic_read(&root_dentry->d_count) > 1;
+}
+
+/**
+ * nilfs_try_to_shrink_tree() - try to shrink dentries of a checkpoint
+ * @root_dentry: root dentry of the tree to be shrunk
+ *
+ * This function returns true if the tree was in-use.
+ */
+static int nilfs_try_to_shrink_tree(struct dentry *root_dentry)
+{
+	if (have_submounts(root_dentry))
+		return true;
+	shrink_dcache_parent(root_dentry);
+	return nilfs_tree_was_touched(root_dentry);
+}
+
+int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno)
+{
+	struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
+	struct nilfs_root *root;
+	struct inode *inode;
+	struct dentry *dentry;
+	int ret;
+
+	if (cno < 0 || cno > nilfs->ns_cno)
+		return false;
+
+	if (cno >= nilfs_last_cno(nilfs))
+		return true;	/* protect recent checkpoints */
+
+	ret = false;
+	root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno);
+	if (root) {
+		inode = nilfs_ilookup(sb, root, NILFS_ROOT_INO);
+		if (inode) {
+			dentry = d_find_alias(inode);
+			if (dentry) {
+				if (nilfs_tree_was_touched(dentry))
+					ret = nilfs_try_to_shrink_tree(dentry);
+				dput(dentry);
+			}
+			iput(inode);
+		}
+		nilfs_put_root(root);
+	}
+	return ret;
+}
+
 /**
  * nilfs_fill_super() - initialize a super block instance
  * @sb: super_block
  * @data: mount options
  * @silent: silent mode flag
- * @nilfs: the_nilfs struct
  *
  * This function is called exclusively by nilfs->ns_mount_mutex.
  * So, the recovery process is protected from other simultaneous mounts.
  */
 static int
-nilfs_fill_super(struct super_block *sb, void *data, int silent,
-		 struct the_nilfs *nilfs)
+nilfs_fill_super(struct super_block *sb, void *data, int silent)
 {
+	struct the_nilfs *nilfs;
 	struct nilfs_sb_info *sbi;
-	struct inode *root;
+	struct nilfs_root *fsroot;
+	struct backing_dev_info *bdi;
 	__u64 cno;
 	int err;
 
@@ -822,19 +911,21 @@
 		return -ENOMEM;
 
 	sb->s_fs_info = sbi;
-
-	get_nilfs(nilfs);
-	sbi->s_nilfs = nilfs;
 	sbi->s_super = sb;
-	atomic_set(&sbi->s_count, 1);
+
+	nilfs = alloc_nilfs(sb->s_bdev);
+	if (!nilfs) {
+		err = -ENOMEM;
+		goto failed_sbi;
+	}
+	sbi->s_nilfs = nilfs;
 
 	err = init_nilfs(nilfs, sbi, (char *)data);
 	if (err)
-		goto failed_sbi;
+		goto failed_nilfs;
 
 	spin_lock_init(&sbi->s_inode_lock);
 	INIT_LIST_HEAD(&sbi->s_dirty_files);
-	INIT_LIST_HEAD(&sbi->s_list);
 
 	/*
 	 * Following initialization is overlapped because
@@ -850,94 +941,59 @@
 	sb->s_export_op = &nilfs_export_ops;
 	sb->s_root = NULL;
 	sb->s_time_gran = 1;
-	sb->s_bdi = nilfs->ns_bdi;
+
+	bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
+	sb->s_bdi = bdi ? : &default_backing_dev_info;
 
 	err = load_nilfs(nilfs, sbi);
 	if (err)
-		goto failed_sbi;
+		goto failed_nilfs;
 
 	cno = nilfs_last_cno(nilfs);
-
-	if (sb->s_flags & MS_RDONLY) {
-		if (nilfs_test_opt(sbi, SNAPSHOT)) {
-			down_read(&nilfs->ns_segctor_sem);
-			err = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile,
-						       sbi->s_snapshot_cno);
-			up_read(&nilfs->ns_segctor_sem);
-			if (err < 0) {
-				if (err == -ENOENT)
-					err = -EINVAL;
-				goto failed_sbi;
-			}
-			if (!err) {
-				printk(KERN_ERR
-				       "NILFS: The specified checkpoint is "
-				       "not a snapshot "
-				       "(checkpoint number=%llu).\n",
-				       (unsigned long long)sbi->s_snapshot_cno);
-				err = -EINVAL;
-				goto failed_sbi;
-			}
-			cno = sbi->s_snapshot_cno;
-		}
-	}
-
-	err = nilfs_attach_checkpoint(sbi, cno);
+	err = nilfs_attach_checkpoint(sbi, cno, true, &fsroot);
 	if (err) {
-		printk(KERN_ERR "NILFS: error loading a checkpoint"
-		       " (checkpoint number=%llu).\n", (unsigned long long)cno);
-		goto failed_sbi;
+		printk(KERN_ERR "NILFS: error loading last checkpoint "
+		       "(checkpoint number=%llu).\n", (unsigned long long)cno);
+		goto failed_unload;
 	}
 
 	if (!(sb->s_flags & MS_RDONLY)) {
-		err = nilfs_attach_segment_constructor(sbi);
+		err = nilfs_attach_segment_constructor(sbi, fsroot);
 		if (err)
 			goto failed_checkpoint;
 	}
 
-	root = nilfs_iget(sb, NILFS_ROOT_INO);
-	if (IS_ERR(root)) {
-		printk(KERN_ERR "NILFS: get root inode failed\n");
-		err = PTR_ERR(root);
+	err = nilfs_get_root_dentry(sb, fsroot, &sb->s_root);
+	if (err)
 		goto failed_segctor;
-	}
-	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
-		iput(root);
-		printk(KERN_ERR "NILFS: corrupt root inode.\n");
-		err = -EINVAL;
-		goto failed_segctor;
-	}
-	sb->s_root = d_alloc_root(root);
-	if (!sb->s_root) {
-		iput(root);
-		printk(KERN_ERR "NILFS: get root dentry failed\n");
-		err = -ENOMEM;
-		goto failed_segctor;
-	}
+
+	nilfs_put_root(fsroot);
 
 	if (!(sb->s_flags & MS_RDONLY)) {
 		down_write(&nilfs->ns_sem);
-		nilfs_setup_super(sbi);
+		nilfs_setup_super(sbi, true);
 		up_write(&nilfs->ns_sem);
 	}
 
-	down_write(&nilfs->ns_super_sem);
-	if (!nilfs_test_opt(sbi, SNAPSHOT))
-		nilfs->ns_current = sbi;
-	up_write(&nilfs->ns_super_sem);
-
 	return 0;
 
  failed_segctor:
 	nilfs_detach_segment_constructor(sbi);
 
  failed_checkpoint:
-	nilfs_detach_checkpoint(sbi);
+	nilfs_put_root(fsroot);
+
+ failed_unload:
+	iput(nilfs->ns_sufile);
+	iput(nilfs->ns_cpfile);
+	iput(nilfs->ns_dat);
+
+ failed_nilfs:
+	destroy_nilfs(nilfs);
 
  failed_sbi:
-	put_nilfs(nilfs);
 	sb->s_fs_info = NULL;
-	nilfs_put_sbinfo(sbi);
+	kfree(sbi);
 	return err;
 }
 
@@ -947,15 +1003,10 @@
 	struct the_nilfs *nilfs = sbi->s_nilfs;
 	unsigned long old_sb_flags;
 	struct nilfs_mount_options old_opts;
-	int was_snapshot, err;
+	int err;
 
-	lock_kernel();
-
-	down_write(&nilfs->ns_super_sem);
 	old_sb_flags = sb->s_flags;
 	old_opts.mount_opt = sbi->s_mount_opt;
-	old_opts.snapshot_cno = sbi->s_snapshot_cno;
-	was_snapshot = nilfs_test_opt(sbi, SNAPSHOT);
 
 	if (!parse_options(data, sb, 1)) {
 		err = -EINVAL;
@@ -964,11 +1015,6 @@
 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL);
 
 	err = -EINVAL;
-	if (was_snapshot && !(*flags & MS_RDONLY)) {
-		printk(KERN_ERR "NILFS (device %s): cannot remount snapshot "
-		       "read/write.\n", sb->s_id);
-		goto restore_opts;
-	}
 
 	if (!nilfs_valid_fs(nilfs)) {
 		printk(KERN_WARNING "NILFS (device %s): couldn't "
@@ -993,6 +1039,7 @@
 		up_write(&nilfs->ns_sem);
 	} else {
 		__u64 features;
+		struct nilfs_root *root;
 
 		/*
 		 * Mounting a RDONLY partition read-write, so reread and
@@ -1014,25 +1061,21 @@
 
 		sb->s_flags &= ~MS_RDONLY;
 
-		err = nilfs_attach_segment_constructor(sbi);
+		root = NILFS_I(sb->s_root->d_inode)->i_root;
+		err = nilfs_attach_segment_constructor(sbi, root);
 		if (err)
 			goto restore_opts;
 
 		down_write(&nilfs->ns_sem);
-		nilfs_setup_super(sbi);
+		nilfs_setup_super(sbi, true);
 		up_write(&nilfs->ns_sem);
 	}
  out:
-	up_write(&nilfs->ns_super_sem);
-	unlock_kernel();
 	return 0;
 
  restore_opts:
 	sb->s_flags = old_sb_flags;
 	sbi->s_mount_opt = old_opts.mount_opt;
-	sbi->s_snapshot_cno = old_opts.snapshot_cno;
-	up_write(&nilfs->ns_super_sem);
-	unlock_kernel();
 	return err;
 }
 
@@ -1052,7 +1095,7 @@
 {
 	char *p, *options = data;
 	substring_t args[MAX_OPT_ARGS];
-	int option, token;
+	int token;
 	int ret = 0;
 
 	do {
@@ -1060,16 +1103,18 @@
 		if (p != NULL && *p) {
 			token = match_token(p, tokens, args);
 			if (token == Opt_snapshot) {
-				if (!(sd->flags & MS_RDONLY))
+				if (!(sd->flags & MS_RDONLY)) {
 					ret++;
-				else {
-					ret = match_int(&args[0], &option);
-					if (!ret) {
-						if (option > 0)
-							sd->cno = option;
-						else
-							ret++;
-					}
+				} else {
+					sd->cno = simple_strtoull(args[0].from,
+								  NULL, 0);
+					/*
+					 * No need to see the end pointer;
+					 * match_token() has done syntax
+					 * checking.
+					 */
+					if (sd->cno == 0)
+						ret++;
 				}
 			}
 			if (ret)
@@ -1086,18 +1131,14 @@
 
 static int nilfs_set_bdev_super(struct super_block *s, void *data)
 {
-	struct nilfs_super_data *sd = data;
-
-	s->s_bdev = sd->bdev;
+	s->s_bdev = data;
 	s->s_dev = s->s_bdev->bd_dev;
 	return 0;
 }
 
 static int nilfs_test_bdev_super(struct super_block *s, void *data)
 {
-	struct nilfs_super_data *sd = data;
-
-	return sd->sbi && s->s_fs_info == (void *)sd->sbi;
+	return (void *)s->s_bdev == data;
 }
 
 static int
@@ -1107,8 +1148,8 @@
 	struct nilfs_super_data sd;
 	struct super_block *s;
 	fmode_t mode = FMODE_READ;
-	struct the_nilfs *nilfs;
-	int err, need_to_close = 1;
+	struct dentry *root_dentry;
+	int err, s_new = false;
 
 	if (!(flags & MS_RDONLY))
 		mode |= FMODE_WRITE;
@@ -1117,12 +1158,6 @@
 	if (IS_ERR(sd.bdev))
 		return PTR_ERR(sd.bdev);
 
-	/*
-	 * To get mount instance using sget() vfs-routine, NILFS needs
-	 * much more information than normal filesystems to identify mount
-	 * instance.  For snapshot mounts, not only a mount type (ro-mount
-	 * or rw-mount) but also a checkpoint number is required.
-	 */
 	sd.cno = 0;
 	sd.flags = flags;
 	if (nilfs_identify((char *)data, &sd)) {
@@ -1130,94 +1165,86 @@
 		goto failed;
 	}
 
-	nilfs = find_or_create_nilfs(sd.bdev);
-	if (!nilfs) {
-		err = -ENOMEM;
+	/*
+	 * once the super is inserted into the list by sget, s_umount
+	 * will protect the lockfs code from trying to start a snapshot
+	 * while we are mounting
+	 */
+	mutex_lock(&sd.bdev->bd_fsfreeze_mutex);
+	if (sd.bdev->bd_fsfreeze_count > 0) {
+		mutex_unlock(&sd.bdev->bd_fsfreeze_mutex);
+		err = -EBUSY;
 		goto failed;
 	}
-
-	mutex_lock(&nilfs->ns_mount_mutex);
-
-	if (!sd.cno) {
-		/*
-		 * Check if an exclusive mount exists or not.
-		 * Snapshot mounts coexist with a current mount
-		 * (i.e. rw-mount or ro-mount), whereas rw-mount and
-		 * ro-mount are mutually exclusive.
-		 */
-		down_read(&nilfs->ns_super_sem);
-		if (nilfs->ns_current &&
-		    ((nilfs->ns_current->s_super->s_flags ^ flags)
-		     & MS_RDONLY)) {
-			up_read(&nilfs->ns_super_sem);
-			err = -EBUSY;
-			goto failed_unlock;
-		}
-		up_read(&nilfs->ns_super_sem);
-	}
-
-	/*
-	 * Find existing nilfs_sb_info struct
-	 */
-	sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno);
-
-	/*
-	 * Get super block instance holding the nilfs_sb_info struct.
-	 * A new instance is allocated if no existing mount is present or
-	 * existing instance has been unmounted.
-	 */
-	s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd);
-	if (sd.sbi)
-		nilfs_put_sbinfo(sd.sbi);
-
+	s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev);
+	mutex_unlock(&sd.bdev->bd_fsfreeze_mutex);
 	if (IS_ERR(s)) {
 		err = PTR_ERR(s);
-		goto failed_unlock;
+		goto failed;
 	}
 
 	if (!s->s_root) {
 		char b[BDEVNAME_SIZE];
 
+		s_new = true;
+
 		/* New superblock instance created */
 		s->s_flags = flags;
 		s->s_mode = mode;
 		strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id));
 		sb_set_blocksize(s, block_size(sd.bdev));
 
-		err = nilfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0,
-				       nilfs);
+		err = nilfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
 		if (err)
-			goto cancel_new;
+			goto failed_super;
 
 		s->s_flags |= MS_ACTIVE;
-		need_to_close = 0;
+	} else if (!sd.cno) {
+		int busy = false;
+
+		if (nilfs_tree_was_touched(s->s_root)) {
+			busy = nilfs_try_to_shrink_tree(s->s_root);
+			if (busy && (flags ^ s->s_flags) & MS_RDONLY) {
+				printk(KERN_ERR "NILFS: the device already "
+				       "has a %s mount.\n",
+				       (s->s_flags & MS_RDONLY) ?
+				       "read-only" : "read/write");
+				err = -EBUSY;
+				goto failed_super;
+			}
+		}
+		if (!busy) {
+			/*
+			 * Try remount to setup mount states if the current
+			 * tree is not mounted and only snapshots use this sb.
+			 */
+			err = nilfs_remount(s, &flags, data);
+			if (err)
+				goto failed_super;
+		}
 	}
 
-	mutex_unlock(&nilfs->ns_mount_mutex);
-	put_nilfs(nilfs);
-	if (need_to_close)
+	if (sd.cno) {
+		err = nilfs_attach_snapshot(s, sd.cno, &root_dentry);
+		if (err)
+			goto failed_super;
+	} else {
+		root_dentry = dget(s->s_root);
+	}
+
+	if (!s_new)
 		close_bdev_exclusive(sd.bdev, mode);
-	simple_set_mnt(mnt, s);
+
+	mnt->mnt_sb = s;
+	mnt->mnt_root = root_dentry;
 	return 0;
 
- failed_unlock:
-	mutex_unlock(&nilfs->ns_mount_mutex);
-	put_nilfs(nilfs);
- failed:
-	close_bdev_exclusive(sd.bdev, mode);
-
-	return err;
-
- cancel_new:
-	/* Abandoning the newly allocated superblock */
-	mutex_unlock(&nilfs->ns_mount_mutex);
-	put_nilfs(nilfs);
+ failed_super:
 	deactivate_locked_super(s);
-	/*
-	 * deactivate_locked_super() invokes close_bdev_exclusive().
-	 * We must finish all post-cleaning before this call;
-	 * put_nilfs() needs the block device.
-	 */
+
+ failed:
+	if (!s_new)
+		close_bdev_exclusive(sd.bdev, mode);
 	return err;
 }
 
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index ba7c10c..0254be2 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -35,9 +35,6 @@
 #include "segbuf.h"
 
 
-static LIST_HEAD(nilfs_objects);
-static DEFINE_SPINLOCK(nilfs_lock);
-
 static int nilfs_valid_sb(struct nilfs_super_block *sbp);
 
 void nilfs_set_last_segment(struct the_nilfs *nilfs,
@@ -61,16 +58,13 @@
 }
 
 /**
- * alloc_nilfs - allocate the_nilfs structure
+ * alloc_nilfs - allocate a nilfs object
  * @bdev: block device to which the_nilfs is related
  *
- * alloc_nilfs() allocates memory for the_nilfs and
- * initializes its reference count and locks.
- *
  * Return Value: On success, pointer to the_nilfs is returned.
  * On error, NULL is returned.
  */
-static struct the_nilfs *alloc_nilfs(struct block_device *bdev)
+struct the_nilfs *alloc_nilfs(struct block_device *bdev)
 {
 	struct the_nilfs *nilfs;
 
@@ -79,103 +73,38 @@
 		return NULL;
 
 	nilfs->ns_bdev = bdev;
-	atomic_set(&nilfs->ns_count, 1);
 	atomic_set(&nilfs->ns_ndirtyblks, 0);
 	init_rwsem(&nilfs->ns_sem);
-	init_rwsem(&nilfs->ns_super_sem);
-	mutex_init(&nilfs->ns_mount_mutex);
-	init_rwsem(&nilfs->ns_writer_sem);
-	INIT_LIST_HEAD(&nilfs->ns_list);
-	INIT_LIST_HEAD(&nilfs->ns_supers);
+	INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
 	spin_lock_init(&nilfs->ns_last_segment_lock);
-	nilfs->ns_gc_inodes_h = NULL;
+	nilfs->ns_cptree = RB_ROOT;
+	spin_lock_init(&nilfs->ns_cptree_lock);
 	init_rwsem(&nilfs->ns_segctor_sem);
 
 	return nilfs;
 }
 
 /**
- * find_or_create_nilfs - find or create nilfs object
- * @bdev: block device to which the_nilfs is related
- *
- * find_nilfs() looks up an existent nilfs object created on the
- * device and gets the reference count of the object.  If no nilfs object
- * is found on the device, a new nilfs object is allocated.
- *
- * Return Value: On success, pointer to the nilfs object is returned.
- * On error, NULL is returned.
+ * destroy_nilfs - destroy nilfs object
+ * @nilfs: nilfs object to be released
  */
-struct the_nilfs *find_or_create_nilfs(struct block_device *bdev)
+void destroy_nilfs(struct the_nilfs *nilfs)
 {
-	struct the_nilfs *nilfs, *new = NULL;
-
- retry:
-	spin_lock(&nilfs_lock);
-	list_for_each_entry(nilfs, &nilfs_objects, ns_list) {
-		if (nilfs->ns_bdev == bdev) {
-			get_nilfs(nilfs);
-			spin_unlock(&nilfs_lock);
-			if (new)
-				put_nilfs(new);
-			return nilfs; /* existing object */
-		}
-	}
-	if (new) {
-		list_add_tail(&new->ns_list, &nilfs_objects);
-		spin_unlock(&nilfs_lock);
-		return new; /* new object */
-	}
-	spin_unlock(&nilfs_lock);
-
-	new = alloc_nilfs(bdev);
-	if (new)
-		goto retry;
-	return NULL; /* insufficient memory */
-}
-
-/**
- * put_nilfs - release a reference to the_nilfs
- * @nilfs: the_nilfs structure to be released
- *
- * put_nilfs() decrements a reference counter of the_nilfs.
- * If the reference count reaches zero, the_nilfs is freed.
- */
-void put_nilfs(struct the_nilfs *nilfs)
-{
-	spin_lock(&nilfs_lock);
-	if (!atomic_dec_and_test(&nilfs->ns_count)) {
-		spin_unlock(&nilfs_lock);
-		return;
-	}
-	list_del_init(&nilfs->ns_list);
-	spin_unlock(&nilfs_lock);
-
-	/*
-	 * Increment of ns_count never occurs below because the caller
-	 * of get_nilfs() holds at least one reference to the_nilfs.
-	 * Thus its exclusion control is not required here.
-	 */
-
 	might_sleep();
-	if (nilfs_loaded(nilfs)) {
-		nilfs_mdt_destroy(nilfs->ns_sufile);
-		nilfs_mdt_destroy(nilfs->ns_cpfile);
-		nilfs_mdt_destroy(nilfs->ns_dat);
-		nilfs_mdt_destroy(nilfs->ns_gc_dat);
-	}
 	if (nilfs_init(nilfs)) {
-		nilfs_destroy_gccache(nilfs);
 		brelse(nilfs->ns_sbh[0]);
 		brelse(nilfs->ns_sbh[1]);
 	}
 	kfree(nilfs);
 }
 
-static int nilfs_load_super_root(struct the_nilfs *nilfs, sector_t sr_block)
+static int nilfs_load_super_root(struct the_nilfs *nilfs,
+				 struct super_block *sb, sector_t sr_block)
 {
 	struct buffer_head *bh_sr;
 	struct nilfs_super_root *raw_sr;
 	struct nilfs_super_block **sbp = nilfs->ns_sbp;
+	struct nilfs_inode *rawi;
 	unsigned dat_entry_size, segment_usage_size, checkpoint_size;
 	unsigned inode_size;
 	int err;
@@ -192,40 +121,22 @@
 
 	inode_size = nilfs->ns_inode_size;
 
-	err = -ENOMEM;
-	nilfs->ns_dat = nilfs_dat_new(nilfs, dat_entry_size);
-	if (unlikely(!nilfs->ns_dat))
+	rawi = (void *)bh_sr->b_data + NILFS_SR_DAT_OFFSET(inode_size);
+	err = nilfs_dat_read(sb, dat_entry_size, rawi, &nilfs->ns_dat);
+	if (err)
 		goto failed;
 
-	nilfs->ns_gc_dat = nilfs_dat_new(nilfs, dat_entry_size);
-	if (unlikely(!nilfs->ns_gc_dat))
+	rawi = (void *)bh_sr->b_data + NILFS_SR_CPFILE_OFFSET(inode_size);
+	err = nilfs_cpfile_read(sb, checkpoint_size, rawi, &nilfs->ns_cpfile);
+	if (err)
 		goto failed_dat;
 
-	nilfs->ns_cpfile = nilfs_cpfile_new(nilfs, checkpoint_size);
-	if (unlikely(!nilfs->ns_cpfile))
-		goto failed_gc_dat;
-
-	nilfs->ns_sufile = nilfs_sufile_new(nilfs, segment_usage_size);
-	if (unlikely(!nilfs->ns_sufile))
+	rawi = (void *)bh_sr->b_data + NILFS_SR_SUFILE_OFFSET(inode_size);
+	err = nilfs_sufile_read(sb, segment_usage_size, rawi,
+				&nilfs->ns_sufile);
+	if (err)
 		goto failed_cpfile;
 
-	nilfs_mdt_set_shadow(nilfs->ns_dat, nilfs->ns_gc_dat);
-
-	err = nilfs_dat_read(nilfs->ns_dat, (void *)bh_sr->b_data +
-			     NILFS_SR_DAT_OFFSET(inode_size));
-	if (unlikely(err))
-		goto failed_sufile;
-
-	err = nilfs_cpfile_read(nilfs->ns_cpfile, (void *)bh_sr->b_data +
-				NILFS_SR_CPFILE_OFFSET(inode_size));
-	if (unlikely(err))
-		goto failed_sufile;
-
-	err = nilfs_sufile_read(nilfs->ns_sufile, (void *)bh_sr->b_data +
-				NILFS_SR_SUFILE_OFFSET(inode_size));
-	if (unlikely(err))
-		goto failed_sufile;
-
 	raw_sr = (struct nilfs_super_root *)bh_sr->b_data;
 	nilfs->ns_nongc_ctime = le64_to_cpu(raw_sr->sr_nongc_ctime);
 
@@ -233,17 +144,11 @@
 	brelse(bh_sr);
 	return err;
 
- failed_sufile:
-	nilfs_mdt_destroy(nilfs->ns_sufile);
-
  failed_cpfile:
-	nilfs_mdt_destroy(nilfs->ns_cpfile);
-
- failed_gc_dat:
-	nilfs_mdt_destroy(nilfs->ns_gc_dat);
+	iput(nilfs->ns_cpfile);
 
  failed_dat:
-	nilfs_mdt_destroy(nilfs->ns_dat);
+	iput(nilfs->ns_dat);
 	goto failed;
 }
 
@@ -306,15 +211,6 @@
 	int valid_fs = nilfs_valid_fs(nilfs);
 	int err;
 
-	if (nilfs_loaded(nilfs)) {
-		if (valid_fs ||
-		    ((s_flags & MS_RDONLY) && nilfs_test_opt(sbi, NORECOVERY)))
-			return 0;
-		printk(KERN_ERR "NILFS: the filesystem is in an incomplete "
-		       "recovery state.\n");
-		return -EINVAL;
-	}
-
 	if (!valid_fs) {
 		printk(KERN_WARNING "NILFS warning: mounting unchecked fs\n");
 		if (s_flags & MS_RDONLY) {
@@ -375,7 +271,7 @@
 			goto scan_error;
 	}
 
-	err = nilfs_load_super_root(nilfs, ri.ri_super_root);
+	err = nilfs_load_super_root(nilfs, sbi->s_super, ri.ri_super_root);
 	if (unlikely(err)) {
 		printk(KERN_ERR "NILFS: error loading super root.\n");
 		goto failed;
@@ -443,10 +339,9 @@
 	goto failed;
 
  failed_unload:
-	nilfs_mdt_destroy(nilfs->ns_cpfile);
-	nilfs_mdt_destroy(nilfs->ns_sufile);
-	nilfs_mdt_destroy(nilfs->ns_dat);
-	nilfs_mdt_destroy(nilfs->ns_gc_dat);
+	iput(nilfs->ns_cpfile);
+	iput(nilfs->ns_sufile);
+	iput(nilfs->ns_dat);
 
  failed:
 	nilfs_clear_recovery_info(&ri);
@@ -468,8 +363,8 @@
 static int nilfs_store_disk_layout(struct the_nilfs *nilfs,
 				   struct nilfs_super_block *sbp)
 {
-	if (le32_to_cpu(sbp->s_rev_level) != NILFS_CURRENT_REV) {
-		printk(KERN_ERR "NILFS: revision mismatch "
+	if (le32_to_cpu(sbp->s_rev_level) < NILFS_MIN_SUPP_REV) {
+		printk(KERN_ERR "NILFS: unsupported revision "
 		       "(superblock rev.=%d.%d, current rev.=%d.%d). "
 		       "Please check the version of mkfs.nilfs.\n",
 		       le32_to_cpu(sbp->s_rev_level),
@@ -631,12 +526,7 @@
  *
  * init_nilfs() performs common initialization per block device (e.g.
  * reading the super block, getting disk layout information, initializing
- * shared fields in the_nilfs). It takes on some portion of the jobs
- * typically done by a fill_super() routine. This division arises from
- * the nature that multiple NILFS instances may be simultaneously
- * mounted on a device.
- * For multiple mounts on the same device, only the first mount
- * invokes these tasks.
+ * shared fields in the_nilfs).
  *
  * Return Value: On success, 0 is returned. On error, a negative error
  * code is returned.
@@ -645,32 +535,10 @@
 {
 	struct super_block *sb = sbi->s_super;
 	struct nilfs_super_block *sbp;
-	struct backing_dev_info *bdi;
 	int blocksize;
 	int err;
 
 	down_write(&nilfs->ns_sem);
-	if (nilfs_init(nilfs)) {
-		/* Load values from existing the_nilfs */
-		sbp = nilfs->ns_sbp[0];
-		err = nilfs_store_magic_and_option(sb, sbp, data);
-		if (err)
-			goto out;
-
-		err = nilfs_check_feature_compatibility(sb, sbp);
-		if (err)
-			goto out;
-
-		blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size);
-		if (sb->s_blocksize != blocksize &&
-		    !sb_set_blocksize(sb, blocksize)) {
-			printk(KERN_ERR "NILFS: blocksize %d unfit to device\n",
-			       blocksize);
-			err = -EINVAL;
-		}
-		sb->s_maxbytes = nilfs_max_size(sb->s_blocksize_bits);
-		goto out;
-	}
 
 	blocksize = sb_min_blocksize(sb, NILFS_MIN_BLOCK_SIZE);
 	if (!blocksize) {
@@ -729,18 +597,10 @@
 
 	nilfs->ns_mount_state = le16_to_cpu(sbp->s_state);
 
-	bdi = nilfs->ns_bdev->bd_inode->i_mapping->backing_dev_info;
-	nilfs->ns_bdi = bdi ? : &default_backing_dev_info;
-
 	err = nilfs_store_log_cursor(nilfs, sbp);
 	if (err)
 		goto failed_sbh;
 
-	/* Initialize gcinode cache */
-	err = nilfs_init_gccache(nilfs);
-	if (err)
-		goto failed_sbh;
-
 	set_nilfs_init(nilfs);
 	err = 0;
  out:
@@ -775,9 +635,7 @@
 			ret = blkdev_issue_discard(nilfs->ns_bdev,
 						   start * sects_per_block,
 						   nblocks * sects_per_block,
-						   GFP_NOFS,
-						   BLKDEV_IFL_WAIT |
-						   BLKDEV_IFL_BARRIER);
+						   GFP_NOFS, 0);
 			if (ret < 0)
 				return ret;
 			nblocks = 0;
@@ -787,8 +645,7 @@
 		ret = blkdev_issue_discard(nilfs->ns_bdev,
 					   start * sects_per_block,
 					   nblocks * sects_per_block,
-					   GFP_NOFS,
-					  BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+					   GFP_NOFS, 0);
 	return ret;
 }
 
@@ -815,79 +672,92 @@
 	return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs;
 }
 
-/**
- * nilfs_find_sbinfo - find existing nilfs_sb_info structure
- * @nilfs: nilfs object
- * @rw_mount: mount type (non-zero value for read/write mount)
- * @cno: checkpoint number (zero for read-only mount)
- *
- * nilfs_find_sbinfo() returns the nilfs_sb_info structure which
- * @rw_mount and @cno (in case of snapshots) matched.  If no instance
- * was found, NULL is returned.  Although the super block instance can
- * be unmounted after this function returns, the nilfs_sb_info struct
- * is kept on memory until nilfs_put_sbinfo() is called.
- */
-struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *nilfs,
-					int rw_mount, __u64 cno)
+struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno)
 {
-	struct nilfs_sb_info *sbi;
+	struct rb_node *n;
+	struct nilfs_root *root;
 
-	down_read(&nilfs->ns_super_sem);
-	/*
-	 * The SNAPSHOT flag and sb->s_flags are supposed to be
-	 * protected with nilfs->ns_super_sem.
-	 */
-	sbi = nilfs->ns_current;
-	if (rw_mount) {
-		if (sbi && !(sbi->s_super->s_flags & MS_RDONLY))
-			goto found; /* read/write mount */
-		else
-			goto out;
-	} else if (cno == 0) {
-		if (sbi && (sbi->s_super->s_flags & MS_RDONLY))
-			goto found; /* read-only mount */
-		else
-			goto out;
-	}
+	spin_lock(&nilfs->ns_cptree_lock);
+	n = nilfs->ns_cptree.rb_node;
+	while (n) {
+		root = rb_entry(n, struct nilfs_root, rb_node);
 
-	list_for_each_entry(sbi, &nilfs->ns_supers, s_list) {
-		if (nilfs_test_opt(sbi, SNAPSHOT) &&
-		    sbi->s_snapshot_cno == cno)
-			goto found; /* snapshot mount */
-	}
- out:
-	up_read(&nilfs->ns_super_sem);
-	return NULL;
-
- found:
-	atomic_inc(&sbi->s_count);
-	up_read(&nilfs->ns_super_sem);
-	return sbi;
-}
-
-int nilfs_checkpoint_is_mounted(struct the_nilfs *nilfs, __u64 cno,
-				int snapshot_mount)
-{
-	struct nilfs_sb_info *sbi;
-	int ret = 0;
-
-	down_read(&nilfs->ns_super_sem);
-	if (cno == 0 || cno > nilfs->ns_cno)
-		goto out_unlock;
-
-	list_for_each_entry(sbi, &nilfs->ns_supers, s_list) {
-		if (sbi->s_snapshot_cno == cno &&
-		    (!snapshot_mount || nilfs_test_opt(sbi, SNAPSHOT))) {
-					/* exclude read-only mounts */
-			ret++;
-			break;
+		if (cno < root->cno) {
+			n = n->rb_left;
+		} else if (cno > root->cno) {
+			n = n->rb_right;
+		} else {
+			atomic_inc(&root->count);
+			spin_unlock(&nilfs->ns_cptree_lock);
+			return root;
 		}
 	}
-	/* for protecting recent checkpoints */
-	if (cno >= nilfs_last_cno(nilfs))
-		ret++;
+	spin_unlock(&nilfs->ns_cptree_lock);
 
- out_unlock:
-	up_read(&nilfs->ns_super_sem);
-	return ret;
+	return NULL;
+}
+
+struct nilfs_root *
+nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno)
+{
+	struct rb_node **p, *parent;
+	struct nilfs_root *root, *new;
+
+	root = nilfs_lookup_root(nilfs, cno);
+	if (root)
+		return root;
+
+	new = kmalloc(sizeof(*root), GFP_KERNEL);
+	if (!new)
+		return NULL;
+
+	spin_lock(&nilfs->ns_cptree_lock);
+
+	p = &nilfs->ns_cptree.rb_node;
+	parent = NULL;
+
+	while (*p) {
+		parent = *p;
+		root = rb_entry(parent, struct nilfs_root, rb_node);
+
+		if (cno < root->cno) {
+			p = &(*p)->rb_left;
+		} else if (cno > root->cno) {
+			p = &(*p)->rb_right;
+		} else {
+			atomic_inc(&root->count);
+			spin_unlock(&nilfs->ns_cptree_lock);
+			kfree(new);
+			return root;
+		}
+	}
+
+	new->cno = cno;
+	new->ifile = NULL;
+	new->nilfs = nilfs;
+	atomic_set(&new->count, 1);
+	atomic_set(&new->inodes_count, 0);
+	atomic_set(&new->blocks_count, 0);
+
+	rb_link_node(&new->rb_node, parent, p);
+	rb_insert_color(&new->rb_node, &nilfs->ns_cptree);
+
+	spin_unlock(&nilfs->ns_cptree_lock);
+
+	return new;
+}
+
+void nilfs_put_root(struct nilfs_root *root)
+{
+	if (atomic_dec_and_test(&root->count)) {
+		struct the_nilfs *nilfs = root->nilfs;
+
+		spin_lock(&nilfs->ns_cptree_lock);
+		rb_erase(&root->rb_node, &nilfs->ns_cptree);
+		spin_unlock(&nilfs->ns_cptree_lock);
+		if (root->ifile)
+			iput(root->ifile);
+
+		kfree(root);
+	}
 }
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index f785a7b..69226e1 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -26,6 +26,7 @@
 
 #include <linux/types.h>
 #include <linux/buffer_head.h>
+#include <linux/rbtree.h>
 #include <linux/fs.h>
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
@@ -45,22 +46,13 @@
 /**
  * struct the_nilfs - struct to supervise multiple nilfs mount points
  * @ns_flags: flags
- * @ns_count: reference count
- * @ns_list: list head for nilfs_list
  * @ns_bdev: block device
- * @ns_bdi: backing dev info
- * @ns_writer: back pointer to writable nilfs_sb_info
  * @ns_sem: semaphore for shared states
- * @ns_super_sem: semaphore for global operations across super block instances
- * @ns_mount_mutex: mutex protecting mount process of nilfs
- * @ns_writer_sem: semaphore protecting ns_writer attach/detach
- * @ns_current: back pointer to current mount
  * @ns_sbh: buffer heads of on-disk super blocks
  * @ns_sbp: pointers to super block data
  * @ns_sbwtime: previous write time of super block
  * @ns_sbwcount: write count of super block
  * @ns_sbsize: size of valid data in super block
- * @ns_supers: list of nilfs super block structs
  * @ns_seg_seq: segment sequence counter
  * @ns_segnum: index number of the latest full segment.
  * @ns_nextnum: index number of the full segment index to be used next
@@ -79,9 +71,9 @@
  * @ns_dat: DAT file inode
  * @ns_cpfile: checkpoint file inode
  * @ns_sufile: segusage file inode
- * @ns_gc_dat: shadow inode of the DAT file inode for GC
+ * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root)
+ * @ns_cptree_lock: lock protecting @ns_cptree
  * @ns_gc_inodes: dummy inodes to keep live blocks
- * @ns_gc_inodes_h: hash list to keep dummy inode holding live blocks
  * @ns_blocksize_bits: bit length of block size
  * @ns_blocksize: block size
  * @ns_nsegments: number of segments in filesystem
@@ -95,22 +87,9 @@
  */
 struct the_nilfs {
 	unsigned long		ns_flags;
-	atomic_t		ns_count;
-	struct list_head	ns_list;
 
 	struct block_device    *ns_bdev;
-	struct backing_dev_info *ns_bdi;
-	struct nilfs_sb_info   *ns_writer;
 	struct rw_semaphore	ns_sem;
-	struct rw_semaphore	ns_super_sem;
-	struct mutex		ns_mount_mutex;
-	struct rw_semaphore	ns_writer_sem;
-
-	/*
-	 * components protected by ns_super_sem
-	 */
-	struct nilfs_sb_info   *ns_current;
-	struct list_head	ns_supers;
 
 	/*
 	 * used for
@@ -163,11 +142,13 @@
 	struct inode	       *ns_dat;
 	struct inode	       *ns_cpfile;
 	struct inode	       *ns_sufile;
-	struct inode	       *ns_gc_dat;
 
-	/* GC inode list and hash table head */
+	/* Checkpoint tree */
+	struct rb_root		ns_cptree;
+	spinlock_t		ns_cptree_lock;
+
+	/* GC inode list */
 	struct list_head	ns_gc_inodes;
-	struct hlist_head      *ns_gc_inodes_h;
 
 	/* Disk layout information (static) */
 	unsigned int		ns_blocksize_bits;
@@ -182,9 +163,6 @@
 	u32			ns_crc_seed;
 };
 
-#define NILFS_GCINODE_HASH_BITS		8
-#define NILFS_GCINODE_HASH_SIZE		(1<<NILFS_GCINODE_HASH_BITS)
-
 #define THE_NILFS_FNS(bit, name)					\
 static inline void set_nilfs_##name(struct the_nilfs *nilfs)		\
 {									\
@@ -205,6 +183,32 @@
 THE_NILFS_FNS(GC_RUNNING, gc_running)
 THE_NILFS_FNS(SB_DIRTY, sb_dirty)
 
+/**
+ * struct nilfs_root - nilfs root object
+ * @cno: checkpoint number
+ * @rb_node: red-black tree node
+ * @count: refcount of this structure
+ * @nilfs: nilfs object
+ * @ifile: inode file
+ * @root: root inode
+ * @inodes_count: number of inodes
+ * @blocks_count: number of blocks (Reserved)
+ */
+struct nilfs_root {
+	__u64 cno;
+	struct rb_node rb_node;
+
+	atomic_t count;
+	struct the_nilfs *nilfs;
+	struct inode *ifile;
+
+	atomic_t inodes_count;
+	atomic_t blocks_count;
+};
+
+/* Special checkpoint number */
+#define NILFS_CPTREE_CURRENT_CNO	0
+
 /* Minimum interval of periodical update of superblocks (in seconds) */
 #define NILFS_SB_FREQ		10
 
@@ -221,46 +225,25 @@
 }
 
 void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64);
-struct the_nilfs *find_or_create_nilfs(struct block_device *);
-void put_nilfs(struct the_nilfs *);
+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 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_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
 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 *);
 
 
-static inline void get_nilfs(struct the_nilfs *nilfs)
+static inline void nilfs_get_root(struct nilfs_root *root)
 {
-	/* Caller must have at least one reference of the_nilfs. */
-	atomic_inc(&nilfs->ns_count);
-}
-
-static inline void
-nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
-{
-	down_write(&nilfs->ns_writer_sem);
-	nilfs->ns_writer = sbi;
-	up_write(&nilfs->ns_writer_sem);
-}
-
-static inline void
-nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
-{
-	down_write(&nilfs->ns_writer_sem);
-	if (sbi == nilfs->ns_writer)
-		nilfs->ns_writer = NULL;
-	up_write(&nilfs->ns_writer_sem);
-}
-
-static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi)
-{
-	if (atomic_dec_and_test(&sbi->s_count))
-		kfree(sbi);
+	atomic_inc(&root->count);
 }
 
 static inline int nilfs_valid_fs(struct the_nilfs *nilfs)
diff --git a/fs/no-block.c b/fs/no-block.c
index d269a93..6e40e42 100644
--- a/fs/no-block.c
+++ b/fs/no-block.c
@@ -19,4 +19,5 @@
 
 const struct file_operations def_blk_fops = {
 	.open		= no_blkdev_open,
+	.llseek		= noop_llseek,
 };
diff --git a/fs/notify/Kconfig b/fs/notify/Kconfig
index 22c629e..b388443 100644
--- a/fs/notify/Kconfig
+++ b/fs/notify/Kconfig
@@ -3,4 +3,4 @@
 
 source "fs/notify/dnotify/Kconfig"
 source "fs/notify/inotify/Kconfig"
-source "fs/notify/fanotify/Kconfig"
+#source "fs/notify/fanotify/Kconfig"
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 5ed8e58..bbcb98e 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -433,6 +433,7 @@
 	.release	= fanotify_release,
 	.unlocked_ioctl	= fanotify_ioctl,
 	.compat_ioctl	= fanotify_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static void fanotify_free_mark(struct fsnotify_mark *fsn_mark)
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index bf7f6d7..24edc11 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -344,6 +344,7 @@
 	.release	= inotify_release,
 	.unlocked_ioctl	= inotify_ioctl,
 	.compat_ioctl	= inotify_ioctl,
+	.llseek		= noop_llseek,
 };
 
 
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 5128061..19c5180 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -30,7 +30,6 @@
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/moduleparam.h>
-#include <linux/smp_lock.h>
 #include <linux/bitmap.h>
 
 #include "sysctl.h"
@@ -445,7 +444,6 @@
 
 	ntfs_debug("Entering with remount options string: %s", opt);
 
-	lock_kernel();
 #ifndef NTFS_RW
 	/* For read-only compiled driver, enforce read-only flag. */
 	*flags |= MS_RDONLY;
@@ -469,18 +467,15 @@
 		if (NVolErrors(vol)) {
 			ntfs_error(sb, "Volume has errors and is read-only%s",
 					es);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (vol->vol_flags & VOLUME_IS_DIRTY) {
 			ntfs_error(sb, "Volume is dirty and read-only%s", es);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (vol->vol_flags & VOLUME_MODIFIED_BY_CHKDSK) {
 			ntfs_error(sb, "Volume has been modified by chkdsk "
 					"and is read-only%s", es);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (vol->vol_flags & VOLUME_MUST_MOUNT_RO_MASK) {
@@ -488,13 +483,11 @@
 					"(0x%x) and is read-only%s",
 					(unsigned)le16_to_cpu(vol->vol_flags),
 					es);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY)) {
 			ntfs_error(sb, "Failed to set dirty bit in volume "
 					"information flags%s", es);
-			unlock_kernel();
 			return -EROFS;
 		}
 #if 0
@@ -514,21 +507,18 @@
 			ntfs_error(sb, "Failed to empty journal $LogFile%s",
 					es);
 			NVolSetErrors(vol);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (!ntfs_mark_quotas_out_of_date(vol)) {
 			ntfs_error(sb, "Failed to mark quotas out of date%s",
 					es);
 			NVolSetErrors(vol);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (!ntfs_stamp_usnjrnl(vol)) {
 			ntfs_error(sb, "Failed to stamp transation log "
 					"($UsnJrnl)%s", es);
 			NVolSetErrors(vol);
-			unlock_kernel();
 			return -EROFS;
 		}
 	} else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
@@ -544,11 +534,9 @@
 
 	// TODO: Deal with *flags.
 
-	if (!parse_options(vol, opt)) {
-		unlock_kernel();
+	if (!parse_options(vol, opt))
 		return -EINVAL;
-	}
-	unlock_kernel();
+
 	ntfs_debug("Done.");
 	return 0;
 }
@@ -2261,8 +2249,6 @@
 
 	ntfs_debug("Entering.");
 
-	lock_kernel();
-
 #ifdef NTFS_RW
 	/*
 	 * Commit all inodes while they are still open in case some of them
@@ -2433,8 +2419,6 @@
 
 	sb->s_fs_info = NULL;
 	kfree(vol);
-
-	unlock_kernel();
 }
 
 /**
@@ -2772,8 +2756,6 @@
 	init_rwsem(&vol->mftbmp_lock);
 	init_rwsem(&vol->lcnbmp_lock);
 
-	unlock_kernel();
-
 	/* By default, enable sparse support. */
 	NVolSetSparseEnabled(vol);
 
@@ -2940,7 +2922,6 @@
 		}
 		mutex_unlock(&ntfs_lock);
 		sb->s_export_op = &ntfs_export_ops;
-		lock_kernel();
 		lockdep_on();
 		return 0;
 	}
@@ -3057,7 +3038,6 @@
 	}
 	/* Errors at this stage are irrelevant. */
 err_out_now:
-	lock_kernel();
 	sb->s_fs_info = NULL;
 	kfree(vol);
 	ntfs_debug("Failed, returning -EINVAL.");
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index a76e0aa..3919150 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -209,7 +209,10 @@
 	}
 
 	inode->i_mode = new_mode;
+	inode->i_ctime = CURRENT_TIME;
 	di->i_mode = cpu_to_le16(inode->i_mode);
+	di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
+	di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
 
 	ocfs2_journal_dirty(handle, di_bh);
 
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 0de69c9..5cfeee1 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -883,8 +883,8 @@
 	 * out in so that future reads from that region will get
 	 * zero's.
 	 */
-	struct page			*w_pages[OCFS2_MAX_CTXT_PAGES];
 	unsigned int			w_num_pages;
+	struct page			*w_pages[OCFS2_MAX_CTXT_PAGES];
 	struct page			*w_target_page;
 
 	/*
@@ -1642,7 +1642,8 @@
 	return ret;
 }
 
-int ocfs2_write_begin_nolock(struct address_space *mapping,
+int ocfs2_write_begin_nolock(struct file *filp,
+			     struct address_space *mapping,
 			     loff_t pos, unsigned len, unsigned flags,
 			     struct page **pagep, void **fsdata,
 			     struct buffer_head *di_bh, struct page *mmap_page)
@@ -1692,7 +1693,7 @@
 		mlog_errno(ret);
 		goto out;
 	} else if (ret == 1) {
-		ret = ocfs2_refcount_cow(inode, di_bh,
+		ret = ocfs2_refcount_cow(inode, filp, di_bh,
 					 wc->w_cpos, wc->w_clen, UINT_MAX);
 		if (ret) {
 			mlog_errno(ret);
@@ -1854,7 +1855,7 @@
 	 */
 	down_write(&OCFS2_I(inode)->ip_alloc_sem);
 
-	ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep,
+	ret = ocfs2_write_begin_nolock(file, mapping, pos, len, flags, pagep,
 				       fsdata, di_bh, NULL);
 	if (ret) {
 		mlog_errno(ret);
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index c48e93f..7606f66 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -48,7 +48,8 @@
 			   loff_t pos, unsigned len, unsigned copied,
 			   struct page *page, void *fsdata);
 
-int ocfs2_write_begin_nolock(struct address_space *mapping,
+int ocfs2_write_begin_nolock(struct file *filp,
+			     struct address_space *mapping,
 			     loff_t pos, unsigned len, unsigned flags,
 			     struct page **pagep, void **fsdata,
 			     struct buffer_head *di_bh, struct page *mmap_page);
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 41d5f1f..52c7557 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -62,10 +62,51 @@
 static LIST_HEAD(o2hb_node_events);
 static DECLARE_WAIT_QUEUE_HEAD(o2hb_steady_queue);
 
+/*
+ * In global heartbeat, we maintain a series of region bitmaps.
+ * 	- o2hb_region_bitmap allows us to limit the region number to max region.
+ * 	- o2hb_live_region_bitmap tracks live regions (seen steady iterations).
+ * 	- o2hb_quorum_region_bitmap tracks live regions that have seen all nodes
+ * 		heartbeat on it.
+ * 	- o2hb_failed_region_bitmap tracks the regions that have seen io timeouts.
+ */
+static unsigned long o2hb_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)];
+static unsigned long o2hb_live_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)];
+static unsigned long o2hb_quorum_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)];
+static unsigned long o2hb_failed_region_bitmap[BITS_TO_LONGS(O2NM_MAX_REGIONS)];
+
+#define O2HB_DB_TYPE_LIVENODES		0
+#define O2HB_DB_TYPE_LIVEREGIONS	1
+#define O2HB_DB_TYPE_QUORUMREGIONS	2
+#define O2HB_DB_TYPE_FAILEDREGIONS	3
+#define O2HB_DB_TYPE_REGION_LIVENODES	4
+#define O2HB_DB_TYPE_REGION_NUMBER	5
+#define O2HB_DB_TYPE_REGION_ELAPSED_TIME	6
+struct o2hb_debug_buf {
+	int db_type;
+	int db_size;
+	int db_len;
+	void *db_data;
+};
+
+static struct o2hb_debug_buf *o2hb_db_livenodes;
+static struct o2hb_debug_buf *o2hb_db_liveregions;
+static struct o2hb_debug_buf *o2hb_db_quorumregions;
+static struct o2hb_debug_buf *o2hb_db_failedregions;
+
 #define O2HB_DEBUG_DIR			"o2hb"
 #define O2HB_DEBUG_LIVENODES		"livenodes"
+#define O2HB_DEBUG_LIVEREGIONS		"live_regions"
+#define O2HB_DEBUG_QUORUMREGIONS	"quorum_regions"
+#define O2HB_DEBUG_FAILEDREGIONS	"failed_regions"
+#define O2HB_DEBUG_REGION_NUMBER	"num"
+#define O2HB_DEBUG_REGION_ELAPSED_TIME	"elapsed_time_in_ms"
+
 static struct dentry *o2hb_debug_dir;
 static struct dentry *o2hb_debug_livenodes;
+static struct dentry *o2hb_debug_liveregions;
+static struct dentry *o2hb_debug_quorumregions;
+static struct dentry *o2hb_debug_failedregions;
 
 static LIST_HEAD(o2hb_all_regions);
 
@@ -77,7 +118,19 @@
 
 #define O2HB_DEFAULT_BLOCK_BITS       9
 
+enum o2hb_heartbeat_modes {
+	O2HB_HEARTBEAT_LOCAL		= 0,
+	O2HB_HEARTBEAT_GLOBAL,
+	O2HB_HEARTBEAT_NUM_MODES,
+};
+
+char *o2hb_heartbeat_mode_desc[O2HB_HEARTBEAT_NUM_MODES] = {
+		"local",	/* O2HB_HEARTBEAT_LOCAL */
+		"global",	/* O2HB_HEARTBEAT_GLOBAL */
+};
+
 unsigned int o2hb_dead_threshold = O2HB_DEFAULT_DEAD_THRESHOLD;
+unsigned int o2hb_heartbeat_mode = O2HB_HEARTBEAT_LOCAL;
 
 /* Only sets a new threshold if there are no active regions.
  *
@@ -94,6 +147,22 @@
 	}
 }
 
+static int o2hb_global_hearbeat_mode_set(unsigned int hb_mode)
+{
+	int ret = -1;
+
+	if (hb_mode < O2HB_HEARTBEAT_NUM_MODES) {
+		spin_lock(&o2hb_live_lock);
+		if (list_empty(&o2hb_all_regions)) {
+			o2hb_heartbeat_mode = hb_mode;
+			ret = 0;
+		}
+		spin_unlock(&o2hb_live_lock);
+	}
+
+	return ret;
+}
+
 struct o2hb_node_event {
 	struct list_head        hn_item;
 	enum o2hb_callback_type hn_event_type;
@@ -135,6 +204,18 @@
 	struct block_device	*hr_bdev;
 	struct o2hb_disk_slot	*hr_slots;
 
+	/* live node map of this region */
+	unsigned long		hr_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
+	unsigned int		hr_region_num;
+
+	struct dentry		*hr_debug_dir;
+	struct dentry		*hr_debug_livenodes;
+	struct dentry		*hr_debug_regnum;
+	struct dentry		*hr_debug_elapsed_time;
+	struct o2hb_debug_buf	*hr_db_livenodes;
+	struct o2hb_debug_buf	*hr_db_regnum;
+	struct o2hb_debug_buf	*hr_db_elapsed_time;
+
 	/* let the person setting up hb wait for it to return until it
 	 * has reached a 'steady' state.  This will be fixed when we have
 	 * a more complete api that doesn't lead to this sort of fragility. */
@@ -163,8 +244,19 @@
 	int               wc_error;
 };
 
+static int o2hb_pop_count(void *map, int count)
+{
+	int i = -1, pop = 0;
+
+	while ((i = find_next_bit(map, count, i + 1)) < count)
+		pop++;
+	return pop;
+}
+
 static void o2hb_write_timeout(struct work_struct *work)
 {
+	int failed, quorum;
+	unsigned long flags;
 	struct o2hb_region *reg =
 		container_of(work, struct o2hb_region,
 			     hr_write_timeout_work.work);
@@ -172,6 +264,28 @@
 	mlog(ML_ERROR, "Heartbeat write timeout to device %s after %u "
 	     "milliseconds\n", reg->hr_dev_name,
 	     jiffies_to_msecs(jiffies - reg->hr_last_timeout_start));
+
+	if (o2hb_global_heartbeat_active()) {
+		spin_lock_irqsave(&o2hb_live_lock, flags);
+		if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
+			set_bit(reg->hr_region_num, o2hb_failed_region_bitmap);
+		failed = o2hb_pop_count(&o2hb_failed_region_bitmap,
+					O2NM_MAX_REGIONS);
+		quorum = o2hb_pop_count(&o2hb_quorum_region_bitmap,
+					O2NM_MAX_REGIONS);
+		spin_unlock_irqrestore(&o2hb_live_lock, flags);
+
+		mlog(ML_HEARTBEAT, "Number of regions %d, failed regions %d\n",
+		     quorum, failed);
+
+		/*
+		 * Fence if the number of failed regions >= half the number
+		 * of  quorum regions
+		 */
+		if ((failed << 1) < quorum)
+			return;
+	}
+
 	o2quo_disk_timeout();
 }
 
@@ -180,6 +294,11 @@
 	mlog(ML_HEARTBEAT, "Queue write timeout for %u ms\n",
 	     O2HB_MAX_WRITE_TIMEOUT_MS);
 
+	if (o2hb_global_heartbeat_active()) {
+		spin_lock(&o2hb_live_lock);
+		clear_bit(reg->hr_region_num, o2hb_failed_region_bitmap);
+		spin_unlock(&o2hb_live_lock);
+	}
 	cancel_delayed_work(&reg->hr_write_timeout_work);
 	reg->hr_last_timeout_start = jiffies;
 	schedule_delayed_work(&reg->hr_write_timeout_work,
@@ -513,6 +632,8 @@
 {
 	assert_spin_locked(&o2hb_live_lock);
 
+	BUG_ON((!node) && (type != O2HB_NODE_DOWN_CB));
+
 	event->hn_event_type = type;
 	event->hn_node = node;
 	event->hn_node_num = node_num;
@@ -554,6 +675,35 @@
 	o2nm_node_put(node);
 }
 
+static void o2hb_set_quorum_device(struct o2hb_region *reg,
+				   struct o2hb_disk_slot *slot)
+{
+	assert_spin_locked(&o2hb_live_lock);
+
+	if (!o2hb_global_heartbeat_active())
+		return;
+
+	if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
+		return;
+
+	/*
+	 * A region can be added to the quorum only when it sees all
+	 * live nodes heartbeat on it. In other words, the region has been
+	 * added to all nodes.
+	 */
+	if (memcmp(reg->hr_live_node_bitmap, o2hb_live_node_bitmap,
+		   sizeof(o2hb_live_node_bitmap)))
+		return;
+
+	if (slot->ds_changed_samples < O2HB_LIVE_THRESHOLD)
+		return;
+
+	printk(KERN_NOTICE "o2hb: Region %s is now a quorum device\n",
+	       config_item_name(&reg->hr_item));
+
+	set_bit(reg->hr_region_num, o2hb_quorum_region_bitmap);
+}
+
 static int o2hb_check_slot(struct o2hb_region *reg,
 			   struct o2hb_disk_slot *slot)
 {
@@ -565,14 +715,22 @@
 	u64 cputime;
 	unsigned int dead_ms = o2hb_dead_threshold * O2HB_REGION_TIMEOUT_MS;
 	unsigned int slot_dead_ms;
+	int tmp;
 
 	memcpy(hb_block, slot->ds_raw_block, reg->hr_block_bytes);
 
-	/* Is this correct? Do we assume that the node doesn't exist
-	 * if we're not configured for him? */
+	/*
+	 * If a node is no longer configured but is still in the livemap, we
+	 * may need to clear that bit from the livemap.
+	 */
 	node = o2nm_get_node_by_num(slot->ds_node_num);
-	if (!node)
-		return 0;
+	if (!node) {
+		spin_lock(&o2hb_live_lock);
+		tmp = test_bit(slot->ds_node_num, o2hb_live_node_bitmap);
+		spin_unlock(&o2hb_live_lock);
+		if (!tmp)
+			return 0;
+	}
 
 	if (!o2hb_verify_crc(reg, hb_block)) {
 		/* all paths from here will drop o2hb_live_lock for
@@ -639,8 +797,12 @@
 		mlog(ML_HEARTBEAT, "Node %d (id 0x%llx) joined my region\n",
 		     slot->ds_node_num, (long long)slot->ds_last_generation);
 
+		set_bit(slot->ds_node_num, reg->hr_live_node_bitmap);
+
 		/* first on the list generates a callback */
 		if (list_empty(&o2hb_live_slots[slot->ds_node_num])) {
+			mlog(ML_HEARTBEAT, "o2hb: Add node %d to live nodes "
+			     "bitmap\n", slot->ds_node_num);
 			set_bit(slot->ds_node_num, o2hb_live_node_bitmap);
 
 			o2hb_queue_node_event(&event, O2HB_NODE_UP_CB, node,
@@ -684,13 +846,18 @@
 		mlog(ML_HEARTBEAT, "Node %d left my region\n",
 		     slot->ds_node_num);
 
+		clear_bit(slot->ds_node_num, reg->hr_live_node_bitmap);
+
 		/* last off the live_slot generates a callback */
 		list_del_init(&slot->ds_live_item);
 		if (list_empty(&o2hb_live_slots[slot->ds_node_num])) {
+			mlog(ML_HEARTBEAT, "o2hb: Remove node %d from live "
+			     "nodes bitmap\n", slot->ds_node_num);
 			clear_bit(slot->ds_node_num, o2hb_live_node_bitmap);
 
-			o2hb_queue_node_event(&event, O2HB_NODE_DOWN_CB, node,
-					      slot->ds_node_num);
+			/* node can be null */
+			o2hb_queue_node_event(&event, O2HB_NODE_DOWN_CB,
+					      node, slot->ds_node_num);
 
 			changed = 1;
 		}
@@ -706,11 +873,14 @@
 		slot->ds_equal_samples = 0;
 	}
 out:
+	o2hb_set_quorum_device(reg, slot);
+
 	spin_unlock(&o2hb_live_lock);
 
 	o2hb_run_event_list(&event);
 
-	o2nm_node_put(node);
+	if (node)
+		o2nm_node_put(node);
 	return changed;
 }
 
@@ -737,6 +907,7 @@
 {
 	int i, ret, highest_node, change = 0;
 	unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)];
+	unsigned long live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
 	struct o2hb_bio_wait_ctxt write_wc;
 
 	ret = o2nm_configured_node_map(configured_nodes,
@@ -746,6 +917,17 @@
 		return ret;
 	}
 
+	/*
+	 * If a node is not configured but is in the livemap, we still need
+	 * to read the slot so as to be able to remove it from the livemap.
+	 */
+	o2hb_fill_node_map(live_node_bitmap, sizeof(live_node_bitmap));
+	i = -1;
+	while ((i = find_next_bit(live_node_bitmap,
+				  O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) {
+		set_bit(i, configured_nodes);
+	}
+
 	highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES);
 	if (highest_node >= O2NM_MAX_NODES) {
 		mlog(ML_NOTICE, "ocfs2_heartbeat: no configured nodes found!\n");
@@ -917,21 +1099,59 @@
 #ifdef CONFIG_DEBUG_FS
 static int o2hb_debug_open(struct inode *inode, struct file *file)
 {
+	struct o2hb_debug_buf *db = inode->i_private;
+	struct o2hb_region *reg;
 	unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)];
 	char *buf = NULL;
 	int i = -1;
 	int out = 0;
 
+	/* max_nodes should be the largest bitmap we pass here */
+	BUG_ON(sizeof(map) < db->db_size);
+
 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!buf)
 		goto bail;
 
-	o2hb_fill_node_map(map, sizeof(map));
+	switch (db->db_type) {
+	case O2HB_DB_TYPE_LIVENODES:
+	case O2HB_DB_TYPE_LIVEREGIONS:
+	case O2HB_DB_TYPE_QUORUMREGIONS:
+	case O2HB_DB_TYPE_FAILEDREGIONS:
+		spin_lock(&o2hb_live_lock);
+		memcpy(map, db->db_data, db->db_size);
+		spin_unlock(&o2hb_live_lock);
+		break;
 
-	while ((i = find_next_bit(map, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES)
+	case O2HB_DB_TYPE_REGION_LIVENODES:
+		spin_lock(&o2hb_live_lock);
+		reg = (struct o2hb_region *)db->db_data;
+		memcpy(map, reg->hr_live_node_bitmap, db->db_size);
+		spin_unlock(&o2hb_live_lock);
+		break;
+
+	case O2HB_DB_TYPE_REGION_NUMBER:
+		reg = (struct o2hb_region *)db->db_data;
+		out += snprintf(buf + out, PAGE_SIZE - out, "%d\n",
+				reg->hr_region_num);
+		goto done;
+
+	case O2HB_DB_TYPE_REGION_ELAPSED_TIME:
+		reg = (struct o2hb_region *)db->db_data;
+		out += snprintf(buf + out, PAGE_SIZE - out, "%u\n",
+				jiffies_to_msecs(jiffies -
+						 reg->hr_last_timeout_start));
+		goto done;
+
+	default:
+		goto done;
+	}
+
+	while ((i = find_next_bit(map, db->db_len, i + 1)) < db->db_len)
 		out += snprintf(buf + out, PAGE_SIZE - out, "%d ", i);
 	out += snprintf(buf + out, PAGE_SIZE - out, "\n");
 
+done:
 	i_size_write(inode, out);
 
 	file->private_data = buf;
@@ -978,10 +1198,104 @@
 
 void o2hb_exit(void)
 {
-	if (o2hb_debug_livenodes)
-		debugfs_remove(o2hb_debug_livenodes);
-	if (o2hb_debug_dir)
-		debugfs_remove(o2hb_debug_dir);
+	kfree(o2hb_db_livenodes);
+	kfree(o2hb_db_liveregions);
+	kfree(o2hb_db_quorumregions);
+	kfree(o2hb_db_failedregions);
+	debugfs_remove(o2hb_debug_failedregions);
+	debugfs_remove(o2hb_debug_quorumregions);
+	debugfs_remove(o2hb_debug_liveregions);
+	debugfs_remove(o2hb_debug_livenodes);
+	debugfs_remove(o2hb_debug_dir);
+}
+
+static struct dentry *o2hb_debug_create(const char *name, struct dentry *dir,
+					struct o2hb_debug_buf **db, int db_len,
+					int type, int size, int len, void *data)
+{
+	*db = kmalloc(db_len, GFP_KERNEL);
+	if (!*db)
+		return NULL;
+
+	(*db)->db_type = type;
+	(*db)->db_size = size;
+	(*db)->db_len = len;
+	(*db)->db_data = data;
+
+	return debugfs_create_file(name, S_IFREG|S_IRUSR, dir, *db,
+				   &o2hb_debug_fops);
+}
+
+static int o2hb_debug_init(void)
+{
+	int ret = -ENOMEM;
+
+	o2hb_debug_dir = debugfs_create_dir(O2HB_DEBUG_DIR, NULL);
+	if (!o2hb_debug_dir) {
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	o2hb_debug_livenodes = o2hb_debug_create(O2HB_DEBUG_LIVENODES,
+						 o2hb_debug_dir,
+						 &o2hb_db_livenodes,
+						 sizeof(*o2hb_db_livenodes),
+						 O2HB_DB_TYPE_LIVENODES,
+						 sizeof(o2hb_live_node_bitmap),
+						 O2NM_MAX_NODES,
+						 o2hb_live_node_bitmap);
+	if (!o2hb_debug_livenodes) {
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	o2hb_debug_liveregions = o2hb_debug_create(O2HB_DEBUG_LIVEREGIONS,
+						   o2hb_debug_dir,
+						   &o2hb_db_liveregions,
+						   sizeof(*o2hb_db_liveregions),
+						   O2HB_DB_TYPE_LIVEREGIONS,
+						   sizeof(o2hb_live_region_bitmap),
+						   O2NM_MAX_REGIONS,
+						   o2hb_live_region_bitmap);
+	if (!o2hb_debug_liveregions) {
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	o2hb_debug_quorumregions =
+			o2hb_debug_create(O2HB_DEBUG_QUORUMREGIONS,
+					  o2hb_debug_dir,
+					  &o2hb_db_quorumregions,
+					  sizeof(*o2hb_db_quorumregions),
+					  O2HB_DB_TYPE_QUORUMREGIONS,
+					  sizeof(o2hb_quorum_region_bitmap),
+					  O2NM_MAX_REGIONS,
+					  o2hb_quorum_region_bitmap);
+	if (!o2hb_debug_quorumregions) {
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	o2hb_debug_failedregions =
+			o2hb_debug_create(O2HB_DEBUG_FAILEDREGIONS,
+					  o2hb_debug_dir,
+					  &o2hb_db_failedregions,
+					  sizeof(*o2hb_db_failedregions),
+					  O2HB_DB_TYPE_FAILEDREGIONS,
+					  sizeof(o2hb_failed_region_bitmap),
+					  O2NM_MAX_REGIONS,
+					  o2hb_failed_region_bitmap);
+	if (!o2hb_debug_failedregions) {
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	ret = 0;
+bail:
+	if (ret)
+		o2hb_exit();
+
+	return ret;
 }
 
 int o2hb_init(void)
@@ -997,24 +1311,12 @@
 	INIT_LIST_HEAD(&o2hb_node_events);
 
 	memset(o2hb_live_node_bitmap, 0, sizeof(o2hb_live_node_bitmap));
+	memset(o2hb_region_bitmap, 0, sizeof(o2hb_region_bitmap));
+	memset(o2hb_live_region_bitmap, 0, sizeof(o2hb_live_region_bitmap));
+	memset(o2hb_quorum_region_bitmap, 0, sizeof(o2hb_quorum_region_bitmap));
+	memset(o2hb_failed_region_bitmap, 0, sizeof(o2hb_failed_region_bitmap));
 
-	o2hb_debug_dir = debugfs_create_dir(O2HB_DEBUG_DIR, NULL);
-	if (!o2hb_debug_dir) {
-		mlog_errno(-ENOMEM);
-		return -ENOMEM;
-	}
-
-	o2hb_debug_livenodes = debugfs_create_file(O2HB_DEBUG_LIVENODES,
-						   S_IFREG|S_IRUSR,
-						   o2hb_debug_dir, NULL,
-						   &o2hb_debug_fops);
-	if (!o2hb_debug_livenodes) {
-		mlog_errno(-ENOMEM);
-		debugfs_remove(o2hb_debug_dir);
-		return -ENOMEM;
-	}
-
-	return 0;
+	return o2hb_debug_init();
 }
 
 /* if we're already in a callback then we're already serialized by the sem */
@@ -1078,6 +1380,13 @@
 	if (reg->hr_slots)
 		kfree(reg->hr_slots);
 
+	kfree(reg->hr_db_regnum);
+	kfree(reg->hr_db_livenodes);
+	debugfs_remove(reg->hr_debug_livenodes);
+	debugfs_remove(reg->hr_debug_regnum);
+	debugfs_remove(reg->hr_debug_elapsed_time);
+	debugfs_remove(reg->hr_debug_dir);
+
 	spin_lock(&o2hb_live_lock);
 	list_del(&reg->hr_all_item);
 	spin_unlock(&o2hb_live_lock);
@@ -1441,6 +1750,8 @@
 	/* Ok, we were woken.  Make sure it wasn't by drop_item() */
 	spin_lock(&o2hb_live_lock);
 	hb_task = reg->hr_task;
+	if (o2hb_global_heartbeat_active())
+		set_bit(reg->hr_region_num, o2hb_live_region_bitmap);
 	spin_unlock(&o2hb_live_lock);
 
 	if (hb_task)
@@ -1448,6 +1759,10 @@
 	else
 		ret = -EIO;
 
+	if (hb_task && o2hb_global_heartbeat_active())
+		printk(KERN_NOTICE "o2hb: Heartbeat started on region %s\n",
+		       config_item_name(&reg->hr_item));
+
 out:
 	if (filp)
 		fput(filp);
@@ -1586,21 +1901,94 @@
 		: NULL;
 }
 
+static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
+{
+	int ret = -ENOMEM;
+
+	reg->hr_debug_dir =
+		debugfs_create_dir(config_item_name(&reg->hr_item), dir);
+	if (!reg->hr_debug_dir) {
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	reg->hr_debug_livenodes =
+			o2hb_debug_create(O2HB_DEBUG_LIVENODES,
+					  reg->hr_debug_dir,
+					  &(reg->hr_db_livenodes),
+					  sizeof(*(reg->hr_db_livenodes)),
+					  O2HB_DB_TYPE_REGION_LIVENODES,
+					  sizeof(reg->hr_live_node_bitmap),
+					  O2NM_MAX_NODES, reg);
+	if (!reg->hr_debug_livenodes) {
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	reg->hr_debug_regnum =
+			o2hb_debug_create(O2HB_DEBUG_REGION_NUMBER,
+					  reg->hr_debug_dir,
+					  &(reg->hr_db_regnum),
+					  sizeof(*(reg->hr_db_regnum)),
+					  O2HB_DB_TYPE_REGION_NUMBER,
+					  0, O2NM_MAX_NODES, reg);
+	if (!reg->hr_debug_regnum) {
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	reg->hr_debug_elapsed_time =
+			o2hb_debug_create(O2HB_DEBUG_REGION_ELAPSED_TIME,
+					  reg->hr_debug_dir,
+					  &(reg->hr_db_elapsed_time),
+					  sizeof(*(reg->hr_db_elapsed_time)),
+					  O2HB_DB_TYPE_REGION_ELAPSED_TIME,
+					  0, 0, reg);
+	if (!reg->hr_debug_elapsed_time) {
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	ret = 0;
+bail:
+	return ret;
+}
+
 static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *group,
 							  const char *name)
 {
 	struct o2hb_region *reg = NULL;
+	int ret;
 
 	reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL);
 	if (reg == NULL)
 		return ERR_PTR(-ENOMEM);
 
-	config_item_init_type_name(&reg->hr_item, name, &o2hb_region_type);
+	if (strlen(name) > O2HB_MAX_REGION_NAME_LEN)
+		return ERR_PTR(-ENAMETOOLONG);
 
 	spin_lock(&o2hb_live_lock);
+	reg->hr_region_num = 0;
+	if (o2hb_global_heartbeat_active()) {
+		reg->hr_region_num = find_first_zero_bit(o2hb_region_bitmap,
+							 O2NM_MAX_REGIONS);
+		if (reg->hr_region_num >= O2NM_MAX_REGIONS) {
+			spin_unlock(&o2hb_live_lock);
+			return ERR_PTR(-EFBIG);
+		}
+		set_bit(reg->hr_region_num, o2hb_region_bitmap);
+	}
 	list_add_tail(&reg->hr_all_item, &o2hb_all_regions);
 	spin_unlock(&o2hb_live_lock);
 
+	config_item_init_type_name(&reg->hr_item, name, &o2hb_region_type);
+
+	ret = o2hb_debug_region_init(reg, o2hb_debug_dir);
+	if (ret) {
+		config_item_put(&reg->hr_item);
+		return ERR_PTR(ret);
+	}
+
 	return &reg->hr_item;
 }
 
@@ -1612,6 +2000,10 @@
 
 	/* stop the thread when the user removes the region dir */
 	spin_lock(&o2hb_live_lock);
+	if (o2hb_global_heartbeat_active()) {
+		clear_bit(reg->hr_region_num, o2hb_region_bitmap);
+		clear_bit(reg->hr_region_num, o2hb_live_region_bitmap);
+	}
 	hb_task = reg->hr_task;
 	reg->hr_task = NULL;
 	spin_unlock(&o2hb_live_lock);
@@ -1628,6 +2020,9 @@
 		wake_up(&o2hb_steady_queue);
 	}
 
+	if (o2hb_global_heartbeat_active())
+		printk(KERN_NOTICE "o2hb: Heartbeat stopped on region %s\n",
+		       config_item_name(&reg->hr_item));
 	config_item_put(item);
 }
 
@@ -1688,6 +2083,41 @@
 	return count;
 }
 
+static
+ssize_t o2hb_heartbeat_group_mode_show(struct o2hb_heartbeat_group *group,
+				       char *page)
+{
+	return sprintf(page, "%s\n",
+		       o2hb_heartbeat_mode_desc[o2hb_heartbeat_mode]);
+}
+
+static
+ssize_t o2hb_heartbeat_group_mode_store(struct o2hb_heartbeat_group *group,
+					const char *page, size_t count)
+{
+	unsigned int i;
+	int ret;
+	size_t len;
+
+	len = (page[count - 1] == '\n') ? count - 1 : count;
+	if (!len)
+		return -EINVAL;
+
+	for (i = 0; i < O2HB_HEARTBEAT_NUM_MODES; ++i) {
+		if (strnicmp(page, o2hb_heartbeat_mode_desc[i], len))
+			continue;
+
+		ret = o2hb_global_hearbeat_mode_set(i);
+		if (!ret)
+			printk(KERN_NOTICE "o2hb: Heartbeat mode set to %s\n",
+			       o2hb_heartbeat_mode_desc[i]);
+		return count;
+	}
+
+	return -EINVAL;
+
+}
+
 static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_threshold = {
 	.attr	= { .ca_owner = THIS_MODULE,
 		    .ca_name = "dead_threshold",
@@ -1696,8 +2126,17 @@
 	.store	= o2hb_heartbeat_group_threshold_store,
 };
 
+static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_mode = {
+	.attr   = { .ca_owner = THIS_MODULE,
+		.ca_name = "mode",
+		.ca_mode = S_IRUGO | S_IWUSR },
+	.show   = o2hb_heartbeat_group_mode_show,
+	.store  = o2hb_heartbeat_group_mode_store,
+};
+
 static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = {
 	&o2hb_heartbeat_group_attr_threshold.attr,
+	&o2hb_heartbeat_group_attr_mode.attr,
 	NULL,
 };
 
@@ -1963,3 +2402,34 @@
 	spin_unlock(&o2hb_live_lock);
 }
 EXPORT_SYMBOL_GPL(o2hb_stop_all_regions);
+
+int o2hb_get_all_regions(char *region_uuids, u8 max_regions)
+{
+	struct o2hb_region *reg;
+	int numregs = 0;
+	char *p;
+
+	spin_lock(&o2hb_live_lock);
+
+	p = region_uuids;
+	list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) {
+		mlog(0, "Region: %s\n", config_item_name(&reg->hr_item));
+		if (numregs < max_regions) {
+			memcpy(p, config_item_name(&reg->hr_item),
+			       O2HB_MAX_REGION_NAME_LEN);
+			p += O2HB_MAX_REGION_NAME_LEN;
+		}
+		numregs++;
+	}
+
+	spin_unlock(&o2hb_live_lock);
+
+	return numregs;
+}
+EXPORT_SYMBOL_GPL(o2hb_get_all_regions);
+
+int o2hb_global_heartbeat_active(void)
+{
+	return (o2hb_heartbeat_mode == O2HB_HEARTBEAT_GLOBAL);
+}
+EXPORT_SYMBOL(o2hb_global_heartbeat_active);
diff --git a/fs/ocfs2/cluster/heartbeat.h b/fs/ocfs2/cluster/heartbeat.h
index 2f16492..00ad8e8 100644
--- a/fs/ocfs2/cluster/heartbeat.h
+++ b/fs/ocfs2/cluster/heartbeat.h
@@ -31,6 +31,8 @@
 
 #define O2HB_REGION_TIMEOUT_MS		2000
 
+#define O2HB_MAX_REGION_NAME_LEN	32
+
 /* number of changes to be seen as live */
 #define O2HB_LIVE_THRESHOLD	   2
 /* number of equal samples to be seen as dead */
@@ -81,5 +83,7 @@
 int o2hb_check_node_heartbeating_from_callback(u8 node_num);
 int o2hb_check_local_node_heartbeating(void);
 void o2hb_stop_all_regions(void);
+int o2hb_get_all_regions(char *region_uuids, u8 numregions);
+int o2hb_global_heartbeat_active(void);
 
 #endif /* O2CLUSTER_HEARTBEAT_H */
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index fd96e2a..ea2ed9f 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -119,7 +119,8 @@
 #define ML_ERROR	0x0000000100000000ULL /* sent to KERN_ERR */
 #define ML_NOTICE	0x0000000200000000ULL /* setn to KERN_NOTICE */
 #define ML_KTHREAD	0x0000000400000000ULL /* kernel thread activity */
-#define	ML_RESERVATIONS	0x0000000800000000ULL /* ocfs2 alloc reservations */
+#define ML_RESERVATIONS	0x0000000800000000ULL /* ocfs2 alloc reservations */
+#define ML_CLUSTER	0x0000001000000000ULL /* cluster stack */
 
 #define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE)
 #define MLOG_INITIAL_NOT_MASK (ML_ENTRY|ML_EXIT)
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
index ed0c9f3..bb24064 100644
--- a/fs/ocfs2/cluster/nodemanager.c
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -711,6 +711,8 @@
 	config_item_init_type_name(&node->nd_item, name, &o2nm_node_type);
 	spin_lock_init(&node->nd_lock);
 
+	mlog(ML_CLUSTER, "o2nm: Registering node %s\n", name);
+
 	return &node->nd_item;
 }
 
@@ -744,6 +746,9 @@
 	}
 	write_unlock(&cluster->cl_nodes_lock);
 
+	mlog(ML_CLUSTER, "o2nm: Unregistered node %s\n",
+	     config_item_name(&node->nd_item));
+
 	config_item_put(item);
 }
 
diff --git a/fs/ocfs2/cluster/ocfs2_nodemanager.h b/fs/ocfs2/cluster/ocfs2_nodemanager.h
index 5b9854b..49b5943 100644
--- a/fs/ocfs2/cluster/ocfs2_nodemanager.h
+++ b/fs/ocfs2/cluster/ocfs2_nodemanager.h
@@ -36,4 +36,10 @@
 /* host name, group name, cluster name all 64 bytes */
 #define O2NM_MAX_NAME_LEN        64    // __NEW_UTS_LEN
 
+/*
+ * Maximum number of global heartbeat regions allowed.
+ * **CAUTION**  Changing this number will break dlm compatibility.
+ */
+#define O2NM_MAX_REGIONS	32
+
 #endif /* _OCFS2_NODEMANAGER_H */
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 1361997..9aa426e 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -977,7 +977,7 @@
 int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
 			   size_t caller_veclen, u8 target_node, int *status)
 {
-	int ret;
+	int ret = 0;
 	struct o2net_msg *msg = NULL;
 	size_t veclen, caller_bytes = 0;
 	struct kvec *vec = NULL;
@@ -1696,6 +1696,9 @@
 {
 	o2quo_hb_down(node_num);
 
+	if (!node)
+		return;
+
 	if (node_num != o2nm_this_node())
 		o2net_disconnect_node(node);
 
@@ -1709,6 +1712,8 @@
 
 	o2quo_hb_up(node_num);
 
+	BUG_ON(!node);
+
 	/* ensure an immediate connect attempt */
 	nn->nn_last_connect_attempt = jiffies -
 		(msecs_to_jiffies(o2net_reconnect_delay()) + 1);
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index b4957c7..edaded4 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -40,6 +40,14 @@
 #include "inode.h"
 #include "super.h"
 
+void ocfs2_dentry_attach_gen(struct dentry *dentry)
+{
+	unsigned long gen =
+		OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen;
+	BUG_ON(dentry->d_inode);
+	dentry->d_fsdata = (void *)gen;
+}
+
 
 static int ocfs2_dentry_revalidate(struct dentry *dentry,
 				   struct nameidata *nd)
@@ -51,11 +59,20 @@
 	mlog_entry("(0x%p, '%.*s')\n", dentry,
 		   dentry->d_name.len, dentry->d_name.name);
 
-	/* Never trust a negative dentry - force a new lookup. */
+	/* For a negative dentry -
+	 * check the generation number of the parent and compare with the
+	 * one stored in the inode.
+	 */
 	if (inode == NULL) {
-		mlog(0, "negative dentry: %.*s\n", dentry->d_name.len,
-		     dentry->d_name.name);
-		goto bail;
+		unsigned long gen = (unsigned long) dentry->d_fsdata;
+		unsigned long pgen =
+			OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen;
+		mlog(0, "negative dentry: %.*s parent gen: %lu "
+			"dentry gen: %lu\n",
+			dentry->d_name.len, dentry->d_name.name, pgen, gen);
+		if (gen != pgen)
+			goto bail;
+		goto valid;
 	}
 
 	BUG_ON(!osb);
@@ -96,6 +113,7 @@
 		goto bail;
 	}
 
+valid:
 	ret = 1;
 
 bail:
@@ -227,6 +245,12 @@
 	if (!inode)
 		return 0;
 
+	if (!dentry->d_inode && dentry->d_fsdata) {
+		/* Converting a negative dentry to positive
+		   Clear dentry->d_fsdata */
+		dentry->d_fsdata = dl = NULL;
+	}
+
 	if (dl) {
 		mlog_bug_on_msg(dl->dl_parent_blkno != parent_blkno,
 				" \"%.*s\": old parent: %llu, new: %llu\n",
@@ -452,6 +476,7 @@
 
 out:
 	iput(inode);
+	ocfs2_dentry_attach_gen(dentry);
 }
 
 /*
diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h
index f5dd178..b79eff7 100644
--- a/fs/ocfs2/dcache.h
+++ b/fs/ocfs2/dcache.h
@@ -64,5 +64,6 @@
 		       struct inode *old_dir, struct inode *new_dir);
 
 extern spinlock_t dentry_attach_lock;
+void ocfs2_dentry_attach_gen(struct dentry *dentry);
 
 #endif /* OCFS2_DCACHE_H */
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index f04ebcf..c49f6de 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -3931,6 +3931,15 @@
 		goto out_commit;
 	}
 
+	cpos = split_hash;
+	ret = ocfs2_dx_dir_new_cluster(dir, &et, cpos, handle,
+				       data_ac, meta_ac, new_dx_leaves,
+				       num_dx_leaves);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
 	for (i = 0; i < num_dx_leaves; i++) {
 		ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
 					      orig_dx_leaves[i],
@@ -3939,15 +3948,14 @@
 			mlog_errno(ret);
 			goto out_commit;
 		}
-	}
 
-	cpos = split_hash;
-	ret = ocfs2_dx_dir_new_cluster(dir, &et, cpos, handle,
-				       data_ac, meta_ac, new_dx_leaves,
-				       num_dx_leaves);
-	if (ret) {
-		mlog_errno(ret);
-		goto out_commit;
+		ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
+					      new_dx_leaves[i],
+					      OCFS2_JOURNAL_ACCESS_WRITE);
+		if (ret) {
+			mlog_errno(ret);
+			goto out_commit;
+		}
 	}
 
 	ocfs2_dx_dir_transfer_leaf(dir, split_hash, handle, tmp_dx_leaf,
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
index 4b6ae2c..b36d0bf 100644
--- a/fs/ocfs2/dlm/dlmcommon.h
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -445,7 +445,9 @@
 	DLM_LOCK_REQUEST_MSG,	 /* 515 */
 	DLM_RECO_DATA_DONE_MSG,	 /* 516 */
 	DLM_BEGIN_RECO_MSG,	 /* 517 */
-	DLM_FINALIZE_RECO_MSG	 /* 518 */
+	DLM_FINALIZE_RECO_MSG,	 /* 518 */
+	DLM_QUERY_REGION,	 /* 519 */
+	DLM_QUERY_NODEINFO,	 /* 520 */
 };
 
 struct dlm_reco_node_data
@@ -727,6 +729,31 @@
 	u8 domain[O2NM_MAX_NAME_LEN];
 };
 
+struct dlm_query_region {
+	u8 qr_node;
+	u8 qr_numregions;
+	u8 qr_namelen;
+	u8 pad1;
+	u8 qr_domain[O2NM_MAX_NAME_LEN];
+	u8 qr_regions[O2HB_MAX_REGION_NAME_LEN * O2NM_MAX_REGIONS];
+};
+
+struct dlm_node_info {
+	u8 ni_nodenum;
+	u8 pad1;
+	u16 ni_ipv4_port;
+	u32 ni_ipv4_address;
+};
+
+struct dlm_query_nodeinfo {
+	u8 qn_nodenum;
+	u8 qn_numnodes;
+	u8 qn_namelen;
+	u8 pad1;
+	u8 qn_domain[O2NM_MAX_NAME_LEN];
+	struct dlm_node_info qn_nodes[O2NM_MAX_NODES];
+};
+
 struct dlm_exit_domain
 {
 	u8 node_idx;
@@ -1030,6 +1057,7 @@
 			 struct dlm_lock_resource *res);
 void dlm_clean_master_list(struct dlm_ctxt *dlm,
 			   u8 dead_node);
+void dlm_force_free_mles(struct dlm_ctxt *dlm);
 int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock);
 int __dlm_lockres_has_locks(struct dlm_lock_resource *res);
 int __dlm_lockres_unused(struct dlm_lock_resource *res);
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
index 5efdd37..272ec86 100644
--- a/fs/ocfs2/dlm/dlmdebug.c
+++ b/fs/ocfs2/dlm/dlmdebug.c
@@ -493,7 +493,7 @@
 	struct hlist_head *bucket;
 	struct hlist_node *list;
 	int i, out = 0;
-	unsigned long total = 0, longest = 0, bktcnt;
+	unsigned long total = 0, longest = 0, bucket_count = 0;
 
 	out += snprintf(db->buf + out, db->len - out,
 			"Dumping MLEs for Domain: %s\n", dlm->name);
@@ -505,13 +505,13 @@
 			mle = hlist_entry(list, struct dlm_master_list_entry,
 					  master_hash_node);
 			++total;
-			++bktcnt;
+			++bucket_count;
 			if (db->len - out < 200)
 				continue;
 			out += dump_mle(mle, db->buf + out, db->len - out);
 		}
-		longest = max(longest, bktcnt);
-		bktcnt = 0;
+		longest = max(longest, bucket_count);
+		bucket_count = 0;
 	}
 	spin_unlock(&dlm->master_lock);
 
@@ -636,8 +636,14 @@
 	spin_lock(&dlm->track_lock);
 	if (oldres)
 		track_list = &oldres->tracking;
-	else
+	else {
 		track_list = &dlm->tracking_list;
+		if (list_empty(track_list)) {
+			dl = NULL;
+			spin_unlock(&dlm->track_lock);
+			goto bail;
+		}
+	}
 
 	list_for_each_entry(res, track_list, tracking) {
 		if (&res->tracking == &dlm->tracking_list)
@@ -660,6 +666,7 @@
 	} else
 		dl = NULL;
 
+bail:
 	/* passed to seq_show */
 	return dl;
 }
@@ -775,7 +782,9 @@
 
 	/* Domain: xxxxxxxxxx  Key: 0xdfbac769 */
 	out += snprintf(db->buf + out, db->len - out,
-			"Domain: %s  Key: 0x%08x\n", dlm->name, dlm->key);
+			"Domain: %s  Key: 0x%08x  Protocol: %d.%d\n",
+			dlm->name, dlm->key, dlm->dlm_locking_proto.pv_major,
+			dlm->dlm_locking_proto.pv_minor);
 
 	/* Thread Pid: xxx  Node: xxx  State: xxxxx */
 	out += snprintf(db->buf + out, db->len - out,
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 153abb5..58a93b9 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -128,10 +128,14 @@
  * will have a negotiated version with the same major number and a minor
  * number equal or smaller.  The dlm_ctxt->dlm_locking_proto field should
  * be used to determine what a running domain is actually using.
+ *
+ * New in version 1.1:
+ *	- Message DLM_QUERY_REGION added to support global heartbeat
+ *	- Message DLM_QUERY_NODEINFO added to allow online node removes
  */
 static const struct dlm_protocol_version dlm_protocol = {
 	.pv_major = 1,
-	.pv_minor = 0,
+	.pv_minor = 1,
 };
 
 #define DLM_DOMAIN_BACKOFF_MS 200
@@ -142,6 +146,8 @@
 				     void **ret_data);
 static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data,
 				   void **ret_data);
+static int dlm_query_region_handler(struct o2net_msg *msg, u32 len,
+				    void *data, void **ret_data);
 static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,
 				   void **ret_data);
 static int dlm_protocol_compare(struct dlm_protocol_version *existing,
@@ -693,6 +699,7 @@
 
 		dlm_mark_domain_leaving(dlm);
 		dlm_leave_domain(dlm);
+		dlm_force_free_mles(dlm);
 		dlm_complete_dlm_shutdown(dlm);
 	}
 	dlm_put(dlm);
@@ -920,6 +927,370 @@
 	return 0;
 }
 
+static int dlm_match_regions(struct dlm_ctxt *dlm,
+			     struct dlm_query_region *qr)
+{
+	char *local = NULL, *remote = qr->qr_regions;
+	char *l, *r;
+	int localnr, i, j, foundit;
+	int status = 0;
+
+	if (!o2hb_global_heartbeat_active()) {
+		if (qr->qr_numregions) {
+			mlog(ML_ERROR, "Domain %s: Joining node %d has global "
+			     "heartbeat enabled but local node %d does not\n",
+			     qr->qr_domain, qr->qr_node, dlm->node_num);
+			status = -EINVAL;
+		}
+		goto bail;
+	}
+
+	if (o2hb_global_heartbeat_active() && !qr->qr_numregions) {
+		mlog(ML_ERROR, "Domain %s: Local node %d has global "
+		     "heartbeat enabled but joining node %d does not\n",
+		     qr->qr_domain, dlm->node_num, qr->qr_node);
+		status = -EINVAL;
+		goto bail;
+	}
+
+	r = remote;
+	for (i = 0; i < qr->qr_numregions; ++i) {
+		mlog(0, "Region %.*s\n", O2HB_MAX_REGION_NAME_LEN, r);
+		r += O2HB_MAX_REGION_NAME_LEN;
+	}
+
+	local = kmalloc(sizeof(qr->qr_regions), GFP_KERNEL);
+	if (!local) {
+		status = -ENOMEM;
+		goto bail;
+	}
+
+	localnr = o2hb_get_all_regions(local, O2NM_MAX_REGIONS);
+
+	/* compare local regions with remote */
+	l = local;
+	for (i = 0; i < localnr; ++i) {
+		foundit = 0;
+		r = remote;
+		for (j = 0; j <= qr->qr_numregions; ++j) {
+			if (!memcmp(l, r, O2HB_MAX_REGION_NAME_LEN)) {
+				foundit = 1;
+				break;
+			}
+			r += O2HB_MAX_REGION_NAME_LEN;
+		}
+		if (!foundit) {
+			status = -EINVAL;
+			mlog(ML_ERROR, "Domain %s: Region '%.*s' registered "
+			     "in local node %d but not in joining node %d\n",
+			     qr->qr_domain, O2HB_MAX_REGION_NAME_LEN, l,
+			     dlm->node_num, qr->qr_node);
+			goto bail;
+		}
+		l += O2HB_MAX_REGION_NAME_LEN;
+	}
+
+	/* compare remote with local regions */
+	r = remote;
+	for (i = 0; i < qr->qr_numregions; ++i) {
+		foundit = 0;
+		l = local;
+		for (j = 0; j < localnr; ++j) {
+			if (!memcmp(r, l, O2HB_MAX_REGION_NAME_LEN)) {
+				foundit = 1;
+				break;
+			}
+			l += O2HB_MAX_REGION_NAME_LEN;
+		}
+		if (!foundit) {
+			status = -EINVAL;
+			mlog(ML_ERROR, "Domain %s: Region '%.*s' registered "
+			     "in joining node %d but not in local node %d\n",
+			     qr->qr_domain, O2HB_MAX_REGION_NAME_LEN, r,
+			     qr->qr_node, dlm->node_num);
+			goto bail;
+		}
+		r += O2HB_MAX_REGION_NAME_LEN;
+	}
+
+bail:
+	kfree(local);
+
+	return status;
+}
+
+static int dlm_send_regions(struct dlm_ctxt *dlm, unsigned long *node_map)
+{
+	struct dlm_query_region *qr = NULL;
+	int status, ret = 0, i;
+	char *p;
+
+	if (find_next_bit(node_map, O2NM_MAX_NODES, 0) >= O2NM_MAX_NODES)
+		goto bail;
+
+	qr = kzalloc(sizeof(struct dlm_query_region), GFP_KERNEL);
+	if (!qr) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	qr->qr_node = dlm->node_num;
+	qr->qr_namelen = strlen(dlm->name);
+	memcpy(qr->qr_domain, dlm->name, qr->qr_namelen);
+	/* if local hb, the numregions will be zero */
+	if (o2hb_global_heartbeat_active())
+		qr->qr_numregions = o2hb_get_all_regions(qr->qr_regions,
+							 O2NM_MAX_REGIONS);
+
+	p = qr->qr_regions;
+	for (i = 0; i < qr->qr_numregions; ++i, p += O2HB_MAX_REGION_NAME_LEN)
+		mlog(0, "Region %.*s\n", O2HB_MAX_REGION_NAME_LEN, p);
+
+	i = -1;
+	while ((i = find_next_bit(node_map, O2NM_MAX_NODES,
+				  i + 1)) < O2NM_MAX_NODES) {
+		if (i == dlm->node_num)
+			continue;
+
+		mlog(0, "Sending regions to node %d\n", i);
+
+		ret = o2net_send_message(DLM_QUERY_REGION, DLM_MOD_KEY, qr,
+					 sizeof(struct dlm_query_region),
+					 i, &status);
+		if (ret >= 0)
+			ret = status;
+		if (ret) {
+			mlog(ML_ERROR, "Region mismatch %d, node %d\n",
+			     ret, i);
+			break;
+		}
+	}
+
+bail:
+	kfree(qr);
+	return ret;
+}
+
+static int dlm_query_region_handler(struct o2net_msg *msg, u32 len,
+				    void *data, void **ret_data)
+{
+	struct dlm_query_region *qr;
+	struct dlm_ctxt *dlm = NULL;
+	int status = 0;
+	int locked = 0;
+
+	qr = (struct dlm_query_region *) msg->buf;
+
+	mlog(0, "Node %u queries hb regions on domain %s\n", qr->qr_node,
+	     qr->qr_domain);
+
+	status = -EINVAL;
+
+	spin_lock(&dlm_domain_lock);
+	dlm = __dlm_lookup_domain_full(qr->qr_domain, qr->qr_namelen);
+	if (!dlm) {
+		mlog(ML_ERROR, "Node %d queried hb regions on domain %s "
+		     "before join domain\n", qr->qr_node, qr->qr_domain);
+		goto bail;
+	}
+
+	spin_lock(&dlm->spinlock);
+	locked = 1;
+	if (dlm->joining_node != qr->qr_node) {
+		mlog(ML_ERROR, "Node %d queried hb regions on domain %s "
+		     "but joining node is %d\n", qr->qr_node, qr->qr_domain,
+		     dlm->joining_node);
+		goto bail;
+	}
+
+	/* Support for global heartbeat was added in 1.1 */
+	if (dlm->dlm_locking_proto.pv_major == 1 &&
+	    dlm->dlm_locking_proto.pv_minor == 0) {
+		mlog(ML_ERROR, "Node %d queried hb regions on domain %s "
+		     "but active dlm protocol is %d.%d\n", qr->qr_node,
+		     qr->qr_domain, dlm->dlm_locking_proto.pv_major,
+		     dlm->dlm_locking_proto.pv_minor);
+		goto bail;
+	}
+
+	status = dlm_match_regions(dlm, qr);
+
+bail:
+	if (locked)
+		spin_unlock(&dlm->spinlock);
+	spin_unlock(&dlm_domain_lock);
+
+	return status;
+}
+
+static int dlm_match_nodes(struct dlm_ctxt *dlm, struct dlm_query_nodeinfo *qn)
+{
+	struct o2nm_node *local;
+	struct dlm_node_info *remote;
+	int i, j;
+	int status = 0;
+
+	for (j = 0; j < qn->qn_numnodes; ++j)
+		mlog(0, "Node %3d, %pI4:%u\n", qn->qn_nodes[j].ni_nodenum,
+		     &(qn->qn_nodes[j].ni_ipv4_address),
+		     ntohs(qn->qn_nodes[j].ni_ipv4_port));
+
+	for (i = 0; i < O2NM_MAX_NODES && !status; ++i) {
+		local = o2nm_get_node_by_num(i);
+		remote = NULL;
+		for (j = 0; j < qn->qn_numnodes; ++j) {
+			if (qn->qn_nodes[j].ni_nodenum == i) {
+				remote = &(qn->qn_nodes[j]);
+				break;
+			}
+		}
+
+		if (!local && !remote)
+			continue;
+
+		if ((local && !remote) || (!local && remote))
+			status = -EINVAL;
+
+		if (!status &&
+		    ((remote->ni_nodenum != local->nd_num) ||
+		     (remote->ni_ipv4_port != local->nd_ipv4_port) ||
+		     (remote->ni_ipv4_address != local->nd_ipv4_address)))
+			status = -EINVAL;
+
+		if (status) {
+			if (remote && !local)
+				mlog(ML_ERROR, "Domain %s: Node %d (%pI4:%u) "
+				     "registered in joining node %d but not in "
+				     "local node %d\n", qn->qn_domain,
+				     remote->ni_nodenum,
+				     &(remote->ni_ipv4_address),
+				     ntohs(remote->ni_ipv4_port),
+				     qn->qn_nodenum, dlm->node_num);
+			if (local && !remote)
+				mlog(ML_ERROR, "Domain %s: Node %d (%pI4:%u) "
+				     "registered in local node %d but not in "
+				     "joining node %d\n", qn->qn_domain,
+				     local->nd_num, &(local->nd_ipv4_address),
+				     ntohs(local->nd_ipv4_port),
+				     dlm->node_num, qn->qn_nodenum);
+			BUG_ON((!local && !remote));
+		}
+
+		if (local)
+			o2nm_node_put(local);
+	}
+
+	return status;
+}
+
+static int dlm_send_nodeinfo(struct dlm_ctxt *dlm, unsigned long *node_map)
+{
+	struct dlm_query_nodeinfo *qn = NULL;
+	struct o2nm_node *node;
+	int ret = 0, status, count, i;
+
+	if (find_next_bit(node_map, O2NM_MAX_NODES, 0) >= O2NM_MAX_NODES)
+		goto bail;
+
+	qn = kzalloc(sizeof(struct dlm_query_nodeinfo), GFP_KERNEL);
+	if (!qn) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto bail;
+	}
+
+	for (i = 0, count = 0; i < O2NM_MAX_NODES; ++i) {
+		node = o2nm_get_node_by_num(i);
+		if (!node)
+			continue;
+		qn->qn_nodes[count].ni_nodenum = node->nd_num;
+		qn->qn_nodes[count].ni_ipv4_port = node->nd_ipv4_port;
+		qn->qn_nodes[count].ni_ipv4_address = node->nd_ipv4_address;
+		mlog(0, "Node %3d, %pI4:%u\n", node->nd_num,
+		     &(node->nd_ipv4_address), ntohs(node->nd_ipv4_port));
+		++count;
+		o2nm_node_put(node);
+	}
+
+	qn->qn_nodenum = dlm->node_num;
+	qn->qn_numnodes = count;
+	qn->qn_namelen = strlen(dlm->name);
+	memcpy(qn->qn_domain, dlm->name, qn->qn_namelen);
+
+	i = -1;
+	while ((i = find_next_bit(node_map, O2NM_MAX_NODES,
+				  i + 1)) < O2NM_MAX_NODES) {
+		if (i == dlm->node_num)
+			continue;
+
+		mlog(0, "Sending nodeinfo to node %d\n", i);
+
+		ret = o2net_send_message(DLM_QUERY_NODEINFO, DLM_MOD_KEY,
+					 qn, sizeof(struct dlm_query_nodeinfo),
+					 i, &status);
+		if (ret >= 0)
+			ret = status;
+		if (ret) {
+			mlog(ML_ERROR, "node mismatch %d, node %d\n", ret, i);
+			break;
+		}
+	}
+
+bail:
+	kfree(qn);
+	return ret;
+}
+
+static int dlm_query_nodeinfo_handler(struct o2net_msg *msg, u32 len,
+				      void *data, void **ret_data)
+{
+	struct dlm_query_nodeinfo *qn;
+	struct dlm_ctxt *dlm = NULL;
+	int locked = 0, status = -EINVAL;
+
+	qn = (struct dlm_query_nodeinfo *) msg->buf;
+
+	mlog(0, "Node %u queries nodes on domain %s\n", qn->qn_nodenum,
+	     qn->qn_domain);
+
+	spin_lock(&dlm_domain_lock);
+	dlm = __dlm_lookup_domain_full(qn->qn_domain, qn->qn_namelen);
+	if (!dlm) {
+		mlog(ML_ERROR, "Node %d queried nodes on domain %s before "
+		     "join domain\n", qn->qn_nodenum, qn->qn_domain);
+		goto bail;
+	}
+
+	spin_lock(&dlm->spinlock);
+	locked = 1;
+	if (dlm->joining_node != qn->qn_nodenum) {
+		mlog(ML_ERROR, "Node %d queried nodes on domain %s but "
+		     "joining node is %d\n", qn->qn_nodenum, qn->qn_domain,
+		     dlm->joining_node);
+		goto bail;
+	}
+
+	/* Support for node query was added in 1.1 */
+	if (dlm->dlm_locking_proto.pv_major == 1 &&
+	    dlm->dlm_locking_proto.pv_minor == 0) {
+		mlog(ML_ERROR, "Node %d queried nodes on domain %s "
+		     "but active dlm protocol is %d.%d\n", qn->qn_nodenum,
+		     qn->qn_domain, dlm->dlm_locking_proto.pv_major,
+		     dlm->dlm_locking_proto.pv_minor);
+		goto bail;
+	}
+
+	status = dlm_match_nodes(dlm, qn);
+
+bail:
+	if (locked)
+		spin_unlock(&dlm->spinlock);
+	spin_unlock(&dlm_domain_lock);
+
+	return status;
+}
+
 static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data,
 				   void **ret_data)
 {
@@ -1240,6 +1611,20 @@
 	set_bit(dlm->node_num, dlm->domain_map);
 	spin_unlock(&dlm->spinlock);
 
+	/* Support for global heartbeat and node info was added in 1.1 */
+	if (dlm_protocol.pv_major > 1 || dlm_protocol.pv_minor > 0) {
+		status = dlm_send_nodeinfo(dlm, ctxt->yes_resp_map);
+		if (status) {
+			mlog_errno(status);
+			goto bail;
+		}
+		status = dlm_send_regions(dlm, ctxt->yes_resp_map);
+		if (status) {
+			mlog_errno(status);
+			goto bail;
+		}
+	}
+
 	dlm_send_join_asserts(dlm, ctxt->yes_resp_map);
 
 	/* Joined state *must* be set before the joining node
@@ -1806,7 +2191,21 @@
 					sizeof(struct dlm_cancel_join),
 					dlm_cancel_join_handler,
 					NULL, NULL, &dlm_join_handlers);
+	if (status)
+		goto bail;
 
+	status = o2net_register_handler(DLM_QUERY_REGION, DLM_MOD_KEY,
+					sizeof(struct dlm_query_region),
+					dlm_query_region_handler,
+					NULL, NULL, &dlm_join_handlers);
+
+	if (status)
+		goto bail;
+
+	status = o2net_register_handler(DLM_QUERY_NODEINFO, DLM_MOD_KEY,
+					sizeof(struct dlm_query_nodeinfo),
+					dlm_query_nodeinfo_handler,
+					NULL, NULL, &dlm_join_handlers);
 bail:
 	if (status < 0)
 		dlm_unregister_net_handlers();
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index ffb4c68..f564b0e 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -3433,3 +3433,43 @@
 	wake_up(&res->wq);
 	wake_up(&dlm->migration_wq);
 }
+
+void dlm_force_free_mles(struct dlm_ctxt *dlm)
+{
+	int i;
+	struct hlist_head *bucket;
+	struct dlm_master_list_entry *mle;
+	struct hlist_node *tmp, *list;
+
+	/*
+	 * We notified all other nodes that we are exiting the domain and
+	 * marked the dlm state to DLM_CTXT_LEAVING. If any mles are still
+	 * around we force free them and wake any processes that are waiting
+	 * on the mles
+	 */
+	spin_lock(&dlm->spinlock);
+	spin_lock(&dlm->master_lock);
+
+	BUG_ON(dlm->dlm_state != DLM_CTXT_LEAVING);
+	BUG_ON((find_next_bit(dlm->domain_map, O2NM_MAX_NODES, 0) < O2NM_MAX_NODES));
+
+	for (i = 0; i < DLM_HASH_BUCKETS; i++) {
+		bucket = dlm_master_hash(dlm, i);
+		hlist_for_each_safe(list, tmp, bucket) {
+			mle = hlist_entry(list, struct dlm_master_list_entry,
+					  master_hash_node);
+			if (mle->type != DLM_MLE_BLOCK) {
+				mlog(ML_ERROR, "bad mle: %p\n", mle);
+				dlm_print_one_mle(mle);
+			}
+			atomic_set(&mle->woken, 1);
+			wake_up(&mle->wq);
+
+			__dlm_unlink_mle(dlm, mle);
+			__dlm_mle_detach_hb_events(dlm, mle);
+			__dlm_put_mle(mle);
+		}
+	}
+	spin_unlock(&dlm->master_lock);
+	spin_unlock(&dlm->spinlock);
+}
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c
index c2903b8..a7ebd9d 100644
--- a/fs/ocfs2/dlmfs/dlmfs.c
+++ b/fs/ocfs2/dlmfs/dlmfs.c
@@ -612,6 +612,7 @@
 	.poll		= dlmfs_file_poll,
 	.read		= dlmfs_file_read,
 	.write		= dlmfs_file_write,
+	.llseek		= default_llseek,
 };
 
 static const struct inode_operations dlmfs_dir_inode_operations = {
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 5e02a89..e8d94d7 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -3635,10 +3635,18 @@
 {
 	struct inode *inode;
 	struct address_space *mapping;
+	struct ocfs2_inode_info *oi;
 
        	inode = ocfs2_lock_res_inode(lockres);
 	mapping = inode->i_mapping;
 
+	if (S_ISDIR(inode->i_mode)) {
+		oi = OCFS2_I(inode);
+		oi->ip_dir_lock_gen++;
+		mlog(0, "generation: %u\n", oi->ip_dir_lock_gen);
+		goto out;
+	}
+
 	if (!S_ISREG(inode->i_mode))
 		goto out;
 
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
index d1ce48e..1d596d8 100644
--- a/fs/ocfs2/dlmglue.h
+++ b/fs/ocfs2/dlmglue.h
@@ -84,6 +84,7 @@
 	OI_LS_PARENT,
 	OI_LS_RENAME1,
 	OI_LS_RENAME2,
+	OI_LS_REFLINK_TARGET,
 };
 
 int ocfs2_dlm_init(struct ocfs2_super *osb);
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 9a03c15..1ca6867 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -64,12 +64,6 @@
 
 #include "buffer_head_io.h"
 
-static int ocfs2_sync_inode(struct inode *inode)
-{
-	filemap_fdatawrite(inode->i_mapping);
-	return sync_mapping_buffers(inode->i_mapping);
-}
-
 static int ocfs2_init_file_private(struct inode *inode, struct file *file)
 {
 	struct ocfs2_file_private *fp;
@@ -180,16 +174,12 @@
 {
 	int err = 0;
 	journal_t *journal;
-	struct dentry *dentry = file->f_path.dentry;
 	struct inode *inode = file->f_mapping->host;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
-	mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", file, dentry, datasync,
-		   dentry->d_name.len, dentry->d_name.name);
-
-	err = ocfs2_sync_inode(dentry->d_inode);
-	if (err)
-		goto bail;
+	mlog_entry("(0x%p, %d, 0x%p, '%.*s')\n", file, datasync,
+		   file->f_path.dentry, file->f_path.dentry->d_name.len,
+		   file->f_path.dentry->d_name.name);
 
 	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) {
 		/*
@@ -197,8 +187,7 @@
 		 * platter
 		 */
 		if (osb->s_mount_opt & OCFS2_MOUNT_BARRIER)
-			blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL,
-					   NULL, BLKDEV_IFL_WAIT);
+			blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 		goto bail;
 	}
 
@@ -370,7 +359,7 @@
 	if (!(ext_flags & OCFS2_EXT_REFCOUNTED))
 		goto out;
 
-	return ocfs2_refcount_cow(inode, fe_bh, cpos, 1, cpos+1);
+	return ocfs2_refcount_cow(inode, NULL, fe_bh, cpos, 1, cpos+1);
 
 out:
 	return status;
@@ -913,8 +902,8 @@
 		zero_clusters = last_cpos - zero_cpos;
 
 	if (needs_cow) {
-		rc = ocfs2_refcount_cow(inode, di_bh, zero_cpos, zero_clusters,
-					UINT_MAX);
+		rc = ocfs2_refcount_cow(inode, NULL, di_bh, zero_cpos,
+					zero_clusters, UINT_MAX);
 		if (rc) {
 			mlog_errno(rc);
 			goto out;
@@ -2062,6 +2051,7 @@
 }
 
 static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
+					    struct file *file,
 					    loff_t pos, size_t count,
 					    int *meta_level)
 {
@@ -2079,7 +2069,7 @@
 
 	*meta_level = 1;
 
-	ret = ocfs2_refcount_cow(inode, di_bh, cpos, clusters, UINT_MAX);
+	ret = ocfs2_refcount_cow(inode, file, di_bh, cpos, clusters, UINT_MAX);
 	if (ret)
 		mlog_errno(ret);
 out:
@@ -2087,7 +2077,7 @@
 	return ret;
 }
 
-static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
+static int ocfs2_prepare_inode_for_write(struct file *file,
 					 loff_t *ppos,
 					 size_t count,
 					 int appending,
@@ -2095,6 +2085,7 @@
 					 int *has_refcount)
 {
 	int ret = 0, meta_level = 0;
+	struct dentry *dentry = file->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
 	loff_t saved_pos, end;
 
@@ -2150,6 +2141,7 @@
 			meta_level = -1;
 
 			ret = ocfs2_prepare_inode_for_refcount(inode,
+							       file,
 							       saved_pos,
 							       count,
 							       &meta_level);
@@ -2232,6 +2224,8 @@
 	struct file *file = iocb->ki_filp;
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	int full_coherency = !(osb->s_mount_opt &
+			       OCFS2_MOUNT_COHERENCY_BUFFERED);
 
 	mlog_entry("(0x%p, %u, '%.*s')\n", file,
 		   (unsigned int)nr_segs,
@@ -2255,16 +2249,39 @@
 		have_alloc_sem = 1;
 	}
 
-	/* concurrent O_DIRECT writes are allowed */
-	rw_level = !direct_io;
+	/*
+	 * Concurrent O_DIRECT writes are allowed with
+	 * mount_option "coherency=buffered".
+	 */
+	rw_level = (!direct_io || full_coherency);
+
 	ret = ocfs2_rw_lock(inode, rw_level);
 	if (ret < 0) {
 		mlog_errno(ret);
 		goto out_sems;
 	}
 
+	/*
+	 * O_DIRECT writes with "coherency=full" need to take EX cluster
+	 * inode_lock to guarantee coherency.
+	 */
+	if (direct_io && full_coherency) {
+		/*
+		 * We need to take and drop the inode lock to force
+		 * other nodes to drop their caches.  Buffered I/O
+		 * already does this in write_begin().
+		 */
+		ret = ocfs2_inode_lock(inode, NULL, 1);
+		if (ret < 0) {
+			mlog_errno(ret);
+			goto out_sems;
+		}
+
+		ocfs2_inode_unlock(inode, 1);
+	}
+
 	can_do_direct = direct_io;
-	ret = ocfs2_prepare_inode_for_write(file->f_path.dentry, ppos,
+	ret = ocfs2_prepare_inode_for_write(file, ppos,
 					    iocb->ki_left, appending,
 					    &can_do_direct, &has_refcount);
 	if (ret < 0) {
@@ -2312,17 +2329,6 @@
 		written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos,
 						    ppos, count, ocount);
 		if (written < 0) {
-			/*
-			 * direct write may have instantiated a few
-			 * blocks outside i_size. Trim these off again.
-			 * Don't need i_size_read because we hold i_mutex.
-			 *
-			 * XXX(truncate): this looks buggy because ocfs2 did not
-			 * actually implement ->truncate.  Take a look at
-			 * the new truncate sequence and update this accordingly
-			 */
-			if (*ppos + count > inode->i_size)
-				truncate_setsize(inode, inode->i_size);
 			ret = written;
 			goto out_dio;
 		}
@@ -2394,7 +2400,7 @@
 {
 	int ret;
 
-	ret = ocfs2_prepare_inode_for_write(out->f_path.dentry,	&sd->pos,
+	ret = ocfs2_prepare_inode_for_write(out, &sd->pos,
 					    sd->total_len, 0, NULL, NULL);
 	if (ret < 0) {
 		mlog_errno(ret);
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index eece3e0..f935fd6 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -335,6 +335,7 @@
 		    else
 			    inode->i_fop = &ocfs2_dops_no_plocks;
 		    i_size_write(inode, le64_to_cpu(fe->i_size));
+		    OCFS2_I(inode)->ip_dir_lock_gen = 1;
 		    break;
 	    case S_IFLNK:
 		    if (ocfs2_inode_is_fast_symlink(inode))
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index 6de5a86..1c508b1 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -46,30 +46,28 @@
 	/* These fields are protected by ip_lock */
 	spinlock_t			ip_lock;
 	u32				ip_open_count;
-	u32				ip_clusters;
 	struct list_head		ip_io_markers;
+	u32				ip_clusters;
 
+	u16				ip_dyn_features;
 	struct mutex			ip_io_mutex;
-
 	u32				ip_flags; /* see below */
 	u32				ip_attr; /* inode attributes */
-	u16				ip_dyn_features;
 
 	/* protected by recovery_lock. */
 	struct inode			*ip_next_orphan;
 
-	u32				ip_dir_start_lookup;
-
 	struct ocfs2_caching_info	ip_metadata_cache;
-
 	struct ocfs2_extent_map		ip_extent_map;
-
 	struct inode			vfs_inode;
 	struct jbd2_inode		ip_jinode;
 
+	u32				ip_dir_start_lookup;
+
 	/* Only valid if the inode is the dir. */
 	u32				ip_last_used_slot;
 	u64				ip_last_used_group;
+	u32				ip_dir_lock_gen;
 
 	struct ocfs2_alloc_reservation	ip_la_data_resv;
 };
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
index 7d9d9c1..7a48681 100644
--- a/fs/ocfs2/ioctl.c
+++ b/fs/ocfs2/ioctl.c
@@ -26,6 +26,26 @@
 
 #include <linux/ext2_fs.h>
 
+#define o2info_from_user(a, b)	\
+		copy_from_user(&(a), (b), sizeof(a))
+#define o2info_to_user(a, b)	\
+		copy_to_user((typeof(a) __user *)b, &(a), sizeof(a))
+
+/*
+ * This call is void because we are already reporting an error that may
+ * be -EFAULT.  The error will be returned from the ioctl(2) call.  It's
+ * just a best-effort to tell userspace that this request caused the error.
+ */
+static inline void __o2info_set_request_error(struct ocfs2_info_request *kreq,
+					struct ocfs2_info_request __user *req)
+{
+	kreq->ir_flags |= OCFS2_INFO_FL_ERROR;
+	(void)put_user(kreq->ir_flags, (__u32 __user *)&(req->ir_flags));
+}
+
+#define o2info_set_request_error(a, b) \
+		__o2info_set_request_error((struct ocfs2_info_request *)&(a), b)
+
 static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
 {
 	int status;
@@ -109,6 +129,328 @@
 	return status;
 }
 
+int ocfs2_info_handle_blocksize(struct inode *inode,
+				struct ocfs2_info_request __user *req)
+{
+	int status = -EFAULT;
+	struct ocfs2_info_blocksize oib;
+
+	if (o2info_from_user(oib, req))
+		goto bail;
+
+	oib.ib_blocksize = inode->i_sb->s_blocksize;
+	oib.ib_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+	if (o2info_to_user(oib, req))
+		goto bail;
+
+	status = 0;
+bail:
+	if (status)
+		o2info_set_request_error(oib, req);
+
+	return status;
+}
+
+int ocfs2_info_handle_clustersize(struct inode *inode,
+				  struct ocfs2_info_request __user *req)
+{
+	int status = -EFAULT;
+	struct ocfs2_info_clustersize oic;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+	if (o2info_from_user(oic, req))
+		goto bail;
+
+	oic.ic_clustersize = osb->s_clustersize;
+	oic.ic_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+	if (o2info_to_user(oic, req))
+		goto bail;
+
+	status = 0;
+bail:
+	if (status)
+		o2info_set_request_error(oic, req);
+
+	return status;
+}
+
+int ocfs2_info_handle_maxslots(struct inode *inode,
+			       struct ocfs2_info_request __user *req)
+{
+	int status = -EFAULT;
+	struct ocfs2_info_maxslots oim;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+	if (o2info_from_user(oim, req))
+		goto bail;
+
+	oim.im_max_slots = osb->max_slots;
+	oim.im_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+	if (o2info_to_user(oim, req))
+		goto bail;
+
+	status = 0;
+bail:
+	if (status)
+		o2info_set_request_error(oim, req);
+
+	return status;
+}
+
+int ocfs2_info_handle_label(struct inode *inode,
+			    struct ocfs2_info_request __user *req)
+{
+	int status = -EFAULT;
+	struct ocfs2_info_label oil;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+	if (o2info_from_user(oil, req))
+		goto bail;
+
+	memcpy(oil.il_label, osb->vol_label, OCFS2_MAX_VOL_LABEL_LEN);
+	oil.il_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+	if (o2info_to_user(oil, req))
+		goto bail;
+
+	status = 0;
+bail:
+	if (status)
+		o2info_set_request_error(oil, req);
+
+	return status;
+}
+
+int ocfs2_info_handle_uuid(struct inode *inode,
+			   struct ocfs2_info_request __user *req)
+{
+	int status = -EFAULT;
+	struct ocfs2_info_uuid oiu;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+	if (o2info_from_user(oiu, req))
+		goto bail;
+
+	memcpy(oiu.iu_uuid_str, osb->uuid_str, OCFS2_TEXT_UUID_LEN + 1);
+	oiu.iu_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+	if (o2info_to_user(oiu, req))
+		goto bail;
+
+	status = 0;
+bail:
+	if (status)
+		o2info_set_request_error(oiu, req);
+
+	return status;
+}
+
+int ocfs2_info_handle_fs_features(struct inode *inode,
+				  struct ocfs2_info_request __user *req)
+{
+	int status = -EFAULT;
+	struct ocfs2_info_fs_features oif;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+	if (o2info_from_user(oif, req))
+		goto bail;
+
+	oif.if_compat_features = osb->s_feature_compat;
+	oif.if_incompat_features = osb->s_feature_incompat;
+	oif.if_ro_compat_features = osb->s_feature_ro_compat;
+	oif.if_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+	if (o2info_to_user(oif, req))
+		goto bail;
+
+	status = 0;
+bail:
+	if (status)
+		o2info_set_request_error(oif, req);
+
+	return status;
+}
+
+int ocfs2_info_handle_journal_size(struct inode *inode,
+				   struct ocfs2_info_request __user *req)
+{
+	int status = -EFAULT;
+	struct ocfs2_info_journal_size oij;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+	if (o2info_from_user(oij, req))
+		goto bail;
+
+	oij.ij_journal_size = osb->journal->j_inode->i_size;
+
+	oij.ij_req.ir_flags |= OCFS2_INFO_FL_FILLED;
+
+	if (o2info_to_user(oij, req))
+		goto bail;
+
+	status = 0;
+bail:
+	if (status)
+		o2info_set_request_error(oij, req);
+
+	return status;
+}
+
+int ocfs2_info_handle_unknown(struct inode *inode,
+			      struct ocfs2_info_request __user *req)
+{
+	int status = -EFAULT;
+	struct ocfs2_info_request oir;
+
+	if (o2info_from_user(oir, req))
+		goto bail;
+
+	oir.ir_flags &= ~OCFS2_INFO_FL_FILLED;
+
+	if (o2info_to_user(oir, req))
+		goto bail;
+
+	status = 0;
+bail:
+	if (status)
+		o2info_set_request_error(oir, req);
+
+	return status;
+}
+
+/*
+ * Validate and distinguish OCFS2_IOC_INFO requests.
+ *
+ * - validate the magic number.
+ * - distinguish different requests.
+ * - validate size of different requests.
+ */
+int ocfs2_info_handle_request(struct inode *inode,
+			      struct ocfs2_info_request __user *req)
+{
+	int status = -EFAULT;
+	struct ocfs2_info_request oir;
+
+	if (o2info_from_user(oir, req))
+		goto bail;
+
+	status = -EINVAL;
+	if (oir.ir_magic != OCFS2_INFO_MAGIC)
+		goto bail;
+
+	switch (oir.ir_code) {
+	case OCFS2_INFO_BLOCKSIZE:
+		if (oir.ir_size == sizeof(struct ocfs2_info_blocksize))
+			status = ocfs2_info_handle_blocksize(inode, req);
+		break;
+	case OCFS2_INFO_CLUSTERSIZE:
+		if (oir.ir_size == sizeof(struct ocfs2_info_clustersize))
+			status = ocfs2_info_handle_clustersize(inode, req);
+		break;
+	case OCFS2_INFO_MAXSLOTS:
+		if (oir.ir_size == sizeof(struct ocfs2_info_maxslots))
+			status = ocfs2_info_handle_maxslots(inode, req);
+		break;
+	case OCFS2_INFO_LABEL:
+		if (oir.ir_size == sizeof(struct ocfs2_info_label))
+			status = ocfs2_info_handle_label(inode, req);
+		break;
+	case OCFS2_INFO_UUID:
+		if (oir.ir_size == sizeof(struct ocfs2_info_uuid))
+			status = ocfs2_info_handle_uuid(inode, req);
+		break;
+	case OCFS2_INFO_FS_FEATURES:
+		if (oir.ir_size == sizeof(struct ocfs2_info_fs_features))
+			status = ocfs2_info_handle_fs_features(inode, req);
+		break;
+	case OCFS2_INFO_JOURNAL_SIZE:
+		if (oir.ir_size == sizeof(struct ocfs2_info_journal_size))
+			status = ocfs2_info_handle_journal_size(inode, req);
+		break;
+	default:
+		status = ocfs2_info_handle_unknown(inode, req);
+		break;
+	}
+
+bail:
+	return status;
+}
+
+int ocfs2_get_request_ptr(struct ocfs2_info *info, int idx,
+			  u64 *req_addr, int compat_flag)
+{
+	int status = -EFAULT;
+	u64 __user *bp = NULL;
+
+	if (compat_flag) {
+#ifdef CONFIG_COMPAT
+		/*
+		 * pointer bp stores the base address of a pointers array,
+		 * which collects all addresses of separate request.
+		 */
+		bp = (u64 __user *)(unsigned long)compat_ptr(info->oi_requests);
+#else
+		BUG();
+#endif
+	} else
+		bp = (u64 __user *)(unsigned long)(info->oi_requests);
+
+	if (o2info_from_user(*req_addr, bp + idx))
+		goto bail;
+
+	status = 0;
+bail:
+	return status;
+}
+
+/*
+ * OCFS2_IOC_INFO handles an array of requests passed from userspace.
+ *
+ * ocfs2_info_handle() recevies a large info aggregation, grab and
+ * validate the request count from header, then break it into small
+ * pieces, later specific handlers can handle them one by one.
+ *
+ * Idea here is to make each separate request small enough to ensure
+ * a better backward&forward compatibility, since a small piece of
+ * request will be less likely to be broken if disk layout get changed.
+ */
+int ocfs2_info_handle(struct inode *inode, struct ocfs2_info *info,
+		      int compat_flag)
+{
+	int i, status = 0;
+	u64 req_addr;
+	struct ocfs2_info_request __user *reqp;
+
+	if ((info->oi_count > OCFS2_INFO_MAX_REQUEST) ||
+	    (!info->oi_requests)) {
+		status = -EINVAL;
+		goto bail;
+	}
+
+	for (i = 0; i < info->oi_count; i++) {
+
+		status = ocfs2_get_request_ptr(info, i, &req_addr, compat_flag);
+		if (status)
+			break;
+
+		reqp = (struct ocfs2_info_request *)(unsigned long)req_addr;
+		if (!reqp) {
+			status = -EINVAL;
+			goto bail;
+		}
+
+		status = ocfs2_info_handle_request(inode, reqp);
+		if (status)
+			break;
+	}
+
+bail:
+	return status;
+}
+
 long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = filp->f_path.dentry->d_inode;
@@ -120,6 +462,7 @@
 	struct reflink_arguments args;
 	const char *old_path, *new_path;
 	bool preserve;
+	struct ocfs2_info info;
 
 	switch (cmd) {
 	case OCFS2_IOC_GETFLAGS:
@@ -174,6 +517,12 @@
 		preserve = (args.preserve != 0);
 
 		return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve);
+	case OCFS2_IOC_INFO:
+		if (copy_from_user(&info, (struct ocfs2_info __user *)arg,
+				   sizeof(struct ocfs2_info)))
+			return -EFAULT;
+
+		return ocfs2_info_handle(inode, &info, 0);
 	default:
 		return -ENOTTY;
 	}
@@ -185,6 +534,7 @@
 	bool preserve;
 	struct reflink_arguments args;
 	struct inode *inode = file->f_path.dentry->d_inode;
+	struct ocfs2_info info;
 
 	switch (cmd) {
 	case OCFS2_IOC32_GETFLAGS:
@@ -209,6 +559,12 @@
 
 		return ocfs2_reflink_ioctl(inode, compat_ptr(args.old_path),
 					   compat_ptr(args.new_path), preserve);
+	case OCFS2_IOC_INFO:
+		if (copy_from_user(&info, (struct ocfs2_info __user *)arg,
+				   sizeof(struct ocfs2_info)))
+			return -EFAULT;
+
+		return ocfs2_info_handle(inode, &info, 1);
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 9b57c03..faa2303 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -301,7 +301,6 @@
 {
 	int status = 0;
 	unsigned int flushed;
-	unsigned long old_id;
 	struct ocfs2_journal *journal = NULL;
 
 	mlog_entry_void();
@@ -326,7 +325,7 @@
 		goto finally;
 	}
 
-	old_id = ocfs2_inc_trans_id(journal);
+	ocfs2_inc_trans_id(journal);
 
 	flushed = atomic_read(&journal->j_num_trans);
 	atomic_set(&journal->j_num_trans, 0);
@@ -342,9 +341,6 @@
 	return status;
 }
 
-/* pass it NULL and it will allocate a new handle object for you.  If
- * you pass it a handle however, it may still return error, in which
- * case it has free'd the passed handle for you. */
 handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs)
 {
 	journal_t *journal = osb->journal->j_journal;
@@ -1888,6 +1884,8 @@
 
 	os = &osb->osb_orphan_scan;
 
+	mlog(0, "Begin orphan scan\n");
+
 	if (atomic_read(&os->os_state) == ORPHAN_SCAN_INACTIVE)
 		goto out;
 
@@ -1920,6 +1918,7 @@
 unlock:
 	ocfs2_orphan_scan_unlock(osb, seqno);
 out:
+	mlog(0, "Orphan scan completed\n");
 	return;
 }
 
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index b5baaa8..43e56b9 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -67,11 +67,12 @@
 	struct buffer_head        *j_bh;      /* Journal disk inode block */
 	atomic_t                  j_num_trans; /* Number of transactions
 					        * currently in the system. */
+	spinlock_t                j_lock;
 	unsigned long             j_trans_id;
 	struct rw_semaphore       j_trans_barrier;
 	wait_queue_head_t         j_checkpointed;
 
-	spinlock_t                j_lock;
+	/* both fields protected by j_lock*/
 	struct list_head          j_la_cleanups;
 	struct work_struct        j_recovery_work;
 };
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index 4c18f4a..7e32db9 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -59,10 +59,11 @@
 	return ret;
 }
 
-static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
+static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh,
 				struct page *page)
 {
 	int ret;
+	struct inode *inode = file->f_path.dentry->d_inode;
 	struct address_space *mapping = inode->i_mapping;
 	loff_t pos = page_offset(page);
 	unsigned int len = PAGE_CACHE_SIZE;
@@ -111,7 +112,7 @@
 	if (page->index == last_index)
 		len = ((size - 1) & ~PAGE_CACHE_MASK) + 1;
 
-	ret = ocfs2_write_begin_nolock(mapping, pos, len, 0, &locked_page,
+	ret = ocfs2_write_begin_nolock(file, mapping, pos, len, 0, &locked_page,
 				       &fsdata, di_bh, page);
 	if (ret) {
 		if (ret != -ENOSPC)
@@ -159,7 +160,7 @@
 	 */
 	down_write(&OCFS2_I(inode)->ip_alloc_sem);
 
-	ret = __ocfs2_page_mkwrite(inode, di_bh, page);
+	ret = __ocfs2_page_mkwrite(vma->vm_file, di_bh, page);
 
 	up_write(&OCFS2_I(inode)->ip_alloc_sem);
 
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index a00dda2..e7bde21 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -171,7 +171,8 @@
 			ret = ERR_PTR(status);
 			goto bail_unlock;
 		}
-	}
+	} else
+		ocfs2_dentry_attach_gen(dentry);
 
 bail_unlock:
 	/* Don't drop the cluster lock until *after* the d_add --
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index c67003b..d840821 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -150,26 +150,33 @@
 struct ocfs2_lock_res {
 	void                    *l_priv;
 	struct ocfs2_lock_res_ops *l_ops;
-	spinlock_t               l_lock;
+
 
 	struct list_head         l_blocked_list;
 	struct list_head         l_mask_waiters;
 
-	enum ocfs2_lock_type     l_type;
 	unsigned long		 l_flags;
 	char                     l_name[OCFS2_LOCK_ID_MAX_LEN];
-	int                      l_level;
 	unsigned int             l_ro_holders;
 	unsigned int             l_ex_holders;
-	struct ocfs2_dlm_lksb    l_lksb;
+	unsigned char            l_level;
+
+	/* Data packed - type enum ocfs2_lock_type */
+	unsigned char            l_type;
 
 	/* used from AST/BAST funcs. */
-	enum ocfs2_ast_action    l_action;
-	enum ocfs2_unlock_action l_unlock_action;
-	int                      l_requested;
-	int                      l_blocking;
+	/* Data packed - enum type ocfs2_ast_action */
+	unsigned char            l_action;
+	/* Data packed - enum type ocfs2_unlock_action */
+	unsigned char            l_unlock_action;
+	unsigned char            l_requested;
+	unsigned char            l_blocking;
 	unsigned int             l_pending_gen;
 
+	spinlock_t               l_lock;
+
+	struct ocfs2_dlm_lksb    l_lksb;
+
 	wait_queue_head_t        l_event;
 
 	struct list_head         l_debug_list;
@@ -243,7 +250,7 @@
 
 enum ocfs2_mount_options
 {
-	OCFS2_MOUNT_HB_LOCAL   = 1 << 0, /* Heartbeat started in local mode */
+	OCFS2_MOUNT_HB_LOCAL = 1 << 0, /* Local heartbeat */
 	OCFS2_MOUNT_BARRIER = 1 << 1,	/* Use block barriers */
 	OCFS2_MOUNT_NOINTR  = 1 << 2,   /* Don't catch signals */
 	OCFS2_MOUNT_ERRORS_PANIC = 1 << 3, /* Panic on errors */
@@ -256,6 +263,10 @@
 						   control lists */
 	OCFS2_MOUNT_USRQUOTA = 1 << 10, /* We support user quotas */
 	OCFS2_MOUNT_GRPQUOTA = 1 << 11, /* We support group quotas */
+	OCFS2_MOUNT_COHERENCY_BUFFERED = 1 << 12, /* Allow concurrent O_DIRECT
+						     writes */
+	OCFS2_MOUNT_HB_NONE = 1 << 13, /* No heartbeat */
+	OCFS2_MOUNT_HB_GLOBAL = 1 << 14, /* Global heartbeat */
 };
 
 #define OCFS2_OSB_SOFT_RO			0x0001
@@ -277,7 +288,8 @@
 	struct super_block *sb;
 	struct inode *root_inode;
 	struct inode *sys_root_inode;
-	struct inode *system_inodes[NUM_SYSTEM_INODES];
+	struct inode *global_system_inodes[NUM_GLOBAL_SYSTEM_INODES];
+	struct inode **local_system_inodes;
 
 	struct ocfs2_slot_info *slot_info;
 
@@ -368,6 +380,8 @@
 	struct ocfs2_alloc_stats alloc_stats;
 	char dev_str[20];		/* "major,minor" of the device */
 
+	u8 osb_stackflags;
+
 	char osb_cluster_stack[OCFS2_STACK_LABEL_LEN + 1];
 	struct ocfs2_cluster_connection *cconn;
 	struct ocfs2_lock_res osb_super_lockres;
@@ -601,10 +615,35 @@
 	return ret;
 }
 
-static inline int ocfs2_userspace_stack(struct ocfs2_super *osb)
+static inline int ocfs2_clusterinfo_valid(struct ocfs2_super *osb)
 {
 	return (osb->s_feature_incompat &
-		OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK);
+		(OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK |
+		 OCFS2_FEATURE_INCOMPAT_CLUSTERINFO));
+}
+
+static inline int ocfs2_userspace_stack(struct ocfs2_super *osb)
+{
+	if (ocfs2_clusterinfo_valid(osb) &&
+	    memcmp(osb->osb_cluster_stack, OCFS2_CLASSIC_CLUSTER_STACK,
+		   OCFS2_STACK_LABEL_LEN))
+		return 1;
+	return 0;
+}
+
+static inline int ocfs2_o2cb_stack(struct ocfs2_super *osb)
+{
+	if (ocfs2_clusterinfo_valid(osb) &&
+	    !memcmp(osb->osb_cluster_stack, OCFS2_CLASSIC_CLUSTER_STACK,
+		   OCFS2_STACK_LABEL_LEN))
+		return 1;
+	return 0;
+}
+
+static inline int ocfs2_cluster_o2cb_global_heartbeat(struct ocfs2_super *osb)
+{
+	return ocfs2_o2cb_stack(osb) &&
+		(osb->osb_stackflags & OCFS2_CLUSTER_O2CB_GLOBAL_HEARTBEAT);
 }
 
 static inline int ocfs2_mount_local(struct ocfs2_super *osb)
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 33f1c9a..c2e4f82 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -101,7 +101,8 @@
 					 | OCFS2_FEATURE_INCOMPAT_META_ECC \
 					 | OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS \
 					 | OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE \
-					 | OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG)
+					 | OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG	\
+					 | OCFS2_FEATURE_INCOMPAT_CLUSTERINFO)
 #define OCFS2_FEATURE_RO_COMPAT_SUPP	(OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \
 					 | OCFS2_FEATURE_RO_COMPAT_USRQUOTA \
 					 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)
@@ -170,6 +171,13 @@
 #define OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG	0x2000
 
 /*
+ * Incompat bit to indicate useable clusterinfo with stackflags for all
+ * cluster stacks (userspace adnd o2cb). If this bit is set,
+ * INCOMPAT_USERSPACE_STACK becomes superfluous and thus should not be set.
+ */
+#define OCFS2_FEATURE_INCOMPAT_CLUSTERINFO	0x4000
+
+/*
  * backup superblock flag is used to indicate that this volume
  * has backup superblocks.
  */
@@ -235,18 +243,31 @@
 #define OCFS2_HAS_REFCOUNT_FL   (0x0010)
 
 /* Inode attributes, keep in sync with EXT2 */
-#define OCFS2_SECRM_FL		(0x00000001)	/* Secure deletion */
-#define OCFS2_UNRM_FL		(0x00000002)	/* Undelete */
-#define OCFS2_COMPR_FL		(0x00000004)	/* Compress file */
-#define OCFS2_SYNC_FL		(0x00000008)	/* Synchronous updates */
-#define OCFS2_IMMUTABLE_FL	(0x00000010)	/* Immutable file */
-#define OCFS2_APPEND_FL		(0x00000020)	/* writes to file may only append */
-#define OCFS2_NODUMP_FL		(0x00000040)	/* do not dump file */
-#define OCFS2_NOATIME_FL	(0x00000080)	/* do not update atime */
-#define OCFS2_DIRSYNC_FL	(0x00010000)	/* dirsync behaviour (directories only) */
+#define OCFS2_SECRM_FL			FS_SECRM_FL	/* Secure deletion */
+#define OCFS2_UNRM_FL			FS_UNRM_FL	/* Undelete */
+#define OCFS2_COMPR_FL			FS_COMPR_FL	/* Compress file */
+#define OCFS2_SYNC_FL			FS_SYNC_FL	/* Synchronous updates */
+#define OCFS2_IMMUTABLE_FL		FS_IMMUTABLE_FL	/* Immutable file */
+#define OCFS2_APPEND_FL			FS_APPEND_FL	/* writes to file may only append */
+#define OCFS2_NODUMP_FL			FS_NODUMP_FL	/* do not dump file */
+#define OCFS2_NOATIME_FL		FS_NOATIME_FL	/* do not update atime */
+/* Reserved for compression usage... */
+#define OCFS2_DIRTY_FL			FS_DIRTY_FL
+#define OCFS2_COMPRBLK_FL		FS_COMPRBLK_FL	/* One or more compressed clusters */
+#define OCFS2_NOCOMP_FL			FS_NOCOMP_FL	/* Don't compress */
+#define OCFS2_ECOMPR_FL			FS_ECOMPR_FL	/* Compression error */
+/* End compression flags --- maybe not all used */
+#define OCFS2_BTREE_FL			FS_BTREE_FL	/* btree format dir */
+#define OCFS2_INDEX_FL			FS_INDEX_FL	/* hash-indexed directory */
+#define OCFS2_IMAGIC_FL			FS_IMAGIC_FL	/* AFS directory */
+#define OCFS2_JOURNAL_DATA_FL		FS_JOURNAL_DATA_FL /* Reserved for ext3 */
+#define OCFS2_NOTAIL_FL			FS_NOTAIL_FL	/* file tail should not be merged */
+#define OCFS2_DIRSYNC_FL		FS_DIRSYNC_FL	/* dirsync behaviour (directories only) */
+#define OCFS2_TOPDIR_FL			FS_TOPDIR_FL	/* Top of directory hierarchies*/
+#define OCFS2_RESERVED_FL		FS_RESERVED_FL	/* reserved for ext2 lib */
 
-#define OCFS2_FL_VISIBLE	(0x000100FF)	/* User visible flags */
-#define OCFS2_FL_MODIFIABLE	(0x000100FF)	/* User modifiable flags */
+#define OCFS2_FL_VISIBLE		FS_FL_USER_VISIBLE	/* User visible flags */
+#define OCFS2_FL_MODIFIABLE		FS_FL_USER_MODIFIABLE	/* User modifiable flags */
 
 /*
  * Extent record flags (e_node.leaf.flags)
@@ -279,10 +300,13 @@
 #define OCFS2_VOL_UUID_LEN		16
 #define OCFS2_MAX_VOL_LABEL_LEN		64
 
-/* The alternate, userspace stack fields */
+/* The cluster stack fields */
 #define OCFS2_STACK_LABEL_LEN		4
 #define OCFS2_CLUSTER_NAME_LEN		16
 
+/* Classic (historically speaking) cluster stack */
+#define OCFS2_CLASSIC_CLUSTER_STACK	"o2cb"
+
 /* Journal limits (in bytes) */
 #define OCFS2_MIN_JOURNAL_SIZE		(4 * 1024 * 1024)
 
@@ -292,6 +316,11 @@
  */
 #define OCFS2_MIN_XATTR_INLINE_SIZE     256
 
+/*
+ * Cluster info flags (ocfs2_cluster_info.ci_stackflags)
+ */
+#define OCFS2_CLUSTER_O2CB_GLOBAL_HEARTBEAT	(0x01)
+
 struct ocfs2_system_inode_info {
 	char	*si_name;
 	int	si_iflags;
@@ -309,6 +338,7 @@
 	USER_QUOTA_SYSTEM_INODE,
 	GROUP_QUOTA_SYSTEM_INODE,
 #define OCFS2_LAST_GLOBAL_SYSTEM_INODE GROUP_QUOTA_SYSTEM_INODE
+#define OCFS2_FIRST_LOCAL_SYSTEM_INODE ORPHAN_DIR_SYSTEM_INODE
 	ORPHAN_DIR_SYSTEM_INODE,
 	EXTENT_ALLOC_SYSTEM_INODE,
 	INODE_ALLOC_SYSTEM_INODE,
@@ -317,8 +347,12 @@
 	TRUNCATE_LOG_SYSTEM_INODE,
 	LOCAL_USER_QUOTA_SYSTEM_INODE,
 	LOCAL_GROUP_QUOTA_SYSTEM_INODE,
+#define OCFS2_LAST_LOCAL_SYSTEM_INODE LOCAL_GROUP_QUOTA_SYSTEM_INODE
 	NUM_SYSTEM_INODES
 };
+#define NUM_GLOBAL_SYSTEM_INODES OCFS2_LAST_GLOBAL_SYSTEM_INODE
+#define NUM_LOCAL_SYSTEM_INODES	\
+		(NUM_SYSTEM_INODES - OCFS2_FIRST_LOCAL_SYSTEM_INODE)
 
 static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
 	/* Global system inodes (single copy) */
@@ -347,6 +381,7 @@
 /* Parameter passed from mount.ocfs2 to module */
 #define OCFS2_HB_NONE			"heartbeat=none"
 #define OCFS2_HB_LOCAL			"heartbeat=local"
+#define OCFS2_HB_GLOBAL			"heartbeat=global"
 
 /*
  * OCFS2 directory file types.  Only the low 3 bits are used.  The
@@ -553,9 +588,21 @@
  */
 };
 
+/*
+ * ci_stackflags is only valid if the incompat bit
+ * OCFS2_FEATURE_INCOMPAT_CLUSTERINFO is set.
+ */
 struct ocfs2_cluster_info {
 /*00*/	__u8   ci_stack[OCFS2_STACK_LABEL_LEN];
-	__le32 ci_reserved;
+	union {
+		__le32 ci_reserved;
+		struct {
+			__u8 ci_stackflags;
+			__u8 ci_reserved1;
+			__u8 ci_reserved2;
+			__u8 ci_reserved3;
+		};
+	};
 /*08*/	__u8   ci_cluster[OCFS2_CLUSTER_NAME_LEN];
 /*18*/
 };
@@ -592,9 +639,9 @@
 					 * group header */
 /*50*/	__u8  s_label[OCFS2_MAX_VOL_LABEL_LEN];	/* Label for mounting, etc. */
 /*90*/	__u8  s_uuid[OCFS2_VOL_UUID_LEN];	/* 128-bit uuid */
-/*A0*/  struct ocfs2_cluster_info s_cluster_info; /* Selected userspace
-						     stack.  Only valid
-						     with INCOMPAT flag. */
+/*A0*/  struct ocfs2_cluster_info s_cluster_info; /* Only valid if either
+						     userspace or clusterinfo
+						     INCOMPAT flag set. */
 /*B8*/	__le16 s_xattr_inline_size;	/* extended attribute inline size
 					   for this fs*/
 	__le16 s_reserved0;
diff --git a/fs/ocfs2/ocfs2_ioctl.h b/fs/ocfs2/ocfs2_ioctl.h
index 2d3420a..b46f39b 100644
--- a/fs/ocfs2/ocfs2_ioctl.h
+++ b/fs/ocfs2/ocfs2_ioctl.h
@@ -23,10 +23,10 @@
 /*
  * ioctl commands
  */
-#define OCFS2_IOC_GETFLAGS	_IOR('f', 1, long)
-#define OCFS2_IOC_SETFLAGS	_IOW('f', 2, long)
-#define OCFS2_IOC32_GETFLAGS	_IOR('f', 1, int)
-#define OCFS2_IOC32_SETFLAGS	_IOW('f', 2, int)
+#define OCFS2_IOC_GETFLAGS	FS_IOC_GETFLAGS
+#define OCFS2_IOC_SETFLAGS	FS_IOC_SETFLAGS
+#define OCFS2_IOC32_GETFLAGS	FS_IOC32_GETFLAGS
+#define OCFS2_IOC32_SETFLAGS	FS_IOC32_SETFLAGS
 
 /*
  * Space reservation / allocation / free ioctls and argument structure
@@ -76,4 +76,99 @@
 };
 #define OCFS2_IOC_REFLINK	_IOW('o', 4, struct reflink_arguments)
 
+/* Following definitions dedicated for ocfs2_info_request ioctls. */
+#define OCFS2_INFO_MAX_REQUEST		(50)
+#define OCFS2_TEXT_UUID_LEN		(OCFS2_VOL_UUID_LEN * 2)
+
+/* Magic number of all requests */
+#define OCFS2_INFO_MAGIC		(0x4F32494E)
+
+/*
+ * Always try to separate info request into small pieces to
+ * guarantee the backward&forward compatibility.
+ */
+struct ocfs2_info {
+	__u64 oi_requests;	/* Array of __u64 pointers to requests */
+	__u32 oi_count;		/* Number of requests in info_requests */
+	__u32 oi_pad;
+};
+
+struct ocfs2_info_request {
+/*00*/	__u32 ir_magic;	/* Magic number */
+	__u32 ir_code;	/* Info request code */
+	__u32 ir_size;	/* Size of request */
+	__u32 ir_flags;	/* Request flags */
+/*10*/			/* Request specific fields */
+};
+
+struct ocfs2_info_clustersize {
+	struct ocfs2_info_request ic_req;
+	__u32 ic_clustersize;
+	__u32 ic_pad;
+};
+
+struct ocfs2_info_blocksize {
+	struct ocfs2_info_request ib_req;
+	__u32 ib_blocksize;
+	__u32 ib_pad;
+};
+
+struct ocfs2_info_maxslots {
+	struct ocfs2_info_request im_req;
+	__u32 im_max_slots;
+	__u32 im_pad;
+};
+
+struct ocfs2_info_label {
+	struct ocfs2_info_request il_req;
+	__u8	il_label[OCFS2_MAX_VOL_LABEL_LEN];
+} __attribute__ ((packed));
+
+struct ocfs2_info_uuid {
+	struct ocfs2_info_request iu_req;
+	__u8	iu_uuid_str[OCFS2_TEXT_UUID_LEN + 1];
+} __attribute__ ((packed));
+
+struct ocfs2_info_fs_features {
+	struct ocfs2_info_request if_req;
+	__u32 if_compat_features;
+	__u32 if_incompat_features;
+	__u32 if_ro_compat_features;
+	__u32 if_pad;
+};
+
+struct ocfs2_info_journal_size {
+	struct ocfs2_info_request ij_req;
+	__u64 ij_journal_size;
+};
+
+/* Codes for ocfs2_info_request */
+enum ocfs2_info_type {
+	OCFS2_INFO_CLUSTERSIZE = 1,
+	OCFS2_INFO_BLOCKSIZE,
+	OCFS2_INFO_MAXSLOTS,
+	OCFS2_INFO_LABEL,
+	OCFS2_INFO_UUID,
+	OCFS2_INFO_FS_FEATURES,
+	OCFS2_INFO_JOURNAL_SIZE,
+	OCFS2_INFO_NUM_TYPES
+};
+
+/* Flags for struct ocfs2_info_request */
+/* Filled by the caller */
+#define OCFS2_INFO_FL_NON_COHERENT	(0x00000001)	/* Cluster coherency not
+							   required. This is a hint.
+							   It is up to ocfs2 whether
+							   the request can be fulfilled
+							   without locking. */
+/* Filled by ocfs2 */
+#define OCFS2_INFO_FL_FILLED		(0x40000000)	/* Filesystem understood
+							   this request and
+							   filled in the answer */
+
+#define OCFS2_INFO_FL_ERROR		(0x80000000)	/* Error happened during
+							   request handling. */
+
+#define OCFS2_IOC_INFO		_IOR('o', 5, struct ocfs2_info)
+
 #endif /* OCFS2_IOCTL_H */
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 0afeda831..b5f9160 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -49,6 +49,7 @@
 
 struct ocfs2_cow_context {
 	struct inode *inode;
+	struct file *file;
 	u32 cow_start;
 	u32 cow_len;
 	struct ocfs2_extent_tree data_et;
@@ -2932,13 +2933,16 @@
 	u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster);
 	struct page *page;
 	pgoff_t page_index;
-	unsigned int from, to;
+	unsigned int from, to, readahead_pages;
 	loff_t offset, end, map_end;
 	struct address_space *mapping = context->inode->i_mapping;
 
 	mlog(0, "old_cluster %u, new %u, len %u at offset %u\n", old_cluster,
 	     new_cluster, new_len, cpos);
 
+	readahead_pages =
+		(ocfs2_cow_contig_clusters(sb) <<
+		 OCFS2_SB(sb)->s_clustersize_bits) >> PAGE_CACHE_SHIFT;
 	offset = ((loff_t)cpos) << OCFS2_SB(sb)->s_clustersize_bits;
 	end = offset + (new_len << OCFS2_SB(sb)->s_clustersize_bits);
 	/*
@@ -2969,6 +2973,14 @@
 		if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize)
 			BUG_ON(PageDirty(page));
 
+		if (PageReadahead(page) && context->file) {
+			page_cache_async_readahead(mapping,
+						   &context->file->f_ra,
+						   context->file,
+						   page, page_index,
+						   readahead_pages);
+		}
+
 		if (!PageUptodate(page)) {
 			ret = block_read_full_page(page, ocfs2_get_block);
 			if (ret) {
@@ -3409,12 +3421,35 @@
 	return ret;
 }
 
+static void ocfs2_readahead_for_cow(struct inode *inode,
+				    struct file *file,
+				    u32 start, u32 len)
+{
+	struct address_space *mapping;
+	pgoff_t index;
+	unsigned long num_pages;
+	int cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits;
+
+	if (!file)
+		return;
+
+	mapping = file->f_mapping;
+	num_pages = (len << cs_bits) >> PAGE_CACHE_SHIFT;
+	if (!num_pages)
+		num_pages = 1;
+
+	index = ((loff_t)start << cs_bits) >> PAGE_CACHE_SHIFT;
+	page_cache_sync_readahead(mapping, &file->f_ra, file,
+				  index, num_pages);
+}
+
 /*
  * Starting at cpos, try to CoW write_len clusters.  Don't CoW
  * past max_cpos.  This will stop when it runs into a hole or an
  * unrefcounted extent.
  */
 static int ocfs2_refcount_cow_hunk(struct inode *inode,
+				   struct file *file,
 				   struct buffer_head *di_bh,
 				   u32 cpos, u32 write_len, u32 max_cpos)
 {
@@ -3443,6 +3478,8 @@
 
 	BUG_ON(cow_len == 0);
 
+	ocfs2_readahead_for_cow(inode, file, cow_start, cow_len);
+
 	context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS);
 	if (!context) {
 		ret = -ENOMEM;
@@ -3464,6 +3501,7 @@
 	context->ref_root_bh = ref_root_bh;
 	context->cow_duplicate_clusters = ocfs2_duplicate_clusters_by_page;
 	context->get_clusters = ocfs2_di_get_clusters;
+	context->file = file;
 
 	ocfs2_init_dinode_extent_tree(&context->data_et,
 				      INODE_CACHE(inode), di_bh);
@@ -3492,6 +3530,7 @@
  * clusters between cpos and cpos+write_len are safe to modify.
  */
 int ocfs2_refcount_cow(struct inode *inode,
+		       struct file *file,
 		       struct buffer_head *di_bh,
 		       u32 cpos, u32 write_len, u32 max_cpos)
 {
@@ -3511,7 +3550,7 @@
 			num_clusters = write_len;
 
 		if (ext_flags & OCFS2_EXT_REFCOUNTED) {
-			ret = ocfs2_refcount_cow_hunk(inode, di_bh, cpos,
+			ret = ocfs2_refcount_cow_hunk(inode, file, di_bh, cpos,
 						      num_clusters, max_cpos);
 			if (ret) {
 				mlog_errno(ret);
@@ -4201,8 +4240,9 @@
 		goto out;
 	}
 
-	mutex_lock(&new_inode->i_mutex);
-	ret = ocfs2_inode_lock(new_inode, &new_bh, 1);
+	mutex_lock_nested(&new_inode->i_mutex, I_MUTEX_CHILD);
+	ret = ocfs2_inode_lock_nested(new_inode, &new_bh, 1,
+				      OI_LS_REFLINK_TARGET);
 	if (ret) {
 		mlog_errno(ret);
 		goto out_unlock;
diff --git a/fs/ocfs2/refcounttree.h b/fs/ocfs2/refcounttree.h
index 9983ba1..c8ce46f7 100644
--- a/fs/ocfs2/refcounttree.h
+++ b/fs/ocfs2/refcounttree.h
@@ -21,14 +21,14 @@
 	struct rb_node rf_node;
 	u64 rf_blkno;
 	u32 rf_generation;
+	struct kref rf_getcnt;
 	struct rw_semaphore rf_sem;
 	struct ocfs2_lock_res rf_lockres;
-	struct kref rf_getcnt;
 	int rf_removed;
 
 	/* the following 4 fields are used by caching_info. */
-	struct ocfs2_caching_info rf_ci;
 	spinlock_t rf_lock;
+	struct ocfs2_caching_info rf_ci;
 	struct mutex rf_io_mutex;
 	struct super_block *rf_sb;
 };
@@ -52,7 +52,8 @@
 					  u32 clusters,
 					  int *credits,
 					  int *ref_blocks);
-int ocfs2_refcount_cow(struct inode *inode, struct buffer_head *di_bh,
+int ocfs2_refcount_cow(struct inode *inode,
+		       struct file *filep, struct buffer_head *di_bh,
 		       u32 cpos, u32 write_len, u32 max_cpos);
 
 typedef int (ocfs2_post_refcount_func)(struct inode *inode,
diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c
index d8b6e42..3e78db3 100644
--- a/fs/ocfs2/reservations.c
+++ b/fs/ocfs2/reservations.c
@@ -732,25 +732,23 @@
 			   struct ocfs2_alloc_reservation *resv,
 			   int *cstart, int *clen)
 {
-	unsigned int wanted = *clen;
-
 	if (resv == NULL || ocfs2_resmap_disabled(resmap))
 		return -ENOSPC;
 
 	spin_lock(&resv_lock);
 
-	/*
-	 * We don't want to over-allocate for temporary
-	 * windows. Otherwise, we run the risk of fragmenting the
-	 * allocation space.
-	 */
-	wanted = ocfs2_resv_window_bits(resmap, resv);
-	if ((resv->r_flags & OCFS2_RESV_FLAG_TMP) || wanted < *clen)
-		wanted = *clen;
-
 	if (ocfs2_resv_empty(resv)) {
-		mlog(0, "empty reservation, find new window\n");
+		/*
+		 * We don't want to over-allocate for temporary
+		 * windows. Otherwise, we run the risk of fragmenting the
+		 * allocation space.
+		 */
+		unsigned int wanted = ocfs2_resv_window_bits(resmap, resv);
 
+		if ((resv->r_flags & OCFS2_RESV_FLAG_TMP) || wanted < *clen)
+			wanted = *clen;
+
+		mlog(0, "empty reservation, find new window\n");
 		/*
 		 * Try to get a window here. If it works, we must fall
 		 * through and test the bitmap . This avoids some
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
index bfbd7e9e..ab4e017 100644
--- a/fs/ocfs2/slot_map.c
+++ b/fs/ocfs2/slot_map.c
@@ -357,7 +357,7 @@
 {
 	int status = 0;
 	u64 blkno;
-	unsigned long long blocks, bytes;
+	unsigned long long blocks, bytes = 0;
 	unsigned int i;
 	struct buffer_head *bh;
 
diff --git a/fs/ocfs2/stack_o2cb.c b/fs/ocfs2/stack_o2cb.c
index 0d3049f..19965b0 100644
--- a/fs/ocfs2/stack_o2cb.c
+++ b/fs/ocfs2/stack_o2cb.c
@@ -283,6 +283,8 @@
 	/* for now we only have one cluster/node, make sure we see it
 	 * in the heartbeat universe */
 	if (!o2hb_check_local_node_heartbeating()) {
+		if (o2hb_global_heartbeat_active())
+			mlog(ML_ERROR, "Global heartbeat not started\n");
 		rc = -EINVAL;
 		goto out;
 	}
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
index 2dc57bc..252e7c8 100644
--- a/fs/ocfs2/stack_user.c
+++ b/fs/ocfs2/stack_user.c
@@ -22,7 +22,6 @@
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/reboot.h>
 #include <asm/uaccess.h>
 
@@ -612,12 +611,10 @@
 		return -ENOMEM;
 	p->op_this_node = -1;
 
-	lock_kernel();
 	mutex_lock(&ocfs2_control_lock);
 	file->private_data = p;
 	list_add(&p->op_list, &ocfs2_control_private_list);
 	mutex_unlock(&ocfs2_control_lock);
-	unlock_kernel();
 
 	return 0;
 }
@@ -628,6 +625,7 @@
 	.read    = ocfs2_control_read,
 	.write   = ocfs2_control_write,
 	.owner   = THIS_MODULE,
+	.llseek  = default_llseek,
 };
 
 static struct miscdevice ocfs2_control_device = {
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index 8a286f5..5fed60d 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -357,7 +357,7 @@
 static void ocfs2_bg_discontig_add_extent(struct ocfs2_super *osb,
 					  struct ocfs2_group_desc *bg,
 					  struct ocfs2_chain_list *cl,
-					  u64 p_blkno, u32 clusters)
+					  u64 p_blkno, unsigned int clusters)
 {
 	struct ocfs2_extent_list *el = &bg->bg_list;
 	struct ocfs2_extent_rec *rec;
@@ -369,7 +369,7 @@
 	rec->e_blkno = cpu_to_le64(p_blkno);
 	rec->e_cpos = cpu_to_le32(le16_to_cpu(bg->bg_bits) /
 				  le16_to_cpu(cl->cl_bpc));
-	rec->e_leaf_clusters = cpu_to_le32(clusters);
+	rec->e_leaf_clusters = cpu_to_le16(clusters);
 	le16_add_cpu(&bg->bg_bits, clusters * le16_to_cpu(cl->cl_bpc));
 	le16_add_cpu(&bg->bg_free_bits_count,
 		     clusters * le16_to_cpu(cl->cl_bpc));
@@ -1380,6 +1380,14 @@
 	}
 
 	le16_add_cpu(&bg->bg_free_bits_count, -num_bits);
+	if (le16_to_cpu(bg->bg_free_bits_count) > le16_to_cpu(bg->bg_bits)) {
+		ocfs2_error(alloc_inode->i_sb, "Group descriptor # %llu has bit"
+			    " count %u but claims %u are freed. num_bits %d",
+			    (unsigned long long)le64_to_cpu(bg->bg_blkno),
+			    le16_to_cpu(bg->bg_bits),
+			    le16_to_cpu(bg->bg_free_bits_count), num_bits);
+		return -EROFS;
+	}
 	while(num_bits--)
 		ocfs2_set_bit(bit_off++, bitmap);
 
@@ -2419,6 +2427,14 @@
 				(unsigned long *) undo_bg->bg_bitmap);
 	}
 	le16_add_cpu(&bg->bg_free_bits_count, num_bits);
+	if (le16_to_cpu(bg->bg_free_bits_count) > le16_to_cpu(bg->bg_bits)) {
+		ocfs2_error(alloc_inode->i_sb, "Group descriptor # %llu has bit"
+			    " count %u but claims %u are freed. num_bits %d",
+			    (unsigned long long)le64_to_cpu(bg->bg_blkno),
+			    le16_to_cpu(bg->bg_bits),
+			    le16_to_cpu(bg->bg_free_bits_count), num_bits);
+		return -EROFS;
+	}
 
 	if (undo_fn)
 		jbd_unlock_bh_state(group_bh);
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index fa1be1b..56f0cb3 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -162,6 +162,7 @@
 	Opt_nointr,
 	Opt_hb_none,
 	Opt_hb_local,
+	Opt_hb_global,
 	Opt_data_ordered,
 	Opt_data_writeback,
 	Opt_atime_quantum,
@@ -177,6 +178,8 @@
 	Opt_noacl,
 	Opt_usrquota,
 	Opt_grpquota,
+	Opt_coherency_buffered,
+	Opt_coherency_full,
 	Opt_resv_level,
 	Opt_dir_resv_level,
 	Opt_err,
@@ -190,6 +193,7 @@
 	{Opt_nointr, "nointr"},
 	{Opt_hb_none, OCFS2_HB_NONE},
 	{Opt_hb_local, OCFS2_HB_LOCAL},
+	{Opt_hb_global, OCFS2_HB_GLOBAL},
 	{Opt_data_ordered, "data=ordered"},
 	{Opt_data_writeback, "data=writeback"},
 	{Opt_atime_quantum, "atime_quantum=%u"},
@@ -205,6 +209,8 @@
 	{Opt_noacl, "noacl"},
 	{Opt_usrquota, "usrquota"},
 	{Opt_grpquota, "grpquota"},
+	{Opt_coherency_buffered, "coherency=buffered"},
+	{Opt_coherency_full, "coherency=full"},
 	{Opt_resv_level, "resv_level=%u"},
 	{Opt_dir_resv_level, "dir_resv_level=%u"},
 	{Opt_err, NULL}
@@ -514,11 +520,11 @@
 
 	mlog_entry_void();
 
-	for (i = 0; i < NUM_SYSTEM_INODES; i++) {
-		inode = osb->system_inodes[i];
+	for (i = 0; i < NUM_GLOBAL_SYSTEM_INODES; i++) {
+		inode = osb->global_system_inodes[i];
 		if (inode) {
 			iput(inode);
-			osb->system_inodes[i] = NULL;
+			osb->global_system_inodes[i] = NULL;
 		}
 	}
 
@@ -534,6 +540,20 @@
 		osb->root_inode = NULL;
 	}
 
+	if (!osb->local_system_inodes)
+		goto out;
+
+	for (i = 0; i < NUM_LOCAL_SYSTEM_INODES * osb->max_slots; i++) {
+		if (osb->local_system_inodes[i]) {
+			iput(osb->local_system_inodes[i]);
+			osb->local_system_inodes[i] = NULL;
+		}
+	}
+
+	kfree(osb->local_system_inodes);
+	osb->local_system_inodes = NULL;
+
+out:
 	mlog_exit(0);
 }
 
@@ -608,8 +628,7 @@
 	int ret = 0;
 	struct mount_options parsed_options;
 	struct ocfs2_super *osb = OCFS2_SB(sb);
-
-	lock_kernel();
+	u32 tmp;
 
 	if (!ocfs2_parse_options(sb, data, &parsed_options, 1) ||
 	    !ocfs2_check_set_options(sb, &parsed_options)) {
@@ -617,8 +636,9 @@
 		goto out;
 	}
 
-	if ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) !=
-	    (parsed_options.mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
+	tmp = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL |
+		OCFS2_MOUNT_HB_NONE;
+	if ((osb->s_mount_opt & tmp) != (parsed_options.mount_opt & tmp)) {
 		ret = -EINVAL;
 		mlog(ML_ERROR, "Cannot change heartbeat mode on remount\n");
 		goto out;
@@ -717,7 +737,6 @@
 							MS_POSIXACL : 0);
 	}
 out:
-	unlock_kernel();
 	return ret;
 }
 
@@ -809,23 +828,29 @@
 
 static int ocfs2_verify_heartbeat(struct ocfs2_super *osb)
 {
-	if (ocfs2_mount_local(osb)) {
-		if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
+	u32 hb_enabled = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL;
+
+	if (osb->s_mount_opt & hb_enabled) {
+		if (ocfs2_mount_local(osb)) {
 			mlog(ML_ERROR, "Cannot heartbeat on a locally "
 			     "mounted device.\n");
 			return -EINVAL;
 		}
-	}
-
-	if (ocfs2_userspace_stack(osb)) {
-		if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
+		if (ocfs2_userspace_stack(osb)) {
 			mlog(ML_ERROR, "Userspace stack expected, but "
 			     "o2cb heartbeat arguments passed to mount\n");
 			return -EINVAL;
 		}
+		if (((osb->s_mount_opt & OCFS2_MOUNT_HB_GLOBAL) &&
+		     !ocfs2_cluster_o2cb_global_heartbeat(osb)) ||
+		    ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) &&
+		     ocfs2_cluster_o2cb_global_heartbeat(osb))) {
+			mlog(ML_ERROR, "Mismatching o2cb heartbeat modes\n");
+			return -EINVAL;
+		}
 	}
 
-	if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
+	if (!(osb->s_mount_opt & hb_enabled)) {
 		if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb) &&
 		    !ocfs2_userspace_stack(osb)) {
 			mlog(ML_ERROR, "Heartbeat has to be started to mount "
@@ -1291,6 +1316,7 @@
 {
 	int status;
 	char *p;
+	u32 tmp;
 
 	mlog_entry("remount: %d, options: \"%s\"\n", is_remount,
 		   options ? options : "(none)");
@@ -1322,7 +1348,10 @@
 			mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL;
 			break;
 		case Opt_hb_none:
-			mopt->mount_opt &= ~OCFS2_MOUNT_HB_LOCAL;
+			mopt->mount_opt |= OCFS2_MOUNT_HB_NONE;
+			break;
+		case Opt_hb_global:
+			mopt->mount_opt |= OCFS2_MOUNT_HB_GLOBAL;
 			break;
 		case Opt_barrier:
 			if (match_int(&args[0], &option)) {
@@ -1438,6 +1467,12 @@
 		case Opt_grpquota:
 			mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA;
 			break;
+		case Opt_coherency_buffered:
+			mopt->mount_opt |= OCFS2_MOUNT_COHERENCY_BUFFERED;
+			break;
+		case Opt_coherency_full:
+			mopt->mount_opt &= ~OCFS2_MOUNT_COHERENCY_BUFFERED;
+			break;
 		case Opt_acl:
 			mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL;
 			mopt->mount_opt &= ~OCFS2_MOUNT_NO_POSIX_ACL;
@@ -1477,6 +1512,15 @@
 		}
 	}
 
+	/* Ensure only one heartbeat mode */
+	tmp = mopt->mount_opt & (OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL |
+				 OCFS2_MOUNT_HB_NONE);
+	if (hweight32(tmp) != 1) {
+		mlog(ML_ERROR, "Invalid heartbeat mount options\n");
+		status = 0;
+		goto bail;
+	}
+
 	status = 1;
 
 bail:
@@ -1490,10 +1534,14 @@
 	unsigned long opts = osb->s_mount_opt;
 	unsigned int local_alloc_megs;
 
-	if (opts & OCFS2_MOUNT_HB_LOCAL)
-		seq_printf(s, ",_netdev,heartbeat=local");
-	else
-		seq_printf(s, ",heartbeat=none");
+	if (opts & (OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL)) {
+		seq_printf(s, ",_netdev");
+		if (opts & OCFS2_MOUNT_HB_LOCAL)
+			seq_printf(s, ",%s", OCFS2_HB_LOCAL);
+		else
+			seq_printf(s, ",%s", OCFS2_HB_GLOBAL);
+	} else
+		seq_printf(s, ",%s", OCFS2_HB_NONE);
 
 	if (opts & OCFS2_MOUNT_NOINTR)
 		seq_printf(s, ",nointr");
@@ -1536,6 +1584,11 @@
 	if (opts & OCFS2_MOUNT_GRPQUOTA)
 		seq_printf(s, ",grpquota");
 
+	if (opts & OCFS2_MOUNT_COHERENCY_BUFFERED)
+		seq_printf(s, ",coherency=buffered");
+	else
+		seq_printf(s, ",coherency=full");
+
 	if (opts & OCFS2_MOUNT_NOUSERXATTR)
 		seq_printf(s, ",nouser_xattr");
 	else
@@ -1640,13 +1693,9 @@
 {
 	mlog_entry("(0x%p)\n", sb);
 
-	lock_kernel();
-
 	ocfs2_sync_blockdev(sb);
 	ocfs2_dismount_volume(sb, 0);
 
-	unlock_kernel();
-
 	mlog_exit_void();
 }
 
@@ -1990,6 +2039,36 @@
 	return 0;
 }
 
+/* Make sure entire volume is addressable by our journal.  Requires
+   osb_clusters_at_boot to be valid and for the journal to have been
+   initialized by ocfs2_journal_init(). */
+static int ocfs2_journal_addressable(struct ocfs2_super *osb)
+{
+	int status = 0;
+	u64 max_block =
+		ocfs2_clusters_to_blocks(osb->sb,
+					 osb->osb_clusters_at_boot) - 1;
+
+	/* 32-bit block number is always OK. */
+	if (max_block <= (u32)~0ULL)
+		goto out;
+
+	/* Volume is "huge", so see if our journal is new enough to
+	   support it. */
+	if (!(OCFS2_HAS_COMPAT_FEATURE(osb->sb,
+				       OCFS2_FEATURE_COMPAT_JBD2_SB) &&
+	      jbd2_journal_check_used_features(osb->journal->j_journal, 0, 0,
+					       JBD2_FEATURE_INCOMPAT_64BIT))) {
+		mlog(ML_ERROR, "The journal cannot address the entire volume. "
+		     "Enable the 'block64' journal option with tunefs.ocfs2");
+		status = -EFBIG;
+		goto out;
+	}
+
+ out:
+	return status;
+}
+
 static int ocfs2_initialize_super(struct super_block *sb,
 				  struct buffer_head *bh,
 				  int sector_size,
@@ -2002,6 +2081,7 @@
 	struct ocfs2_journal *journal;
 	__le32 uuid_net_key;
 	struct ocfs2_super *osb;
+	u64 total_blocks;
 
 	mlog_entry_void();
 
@@ -2060,6 +2140,15 @@
 	snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
 		 MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
 
+	osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots);
+	if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) {
+		mlog(ML_ERROR, "Invalid number of node slots (%u)\n",
+		     osb->max_slots);
+		status = -EINVAL;
+		goto bail;
+	}
+	mlog(0, "max_slots for this device: %u\n", osb->max_slots);
+
 	ocfs2_orphan_scan_init(osb);
 
 	status = ocfs2_recovery_init(osb);
@@ -2098,15 +2187,6 @@
 		goto bail;
 	}
 
-	osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots);
-	if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) {
-		mlog(ML_ERROR, "Invalid number of node slots (%u)\n",
-		     osb->max_slots);
-		status = -EINVAL;
-		goto bail;
-	}
-	mlog(0, "max_slots for this device: %u\n", osb->max_slots);
-
 	osb->slot_recovery_generations =
 		kcalloc(osb->max_slots, sizeof(*osb->slot_recovery_generations),
 			GFP_KERNEL);
@@ -2149,7 +2229,9 @@
 		goto bail;
 	}
 
-	if (ocfs2_userspace_stack(osb)) {
+	if (ocfs2_clusterinfo_valid(osb)) {
+		osb->osb_stackflags =
+			OCFS2_RAW_SB(di)->s_cluster_info.ci_stackflags;
 		memcpy(osb->osb_cluster_stack,
 		       OCFS2_RAW_SB(di)->s_cluster_info.ci_stack,
 		       OCFS2_STACK_LABEL_LEN);
@@ -2214,11 +2296,15 @@
 		goto bail;
 	}
 
-	if (ocfs2_clusters_to_blocks(osb->sb, le32_to_cpu(di->i_clusters) - 1)
-	    > (u32)~0UL) {
-		mlog(ML_ERROR, "Volume might try to write to blocks beyond "
-		     "what jbd can address in 32 bits.\n");
-		status = -EINVAL;
+	total_blocks = ocfs2_clusters_to_blocks(osb->sb,
+						le32_to_cpu(di->i_clusters));
+
+	status = generic_check_addressable(osb->sb->s_blocksize_bits,
+					   total_blocks);
+	if (status) {
+		mlog(ML_ERROR, "Volume too large "
+		     "to mount safely on this system");
+		status = -EFBIG;
 		goto bail;
 	}
 
@@ -2380,6 +2466,12 @@
 		goto finally;
 	}
 
+	/* Now that journal has been initialized, check to make sure
+	   entire volume is addressable. */
+	status = ocfs2_journal_addressable(osb);
+	if (status)
+		goto finally;
+
 	/* If the journal was unmounted cleanly then we don't want to
 	 * recover anything. Otherwise, journal_load will do that
 	 * dirty work for us :) */
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index 32499d21..9975457 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -128,7 +128,7 @@
 	}
 
 	/* Fast symlinks can't be large */
-	len = strlen(target);
+	len = strnlen(target, ocfs2_fast_symlink_chars(inode->i_sb));
 	link = kzalloc(len + 1, GFP_NOFS);
 	if (!link) {
 		status = -ENOMEM;
diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c
index bfe7190..902efb2 100644
--- a/fs/ocfs2/sysfile.c
+++ b/fs/ocfs2/sysfile.c
@@ -44,11 +44,6 @@
 						   int type,
 						   u32 slot);
 
-static inline int is_global_system_inode(int type);
-static inline int is_in_system_inode_array(struct ocfs2_super *osb,
-					   int type,
-					   u32 slot);
-
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 static struct lock_class_key ocfs2_sysfile_cluster_lock_key[NUM_SYSTEM_INODES];
 #endif
@@ -59,11 +54,52 @@
 		type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE;
 }
 
-static inline int is_in_system_inode_array(struct ocfs2_super *osb,
-					   int type,
-					   u32 slot)
+static struct inode **get_local_system_inode(struct ocfs2_super *osb,
+					     int type,
+					     u32 slot)
 {
-	return slot == osb->slot_num || is_global_system_inode(type);
+	int index;
+	struct inode **local_system_inodes, **free = NULL;
+
+	BUG_ON(slot == OCFS2_INVALID_SLOT);
+	BUG_ON(type < OCFS2_FIRST_LOCAL_SYSTEM_INODE ||
+	       type > OCFS2_LAST_LOCAL_SYSTEM_INODE);
+
+	spin_lock(&osb->osb_lock);
+	local_system_inodes = osb->local_system_inodes;
+	spin_unlock(&osb->osb_lock);
+
+	if (unlikely(!local_system_inodes)) {
+		local_system_inodes = kzalloc(sizeof(struct inode *) *
+					      NUM_LOCAL_SYSTEM_INODES *
+					      osb->max_slots,
+					      GFP_NOFS);
+		if (!local_system_inodes) {
+			mlog_errno(-ENOMEM);
+			/*
+			 * return NULL here so that ocfs2_get_sytem_file_inodes
+			 * will try to create an inode and use it. We will try
+			 * to initialize local_system_inodes next time.
+			 */
+			return NULL;
+		}
+
+		spin_lock(&osb->osb_lock);
+		if (osb->local_system_inodes) {
+			/* Someone has initialized it for us. */
+			free = local_system_inodes;
+			local_system_inodes = osb->local_system_inodes;
+		} else
+			osb->local_system_inodes = local_system_inodes;
+		spin_unlock(&osb->osb_lock);
+		if (unlikely(free))
+			kfree(free);
+	}
+
+	index = (slot * NUM_LOCAL_SYSTEM_INODES) +
+		(type - OCFS2_FIRST_LOCAL_SYSTEM_INODE);
+
+	return &local_system_inodes[index];
 }
 
 struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
@@ -74,8 +110,10 @@
 	struct inode **arr = NULL;
 
 	/* avoid the lookup if cached in local system file array */
-	if (is_in_system_inode_array(osb, type, slot))
-		arr = &(osb->system_inodes[type]);
+	if (is_global_system_inode(type)) {
+		arr = &(osb->global_system_inodes[type]);
+	} else
+		arr = get_local_system_inode(osb, type, slot);
 
 	if (arr && ((inode = *arr) != NULL)) {
 		/* get a ref in addition to the array ref */
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index d03469f..67cd439 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -1286,13 +1286,11 @@
 	xis.inode_bh = xbs.inode_bh = di_bh;
 	di = (struct ocfs2_dinode *)di_bh->b_data;
 
-	down_read(&oi->ip_xattr_sem);
 	ret = ocfs2_xattr_ibody_get(inode, name_index, name, buffer,
 				    buffer_size, &xis);
 	if (ret == -ENODATA && di->i_xattr_loc)
 		ret = ocfs2_xattr_block_get(inode, name_index, name, buffer,
 					    buffer_size, &xbs);
-	up_read(&oi->ip_xattr_sem);
 
 	return ret;
 }
@@ -1316,8 +1314,10 @@
 		mlog_errno(ret);
 		return ret;
 	}
+	down_read(&OCFS2_I(inode)->ip_xattr_sem);
 	ret = ocfs2_xattr_get_nolock(inode, di_bh, name_index,
 				     name, buffer, buffer_size);
+	up_read(&OCFS2_I(inode)->ip_xattr_sem);
 
 	ocfs2_inode_unlock(inode, 0);
 
@@ -7081,7 +7081,7 @@
 		goto out;
 	}
 
-	if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED))
+	if (!indexed)
 		ret = ocfs2_reflink_xattr_block(args, blk_bh, new_blk_bh);
 	else
 		ret = ocfs2_reflink_xattr_tree(args, blk_bh, new_blk_bh);
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 79fbf3f..b81bfc0 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -352,6 +352,7 @@
 {
 	struct hd_struct *p = dev_to_part(dev);
 	free_part_stats(p);
+	free_part_info(p);
 	kfree(p);
 }
 
@@ -364,17 +365,25 @@
 static void delete_partition_rcu_cb(struct rcu_head *head)
 {
 	struct hd_struct *part = container_of(head, struct hd_struct, rcu_head);
+	struct gendisk *disk = part_to_disk(part);
+	struct request_queue *q = disk->queue;
+	unsigned long flags;
 
 	part->start_sect = 0;
 	part->nr_sects = 0;
 	part_stat_set_all(part, 0);
 	put_device(part_to_dev(part));
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	elv_quiesce_end(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
 void delete_partition(struct gendisk *disk, int partno)
 {
 	struct disk_part_tbl *ptbl = disk->part_tbl;
 	struct hd_struct *part;
+	struct request_queue *q = disk->queue;
 
 	if (partno >= ptbl->len)
 		return;
@@ -389,6 +398,10 @@
 	kobject_put(part->holder_dir);
 	device_del(part_to_dev(part));
 
+	spin_lock_irq(q->queue_lock);
+	elv_quiesce_start(q);
+	spin_unlock_irq(q->queue_lock);
+
 	call_rcu(&part->rcu_head, delete_partition_rcu_cb);
 }
 
@@ -401,7 +414,8 @@
 		   whole_disk_show, NULL);
 
 struct hd_struct *add_partition(struct gendisk *disk, int partno,
-				sector_t start, sector_t len, int flags)
+				sector_t start, sector_t len, int flags,
+				struct partition_meta_info *info)
 {
 	struct hd_struct *p;
 	dev_t devt = MKDEV(0, 0);
@@ -438,6 +452,14 @@
 	p->partno = partno;
 	p->policy = get_disk_ro(disk);
 
+	if (info) {
+		struct partition_meta_info *pinfo = alloc_part_info(disk);
+		if (!pinfo)
+			goto out_free_stats;
+		memcpy(pinfo, info, sizeof(*info));
+		p->info = pinfo;
+	}
+
 	dname = dev_name(ddev);
 	if (isdigit(dname[strlen(dname) - 1]))
 		dev_set_name(pdev, "%sp%d", dname, partno);
@@ -451,7 +473,7 @@
 
 	err = blk_alloc_devt(p, &devt);
 	if (err)
-		goto out_free_stats;
+		goto out_free_info;
 	pdev->devt = devt;
 
 	/* delay uevent until 'holders' subdir is created */
@@ -481,6 +503,8 @@
 
 	return p;
 
+out_free_info:
+	free_part_info(p);
 out_free_stats:
 	free_part_stats(p);
 out_free:
@@ -513,14 +537,14 @@
 
 	if (device_add(ddev))
 		return;
-#ifndef CONFIG_SYSFS_DEPRECATED
-	err = sysfs_create_link(block_depr, &ddev->kobj,
-				kobject_name(&ddev->kobj));
-	if (err) {
-		device_del(ddev);
-		return;
+	if (!sysfs_deprecated) {
+		err = sysfs_create_link(block_depr, &ddev->kobj,
+					kobject_name(&ddev->kobj));
+		if (err) {
+			device_del(ddev);
+			return;
+		}
 	}
-#endif
 	disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
 	disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
 
@@ -642,6 +666,7 @@
 	/* add partitions */
 	for (p = 1; p < state->limit; p++) {
 		sector_t size, from;
+		struct partition_meta_info *info = NULL;
 
 		size = state->parts[p].size;
 		if (!size)
@@ -675,8 +700,12 @@
 				size = get_capacity(disk) - from;
 			}
 		}
+
+		if (state->parts[p].has_info)
+			info = &state->parts[p].info;
 		part = add_partition(disk, p, from, size,
-				     state->parts[p].flags);
+				     state->parts[p].flags,
+				     &state->parts[p].info);
 		if (IS_ERR(part)) {
 			printk(KERN_ERR " %s: p%d could not be added: %ld\n",
 			       disk->disk_name, p, -PTR_ERR(part));
@@ -737,8 +766,7 @@
 	kobject_put(disk->part0.holder_dir);
 	kobject_put(disk->slave_dir);
 	disk->driverfs_dev = NULL;
-#ifndef CONFIG_SYSFS_DEPRECATED
-	sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
-#endif
+	if (!sysfs_deprecated)
+		sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
 	device_del(disk_to_dev(disk));
 }
diff --git a/fs/partitions/check.h b/fs/partitions/check.h
index 8e4e103..d68bf4d 100644
--- a/fs/partitions/check.h
+++ b/fs/partitions/check.h
@@ -1,5 +1,6 @@
 #include <linux/pagemap.h>
 #include <linux/blkdev.h>
+#include <linux/genhd.h>
 
 /*
  * add_gd_partition adds a partitions details to the devices partition
@@ -12,6 +13,8 @@
 		sector_t from;
 		sector_t size;
 		int flags;
+		bool has_info;
+		struct partition_meta_info info;
 	} parts[DISK_MAX_PARTS];
 	int next;
 	int limit;
diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c
index dbb44d4..ac0ccb5 100644
--- a/fs/partitions/efi.c
+++ b/fs/partitions/efi.c
@@ -94,6 +94,7 @@
  *
  ************************************************************/
 #include <linux/crc32.h>
+#include <linux/ctype.h>
 #include <linux/math64.h>
 #include <linux/slab.h>
 #include "check.h"
@@ -604,6 +605,7 @@
 	gpt_entry *ptes = NULL;
 	u32 i;
 	unsigned ssz = bdev_logical_block_size(state->bdev) / 512;
+	u8 unparsed_guid[37];
 
 	if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) {
 		kfree(gpt);
@@ -614,6 +616,9 @@
 	pr_debug("GUID Partition Table is valid!  Yea!\n");
 
 	for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
+		struct partition_meta_info *info;
+		unsigned label_count = 0;
+		unsigned label_max;
 		u64 start = le64_to_cpu(ptes[i].starting_lba);
 		u64 size = le64_to_cpu(ptes[i].ending_lba) -
 			   le64_to_cpu(ptes[i].starting_lba) + 1ULL;
@@ -627,6 +632,26 @@
 		if (!efi_guidcmp(ptes[i].partition_type_guid,
 				 PARTITION_LINUX_RAID_GUID))
 			state->parts[i + 1].flags = ADDPART_FLAG_RAID;
+
+		info = &state->parts[i + 1].info;
+		/* Instead of doing a manual swap to big endian, reuse the
+		 * common ASCII hex format as the interim.
+		 */
+		efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid);
+		part_pack_uuid(unparsed_guid, info->uuid);
+
+		/* Naively convert UTF16-LE to 7 bits. */
+		label_max = min(sizeof(info->volname) - 1,
+				sizeof(ptes[i].partition_name));
+		info->volname[label_max] = 0;
+		while (label_count < label_max) {
+			u8 c = ptes[i].partition_name[label_count] & 0xff;
+			if (c && !isprint(c))
+				c = '!';
+			info->volname[label_count] = c;
+			label_count++;
+		}
+		state->parts[i + 1].has_info = true;
 	}
 	kfree(ptes);
 	kfree(gpt);
diff --git a/fs/pipe.c b/fs/pipe.c
index 279eef9..37eb1eb 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -382,7 +382,7 @@
 			error = ops->confirm(pipe, buf);
 			if (error) {
 				if (!ret)
-					error = ret;
+					ret = error;
 				break;
 			}
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a1c43e7..dc5d5f5 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1151,6 +1151,7 @@
 static const struct file_operations proc_oom_score_adj_operations = {
 	.read		= oom_score_adj_read,
 	.write		= oom_score_adj_write,
+	.llseek		= default_llseek,
 };
 
 #ifdef CONFIG_AUDITSYSCALL
@@ -2039,11 +2040,13 @@
 static const struct file_operations proc_fdinfo_file_operations = {
 	.open           = nonseekable_open,
 	.read		= proc_fdinfo_read,
+	.llseek		= no_llseek,
 };
 
 static const struct file_operations proc_fd_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_readfd,
+	.llseek		= default_llseek,
 };
 
 /*
@@ -2112,6 +2115,7 @@
 static const struct file_operations proc_fdinfo_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_readfdinfo,
+	.llseek		= default_llseek,
 };
 
 /*
@@ -2343,6 +2347,7 @@
 static const struct file_operations proc_attr_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_attr_dir_readdir,
+	.llseek		= default_llseek,
 };
 
 static struct dentry *proc_attr_dir_lookup(struct inode *dir,
@@ -2675,7 +2680,7 @@
 	INF("auxv",       S_IRUSR, proc_pid_auxv),
 	ONE("status",     S_IRUGO, proc_pid_status),
 	ONE("personality", S_IRUSR, proc_pid_personality),
-	INF("limits",	  S_IRUSR, proc_pid_limits),
+	INF("limits",	  S_IRUGO, proc_pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
 	REG("sched",      S_IRUGO|S_IWUSR, proc_pid_sched_operations),
 #endif
@@ -2751,6 +2756,7 @@
 static const struct file_operations proc_tgid_base_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_tgid_base_readdir,
+	.llseek		= default_llseek,
 };
 
 static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
@@ -3011,7 +3017,7 @@
 	INF("auxv",      S_IRUSR, proc_pid_auxv),
 	ONE("status",    S_IRUGO, proc_pid_status),
 	ONE("personality", S_IRUSR, proc_pid_personality),
-	INF("limits",	 S_IRUSR, proc_pid_limits),
+	INF("limits",	 S_IRUGO, proc_pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
 	REG("sched",     S_IRUGO|S_IWUSR, proc_pid_sched_operations),
 #endif
@@ -3088,6 +3094,7 @@
 static const struct file_operations proc_tid_base_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_tid_base_readdir,
+	.llseek		= default_llseek,
 };
 
 static const struct inode_operations proc_tid_base_inode_operations = {
@@ -3324,4 +3331,5 @@
 static const struct file_operations proc_task_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_task_readdir,
+	.llseek		= default_llseek,
 };
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 5be436e..2fc5255 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -364,6 +364,7 @@
 static const struct file_operations proc_sys_file_operations = {
 	.read		= proc_sys_read,
 	.write		= proc_sys_write,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_sys_dir_file_operations = {
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 4258384..93d99b3 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -179,6 +179,7 @@
 static const struct file_operations proc_root_operations = {
 	.read		 = generic_read_dir,
 	.readdir	 = proc_root_readdir,
+	.llseek		= default_llseek,
 };
 
 /*
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 1dbca4e8..871e25e 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -539,6 +539,7 @@
 
 const struct file_operations proc_clear_refs_operations = {
 	.write		= clear_refs_write,
+	.llseek		= noop_llseek,
 };
 
 struct pagemapread {
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index 6e8fc62..7b03294 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -11,7 +11,6 @@
  * 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support.
  */
 
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include "qnx4.h"
 
@@ -29,8 +28,6 @@
 	QNX4DEBUG((KERN_INFO "qnx4_readdir:i_size = %ld\n", (long) inode->i_size));
 	QNX4DEBUG((KERN_INFO "filp->f_pos         = %ld\n", (long) filp->f_pos));
 
-	lock_kernel();
-
 	while (filp->f_pos < inode->i_size) {
 		blknum = qnx4_block_map( inode, filp->f_pos >> QNX4_BLOCK_SIZE_BITS );
 		bh = sb_bread(inode->i_sb, blknum);
@@ -71,7 +68,6 @@
 		brelse(bh);
 	}
 out:
-	unlock_kernel();
 	return 0;
 }
 
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 1682972..01bad30 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/highuid.h>
-#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
@@ -157,8 +156,6 @@
 	struct super_block *sb = dentry->d_sb;
 	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
-	lock_kernel();
-
 	buf->f_type    = sb->s_magic;
 	buf->f_bsize   = sb->s_blocksize;
 	buf->f_blocks  = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size) * 8;
@@ -168,8 +165,6 @@
 	buf->f_fsid.val[0] = (u32)id;
 	buf->f_fsid.val[1] = (u32)(id >> 32);
 
-	unlock_kernel();
-
 	return 0;
 }
 
@@ -283,7 +278,6 @@
  		goto outi;
 
 	brelse(bh);
-
 	return 0;
 
       outi:
diff --git a/fs/qnx4/namei.c b/fs/qnx4/namei.c
index 58703eb..275327b 100644
--- a/fs/qnx4/namei.c
+++ b/fs/qnx4/namei.c
@@ -12,7 +12,6 @@
  * 04-07-1998 by Frank Denis : first step for rmdir/unlink.
  */
 
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include "qnx4.h"
 
@@ -109,7 +108,6 @@
 	int len = dentry->d_name.len;
 	struct inode *foundinode = NULL;
 
-	lock_kernel();
 	if (!(bh = qnx4_find_entry(len, dir, name, &de, &ino)))
 		goto out;
 	/* The entry is linked, let's get the real info */
@@ -123,13 +121,11 @@
 
 	foundinode = qnx4_iget(dir->i_sb, ino);
 	if (IS_ERR(foundinode)) {
-		unlock_kernel();
 		QNX4DEBUG((KERN_ERR "qnx4: lookup->iget -> error %ld\n",
 			   PTR_ERR(foundinode)));
 		return ERR_CAST(foundinode);
 	}
 out:
-	unlock_kernel();
 	d_add(dentry, foundinode);
 
 	return NULL;
diff --git a/fs/read_write.c b/fs/read_write.c
index 74e3658..e757ef2 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -124,7 +124,7 @@
 {
 	loff_t retval;
 
-	lock_kernel();
+	mutex_lock(&file->f_dentry->d_inode->i_mutex);
 	switch (origin) {
 		case SEEK_END:
 			offset += i_size_read(file->f_path.dentry->d_inode);
@@ -145,7 +145,7 @@
 		retval = offset;
 	}
 out:
-	unlock_kernel();
+	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
 	return retval;
 }
 EXPORT_SYMBOL(default_llseek);
@@ -156,7 +156,6 @@
 
 	fn = no_llseek;
 	if (file->f_mode & FMODE_LSEEK) {
-		fn = default_llseek;
 		if (file->f_op && file->f_op->llseek)
 			fn = file->f_op->llseek;
 	}
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 6846371..91f080c 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -152,8 +152,7 @@
 	barrier_done = reiserfs_commit_for_inode(inode);
 	reiserfs_write_unlock(inode->i_sb);
 	if (barrier_done != 1 && reiserfs_barrier_flush(inode->i_sb))
-		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL, 
-			BLKDEV_IFL_WAIT);
+		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 	if (barrier_done < 0)
 		return barrier_done;
 	return (err < 0) ? -EIO : 0;
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index f53505d..5cbb81e 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -170,6 +170,7 @@
 int reiserfs_unpack(struct inode *inode, struct file *filp)
 {
 	int retval = 0;
+	int depth;
 	int index;
 	struct page *page;
 	struct address_space *mapping;
@@ -188,8 +189,8 @@
 	/* we need to make sure nobody is changing the file size beneath
 	 ** us
 	 */
-	mutex_lock(&inode->i_mutex);
-	reiserfs_write_lock(inode->i_sb);
+	reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb);
+	depth = reiserfs_write_lock_once(inode->i_sb);
 
 	write_from = inode->i_size & (blocksize - 1);
 	/* if we are on a block boundary, we are already unpacked.  */
@@ -224,6 +225,6 @@
 
       out:
 	mutex_unlock(&inode->i_mutex);
-	reiserfs_write_unlock(inode->i_sb);
+	reiserfs_write_unlock_once(inode->i_sb, depth);
 	return retval;
 }
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 812e2c0..076c8b19 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -138,13 +138,6 @@
 	return 0;
 }
 
-static void disable_barrier(struct super_block *s)
-{
-	REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_BARRIER_FLUSH);
-	printk("reiserfs: disabling flush barriers on %s\n",
-	       reiserfs_bdevname(s));
-}
-
 static struct reiserfs_bitmap_node *allocate_bitmap_node(struct super_block
 							 *sb)
 {
@@ -677,30 +670,6 @@
 	submit_bh(WRITE, bh);
 }
 
-static int submit_barrier_buffer(struct buffer_head *bh)
-{
-	get_bh(bh);
-	bh->b_end_io = reiserfs_end_ordered_io;
-	clear_buffer_dirty(bh);
-	if (!buffer_uptodate(bh))
-		BUG();
-	return submit_bh(WRITE_BARRIER, bh);
-}
-
-static void check_barrier_completion(struct super_block *s,
-				     struct buffer_head *bh)
-{
-	if (buffer_eopnotsupp(bh)) {
-		clear_buffer_eopnotsupp(bh);
-		disable_barrier(s);
-		set_buffer_uptodate(bh);
-		set_buffer_dirty(bh);
-		reiserfs_write_unlock(s);
-		sync_dirty_buffer(bh);
-		reiserfs_write_lock(s);
-	}
-}
-
 #define CHUNK_SIZE 32
 struct buffer_chunk {
 	struct buffer_head *bh[CHUNK_SIZE];
@@ -1009,7 +978,6 @@
 	struct buffer_head *tbh = NULL;
 	unsigned int trans_id = jl->j_trans_id;
 	struct reiserfs_journal *journal = SB_JOURNAL(s);
-	int barrier = 0;
 	int retval = 0;
 	int write_len;
 
@@ -1094,24 +1062,6 @@
 	}
 	atomic_dec(&journal->j_async_throttle);
 
-	/* We're skipping the commit if there's an error */
-	if (retval || reiserfs_is_journal_aborted(journal))
-		barrier = 0;
-
-	/* wait on everything written so far before writing the commit
-	 * if we are in barrier mode, send the commit down now
-	 */
-	barrier = reiserfs_barrier_flush(s);
-	if (barrier) {
-		int ret;
-		lock_buffer(jl->j_commit_bh);
-		ret = submit_barrier_buffer(jl->j_commit_bh);
-		if (ret == -EOPNOTSUPP) {
-			set_buffer_uptodate(jl->j_commit_bh);
-			disable_barrier(s);
-			barrier = 0;
-		}
-	}
 	for (i = 0; i < (jl->j_len + 1); i++) {
 		bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) +
 		    (jl->j_start + i) % SB_ONDISK_JOURNAL_SIZE(s);
@@ -1143,27 +1093,22 @@
 
 	BUG_ON(atomic_read(&(jl->j_commit_left)) != 1);
 
-	if (!barrier) {
-		/* If there was a write error in the journal - we can't commit
-		 * this transaction - it will be invalid and, if successful,
-		 * will just end up propagating the write error out to
-		 * the file system. */
-		if (likely(!retval && !reiserfs_is_journal_aborted (journal))) {
-			if (buffer_dirty(jl->j_commit_bh))
-				BUG();
-			mark_buffer_dirty(jl->j_commit_bh) ;
-			reiserfs_write_unlock(s);
-			sync_dirty_buffer(jl->j_commit_bh) ;
-			reiserfs_write_lock(s);
-		}
-	} else {
+	/* If there was a write error in the journal - we can't commit
+	 * this transaction - it will be invalid and, if successful,
+	 * will just end up propagating the write error out to
+	 * the file system. */
+	if (likely(!retval && !reiserfs_is_journal_aborted (journal))) {
+		if (buffer_dirty(jl->j_commit_bh))
+			BUG();
+		mark_buffer_dirty(jl->j_commit_bh) ;
 		reiserfs_write_unlock(s);
-		wait_on_buffer(jl->j_commit_bh);
+		if (reiserfs_barrier_flush(s))
+			__sync_dirty_buffer(jl->j_commit_bh, WRITE_FLUSH_FUA);
+		else
+			sync_dirty_buffer(jl->j_commit_bh);
 		reiserfs_write_lock(s);
 	}
 
-	check_barrier_completion(s, jl->j_commit_bh);
-
 	/* If there was a write error in the journal - we can't commit this
 	 * transaction - it will be invalid and, if successful, will just end
 	 * up propagating the write error out to the filesystem. */
@@ -1319,26 +1264,15 @@
 		jh->j_first_unflushed_offset = cpu_to_le32(offset);
 		jh->j_mount_id = cpu_to_le32(journal->j_mount_id);
 
-		if (reiserfs_barrier_flush(sb)) {
-			int ret;
-			lock_buffer(journal->j_header_bh);
-			ret = submit_barrier_buffer(journal->j_header_bh);
-			if (ret == -EOPNOTSUPP) {
-				set_buffer_uptodate(journal->j_header_bh);
-				disable_barrier(sb);
-				goto sync;
-			}
-			reiserfs_write_unlock(sb);
-			wait_on_buffer(journal->j_header_bh);
-			reiserfs_write_lock(sb);
-			check_barrier_completion(sb, journal->j_header_bh);
-		} else {
-		      sync:
-			set_buffer_dirty(journal->j_header_bh);
-			reiserfs_write_unlock(sb);
+		set_buffer_dirty(journal->j_header_bh);
+		reiserfs_write_unlock(sb);
+
+		if (reiserfs_barrier_flush(sb))
+			__sync_dirty_buffer(journal->j_header_bh, WRITE_FLUSH_FUA);
+		else
 			sync_dirty_buffer(journal->j_header_bh);
-			reiserfs_write_lock(sb);
-		}
+
+		reiserfs_write_lock(sb);
 		if (!buffer_uptodate(journal->j_header_bh)) {
 			reiserfs_warning(sb, "journal-837",
 					 "IO error during journal replay");
diff --git a/fs/romfs/super.c b/fs/romfs/super.c
index 42d2135..2685805 100644
--- a/fs/romfs/super.c
+++ b/fs/romfs/super.c
@@ -282,6 +282,7 @@
 static const struct file_operations romfs_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= romfs_readdir,
+	.llseek		= default_llseek,
 };
 
 static const struct inode_operations romfs_dir_inode_operations = {
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 1c5a6ad..7404730 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -206,6 +206,7 @@
 	.release	= signalfd_release,
 	.poll		= signalfd_poll,
 	.read		= signalfd_read,
+	.llseek		= noop_llseek,
 };
 
 SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
diff --git a/fs/smbfs/Kconfig b/fs/smbfs/Kconfig
index e668127..2bc24a8 100644
--- a/fs/smbfs/Kconfig
+++ b/fs/smbfs/Kconfig
@@ -1,5 +1,6 @@
 config SMB_FS
 	tristate "SMB file system support (OBSOLETE, please use CIFS)"
+	depends on BKL # probably unfixable
 	depends on INET
 	select NLS
 	help
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 450c919..8fc5e50 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -501,6 +501,8 @@
 	void *mem;
 	static int warn_count;
 
+	lock_kernel();
+
 	if (warn_count < 5) {
 		warn_count++;
 		printk(KERN_EMERG "smbfs is deprecated and will be removed"
@@ -621,6 +623,7 @@
 
 	smb_new_dentry(sb->s_root);
 
+	unlock_kernel();
 	return 0;
 
 out_no_root:
@@ -643,9 +646,11 @@
 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;
 }
 
diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c
index 12b933a..0dc340a 100644
--- a/fs/squashfs/dir.c
+++ b/fs/squashfs/dir.c
@@ -230,5 +230,6 @@
 
 const struct file_operations squashfs_dir_ops = {
 	.read = generic_read_dir,
-	.readdir = squashfs_readdir
+	.readdir = squashfs_readdir,
+	.llseek = default_llseek,
 };
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 88b4f86..07a4f11 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -30,7 +30,6 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
@@ -354,8 +353,6 @@
 
 static void squashfs_put_super(struct super_block *sb)
 {
-	lock_kernel();
-
 	if (sb->s_fs_info) {
 		struct squashfs_sb_info *sbi = sb->s_fs_info;
 		squashfs_cache_delete(sbi->block_cache);
@@ -370,8 +367,6 @@
 		kfree(sb->s_fs_info);
 		sb->s_fs_info = NULL;
 	}
-
-	unlock_kernel();
 }
 
 
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 4e321f7..a475983 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -179,30 +179,14 @@
 	struct bin_buffer *bb = file->private_data;
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 
-	if (!bb->vm_ops || !bb->vm_ops->open)
+	if (!bb->vm_ops)
 		return;
 
 	if (!sysfs_get_active(attr_sd))
 		return;
 
-	bb->vm_ops->open(vma);
-
-	sysfs_put_active(attr_sd);
-}
-
-static void bin_vma_close(struct vm_area_struct *vma)
-{
-	struct file *file = vma->vm_file;
-	struct bin_buffer *bb = file->private_data;
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-
-	if (!bb->vm_ops || !bb->vm_ops->close)
-		return;
-
-	if (!sysfs_get_active(attr_sd))
-		return;
-
-	bb->vm_ops->close(vma);
+	if (bb->vm_ops->open)
+		bb->vm_ops->open(vma);
 
 	sysfs_put_active(attr_sd);
 }
@@ -214,13 +198,15 @@
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	int ret;
 
-	if (!bb->vm_ops || !bb->vm_ops->fault)
+	if (!bb->vm_ops)
 		return VM_FAULT_SIGBUS;
 
 	if (!sysfs_get_active(attr_sd))
 		return VM_FAULT_SIGBUS;
 
-	ret = bb->vm_ops->fault(vma, vmf);
+	ret = VM_FAULT_SIGBUS;
+	if (bb->vm_ops->fault)
+		ret = bb->vm_ops->fault(vma, vmf);
 
 	sysfs_put_active(attr_sd);
 	return ret;
@@ -236,13 +222,12 @@
 	if (!bb->vm_ops)
 		return VM_FAULT_SIGBUS;
 
-	if (!bb->vm_ops->page_mkwrite)
-		return 0;
-
 	if (!sysfs_get_active(attr_sd))
 		return VM_FAULT_SIGBUS;
 
-	ret = bb->vm_ops->page_mkwrite(vma, vmf);
+	ret = 0;
+	if (bb->vm_ops->page_mkwrite)
+		ret = bb->vm_ops->page_mkwrite(vma, vmf);
 
 	sysfs_put_active(attr_sd);
 	return ret;
@@ -256,13 +241,15 @@
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	int ret;
 
-	if (!bb->vm_ops || !bb->vm_ops->access)
+	if (!bb->vm_ops)
 		return -EINVAL;
 
 	if (!sysfs_get_active(attr_sd))
 		return -EINVAL;
 
-	ret = bb->vm_ops->access(vma, addr, buf, len, write);
+	ret = -EINVAL;
+	if (bb->vm_ops->access)
+		ret = bb->vm_ops->access(vma, addr, buf, len, write);
 
 	sysfs_put_active(attr_sd);
 	return ret;
@@ -276,13 +263,15 @@
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	int ret;
 
-	if (!bb->vm_ops || !bb->vm_ops->set_policy)
+	if (!bb->vm_ops)
 		return 0;
 
 	if (!sysfs_get_active(attr_sd))
 		return -EINVAL;
 
-	ret = bb->vm_ops->set_policy(vma, new);
+	ret = 0;
+	if (bb->vm_ops->set_policy)
+		ret = bb->vm_ops->set_policy(vma, new);
 
 	sysfs_put_active(attr_sd);
 	return ret;
@@ -296,13 +285,15 @@
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	struct mempolicy *pol;
 
-	if (!bb->vm_ops || !bb->vm_ops->get_policy)
+	if (!bb->vm_ops)
 		return vma->vm_policy;
 
 	if (!sysfs_get_active(attr_sd))
 		return vma->vm_policy;
 
-	pol = bb->vm_ops->get_policy(vma, addr);
+	pol = vma->vm_policy;
+	if (bb->vm_ops->get_policy)
+		pol = bb->vm_ops->get_policy(vma, addr);
 
 	sysfs_put_active(attr_sd);
 	return pol;
@@ -316,13 +307,15 @@
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	int ret;
 
-	if (!bb->vm_ops || !bb->vm_ops->migrate)
+	if (!bb->vm_ops)
 		return 0;
 
 	if (!sysfs_get_active(attr_sd))
 		return 0;
 
-	ret = bb->vm_ops->migrate(vma, from, to, flags);
+	ret = 0;
+	if (bb->vm_ops->migrate)
+		ret = bb->vm_ops->migrate(vma, from, to, flags);
 
 	sysfs_put_active(attr_sd);
 	return ret;
@@ -331,7 +324,6 @@
 
 static const struct vm_operations_struct bin_vm_ops = {
 	.open		= bin_vma_open,
-	.close		= bin_vma_close,
 	.fault		= bin_fault,
 	.page_mkwrite	= bin_page_mkwrite,
 	.access		= bin_access,
@@ -377,6 +369,14 @@
 	if (bb->mmapped && bb->vm_ops != vma->vm_ops)
 		goto out_put;
 
+	/*
+	 * It is not possible to successfully wrap close.
+	 * So error if someone is trying to use close.
+	 */
+	rc = -EINVAL;
+	if (vma->vm_ops && vma->vm_ops->close)
+		goto out_put;
+
 	rc = 0;
 	bb->mmapped = 1;
 	bb->vm_ops = vma->vm_ops;
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 23c1e59..442f34f 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -148,6 +148,65 @@
 	sysfs_put(sd);
 }
 
+/**
+ * sysfs_merge_group - merge files into a pre-existing attribute group.
+ * @kobj:	The kobject containing the group.
+ * @grp:	The files to create and the attribute group they belong to.
+ *
+ * This function returns an error if the group doesn't exist or any of the
+ * files already exist in that group, in which case none of the new files
+ * are created.
+ */
+int sysfs_merge_group(struct kobject *kobj,
+		       const struct attribute_group *grp)
+{
+	struct sysfs_dirent *dir_sd;
+	int error = 0;
+	struct attribute *const *attr;
+	int i;
+
+	if (grp)
+		dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+	else
+		dir_sd = sysfs_get(kobj->sd);
+	if (!dir_sd)
+		return -ENOENT;
+
+	for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr))
+		error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
+	if (error) {
+		while (--i >= 0)
+			sysfs_hash_and_remove(dir_sd, NULL, (*--attr)->name);
+	}
+	sysfs_put(dir_sd);
+
+	return error;
+}
+EXPORT_SYMBOL_GPL(sysfs_merge_group);
+
+/**
+ * sysfs_unmerge_group - remove files from a pre-existing attribute group.
+ * @kobj:	The kobject containing the group.
+ * @grp:	The files to remove and the attribute group they belong to.
+ */
+void sysfs_unmerge_group(struct kobject *kobj,
+		       const struct attribute_group *grp)
+{
+	struct sysfs_dirent *dir_sd;
+	struct attribute *const *attr;
+
+	if (grp)
+		dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+	else
+		dir_sd = sysfs_get(kobj->sd);
+	if (dir_sd) {
+		for (attr = grp->attrs; *attr; ++attr)
+			sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
+		sysfs_put(dir_sd);
+	}
+}
+EXPORT_SYMBOL_GPL(sysfs_unmerge_group);
+
 
 EXPORT_SYMBOL_GPL(sysfs_create_group);
 EXPORT_SYMBOL_GPL(sysfs_update_group);
diff --git a/fs/timerfd.c b/fs/timerfd.c
index b86ab8e..8c4fc14 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -144,6 +144,7 @@
 	.release	= timerfd_release,
 	.poll		= timerfd_poll,
 	.read		= timerfd_read,
+	.llseek		= noop_llseek,
 };
 
 static struct file *timerfd_fget(int fd)
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index 37fa7ed..02429d8 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -63,7 +63,9 @@
 	struct ubifs_lp_stats lst;
 
 	dbg_cmt("start");
-	if (c->ro_media) {
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+
+	if (c->ro_error) {
 		err = -EROFS;
 		goto out_up;
 	}
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index c2a68ba..0bee4db 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2239,6 +2239,162 @@
 	return err;
 }
 
+/**
+ * dbg_check_data_nodes_order - check that list of data nodes is sorted.
+ * @c: UBIFS file-system description object
+ * @head: the list of nodes ('struct ubifs_scan_node' objects)
+ *
+ * This function returns zero if the list of data nodes is sorted correctly,
+ * and %-EINVAL if not.
+ */
+int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
+{
+	struct list_head *cur;
+	struct ubifs_scan_node *sa, *sb;
+
+	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+		return 0;
+
+	for (cur = head->next; cur->next != head; cur = cur->next) {
+		ino_t inuma, inumb;
+		uint32_t blka, blkb;
+
+		cond_resched();
+		sa = container_of(cur, struct ubifs_scan_node, list);
+		sb = container_of(cur->next, struct ubifs_scan_node, list);
+
+		if (sa->type != UBIFS_DATA_NODE) {
+			ubifs_err("bad node type %d", sa->type);
+			dbg_dump_node(c, sa->node);
+			return -EINVAL;
+		}
+		if (sb->type != UBIFS_DATA_NODE) {
+			ubifs_err("bad node type %d", sb->type);
+			dbg_dump_node(c, sb->node);
+			return -EINVAL;
+		}
+
+		inuma = key_inum(c, &sa->key);
+		inumb = key_inum(c, &sb->key);
+
+		if (inuma < inumb)
+			continue;
+		if (inuma > inumb) {
+			ubifs_err("larger inum %lu goes before inum %lu",
+				  (unsigned long)inuma, (unsigned long)inumb);
+			goto error_dump;
+		}
+
+		blka = key_block(c, &sa->key);
+		blkb = key_block(c, &sb->key);
+
+		if (blka > blkb) {
+			ubifs_err("larger block %u goes before %u", blka, blkb);
+			goto error_dump;
+		}
+		if (blka == blkb) {
+			ubifs_err("two data nodes for the same block");
+			goto error_dump;
+		}
+	}
+
+	return 0;
+
+error_dump:
+	dbg_dump_node(c, sa->node);
+	dbg_dump_node(c, sb->node);
+	return -EINVAL;
+}
+
+/**
+ * dbg_check_nondata_nodes_order - check that list of data nodes is sorted.
+ * @c: UBIFS file-system description object
+ * @head: the list of nodes ('struct ubifs_scan_node' objects)
+ *
+ * This function returns zero if the list of non-data nodes is sorted correctly,
+ * and %-EINVAL if not.
+ */
+int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
+{
+	struct list_head *cur;
+	struct ubifs_scan_node *sa, *sb;
+
+	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+		return 0;
+
+	for (cur = head->next; cur->next != head; cur = cur->next) {
+		ino_t inuma, inumb;
+		uint32_t hasha, hashb;
+
+		cond_resched();
+		sa = container_of(cur, struct ubifs_scan_node, list);
+		sb = container_of(cur->next, struct ubifs_scan_node, list);
+
+		if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
+		    sa->type != UBIFS_XENT_NODE) {
+			ubifs_err("bad node type %d", sa->type);
+			dbg_dump_node(c, sa->node);
+			return -EINVAL;
+		}
+		if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
+		    sa->type != UBIFS_XENT_NODE) {
+			ubifs_err("bad node type %d", sb->type);
+			dbg_dump_node(c, sb->node);
+			return -EINVAL;
+		}
+
+		if (sa->type != UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) {
+			ubifs_err("non-inode node goes before inode node");
+			goto error_dump;
+		}
+
+		if (sa->type == UBIFS_INO_NODE && sb->type != UBIFS_INO_NODE)
+			continue;
+
+		if (sa->type == UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) {
+			/* Inode nodes are sorted in descending size order */
+			if (sa->len < sb->len) {
+				ubifs_err("smaller inode node goes first");
+				goto error_dump;
+			}
+			continue;
+		}
+
+		/*
+		 * This is either a dentry or xentry, which should be sorted in
+		 * ascending (parent ino, hash) order.
+		 */
+		inuma = key_inum(c, &sa->key);
+		inumb = key_inum(c, &sb->key);
+
+		if (inuma < inumb)
+			continue;
+		if (inuma > inumb) {
+			ubifs_err("larger inum %lu goes before inum %lu",
+				  (unsigned long)inuma, (unsigned long)inumb);
+			goto error_dump;
+		}
+
+		hasha = key_block(c, &sa->key);
+		hashb = key_block(c, &sb->key);
+
+		if (hasha > hashb) {
+			ubifs_err("larger hash %u goes before %u", hasha, hashb);
+			goto error_dump;
+		}
+	}
+
+	return 0;
+
+error_dump:
+	ubifs_msg("dumping first node");
+	dbg_dump_node(c, sa->node);
+	ubifs_msg("dumping second node");
+	dbg_dump_node(c, sb->node);
+	return -EINVAL;
+	return 0;
+}
+
 static int invocation_cnt;
 
 int dbg_force_in_the_gaps(void)
@@ -2625,6 +2781,7 @@
 	.open = open_debugfs_file,
 	.write = write_debugfs_file,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 /**
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 29d9601..69ebe47 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -324,6 +324,8 @@
 			int row, int col);
 int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
 			 loff_t size);
+int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
+int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
 
 /* Force the use of in-the-gaps method for testing */
 
@@ -465,6 +467,8 @@
 #define dbg_check_lprops(c)                        0
 #define dbg_check_lpt_nodes(c, cnode, row, col)    0
 #define dbg_check_inode_size(c, inode, size)       0
+#define dbg_check_data_nodes_order(c, head)        0
+#define dbg_check_nondata_nodes_order(c, head)     0
 #define dbg_force_in_the_gaps_enabled              0
 #define dbg_force_in_the_gaps()                    0
 #define dbg_failure_mode                           0
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 03ae894..d77db7e 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -433,8 +433,9 @@
 	struct page *page;
 
 	ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size);
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
-	if (unlikely(c->ro_media))
+	if (unlikely(c->ro_error))
 		return -EROFS;
 
 	/* Try out the fast-path part first */
@@ -1439,9 +1440,9 @@
 
 	dbg_gen("ino %lu, pg %lu, i_size %lld",	inode->i_ino, page->index,
 		i_size_read(inode));
-	ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
-	if (unlikely(c->ro_media))
+	if (unlikely(c->ro_error))
 		return VM_FAULT_SIGBUS; /* -EROFS */
 
 	/*
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 918d158..151f108 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -125,10 +125,16 @@
 	struct ubifs_scan_node *sa, *sb;
 
 	cond_resched();
+	if (a == b)
+		return 0;
+
 	sa = list_entry(a, struct ubifs_scan_node, list);
 	sb = list_entry(b, struct ubifs_scan_node, list);
+
 	ubifs_assert(key_type(c, &sa->key) == UBIFS_DATA_KEY);
 	ubifs_assert(key_type(c, &sb->key) == UBIFS_DATA_KEY);
+	ubifs_assert(sa->type == UBIFS_DATA_NODE);
+	ubifs_assert(sb->type == UBIFS_DATA_NODE);
 
 	inuma = key_inum(c, &sa->key);
 	inumb = key_inum(c, &sb->key);
@@ -157,28 +163,40 @@
  */
 int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b)
 {
-	int typea, typeb;
 	ino_t inuma, inumb;
 	struct ubifs_info *c = priv;
 	struct ubifs_scan_node *sa, *sb;
 
 	cond_resched();
+	if (a == b)
+		return 0;
+
 	sa = list_entry(a, struct ubifs_scan_node, list);
 	sb = list_entry(b, struct ubifs_scan_node, list);
-	typea = key_type(c, &sa->key);
-	typeb = key_type(c, &sb->key);
-	ubifs_assert(typea != UBIFS_DATA_KEY && typeb != UBIFS_DATA_KEY);
+
+	ubifs_assert(key_type(c, &sa->key) != UBIFS_DATA_KEY &&
+		     key_type(c, &sb->key) != UBIFS_DATA_KEY);
+	ubifs_assert(sa->type != UBIFS_DATA_NODE &&
+		     sb->type != UBIFS_DATA_NODE);
 
 	/* Inodes go before directory entries */
-	if (typea == UBIFS_INO_KEY) {
-		if (typeb == UBIFS_INO_KEY)
+	if (sa->type == UBIFS_INO_NODE) {
+		if (sb->type == UBIFS_INO_NODE)
 			return sb->len - sa->len;
 		return -1;
 	}
-	if (typeb == UBIFS_INO_KEY)
+	if (sb->type == UBIFS_INO_NODE)
 		return 1;
 
-	ubifs_assert(typea == UBIFS_DENT_KEY && typeb == UBIFS_DENT_KEY);
+	ubifs_assert(key_type(c, &sa->key) == UBIFS_DENT_KEY ||
+		     key_type(c, &sa->key) == UBIFS_XENT_KEY);
+	ubifs_assert(key_type(c, &sb->key) == UBIFS_DENT_KEY ||
+		     key_type(c, &sb->key) == UBIFS_XENT_KEY);
+	ubifs_assert(sa->type == UBIFS_DENT_NODE ||
+		     sa->type == UBIFS_XENT_NODE);
+	ubifs_assert(sb->type == UBIFS_DENT_NODE ||
+		     sb->type == UBIFS_XENT_NODE);
+
 	inuma = key_inum(c, &sa->key);
 	inumb = key_inum(c, &sb->key);
 
@@ -224,17 +242,33 @@
 static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
 		      struct list_head *nondata, int *min)
 {
+	int err;
 	struct ubifs_scan_node *snod, *tmp;
 
 	*min = INT_MAX;
 
 	/* Separate data nodes and non-data nodes */
 	list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
-		int err;
+		ubifs_assert(snod->type == UBIFS_INO_NODE  ||
+			     snod->type == UBIFS_DATA_NODE ||
+			     snod->type == UBIFS_DENT_NODE ||
+			     snod->type == UBIFS_XENT_NODE ||
+			     snod->type == UBIFS_TRUN_NODE);
 
-		ubifs_assert(snod->type != UBIFS_IDX_NODE);
-		ubifs_assert(snod->type != UBIFS_REF_NODE);
-		ubifs_assert(snod->type != UBIFS_CS_NODE);
+		if (snod->type != UBIFS_INO_NODE  &&
+		    snod->type != UBIFS_DATA_NODE &&
+		    snod->type != UBIFS_DENT_NODE &&
+		    snod->type != UBIFS_XENT_NODE) {
+			/* Probably truncation node, zap it */
+			list_del(&snod->list);
+			kfree(snod);
+			continue;
+		}
+
+		ubifs_assert(key_type(c, &snod->key) == UBIFS_DATA_KEY ||
+			     key_type(c, &snod->key) == UBIFS_INO_KEY  ||
+			     key_type(c, &snod->key) == UBIFS_DENT_KEY ||
+			     key_type(c, &snod->key) == UBIFS_XENT_KEY);
 
 		err = ubifs_tnc_has_node(c, &snod->key, 0, sleb->lnum,
 					 snod->offs, 0);
@@ -258,6 +292,13 @@
 	/* Sort data and non-data nodes */
 	list_sort(c, &sleb->nodes, &data_nodes_cmp);
 	list_sort(c, nondata, &nondata_nodes_cmp);
+
+	err = dbg_check_data_nodes_order(c, &sleb->nodes);
+	if (err)
+		return err;
+	err = dbg_check_nondata_nodes_order(c, nondata);
+	if (err)
+		return err;
 	return 0;
 }
 
@@ -575,13 +616,14 @@
 	struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
 
 	ubifs_assert_cmt_locked(c);
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
 	if (ubifs_gc_should_commit(c))
 		return -EAGAIN;
 
 	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
 
-	if (c->ro_media) {
+	if (c->ro_error) {
 		ret = -EROFS;
 		goto out_unlock;
 	}
@@ -677,14 +719,12 @@
 
 		ret = ubifs_garbage_collect_leb(c, &lp);
 		if (ret < 0) {
-			if (ret == -EAGAIN || ret == -ENOSPC) {
+			if (ret == -EAGAIN) {
 				/*
-				 * These codes are not errors, so we have to
-				 * return the LEB to lprops. But if the
-				 * 'ubifs_return_leb()' function fails, its
-				 * failure code is propagated to the caller
-				 * instead of the original '-EAGAIN' or
-				 * '-ENOSPC'.
+				 * This is not error, so we have to return the
+				 * LEB to lprops. But if 'ubifs_return_leb()'
+				 * fails, its failure code is propagated to the
+				 * caller instead of the original '-EAGAIN'.
 				 */
 				err = ubifs_return_leb(c, lp.lnum);
 				if (err)
@@ -774,8 +814,8 @@
 out:
 	ubifs_assert(ret < 0);
 	ubifs_assert(ret != -ENOSPC && ret != -EAGAIN);
-	ubifs_ro_mode(c, ret);
 	ubifs_wbuf_sync_nolock(wbuf);
+	ubifs_ro_mode(c, ret);
 	mutex_unlock(&wbuf->io_mutex);
 	ubifs_return_leb(c, lp.lnum);
 	return ret;
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index bcf5a16..d821731 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -61,8 +61,8 @@
  */
 void ubifs_ro_mode(struct ubifs_info *c, int err)
 {
-	if (!c->ro_media) {
-		c->ro_media = 1;
+	if (!c->ro_error) {
+		c->ro_error = 1;
 		c->no_chk_data_crc = 0;
 		c->vfs_sb->s_flags |= MS_RDONLY;
 		ubifs_warn("switched to read-only mode, error %d", err);
@@ -356,11 +356,11 @@
 
 	dbg_io("LEB %d:%d, %d bytes, jhead %s",
 	       wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead));
-	ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
 	ubifs_assert(!(wbuf->avail & 7));
 	ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
-	if (c->ro_media)
+	if (c->ro_error)
 		return -EROFS;
 
 	ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail);
@@ -440,11 +440,12 @@
 {
 	int err, i;
 
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 	if (!c->need_wbuf_sync)
 		return 0;
 	c->need_wbuf_sync = 0;
 
-	if (c->ro_media) {
+	if (c->ro_error) {
 		err = -EROFS;
 		goto out_timers;
 	}
@@ -519,6 +520,7 @@
 	ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
 	ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
 	ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
 	if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
 		err = -ENOSPC;
@@ -527,7 +529,7 @@
 
 	cancel_wbuf_timer_nolock(wbuf);
 
-	if (c->ro_media)
+	if (c->ro_error)
 		return -EROFS;
 
 	if (aligned_len <= wbuf->avail) {
@@ -663,8 +665,9 @@
 	       buf_len);
 	ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
 	ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
-	if (c->ro_media)
+	if (c->ro_error)
 		return -EROFS;
 
 	ubifs_prepare_node(c, buf, len, 1);
@@ -815,7 +818,8 @@
 	return 0;
 
 out:
-	ubifs_err("bad node at LEB %d:%d", lnum, offs);
+	ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs,
+		  ubi_is_mapped(c->ubi, lnum));
 	dbg_dump_node(c, buf);
 	dbg_dump_stack();
 	return -EINVAL;
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index d321bae..914f1bd 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -122,11 +122,12 @@
 	 * better to try to allocate space at the ends of eraseblocks. This is
 	 * what the squeeze parameter does.
 	 */
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 	squeeze = (jhead == BASEHD);
 again:
 	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
 
-	if (c->ro_media) {
+	if (c->ro_error) {
 		err = -EROFS;
 		goto out_unlock;
 	}
diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h
index 0f530c6..92a8491 100644
--- a/fs/ubifs/key.h
+++ b/fs/ubifs/key.h
@@ -306,6 +306,20 @@
 }
 
 /**
+ * invalid_key_init - initialize invalid node key.
+ * @c: UBIFS file-system description object
+ * @key: key to initialize
+ *
+ * This is a helper function which marks a @key object as invalid.
+ */
+static inline void invalid_key_init(const struct ubifs_info *c,
+				    union ubifs_key *key)
+{
+	key->u32[0] = 0xDEADBEAF;
+	key->u32[1] = UBIFS_INVALID_KEY;
+}
+
+/**
  * key_type - get key type.
  * @c: UBIFS file-system description object
  * @key: key to get type of
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index c345e12..4d0cb12 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -159,7 +159,7 @@
 		jhead = &c->jheads[bud->jhead];
 		list_add_tail(&bud->list, &jhead->buds_list);
 	} else
-		ubifs_assert(c->replaying && (c->vfs_sb->s_flags & MS_RDONLY));
+		ubifs_assert(c->replaying && c->ro_mount);
 
 	/*
 	 * Note, although this is a new bud, we anyway account this space now,
@@ -223,8 +223,8 @@
 	}
 
 	mutex_lock(&c->log_mutex);
-
-	if (c->ro_media) {
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error) {
 		err = -EROFS;
 		goto out_unlock;
 	}
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index 0084a33..72775d3 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -1363,6 +1363,7 @@
 		goto out;
 	for (i = 0; i < c->lsave_cnt; i++) {
 		int lnum = c->lsave[i];
+		struct ubifs_lprops *lprops;
 
 		/*
 		 * Due to automatic resizing, the values in the lsave table
@@ -1370,7 +1371,11 @@
 		 */
 		if (lnum >= c->leb_cnt)
 			continue;
-		ubifs_lpt_lookup(c, lnum);
+		lprops = ubifs_lpt_lookup(c, lnum);
+		if (IS_ERR(lprops)) {
+			err = PTR_ERR(lprops);
+			goto out;
+		}
 	}
 out:
 	vfree(buf);
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index d12535b..5c90dec 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -705,6 +705,9 @@
 	struct ubifs_pnode *pnode;
 
 	pnode = pnode_lookup(c, 0);
+	if (IS_ERR(pnode))
+		return PTR_ERR(pnode);
+
 	while (pnode) {
 		do_make_pnode_dirty(c, pnode);
 		pnode = next_pnode_to_dirty(c, pnode);
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c
index 28beaee..21f47af 100644
--- a/fs/ubifs/master.c
+++ b/fs/ubifs/master.c
@@ -361,7 +361,8 @@
 {
 	int err, lnum, offs, len;
 
-	if (c->ro_media)
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
 		return -EROFS;
 
 	lnum = UBIFS_MST_LNUM;
diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h
index 4fa81d8..c3de04d 100644
--- a/fs/ubifs/misc.h
+++ b/fs/ubifs/misc.h
@@ -132,7 +132,8 @@
 {
 	int err;
 
-	if (c->ro_media)
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
 		return -EROFS;
 	err = ubi_leb_unmap(c->ubi, lnum);
 	if (err) {
@@ -159,7 +160,8 @@
 {
 	int err;
 
-	if (c->ro_media)
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
 		return -EROFS;
 	err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
 	if (err) {
@@ -186,7 +188,8 @@
 {
 	int err;
 
-	if (c->ro_media)
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
 		return -EROFS;
 	err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
 	if (err) {
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index daae9e1..77e9b87 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -292,7 +292,7 @@
 
 	memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ);
 
-	if ((c->vfs_sb->s_flags & MS_RDONLY)) {
+	if (c->ro_mount) {
 		/* Read-only mode. Keep a copy for switching to rw mode */
 		c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL);
 		if (!c->rcvrd_mst_node) {
@@ -469,7 +469,7 @@
 		endpt = snod->offs + snod->len;
 	}
 
-	if ((c->vfs_sb->s_flags & MS_RDONLY) && !c->remounting_rw) {
+	if (c->ro_mount && !c->remounting_rw) {
 		/* Add to recovery list */
 		struct ubifs_unclean_leb *ucleb;
 
@@ -772,7 +772,8 @@
  * @sbuf: LEB-sized buffer to use
  *
  * This function does a scan of a LEB, but caters for errors that might have
- * been caused by the unclean unmount from which we are attempting to recover.
+ * been caused by unclean reboots from which we are attempting to recover
+ * (assume that only the last log LEB can be corrupted by an unclean reboot).
  *
  * This function returns %0 on success and a negative error code on failure.
  */
@@ -883,7 +884,7 @@
 {
 	int err;
 
-	ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY) || c->remounting_rw);
+	ubifs_assert(!c->ro_mount || c->remounting_rw);
 
 	dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs);
 	err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf);
@@ -1461,7 +1462,7 @@
 			}
 		}
 		if (e->exists && e->i_size < e->d_size) {
-			if (!e->inode && (c->vfs_sb->s_flags & MS_RDONLY)) {
+			if (!e->inode && c->ro_mount) {
 				/* Fix the inode size and pin it in memory */
 				struct inode *inode;
 
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 5c2d6d7..eed0fcf 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -627,8 +627,7 @@
 	ubifs_assert(sleb->endpt - offs >= used);
 	ubifs_assert(sleb->endpt % c->min_io_size == 0);
 
-	if (sleb->endpt + c->min_io_size <= c->leb_size &&
-	    !(c->vfs_sb->s_flags & MS_RDONLY))
+	if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount)
 		err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum,
 					     sleb->endpt, UBI_SHORTTERM);
 
@@ -840,6 +839,11 @@
 	if (IS_ERR(sleb)) {
 		if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery)
 			return PTR_ERR(sleb);
+		/*
+		 * Note, the below function will recover this log LEB only if
+		 * it is the last, because unclean reboots can possibly corrupt
+		 * only the tail of the log.
+		 */
 		sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
 		if (IS_ERR(sleb))
 			return PTR_ERR(sleb);
@@ -851,7 +855,6 @@
 	}
 
 	node = sleb->buf;
-
 	snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
 	if (c->cs_sqnum == 0) {
 		/*
@@ -898,7 +901,6 @@
 	}
 
 	list_for_each_entry(snod, &sleb->nodes, list) {
-
 		cond_resched();
 
 		if (snod->sqnum >= SQNUM_WATERMARK) {
@@ -1011,7 +1013,6 @@
 int ubifs_replay_journal(struct ubifs_info *c)
 {
 	int err, i, lnum, offs, free;
-	void *sbuf = NULL;
 
 	BUILD_BUG_ON(UBIFS_TRUN_KEY > 5);
 
@@ -1026,14 +1027,8 @@
 		return -EINVAL;
 	}
 
-	sbuf = vmalloc(c->leb_size);
-	if (!sbuf)
-		return -ENOMEM;
-
 	dbg_mnt("start replaying the journal");
-
 	c->replaying = 1;
-
 	lnum = c->ltail_lnum = c->lhead_lnum;
 	offs = c->lhead_offs;
 
@@ -1046,7 +1041,7 @@
 			lnum = UBIFS_LOG_LNUM;
 			offs = 0;
 		}
-		err = replay_log_leb(c, lnum, offs, sbuf);
+		err = replay_log_leb(c, lnum, offs, c->sbuf);
 		if (err == 1)
 			/* We hit the end of the log */
 			break;
@@ -1079,7 +1074,6 @@
 out:
 	destroy_replay_tree(c);
 	destroy_bud_list(c);
-	vfree(sbuf);
 	c->replaying = 0;
 	return err;
 }
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index 96cb62c..bf31b47 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -542,11 +542,8 @@
 	 * due to the unavailability of time-travelling equipment.
 	 */
 	if (c->fmt_version > UBIFS_FORMAT_VERSION) {
-		struct super_block *sb = c->vfs_sb;
-		int mounting_ro = sb->s_flags & MS_RDONLY;
-
-		ubifs_assert(!c->ro_media || mounting_ro);
-		if (!mounting_ro ||
+		ubifs_assert(!c->ro_media || c->ro_mount);
+		if (!c->ro_mount ||
 		    c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) {
 			ubifs_err("on-flash format version is w%d/r%d, but "
 				  "software only supports up to version "
@@ -624,7 +621,7 @@
 	c->old_leb_cnt = c->leb_cnt;
 	if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) {
 		c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size);
-		if (c->vfs_sb->s_flags & MS_RDONLY)
+		if (c->ro_mount)
 			dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs",
 				c->old_leb_cnt,	c->leb_cnt);
 		else {
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index 96c5253..3e1ee57 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -197,7 +197,7 @@
 	struct ubifs_ino_node *ino = buf;
 	struct ubifs_scan_node *snod;
 
-	snod = kzalloc(sizeof(struct ubifs_scan_node), GFP_NOFS);
+	snod = kmalloc(sizeof(struct ubifs_scan_node), GFP_NOFS);
 	if (!snod)
 		return -ENOMEM;
 
@@ -212,13 +212,15 @@
 	case UBIFS_DENT_NODE:
 	case UBIFS_XENT_NODE:
 	case UBIFS_DATA_NODE:
-	case UBIFS_TRUN_NODE:
 		/*
 		 * The key is in the same place in all keyed
 		 * nodes.
 		 */
 		key_read(c, &ino->key, &snod->key);
 		break;
+	default:
+		invalid_key_init(c, &snod->key);
+		break;
 	}
 	list_add_tail(&snod->list, &sleb->nodes);
 	sleb->nodes_cnt += 1;
diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c
index 0b20111..46961c0 100644
--- a/fs/ubifs/shrinker.c
+++ b/fs/ubifs/shrinker.c
@@ -250,7 +250,7 @@
 			dirty_zn_cnt = atomic_long_read(&c->dirty_zn_cnt);
 
 			if (!dirty_zn_cnt || c->cmt_state == COMMIT_BROKEN ||
-			    c->ro_media) {
+			    c->ro_mount || c->ro_error) {
 				mutex_unlock(&c->umount_mutex);
 				continue;
 			}
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index cd5900b..9a47c9f 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1137,11 +1137,11 @@
  */
 static int mount_ubifs(struct ubifs_info *c)
 {
-	struct super_block *sb = c->vfs_sb;
-	int err, mounted_read_only = (sb->s_flags & MS_RDONLY);
+	int err;
 	long long x;
 	size_t sz;
 
+	c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY);
 	err = init_constants_early(c);
 	if (err)
 		return err;
@@ -1154,7 +1154,7 @@
 	if (err)
 		goto out_free;
 
-	if (c->empty && (mounted_read_only || c->ro_media)) {
+	if (c->empty && (c->ro_mount || c->ro_media)) {
 		/*
 		 * This UBI volume is empty, and read-only, or the file system
 		 * is mounted read-only - we cannot format it.
@@ -1165,7 +1165,7 @@
 		goto out_free;
 	}
 
-	if (c->ro_media && !mounted_read_only) {
+	if (c->ro_media && !c->ro_mount) {
 		ubifs_err("cannot mount read-write - read-only media");
 		err = -EROFS;
 		goto out_free;
@@ -1185,7 +1185,7 @@
 	if (!c->sbuf)
 		goto out_free;
 
-	if (!mounted_read_only) {
+	if (!c->ro_mount) {
 		c->ileb_buf = vmalloc(c->leb_size);
 		if (!c->ileb_buf)
 			goto out_free;
@@ -1228,7 +1228,7 @@
 	}
 
 	sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
-	if (!mounted_read_only) {
+	if (!c->ro_mount) {
 		err = alloc_wbufs(c);
 		if (err)
 			goto out_cbuf;
@@ -1254,12 +1254,12 @@
 	if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
 		ubifs_msg("recovery needed");
 		c->need_recovery = 1;
-		if (!mounted_read_only) {
+		if (!c->ro_mount) {
 			err = ubifs_recover_inl_heads(c, c->sbuf);
 			if (err)
 				goto out_master;
 		}
-	} else if (!mounted_read_only) {
+	} else if (!c->ro_mount) {
 		/*
 		 * Set the "dirty" flag so that if we reboot uncleanly we
 		 * will notice this immediately on the next mount.
@@ -1270,7 +1270,7 @@
 			goto out_master;
 	}
 
-	err = ubifs_lpt_init(c, 1, !mounted_read_only);
+	err = ubifs_lpt_init(c, 1, !c->ro_mount);
 	if (err)
 		goto out_lpt;
 
@@ -1285,11 +1285,11 @@
 	/* Calculate 'min_idx_lebs' after journal replay */
 	c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
 
-	err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only);
+	err = ubifs_mount_orphans(c, c->need_recovery, c->ro_mount);
 	if (err)
 		goto out_orphans;
 
-	if (!mounted_read_only) {
+	if (!c->ro_mount) {
 		int lnum;
 
 		err = check_free_space(c);
@@ -1351,7 +1351,7 @@
 	spin_unlock(&ubifs_infos_lock);
 
 	if (c->need_recovery) {
-		if (mounted_read_only)
+		if (c->ro_mount)
 			ubifs_msg("recovery deferred");
 		else {
 			c->need_recovery = 0;
@@ -1378,7 +1378,7 @@
 
 	ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
 		  c->vi.ubi_num, c->vi.vol_id, c->vi.name);
-	if (mounted_read_only)
+	if (c->ro_mount)
 		ubifs_msg("mounted read-only");
 	x = (long long)c->main_lebs * c->leb_size;
 	ubifs_msg("file system size:   %lld bytes (%lld KiB, %lld MiB, %d "
@@ -1640,7 +1640,7 @@
 	}
 
 	dbg_gen("re-mounted read-write");
-	c->vfs_sb->s_flags &= ~MS_RDONLY;
+	c->ro_mount = 0;
 	c->remounting_rw = 0;
 	c->always_chk_crc = 0;
 	err = dbg_check_space_info(c);
@@ -1676,7 +1676,7 @@
 	int i, err;
 
 	ubifs_assert(!c->need_recovery);
-	ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
+	ubifs_assert(!c->ro_mount);
 
 	mutex_lock(&c->umount_mutex);
 	if (c->bgt) {
@@ -1686,10 +1686,8 @@
 
 	dbg_save_space_info(c);
 
-	for (i = 0; i < c->jhead_cnt; i++) {
+	for (i = 0; i < c->jhead_cnt; i++)
 		ubifs_wbuf_sync(&c->jheads[i].wbuf);
-		hrtimer_cancel(&c->jheads[i].wbuf.timer);
-	}
 
 	c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
 	c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
@@ -1704,6 +1702,7 @@
 	vfree(c->ileb_buf);
 	c->ileb_buf = NULL;
 	ubifs_lpt_free(c, 1);
+	c->ro_mount = 1;
 	err = dbg_check_space_info(c);
 	if (err)
 		ubifs_ro_mode(c, err);
@@ -1735,7 +1734,7 @@
 	 * the mutex is locked.
 	 */
 	mutex_lock(&c->umount_mutex);
-	if (!(c->vfs_sb->s_flags & MS_RDONLY)) {
+	if (!c->ro_mount) {
 		/*
 		 * First of all kill the background thread to make sure it does
 		 * not interfere with un-mounting and freeing resources.
@@ -1745,23 +1744,22 @@
 			c->bgt = NULL;
 		}
 
-		/* Synchronize write-buffers */
-		if (c->jheads)
+		/*
+		 * On fatal errors c->ro_error is set to 1, in which case we do
+		 * not write the master node.
+		 */
+		if (!c->ro_error) {
+			int err;
+
+			/* Synchronize write-buffers */
 			for (i = 0; i < c->jhead_cnt; i++)
 				ubifs_wbuf_sync(&c->jheads[i].wbuf);
 
-		/*
-		 * On fatal errors c->ro_media is set to 1, in which case we do
-		 * not write the master node.
-		 */
-		if (!c->ro_media) {
 			/*
 			 * We are being cleanly unmounted which means the
 			 * orphans were killed - indicate this in the master
 			 * node. Also save the reserved GC LEB number.
 			 */
-			int err;
-
 			c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
 			c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
 			c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
@@ -1774,6 +1772,10 @@
 				 */
 				ubifs_err("failed to write master node, "
 					  "error %d", err);
+		} else {
+			for (i = 0; i < c->jhead_cnt; i++)
+				/* Make sure write-buffer timers are canceled */
+				hrtimer_cancel(&c->jheads[i].wbuf.timer);
 		}
 	}
 
@@ -1797,17 +1799,21 @@
 		return err;
 	}
 
-	if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
+	if (c->ro_mount && !(*flags & MS_RDONLY)) {
+		if (c->ro_error) {
+			ubifs_msg("cannot re-mount R/W due to prior errors");
+			return -EROFS;
+		}
 		if (c->ro_media) {
-			ubifs_msg("cannot re-mount due to prior errors");
+			ubifs_msg("cannot re-mount R/W - UBI volume is R/O");
 			return -EROFS;
 		}
 		err = ubifs_remount_rw(c);
 		if (err)
 			return err;
-	} else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
-		if (c->ro_media) {
-			ubifs_msg("cannot re-mount due to prior errors");
+	} else if (!c->ro_mount && (*flags & MS_RDONLY)) {
+		if (c->ro_error) {
+			ubifs_msg("cannot re-mount R/O due to prior errors");
 			return -EROFS;
 		}
 		ubifs_remount_ro(c);
@@ -2049,8 +2055,8 @@
 	 */
 	ubi = open_ubi(name, UBI_READONLY);
 	if (IS_ERR(ubi)) {
-		ubifs_err("cannot open \"%s\", error %d",
-			  name, (int)PTR_ERR(ubi));
+		dbg_err("cannot open \"%s\", error %d",
+			name, (int)PTR_ERR(ubi));
 		return PTR_ERR(ubi);
 	}
 	ubi_get_volume_info(ubi, &vi);
@@ -2064,9 +2070,11 @@
 	}
 
 	if (sb->s_root) {
+		struct ubifs_info *c1 = sb->s_fs_info;
+
 		/* A new mount point for already mounted UBIFS */
 		dbg_gen("this ubi volume is already mounted");
-		if ((flags ^ sb->s_flags) & MS_RDONLY) {
+		if (!!(flags & MS_RDONLY) != c1->ro_mount) {
 			err = -EBUSY;
 			goto out_deact;
 		}
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 2194915..ad9cf01 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -1177,6 +1177,7 @@
 	unsigned long time = get_seconds();
 
 	dbg_tnc("search key %s", DBGKEY(key));
+	ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY);
 
 	znode = c->zroot.znode;
 	if (unlikely(!znode)) {
@@ -2966,7 +2967,7 @@
  *
  * This function searches an indexing node by its first key @key and its
  * address @lnum:@offs. It looks up the indexing tree by pulling all indexing
- * nodes it traverses to TNC. This function is called fro indexing nodes which
+ * nodes it traverses to TNC. This function is called for indexing nodes which
  * were found on the media by scanning, for example when garbage-collecting or
  * when doing in-the-gaps commit. This means that the indexing node which is
  * looked for does not have to have exactly the same leftmost key @key, because
@@ -2988,6 +2989,8 @@
 	struct ubifs_znode *znode, *zn;
 	int n, nn;
 
+	ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY);
+
 	/*
 	 * The arguments have probably been read off flash, so don't assume
 	 * they are valid.
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 0c9876b..381d6b2 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -119,8 +119,12 @@
  * in TNC. However, when replaying, it is handy to introduce fake "truncation"
  * keys for truncation nodes because the code becomes simpler. So we define
  * %UBIFS_TRUN_KEY type.
+ *
+ * But otherwise, out of the journal reply scope, the truncation keys are
+ * invalid.
  */
-#define UBIFS_TRUN_KEY UBIFS_KEY_TYPES_CNT
+#define UBIFS_TRUN_KEY    UBIFS_KEY_TYPES_CNT
+#define UBIFS_INVALID_KEY UBIFS_KEY_TYPES_CNT
 
 /*
  * How much a directory entry/extended attribute entry adds to the parent/host
@@ -1028,6 +1032,8 @@
  * @max_leb_cnt: maximum count of logical eraseblocks
  * @old_leb_cnt: count of logical eraseblocks before re-size
  * @ro_media: the underlying UBI volume is read-only
+ * @ro_mount: the file-system was mounted as read-only
+ * @ro_error: UBIFS switched to R/O mode because an error happened
  *
  * @dirty_pg_cnt: number of dirty pages (not used)
  * @dirty_zn_cnt: number of dirty znodes
@@ -1168,11 +1174,14 @@
  * @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 mounting ro to rw
- * @rcvrd_mst_node: recovered master node to write when mounting ro to rw
+ * @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 remounting from ro to rw (sb flags have MS_RDONLY)
- * @always_chk_crc: always check CRCs (while mounting and remounting rw)
+ * @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
@@ -1268,7 +1277,9 @@
 	int leb_cnt;
 	int max_leb_cnt;
 	int old_leb_cnt;
-	int ro_media;
+	unsigned int ro_media:1;
+	unsigned int ro_mount:1;
+	unsigned int ro_error:1;
 
 	atomic_long_t dirty_pg_cnt;
 	atomic_long_t dirty_zn_cnt;
diff --git a/fs/udf/Kconfig b/fs/udf/Kconfig
index 0e0e99b..f8def3c 100644
--- a/fs/udf/Kconfig
+++ b/fs/udf/Kconfig
@@ -1,5 +1,6 @@
 config UDF_FS
 	tristate "UDF file system support"
+	depends on BKL # needs serious work to remove
 	select CRC_ITU_T
 	help
 	  This is the new file system used on some CD-ROMs and DVDs. Say Y if
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 65412d8..76f3d6d 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1880,6 +1880,8 @@
 	struct kernel_lb_addr rootdir, fileset;
 	struct udf_sb_info *sbi;
 
+	lock_kernel();
+
 	uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
 	uopt.uid = -1;
 	uopt.gid = -1;
@@ -1888,8 +1890,10 @@
 	uopt.dmode = UDF_INVALID_MODE;
 
 	sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL);
-	if (!sbi)
+	if (!sbi) {
+		unlock_kernel();
 		return -ENOMEM;
+	}
 
 	sb->s_fs_info = sbi;
 
@@ -2035,6 +2039,7 @@
 		goto error_out;
 	}
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
+	unlock_kernel();
 	return 0;
 
 error_out:
@@ -2055,6 +2060,7 @@
 	kfree(sbi);
 	sb->s_fs_info = NULL;
 
+	unlock_kernel();
 	return -EINVAL;
 }
 
diff --git a/fs/ufs/Kconfig b/fs/ufs/Kconfig
index e4f10a4..30c8f22 100644
--- a/fs/ufs/Kconfig
+++ b/fs/ufs/Kconfig
@@ -1,6 +1,7 @@
 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/super.c b/fs/ufs/super.c
index d510c1b..6b9be90 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -696,6 +696,8 @@
 	unsigned maxsymlen;
 	int ret = -EINVAL;
 
+	lock_kernel();
+
 	uspi = NULL;
 	ubh = NULL;
 	flags = 0;
@@ -1163,6 +1165,7 @@
 			goto failed;
 
 	UFSD("EXIT\n");
+	unlock_kernel();
 	return 0;
 
 dalloc_failed:
@@ -1174,10 +1177,12 @@
 	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;
 }
 
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 286e36e..ba53128 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -188,8 +188,8 @@
 	atomic_set(&bp->b_hold, 1);
 	init_completion(&bp->b_iowait);
 	INIT_LIST_HEAD(&bp->b_list);
-	INIT_LIST_HEAD(&bp->b_hash_list);
-	init_MUTEX_LOCKED(&bp->b_sema); /* held, no waiters */
+	RB_CLEAR_NODE(&bp->b_rbnode);
+	sema_init(&bp->b_sema, 0); /* held, no waiters */
 	XB_SET_OWNER(bp);
 	bp->b_target = target;
 	bp->b_file_offset = range_base;
@@ -262,8 +262,6 @@
 {
 	trace_xfs_buf_free(bp, _RET_IP_);
 
-	ASSERT(list_empty(&bp->b_hash_list));
-
 	if (bp->b_flags & (_XBF_PAGE_CACHE|_XBF_PAGES)) {
 		uint		i;
 
@@ -422,8 +420,10 @@
 {
 	xfs_off_t		range_base;
 	size_t			range_length;
-	xfs_bufhash_t		*hash;
-	xfs_buf_t		*bp, *n;
+	struct xfs_perag	*pag;
+	struct rb_node		**rbp;
+	struct rb_node		*parent;
+	xfs_buf_t		*bp;
 
 	range_base = (ioff << BBSHIFT);
 	range_length = (isize << BBSHIFT);
@@ -432,14 +432,37 @@
 	ASSERT(!(range_length < (1 << btp->bt_sshift)));
 	ASSERT(!(range_base & (xfs_off_t)btp->bt_smask));
 
-	hash = &btp->bt_hash[hash_long((unsigned long)ioff, btp->bt_hashshift)];
+	/* get tree root */
+	pag = xfs_perag_get(btp->bt_mount,
+				xfs_daddr_to_agno(btp->bt_mount, ioff));
 
-	spin_lock(&hash->bh_lock);
+	/* walk tree */
+	spin_lock(&pag->pag_buf_lock);
+	rbp = &pag->pag_buf_tree.rb_node;
+	parent = NULL;
+	bp = NULL;
+	while (*rbp) {
+		parent = *rbp;
+		bp = rb_entry(parent, struct xfs_buf, b_rbnode);
 
-	list_for_each_entry_safe(bp, n, &hash->bh_list, b_hash_list) {
-		ASSERT(btp == bp->b_target);
-		if (bp->b_file_offset == range_base &&
-		    bp->b_buffer_length == range_length) {
+		if (range_base < bp->b_file_offset)
+			rbp = &(*rbp)->rb_left;
+		else if (range_base > bp->b_file_offset)
+			rbp = &(*rbp)->rb_right;
+		else {
+			/*
+			 * found a block offset match. If the range doesn't
+			 * match, the only way this is allowed is if the buffer
+			 * in the cache is stale and the transaction that made
+			 * it stale has not yet committed. i.e. we are
+			 * reallocating a busy extent. Skip this buffer and
+			 * continue searching to the right for an exact match.
+			 */
+			if (bp->b_buffer_length != range_length) {
+				ASSERT(bp->b_flags & XBF_STALE);
+				rbp = &(*rbp)->rb_right;
+				continue;
+			}
 			atomic_inc(&bp->b_hold);
 			goto found;
 		}
@@ -449,17 +472,21 @@
 	if (new_bp) {
 		_xfs_buf_initialize(new_bp, btp, range_base,
 				range_length, flags);
-		new_bp->b_hash = hash;
-		list_add(&new_bp->b_hash_list, &hash->bh_list);
+		rb_link_node(&new_bp->b_rbnode, parent, rbp);
+		rb_insert_color(&new_bp->b_rbnode, &pag->pag_buf_tree);
+		/* the buffer keeps the perag reference until it is freed */
+		new_bp->b_pag = pag;
+		spin_unlock(&pag->pag_buf_lock);
 	} else {
 		XFS_STATS_INC(xb_miss_locked);
+		spin_unlock(&pag->pag_buf_lock);
+		xfs_perag_put(pag);
 	}
-
-	spin_unlock(&hash->bh_lock);
 	return new_bp;
 
 found:
-	spin_unlock(&hash->bh_lock);
+	spin_unlock(&pag->pag_buf_lock);
+	xfs_perag_put(pag);
 
 	/* Attempt to get the semaphore without sleeping,
 	 * if this does not work then we need to drop the
@@ -625,8 +652,7 @@
 xfs_buf_readahead(
 	xfs_buftarg_t		*target,
 	xfs_off_t		ioff,
-	size_t			isize,
-	xfs_buf_flags_t		flags)
+	size_t			isize)
 {
 	struct backing_dev_info *bdi;
 
@@ -634,8 +660,42 @@
 	if (bdi_read_congested(bdi))
 		return;
 
-	flags |= (XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD);
-	xfs_buf_read(target, ioff, isize, flags);
+	xfs_buf_read(target, ioff, isize,
+		     XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD|XBF_DONT_BLOCK);
+}
+
+/*
+ * Read an uncached buffer from disk. Allocates and returns a locked
+ * buffer containing the disk contents or nothing.
+ */
+struct xfs_buf *
+xfs_buf_read_uncached(
+	struct xfs_mount	*mp,
+	struct xfs_buftarg	*target,
+	xfs_daddr_t		daddr,
+	size_t			length,
+	int			flags)
+{
+	xfs_buf_t		*bp;
+	int			error;
+
+	bp = xfs_buf_get_uncached(target, length, flags);
+	if (!bp)
+		return NULL;
+
+	/* set up the buffer for a read IO */
+	xfs_buf_lock(bp);
+	XFS_BUF_SET_ADDR(bp, daddr);
+	XFS_BUF_READ(bp);
+	XFS_BUF_BUSY(bp);
+
+	xfsbdstrat(mp, bp);
+	error = xfs_buf_iowait(bp);
+	if (error || bp->b_error) {
+		xfs_buf_relse(bp);
+		return NULL;
+	}
+	return bp;
 }
 
 xfs_buf_t *
@@ -707,9 +767,10 @@
 }
 
 xfs_buf_t *
-xfs_buf_get_noaddr(
+xfs_buf_get_uncached(
+	struct xfs_buftarg	*target,
 	size_t			len,
-	xfs_buftarg_t		*target)
+	int			flags)
 {
 	unsigned long		page_count = PAGE_ALIGN(len) >> PAGE_SHIFT;
 	int			error, i;
@@ -725,7 +786,7 @@
 		goto fail_free_buf;
 
 	for (i = 0; i < page_count; i++) {
-		bp->b_pages[i] = alloc_page(GFP_KERNEL);
+		bp->b_pages[i] = alloc_page(xb_to_gfp(flags));
 		if (!bp->b_pages[i])
 			goto fail_free_mem;
 	}
@@ -740,7 +801,7 @@
 
 	xfs_buf_unlock(bp);
 
-	trace_xfs_buf_get_noaddr(bp, _RET_IP_);
+	trace_xfs_buf_get_uncached(bp, _RET_IP_);
 	return bp;
 
  fail_free_mem:
@@ -774,29 +835,30 @@
 xfs_buf_rele(
 	xfs_buf_t		*bp)
 {
-	xfs_bufhash_t		*hash = bp->b_hash;
+	struct xfs_perag	*pag = bp->b_pag;
 
 	trace_xfs_buf_rele(bp, _RET_IP_);
 
-	if (unlikely(!hash)) {
+	if (!pag) {
 		ASSERT(!bp->b_relse);
+		ASSERT(RB_EMPTY_NODE(&bp->b_rbnode));
 		if (atomic_dec_and_test(&bp->b_hold))
 			xfs_buf_free(bp);
 		return;
 	}
 
+	ASSERT(!RB_EMPTY_NODE(&bp->b_rbnode));
 	ASSERT(atomic_read(&bp->b_hold) > 0);
-	if (atomic_dec_and_lock(&bp->b_hold, &hash->bh_lock)) {
+	if (atomic_dec_and_lock(&bp->b_hold, &pag->pag_buf_lock)) {
 		if (bp->b_relse) {
 			atomic_inc(&bp->b_hold);
-			spin_unlock(&hash->bh_lock);
-			(*(bp->b_relse)) (bp);
-		} else if (bp->b_flags & XBF_FS_MANAGED) {
-			spin_unlock(&hash->bh_lock);
+			spin_unlock(&pag->pag_buf_lock);
+			bp->b_relse(bp);
 		} else {
 			ASSERT(!(bp->b_flags & (XBF_DELWRI|_XBF_DELWRI_Q)));
-			list_del_init(&bp->b_hash_list);
-			spin_unlock(&hash->bh_lock);
+			rb_erase(&bp->b_rbnode, &pag->pag_buf_tree);
+			spin_unlock(&pag->pag_buf_lock);
+			xfs_perag_put(pag);
 			xfs_buf_free(bp);
 		}
 	}
@@ -859,7 +921,7 @@
 	trace_xfs_buf_lock(bp, _RET_IP_);
 
 	if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE))
-		xfs_log_force(bp->b_mount, 0);
+		xfs_log_force(bp->b_target->bt_mount, 0);
 	if (atomic_read(&bp->b_io_remaining))
 		blk_run_address_space(bp->b_target->bt_mapping);
 	down(&bp->b_sema);
@@ -924,19 +986,7 @@
 	xfs_buf_t		*bp =
 		container_of(work, xfs_buf_t, b_iodone_work);
 
-	/*
-	 * We can get an EOPNOTSUPP to ordered writes.  Here we clear the
-	 * ordered flag and reissue them.  Because we can't tell the higher
-	 * layers directly that they should not issue ordered I/O anymore, they
-	 * need to check if the _XFS_BARRIER_FAILED flag was set during I/O completion.
-	 */
-	if ((bp->b_error == EOPNOTSUPP) &&
-	    (bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) {
-		trace_xfs_buf_ordered_retry(bp, _RET_IP_);
-		bp->b_flags &= ~XBF_ORDERED;
-		bp->b_flags |= _XFS_BARRIER_FAILED;
-		xfs_buf_iorequest(bp);
-	} else if (bp->b_iodone)
+	if (bp->b_iodone)
 		(*(bp->b_iodone))(bp);
 	else if (bp->b_flags & XBF_ASYNC)
 		xfs_buf_relse(bp);
@@ -982,7 +1032,6 @@
 {
 	int			error;
 
-	bp->b_mount = mp;
 	bp->b_flags |= XBF_WRITE;
 	bp->b_flags &= ~(XBF_ASYNC | XBF_READ);
 
@@ -1003,8 +1052,6 @@
 {
 	trace_xfs_buf_bdwrite(bp, _RET_IP_);
 
-	bp->b_mount = mp;
-
 	bp->b_flags &= ~XBF_READ;
 	bp->b_flags |= (XBF_DELWRI | XBF_ASYNC);
 
@@ -1013,7 +1060,7 @@
 
 /*
  * Called when we want to stop a buffer from getting written or read.
- * We attach the EIO error, muck with its flags, and call biodone
+ * We attach the EIO error, muck with its flags, and call xfs_buf_ioend
  * so that the proper iodone callbacks get called.
  */
 STATIC int
@@ -1030,21 +1077,21 @@
 	XFS_BUF_ERROR(bp, EIO);
 
 	/*
-	 * We're calling biodone, so delete XBF_DONE flag.
+	 * We're calling xfs_buf_ioend, so delete XBF_DONE flag.
 	 */
 	XFS_BUF_UNREAD(bp);
 	XFS_BUF_UNDELAYWRITE(bp);
 	XFS_BUF_UNDONE(bp);
 	XFS_BUF_STALE(bp);
 
-	xfs_biodone(bp);
+	xfs_buf_ioend(bp, 0);
 
 	return EIO;
 }
 
 /*
  * Same as xfs_bioerror, except that we are releasing the buffer
- * here ourselves, and avoiding the biodone call.
+ * here ourselves, and avoiding the xfs_buf_ioend call.
  * This is meant for userdata errors; metadata bufs come with
  * iodone functions attached, so that we can track down errors.
  */
@@ -1093,7 +1140,7 @@
 xfs_bdstrat_cb(
 	struct xfs_buf	*bp)
 {
-	if (XFS_FORCED_SHUTDOWN(bp->b_mount)) {
+	if (XFS_FORCED_SHUTDOWN(bp->b_target->bt_mount)) {
 		trace_xfs_bdstrat_shut(bp, _RET_IP_);
 		/*
 		 * Metadata write that didn't get logged but
@@ -1195,7 +1242,7 @@
 
 	if (bp->b_flags & XBF_ORDERED) {
 		ASSERT(!(bp->b_flags & XBF_READ));
-		rw = WRITE_BARRIER;
+		rw = WRITE_FLUSH_FUA;
 	} else if (bp->b_flags & XBF_LOG_BUFFER) {
 		ASSERT(!(bp->b_flags & XBF_READ_AHEAD));
 		bp->b_flags &= ~_XBF_RUN_QUEUES;
@@ -1399,63 +1446,25 @@
  */
 void
 xfs_wait_buftarg(
-	xfs_buftarg_t	*btp)
+	struct xfs_buftarg	*btp)
 {
-	xfs_buf_t	*bp, *n;
-	xfs_bufhash_t	*hash;
-	uint		i;
+	struct xfs_perag	*pag;
+	uint			i;
 
-	for (i = 0; i < (1 << btp->bt_hashshift); i++) {
-		hash = &btp->bt_hash[i];
-again:
-		spin_lock(&hash->bh_lock);
-		list_for_each_entry_safe(bp, n, &hash->bh_list, b_hash_list) {
-			ASSERT(btp == bp->b_target);
-			if (!(bp->b_flags & XBF_FS_MANAGED)) {
-				spin_unlock(&hash->bh_lock);
-				/*
-				 * Catch superblock reference count leaks
-				 * immediately
-				 */
-				BUG_ON(bp->b_bn == 0);
-				delay(100);
-				goto again;
-			}
+	for (i = 0; i < btp->bt_mount->m_sb.sb_agcount; i++) {
+		pag = xfs_perag_get(btp->bt_mount, i);
+		spin_lock(&pag->pag_buf_lock);
+		while (rb_first(&pag->pag_buf_tree)) {
+			spin_unlock(&pag->pag_buf_lock);
+			delay(100);
+			spin_lock(&pag->pag_buf_lock);
 		}
-		spin_unlock(&hash->bh_lock);
+		spin_unlock(&pag->pag_buf_lock);
+		xfs_perag_put(pag);
 	}
 }
 
 /*
- *	Allocate buffer hash table for a given target.
- *	For devices containing metadata (i.e. not the log/realtime devices)
- *	we need to allocate a much larger hash table.
- */
-STATIC void
-xfs_alloc_bufhash(
-	xfs_buftarg_t		*btp,
-	int			external)
-{
-	unsigned int		i;
-
-	btp->bt_hashshift = external ? 3 : 12;	/* 8 or 4096 buckets */
-	btp->bt_hash = kmem_zalloc_large((1 << btp->bt_hashshift) *
-					 sizeof(xfs_bufhash_t));
-	for (i = 0; i < (1 << btp->bt_hashshift); i++) {
-		spin_lock_init(&btp->bt_hash[i].bh_lock);
-		INIT_LIST_HEAD(&btp->bt_hash[i].bh_list);
-	}
-}
-
-STATIC void
-xfs_free_bufhash(
-	xfs_buftarg_t		*btp)
-{
-	kmem_free_large(btp->bt_hash);
-	btp->bt_hash = NULL;
-}
-
-/*
  *	buftarg list for delwrite queue processing
  */
 static LIST_HEAD(xfs_buftarg_list);
@@ -1487,7 +1496,6 @@
 	xfs_flush_buftarg(btp, 1);
 	if (mp->m_flags & XFS_MOUNT_BARRIER)
 		xfs_blkdev_issue_flush(btp);
-	xfs_free_bufhash(btp);
 	iput(btp->bt_mapping->host);
 
 	/* Unregister the buftarg first so that we don't get a
@@ -1609,6 +1617,7 @@
 
 xfs_buftarg_t *
 xfs_alloc_buftarg(
+	struct xfs_mount	*mp,
 	struct block_device	*bdev,
 	int			external,
 	const char		*fsname)
@@ -1617,6 +1626,7 @@
 
 	btp = kmem_zalloc(sizeof(*btp), KM_SLEEP);
 
+	btp->bt_mount = mp;
 	btp->bt_dev =  bdev->bd_dev;
 	btp->bt_bdev = bdev;
 	if (xfs_setsize_buftarg_early(btp, bdev))
@@ -1625,7 +1635,6 @@
 		goto error;
 	if (xfs_alloc_delwrite_queue(btp, fsname))
 		goto error;
-	xfs_alloc_bufhash(btp, external);
 	return btp;
 
 error:
@@ -1916,7 +1925,7 @@
 			bp = list_first_entry(&wait_list, struct xfs_buf, b_list);
 
 			list_del_init(&bp->b_list);
-			xfs_iowait(bp);
+			xfs_buf_iowait(bp);
 			xfs_buf_relse(bp);
 		}
 	}
@@ -1933,7 +1942,7 @@
 		goto out;
 
 	xfslogd_workqueue = alloc_workqueue("xfslogd",
-					WQ_RESCUER | WQ_HIGHPRI, 1);
+					WQ_MEM_RECLAIM | WQ_HIGHPRI, 1);
 	if (!xfslogd_workqueue)
 		goto out_free_buf_zone;
 
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 2a05614..383a3f3 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -51,7 +51,6 @@
 #define XBF_DONE	(1 << 5) /* all pages in the buffer uptodate */
 #define XBF_DELWRI	(1 << 6) /* buffer has dirty pages */
 #define XBF_STALE	(1 << 7) /* buffer has been staled, do not find it */
-#define XBF_FS_MANAGED	(1 << 8) /* filesystem controls freeing memory */
 #define XBF_ORDERED	(1 << 11)/* use ordered writes */
 #define XBF_READ_AHEAD	(1 << 12)/* asynchronous read-ahead */
 #define XBF_LOG_BUFFER	(1 << 13)/* this is a buffer used for the log */
@@ -86,14 +85,6 @@
  */
 #define _XBF_PAGE_LOCKED	(1 << 22)
 
-/*
- * If we try a barrier write, but it fails we have to communicate
- * this to the upper layers.  Unfortunately b_error gets overwritten
- * when the buffer is re-issued so we have to add another flag to
- * keep this information.
- */
-#define _XFS_BARRIER_FAILED	(1 << 23)
-
 typedef unsigned int xfs_buf_flags_t;
 
 #define XFS_BUF_FLAGS \
@@ -104,7 +95,6 @@
 	{ XBF_DONE,		"DONE" }, \
 	{ XBF_DELWRI,		"DELWRI" }, \
 	{ XBF_STALE,		"STALE" }, \
-	{ XBF_FS_MANAGED,	"FS_MANAGED" }, \
 	{ XBF_ORDERED,		"ORDERED" }, \
 	{ XBF_READ_AHEAD,	"READ_AHEAD" }, \
 	{ XBF_LOCK,		"LOCK" },  	/* should never be set */\
@@ -114,8 +104,7 @@
 	{ _XBF_PAGES,		"PAGES" }, \
 	{ _XBF_RUN_QUEUES,	"RUN_QUEUES" }, \
 	{ _XBF_DELWRI_Q,	"DELWRI_Q" }, \
-	{ _XBF_PAGE_LOCKED,	"PAGE_LOCKED" }, \
-	{ _XFS_BARRIER_FAILED,	"BARRIER_FAILED" }
+	{ _XBF_PAGE_LOCKED,	"PAGE_LOCKED" }
 
 
 typedef enum {
@@ -132,14 +121,11 @@
 	dev_t			bt_dev;
 	struct block_device	*bt_bdev;
 	struct address_space	*bt_mapping;
+	struct xfs_mount	*bt_mount;
 	unsigned int		bt_bsize;
 	unsigned int		bt_sshift;
 	size_t			bt_smask;
 
-	/* per device buffer hash table */
-	uint			bt_hashshift;
-	xfs_bufhash_t		*bt_hash;
-
 	/* per device delwri queue */
 	struct task_struct	*bt_task;
 	struct list_head	bt_list;
@@ -167,34 +153,41 @@
 #define XB_PAGES	2
 
 typedef struct xfs_buf {
-	struct semaphore	b_sema;		/* semaphore for lockables */
-	unsigned long		b_queuetime;	/* time buffer was queued */
-	atomic_t		b_pin_count;	/* pin count */
-	wait_queue_head_t	b_waiters;	/* unpin waiters */
-	struct list_head	b_list;
-	xfs_buf_flags_t		b_flags;	/* status flags */
-	struct list_head	b_hash_list;	/* hash table list */
-	xfs_bufhash_t		*b_hash;	/* hash table list start */
-	xfs_buftarg_t		*b_target;	/* buffer target (device) */
-	atomic_t		b_hold;		/* reference count */
-	xfs_daddr_t		b_bn;		/* block number for I/O */
+	/*
+	 * first cacheline holds all the fields needed for an uncontended cache
+	 * hit to be fully processed. The semaphore straddles the cacheline
+	 * boundary, but the counter and lock sits on the first cacheline,
+	 * which is the only bit that is touched if we hit the semaphore
+	 * fast-path on locking.
+	 */
+	struct rb_node		b_rbnode;	/* rbtree node */
 	xfs_off_t		b_file_offset;	/* offset in file */
 	size_t			b_buffer_length;/* size of buffer in bytes */
+	atomic_t		b_hold;		/* reference count */
+	xfs_buf_flags_t		b_flags;	/* status flags */
+	struct semaphore	b_sema;		/* semaphore for lockables */
+
+	wait_queue_head_t	b_waiters;	/* unpin waiters */
+	struct list_head	b_list;
+	struct xfs_perag	*b_pag;		/* contains rbtree root */
+	xfs_buftarg_t		*b_target;	/* buffer target (device) */
+	xfs_daddr_t		b_bn;		/* block number for I/O */
 	size_t			b_count_desired;/* desired transfer size */
 	void			*b_addr;	/* virtual address of buffer */
 	struct work_struct	b_iodone_work;
-	atomic_t		b_io_remaining;	/* #outstanding I/O requests */
 	xfs_buf_iodone_t	b_iodone;	/* I/O completion function */
 	xfs_buf_relse_t		b_relse;	/* releasing function */
 	struct completion	b_iowait;	/* queue for I/O waiters */
 	void			*b_fspriv;
 	void			*b_fspriv2;
-	struct xfs_mount	*b_mount;
-	unsigned short		b_error;	/* error code on I/O */
-	unsigned int		b_page_count;	/* size of page array */
-	unsigned int		b_offset;	/* page offset in first page */
 	struct page		**b_pages;	/* array of page pointers */
 	struct page		*b_page_array[XB_PAGES]; /* inline pages */
+	unsigned long		b_queuetime;	/* time buffer was queued */
+	atomic_t		b_pin_count;	/* pin count */
+	atomic_t		b_io_remaining;	/* #outstanding I/O requests */
+	unsigned int		b_page_count;	/* size of page array */
+	unsigned int		b_offset;	/* page offset in first page */
+	unsigned short		b_error;	/* error code on I/O */
 #ifdef XFS_BUF_LOCK_TRACKING
 	int			b_last_holder;
 #endif
@@ -213,11 +206,13 @@
 				xfs_buf_flags_t);
 
 extern xfs_buf_t *xfs_buf_get_empty(size_t, xfs_buftarg_t *);
-extern xfs_buf_t *xfs_buf_get_noaddr(size_t, xfs_buftarg_t *);
+extern xfs_buf_t *xfs_buf_get_uncached(struct xfs_buftarg *, size_t, int);
 extern int xfs_buf_associate_memory(xfs_buf_t *, void *, size_t);
 extern void xfs_buf_hold(xfs_buf_t *);
-extern void xfs_buf_readahead(xfs_buftarg_t *, xfs_off_t, size_t,
-				xfs_buf_flags_t);
+extern void xfs_buf_readahead(xfs_buftarg_t *, xfs_off_t, size_t);
+struct xfs_buf *xfs_buf_read_uncached(struct xfs_mount *mp,
+				struct xfs_buftarg *target,
+				xfs_daddr_t daddr, size_t length, int flags);
 
 /* Releasing Buffers */
 extern void xfs_buf_free(xfs_buf_t *);
@@ -242,6 +237,8 @@
 extern int xfs_buf_iowait(xfs_buf_t *);
 extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *,
 				xfs_buf_rw_t);
+#define xfs_buf_zero(bp, off, len) \
+	    xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
 
 static inline int xfs_buf_geterror(xfs_buf_t *bp)
 {
@@ -276,8 +273,6 @@
 					XFS_BUF_DONE(bp);	\
 				} while (0)
 
-#define XFS_BUF_UNMANAGE(bp)	((bp)->b_flags &= ~XBF_FS_MANAGED)
-
 #define XFS_BUF_DELAYWRITE(bp)		((bp)->b_flags |= XBF_DELWRI)
 #define XFS_BUF_UNDELAYWRITE(bp)	xfs_buf_delwri_dequeue(bp)
 #define XFS_BUF_ISDELAYWRITE(bp)	((bp)->b_flags & XBF_DELWRI)
@@ -356,25 +351,11 @@
 	xfs_buf_rele(bp);
 }
 
-#define xfs_biodone(bp)		xfs_buf_ioend(bp, 0)
-
-#define xfs_biomove(bp, off, len, data, rw) \
-	    xfs_buf_iomove((bp), (off), (len), (data), \
-		((rw) == XBF_WRITE) ? XBRW_WRITE : XBRW_READ)
-
-#define xfs_biozero(bp, off, len) \
-	    xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
-
-#define xfs_iowait(bp)	xfs_buf_iowait(bp)
-
-#define xfs_baread(target, rablkno, ralen)  \
-	xfs_buf_readahead((target), (rablkno), (ralen), XBF_DONT_BLOCK)
-
-
 /*
  *	Handling of buftargs.
  */
-extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int, const char *);
+extern xfs_buftarg_t *xfs_alloc_buftarg(struct xfs_mount *,
+			struct block_device *, int, const char *);
 extern void xfs_free_buftarg(struct xfs_mount *, struct xfs_buftarg *);
 extern void xfs_wait_buftarg(xfs_buftarg_t *);
 extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
diff --git a/fs/xfs/linux-2.6/xfs_cred.h b/fs/xfs/linux-2.6/xfs_cred.h
deleted file mode 100644
index 55bddf3..0000000
--- a/fs/xfs/linux-2.6/xfs_cred.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_CRED_H__
-#define __XFS_CRED_H__
-
-#include <linux/capability.h>
-
-/*
- * Credentials
- */
-typedef const struct cred cred_t;
-
-#endif  /* __XFS_CRED_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c
index 1f279b0..ed88ed1 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.c
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.c
@@ -32,10 +32,9 @@
 	xfs_off_t	last,
 	int		fiopt)
 {
-	struct address_space *mapping = VFS_I(ip)->i_mapping;
-
-	if (mapping->nrpages)
-		truncate_inode_pages(mapping, first);
+	/* can't toss partial tail pages, so mask them out */
+	last &= ~(PAGE_SIZE - 1);
+	truncate_inode_pages_range(VFS_I(ip)->i_mapping, first, last - 1);
 }
 
 int
@@ -50,12 +49,11 @@
 
 	trace_xfs_pagecache_inval(ip, first, last);
 
-	if (mapping->nrpages) {
-		xfs_iflags_clear(ip, XFS_ITRUNCATED);
-		ret = filemap_write_and_wait(mapping);
-		if (!ret)
-			truncate_inode_pages(mapping, first);
-	}
+	xfs_iflags_clear(ip, XFS_ITRUNCATED);
+	ret = filemap_write_and_wait_range(mapping, first,
+				last == -1 ? LLONG_MAX : last);
+	if (!ret)
+		truncate_inode_pages_range(mapping, first, last);
 	return -ret;
 }
 
@@ -71,10 +69,9 @@
 	int		ret = 0;
 	int		ret2;
 
-	if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
-		xfs_iflags_clear(ip, XFS_ITRUNCATED);
-		ret = -filemap_fdatawrite(mapping);
-	}
+	xfs_iflags_clear(ip, XFS_ITRUNCATED);
+	ret = -filemap_fdatawrite_range(mapping, first,
+				last == -1 ? LLONG_MAX : last);
 	if (flags & XBF_ASYNC)
 		return ret;
 	ret2 = xfs_wait_on_pages(ip, first, last);
@@ -91,7 +88,9 @@
 {
 	struct address_space *mapping = VFS_I(ip)->i_mapping;
 
-	if (mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK))
-		return -filemap_fdatawait(mapping);
+	if (mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK)) {
+		return -filemap_fdatawait_range(mapping, first,
+					last == -1 ? ip->i_size - 1 : last);
+	}
 	return 0;
 }
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c
index 2ae8b1c..76e81cf 100644
--- a/fs/xfs/linux-2.6/xfs_globals.c
+++ b/fs/xfs/linux-2.6/xfs_globals.c
@@ -16,7 +16,6 @@
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include "xfs.h"
-#include "xfs_cred.h"
 #include "xfs_sysctl.h"
 
 /*
diff --git a/fs/xfs/linux-2.6/xfs_globals.h b/fs/xfs/linux-2.6/xfs_globals.h
deleted file mode 100644
index 69f71ca..0000000
--- a/fs/xfs/linux-2.6/xfs_globals.h
+++ /dev/null
@@ -1,23 +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
- */
-#ifndef __XFS_GLOBALS_H__
-#define __XFS_GLOBALS_H__
-
-extern uint64_t	xfs_panic_mask;		/* set to cause more panics */
-
-#endif	/* __XFS_GLOBALS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 3b9e626..2ea238f6 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -790,7 +790,7 @@
 	xfs_ilock(ip, XFS_ILOCK_SHARED);
 	fa.fsx_xflags = xfs_ip2xflags(ip);
 	fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
-	fa.fsx_projid = ip->i_d.di_projid;
+	fa.fsx_projid = xfs_get_projid(ip);
 
 	if (attr) {
 		if (ip->i_afp) {
@@ -909,10 +909,10 @@
 		return XFS_ERROR(EIO);
 
 	/*
-	 * Disallow 32bit project ids because on-disk structure
-	 * is 16bit only.
+	 * Disallow 32bit project ids when projid32bit feature is not enabled.
 	 */
-	if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1))
+	if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1) &&
+			!xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
 		return XFS_ERROR(EINVAL);
 
 	/*
@@ -961,7 +961,7 @@
 	if (mask & FSX_PROJID) {
 		if (XFS_IS_QUOTA_RUNNING(mp) &&
 		    XFS_IS_PQUOTA_ON(mp) &&
-		    ip->i_d.di_projid != fa->fsx_projid) {
+		    xfs_get_projid(ip) != fa->fsx_projid) {
 			ASSERT(tp);
 			code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
 						capable(CAP_FOWNER) ?
@@ -1063,12 +1063,12 @@
 		 * Change the ownerships and register quota modifications
 		 * in the transaction.
 		 */
-		if (ip->i_d.di_projid != fa->fsx_projid) {
+		if (xfs_get_projid(ip) != fa->fsx_projid) {
 			if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
 				olddquot = xfs_qm_vop_chown(tp, ip,
 							&ip->i_gdquot, gdqp);
 			}
-			ip->i_d.di_projid = fa->fsx_projid;
+			xfs_set_projid(ip, fa->fsx_projid);
 
 			/*
 			 * We may have to rev the inode as well as
@@ -1088,8 +1088,8 @@
 		xfs_diflags_to_linux(ip);
 	}
 
+	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-	xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
 
 	XFS_STATS_INC(xs_ig_attrchg);
 
@@ -1301,7 +1301,8 @@
 	case XFS_IOC_ALLOCSP64:
 	case XFS_IOC_FREESP64:
 	case XFS_IOC_RESVSP64:
-	case XFS_IOC_UNRESVSP64: {
+	case XFS_IOC_UNRESVSP64:
+	case XFS_IOC_ZERO_RANGE: {
 		xfs_flock64_t		bf;
 
 		if (copy_from_user(&bf, arg, sizeof(bf)))
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 6c83f7f..b3486df 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -164,7 +164,8 @@
 	    get_user(bstat->bs_extsize,	&bstat32->bs_extsize)	||
 	    get_user(bstat->bs_extents,	&bstat32->bs_extents)	||
 	    get_user(bstat->bs_gen,	&bstat32->bs_gen)	||
-	    get_user(bstat->bs_projid,	&bstat32->bs_projid)	||
+	    get_user(bstat->bs_projid_lo, &bstat32->bs_projid_lo) ||
+	    get_user(bstat->bs_projid_hi, &bstat32->bs_projid_hi) ||
 	    get_user(bstat->bs_dmevmask, &bstat32->bs_dmevmask)	||
 	    get_user(bstat->bs_dmstate,	&bstat32->bs_dmstate)	||
 	    get_user(bstat->bs_aextents, &bstat32->bs_aextents))
@@ -218,6 +219,7 @@
 	    put_user(buffer->bs_extents,  &p32->bs_extents)	||
 	    put_user(buffer->bs_gen,	  &p32->bs_gen)		||
 	    put_user(buffer->bs_projid,	  &p32->bs_projid)	||
+	    put_user(buffer->bs_projid_hi,	&p32->bs_projid_hi)	||
 	    put_user(buffer->bs_dmevmask, &p32->bs_dmevmask)	||
 	    put_user(buffer->bs_dmstate,  &p32->bs_dmstate)	||
 	    put_user(buffer->bs_aextents, &p32->bs_aextents))
@@ -574,6 +576,7 @@
 	case XFS_IOC_FSGEOMETRY_V1:
 	case XFS_IOC_FSGROWFSDATA:
 	case XFS_IOC_FSGROWFSRT:
+	case XFS_IOC_ZERO_RANGE:
 		return xfs_file_ioctl(filp, cmd, p);
 #else
 	case XFS_IOC_ALLOCSP_32:
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h
index 1024c4f..08b6057 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.h
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.h
@@ -65,8 +65,10 @@
 	__s32		bs_extsize;	/* extent size			*/
 	__s32		bs_extents;	/* number of extents		*/
 	__u32		bs_gen;		/* generation count		*/
-	__u16		bs_projid;	/* project id			*/
-	unsigned char	bs_pad[14];	/* pad space, unused		*/
+	__u16		bs_projid_lo;	/* lower part of project id	*/
+#define	bs_projid	bs_projid_lo	/* (previously just bs_projid)	*/
+	__u16		bs_projid_hi;	/* high part of project id	*/
+	unsigned char	bs_pad[12];	/* pad space, unused		*/
 	__u32		bs_dmevmask;	/* DMIG event mask		*/
 	__u16		bs_dmstate;	/* DMIG state info		*/
 	__u16		bs_aextents;	/* attribute number of extents	*/
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index b1fc2a6..ec858e0 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -95,41 +95,6 @@
 }
 
 /*
- * Change the requested timestamp in the given inode.
- * We don't lock across timestamp updates, and we don't log them but
- * we do record the fact that there is dirty information in core.
- */
-void
-xfs_ichgtime(
-	xfs_inode_t	*ip,
-	int		flags)
-{
-	struct inode	*inode = VFS_I(ip);
-	timespec_t	tv;
-	int		sync_it = 0;
-
-	tv = current_fs_time(inode->i_sb);
-
-	if ((flags & XFS_ICHGTIME_MOD) &&
-	    !timespec_equal(&inode->i_mtime, &tv)) {
-		inode->i_mtime = tv;
-		sync_it = 1;
-	}
-	if ((flags & XFS_ICHGTIME_CHG) &&
-	    !timespec_equal(&inode->i_ctime, &tv)) {
-		inode->i_ctime = tv;
-		sync_it = 1;
-	}
-
-	/*
-	 * Update complete - now make sure everyone knows that the inode
-	 * is dirty.
-	 */
-	if (sync_it)
-		xfs_mark_inode_dirty_sync(ip);
-}
-
-/*
  * Hook in SELinux.  This is not quite correct yet, what we really need
  * here (as we do for default ACLs) is a mechanism by which creation of
  * these attrs can be journalled at inode creation time (along with the
@@ -224,7 +189,7 @@
 	}
 
 	xfs_dentry_to_name(&name, dentry);
-	error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip, NULL);
+	error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
 	if (unlikely(error))
 		goto out_free_acl;
 
@@ -397,7 +362,7 @@
 		(irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO);
 	xfs_dentry_to_name(&name, dentry);
 
-	error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip, NULL);
+	error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip);
 	if (unlikely(error))
 		goto out;
 
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 2fa0bd9..214ddd7 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -71,6 +71,7 @@
 #include <linux/random.h>
 #include <linux/ctype.h>
 #include <linux/writeback.h>
+#include <linux/capability.h>
 
 #include <asm/page.h>
 #include <asm/div64.h>
@@ -79,14 +80,12 @@
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
-#include <xfs_cred.h>
 #include <xfs_vnode.h>
 #include <xfs_stats.h>
 #include <xfs_sysctl.h>
 #include <xfs_iops.h>
 #include <xfs_aops.h>
 #include <xfs_super.h>
-#include <xfs_globals.h>
 #include <xfs_buf.h>
 
 /*
@@ -144,7 +143,7 @@
 #define SYNCHRONIZE()	barrier()
 #define __return_address __builtin_return_address(0)
 
-#define dfltprid	0
+#define XFS_PROJID_DEFAULT	0
 #define MAXPATHLEN	1024
 
 #define MIN(a,b)	(min(a,b))
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index a4e0797..ab31ce5 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -44,7 +44,6 @@
 #include "xfs_buf_item.h"
 #include "xfs_utils.h"
 #include "xfs_vnodeops.h"
-#include "xfs_version.h"
 #include "xfs_log_priv.h"
 #include "xfs_trans_priv.h"
 #include "xfs_filestream.h"
@@ -645,7 +644,7 @@
 	XFS_BUF_ORDERED(sbp);
 
 	xfsbdstrat(mp, sbp);
-	error = xfs_iowait(sbp);
+	error = xfs_buf_iowait(sbp);
 
 	/*
 	 * Clear all the flags we set and possible error state in the
@@ -693,8 +692,7 @@
 xfs_blkdev_issue_flush(
 	xfs_buftarg_t		*buftarg)
 {
-	blkdev_issue_flush(buftarg->bt_bdev, GFP_KERNEL, NULL,
-			BLKDEV_IFL_WAIT);
+	blkdev_issue_flush(buftarg->bt_bdev, GFP_KERNEL, NULL);
 }
 
 STATIC void
@@ -758,18 +756,20 @@
 	 * Setup xfs_mount buffer target pointers
 	 */
 	error = ENOMEM;
-	mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0, mp->m_fsname);
+	mp->m_ddev_targp = xfs_alloc_buftarg(mp, ddev, 0, mp->m_fsname);
 	if (!mp->m_ddev_targp)
 		goto out_close_rtdev;
 
 	if (rtdev) {
-		mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1, mp->m_fsname);
+		mp->m_rtdev_targp = xfs_alloc_buftarg(mp, rtdev, 1,
+							mp->m_fsname);
 		if (!mp->m_rtdev_targp)
 			goto out_free_ddev_targ;
 	}
 
 	if (logdev && logdev != ddev) {
-		mp->m_logdev_targp = xfs_alloc_buftarg(logdev, 1, mp->m_fsname);
+		mp->m_logdev_targp = xfs_alloc_buftarg(mp, logdev, 1,
+							mp->m_fsname);
 		if (!mp->m_logdev_targp)
 			goto out_free_rtdev_targ;
 	} else {
@@ -972,12 +972,7 @@
 
 /*
  * Dirty the XFS inode when mark_inode_dirty_sync() is called so that
- * we catch unlogged VFS level updates to the inode. Care must be taken
- * here - the transaction code calls mark_inode_dirty_sync() to mark the
- * VFS inode dirty in a transaction and clears the i_update_core field;
- * it must clear the field after calling mark_inode_dirty_sync() to
- * correctly indicate that the dirty state has been propagated into the
- * inode log item.
+ * we catch unlogged VFS level updates to the inode.
  *
  * We need the barrier() to maintain correct ordering between unlogged
  * updates and the transaction commit code that clears the i_update_core
@@ -1521,8 +1516,9 @@
 	if (error)
 		goto out_free_fsname;
 
-	if (xfs_icsb_init_counters(mp))
-		mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB;
+	error = xfs_icsb_init_counters(mp);
+	if (error)
+		goto out_close_devices;
 
 	error = xfs_readsb(mp, flags);
 	if (error)
@@ -1583,6 +1579,7 @@
 	xfs_freesb(mp);
  out_destroy_counters:
 	xfs_icsb_destroy_counters(mp);
+ out_close_devices:
 	xfs_close_devices(mp);
  out_free_fsname:
 	xfs_free_fsname(mp);
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index 1ef4a4d..50a3266 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -62,6 +62,7 @@
 # define XFS_DBG_STRING		"no debug"
 #endif
 
+#define XFS_VERSION_STRING	"SGI XFS"
 #define XFS_BUILD_OPTIONS	XFS_ACL_STRING \
 				XFS_SECURITY_STRING \
 				XFS_REALTIME_STRING \
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index d59c4a6..37d3325 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -39,42 +39,39 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
+/*
+ * The inode lookup is done in batches to keep the amount of lock traffic and
+ * radix tree lookups to a minimum. The batch size is a trade off between
+ * lookup reduction and stack usage. This is in the reclaim path, so we can't
+ * be too greedy.
+ */
+#define XFS_LOOKUP_BATCH	32
 
-STATIC xfs_inode_t *
-xfs_inode_ag_lookup(
-	struct xfs_mount	*mp,
-	struct xfs_perag	*pag,
-	uint32_t		*first_index,
-	int			tag)
+STATIC int
+xfs_inode_ag_walk_grab(
+	struct xfs_inode	*ip)
 {
-	int			nr_found;
-	struct xfs_inode	*ip;
+	struct inode		*inode = VFS_I(ip);
 
-	/*
-	 * use a gang lookup to find the next inode in the tree
-	 * as the tree is sparse and a gang lookup walks to find
-	 * the number of objects requested.
-	 */
-	if (tag == XFS_ICI_NO_TAG) {
-		nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
-				(void **)&ip, *first_index, 1);
-	} else {
-		nr_found = radix_tree_gang_lookup_tag(&pag->pag_ici_root,
-				(void **)&ip, *first_index, 1, tag);
+	/* nothing to sync during shutdown */
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return EFSCORRUPTED;
+
+	/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
+	if (xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
+		return ENOENT;
+
+	/* If we can't grab the inode, it must on it's way to reclaim. */
+	if (!igrab(inode))
+		return ENOENT;
+
+	if (is_bad_inode(inode)) {
+		IRELE(ip);
+		return ENOENT;
 	}
-	if (!nr_found)
-		return NULL;
 
-	/*
-	 * Update the index for the next lookup. Catch overflows
-	 * into the next AG range which can occur if we have inodes
-	 * in the last block of the AG and we are currently
-	 * pointing to the last inode.
-	 */
-	*first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
-	if (*first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
-		return NULL;
-	return ip;
+	/* inode is valid */
+	return 0;
 }
 
 STATIC int
@@ -83,49 +80,75 @@
 	struct xfs_perag	*pag,
 	int			(*execute)(struct xfs_inode *ip,
 					   struct xfs_perag *pag, int flags),
-	int			flags,
-	int			tag,
-	int			exclusive,
-	int			*nr_to_scan)
+	int			flags)
 {
 	uint32_t		first_index;
 	int			last_error = 0;
 	int			skipped;
+	int			done;
+	int			nr_found;
 
 restart:
+	done = 0;
 	skipped = 0;
 	first_index = 0;
+	nr_found = 0;
 	do {
+		struct xfs_inode *batch[XFS_LOOKUP_BATCH];
 		int		error = 0;
-		xfs_inode_t	*ip;
+		int		i;
 
-		if (exclusive)
-			write_lock(&pag->pag_ici_lock);
-		else
-			read_lock(&pag->pag_ici_lock);
-		ip = xfs_inode_ag_lookup(mp, pag, &first_index, tag);
-		if (!ip) {
-			if (exclusive)
-				write_unlock(&pag->pag_ici_lock);
-			else
-				read_unlock(&pag->pag_ici_lock);
+		read_lock(&pag->pag_ici_lock);
+		nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
+					(void **)batch, first_index,
+					XFS_LOOKUP_BATCH);
+		if (!nr_found) {
+			read_unlock(&pag->pag_ici_lock);
 			break;
 		}
 
-		/* execute releases pag->pag_ici_lock */
-		error = execute(ip, pag, flags);
-		if (error == EAGAIN) {
-			skipped++;
-			continue;
+		/*
+		 * Grab the inodes before we drop the lock. if we found
+		 * nothing, nr == 0 and the loop will be skipped.
+		 */
+		for (i = 0; i < nr_found; i++) {
+			struct xfs_inode *ip = batch[i];
+
+			if (done || xfs_inode_ag_walk_grab(ip))
+				batch[i] = NULL;
+
+			/*
+			 * Update the index for the next lookup. Catch overflows
+			 * into the next AG range which can occur if we have inodes
+			 * in the last block of the AG and we are currently
+			 * pointing to the last inode.
+			 */
+			first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
+			if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
+				done = 1;
 		}
-		if (error)
-			last_error = error;
+
+		/* unlock now we've grabbed the inodes. */
+		read_unlock(&pag->pag_ici_lock);
+
+		for (i = 0; i < nr_found; i++) {
+			if (!batch[i])
+				continue;
+			error = execute(batch[i], pag, flags);
+			IRELE(batch[i]);
+			if (error == EAGAIN) {
+				skipped++;
+				continue;
+			}
+			if (error && last_error != EFSCORRUPTED)
+				last_error = error;
+		}
 
 		/* bail out if the filesystem is corrupted.  */
 		if (error == EFSCORRUPTED)
 			break;
 
-	} while ((*nr_to_scan)--);
+	} while (nr_found && !done);
 
 	if (skipped) {
 		delay(1);
@@ -134,110 +157,32 @@
 	return last_error;
 }
 
-/*
- * Select the next per-ag structure to iterate during the walk. The reclaim
- * walk is optimised only to walk AGs with reclaimable inodes in them.
- */
-static struct xfs_perag *
-xfs_inode_ag_iter_next_pag(
-	struct xfs_mount	*mp,
-	xfs_agnumber_t		*first,
-	int			tag)
-{
-	struct xfs_perag	*pag = NULL;
-
-	if (tag == XFS_ICI_RECLAIM_TAG) {
-		int found;
-		int ref;
-
-		spin_lock(&mp->m_perag_lock);
-		found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
-				(void **)&pag, *first, 1, tag);
-		if (found <= 0) {
-			spin_unlock(&mp->m_perag_lock);
-			return NULL;
-		}
-		*first = pag->pag_agno + 1;
-		/* open coded pag reference increment */
-		ref = atomic_inc_return(&pag->pag_ref);
-		spin_unlock(&mp->m_perag_lock);
-		trace_xfs_perag_get_reclaim(mp, pag->pag_agno, ref, _RET_IP_);
-	} else {
-		pag = xfs_perag_get(mp, *first);
-		(*first)++;
-	}
-	return pag;
-}
-
 int
 xfs_inode_ag_iterator(
 	struct xfs_mount	*mp,
 	int			(*execute)(struct xfs_inode *ip,
 					   struct xfs_perag *pag, int flags),
-	int			flags,
-	int			tag,
-	int			exclusive,
-	int			*nr_to_scan)
+	int			flags)
 {
 	struct xfs_perag	*pag;
 	int			error = 0;
 	int			last_error = 0;
 	xfs_agnumber_t		ag;
-	int			nr;
 
-	nr = nr_to_scan ? *nr_to_scan : INT_MAX;
 	ag = 0;
-	while ((pag = xfs_inode_ag_iter_next_pag(mp, &ag, tag))) {
-		error = xfs_inode_ag_walk(mp, pag, execute, flags, tag,
-						exclusive, &nr);
+	while ((pag = xfs_perag_get(mp, ag))) {
+		ag = pag->pag_agno + 1;
+		error = xfs_inode_ag_walk(mp, pag, execute, flags);
 		xfs_perag_put(pag);
 		if (error) {
 			last_error = error;
 			if (error == EFSCORRUPTED)
 				break;
 		}
-		if (nr <= 0)
-			break;
 	}
-	if (nr_to_scan)
-		*nr_to_scan = nr;
 	return XFS_ERROR(last_error);
 }
 
-/* must be called with pag_ici_lock held and releases it */
-int
-xfs_sync_inode_valid(
-	struct xfs_inode	*ip,
-	struct xfs_perag	*pag)
-{
-	struct inode		*inode = VFS_I(ip);
-	int			error = EFSCORRUPTED;
-
-	/* nothing to sync during shutdown */
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
-		goto out_unlock;
-
-	/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
-	error = ENOENT;
-	if (xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
-		goto out_unlock;
-
-	/* If we can't grab the inode, it must on it's way to reclaim. */
-	if (!igrab(inode))
-		goto out_unlock;
-
-	if (is_bad_inode(inode)) {
-		IRELE(ip);
-		goto out_unlock;
-	}
-
-	/* inode is valid */
-	error = 0;
-out_unlock:
-	read_unlock(&pag->pag_ici_lock);
-	return error;
-}
-
 STATIC int
 xfs_sync_inode_data(
 	struct xfs_inode	*ip,
@@ -248,10 +193,6 @@
 	struct address_space *mapping = inode->i_mapping;
 	int			error = 0;
 
-	error = xfs_sync_inode_valid(ip, pag);
-	if (error)
-		return error;
-
 	if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
 		goto out_wait;
 
@@ -268,7 +209,6 @@
  out_wait:
 	if (flags & SYNC_WAIT)
 		xfs_ioend_wait(ip);
-	IRELE(ip);
 	return error;
 }
 
@@ -280,10 +220,6 @@
 {
 	int			error = 0;
 
-	error = xfs_sync_inode_valid(ip, pag);
-	if (error)
-		return error;
-
 	xfs_ilock(ip, XFS_ILOCK_SHARED);
 	if (xfs_inode_clean(ip))
 		goto out_unlock;
@@ -302,7 +238,6 @@
 
  out_unlock:
 	xfs_iunlock(ip, XFS_ILOCK_SHARED);
-	IRELE(ip);
 	return error;
 }
 
@@ -318,8 +253,7 @@
 
 	ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0);
 
-	error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags,
-				      XFS_ICI_NO_TAG, 0, NULL);
+	error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags);
 	if (error)
 		return XFS_ERROR(error);
 
@@ -337,8 +271,7 @@
 {
 	ASSERT((flags & ~SYNC_WAIT) == 0);
 
-	return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags,
-				     XFS_ICI_NO_TAG, 0, NULL);
+	return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags);
 }
 
 STATIC int
@@ -668,14 +601,11 @@
 	xfs_perag_put(pag);
 }
 
-void
-__xfs_inode_clear_reclaim_tag(
-	xfs_mount_t	*mp,
+STATIC void
+__xfs_inode_clear_reclaim(
 	xfs_perag_t	*pag,
 	xfs_inode_t	*ip)
 {
-	radix_tree_tag_clear(&pag->pag_ici_root,
-			XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
 	pag->pag_ici_reclaimable--;
 	if (!pag->pag_ici_reclaimable) {
 		/* clear the reclaim tag from the perag radix tree */
@@ -689,6 +619,54 @@
 	}
 }
 
+void
+__xfs_inode_clear_reclaim_tag(
+	xfs_mount_t	*mp,
+	xfs_perag_t	*pag,
+	xfs_inode_t	*ip)
+{
+	radix_tree_tag_clear(&pag->pag_ici_root,
+			XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
+	__xfs_inode_clear_reclaim(pag, ip);
+}
+
+/*
+ * Grab the inode for reclaim exclusively.
+ * Return 0 if we grabbed it, non-zero otherwise.
+ */
+STATIC int
+xfs_reclaim_inode_grab(
+	struct xfs_inode	*ip,
+	int			flags)
+{
+
+	/*
+	 * do some unlocked checks first to avoid unnecceary lock traffic.
+	 * The first is a flush lock check, the second is a already in reclaim
+	 * check. Only do these checks if we are not going to block on locks.
+	 */
+	if ((flags & SYNC_TRYLOCK) &&
+	    (!ip->i_flush.done || __xfs_iflags_test(ip, XFS_IRECLAIM))) {
+		return 1;
+	}
+
+	/*
+	 * The radix tree lock here protects a thread in xfs_iget from racing
+	 * with us starting reclaim on the inode.  Once we have the
+	 * XFS_IRECLAIM flag set it will not touch us.
+	 */
+	spin_lock(&ip->i_flags_lock);
+	ASSERT_ALWAYS(__xfs_iflags_test(ip, XFS_IRECLAIMABLE));
+	if (__xfs_iflags_test(ip, XFS_IRECLAIM)) {
+		/* ignore as it is already under reclaim */
+		spin_unlock(&ip->i_flags_lock);
+		return 1;
+	}
+	__xfs_iflags_set(ip, XFS_IRECLAIM);
+	spin_unlock(&ip->i_flags_lock);
+	return 0;
+}
+
 /*
  * Inodes in different states need to be treated differently, and the return
  * value of xfs_iflush is not sufficient to get this right. The following table
@@ -747,23 +725,6 @@
 {
 	int	error = 0;
 
-	/*
-	 * The radix tree lock here protects a thread in xfs_iget from racing
-	 * with us starting reclaim on the inode.  Once we have the
-	 * XFS_IRECLAIM flag set it will not touch us.
-	 */
-	spin_lock(&ip->i_flags_lock);
-	ASSERT_ALWAYS(__xfs_iflags_test(ip, XFS_IRECLAIMABLE));
-	if (__xfs_iflags_test(ip, XFS_IRECLAIM)) {
-		/* ignore as it is already under reclaim */
-		spin_unlock(&ip->i_flags_lock);
-		write_unlock(&pag->pag_ici_lock);
-		return 0;
-	}
-	__xfs_iflags_set(ip, XFS_IRECLAIM);
-	spin_unlock(&ip->i_flags_lock);
-	write_unlock(&pag->pag_ici_lock);
-
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
 	if (!xfs_iflock_nowait(ip)) {
 		if (!(sync_mode & SYNC_WAIT))
@@ -838,6 +799,7 @@
 	if (!radix_tree_delete(&pag->pag_ici_root,
 				XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino)))
 		ASSERT(0);
+	__xfs_inode_clear_reclaim(pag, ip);
 	write_unlock(&pag->pag_ici_lock);
 
 	/*
@@ -859,13 +821,126 @@
 
 }
 
+/*
+ * Walk the AGs and reclaim the inodes in them. Even if the filesystem is
+ * corrupted, we still want to try to reclaim all the inodes. If we don't,
+ * then a shut down during filesystem unmount reclaim walk leak all the
+ * unreclaimed inodes.
+ */
+int
+xfs_reclaim_inodes_ag(
+	struct xfs_mount	*mp,
+	int			flags,
+	int			*nr_to_scan)
+{
+	struct xfs_perag	*pag;
+	int			error = 0;
+	int			last_error = 0;
+	xfs_agnumber_t		ag;
+	int			trylock = flags & SYNC_TRYLOCK;
+	int			skipped;
+
+restart:
+	ag = 0;
+	skipped = 0;
+	while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
+		unsigned long	first_index = 0;
+		int		done = 0;
+		int		nr_found = 0;
+
+		ag = pag->pag_agno + 1;
+
+		if (trylock) {
+			if (!mutex_trylock(&pag->pag_ici_reclaim_lock)) {
+				skipped++;
+				continue;
+			}
+			first_index = pag->pag_ici_reclaim_cursor;
+		} else
+			mutex_lock(&pag->pag_ici_reclaim_lock);
+
+		do {
+			struct xfs_inode *batch[XFS_LOOKUP_BATCH];
+			int	i;
+
+			write_lock(&pag->pag_ici_lock);
+			nr_found = radix_tree_gang_lookup_tag(
+					&pag->pag_ici_root,
+					(void **)batch, first_index,
+					XFS_LOOKUP_BATCH,
+					XFS_ICI_RECLAIM_TAG);
+			if (!nr_found) {
+				write_unlock(&pag->pag_ici_lock);
+				break;
+			}
+
+			/*
+			 * Grab the inodes before we drop the lock. if we found
+			 * nothing, nr == 0 and the loop will be skipped.
+			 */
+			for (i = 0; i < nr_found; i++) {
+				struct xfs_inode *ip = batch[i];
+
+				if (done || xfs_reclaim_inode_grab(ip, flags))
+					batch[i] = NULL;
+
+				/*
+				 * Update the index for the next lookup. Catch
+				 * overflows into the next AG range which can
+				 * occur if we have inodes in the last block of
+				 * the AG and we are currently pointing to the
+				 * last inode.
+				 */
+				first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
+				if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
+					done = 1;
+			}
+
+			/* unlock now we've grabbed the inodes. */
+			write_unlock(&pag->pag_ici_lock);
+
+			for (i = 0; i < nr_found; i++) {
+				if (!batch[i])
+					continue;
+				error = xfs_reclaim_inode(batch[i], pag, flags);
+				if (error && last_error != EFSCORRUPTED)
+					last_error = error;
+			}
+
+			*nr_to_scan -= XFS_LOOKUP_BATCH;
+
+		} while (nr_found && !done && *nr_to_scan > 0);
+
+		if (trylock && !done)
+			pag->pag_ici_reclaim_cursor = first_index;
+		else
+			pag->pag_ici_reclaim_cursor = 0;
+		mutex_unlock(&pag->pag_ici_reclaim_lock);
+		xfs_perag_put(pag);
+	}
+
+	/*
+	 * if we skipped any AG, and we still have scan count remaining, do
+	 * another pass this time using blocking reclaim semantics (i.e
+	 * waiting on the reclaim locks and ignoring the reclaim cursors). This
+	 * ensure that when we get more reclaimers than AGs we block rather
+	 * than spin trying to execute reclaim.
+	 */
+	if (trylock && skipped && *nr_to_scan > 0) {
+		trylock = 0;
+		goto restart;
+	}
+	return XFS_ERROR(last_error);
+}
+
 int
 xfs_reclaim_inodes(
 	xfs_mount_t	*mp,
 	int		mode)
 {
-	return xfs_inode_ag_iterator(mp, xfs_reclaim_inode, mode,
-					XFS_ICI_RECLAIM_TAG, 1, NULL);
+	int		nr_to_scan = INT_MAX;
+
+	return xfs_reclaim_inodes_ag(mp, mode, &nr_to_scan);
 }
 
 /*
@@ -887,17 +962,16 @@
 		if (!(gfp_mask & __GFP_FS))
 			return -1;
 
-		xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0,
-					XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan);
-		/* if we don't exhaust the scan, don't bother coming back */
+		xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK, &nr_to_scan);
+		/* terminate if we don't exhaust the scan */
 		if (nr_to_scan > 0)
 			return -1;
        }
 
 	reclaimable = 0;
 	ag = 0;
-	while ((pag = xfs_inode_ag_iter_next_pag(mp, &ag,
-					XFS_ICI_RECLAIM_TAG))) {
+	while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
+		ag = pag->pag_agno + 1;
 		reclaimable += pag->pag_ici_reclaimable;
 		xfs_perag_put(pag);
 	}
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h
index fe78726..32ba662 100644
--- a/fs/xfs/linux-2.6/xfs_sync.h
+++ b/fs/xfs/linux-2.6/xfs_sync.h
@@ -47,10 +47,10 @@
 void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag,
 				struct xfs_inode *ip);
 
-int xfs_sync_inode_valid(struct xfs_inode *ip, struct xfs_perag *pag);
+int xfs_sync_inode_grab(struct xfs_inode *ip);
 int xfs_inode_ag_iterator(struct xfs_mount *mp,
 	int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
-	int flags, int tag, int write_lock, int *nr_to_scan);
+	int flags);
 
 void xfs_inode_shrinker_register(struct xfs_mount *mp);
 void xfs_inode_shrinker_unregister(struct xfs_mount *mp);
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h
index be5dffd..acef2e9 100644
--- a/fs/xfs/linux-2.6/xfs_trace.h
+++ b/fs/xfs/linux-2.6/xfs_trace.h
@@ -124,7 +124,7 @@
 		 unsigned long caller_ip),					\
 	TP_ARGS(mp, agno, refcount, caller_ip))
 DEFINE_PERAG_REF_EVENT(xfs_perag_get);
-DEFINE_PERAG_REF_EVENT(xfs_perag_get_reclaim);
+DEFINE_PERAG_REF_EVENT(xfs_perag_get_tag);
 DEFINE_PERAG_REF_EVENT(xfs_perag_put);
 DEFINE_PERAG_REF_EVENT(xfs_perag_set_reclaim);
 DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim);
@@ -325,13 +325,12 @@
 DEFINE_BUF_EVENT(xfs_buf_lock_done);
 DEFINE_BUF_EVENT(xfs_buf_cond_lock);
 DEFINE_BUF_EVENT(xfs_buf_unlock);
-DEFINE_BUF_EVENT(xfs_buf_ordered_retry);
 DEFINE_BUF_EVENT(xfs_buf_iowait);
 DEFINE_BUF_EVENT(xfs_buf_iowait_done);
 DEFINE_BUF_EVENT(xfs_buf_delwri_queue);
 DEFINE_BUF_EVENT(xfs_buf_delwri_dequeue);
 DEFINE_BUF_EVENT(xfs_buf_delwri_split);
-DEFINE_BUF_EVENT(xfs_buf_get_noaddr);
+DEFINE_BUF_EVENT(xfs_buf_get_uncached);
 DEFINE_BUF_EVENT(xfs_bdstrat_shut);
 DEFINE_BUF_EVENT(xfs_buf_item_relse);
 DEFINE_BUF_EVENT(xfs_buf_item_iodone);
diff --git a/fs/xfs/linux-2.6/xfs_version.h b/fs/xfs/linux-2.6/xfs_version.h
deleted file mode 100644
index f8d279d..0000000
--- a/fs/xfs/linux-2.6/xfs_version.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2001-2002,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_VERSION_H__
-#define __XFS_VERSION_H__
-
-/*
- * Dummy file that can contain a timestamp to put into the
- * XFS init string, to help users keep track of what they're
- * running
- */
-
-#define XFS_VERSION_STRING "SGI XFS"
-
-#endif /* __XFS_VERSION_H__ */
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index e1a2f68..faf8e1a 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -463,88 +463,69 @@
 	uint			flags)
 {
 	xfs_bmbt_irec_t map;
-	int		nmaps, error;
+	int		nmaps = 1, error;
 	xfs_buf_t	*bp;
-	xfs_inode_t	*quotip;
-	xfs_mount_t	*mp;
+	xfs_inode_t	*quotip = XFS_DQ_TO_QIP(dqp);
+	xfs_mount_t	*mp = dqp->q_mount;
 	xfs_disk_dquot_t *ddq;
-	xfs_dqid_t	id;
-	boolean_t	newdquot;
+	xfs_dqid_t	id = be32_to_cpu(dqp->q_core.d_id);
 	xfs_trans_t	*tp = (tpp ? *tpp : NULL);
 
-	mp = dqp->q_mount;
-	id = be32_to_cpu(dqp->q_core.d_id);
-	nmaps = 1;
-	newdquot = B_FALSE;
+	dqp->q_fileoffset = (xfs_fileoff_t)id / mp->m_quotainfo->qi_dqperchunk;
 
-	/*
-	 * If we don't know where the dquot lives, find out.
-	 */
-	if (dqp->q_blkno == (xfs_daddr_t) 0) {
-		/* We use the id as an index */
-		dqp->q_fileoffset = (xfs_fileoff_t)id /
-					mp->m_quotainfo->qi_dqperchunk;
-		nmaps = 1;
-		quotip = XFS_DQ_TO_QIP(dqp);
-		xfs_ilock(quotip, XFS_ILOCK_SHARED);
+	xfs_ilock(quotip, XFS_ILOCK_SHARED);
+	if (XFS_IS_THIS_QUOTA_OFF(dqp)) {
 		/*
-		 * Return if this type of quotas is turned off while we didn't
-		 * have an inode lock
+		 * Return if this type of quotas is turned off while we
+		 * didn't have the quota inode lock.
 		 */
-		if (XFS_IS_THIS_QUOTA_OFF(dqp)) {
-			xfs_iunlock(quotip, XFS_ILOCK_SHARED);
-			return (ESRCH);
-		}
-		/*
-		 * Find the block map; no allocations yet
-		 */
-		error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset,
-				  XFS_DQUOT_CLUSTER_SIZE_FSB,
-				  XFS_BMAPI_METADATA,
-				  NULL, 0, &map, &nmaps, NULL);
-
 		xfs_iunlock(quotip, XFS_ILOCK_SHARED);
-		if (error)
-			return (error);
-		ASSERT(nmaps == 1);
-		ASSERT(map.br_blockcount == 1);
-
-		/*
-		 * offset of dquot in the (fixed sized) dquot chunk.
-		 */
-		dqp->q_bufoffset = (id % mp->m_quotainfo->qi_dqperchunk) *
-			sizeof(xfs_dqblk_t);
-		if (map.br_startblock == HOLESTARTBLOCK) {
-			/*
-			 * We don't allocate unless we're asked to
-			 */
-			if (!(flags & XFS_QMOPT_DQALLOC))
-				return (ENOENT);
-
-			ASSERT(tp);
-			if ((error = xfs_qm_dqalloc(tpp, mp, dqp, quotip,
-						dqp->q_fileoffset, &bp)))
-				return (error);
-			tp = *tpp;
-			newdquot = B_TRUE;
-		} else {
-			/*
-			 * store the blkno etc so that we don't have to do the
-			 * mapping all the time
-			 */
-			dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
-		}
+		return ESRCH;
 	}
-	ASSERT(dqp->q_blkno != DELAYSTARTBLOCK);
-	ASSERT(dqp->q_blkno != HOLESTARTBLOCK);
 
 	/*
-	 * Read in the buffer, unless we've just done the allocation
-	 * (in which case we already have the buf).
+	 * Find the block map; no allocations yet
 	 */
-	if (!newdquot) {
+	error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset,
+			  XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA,
+			  NULL, 0, &map, &nmaps, NULL);
+
+	xfs_iunlock(quotip, XFS_ILOCK_SHARED);
+	if (error)
+		return error;
+
+	ASSERT(nmaps == 1);
+	ASSERT(map.br_blockcount == 1);
+
+	/*
+	 * Offset of dquot in the (fixed sized) dquot chunk.
+	 */
+	dqp->q_bufoffset = (id % mp->m_quotainfo->qi_dqperchunk) *
+		sizeof(xfs_dqblk_t);
+
+	ASSERT(map.br_startblock != DELAYSTARTBLOCK);
+	if (map.br_startblock == HOLESTARTBLOCK) {
+		/*
+		 * We don't allocate unless we're asked to
+		 */
+		if (!(flags & XFS_QMOPT_DQALLOC))
+			return ENOENT;
+
+		ASSERT(tp);
+		error = xfs_qm_dqalloc(tpp, mp, dqp, quotip,
+					dqp->q_fileoffset, &bp);
+		if (error)
+			return error;
+		tp = *tpp;
+	} else {
 		trace_xfs_dqtobp_read(dqp);
 
+		/*
+		 * store the blkno etc so that we don't have to do the
+		 * mapping all the time
+		 */
+		dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
+
 		error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
 					   dqp->q_blkno,
 					   mp->m_quotainfo->qi_dqchunklen,
@@ -552,13 +533,14 @@
 		if (error || !bp)
 			return XFS_ERROR(error);
 	}
+
 	ASSERT(XFS_BUF_ISBUSY(bp));
 	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
 
 	/*
 	 * calculate the location of the dquot inside the buffer.
 	 */
-	ddq = (xfs_disk_dquot_t *)((char *)XFS_BUF_PTR(bp) + dqp->q_bufoffset);
+	ddq = (struct xfs_disk_dquot *)(XFS_BUF_PTR(bp) + dqp->q_bufoffset);
 
 	/*
 	 * A simple sanity check in case we got a corrupted dquot...
@@ -1176,18 +1158,18 @@
 	xfs_dquot_t		*dqp,
 	uint			flags)
 {
-	xfs_mount_t		*mp;
-	xfs_buf_t		*bp;
-	xfs_disk_dquot_t	*ddqp;
+	struct xfs_mount	*mp = dqp->q_mount;
+	struct xfs_buf		*bp;
+	struct xfs_disk_dquot	*ddqp;
 	int			error;
 
 	ASSERT(XFS_DQ_IS_LOCKED(dqp));
 	ASSERT(!completion_done(&dqp->q_flush));
+
 	trace_xfs_dqflush(dqp);
 
 	/*
-	 * If not dirty, or it's pinned and we are not supposed to
-	 * block, nada.
+	 * If not dirty, or it's pinned and we are not supposed to block, nada.
 	 */
 	if (!XFS_DQ_IS_DIRTY(dqp) ||
 	    (!(flags & SYNC_WAIT) && atomic_read(&dqp->q_pincount) > 0)) {
@@ -1201,40 +1183,46 @@
 	 * down forcibly. If that's the case we must not write this dquot
 	 * to disk, because the log record didn't make it to disk!
 	 */
-	if (XFS_FORCED_SHUTDOWN(dqp->q_mount)) {
-		dqp->dq_flags &= ~(XFS_DQ_DIRTY);
+	if (XFS_FORCED_SHUTDOWN(mp)) {
+		dqp->dq_flags &= ~XFS_DQ_DIRTY;
 		xfs_dqfunlock(dqp);
 		return XFS_ERROR(EIO);
 	}
 
 	/*
 	 * Get the buffer containing the on-disk dquot
-	 * We don't need a transaction envelope because we know that the
-	 * the ondisk-dquot has already been allocated for.
 	 */
-	if ((error = xfs_qm_dqtobp(NULL, dqp, &ddqp, &bp, XFS_QMOPT_DOWARN))) {
+	error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
+				   mp->m_quotainfo->qi_dqchunklen, 0, &bp);
+	if (error) {
 		ASSERT(error != ENOENT);
-		/*
-		 * Quotas could have gotten turned off (ESRCH)
-		 */
 		xfs_dqfunlock(dqp);
-		return (error);
+		return error;
 	}
 
-	if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id),
-			   0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
-		xfs_force_shutdown(dqp->q_mount, SHUTDOWN_CORRUPT_INCORE);
+	/*
+	 * Calculate the location of the dquot inside the buffer.
+	 */
+	ddqp = (struct xfs_disk_dquot *)(XFS_BUF_PTR(bp) + dqp->q_bufoffset);
+
+	/*
+	 * 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)")) {
+		xfs_buf_relse(bp);
+		xfs_dqfunlock(dqp);
+		xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 		return XFS_ERROR(EIO);
 	}
 
 	/* This is the only portion of data that needs to persist */
-	memcpy(ddqp, &(dqp->q_core), sizeof(xfs_disk_dquot_t));
+	memcpy(ddqp, &dqp->q_core, sizeof(xfs_disk_dquot_t));
 
 	/*
 	 * Clear the dirty field and remember the flush lsn for later use.
 	 */
-	dqp->dq_flags &= ~(XFS_DQ_DIRTY);
-	mp = dqp->q_mount;
+	dqp->dq_flags &= ~XFS_DQ_DIRTY;
 
 	xfs_trans_ail_copy_lsn(mp->m_ail, &dqp->q_logitem.qli_flush_lsn,
 					&dqp->q_logitem.qli_item.li_lsn);
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 9a92407..f8e854b 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -55,8 +55,6 @@
 kmem_zone_t	*qm_dqzone;
 kmem_zone_t	*qm_dqtrxzone;
 
-static cred_t	xfs_zerocr;
-
 STATIC void	xfs_qm_list_init(xfs_dqlist_t *, char *, int);
 STATIC void	xfs_qm_list_destroy(xfs_dqlist_t *);
 
@@ -837,7 +835,7 @@
 			xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
 						flags & XFS_QMOPT_DQALLOC,
 						ip->i_udquot, &ip->i_gdquot) :
-			xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
+			xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
 						flags & XFS_QMOPT_DQALLOC,
 						ip->i_udquot, &ip->i_gdquot);
 		/*
@@ -1199,87 +1197,6 @@
 	mutex_destroy(&(list->qh_lock));
 }
 
-
-/*
- * Stripped down version of dqattach. This doesn't attach, or even look at the
- * dquots attached to the inode. The rationale is that there won't be any
- * attached at the time this is called from quotacheck.
- */
-STATIC int
-xfs_qm_dqget_noattach(
-	xfs_inode_t	*ip,
-	xfs_dquot_t	**O_udqpp,
-	xfs_dquot_t	**O_gdqpp)
-{
-	int		error;
-	xfs_mount_t	*mp;
-	xfs_dquot_t	*udqp, *gdqp;
-
-	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-	mp = ip->i_mount;
-	udqp = NULL;
-	gdqp = NULL;
-
-	if (XFS_IS_UQUOTA_ON(mp)) {
-		ASSERT(ip->i_udquot == NULL);
-		/*
-		 * We want the dquot allocated if it doesn't exist.
-		 */
-		if ((error = xfs_qm_dqget(mp, ip, ip->i_d.di_uid, XFS_DQ_USER,
-					 XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN,
-					 &udqp))) {
-			/*
-			 * Shouldn't be able to turn off quotas here.
-			 */
-			ASSERT(error != ESRCH);
-			ASSERT(error != ENOENT);
-			return error;
-		}
-		ASSERT(udqp);
-	}
-
-	if (XFS_IS_OQUOTA_ON(mp)) {
-		ASSERT(ip->i_gdquot == NULL);
-		if (udqp)
-			xfs_dqunlock(udqp);
-		error = XFS_IS_GQUOTA_ON(mp) ?
-				xfs_qm_dqget(mp, ip,
-					     ip->i_d.di_gid, XFS_DQ_GROUP,
-					     XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
-					     &gdqp) :
-				xfs_qm_dqget(mp, ip,
-					     ip->i_d.di_projid, XFS_DQ_PROJ,
-					     XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
-					     &gdqp);
-		if (error) {
-			if (udqp)
-				xfs_qm_dqrele(udqp);
-			ASSERT(error != ESRCH);
-			ASSERT(error != ENOENT);
-			return error;
-		}
-		ASSERT(gdqp);
-
-		/* Reacquire the locks in the right order */
-		if (udqp) {
-			if (! xfs_qm_dqlock_nowait(udqp)) {
-				xfs_dqunlock(gdqp);
-				xfs_dqlock(udqp);
-				xfs_dqlock(gdqp);
-			}
-		}
-	}
-
-	*O_udqpp = udqp;
-	*O_gdqpp = gdqp;
-
-#ifdef QUOTADEBUG
-	if (udqp) ASSERT(XFS_DQ_IS_LOCKED(udqp));
-	if (gdqp) ASSERT(XFS_DQ_IS_LOCKED(gdqp));
-#endif
-	return 0;
-}
-
 /*
  * Create an inode and return with a reference already taken, but unlocked
  * This is how we create quota inodes
@@ -1305,8 +1222,8 @@
 		return error;
 	}
 
-	if ((error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0,
-				   &xfs_zerocr, 0, 1, ip, &committed))) {
+	error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip, &committed);
+	if (error) {
 		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
 				 XFS_TRANS_ABORT);
 		return error;
@@ -1516,7 +1433,7 @@
 				rablkcnt =  map[i+1].br_blockcount;
 				rablkno = map[i+1].br_startblock;
 				while (rablkcnt--) {
-					xfs_baread(mp->m_ddev_targp,
+					xfs_buf_readahead(mp->m_ddev_targp,
 					       XFS_FSB_TO_DADDR(mp, rablkno),
 					       mp->m_quotainfo->qi_dqchunklen);
 					rablkno++;
@@ -1546,18 +1463,34 @@
 
 /*
  * Called by dqusage_adjust in doing a quotacheck.
- * Given the inode, and a dquot (either USR or GRP, doesn't matter),
- * this updates its incore copy as well as the buffer copy. This is
- * so that once the quotacheck is done, we can just log all the buffers,
- * as opposed to logging numerous updates to individual dquots.
+ *
+ * Given the inode, and a dquot id this updates both the incore dqout as well
+ * as the buffer copy. This is so that once the quotacheck is done, we can
+ * just log all the buffers, as opposed to logging numerous updates to
+ * individual dquots.
  */
-STATIC void
+STATIC int
 xfs_qm_quotacheck_dqadjust(
-	xfs_dquot_t		*dqp,
+	struct xfs_inode	*ip,
+	xfs_dqid_t		id,
+	uint			type,
 	xfs_qcnt_t		nblks,
 	xfs_qcnt_t		rtblks)
 {
-	ASSERT(XFS_DQ_IS_LOCKED(dqp));
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_dquot	*dqp;
+	int			error;
+
+	error = xfs_qm_dqget(mp, ip, id, type,
+			     XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN, &dqp);
+	if (error) {
+		/*
+		 * Shouldn't be able to turn off quotas here.
+		 */
+		ASSERT(error != ESRCH);
+		ASSERT(error != ENOENT);
+		return error;
+	}
 
 	trace_xfs_dqadjust(dqp);
 
@@ -1582,11 +1515,13 @@
 	 * There are no timers for the default values set in the root dquot.
 	 */
 	if (dqp->q_core.d_id) {
-		xfs_qm_adjust_dqlimits(dqp->q_mount, &dqp->q_core);
-		xfs_qm_adjust_dqtimers(dqp->q_mount, &dqp->q_core);
+		xfs_qm_adjust_dqlimits(mp, &dqp->q_core);
+		xfs_qm_adjust_dqtimers(mp, &dqp->q_core);
 	}
 
 	dqp->dq_flags |= XFS_DQ_DIRTY;
+	xfs_qm_dqput(dqp);
+	return 0;
 }
 
 STATIC int
@@ -1629,8 +1564,7 @@
 	int		*res)		/* result code value */
 {
 	xfs_inode_t	*ip;
-	xfs_dquot_t	*udqp, *gdqp;
-	xfs_qcnt_t	nblks, rtblks;
+	xfs_qcnt_t	nblks, rtblks = 0;
 	int		error;
 
 	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
@@ -1650,51 +1584,24 @@
 	 * the case in all other instances. It's OK that we do this because
 	 * quotacheck is done only at mount time.
 	 */
-	if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip))) {
+	error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip);
+	if (error) {
 		*res = BULKSTAT_RV_NOTHING;
 		return error;
 	}
 
-	/*
-	 * Obtain the locked dquots. In case of an error (eg. allocation
-	 * fails for ENOSPC), we return the negative of the error number
-	 * to bulkstat, so that it can get propagated to quotacheck() and
-	 * making us disable quotas for the file system.
-	 */
-	if ((error = xfs_qm_dqget_noattach(ip, &udqp, &gdqp))) {
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-		IRELE(ip);
-		*res = BULKSTAT_RV_GIVEUP;
-		return error;
-	}
+	ASSERT(ip->i_delayed_blks == 0);
 
-	rtblks = 0;
-	if (! XFS_IS_REALTIME_INODE(ip)) {
-		nblks = (xfs_qcnt_t)ip->i_d.di_nblocks;
-	} else {
+	if (XFS_IS_REALTIME_INODE(ip)) {
 		/*
 		 * Walk thru the extent list and count the realtime blocks.
 		 */
-		if ((error = xfs_qm_get_rtblks(ip, &rtblks))) {
-			xfs_iunlock(ip, XFS_ILOCK_EXCL);
-			IRELE(ip);
-			if (udqp)
-				xfs_qm_dqput(udqp);
-			if (gdqp)
-				xfs_qm_dqput(gdqp);
-			*res = BULKSTAT_RV_GIVEUP;
-			return error;
-		}
-		nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
+		error = xfs_qm_get_rtblks(ip, &rtblks);
+		if (error)
+			goto error0;
 	}
-	ASSERT(ip->i_delayed_blks == 0);
 
-	/*
-	 * We can't release the inode while holding its dquot locks.
-	 * The inode can go into inactive and might try to acquire the dquotlocks.
-	 * So, just unlock here and do a vn_rele at the end.
-	 */
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
 
 	/*
 	 * Add the (disk blocks and inode) resources occupied by this
@@ -1709,26 +1616,36 @@
 	 * and quotaoffs don't race. (Quotachecks happen at mount time only).
 	 */
 	if (XFS_IS_UQUOTA_ON(mp)) {
-		ASSERT(udqp);
-		xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks);
-		xfs_qm_dqput(udqp);
+		error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_uid,
+						   XFS_DQ_USER, nblks, rtblks);
+		if (error)
+			goto error0;
 	}
-	if (XFS_IS_OQUOTA_ON(mp)) {
-		ASSERT(gdqp);
-		xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks);
-		xfs_qm_dqput(gdqp);
-	}
-	/*
-	 * Now release the inode. This will send it to 'inactive', and
-	 * possibly even free blocks.
-	 */
-	IRELE(ip);
 
-	/*
-	 * Goto next inode.
-	 */
+	if (XFS_IS_GQUOTA_ON(mp)) {
+		error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_gid,
+						   XFS_DQ_GROUP, nblks, rtblks);
+		if (error)
+			goto error0;
+	}
+
+	if (XFS_IS_PQUOTA_ON(mp)) {
+		error = xfs_qm_quotacheck_dqadjust(ip, xfs_get_projid(ip),
+						   XFS_DQ_PROJ, nblks, rtblks);
+		if (error)
+			goto error0;
+	}
+
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	IRELE(ip);
 	*res = BULKSTAT_RV_DIDONE;
 	return 0;
+
+error0:
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	IRELE(ip);
+	*res = BULKSTAT_RV_GIVEUP;
+	return error;
 }
 
 /*
@@ -2224,7 +2141,7 @@
 
 
 /*
- * Given an inode, a uid and gid (from cred_t) make sure that we have
+ * Given an inode, a uid, gid and prid make sure that we have
  * allocated relevant dquot(s) on disk, and that we won't exceed inode
  * quotas by creating this file.
  * This also attaches dquot(s) to the given inode after locking it,
@@ -2332,7 +2249,7 @@
 			xfs_dqunlock(gq);
 		}
 	} else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
-		if (ip->i_d.di_projid != prid) {
+		if (xfs_get_projid(ip) != prid) {
 			xfs_iunlock(ip, lockflags);
 			if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
 						 XFS_DQ_PROJ,
@@ -2454,7 +2371,7 @@
 	}
 	if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
 		if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
-		     ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
+		     xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id))
 			prjflags = XFS_QMOPT_ENOSPC;
 
 		if (prjflags ||
@@ -2558,7 +2475,7 @@
 		ip->i_gdquot = gdqp;
 		ASSERT(XFS_IS_OQUOTA_ON(mp));
 		ASSERT((XFS_IS_GQUOTA_ON(mp) ?
-			ip->i_d.di_gid : ip->i_d.di_projid) ==
+			ip->i_d.di_gid : xfs_get_projid(ip)) ==
 				be32_to_cpu(gdqp->q_core.d_id));
 		xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
 	}
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index bea02d7..45b5cb1 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -81,7 +81,7 @@
 	xfs_mount_t		*mp = ip->i_mount;
 	xfs_dquot_t		*dqp;
 
-	if (!xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) {
+	if (!xfs_qm_dqget(mp, NULL, xfs_get_projid(ip), XFS_DQ_PROJ, 0, &dqp)) {
 		xfs_fill_statvfs_from_dquot(statp, &dqp->q_core);
 		xfs_qm_dqput(dqp);
 	}
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 45e5849..bdebc18 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -276,7 +276,7 @@
 		goto out_unlock;
 	}
 
-	xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
 
 out_unlock:
@@ -875,21 +875,14 @@
 	struct xfs_perag	*pag,
 	int			flags)
 {
-	int			error;
-
 	/* skip quota inodes */
 	if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
 	    ip == ip->i_mount->m_quotainfo->qi_gquotaip) {
 		ASSERT(ip->i_udquot == NULL);
 		ASSERT(ip->i_gdquot == NULL);
-		read_unlock(&pag->pag_ici_lock);
 		return 0;
 	}
 
-	error = xfs_sync_inode_valid(ip, pag);
-	if (error)
-		return error;
-
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
 	if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
 		xfs_qm_dqrele(ip->i_udquot);
@@ -900,8 +893,6 @@
 		ip->i_gdquot = NULL;
 	}
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
-	IRELE(ip);
 	return 0;
 }
 
@@ -918,8 +909,7 @@
 	uint		 flags)
 {
 	ASSERT(mp->m_quotainfo);
-	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags,
-				XFS_ICI_NO_TAG, 0, NULL);
+	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags);
 }
 
 /*------------------------------------------------------------------------*/
@@ -1175,7 +1165,7 @@
 	}
 	xfs_qm_internalqcheck_get_dquots(mp,
 					(xfs_dqid_t) ip->i_d.di_uid,
-					(xfs_dqid_t) ip->i_d.di_projid,
+					(xfs_dqid_t) xfs_get_projid(ip),
 					(xfs_dqid_t) ip->i_d.di_gid,
 					&ud, &gd);
 	if (XFS_IS_UQUOTA_ON(mp)) {
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 4917d4e..63c7a1a 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -230,6 +230,15 @@
 	rwlock_t	pag_ici_lock;	/* incore inode lock */
 	struct radix_tree_root pag_ici_root;	/* incore inode cache root */
 	int		pag_ici_reclaimable;	/* reclaimable inodes */
+	struct mutex	pag_ici_reclaim_lock;	/* serialisation point */
+	unsigned long	pag_ici_reclaim_cursor;	/* reclaim restart point */
+
+	/* buffer cache index */
+	spinlock_t	pag_buf_lock;	/* lock for pag_buf_tree */
+	struct rb_root	pag_buf_tree;	/* ordered tree of active buffers */
+
+	/* for rcu-safe freeing */
+	struct rcu_head	rcu_head;
 #endif
 	int		pagb_count;	/* pagb slots in use */
 } xfs_perag_t;
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index af168fa..112abc4 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -675,7 +675,7 @@
 	xfs_agblock_t	gtbnoa;		/* aligned ... */
 	xfs_extlen_t	gtdiff;		/* difference to right side entry */
 	xfs_extlen_t	gtlen;		/* length of right side entry */
-	xfs_extlen_t	gtlena;		/* aligned ... */
+	xfs_extlen_t	gtlena = 0;	/* aligned ... */
 	xfs_agblock_t	gtnew;		/* useful start bno of right side */
 	int		error;		/* error code */
 	int		i;		/* result code, temporary */
@@ -684,7 +684,7 @@
 	xfs_agblock_t	ltbnoa;		/* aligned ... */
 	xfs_extlen_t	ltdiff;		/* difference to left side entry */
 	xfs_extlen_t	ltlen;		/* length of left side entry */
-	xfs_extlen_t	ltlena;		/* aligned ... */
+	xfs_extlen_t	ltlena = 0;	/* aligned ... */
 	xfs_agblock_t	ltnew;		/* useful start bno of left side */
 	xfs_extlen_t	rlen;		/* length of returned extent */
 #if defined(DEBUG) && defined(__KERNEL__)
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index 97f7328..3916925 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -280,38 +280,6 @@
 	return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
 }
 
-STATIC int
-xfs_allocbt_kill_root(
-	struct xfs_btree_cur	*cur,
-	struct xfs_buf		*bp,
-	int			level,
-	union xfs_btree_ptr	*newroot)
-{
-	int			error;
-
-	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
-	XFS_BTREE_STATS_INC(cur, killroot);
-
-	/*
-	 * Update the root pointer, decreasing the level by 1 and then
-	 * free the old root.
-	 */
-	xfs_allocbt_set_root(cur, newroot, -1);
-	error = xfs_allocbt_free_block(cur, bp);
-	if (error) {
-		XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
-		return error;
-	}
-
-	XFS_BTREE_STATS_INC(cur, free);
-
-	xfs_btree_setbuf(cur, level, NULL);
-	cur->bc_nlevels--;
-
-	XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
-	return 0;
-}
-
 #ifdef DEBUG
 STATIC int
 xfs_allocbt_keys_inorder(
@@ -423,7 +391,6 @@
 
 	.dup_cursor		= xfs_allocbt_dup_cursor,
 	.set_root		= xfs_allocbt_set_root,
-	.kill_root		= xfs_allocbt_kill_root,
 	.alloc_block		= xfs_allocbt_alloc_block,
 	.free_block		= xfs_allocbt_free_block,
 	.update_lastrec		= xfs_allocbt_update_lastrec,
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index c256824..c863753 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -355,16 +355,15 @@
 			if (mp->m_flags & XFS_MOUNT_WSYNC) {
 				xfs_trans_set_sync(args.trans);
 			}
+
+			if (!error && (flags & ATTR_KERNOTIME) == 0) {
+				xfs_trans_ichgtime(args.trans, dp,
+							XFS_ICHGTIME_CHG);
+			}
 			err2 = xfs_trans_commit(args.trans,
 						 XFS_TRANS_RELEASE_LOG_RES);
 			xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
-			/*
-			 * Hit the inode change time.
-			 */
-			if (!error && (flags & ATTR_KERNOTIME) == 0) {
-				xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
-			}
 			return(error == 0 ? err2 : error);
 		}
 
@@ -420,6 +419,9 @@
 		xfs_trans_set_sync(args.trans);
 	}
 
+	if ((flags & ATTR_KERNOTIME) == 0)
+		xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
+
 	/*
 	 * Commit the last in the sequence of transactions.
 	 */
@@ -427,13 +429,6 @@
 	error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
-	/*
-	 * Hit the inode change time.
-	 */
-	if (!error && (flags & ATTR_KERNOTIME) == 0) {
-		xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
-	}
-
 	return(error);
 
 out:
@@ -567,6 +562,9 @@
 		xfs_trans_set_sync(args.trans);
 	}
 
+	if ((flags & ATTR_KERNOTIME) == 0)
+		xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
+
 	/*
 	 * Commit the last in the sequence of transactions.
 	 */
@@ -574,13 +572,6 @@
 	error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
-	/*
-	 * Hit the inode change time.
-	 */
-	if (!error && (flags & ATTR_KERNOTIME) == 0) {
-		xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
-	}
-
 	return(error);
 
 out:
@@ -1995,7 +1986,7 @@
 
 			tmp = (valuelen < XFS_BUF_SIZE(bp))
 				? valuelen : XFS_BUF_SIZE(bp);
-			xfs_biomove(bp, 0, tmp, dst, XBF_READ);
+			xfs_buf_iomove(bp, 0, tmp, dst, XBRW_READ);
 			xfs_buf_relse(bp);
 			dst += tmp;
 			valuelen -= tmp;
@@ -2125,9 +2116,9 @@
 
 		tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen :
 							XFS_BUF_SIZE(bp);
-		xfs_biomove(bp, 0, tmp, src, XBF_WRITE);
+		xfs_buf_iomove(bp, 0, tmp, src, XBRW_WRITE);
 		if (tmp < XFS_BUF_SIZE(bp))
-			xfs_biozero(bp, tmp, XFS_BUF_SIZE(bp) - tmp);
+			xfs_buf_zero(bp, tmp, XFS_BUF_SIZE(bp) - tmp);
 		if ((error = xfs_bwrite(mp, bp))) {/* GROT: NOTE: synchronous write */
 			return (error);
 		}
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index f90dadd..8abd12e 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -614,7 +614,7 @@
 			nblks += cur->bc_private.b.allocated;
 		ASSERT(nblks <= da_old);
 		if (nblks < da_old)
-			xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
+			xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
 				(int64_t)(da_old - nblks), rsvd);
 	}
 	/*
@@ -1079,7 +1079,8 @@
 		diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
 			(cur ? cur->bc_private.b.allocated : 0));
 		if (diff > 0 &&
-		    xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd)) {
+		    xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
+					     -((int64_t)diff), rsvd)) {
 			/*
 			 * Ick gross gag me with a spoon.
 			 */
@@ -1089,16 +1090,18 @@
 					temp--;
 					diff--;
 					if (!diff ||
-					    !xfs_mod_incore_sb(ip->i_mount,
-						    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
+					    !xfs_icsb_modify_counters(ip->i_mount,
+						    XFS_SBS_FDBLOCKS,
+						    -((int64_t)diff), rsvd))
 						break;
 				}
 				if (temp2) {
 					temp2--;
 					diff--;
 					if (!diff ||
-					    !xfs_mod_incore_sb(ip->i_mount,
-						    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
+					    !xfs_icsb_modify_counters(ip->i_mount,
+						    XFS_SBS_FDBLOCKS,
+						    -((int64_t)diff), rsvd))
 						break;
 				}
 			}
@@ -1766,7 +1769,7 @@
 	}
 	if (oldlen != newlen) {
 		ASSERT(oldlen > newlen);
-		xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
+		xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
 			(int64_t)(oldlen - newlen), rsvd);
 		/*
 		 * Nothing to do for disk quota accounting here.
@@ -3111,9 +3114,10 @@
 	 * Nothing to do for disk quota accounting here.
 	 */
 	ASSERT(da_old >= da_new);
-	if (da_old > da_new)
-		xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int64_t)(da_old - da_new),
-			rsvd);
+	if (da_old > da_new) {
+		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
+			(int64_t)(da_old - da_new), rsvd);
+	}
 done:
 	*logflagsp = flags;
 	return error;
@@ -4526,13 +4530,13 @@
 							-((int64_t)extsz), (flags &
 							XFS_BMAPI_RSVBLOCKS));
 				} else {
-					error = xfs_mod_incore_sb(mp,
+					error = xfs_icsb_modify_counters(mp,
 							XFS_SBS_FDBLOCKS,
 							-((int64_t)alen), (flags &
 							XFS_BMAPI_RSVBLOCKS));
 				}
 				if (!error) {
-					error = xfs_mod_incore_sb(mp,
+					error = xfs_icsb_modify_counters(mp,
 							XFS_SBS_FDBLOCKS,
 							-((int64_t)indlen), (flags &
 							XFS_BMAPI_RSVBLOCKS));
@@ -4542,7 +4546,7 @@
 							(int64_t)extsz, (flags &
 							XFS_BMAPI_RSVBLOCKS));
 					else if (error)
-						xfs_mod_incore_sb(mp,
+						xfs_icsb_modify_counters(mp,
 							XFS_SBS_FDBLOCKS,
 							(int64_t)alen, (flags &
 							XFS_BMAPI_RSVBLOCKS));
@@ -4744,8 +4748,12 @@
 		 * Check if writing previously allocated but
 		 * unwritten extents.
 		 */
-		if (wr && mval->br_state == XFS_EXT_UNWRITTEN &&
-		    ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) {
+		if (wr &&
+		    ((mval->br_state == XFS_EXT_UNWRITTEN &&
+		      ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) ||
+		     (mval->br_state == XFS_EXT_NORM &&
+		      ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT)) ==
+				(XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT))))) {
 			/*
 			 * Modify (by adding) the state flag, if writing.
 			 */
@@ -4757,7 +4765,9 @@
 					*firstblock;
 				cur->bc_private.b.flist = flist;
 			}
-			mval->br_state = XFS_EXT_NORM;
+			mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN)
+						? XFS_EXT_NORM
+						: XFS_EXT_UNWRITTEN;
 			error = xfs_bmap_add_extent(ip, lastx, &cur, mval,
 				firstblock, flist, &tmp_logflags,
 				whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
@@ -5200,7 +5210,7 @@
 					ip, -((long)del.br_blockcount), 0,
 					XFS_QMOPT_RES_RTBLKS);
 			} else {
-				xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
+				xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
 						(int64_t)del.br_blockcount, rsvd);
 				(void)xfs_trans_reserve_quota_nblks(NULL,
 					ip, -((long)del.br_blockcount), 0,
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index b13569a..71ec9b6 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -74,9 +74,12 @@
 #define	XFS_BMAPI_IGSTATE	0x080	/* Ignore state - */
 					/* combine contig. space */
 #define	XFS_BMAPI_CONTIG	0x100	/* must allocate only one extent */
-#define XFS_BMAPI_CONVERT	0x200	/* unwritten extent conversion - */
-					/* need write cache flushing and no */
-					/* additional allocation alignments */
+/*
+ * unwritten extent conversion - this needs write cache flushing and no additional
+ * allocation alignments. When specified with XFS_BMAPI_PREALLOC it converts
+ * from written to unwritten, otherwise convert from unwritten to written.
+ */
+#define XFS_BMAPI_CONVERT	0x200
 
 #define XFS_BMAPI_FLAGS \
 	{ XFS_BMAPI_WRITE,	"WRITE" }, \
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 829af92..04f9cca 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -217,7 +217,7 @@
 	 */
 	for (i = 0; i < cur->bc_nlevels; i++) {
 		if (cur->bc_bufs[i])
-			xfs_btree_setbuf(cur, i, NULL);
+			xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]);
 		else if (!error)
 			break;
 	}
@@ -656,7 +656,7 @@
 
 	ASSERT(fsbno != NULLFSBLOCK);
 	d = XFS_FSB_TO_DADDR(mp, fsbno);
-	xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);
+	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count);
 }
 
 /*
@@ -676,7 +676,7 @@
 	ASSERT(agno != NULLAGNUMBER);
 	ASSERT(agbno != NULLAGBLOCK);
 	d = XFS_AGB_TO_DADDR(mp, agno, agbno);
-	xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);
+	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count);
 }
 
 STATIC int
@@ -763,22 +763,19 @@
  * Set the buffer for level "lev" in the cursor to bp, releasing
  * any previous buffer.
  */
-void
+STATIC void
 xfs_btree_setbuf(
 	xfs_btree_cur_t		*cur,	/* btree cursor */
 	int			lev,	/* level in btree */
 	xfs_buf_t		*bp)	/* new buffer to set */
 {
 	struct xfs_btree_block	*b;	/* btree block */
-	xfs_buf_t		*obp;	/* old buffer pointer */
 
-	obp = cur->bc_bufs[lev];
-	if (obp)
-		xfs_trans_brelse(cur->bc_tp, obp);
+	if (cur->bc_bufs[lev])
+		xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[lev]);
 	cur->bc_bufs[lev] = bp;
 	cur->bc_ra[lev] = 0;
-	if (!bp)
-		return;
+
 	b = XFS_BUF_TO_BLOCK(bp);
 	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
 		if (be64_to_cpu(b->bb_u.l.bb_leftsib) == NULLDFSBNO)
@@ -3011,6 +3008,43 @@
 	return 0;
 }
 
+/*
+ * Kill the current root node, and replace it with it's only child node.
+ */
+STATIC int
+xfs_btree_kill_root(
+	struct xfs_btree_cur	*cur,
+	struct xfs_buf		*bp,
+	int			level,
+	union xfs_btree_ptr	*newroot)
+{
+	int			error;
+
+	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
+	XFS_BTREE_STATS_INC(cur, killroot);
+
+	/*
+	 * Update the root pointer, decreasing the level by 1 and then
+	 * free the old root.
+	 */
+	cur->bc_ops->set_root(cur, newroot, -1);
+
+	error = cur->bc_ops->free_block(cur, bp);
+	if (error) {
+		XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
+		return error;
+	}
+
+	XFS_BTREE_STATS_INC(cur, free);
+
+	cur->bc_bufs[level] = NULL;
+	cur->bc_ra[level] = 0;
+	cur->bc_nlevels--;
+
+	XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
+	return 0;
+}
+
 STATIC int
 xfs_btree_dec_cursor(
 	struct xfs_btree_cur	*cur,
@@ -3195,7 +3229,7 @@
 			 * Make it the new root of the btree.
 			 */
 			pp = xfs_btree_ptr_addr(cur, 1, block);
-			error = cur->bc_ops->kill_root(cur, bp, level, pp);
+			error = xfs_btree_kill_root(cur, bp, level, pp);
 			if (error)
 				goto error0;
 		} else if (level > 0) {
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 7fa0706..82fafc6 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -152,9 +152,7 @@
 
 	/* update btree root pointer */
 	void	(*set_root)(struct xfs_btree_cur *cur,
-				union xfs_btree_ptr *nptr, int level_change);
-	int	(*kill_root)(struct xfs_btree_cur *cur, struct xfs_buf *bp,
-				int level, union xfs_btree_ptr *newroot);
+			    union xfs_btree_ptr *nptr, int level_change);
 
 	/* block allocation / freeing */
 	int	(*alloc_block)(struct xfs_btree_cur *cur,
@@ -399,16 +397,6 @@
 	xfs_agblock_t		agbno,	/* allocation group block number */
 	xfs_extlen_t		count);	/* count of filesystem blocks */
 
-/*
- * Set the buffer for level "lev" in the cursor to bp, releasing
- * any previous buffer.
- */
-void
-xfs_btree_setbuf(
-	xfs_btree_cur_t		*cur,	/* btree cursor */
-	int			lev,	/* level in btree */
-	struct xfs_buf		*bp);	/* new buffer to set */
-
 
 /*
  * Common btree core entry points.
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 1b09d7a..2686d0d 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -692,8 +692,7 @@
 	 * the first.  If we do already have one, there is
 	 * nothing to do here so return.
 	 */
-	if (bp->b_mount != mp)
-		bp->b_mount = mp;
+	ASSERT(bp->b_target->bt_mount == mp);
 	if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {
 		lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
 		if (lip->li_type == XFS_LI_BUF) {
@@ -974,7 +973,7 @@
 			xfs_buf_do_callbacks(bp, lip);
 			XFS_BUF_SET_FSPRIVATE(bp, NULL);
 			XFS_BUF_CLR_IODONE_FUNC(bp);
-			xfs_biodone(bp);
+			xfs_buf_ioend(bp, 0);
 			return;
 		}
 
@@ -1033,7 +1032,7 @@
 	xfs_buf_do_callbacks(bp, lip);
 	XFS_BUF_SET_FSPRIVATE(bp, NULL);
 	XFS_BUF_CLR_IODONE_FUNC(bp);
-	xfs_biodone(bp);
+	xfs_buf_ioend(bp, 0);
 }
 
 /*
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 30fa0e2..1c00bed 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -2042,7 +2042,7 @@
 				mappedbno, nmapped, 0, &bp);
 			break;
 		case 3:
-			xfs_baread(mp->m_ddev_targp, mappedbno, nmapped);
+			xfs_buf_readahead(mp->m_ddev_targp, mappedbno, nmapped);
 			error = 0;
 			bp = NULL;
 			break;
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index e5b153b..dffba9b 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -49,8 +49,9 @@
 	__be32		di_uid;		/* owner's user id */
 	__be32		di_gid;		/* owner's group id */
 	__be32		di_nlink;	/* number of links to file */
-	__be16		di_projid;	/* owner's project id */
-	__u8		di_pad[8];	/* unused, zeroed space */
+	__be16		di_projid_lo;	/* lower part of owner's project id */
+	__be16		di_projid_hi;	/* higher part owner's project id */
+	__u8		di_pad[6];	/* unused, zeroed space */
 	__be16		di_flushiter;	/* incremented on flush */
 	xfs_timestamp_t	di_atime;	/* time last accessed */
 	xfs_timestamp_t	di_mtime;	/* time last modified */
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 504be86..ae89122 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -961,7 +961,7 @@
 				if (i > ra_current &&
 				    map[ra_index].br_blockcount >=
 				    mp->m_dirblkfsbs) {
-					xfs_baread(mp->m_ddev_targp,
+					xfs_buf_readahead(mp->m_ddev_targp,
 						XFS_FSB_TO_DADDR(mp,
 						   map[ra_index].br_startblock +
 						   ra_offset),
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 87c2e9d..8f6fc1a 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -293,9 +293,11 @@
 	__s32		bs_extsize;	/* extent size			*/
 	__s32		bs_extents;	/* number of extents		*/
 	__u32		bs_gen;		/* generation count		*/
-	__u16		bs_projid;	/* project id			*/
+	__u16		bs_projid_lo;	/* lower part of project id	*/
+#define	bs_projid	bs_projid_lo	/* (previously just bs_projid)	*/
 	__u16		bs_forkoff;	/* inode fork offset in bytes	*/
-	unsigned char	bs_pad[12];	/* pad space, unused		*/
+	__u16		bs_projid_hi;	/* higher part of project id	*/
+	unsigned char	bs_pad[10];	/* pad space, unused		*/
 	__u32		bs_dmevmask;	/* DMIG event mask		*/
 	__u16		bs_dmstate;	/* DMIG state info		*/
 	__u16		bs_aextents;	/* attribute number of extents	*/
@@ -448,6 +450,7 @@
 /*	XFS_IOC_SETBIOSIZE ---- deprecated 46	   */
 /*	XFS_IOC_GETBIOSIZE ---- deprecated 47	   */
 #define XFS_IOC_GETBMAPX	_IOWR('X', 56, struct getbmap)
+#define XFS_IOC_ZERO_RANGE	_IOW ('X', 57, struct xfs_flock64)
 
 /*
  * ioctl commands that replace IRIX syssgi()'s
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 43b1d56..a7c116e 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -144,12 +144,11 @@
 	if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
 		return error;
 	dpct = pct - mp->m_sb.sb_imax_pct;
-	error = xfs_read_buf(mp, mp->m_ddev_targp,
-			XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
-			XFS_FSS_TO_BB(mp, 1), 0, &bp);
-	if (error)
-		return error;
-	ASSERT(bp);
+	bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,
+				XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
+				BBTOB(XFS_FSS_TO_BB(mp, 1)), 0);
+	if (!bp)
+		return EIO;
 	xfs_buf_relse(bp);
 
 	new = nb;	/* use new as a temporary here */
@@ -597,7 +596,8 @@
 		 * the extra reserve blocks from the reserve.....
 		 */
 		int error;
-		error = xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, fdblks_delta, 0);
+		error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
+						 fdblks_delta, 0);
 		if (error == ENOSPC)
 			goto retry;
 	}
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 5371d2d..0626a32 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -212,7 +212,7 @@
 		 *	to log a whole cluster of inodes instead of all the
 		 *	individual transactions causing a lot of log traffic.
 		 */
-		xfs_biozero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog);
+		xfs_buf_zero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog);
 		for (i = 0; i < ninodes; i++) {
 			int	ioffset = i << mp->m_sb.sb_inodelog;
 			uint	isize = sizeof(struct xfs_dinode);
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index d352862..16921f5 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -183,38 +183,6 @@
 			  cur->bc_rec.i.ir_startino;
 }
 
-STATIC int
-xfs_inobt_kill_root(
-	struct xfs_btree_cur	*cur,
-	struct xfs_buf		*bp,
-	int			level,
-	union xfs_btree_ptr	*newroot)
-{
-	int			error;
-
-	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
-	XFS_BTREE_STATS_INC(cur, killroot);
-
-	/*
-	 * Update the root pointer, decreasing the level by 1 and then
-	 * free the old root.
-	 */
-	xfs_inobt_set_root(cur, newroot, -1);
-	error = xfs_inobt_free_block(cur, bp);
-	if (error) {
-		XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
-		return error;
-	}
-
-	XFS_BTREE_STATS_INC(cur, free);
-
-	cur->bc_bufs[level] = NULL;
-	cur->bc_nlevels--;
-
-	XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
-	return 0;
-}
-
 #ifdef DEBUG
 STATIC int
 xfs_inobt_keys_inorder(
@@ -309,7 +277,6 @@
 
 	.dup_cursor		= xfs_inobt_dup_cursor,
 	.set_root		= xfs_inobt_set_root,
-	.kill_root		= xfs_inobt_kill_root,
 	.alloc_block		= xfs_inobt_alloc_block,
 	.free_block		= xfs_inobt_free_block,
 	.get_minrecs		= xfs_inobt_get_minrecs,
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index b1ecc6f..0cdd269 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -365,8 +365,8 @@
 	xfs_perag_t	*pag;
 	xfs_agino_t	agino;
 
-	/* the radix tree exists only in inode capable AGs */
-	if (XFS_INO_TO_AGNO(mp, ino) >= mp->m_maxagi)
+	/* reject inode numbers outside existing AGs */
+	if (XFS_INO_TO_AGNO(mp, ino) >= mp->m_sb.sb_agcount)
 		return EINVAL;
 
 	/* get the perag structure and ensure that it's inode capable */
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 34798f3..108c7a0 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -660,7 +660,8 @@
 	to->di_uid = be32_to_cpu(from->di_uid);
 	to->di_gid = be32_to_cpu(from->di_gid);
 	to->di_nlink = be32_to_cpu(from->di_nlink);
-	to->di_projid = be16_to_cpu(from->di_projid);
+	to->di_projid_lo = be16_to_cpu(from->di_projid_lo);
+	to->di_projid_hi = be16_to_cpu(from->di_projid_hi);
 	memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
 	to->di_flushiter = be16_to_cpu(from->di_flushiter);
 	to->di_atime.t_sec = be32_to_cpu(from->di_atime.t_sec);
@@ -695,7 +696,8 @@
 	to->di_uid = cpu_to_be32(from->di_uid);
 	to->di_gid = cpu_to_be32(from->di_gid);
 	to->di_nlink = cpu_to_be32(from->di_nlink);
-	to->di_projid = cpu_to_be16(from->di_projid);
+	to->di_projid_lo = cpu_to_be16(from->di_projid_lo);
+	to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
 	memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
 	to->di_flushiter = cpu_to_be16(from->di_flushiter);
 	to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec);
@@ -874,7 +876,7 @@
 	if (ip->i_d.di_version == 1) {
 		ip->i_d.di_nlink = ip->i_d.di_onlink;
 		ip->i_d.di_onlink = 0;
-		ip->i_d.di_projid = 0;
+		xfs_set_projid(ip, 0);
 	}
 
 	ip->i_delayed_blks = 0;
@@ -982,8 +984,7 @@
 	mode_t		mode,
 	xfs_nlink_t	nlink,
 	xfs_dev_t	rdev,
-	cred_t		*cr,
-	xfs_prid_t	prid,
+	prid_t		prid,
 	int		okalloc,
 	xfs_buf_t	**ialloc_context,
 	boolean_t	*call_again,
@@ -1027,7 +1028,7 @@
 	ASSERT(ip->i_d.di_nlink == nlink);
 	ip->i_d.di_uid = current_fsuid();
 	ip->i_d.di_gid = current_fsgid();
-	ip->i_d.di_projid = prid;
+	xfs_set_projid(ip, prid);
 	memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
 
 	/*
@@ -2725,7 +2726,7 @@
 			XFS_BUF_UNDONE(bp);
 			XFS_BUF_STALE(bp);
 			XFS_BUF_ERROR(bp,EIO);
-			xfs_biodone(bp);
+			xfs_buf_ioend(bp, 0);
 		} else {
 			XFS_BUF_STALE(bp);
 			xfs_buf_relse(bp);
@@ -3008,7 +3009,7 @@
 			memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
 			memset(&(dip->di_pad[0]), 0,
 			      sizeof(dip->di_pad));
-			ASSERT(ip->i_d.di_projid == 0);
+			ASSERT(xfs_get_projid(ip) == 0);
 		}
 	}
 
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 0898c54..fac5229 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -134,8 +134,9 @@
 	__uint32_t	di_uid;		/* owner's user id */
 	__uint32_t	di_gid;		/* owner's group id */
 	__uint32_t	di_nlink;	/* number of links to file */
-	__uint16_t	di_projid;	/* owner's project id */
-	__uint8_t	di_pad[8];	/* unused, zeroed space */
+	__uint16_t	di_projid_lo;	/* lower part of owner's project id */
+	__uint16_t	di_projid_hi;	/* higher part of owner's project id */
+	__uint8_t	di_pad[6];	/* unused, zeroed space */
 	__uint16_t	di_flushiter;	/* incremented on flush */
 	xfs_ictimestamp_t di_atime;	/* time last accessed */
 	xfs_ictimestamp_t di_mtime;	/* time last modified */
@@ -212,7 +213,6 @@
 #ifdef __KERNEL__
 
 struct bhv_desc;
-struct cred;
 struct xfs_buf;
 struct xfs_bmap_free;
 struct xfs_bmbt_irec;
@@ -335,6 +335,25 @@
 }
 
 /*
+ * Project quota id helpers (previously projid was 16bit only
+ * and using two 16bit values to hold new 32bit projid was choosen
+ * to retain compatibility with "old" filesystems).
+ */
+static inline prid_t
+xfs_get_projid(struct xfs_inode *ip)
+{
+	return (prid_t)ip->i_d.di_projid_hi << 16 | ip->i_d.di_projid_lo;
+}
+
+static inline void
+xfs_set_projid(struct xfs_inode *ip,
+		prid_t projid)
+{
+	ip->i_d.di_projid_hi = (__uint16_t) (projid >> 16);
+	ip->i_d.di_projid_lo = (__uint16_t) (projid & 0xffff);
+}
+
+/*
  * Manage the i_flush queue embedded in the inode.  This completion
  * queue synchronizes processes attempting to flush the in-core
  * inode back to disk.
@@ -456,8 +475,8 @@
  * xfs_inode.c prototypes.
  */
 int		xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
-			   xfs_nlink_t, xfs_dev_t, cred_t *, xfs_prid_t,
-			   int, struct xfs_buf **, boolean_t *, xfs_inode_t **);
+			   xfs_nlink_t, xfs_dev_t, prid_t, int,
+			   struct xfs_buf **, boolean_t *, xfs_inode_t **);
 
 uint		xfs_ip2xflags(struct xfs_inode *);
 uint		xfs_dic2xflags(struct xfs_dinode *);
@@ -471,7 +490,6 @@
 void		xfs_iext_realloc(xfs_inode_t *, int, int);
 void		xfs_iunpin_wait(xfs_inode_t *);
 int		xfs_iflush(xfs_inode_t *, uint);
-void		xfs_ichgtime(xfs_inode_t *, int);
 void		xfs_lock_inodes(xfs_inode_t **, int, uint);
 void		xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint);
 
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index fe00777..c7ac020 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -223,15 +223,6 @@
 	nvecs	     = 1;
 
 	/*
-	 * Make sure the linux inode is dirty. We do this before
-	 * clearing i_update_core as the VFS will call back into
-	 * XFS here and set i_update_core, so we need to dirty the
-	 * inode first so that the ordering of i_update_core and
-	 * unlogged modifications still works as described below.
-	 */
-	xfs_mark_inode_dirty_sync(ip);
-
-	/*
 	 * Clear i_update_core if the timestamps (or any other
 	 * non-transactional modification) need flushing/logging
 	 * and we're about to log them with the rest of the core.
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 7e3626e..dc1882a 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -92,7 +92,8 @@
 	 * further change.
 	 */
 	buf->bs_nlink = dic->di_nlink;
-	buf->bs_projid = dic->di_projid;
+	buf->bs_projid_lo = dic->di_projid_lo;
+	buf->bs_projid_hi = dic->di_projid_hi;
 	buf->bs_ino = ino;
 	buf->bs_mode = dic->di_mode;
 	buf->bs_uid = dic->di_uid;
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 33f718f..cee4ab9 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -917,19 +917,6 @@
 	l = iclog->ic_log;
 
 	/*
-	 * If the _XFS_BARRIER_FAILED flag was set by a lower
-	 * layer, it means the underlying device no longer supports
-	 * barrier I/O. Warn loudly and turn off barriers.
-	 */
-	if (bp->b_flags & _XFS_BARRIER_FAILED) {
-		bp->b_flags &= ~_XFS_BARRIER_FAILED;
-		l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER;
-		xfs_fs_cmn_err(CE_WARN, l->l_mp,
-				"xlog_iodone: Barriers are no longer supported"
-				" by device. Disabling barriers\n");
-	}
-
-	/*
 	 * Race to shutdown the filesystem if we see an error.
 	 */
 	if (XFS_TEST_ERROR((XFS_BUF_GETERROR(bp)), l->l_mp,
@@ -1131,7 +1118,8 @@
 		iclog->ic_prev = prev_iclog;
 		prev_iclog = iclog;
 
-		bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
+		bp = xfs_buf_get_uncached(mp->m_logdev_targp,
+						log->l_iclog_size, 0);
 		if (!bp)
 			goto out_free_iclog;
 		if (!XFS_BUF_CPSEMA(bp))
@@ -1309,7 +1297,7 @@
 	if (iclog->ic_state & XLOG_STATE_IOERROR) {
 		XFS_BUF_ERROR(bp, EIO);
 		XFS_BUF_STALE(bp);
-		xfs_biodone(bp);
+		xfs_buf_ioend(bp, 0);
 		/*
 		 * It would seem logical to return EIO here, but we rely on
 		 * the log state machine to propagate I/O errors instead of
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index ed575fb..23d6ceb 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -146,102 +146,6 @@
 }
 
 /*
- * Insert the log item into the CIL and calculate the difference in space
- * consumed by the item. Add the space to the checkpoint ticket and calculate
- * if the change requires additional log metadata. If it does, take that space
- * as well. Remove the amount of space we addded to the checkpoint ticket from
- * the current transaction ticket so that the accounting works out correctly.
- *
- * If this is the first time the item is being placed into the CIL in this
- * context, pin it so it can't be written to disk until the CIL is flushed to
- * the iclog and the iclog written to disk.
- */
-static void
-xlog_cil_insert(
-	struct log		*log,
-	struct xlog_ticket	*ticket,
-	struct xfs_log_item	*item,
-	struct xfs_log_vec	*lv)
-{
-	struct xfs_cil		*cil = log->l_cilp;
-	struct xfs_log_vec	*old = lv->lv_item->li_lv;
-	struct xfs_cil_ctx	*ctx = cil->xc_ctx;
-	int			len;
-	int			diff_iovecs;
-	int			iclog_space;
-
-	if (old) {
-		/* existing lv on log item, space used is a delta */
-		ASSERT(!list_empty(&item->li_cil));
-		ASSERT(old->lv_buf && old->lv_buf_len && old->lv_niovecs);
-
-		len = lv->lv_buf_len - old->lv_buf_len;
-		diff_iovecs = lv->lv_niovecs - old->lv_niovecs;
-		kmem_free(old->lv_buf);
-		kmem_free(old);
-	} else {
-		/* new lv, must pin the log item */
-		ASSERT(!lv->lv_item->li_lv);
-		ASSERT(list_empty(&item->li_cil));
-
-		len = lv->lv_buf_len;
-		diff_iovecs = lv->lv_niovecs;
-		IOP_PIN(lv->lv_item);
-
-	}
-	len += diff_iovecs * sizeof(xlog_op_header_t);
-
-	/* attach new log vector to log item */
-	lv->lv_item->li_lv = lv;
-
-	spin_lock(&cil->xc_cil_lock);
-	list_move_tail(&item->li_cil, &cil->xc_cil);
-	ctx->nvecs += diff_iovecs;
-
-	/*
-	 * If this is the first time the item is being committed to the CIL,
-	 * store the sequence number on the log item so we can tell
-	 * in future commits whether this is the first checkpoint the item is
-	 * being committed into.
-	 */
-	if (!item->li_seq)
-		item->li_seq = ctx->sequence;
-
-	/*
-	 * Now transfer enough transaction reservation to the context ticket
-	 * for the checkpoint. The context ticket is special - the unit
-	 * reservation has to grow as well as the current reservation as we
-	 * steal from tickets so we can correctly determine the space used
-	 * during the transaction commit.
-	 */
-	if (ctx->ticket->t_curr_res == 0) {
-		/* first commit in checkpoint, steal the header reservation */
-		ASSERT(ticket->t_curr_res >= ctx->ticket->t_unit_res + len);
-		ctx->ticket->t_curr_res = ctx->ticket->t_unit_res;
-		ticket->t_curr_res -= ctx->ticket->t_unit_res;
-	}
-
-	/* do we need space for more log record headers? */
-	iclog_space = log->l_iclog_size - log->l_iclog_hsize;
-	if (len > 0 && (ctx->space_used / iclog_space !=
-				(ctx->space_used + len) / iclog_space)) {
-		int hdrs;
-
-		hdrs = (len + iclog_space - 1) / iclog_space;
-		/* need to take into account split region headers, too */
-		hdrs *= log->l_iclog_hsize + sizeof(struct xlog_op_header);
-		ctx->ticket->t_unit_res += hdrs;
-		ctx->ticket->t_curr_res += hdrs;
-		ticket->t_curr_res -= hdrs;
-		ASSERT(ticket->t_curr_res >= len);
-	}
-	ticket->t_curr_res -= len;
-	ctx->space_used += len;
-
-	spin_unlock(&cil->xc_cil_lock);
-}
-
-/*
  * Format log item into a flat buffers
  *
  * For delayed logging, we need to hold a formatted buffer containing all the
@@ -286,7 +190,7 @@
 			len += lv->lv_iovecp[index].i_len;
 
 		lv->lv_buf_len = len;
-		lv->lv_buf = kmem_zalloc(lv->lv_buf_len, KM_SLEEP|KM_NOFS);
+		lv->lv_buf = kmem_alloc(lv->lv_buf_len, KM_SLEEP|KM_NOFS);
 		ptr = lv->lv_buf;
 
 		for (index = 0; index < lv->lv_niovecs; index++) {
@@ -300,21 +204,136 @@
 	}
 }
 
+/*
+ * Prepare the log item for insertion into the CIL. Calculate the difference in
+ * log space and vectors it will consume, and if it is a new item pin it as
+ * well.
+ */
+STATIC void
+xfs_cil_prepare_item(
+	struct log		*log,
+	struct xfs_log_vec	*lv,
+	int			*len,
+	int			*diff_iovecs)
+{
+	struct xfs_log_vec	*old = lv->lv_item->li_lv;
+
+	if (old) {
+		/* existing lv on log item, space used is a delta */
+		ASSERT(!list_empty(&lv->lv_item->li_cil));
+		ASSERT(old->lv_buf && old->lv_buf_len && old->lv_niovecs);
+
+		*len += lv->lv_buf_len - old->lv_buf_len;
+		*diff_iovecs += lv->lv_niovecs - old->lv_niovecs;
+		kmem_free(old->lv_buf);
+		kmem_free(old);
+	} else {
+		/* new lv, must pin the log item */
+		ASSERT(!lv->lv_item->li_lv);
+		ASSERT(list_empty(&lv->lv_item->li_cil));
+
+		*len += lv->lv_buf_len;
+		*diff_iovecs += lv->lv_niovecs;
+		IOP_PIN(lv->lv_item);
+
+	}
+
+	/* attach new log vector to log item */
+	lv->lv_item->li_lv = lv;
+
+	/*
+	 * If this is the first time the item is being committed to the
+	 * CIL, store the sequence number on the log item so we can
+	 * tell in future commits whether this is the first checkpoint
+	 * the item is being committed into.
+	 */
+	if (!lv->lv_item->li_seq)
+		lv->lv_item->li_seq = log->l_cilp->xc_ctx->sequence;
+}
+
+/*
+ * Insert the log items into the CIL and calculate the difference in space
+ * consumed by the item. Add the space to the checkpoint ticket and calculate
+ * if the change requires additional log metadata. If it does, take that space
+ * as well. Remove the amount of space we addded to the checkpoint ticket from
+ * the current transaction ticket so that the accounting works out correctly.
+ */
 static void
 xlog_cil_insert_items(
 	struct log		*log,
 	struct xfs_log_vec	*log_vector,
-	struct xlog_ticket	*ticket,
-	xfs_lsn_t		*start_lsn)
+	struct xlog_ticket	*ticket)
 {
-	struct xfs_log_vec *lv;
-
-	if (start_lsn)
-		*start_lsn = log->l_cilp->xc_ctx->sequence;
+	struct xfs_cil		*cil = log->l_cilp;
+	struct xfs_cil_ctx	*ctx = cil->xc_ctx;
+	struct xfs_log_vec	*lv;
+	int			len = 0;
+	int			diff_iovecs = 0;
+	int			iclog_space;
 
 	ASSERT(log_vector);
+
+	/*
+	 * Do all the accounting aggregation and switching of log vectors
+	 * around in a separate loop to the insertion of items into the CIL.
+	 * Then we can do a separate loop to update the CIL within a single
+	 * lock/unlock pair. This reduces the number of round trips on the CIL
+	 * lock from O(nr_logvectors) to O(1) and greatly reduces the overall
+	 * hold time for the transaction commit.
+	 *
+	 * If this is the first time the item is being placed into the CIL in
+	 * this context, pin it so it can't be written to disk until the CIL is
+	 * flushed to the iclog and the iclog written to disk.
+	 *
+	 * We can do this safely because the context can't checkpoint until we
+	 * are done so it doesn't matter exactly how we update the CIL.
+	 */
 	for (lv = log_vector; lv; lv = lv->lv_next)
-		xlog_cil_insert(log, ticket, lv->lv_item, lv);
+		xfs_cil_prepare_item(log, lv, &len, &diff_iovecs);
+
+	/* account for space used by new iovec headers  */
+	len += diff_iovecs * sizeof(xlog_op_header_t);
+
+	spin_lock(&cil->xc_cil_lock);
+
+	/* move the items to the tail of the CIL */
+	for (lv = log_vector; lv; lv = lv->lv_next)
+		list_move_tail(&lv->lv_item->li_cil, &cil->xc_cil);
+
+	ctx->nvecs += diff_iovecs;
+
+	/*
+	 * Now transfer enough transaction reservation to the context ticket
+	 * for the checkpoint. The context ticket is special - the unit
+	 * reservation has to grow as well as the current reservation as we
+	 * steal from tickets so we can correctly determine the space used
+	 * during the transaction commit.
+	 */
+	if (ctx->ticket->t_curr_res == 0) {
+		/* first commit in checkpoint, steal the header reservation */
+		ASSERT(ticket->t_curr_res >= ctx->ticket->t_unit_res + len);
+		ctx->ticket->t_curr_res = ctx->ticket->t_unit_res;
+		ticket->t_curr_res -= ctx->ticket->t_unit_res;
+	}
+
+	/* do we need space for more log record headers? */
+	iclog_space = log->l_iclog_size - log->l_iclog_hsize;
+	if (len > 0 && (ctx->space_used / iclog_space !=
+				(ctx->space_used + len) / iclog_space)) {
+		int hdrs;
+
+		hdrs = (len + iclog_space - 1) / iclog_space;
+		/* need to take into account split region headers, too */
+		hdrs *= log->l_iclog_hsize + sizeof(struct xlog_op_header);
+		ctx->ticket->t_unit_res += hdrs;
+		ctx->ticket->t_curr_res += hdrs;
+		ticket->t_curr_res -= hdrs;
+		ASSERT(ticket->t_curr_res >= len);
+	}
+	ticket->t_curr_res -= len;
+	ctx->space_used += len;
+
+	spin_unlock(&cil->xc_cil_lock);
 }
 
 static void
@@ -405,9 +424,15 @@
 	new_ctx = kmem_zalloc(sizeof(*new_ctx), KM_SLEEP|KM_NOFS);
 	new_ctx->ticket = xlog_cil_ticket_alloc(log);
 
-	/* lock out transaction commit, but don't block on background push */
+	/*
+	 * Lock out transaction commit, but don't block for background pushes
+	 * unless we are well over the CIL space limit. See the definition of
+	 * XLOG_CIL_HARD_SPACE_LIMIT() for the full explanation of the logic
+	 * used here.
+	 */
 	if (!down_write_trylock(&cil->xc_ctx_lock)) {
-		if (!push_seq)
+		if (!push_seq &&
+		    cil->xc_ctx->space_used < XLOG_CIL_HARD_SPACE_LIMIT(log))
 			goto out_free_ticket;
 		down_write(&cil->xc_ctx_lock);
 	}
@@ -422,7 +447,7 @@
 		goto out_skip;
 
 	/* check for a previously pushed seqeunce */
-	if (push_seq < cil->xc_ctx->sequence)
+	if (push_seq && push_seq < cil->xc_ctx->sequence)
 		goto out_skip;
 
 	/*
@@ -632,7 +657,10 @@
 
 	/* lock out background commit */
 	down_read(&log->l_cilp->xc_ctx_lock);
-	xlog_cil_insert_items(log, log_vector, tp->t_ticket, commit_lsn);
+	if (commit_lsn)
+		*commit_lsn = log->l_cilp->xc_ctx->sequence;
+
+	xlog_cil_insert_items(log, log_vector, tp->t_ticket);
 
 	/* check we didn't blow the reservation */
 	if (tp->t_ticket->t_curr_res < 0)
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index ced52b9..edcdfe0 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -426,13 +426,13 @@
 };
 
 /*
- * The amount of log space we should the CIL to aggregate is difficult to size.
- * Whatever we chose we have to make we can get a reservation for the log space
- * effectively, that it is large enough to capture sufficient relogging to
- * reduce log buffer IO significantly, but it is not too large for the log or
- * induces too much latency when writing out through the iclogs. We track both
- * space consumed and the number of vectors in the checkpoint context, so we
- * need to decide which to use for limiting.
+ * The amount of log space we allow the CIL to aggregate is difficult to size.
+ * Whatever we choose, we have to make sure we can get a reservation for the
+ * log space effectively, that it is large enough to capture sufficient
+ * relogging to reduce log buffer IO significantly, but it is not too large for
+ * the log or induces too much latency when writing out through the iclogs. We
+ * track both space consumed and the number of vectors in the checkpoint
+ * context, so we need to decide which to use for limiting.
  *
  * Every log buffer we write out during a push needs a header reserved, which
  * is at least one sector and more for v2 logs. Hence we need a reservation of
@@ -459,16 +459,21 @@
  * checkpoint transaction ticket is specific to the checkpoint context, rather
  * than the CIL itself.
  *
- * With dynamic reservations, we can basically make up arbitrary limits for the
- * checkpoint size so long as they don't violate any other size rules.  Hence
- * the initial maximum size for the checkpoint transaction will be set to a
- * quarter of the log or 8MB, which ever is smaller. 8MB is an arbitrary limit
- * right now based on the latency of writing out a large amount of data through
- * the circular iclog buffers.
+ * With dynamic reservations, we can effectively make up arbitrary limits for
+ * the checkpoint size so long as they don't violate any other size rules.
+ * Recovery imposes a rule that no transaction exceed half the log, so we are
+ * limited by that.  Furthermore, the log transaction reservation subsystem
+ * tries to keep 25% of the log free, so we need to keep below that limit or we
+ * risk running out of free log space to start any new transactions.
+ *
+ * In order to keep background CIL push efficient, we will set a lower
+ * threshold at which background pushing is attempted without blocking current
+ * transaction commits.  A separate, higher bound defines when CIL pushes are
+ * enforced to ensure we stay within our maximum checkpoint size bounds.
+ * threshold, yet give us plenty of space for aggregation on large logs.
  */
-
-#define XLOG_CIL_SPACE_LIMIT(log)	\
-	(min((log->l_logsize >> 2), (8 * 1024 * 1024)))
+#define XLOG_CIL_SPACE_LIMIT(log)	(log->l_logsize >> 3)
+#define XLOG_CIL_HARD_SPACE_LIMIT(log)	(3 * (log->l_logsize >> 4))
 
 /*
  * The reservation head lsn is not made up of a cycle number and block number.
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 6f3f5fa..966d3f9 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -107,7 +107,8 @@
 		nbblks += log->l_sectBBsize;
 	nbblks = round_up(nbblks, log->l_sectBBsize);
 
-	return xfs_buf_get_noaddr(BBTOB(nbblks), log->l_mp->m_logdev_targp);
+	return xfs_buf_get_uncached(log->l_mp->m_logdev_targp,
+					BBTOB(nbblks), 0);
 }
 
 STATIC void
@@ -167,7 +168,7 @@
 	XFS_BUF_SET_TARGET(bp, log->l_mp->m_logdev_targp);
 
 	xfsbdstrat(log->l_mp, bp);
-	error = xfs_iowait(bp);
+	error = xfs_buf_iowait(bp);
 	if (error)
 		xfs_ioerror_alert("xlog_bread", log->l_mp,
 				  bp, XFS_BUF_ADDR(bp));
@@ -321,12 +322,13 @@
 		 * this during recovery. One strike!
 		 */
 		xfs_ioerror_alert("xlog_recover_iodone",
-				  bp->b_mount, bp, XFS_BUF_ADDR(bp));
-		xfs_force_shutdown(bp->b_mount, SHUTDOWN_META_IO_ERROR);
+					bp->b_target->bt_mount, bp,
+					XFS_BUF_ADDR(bp));
+		xfs_force_shutdown(bp->b_target->bt_mount,
+					SHUTDOWN_META_IO_ERROR);
 	}
-	bp->b_mount = NULL;
 	XFS_BUF_CLR_IODONE_FUNC(bp);
-	xfs_biodone(bp);
+	xfs_buf_ioend(bp, 0);
 }
 
 /*
@@ -2275,8 +2277,7 @@
 		XFS_BUF_STALE(bp);
 		error = xfs_bwrite(mp, bp);
 	} else {
-		ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
-		bp->b_mount = mp;
+		ASSERT(bp->b_target->bt_mount == mp);
 		XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
 		xfs_bdwrite(mp, bp);
 	}
@@ -2540,8 +2541,7 @@
 	}
 
 write_inode_buffer:
-	ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
-	bp->b_mount = mp;
+	ASSERT(bp->b_target->bt_mount == mp);
 	XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
 	xfs_bdwrite(mp, bp);
 error:
@@ -2678,8 +2678,7 @@
 	memcpy(ddq, recddq, item->ri_buf[1].i_len);
 
 	ASSERT(dq_f->qlf_size == 2);
-	ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
-	bp->b_mount = mp;
+	ASSERT(bp->b_target->bt_mount == mp);
 	XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
 	xfs_bdwrite(mp, bp);
 
@@ -3817,7 +3816,7 @@
 	XFS_BUF_READ(bp);
 	XFS_BUF_UNASYNC(bp);
 	xfsbdstrat(log->l_mp, bp);
-	error = xfs_iowait(bp);
+	error = xfs_buf_iowait(bp);
 	if (error) {
 		xfs_ioerror_alert("xlog_do_recover",
 				  log->l_mp, bp, XFS_BUF_ADDR(bp));
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index aeb9d72..b1498ab 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -52,16 +52,11 @@
 						int);
 STATIC void	xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t,
 						int);
-STATIC int	xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t,
-						int64_t, int);
 STATIC void	xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
-
 #else
 
 #define xfs_icsb_balance_counter(mp, a, b)		do { } while (0)
 #define xfs_icsb_balance_counter_locked(mp, a, b)	do { } while (0)
-#define xfs_icsb_modify_counters(mp, a, b, c)		do { } while (0)
-
 #endif
 
 static const struct {
@@ -199,6 +194,8 @@
 
 /*
  * Reference counting access wrappers to the perag structures.
+ * Because we never free per-ag structures, the only thing we
+ * have to protect against changes is the tree structure itself.
  */
 struct xfs_perag *
 xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno)
@@ -206,19 +203,43 @@
 	struct xfs_perag	*pag;
 	int			ref = 0;
 
-	spin_lock(&mp->m_perag_lock);
+	rcu_read_lock();
 	pag = radix_tree_lookup(&mp->m_perag_tree, agno);
 	if (pag) {
 		ASSERT(atomic_read(&pag->pag_ref) >= 0);
-		/* catch leaks in the positive direction during testing */
-		ASSERT(atomic_read(&pag->pag_ref) < 1000);
 		ref = atomic_inc_return(&pag->pag_ref);
 	}
-	spin_unlock(&mp->m_perag_lock);
+	rcu_read_unlock();
 	trace_xfs_perag_get(mp, agno, ref, _RET_IP_);
 	return pag;
 }
 
+/*
+ * search from @first to find the next perag with the given tag set.
+ */
+struct xfs_perag *
+xfs_perag_get_tag(
+	struct xfs_mount	*mp,
+	xfs_agnumber_t		first,
+	int			tag)
+{
+	struct xfs_perag	*pag;
+	int			found;
+	int			ref;
+
+	rcu_read_lock();
+	found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
+					(void **)&pag, first, 1, tag);
+	if (found <= 0) {
+		rcu_read_unlock();
+		return NULL;
+	}
+	ref = atomic_inc_return(&pag->pag_ref);
+	rcu_read_unlock();
+	trace_xfs_perag_get_tag(mp, pag->pag_agno, ref, _RET_IP_);
+	return pag;
+}
+
 void
 xfs_perag_put(struct xfs_perag *pag)
 {
@@ -229,10 +250,18 @@
 	trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_);
 }
 
+STATIC void
+__xfs_free_perag(
+	struct rcu_head	*head)
+{
+	struct xfs_perag *pag = container_of(head, struct xfs_perag, rcu_head);
+
+	ASSERT(atomic_read(&pag->pag_ref) == 0);
+	kmem_free(pag);
+}
+
 /*
- * Free up the resources associated with a mount structure.  Assume that
- * the structure was initially zeroed, so we can tell which fields got
- * initialized.
+ * Free up the per-ag resources associated with the mount structure.
  */
 STATIC void
 xfs_free_perag(
@@ -244,10 +273,9 @@
 	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
 		spin_lock(&mp->m_perag_lock);
 		pag = radix_tree_delete(&mp->m_perag_tree, agno);
-		ASSERT(pag);
-		ASSERT(atomic_read(&pag->pag_ref) == 0);
 		spin_unlock(&mp->m_perag_lock);
-		kmem_free(pag);
+		ASSERT(pag);
+		call_rcu(&pag->rcu_head, __xfs_free_perag);
 	}
 }
 
@@ -444,7 +472,10 @@
 		pag->pag_agno = index;
 		pag->pag_mount = mp;
 		rwlock_init(&pag->pag_ici_lock);
+		mutex_init(&pag->pag_ici_reclaim_lock);
 		INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
+		spin_lock_init(&pag->pag_buf_lock);
+		pag->pag_buf_tree = RB_ROOT;
 
 		if (radix_tree_preload(GFP_NOFS))
 			goto out_unwind;
@@ -639,7 +670,6 @@
 xfs_readsb(xfs_mount_t *mp, int flags)
 {
 	unsigned int	sector_size;
-	unsigned int	extra_flags;
 	xfs_buf_t	*bp;
 	int		error;
 
@@ -652,28 +682,24 @@
 	 * access to the superblock.
 	 */
 	sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
-	extra_flags = XBF_LOCK | XBF_FS_MANAGED | XBF_MAPPED;
 
-	bp = xfs_buf_read(mp->m_ddev_targp, XFS_SB_DADDR, BTOBB(sector_size),
-			  extra_flags);
-	if (!bp || XFS_BUF_ISERROR(bp)) {
-		xfs_fs_mount_cmn_err(flags, "SB read failed");
-		error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
-		goto fail;
+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");
+		return EIO;
 	}
-	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
 
 	/*
 	 * Initialize the mount structure from the superblock.
 	 * But first do some basic consistency checking.
 	 */
 	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");
-		goto fail;
+		goto release_buf;
 	}
 
 	/*
@@ -684,7 +710,7 @@
 			"device supports only %u byte sectors (not %u)",
 			sector_size, mp->m_sb.sb_sectsize);
 		error = ENOSYS;
-		goto fail;
+		goto release_buf;
 	}
 
 	/*
@@ -692,33 +718,20 @@
 	 * re-read the superblock so the buffer is correctly sized.
 	 */
 	if (sector_size < mp->m_sb.sb_sectsize) {
-		XFS_BUF_UNMANAGE(bp);
 		xfs_buf_relse(bp);
 		sector_size = mp->m_sb.sb_sectsize;
-		bp = xfs_buf_read(mp->m_ddev_targp, XFS_SB_DADDR,
-				  BTOBB(sector_size), extra_flags);
-		if (!bp || XFS_BUF_ISERROR(bp)) {
-			xfs_fs_mount_cmn_err(flags, "SB re-read failed");
-			error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
-			goto fail;
-		}
-		ASSERT(XFS_BUF_ISBUSY(bp));
-		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
+		goto reread;
 	}
 
 	/* Initialize per-cpu counters */
 	xfs_icsb_reinit_counters(mp);
 
 	mp->m_sb_bp = bp;
-	xfs_buf_relse(bp);
-	ASSERT(XFS_BUF_VALUSEMA(bp) > 0);
+	xfs_buf_unlock(bp);
 	return 0;
 
- fail:
-	if (bp) {
-		XFS_BUF_UNMANAGE(bp);
-		xfs_buf_relse(bp);
-	}
+release_buf:
+	xfs_buf_relse(bp);
 	return error;
 }
 
@@ -991,42 +1004,35 @@
 {
 	xfs_buf_t	*bp;
 	xfs_daddr_t	d;
-	int		error;
 
 	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: size check 1 failed");
+		cmn_err(CE_WARN, "XFS: filesystem size mismatch detected");
 		return XFS_ERROR(EFBIG);
 	}
-	error = xfs_read_buf(mp, mp->m_ddev_targp,
-			     d - XFS_FSS_TO_BB(mp, 1),
-			     XFS_FSS_TO_BB(mp, 1), 0, &bp);
-	if (!error) {
-		xfs_buf_relse(bp);
-	} else {
-		cmn_err(CE_WARN, "XFS: size check 2 failed");
-		if (error == ENOSPC)
-			error = XFS_ERROR(EFBIG);
-		return error;
+	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");
+		return EIO;
 	}
+	xfs_buf_relse(bp);
 
 	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: size check 3 failed");
+			cmn_err(CE_WARN, "XFS: log size mismatch detected");
 			return XFS_ERROR(EFBIG);
 		}
-		error = xfs_read_buf(mp, mp->m_logdev_targp,
-				     d - XFS_FSB_TO_BB(mp, 1),
-				     XFS_FSB_TO_BB(mp, 1), 0, &bp);
-		if (!error) {
-			xfs_buf_relse(bp);
-		} else {
-			cmn_err(CE_WARN, "XFS: size check 3 failed");
-			if (error == ENOSPC)
-				error = XFS_ERROR(EFBIG);
-			return error;
+		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");
+			return EIO;
 		}
+		xfs_buf_relse(bp);
 	}
 	return 0;
 }
@@ -1601,7 +1607,7 @@
 		XFS_BUF_UNASYNC(sbp);
 		ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp);
 		xfsbdstrat(mp, sbp);
-		error = xfs_iowait(sbp);
+		error = xfs_buf_iowait(sbp);
 		if (error)
 			xfs_ioerror_alert("xfs_unmountfs_writesb",
 					  mp, sbp, XFS_BUF_ADDR(sbp));
@@ -1832,135 +1838,72 @@
  */
 int
 xfs_mod_incore_sb(
-	xfs_mount_t	*mp,
-	xfs_sb_field_t	field,
-	int64_t		delta,
-	int		rsvd)
+	struct xfs_mount	*mp,
+	xfs_sb_field_t		field,
+	int64_t			delta,
+	int			rsvd)
 {
-	int	status;
+	int			status;
 
-	/* check for per-cpu counters */
-	switch (field) {
 #ifdef HAVE_PERCPU_SB
-	case XFS_SBS_ICOUNT:
-	case XFS_SBS_IFREE:
-	case XFS_SBS_FDBLOCKS:
-		if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
-			status = xfs_icsb_modify_counters(mp, field,
-							delta, rsvd);
-			break;
-		}
-		/* FALLTHROUGH */
+	ASSERT(field < XFS_SBS_ICOUNT || field > XFS_SBS_FDBLOCKS);
 #endif
-	default:
-		spin_lock(&mp->m_sb_lock);
-		status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
-		spin_unlock(&mp->m_sb_lock);
-		break;
-	}
+	spin_lock(&mp->m_sb_lock);
+	status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
+	spin_unlock(&mp->m_sb_lock);
 
 	return status;
 }
 
 /*
- * xfs_mod_incore_sb_batch() is used to change more than one field
- * in the in-core superblock structure at a time.  This modification
- * is protected by a lock internal to this module.  The fields and
- * changes to those fields are specified in the array of xfs_mod_sb
- * structures passed in.
+ * Change more than one field in the in-core superblock structure at a time.
  *
- * Either all of the specified deltas will be applied or none of
- * them will.  If any modified field dips below 0, then all modifications
- * will be backed out and EINVAL will be returned.
+ * The fields and changes to those fields are specified in the array of
+ * xfs_mod_sb structures passed in.  Either all of the specified deltas
+ * will be applied or none of them will.  If any modified field dips below 0,
+ * then all modifications will be backed out and EINVAL will be returned.
+ *
+ * Note that this function may not be used for the superblock values that
+ * are tracked with the in-memory per-cpu counters - a direct call to
+ * xfs_icsb_modify_counters is required for these.
  */
 int
-xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd)
+xfs_mod_incore_sb_batch(
+	struct xfs_mount	*mp,
+	xfs_mod_sb_t		*msb,
+	uint			nmsb,
+	int			rsvd)
 {
-	int		status=0;
-	xfs_mod_sb_t	*msbp;
+	xfs_mod_sb_t		*msbp = &msb[0];
+	int			error = 0;
 
 	/*
-	 * Loop through the array of mod structures and apply each
-	 * individually.  If any fail, then back out all those
-	 * which have already been applied.  Do all of this within
-	 * the scope of the m_sb_lock so that all of the changes will
-	 * be atomic.
+	 * Loop through the array of mod structures and apply each individually.
+	 * If any fail, then back out all those which have already been applied.
+	 * Do all of this within the scope of the m_sb_lock so that all of the
+	 * changes will be atomic.
 	 */
 	spin_lock(&mp->m_sb_lock);
-	msbp = &msb[0];
 	for (msbp = &msbp[0]; msbp < (msb + nmsb); msbp++) {
-		/*
-		 * Apply the delta at index n.  If it fails, break
-		 * from the loop so we'll fall into the undo loop
-		 * below.
-		 */
-		switch (msbp->msb_field) {
-#ifdef HAVE_PERCPU_SB
-		case XFS_SBS_ICOUNT:
-		case XFS_SBS_IFREE:
-		case XFS_SBS_FDBLOCKS:
-			if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
-				spin_unlock(&mp->m_sb_lock);
-				status = xfs_icsb_modify_counters(mp,
-							msbp->msb_field,
-							msbp->msb_delta, rsvd);
-				spin_lock(&mp->m_sb_lock);
-				break;
-			}
-			/* FALLTHROUGH */
-#endif
-		default:
-			status = xfs_mod_incore_sb_unlocked(mp,
-						msbp->msb_field,
-						msbp->msb_delta, rsvd);
-			break;
-		}
+		ASSERT(msbp->msb_field < XFS_SBS_ICOUNT ||
+		       msbp->msb_field > XFS_SBS_FDBLOCKS);
 
-		if (status != 0) {
-			break;
-		}
-	}
-
-	/*
-	 * If we didn't complete the loop above, then back out
-	 * any changes made to the superblock.  If you add code
-	 * between the loop above and here, make sure that you
-	 * preserve the value of status. Loop back until
-	 * we step below the beginning of the array.  Make sure
-	 * we don't touch anything back there.
-	 */
-	if (status != 0) {
-		msbp--;
-		while (msbp >= msb) {
-			switch (msbp->msb_field) {
-#ifdef HAVE_PERCPU_SB
-			case XFS_SBS_ICOUNT:
-			case XFS_SBS_IFREE:
-			case XFS_SBS_FDBLOCKS:
-				if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
-					spin_unlock(&mp->m_sb_lock);
-					status = xfs_icsb_modify_counters(mp,
-							msbp->msb_field,
-							-(msbp->msb_delta),
-							rsvd);
-					spin_lock(&mp->m_sb_lock);
-					break;
-				}
-				/* FALLTHROUGH */
-#endif
-			default:
-				status = xfs_mod_incore_sb_unlocked(mp,
-							msbp->msb_field,
-							-(msbp->msb_delta),
-							rsvd);
-				break;
-			}
-			ASSERT(status == 0);
-			msbp--;
-		}
+		error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
+						   msbp->msb_delta, rsvd);
+		if (error)
+			goto unwind;
 	}
 	spin_unlock(&mp->m_sb_lock);
-	return status;
+	return 0;
+
+unwind:
+	while (--msbp >= msb) {
+		error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
+						   -msbp->msb_delta, rsvd);
+		ASSERT(error == 0);
+	}
+	spin_unlock(&mp->m_sb_lock);
+	return error;
 }
 
 /*
@@ -1998,18 +1941,13 @@
  */
 void
 xfs_freesb(
-	xfs_mount_t	*mp)
+	struct xfs_mount	*mp)
 {
-	xfs_buf_t	*bp;
+	struct xfs_buf		*bp = mp->m_sb_bp;
 
-	/*
-	 * Use xfs_getsb() so that the buffer will be locked
-	 * when we call xfs_buf_relse().
-	 */
-	bp = xfs_getsb(mp, 0);
-	XFS_BUF_UNMANAGE(bp);
-	xfs_buf_relse(bp);
+	xfs_buf_lock(bp);
 	mp->m_sb_bp = NULL;
+	xfs_buf_relse(bp);
 }
 
 /*
@@ -2496,7 +2434,7 @@
 	spin_unlock(&mp->m_sb_lock);
 }
 
-STATIC int
+int
 xfs_icsb_modify_counters(
 	xfs_mount_t	*mp,
 	xfs_sb_field_t	field,
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 622da21..5861b49 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -53,7 +53,6 @@
 
 #include "xfs_sync.h"
 
-struct cred;
 struct log;
 struct xfs_mount_args;
 struct xfs_inode;
@@ -91,6 +90,8 @@
 extern void	xfs_icsb_destroy_counters(struct xfs_mount *);
 extern void	xfs_icsb_sync_counters(struct xfs_mount *, int);
 extern void	xfs_icsb_sync_counters_locked(struct xfs_mount *, int);
+extern int	xfs_icsb_modify_counters(struct xfs_mount *, xfs_sb_field_t,
+						int64_t, int);
 
 #else
 #define xfs_icsb_init_counters(mp)		(0)
@@ -98,6 +99,8 @@
 #define xfs_icsb_reinit_counters(mp)		do { } while (0)
 #define xfs_icsb_sync_counters(mp, flags)	do { } while (0)
 #define xfs_icsb_sync_counters_locked(mp, flags) do { } while (0)
+#define xfs_icsb_modify_counters(mp, field, delta, rsvd) \
+	xfs_mod_incore_sb(mp, field, delta, rsvd)
 #endif
 
 typedef struct xfs_mount {
@@ -232,8 +235,6 @@
 #define XFS_MOUNT_DIRSYNC	(1ULL << 21)	/* synchronous directory ops */
 #define XFS_MOUNT_COMPAT_IOSIZE	(1ULL << 22)	/* don't report large preferred
 						 * I/O size in stat() */
-#define XFS_MOUNT_NO_PERCPU_SB	(1ULL << 23)	/* don't use per-cpu superblock
-						   counters */
 #define XFS_MOUNT_FILESTREAMS	(1ULL << 24)	/* enable the filestreams
 						   allocator */
 #define XFS_MOUNT_NOATTR2	(1ULL << 25)	/* disable use of attr2 format */
@@ -327,6 +328,8 @@
  * perag get/put wrappers for ref counting
  */
 struct xfs_perag *xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno);
+struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
+					int tag);
 void	xfs_perag_put(struct xfs_perag *pag);
 
 /*
diff --git a/fs/xfs/xfs_refcache.h b/fs/xfs/xfs_refcache.h
deleted file mode 100644
index 2dec79e..0000000
--- a/fs/xfs/xfs_refcache.h
+++ /dev/null
@@ -1,52 +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
- */
-#ifndef __XFS_REFCACHE_H__
-#define __XFS_REFCACHE_H__
-
-#ifdef HAVE_REFCACHE
-/*
- * Maximum size (in inodes) for the NFS reference cache
- */
-#define XFS_REFCACHE_SIZE_MAX	512
-
-struct xfs_inode;
-struct xfs_mount;
-
-extern void xfs_refcache_insert(struct xfs_inode *);
-extern void xfs_refcache_purge_ip(struct xfs_inode *);
-extern void xfs_refcache_purge_mp(struct xfs_mount *);
-extern void xfs_refcache_purge_some(struct xfs_mount *);
-extern void xfs_refcache_resize(int);
-extern void xfs_refcache_destroy(void);
-
-extern void xfs_refcache_iunlock(struct xfs_inode *, uint);
-
-#else
-
-#define xfs_refcache_insert(ip)		do { } while (0)
-#define xfs_refcache_purge_ip(ip)	do { } while (0)
-#define xfs_refcache_purge_mp(mp)	do { } while (0)
-#define xfs_refcache_purge_some(mp)	do { } while (0)
-#define xfs_refcache_resize(size)	do { } while (0)
-#define xfs_refcache_destroy()		do { } while (0)
-
-#define xfs_refcache_iunlock(ip, flags)	xfs_iunlock(ip, flags)
-
-#endif
-
-#endif	/* __XFS_REFCACHE_H__ */
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 8fca957..d2af0a8 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -183,7 +183,7 @@
 	 * tree quota mechanism would be circumvented.
 	 */
 	if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
-		     (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) {
+		     (xfs_get_projid(target_dp) != xfs_get_projid(src_ip)))) {
 		error = XFS_ERROR(EXDEV);
 		goto error_return;
 	}
@@ -211,7 +211,9 @@
 			goto error_return;
 		if (error)
 			goto abort_return;
-		xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+
+		xfs_trans_ichgtime(tp, target_dp,
+					XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
 		if (new_parent && src_is_directory) {
 			error = xfs_bumplink(tp, target_dp);
@@ -249,7 +251,9 @@
 					&first_block, &free_list, spaceres);
 		if (error)
 			goto abort_return;
-		xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+
+		xfs_trans_ichgtime(tp, target_dp,
+					XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
 		/*
 		 * Decrement the link count on the target since the target
@@ -292,7 +296,7 @@
 	 * inode isn't really being changed, but old unix file systems did
 	 * it and some incremental backup programs won't work without it.
 	 */
-	xfs_ichgtime(src_ip, XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, src_ip, XFS_ICHGTIME_CHG);
 
 	/*
 	 * Adjust the link count on src_dp.  This is necessary when
@@ -315,7 +319,7 @@
 	if (error)
 		goto abort_return;
 
-	xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, src_dp, XFS_ILOG_CORE);
 	if (new_parent)
 		xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE);
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 891260f..12a1913 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -39,6 +39,7 @@
 #include "xfs_trans_space.h"
 #include "xfs_utils.h"
 #include "xfs_trace.h"
+#include "xfs_buf.h"
 
 
 /*
@@ -1883,13 +1884,13 @@
 	/*
 	 * Read in the last block of the device, make sure it exists.
 	 */
-	error = xfs_read_buf(mp, mp->m_rtdev_targp,
-			XFS_FSB_TO_BB(mp, nrblocks - 1),
-			XFS_FSB_TO_BB(mp, 1), 0, &bp);
-	if (error)
-		return error;
-	ASSERT(bp);
+	bp = xfs_buf_read_uncached(mp, mp->m_rtdev_targp,
+				XFS_FSB_TO_BB(mp, nrblocks - 1),
+				XFS_FSB_TO_B(mp, 1), 0);
+	if (!bp)
+		return EIO;
 	xfs_buf_relse(bp);
+
 	/*
 	 * Calculate new parameters.  These are the final values to be reached.
 	 */
@@ -2215,7 +2216,6 @@
 {
 	xfs_buf_t	*bp;	/* buffer for last block of subvolume */
 	xfs_daddr_t	d;	/* address of last block of subvolume */
-	int		error;	/* error return value */
 	xfs_sb_t	*sbp;	/* filesystem superblock copy in mount */
 
 	sbp = &mp->m_sb;
@@ -2242,15 +2242,12 @@
 			(unsigned long long) mp->m_sb.sb_rblocks);
 		return XFS_ERROR(EFBIG);
 	}
-	error = xfs_read_buf(mp, mp->m_rtdev_targp,
-				d - XFS_FSB_TO_BB(mp, 1),
-				XFS_FSB_TO_BB(mp, 1), 0, &bp);
-	if (error) {
-		cmn_err(CE_WARN,
-	"XFS: realtime mount -- xfs_read_buf failed, returned %d", error);
-		if (error == ENOSPC)
-			return XFS_ERROR(EFBIG);
-		return error;
+	bp = xfs_buf_read_uncached(mp, mp->m_rtdev_targp,
+					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");
+		return EIO;
 	}
 	xfs_buf_relse(bp);
 	return 0;
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 1b017c6..1eb2ba5 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -80,10 +80,12 @@
 #define XFS_SB_VERSION2_RESERVED4BIT	0x00000004
 #define XFS_SB_VERSION2_ATTR2BIT	0x00000008	/* Inline attr rework */
 #define XFS_SB_VERSION2_PARENTBIT	0x00000010	/* parent pointers */
+#define XFS_SB_VERSION2_PROJID32BIT	0x00000080	/* 32 bit project id */
 
 #define	XFS_SB_VERSION2_OKREALFBITS	\
 	(XFS_SB_VERSION2_LAZYSBCOUNTBIT	| \
-	 XFS_SB_VERSION2_ATTR2BIT)
+	 XFS_SB_VERSION2_ATTR2BIT	| \
+	 XFS_SB_VERSION2_PROJID32BIT)
 #define	XFS_SB_VERSION2_OKSASHFBITS	\
 	(0)
 #define XFS_SB_VERSION2_OKREALBITS	\
@@ -495,6 +497,12 @@
 		sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT;
 }
 
+static inline int xfs_sb_version_hasprojid32bit(xfs_sb_t *sbp)
+{
+	return xfs_sb_version_hasmorebits(sbp) &&
+		(sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT);
+}
+
 /*
  * end of superblock version macros
  */
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 1c47eda..f6d956b 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -696,7 +696,7 @@
 	 * fail if the count would go below zero.
 	 */
 	if (blocks > 0) {
-		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
+		error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
 					  -((int64_t)blocks), rsvd);
 		if (error != 0) {
 			current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
@@ -767,7 +767,7 @@
 
 undo_blocks:
 	if (blocks > 0) {
-		(void) xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
+		xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
 					 (int64_t)blocks, rsvd);
 		tp->t_blk_res = 0;
 	}
@@ -1009,7 +1009,7 @@
 xfs_trans_unreserve_and_mod_sb(
 	xfs_trans_t	*tp)
 {
-	xfs_mod_sb_t	msb[14];	/* If you add cases, add entries */
+	xfs_mod_sb_t	msb[9];	/* If you add cases, add entries */
 	xfs_mod_sb_t	*msbp;
 	xfs_mount_t	*mp = tp->t_mountp;
 	/* REFERENCED */
@@ -1017,55 +1017,61 @@
 	int		rsvd;
 	int64_t		blkdelta = 0;
 	int64_t		rtxdelta = 0;
+	int64_t		idelta = 0;
+	int64_t		ifreedelta = 0;
 
 	msbp = msb;
 	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
 
-	/* calculate free blocks delta */
+	/* calculate deltas */
 	if (tp->t_blk_res > 0)
 		blkdelta = tp->t_blk_res;
-
 	if ((tp->t_fdblocks_delta != 0) &&
 	    (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
 	     (tp->t_flags & XFS_TRANS_SB_DIRTY)))
 	        blkdelta += tp->t_fdblocks_delta;
 
-	if (blkdelta != 0) {
-		msbp->msb_field = XFS_SBS_FDBLOCKS;
-		msbp->msb_delta = blkdelta;
-		msbp++;
-	}
-
-	/* calculate free realtime extents delta */
 	if (tp->t_rtx_res > 0)
 		rtxdelta = tp->t_rtx_res;
-
 	if ((tp->t_frextents_delta != 0) &&
 	    (tp->t_flags & XFS_TRANS_SB_DIRTY))
 		rtxdelta += tp->t_frextents_delta;
 
+	if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
+	     (tp->t_flags & XFS_TRANS_SB_DIRTY)) {
+		idelta = tp->t_icount_delta;
+		ifreedelta = tp->t_ifree_delta;
+	}
+
+	/* apply the per-cpu counters */
+	if (blkdelta) {
+		error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
+						 blkdelta, rsvd);
+		if (error)
+			goto out;
+	}
+
+	if (idelta) {
+		error = xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT,
+						 idelta, rsvd);
+		if (error)
+			goto out_undo_fdblocks;
+	}
+
+	if (ifreedelta) {
+		error = xfs_icsb_modify_counters(mp, XFS_SBS_IFREE,
+						 ifreedelta, rsvd);
+		if (error)
+			goto out_undo_icount;
+	}
+
+	/* apply remaining deltas */
 	if (rtxdelta != 0) {
 		msbp->msb_field = XFS_SBS_FREXTENTS;
 		msbp->msb_delta = rtxdelta;
 		msbp++;
 	}
 
-	/* apply remaining deltas */
-
-	if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
-	     (tp->t_flags & XFS_TRANS_SB_DIRTY)) {
-		if (tp->t_icount_delta != 0) {
-			msbp->msb_field = XFS_SBS_ICOUNT;
-			msbp->msb_delta = tp->t_icount_delta;
-			msbp++;
-		}
-		if (tp->t_ifree_delta != 0) {
-			msbp->msb_field = XFS_SBS_IFREE;
-			msbp->msb_delta = tp->t_ifree_delta;
-			msbp++;
-		}
-	}
-
 	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
 		if (tp->t_dblocks_delta != 0) {
 			msbp->msb_field = XFS_SBS_DBLOCKS;
@@ -1115,8 +1121,24 @@
 	if (msbp > msb) {
 		error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
 			(uint)(msbp - msb), rsvd);
-		ASSERT(error == 0);
+		if (error)
+			goto out_undo_ifreecount;
 	}
+
+	return;
+
+out_undo_ifreecount:
+	if (ifreedelta)
+		xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd);
+out_undo_icount:
+	if (idelta)
+		xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, -idelta, rsvd);
+out_undo_fdblocks:
+	if (blkdelta)
+		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);
+out:
+	ASSERT(error = 0);
+	return;
 }
 
 /*
@@ -1389,15 +1411,12 @@
  */
 STATIC void
 xfs_trans_committed(
-	struct xfs_trans	*tp,
+	void			*arg,
 	int			abortflag)
 {
+	struct xfs_trans	*tp = arg;
 	struct xfs_log_item_desc *lidp, *next;
 
-	/* Call the transaction's completion callback if there is one. */
-	if (tp->t_callback != NULL)
-		tp->t_callback(tp, tp->t_callarg);
-
 	list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
 		xfs_trans_item_committed(lidp->lid_item, tp->t_lsn, abortflag);
 		xfs_trans_free_item_desc(lidp);
@@ -1525,7 +1544,7 @@
 	 * running in simulation mode (the log is explicitly turned
 	 * off).
 	 */
-	tp->t_logcb.cb_func = (void(*)(void*, int))xfs_trans_committed;
+	tp->t_logcb.cb_func = xfs_trans_committed;
 	tp->t_logcb.cb_arg = tp;
 
 	/*
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index c13c0f9..246286b 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -399,8 +399,6 @@
 						 * transaction. */
 	struct xfs_mount	*t_mountp;	/* ptr to fs mount struct */
 	struct xfs_dquot_acct   *t_dqinfo;	/* acctg info for dquots */
-	xfs_trans_callback_t	t_callback;	/* transaction callback */
-	void			*t_callarg;	/* callback arg */
 	unsigned int		t_flags;	/* misc flags */
 	int64_t			t_icount_delta;	/* superblock icount change */
 	int64_t			t_ifree_delta;	/* superblock ifree change */
@@ -473,6 +471,7 @@
 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 *);
 void		xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 90af025..c47918c 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -336,7 +336,7 @@
 			ASSERT(!XFS_BUF_ISASYNC(bp));
 			XFS_BUF_READ(bp);
 			xfsbdstrat(tp->t_mountp, bp);
-			error = xfs_iowait(bp);
+			error = xfs_buf_iowait(bp);
 			if (error) {
 				xfs_ioerror_alert("xfs_trans_read_buf", mp,
 						  bp, blkno);
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index cdc53a1..ccb3453 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -118,6 +118,36 @@
 }
 
 /*
+ * Transactional inode timestamp update. Requires the inode to be locked and
+ * joined to the transaction supplied. Relies on the transaction subsystem to
+ * track dirty state and update/writeback the inode accordingly.
+ */
+void
+xfs_trans_ichgtime(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*ip,
+	int			flags)
+{
+	struct inode		*inode = VFS_I(ip);
+	timespec_t		tv;
+
+	ASSERT(tp);
+	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+	ASSERT(ip->i_transp == tp);
+
+	tv = current_fs_time(inode->i_sb);
+
+	if ((flags & XFS_ICHGTIME_MOD) &&
+	    !timespec_equal(&inode->i_mtime, &tv)) {
+		inode->i_mtime = tv;
+	}
+	if ((flags & XFS_ICHGTIME_CHG) &&
+	    !timespec_equal(&inode->i_ctime, &tv)) {
+		inode->i_ctime = tv;
+	}
+}
+
+/*
  * This is called to mark the fields indicated in fieldmask as needing
  * to be logged when the transaction is committed.  The inode must
  * already be associated with the given transaction.
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index 3207752..26d1867 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -73,8 +73,6 @@
 typedef	__uint32_t	xfs_dablk_t;	/* dir/attr block number (in file) */
 typedef	__uint32_t	xfs_dahash_t;	/* dir/attr hash value */
 
-typedef __uint16_t	xfs_prid_t;	/* prid_t truncated to 16bits in XFS */
-
 typedef __uint32_t	xlog_tid_t;	/* transaction ID type */
 
 /*
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index b7d5769..8b32d1a 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -56,7 +56,6 @@
 	mode_t		mode,
 	xfs_nlink_t	nlink,
 	xfs_dev_t	rdev,
-	cred_t		*credp,
 	prid_t		prid,		/* project id */
 	int		okalloc,	/* ok to allocate new space */
 	xfs_inode_t	**ipp,		/* pointer to inode; it will be
@@ -93,7 +92,7 @@
 	 * transaction commit so that no other process can steal
 	 * the inode(s) that we've just allocated.
 	 */
-	code = xfs_ialloc(tp, dp, mode, nlink, rdev, credp, prid, okalloc,
+	code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid, okalloc,
 			  &ialloc_context, &call_again, &ip);
 
 	/*
@@ -197,7 +196,7 @@
 		 * other allocations in this allocation group,
 		 * this call should always succeed.
 		 */
-		code = xfs_ialloc(tp, dp, mode, nlink, rdev, credp, prid,
+		code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid,
 				  okalloc, &ialloc_context, &call_again, &ip);
 
 		/*
@@ -235,7 +234,7 @@
 {
 	int	error;
 
-	xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
 
 	ASSERT (ip->i_d.di_nlink > 0);
 	ip->i_d.di_nlink--;
@@ -299,7 +298,7 @@
 {
 	if (ip->i_d.di_nlink >= XFS_MAXLINK)
 		return XFS_ERROR(EMLINK);
-	xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
 
 	ASSERT(ip->i_d.di_nlink > 0);
 	ip->i_d.di_nlink++;
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
index f55b967..456fca3 100644
--- a/fs/xfs/xfs_utils.h
+++ b/fs/xfs/xfs_utils.h
@@ -19,8 +19,7 @@
 #define __XFS_UTILS_H__
 
 extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
-				xfs_dev_t, cred_t *, prid_t, int,
-				xfs_inode_t **, int *);
+				xfs_dev_t, prid_t, int, xfs_inode_t **, int *);
 extern int xfs_droplink(xfs_trans_t *, xfs_inode_t *);
 extern int xfs_bumplink(xfs_trans_t *, xfs_inode_t *);
 extern void xfs_bump_ino_vers2(xfs_trans_t *, xfs_inode_t *);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 4c7c7bf..8e4a63c 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -114,7 +114,7 @@
 		 */
 		ASSERT(udqp == NULL);
 		ASSERT(gdqp == NULL);
-		code = xfs_qm_vop_dqalloc(ip, uid, gid, ip->i_d.di_projid,
+		code = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip),
 					 qflags, &udqp, &gdqp);
 		if (code)
 			return code;
@@ -184,8 +184,11 @@
 		    ip->i_size == 0 && ip->i_d.di_nextents == 0) {
 			xfs_iunlock(ip, XFS_ILOCK_EXCL);
 			lock_flags &= ~XFS_ILOCK_EXCL;
-			if (mask & ATTR_CTIME)
-				xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+			if (mask & ATTR_CTIME) {
+				inode->i_mtime = inode->i_ctime =
+						current_fs_time(inode->i_sb);
+				xfs_mark_inode_dirty_sync(ip);
+			}
 			code = 0;
 			goto error_return;
 		}
@@ -1253,8 +1256,7 @@
 	struct xfs_name		*name,
 	mode_t			mode,
 	xfs_dev_t		rdev,
-	xfs_inode_t		**ipp,
-	cred_t			*credp)
+	xfs_inode_t		**ipp)
 {
 	int			is_dir = S_ISDIR(mode);
 	struct xfs_mount	*mp = dp->i_mount;
@@ -1266,7 +1268,7 @@
 	boolean_t		unlock_dp_on_error = B_FALSE;
 	uint			cancel_flags;
 	int			committed;
-	xfs_prid_t		prid;
+	prid_t			prid;
 	struct xfs_dquot	*udqp = NULL;
 	struct xfs_dquot	*gdqp = NULL;
 	uint			resblks;
@@ -1279,9 +1281,9 @@
 		return XFS_ERROR(EIO);
 
 	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
-		prid = dp->i_d.di_projid;
+		prid = xfs_get_projid(dp);
 	else
-		prid = dfltprid;
+		prid = XFS_PROJID_DEFAULT;
 
 	/*
 	 * Make sure that we have allocated dquot(s) on disk.
@@ -1360,7 +1362,7 @@
 	 * entry pointing to them, but a directory also the "." entry
 	 * pointing to itself.
 	 */
-	error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev, credp,
+	error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev,
 			       prid, resblks > 0, &ip, &committed);
 	if (error) {
 		if (error == ENOSPC)
@@ -1391,7 +1393,7 @@
 		ASSERT(error != ENOSPC);
 		goto out_trans_abort;
 	}
-	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
 	if (is_dir) {
@@ -1742,7 +1744,7 @@
 		ASSERT(error != ENOENT);
 		goto out_bmap_cancel;
 	}
-	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
 	if (is_dir) {
 		/*
@@ -1880,7 +1882,7 @@
 	 * the tree quota mechanism could be circumvented.
 	 */
 	if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
-		     (tdp->i_d.di_projid != sip->i_d.di_projid))) {
+		     (xfs_get_projid(tdp) != xfs_get_projid(sip)))) {
 		error = XFS_ERROR(EXDEV);
 		goto error_return;
 	}
@@ -1895,7 +1897,7 @@
 					&first_block, &free_list, resblks);
 	if (error)
 		goto abort_return;
-	xfs_ichgtime(tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);
 
 	error = xfs_bumplink(tp, sip);
@@ -1933,8 +1935,7 @@
 	struct xfs_name		*link_name,
 	const char		*target_path,
 	mode_t			mode,
-	xfs_inode_t		**ipp,
-	cred_t			*credp)
+	xfs_inode_t		**ipp)
 {
 	xfs_mount_t		*mp = dp->i_mount;
 	xfs_trans_t		*tp;
@@ -1955,7 +1956,7 @@
 	int			byte_cnt;
 	int			n;
 	xfs_buf_t		*bp;
-	xfs_prid_t		prid;
+	prid_t			prid;
 	struct xfs_dquot	*udqp, *gdqp;
 	uint			resblks;
 
@@ -1978,9 +1979,9 @@
 
 	udqp = gdqp = NULL;
 	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
-		prid = dp->i_d.di_projid;
+		prid = xfs_get_projid(dp);
 	else
-		prid = (xfs_prid_t)dfltprid;
+		prid = XFS_PROJID_DEFAULT;
 
 	/*
 	 * Make sure that we have allocated dquot(s) on disk.
@@ -2046,8 +2047,8 @@
 	/*
 	 * Allocate an inode for the symlink.
 	 */
-	error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT),
-			       1, 0, credp, prid, resblks > 0, &ip, NULL);
+	error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT), 1, 0,
+			       prid, resblks > 0, &ip, NULL);
 	if (error) {
 		if (error == ENOSPC)
 			goto error_return;
@@ -2129,7 +2130,7 @@
 					&first_block, &free_list, resblks);
 	if (error)
 		goto error1;
-	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
 	/*
@@ -2272,7 +2273,7 @@
 	count = len;
 	imapp = &imaps[0];
 	nimaps = 1;
-	bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
+	bmapi_flag = XFS_BMAPI_WRITE | alloc_type;
 	startoffset_fsb	= XFS_B_TO_FSBT(mp, offset);
 	allocatesize_fsb = XFS_B_TO_FSB(mp, count);
 
@@ -2431,9 +2432,9 @@
 	if (endoff > ip->i_size)
 		endoff = ip->i_size;
 
-	bp = xfs_buf_get_noaddr(mp->m_sb.sb_blocksize,
-				XFS_IS_REALTIME_INODE(ip) ?
-				mp->m_rtdev_targp : mp->m_ddev_targp);
+	bp = xfs_buf_get_uncached(XFS_IS_REALTIME_INODE(ip) ?
+					mp->m_rtdev_targp : mp->m_ddev_targp,
+				mp->m_sb.sb_blocksize, XBF_DONT_BLOCK);
 	if (!bp)
 		return XFS_ERROR(ENOMEM);
 
@@ -2459,7 +2460,7 @@
 		XFS_BUF_READ(bp);
 		XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
 		xfsbdstrat(mp, bp);
-		error = xfs_iowait(bp);
+		error = xfs_buf_iowait(bp);
 		if (error) {
 			xfs_ioerror_alert("xfs_zero_remaining_bytes(read)",
 					  mp, bp, XFS_BUF_ADDR(bp));
@@ -2472,7 +2473,7 @@
 		XFS_BUF_UNREAD(bp);
 		XFS_BUF_WRITE(bp);
 		xfsbdstrat(mp, bp);
-		error = xfs_iowait(bp);
+		error = xfs_buf_iowait(bp);
 		if (error) {
 			xfs_ioerror_alert("xfs_zero_remaining_bytes(write)",
 					  mp, bp, XFS_BUF_ADDR(bp));
@@ -2711,6 +2712,7 @@
 	xfs_off_t	llen;
 	xfs_trans_t	*tp;
 	struct iattr	iattr;
+	int		prealloc_type;
 
 	if (!S_ISREG(ip->i_d.di_mode))
 		return XFS_ERROR(EINVAL);
@@ -2753,12 +2755,17 @@
 	 * size to be changed.
 	 */
 	setprealloc = clrprealloc = 0;
+	prealloc_type = XFS_BMAPI_PREALLOC;
 
 	switch (cmd) {
+	case XFS_IOC_ZERO_RANGE:
+		prealloc_type |= XFS_BMAPI_CONVERT;
+		xfs_tosspages(ip, startoffset, startoffset + bf->l_len, 0);
+		/* FALLTHRU */
 	case XFS_IOC_RESVSP:
 	case XFS_IOC_RESVSP64:
 		error = xfs_alloc_file_space(ip, startoffset, bf->l_len,
-								1, attr_flags);
+						prealloc_type, attr_flags);
 		if (error)
 			return error;
 		setprealloc = 1;
@@ -2827,7 +2834,7 @@
 		if (ip->i_d.di_mode & S_IXGRP)
 			ip->i_d.di_mode &= ~S_ISGID;
 
-		xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+		xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	}
 	if (setprealloc)
 		ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index d8dfa8d..f6702927 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -2,7 +2,6 @@
 #define _XFS_VNODEOPS_H 1
 
 struct attrlist_cursor_kern;
-struct cred;
 struct file;
 struct iattr;
 struct inode;
@@ -26,7 +25,7 @@
 int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
 		struct xfs_inode **ipp, struct xfs_name *ci_name);
 int xfs_create(struct xfs_inode *dp, struct xfs_name *name, mode_t mode,
-		xfs_dev_t rdev, struct xfs_inode **ipp, cred_t *credp);
+		xfs_dev_t rdev, struct xfs_inode **ipp);
 int xfs_remove(struct xfs_inode *dp, struct xfs_name *name,
 		struct xfs_inode *ip);
 int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
@@ -34,8 +33,7 @@
 int xfs_readdir(struct xfs_inode	*dp, void *dirent, size_t bufsize,
 		       xfs_off_t *offset, filldir_t filldir);
 int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
-		const char *target_path, mode_t mode, struct xfs_inode **ipp,
-		cred_t *credp);
+		const char *target_path, mode_t mode, struct xfs_inode **ipp);
 int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state);
 int xfs_change_file_space(struct xfs_inode *ip, int cmd,
 		xfs_flock64_t *bf, xfs_off_t offset, int attr_flags);
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index c0786d4..984cdc6 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -55,7 +55,7 @@
 extern u8 acpi_gbl_permanent_mmap;
 
 /*
- * Globals that are publically available, allowing for
+ * Globals that are publicly available, allowing for
  * run time configuration
  */
 extern u32 acpi_dbg_level;
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index e53347f..e994197 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -43,6 +43,7 @@
  */
 #define atomic_set(v, i) (((v)->counter) = (i))
 
+#include <linux/irqflags.h>
 #include <asm/system.h>
 
 /**
@@ -57,7 +58,7 @@
 	unsigned long flags;
 	int temp;
 
-	raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
+	raw_local_irq_save(flags); /* Don't trace it in an irqsoff handler */
 	temp = v->counter;
 	temp += i;
 	v->counter = temp;
@@ -78,7 +79,7 @@
 	unsigned long flags;
 	int temp;
 
-	raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
+	raw_local_irq_save(flags); /* Don't trace it in an irqsoff handler */
 	temp = v->counter;
 	temp -= i;
 	v->counter = temp;
@@ -119,14 +120,23 @@
 #define atomic_dec_and_test(v)		(atomic_sub_return(1, (v)) == 0)
 #define atomic_inc_and_test(v)		(atomic_add_return(1, (v)) == 0)
 
-#define atomic_add_unless(v, a, u)				\
-({								\
-	int c, old;						\
-	c = atomic_read(v);					\
-	while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-		c = old;					\
-	c != (u);						\
-})
+#define atomic_xchg(ptr, v)		(xchg(&(ptr)->counter, (v)))
+#define atomic_cmpxchg(v, old, new)	(cmpxchg(&((v)->counter), (old), (new)))
+
+#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))
+
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
+{
+  int c, old;
+  c = atomic_read(v);
+  while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c)
+    c = old;
+  return c != u;
+}
 
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
@@ -140,15 +150,6 @@
 	raw_local_irq_restore(flags);
 }
 
-#define atomic_xchg(ptr, v)		(xchg(&(ptr)->counter, (v)))
-#define atomic_cmpxchg(v, old, new)	(cmpxchg(&((v)->counter), (old), (new)))
-
-#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))
-
 /* Assume that atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()	barrier()
 #define smp_mb__after_atomic_dec()	barrier()
diff --git a/include/asm-generic/bitops/find.h b/include/asm-generic/bitops/find.h
index 1914e97..110fa70 100644
--- a/include/asm-generic/bitops/find.h
+++ b/include/asm-generic/bitops/find.h
@@ -1,15 +1,50 @@
 #ifndef _ASM_GENERIC_BITOPS_FIND_H_
 #define _ASM_GENERIC_BITOPS_FIND_H_
 
-#ifndef CONFIG_GENERIC_FIND_NEXT_BIT
+/**
+ * find_next_bit - find the next set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The bitmap size in bits
+ */
 extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
 		size, unsigned long offset);
 
+/**
+ * find_next_zero_bit - find the next cleared bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The bitmap size in bits
+ */
 extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned
 		long size, unsigned long offset);
-#endif
+
+#ifdef CONFIG_GENERIC_FIND_FIRST_BIT
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit number of the first set bit.
+ */
+extern unsigned long find_first_bit(const unsigned long *addr,
+				    unsigned long size);
+
+/**
+ * find_first_zero_bit - find the first cleared bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit number of the first cleared bit.
+ */
+extern unsigned long find_first_zero_bit(const unsigned long *addr,
+					 unsigned long size);
+#else /* CONFIG_GENERIC_FIND_FIRST_BIT */
 
 #define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
 #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
 
+#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
+
 #endif /*_ASM_GENERIC_BITOPS_FIND_H_ */
diff --git a/include/asm-generic/cmpxchg-local.h b/include/asm-generic/cmpxchg-local.h
index b2ba2fc..2533fdd 100644
--- a/include/asm-generic/cmpxchg-local.h
+++ b/include/asm-generic/cmpxchg-local.h
@@ -2,6 +2,7 @@
 #define __ASM_GENERIC_CMPXCHG_LOCAL_H
 
 #include <linux/types.h>
+#include <linux/irqflags.h>
 
 extern unsigned long wrong_size_cmpxchg(volatile void *ptr);
 
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index a70b2d2..0fc16e3 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -122,7 +122,7 @@
 
 struct f_owner_ex {
 	int	type;
-	pid_t	pid;
+	__kernel_pid_t	pid;
 };
 
 /* for F_[GET|SET]FL */
diff --git a/include/asm-generic/hardirq.h b/include/asm-generic/hardirq.h
index 62f5908..04d0a97 100644
--- a/include/asm-generic/hardirq.h
+++ b/include/asm-generic/hardirq.h
@@ -3,13 +3,13 @@
 
 #include <linux/cache.h>
 #include <linux/threads.h>
-#include <linux/irq.h>
 
 typedef struct {
 	unsigned int __softirq_pending;
 } ____cacheline_aligned irq_cpustat_t;
 
 #include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+#include <linux/irq.h>
 
 #ifndef ack_bad_irq
 static inline void ack_bad_irq(unsigned int irq)
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 118601f..3577ca1 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -19,7 +19,9 @@
 #include <asm-generic/iomap.h>
 #endif
 
+#ifndef mmiowb
 #define mmiowb() do {} while (0)
+#endif
 
 /*****************************************************************************/
 /*
@@ -28,39 +30,51 @@
  * differently. On the simple architectures, we just read/write the
  * memory location directly.
  */
+#ifndef __raw_readb
 static inline u8 __raw_readb(const volatile void __iomem *addr)
 {
 	return *(const volatile u8 __force *) addr;
 }
+#endif
 
+#ifndef __raw_readw
 static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
 	return *(const volatile u16 __force *) addr;
 }
+#endif
 
+#ifndef __raw_readl
 static inline u32 __raw_readl(const volatile void __iomem *addr)
 {
 	return *(const volatile u32 __force *) addr;
 }
+#endif
 
 #define readb __raw_readb
 #define readw(addr) __le16_to_cpu(__raw_readw(addr))
 #define readl(addr) __le32_to_cpu(__raw_readl(addr))
 
+#ifndef __raw_writeb
 static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
 {
 	*(volatile u8 __force *) addr = b;
 }
+#endif
 
+#ifndef __raw_writew
 static inline void __raw_writew(u16 b, volatile void __iomem *addr)
 {
 	*(volatile u16 __force *) addr = b;
 }
+#endif
 
+#ifndef __raw_writel
 static inline void __raw_writel(u32 b, volatile void __iomem *addr)
 {
 	*(volatile u32 __force *) addr = b;
 }
+#endif
 
 #define writeb __raw_writeb
 #define writew(b,addr) __raw_writew(__cpu_to_le16(b),addr)
@@ -122,6 +136,7 @@
 #define outw_p(x, addr)	outw((x), (addr))
 #define outl_p(x, addr)	outl((x), (addr))
 
+#ifndef insb
 static inline void insb(unsigned long addr, void *buffer, int count)
 {
 	if (count) {
@@ -132,7 +147,9 @@
 		} while (--count);
 	}
 }
+#endif
 
+#ifndef insw
 static inline void insw(unsigned long addr, void *buffer, int count)
 {
 	if (count) {
@@ -143,7 +160,9 @@
 		} while (--count);
 	}
 }
+#endif
 
+#ifndef insl
 static inline void insl(unsigned long addr, void *buffer, int count)
 {
 	if (count) {
@@ -154,7 +173,9 @@
 		} while (--count);
 	}
 }
+#endif
 
+#ifndef outsb
 static inline void outsb(unsigned long addr, const void *buffer, int count)
 {
 	if (count) {
@@ -164,7 +185,9 @@
 		} while (--count);
 	}
 }
+#endif
 
+#ifndef outsw
 static inline void outsw(unsigned long addr, const void *buffer, int count)
 {
 	if (count) {
@@ -174,7 +197,9 @@
 		} while (--count);
 	}
 }
+#endif
 
+#ifndef outsl
 static inline void outsl(unsigned long addr, const void *buffer, int count)
 {
 	if (count) {
@@ -184,6 +209,7 @@
 		} while (--count);
 	}
 }
+#endif
 
 #ifndef CONFIG_GENERIC_IOMAP
 #define ioread8(addr)		readb(addr)
diff --git a/include/asm-generic/ioctls.h b/include/asm-generic/ioctls.h
index 8554cb6..a321665 100644
--- a/include/asm-generic/ioctls.h
+++ b/include/asm-generic/ioctls.h
@@ -62,7 +62,9 @@
 #define TCSETSW2	_IOW('T', 0x2C, struct termios2)
 #define TCSETSF2	_IOW('T', 0x2D, struct termios2)
 #define TIOCGRS485	0x542E
+#ifndef TIOCSRS485
 #define TIOCSRS485	0x542F
+#endif
 #define TIOCGPTN	_IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T', 0x31, int)  /* Lock/unlock Pty */
 #define TCGETX		0x5432 /* SYS5 TCGETX compatibility */
diff --git a/include/asm-generic/irqflags.h b/include/asm-generic/irqflags.h
index 9aebf61..1f40d002 100644
--- a/include/asm-generic/irqflags.h
+++ b/include/asm-generic/irqflags.h
@@ -5,68 +5,62 @@
  * All architectures should implement at least the first two functions,
  * usually inline assembly will be the best way.
  */
-#ifndef RAW_IRQ_DISABLED
-#define RAW_IRQ_DISABLED 0
-#define RAW_IRQ_ENABLED 1
+#ifndef ARCH_IRQ_DISABLED
+#define ARCH_IRQ_DISABLED 0
+#define ARCH_IRQ_ENABLED 1
 #endif
 
 /* read interrupt enabled status */
-#ifndef __raw_local_save_flags
-unsigned long __raw_local_save_flags(void);
+#ifndef arch_local_save_flags
+unsigned long arch_local_save_flags(void);
 #endif
 
 /* set interrupt enabled status */
-#ifndef raw_local_irq_restore
-void raw_local_irq_restore(unsigned long flags);
+#ifndef arch_local_irq_restore
+void arch_local_irq_restore(unsigned long flags);
 #endif
 
 /* get status and disable interrupts */
-#ifndef __raw_local_irq_save
-static inline unsigned long __raw_local_irq_save(void)
+#ifndef arch_local_irq_save
+static inline unsigned long arch_local_irq_save(void)
 {
 	unsigned long flags;
-	flags = __raw_local_save_flags();
-	raw_local_irq_restore(RAW_IRQ_DISABLED);
+	flags = arch_local_save_flags();
+	arch_local_irq_restore(ARCH_IRQ_DISABLED);
 	return flags;
 }
 #endif
 
 /* test flags */
-#ifndef raw_irqs_disabled_flags
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+#ifndef arch_irqs_disabled_flags
+static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
-	return flags == RAW_IRQ_DISABLED;
+	return flags == ARCH_IRQ_DISABLED;
 }
 #endif
 
 /* unconditionally enable interrupts */
-#ifndef raw_local_irq_enable
-static inline void raw_local_irq_enable(void)
+#ifndef arch_local_irq_enable
+static inline void arch_local_irq_enable(void)
 {
-	raw_local_irq_restore(RAW_IRQ_ENABLED);
+	arch_local_irq_restore(ARCH_IRQ_ENABLED);
 }
 #endif
 
 /* unconditionally disable interrupts */
-#ifndef raw_local_irq_disable
-static inline void raw_local_irq_disable(void)
+#ifndef arch_local_irq_disable
+static inline void arch_local_irq_disable(void)
 {
-	raw_local_irq_restore(RAW_IRQ_DISABLED);
+	arch_local_irq_restore(ARCH_IRQ_DISABLED);
 }
 #endif
 
 /* test hardware interrupt enable bit */
-#ifndef raw_irqs_disabled
-static inline int raw_irqs_disabled(void)
+#ifndef arch_irqs_disabled
+static inline int arch_irqs_disabled(void)
 {
-	return raw_irqs_disabled_flags(__raw_local_save_flags());
+	return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 #endif
 
-#define raw_local_save_flags(flags) \
-	do { (flags) = __raw_local_save_flags(); } while (0)
-
-#define raw_local_irq_save(flags) \
-	do { (flags) = __raw_local_irq_save(); } while (0)
-
 #endif /* __ASM_GENERIC_IRQFLAGS_H */
diff --git a/include/asm-generic/kdebug.h b/include/asm-generic/kdebug.h
index 11e57b6..d181449 100644
--- a/include/asm-generic/kdebug.h
+++ b/include/asm-generic/kdebug.h
@@ -3,7 +3,7 @@
 
 enum die_val {
 	DIE_UNUSED,
-	DIE_OOPS=1
+	DIE_OOPS = 1,
 };
 
 #endif /* _ASM_GENERIC_KDEBUG_H */
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index 08923b6..d17784e 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -55,14 +55,18 @@
  */
 #define per_cpu(var, cpu) \
 	(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))
-#define __get_cpu_var(var) \
-	(*SHIFT_PERCPU_PTR(&(var), my_cpu_offset))
-#define __raw_get_cpu_var(var) \
-	(*SHIFT_PERCPU_PTR(&(var), __my_cpu_offset))
 
-#define this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, my_cpu_offset)
+#ifndef __this_cpu_ptr
 #define __this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, __my_cpu_offset)
+#endif
+#ifdef CONFIG_DEBUG_PREEMPT
+#define this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, my_cpu_offset)
+#else
+#define this_cpu_ptr(ptr) __this_cpu_ptr(ptr)
+#endif
 
+#define __get_cpu_var(var) (*this_cpu_ptr(&(var)))
+#define __raw_get_cpu_var(var) (*__this_cpu_ptr(&(var)))
 
 #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA
 extern void setup_per_cpu_areas(void);
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index e2bd73e..f4d4120 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -129,6 +129,10 @@
 #define move_pte(pte, prot, old_addr, new_addr)	(pte)
 #endif
 
+#ifndef flush_tlb_fix_spurious_fault
+#define flush_tlb_fix_spurious_fault(vma, address) flush_tlb_page(vma, address)
+#endif
+
 #ifndef pgprot_noncached
 #define pgprot_noncached(prot)	(prot)
 #endif
diff --git a/include/asm-generic/system.h b/include/asm-generic/system.h
index efa403b..4b0b9cb 100644
--- a/include/asm-generic/system.h
+++ b/include/asm-generic/system.h
@@ -21,6 +21,7 @@
 #include <linux/irqflags.h>
 
 #include <asm/cmpxchg-local.h>
+#include <asm/cmpxchg.h>
 
 struct task_struct;
 
@@ -136,25 +137,6 @@
 #define xchg(ptr, x) \
 	((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
 
-static inline unsigned long __cmpxchg(volatile unsigned long *m,
-				      unsigned long old, unsigned long new)
-{
-	unsigned long retval;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	retval = *m;
-	if (retval == old)
-		*m = new;
-	local_irq_restore(flags);
-	return retval;
-}
-
-#define cmpxchg(ptr, o, n)					\
-	((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
-					(unsigned long)(o),	\
-					(unsigned long)(n)))
-
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a92a17..f4229fb 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -220,6 +220,8 @@
 									\
 	BUG_TABLE							\
 									\
+	JUMP_TABLE							\
+									\
 	/* PCI quirks */						\
 	.pci_fixup        : AT(ADDR(.pci_fixup) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_pci_fixups_early) = .;		\
@@ -563,6 +565,14 @@
 #define BUG_TABLE
 #endif
 
+#define JUMP_TABLE							\
+	. = ALIGN(8);							\
+	__jump_table : AT(ADDR(__jump_table) - LOAD_OFFSET) {		\
+		VMLINUX_SYMBOL(__start___jump_table) = .;		\
+		*(__jump_table)						\
+		VMLINUX_SYMBOL(__stop___jump_table) = .;		\
+	}
+
 #ifdef CONFIG_PM_TRACE
 #define TRACEDATA							\
 	. = ALIGN(4);							\
@@ -677,7 +687,9 @@
 				- LOAD_OFFSET) {			\
 		VMLINUX_SYMBOL(__per_cpu_start) = .;			\
 		*(.data..percpu..first)					\
+		. = ALIGN(PAGE_SIZE);					\
 		*(.data..percpu..page_aligned)				\
+		*(.data..percpu..readmostly)				\
 		*(.data..percpu)					\
 		*(.data..percpu..shared_aligned)			\
 		VMLINUX_SYMBOL(__per_cpu_end) = .;			\
@@ -703,7 +715,9 @@
 		VMLINUX_SYMBOL(__per_cpu_load) = .;			\
 		VMLINUX_SYMBOL(__per_cpu_start) = .;			\
 		*(.data..percpu..first)					\
+		. = ALIGN(PAGE_SIZE);					\
 		*(.data..percpu..page_aligned)				\
+		*(.data..percpu..readmostly)				\
 		*(.data..percpu)					\
 		*(.data..percpu..shared_aligned)			\
 		VMLINUX_SYMBOL(__per_cpu_end) = .;			\
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 7809d230..4c9461a 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -612,7 +612,7 @@
 	struct kref refcount;
 
 	/** Handle count of this object. Each handle also holds a reference */
-	struct kref handlecount;
+	atomic_t handle_count; /* number of handles on this object */
 
 	/** Related drm device */
 	struct drm_device *dev;
@@ -808,7 +808,6 @@
 	 */
 	int (*gem_init_object) (struct drm_gem_object *obj);
 	void (*gem_free_object) (struct drm_gem_object *obj);
-	void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
 
 	/* vga arb irq handler */
 	void (*vgaarb_irq)(struct drm_device *dev, bool state);
@@ -1175,6 +1174,7 @@
 extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
 extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);
 extern void drm_vm_open_locked(struct vm_area_struct *vma);
+extern void drm_vm_close_locked(struct vm_area_struct *vma);
 extern resource_size_t drm_core_get_map_ofs(struct drm_local_map * map);
 extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev);
 extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
@@ -1455,12 +1455,11 @@
 void drm_gem_destroy(struct drm_device *dev);
 void drm_gem_object_release(struct drm_gem_object *obj);
 void drm_gem_object_free(struct kref *kref);
-void drm_gem_object_free_unlocked(struct kref *kref);
 struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
 					    size_t size);
 int drm_gem_object_init(struct drm_device *dev,
 			struct drm_gem_object *obj, size_t size);
-void drm_gem_object_handle_free(struct kref *kref);
+void drm_gem_object_handle_free(struct drm_gem_object *obj);
 void drm_gem_vm_open(struct vm_area_struct *vma);
 void drm_gem_vm_close(struct vm_area_struct *vma);
 int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
@@ -1483,8 +1482,12 @@
 static inline void
 drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
 {
-	if (obj != NULL)
-		kref_put(&obj->refcount, drm_gem_object_free_unlocked);
+	if (obj != NULL) {
+		struct drm_device *dev = obj->dev;
+		mutex_lock(&dev->struct_mutex);
+		kref_put(&obj->refcount, drm_gem_object_free);
+		mutex_unlock(&dev->struct_mutex);
+	}
 }
 
 int drm_gem_handle_create(struct drm_file *file_priv,
@@ -1495,7 +1498,7 @@
 drm_gem_object_handle_reference(struct drm_gem_object *obj)
 {
 	drm_gem_object_reference(obj);
-	kref_get(&obj->handlecount);
+	atomic_inc(&obj->handle_count);
 }
 
 static inline void
@@ -1504,12 +1507,15 @@
 	if (obj == NULL)
 		return;
 
+	if (atomic_read(&obj->handle_count) == 0)
+		return;
 	/*
 	 * Must bump handle count first as this may be the last
 	 * ref, in which case the object would disappear before we
 	 * checked for a name
 	 */
-	kref_put(&obj->handlecount, drm_gem_object_handle_free);
+	if (atomic_dec_and_test(&obj->handle_count))
+		drm_gem_object_handle_free(obj);
 	drm_gem_object_unreference(obj);
 }
 
@@ -1519,12 +1525,17 @@
 	if (obj == NULL)
 		return;
 
+	if (atomic_read(&obj->handle_count) == 0)
+		return;
+
 	/*
 	* Must bump handle count first as this may be the last
 	* ref, in which case the object would disappear before we
 	* checked for a name
 	*/
-	kref_put(&obj->handlecount, drm_gem_object_handle_free);
+
+	if (atomic_dec_and_test(&obj->handle_count))
+		drm_gem_object_handle_free(obj);
 	drm_gem_object_unreference_unlocked(obj);
 }
 
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index 3a9940e..883c1d4 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -85,7 +85,6 @@
 	{0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
-	{0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
@@ -103,6 +102,7 @@
 	{0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
 	{0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x5954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index 267a86c..2040e6c 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -246,9 +246,11 @@
 
 	atomic_t reserved;
 
-
 	/**
 	 * Members protected by the bo::lock
+	 * In addition, setting sync_obj to anything else
+	 * than NULL requires bo::reserved to be held. This allows for
+	 * checking NULL while reserved but not holding bo::lock.
 	 */
 
 	void *sync_obj_arg;
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 626b629..831c463 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -118,7 +118,6 @@
 header-y += ext2_fs.h
 header-y += fadvise.h
 header-y += falloc.h
-header-y += fanotify.h
 header-y += fb.h
 header-y += fcntl.h
 header-y += fd.h
@@ -302,6 +301,7 @@
 header-y += radeonfb.h
 header-y += random.h
 header-y += raw.h
+header-y += rds.h
 header-y += reboot.h
 header-y += reiserfs_fs.h
 header-y += reiserfs_xattr.h
diff --git a/include/linux/acpi_pmtmr.h b/include/linux/acpi_pmtmr.h
index 7e3d285..1d0ef1a 100644
--- a/include/linux/acpi_pmtmr.h
+++ b/include/linux/acpi_pmtmr.h
@@ -25,8 +25,6 @@
 	return acpi_pm_read_verified() & ACPI_PM_MASK;
 }
 
-extern void pmtimer_wait(unsigned);
-
 #else
 
 static inline u32 acpi_pm_read_early(void)
diff --git a/include/linux/altera_uart.h b/include/linux/altera_uart.h
index 8d44106..a10a907 100644
--- a/include/linux/altera_uart.h
+++ b/include/linux/altera_uart.h
@@ -5,10 +5,15 @@
 #ifndef	__ALTUART_H
 #define	__ALTUART_H
 
+#include <linux/init.h>
+
 struct altera_uart_platform_uart {
 	unsigned long mapbase;	/* Physical address base */
 	unsigned int irq;	/* Interrupt vector */
 	unsigned int uartclk;	/* UART clock rate */
+	unsigned int bus_shift;	/* Bus shift (address stride) */
 };
 
+int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp);
+
 #endif /* __ALTUART_H */
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index b0c1740..c6454cc 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -20,6 +20,7 @@
 #include <linux/resource.h>
 
 #define AMBA_NR_IRQS	2
+#define AMBA_CID	0xb105f00d
 
 struct clk;
 
@@ -70,9 +71,15 @@
 #define amba_pclk_disable(d)	\
 	do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0)
 
-#define amba_config(d)	(((d)->periphid >> 24) & 0xff)
-#define amba_rev(d)	(((d)->periphid >> 20) & 0x0f)
-#define amba_manf(d)	(((d)->periphid >> 12) & 0xff)
-#define amba_part(d)	((d)->periphid & 0xfff)
+/* Some drivers don't use the struct amba_device */
+#define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
+#define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)
+#define AMBA_MANF_BITS(a) (((a) >> 12) & 0xff)
+#define AMBA_PART_BITS(a) ((a) & 0xfff)
+
+#define amba_config(d)	AMBA_CONFIG_BITS((d)->periphid)
+#define amba_rev(d)	AMBA_REV_BITS((d)->periphid)
+#define amba_manf(d)	AMBA_MANF_BITS((d)->periphid)
+#define amba_part(d)	AMBA_PART_BITS((d)->periphid)
 
 #endif
diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h
index ca84ce7..f4ee9ac 100644
--- a/include/linux/amba/mmci.h
+++ b/include/linux/amba/mmci.h
@@ -24,6 +24,7 @@
  * whether a card is present in the MMC slot or not
  * @gpio_wp: read this GPIO pin to see if the card is write protected
  * @gpio_cd: read this GPIO pin to detect card insertion
+ * @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
  */
@@ -35,6 +36,7 @@
 	unsigned int (*status)(struct device *);
 	int	gpio_wp;
 	int	gpio_cd;
+	bool	cd_invert;
 	unsigned long capabilities;
 };
 
diff --git a/include/linux/amba/pl022.h b/include/linux/amba/pl022.h
index abf26cc..4ce98f5 100644
--- a/include/linux/amba/pl022.h
+++ b/include/linux/amba/pl022.h
@@ -228,6 +228,7 @@
 };
 
 
+struct dma_chan;
 /**
  * struct pl022_ssp_master - device.platform_data for SPI controller devices.
  * @num_chipselect: chipselects are used to distinguish individual
@@ -235,11 +236,16 @@
  *     each slave has a chipselect signal, but it's common that not
  *     every chipselect is connected to a slave.
  * @enable_dma: if true enables DMA driven transfers.
+ * @dma_rx_param: parameter to locate an RX DMA channel.
+ * @dma_tx_param: parameter to locate a TX DMA channel.
  */
 struct pl022_ssp_controller {
 	u16 bus_id;
 	u8 num_chipselect;
 	u8 enable_dma:1;
+	bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
+	void *dma_rx_param;
+	void *dma_tx_param;
 };
 
 /**
@@ -270,20 +276,13 @@
  * @dma_config: DMA configuration for SSP controller and peripheral
  */
 struct pl022_config_chip {
-	struct device *dev;
-	enum ssp_loopback lbm;
 	enum ssp_interface iface;
 	enum ssp_hierarchy hierarchy;
 	bool slave_tx_disable;
 	struct ssp_clock_params clk_freq;
-	enum ssp_rx_endian endian_rx;
-	enum ssp_tx_endian endian_tx;
-	enum ssp_data_size data_size;
 	enum ssp_mode com_mode;
 	enum ssp_rx_level_trig rx_lev_trig;
 	enum ssp_tx_level_trig tx_lev_trig;
-	enum ssp_spi_clk_phase clk_phase;
-	enum ssp_spi_clk_pol clk_pol;
 	enum ssp_microwire_ctrl_len ctrl_len;
 	enum ssp_microwire_wait_state wait_state;
 	enum ssp_duplex duplex;
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
index e1b634b..6021588 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -32,7 +32,9 @@
 #define UART01x_RSR		0x04	/* Receive status register (Read). */
 #define UART01x_ECR		0x04	/* Error clear register (Write). */
 #define UART010_LCRH		0x08	/* Line control register, high byte. */
+#define ST_UART011_DMAWM	0x08    /* DMA watermark configure register. */
 #define UART010_LCRM		0x0C	/* Line control register, middle byte. */
+#define ST_UART011_TIMEOUT	0x0C    /* Timeout period register. */
 #define UART010_LCRL		0x10	/* Line control register, low byte. */
 #define UART010_CR		0x14	/* Control register. */
 #define UART01x_FR		0x18	/* Flag register (Read only). */
@@ -51,6 +53,15 @@
 #define UART011_MIS		0x40	/* Masked interrupt status. */
 #define UART011_ICR		0x44	/* Interrupt clear register. */
 #define UART011_DMACR		0x48	/* DMA control register. */
+#define ST_UART011_XFCR		0x50	/* XON/XOFF control register. */
+#define ST_UART011_XON1		0x54	/* XON1 register. */
+#define ST_UART011_XON2		0x58	/* XON2 register. */
+#define ST_UART011_XOFF1	0x5C	/* XON1 register. */
+#define ST_UART011_XOFF2	0x60	/* XON2 register. */
+#define ST_UART011_ITCR		0x80	/* Integration test control register. */
+#define ST_UART011_ITIP		0x84	/* Integration test input register. */
+#define ST_UART011_ABCR		0x100	/* Autobaud control register. */
+#define ST_UART011_ABIMSC	0x15C	/* Autobaud interrupt mask/clear register. */
 
 #define UART011_DR_OE		(1 << 11)
 #define UART011_DR_BE		(1 << 10)
diff --git a/include/linux/ata.h b/include/linux/ata.h
index fe6e681..0c4929f 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -89,6 +89,7 @@
 	ATA_ID_SPG		= 98,
 	ATA_ID_LBA_CAPACITY_2	= 100,
 	ATA_ID_SECTOR_SIZE	= 106,
+	ATA_ID_LOGICAL_SECTOR_SIZE	= 117,	/* and 118 */
 	ATA_ID_LAST_LUN		= 126,
 	ATA_ID_DLF		= 128,
 	ATA_ID_CSFO		= 129,
@@ -640,16 +641,49 @@
 	return (id[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400;
 }
 
-static inline int ata_id_has_large_logical_sectors(const u16 *id)
+static inline u32 ata_id_logical_sector_size(const u16 *id)
 {
-	if ((id[ATA_ID_SECTOR_SIZE] & 0xc000) != 0x4000)
-		return 0;
-	return id[ATA_ID_SECTOR_SIZE] & (1 << 13);
+	/* T13/1699-D Revision 6a, Sep 6, 2008. Page 128.
+	 * IDENTIFY DEVICE data, word 117-118.
+	 * 0xd000 ignores bit 13 (logical:physical > 1)
+	 */
+	if ((id[ATA_ID_SECTOR_SIZE] & 0xd000) == 0x5000)
+		return (((id[ATA_ID_LOGICAL_SECTOR_SIZE+1] << 16)
+			 + id[ATA_ID_LOGICAL_SECTOR_SIZE]) * sizeof(u16)) ;
+	return ATA_SECT_SIZE;
 }
 
-static inline u16 ata_id_logical_per_physical_sectors(const u16 *id)
+static inline u8 ata_id_log2_per_physical_sector(const u16 *id)
 {
-	return 1 << (id[ATA_ID_SECTOR_SIZE] & 0xf);
+	/* T13/1699-D Revision 6a, Sep 6, 2008. Page 128.
+	 * IDENTIFY DEVICE data, word 106.
+	 * 0xe000 ignores bit 12 (logical sector > 512 bytes)
+	 */
+	if ((id[ATA_ID_SECTOR_SIZE] & 0xe000) == 0x6000)
+		return (id[ATA_ID_SECTOR_SIZE] & 0xf);
+	return 0;
+}
+
+/* Offset of logical sectors relative to physical sectors.
+ *
+ * If device has more than one logical sector per physical sector
+ * (aka 512 byte emulation), vendors might offset the "sector 0" address
+ * so sector 63 is "naturally aligned" - e.g. FAT partition table.
+ * This avoids Read/Mod/Write penalties when using FAT partition table
+ * and updating "well aligned" (FS perspective) physical sectors on every
+ * transaction.
+ */
+static inline u16 ata_id_logical_sector_offset(const u16 *id,
+	 u8 log2_per_phys)
+{
+	u16 word_209 = id[209];
+
+	if ((log2_per_phys > 1) && (word_209 & 0xc000) == 0x4000) {
+		u16 first = word_209 & 0x3fff;
+		if (first > 0)
+			return (1 << log2_per_phys) - first;
+	}
+	return 0;
 }
 
 static inline int ata_id_has_lba48(const u16 *id)
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index f6481da..a8e4e83 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -449,7 +449,7 @@
 
 static inline int atm_guess_pdu2truesize(int size)
 {
-	return (SKB_DATA_ALIGN(size) + sizeof(struct skb_shared_info));
+	return SKB_DATA_ALIGN(size) + sizeof(struct skb_shared_info);
 }
 
 
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 5274103..ba67999 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -346,8 +346,15 @@
 }
 
 #else
-#define bvec_kmap_irq(bvec, flags)	(page_address((bvec)->bv_page) + (bvec)->bv_offset)
-#define bvec_kunmap_irq(buf, flags)	do { *(flags) = 0; } while (0)
+static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
+{
+	return page_address(bvec->bv_page) + bvec->bv_offset;
+}
+
+static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
+{
+	*flags = 0;
+}
 #endif
 
 static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
@@ -496,6 +503,10 @@
 #define bip_for_each_vec(bvl, bip, i)					\
 	__bip_for_each_vec(bvl, bip, i, (bip)->bip_idx)
 
+#define bio_for_each_integrity_vec(_bvl, _bio, _iter)			\
+	for_each_bio(_bio)						\
+		bip_for_each_vec(_bvl, _bio->bi_integrity, _iter)
+
 #define bio_integrity(bio) (bio->bi_integrity != NULL)
 
 extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *);
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index fc68053..827cc95 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -136,28 +136,6 @@
 }
 
 #ifdef __KERNEL__
-#ifdef CONFIG_GENERIC_FIND_FIRST_BIT
-
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit number of the first set bit.
- */
-extern unsigned long find_first_bit(const unsigned long *addr,
-				    unsigned long size);
-
-/**
- * find_first_zero_bit - find the first cleared bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit number of the first cleared bit.
- */
-extern unsigned long find_first_zero_bit(const unsigned long *addr,
-					 unsigned long size);
-#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
 
 #ifdef CONFIG_GENERIC_FIND_LAST_BIT
 /**
@@ -171,28 +149,5 @@
 				   unsigned long size);
 #endif /* CONFIG_GENERIC_FIND_LAST_BIT */
 
-#ifdef CONFIG_GENERIC_FIND_NEXT_BIT
-
-/**
- * find_next_bit - find the next set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The bitmap size in bits
- */
-extern unsigned long find_next_bit(const unsigned long *addr,
-				   unsigned long size, unsigned long offset);
-
-/**
- * find_next_zero_bit - find the next cleared bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The bitmap size in bits
- */
-
-extern unsigned long find_next_zero_bit(const unsigned long *addr,
-					unsigned long size,
-					unsigned long offset);
-
-#endif /* CONFIG_GENERIC_FIND_NEXT_BIT */
 #endif /* __KERNEL__ */
 #endif
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index ca83a97..0437ab6 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -97,6 +97,7 @@
 #define BIO_NULL_MAPPED 9	/* contains invalid user pages */
 #define BIO_FS_INTEGRITY 10	/* fs owns integrity data, not block layer */
 #define BIO_QUIET	11	/* Make BIO Quiet */
+#define BIO_MAPPED_INTEGRITY 12/* integrity metadata has been remapped */
 #define bio_flagged(bio, flag)	((bio)->bi_flags & (1 << (flag)))
 
 /*
@@ -130,6 +131,8 @@
 	/* bio only flags */
 	__REQ_UNPLUG,		/* unplug the immediately after submission */
 	__REQ_RAHEAD,		/* read ahead, can fail anytime */
+	__REQ_THROTTLED,	/* This bio has already been subjected to
+				 * throttling rules. Don't do it again. */
 
 	/* request only flags */
 	__REQ_SORTED,		/* elevator knows about this request */
@@ -143,10 +146,8 @@
 	__REQ_FAILED,		/* set if the request failed */
 	__REQ_QUIET,		/* don't worry about errors */
 	__REQ_PREEMPT,		/* set for "ide_preempt" requests */
-	__REQ_ORDERED_COLOR,	/* is before or after barrier */
 	__REQ_ALLOCED,		/* request came from our alloc pool */
 	__REQ_COPY_USER,	/* contains copies of user pages */
-	__REQ_INTEGRITY,	/* integrity metadata has been remapped */
 	__REQ_FLUSH,		/* request for cache flush */
 	__REQ_IO_STAT,		/* account I/O stat */
 	__REQ_MIXED_MERGE,	/* merge of different types, fail separately */
@@ -168,10 +169,12 @@
 	(REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)
 #define REQ_COMMON_MASK \
 	(REQ_WRITE | REQ_FAILFAST_MASK | REQ_HARDBARRIER | REQ_SYNC | \
-	 REQ_META| REQ_DISCARD | REQ_NOIDLE)
+	 REQ_META | REQ_DISCARD | REQ_NOIDLE | REQ_FLUSH | REQ_FUA)
+#define REQ_CLONE_MASK		REQ_COMMON_MASK
 
 #define REQ_UNPLUG		(1 << __REQ_UNPLUG)
 #define REQ_RAHEAD		(1 << __REQ_RAHEAD)
+#define REQ_THROTTLED		(1 << __REQ_THROTTLED)
 
 #define REQ_SORTED		(1 << __REQ_SORTED)
 #define REQ_SOFTBARRIER		(1 << __REQ_SOFTBARRIER)
@@ -184,10 +187,8 @@
 #define REQ_FAILED		(1 << __REQ_FAILED)
 #define REQ_QUIET		(1 << __REQ_QUIET)
 #define REQ_PREEMPT		(1 << __REQ_PREEMPT)
-#define REQ_ORDERED_COLOR	(1 << __REQ_ORDERED_COLOR)
 #define REQ_ALLOCED		(1 << __REQ_ALLOCED)
 #define REQ_COPY_USER		(1 << __REQ_COPY_USER)
-#define REQ_INTEGRITY		(1 << __REQ_INTEGRITY)
 #define REQ_FLUSH		(1 << __REQ_FLUSH)
 #define REQ_IO_STAT		(1 << __REQ_IO_STAT)
 #define REQ_MIXED_MERGE		(1 << __REQ_MIXED_MERGE)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 2c54906..009b80e 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -115,6 +115,7 @@
 	void *elevator_private3;
 
 	struct gendisk *rq_disk;
+	struct hd_struct *part;
 	unsigned long start_time;
 #ifdef CONFIG_BLK_CGROUP
 	unsigned long long start_time_ns;
@@ -124,6 +125,9 @@
 	 * physical address coalescing is performed.
 	 */
 	unsigned short nr_phys_segments;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+	unsigned short nr_integrity_segments;
+#endif
 
 	unsigned short ioprio;
 
@@ -243,6 +247,7 @@
 
 	unsigned short		logical_block_size;
 	unsigned short		max_segments;
+	unsigned short		max_integrity_segments;
 
 	unsigned char		misaligned;
 	unsigned char		discard_misaligned;
@@ -355,18 +360,25 @@
 	struct blk_trace	*blk_trace;
 #endif
 	/*
-	 * reserved for flush operations
+	 * for flush operations
 	 */
-	unsigned int		ordered, next_ordered, ordseq;
-	int			orderr, ordcolor;
-	struct request		pre_flush_rq, bar_rq, post_flush_rq;
-	struct request		*orig_bar_rq;
+	unsigned int		flush_flags;
+	unsigned int		flush_seq;
+	int			flush_err;
+	struct request		flush_rq;
+	struct request		*orig_flush_rq;
+	struct list_head	pending_flushes;
 
 	struct mutex		sysfs_lock;
 
 #if defined(CONFIG_BLK_DEV_BSG)
 	struct bsg_class_device bsg_dev;
 #endif
+
+#ifdef CONFIG_BLK_DEV_THROTTLING
+	/* Throttle data */
+	struct throtl_data *td;
+#endif
 };
 
 #define QUEUE_FLAG_CLUSTER	0	/* cluster several segments into 1 */
@@ -462,56 +474,6 @@
 	__clear_bit(flag, &q->queue_flags);
 }
 
-enum {
-	/*
-	 * Hardbarrier is supported with one of the following methods.
-	 *
-	 * NONE		: hardbarrier unsupported
-	 * DRAIN	: ordering by draining is enough
-	 * DRAIN_FLUSH	: ordering by draining w/ pre and post flushes
-	 * DRAIN_FUA	: ordering by draining w/ pre flush and FUA write
-	 * TAG		: ordering by tag is enough
-	 * TAG_FLUSH	: ordering by tag w/ pre and post flushes
-	 * TAG_FUA	: ordering by tag w/ pre flush and FUA write
-	 */
-	QUEUE_ORDERED_BY_DRAIN		= 0x01,
-	QUEUE_ORDERED_BY_TAG		= 0x02,
-	QUEUE_ORDERED_DO_PREFLUSH	= 0x10,
-	QUEUE_ORDERED_DO_BAR		= 0x20,
-	QUEUE_ORDERED_DO_POSTFLUSH	= 0x40,
-	QUEUE_ORDERED_DO_FUA		= 0x80,
-
-	QUEUE_ORDERED_NONE		= 0x00,
-
-	QUEUE_ORDERED_DRAIN		= QUEUE_ORDERED_BY_DRAIN |
-					  QUEUE_ORDERED_DO_BAR,
-	QUEUE_ORDERED_DRAIN_FLUSH	= QUEUE_ORDERED_DRAIN |
-					  QUEUE_ORDERED_DO_PREFLUSH |
-					  QUEUE_ORDERED_DO_POSTFLUSH,
-	QUEUE_ORDERED_DRAIN_FUA		= QUEUE_ORDERED_DRAIN |
-					  QUEUE_ORDERED_DO_PREFLUSH |
-					  QUEUE_ORDERED_DO_FUA,
-
-	QUEUE_ORDERED_TAG		= QUEUE_ORDERED_BY_TAG |
-					  QUEUE_ORDERED_DO_BAR,
-	QUEUE_ORDERED_TAG_FLUSH		= QUEUE_ORDERED_TAG |
-					  QUEUE_ORDERED_DO_PREFLUSH |
-					  QUEUE_ORDERED_DO_POSTFLUSH,
-	QUEUE_ORDERED_TAG_FUA		= QUEUE_ORDERED_TAG |
-					  QUEUE_ORDERED_DO_PREFLUSH |
-					  QUEUE_ORDERED_DO_FUA,
-
-	/*
-	 * Ordered operation sequence
-	 */
-	QUEUE_ORDSEQ_STARTED	= 0x01,	/* flushing in progress */
-	QUEUE_ORDSEQ_DRAIN	= 0x02,	/* waiting for the queue to be drained */
-	QUEUE_ORDSEQ_PREFLUSH	= 0x04,	/* pre-flushing in progress */
-	QUEUE_ORDSEQ_BAR	= 0x08,	/* original barrier req in progress */
-	QUEUE_ORDSEQ_POSTFLUSH	= 0x10,	/* post-flushing in progress */
-	QUEUE_ORDSEQ_DONE	= 0x20,
-};
-
 #define blk_queue_plugged(q)	test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
 #define blk_queue_tagged(q)	test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
 #define blk_queue_stopped(q)	test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
@@ -521,7 +483,6 @@
 #define blk_queue_nonrot(q)	test_bit(QUEUE_FLAG_NONROT, &(q)->queue_flags)
 #define blk_queue_io_stat(q)	test_bit(QUEUE_FLAG_IO_STAT, &(q)->queue_flags)
 #define blk_queue_add_random(q)	test_bit(QUEUE_FLAG_ADD_RANDOM, &(q)->queue_flags)
-#define blk_queue_flushing(q)	((q)->ordseq)
 #define blk_queue_stackable(q)	\
 	test_bit(QUEUE_FLAG_STACKABLE, &(q)->queue_flags)
 #define blk_queue_discard(q)	test_bit(QUEUE_FLAG_DISCARD, &(q)->queue_flags)
@@ -592,7 +553,8 @@
  * it already be started by driver.
  */
 #define RQ_NOMERGE_FLAGS	\
-	(REQ_NOMERGE | REQ_STARTED | REQ_HARDBARRIER | REQ_SOFTBARRIER)
+	(REQ_NOMERGE | REQ_STARTED | REQ_HARDBARRIER | REQ_SOFTBARRIER | \
+	 REQ_FLUSH | REQ_FUA)
 #define rq_mergeable(rq)	\
 	(!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && \
 	 (((rq)->cmd_flags & REQ_DISCARD) || \
@@ -851,7 +813,7 @@
 extern void blk_queue_max_discard_sectors(struct request_queue *q,
 		unsigned int max_discard_sectors);
 extern void blk_queue_logical_block_size(struct request_queue *, unsigned short);
-extern void blk_queue_physical_block_size(struct request_queue *, unsigned short);
+extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
 extern void blk_queue_alignment_offset(struct request_queue *q,
 				       unsigned int alignment);
 extern void blk_limits_io_min(struct queue_limits *limits, unsigned int min);
@@ -881,12 +843,8 @@
 extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *);
 extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *);
 extern void blk_queue_rq_timeout(struct request_queue *, unsigned int);
+extern void blk_queue_flush(struct request_queue *q, unsigned int flush);
 extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
-extern int blk_queue_ordered(struct request_queue *, unsigned);
-extern bool blk_do_ordered(struct request_queue *, struct request **);
-extern unsigned blk_ordered_cur_seq(struct request_queue *);
-extern unsigned blk_ordered_req_seq(struct request *);
-extern bool blk_ordered_complete_seq(struct request_queue *, unsigned, int);
 
 extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *);
 extern void blk_dump_rq_flags(struct request *, char *);
@@ -919,27 +877,20 @@
 		return NULL;
 	return bqt->tag_index[tag];
 }
-enum{
-	BLKDEV_WAIT,	/* wait for completion */
-	BLKDEV_BARRIER,	/* issue request with barrier */
-	BLKDEV_SECURE,	/* secure discard */
-};
-#define BLKDEV_IFL_WAIT		(1 << BLKDEV_WAIT)
-#define BLKDEV_IFL_BARRIER	(1 << BLKDEV_BARRIER)
-#define BLKDEV_IFL_SECURE	(1 << BLKDEV_SECURE)
-extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *,
-			unsigned long);
+
+#define BLKDEV_DISCARD_SECURE  0x01    /* secure discard */
+
+extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *);
 extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 		sector_t nr_sects, gfp_t gfp_mask, unsigned long flags);
 extern int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
-			sector_t nr_sects, gfp_t gfp_mask, unsigned long flags);
-static inline int sb_issue_discard(struct super_block *sb,
-				   sector_t block, sector_t nr_blocks)
+			sector_t nr_sects, gfp_t gfp_mask);
+static inline int sb_issue_discard(struct super_block *sb, sector_t block,
+		sector_t nr_blocks, gfp_t gfp_mask, unsigned long flags)
 {
-	block <<= (sb->s_blocksize_bits - 9);
-	nr_blocks <<= (sb->s_blocksize_bits - 9);
-	return blkdev_issue_discard(sb->s_bdev, block, nr_blocks, GFP_NOFS,
-				   BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+	return blkdev_issue_discard(sb->s_bdev, block << (sb->s_blocksize_bits - 9),
+				    nr_blocks << (sb->s_blocksize_bits - 9),
+				    gfp_mask, flags);
 }
 
 extern int blk_verify_command(unsigned char *cmd, fmode_t has_write_perm);
@@ -1004,7 +955,7 @@
 	return q->limits.physical_block_size;
 }
 
-static inline int bdev_physical_block_size(struct block_device *bdev)
+static inline unsigned int bdev_physical_block_size(struct block_device *bdev)
 {
 	return queue_physical_block_size(bdev_get_queue(bdev));
 }
@@ -1093,11 +1044,11 @@
 	return q ? q->dma_alignment : 511;
 }
 
-static inline int blk_rq_aligned(struct request_queue *q, void *addr,
+static inline int blk_rq_aligned(struct request_queue *q, unsigned long addr,
 				 unsigned int len)
 {
 	unsigned int alignment = queue_dma_alignment(q) | q->dma_pad_mask;
-	return !((unsigned long)addr & alignment) && !(len & alignment);
+	return !(addr & alignment) && !(len & alignment);
 }
 
 /* assumes size > 256 */
@@ -1127,6 +1078,7 @@
 
 struct work_struct;
 int kblockd_schedule_work(struct request_queue *q, struct work_struct *work);
+int kblockd_schedule_delayed_work(struct request_queue *q, struct delayed_work *dwork, unsigned long delay);
 
 #ifdef CONFIG_BLK_CGROUP
 /*
@@ -1170,6 +1122,24 @@
 }
 #endif
 
+#ifdef CONFIG_BLK_DEV_THROTTLING
+extern int blk_throtl_init(struct request_queue *q);
+extern void blk_throtl_exit(struct request_queue *q);
+extern int blk_throtl_bio(struct request_queue *q, struct bio **bio);
+extern void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay);
+extern void throtl_shutdown_timer_wq(struct request_queue *q);
+#else /* CONFIG_BLK_DEV_THROTTLING */
+static inline int blk_throtl_bio(struct request_queue *q, struct bio **bio)
+{
+	return 0;
+}
+
+static inline int blk_throtl_init(struct request_queue *q) { return 0; }
+static inline int blk_throtl_exit(struct request_queue *q) { return 0; }
+static inline void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay) {}
+static inline void throtl_shutdown_timer_wq(struct request_queue *q) {}
+#endif /* CONFIG_BLK_DEV_THROTTLING */
+
 #define MODULE_ALIAS_BLOCKDEV(major,minor) \
 	MODULE_ALIAS("block-major-" __stringify(major) "-" __stringify(minor))
 #define MODULE_ALIAS_BLOCKDEV_MAJOR(major) \
@@ -1213,8 +1183,13 @@
 extern int blk_integrity_register(struct gendisk *, struct blk_integrity *);
 extern void blk_integrity_unregister(struct gendisk *);
 extern int blk_integrity_compare(struct gendisk *, struct gendisk *);
-extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *);
-extern int blk_rq_count_integrity_sg(struct request *);
+extern int blk_rq_map_integrity_sg(struct request_queue *, struct bio *,
+				   struct scatterlist *);
+extern int blk_rq_count_integrity_sg(struct request_queue *, struct bio *);
+extern int blk_integrity_merge_rq(struct request_queue *, struct request *,
+				  struct request *);
+extern int blk_integrity_merge_bio(struct request_queue *, struct request *,
+				   struct bio *);
 
 static inline
 struct blk_integrity *bdev_get_integrity(struct block_device *bdev)
@@ -1235,16 +1210,32 @@
 	return bio_integrity(rq->bio);
 }
 
+static inline void blk_queue_max_integrity_segments(struct request_queue *q,
+						    unsigned int segs)
+{
+	q->limits.max_integrity_segments = segs;
+}
+
+static inline unsigned short
+queue_max_integrity_segments(struct request_queue *q)
+{
+	return q->limits.max_integrity_segments;
+}
+
 #else /* CONFIG_BLK_DEV_INTEGRITY */
 
 #define blk_integrity_rq(rq)			(0)
-#define blk_rq_count_integrity_sg(a)		(0)
-#define blk_rq_map_integrity_sg(a, b)		(0)
+#define blk_rq_count_integrity_sg(a, b)		(0)
+#define blk_rq_map_integrity_sg(a, b, c)	(0)
 #define bdev_get_integrity(a)			(0)
 #define blk_get_integrity(a)			(0)
 #define blk_integrity_compare(a, b)		(0)
 #define blk_integrity_register(a, b)		(0)
 #define blk_integrity_unregister(a)		do { } while (0);
+#define blk_queue_max_integrity_segments(a, b)	do { } while (0);
+#define queue_max_integrity_segments(a)		(0)
+#define blk_integrity_merge_rq(a, b, c)		(0)
+#define blk_integrity_merge_bio(a, b, c)	(0)
 
 #endif /* CONFIG_BLK_DEV_INTEGRITY */
 
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index ec94c12..dd1b25b 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -32,7 +32,6 @@
 	BH_Delay,	/* Buffer is not yet allocated on disk */
 	BH_Boundary,	/* Block is followed by a discontiguity */
 	BH_Write_EIO,	/* I/O error on write */
-	BH_Eopnotsupp,	/* operation not supported (barrier) */
 	BH_Unwritten,	/* Buffer is allocated on disk but not written */
 	BH_Quiet,	/* Buffer Error Prinks to be quiet */
 
@@ -124,7 +123,6 @@
 BUFFER_FNS(Delay, delay)
 BUFFER_FNS(Boundary, boundary)
 BUFFER_FNS(Write_EIO, write_io_error)
-BUFFER_FNS(Eopnotsupp, eopnotsupp)
 BUFFER_FNS(Unwritten, unwritten)
 
 #define bh_offset(bh)		((unsigned long)(bh)->b_data & ~PAGE_MASK)
diff --git a/include/linux/can/platform/mcp251x.h b/include/linux/can/platform/mcp251x.h
index dba2826..8e20540 100644
--- a/include/linux/can/platform/mcp251x.h
+++ b/include/linux/can/platform/mcp251x.h
@@ -12,7 +12,6 @@
 /**
  * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data
  * @oscillator_frequency:       - oscillator frequency in Hz
- * @model:                      - actual type of chip
  * @board_specific_setup:       - called before probing the chip (power,reset)
  * @transceiver_enable:         - called to power on/off the transceiver
  * @power_enable:               - called to power on/off the mcp *and* the
@@ -25,9 +24,6 @@
 
 struct mcp251x_platform_data {
 	unsigned long oscillator_frequency;
-	int model;
-#define CAN_MCP251X_MCP2510 0x2510
-#define CAN_MCP251X_MCP2515 0x2515
 	int (*board_specific_setup)(struct spi_device *spi);
 	int (*transceiver_enable)(int enable);
 	int (*power_enable) (int enable);
diff --git a/include/linux/ceph/auth.h b/include/linux/ceph/auth.h
new file mode 100644
index 0000000..7fff521
--- /dev/null
+++ b/include/linux/ceph/auth.h
@@ -0,0 +1,92 @@
+#ifndef _FS_CEPH_AUTH_H
+#define _FS_CEPH_AUTH_H
+
+#include <linux/ceph/types.h>
+#include <linux/ceph/buffer.h>
+
+/*
+ * Abstract interface for communicating with the authenticate module.
+ * There is some handshake that takes place between us and the monitor
+ * to acquire the necessary keys.  These are used to generate an
+ * 'authorizer' that we use when connecting to a service (mds, osd).
+ */
+
+struct ceph_auth_client;
+struct ceph_authorizer;
+
+struct ceph_auth_client_ops {
+	const char *name;
+
+	/*
+	 * true if we are authenticated and can connect to
+	 * services.
+	 */
+	int (*is_authenticated)(struct ceph_auth_client *ac);
+
+	/*
+	 * true if we should (re)authenticate, e.g., when our tickets
+	 * are getting old and crusty.
+	 */
+	int (*should_authenticate)(struct ceph_auth_client *ac);
+
+	/*
+	 * build requests and process replies during monitor
+	 * handshake.  if handle_reply returns -EAGAIN, we build
+	 * another request.
+	 */
+	int (*build_request)(struct ceph_auth_client *ac, void *buf, void *end);
+	int (*handle_reply)(struct ceph_auth_client *ac, int result,
+			    void *buf, void *end);
+
+	/*
+	 * Create authorizer for connecting to a service, and verify
+	 * the response to authenticate the service.
+	 */
+	int (*create_authorizer)(struct ceph_auth_client *ac, int peer_type,
+				 struct ceph_authorizer **a,
+				 void **buf, size_t *len,
+				 void **reply_buf, size_t *reply_len);
+	int (*verify_authorizer_reply)(struct ceph_auth_client *ac,
+				       struct ceph_authorizer *a, size_t len);
+	void (*destroy_authorizer)(struct ceph_auth_client *ac,
+				   struct ceph_authorizer *a);
+	void (*invalidate_authorizer)(struct ceph_auth_client *ac,
+				      int peer_type);
+
+	/* reset when we (re)connect to a monitor */
+	void (*reset)(struct ceph_auth_client *ac);
+
+	void (*destroy)(struct ceph_auth_client *ac);
+};
+
+struct ceph_auth_client {
+	u32 protocol;           /* CEPH_AUTH_* */
+	void *private;          /* for use by protocol implementation */
+	const struct ceph_auth_client_ops *ops;  /* null iff protocol==0 */
+
+	bool negotiating;       /* true if negotiating protocol */
+	const char *name;       /* entity name */
+	u64 global_id;          /* our unique id in system */
+	const char *secret;     /* our secret key */
+	unsigned want_keys;     /* which services we want */
+};
+
+extern struct ceph_auth_client *ceph_auth_init(const char *name,
+					       const char *secret);
+extern void ceph_auth_destroy(struct ceph_auth_client *ac);
+
+extern void ceph_auth_reset(struct ceph_auth_client *ac);
+
+extern int ceph_auth_build_hello(struct ceph_auth_client *ac,
+				 void *buf, size_t len);
+extern int ceph_handle_auth_reply(struct ceph_auth_client *ac,
+				  void *buf, size_t len,
+				  void *reply_buf, size_t reply_len);
+extern int ceph_entity_name_encode(const char *name, void **p, void *end);
+
+extern int ceph_build_auth(struct ceph_auth_client *ac,
+		    void *msg_buf, size_t msg_len);
+
+extern int ceph_auth_is_authenticated(struct ceph_auth_client *ac);
+
+#endif
diff --git a/fs/ceph/buffer.h b/include/linux/ceph/buffer.h
similarity index 100%
rename from fs/ceph/buffer.h
rename to include/linux/ceph/buffer.h
diff --git a/include/linux/ceph/ceph_debug.h b/include/linux/ceph/ceph_debug.h
new file mode 100644
index 0000000..aa2e191
--- /dev/null
+++ b/include/linux/ceph/ceph_debug.h
@@ -0,0 +1,38 @@
+#ifndef _FS_CEPH_DEBUG_H
+#define _FS_CEPH_DEBUG_H
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#ifdef CONFIG_CEPH_LIB_PRETTYDEBUG
+
+/*
+ * wrap pr_debug to include a filename:lineno prefix on each line.
+ * this incurs some overhead (kernel size and execution time) due to
+ * the extra function call at each call site.
+ */
+
+# if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
+extern const char *ceph_file_part(const char *s, int len);
+#  define dout(fmt, ...)						\
+	pr_debug("%.*s %12.12s:%-4d : " fmt,				\
+		 8 - (int)sizeof(KBUILD_MODNAME), "    ",		\
+		 ceph_file_part(__FILE__, sizeof(__FILE__)),		\
+		 __LINE__, ##__VA_ARGS__)
+# else
+/* faux printk call just to see any compiler warnings. */
+#  define dout(fmt, ...)	do {				\
+		if (0)						\
+			printk(KERN_DEBUG fmt, ##__VA_ARGS__);	\
+	} while (0)
+# endif
+
+#else
+
+/*
+ * or, just wrap pr_debug
+ */
+# define dout(fmt, ...)	pr_debug(" " fmt, ##__VA_ARGS__)
+
+#endif
+
+#endif
diff --git a/fs/ceph/ceph_frag.h b/include/linux/ceph/ceph_frag.h
similarity index 100%
rename from fs/ceph/ceph_frag.h
rename to include/linux/ceph/ceph_frag.h
diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h
new file mode 100644
index 0000000..c3c74ae
--- /dev/null
+++ b/include/linux/ceph/ceph_fs.h
@@ -0,0 +1,729 @@
+/*
+ * ceph_fs.h - Ceph constants and data types to share between kernel and
+ * user space.
+ *
+ * Most types in this file are defined as little-endian, and are
+ * primarily intended to describe data structures that pass over the
+ * wire or that are stored on disk.
+ *
+ * LGPL2
+ */
+
+#ifndef CEPH_FS_H
+#define CEPH_FS_H
+
+#include "msgr.h"
+#include "rados.h"
+
+/*
+ * subprotocol versions.  when specific messages types or high-level
+ * protocols change, bump the affected components.  we keep rev
+ * internal cluster protocols separately from the public,
+ * client-facing protocol.
+ */
+#define CEPH_OSD_PROTOCOL     8 /* cluster internal */
+#define CEPH_MDS_PROTOCOL    12 /* cluster internal */
+#define CEPH_MON_PROTOCOL     5 /* cluster internal */
+#define CEPH_OSDC_PROTOCOL   24 /* server/client */
+#define CEPH_MDSC_PROTOCOL   32 /* server/client */
+#define CEPH_MONC_PROTOCOL   15 /* server/client */
+
+
+#define CEPH_INO_ROOT  1
+#define CEPH_INO_CEPH  2        /* hidden .ceph dir */
+
+/* arbitrary limit on max # of monitors (cluster of 3 is typical) */
+#define CEPH_MAX_MON   31
+
+
+/*
+ * feature bits
+ */
+#define CEPH_FEATURE_UID            (1<<0)
+#define CEPH_FEATURE_NOSRCADDR      (1<<1)
+#define CEPH_FEATURE_MONCLOCKCHECK  (1<<2)
+#define CEPH_FEATURE_FLOCK          (1<<3)
+
+
+/*
+ * ceph_file_layout - describe data layout for a file/inode
+ */
+struct ceph_file_layout {
+	/* file -> object mapping */
+	__le32 fl_stripe_unit;     /* stripe unit, in bytes.  must be multiple
+				      of page size. */
+	__le32 fl_stripe_count;    /* over this many objects */
+	__le32 fl_object_size;     /* until objects are this big, then move to
+				      new objects */
+	__le32 fl_cas_hash;        /* 0 = none; 1 = sha256 */
+
+	/* pg -> disk layout */
+	__le32 fl_object_stripe_unit;  /* for per-object parity, if any */
+
+	/* object -> pg layout */
+	__le32 fl_pg_preferred; /* preferred primary for pg (-1 for none) */
+	__le32 fl_pg_pool;      /* namespace, crush ruleset, rep level */
+} __attribute__ ((packed));
+
+#define CEPH_MIN_STRIPE_UNIT 65536
+
+int ceph_file_layout_is_valid(const struct ceph_file_layout *layout);
+
+
+/* crypto algorithms */
+#define CEPH_CRYPTO_NONE 0x0
+#define CEPH_CRYPTO_AES  0x1
+
+#define CEPH_AES_IV "cephsageyudagreg"
+
+/* security/authentication protocols */
+#define CEPH_AUTH_UNKNOWN	0x0
+#define CEPH_AUTH_NONE	 	0x1
+#define CEPH_AUTH_CEPHX	 	0x2
+
+#define CEPH_AUTH_UID_DEFAULT ((__u64) -1)
+
+
+/*********************************************
+ * message layer
+ */
+
+/*
+ * message types
+ */
+
+/* misc */
+#define CEPH_MSG_SHUTDOWN               1
+#define CEPH_MSG_PING                   2
+
+/* client <-> monitor */
+#define CEPH_MSG_MON_MAP                4
+#define CEPH_MSG_MON_GET_MAP            5
+#define CEPH_MSG_STATFS                 13
+#define CEPH_MSG_STATFS_REPLY           14
+#define CEPH_MSG_MON_SUBSCRIBE          15
+#define CEPH_MSG_MON_SUBSCRIBE_ACK      16
+#define CEPH_MSG_AUTH			17
+#define CEPH_MSG_AUTH_REPLY		18
+
+/* client <-> mds */
+#define CEPH_MSG_MDS_MAP                21
+
+#define CEPH_MSG_CLIENT_SESSION         22
+#define CEPH_MSG_CLIENT_RECONNECT       23
+
+#define CEPH_MSG_CLIENT_REQUEST         24
+#define CEPH_MSG_CLIENT_REQUEST_FORWARD 25
+#define CEPH_MSG_CLIENT_REPLY           26
+#define CEPH_MSG_CLIENT_CAPS            0x310
+#define CEPH_MSG_CLIENT_LEASE           0x311
+#define CEPH_MSG_CLIENT_SNAP            0x312
+#define CEPH_MSG_CLIENT_CAPRELEASE      0x313
+
+/* pool ops */
+#define CEPH_MSG_POOLOP_REPLY           48
+#define CEPH_MSG_POOLOP                 49
+
+
+/* osd */
+#define CEPH_MSG_OSD_MAP          41
+#define CEPH_MSG_OSD_OP           42
+#define CEPH_MSG_OSD_OPREPLY      43
+
+/* pool operations */
+enum {
+  POOL_OP_CREATE			= 0x01,
+  POOL_OP_DELETE			= 0x02,
+  POOL_OP_AUID_CHANGE			= 0x03,
+  POOL_OP_CREATE_SNAP			= 0x11,
+  POOL_OP_DELETE_SNAP			= 0x12,
+  POOL_OP_CREATE_UNMANAGED_SNAP		= 0x21,
+  POOL_OP_DELETE_UNMANAGED_SNAP		= 0x22,
+};
+
+struct ceph_mon_request_header {
+	__le64 have_version;
+	__le16 session_mon;
+	__le64 session_mon_tid;
+} __attribute__ ((packed));
+
+struct ceph_mon_statfs {
+	struct ceph_mon_request_header monhdr;
+	struct ceph_fsid fsid;
+} __attribute__ ((packed));
+
+struct ceph_statfs {
+	__le64 kb, kb_used, kb_avail;
+	__le64 num_objects;
+} __attribute__ ((packed));
+
+struct ceph_mon_statfs_reply {
+	struct ceph_fsid fsid;
+	__le64 version;
+	struct ceph_statfs st;
+} __attribute__ ((packed));
+
+const char *ceph_pool_op_name(int op);
+
+struct ceph_mon_poolop {
+	struct ceph_mon_request_header monhdr;
+	struct ceph_fsid fsid;
+	__le32 pool;
+	__le32 op;
+	__le64 auid;
+	__le64 snapid;
+	__le32 name_len;
+} __attribute__ ((packed));
+
+struct ceph_mon_poolop_reply {
+	struct ceph_mon_request_header monhdr;
+	struct ceph_fsid fsid;
+	__le32 reply_code;
+	__le32 epoch;
+	char has_data;
+	char data[0];
+} __attribute__ ((packed));
+
+struct ceph_mon_unmanaged_snap {
+	__le64 snapid;
+} __attribute__ ((packed));
+
+struct ceph_osd_getmap {
+	struct ceph_mon_request_header monhdr;
+	struct ceph_fsid fsid;
+	__le32 start;
+} __attribute__ ((packed));
+
+struct ceph_mds_getmap {
+	struct ceph_mon_request_header monhdr;
+	struct ceph_fsid fsid;
+} __attribute__ ((packed));
+
+struct ceph_client_mount {
+	struct ceph_mon_request_header monhdr;
+} __attribute__ ((packed));
+
+struct ceph_mon_subscribe_item {
+	__le64 have_version;	__le64 have;
+	__u8 onetime;
+} __attribute__ ((packed));
+
+struct ceph_mon_subscribe_ack {
+	__le32 duration;         /* seconds */
+	struct ceph_fsid fsid;
+} __attribute__ ((packed));
+
+/*
+ * mds states
+ *   > 0 -> in
+ *  <= 0 -> out
+ */
+#define CEPH_MDS_STATE_DNE          0  /* down, does not exist. */
+#define CEPH_MDS_STATE_STOPPED     -1  /* down, once existed, but no subtrees.
+					  empty log. */
+#define CEPH_MDS_STATE_BOOT        -4  /* up, boot announcement. */
+#define CEPH_MDS_STATE_STANDBY     -5  /* up, idle.  waiting for assignment. */
+#define CEPH_MDS_STATE_CREATING    -6  /* up, creating MDS instance. */
+#define CEPH_MDS_STATE_STARTING    -7  /* up, starting previously stopped mds */
+#define CEPH_MDS_STATE_STANDBY_REPLAY -8 /* up, tailing active node's journal */
+
+#define CEPH_MDS_STATE_REPLAY       8  /* up, replaying journal. */
+#define CEPH_MDS_STATE_RESOLVE      9  /* up, disambiguating distributed
+					  operations (import, rename, etc.) */
+#define CEPH_MDS_STATE_RECONNECT    10 /* up, reconnect to clients */
+#define CEPH_MDS_STATE_REJOIN       11 /* up, rejoining distributed cache */
+#define CEPH_MDS_STATE_CLIENTREPLAY 12 /* up, replaying client operations */
+#define CEPH_MDS_STATE_ACTIVE       13 /* up, active */
+#define CEPH_MDS_STATE_STOPPING     14 /* up, but exporting metadata */
+
+extern const char *ceph_mds_state_name(int s);
+
+
+/*
+ * metadata lock types.
+ *  - these are bitmasks.. we can compose them
+ *  - they also define the lock ordering by the MDS
+ *  - a few of these are internal to the mds
+ */
+#define CEPH_LOCK_DVERSION    1
+#define CEPH_LOCK_DN          2
+#define CEPH_LOCK_ISNAP       16
+#define CEPH_LOCK_IVERSION    32    /* mds internal */
+#define CEPH_LOCK_IFILE       64
+#define CEPH_LOCK_IAUTH       128
+#define CEPH_LOCK_ILINK       256
+#define CEPH_LOCK_IDFT        512   /* dir frag tree */
+#define CEPH_LOCK_INEST       1024  /* mds internal */
+#define CEPH_LOCK_IXATTR      2048
+#define CEPH_LOCK_IFLOCK      4096  /* advisory file locks */
+#define CEPH_LOCK_INO         8192  /* immutable inode bits; not a lock */
+
+/* client_session ops */
+enum {
+	CEPH_SESSION_REQUEST_OPEN,
+	CEPH_SESSION_OPEN,
+	CEPH_SESSION_REQUEST_CLOSE,
+	CEPH_SESSION_CLOSE,
+	CEPH_SESSION_REQUEST_RENEWCAPS,
+	CEPH_SESSION_RENEWCAPS,
+	CEPH_SESSION_STALE,
+	CEPH_SESSION_RECALL_STATE,
+};
+
+extern const char *ceph_session_op_name(int op);
+
+struct ceph_mds_session_head {
+	__le32 op;
+	__le64 seq;
+	struct ceph_timespec stamp;
+	__le32 max_caps, max_leases;
+} __attribute__ ((packed));
+
+/* client_request */
+/*
+ * metadata ops.
+ *  & 0x001000 -> write op
+ *  & 0x010000 -> follow symlink (e.g. stat(), not lstat()).
+ &  & 0x100000 -> use weird ino/path trace
+ */
+#define CEPH_MDS_OP_WRITE        0x001000
+enum {
+	CEPH_MDS_OP_LOOKUP     = 0x00100,
+	CEPH_MDS_OP_GETATTR    = 0x00101,
+	CEPH_MDS_OP_LOOKUPHASH = 0x00102,
+	CEPH_MDS_OP_LOOKUPPARENT = 0x00103,
+
+	CEPH_MDS_OP_SETXATTR   = 0x01105,
+	CEPH_MDS_OP_RMXATTR    = 0x01106,
+	CEPH_MDS_OP_SETLAYOUT  = 0x01107,
+	CEPH_MDS_OP_SETATTR    = 0x01108,
+	CEPH_MDS_OP_SETFILELOCK= 0x01109,
+	CEPH_MDS_OP_GETFILELOCK= 0x00110,
+	CEPH_MDS_OP_SETDIRLAYOUT=0x0110a,
+
+	CEPH_MDS_OP_MKNOD      = 0x01201,
+	CEPH_MDS_OP_LINK       = 0x01202,
+	CEPH_MDS_OP_UNLINK     = 0x01203,
+	CEPH_MDS_OP_RENAME     = 0x01204,
+	CEPH_MDS_OP_MKDIR      = 0x01220,
+	CEPH_MDS_OP_RMDIR      = 0x01221,
+	CEPH_MDS_OP_SYMLINK    = 0x01222,
+
+	CEPH_MDS_OP_CREATE     = 0x01301,
+	CEPH_MDS_OP_OPEN       = 0x00302,
+	CEPH_MDS_OP_READDIR    = 0x00305,
+
+	CEPH_MDS_OP_LOOKUPSNAP = 0x00400,
+	CEPH_MDS_OP_MKSNAP     = 0x01400,
+	CEPH_MDS_OP_RMSNAP     = 0x01401,
+	CEPH_MDS_OP_LSSNAP     = 0x00402,
+};
+
+extern const char *ceph_mds_op_name(int op);
+
+
+#define CEPH_SETATTR_MODE   1
+#define CEPH_SETATTR_UID    2
+#define CEPH_SETATTR_GID    4
+#define CEPH_SETATTR_MTIME  8
+#define CEPH_SETATTR_ATIME 16
+#define CEPH_SETATTR_SIZE  32
+#define CEPH_SETATTR_CTIME 64
+
+union ceph_mds_request_args {
+	struct {
+		__le32 mask;                 /* CEPH_CAP_* */
+	} __attribute__ ((packed)) getattr;
+	struct {
+		__le32 mode;
+		__le32 uid;
+		__le32 gid;
+		struct ceph_timespec mtime;
+		struct ceph_timespec atime;
+		__le64 size, old_size;       /* old_size needed by truncate */
+		__le32 mask;                 /* CEPH_SETATTR_* */
+	} __attribute__ ((packed)) setattr;
+	struct {
+		__le32 frag;                 /* which dir fragment */
+		__le32 max_entries;          /* how many dentries to grab */
+		__le32 max_bytes;
+	} __attribute__ ((packed)) readdir;
+	struct {
+		__le32 mode;
+		__le32 rdev;
+	} __attribute__ ((packed)) mknod;
+	struct {
+		__le32 mode;
+	} __attribute__ ((packed)) mkdir;
+	struct {
+		__le32 flags;
+		__le32 mode;
+		__le32 stripe_unit;          /* layout for newly created file */
+		__le32 stripe_count;         /* ... */
+		__le32 object_size;
+		__le32 file_replication;
+		__le32 preferred;
+	} __attribute__ ((packed)) open;
+	struct {
+		__le32 flags;
+	} __attribute__ ((packed)) setxattr;
+	struct {
+		struct ceph_file_layout layout;
+	} __attribute__ ((packed)) setlayout;
+	struct {
+		__u8 rule; /* currently fcntl or flock */
+		__u8 type; /* shared, exclusive, remove*/
+		__le64 pid; /* process id requesting the lock */
+		__le64 pid_namespace;
+		__le64 start; /* initial location to lock */
+		__le64 length; /* num bytes to lock from start */
+		__u8 wait; /* will caller wait for lock to become available? */
+	} __attribute__ ((packed)) filelock_change;
+} __attribute__ ((packed));
+
+#define CEPH_MDS_FLAG_REPLAY        1  /* this is a replayed op */
+#define CEPH_MDS_FLAG_WANT_DENTRY   2  /* want dentry in reply */
+
+struct ceph_mds_request_head {
+	__le64 oldest_client_tid;
+	__le32 mdsmap_epoch;           /* on client */
+	__le32 flags;                  /* CEPH_MDS_FLAG_* */
+	__u8 num_retry, num_fwd;       /* count retry, fwd attempts */
+	__le16 num_releases;           /* # include cap/lease release records */
+	__le32 op;                     /* mds op code */
+	__le32 caller_uid, caller_gid;
+	__le64 ino;                    /* use this ino for openc, mkdir, mknod,
+					  etc. (if replaying) */
+	union ceph_mds_request_args args;
+} __attribute__ ((packed));
+
+/* cap/lease release record */
+struct ceph_mds_request_release {
+	__le64 ino, cap_id;            /* ino and unique cap id */
+	__le32 caps, wanted;           /* new issued, wanted */
+	__le32 seq, issue_seq, mseq;
+	__le32 dname_seq;              /* if releasing a dentry lease, a */
+	__le32 dname_len;              /* string follows. */
+} __attribute__ ((packed));
+
+/* client reply */
+struct ceph_mds_reply_head {
+	__le32 op;
+	__le32 result;
+	__le32 mdsmap_epoch;
+	__u8 safe;                     /* true if committed to disk */
+	__u8 is_dentry, is_target;     /* true if dentry, target inode records
+					  are included with reply */
+} __attribute__ ((packed));
+
+/* one for each node split */
+struct ceph_frag_tree_split {
+	__le32 frag;                   /* this frag splits... */
+	__le32 by;                     /* ...by this many bits */
+} __attribute__ ((packed));
+
+struct ceph_frag_tree_head {
+	__le32 nsplits;                /* num ceph_frag_tree_split records */
+	struct ceph_frag_tree_split splits[];
+} __attribute__ ((packed));
+
+/* capability issue, for bundling with mds reply */
+struct ceph_mds_reply_cap {
+	__le32 caps, wanted;           /* caps issued, wanted */
+	__le64 cap_id;
+	__le32 seq, mseq;
+	__le64 realm;                  /* snap realm */
+	__u8 flags;                    /* CEPH_CAP_FLAG_* */
+} __attribute__ ((packed));
+
+#define CEPH_CAP_FLAG_AUTH  1          /* cap is issued by auth mds */
+
+/* inode record, for bundling with mds reply */
+struct ceph_mds_reply_inode {
+	__le64 ino;
+	__le64 snapid;
+	__le32 rdev;
+	__le64 version;                /* inode version */
+	__le64 xattr_version;          /* version for xattr blob */
+	struct ceph_mds_reply_cap cap; /* caps issued for this inode */
+	struct ceph_file_layout layout;
+	struct ceph_timespec ctime, mtime, atime;
+	__le32 time_warp_seq;
+	__le64 size, max_size, truncate_size;
+	__le32 truncate_seq;
+	__le32 mode, uid, gid;
+	__le32 nlink;
+	__le64 files, subdirs, rbytes, rfiles, rsubdirs;  /* dir stats */
+	struct ceph_timespec rctime;
+	struct ceph_frag_tree_head fragtree;  /* (must be at end of struct) */
+} __attribute__ ((packed));
+/* followed by frag array, then symlink string, then xattr blob */
+
+/* reply_lease follows dname, and reply_inode */
+struct ceph_mds_reply_lease {
+	__le16 mask;            /* lease type(s) */
+	__le32 duration_ms;     /* lease duration */
+	__le32 seq;
+} __attribute__ ((packed));
+
+struct ceph_mds_reply_dirfrag {
+	__le32 frag;            /* fragment */
+	__le32 auth;            /* auth mds, if this is a delegation point */
+	__le32 ndist;           /* number of mds' this is replicated on */
+	__le32 dist[];
+} __attribute__ ((packed));
+
+#define CEPH_LOCK_FCNTL    1
+#define CEPH_LOCK_FLOCK    2
+
+#define CEPH_LOCK_SHARED   1
+#define CEPH_LOCK_EXCL     2
+#define CEPH_LOCK_UNLOCK   4
+
+struct ceph_filelock {
+	__le64 start;/* file offset to start lock at */
+	__le64 length; /* num bytes to lock; 0 for all following start */
+	__le64 client; /* which client holds the lock */
+	__le64 pid; /* process id holding the lock on the client */
+	__le64 pid_namespace;
+	__u8 type; /* shared lock, exclusive lock, or unlock */
+} __attribute__ ((packed));
+
+
+/* file access modes */
+#define CEPH_FILE_MODE_PIN        0
+#define CEPH_FILE_MODE_RD         1
+#define CEPH_FILE_MODE_WR         2
+#define CEPH_FILE_MODE_RDWR       3  /* RD | WR */
+#define CEPH_FILE_MODE_LAZY       4  /* lazy io */
+#define CEPH_FILE_MODE_NUM        8  /* bc these are bit fields.. mostly */
+
+int ceph_flags_to_mode(int flags);
+
+
+/* capability bits */
+#define CEPH_CAP_PIN         1  /* no specific capabilities beyond the pin */
+
+/* generic cap bits */
+#define CEPH_CAP_GSHARED     1  /* client can reads */
+#define CEPH_CAP_GEXCL       2  /* client can read and update */
+#define CEPH_CAP_GCACHE      4  /* (file) client can cache reads */
+#define CEPH_CAP_GRD         8  /* (file) client can read */
+#define CEPH_CAP_GWR        16  /* (file) client can write */
+#define CEPH_CAP_GBUFFER    32  /* (file) client can buffer writes */
+#define CEPH_CAP_GWREXTEND  64  /* (file) client can extend EOF */
+#define CEPH_CAP_GLAZYIO   128  /* (file) client can perform lazy io */
+
+/* per-lock shift */
+#define CEPH_CAP_SAUTH      2
+#define CEPH_CAP_SLINK      4
+#define CEPH_CAP_SXATTR     6
+#define CEPH_CAP_SFILE      8
+#define CEPH_CAP_SFLOCK    20 
+
+#define CEPH_CAP_BITS       22
+
+/* composed values */
+#define CEPH_CAP_AUTH_SHARED  (CEPH_CAP_GSHARED  << CEPH_CAP_SAUTH)
+#define CEPH_CAP_AUTH_EXCL     (CEPH_CAP_GEXCL     << CEPH_CAP_SAUTH)
+#define CEPH_CAP_LINK_SHARED  (CEPH_CAP_GSHARED  << CEPH_CAP_SLINK)
+#define CEPH_CAP_LINK_EXCL     (CEPH_CAP_GEXCL     << CEPH_CAP_SLINK)
+#define CEPH_CAP_XATTR_SHARED (CEPH_CAP_GSHARED  << CEPH_CAP_SXATTR)
+#define CEPH_CAP_XATTR_EXCL    (CEPH_CAP_GEXCL     << CEPH_CAP_SXATTR)
+#define CEPH_CAP_FILE(x)    (x << CEPH_CAP_SFILE)
+#define CEPH_CAP_FILE_SHARED   (CEPH_CAP_GSHARED   << CEPH_CAP_SFILE)
+#define CEPH_CAP_FILE_EXCL     (CEPH_CAP_GEXCL     << CEPH_CAP_SFILE)
+#define CEPH_CAP_FILE_CACHE    (CEPH_CAP_GCACHE    << CEPH_CAP_SFILE)
+#define CEPH_CAP_FILE_RD       (CEPH_CAP_GRD       << CEPH_CAP_SFILE)
+#define CEPH_CAP_FILE_WR       (CEPH_CAP_GWR       << CEPH_CAP_SFILE)
+#define CEPH_CAP_FILE_BUFFER   (CEPH_CAP_GBUFFER   << CEPH_CAP_SFILE)
+#define CEPH_CAP_FILE_WREXTEND (CEPH_CAP_GWREXTEND << CEPH_CAP_SFILE)
+#define CEPH_CAP_FILE_LAZYIO   (CEPH_CAP_GLAZYIO   << CEPH_CAP_SFILE)
+#define CEPH_CAP_FLOCK_SHARED  (CEPH_CAP_GSHARED   << CEPH_CAP_SFLOCK)
+#define CEPH_CAP_FLOCK_EXCL    (CEPH_CAP_GEXCL     << CEPH_CAP_SFLOCK)
+
+
+/* cap masks (for getattr) */
+#define CEPH_STAT_CAP_INODE    CEPH_CAP_PIN
+#define CEPH_STAT_CAP_TYPE     CEPH_CAP_PIN  /* mode >> 12 */
+#define CEPH_STAT_CAP_SYMLINK  CEPH_CAP_PIN
+#define CEPH_STAT_CAP_UID      CEPH_CAP_AUTH_SHARED
+#define CEPH_STAT_CAP_GID      CEPH_CAP_AUTH_SHARED
+#define CEPH_STAT_CAP_MODE     CEPH_CAP_AUTH_SHARED
+#define CEPH_STAT_CAP_NLINK    CEPH_CAP_LINK_SHARED
+#define CEPH_STAT_CAP_LAYOUT   CEPH_CAP_FILE_SHARED
+#define CEPH_STAT_CAP_MTIME    CEPH_CAP_FILE_SHARED
+#define CEPH_STAT_CAP_SIZE     CEPH_CAP_FILE_SHARED
+#define CEPH_STAT_CAP_ATIME    CEPH_CAP_FILE_SHARED  /* fixme */
+#define CEPH_STAT_CAP_XATTR    CEPH_CAP_XATTR_SHARED
+#define CEPH_STAT_CAP_INODE_ALL (CEPH_CAP_PIN |			\
+				 CEPH_CAP_AUTH_SHARED |	\
+				 CEPH_CAP_LINK_SHARED |	\
+				 CEPH_CAP_FILE_SHARED |	\
+				 CEPH_CAP_XATTR_SHARED)
+
+#define CEPH_CAP_ANY_SHARED (CEPH_CAP_AUTH_SHARED |			\
+			      CEPH_CAP_LINK_SHARED |			\
+			      CEPH_CAP_XATTR_SHARED |			\
+			      CEPH_CAP_FILE_SHARED)
+#define CEPH_CAP_ANY_RD   (CEPH_CAP_ANY_SHARED | CEPH_CAP_FILE_RD |	\
+			   CEPH_CAP_FILE_CACHE)
+
+#define CEPH_CAP_ANY_EXCL (CEPH_CAP_AUTH_EXCL |		\
+			   CEPH_CAP_LINK_EXCL |		\
+			   CEPH_CAP_XATTR_EXCL |	\
+			   CEPH_CAP_FILE_EXCL)
+#define CEPH_CAP_ANY_FILE_WR (CEPH_CAP_FILE_WR | CEPH_CAP_FILE_BUFFER |	\
+			      CEPH_CAP_FILE_EXCL)
+#define CEPH_CAP_ANY_WR   (CEPH_CAP_ANY_EXCL | CEPH_CAP_ANY_FILE_WR)
+#define CEPH_CAP_ANY      (CEPH_CAP_ANY_RD | CEPH_CAP_ANY_EXCL | \
+			   CEPH_CAP_ANY_FILE_WR | CEPH_CAP_FILE_LAZYIO | \
+			   CEPH_CAP_PIN)
+
+#define CEPH_CAP_LOCKS (CEPH_LOCK_IFILE | CEPH_LOCK_IAUTH | CEPH_LOCK_ILINK | \
+			CEPH_LOCK_IXATTR)
+
+int ceph_caps_for_mode(int mode);
+
+enum {
+	CEPH_CAP_OP_GRANT,         /* mds->client grant */
+	CEPH_CAP_OP_REVOKE,        /* mds->client revoke */
+	CEPH_CAP_OP_TRUNC,         /* mds->client trunc notify */
+	CEPH_CAP_OP_EXPORT,        /* mds has exported the cap */
+	CEPH_CAP_OP_IMPORT,        /* mds has imported the cap */
+	CEPH_CAP_OP_UPDATE,        /* client->mds update */
+	CEPH_CAP_OP_DROP,          /* client->mds drop cap bits */
+	CEPH_CAP_OP_FLUSH,         /* client->mds cap writeback */
+	CEPH_CAP_OP_FLUSH_ACK,     /* mds->client flushed */
+	CEPH_CAP_OP_FLUSHSNAP,     /* client->mds flush snapped metadata */
+	CEPH_CAP_OP_FLUSHSNAP_ACK, /* mds->client flushed snapped metadata */
+	CEPH_CAP_OP_RELEASE,       /* client->mds release (clean) cap */
+	CEPH_CAP_OP_RENEW,         /* client->mds renewal request */
+};
+
+extern const char *ceph_cap_op_name(int op);
+
+/*
+ * caps message, used for capability callbacks, acks, requests, etc.
+ */
+struct ceph_mds_caps {
+	__le32 op;                  /* CEPH_CAP_OP_* */
+	__le64 ino, realm;
+	__le64 cap_id;
+	__le32 seq, issue_seq;
+	__le32 caps, wanted, dirty; /* latest issued/wanted/dirty */
+	__le32 migrate_seq;
+	__le64 snap_follows;
+	__le32 snap_trace_len;
+
+	/* authlock */
+	__le32 uid, gid, mode;
+
+	/* linklock */
+	__le32 nlink;
+
+	/* xattrlock */
+	__le32 xattr_len;
+	__le64 xattr_version;
+
+	/* filelock */
+	__le64 size, max_size, truncate_size;
+	__le32 truncate_seq;
+	struct ceph_timespec mtime, atime, ctime;
+	struct ceph_file_layout layout;
+	__le32 time_warp_seq;
+} __attribute__ ((packed));
+
+/* cap release msg head */
+struct ceph_mds_cap_release {
+	__le32 num;                /* number of cap_items that follow */
+} __attribute__ ((packed));
+
+struct ceph_mds_cap_item {
+	__le64 ino;
+	__le64 cap_id;
+	__le32 migrate_seq, seq;
+} __attribute__ ((packed));
+
+#define CEPH_MDS_LEASE_REVOKE           1  /*    mds  -> client */
+#define CEPH_MDS_LEASE_RELEASE          2  /* client  -> mds    */
+#define CEPH_MDS_LEASE_RENEW            3  /* client <-> mds    */
+#define CEPH_MDS_LEASE_REVOKE_ACK       4  /* client  -> mds    */
+
+extern const char *ceph_lease_op_name(int o);
+
+/* lease msg header */
+struct ceph_mds_lease {
+	__u8 action;            /* CEPH_MDS_LEASE_* */
+	__le16 mask;            /* which lease */
+	__le64 ino;
+	__le64 first, last;     /* snap range */
+	__le32 seq;
+	__le32 duration_ms;     /* duration of renewal */
+} __attribute__ ((packed));
+/* followed by a __le32+string for dname */
+
+/* client reconnect */
+struct ceph_mds_cap_reconnect {
+	__le64 cap_id;
+	__le32 wanted;
+	__le32 issued;
+	__le64 snaprealm;
+	__le64 pathbase;        /* base ino for our path to this ino */
+	__le32 flock_len;       /* size of flock state blob, if any */
+} __attribute__ ((packed));
+/* followed by flock blob */
+
+struct ceph_mds_cap_reconnect_v1 {
+	__le64 cap_id;
+	__le32 wanted;
+	__le32 issued;
+	__le64 size;
+	struct ceph_timespec mtime, atime;
+	__le64 snaprealm;
+	__le64 pathbase;        /* base ino for our path to this ino */
+} __attribute__ ((packed));
+
+struct ceph_mds_snaprealm_reconnect {
+	__le64 ino;     /* snap realm base */
+	__le64 seq;     /* snap seq for this snap realm */
+	__le64 parent;  /* parent realm */
+} __attribute__ ((packed));
+
+/*
+ * snaps
+ */
+enum {
+	CEPH_SNAP_OP_UPDATE,  /* CREATE or DESTROY */
+	CEPH_SNAP_OP_CREATE,
+	CEPH_SNAP_OP_DESTROY,
+	CEPH_SNAP_OP_SPLIT,
+};
+
+extern const char *ceph_snap_op_name(int o);
+
+/* snap msg header */
+struct ceph_mds_snap_head {
+	__le32 op;                /* CEPH_SNAP_OP_* */
+	__le64 split;             /* ino to split off, if any */
+	__le32 num_split_inos;    /* # inos belonging to new child realm */
+	__le32 num_split_realms;  /* # child realms udner new child realm */
+	__le32 trace_len;         /* size of snap trace blob */
+} __attribute__ ((packed));
+/* followed by split ino list, then split realms, then the trace blob */
+
+/*
+ * encode info about a snaprealm, as viewed by a client
+ */
+struct ceph_mds_snap_realm {
+	__le64 ino;           /* ino */
+	__le64 created;       /* snap: when created */
+	__le64 parent;        /* ino: parent realm */
+	__le64 parent_since;  /* snap: same parent since */
+	__le64 seq;           /* snap: version */
+	__le32 num_snaps;
+	__le32 num_prior_parent_snaps;
+} __attribute__ ((packed));
+/* followed by my snap list, then prior parent snap list */
+
+#endif
diff --git a/fs/ceph/ceph_hash.h b/include/linux/ceph/ceph_hash.h
similarity index 100%
rename from fs/ceph/ceph_hash.h
rename to include/linux/ceph/ceph_hash.h
diff --git a/include/linux/ceph/debugfs.h b/include/linux/ceph/debugfs.h
new file mode 100644
index 0000000..2a79702
--- /dev/null
+++ b/include/linux/ceph/debugfs.h
@@ -0,0 +1,33 @@
+#ifndef _FS_CEPH_DEBUGFS_H
+#define _FS_CEPH_DEBUGFS_H
+
+#include "ceph_debug.h"
+#include "types.h"
+
+#define CEPH_DEFINE_SHOW_FUNC(name)					\
+static int name##_open(struct inode *inode, struct file *file)		\
+{									\
+	struct seq_file *sf;						\
+	int ret;							\
+									\
+	ret = single_open(file, name, NULL);				\
+	sf = file->private_data;					\
+	sf->private = inode->i_private;					\
+	return ret;							\
+}									\
+									\
+static const struct file_operations name##_fops = {			\
+	.open		= name##_open,					\
+	.read		= seq_read,					\
+	.llseek		= seq_lseek,					\
+	.release	= single_release,				\
+};
+
+/* debugfs.c */
+extern int ceph_debugfs_init(void);
+extern void ceph_debugfs_cleanup(void);
+extern int ceph_debugfs_client_init(struct ceph_client *client);
+extern void ceph_debugfs_client_cleanup(struct ceph_client *client);
+
+#endif
+
diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h
new file mode 100644
index 0000000..c5b6939
--- /dev/null
+++ b/include/linux/ceph/decode.h
@@ -0,0 +1,201 @@
+#ifndef __CEPH_DECODE_H
+#define __CEPH_DECODE_H
+
+#include <asm/unaligned.h>
+#include <linux/time.h>
+
+#include "types.h"
+
+/*
+ * in all cases,
+ *   void **p     pointer to position pointer
+ *   void *end    pointer to end of buffer (last byte + 1)
+ */
+
+static inline u64 ceph_decode_64(void **p)
+{
+	u64 v = get_unaligned_le64(*p);
+	*p += sizeof(u64);
+	return v;
+}
+static inline u32 ceph_decode_32(void **p)
+{
+	u32 v = get_unaligned_le32(*p);
+	*p += sizeof(u32);
+	return v;
+}
+static inline u16 ceph_decode_16(void **p)
+{
+	u16 v = get_unaligned_le16(*p);
+	*p += sizeof(u16);
+	return v;
+}
+static inline u8 ceph_decode_8(void **p)
+{
+	u8 v = *(u8 *)*p;
+	(*p)++;
+	return v;
+}
+static inline void ceph_decode_copy(void **p, void *pv, size_t n)
+{
+	memcpy(pv, *p, n);
+	*p += n;
+}
+
+/*
+ * bounds check input.
+ */
+#define ceph_decode_need(p, end, n, bad)		\
+	do {						\
+		if (unlikely(*(p) + (n) > (end))) 	\
+			goto bad;			\
+	} while (0)
+
+#define ceph_decode_64_safe(p, end, v, bad)			\
+	do {							\
+		ceph_decode_need(p, end, sizeof(u64), bad);	\
+		v = ceph_decode_64(p);				\
+	} while (0)
+#define ceph_decode_32_safe(p, end, v, bad)			\
+	do {							\
+		ceph_decode_need(p, end, sizeof(u32), bad);	\
+		v = ceph_decode_32(p);				\
+	} while (0)
+#define ceph_decode_16_safe(p, end, v, bad)			\
+	do {							\
+		ceph_decode_need(p, end, sizeof(u16), bad);	\
+		v = ceph_decode_16(p);				\
+	} while (0)
+#define ceph_decode_8_safe(p, end, v, bad)			\
+	do {							\
+		ceph_decode_need(p, end, sizeof(u8), bad);	\
+		v = ceph_decode_8(p);				\
+	} while (0)
+
+#define ceph_decode_copy_safe(p, end, pv, n, bad)		\
+	do {							\
+		ceph_decode_need(p, end, n, bad);		\
+		ceph_decode_copy(p, pv, n);			\
+	} while (0)
+
+/*
+ * struct ceph_timespec <-> struct timespec
+ */
+static inline void ceph_decode_timespec(struct timespec *ts,
+					const struct ceph_timespec *tv)
+{
+	ts->tv_sec = le32_to_cpu(tv->tv_sec);
+	ts->tv_nsec = le32_to_cpu(tv->tv_nsec);
+}
+static inline void ceph_encode_timespec(struct ceph_timespec *tv,
+					const struct timespec *ts)
+{
+	tv->tv_sec = cpu_to_le32(ts->tv_sec);
+	tv->tv_nsec = cpu_to_le32(ts->tv_nsec);
+}
+
+/*
+ * sockaddr_storage <-> ceph_sockaddr
+ */
+static inline void ceph_encode_addr(struct ceph_entity_addr *a)
+{
+	__be16 ss_family = htons(a->in_addr.ss_family);
+	a->in_addr.ss_family = *(__u16 *)&ss_family;
+}
+static inline void ceph_decode_addr(struct ceph_entity_addr *a)
+{
+	__be16 ss_family = *(__be16 *)&a->in_addr.ss_family;
+	a->in_addr.ss_family = ntohs(ss_family);
+	WARN_ON(a->in_addr.ss_family == 512);
+}
+
+/*
+ * encoders
+ */
+static inline void ceph_encode_64(void **p, u64 v)
+{
+	put_unaligned_le64(v, (__le64 *)*p);
+	*p += sizeof(u64);
+}
+static inline void ceph_encode_32(void **p, u32 v)
+{
+	put_unaligned_le32(v, (__le32 *)*p);
+	*p += sizeof(u32);
+}
+static inline void ceph_encode_16(void **p, u16 v)
+{
+	put_unaligned_le16(v, (__le16 *)*p);
+	*p += sizeof(u16);
+}
+static inline void ceph_encode_8(void **p, u8 v)
+{
+	*(u8 *)*p = v;
+	(*p)++;
+}
+static inline void ceph_encode_copy(void **p, const void *s, int len)
+{
+	memcpy(*p, s, len);
+	*p += len;
+}
+
+/*
+ * filepath, string encoders
+ */
+static inline void ceph_encode_filepath(void **p, void *end,
+					u64 ino, const char *path)
+{
+	u32 len = path ? strlen(path) : 0;
+	BUG_ON(*p + sizeof(ino) + sizeof(len) + len > end);
+	ceph_encode_8(p, 1);
+	ceph_encode_64(p, ino);
+	ceph_encode_32(p, len);
+	if (len)
+		memcpy(*p, path, len);
+	*p += len;
+}
+
+static inline void ceph_encode_string(void **p, void *end,
+				      const char *s, u32 len)
+{
+	BUG_ON(*p + sizeof(len) + len > end);
+	ceph_encode_32(p, len);
+	if (len)
+		memcpy(*p, s, len);
+	*p += len;
+}
+
+#define ceph_encode_need(p, end, n, bad)		\
+	do {						\
+		if (unlikely(*(p) + (n) > (end))) 	\
+			goto bad;			\
+	} while (0)
+
+#define ceph_encode_64_safe(p, end, v, bad)			\
+	do {							\
+		ceph_encode_need(p, end, sizeof(u64), bad);	\
+		ceph_encode_64(p, v);				\
+	} while (0)
+#define ceph_encode_32_safe(p, end, v, bad)			\
+	do {							\
+		ceph_encode_need(p, end, sizeof(u32), bad);	\
+		ceph_encode_32(p, v);			\
+	} while (0)
+#define ceph_encode_16_safe(p, end, v, bad)			\
+	do {							\
+		ceph_encode_need(p, end, sizeof(u16), bad);	\
+		ceph_encode_16(p, v);			\
+	} while (0)
+
+#define ceph_encode_copy_safe(p, end, pv, n, bad)		\
+	do {							\
+		ceph_encode_need(p, end, n, bad);		\
+		ceph_encode_copy(p, pv, n);			\
+	} while (0)
+#define ceph_encode_string_safe(p, end, s, n, bad)		\
+	do {							\
+		ceph_encode_need(p, end, n, bad);		\
+		ceph_encode_string(p, end, s, n);		\
+	} while (0)
+
+
+#endif
diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
new file mode 100644
index 0000000..f22b2e9
--- /dev/null
+++ b/include/linux/ceph/libceph.h
@@ -0,0 +1,249 @@
+#ifndef _FS_CEPH_LIBCEPH_H
+#define _FS_CEPH_LIBCEPH_H
+
+#include "ceph_debug.h"
+
+#include <asm/unaligned.h>
+#include <linux/backing-dev.h>
+#include <linux/completion.h>
+#include <linux/exportfs.h>
+#include <linux/fs.h>
+#include <linux/mempool.h>
+#include <linux/pagemap.h>
+#include <linux/wait.h>
+#include <linux/writeback.h>
+#include <linux/slab.h>
+
+#include "types.h"
+#include "messenger.h"
+#include "msgpool.h"
+#include "mon_client.h"
+#include "osd_client.h"
+#include "ceph_fs.h"
+
+/*
+ * Supported features
+ */
+#define CEPH_FEATURE_SUPPORTED_DEFAULT CEPH_FEATURE_NOSRCADDR
+#define CEPH_FEATURE_REQUIRED_DEFAULT  CEPH_FEATURE_NOSRCADDR
+
+/*
+ * mount options
+ */
+#define CEPH_OPT_FSID             (1<<0)
+#define CEPH_OPT_NOSHARE          (1<<1) /* don't share client with other sbs */
+#define CEPH_OPT_MYIP             (1<<2) /* specified my ip */
+#define CEPH_OPT_NOCRC            (1<<3) /* no data crc on writes */
+
+#define CEPH_OPT_DEFAULT   (0);
+
+#define ceph_set_opt(client, opt) \
+	(client)->options->flags |= CEPH_OPT_##opt;
+#define ceph_test_opt(client, opt) \
+	(!!((client)->options->flags & CEPH_OPT_##opt))
+
+struct ceph_options {
+	int flags;
+	struct ceph_fsid fsid;
+	struct ceph_entity_addr my_addr;
+	int mount_timeout;
+	int osd_idle_ttl;
+	int osd_timeout;
+	int osd_keepalive_timeout;
+
+	/*
+	 * any type that can't be simply compared or doesn't need need
+	 * to be compared should go beyond this point,
+	 * ceph_compare_options() should be updated accordingly
+	 */
+
+	struct ceph_entity_addr *mon_addr; /* should be the first
+					      pointer type of args */
+	int num_mon;
+	char *name;
+	char *secret;
+};
+
+/*
+ * defaults
+ */
+#define CEPH_MOUNT_TIMEOUT_DEFAULT  60
+#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)
+
+#define CEPH_AUTH_NAME_DEFAULT   "guest"
+
+/*
+ * Delay telling the MDS we no longer want caps, in case we reopen
+ * the file.  Delay a minimum amount of time, even if we send a cap
+ * message for some other reason.  Otherwise, take the oppotunity to
+ * update the mds to avoid sending another message later.
+ */
+#define CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT      5  /* cap release delay */
+#define CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT     60  /* cap release delay */
+
+#define CEPH_CAP_RELEASE_SAFETY_DEFAULT        (CEPH_CAPS_PER_RELEASE * 4)
+
+/* mount state */
+enum {
+	CEPH_MOUNT_MOUNTING,
+	CEPH_MOUNT_MOUNTED,
+	CEPH_MOUNT_UNMOUNTING,
+	CEPH_MOUNT_UNMOUNTED,
+	CEPH_MOUNT_SHUTDOWN,
+};
+
+/*
+ * subtract jiffies
+ */
+static inline unsigned long time_sub(unsigned long a, unsigned long b)
+{
+	BUG_ON(time_after(b, a));
+	return (long)a - (long)b;
+}
+
+struct ceph_mds_client;
+
+/*
+ * per client state
+ *
+ * possibly shared by multiple mount points, if they are
+ * mounting the same ceph filesystem/cluster.
+ */
+struct ceph_client {
+	struct ceph_fsid fsid;
+	bool have_fsid;
+
+	void *private;
+
+	struct ceph_options *options;
+
+	struct mutex mount_mutex;      /* serialize mount attempts */
+	wait_queue_head_t auth_wq;
+	int auth_err;
+
+	int (*extra_mon_dispatch)(struct ceph_client *, struct ceph_msg *);
+
+	u32 supported_features;
+	u32 required_features;
+
+	struct ceph_messenger *msgr;   /* messenger instance */
+	struct ceph_mon_client monc;
+	struct ceph_osd_client osdc;
+
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_dir;
+	struct dentry *debugfs_monmap;
+	struct dentry *debugfs_osdmap;
+#endif
+};
+
+
+
+/*
+ * snapshots
+ */
+
+/*
+ * A "snap context" is the set of existing snapshots when we
+ * write data.  It is used by the OSD to guide its COW behavior.
+ *
+ * The ceph_snap_context is refcounted, and attached to each dirty
+ * page, indicating which context the dirty data belonged when it was
+ * dirtied.
+ */
+struct ceph_snap_context {
+	atomic_t nref;
+	u64 seq;
+	int num_snaps;
+	u64 snaps[];
+};
+
+static inline struct ceph_snap_context *
+ceph_get_snap_context(struct ceph_snap_context *sc)
+{
+	/*
+	printk("get_snap_context %p %d -> %d\n", sc, atomic_read(&sc->nref),
+	       atomic_read(&sc->nref)+1);
+	*/
+	if (sc)
+		atomic_inc(&sc->nref);
+	return sc;
+}
+
+static inline void ceph_put_snap_context(struct ceph_snap_context *sc)
+{
+	if (!sc)
+		return;
+	/*
+	printk("put_snap_context %p %d -> %d\n", sc, atomic_read(&sc->nref),
+	       atomic_read(&sc->nref)-1);
+	*/
+	if (atomic_dec_and_test(&sc->nref)) {
+		/*printk(" deleting snap_context %p\n", sc);*/
+		kfree(sc);
+	}
+}
+
+/*
+ * calculate the number of pages a given length and offset map onto,
+ * if we align the data.
+ */
+static inline int calc_pages_for(u64 off, u64 len)
+{
+	return ((off+len+PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT) -
+		(off >> PAGE_CACHE_SHIFT);
+}
+
+/* ceph_common.c */
+extern const char *ceph_msg_type_name(int type);
+extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
+extern struct kmem_cache *ceph_inode_cachep;
+extern struct kmem_cache *ceph_cap_cachep;
+extern struct kmem_cache *ceph_dentry_cachep;
+extern struct kmem_cache *ceph_file_cachep;
+
+extern int ceph_parse_options(struct ceph_options **popt, char *options,
+			      const char *dev_name, const char *dev_name_end,
+			      int (*parse_extra_token)(char *c, void *private),
+			      void *private);
+extern void ceph_destroy_options(struct ceph_options *opt);
+extern int ceph_compare_options(struct ceph_options *new_opt,
+				struct ceph_client *client);
+extern struct ceph_client *ceph_create_client(struct ceph_options *opt,
+					      void *private);
+extern u64 ceph_client_id(struct ceph_client *client);
+extern void ceph_destroy_client(struct ceph_client *client);
+extern int __ceph_open_session(struct ceph_client *client,
+			       unsigned long started);
+extern int ceph_open_session(struct ceph_client *client);
+
+/* pagevec.c */
+extern void ceph_release_page_vector(struct page **pages, int num_pages);
+
+extern struct page **ceph_get_direct_page_vector(const char __user *data,
+					    int num_pages,
+					    loff_t off, size_t len);
+extern void ceph_put_page_vector(struct page **pages, int num_pages);
+extern void ceph_release_page_vector(struct page **pages, int num_pages);
+extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
+extern int ceph_copy_user_to_page_vector(struct page **pages,
+					 const char __user *data,
+					 loff_t off, size_t len);
+extern int ceph_copy_to_page_vector(struct page **pages,
+				    const char *data,
+				    loff_t off, size_t len);
+extern int ceph_copy_from_page_vector(struct page **pages,
+				    char *data,
+				    loff_t off, size_t len);
+extern int ceph_copy_page_vector_to_user(struct page **pages, char __user *data,
+				    loff_t off, size_t len);
+extern void ceph_zero_page_vector_range(int off, int len, struct page **pages);
+
+
+#endif /* _FS_CEPH_SUPER_H */
diff --git a/fs/ceph/mdsmap.h b/include/linux/ceph/mdsmap.h
similarity index 100%
rename from fs/ceph/mdsmap.h
rename to include/linux/ceph/mdsmap.h
diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h
new file mode 100644
index 0000000..5956d62
--- /dev/null
+++ b/include/linux/ceph/messenger.h
@@ -0,0 +1,261 @@
+#ifndef __FS_CEPH_MESSENGER_H
+#define __FS_CEPH_MESSENGER_H
+
+#include <linux/kref.h>
+#include <linux/mutex.h>
+#include <linux/net.h>
+#include <linux/radix-tree.h>
+#include <linux/uio.h>
+#include <linux/version.h>
+#include <linux/workqueue.h>
+
+#include "types.h"
+#include "buffer.h"
+
+struct ceph_msg;
+struct ceph_connection;
+
+extern struct workqueue_struct *ceph_msgr_wq;       /* receive work queue */
+
+/*
+ * Ceph defines these callbacks for handling connection events.
+ */
+struct ceph_connection_operations {
+	struct ceph_connection *(*get)(struct ceph_connection *);
+	void (*put)(struct ceph_connection *);
+
+	/* handle an incoming message. */
+	void (*dispatch) (struct ceph_connection *con, struct ceph_msg *m);
+
+	/* authorize an outgoing connection */
+	int (*get_authorizer) (struct ceph_connection *con,
+			       void **buf, int *len, int *proto,
+			       void **reply_buf, int *reply_len, int force_new);
+	int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
+	int (*invalidate_authorizer)(struct ceph_connection *con);
+
+	/* protocol version mismatch */
+	void (*bad_proto) (struct ceph_connection *con);
+
+	/* there was some error on the socket (disconnect, whatever) */
+	void (*fault) (struct ceph_connection *con);
+
+	/* a remote host as terminated a message exchange session, and messages
+	 * we sent (or they tried to send us) may be lost. */
+	void (*peer_reset) (struct ceph_connection *con);
+
+	struct ceph_msg * (*alloc_msg) (struct ceph_connection *con,
+					struct ceph_msg_header *hdr,
+					int *skip);
+};
+
+/* use format string %s%d */
+#define ENTITY_NAME(n) ceph_entity_type_name((n).type), le64_to_cpu((n).num)
+
+struct ceph_messenger {
+	struct ceph_entity_inst inst;    /* my name+address */
+	struct ceph_entity_addr my_enc_addr;
+	struct page *zero_page;          /* used in certain error cases */
+
+	bool nocrc;
+
+	/*
+	 * the global_seq counts connections i (attempt to) initiate
+	 * in order to disambiguate certain connect race conditions.
+	 */
+	u32 global_seq;
+	spinlock_t global_seq_lock;
+
+	u32 supported_features;
+	u32 required_features;
+};
+
+/*
+ * a single message.  it contains a header (src, dest, message type, etc.),
+ * footer (crc values, mainly), a "front" message body, and possibly a
+ * data payload (stored in some number of pages).
+ */
+struct ceph_msg {
+	struct ceph_msg_header hdr;	/* header */
+	struct ceph_msg_footer footer;	/* footer */
+	struct kvec front;              /* unaligned blobs of message */
+	struct ceph_buffer *middle;
+	struct page **pages;            /* data payload.  NOT OWNER. */
+	unsigned nr_pages;              /* size of page array */
+	struct ceph_pagelist *pagelist; /* instead of pages */
+	struct list_head list_head;
+	struct kref kref;
+	struct bio  *bio;		/* instead of pages/pagelist */
+	struct bio  *bio_iter;		/* bio iterator */
+	int bio_seg;			/* current bio segment */
+	struct ceph_pagelist *trail;	/* the trailing part of the data */
+	bool front_is_vmalloc;
+	bool more_to_follow;
+	bool needs_out_seq;
+	int front_max;
+
+	struct ceph_msgpool *pool;
+};
+
+struct ceph_msg_pos {
+	int page, page_pos;  /* which page; offset in page */
+	int data_pos;        /* offset in data payload */
+	int did_page_crc;    /* true if we've calculated crc for current page */
+};
+
+/* ceph connection fault delay defaults, for exponential backoff */
+#define BASE_DELAY_INTERVAL	(HZ/2)
+#define MAX_DELAY_INTERVAL	(5 * 60 * HZ)
+
+/*
+ * ceph_connection state bit flags
+ *
+ * QUEUED and BUSY are used together to ensure that only a single
+ * thread is currently opening, reading or writing data to the socket.
+ */
+#define LOSSYTX         0  /* we can close channel or drop messages on errors */
+#define CONNECTING	1
+#define NEGOTIATING	2
+#define KEEPALIVE_PENDING      3
+#define WRITE_PENDING	4  /* we have data ready to send */
+#define QUEUED          5  /* there is work queued on this connection */
+#define BUSY            6  /* work is being done */
+#define STANDBY		8  /* no outgoing messages, socket closed.  we keep
+			    * the ceph_connection around to maintain shared
+			    * state with the peer. */
+#define CLOSED		10 /* we've closed the connection */
+#define SOCK_CLOSED	11 /* socket state changed to closed */
+#define OPENING         13 /* open connection w/ (possibly new) peer */
+#define DEAD            14 /* dead, about to kfree */
+
+/*
+ * A single connection with another host.
+ *
+ * We maintain a queue of outgoing messages, and some session state to
+ * ensure that we can preserve the lossless, ordered delivery of
+ * messages in the case of a TCP disconnect.
+ */
+struct ceph_connection {
+	void *private;
+	atomic_t nref;
+
+	const struct ceph_connection_operations *ops;
+
+	struct ceph_messenger *msgr;
+	struct socket *sock;
+	unsigned long state;	/* connection state (see flags above) */
+	const char *error_msg;  /* error message, if any */
+
+	struct ceph_entity_addr peer_addr; /* peer address */
+	struct ceph_entity_name peer_name; /* peer name */
+	struct ceph_entity_addr peer_addr_for_me;
+	unsigned peer_features;
+	u32 connect_seq;      /* identify the most recent connection
+				 attempt for this connection, client */
+	u32 peer_global_seq;  /* peer's global seq for this connection */
+
+	int auth_retry;       /* true if we need a newer authorizer */
+	void *auth_reply_buf;   /* where to put the authorizer reply */
+	int auth_reply_buf_len;
+
+	struct mutex mutex;
+
+	/* out queue */
+	struct list_head out_queue;
+	struct list_head out_sent;   /* sending or sent but unacked */
+	u64 out_seq;		     /* last message queued for send */
+	bool out_keepalive_pending;
+
+	u64 in_seq, in_seq_acked;  /* last message received, acked */
+
+	/* connection negotiation temps */
+	char in_banner[CEPH_BANNER_MAX_LEN];
+	union {
+		struct {  /* outgoing connection */
+			struct ceph_msg_connect out_connect;
+			struct ceph_msg_connect_reply in_reply;
+		};
+		struct {  /* incoming */
+			struct ceph_msg_connect in_connect;
+			struct ceph_msg_connect_reply out_reply;
+		};
+	};
+	struct ceph_entity_addr actual_peer_addr;
+
+	/* message out temps */
+	struct ceph_msg *out_msg;        /* sending message (== tail of
+					    out_sent) */
+	bool out_msg_done;
+	struct ceph_msg_pos out_msg_pos;
+
+	struct kvec out_kvec[8],         /* sending header/footer data */
+		*out_kvec_cur;
+	int out_kvec_left;   /* kvec's left in out_kvec */
+	int out_skip;        /* skip this many bytes */
+	int out_kvec_bytes;  /* total bytes left */
+	bool out_kvec_is_msg; /* kvec refers to out_msg */
+	int out_more;        /* there is more data after the kvecs */
+	__le64 out_temp_ack; /* for writing an ack */
+
+	/* message in temps */
+	struct ceph_msg_header in_hdr;
+	struct ceph_msg *in_msg;
+	struct ceph_msg_pos in_msg_pos;
+	u32 in_front_crc, in_middle_crc, in_data_crc;  /* calculated crc */
+
+	char in_tag;         /* protocol control byte */
+	int in_base_pos;     /* bytes read */
+	__le64 in_temp_ack;  /* for reading an ack */
+
+	struct delayed_work work;	    /* send|recv work */
+	unsigned long       delay;          /* current delay interval */
+};
+
+
+extern const char *ceph_pr_addr(const struct sockaddr_storage *ss);
+extern int ceph_parse_ips(const char *c, const char *end,
+			  struct ceph_entity_addr *addr,
+			  int max_count, int *count);
+
+
+extern int ceph_msgr_init(void);
+extern void ceph_msgr_exit(void);
+extern void ceph_msgr_flush(void);
+
+extern struct ceph_messenger *ceph_messenger_create(
+	struct ceph_entity_addr *myaddr,
+	u32 features, u32 required);
+extern void ceph_messenger_destroy(struct ceph_messenger *);
+
+extern void ceph_con_init(struct ceph_messenger *msgr,
+			  struct ceph_connection *con);
+extern void ceph_con_open(struct ceph_connection *con,
+			  struct ceph_entity_addr *addr);
+extern bool ceph_con_opened(struct ceph_connection *con);
+extern void ceph_con_close(struct ceph_connection *con);
+extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg);
+extern void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg);
+extern void ceph_con_revoke_message(struct ceph_connection *con,
+				  struct ceph_msg *msg);
+extern void ceph_con_keepalive(struct ceph_connection *con);
+extern struct ceph_connection *ceph_con_get(struct ceph_connection *con);
+extern void ceph_con_put(struct ceph_connection *con);
+
+extern struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags);
+extern void ceph_msg_kfree(struct ceph_msg *m);
+
+
+static inline struct ceph_msg *ceph_msg_get(struct ceph_msg *msg)
+{
+	kref_get(&msg->kref);
+	return msg;
+}
+extern void ceph_msg_last_put(struct kref *kref);
+static inline void ceph_msg_put(struct ceph_msg *msg)
+{
+	kref_put(&msg->kref, ceph_msg_last_put);
+}
+
+extern void ceph_msg_dump(struct ceph_msg *msg);
+
+#endif
diff --git a/include/linux/ceph/mon_client.h b/include/linux/ceph/mon_client.h
new file mode 100644
index 0000000..545f859
--- /dev/null
+++ b/include/linux/ceph/mon_client.h
@@ -0,0 +1,122 @@
+#ifndef _FS_CEPH_MON_CLIENT_H
+#define _FS_CEPH_MON_CLIENT_H
+
+#include <linux/completion.h>
+#include <linux/kref.h>
+#include <linux/rbtree.h>
+
+#include "messenger.h"
+
+struct ceph_client;
+struct ceph_mount_args;
+struct ceph_auth_client;
+
+/*
+ * The monitor map enumerates the set of all monitors.
+ */
+struct ceph_monmap {
+	struct ceph_fsid fsid;
+	u32 epoch;
+	u32 num_mon;
+	struct ceph_entity_inst mon_inst[0];
+};
+
+struct ceph_mon_client;
+struct ceph_mon_generic_request;
+
+
+/*
+ * Generic mechanism for resending monitor requests.
+ */
+typedef void (*ceph_monc_request_func_t)(struct ceph_mon_client *monc,
+					 int newmon);
+
+/* a pending monitor request */
+struct ceph_mon_request {
+	struct ceph_mon_client *monc;
+	struct delayed_work delayed_work;
+	unsigned long delay;
+	ceph_monc_request_func_t do_request;
+};
+
+/*
+ * ceph_mon_generic_request is being used for the statfs and poolop requests
+ * which are bening done a bit differently because we need to get data back
+ * to the caller
+ */
+struct ceph_mon_generic_request {
+	struct kref kref;
+	u64 tid;
+	struct rb_node node;
+	int result;
+	void *buf;
+	int buf_len;
+	struct completion completion;
+	struct ceph_msg *request;  /* original request */
+	struct ceph_msg *reply;    /* and reply */
+};
+
+struct ceph_mon_client {
+	struct ceph_client *client;
+	struct ceph_monmap *monmap;
+
+	struct mutex mutex;
+	struct delayed_work delayed_work;
+
+	struct ceph_auth_client *auth;
+	struct ceph_msg *m_auth, *m_auth_reply, *m_subscribe, *m_subscribe_ack;
+	int pending_auth;
+
+	bool hunting;
+	int cur_mon;                       /* last monitor i contacted */
+	unsigned long sub_sent, sub_renew_after;
+	struct ceph_connection *con;
+	bool have_fsid;
+
+	/* pending generic requests */
+	struct rb_root generic_request_tree;
+	int num_generic_requests;
+	u64 last_tid;
+
+	/* mds/osd map */
+	int want_mdsmap;
+	int want_next_osdmap; /* 1 = want, 2 = want+asked */
+	u32 have_osdmap, have_mdsmap;
+
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_file;
+#endif
+};
+
+extern struct ceph_monmap *ceph_monmap_decode(void *p, void *end);
+extern int ceph_monmap_contains(struct ceph_monmap *m,
+				struct ceph_entity_addr *addr);
+
+extern int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl);
+extern void ceph_monc_stop(struct ceph_mon_client *monc);
+
+/*
+ * The model here is to indicate that we need a new map of at least
+ * epoch @want, and also call in when we receive a map.  We will
+ * periodically rerequest the map from the monitor cluster until we
+ * get what we want.
+ */
+extern int ceph_monc_got_mdsmap(struct ceph_mon_client *monc, u32 have);
+extern int ceph_monc_got_osdmap(struct ceph_mon_client *monc, u32 have);
+
+extern void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc);
+
+extern int ceph_monc_do_statfs(struct ceph_mon_client *monc,
+			       struct ceph_statfs *buf);
+
+extern int ceph_monc_open_session(struct ceph_mon_client *monc);
+
+extern int ceph_monc_validate_auth(struct ceph_mon_client *monc);
+
+extern int ceph_monc_create_snapid(struct ceph_mon_client *monc,
+				   u32 pool, u64 *snapid);
+
+extern int ceph_monc_delete_snapid(struct ceph_mon_client *monc,
+				   u32 pool, u64 snapid);
+
+#endif
diff --git a/fs/ceph/msgpool.h b/include/linux/ceph/msgpool.h
similarity index 100%
rename from fs/ceph/msgpool.h
rename to include/linux/ceph/msgpool.h
diff --git a/fs/ceph/msgr.h b/include/linux/ceph/msgr.h
similarity index 100%
rename from fs/ceph/msgr.h
rename to include/linux/ceph/msgr.h
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
new file mode 100644
index 0000000..6c91fb0
--- /dev/null
+++ b/include/linux/ceph/osd_client.h
@@ -0,0 +1,234 @@
+#ifndef _FS_CEPH_OSD_CLIENT_H
+#define _FS_CEPH_OSD_CLIENT_H
+
+#include <linux/completion.h>
+#include <linux/kref.h>
+#include <linux/mempool.h>
+#include <linux/rbtree.h>
+
+#include "types.h"
+#include "osdmap.h"
+#include "messenger.h"
+
+struct ceph_msg;
+struct ceph_snap_context;
+struct ceph_osd_request;
+struct ceph_osd_client;
+struct ceph_authorizer;
+struct ceph_pagelist;
+
+/*
+ * completion callback for async writepages
+ */
+typedef void (*ceph_osdc_callback_t)(struct ceph_osd_request *,
+				     struct ceph_msg *);
+
+/* a given osd we're communicating with */
+struct ceph_osd {
+	atomic_t o_ref;
+	struct ceph_osd_client *o_osdc;
+	int o_osd;
+	int o_incarnation;
+	struct rb_node o_node;
+	struct ceph_connection o_con;
+	struct list_head o_requests;
+	struct list_head o_osd_lru;
+	struct ceph_authorizer *o_authorizer;
+	void *o_authorizer_buf, *o_authorizer_reply_buf;
+	size_t o_authorizer_buf_len, o_authorizer_reply_buf_len;
+	unsigned long lru_ttl;
+	int o_marked_for_keepalive;
+	struct list_head o_keepalive_item;
+};
+
+/* an in-flight request */
+struct ceph_osd_request {
+	u64             r_tid;              /* unique for this client */
+	struct rb_node  r_node;
+	struct list_head r_req_lru_item;
+	struct list_head r_osd_item;
+	struct ceph_osd *r_osd;
+	struct ceph_pg   r_pgid;
+	int              r_pg_osds[CEPH_PG_MAX_SIZE];
+	int              r_num_pg_osds;
+
+	struct ceph_connection *r_con_filling_msg;
+
+	struct ceph_msg  *r_request, *r_reply;
+	int               r_result;
+	int               r_flags;     /* any additional flags for the osd */
+	u32               r_sent;      /* >0 if r_request is sending/sent */
+	int               r_got_reply;
+
+	struct ceph_osd_client *r_osdc;
+	struct kref       r_kref;
+	bool              r_mempool;
+	struct completion r_completion, r_safe_completion;
+	ceph_osdc_callback_t r_callback, r_safe_callback;
+	struct ceph_eversion r_reassert_version;
+	struct list_head  r_unsafe_item;
+
+	struct inode *r_inode;         	      /* for use by callbacks */
+	void *r_priv;			      /* ditto */
+
+	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 */
+	unsigned          r_num_pages;        /* size of page array (follows) */
+	struct page     **r_pages;            /* pages for data payload */
+	int               r_pages_from_pool;
+	int               r_own_pages;        /* if true, i own page list */
+#ifdef CONFIG_BLOCK
+	struct bio       *r_bio;	      /* instead of pages */
+#endif
+
+	struct ceph_pagelist *r_trail;	      /* trailing part of the data */
+};
+
+struct ceph_osd_client {
+	struct ceph_client     *client;
+
+	struct ceph_osdmap     *osdmap;       /* current map */
+	struct rw_semaphore    map_sem;
+	struct completion      map_waiters;
+	u64                    last_requested_map;
+
+	struct mutex           request_mutex;
+	struct rb_root         osds;          /* osds */
+	struct list_head       osd_lru;       /* idle osds */
+	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 */
+	int                    num_requests;
+	struct delayed_work    timeout_work;
+	struct delayed_work    osds_timeout_work;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry 	       *debugfs_file;
+#endif
+
+	mempool_t              *req_mempool;
+
+	struct ceph_msgpool	msgpool_op;
+	struct ceph_msgpool	msgpool_op_reply;
+};
+
+struct ceph_osd_req_op {
+	u16 op;           /* CEPH_OSD_OP_* */
+	u32 flags;        /* CEPH_OSD_FLAG_* */
+	union {
+		struct {
+			u64 offset, length;
+			u64 truncate_size;
+			u32 truncate_seq;
+		} extent;
+		struct {
+			const char *name;
+			u32 name_len;
+			const char  *val;
+			u32 value_len;
+			__u8 cmp_op;       /* CEPH_OSD_CMPXATTR_OP_* */
+			__u8 cmp_mode;     /* CEPH_OSD_CMPXATTR_MODE_* */
+		} xattr;
+		struct {
+			const char *class_name;
+			__u8 class_len;
+			const char *method_name;
+			__u8 method_len;
+			__u8 argc;
+			const char *indata;
+			u32 indata_len;
+		} cls;
+		struct {
+			u64 cookie, count;
+		} pgls;
+	        struct {
+		        u64 snapid;
+	        } snap;
+	};
+	u32 payload_len;
+};
+
+extern int ceph_osdc_init(struct ceph_osd_client *osdc,
+			  struct ceph_client *client);
+extern void ceph_osdc_stop(struct ceph_osd_client *osdc);
+
+extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc,
+				   struct ceph_msg *msg);
+extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc,
+				 struct ceph_msg *msg);
+
+extern void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
+			struct ceph_file_layout *layout,
+			u64 snapid,
+			u64 off, u64 *plen, u64 *bno,
+			struct ceph_osd_request *req,
+			struct ceph_osd_req_op *op);
+
+extern struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
+					       int flags,
+					       struct ceph_snap_context *snapc,
+					       struct ceph_osd_req_op *ops,
+					       bool use_mempool,
+					       gfp_t gfp_flags,
+					       struct page **pages,
+					       struct bio *bio);
+
+extern void ceph_osdc_build_request(struct ceph_osd_request *req,
+				    u64 off, u64 *plen,
+				    struct ceph_osd_req_op *src_ops,
+				    struct ceph_snap_context *snapc,
+				    struct timespec *mtime,
+				    const char *oid,
+				    int oid_len);
+
+extern struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *,
+				      struct ceph_file_layout *layout,
+				      struct ceph_vino vino,
+				      u64 offset, u64 *len, int op, int flags,
+				      struct ceph_snap_context *snapc,
+				      int do_sync, u32 truncate_seq,
+				      u64 truncate_size,
+				      struct timespec *mtime,
+				      bool use_mempool, int num_reply);
+
+static inline void ceph_osdc_get_request(struct ceph_osd_request *req)
+{
+	kref_get(&req->r_kref);
+}
+extern void ceph_osdc_release_request(struct kref *kref);
+static inline void ceph_osdc_put_request(struct ceph_osd_request *req)
+{
+	kref_put(&req->r_kref, ceph_osdc_release_request);
+}
+
+extern int ceph_osdc_start_request(struct ceph_osd_client *osdc,
+				   struct ceph_osd_request *req,
+				   bool nofail);
+extern int ceph_osdc_wait_request(struct ceph_osd_client *osdc,
+				  struct ceph_osd_request *req);
+extern void ceph_osdc_sync(struct ceph_osd_client *osdc);
+
+extern int ceph_osdc_readpages(struct ceph_osd_client *osdc,
+			       struct ceph_vino vino,
+			       struct ceph_file_layout *layout,
+			       u64 off, u64 *plen,
+			       u32 truncate_seq, u64 truncate_size,
+			       struct page **pages, int nr_pages);
+
+extern int ceph_osdc_writepages(struct ceph_osd_client *osdc,
+				struct ceph_vino vino,
+				struct ceph_file_layout *layout,
+				struct ceph_snap_context *sc,
+				u64 off, u64 len,
+				u32 truncate_seq, u64 truncate_size,
+				struct timespec *mtime,
+				struct page **pages, int nr_pages,
+				int flags, int do_sync, bool nofail);
+
+#endif
+
diff --git a/include/linux/ceph/osdmap.h b/include/linux/ceph/osdmap.h
new file mode 100644
index 0000000..ba4c205
--- /dev/null
+++ b/include/linux/ceph/osdmap.h
@@ -0,0 +1,130 @@
+#ifndef _FS_CEPH_OSDMAP_H
+#define _FS_CEPH_OSDMAP_H
+
+#include <linux/rbtree.h>
+#include "types.h"
+#include "ceph_fs.h"
+#include <linux/crush/crush.h>
+
+/*
+ * The osd map describes the current membership of the osd cluster and
+ * specifies the mapping of objects to placement groups and placement
+ * groups to (sets of) osds.  That is, it completely specifies the
+ * (desired) distribution of all data objects in the system at some
+ * point in time.
+ *
+ * Each map version is identified by an epoch, which increases monotonically.
+ *
+ * The map can be updated either via an incremental map (diff) describing
+ * the change between two successive epochs, or as a fully encoded map.
+ */
+struct ceph_pg_pool_info {
+	struct rb_node node;
+	int id;
+	struct ceph_pg_pool v;
+	int pg_num_mask, pgp_num_mask, lpg_num_mask, lpgp_num_mask;
+	char *name;
+};
+
+struct ceph_pg_mapping {
+	struct rb_node node;
+	struct ceph_pg pgid;
+	int len;
+	int osds[];
+};
+
+struct ceph_osdmap {
+	struct ceph_fsid fsid;
+	u32 epoch;
+	u32 mkfs_epoch;
+	struct ceph_timespec created, modified;
+
+	u32 flags;         /* CEPH_OSDMAP_* */
+
+	u32 max_osd;       /* size of osd_state, _offload, _addr arrays */
+	u8 *osd_state;     /* CEPH_OSD_* */
+	u32 *osd_weight;   /* 0 = failed, 0x10000 = 100% normal */
+	struct ceph_entity_addr *osd_addr;
+
+	struct rb_root pg_temp;
+	struct rb_root pg_pools;
+	u32 pool_max;
+
+	/* the CRUSH map specifies the mapping of placement groups to
+	 * the list of osds that store+replicate them. */
+	struct crush_map *crush;
+};
+
+/*
+ * file layout helpers
+ */
+#define ceph_file_layout_su(l) ((__s32)le32_to_cpu((l).fl_stripe_unit))
+#define ceph_file_layout_stripe_count(l) \
+	((__s32)le32_to_cpu((l).fl_stripe_count))
+#define ceph_file_layout_object_size(l) ((__s32)le32_to_cpu((l).fl_object_size))
+#define ceph_file_layout_cas_hash(l) ((__s32)le32_to_cpu((l).fl_cas_hash))
+#define ceph_file_layout_object_su(l) \
+	((__s32)le32_to_cpu((l).fl_object_stripe_unit))
+#define ceph_file_layout_pg_preferred(l) \
+	((__s32)le32_to_cpu((l).fl_pg_preferred))
+#define ceph_file_layout_pg_pool(l) \
+	((__s32)le32_to_cpu((l).fl_pg_pool))
+
+static inline unsigned ceph_file_layout_stripe_width(struct ceph_file_layout *l)
+{
+	return le32_to_cpu(l->fl_stripe_unit) *
+		le32_to_cpu(l->fl_stripe_count);
+}
+
+/* "period" == bytes before i start on a new set of objects */
+static inline unsigned ceph_file_layout_period(struct ceph_file_layout *l)
+{
+	return le32_to_cpu(l->fl_object_size) *
+		le32_to_cpu(l->fl_stripe_count);
+}
+
+
+static inline int ceph_osd_is_up(struct ceph_osdmap *map, int osd)
+{
+	return (osd < map->max_osd) && (map->osd_state[osd] & CEPH_OSD_UP);
+}
+
+static inline bool ceph_osdmap_flag(struct ceph_osdmap *map, int flag)
+{
+	return map && (map->flags & flag);
+}
+
+extern char *ceph_osdmap_state_str(char *str, int len, int state);
+
+static inline struct ceph_entity_addr *ceph_osd_addr(struct ceph_osdmap *map,
+						     int osd)
+{
+	if (osd >= map->max_osd)
+		return NULL;
+	return &map->osd_addr[osd];
+}
+
+extern struct ceph_osdmap *osdmap_decode(void **p, void *end);
+extern struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
+					    struct ceph_osdmap *map,
+					    struct ceph_messenger *msgr);
+extern void ceph_osdmap_destroy(struct ceph_osdmap *map);
+
+/* calculate mapping of a file extent to an object */
+extern void ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
+					  u64 off, u64 *plen,
+					  u64 *bno, u64 *oxoff, u64 *oxlen);
+
+/* calculate mapping of object to a placement group */
+extern int ceph_calc_object_layout(struct ceph_object_layout *ol,
+				   const char *oid,
+				   struct ceph_file_layout *fl,
+				   struct ceph_osdmap *osdmap);
+extern int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
+			       int *acting);
+extern int ceph_calc_pg_primary(struct ceph_osdmap *osdmap,
+				struct ceph_pg pgid);
+
+extern int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name);
+
+#endif
diff --git a/include/linux/ceph/pagelist.h b/include/linux/ceph/pagelist.h
new file mode 100644
index 0000000..9660d6b
--- /dev/null
+++ b/include/linux/ceph/pagelist.h
@@ -0,0 +1,75 @@
+#ifndef __FS_CEPH_PAGELIST_H
+#define __FS_CEPH_PAGELIST_H
+
+#include <linux/list.h>
+
+struct ceph_pagelist {
+	struct list_head head;
+	void *mapped_tail;
+	size_t length;
+	size_t room;
+	struct list_head free_list;
+	size_t num_pages_free;
+};
+
+struct ceph_pagelist_cursor {
+	struct ceph_pagelist *pl;   /* pagelist, for error checking */
+	struct list_head *page_lru; /* page in list */
+	size_t room;		    /* room remaining to reset to */
+};
+
+static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
+{
+	INIT_LIST_HEAD(&pl->head);
+	pl->mapped_tail = NULL;
+	pl->length = 0;
+	pl->room = 0;
+	INIT_LIST_HEAD(&pl->free_list);
+	pl->num_pages_free = 0;
+}
+
+extern int ceph_pagelist_release(struct ceph_pagelist *pl);
+
+extern int ceph_pagelist_append(struct ceph_pagelist *pl, const void *d, size_t l);
+
+extern int ceph_pagelist_reserve(struct ceph_pagelist *pl, size_t space);
+
+extern int ceph_pagelist_free_reserve(struct ceph_pagelist *pl);
+
+extern void ceph_pagelist_set_cursor(struct ceph_pagelist *pl,
+				     struct ceph_pagelist_cursor *c);
+
+extern int ceph_pagelist_truncate(struct ceph_pagelist *pl,
+				  struct ceph_pagelist_cursor *c);
+
+static inline int ceph_pagelist_encode_64(struct ceph_pagelist *pl, u64 v)
+{
+	__le64 ev = cpu_to_le64(v);
+	return ceph_pagelist_append(pl, &ev, sizeof(ev));
+}
+static inline int ceph_pagelist_encode_32(struct ceph_pagelist *pl, u32 v)
+{
+	__le32 ev = cpu_to_le32(v);
+	return ceph_pagelist_append(pl, &ev, sizeof(ev));
+}
+static inline int ceph_pagelist_encode_16(struct ceph_pagelist *pl, u16 v)
+{
+	__le16 ev = cpu_to_le16(v);
+	return ceph_pagelist_append(pl, &ev, sizeof(ev));
+}
+static inline int ceph_pagelist_encode_8(struct ceph_pagelist *pl, u8 v)
+{
+	return ceph_pagelist_append(pl, &v, 1);
+}
+static inline int ceph_pagelist_encode_string(struct ceph_pagelist *pl,
+					      char *s, size_t len)
+{
+	int ret = ceph_pagelist_encode_32(pl, len);
+	if (ret)
+		return ret;
+	if (len)
+		return ceph_pagelist_append(pl, s, len);
+	return 0;
+}
+
+#endif
diff --git a/fs/ceph/rados.h b/include/linux/ceph/rados.h
similarity index 100%
rename from fs/ceph/rados.h
rename to include/linux/ceph/rados.h
diff --git a/fs/ceph/types.h b/include/linux/ceph/types.h
similarity index 100%
rename from fs/ceph/types.h
rename to include/linux/ceph/types.h
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 0c99102..709dfb9 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -75,7 +75,7 @@
 
 	unsigned long flags;
 	/* ID for this css, if possible */
-	struct css_id *id;
+	struct css_id __rcu *id;
 };
 
 /* bits in struct cgroup_subsys_state flags field */
@@ -205,7 +205,7 @@
 	struct list_head children;	/* my children */
 
 	struct cgroup *parent;		/* my parent */
-	struct dentry *dentry;	  	/* cgroup fs entry, RCU protected */
+	struct dentry __rcu *dentry;	/* cgroup fs entry, RCU protected */
 
 	/* Private pointers for each registered subsystem */
 	struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index c1a62c5..320d6c9 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -16,7 +16,11 @@
 # define __release(x)	__context__(x,-1)
 # define __cond_lock(x,c)	((c) ? ({ __acquire(x); 1; }) : 0)
 # define __percpu	__attribute__((noderef, address_space(3)))
+#ifdef CONFIG_SPARSE_RCU_POINTER
+# define __rcu		__attribute__((noderef, address_space(4)))
+#else
 # define __rcu
+#endif
 extern void __chk_user_ptr(const volatile void __user *);
 extern void __chk_io_ptr(const volatile void __iomem *);
 #else
diff --git a/include/linux/coredump.h b/include/linux/coredump.h
index 8ba66a9..ba4b85a 100644
--- a/include/linux/coredump.h
+++ b/include/linux/coredump.h
@@ -9,37 +9,7 @@
  * These are the only things you should do on a core-file: use only these
  * functions to write out all the necessary info.
  */
-static inline int dump_write(struct file *file, const void *addr, int nr)
-{
-	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
-
-static inline int dump_seek(struct file *file, loff_t off)
-{
-	int ret = 1;
-
-	if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
-		if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
-			return 0;
-	} else {
-		char *buf = (char *)get_zeroed_page(GFP_KERNEL);
-
-		if (!buf)
-			return 0;
-		while (off > 0) {
-			unsigned long n = off;
-
-			if (n > PAGE_SIZE)
-				n = PAGE_SIZE;
-			if (!dump_write(file, buf, n)) {
-				ret = 0;
-				break;
-			}
-			off -= n;
-		}
-		free_page((unsigned long)buf);
-	}
-	return ret;
-}
+extern int dump_write(struct file *file, const void *addr, int nr);
+extern int dump_seek(struct file *file, loff_t off);
 
 #endif /* _LINUX_COREDUMP_H */
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 36ca972..1be416b 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -53,6 +53,7 @@
 #define CPUIDLE_FLAG_BALANCED	(0x40) /* medium latency, moderate savings */
 #define CPUIDLE_FLAG_DEEP	(0x80) /* high latency, large savings */
 #define CPUIDLE_FLAG_IGNORE	(0x100) /* ignore during this idle period */
+#define CPUIDLE_FLAG_TLB_FLUSHED (0x200) /* tlb will be flushed */
 
 #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
 
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 4d2c395..4aaeab3 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -84,7 +84,7 @@
 	atomic_t	usage;
 	pid_t		tgid;			/* thread group process ID */
 	spinlock_t	lock;
-	struct key	*session_keyring;	/* keyring inherited over fork */
+	struct key __rcu *session_keyring;	/* keyring inherited over fork */
 	struct key	*process_keyring;	/* keyring private to this process */
 	struct rcu_head	rcu;			/* RCU deletion hook */
 };
diff --git a/fs/ceph/crush/crush.h b/include/linux/crush/crush.h
similarity index 100%
rename from fs/ceph/crush/crush.h
rename to include/linux/crush/crush.h
diff --git a/fs/ceph/crush/hash.h b/include/linux/crush/hash.h
similarity index 100%
rename from fs/ceph/crush/hash.h
rename to include/linux/crush/hash.h
diff --git a/fs/ceph/crush/mapper.h b/include/linux/crush/mapper.h
similarity index 100%
rename from fs/ceph/crush/mapper.h
rename to include/linux/crush/mapper.h
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 7434a83..7187bd8 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -165,8 +165,10 @@
 	DCCPO_TIMESTAMP_ECHO = 42,
 	DCCPO_ELAPSED_TIME = 43,
 	DCCPO_MAX = 45,
-	DCCPO_MIN_CCID_SPECIFIC = 128,
-	DCCPO_MAX_CCID_SPECIFIC = 255,
+	DCCPO_MIN_RX_CCID_SPECIFIC = 128,	/* from sender to receiver */
+	DCCPO_MAX_RX_CCID_SPECIFIC = 191,
+	DCCPO_MIN_TX_CCID_SPECIFIC = 192,	/* from receiver to sender */
+	DCCPO_MAX_TX_CCID_SPECIFIC = 255,
 };
 /* maximum size of a single TLV-encoded DCCP option (sans type/len bytes) */
 #define DCCP_SINGLE_OPT_MAXLEN	253
diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h
index 29b3ce3..2833452 100644
--- a/include/linux/debug_locks.h
+++ b/include/linux/debug_locks.h
@@ -49,7 +49,6 @@
 
 #ifdef CONFIG_LOCKDEP
 extern void debug_show_all_locks(void);
-extern void __debug_show_held_locks(struct task_struct *task);
 extern void debug_show_held_locks(struct task_struct *task);
 extern void debug_check_no_locks_freed(const void *from, unsigned long len);
 extern void debug_check_no_locks_held(struct task_struct *task);
@@ -58,10 +57,6 @@
 {
 }
 
-static inline void __debug_show_held_locks(struct task_struct *task)
-{
-}
-
 static inline void debug_show_held_locks(struct task_struct *task)
 {
 }
diff --git a/include/linux/device.h b/include/linux/device.h
index 516feca..dd48953 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -751,4 +751,11 @@
 	MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))
 #define MODULE_ALIAS_CHARDEV_MAJOR(major) \
 	MODULE_ALIAS("char-major-" __stringify(major) "-*")
+
+#ifdef CONFIG_SYSFS_DEPRECATED
+extern long sysfs_deprecated;
+#else
+#define sysfs_deprecated 0
+#endif
+
 #endif /* _DEVICE_H_ */
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index 0b3518c..d4e02f5 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -48,10 +48,10 @@
  *
  * 0 if lock request was successful
  * -EAGAIN if request would block and is flagged DLM_LKF_NOQUEUE
- * -ENOMEM if there is no memory to process request
- * -EINVAL if there are invalid parameters
  * -DLM_EUNLOCK if unlock request was successful
  * -DLM_ECANCEL if a cancel completed successfully
+ * -EDEADLK if a deadlock was detected
+ * -ETIMEDOUT if the lock request was canceled due to a timeout
  */
 
 #define DLM_SBF_DEMOTED		0x01
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index c61d4ca..e210649 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -548,7 +548,7 @@
 	return (dma->max_pq & DMA_HAS_PQ_CONTINUE) == DMA_HAS_PQ_CONTINUE;
 }
 
-static unsigned short dma_dev_to_maxpq(struct dma_device *dma)
+static inline unsigned short dma_dev_to_maxpq(struct dma_device *dma)
 {
 	return dma->max_pq & ~DMA_HAS_PQ_CONTINUE;
 }
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index d7cecc9..a7d9dc2 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -57,15 +57,15 @@
 extern int dmar_dev_scope_init(void);
 
 /* Intel IOMMU detection */
-extern void detect_intel_iommu(void);
+extern int detect_intel_iommu(void);
 extern int enable_drhd_fault_handling(void);
 
 extern int parse_ioapics_under_ir(void);
 extern int alloc_iommu(struct dmar_drhd_unit *);
 #else
-static inline void detect_intel_iommu(void)
+static inline int detect_intel_iommu(void)
 {
-	return;
+	return -ENODEV;
 }
 
 static inline int dmar_table_init(void)
@@ -106,6 +106,7 @@
 		__u64 high;
 	};
 };
+
 #ifdef CONFIG_INTR_REMAP
 extern int intr_remapping_enabled;
 extern int intr_remapping_supported(void);
@@ -119,11 +120,8 @@
 extern int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index,
    			u16 sub_handle);
 extern int map_irq_to_irte_handle(int irq, u16 *sub_handle);
-extern int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index);
-extern int flush_irte(int irq);
 extern int free_irte(int irq);
 
-extern int irq_remapped(int irq);
 extern struct intel_iommu *map_dev_to_ir(struct pci_dev *dev);
 extern struct intel_iommu *map_ioapic_to_ir(int apic);
 extern struct intel_iommu *map_hpet_to_ir(u8 id);
@@ -177,7 +175,6 @@
 	return 0;
 }
 
-#define irq_remapped(irq)		(0)
 #define enable_intr_remapping(mode)	(-1)
 #define disable_intr_remapping()	(0)
 #define reenable_intr_remapping(mode)	(0)
@@ -187,8 +184,9 @@
 /* Can't use the common MSI interrupt functions
  * since DMAR is not a pci device
  */
-extern void dmar_msi_unmask(unsigned int irq);
-extern void dmar_msi_mask(unsigned int irq);
+struct irq_data;
+extern void dmar_msi_unmask(struct irq_data *data);
+extern void dmar_msi_mask(struct irq_data *data);
 extern void dmar_msi_read(int irq, struct msi_msg *msg);
 extern void dmar_msi_write(int irq, struct msi_msg *msg);
 extern int dmar_set_interrupt(struct intel_iommu *iommu);
diff --git a/include/linux/drbd.h b/include/linux/drbd.h
index 479ee3a..9b2a015 100644
--- a/include/linux/drbd.h
+++ b/include/linux/drbd.h
@@ -53,10 +53,10 @@
 
 
 extern const char *drbd_buildtag(void);
-#define REL_VERSION "8.3.8.1"
+#define REL_VERSION "8.3.9rc2"
 #define API_VERSION 88
 #define PRO_VERSION_MIN 86
-#define PRO_VERSION_MAX 94
+#define PRO_VERSION_MAX 95
 
 
 enum drbd_io_error_p {
@@ -91,6 +91,11 @@
 	ASB_VIOLENTLY
 };
 
+enum drbd_on_no_data {
+	OND_IO_ERROR,
+	OND_SUSPEND_IO
+};
+
 /* KEEP the order, do not delete or insert. Only append. */
 enum drbd_ret_codes {
 	ERR_CODE_BASE		= 100,
@@ -140,6 +145,7 @@
 	ERR_CONNECTED		= 151, /* DRBD 8.3 only */
 	ERR_PERM		= 152,
 	ERR_NEED_APV_93		= 153,
+	ERR_STONITH_AND_PROT_A  = 154,
 
 	/* insert new ones above this line */
 	AFTER_LAST_ERR_CODE
@@ -226,13 +232,17 @@
 		unsigned conn:5 ;   /* 17/32	 cstates */
 		unsigned disk:4 ;   /* 8/16	 from D_DISKLESS to D_UP_TO_DATE */
 		unsigned pdsk:4 ;   /* 8/16	 from D_DISKLESS to D_UP_TO_DATE */
-		unsigned susp:1 ;   /* 2/2	 IO suspended  no/yes */
+		unsigned susp:1 ;   /* 2/2	 IO suspended no/yes (by user) */
 		unsigned aftr_isp:1 ; /* isp .. imposed sync pause */
 		unsigned peer_isp:1 ;
 		unsigned user_isp:1 ;
-		unsigned _pad:11;   /* 0	 unused */
+		unsigned susp_nod:1 ; /* IO suspended because no data */
+		unsigned susp_fen:1 ; /* IO suspended because fence peer handler runs*/
+		unsigned _pad:9;   /* 0	 unused */
 #elif defined(__BIG_ENDIAN_BITFIELD)
-		unsigned _pad:11;   /* 0	 unused */
+		unsigned _pad:9;
+		unsigned susp_fen:1 ;
+		unsigned susp_nod:1 ;
 		unsigned user_isp:1 ;
 		unsigned peer_isp:1 ;
 		unsigned aftr_isp:1 ; /* isp .. imposed sync pause */
@@ -312,6 +322,8 @@
 
 #define DRBD_MAGIC 0x83740267
 #define BE_DRBD_MAGIC __constant_cpu_to_be32(DRBD_MAGIC)
+#define DRBD_MAGIC_BIG 0x835a
+#define BE_DRBD_MAGIC_BIG __constant_cpu_to_be16(DRBD_MAGIC_BIG)
 
 /* these are of type "int" */
 #define DRBD_MD_INDEX_INTERNAL -1
diff --git a/include/linux/drbd_limits.h b/include/linux/drbd_limits.h
index 440b42e..4ac33f3 100644
--- a/include/linux/drbd_limits.h
+++ b/include/linux/drbd_limits.h
@@ -128,26 +128,31 @@
 #define DRBD_AFTER_SB_1P_DEF ASB_DISCONNECT
 #define DRBD_AFTER_SB_2P_DEF ASB_DISCONNECT
 #define DRBD_RR_CONFLICT_DEF ASB_DISCONNECT
+#define DRBD_ON_NO_DATA_DEF OND_IO_ERROR
 
 #define DRBD_MAX_BIO_BVECS_MIN 0
 #define DRBD_MAX_BIO_BVECS_MAX 128
 #define DRBD_MAX_BIO_BVECS_DEF 0
 
-#define DRBD_DP_VOLUME_MIN 4
-#define DRBD_DP_VOLUME_MAX 1048576
-#define DRBD_DP_VOLUME_DEF 16384
+#define DRBD_C_PLAN_AHEAD_MIN  0
+#define DRBD_C_PLAN_AHEAD_MAX  300
+#define DRBD_C_PLAN_AHEAD_DEF  0 /* RS rate controller disabled by default */
 
-#define DRBD_DP_INTERVAL_MIN 1
-#define DRBD_DP_INTERVAL_MAX 600
-#define DRBD_DP_INTERVAL_DEF 5
+#define DRBD_C_DELAY_TARGET_MIN 1
+#define DRBD_C_DELAY_TARGET_MAX 100
+#define DRBD_C_DELAY_TARGET_DEF 10
 
-#define DRBD_RS_THROTTLE_TH_MIN 1
-#define DRBD_RS_THROTTLE_TH_MAX 600
-#define DRBD_RS_THROTTLE_TH_DEF 20
+#define DRBD_C_FILL_TARGET_MIN 0
+#define DRBD_C_FILL_TARGET_MAX (1<<20) /* 500MByte in sec */
+#define DRBD_C_FILL_TARGET_DEF 0 /* By default disabled -> controlled by delay_target */
 
-#define DRBD_RS_HOLD_OFF_TH_MIN 1
-#define DRBD_RS_HOLD_OFF_TH_MAX 6000
-#define DRBD_RS_HOLD_OFF_TH_DEF 100
+#define DRBD_C_MAX_RATE_MIN     250 /* kByte/sec */
+#define DRBD_C_MAX_RATE_MAX     (4 << 20)
+#define DRBD_C_MAX_RATE_DEF     102400
+
+#define DRBD_C_MIN_RATE_MIN     0 /* kByte/sec */
+#define DRBD_C_MIN_RATE_MAX     (4 << 20)
+#define DRBD_C_MIN_RATE_DEF     4096
 
 #undef RANGE
 #endif
diff --git a/include/linux/drbd_nl.h b/include/linux/drbd_nl.h
index 5f04281..ade9110 100644
--- a/include/linux/drbd_nl.h
+++ b/include/linux/drbd_nl.h
@@ -87,6 +87,12 @@
 	NL_STRING(      51,     T_MAY_IGNORE,   cpu_mask,       32)
 	NL_STRING(	64,	T_MAY_IGNORE,	csums_alg,	SHARED_SECRET_MAX)
 	NL_BIT(         65,     T_MAY_IGNORE,   use_rle)
+	NL_INTEGER(	75,	T_MAY_IGNORE,	on_no_data)
+	NL_INTEGER(	76,	T_MAY_IGNORE,	c_plan_ahead)
+	NL_INTEGER(     77,	T_MAY_IGNORE,	c_delay_target)
+	NL_INTEGER(     78,	T_MAY_IGNORE,	c_fill_target)
+	NL_INTEGER(     79,	T_MAY_IGNORE,	c_max_rate)
+	NL_INTEGER(     80,	T_MAY_IGNORE,	c_min_rate)
 )
 
 NL_PACKET(invalidate, 9, )
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 52c0da4..a90b389 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -1,6 +1,8 @@
 #ifndef _DYNAMIC_DEBUG_H
 #define _DYNAMIC_DEBUG_H
 
+#include <linux/jump_label.h>
+
 /* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
  * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
  * use independent hash functions, to reduce the chance of false positives.
@@ -22,8 +24,6 @@
 	const char *function;
 	const char *filename;
 	const char *format;
-	char primary_hash;
-	char secondary_hash;
 	unsigned int lineno:24;
 	/*
  	 * The flags field controls the behaviour at the callsite.
@@ -33,6 +33,7 @@
 #define _DPRINTK_FLAGS_PRINT   (1<<0)  /* printk() a message using the format */
 #define _DPRINTK_FLAGS_DEFAULT 0
 	unsigned int flags:8;
+	char enabled;
 } __attribute__((aligned(8)));
 
 
@@ -42,33 +43,35 @@
 #if defined(CONFIG_DYNAMIC_DEBUG)
 extern int ddebug_remove_module(const char *mod_name);
 
-#define __dynamic_dbg_enabled(dd)  ({	     \
-	int __ret = 0;							     \
-	if (unlikely((dynamic_debug_enabled & (1LL << DEBUG_HASH)) &&	     \
-			(dynamic_debug_enabled2 & (1LL << DEBUG_HASH2))))   \
-				if (unlikely(dd.flags))			     \
-					__ret = 1;			     \
-	__ret; })
-
 #define dynamic_pr_debug(fmt, ...) do {					\
+	__label__ do_printk;						\
+	__label__ out;							\
 	static struct _ddebug descriptor				\
 	__used								\
 	__attribute__((section("__verbose"), aligned(8))) =		\
-	{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH,	\
-		DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT };	\
-	if (__dynamic_dbg_enabled(descriptor))				\
-		printk(KERN_DEBUG pr_fmt(fmt),	##__VA_ARGS__);		\
+	{ KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__,		\
+		_DPRINTK_FLAGS_DEFAULT };				\
+	JUMP_LABEL(&descriptor.enabled, do_printk);			\
+	goto out;							\
+do_printk:								\
+	printk(KERN_DEBUG pr_fmt(fmt),	##__VA_ARGS__);			\
+out:	;								\
 	} while (0)
 
 
 #define dynamic_dev_dbg(dev, fmt, ...) do {				\
+	__label__ do_printk;						\
+	__label__ out;							\
 	static struct _ddebug descriptor				\
 	__used								\
 	__attribute__((section("__verbose"), aligned(8))) =		\
-	{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH,	\
-		DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT };	\
-	if (__dynamic_dbg_enabled(descriptor))				\
-		dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__);	\
+	{ KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__,		\
+		_DPRINTK_FLAGS_DEFAULT };				\
+	JUMP_LABEL(&descriptor.enabled, do_printk);			\
+	goto out;							\
+do_printk:								\
+	dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__);		\
+out:	;								\
 	} while (0)
 
 #else
@@ -80,7 +83,7 @@
 
 #define dynamic_pr_debug(fmt, ...)					\
 	do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)
-#define dynamic_dev_dbg(dev, format, ...)				\
+#define dynamic_dev_dbg(dev, fmt, ...)					\
 	do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0)
 #endif
 
diff --git a/include/linux/early_res.h b/include/linux/early_res.h
deleted file mode 100644
index 29c09f5..0000000
--- a/include/linux/early_res.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _LINUX_EARLY_RES_H
-#define _LINUX_EARLY_RES_H
-#ifdef __KERNEL__
-
-extern void reserve_early(u64 start, u64 end, char *name);
-extern void reserve_early_overlap_ok(u64 start, u64 end, char *name);
-extern void free_early(u64 start, u64 end);
-void free_early_partial(u64 start, u64 end);
-extern void early_res_to_bootmem(u64 start, u64 end);
-
-void reserve_early_without_check(u64 start, u64 end, char *name);
-u64 find_early_area(u64 ei_start, u64 ei_last, u64 start, u64 end,
-			 u64 size, u64 align);
-u64 find_early_area_size(u64 ei_start, u64 ei_last, u64 start,
-			 u64 *sizep, u64 align);
-u64 find_fw_memmap_area(u64 start, u64 end, u64 size, u64 align);
-u64 get_max_mapped(void);
-#include <linux/range.h>
-int get_free_all_memory_range(struct range **rangep, int nodeid);
-
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_EARLY_RES_H */
diff --git a/include/linux/edac.h b/include/linux/edac.h
index 7cf92e8..36c6644 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -13,6 +13,7 @@
 #define _LINUX_EDAC_H_
 
 #include <asm/atomic.h>
+#include <linux/sysdev.h>
 
 #define EDAC_OPSTATE_INVAL	-1
 #define EDAC_OPSTATE_POLL	0
@@ -22,9 +23,12 @@
 extern int edac_op_state;
 extern int edac_err_assert;
 extern atomic_t edac_handlers;
+extern struct sysdev_class edac_class;
 
 extern int edac_handler_set(void);
 extern void edac_atomic_assert_error(void);
+extern struct sysdev_class *edac_get_sysfs_class(void);
+extern void edac_put_sysfs_class(void);
 
 static inline void opstate_init(void)
 {
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 926b503..80a0ece 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -93,6 +93,7 @@
 	struct elevator_type *elevator_type;
 	struct mutex sysfs_lock;
 	struct hlist_head *hash;
+	unsigned int registered:1;
 };
 
 /*
@@ -121,6 +122,8 @@
 extern int elv_set_request(struct request_queue *, struct request *, gfp_t);
 extern void elv_put_request(struct request_queue *, struct request *);
 extern void elv_drain_elevator(struct request_queue *);
+extern void elv_quiesce_start(struct request_queue *);
+extern void elv_quiesce_end(struct request_queue *);
 
 /*
  * io scheduler registration
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 2308fbb..f16a010 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -71,7 +71,7 @@
  */
 static inline int is_multicast_ether_addr(const u8 *addr)
 {
-	return (0x01 & addr[0]);
+	return 0x01 & addr[0];
 }
 
 /**
@@ -82,7 +82,7 @@
  */
 static inline int is_local_ether_addr(const u8 *addr)
 {
-	return (0x02 & addr[0]);
+	return 0x02 & addr[0];
 }
 
 /**
@@ -237,13 +237,29 @@
  * entry points.
  */
 
-static inline int compare_ether_header(const void *a, const void *b)
+static inline unsigned long compare_ether_header(const void *a, const void *b)
 {
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+	unsigned long fold;
+
+	/*
+	 * We want to compare 14 bytes:
+	 *  [a0 ... a13] ^ [b0 ... b13]
+	 * Use two long XOR, ORed together, with an overlap of two bytes.
+	 *  [a0  a1  a2  a3  a4  a5  a6  a7 ] ^ [b0  b1  b2  b3  b4  b5  b6  b7 ] |
+	 *  [a6  a7  a8  a9  a10 a11 a12 a13] ^ [b6  b7  b8  b9  b10 b11 b12 b13]
+	 * This means the [a6 a7] ^ [b6 b7] part is done two times.
+	*/
+	fold = *(unsigned long *)a ^ *(unsigned long *)b;
+	fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6);
+	return fold;
+#else
 	u32 *a32 = (u32 *)((u8 *)a + 2);
 	u32 *b32 = (u32 *)((u8 *)b + 2);
 
 	return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) |
 	       (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]);
+#endif
 }
 
 #endif	/* _LINUX_ETHERDEVICE_H */
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 991269e..6628a50 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -14,6 +14,7 @@
 #define _LINUX_ETHTOOL_H
 
 #include <linux/types.h>
+#include <linux/if_ether.h>
 
 /* This should work for both 32 and 64 bit userland. */
 struct ethtool_cmd {
@@ -308,15 +309,28 @@
  * flag differs from the read-only value.
  */
 enum ethtool_flags {
+	ETH_FLAG_TXVLAN		= (1 << 7),	/* TX VLAN offload enabled */
+	ETH_FLAG_RXVLAN		= (1 << 8),	/* RX VLAN offload enabled */
 	ETH_FLAG_LRO		= (1 << 15),	/* LRO is enabled */
 	ETH_FLAG_NTUPLE		= (1 << 27),	/* N-tuple filters enabled */
 	ETH_FLAG_RXHASH		= (1 << 28),
 };
 
 /* The following structures are for supporting RX network flow
- * classification configuration. Note, all multibyte fields, e.g.,
- * ip4src, ip4dst, psrc, pdst, spi, etc. are expected to be in network
- * byte order.
+ * classification and RX n-tuple configuration. Note, all multibyte
+ * fields, e.g., ip4src, ip4dst, psrc, pdst, spi, etc. are expected to
+ * be in network byte order.
+ */
+
+/**
+ * struct ethtool_tcpip4_spec - flow specification for TCP/IPv4 etc.
+ * @ip4src: Source host
+ * @ip4dst: Destination host
+ * @psrc: Source port
+ * @pdst: Destination port
+ * @tos: Type-of-service
+ *
+ * This can be used to specify a TCP/IPv4, UDP/IPv4 or SCTP/IPv4 flow.
  */
 struct ethtool_tcpip4_spec {
 	__be32	ip4src;
@@ -326,6 +340,15 @@
 	__u8    tos;
 };
 
+/**
+ * struct ethtool_ah_espip4_spec - flow specification for IPsec/IPv4
+ * @ip4src: Source host
+ * @ip4dst: Destination host
+ * @spi: Security parameters index
+ * @tos: Type-of-service
+ *
+ * This can be used to specify an IPsec transport or tunnel over IPv4.
+ */
 struct ethtool_ah_espip4_spec {
 	__be32	ip4src;
 	__be32	ip4dst;
@@ -333,21 +356,17 @@
 	__u8    tos;
 };
 
-struct ethtool_rawip4_spec {
-	__be32	ip4src;
-	__be32	ip4dst;
-	__u8	hdata[64];
-};
-
-struct ethtool_ether_spec {
-	__be16	ether_type;
-	__u8	frame_size;
-	__u8	eframe[16];
-};
-
 #define	ETH_RX_NFC_IP4	1
-#define	ETH_RX_NFC_IP6	2
 
+/**
+ * struct ethtool_usrip4_spec - general flow specification for IPv4
+ * @ip4src: Source host
+ * @ip4dst: Destination host
+ * @l4_4_bytes: First 4 bytes of transport (layer 4) header
+ * @tos: Type-of-service
+ * @ip_ver: Value must be %ETH_RX_NFC_IP4; mask must be 0
+ * @proto: Transport protocol number; mask must be 0
+ */
 struct ethtool_usrip4_spec {
 	__be32	ip4src;
 	__be32	ip4dst;
@@ -357,6 +376,15 @@
 	__u8    proto;
 };
 
+/**
+ * struct ethtool_rx_flow_spec - specification for RX flow filter
+ * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW
+ * @h_u: Flow fields to match (dependent on @flow_type)
+ * @m_u: Masks for flow field bits to be ignored
+ * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC
+ *	if packets should be discarded
+ * @location: Index of filter in hardware table
+ */
 struct ethtool_rx_flow_spec {
 	__u32		flow_type;
 	union {
@@ -365,36 +393,91 @@
 		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_rawip4_spec		raw_ip4_spec;
-		struct ethtool_ether_spec		ether_spec;
 		struct ethtool_usrip4_spec		usr_ip4_spec;
-		__u8					hdata[64];
-	} h_u, m_u; /* entry, mask */
+		struct ethhdr				ether_spec;
+		__u8					hdata[72];
+	} h_u, m_u;
 	__u64		ring_cookie;
 	__u32		location;
 };
 
+/**
+ * struct ethtool_rxnfc - command to get or set RX flow classification rules
+ * @cmd: Specific command number - %ETHTOOL_GRXFH, %ETHTOOL_SRXFH,
+ *	%ETHTOOL_GRXRINGS, %ETHTOOL_GRXCLSRLCNT, %ETHTOOL_GRXCLSRULE,
+ *	%ETHTOOL_GRXCLSRLALL, %ETHTOOL_SRXCLSRLDEL or %ETHTOOL_SRXCLSRLINS
+ * @flow_type: Type of flow to be affected, e.g. %TCP_V4_FLOW
+ * @data: Command-dependent value
+ * @fs: Flow filter specification
+ * @rule_cnt: Number of rules to be affected
+ * @rule_locs: Array of valid rule indices
+ *
+ * For %ETHTOOL_GRXFH and %ETHTOOL_SRXFH, @data is a bitmask indicating
+ * the fields included in the flow hash, e.g. %RXH_IP_SRC.  The following
+ * structure fields must not be used.
+ *
+ * For %ETHTOOL_GRXRINGS, @data is set to the number of RX rings/queues
+ * on return.
+ *
+ * For %ETHTOOL_GRXCLSRLCNT, @rule_cnt is set to the number of defined
+ * rules on return.
+ *
+ * For %ETHTOOL_GRXCLSRULE, @fs.@location specifies the index of an
+ * existing filter rule on entry and @fs contains the rule on return.
+ *
+ * For %ETHTOOL_GRXCLSRLALL, @rule_cnt specifies the array size of the
+ * user buffer for @rule_locs on entry.  On return, @data is the size
+ * of the filter table and @rule_locs contains the indices of the
+ * defined rules.
+ *
+ * For %ETHTOOL_SRXCLSRLINS, @fs specifies the filter rule to add or
+ * update.  @fs.@location specifies the index to use and must not be
+ * ignored.
+ *
+ * For %ETHTOOL_SRXCLSRLDEL, @fs.@location specifies the index of an
+ * existing filter rule on entry.
+ *
+ * Implementation of indexed classification rules generally requires a
+ * TCAM.
+ */
 struct ethtool_rxnfc {
 	__u32				cmd;
 	__u32				flow_type;
-	/* The rx flow hash value or the rule DB size */
 	__u64				data;
-	/* The following fields are not valid and must not be used for
-	 * the ETHTOOL_{G,X}RXFH commands. */
 	struct ethtool_rx_flow_spec	fs;
 	__u32				rule_cnt;
 	__u32				rule_locs[0];
 };
 
+/**
+ * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection
+ * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR
+ * @size: On entry, the array size of the user buffer.  On return from
+ *	%ETHTOOL_GRXFHINDIR, the array size of the hardware indirection table.
+ * @ring_index: RX ring/queue index for each hash value
+ */
 struct ethtool_rxfh_indir {
 	__u32	cmd;
-	/* On entry, this is the array size of the user buffer.  On
-	 * return from ETHTOOL_GRXFHINDIR, this is the array size of
-	 * the hardware indirection table. */
 	__u32	size;
-	__u32	ring_index[0];	/* ring/queue index for each hash value */
+	__u32	ring_index[0];
 };
 
+/**
+ * struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter
+ * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW
+ * @h_u: Flow field values to match (dependent on @flow_type)
+ * @m_u: Masks for flow field value bits to be ignored
+ * @vlan_tag: VLAN tag to match
+ * @vlan_tag_mask: Mask for VLAN tag bits to be ignored
+ * @data: Driver-dependent data to match
+ * @data_mask: Mask for driver-dependent data bits to be ignored
+ * @action: RX ring/queue index to deliver to (non-negative) or other action
+ *	(negative, e.g. %ETHTOOL_RXNTUPLE_ACTION_DROP)
+ *
+ * For flow types %TCP_V4_FLOW, %UDP_V4_FLOW and %SCTP_V4_FLOW, where
+ * a field value and mask are both zero this is treated as if all mask
+ * bits are set i.e. the field is ignored.
+ */
 struct ethtool_rx_ntuple_flow_spec {
 	__u32		 flow_type;
 	union {
@@ -403,22 +486,26 @@
 		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_rawip4_spec		raw_ip4_spec;
-		struct ethtool_ether_spec		ether_spec;
 		struct ethtool_usrip4_spec		usr_ip4_spec;
-		__u8					hdata[64];
-	} h_u, m_u; /* entry, mask */
+		struct ethhdr				ether_spec;
+		__u8					hdata[72];
+	} h_u, m_u;
 
 	__u16	        vlan_tag;
 	__u16	        vlan_tag_mask;
-	__u64		data;      /* user-defined flow spec data */
-	__u64		data_mask; /* user-defined flow spec mask */
+	__u64		data;
+	__u64		data_mask;
 
-	/* signed to distinguish between queue and actions (DROP) */
 	__s32		action;
-#define ETHTOOL_RXNTUPLE_ACTION_DROP -1
+#define ETHTOOL_RXNTUPLE_ACTION_DROP	(-1)	/* drop packet */
+#define ETHTOOL_RXNTUPLE_ACTION_CLEAR	(-2)	/* clear filter */
 };
 
+/**
+ * struct ethtool_rx_ntuple - command to set or clear RX flow filter
+ * @cmd: Command number - %ETHTOOL_SRXNTUPLE
+ * @fs: Flow filter specification
+ */
 struct ethtool_rx_ntuple {
 	__u32					cmd;
 	struct ethtool_rx_ntuple_flow_spec	fs;
@@ -759,22 +846,23 @@
 #define WAKE_MAGIC		(1 << 5)
 #define WAKE_MAGICSECURE	(1 << 6) /* only meaningful if WAKE_MAGIC */
 
-/* L3-L4 network traffic flow types */
-#define	TCP_V4_FLOW	0x01
-#define	UDP_V4_FLOW	0x02
-#define	SCTP_V4_FLOW	0x03
-#define	AH_ESP_V4_FLOW	0x04
-#define	TCP_V6_FLOW	0x05
-#define	UDP_V6_FLOW	0x06
-#define	SCTP_V6_FLOW	0x07
-#define	AH_ESP_V6_FLOW	0x08
-#define	AH_V4_FLOW	0x09
-#define	ESP_V4_FLOW	0x0a
-#define	AH_V6_FLOW	0x0b
-#define	ESP_V6_FLOW	0x0c
-#define	IP_USER_FLOW	0x0d
-#define	IPV4_FLOW	0x10
-#define	IPV6_FLOW	0x11
+/* L2-L4 network traffic flow types */
+#define	TCP_V4_FLOW	0x01	/* hash or spec (tcp_ip4_spec) */
+#define	UDP_V4_FLOW	0x02	/* hash or spec (udp_ip4_spec) */
+#define	SCTP_V4_FLOW	0x03	/* hash or spec (sctp_ip4_spec) */
+#define	AH_ESP_V4_FLOW	0x04	/* hash only */
+#define	TCP_V6_FLOW	0x05	/* hash only */
+#define	UDP_V6_FLOW	0x06	/* hash only */
+#define	SCTP_V6_FLOW	0x07	/* hash only */
+#define	AH_ESP_V6_FLOW	0x08	/* hash only */
+#define	AH_V4_FLOW	0x09	/* hash or spec (ah_ip4_spec) */
+#define	ESP_V4_FLOW	0x0a	/* hash or spec (esp_ip4_spec) */
+#define	AH_V6_FLOW	0x0b	/* hash only */
+#define	ESP_V6_FLOW	0x0c	/* hash only */
+#define	IP_USER_FLOW	0x0d	/* spec only (usr_ip4_spec) */
+#define	IPV4_FLOW	0x10	/* hash only */
+#define	IPV6_FLOW	0x11	/* hash only */
+#define	ETHER_FLOW	0x12	/* spec only (ether_spec) */
 
 /* L3-L4 network traffic flow hash options */
 #define	RXH_L2DA	(1 << 1)
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index a9cd507..2802898 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -67,6 +67,19 @@
 	 * 32 bit parent block number, 32 bit parent generation number
 	 */
 	FILEID_UDF_WITH_PARENT = 0x52,
+
+	/*
+	 * 64 bit checkpoint number, 64 bit inode number,
+	 * 32 bit generation number.
+	 */
+	FILEID_NILFS_WITHOUT_PARENT = 0x61,
+
+	/*
+	 * 64 bit checkpoint number, 64 bit inode number,
+	 * 32 bit generation number, 32 bit parent generation.
+	 * 64 bit parent inode number.
+	 */
+	FILEID_NILFS_WITH_PARENT = 0x62,
 };
 
 struct fid {
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index f59ed29..133c0ba 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -31,7 +31,7 @@
 
 struct fdtable {
 	unsigned int max_fds;
-	struct file ** fd;      /* current fd array */
+	struct file __rcu **fd;      /* current fd array */
 	fd_set *close_on_exec;
 	fd_set *open_fds;
 	struct rcu_head rcu;
@@ -46,7 +46,7 @@
    * read mostly part
    */
 	atomic_t count;
-	struct fdtable *fdt;
+	struct fdtable __rcu *fdt;
 	struct fdtable fdtab;
   /*
    * written part on a separate cache line in SMP
@@ -55,7 +55,7 @@
 	int next_fd;
 	struct embedded_fd_set close_on_exec_init;
 	struct embedded_fd_set open_fds_init;
-	struct file * fd_array[NR_OPEN_DEFAULT];
+	struct file __rcu * fd_array[NR_OPEN_DEFAULT];
 };
 
 #define rcu_dereference_check_fdtable(files, fdtfd) \
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 63d069b..4f34ff6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -135,12 +135,12 @@
  *			immediately after submission. The write equivalent
  *			of READ_SYNC.
  * WRITE_ODIRECT_PLUG	Special case write for O_DIRECT only.
- * WRITE_BARRIER	Like WRITE_SYNC, but tells the block layer that all
- *			previously submitted writes must be safely on storage
- *			before this one is started. Also guarantees that when
- *			this write is complete, it itself is also safely on
- *			storage. Prevents reordering of writes on both sides
- *			of this IO.
+ * WRITE_FLUSH		Like WRITE_SYNC but with preceding cache flush.
+ * WRITE_FUA		Like WRITE_SYNC but data is guaranteed to be on
+ *			non-volatile media on completion.
+ * WRITE_FLUSH_FUA	Combination of WRITE_FLUSH and FUA. The IO is preceded
+ *			by a cache flush and data is guaranteed to be on
+ *			non-volatile media on completion.
  *
  */
 #define RW_MASK			REQ_WRITE
@@ -156,16 +156,12 @@
 #define WRITE_SYNC		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG)
 #define WRITE_ODIRECT_PLUG	(WRITE | REQ_SYNC)
 #define WRITE_META		(WRITE | REQ_META)
-#define WRITE_BARRIER		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \
-				 REQ_HARDBARRIER)
-
-/*
- * These aren't really reads or writes, they pass down information about
- * parts of device that are now unused by the file system.
- */
-#define DISCARD_NOBARRIER	(WRITE | REQ_DISCARD)
-#define DISCARD_BARRIER		(WRITE | REQ_DISCARD | REQ_HARDBARRIER)
-#define DISCARD_SECURE		(DISCARD_NOBARRIER | REQ_SECURE)
+#define WRITE_FLUSH		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \
+				 REQ_FLUSH)
+#define WRITE_FUA		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \
+				 REQ_FUA)
+#define WRITE_FLUSH_FUA		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \
+				 REQ_FLUSH | REQ_FUA)
 
 #define SEL_IN		1
 #define SEL_OUT		2
@@ -1093,10 +1089,6 @@
 
 #include <linux/fcntl.h>
 
-/* temporary stubs for BKL removal */
-#define lock_flocks() lock_kernel()
-#define unlock_flocks() unlock_kernel()
-
 extern void send_sigio(struct fown_struct *fown, int fd, int band);
 
 #ifdef CONFIG_FILE_LOCKING
@@ -1135,6 +1127,8 @@
 extern int lease_modify(struct file_lock **, int);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
 extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
+extern void lock_flocks(void);
+extern void unlock_flocks(void);
 #else /* !CONFIG_FILE_LOCKING */
 static inline int fcntl_getlk(struct file *file, struct flock __user *user)
 {
@@ -1277,6 +1271,14 @@
 	return 1;
 }
 
+static inline void lock_flocks(void)
+{
+}
+
+static inline void unlock_flocks(void)
+{
+}
+
 #endif /* !CONFIG_FILE_LOCKING */
 
 
@@ -1384,7 +1386,7 @@
 	 * Saved mount options for lazy filesystems using
 	 * generic_show_options()
 	 */
-	char *s_options;
+	char __rcu *s_options;
 };
 
 extern struct timespec current_fs_time(struct super_block *sb);
@@ -2378,6 +2380,8 @@
 
 extern int generic_file_fsync(struct file *, int);
 
+extern int generic_check_addressable(unsigned, u64);
+
 #ifdef CONFIG_MIGRATION
 extern int buffer_migrate_page(struct address_space *,
 				struct page *, struct page *);
@@ -2454,6 +2458,7 @@
 	.release = simple_attr_release,					\
 	.read	 = simple_attr_read,					\
 	.write	 = simple_attr_write,					\
+	.llseek	 = generic_file_llseek,					\
 };
 
 static inline void __attribute__((format(printf, 1, 2)))
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 28e33fe..4eb56ed 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -58,17 +58,35 @@
 	FSL_USB2_PHY_SERIAL,
 };
 
+struct clk;
+struct platform_device;
+
 struct fsl_usb2_platform_data {
 	/* board specific information */
 	enum fsl_usb2_operating_modes	operating_mode;
 	enum fsl_usb2_phy_modes		phy_mode;
 	unsigned int			port_enables;
+	unsigned int			workaround;
+
+	int		(*init)(struct platform_device *);
+	void		(*exit)(struct platform_device *);
+	void __iomem	*regs;		/* ioremap'd register base */
+	struct clk	*clk;
+	unsigned	big_endian_mmio:1;
+	unsigned	big_endian_desc:1;
+	unsigned	es:1;		/* need USBMODE:ES */
+	unsigned	le_setup_buf:1;
+	unsigned	have_sysif_regs:1;
+	unsigned	invert_drvvbus:1;
+	unsigned	invert_pwr_fault:1;
 };
 
 /* Flags in fsl_usb2_mph_platform_data */
 #define FSL_USB2_PORT0_ENABLED	0x00000001
 #define FSL_USB2_PORT1_ENABLED	0x00000002
 
+#define FLS_USB2_WORKAROUND_ENGCM09152	(1 << 0)
+
 struct spi_device;
 
 struct fsl_spi_platform_data {
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 02b8b24..8beabb9 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -191,8 +191,8 @@
 	unsigned int		flags;
 
 #ifdef CONFIG_PERF_EVENTS
-	int			perf_refcount;
-	struct hlist_head	*perf_events;
+	int				perf_refcount;
+	struct hlist_head __percpu	*perf_events;
 #endif
 };
 
@@ -252,8 +252,8 @@
 
 extern int  perf_trace_init(struct perf_event *event);
 extern void perf_trace_destroy(struct perf_event *event);
-extern int  perf_trace_enable(struct perf_event *event);
-extern void perf_trace_disable(struct perf_event *event);
+extern int  perf_trace_add(struct perf_event *event, int flags);
+extern void perf_trace_del(struct perf_event *event, int flags);
 extern int  ftrace_profile_set_filter(struct perf_event *event, int event_id,
 				     char *filter_str);
 extern void ftrace_profile_free_filter(struct perf_event *event);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 5f2f4c4..557c392 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/kdev_t.h>
 #include <linux/rcupdate.h>
+#include <linux/slab.h>
 
 #ifdef CONFIG_BLOCK
 
@@ -86,7 +87,15 @@
 	unsigned long io_ticks;
 	unsigned long time_in_queue;
 };
-	
+
+#define PARTITION_META_INFO_VOLNAMELTH	64
+#define PARTITION_META_INFO_UUIDLTH	16
+
+struct partition_meta_info {
+	u8 uuid[PARTITION_META_INFO_UUIDLTH];	/* always big endian */
+	u8 volname[PARTITION_META_INFO_VOLNAMELTH];
+};
+
 struct hd_struct {
 	sector_t start_sect;
 	sector_t nr_sects;
@@ -95,6 +104,7 @@
 	struct device __dev;
 	struct kobject *holder_dir;
 	int policy, partno;
+	struct partition_meta_info *info;
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 	int make_it_fail;
 #endif
@@ -129,8 +139,9 @@
 struct disk_part_tbl {
 	struct rcu_head rcu_head;
 	int len;
-	struct hd_struct *last_lookup;
-	struct hd_struct *part[];
+	struct hd_struct __rcu *last_lookup;
+	struct gendisk *disk;
+	struct hd_struct __rcu *part[];
 };
 
 struct gendisk {
@@ -149,7 +160,7 @@
 	 * non-critical accesses use RCU.  Always access through
 	 * helpers.
 	 */
-	struct disk_part_tbl *part_tbl;
+	struct disk_part_tbl __rcu *part_tbl;
 	struct hd_struct part0;
 
 	const struct block_device_operations *fops;
@@ -181,6 +192,30 @@
 	return NULL;
 }
 
+static inline void part_pack_uuid(const u8 *uuid_str, u8 *to)
+{
+	int i;
+	for (i = 0; i < 16; ++i) {
+		*to++ = (hex_to_bin(*uuid_str) << 4) |
+			(hex_to_bin(*(uuid_str + 1)));
+		uuid_str += 2;
+		switch (i) {
+		case 3:
+		case 5:
+		case 7:
+		case 9:
+			uuid_str++;
+			continue;
+		}
+	}
+}
+
+static inline char *part_unpack_uuid(const u8 *uuid, char *out)
+{
+	sprintf(out, "%pU", uuid);
+	return out;
+}
+
 static inline int disk_max_parts(struct gendisk *disk)
 {
 	if (disk->flags & GENHD_FL_EXT_DEVT)
@@ -342,6 +377,19 @@
 	return part->in_flight[0] + part->in_flight[1];
 }
 
+static inline struct partition_meta_info *alloc_part_info(struct gendisk *disk)
+{
+	if (disk)
+		return kzalloc_node(sizeof(struct partition_meta_info),
+				    GFP_KERNEL, disk->node_id);
+	return kzalloc(sizeof(struct partition_meta_info), GFP_KERNEL);
+}
+
+static inline void free_part_info(struct hd_struct *part)
+{
+	kfree(part->info);
+}
+
 /* block/blk-core.c */
 extern void part_round_stats(int cpu, struct hd_struct *part);
 
@@ -533,7 +581,9 @@
 extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
 extern struct hd_struct * __must_check add_partition(struct gendisk *disk,
 						     int partno, sector_t start,
-						     sector_t len, int flags);
+						     sector_t len, int flags,
+						     struct partition_meta_info
+						       *info);
 extern void delete_partition(struct gendisk *, int);
 extern void printk_all_partitions(void);
 
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index d5b3876..8a389b6 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -8,7 +8,6 @@
 #include <linux/lockdep.h>
 #include <linux/ftrace_irq.h>
 #include <asm/hardirq.h>
-#include <asm/system.h>
 
 /*
  * We put the hardirq and softirq counter into the preemption
@@ -64,6 +63,8 @@
 #define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
 #define NMI_OFFSET	(1UL << NMI_SHIFT)
 
+#define SOFTIRQ_DISABLE_OFFSET	(2 * SOFTIRQ_OFFSET)
+
 #ifndef PREEMPT_ACTIVE
 #define PREEMPT_ACTIVE_BITS	1
 #define PREEMPT_ACTIVE_SHIFT	(NMI_SHIFT + NMI_BITS)
@@ -82,10 +83,13 @@
 /*
  * Are we doing bottom half or hardware interrupt processing?
  * Are we in a softirq context? Interrupt context?
+ * in_softirq - Are we currently processing softirq or have bh disabled?
+ * in_serving_softirq - Are we currently processing softirq?
  */
 #define in_irq()		(hardirq_count())
 #define in_softirq()		(softirq_count())
 #define in_interrupt()		(irq_count())
+#define in_serving_softirq()	(softirq_count() & SOFTIRQ_OFFSET)
 
 /*
  * Are we in NMI context?
@@ -132,14 +136,16 @@
 
 struct task_struct;
 
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+#if !defined(CONFIG_VIRT_CPU_ACCOUNTING) && !defined(CONFIG_IRQ_TIME_ACCOUNTING)
 static inline void account_system_vtime(struct task_struct *tsk)
 {
 }
+#else
+extern void account_system_vtime(struct task_struct *tsk);
 #endif
 
 #if defined(CONFIG_NO_HZ)
-#if defined(CONFIG_TINY_RCU)
+#if defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU)
 extern void rcu_enter_nohz(void);
 extern void rcu_exit_nohz(void);
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 42a0f1d..4cfe02c 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -316,6 +316,7 @@
 #define HID_QUIRK_FULLSPEED_INTERVAL		0x10000000
 #define HID_QUIRK_NO_INIT_REPORTS		0x20000000
 #define HID_QUIRK_NO_IGNORE			0x40000000
+#define HID_QUIRK_NO_INPUT_SYNC			0x80000000
 
 /*
  * This is the global environment of the parser. This information is
diff --git a/include/linux/hiddev.h b/include/linux/hiddev.h
index bb6f58b..a3f481a 100644
--- a/include/linux/hiddev.h
+++ b/include/linux/hiddev.h
@@ -226,8 +226,6 @@
 void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
 		      struct hid_usage *usage, __s32 value);
 void hiddev_report_event(struct hid_device *hid, struct hid_report *report);
-int __init hiddev_init(void);
-void hiddev_exit(void);
 #else
 static inline int hiddev_connect(struct hid_device *hid,
 		unsigned int force)
@@ -236,8 +234,6 @@
 static inline void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
 		      struct hid_usage *usage, __s32 value) { }
 static inline void hiddev_report_event(struct hid_device *hid, struct hid_report *report) { }
-static inline int hiddev_init(void) { return 0; }
-static inline void hiddev_exit(void) { }
 #endif
 
 #endif
diff --git a/include/linux/htirq.h b/include/linux/htirq.h
index c96ea46..70a1dbb 100644
--- a/include/linux/htirq.h
+++ b/include/linux/htirq.h
@@ -9,8 +9,9 @@
 /* Helper functions.. */
 void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
 void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg);
-void mask_ht_irq(unsigned int irq);
-void unmask_ht_irq(unsigned int irq);
+struct irq_data;
+void mask_ht_irq(struct irq_data *data);
+void unmask_ht_irq(struct irq_data *data);
 
 /* The arch hook for getting things started */
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev);
diff --git a/include/linux/idr.h b/include/linux/idr.h
index e968db7..cdb715e 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -50,14 +50,14 @@
 
 struct idr_layer {
 	unsigned long		 bitmap; /* A zero bit means "space here" */
-	struct idr_layer	*ary[1<<IDR_BITS];
+	struct idr_layer __rcu	*ary[1<<IDR_BITS];
 	int			 count;	 /* When zero, we can release it */
 	int			 layer;	 /* distance from leaf */
 	struct rcu_head		 rcu_head;
 };
 
 struct idr {
-	struct idr_layer *top;
+	struct idr_layer __rcu *top;
 	struct idr_layer *id_free;
 	int		  layers; /* only valid without concurrent changes */
 	int		  id_free_cnt;
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 97b2eae..ed5a03c 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -986,6 +986,7 @@
 #define WLAN_AUTH_OPEN 0
 #define WLAN_AUTH_SHARED_KEY 1
 #define WLAN_AUTH_FT 2
+#define WLAN_AUTH_SAE 3
 #define WLAN_AUTH_LEAP 128
 
 #define WLAN_AUTH_CHALLENGE_LEN 128
@@ -1072,6 +1073,10 @@
 	WLAN_STATUS_NO_DIRECT_LINK = 48,
 	WLAN_STATUS_STA_NOT_PRESENT = 49,
 	WLAN_STATUS_STA_NOT_QSTA = 50,
+	/* 802.11s */
+	WLAN_STATUS_ANTI_CLOG_REQUIRED = 76,
+	WLAN_STATUS_FCG_NOT_SUPP = 78,
+	WLAN_STATUS_STA_NO_TBTT = 78,
 };
 
 
@@ -1112,6 +1117,22 @@
 	WLAN_REASON_QSTA_REQUIRE_SETUP = 38,
 	WLAN_REASON_QSTA_TIMEOUT = 39,
 	WLAN_REASON_QSTA_CIPHER_NOT_SUPP = 45,
+	/* 802.11s */
+	WLAN_REASON_MESH_PEER_CANCELED = 52,
+	WLAN_REASON_MESH_MAX_PEERS = 53,
+	WLAN_REASON_MESH_CONFIG = 54,
+	WLAN_REASON_MESH_CLOSE = 55,
+	WLAN_REASON_MESH_MAX_RETRIES = 56,
+	WLAN_REASON_MESH_CONFIRM_TIMEOUT = 57,
+	WLAN_REASON_MESH_INVALID_GTK = 58,
+	WLAN_REASON_MESH_INCONSISTENT_PARAM = 59,
+	WLAN_REASON_MESH_INVALID_SECURITY = 60,
+	WLAN_REASON_MESH_PATH_ERROR = 61,
+	WLAN_REASON_MESH_PATH_NOFORWARD = 62,
+	WLAN_REASON_MESH_PATH_DEST_UNREACHABLE = 63,
+	WLAN_REASON_MAC_EXISTS_IN_MBSS = 64,
+	WLAN_REASON_MESH_CHAN_REGULATORY = 65,
+	WLAN_REASON_MESH_CHAN = 66,
 };
 
 
@@ -1139,20 +1160,33 @@
 	WLAN_EID_TS_DELAY = 43,
 	WLAN_EID_TCLAS_PROCESSING = 44,
 	WLAN_EID_QOS_CAPA = 46,
-	/* 802.11s
-	 *
-	 * All mesh EID numbers are pending IEEE 802.11 ANA approval.
-	 * The numbers have been incremented from those suggested in
-	 * 802.11s/D2.0 so that MESH_CONFIG does not conflict with
-	 * EXT_SUPP_RATES.
+	/* 802.11s */
+	WLAN_EID_MESH_CONFIG = 113,
+	WLAN_EID_MESH_ID = 114,
+	WLAN_EID_LINK_METRIC_REPORT = 115,
+	WLAN_EID_CONGESTION_NOTIFICATION = 116,
+	/* Note that the Peer Link IE has been replaced with the similar
+	 * Peer Management IE.  We will keep the former definition until mesh
+	 * code is changed to comply with latest 802.11s drafts.
 	 */
-	WLAN_EID_MESH_CONFIG = 51,
-	WLAN_EID_MESH_ID = 52,
-	WLAN_EID_PEER_LINK = 55,
-	WLAN_EID_PREQ = 68,
-	WLAN_EID_PREP = 69,
-	WLAN_EID_PERR = 70,
-	WLAN_EID_RANN = 49,	/* compatible with FreeBSD */
+	WLAN_EID_PEER_LINK = 55,  /* no longer in 802.11s drafts */
+	WLAN_EID_PEER_MGMT = 117,
+	WLAN_EID_CHAN_SWITCH_PARAM = 118,
+	WLAN_EID_MESH_AWAKE_WINDOW = 119,
+	WLAN_EID_BEACON_TIMING = 120,
+	WLAN_EID_MCCAOP_SETUP_REQ = 121,
+	WLAN_EID_MCCAOP_SETUP_RESP = 122,
+	WLAN_EID_MCCAOP_ADVERT = 123,
+	WLAN_EID_MCCAOP_TEARDOWN = 124,
+	WLAN_EID_GANN = 125,
+	WLAN_EID_RANN = 126,
+	WLAN_EID_PREQ = 130,
+	WLAN_EID_PREP = 131,
+	WLAN_EID_PERR = 132,
+	WLAN_EID_PXU = 137,
+	WLAN_EID_PXUC = 138,
+	WLAN_EID_AUTH_MESH_PEER_EXCH = 139,
+	WLAN_EID_MIC = 140,
 
 	WLAN_EID_PWR_CONSTRAINT = 32,
 	WLAN_EID_PWR_CAPABILITY = 33,
@@ -1211,9 +1245,14 @@
 	WLAN_CATEGORY_HT = 7,
 	WLAN_CATEGORY_SA_QUERY = 8,
 	WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9,
+	WLAN_CATEGORY_MESH_ACTION = 13,
+	WLAN_CATEGORY_MULTIHOP_ACTION = 14,
+	WLAN_CATEGORY_SELF_PROTECTED = 15,
 	WLAN_CATEGORY_WMM = 17,
-	WLAN_CATEGORY_MESH_PLINK = 30,		/* Pending ANA approval */
-	WLAN_CATEGORY_MESH_PATH_SEL = 32,	/* Pending ANA approval */
+	/* TODO: remove MESH_PLINK and MESH_PATH_SEL after */
+	/*       mesh is updated to current 802.11s draft  */
+	WLAN_CATEGORY_MESH_PLINK = 30,
+	WLAN_CATEGORY_MESH_PATH_SEL = 32,
 	WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126,
 	WLAN_CATEGORY_VENDOR_SPECIFIC = 127,
 };
@@ -1351,6 +1390,8 @@
 /* AKM suite selectors */
 #define WLAN_AKM_SUITE_8021X		0x000FAC01
 #define WLAN_AKM_SUITE_PSK		0x000FAC02
+#define WLAN_AKM_SUITE_SAE			0x000FAC08
+#define WLAN_AKM_SUITE_FT_OVER_SAE	0x000FAC09
 
 #define WLAN_MAX_KEY_LEN		32
 
diff --git a/include/linux/if.h b/include/linux/if.h
index 53558ec..1239599 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -75,6 +75,8 @@
 #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
+					 * datapath port */
 
 #define IF_GET_IFACE	0x0001		/* for querying only */
 #define IF_GET_PROTO	0x0002
diff --git a/include/linux/if_bonding.h b/include/linux/if_bonding.h
index 2c799437..a17edda 100644
--- a/include/linux/if_bonding.h
+++ b/include/linux/if_bonding.h
@@ -84,6 +84,9 @@
 #define BOND_DEFAULT_MAX_BONDS  1   /* Default maximum number of devices to support */
 
 #define BOND_DEFAULT_TX_QUEUES 16   /* Default number of tx queues per device */
+
+#define BOND_DEFAULT_RESEND_IGMP	1 /* Default number of IGMP membership reports */
+
 /* hashing types */
 #define BOND_XMIT_POLICY_LAYER2		0 /* layer 2 (MAC only), default */
 #define BOND_XMIT_POLICY_LAYER34	1 /* layer 3+4 (IP ^ (TCP || UDP)) */
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index bed7a46..f9c3df0 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -137,8 +137,6 @@
 
 extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len);
 
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-
 #endif
 
 #endif	/* _LINUX_IF_ETHER_H */
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index 35280b3..8a2fd66 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -40,6 +40,12 @@
 	unsigned long		rx_errors;
 };
 
+/*
+ * Maximum times a macvtap device can be opened. This can be used to
+ * configure the number of receive queue, e.g. for multiqueue virtio.
+ */
+#define MAX_MACVTAP_QUEUES	(NR_CPUS < 16 ? NR_CPUS : 16)
+
 struct macvlan_dev {
 	struct net_device	*dev;
 	struct list_head	list;
@@ -50,7 +56,8 @@
 	enum macvlan_mode	mode;
 	int (*receive)(struct sk_buff *skb);
 	int (*forward)(struct net_device *dev, struct sk_buff *skb);
-	struct macvtap_queue	*tap;
+	struct macvtap_queue	*taps[MAX_MACVTAP_QUEUES];
+	int			numvtaps;
 };
 
 static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index 27741e0..397921b 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -40,25 +40,35 @@
  * PPPoE addressing definition 
  */ 
 typedef __be16 sid_t;
-struct pppoe_addr{ 
-       sid_t           sid;                    /* Session identifier */ 
-       unsigned char   remote[ETH_ALEN];       /* Remote address */ 
-       char            dev[IFNAMSIZ];          /* Local device to use */ 
+struct pppoe_addr {
+	sid_t         sid;                    /* Session identifier */
+	unsigned char remote[ETH_ALEN];       /* Remote address */
+	char          dev[IFNAMSIZ];          /* Local device to use */
 }; 
  
 /************************************************************************ 
- * Protocols supported by AF_PPPOX 
- */ 
+ * PPTP addressing definition
+ */
+struct pptp_addr {
+	__be16		call_id;
+	struct in_addr	sin_addr;
+};
+
+/************************************************************************
+ * Protocols supported by AF_PPPOX
+ */
 #define PX_PROTO_OE    0 /* Currently just PPPoE */
 #define PX_PROTO_OL2TP 1 /* Now L2TP also */
-#define PX_MAX_PROTO   2
+#define PX_PROTO_PPTP  2
+#define PX_MAX_PROTO   3
 
-struct sockaddr_pppox { 
-       sa_family_t     sa_family;            /* address family, AF_PPPOX */ 
-       unsigned int    sa_protocol;          /* protocol identifier */ 
-       union{ 
-               struct pppoe_addr       pppoe; 
-       }sa_addr; 
+struct sockaddr_pppox {
+	sa_family_t     sa_family;            /* address family, AF_PPPOX */
+	unsigned int    sa_protocol;          /* protocol identifier */
+	union {
+		struct pppoe_addr  pppoe;
+		struct pptp_addr   pptp;
+	} sa_addr;
 } __attribute__((packed));
 
 /* The use of the above union isn't viable because the size of this
@@ -150,15 +160,23 @@
 					     relayed to (PPPoE relaying) */
 };
 
+struct pptp_opt {
+	struct pptp_addr src_addr;
+	struct pptp_addr dst_addr;
+	u32 ack_sent, ack_recv;
+	u32 seq_sent, seq_recv;
+	int ppp_flags;
+};
 #include <net/sock.h>
 
 struct pppox_sock {
 	/* struct sock must be the first member of pppox_sock */
-	struct sock		sk;
-	struct ppp_channel	chan;
+	struct sock sk;
+	struct ppp_channel chan;
 	struct pppox_sock	*next;	  /* for hash table */
 	union {
 		struct pppoe_opt pppoe;
+		struct pptp_opt  pptp;
 	} proto;
 	__be16			num;
 };
@@ -186,7 +204,7 @@
 	struct module	*owner;
 };
 
-extern int register_pppox_proto(int proto_num, struct pppox_proto *pp);
+extern int register_pppox_proto(int proto_num, const struct pppox_proto *pp);
 extern void unregister_pppox_proto(int proto_num);
 extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */
 extern int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 3d870fd..c2f3a72 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -16,6 +16,7 @@
 #ifdef __KERNEL__
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
 
 #define VLAN_HLEN	4		/* The additional bytes (on top of the Ethernet header)
 					 * that VLAN requires.
@@ -68,6 +69,7 @@
 #define VLAN_CFI_MASK		0x1000 /* Canonical Format Indicator */
 #define VLAN_TAG_PRESENT	VLAN_CFI_MASK
 #define VLAN_VID_MASK		0x0fff /* VLAN Identifier */
+#define VLAN_N_VID		4096
 
 /* found in socket.c */
 extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
@@ -76,9 +78,8 @@
  * depends on completely exhausting the VLAN identifier space.  Thus
  * it gives constant time look-up, but in many cases it wastes memory.
  */
-#define VLAN_GROUP_ARRAY_LEN          4096
 #define VLAN_GROUP_ARRAY_SPLIT_PARTS  8
-#define VLAN_GROUP_ARRAY_PART_LEN     (VLAN_GROUP_ARRAY_LEN/VLAN_GROUP_ARRAY_SPLIT_PARTS)
+#define VLAN_GROUP_ARRAY_PART_LEN     (VLAN_N_VID/VLAN_GROUP_ARRAY_SPLIT_PARTS)
 
 struct vlan_group {
 	struct net_device	*real_dev; /* The ethernet(like) device
@@ -114,12 +115,24 @@
 #define vlan_tx_tag_get(__skb)		((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+/* Must be invoked with rcu_read_lock or with RTNL. */
+static inline struct net_device *vlan_find_dev(struct net_device *real_dev,
+					       u16 vlan_id)
+{
+	struct vlan_group *grp = rcu_dereference_rtnl(real_dev->vlgrp);
+
+	if (grp)
+		return vlan_group_get_device(grp, vlan_id);
+
+	return NULL;
+}
+
 extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
 extern u16 vlan_dev_vlan_id(const struct net_device *dev);
 
 extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
 			     u16 vlan_tci, int polling);
-extern int vlan_hwaccel_do_receive(struct sk_buff *skb);
+extern bool vlan_hwaccel_do_receive(struct sk_buff **skb);
 extern gro_result_t
 vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
 		 unsigned int vlan_tci, struct sk_buff *skb);
@@ -128,6 +141,12 @@
 	       unsigned int vlan_tci);
 
 #else
+static inline struct net_device *vlan_find_dev(struct net_device *real_dev,
+					       u16 vlan_id)
+{
+	return NULL;
+}
+
 static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev)
 {
 	BUG();
@@ -147,9 +166,11 @@
 	return NET_XMIT_SUCCESS;
 }
 
-static inline int vlan_hwaccel_do_receive(struct sk_buff *skb)
+static inline bool vlan_hwaccel_do_receive(struct sk_buff **skb)
 {
-	return 0;
+	if ((*skb)->vlan_tci & VLAN_VID_MASK)
+		(*skb)->pkt_type = PACKET_OTHERHOST;
+	return false;
 }
 
 static inline gro_result_t
diff --git a/include/linux/in.h b/include/linux/in.h
index 41d88a4..beeb6de 100644
--- a/include/linux/in.h
+++ b/include/linux/in.h
@@ -250,6 +250,25 @@
 
 #ifdef __KERNEL__
 
+#include <linux/errno.h>
+
+static inline int proto_ports_offset(int proto)
+{
+	switch (proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_DCCP:
+	case IPPROTO_ESP:	/* SPI */
+	case IPPROTO_SCTP:
+	case IPPROTO_UDPLITE:
+		return 0;
+	case IPPROTO_AH:	/* SPI */
+		return 4;
+	default:
+		return -EINVAL;
+	}
+}
+
 static inline bool ipv4_is_loopback(__be32 addr)
 {
 	return (addr & htonl(0xff000000)) == htonl(0x7f000000);
diff --git a/include/linux/in6.h b/include/linux/in6.h
index c4bf46f..097a34b 100644
--- a/include/linux/in6.h
+++ b/include/linux/in6.h
@@ -268,6 +268,10 @@
 /* RFC5082: Generalized Ttl Security Mechanism */
 #define IPV6_MINHOPCOUNT		73
 
+#define IPV6_ORIGDSTADDR        74
+#define IPV6_RECVORIGDSTADDR    IPV6_ORIGDSTADDR
+#define IPV6_TRANSPARENT        75
+
 /*
  * Multicast Routing:
  * see include/linux/mroute6.h.
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 2be1a1a..ccd5b07 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -9,6 +9,7 @@
 #include <linux/rcupdate.h>
 #include <linux/timer.h>
 #include <linux/sysctl.h>
+#include <linux/rtnetlink.h>
 
 enum
 {
@@ -158,7 +159,12 @@
 extern int register_inetaddr_notifier(struct notifier_block *nb);
 extern int unregister_inetaddr_notifier(struct notifier_block *nb);
 
-extern struct net_device *ip_dev_find(struct net *net, __be32 addr);
+extern struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref);
+static inline struct net_device *ip_dev_find(struct net *net, __be32 addr)
+{
+	return __ip_dev_find(net, addr, true);
+}
+
 extern int		inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
 extern int		devinet_ioctl(struct net *net, unsigned int cmd, void __user *);
 extern void		devinet_init(void);
@@ -198,14 +204,10 @@
 
 static inline struct in_device *__in_dev_get_rcu(const struct net_device *dev)
 {
-	struct in_device *in_dev = dev->ip_ptr;
-	if (in_dev)
-		in_dev = rcu_dereference(in_dev);
-	return in_dev;
+	return rcu_dereference(dev->ip_ptr);
 }
 
-static __inline__ struct in_device *
-in_dev_get(const struct net_device *dev)
+static inline struct in_device *in_dev_get(const struct net_device *dev)
 {
 	struct in_device *in_dev;
 
@@ -217,10 +219,9 @@
 	return in_dev;
 }
 
-static __inline__ struct in_device *
-__in_dev_get_rtnl(const struct net_device *dev)
+static inline struct in_device *__in_dev_get_rtnl(const struct net_device *dev)
 {
-	return (struct in_device*)dev->ip_ptr;
+	return rcu_dereference_check(dev->ip_ptr, lockdep_rtnl_is_held());
 }
 
 extern void in_dev_finish_destroy(struct in_device *idev);
diff --git a/include/linux/init.h b/include/linux/init.h
index de99430..577671c 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -46,16 +46,23 @@
 #define __exitdata	__section(.exit.data)
 #define __exit_call	__used __section(.exitcall.exit)
 
-/* modpost check for section mismatches during the kernel build.
+/*
+ * modpost check for section mismatches during the kernel build.
  * A section mismatch happens when there are references from a
  * code or data section to an init section (both code or data).
  * The init sections are (for most archs) discarded by the kernel
  * when early init has completed so all such references are potential bugs.
  * For exit sections the same issue exists.
+ *
  * The following markers are used for the cases where the reference to
  * the *init / *exit section (code or data) is valid and will teach
- * modpost not to issue a warning.
- * The markers follow same syntax rules as __init / __initdata. */
+ * modpost not to issue a warning.  Intended semantics is that a code or
+ * data tagged __ref* can reference code or data from init section without
+ * producing a warning (of course, no warning does not mean code is
+ * correct, so optimally document why the __ref is needed and why it's OK).
+ *
+ * The markers follow same syntax rules as __init / __initdata.
+ */
 #define __ref            __section(.ref.text) noinline
 #define __refdata        __section(.ref.data)
 #define __refconst       __section(.ref.rodata)
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 1f43fa5..2fea6c8 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -82,11 +82,17 @@
 # define CAP_INIT_BSET  CAP_FULL_SET
 
 #ifdef CONFIG_TREE_PREEMPT_RCU
+#define INIT_TASK_RCU_TREE_PREEMPT()					\
+	.rcu_blocked_node = NULL,
+#else
+#define INIT_TASK_RCU_TREE_PREEMPT(tsk)
+#endif
+#ifdef CONFIG_PREEMPT_RCU
 #define INIT_TASK_RCU_PREEMPT(tsk)					\
 	.rcu_read_lock_nesting = 0,					\
 	.rcu_read_unlock_special = 0,					\
-	.rcu_blocked_node = NULL,					\
-	.rcu_node_entry = LIST_HEAD_INIT(tsk.rcu_node_entry),
+	.rcu_node_entry = LIST_HEAD_INIT(tsk.rcu_node_entry),		\
+	INIT_TASK_RCU_TREE_PREEMPT()
 #else
 #define INIT_TASK_RCU_PREEMPT(tsk)
 #endif
@@ -137,8 +143,8 @@
 	.children	= LIST_HEAD_INIT(tsk.children),			\
 	.sibling	= LIST_HEAD_INIT(tsk.sibling),			\
 	.group_leader	= &tsk,						\
-	.real_cred	= &init_cred,					\
-	.cred		= &init_cred,					\
+	RCU_INIT_POINTER(.real_cred, &init_cred),			\
+	RCU_INIT_POINTER(.cred, &init_cred),				\
 	.cred_guard_mutex =						\
 		 __MUTEX_INITIALIZER(tsk.cred_guard_mutex),		\
 	.comm		= "swapper",					\
diff --git a/include/linux/input.h b/include/linux/input.h
index 896a922..d6ae176 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -1196,7 +1196,7 @@
 	int (*flush)(struct input_dev *dev, struct file *file);
 	int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 
-	struct input_handle *grab;
+	struct input_handle __rcu *grab;
 
 	spinlock_t event_lock;
 	struct mutex mutex;
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index a0384a4..01b2816 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -18,6 +18,7 @@
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
+#include <trace/events/irq.h>
 
 /*
  * These correspond to the IORESOURCE_IRQ_* defines in
@@ -407,10 +408,14 @@
 asmlinkage void __do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
+static inline void __raise_softirq_irqoff(unsigned int nr)
+{
+	trace_softirq_raise((struct softirq_action *)(unsigned long)nr, NULL);
+	or_softirq_pending(1UL << nr);
+}
+
 extern void raise_softirq_irqoff(unsigned int nr);
 extern void raise_softirq(unsigned int nr);
-extern void wakeup_softirqd(void);
 
 /* This is the worklist that queues up per-cpu softirq work.
  *
@@ -641,11 +646,8 @@
 struct seq_file;
 int show_interrupts(struct seq_file *p, void *v);
 
-struct irq_desc;
-
 extern int early_irq_init(void);
 extern int arch_probe_nr_irqs(void);
 extern int arch_early_irq_init(void);
-extern int arch_init_chip_data(struct irq_desc *desc, int node);
 
 #endif
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index 64d5291..3e70b21 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -53,7 +53,7 @@
 
 	struct radix_tree_root radix_root;
 	struct hlist_head cic_list;
-	void *ioc_data;
+	void __rcu *ioc_data;
 };
 
 static inline struct io_context *ioc_task_link(struct io_context *ioc)
diff --git a/include/linux/ip_vs.h b/include/linux/ip_vs.h
index 9708de2..5f43a3b 100644
--- a/include/linux/ip_vs.h
+++ b/include/linux/ip_vs.h
@@ -70,6 +70,7 @@
 
 /*
  *      IPVS Connection Flags
+ *      Only flags 0..15 are sent to backup server
  */
 #define IP_VS_CONN_F_FWD_MASK	0x0007		/* mask for the fwd methods */
 #define IP_VS_CONN_F_MASQ	0x0000		/* masquerading/NAT */
@@ -88,9 +89,20 @@
 #define IP_VS_CONN_F_TEMPLATE	0x1000		/* template, not connection */
 #define IP_VS_CONN_F_ONE_PACKET	0x2000		/* forward only one packet */
 
+/* Flags that are not sent to backup server start from bit 16 */
+#define IP_VS_CONN_F_NFCT	(1 << 16)	/* use netfilter conntrack */
+
+/* Connection flags from destination that can be changed by user space */
+#define IP_VS_CONN_F_DEST_MASK (IP_VS_CONN_F_FWD_MASK | \
+				IP_VS_CONN_F_ONE_PACKET | \
+				IP_VS_CONN_F_NFCT | \
+				0)
+
 #define IP_VS_SCHEDNAME_MAXLEN	16
+#define IP_VS_PENAME_MAXLEN	16
 #define IP_VS_IFNAME_MAXLEN	16
 
+#define IP_VS_PEDATA_MAXLEN     255
 
 /*
  *	The struct ip_vs_service_user and struct ip_vs_dest_user are
@@ -324,6 +336,9 @@
 	IPVS_SVC_ATTR_NETMASK,		/* persistent netmask */
 
 	IPVS_SVC_ATTR_STATS,		/* nested attribute for service stats */
+
+	IPVS_SVC_ATTR_PE_NAME,		/* name of ct retriever */
+
 	__IPVS_SVC_ATTR_MAX,
 };
 
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index e62683b..8e429d0 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -341,7 +341,9 @@
 				odstopts:1,
                                 rxflow:1,
 				rxtclass:1,
-				rxpmtu:1;
+				rxpmtu:1,
+				rxorigdstaddr:1;
+				/* 2 bits hole */
 		} bits;
 		__u16		all;
 	} rxopt;
diff --git a/include/linux/irq.h b/include/linux/irq.h
index c03243a..e963911 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -72,6 +72,10 @@
 #define IRQ_ONESHOT		0x08000000	/* IRQ is not unmasked after hardirq */
 #define IRQ_NESTED_THREAD	0x10000000	/* IRQ is nested into another, no own handler thread */
 
+#define IRQF_MODIFY_MASK	\
+	(IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
+	 IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL)
+
 #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)
@@ -80,36 +84,77 @@
 # define IRQ_NO_BALANCING_MASK	IRQ_NO_BALANCING
 #endif
 
-struct proc_dir_entry;
 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
+ * @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
+ *			methods, to allow shared chip implementations
+ * @msi_desc:		MSI descriptor
+ * @affinity:		IRQ affinity on SMP
+ *
+ * The fields here need to overlay the ones in irq_desc until we
+ * cleaned up the direct references and switched everything over to
+ * irq_data.
+ */
+struct irq_data {
+	unsigned int		irq;
+	unsigned int		node;
+	struct irq_chip		*chip;
+	void			*handler_data;
+	void			*chip_data;
+	struct msi_desc		*msi_desc;
+#ifdef CONFIG_SMP
+	cpumask_var_t		affinity;
+#endif
+};
+
+/**
  * struct irq_chip - hardware interrupt chip descriptor
  *
  * @name:		name for /proc/interrupts
- * @startup:		start up the interrupt (defaults to ->enable if NULL)
- * @shutdown:		shut down the interrupt (defaults to ->disable if NULL)
- * @enable:		enable the interrupt (defaults to chip->unmask if NULL)
- * @disable:		disable the interrupt
- * @ack:		start of a new interrupt
- * @mask:		mask an interrupt source
- * @mask_ack:		ack and mask an interrupt source
- * @unmask:		unmask an interrupt source
- * @eoi:		end of interrupt - chip level
- * @end:		end of interrupt - flow level
- * @set_affinity:	set the CPU affinity on SMP machines
- * @retrigger:		resend an IRQ to the CPU
- * @set_type:		set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
- * @set_wake:		enable/disable power-management wake-on of an IRQ
+ * @startup:		deprecated, replaced by irq_startup
+ * @shutdown:		deprecated, replaced by irq_shutdown
+ * @enable:		deprecated, replaced by irq_enable
+ * @disable:		deprecated, replaced by irq_disable
+ * @ack:		deprecated, replaced by irq_ack
+ * @mask:		deprecated, replaced by irq_mask
+ * @mask_ack:		deprecated, replaced by irq_mask_ack
+ * @unmask:		deprecated, replaced by irq_unmask
+ * @eoi:		deprecated, replaced by irq_eoi
+ * @end:		deprecated, will go away with __do_IRQ()
+ * @set_affinity:	deprecated, replaced by irq_set_affinity
+ * @retrigger:		deprecated, replaced by irq_retrigger
+ * @set_type:		deprecated, replaced by irq_set_type
+ * @set_wake:		deprecated, replaced by irq_wake
+ * @bus_lock:		deprecated, replaced by irq_bus_lock
+ * @bus_sync_unlock:	deprecated, replaced by irq_bus_sync_unlock
  *
- * @bus_lock:		function to lock access to slow bus (i2c) chips
- * @bus_sync_unlock:	function to sync and unlock slow bus (i2c) chips
+ * @irq_startup:	start up the interrupt (defaults to ->enable if NULL)
+ * @irq_shutdown:	shut down the interrupt (defaults to ->disable if NULL)
+ * @irq_enable:		enable the interrupt (defaults to chip->unmask if NULL)
+ * @irq_disable:	disable the interrupt
+ * @irq_ack:		start of a new interrupt
+ * @irq_mask:		mask an interrupt source
+ * @irq_mask_ack:	ack and mask an interrupt source
+ * @irq_unmask:		unmask an interrupt source
+ * @irq_eoi:		end of interrupt
+ * @irq_set_affinity:	set the CPU affinity on SMP machines
+ * @irq_retrigger:	resend an IRQ to the CPU
+ * @irq_set_type:	set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
+ * @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
  *
  * @release:		release function solely used by UML
- * @typename:		obsoleted by name, kept as migration helper
  */
 struct irq_chip {
 	const char	*name;
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
 	unsigned int	(*startup)(unsigned int irq);
 	void		(*shutdown)(unsigned int irq);
 	void		(*enable)(unsigned int irq);
@@ -130,154 +175,66 @@
 
 	void		(*bus_lock)(unsigned int irq);
 	void		(*bus_sync_unlock)(unsigned int irq);
+#endif
+	unsigned int	(*irq_startup)(struct irq_data *data);
+	void		(*irq_shutdown)(struct irq_data *data);
+	void		(*irq_enable)(struct irq_data *data);
+	void		(*irq_disable)(struct irq_data *data);
+
+	void		(*irq_ack)(struct irq_data *data);
+	void		(*irq_mask)(struct irq_data *data);
+	void		(*irq_mask_ack)(struct irq_data *data);
+	void		(*irq_unmask)(struct irq_data *data);
+	void		(*irq_eoi)(struct irq_data *data);
+
+	int		(*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
+	int		(*irq_retrigger)(struct irq_data *data);
+	int		(*irq_set_type)(struct irq_data *data, unsigned int flow_type);
+	int		(*irq_set_wake)(struct irq_data *data, unsigned int on);
+
+	void		(*irq_bus_lock)(struct irq_data *data);
+	void		(*irq_bus_sync_unlock)(struct irq_data *data);
 
 	/* Currently used only by UML, might disappear one day.*/
 #ifdef CONFIG_IRQ_RELEASE_METHOD
 	void		(*release)(unsigned int irq, void *dev_id);
 #endif
-	/*
-	 * For compatibility, ->typename is copied into ->name.
-	 * Will disappear.
-	 */
-	const char	*typename;
 };
 
-struct timer_rand_state;
-struct irq_2_iommu;
-/**
- * struct irq_desc - interrupt descriptor
- * @irq:		interrupt number for this descriptor
- * @timer_rand_state:	pointer to timer rand state struct
- * @kstat_irqs:		irq stats per cpu
- * @irq_2_iommu:	iommu with this irq
- * @handle_irq:		highlevel irq-events handler [if NULL, __do_IRQ()]
- * @chip:		low level interrupt hardware access
- * @msi_desc:		MSI descriptor
- * @handler_data:	per-IRQ data for the irq_chip methods
- * @chip_data:		platform-specific per-chip private data for the chip
- *			methods, to allow shared chip implementations
- * @action:		the irq action chain
- * @status:		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:		IRQ affinity on SMP
- * @node:		node index useful for balancing
- * @pending_mask:	pending rebalanced interrupts
- * @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
- * @name:		flow handler name for /proc/interrupts output
- */
-struct irq_desc {
-	unsigned int		irq;
-	struct timer_rand_state *timer_rand_state;
-	unsigned int            *kstat_irqs;
-#ifdef CONFIG_INTR_REMAP
-	struct irq_2_iommu      *irq_2_iommu;
-#endif
-	irq_flow_handler_t	handle_irq;
-	struct irq_chip		*chip;
-	struct msi_desc		*msi_desc;
-	void			*handler_data;
-	void			*chip_data;
-	struct irqaction	*action;	/* IRQ action list */
-	unsigned int		status;		/* IRQ status */
-
-	unsigned int		depth;		/* nested irq disables */
-	unsigned int		wake_depth;	/* nested wake enables */
-	unsigned int		irq_count;	/* For detecting broken IRQs */
-	unsigned long		last_unhandled;	/* Aging timer for unhandled count */
-	unsigned int		irqs_unhandled;
-	raw_spinlock_t		lock;
-#ifdef CONFIG_SMP
-	cpumask_var_t		affinity;
-	const struct cpumask	*affinity_hint;
-	unsigned int		node;
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-	cpumask_var_t		pending_mask;
-#endif
-#endif
-	atomic_t		threads_active;
-	wait_queue_head_t       wait_for_threads;
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry	*dir;
-#endif
-	const char		*name;
-} ____cacheline_internodealigned_in_smp;
-
-extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
-					struct irq_desc *desc, int node);
-extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
-
-#ifndef CONFIG_SPARSE_IRQ
-extern struct irq_desc irq_desc[NR_IRQS];
-#endif
-
-#ifdef CONFIG_NUMA_IRQ_DESC
-extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int node);
-#else
-static inline struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
-{
-	return desc;
-}
-#endif
-
-extern struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node);
+/* This include will go away once we isolated irq_desc usage to core code */
+#include <linux/irqdesc.h>
 
 /*
  * Pick up the arch-dependent methods:
  */
 #include <asm/hw_irq.h>
 
+#ifndef NR_IRQS_LEGACY
+# define NR_IRQS_LEGACY 0
+#endif
+
+#ifndef ARCH_IRQ_INIT_FLAGS
+# define ARCH_IRQ_INIT_FLAGS	0
+#endif
+
+#define IRQ_DEFAULT_INIT_FLAGS	(IRQ_DISABLED | ARCH_IRQ_INIT_FLAGS)
+
+struct irqaction;
 extern int setup_irq(unsigned int irq, struct irqaction *new);
 extern void remove_irq(unsigned int irq, struct irqaction *act);
 
 #ifdef CONFIG_GENERIC_HARDIRQS
 
-#ifdef CONFIG_SMP
-
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-
+#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ)
 void move_native_irq(int irq);
 void move_masked_irq(int irq);
-
-#else /* CONFIG_GENERIC_PENDING_IRQ */
-
-static inline void move_irq(int irq)
-{
-}
-
-static inline void move_native_irq(int irq)
-{
-}
-
-static inline void move_masked_irq(int irq)
-{
-}
-
-#endif /* CONFIG_GENERIC_PENDING_IRQ */
-
-#else /* CONFIG_SMP */
-
-#define move_native_irq(x)
-#define move_masked_irq(x)
-
-#endif /* CONFIG_SMP */
+#else
+static inline void move_native_irq(int irq) { }
+static inline void move_masked_irq(int irq) { }
+#endif
 
 extern int no_irq_affinity;
 
-static inline int irq_balancing_disabled(unsigned int irq)
-{
-	struct irq_desc *desc;
-
-	desc = irq_to_desc(irq);
-	return desc->status & IRQ_NO_BALANCING_MASK;
-}
-
 /* Handle irq action chains: */
 extern irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action);
 
@@ -293,42 +250,10 @@
 extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_nested_irq(unsigned int irq);
 
-/*
- * Monolithic do_IRQ implementation.
- */
-#ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
-extern unsigned int __do_IRQ(unsigned int irq);
-#endif
-
-/*
- * Architectures call this to let the generic IRQ layer
- * handle an interrupt. If the descriptor is attached to an
- * irqchip-style controller then we call the ->handle_irq() handler,
- * and it calls __do_IRQ() if it's attached to an irqtype-style controller.
- */
-static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
-{
-#ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
-	desc->handle_irq(irq, desc);
-#else
-	if (likely(desc->handle_irq))
-		desc->handle_irq(irq, desc);
-	else
-		__do_IRQ(irq);
-#endif
-}
-
-static inline void generic_handle_irq(unsigned int irq)
-{
-	generic_handle_irq_desc(irq, irq_to_desc(irq));
-}
-
 /* Handling of unhandled and spurious interrupts: */
 extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
 			   irqreturn_t action_ret);
 
-/* Resending of interrupts :*/
-void check_irq_resend(struct irq_desc *desc, unsigned int irq);
 
 /* Enable/disable irq debugging output: */
 extern int noirqdebug_setup(char *str);
@@ -351,16 +276,6 @@
 __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
 		  const char *name);
 
-/* caller has locked the irq_desc and both params are valid */
-static inline void __set_irq_handler_unlocked(int irq,
-					      irq_flow_handler_t handler)
-{
-	struct irq_desc *desc;
-
-	desc = irq_to_desc(irq);
-	desc->handle_irq = handler;
-}
-
 /*
  * Set a highlevel flow handler for a given IRQ:
  */
@@ -384,26 +299,42 @@
 
 extern void set_irq_nested_thread(unsigned int irq, int nest);
 
-extern void set_irq_noprobe(unsigned int irq);
-extern void set_irq_probe(unsigned int irq);
+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)
+{
+	irq_modify_status(irq, 0, set);
+}
+
+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)
+{
+	irq_modify_status(irq, 0, IRQ_NOPROBE);
+}
+
+static inline void set_irq_probe(unsigned int irq)
+{
+	irq_modify_status(irq, IRQ_NOPROBE, 0);
+}
 
 /* Handle dynamic irq creation and destruction */
 extern unsigned int create_irq_nr(unsigned int irq_want, int node);
 extern int create_irq(void);
 extern void destroy_irq(unsigned int irq);
 
-/* Test to see if a driver has successfully requested an irq */
-static inline int irq_has_action(unsigned int irq)
-{
-	struct irq_desc *desc = irq_to_desc(irq);
-	return desc->action != NULL;
-}
-
-/* Dynamic irq helper functions */
-extern void dynamic_irq_init(unsigned int irq);
-void dynamic_irq_init_keep_chip_data(unsigned int irq);
+/*
+ * Dynamic irq helper functions. Obsolete. Use irq_alloc_desc* and
+ * irq_free_desc instead.
+ */
 extern void dynamic_irq_cleanup(unsigned int irq);
-void dynamic_irq_cleanup_keep_chip_data(unsigned int irq);
+static inline void dynamic_irq_init(unsigned int irq)
+{
+	dynamic_irq_cleanup(irq);
+}
 
 /* Set/get chip/data for an IRQ: */
 extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
@@ -411,114 +342,78 @@
 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 struct irq_data *irq_get_irq_data(unsigned int irq);
 
-#define get_irq_chip(irq)	(irq_to_desc(irq)->chip)
-#define get_irq_chip_data(irq)	(irq_to_desc(irq)->chip_data)
-#define get_irq_data(irq)	(irq_to_desc(irq)->handler_data)
-#define get_irq_msi(irq)	(irq_to_desc(irq)->msi_desc)
+static inline struct irq_chip *get_irq_chip(unsigned int irq)
+{
+	struct irq_data *d = irq_get_irq_data(irq);
+	return d ? d->chip : NULL;
+}
 
-#define get_irq_desc_chip(desc)		((desc)->chip)
-#define get_irq_desc_chip_data(desc)	((desc)->chip_data)
-#define get_irq_desc_data(desc)		((desc)->handler_data)
-#define get_irq_desc_msi(desc)		((desc)->msi_desc)
+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)
+{
+	struct irq_data *d = irq_get_irq_data(irq);
+	return d ? d->chip_data : NULL;
+}
+
+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)
+{
+	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)
+{
+	return d->handler_data;
+}
+
+static inline struct msi_desc *get_irq_msi(unsigned int irq)
+{
+	struct irq_data *d = irq_get_irq_data(irq);
+	return d ? d->msi_desc : NULL;
+}
+
+static inline struct msi_desc *irq_data_get_msi(struct irq_data *d)
+{
+	return d->msi_desc;
+}
+
+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);
+
+static inline int irq_alloc_desc(int node)
+{
+	return irq_alloc_descs(-1, 0, 1, node);
+}
+
+static inline int irq_alloc_desc_at(unsigned int at, int node)
+{
+	return irq_alloc_descs(at, at, 1, node);
+}
+
+static inline int irq_alloc_desc_from(unsigned int from, int node)
+{
+	return irq_alloc_descs(-1, from, 1, node);
+}
+
+static inline void irq_free_desc(unsigned int irq)
+{
+	irq_free_descs(irq, 1);
+}
 
 #endif /* CONFIG_GENERIC_HARDIRQS */
 
 #endif /* !CONFIG_S390 */
 
-#ifdef CONFIG_SMP
-/**
- * alloc_desc_masks - allocate cpumasks for irq_desc
- * @desc:	pointer to irq_desc struct
- * @node:	node which will be handling the cpumasks
- * @boot:	true if need bootmem
- *
- * Allocates affinity and pending_mask cpumask if required.
- * Returns true if successful (or not required).
- */
-static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
-							bool boot)
-{
-	gfp_t gfp = GFP_ATOMIC;
-
-	if (boot)
-		gfp = GFP_NOWAIT;
-
-#ifdef CONFIG_CPUMASK_OFFSTACK
-	if (!alloc_cpumask_var_node(&desc->affinity, gfp, node))
-		return false;
-
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-	if (!alloc_cpumask_var_node(&desc->pending_mask, gfp, node)) {
-		free_cpumask_var(desc->affinity);
-		return false;
-	}
-#endif
-#endif
-	return true;
-}
-
-static inline void init_desc_masks(struct irq_desc *desc)
-{
-	cpumask_setall(desc->affinity);
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-	cpumask_clear(desc->pending_mask);
-#endif
-}
-
-/**
- * init_copy_desc_masks - copy cpumasks for irq_desc
- * @old_desc:	pointer to old irq_desc struct
- * @new_desc:	pointer to new irq_desc struct
- *
- * Insures affinity and pending_masks are copied to new irq_desc.
- * If !CONFIG_CPUMASKS_OFFSTACK the cpumasks are embedded in the
- * irq_desc struct so the copy is redundant.
- */
-
-static inline void init_copy_desc_masks(struct irq_desc *old_desc,
-					struct irq_desc *new_desc)
-{
-#ifdef CONFIG_CPUMASK_OFFSTACK
-	cpumask_copy(new_desc->affinity, old_desc->affinity);
-
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-	cpumask_copy(new_desc->pending_mask, old_desc->pending_mask);
-#endif
-#endif
-}
-
-static inline void free_desc_masks(struct irq_desc *old_desc,
-				   struct irq_desc *new_desc)
-{
-	free_cpumask_var(old_desc->affinity);
-
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-	free_cpumask_var(old_desc->pending_mask);
-#endif
-}
-
-#else /* !CONFIG_SMP */
-
-static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
-								bool boot)
-{
-	return true;
-}
-
-static inline void init_desc_masks(struct irq_desc *desc)
-{
-}
-
-static inline void init_copy_desc_masks(struct irq_desc *old_desc,
-					struct irq_desc *new_desc)
-{
-}
-
-static inline void free_desc_masks(struct irq_desc *old_desc,
-				   struct irq_desc *new_desc)
-{
-}
-#endif	/* CONFIG_SMP */
-
 #endif /* _LINUX_IRQ_H */
diff --git a/include/linux/irq_work.h b/include/linux/irq_work.h
new file mode 100644
index 0000000..4fa09d4
--- /dev/null
+++ b/include/linux/irq_work.h
@@ -0,0 +1,20 @@
+#ifndef _LINUX_IRQ_WORK_H
+#define _LINUX_IRQ_WORK_H
+
+struct irq_work {
+	struct irq_work *next;
+	void (*func)(struct irq_work *);
+};
+
+static inline
+void init_irq_work(struct irq_work *entry, void (*func)(struct irq_work *))
+{
+	entry->next = NULL;
+	entry->func = func;
+}
+
+bool irq_work_queue(struct irq_work *entry);
+void irq_work_run(void);
+void irq_work_sync(struct irq_work *entry);
+
+#endif /* _LINUX_IRQ_WORK_H */
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
new file mode 100644
index 0000000..979c68c
--- /dev/null
+++ b/include/linux/irqdesc.h
@@ -0,0 +1,159 @@
+#ifndef _LINUX_IRQDESC_H
+#define _LINUX_IRQDESC_H
+
+/*
+ * Core internal functions to deal with irq descriptors
+ *
+ * This include will move to kernel/irq once we cleaned up the tree.
+ * For now it's included from <linux/irq.h>
+ */
+
+struct proc_dir_entry;
+struct timer_rand_state;
+/**
+ * struct irq_desc - interrupt descriptor
+ * @irq_data:		per irq and chip data passed down to chip functions
+ * @timer_rand_state:	pointer to timer rand state struct
+ * @kstat_irqs:		irq stats per cpu
+ * @handle_irq:		highlevel irq-events handler [if NULL, __do_IRQ()]
+ * @action:		the irq action chain
+ * @status:		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
+ * @pending_mask:	pending rebalanced interrupts
+ * @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
+ * @name:		flow handler name for /proc/interrupts output
+ */
+struct irq_desc {
+
+#ifdef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
+	struct irq_data		irq_data;
+#else
+	/*
+	 * This union will go away, once we fixed the direct access to
+	 * irq_desc all over the place. The direct fields are a 1:1
+	 * overlay of irq_data.
+	 */
+	union {
+		struct irq_data		irq_data;
+		struct {
+			unsigned int		irq;
+			unsigned int		node;
+			struct irq_chip		*chip;
+			void			*handler_data;
+			void			*chip_data;
+			struct msi_desc		*msi_desc;
+#ifdef CONFIG_SMP
+			cpumask_var_t		affinity;
+#endif
+		};
+	};
+#endif
+
+	struct timer_rand_state *timer_rand_state;
+	unsigned int		*kstat_irqs;
+	irq_flow_handler_t	handle_irq;
+	struct irqaction	*action;	/* IRQ action list */
+	unsigned int		status;		/* IRQ status */
+
+	unsigned int		depth;		/* nested irq disables */
+	unsigned int		wake_depth;	/* nested wake enables */
+	unsigned int		irq_count;	/* For detecting broken IRQs */
+	unsigned long		last_unhandled;	/* Aging timer for unhandled count */
+	unsigned int		irqs_unhandled;
+	raw_spinlock_t		lock;
+#ifdef CONFIG_SMP
+	const struct cpumask	*affinity_hint;
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+	cpumask_var_t		pending_mask;
+#endif
+#endif
+	atomic_t		threads_active;
+	wait_queue_head_t       wait_for_threads;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry	*dir;
+#endif
+	const char		*name;
+} ____cacheline_internodealigned_in_smp;
+
+#ifndef CONFIG_SPARSE_IRQ
+extern struct irq_desc irq_desc[NR_IRQS];
+#endif
+
+/* Will be removed once the last users in power and sh are gone */
+extern struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node);
+static inline struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
+{
+	return desc;
+}
+
+#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)
+
+/*
+ * Monolithic do_IRQ implementation.
+ */
+#ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
+extern unsigned int __do_IRQ(unsigned int irq);
+#endif
+
+/*
+ * Architectures call this to let the generic IRQ layer
+ * handle an interrupt. If the descriptor is attached to an
+ * irqchip-style controller then we call the ->handle_irq() handler,
+ * and it calls __do_IRQ() if it's attached to an irqtype-style controller.
+ */
+static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
+{
+#ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
+	desc->handle_irq(irq, desc);
+#else
+	if (likely(desc->handle_irq))
+		desc->handle_irq(irq, desc);
+	else
+		__do_IRQ(irq);
+#endif
+}
+
+static inline void generic_handle_irq(unsigned int irq)
+{
+	generic_handle_irq_desc(irq, irq_to_desc(irq));
+}
+
+/* Test to see if a driver has successfully requested an irq */
+static inline int irq_has_action(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	return desc->action != NULL;
+}
+
+static inline int irq_balancing_disabled(unsigned int irq)
+{
+	struct irq_desc *desc;
+
+	desc = irq_to_desc(irq);
+	return desc->status & IRQ_NO_BALANCING_MASK;
+}
+
+/* caller has locked the irq_desc and both params are valid */
+static inline void __set_irq_handler_unlocked(int irq,
+					      irq_flow_handler_t handler)
+{
+	struct irq_desc *desc;
+
+	desc = irq_to_desc(irq);
+	desc->handle_irq = handler;
+}
+#endif
+
+#endif
diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
index 006bf45..d176d65 100644
--- a/include/linux/irqflags.h
+++ b/include/linux/irqflags.h
@@ -12,6 +12,7 @@
 #define _LINUX_TRACE_IRQFLAGS_H
 
 #include <linux/typecheck.h>
+#include <asm/irqflags.h>
 
 #ifdef CONFIG_TRACE_IRQFLAGS
   extern void trace_softirqs_on(unsigned long ip);
@@ -52,17 +53,45 @@
 # define start_critical_timings() do { } while (0)
 #endif
 
+/*
+ * Wrap the arch provided IRQ routines to provide appropriate checks.
+ */
+#define raw_local_irq_disable()		arch_local_irq_disable()
+#define raw_local_irq_enable()		arch_local_irq_enable()
+#define raw_local_irq_save(flags)			\
+	do {						\
+		typecheck(unsigned long, flags);	\
+		flags = arch_local_irq_save();		\
+	} while (0)
+#define raw_local_irq_restore(flags)			\
+	do {						\
+		typecheck(unsigned long, flags);	\
+		arch_local_irq_restore(flags);		\
+	} while (0)
+#define raw_local_save_flags(flags)			\
+	do {						\
+		typecheck(unsigned long, flags);	\
+		flags = arch_local_save_flags();	\
+	} while (0)
+#define raw_irqs_disabled_flags(flags)			\
+	({						\
+		typecheck(unsigned long, flags);	\
+		arch_irqs_disabled_flags(flags);	\
+	})
+#define raw_irqs_disabled()		(arch_irqs_disabled())
+#define raw_safe_halt()			arch_safe_halt()
+
+/*
+ * The local_irq_*() APIs are equal to the raw_local_irq*()
+ * if !TRACE_IRQFLAGS.
+ */
 #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
-
-#include <asm/irqflags.h>
-
 #define local_irq_enable() \
 	do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
 #define local_irq_disable() \
 	do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
 #define local_irq_save(flags)				\
 	do {						\
-		typecheck(unsigned long, flags);	\
 		raw_local_irq_save(flags);		\
 		trace_hardirqs_off();			\
 	} while (0)
@@ -70,7 +99,6 @@
 
 #define local_irq_restore(flags)			\
 	do {						\
-		typecheck(unsigned long, flags);	\
 		if (raw_irqs_disabled_flags(flags)) {	\
 			raw_local_irq_restore(flags);	\
 			trace_hardirqs_off();		\
@@ -79,51 +107,44 @@
 			raw_local_irq_restore(flags);	\
 		}					\
 	} while (0)
-#else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
-/*
- * The local_irq_*() APIs are equal to the raw_local_irq*()
- * if !TRACE_IRQFLAGS.
- */
-# define raw_local_irq_disable()	local_irq_disable()
-# define raw_local_irq_enable()		local_irq_enable()
-# define raw_local_irq_save(flags)			\
-	do {						\
-		typecheck(unsigned long, flags);	\
-		local_irq_save(flags);			\
-	} while (0)
-# define raw_local_irq_restore(flags)			\
-	do {						\
-		typecheck(unsigned long, flags);	\
-		local_irq_restore(flags);		\
-	} while (0)
-#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
-
-#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
-#define safe_halt()						\
-	do {							\
-		trace_hardirqs_on();				\
-		raw_safe_halt();				\
-	} while (0)
-
 #define local_save_flags(flags)				\
 	do {						\
-		typecheck(unsigned long, flags);	\
 		raw_local_save_flags(flags);		\
 	} while (0)
 
-#define irqs_disabled()						\
-({								\
-	unsigned long _flags;					\
-								\
-	raw_local_save_flags(_flags);				\
-	raw_irqs_disabled_flags(_flags);			\
-})
+#define irqs_disabled_flags(flags)			\
+	({						\
+		raw_irqs_disabled_flags(flags);		\
+	})
 
-#define irqs_disabled_flags(flags)		\
-({						\
-	typecheck(unsigned long, flags);	\
-	raw_irqs_disabled_flags(flags);		\
-})
+#define irqs_disabled()					\
+	({						\
+		unsigned long _flags;			\
+		raw_local_save_flags(_flags);		\
+		raw_irqs_disabled_flags(_flags);	\
+	})
+
+#define safe_halt()				\
+	do {					\
+		trace_hardirqs_on();		\
+		raw_safe_halt();		\
+	} while (0)
+
+
+#else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
+
+#define local_irq_enable()	do { raw_local_irq_enable(); } while (0)
+#define local_irq_disable()	do { raw_local_irq_disable(); } while (0)
+#define local_irq_save(flags)					\
+	do {							\
+		raw_local_irq_save(flags);			\
+	} while (0)
+#define local_irq_restore(flags) do { raw_local_irq_restore(flags); } while (0)
+#define local_save_flags(flags)	do { raw_local_save_flags(flags); } while (0)
+#define irqs_disabled()		(raw_irqs_disabled())
+#define irqs_disabled_flags(flags) (raw_irqs_disabled_flags(flags))
+#define safe_halt()		do { raw_safe_halt(); } while (0)
+
 #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
 
 #endif
diff --git a/include/linux/irqnr.h b/include/linux/irqnr.h
index 7bf89bc..05aa8c23 100644
--- a/include/linux/irqnr.h
+++ b/include/linux/irqnr.h
@@ -25,6 +25,7 @@
 
 extern int nr_irqs;
 extern struct irq_desc *irq_to_desc(unsigned int irq);
+unsigned int irq_get_next_irq(unsigned int offset);
 
 # define for_each_irq_desc(irq, desc)					\
 	for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs;		\
@@ -47,6 +48,10 @@
 #define irq_node(irq)	0
 #endif
 
+# define for_each_active_irq(irq)			\
+	for (irq = irq_get_next_irq(0); irq < nr_irqs;	\
+	     irq = irq_get_next_irq(irq + 1))
+
 #endif /* CONFIG_GENERIC_HARDIRQS */
 
 #define for_each_irq_nr(irq)                   \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
new file mode 100644
index 0000000..b67cb18
--- /dev/null
+++ b/include/linux/jump_label.h
@@ -0,0 +1,74 @@
+#ifndef _LINUX_JUMP_LABEL_H
+#define _LINUX_JUMP_LABEL_H
+
+#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_HAVE_ARCH_JUMP_LABEL)
+# include <asm/jump_label.h>
+# define HAVE_JUMP_LABEL
+#endif
+
+enum jump_label_type {
+	JUMP_LABEL_ENABLE,
+	JUMP_LABEL_DISABLE
+};
+
+struct module;
+
+#ifdef HAVE_JUMP_LABEL
+
+extern struct jump_entry __start___jump_table[];
+extern struct jump_entry __stop___jump_table[];
+
+extern void arch_jump_label_transform(struct jump_entry *entry,
+				 enum jump_label_type type);
+extern void arch_jump_label_text_poke_early(jump_label_t addr);
+extern void jump_label_update(unsigned long key, enum jump_label_type type);
+extern void jump_label_apply_nops(struct module *mod);
+extern int jump_label_text_reserved(void *start, void *end);
+
+#define jump_label_enable(key) \
+	jump_label_update((unsigned long)key, JUMP_LABEL_ENABLE);
+
+#define jump_label_disable(key) \
+	jump_label_update((unsigned long)key, JUMP_LABEL_DISABLE);
+
+#else
+
+#define JUMP_LABEL(key, label)			\
+do {						\
+	if (unlikely(*key))			\
+		goto label;			\
+} while (0)
+
+#define jump_label_enable(cond_var)	\
+do {					\
+       *(cond_var) = 1;			\
+} while (0)
+
+#define jump_label_disable(cond_var)	\
+do {					\
+       *(cond_var) = 0;			\
+} while (0)
+
+static inline int jump_label_apply_nops(struct module *mod)
+{
+	return 0;
+}
+
+static inline int jump_label_text_reserved(void *start, void *end)
+{
+	return 0;
+}
+
+#endif
+
+#define COND_STMT(key, stmt)					\
+do {								\
+	__label__ jl_enabled;					\
+	JUMP_LABEL(key, jl_enabled);				\
+	if (0) {						\
+jl_enabled:							\
+		stmt;						\
+	}							\
+} while (0)
+
+#endif
diff --git a/include/linux/jump_label_ref.h b/include/linux/jump_label_ref.h
new file mode 100644
index 0000000..e5d012a
--- /dev/null
+++ b/include/linux/jump_label_ref.h
@@ -0,0 +1,44 @@
+#ifndef _LINUX_JUMP_LABEL_REF_H
+#define _LINUX_JUMP_LABEL_REF_H
+
+#include <linux/jump_label.h>
+#include <asm/atomic.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+static inline void jump_label_inc(atomic_t *key)
+{
+	if (atomic_add_return(1, key) == 1)
+		jump_label_enable(key);
+}
+
+static inline void jump_label_dec(atomic_t *key)
+{
+	if (atomic_dec_and_test(key))
+		jump_label_disable(key);
+}
+
+#else /* !HAVE_JUMP_LABEL */
+
+static inline void jump_label_inc(atomic_t *key)
+{
+	atomic_inc(key);
+}
+
+static inline void jump_label_dec(atomic_t *key)
+{
+	atomic_dec(key);
+}
+
+#undef JUMP_LABEL
+#define JUMP_LABEL(key, label)						\
+do {									\
+	if (unlikely(__builtin_choose_expr(				\
+	      __builtin_types_compatible_p(typeof(key), atomic_t *),	\
+	      atomic_read((atomic_t *)(key)), *(key))))			\
+		goto label;						\
+} while (0)
+
+#endif /* HAVE_JUMP_LABEL */
+
+#endif /* _LINUX_JUMP_LABEL_REF_H */
diff --git a/include/linux/kdb.h b/include/linux/kdb.h
index ea6e524..aadff7c 100644
--- a/include/linux/kdb.h
+++ b/include/linux/kdb.h
@@ -28,6 +28,41 @@
 extern int kdb_initial_cpu;
 extern atomic_t kdb_event;
 
+/* Types and messages used for dynamically added kdb shell commands */
+
+#define KDB_MAXARGS    16 /* Maximum number of arguments to a function  */
+
+typedef enum {
+	KDB_REPEAT_NONE = 0,	/* Do not repeat this command */
+	KDB_REPEAT_NO_ARGS,	/* Repeat the command without arguments */
+	KDB_REPEAT_WITH_ARGS,	/* Repeat the command including its arguments */
+} kdb_repeat_t;
+
+typedef int (*kdb_func_t)(int, const char **);
+
+/* KDB return codes from a command or internal kdb function */
+#define KDB_NOTFOUND	(-1)
+#define KDB_ARGCOUNT	(-2)
+#define KDB_BADWIDTH	(-3)
+#define KDB_BADRADIX	(-4)
+#define KDB_NOTENV	(-5)
+#define KDB_NOENVVALUE	(-6)
+#define KDB_NOTIMP	(-7)
+#define KDB_ENVFULL	(-8)
+#define KDB_ENVBUFFULL	(-9)
+#define KDB_TOOMANYBPT	(-10)
+#define KDB_TOOMANYDBREGS (-11)
+#define KDB_DUPBPT	(-12)
+#define KDB_BPTNOTFOUND	(-13)
+#define KDB_BADMODE	(-14)
+#define KDB_BADINT	(-15)
+#define KDB_INVADDRFMT  (-16)
+#define KDB_BADREG      (-17)
+#define KDB_BADCPUNUM   (-18)
+#define KDB_BADLENGTH	(-19)
+#define KDB_NOBP	(-20)
+#define KDB_BADADDR	(-21)
+
 /*
  * kdb_diemsg
  *
@@ -104,10 +139,26 @@
 
 /* kdb access to register set for stack dumping */
 extern struct pt_regs *kdb_current_regs;
+#ifdef CONFIG_KALLSYMS
+extern const char *kdb_walk_kallsyms(loff_t *pos);
+#else /* ! CONFIG_KALLSYMS */
+static inline const char *kdb_walk_kallsyms(loff_t *pos)
+{
+	return NULL;
+}
+#endif /* ! CONFIG_KALLSYMS */
 
+/* Dynamic kdb shell command registration */
+extern int kdb_register(char *, kdb_func_t, char *, char *, short);
+extern int kdb_register_repeat(char *, kdb_func_t, char *, char *,
+			       short, kdb_repeat_t);
+extern int kdb_unregister(char *);
 #else /* ! CONFIG_KGDB_KDB */
 #define kdb_printf(...)
 #define kdb_init(x)
+#define kdb_register(...)
+#define kdb_register_repeat(...)
+#define kdb_uregister(x)
 #endif	/* CONFIG_KGDB_KDB */
 enum {
 	KDB_NOT_INITIALIZED,
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2b0a35e..edef168 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -58,7 +58,18 @@
 
 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
-#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+#define roundup(x, y) (					\
+{							\
+	typeof(y) __y = y;				\
+	(((x) + (__y - 1)) / __y) * __y;		\
+}							\
+)
+#define rounddown(x, y) (				\
+{							\
+	typeof(x) __x = (x);				\
+	__x - (__x % (y));				\
+}							\
+)
 #define DIV_ROUND_CLOSEST(x, divisor)(			\
 {							\
 	typeof(divisor) __divisor = divisor;		\
@@ -641,6 +652,16 @@
 	_max1 > _max2 ? _max1 : _max2; })
 
 /**
+ * min_not_zero - return the minimum that is _not_ zero, unless both are zero
+ * @x: value1
+ * @y: value2
+ */
+#define min_not_zero(x, y) ({			\
+	typeof(x) __x = (x);			\
+	typeof(y) __y = (y);			\
+	__x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); })
+
+/**
  * clamp - return a value clamped to a given range with strict typechecking
  * @val: current value
  * @min: minimum allowable value
diff --git a/include/linux/key.h b/include/linux/key.h
index cd50dfa..3db0adc 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -178,8 +178,9 @@
 	 */
 	union {
 		unsigned long		value;
+		void __rcu		*rcudata;
 		void			*data;
-		struct keyring_list	*subscriptions;
+		struct keyring_list __rcu *subscriptions;
 	} payload;
 };
 
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 7950a37..8f6d121 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -191,6 +191,8 @@
 }
 
 extern struct kobject *kset_find_obj(struct kset *, const char *);
+extern struct kobject *kset_find_obj_hinted(struct kset *, const char *,
+						struct kobject *);
 
 /* The global /sys/kernel/ kobject for people to chain off of */
 extern struct kobject *kernel_kobj;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index c13cc48..ac740b2 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -205,7 +205,7 @@
 
 	struct mutex irq_lock;
 #ifdef CONFIG_HAVE_KVM_IRQCHIP
-	struct kvm_irq_routing_table *irq_routing;
+	struct kvm_irq_routing_table __rcu *irq_routing;
 	struct hlist_head mask_notifier_list;
 	struct hlist_head irq_ack_notifier_list;
 #endif
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 45fb296..15b77b8 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -37,6 +37,7 @@
 #include <scsi/scsi_host.h>
 #include <linux/acpi.h>
 #include <linux/cdrom.h>
+#include <linux/sched.h>
 
 /*
  * Define if arch has non-standard setup.  This is a _PCI_ standard
@@ -172,6 +173,7 @@
 	ATA_LFLAG_NO_RETRY	= (1 << 5), /* don't retry this link */
 	ATA_LFLAG_DISABLED	= (1 << 6), /* link is disabled */
 	ATA_LFLAG_SW_ACTIVITY	= (1 << 7), /* keep activity stats */
+	ATA_LFLAG_NO_LPM	= (1 << 8), /* disable LPM on this link */
 
 	/* struct ata_port flags */
 	ATA_FLAG_SLAVE_POSS	= (1 << 0), /* host supports slave dev */
@@ -196,7 +198,7 @@
 	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_IPM		= (1 << 20), /* driver can handle IPM */
+	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
@@ -324,12 +326,11 @@
 	ATA_EH_HARDRESET	= (1 << 2), /* meaningful only in ->prereset */
 	ATA_EH_RESET		= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
 	ATA_EH_ENABLE_LINK	= (1 << 3),
-	ATA_EH_LPM		= (1 << 4),  /* link power management action */
 	ATA_EH_PARK		= (1 << 5), /* unload heads and stop I/O */
 
 	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE | ATA_EH_PARK,
 	ATA_EH_ALL_ACTIONS	= ATA_EH_REVALIDATE | ATA_EH_RESET |
-				  ATA_EH_ENABLE_LINK | ATA_EH_LPM,
+				  ATA_EH_ENABLE_LINK,
 
 	/* ata_eh_info->flags */
 	ATA_EHI_HOTPLUGGED	= (1 << 0),  /* could have been hotplugged */
@@ -341,7 +342,7 @@
 	ATA_EHI_DID_HARDRESET	= (1 << 17), /* already soft-reset this port */
 	ATA_EHI_PRINTINFO	= (1 << 18), /* print configuration info */
 	ATA_EHI_SETMODE		= (1 << 19), /* configure transfer mode */
-	ATA_EHI_POST_SETMODE	= (1 << 20), /* revaildating after setmode */
+	ATA_EHI_POST_SETMODE	= (1 << 20), /* revalidating after setmode */
 
 	ATA_EHI_DID_RESET	= ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
 
@@ -377,7 +378,6 @@
 	ATA_HORKAGE_BROKEN_HPA	= (1 << 4),	/* Broken HPA */
 	ATA_HORKAGE_DISABLE	= (1 << 5),	/* Disable it */
 	ATA_HORKAGE_HPA_SIZE	= (1 << 6),	/* native size off by one */
-	ATA_HORKAGE_IPM		= (1 << 7),	/* Link PM problems */
 	ATA_HORKAGE_IVB		= (1 << 8),	/* cbl det validity bit bugs */
 	ATA_HORKAGE_STUCK_ERR	= (1 << 9),	/* stuck ERR on next PACKET */
 	ATA_HORKAGE_BRIDGE_OK	= (1 << 10),	/* no bridge limits */
@@ -464,6 +464,22 @@
 	AC_ERR_NCQ		= (1 << 10), /* marker for offending NCQ qc */
 };
 
+/*
+ * Link power management policy: If you alter this, you also need to
+ * alter libata-scsi.c (for the ascii descriptions)
+ */
+enum ata_lpm_policy {
+	ATA_LPM_UNKNOWN,
+	ATA_LPM_MAX_POWER,
+	ATA_LPM_MED_POWER,
+	ATA_LPM_MIN_POWER,
+};
+
+enum ata_lpm_hints {
+	ATA_LPM_EMPTY		= (1 << 0), /* port empty/probing */
+	ATA_LPM_HIPM		= (1 << 1), /* may use HIPM */
+};
+
 /* forward declarations */
 struct scsi_device;
 struct ata_port_operations;
@@ -478,16 +494,6 @@
 			      unsigned long deadline);
 typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes);
 
-/*
- * host pm policy: If you alter this, you also need to alter libata-scsi.c
- * (for the ascii descriptions)
- */
-enum link_pm {
-	NOT_AVAILABLE,
-	MIN_POWER,
-	MAX_PERFORMANCE,
-	MEDIUM_POWER,
-};
 extern struct device_attribute dev_attr_link_power_management_policy;
 extern struct device_attribute dev_attr_unload_heads;
 extern struct device_attribute dev_attr_em_message_type;
@@ -530,6 +536,10 @@
 	void			*private_data;
 	struct ata_port_operations *ops;
 	unsigned long		flags;
+
+	struct mutex		eh_mutex;
+	struct task_struct	*eh_owner;
+
 #ifdef CONFIG_ATA_ACPI
 	acpi_handle		acpi_handle;
 #endif
@@ -560,13 +570,13 @@
 	unsigned int		extrabytes;
 	unsigned int		curbytes;
 
-	struct scatterlist	*cursg;
-	unsigned int		cursg_ofs;
-
 	struct scatterlist	sgent;
 
 	struct scatterlist	*sg;
 
+	struct scatterlist	*cursg;
+	unsigned int		cursg_ofs;
+
 	unsigned int		err_mask;
 	struct ata_taskfile	result_tf;
 	ata_qc_cb_t		complete_fn;
@@ -604,6 +614,7 @@
 	union acpi_object	*gtf_cache;
 	unsigned int		gtf_filter;
 #endif
+	struct device		tdev;
 	/* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */
 	u64			n_sectors;	/* size of device, if ATA */
 	u64			n_native_sectors; /* native size, if ATA */
@@ -690,6 +701,7 @@
 	struct ata_port		*ap;
 	int			pmp;		/* port multiplier port # */
 
+	struct device		tdev;
 	unsigned int		active_tag;	/* active tag on this link */
 	u32			sactive;	/* active NCQ commands */
 
@@ -699,6 +711,7 @@
 	unsigned int		hw_sata_spd_limit;
 	unsigned int		sata_spd_limit;
 	unsigned int		sata_spd;	/* current SATA PHY speed */
+	enum ata_lpm_policy	lpm_policy;
 
 	/* record runtime error info, protected by host_set lock */
 	struct ata_eh_info	eh_info;
@@ -707,6 +720,8 @@
 
 	struct ata_device	device[ATA_MAX_DEVICES];
 };
+#define ATA_LINK_CLEAR_BEGIN		offsetof(struct ata_link, active_tag)
+#define ATA_LINK_CLEAR_END		offsetof(struct ata_link, device[0])
 
 struct ata_port {
 	struct Scsi_Host	*scsi_host; /* our co-allocated scsi host */
@@ -752,6 +767,7 @@
 	struct ata_port_stats	stats;
 	struct ata_host		*host;
 	struct device 		*dev;
+	struct device		tdev;
 
 	struct mutex		scsi_scan_mutex;
 	struct delayed_work	hotplug_task;
@@ -767,7 +783,7 @@
 
 	pm_message_t		pm_mesg;
 	int			*pm_result;
-	enum link_pm		pm_policy;
+	enum ata_lpm_policy	target_lpm_policy;
 
 	struct timer_list	fastdrain_timer;
 	unsigned long		fastdrain_cnt;
@@ -833,8 +849,8 @@
 	int  (*scr_write)(struct ata_link *link, unsigned int sc_reg, u32 val);
 	void (*pmp_attach)(struct ata_port *ap);
 	void (*pmp_detach)(struct ata_port *ap);
-	int  (*enable_pm)(struct ata_port *ap, enum link_pm policy);
-	void (*disable_pm)(struct ata_port *ap);
+	int  (*set_lpm)(struct ata_link *link, enum ata_lpm_policy policy,
+			unsigned hints);
 
 	/*
 	 * Start, stop, suspend and resume
@@ -946,6 +962,8 @@
 			const unsigned long *params, unsigned long deadline);
 extern int sata_link_resume(struct ata_link *link, const unsigned long *params,
 			    unsigned long deadline);
+extern int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+			     bool spm_wakeup);
 extern int sata_link_hardreset(struct ata_link *link,
 			const unsigned long *timing, unsigned long deadline,
 			bool *online, int (*check_ready)(struct ata_link *));
@@ -991,8 +1009,9 @@
 extern void ata_host_resume(struct ata_host *host);
 #endif
 extern int ata_ratelimit(void);
-extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
-			     unsigned long interval, unsigned long timeout);
+extern void ata_msleep(struct ata_port *ap, unsigned int msecs);
+extern u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask,
+			u32 val, unsigned long interval, unsigned long timeout);
 extern int atapi_cmd_type(u8 opcode);
 extern void ata_tf_to_fis(const struct ata_taskfile *tf,
 			  u8 pmp, int is_cmd, u8 *fis);
diff --git a/include/linux/list.h b/include/linux/list.h
index d167b5d..88a0006 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -5,7 +5,6 @@
 #include <linux/stddef.h>
 #include <linux/poison.h>
 #include <linux/prefetch.h>
-#include <asm/system.h>
 
 /*
  * Simple doubly linked list implementation.
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 06aed83..71c09b26 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -32,6 +32,17 @@
 #define MAX_LOCKDEP_SUBCLASSES		8UL
 
 /*
+ * NR_LOCKDEP_CACHING_CLASSES ... Number of classes
+ * cached in the instance of lockdep_map
+ *
+ * Currently main class (subclass == 0) and signle depth subclass
+ * are cached in lockdep_map. This optimization is mainly targeting
+ * on rq->lock. double_rq_lock() acquires this highly competitive with
+ * single depth.
+ */
+#define NR_LOCKDEP_CACHING_CLASSES	2
+
+/*
  * Lock-classes are keyed via unique addresses, by embedding the
  * lockclass-key into the kernel (or module) .data section. (For
  * static locks we use the lock address itself as the key.)
@@ -138,7 +149,7 @@
  */
 struct lockdep_map {
 	struct lock_class_key		*key;
-	struct lock_class		*class_cache;
+	struct lock_class		*class_cache[NR_LOCKDEP_CACHING_CLASSES];
 	const char			*name;
 #ifdef CONFIG_LOCK_STAT
 	int				cpu;
@@ -424,14 +435,6 @@
 
 #endif /* CONFIG_LOCKDEP */
 
-#ifdef CONFIG_GENERIC_HARDIRQS
-extern void early_init_irq_lock_class(void);
-#else
-static inline void early_init_irq_lock_class(void)
-{
-}
-#endif
-
 #ifdef CONFIG_TRACE_IRQFLAGS
 extern void early_boot_irqs_off(void);
 extern void early_boot_irqs_on(void);
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index a59faf2..62a10c2 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -2,6 +2,7 @@
 #define _LINUX_MEMBLOCK_H
 #ifdef __KERNEL__
 
+#ifdef CONFIG_HAVE_MEMBLOCK
 /*
  * Logical memory blocks.
  *
@@ -16,73 +17,150 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 
-#define MAX_MEMBLOCK_REGIONS 128
+#include <asm/memblock.h>
 
-struct memblock_property {
-	u64 base;
-	u64 size;
-};
+#define INIT_MEMBLOCK_REGIONS	128
+#define MEMBLOCK_ERROR		0
 
 struct memblock_region {
-	unsigned long cnt;
-	u64 size;
-	struct memblock_property region[MAX_MEMBLOCK_REGIONS+1];
+	phys_addr_t base;
+	phys_addr_t size;
+};
+
+struct memblock_type {
+	unsigned long cnt;	/* number of regions */
+	unsigned long max;	/* size of the allocated array */
+	struct memblock_region *regions;
 };
 
 struct memblock {
-	unsigned long debug;
-	u64 rmo_size;
-	struct memblock_region memory;
-	struct memblock_region reserved;
+	phys_addr_t current_limit;
+	phys_addr_t memory_size;	/* Updated by memblock_analyze() */
+	struct memblock_type memory;
+	struct memblock_type reserved;
 };
 
 extern struct memblock memblock;
+extern int memblock_debug;
+extern int memblock_can_resize;
 
-extern void __init memblock_init(void);
-extern void __init memblock_analyze(void);
-extern long memblock_add(u64 base, u64 size);
-extern long memblock_remove(u64 base, u64 size);
-extern long __init memblock_free(u64 base, u64 size);
-extern long __init memblock_reserve(u64 base, u64 size);
-extern u64 __init memblock_alloc_nid(u64 size, u64 align, int nid,
-				u64 (*nid_range)(u64, u64, int *));
-extern u64 __init memblock_alloc(u64 size, u64 align);
-extern u64 __init memblock_alloc_base(u64 size,
-		u64, u64 max_addr);
-extern u64 __init __memblock_alloc_base(u64 size,
-		u64 align, u64 max_addr);
-extern u64 __init memblock_phys_mem_size(void);
-extern u64 memblock_end_of_DRAM(void);
-extern void __init memblock_enforce_memory_limit(u64 memory_limit);
-extern int __init memblock_is_reserved(u64 addr);
-extern int memblock_is_region_reserved(u64 base, u64 size);
-extern int memblock_find(struct memblock_property *res);
+#define memblock_dbg(fmt, ...) \
+	if (memblock_debug) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
+
+u64 memblock_find_in_range(u64 start, u64 end, u64 size, u64 align);
+int memblock_free_reserved_regions(void);
+int memblock_reserve_reserved_regions(void);
+
+extern void memblock_init(void);
+extern void memblock_analyze(void);
+extern long memblock_add(phys_addr_t base, phys_addr_t size);
+extern long memblock_remove(phys_addr_t base, phys_addr_t size);
+extern long memblock_free(phys_addr_t base, phys_addr_t size);
+extern long memblock_reserve(phys_addr_t base, phys_addr_t size);
+
+/* The numa aware allocator is only available if
+ * CONFIG_ARCH_POPULATES_NODE_MAP is set
+ */
+extern phys_addr_t memblock_alloc_nid(phys_addr_t size, phys_addr_t align,
+					int nid);
+extern phys_addr_t memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align,
+					    int nid);
+
+extern phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align);
+
+/* Flags for memblock_alloc_base() amd __memblock_alloc_base() */
+#define MEMBLOCK_ALLOC_ANYWHERE	(~(phys_addr_t)0)
+#define MEMBLOCK_ALLOC_ACCESSIBLE	0
+
+extern phys_addr_t memblock_alloc_base(phys_addr_t size,
+					 phys_addr_t align,
+					 phys_addr_t max_addr);
+extern phys_addr_t __memblock_alloc_base(phys_addr_t size,
+					   phys_addr_t align,
+					   phys_addr_t max_addr);
+extern phys_addr_t memblock_phys_mem_size(void);
+extern phys_addr_t memblock_end_of_DRAM(void);
+extern void memblock_enforce_memory_limit(phys_addr_t memory_limit);
+extern int memblock_is_memory(phys_addr_t addr);
+extern int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
+extern int memblock_is_reserved(phys_addr_t addr);
+extern int memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
 
 extern void memblock_dump_all(void);
 
-static inline u64
-memblock_size_bytes(struct memblock_region *type, unsigned long region_nr)
+/* Provided by the architecture */
+extern phys_addr_t memblock_nid_range(phys_addr_t start, phys_addr_t end, int *nid);
+extern int memblock_memory_can_coalesce(phys_addr_t addr1, phys_addr_t size1,
+				   phys_addr_t addr2, phys_addr_t size2);
+
+/**
+ * memblock_set_current_limit - Set the current allocation limit to allow
+ *                         limiting allocations to what is currently
+ *                         accessible during boot
+ * @limit: New limit value (physical address)
+ */
+extern void memblock_set_current_limit(phys_addr_t limit);
+
+
+/*
+ * pfn conversion functions
+ *
+ * While the memory MEMBLOCKs should always be page aligned, the reserved
+ * MEMBLOCKs may not be. This accessor attempt to provide a very clear
+ * idea of what they return for such non aligned MEMBLOCKs.
+ */
+
+/**
+ * memblock_region_memory_base_pfn - Return the lowest pfn intersecting with the memory region
+ * @reg: memblock_region structure
+ */
+static inline unsigned long memblock_region_memory_base_pfn(const struct memblock_region *reg)
 {
-	return type->region[region_nr].size;
-}
-static inline u64
-memblock_size_pages(struct memblock_region *type, unsigned long region_nr)
-{
-	return memblock_size_bytes(type, region_nr) >> PAGE_SHIFT;
-}
-static inline u64
-memblock_start_pfn(struct memblock_region *type, unsigned long region_nr)
-{
-	return type->region[region_nr].base >> PAGE_SHIFT;
-}
-static inline u64
-memblock_end_pfn(struct memblock_region *type, unsigned long region_nr)
-{
-	return memblock_start_pfn(type, region_nr) +
-	       memblock_size_pages(type, region_nr);
+	return PFN_UP(reg->base);
 }
 
-#include <asm/memblock.h>
+/**
+ * memblock_region_memory_end_pfn - Return the end_pfn this region
+ * @reg: memblock_region structure
+ */
+static inline unsigned long memblock_region_memory_end_pfn(const struct memblock_region *reg)
+{
+	return PFN_DOWN(reg->base + reg->size);
+}
+
+/**
+ * memblock_region_reserved_base_pfn - Return the lowest pfn intersecting with the reserved region
+ * @reg: memblock_region structure
+ */
+static inline unsigned long memblock_region_reserved_base_pfn(const struct memblock_region *reg)
+{
+	return PFN_DOWN(reg->base);
+}
+
+/**
+ * memblock_region_reserved_end_pfn - Return the end_pfn this region
+ * @reg: memblock_region structure
+ */
+static inline unsigned long memblock_region_reserved_end_pfn(const struct memblock_region *reg)
+{
+	return PFN_UP(reg->base + reg->size);
+}
+
+#define for_each_memblock(memblock_type, region)					\
+	for (region = memblock.memblock_type.regions;				\
+	     region < (memblock.memblock_type.regions + memblock.memblock_type.cnt);	\
+	     region++)
+
+
+#ifdef ARCH_DISCARD_MEMBLOCK
+#define __init_memblock __init
+#define __initdata_memblock __initdata
+#else
+#define __init_memblock
+#define __initdata_memblock
+#endif
+
+#endif /* CONFIG_HAVE_MEMBLOCK */
 
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 85582e1..06c1fa0 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -23,6 +23,8 @@
 struct memory_block {
 	unsigned long phys_index;
 	unsigned long state;
+	int section_count;
+
 	/*
 	 * This serializes all state change requests.  It isn't
 	 * held during creation because the control files are
@@ -113,6 +115,8 @@
 extern int remove_memory_block(unsigned long, struct mem_section *, int);
 extern int memory_notify(unsigned long val, void *v);
 extern int memory_isolate_notify(unsigned long val, void *v);
+extern struct memory_block *find_memory_block_hinted(struct mem_section *,
+							struct memory_block *);
 extern struct memory_block *find_memory_block(struct mem_section *);
 #define CONFIG_MEM_BLOCK_SIZE	(PAGES_PER_SECTION<<PAGE_SHIFT)
 enum mem_add_context { BOOT, HOTPLUG };
diff --git a/include/linux/mfd/tc35892.h b/include/linux/mfd/tc35892.h
index e47f770..eff3094 100644
--- a/include/linux/mfd/tc35892.h
+++ b/include/linux/mfd/tc35892.h
@@ -111,9 +111,13 @@
  * struct tc35892_gpio_platform_data - TC35892 GPIO platform data
  * @gpio_base: first gpio number assigned to TC35892.  A maximum of
  *	       %TC35892_NR_GPIOS GPIOs will be allocated.
+ * @setup: callback for board-specific initialization
+ * @remove: callback for board-specific teardown
  */
 struct tc35892_gpio_platform_data {
 	int gpio_base;
+	void (*setup)(struct tc35892 *tc35892, unsigned gpio_base);
+	void (*remove)(struct tc35892 *tc35892, unsigned gpio_base);
 };
 
 /**
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 0f82293..78a1b96 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -56,6 +56,7 @@
 	MLX4_CMD_QUERY_HCA	 = 0xb,
 	MLX4_CMD_QUERY_PORT	 = 0x43,
 	MLX4_CMD_SENSE_PORT	 = 0x4d,
+	MLX4_CMD_HW_HEALTH_CHECK = 0x50,
 	MLX4_CMD_SET_PORT	 = 0xc,
 	MLX4_CMD_ACCESS_DDR	 = 0x2e,
 	MLX4_CMD_MAP_ICM	 = 0xffa,
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 7a7f9c1..7338654 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -186,6 +186,10 @@
 	int			eth_mtu_cap[MLX4_MAX_PORTS + 1];
 	int			gid_table_len[MLX4_MAX_PORTS + 1];
 	int			pkey_table_len[MLX4_MAX_PORTS + 1];
+	int			trans_type[MLX4_MAX_PORTS + 1];
+	int			vendor_oui[MLX4_MAX_PORTS + 1];
+	int			wavelength[MLX4_MAX_PORTS + 1];
+	u64			trans_code[MLX4_MAX_PORTS + 1];
 	int			local_ca_ack_delay;
 	int			num_uars;
 	int			bf_reg_size;
@@ -229,6 +233,8 @@
 	u32			bmme_flags;
 	u32			reserved_lkey;
 	u16			stat_rate_support;
+	int			udp_rss;
+	int			loopback_support;
 	u8			port_width_cap[MLX4_MAX_PORTS + 1];
 	int			max_gso_sz;
 	int                     reserved_qps_cnt[MLX4_NUM_QP_REGION];
@@ -480,5 +486,6 @@
 		    u32 *lkey, u32 *rkey);
 int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr);
 int mlx4_SYNC_TPT(struct mlx4_dev *dev);
+int mlx4_test_interrupts(struct mlx4_dev *dev);
 
 #endif /* MLX4_DEVICE_H */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 74949fb..7687228 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1175,6 +1175,8 @@
 						unsigned long max_low_pfn);
 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 *);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index ee7e258..cb57d65 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -299,7 +299,7 @@
 	 * new_owner->mm == mm
 	 * new_owner->alloc_lock is held
 	 */
-	struct task_struct *owner;
+	struct task_struct __rcu *owner;
 #endif
 
 #ifdef CONFIG_PROC_FS
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index 33b2ea0..a36ab3b 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -18,6 +18,7 @@
 #define SDIO_CLASS_PHS		0x06	/* PHS standard interface */
 #define SDIO_CLASS_WLAN		0x07	/* WLAN interface */
 #define SDIO_CLASS_ATA		0x08	/* Embedded SDIO-ATA std interface */
+#define SDIO_CLASS_BT_AMP	0x09	/* Type-A Bluetooth AMP interface */
 
 /*
  * Vendors and devices.  Sort key: vendor first, device next.
diff --git a/include/linux/module.h b/include/linux/module.h
index 8a6b9fd..b29e745 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -350,7 +350,10 @@
 	struct tracepoint *tracepoints;
 	unsigned int num_tracepoints;
 #endif
-
+#ifdef HAVE_JUMP_LABEL
+	struct jump_entry *jump_entries;
+	unsigned int num_jump_entries;
+#endif
 #ifdef CONFIG_TRACING
 	const char **trace_bprintk_fmt_start;
 	unsigned int num_trace_bprintk_fmt;
@@ -686,17 +689,16 @@
 
 
 #ifdef CONFIG_GENERIC_BUG
-int  module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
+void module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
 			 struct module *);
 void module_bug_cleanup(struct module *);
 
 #else	/* !CONFIG_GENERIC_BUG */
 
-static inline int  module_bug_finalize(const Elf_Ehdr *hdr,
+static inline void module_bug_finalize(const Elf_Ehdr *hdr,
 					const Elf_Shdr *sechdrs,
 					struct module *mod)
 {
-	return 0;
 }
 static inline void module_bug_cleanup(struct module *mod) {}
 #endif	/* CONFIG_GENERIC_BUG */
diff --git a/include/linux/mroute.h b/include/linux/mroute.h
index fa04b24..0fa7a3a 100644
--- a/include/linux/mroute.h
+++ b/include/linux/mroute.h
@@ -213,6 +213,7 @@
 			unsigned char ttls[MAXVIFS];	/* TTL thresholds		*/
 		} res;
 	} mfc_un;
+	struct rcu_head	rcu;
 };
 
 #define MFC_STATIC		1
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 91b05c1..05acced 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -10,12 +10,13 @@
 };
 
 /* Helper functions */
-struct irq_desc;
-extern void mask_msi_irq(unsigned int irq);
-extern void unmask_msi_irq(unsigned int irq);
-extern void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
-extern void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
-extern void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
+struct irq_data;
+struct msi_desc;
+extern void mask_msi_irq(struct irq_data *data);
+extern void unmask_msi_irq(struct irq_data *data);
+extern void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+extern void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+extern void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
 extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
 extern void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
 extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
diff --git a/include/linux/mtio.h b/include/linux/mtio.h
index ef01d6a..8f82575 100644
--- a/include/linux/mtio.h
+++ b/include/linux/mtio.h
@@ -63,6 +63,7 @@
 #define MTCOMPRESSION 32/* control compression with SCSI mode page 15 */
 #define MTSETPART 33	/* Change the active tape partition */
 #define MTMKPART  34	/* Format the tape with one or two partitions */
+#define MTWEOFI	35	/* write an end-of-file record (mark) in immediate mode */
 
 /* structure for MTIOCGET - mag tape get status command */
 
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 4522aed..ef66306 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -241,34 +241,6 @@
 /* linux/fs/ncpfs/ncplib_kernel.c */
 int ncp_make_closed(struct inode *);
 
-#define ncp_namespace(i)	(NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
-
-static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
-{
-#ifdef CONFIG_NCPFS_SMALLDOS
-	int ns = ncp_namespace(i);
-
-	if ((ns == NW_NS_DOS)
-#ifdef CONFIG_NCPFS_OS2_NS
-		|| ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
-#endif /* CONFIG_NCPFS_OS2_NS */
-				)
-		return 0;
-#endif /* CONFIG_NCPFS_SMALLDOS */
-	return 1;
-}
-
-#define ncp_preserve_case(i)	(ncp_namespace(i) != NW_NS_DOS)
-
-static inline int ncp_case_sensitive(struct inode *i)
-{
-#ifdef CONFIG_NCPFS_NFS_NS
-	return ncp_namespace(i) == NW_NS_NFS;
-#else
-	return 0;
-#endif	/* CONFIG_NCPFS_NFS_NS */
-} 
-
 #endif				/* __KERNEL__ */
 
 #endif				/* _LINUX_NCP_FS_H */
diff --git a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h
index 8da05bc..d64b0e8 100644
--- a/include/linux/ncp_fs_sb.h
+++ b/include/linux/ncp_fs_sb.h
@@ -62,6 +62,7 @@
 	int ncp_reply_size;
 
 	int root_setuped;
+	struct mutex root_setup_lock;
 
 	/* info for packet signing */
 	int sign_wanted;	/* 1=Server needs signed packets */
@@ -81,13 +82,14 @@
 		size_t	len;
 		void*	data;
 	} priv;
+	struct rw_semaphore auth_rwsem;
 
 	/* nls info: codepage for volume and charset for I/O */
 	struct nls_table *nls_vol;
 	struct nls_table *nls_io;
 
 	/* maximum age in jiffies */
-	int dentry_ttl;
+	atomic_t dentry_ttl;
 
 	/* miscellaneous */
 	unsigned int flags;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 46c36ff..fcd3dda 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -228,9 +228,9 @@
 #define NETDEV_HW_ADDR_T_SLAVE		3
 #define NETDEV_HW_ADDR_T_UNICAST	4
 #define NETDEV_HW_ADDR_T_MULTICAST	5
-	int			refcount;
 	bool			synced;
 	bool			global_use;
+	int			refcount;
 	struct rcu_head		rcu_head;
 };
 
@@ -281,6 +281,12 @@
 	unsigned long	hh_data[HH_DATA_ALIGN(LL_MAX_HEADER) / sizeof(long)];
 };
 
+static inline void hh_cache_put(struct hh_cache *hh)
+{
+	if (atomic_dec_and_test(&hh->hh_refcnt))
+		kfree(hh);
+}
+
 /* Reserve HH_DATA_MOD byte aligned hard_header_len, but at least that much.
  * Alternative is:
  *   dev->hard_header_len ? (dev->hard_header_len +
@@ -884,6 +890,9 @@
 	int			iflink;
 
 	struct net_device_stats	stats;
+	atomic_long_t		rx_dropped; /* dropped packets by core network
+					     * Do not use this in drivers.
+					     */
 
 #ifdef CONFIG_WIRELESS_EXT
 	/* List of functions to handle Wireless Extensions (instead of ioctl).
@@ -901,7 +910,7 @@
 
 	unsigned int		flags;	/* interface flags (a la BSD)	*/
 	unsigned short		gflags;
-        unsigned short          priv_flags; /* Like 'flags' but invisible to userspace. */
+        unsigned int            priv_flags; /* Like 'flags' but invisible to userspace. */
 	unsigned short		padded;	/* How much padding added by alloc_netdev() */
 
 	unsigned char		operstate; /* RFC2863 operstate */
@@ -918,10 +927,6 @@
 	unsigned short		needed_headroom;
 	unsigned short		needed_tailroom;
 
-	struct net_device	*master; /* Pointer to master device of a group,
-					  * which this device is member of.
-					  */
-
 	/* Interface address info. */
 	unsigned char		perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
 	unsigned char		addr_assign_type; /* hw address assignment type */
@@ -937,12 +942,15 @@
 
 
 	/* Protocol specific pointers */
-	
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+	struct vlan_group	*vlgrp;		/* VLAN group */
+#endif
 #ifdef CONFIG_NET_DSA
 	void			*dsa_ptr;	/* dsa specific data */
 #endif
 	void 			*atalk_ptr;	/* AppleTalk link 	*/
-	void			*ip_ptr;	/* IPv4 specific data	*/
+	struct in_device __rcu	*ip_ptr;	/* IPv4 specific data	*/
 	void                    *dn_ptr;        /* DECnet specific data */
 	void                    *ip6_ptr;       /* IPv6 specific data */
 	void			*ec_ptr;	/* Econet specific data	*/
@@ -951,9 +959,20 @@
 						   assign before registering */
 
 /*
- * Cache line mostly used on receive path (including eth_type_trans())
+ * Cache lines mostly used on receive path (including eth_type_trans())
  */
-	unsigned long		last_rx;	/* Time of last Rx	*/
+	unsigned long		last_rx;	/* Time of last Rx
+						 * This should not be set in
+						 * drivers, unless really needed,
+						 * because network stack (bonding)
+						 * use it if/when necessary, to
+						 * avoid dirtying this cache line.
+						 */
+
+	struct net_device	*master; /* Pointer to master device of a group,
+					  * which this device is member of.
+					  */
+
 	/* Interface address info used in eth_type_trans() */
 	unsigned char		*dev_addr;	/* hw address, (before bcast
 						   because most packets are
@@ -969,14 +988,21 @@
 
 	struct netdev_rx_queue	*_rx;
 
-	/* Number of RX queues allocated at alloc_netdev_mq() time  */
+	/* Number of RX queues allocated at register_netdev() time */
 	unsigned int		num_rx_queues;
+
+	/* Number of RX queues currently active in device */
+	unsigned int		real_num_rx_queues;
 #endif
 
-	struct netdev_queue	rx_queue;
 	rx_handler_func_t	*rx_handler;
 	void			*rx_handler_data;
 
+	struct netdev_queue __rcu *ingress_queue;
+
+/*
+ * Cache lines mostly used on transmit path
+ */
 	struct netdev_queue	*_tx ____cacheline_aligned_in_smp;
 
 	/* Number of TX queues allocated at alloc_netdev_mq() time  */
@@ -990,9 +1016,7 @@
 
 	unsigned long		tx_queue_len;	/* Max frames per queue allowed */
 	spinlock_t		tx_global_lock;
-/*
- * One part is mostly used on xmit path (device)
- */
+
 	/* These may be needed for future network-power-down code. */
 
 	/*
@@ -1005,7 +1029,7 @@
 	struct timer_list	watchdog_timer;
 
 	/* Number of references to this device */
-	atomic_t		refcnt ____cacheline_aligned_in_smp;
+	int __percpu		*pcpu_refcnt;
 
 	/* delayed register/unregister */
 	struct list_head	todo_list;
@@ -1041,8 +1065,12 @@
 #endif
 
 	/* mid-layer private */
-	void			*ml_priv;
-
+	union {
+		void				*ml_priv;
+		struct pcpu_lstats __percpu	*lstats; /* loopback stats */
+		struct pcpu_tstats __percpu	*tstats; /* tunnel stats */
+		struct pcpu_dstats __percpu	*dstats; /* dummy stats */
+	};
 	/* GARP */
 	struct garp_port	*garp_port;
 
@@ -1305,6 +1333,7 @@
 	unregister_netdevice_queue(dev, NULL);
 }
 
+extern int 		netdev_refcnt_read(const struct net_device *dev);
 extern void		free_netdev(struct net_device *dev);
 extern void		synchronize_net(void);
 extern int 		register_netdevice_notifier(struct notifier_block *nb);
@@ -1667,11 +1696,34 @@
  */
 static inline int netif_is_multiqueue(const struct net_device *dev)
 {
-	return (dev->num_tx_queues > 1);
+	return dev->num_tx_queues > 1;
 }
 
-extern void netif_set_real_num_tx_queues(struct net_device *dev,
-					 unsigned int txq);
+extern int netif_set_real_num_tx_queues(struct net_device *dev,
+					unsigned int txq);
+
+#ifdef CONFIG_RPS
+extern int netif_set_real_num_rx_queues(struct net_device *dev,
+					unsigned int rxq);
+#else
+static inline int netif_set_real_num_rx_queues(struct net_device *dev,
+						unsigned int rxq)
+{
+	return 0;
+}
+#endif
+
+static inline int netif_copy_real_num_queues(struct net_device *to_dev,
+					     const struct net_device *from_dev)
+{
+	netif_set_real_num_tx_queues(to_dev, from_dev->real_num_tx_queues);
+#ifdef CONFIG_RPS
+	return netif_set_real_num_rx_queues(to_dev,
+					    from_dev->real_num_rx_queues);
+#else
+	return 0;
+#endif
+}
 
 /* Use this variant when it is known for sure that it
  * is executing from hardware interrupt context or with hardware interrupts
@@ -1695,8 +1747,7 @@
 extern gro_result_t	napi_skb_finish(gro_result_t ret, struct sk_buff *skb);
 extern gro_result_t	napi_gro_receive(struct napi_struct *napi,
 					 struct sk_buff *skb);
-extern void		napi_reuse_skb(struct napi_struct *napi,
-				       struct sk_buff *skb);
+extern void		napi_gro_flush(struct napi_struct *napi);
 extern struct sk_buff *	napi_get_frags(struct napi_struct *napi);
 extern gro_result_t	napi_frags_finish(struct napi_struct *napi,
 					  struct sk_buff *skb,
@@ -1715,7 +1766,6 @@
 				      void *rx_handler_data);
 extern void netdev_rx_handler_unregister(struct net_device *dev);
 
-extern void		netif_nit_deliver(struct sk_buff *skb);
 extern int		dev_valid_name(const char *name);
 extern int		dev_ioctl(struct net *net, unsigned int cmd, void __user *);
 extern int		dev_ethtool(struct net *net, struct ifreq *);
@@ -1749,7 +1799,7 @@
  */
 static inline void dev_put(struct net_device *dev)
 {
-	atomic_dec(&dev->refcnt);
+	irqsafe_cpu_dec(*dev->pcpu_refcnt);
 }
 
 /**
@@ -1760,7 +1810,7 @@
  */
 static inline void dev_hold(struct net_device *dev)
 {
-	atomic_inc(&dev->refcnt);
+	irqsafe_cpu_inc(*dev->pcpu_refcnt);
 }
 
 /* Carrier loss detection, dial on demand. The functions netif_carrier_on
@@ -2171,6 +2221,8 @@
 extern int netdev_class_create_file(struct class_attribute *class_attr);
 extern void netdev_class_remove_file(struct class_attribute *class_attr);
 
+extern struct kobj_ns_type_operations net_ns_type_operations;
+
 extern char *netdev_drivername(const struct net_device *dev, char *buffer, int len);
 
 extern void linkwatch_run_queue(void);
@@ -2191,14 +2243,22 @@
 static inline int skb_gso_ok(struct sk_buff *skb, int features)
 {
 	return net_gso_ok(features, skb_shinfo(skb)->gso_type) &&
-	       (!skb_has_frags(skb) || (features & NETIF_F_FRAGLIST));
+	       (!skb_has_frag_list(skb) || (features & NETIF_F_FRAGLIST));
 }
 
 static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
 {
-	return skb_is_gso(skb) &&
-	       (!skb_gso_ok(skb, dev->features) ||
-		unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
+	if (skb_is_gso(skb)) {
+		int features = dev->features;
+
+		if (skb->protocol == htons(ETH_P_8021Q) || skb->vlan_tci)
+			features &= dev->vlan_features;
+
+		return (!skb_gso_ok(skb, features) ||
+			unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
+	}
+
+	return 0;
 }
 
 static inline void netif_set_gso_max_size(struct net_device *dev,
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index 1afd18c..50cdc25 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -98,8 +98,14 @@
 
 enum ip_conntrack_expect_events {
 	IPEXP_NEW,		/* new expectation */
+	IPEXP_DESTROY,		/* destroyed expectation */
 };
 
+/* expectation flags */
+#define NF_CT_EXPECT_PERMANENT		0x1
+#define NF_CT_EXPECT_INACTIVE		0x2
+#define NF_CT_EXPECT_USERSPACE		0x4
+
 #ifdef __KERNEL__
 struct ip_conntrack_stat {
 	unsigned int searched;
diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h
index ff8cfbc..0ce91d5 100644
--- a/include/linux/netfilter/nf_conntrack_sip.h
+++ b/include/linux/netfilter/nf_conntrack_sip.h
@@ -89,6 +89,7 @@
 	SIP_HDR_VIA_TCP,
 	SIP_HDR_EXPIRES,
 	SIP_HDR_CONTENT_LENGTH,
+	SIP_HDR_CALL_ID,
 };
 
 enum sdp_header_types {
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
index 9ed534c..19711e3 100644
--- a/include/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/linux/netfilter/nfnetlink_conntrack.h
@@ -39,8 +39,9 @@
 	CTA_TUPLE_MASTER,
 	CTA_NAT_SEQ_ADJ_ORIG,
 	CTA_NAT_SEQ_ADJ_REPLY,
-	CTA_SECMARK,
+	CTA_SECMARK,		/* obsolete */
 	CTA_ZONE,
+	CTA_SECCTX,
 	__CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
@@ -161,6 +162,7 @@
 	CTA_EXPECT_ID,
 	CTA_EXPECT_HELP_NAME,
 	CTA_EXPECT_ZONE,
+	CTA_EXPECT_FLAGS,
 	__CTA_EXPECT_MAX
 };
 #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1)
@@ -172,4 +174,11 @@
 };
 #define CTA_HELP_MAX (__CTA_HELP_MAX - 1)
 
+enum ctattr_secctx {
+	CTA_SECCTX_UNSPEC,
+	CTA_SECCTX_NAME,
+	__CTA_SECCTX_MAX
+};
+#define CTA_SECCTX_MAX (__CTA_SECCTX_MAX - 1)
+
 #endif /* _IPCONNTRACK_NETLINK_H */
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 24e5d01..742bec0 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -66,6 +66,11 @@
 	int verdict;
 };
 
+struct xt_error_target {
+	struct xt_entry_target target;
+	char errorname[XT_FUNCTION_MAXNAMELEN];
+};
+
 /* The argument to IPT_SO_GET_REVISION_*.  Returns highest revision
  * kernel supports, if >= revision. */
 struct xt_get_revision {
diff --git a/include/linux/netfilter/xt_SECMARK.h b/include/linux/netfilter/xt_SECMARK.h
index 6fcd344..989092b 100644
--- a/include/linux/netfilter/xt_SECMARK.h
+++ b/include/linux/netfilter/xt_SECMARK.h
@@ -11,18 +11,12 @@
  * packets are being marked for.
  */
 #define SECMARK_MODE_SEL	0x01		/* SELinux */
-#define SECMARK_SELCTX_MAX	256
-
-struct xt_secmark_target_selinux_info {
-	__u32 selsid;
-	char selctx[SECMARK_SELCTX_MAX];
-};
+#define SECMARK_SECCTX_MAX	256
 
 struct xt_secmark_target_info {
 	__u8 mode;
-	union {
-		struct xt_secmark_target_selinux_info sel;
-	} u;
+	__u32 secid;
+	char secctx[SECMARK_SECCTX_MAX];
 };
 
 #endif /*_XT_SECMARK_H_target */
diff --git a/include/linux/netfilter/xt_TPROXY.h b/include/linux/netfilter/xt_TPROXY.h
index 152e8f9..3f3d693 100644
--- a/include/linux/netfilter/xt_TPROXY.h
+++ b/include/linux/netfilter/xt_TPROXY.h
@@ -1,5 +1,5 @@
-#ifndef _XT_TPROXY_H_target
-#define _XT_TPROXY_H_target
+#ifndef _XT_TPROXY_H
+#define _XT_TPROXY_H
 
 /* TPROXY target is capable of marking the packet to perform
  * redirection. We can get rid of that whenever we get support for
@@ -11,4 +11,11 @@
 	__be16 lport;
 };
 
-#endif /* _XT_TPROXY_H_target */
+struct xt_tproxy_target_info_v1 {
+	u_int32_t mark_mask;
+	u_int32_t mark_value;
+	union nf_inet_addr laddr;
+	__be16 lport;
+};
+
+#endif /* _XT_TPROXY_H */
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index e9948c0..adbf4bf 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -21,8 +21,21 @@
 
 #include <linux/netfilter/x_tables.h>
 
+#ifndef __KERNEL__
 #define ARPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
 #define ARPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
+#define arpt_entry_target xt_entry_target
+#define arpt_standard_target xt_standard_target
+#define arpt_error_target xt_error_target
+#define ARPT_CONTINUE XT_CONTINUE
+#define ARPT_RETURN XT_RETURN
+#define arpt_counters_info xt_counters_info
+#define arpt_counters xt_counters
+#define ARPT_STANDARD_TARGET XT_STANDARD_TARGET
+#define ARPT_ERROR_TARGET XT_ERROR_TARGET
+#define ARPT_ENTRY_ITERATE(entries, size, fn, args...) \
+	XT_ENTRY_ITERATE(struct arpt_entry, entries, size, fn, ## args)
+#endif
 
 #define ARPT_DEV_ADDR_LEN_MAX 16
 
@@ -63,9 +76,6 @@
 	u_int16_t invflags;
 };
 
-#define arpt_entry_target xt_entry_target
-#define arpt_standard_target xt_standard_target
-
 /* Values for "flag" field in struct arpt_ip (general arp structure).
  * No flags defined yet.
  */
@@ -125,16 +135,10 @@
 #define ARPT_SO_GET_REVISION_TARGET	(ARPT_BASE_CTL + 3)
 #define ARPT_SO_GET_MAX			(ARPT_SO_GET_REVISION_TARGET)
 
-/* CONTINUE verdict for targets */
-#define ARPT_CONTINUE XT_CONTINUE
-
-/* For standard target */
-#define ARPT_RETURN XT_RETURN
-
 /* The argument to ARPT_SO_GET_INFO */
 struct arpt_getinfo {
 	/* Which table: caller fills this in. */
-	char name[ARPT_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 
 	/* Kernel fills these in. */
 	/* Which hook entry points are valid: bitmask */
@@ -156,7 +160,7 @@
 /* The argument to ARPT_SO_SET_REPLACE. */
 struct arpt_replace {
 	/* Which table. */
-	char name[ARPT_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 
 	/* Which hook entry points are valid: bitmask.  You can't
            change this. */
@@ -184,14 +188,10 @@
 	struct arpt_entry entries[0];
 };
 
-/* The argument to ARPT_SO_ADD_COUNTERS. */
-#define arpt_counters_info xt_counters_info
-#define arpt_counters xt_counters
-
 /* The argument to ARPT_SO_GET_ENTRIES. */
 struct arpt_get_entries {
 	/* Which table: user fills this in. */
-	char name[ARPT_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 
 	/* User fills this in: total entry size. */
 	unsigned int size;
@@ -200,23 +200,12 @@
 	struct arpt_entry entrytable[0];
 };
 
-/* Standard return verdict, or do jump. */
-#define ARPT_STANDARD_TARGET XT_STANDARD_TARGET
-/* Error verdict. */
-#define ARPT_ERROR_TARGET XT_ERROR_TARGET
-
 /* Helper functions */
-static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e)
+static __inline__ struct xt_entry_target *arpt_get_target(struct arpt_entry *e)
 {
 	return (void *)e + e->target_offset;
 }
 
-#ifndef __KERNEL__
-/* fn returns 0 to continue iteration */
-#define ARPT_ENTRY_ITERATE(entries, size, fn, args...) \
-	XT_ENTRY_ITERATE(struct arpt_entry, entries, size, fn, ## args)
-#endif
-
 /*
  *	Main firewall chains definitions and global var's definitions.
  */
@@ -225,17 +214,12 @@
 /* Standard entry. */
 struct arpt_standard {
 	struct arpt_entry entry;
-	struct arpt_standard_target target;
-};
-
-struct arpt_error_target {
-	struct arpt_entry_target target;
-	char errorname[ARPT_FUNCTION_MAXNAMELEN];
+	struct xt_standard_target target;
 };
 
 struct arpt_error {
 	struct arpt_entry entry;
-	struct arpt_error_target target;
+	struct xt_error_target target;
 };
 
 #define ARPT_ENTRY_INIT(__size)						       \
@@ -247,16 +231,16 @@
 #define ARPT_STANDARD_INIT(__verdict)					       \
 {									       \
 	.entry		= ARPT_ENTRY_INIT(sizeof(struct arpt_standard)),       \
-	.target		= XT_TARGET_INIT(ARPT_STANDARD_TARGET,		       \
-					 sizeof(struct arpt_standard_target)), \
+	.target		= XT_TARGET_INIT(XT_STANDARD_TARGET,		       \
+					 sizeof(struct xt_standard_target)), \
 	.target.verdict	= -(__verdict) - 1,				       \
 }
 
 #define ARPT_ERROR_INIT							       \
 {									       \
 	.entry		= ARPT_ENTRY_INIT(sizeof(struct arpt_error)),	       \
-	.target		= XT_TARGET_INIT(ARPT_ERROR_TARGET,		       \
-					 sizeof(struct arpt_error_target)),    \
+	.target		= XT_TARGET_INIT(XT_ERROR_TARGET,		       \
+					 sizeof(struct xt_error_target)),      \
 	.target.errorname = "ERROR",					       \
 }
 
@@ -271,8 +255,6 @@
 				  const struct net_device *out,
 				  struct xt_table *table);
 
-#define ARPT_ALIGN(s) XT_ALIGN(s)
-
 #ifdef CONFIG_COMPAT
 #include <net/compat.h>
 
@@ -285,14 +267,12 @@
 	unsigned char elems[0];
 };
 
-static inline struct arpt_entry_target *
+static inline struct xt_entry_target *
 compat_arpt_get_target(struct compat_arpt_entry *e)
 {
 	return (void *)e + e->target_offset;
 }
 
-#define COMPAT_ARPT_ALIGN(s)	COMPAT_XT_ALIGN(s)
-
 #endif /* CONFIG_COMPAT */
 #endif /*__KERNEL__*/
 #endif /* _ARPTABLES_H */
diff --git a/include/linux/netfilter_bridge/Kbuild b/include/linux/netfilter_bridge/Kbuild
index d4d7867..e48f1a3 100644
--- a/include/linux/netfilter_bridge/Kbuild
+++ b/include/linux/netfilter_bridge/Kbuild
@@ -3,11 +3,13 @@
 header-y += ebt_arp.h
 header-y += ebt_arpreply.h
 header-y += ebt_ip.h
+header-y += ebt_ip6.h
 header-y += ebt_limit.h
 header-y += ebt_log.h
 header-y += ebt_mark_m.h
 header-y += ebt_mark_t.h
 header-y += ebt_nat.h
+header-y += ebt_nflog.h
 header-y += ebt_pkttype.h
 header-y += ebt_redirect.h
 header-y += ebt_stp.h
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 704a7b6..64a5d95 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -27,12 +27,49 @@
 
 #include <linux/netfilter/x_tables.h>
 
+#ifndef __KERNEL__
 #define IPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
 #define IPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
 #define ipt_match xt_match
 #define ipt_target xt_target
 #define ipt_table xt_table
 #define ipt_get_revision xt_get_revision
+#define ipt_entry_match xt_entry_match
+#define ipt_entry_target xt_entry_target
+#define ipt_standard_target xt_standard_target
+#define ipt_error_target xt_error_target
+#define ipt_counters xt_counters
+#define IPT_CONTINUE XT_CONTINUE
+#define IPT_RETURN XT_RETURN
+
+/* This group is older than old (iptables < v1.4.0-rc1~89) */
+#include <linux/netfilter/xt_tcpudp.h>
+#define ipt_udp xt_udp
+#define ipt_tcp xt_tcp
+#define IPT_TCP_INV_SRCPT	XT_TCP_INV_SRCPT
+#define IPT_TCP_INV_DSTPT	XT_TCP_INV_DSTPT
+#define IPT_TCP_INV_FLAGS	XT_TCP_INV_FLAGS
+#define IPT_TCP_INV_OPTION	XT_TCP_INV_OPTION
+#define IPT_TCP_INV_MASK	XT_TCP_INV_MASK
+#define IPT_UDP_INV_SRCPT	XT_UDP_INV_SRCPT
+#define IPT_UDP_INV_DSTPT	XT_UDP_INV_DSTPT
+#define IPT_UDP_INV_MASK	XT_UDP_INV_MASK
+
+/* The argument to IPT_SO_ADD_COUNTERS. */
+#define ipt_counters_info xt_counters_info
+/* Standard return verdict, or do jump. */
+#define IPT_STANDARD_TARGET XT_STANDARD_TARGET
+/* Error verdict. */
+#define IPT_ERROR_TARGET XT_ERROR_TARGET
+
+/* fn returns 0 to continue iteration */
+#define IPT_MATCH_ITERATE(e, fn, args...) \
+	XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args)
+
+/* fn returns 0 to continue iteration */
+#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \
+	XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args)
+#endif
 
 /* Yes, Virginia, you have to zero the padding. */
 struct ipt_ip {
@@ -52,12 +89,6 @@
 	u_int8_t invflags;
 };
 
-#define ipt_entry_match xt_entry_match
-#define ipt_entry_target xt_entry_target
-#define ipt_standard_target xt_standard_target
-
-#define ipt_counters xt_counters
-
 /* Values for "flag" field in struct ipt_ip (general ip structure). */
 #define IPT_F_FRAG		0x01	/* Set if rule is a fragment rule */
 #define IPT_F_GOTO		0x02	/* Set if jump is a goto */
@@ -116,23 +147,6 @@
 #define IPT_SO_GET_REVISION_TARGET	(IPT_BASE_CTL + 3)
 #define IPT_SO_GET_MAX			IPT_SO_GET_REVISION_TARGET
 
-#define IPT_CONTINUE XT_CONTINUE
-#define IPT_RETURN XT_RETURN
-
-#include <linux/netfilter/xt_tcpudp.h>
-#define ipt_udp xt_udp
-#define ipt_tcp xt_tcp
-
-#define IPT_TCP_INV_SRCPT	XT_TCP_INV_SRCPT
-#define IPT_TCP_INV_DSTPT	XT_TCP_INV_DSTPT
-#define IPT_TCP_INV_FLAGS	XT_TCP_INV_FLAGS
-#define IPT_TCP_INV_OPTION	XT_TCP_INV_OPTION
-#define IPT_TCP_INV_MASK	XT_TCP_INV_MASK
-
-#define IPT_UDP_INV_SRCPT	XT_UDP_INV_SRCPT
-#define IPT_UDP_INV_DSTPT	XT_UDP_INV_DSTPT
-#define IPT_UDP_INV_MASK	XT_UDP_INV_MASK
-
 /* ICMP matching stuff */
 struct ipt_icmp {
 	u_int8_t type;				/* type to match */
@@ -146,7 +160,7 @@
 /* The argument to IPT_SO_GET_INFO */
 struct ipt_getinfo {
 	/* Which table: caller fills this in. */
-	char name[IPT_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 
 	/* Kernel fills these in. */
 	/* Which hook entry points are valid: bitmask */
@@ -168,7 +182,7 @@
 /* The argument to IPT_SO_SET_REPLACE. */
 struct ipt_replace {
 	/* Which table. */
-	char name[IPT_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 
 	/* Which hook entry points are valid: bitmask.  You can't
            change this. */
@@ -196,13 +210,10 @@
 	struct ipt_entry entries[0];
 };
 
-/* The argument to IPT_SO_ADD_COUNTERS. */
-#define ipt_counters_info xt_counters_info
-
 /* The argument to IPT_SO_GET_ENTRIES. */
 struct ipt_get_entries {
 	/* Which table: user fills this in. */
-	char name[IPT_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 
 	/* User fills this in: total entry size. */
 	unsigned int size;
@@ -211,28 +222,13 @@
 	struct ipt_entry entrytable[0];
 };
 
-/* Standard return verdict, or do jump. */
-#define IPT_STANDARD_TARGET XT_STANDARD_TARGET
-/* Error verdict. */
-#define IPT_ERROR_TARGET XT_ERROR_TARGET
-
 /* Helper functions */
-static __inline__ struct ipt_entry_target *
+static __inline__ struct xt_entry_target *
 ipt_get_target(struct ipt_entry *e)
 {
 	return (void *)e + e->target_offset;
 }
 
-#ifndef __KERNEL__
-/* fn returns 0 to continue iteration */
-#define IPT_MATCH_ITERATE(e, fn, args...) \
-	XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args)
-
-/* fn returns 0 to continue iteration */
-#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \
-	XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args)
-#endif
-
 /*
  *	Main firewall chains definitions and global var's definitions.
  */
@@ -249,17 +245,12 @@
 /* Standard entry. */
 struct ipt_standard {
 	struct ipt_entry entry;
-	struct ipt_standard_target target;
-};
-
-struct ipt_error_target {
-	struct ipt_entry_target target;
-	char errorname[IPT_FUNCTION_MAXNAMELEN];
+	struct xt_standard_target target;
 };
 
 struct ipt_error {
 	struct ipt_entry entry;
-	struct ipt_error_target target;
+	struct xt_error_target target;
 };
 
 #define IPT_ENTRY_INIT(__size)						       \
@@ -271,7 +262,7 @@
 #define IPT_STANDARD_INIT(__verdict)					       \
 {									       \
 	.entry		= IPT_ENTRY_INIT(sizeof(struct ipt_standard)),	       \
-	.target		= XT_TARGET_INIT(IPT_STANDARD_TARGET,		       \
+	.target		= XT_TARGET_INIT(XT_STANDARD_TARGET,		       \
 					 sizeof(struct xt_standard_target)),   \
 	.target.verdict	= -(__verdict) - 1,				       \
 }
@@ -279,8 +270,8 @@
 #define IPT_ERROR_INIT							       \
 {									       \
 	.entry		= IPT_ENTRY_INIT(sizeof(struct ipt_error)),	       \
-	.target		= XT_TARGET_INIT(IPT_ERROR_TARGET,		       \
-					 sizeof(struct ipt_error_target)),     \
+	.target		= XT_TARGET_INIT(XT_ERROR_TARGET,		       \
+					 sizeof(struct xt_error_target)),      \
 	.target.errorname = "ERROR",					       \
 }
 
@@ -291,8 +282,6 @@
 				 const struct net_device *out,
 				 struct xt_table *table);
 
-#define IPT_ALIGN(s) XT_ALIGN(s)
-
 #ifdef CONFIG_COMPAT
 #include <net/compat.h>
 
@@ -307,14 +296,12 @@
 };
 
 /* Helper functions */
-static inline struct ipt_entry_target *
+static inline struct xt_entry_target *
 compat_ipt_get_target(struct compat_ipt_entry *e)
 {
 	return (void *)e + e->target_offset;
 }
 
-#define COMPAT_IPT_ALIGN(s) 	COMPAT_XT_ALIGN(s)
-
 #endif /* CONFIG_COMPAT */
 #endif /*__KERNEL__*/
 #endif /* _IPTABLES_H */
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 18442ff..c9784f7 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -27,13 +27,42 @@
 
 #include <linux/netfilter/x_tables.h>
 
+#ifndef __KERNEL__
 #define IP6T_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
 #define IP6T_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
-
 #define ip6t_match xt_match
 #define ip6t_target xt_target
 #define ip6t_table xt_table
 #define ip6t_get_revision xt_get_revision
+#define ip6t_entry_match xt_entry_match
+#define ip6t_entry_target xt_entry_target
+#define ip6t_standard_target xt_standard_target
+#define ip6t_error_target xt_error_target
+#define ip6t_counters xt_counters
+#define IP6T_CONTINUE XT_CONTINUE
+#define IP6T_RETURN XT_RETURN
+
+/* Pre-iptables-1.4.0 */
+#include <linux/netfilter/xt_tcpudp.h>
+#define ip6t_tcp xt_tcp
+#define ip6t_udp xt_udp
+#define IP6T_TCP_INV_SRCPT	XT_TCP_INV_SRCPT
+#define IP6T_TCP_INV_DSTPT	XT_TCP_INV_DSTPT
+#define IP6T_TCP_INV_FLAGS	XT_TCP_INV_FLAGS
+#define IP6T_TCP_INV_OPTION	XT_TCP_INV_OPTION
+#define IP6T_TCP_INV_MASK	XT_TCP_INV_MASK
+#define IP6T_UDP_INV_SRCPT	XT_UDP_INV_SRCPT
+#define IP6T_UDP_INV_DSTPT	XT_UDP_INV_DSTPT
+#define IP6T_UDP_INV_MASK	XT_UDP_INV_MASK
+
+#define ip6t_counters_info xt_counters_info
+#define IP6T_STANDARD_TARGET XT_STANDARD_TARGET
+#define IP6T_ERROR_TARGET XT_ERROR_TARGET
+#define IP6T_MATCH_ITERATE(e, fn, args...) \
+	XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args)
+#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \
+	XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args)
+#endif
 
 /* Yes, Virginia, you have to zero the padding. */
 struct ip6t_ip6 {
@@ -62,12 +91,6 @@
 	u_int8_t invflags;
 };
 
-#define ip6t_entry_match xt_entry_match
-#define ip6t_entry_target xt_entry_target
-#define ip6t_standard_target xt_standard_target
-
-#define ip6t_counters	xt_counters
-
 /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
 #define IP6T_F_PROTO		0x01	/* Set if rule cares about upper 
 					   protocols */
@@ -112,17 +135,12 @@
 /* Standard entry */
 struct ip6t_standard {
 	struct ip6t_entry entry;
-	struct ip6t_standard_target target;
-};
-
-struct ip6t_error_target {
-	struct ip6t_entry_target target;
-	char errorname[IP6T_FUNCTION_MAXNAMELEN];
+	struct xt_standard_target target;
 };
 
 struct ip6t_error {
 	struct ip6t_entry entry;
-	struct ip6t_error_target target;
+	struct xt_error_target target;
 };
 
 #define IP6T_ENTRY_INIT(__size)						       \
@@ -134,16 +152,16 @@
 #define IP6T_STANDARD_INIT(__verdict)					       \
 {									       \
 	.entry		= IP6T_ENTRY_INIT(sizeof(struct ip6t_standard)),       \
-	.target		= XT_TARGET_INIT(IP6T_STANDARD_TARGET,		       \
-					 sizeof(struct ip6t_standard_target)), \
+	.target		= XT_TARGET_INIT(XT_STANDARD_TARGET,		       \
+					 sizeof(struct xt_standard_target)),   \
 	.target.verdict	= -(__verdict) - 1,				       \
 }
 
 #define IP6T_ERROR_INIT							       \
 {									       \
 	.entry		= IP6T_ENTRY_INIT(sizeof(struct ip6t_error)),	       \
-	.target		= XT_TARGET_INIT(IP6T_ERROR_TARGET,		       \
-					 sizeof(struct ip6t_error_target)),    \
+	.target		= XT_TARGET_INIT(XT_ERROR_TARGET,		       \
+					 sizeof(struct xt_error_target)),      \
 	.target.errorname = "ERROR",					       \
 }
 
@@ -166,30 +184,6 @@
 #define IP6T_SO_GET_REVISION_TARGET	(IP6T_BASE_CTL + 5)
 #define IP6T_SO_GET_MAX			IP6T_SO_GET_REVISION_TARGET
 
-/* CONTINUE verdict for targets */
-#define IP6T_CONTINUE XT_CONTINUE
-
-/* For standard target */
-#define IP6T_RETURN XT_RETURN
-
-/* TCP/UDP matching stuff */
-#include <linux/netfilter/xt_tcpudp.h>
-
-#define ip6t_tcp xt_tcp
-#define ip6t_udp xt_udp
-
-/* Values for "inv" field in struct ipt_tcp. */
-#define IP6T_TCP_INV_SRCPT	XT_TCP_INV_SRCPT
-#define IP6T_TCP_INV_DSTPT	XT_TCP_INV_DSTPT
-#define IP6T_TCP_INV_FLAGS	XT_TCP_INV_FLAGS
-#define IP6T_TCP_INV_OPTION	XT_TCP_INV_OPTION
-#define IP6T_TCP_INV_MASK	XT_TCP_INV_MASK
-
-/* Values for "invflags" field in struct ipt_udp. */
-#define IP6T_UDP_INV_SRCPT	XT_UDP_INV_SRCPT
-#define IP6T_UDP_INV_DSTPT	XT_UDP_INV_DSTPT
-#define IP6T_UDP_INV_MASK	XT_UDP_INV_MASK
-
 /* ICMP matching stuff */
 struct ip6t_icmp {
 	u_int8_t type;				/* type to match */
@@ -203,7 +197,7 @@
 /* The argument to IP6T_SO_GET_INFO */
 struct ip6t_getinfo {
 	/* Which table: caller fills this in. */
-	char name[IP6T_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 
 	/* Kernel fills these in. */
 	/* Which hook entry points are valid: bitmask */
@@ -225,7 +219,7 @@
 /* The argument to IP6T_SO_SET_REPLACE. */
 struct ip6t_replace {
 	/* Which table. */
-	char name[IP6T_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 
 	/* Which hook entry points are valid: bitmask.  You can't
            change this. */
@@ -253,13 +247,10 @@
 	struct ip6t_entry entries[0];
 };
 
-/* The argument to IP6T_SO_ADD_COUNTERS. */
-#define ip6t_counters_info xt_counters_info
-
 /* The argument to IP6T_SO_GET_ENTRIES. */
 struct ip6t_get_entries {
 	/* Which table: user fills this in. */
-	char name[IP6T_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 
 	/* User fills this in: total entry size. */
 	unsigned int size;
@@ -268,28 +259,13 @@
 	struct ip6t_entry entrytable[0];
 };
 
-/* Standard return verdict, or do jump. */
-#define IP6T_STANDARD_TARGET XT_STANDARD_TARGET
-/* Error verdict. */
-#define IP6T_ERROR_TARGET XT_ERROR_TARGET
-
 /* Helper functions */
-static __inline__ struct ip6t_entry_target *
+static __inline__ struct xt_entry_target *
 ip6t_get_target(struct ip6t_entry *e)
 {
 	return (void *)e + e->target_offset;
 }
 
-#ifndef __KERNEL__
-/* fn returns 0 to continue iteration */
-#define IP6T_MATCH_ITERATE(e, fn, args...) \
-	XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args)
-
-/* fn returns 0 to continue iteration */
-#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \
-	XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args)
-#endif
-
 /*
  *	Main firewall chains definitions and global var's definitions.
  */
@@ -316,8 +292,6 @@
 extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
 			 int target, unsigned short *fragoff);
 
-#define IP6T_ALIGN(s) XT_ALIGN(s)
-
 #ifdef CONFIG_COMPAT
 #include <net/compat.h>
 
@@ -331,14 +305,12 @@
 	unsigned char elems[0];
 };
 
-static inline struct ip6t_entry_target *
+static inline struct xt_entry_target *
 compat_ip6t_get_target(struct compat_ip6t_entry *e)
 {
 	return (void *)e + e->target_offset;
 }
 
-#define COMPAT_IP6T_ALIGN(s)	COMPAT_XT_ALIGN(s)
-
 #endif /* CONFIG_COMPAT */
 #endif /*__KERNEL__*/
 #endif /* _IP6_TABLES_H */
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 59d0669..1235669 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -27,8 +27,6 @@
 
 #define MAX_LINKS 32		
 
-struct net;
-
 struct sockaddr_nl {
 	sa_family_t	nl_family;	/* AF_NETLINK	*/
 	unsigned short	nl_pad;		/* zero		*/
@@ -151,6 +149,8 @@
 #include <linux/capability.h>
 #include <linux/skbuff.h>
 
+struct net;
+
 static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb)
 {
 	return (struct nlmsghdr *)skb->data;
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index 50d8009..79358bb 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -14,7 +14,6 @@
 
 struct netpoll {
 	struct net_device *dev;
-	struct net_device *real_dev;
 	char dev_name[IFNAMSIZ];
 	const char *name;
 	void (*rx_hook)(struct netpoll *, int, char *, int);
@@ -53,7 +52,13 @@
 void __netpoll_cleanup(struct netpoll *np);
 void netpoll_cleanup(struct netpoll *np);
 int __netpoll_rx(struct sk_buff *skb);
-void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb);
+void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
+			     struct net_device *dev);
+static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
+{
+	netpoll_send_skb_on_dev(np, skb, np->dev);
+}
+
 
 
 #ifdef CONFIG_NETPOLL
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 508f8cf..d0edf7d 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -185,7 +185,7 @@
 	struct nfs4_cached_acl	*nfs4_acl;
         /* NFSv4 state */
 	struct list_head	open_states;
-	struct nfs_delegation	*delegation;
+	struct nfs_delegation __rcu *delegation;
 	fmode_t			 delegation_state;
 	struct rw_semaphore	rwsem;
 #endif /* CONFIG_NFS_V4*/
diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h
index f5487b6..227e49d 100644
--- a/include/linux/nilfs2_fs.h
+++ b/include/linux/nilfs2_fs.h
@@ -4,16 +4,16 @@
  * 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
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
+ * You should have received a copy of the GNU Lesser 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
  *
@@ -147,7 +147,6 @@
 #define NILFS_MOUNT_ERRORS_CONT		0x0010  /* Continue on errors */
 #define NILFS_MOUNT_ERRORS_RO		0x0020  /* Remount fs ro on errors */
 #define NILFS_MOUNT_ERRORS_PANIC	0x0040  /* Panic on errors */
-#define NILFS_MOUNT_SNAPSHOT		0x0080  /* Snapshot flag */
 #define NILFS_MOUNT_BARRIER		0x1000  /* Use block barriers */
 #define NILFS_MOUNT_STRICT_ORDER	0x2000  /* Apply strict in-order
 						   semantics also for data */
@@ -229,6 +228,7 @@
  */
 #define NILFS_CURRENT_REV	2	/* current major revision */
 #define NILFS_MINOR_REV		0	/* minor revision */
+#define NILFS_MIN_SUPP_REV	2	/* minimum supported revision */
 
 /*
  * Feature set definitions
@@ -270,6 +270,14 @@
 					   segments */
 
 /*
+ * We call DAT, cpfile, and sufile root metadata files.  Inodes of
+ * these files are written in super root block instead of ifile, and
+ * garbage collector doesn't keep any past versions of these files.
+ */
+#define NILFS_ROOT_METADATA_FILE(ino) \
+	((ino) >= NILFS_DAT_INO && (ino) <= NILFS_SUFILE_INO)
+
+/*
  * bytes offset of secondary super block
  */
 #define NILFS_SB2_OFFSET_BYTES(devsize)	((((devsize) >> 12) - 1) << 12)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 2c87016..0edb256 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -40,6 +40,43 @@
  */
 
 /**
+ * DOC: Frame transmission/registration support
+ *
+ * Frame transmission and registration support exists to allow userspace
+ * management entities such as wpa_supplicant react to management frames
+ * that are not being handled by the kernel. This includes, for example,
+ * certain classes of action frames that cannot be handled in the kernel
+ * for various reasons.
+ *
+ * Frame registration is done on a per-interface basis and registrations
+ * cannot be removed other than by closing the socket. It is possible to
+ * specify a registration filter to register, for example, only for a
+ * certain type of action frame. In particular with action frames, those
+ * that userspace registers for will not be returned as unhandled by the
+ * driver, so that the registered application has to take responsibility
+ * for doing that.
+ *
+ * The type of frame that can be registered for is also dependent on the
+ * driver and interface type. The frame types are advertised in wiphy
+ * attributes so applications know what to expect.
+ *
+ * NOTE: When an interface changes type while registrations are active,
+ *       these registrations are ignored until the interface type is
+ *       changed again. This means that changing the interface type can
+ *       lead to a situation that couldn't otherwise be produced, but
+ *       any such registrations will be dormant in the sense that they
+ *       will not be serviced, i.e. they will not receive any frames.
+ *
+ * Frame transmission allows userspace to send for example the required
+ * responses to action frames. It is subject to some sanity checking,
+ * but many frames can be transmitted. When a frame was transmitted, its
+ * status is indicated to the sending socket.
+ *
+ * For more technical details, see the corresponding command descriptions
+ * below.
+ */
+
+/**
  * enum nl80211_commands - supported nl80211 commands
  *
  * @NL80211_CMD_UNSPEC: unspecified command to catch errors
@@ -258,7 +295,9 @@
  *	auth and assoc steps. For this, you need to specify the SSID in a
  *	%NL80211_ATTR_SSID attribute, and can optionally specify the association
  *	IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC,
- *	%NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_CONTROL_PORT.
+ *	%NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT,
+ *	%NL80211_ATTR_CONTROL_PORT_ETHERTYPE and
+ *	%NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT.
  *	It is also sent as an event, with the BSSID and response IEs when the
  *	connection is established or failed to be established. This can be
  *	determined by the STATUS_CODE attribute.
@@ -276,8 +315,8 @@
  *	channel for the specified amount of time. This can be used to do
  *	off-channel operations like transmit a Public Action frame and wait for
  *	a response while being associated to an AP on another channel.
- *	%NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify which
- *	radio is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
+ *	%NL80211_ATTR_IFINDEX is used to specify which interface (and thus
+ *	radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
  *	frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be
  *	optionally used to specify additional channel parameters.
  *	%NL80211_ATTR_DURATION is used to specify the duration in milliseconds
@@ -301,16 +340,20 @@
  *	rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface
  *	and @NL80211_ATTR_TX_RATES the set of allowed rates.
  *
- * @NL80211_CMD_REGISTER_ACTION: Register for receiving certain action frames
- *	(via @NL80211_CMD_ACTION) for processing in userspace. This command
- *	requires an interface index and a match attribute containing the first
- *	few bytes of the frame that should match, e.g. a single byte for only
- *	a category match or four bytes for vendor frames including the OUI.
- *	The registration cannot be dropped, but is removed automatically
- *	when the netlink socket is closed. Multiple registrations can be made.
- * @NL80211_CMD_ACTION: Action frame TX request and RX notification. This
- *	command is used both as a request to transmit an Action frame and as an
- *	event indicating reception of an Action frame that was not processed in
+ * @NL80211_CMD_REGISTER_FRAME: Register for receiving certain mgmt frames
+ *	(via @NL80211_CMD_FRAME) for processing in userspace. This command
+ *	requires an interface index, a frame type attribute (optional for
+ *	backward compatibility reasons, if not given assumes action frames)
+ *	and a match attribute containing the first few bytes of the frame
+ *	that should match, e.g. a single byte for only a category match or
+ *	four bytes for vendor frames including the OUI. The registration
+ *	cannot be dropped, but is removed automatically when the netlink
+ *	socket is closed. Multiple registrations can be made.
+ * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for
+ *	backward compatibility
+ * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This
+ *	command is used both as a request to transmit a management frame and
+ *	as an event indicating reception of a frame that was not processed in
  *	kernel code, but is for us (i.e., which may need to be processed in a
  *	user space application). %NL80211_ATTR_FRAME is used to specify the
  *	frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and
@@ -320,11 +363,14 @@
  *	operational channel). When called, this operation returns a cookie
  *	(%NL80211_ATTR_COOKIE) that will be included with the TX status event
  *	pertaining to the TX request.
- * @NL80211_CMD_ACTION_TX_STATUS: Report TX status of an Action frame
- *	transmitted with %NL80211_CMD_ACTION. %NL80211_ATTR_COOKIE identifies
+ * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility.
+ * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame
+ *	transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies
  *	the TX command and %NL80211_ATTR_FRAME includes the contents of the
  *	frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged
  *	the frame.
+ * @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for
+ *	backward compatibility.
  * @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command
  *	is used to configure connection quality monitoring notification trigger
  *	levels.
@@ -341,6 +387,8 @@
  *	of any other interfaces, and other interfaces will again take
  *	precedence when they are used.
  *
+ * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -429,9 +477,12 @@
 
 	NL80211_CMD_SET_TX_BITRATE_MASK,
 
-	NL80211_CMD_REGISTER_ACTION,
-	NL80211_CMD_ACTION,
-	NL80211_CMD_ACTION_TX_STATUS,
+	NL80211_CMD_REGISTER_FRAME,
+	NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME,
+	NL80211_CMD_FRAME,
+	NL80211_CMD_ACTION = NL80211_CMD_FRAME,
+	NL80211_CMD_FRAME_TX_STATUS,
+	NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS,
 
 	NL80211_CMD_SET_POWER_SAVE,
 	NL80211_CMD_GET_POWER_SAVE,
@@ -440,6 +491,7 @@
 	NL80211_CMD_NOTIFY_CQM,
 
 	NL80211_CMD_SET_CHANNEL,
+	NL80211_CMD_SET_WDS_PEER,
 
 	/* add new commands above here */
 
@@ -639,6 +691,15 @@
  *	request, the driver will assume that the port is unauthorized until
  *	authorized by user space. Otherwise, port is marked authorized by
  *	default in station mode.
+ * @NL80211_ATTR_CONTROL_PORT_ETHERTYPE: A 16-bit value indicating the
+ *	ethertype that will be used for key negotiation. It can be
+ *	specified with the associate and connect commands. If it is not
+ *	specified, the value defaults to 0x888E (PAE, 802.1X). This
+ *	attribute is also used as a flag in the wiphy information to
+ *	indicate that protocols other than PAE are supported.
+ * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with
+ *	%NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom
+ *	ethertype frames used for key negotiation must not be encrypted.
  *
  * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
  *	We recommend using nested, driver-specific attributes within this.
@@ -708,7 +769,16 @@
  *	is used with %NL80211_CMD_SET_TX_BITRATE_MASK.
  *
  * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain
- *	at least one byte, currently used with @NL80211_CMD_REGISTER_ACTION.
+ *	at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME.
+ * @NL80211_ATTR_FRAME_TYPE: A u16 indicating the frame type/subtype for the
+ *	@NL80211_CMD_REGISTER_FRAME command.
+ * @NL80211_ATTR_TX_FRAME_TYPES: wiphy capability attribute, which is a
+ *	nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing
+ *	information about which frame types can be transmitted with
+ *	%NL80211_CMD_FRAME.
+ * @NL80211_ATTR_RX_FRAME_TYPES: wiphy capability attribute, which is a
+ *	nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing
+ *	information about which frame types can be registered for RX.
  *
  * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was
  *	acknowledged by the recipient.
@@ -731,6 +801,9 @@
  *      This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING
  *      for non-automatic settings.
  *
+ * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly
+ *	means support for per-station GTKs.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -891,6 +964,15 @@
 	NL80211_ATTR_WIPHY_TX_POWER_SETTING,
 	NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
 
+	NL80211_ATTR_TX_FRAME_TYPES,
+	NL80211_ATTR_RX_FRAME_TYPES,
+	NL80211_ATTR_FRAME_TYPE,
+
+	NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
+	NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT,
+
+	NL80211_ATTR_SUPPORT_IBSS_RSN,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -946,8 +1028,10 @@
  * @NL80211_IFTYPE_WDS: wireless distribution interface
  * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
  * @NL80211_IFTYPE_MESH_POINT: mesh point
+ * @NL80211_IFTYPE_P2P_CLIENT: P2P client
+ * @NL80211_IFTYPE_P2P_GO: P2P group owner
  * @NL80211_IFTYPE_MAX: highest interface type number currently defined
- * @__NL80211_IFTYPE_AFTER_LAST: internal use
+ * @NUM_NL80211_IFTYPES: number of defined interface types
  *
  * These values are used with the %NL80211_ATTR_IFTYPE
  * to set the type of an interface.
@@ -962,10 +1046,12 @@
 	NL80211_IFTYPE_WDS,
 	NL80211_IFTYPE_MONITOR,
 	NL80211_IFTYPE_MESH_POINT,
+	NL80211_IFTYPE_P2P_CLIENT,
+	NL80211_IFTYPE_P2P_GO,
 
 	/* keep last */
-	__NL80211_IFTYPE_AFTER_LAST,
-	NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1
+	NUM_NL80211_IFTYPES,
+	NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1
 };
 
 /**
@@ -974,11 +1060,14 @@
  * Station flags. When a station is added to an AP interface, it is
  * assumed to be already associated (and hence authenticated.)
  *
+ * @__NL80211_STA_FLAG_INVALID: attribute number 0 is reserved
  * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X)
  * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames
  *	with short barker preamble
  * @NL80211_STA_FLAG_WME: station is WME/QoS capable
  * @NL80211_STA_FLAG_MFP: station uses management frame protection
+ * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
+ * @__NL80211_STA_FLAG_AFTER_LAST: internal use
  */
 enum nl80211_sta_flags {
 	__NL80211_STA_FLAG_INVALID,
@@ -1048,6 +1137,8 @@
  * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station)
  * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this
  *	station)
+ * @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station)
+ * @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station)
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -1061,6 +1152,8 @@
 	NL80211_STA_INFO_TX_BITRATE,
 	NL80211_STA_INFO_RX_PACKETS,
 	NL80211_STA_INFO_TX_PACKETS,
+	NL80211_STA_INFO_TX_RETRIES,
+	NL80211_STA_INFO_TX_FAILED,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
@@ -1091,14 +1184,17 @@
  * information about a mesh path.
  *
  * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_ATTR_MPATH_FRAME_QLEN: number of queued frames for this destination
- * @NL80211_ATTR_MPATH_SN: destination sequence number
- * @NL80211_ATTR_MPATH_METRIC: metric (cost) of this mesh path
- * @NL80211_ATTR_MPATH_EXPTIME: expiration time for the path, in msec from now
- * @NL80211_ATTR_MPATH_FLAGS: mesh path flags, enumerated in
+ * @NL80211_MPATH_INFO_FRAME_QLEN: number of queued frames for this destination
+ * @NL80211_MPATH_INFO_SN: destination sequence number
+ * @NL80211_MPATH_INFO_METRIC: metric (cost) of this mesh path
+ * @NL80211_MPATH_INFO_EXPTIME: expiration time for the path, in msec from now
+ * @NL80211_MPATH_INFO_FLAGS: mesh path flags, enumerated in
  * 	&enum nl80211_mpath_flags;
- * @NL80211_ATTR_MPATH_DISCOVERY_TIMEOUT: total path discovery timeout, in msec
- * @NL80211_ATTR_MPATH_DISCOVERY_RETRIES: mesh path discovery retries
+ * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec
+ * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries
+ * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number
+ *	currently defind
+ * @__NL80211_MPATH_INFO_AFTER_LAST: internal use
  */
 enum nl80211_mpath_info {
 	__NL80211_MPATH_INFO_INVALID,
@@ -1127,6 +1223,8 @@
  * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE
  * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n
  * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n
+ * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
+ * @__NL80211_BAND_ATTR_AFTER_LAST: internal use
  */
 enum nl80211_band_attr {
 	__NL80211_BAND_ATTR_INVALID,
@@ -1147,6 +1245,7 @@
 
 /**
  * enum nl80211_frequency_attr - frequency attributes
+ * @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved
  * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
  * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
  *	regulatory domain.
@@ -1158,6 +1257,9 @@
  *	on this channel in current regulatory domain.
  * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
  *	(100 * dBm).
+ * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
+ *	currently defined
+ * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
  */
 enum nl80211_frequency_attr {
 	__NL80211_FREQUENCY_ATTR_INVALID,
@@ -1177,9 +1279,13 @@
 
 /**
  * enum nl80211_bitrate_attr - bitrate attributes
+ * @__NL80211_BITRATE_ATTR_INVALID: attribute number 0 is reserved
  * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps
  * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported
  *	in 2.4 GHz band.
+ * @NL80211_BITRATE_ATTR_MAX: highest bitrate attribute number
+ *	currently defined
+ * @__NL80211_BITRATE_ATTR_AFTER_LAST: internal use
  */
 enum nl80211_bitrate_attr {
 	__NL80211_BITRATE_ATTR_INVALID,
@@ -1235,6 +1341,7 @@
 
 /**
  * enum nl80211_reg_rule_attr - regulatory rule attributes
+ * @__NL80211_REG_RULE_ATTR_INVALID: attribute number 0 is reserved
  * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional
  * 	considerations for a given frequency range. These are the
  * 	&enum nl80211_reg_rule_flags.
@@ -1251,6 +1358,9 @@
  * 	If you don't have one then don't send this.
  * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
  * 	a given frequency range. The value is in mBm (100 * dBm).
+ * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
+ *	currently defined
+ * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
  */
 enum nl80211_reg_rule_attr {
 	__NL80211_REG_RULE_ATTR_INVALID,
@@ -1302,11 +1412,31 @@
  * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved
  * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel
  * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm)
+ * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME: amount of time (in ms) that the radio
+ *	spent on this channel
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: amount of the time the primary
+ *	channel was sensed busy (either due to activity or energy detect)
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: amount of time the extension
+ *	channel was sensed busy
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_RX: amount of time the radio spent
+ *	receiving data
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_TX: amount of time the radio spent
+ *	transmitting data
+ * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number
+ *	currently defined
+ * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use
  */
 enum nl80211_survey_info {
 	__NL80211_SURVEY_INFO_INVALID,
 	NL80211_SURVEY_INFO_FREQUENCY,
 	NL80211_SURVEY_INFO_NOISE,
+	NL80211_SURVEY_INFO_IN_USE,
+	NL80211_SURVEY_INFO_CHANNEL_TIME,
+	NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
+	NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
+	NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
+	NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
 
 	/* keep last */
 	__NL80211_SURVEY_INFO_AFTER_LAST,
@@ -1466,6 +1596,7 @@
  * enum nl80211_bss - netlink attributes for a BSS
  *
  * @__NL80211_BSS_INVALID: invalid
+ * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets)
  * @NL80211_BSS_FREQUENCY: frequency in MHz (u32)
  * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64)
  * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16)
@@ -1509,6 +1640,12 @@
 
 /**
  * enum nl80211_bss_status - BSS "status"
+ * @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS.
+ * @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS.
+ * @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS.
+ *
+ * The BSS status is a BSS attribute in scan dumps, which
+ * indicates the status the interface has wrt. this BSS.
  */
 enum nl80211_bss_status {
 	NL80211_BSS_STATUS_AUTHENTICATED,
@@ -1546,11 +1683,14 @@
  * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key
  * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key
  * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS)
+ * @NUM_NL80211_KEYTYPES: number of defined key types
  */
 enum nl80211_key_type {
 	NL80211_KEYTYPE_GROUP,
 	NL80211_KEYTYPE_PAIRWISE,
 	NL80211_KEYTYPE_PEERKEY,
+
+	NUM_NL80211_KEYTYPES
 };
 
 /**
@@ -1581,6 +1721,9 @@
  *	CCMP keys, each six bytes in little endian
  * @NL80211_KEY_DEFAULT: flag indicating default key
  * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key
+ * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not
+ *	specified the default depends on whether a MAC address was
+ *	given with the command using the key or not (u32)
  * @__NL80211_KEY_AFTER_LAST: internal
  * @NL80211_KEY_MAX: highest key attribute
  */
@@ -1592,6 +1735,7 @@
 	NL80211_KEY_SEQ,
 	NL80211_KEY_DEFAULT,
 	NL80211_KEY_DEFAULT_MGMT,
+	NL80211_KEY_TYPE,
 
 	/* keep last */
 	__NL80211_KEY_AFTER_LAST,
@@ -1619,8 +1763,8 @@
 
 /**
  * enum nl80211_band - Frequency band
- * @NL80211_BAND_2GHZ - 2.4 GHz ISM band
- * @NL80211_BAND_5GHZ - around 5 GHz band (4.9 - 5.7 GHz)
+ * @NL80211_BAND_2GHZ: 2.4 GHz ISM band
+ * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
  */
 enum nl80211_band {
 	NL80211_BAND_2GHZ,
@@ -1658,9 +1802,9 @@
 
 /**
  * enum nl80211_cqm_rssi_threshold_event - RSSI threshold event
- * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW - The RSSI level is lower than the
+ * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: The RSSI level is lower than the
  *      configured threshold
- * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH - The RSSI is higher than the
+ * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the
  *      configured threshold
  */
 enum nl80211_cqm_rssi_threshold_event {
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index b2f1a4d..2026f9e 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -49,28 +49,28 @@
 
 struct notifier_block {
 	int (*notifier_call)(struct notifier_block *, unsigned long, void *);
-	struct notifier_block *next;
+	struct notifier_block __rcu *next;
 	int priority;
 };
 
 struct atomic_notifier_head {
 	spinlock_t lock;
-	struct notifier_block *head;
+	struct notifier_block __rcu *head;
 };
 
 struct blocking_notifier_head {
 	struct rw_semaphore rwsem;
-	struct notifier_block *head;
+	struct notifier_block __rcu *head;
 };
 
 struct raw_notifier_head {
-	struct notifier_block *head;
+	struct notifier_block __rcu *head;
 };
 
 struct srcu_notifier_head {
 	struct mutex mutex;
 	struct srcu_struct srcu;
-	struct notifier_block *head;
+	struct notifier_block __rcu *head;
 };
 
 #define ATOMIC_INIT_NOTIFIER_HEAD(name) do {	\
diff --git a/include/linux/opp.h b/include/linux/opp.h
new file mode 100644
index 0000000..5449945
--- /dev/null
+++ b/include/linux/opp.h
@@ -0,0 +1,105 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ *	Nishanth Menon
+ *	Romit Dasgupta
+ *	Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_OPP_H__
+#define __LINUX_OPP_H__
+
+#include <linux/err.h>
+#include <linux/cpufreq.h>
+
+struct opp;
+
+#if defined(CONFIG_PM_OPP)
+
+unsigned long opp_get_voltage(struct opp *opp);
+
+unsigned long opp_get_freq(struct opp *opp);
+
+int opp_get_opp_count(struct device *dev);
+
+struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
+				bool available);
+
+struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq);
+
+struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq);
+
+int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt);
+
+int opp_enable(struct device *dev, unsigned long freq);
+
+int opp_disable(struct device *dev, unsigned long freq);
+
+#else
+static inline unsigned long opp_get_voltage(struct opp *opp)
+{
+	return 0;
+}
+
+static inline unsigned long opp_get_freq(struct opp *opp)
+{
+	return 0;
+}
+
+static inline int opp_get_opp_count(struct device *dev)
+{
+	return 0;
+}
+
+static inline struct opp *opp_find_freq_exact(struct device *dev,
+					unsigned long freq, bool available)
+{
+	return ERR_PTR(-EINVAL);
+}
+
+static inline struct opp *opp_find_freq_floor(struct device *dev,
+					unsigned long *freq)
+{
+	return ERR_PTR(-EINVAL);
+}
+
+static inline struct opp *opp_find_freq_ceil(struct device *dev,
+					unsigned long *freq)
+{
+	return ERR_PTR(-EINVAL);
+}
+
+static inline int opp_add(struct device *dev, unsigned long freq,
+					unsigned long u_volt)
+{
+	return -EINVAL;
+}
+
+static inline int opp_enable(struct device *dev, unsigned long freq)
+{
+	return 0;
+}
+
+static inline int opp_disable(struct device *dev, unsigned long freq)
+{
+	return 0;
+}
+#endif		/* CONFIG_PM */
+
+#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
+int opp_init_cpufreq_table(struct device *dev,
+			    struct cpufreq_frequency_table **table);
+#else
+static inline int opp_init_cpufreq_table(struct device *dev,
+			    struct cpufreq_frequency_table **table)
+{
+	return -EINVAL;
+}
+#endif		/* CONFIG_CPU_FREQ */
+
+#endif		/* __LINUX_OPP_H__ */
diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h
index 5171639..32fb812 100644
--- a/include/linux/oprofile.h
+++ b/include/linux/oprofile.h
@@ -15,6 +15,7 @@
 
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <linux/init.h>
 #include <asm/atomic.h>
  
 /* Each escaped entry is prefixed by ESCAPE_CODE
@@ -185,4 +186,10 @@
 int oprofile_add_data64(struct op_entry *entry, u64 val);
 int oprofile_write_commit(struct op_entry *entry);
 
+#ifdef CONFIG_PERF_EVENTS
+int __init oprofile_perf_init(struct oprofile_operations *ops);
+void oprofile_perf_exit(void);
+char *op_name_from_perf_id(void);
+#endif /* CONFIG_PERF_EVENTS */
+
 #endif /* OPROFILE_H */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 10d3330..90c038c 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -393,6 +393,9 @@
 #define PCI_DEVICE_ID_VLSI_82C147	0x0105
 #define PCI_DEVICE_ID_VLSI_VAS96011	0x0702
 
+/* AMD RD890 Chipset */
+#define PCI_DEVICE_ID_RD890_IOMMU	0x5a23
+
 #define PCI_VENDOR_ID_ADL		0x1005
 #define PCI_DEVICE_ID_ADL_2301		0x2301
 
@@ -514,6 +517,7 @@
 #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_LANCE		0x2000
 #define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001
 #define PCI_DEVICE_ID_AMD_SCSI		0x2020
@@ -739,6 +743,7 @@
 #define PCI_DEVICE_ID_HP_CISSC		0x3230
 #define PCI_DEVICE_ID_HP_CISSD		0x3238
 #define PCI_DEVICE_ID_HP_CISSE		0x323a
+#define PCI_DEVICE_ID_HP_CISSF		0x323b
 #define PCI_DEVICE_ID_HP_ZX2_IOC	0x4031
 
 #define PCI_VENDOR_ID_PCTECH		0x1042
@@ -2189,6 +2194,9 @@
 #define PCI_VENDOR_ID_ARIMA		0x161f
 
 #define PCI_VENDOR_ID_BROCADE		0x1657
+#define PCI_DEVICE_ID_BROCADE_CT	0x0014
+#define PCI_DEVICE_ID_BROCADE_FC_8G1P	0x0017
+#define PCI_DEVICE_ID_BROCADE_CT_FC	0x0021
 
 #define PCI_VENDOR_ID_SIBYTE		0x166d
 #define PCI_DEVICE_ID_BCM1250_PCI	0x0001
@@ -2312,6 +2320,14 @@
 #define PCI_DEVICE_ID_P4080		0x0401
 #define PCI_DEVICE_ID_P4040E		0x0408
 #define PCI_DEVICE_ID_P4040		0x0409
+#define PCI_DEVICE_ID_P2040E		0x0410
+#define PCI_DEVICE_ID_P2040		0x0411
+#define PCI_DEVICE_ID_P3041E		0x041E
+#define PCI_DEVICE_ID_P3041		0x041F
+#define PCI_DEVICE_ID_P5020E		0x0420
+#define PCI_DEVICE_ID_P5020		0x0421
+#define PCI_DEVICE_ID_P5010E		0x0428
+#define PCI_DEVICE_ID_P5010		0x0429
 #define PCI_DEVICE_ID_MPC8641		0x7010
 #define PCI_DEVICE_ID_MPC8641D		0x7011
 #define PCI_DEVICE_ID_MPC8610		0x7018
diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h
index ce2dc65..018db9a 100644
--- a/include/linux/percpu-defs.h
+++ b/include/linux/percpu-defs.h
@@ -139,6 +139,27 @@
 	__aligned(PAGE_SIZE)
 
 /*
+ * Declaration/definition used for per-CPU variables that must be read mostly.
+ */
+#define DECLARE_PER_CPU_READ_MOSTLY(type, name)			\
+	DECLARE_PER_CPU_SECTION(type, name, "..readmostly")
+
+#define DEFINE_PER_CPU_READ_MOSTLY(type, name)				\
+	DEFINE_PER_CPU_SECTION(type, name, "..readmostly")
+
+/*
+ * Declaration/definition used for large per-CPU variables that must be
+ * aligned to something larger than the pagesize.
+ */
+#define DECLARE_PER_CPU_MULTIPAGE_ALIGNED(type, name, size)		\
+	DECLARE_PER_CPU_SECTION(type, name, "..page_aligned")		\
+	__aligned(size)
+
+#define DEFINE_PER_CPU_MULTIPAGE_ALIGNED(type, name, size)		\
+	DEFINE_PER_CPU_SECTION(type, name, "..page_aligned")		\
+	__aligned(size)
+
+/*
  * Intermodule exports for per-CPU variables.  sparse forgets about
  * address space across EXPORT_SYMBOL(), change EXPORT_SYMBOL() to
  * noop if __CHECKER__.
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 49466b1..5095b83 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -39,10 +39,17 @@
 	preempt_enable();				\
 } while (0)
 
-#ifdef CONFIG_SMP
+#define get_cpu_ptr(var) ({				\
+	preempt_disable();				\
+	this_cpu_ptr(var); })
+
+#define put_cpu_ptr(var) do {				\
+	(void)(var);					\
+	preempt_enable();				\
+} while (0)
 
 /* minimum unit size, also is the maximum supported allocation size */
-#define PCPU_MIN_UNIT_SIZE		PFN_ALIGN(64 << 10)
+#define PCPU_MIN_UNIT_SIZE		PFN_ALIGN(32 << 10)
 
 /*
  * Percpu allocator can serve percpu allocations before slab is
@@ -137,37 +144,20 @@
  * dynamically allocated. Non-atomic access to the current CPU's
  * version should probably be combined with get_cpu()/put_cpu().
  */
+#ifdef CONFIG_SMP
 #define per_cpu_ptr(ptr, cpu)	SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu)))
+#else
+#define per_cpu_ptr(ptr, cpu)	({ (void)(cpu); VERIFY_PERCPU_PTR((ptr)); })
+#endif
 
 extern void __percpu *__alloc_reserved_percpu(size_t size, size_t align);
 extern bool is_kernel_percpu_address(unsigned long addr);
 
-#ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
+#if !defined(CONFIG_SMP) || !defined(CONFIG_HAVE_SETUP_PER_CPU_AREA)
 extern void __init setup_per_cpu_areas(void);
 #endif
 extern void __init percpu_init_late(void);
 
-#else /* CONFIG_SMP */
-
-#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); VERIFY_PERCPU_PTR((ptr)); })
-
-/* can't distinguish from other static vars, always false */
-static inline bool is_kernel_percpu_address(unsigned long addr)
-{
-	return false;
-}
-
-static inline void __init setup_per_cpu_areas(void) { }
-
-static inline void __init percpu_init_late(void) { }
-
-static inline void *pcpu_lpage_remapped(void *kaddr)
-{
-	return NULL;
-}
-
-#endif /* CONFIG_SMP */
-
 extern void __percpu *__alloc_percpu(size_t size, size_t align);
 extern void free_percpu(void __percpu *__pdata);
 extern phys_addr_t per_cpu_ptr_to_phys(void *addr);
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 716f99b..057bf22 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -486,6 +486,8 @@
 #include <linux/workqueue.h>
 #include <linux/ftrace.h>
 #include <linux/cpu.h>
+#include <linux/irq_work.h>
+#include <linux/jump_label_ref.h>
 #include <asm/atomic.h>
 #include <asm/local.h>
 
@@ -529,16 +531,22 @@
 			int		last_cpu;
 		};
 		struct { /* software */
-			s64		remaining;
 			struct hrtimer	hrtimer;
 		};
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 		struct { /* breakpoint */
 			struct arch_hw_breakpoint	info;
 			struct list_head		bp_list;
+			/*
+			 * Crufty hack to avoid the chicken and egg
+			 * problem hw_breakpoint has with context
+			 * creation and event initalization.
+			 */
+			struct task_struct		*bp_target;
 		};
 #endif
 	};
+	int				state;
 	local64_t			prev_count;
 	u64				sample_period;
 	u64				last_period;
@@ -550,6 +558,13 @@
 #endif
 };
 
+/*
+ * hw_perf_event::state flags
+ */
+#define PERF_HES_STOPPED	0x01 /* the counter is stopped */
+#define PERF_HES_UPTODATE	0x02 /* event->count up-to-date */
+#define PERF_HES_ARCH		0x04
+
 struct perf_event;
 
 /*
@@ -561,36 +576,70 @@
  * struct pmu - generic performance monitoring unit
  */
 struct pmu {
-	int (*enable)			(struct perf_event *event);
-	void (*disable)			(struct perf_event *event);
-	int (*start)			(struct perf_event *event);
-	void (*stop)			(struct perf_event *event);
+	struct list_head		entry;
+
+	int * __percpu			pmu_disable_count;
+	struct perf_cpu_context * __percpu pmu_cpu_context;
+	int				task_ctx_nr;
+
+	/*
+	 * Fully disable/enable this PMU, can be used to protect from the PMI
+	 * as well as for lazy/batch writing of the MSRs.
+	 */
+	void (*pmu_enable)		(struct pmu *pmu); /* optional */
+	void (*pmu_disable)		(struct pmu *pmu); /* optional */
+
+	/*
+	 * Try and initialize the event for this PMU.
+	 * Should return -ENOENT when the @event doesn't match this PMU.
+	 */
+	int (*event_init)		(struct perf_event *event);
+
+#define PERF_EF_START	0x01		/* start the counter when adding    */
+#define PERF_EF_RELOAD	0x02		/* reload the counter when starting */
+#define PERF_EF_UPDATE	0x04		/* update the counter when stopping */
+
+	/*
+	 * Adds/Removes a counter to/from the PMU, can be done inside
+	 * a transaction, see the ->*_txn() methods.
+	 */
+	int  (*add)			(struct perf_event *event, int flags);
+	void (*del)			(struct perf_event *event, int flags);
+
+	/*
+	 * Starts/Stops a counter present on the PMU. The PMI handler
+	 * should stop the counter when perf_event_overflow() returns
+	 * !0. ->start() will be used to continue.
+	 */
+	void (*start)			(struct perf_event *event, int flags);
+	void (*stop)			(struct perf_event *event, int flags);
+
+	/*
+	 * Updates the counter value of the event.
+	 */
 	void (*read)			(struct perf_event *event);
-	void (*unthrottle)		(struct perf_event *event);
 
 	/*
-	 * Group events scheduling is treated as a transaction, add group
-	 * events as a whole and perform one schedulability test. If the test
-	 * fails, roll back the whole group
+	 * Group events scheduling is treated as a transaction, add
+	 * group events as a whole and perform one schedulability test.
+	 * If the test fails, roll back the whole group
+	 *
+	 * Start the transaction, after this ->add() doesn't need to
+	 * do schedulability tests.
 	 */
-
+	void (*start_txn)	(struct pmu *pmu); /* optional */
 	/*
-	 * Start the transaction, after this ->enable() doesn't need
-	 * to do schedulability tests.
-	 */
-	void (*start_txn)	(const struct pmu *pmu);
-	/*
-	 * If ->start_txn() disabled the ->enable() schedulability test
+	 * If ->start_txn() disabled the ->add() schedulability test
 	 * then ->commit_txn() is required to perform one. On success
 	 * the transaction is closed. On error the transaction is kept
 	 * open until ->cancel_txn() is called.
 	 */
-	int  (*commit_txn)	(const struct pmu *pmu);
+	int  (*commit_txn)	(struct pmu *pmu); /* optional */
 	/*
-	 * Will cancel the transaction, assumes ->disable() is called for
-	 * each successfull ->enable() during the transaction.
+	 * Will cancel the transaction, assumes ->del() is called
+	 * for each successfull ->add() during the transaction.
 	 */
-	void (*cancel_txn)	(const struct pmu *pmu);
+	void (*cancel_txn)	(struct pmu *pmu); /* optional */
 };
 
 /**
@@ -631,11 +680,6 @@
 	void				*data_pages[0];
 };
 
-struct perf_pending_entry {
-	struct perf_pending_entry *next;
-	void (*func)(struct perf_pending_entry *);
-};
-
 struct perf_sample_data;
 
 typedef void (*perf_overflow_handler_t)(struct perf_event *, int,
@@ -656,6 +700,7 @@
 
 #define PERF_ATTACH_CONTEXT	0x01
 #define PERF_ATTACH_GROUP	0x02
+#define PERF_ATTACH_TASK	0x04
 
 /**
  * struct perf_event - performance event kernel representation:
@@ -669,7 +714,7 @@
 	int				nr_siblings;
 	int				group_flags;
 	struct perf_event		*group_leader;
-	const struct pmu		*pmu;
+	struct pmu			*pmu;
 
 	enum perf_event_active_state	state;
 	unsigned int			attach_state;
@@ -743,7 +788,7 @@
 	int				pending_wakeup;
 	int				pending_kill;
 	int				pending_disable;
-	struct perf_pending_entry	pending;
+	struct irq_work			pending;
 
 	atomic_t			event_limit;
 
@@ -763,12 +808,19 @@
 #endif /* CONFIG_PERF_EVENTS */
 };
 
+enum perf_event_context_type {
+	task_context,
+	cpu_context,
+};
+
 /**
  * struct perf_event_context - event context structure
  *
  * 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;
 	/*
 	 * Protect the states of the events in the list,
 	 * nr_active, and the list:
@@ -808,6 +860,12 @@
 	struct rcu_head			rcu_head;
 };
 
+/*
+ * Number of contexts where an event can trigger:
+ * 	task, softirq, hardirq, nmi.
+ */
+#define PERF_NR_CONTEXTS	4
+
 /**
  * struct perf_event_cpu_context - per cpu event context structure
  */
@@ -815,18 +873,9 @@
 	struct perf_event_context	ctx;
 	struct perf_event_context	*task_ctx;
 	int				active_oncpu;
-	int				max_pertask;
 	int				exclusive;
-	struct swevent_hlist		*swevent_hlist;
-	struct mutex			hlist_mutex;
-	int				hlist_refcount;
-
-	/*
-	 * Recursion avoidance:
-	 *
-	 * task, softirq, irq, nmi context
-	 */
-	int				recursion[4];
+	struct list_head		rotation_list;
+	int				jiffies_interval;
 };
 
 struct perf_output_handle {
@@ -842,26 +891,34 @@
 
 #ifdef CONFIG_PERF_EVENTS
 
-/*
- * Set by architecture code:
- */
-extern int perf_max_events;
+extern int perf_pmu_register(struct pmu *pmu);
+extern void perf_pmu_unregister(struct pmu *pmu);
 
-extern const struct pmu *hw_perf_event_init(struct perf_event *event);
+extern int perf_num_counters(void);
+extern const char *perf_pmu_name(void);
+extern void __perf_event_task_sched_in(struct task_struct *task);
+extern void __perf_event_task_sched_out(struct task_struct *task, struct task_struct *next);
 
-extern void perf_event_task_sched_in(struct task_struct *task);
-extern void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next);
-extern void perf_event_task_tick(struct task_struct *task);
+extern atomic_t perf_task_events;
+
+static inline void perf_event_task_sched_in(struct task_struct *task)
+{
+	COND_STMT(&perf_task_events, __perf_event_task_sched_in(task));
+}
+
+static inline
+void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next)
+{
+	COND_STMT(&perf_task_events, __perf_event_task_sched_out(task, next));
+}
+
 extern int perf_event_init_task(struct task_struct *child);
 extern void perf_event_exit_task(struct task_struct *child);
 extern void perf_event_free_task(struct task_struct *task);
-extern void set_perf_event_pending(void);
-extern void perf_event_do_pending(void);
+extern void perf_event_delayed_put(struct task_struct *task);
 extern void perf_event_print_debug(void);
-extern void __perf_disable(void);
-extern bool __perf_enable(void);
-extern void perf_disable(void);
-extern void perf_enable(void);
+extern void perf_pmu_disable(struct pmu *pmu);
+extern void perf_pmu_enable(struct pmu *pmu);
 extern int perf_event_task_disable(void);
 extern int perf_event_task_enable(void);
 extern void perf_event_update_userpage(struct perf_event *event);
@@ -869,7 +926,7 @@
 extern struct perf_event *
 perf_event_create_kernel_counter(struct perf_event_attr *attr,
 				int cpu,
-				pid_t pid,
+				struct task_struct *task,
 				perf_overflow_handler_t callback);
 extern u64 perf_event_read_value(struct perf_event *event,
 				 u64 *enabled, u64 *running);
@@ -920,14 +977,7 @@
  */
 static inline int is_software_event(struct perf_event *event)
 {
-	switch (event->attr.type) {
-	case PERF_TYPE_SOFTWARE:
-	case PERF_TYPE_TRACEPOINT:
-	/* for now the breakpoint stuff also works as software event */
-	case PERF_TYPE_BREAKPOINT:
-		return 1;
-	}
-	return 0;
+	return event->pmu->task_ctx_nr == perf_sw_context;
 }
 
 extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
@@ -954,18 +1004,20 @@
 	perf_arch_fetch_caller_regs(regs, CALLER_ADDR0);
 }
 
-static inline void
+static __always_inline void
 perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
 {
-	if (atomic_read(&perf_swevent_enabled[event_id])) {
-		struct pt_regs hot_regs;
+	struct pt_regs hot_regs;
 
-		if (!regs) {
-			perf_fetch_caller_regs(&hot_regs);
-			regs = &hot_regs;
-		}
-		__perf_sw_event(event_id, nr, nmi, regs, addr);
+	JUMP_LABEL(&perf_swevent_enabled[event_id], have_event);
+	return;
+
+have_event:
+	if (!regs) {
+		perf_fetch_caller_regs(&hot_regs);
+		regs = &hot_regs;
 	}
+	__perf_sw_event(event_id, nr, nmi, regs, addr);
 }
 
 extern void perf_event_mmap(struct vm_area_struct *vma);
@@ -976,7 +1028,21 @@
 extern void perf_event_comm(struct task_struct *tsk);
 extern void perf_event_fork(struct task_struct *tsk);
 
-extern struct perf_callchain_entry *perf_callchain(struct pt_regs *regs);
+/* Callchains */
+DECLARE_PER_CPU(struct perf_callchain_entry, perf_callchain_entry);
+
+extern void perf_callchain_user(struct perf_callchain_entry *entry,
+				struct pt_regs *regs);
+extern void perf_callchain_kernel(struct perf_callchain_entry *entry,
+				  struct pt_regs *regs);
+
+
+static inline void
+perf_callchain_store(struct perf_callchain_entry *entry, u64 ip)
+{
+	if (entry->nr < PERF_MAX_STACK_DEPTH)
+		entry->ip[entry->nr++] = ip;
+}
 
 extern int sysctl_perf_event_paranoid;
 extern int sysctl_perf_event_mlock;
@@ -1019,21 +1085,18 @@
 extern void perf_swevent_put_recursion_context(int rctx);
 extern void perf_event_enable(struct perf_event *event);
 extern void perf_event_disable(struct perf_event *event);
+extern void perf_event_task_tick(void);
 #else
 static inline void
 perf_event_task_sched_in(struct task_struct *task)			{ }
 static inline void
 perf_event_task_sched_out(struct task_struct *task,
 			    struct task_struct *next)			{ }
-static inline void
-perf_event_task_tick(struct task_struct *task)				{ }
 static inline int perf_event_init_task(struct task_struct *child)	{ return 0; }
 static inline void perf_event_exit_task(struct task_struct *child)	{ }
 static inline void perf_event_free_task(struct task_struct *task)	{ }
-static inline void perf_event_do_pending(void)				{ }
+static inline void perf_event_delayed_put(struct task_struct *task)	{ }
 static inline void perf_event_print_debug(void)				{ }
-static inline void perf_disable(void)					{ }
-static inline void perf_enable(void)					{ }
 static inline int perf_event_task_disable(void)				{ return -EINVAL; }
 static inline int perf_event_task_enable(void)				{ return -EINVAL; }
 
@@ -1056,6 +1119,7 @@
 static inline void perf_swevent_put_recursion_context(int rctx)		{ }
 static inline void perf_event_enable(struct perf_event *event)		{ }
 static inline void perf_event_disable(struct perf_event *event)		{ }
+static inline void perf_event_task_tick(void)				{ }
 #endif
 
 #define perf_output_put(handle, x) \
diff --git a/include/linux/phonet.h b/include/linux/phonet.h
index 76edadf..26c8df7 100644
--- a/include/linux/phonet.h
+++ b/include/linux/phonet.h
@@ -36,6 +36,9 @@
 /* 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 PNADDR_ANY		0
 #define PNADDR_BROADCAST	0xFC
@@ -47,6 +50,8 @@
 
 /* ioctls */
 #define SIOCPNGETOBJECT		(SIOCPROTOPRIVATE + 0)
+#define SIOCPNADDRESOURCE	(SIOCPROTOPRIVATE + 14)
+#define SIOCPNDELRESOURCE	(SIOCPROTOPRIVATE + 15)
 
 /* Phonet protocol header */
 struct phonethdr {
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 6b0a782..a6e047a 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -116,7 +116,7 @@
 	/* list of all PHYs on bus */
 	struct phy_device *phy_map[PHY_MAX_ADDR];
 
-	/* Phy addresses to be ignored when probing */
+	/* PHY addresses to be ignored when probing */
 	u32 phy_mask;
 
 	/*
@@ -283,7 +283,7 @@
 
 	phy_interface_t interface;
 
-	/* Bus address of the PHY (0-32) */
+	/* Bus address of the PHY (0-31) */
 	int addr;
 
 	/*
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index 7f6ba86..defbde2 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -332,6 +332,7 @@
 	FLOW_KEY_SKUID,
 	FLOW_KEY_SKGID,
 	FLOW_KEY_VLAN_TAG,
+	FLOW_KEY_RXHASH,
 	__FLOW_KEY_MAX,
 };
 
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index d7ecad0..2e700ec 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -138,6 +138,9 @@
 					struct resource *res, unsigned int n_res,
 					const void *data, size_t size);
 
+extern const struct dev_pm_ops * platform_bus_get_pm_ops(void);
+extern void platform_bus_set_pm_ops(const struct dev_pm_ops *pm);
+
 /* early platform driver interface */
 struct early_platform_driver {
 	const char *class_str;
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 52e8c55..40f3f45 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -41,6 +41,12 @@
 
 struct device;
 
+#ifdef CONFIG_PM
+extern const char power_group_name[];		/* = "power" */
+#else
+#define power_group_name	NULL
+#endif
+
 typedef struct pm_message {
 	int event;
 } pm_message_t;
@@ -438,6 +444,9 @@
  *
  * RPM_REQ_SUSPEND	Run the device bus type's ->runtime_suspend() callback
  *
+ * RPM_REQ_AUTOSUSPEND	Same as RPM_REQ_SUSPEND, but not until the device has
+ *			been inactive for as long as power.autosuspend_delay
+ *
  * RPM_REQ_RESUME	Run the device bus type's ->runtime_resume() callback
  */
 
@@ -445,26 +454,28 @@
 	RPM_REQ_NONE = 0,
 	RPM_REQ_IDLE,
 	RPM_REQ_SUSPEND,
+	RPM_REQ_AUTOSUSPEND,
 	RPM_REQ_RESUME,
 };
 
+struct wakeup_source;
+
 struct dev_pm_info {
 	pm_message_t		power_state;
 	unsigned int		can_wakeup:1;
-	unsigned int		should_wakeup:1;
 	unsigned		async_suspend:1;
 	enum dpm_state		status;		/* Owned by the PM core */
+	spinlock_t		lock;
 #ifdef CONFIG_PM_SLEEP
 	struct list_head	entry;
 	struct completion	completion;
-	unsigned long		wakeup_count;
+	struct wakeup_source	*wakeup;
 #endif
 #ifdef CONFIG_PM_RUNTIME
 	struct timer_list	suspend_timer;
 	unsigned long		timer_expires;
 	struct work_struct	work;
 	wait_queue_head_t	wait_queue;
-	spinlock_t		lock;
 	atomic_t		usage_count;
 	atomic_t		child_count;
 	unsigned int		disable_depth:3;
@@ -474,9 +485,14 @@
 	unsigned int		deferred_resume:1;
 	unsigned int		run_wake:1;
 	unsigned int		runtime_auto:1;
+	unsigned int		no_callbacks:1;
+	unsigned int		use_autosuspend:1;
+	unsigned int		timer_autosuspends:1;
 	enum rpm_request	request;
 	enum rpm_status		runtime_status;
 	int			runtime_error;
+	int			autosuspend_delay;
+	unsigned long		last_busy;
 	unsigned long		active_jiffies;
 	unsigned long		suspended_jiffies;
 	unsigned long		accounting_timestamp;
@@ -558,12 +574,7 @@
 		__suspend_report_result(__func__, fn, ret);		\
 	} while (0)
 
-extern void device_pm_wait_for_dev(struct device *sub, struct device *dev);
-
-/* drivers/base/power/wakeup.c */
-extern void pm_wakeup_event(struct device *dev, unsigned int msec);
-extern void pm_stay_awake(struct device *dev);
-extern void pm_relax(void);
+extern int device_pm_wait_for_dev(struct device *sub, struct device *dev);
 #else /* !CONFIG_PM_SLEEP */
 
 #define device_pm_lock() do {} while (0)
@@ -576,11 +587,10 @@
 
 #define suspend_report_result(fn, ret)		do {} while (0)
 
-static inline void device_pm_wait_for_dev(struct device *a, struct device *b) {}
-
-static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {}
-static inline void pm_stay_awake(struct device *dev) {}
-static inline void pm_relax(void) {}
+static inline int device_pm_wait_for_dev(struct device *a, struct device *b)
+{
+	return 0;
+}
 #endif /* !CONFIG_PM_SLEEP */
 
 /* How to reorder dpm_list after device_move() */
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index 6e81888..3ec2358 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -12,18 +12,24 @@
 #include <linux/device.h>
 #include <linux/pm.h>
 
+#include <linux/jiffies.h>
+
+/* Runtime PM flag argument bits */
+#define RPM_ASYNC		0x01	/* Request is asynchronous */
+#define RPM_NOWAIT		0x02	/* Don't wait for concurrent
+					    state change */
+#define RPM_GET_PUT		0x04	/* Increment/decrement the
+					    usage_count */
+#define RPM_AUTO		0x08	/* Use autosuspend_delay */
+
 #ifdef CONFIG_PM_RUNTIME
 
 extern struct workqueue_struct *pm_wq;
 
-extern int pm_runtime_idle(struct device *dev);
-extern int pm_runtime_suspend(struct device *dev);
-extern int pm_runtime_resume(struct device *dev);
-extern int pm_request_idle(struct device *dev);
+extern int __pm_runtime_idle(struct device *dev, int rpmflags);
+extern int __pm_runtime_suspend(struct device *dev, int rpmflags);
+extern int __pm_runtime_resume(struct device *dev, int rpmflags);
 extern int pm_schedule_suspend(struct device *dev, unsigned int delay);
-extern int pm_request_resume(struct device *dev);
-extern int __pm_runtime_get(struct device *dev, bool sync);
-extern int __pm_runtime_put(struct device *dev, bool sync);
 extern int __pm_runtime_set_status(struct device *dev, unsigned int status);
 extern int pm_runtime_barrier(struct device *dev);
 extern void pm_runtime_enable(struct device *dev);
@@ -33,6 +39,10 @@
 extern int pm_generic_runtime_idle(struct device *dev);
 extern int pm_generic_runtime_suspend(struct device *dev);
 extern int pm_generic_runtime_resume(struct device *dev);
+extern void pm_runtime_no_callbacks(struct device *dev);
+extern void __pm_runtime_use_autosuspend(struct device *dev, bool use);
+extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
+extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
 
 static inline bool pm_children_suspended(struct device *dev)
 {
@@ -70,19 +80,29 @@
 	return dev->power.runtime_status == RPM_SUSPENDED;
 }
 
+static inline void pm_runtime_mark_last_busy(struct device *dev)
+{
+	ACCESS_ONCE(dev->power.last_busy) = jiffies;
+}
+
 #else /* !CONFIG_PM_RUNTIME */
 
-static inline int pm_runtime_idle(struct device *dev) { return -ENOSYS; }
-static inline int pm_runtime_suspend(struct device *dev) { return -ENOSYS; }
-static inline int pm_runtime_resume(struct device *dev) { return 0; }
-static inline int pm_request_idle(struct device *dev) { return -ENOSYS; }
+static inline int __pm_runtime_idle(struct device *dev, int rpmflags)
+{
+	return -ENOSYS;
+}
+static inline int __pm_runtime_suspend(struct device *dev, int rpmflags)
+{
+	return -ENOSYS;
+}
+static inline int __pm_runtime_resume(struct device *dev, int rpmflags)
+{
+	return 1;
+}
 static inline int pm_schedule_suspend(struct device *dev, unsigned int delay)
 {
 	return -ENOSYS;
 }
-static inline int pm_request_resume(struct device *dev) { return 0; }
-static inline int __pm_runtime_get(struct device *dev, bool sync) { return 1; }
-static inline int __pm_runtime_put(struct device *dev, bool sync) { return 0; }
 static inline int __pm_runtime_set_status(struct device *dev,
 					    unsigned int status) { return 0; }
 static inline int pm_runtime_barrier(struct device *dev) { return 0; }
@@ -102,27 +122,82 @@
 static inline int pm_generic_runtime_idle(struct device *dev) { return 0; }
 static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
 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_mark_last_busy(struct device *dev) {}
+static inline void __pm_runtime_use_autosuspend(struct device *dev,
+						bool use) {}
+static inline void pm_runtime_set_autosuspend_delay(struct device *dev,
+						int delay) {}
+static inline unsigned long pm_runtime_autosuspend_expiration(
+				struct device *dev) { return 0; }
 
 #endif /* !CONFIG_PM_RUNTIME */
 
+static inline int pm_runtime_idle(struct device *dev)
+{
+	return __pm_runtime_idle(dev, 0);
+}
+
+static inline int pm_runtime_suspend(struct device *dev)
+{
+	return __pm_runtime_suspend(dev, 0);
+}
+
+static inline int pm_runtime_autosuspend(struct device *dev)
+{
+	return __pm_runtime_suspend(dev, RPM_AUTO);
+}
+
+static inline int pm_runtime_resume(struct device *dev)
+{
+	return __pm_runtime_resume(dev, 0);
+}
+
+static inline int pm_request_idle(struct device *dev)
+{
+	return __pm_runtime_idle(dev, RPM_ASYNC);
+}
+
+static inline int pm_request_resume(struct device *dev)
+{
+	return __pm_runtime_resume(dev, RPM_ASYNC);
+}
+
+static inline int pm_request_autosuspend(struct device *dev)
+{
+	return __pm_runtime_suspend(dev, RPM_ASYNC | RPM_AUTO);
+}
+
 static inline int pm_runtime_get(struct device *dev)
 {
-	return __pm_runtime_get(dev, false);
+	return __pm_runtime_resume(dev, RPM_GET_PUT | RPM_ASYNC);
 }
 
 static inline int pm_runtime_get_sync(struct device *dev)
 {
-	return __pm_runtime_get(dev, true);
+	return __pm_runtime_resume(dev, RPM_GET_PUT);
 }
 
 static inline int pm_runtime_put(struct device *dev)
 {
-	return __pm_runtime_put(dev, false);
+	return __pm_runtime_idle(dev, RPM_GET_PUT | RPM_ASYNC);
+}
+
+static inline int pm_runtime_put_autosuspend(struct device *dev)
+{
+	return __pm_runtime_suspend(dev,
+	    RPM_GET_PUT | RPM_ASYNC | RPM_AUTO);
 }
 
 static inline int pm_runtime_put_sync(struct device *dev)
 {
-	return __pm_runtime_put(dev, true);
+	return __pm_runtime_idle(dev, RPM_GET_PUT);
+}
+
+static inline int pm_runtime_put_sync_autosuspend(struct device *dev)
+{
+	return __pm_runtime_suspend(dev, RPM_GET_PUT | RPM_AUTO);
 }
 
 static inline int pm_runtime_set_active(struct device *dev)
@@ -140,4 +215,14 @@
 	__pm_runtime_disable(dev, true);
 }
 
+static inline void pm_runtime_use_autosuspend(struct device *dev)
+{
+	__pm_runtime_use_autosuspend(dev, true);
+}
+
+static inline void pm_runtime_dont_use_autosuspend(struct device *dev)
+{
+	__pm_runtime_use_autosuspend(dev, false);
+}
+
 #endif
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
index 76aca48..9cff00d 100644
--- a/include/linux/pm_wakeup.h
+++ b/include/linux/pm_wakeup.h
@@ -2,6 +2,7 @@
  *  pm_wakeup.h - Power management wakeup interface
  *
  *  Copyright (C) 2008 Alan Stern
+ *  Copyright (C) 2010 Rafael J. Wysocki, 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
@@ -27,18 +28,39 @@
 
 #include <linux/types.h>
 
-#ifdef CONFIG_PM
-
-/* Changes to device_may_wakeup take effect on the next pm state change.
+/**
+ * struct wakeup_source - Representation of wakeup sources
  *
- * By default, most devices should leave wakeup disabled.  The exceptions
- * are devices that everyone expects to be wakeup sources: keyboards,
- * power buttons, possibly network interfaces, etc.
+ * @total_time: Total time this wakeup source has been active.
+ * @max_time: Maximum time this wakeup source has been continuously active.
+ * @last_time: Monotonic clock when the wakeup source's was activated last time.
+ * @event_count: Number of signaled wakeup events.
+ * @active_count: Number of times the wakeup sorce was activated.
+ * @relax_count: Number of times the wakeup sorce was deactivated.
+ * @hit_count: Number of times the wakeup sorce might abort system suspend.
+ * @active: Status of the wakeup source.
  */
-static inline void device_init_wakeup(struct device *dev, bool val)
-{
-	dev->power.can_wakeup = dev->power.should_wakeup = val;
-}
+struct wakeup_source {
+	char 			*name;
+	struct list_head	entry;
+	spinlock_t		lock;
+	struct timer_list	timer;
+	unsigned long		timer_expires;
+	ktime_t total_time;
+	ktime_t max_time;
+	ktime_t last_time;
+	unsigned long		event_count;
+	unsigned long		active_count;
+	unsigned long		relax_count;
+	unsigned long		hit_count;
+	unsigned int		active:1;
+};
+
+#ifdef CONFIG_PM_SLEEP
+
+/*
+ * 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)
 {
@@ -50,23 +72,32 @@
 	return dev->power.can_wakeup;
 }
 
-static inline void device_set_wakeup_enable(struct device *dev, bool enable)
-{
-	dev->power.should_wakeup = enable;
-}
+
 
 static inline bool device_may_wakeup(struct device *dev)
 {
-	return dev->power.can_wakeup && dev->power.should_wakeup;
+	return dev->power.can_wakeup && !!dev->power.wakeup;
 }
 
-#else /* !CONFIG_PM */
+/* drivers/base/power/wakeup.c */
+extern struct wakeup_source *wakeup_source_create(const char *name);
+extern void wakeup_source_destroy(struct wakeup_source *ws);
+extern void wakeup_source_add(struct wakeup_source *ws);
+extern void wakeup_source_remove(struct wakeup_source *ws);
+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 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);
+extern void pm_stay_awake(struct device *dev);
+extern void __pm_relax(struct wakeup_source *ws);
+extern void pm_relax(struct device *dev);
+extern void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec);
+extern void pm_wakeup_event(struct device *dev, unsigned int msec);
 
-/* For some reason the following routines work even without CONFIG_PM */
-static inline void device_init_wakeup(struct device *dev, bool val)
-{
-	dev->power.can_wakeup = val;
-}
+#else /* !CONFIG_PM_SLEEP */
 
 static inline void device_set_wakeup_capable(struct device *dev, bool capable)
 {
@@ -78,15 +109,63 @@
 	return dev->power.can_wakeup;
 }
 
-static inline void device_set_wakeup_enable(struct device *dev, bool enable)
-{
-}
-
 static inline bool device_may_wakeup(struct device *dev)
 {
 	return false;
 }
 
-#endif /* !CONFIG_PM */
+static inline struct wakeup_source *wakeup_source_create(const char *name)
+{
+	return NULL;
+}
+
+static inline void wakeup_source_destroy(struct wakeup_source *ws) {}
+
+static inline void wakeup_source_add(struct wakeup_source *ws) {}
+
+static inline void wakeup_source_remove(struct wakeup_source *ws) {}
+
+static inline struct wakeup_source *wakeup_source_register(const char *name)
+{
+	return NULL;
+}
+
+static inline void wakeup_source_unregister(struct wakeup_source *ws) {}
+
+static inline int device_wakeup_enable(struct device *dev)
+{
+	return -EINVAL;
+}
+
+static inline int device_wakeup_disable(struct device *dev)
+{
+	return 0;
+}
+
+static inline int device_init_wakeup(struct device *dev, bool val)
+{
+	dev->power.can_wakeup = val;
+	return val ? -EINVAL : 0;
+}
+
+
+static inline int device_set_wakeup_enable(struct device *dev, bool enable)
+{
+	return -EINVAL;
+}
+
+static inline void __pm_stay_awake(struct wakeup_source *ws) {}
+
+static inline void pm_stay_awake(struct device *dev) {}
+
+static inline void __pm_relax(struct wakeup_source *ws) {}
+
+static inline void pm_relax(struct device *dev) {}
+
+static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) {}
+
+static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {}
+
+#endif /* !CONFIG_PM_SLEEP */
 
 #endif /* _LINUX_PM_WAKEUP_H */
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 634b8e6..a39cbed 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -47,6 +47,8 @@
 {
 	return (void *)((unsigned long)ptr & ~RADIX_TREE_INDIRECT_PTR);
 }
+#define radix_tree_indirect_to_ptr(ptr) \
+	radix_tree_indirect_to_ptr((void __force *)(ptr))
 
 static inline int radix_tree_is_indirect_ptr(void *ptr)
 {
@@ -61,7 +63,7 @@
 struct radix_tree_root {
 	unsigned int		height;
 	gfp_t			gfp_mask;
-	struct radix_tree_node	*rnode;
+	struct radix_tree_node	__rcu *rnode;
 };
 
 #define RADIX_TREE_INIT(mask)	{					\
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index 4ec3b38..f31ef61 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -10,6 +10,21 @@
 #include <linux/rcupdate.h>
 
 /*
+ * Why is there no list_empty_rcu()?  Because list_empty() serves this
+ * purpose.  The list_empty() function fetches the RCU-protected pointer
+ * and compares it to the address of the list head, but neither dereferences
+ * this pointer itself nor provides this pointer to the caller.  Therefore,
+ * it is not necessary to use rcu_dereference(), so that list_empty() can
+ * be used anywhere you would want to use a list_empty_rcu().
+ */
+
+/*
+ * return the ->next pointer of a list_head in an rcu safe
+ * way, we must not access it directly
+ */
+#define list_next_rcu(list)	(*((struct list_head __rcu **)(&(list)->next)))
+
+/*
  * Insert a new entry between two known consecutive entries.
  *
  * This is only for internal list manipulation where we know
@@ -20,7 +35,7 @@
 {
 	new->next = next;
 	new->prev = prev;
-	rcu_assign_pointer(prev->next, new);
+	rcu_assign_pointer(list_next_rcu(prev), new);
 	next->prev = new;
 }
 
@@ -138,7 +153,7 @@
 {
 	new->next = old->next;
 	new->prev = old->prev;
-	rcu_assign_pointer(new->prev->next, new);
+	rcu_assign_pointer(list_next_rcu(new->prev), new);
 	new->next->prev = new;
 	old->prev = LIST_POISON2;
 }
@@ -193,7 +208,7 @@
 	 */
 
 	last->next = at;
-	rcu_assign_pointer(head->next, first);
+	rcu_assign_pointer(list_next_rcu(head), first);
 	first->prev = head;
 	at->prev = last;
 }
@@ -208,7 +223,9 @@
  * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
  */
 #define list_entry_rcu(ptr, type, member) \
-	container_of(rcu_dereference_raw(ptr), type, member)
+	({typeof (*ptr) __rcu *__ptr = (typeof (*ptr) __rcu __force *)ptr; \
+	 container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \
+	})
 
 /**
  * list_first_entry_rcu - get the first element from a list
@@ -225,9 +242,9 @@
 	list_entry_rcu((ptr)->next, type, member)
 
 #define __list_for_each_rcu(pos, head) \
-	for (pos = rcu_dereference_raw((head)->next); \
+	for (pos = rcu_dereference_raw(list_next_rcu(head)); \
 		pos != (head); \
-		pos = rcu_dereference_raw(pos->next))
+		pos = rcu_dereference_raw(list_next_rcu((pos)))
 
 /**
  * list_for_each_entry_rcu	-	iterate over rcu list of given type
@@ -257,9 +274,9 @@
  * as long as the traversal is guarded by rcu_read_lock().
  */
 #define list_for_each_continue_rcu(pos, head) \
-	for ((pos) = rcu_dereference_raw((pos)->next); \
+	for ((pos) = rcu_dereference_raw(list_next_rcu(pos)); \
 		prefetch((pos)->next), (pos) != (head); \
-		(pos) = rcu_dereference_raw((pos)->next))
+		(pos) = rcu_dereference_raw(list_next_rcu(pos)))
 
 /**
  * list_for_each_entry_continue_rcu - continue iteration over list of given type
@@ -314,12 +331,19 @@
 
 	new->next = next;
 	new->pprev = old->pprev;
-	rcu_assign_pointer(*new->pprev, new);
+	rcu_assign_pointer(*(struct hlist_node __rcu **)new->pprev, new);
 	if (next)
 		new->next->pprev = &new->next;
 	old->pprev = LIST_POISON2;
 }
 
+/*
+ * return the first or the next element in an RCU protected hlist
+ */
+#define hlist_first_rcu(head)	(*((struct hlist_node __rcu **)(&(head)->first)))
+#define hlist_next_rcu(node)	(*((struct hlist_node __rcu **)(&(node)->next)))
+#define hlist_pprev_rcu(node)	(*((struct hlist_node __rcu **)((node)->pprev)))
+
 /**
  * hlist_add_head_rcu
  * @n: the element to add to the hash list.
@@ -346,7 +370,7 @@
 
 	n->next = first;
 	n->pprev = &h->first;
-	rcu_assign_pointer(h->first, n);
+	rcu_assign_pointer(hlist_first_rcu(h), n);
 	if (first)
 		first->pprev = &n->next;
 }
@@ -374,7 +398,7 @@
 {
 	n->pprev = next->pprev;
 	n->next = next;
-	rcu_assign_pointer(*(n->pprev), n);
+	rcu_assign_pointer(hlist_pprev_rcu(n), n);
 	next->pprev = &n->next;
 }
 
@@ -401,15 +425,15 @@
 {
 	n->next = prev->next;
 	n->pprev = &prev->next;
-	rcu_assign_pointer(prev->next, n);
+	rcu_assign_pointer(hlist_next_rcu(prev), n);
 	if (n->next)
 		n->next->pprev = &n->next;
 }
 
-#define __hlist_for_each_rcu(pos, head)			\
-	for (pos = rcu_dereference((head)->first);	\
-	     pos && ({ prefetch(pos->next); 1; });	\
-	     pos = rcu_dereference(pos->next))
+#define __hlist_for_each_rcu(pos, head)				\
+	for (pos = rcu_dereference(hlist_first_rcu(head));	\
+	     pos && ({ prefetch(pos->next); 1; });		\
+	     pos = rcu_dereference(hlist_next_rcu(pos)))
 
 /**
  * hlist_for_each_entry_rcu - iterate over rcu list of given type
@@ -422,11 +446,11 @@
  * the _rcu list-mutation primitives such as hlist_add_head_rcu()
  * as long as the traversal is guarded by rcu_read_lock().
  */
-#define hlist_for_each_entry_rcu(tpos, pos, head, member)		 \
-	for (pos = rcu_dereference_raw((head)->first);			 \
+#define hlist_for_each_entry_rcu(tpos, pos, head, member)		\
+	for (pos = rcu_dereference_raw(hlist_first_rcu(head));		\
 		pos && ({ prefetch(pos->next); 1; }) &&			 \
 		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
-		pos = rcu_dereference_raw(pos->next))
+		pos = rcu_dereference_raw(hlist_next_rcu(pos)))
 
 /**
  * hlist_for_each_entry_rcu_bh - iterate over rcu list of given type
diff --git a/include/linux/rculist_nulls.h b/include/linux/rculist_nulls.h
index b70ffe5..2ae1371 100644
--- a/include/linux/rculist_nulls.h
+++ b/include/linux/rculist_nulls.h
@@ -37,6 +37,12 @@
 	}
 }
 
+#define hlist_nulls_first_rcu(head) \
+	(*((struct hlist_nulls_node __rcu __force **)&(head)->first))
+
+#define hlist_nulls_next_rcu(node) \
+	(*((struct hlist_nulls_node __rcu __force **)&(node)->next))
+
 /**
  * hlist_nulls_del_rcu - deletes entry from hash list without re-initialization
  * @n: the element to delete from the hash list.
@@ -88,7 +94,7 @@
 
 	n->next = first;
 	n->pprev = &h->first;
-	rcu_assign_pointer(h->first, n);
+	rcu_assign_pointer(hlist_nulls_first_rcu(h), n);
 	if (!is_a_nulls(first))
 		first->pprev = &n->next;
 }
@@ -100,11 +106,11 @@
  * @member:	the name of the hlist_nulls_node within the struct.
  *
  */
-#define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member) \
-	for (pos = rcu_dereference_raw((head)->first);			 \
-		(!is_a_nulls(pos)) &&			\
+#define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member)			\
+	for (pos = rcu_dereference_raw(hlist_nulls_first_rcu(head));		\
+		(!is_a_nulls(pos)) &&						\
 		({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1; }); \
-		pos = rcu_dereference_raw(pos->next))
+		pos = rcu_dereference_raw(hlist_nulls_next_rcu(pos)))
 
 #endif
 #endif
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 9fbc54a..03cda7b 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -41,11 +41,15 @@
 #include <linux/lockdep.h>
 #include <linux/completion.h>
 #include <linux/debugobjects.h>
+#include <linux/compiler.h>
 
 #ifdef CONFIG_RCU_TORTURE_TEST
 extern int rcutorture_runnable; /* for sysctl */
 #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
 
+#define ULONG_CMP_GE(a, b)	(ULONG_MAX / 2 >= (a) - (b))
+#define ULONG_CMP_LT(a, b)	(ULONG_MAX / 2 < (a) - (b))
+
 /**
  * struct rcu_head - callback structure for use with RCU
  * @next: next update requests in a list
@@ -57,29 +61,94 @@
 };
 
 /* Exported common interfaces */
-extern void rcu_barrier(void);
+extern void call_rcu_sched(struct rcu_head *head,
+			   void (*func)(struct rcu_head *rcu));
+extern void synchronize_sched(void);
 extern void rcu_barrier_bh(void);
 extern void rcu_barrier_sched(void);
 extern void synchronize_sched_expedited(void);
 extern int sched_expedited_torture_stats(char *page);
 
+static inline void __rcu_read_lock_bh(void)
+{
+	local_bh_disable();
+}
+
+static inline void __rcu_read_unlock_bh(void)
+{
+	local_bh_enable();
+}
+
+#ifdef CONFIG_PREEMPT_RCU
+
+extern void __rcu_read_lock(void);
+extern void __rcu_read_unlock(void);
+void synchronize_rcu(void);
+
+/*
+ * Defined as a macro as it is a very low level header included from
+ * areas that don't even know about current.  This gives the rcu_read_lock()
+ * nesting depth, but makes sense only if CONFIG_PREEMPT_RCU -- in other
+ * types of kernel builds, the rcu_read_lock() nesting depth is unknowable.
+ */
+#define rcu_preempt_depth() (current->rcu_read_lock_nesting)
+
+#else /* #ifdef CONFIG_PREEMPT_RCU */
+
+static inline void __rcu_read_lock(void)
+{
+	preempt_disable();
+}
+
+static inline void __rcu_read_unlock(void)
+{
+	preempt_enable();
+}
+
+static inline void synchronize_rcu(void)
+{
+	synchronize_sched();
+}
+
+static inline int rcu_preempt_depth(void)
+{
+	return 0;
+}
+
+#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
+
 /* Internal to kernel */
 extern void rcu_init(void);
+extern void rcu_sched_qs(int cpu);
+extern void rcu_bh_qs(int cpu);
+extern void rcu_check_callbacks(int cpu, int user);
+struct notifier_block;
+
+#ifdef CONFIG_NO_HZ
+
+extern void rcu_enter_nohz(void);
+extern void rcu_exit_nohz(void);
+
+#else /* #ifdef CONFIG_NO_HZ */
+
+static inline void rcu_enter_nohz(void)
+{
+}
+
+static inline void rcu_exit_nohz(void)
+{
+}
+
+#endif /* #else #ifdef CONFIG_NO_HZ */
 
 #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
 #include <linux/rcutree.h>
-#elif defined(CONFIG_TINY_RCU)
+#elif defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU)
 #include <linux/rcutiny.h>
 #else
 #error "Unknown RCU implementation specified to kernel configuration"
 #endif
 
-#define RCU_HEAD_INIT	{ .next = NULL, .func = NULL }
-#define RCU_HEAD(head) struct rcu_head head = RCU_HEAD_INIT
-#define INIT_RCU_HEAD(ptr) do { \
-       (ptr)->next = NULL; (ptr)->func = NULL; \
-} while (0)
-
 /*
  * init_rcu_head_on_stack()/destroy_rcu_head_on_stack() are needed for dynamic
  * initialization and destruction of rcu_head on the stack. rcu_head structures
@@ -120,14 +189,15 @@
 extern int debug_lockdep_rcu_enabled(void);
 
 /**
- * rcu_read_lock_held - might we be in RCU read-side critical section?
+ * rcu_read_lock_held() - might we be in RCU read-side critical section?
  *
  * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an RCU
  * read-side critical section.  In absence of CONFIG_DEBUG_LOCK_ALLOC,
  * this assumes we are in an RCU read-side critical section unless it can
- * prove otherwise.
+ * prove otherwise.  This is useful for debug checks in functions that
+ * require that they be called within an RCU read-side critical section.
  *
- * Check debug_lockdep_rcu_enabled() to prevent false positives during boot
+ * Checks debug_lockdep_rcu_enabled() to prevent false positives during boot
  * and while lockdep is disabled.
  */
 static inline int rcu_read_lock_held(void)
@@ -144,14 +214,16 @@
 extern int rcu_read_lock_bh_held(void);
 
 /**
- * rcu_read_lock_sched_held - might we be in RCU-sched read-side critical section?
+ * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section?
  *
  * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an
  * RCU-sched read-side critical section.  In absence of
  * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side
  * critical section unless it can prove otherwise.  Note that disabling
  * of preemption (including disabling irqs) counts as an RCU-sched
- * read-side critical section.
+ * read-side critical section.  This is useful for debug checks in functions
+ * that required that they be called within an RCU-sched read-side
+ * critical section.
  *
  * Check debug_lockdep_rcu_enabled() to prevent false positives during boot
  * and while lockdep is disabled.
@@ -211,7 +283,11 @@
 
 extern int rcu_my_thread_group_empty(void);
 
-#define __do_rcu_dereference_check(c)					\
+/**
+ * rcu_lockdep_assert - emit lockdep splat if specified condition not met
+ * @c: condition to check
+ */
+#define rcu_lockdep_assert(c)						\
 	do {								\
 		static bool __warned;					\
 		if (debug_lockdep_rcu_enabled() && !__warned && !(c)) {	\
@@ -220,41 +296,163 @@
 		}							\
 	} while (0)
 
+#else /* #ifdef CONFIG_PROVE_RCU */
+
+#define rcu_lockdep_assert(c) do { } while (0)
+
+#endif /* #else #ifdef CONFIG_PROVE_RCU */
+
+/*
+ * Helper functions for rcu_dereference_check(), rcu_dereference_protected()
+ * and rcu_assign_pointer().  Some of these could be folded into their
+ * callers, but they are left separate in order to ease introduction of
+ * multiple flavors of pointers to match the multiple flavors of RCU
+ * (e.g., __rcu_bh, * __rcu_sched, and __srcu), should this make sense in
+ * the future.
+ */
+
+#ifdef __CHECKER__
+#define rcu_dereference_sparse(p, space) \
+	((void)(((typeof(*p) space *)p) == p))
+#else /* #ifdef __CHECKER__ */
+#define rcu_dereference_sparse(p, space)
+#endif /* #else #ifdef __CHECKER__ */
+
+#define __rcu_access_pointer(p, space) \
+	({ \
+		typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
+		rcu_dereference_sparse(p, space); \
+		((typeof(*p) __force __kernel *)(_________p1)); \
+	})
+#define __rcu_dereference_check(p, c, space) \
+	({ \
+		typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
+		rcu_lockdep_assert(c); \
+		rcu_dereference_sparse(p, space); \
+		smp_read_barrier_depends(); \
+		((typeof(*p) __force __kernel *)(_________p1)); \
+	})
+#define __rcu_dereference_protected(p, c, space) \
+	({ \
+		rcu_lockdep_assert(c); \
+		rcu_dereference_sparse(p, space); \
+		((typeof(*p) __force __kernel *)(p)); \
+	})
+
+#define __rcu_dereference_index_check(p, c) \
+	({ \
+		typeof(p) _________p1 = ACCESS_ONCE(p); \
+		rcu_lockdep_assert(c); \
+		smp_read_barrier_depends(); \
+		(_________p1); \
+	})
+#define __rcu_assign_pointer(p, v, space) \
+	({ \
+		if (!__builtin_constant_p(v) || \
+		    ((v) != NULL)) \
+			smp_wmb(); \
+		(p) = (typeof(*v) __force space *)(v); \
+	})
+
+
 /**
- * rcu_dereference_check - rcu_dereference with debug checking
+ * rcu_access_pointer() - fetch RCU pointer with no dereferencing
+ * @p: The pointer to read
+ *
+ * Return the value of the specified RCU-protected pointer, but omit the
+ * smp_read_barrier_depends() and keep the ACCESS_ONCE().  This is useful
+ * when the value of this pointer is accessed, but the pointer is not
+ * dereferenced, for example, when testing an RCU-protected pointer against
+ * NULL.  Although rcu_access_pointer() may also be used in cases where
+ * update-side locks prevent the value of the pointer from changing, you
+ * should instead use rcu_dereference_protected() for this use case.
+ */
+#define rcu_access_pointer(p) __rcu_access_pointer((p), __rcu)
+
+/**
+ * rcu_dereference_check() - rcu_dereference with debug checking
  * @p: The pointer to read, prior to dereferencing
  * @c: The conditions under which the dereference will take place
  *
  * Do an rcu_dereference(), but check that the conditions under which the
- * dereference will take place are correct.  Typically the conditions indicate
- * the various locking conditions that should be held at that point.  The check
- * should return true if the conditions are satisfied.
+ * dereference will take place are correct.  Typically the conditions
+ * indicate the various locking conditions that should be held at that
+ * point.  The check should return true if the conditions are satisfied.
+ * An implicit check for being in an RCU read-side critical section
+ * (rcu_read_lock()) is included.
  *
  * For example:
  *
- *	bar = rcu_dereference_check(foo->bar, rcu_read_lock_held() ||
- *					      lockdep_is_held(&foo->lock));
+ *	bar = rcu_dereference_check(foo->bar, lockdep_is_held(&foo->lock));
  *
  * could be used to indicate to lockdep that foo->bar may only be dereferenced
- * if either the RCU read lock is held, or that the lock required to replace
+ * if either rcu_read_lock() is held, or that the lock required to replace
  * the bar struct at foo->bar is held.
  *
  * Note that the list of conditions may also include indications of when a lock
  * need not be held, for example during initialisation or destruction of the
  * target struct:
  *
- *	bar = rcu_dereference_check(foo->bar, rcu_read_lock_held() ||
- *					      lockdep_is_held(&foo->lock) ||
+ *	bar = rcu_dereference_check(foo->bar, lockdep_is_held(&foo->lock) ||
  *					      atomic_read(&foo->usage) == 0);
+ *
+ * Inserts memory barriers on architectures that require them
+ * (currently only the Alpha), prevents the compiler from refetching
+ * (and from merging fetches), and, more importantly, documents exactly
+ * which pointers are protected by RCU and checks that the pointer is
+ * annotated as __rcu.
  */
 #define rcu_dereference_check(p, c) \
-	({ \
-		__do_rcu_dereference_check(c); \
-		rcu_dereference_raw(p); \
-	})
+	__rcu_dereference_check((p), rcu_read_lock_held() || (c), __rcu)
 
 /**
- * rcu_dereference_protected - fetch RCU pointer when updates prevented
+ * rcu_dereference_bh_check() - rcu_dereference_bh with debug checking
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
+ *
+ * This is the RCU-bh counterpart to rcu_dereference_check().
+ */
+#define rcu_dereference_bh_check(p, c) \
+	__rcu_dereference_check((p), rcu_read_lock_bh_held() || (c), __rcu)
+
+/**
+ * rcu_dereference_sched_check() - rcu_dereference_sched with debug checking
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
+ *
+ * This is the RCU-sched counterpart to rcu_dereference_check().
+ */
+#define rcu_dereference_sched_check(p, c) \
+	__rcu_dereference_check((p), rcu_read_lock_sched_held() || (c), \
+				__rcu)
+
+#define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*@@@ needed? @@@*/
+
+/**
+ * rcu_dereference_index_check() - rcu_dereference for indices with debug checking
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
+ *
+ * Similar to rcu_dereference_check(), but omits the sparse checking.
+ * This allows rcu_dereference_index_check() to be used on integers,
+ * which can then be used as array indices.  Attempting to use
+ * rcu_dereference_check() on an integer will give compiler warnings
+ * because the sparse address-space mechanism relies on dereferencing
+ * the RCU-protected pointer.  Dereferencing integers is not something
+ * that even gcc will put up with.
+ *
+ * Note that this function does not implicitly check for RCU read-side
+ * critical sections.  If this function gains lots of uses, it might
+ * make sense to provide versions for each flavor of RCU, but it does
+ * not make sense as of early 2010.
+ */
+#define rcu_dereference_index_check(p, c) \
+	__rcu_dereference_index_check((p), (c))
+
+/**
+ * rcu_dereference_protected() - fetch RCU pointer when updates prevented
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
  *
  * Return the value of the specified RCU-protected pointer, but omit
  * both the smp_read_barrier_depends() and the ACCESS_ONCE().  This
@@ -263,35 +461,61 @@
  * prevent the compiler from repeating this reference or combining it
  * with other references, so it should not be used without protection
  * of appropriate locks.
+ *
+ * This function is only for update-side use.  Using this function
+ * when protected only by rcu_read_lock() will result in infrequent
+ * but very ugly failures.
  */
 #define rcu_dereference_protected(p, c) \
-	({ \
-		__do_rcu_dereference_check(c); \
-		(p); \
-	})
-
-#else /* #ifdef CONFIG_PROVE_RCU */
-
-#define rcu_dereference_check(p, c)	rcu_dereference_raw(p)
-#define rcu_dereference_protected(p, c) (p)
-
-#endif /* #else #ifdef CONFIG_PROVE_RCU */
+	__rcu_dereference_protected((p), (c), __rcu)
 
 /**
- * rcu_access_pointer - fetch RCU pointer with no dereferencing
+ * rcu_dereference_bh_protected() - fetch RCU-bh pointer when updates prevented
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
  *
- * Return the value of the specified RCU-protected pointer, but omit the
- * smp_read_barrier_depends() and keep the ACCESS_ONCE().  This is useful
- * when the value of this pointer is accessed, but the pointer is not
- * dereferenced, for example, when testing an RCU-protected pointer against
- * NULL.  This may also be used in cases where update-side locks prevent
- * the value of the pointer from changing, but rcu_dereference_protected()
- * is a lighter-weight primitive for this use case.
+ * This is the RCU-bh counterpart to rcu_dereference_protected().
  */
-#define rcu_access_pointer(p)	ACCESS_ONCE(p)
+#define rcu_dereference_bh_protected(p, c) \
+	__rcu_dereference_protected((p), (c), __rcu)
 
 /**
- * rcu_read_lock - mark the beginning of an RCU read-side critical section.
+ * rcu_dereference_sched_protected() - fetch RCU-sched pointer when updates prevented
+ * @p: The pointer to read, prior to dereferencing
+ * @c: The conditions under which the dereference will take place
+ *
+ * This is the RCU-sched counterpart to rcu_dereference_protected().
+ */
+#define rcu_dereference_sched_protected(p, c) \
+	__rcu_dereference_protected((p), (c), __rcu)
+
+
+/**
+ * rcu_dereference() - fetch RCU-protected pointer for dereferencing
+ * @p: The pointer to read, prior to dereferencing
+ *
+ * This is a simple wrapper around rcu_dereference_check().
+ */
+#define rcu_dereference(p) rcu_dereference_check(p, 0)
+
+/**
+ * rcu_dereference_bh() - fetch an RCU-bh-protected pointer for dereferencing
+ * @p: The pointer to read, prior to dereferencing
+ *
+ * Makes rcu_dereference_check() do the dirty work.
+ */
+#define rcu_dereference_bh(p) rcu_dereference_bh_check(p, 0)
+
+/**
+ * rcu_dereference_sched() - fetch RCU-sched-protected pointer for dereferencing
+ * @p: The pointer to read, prior to dereferencing
+ *
+ * Makes rcu_dereference_check() do the dirty work.
+ */
+#define rcu_dereference_sched(p) rcu_dereference_sched_check(p, 0)
+
+/**
+ * rcu_read_lock() - mark the beginning of an RCU read-side critical section
  *
  * When synchronize_rcu() is invoked on one CPU while other CPUs
  * are within RCU read-side critical sections, then the
@@ -302,7 +526,7 @@
  * until after the all the other CPUs exit their critical sections.
  *
  * Note, however, that RCU callbacks are permitted to run concurrently
- * with RCU read-side critical sections.  One way that this can happen
+ * with new RCU read-side critical sections.  One way that this can happen
  * is via the following sequence of events: (1) CPU 0 enters an RCU
  * read-side critical section, (2) CPU 1 invokes call_rcu() to register
  * an RCU callback, (3) CPU 0 exits the RCU read-side critical section,
@@ -317,7 +541,20 @@
  * will be deferred until the outermost RCU read-side critical section
  * completes.
  *
- * It is illegal to block while in an RCU read-side critical section.
+ * You can avoid reading and understanding the next paragraph by
+ * following this rule: don't put anything in an rcu_read_lock() RCU
+ * read-side critical section that would block in a !PREEMPT kernel.
+ * But if you want the full story, read on!
+ *
+ * In non-preemptible RCU implementations (TREE_RCU and TINY_RCU), it
+ * is illegal to block while in an RCU read-side critical section.  In
+ * preemptible RCU implementations (TREE_PREEMPT_RCU and TINY_PREEMPT_RCU)
+ * in CONFIG_PREEMPT kernel builds, RCU read-side critical sections may
+ * be preempted, but explicit blocking is illegal.  Finally, in preemptible
+ * RCU implementations in real-time (CONFIG_PREEMPT_RT) kernel builds,
+ * RCU read-side critical sections may be preempted and they may also
+ * block, but only when acquiring spinlocks that are subject to priority
+ * inheritance.
  */
 static inline void rcu_read_lock(void)
 {
@@ -337,7 +574,7 @@
  */
 
 /**
- * rcu_read_unlock - marks the end of an RCU read-side critical section.
+ * rcu_read_unlock() - marks the end of an RCU read-side critical section.
  *
  * See rcu_read_lock() for more information.
  */
@@ -349,15 +586,16 @@
 }
 
 /**
- * rcu_read_lock_bh - mark the beginning of a softirq-only RCU critical section
+ * rcu_read_lock_bh() - mark the beginning of an RCU-bh critical section
  *
  * This is equivalent of rcu_read_lock(), but to be used when updates
- * are being done using call_rcu_bh(). Since call_rcu_bh() callbacks
- * consider completion of a softirq handler to be a quiescent state,
- * a process in RCU read-side critical section must be protected by
- * disabling softirqs. Read-side critical sections in interrupt context
- * can use just rcu_read_lock().
- *
+ * are being done using call_rcu_bh() or synchronize_rcu_bh(). Since
+ * both call_rcu_bh() and synchronize_rcu_bh() consider completion of a
+ * softirq handler to be a quiescent state, a process in RCU read-side
+ * critical section must be protected by disabling softirqs. Read-side
+ * critical sections in interrupt context can use just rcu_read_lock(),
+ * though this should at least be commented to avoid confusing people
+ * reading the code.
  */
 static inline void rcu_read_lock_bh(void)
 {
@@ -379,13 +617,12 @@
 }
 
 /**
- * rcu_read_lock_sched - mark the beginning of a RCU-classic critical section
+ * rcu_read_lock_sched() - mark the beginning of a RCU-sched critical section
  *
- * Should be used with either
- * - synchronize_sched()
- * or
- * - call_rcu_sched() and rcu_barrier_sched()
- * on the write-side to insure proper synchronization.
+ * This is equivalent of rcu_read_lock(), but to be used when updates
+ * are being done using call_rcu_sched() or synchronize_rcu_sched().
+ * Read-side critical sections can also be introduced by anything that
+ * disables preemption, including local_irq_disable() and friends.
  */
 static inline void rcu_read_lock_sched(void)
 {
@@ -420,54 +657,14 @@
 	preempt_enable_notrace();
 }
 
-
 /**
- * rcu_dereference_raw - fetch an RCU-protected pointer
+ * rcu_assign_pointer() - assign to RCU-protected pointer
+ * @p: pointer to assign to
+ * @v: value to assign (publish)
  *
- * The caller must be within some flavor of RCU read-side critical
- * section, or must be otherwise preventing the pointer from changing,
- * for example, by holding an appropriate lock.  This pointer may later
- * be safely dereferenced.  It is the caller's responsibility to have
- * done the right thing, as this primitive does no checking of any kind.
- *
- * Inserts memory barriers on architectures that require them
- * (currently only the Alpha), and, more importantly, documents
- * exactly which pointers are protected by RCU.
- */
-#define rcu_dereference_raw(p)	({ \
-				typeof(p) _________p1 = ACCESS_ONCE(p); \
-				smp_read_barrier_depends(); \
-				(_________p1); \
-				})
-
-/**
- * rcu_dereference - fetch an RCU-protected pointer, checking for RCU
- *
- * Makes rcu_dereference_check() do the dirty work.
- */
-#define rcu_dereference(p) \
-	rcu_dereference_check(p, rcu_read_lock_held())
-
-/**
- * rcu_dereference_bh - fetch an RCU-protected pointer, checking for RCU-bh
- *
- * Makes rcu_dereference_check() do the dirty work.
- */
-#define rcu_dereference_bh(p) \
-		rcu_dereference_check(p, rcu_read_lock_bh_held())
-
-/**
- * rcu_dereference_sched - fetch RCU-protected pointer, checking for RCU-sched
- *
- * Makes rcu_dereference_check() do the dirty work.
- */
-#define rcu_dereference_sched(p) \
-		rcu_dereference_check(p, rcu_read_lock_sched_held())
-
-/**
- * rcu_assign_pointer - assign (publicize) a pointer to a newly
- * initialized structure that will be dereferenced by RCU read-side
- * critical sections.  Returns the value assigned.
+ * Assigns the specified value to the specified RCU-protected
+ * pointer, ensuring that any concurrent RCU readers will see
+ * any prior initialization.  Returns the value assigned.
  *
  * Inserts memory barriers on architectures that require them
  * (pretty much all of them other than x86), and also prevents
@@ -476,14 +673,17 @@
  * call documents which pointers will be dereferenced by RCU read-side
  * code.
  */
-
 #define rcu_assign_pointer(p, v) \
-	({ \
-		if (!__builtin_constant_p(v) || \
-		    ((v) != NULL)) \
-			smp_wmb(); \
-		(p) = (v); \
-	})
+	__rcu_assign_pointer((p), (v), __rcu)
+
+/**
+ * RCU_INIT_POINTER() - initialize an RCU protected pointer
+ *
+ * Initialize an RCU-protected pointer in such a way to avoid RCU-lockdep
+ * splats.
+ */
+#define RCU_INIT_POINTER(p, v) \
+		p = (typeof(*v) __force __rcu *)(v)
 
 /* Infrastructure to implement the synchronize_() primitives. */
 
@@ -494,26 +694,37 @@
 
 extern void wakeme_after_rcu(struct rcu_head  *head);
 
+#ifdef CONFIG_PREEMPT_RCU
+
 /**
- * call_rcu - Queue an RCU callback for invocation after a grace period.
+ * call_rcu() - Queue an RCU callback for invocation after a grace period.
  * @head: structure to be used for queueing the RCU updates.
- * @func: actual update function to be invoked after the grace period
+ * @func: actual callback function to be invoked after the grace period
  *
- * The update function will be invoked some time after a full grace
- * period elapses, in other words after all currently executing RCU
- * read-side critical sections have completed.  RCU read-side critical
+ * The callback function will be invoked some time after a full grace
+ * period elapses, in other words after all pre-existing RCU read-side
+ * critical sections have completed.  However, the callback function
+ * might well execute concurrently with RCU read-side critical sections
+ * that started after call_rcu() was invoked.  RCU read-side critical
  * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
  * and may be nested.
  */
 extern void call_rcu(struct rcu_head *head,
 			      void (*func)(struct rcu_head *head));
 
+#else /* #ifdef CONFIG_PREEMPT_RCU */
+
+/* In classic RCU, call_rcu() is just call_rcu_sched(). */
+#define	call_rcu	call_rcu_sched
+
+#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
+
 /**
- * call_rcu_bh - Queue an RCU for invocation after a quicker grace period.
+ * call_rcu_bh() - Queue an RCU for invocation after a quicker grace period.
  * @head: structure to be used for queueing the RCU updates.
- * @func: actual update function to be invoked after the grace period
+ * @func: actual callback function to be invoked after the grace period
  *
- * The update function will be invoked some time after a full grace
+ * The callback function will be invoked some time after a full grace
  * period elapses, in other words after all currently executing RCU
  * read-side critical sections have completed. call_rcu_bh() assumes
  * that the read-side critical sections end on completion of a softirq
@@ -566,37 +777,4 @@
 }
 #endif	/* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
 
-#ifndef CONFIG_PROVE_RCU
-#define __do_rcu_dereference_check(c) do { } while (0)
-#endif /* #ifdef CONFIG_PROVE_RCU */
-
-#define __rcu_dereference_index_check(p, c) \
-	({ \
-		typeof(p) _________p1 = ACCESS_ONCE(p); \
-		__do_rcu_dereference_check(c); \
-		smp_read_barrier_depends(); \
-		(_________p1); \
-	})
-
-/**
- * rcu_dereference_index_check() - rcu_dereference for indices with debug checking
- * @p: The pointer to read, prior to dereferencing
- * @c: The conditions under which the dereference will take place
- *
- * Similar to rcu_dereference_check(), but omits the sparse checking.
- * This allows rcu_dereference_index_check() to be used on integers,
- * which can then be used as array indices.  Attempting to use
- * rcu_dereference_check() on an integer will give compiler warnings
- * because the sparse address-space mechanism relies on dereferencing
- * the RCU-protected pointer.  Dereferencing integers is not something
- * that even gcc will put up with.
- *
- * Note that this function does not implicitly check for RCU read-side
- * critical sections.  If this function gains lots of uses, it might
- * make sense to provide versions for each flavor of RCU, but it does
- * not make sense as of early 2010.
- */
-#define rcu_dereference_index_check(p, c) \
-	__rcu_dereference_index_check((p), (c))
-
 #endif /* __LINUX_RCUPDATE_H */
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index e2e8931..13877cb 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -27,27 +27,71 @@
 
 #include <linux/cache.h>
 
-void rcu_sched_qs(int cpu);
-void rcu_bh_qs(int cpu);
-static inline void rcu_note_context_switch(int cpu)
+#define rcu_init_sched()	do { } while (0)
+
+#ifdef CONFIG_TINY_RCU
+
+static inline void synchronize_rcu_expedited(void)
 {
-	rcu_sched_qs(cpu);
+	synchronize_sched();	/* Only one CPU, so pretty fast anyway!!! */
 }
 
-#define __rcu_read_lock()	preempt_disable()
-#define __rcu_read_unlock()	preempt_enable()
-#define __rcu_read_lock_bh()	local_bh_disable()
-#define __rcu_read_unlock_bh()	local_bh_enable()
-#define call_rcu_sched		call_rcu
+static inline void rcu_barrier(void)
+{
+	rcu_barrier_sched();  /* Only one CPU, so only one list of callbacks! */
+}
 
-#define rcu_init_sched()	do { } while (0)
-extern void rcu_check_callbacks(int cpu, int user);
+#else /* #ifdef CONFIG_TINY_RCU */
+
+void rcu_barrier(void);
+void synchronize_rcu_expedited(void);
+
+#endif /* #else #ifdef CONFIG_TINY_RCU */
+
+static inline void synchronize_rcu_bh(void)
+{
+	synchronize_sched();
+}
+
+static inline void synchronize_rcu_bh_expedited(void)
+{
+	synchronize_sched();
+}
+
+#ifdef CONFIG_TINY_RCU
+
+static inline void rcu_preempt_note_context_switch(void)
+{
+}
+
+static inline void exit_rcu(void)
+{
+}
 
 static inline int rcu_needs_cpu(int cpu)
 {
 	return 0;
 }
 
+#else /* #ifdef CONFIG_TINY_RCU */
+
+void rcu_preempt_note_context_switch(void);
+extern void exit_rcu(void);
+int rcu_preempt_needs_cpu(void);
+
+static inline int rcu_needs_cpu(int cpu)
+{
+	return rcu_preempt_needs_cpu();
+}
+
+#endif /* #else #ifdef CONFIG_TINY_RCU */
+
+static inline void rcu_note_context_switch(int cpu)
+{
+	rcu_sched_qs(cpu);
+	rcu_preempt_note_context_switch();
+}
+
 /*
  * Return the number of grace periods.
  */
@@ -76,54 +120,8 @@
 {
 }
 
-extern void synchronize_sched(void);
-
-static inline void synchronize_rcu(void)
+static inline void rcu_cpu_stall_reset(void)
 {
-	synchronize_sched();
-}
-
-static inline void synchronize_rcu_bh(void)
-{
-	synchronize_sched();
-}
-
-static inline void synchronize_rcu_expedited(void)
-{
-	synchronize_sched();
-}
-
-static inline void synchronize_rcu_bh_expedited(void)
-{
-	synchronize_sched();
-}
-
-struct notifier_block;
-
-#ifdef CONFIG_NO_HZ
-
-extern void rcu_enter_nohz(void);
-extern void rcu_exit_nohz(void);
-
-#else /* #ifdef CONFIG_NO_HZ */
-
-static inline void rcu_enter_nohz(void)
-{
-}
-
-static inline void rcu_exit_nohz(void)
-{
-}
-
-#endif /* #else #ifdef CONFIG_NO_HZ */
-
-static inline void exit_rcu(void)
-{
-}
-
-static inline int rcu_preempt_depth(void)
-{
-	return 0;
 }
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index c0ed1c0..95518e6 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -30,64 +30,23 @@
 #ifndef __LINUX_RCUTREE_H
 #define __LINUX_RCUTREE_H
 
-struct notifier_block;
-
-extern void rcu_sched_qs(int cpu);
-extern void rcu_bh_qs(int cpu);
 extern void rcu_note_context_switch(int cpu);
 extern int rcu_needs_cpu(int cpu);
+extern void rcu_cpu_stall_reset(void);
 
 #ifdef CONFIG_TREE_PREEMPT_RCU
 
-extern void __rcu_read_lock(void);
-extern void __rcu_read_unlock(void);
-extern void synchronize_rcu(void);
 extern void exit_rcu(void);
 
-/*
- * Defined as macro as it is a very low level header
- * included from areas that don't even know about current
- */
-#define rcu_preempt_depth() (current->rcu_read_lock_nesting)
-
 #else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
 
-static inline void __rcu_read_lock(void)
-{
-	preempt_disable();
-}
-
-static inline void __rcu_read_unlock(void)
-{
-	preempt_enable();
-}
-
-#define synchronize_rcu synchronize_sched
-
 static inline void exit_rcu(void)
 {
 }
 
-static inline int rcu_preempt_depth(void)
-{
-	return 0;
-}
-
 #endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
 
-static inline void __rcu_read_lock_bh(void)
-{
-	local_bh_disable();
-}
-static inline void __rcu_read_unlock_bh(void)
-{
-	local_bh_enable();
-}
-
-extern void call_rcu_sched(struct rcu_head *head,
-			   void (*func)(struct rcu_head *rcu));
 extern void synchronize_rcu_bh(void);
-extern void synchronize_sched(void);
 extern void synchronize_rcu_expedited(void);
 
 static inline void synchronize_rcu_bh_expedited(void)
@@ -95,7 +54,7 @@
 	synchronize_sched_expedited();
 }
 
-extern void rcu_check_callbacks(int cpu, int user);
+extern void rcu_barrier(void);
 
 extern long rcu_batches_completed(void);
 extern long rcu_batches_completed_bh(void);
@@ -104,18 +63,6 @@
 extern void rcu_bh_force_quiescent_state(void);
 extern void rcu_sched_force_quiescent_state(void);
 
-#ifdef CONFIG_NO_HZ
-void rcu_enter_nohz(void);
-void rcu_exit_nohz(void);
-#else /* CONFIG_NO_HZ */
-static inline void rcu_enter_nohz(void)
-{
-}
-static inline void rcu_exit_nohz(void)
-{
-}
-#endif /* CONFIG_NO_HZ */
-
 /* A context switch is a grace period for RCU-sched and RCU-bh. */
 static inline int rcu_blocking_is_gp(void)
 {
diff --git a/include/linux/rds.h b/include/linux/rds.h
index 24bce3d..9195095 100644
--- a/include/linux/rds.h
+++ b/include/linux/rds.h
@@ -36,15 +36,6 @@
 
 #include <linux/types.h>
 
-/* These sparse annotated types shouldn't be in any user
- * visible header file. We should clean this up rather
- * than kludging around them. */
-#ifndef __KERNEL__
-#define __be16	u_int16_t
-#define __be32	u_int32_t
-#define __be64	u_int64_t
-#endif
-
 #define RDS_IB_ABI_VERSION		0x301
 
 /*
@@ -82,6 +73,10 @@
 #define RDS_CMSG_RDMA_MAP		3
 #define RDS_CMSG_RDMA_STATUS		4
 #define RDS_CMSG_CONG_UPDATE		5
+#define RDS_CMSG_ATOMIC_FADD		6
+#define RDS_CMSG_ATOMIC_CSWP		7
+#define RDS_CMSG_MASKED_ATOMIC_FADD	8
+#define RDS_CMSG_MASKED_ATOMIC_CSWP	9
 
 #define RDS_INFO_FIRST			10000
 #define RDS_INFO_COUNTERS		10000
@@ -98,9 +93,9 @@
 #define RDS_INFO_LAST			10010
 
 struct rds_info_counter {
-	u_int8_t	name[32];
-	u_int64_t	value;
-} __packed;
+	uint8_t	name[32];
+	uint64_t	value;
+} __attribute__((packed));
 
 #define RDS_INFO_CONNECTION_FLAG_SENDING	0x01
 #define RDS_INFO_CONNECTION_FLAG_CONNECTING	0x02
@@ -109,56 +104,48 @@
 #define TRANSNAMSIZ	16
 
 struct rds_info_connection {
-	u_int64_t	next_tx_seq;
-	u_int64_t	next_rx_seq;
+	uint64_t	next_tx_seq;
+	uint64_t	next_rx_seq;
 	__be32		laddr;
 	__be32		faddr;
-	u_int8_t	transport[TRANSNAMSIZ];		/* null term ascii */
-	u_int8_t	flags;
-} __packed;
-
-struct rds_info_flow {
-	__be32		laddr;
-	__be32		faddr;
-	u_int32_t	bytes;
-	__be16		lport;
-	__be16		fport;
-} __packed;
+	uint8_t	transport[TRANSNAMSIZ];		/* null term ascii */
+	uint8_t	flags;
+} __attribute__((packed));
 
 #define RDS_INFO_MESSAGE_FLAG_ACK               0x01
 #define RDS_INFO_MESSAGE_FLAG_FAST_ACK          0x02
 
 struct rds_info_message {
-	u_int64_t	seq;
-	u_int32_t	len;
+	uint64_t	seq;
+	uint32_t	len;
 	__be32		laddr;
 	__be32		faddr;
 	__be16		lport;
 	__be16		fport;
-	u_int8_t	flags;
-} __packed;
+	uint8_t	flags;
+} __attribute__((packed));
 
 struct rds_info_socket {
-	u_int32_t	sndbuf;
+	uint32_t	sndbuf;
 	__be32		bound_addr;
 	__be32		connected_addr;
 	__be16		bound_port;
 	__be16		connected_port;
-	u_int32_t	rcvbuf;
-	u_int64_t	inum;
-} __packed;
+	uint32_t	rcvbuf;
+	uint64_t	inum;
+} __attribute__((packed));
 
 struct rds_info_tcp_socket {
 	__be32          local_addr;
 	__be16          local_port;
 	__be32          peer_addr;
 	__be16          peer_port;
-	u_int64_t       hdr_rem;
-	u_int64_t       data_rem;
-	u_int32_t       last_sent_nxt;
-	u_int32_t       last_expected_una;
-	u_int32_t       last_seen_una;
-} __packed;
+	uint64_t       hdr_rem;
+	uint64_t       data_rem;
+	uint32_t       last_sent_nxt;
+	uint32_t       last_expected_una;
+	uint32_t       last_seen_una;
+} __attribute__((packed));
 
 #define RDS_IB_GID_LEN	16
 struct rds_info_rdma_connection {
@@ -212,42 +199,69 @@
  * (so that the application does not have to worry about
  * alignment).
  */
-typedef u_int64_t	rds_rdma_cookie_t;
+typedef uint64_t	rds_rdma_cookie_t;
 
 struct rds_iovec {
-	u_int64_t	addr;
-	u_int64_t	bytes;
+	uint64_t	addr;
+	uint64_t	bytes;
 };
 
 struct rds_get_mr_args {
 	struct rds_iovec vec;
-	u_int64_t	cookie_addr;
+	uint64_t	cookie_addr;
 	uint64_t	flags;
 };
 
 struct rds_get_mr_for_dest_args {
 	struct sockaddr_storage	dest_addr;
 	struct rds_iovec 	vec;
-	u_int64_t		cookie_addr;
+	uint64_t		cookie_addr;
 	uint64_t		flags;
 };
 
 struct rds_free_mr_args {
 	rds_rdma_cookie_t cookie;
-	u_int64_t	flags;
+	uint64_t	flags;
 };
 
 struct rds_rdma_args {
 	rds_rdma_cookie_t cookie;
 	struct rds_iovec remote_vec;
-	u_int64_t	local_vec_addr;
-	u_int64_t	nr_local;
-	u_int64_t	flags;
-	u_int64_t	user_token;
+	uint64_t	local_vec_addr;
+	uint64_t	nr_local;
+	uint64_t	flags;
+	uint64_t	user_token;
+};
+
+struct rds_atomic_args {
+	rds_rdma_cookie_t cookie;
+	uint64_t 	local_addr;
+	uint64_t 	remote_addr;
+	union {
+		struct {
+			uint64_t	compare;
+			uint64_t	swap;
+		} cswp;
+		struct {
+			uint64_t	add;
+		} fadd;
+		struct {
+			uint64_t	compare;
+			uint64_t	swap;
+			uint64_t	compare_mask;
+			uint64_t	swap_mask;
+		} m_cswp;
+		struct {
+			uint64_t	add;
+			uint64_t	nocarry_mask;
+		} m_fadd;
+	};
+	uint64_t	flags;
+	uint64_t	user_token;
 };
 
 struct rds_rdma_notify {
-	u_int64_t	user_token;
+	uint64_t	user_token;
 	int32_t		status;
 };
 
@@ -266,5 +280,6 @@
 #define RDS_RDMA_USE_ONCE	0x0008	/* free MR after use */
 #define RDS_RDMA_DONTWAIT	0x0010	/* Don't wait in SET_BARRIER */
 #define RDS_RDMA_NOTIFY_ME	0x0020	/* Notify when operation completes */
+#define RDS_RDMA_SILENT		0x0040	/* Do not interrupt remote */
 
 #endif /* IB_RDS_H */
diff --git a/include/linux/resume-trace.h b/include/linux/resume-trace.h
index bc8c388..f31db23 100644
--- a/include/linux/resume-trace.h
+++ b/include/linux/resume-trace.h
@@ -3,6 +3,7 @@
 
 #ifdef CONFIG_PM_TRACE
 #include <asm/resume-trace.h>
+#include <linux/types.h>
 
 extern int pm_trace_enabled;
 
@@ -14,6 +15,7 @@
 struct device;
 extern void set_trace_device(struct device *);
 extern void generate_resume_trace(const void *tracedata, unsigned int user);
+extern int show_trace_dev_match(char *buf, size_t size);
 
 #define TRACE_DEVICE(dev) do { \
 	if (pm_trace_enabled) \
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 58d4449..d42f2744 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -6,6 +6,7 @@
 #include <linux/if_link.h>
 #include <linux/if_addr.h>
 #include <linux/neighbour.h>
+#include <linux/netdevice.h>
 
 /* rtnetlink families. Values up to 127 are reserved for real address
  * families, values above 128 may be used arbitrarily.
@@ -749,6 +750,35 @@
 extern int lockdep_rtnl_is_held(void);
 #endif /* #ifdef CONFIG_PROVE_LOCKING */
 
+/**
+ * rcu_dereference_rtnl - rcu_dereference with debug checking
+ * @p: The pointer to read, prior to dereferencing
+ *
+ * Do an rcu_dereference(p), but check caller either holds rcu_read_lock()
+ * or RTNL. Note : Please prefer rtnl_dereference() or rcu_dereference()
+ */
+#define rcu_dereference_rtnl(p)					\
+	rcu_dereference_check(p, rcu_read_lock_held() ||	\
+				 lockdep_rtnl_is_held())
+
+/**
+ * rtnl_dereference - fetch RCU pointer when updates are prevented by RTNL
+ * @p: The pointer to read, prior to dereferencing
+ *
+ * Return the value of the specified RCU-protected pointer, but omit
+ * both the smp_read_barrier_depends() and the ACCESS_ONCE(), because
+ * caller holds RTNL.
+ */
+#define rtnl_dereference(p)					\
+	rcu_dereference_protected(p, lockdep_rtnl_is_held())
+
+static inline struct netdev_queue *dev_ingress_queue(struct net_device *dev)
+{
+	return rtnl_dereference(dev->ingress_queue);
+}
+
+extern struct netdev_queue *dev_ingress_queue_create(struct net_device *dev);
+
 extern void rtnetlink_init(void);
 extern void __rtnl_unlock(void);
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 1e2a6db..56154bb 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -336,6 +336,9 @@
 extern int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
 					 void __user *buffer,
 					 size_t *lenp, loff_t *ppos);
+#else
+/* Avoid need for ifdefs elsewhere in the code */
+enum { sysctl_hung_task_timeout_secs = 0 };
 #endif
 
 /* Attach to any functions which should be ignored in wchan output. */
@@ -875,6 +878,7 @@
 	SD_LV_NONE = 0,
 	SD_LV_SIBLING,
 	SD_LV_MC,
+	SD_LV_BOOK,
 	SD_LV_CPU,
 	SD_LV_NODE,
 	SD_LV_ALLNODES,
@@ -1160,6 +1164,13 @@
 
 struct rcu_node;
 
+enum perf_event_task_context {
+	perf_invalid_context = -1,
+	perf_hw_context = 0,
+	perf_sw_context,
+	perf_nr_task_contexts,
+};
+
 struct task_struct {
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
 	void *stack;
@@ -1202,11 +1213,13 @@
 	unsigned int policy;
 	cpumask_t cpus_allowed;
 
-#ifdef CONFIG_TREE_PREEMPT_RCU
+#ifdef CONFIG_PREEMPT_RCU
 	int rcu_read_lock_nesting;
 	char rcu_read_unlock_special;
-	struct rcu_node *rcu_blocked_node;
 	struct list_head rcu_node_entry;
+#endif /* #ifdef CONFIG_PREEMPT_RCU */
+#ifdef CONFIG_TREE_PREEMPT_RCU
+	struct rcu_node *rcu_blocked_node;
 #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
 
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
@@ -1288,9 +1301,9 @@
 	struct list_head cpu_timers[3];
 
 /* process credentials */
-	const struct cred *real_cred;	/* objective and real subjective task
+	const struct cred __rcu *real_cred; /* objective and real subjective task
 					 * credentials (COW) */
-	const struct cred *cred;	/* effective (overridable) subjective task
+	const struct cred __rcu *cred;	/* effective (overridable) subjective task
 					 * credentials (COW) */
 	struct mutex cred_guard_mutex;	/* guard against foreign influences on
 					 * credential calculations
@@ -1418,7 +1431,7 @@
 #endif
 #ifdef CONFIG_CGROUPS
 	/* Control Group info protected by css_set_lock */
-	struct css_set *cgroups;
+	struct css_set __rcu *cgroups;
 	/* cg_list protected by css_set_lock and tsk->alloc_lock */
 	struct list_head cg_list;
 #endif
@@ -1431,7 +1444,7 @@
 	struct futex_pi_state *pi_state_cache;
 #endif
 #ifdef CONFIG_PERF_EVENTS
-	struct perf_event_context *perf_event_ctxp;
+	struct perf_event_context *perf_event_ctxp[perf_nr_task_contexts];
 	struct mutex perf_event_mutex;
 	struct list_head perf_event_list;
 #endif
@@ -1681,8 +1694,7 @@
 /*
  * Per process flags
  */
-#define PF_ALIGNWARN	0x00000001	/* Print alignment warning msgs */
-					/* Not implemented yet, only for 486*/
+#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 */
@@ -1740,7 +1752,7 @@
 #define tsk_used_math(p) ((p)->flags & PF_USED_MATH)
 #define used_math() tsk_used_math(current)
 
-#ifdef CONFIG_TREE_PREEMPT_RCU
+#ifdef CONFIG_PREEMPT_RCU
 
 #define RCU_READ_UNLOCK_BLOCKED (1 << 0) /* blocked while in RCU read-side. */
 #define RCU_READ_UNLOCK_NEED_QS (1 << 1) /* RCU core needs CPU response. */
@@ -1749,7 +1761,9 @@
 {
 	p->rcu_read_lock_nesting = 0;
 	p->rcu_read_unlock_special = 0;
+#ifdef CONFIG_TREE_PREEMPT_RCU
 	p->rcu_blocked_node = NULL;
+#endif
 	INIT_LIST_HEAD(&p->rcu_node_entry);
 }
 
@@ -1826,6 +1840,19 @@
 extern void sched_clock_idle_wakeup_event(u64 delta_ns);
 #endif
 
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+/*
+ * An i/f to runtime opt-in for irq time accounting based off of sched_clock.
+ * The reason for this explicit opt-in is not to have perf penalty with
+ * slow sched_clocks.
+ */
+extern void enable_sched_clock_irqtime(void);
+extern void disable_sched_clock_irqtime(void);
+#else
+static inline void enable_sched_clock_irqtime(void) {}
+static inline void disable_sched_clock_irqtime(void) {}
+#endif
+
 extern unsigned long long
 task_sched_runtime(struct task_struct *task);
 extern unsigned long long thread_group_sched_runtime(struct task_struct *task);
@@ -2367,9 +2394,9 @@
 
 extern int __cond_resched_softirq(void);
 
-#define cond_resched_softirq() ({				\
-	__might_sleep(__FILE__, __LINE__, SOFTIRQ_OFFSET);	\
-	__cond_resched_softirq();				\
+#define cond_resched_softirq() ({					\
+	__might_sleep(__FILE__, __LINE__, SOFTIRQ_DISABLE_OFFSET);	\
+	__cond_resched_softirq();					\
 })
 
 /*
diff --git a/include/linux/security.h b/include/linux/security.h
index a22219a..b8246a8 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -74,7 +74,7 @@
 extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags);
 extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
 			  unsigned long arg4, unsigned long arg5);
-extern int cap_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp);
+extern int cap_task_setscheduler(struct task_struct *p);
 extern int cap_task_setioprio(struct task_struct *p, int ioprio);
 extern int cap_task_setnice(struct task_struct *p, int nice);
 extern int cap_syslog(int type, bool from_file);
@@ -959,6 +959,12 @@
  *	Sets the new child socket's sid to the openreq sid.
  * @inet_conn_established:
  *	Sets the connection's peersid to the secmark on skb.
+ * @secmark_relabel_packet:
+ *	check if the process should be allowed to relabel packets to the given secid
+ * @security_secmark_refcount_inc
+ *	tells the LSM to increment the number of secmark labeling rules loaded
+ * @security_secmark_refcount_dec
+ *	tells the LSM to decrement the number of secmark labeling rules loaded
  * @req_classify_flow:
  *	Sets the flow's sid to the openreq sid.
  * @tun_dev_create:
@@ -1279,9 +1285,13 @@
  *	Return 0 if permission is granted.
  *
  * @secid_to_secctx:
- *	Convert secid to security context.
+ *	Convert secid to security context.  If secdata is NULL the length of
+ *	the result will be returned in seclen, but no secdata will be returned.
+ *	This does mean that the length could change between calls to check the
+ *	length and the next call which actually allocates and returns the secdata.
  *	@secid contains the security ID.
  *	@secdata contains the pointer that stores the converted security context.
+ *	@seclen pointer which contains the length of the data
  * @secctx_to_secid:
  *	Convert security context to secid.
  *	@secid contains the pointer to the generated security ID.
@@ -1501,8 +1511,7 @@
 	int (*task_getioprio) (struct task_struct *p);
 	int (*task_setrlimit) (struct task_struct *p, unsigned int resource,
 			struct rlimit *new_rlim);
-	int (*task_setscheduler) (struct task_struct *p, int policy,
-				  struct sched_param *lp);
+	int (*task_setscheduler) (struct task_struct *p);
 	int (*task_getscheduler) (struct task_struct *p);
 	int (*task_movememory) (struct task_struct *p);
 	int (*task_kill) (struct task_struct *p,
@@ -1594,6 +1603,9 @@
 				  struct request_sock *req);
 	void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req);
 	void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb);
+	int (*secmark_relabel_packet) (u32 secid);
+	void (*secmark_refcount_inc) (void);
+	void (*secmark_refcount_dec) (void);
 	void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
 	int (*tun_dev_create)(void);
 	void (*tun_dev_post_create)(struct sock *sk);
@@ -1752,8 +1764,7 @@
 int security_task_getioprio(struct task_struct *p);
 int security_task_setrlimit(struct task_struct *p, unsigned int resource,
 		struct rlimit *new_rlim);
-int security_task_setscheduler(struct task_struct *p,
-				int policy, struct sched_param *lp);
+int security_task_setscheduler(struct task_struct *p);
 int security_task_getscheduler(struct task_struct *p);
 int security_task_movememory(struct task_struct *p);
 int security_task_kill(struct task_struct *p, struct siginfo *info,
@@ -2320,11 +2331,9 @@
 	return 0;
 }
 
-static inline int security_task_setscheduler(struct task_struct *p,
-					     int policy,
-					     struct sched_param *lp)
+static inline int security_task_setscheduler(struct task_struct *p)
 {
-	return cap_task_setscheduler(p, policy, lp);
+	return cap_task_setscheduler(p);
 }
 
 static inline int security_task_getscheduler(struct task_struct *p)
@@ -2551,6 +2560,9 @@
 			const struct request_sock *req);
 void security_inet_conn_established(struct sock *sk,
 			struct sk_buff *skb);
+int security_secmark_relabel_packet(u32 secid);
+void security_secmark_refcount_inc(void);
+void security_secmark_refcount_dec(void);
 int security_tun_dev_create(void);
 void security_tun_dev_post_create(struct sock *sk);
 int security_tun_dev_attach(struct sock *sk);
@@ -2705,6 +2717,19 @@
 {
 }
 
+static inline int security_secmark_relabel_packet(u32 secid)
+{
+	return 0;
+}
+
+static inline void security_secmark_refcount_inc(void)
+{
+}
+
+static inline void security_secmark_refcount_dec(void)
+{
+}
+
 static inline int security_tun_dev_create(void)
 {
 	return 0;
diff --git a/include/linux/selection.h b/include/linux/selection.h
index 8cdaa11..85193aa 100644
--- a/include/linux/selection.h
+++ b/include/linux/selection.h
@@ -39,5 +39,6 @@
 
 extern u16 vcs_scr_readw(struct vc_data *vc, const u16 *org);
 extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org);
+extern void vcs_scr_updated(struct vc_data *vc);
 
 #endif
diff --git a/include/linux/selinux.h b/include/linux/selinux.h
index 82e0f26..44f4596 100644
--- a/include/linux/selinux.h
+++ b/include/linux/selinux.h
@@ -21,74 +21,11 @@
 #ifdef CONFIG_SECURITY_SELINUX
 
 /**
- *     selinux_string_to_sid - map a security context string to a security ID
- *     @str: the security context string to be mapped
- *     @sid: ID value returned via this.
- *
- *     Returns 0 if successful, with the SID stored in sid.  A value
- *     of zero for sid indicates no SID could be determined (but no error
- *     occurred).
- */
-int selinux_string_to_sid(char *str, u32 *sid);
-
-/**
- *     selinux_secmark_relabel_packet_permission - secmark permission check
- *     @sid: SECMARK ID value to be applied to network packet
- *
- *     Returns 0 if the current task is allowed to set the SECMARK label of
- *     packets with the supplied security ID.  Note that it is implicit that
- *     the packet is always being relabeled from the default unlabeled value,
- *     and that the access control decision is made in the AVC.
- */
-int selinux_secmark_relabel_packet_permission(u32 sid);
-
-/**
- *     selinux_secmark_refcount_inc - increments the secmark use counter
- *
- *     SELinux keeps track of the current SECMARK targets in use so it knows
- *     when to apply SECMARK label access checks to network packets.  This
- *     function incements this reference count to indicate that a new SECMARK
- *     target has been configured.
- */
-void selinux_secmark_refcount_inc(void);
-
-/**
- *     selinux_secmark_refcount_dec - decrements the secmark use counter
- *
- *     SELinux keeps track of the current SECMARK targets in use so it knows
- *     when to apply SECMARK label access checks to network packets.  This
- *     function decements this reference count to indicate that one of the
- *     existing SECMARK targets has been removed/flushed.
- */
-void selinux_secmark_refcount_dec(void);
-
-/**
  * selinux_is_enabled - is SELinux enabled?
  */
 bool selinux_is_enabled(void);
 #else
 
-static inline int selinux_string_to_sid(const char *str, u32 *sid)
-{
-       *sid = 0;
-       return 0;
-}
-
-static inline int selinux_secmark_relabel_packet_permission(u32 sid)
-{
-	return 0;
-}
-
-static inline void selinux_secmark_refcount_inc(void)
-{
-	return;
-}
-
-static inline void selinux_secmark_refcount_dec(void)
-{
-	return;
-}
-
 static inline bool selinux_is_enabled(void)
 {
 	return false;
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 7638dea..97f5b45 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -35,6 +35,8 @@
 	void		(*set_termios)(struct uart_port *,
 			               struct ktermios *new,
 			               struct ktermios *old);
+	void		(*pm)(struct uart_port *, unsigned int state,
+			      unsigned old);
 };
 
 /*
@@ -76,5 +78,11 @@
 extern int setup_early_serial8250_console(char *cmdline);
 extern void serial8250_do_set_termios(struct uart_port *port,
 		struct ktermios *termios, struct ktermios *old);
+extern void serial8250_do_pm(struct uart_port *port, unsigned int state,
+			     unsigned int oldstate);
+
+extern void serial8250_set_isa_configurator(void (*v)
+					(int port, struct uart_port *up,
+						unsigned short *capabilities));
 
 #endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 563e234..99e5994 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -289,6 +289,8 @@
 	void			(*set_termios)(struct uart_port *,
 				               struct ktermios *new,
 				               struct ktermios *old);
+	void			(*pm)(struct uart_port *, unsigned int state,
+				      unsigned int old);
 	unsigned int		irq;			/* irq number */
 	unsigned long		irqflags;		/* irq flags  */
 	unsigned int		uartclk;		/* base uart clock */
@@ -411,6 +413,14 @@
 				unsigned int max);
 unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud);
 
+/* Base timer interval for polling */
+static inline int uart_poll_timeout(struct uart_port *port)
+{
+	int timeout = port->timeout;
+
+	return timeout > 6 ? (timeout / 2 - 2) : 1;
+}
+
 /*
  * Console helpers.
  */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 77eb60d..e6ba898 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -129,8 +129,13 @@
 
 struct skb_frag_struct {
 	struct page *page;
+#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
 	__u32 page_offset;
 	__u32 size;
+#else
+	__u16 page_offset;
+	__u16 size;
+#endif
 };
 
 #define HAVE_HW_TIME_STAMP
@@ -163,26 +168,19 @@
 	ktime_t	syststamp;
 };
 
-/**
- * struct skb_shared_tx - instructions for time stamping of outgoing packets
- * @hardware:		generate hardware time stamp
- * @software:		generate software time stamp
- * @in_progress:	device driver is going to provide
- *			hardware time stamp
- * @prevent_sk_orphan:	make sk reference available on driver level
- * @flags:		all shared_tx flags
- *
- * These flags are attached to packets as part of the
- * &skb_shared_info. Use skb_tx() to get a pointer.
- */
-union skb_shared_tx {
-	struct {
-		__u8	hardware:1,
-			software:1,
-			in_progress:1,
-			prevent_sk_orphan:1;
-	};
-	__u8 flags;
+/* Definitions for tx_flags in struct skb_shared_info */
+enum {
+	/* generate hardware time stamp */
+	SKBTX_HW_TSTAMP = 1 << 0,
+
+	/* generate software time stamp */
+	SKBTX_SW_TSTAMP = 1 << 1,
+
+	/* device driver is going to provide hardware time stamp */
+	SKBTX_IN_PROGRESS = 1 << 2,
+
+	/* ensure the originating sk reference is available on driver level */
+	SKBTX_DRV_NEEDS_SK_REF = 1 << 3,
 };
 
 /* This data is invariant across clones and lives at
@@ -195,7 +193,7 @@
 	unsigned short	gso_segs;
 	unsigned short  gso_type;
 	__be32          ip6_frag_id;
-	union skb_shared_tx tx_flags;
+	__u8		tx_flags;
 	struct sk_buff	*frag_list;
 	struct skb_shared_hwtstamps hwtstamps;
 
@@ -462,19 +460,7 @@
 	skb->_skb_refdst = (unsigned long)dst;
 }
 
-/**
- * skb_dst_set_noref - sets skb dst, without a reference
- * @skb: buffer
- * @dst: dst entry
- *
- * Sets skb dst, assuming a reference was not taken on dst
- * skb_dst_drop() should not dst_release() this dst
- */
-static inline void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst)
-{
-	WARN_ON(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
-	skb->_skb_refdst = (unsigned long)dst | SKB_DST_NOREF;
-}
+extern void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst);
 
 /**
  * skb_dst_is_noref - Test if skb dst isnt refcounted
@@ -498,13 +484,13 @@
 static inline struct sk_buff *alloc_skb(unsigned int size,
 					gfp_t priority)
 {
-	return __alloc_skb(size, priority, 0, -1);
+	return __alloc_skb(size, priority, 0, NUMA_NO_NODE);
 }
 
 static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
 					       gfp_t priority)
 {
-	return __alloc_skb(size, priority, 1, -1);
+	return __alloc_skb(size, priority, 1, NUMA_NO_NODE);
 }
 
 extern bool skb_recycle_check(struct sk_buff *skb, int skb_size);
@@ -558,6 +544,15 @@
 				    unsigned int to, struct ts_config *config,
 				    struct ts_state *state);
 
+extern __u32 __skb_get_rxhash(struct sk_buff *skb);
+static inline __u32 skb_get_rxhash(struct sk_buff *skb)
+{
+	if (!skb->rxhash)
+		skb->rxhash = __skb_get_rxhash(skb);
+
+	return skb->rxhash;
+}
+
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
 static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
 {
@@ -578,11 +573,6 @@
 	return &skb_shinfo(skb)->hwtstamps;
 }
 
-static inline union skb_shared_tx *skb_tx(struct sk_buff *skb)
-{
-	return &skb_shinfo(skb)->tx_flags;
-}
-
 /**
  *	skb_queue_empty - check if a queue is empty
  *	@list: queue head
@@ -604,7 +594,7 @@
 static inline bool skb_queue_is_last(const struct sk_buff_head *list,
 				     const struct sk_buff *skb)
 {
-	return (skb->next == (struct sk_buff *) list);
+	return skb->next == (struct sk_buff *)list;
 }
 
 /**
@@ -617,7 +607,7 @@
 static inline bool skb_queue_is_first(const struct sk_buff_head *list,
 				      const struct sk_buff *skb)
 {
-	return (skb->prev == (struct sk_buff *) list);
+	return skb->prev == (struct sk_buff *)list;
 }
 
 /**
@@ -1123,7 +1113,7 @@
 			    int off, int size);
 
 #define SKB_PAGE_ASSERT(skb) 	BUG_ON(skb_shinfo(skb)->nr_frags)
-#define SKB_FRAG_ASSERT(skb) 	BUG_ON(skb_has_frags(skb))
+#define SKB_FRAG_ASSERT(skb) 	BUG_ON(skb_has_frag_list(skb))
 #define SKB_LINEAR_ASSERT(skb)  BUG_ON(skb_is_nonlinear(skb))
 
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
@@ -1561,13 +1551,25 @@
 	return skb;
 }
 
-extern struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask);
+/**
+ *	__netdev_alloc_page - allocate a page for ps-rx on a specific device
+ *	@dev: network device to receive on
+ *	@gfp_mask: alloc_pages_node mask
+ *
+ * 	Allocate a new page. dev currently unused.
+ *
+ * 	%NULL is returned if there is no free memory.
+ */
+static inline struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask)
+{
+	return alloc_pages_node(NUMA_NO_NODE, gfp_mask, 0);
+}
 
 /**
  *	netdev_alloc_page - allocate a page for ps-rx on a specific device
  *	@dev: network device to receive on
  *
- * 	Allocate a new page node local to the specified device.
+ * 	Allocate a new page. dev currently unused.
  *
  * 	%NULL is returned if there is no free memory.
  */
@@ -1787,7 +1789,7 @@
 		     skb = skb->prev)
 
 
-static inline bool skb_has_frags(const struct sk_buff *skb)
+static inline bool skb_has_frag_list(const struct sk_buff *skb)
 {
 	return skb_shinfo(skb)->frag_list != NULL;
 }
@@ -1987,8 +1989,8 @@
 
 static inline void sw_tx_timestamp(struct sk_buff *skb)
 {
-	union skb_shared_tx *shtx = skb_tx(skb);
-	if (shtx->software && !shtx->in_progress)
+	if (skb_shinfo(skb)->tx_flags & SKBTX_SW_TSTAMP &&
+	    !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
 		skb_tstamp_tx(skb, NULL);
 }
 
@@ -2159,7 +2161,7 @@
 
 static inline bool skb_rx_queue_recorded(const struct sk_buff *skb)
 {
-	return (skb->queue_mapping != 0);
+	return skb->queue_mapping != 0;
 }
 
 extern u16 skb_tx_hash(const struct net_device *dev,
@@ -2209,6 +2211,21 @@
 		skb->ip_summed = CHECKSUM_NONE;
 }
 
+/**
+ * skb_checksum_none_assert - make sure skb ip_summed is CHECKSUM_NONE
+ * @skb: skb to check
+ *
+ * fresh skbs have their ip_summed set to CHECKSUM_NONE.
+ * Instead of forcing ip_summed to CHECKSUM_NONE, we can
+ * use this helper, to document places where we make this assertion.
+ */
+static inline void skb_checksum_none_assert(struct sk_buff *skb)
+{
+#ifdef DEBUG
+	BUG_ON(skb->ip_summed != CHECKSUM_NONE);
+#endif
+}
+
 bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SKBUFF_H */
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h
index 2ea1dd1..291f721 100644
--- a/include/linux/smp_lock.h
+++ b/include/linux/smp_lock.h
@@ -54,12 +54,15 @@
 
 #else
 
+#ifdef CONFIG_BKL /* provoke build bug if not set */
 #define lock_kernel()
 #define unlock_kernel()
-#define release_kernel_lock(task)		do { } while(0)
 #define cycle_kernel_lock()			do { } while(0)
-#define reacquire_kernel_lock(task)		0
 #define kernel_locked()				1
+#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/socket.h b/include/linux/socket.h
index a2fada9..5146b50 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -322,11 +322,10 @@
 					  int offset, 
 					  unsigned int len, __wsum *csump);
 
-extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode);
+extern long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode);
 extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
 extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
 			     int offset, int len);
-extern int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr, int __user *ulen);
 extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr);
 extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
 
diff --git a/include/linux/spi/wl12xx.h b/include/linux/spi/wl12xx.h
deleted file mode 100644
index a223ecb..0000000
--- a/include/linux/spi/wl12xx.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * This file is part of wl12xx
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * Contact: Kalle Valo <kalle.valo@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
- *
- */
-
-#ifndef _LINUX_SPI_WL12XX_H
-#define _LINUX_SPI_WL12XX_H
-
-struct wl12xx_platform_data {
-	void (*set_power)(bool enable);
-	/* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */
-	int irq;
-	bool use_eeprom;
-};
-
-#endif
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index f885465..80e5358 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -50,6 +50,7 @@
 #include <linux/preempt.h>
 #include <linux/linkage.h>
 #include <linux/compiler.h>
+#include <linux/irqflags.h>
 #include <linux/thread_info.h>
 #include <linux/kernel.h>
 #include <linux/stringify.h>
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 4d5d2f5..58971e8 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -108,19 +108,43 @@
 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
 /**
- * srcu_dereference - fetch SRCU-protected pointer with checking
+ * srcu_dereference_check - fetch SRCU-protected pointer for later dereferencing
+ * @p: the pointer to fetch and protect for later dereferencing
+ * @sp: pointer to the srcu_struct, which is used to check that we
+ *	really are in an SRCU read-side critical section.
+ * @c: condition to check for update-side use
  *
- * Makes rcu_dereference_check() do the dirty work.
+ * If PROVE_RCU is enabled, invoking this outside of an RCU read-side
+ * critical section will result in an RCU-lockdep splat, unless @c evaluates
+ * to 1.  The @c argument will normally be a logical expression containing
+ * lockdep_is_held() calls.
  */
-#define srcu_dereference(p, sp) \
-		rcu_dereference_check(p, srcu_read_lock_held(sp))
+#define srcu_dereference_check(p, sp, c) \
+	__rcu_dereference_check((p), srcu_read_lock_held(sp) || (c), __rcu)
+
+/**
+ * srcu_dereference - fetch SRCU-protected pointer for later dereferencing
+ * @p: the pointer to fetch and protect for later dereferencing
+ * @sp: pointer to the srcu_struct, which is used to check that we
+ *	really are in an SRCU read-side critical section.
+ *
+ * Makes rcu_dereference_check() do the dirty work.  If PROVE_RCU
+ * is enabled, invoking this outside of an RCU read-side critical
+ * section will result in an RCU-lockdep splat.
+ */
+#define srcu_dereference(p, sp) srcu_dereference_check((p), (sp), 0)
 
 /**
  * srcu_read_lock - register a new reader for an SRCU-protected structure.
  * @sp: srcu_struct in which to register the new reader.
  *
  * Enter an SRCU read-side critical section.  Note that SRCU read-side
- * critical sections may be nested.
+ * critical sections may be nested.  However, it is illegal to
+ * call anything that waits on an SRCU grace period for the same
+ * srcu_struct, whether directly or indirectly.  Please note that
+ * one way to indirectly wait on an SRCU grace period is to acquire
+ * a mutex that is held elsewhere while calling synchronize_srcu() or
+ * synchronize_srcu_expedited().
  */
 static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp)
 {
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h
index a6d5225..11daf9c 100644
--- a/include/linux/ssb/ssb_regs.h
+++ b/include/linux/ssb/ssb_regs.h
@@ -97,6 +97,7 @@
 #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 */
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 632ff7c..d66c617 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -32,10 +32,14 @@
 struct plat_stmmacenet_data {
 	int bus_id;
 	int pbl;
+	int clk_csr;
 	int has_gmac;
 	int enh_desc;
+	int tx_coe;
+	int bugged_jumbo;
+	int pmt;
 	void (*fix_mac_speed)(void *priv, unsigned int speed);
-	void (*bus_setup)(unsigned long ioaddr);
+	void (*bus_setup)(void __iomem *ioaddr);
 #ifdef CONFIG_STM_DRIVERS
 	struct stm_pad_config *pad_config;
 #endif
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 6b524a0..1808960 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -126,8 +126,8 @@
 
 #else	 /* CONFIG_STOP_MACHINE && CONFIG_SMP */
 
-static inline int stop_machine(int (*fn)(void *), void *data,
-			       const struct cpumask *cpus)
+static inline int __stop_machine(int (*fn)(void *), void *data,
+				 const struct cpumask *cpus)
 {
 	int ret;
 	local_irq_disable();
@@ -136,5 +136,11 @@
 	return ret;
 }
 
+static inline int stop_machine(int (*fn)(void *), void *data,
+			       const struct cpumask *cpus)
+{
+	return __stop_machine(fn, data, cpus);
+}
+
 #endif	/* CONFIG_STOP_MACHINE && CONFIG_SMP */
 #endif	/* _LINUX_STOP_MACHINE */
diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 671538d..8eee9db 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -69,7 +69,7 @@
 	enum rpc_gss_proc	gc_proc;
 	u32			gc_seq;
 	spinlock_t		gc_seq_lock;
-	struct gss_ctx		*gc_gss_ctx;
+	struct gss_ctx __rcu	*gc_gss_ctx;
 	struct xdr_netobj	gc_wire_ctx;
 	u32			gc_win;
 	unsigned long		gc_expiry;
@@ -80,7 +80,7 @@
 struct gss_cred {
 	struct rpc_cred		gc_base;
 	enum rpc_gss_svc	gc_service;
-	struct gss_cl_ctx	*gc_ctx;
+	struct gss_cl_ctx __rcu	*gc_ctx;
 	struct gss_upcall_msg	*gc_upcall;
 	unsigned long		gc_upcall_timestamp;
 	unsigned char		gc_machine_cred : 1;
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 4af270e..2669751 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -293,8 +293,8 @@
 extern bool events_check_enabled;
 
 extern bool pm_check_wakeup_events(void);
-extern bool pm_get_wakeup_count(unsigned long *count);
-extern bool pm_save_wakeup_count(unsigned long count);
+extern bool pm_get_wakeup_count(unsigned int *count);
+extern bool pm_save_wakeup_count(unsigned int count);
 #else /* !CONFIG_PM_SLEEP */
 
 static inline int register_pm_notifier(struct notifier_block *nb)
@@ -308,6 +308,8 @@
 }
 
 #define pm_notifier(fn, pri)	do { (void)(fn); } while (0)
+
+static inline bool pm_check_wakeup_events(void) { return true; }
 #endif /* !CONFIG_PM_SLEEP */
 
 extern struct mutex pm_mutex;
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 96eb576..30b8815 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -164,6 +164,10 @@
 			const struct attribute *attr, const char *group);
 void sysfs_remove_file_from_group(struct kobject *kobj,
 			const struct attribute *attr, const char *group);
+int sysfs_merge_group(struct kobject *kobj,
+		       const struct attribute_group *grp);
+void sysfs_unmerge_group(struct kobject *kobj,
+		       const struct attribute_group *grp);
 
 void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
 void sysfs_notify_dirent(struct sysfs_dirent *sd);
@@ -302,6 +306,17 @@
 {
 }
 
+static inline int sysfs_merge_group(struct kobject *kobj,
+		       const struct attribute_group *grp)
+{
+	return 0;
+}
+
+static inline void sysfs_unmerge_group(struct kobject *kobj,
+		       const struct attribute_group *grp)
+{
+}
+
 static inline void sysfs_notify(struct kobject *kobj, const char *dir,
 				const char *attr)
 {
diff --git a/include/linux/tc_act/Kbuild b/include/linux/tc_act/Kbuild
index 7699093..67b501c3 100644
--- a/include/linux/tc_act/Kbuild
+++ b/include/linux/tc_act/Kbuild
@@ -4,3 +4,4 @@
 header-y += tc_pedit.h
 header-y += tc_nat.h
 header-y += tc_skbedit.h
+header-y += tc_csum.h
diff --git a/include/linux/tc_act/tc_csum.h b/include/linux/tc_act/tc_csum.h
new file mode 100644
index 0000000..a047c49
--- /dev/null
+++ b/include/linux/tc_act/tc_csum.h
@@ -0,0 +1,32 @@
+#ifndef __LINUX_TC_CSUM_H
+#define __LINUX_TC_CSUM_H
+
+#include <linux/types.h>
+#include <linux/pkt_cls.h>
+
+#define TCA_ACT_CSUM 16
+
+enum {
+	TCA_CSUM_UNSPEC,
+	TCA_CSUM_PARMS,
+	TCA_CSUM_TM,
+	__TCA_CSUM_MAX
+};
+#define TCA_CSUM_MAX (__TCA_CSUM_MAX - 1)
+
+enum {
+	TCA_CSUM_UPDATE_FLAG_IPV4HDR = 1,
+	TCA_CSUM_UPDATE_FLAG_ICMP    = 2,
+	TCA_CSUM_UPDATE_FLAG_IGMP    = 4,
+	TCA_CSUM_UPDATE_FLAG_TCP     = 8,
+	TCA_CSUM_UPDATE_FLAG_UDP     = 16,
+	TCA_CSUM_UPDATE_FLAG_UDPLITE = 32
+};
+
+struct tc_csum {
+	tc_gen;
+
+	__u32 update_flags;
+};
+
+#endif /* __LINUX_TC_CSUM_H */
diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h
index 0864206..7138962 100644
--- a/include/linux/tc_ematch/tc_em_meta.h
+++ b/include/linux/tc_ematch/tc_em_meta.h
@@ -79,6 +79,7 @@
  	TCF_META_ID_SK_SENDMSG_OFF,
  	TCF_META_ID_SK_WRITE_PENDING,
 	TCF_META_ID_VLAN_TAG,
+	TCF_META_ID_RXHASH,
 	__TCF_META_ID_MAX
 };
 #define TCF_META_ID_MAX (__TCF_META_ID_MAX - 1)
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index a778ee0..e64f4c6 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -105,6 +105,7 @@
 #define TCP_COOKIE_TRANSACTIONS	15	/* TCP Cookie Transactions */
 #define TCP_THIN_LINEAR_TIMEOUTS 16      /* Use linear timeouts for thin streams*/
 #define TCP_THIN_DUPACK         17      /* Fast retrans. after 1 dupack */
+#define TCP_USER_TIMEOUT	18	/* How long for loss retry before timeout */
 
 /* for TCP_INFO socket option */
 #define TCPI_OPT_TIMESTAMPS	1
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index a8cc4e1..c9069654 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -23,12 +23,12 @@
 		};
 		/* For futex_wait and futex_wait_requeue_pi */
 		struct {
-			u32 *uaddr;
+			u32 __user *uaddr;
 			u32 val;
 			u32 flags;
 			u32 bitset;
 			u64 time;
-			u32 *uaddr2;
+			u32 __user *uaddr2;
 		} futex;
 		/* For nanosleep */
 		struct {
diff --git a/include/linux/tipc.h b/include/linux/tipc.h
index 181c8d0..d10614b 100644
--- a/include/linux/tipc.h
+++ b/include/linux/tipc.h
@@ -127,17 +127,23 @@
  * TIPC topology subscription service definitions
  */
 
-#define TIPC_SUB_SERVICE     	0x00  	/* Filter for service availability    */
-#define TIPC_SUB_PORTS     	0x01  	/* Filter for port availability  */
-#define TIPC_SUB_CANCEL         0x04    /* Cancel a subscription         */
+#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 */
 
 struct tipc_subscr {
-	struct tipc_name_seq seq;	/* NBO. Name sequence of interest */
-	__u32 timeout;			/* NBO. Subscription duration (in ms) */
-        __u32 filter;   		/* NBO. Bitmask of filter options */
-	char usr_handle[8];		/* Opaque. Available for subscriber use */
+	struct tipc_name_seq seq;	/* name sequence of interest */
+	__u32 timeout;			/* subscription duration (in ms) */
+        __u32 filter;   		/* bitmask of filter options */
+	char usr_handle[8];		/* available for subscriber use */
 };
 
 #define TIPC_PUBLISHED		1	/* publication event */
@@ -145,11 +151,11 @@
 #define TIPC_SUBSCR_TIMEOUT	3	/* subscription timeout event */
 
 struct tipc_event {
-	__u32 event;			/* NBO. Event type, as defined above */
-	__u32 found_lower;		/* NBO. Matching name seq instances  */
-	__u32 found_upper;		/*  "      "       "   "    "        */
-	struct tipc_portid port;	/* NBO. Associated port              */
-	struct tipc_subscr s;		/* Original, associated subscription */
+	__u32 event;			/* event type */
+	__u32 found_lower;		/* matching name seq instances */
+	__u32 found_upper;		/*    "      "    "     "      */
+	struct tipc_portid port;	/* associated port */
+	struct tipc_subscr s;		/* associated subscription */
 };
 
 /*
diff --git a/include/linux/topology.h b/include/linux/topology.h
index 64e084f..b91a40e 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -201,6 +201,12 @@
 	.balance_interval	= 64,					\
 }
 
+#ifdef CONFIG_SCHED_BOOK
+#ifndef SD_BOOK_INIT
+#error Please define an appropriate SD_BOOK_INIT in include/asm/topology.h!!!
+#endif
+#endif /* CONFIG_SCHED_BOOK */
+
 #ifdef CONFIG_NUMA
 #ifndef SD_NODE_INIT
 #error Please define an appropriate SD_NODE_INIT in include/asm/topology.h!!!
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 103d1b6..a4a90b6 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -17,6 +17,7 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/rcupdate.h>
+#include <linux/jump_label.h>
 
 struct module;
 struct tracepoint;
@@ -145,7 +146,9 @@
 	extern struct tracepoint __tracepoint_##name;			\
 	static inline void trace_##name(proto)				\
 	{								\
-		if (unlikely(__tracepoint_##name.state))		\
+		JUMP_LABEL(&__tracepoint_##name.state, do_trace);	\
+		return;							\
+do_trace:								\
 			__DO_TRACE(&__tracepoint_##name,		\
 				TP_PROTO(data_proto),			\
 				TP_ARGS(data_args));			\
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 67d64e6..86be0cd 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -256,6 +256,7 @@
 struct tty_struct {
 	int	magic;
 	struct kref kref;
+	struct device *dev;
 	struct tty_driver *driver;
 	const struct tty_operations *ops;
 	int index;
@@ -465,7 +466,7 @@
 extern struct tty_struct *get_current_tty(void);
 extern void tty_default_fops(struct file_operations *fops);
 extern struct tty_struct *alloc_tty_struct(void);
-extern void tty_add_file(struct tty_struct *tty, struct file *file);
+extern int tty_add_file(struct tty_struct *tty, struct file *file);
 extern void free_tty_struct(struct tty_struct *tty);
 extern void initialize_tty_struct(struct tty_struct *tty,
 		struct tty_driver *driver, int idx);
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index b086779..db2d227 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -224,6 +224,12 @@
  *	unless the tty also has a valid tty->termiox pointer.
  *
  *	Optional: Called under the termios lock
+ *
+ * int (*get_icount)(struct tty_struct *tty, struct serial_icounter *icount);
+ *
+ *	Called when the device receives a TIOCGICOUNT ioctl. Passed a kernel
+ *	structure to complete. This method is optional and will only be called
+ *	if provided (otherwise EINVAL will be returned).
  */
 
 #include <linux/fs.h>
@@ -232,6 +238,7 @@
 
 struct tty_struct;
 struct tty_driver;
+struct serial_icounter_struct;
 
 struct tty_operations {
 	struct tty_struct * (*lookup)(struct tty_driver *driver,
@@ -268,6 +275,8 @@
 			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);
+	int (*get_icount)(struct tty_struct *tty,
+				struct serial_icounter_struct *icount);
 #ifdef CONFIG_CONSOLE_POLL
 	int (*poll_init)(struct tty_driver *driver, int line, char *options);
 	int (*poll_get_char)(struct tty_driver *driver, int line);
diff --git a/include/linux/types.h b/include/linux/types.h
index 01a082f..357dbc1 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -121,7 +121,15 @@
 typedef		__s64		int64_t;
 #endif
 
-/* this is a special 64bit data type that is 8-byte aligned */
+/*
+ * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid
+ * common 32/64-bit compat problems.
+ * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other
+ * architectures) and to 8-byte boundaries on 64-bit architetures.  The new
+ * aligned_64 type enforces 8-byte alignment so that structs containing
+ * aligned_64 values have the same alignment on 32-bit and 64-bit architectures.
+ * No conversions are necessary between 32-bit user-space and a 64-bit kernel.
+ */
 #define aligned_u64 __u64 __attribute__((aligned(8)))
 #define aligned_be64 __be64 __attribute__((aligned(8)))
 #define aligned_le64 __le64 __attribute__((aligned(8)))
@@ -178,6 +186,11 @@
 typedef __u16 __bitwise __sum16;
 typedef __u32 __bitwise __wsum;
 
+/* this is a special 64bit data type that is 8-byte aligned */
+#define __aligned_u64 __u64 __attribute__((aligned(8)))
+#define __aligned_be64 __be64 __attribute__((aligned(8)))
+#define __aligned_le64 __le64 __attribute__((aligned(8)))
+
 #ifdef __KERNEL__
 typedef unsigned __bitwise__ gfp_t;
 typedef unsigned __bitwise__ fmode_t;
diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h
index 5dcc9ff..d6188e5 100644
--- a/include/linux/uio_driver.h
+++ b/include/linux/uio_driver.h
@@ -108,7 +108,7 @@
 
 /* defines for uio_info->irq */
 #define UIO_IRQ_CUSTOM	-1
-#define UIO_IRQ_NONE	-2
+#define UIO_IRQ_NONE	0
 
 /* defines for uio_mem->memtype */
 #define UIO_MEM_NONE	0
diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
index c117a68..5e86dc7 100644
--- a/include/linux/usb/cdc.h
+++ b/include/linux/usb/cdc.h
@@ -32,6 +32,8 @@
 
 #define USB_CDC_PROTO_EEM			7
 
+#define USB_CDC_NCM_PROTO_NTB			1
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -274,13 +276,13 @@
 /*
  * Class Specific structures and constants
  *
- * CDC NCM parameter structure, CDC NCM subclass 6.2.1
+ * CDC NCM NTB parameters structure, CDC NCM subclass 6.2.1
  *
  */
 
-struct usb_cdc_ncm_ntb_parameter {
+struct usb_cdc_ncm_ntb_parameters {
 	__le16	wLength;
-	__le16	bmNtbFormatSupported;
+	__le16	bmNtbFormatsSupported;
 	__le32	dwNtbInMaxSize;
 	__le16	wNdpInDivisor;
 	__le16	wNdpInPayloadRemainder;
@@ -297,8 +299,8 @@
  * CDC NCM transfer headers, CDC NCM subclass 3.2
  */
 
-#define NCM_NTH16_SIGN		0x484D434E /* NCMH */
-#define NCM_NTH32_SIGN		0x686D636E /* ncmh */
+#define USB_CDC_NCM_NTH16_SIGN		0x484D434E /* NCMH */
+#define USB_CDC_NCM_NTH32_SIGN		0x686D636E /* ncmh */
 
 struct usb_cdc_ncm_nth16 {
 	__le32	dwSignature;
@@ -320,25 +322,78 @@
  * CDC NCM datagram pointers, CDC NCM subclass 3.3
  */
 
-#define NCM_NDP16_CRC_SIGN	0x314D434E /* NCM1 */
-#define NCM_NDP16_NOCRC_SIGN	0x304D434E /* NCM0 */
-#define NCM_NDP32_CRC_SIGN	0x316D636E /* ncm1 */
-#define NCM_NDP32_NOCRC_SIGN	0x306D636E /* ncm0 */
+#define USB_CDC_NCM_NDP16_CRC_SIGN	0x314D434E /* NCM1 */
+#define USB_CDC_NCM_NDP16_NOCRC_SIGN	0x304D434E /* NCM0 */
+#define USB_CDC_NCM_NDP32_CRC_SIGN	0x316D636E /* ncm1 */
+#define USB_CDC_NCM_NDP32_NOCRC_SIGN	0x306D636E /* ncm0 */
 
+/* 16-bit NCM Datagram Pointer Entry */
+struct usb_cdc_ncm_dpe16 {
+	__le16	wDatagramIndex;
+	__le16	wDatagramLength;
+} __attribute__((__packed__));
+
+/* 16-bit NCM Datagram Pointer Table */
 struct usb_cdc_ncm_ndp16 {
 	__le32	dwSignature;
 	__le16	wLength;
 	__le16	wNextFpIndex;
-	__u8	data[0];
+	struct	usb_cdc_ncm_dpe16 dpe16[0];
 } __attribute__ ((packed));
 
+/* 32-bit NCM Datagram Pointer Entry */
+struct usb_cdc_ncm_dpe32 {
+	__le32	dwDatagramIndex;
+	__le32	dwDatagramLength;
+} __attribute__((__packed__));
+
+/* 32-bit NCM Datagram Pointer Table */
 struct usb_cdc_ncm_ndp32 {
 	__le32	dwSignature;
 	__le16	wLength;
 	__le16	wReserved6;
-	__le32	dwNextFpIndex;
+	__le32	dwNextNdpIndex;
 	__le32	dwReserved12;
-	__u8	data[0];
+	struct	usb_cdc_ncm_dpe32 dpe32[0];
 } __attribute__ ((packed));
 
+/* CDC NCM subclass 3.2.1 and 3.2.2 */
+#define USB_CDC_NCM_NDP16_INDEX_MIN			0x000C
+#define USB_CDC_NCM_NDP32_INDEX_MIN			0x0010
+
+/* CDC NCM subclass 3.3.3 Datagram Formatting */
+#define USB_CDC_NCM_DATAGRAM_FORMAT_CRC			0x30
+#define USB_CDC_NCM_DATAGRAM_FORMAT_NOCRC		0X31
+
+/* CDC NCM subclass 4.2 NCM Communications Interface Protocol Code */
+#define USB_CDC_NCM_PROTO_CODE_NO_ENCAP_COMMANDS	0x00
+#define USB_CDC_NCM_PROTO_CODE_EXTERN_PROTO		0xFE
+
+/* CDC NCM subclass 5.2.1 NCM Functional Descriptor, bmNetworkCapabilities */
+#define USB_CDC_NCM_NCAP_ETH_FILTER			(1 << 0)
+#define USB_CDC_NCM_NCAP_NET_ADDRESS			(1 << 1)
+#define USB_CDC_NCM_NCAP_ENCAP_COMMAND			(1 << 2)
+#define USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE		(1 << 3)
+#define USB_CDC_NCM_NCAP_CRC_MODE			(1 << 4)
+
+/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
+#define USB_CDC_NCM_NTB16_SUPPORTED			(1 << 0)
+#define USB_CDC_NCM_NTB32_SUPPORTED			(1 << 1)
+
+/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
+#define USB_CDC_NCM_NDP_ALIGN_MIN_SIZE			0x04
+#define USB_CDC_NCM_NTB_MAX_LENGTH			0x1C
+
+/* CDC NCM subclass 6.2.5 SetNtbFormat */
+#define USB_CDC_NCM_NTB16_FORMAT			0x00
+#define USB_CDC_NCM_NTB32_FORMAT			0x01
+
+/* CDC NCM subclass 6.2.7 SetNtbInputSize */
+#define USB_CDC_NCM_NTB_MIN_IN_SIZE			2048
+#define USB_CDC_NCM_NTB_MIN_OUT_SIZE			2048
+
+/* CDC NCM subclass 6.2.11 SetCrcMode */
+#define USB_CDC_NCM_CRC_NOT_APPENDED			0x00
+#define USB_CDC_NCM_CRC_APPENDED			0x01
+
 #endif /* __LINUX_USB_CDC_H */
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index da2ed77..f917bbb 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -123,8 +123,23 @@
 #define USB_DEVICE_A_ALT_HNP_SUPPORT	5	/* (otg) other RH port does */
 #define USB_DEVICE_DEBUG_MODE		6	/* (special devices only) */
 
+/*
+ * New Feature Selectors as added by USB 3.0
+ * See USB 3.0 spec Table 9-6
+ */
+#define USB_DEVICE_U1_ENABLE	48	/* dev may initiate U1 transition */
+#define USB_DEVICE_U2_ENABLE	49	/* dev may initiate U2 transition */
+#define USB_DEVICE_LTM_ENABLE	50	/* dev may send LTM */
+#define USB_INTRF_FUNC_SUSPEND	0	/* function suspend */
+
+#define USB_INTR_FUNC_SUSPEND_OPT_MASK	0xFF00
+
 #define USB_ENDPOINT_HALT		0	/* IN/OUT will STALL */
 
+/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
+#define USB_DEV_STAT_U1_ENABLED		2	/* transition into U1 state */
+#define USB_DEV_STAT_U2_ENABLED		3	/* transition into U2 state */
+#define USB_DEV_STAT_LTM_ENABLED	4	/* Latency tolerance messages */
 
 /**
  * struct usb_ctrlrequest - SETUP data for a USB device control request
@@ -675,6 +690,7 @@
 	__u8  bNumDeviceCaps;
 } __attribute__((packed));
 
+#define USB_DT_BOS_SIZE		5
 /*-------------------------------------------------------------------------*/
 
 /* USB_DT_DEVICE_CAPABILITY:  grouped with BOS */
@@ -712,16 +728,56 @@
 	__u8  bReserved;
 } __attribute__((packed));
 
+/* USB 2.0 Extension descriptor */
 #define	USB_CAP_TYPE_EXT		2
 
 struct usb_ext_cap_descriptor {		/* Link Power Management */
 	__u8  bLength;
 	__u8  bDescriptorType;
 	__u8  bDevCapabilityType;
-	__u8  bmAttributes;
+	__le32 bmAttributes;
 #define USB_LPM_SUPPORT			(1 << 1)	/* supports LPM */
 } __attribute__((packed));
 
+#define USB_DT_USB_EXT_CAP_SIZE	7
+
+/*
+ * SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB
+ * specific device level capabilities
+ */
+#define		USB_SS_CAP_TYPE		3
+struct usb_ss_cap_descriptor {		/* Link Power Management */
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u8  bDevCapabilityType;
+	__u8  bmAttributes;
+#define USB_LTM_SUPPORT			(1 << 1) /* supports LTM */
+	__le16 wSpeedSupported;
+#define USB_LOW_SPEED_OPERATION		(1)	 /* Low speed operation */
+#define USB_FULL_SPEED_OPERATION	(1 << 1) /* Full speed operation */
+#define USB_HIGH_SPEED_OPERATION	(1 << 2) /* High speed operation */
+#define USB_5GBPS_OPERATION		(1 << 3) /* Operation at 5Gbps */
+	__u8  bFunctionalitySupport;
+	__u8  bU1devExitLat;
+	__le16 bU2DevExitLat;
+} __attribute__((packed));
+
+#define USB_DT_USB_SS_CAP_SIZE	10
+
+/*
+ * Container ID Capability descriptor: Defines the instance unique ID used to
+ * identify the instance across all operating modes
+ */
+#define	CONTAINER_ID_TYPE	4
+struct usb_ss_container_id_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u8  bDevCapabilityType;
+	__u8  bReserved;
+	__u8  ContainerID[16]; /* 128-bit number */
+} __attribute__((packed));
+
+#define USB_DT_USB_SS_CONTN_ID_SIZE	20
 /*-------------------------------------------------------------------------*/
 
 /* USB_DT_WIRELESS_ENDPOINT_COMP:  companion descriptor associated with
@@ -808,4 +864,14 @@
 	 */
 };
 
+/*-------------------------------------------------------------------------*/
+
+/*
+ * As per USB compliance update, a device that is actively drawing
+ * more than 100mA from USB must report itself as bus-powered in
+ * the GetStatus(DEVICE) call.
+ * http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34
+ */
+#define USB_SELF_POWER_VBUS_MAX_DRAW		100
+
 #endif /* __LINUX_USB_CH9_H */
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 6170681..3d29a7d 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -161,8 +161,6 @@
  *	and by language IDs provided in control requests.
  * @descriptors: Table of descriptors preceding all function descriptors.
  *	Examples include OTG and vendor-specific descriptors.
- * @bind: Called from @usb_add_config() to allocate resources unique to this
- *	configuration and to call @usb_add_function() for each function used.
  * @unbind: Reverses @bind; called as a side effect of unregistering the
  *	driver which added this configuration.
  * @setup: Used to delegate control requests that aren't handled by standard
@@ -207,8 +205,7 @@
 	 * we can't restructure things to avoid mismatching...
 	 */
 
-	/* configuration management:  bind/unbind */
-	int			(*bind)(struct usb_configuration *);
+	/* configuration management: unbind/setup */
 	void			(*unbind)(struct usb_configuration *);
 	int			(*setup)(struct usb_configuration *,
 					const struct usb_ctrlrequest *);
@@ -232,20 +229,24 @@
 };
 
 int usb_add_config(struct usb_composite_dev *,
-		struct usb_configuration *);
+		struct usb_configuration *,
+		int (*)(struct usb_configuration *));
 
 /**
  * struct usb_composite_driver - groups configurations into a gadget
  * @name: For diagnostics, identifies the driver.
+ * @iProduct: Used as iProduct override if @dev->iProduct is not set.
+ *	If NULL value of @name is taken.
+ * @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is
+ *	not set. If NULL a default "<system> <release> with <udc>" value
+ *	will be used.
  * @dev: Template descriptor for the device, including default device
  *	identifiers.
  * @strings: tables of strings, keyed by identifiers assigned during bind()
  *	and language IDs provided in control requests
- * @bind: (REQUIRED) Used to allocate resources that are shared across the
- *	whole device, such as string IDs, and add its configurations using
- *	@usb_add_config().  This may fail by returning a negative errno
- *	value; it should return zero on successful initialization.
- * @unbind: Reverses @bind(); called as a side effect of unregistering
+ * @needs_serial: set to 1 if the gadget needs userspace to provide
+ * 	a serial number.  If one is not provided, warning will be printed.
+ * @unbind: Reverses bind; called as a side effect of unregistering
  *	this driver.
  * @disconnect: optional driver disconnect method
  * @suspend: Notifies when the host stops sending USB traffic,
@@ -256,7 +257,7 @@
  * Devices default to reporting self powered operation.  Devices which rely
  * on bus powered operation should report this in their @bind() method.
  *
- * Before returning from @bind, various fields in the template descriptor
+ * Before returning from bind, various fields in the template descriptor
  * may be overridden.  These include the idVendor/idProduct/bcdDevice values
  * normally to bind the appropriate host side driver, and the three strings
  * (iManufacturer, iProduct, iSerialNumber) normally used to provide user
@@ -266,15 +267,12 @@
  */
 struct usb_composite_driver {
 	const char				*name;
+	const char				*iProduct;
+	const char				*iManufacturer;
 	const struct usb_device_descriptor	*dev;
 	struct usb_gadget_strings		**strings;
+	unsigned		needs_serial:1;
 
-	/* REVISIT:  bind() functions can be marked __init, which
-	 * makes trouble for section mismatch analysis.  See if
-	 * we can't restructure things to avoid mismatching...
-	 */
-
-	int			(*bind)(struct usb_composite_dev *);
 	int			(*unbind)(struct usb_composite_dev *);
 
 	void			(*disconnect)(struct usb_composite_dev *);
@@ -284,8 +282,9 @@
 	void			(*resume)(struct usb_composite_dev *);
 };
 
-extern int usb_composite_register(struct usb_composite_driver *);
-extern void usb_composite_unregister(struct usb_composite_driver *);
+extern int usb_composite_probe(struct usb_composite_driver *driver,
+			       int (*bind)(struct usb_composite_dev *cdev));
+extern void usb_composite_unregister(struct usb_composite_driver *driver);
 
 
 /**
@@ -334,6 +333,9 @@
 	struct list_head		configs;
 	struct usb_composite_driver	*driver;
 	u8				next_string_id;
+	u8				manufacturer_override;
+	u8				product_override;
+	u8				serial_override;
 
 	/* the gadget driver won't enable the data pullup
 	 * while the deactivation count is nonzero.
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index d3ef42d..006412c 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -705,11 +705,6 @@
  * struct usb_gadget_driver - driver for usb 'slave' devices
  * @function: String describing the gadget's function
  * @speed: Highest speed the driver handles.
- * @bind: Invoked when the driver is bound to a gadget, usually
- *	after registering the driver.
- *	At that point, ep0 is fully initialized, and ep_list holds
- *	the currently-available endpoints.
- *	Called in a context that permits sleeping.
  * @setup: Invoked for ep0 control requests that aren't handled by
  *	the hardware level driver. Most calls must be handled by
  *	the gadget driver, including descriptor and configuration
@@ -774,7 +769,6 @@
 struct usb_gadget_driver {
 	char			*function;
 	enum usb_device_speed	speed;
-	int			(*bind)(struct usb_gadget *);
 	void			(*unbind)(struct usb_gadget *);
 	int			(*setup)(struct usb_gadget *,
 					const struct usb_ctrlrequest *);
@@ -798,17 +792,19 @@
  */
 
 /**
- * usb_gadget_register_driver - register a gadget driver
- * @driver:the driver being registered
+ * usb_gadget_probe_driver - probe a gadget driver
+ * @driver: the driver being registered
+ * @bind: the driver's bind callback
  * Context: can sleep
  *
  * Call this in your gadget driver's module initialization function,
  * to tell the underlying usb controller driver about your driver.
- * The driver's bind() function will be called to bind it to a
- * gadget before this registration call returns.  It's expected that
- * the bind() functions will be in init sections.
+ * The @bind() function will be called to bind it to a gadget before this
+ * registration call returns.  It's expected that the @bind() function will
+ * be in init sections.
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver);
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
 
 /**
  * usb_gadget_unregister_driver - unregister a gadget driver
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 3b571f1..0b6e751 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -329,6 +329,8 @@
 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 void usb_hcd_flush_endpoint(struct usb_device *udev,
 		struct usb_host_endpoint *ep);
 extern void usb_hcd_disable_endpoint(struct usb_device *udev,
diff --git a/include/linux/usb/intel_mid_otg.h b/include/linux/usb/intel_mid_otg.h
new file mode 100644
index 0000000..a0ccf79
--- /dev/null
+++ b/include/linux/usb/intel_mid_otg.h
@@ -0,0 +1,180 @@
+/*
+ * Intel MID (Langwell/Penwell) USB OTG Transceiver driver
+ * Copyright (C) 2008 - 2010, 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_MID_OTG_H
+#define __INTEL_MID_OTG_H
+
+#include <linux/pm.h>
+#include <linux/usb/otg.h>
+#include <linux/notifier.h>
+
+struct intel_mid_otg_xceiv;
+
+/* This is a common data structure for Intel MID platform to
+ * save values of the OTG state machine */
+struct otg_hsm {
+	/* Input */
+	int a_bus_resume;
+	int a_bus_suspend;
+	int a_conn;
+	int a_sess_vld;
+	int a_srp_det;
+	int a_vbus_vld;
+	int b_bus_resume;
+	int b_bus_suspend;
+	int b_conn;
+	int b_se0_srp;
+	int b_ssend_srp;
+	int b_sess_end;
+	int b_sess_vld;
+	int id;
+/* id values */
+#define ID_B		0x05
+#define ID_A		0x04
+#define ID_ACA_C	0x03
+#define ID_ACA_B	0x02
+#define ID_ACA_A	0x01
+	int power_up;
+	int adp_change;
+	int test_device;
+
+	/* Internal variables */
+	int a_set_b_hnp_en;
+	int b_srp_done;
+	int b_hnp_enable;
+	int hnp_poll_enable;
+
+	/* Timeout indicator for timers */
+	int a_wait_vrise_tmout;
+	int a_wait_bcon_tmout;
+	int a_aidl_bdis_tmout;
+	int a_bidl_adis_tmout;
+	int a_bidl_adis_tmr;
+	int a_wait_vfall_tmout;
+	int b_ase0_brst_tmout;
+	int b_bus_suspend_tmout;
+	int b_srp_init_tmout;
+	int b_srp_fail_tmout;
+	int b_srp_fail_tmr;
+	int b_adp_sense_tmout;
+
+	/* Informative variables */
+	int a_bus_drop;
+	int a_bus_req;
+	int a_clr_err;
+	int b_bus_req;
+	int a_suspend_req;
+	int b_bus_suspend_vld;
+
+	/* Output */
+	int drv_vbus;
+	int loc_conn;
+	int loc_sof;
+
+	/* Others */
+	int vbus_srp_up;
+};
+
+/* must provide ULPI access function to read/write registers implemented in
+ * ULPI address space */
+struct iotg_ulpi_access_ops {
+	int	(*read)(struct intel_mid_otg_xceiv *iotg, u8 reg, u8 *val);
+	int	(*write)(struct intel_mid_otg_xceiv *iotg, u8 reg, u8 val);
+};
+
+#define OTG_A_DEVICE	0x0
+#define OTG_B_DEVICE	0x1
+
+/*
+ * the Intel MID (Langwell/Penwell) otg transceiver driver needs to interact
+ * with device and host drivers to implement the USB OTG related feature. More
+ * function members are added based on otg_transceiver data structure for this
+ * purpose.
+ */
+struct intel_mid_otg_xceiv {
+	struct otg_transceiver	otg;
+	struct otg_hsm		hsm;
+
+	/* base address */
+	void __iomem		*base;
+
+	/* ops to access ulpi */
+	struct iotg_ulpi_access_ops	ulpi_ops;
+
+	/* atomic notifier for interrupt context */
+	struct atomic_notifier_head	iotg_notifier;
+
+	/* start/stop USB Host function */
+	int	(*start_host)(struct intel_mid_otg_xceiv *iotg);
+	int	(*stop_host)(struct intel_mid_otg_xceiv *iotg);
+
+	/* start/stop USB Peripheral function */
+	int	(*start_peripheral)(struct intel_mid_otg_xceiv *iotg);
+	int	(*stop_peripheral)(struct intel_mid_otg_xceiv *iotg);
+
+	/* start/stop ADP sense/probe function */
+	int	(*set_adp_probe)(struct intel_mid_otg_xceiv *iotg,
+					bool enabled, int dev);
+	int	(*set_adp_sense)(struct intel_mid_otg_xceiv *iotg,
+					bool enabled);
+
+#ifdef CONFIG_PM
+	/* suspend/resume USB host function */
+	int	(*suspend_host)(struct intel_mid_otg_xceiv *iotg,
+					pm_message_t message);
+	int	(*resume_host)(struct intel_mid_otg_xceiv *iotg);
+
+	int	(*suspend_peripheral)(struct intel_mid_otg_xceiv *iotg,
+					pm_message_t message);
+	int	(*resume_peripheral)(struct intel_mid_otg_xceiv *iotg);
+#endif
+
+};
+static inline
+struct intel_mid_otg_xceiv *otg_to_mid_xceiv(struct otg_transceiver *otg)
+{
+	return container_of(otg, struct intel_mid_otg_xceiv, otg);
+}
+
+#define MID_OTG_NOTIFY_CONNECT		0x0001
+#define MID_OTG_NOTIFY_DISCONN		0x0002
+#define MID_OTG_NOTIFY_HSUSPEND		0x0003
+#define MID_OTG_NOTIFY_HRESUME		0x0004
+#define MID_OTG_NOTIFY_CSUSPEND		0x0005
+#define MID_OTG_NOTIFY_CRESUME		0x0006
+#define MID_OTG_NOTIFY_HOSTADD		0x0007
+#define MID_OTG_NOTIFY_HOSTREMOVE	0x0008
+#define MID_OTG_NOTIFY_CLIENTADD	0x0009
+#define MID_OTG_NOTIFY_CLIENTREMOVE	0x000a
+
+static inline int
+intel_mid_otg_register_notifier(struct intel_mid_otg_xceiv *iotg,
+				struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&iotg->iotg_notifier, nb);
+}
+
+static inline void
+intel_mid_otg_unregister_notifier(struct intel_mid_otg_xceiv *iotg,
+				struct notifier_block *nb)
+{
+	atomic_notifier_chain_unregister(&iotg->iotg_notifier, nb);
+}
+
+#endif /* __INTEL_MID_OTG_H */
diff --git a/include/linux/usb/langwell_otg.h b/include/linux/usb/langwell_otg.h
new file mode 100644
index 0000000..51f17b1
--- /dev/null
+++ b/include/linux/usb/langwell_otg.h
@@ -0,0 +1,139 @@
+/*
+ * Intel Langwell USB OTG transceiver driver
+ * Copyright (C) 2008 - 2010, 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 __LANGWELL_OTG_H
+#define __LANGWELL_OTG_H
+
+#include <linux/usb/intel_mid_otg.h>
+
+#define CI_USBCMD		0x30
+#	define USBCMD_RST		BIT(1)
+#	define USBCMD_RS		BIT(0)
+#define CI_USBSTS		0x34
+#	define USBSTS_SLI		BIT(8)
+#	define USBSTS_URI		BIT(6)
+#	define USBSTS_PCI		BIT(2)
+#define CI_PORTSC1		0x74
+#	define PORTSC_PP		BIT(12)
+#	define PORTSC_LS		(BIT(11) | BIT(10))
+#	define PORTSC_SUSP		BIT(7)
+#	define PORTSC_CCS		BIT(0)
+#define CI_HOSTPC1		0xb4
+#	define HOSTPC1_PHCD		BIT(22)
+#define CI_OTGSC		0xf4
+#	define OTGSC_DPIE		BIT(30)
+#	define OTGSC_1MSE		BIT(29)
+#	define OTGSC_BSEIE		BIT(28)
+#	define OTGSC_BSVIE		BIT(27)
+#	define OTGSC_ASVIE		BIT(26)
+#	define OTGSC_AVVIE		BIT(25)
+#	define OTGSC_IDIE		BIT(24)
+#	define OTGSC_DPIS		BIT(22)
+#	define OTGSC_1MSS		BIT(21)
+#	define OTGSC_BSEIS		BIT(20)
+#	define OTGSC_BSVIS		BIT(19)
+#	define OTGSC_ASVIS		BIT(18)
+#	define OTGSC_AVVIS		BIT(17)
+#	define OTGSC_IDIS		BIT(16)
+#	define OTGSC_DPS		BIT(14)
+#	define OTGSC_1MST		BIT(13)
+#	define OTGSC_BSE		BIT(12)
+#	define OTGSC_BSV		BIT(11)
+#	define OTGSC_ASV		BIT(10)
+#	define OTGSC_AVV		BIT(9)
+#	define OTGSC_ID			BIT(8)
+#	define OTGSC_HABA		BIT(7)
+#	define OTGSC_HADP		BIT(6)
+#	define OTGSC_IDPU		BIT(5)
+#	define OTGSC_DP			BIT(4)
+#	define OTGSC_OT			BIT(3)
+#	define OTGSC_HAAR		BIT(2)
+#	define OTGSC_VC			BIT(1)
+#	define OTGSC_VD			BIT(0)
+#	define OTGSC_INTEN_MASK		(0x7f << 24)
+#	define OTGSC_INT_MASK		(0x5f << 24)
+#	define OTGSC_INTSTS_MASK	(0x7f << 16)
+#define CI_USBMODE		0xf8
+#	define USBMODE_CM		(BIT(1) | BIT(0))
+#	define USBMODE_IDLE		0
+#	define USBMODE_DEVICE		0x2
+#	define USBMODE_HOST		0x3
+#define USBCFG_ADDR			0xff10801c
+#define USBCFG_LEN			4
+#	define USBCFG_VBUSVAL		BIT(14)
+#	define USBCFG_AVALID		BIT(13)
+#	define USBCFG_BVALID		BIT(12)
+#	define USBCFG_SESEND		BIT(11)
+
+#define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI)
+
+enum langwell_otg_timer_type {
+	TA_WAIT_VRISE_TMR,
+	TA_WAIT_BCON_TMR,
+	TA_AIDL_BDIS_TMR,
+	TB_ASE0_BRST_TMR,
+	TB_SE0_SRP_TMR,
+	TB_SRP_INIT_TMR,
+	TB_SRP_FAIL_TMR,
+	TB_BUS_SUSPEND_TMR
+};
+
+#define TA_WAIT_VRISE	100
+#define TA_WAIT_BCON	30000
+#define TA_AIDL_BDIS	15000
+#define TB_ASE0_BRST	5000
+#define TB_SE0_SRP	2
+#define TB_SRP_INIT	100
+#define TB_SRP_FAIL	5500
+#define TB_BUS_SUSPEND	500
+
+struct langwell_otg_timer {
+	unsigned long expires;	/* Number of count increase to timeout */
+	unsigned long count;	/* Tick counter */
+	void (*function)(unsigned long);	/* Timeout function */
+	unsigned long data;	/* Data passed to function */
+	struct list_head list;
+};
+
+struct langwell_otg {
+	struct intel_mid_otg_xceiv	iotg;
+	struct device			*dev;
+
+	void __iomem			*usbcfg;	/* SCCBUSB config Reg */
+
+	unsigned			region;
+	unsigned			cfg_region;
+
+	struct work_struct		work;
+	struct workqueue_struct		*qwork;
+	struct timer_list		hsm_timer;
+
+	spinlock_t			lock;
+	spinlock_t			wq_lock;
+
+	struct notifier_block		iotg_notifier;
+};
+
+static inline
+struct langwell_otg *mid_xceiv_to_lnw(struct intel_mid_otg_xceiv *iotg)
+{
+	return container_of(iotg, struct langwell_otg, iotg);
+}
+
+#endif /* __LANGWELL_OTG_H__ */
diff --git a/include/linux/usb/ncm.h b/include/linux/usb/ncm.h
deleted file mode 100644
index 006d106..0000000
--- a/include/linux/usb/ncm.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * USB CDC NCM auxiliary definitions
- */
-
-#ifndef __LINUX_USB_NCM_H
-#define __LINUX_USB_NCM_H
-
-#include <linux/types.h>
-#include <linux/usb/cdc.h>
-#include <asm/unaligned.h>
-
-#define NCM_NTB_MIN_IN_SIZE		2048
-#define NCM_NTB_MIN_OUT_SIZE		2048
-
-#define NCM_CONTROL_TIMEOUT		(5 * 1000)
-
-/* bmNetworkCapabilities */
-
-#define NCM_NCAP_ETH_FILTER	(1 << 0)
-#define NCM_NCAP_NET_ADDRESS	(1 << 1)
-#define NCM_NCAP_ENCAP_COMM	(1 << 2)
-#define NCM_NCAP_MAX_DGRAM	(1 << 3)
-#define NCM_NCAP_CRC_MODE	(1 << 4)
-
-/*
- * Here are options for NCM Datagram Pointer table (NDP) parser.
- * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3),
- * in NDP16 offsets and sizes fields are 1 16bit word wide,
- * in NDP32 -- 2 16bit words wide. Also signatures are different.
- * To make the parser code the same, put the differences in the structure,
- * and switch pointers to the structures when the format is changed.
- */
-
-struct ndp_parser_opts {
-	u32		nth_sign;
-	u32		ndp_sign;
-	unsigned	nth_size;
-	unsigned	ndp_size;
-	unsigned	ndplen_align;
-	/* sizes in u16 units */
-	unsigned	dgram_item_len; /* index or length */
-	unsigned	block_length;
-	unsigned	fp_index;
-	unsigned	reserved1;
-	unsigned	reserved2;
-	unsigned	next_fp_index;
-};
-
-#define INIT_NDP16_OPTS {					\
-		.nth_sign = NCM_NTH16_SIGN,			\
-		.ndp_sign = NCM_NDP16_NOCRC_SIGN,		\
-		.nth_size = sizeof(struct usb_cdc_ncm_nth16),	\
-		.ndp_size = sizeof(struct usb_cdc_ncm_ndp16),	\
-		.ndplen_align = 4,				\
-		.dgram_item_len = 1,				\
-		.block_length = 1,				\
-		.fp_index = 1,					\
-		.reserved1 = 0,					\
-		.reserved2 = 0,					\
-		.next_fp_index = 1,				\
-	}
-
-
-#define INIT_NDP32_OPTS {					\
-		.nth_sign = NCM_NTH32_SIGN,			\
-		.ndp_sign = NCM_NDP32_NOCRC_SIGN,		\
-		.nth_size = sizeof(struct usb_cdc_ncm_nth32),	\
-		.ndp_size = sizeof(struct usb_cdc_ncm_ndp32),	\
-		.ndplen_align = 8,				\
-		.dgram_item_len = 2,				\
-		.block_length = 2,				\
-		.fp_index = 2,					\
-		.reserved1 = 1,					\
-		.reserved2 = 2,					\
-		.next_fp_index = 2,				\
-	}
-
-static inline void put_ncm(__le16 **p, unsigned size, unsigned val)
-{
-	switch (size) {
-	case 1:
-		put_unaligned_le16((u16)val, *p);
-		break;
-	case 2:
-		put_unaligned_le32((u32)val, *p);
-
-		break;
-	default:
-		BUG();
-	}
-
-	*p += size;
-}
-
-static inline unsigned get_ncm(__le16 **p, unsigned size)
-{
-	unsigned tmp;
-
-	switch (size) {
-	case 1:
-		tmp = get_unaligned_le16(*p);
-		break;
-	case 2:
-		tmp = get_unaligned_le32(*p);
-		break;
-	default:
-		BUG();
-	}
-
-	*p += size;
-	return tmp;
-}
-
-#endif /* __LINUX_USB_NCM_H */
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 545cba7..0a5b371 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -164,8 +164,19 @@
 }
 
 /* for usb host and peripheral controller drivers */
+#ifdef CONFIG_USB_OTG_UTILS
 extern struct otg_transceiver *otg_get_transceiver(void);
 extern void otg_put_transceiver(struct otg_transceiver *);
+#else
+static inline struct otg_transceiver *otg_get_transceiver(void)
+{
+	return NULL;
+}
+
+static inline void otg_put_transceiver(struct otg_transceiver *x)
+{
+}
+#endif
 
 /* Context: can sleep */
 static inline int
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 55675b1..16d682f 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -271,6 +271,8 @@
 	int  (*tiocmget)(struct tty_struct *tty, struct file *file);
 	int  (*tiocmset)(struct tty_struct *tty, struct file *file,
 			 unsigned int set, unsigned int clear);
+	int  (*get_icount)(struct tty_struct *tty,
+			struct serial_icounter_struct *icount);
 	/* Called by the tty layer for port level work. There may or may not
 	   be an attached tty at this point */
 	void (*dtr_rts)(struct usb_serial_port *port, int on);
diff --git a/include/linux/usb/storage.h b/include/linux/usb/storage.h
new file mode 100644
index 0000000..d7fc910
--- /dev/null
+++ b/include/linux/usb/storage.h
@@ -0,0 +1,48 @@
+#ifndef __LINUX_USB_STORAGE_H
+#define __LINUX_USB_STORAGE_H
+
+/*
+ * linux/usb/storage.h
+ *
+ * Copyright Matthew Wilcox for Intel Corp, 2010
+ *
+ * This file contains definitions taken from the
+ * USB Mass Storage Class Specification Overview
+ *
+ * Distributed under the terms of the GNU GPL, version two.
+ */
+
+/* Storage subclass codes */
+
+#define USB_SC_RBC	0x01		/* Typically, flash devices */
+#define USB_SC_8020	0x02		/* CD-ROM */
+#define USB_SC_QIC	0x03		/* QIC-157 Tapes */
+#define USB_SC_UFI	0x04		/* Floppy */
+#define USB_SC_8070	0x05		/* Removable media */
+#define USB_SC_SCSI	0x06		/* Transparent */
+#define USB_SC_LOCKABLE	0x07		/* Password-protected */
+
+#define USB_SC_ISD200	0xf0		/* ISD200 ATA */
+#define USB_SC_CYP_ATACB	0xf1	/* Cypress ATACB */
+#define USB_SC_DEVICE	0xff		/* Use device's value */
+
+/* Storage protocol codes */
+
+#define USB_PR_CBI	0x00		/* Control/Bulk/Interrupt */
+#define USB_PR_CB	0x01		/* Control/Bulk w/o interrupt */
+#define USB_PR_BULK	0x50		/* bulk only */
+#define USB_PR_UAS	0x62		/* USB Attached SCSI */
+
+#define USB_PR_USBAT	0x80		/* SCM-ATAPI bridge */
+#define USB_PR_EUSB_SDDR09	0x81	/* SCM-SCSI bridge for SDDR-09 */
+#define USB_PR_SDDR55	0x82		/* SDDR-55 (made up) */
+#define USB_PR_DPCM_USB	0xf0		/* Combination CB/SDDR09 */
+#define USB_PR_FREECOM	0xf1		/* Freecom */
+#define USB_PR_DATAFAB	0xf2		/* Datafab chipsets */
+#define USB_PR_JUMPSHOT	0xf3		/* Lexar Jumpshot */
+#define USB_PR_ALAUDA	0xf4		/* Alauda chipsets */
+#define USB_PR_KARMA	0xf5		/* Rio Karma */
+
+#define USB_PR_DEVICE	0xff		/* Use device's value */
+
+#endif
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index a4b947e..71693d4 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -58,7 +58,11 @@
 	US_FLAG(CAPACITY_OK,	0x00010000)			\
 		/* READ CAPACITY response is correct */		\
 	US_FLAG(BAD_SENSE,	0x00020000)			\
-		/* Bad Sense (never more than 18 bytes) */
+		/* Bad Sense (never more than 18 bytes) */	\
+	US_FLAG(NO_READ_DISC_INFO,	0x00040000)		\
+		/* cannot handle READ_DISC_INFO */		\
+	US_FLAG(NO_READ_CAPACITY_16,	0x00080000)		\
+		/* cannot handle READ_CAPACITY_16 */
 
 #define US_FLAG(name, value)	US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
@@ -74,42 +78,7 @@
 #define USB_US_TYPE(flags) 		(((flags) >> 24) & 0xFF)
 #define USB_US_ORIG_FLAGS(flags)	((flags) & 0x00FFFFFF)
 
-/*
- * This is probably not the best place to keep these constants, conceptually.
- * But it's the only header included into all places which need them.
- */
-
-/* Sub Classes */
-
-#define US_SC_RBC	0x01		/* Typically, flash devices */
-#define US_SC_8020	0x02		/* CD-ROM */
-#define US_SC_QIC	0x03		/* QIC-157 Tapes */
-#define US_SC_UFI	0x04		/* Floppy */
-#define US_SC_8070	0x05		/* Removable media */
-#define US_SC_SCSI	0x06		/* Transparent */
-#define US_SC_LOCKABLE	0x07		/* Password-protected */
-
-#define US_SC_ISD200    0xf0		/* ISD200 ATA */
-#define US_SC_CYP_ATACB 0xf1		/* Cypress ATACB */
-#define US_SC_DEVICE	0xff		/* Use device's value */
-
-/* Protocols */
-
-#define US_PR_CBI	0x00		/* Control/Bulk/Interrupt */
-#define US_PR_CB	0x01		/* Control/Bulk w/o interrupt */
-#define US_PR_BULK	0x50		/* bulk only */
-
-#define US_PR_USBAT	0x80		/* SCM-ATAPI bridge */
-#define US_PR_EUSB_SDDR09	0x81	/* SCM-SCSI bridge for SDDR-09 */
-#define US_PR_SDDR55	0x82		/* SDDR-55 (made up) */
-#define US_PR_DPCM_USB  0xf0		/* Combination CB/SDDR09 */
-#define US_PR_FREECOM   0xf1		/* Freecom */
-#define US_PR_DATAFAB   0xf2		/* Datafab chipsets */
-#define US_PR_JUMPSHOT  0xf3		/* Lexar Jumpshot */
-#define US_PR_ALAUDA    0xf4		/* Alauda chipsets */
-#define US_PR_KARMA     0xf5		/* Rio Karma */
-
-#define US_PR_DEVICE	0xff		/* Use device's value */
+#include <linux/usb/storage.h>
 
 /*
  */
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 01c2145..63a4fe6 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -117,10 +117,12 @@
 extern struct vm_struct *vmlist;
 extern __init void vm_area_register_early(struct vm_struct *vm, size_t align);
 
+#ifdef CONFIG_SMP
 struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
 				     const size_t *sizes, int nr_vms,
 				     size_t align, gfp_t gfp_mask);
 
 void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms);
+#endif
 
 #endif /* _LINUX_VMALLOC_H */
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 0836ccc..3efc9f3 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -614,6 +614,7 @@
 		(wait)->private = current;				\
 		(wait)->func = autoremove_wake_function;		\
 		INIT_LIST_HEAD(&(wait)->task_list);			\
+		(wait)->flags = 0;					\
 	} while (0)
 
 /**
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index e6827ee..4395b28 100644
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -1157,6 +1157,6 @@
 #define IW_EV_PARAM_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(struct iw_param))
 #define IW_EV_ADDR_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(struct sockaddr))
 #define IW_EV_QUAL_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(struct iw_quality))
-#define IW_EV_POINT_PK_LEN	(IW_EV_LCP_LEN + 4)
+#define IW_EV_POINT_PK_LEN	(IW_EV_LCP_PK_LEN + 4)
 
 #endif	/* _LINUX_WIRELESS_H */
diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h
new file mode 100644
index 0000000..4f902e1
--- /dev/null
+++ b/include/linux/wl12xx.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@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
+ *
+ */
+
+#ifndef _LINUX_WL12XX_H
+#define _LINUX_WL12XX_H
+
+struct wl12xx_platform_data {
+	void (*set_power)(bool enable);
+	/* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */
+	int irq;
+	bool use_eeprom;
+	int board_ref_clock;
+};
+
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+
+int wl12xx_set_platform_data(const struct wl12xx_platform_data *data);
+
+#else
+
+static inline
+int wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
+{
+	return -ENOSYS;
+}
+
+#endif
+
+const struct wl12xx_platform_data *wl12xx_get_platform_data(void);
+
+#endif
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 25e02c9..070bb7a 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -243,11 +243,12 @@
 	WQ_NON_REENTRANT	= 1 << 0, /* guarantee non-reentrance */
 	WQ_UNBOUND		= 1 << 1, /* not bound to any cpu */
 	WQ_FREEZEABLE		= 1 << 2, /* freeze during suspend */
-	WQ_RESCUER		= 1 << 3, /* has an rescue worker */
+	WQ_MEM_RECLAIM		= 1 << 3, /* may be used for memory reclaim */
 	WQ_HIGHPRI		= 1 << 4, /* high priority */
 	WQ_CPU_INTENSIVE	= 1 << 5, /* cpu instensive workqueue */
 
 	WQ_DYING		= 1 << 6, /* internal: workqueue is dying */
+	WQ_RESCUER		= 1 << 7, /* internal: workqueue has rescuer */
 
 	WQ_MAX_ACTIVE		= 512,	  /* I like 512, better ideas? */
 	WQ_MAX_UNBOUND_PER_CPU	= 4,	  /* 4 * #cpus for unbound wq */
@@ -306,12 +307,30 @@
 	__alloc_workqueue_key((name), (flags), (max_active), NULL, NULL)
 #endif
 
+/**
+ * alloc_ordered_workqueue - allocate an ordered workqueue
+ * @name: name of the workqueue
+ * @flags: WQ_* flags (only WQ_FREEZEABLE and WQ_MEM_RECLAIM are meaningful)
+ *
+ * Allocate an ordered workqueue.  An ordered workqueue executes at
+ * most one work item at any given time in the queued order.  They are
+ * implemented as unbound workqueues with @max_active of one.
+ *
+ * RETURNS:
+ * Pointer to the allocated workqueue on success, %NULL on failure.
+ */
+static inline struct workqueue_struct *
+alloc_ordered_workqueue(const char *name, unsigned int flags)
+{
+	return alloc_workqueue(name, WQ_UNBOUND | flags, 1);
+}
+
 #define create_workqueue(name)					\
-	alloc_workqueue((name), WQ_RESCUER, 1)
+	alloc_workqueue((name), WQ_MEM_RECLAIM, 1)
 #define create_freezeable_workqueue(name)			\
-	alloc_workqueue((name), WQ_FREEZEABLE | WQ_UNBOUND | WQ_RESCUER, 1)
+	alloc_workqueue((name), WQ_FREEZEABLE | WQ_UNBOUND | WQ_MEM_RECLAIM, 1)
 #define create_singlethread_workqueue(name)			\
-	alloc_workqueue((name), WQ_UNBOUND | WQ_RESCUER, 1)
+	alloc_workqueue((name), WQ_UNBOUND | WQ_MEM_RECLAIM, 1)
 
 extern void destroy_workqueue(struct workqueue_struct *wq);
 
@@ -325,7 +344,6 @@
 
 extern void flush_workqueue(struct workqueue_struct *wq);
 extern void flush_scheduled_work(void);
-extern void flush_delayed_work(struct delayed_work *work);
 
 extern int schedule_work(struct work_struct *work);
 extern int schedule_work_on(int cpu, struct work_struct *work);
@@ -337,8 +355,13 @@
 
 int execute_in_process_context(work_func_t fn, struct execute_work *);
 
-extern int flush_work(struct work_struct *work);
-extern int cancel_work_sync(struct work_struct *work);
+extern bool flush_work(struct work_struct *work);
+extern bool flush_work_sync(struct work_struct *work);
+extern bool cancel_work_sync(struct work_struct *work);
+
+extern bool flush_delayed_work(struct delayed_work *dwork);
+extern bool flush_delayed_work_sync(struct delayed_work *work);
+extern bool cancel_delayed_work_sync(struct delayed_work *dwork);
 
 extern void workqueue_set_max_active(struct workqueue_struct *wq,
 				     int max_active);
@@ -352,9 +375,9 @@
  * it returns 1 and the work doesn't re-arm itself. Run flush_workqueue() or
  * cancel_work_sync() to wait on it.
  */
-static inline int cancel_delayed_work(struct delayed_work *work)
+static inline bool cancel_delayed_work(struct delayed_work *work)
 {
-	int ret;
+	bool ret;
 
 	ret = del_timer_sync(&work->timer);
 	if (ret)
@@ -367,9 +390,9 @@
  * if it returns 0 the timer function may be running and the queueing is in
  * progress.
  */
-static inline int __cancel_delayed_work(struct delayed_work *work)
+static inline bool __cancel_delayed_work(struct delayed_work *work)
 {
-	int ret;
+	bool ret;
 
 	ret = del_timer(&work->timer);
 	if (ret)
@@ -377,8 +400,6 @@
 	return ret;
 }
 
-extern int cancel_delayed_work_sync(struct delayed_work *work);
-
 /* Obsolete. use cancel_delayed_work_sync() */
 static inline
 void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
@@ -409,8 +430,4 @@
 extern void thaw_workqueues(void);
 #endif /* CONFIG_FREEZER */
 
-#ifdef CONFIG_LOCKDEP
-int in_workqueue_context(struct workqueue_struct *wq);
-#endif
-
 #endif
diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h
index 97e07f4..aa4ebb4 100644
--- a/include/media/videobuf-dma-sg.h
+++ b/include/media/videobuf-dma-sg.h
@@ -48,6 +48,7 @@
 
 	/* for userland buffer */
 	int                 offset;
+	size_t		    size;
 	struct page         **pages;
 
 	/* for kernel buffers */
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index d1aa2cf..7f63d5a 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -212,15 +212,12 @@
 
 int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb);
 int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name);
-int p9_client_version(struct p9_client *);
 struct p9_client *p9_client_create(const char *dev_name, char *options);
 void p9_client_destroy(struct p9_client *clnt);
 void p9_client_disconnect(struct p9_client *clnt);
 void p9_client_begin_disconnect(struct p9_client *clnt);
 struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
 					char *uname, u32 n_uname, char *aname);
-struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname,
-						u32 n_uname, char *aname);
 struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
 								int clone);
 int p9_client_open(struct p9_fid *fid, int mode);
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 45375b4..a944124 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -121,6 +121,7 @@
  *	IPv6 Address Label subsystem (addrlabel.c)
  */
 extern int			ipv6_addr_label_init(void);
+extern void			ipv6_addr_label_cleanup(void);
 extern void			ipv6_addr_label_rtnl_register(void);
 extern u32			ipv6_addr_label(struct net *net,
 						const struct in6_addr *addr,
@@ -174,20 +175,32 @@
 extern int register_inet6addr_notifier(struct notifier_block *nb);
 extern int unregister_inet6addr_notifier(struct notifier_block *nb);
 
-static inline struct inet6_dev *
-__in6_dev_get(struct net_device *dev)
+/**
+ * __in6_dev_get - get inet6_dev pointer from netdevice
+ * @dev: network device
+ *
+ * Caller must hold rcu_read_lock or RTNL, because this function
+ * does not take a reference on the inet6_dev.
+ */
+static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)
 {
-	return rcu_dereference_check(dev->ip6_ptr,
-				     rcu_read_lock_held() ||
-				     lockdep_rtnl_is_held());
+	return rcu_dereference_rtnl(dev->ip6_ptr);
 }
 
-static inline struct inet6_dev *
-in6_dev_get(struct net_device *dev)
+/**
+ * in6_dev_get - get inet6_dev pointer from netdevice
+ * @dev: network device
+ *
+ * This version can be used in any context, and takes a reference
+ * on the inet6_dev. Callers must use in6_dev_put() later to
+ * release this reference.
+ */
+static inline struct inet6_dev *in6_dev_get(const struct net_device *dev)
 {
-	struct inet6_dev *idev = NULL;
+	struct inet6_dev *idev;
+
 	rcu_read_lock();
-	idev = __in6_dev_get(dev);
+	idev = rcu_dereference(dev->ip6_ptr);
 	if (idev)
 		atomic_inc(&idev->refcnt);
 	rcu_read_unlock();
@@ -196,16 +209,21 @@
 
 extern void in6_dev_finish_destroy(struct inet6_dev *idev);
 
-static inline void
-in6_dev_put(struct inet6_dev *idev)
+static inline void in6_dev_put(struct inet6_dev *idev)
 {
 	if (atomic_dec_and_test(&idev->refcnt))
 		in6_dev_finish_destroy(idev);
 }
 
-#define __in6_dev_put(idev)  atomic_dec(&(idev)->refcnt)
-#define in6_dev_hold(idev)   atomic_inc(&(idev)->refcnt)
+static inline void __in6_dev_put(struct inet6_dev *idev)
+{
+	atomic_dec(&idev->refcnt);
+}
 
+static inline void in6_dev_hold(struct inet6_dev *idev)
+{
+	atomic_inc(&idev->refcnt);
+}
 
 extern void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
 
@@ -215,9 +233,15 @@
 		inet6_ifa_finish_destroy(ifp);
 }
 
-#define __in6_ifa_put(ifp)	atomic_dec(&(ifp)->refcnt)
-#define in6_ifa_hold(ifp)	atomic_inc(&(ifp)->refcnt)
+static inline void __in6_ifa_put(struct inet6_ifaddr *ifp)
+{
+	atomic_dec(&ifp->refcnt);
+}
 
+static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
+{
+	atomic_inc(&ifp->refcnt);
+}
 
 
 /*
@@ -240,23 +264,21 @@
 
 static inline int ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
 {
-	return (((addr->s6_addr32[0] ^ htonl(0xff020000)) |
+	return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
 		addr->s6_addr32[1] | addr->s6_addr32[2] |
-		(addr->s6_addr32[3] ^ htonl(0x00000001))) == 0);
+		(addr->s6_addr32[3] ^ htonl(0x00000001))) == 0;
 }
 
 static inline int ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)
 {
-	return (((addr->s6_addr32[0] ^ htonl(0xff020000)) |
+	return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
 		addr->s6_addr32[1] | addr->s6_addr32[2] |
-		(addr->s6_addr32[3] ^ htonl(0x00000002))) == 0);
+		(addr->s6_addr32[3] ^ htonl(0x00000002))) == 0;
 }
 
-extern int __ipv6_isatap_ifid(u8 *eui, __be32 addr);
-
 static inline int ipv6_addr_is_isatap(const struct in6_addr *addr)
 {
-	return ((addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE));
+	return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
 }
 
 #ifdef CONFIG_PROC_FS
diff --git a/include/net/arp.h b/include/net/arp.h
index 716f43c..f4cf6ce 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -26,6 +26,4 @@
 				  const unsigned char *target_hw);
 extern void arp_xmit(struct sk_buff *skb);
 
-extern const struct neigh_ops arp_broken_ops;
-
 #endif	/* _ARP_H */
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 27a902d..d81ea79 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -126,6 +126,8 @@
 void bt_sock_link(struct bt_sock_list *l, struct sock *s);
 void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
 int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
+int  bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
+			struct msghdr *msg, size_t len, int flags);
 uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
 int  bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
 int  bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
@@ -161,12 +163,30 @@
 {
 	struct sk_buff *skb;
 
+	release_sock(sk);
 	if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) {
 		skb_reserve(skb, BT_SKB_RESERVE);
 		bt_cb(skb)->incoming  = 0;
 	}
+	lock_sock(sk);
+
+	if (!skb && *err)
+		return NULL;
+
+	*err = sock_error(sk);
+	if (*err)
+		goto out;
+
+	if (sk->sk_shutdown) {
+		*err = -ECONNRESET;
+		goto out;
+	}
 
 	return skb;
+
+out:
+	kfree_skb(skb);
+	return NULL;
 }
 
 int bt_err(__u16 code);
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index bcbdd6d..e30e008 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -54,7 +54,7 @@
 
 /* HCI controller types */
 #define HCI_BREDR	0x00
-#define HCI_80211	0x01
+#define HCI_AMP		0x01
 
 /* HCI device quirks */
 enum {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4568b93..ebec8c9 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -233,7 +233,7 @@
 static inline int inquiry_cache_empty(struct hci_dev *hdev)
 {
 	struct inquiry_cache *c = &hdev->inq_cache;
-	return (c->list == NULL);
+	return c->list == NULL;
 }
 
 static inline long inquiry_cache_age(struct hci_dev *hdev)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 6c24144..c819c8b 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -414,7 +414,7 @@
 	if (sub < 0)
 		sub += 64;
 
-	return (sub == pi->remote_tx_win);
+	return sub == pi->remote_tx_win;
 }
 
 #define __get_txseq(ctrl) ((ctrl) & L2CAP_CTRL_TXSEQ) >> 1
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index a140847..71047bc 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -213,11 +213,6 @@
 #define RFCOMM_DEFER_SETUP  8
 
 /* Scheduling flags and events */
-#define RFCOMM_SCHED_STATE  0
-#define RFCOMM_SCHED_RX     1
-#define RFCOMM_SCHED_TX     2
-#define RFCOMM_SCHED_TIMEO  3
-#define RFCOMM_SCHED_AUTH   4
 #define RFCOMM_SCHED_WAKEUP 31
 
 /* MSC exchange flags */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2fd06c6..2a7936d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -25,6 +25,43 @@
 #include <linux/wireless.h>
 
 
+/**
+ * DOC: Introduction
+ *
+ * cfg80211 is the configuration API for 802.11 devices in Linux. It bridges
+ * userspace and drivers, and offers some utility functionality associated
+ * with 802.11. cfg80211 must, directly or indirectly via mac80211, be used
+ * by all modern wireless drivers in Linux, so that they offer a consistent
+ * API through nl80211. For backward compatibility, cfg80211 also offers
+ * wireless extensions to userspace, but hides them from drivers completely.
+ *
+ * Additionally, cfg80211 contains code to help enforce regulatory spectrum
+ * use restrictions.
+ */
+
+
+/**
+ * DOC: Device registration
+ *
+ * In order for a driver to use cfg80211, it must register the hardware device
+ * with cfg80211. This happens through a number of hardware capability structs
+ * described below.
+ *
+ * The fundamental structure for each device is the 'wiphy', of which each
+ * instance describes a physical wireless device connected to the system. Each
+ * such wiphy can have zero, one, or many virtual interfaces associated with
+ * it, which need to be identified as such by pointing the network interface's
+ * @ieee80211_ptr pointer to a &struct wireless_dev which further describes
+ * the wireless part of the interface, normally this struct is embedded in the
+ * network interface's private data area. Drivers can optionally allow creating
+ * or destroying virtual interfaces on the fly, but without at least one or the
+ * ability to create some the wireless device isn't useful.
+ *
+ * Each wiphy structure contains device capability information, and also has
+ * a pointer to the various operations the driver offers. The definitions and
+ * structures here describe these capabilities in detail.
+ */
+
 /*
  * wireless hardware capability structures
  */
@@ -205,6 +242,21 @@
  */
 
 /**
+ * DOC: Actions and configuration
+ *
+ * Each wireless device and each virtual interface offer a set of configuration
+ * operations and other actions that are invoked by userspace. Each of these
+ * actions is described in the operations structure, and the parameters these
+ * operations use are described separately.
+ *
+ * Additionally, some operations are asynchronous and expect to get status
+ * information via some functions that drivers need to call.
+ *
+ * Scanning and BSS list handling with its associated functionality is described
+ * in a separate chapter.
+ */
+
+/**
  * struct vif_params - describes virtual interface parameters
  * @mesh_id: mesh ID to use
  * @mesh_id_len: length of the mesh ID
@@ -241,12 +293,24 @@
  * enum survey_info_flags - survey information flags
  *
  * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in
+ * @SURVEY_INFO_IN_USE: channel is currently being used
+ * @SURVEY_INFO_CHANNEL_TIME: channel active time (in ms) was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_BUSY: channel busy time was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: extension channel busy time was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_RX: channel receive time was filled in
+ * @SURVEY_INFO_CHANNEL_TIME_TX: channel transmit time was filled in
  *
  * Used by the driver to indicate which info in &struct survey_info
  * it has filled in during the get_survey().
  */
 enum survey_info_flags {
 	SURVEY_INFO_NOISE_DBM = 1<<0,
+	SURVEY_INFO_IN_USE = 1<<1,
+	SURVEY_INFO_CHANNEL_TIME = 1<<2,
+	SURVEY_INFO_CHANNEL_TIME_BUSY = 1<<3,
+	SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 1<<4,
+	SURVEY_INFO_CHANNEL_TIME_RX = 1<<5,
+	SURVEY_INFO_CHANNEL_TIME_TX = 1<<6,
 };
 
 /**
@@ -256,6 +320,11 @@
  * @filled: bitflag of flags from &enum survey_info_flags
  * @noise: channel noise in dBm. This and all following fields are
  *     optional
+ * @channel_time: amount of time in ms the radio spent on the channel
+ * @channel_time_busy: amount of time the primary channel was sensed busy
+ * @channel_time_ext_busy: amount of time the extension channel was sensed busy
+ * @channel_time_rx: amount of time the radio spent receiving data
+ * @channel_time_tx: amount of time the radio spent transmitting data
  *
  * Used by dump_survey() to report back per-channel survey information.
  *
@@ -264,6 +333,11 @@
  */
 struct survey_info {
 	struct ieee80211_channel *channel;
+	u64 channel_time;
+	u64 channel_time_busy;
+	u64 channel_time_ext_busy;
+	u64 channel_time_rx;
+	u64 channel_time_tx;
 	u32 filled;
 	s8 noise;
 };
@@ -347,6 +421,9 @@
  *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  * @STATION_INFO_RX_PACKETS: @rx_packets filled
  * @STATION_INFO_TX_PACKETS: @tx_packets filled
+ * @STATION_INFO_TX_RETRIES: @tx_retries filled
+ * @STATION_INFO_TX_FAILED: @tx_failed filled
+ * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -359,6 +436,9 @@
 	STATION_INFO_TX_BITRATE		= 1<<7,
 	STATION_INFO_RX_PACKETS		= 1<<8,
 	STATION_INFO_TX_PACKETS		= 1<<9,
+	STATION_INFO_TX_RETRIES		= 1<<10,
+	STATION_INFO_TX_FAILED		= 1<<11,
+	STATION_INFO_RX_DROP_MISC	= 1<<12,
 };
 
 /**
@@ -408,6 +488,9 @@
  * @txrate: current unicast bitrate to this station
  * @rx_packets: packets received from this station
  * @tx_packets: packets transmitted to this station
+ * @tx_retries: cumulative retry counts
+ * @tx_failed: number of failed transmissions (retries exceeded, no ACK)
+ * @rx_dropped_misc:  Dropped for un-specified reason.
  * @generation: generation number for nl80211 dumps.
  *	This number should increase every time the list of stations
  *	changes, i.e. when a station is added or removed, so that
@@ -425,6 +508,9 @@
 	struct rate_info txrate;
 	u32 rx_packets;
 	u32 tx_packets;
+	u32 tx_retries;
+	u32 tx_failed;
+	u32 rx_dropped_misc;
 
 	int generation;
 };
@@ -570,8 +656,28 @@
 /* from net/wireless.h */
 struct wiphy;
 
-/* from net/ieee80211.h */
-struct ieee80211_channel;
+/**
+ * DOC: Scanning and BSS list handling
+ *
+ * The scanning process itself is fairly simple, but cfg80211 offers quite
+ * a bit of helper functionality. To start a scan, the scan operation will
+ * be invoked with a scan definition. This scan definition contains the
+ * channels to scan, and the SSIDs to send probe requests for (including the
+ * wildcard, if desired). A passive scan is indicated by having no SSIDs to
+ * probe. Additionally, a scan request may contain extra information elements
+ * that should be added to the probe request. The IEs are guaranteed to be
+ * well-formed, and will not exceed the maximum length the driver advertised
+ * in the wiphy structure.
+ *
+ * When scanning finds a BSS, cfg80211 needs to be notified of that, because
+ * it is responsible for maintaining the BSS list; the driver should not
+ * maintain a list itself. For this notification, various functions exist.
+ *
+ * Since drivers do not maintain a BSS list, there are also a number of
+ * functions to search for a BSS and obtain information about it from the
+ * BSS structure cfg80211 maintains. The BSS list is also made available
+ * to userspace.
+ */
 
 /**
  * struct cfg80211_ssid - SSID description
@@ -691,6 +797,10 @@
  *	sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
  *	required to assume that the port is unauthorized until authorized by
  *	user space. Otherwise, port is marked authorized by default.
+ * @control_port_ethertype: the control port protocol that should be
+ *	allowed through even on unauthorized ports
+ * @control_port_no_encrypt: TRUE to prevent encryption of control port
+ *	protocol frames.
  */
 struct cfg80211_crypto_settings {
 	u32 wpa_versions;
@@ -700,6 +810,8 @@
 	int n_akm_suites;
 	u32 akm_suites[NL80211_MAX_NR_AKM_SUITES];
 	bool control_port;
+	__be16 control_port_ethertype;
+	bool control_port_no_encrypt;
 };
 
 /**
@@ -1020,7 +1132,7 @@
  * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation.
  *	This allows the operation to be terminated prior to timeout based on
  *	the duration value.
- * @action: Transmit an action frame
+ * @mgmt_tx: Transmit a management frame
  *
  * @testmode_cmd: run a test mode command
  *
@@ -1035,6 +1147,9 @@
  *	allows the driver to adjust the dynamic ps timeout value.
  * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold.
  *
+ * @mgmt_frame_register: Notify driver that a management frame type was
+ *	registered. Note that this callback may not sleep, and cannot run
+ *	concurrently with itself.
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy);
@@ -1050,13 +1165,14 @@
 				       struct vif_params *params);
 
 	int	(*add_key)(struct wiphy *wiphy, struct net_device *netdev,
-			   u8 key_index, const u8 *mac_addr,
+			   u8 key_index, bool pairwise, const u8 *mac_addr,
 			   struct key_params *params);
 	int	(*get_key)(struct wiphy *wiphy, struct net_device *netdev,
-			   u8 key_index, const u8 *mac_addr, void *cookie,
+			   u8 key_index, bool pairwise, const u8 *mac_addr,
+			   void *cookie,
 			   void (*callback)(void *cookie, struct key_params*));
 	int	(*del_key)(struct wiphy *wiphy, struct net_device *netdev,
-			   u8 key_index, const u8 *mac_addr);
+			   u8 key_index, bool pairwise, const u8 *mac_addr);
 	int	(*set_default_key)(struct wiphy *wiphy,
 				   struct net_device *netdev,
 				   u8 key_index);
@@ -1140,7 +1256,7 @@
 	int	(*get_tx_power)(struct wiphy *wiphy, int *dbm);
 
 	int	(*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
-				u8 *addr);
+				const u8 *addr);
 
 	void	(*rfkill_poll)(struct wiphy *wiphy);
 
@@ -1172,7 +1288,7 @@
 					    struct net_device *dev,
 					    u64 cookie);
 
-	int	(*action)(struct wiphy *wiphy, struct net_device *dev,
+	int	(*mgmt_tx)(struct wiphy *wiphy, struct net_device *dev,
 			  struct ieee80211_channel *chan,
 			  enum nl80211_channel_type channel_type,
 			  bool channel_type_valid,
@@ -1184,6 +1300,10 @@
 	int	(*set_cqm_rssi_config)(struct wiphy *wiphy,
 				       struct net_device *dev,
 				       s32 rssi_thold, u32 rssi_hyst);
+
+	void	(*mgmt_frame_register)(struct wiphy *wiphy,
+				       struct net_device *dev,
+				       u16 frame_type, bool reg);
 };
 
 /*
@@ -1221,21 +1341,31 @@
  * @WIPHY_FLAG_4ADDR_AP: supports 4addr mode even on AP (with a single station
  *	on a VLAN interface)
  * @WIPHY_FLAG_4ADDR_STATION: supports 4addr mode even as a station
+ * @WIPHY_FLAG_CONTROL_PORT_PROTOCOL: This device supports setting the
+ *	control port protocol ethertype. The device also honours the
+ *	control_port_no_encrypt flag.
+ * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN.
  */
 enum wiphy_flags {
-	WIPHY_FLAG_CUSTOM_REGULATORY	= BIT(0),
-	WIPHY_FLAG_STRICT_REGULATORY	= BIT(1),
-	WIPHY_FLAG_DISABLE_BEACON_HINTS	= BIT(2),
-	WIPHY_FLAG_NETNS_OK		= BIT(3),
-	WIPHY_FLAG_PS_ON_BY_DEFAULT	= BIT(4),
-	WIPHY_FLAG_4ADDR_AP		= BIT(5),
-	WIPHY_FLAG_4ADDR_STATION	= BIT(6),
+	WIPHY_FLAG_CUSTOM_REGULATORY		= BIT(0),
+	WIPHY_FLAG_STRICT_REGULATORY		= BIT(1),
+	WIPHY_FLAG_DISABLE_BEACON_HINTS		= BIT(2),
+	WIPHY_FLAG_NETNS_OK			= BIT(3),
+	WIPHY_FLAG_PS_ON_BY_DEFAULT		= BIT(4),
+	WIPHY_FLAG_4ADDR_AP			= BIT(5),
+	WIPHY_FLAG_4ADDR_STATION		= BIT(6),
+	WIPHY_FLAG_CONTROL_PORT_PROTOCOL	= BIT(7),
+	WIPHY_FLAG_IBSS_RSN			= BIT(7),
 };
 
 struct mac_address {
 	u8 addr[ETH_ALEN];
 };
 
+struct ieee80211_txrx_stypes {
+	u16 tx, rx;
+};
+
 /**
  * struct wiphy - wireless hardware description
  * @reg_notifier: the driver's regulatory notification callback
@@ -1286,6 +1416,10 @@
  * @privid: a pointer that drivers can use to identify if an arbitrary
  *	wiphy is theirs, e.g. in global notifiers
  * @bands: information about bands/channels supported by this device
+ *
+ * @mgmt_stypes: bitmasks of frame subtypes that can be subscribed to or
+ *	transmitted through nl80211, points to an array indexed by interface
+ *	type
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -1294,9 +1428,12 @@
 	u8 perm_addr[ETH_ALEN];
 	u8 addr_mask[ETH_ALEN];
 
-	u16 n_addresses;
 	struct mac_address *addresses;
 
+	const struct ieee80211_txrx_stypes *mgmt_stypes;
+
+	u16 n_addresses;
+
 	/* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
 	u16 interface_modes;
 
@@ -1492,8 +1629,8 @@
  *	set by driver (if supported) on add_interface BEFORE registering the
  *	netdev and may otherwise be used by driver read-only, will be update
  *	by cfg80211 on change_interface
- * @action_registrations: list of registrations for action frames
- * @action_registrations_lock: lock for the list
+ * @mgmt_registrations: list of registrations for management frames
+ * @mgmt_registrations_lock: lock for the list
  * @mtx: mutex used to lock data in this struct
  * @cleanup_work: work struct used for cleanup that can't be done directly
  */
@@ -1505,8 +1642,8 @@
 	struct list_head list;
 	struct net_device *netdev;
 
-	struct list_head action_registrations;
-	spinlock_t action_registrations_lock;
+	struct list_head mgmt_registrations;
+	spinlock_t mgmt_registrations_lock;
 
 	struct mutex mtx;
 
@@ -1563,8 +1700,10 @@
 	return wiphy_priv(wdev->wiphy);
 }
 
-/*
- * Utility functions
+/**
+ * DOC: Utility functions
+ *
+ * cfg80211 offers a number of utility functions that can be useful.
  */
 
 /**
@@ -1715,7 +1854,15 @@
  * ieee80211_hdrlen - get header length in bytes from frame control
  * @fc: frame control field in little-endian format
  */
-unsigned int ieee80211_hdrlen(__le16 fc);
+unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
+
+/**
+ * DOC: Data path helpers
+ *
+ * In addition to generic utilities, cfg80211 also offers
+ * functions that help implement the data path for devices
+ * that do not do the 802.11/802.3 conversion on the device.
+ */
 
 /**
  * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
@@ -1777,8 +1924,10 @@
  */
 const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len);
 
-/*
- * Regulatory helper functions for wiphys
+/**
+ * DOC: Regulatory enforcement infrastructure
+ *
+ * TODO
  */
 
 /**
@@ -2181,6 +2330,20 @@
 void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
 
 /**
+ * DOC: RFkill integration
+ *
+ * RFkill integration in cfg80211 is almost invisible to drivers,
+ * as cfg80211 automatically registers an rfkill instance for each
+ * wireless device it knows about. Soft kill is also translated
+ * into disconnecting and turning all interfaces off, drivers are
+ * expected to turn off the device when all interfaces are down.
+ *
+ * However, devices may have a hard RFkill line, in which case they
+ * also need to interact with the rfkill subsystem, via cfg80211.
+ * They can do this with a few helper functions documented here.
+ */
+
+/**
  * wiphy_rfkill_set_hw_state - notify cfg80211 about hw block state
  * @wiphy: the wiphy
  * @blocked: block status
@@ -2201,6 +2364,17 @@
 
 #ifdef CONFIG_NL80211_TESTMODE
 /**
+ * DOC: Test mode
+ *
+ * Test mode is a set of utility functions to allow drivers to
+ * interact with driver-specific tools to aid, for instance,
+ * factory programming.
+ *
+ * This chapter describes how drivers interact with it, for more
+ * information see the nl80211 book's chapter on it.
+ */
+
+/**
  * cfg80211_testmode_alloc_reply_skb - allocate testmode reply
  * @wiphy: the wiphy
  * @approxlen: an upper bound of the length of the data that will
@@ -2373,38 +2547,39 @@
 		      struct station_info *sinfo, gfp_t gfp);
 
 /**
- * cfg80211_rx_action - notification of received, unprocessed Action frame
+ * cfg80211_rx_mgmt - notification of received, unprocessed management frame
  * @dev: network device
  * @freq: Frequency on which the frame was received in MHz
- * @buf: Action frame (header + body)
+ * @buf: Management frame (header + body)
  * @len: length of the frame data
  * @gfp: context flags
- * Returns %true if a user space application is responsible for rejecting the
- *	unrecognized Action frame; %false if no such application is registered
- *	(i.e., the driver is responsible for rejecting the unrecognized Action
- *	frame)
+ *
+ * Returns %true if a user space application has registered for this frame.
+ * For action frames, that makes it responsible for rejecting unrecognized
+ * action frames; %false otherwise, in which case for action frames the
+ * driver is responsible for rejecting the frame.
  *
  * This function is called whenever an Action frame is received for a station
  * mode interface, but is not processed in kernel.
  */
-bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf,
-			size_t len, gfp_t gfp);
+bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
+		      size_t len, gfp_t gfp);
 
 /**
- * cfg80211_action_tx_status - notification of TX status for Action frame
+ * cfg80211_mgmt_tx_status - notification of TX status for management frame
  * @dev: network device
- * @cookie: Cookie returned by cfg80211_ops::action()
- * @buf: Action frame (header + body)
+ * @cookie: Cookie returned by cfg80211_ops::mgmt_tx()
+ * @buf: Management frame (header + body)
  * @len: length of the frame data
  * @ack: Whether frame was acknowledged
  * @gfp: context flags
  *
- * This function is called whenever an Action frame was requested to be
- * transmitted with cfg80211_ops::action() to report the TX status of the
+ * This function is called whenever a management frame was requested to be
+ * transmitted with cfg80211_ops::mgmt_tx() to report the TX status of the
  * transmission attempt.
  */
-void cfg80211_action_tx_status(struct net_device *dev, u64 cookie,
-			       const u8 *buf, size_t len, bool ack, gfp_t gfp);
+void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie,
+			     const u8 *buf, size_t len, bool ack, gfp_t gfp);
 
 
 /**
@@ -2420,56 +2595,41 @@
 			      enum nl80211_cqm_rssi_threshold_event rssi_event,
 			      gfp_t gfp);
 
-#ifdef __KERNEL__
-
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
 
 #define wiphy_printk(level, wiphy, format, args...)		\
-	printk(level "%s: " format, wiphy_name(wiphy), ##args)
+	dev_printk(level, &(wiphy)->dev, format, ##args)
 #define wiphy_emerg(wiphy, format, args...)			\
-	wiphy_printk(KERN_EMERG, wiphy, format, ##args)
+	dev_emerg(&(wiphy)->dev, format, ##args)
 #define wiphy_alert(wiphy, format, args...)			\
-	wiphy_printk(KERN_ALERT, wiphy, format, ##args)
+	dev_alert(&(wiphy)->dev, format, ##args)
 #define wiphy_crit(wiphy, format, args...)			\
-	wiphy_printk(KERN_CRIT, wiphy, format, ##args)
+	dev_crit(&(wiphy)->dev, format, ##args)
 #define wiphy_err(wiphy, format, args...)			\
-	wiphy_printk(KERN_ERR, wiphy, format, ##args)
+	dev_err(&(wiphy)->dev, format, ##args)
 #define wiphy_warn(wiphy, format, args...)			\
-	wiphy_printk(KERN_WARNING, wiphy, format, ##args)
+	dev_warn(&(wiphy)->dev, format, ##args)
 #define wiphy_notice(wiphy, format, args...)			\
-	wiphy_printk(KERN_NOTICE, wiphy, format, ##args)
+	dev_notice(&(wiphy)->dev, format, ##args)
 #define wiphy_info(wiphy, format, args...)			\
-	wiphy_printk(KERN_INFO, wiphy, format, ##args)
+	dev_info(&(wiphy)->dev, format, ##args)
 
-int wiphy_debug(const struct wiphy *wiphy, const char *format, ...)
-	__attribute__ ((format (printf, 2, 3)));
-
-#if defined(DEBUG)
-#define wiphy_dbg(wiphy, format, args...)			\
+#define wiphy_debug(wiphy, format, args...)			\
 	wiphy_printk(KERN_DEBUG, wiphy, format, ##args)
-#elif defined(CONFIG_DYNAMIC_DEBUG)
+
 #define wiphy_dbg(wiphy, format, args...)			\
-	dynamic_pr_debug("%s: " format,	wiphy_name(wiphy), ##args)
-#else
-#define wiphy_dbg(wiphy, format, args...)				\
-({									\
-	if (0)								\
-		wiphy_printk(KERN_DEBUG, wiphy, format, ##args);	\
-	0;								\
-})
-#endif
+	dev_dbg(&(wiphy)->dev, format, ##args)
 
 #if defined(VERBOSE_DEBUG)
 #define wiphy_vdbg	wiphy_dbg
 #else
-
 #define wiphy_vdbg(wiphy, format, args...)				\
 ({									\
 	if (0)								\
 		wiphy_printk(KERN_DEBUG, wiphy, format, ##args);	\
-		0;							\
+	0;								\
 })
 #endif
 
@@ -2481,6 +2641,4 @@
 #define wiphy_WARN(wiphy, format, args...)			\
 	WARN(1, "wiphy: %s\n" format, wiphy_name(wiphy), ##args);
 
-#endif
-
 #endif /* __NET_CFG80211_H */
diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h
index ef6c24a..a4dc5b0 100644
--- a/include/net/cls_cgroup.h
+++ b/include/net/cls_cgroup.h
@@ -51,7 +51,8 @@
 		return 0;
 
 	rcu_read_lock();
-	id = rcu_dereference(net_cls_subsys_id);
+	id = rcu_dereference_index_check(net_cls_subsys_id,
+					 rcu_read_lock_held());
 	if (id >= 0)
 		classid = container_of(task_subsys_state(p, id),
 				       struct cgroup_cls_state, css)->classid;
diff --git a/include/net/dst.h b/include/net/dst.h
index 81d1413..a217c83 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -43,10 +43,11 @@
 	short			error;
 	short			obsolete;
 	int			flags;
-#define DST_HOST		1
-#define DST_NOXFRM		2
-#define DST_NOPOLICY		4
-#define DST_NOHASH		8
+#define DST_HOST		0x0001
+#define DST_NOXFRM		0x0002
+#define DST_NOPOLICY		0x0004
+#define DST_NOHASH		0x0008
+#define DST_NOCACHE		0x0010
 	unsigned long		expires;
 
 	unsigned short		header_len;	/* more space at head required */
@@ -228,22 +229,37 @@
 
 
 /**
+ *	__skb_tunnel_rx - prepare skb for rx reinsert
+ *	@skb: buffer
+ *	@dev: tunnel device
+ *
+ *	After decapsulation, packet is going to re-enter (netif_rx()) our stack,
+ *	so make some cleanups. (no accounting done)
+ */
+static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
+{
+	skb->dev = dev;
+	skb->rxhash = 0;
+	skb_set_queue_mapping(skb, 0);
+	skb_dst_drop(skb);
+	nf_reset(skb);
+}
+
+/**
  *	skb_tunnel_rx - prepare skb for rx reinsert
  *	@skb: buffer
  *	@dev: tunnel device
  *
  *	After decapsulation, packet is going to re-enter (netif_rx()) our stack,
  *	so make some cleanups, and perform accounting.
+ *	Note: this accounting is not SMP safe.
  */
 static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
 {
-	skb->dev = dev;
 	/* TODO : stats should be SMP safe */
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += skb->len;
-	skb->rxhash = 0;
-	skb_dst_drop(skb);
-	nf_reset(skb);
+	__skb_tunnel_rx(skb, dev);
 }
 
 /* Children define the path of the packet through the
diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h
index d1ff9b7..1fa5306 100644
--- a/include/net/dst_ops.h
+++ b/include/net/dst_ops.h
@@ -1,6 +1,7 @@
 #ifndef _NET_DST_OPS_H
 #define _NET_DST_OPS_H
 #include <linux/types.h>
+#include <linux/percpu_counter.h>
 
 struct dst_entry;
 struct kmem_cachep;
@@ -22,7 +23,41 @@
 	void			(*update_pmtu)(struct dst_entry *dst, u32 mtu);
 	int			(*local_out)(struct sk_buff *skb);
 
-	atomic_t		entries;
 	struct kmem_cache	*kmem_cachep;
+
+	struct percpu_counter	pcpuc_entries ____cacheline_aligned_in_smp;
 };
+
+static inline int dst_entries_get_fast(struct dst_ops *dst)
+{
+	return percpu_counter_read_positive(&dst->pcpuc_entries);
+}
+
+static inline int dst_entries_get_slow(struct dst_ops *dst)
+{
+	int res;
+
+	local_bh_disable();
+	res = percpu_counter_sum_positive(&dst->pcpuc_entries);
+	local_bh_enable();
+	return res;
+}
+
+static inline void dst_entries_add(struct dst_ops *dst, int val)
+{
+	local_bh_disable();
+	percpu_counter_add(&dst->pcpuc_entries, val);
+	local_bh_enable();
+}
+
+static inline int dst_entries_init(struct dst_ops *dst)
+{
+	return percpu_counter_init(&dst->pcpuc_entries, 0);
+}
+
+static inline void dst_entries_destroy(struct dst_ops *dst)
+{
+	percpu_counter_destroy(&dst->pcpuc_entries);
+}
+
 #endif
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index e8923bc..106f309 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -31,6 +31,8 @@
 	void			*lookup_ptr;
 	void			*result;
 	struct fib_rule		*rule;
+	int			flags;
+#define FIB_LOOKUP_NOREF	1
 };
 
 struct fib_rules_ops {
@@ -106,7 +108,6 @@
 
 extern struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *, struct net *);
 extern void fib_rules_unregister(struct fib_rules_ops *);
-extern void                     fib_rules_cleanup_ops(struct fib_rules_ops *);
 
 extern int			fib_rules_lookup(struct fib_rules_ops *,
 						 struct flowi *, int flags,
diff --git a/include/net/flow.h b/include/net/flow.h
index bb08692..0ac3fb5e 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -49,6 +49,7 @@
 	__u8	proto;
 	__u8	flags;
 #define FLOWI_FLAG_ANYSRC 0x01
+#define FLOWI_FLAG_MATCH_ANY_IIF 0x02
 	union {
 		struct {
 			__be16	sport;
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index f7dcd2c..8a64b81 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -20,6 +20,9 @@
 	u32			id;
 };
 
+struct genl_ops;
+struct genl_info;
+
 /**
  * struct genl_family - generic netlink family
  * @id: protocol family idenfitier
@@ -29,6 +32,10 @@
  * @maxattr: maximum number of attributes supported
  * @netnsok: set to true if the family can handle network
  *	namespaces and should be presented in all of them
+ * @pre_doit: called before an operation's doit callback, it may
+ *	do additional, common, filtering and return an error
+ * @post_doit: called after an operation's doit callback, it may
+ *	undo operations done by pre_doit, for example release locks
  * @attrbuf: buffer to store parsed attributes
  * @ops_list: list of all assigned operations
  * @family_list: family list
@@ -41,6 +48,12 @@
 	unsigned int		version;
 	unsigned int		maxattr;
 	bool			netnsok;
+	int			(*pre_doit)(struct genl_ops *ops,
+					    struct sk_buff *skb,
+					    struct genl_info *info);
+	void			(*post_doit)(struct genl_ops *ops,
+					     struct sk_buff *skb,
+					     struct genl_info *info);
 	struct nlattr **	attrbuf;	/* private */
 	struct list_head	ops_list;	/* private */
 	struct list_head	family_list;	/* private */
@@ -55,6 +68,8 @@
  * @genlhdr: generic netlink message header
  * @userhdr: user specific header
  * @attrs: netlink attributes
+ * @_net: network namespace
+ * @user_ptr: user pointers
  */
 struct genl_info {
 	u32			snd_seq;
@@ -66,6 +81,7 @@
 #ifdef CONFIG_NET_NS
 	struct net *		_net;
 #endif
+	void *			user_ptr[2];
 };
 
 static inline struct net *genl_info_net(struct genl_info *info)
@@ -81,6 +97,7 @@
 /**
  * struct genl_ops - generic netlink operations
  * @cmd: command identifier
+ * @internal_flags: flags used by the family
  * @flags: flags
  * @policy: attribute validation policy
  * @doit: standard command callback
@@ -90,6 +107,7 @@
  */
 struct genl_ops {
 	u8			cmd;
+	u8			internal_flags;
 	unsigned int		flags;
 	const struct nla_policy	*policy;
 	int		       (*doit)(struct sk_buff *skb,
diff --git a/include/net/gre.h b/include/net/gre.h
new file mode 100644
index 0000000..8266547
--- /dev/null
+++ b/include/net/gre.h
@@ -0,0 +1,18 @@
+#ifndef __LINUX_GRE_H
+#define __LINUX_GRE_H
+
+#include <linux/skbuff.h>
+
+#define GREPROTO_CISCO		0
+#define GREPROTO_PPTP		1
+#define GREPROTO_MAX		2
+
+struct gre_protocol {
+	int  (*handler)(struct sk_buff *skb);
+	void (*err_handler)(struct sk_buff *skb, u32 info);
+};
+
+int gre_add_protocol(const struct gre_protocol *proto, u8 version);
+int gre_del_protocol(const struct gre_protocol *proto, u8 version);
+
+#endif
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index b6d3b55..e4f494b 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -125,6 +125,7 @@
 		int		  probe_size;
 	} icsk_mtup;
 	u32			  icsk_ca_priv[16];
+	u32			  icsk_user_timeout;
 #define ICSK_CA_PRIV_SIZE	(16 * sizeof(u32))
 };
 
diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h
index 9b5d08f..88bdd01 100644
--- a/include/net/inet_ecn.h
+++ b/include/net/inet_ecn.h
@@ -27,7 +27,7 @@
 
 static inline int INET_ECN_is_capable(__u8 dsfield)
 {
-	return (dsfield & INET_ECN_ECT_0);
+	return dsfield & INET_ECN_ECT_0;
 }
 
 static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 74358d1..e9c2ed8 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -245,7 +245,7 @@
 }
 
 /* Caller must disable local BH processing. */
-extern void __inet_inherit_port(struct sock *sk, struct sock *child);
+extern int __inet_inherit_port(struct sock *sk, struct sock *child);
 
 extern void inet_put_port(struct sock *sk);
 
diff --git a/include/net/ip.h b/include/net/ip.h
index 890f972..dbee3fe 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -53,7 +53,7 @@
 	__be32			addr;
 	int			oif;
 	struct ip_options	*opt;
-	union skb_shared_tx	shtx;
+	__u8			tx_flags;
 };
 
 #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
@@ -238,9 +238,9 @@
 static inline
 int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
 {
-	return (inet_sk(sk)->pmtudisc == IP_PMTUDISC_DO ||
+	return  inet_sk(sk)->pmtudisc == IP_PMTUDISC_DO ||
 		(inet_sk(sk)->pmtudisc == IP_PMTUDISC_WANT &&
-		 !(dst_metric_locked(dst, RTAX_MTU))));
+		 !(dst_metric_locked(dst, RTAX_MTU)));
 }
 
 extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more);
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index c93f94e..ba3666d 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -86,6 +86,7 @@
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 	int			fib_power;
 #endif
+	struct rcu_head		rcu;
 	struct fib_nh		fib_nh[0];
 #define fib_dev		fib_nh[0].nh_dev
 };
@@ -148,7 +149,7 @@
 };
 
 extern int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
-			    struct fib_result *res);
+			    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,
@@ -185,11 +186,11 @@
 	struct fib_table *table;
 
 	table = fib_get_table(net, RT_TABLE_LOCAL);
-	if (!fib_table_lookup(table, flp, res))
+	if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
 		return 0;
 
 	table = fib_get_table(net, RT_TABLE_MAIN);
-	if (!fib_table_lookup(table, flp, res))
+	if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
 		return 0;
 	return -ENETUNREACH;
 }
@@ -254,16 +255,6 @@
 		free_fib_info(fi);
 }
 
-static inline void fib_res_put(struct fib_result *res)
-{
-	if (res->fi)
-		fib_info_put(res->fi);
-#ifdef CONFIG_IP_MULTIPLE_TABLES
-	if (res->r)
-		fib_rule_put(res->r);
-#endif
-}
-
 #ifdef CONFIG_PROC_FS
 extern int __net_init  fib_proc_init(struct net *net);
 extern void __net_exit fib_proc_exit(struct net *net);
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index f976885..b7bbd6c 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -25,7 +25,9 @@
 #include <linux/ip.h>
 #include <linux/ipv6.h>			/* for struct ipv6hdr */
 #include <net/ipv6.h>			/* for ipv6_addr_copy */
-
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#include <net/netfilter/nf_conntrack.h>
+#endif
 
 /* Connections' size value needed by ip_vs_ctl.c */
 extern int ip_vs_conn_tab_size;
@@ -134,24 +136,24 @@
 		if (net_ratelimit())					\
 			printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__);	\
 	} while (0)
-#define IP_VS_DBG_PKT(level, pp, skb, ofs, msg)				\
+#define IP_VS_DBG_PKT(level, af, pp, skb, ofs, msg)			\
 	do {								\
 		if (level <= ip_vs_get_debug_level())			\
-			pp->debug_packet(pp, skb, ofs, msg);		\
+			pp->debug_packet(af, pp, skb, ofs, msg);	\
 	} while (0)
-#define IP_VS_DBG_RL_PKT(level, pp, skb, ofs, msg)			\
+#define IP_VS_DBG_RL_PKT(level, af, pp, skb, ofs, msg)			\
 	do {								\
 		if (level <= ip_vs_get_debug_level() &&			\
 		    net_ratelimit())					\
-			pp->debug_packet(pp, skb, ofs, msg);		\
+			pp->debug_packet(af, pp, skb, ofs, msg);	\
 	} while (0)
 #else	/* NO DEBUGGING at ALL */
 #define IP_VS_DBG_BUF(level, msg...)  do {} while (0)
 #define IP_VS_ERR_BUF(msg...)  do {} while (0)
 #define IP_VS_DBG(level, msg...)  do {} while (0)
 #define IP_VS_DBG_RL(msg...)  do {} while (0)
-#define IP_VS_DBG_PKT(level, pp, skb, ofs, msg)		do {} while (0)
-#define IP_VS_DBG_RL_PKT(level, pp, skb, ofs, msg)	do {} while (0)
+#define IP_VS_DBG_PKT(level, af, pp, skb, ofs, msg)	do {} while (0)
+#define IP_VS_DBG_RL_PKT(level, af, pp, skb, ofs, msg)	do {} while (0)
 #endif
 
 #define IP_VS_BUG() BUG()
@@ -343,7 +345,7 @@
 
 	int (*app_conn_bind)(struct ip_vs_conn *cp);
 
-	void (*debug_packet)(struct ip_vs_protocol *pp,
+	void (*debug_packet)(int af, struct ip_vs_protocol *pp,
 			     const struct sk_buff *skb,
 			     int offset,
 			     const char *msg);
@@ -355,6 +357,19 @@
 
 extern struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto);
 
+struct ip_vs_conn_param {
+	const union nf_inet_addr	*caddr;
+	const union nf_inet_addr	*vaddr;
+	__be16				cport;
+	__be16				vport;
+	__u16				protocol;
+	u16				af;
+
+	const struct ip_vs_pe		*pe;
+	char				*pe_data;
+	__u8				pe_data_len;
+};
+
 /*
  *	IP_VS structure allocated for each dynamically scheduled connection
  */
@@ -366,6 +381,7 @@
 	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;
@@ -378,7 +394,6 @@
 
 	/* Flags and state transition */
 	spinlock_t              lock;           /* lock for state transition */
-	volatile __u16          flags;          /* status flags */
 	volatile __u16          state;          /* state info */
 	volatile __u16          old_state;      /* old state, to be used for
 						 * state transition triggerd
@@ -394,6 +409,7 @@
 	/* packet transmitter for different forwarding methods.  If it
 	   mangles the packet, it must return NF_DROP or better NF_STOLEN,
 	   otherwise this must be changed to a sk_buff **.
+	   NF_ACCEPT can be returned when destination is local.
 	 */
 	int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp,
 			   struct ip_vs_protocol *pp);
@@ -405,6 +421,9 @@
 	void                    *app_data;      /* Application private data */
 	struct ip_vs_seq        in_seq;         /* incoming seq. struct */
 	struct ip_vs_seq        out_seq;        /* outgoing seq. struct */
+
+	char			*pe_data;
+	__u8			pe_data_len;
 };
 
 
@@ -426,6 +445,7 @@
 
 	/* virtual service options */
 	char			*sched_name;
+	char			*pe_name;
 	unsigned		flags;		/* virtual service flags */
 	unsigned		timeout;	/* persistent timeout in sec */
 	u32			netmask;	/* persistent netmask */
@@ -475,6 +495,9 @@
 	struct ip_vs_scheduler	*scheduler;    /* bound scheduler object */
 	rwlock_t		sched_lock;    /* lock sched_data */
 	void			*sched_data;   /* scheduler application data */
+
+	/* alternate persistence engine */
+	struct ip_vs_pe		*pe;
 };
 
 
@@ -507,6 +530,10 @@
 	spinlock_t		dst_lock;	/* lock of dst_cache */
 	struct dst_entry	*dst_cache;	/* destination cache entry */
 	u32			dst_rtos;	/* RT_TOS(tos) for dst */
+	u32			dst_cookie;
+#ifdef CONFIG_IP_VS_IPV6
+	struct in6_addr		dst_saddr;
+#endif
 
 	/* for virtual service */
 	struct ip_vs_service	*svc;		/* service it belongs to */
@@ -538,6 +565,21 @@
 				       const struct sk_buff *skb);
 };
 
+/* The persistence engine object */
+struct ip_vs_pe {
+	struct list_head	n_list;		/* d-linked list head */
+	char			*name;		/* scheduler name */
+	atomic_t		refcnt;		/* reference counter */
+	struct module		*module;	/* THIS_MODULE/NULL */
+
+	/* get the connection template, if any */
+	int (*fill_param)(struct ip_vs_conn_param *p, struct sk_buff *skb);
+	bool (*ct_match)(const struct ip_vs_conn_param *p,
+			 struct ip_vs_conn *ct);
+	u32 (*hashkey_raw)(const struct ip_vs_conn_param *p, u32 initval,
+			   bool inverse);
+	int (*show_pe_data)(const struct ip_vs_conn *cp, char *buf);
+};
 
 /*
  *	The application module object (a.k.a. app incarnation)
@@ -556,11 +598,19 @@
 	__be16			port;		/* port number in net order */
 	atomic_t		usecnt;		/* usage counter */
 
-	/* output hook: return false if can't linearize. diff set for TCP.  */
+	/*
+	 * output hook: Process packet in inout direction, diff set for TCP.
+	 * Return: 0=Error, 1=Payload Not Mangled/Mangled but checksum is ok,
+	 *	   2=Mangled but checksum was not updated
+	 */
 	int (*pkt_out)(struct ip_vs_app *, struct ip_vs_conn *,
 		       struct sk_buff *, int *diff);
 
-	/* input hook: return false if can't linearize. diff set for TCP. */
+	/*
+	 * input hook: Process packet in outin direction, diff set for TCP.
+	 * Return: 0=Error, 1=Payload Not Mangled/Mangled but checksum is ok,
+	 *	   2=Mangled but checksum was not updated
+	 */
 	int (*pkt_in)(struct ip_vs_app *, struct ip_vs_conn *,
 		      struct sk_buff *, int *diff);
 
@@ -624,13 +674,25 @@
 	IP_VS_DIR_LAST,
 };
 
-extern struct ip_vs_conn *ip_vs_conn_in_get
-(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
- const union nf_inet_addr *d_addr, __be16 d_port);
+static inline void ip_vs_conn_fill_param(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->af = af;
+	p->protocol = protocol;
+	p->caddr = caddr;
+	p->cport = cport;
+	p->vaddr = vaddr;
+	p->vport = vport;
+	p->pe = NULL;
+	p->pe_data = NULL;
+}
 
-extern struct ip_vs_conn *ip_vs_ct_in_get
-(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
- const union nf_inet_addr *d_addr, __be16 d_port);
+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,
@@ -638,9 +700,7 @@
 					    unsigned int proto_off,
 					    int inverse);
 
-extern struct ip_vs_conn *ip_vs_conn_out_get
-(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
- const union nf_inet_addr *d_addr, __be16 d_port);
+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,
@@ -656,11 +716,10 @@
 extern void ip_vs_conn_put(struct ip_vs_conn *cp);
 extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
 
-extern struct ip_vs_conn *
-ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
-	       const union nf_inet_addr *vaddr, __be16 vport,
-	       const union nf_inet_addr *daddr, __be16 dport, unsigned flags,
-	       struct ip_vs_dest *dest);
+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);
 extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
 
 extern const char * ip_vs_state_name(__u16 proto, int state);
@@ -751,6 +810,12 @@
 extern int ip_vs_app_init(void);
 extern void ip_vs_app_cleanup(void);
 
+void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe);
+void ip_vs_unbind_pe(struct ip_vs_service *svc);
+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);
 
 /*
  *	IPVS protocol functions (from ip_vs_proto.c)
@@ -763,7 +828,8 @@
 ip_vs_set_state_timeout(int *table, int num, const char *const *names,
 			const char *name, int to);
 extern void
-ip_vs_tcpudp_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb,
+ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
+			  const struct sk_buff *skb,
 			  int offset, const char *msg);
 
 extern struct ip_vs_protocol ip_vs_protocol_tcp;
@@ -785,7 +851,8 @@
 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, const struct sk_buff *skb);
+ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
+	       struct ip_vs_protocol *pp, int *ignored);
 extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 			struct ip_vs_protocol *pp);
 
@@ -798,6 +865,8 @@
 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[];
 
@@ -955,8 +1024,65 @@
 	return csum_partial(diff, sizeof(diff), oldsum);
 }
 
+/*
+ * Forget current conntrack (unconfirmed) and attach notrack entry
+ */
+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);
+
+	if (!ct || !nf_ct_is_untracked(ct)) {
+		nf_reset(skb);
+		skb->nfct = &nf_ct_untracked_get()->ct_general;
+		skb->nfctinfo = IP_CT_NEW;
+		nf_conntrack_get(skb->nfct);
+	}
+#endif
+}
+
+#ifdef CONFIG_IP_VS_NFCT
+/*
+ *      Netfilter connection tracking
+ *      (from ip_vs_nfct.c)
+ */
+static inline int ip_vs_conntrack_enabled(void)
+{
+	return sysctl_ip_vs_conntrack;
+}
+
 extern void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp,
 				   int outin);
+extern int ip_vs_confirm_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp);
+extern void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct,
+				      struct ip_vs_conn *cp, u_int8_t proto,
+				      const __be16 port, int from_rs);
+extern void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp);
+
+#else
+
+static inline int ip_vs_conntrack_enabled(void)
+{
+	return 0;
+}
+
+static inline void ip_vs_update_conntrack(struct sk_buff *skb,
+					  struct ip_vs_conn *cp, int outin)
+{
+}
+
+static inline int ip_vs_confirm_conntrack(struct sk_buff *skb,
+					  struct ip_vs_conn *cp)
+{
+	return NF_ACCEPT;
+}
+
+static inline void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp)
+{
+}
+/* CONFIG_IP_VS_NFCT */
+#endif
 
 #endif /* __KERNEL__ */
 
diff --git a/include/net/ipip.h b/include/net/ipip.h
index 65caea8..58abbf9 100644
--- a/include/net/ipip.h
+++ b/include/net/ipip.h
@@ -45,7 +45,7 @@
 	struct rcu_head			rcu_head;
 };
 
-#define IPTUNNEL_XMIT() do {						\
+#define __IPTUNNEL_XMIT(stats1, stats2) do {				\
 	int err;							\
 	int pkt_len = skb->len - skb_transport_offset(skb);		\
 									\
@@ -54,12 +54,14 @@
 									\
 	err = ip_local_out(skb);					\
 	if (likely(net_xmit_eval(err) == 0)) {				\
-		txq->tx_bytes += pkt_len;				\
-		txq->tx_packets++;					\
+		(stats1)->tx_bytes += pkt_len;				\
+		(stats1)->tx_packets++;					\
 	} else {							\
-		stats->tx_errors++;					\
-		stats->tx_aborted_errors++;				\
+		(stats2)->tx_errors++;					\
+		(stats2)->tx_aborted_errors++;				\
 	}								\
 } while (0)
 
+#define IPTUNNEL_XMIT() __IPTUNNEL_XMIT(txq, stats)
+
 #endif
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 1f84124..4a3cd2c 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -262,7 +262,7 @@
 
 static inline int __ipv6_addr_src_scope(int type)
 {
-	return (type == IPV6_ADDR_ANY ? __IPV6_ADDR_SCOPE_INVALID : (type >> 16));
+	return (type == IPV6_ADDR_ANY) ? __IPV6_ADDR_SCOPE_INVALID : (type >> 16);
 }
 
 static inline int ipv6_addr_src_scope(const struct in6_addr *addr)
@@ -279,10 +279,10 @@
 ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m,
 		     const struct in6_addr *a2)
 {
-	return (!!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) |
-		   ((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) |
-		   ((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) |
-		   ((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3])));
+	return !!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) |
+		  ((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) |
+		  ((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) |
+		  ((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3]));
 }
 
 static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2)
@@ -317,10 +317,10 @@
 static inline int ipv6_addr_equal(const struct in6_addr *a1,
 				  const struct in6_addr *a2)
 {
-	return (((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
-		 (a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
-		 (a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
-		 (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0);
+	return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
+		(a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
+		(a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
+		(a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0;
 }
 
 static inline int __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,
@@ -373,20 +373,20 @@
 
 static inline int ipv6_addr_any(const struct in6_addr *a)
 {
-	return ((a->s6_addr32[0] | a->s6_addr32[1] | 
-		 a->s6_addr32[2] | a->s6_addr32[3] ) == 0); 
+	return (a->s6_addr32[0] | a->s6_addr32[1] |
+		a->s6_addr32[2] | a->s6_addr32[3]) == 0;
 }
 
 static inline int ipv6_addr_loopback(const struct in6_addr *a)
 {
-	return ((a->s6_addr32[0] | a->s6_addr32[1] |
-		 a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0);
+	return (a->s6_addr32[0] | a->s6_addr32[1] |
+		a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0;
 }
 
 static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
 {
-	return ((a->s6_addr32[0] | a->s6_addr32[1] |
-		 (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0);
+	return (a->s6_addr32[0] | a->s6_addr32[1] |
+		 (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0;
 }
 
 /*
@@ -395,8 +395,7 @@
  */
 static inline int ipv6_addr_orchid(const struct in6_addr *a)
 {
-	return ((a->s6_addr32[0] & htonl(0xfffffff0))
-		== htonl(0x20010010));
+	return (a->s6_addr32[0] & htonl(0xfffffff0)) == htonl(0x20010010);
 }
 
 static inline void ipv6_addr_set_v4mapped(const __be32 addr,
@@ -441,7 +440,7 @@
 	 *	if returned value is greater than prefix length.
 	 *					--ANK (980803)
 	 */
-	return (addrlen << 5);
+	return addrlen << 5;
 }
 
 static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_addr *a2)
diff --git a/include/net/irda/irlan_common.h b/include/net/irda/irlan_common.h
index 73cacb3..0af8b8d 100644
--- a/include/net/irda/irlan_common.h
+++ b/include/net/irda/irlan_common.h
@@ -171,7 +171,6 @@
 	int    magic;
 	struct list_head  dev_list;
 	struct net_device *dev;        /* Ethernet device structure*/
-	struct net_device_stats stats;
 
 	__u32 saddr;               /* Source device address */
 	__u32 daddr;               /* Destination device address */
diff --git a/include/net/irda/irlan_event.h b/include/net/irda/irlan_event.h
index 6d9539f..018b5a7 100644
--- a/include/net/irda/irlan_event.h
+++ b/include/net/irda/irlan_event.h
@@ -67,7 +67,7 @@
 	IRLAN_WATCHDOG_TIMEOUT,
 } IRLAN_EVENT;
 
-extern char *irlan_state[];
+extern const char * const irlan_state[];
 
 void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event, 
 			   struct sk_buff *skb);
diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h
index 9d0c78ea..17fcd96 100644
--- a/include/net/irda/irlap.h
+++ b/include/net/irda/irlap.h
@@ -282,7 +282,7 @@
 	default:
 		ret = -1;
 	}
-	return(ret);
+	return ret;
 }
 
 /* Clear a pending IrLAP disconnect. - Jean II */
diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h
index 3ffc1d0..fff11b7 100644
--- a/include/net/irda/irlmp.h
+++ b/include/net/irda/irlmp.h
@@ -274,7 +274,7 @@
 	if (self->lap->irlap == NULL)
 		return 0;
 
-	return(IRLAP_GET_TX_QUEUE_LEN(self->lap->irlap) >= LAP_HIGH_THRESHOLD);
+	return IRLAP_GET_TX_QUEUE_LEN(self->lap->irlap) >= LAP_HIGH_THRESHOLD;
 }
 
 /* After doing a irlmp_dup(), this get one of the two socket back into
diff --git a/include/net/irda/irttp.h b/include/net/irda/irttp.h
index 11aee7a..af4b877 100644
--- a/include/net/irda/irttp.h
+++ b/include/net/irda/irttp.h
@@ -204,7 +204,7 @@
 	    (self->lsap->lap == NULL) ||
 	    (self->lsap->lap->irlap == NULL))
 		return -2;
-	return(irlap_is_primary(self->lsap->lap->irlap));
+	return irlap_is_primary(self->lsap->lap->irlap);
 }
 
 #endif /* IRTTP_H */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index b0787a1..9fdf982 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -149,6 +149,7 @@
  * @BSS_CHANGED_ARP_FILTER: Hardware ARP filter address list or state changed.
  * @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
  *	that it is only ever disabled for station mode.
+ * @BSS_CHANGED_IDLE: Idle changed for this BSS/interface.
  */
 enum ieee80211_bss_change {
 	BSS_CHANGED_ASSOC		= 1<<0,
@@ -165,6 +166,7 @@
 	BSS_CHANGED_IBSS		= 1<<11,
 	BSS_CHANGED_ARP_FILTER		= 1<<12,
 	BSS_CHANGED_QOS			= 1<<13,
+	BSS_CHANGED_IDLE		= 1<<14,
 
 	/* when adding here, make sure to change ieee80211_reconfig */
 };
@@ -223,6 +225,9 @@
  *	hardware must not perform any ARP filtering. Note, that the filter will
  *	be enabled also in promiscuous mode.
  * @qos: This is a QoS-enabled BSS.
+ * @idle: This interface is idle. There's also a global idle flag in the
+ *	hardware config which may be more appropriate depending on what
+ *	your driver/device needs to do.
  */
 struct ieee80211_bss_conf {
 	const u8 *bssid;
@@ -247,6 +252,7 @@
 	u8 arp_addr_cnt;
 	bool arp_filter_enabled;
 	bool qos;
+	bool idle;
 };
 
 /**
@@ -315,6 +321,9 @@
  * @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame
  * @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this
  *	frame and selects the maximum number of streams that it can use.
+ *
+ * Note: If you have to add new flags to the enumeration, then don't
+ *	 forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary.
  */
 enum mac80211_tx_control_flags {
 	IEEE80211_TX_CTL_REQ_TX_STATUS		= BIT(0),
@@ -344,6 +353,19 @@
 
 #define IEEE80211_TX_CTL_STBC_SHIFT		23
 
+/*
+ * This definition is used as a mask to clear all temporary flags, which are
+ * set by the tx handlers for each transmission attempt by the mac80211 stack.
+ */
+#define IEEE80211_TX_TEMPORARY_FLAGS (IEEE80211_TX_CTL_NO_ACK |		      \
+	IEEE80211_TX_CTL_CLEAR_PS_FILT | IEEE80211_TX_CTL_FIRST_FRAGMENT |    \
+	IEEE80211_TX_CTL_SEND_AFTER_DTIM | IEEE80211_TX_CTL_AMPDU |	      \
+	IEEE80211_TX_STAT_TX_FILTERED |	IEEE80211_TX_STAT_ACK |		      \
+	IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_STAT_AMPDU_NO_BACK |	      \
+	IEEE80211_TX_CTL_RATE_CTRL_PROBE | IEEE80211_TX_CTL_PSPOLL_RESPONSE | \
+	IEEE80211_TX_CTL_MORE_FRAMES | IEEE80211_TX_CTL_LDPC |		      \
+	IEEE80211_TX_CTL_STBC)
+
 /**
  * enum mac80211_rate_control_flags - per-rate flags set by the
  *	Rate Control algorithm.
@@ -559,9 +581,6 @@
  * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
  * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
  * @RX_FLAG_SHORT_GI: Short guard interval was used
- * @RX_FLAG_INTERNAL_CMTR: set internally after frame was reported
- *	on cooked monitor to avoid double-reporting it for multiple
- *	virtual interfaces
  */
 enum mac80211_rx_flags {
 	RX_FLAG_MMIC_ERROR	= 1<<0,
@@ -575,7 +594,6 @@
 	RX_FLAG_HT		= 1<<9,
 	RX_FLAG_40MHZ		= 1<<10,
 	RX_FLAG_SHORT_GI	= 1<<11,
-	RX_FLAG_INTERNAL_CMTR	= 1<<12,
 };
 
 /**
@@ -596,6 +614,7 @@
  * @rate_idx: index of data rate into band's supported rates or MCS index if
  *	HT rates are use (RX_FLAG_HT)
  * @flag: %RX_FLAG_*
+ * @rx_flags: internal RX flags for mac80211
  */
 struct ieee80211_rx_status {
 	u64 mactime;
@@ -605,6 +624,7 @@
 	int antenna;
 	int rate_idx;
 	int flag;
+	unsigned int rx_flags;
 };
 
 /**
@@ -763,6 +783,8 @@
  * @bss_conf: BSS configuration for this interface, either our own
  *	or the BSS we're associated to
  * @addr: address of this interface
+ * @p2p: indicates whether this AP or STA interface is a p2p
+ *	interface, i.e. a GO or p2p-sta respectively
  * @drv_priv: data area for driver use, will always be aligned to
  *	sizeof(void *).
  */
@@ -770,6 +792,7 @@
 	enum nl80211_iftype type;
 	struct ieee80211_bss_conf bss_conf;
 	u8 addr[ETH_ALEN];
+	bool p2p;
 	/* must be last */
 	u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
 };
@@ -783,20 +806,6 @@
 }
 
 /**
- * enum ieee80211_key_alg - key algorithm
- * @ALG_WEP: WEP40 or WEP104
- * @ALG_TKIP: TKIP
- * @ALG_CCMP: CCMP (AES)
- * @ALG_AES_CMAC: AES-128-CMAC
- */
-enum ieee80211_key_alg {
-	ALG_WEP,
-	ALG_TKIP,
-	ALG_CCMP,
-	ALG_AES_CMAC,
-};
-
-/**
  * enum ieee80211_key_flags - key flags
  *
  * These flags are used for communication about keys between the driver
@@ -833,7 +842,7 @@
  * @hw_key_idx: To be set by the driver, this is the key index the driver
  *	wants to be given when a frame is transmitted and needs to be
  *	encrypted in hardware.
- * @alg: The key algorithm.
+ * @cipher: The key's cipher suite selector.
  * @flags: key flags, see &enum ieee80211_key_flags.
  * @keyidx: the key index (0-3)
  * @keylen: key material length
@@ -846,7 +855,7 @@
  * @iv_len: The IV length for this key type
  */
 struct ieee80211_key_conf {
-	enum ieee80211_key_alg alg;
+	u32 cipher;
 	u8 icv_len;
 	u8 iv_len;
 	u8 hw_key_idx;
@@ -1032,6 +1041,13 @@
  * @IEEE80211_HW_NEED_DTIM_PERIOD:
  *	This device needs to know the DTIM period for the BSS before
  *	associating.
+ *
+ * @IEEE80211_HW_SUPPORTS_PER_STA_GTK: The device's crypto engine supports
+ *	per-station GTKs as used by IBSS RSN or during fast transition. If
+ *	the device doesn't support per-station GTKs, but can be asked not
+ *	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.
  */
 enum ieee80211_hw_flags {
 	IEEE80211_HW_HAS_RATE_CONTROL			= 1<<0,
@@ -1055,6 +1071,7 @@
 	IEEE80211_HW_REPORTS_TX_ACK_STATUS		= 1<<18,
 	IEEE80211_HW_CONNECTION_MONITOR			= 1<<19,
 	IEEE80211_HW_SUPPORTS_CQM_RSSI			= 1<<20,
+	IEEE80211_HW_SUPPORTS_PER_STA_GTK		= 1<<21,
 };
 
 /**
@@ -1100,8 +1117,15 @@
  * @sta_data_size: size (in bytes) of the drv_priv data area
  *	within &struct ieee80211_sta.
  *
- * @max_rates: maximum number of alternate rate retry stages
+ * @max_rates: maximum number of alternate rate retry stages the hw
+ *	can handle.
+ * @max_report_rates: maximum number of alternate rate retry stages
+ *	the hw can report back.
  * @max_rate_tries: maximum number of tries for each stage
+ *
+ * @napi_weight: weight used for NAPI polling.  You must specify an
+ *	appropriate value here if a napi_poll operation is provided
+ *	by your driver.
  */
 struct ieee80211_hw {
 	struct ieee80211_conf conf;
@@ -1113,10 +1137,12 @@
 	int channel_change_time;
 	int vif_data_size;
 	int sta_data_size;
+	int napi_weight;
 	u16 queues;
 	u16 max_listen_interval;
 	s8 max_signal;
 	u8 max_rates;
+	u8 max_report_rates;
 	u8 max_rate_tries;
 };
 
@@ -1245,8 +1271,8 @@
  * %IEEE80211_CONF_PS flag enabled means that the powersave mode defined in
  * IEEE 802.11-2007 section 11.2 is enabled. This is not to be confused
  * with hardware wakeup and sleep states. Driver is responsible for waking
- * up the hardware before issueing commands to the hardware and putting it
- * back to sleep at approriate times.
+ * up the hardware before issuing commands to the hardware and putting it
+ * back to sleep at appropriate times.
  *
  * When PS is enabled, hardware needs to wakeup for beacons and receive the
  * buffered multicast/broadcast frames after the beacon. Also it must be
@@ -1267,7 +1293,7 @@
  * there's data traffic and still saving significantly power in idle
  * periods.
  *
- * Dynamic powersave is supported by simply mac80211 enabling and disabling
+ * Dynamic powersave is simply supported by mac80211 enabling and disabling
  * PS based on traffic. Driver needs to only set %IEEE80211_HW_SUPPORTS_PS
  * flag and mac80211 will handle everything automatically. Additionally,
  * hardware having support for the dynamic PS feature may set the
@@ -1452,12 +1478,14 @@
  *	honour this flag if possible.
  *
  * @FIF_CONTROL: pass control frames (except for PS Poll), if PROMISC_IN_BSS
- *  is not set then only those addressed to this station.
+ * 	is not set then only those addressed to this station.
  *
  * @FIF_OTHER_BSS: pass frames destined to other BSSes
  *
- * @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS  is not set then only
- *  those addressed to this station.
+ * @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS is not set then only
+ * 	those addressed to this station.
+ *
+ * @FIF_PROBE_REQ: pass probe request frames
  */
 enum ieee80211_filter_flags {
 	FIF_PROMISC_IN_BSS	= 1<<0,
@@ -1468,6 +1496,7 @@
 	FIF_CONTROL		= 1<<5,
 	FIF_OTHER_BSS		= 1<<6,
 	FIF_PSPOLL		= 1<<7,
+	FIF_PROBE_REQ		= 1<<8,
 };
 
 /**
@@ -1540,6 +1569,12 @@
  *	negative error code (which will be seen in userspace.)
  *	Must be implemented and can sleep.
  *
+ * @change_interface: Called when a netdevice changes type. This callback
+ *	is optional, but only if it is supported can interface types be
+ *	switched while the interface is UP. The callback may sleep.
+ *	Note that while an interface is being switched, it will not be
+ *	found by the interface iteration callbacks.
+ *
  * @remove_interface: Notifies a driver that an interface is going down.
  *	The @stop callback is called after this if it is the last interface
  *	and no monitor interfaces are present.
@@ -1687,6 +1722,8 @@
  *	switch operation for CSAs received from the AP may implement this
  *	callback. They must then call ieee80211_chswitch_done() to indicate
  *	completion of the channel switch.
+ *
+ * @napi_poll: Poll Rx queue for incoming data frames.
  */
 struct ieee80211_ops {
 	int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1694,6 +1731,9 @@
 	void (*stop)(struct ieee80211_hw *hw);
 	int (*add_interface)(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif);
+	int (*change_interface)(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				enum nl80211_iftype new_type, bool p2p);
 	void (*remove_interface)(struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif);
 	int (*config)(struct ieee80211_hw *hw, u32 changed);
@@ -1752,6 +1792,7 @@
 	void (*flush)(struct ieee80211_hw *hw, bool drop);
 	void (*channel_switch)(struct ieee80211_hw *hw,
 			       struct ieee80211_channel_switch *ch_switch);
+	int (*napi_poll)(struct ieee80211_hw *hw, int budget);
 };
 
 /**
@@ -1897,6 +1938,22 @@
  */
 void ieee80211_restart_hw(struct ieee80211_hw *hw);
 
+/** ieee80211_napi_schedule - schedule NAPI poll
+ *
+ * Use this function to schedule NAPI polling on a device.
+ *
+ * @hw: the hardware to start polling
+ */
+void ieee80211_napi_schedule(struct ieee80211_hw *hw);
+
+/** ieee80211_napi_complete - complete NAPI polling
+ *
+ * Use this function to finish NAPI polling on a device.
+ *
+ * @hw: the hardware to stop polling
+ */
+void ieee80211_napi_complete(struct ieee80211_hw *hw);
+
 /**
  * ieee80211_rx - receive frame
  *
@@ -2252,7 +2309,8 @@
  *
  * When hardware scan offload is used (i.e. the hw_scan() callback is
  * assigned) this function needs to be called by the driver to notify
- * mac80211 that the scan finished.
+ * mac80211 that the scan finished. This function can be called from
+ * any context, including hardirq context.
  *
  * @hw: the hardware that finished the scan
  * @aborted: set to true if scan was aborted
@@ -2267,6 +2325,7 @@
  * This function allows the iterator function to sleep, when the iterator
  * function is atomic @ieee80211_iterate_active_interfaces_atomic can
  * be used.
+ * Does not iterate over a new interface during add_interface()
  *
  * @hw: the hardware struct of which the interfaces should be iterated over
  * @iterator: the iterator function to call
@@ -2284,6 +2343,7 @@
  * hardware that are currently active and calls the callback for them.
  * This function requires the iterator callback function to be atomic,
  * if that is not desired, use @ieee80211_iterate_active_interfaces instead.
+ * Does not iterate over a new interface during add_interface()
  *
  * @hw: the hardware struct of which the interfaces should be iterated over
  * @iterator: the iterator function to call, cannot sleep
@@ -2385,25 +2445,28 @@
 					 const u8 *addr);
 
 /**
- * ieee80211_find_sta_by_hw - find a station on hardware
+ * ieee80211_find_sta_by_ifaddr - find a station on hardware
  *
  * @hw: pointer as obtained from ieee80211_alloc_hw()
- * @addr: station's address
+ * @addr: remote station's address
+ * @localaddr: local address (vif->sdata->vif.addr). Use NULL for 'any'.
  *
  * This function must be called under RCU lock and the
  * resulting pointer is only valid under RCU lock as well.
  *
- * NOTE: This function should not be used! When mac80211 is converted
- *	 internally to properly keep track of stations on multiple
- *	 virtual interfaces, it will not always know which station to
- *	 return here since a single address might be used by multiple
- *	 logical stations (e.g. consider a station connecting to another
- *	 BSSID on the same AP hardware without disconnecting first).
+ * NOTE: You may pass NULL for localaddr, but then you will just get
+ *      the first STA that matches the remote address 'addr'.
+ *      We can have multiple STA associated with multiple
+ *      logical stations (e.g. consider a station connecting to another
+ *      BSSID on the same AP hardware without disconnecting first).
+ *      In this case, the result of this method with localaddr NULL
+ *      is not reliable.
  *
- * DO NOT USE THIS FUNCTION.
+ * DO NOT USE THIS FUNCTION with localaddr NULL if at all possible.
  */
-struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
-					       const u8 *addr);
+struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
+					       const u8 *addr,
+					       const u8 *localaddr);
 
 /**
  * ieee80211_sta_block_awake - block station from waking up
@@ -2442,7 +2505,7 @@
  *
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
  *
- * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTERING and
+ * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTER and
  * %IEEE80211_CONF_PS is set, the driver needs to inform whenever the
  * hardware is not receiving beacons with this function.
  */
@@ -2453,7 +2516,7 @@
  *
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
  *
- * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTERING, and
+ * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTER, and
  * %IEEE80211_CONF_PS and %IEEE80211_HW_CONNECTION_MONITOR are set, the driver
  * needs to inform if the connection to the AP has been lost.
  *
@@ -2518,6 +2581,34 @@
  */
 void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success);
 
+/**
+ * ieee80211_request_smps - request SM PS transition
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @smps_mode: new SM PS mode
+ *
+ * This allows the driver to request an SM PS transition in managed
+ * mode. This is useful when the driver has more information than
+ * the stack about possible interference, for example by bluetooth.
+ */
+void ieee80211_request_smps(struct ieee80211_vif *vif,
+			    enum ieee80211_smps_mode smps_mode);
+
+/**
+ * ieee80211_key_removed - disable hw acceleration for key
+ * @key_conf: The key hw acceleration should be disabled for
+ *
+ * This allows drivers to indicate that the given key has been
+ * removed from hardware acceleration, due to a new key that
+ * was added. Don't use this if the key can continue to be used
+ * for TX, if the key restriction is on RX only it is permitted
+ * to keep the key for TX only and not call this function.
+ *
+ * Due to locking constraints, it may only be called during
+ * @set_key. This function must be allowed to sleep, and the
+ * key it tries to disable may still be used until it returns.
+ */
+void ieee80211_key_removed(struct ieee80211_key_conf *key_conf);
+
 /* Rate control API */
 
 /**
@@ -2681,4 +2772,26 @@
 	return conf->channel_type != NL80211_CHAN_NO_HT;
 }
 
+static inline enum nl80211_iftype
+ieee80211_iftype_p2p(enum nl80211_iftype type, bool p2p)
+{
+	if (p2p) {
+		switch (type) {
+		case NL80211_IFTYPE_STATION:
+			return NL80211_IFTYPE_P2P_CLIENT;
+		case NL80211_IFTYPE_AP:
+			return NL80211_IFTYPE_P2P_GO;
+		default:
+			break;
+		}
+	}
+	return type;
+}
+
+static inline enum nl80211_iftype
+ieee80211_vif_type_p2p(struct ieee80211_vif *vif)
+{
+	return ieee80211_iftype_p2p(vif->type, vif->p2p);
+}
+
 #endif /* MAC80211_H */
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 242879b..55590ab 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -91,26 +91,28 @@
 #define NEIGH_CACHE_STAT_INC(tbl, field) this_cpu_inc((tbl)->stats->field)
 
 struct neighbour {
-	struct neighbour	*next;
+	struct neighbour __rcu	*next;
 	struct neigh_table	*tbl;
 	struct neigh_parms	*parms;
-	struct net_device		*dev;
-	unsigned long		used;
 	unsigned long		confirmed;
 	unsigned long		updated;
 	__u8			flags;
 	__u8			nud_state;
 	__u8			type;
 	__u8			dead;
-	atomic_t		probes;
-	rwlock_t		lock;
-	unsigned char		ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
-	struct hh_cache		*hh;
 	atomic_t		refcnt;
-	int			(*output)(struct sk_buff *skb);
 	struct sk_buff_head	arp_queue;
 	struct timer_list	timer;
+	unsigned long		used;
+	atomic_t		probes;
+	rwlock_t		lock;
+	seqlock_t		ha_lock;
+	unsigned char		ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
+	struct hh_cache		*hh;
+	int			(*output)(struct sk_buff *skb);
 	const struct neigh_ops	*ops;
+	struct rcu_head		rcu;
+	struct net_device	*dev;
 	u8			primary_key[0];
 };
 
@@ -138,13 +140,22 @@
  *	neighbour table manipulation
  */
 
+struct neigh_hash_table {
+	struct neighbour __rcu	**hash_buckets;
+	unsigned int		hash_mask;
+	__u32			hash_rnd;
+	struct rcu_head		rcu;
+};
+
 
 struct neigh_table {
 	struct neigh_table	*next;
 	int			family;
 	int			entry_size;
 	int			key_len;
-	__u32			(*hash)(const void *pkey, const struct net_device *);
+	__u32			(*hash)(const void *pkey,
+					const struct net_device *dev,
+					__u32 hash_rnd);
 	int			(*constructor)(struct neighbour *);
 	int			(*pconstructor)(struct pneigh_entry *);
 	void			(*pdestructor)(struct pneigh_entry *);
@@ -163,11 +174,9 @@
 	atomic_t		entries;
 	rwlock_t		lock;
 	unsigned long		last_rand;
-	struct kmem_cache		*kmem_cachep;
+	struct kmem_cache	*kmem_cachep;
 	struct neigh_statistics	__percpu *stats;
-	struct neighbour	**hash_buckets;
-	unsigned int		hash_mask;
-	__u32			hash_rnd;
+	struct neigh_hash_table __rcu *nht;
 	struct pneigh_entry	**phash_buckets;
 };
 
@@ -237,6 +246,7 @@
 struct neigh_seq_state {
 	struct seq_net_private p;
 	struct neigh_table *tbl;
+	struct neigh_hash_table *nht;
 	void *(*neigh_sub_iter)(struct neigh_seq_state *state,
 				struct neighbour *n, loff_t *pos);
 	unsigned int bucket;
@@ -293,7 +303,10 @@
 
 static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 {
-	neigh->used = jiffies;
+	unsigned long now = ACCESS_ONCE(jiffies);
+	
+	if (neigh->used != now)
+		neigh->used = now;
 	if (!(neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE)))
 		return __neigh_event_send(neigh, skb);
 	return 0;
@@ -364,4 +377,14 @@
 
 #define NEIGH_CB(skb)	((struct neighbour_cb *)(skb)->cb)
 
+static inline void neigh_ha_snapshot(char *dst, const struct neighbour *n,
+				     const struct net_device *dev)
+{
+	unsigned int seq;
+
+	do {
+		seq = read_seqbegin(&n->ha_lock);
+		memcpy(dst, n->ha, dev->addr_len);
+	} while (read_seqretry(&n->ha_lock, seq));
+}
 #endif
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index bd10a79..65af9a0 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -41,6 +41,8 @@
 						 * destroy on demand
 						 */
 #endif
+	spinlock_t		rules_mod_lock;
+
 	struct list_head	list;		/* list of network namespaces */
 	struct list_head	cleanup_list;	/* namespaces on death row */
 	struct list_head	exit_list;	/* Use only net_mutex */
@@ -52,7 +54,8 @@
 	struct ctl_table_set	sysctls;
 #endif
 
-	struct net_device       *loopback_dev;          /* The loopback */
+	struct sock 		*rtnl;			/* rtnetlink socket */
+	struct sock		*genl_sock;
 
 	struct list_head 	dev_base_head;
 	struct hlist_head 	*dev_name_head;
@@ -60,11 +63,9 @@
 
 	/* core fib_rules */
 	struct list_head	rules_ops;
-	spinlock_t		rules_mod_lock;
 
-	struct sock 		*rtnl;			/* rtnetlink socket */
-	struct sock		*genl_sock;
 
+	struct net_device       *loopback_dev;          /* The loopback */
 	struct netns_core	core;
 	struct netns_mib	mib;
 	struct netns_packet	packet;
@@ -84,13 +85,15 @@
 	struct sock		*nfnl;
 	struct sock		*nfnl_stash;
 #endif
-#ifdef CONFIG_XFRM
-	struct netns_xfrm	xfrm;
-#endif
 #ifdef CONFIG_WEXT_CORE
 	struct sk_buff_head	wext_nlevents;
 #endif
 	struct net_generic	*gen;
+
+	/* Note : following structs are cache line aligned */
+#ifdef CONFIG_XFRM
+	struct netns_xfrm	xfrm;
+#endif
 };
 
 
diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
new file mode 100644
index 0000000..94dd54d
--- /dev/null
+++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
@@ -0,0 +1,6 @@
+#ifndef _NF_DEFRAG_IPV6_H
+#define _NF_DEFRAG_IPV6_H
+
+extern void nf_defrag_ipv6_enable(void);
+
+#endif /* _NF_DEFRAG_IPV6_H */
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index e624dae..caf17db 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -75,7 +75,7 @@
 /* nf_conn feature for connections that have a helper */
 struct nf_conn_help {
 	/* Helper. if any */
-	struct nf_conntrack_helper *helper;
+	struct nf_conntrack_helper __rcu *helper;
 
 	union nf_conntrack_help help;
 
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 11e8150..0f8a8c5 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -67,9 +67,6 @@
 
 #define NF_CT_EXPECT_CLASS_DEFAULT	0
 
-#define NF_CT_EXPECT_PERMANENT	0x1
-#define NF_CT_EXPECT_INACTIVE	0x2
-
 int nf_conntrack_expect_init(struct net *net);
 void nf_conntrack_expect_fini(struct net *net);
 
@@ -85,9 +82,16 @@
 nf_ct_find_expectation(struct net *net, u16 zone,
 		       const struct nf_conntrack_tuple *tuple);
 
-void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
+void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
+				u32 pid, int report);
+static inline void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
+{
+	nf_ct_unlink_expect_report(exp, 0, 0);
+}
+
 void nf_ct_remove_expectations(struct nf_conn *ct);
 void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
+void nf_ct_remove_userspace_expectations(void);
 
 /* Allocate space for an expectation: this is mandatory before calling
    nf_ct_expect_related.  You will have to call put afterwards. */
diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h
index df17bac..93cc90d 100644
--- a/include/net/netfilter/nf_nat_protocol.h
+++ b/include/net/netfilter/nf_nat_protocol.h
@@ -45,9 +45,6 @@
 extern int nf_nat_protocol_register(const struct nf_nat_protocol *proto);
 extern void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto);
 
-extern const struct nf_nat_protocol *nf_nat_proto_find_get(u_int8_t protocol);
-extern void nf_nat_proto_put(const struct nf_nat_protocol *proto);
-
 /* Built-in protocols. */
 extern const struct nf_nat_protocol nf_nat_protocol_tcp;
 extern const struct nf_nat_protocol nf_nat_protocol_udp;
diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
index 208b46f..cd85b3b 100644
--- a/include/net/netfilter/nf_tproxy_core.h
+++ b/include/net/netfilter/nf_tproxy_core.h
@@ -5,15 +5,201 @@
 #include <linux/in.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <net/inet_sock.h>
+#include <net/inet_hashtables.h>
+#include <net/inet6_hashtables.h>
 #include <net/tcp.h>
 
+#define NFT_LOOKUP_ANY         0
+#define NFT_LOOKUP_LISTENER    1
+#define NFT_LOOKUP_ESTABLISHED 2
+
 /* look up and get a reference to a matching socket */
-extern struct sock *
+
+
+/* This function is used by the 'TPROXY' target and the 'socket'
+ * match. The following lookups are supported:
+ *
+ * Explicit TProxy target rule
+ * ===========================
+ *
+ * This is used when the user wants to intercept a connection matching
+ * an explicit iptables rule. In this case the sockets are assumed
+ * matching in preference order:
+ *
+ *   - match: if there's a fully established connection matching the
+ *     _packet_ tuple, it is returned, assuming the redirection
+ *     already took place and we process a packet belonging to an
+ *     established connection
+ *
+ *   - match: if there's a listening socket matching the redirection
+ *     (e.g. on-port & on-ip of the connection), it is returned,
+ *     regardless if it was bound to 0.0.0.0 or an explicit
+ *     address. The reasoning is that if there's an explicit rule, it
+ *     does not really matter if the listener is bound to an interface
+ *     or to 0. The user already stated that he wants redirection
+ *     (since he added the rule).
+ *
+ * "socket" match based redirection (no specific rule)
+ * ===================================================
+ *
+ * There are connections with dynamic endpoints (e.g. FTP data
+ * connection) that the user is unable to add explicit rules
+ * for. These are taken care of by a generic "socket" rule. It is
+ * assumed that the proxy application is trusted to open such
+ * connections without explicit iptables rule (except of course the
+ * generic 'socket' rule). In this case the following sockets are
+ * matched in preference order:
+ *
+ *   - match: if there's a fully established connection matching the
+ *     _packet_ tuple
+ *
+ *   - match: if there's a non-zero bound listener (possibly with a
+ *     non-local address) We don't accept zero-bound listeners, since
+ *     then local services could intercept traffic going through the
+ *     box.
+ *
+ * Please note that there's an overlap between what a TPROXY target
+ * and a socket match will match. Normally if you have both rules the
+ * "socket" match will be the first one, effectively all packets
+ * belonging to established connections going through that one.
+ */
+static inline struct sock *
 nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
 		      const __be32 saddr, const __be32 daddr,
 		      const __be16 sport, const __be16 dport,
-		      const struct net_device *in, bool listening);
+		      const struct net_device *in, int lookup_type)
+{
+	struct sock *sk;
+
+	/* look up socket */
+	switch (protocol) {
+	case IPPROTO_TCP:
+		switch (lookup_type) {
+		case NFT_LOOKUP_ANY:
+			sk = __inet_lookup(net, &tcp_hashinfo,
+					   saddr, sport, daddr, dport,
+					   in->ifindex);
+			break;
+		case NFT_LOOKUP_LISTENER:
+			sk = inet_lookup_listener(net, &tcp_hashinfo,
+						    daddr, dport,
+						    in->ifindex);
+
+			/* NOTE: we return listeners even if bound to
+			 * 0.0.0.0, those are filtered out in
+			 * xt_socket, since xt_TPROXY needs 0 bound
+			 * listeners too */
+
+			break;
+		case NFT_LOOKUP_ESTABLISHED:
+			sk = inet_lookup_established(net, &tcp_hashinfo,
+						    saddr, sport, daddr, dport,
+						    in->ifindex);
+			break;
+		default:
+			WARN_ON(1);
+			sk = NULL;
+			break;
+		}
+		break;
+	case IPPROTO_UDP:
+		sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
+				     in->ifindex);
+		if (sk && lookup_type != NFT_LOOKUP_ANY) {
+			int connected = (sk->sk_state == TCP_ESTABLISHED);
+			int wildcard = (inet_sk(sk)->inet_rcv_saddr == 0);
+
+			/* NOTE: we return listeners even if bound to
+			 * 0.0.0.0, those are filtered out in
+			 * xt_socket, since xt_TPROXY needs 0 bound
+			 * listeners too */
+			if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
+			    (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
+				sock_put(sk);
+				sk = NULL;
+			}
+		}
+		break;
+	default:
+		WARN_ON(1);
+		sk = NULL;
+	}
+
+	pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n",
+		 protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk);
+
+	return sk;
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static inline struct sock *
+nf_tproxy_get_sock_v6(struct net *net, const u8 protocol,
+		      const struct in6_addr *saddr, const struct in6_addr *daddr,
+		      const __be16 sport, const __be16 dport,
+		      const struct net_device *in, int lookup_type)
+{
+	struct sock *sk;
+
+	/* look up socket */
+	switch (protocol) {
+	case IPPROTO_TCP:
+		switch (lookup_type) {
+		case NFT_LOOKUP_ANY:
+			sk = inet6_lookup(net, &tcp_hashinfo,
+					  saddr, sport, daddr, dport,
+					  in->ifindex);
+			break;
+		case NFT_LOOKUP_LISTENER:
+			sk = inet6_lookup_listener(net, &tcp_hashinfo,
+						   daddr, ntohs(dport),
+						   in->ifindex);
+
+			/* NOTE: we return listeners even if bound to
+			 * 0.0.0.0, those are filtered out in
+			 * xt_socket, since xt_TPROXY needs 0 bound
+			 * listeners too */
+
+			break;
+		case NFT_LOOKUP_ESTABLISHED:
+			sk = __inet6_lookup_established(net, &tcp_hashinfo,
+							saddr, sport, daddr, ntohs(dport),
+							in->ifindex);
+			break;
+		default:
+			WARN_ON(1);
+			sk = NULL;
+			break;
+		}
+		break;
+	case IPPROTO_UDP:
+		sk = udp6_lib_lookup(net, saddr, sport, daddr, dport,
+				     in->ifindex);
+		if (sk && lookup_type != NFT_LOOKUP_ANY) {
+			int connected = (sk->sk_state == TCP_ESTABLISHED);
+			int wildcard = ipv6_addr_any(&inet6_sk(sk)->rcv_saddr);
+
+			/* NOTE: we return listeners even if bound to
+			 * 0.0.0.0, those are filtered out in
+			 * xt_socket, since xt_TPROXY needs 0 bound
+			 * listeners too */
+			if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
+			    (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
+				sock_put(sk);
+				sk = NULL;
+			}
+		}
+		break;
+	default:
+		WARN_ON(1);
+		sk = NULL;
+	}
+
+	pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n",
+		 protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk);
+
+	return sk;
+}
+#endif
 
 static inline void
 nf_tproxy_put_sock(struct sock *sk)
diff --git a/include/net/netfilter/xt_log.h b/include/net/netfilter/xt_log.h
new file mode 100644
index 0000000..0dfb34a
--- /dev/null
+++ b/include/net/netfilter/xt_log.h
@@ -0,0 +1,54 @@
+#define S_SIZE (1024 - (sizeof(unsigned int) + 1))
+
+struct sbuff {
+	unsigned int	count;
+	char		buf[S_SIZE + 1];
+};
+static struct sbuff emergency, *emergency_ptr = &emergency;
+
+static int sb_add(struct sbuff *m, const char *f, ...)
+{
+	va_list args;
+	int len;
+
+	if (likely(m->count < S_SIZE)) {
+		va_start(args, f);
+		len = vsnprintf(m->buf + m->count, S_SIZE - m->count, f, args);
+		va_end(args);
+		if (likely(m->count + len < S_SIZE)) {
+			m->count += len;
+			return 0;
+		}
+	}
+	m->count = S_SIZE;
+	printk_once(KERN_ERR KBUILD_MODNAME " please increase S_SIZE\n");
+	return -1;
+}
+
+static struct sbuff *sb_open(void)
+{
+	struct sbuff *m = kmalloc(sizeof(*m), GFP_ATOMIC);
+
+	if (unlikely(!m)) {
+		local_bh_disable();
+		do {
+			m = xchg(&emergency_ptr, NULL);
+		} while (!m);
+	}
+	m->count = 0;
+	return m;
+}
+
+static void sb_close(struct sbuff *m)
+{
+	m->buf[m->count] = 0;
+	printk("%s\n", m->buf);
+
+	if (likely(m != &emergency))
+		kfree(m);
+	else {
+		xchg(&emergency_ptr, m);
+		local_bh_enable();
+	}
+}
+
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 74f119a..748f91f 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -43,10 +43,6 @@
 	unsigned int		policy_count[XFRM_POLICY_MAX * 2];
 	struct work_struct	policy_hash_work;
 
-	struct dst_ops		xfrm4_dst_ops;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-	struct dst_ops		xfrm6_dst_ops;
-#endif
 
 	struct sock		*nlsk;
 	struct sock		*nlsk_stash;
@@ -58,6 +54,11 @@
 #ifdef CONFIG_SYSCTL
 	struct ctl_table_header	*sysctl_hdr;
 #endif
+
+	struct dst_ops		xfrm4_dst_ops;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	struct dst_ops		xfrm6_dst_ops;
+#endif
 };
 
 #endif
diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h
index 35672b1..b60b28c 100644
--- a/include/net/phonet/pep.h
+++ b/include/net/phonet/pep.h
@@ -45,6 +45,10 @@
 	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)
@@ -77,6 +81,11 @@
 #define MAX_PNPIPE_HEADER (MAX_PHONET_HEADER + 4)
 
 enum {
+	PNS_PIPE_CREATE_REQ = 0x00,
+	PNS_PIPE_CREATE_RESP,
+	PNS_PIPE_REMOVE_REQ,
+	PNS_PIPE_REMOVE_RESP,
+
 	PNS_PIPE_DATA = 0x20,
 	PNS_PIPE_ALIGNED_DATA,
 
@@ -160,4 +169,21 @@
 	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 7b11407..d5df797 100644
--- a/include/net/phonet/phonet.h
+++ b/include/net/phonet/phonet.h
@@ -54,6 +54,11 @@
 void pn_sock_unhash(struct sock *sk);
 int pn_sock_get_port(struct sock *sk, unsigned short sport);
 
+struct sock *pn_find_sock_by_res(struct net *net, u8 res);
+int pn_sock_bind_res(struct sock *sock, u8 res);
+int pn_sock_unbind_res(struct sock *sk, u8 res);
+void pn_sock_unbind_all_res(struct sock *sk);
+
 int pn_skb_send(struct sock *sk, struct sk_buff *skb,
 		const struct sockaddr_pn *target);
 
diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h
index 2d16783..13649eb 100644
--- a/include/net/phonet/pn_dev.h
+++ b/include/net/phonet/pn_dev.h
@@ -57,5 +57,6 @@
 #define PN_NO_ADDR	0xff
 
 extern const struct file_operations pn_sock_seq_fops;
+extern const struct file_operations pn_res_seq_fops;
 
 #endif
diff --git a/include/net/raw.h b/include/net/raw.h
index 43c5750..42ce6fe 100644
--- a/include/net/raw.h
+++ b/include/net/raw.h
@@ -45,7 +45,10 @@
 	struct raw_hashinfo *h;
 };
 
-#define raw_seq_private(seq) ((struct raw_iter_state *)(seq)->private)
+static inline struct raw_iter_state *raw_seq_private(struct seq_file *seq)
+{
+	return seq->private;
+}
 void *raw_seq_start(struct seq_file *seq, loff_t *pos);
 void *raw_seq_next(struct seq_file *seq, void *v, loff_t *pos);
 void raw_seq_stop(struct seq_file *seq, void *v);
diff --git a/include/net/route.h b/include/net/route.h
index bd732d6..7e5e73b 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -199,6 +199,8 @@
 		fl.fl_ip_sport = sport;
 		fl.fl_ip_dport = dport;
 		fl.proto = protocol;
+		if (inet_sk(sk)->transparent)
+			fl.flags |= FLOWI_FLAG_ANYSRC;
 		ip_rt_put(*rp);
 		*rp = NULL;
 		security_sk_classify_flow(sk, &fl);
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index af60fd0..e013c68 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -79,7 +79,6 @@
 
 extern int	__rtnl_link_register(struct rtnl_link_ops *ops);
 extern void	__rtnl_link_unregister(struct rtnl_link_ops *ops);
-extern void	rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops);
 
 extern int	rtnl_link_register(struct rtnl_link_ops *ops);
 extern void	rtnl_link_unregister(struct rtnl_link_ops *ops);
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 3c8728a..ea1f8a8 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -328,8 +328,7 @@
 extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);
 extern struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
 				 struct Qdisc_ops *ops);
-extern struct Qdisc *qdisc_create_dflt(struct net_device *dev,
-				       struct netdev_queue *dev_queue,
+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);
@@ -601,7 +600,7 @@
 		slot = 0;
 	slot >>= rtab->rate.cell_log;
 	if (slot > 255)
-		return (rtab->data[255]*(slot >> 8) + rtab->data[slot & 0xFF]);
+		return rtab->data[255]*(slot >> 8) + rtab->data[slot & 0xFF];
 	return rtab->data[slot];
 }
 
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 65946bc..505845d 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -275,24 +275,35 @@
 /* Print debugging messages.  */
 #if SCTP_DEBUG
 extern int sctp_debug_flag;
-#define SCTP_DEBUG_PRINTK(whatever...) \
-	((void) (sctp_debug_flag && printk(KERN_DEBUG whatever)))
-#define SCTP_DEBUG_PRINTK_IPADDR(lead, trail, leadparm, saddr, otherparms...) \
-	if (sctp_debug_flag) { \
-		if (saddr->sa.sa_family == AF_INET6) { \
-			printk(KERN_DEBUG \
-			       lead "%pI6" trail, \
-			       leadparm, \
-			       &saddr->v6.sin6_addr, \
-			       otherparms); \
-		} else { \
-			printk(KERN_DEBUG \
-			       lead "%pI4" trail, \
-			       leadparm, \
-			       &saddr->v4.sin_addr.s_addr, \
-			       otherparms); \
-		} \
-	}
+#define SCTP_DEBUG_PRINTK(fmt, args...)			\
+do {							\
+	if (sctp_debug_flag)				\
+		printk(KERN_DEBUG pr_fmt(fmt), ##args);	\
+} while (0)
+#define SCTP_DEBUG_PRINTK_CONT(fmt, args...)		\
+do {							\
+	if (sctp_debug_flag)				\
+		pr_cont(fmt, ##args);			\
+} while (0)
+#define SCTP_DEBUG_PRINTK_IPADDR(fmt_lead, fmt_trail,			\
+				 args_lead, saddr, args_trail...)	\
+do {									\
+	if (sctp_debug_flag) {						\
+		if (saddr->sa.sa_family == AF_INET6) {			\
+			printk(KERN_DEBUG				\
+			       pr_fmt(fmt_lead "%pI6" fmt_trail),	\
+			       args_lead,				\
+			       &saddr->v6.sin6_addr,			\
+			       args_trail);				\
+		} else {						\
+			printk(KERN_DEBUG				\
+			       pr_fmt(fmt_lead "%pI4" fmt_trail),	\
+			       args_lead,				\
+			       &saddr->v4.sin_addr.s_addr,		\
+			       args_trail);				\
+		}							\
+	}								\
+} while (0)
 #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; }
 #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; }
 
@@ -306,6 +317,7 @@
 #else	/* SCTP_DEBUG */
 
 #define SCTP_DEBUG_PRINTK(whatever...)
+#define SCTP_DEBUG_PRINTK_CONT(fmt, args...)
 #define SCTP_DEBUG_PRINTK_IPADDR(whatever...)
 #define SCTP_ENABLE_DEBUG
 #define SCTP_DISABLE_DEBUG
@@ -393,7 +405,7 @@
 /* Map an association to an assoc_id. */
 static inline sctp_assoc_t sctp_assoc2id(const struct sctp_association *asoc)
 {
-	return (asoc?asoc->assoc_id:0);
+	return asoc ? asoc->assoc_id : 0;
 }
 
 /* Look up the association by its id.  */
@@ -461,7 +473,7 @@
 /* Tests if the list has one and only one entry. */
 static inline int sctp_list_single_entry(struct list_head *head)
 {
-	return ((head->next != head) && (head->next == head->prev));
+	return (head->next != head) && (head->next == head->prev);
 }
 
 /* Generate a random jitter in the range of -50% ~ +50% of input RTO. */
@@ -619,13 +631,13 @@
 /* This is the hash function for the SCTP port hash table. */
 static inline int sctp_phashfn(__u16 lport)
 {
-	return (lport & (sctp_port_hashsize - 1));
+	return lport & (sctp_port_hashsize - 1);
 }
 
 /* This is the hash function for the endpoint hash table. */
 static inline int sctp_ep_hashfn(__u16 lport)
 {
-	return (lport & (sctp_ep_hashsize - 1));
+	return lport & (sctp_ep_hashsize - 1);
 }
 
 /* This is the hash function for the association hash table. */
@@ -633,7 +645,7 @@
 {
 	int h = (lport << 16) + rport;
 	h ^= h>>8;
-	return (h & (sctp_assoc_hashsize - 1));
+	return h & (sctp_assoc_hashsize - 1);
 }
 
 /* This is the hash function for the association hash table.  This is
@@ -644,7 +656,7 @@
 {
 	int h = (lport << 16) + rport;
 	h ^= vtag;
-	return (h & (sctp_assoc_hashsize-1));
+	return h & (sctp_assoc_hashsize - 1);
 }
 
 #define sctp_for_each_hentry(epb, node, head) \
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 4088c89..9352d12 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -345,12 +345,12 @@
 
 static inline int TSN_lt(__u32 s, __u32 t)
 {
-	return (((s) - (t)) & TSN_SIGN_BIT);
+	return ((s) - (t)) & TSN_SIGN_BIT;
 }
 
 static inline int TSN_lte(__u32 s, __u32 t)
 {
-	return (((s) == (t)) || (((s) - (t)) & TSN_SIGN_BIT));
+	return ((s) == (t)) || (((s) - (t)) & TSN_SIGN_BIT);
 }
 
 /* Compare two SSNs */
@@ -369,12 +369,12 @@
 
 static inline int SSN_lt(__u16 s, __u16 t)
 {
-	return (((s) - (t)) & SSN_SIGN_BIT);
+	return ((s) - (t)) & SSN_SIGN_BIT;
 }
 
 static inline int SSN_lte(__u16 s, __u16 t)
 {
-	return (((s) == (t)) || (((s) - (t)) & SSN_SIGN_BIT));
+	return ((s) == (t)) || (((s) - (t)) & SSN_SIGN_BIT);
 }
 
 /*
@@ -388,7 +388,7 @@
 
 static inline int ADDIP_SERIAL_gte(__u16 s, __u16 t)
 {
-	return (((s) == (t)) || (((t) - (s)) & ADDIP_SERIAL_SIGN_BIT));
+	return ((s) == (t)) || (((t) - (s)) & ADDIP_SERIAL_SIGN_BIT);
 }
 
 /* Check VTAG of the packet matches the sender's own tag. */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index f9e7473..69fef4f 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -847,7 +847,7 @@
 
 static inline int sctp_packet_empty(struct sctp_packet *packet)
 {
-	return (packet->size == packet->overhead);
+	return packet->size == packet->overhead;
 }
 
 /* This represents a remote transport address.
diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h
index 4aabc5a..e7728bc 100644
--- a/include/net/sctp/tsnmap.h
+++ b/include/net/sctp/tsnmap.h
@@ -157,7 +157,7 @@
 /* Is there a gap in the TSN map?  */
 static inline int sctp_tsnmap_has_gap(const struct sctp_tsnmap *map)
 {
-	return (map->cumulative_tsn_ack_point != map->max_tsn_seen);
+	return map->cumulative_tsn_ack_point != map->max_tsn_seen;
 }
 
 /* Mark a duplicate TSN.  Note:  limit the storage of duplicate TSN
diff --git a/include/net/sock.h b/include/net/sock.h
index adab9dc..73a4f97 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1558,7 +1558,11 @@
 }
 
 #define SOCK_MIN_SNDBUF 2048
-#define SOCK_MIN_RCVBUF 256
+/*
+ * Since sk_rmem_alloc sums skb->truesize, even a small frame might need
+ * sizeof(sk_buff) + MTU + padding, unless net driver perform copybreak
+ */
+#define SOCK_MIN_RCVBUF (2048 + sizeof(struct sk_buff))
 
 static inline void sk_stream_moderate_sndbuf(struct sock *sk)
 {
@@ -1670,17 +1674,13 @@
 
 /**
  * sock_tx_timestamp - checks whether the outgoing packet is to be time stamped
- * @msg:	outgoing packet
  * @sk:		socket sending this packet
- * @shtx:	filled with instructions for time stamping
+ * @tx_flags:	filled with instructions for time stamping
  *
  * Currently only depends on SOCK_TIMESTAMPING* flags. Returns error code if
  * parameters are invalid.
  */
-extern int sock_tx_timestamp(struct msghdr *msg,
-			     struct sock *sk,
-			     union skb_shared_tx *shtx);
-
+extern int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags);
 
 /**
  * sk_eat_skb - Release a skb if it is no longer needed
diff --git a/include/net/tc_act/tc_csum.h b/include/net/tc_act/tc_csum.h
new file mode 100644
index 0000000..9e8710b
--- /dev/null
+++ b/include/net/tc_act/tc_csum.h
@@ -0,0 +1,15 @@
+#ifndef __NET_TC_CSUM_H
+#define __NET_TC_CSUM_H
+
+#include <linux/types.h>
+#include <net/act_api.h>
+
+struct tcf_csum {
+	struct tcf_common common;
+
+	u32 update_flags;
+};
+#define to_tcf_csum(pc) \
+	container_of(pc,struct tcf_csum,common)
+
+#endif /* __NET_TC_CSUM_H */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 3e4b33e..4fee042 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -346,8 +346,6 @@
 	}
 }
 
-extern void tcp_enter_quickack_mode(struct sock *sk);
-
 #define	TCP_ECN_OK		1
 #define	TCP_ECN_QUEUE_CWR	2
 #define	TCP_ECN_DEMAND_CWR	4
@@ -803,6 +801,15 @@
 /* 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);
 
diff --git a/include/net/tipc/tipc.h b/include/net/tipc/tipc.h
index 15af6dc..1e0645e 100644
--- a/include/net/tipc/tipc.h
+++ b/include/net/tipc/tipc.h
@@ -50,8 +50,6 @@
  * TIPC operating mode routines
  */
 
-u32 tipc_get_addr(void);
-
 #define TIPC_NOT_RUNNING  0
 #define TIPC_NODE_MODE    1
 #define TIPC_NET_MODE     2
@@ -62,8 +60,6 @@
 
 void tipc_detach(unsigned int userref);
 
-int tipc_get_mode(void);
-
 /*
  * TIPC port manipulation routines
  */
@@ -153,12 +149,6 @@
 
 int tipc_shutdown(u32 ref);
 
-int tipc_isconnected(u32 portref, int *isconnected);
-
-int tipc_peer(u32 portref, struct tipc_portid *peer);
-
-int tipc_ref_valid(u32 portref); 
-
 /*
  * TIPC messaging routines
  */
@@ -170,38 +160,12 @@
 	      unsigned int num_sect,
 	      struct iovec const *msg_sect);
 
-int tipc_send_buf(u32 portref,
-		  struct sk_buff *buf,
-		  unsigned int dsz);
-
 int tipc_send2name(u32 portref, 
 		   struct tipc_name const *name, 
 		   u32 domain,
 		   unsigned int num_sect,
 		   struct iovec const *msg_sect);
 
-int tipc_send_buf2name(u32 portref,
-		       struct tipc_name const *name,
-		       u32 domain,
-		       struct sk_buff *buf,
-		       unsigned int dsz);
-
-int tipc_forward2name(u32 portref, 
-		      struct tipc_name const *name, 
-		      u32 domain,
-		      unsigned int section_count,
-		      struct iovec const *msg_sect,
-		      struct tipc_portid const *origin,
-		      unsigned int importance);
-
-int tipc_forward_buf2name(u32 portref,
-			  struct tipc_name const *name,
-			  u32 domain,
-			  struct sk_buff *buf,
-			  unsigned int dsz,
-			  struct tipc_portid const *orig,
-			  unsigned int importance);
-
 int tipc_send2port(u32 portref,
 		   struct tipc_portid const *dest,
 		   unsigned int num_sect,
@@ -212,46 +176,11 @@
 		       struct sk_buff *buf,
 		       unsigned int dsz);
 
-int tipc_forward2port(u32 portref,
-		      struct tipc_portid const *dest,
-		      unsigned int num_sect,
-		      struct iovec const *msg_sect,
-		      struct tipc_portid const *origin,
-		      unsigned int importance);
-
-int tipc_forward_buf2port(u32 portref,
-			  struct tipc_portid const *dest,
-			  struct sk_buff *buf,
-			  unsigned int dsz,
-			  struct tipc_portid const *orig,
-			  unsigned int importance);
-
 int tipc_multicast(u32 portref, 
 		   struct tipc_name_seq const *seq, 
 		   u32 domain,	/* currently unused */
 		   unsigned int section_count,
 		   struct iovec const *msg);
-
-#if 0
-int tipc_multicast_buf(u32 portref, 
-		       struct tipc_name_seq const *seq, 
-		       u32 domain,
-		       void *buf,
-		       unsigned int size);
-#endif
-
-/*
- * TIPC subscription routines
- */
-
-int tipc_ispublished(struct tipc_name const *name);
-
-/*
- * Get number of available nodes within specified domain (excluding own node)
- */
-
-unsigned int tipc_available_nodes(const u32 domain);
-
 #endif
 
 #endif
diff --git a/include/net/tipc/tipc_msg.h b/include/net/tipc/tipc_msg.h
index 2e159a8..ffe50b4e 100644
--- a/include/net/tipc/tipc_msg.h
+++ b/include/net/tipc/tipc_msg.h
@@ -107,7 +107,7 @@
 
 static inline int msg_short(struct tipc_msg *m)
 {
-	return (msg_hdr_sz(m) == 24);
+	return msg_hdr_sz(m) == 24;
 }
 
 static inline u32 msg_size(struct tipc_msg *m)
@@ -117,7 +117,7 @@
 
 static inline u32 msg_data_sz(struct tipc_msg *m)
 {
-	return (msg_size(m) - msg_hdr_sz(m));
+	return msg_size(m) - msg_hdr_sz(m);
 }
 
 static inline unchar *msg_data(struct tipc_msg *m)
@@ -132,17 +132,17 @@
 
 static inline u32 msg_named(struct tipc_msg *m)
 {
-	return (msg_type(m) == TIPC_NAMED_MSG);
+	return msg_type(m) == TIPC_NAMED_MSG;
 }
 
 static inline u32 msg_mcast(struct tipc_msg *m)
 {
-	return (msg_type(m) == TIPC_MCAST_MSG);
+	return msg_type(m) == TIPC_MCAST_MSG;
 }
 
 static inline u32 msg_connected(struct tipc_msg *m)
 {
-	return (msg_type(m) == TIPC_CONN_MSG);
+	return msg_type(m) == TIPC_CONN_MSG;
 }
 
 static inline u32 msg_errcode(struct tipc_msg *m)
diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h
index c54917cb..1893aaf 100644
--- a/include/net/tipc/tipc_port.h
+++ b/include/net/tipc/tipc_port.h
@@ -88,8 +88,6 @@
 
 struct tipc_port *tipc_get_port(const u32 ref);
 
-void *tipc_get_handle(const u32 ref);
-
 /*
  * The following routines require that the port be locked on entry
  */
diff --git a/include/net/udp.h b/include/net/udp.h
index a184d34..200b828 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -183,6 +183,9 @@
 extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
 				    __be32 daddr, __be16 dport,
 				    int dif);
+extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
+				    const struct in6_addr *daddr, __be16 dport,
+				    int dif);
 
 /*
  * 	SNMP statistics for UDP and UDP-Lite
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index fc8f36d..f28d7c9 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -298,8 +298,8 @@
 	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_state *x, struct flowi *fl,
-						struct xfrm_tmpl *tmpl,
+	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);
 	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);
@@ -1419,7 +1419,6 @@
 extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
 extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
 extern __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
-extern void xfrm6_tunnel_free_spi(struct net *net, xfrm_address_t *saddr);
 extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr);
 extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
@@ -1466,8 +1465,6 @@
 				 xfrm_address_t *saddr, int create,
 				 unsigned short family);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
-extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
-			  struct flowi *fl, int family, int strict);
 
 #ifdef CONFIG_XFRM_MIGRATE
 extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
deleted file mode 100644
index 68d8bde..0000000
--- a/include/pcmcia/cs.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * cs.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.
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
- *
- * (C) 1999             David A. Hinds
- */
-
-#ifndef _LINUX_CS_H
-#define _LINUX_CS_H
-
-#ifdef __KERNEL__
-#include <linux/interrupt.h>
-#endif
-
-/* ModifyConfiguration */
-typedef struct modconf_t {
-    u_int	Attributes;
-    u_int	Vcc, Vpp1, Vpp2;
-} modconf_t;
-
-/* Attributes for ModifyConfiguration */
-#define CONF_IRQ_CHANGE_VALID	0x0100
-#define CONF_VCC_CHANGE_VALID	0x0200
-#define CONF_VPP1_CHANGE_VALID	0x0400
-#define CONF_VPP2_CHANGE_VALID	0x0800
-#define CONF_IO_CHANGE_WIDTH	0x1000
-
-/* For RequestConfiguration */
-typedef struct config_req_t {
-    u_int	Attributes;
-    u_int	Vpp; /* both Vpp1 and Vpp2 */
-    u_int	IntType;
-    u_int	ConfigBase;
-    u_char	Status, Pin, Copy, ExtStatus;
-    u_char	ConfigIndex;
-    u_int	Present;
-} config_req_t;
-
-/* Attributes for RequestConfiguration */
-#define CONF_ENABLE_IRQ		0x01
-#define CONF_ENABLE_DMA		0x02
-#define CONF_ENABLE_SPKR	0x04
-#define CONF_ENABLE_PULSE_IRQ	0x08
-#define CONF_VALID_CLIENT	0x100
-
-/* IntType field */
-#define INT_MEMORY		0x01
-#define INT_MEMORY_AND_IO	0x02
-#define INT_CARDBUS		0x04
-#define INT_ZOOMED_VIDEO	0x08
-
-/* Configuration registers present */
-#define PRESENT_OPTION		0x001
-#define PRESENT_STATUS		0x002
-#define PRESENT_PIN_REPLACE	0x004
-#define PRESENT_COPY		0x008
-#define PRESENT_EXT_STATUS	0x010
-#define PRESENT_IOBASE_0	0x020
-#define PRESENT_IOBASE_1	0x040
-#define PRESENT_IOBASE_2	0x080
-#define PRESENT_IOBASE_3	0x100
-#define PRESENT_IOSIZE		0x200
-
-/* For RequestWindow */
-typedef struct win_req_t {
-    u_int	Attributes;
-    u_long	Base;
-    u_int	Size;
-    u_int	AccessSpeed;
-} win_req_t;
-
-/* Attributes for RequestWindow */
-#define WIN_MEMORY_TYPE_CM	0x00 /* default */
-#define WIN_MEMORY_TYPE_AM	0x20 /* MAP_ATTRIB */
-#define WIN_DATA_WIDTH_8	0x00 /* default */
-#define WIN_DATA_WIDTH_16	0x02 /* MAP_16BIT */
-#define WIN_ENABLE		0x01 /* MAP_ACTIVE */
-#define WIN_USE_WAIT		0x40 /* MAP_USE_WAIT */
-
-#define WIN_FLAGS_MAP		0x63 /* MAP_ATTRIB | MAP_16BIT | MAP_ACTIVE |
-					MAP_USE_WAIT */
-#define WIN_FLAGS_REQ		0x1c /* mapping to socket->win[i]:
-					0x04 -> 0
-					0x08 -> 1
-					0x0c -> 2
-					0x10 -> 3 */
-
-#endif /* _LINUX_CS_H */
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 70c58ed..8479b66 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -24,9 +24,11 @@
 
 #ifdef __KERNEL__
 #include <linux/device.h>
+#include <linux/interrupt.h>
 #include <pcmcia/ss.h>
 #include <asm/atomic.h>
 
+
 /*
  * PCMCIA device drivers (16-bit cards only; 32-bit cards require CardBus
  * a.k.a. PCI drivers
@@ -36,8 +38,6 @@
 struct config_t;
 struct net_device;
 
-typedef struct resource *window_handle_t;
-
 /* dynamic device IDs for PCMCIA device drivers. See
  * Documentation/pcmcia/driver.txt for details.
 */
@@ -47,6 +47,8 @@
 };
 
 struct pcmcia_driver {
+	const char		*name;
+
 	int (*probe)		(struct pcmcia_device *dev);
 	void (*remove)		(struct pcmcia_device *dev);
 
@@ -90,15 +92,17 @@
 
 	struct list_head	socket_device_list;
 
-	/* deprecated, will be cleaned up soon */
-	config_req_t		conf;
-	window_handle_t		win;
-
 	/* device setup */
 	unsigned int		irq;
 	struct resource		*resource[PCMCIA_NUM_RESOURCES];
+	resource_size_t		card_addr;	/* for the 1st IOMEM resource */
+	unsigned int		vpp;
 
-	unsigned int		io_lines; /* number of I/O lines */
+	unsigned int		config_flags;	/* CONF_ENABLE_ flags below */
+	unsigned int		config_base;
+	unsigned int		config_index;
+	unsigned int		config_regs;	/* PRESENT_ flags below */
+	unsigned int		io_lines;	/* number of I/O lines */
 
 	/* Is the device suspended? */
 	u16			suspended:1;
@@ -174,9 +178,6 @@
 /* loop CIS entries for valid configuration */
 int pcmcia_loop_config(struct pcmcia_device *p_dev,
 		       int	(*conf_check)	(struct pcmcia_device *p_dev,
-						 cistpl_cftable_entry_t *cf,
-						 cistpl_cftable_entry_t *dflt,
-						 unsigned int vcc,
 						 void *priv_data),
 		       void *priv_data);
 
@@ -206,16 +207,17 @@
 int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
 				irq_handler_t handler);
 
-int pcmcia_request_configuration(struct pcmcia_device *p_dev,
-				 config_req_t *req);
+int pcmcia_enable_device(struct pcmcia_device *p_dev);
 
-int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req,
-			  window_handle_t *wh);
-int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t win);
-int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t win,
+int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res,
+			unsigned int speed);
+int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res);
+int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
 			unsigned int offset);
 
-int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
+int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp);
+int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev);
+
 void pcmcia_disable_device(struct pcmcia_device *p_dev);
 
 /* IO ports */
@@ -224,15 +226,48 @@
 #define IO_DATA_PATH_WIDTH_16	0x08
 #define IO_DATA_PATH_WIDTH_AUTO	0x10
 
-/* convert flag found in cfgtable to data path width parameter */
-static inline int pcmcia_io_cfg_data_width(unsigned int flags)
-{
-	if (!(flags & CISTPL_IO_8BIT))
-		return IO_DATA_PATH_WIDTH_16;
-	if (!(flags & CISTPL_IO_16BIT))
-		return IO_DATA_PATH_WIDTH_8;
-	return IO_DATA_PATH_WIDTH_AUTO;
-}
+/* IO memory */
+#define WIN_MEMORY_TYPE_CM	0x00 /* default */
+#define WIN_MEMORY_TYPE_AM	0x20 /* MAP_ATTRIB */
+#define WIN_DATA_WIDTH_8	0x00 /* default */
+#define WIN_DATA_WIDTH_16	0x02 /* MAP_16BIT */
+#define WIN_ENABLE		0x01 /* MAP_ACTIVE */
+#define WIN_USE_WAIT		0x40 /* MAP_USE_WAIT */
+
+#define WIN_FLAGS_MAP		0x63 /* MAP_ATTRIB | MAP_16BIT | MAP_ACTIVE |
+					MAP_USE_WAIT */
+#define WIN_FLAGS_REQ		0x1c /* mapping to socket->win[i]:
+					0x04 -> 0
+					0x08 -> 1
+					0x0c -> 2
+					0x10 -> 3 */
+
+/* config_reg{ister}s present for this PCMCIA device */
+#define PRESENT_OPTION		0x001
+#define PRESENT_STATUS		0x002
+#define PRESENT_PIN_REPLACE	0x004
+#define PRESENT_COPY		0x008
+#define PRESENT_EXT_STATUS	0x010
+#define PRESENT_IOBASE_0	0x020
+#define PRESENT_IOBASE_1	0x040
+#define PRESENT_IOBASE_2	0x080
+#define PRESENT_IOBASE_3	0x100
+#define PRESENT_IOSIZE		0x200
+
+/* flags to be passed to pcmcia_enable_device() */
+#define CONF_ENABLE_IRQ         0x0001
+#define CONF_ENABLE_SPKR        0x0002
+#define CONF_ENABLE_PULSE_IRQ   0x0004
+#define CONF_ENABLE_ESR         0x0008
+#define CONF_ENABLE_IOCARD	0x0010 /* auto-enabled if IO resources or IRQ
+					* (CONF_ENABLE_IRQ) in use */
+
+/* flags used by pcmcia_loop_config() autoconfiguration */
+#define CONF_AUTO_CHECK_VCC	0x0100 /* check for matching Vcc? */
+#define CONF_AUTO_SET_VPP	0x0200 /* set Vpp? */
+#define CONF_AUTO_AUDIO		0x0400 /* enable audio line? */
+#define CONF_AUTO_SET_IO	0x0800 /* set ->resource[0,1] */
+#define CONF_AUTO_SET_IOMEM	0x1000 /* set ->resource[2] */
 
 #endif /* __KERNEL__ */
 
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 626b63c..731cde0 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -19,7 +19,6 @@
 #include <linux/sched.h>	/* task_struct, completion */
 #include <linux/mutex.h>
 
-#include <pcmcia/cs.h>
 #ifdef CONFIG_CARDBUS
 #include <linux/pci.h>
 #endif
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index d06e13b..3dec194 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -205,6 +205,7 @@
         };
 
         void *lldd_dev;
+	int gone;
 };
 
 struct sas_discovery_event {
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 8fcb6e0..216af85 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -32,6 +32,12 @@
 #endif
 
 /*
+ * DIX-capable adapters effectively support infinite chaining for the
+ * protection information scatterlist
+ */
+#define SCSI_MAX_PROT_SG_SEGMENTS	0xFFFF
+
+/*
  * Special value for scanning to specify scanning or rescanning of all
  * possible channels, (target) ids, or luns on a given shost.
  */
@@ -67,6 +73,7 @@
 #define SEND_DIAGNOSTIC       0x1d
 #define ALLOW_MEDIUM_REMOVAL  0x1e
 
+#define READ_FORMAT_CAPACITIES 0x23
 #define SET_WINDOW            0x24
 #define READ_CAPACITY         0x25
 #define READ_10               0x28
@@ -96,6 +103,7 @@
 #define WRITE_SAME            0x41
 #define UNMAP		      0x42
 #define READ_TOC              0x43
+#define READ_HEADER           0x44
 #define LOG_SELECT            0x4c
 #define LOG_SENSE             0x4d
 #define XDWRITEREAD_10        0x53
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 50cb34f..85867dc 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -148,6 +148,8 @@
 	unsigned retry_hwerror:1;	/* Retry HARDWARE_ERROR */
 	unsigned last_sector_bug:1;	/* do not use multisector accesses on
 					   SD_LAST_BUGGY_SECTORS */
+	unsigned no_read_disc_info:1;	/* Avoid READ_DISC_INFO cmds */
+	unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
 	unsigned is_visible:1;	/* is the device visible in sysfs */
 
 	DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index b7bdecb..d0a6a84 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -388,6 +388,7 @@
 	 * of scatter-gather.
 	 */
 	unsigned short sg_tablesize;
+	unsigned short sg_prot_tablesize;
 
 	/*
 	 * Set this if the host adapter has limitations beside segment count.
@@ -599,6 +600,7 @@
 	int can_queue;
 	short cmd_per_lun;
 	short unsigned int sg_tablesize;
+	short unsigned int sg_prot_tablesize;
 	short unsigned int max_sectors;
 	unsigned long dma_boundary;
 	/* 
@@ -823,6 +825,11 @@
 	return shost->prot_capabilities;
 }
 
+static inline int scsi_host_prot_dma(struct Scsi_Host *shost)
+{
+	return shost->prot_capabilities >= SHOST_DIX_TYPE0_PROTECTION;
+}
+
 static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsigned int target_type)
 {
 	static unsigned char cap[] = { 0,
diff --git a/include/scsi/scsi_tcq.h b/include/scsi/scsi_tcq.h
index 1723138..d6e7994 100644
--- a/include/scsi/scsi_tcq.h
+++ b/include/scsi/scsi_tcq.h
@@ -97,13 +97,9 @@
 static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg)
 {
         struct request *req = cmd->request;
-	struct scsi_device *sdev = cmd->device;
 
         if (blk_rq_tagged(req)) {
-		if (sdev->ordered_tags && req->cmd_flags & REQ_HARDBARRIER)
-        	        *msg++ = MSG_ORDERED_TAG;
-        	else
-        	        *msg++ = MSG_SIMPLE_TAG;
+		*msg++ = MSG_SIMPLE_TAG;
         	*msg++ = req->tag;
         	return 2;
 	}
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 87d81b3..59816fe 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -496,6 +496,7 @@
 	u64 fabric_name;
 	char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
 	char system_hostname[FC_SYMBOLIC_NAME_SIZE];
+	u32 dev_loss_tmo;
 
 	/* Private (Transport-managed) Attributes */
 	enum fc_tgtid_binding_type  tgtid_bind_type;
@@ -580,6 +581,8 @@
 	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name)
 #define fc_host_devloss_work_q(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
+#define fc_host_dev_loss_tmo(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo)
 
 
 struct fc_bsg_buffer {
diff --git a/include/sound/core.h b/include/sound/core.h
index 89e0ac1..df26ebb 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -133,9 +133,7 @@
 	int free_on_last_close;		/* free in context of file_release */
 	wait_queue_head_t shutdown_sleep;
 	struct device *dev;		/* device assigned to this card */
-#ifndef CONFIG_SYSFS_DEPRECATED
 	struct device *card_dev;	/* cardX object for sysfs */
-#endif
 
 #ifdef CONFIG_PM
 	unsigned int power_state;	/* power state */
@@ -196,11 +194,7 @@
 /* return a device pointer linked to each sound device as a parent */
 static inline struct device *snd_card_get_device_link(struct snd_card *card)
 {
-#ifdef CONFIG_SYSFS_DEPRECATED
-	return card ? card->dev : NULL;
-#else
 	return card ? card->card_dev : NULL;
-#endif
 }
 
 /* sound.c */
diff --git a/include/trace/events/irq.h b/include/trace/events/irq.h
index 0e4cfb6..6fa7cbab7 100644
--- a/include/trace/events/irq.h
+++ b/include/trace/events/irq.h
@@ -5,7 +5,9 @@
 #define _TRACE_IRQ_H
 
 #include <linux/tracepoint.h>
-#include <linux/interrupt.h>
+
+struct irqaction;
+struct softirq_action;
 
 #define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
 #define show_softirq_name(val)				\
@@ -93,7 +95,10 @@
 	),
 
 	TP_fast_assign(
-		__entry->vec = (int)(h - vec);
+		if (vec)
+			__entry->vec = (int)(h - vec);
+		else
+			__entry->vec = (int)(long)h;
 	),
 
 	TP_printk("vec=%d [action=%s]", __entry->vec,
@@ -136,6 +141,23 @@
 	TP_ARGS(h, vec)
 );
 
+/**
+ * softirq_raise - called immediately when a softirq is raised
+ * @h: pointer to struct softirq_action
+ * @vec: pointer to first struct softirq_action in softirq_vec array
+ *
+ * The @h parameter contains a pointer to the softirq vector number which is
+ * raised. @vec is NULL and it means @h includes vector number not
+ * softirq_action. When used in combination with the softirq_entry tracepoint
+ * we can determine the softirq raise latency.
+ */
+DEFINE_EVENT(softirq, softirq_raise,
+
+	TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
+
+	TP_ARGS(h, vec)
+);
+
 #endif /*  _TRACE_IRQ_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/napi.h b/include/trace/events/napi.h
index 188deca..8fe1e93 100644
--- a/include/trace/events/napi.h
+++ b/include/trace/events/napi.h
@@ -6,10 +6,31 @@
 
 #include <linux/netdevice.h>
 #include <linux/tracepoint.h>
+#include <linux/ftrace.h>
 
-DECLARE_TRACE(napi_poll,
+#define NO_DEV "(no_device)"
+
+TRACE_EVENT(napi_poll,
+
 	TP_PROTO(struct napi_struct *napi),
-	TP_ARGS(napi));
+
+	TP_ARGS(napi),
+
+	TP_STRUCT__entry(
+		__field(	struct napi_struct *,	napi)
+		__string(	dev_name, napi->dev ? napi->dev->name : NO_DEV)
+	),
+
+	TP_fast_assign(
+		__entry->napi = napi;
+		__assign_str(dev_name, napi->dev ? napi->dev->name : NO_DEV);
+	),
+
+	TP_printk("napi poll on napi struct %p for device %s",
+		__entry->napi, __get_str(dev_name))
+);
+
+#undef NO_DEV
 
 #endif /* _TRACE_NAPI_H_ */
 
diff --git a/include/trace/events/net.h b/include/trace/events/net.h
new file mode 100644
index 0000000..5f247f5
--- /dev/null
+++ b/include/trace/events/net.h
@@ -0,0 +1,82 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM net
+
+#if !defined(_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_NET_H
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(net_dev_xmit,
+
+	TP_PROTO(struct sk_buff *skb,
+		 int rc),
+
+	TP_ARGS(skb, rc),
+
+	TP_STRUCT__entry(
+		__field(	void *,		skbaddr		)
+		__field(	unsigned int,	len		)
+		__field(	int,		rc		)
+		__string(	name,		skb->dev->name	)
+	),
+
+	TP_fast_assign(
+		__entry->skbaddr = skb;
+		__entry->len = skb->len;
+		__entry->rc = rc;
+		__assign_str(name, skb->dev->name);
+	),
+
+	TP_printk("dev=%s skbaddr=%p len=%u rc=%d",
+		__get_str(name), __entry->skbaddr, __entry->len, __entry->rc)
+);
+
+DECLARE_EVENT_CLASS(net_dev_template,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb),
+
+	TP_STRUCT__entry(
+		__field(	void *,		skbaddr		)
+		__field(	unsigned int,	len		)
+		__string(	name,		skb->dev->name	)
+	),
+
+	TP_fast_assign(
+		__entry->skbaddr = skb;
+		__entry->len = skb->len;
+		__assign_str(name, skb->dev->name);
+	),
+
+	TP_printk("dev=%s skbaddr=%p len=%u",
+		__get_str(name), __entry->skbaddr, __entry->len)
+)
+
+DEFINE_EVENT(net_dev_template, net_dev_queue,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb)
+);
+
+DEFINE_EVENT(net_dev_template, netif_receive_skb,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb)
+);
+
+DEFINE_EVENT(net_dev_template, netif_rx,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb)
+);
+#endif /* _TRACE_NET_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 35a2a6e..286784d 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -10,12 +10,17 @@
 #ifndef _TRACE_POWER_ENUM_
 #define _TRACE_POWER_ENUM_
 enum {
-	POWER_NONE = 0,
-	POWER_CSTATE = 1,
-	POWER_PSTATE = 2,
+	POWER_NONE	= 0,
+	POWER_CSTATE	= 1,	/* C-State */
+	POWER_PSTATE	= 2,	/* Fequency change or DVFS */
+	POWER_SSTATE	= 3,	/* Suspend */
 };
 #endif
 
+/*
+ * The power events are used for cpuidle & suspend (power_start, power_end)
+ *  and for cpufreq (power_frequency)
+ */
 DECLARE_EVENT_CLASS(power,
 
 	TP_PROTO(unsigned int type, unsigned int state, unsigned int cpu_id),
@@ -70,6 +75,85 @@
 
 );
 
+/*
+ * The clock events are used for clock enable/disable and for
+ *  clock rate change
+ */
+DECLARE_EVENT_CLASS(clock,
+
+	TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+	TP_ARGS(name, state, cpu_id),
+
+	TP_STRUCT__entry(
+		__string(       name,           name            )
+		__field(        u64,            state           )
+		__field(        u64,            cpu_id          )
+	),
+
+	TP_fast_assign(
+		__assign_str(name, name);
+		__entry->state = state;
+		__entry->cpu_id = cpu_id;
+	),
+
+	TP_printk("%s state=%lu cpu_id=%lu", __get_str(name),
+		(unsigned long)__entry->state, (unsigned long)__entry->cpu_id)
+);
+
+DEFINE_EVENT(clock, clock_enable,
+
+	TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+	TP_ARGS(name, state, cpu_id)
+);
+
+DEFINE_EVENT(clock, clock_disable,
+
+	TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+	TP_ARGS(name, state, cpu_id)
+);
+
+DEFINE_EVENT(clock, clock_set_rate,
+
+	TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+	TP_ARGS(name, state, cpu_id)
+);
+
+/*
+ * The power domain events are used for power domains transitions
+ */
+DECLARE_EVENT_CLASS(power_domain,
+
+	TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+	TP_ARGS(name, state, cpu_id),
+
+	TP_STRUCT__entry(
+		__string(       name,           name            )
+		__field(        u64,            state           )
+		__field(        u64,            cpu_id          )
+	),
+
+	TP_fast_assign(
+		__assign_str(name, name);
+		__entry->state = state;
+		__entry->cpu_id = cpu_id;
+),
+
+	TP_printk("%s state=%lu cpu_id=%lu", __get_str(name),
+		(unsigned long)__entry->state, (unsigned long)__entry->cpu_id)
+);
+
+DEFINE_EVENT(power_domain, power_domain_target,
+
+	TP_PROTO(const char *name, unsigned int state, unsigned int cpu_id),
+
+	TP_ARGS(name, state, cpu_id)
+);
+
 #endif /* _TRACE_POWER_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 9208c92..f633478 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -362,6 +362,35 @@
 			(unsigned long long)__entry->vruntime)
 );
 
+/*
+ * Tracepoint for showing priority inheritance modifying a tasks
+ * priority.
+ */
+TRACE_EVENT(sched_pi_setprio,
+
+	TP_PROTO(struct task_struct *tsk, int newprio),
+
+	TP_ARGS(tsk, newprio),
+
+	TP_STRUCT__entry(
+		__array( char,	comm,	TASK_COMM_LEN	)
+		__field( pid_t,	pid			)
+		__field( int,	oldprio			)
+		__field( int,	newprio			)
+	),
+
+	TP_fast_assign(
+		memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN);
+		__entry->pid		= tsk->pid;
+		__entry->oldprio	= tsk->prio;
+		__entry->newprio	= newprio;
+	),
+
+	TP_printk("comm=%s pid=%d oldprio=%d newprio=%d",
+			__entry->comm, __entry->pid,
+			__entry->oldprio, __entry->newprio)
+);
+
 #endif /* _TRACE_SCHED_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/skb.h b/include/trace/events/skb.h
index 4b2be6d..75ce9d5 100644
--- a/include/trace/events/skb.h
+++ b/include/trace/events/skb.h
@@ -35,6 +35,23 @@
 		__entry->skbaddr, __entry->protocol, __entry->location)
 );
 
+TRACE_EVENT(consume_skb,
+
+	TP_PROTO(struct sk_buff *skb),
+
+	TP_ARGS(skb),
+
+	TP_STRUCT__entry(
+		__field(	void *,	skbaddr	)
+	),
+
+	TP_fast_assign(
+		__entry->skbaddr = skb;
+	),
+
+	TP_printk("skbaddr=%p", __entry->skbaddr)
+);
+
 TRACE_EVENT(skb_copy_datagram_iovec,
 
 	TP_PROTO(const struct sk_buff *skb, int len),
diff --git a/include/trace/events/workqueue.h b/include/trace/events/workqueue.h
index 49682d7..7d49729 100644
--- a/include/trace/events/workqueue.h
+++ b/include/trace/events/workqueue.h
@@ -7,6 +7,76 @@
 #include <linux/tracepoint.h>
 #include <linux/workqueue.h>
 
+DECLARE_EVENT_CLASS(workqueue_work,
+
+	TP_PROTO(struct work_struct *work),
+
+	TP_ARGS(work),
+
+	TP_STRUCT__entry(
+		__field( void *,	work	)
+	),
+
+	TP_fast_assign(
+		__entry->work		= work;
+	),
+
+	TP_printk("work struct %p", __entry->work)
+);
+
+/**
+ * workqueue_queue_work - called when a work gets queued
+ * @req_cpu:	the requested cpu
+ * @cwq:	pointer to struct cpu_workqueue_struct
+ * @work:	pointer to struct work_struct
+ *
+ * This event occurs when a work is queued immediately or once a
+ * delayed work is actually queued on a workqueue (ie: once the delay
+ * has been reached).
+ */
+TRACE_EVENT(workqueue_queue_work,
+
+	TP_PROTO(unsigned int req_cpu, struct cpu_workqueue_struct *cwq,
+		 struct work_struct *work),
+
+	TP_ARGS(req_cpu, cwq, work),
+
+	TP_STRUCT__entry(
+		__field( void *,	work	)
+		__field( void *,	function)
+		__field( void *,	workqueue)
+		__field( unsigned int,	req_cpu	)
+		__field( unsigned int,	cpu	)
+	),
+
+	TP_fast_assign(
+		__entry->work		= work;
+		__entry->function	= work->func;
+		__entry->workqueue	= cwq->wq;
+		__entry->req_cpu	= req_cpu;
+		__entry->cpu		= cwq->gcwq->cpu;
+	),
+
+	TP_printk("work struct=%p function=%pf workqueue=%p req_cpu=%u cpu=%u",
+		  __entry->work, __entry->function, __entry->workqueue,
+		  __entry->req_cpu, __entry->cpu)
+);
+
+/**
+ * workqueue_activate_work - called when a work gets activated
+ * @work:	pointer to struct work_struct
+ *
+ * This event occurs when a queued work is put on the active queue,
+ * which happens immediately after queueing unless @max_active limit
+ * is reached.
+ */
+DEFINE_EVENT(workqueue_work, workqueue_activate_work,
+
+	TP_PROTO(struct work_struct *work),
+
+	TP_ARGS(work)
+);
+
 /**
  * workqueue_execute_start - called immediately before the workqueue callback
  * @work:	pointer to struct work_struct
@@ -38,24 +108,13 @@
  *
  * Allows to track workqueue execution.
  */
-TRACE_EVENT(workqueue_execute_end,
+DEFINE_EVENT(workqueue_work, workqueue_execute_end,
 
 	TP_PROTO(struct work_struct *work),
 
-	TP_ARGS(work),
-
-	TP_STRUCT__entry(
-		__field( void *,	work	)
-	),
-
-	TP_fast_assign(
-		__entry->work		= work;
-	),
-
-	TP_printk("work struct %p", __entry->work)
+	TP_ARGS(work)
 );
 
-
 #endif /*  _TRACE_WORKQUEUE_H */
 
 /* This part must be outside protection */
diff --git a/init/Kconfig b/init/Kconfig
index 2de5b1c..fdfd97e 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -21,6 +21,13 @@
 	depends on !UML
 	default y
 
+config HAVE_IRQ_WORK
+	bool
+
+config IRQ_WORK
+	bool
+	depends on HAVE_IRQ_WORK
+
 menu "General setup"
 
 config EXPERIMENTAL
@@ -64,7 +71,7 @@
 
 config LOCK_KERNEL
 	bool
-	depends on SMP || PREEMPT
+	depends on (SMP || PREEMPT) && BKL
 	default y
 
 config INIT_ENV_ARG_LIMIT
@@ -332,6 +339,8 @@
 	depends on AUDITSYSCALL
 	select FSNOTIFY
 
+source "kernel/irq/Kconfig"
+
 menu "RCU Subsystem"
 
 choice
@@ -340,6 +349,7 @@
 
 config TREE_RCU
 	bool "Tree-based hierarchical RCU"
+	depends on !PREEMPT && SMP
 	help
 	  This option selects the RCU implementation that is
 	  designed for very large SMP system with hundreds or
@@ -347,7 +357,7 @@
 	  smaller systems.
 
 config TREE_PREEMPT_RCU
-	bool "Preemptable tree-based hierarchical RCU"
+	bool "Preemptible tree-based hierarchical RCU"
 	depends on PREEMPT
 	help
 	  This option selects the RCU implementation that is
@@ -365,8 +375,22 @@
 	  is not required.  This option greatly reduces the
 	  memory footprint of RCU.
 
+config TINY_PREEMPT_RCU
+	bool "Preemptible UP-only small-memory-footprint RCU"
+	depends on !SMP && PREEMPT
+	help
+	  This option selects the RCU implementation that is designed
+	  for real-time UP systems.  This option greatly reduces the
+	  memory footprint of RCU.
+
 endchoice
 
+config PREEMPT_RCU
+	def_bool ( TREE_PREEMPT_RCU || TINY_PREEMPT_RCU )
+	help
+	  This option enables preemptible-RCU code that is common between
+	  the TREE_PREEMPT_RCU and TINY_PREEMPT_RCU implementations.
+
 config RCU_TRACE
 	bool "Enable tracing for RCU"
 	depends on TREE_RCU || TREE_PREEMPT_RCU
@@ -387,9 +411,12 @@
 	help
 	  This option controls the fanout of hierarchical implementations
 	  of RCU, allowing RCU to work efficiently on machines with
-	  large numbers of CPUs.  This value must be at least the cube
-	  root of NR_CPUS, which allows NR_CPUS up to 32,768 for 32-bit
-	  systems and up to 262,144 for 64-bit systems.
+	  large numbers of CPUs.  This value must be at least the fourth
+	  root of NR_CPUS, which allows NR_CPUS to be insanely large.
+	  The default value of RCU_FANOUT should be used for production
+	  systems, but if you are stress-testing the RCU implementation
+	  itself, small RCU_FANOUT values allow you to test large-system
+	  code paths on small(er) systems.
 
 	  Select a specific number if testing RCU itself.
 	  Take the default if unsure.
@@ -634,11 +661,14 @@
 
 	Currently, CFQ IO scheduler uses it to recognize task groups and
 	control disk bandwidth allocation (proportional time slice allocation)
-	to such task groups.
+	to such task groups. It is also used by bio throttling logic in
+	block layer to implement upper limit in IO rates on a device.
 
 	This option only enables generic Block IO controller infrastructure.
-	One needs to also enable actual IO controlling logic in CFQ for it
-	to take effect. (CONFIG_CFQ_GROUP_IOSCHED=y).
+	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.
 
 	See Documentation/cgroups/blkio-controller.txt for more information.
 
@@ -656,40 +686,42 @@
 	bool
 
 config SYSFS_DEPRECATED
-	bool
-
-config SYSFS_DEPRECATED_V2
 	bool "enable deprecated sysfs features to support old userspace tools"
 	depends on SYSFS
 	default n
-	select SYSFS_DEPRECATED
 	help
-	  This option switches the layout of sysfs to the deprecated
-	  version. Do not use it on recent distributions.
+	  This option adds code that switches the layout of the "block" class
+	  devices, to not show up in /sys/class/block/, but only in
+	  /sys/block/.
 
-	  The current sysfs layout features a unified device tree at
-	  /sys/devices/, which is able to express a hierarchy between
-	  class devices. If the deprecated option is set to Y, the
-	  unified device tree is split into a bus device tree at
-	  /sys/devices/ and several individual class device trees at
-	  /sys/class/. The class and bus devices will be connected by
-	  "<subsystem>:<name>" and the "device" links. The "block"
-	  class devices, will not show up in /sys/class/block/. Some
-	  subsystems will suppress the creation of some devices which
-	  depend on the unified device tree.
+	  This switch is only active when the sysfs.deprecated=1 boot option is
+	  passed or the SYSFS_DEPRECATED_V2 option is set.
 
-	  This option is not a pure compatibility option that can
-	  be safely enabled on newer distributions. It will change the
-	  layout of sysfs to the non-extensible deprecated version,
-	  and disable some features, which can not be exported without
-	  confusing older userspace tools. Since 2007/2008 all major
-	  distributions do not enable this option, and ship no tools which
-	  depend on the deprecated layout or this option.
+	  This option allows new kernels to run on old distributions and tools,
+	  which might get confused by /sys/class/block/. Since 2007/2008 all
+	  major distributions and tools handle this just fine.
 
-	  If you are using a new kernel on an older distribution, or use
-	  older userspace tools, you might need to say Y here. Do not say Y,
-	  if the original kernel, that came with your distribution, has
-	  this option set to N.
+	  Recent distributions and userspace tools after 2009/2010 depend on
+	  the existence of /sys/class/block/, and will not work with this
+	  option enabled.
+
+	  Only if you are using a new kernel on an old distribution, you might
+	  need to say Y here.
+
+config SYSFS_DEPRECATED_V2
+	bool "enabled deprecated sysfs features by default"
+	default n
+	depends on SYSFS
+	depends on SYSFS_DEPRECATED
+	help
+	  Enable deprecated sysfs by default.
+
+	  See the CONFIG_SYSFS_DEPRECATED option for more details about this
+	  option.
+
+	  Only if you are using a new kernel on an old distribution, you might
+	  need to say Y here. Even then, odds are you would not need it
+	  enabled, you can always pass the boot option if absolutely necessary.
 
 config RELAY
 	bool "Kernel->user space relay support (formerly relayfs)"
@@ -987,6 +1019,7 @@
 	default y if (PROFILING || PERF_COUNTERS)
 	depends on HAVE_PERF_EVENTS
 	select ANON_INODES
+	select IRQ_WORK
 	help
 	  Enable kernel support for various performance events provided
 	  by software and hardware.
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 02e3ca4..42db055 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -58,6 +58,62 @@
 __setup("ro", readonly);
 __setup("rw", readwrite);
 
+#ifdef CONFIG_BLOCK
+/**
+ * match_dev_by_uuid - callback for finding a partition using its uuid
+ * @dev:	device passed in by the caller
+ * @data:	opaque pointer to a 36 byte char array with a UUID
+ *
+ * Returns 1 if the device matches, and 0 otherwise.
+ */
+static int match_dev_by_uuid(struct device *dev, void *data)
+{
+	u8 *uuid = data;
+	struct hd_struct *part = dev_to_part(dev);
+
+	if (!part->info)
+		goto no_match;
+
+	if (memcmp(uuid, part->info->uuid, sizeof(part->info->uuid)))
+			goto no_match;
+
+	return 1;
+no_match:
+	return 0;
+}
+
+
+/**
+ * devt_from_partuuid - looks up the dev_t of a partition by its UUID
+ * @uuid:	36 byte char array containing a hex ascii UUID
+ *
+ * The function will return the first partition which contains a matching
+ * UUID value in its partition_meta_info struct.  This does not search
+ * by filesystem UUIDs.
+ *
+ * Returns the matching dev_t on success or 0 on failure.
+ */
+static dev_t __init devt_from_partuuid(char *uuid_str)
+{
+	dev_t res = 0;
+	struct device *dev = NULL;
+	u8 uuid[16];
+
+	/* Pack the requested UUID in the expected format. */
+	part_pack_uuid(uuid_str, uuid);
+
+	dev = class_find_device(&block_class, NULL, uuid, &match_dev_by_uuid);
+	if (!dev)
+		goto done;
+
+	res = dev->devt;
+	put_device(dev);
+
+done:
+	return res;
+}
+#endif
+
 /*
  *	Convert a name into device number.  We accept the following variants:
  *
@@ -68,6 +124,8 @@
  *         of partition - device number of disk plus the partition number
  *	5) /dev/<disk_name>p<decimal> - same as the above, that form is
  *	   used when disk name of partitioned disk ends on a digit.
+ *	6) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
+ *	   unique id of a partition if the partition table provides it.
  *
  *	If name doesn't have fall into the categories above, we return (0,0).
  *	block_class is used to check if something is a disk name. If the disk
@@ -82,6 +140,18 @@
 	dev_t res = 0;
 	int part;
 
+#ifdef CONFIG_BLOCK
+	if (strncmp(name, "PARTUUID=", 9) == 0) {
+		name += 9;
+		if (strlen(name) != 36)
+			goto fail;
+		res = devt_from_partuuid(name);
+		if (!res)
+			goto fail;
+		goto done;
+	}
+#endif
+
 	if (strncmp(name, "/dev/", 5) != 0) {
 		unsigned maj, min;
 
diff --git a/init/main.c b/init/main.c
index 94ab488..e59af24 100644
--- a/init/main.c
+++ b/init/main.c
@@ -424,7 +424,6 @@
 static __initdata DECLARE_COMPLETION(kthreadd_done);
 
 static noinline void __init_refok rest_init(void)
-	__releases(kernel_lock)
 {
 	int pid;
 
@@ -556,7 +555,6 @@
 
 	local_irq_disable();
 	early_boot_irqs_off();
-	early_init_irq_lock_class();
 
 /*
  * Interrupts are still disabled. Do necessary setups, then
@@ -819,7 +817,6 @@
  * makes it inline to init() and it becomes part of init.text section
  */
 static noinline int init_post(void)
-	__releases(kernel_lock)
 {
 	/* need to finish all async __init code before freeing the memory */
 	async_synchronize_full();
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index c60e519..e1e7b96 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -1219,6 +1219,7 @@
 	.flush = mqueue_flush_file,
 	.poll = mqueue_poll_file,
 	.read = mqueue_read_file,
+	.llseek = default_llseek,
 };
 
 static const struct super_operations mqueue_super_ops = {
diff --git a/ipc/sem.c b/ipc/sem.c
index 40a8f46..0e0d49b 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -743,6 +743,8 @@
 	    {
 		struct semid_ds out;
 
+		memset(&out, 0, sizeof(out));
+
 		ipc64_perm_to_ipc_perm(&in->sem_perm, &out.sem_perm);
 
 		out.sem_otime	= in->sem_otime;
diff --git a/ipc/shm.c b/ipc/shm.c
index 52ed77e..7bc46a9 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -298,6 +298,7 @@
 #ifndef CONFIG_MMU
 	.get_unmapped_area	= shm_get_unmapped_area,
 #endif
+	.llseek		= noop_llseek,
 };
 
 static const struct file_operations shm_file_operations_huge = {
@@ -305,6 +306,7 @@
 	.fsync		= shm_fsync,
 	.release	= shm_release,
 	.get_unmapped_area	= shm_get_unmapped_area,
+	.llseek		= noop_llseek,
 };
 
 int is_file_shm_hugepages(struct file *file)
diff --git a/kernel/Makefile b/kernel/Makefile
index 0b72d1a..0b5ff08 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -10,8 +10,7 @@
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
 	    hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
 	    notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \
-	    async.o range.o
-obj-$(CONFIG_HAVE_EARLY_RES) += early_res.o
+	    async.o range.o jump_label.o
 obj-y += groups.o
 
 ifdef CONFIG_FUNCTION_TRACER
@@ -23,6 +22,7 @@
 CFLAGS_REMOVE_cgroup-debug.o = -pg
 CFLAGS_REMOVE_sched_clock.o = -pg
 CFLAGS_REMOVE_perf_event.o = -pg
+CFLAGS_REMOVE_irq_work.o = -pg
 endif
 
 obj-$(CONFIG_FREEZER) += freezer.o
@@ -86,6 +86,7 @@
 obj-$(CONFIG_TREE_PREEMPT_RCU) += rcutree.o
 obj-$(CONFIG_TREE_RCU_TRACE) += rcutree_trace.o
 obj-$(CONFIG_TINY_RCU) += rcutiny.o
+obj-$(CONFIG_TINY_PREEMPT_RCU) += rcutiny.o
 obj-$(CONFIG_RELAY) += relay.o
 obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
 obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
@@ -100,6 +101,7 @@
 obj-$(CONFIG_X86_DS) += trace/
 obj-$(CONFIG_RING_BUFFER) += trace/
 obj-$(CONFIG_SMP) += sched_cpupri.o
+obj-$(CONFIG_IRQ_WORK) += irq_work.o
 obj-$(CONFIG_PERF_EVENTS) += perf_event.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
 obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index c9483d8..7b69b8d 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -52,7 +52,6 @@
 #include <linux/cgroupstats.h>
 #include <linux/hash.h>
 #include <linux/namei.h>
-#include <linux/smp_lock.h>
 #include <linux/pid_namespace.h>
 #include <linux/idr.h>
 #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
@@ -138,7 +137,7 @@
 	 * is called after synchronize_rcu(). But for safe use, css_is_removed()
 	 * css_tryget() should be used for avoiding race.
 	 */
-	struct cgroup_subsys_state *css;
+	struct cgroup_subsys_state __rcu *css;
 	/*
 	 * ID of this css.
 	 */
@@ -1222,7 +1221,6 @@
 	struct cgroup *cgrp = &root->top_cgroup;
 	struct cgroup_sb_opts opts;
 
-	lock_kernel();
 	mutex_lock(&cgrp->dentry->d_inode->i_mutex);
 	mutex_lock(&cgroup_mutex);
 
@@ -1255,7 +1253,6 @@
 	kfree(opts.name);
 	mutex_unlock(&cgroup_mutex);
 	mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
-	unlock_kernel();
 	return ret;
 }
 
@@ -1568,7 +1565,6 @@
  out_err:
 	kfree(opts.release_agent);
 	kfree(opts.name);
-
 	return ret;
 }
 
diff --git a/kernel/configs.c b/kernel/configs.c
index abaee68..b4066b4 100644
--- a/kernel/configs.c
+++ b/kernel/configs.c
@@ -66,6 +66,7 @@
 static const struct file_operations ikconfig_file_ops = {
 	.owner = THIS_MODULE,
 	.read = ikconfig_read_current,
+	.llseek = default_llseek,
 };
 
 static int __init ikconfig_init(void)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index b23c097..51b143e 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1397,7 +1397,7 @@
 	if (tsk->flags & PF_THREAD_BOUND)
 		return -EINVAL;
 
-	ret = security_task_setscheduler(tsk, 0, NULL);
+	ret = security_task_setscheduler(tsk);
 	if (ret)
 		return ret;
 	if (threadgroup) {
@@ -1405,7 +1405,7 @@
 
 		rcu_read_lock();
 		list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) {
-			ret = security_task_setscheduler(c, 0, NULL);
+			ret = security_task_setscheduler(c);
 			if (ret) {
 				rcu_read_unlock();
 				return ret;
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index de407c7..fec596d 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -47,6 +47,7 @@
 #include <linux/pid.h>
 #include <linux/smp.h>
 #include <linux/mm.h>
+#include <linux/rcupdate.h>
 
 #include <asm/cacheflush.h>
 #include <asm/byteorder.h>
@@ -109,13 +110,15 @@
  */
 atomic_t			kgdb_active = ATOMIC_INIT(-1);
 EXPORT_SYMBOL_GPL(kgdb_active);
+static DEFINE_RAW_SPINLOCK(dbg_master_lock);
+static DEFINE_RAW_SPINLOCK(dbg_slave_lock);
 
 /*
  * We use NR_CPUs not PERCPU, in case kgdb is used to debug early
  * bootup code (which might not have percpu set up yet):
  */
-static atomic_t			passive_cpu_wait[NR_CPUS];
-static atomic_t			cpu_in_kgdb[NR_CPUS];
+static atomic_t			masters_in_kgdb;
+static atomic_t			slaves_in_kgdb;
 static atomic_t			kgdb_break_tasklet_var;
 atomic_t			kgdb_setting_breakpoint;
 
@@ -457,26 +460,32 @@
 	return 1;
 }
 
-static void dbg_cpu_switch(int cpu, int next_cpu)
+static void dbg_touch_watchdogs(void)
 {
-	/* Mark the cpu we are switching away from as a slave when it
-	 * holds the kgdb_active token.  This must be done so that the
-	 * that all the cpus wait in for the debug core will not enter
-	 * again as the master. */
-	if (cpu == atomic_read(&kgdb_active)) {
-		kgdb_info[cpu].exception_state |= DCPU_IS_SLAVE;
-		kgdb_info[cpu].exception_state &= ~DCPU_WANT_MASTER;
-	}
-	kgdb_info[next_cpu].exception_state |= DCPU_NEXT_MASTER;
+	touch_softlockup_watchdog_sync();
+	clocksource_touch_watchdog();
+	rcu_cpu_stall_reset();
 }
 
-static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs)
+static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
+		int exception_state)
 {
 	unsigned long flags;
 	int sstep_tries = 100;
 	int error;
-	int i, cpu;
+	int cpu;
 	int trace_on = 0;
+	int online_cpus = num_online_cpus();
+
+	kgdb_info[ks->cpu].enter_kgdb++;
+	kgdb_info[ks->cpu].exception_state |= exception_state;
+
+	if (exception_state == DCPU_WANT_MASTER)
+		atomic_inc(&masters_in_kgdb);
+	else
+		atomic_inc(&slaves_in_kgdb);
+	kgdb_disable_hw_debug(ks->linux_regs);
+
 acquirelock:
 	/*
 	 * Interrupts will be restored by the 'trap return' code, except when
@@ -489,14 +498,15 @@
 	kgdb_info[cpu].task = current;
 	kgdb_info[cpu].ret_state = 0;
 	kgdb_info[cpu].irq_depth = hardirq_count() >> HARDIRQ_SHIFT;
-	/*
-	 * Make sure the above info reaches the primary CPU before
-	 * our cpu_in_kgdb[] flag setting does:
-	 */
-	atomic_inc(&cpu_in_kgdb[cpu]);
 
-	if (exception_level == 1)
+	/* Make sure the above info reaches the primary CPU */
+	smp_mb();
+
+	if (exception_level == 1) {
+		if (raw_spin_trylock(&dbg_master_lock))
+			atomic_xchg(&kgdb_active, cpu);
 		goto cpu_master_loop;
+	}
 
 	/*
 	 * CPU will loop if it is a slave or request to become a kgdb
@@ -508,10 +518,12 @@
 			kgdb_info[cpu].exception_state &= ~DCPU_NEXT_MASTER;
 			goto cpu_master_loop;
 		} else if (kgdb_info[cpu].exception_state & DCPU_WANT_MASTER) {
-			if (atomic_cmpxchg(&kgdb_active, -1, cpu) == cpu)
+			if (raw_spin_trylock(&dbg_master_lock)) {
+				atomic_xchg(&kgdb_active, cpu);
 				break;
+			}
 		} else if (kgdb_info[cpu].exception_state & DCPU_IS_SLAVE) {
-			if (!atomic_read(&passive_cpu_wait[cpu]))
+			if (!raw_spin_is_locked(&dbg_slave_lock))
 				goto return_normal;
 		} else {
 return_normal:
@@ -522,9 +534,12 @@
 				arch_kgdb_ops.correct_hw_break();
 			if (trace_on)
 				tracing_on();
-			atomic_dec(&cpu_in_kgdb[cpu]);
-			touch_softlockup_watchdog_sync();
-			clocksource_touch_watchdog();
+			kgdb_info[cpu].exception_state &=
+				~(DCPU_WANT_MASTER | DCPU_IS_SLAVE);
+			kgdb_info[cpu].enter_kgdb--;
+			smp_mb__before_atomic_dec();
+			atomic_dec(&slaves_in_kgdb);
+			dbg_touch_watchdogs();
 			local_irq_restore(flags);
 			return 0;
 		}
@@ -541,8 +556,8 @@
 	    (kgdb_info[cpu].task &&
 	     kgdb_info[cpu].task->pid != kgdb_sstep_pid) && --sstep_tries) {
 		atomic_set(&kgdb_active, -1);
-		touch_softlockup_watchdog_sync();
-		clocksource_touch_watchdog();
+		raw_spin_unlock(&dbg_master_lock);
+		dbg_touch_watchdogs();
 		local_irq_restore(flags);
 
 		goto acquirelock;
@@ -563,16 +578,12 @@
 	if (dbg_io_ops->pre_exception)
 		dbg_io_ops->pre_exception();
 
-	kgdb_disable_hw_debug(ks->linux_regs);
-
 	/*
 	 * Get the passive CPU lock which will hold all the non-primary
 	 * CPU in a spin state while the debugger is active
 	 */
-	if (!kgdb_single_step) {
-		for (i = 0; i < NR_CPUS; i++)
-			atomic_inc(&passive_cpu_wait[i]);
-	}
+	if (!kgdb_single_step)
+		raw_spin_lock(&dbg_slave_lock);
 
 #ifdef CONFIG_SMP
 	/* Signal the other CPUs to enter kgdb_wait() */
@@ -583,10 +594,9 @@
 	/*
 	 * Wait for the other CPUs to be notified and be waiting for us:
 	 */
-	for_each_online_cpu(i) {
-		while (kgdb_do_roundup && !atomic_read(&cpu_in_kgdb[i]))
-			cpu_relax();
-	}
+	while (kgdb_do_roundup && (atomic_read(&masters_in_kgdb) +
+				atomic_read(&slaves_in_kgdb)) != online_cpus)
+		cpu_relax();
 
 	/*
 	 * At this point the primary processor is completely
@@ -615,7 +625,8 @@
 		if (error == DBG_PASS_EVENT) {
 			dbg_kdb_mode = !dbg_kdb_mode;
 		} else if (error == DBG_SWITCH_CPU_EVENT) {
-			dbg_cpu_switch(cpu, dbg_switch_cpu);
+			kgdb_info[dbg_switch_cpu].exception_state |=
+				DCPU_NEXT_MASTER;
 			goto cpu_loop;
 		} else {
 			kgdb_info[cpu].ret_state = error;
@@ -627,24 +638,11 @@
 	if (dbg_io_ops->post_exception)
 		dbg_io_ops->post_exception();
 
-	atomic_dec(&cpu_in_kgdb[ks->cpu]);
-
 	if (!kgdb_single_step) {
-		for (i = NR_CPUS-1; i >= 0; i--)
-			atomic_dec(&passive_cpu_wait[i]);
-		/*
-		 * Wait till all the CPUs have quit from the debugger,
-		 * but allow a CPU that hit an exception and is
-		 * waiting to become the master to remain in the debug
-		 * core.
-		 */
-		for_each_online_cpu(i) {
-			while (kgdb_do_roundup &&
-			       atomic_read(&cpu_in_kgdb[i]) &&
-			       !(kgdb_info[i].exception_state &
-				 DCPU_WANT_MASTER))
-				cpu_relax();
-		}
+		raw_spin_unlock(&dbg_slave_lock);
+		/* Wait till all the CPUs have quit from the debugger. */
+		while (kgdb_do_roundup && atomic_read(&slaves_in_kgdb))
+			cpu_relax();
 	}
 
 kgdb_restore:
@@ -655,12 +653,20 @@
 		else
 			kgdb_sstep_pid = 0;
 	}
+	if (arch_kgdb_ops.correct_hw_break)
+		arch_kgdb_ops.correct_hw_break();
 	if (trace_on)
 		tracing_on();
+
+	kgdb_info[cpu].exception_state &=
+		~(DCPU_WANT_MASTER | DCPU_IS_SLAVE);
+	kgdb_info[cpu].enter_kgdb--;
+	smp_mb__before_atomic_dec();
+	atomic_dec(&masters_in_kgdb);
 	/* Free kgdb_active */
 	atomic_set(&kgdb_active, -1);
-	touch_softlockup_watchdog_sync();
-	clocksource_touch_watchdog();
+	raw_spin_unlock(&dbg_master_lock);
+	dbg_touch_watchdogs();
 	local_irq_restore(flags);
 
 	return kgdb_info[cpu].ret_state;
@@ -678,7 +684,6 @@
 {
 	struct kgdb_state kgdb_var;
 	struct kgdb_state *ks = &kgdb_var;
-	int ret;
 
 	ks->cpu			= raw_smp_processor_id();
 	ks->ex_vector		= evector;
@@ -689,11 +694,10 @@
 
 	if (kgdb_reenter_check(ks))
 		return 0; /* Ouch, double exception ! */
-	kgdb_info[ks->cpu].exception_state |= DCPU_WANT_MASTER;
-	ret = kgdb_cpu_enter(ks, regs);
-	kgdb_info[ks->cpu].exception_state &= ~(DCPU_WANT_MASTER |
-						DCPU_IS_SLAVE);
-	return ret;
+	if (kgdb_info[ks->cpu].enter_kgdb != 0)
+		return 0;
+
+	return kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER);
 }
 
 int kgdb_nmicallback(int cpu, void *regs)
@@ -706,12 +710,9 @@
 	ks->cpu			= cpu;
 	ks->linux_regs		= regs;
 
-	if (!atomic_read(&cpu_in_kgdb[cpu]) &&
-	    atomic_read(&kgdb_active) != -1 &&
-	    atomic_read(&kgdb_active) != cpu) {
-		kgdb_info[cpu].exception_state |= DCPU_IS_SLAVE;
-		kgdb_cpu_enter(ks, regs);
-		kgdb_info[cpu].exception_state &= ~DCPU_IS_SLAVE;
+	if (kgdb_info[ks->cpu].enter_kgdb == 0 &&
+			raw_spin_is_locked(&dbg_master_lock)) {
+		kgdb_cpu_enter(ks, regs, DCPU_IS_SLAVE);
 		return 0;
 	}
 #endif
diff --git a/kernel/debug/debug_core.h b/kernel/debug/debug_core.h
index c5d753d..3494c28 100644
--- a/kernel/debug/debug_core.h
+++ b/kernel/debug/debug_core.h
@@ -40,6 +40,7 @@
 	int			exception_state;
 	int			ret_state;
 	int			irq_depth;
+	int			enter_kgdb;
 };
 
 extern struct debuggerinfo_struct kgdb_info[];
diff --git a/kernel/debug/kdb/kdb_debugger.c b/kernel/debug/kdb/kdb_debugger.c
index bf6e827..dd0b1b7 100644
--- a/kernel/debug/kdb/kdb_debugger.c
+++ b/kernel/debug/kdb/kdb_debugger.c
@@ -86,7 +86,7 @@
 	}
 	/* Set initial kdb state variables */
 	KDB_STATE_CLEAR(KGDB_TRANS);
-	kdb_initial_cpu = ks->cpu;
+	kdb_initial_cpu = atomic_read(&kgdb_active);
 	kdb_current_task = kgdb_info[ks->cpu].task;
 	kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo;
 	/* Remove any breakpoints as needed by kdb and clear single step */
@@ -105,7 +105,6 @@
 		ks->pass_exception = 1;
 		KDB_FLAG_SET(CATASTROPHIC);
 	}
-	kdb_initial_cpu = ks->cpu;
 	if (KDB_STATE(SSBPT) && reason == KDB_REASON_SSTEP) {
 		KDB_STATE_CLEAR(SSBPT);
 		KDB_STATE_CLEAR(DOING_SS);
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index c9b7f4f9..96fdaac 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -823,4 +823,4 @@
 
 	return r;
 }
-
+EXPORT_SYMBOL_GPL(kdb_printf);
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index caf057a..d7bda21 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -1749,13 +1749,13 @@
 	int nextarg;
 	long offset;
 
+	if (raw_smp_processor_id() != kdb_initial_cpu) {
+		kdb_printf("go must execute on the entry cpu, "
+			   "please use \"cpu %d\" and then execute go\n",
+			   kdb_initial_cpu);
+		return KDB_BADCPUNUM;
+	}
 	if (argc == 1) {
-		if (raw_smp_processor_id() != kdb_initial_cpu) {
-			kdb_printf("go <address> must be issued from the "
-				   "initial cpu, do cpu %d first\n",
-				   kdb_initial_cpu);
-			return KDB_ARGCOUNT;
-		}
 		nextarg = 1;
 		diag = kdbgetaddrarg(argc, argv, &nextarg,
 				     &addr, &offset, NULL);
@@ -2783,6 +2783,8 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(kdb_register_repeat);
+
 
 /*
  * kdb_register - Compatibility register function for commands that do
@@ -2805,6 +2807,7 @@
 	return kdb_register_repeat(cmd, func, usage, help, minlen,
 				   KDB_REPEAT_NONE);
 }
+EXPORT_SYMBOL_GPL(kdb_register);
 
 /*
  * kdb_unregister - This function is used to unregister a kernel
@@ -2823,7 +2826,7 @@
 	/*
 	 *  find the command.
 	 */
-	for (i = 0, kp = kdb_commands; i < kdb_max_commands; i++, kp++) {
+	for_each_kdbcmd(kp, i) {
 		if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
 			kp->cmd_name = NULL;
 			return 0;
@@ -2833,6 +2836,7 @@
 	/* Couldn't find it.  */
 	return 1;
 }
+EXPORT_SYMBOL_GPL(kdb_unregister);
 
 /* Initialize the kdb command table. */
 static void __init kdb_inittab(void)
diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h
index be775f7..35d69ed 100644
--- a/kernel/debug/kdb/kdb_private.h
+++ b/kernel/debug/kdb/kdb_private.h
@@ -15,29 +15,6 @@
 #include <linux/kgdb.h>
 #include "../debug_core.h"
 
-/* Kernel Debugger Error codes.  Must not overlap with command codes. */
-#define KDB_NOTFOUND	(-1)
-#define KDB_ARGCOUNT	(-2)
-#define KDB_BADWIDTH	(-3)
-#define KDB_BADRADIX	(-4)
-#define KDB_NOTENV	(-5)
-#define KDB_NOENVVALUE	(-6)
-#define KDB_NOTIMP	(-7)
-#define KDB_ENVFULL	(-8)
-#define KDB_ENVBUFFULL	(-9)
-#define KDB_TOOMANYBPT	(-10)
-#define KDB_TOOMANYDBREGS (-11)
-#define KDB_DUPBPT	(-12)
-#define KDB_BPTNOTFOUND	(-13)
-#define KDB_BADMODE	(-14)
-#define KDB_BADINT	(-15)
-#define KDB_INVADDRFMT  (-16)
-#define KDB_BADREG      (-17)
-#define KDB_BADCPUNUM   (-18)
-#define KDB_BADLENGTH	(-19)
-#define KDB_NOBP	(-20)
-#define KDB_BADADDR	(-21)
-
 /* Kernel Debugger Command codes.  Must not overlap with error codes. */
 #define KDB_CMD_GO	(-1001)
 #define KDB_CMD_CPU	(-1002)
@@ -93,17 +70,6 @@
  */
 #define KDB_MAXBPT	16
 
-/* Maximum number of arguments to a function  */
-#define KDB_MAXARGS    16
-
-typedef enum {
-	KDB_REPEAT_NONE = 0,	/* Do not repeat this command */
-	KDB_REPEAT_NO_ARGS,	/* Repeat the command without arguments */
-	KDB_REPEAT_WITH_ARGS,	/* Repeat the command including its arguments */
-} kdb_repeat_t;
-
-typedef int (*kdb_func_t)(int, const char **);
-
 /* Symbol table format returned by kallsyms. */
 typedef struct __ksymtab {
 		unsigned long value;	/* Address of symbol */
@@ -123,11 +89,6 @@
 extern int kallsyms_symbol_complete(char *prefix_name, int max_len);
 
 /* Exported Symbols for kernel loadable modules to use. */
-extern int kdb_register(char *, kdb_func_t, char *, char *, short);
-extern int kdb_register_repeat(char *, kdb_func_t, char *, char *,
-			       short, kdb_repeat_t);
-extern int kdb_unregister(char *);
-
 extern int kdb_getarea_size(void *, unsigned long, size_t);
 extern int kdb_putarea_size(unsigned long, void *, size_t);
 
@@ -144,6 +105,7 @@
 extern int kdb_putword(unsigned long, unsigned long, size_t);
 
 extern int kdbgetularg(const char *, unsigned long *);
+extern int kdbgetu64arg(const char *, u64 *);
 extern char *kdbgetenv(const char *);
 extern int kdbgetaddrarg(int, const char **, int*, unsigned long *,
 			 long *, char **);
@@ -255,14 +217,6 @@
 extern void kdb_print_nameval(const char *name, unsigned long val);
 extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info);
 extern void kdb_meminfo_proc_show(void);
-#ifdef CONFIG_KALLSYMS
-extern const char *kdb_walk_kallsyms(loff_t *pos);
-#else /* ! CONFIG_KALLSYMS */
-static inline const char *kdb_walk_kallsyms(loff_t *pos)
-{
-	return NULL;
-}
-#endif /* ! CONFIG_KALLSYMS */
 extern char *kdb_getstr(char *, size_t, char *);
 
 /* Defines for kdb_symbol_print */
diff --git a/kernel/early_res.c b/kernel/early_res.c
deleted file mode 100644
index 7bfae88..0000000
--- a/kernel/early_res.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- * early_res, could be used to replace bootmem
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <linux/early_res.h>
-#include <linux/slab.h>
-#include <linux/kmemleak.h>
-
-/*
- * Early reserved memory areas.
- */
-/*
- * need to make sure this one is bigger enough before
- * find_fw_memmap_area could be used
- */
-#define MAX_EARLY_RES_X 32
-
-struct early_res {
-	u64 start, end;
-	char name[15];
-	char overlap_ok;
-};
-static struct early_res early_res_x[MAX_EARLY_RES_X] __initdata;
-
-static int max_early_res __initdata = MAX_EARLY_RES_X;
-static struct early_res *early_res __initdata = &early_res_x[0];
-static int early_res_count __initdata;
-
-static int __init find_overlapped_early(u64 start, u64 end)
-{
-	int i;
-	struct early_res *r;
-
-	for (i = 0; i < max_early_res && early_res[i].end; i++) {
-		r = &early_res[i];
-		if (end > r->start && start < r->end)
-			break;
-	}
-
-	return i;
-}
-
-/*
- * Drop the i-th range from the early reservation map,
- * by copying any higher ranges down one over it, and
- * clearing what had been the last slot.
- */
-static void __init drop_range(int i)
-{
-	int j;
-
-	for (j = i + 1; j < max_early_res && early_res[j].end; j++)
-		;
-
-	memmove(&early_res[i], &early_res[i + 1],
-	       (j - 1 - i) * sizeof(struct early_res));
-
-	early_res[j - 1].end = 0;
-	early_res_count--;
-}
-
-static void __init drop_range_partial(int i, u64 start, u64 end)
-{
-	u64 common_start, common_end;
-	u64 old_start, old_end;
-
-	old_start = early_res[i].start;
-	old_end = early_res[i].end;
-	common_start = max(old_start, start);
-	common_end = min(old_end, end);
-
-	/* no overlap ? */
-	if (common_start >= common_end)
-		return;
-
-	if (old_start < common_start) {
-		/* make head segment */
-		early_res[i].end = common_start;
-		if (old_end > common_end) {
-			char name[15];
-
-			/*
-			 * Save a local copy of the name, since the
-			 * early_res array could get resized inside
-			 * reserve_early_without_check() ->
-			 * __check_and_double_early_res(), which would
-			 * make the current name pointer invalid.
-			 */
-			strncpy(name, early_res[i].name,
-					 sizeof(early_res[i].name) - 1);
-			/* add another for left over on tail */
-			reserve_early_without_check(common_end, old_end, name);
-		}
-		return;
-	} else {
-		if (old_end > common_end) {
-			/* reuse the entry for tail left */
-			early_res[i].start = common_end;
-			return;
-		}
-		/* all covered */
-		drop_range(i);
-	}
-}
-
-/*
- * Split any existing ranges that:
- *  1) are marked 'overlap_ok', and
- *  2) overlap with the stated range [start, end)
- * into whatever portion (if any) of the existing range is entirely
- * below or entirely above the stated range.  Drop the portion
- * of the existing range that overlaps with the stated range,
- * which will allow the caller of this routine to then add that
- * stated range without conflicting with any existing range.
- */
-static void __init drop_overlaps_that_are_ok(u64 start, u64 end)
-{
-	int i;
-	struct early_res *r;
-	u64 lower_start, lower_end;
-	u64 upper_start, upper_end;
-	char name[15];
-
-	for (i = 0; i < max_early_res && early_res[i].end; i++) {
-		r = &early_res[i];
-
-		/* Continue past non-overlapping ranges */
-		if (end <= r->start || start >= r->end)
-			continue;
-
-		/*
-		 * Leave non-ok overlaps as is; let caller
-		 * panic "Overlapping early reservations"
-		 * when it hits this overlap.
-		 */
-		if (!r->overlap_ok)
-			return;
-
-		/*
-		 * We have an ok overlap.  We will drop it from the early
-		 * reservation map, and add back in any non-overlapping
-		 * portions (lower or upper) as separate, overlap_ok,
-		 * non-overlapping ranges.
-		 */
-
-		/* 1. Note any non-overlapping (lower or upper) ranges. */
-		strncpy(name, r->name, sizeof(name) - 1);
-
-		lower_start = lower_end = 0;
-		upper_start = upper_end = 0;
-		if (r->start < start) {
-			lower_start = r->start;
-			lower_end = start;
-		}
-		if (r->end > end) {
-			upper_start = end;
-			upper_end = r->end;
-		}
-
-		/* 2. Drop the original ok overlapping range */
-		drop_range(i);
-
-		i--;		/* resume for-loop on copied down entry */
-
-		/* 3. Add back in any non-overlapping ranges. */
-		if (lower_end)
-			reserve_early_overlap_ok(lower_start, lower_end, name);
-		if (upper_end)
-			reserve_early_overlap_ok(upper_start, upper_end, name);
-	}
-}
-
-static void __init __reserve_early(u64 start, u64 end, char *name,
-						int overlap_ok)
-{
-	int i;
-	struct early_res *r;
-
-	i = find_overlapped_early(start, end);
-	if (i >= max_early_res)
-		panic("Too many early reservations");
-	r = &early_res[i];
-	if (r->end)
-		panic("Overlapping early reservations "
-		      "%llx-%llx %s to %llx-%llx %s\n",
-		      start, end - 1, name ? name : "", r->start,
-		      r->end - 1, r->name);
-	r->start = start;
-	r->end = end;
-	r->overlap_ok = overlap_ok;
-	if (name)
-		strncpy(r->name, name, sizeof(r->name) - 1);
-	early_res_count++;
-}
-
-/*
- * A few early reservtations come here.
- *
- * The 'overlap_ok' in the name of this routine does -not- mean it
- * is ok for these reservations to overlap an earlier reservation.
- * Rather it means that it is ok for subsequent reservations to
- * overlap this one.
- *
- * Use this entry point to reserve early ranges when you are doing
- * so out of "Paranoia", reserving perhaps more memory than you need,
- * just in case, and don't mind a subsequent overlapping reservation
- * that is known to be needed.
- *
- * The drop_overlaps_that_are_ok() call here isn't really needed.
- * It would be needed if we had two colliding 'overlap_ok'
- * reservations, so that the second such would not panic on the
- * overlap with the first.  We don't have any such as of this
- * writing, but might as well tolerate such if it happens in
- * the future.
- */
-void __init reserve_early_overlap_ok(u64 start, u64 end, char *name)
-{
-	drop_overlaps_that_are_ok(start, end);
-	__reserve_early(start, end, name, 1);
-}
-
-static void __init __check_and_double_early_res(u64 ex_start, u64 ex_end)
-{
-	u64 start, end, size, mem;
-	struct early_res *new;
-
-	/* do we have enough slots left ? */
-	if ((max_early_res - early_res_count) > max(max_early_res/8, 2))
-		return;
-
-	/* double it */
-	mem = -1ULL;
-	size = sizeof(struct early_res) * max_early_res * 2;
-	if (early_res == early_res_x)
-		start = 0;
-	else
-		start = early_res[0].end;
-	end = ex_start;
-	if (start + size < end)
-		mem = find_fw_memmap_area(start, end, size,
-					 sizeof(struct early_res));
-	if (mem == -1ULL) {
-		start = ex_end;
-		end = get_max_mapped();
-		if (start + size < end)
-			mem = find_fw_memmap_area(start, end, size,
-						 sizeof(struct early_res));
-	}
-	if (mem == -1ULL)
-		panic("can not find more space for early_res array");
-
-	new = __va(mem);
-	/* save the first one for own */
-	new[0].start = mem;
-	new[0].end = mem + size;
-	new[0].overlap_ok = 0;
-	/* copy old to new */
-	if (early_res == early_res_x) {
-		memcpy(&new[1], &early_res[0],
-			 sizeof(struct early_res) * max_early_res);
-		memset(&new[max_early_res+1], 0,
-			 sizeof(struct early_res) * (max_early_res - 1));
-		early_res_count++;
-	} else {
-		memcpy(&new[1], &early_res[1],
-			 sizeof(struct early_res) * (max_early_res - 1));
-		memset(&new[max_early_res], 0,
-			 sizeof(struct early_res) * max_early_res);
-	}
-	memset(&early_res[0], 0, sizeof(struct early_res) * max_early_res);
-	early_res = new;
-	max_early_res *= 2;
-	printk(KERN_DEBUG "early_res array is doubled to %d at [%llx - %llx]\n",
-		max_early_res, mem, mem + size - 1);
-}
-
-/*
- * Most early reservations come here.
- *
- * We first have drop_overlaps_that_are_ok() drop any pre-existing
- * 'overlap_ok' ranges, so that we can then reserve this memory
- * range without risk of panic'ing on an overlapping overlap_ok
- * early reservation.
- */
-void __init reserve_early(u64 start, u64 end, char *name)
-{
-	if (start >= end)
-		return;
-
-	__check_and_double_early_res(start, end);
-
-	drop_overlaps_that_are_ok(start, end);
-	__reserve_early(start, end, name, 0);
-}
-
-void __init reserve_early_without_check(u64 start, u64 end, char *name)
-{
-	struct early_res *r;
-
-	if (start >= end)
-		return;
-
-	__check_and_double_early_res(start, end);
-
-	r = &early_res[early_res_count];
-
-	r->start = start;
-	r->end = end;
-	r->overlap_ok = 0;
-	if (name)
-		strncpy(r->name, name, sizeof(r->name) - 1);
-	early_res_count++;
-}
-
-void __init free_early(u64 start, u64 end)
-{
-	struct early_res *r;
-	int i;
-
-	kmemleak_free_part(__va(start), end - start);
-
-	i = find_overlapped_early(start, end);
-	r = &early_res[i];
-	if (i >= max_early_res || r->end != end || r->start != start)
-		panic("free_early on not reserved area: %llx-%llx!",
-			 start, end - 1);
-
-	drop_range(i);
-}
-
-void __init free_early_partial(u64 start, u64 end)
-{
-	struct early_res *r;
-	int i;
-
-	kmemleak_free_part(__va(start), end - start);
-
-	if (start == end)
-		return;
-
-	if (WARN_ONCE(start > end, "  wrong range [%#llx, %#llx]\n", start, end))
-		return;
-
-try_next:
-	i = find_overlapped_early(start, end);
-	if (i >= max_early_res)
-		return;
-
-	r = &early_res[i];
-	/* hole ? */
-	if (r->end >= end && r->start <= start) {
-		drop_range_partial(i, start, end);
-		return;
-	}
-
-	drop_range_partial(i, start, end);
-	goto try_next;
-}
-
-#ifdef CONFIG_NO_BOOTMEM
-static void __init subtract_early_res(struct range *range, int az)
-{
-	int i, count;
-	u64 final_start, final_end;
-	int idx = 0;
-
-	count  = 0;
-	for (i = 0; i < max_early_res && early_res[i].end; i++)
-		count++;
-
-	/* need to skip first one ?*/
-	if (early_res != early_res_x)
-		idx = 1;
-
-#define DEBUG_PRINT_EARLY_RES 1
-
-#if DEBUG_PRINT_EARLY_RES
-	printk(KERN_INFO "Subtract (%d early reservations)\n", count);
-#endif
-	for (i = idx; i < count; i++) {
-		struct early_res *r = &early_res[i];
-#if DEBUG_PRINT_EARLY_RES
-		printk(KERN_INFO "  #%d [%010llx - %010llx] %15s\n", i,
-			r->start, r->end, r->name);
-#endif
-		final_start = PFN_DOWN(r->start);
-		final_end = PFN_UP(r->end);
-		if (final_start >= final_end)
-			continue;
-		subtract_range(range, az, final_start, final_end);
-	}
-
-}
-
-int __init get_free_all_memory_range(struct range **rangep, int nodeid)
-{
-	int i, count;
-	u64 start = 0, end;
-	u64 size;
-	u64 mem;
-	struct range *range;
-	int nr_range;
-
-	count  = 0;
-	for (i = 0; i < max_early_res && early_res[i].end; i++)
-		count++;
-
-	count *= 2;
-
-	size = sizeof(struct range) * count;
-	end = get_max_mapped();
-#ifdef MAX_DMA32_PFN
-	if (end > (MAX_DMA32_PFN << PAGE_SHIFT))
-		start = MAX_DMA32_PFN << PAGE_SHIFT;
-#endif
-	mem = find_fw_memmap_area(start, end, size, sizeof(struct range));
-	if (mem == -1ULL)
-		panic("can not find more space for range free");
-
-	range = __va(mem);
-	/* use early_node_map[] and early_res to get range array at first */
-	memset(range, 0, size);
-	nr_range = 0;
-
-	/* need to go over early_node_map to find out good range for node */
-	nr_range = add_from_early_node_map(range, count, nr_range, nodeid);
-#ifdef CONFIG_X86_32
-	subtract_range(range, count, max_low_pfn, -1ULL);
-#endif
-	subtract_early_res(range, count);
-	nr_range = clean_sort_range(range, count);
-
-	/* need to clear it ? */
-	if (nodeid == MAX_NUMNODES) {
-		memset(&early_res[0], 0,
-			 sizeof(struct early_res) * max_early_res);
-		early_res = NULL;
-		max_early_res = 0;
-	}
-
-	*rangep = range;
-	return nr_range;
-}
-#else
-void __init early_res_to_bootmem(u64 start, u64 end)
-{
-	int i, count;
-	u64 final_start, final_end;
-	int idx = 0;
-
-	count  = 0;
-	for (i = 0; i < max_early_res && early_res[i].end; i++)
-		count++;
-
-	/* need to skip first one ?*/
-	if (early_res != early_res_x)
-		idx = 1;
-
-	printk(KERN_INFO "(%d/%d early reservations) ==> bootmem [%010llx - %010llx]\n",
-			 count - idx, max_early_res, start, end);
-	for (i = idx; i < count; i++) {
-		struct early_res *r = &early_res[i];
-		printk(KERN_INFO "  #%d [%010llx - %010llx] %16s", i,
-			r->start, r->end, r->name);
-		final_start = max(start, r->start);
-		final_end = min(end, r->end);
-		if (final_start >= final_end) {
-			printk(KERN_CONT "\n");
-			continue;
-		}
-		printk(KERN_CONT " ==> [%010llx - %010llx]\n",
-			final_start, final_end);
-		reserve_bootmem_generic(final_start, final_end - final_start,
-				BOOTMEM_DEFAULT);
-	}
-	/* clear them */
-	memset(&early_res[0], 0, sizeof(struct early_res) * max_early_res);
-	early_res = NULL;
-	max_early_res = 0;
-	early_res_count = 0;
-}
-#endif
-
-/* Check for already reserved areas */
-static inline int __init bad_addr(u64 *addrp, u64 size, u64 align)
-{
-	int i;
-	u64 addr = *addrp;
-	int changed = 0;
-	struct early_res *r;
-again:
-	i = find_overlapped_early(addr, addr + size);
-	r = &early_res[i];
-	if (i < max_early_res && r->end) {
-		*addrp = addr = round_up(r->end, align);
-		changed = 1;
-		goto again;
-	}
-	return changed;
-}
-
-/* Check for already reserved areas */
-static inline int __init bad_addr_size(u64 *addrp, u64 *sizep, u64 align)
-{
-	int i;
-	u64 addr = *addrp, last;
-	u64 size = *sizep;
-	int changed = 0;
-again:
-	last = addr + size;
-	for (i = 0; i < max_early_res && early_res[i].end; i++) {
-		struct early_res *r = &early_res[i];
-		if (last > r->start && addr < r->start) {
-			size = r->start - addr;
-			changed = 1;
-			goto again;
-		}
-		if (last > r->end && addr < r->end) {
-			addr = round_up(r->end, align);
-			size = last - addr;
-			changed = 1;
-			goto again;
-		}
-		if (last <= r->end && addr >= r->start) {
-			(*sizep)++;
-			return 0;
-		}
-	}
-	if (changed) {
-		*addrp = addr;
-		*sizep = size;
-	}
-	return changed;
-}
-
-/*
- * Find a free area with specified alignment in a specific range.
- * only with the area.between start to end is active range from early_node_map
- * so they are good as RAM
- */
-u64 __init find_early_area(u64 ei_start, u64 ei_last, u64 start, u64 end,
-			 u64 size, u64 align)
-{
-	u64 addr, last;
-
-	addr = round_up(ei_start, align);
-	if (addr < start)
-		addr = round_up(start, align);
-	if (addr >= ei_last)
-		goto out;
-	while (bad_addr(&addr, size, align) && addr+size <= ei_last)
-		;
-	last = addr + size;
-	if (last > ei_last)
-		goto out;
-	if (last > end)
-		goto out;
-
-	return addr;
-
-out:
-	return -1ULL;
-}
-
-u64 __init find_early_area_size(u64 ei_start, u64 ei_last, u64 start,
-			 u64 *sizep, u64 align)
-{
-	u64 addr, last;
-
-	addr = round_up(ei_start, align);
-	if (addr < start)
-		addr = round_up(start, align);
-	if (addr >= ei_last)
-		goto out;
-	*sizep = ei_last - addr;
-	while (bad_addr_size(&addr, sizep, align) && addr + *sizep <= ei_last)
-		;
-	last = addr + *sizep;
-	if (last > ei_last)
-		goto out;
-
-	return addr;
-
-out:
-	return -1ULL;
-}
diff --git a/kernel/exit.c b/kernel/exit.c
index 0312022..e2bdf37 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -149,9 +149,7 @@
 {
 	struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
 
-#ifdef CONFIG_PERF_EVENTS
-	WARN_ON_ONCE(tsk->perf_event_ctxp);
-#endif
+	perf_event_delayed_put(tsk);
 	trace_sched_process_free(tsk);
 	put_task_struct(tsk);
 }
diff --git a/kernel/futex.c b/kernel/futex.c
index 6a3a5fa..a118bf1 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -91,6 +91,7 @@
 
 /**
  * struct futex_q - The hashed futex queue entry, one per waiting task
+ * @list:		priority-sorted list of tasks waiting on this futex
  * @task:		the task waiting on the futex
  * @lock_ptr:		the hash bucket lock
  * @key:		the key the futex is hashed on
@@ -104,7 +105,7 @@
  *
  * A futex_q has a woken state, just like tasks have TASK_RUNNING.
  * It is considered woken when plist_node_empty(&q->list) || q->lock_ptr == 0.
- * The order of wakup is always to make the first condition true, then
+ * The order of wakeup is always to make the first condition true, then
  * the second.
  *
  * PI futexes are typically woken before they are removed from the hash list via
@@ -295,7 +296,7 @@
  * Slow path to fixup the fault we just took in the atomic write
  * access to @uaddr.
  *
- * We have no generic implementation of a non destructive write to the
+ * We have no generic implementation of a non-destructive write to the
  * user address. We know that we faulted in the atomic pagefault
  * disabled section so we can as well avoid the #PF overhead by
  * calling get_user_pages() right away.
@@ -515,7 +516,7 @@
 			 */
 			pi_state = this->pi_state;
 			/*
-			 * Userspace might have messed up non PI and PI futexes
+			 * Userspace might have messed up non-PI and PI futexes
 			 */
 			if (unlikely(!pi_state))
 				return -EINVAL;
@@ -736,8 +737,8 @@
 
 	/*
 	 * We set q->lock_ptr = NULL _before_ we wake up the task. If
-	 * a non futex wake up happens on another CPU then the task
-	 * might exit and p would dereference a non existing task
+	 * a non-futex wake up happens on another CPU then the task
+	 * might exit and p would dereference a non-existing task
 	 * struct. Prevent this by holding a reference on p across the
 	 * wake up.
 	 */
@@ -1131,11 +1132,13 @@
 
 /**
  * futex_requeue() - Requeue waiters from uaddr1 to uaddr2
- * uaddr1:	source futex user address
- * uaddr2:	target futex user address
- * nr_wake:	number of waiters to wake (must be 1 for requeue_pi)
- * nr_requeue:	number of waiters to requeue (0-INT_MAX)
- * requeue_pi:	if we are attempting to requeue from a non-pi futex to a
+ * @uaddr1:	source futex user address
+ * @fshared:	0 for a PROCESS_PRIVATE futex, 1 for PROCESS_SHARED
+ * @uaddr2:	target futex user address
+ * @nr_wake:	number of waiters to wake (must be 1 for requeue_pi)
+ * @nr_requeue:	number of waiters to requeue (0-INT_MAX)
+ * @cmpval:	@uaddr1 expected value (or %NULL)
+ * @requeue_pi:	if we are attempting to requeue from a non-pi futex to a
  * 		pi futex (pi to pi requeue is not supported)
  *
  * Requeue waiters on uaddr1 to uaddr2. In the requeue_pi case, try to acquire
@@ -1360,10 +1363,10 @@
 
 /* The key must be already stored in q->key. */
 static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
+	__acquires(&hb->lock)
 {
 	struct futex_hash_bucket *hb;
 
-	get_futex_key_refs(&q->key);
 	hb = hash_futex(&q->key);
 	q->lock_ptr = &hb->lock;
 
@@ -1373,9 +1376,9 @@
 
 static inline void
 queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
+	__releases(&hb->lock)
 {
 	spin_unlock(&hb->lock);
-	drop_futex_key_refs(&q->key);
 }
 
 /**
@@ -1391,6 +1394,7 @@
  * an example).
  */
 static inline void queue_me(struct futex_q *q, struct futex_hash_bucket *hb)
+	__releases(&hb->lock)
 {
 	int prio;
 
@@ -1471,6 +1475,7 @@
  * and dropped here.
  */
 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);
@@ -1480,8 +1485,6 @@
 	q->pi_state = NULL;
 
 	spin_unlock(q->lock_ptr);
-
-	drop_futex_key_refs(&q->key);
 }
 
 /*
@@ -1812,7 +1815,10 @@
 	}
 
 retry:
-	/* Prepare to wait on uaddr. */
+	/*
+	 * Prepare to wait on uaddr. On success, holds hb lock and increments
+	 * q.key refs.
+	 */
 	ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
 	if (ret)
 		goto out;
@@ -1822,28 +1828,27 @@
 
 	/* If we were woken (and unqueued), we succeeded, whatever. */
 	ret = 0;
+	/* unqueue_me() drops q.key ref */
 	if (!unqueue_me(&q))
-		goto out_put_key;
+		goto out;
 	ret = -ETIMEDOUT;
 	if (to && !to->task)
-		goto out_put_key;
+		goto out;
 
 	/*
 	 * We expect signal_pending(current), but we might be the
 	 * victim of a spurious wakeup as well.
 	 */
-	if (!signal_pending(current)) {
-		put_futex_key(fshared, &q.key);
+	if (!signal_pending(current))
 		goto retry;
-	}
 
 	ret = -ERESTARTSYS;
 	if (!abs_time)
-		goto out_put_key;
+		goto out;
 
 	restart = &current_thread_info()->restart_block;
 	restart->fn = futex_wait_restart;
-	restart->futex.uaddr = (u32 *)uaddr;
+	restart->futex.uaddr = uaddr;
 	restart->futex.val = val;
 	restart->futex.time = abs_time->tv64;
 	restart->futex.bitset = bitset;
@@ -1856,8 +1861,6 @@
 
 	ret = -ERESTART_RESTARTBLOCK;
 
-out_put_key:
-	put_futex_key(fshared, &q.key);
 out:
 	if (to) {
 		hrtimer_cancel(&to->timer);
@@ -1869,7 +1872,7 @@
 
 static long futex_wait_restart(struct restart_block *restart)
 {
-	u32 __user *uaddr = (u32 __user *)restart->futex.uaddr;
+	u32 __user *uaddr = restart->futex.uaddr;
 	int fshared = 0;
 	ktime_t t, *tp = NULL;
 
@@ -2236,7 +2239,10 @@
 	q.rt_waiter = &rt_waiter;
 	q.requeue_pi_key = &key2;
 
-	/* Prepare to wait on uaddr. */
+	/*
+	 * Prepare to wait on uaddr. On success, increments q.key (key1) ref
+	 * count.
+	 */
 	ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
 	if (ret)
 		goto out_key2;
@@ -2254,7 +2260,9 @@
 	 * In order for us to be here, we know our q.key == key2, and since
 	 * we took the hb->lock above, we also know that futex_requeue() has
 	 * completed and we no longer have to concern ourselves with a wakeup
-	 * race with the atomic proxy lock acquition by the requeue code.
+	 * race with the atomic proxy lock acquisition by the requeue code. The
+	 * futex_requeue dropped our key1 reference and incremented our key2
+	 * reference count.
 	 */
 
 	/* Check if the requeue code acquired the second futex for us. */
@@ -2458,7 +2466,7 @@
  */
 static inline int fetch_robust_entry(struct robust_list __user **entry,
 				     struct robust_list __user * __user *head,
-				     int *pi)
+				     unsigned int *pi)
 {
 	unsigned long uentry;
 
@@ -2647,7 +2655,7 @@
 	 * of the complex code paths. Also we want to prevent
 	 * registration of robust lists in that case. NULL is
 	 * guaranteed to fault and we get -EFAULT on functional
-	 * implementation, the non functional ones will return
+	 * implementation, the non-functional ones will return
 	 * -ENOSYS.
 	 */
 	curval = cmpxchg_futex_value_locked(NULL, 0, 0);
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index d49afb2..06da4df 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -19,7 +19,7 @@
  */
 static inline int
 fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
-		   compat_uptr_t __user *head, int *pi)
+		   compat_uptr_t __user *head, unsigned int *pi)
 {
 	if (get_user(*uentry, head))
 		return -EFAULT;
diff --git a/kernel/gcov/fs.c b/kernel/gcov/fs.c
index f83972b..9bd0934 100644
--- a/kernel/gcov/fs.c
+++ b/kernel/gcov/fs.c
@@ -561,6 +561,7 @@
 static const struct file_operations gcov_reset_fops = {
 	.write	= reset_write,
 	.read	= reset_read,
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 1decafb..72206cf 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -931,6 +931,7 @@
 remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
 {
 	if (hrtimer_is_queued(timer)) {
+		unsigned long state;
 		int reprogram;
 
 		/*
@@ -944,8 +945,13 @@
 		debug_deactivate(timer);
 		timer_stats_hrtimer_clear_start_info(timer);
 		reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
-		__remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE,
-				 reprogram);
+		/*
+		 * We must preserve the CALLBACK state flag here,
+		 * otherwise we could move the timer base in
+		 * switch_hrtimer_base.
+		 */
+		state = timer->state & HRTIMER_STATE_CALLBACK;
+		__remove_hrtimer(timer, base, state, reprogram);
 		return 1;
 	}
 	return 0;
@@ -1231,6 +1237,9 @@
 		BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
 		enqueue_hrtimer(timer, base);
 	}
+
+	WARN_ON_ONCE(!(timer->state & HRTIMER_STATE_CALLBACK));
+
 	timer->state &= ~HRTIMER_STATE_CALLBACK;
 }
 
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index 0c642d5..53ead17 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -98,7 +98,7 @@
 	printk(KERN_ERR "\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
 			" disables this message.\n");
 	sched_show_task(t);
-	__debug_show_held_locks(t);
+	debug_show_held_locks(t);
 
 	touch_nmi_watchdog();
 
@@ -111,7 +111,7 @@
  * periodically exit the critical section and enter a new one.
  *
  * For preemptible RCU it is sufficient to call rcu_read_unlock in order
- * exit the grace period. For classic RCU, a reschedule is required.
+ * to exit the grace period. For classic RCU, a reschedule is required.
  */
 static void rcu_lock_break(struct task_struct *g, struct task_struct *t)
 {
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c
index c7c2aed..2c9120f 100644
--- a/kernel/hw_breakpoint.c
+++ b/kernel/hw_breakpoint.c
@@ -113,12 +113,12 @@
  */
 static int task_bp_pinned(struct perf_event *bp, enum bp_type_idx type)
 {
-	struct perf_event_context *ctx = bp->ctx;
+	struct task_struct *tsk = bp->hw.bp_target;
 	struct perf_event *iter;
 	int count = 0;
 
 	list_for_each_entry(iter, &bp_task_head, hw.bp_list) {
-		if (iter->ctx == ctx && find_slot_idx(iter) == type)
+		if (iter->hw.bp_target == tsk && find_slot_idx(iter) == type)
 			count += hw_breakpoint_weight(iter);
 	}
 
@@ -134,7 +134,7 @@
 		    enum bp_type_idx type)
 {
 	int cpu = bp->cpu;
-	struct task_struct *tsk = bp->ctx->task;
+	struct task_struct *tsk = bp->hw.bp_target;
 
 	if (cpu >= 0) {
 		slots->pinned = per_cpu(nr_cpu_bp_pinned[type], cpu);
@@ -213,7 +213,7 @@
 	       int weight)
 {
 	int cpu = bp->cpu;
-	struct task_struct *tsk = bp->ctx->task;
+	struct task_struct *tsk = bp->hw.bp_target;
 
 	/* Pinned counter cpu profiling */
 	if (!tsk) {
@@ -433,8 +433,7 @@
 			    perf_overflow_handler_t triggered,
 			    struct task_struct *tsk)
 {
-	return perf_event_create_kernel_counter(attr, -1, task_pid_vnr(tsk),
-						triggered);
+	return perf_event_create_kernel_counter(attr, -1, tsk, triggered);
 }
 EXPORT_SYMBOL_GPL(register_user_hw_breakpoint);
 
@@ -516,7 +515,7 @@
 	get_online_cpus();
 	for_each_online_cpu(cpu) {
 		pevent = per_cpu_ptr(cpu_events, cpu);
-		bp = perf_event_create_kernel_counter(attr, cpu, -1, triggered);
+		bp = perf_event_create_kernel_counter(attr, cpu, NULL, triggered);
 
 		*pevent = bp;
 
@@ -566,6 +565,61 @@
 	.priority = 0x7fffffff
 };
 
+static void bp_perf_event_destroy(struct perf_event *event)
+{
+	release_bp_slot(event);
+}
+
+static int hw_breakpoint_event_init(struct perf_event *bp)
+{
+	int err;
+
+	if (bp->attr.type != PERF_TYPE_BREAKPOINT)
+		return -ENOENT;
+
+	err = register_perf_hw_breakpoint(bp);
+	if (err)
+		return err;
+
+	bp->destroy = bp_perf_event_destroy;
+
+	return 0;
+}
+
+static int hw_breakpoint_add(struct perf_event *bp, int flags)
+{
+	if (!(flags & PERF_EF_START))
+		bp->hw.state = PERF_HES_STOPPED;
+
+	return arch_install_hw_breakpoint(bp);
+}
+
+static void hw_breakpoint_del(struct perf_event *bp, int flags)
+{
+	arch_uninstall_hw_breakpoint(bp);
+}
+
+static void hw_breakpoint_start(struct perf_event *bp, int flags)
+{
+	bp->hw.state = 0;
+}
+
+static void hw_breakpoint_stop(struct perf_event *bp, int flags)
+{
+	bp->hw.state = PERF_HES_STOPPED;
+}
+
+static struct pmu perf_breakpoint = {
+	.task_ctx_nr	= perf_sw_context, /* could eventually get its own */
+
+	.event_init	= hw_breakpoint_event_init,
+	.add		= hw_breakpoint_add,
+	.del		= hw_breakpoint_del,
+	.start		= hw_breakpoint_start,
+	.stop		= hw_breakpoint_stop,
+	.read		= hw_breakpoint_pmu_read,
+};
+
 static int __init init_hw_breakpoint(void)
 {
 	unsigned int **task_bp_pinned;
@@ -587,6 +641,8 @@
 
 	constraints_initialized = 1;
 
+	perf_pmu_register(&perf_breakpoint);
+
 	return register_die_notifier(&hw_breakpoint_exceptions_nb);
 
  err_alloc:
@@ -602,8 +658,3 @@
 core_initcall(init_hw_breakpoint);
 
 
-struct pmu perf_ops_bp = {
-	.enable		= arch_install_hw_breakpoint,
-	.disable	= arch_uninstall_hw_breakpoint,
-	.read		= hw_breakpoint_pmu_read,
-};
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
new file mode 100644
index 0000000..31d766b
--- /dev/null
+++ b/kernel/irq/Kconfig
@@ -0,0 +1,53 @@
+config HAVE_GENERIC_HARDIRQS
+	def_bool n
+
+if HAVE_GENERIC_HARDIRQS
+menu "IRQ subsystem"
+#
+# Interrupt subsystem related configuration options
+#
+config GENERIC_HARDIRQS
+       def_bool y
+
+config GENERIC_HARDIRQS_NO__DO_IRQ
+       def_bool y
+
+# Select this to disable the deprecated stuff
+config GENERIC_HARDIRQS_NO_DEPRECATED
+       def_bool n
+
+# Options selectable by the architecture code
+config HAVE_SPARSE_IRQ
+       def_bool n
+
+config GENERIC_IRQ_PROBE
+	def_bool n
+
+config GENERIC_PENDING_IRQ
+	def_bool n
+
+config AUTO_IRQ_AFFINITY
+       def_bool n
+
+config IRQ_PER_CPU
+       def_bool n
+
+config HARDIRQS_SW_RESEND
+       def_bool n
+
+config SPARSE_IRQ
+	bool "Support sparse irq numbering"
+	depends on HAVE_SPARSE_IRQ
+	---help---
+
+	  Sparse irq numbering is useful for distro kernels that want
+	  to define a high CONFIG_NR_CPUS value but still want to have
+	  low kernel memory footprint on smaller machines.
+
+	  ( Sparse irqs can also be beneficial on NUMA boxes, as they spread
+	    out the interrupt descriptors in a more NUMA-friendly way. )
+
+	  If you don't know what to do here, say N.
+
+endmenu
+endif
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 7d04780..54329cd 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -1,7 +1,6 @@
 
-obj-y := handle.o manage.o spurious.o resend.o chip.o devres.o
+obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
-obj-$(CONFIG_NUMA_IRQ_DESC) += numa_migrate.o
 obj-$(CONFIG_PM_SLEEP) += pm.o
diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c
index 2295a31..505798f 100644
--- a/kernel/irq/autoprobe.c
+++ b/kernel/irq/autoprobe.c
@@ -57,9 +57,10 @@
 			 * Some chips need to know about probing in
 			 * progress:
 			 */
-			if (desc->chip->set_type)
-				desc->chip->set_type(i, IRQ_TYPE_PROBE);
-			desc->chip->startup(i);
+			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);
 		}
 		raw_spin_unlock_irq(&desc->lock);
 	}
@@ -76,7 +77,7 @@
 		raw_spin_lock_irq(&desc->lock);
 		if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
 			desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
-			if (desc->chip->startup(i))
+			if (desc->irq_data.chip->irq_startup(&desc->irq_data))
 				desc->status |= IRQ_PENDING;
 		}
 		raw_spin_unlock_irq(&desc->lock);
@@ -98,7 +99,7 @@
 			/* It triggered already - consider it spurious. */
 			if (!(status & IRQ_WAITING)) {
 				desc->status = status & ~IRQ_AUTODETECT;
-				desc->chip->shutdown(i);
+				desc->irq_data.chip->irq_shutdown(&desc->irq_data);
 			} else
 				if (i < 32)
 					mask |= 1 << i;
@@ -137,7 +138,7 @@
 				mask |= 1 << i;
 
 			desc->status = status & ~IRQ_AUTODETECT;
-			desc->chip->shutdown(i);
+			desc->irq_data.chip->irq_shutdown(&desc->irq_data);
 		}
 		raw_spin_unlock_irq(&desc->lock);
 	}
@@ -181,7 +182,7 @@
 				nr_of_irqs++;
 			}
 			desc->status = status & ~IRQ_AUTODETECT;
-			desc->chip->shutdown(i);
+			desc->irq_data.chip->irq_shutdown(&desc->irq_data);
 		}
 		raw_spin_unlock_irq(&desc->lock);
 	}
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index b7091d5..baa5c4a 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -18,108 +18,6 @@
 
 #include "internals.h"
 
-static void dynamic_irq_init_x(unsigned int irq, bool keep_chip_data)
-{
-	struct irq_desc *desc;
-	unsigned long flags;
-
-	desc = irq_to_desc(irq);
-	if (!desc) {
-		WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
-		return;
-	}
-
-	/* Ensure we don't have left over values from a previous use of this irq */
-	raw_spin_lock_irqsave(&desc->lock, flags);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &no_irq_chip;
-	desc->handle_irq = handle_bad_irq;
-	desc->depth = 1;
-	desc->msi_desc = NULL;
-	desc->handler_data = NULL;
-	if (!keep_chip_data)
-		desc->chip_data = NULL;
-	desc->action = NULL;
-	desc->irq_count = 0;
-	desc->irqs_unhandled = 0;
-#ifdef CONFIG_SMP
-	cpumask_setall(desc->affinity);
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-	cpumask_clear(desc->pending_mask);
-#endif
-#endif
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/**
- *	dynamic_irq_init - initialize a dynamically allocated irq
- *	@irq:	irq number to initialize
- */
-void dynamic_irq_init(unsigned int irq)
-{
-	dynamic_irq_init_x(irq, false);
-}
-
-/**
- *	dynamic_irq_init_keep_chip_data - initialize a dynamically allocated irq
- *	@irq:	irq number to initialize
- *
- *	does not set irq_to_desc(irq)->chip_data to NULL
- */
-void dynamic_irq_init_keep_chip_data(unsigned int irq)
-{
-	dynamic_irq_init_x(irq, true);
-}
-
-static void dynamic_irq_cleanup_x(unsigned int irq, bool keep_chip_data)
-{
-	struct irq_desc *desc = irq_to_desc(irq);
-	unsigned long flags;
-
-	if (!desc) {
-		WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
-		return;
-	}
-
-	raw_spin_lock_irqsave(&desc->lock, flags);
-	if (desc->action) {
-		raw_spin_unlock_irqrestore(&desc->lock, flags);
-		WARN(1, KERN_ERR "Destroying IRQ%d without calling free_irq\n",
-			irq);
-		return;
-	}
-	desc->msi_desc = NULL;
-	desc->handler_data = NULL;
-	if (!keep_chip_data)
-		desc->chip_data = NULL;
-	desc->handle_irq = handle_bad_irq;
-	desc->chip = &no_irq_chip;
-	desc->name = NULL;
-	clear_kstat_irqs(desc);
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/**
- *	dynamic_irq_cleanup - cleanup a dynamically allocated irq
- *	@irq:	irq number to initialize
- */
-void dynamic_irq_cleanup(unsigned int irq)
-{
-	dynamic_irq_cleanup_x(irq, false);
-}
-
-/**
- *	dynamic_irq_cleanup_keep_chip_data - cleanup a dynamically allocated irq
- *	@irq:	irq number to initialize
- *
- *	does not set irq_to_desc(irq)->chip_data to NULL
- */
-void dynamic_irq_cleanup_keep_chip_data(unsigned int irq)
-{
-	dynamic_irq_cleanup_x(irq, true);
-}
-
-
 /**
  *	set_irq_chip - set the irq chip for an irq
  *	@irq:	irq number
@@ -140,7 +38,7 @@
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
 	irq_chip_set_defaults(chip);
-	desc->chip = chip;
+	desc->irq_data.chip = chip;
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
 
 	return 0;
@@ -193,7 +91,7 @@
 	}
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
-	desc->handler_data = data;
+	desc->irq_data.handler_data = data;
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
 	return 0;
 }
@@ -218,7 +116,7 @@
 	}
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
-	desc->msi_desc = entry;
+	desc->irq_data.msi_desc = entry;
 	if (entry)
 		entry->irq = irq;
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
@@ -243,19 +141,27 @@
 		return -EINVAL;
 	}
 
-	if (!desc->chip) {
+	if (!desc->irq_data.chip) {
 		printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq);
 		return -EINVAL;
 	}
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
-	desc->chip_data = data;
+	desc->irq_data.chip_data = data;
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
 
 	return 0;
 }
 EXPORT_SYMBOL(set_irq_chip_data);
 
+struct irq_data *irq_get_irq_data(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	return desc ? &desc->irq_data : NULL;
+}
+EXPORT_SYMBOL_GPL(irq_get_irq_data);
+
 /**
  *	set_irq_nested_thread - Set/Reset the IRQ_NESTED_THREAD flag of an irq
  *
@@ -287,93 +193,216 @@
 /*
  * default enable function
  */
-static void default_enable(unsigned int irq)
+static void default_enable(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_desc *desc = irq_data_to_desc(data);
 
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 	desc->status &= ~IRQ_MASKED;
 }
 
 /*
  * default disable function
  */
-static void default_disable(unsigned int irq)
+static void default_disable(struct irq_data *data)
 {
 }
 
 /*
  * default startup function
  */
-static unsigned int default_startup(unsigned int irq)
+static unsigned int default_startup(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_desc *desc = irq_data_to_desc(data);
 
-	desc->chip->enable(irq);
+	desc->irq_data.chip->irq_enable(data);
 	return 0;
 }
 
 /*
  * default shutdown function
  */
-static void default_shutdown(unsigned int irq)
+static void default_shutdown(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_desc *desc = irq_data_to_desc(data);
 
-	desc->chip->mask(irq);
+	desc->irq_data.chip->irq_mask(&desc->irq_data);
 	desc->status |= IRQ_MASKED;
 }
 
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
+/* Temporary migration helpers */
+static void compat_irq_mask(struct irq_data *data)
+{
+	data->chip->mask(data->irq);
+}
+
+static void compat_irq_unmask(struct irq_data *data)
+{
+	data->chip->unmask(data->irq);
+}
+
+static void compat_irq_ack(struct irq_data *data)
+{
+	data->chip->ack(data->irq);
+}
+
+static void compat_irq_mask_ack(struct irq_data *data)
+{
+	data->chip->mask_ack(data->irq);
+}
+
+static void compat_irq_eoi(struct irq_data *data)
+{
+	data->chip->eoi(data->irq);
+}
+
+static void compat_irq_enable(struct irq_data *data)
+{
+	data->chip->enable(data->irq);
+}
+
+static void compat_irq_disable(struct irq_data *data)
+{
+	data->chip->disable(data->irq);
+}
+
+static void compat_irq_shutdown(struct irq_data *data)
+{
+	data->chip->shutdown(data->irq);
+}
+
+static unsigned int compat_irq_startup(struct irq_data *data)
+{
+	return data->chip->startup(data->irq);
+}
+
+static int compat_irq_set_affinity(struct irq_data *data,
+				   const struct cpumask *dest, bool force)
+{
+	return data->chip->set_affinity(data->irq, dest);
+}
+
+static int compat_irq_set_type(struct irq_data *data, unsigned int type)
+{
+	return data->chip->set_type(data->irq, type);
+}
+
+static int compat_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+	return data->chip->set_wake(data->irq, on);
+}
+
+static int compat_irq_retrigger(struct irq_data *data)
+{
+	return data->chip->retrigger(data->irq);
+}
+
+static void compat_bus_lock(struct irq_data *data)
+{
+	data->chip->bus_lock(data->irq);
+}
+
+static void compat_bus_sync_unlock(struct irq_data *data)
+{
+	data->chip->bus_sync_unlock(data->irq);
+}
+#endif
+
 /*
  * Fixup enable/disable function pointers
  */
 void irq_chip_set_defaults(struct irq_chip *chip)
 {
-	if (!chip->enable)
-		chip->enable = default_enable;
-	if (!chip->disable)
-		chip->disable = default_disable;
-	if (!chip->startup)
-		chip->startup = default_startup;
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
 	/*
-	 * We use chip->disable, when the user provided its own. When
-	 * we have default_disable set for chip->disable, then we need
+	 * 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)
+		chip->irq_disable = compat_irq_disable;
+	if (chip->shutdown)
+		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->shutdown)
-		chip->shutdown = chip->disable != default_disable ?
-			chip->disable : default_shutdown;
-	if (!chip->name)
-		chip->name = chip->typename;
+	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)
+		chip->irq_bus_sync_unlock = compat_bus_sync_unlock;
+	if (chip->mask)
+		chip->irq_mask = compat_irq_mask;
+	if (chip->unmask)
+		chip->irq_unmask = compat_irq_unmask;
+	if (chip->ack)
+		chip->irq_ack = compat_irq_ack;
+	if (chip->mask_ack)
+		chip->irq_mask_ack = compat_irq_mask_ack;
+	if (chip->eoi)
+		chip->irq_eoi = compat_irq_eoi;
+	if (chip->set_affinity)
+		chip->irq_set_affinity = compat_irq_set_affinity;
+	if (chip->set_type)
+		chip->irq_set_type = compat_irq_set_type;
+	if (chip->set_wake)
+		chip->irq_set_wake = compat_irq_set_wake;
+	if (chip->retrigger)
+		chip->irq_retrigger = compat_irq_retrigger;
+#endif
 }
 
-static inline void mask_ack_irq(struct irq_desc *desc, int irq)
+static inline void mask_ack_irq(struct irq_desc *desc)
 {
-	if (desc->chip->mask_ack)
-		desc->chip->mask_ack(irq);
+	if (desc->irq_data.chip->irq_mask_ack)
+		desc->irq_data.chip->irq_mask_ack(&desc->irq_data);
 	else {
-		desc->chip->mask(irq);
-		if (desc->chip->ack)
-			desc->chip->ack(irq);
+		desc->irq_data.chip->irq_mask(&desc->irq_data);
+		if (desc->irq_data.chip->irq_ack)
+			desc->irq_data.chip->irq_ack(&desc->irq_data);
 	}
 	desc->status |= IRQ_MASKED;
 }
 
-static inline void mask_irq(struct irq_desc *desc, int irq)
+static inline void mask_irq(struct irq_desc *desc)
 {
-	if (desc->chip->mask) {
-		desc->chip->mask(irq);
+	if (desc->irq_data.chip->irq_mask) {
+		desc->irq_data.chip->irq_mask(&desc->irq_data);
 		desc->status |= IRQ_MASKED;
 	}
 }
 
-static inline void unmask_irq(struct irq_desc *desc, int irq)
+static inline void unmask_irq(struct irq_desc *desc)
 {
-	if (desc->chip->unmask) {
-		desc->chip->unmask(irq);
+	if (desc->irq_data.chip->irq_unmask) {
+		desc->irq_data.chip->irq_unmask(&desc->irq_data);
 		desc->status &= ~IRQ_MASKED;
 	}
 }
@@ -476,7 +505,7 @@
 	irqreturn_t action_ret;
 
 	raw_spin_lock(&desc->lock);
-	mask_ack_irq(desc, irq);
+	mask_ack_irq(desc);
 
 	if (unlikely(desc->status & IRQ_INPROGRESS))
 		goto out_unlock;
@@ -502,7 +531,7 @@
 	desc->status &= ~IRQ_INPROGRESS;
 
 	if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT)))
-		unmask_irq(desc, irq);
+		unmask_irq(desc);
 out_unlock:
 	raw_spin_unlock(&desc->lock);
 }
@@ -539,7 +568,7 @@
 	action = desc->action;
 	if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
 		desc->status |= IRQ_PENDING;
-		mask_irq(desc, irq);
+		mask_irq(desc);
 		goto out;
 	}
 
@@ -554,7 +583,7 @@
 	raw_spin_lock(&desc->lock);
 	desc->status &= ~IRQ_INPROGRESS;
 out:
-	desc->chip->eoi(irq);
+	desc->irq_data.chip->irq_eoi(&desc->irq_data);
 
 	raw_spin_unlock(&desc->lock);
 }
@@ -590,14 +619,13 @@
 	if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
 		    !desc->action)) {
 		desc->status |= (IRQ_PENDING | IRQ_MASKED);
-		mask_ack_irq(desc, irq);
+		mask_ack_irq(desc);
 		goto out_unlock;
 	}
 	kstat_incr_irqs_this_cpu(irq, desc);
 
 	/* Start handling the irq */
-	if (desc->chip->ack)
-		desc->chip->ack(irq);
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	/* Mark the IRQ currently in progress.*/
 	desc->status |= IRQ_INPROGRESS;
@@ -607,7 +635,7 @@
 		irqreturn_t action_ret;
 
 		if (unlikely(!action)) {
-			mask_irq(desc, irq);
+			mask_irq(desc);
 			goto out_unlock;
 		}
 
@@ -619,7 +647,7 @@
 		if (unlikely((desc->status &
 			       (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
 			      (IRQ_PENDING | IRQ_MASKED))) {
-			unmask_irq(desc, irq);
+			unmask_irq(desc);
 		}
 
 		desc->status &= ~IRQ_PENDING;
@@ -650,15 +678,15 @@
 
 	kstat_incr_irqs_this_cpu(irq, desc);
 
-	if (desc->chip->ack)
-		desc->chip->ack(irq);
+	if (desc->irq_data.chip->irq_ack)
+		desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	action_ret = handle_IRQ_event(irq, desc->action);
 	if (!noirqdebug)
 		note_interrupt(irq, desc, action_ret);
 
-	if (desc->chip->eoi)
-		desc->chip->eoi(irq);
+	if (desc->irq_data.chip->irq_eoi)
+		desc->irq_data.chip->irq_eoi(&desc->irq_data);
 }
 
 void
@@ -676,7 +704,7 @@
 
 	if (!handle)
 		handle = handle_bad_irq;
-	else if (desc->chip == &no_irq_chip) {
+	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);
 		/*
@@ -686,16 +714,16 @@
 		 * prevent us to setup the interrupt at all. Switch it to
 		 * dummy_irq_chip for easy transition.
 		 */
-		desc->chip = &dummy_irq_chip;
+		desc->irq_data.chip = &dummy_irq_chip;
 	}
 
-	chip_bus_lock(irq, desc);
+	chip_bus_lock(desc);
 	raw_spin_lock_irqsave(&desc->lock, flags);
 
 	/* Uninstall? */
 	if (handle == handle_bad_irq) {
-		if (desc->chip != &no_irq_chip)
-			mask_ack_irq(desc, irq);
+		if (desc->irq_data.chip != &no_irq_chip)
+			mask_ack_irq(desc);
 		desc->status |= IRQ_DISABLED;
 		desc->depth = 1;
 	}
@@ -706,10 +734,10 @@
 		desc->status &= ~IRQ_DISABLED;
 		desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
 		desc->depth = 0;
-		desc->chip->startup(irq);
+		desc->irq_data.chip->irq_startup(&desc->irq_data);
 	}
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
-	chip_bus_sync_unlock(irq, desc);
+	chip_bus_sync_unlock(desc);
 }
 EXPORT_SYMBOL_GPL(__set_irq_handler);
 
@@ -729,32 +757,20 @@
 	__set_irq_handler(irq, handle, 0, name);
 }
 
-void set_irq_noprobe(unsigned int irq)
+void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
 
-	if (!desc) {
-		printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq);
+	if (!desc)
 		return;
-	}
+
+	/* Sanitize flags */
+	set &= IRQF_MODIFY_MASK;
+	clr &= IRQF_MODIFY_MASK;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
-	desc->status |= IRQ_NOPROBE;
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-void set_irq_probe(unsigned int irq)
-{
-	struct irq_desc *desc = irq_to_desc(irq);
-	unsigned long flags;
-
-	if (!desc) {
-		printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq);
-		return;
-	}
-
-	raw_spin_lock_irqsave(&desc->lock, flags);
-	desc->status &= ~IRQ_NOPROBE;
+	desc->status &= ~clr;
+	desc->status |= set;
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
 }
diff --git a/kernel/irq/dummychip.c b/kernel/irq/dummychip.c
new file mode 100644
index 0000000..20dc547
--- /dev/null
+++ b/kernel/irq/dummychip.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
+ * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
+ *
+ * This file contains the dummy interrupt chip implementation
+ */
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include "internals.h"
+
+/*
+ * What should we do if we get a hw irq event on an illegal vector?
+ * Each architecture has to answer this themself.
+ */
+static void ack_bad(struct irq_data *data)
+{
+	struct irq_desc *desc = irq_data_to_desc(data);
+
+	print_irq_desc(data->irq, desc);
+	ack_bad_irq(data->irq);
+}
+
+/*
+ * NOP functions
+ */
+static void noop(struct irq_data *data) { }
+
+static unsigned int noop_ret(struct irq_data *data)
+{
+	return 0;
+}
+
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
+static void compat_noop(unsigned int irq) { }
+#define END_INIT .end = compat_noop
+#else
+#define END_INIT
+#endif
+
+/*
+ * Generic no controller implementation
+ */
+struct irq_chip no_irq_chip = {
+	.name		= "none",
+	.irq_startup	= noop_ret,
+	.irq_shutdown	= noop,
+	.irq_enable	= noop,
+	.irq_disable	= noop,
+	.irq_ack	= ack_bad,
+	END_INIT
+};
+
+/*
+ * Generic dummy implementation which can be used for
+ * real dumb interrupt sources
+ */
+struct irq_chip dummy_irq_chip = {
+	.name		= "dummy",
+	.irq_startup	= noop_ret,
+	.irq_shutdown	= noop,
+	.irq_enable	= noop,
+	.irq_disable	= noop,
+	.irq_ack	= noop,
+	.irq_mask	= noop,
+	.irq_unmask	= noop,
+	END_INIT
+};
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 27e5c69..e2347eb 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -11,24 +11,15 @@
  */
 
 #include <linux/irq.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/module.h>
 #include <linux/random.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
-#include <linux/rculist.h>
-#include <linux/hash.h>
-#include <linux/radix-tree.h>
+
 #include <trace/events/irq.h>
 
 #include "internals.h"
 
-/*
- * lockdep: we want to handle all irq_desc locks as a single lock-class:
- */
-struct lock_class_key irq_desc_lock_class;
-
 /**
  * handle_bad_irq - handle spurious and unhandled irqs
  * @irq:       the interrupt number
@@ -43,304 +34,6 @@
 	ack_bad_irq(irq);
 }
 
-#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
-static void __init init_irq_default_affinity(void)
-{
-	alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
-	cpumask_setall(irq_default_affinity);
-}
-#else
-static void __init init_irq_default_affinity(void)
-{
-}
-#endif
-
-/*
- * Linux has a controller-independent interrupt architecture.
- * Every controller has a 'controller-template', that is used
- * by the main code to do the right thing. Each driver-visible
- * interrupt source is transparently wired to the appropriate
- * controller. Thus drivers need not be aware of the
- * interrupt-controller.
- *
- * The code is designed to be easily extended with new/different
- * interrupt controllers, without having to do assembly magic or
- * having to touch the generic code.
- *
- * Controller mappings for all interrupt sources:
- */
-int nr_irqs = NR_IRQS;
-EXPORT_SYMBOL_GPL(nr_irqs);
-
-#ifdef CONFIG_SPARSE_IRQ
-
-static struct irq_desc irq_desc_init = {
-	.irq	    = -1,
-	.status	    = IRQ_DISABLED,
-	.chip	    = &no_irq_chip,
-	.handle_irq = handle_bad_irq,
-	.depth      = 1,
-	.lock       = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
-};
-
-void __ref init_kstat_irqs(struct irq_desc *desc, int node, int nr)
-{
-	void *ptr;
-
-	ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs),
-			   GFP_ATOMIC, node);
-
-	/*
-	 * don't overwite if can not get new one
-	 * init_copy_kstat_irqs() could still use old one
-	 */
-	if (ptr) {
-		printk(KERN_DEBUG "  alloc kstat_irqs on node %d\n", node);
-		desc->kstat_irqs = ptr;
-	}
-}
-
-static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)
-{
-	memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
-
-	raw_spin_lock_init(&desc->lock);
-	desc->irq = irq;
-#ifdef CONFIG_SMP
-	desc->node = node;
-#endif
-	lockdep_set_class(&desc->lock, &irq_desc_lock_class);
-	init_kstat_irqs(desc, node, nr_cpu_ids);
-	if (!desc->kstat_irqs) {
-		printk(KERN_ERR "can not alloc kstat_irqs\n");
-		BUG_ON(1);
-	}
-	if (!alloc_desc_masks(desc, node, false)) {
-		printk(KERN_ERR "can not alloc irq_desc cpumasks\n");
-		BUG_ON(1);
-	}
-	init_desc_masks(desc);
-	arch_init_chip_data(desc, node);
-}
-
-/*
- * Protect the sparse_irqs:
- */
-DEFINE_RAW_SPINLOCK(sparse_irq_lock);
-
-static RADIX_TREE(irq_desc_tree, GFP_ATOMIC);
-
-static void set_irq_desc(unsigned int irq, struct irq_desc *desc)
-{
-	radix_tree_insert(&irq_desc_tree, irq, desc);
-}
-
-struct irq_desc *irq_to_desc(unsigned int irq)
-{
-	return radix_tree_lookup(&irq_desc_tree, irq);
-}
-
-void replace_irq_desc(unsigned int irq, struct irq_desc *desc)
-{
-	void **ptr;
-
-	ptr = radix_tree_lookup_slot(&irq_desc_tree, irq);
-	if (ptr)
-		radix_tree_replace_slot(ptr, desc);
-}
-
-static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = {
-	[0 ... NR_IRQS_LEGACY-1] = {
-		.irq	    = -1,
-		.status	    = IRQ_DISABLED,
-		.chip	    = &no_irq_chip,
-		.handle_irq = handle_bad_irq,
-		.depth	    = 1,
-		.lock	    = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
-	}
-};
-
-static unsigned int *kstat_irqs_legacy;
-
-int __init early_irq_init(void)
-{
-	struct irq_desc *desc;
-	int legacy_count;
-	int node;
-	int i;
-
-	init_irq_default_affinity();
-
-	 /* initialize nr_irqs based on nr_cpu_ids */
-	arch_probe_nr_irqs();
-	printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d\n", NR_IRQS, nr_irqs);
-
-	desc = irq_desc_legacy;
-	legacy_count = ARRAY_SIZE(irq_desc_legacy);
-	node = first_online_node;
-
-	/* allocate based on nr_cpu_ids */
-	kstat_irqs_legacy = kzalloc_node(NR_IRQS_LEGACY * nr_cpu_ids *
-					  sizeof(int), GFP_NOWAIT, node);
-
-	for (i = 0; i < legacy_count; i++) {
-		desc[i].irq = i;
-#ifdef CONFIG_SMP
-		desc[i].node = node;
-#endif
-		desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids;
-		lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
-		alloc_desc_masks(&desc[i], node, true);
-		init_desc_masks(&desc[i]);
-		set_irq_desc(i, &desc[i]);
-	}
-
-	return arch_early_irq_init();
-}
-
-struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
-{
-	struct irq_desc *desc;
-	unsigned long flags;
-
-	if (irq >= nr_irqs) {
-		WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n",
-			irq, nr_irqs);
-		return NULL;
-	}
-
-	desc = irq_to_desc(irq);
-	if (desc)
-		return desc;
-
-	raw_spin_lock_irqsave(&sparse_irq_lock, flags);
-
-	/* We have to check it to avoid races with another CPU */
-	desc = irq_to_desc(irq);
-	if (desc)
-		goto out_unlock;
-
-	desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
-
-	printk(KERN_DEBUG "  alloc irq_desc for %d on node %d\n", irq, node);
-	if (!desc) {
-		printk(KERN_ERR "can not alloc irq_desc\n");
-		BUG_ON(1);
-	}
-	init_one_irq_desc(irq, desc, node);
-
-	set_irq_desc(irq, desc);
-
-out_unlock:
-	raw_spin_unlock_irqrestore(&sparse_irq_lock, flags);
-
-	return desc;
-}
-
-#else /* !CONFIG_SPARSE_IRQ */
-
-struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
-	[0 ... NR_IRQS-1] = {
-		.status = IRQ_DISABLED,
-		.chip = &no_irq_chip,
-		.handle_irq = handle_bad_irq,
-		.depth = 1,
-		.lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
-	}
-};
-
-static unsigned int kstat_irqs_all[NR_IRQS][NR_CPUS];
-int __init early_irq_init(void)
-{
-	struct irq_desc *desc;
-	int count;
-	int i;
-
-	init_irq_default_affinity();
-
-	printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);
-
-	desc = irq_desc;
-	count = ARRAY_SIZE(irq_desc);
-
-	for (i = 0; i < count; i++) {
-		desc[i].irq = i;
-		alloc_desc_masks(&desc[i], 0, true);
-		init_desc_masks(&desc[i]);
-		desc[i].kstat_irqs = kstat_irqs_all[i];
-	}
-	return arch_early_irq_init();
-}
-
-struct irq_desc *irq_to_desc(unsigned int irq)
-{
-	return (irq < NR_IRQS) ? irq_desc + irq : NULL;
-}
-
-struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
-{
-	return irq_to_desc(irq);
-}
-#endif /* !CONFIG_SPARSE_IRQ */
-
-void clear_kstat_irqs(struct irq_desc *desc)
-{
-	memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs)));
-}
-
-/*
- * What should we do if we get a hw irq event on an illegal vector?
- * Each architecture has to answer this themself.
- */
-static void ack_bad(unsigned int irq)
-{
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	print_irq_desc(irq, desc);
-	ack_bad_irq(irq);
-}
-
-/*
- * NOP functions
- */
-static void noop(unsigned int irq)
-{
-}
-
-static unsigned int noop_ret(unsigned int irq)
-{
-	return 0;
-}
-
-/*
- * Generic no controller implementation
- */
-struct irq_chip no_irq_chip = {
-	.name		= "none",
-	.startup	= noop_ret,
-	.shutdown	= noop,
-	.enable		= noop,
-	.disable	= noop,
-	.ack		= ack_bad,
-	.end		= noop,
-};
-
-/*
- * Generic dummy implementation which can be used for
- * real dumb interrupt sources
- */
-struct irq_chip dummy_irq_chip = {
-	.name		= "dummy",
-	.startup	= noop_ret,
-	.shutdown	= noop,
-	.enable		= noop,
-	.disable	= noop,
-	.ack		= noop,
-	.mask		= noop,
-	.unmask		= noop,
-	.end		= noop,
-};
-
 /*
  * Special, empty irq handler:
  */
@@ -457,20 +150,20 @@
 		/*
 		 * No locking required for CPU-local interrupts:
 		 */
-		if (desc->chip->ack)
-			desc->chip->ack(irq);
+		if (desc->irq_data.chip->ack)
+			desc->irq_data.chip->ack(irq);
 		if (likely(!(desc->status & IRQ_DISABLED))) {
 			action_ret = handle_IRQ_event(irq, desc->action);
 			if (!noirqdebug)
 				note_interrupt(irq, desc, action_ret);
 		}
-		desc->chip->end(irq);
+		desc->irq_data.chip->end(irq);
 		return 1;
 	}
 
 	raw_spin_lock(&desc->lock);
-	if (desc->chip->ack)
-		desc->chip->ack(irq);
+	if (desc->irq_data.chip->ack)
+		desc->irq_data.chip->ack(irq);
 	/*
 	 * REPLAY is when Linux resends an IRQ that was dropped earlier
 	 * WAITING is used by probe to mark irqs that are being tested
@@ -530,27 +223,9 @@
 	 * The ->end() handler has to deal with interrupts which got
 	 * disabled while the handler was running.
 	 */
-	desc->chip->end(irq);
+	desc->irq_data.chip->end(irq);
 	raw_spin_unlock(&desc->lock);
 
 	return 1;
 }
 #endif
-
-void early_init_irq_lock_class(void)
-{
-	struct irq_desc *desc;
-	int i;
-
-	for_each_irq_desc(i, desc) {
-		lockdep_set_class(&desc->lock, &irq_desc_lock_class);
-	}
-}
-
-unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
-{
-	struct irq_desc *desc = irq_to_desc(irq);
-	return desc ? desc->kstat_irqs[cpu] : 0;
-}
-EXPORT_SYMBOL(kstat_irqs_cpu);
-
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index c63f3bc..4571ae7 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -1,9 +1,12 @@
 /*
  * IRQ subsystem internal functions and variables:
  */
+#include <linux/irqdesc.h>
 
 extern int noirqdebug;
 
+#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);
 
@@ -15,21 +18,19 @@
 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 struct lock_class_key irq_desc_lock_class;
 extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
-extern void clear_kstat_irqs(struct irq_desc *desc);
-extern raw_spinlock_t sparse_irq_lock;
 
-#ifdef CONFIG_SPARSE_IRQ
-void replace_irq_desc(unsigned int irq, struct irq_desc *desc);
-#endif
+/* Resending of interrupts :*/
+void check_irq_resend(struct irq_desc *desc, unsigned int irq);
 
 #ifdef CONFIG_PROC_FS
 extern void register_irq_proc(unsigned int irq, struct irq_desc *desc);
+extern void unregister_irq_proc(unsigned int irq, struct irq_desc *desc);
 extern void register_handler_proc(unsigned int irq, struct irqaction *action);
 extern void unregister_handler_proc(unsigned int irq, struct irqaction *action);
 #else
 static inline void register_irq_proc(unsigned int irq, struct irq_desc *desc) { }
+static inline void unregister_irq_proc(unsigned int irq, struct irq_desc *desc) { }
 static inline void register_handler_proc(unsigned int irq,
 					 struct irqaction *action) { }
 static inline void unregister_handler_proc(unsigned int irq,
@@ -40,17 +41,27 @@
 
 extern void irq_set_thread_affinity(struct irq_desc *desc);
 
-/* Inline functions for support of irq chips on slow busses */
-static inline void chip_bus_lock(unsigned int irq, struct irq_desc *desc)
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
+static inline void irq_end(unsigned int irq, struct irq_desc *desc)
 {
-	if (unlikely(desc->chip->bus_lock))
-		desc->chip->bus_lock(irq);
+	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)
+{
+	if (unlikely(desc->irq_data.chip->irq_bus_lock))
+		desc->irq_data.chip->irq_bus_lock(&desc->irq_data);
 }
 
-static inline void chip_bus_sync_unlock(unsigned int irq, struct irq_desc *desc)
+static inline void chip_bus_sync_unlock(struct irq_desc *desc)
 {
-	if (unlikely(desc->chip->bus_sync_unlock))
-		desc->chip->bus_sync_unlock(irq);
+	if (unlikely(desc->irq_data.chip->irq_bus_sync_unlock))
+		desc->irq_data.chip->irq_bus_sync_unlock(&desc->irq_data);
 }
 
 /*
@@ -67,8 +78,8 @@
 		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("->chip(): %p, ", desc->chip);
-	print_symbol("%s\n", (unsigned long)desc->chip);
+	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);
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
new file mode 100644
index 0000000..9d917ff
--- /dev/null
+++ b/kernel/irq/irqdesc.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
+ * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
+ *
+ * This file contains the interrupt descriptor management code
+ *
+ * Detailed information is available in Documentation/DocBook/genericirq
+ *
+ */
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/radix-tree.h>
+#include <linux/bitmap.h>
+
+#include "internals.h"
+
+/*
+ * lockdep: we want to handle all irq_desc locks as a single lock-class:
+ */
+static struct lock_class_key irq_desc_lock_class;
+
+#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
+static void __init init_irq_default_affinity(void)
+{
+	alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
+	cpumask_setall(irq_default_affinity);
+}
+#else
+static void __init init_irq_default_affinity(void)
+{
+}
+#endif
+
+#ifdef CONFIG_SMP
+static int alloc_masks(struct irq_desc *desc, gfp_t gfp, int node)
+{
+	if (!zalloc_cpumask_var_node(&desc->irq_data.affinity, gfp, node))
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+	if (!zalloc_cpumask_var_node(&desc->pending_mask, gfp, node)) {
+		free_cpumask_var(desc->irq_data.affinity);
+		return -ENOMEM;
+	}
+#endif
+	return 0;
+}
+
+static void desc_smp_init(struct irq_desc *desc, int node)
+{
+	desc->irq_data.node = node;
+	cpumask_copy(desc->irq_data.affinity, irq_default_affinity);
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+	cpumask_clear(desc->pending_mask);
+#endif
+}
+
+static inline int desc_node(struct irq_desc *desc)
+{
+	return desc->irq_data.node;
+}
+
+#else
+static inline int
+alloc_masks(struct irq_desc *desc, gfp_t gfp, int node) { return 0; }
+static inline void desc_smp_init(struct irq_desc *desc, int node) { }
+static inline int desc_node(struct irq_desc *desc) { return 0; }
+#endif
+
+static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)
+{
+	desc->irq_data.irq = irq;
+	desc->irq_data.chip = &no_irq_chip;
+	desc->irq_data.chip_data = NULL;
+	desc->irq_data.handler_data = NULL;
+	desc->irq_data.msi_desc = NULL;
+	desc->status = IRQ_DEFAULT_INIT_FLAGS;
+	desc->handle_irq = handle_bad_irq;
+	desc->depth = 1;
+	desc->irq_count = 0;
+	desc->irqs_unhandled = 0;
+	desc->name = NULL;
+	memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs)));
+	desc_smp_init(desc, node);
+}
+
+int nr_irqs = NR_IRQS;
+EXPORT_SYMBOL_GPL(nr_irqs);
+
+static DEFINE_MUTEX(sparse_irq_lock);
+static DECLARE_BITMAP(allocated_irqs, NR_IRQS);
+
+#ifdef CONFIG_SPARSE_IRQ
+
+static RADIX_TREE(irq_desc_tree, GFP_KERNEL);
+
+static void irq_insert_desc(unsigned int irq, struct irq_desc *desc)
+{
+	radix_tree_insert(&irq_desc_tree, irq, desc);
+}
+
+struct irq_desc *irq_to_desc(unsigned int irq)
+{
+	return radix_tree_lookup(&irq_desc_tree, irq);
+}
+
+static void delete_irq_desc(unsigned int irq)
+{
+	radix_tree_delete(&irq_desc_tree, irq);
+}
+
+#ifdef CONFIG_SMP
+static void free_masks(struct irq_desc *desc)
+{
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+	free_cpumask_var(desc->pending_mask);
+#endif
+	free_cpumask_var(desc->irq_data.affinity);
+}
+#else
+static inline void free_masks(struct irq_desc *desc) { }
+#endif
+
+static struct irq_desc *alloc_desc(int irq, int node)
+{
+	struct irq_desc *desc;
+	gfp_t gfp = GFP_KERNEL;
+
+	desc = kzalloc_node(sizeof(*desc), gfp, node);
+	if (!desc)
+		return NULL;
+	/* allocate based on nr_cpu_ids */
+	desc->kstat_irqs = kzalloc_node(nr_cpu_ids * sizeof(*desc->kstat_irqs),
+					 gfp, node);
+	if (!desc->kstat_irqs)
+		goto err_desc;
+
+	if (alloc_masks(desc, gfp, node))
+		goto err_kstat;
+
+	raw_spin_lock_init(&desc->lock);
+	lockdep_set_class(&desc->lock, &irq_desc_lock_class);
+
+	desc_set_defaults(irq, desc, node);
+
+	return desc;
+
+err_kstat:
+	kfree(desc->kstat_irqs);
+err_desc:
+	kfree(desc);
+	return NULL;
+}
+
+static void free_desc(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	unregister_irq_proc(irq, desc);
+
+	mutex_lock(&sparse_irq_lock);
+	delete_irq_desc(irq);
+	mutex_unlock(&sparse_irq_lock);
+
+	free_masks(desc);
+	kfree(desc->kstat_irqs);
+	kfree(desc);
+}
+
+static int alloc_descs(unsigned int start, unsigned int cnt, int node)
+{
+	struct irq_desc *desc;
+	int i;
+
+	for (i = 0; i < cnt; i++) {
+		desc = alloc_desc(start + i, node);
+		if (!desc)
+			goto err;
+		mutex_lock(&sparse_irq_lock);
+		irq_insert_desc(start + i, desc);
+		mutex_unlock(&sparse_irq_lock);
+	}
+	return start;
+
+err:
+	for (i--; i >= 0; i--)
+		free_desc(start + i);
+
+	mutex_lock(&sparse_irq_lock);
+	bitmap_clear(allocated_irqs, start, cnt);
+	mutex_unlock(&sparse_irq_lock);
+	return -ENOMEM;
+}
+
+struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
+{
+	int res = irq_alloc_descs(irq, irq, 1, node);
+
+	if (res == -EEXIST || res == irq)
+		return irq_to_desc(irq);
+	return NULL;
+}
+
+int __init early_irq_init(void)
+{
+	int i, initcnt, node = first_online_node;
+	struct irq_desc *desc;
+
+	init_irq_default_affinity();
+
+	/* Let arch update nr_irqs and return the nr of preallocated irqs */
+	initcnt = arch_probe_nr_irqs();
+	printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d %d\n", NR_IRQS, nr_irqs, initcnt);
+
+	for (i = 0; i < initcnt; i++) {
+		desc = alloc_desc(i, node);
+		set_bit(i, allocated_irqs);
+		irq_insert_desc(i, desc);
+	}
+	return arch_early_irq_init();
+}
+
+#else /* !CONFIG_SPARSE_IRQ */
+
+struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
+	[0 ... NR_IRQS-1] = {
+		.status		= IRQ_DEFAULT_INIT_FLAGS,
+		.handle_irq	= handle_bad_irq,
+		.depth		= 1,
+		.lock		= __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
+	}
+};
+
+static unsigned int kstat_irqs_all[NR_IRQS][NR_CPUS];
+int __init early_irq_init(void)
+{
+	int count, i, node = first_online_node;
+	struct irq_desc *desc;
+
+	init_irq_default_affinity();
+
+	printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);
+
+	desc = irq_desc;
+	count = ARRAY_SIZE(irq_desc);
+
+	for (i = 0; i < count; i++) {
+		desc[i].irq_data.irq = i;
+		desc[i].irq_data.chip = &no_irq_chip;
+		desc[i].kstat_irqs = kstat_irqs_all[i];
+		alloc_masks(desc + i, GFP_KERNEL, node);
+		desc_smp_init(desc + i, node);
+		lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
+	}
+	return arch_early_irq_init();
+}
+
+struct irq_desc *irq_to_desc(unsigned int irq)
+{
+	return (irq < NR_IRQS) ? irq_desc + irq : NULL;
+}
+
+struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
+{
+	return irq_to_desc(irq);
+}
+
+static void free_desc(unsigned int irq)
+{
+	dynamic_irq_cleanup(irq);
+}
+
+static inline int alloc_descs(unsigned int start, unsigned int cnt, int node)
+{
+	return start;
+}
+#endif /* !CONFIG_SPARSE_IRQ */
+
+/* Dynamic interrupt handling */
+
+/**
+ * irq_free_descs - free irq descriptors
+ * @from:	Start of descriptor range
+ * @cnt:	Number of consecutive irqs to free
+ */
+void irq_free_descs(unsigned int from, unsigned int cnt)
+{
+	int i;
+
+	if (from >= nr_irqs || (from + cnt) > nr_irqs)
+		return;
+
+	for (i = 0; i < cnt; i++)
+		free_desc(from + i);
+
+	mutex_lock(&sparse_irq_lock);
+	bitmap_clear(allocated_irqs, from, cnt);
+	mutex_unlock(&sparse_irq_lock);
+}
+
+/**
+ * irq_alloc_descs - allocate and initialize a range of irq descriptors
+ * @irq:	Allocate for specific irq number if irq >= 0
+ * @from:	Start the search from this irq number
+ * @cnt:	Number of consecutive irqs to allocate.
+ * @node:	Preferred node on which the irq descriptor should be allocated
+ *
+ * Returns the first irq number or error code
+ */
+int __ref
+irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
+{
+	int start, ret;
+
+	if (!cnt)
+		return -EINVAL;
+
+	mutex_lock(&sparse_irq_lock);
+
+	start = bitmap_find_next_zero_area(allocated_irqs, nr_irqs, from, cnt, 0);
+	ret = -EEXIST;
+	if (irq >=0 && start != irq)
+		goto err;
+
+	ret = -ENOMEM;
+	if (start >= nr_irqs)
+		goto err;
+
+	bitmap_set(allocated_irqs, start, cnt);
+	mutex_unlock(&sparse_irq_lock);
+	return alloc_descs(start, cnt, node);
+
+err:
+	mutex_unlock(&sparse_irq_lock);
+	return ret;
+}
+
+/**
+ * irq_reserve_irqs - mark irqs allocated
+ * @from:	mark from irq number
+ * @cnt:	number of irqs to mark
+ *
+ * Returns 0 on success or an appropriate error code
+ */
+int irq_reserve_irqs(unsigned int from, unsigned int cnt)
+{
+	unsigned int start;
+	int ret = 0;
+
+	if (!cnt || (from + cnt) > nr_irqs)
+		return -EINVAL;
+
+	mutex_lock(&sparse_irq_lock);
+	start = bitmap_find_next_zero_area(allocated_irqs, nr_irqs, from, cnt, 0);
+	if (start == from)
+		bitmap_set(allocated_irqs, start, cnt);
+	else
+		ret = -EEXIST;
+	mutex_unlock(&sparse_irq_lock);
+	return ret;
+}
+
+/**
+ * irq_get_next_irq - get next allocated irq number
+ * @offset:	where to start the search
+ *
+ * Returns next irq number after offset or nr_irqs if none is found.
+ */
+unsigned int irq_get_next_irq(unsigned int offset)
+{
+	return find_next_bit(allocated_irqs, nr_irqs, offset);
+}
+
+/**
+ * dynamic_irq_cleanup - cleanup a dynamically allocated irq
+ * @irq:	irq number to initialize
+ */
+void dynamic_irq_cleanup(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&desc->lock, flags);
+	desc_set_defaults(irq, desc, desc_node(desc));
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	return desc ? desc->kstat_irqs[cpu] : 0;
+}
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index c3003e9..644e8d5 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -73,8 +73,8 @@
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
-	if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip ||
-	    !desc->chip->set_affinity)
+	if (CHECK_IRQ_PER_CPU(desc->status) || !desc->irq_data.chip ||
+	    !desc->irq_data.chip->irq_set_affinity)
 		return 0;
 
 	return 1;
@@ -109,17 +109,18 @@
 int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_chip *chip = desc->irq_data.chip;
 	unsigned long flags;
 
-	if (!desc->chip->set_affinity)
+	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 (!desc->chip->set_affinity(irq, cpumask)) {
-			cpumask_copy(desc->affinity, cpumask);
+		if (!chip->irq_set_affinity(&desc->irq_data, cpumask, false)) {
+			cpumask_copy(desc->irq_data.affinity, cpumask);
 			irq_set_thread_affinity(desc);
 		}
 	}
@@ -128,8 +129,8 @@
 		cpumask_copy(desc->pending_mask, cpumask);
 	}
 #else
-	if (!desc->chip->set_affinity(irq, cpumask)) {
-		cpumask_copy(desc->affinity, cpumask);
+	if (!chip->irq_set_affinity(&desc->irq_data, cpumask, false)) {
+		cpumask_copy(desc->irq_data.affinity, cpumask);
 		irq_set_thread_affinity(desc);
 	}
 #endif
@@ -168,16 +169,16 @@
 	 * one of the targets is online.
 	 */
 	if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) {
-		if (cpumask_any_and(desc->affinity, cpu_online_mask)
+		if (cpumask_any_and(desc->irq_data.affinity, cpu_online_mask)
 		    < nr_cpu_ids)
 			goto set_affinity;
 		else
 			desc->status &= ~IRQ_AFFINITY_SET;
 	}
 
-	cpumask_and(desc->affinity, cpu_online_mask, irq_default_affinity);
+	cpumask_and(desc->irq_data.affinity, cpu_online_mask, irq_default_affinity);
 set_affinity:
-	desc->chip->set_affinity(irq, desc->affinity);
+	desc->irq_data.chip->irq_set_affinity(&desc->irq_data, desc->irq_data.affinity, false);
 
 	return 0;
 }
@@ -223,7 +224,7 @@
 
 	if (!desc->depth++) {
 		desc->status |= IRQ_DISABLED;
-		desc->chip->disable(irq);
+		desc->irq_data.chip->irq_disable(&desc->irq_data);
 	}
 }
 
@@ -246,11 +247,11 @@
 	if (!desc)
 		return;
 
-	chip_bus_lock(irq, desc);
+	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(irq, desc);
+	chip_bus_sync_unlock(desc);
 }
 EXPORT_SYMBOL(disable_irq_nosync);
 
@@ -313,7 +314,7 @@
  *	IRQ line is re-enabled.
  *
  *	This function may be called from IRQ context only when
- *	desc->chip->bus_lock and desc->chip->bus_sync_unlock are NULL !
+ *	desc->irq_data.chip->bus_lock and desc->chip->bus_sync_unlock are NULL !
  */
 void enable_irq(unsigned int irq)
 {
@@ -323,11 +324,11 @@
 	if (!desc)
 		return;
 
-	chip_bus_lock(irq, desc);
+	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(irq, desc);
+	chip_bus_sync_unlock(desc);
 }
 EXPORT_SYMBOL(enable_irq);
 
@@ -336,8 +337,8 @@
 	struct irq_desc *desc = irq_to_desc(irq);
 	int ret = -ENXIO;
 
-	if (desc->chip->set_wake)
-		ret = desc->chip->set_wake(irq, on);
+	if (desc->irq_data.chip->irq_set_wake)
+		ret = desc->irq_data.chip->irq_set_wake(&desc->irq_data, on);
 
 	return ret;
 }
@@ -429,12 +430,12 @@
 }
 
 int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
-		unsigned long flags)
+		      unsigned long flags)
 {
 	int ret;
-	struct irq_chip *chip = desc->chip;
+	struct irq_chip *chip = desc->irq_data.chip;
 
-	if (!chip || !chip->set_type) {
+	if (!chip || !chip->irq_set_type) {
 		/*
 		 * IRQF_TRIGGER_* but the PIC does not support multiple
 		 * flow-types?
@@ -445,11 +446,11 @@
 	}
 
 	/* caller masked out all except trigger mode flags */
-	ret = chip->set_type(irq, flags);
+	ret = chip->irq_set_type(&desc->irq_data, flags);
 
 	if (ret)
-		pr_err("setting trigger mode %d for irq %u failed (%pF)\n",
-				(int)flags, irq, chip->set_type);
+		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;
@@ -457,8 +458,8 @@
 		desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK);
 		desc->status |= flags;
 
-		if (chip != desc->chip)
-			irq_chip_set_defaults(desc->chip);
+		if (chip != desc->irq_data.chip)
+			irq_chip_set_defaults(desc->irq_data.chip);
 	}
 
 	return ret;
@@ -507,7 +508,7 @@
 static void irq_finalize_oneshot(unsigned int irq, struct irq_desc *desc)
 {
 again:
-	chip_bus_lock(irq, desc);
+	chip_bus_lock(desc);
 	raw_spin_lock_irq(&desc->lock);
 
 	/*
@@ -521,17 +522,17 @@
 	 */
 	if (unlikely(desc->status & IRQ_INPROGRESS)) {
 		raw_spin_unlock_irq(&desc->lock);
-		chip_bus_sync_unlock(irq, desc);
+		chip_bus_sync_unlock(desc);
 		cpu_relax();
 		goto again;
 	}
 
 	if (!(desc->status & IRQ_DISABLED) && (desc->status & IRQ_MASKED)) {
 		desc->status &= ~IRQ_MASKED;
-		desc->chip->unmask(irq);
+		desc->irq_data.chip->irq_unmask(&desc->irq_data);
 	}
 	raw_spin_unlock_irq(&desc->lock);
-	chip_bus_sync_unlock(irq, desc);
+	chip_bus_sync_unlock(desc);
 }
 
 #ifdef CONFIG_SMP
@@ -556,7 +557,7 @@
 	}
 
 	raw_spin_lock_irq(&desc->lock);
-	cpumask_copy(mask, desc->affinity);
+	cpumask_copy(mask, desc->irq_data.affinity);
 	raw_spin_unlock_irq(&desc->lock);
 
 	set_cpus_allowed_ptr(current, mask);
@@ -657,7 +658,7 @@
 	if (!desc)
 		return -EINVAL;
 
-	if (desc->chip == &no_irq_chip)
+	if (desc->irq_data.chip == &no_irq_chip)
 		return -ENOSYS;
 	/*
 	 * Some drivers like serial.c use request_irq() heavily,
@@ -752,7 +753,7 @@
 	}
 
 	if (!shared) {
-		irq_chip_set_defaults(desc->chip);
+		irq_chip_set_defaults(desc->irq_data.chip);
 
 		init_waitqueue_head(&desc->wait_for_threads);
 
@@ -779,7 +780,7 @@
 		if (!(desc->status & IRQ_NOAUTOEN)) {
 			desc->depth = 0;
 			desc->status &= ~IRQ_DISABLED;
-			desc->chip->startup(irq);
+			desc->irq_data.chip->irq_startup(&desc->irq_data);
 		} else
 			/* Undo nested disables: */
 			desc->depth = 1;
@@ -912,17 +913,17 @@
 
 	/* Currently used only by UML, might disappear one day: */
 #ifdef CONFIG_IRQ_RELEASE_METHOD
-	if (desc->chip->release)
-		desc->chip->release(irq, dev_id);
+	if (desc->irq_data.chip->release)
+		desc->irq_data.chip->release(irq, dev_id);
 #endif
 
 	/* If this was the last handler, shut down the IRQ line: */
 	if (!desc->action) {
 		desc->status |= IRQ_DISABLED;
-		if (desc->chip->shutdown)
-			desc->chip->shutdown(irq);
+		if (desc->irq_data.chip->irq_shutdown)
+			desc->irq_data.chip->irq_shutdown(&desc->irq_data);
 		else
-			desc->chip->disable(irq);
+			desc->irq_data.chip->irq_disable(&desc->irq_data);
 	}
 
 #ifdef CONFIG_SMP
@@ -997,9 +998,9 @@
 	if (!desc)
 		return;
 
-	chip_bus_lock(irq, desc);
+	chip_bus_lock(desc);
 	kfree(__free_irq(irq, dev_id));
-	chip_bus_sync_unlock(irq, desc);
+	chip_bus_sync_unlock(desc);
 }
 EXPORT_SYMBOL(free_irq);
 
@@ -1086,9 +1087,9 @@
 	action->name = devname;
 	action->dev_id = dev_id;
 
-	chip_bus_lock(irq, desc);
+	chip_bus_lock(desc);
 	retval = __setup_irq(irq, desc, action);
-	chip_bus_sync_unlock(irq, desc);
+	chip_bus_sync_unlock(desc);
 
 	if (retval)
 		kfree(action);
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index 2419622..1d25419 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -7,6 +7,7 @@
 void move_masked_irq(int irq)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_chip *chip = desc->irq_data.chip;
 
 	if (likely(!(desc->status & IRQ_MOVE_PENDING)))
 		return;
@@ -24,7 +25,7 @@
 	if (unlikely(cpumask_empty(desc->pending_mask)))
 		return;
 
-	if (!desc->chip->set_affinity)
+	if (!chip->irq_set_affinity)
 		return;
 
 	assert_raw_spin_locked(&desc->lock);
@@ -43,8 +44,9 @@
 	 */
 	if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
 		   < nr_cpu_ids))
-		if (!desc->chip->set_affinity(irq, desc->pending_mask)) {
-			cpumask_copy(desc->affinity, desc->pending_mask);
+		if (!chip->irq_set_affinity(&desc->irq_data,
+					    desc->pending_mask, false)) {
+			cpumask_copy(desc->irq_data.affinity, desc->pending_mask);
 			irq_set_thread_affinity(desc);
 		}
 
@@ -61,8 +63,8 @@
 	if (unlikely(desc->status & IRQ_DISABLED))
 		return;
 
-	desc->chip->mask(irq);
+	desc->irq_data.chip->irq_mask(&desc->irq_data);
 	move_masked_irq(irq);
-	desc->chip->unmask(irq);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c
deleted file mode 100644
index 65d3845..0000000
--- a/kernel/irq/numa_migrate.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * NUMA irq-desc migration code
- *
- * Migrate IRQ data structures (irq_desc, chip_data, etc.) over to
- * the new "home node" of the IRQ.
- */
-
-#include <linux/irq.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/random.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-
-#include "internals.h"
-
-static void init_copy_kstat_irqs(struct irq_desc *old_desc,
-				 struct irq_desc *desc,
-				 int node, int nr)
-{
-	init_kstat_irqs(desc, node, nr);
-
-	if (desc->kstat_irqs != old_desc->kstat_irqs)
-		memcpy(desc->kstat_irqs, old_desc->kstat_irqs,
-			 nr * sizeof(*desc->kstat_irqs));
-}
-
-static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc)
-{
-	if (old_desc->kstat_irqs == desc->kstat_irqs)
-		return;
-
-	kfree(old_desc->kstat_irqs);
-	old_desc->kstat_irqs = NULL;
-}
-
-static bool init_copy_one_irq_desc(int irq, struct irq_desc *old_desc,
-		 struct irq_desc *desc, int node)
-{
-	memcpy(desc, old_desc, sizeof(struct irq_desc));
-	if (!alloc_desc_masks(desc, node, false)) {
-		printk(KERN_ERR "irq %d: can not get new irq_desc cpumask "
-				"for migration.\n", irq);
-		return false;
-	}
-	raw_spin_lock_init(&desc->lock);
-	desc->node = node;
-	lockdep_set_class(&desc->lock, &irq_desc_lock_class);
-	init_copy_kstat_irqs(old_desc, desc, node, nr_cpu_ids);
-	init_copy_desc_masks(old_desc, desc);
-	arch_init_copy_chip_data(old_desc, desc, node);
-	return true;
-}
-
-static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc)
-{
-	free_kstat_irqs(old_desc, desc);
-	free_desc_masks(old_desc, desc);
-	arch_free_chip_data(old_desc, desc);
-}
-
-static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
-						int node)
-{
-	struct irq_desc *desc;
-	unsigned int irq;
-	unsigned long flags;
-
-	irq = old_desc->irq;
-
-	raw_spin_lock_irqsave(&sparse_irq_lock, flags);
-
-	/* We have to check it to avoid races with another CPU */
-	desc = irq_to_desc(irq);
-
-	if (desc && old_desc != desc)
-		goto out_unlock;
-
-	desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
-	if (!desc) {
-		printk(KERN_ERR "irq %d: can not get new irq_desc "
-				"for migration.\n", irq);
-		/* still use old one */
-		desc = old_desc;
-		goto out_unlock;
-	}
-	if (!init_copy_one_irq_desc(irq, old_desc, desc, node)) {
-		/* still use old one */
-		kfree(desc);
-		desc = old_desc;
-		goto out_unlock;
-	}
-
-	replace_irq_desc(irq, desc);
-	raw_spin_unlock_irqrestore(&sparse_irq_lock, flags);
-
-	/* free the old one */
-	free_one_irq_desc(old_desc, desc);
-	kfree(old_desc);
-
-	return desc;
-
-out_unlock:
-	raw_spin_unlock_irqrestore(&sparse_irq_lock, flags);
-
-	return desc;
-}
-
-struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
-{
-	/* those static or target node is -1, do not move them */
-	if (desc->irq < NR_IRQS_LEGACY || node == -1)
-		return desc;
-
-	if (desc->node != node)
-		desc = __real_move_irq_desc(desc, node);
-
-	return desc;
-}
-
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 09a2ee5..01b1d3a 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -21,7 +21,7 @@
 static int irq_affinity_proc_show(struct seq_file *m, void *v)
 {
 	struct irq_desc *desc = irq_to_desc((long)m->private);
-	const struct cpumask *mask = desc->affinity;
+	const struct cpumask *mask = desc->irq_data.affinity;
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 	if (desc->status & IRQ_MOVE_PENDING)
@@ -65,7 +65,7 @@
 	cpumask_var_t new_value;
 	int err;
 
-	if (!irq_to_desc(irq)->chip->set_affinity || no_irq_affinity ||
+	if (!irq_to_desc(irq)->irq_data.chip->irq_set_affinity || no_irq_affinity ||
 	    irq_balancing_disabled(irq))
 		return -EIO;
 
@@ -185,7 +185,7 @@
 {
 	struct irq_desc *desc = irq_to_desc((long) m->private);
 
-	seq_printf(m, "%d\n", desc->node);
+	seq_printf(m, "%d\n", desc->irq_data.node);
 	return 0;
 }
 
@@ -269,7 +269,7 @@
 {
 	char name [MAX_NAMELEN];
 
-	if (!root_irq_dir || (desc->chip == &no_irq_chip) || desc->dir)
+	if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip) || desc->dir)
 		return;
 
 	memset(name, 0, MAX_NAMELEN);
@@ -297,6 +297,24 @@
 			 &irq_spurious_proc_fops, (void *)(long)irq);
 }
 
+void unregister_irq_proc(unsigned int irq, struct irq_desc *desc)
+{
+	char name [MAX_NAMELEN];
+
+	if (!root_irq_dir || !desc->dir)
+		return;
+#ifdef CONFIG_SMP
+	remove_proc_entry("smp_affinity", desc->dir);
+	remove_proc_entry("affinity_hint", desc->dir);
+	remove_proc_entry("node", desc->dir);
+#endif
+	remove_proc_entry("spurious", desc->dir);
+
+	memset(name, 0, MAX_NAMELEN);
+	sprintf(name, "%u", irq);
+	remove_proc_entry(name, root_irq_dir);
+}
+
 #undef MAX_NAMELEN
 
 void unregister_handler_proc(unsigned int irq, struct irqaction *action)
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index 090c376..891115a 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -60,7 +60,7 @@
 	/*
 	 * Make sure the interrupt is enabled, before resending it:
 	 */
-	desc->chip->enable(irq);
+	desc->irq_data.chip->irq_enable(&desc->irq_data);
 
 	/*
 	 * We do not resend level type interrupts. Level type
@@ -70,7 +70,8 @@
 	if ((status & (IRQ_LEVEL | IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
 		desc->status = (status & ~IRQ_PENDING) | IRQ_REPLAY;
 
-		if (!desc->chip->retrigger || !desc->chip->retrigger(irq)) {
+		if (!desc->irq_data.chip->irq_retrigger ||
+		    !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) {
 #ifdef CONFIG_HARDIRQS_SW_RESEND
 			/* Set it pending and activate the softirq: */
 			set_bit(irq, irqs_resend);
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 89fb90a..3089d3b9 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -14,6 +14,8 @@
 #include <linux/moduleparam.h>
 #include <linux/timer.h>
 
+#include "internals.h"
+
 static int irqfixup __read_mostly;
 
 #define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10)
@@ -78,8 +80,8 @@
 	 * If we did actual work for the real IRQ line we must let the
 	 * IRQ controller clean up too
 	 */
-	if (work && desc->chip && desc->chip->end)
-		desc->chip->end(irq);
+	if (work)
+		irq_end(irq, desc);
 	raw_spin_unlock(&desc->lock);
 
 	return ok;
@@ -254,7 +256,7 @@
 		printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
 		desc->status |= IRQ_DISABLED | IRQ_SPURIOUS_DISABLED;
 		desc->depth++;
-		desc->chip->disable(irq);
+		desc->irq_data.chip->irq_disable(&desc->irq_data);
 
 		mod_timer(&poll_spurious_irq_timer,
 			  jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
new file mode 100644
index 0000000..f16763f
--- /dev/null
+++ b/kernel/irq_work.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *
+ * Provides a framework for enqueueing and running callbacks from hardirq
+ * context. The enqueueing is NMI-safe.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/irq_work.h>
+#include <linux/hardirq.h>
+
+/*
+ * An entry can be in one of four states:
+ *
+ * free	     NULL, 0 -> {claimed}       : free to be used
+ * claimed   NULL, 3 -> {pending}       : claimed to be enqueued
+ * pending   next, 3 -> {busy}          : queued, pending callback
+ * busy      NULL, 2 -> {free, claimed} : callback in progress, can be claimed
+ *
+ * We use the lower two bits of the next pointer to keep PENDING and BUSY
+ * flags.
+ */
+
+#define IRQ_WORK_PENDING	1UL
+#define IRQ_WORK_BUSY		2UL
+#define IRQ_WORK_FLAGS		3UL
+
+static inline bool irq_work_is_set(struct irq_work *entry, int flags)
+{
+	return (unsigned long)entry->next & flags;
+}
+
+static inline struct irq_work *irq_work_next(struct irq_work *entry)
+{
+	unsigned long next = (unsigned long)entry->next;
+	next &= ~IRQ_WORK_FLAGS;
+	return (struct irq_work *)next;
+}
+
+static inline struct irq_work *next_flags(struct irq_work *entry, int flags)
+{
+	unsigned long next = (unsigned long)entry;
+	next |= flags;
+	return (struct irq_work *)next;
+}
+
+static DEFINE_PER_CPU(struct irq_work *, irq_work_list);
+
+/*
+ * Claim the entry so that no one else will poke at it.
+ */
+static bool irq_work_claim(struct irq_work *entry)
+{
+	struct irq_work *next, *nflags;
+
+	do {
+		next = entry->next;
+		if ((unsigned long)next & IRQ_WORK_PENDING)
+			return false;
+		nflags = next_flags(next, IRQ_WORK_FLAGS);
+	} while (cmpxchg(&entry->next, next, nflags) != next);
+
+	return true;
+}
+
+
+void __weak arch_irq_work_raise(void)
+{
+	/*
+	 * Lame architectures will get the timer tick callback
+	 */
+}
+
+/*
+ * Queue the entry and raise the IPI if needed.
+ */
+static void __irq_work_queue(struct irq_work *entry)
+{
+	struct irq_work **head, *next;
+
+	head = &get_cpu_var(irq_work_list);
+
+	do {
+		next = *head;
+		/* Can assign non-atomic because we keep the flags set. */
+		entry->next = next_flags(next, IRQ_WORK_FLAGS);
+	} while (cmpxchg(head, next, entry) != next);
+
+	/* The list was empty, raise self-interrupt to start processing. */
+	if (!irq_work_next(entry))
+		arch_irq_work_raise();
+
+	put_cpu_var(irq_work_list);
+}
+
+/*
+ * Enqueue the irq_work @entry, returns true on success, failure when the
+ * @entry was already enqueued by someone else.
+ *
+ * Can be re-enqueued while the callback is still in progress.
+ */
+bool irq_work_queue(struct irq_work *entry)
+{
+	if (!irq_work_claim(entry)) {
+		/*
+		 * Already enqueued, can't do!
+		 */
+		return false;
+	}
+
+	__irq_work_queue(entry);
+	return true;
+}
+EXPORT_SYMBOL_GPL(irq_work_queue);
+
+/*
+ * Run the irq_work entries on this cpu. Requires to be ran from hardirq
+ * context with local IRQs disabled.
+ */
+void irq_work_run(void)
+{
+	struct irq_work *list, **head;
+
+	head = &__get_cpu_var(irq_work_list);
+	if (*head == NULL)
+		return;
+
+	BUG_ON(!in_irq());
+	BUG_ON(!irqs_disabled());
+
+	list = xchg(head, NULL);
+	while (list != NULL) {
+		struct irq_work *entry = list;
+
+		list = irq_work_next(list);
+
+		/*
+		 * Clear the PENDING bit, after this point the @entry
+		 * can be re-used.
+		 */
+		entry->next = next_flags(NULL, IRQ_WORK_BUSY);
+		entry->func(entry);
+		/*
+		 * Clear the BUSY bit and return to the free state if
+		 * no-one else claimed it meanwhile.
+		 */
+		cmpxchg(&entry->next, next_flags(NULL, IRQ_WORK_BUSY), NULL);
+	}
+}
+EXPORT_SYMBOL_GPL(irq_work_run);
+
+/*
+ * Synchronize against the irq_work @entry, ensures the entry is not
+ * currently in use.
+ */
+void irq_work_sync(struct irq_work *entry)
+{
+	WARN_ON_ONCE(irqs_disabled());
+
+	while (irq_work_is_set(entry, IRQ_WORK_BUSY))
+		cpu_relax();
+}
+EXPORT_SYMBOL_GPL(irq_work_sync);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
new file mode 100644
index 0000000..7be868b
--- /dev/null
+++ b/kernel/jump_label.c
@@ -0,0 +1,429 @@
+/*
+ * jump label support
+ *
+ * Copyright (C) 2009 Jason Baron <jbaron@redhat.com>
+ *
+ */
+#include <linux/jump_label.h>
+#include <linux/memory.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/jhash.h>
+#include <linux/slab.h>
+#include <linux/sort.h>
+#include <linux/err.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+#define JUMP_LABEL_HASH_BITS 6
+#define JUMP_LABEL_TABLE_SIZE (1 << JUMP_LABEL_HASH_BITS)
+static struct hlist_head jump_label_table[JUMP_LABEL_TABLE_SIZE];
+
+/* mutex to protect coming/going of the the jump_label table */
+static DEFINE_MUTEX(jump_label_mutex);
+
+struct jump_label_entry {
+	struct hlist_node hlist;
+	struct jump_entry *table;
+	int nr_entries;
+	/* hang modules off here */
+	struct hlist_head modules;
+	unsigned long key;
+};
+
+struct jump_label_module_entry {
+	struct hlist_node hlist;
+	struct jump_entry *table;
+	int nr_entries;
+	struct module *mod;
+};
+
+static int jump_label_cmp(const void *a, const void *b)
+{
+	const struct jump_entry *jea = a;
+	const struct jump_entry *jeb = b;
+
+	if (jea->key < jeb->key)
+		return -1;
+
+	if (jea->key > jeb->key)
+		return 1;
+
+	return 0;
+}
+
+static void
+sort_jump_label_entries(struct jump_entry *start, struct jump_entry *stop)
+{
+	unsigned long size;
+
+	size = (((unsigned long)stop - (unsigned long)start)
+					/ sizeof(struct jump_entry));
+	sort(start, size, sizeof(struct jump_entry), jump_label_cmp, NULL);
+}
+
+static struct jump_label_entry *get_jump_label_entry(jump_label_t key)
+{
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct jump_label_entry *e;
+	u32 hash = jhash((void *)&key, sizeof(jump_label_t), 0);
+
+	head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)];
+	hlist_for_each_entry(e, node, head, hlist) {
+		if (key == e->key)
+			return e;
+	}
+	return NULL;
+}
+
+static struct jump_label_entry *
+add_jump_label_entry(jump_label_t key, int nr_entries, struct jump_entry *table)
+{
+	struct hlist_head *head;
+	struct jump_label_entry *e;
+	u32 hash;
+
+	e = get_jump_label_entry(key);
+	if (e)
+		return ERR_PTR(-EEXIST);
+
+	e = kmalloc(sizeof(struct jump_label_entry), GFP_KERNEL);
+	if (!e)
+		return ERR_PTR(-ENOMEM);
+
+	hash = jhash((void *)&key, sizeof(jump_label_t), 0);
+	head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)];
+	e->key = key;
+	e->table = table;
+	e->nr_entries = nr_entries;
+	INIT_HLIST_HEAD(&(e->modules));
+	hlist_add_head(&e->hlist, head);
+	return e;
+}
+
+static int
+build_jump_label_hashtable(struct jump_entry *start, struct jump_entry *stop)
+{
+	struct jump_entry *iter, *iter_begin;
+	struct jump_label_entry *entry;
+	int count;
+
+	sort_jump_label_entries(start, stop);
+	iter = start;
+	while (iter < stop) {
+		entry = get_jump_label_entry(iter->key);
+		if (!entry) {
+			iter_begin = iter;
+			count = 0;
+			while ((iter < stop) &&
+				(iter->key == iter_begin->key)) {
+				iter++;
+				count++;
+			}
+			entry = add_jump_label_entry(iter_begin->key,
+							count, iter_begin);
+			if (IS_ERR(entry))
+				return PTR_ERR(entry);
+		 } else {
+			WARN_ONCE(1, KERN_ERR "build_jump_hashtable: unexpected entry!\n");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+/***
+ * jump_label_update - update jump label text
+ * @key -  key value associated with a a jump label
+ * @type - enum set to JUMP_LABEL_ENABLE or JUMP_LABEL_DISABLE
+ *
+ * Will enable/disable the jump for jump label @key, depending on the
+ * value of @type.
+ *
+ */
+
+void jump_label_update(unsigned long key, enum jump_label_type type)
+{
+	struct jump_entry *iter;
+	struct jump_label_entry *entry;
+	struct hlist_node *module_node;
+	struct jump_label_module_entry *e_module;
+	int count;
+
+	mutex_lock(&jump_label_mutex);
+	entry = get_jump_label_entry((jump_label_t)key);
+	if (entry) {
+		count = entry->nr_entries;
+		iter = entry->table;
+		while (count--) {
+			if (kernel_text_address(iter->code))
+				arch_jump_label_transform(iter, type);
+			iter++;
+		}
+		/* eanble/disable jump labels in modules */
+		hlist_for_each_entry(e_module, module_node, &(entry->modules),
+							hlist) {
+			count = e_module->nr_entries;
+			iter = e_module->table;
+			while (count--) {
+				if (kernel_text_address(iter->code))
+					arch_jump_label_transform(iter, type);
+				iter++;
+			}
+		}
+	}
+	mutex_unlock(&jump_label_mutex);
+}
+
+static int addr_conflict(struct jump_entry *entry, void *start, void *end)
+{
+	if (entry->code <= (unsigned long)end &&
+		entry->code + JUMP_LABEL_NOP_SIZE > (unsigned long)start)
+		return 1;
+
+	return 0;
+}
+
+#ifdef CONFIG_MODULES
+
+static int module_conflict(void *start, void *end)
+{
+	struct hlist_head *head;
+	struct hlist_node *node, *node_next, *module_node, *module_node_next;
+	struct jump_label_entry *e;
+	struct jump_label_module_entry *e_module;
+	struct jump_entry *iter;
+	int i, count;
+	int conflict = 0;
+
+	for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) {
+		head = &jump_label_table[i];
+		hlist_for_each_entry_safe(e, node, node_next, head, hlist) {
+			hlist_for_each_entry_safe(e_module, module_node,
+							module_node_next,
+							&(e->modules), hlist) {
+				count = e_module->nr_entries;
+				iter = e_module->table;
+				while (count--) {
+					if (addr_conflict(iter, start, end)) {
+						conflict = 1;
+						goto out;
+					}
+					iter++;
+				}
+			}
+		}
+	}
+out:
+	return conflict;
+}
+
+#endif
+
+/***
+ * jump_label_text_reserved - check if addr range is reserved
+ * @start: start text addr
+ * @end: end text addr
+ *
+ * checks if the text addr located between @start and @end
+ * overlaps with any of the jump label patch addresses. Code
+ * that wants to modify kernel text should first verify that
+ * it does not overlap with any of the jump label addresses.
+ *
+ * returns 1 if there is an overlap, 0 otherwise
+ */
+int jump_label_text_reserved(void *start, void *end)
+{
+	struct jump_entry *iter;
+	struct jump_entry *iter_start = __start___jump_table;
+	struct jump_entry *iter_stop = __start___jump_table;
+	int conflict = 0;
+
+	mutex_lock(&jump_label_mutex);
+	iter = iter_start;
+	while (iter < iter_stop) {
+		if (addr_conflict(iter, start, end)) {
+			conflict = 1;
+			goto out;
+		}
+		iter++;
+	}
+
+	/* now check modules */
+#ifdef CONFIG_MODULES
+	conflict = module_conflict(start, end);
+#endif
+out:
+	mutex_unlock(&jump_label_mutex);
+	return conflict;
+}
+
+static __init int init_jump_label(void)
+{
+	int ret;
+	struct jump_entry *iter_start = __start___jump_table;
+	struct jump_entry *iter_stop = __stop___jump_table;
+	struct jump_entry *iter;
+
+	mutex_lock(&jump_label_mutex);
+	ret = build_jump_label_hashtable(__start___jump_table,
+					 __stop___jump_table);
+	iter = iter_start;
+	while (iter < iter_stop) {
+		arch_jump_label_text_poke_early(iter->code);
+		iter++;
+	}
+	mutex_unlock(&jump_label_mutex);
+	return ret;
+}
+early_initcall(init_jump_label);
+
+#ifdef CONFIG_MODULES
+
+static struct jump_label_module_entry *
+add_jump_label_module_entry(struct jump_label_entry *entry,
+			    struct jump_entry *iter_begin,
+			    int count, struct module *mod)
+{
+	struct jump_label_module_entry *e;
+
+	e = kmalloc(sizeof(struct jump_label_module_entry), GFP_KERNEL);
+	if (!e)
+		return ERR_PTR(-ENOMEM);
+	e->mod = mod;
+	e->nr_entries = count;
+	e->table = iter_begin;
+	hlist_add_head(&e->hlist, &entry->modules);
+	return e;
+}
+
+static int add_jump_label_module(struct module *mod)
+{
+	struct jump_entry *iter, *iter_begin;
+	struct jump_label_entry *entry;
+	struct jump_label_module_entry *module_entry;
+	int count;
+
+	/* if the module doesn't have jump label entries, just return */
+	if (!mod->num_jump_entries)
+		return 0;
+
+	sort_jump_label_entries(mod->jump_entries,
+				mod->jump_entries + mod->num_jump_entries);
+	iter = mod->jump_entries;
+	while (iter < mod->jump_entries + mod->num_jump_entries) {
+		entry = get_jump_label_entry(iter->key);
+		iter_begin = iter;
+		count = 0;
+		while ((iter < mod->jump_entries + mod->num_jump_entries) &&
+			(iter->key == iter_begin->key)) {
+				iter++;
+				count++;
+		}
+		if (!entry) {
+			entry = add_jump_label_entry(iter_begin->key, 0, NULL);
+			if (IS_ERR(entry))
+				return PTR_ERR(entry);
+		}
+		module_entry = add_jump_label_module_entry(entry, iter_begin,
+							   count, mod);
+		if (IS_ERR(module_entry))
+			return PTR_ERR(module_entry);
+	}
+	return 0;
+}
+
+static void remove_jump_label_module(struct module *mod)
+{
+	struct hlist_head *head;
+	struct hlist_node *node, *node_next, *module_node, *module_node_next;
+	struct jump_label_entry *e;
+	struct jump_label_module_entry *e_module;
+	int i;
+
+	/* if the module doesn't have jump label entries, just return */
+	if (!mod->num_jump_entries)
+		return;
+
+	for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) {
+		head = &jump_label_table[i];
+		hlist_for_each_entry_safe(e, node, node_next, head, hlist) {
+			hlist_for_each_entry_safe(e_module, module_node,
+						  module_node_next,
+						  &(e->modules), hlist) {
+				if (e_module->mod == mod) {
+					hlist_del(&e_module->hlist);
+					kfree(e_module);
+				}
+			}
+			if (hlist_empty(&e->modules) && (e->nr_entries == 0)) {
+				hlist_del(&e->hlist);
+				kfree(e);
+			}
+		}
+	}
+}
+
+static int
+jump_label_module_notify(struct notifier_block *self, unsigned long val,
+			 void *data)
+{
+	struct module *mod = data;
+	int ret = 0;
+
+	switch (val) {
+	case MODULE_STATE_COMING:
+		mutex_lock(&jump_label_mutex);
+		ret = add_jump_label_module(mod);
+		if (ret)
+			remove_jump_label_module(mod);
+		mutex_unlock(&jump_label_mutex);
+		break;
+	case MODULE_STATE_GOING:
+		mutex_lock(&jump_label_mutex);
+		remove_jump_label_module(mod);
+		mutex_unlock(&jump_label_mutex);
+		break;
+	}
+	return ret;
+}
+
+/***
+ * apply_jump_label_nops - patch module jump labels with arch_get_jump_label_nop()
+ * @mod: module to patch
+ *
+ * Allow for run-time selection of the optimal nops. Before the module
+ * loads patch these with arch_get_jump_label_nop(), which is specified by
+ * the arch specific jump label code.
+ */
+void jump_label_apply_nops(struct module *mod)
+{
+	struct jump_entry *iter;
+
+	/* if the module doesn't have jump label entries, just return */
+	if (!mod->num_jump_entries)
+		return;
+
+	iter = mod->jump_entries;
+	while (iter < mod->jump_entries + mod->num_jump_entries) {
+		arch_jump_label_text_poke_early(iter->code);
+		iter++;
+	}
+}
+
+struct notifier_block jump_label_module_nb = {
+	.notifier_call = jump_label_module_notify,
+	.priority = 0,
+};
+
+static __init int init_jump_label_module(void)
+{
+	return register_module_notifier(&jump_label_module_nb);
+}
+early_initcall(init_jump_label_module);
+
+#endif /* CONFIG_MODULES */
+
+#endif
diff --git a/kernel/kfifo.c b/kernel/kfifo.c
index 6b5580c..01a0700 100644
--- a/kernel/kfifo.c
+++ b/kernel/kfifo.c
@@ -365,8 +365,6 @@
 	n = setup_sgl_buf(sgl, fifo->data + off, nents, l);
 	n += setup_sgl_buf(sgl + n, fifo->data, nents - n, len - l);
 
-	if (n)
-		sg_mark_end(sgl + n - 1);
 	return n;
 }
 
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 282035f..56a8919 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -47,6 +47,7 @@
 #include <linux/memory.h>
 #include <linux/ftrace.h>
 #include <linux/cpu.h>
+#include <linux/jump_label.h>
 
 #include <asm-generic/sections.h>
 #include <asm/cacheflush.h>
@@ -399,7 +400,7 @@
  * Return an optimized kprobe whose optimizing code replaces
  * instructions including addr (exclude breakpoint).
  */
-struct kprobe *__kprobes get_optimized_kprobe(unsigned long addr)
+static struct kprobe *__kprobes get_optimized_kprobe(unsigned long addr)
 {
 	int i;
 	struct kprobe *p = NULL;
@@ -831,6 +832,7 @@
 
 void __kprobes kretprobe_hash_lock(struct task_struct *tsk,
 			 struct hlist_head **head, unsigned long *flags)
+__acquires(hlist_lock)
 {
 	unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS);
 	spinlock_t *hlist_lock;
@@ -842,6 +844,7 @@
 
 static void __kprobes kretprobe_table_lock(unsigned long hash,
 	unsigned long *flags)
+__acquires(hlist_lock)
 {
 	spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
 	spin_lock_irqsave(hlist_lock, *flags);
@@ -849,6 +852,7 @@
 
 void __kprobes kretprobe_hash_unlock(struct task_struct *tsk,
 	unsigned long *flags)
+__releases(hlist_lock)
 {
 	unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS);
 	spinlock_t *hlist_lock;
@@ -857,7 +861,9 @@
 	spin_unlock_irqrestore(hlist_lock, *flags);
 }
 
-void __kprobes kretprobe_table_unlock(unsigned long hash, unsigned long *flags)
+static void __kprobes kretprobe_table_unlock(unsigned long hash,
+       unsigned long *flags)
+__releases(hlist_lock)
 {
 	spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
 	spin_unlock_irqrestore(hlist_lock, *flags);
@@ -1141,7 +1147,8 @@
 	preempt_disable();
 	if (!kernel_text_address((unsigned long) p->addr) ||
 	    in_kprobes_functions((unsigned long) p->addr) ||
-	    ftrace_text_reserved(p->addr, p->addr)) {
+	    ftrace_text_reserved(p->addr, p->addr) ||
+	    jump_label_text_reserved(p->addr, p->addr)) {
 		preempt_enable();
 		return -EINVAL;
 	}
@@ -1339,18 +1346,19 @@
 	if (num <= 0)
 		return -EINVAL;
 	for (i = 0; i < num; i++) {
-		unsigned long addr;
+		unsigned long addr, offset;
 		jp = jps[i];
 		addr = arch_deref_entry_point(jp->entry);
 
-		if (!kernel_text_address(addr))
-			ret = -EINVAL;
-		else {
-			/* Todo: Verify probepoint is a function entry point */
+		/* Verify probepoint is a function entry point */
+		if (kallsyms_lookup_size_offset(addr, NULL, &offset) &&
+		    offset == 0) {
 			jp->kp.pre_handler = setjmp_pre_handler;
 			jp->kp.break_handler = longjmp_break_handler;
 			ret = register_kprobe(&jp->kp);
-		}
+		} else
+			ret = -EINVAL;
+
 		if (ret < 0) {
 			if (i > 0)
 				unregister_jprobes(jps, i);
@@ -1992,6 +2000,7 @@
 static const struct file_operations fops_kp = {
 	.read =         read_enabled_file_bool,
 	.write =        write_enabled_file_bool,
+	.llseek =	default_llseek,
 };
 
 static int __kprobes debugfs_kprobe_init(void)
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index f2852a5..42ba65d 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -639,6 +639,16 @@
 	}
 #endif
 
+	if (unlikely(subclass >= MAX_LOCKDEP_SUBCLASSES)) {
+		debug_locks_off();
+		printk(KERN_ERR
+			"BUG: looking up invalid subclass: %u\n", subclass);
+		printk(KERN_ERR
+			"turning off the locking correctness validator.\n");
+		dump_stack();
+		return NULL;
+	}
+
 	/*
 	 * Static locks do not have their class-keys yet - for them the key
 	 * is the lock object itself:
@@ -774,7 +784,9 @@
 	raw_local_irq_restore(flags);
 
 	if (!subclass || force)
-		lock->class_cache = class;
+		lock->class_cache[0] = class;
+	else if (subclass < NR_LOCKDEP_CACHING_CLASSES)
+		lock->class_cache[subclass] = class;
 
 	if (DEBUG_LOCKS_WARN_ON(class->subclass != subclass))
 		return NULL;
@@ -2679,7 +2691,11 @@
 void lockdep_init_map(struct lockdep_map *lock, const char *name,
 		      struct lock_class_key *key, int subclass)
 {
-	lock->class_cache = NULL;
+	int i;
+
+	for (i = 0; i < NR_LOCKDEP_CACHING_CLASSES; i++)
+		lock->class_cache[i] = NULL;
+
 #ifdef CONFIG_LOCK_STAT
 	lock->cpu = raw_smp_processor_id();
 #endif
@@ -2739,21 +2755,13 @@
 	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
 		return 0;
 
-	if (unlikely(subclass >= MAX_LOCKDEP_SUBCLASSES)) {
-		debug_locks_off();
-		printk("BUG: MAX_LOCKDEP_SUBCLASSES too low!\n");
-		printk("turning off the locking correctness validator.\n");
-		dump_stack();
-		return 0;
-	}
-
 	if (lock->key == &__lockdep_no_validate__)
 		check = 1;
 
-	if (!subclass)
-		class = lock->class_cache;
+	if (subclass < NR_LOCKDEP_CACHING_CLASSES)
+		class = lock->class_cache[subclass];
 	/*
-	 * Not cached yet or subclass?
+	 * Not cached?
 	 */
 	if (unlikely(!class)) {
 		class = register_lock_class(lock, subclass, 0);
@@ -2918,7 +2926,7 @@
 		return 1;
 
 	if (hlock->references) {
-		struct lock_class *class = lock->class_cache;
+		struct lock_class *class = lock->class_cache[0];
 
 		if (!class)
 			class = look_up_lock_class(lock, 0);
@@ -3559,7 +3567,12 @@
 		if (list_empty(head))
 			continue;
 		list_for_each_entry_safe(class, next, head, hash_entry) {
-			if (unlikely(class == lock->class_cache)) {
+			int match = 0;
+
+			for (j = 0; j < NR_LOCKDEP_CACHING_CLASSES; j++)
+				match |= class == lock->class_cache[j];
+
+			if (unlikely(match)) {
 				if (debug_locks_off_graph_unlock())
 					WARN_ON(1);
 				goto out_restore;
@@ -3775,7 +3788,7 @@
  * Careful: only use this function if you are sure that
  * the task cannot run in parallel!
  */
-void __debug_show_held_locks(struct task_struct *task)
+void debug_show_held_locks(struct task_struct *task)
 {
 	if (unlikely(!debug_locks)) {
 		printk("INFO: lockdep is turned off.\n");
@@ -3783,12 +3796,6 @@
 	}
 	lockdep_print_held_locks(task);
 }
-EXPORT_SYMBOL_GPL(__debug_show_held_locks);
-
-void debug_show_held_locks(struct task_struct *task)
-{
-		__debug_show_held_locks(task);
-}
 EXPORT_SYMBOL_GPL(debug_show_held_locks);
 
 void lockdep_sys_exit(void)
diff --git a/kernel/module.c b/kernel/module.c
index d0b5f8d..2df4630 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -55,6 +55,7 @@
 #include <linux/async.h>
 #include <linux/percpu.h>
 #include <linux/kmemleak.h>
+#include <linux/jump_label.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/module.h>
@@ -1537,6 +1538,7 @@
 {
 	struct module *mod = _mod;
 	list_del(&mod->list);
+	module_bug_cleanup(mod);
 	return 0;
 }
 
@@ -2308,6 +2310,11 @@
 					sizeof(*mod->tracepoints),
 					&mod->num_tracepoints);
 #endif
+#ifdef HAVE_JUMP_LABEL
+	mod->jump_entries = section_objs(info, "__jump_table",
+					sizeof(*mod->jump_entries),
+					&mod->num_jump_entries);
+#endif
 #ifdef CONFIG_EVENT_TRACING
 	mod->trace_events = section_objs(info, "_ftrace_events",
 					 sizeof(*mod->trace_events),
@@ -2625,6 +2632,7 @@
 	if (err < 0)
 		goto ddebug;
 
+	module_bug_finalize(info.hdr, info.sechdrs, mod);
 	list_add_rcu(&mod->list, &modules);
 	mutex_unlock(&module_mutex);
 
@@ -2650,6 +2658,8 @@
 	mutex_lock(&module_mutex);
 	/* Unlink carefully: kallsyms could be walking list. */
 	list_del_rcu(&mod->list);
+	module_bug_cleanup(mod);
+
  ddebug:
 	if (!mod->taints)
 		dynamic_debug_remove(info.debug);
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index db5b560..f309e80 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -31,24 +31,18 @@
 #include <linux/kernel_stat.h>
 #include <linux/perf_event.h>
 #include <linux/ftrace_event.h>
-#include <linux/hw_breakpoint.h>
 
 #include <asm/irq_regs.h>
 
-/*
- * Each CPU has a list of per CPU events:
- */
-static DEFINE_PER_CPU(struct perf_cpu_context, perf_cpu_context);
-
-int perf_max_events __read_mostly = 1;
-static int perf_reserved_percpu __read_mostly;
-static int perf_overcommit __read_mostly = 1;
-
-static atomic_t nr_events __read_mostly;
+atomic_t perf_task_events __read_mostly;
 static atomic_t nr_mmap_events __read_mostly;
 static atomic_t nr_comm_events __read_mostly;
 static atomic_t nr_task_events __read_mostly;
 
+static LIST_HEAD(pmus);
+static DEFINE_MUTEX(pmus_lock);
+static struct srcu_struct pmus_srcu;
+
 /*
  * perf event paranoia level:
  *  -1 - not paranoid at all
@@ -67,36 +61,43 @@
 
 static atomic64_t perf_event_id;
 
-/*
- * Lock for (sysadmin-configurable) event reservations:
- */
-static DEFINE_SPINLOCK(perf_resource_lock);
-
-/*
- * Architecture provided APIs - weak aliases:
- */
-extern __weak const struct pmu *hw_perf_event_init(struct perf_event *event)
-{
-	return NULL;
-}
-
-void __weak hw_perf_disable(void)		{ barrier(); }
-void __weak hw_perf_enable(void)		{ barrier(); }
-
 void __weak perf_event_print_debug(void)	{ }
 
-static DEFINE_PER_CPU(int, perf_disable_count);
-
-void perf_disable(void)
+extern __weak const char *perf_pmu_name(void)
 {
-	if (!__get_cpu_var(perf_disable_count)++)
-		hw_perf_disable();
+	return "pmu";
 }
 
-void perf_enable(void)
+void perf_pmu_disable(struct pmu *pmu)
 {
-	if (!--__get_cpu_var(perf_disable_count))
-		hw_perf_enable();
+	int *count = this_cpu_ptr(pmu->pmu_disable_count);
+	if (!(*count)++)
+		pmu->pmu_disable(pmu);
+}
+
+void perf_pmu_enable(struct pmu *pmu)
+{
+	int *count = this_cpu_ptr(pmu->pmu_disable_count);
+	if (!--(*count))
+		pmu->pmu_enable(pmu);
+}
+
+static DEFINE_PER_CPU(struct list_head, rotation_list);
+
+/*
+ * perf_pmu_rotate_start() and perf_rotate_context() are fully serialized
+ * because they're strictly cpu affine and rotate_start is called with IRQs
+ * disabled, while rotate_context is called from IRQ context.
+ */
+static void perf_pmu_rotate_start(struct pmu *pmu)
+{
+	struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
+	struct list_head *head = &__get_cpu_var(rotation_list);
+
+	WARN_ON(!irqs_disabled());
+
+	if (list_empty(&cpuctx->rotation_list))
+		list_add(&cpuctx->rotation_list, head);
 }
 
 static void get_ctx(struct perf_event_context *ctx)
@@ -151,13 +152,13 @@
  * the context could get moved to another task.
  */
 static struct perf_event_context *
-perf_lock_task_context(struct task_struct *task, unsigned long *flags)
+perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags)
 {
 	struct perf_event_context *ctx;
 
 	rcu_read_lock();
- retry:
-	ctx = rcu_dereference(task->perf_event_ctxp);
+retry:
+	ctx = rcu_dereference(task->perf_event_ctxp[ctxn]);
 	if (ctx) {
 		/*
 		 * If this context is a clone of another, it might
@@ -170,7 +171,7 @@
 		 * can't get swapped on us any more.
 		 */
 		raw_spin_lock_irqsave(&ctx->lock, *flags);
-		if (ctx != rcu_dereference(task->perf_event_ctxp)) {
+		if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) {
 			raw_spin_unlock_irqrestore(&ctx->lock, *flags);
 			goto retry;
 		}
@@ -189,12 +190,13 @@
  * can't get swapped to another task.  This also increments its
  * reference count so that the context can't get freed.
  */
-static struct perf_event_context *perf_pin_task_context(struct task_struct *task)
+static struct perf_event_context *
+perf_pin_task_context(struct task_struct *task, int ctxn)
 {
 	struct perf_event_context *ctx;
 	unsigned long flags;
 
-	ctx = perf_lock_task_context(task, &flags);
+	ctx = perf_lock_task_context(task, ctxn, &flags);
 	if (ctx) {
 		++ctx->pin_count;
 		raw_spin_unlock_irqrestore(&ctx->lock, flags);
@@ -302,6 +304,8 @@
 	}
 
 	list_add_rcu(&event->event_entry, &ctx->event_list);
+	if (!ctx->nr_events)
+		perf_pmu_rotate_start(ctx->pmu);
 	ctx->nr_events++;
 	if (event->attr.inherit_stat)
 		ctx->nr_stat++;
@@ -311,7 +315,12 @@
 {
 	struct perf_event *group_leader = event->group_leader;
 
-	WARN_ON_ONCE(event->attach_state & PERF_ATTACH_GROUP);
+	/*
+	 * We can have double attach due to group movement in perf_event_open.
+	 */
+	if (event->attach_state & PERF_ATTACH_GROUP)
+		return;
+
 	event->attach_state |= PERF_ATTACH_GROUP;
 
 	if (group_leader == event)
@@ -408,8 +417,8 @@
 	return event->cpu == -1 || event->cpu == smp_processor_id();
 }
 
-static void
-event_sched_out(struct perf_event *event,
+static int
+__event_sched_out(struct perf_event *event,
 		  struct perf_cpu_context *cpuctx,
 		  struct perf_event_context *ctx)
 {
@@ -428,15 +437,14 @@
 	}
 
 	if (event->state != PERF_EVENT_STATE_ACTIVE)
-		return;
+		return 0;
 
 	event->state = PERF_EVENT_STATE_INACTIVE;
 	if (event->pending_disable) {
 		event->pending_disable = 0;
 		event->state = PERF_EVENT_STATE_OFF;
 	}
-	event->tstamp_stopped = ctx->time;
-	event->pmu->disable(event);
+	event->pmu->del(event, 0);
 	event->oncpu = -1;
 
 	if (!is_software_event(event))
@@ -444,6 +452,19 @@
 	ctx->nr_active--;
 	if (event->attr.exclusive || !cpuctx->active_oncpu)
 		cpuctx->exclusive = 0;
+	return 1;
+}
+
+static void
+event_sched_out(struct perf_event *event,
+		  struct perf_cpu_context *cpuctx,
+		  struct perf_event_context *ctx)
+{
+	int ret;
+
+	ret = __event_sched_out(event, cpuctx, ctx);
+	if (ret)
+		event->tstamp_stopped = ctx->time;
 }
 
 static void
@@ -466,6 +487,12 @@
 		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
  *
@@ -474,9 +501,9 @@
  */
 static void __perf_event_remove_from_context(void *info)
 {
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
 	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
@@ -487,27 +514,11 @@
 		return;
 
 	raw_spin_lock(&ctx->lock);
-	/*
-	 * Protect the list operation against NMI by disabling the
-	 * events on a global level.
-	 */
-	perf_disable();
 
 	event_sched_out(event, cpuctx, ctx);
 
 	list_del_event(event, ctx);
 
-	if (!ctx->task) {
-		/*
-		 * Allow more per task events with respect to the
-		 * reservation:
-		 */
-		cpuctx->max_pertask =
-			min(perf_max_events - ctx->nr_events,
-			    perf_max_events - perf_reserved_percpu);
-	}
-
-	perf_enable();
 	raw_spin_unlock(&ctx->lock);
 }
 
@@ -572,8 +583,8 @@
 static void __perf_event_disable(void *info)
 {
 	struct perf_event *event = info;
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
 	struct perf_event_context *ctx = event->ctx;
+	struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 
 	/*
 	 * If this is a per-task event, need to check whether this
@@ -628,7 +639,7 @@
 		return;
 	}
 
- retry:
+retry:
 	task_oncpu_function_call(task, __perf_event_disable, event);
 
 	raw_spin_lock_irq(&ctx->lock);
@@ -653,7 +664,7 @@
 }
 
 static int
-event_sched_in(struct perf_event *event,
+__event_sched_in(struct perf_event *event,
 		 struct perf_cpu_context *cpuctx,
 		 struct perf_event_context *ctx)
 {
@@ -667,14 +678,12 @@
 	 */
 	smp_wmb();
 
-	if (event->pmu->enable(event)) {
+	if (event->pmu->add(event, PERF_EF_START)) {
 		event->state = PERF_EVENT_STATE_INACTIVE;
 		event->oncpu = -1;
 		return -EAGAIN;
 	}
 
-	event->tstamp_running += ctx->time - event->tstamp_stopped;
-
 	if (!is_software_event(event))
 		cpuctx->active_oncpu++;
 	ctx->nr_active++;
@@ -685,28 +694,56 @@
 	return 0;
 }
 
+static inline int
+event_sched_in(struct perf_event *event,
+		 struct perf_cpu_context *cpuctx,
+		 struct perf_event_context *ctx)
+{
+	int ret = __event_sched_in(event, cpuctx, ctx);
+	if (ret)
+		return ret;
+	event->tstamp_running += ctx->time - event->tstamp_stopped;
+	return 0;
+}
+
+static void
+group_commit_event_sched_in(struct perf_event *group_event,
+	       struct perf_cpu_context *cpuctx,
+	       struct perf_event_context *ctx)
+{
+	struct perf_event *event;
+	u64 now = ctx->time;
+
+	group_event->tstamp_running += now - group_event->tstamp_stopped;
+	/*
+	 * Schedule in siblings as one group (if any):
+	 */
+	list_for_each_entry(event, &group_event->sibling_list, group_entry) {
+		event->tstamp_running += now - event->tstamp_stopped;
+	}
+}
+
 static int
 group_sched_in(struct perf_event *group_event,
 	       struct perf_cpu_context *cpuctx,
 	       struct perf_event_context *ctx)
 {
 	struct perf_event *event, *partial_group = NULL;
-	const struct pmu *pmu = group_event->pmu;
-	bool txn = false;
+	struct pmu *pmu = group_event->pmu;
 
 	if (group_event->state == PERF_EVENT_STATE_OFF)
 		return 0;
 
-	/* Check if group transaction availabe */
-	if (pmu->start_txn)
-		txn = true;
+	pmu->start_txn(pmu);
 
-	if (txn)
-		pmu->start_txn(pmu);
-
-	if (event_sched_in(group_event, cpuctx, ctx)) {
-		if (txn)
-			pmu->cancel_txn(pmu);
+	/*
+	 * use __event_sched_in() to delay updating tstamp_running
+	 * until the transaction is committed. In case of failure
+	 * we will keep an unmodified tstamp_running which is a
+	 * requirement to get correct timing information
+	 */
+	if (__event_sched_in(group_event, cpuctx, ctx)) {
+		pmu->cancel_txn(pmu);
 		return -EAGAIN;
 	}
 
@@ -714,29 +751,33 @@
 	 * Schedule in siblings as one group (if any):
 	 */
 	list_for_each_entry(event, &group_event->sibling_list, group_entry) {
-		if (event_sched_in(event, cpuctx, ctx)) {
+		if (__event_sched_in(event, cpuctx, ctx)) {
 			partial_group = event;
 			goto group_error;
 		}
 	}
 
-	if (!txn || !pmu->commit_txn(pmu))
+	if (!pmu->commit_txn(pmu)) {
+		/* commit tstamp_running */
+		group_commit_event_sched_in(group_event, cpuctx, ctx);
 		return 0;
-
+	}
 group_error:
 	/*
 	 * Groups can be scheduled in as one unit only, so undo any
 	 * partial group before returning:
+	 *
+	 * use __event_sched_out() to avoid updating tstamp_stopped
+	 * because the event never actually ran
 	 */
 	list_for_each_entry(event, &group_event->sibling_list, group_entry) {
 		if (event == partial_group)
 			break;
-		event_sched_out(event, cpuctx, ctx);
+		__event_sched_out(event, cpuctx, ctx);
 	}
-	event_sched_out(group_event, cpuctx, ctx);
+	__event_sched_out(group_event, cpuctx, ctx);
 
-	if (txn)
-		pmu->cancel_txn(pmu);
+	pmu->cancel_txn(pmu);
 
 	return -EAGAIN;
 }
@@ -789,10 +830,10 @@
  */
 static void __perf_install_in_context(void *info)
 {
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
 	struct perf_event *event = info;
 	struct perf_event_context *ctx = event->ctx;
 	struct perf_event *leader = event->group_leader;
+	struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 	int err;
 
 	/*
@@ -812,12 +853,6 @@
 	ctx->is_active = 1;
 	update_context_time(ctx);
 
-	/*
-	 * Protect the list operation against NMI by disabling the
-	 * events on a global level. NOP for non NMI based events.
-	 */
-	perf_disable();
-
 	add_event_to_ctx(event, ctx);
 
 	if (event->cpu != -1 && event->cpu != smp_processor_id())
@@ -855,12 +890,7 @@
 		}
 	}
 
-	if (!err && !ctx->task && cpuctx->max_pertask)
-		cpuctx->max_pertask--;
-
- unlock:
-	perf_enable();
-
+unlock:
 	raw_spin_unlock(&ctx->lock);
 }
 
@@ -883,6 +913,8 @@
 {
 	struct task_struct *task = ctx->task;
 
+	event->ctx = ctx;
+
 	if (!task) {
 		/*
 		 * Per cpu events are installed via an smp call and
@@ -931,10 +963,12 @@
 
 	event->state = PERF_EVENT_STATE_INACTIVE;
 	event->tstamp_enabled = ctx->time - event->total_time_enabled;
-	list_for_each_entry(sub, &event->sibling_list, group_entry)
-		if (sub->state >= PERF_EVENT_STATE_INACTIVE)
+	list_for_each_entry(sub, &event->sibling_list, group_entry) {
+		if (sub->state >= PERF_EVENT_STATE_INACTIVE) {
 			sub->tstamp_enabled =
 				ctx->time - sub->total_time_enabled;
+		}
+	}
 }
 
 /*
@@ -943,9 +977,9 @@
 static void __perf_event_enable(void *info)
 {
 	struct perf_event *event = info;
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
 	struct perf_event_context *ctx = event->ctx;
 	struct perf_event *leader = event->group_leader;
+	struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 	int err;
 
 	/*
@@ -979,12 +1013,10 @@
 	if (!group_can_go_on(event, cpuctx, 1)) {
 		err = -EEXIST;
 	} else {
-		perf_disable();
 		if (event == leader)
 			err = group_sched_in(event, cpuctx, ctx);
 		else
 			err = event_sched_in(event, cpuctx, ctx);
-		perf_enable();
 	}
 
 	if (err) {
@@ -1000,7 +1032,7 @@
 		}
 	}
 
- unlock:
+unlock:
 	raw_spin_unlock(&ctx->lock);
 }
 
@@ -1041,7 +1073,7 @@
 	if (event->state == PERF_EVENT_STATE_ERROR)
 		event->state = PERF_EVENT_STATE_OFF;
 
- retry:
+retry:
 	raw_spin_unlock_irq(&ctx->lock);
 	task_oncpu_function_call(task, __perf_event_enable, event);
 
@@ -1061,7 +1093,7 @@
 	if (event->state == PERF_EVENT_STATE_OFF)
 		__perf_event_mark_enabled(event, ctx);
 
- out:
+out:
 	raw_spin_unlock_irq(&ctx->lock);
 }
 
@@ -1092,26 +1124,26 @@
 	struct perf_event *event;
 
 	raw_spin_lock(&ctx->lock);
+	perf_pmu_disable(ctx->pmu);
 	ctx->is_active = 0;
 	if (likely(!ctx->nr_events))
 		goto out;
 	update_context_time(ctx);
 
-	perf_disable();
 	if (!ctx->nr_active)
-		goto out_enable;
+		goto out;
 
-	if (event_type & EVENT_PINNED)
+	if (event_type & EVENT_PINNED) {
 		list_for_each_entry(event, &ctx->pinned_groups, group_entry)
 			group_sched_out(event, cpuctx, ctx);
+	}
 
-	if (event_type & EVENT_FLEXIBLE)
+	if (event_type & EVENT_FLEXIBLE) {
 		list_for_each_entry(event, &ctx->flexible_groups, group_entry)
 			group_sched_out(event, cpuctx, ctx);
-
- out_enable:
-	perf_enable();
- out:
+	}
+out:
+	perf_pmu_enable(ctx->pmu);
 	raw_spin_unlock(&ctx->lock);
 }
 
@@ -1209,34 +1241,25 @@
 	}
 }
 
-/*
- * Called from scheduler to remove the events of the current task,
- * with interrupts disabled.
- *
- * We stop each event and update the event value in event->count.
- *
- * This does not protect us against NMI, but disable()
- * sets the disabled bit in the control field of event _before_
- * accessing the event control register. If a NMI hits, then it will
- * not restart the event.
- */
-void perf_event_task_sched_out(struct task_struct *task,
-				 struct task_struct *next)
+void perf_event_context_sched_out(struct task_struct *task, int ctxn,
+				  struct task_struct *next)
 {
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-	struct perf_event_context *ctx = task->perf_event_ctxp;
+	struct perf_event_context *ctx = task->perf_event_ctxp[ctxn];
 	struct perf_event_context *next_ctx;
 	struct perf_event_context *parent;
+	struct perf_cpu_context *cpuctx;
 	int do_switch = 1;
 
-	perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
+	if (likely(!ctx))
+		return;
 
-	if (likely(!ctx || !cpuctx->task_ctx))
+	cpuctx = __get_cpu_context(ctx);
+	if (!cpuctx->task_ctx)
 		return;
 
 	rcu_read_lock();
 	parent = rcu_dereference(ctx->parent_ctx);
-	next_ctx = next->perf_event_ctxp;
+	next_ctx = next->perf_event_ctxp[ctxn];
 	if (parent && next_ctx &&
 	    rcu_dereference(next_ctx->parent_ctx) == parent) {
 		/*
@@ -1255,8 +1278,8 @@
 			 * XXX do we need a memory barrier of sorts
 			 * wrt to rcu_dereference() of perf_event_ctxp
 			 */
-			task->perf_event_ctxp = next_ctx;
-			next->perf_event_ctxp = ctx;
+			task->perf_event_ctxp[ctxn] = next_ctx;
+			next->perf_event_ctxp[ctxn] = ctx;
 			ctx->task = next;
 			next_ctx->task = task;
 			do_switch = 0;
@@ -1274,10 +1297,35 @@
 	}
 }
 
+#define for_each_task_context_nr(ctxn)					\
+	for ((ctxn) = 0; (ctxn) < perf_nr_task_contexts; (ctxn)++)
+
+/*
+ * Called from scheduler to remove the events of the current task,
+ * with interrupts disabled.
+ *
+ * We stop each event and update the event value in event->count.
+ *
+ * This does not protect us against NMI, but disable()
+ * sets the disabled bit in the control field of event _before_
+ * accessing the event control register. If a NMI hits, then it will
+ * not restart the event.
+ */
+void __perf_event_task_sched_out(struct task_struct *task,
+				 struct task_struct *next)
+{
+	int ctxn;
+
+	perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
+
+	for_each_task_context_nr(ctxn)
+		perf_event_context_sched_out(task, ctxn, next);
+}
+
 static void task_ctx_sched_out(struct perf_event_context *ctx,
 			       enum event_type_t event_type)
 {
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
+	struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 
 	if (!cpuctx->task_ctx)
 		return;
@@ -1292,14 +1340,6 @@
 /*
  * Called with IRQs disabled
  */
-static void __perf_event_task_sched_out(struct perf_event_context *ctx)
-{
-	task_ctx_sched_out(ctx, EVENT_ALL);
-}
-
-/*
- * Called with IRQs disabled
- */
 static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
 			      enum event_type_t event_type)
 {
@@ -1350,9 +1390,10 @@
 		if (event->cpu != -1 && event->cpu != smp_processor_id())
 			continue;
 
-		if (group_can_go_on(event, cpuctx, can_add_hw))
+		if (group_can_go_on(event, cpuctx, can_add_hw)) {
 			if (group_sched_in(event, cpuctx, ctx))
 				can_add_hw = 0;
+		}
 	}
 }
 
@@ -1368,8 +1409,6 @@
 
 	ctx->timestamp = perf_clock();
 
-	perf_disable();
-
 	/*
 	 * First go through the list and put on any pinned groups
 	 * in order to give them the best chance of going on.
@@ -1381,8 +1420,7 @@
 	if (event_type & EVENT_FLEXIBLE)
 		ctx_flexible_sched_in(ctx, cpuctx);
 
-	perf_enable();
- out:
+out:
 	raw_spin_unlock(&ctx->lock);
 }
 
@@ -1394,43 +1432,28 @@
 	ctx_sched_in(ctx, cpuctx, event_type);
 }
 
-static void task_ctx_sched_in(struct task_struct *task,
+static void task_ctx_sched_in(struct perf_event_context *ctx,
 			      enum event_type_t event_type)
 {
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-	struct perf_event_context *ctx = task->perf_event_ctxp;
+	struct perf_cpu_context *cpuctx;
 
-	if (likely(!ctx))
-		return;
+       	cpuctx = __get_cpu_context(ctx);
 	if (cpuctx->task_ctx == ctx)
 		return;
+
 	ctx_sched_in(ctx, cpuctx, event_type);
 	cpuctx->task_ctx = ctx;
 }
-/*
- * Called from scheduler to add the events of the current task
- * with interrupts disabled.
- *
- * We restore the event value and then enable it.
- *
- * This does not protect us against NMI, but enable()
- * sets the enabled bit in the control field of event _before_
- * accessing the event control register. If a NMI hits, then it will
- * keep the event running.
- */
-void perf_event_task_sched_in(struct task_struct *task)
+
+void perf_event_context_sched_in(struct perf_event_context *ctx)
 {
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-	struct perf_event_context *ctx = task->perf_event_ctxp;
+	struct perf_cpu_context *cpuctx;
 
-	if (likely(!ctx))
-		return;
-
+	cpuctx = __get_cpu_context(ctx);
 	if (cpuctx->task_ctx == ctx)
 		return;
 
-	perf_disable();
-
+	perf_pmu_disable(ctx->pmu);
 	/*
 	 * We want to keep the following priority order:
 	 * cpu pinned (that don't need to move), task pinned,
@@ -1444,7 +1467,37 @@
 
 	cpuctx->task_ctx = ctx;
 
-	perf_enable();
+	/*
+	 * Since these rotations are per-cpu, we need to ensure the
+	 * cpu-context we got scheduled on is actually rotating.
+	 */
+	perf_pmu_rotate_start(ctx->pmu);
+	perf_pmu_enable(ctx->pmu);
+}
+
+/*
+ * Called from scheduler to add the events of the current task
+ * with interrupts disabled.
+ *
+ * We restore the event value and then enable it.
+ *
+ * This does not protect us against NMI, but enable()
+ * sets the enabled bit in the control field of event _before_
+ * accessing the event control register. If a NMI hits, then it will
+ * keep the event running.
+ */
+void __perf_event_task_sched_in(struct task_struct *task)
+{
+	struct perf_event_context *ctx;
+	int ctxn;
+
+	for_each_task_context_nr(ctxn) {
+		ctx = task->perf_event_ctxp[ctxn];
+		if (likely(!ctx))
+			continue;
+
+		perf_event_context_sched_in(ctx);
+	}
 }
 
 #define MAX_INTERRUPTS (~0ULL)
@@ -1524,22 +1577,6 @@
 	return div64_u64(dividend, divisor);
 }
 
-static void perf_event_stop(struct perf_event *event)
-{
-	if (!event->pmu->stop)
-		return event->pmu->disable(event);
-
-	return event->pmu->stop(event);
-}
-
-static int perf_event_start(struct perf_event *event)
-{
-	if (!event->pmu->start)
-		return event->pmu->enable(event);
-
-	return event->pmu->start(event);
-}
-
 static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
 {
 	struct hw_perf_event *hwc = &event->hw;
@@ -1559,15 +1596,13 @@
 	hwc->sample_period = sample_period;
 
 	if (local64_read(&hwc->period_left) > 8*sample_period) {
-		perf_disable();
-		perf_event_stop(event);
+		event->pmu->stop(event, PERF_EF_UPDATE);
 		local64_set(&hwc->period_left, 0);
-		perf_event_start(event);
-		perf_enable();
+		event->pmu->start(event, PERF_EF_RELOAD);
 	}
 }
 
-static void perf_ctx_adjust_freq(struct perf_event_context *ctx)
+static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
 {
 	struct perf_event *event;
 	struct hw_perf_event *hwc;
@@ -1592,23 +1627,19 @@
 		 */
 		if (interrupts == MAX_INTERRUPTS) {
 			perf_log_throttle(event, 1);
-			perf_disable();
-			event->pmu->unthrottle(event);
-			perf_enable();
+			event->pmu->start(event, 0);
 		}
 
 		if (!event->attr.freq || !event->attr.sample_freq)
 			continue;
 
-		perf_disable();
 		event->pmu->read(event);
 		now = local64_read(&event->count);
 		delta = now - hwc->freq_count_stamp;
 		hwc->freq_count_stamp = now;
 
 		if (delta > 0)
-			perf_adjust_period(event, TICK_NSEC, delta);
-		perf_enable();
+			perf_adjust_period(event, period, delta);
 	}
 	raw_spin_unlock(&ctx->lock);
 }
@@ -1626,32 +1657,38 @@
 	raw_spin_unlock(&ctx->lock);
 }
 
-void perf_event_task_tick(struct task_struct *curr)
+/*
+ * perf_pmu_rotate_start() and perf_rotate_context() are fully serialized
+ * because they're strictly cpu affine and rotate_start is called with IRQs
+ * disabled, while rotate_context is called from IRQ context.
+ */
+static void perf_rotate_context(struct perf_cpu_context *cpuctx)
 {
-	struct perf_cpu_context *cpuctx;
-	struct perf_event_context *ctx;
-	int rotate = 0;
+	u64 interval = (u64)cpuctx->jiffies_interval * TICK_NSEC;
+	struct perf_event_context *ctx = NULL;
+	int rotate = 0, remove = 1;
 
-	if (!atomic_read(&nr_events))
-		return;
+	if (cpuctx->ctx.nr_events) {
+		remove = 0;
+		if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active)
+			rotate = 1;
+	}
 
-	cpuctx = &__get_cpu_var(perf_cpu_context);
-	if (cpuctx->ctx.nr_events &&
-	    cpuctx->ctx.nr_events != cpuctx->ctx.nr_active)
-		rotate = 1;
+	ctx = cpuctx->task_ctx;
+	if (ctx && ctx->nr_events) {
+		remove = 0;
+		if (ctx->nr_events != ctx->nr_active)
+			rotate = 1;
+	}
 
-	ctx = curr->perf_event_ctxp;
-	if (ctx && ctx->nr_events && ctx->nr_events != ctx->nr_active)
-		rotate = 1;
-
-	perf_ctx_adjust_freq(&cpuctx->ctx);
+	perf_pmu_disable(cpuctx->ctx.pmu);
+	perf_ctx_adjust_freq(&cpuctx->ctx, interval);
 	if (ctx)
-		perf_ctx_adjust_freq(ctx);
+		perf_ctx_adjust_freq(ctx, interval);
 
 	if (!rotate)
-		return;
+		goto done;
 
-	perf_disable();
 	cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
 	if (ctx)
 		task_ctx_sched_out(ctx, EVENT_FLEXIBLE);
@@ -1662,8 +1699,27 @@
 
 	cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE);
 	if (ctx)
-		task_ctx_sched_in(curr, EVENT_FLEXIBLE);
-	perf_enable();
+		task_ctx_sched_in(ctx, EVENT_FLEXIBLE);
+
+done:
+	if (remove)
+		list_del_init(&cpuctx->rotation_list);
+
+	perf_pmu_enable(cpuctx->ctx.pmu);
+}
+
+void perf_event_task_tick(void)
+{
+	struct list_head *head = &__get_cpu_var(rotation_list);
+	struct perf_cpu_context *cpuctx, *tmp;
+
+	WARN_ON(!irqs_disabled());
+
+	list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) {
+		if (cpuctx->jiffies_interval == 1 ||
+				!(jiffies % cpuctx->jiffies_interval))
+			perf_rotate_context(cpuctx);
+	}
 }
 
 static int event_enable_on_exec(struct perf_event *event,
@@ -1685,20 +1741,18 @@
  * Enable all of a task's events that have been marked enable-on-exec.
  * This expects task == current.
  */
-static void perf_event_enable_on_exec(struct task_struct *task)
+static void perf_event_enable_on_exec(struct perf_event_context *ctx)
 {
-	struct perf_event_context *ctx;
 	struct perf_event *event;
 	unsigned long flags;
 	int enabled = 0;
 	int ret;
 
 	local_irq_save(flags);
-	ctx = task->perf_event_ctxp;
 	if (!ctx || !ctx->nr_events)
 		goto out;
 
-	__perf_event_task_sched_out(ctx);
+	task_ctx_sched_out(ctx, EVENT_ALL);
 
 	raw_spin_lock(&ctx->lock);
 
@@ -1722,8 +1776,8 @@
 
 	raw_spin_unlock(&ctx->lock);
 
-	perf_event_task_sched_in(task);
- out:
+	perf_event_context_sched_in(ctx);
+out:
 	local_irq_restore(flags);
 }
 
@@ -1732,9 +1786,9 @@
  */
 static void __perf_event_read(void *info)
 {
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
 	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
@@ -1773,7 +1827,13 @@
 		unsigned long flags;
 
 		raw_spin_lock_irqsave(&ctx->lock, flags);
-		update_context_time(ctx);
+		/*
+		 * may read while context is not active
+		 * (e.g., thread is blocked), in that case
+		 * we cannot update context time
+		 */
+		if (ctx->is_active)
+			update_context_time(ctx);
 		update_event_times(event);
 		raw_spin_unlock_irqrestore(&ctx->lock, flags);
 	}
@@ -1782,11 +1842,219 @@
 }
 
 /*
+ * Callchain support
+ */
+
+struct callchain_cpus_entries {
+	struct rcu_head			rcu_head;
+	struct perf_callchain_entry	*cpu_entries[0];
+};
+
+static DEFINE_PER_CPU(int, callchain_recursion[PERF_NR_CONTEXTS]);
+static atomic_t nr_callchain_events;
+static DEFINE_MUTEX(callchain_mutex);
+struct callchain_cpus_entries *callchain_cpus_entries;
+
+
+__weak void perf_callchain_kernel(struct perf_callchain_entry *entry,
+				  struct pt_regs *regs)
+{
+}
+
+__weak void perf_callchain_user(struct perf_callchain_entry *entry,
+				struct pt_regs *regs)
+{
+}
+
+static void release_callchain_buffers_rcu(struct rcu_head *head)
+{
+	struct callchain_cpus_entries *entries;
+	int cpu;
+
+	entries = container_of(head, struct callchain_cpus_entries, rcu_head);
+
+	for_each_possible_cpu(cpu)
+		kfree(entries->cpu_entries[cpu]);
+
+	kfree(entries);
+}
+
+static void release_callchain_buffers(void)
+{
+	struct callchain_cpus_entries *entries;
+
+	entries = callchain_cpus_entries;
+	rcu_assign_pointer(callchain_cpus_entries, NULL);
+	call_rcu(&entries->rcu_head, release_callchain_buffers_rcu);
+}
+
+static int alloc_callchain_buffers(void)
+{
+	int cpu;
+	int size;
+	struct callchain_cpus_entries *entries;
+
+	/*
+	 * We can't use the percpu allocation API for data that can be
+	 * accessed from NMI. Use a temporary manual per cpu allocation
+	 * until that gets sorted out.
+	 */
+	size = sizeof(*entries) + sizeof(struct perf_callchain_entry *) *
+		num_possible_cpus();
+
+	entries = kzalloc(size, GFP_KERNEL);
+	if (!entries)
+		return -ENOMEM;
+
+	size = sizeof(struct perf_callchain_entry) * PERF_NR_CONTEXTS;
+
+	for_each_possible_cpu(cpu) {
+		entries->cpu_entries[cpu] = kmalloc_node(size, GFP_KERNEL,
+							 cpu_to_node(cpu));
+		if (!entries->cpu_entries[cpu])
+			goto fail;
+	}
+
+	rcu_assign_pointer(callchain_cpus_entries, entries);
+
+	return 0;
+
+fail:
+	for_each_possible_cpu(cpu)
+		kfree(entries->cpu_entries[cpu]);
+	kfree(entries);
+
+	return -ENOMEM;
+}
+
+static int get_callchain_buffers(void)
+{
+	int err = 0;
+	int count;
+
+	mutex_lock(&callchain_mutex);
+
+	count = atomic_inc_return(&nr_callchain_events);
+	if (WARN_ON_ONCE(count < 1)) {
+		err = -EINVAL;
+		goto exit;
+	}
+
+	if (count > 1) {
+		/* If the allocation failed, give up */
+		if (!callchain_cpus_entries)
+			err = -ENOMEM;
+		goto exit;
+	}
+
+	err = alloc_callchain_buffers();
+	if (err)
+		release_callchain_buffers();
+exit:
+	mutex_unlock(&callchain_mutex);
+
+	return err;
+}
+
+static void put_callchain_buffers(void)
+{
+	if (atomic_dec_and_mutex_lock(&nr_callchain_events, &callchain_mutex)) {
+		release_callchain_buffers();
+		mutex_unlock(&callchain_mutex);
+	}
+}
+
+static int get_recursion_context(int *recursion)
+{
+	int rctx;
+
+	if (in_nmi())
+		rctx = 3;
+	else if (in_irq())
+		rctx = 2;
+	else if (in_softirq())
+		rctx = 1;
+	else
+		rctx = 0;
+
+	if (recursion[rctx])
+		return -1;
+
+	recursion[rctx]++;
+	barrier();
+
+	return rctx;
+}
+
+static inline void put_recursion_context(int *recursion, int rctx)
+{
+	barrier();
+	recursion[rctx]--;
+}
+
+static struct perf_callchain_entry *get_callchain_entry(int *rctx)
+{
+	int cpu;
+	struct callchain_cpus_entries *entries;
+
+	*rctx = get_recursion_context(__get_cpu_var(callchain_recursion));
+	if (*rctx == -1)
+		return NULL;
+
+	entries = rcu_dereference(callchain_cpus_entries);
+	if (!entries)
+		return NULL;
+
+	cpu = smp_processor_id();
+
+	return &entries->cpu_entries[cpu][*rctx];
+}
+
+static void
+put_callchain_entry(int rctx)
+{
+	put_recursion_context(__get_cpu_var(callchain_recursion), rctx);
+}
+
+static struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
+{
+	int rctx;
+	struct perf_callchain_entry *entry;
+
+
+	entry = get_callchain_entry(&rctx);
+	if (rctx == -1)
+		return NULL;
+
+	if (!entry)
+		goto exit_put;
+
+	entry->nr = 0;
+
+	if (!user_mode(regs)) {
+		perf_callchain_store(entry, PERF_CONTEXT_KERNEL);
+		perf_callchain_kernel(entry, regs);
+		if (current->mm)
+			regs = task_pt_regs(current);
+		else
+			regs = NULL;
+	}
+
+	if (regs) {
+		perf_callchain_store(entry, PERF_CONTEXT_USER);
+		perf_callchain_user(entry, regs);
+	}
+
+exit_put:
+	put_callchain_entry(rctx);
+
+	return entry;
+}
+
+/*
  * Initialize the perf_event context in a task_struct:
  */
-static void
-__perf_event_init_context(struct perf_event_context *ctx,
-			    struct task_struct *task)
+static void __perf_event_init_context(struct perf_event_context *ctx)
 {
 	raw_spin_lock_init(&ctx->lock);
 	mutex_init(&ctx->mutex);
@@ -1794,45 +2062,38 @@
 	INIT_LIST_HEAD(&ctx->flexible_groups);
 	INIT_LIST_HEAD(&ctx->event_list);
 	atomic_set(&ctx->refcount, 1);
-	ctx->task = task;
 }
 
-static struct perf_event_context *find_get_context(pid_t pid, int cpu)
+static struct perf_event_context *
+alloc_perf_context(struct pmu *pmu, struct task_struct *task)
 {
 	struct perf_event_context *ctx;
-	struct perf_cpu_context *cpuctx;
+
+	ctx = kzalloc(sizeof(struct perf_event_context), GFP_KERNEL);
+	if (!ctx)
+		return NULL;
+
+	__perf_event_init_context(ctx);
+	if (task) {
+		ctx->task = task;
+		get_task_struct(task);
+	}
+	ctx->pmu = pmu;
+
+	return ctx;
+}
+
+static struct task_struct *
+find_lively_task_by_vpid(pid_t vpid)
+{
 	struct task_struct *task;
-	unsigned long flags;
 	int err;
 
-	if (pid == -1 && cpu != -1) {
-		/* Must be root to operate on a CPU event: */
-		if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
-			return ERR_PTR(-EACCES);
-
-		if (cpu < 0 || cpu >= nr_cpumask_bits)
-			return ERR_PTR(-EINVAL);
-
-		/*
-		 * We could be clever and allow to attach a event to an
-		 * offline CPU and activate it when the CPU comes up, but
-		 * that's for later.
-		 */
-		if (!cpu_online(cpu))
-			return ERR_PTR(-ENODEV);
-
-		cpuctx = &per_cpu(perf_cpu_context, cpu);
-		ctx = &cpuctx->ctx;
-		get_ctx(ctx);
-
-		return ctx;
-	}
-
 	rcu_read_lock();
-	if (!pid)
+	if (!vpid)
 		task = current;
 	else
-		task = find_task_by_vpid(pid);
+		task = find_task_by_vpid(vpid);
 	if (task)
 		get_task_struct(task);
 	rcu_read_unlock();
@@ -1852,36 +2113,78 @@
 	if (!ptrace_may_access(task, PTRACE_MODE_READ))
 		goto errout;
 
- retry:
-	ctx = perf_lock_task_context(task, &flags);
+	return task;
+errout:
+	put_task_struct(task);
+	return ERR_PTR(err);
+
+}
+
+static struct perf_event_context *
+find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
+{
+	struct perf_event_context *ctx;
+	struct perf_cpu_context *cpuctx;
+	unsigned long flags;
+	int ctxn, err;
+
+	if (!task && cpu != -1) {
+		/* Must be root to operate on a CPU event: */
+		if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
+			return ERR_PTR(-EACCES);
+
+		if (cpu < 0 || cpu >= nr_cpumask_bits)
+			return ERR_PTR(-EINVAL);
+
+		/*
+		 * We could be clever and allow to attach a event to an
+		 * offline CPU and activate it when the CPU comes up, but
+		 * that's for later.
+		 */
+		if (!cpu_online(cpu))
+			return ERR_PTR(-ENODEV);
+
+		cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
+		ctx = &cpuctx->ctx;
+		get_ctx(ctx);
+
+		return ctx;
+	}
+
+	err = -EINVAL;
+	ctxn = pmu->task_ctx_nr;
+	if (ctxn < 0)
+		goto errout;
+
+retry:
+	ctx = perf_lock_task_context(task, ctxn, &flags);
 	if (ctx) {
 		unclone_ctx(ctx);
 		raw_spin_unlock_irqrestore(&ctx->lock, flags);
 	}
 
 	if (!ctx) {
-		ctx = kzalloc(sizeof(struct perf_event_context), GFP_KERNEL);
+		ctx = alloc_perf_context(pmu, task);
 		err = -ENOMEM;
 		if (!ctx)
 			goto errout;
-		__perf_event_init_context(ctx, task);
+
 		get_ctx(ctx);
-		if (cmpxchg(&task->perf_event_ctxp, NULL, ctx)) {
+
+		if (cmpxchg(&task->perf_event_ctxp[ctxn], NULL, ctx)) {
 			/*
 			 * We raced with some other task; use
 			 * the context they set.
 			 */
+			put_task_struct(task);
 			kfree(ctx);
 			goto retry;
 		}
-		get_task_struct(task);
 	}
 
-	put_task_struct(task);
 	return ctx;
 
- errout:
-	put_task_struct(task);
+errout:
 	return ERR_PTR(err);
 }
 
@@ -1898,21 +2201,23 @@
 	kfree(event);
 }
 
-static void perf_pending_sync(struct perf_event *event);
 static void perf_buffer_put(struct perf_buffer *buffer);
 
 static void free_event(struct perf_event *event)
 {
-	perf_pending_sync(event);
+	irq_work_sync(&event->pending);
 
 	if (!event->parent) {
-		atomic_dec(&nr_events);
+		if (event->attach_state & PERF_ATTACH_TASK)
+			jump_label_dec(&perf_task_events);
 		if (event->attr.mmap || event->attr.mmap_data)
 			atomic_dec(&nr_mmap_events);
 		if (event->attr.comm)
 			atomic_dec(&nr_comm_events);
 		if (event->attr.task)
 			atomic_dec(&nr_task_events);
+		if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
+			put_callchain_buffers();
 	}
 
 	if (event->buffer) {
@@ -1923,7 +2228,9 @@
 	if (event->destroy)
 		event->destroy(event);
 
-	put_ctx(event->ctx);
+	if (event->ctx)
+		put_ctx(event->ctx);
+
 	call_rcu(&event->rcu_head, free_event_rcu);
 }
 
@@ -2202,15 +2509,13 @@
 static int perf_event_period(struct perf_event *event, u64 __user *arg)
 {
 	struct perf_event_context *ctx = event->ctx;
-	unsigned long size;
 	int ret = 0;
 	u64 value;
 
 	if (!event->attr.sample_period)
 		return -EINVAL;
 
-	size = copy_from_user(&value, arg, sizeof(value));
-	if (size != sizeof(value))
+	if (copy_from_user(&value, arg, sizeof(value)))
 		return -EFAULT;
 
 	if (!value)
@@ -2344,6 +2649,9 @@
 
 static int perf_event_index(struct perf_event *event)
 {
+	if (event->hw.state & PERF_HES_STOPPED)
+		return 0;
+
 	if (event->state != PERF_EVENT_STATE_ACTIVE)
 		return 0;
 
@@ -2847,16 +3155,7 @@
 	}
 }
 
-/*
- * Pending wakeups
- *
- * Handle the case where we need to wakeup up from NMI (or rq->lock) context.
- *
- * The NMI bit means we cannot possibly take locks. Therefore, maintain a
- * single linked list and use cmpxchg() to add entries lockless.
- */
-
-static void perf_pending_event(struct perf_pending_entry *entry)
+static void perf_pending_event(struct irq_work *entry)
 {
 	struct perf_event *event = container_of(entry,
 			struct perf_event, pending);
@@ -2872,99 +3171,6 @@
 	}
 }
 
-#define PENDING_TAIL ((struct perf_pending_entry *)-1UL)
-
-static DEFINE_PER_CPU(struct perf_pending_entry *, perf_pending_head) = {
-	PENDING_TAIL,
-};
-
-static void perf_pending_queue(struct perf_pending_entry *entry,
-			       void (*func)(struct perf_pending_entry *))
-{
-	struct perf_pending_entry **head;
-
-	if (cmpxchg(&entry->next, NULL, PENDING_TAIL) != NULL)
-		return;
-
-	entry->func = func;
-
-	head = &get_cpu_var(perf_pending_head);
-
-	do {
-		entry->next = *head;
-	} while (cmpxchg(head, entry->next, entry) != entry->next);
-
-	set_perf_event_pending();
-
-	put_cpu_var(perf_pending_head);
-}
-
-static int __perf_pending_run(void)
-{
-	struct perf_pending_entry *list;
-	int nr = 0;
-
-	list = xchg(&__get_cpu_var(perf_pending_head), PENDING_TAIL);
-	while (list != PENDING_TAIL) {
-		void (*func)(struct perf_pending_entry *);
-		struct perf_pending_entry *entry = list;
-
-		list = list->next;
-
-		func = entry->func;
-		entry->next = NULL;
-		/*
-		 * Ensure we observe the unqueue before we issue the wakeup,
-		 * so that we won't be waiting forever.
-		 * -- see perf_not_pending().
-		 */
-		smp_wmb();
-
-		func(entry);
-		nr++;
-	}
-
-	return nr;
-}
-
-static inline int perf_not_pending(struct perf_event *event)
-{
-	/*
-	 * If we flush on whatever cpu we run, there is a chance we don't
-	 * need to wait.
-	 */
-	get_cpu();
-	__perf_pending_run();
-	put_cpu();
-
-	/*
-	 * Ensure we see the proper queue state before going to sleep
-	 * so that we do not miss the wakeup. -- see perf_pending_handle()
-	 */
-	smp_rmb();
-	return event->pending.next == NULL;
-}
-
-static void perf_pending_sync(struct perf_event *event)
-{
-	wait_event(event->waitq, perf_not_pending(event));
-}
-
-void perf_event_do_pending(void)
-{
-	__perf_pending_run();
-}
-
-/*
- * Callchain support -- arch specific
- */
-
-__weak struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
-{
-	return NULL;
-}
-
-
 /*
  * We assume there is only KVM supporting the callbacks.
  * Later on, we might change it to a list if there is
@@ -3014,8 +3220,7 @@
 
 	if (handle->nmi) {
 		handle->event->pending_wakeup = 1;
-		perf_pending_queue(&handle->event->pending,
-				   perf_pending_event);
+		irq_work_queue(&handle->event->pending);
 	} else
 		perf_event_wakeup(handle->event);
 }
@@ -3071,7 +3276,7 @@
 	if (handle->wakeup != local_read(&buffer->wakeup))
 		perf_output_wakeup(handle);
 
- out:
+out:
 	preempt_enable();
 }
 
@@ -3459,14 +3664,20 @@
 	struct perf_output_handle handle;
 	struct perf_event_header header;
 
+	/* protect the callchain buffers */
+	rcu_read_lock();
+
 	perf_prepare_sample(&header, data, event, regs);
 
 	if (perf_output_begin(&handle, event, header.size, nmi, 1))
-		return;
+		goto exit;
 
 	perf_output_sample(&handle, &header, data, event);
 
 	perf_output_end(&handle);
+
+exit:
+	rcu_read_unlock();
 }
 
 /*
@@ -3580,16 +3791,27 @@
 static void perf_event_task_event(struct perf_task_event *task_event)
 {
 	struct perf_cpu_context *cpuctx;
-	struct perf_event_context *ctx = task_event->task_ctx;
+	struct perf_event_context *ctx;
+	struct pmu *pmu;
+	int ctxn;
 
 	rcu_read_lock();
-	cpuctx = &get_cpu_var(perf_cpu_context);
-	perf_event_task_ctx(&cpuctx->ctx, task_event);
-	if (!ctx)
-		ctx = rcu_dereference(current->perf_event_ctxp);
-	if (ctx)
-		perf_event_task_ctx(ctx, task_event);
-	put_cpu_var(perf_cpu_context);
+	list_for_each_entry_rcu(pmu, &pmus, entry) {
+		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+		perf_event_task_ctx(&cpuctx->ctx, task_event);
+
+		ctx = task_event->task_ctx;
+		if (!ctx) {
+			ctxn = pmu->task_ctx_nr;
+			if (ctxn < 0)
+				goto next;
+			ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
+		}
+		if (ctx)
+			perf_event_task_ctx(ctx, task_event);
+next:
+		put_cpu_ptr(pmu->pmu_cpu_context);
+	}
 	rcu_read_unlock();
 }
 
@@ -3694,8 +3916,10 @@
 {
 	struct perf_cpu_context *cpuctx;
 	struct perf_event_context *ctx;
-	unsigned int size;
 	char comm[TASK_COMM_LEN];
+	unsigned int size;
+	struct pmu *pmu;
+	int ctxn;
 
 	memset(comm, 0, sizeof(comm));
 	strlcpy(comm, comm_event->task->comm, sizeof(comm));
@@ -3707,21 +3931,36 @@
 	comm_event->event_id.header.size = sizeof(comm_event->event_id) + size;
 
 	rcu_read_lock();
-	cpuctx = &get_cpu_var(perf_cpu_context);
-	perf_event_comm_ctx(&cpuctx->ctx, comm_event);
-	ctx = rcu_dereference(current->perf_event_ctxp);
-	if (ctx)
-		perf_event_comm_ctx(ctx, comm_event);
-	put_cpu_var(perf_cpu_context);
+	list_for_each_entry_rcu(pmu, &pmus, entry) {
+		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+		perf_event_comm_ctx(&cpuctx->ctx, comm_event);
+
+		ctxn = pmu->task_ctx_nr;
+		if (ctxn < 0)
+			goto next;
+
+		ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
+		if (ctx)
+			perf_event_comm_ctx(ctx, comm_event);
+next:
+		put_cpu_ptr(pmu->pmu_cpu_context);
+	}
 	rcu_read_unlock();
 }
 
 void perf_event_comm(struct task_struct *task)
 {
 	struct perf_comm_event comm_event;
+	struct perf_event_context *ctx;
+	int ctxn;
 
-	if (task->perf_event_ctxp)
-		perf_event_enable_on_exec(task);
+	for_each_task_context_nr(ctxn) {
+		ctx = task->perf_event_ctxp[ctxn];
+		if (!ctx)
+			continue;
+
+		perf_event_enable_on_exec(ctx);
+	}
 
 	if (!atomic_read(&nr_comm_events))
 		return;
@@ -3823,6 +4062,8 @@
 	char tmp[16];
 	char *buf = NULL;
 	const char *name;
+	struct pmu *pmu;
+	int ctxn;
 
 	memset(tmp, 0, sizeof(tmp));
 
@@ -3875,12 +4116,23 @@
 	mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size;
 
 	rcu_read_lock();
-	cpuctx = &get_cpu_var(perf_cpu_context);
-	perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, vma->vm_flags & VM_EXEC);
-	ctx = rcu_dereference(current->perf_event_ctxp);
-	if (ctx)
-		perf_event_mmap_ctx(ctx, mmap_event, vma->vm_flags & VM_EXEC);
-	put_cpu_var(perf_cpu_context);
+	list_for_each_entry_rcu(pmu, &pmus, entry) {
+		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+		perf_event_mmap_ctx(&cpuctx->ctx, mmap_event,
+					vma->vm_flags & VM_EXEC);
+
+		ctxn = pmu->task_ctx_nr;
+		if (ctxn < 0)
+			goto next;
+
+		ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
+		if (ctx) {
+			perf_event_mmap_ctx(ctx, mmap_event,
+					vma->vm_flags & VM_EXEC);
+		}
+next:
+		put_cpu_ptr(pmu->pmu_cpu_context);
+	}
 	rcu_read_unlock();
 
 	kfree(buf);
@@ -3962,8 +4214,6 @@
 	struct hw_perf_event *hwc = &event->hw;
 	int ret = 0;
 
-	throttle = (throttle && event->pmu->unthrottle != NULL);
-
 	if (!throttle) {
 		hwc->interrupts++;
 	} else {
@@ -4006,8 +4256,7 @@
 		event->pending_kill = POLL_HUP;
 		if (nmi) {
 			event->pending_disable = 1;
-			perf_pending_queue(&event->pending,
-					   perf_pending_event);
+			irq_work_queue(&event->pending);
 		} else
 			perf_event_disable(event);
 	}
@@ -4031,6 +4280,17 @@
  * Generic software event infrastructure
  */
 
+struct swevent_htable {
+	struct swevent_hlist		*swevent_hlist;
+	struct mutex			hlist_mutex;
+	int				hlist_refcount;
+
+	/* Recursion avoidance in each contexts */
+	int				recursion[PERF_NR_CONTEXTS];
+};
+
+static DEFINE_PER_CPU(struct swevent_htable, swevent_htable);
+
 /*
  * We directly increment event->count and keep a second value in
  * event->hw.period_left to count intervals. This period event
@@ -4088,7 +4348,7 @@
 	}
 }
 
-static void perf_swevent_add(struct perf_event *event, u64 nr,
+static void perf_swevent_event(struct perf_event *event, u64 nr,
 			       int nmi, struct perf_sample_data *data,
 			       struct pt_regs *regs)
 {
@@ -4114,6 +4374,9 @@
 static int perf_exclude_event(struct perf_event *event,
 			      struct pt_regs *regs)
 {
+	if (event->hw.state & PERF_HES_STOPPED)
+		return 0;
+
 	if (regs) {
 		if (event->attr.exclude_user && user_mode(regs))
 			return 1;
@@ -4160,11 +4423,11 @@
 
 /* For the read side: events when they trigger */
 static inline struct hlist_head *
-find_swevent_head_rcu(struct perf_cpu_context *ctx, u64 type, u32 event_id)
+find_swevent_head_rcu(struct swevent_htable *swhash, u64 type, u32 event_id)
 {
 	struct swevent_hlist *hlist;
 
-	hlist = rcu_dereference(ctx->swevent_hlist);
+	hlist = rcu_dereference(swhash->swevent_hlist);
 	if (!hlist)
 		return NULL;
 
@@ -4173,7 +4436,7 @@
 
 /* For the event head insertion and removal in the hlist */
 static inline struct hlist_head *
-find_swevent_head(struct perf_cpu_context *ctx, struct perf_event *event)
+find_swevent_head(struct swevent_htable *swhash, struct perf_event *event)
 {
 	struct swevent_hlist *hlist;
 	u32 event_id = event->attr.config;
@@ -4184,7 +4447,7 @@
 	 * and release. Which makes the protected version suitable here.
 	 * The context lock guarantees that.
 	 */
-	hlist = rcu_dereference_protected(ctx->swevent_hlist,
+	hlist = rcu_dereference_protected(swhash->swevent_hlist,
 					  lockdep_is_held(&event->ctx->lock));
 	if (!hlist)
 		return NULL;
@@ -4197,23 +4460,19 @@
 				    struct perf_sample_data *data,
 				    struct pt_regs *regs)
 {
-	struct perf_cpu_context *cpuctx;
+	struct swevent_htable *swhash = &__get_cpu_var(swevent_htable);
 	struct perf_event *event;
 	struct hlist_node *node;
 	struct hlist_head *head;
 
-	cpuctx = &__get_cpu_var(perf_cpu_context);
-
 	rcu_read_lock();
-
-	head = find_swevent_head_rcu(cpuctx, type, event_id);
-
+	head = find_swevent_head_rcu(swhash, type, event_id);
 	if (!head)
 		goto end;
 
 	hlist_for_each_entry_rcu(event, node, head, hlist_entry) {
 		if (perf_swevent_match(event, type, event_id, data, regs))
-			perf_swevent_add(event, nr, nmi, data, regs);
+			perf_swevent_event(event, nr, nmi, data, regs);
 	}
 end:
 	rcu_read_unlock();
@@ -4221,33 +4480,17 @@
 
 int perf_swevent_get_recursion_context(void)
 {
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-	int rctx;
+	struct swevent_htable *swhash = &__get_cpu_var(swevent_htable);
 
-	if (in_nmi())
-		rctx = 3;
-	else if (in_irq())
-		rctx = 2;
-	else if (in_softirq())
-		rctx = 1;
-	else
-		rctx = 0;
-
-	if (cpuctx->recursion[rctx])
-		return -1;
-
-	cpuctx->recursion[rctx]++;
-	barrier();
-
-	return rctx;
+	return get_recursion_context(swhash->recursion);
 }
 EXPORT_SYMBOL_GPL(perf_swevent_get_recursion_context);
 
 void inline perf_swevent_put_recursion_context(int rctx)
 {
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-	barrier();
-	cpuctx->recursion[rctx]--;
+	struct swevent_htable *swhash = &__get_cpu_var(swevent_htable);
+
+	put_recursion_context(swhash->recursion, rctx);
 }
 
 void __perf_sw_event(u32 event_id, u64 nr, int nmi,
@@ -4273,20 +4516,20 @@
 {
 }
 
-static int perf_swevent_enable(struct perf_event *event)
+static int perf_swevent_add(struct perf_event *event, int flags)
 {
+	struct swevent_htable *swhash = &__get_cpu_var(swevent_htable);
 	struct hw_perf_event *hwc = &event->hw;
-	struct perf_cpu_context *cpuctx;
 	struct hlist_head *head;
 
-	cpuctx = &__get_cpu_var(perf_cpu_context);
-
 	if (hwc->sample_period) {
 		hwc->last_period = hwc->sample_period;
 		perf_swevent_set_period(event);
 	}
 
-	head = find_swevent_head(cpuctx, event);
+	hwc->state = !(flags & PERF_EF_START);
+
+	head = find_swevent_head(swhash, event);
 	if (WARN_ON_ONCE(!head))
 		return -EINVAL;
 
@@ -4295,202 +4538,27 @@
 	return 0;
 }
 
-static void perf_swevent_disable(struct perf_event *event)
+static void perf_swevent_del(struct perf_event *event, int flags)
 {
 	hlist_del_rcu(&event->hlist_entry);
 }
 
-static void perf_swevent_void(struct perf_event *event)
+static void perf_swevent_start(struct perf_event *event, int flags)
 {
+	event->hw.state = 0;
 }
 
-static int perf_swevent_int(struct perf_event *event)
+static void perf_swevent_stop(struct perf_event *event, int flags)
 {
-	return 0;
+	event->hw.state = PERF_HES_STOPPED;
 }
 
-static const struct pmu perf_ops_generic = {
-	.enable		= perf_swevent_enable,
-	.disable	= perf_swevent_disable,
-	.start		= perf_swevent_int,
-	.stop		= perf_swevent_void,
-	.read		= perf_swevent_read,
-	.unthrottle	= perf_swevent_void, /* hwc->interrupts already reset */
-};
-
-/*
- * hrtimer based swevent callback
- */
-
-static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
-{
-	enum hrtimer_restart ret = HRTIMER_RESTART;
-	struct perf_sample_data data;
-	struct pt_regs *regs;
-	struct perf_event *event;
-	u64 period;
-
-	event = container_of(hrtimer, struct perf_event, hw.hrtimer);
-	event->pmu->read(event);
-
-	perf_sample_data_init(&data, 0);
-	data.period = event->hw.last_period;
-	regs = get_irq_regs();
-
-	if (regs && !perf_exclude_event(event, regs)) {
-		if (!(event->attr.exclude_idle && current->pid == 0))
-			if (perf_event_overflow(event, 0, &data, regs))
-				ret = HRTIMER_NORESTART;
-	}
-
-	period = max_t(u64, 10000, event->hw.sample_period);
-	hrtimer_forward_now(hrtimer, ns_to_ktime(period));
-
-	return ret;
-}
-
-static void perf_swevent_start_hrtimer(struct perf_event *event)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-	hwc->hrtimer.function = perf_swevent_hrtimer;
-	if (hwc->sample_period) {
-		u64 period;
-
-		if (hwc->remaining) {
-			if (hwc->remaining < 0)
-				period = 10000;
-			else
-				period = hwc->remaining;
-			hwc->remaining = 0;
-		} else {
-			period = max_t(u64, 10000, hwc->sample_period);
-		}
-		__hrtimer_start_range_ns(&hwc->hrtimer,
-				ns_to_ktime(period), 0,
-				HRTIMER_MODE_REL, 0);
-	}
-}
-
-static void perf_swevent_cancel_hrtimer(struct perf_event *event)
-{
-	struct hw_perf_event *hwc = &event->hw;
-
-	if (hwc->sample_period) {
-		ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer);
-		hwc->remaining = ktime_to_ns(remaining);
-
-		hrtimer_cancel(&hwc->hrtimer);
-	}
-}
-
-/*
- * Software event: cpu wall time clock
- */
-
-static void cpu_clock_perf_event_update(struct perf_event *event)
-{
-	int cpu = raw_smp_processor_id();
-	s64 prev;
-	u64 now;
-
-	now = cpu_clock(cpu);
-	prev = local64_xchg(&event->hw.prev_count, now);
-	local64_add(now - prev, &event->count);
-}
-
-static int cpu_clock_perf_event_enable(struct perf_event *event)
-{
-	struct hw_perf_event *hwc = &event->hw;
-	int cpu = raw_smp_processor_id();
-
-	local64_set(&hwc->prev_count, cpu_clock(cpu));
-	perf_swevent_start_hrtimer(event);
-
-	return 0;
-}
-
-static void cpu_clock_perf_event_disable(struct perf_event *event)
-{
-	perf_swevent_cancel_hrtimer(event);
-	cpu_clock_perf_event_update(event);
-}
-
-static void cpu_clock_perf_event_read(struct perf_event *event)
-{
-	cpu_clock_perf_event_update(event);
-}
-
-static const struct pmu perf_ops_cpu_clock = {
-	.enable		= cpu_clock_perf_event_enable,
-	.disable	= cpu_clock_perf_event_disable,
-	.read		= cpu_clock_perf_event_read,
-};
-
-/*
- * Software event: task time clock
- */
-
-static void task_clock_perf_event_update(struct perf_event *event, u64 now)
-{
-	u64 prev;
-	s64 delta;
-
-	prev = local64_xchg(&event->hw.prev_count, now);
-	delta = now - prev;
-	local64_add(delta, &event->count);
-}
-
-static int task_clock_perf_event_enable(struct perf_event *event)
-{
-	struct hw_perf_event *hwc = &event->hw;
-	u64 now;
-
-	now = event->ctx->time;
-
-	local64_set(&hwc->prev_count, now);
-
-	perf_swevent_start_hrtimer(event);
-
-	return 0;
-}
-
-static void task_clock_perf_event_disable(struct perf_event *event)
-{
-	perf_swevent_cancel_hrtimer(event);
-	task_clock_perf_event_update(event, event->ctx->time);
-
-}
-
-static void task_clock_perf_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;
-	}
-
-	task_clock_perf_event_update(event, time);
-}
-
-static const struct pmu perf_ops_task_clock = {
-	.enable		= task_clock_perf_event_enable,
-	.disable	= task_clock_perf_event_disable,
-	.read		= task_clock_perf_event_read,
-};
-
 /* Deref the hlist from the update side */
 static inline struct swevent_hlist *
-swevent_hlist_deref(struct perf_cpu_context *cpuctx)
+swevent_hlist_deref(struct swevent_htable *swhash)
 {
-	return rcu_dereference_protected(cpuctx->swevent_hlist,
-					 lockdep_is_held(&cpuctx->hlist_mutex));
+	return rcu_dereference_protected(swhash->swevent_hlist,
+					 lockdep_is_held(&swhash->hlist_mutex));
 }
 
 static void swevent_hlist_release_rcu(struct rcu_head *rcu_head)
@@ -4501,27 +4569,27 @@
 	kfree(hlist);
 }
 
-static void swevent_hlist_release(struct perf_cpu_context *cpuctx)
+static void swevent_hlist_release(struct swevent_htable *swhash)
 {
-	struct swevent_hlist *hlist = swevent_hlist_deref(cpuctx);
+	struct swevent_hlist *hlist = swevent_hlist_deref(swhash);
 
 	if (!hlist)
 		return;
 
-	rcu_assign_pointer(cpuctx->swevent_hlist, NULL);
+	rcu_assign_pointer(swhash->swevent_hlist, NULL);
 	call_rcu(&hlist->rcu_head, swevent_hlist_release_rcu);
 }
 
 static void swevent_hlist_put_cpu(struct perf_event *event, int cpu)
 {
-	struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
+	struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
-	mutex_lock(&cpuctx->hlist_mutex);
+	mutex_lock(&swhash->hlist_mutex);
 
-	if (!--cpuctx->hlist_refcount)
-		swevent_hlist_release(cpuctx);
+	if (!--swhash->hlist_refcount)
+		swevent_hlist_release(swhash);
 
-	mutex_unlock(&cpuctx->hlist_mutex);
+	mutex_unlock(&swhash->hlist_mutex);
 }
 
 static void swevent_hlist_put(struct perf_event *event)
@@ -4539,12 +4607,12 @@
 
 static int swevent_hlist_get_cpu(struct perf_event *event, int cpu)
 {
-	struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
+	struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 	int err = 0;
 
-	mutex_lock(&cpuctx->hlist_mutex);
+	mutex_lock(&swhash->hlist_mutex);
 
-	if (!swevent_hlist_deref(cpuctx) && cpu_online(cpu)) {
+	if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) {
 		struct swevent_hlist *hlist;
 
 		hlist = kzalloc(sizeof(*hlist), GFP_KERNEL);
@@ -4552,11 +4620,11 @@
 			err = -ENOMEM;
 			goto exit;
 		}
-		rcu_assign_pointer(cpuctx->swevent_hlist, hlist);
+		rcu_assign_pointer(swhash->swevent_hlist, hlist);
 	}
-	cpuctx->hlist_refcount++;
- exit:
-	mutex_unlock(&cpuctx->hlist_mutex);
+	swhash->hlist_refcount++;
+exit:
+	mutex_unlock(&swhash->hlist_mutex);
 
 	return err;
 }
@@ -4580,7 +4648,7 @@
 	put_online_cpus();
 
 	return 0;
- fail:
+fail:
 	for_each_possible_cpu(cpu) {
 		if (cpu == failed_cpu)
 			break;
@@ -4591,17 +4659,64 @@
 	return err;
 }
 
-#ifdef CONFIG_EVENT_TRACING
+atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
 
-static const struct pmu perf_ops_tracepoint = {
-	.enable		= perf_trace_enable,
-	.disable	= perf_trace_disable,
-	.start		= perf_swevent_int,
-	.stop		= perf_swevent_void,
+static void sw_perf_event_destroy(struct perf_event *event)
+{
+	u64 event_id = event->attr.config;
+
+	WARN_ON(event->parent);
+
+	jump_label_dec(&perf_swevent_enabled[event_id]);
+	swevent_hlist_put(event);
+}
+
+static int perf_swevent_init(struct perf_event *event)
+{
+	int event_id = event->attr.config;
+
+	if (event->attr.type != PERF_TYPE_SOFTWARE)
+		return -ENOENT;
+
+	switch (event_id) {
+	case PERF_COUNT_SW_CPU_CLOCK:
+	case PERF_COUNT_SW_TASK_CLOCK:
+		return -ENOENT;
+
+	default:
+		break;
+	}
+
+	if (event_id > PERF_COUNT_SW_MAX)
+		return -ENOENT;
+
+	if (!event->parent) {
+		int err;
+
+		err = swevent_hlist_get(event);
+		if (err)
+			return err;
+
+		jump_label_inc(&perf_swevent_enabled[event_id]);
+		event->destroy = sw_perf_event_destroy;
+	}
+
+	return 0;
+}
+
+static struct pmu perf_swevent = {
+	.task_ctx_nr	= perf_sw_context,
+
+	.event_init	= perf_swevent_init,
+	.add		= perf_swevent_add,
+	.del		= perf_swevent_del,
+	.start		= perf_swevent_start,
+	.stop		= perf_swevent_stop,
 	.read		= perf_swevent_read,
-	.unthrottle	= perf_swevent_void,
 };
 
+#ifdef CONFIG_EVENT_TRACING
+
 static int perf_tp_filter_match(struct perf_event *event,
 				struct perf_sample_data *data)
 {
@@ -4645,7 +4760,7 @@
 
 	hlist_for_each_entry_rcu(event, node, head, hlist_entry) {
 		if (perf_tp_event_match(event, &data, regs))
-			perf_swevent_add(event, count, 1, &data, regs);
+			perf_swevent_event(event, count, 1, &data, regs);
 	}
 
 	perf_swevent_put_recursion_context(rctx);
@@ -4657,10 +4772,13 @@
 	perf_trace_destroy(event);
 }
 
-static const struct pmu *tp_perf_event_init(struct perf_event *event)
+static int perf_tp_event_init(struct perf_event *event)
 {
 	int err;
 
+	if (event->attr.type != PERF_TYPE_TRACEPOINT)
+		return -ENOENT;
+
 	/*
 	 * Raw tracepoint data is a severe data leak, only allow root to
 	 * have these.
@@ -4668,15 +4786,31 @@
 	if ((event->attr.sample_type & PERF_SAMPLE_RAW) &&
 			perf_paranoid_tracepoint_raw() &&
 			!capable(CAP_SYS_ADMIN))
-		return ERR_PTR(-EPERM);
+		return -EPERM;
 
 	err = perf_trace_init(event);
 	if (err)
-		return NULL;
+		return err;
 
 	event->destroy = tp_perf_event_destroy;
 
-	return &perf_ops_tracepoint;
+	return 0;
+}
+
+static struct pmu perf_tracepoint = {
+	.task_ctx_nr	= perf_sw_context,
+
+	.event_init	= perf_tp_event_init,
+	.add		= perf_trace_add,
+	.del		= perf_trace_del,
+	.start		= perf_swevent_start,
+	.stop		= perf_swevent_stop,
+	.read		= perf_swevent_read,
+};
+
+static inline void perf_tp_register(void)
+{
+	perf_pmu_register(&perf_tracepoint);
 }
 
 static int perf_event_set_filter(struct perf_event *event, void __user *arg)
@@ -4704,9 +4838,8 @@
 
 #else
 
-static const struct pmu *tp_perf_event_init(struct perf_event *event)
+static inline void perf_tp_register(void)
 {
-	return NULL;
 }
 
 static int perf_event_set_filter(struct perf_event *event, void __user *arg)
@@ -4721,24 +4854,6 @@
 #endif /* CONFIG_EVENT_TRACING */
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
-static void bp_perf_event_destroy(struct perf_event *event)
-{
-	release_bp_slot(event);
-}
-
-static const struct pmu *bp_perf_event_init(struct perf_event *bp)
-{
-	int err;
-
-	err = register_perf_hw_breakpoint(bp);
-	if (err)
-		return ERR_PTR(err);
-
-	bp->destroy = bp_perf_event_destroy;
-
-	return &perf_ops_bp;
-}
-
 void perf_bp_event(struct perf_event *bp, void *data)
 {
 	struct perf_sample_data sample;
@@ -4746,80 +4861,382 @@
 
 	perf_sample_data_init(&sample, bp->attr.bp_addr);
 
-	if (!perf_exclude_event(bp, regs))
-		perf_swevent_add(bp, 1, 1, &sample, regs);
-}
-#else
-static const struct pmu *bp_perf_event_init(struct perf_event *bp)
-{
-	return NULL;
-}
-
-void perf_bp_event(struct perf_event *bp, void *regs)
-{
+	if (!bp->hw.state && !perf_exclude_event(bp, regs))
+		perf_swevent_event(bp, 1, 1, &sample, regs);
 }
 #endif
 
-atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
+/*
+ * hrtimer based swevent callback
+ */
 
-static void sw_perf_event_destroy(struct perf_event *event)
+static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
 {
-	u64 event_id = event->attr.config;
+	enum hrtimer_restart ret = HRTIMER_RESTART;
+	struct perf_sample_data data;
+	struct pt_regs *regs;
+	struct perf_event *event;
+	u64 period;
 
-	WARN_ON(event->parent);
+	event = container_of(hrtimer, struct perf_event, hw.hrtimer);
+	event->pmu->read(event);
 
-	atomic_dec(&perf_swevent_enabled[event_id]);
-	swevent_hlist_put(event);
+	perf_sample_data_init(&data, 0);
+	data.period = event->hw.last_period;
+	regs = get_irq_regs();
+
+	if (regs && !perf_exclude_event(event, regs)) {
+		if (!(event->attr.exclude_idle && current->pid == 0))
+			if (perf_event_overflow(event, 0, &data, regs))
+				ret = HRTIMER_NORESTART;
+	}
+
+	period = max_t(u64, 10000, event->hw.sample_period);
+	hrtimer_forward_now(hrtimer, ns_to_ktime(period));
+
+	return ret;
 }
 
-static const struct pmu *sw_perf_event_init(struct perf_event *event)
+static void perf_swevent_start_hrtimer(struct perf_event *event)
 {
-	const struct pmu *pmu = NULL;
-	u64 event_id = event->attr.config;
+	struct hw_perf_event *hwc = &event->hw;
+
+	hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	hwc->hrtimer.function = perf_swevent_hrtimer;
+	if (hwc->sample_period) {
+		s64 period = local64_read(&hwc->period_left);
+
+		if (period) {
+			if (period < 0)
+				period = 10000;
+
+			local64_set(&hwc->period_left, 0);
+		} else {
+			period = max_t(u64, 10000, hwc->sample_period);
+		}
+		__hrtimer_start_range_ns(&hwc->hrtimer,
+				ns_to_ktime(period), 0,
+				HRTIMER_MODE_REL_PINNED, 0);
+	}
+}
+
+static void perf_swevent_cancel_hrtimer(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (hwc->sample_period) {
+		ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer);
+		local64_set(&hwc->period_left, ktime_to_ns(remaining));
+
+		hrtimer_cancel(&hwc->hrtimer);
+	}
+}
+
+/*
+ * Software event: cpu wall time clock
+ */
+
+static void cpu_clock_event_update(struct perf_event *event)
+{
+	s64 prev;
+	u64 now;
+
+	now = local_clock();
+	prev = local64_xchg(&event->hw.prev_count, now);
+	local64_add(now - prev, &event->count);
+}
+
+static void cpu_clock_event_start(struct perf_event *event, int flags)
+{
+	local64_set(&event->hw.prev_count, local_clock());
+	perf_swevent_start_hrtimer(event);
+}
+
+static void cpu_clock_event_stop(struct perf_event *event, int flags)
+{
+	perf_swevent_cancel_hrtimer(event);
+	cpu_clock_event_update(event);
+}
+
+static int cpu_clock_event_add(struct perf_event *event, int flags)
+{
+	if (flags & PERF_EF_START)
+		cpu_clock_event_start(event, flags);
+
+	return 0;
+}
+
+static void cpu_clock_event_del(struct perf_event *event, int flags)
+{
+	cpu_clock_event_stop(event, flags);
+}
+
+static void cpu_clock_event_read(struct perf_event *event)
+{
+	cpu_clock_event_update(event);
+}
+
+static int cpu_clock_event_init(struct perf_event *event)
+{
+	if (event->attr.type != PERF_TYPE_SOFTWARE)
+		return -ENOENT;
+
+	if (event->attr.config != PERF_COUNT_SW_CPU_CLOCK)
+		return -ENOENT;
+
+	return 0;
+}
+
+static struct pmu perf_cpu_clock = {
+	.task_ctx_nr	= perf_sw_context,
+
+	.event_init	= cpu_clock_event_init,
+	.add		= cpu_clock_event_add,
+	.del		= cpu_clock_event_del,
+	.start		= cpu_clock_event_start,
+	.stop		= cpu_clock_event_stop,
+	.read		= cpu_clock_event_read,
+};
+
+/*
+ * Software event: task time clock
+ */
+
+static void task_clock_event_update(struct perf_event *event, u64 now)
+{
+	u64 prev;
+	s64 delta;
+
+	prev = local64_xchg(&event->hw.prev_count, now);
+	delta = now - prev;
+	local64_add(delta, &event->count);
+}
+
+static void task_clock_event_start(struct perf_event *event, int flags)
+{
+	local64_set(&event->hw.prev_count, event->ctx->time);
+	perf_swevent_start_hrtimer(event);
+}
+
+static void task_clock_event_stop(struct perf_event *event, int flags)
+{
+	perf_swevent_cancel_hrtimer(event);
+	task_clock_event_update(event, event->ctx->time);
+}
+
+static int task_clock_event_add(struct perf_event *event, int flags)
+{
+	if (flags & PERF_EF_START)
+		task_clock_event_start(event, flags);
+
+	return 0;
+}
+
+static void task_clock_event_del(struct perf_event *event, int flags)
+{
+	task_clock_event_stop(event, PERF_EF_UPDATE);
+}
+
+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;
+	}
+
+	task_clock_event_update(event, time);
+}
+
+static int task_clock_event_init(struct perf_event *event)
+{
+	if (event->attr.type != PERF_TYPE_SOFTWARE)
+		return -ENOENT;
+
+	if (event->attr.config != PERF_COUNT_SW_TASK_CLOCK)
+		return -ENOENT;
+
+	return 0;
+}
+
+static struct pmu perf_task_clock = {
+	.task_ctx_nr	= perf_sw_context,
+
+	.event_init	= task_clock_event_init,
+	.add		= task_clock_event_add,
+	.del		= task_clock_event_del,
+	.start		= task_clock_event_start,
+	.stop		= task_clock_event_stop,
+	.read		= task_clock_event_read,
+};
+
+static void perf_pmu_nop_void(struct pmu *pmu)
+{
+}
+
+static int perf_pmu_nop_int(struct pmu *pmu)
+{
+	return 0;
+}
+
+static void perf_pmu_start_txn(struct pmu *pmu)
+{
+	perf_pmu_disable(pmu);
+}
+
+static int perf_pmu_commit_txn(struct pmu *pmu)
+{
+	perf_pmu_enable(pmu);
+	return 0;
+}
+
+static void perf_pmu_cancel_txn(struct pmu *pmu)
+{
+	perf_pmu_enable(pmu);
+}
+
+/*
+ * Ensures all contexts with the same task_ctx_nr have the same
+ * pmu_cpu_context too.
+ */
+static void *find_pmu_context(int ctxn)
+{
+	struct pmu *pmu;
+
+	if (ctxn < 0)
+		return NULL;
+
+	list_for_each_entry(pmu, &pmus, entry) {
+		if (pmu->task_ctx_nr == ctxn)
+			return pmu->pmu_cpu_context;
+	}
+
+	return NULL;
+}
+
+static void free_pmu_context(void * __percpu cpu_context)
+{
+	struct pmu *pmu;
+
+	mutex_lock(&pmus_lock);
+	/*
+	 * Like a real lame refcount.
+	 */
+	list_for_each_entry(pmu, &pmus, entry) {
+		if (pmu->pmu_cpu_context == cpu_context)
+			goto out;
+	}
+
+	free_percpu(cpu_context);
+out:
+	mutex_unlock(&pmus_lock);
+}
+
+int perf_pmu_register(struct pmu *pmu)
+{
+	int cpu, ret;
+
+	mutex_lock(&pmus_lock);
+	ret = -ENOMEM;
+	pmu->pmu_disable_count = alloc_percpu(int);
+	if (!pmu->pmu_disable_count)
+		goto unlock;
+
+	pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr);
+	if (pmu->pmu_cpu_context)
+		goto got_cpu_context;
+
+	pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context);
+	if (!pmu->pmu_cpu_context)
+		goto free_pdc;
+
+	for_each_possible_cpu(cpu) {
+		struct perf_cpu_context *cpuctx;
+
+		cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
+		__perf_event_init_context(&cpuctx->ctx);
+		cpuctx->ctx.type = cpu_context;
+		cpuctx->ctx.pmu = pmu;
+		cpuctx->jiffies_interval = 1;
+		INIT_LIST_HEAD(&cpuctx->rotation_list);
+	}
+
+got_cpu_context:
+	if (!pmu->start_txn) {
+		if (pmu->pmu_enable) {
+			/*
+			 * If we have pmu_enable/pmu_disable calls, install
+			 * transaction stubs that use that to try and batch
+			 * hardware accesses.
+			 */
+			pmu->start_txn  = perf_pmu_start_txn;
+			pmu->commit_txn = perf_pmu_commit_txn;
+			pmu->cancel_txn = perf_pmu_cancel_txn;
+		} else {
+			pmu->start_txn  = perf_pmu_nop_void;
+			pmu->commit_txn = perf_pmu_nop_int;
+			pmu->cancel_txn = perf_pmu_nop_void;
+		}
+	}
+
+	if (!pmu->pmu_enable) {
+		pmu->pmu_enable  = perf_pmu_nop_void;
+		pmu->pmu_disable = perf_pmu_nop_void;
+	}
+
+	list_add_rcu(&pmu->entry, &pmus);
+	ret = 0;
+unlock:
+	mutex_unlock(&pmus_lock);
+
+	return ret;
+
+free_pdc:
+	free_percpu(pmu->pmu_disable_count);
+	goto unlock;
+}
+
+void perf_pmu_unregister(struct pmu *pmu)
+{
+	mutex_lock(&pmus_lock);
+	list_del_rcu(&pmu->entry);
+	mutex_unlock(&pmus_lock);
 
 	/*
-	 * Software events (currently) can't in general distinguish
-	 * between user, kernel and hypervisor events.
-	 * However, context switches and cpu migrations are considered
-	 * to be kernel events, and page faults are never hypervisor
-	 * events.
+	 * We dereference the pmu list under both SRCU and regular RCU, so
+	 * synchronize against both of those.
 	 */
-	switch (event_id) {
-	case PERF_COUNT_SW_CPU_CLOCK:
-		pmu = &perf_ops_cpu_clock;
+	synchronize_srcu(&pmus_srcu);
+	synchronize_rcu();
 
-		break;
-	case PERF_COUNT_SW_TASK_CLOCK:
-		/*
-		 * If the user instantiates this as a per-cpu event,
-		 * use the cpu_clock event instead.
-		 */
-		if (event->ctx->task)
-			pmu = &perf_ops_task_clock;
-		else
-			pmu = &perf_ops_cpu_clock;
+	free_percpu(pmu->pmu_disable_count);
+	free_pmu_context(pmu->pmu_cpu_context);
+}
 
-		break;
-	case PERF_COUNT_SW_PAGE_FAULTS:
-	case PERF_COUNT_SW_PAGE_FAULTS_MIN:
-	case PERF_COUNT_SW_PAGE_FAULTS_MAJ:
-	case PERF_COUNT_SW_CONTEXT_SWITCHES:
-	case PERF_COUNT_SW_CPU_MIGRATIONS:
-	case PERF_COUNT_SW_ALIGNMENT_FAULTS:
-	case PERF_COUNT_SW_EMULATION_FAULTS:
-		if (!event->parent) {
-			int err;
+struct pmu *perf_init_event(struct perf_event *event)
+{
+	struct pmu *pmu = NULL;
+	int idx;
 
-			err = swevent_hlist_get(event);
-			if (err)
-				return ERR_PTR(err);
+	idx = srcu_read_lock(&pmus_srcu);
+	list_for_each_entry_rcu(pmu, &pmus, entry) {
+		int ret = pmu->event_init(event);
+		if (!ret)
+			goto unlock;
 
-			atomic_inc(&perf_swevent_enabled[event_id]);
-			event->destroy = sw_perf_event_destroy;
+		if (ret != -ENOENT) {
+			pmu = ERR_PTR(ret);
+			goto unlock;
 		}
-		pmu = &perf_ops_generic;
-		break;
 	}
+	pmu = ERR_PTR(-ENOENT);
+unlock:
+	srcu_read_unlock(&pmus_srcu, idx);
 
 	return pmu;
 }
@@ -4828,20 +5245,18 @@
  * Allocate and initialize a event structure
  */
 static struct perf_event *
-perf_event_alloc(struct perf_event_attr *attr,
-		   int cpu,
-		   struct perf_event_context *ctx,
-		   struct perf_event *group_leader,
-		   struct perf_event *parent_event,
-		   perf_overflow_handler_t overflow_handler,
-		   gfp_t gfpflags)
+perf_event_alloc(struct perf_event_attr *attr, int cpu,
+		 struct task_struct *task,
+		 struct perf_event *group_leader,
+		 struct perf_event *parent_event,
+		 perf_overflow_handler_t overflow_handler)
 {
-	const struct pmu *pmu;
+	struct pmu *pmu;
 	struct perf_event *event;
 	struct hw_perf_event *hwc;
 	long err;
 
-	event = kzalloc(sizeof(*event), gfpflags);
+	event = kzalloc(sizeof(*event), GFP_KERNEL);
 	if (!event)
 		return ERR_PTR(-ENOMEM);
 
@@ -4859,6 +5274,7 @@
 	INIT_LIST_HEAD(&event->event_entry);
 	INIT_LIST_HEAD(&event->sibling_list);
 	init_waitqueue_head(&event->waitq);
+	init_irq_work(&event->pending, perf_pending_event);
 
 	mutex_init(&event->mmap_mutex);
 
@@ -4866,7 +5282,6 @@
 	event->attr		= *attr;
 	event->group_leader	= group_leader;
 	event->pmu		= NULL;
-	event->ctx		= ctx;
 	event->oncpu		= -1;
 
 	event->parent		= parent_event;
@@ -4876,6 +5291,17 @@
 
 	event->state		= PERF_EVENT_STATE_INACTIVE;
 
+	if (task) {
+		event->attach_state = PERF_ATTACH_TASK;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+		/*
+		 * hw_breakpoint is a bit difficult here..
+		 */
+		if (attr->type == PERF_TYPE_BREAKPOINT)
+			event->hw.bp_target = task;
+#endif
+	}
+
 	if (!overflow_handler && parent_event)
 		overflow_handler = parent_event->overflow_handler;
 	
@@ -4900,29 +5326,8 @@
 	if (attr->inherit && (attr->read_format & PERF_FORMAT_GROUP))
 		goto done;
 
-	switch (attr->type) {
-	case PERF_TYPE_RAW:
-	case PERF_TYPE_HARDWARE:
-	case PERF_TYPE_HW_CACHE:
-		pmu = hw_perf_event_init(event);
-		break;
+	pmu = perf_init_event(event);
 
-	case PERF_TYPE_SOFTWARE:
-		pmu = sw_perf_event_init(event);
-		break;
-
-	case PERF_TYPE_TRACEPOINT:
-		pmu = tp_perf_event_init(event);
-		break;
-
-	case PERF_TYPE_BREAKPOINT:
-		pmu = bp_perf_event_init(event);
-		break;
-
-
-	default:
-		break;
-	}
 done:
 	err = 0;
 	if (!pmu)
@@ -4940,13 +5345,21 @@
 	event->pmu = pmu;
 
 	if (!event->parent) {
-		atomic_inc(&nr_events);
+		if (event->attach_state & PERF_ATTACH_TASK)
+			jump_label_inc(&perf_task_events);
 		if (event->attr.mmap || event->attr.mmap_data)
 			atomic_inc(&nr_mmap_events);
 		if (event->attr.comm)
 			atomic_inc(&nr_comm_events);
 		if (event->attr.task)
 			atomic_inc(&nr_task_events);
+		if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
+			err = get_callchain_buffers();
+			if (err) {
+				free_event(event);
+				return ERR_PTR(err);
+			}
+		}
 	}
 
 	return event;
@@ -5094,12 +5507,16 @@
 		struct perf_event_attr __user *, attr_uptr,
 		pid_t, pid, int, cpu, int, group_fd, unsigned long, flags)
 {
-	struct perf_event *event, *group_leader = NULL, *output_event = NULL;
+	struct perf_event *group_leader = NULL, *output_event = NULL;
+	struct perf_event *event, *sibling;
 	struct perf_event_attr attr;
 	struct perf_event_context *ctx;
 	struct file *event_file = NULL;
 	struct file *group_file = NULL;
+	struct task_struct *task = NULL;
+	struct pmu *pmu;
 	int event_fd;
+	int move_group = 0;
 	int fput_needed = 0;
 	int err;
 
@@ -5125,20 +5542,11 @@
 	if (event_fd < 0)
 		return event_fd;
 
-	/*
-	 * Get the target context (task or percpu):
-	 */
-	ctx = find_get_context(pid, cpu);
-	if (IS_ERR(ctx)) {
-		err = PTR_ERR(ctx);
-		goto err_fd;
-	}
-
 	if (group_fd != -1) {
 		group_leader = perf_fget_light(group_fd, &fput_needed);
 		if (IS_ERR(group_leader)) {
 			err = PTR_ERR(group_leader);
-			goto err_put_context;
+			goto err_fd;
 		}
 		group_file = group_leader->filp;
 		if (flags & PERF_FLAG_FD_OUTPUT)
@@ -5147,6 +5555,58 @@
 			group_leader = NULL;
 	}
 
+	if (pid != -1) {
+		task = find_lively_task_by_vpid(pid);
+		if (IS_ERR(task)) {
+			err = PTR_ERR(task);
+			goto err_group_fd;
+		}
+	}
+
+	event = perf_event_alloc(&attr, cpu, task, group_leader, NULL, NULL);
+	if (IS_ERR(event)) {
+		err = PTR_ERR(event);
+		goto err_task;
+	}
+
+	/*
+	 * Special case software events and allow them to be part of
+	 * any hardware group.
+	 */
+	pmu = event->pmu;
+
+	if (group_leader &&
+	    (is_software_event(event) != is_software_event(group_leader))) {
+		if (is_software_event(event)) {
+			/*
+			 * If event and group_leader are not both a software
+			 * event, and event is, then group leader is not.
+			 *
+			 * Allow the addition of software events to !software
+			 * groups, this is safe because software events never
+			 * fail to schedule.
+			 */
+			pmu = group_leader->pmu;
+		} else if (is_software_event(group_leader) &&
+			   (group_leader->group_flags & PERF_GROUP_SOFTWARE)) {
+			/*
+			 * In case the group is a pure software group, and we
+			 * try to add a hardware event, move the whole group to
+			 * the hardware context.
+			 */
+			move_group = 1;
+		}
+	}
+
+	/*
+	 * Get the target context (task or percpu):
+	 */
+	ctx = find_get_context(pmu, task, cpu);
+	if (IS_ERR(ctx)) {
+		err = PTR_ERR(ctx);
+		goto err_alloc;
+	}
+
 	/*
 	 * Look up the group leader (we will attach this event to it):
 	 */
@@ -5158,42 +5618,66 @@
 		 * becoming part of another group-sibling):
 		 */
 		if (group_leader->group_leader != group_leader)
-			goto err_put_context;
+			goto err_context;
 		/*
 		 * Do not allow to attach to a group in a different
 		 * task or CPU context:
 		 */
-		if (group_leader->ctx != ctx)
-			goto err_put_context;
+		if (move_group) {
+			if (group_leader->ctx->type != ctx->type)
+				goto err_context;
+		} else {
+			if (group_leader->ctx != ctx)
+				goto err_context;
+		}
+
 		/*
 		 * Only a group leader can be exclusive or pinned
 		 */
 		if (attr.exclusive || attr.pinned)
-			goto err_put_context;
-	}
-
-	event = perf_event_alloc(&attr, cpu, ctx, group_leader,
-				     NULL, NULL, GFP_KERNEL);
-	if (IS_ERR(event)) {
-		err = PTR_ERR(event);
-		goto err_put_context;
+			goto err_context;
 	}
 
 	if (output_event) {
 		err = perf_event_set_output(event, output_event);
 		if (err)
-			goto err_free_put_context;
+			goto err_context;
 	}
 
 	event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR);
 	if (IS_ERR(event_file)) {
 		err = PTR_ERR(event_file);
-		goto err_free_put_context;
+		goto err_context;
+	}
+
+	if (move_group) {
+		struct perf_event_context *gctx = group_leader->ctx;
+
+		mutex_lock(&gctx->mutex);
+		perf_event_remove_from_context(group_leader);
+		list_for_each_entry(sibling, &group_leader->sibling_list,
+				    group_entry) {
+			perf_event_remove_from_context(sibling);
+			put_ctx(gctx);
+		}
+		mutex_unlock(&gctx->mutex);
+		put_ctx(gctx);
 	}
 
 	event->filp = event_file;
 	WARN_ON_ONCE(ctx->parent_ctx);
 	mutex_lock(&ctx->mutex);
+
+	if (move_group) {
+		perf_install_in_context(ctx, group_leader, cpu);
+		get_ctx(ctx);
+		list_for_each_entry(sibling, &group_leader->sibling_list,
+				    group_entry) {
+			perf_install_in_context(ctx, sibling, cpu);
+			get_ctx(ctx);
+		}
+	}
+
 	perf_install_in_context(ctx, event, cpu);
 	++ctx->generation;
 	mutex_unlock(&ctx->mutex);
@@ -5214,11 +5698,15 @@
 	fd_install(event_fd, event_file);
 	return event_fd;
 
-err_free_put_context:
-	free_event(event);
-err_put_context:
-	fput_light(group_file, fput_needed);
+err_context:
 	put_ctx(ctx);
+err_alloc:
+	free_event(event);
+err_task:
+	if (task)
+		put_task_struct(task);
+err_group_fd:
+	fput_light(group_file, fput_needed);
 err_fd:
 	put_unused_fd(event_fd);
 	return err;
@@ -5229,32 +5717,31 @@
  *
  * @attr: attributes of the counter to create
  * @cpu: cpu in which the counter is bound
- * @pid: task to profile
+ * @task: task to profile (NULL for percpu)
  */
 struct perf_event *
 perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
-				 pid_t pid,
+				 struct task_struct *task,
 				 perf_overflow_handler_t overflow_handler)
 {
-	struct perf_event *event;
 	struct perf_event_context *ctx;
+	struct perf_event *event;
 	int err;
 
 	/*
 	 * Get the target context (task or percpu):
 	 */
 
-	ctx = find_get_context(pid, cpu);
-	if (IS_ERR(ctx)) {
-		err = PTR_ERR(ctx);
-		goto err_exit;
-	}
-
-	event = perf_event_alloc(attr, cpu, ctx, NULL,
-				 NULL, overflow_handler, GFP_KERNEL);
+	event = perf_event_alloc(attr, cpu, task, NULL, NULL, overflow_handler);
 	if (IS_ERR(event)) {
 		err = PTR_ERR(event);
-		goto err_put_context;
+		goto err;
+	}
+
+	ctx = find_get_context(event->pmu, task, cpu);
+	if (IS_ERR(ctx)) {
+		err = PTR_ERR(ctx);
+		goto err_free;
 	}
 
 	event->filp = NULL;
@@ -5272,112 +5759,13 @@
 
 	return event;
 
- err_put_context:
-	put_ctx(ctx);
- err_exit:
+err_free:
+	free_event(event);
+err:
 	return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter);
 
-/*
- * inherit a event from parent task to child task:
- */
-static struct perf_event *
-inherit_event(struct perf_event *parent_event,
-	      struct task_struct *parent,
-	      struct perf_event_context *parent_ctx,
-	      struct task_struct *child,
-	      struct perf_event *group_leader,
-	      struct perf_event_context *child_ctx)
-{
-	struct perf_event *child_event;
-
-	/*
-	 * Instead of creating recursive hierarchies of events,
-	 * we link inherited events back to the original parent,
-	 * which has a filp for sure, which we use as the reference
-	 * count:
-	 */
-	if (parent_event->parent)
-		parent_event = parent_event->parent;
-
-	child_event = perf_event_alloc(&parent_event->attr,
-					   parent_event->cpu, child_ctx,
-					   group_leader, parent_event,
-					   NULL, GFP_KERNEL);
-	if (IS_ERR(child_event))
-		return child_event;
-	get_ctx(child_ctx);
-
-	/*
-	 * Make the child state follow the state of the parent event,
-	 * not its attr.disabled bit.  We hold the parent's mutex,
-	 * so we won't race with perf_event_{en, dis}able_family.
-	 */
-	if (parent_event->state >= PERF_EVENT_STATE_INACTIVE)
-		child_event->state = PERF_EVENT_STATE_INACTIVE;
-	else
-		child_event->state = PERF_EVENT_STATE_OFF;
-
-	if (parent_event->attr.freq) {
-		u64 sample_period = parent_event->hw.sample_period;
-		struct hw_perf_event *hwc = &child_event->hw;
-
-		hwc->sample_period = sample_period;
-		hwc->last_period   = sample_period;
-
-		local64_set(&hwc->period_left, sample_period);
-	}
-
-	child_event->overflow_handler = parent_event->overflow_handler;
-
-	/*
-	 * Link it up in the child's context:
-	 */
-	add_event_to_ctx(child_event, child_ctx);
-
-	/*
-	 * Get a reference to the parent filp - we will fput it
-	 * when the child event exits. This is safe to do because
-	 * we are in the parent and we know that the filp still
-	 * exists and has a nonzero count:
-	 */
-	atomic_long_inc(&parent_event->filp->f_count);
-
-	/*
-	 * Link this into the parent event's child list
-	 */
-	WARN_ON_ONCE(parent_event->ctx->parent_ctx);
-	mutex_lock(&parent_event->child_mutex);
-	list_add_tail(&child_event->child_list, &parent_event->child_list);
-	mutex_unlock(&parent_event->child_mutex);
-
-	return child_event;
-}
-
-static int inherit_group(struct perf_event *parent_event,
-	      struct task_struct *parent,
-	      struct perf_event_context *parent_ctx,
-	      struct task_struct *child,
-	      struct perf_event_context *child_ctx)
-{
-	struct perf_event *leader;
-	struct perf_event *sub;
-	struct perf_event *child_ctr;
-
-	leader = inherit_event(parent_event, parent, parent_ctx,
-				 child, NULL, child_ctx);
-	if (IS_ERR(leader))
-		return PTR_ERR(leader);
-	list_for_each_entry(sub, &parent_event->sibling_list, group_entry) {
-		child_ctr = inherit_event(sub, parent, parent_ctx,
-					    child, leader, child_ctx);
-		if (IS_ERR(child_ctr))
-			return PTR_ERR(child_ctr);
-	}
-	return 0;
-}
-
 static void sync_child_event(struct perf_event *child_event,
 			       struct task_struct *child)
 {
@@ -5434,16 +5822,13 @@
 	}
 }
 
-/*
- * When a child task exits, feed back event values to parent events.
- */
-void perf_event_exit_task(struct task_struct *child)
+static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
 {
 	struct perf_event *child_event, *tmp;
 	struct perf_event_context *child_ctx;
 	unsigned long flags;
 
-	if (likely(!child->perf_event_ctxp)) {
+	if (likely(!child->perf_event_ctxp[ctxn])) {
 		perf_event_task(child, NULL, 0);
 		return;
 	}
@@ -5455,8 +5840,8 @@
 	 * scheduled, so we are now safe from rescheduling changing
 	 * our context.
 	 */
-	child_ctx = child->perf_event_ctxp;
-	__perf_event_task_sched_out(child_ctx);
+	child_ctx = child->perf_event_ctxp[ctxn];
+	task_ctx_sched_out(child_ctx, EVENT_ALL);
 
 	/*
 	 * Take the context lock here so that if find_get_context is
@@ -5464,7 +5849,7 @@
 	 * incremented the context's refcount before we do put_ctx below.
 	 */
 	raw_spin_lock(&child_ctx->lock);
-	child->perf_event_ctxp = NULL;
+	child->perf_event_ctxp[ctxn] = NULL;
 	/*
 	 * If this context is a clone; unclone it so it can't get
 	 * swapped to another process while we're removing all
@@ -5517,6 +5902,17 @@
 	put_ctx(child_ctx);
 }
 
+/*
+ * When a child task exits, feed back event values to parent events.
+ */
+void perf_event_exit_task(struct task_struct *child)
+{
+	int ctxn;
+
+	for_each_task_context_nr(ctxn)
+		perf_event_exit_task_context(child, ctxn);
+}
+
 static void perf_free_event(struct perf_event *event,
 			    struct perf_event_context *ctx)
 {
@@ -5538,48 +5934,166 @@
 
 /*
  * free an unexposed, unused context as created by inheritance by
- * init_task below, used by fork() in case of fail.
+ * perf_event_init_task below, used by fork() in case of fail.
  */
 void perf_event_free_task(struct task_struct *task)
 {
-	struct perf_event_context *ctx = task->perf_event_ctxp;
+	struct perf_event_context *ctx;
 	struct perf_event *event, *tmp;
+	int ctxn;
 
-	if (!ctx)
-		return;
+	for_each_task_context_nr(ctxn) {
+		ctx = task->perf_event_ctxp[ctxn];
+		if (!ctx)
+			continue;
 
-	mutex_lock(&ctx->mutex);
+		mutex_lock(&ctx->mutex);
 again:
-	list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry)
-		perf_free_event(event, ctx);
+		list_for_each_entry_safe(event, tmp, &ctx->pinned_groups,
+				group_entry)
+			perf_free_event(event, ctx);
 
-	list_for_each_entry_safe(event, tmp, &ctx->flexible_groups,
-				 group_entry)
-		perf_free_event(event, ctx);
+		list_for_each_entry_safe(event, tmp, &ctx->flexible_groups,
+				group_entry)
+			perf_free_event(event, ctx);
 
-	if (!list_empty(&ctx->pinned_groups) ||
-	    !list_empty(&ctx->flexible_groups))
-		goto again;
+		if (!list_empty(&ctx->pinned_groups) ||
+				!list_empty(&ctx->flexible_groups))
+			goto again;
 
-	mutex_unlock(&ctx->mutex);
+		mutex_unlock(&ctx->mutex);
 
-	put_ctx(ctx);
+		put_ctx(ctx);
+	}
+}
+
+void perf_event_delayed_put(struct task_struct *task)
+{
+	int ctxn;
+
+	for_each_task_context_nr(ctxn)
+		WARN_ON_ONCE(task->perf_event_ctxp[ctxn]);
+}
+
+/*
+ * inherit a event from parent task to child task:
+ */
+static struct perf_event *
+inherit_event(struct perf_event *parent_event,
+	      struct task_struct *parent,
+	      struct perf_event_context *parent_ctx,
+	      struct task_struct *child,
+	      struct perf_event *group_leader,
+	      struct perf_event_context *child_ctx)
+{
+	struct perf_event *child_event;
+	unsigned long flags;
+
+	/*
+	 * Instead of creating recursive hierarchies of events,
+	 * we link inherited events back to the original parent,
+	 * which has a filp for sure, which we use as the reference
+	 * count:
+	 */
+	if (parent_event->parent)
+		parent_event = parent_event->parent;
+
+	child_event = perf_event_alloc(&parent_event->attr,
+					   parent_event->cpu,
+					   child,
+					   group_leader, parent_event,
+					   NULL);
+	if (IS_ERR(child_event))
+		return child_event;
+	get_ctx(child_ctx);
+
+	/*
+	 * Make the child state follow the state of the parent event,
+	 * not its attr.disabled bit.  We hold the parent's mutex,
+	 * so we won't race with perf_event_{en, dis}able_family.
+	 */
+	if (parent_event->state >= PERF_EVENT_STATE_INACTIVE)
+		child_event->state = PERF_EVENT_STATE_INACTIVE;
+	else
+		child_event->state = PERF_EVENT_STATE_OFF;
+
+	if (parent_event->attr.freq) {
+		u64 sample_period = parent_event->hw.sample_period;
+		struct hw_perf_event *hwc = &child_event->hw;
+
+		hwc->sample_period = sample_period;
+		hwc->last_period   = sample_period;
+
+		local64_set(&hwc->period_left, sample_period);
+	}
+
+	child_event->ctx = child_ctx;
+	child_event->overflow_handler = parent_event->overflow_handler;
+
+	/*
+	 * Link it up in the child's context:
+	 */
+	raw_spin_lock_irqsave(&child_ctx->lock, flags);
+	add_event_to_ctx(child_event, child_ctx);
+	raw_spin_unlock_irqrestore(&child_ctx->lock, flags);
+
+	/*
+	 * Get a reference to the parent filp - we will fput it
+	 * when the child event exits. This is safe to do because
+	 * we are in the parent and we know that the filp still
+	 * exists and has a nonzero count:
+	 */
+	atomic_long_inc(&parent_event->filp->f_count);
+
+	/*
+	 * Link this into the parent event's child list
+	 */
+	WARN_ON_ONCE(parent_event->ctx->parent_ctx);
+	mutex_lock(&parent_event->child_mutex);
+	list_add_tail(&child_event->child_list, &parent_event->child_list);
+	mutex_unlock(&parent_event->child_mutex);
+
+	return child_event;
+}
+
+static int inherit_group(struct perf_event *parent_event,
+	      struct task_struct *parent,
+	      struct perf_event_context *parent_ctx,
+	      struct task_struct *child,
+	      struct perf_event_context *child_ctx)
+{
+	struct perf_event *leader;
+	struct perf_event *sub;
+	struct perf_event *child_ctr;
+
+	leader = inherit_event(parent_event, parent, parent_ctx,
+				 child, NULL, child_ctx);
+	if (IS_ERR(leader))
+		return PTR_ERR(leader);
+	list_for_each_entry(sub, &parent_event->sibling_list, group_entry) {
+		child_ctr = inherit_event(sub, parent, parent_ctx,
+					    child, leader, child_ctx);
+		if (IS_ERR(child_ctr))
+			return PTR_ERR(child_ctr);
+	}
+	return 0;
 }
 
 static int
 inherit_task_group(struct perf_event *event, struct task_struct *parent,
 		   struct perf_event_context *parent_ctx,
-		   struct task_struct *child,
+		   struct task_struct *child, int ctxn,
 		   int *inherited_all)
 {
 	int ret;
-	struct perf_event_context *child_ctx = child->perf_event_ctxp;
+	struct perf_event_context *child_ctx;
 
 	if (!event->attr.inherit) {
 		*inherited_all = 0;
 		return 0;
 	}
 
+       	child_ctx = child->perf_event_ctxp[ctxn];
 	if (!child_ctx) {
 		/*
 		 * This is executed from the parent task context, so
@@ -5588,14 +6102,11 @@
 		 * child.
 		 */
 
-		child_ctx = kzalloc(sizeof(struct perf_event_context),
-				    GFP_KERNEL);
+		child_ctx = alloc_perf_context(event->pmu, child);
 		if (!child_ctx)
 			return -ENOMEM;
 
-		__perf_event_init_context(child_ctx, child);
-		child->perf_event_ctxp = child_ctx;
-		get_task_struct(child);
+		child->perf_event_ctxp[ctxn] = child_ctx;
 	}
 
 	ret = inherit_group(event, parent, parent_ctx,
@@ -5607,11 +6118,10 @@
 	return ret;
 }
 
-
 /*
  * Initialize the perf_event context in task_struct
  */
-int perf_event_init_task(struct task_struct *child)
+int perf_event_init_context(struct task_struct *child, int ctxn)
 {
 	struct perf_event_context *child_ctx, *parent_ctx;
 	struct perf_event_context *cloned_ctx;
@@ -5620,19 +6130,19 @@
 	int inherited_all = 1;
 	int ret = 0;
 
-	child->perf_event_ctxp = NULL;
+	child->perf_event_ctxp[ctxn] = NULL;
 
 	mutex_init(&child->perf_event_mutex);
 	INIT_LIST_HEAD(&child->perf_event_list);
 
-	if (likely(!parent->perf_event_ctxp))
+	if (likely(!parent->perf_event_ctxp[ctxn]))
 		return 0;
 
 	/*
 	 * If the parent's context is a clone, pin it so it won't get
 	 * swapped under us.
 	 */
-	parent_ctx = perf_pin_task_context(parent);
+	parent_ctx = perf_pin_task_context(parent, ctxn);
 
 	/*
 	 * No need to check if parent_ctx != NULL here; since we saw
@@ -5652,20 +6162,20 @@
 	 * the list, not manipulating it:
 	 */
 	list_for_each_entry(event, &parent_ctx->pinned_groups, group_entry) {
-		ret = inherit_task_group(event, parent, parent_ctx, child,
-					 &inherited_all);
+		ret = inherit_task_group(event, parent, parent_ctx,
+					 child, ctxn, &inherited_all);
 		if (ret)
 			break;
 	}
 
 	list_for_each_entry(event, &parent_ctx->flexible_groups, group_entry) {
-		ret = inherit_task_group(event, parent, parent_ctx, child,
-					 &inherited_all);
+		ret = inherit_task_group(event, parent, parent_ctx,
+					 child, ctxn, &inherited_all);
 		if (ret)
 			break;
 	}
 
-	child_ctx = child->perf_event_ctxp;
+	child_ctx = child->perf_event_ctxp[ctxn];
 
 	if (child_ctx && inherited_all) {
 		/*
@@ -5694,63 +6204,98 @@
 	return ret;
 }
 
+/*
+ * Initialize the perf_event context in task_struct
+ */
+int perf_event_init_task(struct task_struct *child)
+{
+	int ctxn, ret;
+
+	for_each_task_context_nr(ctxn) {
+		ret = perf_event_init_context(child, ctxn);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static void __init perf_event_init_all_cpus(void)
 {
+	struct swevent_htable *swhash;
 	int cpu;
-	struct perf_cpu_context *cpuctx;
 
 	for_each_possible_cpu(cpu) {
-		cpuctx = &per_cpu(perf_cpu_context, cpu);
-		mutex_init(&cpuctx->hlist_mutex);
-		__perf_event_init_context(&cpuctx->ctx, NULL);
+		swhash = &per_cpu(swevent_htable, cpu);
+		mutex_init(&swhash->hlist_mutex);
+		INIT_LIST_HEAD(&per_cpu(rotation_list, cpu));
 	}
 }
 
 static void __cpuinit perf_event_init_cpu(int cpu)
 {
-	struct perf_cpu_context *cpuctx;
+	struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
-	cpuctx = &per_cpu(perf_cpu_context, cpu);
-
-	spin_lock(&perf_resource_lock);
-	cpuctx->max_pertask = perf_max_events - perf_reserved_percpu;
-	spin_unlock(&perf_resource_lock);
-
-	mutex_lock(&cpuctx->hlist_mutex);
-	if (cpuctx->hlist_refcount > 0) {
+	mutex_lock(&swhash->hlist_mutex);
+	if (swhash->hlist_refcount > 0) {
 		struct swevent_hlist *hlist;
 
-		hlist = kzalloc(sizeof(*hlist), GFP_KERNEL);
-		WARN_ON_ONCE(!hlist);
-		rcu_assign_pointer(cpuctx->swevent_hlist, hlist);
+		hlist = kzalloc_node(sizeof(*hlist), GFP_KERNEL, cpu_to_node(cpu));
+		WARN_ON(!hlist);
+		rcu_assign_pointer(swhash->swevent_hlist, hlist);
 	}
-	mutex_unlock(&cpuctx->hlist_mutex);
+	mutex_unlock(&swhash->hlist_mutex);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static void __perf_event_exit_cpu(void *info)
+static void perf_pmu_rotate_stop(struct pmu *pmu)
 {
-	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
-	struct perf_event_context *ctx = &cpuctx->ctx;
+	struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
+
+	WARN_ON(!irqs_disabled());
+
+	list_del_init(&cpuctx->rotation_list);
+}
+
+static void __perf_event_exit_context(void *__info)
+{
+	struct perf_event_context *ctx = __info;
 	struct perf_event *event, *tmp;
 
+	perf_pmu_rotate_stop(ctx->pmu);
+
 	list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry)
 		__perf_event_remove_from_context(event);
 	list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry)
 		__perf_event_remove_from_context(event);
 }
+
+static void perf_event_exit_cpu_context(int cpu)
+{
+	struct perf_event_context *ctx;
+	struct pmu *pmu;
+	int idx;
+
+	idx = srcu_read_lock(&pmus_srcu);
+	list_for_each_entry_rcu(pmu, &pmus, entry) {
+		ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx;
+
+		mutex_lock(&ctx->mutex);
+		smp_call_function_single(cpu, __perf_event_exit_context, ctx, 1);
+		mutex_unlock(&ctx->mutex);
+	}
+	srcu_read_unlock(&pmus_srcu, idx);
+}
+
 static void perf_event_exit_cpu(int cpu)
 {
-	struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
-	struct perf_event_context *ctx = &cpuctx->ctx;
+	struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
-	mutex_lock(&cpuctx->hlist_mutex);
-	swevent_hlist_release(cpuctx);
-	mutex_unlock(&cpuctx->hlist_mutex);
+	mutex_lock(&swhash->hlist_mutex);
+	swevent_hlist_release(swhash);
+	mutex_unlock(&swhash->hlist_mutex);
 
-	mutex_lock(&ctx->mutex);
-	smp_call_function_single(cpu, __perf_event_exit_cpu, NULL, 1);
-	mutex_unlock(&ctx->mutex);
+	perf_event_exit_cpu_context(cpu);
 }
 #else
 static inline void perf_event_exit_cpu(int cpu) { }
@@ -5780,118 +6325,13 @@
 	return NOTIFY_OK;
 }
 
-/*
- * This has to have a higher priority than migration_notifier in sched.c.
- */
-static struct notifier_block __cpuinitdata perf_cpu_nb = {
-	.notifier_call		= perf_cpu_notify,
-	.priority		= 20,
-};
-
 void __init perf_event_init(void)
 {
 	perf_event_init_all_cpus();
-	perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_UP_PREPARE,
-			(void *)(long)smp_processor_id());
-	perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_ONLINE,
-			(void *)(long)smp_processor_id());
-	register_cpu_notifier(&perf_cpu_nb);
+	init_srcu_struct(&pmus_srcu);
+	perf_pmu_register(&perf_swevent);
+	perf_pmu_register(&perf_cpu_clock);
+	perf_pmu_register(&perf_task_clock);
+	perf_tp_register();
+	perf_cpu_notifier(perf_cpu_notify);
 }
-
-static ssize_t perf_show_reserve_percpu(struct sysdev_class *class,
-					struct sysdev_class_attribute *attr,
-					char *buf)
-{
-	return sprintf(buf, "%d\n", perf_reserved_percpu);
-}
-
-static ssize_t
-perf_set_reserve_percpu(struct sysdev_class *class,
-			struct sysdev_class_attribute *attr,
-			const char *buf,
-			size_t count)
-{
-	struct perf_cpu_context *cpuctx;
-	unsigned long val;
-	int err, cpu, mpt;
-
-	err = strict_strtoul(buf, 10, &val);
-	if (err)
-		return err;
-	if (val > perf_max_events)
-		return -EINVAL;
-
-	spin_lock(&perf_resource_lock);
-	perf_reserved_percpu = val;
-	for_each_online_cpu(cpu) {
-		cpuctx = &per_cpu(perf_cpu_context, cpu);
-		raw_spin_lock_irq(&cpuctx->ctx.lock);
-		mpt = min(perf_max_events - cpuctx->ctx.nr_events,
-			  perf_max_events - perf_reserved_percpu);
-		cpuctx->max_pertask = mpt;
-		raw_spin_unlock_irq(&cpuctx->ctx.lock);
-	}
-	spin_unlock(&perf_resource_lock);
-
-	return count;
-}
-
-static ssize_t perf_show_overcommit(struct sysdev_class *class,
-				    struct sysdev_class_attribute *attr,
-				    char *buf)
-{
-	return sprintf(buf, "%d\n", perf_overcommit);
-}
-
-static ssize_t
-perf_set_overcommit(struct sysdev_class *class,
-		    struct sysdev_class_attribute *attr,
-		    const char *buf, size_t count)
-{
-	unsigned long val;
-	int err;
-
-	err = strict_strtoul(buf, 10, &val);
-	if (err)
-		return err;
-	if (val > 1)
-		return -EINVAL;
-
-	spin_lock(&perf_resource_lock);
-	perf_overcommit = val;
-	spin_unlock(&perf_resource_lock);
-
-	return count;
-}
-
-static SYSDEV_CLASS_ATTR(
-				reserve_percpu,
-				0644,
-				perf_show_reserve_percpu,
-				perf_set_reserve_percpu
-			);
-
-static SYSDEV_CLASS_ATTR(
-				overcommit,
-				0644,
-				perf_show_overcommit,
-				perf_set_overcommit
-			);
-
-static struct attribute *perfclass_attrs[] = {
-	&attr_reserve_percpu.attr,
-	&attr_overcommit.attr,
-	NULL
-};
-
-static struct attribute_group perfclass_attr_group = {
-	.attrs			= perfclass_attrs,
-	.name			= "perf_events",
-};
-
-static int __init perf_event_sysfs_init(void)
-{
-	return sysfs_create_group(&cpu_sysdev_class.kset.kobj,
-				  &perfclass_attr_group);
-}
-device_initcall(perf_event_sysfs_init);
diff --git a/kernel/pid.c b/kernel/pid.c
index d55c6fb..39b65b6 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -401,7 +401,7 @@
 	struct task_struct *result = NULL;
 	if (pid) {
 		struct hlist_node *first;
-		first = rcu_dereference_check(pid->tasks[type].first,
+		first = rcu_dereference_check(hlist_first_rcu(&pid->tasks[type]),
 					      rcu_read_lock_held() ||
 					      lockdep_tasklist_lock_is_held());
 		if (first)
@@ -416,6 +416,7 @@
  */
 struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns)
 {
+	rcu_lockdep_assert(rcu_read_lock_held());
 	return pid_task(find_pid_ns(nr, ns), PIDTYPE_PID);
 }
 
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index 645e541..a96b850 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -110,6 +110,7 @@
 	.write = pm_qos_power_write,
 	.open = pm_qos_power_open,
 	.release = pm_qos_power_release,
+	.llseek = noop_llseek,
 };
 
 /* unlocked internal variant */
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index ca6066a..29bff61 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -86,6 +86,7 @@
 	depends on SMP
 	depends on ARCH_SUSPEND_POSSIBLE || ARCH_HIBERNATION_POSSIBLE
 	depends on PM_SLEEP
+	select HOTPLUG
 	select HOTPLUG_CPU
 	default y
 
@@ -137,6 +138,8 @@
 config HIBERNATION
 	bool "Hibernation (aka 'suspend to disk')"
 	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
+	select LZO_COMPRESS
+	select LZO_DECOMPRESS
 	select SUSPEND_NVS if HAS_IOMEM
 	---help---
 	  Enable the suspend to disk (STD) functionality, which is usually
@@ -242,3 +245,17 @@
 	bool
 	depends on PM_SLEEP || PM_RUNTIME
 	default y
+
+config PM_OPP
+	bool "Operating Performance Point (OPP) Layer library"
+	depends on PM
+	---help---
+	  SOCs have a standard set of tuples consisting of frequency and
+	  voltage pairs that the device will support per voltage domain. This
+	  is called Operating Performance Point or OPP. The actual definitions
+	  of OPP varies over silicon within the same family of devices.
+
+	  OPP layer organizes the data internally using device pointers
+	  representing individual voltage domains and provides SOC
+	  implementations a ready to use framework to manage OPPs.
+	  For more information, read <file:Documentation/power/opp.txt>
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 8dc31e0..657272e9 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -29,6 +29,7 @@
 #include "power.h"
 
 
+static int nocompress = 0;
 static int noresume = 0;
 static char resume_file[256] = CONFIG_PM_STD_PARTITION;
 dev_t swsusp_resume_device;
@@ -638,6 +639,8 @@
 
 		if (hibernation_mode == HIBERNATION_PLATFORM)
 			flags |= SF_PLATFORM_MODE;
+		if (nocompress)
+			flags |= SF_NOCOMPRESS_MODE;
 		pr_debug("PM: writing image.\n");
 		error = swsusp_write(flags);
 		swsusp_free();
@@ -705,7 +708,7 @@
 		goto Unlock;
 	}
 
-	pr_debug("PM: Checking image partition %s\n", resume_file);
+	pr_debug("PM: Checking hibernation image partition %s\n", resume_file);
 
 	/* Check if the device is there */
 	swsusp_resume_device = name_to_dev_t(resume_file);
@@ -730,10 +733,10 @@
 	}
 
  Check_image:
-	pr_debug("PM: Resume from partition %d:%d\n",
+	pr_debug("PM: Hibernation image partition %d:%d present\n",
 		MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
 
-	pr_debug("PM: Checking hibernation image.\n");
+	pr_debug("PM: Looking for hibernation image.\n");
 	error = swsusp_check();
 	if (error)
 		goto Unlock;
@@ -765,14 +768,14 @@
 		goto Done;
 	}
 
-	pr_debug("PM: Reading hibernation image.\n");
+	pr_debug("PM: Loading hibernation image.\n");
 
 	error = swsusp_read(&flags);
 	swsusp_close(FMODE_READ);
 	if (!error)
 		hibernation_restore(flags & SF_PLATFORM_MODE);
 
-	printk(KERN_ERR "PM: Restore failed, recovering.\n");
+	printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
 	swsusp_free();
 	thaw_processes();
  Done:
@@ -785,7 +788,7 @@
 	/* For success case, the suspend path will release the lock */
  Unlock:
 	mutex_unlock(&pm_mutex);
-	pr_debug("PM: Resume from disk failed.\n");
+	pr_debug("PM: Hibernation image not present or could not be loaded.\n");
 	return error;
 close_finish:
 	swsusp_close(FMODE_READ);
@@ -1004,6 +1007,15 @@
 	return 1;
 }
 
+static int __init hibernate_setup(char *str)
+{
+	if (!strncmp(str, "noresume", 8))
+		noresume = 1;
+	else if (!strncmp(str, "nocompress", 10))
+		nocompress = 1;
+	return 1;
+}
+
 static int __init noresume_setup(char *str)
 {
 	noresume = 1;
@@ -1013,3 +1025,4 @@
 __setup("noresume", noresume_setup);
 __setup("resume_offset=", resume_offset_setup);
 __setup("resume=", resume_setup);
+__setup("hibernate=", hibernate_setup);
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 62b0bc6..7b5db6a 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -237,18 +237,18 @@
 				struct kobj_attribute *attr,
 				char *buf)
 {
-	unsigned long val;
+	unsigned int val;
 
-	return pm_get_wakeup_count(&val) ? sprintf(buf, "%lu\n", val) : -EINTR;
+	return pm_get_wakeup_count(&val) ? sprintf(buf, "%u\n", val) : -EINTR;
 }
 
 static ssize_t wakeup_count_store(struct kobject *kobj,
 				struct kobj_attribute *attr,
 				const char *buf, size_t n)
 {
-	unsigned long val;
+	unsigned int val;
 
-	if (sscanf(buf, "%lu", &val) == 1) {
+	if (sscanf(buf, "%u", &val) == 1) {
 		if (pm_save_wakeup_count(val))
 			return n;
 	}
@@ -281,12 +281,30 @@
 }
 
 power_attr(pm_trace);
+
+static ssize_t pm_trace_dev_match_show(struct kobject *kobj,
+				       struct kobj_attribute *attr,
+				       char *buf)
+{
+	return show_trace_dev_match(buf, PAGE_SIZE);
+}
+
+static ssize_t
+pm_trace_dev_match_store(struct kobject *kobj, struct kobj_attribute *attr,
+			 const char *buf, size_t n)
+{
+	return -EINVAL;
+}
+
+power_attr(pm_trace_dev_match);
+
 #endif /* CONFIG_PM_TRACE */
 
 static struct attribute * g[] = {
 	&state_attr.attr,
 #ifdef CONFIG_PM_TRACE
 	&pm_trace_attr.attr,
+	&pm_trace_dev_match_attr.attr,
 #endif
 #ifdef CONFIG_PM_SLEEP
 	&pm_async_attr.attr,
@@ -308,7 +326,7 @@
 
 static int __init pm_start_workqueue(void)
 {
-	pm_wq = create_freezeable_workqueue("pm");
+	pm_wq = alloc_workqueue("pm", WQ_FREEZEABLE, 0);
 
 	return pm_wq ? 0 : -ENOMEM;
 }
@@ -321,6 +339,7 @@
 	int error = pm_start_workqueue();
 	if (error)
 		return error;
+	hibernate_image_size_init();
 	power_kobj = kobject_create_and_add("power", NULL);
 	if (!power_kobj)
 		return -ENOMEM;
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 006270f..03634be 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -14,6 +14,9 @@
 } __attribute__((aligned(PAGE_SIZE)));
 
 #ifdef CONFIG_HIBERNATION
+/* kernel/power/snapshot.c */
+extern void __init hibernate_image_size_init(void);
+
 #ifdef CONFIG_ARCH_HIBERNATION_HEADER
 /* Maximum size of architecture specific data in a hibernation header */
 #define MAX_ARCH_HEADER_SIZE	(sizeof(struct new_utsname) + 4)
@@ -49,7 +52,11 @@
 extern int hibernation_snapshot(int platform_mode);
 extern int hibernation_restore(int platform_mode);
 extern int hibernation_platform_enter(void);
-#endif
+
+#else /* !CONFIG_HIBERNATION */
+
+static inline void hibernate_image_size_init(void) {}
+#endif /* !CONFIG_HIBERNATION */
 
 extern int pfn_is_nosave(unsigned long);
 
@@ -134,6 +141,7 @@
  * the image header.
  */
 #define SF_PLATFORM_MODE	1
+#define SF_NOCOMPRESS_MODE	2
 
 /* kernel/power/hibernate.c */
 extern int swsusp_check(void);
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 028a995..e50b4c1 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -40,6 +40,7 @@
 	struct timeval start, end;
 	u64 elapsed_csecs64;
 	unsigned int elapsed_csecs;
+	bool wakeup = false;
 
 	do_gettimeofday(&start);
 
@@ -78,6 +79,11 @@
 		if (!todo || time_after(jiffies, end_time))
 			break;
 
+		if (!pm_check_wakeup_events()) {
+			wakeup = true;
+			break;
+		}
+
 		/*
 		 * We need to retry, but first give the freezing tasks some
 		 * time to enter the regrigerator.
@@ -97,8 +103,9 @@
 		 * but it cleans up leftover PF_FREEZE requests.
 		 */
 		printk("\n");
-		printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
+		printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds "
 		       "(%d tasks refusing to freeze, wq_busy=%d):\n",
+		       wakeup ? "aborted" : "failed",
 		       elapsed_csecs / 100, elapsed_csecs % 100,
 		       todo - wq_busy, wq_busy);
 
@@ -107,7 +114,7 @@
 		read_lock(&tasklist_lock);
 		do_each_thread(g, p) {
 			task_lock(p);
-			if (freezing(p) && !freezer_should_skip(p))
+			if (!wakeup && freezing(p) && !freezer_should_skip(p))
 				sched_show_task(p);
 			cancel_freezing(p);
 			task_unlock(p);
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index d3f795f..ac7eb10 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -46,7 +46,12 @@
  * size will not exceed N bytes, but if that is impossible, it will
  * try to create the smallest image possible.
  */
-unsigned long image_size = 500 * 1024 * 1024;
+unsigned long image_size;
+
+void __init hibernate_image_size_init(void)
+{
+	image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE;
+}
 
 /* List of PBEs needed for restoring the pages that were allocated before
  * the suspend and included in the suspend image, but have also been
@@ -1318,12 +1323,14 @@
 
 	/* Compute the maximum number of saveable pages to leave in memory. */
 	max_size = (count - (size + PAGES_FOR_IO)) / 2 - 2 * SPARE_PAGES;
+	/* Compute the desired number of image pages specified by image_size. */
 	size = DIV_ROUND_UP(image_size, PAGE_SIZE);
 	if (size > max_size)
 		size = max_size;
 	/*
-	 * If the maximum is not less than the current number of saveable pages
-	 * in memory, allocate page frames for the image and we're done.
+	 * If the desired number of image pages is at least as large as the
+	 * current number of saveable pages in memory, allocate page frames for
+	 * the image and we're done.
 	 */
 	if (size >= saveable) {
 		pages = preallocate_image_highmem(save_highmem);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index e6a5bdf..916eaa7 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -24,10 +24,12 @@
 #include <linux/swapops.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
+#include <linux/lzo.h>
+#include <linux/vmalloc.h>
 
 #include "power.h"
 
-#define SWSUSP_SIG	"S1SUSPEND"
+#define HIBERNATE_SIG	"LINHIB0001"
 
 /*
  *	The swap map is a data structure used for keeping track of each page
@@ -193,7 +195,7 @@
 	if (!memcmp("SWAP-SPACE",swsusp_header->sig, 10) ||
 	    !memcmp("SWAPSPACE2",swsusp_header->sig, 10)) {
 		memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
-		memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
+		memcpy(swsusp_header->sig, HIBERNATE_SIG, 10);
 		swsusp_header->image = handle->first_sector;
 		swsusp_header->flags = flags;
 		error = hib_bio_write_page(swsusp_resume_block,
@@ -357,6 +359,18 @@
 	return error;
 }
 
+/* We need to remember how much compressed data we need to read. */
+#define LZO_HEADER	sizeof(size_t)
+
+/* Number of pages/bytes we'll compress at one time. */
+#define LZO_UNC_PAGES	32
+#define LZO_UNC_SIZE	(LZO_UNC_PAGES * PAGE_SIZE)
+
+/* Number of pages/bytes we need for compressed data (worst case). */
+#define LZO_CMP_PAGES	DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \
+			             LZO_HEADER, PAGE_SIZE)
+#define LZO_CMP_SIZE	(LZO_CMP_PAGES * PAGE_SIZE)
+
 /**
  *	save_image - save the suspend image data
  */
@@ -404,6 +418,137 @@
 	return ret;
 }
 
+
+/**
+ * save_image_lzo - Save the suspend image data compressed with LZO.
+ * @handle: Swap mam handle to use for saving the image.
+ * @snapshot: Image to read data from.
+ * @nr_to_write: Number of pages to save.
+ */
+static int save_image_lzo(struct swap_map_handle *handle,
+                          struct snapshot_handle *snapshot,
+                          unsigned int nr_to_write)
+{
+	unsigned int m;
+	int ret = 0;
+	int nr_pages;
+	int err2;
+	struct bio *bio;
+	struct timeval start;
+	struct timeval stop;
+	size_t off, unc_len, cmp_len;
+	unsigned char *unc, *cmp, *wrk, *page;
+
+	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+	if (!page) {
+		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
+		return -ENOMEM;
+	}
+
+	wrk = vmalloc(LZO1X_1_MEM_COMPRESS);
+	if (!wrk) {
+		printk(KERN_ERR "PM: Failed to allocate LZO workspace\n");
+		free_page((unsigned long)page);
+		return -ENOMEM;
+	}
+
+	unc = vmalloc(LZO_UNC_SIZE);
+	if (!unc) {
+		printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
+		vfree(wrk);
+		free_page((unsigned long)page);
+		return -ENOMEM;
+	}
+
+	cmp = vmalloc(LZO_CMP_SIZE);
+	if (!cmp) {
+		printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
+		vfree(unc);
+		vfree(wrk);
+		free_page((unsigned long)page);
+		return -ENOMEM;
+	}
+
+	printk(KERN_INFO
+		"PM: Compressing and saving image data (%u pages) ...     ",
+		nr_to_write);
+	m = nr_to_write / 100;
+	if (!m)
+		m = 1;
+	nr_pages = 0;
+	bio = NULL;
+	do_gettimeofday(&start);
+	for (;;) {
+		for (off = 0; off < LZO_UNC_SIZE; off += PAGE_SIZE) {
+			ret = snapshot_read_next(snapshot);
+			if (ret < 0)
+				goto out_finish;
+
+			if (!ret)
+				break;
+
+			memcpy(unc + off, data_of(*snapshot), PAGE_SIZE);
+
+			if (!(nr_pages % m))
+				printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
+			nr_pages++;
+		}
+
+		if (!off)
+			break;
+
+		unc_len = off;
+		ret = lzo1x_1_compress(unc, unc_len,
+		                       cmp + LZO_HEADER, &cmp_len, wrk);
+		if (ret < 0) {
+			printk(KERN_ERR "PM: LZO compression failed\n");
+			break;
+		}
+
+		if (unlikely(!cmp_len ||
+		             cmp_len > lzo1x_worst_compress(unc_len))) {
+			printk(KERN_ERR "PM: Invalid LZO compressed length\n");
+			ret = -1;
+			break;
+		}
+
+		*(size_t *)cmp = cmp_len;
+
+		/*
+		 * Given we are writing one page at a time to disk, we copy
+		 * that much from the buffer, although the last bit will likely
+		 * be smaller than full page. This is OK - we saved the length
+		 * of the compressed data, so any garbage at the end will be
+		 * discarded when we read it.
+		 */
+		for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
+			memcpy(page, cmp + off, PAGE_SIZE);
+
+			ret = swap_write_page(handle, page, &bio);
+			if (ret)
+				goto out_finish;
+		}
+	}
+
+out_finish:
+	err2 = hib_wait_on_bio_chain(&bio);
+	do_gettimeofday(&stop);
+	if (!ret)
+		ret = err2;
+	if (!ret)
+		printk(KERN_CONT "\b\b\b\bdone\n");
+	else
+		printk(KERN_CONT "\n");
+	swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
+
+	vfree(cmp);
+	vfree(unc);
+	vfree(wrk);
+	free_page((unsigned long)page);
+
+	return ret;
+}
+
 /**
  *	enough_swap - Make sure we have enough swap to save the image.
  *
@@ -411,12 +556,16 @@
  *	space avaiable from the resume partition.
  */
 
-static int enough_swap(unsigned int nr_pages)
+static int enough_swap(unsigned int nr_pages, unsigned int flags)
 {
 	unsigned int free_swap = count_swap_pages(root_swap, 1);
+	unsigned int required;
 
 	pr_debug("PM: Free swap pages: %u\n", free_swap);
-	return free_swap > nr_pages + PAGES_FOR_IO;
+
+	required = PAGES_FOR_IO + ((flags & SF_NOCOMPRESS_MODE) ?
+		nr_pages : (nr_pages * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1);
+	return free_swap > required;
 }
 
 /**
@@ -443,7 +592,7 @@
 		printk(KERN_ERR "PM: Cannot get swap writer\n");
 		return error;
 	}
-	if (!enough_swap(pages)) {
+	if (!enough_swap(pages, flags)) {
 		printk(KERN_ERR "PM: Not enough free swap\n");
 		error = -ENOSPC;
 		goto out_finish;
@@ -458,8 +607,11 @@
 	}
 	header = (struct swsusp_info *)data_of(snapshot);
 	error = swap_write_page(&handle, header, NULL);
-	if (!error)
-		error = save_image(&handle, &snapshot, pages - 1);
+	if (!error) {
+		error = (flags & SF_NOCOMPRESS_MODE) ?
+			save_image(&handle, &snapshot, pages - 1) :
+			save_image_lzo(&handle, &snapshot, pages - 1);
+	}
 out_finish:
 	error = swap_writer_finish(&handle, flags, error);
 	return error;
@@ -590,6 +742,127 @@
 }
 
 /**
+ * load_image_lzo - Load compressed image data and decompress them with LZO.
+ * @handle: Swap map handle to use for loading data.
+ * @snapshot: Image to copy uncompressed data into.
+ * @nr_to_read: Number of pages to load.
+ */
+static int load_image_lzo(struct swap_map_handle *handle,
+                          struct snapshot_handle *snapshot,
+                          unsigned int nr_to_read)
+{
+	unsigned int m;
+	int error = 0;
+	struct timeval start;
+	struct timeval stop;
+	unsigned nr_pages;
+	size_t off, unc_len, cmp_len;
+	unsigned char *unc, *cmp, *page;
+
+	page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
+	if (!page) {
+		printk(KERN_ERR "PM: Failed to allocate LZO page\n");
+		return -ENOMEM;
+	}
+
+	unc = vmalloc(LZO_UNC_SIZE);
+	if (!unc) {
+		printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n");
+		free_page((unsigned long)page);
+		return -ENOMEM;
+	}
+
+	cmp = vmalloc(LZO_CMP_SIZE);
+	if (!cmp) {
+		printk(KERN_ERR "PM: Failed to allocate LZO compressed\n");
+		vfree(unc);
+		free_page((unsigned long)page);
+		return -ENOMEM;
+	}
+
+	printk(KERN_INFO
+		"PM: Loading and decompressing image data (%u pages) ...     ",
+		nr_to_read);
+	m = nr_to_read / 100;
+	if (!m)
+		m = 1;
+	nr_pages = 0;
+	do_gettimeofday(&start);
+
+	error = snapshot_write_next(snapshot);
+	if (error <= 0)
+		goto out_finish;
+
+	for (;;) {
+		error = swap_read_page(handle, page, NULL); /* sync */
+		if (error)
+			break;
+
+		cmp_len = *(size_t *)page;
+		if (unlikely(!cmp_len ||
+		             cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) {
+			printk(KERN_ERR "PM: Invalid LZO compressed length\n");
+			error = -1;
+			break;
+		}
+
+		memcpy(cmp, page, PAGE_SIZE);
+		for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) {
+			error = swap_read_page(handle, page, NULL); /* sync */
+			if (error)
+				goto out_finish;
+
+			memcpy(cmp + off, page, PAGE_SIZE);
+		}
+
+		unc_len = LZO_UNC_SIZE;
+		error = lzo1x_decompress_safe(cmp + LZO_HEADER, cmp_len,
+		                              unc, &unc_len);
+		if (error < 0) {
+			printk(KERN_ERR "PM: LZO decompression failed\n");
+			break;
+		}
+
+		if (unlikely(!unc_len ||
+		             unc_len > LZO_UNC_SIZE ||
+		             unc_len & (PAGE_SIZE - 1))) {
+			printk(KERN_ERR "PM: Invalid LZO uncompressed length\n");
+			error = -1;
+			break;
+		}
+
+		for (off = 0; off < unc_len; off += PAGE_SIZE) {
+			memcpy(data_of(*snapshot), unc + off, PAGE_SIZE);
+
+			if (!(nr_pages % m))
+				printk("\b\b\b\b%3d%%", nr_pages / m);
+			nr_pages++;
+
+			error = snapshot_write_next(snapshot);
+			if (error <= 0)
+				goto out_finish;
+		}
+	}
+
+out_finish:
+	do_gettimeofday(&stop);
+	if (!error) {
+		printk("\b\b\b\bdone\n");
+		snapshot_write_finalize(snapshot);
+		if (!snapshot_image_loaded(snapshot))
+			error = -ENODATA;
+	} else
+		printk("\n");
+	swsusp_show_speed(&start, &stop, nr_to_read, "Read");
+
+	vfree(cmp);
+	vfree(unc);
+	free_page((unsigned long)page);
+
+	return error;
+}
+
+/**
  *	swsusp_read - read the hibernation image.
  *	@flags_p: flags passed by the "frozen" kernel in the image header should
  *		  be written into this memeory location
@@ -612,8 +885,11 @@
 		goto end;
 	if (!error)
 		error = swap_read_page(&handle, header, NULL);
-	if (!error)
-		error = load_image(&handle, &snapshot, header->pages - 1);
+	if (!error) {
+		error = (*flags_p & SF_NOCOMPRESS_MODE) ?
+			load_image(&handle, &snapshot, header->pages - 1) :
+			load_image_lzo(&handle, &snapshot, header->pages - 1);
+	}
 	swap_reader_finish(&handle);
 end:
 	if (!error)
@@ -640,7 +916,7 @@
 		if (error)
 			goto put;
 
-		if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) {
+		if (!memcmp(HIBERNATE_SIG, swsusp_header->sig, 10)) {
 			memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
 			/* Reset swap signature now */
 			error = hib_bio_write_page(swsusp_resume_block,
@@ -653,13 +929,13 @@
 		if (error)
 			blkdev_put(hib_resume_bdev, FMODE_READ);
 		else
-			pr_debug("PM: Signature found, resuming\n");
+			pr_debug("PM: Image signature found, resuming\n");
 	} else {
 		error = PTR_ERR(hib_resume_bdev);
 	}
 
 	if (error)
-		pr_debug("PM: Error %d checking image file\n", error);
+		pr_debug("PM: Image not found (code %d)\n", error);
 
 	return error;
 }
diff --git a/kernel/printk.c b/kernel/printk.c
index 8fe465a..2531017 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -85,7 +85,7 @@
  * provides serialisation for access to the entire console
  * driver system.
  */
-static DECLARE_MUTEX(console_sem);
+static DEFINE_SEMAPHORE(console_sem);
 struct console *console_drivers;
 EXPORT_SYMBOL_GPL(console_drivers);
 
@@ -556,7 +556,7 @@
 	/* If a crash is occurring, make sure we can't deadlock */
 	spin_lock_init(&logbuf_lock);
 	/* And make sure that we print immediately */
-	init_MUTEX(&console_sem);
+	sema_init(&console_sem, 1);
 }
 
 #if defined(CONFIG_PRINTK_TIME)
diff --git a/kernel/profile.c b/kernel/profile.c
index b22a899..66f841b 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -555,6 +555,7 @@
 static const struct file_operations proc_profile_operations = {
 	.read		= read_profile,
 	.write		= write_profile,
+	.llseek		= default_llseek,
 };
 
 #ifdef CONFIG_SMP
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 4d16983..a23a57a 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -73,12 +73,14 @@
 EXPORT_SYMBOL_GPL(debug_lockdep_rcu_enabled);
 
 /**
- * rcu_read_lock_bh_held - might we be in RCU-bh read-side critical section?
+ * rcu_read_lock_bh_held() - might we be in RCU-bh read-side critical section?
  *
  * Check for bottom half being disabled, which covers both the
  * CONFIG_PROVE_RCU and not cases.  Note that if someone uses
  * rcu_read_lock_bh(), but then later enables BH, lockdep (if enabled)
- * will show the situation.
+ * will show the situation.  This is useful for debug checks in functions
+ * that require that they be called within an RCU read-side critical
+ * section.
  *
  * Check debug_lockdep_rcu_enabled() to prevent false positives during boot.
  */
@@ -86,7 +88,7 @@
 {
 	if (!debug_lockdep_rcu_enabled())
 		return 1;
-	return in_softirq();
+	return in_softirq() || irqs_disabled();
 }
 EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held);
 
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c
index 196ec02..d806735 100644
--- a/kernel/rcutiny.c
+++ b/kernel/rcutiny.c
@@ -59,6 +59,14 @@
 EXPORT_SYMBOL_GPL(rcu_scheduler_active);
 #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
+/* Forward declarations for rcutiny_plugin.h. */
+static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp);
+static void __call_rcu(struct rcu_head *head,
+		       void (*func)(struct rcu_head *rcu),
+		       struct rcu_ctrlblk *rcp);
+
+#include "rcutiny_plugin.h"
+
 #ifdef CONFIG_NO_HZ
 
 static long rcu_dynticks_nesting = 1;
@@ -140,6 +148,7 @@
 		rcu_sched_qs(cpu);
 	else if (!in_softirq())
 		rcu_bh_qs(cpu);
+	rcu_preempt_check_callbacks();
 }
 
 /*
@@ -162,6 +171,7 @@
 	*rcp->donetail = NULL;
 	if (rcp->curtail == rcp->donetail)
 		rcp->curtail = &rcp->rcucblist;
+	rcu_preempt_remove_callbacks(rcp);
 	rcp->donetail = &rcp->rcucblist;
 	local_irq_restore(flags);
 
@@ -182,6 +192,7 @@
 {
 	__rcu_process_callbacks(&rcu_sched_ctrlblk);
 	__rcu_process_callbacks(&rcu_bh_ctrlblk);
+	rcu_preempt_process_callbacks();
 }
 
 /*
@@ -223,15 +234,15 @@
 }
 
 /*
- * Post an RCU callback to be invoked after the end of an RCU grace
+ * Post an RCU callback to be invoked after the end of an RCU-sched grace
  * period.  But since we have but one CPU, that would be after any
  * quiescent state.
  */
-void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
+void call_rcu_sched(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
 {
 	__call_rcu(head, func, &rcu_sched_ctrlblk);
 }
-EXPORT_SYMBOL_GPL(call_rcu);
+EXPORT_SYMBOL_GPL(call_rcu_sched);
 
 /*
  * Post an RCU bottom-half callback to be invoked after any subsequent
@@ -243,20 +254,6 @@
 }
 EXPORT_SYMBOL_GPL(call_rcu_bh);
 
-void rcu_barrier(void)
-{
-	struct rcu_synchronize rcu;
-
-	init_rcu_head_on_stack(&rcu.head);
-	init_completion(&rcu.completion);
-	/* Will wake me after RCU finished. */
-	call_rcu(&rcu.head, wakeme_after_rcu);
-	/* Wait for it. */
-	wait_for_completion(&rcu.completion);
-	destroy_rcu_head_on_stack(&rcu.head);
-}
-EXPORT_SYMBOL_GPL(rcu_barrier);
-
 void rcu_barrier_bh(void)
 {
 	struct rcu_synchronize rcu;
@@ -289,5 +286,3 @@
 {
 	open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
 }
-
-#include "rcutiny_plugin.h"
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h
index d223a92bc..6ceca4f 100644
--- a/kernel/rcutiny_plugin.h
+++ b/kernel/rcutiny_plugin.h
@@ -1,7 +1,7 @@
 /*
- * Read-Copy Update mechanism for mutual exclusion (tree-based version)
+ * Read-Copy Update mechanism for mutual exclusion, the Bloatwatch edition
  * Internal non-public definitions that provide either classic
- * or preemptable semantics.
+ * or preemptible semantics.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,11 +17,587 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
- * Copyright IBM Corporation, 2009
+ * Copyright (c) 2010 Linaro
  *
  * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
  */
 
+#ifdef CONFIG_TINY_PREEMPT_RCU
+
+#include <linux/delay.h>
+
+/* Global control variables for preemptible RCU. */
+struct rcu_preempt_ctrlblk {
+	struct rcu_ctrlblk rcb;	/* curtail: ->next ptr of last CB for GP. */
+	struct rcu_head **nexttail;
+				/* Tasks blocked in a preemptible RCU */
+				/*  read-side critical section while an */
+				/*  preemptible-RCU grace period is in */
+				/*  progress must wait for a later grace */
+				/*  period.  This pointer points to the */
+				/*  ->next pointer of the last task that */
+				/*  must wait for a later grace period, or */
+				/*  to &->rcb.rcucblist if there is no */
+				/*  such task. */
+	struct list_head blkd_tasks;
+				/* Tasks blocked in RCU read-side critical */
+				/*  section.  Tasks are placed at the head */
+				/*  of this list and age towards the tail. */
+	struct list_head *gp_tasks;
+				/* Pointer to the first task blocking the */
+				/*  current grace period, or NULL if there */
+				/*  is not such task. */
+	struct list_head *exp_tasks;
+				/* Pointer to first task blocking the */
+				/*  current expedited grace period, or NULL */
+				/*  if there is no such task.  If there */
+				/*  is no current expedited grace period, */
+				/*  then there cannot be any such task. */
+	u8 gpnum;		/* Current grace period. */
+	u8 gpcpu;		/* Last grace period blocked by the CPU. */
+	u8 completed;		/* Last grace period completed. */
+				/*  If all three are equal, RCU is idle. */
+};
+
+static struct rcu_preempt_ctrlblk rcu_preempt_ctrlblk = {
+	.rcb.donetail = &rcu_preempt_ctrlblk.rcb.rcucblist,
+	.rcb.curtail = &rcu_preempt_ctrlblk.rcb.rcucblist,
+	.nexttail = &rcu_preempt_ctrlblk.rcb.rcucblist,
+	.blkd_tasks = LIST_HEAD_INIT(rcu_preempt_ctrlblk.blkd_tasks),
+};
+
+static int rcu_preempted_readers_exp(void);
+static void rcu_report_exp_done(void);
+
+/*
+ * Return true if the CPU has not yet responded to the current grace period.
+ */
+static int rcu_cpu_blocking_cur_gp(void)
+{
+	return rcu_preempt_ctrlblk.gpcpu != rcu_preempt_ctrlblk.gpnum;
+}
+
+/*
+ * Check for a running RCU reader.  Because there is only one CPU,
+ * there can be but one running RCU reader at a time.  ;-)
+ */
+static int rcu_preempt_running_reader(void)
+{
+	return current->rcu_read_lock_nesting;
+}
+
+/*
+ * Check for preempted RCU readers blocking any grace period.
+ * If the caller needs a reliable answer, it must disable hard irqs.
+ */
+static int rcu_preempt_blocked_readers_any(void)
+{
+	return !list_empty(&rcu_preempt_ctrlblk.blkd_tasks);
+}
+
+/*
+ * Check for preempted RCU readers blocking the current grace period.
+ * If the caller needs a reliable answer, it must disable hard irqs.
+ */
+static int rcu_preempt_blocked_readers_cgp(void)
+{
+	return rcu_preempt_ctrlblk.gp_tasks != NULL;
+}
+
+/*
+ * Return true if another preemptible-RCU grace period is needed.
+ */
+static int rcu_preempt_needs_another_gp(void)
+{
+	return *rcu_preempt_ctrlblk.rcb.curtail != NULL;
+}
+
+/*
+ * Return true if a preemptible-RCU grace period is in progress.
+ * The caller must disable hardirqs.
+ */
+static int rcu_preempt_gp_in_progress(void)
+{
+	return rcu_preempt_ctrlblk.completed != rcu_preempt_ctrlblk.gpnum;
+}
+
+/*
+ * Record a preemptible-RCU quiescent state for the specified CPU.  Note
+ * that this just means that the task currently running on the CPU is
+ * in a quiescent state.  There might be any number of tasks blocked
+ * while in an RCU read-side critical section.
+ *
+ * Unlike the other rcu_*_qs() functions, callers to this function
+ * must disable irqs in order to protect the assignment to
+ * ->rcu_read_unlock_special.
+ *
+ * Because this is a single-CPU implementation, the only way a grace
+ * period can end is if the CPU is in a quiescent state.  The reason is
+ * that a blocked preemptible-RCU reader can exit its critical section
+ * only if the CPU is running it at the time.  Therefore, when the
+ * last task blocking the current grace period exits its RCU read-side
+ * critical section, neither the CPU nor blocked tasks will be stopping
+ * the current grace period.  (In contrast, SMP implementations
+ * might have CPUs running in RCU read-side critical sections that
+ * block later grace periods -- but this is not possible given only
+ * one CPU.)
+ */
+static void rcu_preempt_cpu_qs(void)
+{
+	/* Record both CPU and task as having responded to current GP. */
+	rcu_preempt_ctrlblk.gpcpu = rcu_preempt_ctrlblk.gpnum;
+	current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
+
+	/*
+	 * If there is no GP, or if blocked readers are still blocking GP,
+	 * then there is nothing more to do.
+	 */
+	if (!rcu_preempt_gp_in_progress() || rcu_preempt_blocked_readers_cgp())
+		return;
+
+	/* Advance callbacks. */
+	rcu_preempt_ctrlblk.completed = rcu_preempt_ctrlblk.gpnum;
+	rcu_preempt_ctrlblk.rcb.donetail = rcu_preempt_ctrlblk.rcb.curtail;
+	rcu_preempt_ctrlblk.rcb.curtail = rcu_preempt_ctrlblk.nexttail;
+
+	/* If there are no blocked readers, next GP is done instantly. */
+	if (!rcu_preempt_blocked_readers_any())
+		rcu_preempt_ctrlblk.rcb.donetail = rcu_preempt_ctrlblk.nexttail;
+
+	/* If there are done callbacks, make RCU_SOFTIRQ process them. */
+	if (*rcu_preempt_ctrlblk.rcb.donetail != NULL)
+		raise_softirq(RCU_SOFTIRQ);
+}
+
+/*
+ * Start a new RCU grace period if warranted.  Hard irqs must be disabled.
+ */
+static void rcu_preempt_start_gp(void)
+{
+	if (!rcu_preempt_gp_in_progress() && rcu_preempt_needs_another_gp()) {
+
+		/* Official start of GP. */
+		rcu_preempt_ctrlblk.gpnum++;
+
+		/* Any blocked RCU readers block new GP. */
+		if (rcu_preempt_blocked_readers_any())
+			rcu_preempt_ctrlblk.gp_tasks =
+				rcu_preempt_ctrlblk.blkd_tasks.next;
+
+		/* If there is no running reader, CPU is done with GP. */
+		if (!rcu_preempt_running_reader())
+			rcu_preempt_cpu_qs();
+	}
+}
+
+/*
+ * We have entered the scheduler, and the current task might soon be
+ * context-switched away from.  If this task is in an RCU read-side
+ * critical section, we will no longer be able to rely on the CPU to
+ * record that fact, so we enqueue the task on the blkd_tasks list.
+ * If the task started after the current grace period began, as recorded
+ * by ->gpcpu, we enqueue at the beginning of the list.  Otherwise
+ * before the element referenced by ->gp_tasks (or at the tail if
+ * ->gp_tasks is NULL) and point ->gp_tasks at the newly added element.
+ * The task will dequeue itself when it exits the outermost enclosing
+ * RCU read-side critical section.  Therefore, the current grace period
+ * cannot be permitted to complete until the ->gp_tasks pointer becomes
+ * NULL.
+ *
+ * Caller must disable preemption.
+ */
+void rcu_preempt_note_context_switch(void)
+{
+	struct task_struct *t = current;
+	unsigned long flags;
+
+	local_irq_save(flags); /* must exclude scheduler_tick(). */
+	if (rcu_preempt_running_reader() &&
+	    (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) {
+
+		/* Possibly blocking in an RCU read-side critical section. */
+		t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED;
+
+		/*
+		 * If this CPU has already checked in, then this task
+		 * will hold up the next grace period rather than the
+		 * current grace period.  Queue the task accordingly.
+		 * If the task is queued for the current grace period
+		 * (i.e., this CPU has not yet passed through a quiescent
+		 * state for the current grace period), then as long
+		 * as that task remains queued, the current grace period
+		 * cannot end.
+		 */
+		list_add(&t->rcu_node_entry, &rcu_preempt_ctrlblk.blkd_tasks);
+		if (rcu_cpu_blocking_cur_gp())
+			rcu_preempt_ctrlblk.gp_tasks = &t->rcu_node_entry;
+	}
+
+	/*
+	 * Either we were not in an RCU read-side critical section to
+	 * begin with, or we have now recorded that critical section
+	 * globally.  Either way, we can now note a quiescent state
+	 * for this CPU.  Again, if we were in an RCU read-side critical
+	 * section, and if that critical section was blocking the current
+	 * grace period, then the fact that the task has been enqueued
+	 * means that current grace period continues to be blocked.
+	 */
+	rcu_preempt_cpu_qs();
+	local_irq_restore(flags);
+}
+
+/*
+ * Tiny-preemptible RCU implementation for rcu_read_lock().
+ * Just increment ->rcu_read_lock_nesting, shared state will be updated
+ * if we block.
+ */
+void __rcu_read_lock(void)
+{
+	current->rcu_read_lock_nesting++;
+	barrier();  /* needed if we ever invoke rcu_read_lock in rcutiny.c */
+}
+EXPORT_SYMBOL_GPL(__rcu_read_lock);
+
+/*
+ * Handle special cases during rcu_read_unlock(), such as needing to
+ * notify RCU core processing or task having blocked during the RCU
+ * read-side critical section.
+ */
+static void rcu_read_unlock_special(struct task_struct *t)
+{
+	int empty;
+	int empty_exp;
+	unsigned long flags;
+	struct list_head *np;
+	int special;
+
+	/*
+	 * NMI handlers cannot block and cannot safely manipulate state.
+	 * They therefore cannot possibly be special, so just leave.
+	 */
+	if (in_nmi())
+		return;
+
+	local_irq_save(flags);
+
+	/*
+	 * If RCU core is waiting for this CPU to exit critical section,
+	 * let it know that we have done so.
+	 */
+	special = t->rcu_read_unlock_special;
+	if (special & RCU_READ_UNLOCK_NEED_QS)
+		rcu_preempt_cpu_qs();
+
+	/* Hardware IRQ handlers cannot block. */
+	if (in_irq()) {
+		local_irq_restore(flags);
+		return;
+	}
+
+	/* Clean up if blocked during RCU read-side critical section. */
+	if (special & RCU_READ_UNLOCK_BLOCKED) {
+		t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_BLOCKED;
+
+		/*
+		 * Remove this task from the ->blkd_tasks list and adjust
+		 * any pointers that might have been referencing it.
+		 */
+		empty = !rcu_preempt_blocked_readers_cgp();
+		empty_exp = rcu_preempt_ctrlblk.exp_tasks == NULL;
+		np = t->rcu_node_entry.next;
+		if (np == &rcu_preempt_ctrlblk.blkd_tasks)
+			np = NULL;
+		list_del(&t->rcu_node_entry);
+		if (&t->rcu_node_entry == rcu_preempt_ctrlblk.gp_tasks)
+			rcu_preempt_ctrlblk.gp_tasks = np;
+		if (&t->rcu_node_entry == rcu_preempt_ctrlblk.exp_tasks)
+			rcu_preempt_ctrlblk.exp_tasks = np;
+		INIT_LIST_HEAD(&t->rcu_node_entry);
+
+		/*
+		 * If this was the last task on the current list, and if
+		 * we aren't waiting on the CPU, report the quiescent state
+		 * and start a new grace period if needed.
+		 */
+		if (!empty && !rcu_preempt_blocked_readers_cgp()) {
+			rcu_preempt_cpu_qs();
+			rcu_preempt_start_gp();
+		}
+
+		/*
+		 * If this was the last task on the expedited lists,
+		 * then we need wake up the waiting task.
+		 */
+		if (!empty_exp && rcu_preempt_ctrlblk.exp_tasks == NULL)
+			rcu_report_exp_done();
+	}
+	local_irq_restore(flags);
+}
+
+/*
+ * Tiny-preemptible RCU implementation for rcu_read_unlock().
+ * Decrement ->rcu_read_lock_nesting.  If the result is zero (outermost
+ * rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then
+ * invoke rcu_read_unlock_special() to clean up after a context switch
+ * in an RCU read-side critical section and other special cases.
+ */
+void __rcu_read_unlock(void)
+{
+	struct task_struct *t = current;
+
+	barrier();  /* needed if we ever invoke rcu_read_unlock in rcutiny.c */
+	--t->rcu_read_lock_nesting;
+	barrier();  /* decrement before load of ->rcu_read_unlock_special */
+	if (t->rcu_read_lock_nesting == 0 &&
+	    unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
+		rcu_read_unlock_special(t);
+#ifdef CONFIG_PROVE_LOCKING
+	WARN_ON_ONCE(t->rcu_read_lock_nesting < 0);
+#endif /* #ifdef CONFIG_PROVE_LOCKING */
+}
+EXPORT_SYMBOL_GPL(__rcu_read_unlock);
+
+/*
+ * Check for a quiescent state from the current CPU.  When a task blocks,
+ * the task is recorded in the rcu_preempt_ctrlblk structure, which is
+ * checked elsewhere.  This is called from the scheduling-clock interrupt.
+ *
+ * Caller must disable hard irqs.
+ */
+static void rcu_preempt_check_callbacks(void)
+{
+	struct task_struct *t = current;
+
+	if (rcu_preempt_gp_in_progress() &&
+	    (!rcu_preempt_running_reader() ||
+	     !rcu_cpu_blocking_cur_gp()))
+		rcu_preempt_cpu_qs();
+	if (&rcu_preempt_ctrlblk.rcb.rcucblist !=
+	    rcu_preempt_ctrlblk.rcb.donetail)
+		raise_softirq(RCU_SOFTIRQ);
+	if (rcu_preempt_gp_in_progress() &&
+	    rcu_cpu_blocking_cur_gp() &&
+	    rcu_preempt_running_reader())
+		t->rcu_read_unlock_special |= RCU_READ_UNLOCK_NEED_QS;
+}
+
+/*
+ * TINY_PREEMPT_RCU has an extra callback-list tail pointer to
+ * update, so this is invoked from __rcu_process_callbacks() to
+ * handle that case.  Of course, it is invoked for all flavors of
+ * RCU, but RCU callbacks can appear only on one of the lists, and
+ * neither ->nexttail nor ->donetail can possibly be NULL, so there
+ * is no need for an explicit check.
+ */
+static void rcu_preempt_remove_callbacks(struct rcu_ctrlblk *rcp)
+{
+	if (rcu_preempt_ctrlblk.nexttail == rcp->donetail)
+		rcu_preempt_ctrlblk.nexttail = &rcp->rcucblist;
+}
+
+/*
+ * Process callbacks for preemptible RCU.
+ */
+static void rcu_preempt_process_callbacks(void)
+{
+	__rcu_process_callbacks(&rcu_preempt_ctrlblk.rcb);
+}
+
+/*
+ * Queue a preemptible -RCU callback for invocation after a grace period.
+ */
+void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
+{
+	unsigned long flags;
+
+	debug_rcu_head_queue(head);
+	head->func = func;
+	head->next = NULL;
+
+	local_irq_save(flags);
+	*rcu_preempt_ctrlblk.nexttail = head;
+	rcu_preempt_ctrlblk.nexttail = &head->next;
+	rcu_preempt_start_gp();  /* checks to see if GP needed. */
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(call_rcu);
+
+void rcu_barrier(void)
+{
+	struct rcu_synchronize rcu;
+
+	init_rcu_head_on_stack(&rcu.head);
+	init_completion(&rcu.completion);
+	/* Will wake me after RCU finished. */
+	call_rcu(&rcu.head, wakeme_after_rcu);
+	/* Wait for it. */
+	wait_for_completion(&rcu.completion);
+	destroy_rcu_head_on_stack(&rcu.head);
+}
+EXPORT_SYMBOL_GPL(rcu_barrier);
+
+/*
+ * synchronize_rcu - wait until a grace period has elapsed.
+ *
+ * Control will return to the caller some time after a full grace
+ * period has elapsed, in other words after all currently executing RCU
+ * read-side critical sections have completed.  RCU read-side critical
+ * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
+ * and may be nested.
+ */
+void synchronize_rcu(void)
+{
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	if (!rcu_scheduler_active)
+		return;
+#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
+	WARN_ON_ONCE(rcu_preempt_running_reader());
+	if (!rcu_preempt_blocked_readers_any())
+		return;
+
+	/* Once we get past the fastpath checks, same code as rcu_barrier(). */
+	rcu_barrier();
+}
+EXPORT_SYMBOL_GPL(synchronize_rcu);
+
+static DECLARE_WAIT_QUEUE_HEAD(sync_rcu_preempt_exp_wq);
+static unsigned long sync_rcu_preempt_exp_count;
+static DEFINE_MUTEX(sync_rcu_preempt_exp_mutex);
+
+/*
+ * Return non-zero if there are any tasks in RCU read-side critical
+ * sections blocking the current preemptible-RCU expedited grace period.
+ * If there is no preemptible-RCU expedited grace period currently in
+ * progress, returns zero unconditionally.
+ */
+static int rcu_preempted_readers_exp(void)
+{
+	return rcu_preempt_ctrlblk.exp_tasks != NULL;
+}
+
+/*
+ * Report the exit from RCU read-side critical section for the last task
+ * that queued itself during or before the current expedited preemptible-RCU
+ * grace period.
+ */
+static void rcu_report_exp_done(void)
+{
+	wake_up(&sync_rcu_preempt_exp_wq);
+}
+
+/*
+ * Wait for an rcu-preempt grace period, but expedite it.  The basic idea
+ * is to rely in the fact that there is but one CPU, and that it is
+ * illegal for a task to invoke synchronize_rcu_expedited() while in a
+ * preemptible-RCU read-side critical section.  Therefore, any such
+ * critical sections must correspond to blocked tasks, which must therefore
+ * be on the ->blkd_tasks list.  So just record the current head of the
+ * list in the ->exp_tasks pointer, and wait for all tasks including and
+ * after the task pointed to by ->exp_tasks to drain.
+ */
+void synchronize_rcu_expedited(void)
+{
+	unsigned long flags;
+	struct rcu_preempt_ctrlblk *rpcp = &rcu_preempt_ctrlblk;
+	unsigned long snap;
+
+	barrier(); /* ensure prior action seen before grace period. */
+
+	WARN_ON_ONCE(rcu_preempt_running_reader());
+
+	/*
+	 * Acquire lock so that there is only one preemptible RCU grace
+	 * period in flight.  Of course, if someone does the expedited
+	 * grace period for us while we are acquiring the lock, just leave.
+	 */
+	snap = sync_rcu_preempt_exp_count + 1;
+	mutex_lock(&sync_rcu_preempt_exp_mutex);
+	if (ULONG_CMP_LT(snap, sync_rcu_preempt_exp_count))
+		goto unlock_mb_ret; /* Others did our work for us. */
+
+	local_irq_save(flags);
+
+	/*
+	 * All RCU readers have to already be on blkd_tasks because
+	 * we cannot legally be executing in an RCU read-side critical
+	 * section.
+	 */
+
+	/* Snapshot current head of ->blkd_tasks list. */
+	rpcp->exp_tasks = rpcp->blkd_tasks.next;
+	if (rpcp->exp_tasks == &rpcp->blkd_tasks)
+		rpcp->exp_tasks = NULL;
+	local_irq_restore(flags);
+
+	/* Wait for tail of ->blkd_tasks list to drain. */
+	if (rcu_preempted_readers_exp())
+		wait_event(sync_rcu_preempt_exp_wq,
+			   !rcu_preempted_readers_exp());
+
+	/* Clean up and exit. */
+	barrier(); /* ensure expedited GP seen before counter increment. */
+	sync_rcu_preempt_exp_count++;
+unlock_mb_ret:
+	mutex_unlock(&sync_rcu_preempt_exp_mutex);
+	barrier(); /* ensure subsequent action seen after grace period. */
+}
+EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
+
+/*
+ * Does preemptible RCU need the CPU to stay out of dynticks mode?
+ */
+int rcu_preempt_needs_cpu(void)
+{
+	if (!rcu_preempt_running_reader())
+		rcu_preempt_cpu_qs();
+	return rcu_preempt_ctrlblk.rcb.rcucblist != NULL;
+}
+
+/*
+ * Check for a task exiting while in a preemptible -RCU read-side
+ * critical section, clean up if so.  No need to issue warnings,
+ * as debug_check_no_locks_held() already does this if lockdep
+ * is enabled.
+ */
+void exit_rcu(void)
+{
+	struct task_struct *t = current;
+
+	if (t->rcu_read_lock_nesting == 0)
+		return;
+	t->rcu_read_lock_nesting = 1;
+	rcu_read_unlock();
+}
+
+#else /* #ifdef CONFIG_TINY_PREEMPT_RCU */
+
+/*
+ * Because preemptible RCU does not exist, it never has any callbacks
+ * to check.
+ */
+static void rcu_preempt_check_callbacks(void)
+{
+}
+
+/*
+ * Because preemptible RCU does not exist, it never has any callbacks
+ * to remove.
+ */
+static void rcu_preempt_remove_callbacks(struct rcu_ctrlblk *rcp)
+{
+}
+
+/*
+ * Because preemptible RCU does not exist, it never has any callbacks
+ * to process.
+ */
+static void rcu_preempt_process_callbacks(void)
+{
+}
+
+#endif /* #else #ifdef CONFIG_TINY_PREEMPT_RCU */
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 
 #include <linux/kernel_stat.h>
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 2e2726d..9d8e8fb 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -120,7 +120,7 @@
 };
 
 static LIST_HEAD(rcu_torture_freelist);
-static struct rcu_torture *rcu_torture_current;
+static struct rcu_torture __rcu *rcu_torture_current;
 static long rcu_torture_current_version;
 static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
 static DEFINE_SPINLOCK(rcu_torture_lock);
@@ -153,8 +153,10 @@
 #define FULLSTOP_SHUTDOWN 1	/* System shutdown with rcutorture running. */
 #define FULLSTOP_RMMOD    2	/* Normal rmmod of rcutorture. */
 static int fullstop = FULLSTOP_RMMOD;
-DEFINE_MUTEX(fullstop_mutex);	/* Protect fullstop transitions and spawning */
-				/*  of kthreads. */
+/*
+ * Protect fullstop transitions and spawning of kthreads.
+ */
+static DEFINE_MUTEX(fullstop_mutex);
 
 /*
  * Detect and respond to a system shutdown.
@@ -303,6 +305,10 @@
 		mdelay(longdelay_ms);
 	if (!(rcu_random(rrsp) % (nrealreaders * 2 * shortdelay_us)))
 		udelay(shortdelay_us);
+#ifdef CONFIG_PREEMPT
+	if (!preempt_count() && !(rcu_random(rrsp) % (nrealreaders * 20000)))
+		preempt_schedule();  /* No QS if preempt_disable() in effect */
+#endif
 }
 
 static void rcu_torture_read_unlock(int idx) __releases(RCU)
@@ -536,6 +542,8 @@
 	delay = rcu_random(rrsp) % (nrealreaders * 2 * longdelay * uspertick);
 	if (!delay)
 		schedule_timeout_interruptible(longdelay);
+	else
+		rcu_read_delay(rrsp);
 }
 
 static void srcu_torture_read_unlock(int idx) __releases(&srcu_ctl)
@@ -731,7 +739,8 @@
 			continue;
 		rp->rtort_pipe_count = 0;
 		udelay(rcu_random(&rand) & 0x3ff);
-		old_rp = rcu_torture_current;
+		old_rp = rcu_dereference_check(rcu_torture_current,
+					       current == writer_task);
 		rp->rtort_mbtest = 1;
 		rcu_assign_pointer(rcu_torture_current, rp);
 		smp_wmb(); /* Mods to old_rp must follow rcu_assign_pointer() */
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index d5bc439..ccdc04c 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -143,6 +143,11 @@
 module_param(qhimark, int, 0);
 module_param(qlowmark, int, 0);
 
+#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
+int rcu_cpu_stall_suppress __read_mostly = RCU_CPU_STALL_SUPPRESS_INIT;
+module_param(rcu_cpu_stall_suppress, int, 0644);
+#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
+
 static void force_quiescent_state(struct rcu_state *rsp, int relaxed);
 static int rcu_pending(int cpu);
 
@@ -450,7 +455,7 @@
 
 #ifdef CONFIG_RCU_CPU_STALL_DETECTOR
 
-int rcu_cpu_stall_panicking __read_mostly;
+int rcu_cpu_stall_suppress __read_mostly;
 
 static void record_gp_stall_check_time(struct rcu_state *rsp)
 {
@@ -482,8 +487,11 @@
 	rcu_print_task_stall(rnp);
 	raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
-	/* OK, time to rat on our buddy... */
-
+	/*
+	 * OK, time to rat on our buddy...
+	 * See Documentation/RCU/stallwarn.txt for info on how to debug
+	 * RCU CPU stall warnings.
+	 */
 	printk(KERN_ERR "INFO: %s detected stalls on CPUs/tasks: {",
 	       rsp->name);
 	rcu_for_each_leaf_node(rsp, rnp) {
@@ -512,6 +520,11 @@
 	unsigned long flags;
 	struct rcu_node *rnp = rcu_get_root(rsp);
 
+	/*
+	 * OK, time to rat on ourselves...
+	 * See Documentation/RCU/stallwarn.txt for info on how to debug
+	 * RCU CPU stall warnings.
+	 */
 	printk(KERN_ERR "INFO: %s detected stall on CPU %d (t=%lu jiffies)\n",
 	       rsp->name, smp_processor_id(), jiffies - rsp->gp_start);
 	trigger_all_cpu_backtrace();
@@ -530,11 +543,11 @@
 	long delta;
 	struct rcu_node *rnp;
 
-	if (rcu_cpu_stall_panicking)
+	if (rcu_cpu_stall_suppress)
 		return;
-	delta = jiffies - rsp->jiffies_stall;
+	delta = jiffies - ACCESS_ONCE(rsp->jiffies_stall);
 	rnp = rdp->mynode;
-	if ((rnp->qsmask & rdp->grpmask) && delta >= 0) {
+	if ((ACCESS_ONCE(rnp->qsmask) & rdp->grpmask) && delta >= 0) {
 
 		/* We haven't checked in, so go dump stack. */
 		print_cpu_stall(rsp);
@@ -548,10 +561,26 @@
 
 static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)
 {
-	rcu_cpu_stall_panicking = 1;
+	rcu_cpu_stall_suppress = 1;
 	return NOTIFY_DONE;
 }
 
+/**
+ * rcu_cpu_stall_reset - prevent further stall warnings in current grace period
+ *
+ * Set the stall-warning timeout way off into the future, thus preventing
+ * any RCU CPU stall-warning messages from appearing in the current set of
+ * RCU grace periods.
+ *
+ * The caller must disable hard irqs.
+ */
+void rcu_cpu_stall_reset(void)
+{
+	rcu_sched_state.jiffies_stall = jiffies + ULONG_MAX / 2;
+	rcu_bh_state.jiffies_stall = jiffies + ULONG_MAX / 2;
+	rcu_preempt_stall_reset();
+}
+
 static struct notifier_block rcu_panic_block = {
 	.notifier_call = rcu_panic,
 };
@@ -571,6 +600,10 @@
 {
 }
 
+void rcu_cpu_stall_reset(void)
+{
+}
+
 static void __init check_cpu_stall_init(void)
 {
 }
@@ -712,7 +745,7 @@
 rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
 	__releases(rcu_get_root(rsp)->lock)
 {
-	struct rcu_data *rdp = rsp->rda[smp_processor_id()];
+	struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
 	struct rcu_node *rnp = rcu_get_root(rsp);
 
 	if (!cpu_needs_another_gp(rsp, rdp) || rsp->fqs_active) {
@@ -960,7 +993,7 @@
 static void rcu_send_cbs_to_orphanage(struct rcu_state *rsp)
 {
 	int i;
-	struct rcu_data *rdp = rsp->rda[smp_processor_id()];
+	struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
 
 	if (rdp->nxtlist == NULL)
 		return;  /* irqs disabled, so comparison is stable. */
@@ -971,6 +1004,7 @@
 	for (i = 0; i < RCU_NEXT_SIZE; i++)
 		rdp->nxttail[i] = &rdp->nxtlist;
 	rsp->orphan_qlen += rdp->qlen;
+	rdp->n_cbs_orphaned += rdp->qlen;
 	rdp->qlen = 0;
 	raw_spin_unlock(&rsp->onofflock);  /* irqs remain disabled. */
 }
@@ -984,7 +1018,7 @@
 	struct rcu_data *rdp;
 
 	raw_spin_lock_irqsave(&rsp->onofflock, flags);
-	rdp = rsp->rda[smp_processor_id()];
+	rdp = this_cpu_ptr(rsp->rda);
 	if (rsp->orphan_cbs_list == NULL) {
 		raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
 		return;
@@ -992,6 +1026,7 @@
 	*rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_cbs_list;
 	rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_cbs_tail;
 	rdp->qlen += rsp->orphan_qlen;
+	rdp->n_cbs_adopted += rsp->orphan_qlen;
 	rsp->orphan_cbs_list = NULL;
 	rsp->orphan_cbs_tail = &rsp->orphan_cbs_list;
 	rsp->orphan_qlen = 0;
@@ -1007,7 +1042,7 @@
 	unsigned long flags;
 	unsigned long mask;
 	int need_report = 0;
-	struct rcu_data *rdp = rsp->rda[cpu];
+	struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
 	struct rcu_node *rnp;
 
 	/* Exclude any attempts to start a new grace period. */
@@ -1123,6 +1158,7 @@
 
 	/* Update count, and requeue any remaining callbacks. */
 	rdp->qlen -= count;
+	rdp->n_cbs_invoked += count;
 	if (list != NULL) {
 		*tail = rdp->nxtlist;
 		rdp->nxtlist = list;
@@ -1226,7 +1262,8 @@
 		cpu = rnp->grplo;
 		bit = 1;
 		for (; cpu <= rnp->grphi; cpu++, bit <<= 1) {
-			if ((rnp->qsmask & bit) != 0 && f(rsp->rda[cpu]))
+			if ((rnp->qsmask & bit) != 0 &&
+			    f(per_cpu_ptr(rsp->rda, cpu)))
 				mask |= bit;
 		}
 		if (mask != 0) {
@@ -1402,7 +1439,7 @@
 	 * a quiescent state betweentimes.
 	 */
 	local_irq_save(flags);
-	rdp = rsp->rda[smp_processor_id()];
+	rdp = this_cpu_ptr(rsp->rda);
 	rcu_process_gp_end(rsp, rdp);
 	check_for_new_grace_period(rsp, rdp);
 
@@ -1701,7 +1738,7 @@
 {
 	unsigned long flags;
 	int i;
-	struct rcu_data *rdp = rsp->rda[cpu];
+	struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
 	struct rcu_node *rnp = rcu_get_root(rsp);
 
 	/* Set up local state, ensuring consistent view of global state. */
@@ -1729,7 +1766,7 @@
 {
 	unsigned long flags;
 	unsigned long mask;
-	struct rcu_data *rdp = rsp->rda[cpu];
+	struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
 	struct rcu_node *rnp = rcu_get_root(rsp);
 
 	/* Set up local state, ensuring consistent view of global state. */
@@ -1865,7 +1902,8 @@
 /*
  * Helper function for rcu_init() that initializes one rcu_state structure.
  */
-static void __init rcu_init_one(struct rcu_state *rsp)
+static void __init rcu_init_one(struct rcu_state *rsp,
+		struct rcu_data __percpu *rda)
 {
 	static char *buf[] = { "rcu_node_level_0",
 			       "rcu_node_level_1",
@@ -1918,37 +1956,23 @@
 		}
 	}
 
+	rsp->rda = rda;
 	rnp = rsp->level[NUM_RCU_LVLS - 1];
 	for_each_possible_cpu(i) {
 		while (i > rnp->grphi)
 			rnp++;
-		rsp->rda[i]->mynode = rnp;
+		per_cpu_ptr(rsp->rda, i)->mynode = rnp;
 		rcu_boot_init_percpu_data(i, rsp);
 	}
 }
 
-/*
- * Helper macro for __rcu_init() and __rcu_init_preempt().  To be used
- * nowhere else!  Assigns leaf node pointers into each CPU's rcu_data
- * structure.
- */
-#define RCU_INIT_FLAVOR(rsp, rcu_data) \
-do { \
-	int i; \
-	\
-	for_each_possible_cpu(i) { \
-		(rsp)->rda[i] = &per_cpu(rcu_data, i); \
-	} \
-	rcu_init_one(rsp); \
-} while (0)
-
 void __init rcu_init(void)
 {
 	int cpu;
 
 	rcu_bootup_announce();
-	RCU_INIT_FLAVOR(&rcu_sched_state, rcu_sched_data);
-	RCU_INIT_FLAVOR(&rcu_bh_state, rcu_bh_data);
+	rcu_init_one(&rcu_sched_state, &rcu_sched_data);
+	rcu_init_one(&rcu_bh_state, &rcu_bh_data);
 	__rcu_init_preempt();
 	open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
 
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index 14c040b..91d4170 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -202,6 +202,9 @@
 	long		qlen;		/* # of queued callbacks */
 	long		qlen_last_fqs_check;
 					/* qlen at last check for QS forcing */
+	unsigned long	n_cbs_invoked;	/* count of RCU cbs invoked. */
+	unsigned long	n_cbs_orphaned;	/* RCU cbs sent to orphanage. */
+	unsigned long	n_cbs_adopted;	/* RCU cbs adopted from orphanage. */
 	unsigned long	n_force_qs_snap;
 					/* did other CPU force QS recently? */
 	long		blimit;		/* Upper limit on a processed batch */
@@ -254,19 +257,23 @@
 #define RCU_STALL_DELAY_DELTA	       0
 #endif
 
-#define RCU_SECONDS_TILL_STALL_CHECK   (10 * HZ + RCU_STALL_DELAY_DELTA)
+#define RCU_SECONDS_TILL_STALL_CHECK   (CONFIG_RCU_CPU_STALL_TIMEOUT * HZ + \
+					RCU_STALL_DELAY_DELTA)
 						/* for rsp->jiffies_stall */
-#define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ + RCU_STALL_DELAY_DELTA)
+#define RCU_SECONDS_TILL_STALL_RECHECK (3 * RCU_SECONDS_TILL_STALL_CHECK + 30)
 						/* for rsp->jiffies_stall */
 #define RCU_STALL_RAT_DELAY		2	/* Allow other CPUs time */
 						/*  to take at least one */
 						/*  scheduling clock irq */
 						/*  before ratting on them. */
 
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
+#ifdef CONFIG_RCU_CPU_STALL_DETECTOR_RUNNABLE
+#define RCU_CPU_STALL_SUPPRESS_INIT 0
+#else
+#define RCU_CPU_STALL_SUPPRESS_INIT 1
+#endif
 
-#define ULONG_CMP_GE(a, b)	(ULONG_MAX / 2 >= (a) - (b))
-#define ULONG_CMP_LT(a, b)	(ULONG_MAX / 2 < (a) - (b))
+#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
 /*
  * RCU global state, including node hierarchy.  This hierarchy is
@@ -283,7 +290,7 @@
 	struct rcu_node *level[NUM_RCU_LVLS];	/* Hierarchy levels. */
 	u32 levelcnt[MAX_RCU_LVLS + 1];		/* # nodes in each level. */
 	u8 levelspread[NUM_RCU_LVLS];		/* kids/node in each level. */
-	struct rcu_data *rda[NR_CPUS];		/* array of rdp pointers. */
+	struct rcu_data __percpu *rda;		/* pointer of percu rcu_data. */
 
 	/* The following fields are guarded by the root rcu_node's lock. */
 
@@ -365,6 +372,7 @@
 #ifdef CONFIG_RCU_CPU_STALL_DETECTOR
 static void rcu_print_detail_task_stall(struct rcu_state *rsp);
 static void rcu_print_task_stall(struct rcu_node *rnp);
+static void rcu_preempt_stall_reset(void);
 #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 0e4f420..71a4147 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -57,7 +57,7 @@
 	printk(KERN_INFO
 	       "\tRCU-based detection of stalled CPUs is disabled.\n");
 #endif
-#ifndef CONFIG_RCU_CPU_STALL_VERBOSE
+#if defined(CONFIG_TREE_PREEMPT_RCU) && !defined(CONFIG_RCU_CPU_STALL_VERBOSE)
 	printk(KERN_INFO "\tVerbose stalled-CPUs detection is disabled.\n");
 #endif
 #if NUM_RCU_LVL_4 != 0
@@ -154,7 +154,7 @@
 	    (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) {
 
 		/* Possibly blocking in an RCU read-side critical section. */
-		rdp = rcu_preempt_state.rda[cpu];
+		rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu);
 		rnp = rdp->mynode;
 		raw_spin_lock_irqsave(&rnp->lock, flags);
 		t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED;
@@ -201,7 +201,7 @@
  */
 void __rcu_read_lock(void)
 {
-	ACCESS_ONCE(current->rcu_read_lock_nesting)++;
+	current->rcu_read_lock_nesting++;
 	barrier();  /* needed if we ever invoke rcu_read_lock in rcutree.c */
 }
 EXPORT_SYMBOL_GPL(__rcu_read_lock);
@@ -344,7 +344,9 @@
 	struct task_struct *t = current;
 
 	barrier();  /* needed if we ever invoke rcu_read_unlock in rcutree.c */
-	if (--ACCESS_ONCE(t->rcu_read_lock_nesting) == 0 &&
+	--t->rcu_read_lock_nesting;
+	barrier();  /* decrement before load of ->rcu_read_unlock_special */
+	if (t->rcu_read_lock_nesting == 0 &&
 	    unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
 		rcu_read_unlock_special(t);
 #ifdef CONFIG_PROVE_LOCKING
@@ -417,6 +419,16 @@
 	}
 }
 
+/*
+ * Suppress preemptible RCU's CPU stall warnings by pushing the
+ * time of the next stall-warning message comfortably far into the
+ * future.
+ */
+static void rcu_preempt_stall_reset(void)
+{
+	rcu_preempt_state.jiffies_stall = jiffies + ULONG_MAX / 2;
+}
+
 #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
 /*
@@ -546,9 +558,11 @@
  *
  * Control will return to the caller some time after a full grace
  * period has elapsed, in other words after all currently executing RCU
- * read-side critical sections have completed.  RCU read-side critical
- * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
- * and may be nested.
+ * read-side critical sections have completed.  Note, however, that
+ * upon return from synchronize_rcu(), the caller might well be executing
+ * concurrently with new RCU read-side critical sections that began while
+ * synchronize_rcu() was waiting.  RCU read-side critical sections are
+ * delimited by rcu_read_lock() and rcu_read_unlock(), and may be nested.
  */
 void synchronize_rcu(void)
 {
@@ -771,7 +785,7 @@
  */
 static void __init __rcu_init_preempt(void)
 {
-	RCU_INIT_FLAVOR(&rcu_preempt_state, rcu_preempt_data);
+	rcu_init_one(&rcu_preempt_state, &rcu_preempt_data);
 }
 
 /*
@@ -865,6 +879,14 @@
 {
 }
 
+/*
+ * Because preemptible RCU does not exist, there is no need to suppress
+ * its CPU stall warnings.
+ */
+static void rcu_preempt_stall_reset(void)
+{
+}
+
 #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
 /*
@@ -919,15 +941,6 @@
 }
 
 /*
- * In classic RCU, call_rcu() is just call_rcu_sched().
- */
-void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
-{
-	call_rcu_sched(head, func);
-}
-EXPORT_SYMBOL_GPL(call_rcu);
-
-/*
  * Wait for an rcu-preempt grace period, but make it happen quickly.
  * But because preemptable RCU does not exist, map to rcu-sched.
  */
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index 36c95b4..d15430b 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -64,7 +64,9 @@
 		   rdp->dynticks_fqs);
 #endif /* #ifdef CONFIG_NO_HZ */
 	seq_printf(m, " of=%lu ri=%lu", rdp->offline_fqs, rdp->resched_ipi);
-	seq_printf(m, " ql=%ld b=%ld\n", rdp->qlen, rdp->blimit);
+	seq_printf(m, " ql=%ld b=%ld", rdp->qlen, rdp->blimit);
+	seq_printf(m, " ci=%lu co=%lu ca=%lu\n",
+		   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
 
 #define PRINT_RCU_DATA(name, func, m) \
@@ -119,7 +121,9 @@
 		   rdp->dynticks_fqs);
 #endif /* #ifdef CONFIG_NO_HZ */
 	seq_printf(m, ",%lu,%lu", rdp->offline_fqs, rdp->resched_ipi);
-	seq_printf(m, ",%ld,%ld\n", rdp->qlen, rdp->blimit);
+	seq_printf(m, ",%ld,%ld", rdp->qlen, rdp->blimit);
+	seq_printf(m, ",%lu,%lu,%lu\n",
+		   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
 
 static int show_rcudata_csv(struct seq_file *m, void *unused)
@@ -128,7 +132,7 @@
 #ifdef CONFIG_NO_HZ
 	seq_puts(m, "\"dt\",\"dt nesting\",\"dn\",\"df\",");
 #endif /* #ifdef CONFIG_NO_HZ */
-	seq_puts(m, "\"of\",\"ri\",\"ql\",\"b\"\n");
+	seq_puts(m, "\"of\",\"ri\",\"ql\",\"b\",\"ci\",\"co\",\"ca\"\n");
 #ifdef CONFIG_TREE_PREEMPT_RCU
 	seq_puts(m, "\"rcu_preempt:\"\n");
 	PRINT_RCU_DATA(rcu_preempt_data, print_one_rcu_data_csv, m);
@@ -262,7 +266,7 @@
 	struct rcu_data *rdp;
 
 	for_each_possible_cpu(cpu) {
-		rdp = rsp->rda[cpu];
+		rdp = per_cpu_ptr(rsp->rda, cpu);
 		if (rdp->beenonline)
 			print_one_rcu_pending(m, rdp);
 	}
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
index a56f629..66cb89b 100644
--- a/kernel/rtmutex-tester.c
+++ b/kernel/rtmutex-tester.c
@@ -76,7 +76,9 @@
 		}
 
 		if (!lockwakeup && td->bkl == 4) {
+#ifdef CONFIG_LOCK_KERNEL
 			unlock_kernel();
+#endif
 			td->bkl = 0;
 		}
 		return 0;
@@ -133,14 +135,18 @@
 		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;
 
diff --git a/kernel/sched.c b/kernel/sched.c
index dc85ceb..d42992b 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -426,9 +426,7 @@
 	 */
 	cpumask_var_t rto_mask;
 	atomic_t rto_count;
-#ifdef CONFIG_SMP
 	struct cpupri cpupri;
-#endif
 };
 
 /*
@@ -437,7 +435,7 @@
  */
 static struct root_domain def_root_domain;
 
-#endif
+#endif /* CONFIG_SMP */
 
 /*
  * This is the main, per-CPU runqueue data structure.
@@ -488,11 +486,12 @@
 	 */
 	unsigned long nr_uninterruptible;
 
-	struct task_struct *curr, *idle;
+	struct task_struct *curr, *idle, *stop;
 	unsigned long next_balance;
 	struct mm_struct *prev_mm;
 
 	u64 clock;
+	u64 clock_task;
 
 	atomic_t nr_iowait;
 
@@ -520,6 +519,10 @@
 	u64 avg_idle;
 #endif
 
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+	u64 prev_irq_time;
+#endif
+
 	/* calc_load related fields */
 	unsigned long calc_load_update;
 	long calc_load_active;
@@ -643,10 +646,22 @@
 
 #endif /* CONFIG_CGROUP_SCHED */
 
+static u64 irq_time_cpu(int cpu);
+static void sched_irq_time_avg_update(struct rq *rq, u64 irq_time);
+
 inline void update_rq_clock(struct rq *rq)
 {
-	if (!rq->skip_clock_update)
-		rq->clock = sched_clock_cpu(cpu_of(rq));
+	if (!rq->skip_clock_update) {
+		int cpu = cpu_of(rq);
+		u64 irq_time;
+
+		rq->clock = sched_clock_cpu(cpu);
+		irq_time = irq_time_cpu(cpu);
+		if (rq->clock - irq_time > rq->clock_task)
+			rq->clock_task = rq->clock - irq_time;
+
+		sched_irq_time_avg_update(rq, irq_time);
+	}
 }
 
 /*
@@ -723,7 +738,7 @@
 		size_t cnt, loff_t *ppos)
 {
 	char buf[64];
-	char *cmp = buf;
+	char *cmp;
 	int neg = 0;
 	int i;
 
@@ -734,6 +749,7 @@
 		return -EFAULT;
 
 	buf[cnt] = 0;
+	cmp = strstrip(buf);
 
 	if (strncmp(buf, "NO_", 3) == 0) {
 		neg = 1;
@@ -741,9 +757,7 @@
 	}
 
 	for (i = 0; sched_feat_names[i]; i++) {
-		int len = strlen(sched_feat_names[i]);
-
-		if (strncmp(cmp, sched_feat_names[i], len) == 0) {
+		if (strcmp(cmp, sched_feat_names[i]) == 0) {
 			if (neg)
 				sysctl_sched_features &= ~(1UL << i);
 			else
@@ -1840,7 +1854,7 @@
 
 static const struct sched_class rt_sched_class;
 
-#define sched_class_highest (&rt_sched_class)
+#define sched_class_highest (&stop_sched_class)
 #define for_each_class(class) \
    for (class = sched_class_highest; class; class = class->next)
 
@@ -1858,12 +1872,6 @@
 
 static void set_load_weight(struct task_struct *p)
 {
-	if (task_has_rt_policy(p)) {
-		p->se.load.weight = 0;
-		p->se.load.inv_weight = WMULT_CONST;
-		return;
-	}
-
 	/*
 	 * SCHED_IDLE tasks get minimal weight:
 	 */
@@ -1917,13 +1925,132 @@
 	dec_nr_running(rq);
 }
 
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+
+/*
+ * There are no locks covering percpu hardirq/softirq time.
+ * They are only modified in account_system_vtime, on corresponding CPU
+ * with interrupts disabled. So, writes are safe.
+ * They are read and saved off onto struct rq in update_rq_clock().
+ * This may result in other CPU reading this CPU's irq time and can
+ * race with irq/account_system_vtime on this CPU. We would either get old
+ * or new value (or semi updated value on 32 bit) with a side effect of
+ * accounting a slice of irq time to wrong task when irq is in progress
+ * while we read rq->clock. That is a worthy compromise in place of having
+ * locks on each irq in account_system_time.
+ */
+static DEFINE_PER_CPU(u64, cpu_hardirq_time);
+static DEFINE_PER_CPU(u64, cpu_softirq_time);
+
+static DEFINE_PER_CPU(u64, irq_start_time);
+static int sched_clock_irqtime;
+
+void enable_sched_clock_irqtime(void)
+{
+	sched_clock_irqtime = 1;
+}
+
+void disable_sched_clock_irqtime(void)
+{
+	sched_clock_irqtime = 0;
+}
+
+static u64 irq_time_cpu(int cpu)
+{
+	if (!sched_clock_irqtime)
+		return 0;
+
+	return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu);
+}
+
+void account_system_vtime(struct task_struct *curr)
+{
+	unsigned long flags;
+	int cpu;
+	u64 now, delta;
+
+	if (!sched_clock_irqtime)
+		return;
+
+	local_irq_save(flags);
+
+	cpu = smp_processor_id();
+	now = sched_clock_cpu(cpu);
+	delta = now - per_cpu(irq_start_time, cpu);
+	per_cpu(irq_start_time, cpu) = now;
+	/*
+	 * We do not account for softirq time from ksoftirqd here.
+	 * We want to continue accounting softirq time to ksoftirqd thread
+	 * in that case, so as not to confuse scheduler with a special task
+	 * that do not consume any time, but still wants to run.
+	 */
+	if (hardirq_count())
+		per_cpu(cpu_hardirq_time, cpu) += delta;
+	else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD))
+		per_cpu(cpu_softirq_time, cpu) += delta;
+
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(account_system_vtime);
+
+static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time)
+{
+	if (sched_clock_irqtime && sched_feat(NONIRQ_POWER)) {
+		u64 delta_irq = curr_irq_time - rq->prev_irq_time;
+		rq->prev_irq_time = curr_irq_time;
+		sched_rt_avg_update(rq, delta_irq);
+	}
+}
+
+#else
+
+static u64 irq_time_cpu(int cpu)
+{
+	return 0;
+}
+
+static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { }
+
+#endif
+
 #include "sched_idletask.c"
 #include "sched_fair.c"
 #include "sched_rt.c"
+#include "sched_stoptask.c"
 #ifdef CONFIG_SCHED_DEBUG
 # include "sched_debug.c"
 #endif
 
+void sched_set_stop_task(int cpu, struct task_struct *stop)
+{
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+	struct task_struct *old_stop = cpu_rq(cpu)->stop;
+
+	if (stop) {
+		/*
+		 * Make it appear like a SCHED_FIFO task, its something
+		 * userspace knows about and won't get confused about.
+		 *
+		 * Also, it will make PI more or less work without too
+		 * much confusion -- but then, stop work should not
+		 * rely on PI working anyway.
+		 */
+		sched_setscheduler_nocheck(stop, SCHED_FIFO, &param);
+
+		stop->sched_class = &stop_sched_class;
+	}
+
+	cpu_rq(cpu)->stop = stop;
+
+	if (old_stop) {
+		/*
+		 * Reset it back to a normal scheduling class so that
+		 * it can die in pieces.
+		 */
+		old_stop->sched_class = &rt_sched_class;
+	}
+}
+
 /*
  * __normal_prio - return the priority that is based on the static prio
  */
@@ -2003,6 +2130,9 @@
 	if (p->sched_class != &fair_sched_class)
 		return 0;
 
+	if (unlikely(p->policy == SCHED_IDLE))
+		return 0;
+
 	/*
 	 * Buddy candidates are cache hot:
 	 */
@@ -2852,14 +2982,14 @@
 	 */
 	arch_start_context_switch(prev);
 
-	if (likely(!mm)) {
+	if (!mm) {
 		next->active_mm = oldmm;
 		atomic_inc(&oldmm->mm_count);
 		enter_lazy_tlb(oldmm, next);
 	} else
 		switch_mm(oldmm, mm, next);
 
-	if (likely(!prev->mm)) {
+	if (!prev->mm) {
 		prev->active_mm = NULL;
 		rq->prev_mm = oldmm;
 	}
@@ -3248,7 +3378,7 @@
 
 	if (task_current(rq, p)) {
 		update_rq_clock(rq);
-		ns = rq->clock - p->se.exec_start;
+		ns = rq->clock_task - p->se.exec_start;
 		if ((s64)ns < 0)
 			ns = 0;
 	}
@@ -3397,7 +3527,7 @@
 	tmp = cputime_to_cputime64(cputime);
 	if (hardirq_count() - hardirq_offset)
 		cpustat->irq = cputime64_add(cpustat->irq, tmp);
-	else if (softirq_count())
+	else if (in_serving_softirq())
 		cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
 	else
 		cpustat->system = cputime64_add(cpustat->system, tmp);
@@ -3584,7 +3714,7 @@
 	curr->sched_class->task_tick(rq, curr, 0);
 	raw_spin_unlock(&rq->lock);
 
-	perf_event_task_tick(curr);
+	perf_event_task_tick();
 
 #ifdef CONFIG_SMP
 	rq->idle_at_tick = idle_cpu(cpu);
@@ -3723,17 +3853,13 @@
 			return p;
 	}
 
-	class = sched_class_highest;
-	for ( ; ; ) {
+	for_each_class(class) {
 		p = class->pick_next_task(rq);
 		if (p)
 			return p;
-		/*
-		 * Will never be NULL as the idle class always
-		 * returns a non-NULL p:
-		 */
-		class = class->next;
 	}
+
+	BUG(); /* the idle class will always have a runnable task */
 }
 
 /*
@@ -4358,6 +4484,7 @@
 
 	rq = task_rq_lock(p, &flags);
 
+	trace_sched_pi_setprio(p, prio);
 	oldprio = p->prio;
 	prev_class = p->sched_class;
 	on_rq = p->se.on_rq;
@@ -4645,7 +4772,7 @@
 	}
 
 	if (user) {
-		retval = security_task_setscheduler(p, policy, param);
+		retval = security_task_setscheduler(p);
 		if (retval)
 			return retval;
 	}
@@ -4661,6 +4788,15 @@
 	 */
 	rq = __task_rq_lock(p);
 
+	/*
+	 * Changing the policy of the stop threads its a very bad idea
+	 */
+	if (p == rq->stop) {
+		__task_rq_unlock(rq);
+		raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+		return -EINVAL;
+	}
+
 #ifdef CONFIG_RT_GROUP_SCHED
 	if (user) {
 		/*
@@ -4887,13 +5023,13 @@
 	if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
 		goto out_unlock;
 
-	retval = security_task_setscheduler(p, 0, NULL);
+	retval = security_task_setscheduler(p);
 	if (retval)
 		goto out_unlock;
 
 	cpuset_cpus_allowed(p, cpus_allowed);
 	cpumask_and(new_mask, in_mask, cpus_allowed);
- again:
+again:
 	retval = set_cpus_allowed_ptr(p, new_mask);
 
 	if (!retval) {
@@ -5337,7 +5473,19 @@
 	idle->se.exec_start = sched_clock();
 
 	cpumask_copy(&idle->cpus_allowed, cpumask_of(cpu));
+	/*
+	 * We're having a chicken and egg problem, even though we are
+	 * holding rq->lock, the cpu isn't yet set to this cpu so the
+	 * lockdep check in task_group() will fail.
+	 *
+	 * Similar case to sched_fork(). / Alternatively we could
+	 * use task_rq_lock() here and obtain the other rq->lock.
+	 *
+	 * Silence PROVE_RCU
+	 */
+	rcu_read_lock();
 	__set_task_cpu(idle, cpu);
+	rcu_read_unlock();
 
 	rq->curr = rq->idle = idle;
 #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
@@ -6514,6 +6662,7 @@
 	cpumask_var_t		nodemask;
 	cpumask_var_t		this_sibling_map;
 	cpumask_var_t		this_core_map;
+	cpumask_var_t		this_book_map;
 	cpumask_var_t		send_covered;
 	cpumask_var_t		tmpmask;
 	struct sched_group	**sched_group_nodes;
@@ -6525,6 +6674,7 @@
 	sa_rootdomain,
 	sa_tmpmask,
 	sa_send_covered,
+	sa_this_book_map,
 	sa_this_core_map,
 	sa_this_sibling_map,
 	sa_nodemask,
@@ -6560,31 +6710,48 @@
 #ifdef CONFIG_SCHED_MC
 static DEFINE_PER_CPU(struct static_sched_domain, core_domains);
 static DEFINE_PER_CPU(struct static_sched_group, sched_group_core);
-#endif /* CONFIG_SCHED_MC */
 
-#if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT)
 static int
 cpu_to_core_group(int cpu, const struct cpumask *cpu_map,
 		  struct sched_group **sg, struct cpumask *mask)
 {
 	int group;
-
+#ifdef CONFIG_SCHED_SMT
 	cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map);
 	group = cpumask_first(mask);
+#else
+	group = cpu;
+#endif
 	if (sg)
 		*sg = &per_cpu(sched_group_core, group).sg;
 	return group;
 }
-#elif defined(CONFIG_SCHED_MC)
+#endif /* CONFIG_SCHED_MC */
+
+/*
+ * book sched-domains:
+ */
+#ifdef CONFIG_SCHED_BOOK
+static DEFINE_PER_CPU(struct static_sched_domain, book_domains);
+static DEFINE_PER_CPU(struct static_sched_group, sched_group_book);
+
 static int
-cpu_to_core_group(int cpu, const struct cpumask *cpu_map,
-		  struct sched_group **sg, struct cpumask *unused)
+cpu_to_book_group(int cpu, const struct cpumask *cpu_map,
+		  struct sched_group **sg, struct cpumask *mask)
 {
-	if (sg)
-		*sg = &per_cpu(sched_group_core, cpu).sg;
-	return cpu;
-}
+	int group = cpu;
+#ifdef CONFIG_SCHED_MC
+	cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map);
+	group = cpumask_first(mask);
+#elif defined(CONFIG_SCHED_SMT)
+	cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map);
+	group = cpumask_first(mask);
 #endif
+	if (sg)
+		*sg = &per_cpu(sched_group_book, group).sg;
+	return group;
+}
+#endif /* CONFIG_SCHED_BOOK */
 
 static DEFINE_PER_CPU(struct static_sched_domain, phys_domains);
 static DEFINE_PER_CPU(struct static_sched_group, sched_group_phys);
@@ -6594,7 +6761,10 @@
 		  struct sched_group **sg, struct cpumask *mask)
 {
 	int group;
-#ifdef CONFIG_SCHED_MC
+#ifdef CONFIG_SCHED_BOOK
+	cpumask_and(mask, cpu_book_mask(cpu), cpu_map);
+	group = cpumask_first(mask);
+#elif defined(CONFIG_SCHED_MC)
 	cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map);
 	group = cpumask_first(mask);
 #elif defined(CONFIG_SCHED_SMT)
@@ -6855,6 +7025,9 @@
 #ifdef CONFIG_SCHED_MC
  SD_INIT_FUNC(MC)
 #endif
+#ifdef CONFIG_SCHED_BOOK
+ SD_INIT_FUNC(BOOK)
+#endif
 
 static int default_relax_domain_level = -1;
 
@@ -6904,6 +7077,8 @@
 		free_cpumask_var(d->tmpmask); /* fall through */
 	case sa_send_covered:
 		free_cpumask_var(d->send_covered); /* fall through */
+	case sa_this_book_map:
+		free_cpumask_var(d->this_book_map); /* fall through */
 	case sa_this_core_map:
 		free_cpumask_var(d->this_core_map); /* fall through */
 	case sa_this_sibling_map:
@@ -6950,8 +7125,10 @@
 		return sa_nodemask;
 	if (!alloc_cpumask_var(&d->this_core_map, GFP_KERNEL))
 		return sa_this_sibling_map;
-	if (!alloc_cpumask_var(&d->send_covered, GFP_KERNEL))
+	if (!alloc_cpumask_var(&d->this_book_map, GFP_KERNEL))
 		return sa_this_core_map;
+	if (!alloc_cpumask_var(&d->send_covered, GFP_KERNEL))
+		return sa_this_book_map;
 	if (!alloc_cpumask_var(&d->tmpmask, GFP_KERNEL))
 		return sa_send_covered;
 	d->rd = alloc_rootdomain();
@@ -7009,6 +7186,23 @@
 	return sd;
 }
 
+static struct sched_domain *__build_book_sched_domain(struct s_data *d,
+	const struct cpumask *cpu_map, struct sched_domain_attr *attr,
+	struct sched_domain *parent, int i)
+{
+	struct sched_domain *sd = parent;
+#ifdef CONFIG_SCHED_BOOK
+	sd = &per_cpu(book_domains, i).sd;
+	SD_INIT(sd, BOOK);
+	set_domain_attribute(sd, attr);
+	cpumask_and(sched_domain_span(sd), cpu_map, cpu_book_mask(i));
+	sd->parent = parent;
+	parent->child = sd;
+	cpu_to_book_group(i, cpu_map, &sd->groups, d->tmpmask);
+#endif
+	return sd;
+}
+
 static struct sched_domain *__build_mc_sched_domain(struct s_data *d,
 	const struct cpumask *cpu_map, struct sched_domain_attr *attr,
 	struct sched_domain *parent, int i)
@@ -7066,6 +7260,15 @@
 						d->send_covered, d->tmpmask);
 		break;
 #endif
+#ifdef CONFIG_SCHED_BOOK
+	case SD_LV_BOOK: /* set up book groups */
+		cpumask_and(d->this_book_map, cpu_map, cpu_book_mask(cpu));
+		if (cpu == cpumask_first(d->this_book_map))
+			init_sched_build_groups(d->this_book_map, cpu_map,
+						&cpu_to_book_group,
+						d->send_covered, d->tmpmask);
+		break;
+#endif
 	case SD_LV_CPU: /* set up physical groups */
 		cpumask_and(d->nodemask, cpumask_of_node(cpu), cpu_map);
 		if (!cpumask_empty(d->nodemask))
@@ -7113,12 +7316,14 @@
 
 		sd = __build_numa_sched_domains(&d, cpu_map, attr, i);
 		sd = __build_cpu_sched_domain(&d, cpu_map, attr, sd, i);
+		sd = __build_book_sched_domain(&d, cpu_map, attr, sd, i);
 		sd = __build_mc_sched_domain(&d, cpu_map, attr, sd, i);
 		sd = __build_smt_sched_domain(&d, cpu_map, attr, sd, i);
 	}
 
 	for_each_cpu(i, cpu_map) {
 		build_sched_groups(&d, SD_LV_SIBLING, cpu_map, i);
+		build_sched_groups(&d, SD_LV_BOOK, cpu_map, i);
 		build_sched_groups(&d, SD_LV_MC, cpu_map, i);
 	}
 
@@ -7149,6 +7354,12 @@
 		init_sched_groups_power(i, sd);
 	}
 #endif
+#ifdef CONFIG_SCHED_BOOK
+	for_each_cpu(i, cpu_map) {
+		sd = &per_cpu(book_domains, i).sd;
+		init_sched_groups_power(i, sd);
+	}
+#endif
 
 	for_each_cpu(i, cpu_map) {
 		sd = &per_cpu(phys_domains, i).sd;
@@ -7174,6 +7385,8 @@
 		sd = &per_cpu(cpu_domains, i).sd;
 #elif defined(CONFIG_SCHED_MC)
 		sd = &per_cpu(core_domains, i).sd;
+#elif defined(CONFIG_SCHED_BOOK)
+		sd = &per_cpu(book_domains, i).sd;
 #else
 		sd = &per_cpu(phys_domains, i).sd;
 #endif
@@ -8078,9 +8291,9 @@
 
 	return 1;
 
- err_free_rq:
+err_free_rq:
 	kfree(cfs_rq);
- err:
+err:
 	return 0;
 }
 
@@ -8168,9 +8381,9 @@
 
 	return 1;
 
- err_free_rq:
+err_free_rq:
 	kfree(rt_rq);
- err:
+err:
 	return 0;
 }
 
@@ -8528,7 +8741,7 @@
 		raw_spin_unlock(&rt_rq->rt_runtime_lock);
 	}
 	raw_spin_unlock_irq(&tg->rt_bandwidth.rt_runtime_lock);
- unlock:
+unlock:
 	read_unlock(&tasklist_lock);
 	mutex_unlock(&rt_constraints_mutex);
 
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index db3f674..933f3d1 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -25,7 +25,7 @@
 
 /*
  * Targeted preemption latency for CPU-bound tasks:
- * (default: 5ms * (1 + ilog(ncpus)), units: nanoseconds)
+ * (default: 6ms * (1 + ilog(ncpus)), units: nanoseconds)
  *
  * NOTE: this latency value is not the same as the concept of
  * 'timeslice length' - timeslices in CFS are of variable length
@@ -52,7 +52,7 @@
 
 /*
  * Minimal preemption granularity for CPU-bound tasks:
- * (default: 2 msec * (1 + ilog(ncpus)), units: nanoseconds)
+ * (default: 0.75 msec * (1 + ilog(ncpus)), units: nanoseconds)
  */
 unsigned int sysctl_sched_min_granularity = 750000ULL;
 unsigned int normalized_sysctl_sched_min_granularity = 750000ULL;
@@ -519,7 +519,7 @@
 static void update_curr(struct cfs_rq *cfs_rq)
 {
 	struct sched_entity *curr = cfs_rq->curr;
-	u64 now = rq_of(cfs_rq)->clock;
+	u64 now = rq_of(cfs_rq)->clock_task;
 	unsigned long delta_exec;
 
 	if (unlikely(!curr))
@@ -602,7 +602,7 @@
 	/*
 	 * We are starting a new run period:
 	 */
-	se->exec_start = rq_of(cfs_rq)->clock;
+	se->exec_start = rq_of(cfs_rq)->clock_task;
 }
 
 /**************************************************
@@ -1764,6 +1764,10 @@
 	set_task_cpu(p, this_cpu);
 	activate_task(this_rq, p, 0);
 	check_preempt_curr(this_rq, p, 0);
+
+	/* re-arm NEWIDLE balancing when moving tasks */
+	src_rq->avg_idle = this_rq->avg_idle = 2*sysctl_sched_migration_cost;
+	this_rq->idle_stamp = 0;
 }
 
 /*
@@ -1798,7 +1802,7 @@
 	 * 2) too many balance attempts have failed.
 	 */
 
-	tsk_cache_hot = task_hot(p, rq->clock, sd);
+	tsk_cache_hot = task_hot(p, rq->clock_task, sd);
 	if (!tsk_cache_hot ||
 		sd->nr_balance_failed > sd->cache_nice_tries) {
 #ifdef CONFIG_SCHEDSTATS
@@ -2030,12 +2034,14 @@
 	unsigned long this_load;
 	unsigned long this_load_per_task;
 	unsigned long this_nr_running;
+	unsigned long this_has_capacity;
 
 	/* Statistics of the busiest group */
 	unsigned long max_load;
 	unsigned long busiest_load_per_task;
 	unsigned long busiest_nr_running;
 	unsigned long busiest_group_capacity;
+	unsigned long busiest_has_capacity;
 
 	int group_imb; /* Is there imbalance in this sd */
 #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
@@ -2058,6 +2064,7 @@
 	unsigned long sum_weighted_load; /* Weighted load of group's tasks */
 	unsigned long group_capacity;
 	int group_imb; /* Is there an imbalance in the group ? */
+	int group_has_capacity; /* Is there extra capacity in the group? */
 };
 
 /**
@@ -2268,7 +2275,13 @@
 	u64 total, available;
 
 	total = sched_avg_period() + (rq->clock - rq->age_stamp);
-	available = total - rq->rt_avg;
+
+	if (unlikely(total < rq->rt_avg)) {
+		/* Ensures that power won't end up being negative */
+		available = 0;
+	} else {
+		available = total - rq->rt_avg;
+	}
 
 	if (unlikely((s64)total < SCHED_LOAD_SCALE))
 		total = SCHED_LOAD_SCALE;
@@ -2378,7 +2391,7 @@
 			int local_group, const struct cpumask *cpus,
 			int *balance, struct sg_lb_stats *sgs)
 {
-	unsigned long load, max_cpu_load, min_cpu_load;
+	unsigned long load, max_cpu_load, min_cpu_load, max_nr_running;
 	int i;
 	unsigned int balance_cpu = -1, first_idle_cpu = 0;
 	unsigned long avg_load_per_task = 0;
@@ -2389,6 +2402,7 @@
 	/* Tally up the load of all CPUs in the group */
 	max_cpu_load = 0;
 	min_cpu_load = ~0UL;
+	max_nr_running = 0;
 
 	for_each_cpu_and(i, sched_group_cpus(group), cpus) {
 		struct rq *rq = cpu_rq(i);
@@ -2406,8 +2420,10 @@
 			load = target_load(i, load_idx);
 		} else {
 			load = source_load(i, load_idx);
-			if (load > max_cpu_load)
+			if (load > max_cpu_load) {
 				max_cpu_load = load;
+				max_nr_running = rq->nr_running;
+			}
 			if (min_cpu_load > load)
 				min_cpu_load = load;
 		}
@@ -2447,13 +2463,15 @@
 	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)
+	if ((max_cpu_load - min_cpu_load) > 2*avg_load_per_task && max_nr_running > 1)
 		sgs->group_imb = 1;
 
-	sgs->group_capacity =
-		DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE);
+	sgs->group_capacity = DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE);
 	if (!sgs->group_capacity)
 		sgs->group_capacity = fix_small_capacity(sd, group);
+
+	if (sgs->group_capacity > sgs->sum_nr_running)
+		sgs->group_has_capacity = 1;
 }
 
 /**
@@ -2542,9 +2560,14 @@
 		/*
 		 * In case the child domain prefers tasks go to siblings
 		 * first, lower the sg capacity to one so that we'll try
-		 * and move all the excess tasks away.
+		 * and move all the excess tasks away. We lower the capacity
+		 * of a group only if the local group has the capacity to fit
+		 * these excess tasks, i.e. nr_running < group_capacity. The
+		 * extra check prevents the case where you always pull from the
+		 * heaviest group when it is already under-utilized (possible
+		 * with a large weight task outweighs the tasks on the system).
 		 */
-		if (prefer_sibling)
+		if (prefer_sibling && !local_group && sds->this_has_capacity)
 			sgs.group_capacity = min(sgs.group_capacity, 1UL);
 
 		if (local_group) {
@@ -2552,12 +2575,14 @@
 			sds->this = sg;
 			sds->this_nr_running = sgs.sum_nr_running;
 			sds->this_load_per_task = sgs.sum_weighted_load;
+			sds->this_has_capacity = sgs.group_has_capacity;
 		} else if (update_sd_pick_busiest(sd, sds, sg, &sgs, this_cpu)) {
 			sds->max_load = sgs.avg_load;
 			sds->busiest = sg;
 			sds->busiest_nr_running = sgs.sum_nr_running;
 			sds->busiest_group_capacity = sgs.group_capacity;
 			sds->busiest_load_per_task = sgs.sum_weighted_load;
+			sds->busiest_has_capacity = sgs.group_has_capacity;
 			sds->group_imb = sgs.group_imb;
 		}
 
@@ -2754,6 +2779,7 @@
 		return fix_small_imbalance(sds, this_cpu, imbalance);
 
 }
+
 /******* find_busiest_group() helpers end here *********************/
 
 /**
@@ -2805,6 +2831,11 @@
 	 * 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.
 	 */
 	if (!(*balance))
 		goto ret;
@@ -2816,6 +2847,11 @@
 	if (!sds.busiest || sds.busiest_nr_running == 0)
 		goto out_balanced;
 
+	/*  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 (sds.this_load >= sds.max_load)
 		goto out_balanced;
 
@@ -2827,6 +2863,7 @@
 	if (100 * sds.max_load <= sd->imbalance_pct * sds.this_load)
 		goto out_balanced;
 
+force_balance:
 	/* Looks like there is an imbalance. Compute it */
 	calculate_imbalance(&sds, this_cpu, imbalance);
 	return sds.busiest;
@@ -3031,7 +3068,14 @@
 
 	if (!ld_moved) {
 		schedstat_inc(sd, lb_failed[idle]);
-		sd->nr_balance_failed++;
+		/*
+		 * Increment the failure counter only on periodic balance.
+		 * We do not want newidle balance, which can be very
+		 * frequent, pollute the failure counter causing
+		 * excessive cache_hot migrations and active balances.
+		 */
+		if (idle != CPU_NEWLY_IDLE)
+			sd->nr_balance_failed++;
 
 		if (need_active_balance(sd, sd_idle, idle, cpu_of(busiest),
 					this_cpu)) {
@@ -3153,10 +3197,8 @@
 		interval = msecs_to_jiffies(sd->balance_interval);
 		if (time_after(next_balance, sd->last_balance + interval))
 			next_balance = sd->last_balance + interval;
-		if (pulled_task) {
-			this_rq->idle_stamp = 0;
+		if (pulled_task)
 			break;
-		}
 	}
 
 	raw_spin_lock(&this_rq->lock);
@@ -3751,8 +3793,11 @@
 
 	update_rq_clock(rq);
 
-	if (unlikely(task_cpu(p) != this_cpu))
+	if (unlikely(task_cpu(p) != this_cpu)) {
+		rcu_read_lock();
 		__set_task_cpu(p, this_cpu);
+		rcu_read_unlock();
+	}
 
 	update_curr(cfs_rq);
 
diff --git a/kernel/sched_features.h b/kernel/sched_features.h
index 83c66e8..185f920 100644
--- a/kernel/sched_features.h
+++ b/kernel/sched_features.h
@@ -61,3 +61,8 @@
  * release the lock. Decreases scheduling overhead.
  */
 SCHED_FEAT(OWNER_SPIN, 1)
+
+/*
+ * Decrement CPU power based on irq activity
+ */
+SCHED_FEAT(NONIRQ_POWER, 1)
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index d10c80e..bea7d79 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -609,7 +609,7 @@
 	if (!task_has_rt_policy(curr))
 		return;
 
-	delta_exec = rq->clock - curr->se.exec_start;
+	delta_exec = rq->clock_task - curr->se.exec_start;
 	if (unlikely((s64)delta_exec < 0))
 		delta_exec = 0;
 
@@ -618,7 +618,7 @@
 	curr->se.sum_exec_runtime += delta_exec;
 	account_group_exec_runtime(curr, delta_exec);
 
-	curr->se.exec_start = rq->clock;
+	curr->se.exec_start = rq->clock_task;
 	cpuacct_charge(curr, delta_exec);
 
 	sched_rt_avg_update(rq, delta_exec);
@@ -960,18 +960,19 @@
 	 * runqueue. Otherwise simply start this RT task
 	 * on its current runqueue.
 	 *
-	 * We want to avoid overloading runqueues. Even if
-	 * the RT task is of higher priority than the current RT task.
-	 * RT tasks behave differently than other tasks. If
-	 * one gets preempted, we try to push it off to another queue.
-	 * So trying to keep a preempting RT task on the same
-	 * cache hot CPU will force the running RT task to
-	 * a cold CPU. So we waste all the cache for the lower
-	 * RT task in hopes of saving some of a RT task
-	 * that is just being woken and probably will have
-	 * cold cache anyway.
+	 * We want to avoid overloading runqueues. If the woken
+	 * task is a higher priority, then it will stay on this CPU
+	 * and the lower prio task should be moved to another CPU.
+	 * Even though this will probably make the lower prio task
+	 * lose its cache, we do not want to bounce a higher task
+	 * around just because it gave up its CPU, perhaps for a
+	 * lock?
+	 *
+	 * For equal prio tasks, we just let the scheduler sort it out.
 	 */
 	if (unlikely(rt_task(rq->curr)) &&
+	    (rq->curr->rt.nr_cpus_allowed < 2 ||
+	     rq->curr->prio < p->prio) &&
 	    (p->rt.nr_cpus_allowed > 1)) {
 		int cpu = find_lowest_rq(p);
 
@@ -1074,7 +1075,7 @@
 	} while (rt_rq);
 
 	p = rt_task_of(rt_se);
-	p->se.exec_start = rq->clock;
+	p->se.exec_start = rq->clock_task;
 
 	return p;
 }
@@ -1139,7 +1140,7 @@
 	for_each_leaf_rt_rq(rt_rq, rq) {
 		array = &rt_rq->active;
 		idx = sched_find_first_bit(array->bitmap);
- next_idx:
+next_idx:
 		if (idx >= MAX_RT_PRIO)
 			continue;
 		if (next && next->prio < idx)
@@ -1315,7 +1316,7 @@
 	if (!next_task)
 		return 0;
 
- retry:
+retry:
 	if (unlikely(next_task == rq->curr)) {
 		WARN_ON(1);
 		return 0;
@@ -1463,7 +1464,7 @@
 			 * but possible)
 			 */
 		}
- skip:
+skip:
 		double_unlock_balance(this_rq, src_rq);
 	}
 
@@ -1491,7 +1492,10 @@
 	if (!task_running(rq, p) &&
 	    !test_tsk_need_resched(rq->curr) &&
 	    has_pushable_tasks(rq) &&
-	    p->rt.nr_cpus_allowed > 1)
+	    p->rt.nr_cpus_allowed > 1 &&
+	    rt_task(rq->curr) &&
+	    (rq->curr->rt.nr_cpus_allowed < 2 ||
+	     rq->curr->prio < p->prio))
 		push_rt_tasks(rq);
 }
 
@@ -1709,7 +1713,7 @@
 {
 	struct task_struct *p = rq->curr;
 
-	p->se.exec_start = rq->clock;
+	p->se.exec_start = rq->clock_task;
 
 	/* The running task is never eligible for pushing */
 	dequeue_pushable_task(rq, p);
diff --git a/kernel/sched_stoptask.c b/kernel/sched_stoptask.c
new file mode 100644
index 0000000..45bddc0
--- /dev/null
+++ b/kernel/sched_stoptask.c
@@ -0,0 +1,108 @@
+/*
+ * stop-task scheduling class.
+ *
+ * The stop task is the highest priority task in the system, it preempts
+ * everything and will be preempted by nothing.
+ *
+ * See kernel/stop_machine.c
+ */
+
+#ifdef CONFIG_SMP
+static int
+select_task_rq_stop(struct rq *rq, struct task_struct *p,
+		    int sd_flag, int flags)
+{
+	return task_cpu(p); /* stop tasks as never migrate */
+}
+#endif /* CONFIG_SMP */
+
+static void
+check_preempt_curr_stop(struct rq *rq, struct task_struct *p, int flags)
+{
+	resched_task(rq->curr); /* we preempt everything */
+}
+
+static struct task_struct *pick_next_task_stop(struct rq *rq)
+{
+	struct task_struct *stop = rq->stop;
+
+	if (stop && stop->state == TASK_RUNNING)
+		return stop;
+
+	return NULL;
+}
+
+static void
+enqueue_task_stop(struct rq *rq, struct task_struct *p, int flags)
+{
+}
+
+static void
+dequeue_task_stop(struct rq *rq, struct task_struct *p, int flags)
+{
+}
+
+static void yield_task_stop(struct rq *rq)
+{
+	BUG(); /* the stop task should never yield, its pointless. */
+}
+
+static void put_prev_task_stop(struct rq *rq, struct task_struct *prev)
+{
+}
+
+static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued)
+{
+}
+
+static void set_curr_task_stop(struct rq *rq)
+{
+}
+
+static void switched_to_stop(struct rq *rq, struct task_struct *p,
+			     int running)
+{
+	BUG(); /* its impossible to change to this class */
+}
+
+static void prio_changed_stop(struct rq *rq, struct task_struct *p,
+			      int oldprio, int running)
+{
+	BUG(); /* how!?, what priority? */
+}
+
+static unsigned int
+get_rr_interval_stop(struct rq *rq, struct task_struct *task)
+{
+	return 0;
+}
+
+/*
+ * Simple, special scheduling class for the per-CPU stop tasks:
+ */
+static const struct sched_class stop_sched_class = {
+	.next			= &rt_sched_class,
+
+	.enqueue_task		= enqueue_task_stop,
+	.dequeue_task		= dequeue_task_stop,
+	.yield_task		= yield_task_stop,
+
+	.check_preempt_curr	= check_preempt_curr_stop,
+
+	.pick_next_task		= pick_next_task_stop,
+	.put_prev_task		= put_prev_task_stop,
+
+#ifdef CONFIG_SMP
+	.select_task_rq		= select_task_rq_stop,
+#endif
+
+	.set_curr_task          = set_curr_task_stop,
+	.task_tick		= task_tick_stop,
+
+	.get_rr_interval	= get_rr_interval_stop,
+
+	.prio_changed		= prio_changed_stop,
+	.switched_to		= switched_to_stop,
+
+	/* no .task_new for stop tasks */
+};
diff --git a/kernel/signal.c b/kernel/signal.c
index bded651..919562c 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2215,6 +2215,14 @@
 #ifdef __ARCH_SI_TRAPNO
 		err |= __put_user(from->si_trapno, &to->si_trapno);
 #endif
+#ifdef BUS_MCEERR_AO
+		/* 
+		 * Other callers might not initialize the si_lsb field,
+	 	 * so check explicitely for the right codes here.
+		 */
+		if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)
+			err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
+#endif
 		break;
 	case __SI_CHLD:
 		err |= __put_user(from->si_pid, &to->si_pid);
diff --git a/kernel/smp.c b/kernel/smp.c
index 75c970c..ed6aacf 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -365,9 +365,10 @@
 EXPORT_SYMBOL_GPL(smp_call_function_any);
 
 /**
- * __smp_call_function_single(): Run a function on another CPU
+ * __smp_call_function_single(): Run a function on a specific CPU
  * @cpu: The CPU to run on.
  * @data: Pre-allocated and setup data structure
+ * @wait: If true, wait until function has completed on specified CPU.
  *
  * Like smp_call_function_single(), but allow caller to pass in a
  * pre-allocated data structure. Useful for embedding @data inside
@@ -376,8 +377,10 @@
 void __smp_call_function_single(int cpu, struct call_single_data *data,
 				int wait)
 {
-	csd_lock(data);
+	unsigned int this_cpu;
+	unsigned long flags;
 
+	this_cpu = get_cpu();
 	/*
 	 * Can deadlock when called with interrupts disabled.
 	 * We allow cpu's that are not yet online though, as no one else can
@@ -387,7 +390,15 @@
 	WARN_ON_ONCE(cpu_online(smp_processor_id()) && wait && irqs_disabled()
 		     && !oops_in_progress);
 
-	generic_exec_single(cpu, data, wait);
+	if (cpu == this_cpu) {
+		local_irq_save(flags);
+		data->func(data->info);
+		local_irq_restore(flags);
+	} else {
+		csd_lock(data);
+		generic_exec_single(cpu, data, wait);
+	}
+	put_cpu();
 }
 
 /**
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 07b4f1b..f02a9df 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -67,7 +67,7 @@
  * to the pending events, so lets the scheduler to balance
  * the softirq load for us.
  */
-void wakeup_softirqd(void)
+static void wakeup_softirqd(void)
 {
 	/* Interrupts are disabled: no need to stop preemption */
 	struct task_struct *tsk = __get_cpu_var(ksoftirqd);
@@ -77,11 +77,21 @@
 }
 
 /*
+ * preempt_count and SOFTIRQ_OFFSET usage:
+ * - preempt_count is changed by SOFTIRQ_OFFSET on entering or leaving
+ *   softirq processing.
+ * - preempt_count is changed by SOFTIRQ_DISABLE_OFFSET (= 2 * SOFTIRQ_OFFSET)
+ *   on local_bh_disable or local_bh_enable.
+ * This lets us distinguish between whether we are currently processing
+ * softirq and whether we just have bh disabled.
+ */
+
+/*
  * This one is for softirq.c-internal use,
  * where hardirqs are disabled legitimately:
  */
 #ifdef CONFIG_TRACE_IRQFLAGS
-static void __local_bh_disable(unsigned long ip)
+static void __local_bh_disable(unsigned long ip, unsigned int cnt)
 {
 	unsigned long flags;
 
@@ -95,32 +105,43 @@
 	 * We must manually increment preempt_count here and manually
 	 * call the trace_preempt_off later.
 	 */
-	preempt_count() += SOFTIRQ_OFFSET;
+	preempt_count() += cnt;
 	/*
 	 * Were softirqs turned off above:
 	 */
-	if (softirq_count() == SOFTIRQ_OFFSET)
+	if (softirq_count() == cnt)
 		trace_softirqs_off(ip);
 	raw_local_irq_restore(flags);
 
-	if (preempt_count() == SOFTIRQ_OFFSET)
+	if (preempt_count() == cnt)
 		trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
 }
 #else /* !CONFIG_TRACE_IRQFLAGS */
-static inline void __local_bh_disable(unsigned long ip)
+static inline void __local_bh_disable(unsigned long ip, unsigned int cnt)
 {
-	add_preempt_count(SOFTIRQ_OFFSET);
+	add_preempt_count(cnt);
 	barrier();
 }
 #endif /* CONFIG_TRACE_IRQFLAGS */
 
 void local_bh_disable(void)
 {
-	__local_bh_disable((unsigned long)__builtin_return_address(0));
+	__local_bh_disable((unsigned long)__builtin_return_address(0),
+				SOFTIRQ_DISABLE_OFFSET);
 }
 
 EXPORT_SYMBOL(local_bh_disable);
 
+static void __local_bh_enable(unsigned int cnt)
+{
+	WARN_ON_ONCE(in_irq());
+	WARN_ON_ONCE(!irqs_disabled());
+
+	if (softirq_count() == cnt)
+		trace_softirqs_on((unsigned long)__builtin_return_address(0));
+	sub_preempt_count(cnt);
+}
+
 /*
  * Special-case - softirqs can safely be enabled in
  * cond_resched_softirq(), or by __do_softirq(),
@@ -128,12 +149,7 @@
  */
 void _local_bh_enable(void)
 {
-	WARN_ON_ONCE(in_irq());
-	WARN_ON_ONCE(!irqs_disabled());
-
-	if (softirq_count() == SOFTIRQ_OFFSET)
-		trace_softirqs_on((unsigned long)__builtin_return_address(0));
-	sub_preempt_count(SOFTIRQ_OFFSET);
+	__local_bh_enable(SOFTIRQ_DISABLE_OFFSET);
 }
 
 EXPORT_SYMBOL(_local_bh_enable);
@@ -147,13 +163,13 @@
 	/*
 	 * Are softirqs going to be turned on now:
 	 */
-	if (softirq_count() == SOFTIRQ_OFFSET)
+	if (softirq_count() == SOFTIRQ_DISABLE_OFFSET)
 		trace_softirqs_on(ip);
 	/*
 	 * Keep preemption disabled until we are done with
 	 * softirq processing:
  	 */
- 	sub_preempt_count(SOFTIRQ_OFFSET - 1);
+	sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1);
 
 	if (unlikely(!in_interrupt() && local_softirq_pending()))
 		do_softirq();
@@ -198,7 +214,8 @@
 	pending = local_softirq_pending();
 	account_system_vtime(current);
 
-	__local_bh_disable((unsigned long)__builtin_return_address(0));
+	__local_bh_disable((unsigned long)__builtin_return_address(0),
+				SOFTIRQ_OFFSET);
 	lockdep_softirq_enter();
 
 	cpu = smp_processor_id();
@@ -245,7 +262,7 @@
 	lockdep_softirq_exit();
 
 	account_system_vtime(current);
-	_local_bh_enable();
+	__local_bh_enable(SOFTIRQ_OFFSET);
 }
 
 #ifndef __ARCH_HAS_DO_SOFTIRQ
@@ -279,10 +296,16 @@
 
 	rcu_irq_enter();
 	if (idle_cpu(cpu) && !in_interrupt()) {
-		__irq_enter();
+		/*
+		 * Prevent raise_softirq from needlessly waking up ksoftirqd
+		 * here, as softirq will be serviced on return from interrupt.
+		 */
+		local_bh_disable();
 		tick_check_idle(cpu);
-	} else
-		__irq_enter();
+		_local_bh_enable();
+	}
+
+	__irq_enter();
 }
 
 #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
@@ -696,6 +719,7 @@
 {
 	set_current_state(TASK_INTERRUPTIBLE);
 
+	current->flags |= PF_KSOFTIRQD;
 	while (!kthread_should_stop()) {
 		preempt_disable();
 		if (!local_softirq_pending()) {
@@ -886,17 +910,14 @@
 	return 0;
 }
 
+#ifdef CONFIG_GENERIC_HARDIRQS
 int __init __weak arch_probe_nr_irqs(void)
 {
-	return 0;
+	return NR_IRQS_LEGACY;
 }
 
 int __init __weak arch_early_irq_init(void)
 {
 	return 0;
 }
-
-int __weak arch_init_chip_data(struct irq_desc *desc, int node)
-{
-	return 0;
-}
+#endif
diff --git a/kernel/srcu.c b/kernel/srcu.c
index 2980da3..c71e075 100644
--- a/kernel/srcu.c
+++ b/kernel/srcu.c
@@ -46,11 +46,9 @@
 int __init_srcu_struct(struct srcu_struct *sp, const char *name,
 		       struct lock_class_key *key)
 {
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
 	/* Don't re-initialize a lock while it is held. */
 	debug_check_no_locks_freed((void *)sp, sizeof(*sp));
 	lockdep_init_map(&sp->dep_map, name, key, 0);
-#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 	return init_srcu_struct_fields(sp);
 }
 EXPORT_SYMBOL_GPL(__init_srcu_struct);
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 4372ccb..090c288 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -287,11 +287,12 @@
 	goto repeat;
 }
 
+extern void sched_set_stop_task(int cpu, struct task_struct *stop);
+
 /* manage stopper for a cpu, mostly lifted from sched migration thread mgmt */
 static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb,
 					   unsigned long action, void *hcpu)
 {
-	struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
 	unsigned int cpu = (unsigned long)hcpu;
 	struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
 	struct task_struct *p;
@@ -304,13 +305,13 @@
 				   cpu);
 		if (IS_ERR(p))
 			return NOTIFY_BAD;
-		sched_setscheduler_nocheck(p, SCHED_FIFO, &param);
 		get_task_struct(p);
+		kthread_bind(p, cpu);
+		sched_set_stop_task(cpu, p);
 		stopper->thread = p;
 		break;
 
 	case CPU_ONLINE:
-		kthread_bind(stopper->thread, cpu);
 		/* strictly unnecessary, as first user will wake it */
 		wake_up_process(stopper->thread);
 		/* mark enabled */
@@ -325,6 +326,7 @@
 	{
 		struct cpu_stop_work *work;
 
+		sched_set_stop_task(cpu, NULL);
 		/* kill the stopper */
 		kthread_stop(stopper->thread);
 		/* drain remaining works */
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index bad369e..c782fe9 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -50,6 +50,7 @@
 cond_syscall(sys_recvmsg);
 cond_syscall(sys_recvmmsg);
 cond_syscall(compat_sys_recvmsg);
+cond_syscall(compat_sys_recv);
 cond_syscall(compat_sys_recvfrom);
 cond_syscall(compat_sys_recvmmsg);
 cond_syscall(sys_socketcall);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index f88552c..3a45c22 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2485,7 +2485,7 @@
 		kbuf[left] = 0;
 	}
 
-	for (; left && vleft--; i++, min++, max++, first=0) {
+	for (; left && vleft--; i++, first = 0) {
 		unsigned long val;
 
 		if (write) {
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index 04cdcf7..10b90d8 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -143,15 +143,6 @@
 				if (!table->maxlen)
 					set_fail(&fail, table, "No maxlen");
 			}
-			if ((table->proc_handler == proc_doulongvec_minmax) ||
-			    (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) {
-				if (table->maxlen > sizeof (unsigned long)) {
-					if (!table->extra1)
-						set_fail(&fail, table, "No min");
-					if (!table->extra2)
-						set_fail(&fail, table, "No max");
-				}
-			}
 #ifdef CONFIG_PROC_SYSCTL
 			if (table->procname && !table->proc_handler)
 				set_fail(&fail, table, "No proc_handler");
diff --git a/kernel/test_kprobes.c b/kernel/test_kprobes.c
index 4f10451..f8b11a2 100644
--- a/kernel/test_kprobes.c
+++ b/kernel/test_kprobes.c
@@ -115,7 +115,9 @@
 	int ret;
 	struct kprobe *kps[2] = {&kp, &kp2};
 
-	kp.addr = 0; /* addr should be cleard for reusing kprobe. */
+	/* addr and flags should be cleard for reusing kprobe. */
+	kp.addr = NULL;
+	kp.flags = 0;
 	ret = register_kprobes(kps, 2);
 	if (ret < 0) {
 		printk(KERN_ERR "Kprobe smoke test failed: "
@@ -210,7 +212,9 @@
 	int ret;
 	struct jprobe *jps[2] = {&jp, &jp2};
 
-	jp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */
+	/* addr and flags should be cleard for reusing kprobe. */
+	jp.kp.addr = NULL;
+	jp.kp.flags = 0;
 	ret = register_jprobes(jps, 2);
 	if (ret < 0) {
 		printk(KERN_ERR "Kprobe smoke test failed: "
@@ -323,7 +327,9 @@
 	int ret;
 	struct kretprobe *rps[2] = {&rp, &rp2};
 
-	rp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */
+	/* addr and flags should be cleard for reusing kprobe. */
+	rp.kp.addr = NULL;
+	rp.kp.flags = 0;
 	ret = register_kretprobes(rps, 2);
 	if (ret < 0) {
 		printk(KERN_ERR "Kprobe smoke test failed: "
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index c631168..d232189 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -149,10 +149,18 @@
 	time_reftime = get_seconds();
 
 	offset64    = offset;
-	freq_adj    = (offset64 * secs) <<
-			(NTP_SCALE_SHIFT - 2 * (SHIFT_PLL + 2 + time_constant));
+	freq_adj    = ntp_update_offset_fll(offset64, secs);
 
-	freq_adj    += ntp_update_offset_fll(offset64, secs);
+	/*
+	 * Clamp update interval to reduce PLL gain with low
+	 * sampling rate (e.g. intermittent network connection)
+	 * to avoid instability.
+	 */
+	if (unlikely(secs > 1 << (SHIFT_PLL + 1 + time_constant)))
+		secs = 1 << (SHIFT_PLL + 1 + time_constant);
+
+	freq_adj    += (offset64 * secs) <<
+			(NTP_SCALE_SHIFT - 2 * (SHIFT_PLL + 2 + time_constant));
 
 	freq_adj    = min(freq_adj + time_freq, MAXFREQ_SCALED);
 
diff --git a/kernel/timer.c b/kernel/timer.c
index 97bf05b..68a9ae7 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -37,7 +37,7 @@
 #include <linux/delay.h>
 #include <linux/tick.h>
 #include <linux/kallsyms.h>
-#include <linux/perf_event.h>
+#include <linux/irq_work.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 
@@ -1279,7 +1279,10 @@
 	run_local_timers();
 	rcu_check_callbacks(cpu, user_tick);
 	printk_tick();
-	perf_event_do_pending();
+#ifdef CONFIG_IRQ_WORK
+	if (in_irq())
+		irq_work_run();
+#endif
 	scheduler_tick();
 	run_posix_cpu_timers(p);
 }
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 538501c..e04b8bc 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -49,6 +49,11 @@
 	help
 	  See Documentation/trace/ftrace-design.txt
 
+config HAVE_C_RECORDMCOUNT
+	bool
+	help
+	  C version of recordmcount available?
+
 config TRACER_MAX_TRACE
 	bool
 
@@ -121,7 +126,7 @@
 config FUNCTION_TRACER
 	bool "Kernel Function Tracer"
 	depends on HAVE_FUNCTION_TRACER
-	select FRAME_POINTER
+	select FRAME_POINTER if (!ARM_UNWIND)
 	select KALLSYMS
 	select GENERIC_TRACER
 	select CONTEXT_SWITCH_TRACER
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 959f8d6..bc251ed 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -23,7 +23,6 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
-#include <linux/smp_lock.h>
 #include <linux/time.h>
 #include <linux/uaccess.h>
 
@@ -326,6 +325,7 @@
 	.owner =	THIS_MODULE,
 	.open =		blk_dropped_open,
 	.read =		blk_dropped_read,
+	.llseek =	default_llseek,
 };
 
 static int blk_msg_open(struct inode *inode, struct file *filp)
@@ -365,6 +365,7 @@
 	.owner =	THIS_MODULE,
 	.open =		blk_msg_open,
 	.write =	blk_msg_write,
+	.llseek =	noop_llseek,
 };
 
 /*
@@ -639,7 +640,6 @@
 	if (!q)
 		return -ENXIO;
 
-	lock_kernel();
 	mutex_lock(&bdev->bd_mutex);
 
 	switch (cmd) {
@@ -667,7 +667,6 @@
 	}
 
 	mutex_unlock(&bdev->bd_mutex);
-	unlock_kernel();
 	return ret;
 }
 
@@ -1652,10 +1651,9 @@
 	struct block_device *bdev;
 	ssize_t ret = -ENXIO;
 
-	lock_kernel();
 	bdev = bdget(part_devt(p));
 	if (bdev == NULL)
-		goto out_unlock_kernel;
+		goto out;
 
 	q = blk_trace_get_queue(bdev);
 	if (q == NULL)
@@ -1683,8 +1681,7 @@
 	mutex_unlock(&bdev->bd_mutex);
 out_bdput:
 	bdput(bdev);
-out_unlock_kernel:
-	unlock_kernel();
+out:
 	return ret;
 }
 
@@ -1714,11 +1711,10 @@
 
 	ret = -ENXIO;
 
-	lock_kernel();
 	p = dev_to_part(dev);
 	bdev = bdget(part_devt(p));
 	if (bdev == NULL)
-		goto out_unlock_kernel;
+		goto out;
 
 	q = blk_trace_get_queue(bdev);
 	if (q == NULL)
@@ -1753,8 +1749,6 @@
 	mutex_unlock(&bdev->bd_mutex);
 out_bdput:
 	bdput(bdev);
-out_unlock_kernel:
-	unlock_kernel();
 out:
 	return ret ? ret : count;
 }
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index fa7ece6..f3dadae 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -800,6 +800,7 @@
 	.open		= tracing_open_generic,
 	.read		= ftrace_profile_read,
 	.write		= ftrace_profile_write,
+	.llseek		= default_llseek,
 };
 
 /* used to initialize the real stat files */
@@ -884,10 +885,8 @@
 	FTRACE_ENABLE_CALLS		= (1 << 0),
 	FTRACE_DISABLE_CALLS		= (1 << 1),
 	FTRACE_UPDATE_TRACE_FUNC	= (1 << 2),
-	FTRACE_ENABLE_MCOUNT		= (1 << 3),
-	FTRACE_DISABLE_MCOUNT		= (1 << 4),
-	FTRACE_START_FUNC_RET		= (1 << 5),
-	FTRACE_STOP_FUNC_RET		= (1 << 6),
+	FTRACE_START_FUNC_RET		= (1 << 3),
+	FTRACE_STOP_FUNC_RET		= (1 << 4),
 };
 
 static int ftrace_filtered;
@@ -1226,8 +1225,6 @@
 
 static void ftrace_startup_sysctl(void)
 {
-	int command = FTRACE_ENABLE_MCOUNT;
-
 	if (unlikely(ftrace_disabled))
 		return;
 
@@ -1235,23 +1232,17 @@
 	saved_ftrace_func = NULL;
 	/* ftrace_start_up is true if we want ftrace running */
 	if (ftrace_start_up)
-		command |= FTRACE_ENABLE_CALLS;
-
-	ftrace_run_update_code(command);
+		ftrace_run_update_code(FTRACE_ENABLE_CALLS);
 }
 
 static void ftrace_shutdown_sysctl(void)
 {
-	int command = FTRACE_DISABLE_MCOUNT;
-
 	if (unlikely(ftrace_disabled))
 		return;
 
 	/* ftrace_start_up is true if ftrace is running */
 	if (ftrace_start_up)
-		command |= FTRACE_DISABLE_CALLS;
-
-	ftrace_run_update_code(command);
+		ftrace_run_update_code(FTRACE_DISABLE_CALLS);
 }
 
 static cycle_t		ftrace_update_time;
@@ -1368,24 +1359,29 @@
 #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
 
 struct ftrace_iterator {
-	struct ftrace_page	*pg;
-	int			hidx;
-	int			idx;
-	unsigned		flags;
-	struct trace_parser	parser;
+	loff_t				pos;
+	loff_t				func_pos;
+	struct ftrace_page		*pg;
+	struct dyn_ftrace		*func;
+	struct ftrace_func_probe	*probe;
+	struct trace_parser		parser;
+	int				hidx;
+	int				idx;
+	unsigned			flags;
 };
 
 static void *
-t_hash_next(struct seq_file *m, void *v, loff_t *pos)
+t_hash_next(struct seq_file *m, loff_t *pos)
 {
 	struct ftrace_iterator *iter = m->private;
-	struct hlist_node *hnd = v;
+	struct hlist_node *hnd = NULL;
 	struct hlist_head *hhd;
 
-	WARN_ON(!(iter->flags & FTRACE_ITER_HASH));
-
 	(*pos)++;
+	iter->pos = *pos;
 
+	if (iter->probe)
+		hnd = &iter->probe->node;
  retry:
 	if (iter->hidx >= FTRACE_FUNC_HASHSIZE)
 		return NULL;
@@ -1408,7 +1404,12 @@
 		}
 	}
 
-	return hnd;
+	if (WARN_ON_ONCE(!hnd))
+		return NULL;
+
+	iter->probe = hlist_entry(hnd, struct ftrace_func_probe, node);
+
+	return iter;
 }
 
 static void *t_hash_start(struct seq_file *m, loff_t *pos)
@@ -1417,26 +1418,32 @@
 	void *p = NULL;
 	loff_t l;
 
-	if (!(iter->flags & FTRACE_ITER_HASH))
-		*pos = 0;
-
-	iter->flags |= FTRACE_ITER_HASH;
+	if (iter->func_pos > *pos)
+		return NULL;
 
 	iter->hidx = 0;
-	for (l = 0; l <= *pos; ) {
-		p = t_hash_next(m, p, &l);
+	for (l = 0; l <= (*pos - iter->func_pos); ) {
+		p = t_hash_next(m, &l);
 		if (!p)
 			break;
 	}
-	return p;
+	if (!p)
+		return NULL;
+
+	/* Only set this if we have an item */
+	iter->flags |= FTRACE_ITER_HASH;
+
+	return iter;
 }
 
-static int t_hash_show(struct seq_file *m, void *v)
+static int
+t_hash_show(struct seq_file *m, struct ftrace_iterator *iter)
 {
 	struct ftrace_func_probe *rec;
-	struct hlist_node *hnd = v;
 
-	rec = hlist_entry(hnd, struct ftrace_func_probe, node);
+	rec = iter->probe;
+	if (WARN_ON_ONCE(!rec))
+		return -EIO;
 
 	if (rec->ops->print)
 		return rec->ops->print(m, rec->ip, rec->ops, rec->data);
@@ -1457,12 +1464,13 @@
 	struct dyn_ftrace *rec = NULL;
 
 	if (iter->flags & FTRACE_ITER_HASH)
-		return t_hash_next(m, v, pos);
+		return t_hash_next(m, pos);
 
 	(*pos)++;
+	iter->pos = *pos;
 
 	if (iter->flags & FTRACE_ITER_PRINTALL)
-		return NULL;
+		return t_hash_start(m, pos);
 
  retry:
 	if (iter->idx >= iter->pg->index) {
@@ -1491,7 +1499,20 @@
 		}
 	}
 
-	return rec;
+	if (!rec)
+		return t_hash_start(m, pos);
+
+	iter->func_pos = *pos;
+	iter->func = rec;
+
+	return iter;
+}
+
+static void reset_iter_read(struct ftrace_iterator *iter)
+{
+	iter->pos = 0;
+	iter->func_pos = 0;
+	iter->flags &= ~(FTRACE_ITER_PRINTALL & FTRACE_ITER_HASH);
 }
 
 static void *t_start(struct seq_file *m, loff_t *pos)
@@ -1502,6 +1523,12 @@
 
 	mutex_lock(&ftrace_lock);
 	/*
+	 * If an lseek was done, then reset and start from beginning.
+	 */
+	if (*pos < iter->pos)
+		reset_iter_read(iter);
+
+	/*
 	 * For set_ftrace_filter reading, if we have the filter
 	 * off, we can short cut and just print out that all
 	 * functions are enabled.
@@ -1518,6 +1545,11 @@
 	if (iter->flags & FTRACE_ITER_HASH)
 		return t_hash_start(m, pos);
 
+	/*
+	 * Unfortunately, we need to restart at ftrace_pages_start
+	 * every time we let go of the ftrace_mutex. This is because
+	 * those pointers can change without the lock.
+	 */
 	iter->pg = ftrace_pages_start;
 	iter->idx = 0;
 	for (l = 0; l <= *pos; ) {
@@ -1526,10 +1558,14 @@
 			break;
 	}
 
-	if (!p && iter->flags & FTRACE_ITER_FILTER)
-		return t_hash_start(m, pos);
+	if (!p) {
+		if (iter->flags & FTRACE_ITER_FILTER)
+			return t_hash_start(m, pos);
 
-	return p;
+		return NULL;
+	}
+
+	return iter;
 }
 
 static void t_stop(struct seq_file *m, void *p)
@@ -1540,16 +1576,18 @@
 static int t_show(struct seq_file *m, void *v)
 {
 	struct ftrace_iterator *iter = m->private;
-	struct dyn_ftrace *rec = v;
+	struct dyn_ftrace *rec;
 
 	if (iter->flags & FTRACE_ITER_HASH)
-		return t_hash_show(m, v);
+		return t_hash_show(m, iter);
 
 	if (iter->flags & FTRACE_ITER_PRINTALL) {
 		seq_printf(m, "#### all functions enabled ####\n");
 		return 0;
 	}
 
+	rec = iter->func;
+
 	if (!rec)
 		return 0;
 
@@ -1601,8 +1639,8 @@
 
 	ret = ftrace_avail_open(inode, file);
 	if (!ret) {
-		m = (struct seq_file *)file->private_data;
-		iter = (struct ftrace_iterator *)m->private;
+		m = file->private_data;
+		iter = m->private;
 		iter->flags = FTRACE_ITER_FAILURES;
 	}
 
@@ -2418,7 +2456,7 @@
 	.open = ftrace_filter_open,
 	.read = seq_read,
 	.write = ftrace_filter_write,
-	.llseek = no_llseek,
+	.llseek = ftrace_regex_lseek,
 	.release = ftrace_filter_release,
 };
 
@@ -2632,6 +2670,7 @@
 	.read		= seq_read,
 	.write		= ftrace_graph_write,
 	.release	= ftrace_graph_release,
+	.llseek		= seq_lseek,
 };
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 492197e..c3dab05 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -405,7 +405,7 @@
 #define BUF_MAX_DATA_SIZE (BUF_PAGE_SIZE - (sizeof(u32) * 2))
 
 /* Max number of timestamps that can fit on a page */
-#define RB_TIMESTAMPS_PER_PAGE	(BUF_PAGE_SIZE / RB_LEN_TIME_STAMP)
+#define RB_TIMESTAMPS_PER_PAGE	(BUF_PAGE_SIZE / RB_LEN_TIME_EXTEND)
 
 int ring_buffer_print_page_header(struct trace_seq *s)
 {
@@ -2606,6 +2606,19 @@
 }
 EXPORT_SYMBOL_GPL(ring_buffer_record_enable_cpu);
 
+/*
+ * The total entries in the ring buffer is the running counter
+ * of entries entered into the ring buffer, minus the sum of
+ * the entries read from the ring buffer and the number of
+ * entries that were overwritten.
+ */
+static inline unsigned long
+rb_num_of_entries(struct ring_buffer_per_cpu *cpu_buffer)
+{
+	return local_read(&cpu_buffer->entries) -
+		(local_read(&cpu_buffer->overrun) + cpu_buffer->read);
+}
+
 /**
  * ring_buffer_entries_cpu - get the number of entries in a cpu buffer
  * @buffer: The ring buffer
@@ -2614,16 +2627,13 @@
 unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu)
 {
 	struct ring_buffer_per_cpu *cpu_buffer;
-	unsigned long ret;
 
 	if (!cpumask_test_cpu(cpu, buffer->cpumask))
 		return 0;
 
 	cpu_buffer = buffer->buffers[cpu];
-	ret = (local_read(&cpu_buffer->entries) - local_read(&cpu_buffer->overrun))
-		- cpu_buffer->read;
 
-	return ret;
+	return rb_num_of_entries(cpu_buffer);
 }
 EXPORT_SYMBOL_GPL(ring_buffer_entries_cpu);
 
@@ -2684,8 +2694,7 @@
 	/* if you care about this being correct, lock the buffer */
 	for_each_buffer_cpu(buffer, cpu) {
 		cpu_buffer = buffer->buffers[cpu];
-		entries += (local_read(&cpu_buffer->entries) -
-			    local_read(&cpu_buffer->overrun)) - cpu_buffer->read;
+		entries += rb_num_of_entries(cpu_buffer);
 	}
 
 	return entries;
@@ -3965,6 +3974,7 @@
 	.open		= tracing_open_generic,
 	.read		= rb_simple_read,
 	.write		= rb_simple_write,
+	.llseek		= default_llseek,
 };
 
 
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 9ec59f5..001bcd2 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2196,7 +2196,7 @@
 
 static int tracing_release(struct inode *inode, struct file *file)
 {
-	struct seq_file *m = (struct seq_file *)file->private_data;
+	struct seq_file *m = file->private_data;
 	struct trace_iterator *iter;
 	int cpu;
 
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index d39b3c5..9021f8c 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -343,6 +343,10 @@
 		    unsigned long ip,
 		    unsigned long parent_ip,
 		    unsigned long flags, int pc);
+void trace_graph_function(struct trace_array *tr,
+		    unsigned long ip,
+		    unsigned long parent_ip,
+		    unsigned long flags, int pc);
 void trace_default_header(struct seq_file *m);
 void print_trace_header(struct seq_file *m, struct trace_iterator *iter);
 int trace_empty(struct trace_iterator *iter);
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index 31cc4cb..39c059c 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -9,7 +9,7 @@
 #include <linux/kprobes.h>
 #include "trace.h"
 
-static char *perf_trace_buf[4];
+static char __percpu *perf_trace_buf[PERF_NR_CONTEXTS];
 
 /*
  * Force it to be aligned to unsigned long to avoid misaligned accesses
@@ -24,7 +24,7 @@
 static int perf_trace_event_init(struct ftrace_event_call *tp_event,
 				 struct perf_event *p_event)
 {
-	struct hlist_head *list;
+	struct hlist_head __percpu *list;
 	int ret = -ENOMEM;
 	int cpu;
 
@@ -42,11 +42,11 @@
 	tp_event->perf_events = list;
 
 	if (!total_ref_count) {
-		char *buf;
+		char __percpu *buf;
 		int i;
 
-		for (i = 0; i < 4; i++) {
-			buf = (char *)alloc_percpu(perf_trace_t);
+		for (i = 0; i < PERF_NR_CONTEXTS; i++) {
+			buf = (char __percpu *)alloc_percpu(perf_trace_t);
 			if (!buf)
 				goto fail;
 
@@ -65,7 +65,7 @@
 	if (!total_ref_count) {
 		int i;
 
-		for (i = 0; i < 4; i++) {
+		for (i = 0; i < PERF_NR_CONTEXTS; i++) {
 			free_percpu(perf_trace_buf[i]);
 			perf_trace_buf[i] = NULL;
 		}
@@ -101,22 +101,26 @@
 	return ret;
 }
 
-int perf_trace_enable(struct perf_event *p_event)
+int perf_trace_add(struct perf_event *p_event, int flags)
 {
 	struct ftrace_event_call *tp_event = p_event->tp_event;
+	struct hlist_head __percpu *pcpu_list;
 	struct hlist_head *list;
 
-	list = tp_event->perf_events;
-	if (WARN_ON_ONCE(!list))
+	pcpu_list = tp_event->perf_events;
+	if (WARN_ON_ONCE(!pcpu_list))
 		return -EINVAL;
 
-	list = this_cpu_ptr(list);
+	if (!(flags & PERF_EF_START))
+		p_event->hw.state = PERF_HES_STOPPED;
+
+	list = this_cpu_ptr(pcpu_list);
 	hlist_add_head_rcu(&p_event->hlist_entry, list);
 
 	return 0;
 }
 
-void perf_trace_disable(struct perf_event *p_event)
+void perf_trace_del(struct perf_event *p_event, int flags)
 {
 	hlist_del_rcu(&p_event->hlist_entry);
 }
@@ -142,7 +146,7 @@
 	tp_event->perf_events = NULL;
 
 	if (!--total_ref_count) {
-		for (i = 0; i < 4; i++) {
+		for (i = 0; i < PERF_NR_CONTEXTS; i++) {
 			free_percpu(perf_trace_buf[i]);
 			perf_trace_buf[i] = NULL;
 		}
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 4c758f1..0725eea 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -600,21 +600,29 @@
 
 enum {
 	FORMAT_HEADER		= 1,
-	FORMAT_PRINTFMT		= 2,
+	FORMAT_FIELD_SEPERATOR	= 2,
+	FORMAT_PRINTFMT		= 3,
 };
 
 static void *f_next(struct seq_file *m, void *v, loff_t *pos)
 {
 	struct ftrace_event_call *call = m->private;
 	struct ftrace_event_field *field;
-	struct list_head *head;
+	struct list_head *common_head = &ftrace_common_fields;
+	struct list_head *head = trace_get_fields(call);
 
 	(*pos)++;
 
 	switch ((unsigned long)v) {
 	case FORMAT_HEADER:
-		head = &ftrace_common_fields;
+		if (unlikely(list_empty(common_head)))
+			return NULL;
 
+		field = list_entry(common_head->prev,
+				   struct ftrace_event_field, link);
+		return field;
+
+	case FORMAT_FIELD_SEPERATOR:
 		if (unlikely(list_empty(head)))
 			return NULL;
 
@@ -626,31 +634,10 @@
 		return NULL;
 	}
 
-	head = trace_get_fields(call);
-
-	/*
-	 * To separate common fields from event fields, the
-	 * LSB is set on the first event field. Clear it in case.
-	 */
-	v = (void *)((unsigned long)v & ~1L);
-
 	field = v;
-	/*
-	 * If this is a common field, and at the end of the list, then
-	 * continue with main list.
-	 */
-	if (field->link.prev == &ftrace_common_fields) {
-		if (unlikely(list_empty(head)))
-			return NULL;
-		field = list_entry(head->prev, struct ftrace_event_field, link);
-		/* Set the LSB to notify f_show to print an extra newline */
-		field = (struct ftrace_event_field *)
-			((unsigned long)field | 1);
-		return field;
-	}
-
-	/* If we are done tell f_show to print the format */
-	if (field->link.prev == head)
+	if (field->link.prev == common_head)
+		return (void *)FORMAT_FIELD_SEPERATOR;
+	else if (field->link.prev == head)
 		return (void *)FORMAT_PRINTFMT;
 
 	field = list_entry(field->link.prev, struct ftrace_event_field, link);
@@ -688,22 +675,16 @@
 		seq_printf(m, "format:\n");
 		return 0;
 
+	case FORMAT_FIELD_SEPERATOR:
+		seq_putc(m, '\n');
+		return 0;
+
 	case FORMAT_PRINTFMT:
 		seq_printf(m, "\nprint fmt: %s\n",
 			   call->print_fmt);
 		return 0;
 	}
 
-	/*
-	 * To separate common fields from event fields, the
-	 * LSB is set on the first event field. Clear it and
-	 * print a newline if it is set.
-	 */
-	if ((unsigned long)v & 1) {
-		seq_putc(m, '\n');
-		v = (void *)((unsigned long)v & ~1L);
-	}
-
 	field = v;
 
 	/*
@@ -951,6 +932,7 @@
 	.open = tracing_open_generic,
 	.read = event_enable_read,
 	.write = event_enable_write,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_event_format_fops = {
@@ -963,29 +945,34 @@
 static const struct file_operations ftrace_event_id_fops = {
 	.open = tracing_open_generic,
 	.read = event_id_read,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_event_filter_fops = {
 	.open = tracing_open_generic,
 	.read = event_filter_read,
 	.write = event_filter_write,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_subsystem_filter_fops = {
 	.open = tracing_open_generic,
 	.read = subsystem_filter_read,
 	.write = subsystem_filter_write,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_system_enable_fops = {
 	.open = tracing_open_generic,
 	.read = system_enable_read,
 	.write = system_enable_write,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_show_header_fops = {
 	.open = tracing_open_generic,
 	.read = show_header,
+	.llseek = default_llseek,
 };
 
 static struct dentry *event_trace_events_dir(void)
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 6f23369..76b0598 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -15,15 +15,19 @@
 #include "trace.h"
 #include "trace_output.h"
 
+/* When set, irq functions will be ignored */
+static int ftrace_graph_skip_irqs;
+
 struct fgraph_cpu_data {
 	pid_t		last_pid;
 	int		depth;
+	int		depth_irq;
 	int		ignore;
 	unsigned long	enter_funcs[FTRACE_RETFUNC_DEPTH];
 };
 
 struct fgraph_data {
-	struct fgraph_cpu_data		*cpu_data;
+	struct fgraph_cpu_data __percpu *cpu_data;
 
 	/* Place to preserve last processed entry. */
 	struct ftrace_graph_ent_entry	ent;
@@ -41,6 +45,7 @@
 #define TRACE_GRAPH_PRINT_PROC		0x8
 #define TRACE_GRAPH_PRINT_DURATION	0x10
 #define TRACE_GRAPH_PRINT_ABS_TIME	0x20
+#define TRACE_GRAPH_PRINT_IRQS		0x40
 
 static struct tracer_opt trace_opts[] = {
 	/* Display overruns? (for self-debug purpose) */
@@ -55,13 +60,15 @@
 	{ TRACER_OPT(funcgraph-duration, TRACE_GRAPH_PRINT_DURATION) },
 	/* Display absolute time of an entry */
 	{ TRACER_OPT(funcgraph-abstime, TRACE_GRAPH_PRINT_ABS_TIME) },
+	/* Display interrupts */
+	{ TRACER_OPT(funcgraph-irqs, TRACE_GRAPH_PRINT_IRQS) },
 	{ } /* Empty entry */
 };
 
 static struct tracer_flags tracer_flags = {
 	/* Don't display overruns and proc by default */
 	.val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD |
-	       TRACE_GRAPH_PRINT_DURATION,
+	       TRACE_GRAPH_PRINT_DURATION | TRACE_GRAPH_PRINT_IRQS,
 	.opts = trace_opts
 };
 
@@ -204,6 +211,14 @@
 	return 1;
 }
 
+static inline int ftrace_graph_ignore_irqs(void)
+{
+	if (!ftrace_graph_skip_irqs)
+		return 0;
+
+	return in_irq();
+}
+
 int trace_graph_entry(struct ftrace_graph_ent *trace)
 {
 	struct trace_array *tr = graph_array;
@@ -218,7 +233,8 @@
 		return 0;
 
 	/* trace it when it is-nested-in or is a function enabled. */
-	if (!(trace->depth || ftrace_graph_addr(trace->func)))
+	if (!(trace->depth || ftrace_graph_addr(trace->func)) ||
+	      ftrace_graph_ignore_irqs())
 		return 0;
 
 	local_irq_save(flags);
@@ -246,6 +262,34 @@
 		return trace_graph_entry(trace);
 }
 
+static void
+__trace_graph_function(struct trace_array *tr,
+		unsigned long ip, unsigned long flags, int pc)
+{
+	u64 time = trace_clock_local();
+	struct ftrace_graph_ent ent = {
+		.func  = ip,
+		.depth = 0,
+	};
+	struct ftrace_graph_ret ret = {
+		.func     = ip,
+		.depth    = 0,
+		.calltime = time,
+		.rettime  = time,
+	};
+
+	__trace_graph_entry(tr, &ent, flags, pc);
+	__trace_graph_return(tr, &ret, flags, pc);
+}
+
+void
+trace_graph_function(struct trace_array *tr,
+		unsigned long ip, unsigned long parent_ip,
+		unsigned long flags, int pc)
+{
+	__trace_graph_function(tr, ip, flags, pc);
+}
+
 void __trace_graph_return(struct trace_array *tr,
 				struct ftrace_graph_ret *trace,
 				unsigned long flags,
@@ -649,8 +693,9 @@
 
 	/* Print nsecs (we don't want to exceed 7 numbers) */
 	if (len < 7) {
-		snprintf(nsecs_str, min(sizeof(nsecs_str), 8UL - len), "%03lu",
-			 nsecs_rem);
+		size_t slen = min_t(size_t, sizeof(nsecs_str), 8UL - len);
+
+		snprintf(nsecs_str, slen, "%03lu", nsecs_rem);
 		ret = trace_seq_printf(s, ".%s", nsecs_str);
 		if (!ret)
 			return TRACE_TYPE_PARTIAL_LINE;
@@ -855,6 +900,108 @@
 	return 0;
 }
 
+/*
+ * Entry check for irq code
+ *
+ * returns 1 if
+ *  - we are inside irq code
+ *  - we just extered irq code
+ *
+ * retunns 0 if
+ *  - funcgraph-interrupts option is set
+ *  - we are not inside irq code
+ */
+static int
+check_irq_entry(struct trace_iterator *iter, u32 flags,
+		unsigned long addr, int depth)
+{
+	int cpu = iter->cpu;
+	int *depth_irq;
+	struct fgraph_data *data = iter->private;
+
+	/*
+	 * If we are either displaying irqs, or we got called as
+	 * a graph event and private data does not exist,
+	 * then we bypass the irq check.
+	 */
+	if ((flags & TRACE_GRAPH_PRINT_IRQS) ||
+	    (!data))
+		return 0;
+
+	depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
+
+	/*
+	 * We are inside the irq code
+	 */
+	if (*depth_irq >= 0)
+		return 1;
+
+	if ((addr < (unsigned long)__irqentry_text_start) ||
+	    (addr >= (unsigned long)__irqentry_text_end))
+		return 0;
+
+	/*
+	 * We are entering irq code.
+	 */
+	*depth_irq = depth;
+	return 1;
+}
+
+/*
+ * Return check for irq code
+ *
+ * returns 1 if
+ *  - we are inside irq code
+ *  - we just left irq code
+ *
+ * returns 0 if
+ *  - funcgraph-interrupts option is set
+ *  - we are not inside irq code
+ */
+static int
+check_irq_return(struct trace_iterator *iter, u32 flags, int depth)
+{
+	int cpu = iter->cpu;
+	int *depth_irq;
+	struct fgraph_data *data = iter->private;
+
+	/*
+	 * If we are either displaying irqs, or we got called as
+	 * a graph event and private data does not exist,
+	 * then we bypass the irq check.
+	 */
+	if ((flags & TRACE_GRAPH_PRINT_IRQS) ||
+	    (!data))
+		return 0;
+
+	depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
+
+	/*
+	 * We are not inside the irq code.
+	 */
+	if (*depth_irq == -1)
+		return 0;
+
+	/*
+	 * We are inside the irq code, and this is returning entry.
+	 * Let's not trace it and clear the entry depth, since
+	 * we are out of irq code.
+	 *
+	 * This condition ensures that we 'leave the irq code' once
+	 * we are out of the entry depth. Thus protecting us from
+	 * the RETURN entry loss.
+	 */
+	if (*depth_irq >= depth) {
+		*depth_irq = -1;
+		return 1;
+	}
+
+	/*
+	 * We are inside the irq code, and this is not the entry.
+	 */
+	return 1;
+}
+
 static enum print_line_t
 print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
 			struct trace_iterator *iter, u32 flags)
@@ -865,6 +1012,9 @@
 	static enum print_line_t ret;
 	int cpu = iter->cpu;
 
+	if (check_irq_entry(iter, flags, call->func, call->depth))
+		return TRACE_TYPE_HANDLED;
+
 	if (print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func, flags))
 		return TRACE_TYPE_PARTIAL_LINE;
 
@@ -902,6 +1052,9 @@
 	int ret;
 	int i;
 
+	if (check_irq_return(iter, flags, trace->depth))
+		return TRACE_TYPE_HANDLED;
+
 	if (data) {
 		struct fgraph_cpu_data *cpu_data;
 		int cpu = iter->cpu;
@@ -1054,7 +1207,7 @@
 
 
 enum print_line_t
-print_graph_function_flags(struct trace_iterator *iter, u32 flags)
+__print_graph_function_flags(struct trace_iterator *iter, u32 flags)
 {
 	struct ftrace_graph_ent_entry *field;
 	struct fgraph_data *data = iter->private;
@@ -1117,7 +1270,18 @@
 static enum print_line_t
 print_graph_function(struct trace_iterator *iter)
 {
-	return print_graph_function_flags(iter, tracer_flags.val);
+	return __print_graph_function_flags(iter, tracer_flags.val);
+}
+
+enum print_line_t print_graph_function_flags(struct trace_iterator *iter,
+					     u32 flags)
+{
+	if (trace_flags & TRACE_ITER_LATENCY_FMT)
+		flags |= TRACE_GRAPH_PRINT_DURATION;
+	else
+		flags |= TRACE_GRAPH_PRINT_ABS_TIME;
+
+	return __print_graph_function_flags(iter, flags);
 }
 
 static enum print_line_t
@@ -1149,7 +1313,7 @@
 	seq_printf(s, "#%.*s|||| /                     \n", size, spaces);
 }
 
-void print_graph_headers_flags(struct seq_file *s, u32 flags)
+static void __print_graph_headers_flags(struct seq_file *s, u32 flags)
 {
 	int lat = trace_flags & TRACE_ITER_LATENCY_FMT;
 
@@ -1190,6 +1354,23 @@
 	print_graph_headers_flags(s, tracer_flags.val);
 }
 
+void print_graph_headers_flags(struct seq_file *s, u32 flags)
+{
+	struct trace_iterator *iter = s->private;
+
+	if (trace_flags & TRACE_ITER_LATENCY_FMT) {
+		/* print nothing if the buffers are empty */
+		if (trace_empty(iter))
+			return;
+
+		print_trace_header(s, iter);
+		flags |= TRACE_GRAPH_PRINT_DURATION;
+	} else
+		flags |= TRACE_GRAPH_PRINT_ABS_TIME;
+
+	__print_graph_headers_flags(s, flags);
+}
+
 void graph_trace_open(struct trace_iterator *iter)
 {
 	/* pid and depth on the last trace processed */
@@ -1210,9 +1391,12 @@
 		pid_t *pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid);
 		int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth);
 		int *ignore = &(per_cpu_ptr(data->cpu_data, cpu)->ignore);
+		int *depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
+
 		*pid = -1;
 		*depth = 0;
 		*ignore = 0;
+		*depth_irq = -1;
 	}
 
 	iter->private = data;
@@ -1235,6 +1419,14 @@
 	}
 }
 
+static int func_graph_set_flag(u32 old_flags, u32 bit, int set)
+{
+	if (bit == TRACE_GRAPH_PRINT_IRQS)
+		ftrace_graph_skip_irqs = !set;
+
+	return 0;
+}
+
 static struct trace_event_functions graph_functions = {
 	.trace		= print_graph_function_event,
 };
@@ -1261,6 +1453,7 @@
 	.print_line	= print_graph_function,
 	.print_header	= print_graph_headers,
 	.flags		= &tracer_flags,
+	.set_flag	= func_graph_set_flag,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest	= trace_selftest_startup_function_graph,
 #endif
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index 73a6b06..5cf8c60 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -87,14 +87,22 @@
 
 #ifdef CONFIG_FUNCTION_TRACER
 /*
- * irqsoff uses its own tracer function to keep the overhead down:
+ * Prologue for the preempt and irqs off function tracers.
+ *
+ * Returns 1 if it is OK to continue, and data->disabled is
+ *            incremented.
+ *         0 if the trace is to be ignored, and data->disabled
+ *            is kept the same.
+ *
+ * Note, this function is also used outside this ifdef but
+ *  inside the #ifdef of the function graph tracer below.
+ *  This is OK, since the function graph tracer is
+ *  dependent on the function tracer.
  */
-static void
-irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip)
+static int func_prolog_dec(struct trace_array *tr,
+			   struct trace_array_cpu **data,
+			   unsigned long *flags)
 {
-	struct trace_array *tr = irqsoff_trace;
-	struct trace_array_cpu *data;
-	unsigned long flags;
 	long disabled;
 	int cpu;
 
@@ -106,18 +114,38 @@
 	 */
 	cpu = raw_smp_processor_id();
 	if (likely(!per_cpu(tracing_cpu, cpu)))
-		return;
+		return 0;
 
-	local_save_flags(flags);
+	local_save_flags(*flags);
 	/* slight chance to get a false positive on tracing_cpu */
-	if (!irqs_disabled_flags(flags))
-		return;
+	if (!irqs_disabled_flags(*flags))
+		return 0;
 
-	data = tr->data[cpu];
-	disabled = atomic_inc_return(&data->disabled);
+	*data = tr->data[cpu];
+	disabled = atomic_inc_return(&(*data)->disabled);
 
 	if (likely(disabled == 1))
-		trace_function(tr, ip, parent_ip, flags, preempt_count());
+		return 1;
+
+	atomic_dec(&(*data)->disabled);
+
+	return 0;
+}
+
+/*
+ * irqsoff uses its own tracer function to keep the overhead down:
+ */
+static void
+irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip)
+{
+	struct trace_array *tr = irqsoff_trace;
+	struct trace_array_cpu *data;
+	unsigned long flags;
+
+	if (!func_prolog_dec(tr, &data, &flags))
+		return;
+
+	trace_function(tr, ip, parent_ip, flags, preempt_count());
 
 	atomic_dec(&data->disabled);
 }
@@ -155,30 +183,16 @@
 	struct trace_array *tr = irqsoff_trace;
 	struct trace_array_cpu *data;
 	unsigned long flags;
-	long disabled;
 	int ret;
-	int cpu;
 	int pc;
 
-	cpu = raw_smp_processor_id();
-	if (likely(!per_cpu(tracing_cpu, cpu)))
+	if (!func_prolog_dec(tr, &data, &flags))
 		return 0;
 
-	local_save_flags(flags);
-	/* slight chance to get a false positive on tracing_cpu */
-	if (!irqs_disabled_flags(flags))
-		return 0;
-
-	data = tr->data[cpu];
-	disabled = atomic_inc_return(&data->disabled);
-
-	if (likely(disabled == 1)) {
-		pc = preempt_count();
-		ret = __trace_graph_entry(tr, trace, flags, pc);
-	} else
-		ret = 0;
-
+	pc = preempt_count();
+	ret = __trace_graph_entry(tr, trace, flags, pc);
 	atomic_dec(&data->disabled);
+
 	return ret;
 }
 
@@ -187,27 +201,13 @@
 	struct trace_array *tr = irqsoff_trace;
 	struct trace_array_cpu *data;
 	unsigned long flags;
-	long disabled;
-	int cpu;
 	int pc;
 
-	cpu = raw_smp_processor_id();
-	if (likely(!per_cpu(tracing_cpu, cpu)))
+	if (!func_prolog_dec(tr, &data, &flags))
 		return;
 
-	local_save_flags(flags);
-	/* slight chance to get a false positive on tracing_cpu */
-	if (!irqs_disabled_flags(flags))
-		return;
-
-	data = tr->data[cpu];
-	disabled = atomic_inc_return(&data->disabled);
-
-	if (likely(disabled == 1)) {
-		pc = preempt_count();
-		__trace_graph_return(tr, trace, flags, pc);
-	}
-
+	pc = preempt_count();
+	__trace_graph_return(tr, trace, flags, pc);
 	atomic_dec(&data->disabled);
 }
 
@@ -229,75 +229,33 @@
 
 static enum print_line_t irqsoff_print_line(struct trace_iterator *iter)
 {
-	u32 flags = GRAPH_TRACER_FLAGS;
-
-	if (trace_flags & TRACE_ITER_LATENCY_FMT)
-		flags |= TRACE_GRAPH_PRINT_DURATION;
-	else
-		flags |= TRACE_GRAPH_PRINT_ABS_TIME;
-
 	/*
 	 * In graph mode call the graph tracer output function,
 	 * otherwise go with the TRACE_FN event handler
 	 */
 	if (is_graph())
-		return print_graph_function_flags(iter, flags);
+		return print_graph_function_flags(iter, GRAPH_TRACER_FLAGS);
 
 	return TRACE_TYPE_UNHANDLED;
 }
 
 static void irqsoff_print_header(struct seq_file *s)
 {
-	if (is_graph()) {
-		struct trace_iterator *iter = s->private;
-		u32 flags = GRAPH_TRACER_FLAGS;
-
-		if (trace_flags & TRACE_ITER_LATENCY_FMT) {
-			/* print nothing if the buffers are empty */
-			if (trace_empty(iter))
-				return;
-
-			print_trace_header(s, iter);
-			flags |= TRACE_GRAPH_PRINT_DURATION;
-		} else
-			flags |= TRACE_GRAPH_PRINT_ABS_TIME;
-
-		print_graph_headers_flags(s, flags);
-	} else
+	if (is_graph())
+		print_graph_headers_flags(s, GRAPH_TRACER_FLAGS);
+	else
 		trace_default_header(s);
 }
 
 static void
-trace_graph_function(struct trace_array *tr,
-		 unsigned long ip, unsigned long flags, int pc)
-{
-	u64 time = trace_clock_local();
-	struct ftrace_graph_ent ent = {
-		.func  = ip,
-		.depth = 0,
-	};
-	struct ftrace_graph_ret ret = {
-		.func     = ip,
-		.depth    = 0,
-		.calltime = time,
-		.rettime  = time,
-	};
-
-	__trace_graph_entry(tr, &ent, flags, pc);
-	__trace_graph_return(tr, &ret, flags, pc);
-}
-
-static void
 __trace_function(struct trace_array *tr,
 		 unsigned long ip, unsigned long parent_ip,
 		 unsigned long flags, int pc)
 {
-	if (!is_graph())
+	if (is_graph())
+		trace_graph_function(tr, ip, parent_ip, flags, pc);
+	else
 		trace_function(tr, ip, parent_ip, flags, pc);
-	else {
-		trace_graph_function(tr, parent_ip, flags, pc);
-		trace_graph_function(tr, ip, flags, pc);
-	}
 }
 
 #else
diff --git a/kernel/trace/trace_kdb.c b/kernel/trace/trace_kdb.c
index 7b8ecd7..3c5c5df 100644
--- a/kernel/trace/trace_kdb.c
+++ b/kernel/trace/trace_kdb.c
@@ -13,7 +13,6 @@
 #include <linux/kdb.h>
 #include <linux/ftrace.h>
 
-#include "../debug/kdb/kdb_private.h"
 #include "trace.h"
 #include "trace_output.h"
 
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index 4086eae6..7319559 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -31,13 +31,81 @@
 static arch_spinlock_t wakeup_lock =
 	(arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
 
+static void wakeup_reset(struct trace_array *tr);
 static void __wakeup_reset(struct trace_array *tr);
+static int wakeup_graph_entry(struct ftrace_graph_ent *trace);
+static void wakeup_graph_return(struct ftrace_graph_ret *trace);
 
 static int save_lat_flag;
 
+#define TRACE_DISPLAY_GRAPH     1
+
+static struct tracer_opt trace_opts[] = {
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	/* display latency trace as call graph */
+	{ TRACER_OPT(display-graph, TRACE_DISPLAY_GRAPH) },
+#endif
+	{ } /* Empty entry */
+};
+
+static struct tracer_flags tracer_flags = {
+	.val  = 0,
+	.opts = trace_opts,
+};
+
+#define is_graph() (tracer_flags.val & TRACE_DISPLAY_GRAPH)
+
 #ifdef CONFIG_FUNCTION_TRACER
+
 /*
- * irqsoff uses its own tracer function to keep the overhead down:
+ * Prologue for the wakeup function tracers.
+ *
+ * Returns 1 if it is OK to continue, and preemption
+ *            is disabled and data->disabled is incremented.
+ *         0 if the trace is to be ignored, and preemption
+ *            is not disabled and data->disabled is
+ *            kept the same.
+ *
+ * Note, this function is also used outside this ifdef but
+ *  inside the #ifdef of the function graph tracer below.
+ *  This is OK, since the function graph tracer is
+ *  dependent on the function tracer.
+ */
+static int
+func_prolog_preempt_disable(struct trace_array *tr,
+			    struct trace_array_cpu **data,
+			    int *pc)
+{
+	long disabled;
+	int cpu;
+
+	if (likely(!wakeup_task))
+		return 0;
+
+	*pc = preempt_count();
+	preempt_disable_notrace();
+
+	cpu = raw_smp_processor_id();
+	if (cpu != wakeup_current_cpu)
+		goto out_enable;
+
+	*data = tr->data[cpu];
+	disabled = atomic_inc_return(&(*data)->disabled);
+	if (unlikely(disabled != 1))
+		goto out;
+
+	return 1;
+
+out:
+	atomic_dec(&(*data)->disabled);
+
+out_enable:
+	preempt_enable_notrace();
+	return 0;
+}
+
+/*
+ * wakeup uses its own tracer function to keep the overhead down:
  */
 static void
 wakeup_tracer_call(unsigned long ip, unsigned long parent_ip)
@@ -45,34 +113,16 @@
 	struct trace_array *tr = wakeup_trace;
 	struct trace_array_cpu *data;
 	unsigned long flags;
-	long disabled;
-	int cpu;
 	int pc;
 
-	if (likely(!wakeup_task))
+	if (!func_prolog_preempt_disable(tr, &data, &pc))
 		return;
 
-	pc = preempt_count();
-	preempt_disable_notrace();
-
-	cpu = raw_smp_processor_id();
-	if (cpu != wakeup_current_cpu)
-		goto out_enable;
-
-	data = tr->data[cpu];
-	disabled = atomic_inc_return(&data->disabled);
-	if (unlikely(disabled != 1))
-		goto out;
-
 	local_irq_save(flags);
-
 	trace_function(tr, ip, parent_ip, flags, pc);
-
 	local_irq_restore(flags);
 
- out:
 	atomic_dec(&data->disabled);
- out_enable:
 	preempt_enable_notrace();
 }
 
@@ -82,6 +132,156 @@
 };
 #endif /* CONFIG_FUNCTION_TRACER */
 
+static int start_func_tracer(int graph)
+{
+	int ret;
+
+	if (!graph)
+		ret = register_ftrace_function(&trace_ops);
+	else
+		ret = register_ftrace_graph(&wakeup_graph_return,
+					    &wakeup_graph_entry);
+
+	if (!ret && tracing_is_enabled())
+		tracer_enabled = 1;
+	else
+		tracer_enabled = 0;
+
+	return ret;
+}
+
+static void stop_func_tracer(int graph)
+{
+	tracer_enabled = 0;
+
+	if (!graph)
+		unregister_ftrace_function(&trace_ops);
+	else
+		unregister_ftrace_graph();
+}
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+static int wakeup_set_flag(u32 old_flags, u32 bit, int set)
+{
+
+	if (!(bit & TRACE_DISPLAY_GRAPH))
+		return -EINVAL;
+
+	if (!(is_graph() ^ set))
+		return 0;
+
+	stop_func_tracer(!set);
+
+	wakeup_reset(wakeup_trace);
+	tracing_max_latency = 0;
+
+	return start_func_tracer(set);
+}
+
+static int wakeup_graph_entry(struct ftrace_graph_ent *trace)
+{
+	struct trace_array *tr = wakeup_trace;
+	struct trace_array_cpu *data;
+	unsigned long flags;
+	int pc, ret = 0;
+
+	if (!func_prolog_preempt_disable(tr, &data, &pc))
+		return 0;
+
+	local_save_flags(flags);
+	ret = __trace_graph_entry(tr, trace, flags, pc);
+	atomic_dec(&data->disabled);
+	preempt_enable_notrace();
+
+	return ret;
+}
+
+static void wakeup_graph_return(struct ftrace_graph_ret *trace)
+{
+	struct trace_array *tr = wakeup_trace;
+	struct trace_array_cpu *data;
+	unsigned long flags;
+	int pc;
+
+	if (!func_prolog_preempt_disable(tr, &data, &pc))
+		return;
+
+	local_save_flags(flags);
+	__trace_graph_return(tr, trace, flags, pc);
+	atomic_dec(&data->disabled);
+
+	preempt_enable_notrace();
+	return;
+}
+
+static void wakeup_trace_open(struct trace_iterator *iter)
+{
+	if (is_graph())
+		graph_trace_open(iter);
+}
+
+static void wakeup_trace_close(struct trace_iterator *iter)
+{
+	if (iter->private)
+		graph_trace_close(iter);
+}
+
+#define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_PROC)
+
+static enum print_line_t wakeup_print_line(struct trace_iterator *iter)
+{
+	/*
+	 * In graph mode call the graph tracer output function,
+	 * otherwise go with the TRACE_FN event handler
+	 */
+	if (is_graph())
+		return print_graph_function_flags(iter, GRAPH_TRACER_FLAGS);
+
+	return TRACE_TYPE_UNHANDLED;
+}
+
+static void wakeup_print_header(struct seq_file *s)
+{
+	if (is_graph())
+		print_graph_headers_flags(s, GRAPH_TRACER_FLAGS);
+	else
+		trace_default_header(s);
+}
+
+static void
+__trace_function(struct trace_array *tr,
+		 unsigned long ip, unsigned long parent_ip,
+		 unsigned long flags, int pc)
+{
+	if (is_graph())
+		trace_graph_function(tr, ip, parent_ip, flags, pc);
+	else
+		trace_function(tr, ip, parent_ip, flags, pc);
+}
+#else
+#define __trace_function trace_function
+
+static int wakeup_set_flag(u32 old_flags, u32 bit, int set)
+{
+	return -EINVAL;
+}
+
+static int wakeup_graph_entry(struct ftrace_graph_ent *trace)
+{
+	return -1;
+}
+
+static enum print_line_t wakeup_print_line(struct trace_iterator *iter)
+{
+	return TRACE_TYPE_UNHANDLED;
+}
+
+static void wakeup_graph_return(struct ftrace_graph_ret *trace) { }
+static void wakeup_print_header(struct seq_file *s) { }
+static void wakeup_trace_open(struct trace_iterator *iter) { }
+static void wakeup_trace_close(struct trace_iterator *iter) { }
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
 /*
  * Should this new latency be reported/recorded?
  */
@@ -152,7 +352,7 @@
 	/* The task we are waiting for is waking up */
 	data = wakeup_trace->data[wakeup_cpu];
 
-	trace_function(wakeup_trace, CALLER_ADDR0, CALLER_ADDR1, flags, pc);
+	__trace_function(wakeup_trace, CALLER_ADDR0, CALLER_ADDR1, flags, pc);
 	tracing_sched_switch_trace(wakeup_trace, prev, next, flags, pc);
 
 	T0 = data->preempt_timestamp;
@@ -252,7 +452,7 @@
 	 * is not called by an assembly function  (where as schedule is)
 	 * it should be safe to use it here.
 	 */
-	trace_function(wakeup_trace, CALLER_ADDR1, CALLER_ADDR2, flags, pc);
+	__trace_function(wakeup_trace, CALLER_ADDR1, CALLER_ADDR2, flags, pc);
 
 out_locked:
 	arch_spin_unlock(&wakeup_lock);
@@ -303,12 +503,8 @@
 	 */
 	smp_wmb();
 
-	register_ftrace_function(&trace_ops);
-
-	if (tracing_is_enabled())
-		tracer_enabled = 1;
-	else
-		tracer_enabled = 0;
+	if (start_func_tracer(is_graph()))
+		printk(KERN_ERR "failed to start wakeup tracer\n");
 
 	return;
 fail_deprobe_wake_new:
@@ -320,7 +516,7 @@
 static void stop_wakeup_tracer(struct trace_array *tr)
 {
 	tracer_enabled = 0;
-	unregister_ftrace_function(&trace_ops);
+	stop_func_tracer(is_graph());
 	unregister_trace_sched_switch(probe_wakeup_sched_switch, NULL);
 	unregister_trace_sched_wakeup_new(probe_wakeup, NULL);
 	unregister_trace_sched_wakeup(probe_wakeup, NULL);
@@ -379,9 +575,15 @@
 	.start		= wakeup_tracer_start,
 	.stop		= wakeup_tracer_stop,
 	.print_max	= 1,
+	.print_header	= wakeup_print_header,
+	.print_line	= wakeup_print_line,
+	.flags		= &tracer_flags,
+	.set_flag	= wakeup_set_flag,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_wakeup,
 #endif
+	.open		= wakeup_trace_open,
+	.close		= wakeup_trace_close,
 	.use_max_tr	= 1,
 };
 
@@ -394,9 +596,15 @@
 	.stop		= wakeup_tracer_stop,
 	.wait_pipe	= poll_wait_pipe,
 	.print_max	= 1,
+	.print_header	= wakeup_print_header,
+	.print_line	= wakeup_print_line,
+	.flags		= &tracer_flags,
+	.set_flag	= wakeup_set_flag,
 #ifdef CONFIG_FTRACE_SELFTEST
 	.selftest    = trace_selftest_startup_wakeup,
 #endif
+	.open		= wakeup_trace_open,
+	.close		= wakeup_trace_close,
 	.use_max_tr	= 1,
 };
 
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index a6b7e0e..4c5dead 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -195,6 +195,7 @@
 	.open		= tracing_open_generic,
 	.read		= stack_max_size_read,
 	.write		= stack_max_size_write,
+	.llseek		= default_llseek,
 };
 
 static void *
diff --git a/kernel/trace/trace_workqueue.c b/kernel/trace/trace_workqueue.c
index a7cc379..209b379 100644
--- a/kernel/trace/trace_workqueue.c
+++ b/kernel/trace/trace_workqueue.c
@@ -263,6 +263,11 @@
 {
 	int ret, cpu;
 
+	for_each_possible_cpu(cpu) {
+		spin_lock_init(&workqueue_cpu_stat(cpu)->lock);
+		INIT_LIST_HEAD(&workqueue_cpu_stat(cpu)->list);
+	}
+
 	ret = register_trace_workqueue_insertion(probe_workqueue_insertion, NULL);
 	if (ret)
 		goto out;
@@ -279,11 +284,6 @@
 	if (ret)
 		goto no_creation;
 
-	for_each_possible_cpu(cpu) {
-		spin_lock_init(&workqueue_cpu_stat(cpu)->lock);
-		INIT_LIST_HEAD(&workqueue_cpu_stat(cpu)->list);
-	}
-
 	return 0;
 
 no_creation:
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index c77f3ec..e95ee7f 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/jump_label.h>
 
 extern struct tracepoint __start___tracepoints[];
 extern struct tracepoint __stop___tracepoints[];
@@ -263,7 +264,13 @@
 	 * is used.
 	 */
 	rcu_assign_pointer(elem->funcs, (*entry)->funcs);
-	elem->state = active;
+	if (!elem->state && active) {
+		jump_label_enable(&elem->state);
+		elem->state = active;
+	} else if (elem->state && !active) {
+		jump_label_disable(&elem->state);
+		elem->state = active;
+	}
 }
 
 /*
@@ -277,7 +284,10 @@
 	if (elem->unregfunc && elem->state)
 		elem->unregfunc();
 
-	elem->state = 0;
+	if (elem->state) {
+		jump_label_disable(&elem->state);
+		elem->state = 0;
+	}
 	rcu_assign_pointer(elem->funcs, NULL);
 }
 
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 7f9c3c5..bafba68 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -43,7 +43,6 @@
 static DEFINE_PER_CPU(struct perf_event *, watchdog_ev);
 #endif
 
-static int __read_mostly did_panic;
 static int __initdata no_watchdog;
 
 
@@ -187,18 +186,6 @@
 	return 0;
 }
 
-static int
-watchdog_panic(struct notifier_block *this, unsigned long event, void *ptr)
-{
-	did_panic = 1;
-
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block panic_block = {
-	.notifier_call = watchdog_panic,
-};
-
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
 static struct perf_event_attr wd_hw_attr = {
 	.type		= PERF_TYPE_HARDWARE,
@@ -209,7 +196,7 @@
 };
 
 /* Callback function for perf event subsystem */
-void watchdog_overflow_callback(struct perf_event *event, int nmi,
+static void watchdog_overflow_callback(struct perf_event *event, int nmi,
 		 struct perf_sample_data *data,
 		 struct pt_regs *regs)
 {
@@ -371,14 +358,14 @@
 	/* Try to register using hardware perf events */
 	wd_attr = &wd_hw_attr;
 	wd_attr->sample_period = hw_nmi_get_sample_period();
-	event = perf_event_create_kernel_counter(wd_attr, cpu, -1, watchdog_overflow_callback);
+	event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback);
 	if (!IS_ERR(event)) {
 		printk(KERN_INFO "NMI watchdog enabled, takes one hw-pmu counter.\n");
 		goto out_save;
 	}
 
 	printk(KERN_ERR "NMI watchdog failed to create perf event on cpu%i: %p\n", cpu, event);
-	return -1;
+	return PTR_ERR(event);
 
 	/* success path */
 out_save:
@@ -422,17 +409,19 @@
 static int watchdog_enable(int cpu)
 {
 	struct task_struct *p = per_cpu(softlockup_watchdog, cpu);
+	int err;
 
 	/* enable the perf event */
-	if (watchdog_nmi_enable(cpu) != 0)
-		return -1;
+	err = watchdog_nmi_enable(cpu);
+	if (err)
+		return err;
 
 	/* 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 -1;
+			return PTR_ERR(p);
 		}
 		kthread_bind(p, cpu);
 		per_cpu(watchdog_touch_ts, cpu) = 0;
@@ -484,6 +473,9 @@
 {
 	int cpu;
 
+	if (no_watchdog)
+		return;
+
 	for_each_online_cpu(cpu)
 		watchdog_disable(cpu);
 
@@ -526,17 +518,16 @@
 cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
 	int hotcpu = (unsigned long)hcpu;
+	int err = 0;
 
 	switch (action) {
 	case CPU_UP_PREPARE:
 	case CPU_UP_PREPARE_FROZEN:
-		if (watchdog_prepare_cpu(hotcpu))
-			return NOTIFY_BAD;
+		err = watchdog_prepare_cpu(hotcpu);
 		break;
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
-		if (watchdog_enable(hotcpu))
-			return NOTIFY_BAD;
+		err = watchdog_enable(hotcpu);
 		break;
 #ifdef CONFIG_HOTPLUG_CPU
 	case CPU_UP_CANCELED:
@@ -549,7 +540,7 @@
 		break;
 #endif /* CONFIG_HOTPLUG_CPU */
 	}
-	return NOTIFY_OK;
+	return notifier_from_errno(err);
 }
 
 static struct notifier_block __cpuinitdata cpu_nfb = {
@@ -565,13 +556,11 @@
 		return 0;
 
 	err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
-	WARN_ON(err == NOTIFY_BAD);
+	WARN_ON(notifier_to_errno(err));
 
 	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
 	register_cpu_notifier(&cpu_nfb);
 
-	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
-
 	return 0;
 }
 early_initcall(spawn_watchdog_task);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index f77afd9..30acdb7 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -42,9 +42,6 @@
 #include <linux/lockdep.h>
 #include <linux/idr.h>
 
-#define CREATE_TRACE_POINTS
-#include <trace/events/workqueue.h>
-
 #include "workqueue_sched.h"
 
 enum {
@@ -257,6 +254,9 @@
 EXPORT_SYMBOL_GPL(system_nrt_wq);
 EXPORT_SYMBOL_GPL(system_unbound_wq);
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/workqueue.h>
+
 #define for_each_busy_worker(worker, i, pos, gcwq)			\
 	for (i = 0; i < BUSY_WORKER_HASH_SIZE; i++)			\
 		hlist_for_each_entry(worker, pos, &gcwq->busy_hash[i], hentry)
@@ -310,21 +310,6 @@
 	     (cpu) < WORK_CPU_NONE;					\
 	     (cpu) = __next_wq_cpu((cpu), cpu_possible_mask, (wq)))
 
-#ifdef CONFIG_LOCKDEP
-/**
- * in_workqueue_context() - in context of specified workqueue?
- * @wq: the workqueue of interest
- *
- * Checks lockdep state to see if the current task is executing from
- * within a workqueue item.  This function exists only if lockdep is
- * enabled.
- */
-int in_workqueue_context(struct workqueue_struct *wq)
-{
-	return lock_is_held(&wq->lockdep_map);
-}
-#endif
-
 #ifdef CONFIG_DEBUG_OBJECTS_WORK
 
 static struct debug_obj_descr work_debug_descr;
@@ -604,7 +589,9 @@
 {
 	atomic_t *nr_running = get_gcwq_nr_running(gcwq->cpu);
 
-	return !list_empty(&gcwq->worklist) && atomic_read(nr_running) <= 1;
+	return !list_empty(&gcwq->worklist) &&
+		(atomic_read(nr_running) <= 1 ||
+		 gcwq->flags & GCWQ_HIGHPRI_PENDING);
 }
 
 /* Do we need a new worker?  Called from manager. */
@@ -997,6 +984,7 @@
 
 	/* gcwq determined, get cwq and queue */
 	cwq = get_cwq(gcwq->cpu, wq);
+	trace_workqueue_queue_work(cpu, cwq, work);
 
 	BUG_ON(!list_empty(&work->entry));
 
@@ -1004,6 +992,7 @@
 	work_flags = work_color_to_flags(cwq->work_color);
 
 	if (likely(cwq->nr_active < cwq->max_active)) {
+		trace_workqueue_activate_work(work);
 		cwq->nr_active++;
 		worklist = gcwq_determine_ins_pos(gcwq, cwq);
 	} else {
@@ -1679,6 +1668,7 @@
 						    struct work_struct, entry);
 	struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq);
 
+	trace_workqueue_activate_work(work);
 	move_linked_works(work, pos, NULL);
 	__clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work));
 	cwq->nr_active++;
@@ -2326,27 +2316,17 @@
 }
 EXPORT_SYMBOL_GPL(flush_workqueue);
 
-/**
- * flush_work - block until a work_struct's callback has terminated
- * @work: the work which is to be flushed
- *
- * Returns false if @work has already terminated.
- *
- * It is expected that, prior to calling flush_work(), the caller has
- * arranged for the work to not be requeued, otherwise it doesn't make
- * sense to use this function.
- */
-int flush_work(struct work_struct *work)
+static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr,
+			     bool wait_executing)
 {
 	struct worker *worker = NULL;
 	struct global_cwq *gcwq;
 	struct cpu_workqueue_struct *cwq;
-	struct wq_barrier barr;
 
 	might_sleep();
 	gcwq = get_work_gcwq(work);
 	if (!gcwq)
-		return 0;
+		return false;
 
 	spin_lock_irq(&gcwq->lock);
 	if (!list_empty(&work->entry)) {
@@ -2359,28 +2339,127 @@
 		cwq = get_work_cwq(work);
 		if (unlikely(!cwq || gcwq != cwq->gcwq))
 			goto already_gone;
-	} else {
+	} else if (wait_executing) {
 		worker = find_worker_executing_work(gcwq, work);
 		if (!worker)
 			goto already_gone;
 		cwq = worker->current_cwq;
-	}
+	} else
+		goto already_gone;
 
-	insert_wq_barrier(cwq, &barr, work, worker);
+	insert_wq_barrier(cwq, barr, work, worker);
 	spin_unlock_irq(&gcwq->lock);
 
 	lock_map_acquire(&cwq->wq->lockdep_map);
 	lock_map_release(&cwq->wq->lockdep_map);
-
-	wait_for_completion(&barr.done);
-	destroy_work_on_stack(&barr.work);
-	return 1;
+	return true;
 already_gone:
 	spin_unlock_irq(&gcwq->lock);
-	return 0;
+	return false;
+}
+
+/**
+ * flush_work - wait for a work to finish executing the last queueing instance
+ * @work: the work to flush
+ *
+ * Wait until @work has finished execution.  This function considers
+ * only the last queueing instance of @work.  If @work has been
+ * enqueued across different CPUs on a non-reentrant workqueue or on
+ * multiple workqueues, @work might still be executing on return on
+ * some of the CPUs from earlier queueing.
+ *
+ * If @work was queued only on a non-reentrant, ordered or unbound
+ * workqueue, @work is guaranteed to be idle on return if it hasn't
+ * been requeued since flush started.
+ *
+ * RETURNS:
+ * %true if flush_work() waited for the work to finish execution,
+ * %false if it was already idle.
+ */
+bool flush_work(struct work_struct *work)
+{
+	struct wq_barrier barr;
+
+	if (start_flush_work(work, &barr, true)) {
+		wait_for_completion(&barr.done);
+		destroy_work_on_stack(&barr.work);
+		return true;
+	} else
+		return false;
 }
 EXPORT_SYMBOL_GPL(flush_work);
 
+static bool wait_on_cpu_work(struct global_cwq *gcwq, struct work_struct *work)
+{
+	struct wq_barrier barr;
+	struct worker *worker;
+
+	spin_lock_irq(&gcwq->lock);
+
+	worker = find_worker_executing_work(gcwq, work);
+	if (unlikely(worker))
+		insert_wq_barrier(worker->current_cwq, &barr, work, worker);
+
+	spin_unlock_irq(&gcwq->lock);
+
+	if (unlikely(worker)) {
+		wait_for_completion(&barr.done);
+		destroy_work_on_stack(&barr.work);
+		return true;
+	} else
+		return false;
+}
+
+static bool wait_on_work(struct work_struct *work)
+{
+	bool ret = false;
+	int cpu;
+
+	might_sleep();
+
+	lock_map_acquire(&work->lockdep_map);
+	lock_map_release(&work->lockdep_map);
+
+	for_each_gcwq_cpu(cpu)
+		ret |= wait_on_cpu_work(get_gcwq(cpu), work);
+	return ret;
+}
+
+/**
+ * flush_work_sync - wait until a work has finished execution
+ * @work: the work to flush
+ *
+ * Wait until @work has finished execution.  On return, it's
+ * guaranteed that all queueing instances of @work which happened
+ * before this function is called are finished.  In other words, if
+ * @work hasn't been requeued since this function was called, @work is
+ * guaranteed to be idle on return.
+ *
+ * RETURNS:
+ * %true if flush_work_sync() waited for the work to finish execution,
+ * %false if it was already idle.
+ */
+bool flush_work_sync(struct work_struct *work)
+{
+	struct wq_barrier barr;
+	bool pending, waited;
+
+	/* we'll wait for executions separately, queue barr only if pending */
+	pending = start_flush_work(work, &barr, false);
+
+	/* wait for executions to finish */
+	waited = wait_on_work(work);
+
+	/* wait for the pending one */
+	if (pending) {
+		wait_for_completion(&barr.done);
+		destroy_work_on_stack(&barr.work);
+	}
+
+	return pending || waited;
+}
+EXPORT_SYMBOL_GPL(flush_work_sync);
+
 /*
  * Upon a successful return (>= 0), the caller "owns" WORK_STRUCT_PENDING bit,
  * so this work can't be re-armed in any way.
@@ -2423,39 +2502,7 @@
 	return ret;
 }
 
-static void wait_on_cpu_work(struct global_cwq *gcwq, struct work_struct *work)
-{
-	struct wq_barrier barr;
-	struct worker *worker;
-
-	spin_lock_irq(&gcwq->lock);
-
-	worker = find_worker_executing_work(gcwq, work);
-	if (unlikely(worker))
-		insert_wq_barrier(worker->current_cwq, &barr, work, worker);
-
-	spin_unlock_irq(&gcwq->lock);
-
-	if (unlikely(worker)) {
-		wait_for_completion(&barr.done);
-		destroy_work_on_stack(&barr.work);
-	}
-}
-
-static void wait_on_work(struct work_struct *work)
-{
-	int cpu;
-
-	might_sleep();
-
-	lock_map_acquire(&work->lockdep_map);
-	lock_map_release(&work->lockdep_map);
-
-	for_each_gcwq_cpu(cpu)
-		wait_on_cpu_work(get_gcwq(cpu), work);
-}
-
-static int __cancel_work_timer(struct work_struct *work,
+static bool __cancel_work_timer(struct work_struct *work,
 				struct timer_list* timer)
 {
 	int ret;
@@ -2472,42 +2519,81 @@
 }
 
 /**
- * cancel_work_sync - block until a work_struct's callback has terminated
- * @work: the work which is to be flushed
+ * cancel_work_sync - cancel a work and wait for it to finish
+ * @work: the work to cancel
  *
- * Returns true if @work was pending.
+ * Cancel @work and wait for its execution to finish.  This function
+ * can be used even if the work re-queues itself or migrates to
+ * another workqueue.  On return from this function, @work is
+ * guaranteed to be not pending or executing on any CPU.
  *
- * cancel_work_sync() will cancel the work if it is queued. If the work's
- * callback appears to be running, cancel_work_sync() will block until it
- * has completed.
+ * cancel_work_sync(&delayed_work->work) must not be used for
+ * delayed_work's.  Use cancel_delayed_work_sync() instead.
  *
- * It is possible to use this function if the work re-queues itself. It can
- * cancel the work even if it migrates to another workqueue, however in that
- * case it only guarantees that work->func() has completed on the last queued
- * workqueue.
- *
- * cancel_work_sync(&delayed_work->work) should be used only if ->timer is not
- * pending, otherwise it goes into a busy-wait loop until the timer expires.
- *
- * The caller must ensure that workqueue_struct on which this work was last
+ * The caller must ensure that the workqueue on which @work was last
  * queued can't be destroyed before this function returns.
+ *
+ * RETURNS:
+ * %true if @work was pending, %false otherwise.
  */
-int cancel_work_sync(struct work_struct *work)
+bool cancel_work_sync(struct work_struct *work)
 {
 	return __cancel_work_timer(work, NULL);
 }
 EXPORT_SYMBOL_GPL(cancel_work_sync);
 
 /**
- * cancel_delayed_work_sync - reliably kill off a delayed work.
- * @dwork: the delayed work struct
+ * flush_delayed_work - wait for a dwork to finish executing the last queueing
+ * @dwork: the delayed work to flush
  *
- * Returns true if @dwork was pending.
+ * Delayed timer is cancelled and the pending work is queued for
+ * immediate execution.  Like flush_work(), this function only
+ * considers the last queueing instance of @dwork.
  *
- * It is possible to use this function if @dwork rearms itself via queue_work()
- * or queue_delayed_work(). See also the comment for cancel_work_sync().
+ * RETURNS:
+ * %true if flush_work() waited for the work to finish execution,
+ * %false if it was already idle.
  */
-int cancel_delayed_work_sync(struct delayed_work *dwork)
+bool flush_delayed_work(struct delayed_work *dwork)
+{
+	if (del_timer_sync(&dwork->timer))
+		__queue_work(raw_smp_processor_id(),
+			     get_work_cwq(&dwork->work)->wq, &dwork->work);
+	return flush_work(&dwork->work);
+}
+EXPORT_SYMBOL(flush_delayed_work);
+
+/**
+ * flush_delayed_work_sync - wait for a dwork to finish
+ * @dwork: the delayed work to flush
+ *
+ * Delayed timer is cancelled and the pending work is queued for
+ * execution immediately.  Other than timer handling, its behavior
+ * is identical to flush_work_sync().
+ *
+ * RETURNS:
+ * %true if flush_work_sync() waited for the work to finish execution,
+ * %false if it was already idle.
+ */
+bool flush_delayed_work_sync(struct delayed_work *dwork)
+{
+	if (del_timer_sync(&dwork->timer))
+		__queue_work(raw_smp_processor_id(),
+			     get_work_cwq(&dwork->work)->wq, &dwork->work);
+	return flush_work_sync(&dwork->work);
+}
+EXPORT_SYMBOL(flush_delayed_work_sync);
+
+/**
+ * cancel_delayed_work_sync - cancel a delayed work and wait for it to finish
+ * @dwork: the delayed work cancel
+ *
+ * This is cancel_work_sync() for delayed works.
+ *
+ * RETURNS:
+ * %true if @dwork was pending, %false otherwise.
+ */
+bool cancel_delayed_work_sync(struct delayed_work *dwork)
 {
 	return __cancel_work_timer(&dwork->work, &dwork->timer);
 }
@@ -2559,23 +2645,6 @@
 EXPORT_SYMBOL(schedule_delayed_work);
 
 /**
- * flush_delayed_work - block until a dwork_struct's callback has terminated
- * @dwork: the delayed work which is to be flushed
- *
- * Any timeout is cancelled, and any pending work is run immediately.
- */
-void flush_delayed_work(struct delayed_work *dwork)
-{
-	if (del_timer_sync(&dwork->timer)) {
-		__queue_work(get_cpu(), get_work_cwq(&dwork->work)->wq,
-			     &dwork->work);
-		put_cpu();
-	}
-	flush_work(&dwork->work);
-}
-EXPORT_SYMBOL(flush_delayed_work);
-
-/**
  * schedule_delayed_work_on - queue work in global workqueue on CPU after delay
  * @cpu: cpu to use
  * @dwork: job to be done
@@ -2592,13 +2661,15 @@
 EXPORT_SYMBOL(schedule_delayed_work_on);
 
 /**
- * schedule_on_each_cpu - call a function on each online CPU from keventd
+ * schedule_on_each_cpu - execute a function synchronously on each online CPU
  * @func: the function to call
  *
- * Returns zero on success.
- * Returns -ve errno on failure.
- *
+ * schedule_on_each_cpu() executes @func on each online CPU using the
+ * system workqueue and blocks until all CPUs have completed.
  * schedule_on_each_cpu() is very slow.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
  */
 int schedule_on_each_cpu(work_func_t func)
 {
@@ -2764,6 +2835,13 @@
 	unsigned int cpu;
 
 	/*
+	 * Workqueues which may be used during memory reclaim should
+	 * have a rescuer to guarantee forward progress.
+	 */
+	if (flags & WQ_MEM_RECLAIM)
+		flags |= WQ_RESCUER;
+
+	/*
 	 * Unbound workqueues aren't concurrency managed and should be
 	 * dispatched to workers immediately.
 	 */
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1b4afd2..7b2a8ca9 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -461,6 +461,15 @@
 	 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
@@ -482,6 +491,7 @@
 	select DEBUG_SPINLOCK
 	select DEBUG_MUTEXES
 	select DEBUG_LOCK_ALLOC
+	select TRACE_IRQFLAGS
 	default n
 	help
 	 This feature enables the kernel to prove that all locking
@@ -539,6 +549,23 @@
 	 disabling, allowing multiple RCU-lockdep warnings to be printed
 	 on a single reboot.
 
+	 Say Y to allow multiple RCU-lockdep warnings per boot.
+
+	 Say N if you are unsure.
+
+config SPARSE_RCU_POINTER
+	bool "RCU debugging: sparse-based checks for pointer usage"
+	default n
+	help
+	 This feature enables the __rcu sparse annotation for
+	 RCU-protected pointers.  This annotation will cause sparse
+	 to flag any non-RCU used of annotated pointers.  This can be
+	 helpful when debugging RCU usage.  Please note that this feature
+	 is not intended to enforce code cleanliness; it is instead merely
+	 a debugging aid.
+
+	 Say Y to make sparse flag questionable use of RCU-protected pointers
+
 	 Say N if you are unsure.
 
 config LOCKDEP
@@ -579,11 +606,10 @@
 	  of more runtime overhead.
 
 config TRACE_IRQFLAGS
-	depends on DEBUG_KERNEL
 	bool
-	default y
-	depends on TRACE_IRQFLAGS_SUPPORT
-	depends on PROVE_LOCKING
+	help
+	  Enables hooks to interrupt enabling and disabling for
+	  either tracing or lock debugging.
 
 config DEBUG_SPINLOCK_SLEEP
 	bool "Spinlock debugging: sleep-inside-spinlock checking"
@@ -832,6 +858,30 @@
 
 	  Say Y if you are unsure.
 
+config RCU_CPU_STALL_TIMEOUT
+	int "RCU CPU stall timeout in seconds"
+	depends on RCU_CPU_STALL_DETECTOR
+	range 3 300
+	default 60
+	help
+	  If a given RCU grace period extends more than the specified
+	  number of seconds, a CPU stall warning is printed.  If the
+	  RCU grace period persists, additional CPU stall warnings are
+	  printed at more widely spaced intervals.
+
+config RCU_CPU_STALL_DETECTOR_RUNNABLE
+	bool "RCU CPU stall checking starts automatically at boot"
+	depends on RCU_CPU_STALL_DETECTOR
+	default y
+	help
+	  If set, start checking for RCU CPU stalls immediately on
+	  boot.  Otherwise, RCU CPU stall checking must be manually
+	  enabled.
+
+	  Say Y if you are unsure.
+
+	  Say N if you wish to suppress RCU CPU stall checking during boot.
+
 config RCU_CPU_STALL_VERBOSE
 	bool "Print additional per-task information for RCU_CPU_STALL_DETECTOR"
 	depends on RCU_CPU_STALL_DETECTOR && TREE_PREEMPT_RCU
diff --git a/lib/bug.c b/lib/bug.c
index 7cdfad8..1955209 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -72,8 +72,8 @@
 	return NULL;
 }
 
-int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
-			struct module *mod)
+void module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+			 struct module *mod)
 {
 	char *secstrings;
 	unsigned int i;
@@ -97,8 +97,6 @@
 	 * could potentially lead to deadlock and thus be counter-productive.
 	 */
 	list_add(&mod->bug_list, &module_bug_list);
-
-	return 0;
 }
 
 void module_bug_cleanup(struct module *mod)
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 01e6427..4bfb047 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -590,6 +590,7 @@
 static const struct file_operations filter_fops = {
 	.read  = filter_read,
 	.write = filter_write,
+	.llseek = default_llseek,
 };
 
 static int dma_debug_fs_init(void)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 02afc25..3094318 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -26,19 +26,11 @@
 #include <linux/dynamic_debug.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/jump_label.h>
 
 extern struct _ddebug __start___verbose[];
 extern struct _ddebug __stop___verbose[];
 
-/* dynamic_debug_enabled, and dynamic_debug_enabled2 are bitmasks in which
- * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
- * use independent hash functions, to reduce the chance of false positives.
- */
-long long dynamic_debug_enabled;
-EXPORT_SYMBOL_GPL(dynamic_debug_enabled);
-long long dynamic_debug_enabled2;
-EXPORT_SYMBOL_GPL(dynamic_debug_enabled2);
-
 struct ddebug_table {
 	struct list_head link;
 	char *mod_name;
@@ -88,26 +80,6 @@
 }
 
 /*
- * must be called with ddebug_lock held
- */
-
-static int disabled_hash(char hash, bool first_table)
-{
-	struct ddebug_table *dt;
-	char table_hash_value;
-
-	list_for_each_entry(dt, &ddebug_tables, link) {
-		if (first_table)
-			table_hash_value = dt->ddebugs->primary_hash;
-		else
-			table_hash_value = dt->ddebugs->secondary_hash;
-		if (dt->num_enabled && (hash == table_hash_value))
-			return 0;
-	}
-	return 1;
-}
-
-/*
  * Search the tables for _ddebug's which match the given
  * `query' and apply the `flags' and `mask' to them.  Tells
  * the user which ddebug's were changed, or whether none
@@ -170,17 +142,9 @@
 				dt->num_enabled++;
 			dp->flags = newflags;
 			if (newflags) {
-				dynamic_debug_enabled |=
-						(1LL << dp->primary_hash);
-				dynamic_debug_enabled2 |=
-						(1LL << dp->secondary_hash);
+				jump_label_enable(&dp->enabled);
 			} else {
-				if (disabled_hash(dp->primary_hash, true))
-					dynamic_debug_enabled &=
-						~(1LL << dp->primary_hash);
-				if (disabled_hash(dp->secondary_hash, false))
-					dynamic_debug_enabled2 &=
-						~(1LL << dp->secondary_hash);
+				jump_label_disable(&dp->enabled);
 			}
 			if (verbose)
 				printk(KERN_INFO
@@ -429,6 +393,40 @@
 	return 0;
 }
 
+static int ddebug_exec_query(char *query_string)
+{
+	unsigned int flags = 0, mask = 0;
+	struct ddebug_query query;
+#define MAXWORDS 9
+	int nwords;
+	char *words[MAXWORDS];
+
+	nwords = ddebug_tokenize(query_string, words, MAXWORDS);
+	if (nwords <= 0)
+		return -EINVAL;
+	if (ddebug_parse_query(words, nwords-1, &query))
+		return -EINVAL;
+	if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
+		return -EINVAL;
+
+	/* actually go and implement the change */
+	ddebug_change(&query, flags, mask);
+	return 0;
+}
+
+static __initdata char ddebug_setup_string[1024];
+static __init int ddebug_setup_query(char *str)
+{
+	if (strlen(str) >= 1024) {
+		pr_warning("ddebug boot param string too large\n");
+		return 0;
+	}
+	strcpy(ddebug_setup_string, str);
+	return 1;
+}
+
+__setup("ddebug_query=", ddebug_setup_query);
+
 /*
  * File_ops->write method for <debugfs>/dynamic_debug/conrol.  Gathers the
  * command text from userspace, parses and executes it.
@@ -436,12 +434,8 @@
 static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
 				  size_t len, loff_t *offp)
 {
-	unsigned int flags = 0, mask = 0;
-	struct ddebug_query query;
-#define MAXWORDS 9
-	int nwords;
-	char *words[MAXWORDS];
 	char tmpbuf[256];
+	int ret;
 
 	if (len == 0)
 		return 0;
@@ -455,16 +449,9 @@
 		printk(KERN_INFO "%s: read %d bytes from userspace\n",
 			__func__, (int)len);
 
-	nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS);
-	if (nwords <= 0)
-		return -EINVAL;
-	if (ddebug_parse_query(words, nwords-1, &query))
-		return -EINVAL;
-	if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
-		return -EINVAL;
-
-	/* actually go and implement the change */
-	ddebug_change(&query, flags, mask);
+	ret = ddebug_exec_query(tmpbuf);
+	if (ret)
+		return ret;
 
 	*offp += len;
 	return len;
@@ -725,13 +712,14 @@
 	mutex_unlock(&ddebug_lock);
 }
 
-static int __init dynamic_debug_init(void)
+static __initdata int ddebug_init_success;
+
+static int __init dynamic_debug_init_debugfs(void)
 {
 	struct dentry *dir, *file;
-	struct _ddebug *iter, *iter_start;
-	const char *modname = NULL;
-	int ret = 0;
-	int n = 0;
+
+	if (!ddebug_init_success)
+		return -ENODEV;
 
 	dir = debugfs_create_dir("dynamic_debug", NULL);
 	if (!dir)
@@ -742,6 +730,16 @@
 		debugfs_remove(dir);
 		return -ENOMEM;
 	}
+	return 0;
+}
+
+static int __init dynamic_debug_init(void)
+{
+	struct _ddebug *iter, *iter_start;
+	const char *modname = NULL;
+	int ret = 0;
+	int n = 0;
+
 	if (__start___verbose != __stop___verbose) {
 		iter = __start___verbose;
 		modname = iter->modname;
@@ -759,12 +757,26 @@
 		}
 		ret = ddebug_add_module(iter_start, n, modname);
 	}
-out_free:
-	if (ret) {
-		ddebug_remove_all_tables();
-		debugfs_remove(dir);
-		debugfs_remove(file);
+
+	/* ddebug_query boot param got passed -> set it up */
+	if (ddebug_setup_string[0] != '\0') {
+		ret = ddebug_exec_query(ddebug_setup_string);
+		if (ret)
+			pr_warning("Invalid ddebug boot param %s",
+				   ddebug_setup_string);
+		else
+			pr_info("ddebug initialized with string %s",
+				ddebug_setup_string);
 	}
+
+out_free:
+	if (ret)
+		ddebug_remove_all_tables();
+	else
+		ddebug_init_success = 1;
 	return 0;
 }
-module_init(dynamic_debug_init);
+/* Allow early initialization for boot messages via boot param */
+arch_initcall(dynamic_debug_init);
+/* Debugfs setup must be done later */
+module_init(dynamic_debug_init_debugfs);
diff --git a/lib/kobject.c b/lib/kobject.c
index f07c572..82dc34c 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -746,17 +746,56 @@
  */
 struct kobject *kset_find_obj(struct kset *kset, const char *name)
 {
+	return kset_find_obj_hinted(kset, name, NULL);
+}
+
+/**
+ * kset_find_obj_hinted - search for object in kset given a predecessor hint.
+ * @kset: kset we're looking in.
+ * @name: object's name.
+ * @hint: hint to possible object's predecessor.
+ *
+ * Check the hint's next object and if it is a match return it directly,
+ * otherwise, fall back to the behavior of kset_find_obj().  Either way
+ * a reference for the returned object is held and the reference on the
+ * hinted object is released.
+ */
+struct kobject *kset_find_obj_hinted(struct kset *kset, const char *name,
+				     struct kobject *hint)
+{
 	struct kobject *k;
 	struct kobject *ret = NULL;
 
 	spin_lock(&kset->list_lock);
+
+	if (!hint)
+		goto slow_search;
+
+	/* end of list detection */
+	if (hint->entry.next == kset->list.next)
+		goto slow_search;
+
+	k = container_of(hint->entry.next, struct kobject, entry);
+	if (!kobject_name(k) || strcmp(kobject_name(k), name))
+		goto slow_search;
+
+	ret = kobject_get(k);
+	goto unlock_exit;
+
+slow_search:
 	list_for_each_entry(k, &kset->list, entry) {
 		if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
 			ret = kobject_get(k);
 			break;
 		}
 	}
+
+unlock_exit:
 	spin_unlock(&kset->list_lock);
+
+	if (hint)
+		kobject_put(hint);
+
 	return ret;
 }
 
diff --git a/lib/list_sort.c b/lib/list_sort.c
index 4b5cb79..a7616fa 100644
--- a/lib/list_sort.c
+++ b/lib/list_sort.c
@@ -70,7 +70,7 @@
 		 * element comparison is needed, so the client's cmp()
 		 * routine can invoke cond_resched() periodically.
 		 */
-		(*cmp)(priv, tail, tail);
+		(*cmp)(priv, tail->next, tail->next);
 
 		tail->next->prev = tail;
 		tail = tail->next;
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index efd16fa..6f412ab4 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -49,7 +49,7 @@
 	unsigned int	height;		/* Height from the bottom */
 	unsigned int	count;
 	struct rcu_head	rcu_head;
-	void		*slots[RADIX_TREE_MAP_SIZE];
+	void __rcu	*slots[RADIX_TREE_MAP_SIZE];
 	unsigned long	tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
 };
 
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 34e3082..7c06ee5 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -70,7 +70,7 @@
  */
 static unsigned long io_tlb_overflow = 32*1024;
 
-void *io_tlb_overflow_buffer;
+static void *io_tlb_overflow_buffer;
 
 /*
  * This is a free list describing the number of free entries available from
@@ -147,16 +147,16 @@
 	 * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE
 	 * between io_tlb_start and io_tlb_end.
 	 */
-	io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int));
+	io_tlb_list = alloc_bootmem_pages(PAGE_ALIGN(io_tlb_nslabs * sizeof(int)));
 	for (i = 0; i < io_tlb_nslabs; i++)
  		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
 	io_tlb_index = 0;
-	io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(phys_addr_t));
+	io_tlb_orig_addr = alloc_bootmem_pages(PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)));
 
 	/*
 	 * Get the overflow emergency buffer
 	 */
-	io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
+	io_tlb_overflow_buffer = alloc_bootmem_low_pages(PAGE_ALIGN(io_tlb_overflow));
 	if (!io_tlb_overflow_buffer)
 		panic("Cannot allocate SWIOTLB overflow buffer!\n");
 	if (verbose)
@@ -182,7 +182,7 @@
 	/*
 	 * Get IO TLB memory from the low pages
 	 */
-	io_tlb_start = alloc_bootmem_low_pages(bytes);
+	io_tlb_start = alloc_bootmem_low_pages(PAGE_ALIGN(bytes));
 	if (!io_tlb_start)
 		panic("Cannot allocate SWIOTLB buffer");
 
@@ -308,13 +308,13 @@
 			   get_order(io_tlb_nslabs << IO_TLB_SHIFT));
 	} else {
 		free_bootmem_late(__pa(io_tlb_overflow_buffer),
-				  io_tlb_overflow);
+				  PAGE_ALIGN(io_tlb_overflow));
 		free_bootmem_late(__pa(io_tlb_orig_addr),
-				  io_tlb_nslabs * sizeof(phys_addr_t));
+				  PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)));
 		free_bootmem_late(__pa(io_tlb_list),
-				  io_tlb_nslabs * sizeof(int));
+				  PAGE_ALIGN(io_tlb_nslabs * sizeof(int)));
 		free_bootmem_late(__pa(io_tlb_start),
-				  io_tlb_nslabs << IO_TLB_SHIFT);
+				  PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
 	}
 }
 
diff --git a/mm/Kconfig b/mm/Kconfig
index f0fb912..c2c8a4a 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -301,3 +301,11 @@
 	  of 1 says that all excess pages should be trimmed.
 
 	  See Documentation/nommu-mmap.txt for more information.
+
+#
+# UP and nommu archs use km based percpu allocator
+#
+config NEED_PER_CPU_KM
+	depends on !SMP
+	bool
+	default y
diff --git a/mm/Makefile b/mm/Makefile
index 34b2546..f73f75a 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -11,7 +11,7 @@
 			   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 \
-			   page_isolation.o mm_init.o mmu_context.o \
+			   page_isolation.o mm_init.o mmu_context.o percpu.o \
 			   $(mmu-y)
 obj-y += init-mm.o
 
@@ -36,11 +36,6 @@
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
 obj-$(CONFIG_FS_XIP) += filemap_xip.o
 obj-$(CONFIG_MIGRATION) += migrate.o
-ifdef CONFIG_SMP
-obj-y += percpu.o
-else
-obj-y += percpu_up.o
-endif
 obj-$(CONFIG_QUICKLIST) += quicklist.o
 obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o
 obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 142c84a..13b0caa 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/kmemleak.h>
 #include <linux/range.h>
+#include <linux/memblock.h>
 
 #include <asm/bug.h>
 #include <asm/io.h>
@@ -434,7 +435,8 @@
 			      unsigned long size)
 {
 #ifdef CONFIG_NO_BOOTMEM
-	free_early(physaddr, physaddr + size);
+	kmemleak_free_part(__va(physaddr), size);
+	memblock_x86_free_range(physaddr, physaddr + size);
 #else
 	unsigned long start, end;
 
@@ -459,7 +461,8 @@
 void __init free_bootmem(unsigned long addr, unsigned long size)
 {
 #ifdef CONFIG_NO_BOOTMEM
-	free_early(addr, addr + size);
+	kmemleak_free_part(__va(addr), size);
+	memblock_x86_free_range(addr, addr + size);
 #else
 	unsigned long start, end;
 
@@ -526,6 +529,12 @@
 }
 
 #ifndef CONFIG_NO_BOOTMEM
+int __weak __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
+				   int flags)
+{
+	return reserve_bootmem(phys, len, flags);
+}
+
 static unsigned long __init align_idx(struct bootmem_data *bdata,
 				      unsigned long idx, unsigned long step)
 {
diff --git a/mm/fremap.c b/mm/fremap.c
index 46f5dac..ec520c7 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -125,7 +125,6 @@
 {
 	struct mm_struct *mm = current->mm;
 	struct address_space *mapping;
-	unsigned long end = start + size;
 	struct vm_area_struct *vma;
 	int err = -EINVAL;
 	int has_write_lock = 0;
@@ -142,6 +141,10 @@
 	if (start + size <= start)
 		return err;
 
+	/* Does pgoff wrap? */
+	if (pgoff + (size >> PAGE_SHIFT) < pgoff)
+		return err;
+
 	/* Can we represent this offset inside this architecture's pte's? */
 #if PTE_FILE_MAX_BITS < BITS_PER_LONG
 	if (pgoff + (size >> PAGE_SHIFT) >= (1UL << PTE_FILE_MAX_BITS))
@@ -168,7 +171,7 @@
 	if (!(vma->vm_flags & VM_CAN_NONLINEAR))
 		goto out;
 
-	if (end <= start || start < vma->vm_start || end > vma->vm_end)
+	if (start < vma->vm_start || start + size > vma->vm_end)
 		goto out;
 
 	/* Must set VM_NONLINEAR before any pages are populated. */
diff --git a/mm/ksm.c b/mm/ksm.c
index b1873cf..65ab5c7 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -712,7 +712,7 @@
 	if (!ptep)
 		goto out;
 
-	if (pte_write(*ptep)) {
+	if (pte_write(*ptep) || pte_dirty(*ptep)) {
 		pte_t entry;
 
 		swapped = PageSwapCache(page);
@@ -735,7 +735,9 @@
 			set_pte_at(mm, addr, ptep, entry);
 			goto out_unlock;
 		}
-		entry = pte_wrprotect(entry);
+		if (pte_dirty(entry))
+			set_page_dirty(page);
+		entry = pte_mkclean(pte_wrprotect(entry));
 		set_pte_at_notify(mm, addr, ptep, entry);
 	}
 	*orig_pte = *ptep;
diff --git a/mm/memblock.c b/mm/memblock.c
index 43840b3..400dc62 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -11,60 +11,55 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
+#include <linux/poison.h>
+#include <linux/pfn.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/memblock.h>
 
-#define MEMBLOCK_ALLOC_ANYWHERE	0
+struct memblock memblock __initdata_memblock;
 
-struct memblock memblock;
+int memblock_debug __initdata_memblock;
+int memblock_can_resize __initdata_memblock;
+static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS + 1] __initdata_memblock;
+static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS + 1] __initdata_memblock;
 
-static int memblock_debug;
-
-static int __init early_memblock(char *p)
+/* inline so we don't get a warning when pr_debug is compiled out */
+static inline const char *memblock_type_name(struct memblock_type *type)
 {
-	if (p && strstr(p, "debug"))
-		memblock_debug = 1;
-	return 0;
-}
-early_param("memblock", early_memblock);
-
-static void memblock_dump(struct memblock_region *region, char *name)
-{
-	unsigned long long base, size;
-	int i;
-
-	pr_info(" %s.cnt  = 0x%lx\n", name, region->cnt);
-
-	for (i = 0; i < region->cnt; i++) {
-		base = region->region[i].base;
-		size = region->region[i].size;
-
-		pr_info(" %s[0x%x]\t0x%016llx - 0x%016llx, 0x%llx bytes\n",
-		    name, i, base, base + size - 1, size);
-	}
+	if (type == &memblock.memory)
+		return "memory";
+	else if (type == &memblock.reserved)
+		return "reserved";
+	else
+		return "unknown";
 }
 
-void memblock_dump_all(void)
+/*
+ * Address comparison utilities
+ */
+
+static phys_addr_t __init_memblock memblock_align_down(phys_addr_t addr, phys_addr_t size)
 {
-	if (!memblock_debug)
-		return;
-
-	pr_info("MEMBLOCK configuration:\n");
-	pr_info(" rmo_size    = 0x%llx\n", (unsigned long long)memblock.rmo_size);
-	pr_info(" memory.size = 0x%llx\n", (unsigned long long)memblock.memory.size);
-
-	memblock_dump(&memblock.memory, "memory");
-	memblock_dump(&memblock.reserved, "reserved");
+	return addr & ~(size - 1);
 }
 
-static unsigned long memblock_addrs_overlap(u64 base1, u64 size1, u64 base2,
-					u64 size2)
+static phys_addr_t __init_memblock memblock_align_up(phys_addr_t addr, phys_addr_t size)
+{
+	return (addr + (size - 1)) & ~(size - 1);
+}
+
+static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
+				       phys_addr_t base2, phys_addr_t size2)
 {
 	return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
 }
 
-static long memblock_addrs_adjacent(u64 base1, u64 size1, u64 base2, u64 size2)
+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;
@@ -74,174 +69,365 @@
 	return 0;
 }
 
-static long memblock_regions_adjacent(struct memblock_region *rgn,
-		unsigned long r1, unsigned long r2)
+static long __init_memblock memblock_regions_adjacent(struct memblock_type *type,
+				 unsigned long r1, unsigned long r2)
 {
-	u64 base1 = rgn->region[r1].base;
-	u64 size1 = rgn->region[r1].size;
-	u64 base2 = rgn->region[r2].base;
-	u64 size2 = rgn->region[r2].size;
+	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);
 }
 
-static void memblock_remove_region(struct memblock_region *rgn, unsigned long r)
+long __init_memblock memblock_overlaps_region(struct memblock_type *type, phys_addr_t base, phys_addr_t size)
 {
 	unsigned long i;
 
-	for (i = r; i < rgn->cnt - 1; i++) {
-		rgn->region[i].base = rgn->region[i + 1].base;
-		rgn->region[i].size = rgn->region[i + 1].size;
+	for (i = 0; i < type->cnt; i++) {
+		phys_addr_t rgnbase = type->regions[i].base;
+		phys_addr_t rgnsize = type->regions[i].size;
+		if (memblock_addrs_overlap(base, size, rgnbase, rgnsize))
+			break;
 	}
-	rgn->cnt--;
+
+	return (i < type->cnt) ? i : -1;
+}
+
+/*
+ * Find, allocate, deallocate or reserve unreserved regions. All allocations
+ * are top-down.
+ */
+
+static phys_addr_t __init_memblock memblock_find_region(phys_addr_t start, phys_addr_t end,
+					  phys_addr_t size, phys_addr_t align)
+{
+	phys_addr_t base, res_base;
+	long j;
+
+	/* In case, huge size is requested */
+	if (end < size)
+		return MEMBLOCK_ERROR;
+
+	base = memblock_align_down((end - size), align);
+
+	/* Prevent allocations returning 0 as it's also used to
+	 * indicate an allocation failure
+	 */
+	if (start == 0)
+		start = PAGE_SIZE;
+
+	while (start <= base) {
+		j = memblock_overlaps_region(&memblock.reserved, base, size);
+		if (j < 0)
+			return base;
+		res_base = memblock.reserved.regions[j].base;
+		if (res_base < size)
+			break;
+		base = memblock_align_down(res_base - size, align);
+	}
+
+	return MEMBLOCK_ERROR;
+}
+
+static phys_addr_t __init_memblock memblock_find_base(phys_addr_t size,
+			phys_addr_t align, phys_addr_t start, phys_addr_t end)
+{
+	long i;
+
+	BUG_ON(0 == size);
+
+	size = memblock_align_up(size, align);
+
+	/* Pump up max_addr */
+	if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
+		end = memblock.current_limit;
+
+	/* We do a top-down search, this tends to limit memory
+	 * fragmentation by keeping early boot allocs near the
+	 * top of memory
+	 */
+	for (i = memblock.memory.cnt - 1; i >= 0; i--) {
+		phys_addr_t memblockbase = memblock.memory.regions[i].base;
+		phys_addr_t memblocksize = memblock.memory.regions[i].size;
+		phys_addr_t bottom, top, found;
+
+		if (memblocksize < size)
+			continue;
+		if ((memblockbase + memblocksize) <= start)
+			break;
+		bottom = max(memblockbase, start);
+		top = min(memblockbase + memblocksize, end);
+		if (bottom >= top)
+			continue;
+		found = memblock_find_region(bottom, top, size, align);
+		if (found != MEMBLOCK_ERROR)
+			return found;
+	}
+	return MEMBLOCK_ERROR;
+}
+
+/*
+ * Find a free area with specified alignment in a specific range.
+ */
+u64 __init_memblock memblock_find_in_range(u64 start, u64 end, u64 size, u64 align)
+{
+	return memblock_find_base(size, align, start, end);
+}
+
+/*
+ * Free memblock.reserved.regions
+ */
+int __init_memblock memblock_free_reserved_regions(void)
+{
+	if (memblock.reserved.regions == memblock_reserved_init_regions)
+		return 0;
+
+	return memblock_free(__pa(memblock.reserved.regions),
+		 sizeof(struct memblock_region) * memblock.reserved.max);
+}
+
+/*
+ * Reserve memblock.reserved.regions
+ */
+int __init_memblock memblock_reserve_reserved_regions(void)
+{
+	if (memblock.reserved.regions == memblock_reserved_init_regions)
+		return 0;
+
+	return memblock_reserve(__pa(memblock.reserved.regions),
+		 sizeof(struct memblock_region) * memblock.reserved.max);
+}
+
+static void __init_memblock memblock_remove_region(struct memblock_type *type, unsigned long r)
+{
+	unsigned long i;
+
+	for (i = r; i < type->cnt - 1; i++) {
+		type->regions[i].base = type->regions[i + 1].base;
+		type->regions[i].size = type->regions[i + 1].size;
+	}
+	type->cnt--;
 }
 
 /* Assumption: base addr of region 1 < base addr of region 2 */
-static void memblock_coalesce_regions(struct memblock_region *rgn,
+static void __init_memblock memblock_coalesce_regions(struct memblock_type *type,
 		unsigned long r1, unsigned long r2)
 {
-	rgn->region[r1].size += rgn->region[r2].size;
-	memblock_remove_region(rgn, r2);
+	type->regions[r1].size += type->regions[r2].size;
+	memblock_remove_region(type, r2);
 }
 
-void __init memblock_init(void)
+/* Defined below but needed now */
+static long memblock_add_region(struct memblock_type *type, phys_addr_t base, phys_addr_t size);
+
+static int __init_memblock memblock_double_array(struct memblock_type *type)
 {
-	/* Create a dummy zero size MEMBLOCK which will get coalesced away later.
-	 * This simplifies the memblock_add() code below...
+	struct memblock_region *new_array, *old_array;
+	phys_addr_t old_size, new_size, addr;
+	int use_slab = slab_is_available();
+
+	/* We don't allow resizing until we know about the reserved regions
+	 * of memory that aren't suitable for allocation
 	 */
-	memblock.memory.region[0].base = 0;
-	memblock.memory.region[0].size = 0;
-	memblock.memory.cnt = 1;
+	if (!memblock_can_resize)
+		return -1;
 
-	/* Ditto. */
-	memblock.reserved.region[0].base = 0;
-	memblock.reserved.region[0].size = 0;
-	memblock.reserved.cnt = 1;
+	/* Calculate new doubled size */
+	old_size = type->max * sizeof(struct memblock_region);
+	new_size = old_size << 1;
+
+	/* Try to find some space for it.
+	 *
+	 * WARNING: We assume that either slab_is_available() and we use it or
+	 * we use MEMBLOCK for allocations. That means that this is unsafe to use
+	 * when bootmem is currently active (unless bootmem itself is implemented
+	 * on top of MEMBLOCK which isn't the case yet)
+	 *
+	 * This should however not be an issue for now, as we currently only
+	 * call into MEMBLOCK while it's still active, or much later when slab is
+	 * active for memory hotplug operations
+	 */
+	if (use_slab) {
+		new_array = kmalloc(new_size, GFP_KERNEL);
+		addr = new_array == NULL ? MEMBLOCK_ERROR : __pa(new_array);
+	} else
+		addr = memblock_find_base(new_size, sizeof(phys_addr_t), 0, MEMBLOCK_ALLOC_ACCESSIBLE);
+	if (addr == MEMBLOCK_ERROR) {
+		pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n",
+		       memblock_type_name(type), type->max, type->max * 2);
+		return -1;
+	}
+	new_array = __va(addr);
+
+	memblock_dbg("memblock: %s array is doubled to %ld at [%#010llx-%#010llx]",
+		 memblock_type_name(type), type->max * 2, (u64)addr, (u64)addr + new_size - 1);
+
+	/* Found space, we now need to move the array over before
+	 * we add the reserved region since it may be our reserved
+	 * array itself that is full.
+	 */
+	memcpy(new_array, type->regions, old_size);
+	memset(new_array + type->max, 0, old_size);
+	old_array = type->regions;
+	type->regions = new_array;
+	type->max <<= 1;
+
+	/* If we use SLAB that's it, we are done */
+	if (use_slab)
+		return 0;
+
+	/* Add the new reserved region now. Should not fail ! */
+	BUG_ON(memblock_add_region(&memblock.reserved, addr, new_size) < 0);
+
+	/* 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
+	 * to use kfree or free_bootmem_pages(). Shouldn't be a big deal
+	 * anyways
+	 */
+	if (old_array != memblock_memory_init_regions &&
+	    old_array != memblock_reserved_init_regions)
+		memblock_free(__pa(old_array), old_size);
+
+	return 0;
 }
 
-void __init memblock_analyze(void)
+extern int __init_memblock __weak memblock_memory_can_coalesce(phys_addr_t addr1, phys_addr_t size1,
+					  phys_addr_t addr2, phys_addr_t size2)
 {
-	int i;
-
-	memblock.memory.size = 0;
-
-	for (i = 0; i < memblock.memory.cnt; i++)
-		memblock.memory.size += memblock.memory.region[i].size;
+	return 1;
 }
 
-static long memblock_add_region(struct memblock_region *rgn, u64 base, u64 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 ((rgn->cnt == 1) && (rgn->region[0].size == 0)) {
-		rgn->region[0].base = base;
-		rgn->region[0].size = size;
+	if ((type->cnt == 1) && (type->regions[0].size == 0)) {
+		type->regions[0].base = base;
+		type->regions[0].size = size;
 		return 0;
 	}
 
 	/* First try and coalesce this MEMBLOCK with another. */
-	for (i = 0; i < rgn->cnt; i++) {
-		u64 rgnbase = rgn->region[i].base;
-		u64 rgnsize = rgn->region[i].size;
+	for (i = 0; i < type->cnt; i++) {
+		phys_addr_t rgnbase = type->regions[i].base;
+		phys_addr_t rgnsize = type->regions[i].size;
 
 		if ((rgnbase == base) && (rgnsize == size))
 			/* Already have this region, so we're done */
 			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) {
-			rgn->region[i].base -= size;
-			rgn->region[i].size += size;
+			type->regions[i].base -= size;
+			type->regions[i].size += size;
 			coalesced++;
 			break;
 		} else if (adjacent < 0) {
-			rgn->region[i].size += size;
+			type->regions[i].size += size;
 			coalesced++;
 			break;
 		}
 	}
 
-	if ((i < rgn->cnt - 1) && memblock_regions_adjacent(rgn, i, i+1)) {
-		memblock_coalesce_regions(rgn, i, i+1);
+	/* If we plugged a hole, we may want to also coalesce with the
+	 * next region
+	 */
+	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 (coalesced)
 		return coalesced;
-	if (rgn->cnt >= MAX_MEMBLOCK_REGIONS)
+
+	/* 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.
+	 */
+	if (WARN_ON(type->cnt >= type->max))
 		return -1;
 
 	/* Couldn't coalesce the MEMBLOCK, so add it to the sorted table. */
-	for (i = rgn->cnt - 1; i >= 0; i--) {
-		if (base < rgn->region[i].base) {
-			rgn->region[i+1].base = rgn->region[i].base;
-			rgn->region[i+1].size = rgn->region[i].size;
+	for (i = type->cnt - 1; i >= 0; i--) {
+		if (base < type->regions[i].base) {
+			type->regions[i+1].base = type->regions[i].base;
+			type->regions[i+1].size = type->regions[i].size;
 		} else {
-			rgn->region[i+1].base = base;
-			rgn->region[i+1].size = size;
+			type->regions[i+1].base = base;
+			type->regions[i+1].size = size;
 			break;
 		}
 	}
 
-	if (base < rgn->region[0].base) {
-		rgn->region[0].base = base;
-		rgn->region[0].size = size;
+	if (base < type->regions[0].base) {
+		type->regions[0].base = base;
+		type->regions[0].size = size;
 	}
-	rgn->cnt++;
+	type->cnt++;
+
+	/* The array is full ? Try to resize it. If that fails, we undo
+	 * our allocation and return an error
+	 */
+	if (type->cnt == type->max && memblock_double_array(type)) {
+		type->cnt--;
+		return -1;
+	}
 
 	return 0;
 }
 
-long memblock_add(u64 base, u64 size)
+long __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
 {
-	struct memblock_region *_rgn = &memblock.memory;
-
-	/* On pSeries LPAR systems, the first MEMBLOCK is our RMO region. */
-	if (base == 0)
-		memblock.rmo_size = size;
-
-	return memblock_add_region(_rgn, base, size);
+	return memblock_add_region(&memblock.memory, base, size);
 
 }
 
-static long __memblock_remove(struct memblock_region *rgn, u64 base, u64 size)
+static long __init_memblock __memblock_remove(struct memblock_type *type, phys_addr_t base, phys_addr_t size)
 {
-	u64 rgnbegin, rgnend;
-	u64 end = base + 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 < rgn->cnt; i++) {
-		rgnbegin = rgn->region[i].base;
-		rgnend = rgnbegin + rgn->region[i].size;
+	for (i=0; i < type->cnt; i++) {
+		rgnbegin = type->regions[i].base;
+		rgnend = rgnbegin + type->regions[i].size;
 
 		if ((rgnbegin <= base) && (end <= rgnend))
 			break;
 	}
 
 	/* Didn't find the region */
-	if (i == rgn->cnt)
+	if (i == type->cnt)
 		return -1;
 
 	/* Check to see if we are removing entire region */
 	if ((rgnbegin == base) && (rgnend == end)) {
-		memblock_remove_region(rgn, i);
+		memblock_remove_region(type, i);
 		return 0;
 	}
 
 	/* Check to see if region is matching at the front */
 	if (rgnbegin == base) {
-		rgn->region[i].base = end;
-		rgn->region[i].size -= size;
+		type->regions[i].base = end;
+		type->regions[i].size -= size;
 		return 0;
 	}
 
 	/* Check to see if the region is matching at the end */
 	if (rgnend == end) {
-		rgn->region[i].size -= size;
+		type->regions[i].size -= size;
 		return 0;
 	}
 
@@ -249,133 +435,49 @@
 	 * We need to split the entry -  adjust the current one to the
 	 * beginging of the hole and add the region after hole.
 	 */
-	rgn->region[i].size = base - rgn->region[i].base;
-	return memblock_add_region(rgn, end, rgnend - end);
+	type->regions[i].size = base - type->regions[i].base;
+	return memblock_add_region(type, end, rgnend - end);
 }
 
-long memblock_remove(u64 base, u64 size)
+long __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)
 {
 	return __memblock_remove(&memblock.memory, base, size);
 }
 
-long __init memblock_free(u64 base, u64 size)
+long __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)
 {
 	return __memblock_remove(&memblock.reserved, base, size);
 }
 
-long __init memblock_reserve(u64 base, u64 size)
+long __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
 {
-	struct memblock_region *_rgn = &memblock.reserved;
+	struct memblock_type *_rgn = &memblock.reserved;
 
 	BUG_ON(0 == size);
 
 	return memblock_add_region(_rgn, base, size);
 }
 
-long memblock_overlaps_region(struct memblock_region *rgn, u64 base, u64 size)
+phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
 {
-	unsigned long i;
+	phys_addr_t found;
 
-	for (i = 0; i < rgn->cnt; i++) {
-		u64 rgnbase = rgn->region[i].base;
-		u64 rgnsize = rgn->region[i].size;
-		if (memblock_addrs_overlap(base, size, rgnbase, rgnsize))
-			break;
-	}
-
-	return (i < rgn->cnt) ? i : -1;
-}
-
-static u64 memblock_align_down(u64 addr, u64 size)
-{
-	return addr & ~(size - 1);
-}
-
-static u64 memblock_align_up(u64 addr, u64 size)
-{
-	return (addr + (size - 1)) & ~(size - 1);
-}
-
-static u64 __init memblock_alloc_nid_unreserved(u64 start, u64 end,
-					   u64 size, u64 align)
-{
-	u64 base, res_base;
-	long j;
-
-	base = memblock_align_down((end - size), align);
-	while (start <= base) {
-		j = memblock_overlaps_region(&memblock.reserved, base, size);
-		if (j < 0) {
-			/* this area isn't reserved, take it */
-			if (memblock_add_region(&memblock.reserved, base, size) < 0)
-				base = ~(u64)0;
-			return base;
-		}
-		res_base = memblock.reserved.region[j].base;
-		if (res_base < size)
-			break;
-		base = memblock_align_down(res_base - size, align);
-	}
-
-	return ~(u64)0;
-}
-
-static u64 __init memblock_alloc_nid_region(struct memblock_property *mp,
-				       u64 (*nid_range)(u64, u64, int *),
-				       u64 size, u64 align, int nid)
-{
-	u64 start, end;
-
-	start = mp->base;
-	end = start + mp->size;
-
-	start = memblock_align_up(start, align);
-	while (start < end) {
-		u64 this_end;
-		int this_nid;
-
-		this_end = nid_range(start, end, &this_nid);
-		if (this_nid == nid) {
-			u64 ret = memblock_alloc_nid_unreserved(start, this_end,
-							   size, align);
-			if (ret != ~(u64)0)
-				return ret;
-		}
-		start = this_end;
-	}
-
-	return ~(u64)0;
-}
-
-u64 __init memblock_alloc_nid(u64 size, u64 align, int nid,
-			 u64 (*nid_range)(u64 start, u64 end, int *nid))
-{
-	struct memblock_region *mem = &memblock.memory;
-	int i;
-
-	BUG_ON(0 == size);
-
+	/* We align the size to limit fragmentation. Without this, a lot of
+	 * small allocs quickly eat up the whole reserve array on sparc
+	 */
 	size = memblock_align_up(size, align);
 
-	for (i = 0; i < mem->cnt; i++) {
-		u64 ret = memblock_alloc_nid_region(&mem->region[i],
-					       nid_range,
-					       size, align, nid);
-		if (ret != ~(u64)0)
-			return ret;
-	}
+	found = memblock_find_base(size, align, 0, max_addr);
+	if (found != MEMBLOCK_ERROR &&
+	    memblock_add_region(&memblock.reserved, found, size) >= 0)
+		return found;
 
-	return memblock_alloc(size, align);
+	return 0;
 }
 
-u64 __init memblock_alloc(u64 size, u64 align)
+phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
 {
-	return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE);
-}
-
-u64 __init memblock_alloc_base(u64 size, u64 align, u64 max_addr)
-{
-	u64 alloc;
+	phys_addr_t alloc;
 
 	alloc = __memblock_alloc_base(size, align, max_addr);
 
@@ -386,71 +488,136 @@
 	return alloc;
 }
 
-u64 __init __memblock_alloc_base(u64 size, u64 align, u64 max_addr)
+phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align)
 {
-	long i, j;
-	u64 base = 0;
-	u64 res_base;
+	return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
+}
+
+
+/*
+ * Additional node-local allocators. Search for node memory is bottom up
+ * and walks memblock regions within that node bottom-up as well, but allocation
+ * within an memblock region is top-down. XXX I plan to fix that at some stage
+ *
+ * WARNING: Only available after early_node_map[] has been populated,
+ * on some architectures, that is after all the calls to add_active_range()
+ * have been done to populate it.
+ */
+
+phys_addr_t __weak __init memblock_nid_range(phys_addr_t start, phys_addr_t end, int *nid)
+{
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+	/*
+	 * This code originates from sparc which really wants use to walk by addresses
+	 * and returns the nid. This is not very convenient for early_pfn_map[] users
+	 * as the map isn't sorted yet, and it really wants to be walked by nid.
+	 *
+	 * For now, I implement the inefficient method below which walks the early
+	 * map multiple times. Eventually we may want to use an ARCH config option
+	 * to implement a completely different method for both case.
+	 */
+	unsigned long start_pfn, end_pfn;
+	int i;
+
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		get_pfn_range_for_nid(i, &start_pfn, &end_pfn);
+		if (start < PFN_PHYS(start_pfn) || start >= PFN_PHYS(end_pfn))
+			continue;
+		*nid = i;
+		return min(end, PFN_PHYS(end_pfn));
+	}
+#endif
+	*nid = 0;
+
+	return end;
+}
+
+static phys_addr_t __init memblock_alloc_nid_region(struct memblock_region *mp,
+					       phys_addr_t size,
+					       phys_addr_t align, int nid)
+{
+	phys_addr_t start, end;
+
+	start = mp->base;
+	end = start + mp->size;
+
+	start = memblock_align_up(start, align);
+	while (start < end) {
+		phys_addr_t this_end;
+		int this_nid;
+
+		this_end = memblock_nid_range(start, end, &this_nid);
+		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)
+				return ret;
+		}
+		start = this_end;
+	}
+
+	return MEMBLOCK_ERROR;
+}
+
+phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
+{
+	struct memblock_type *mem = &memblock.memory;
+	int i;
 
 	BUG_ON(0 == size);
 
+	/* We align the size to limit fragmentation. Without this, a lot of
+	 * small allocs quickly eat up the whole reserve array on sparc
+	 */
 	size = memblock_align_up(size, align);
 
-	/* On some platforms, make sure we allocate lowmem */
-	/* Note that MEMBLOCK_REAL_LIMIT may be MEMBLOCK_ALLOC_ANYWHERE */
-	if (max_addr == MEMBLOCK_ALLOC_ANYWHERE)
-		max_addr = MEMBLOCK_REAL_LIMIT;
-
-	for (i = memblock.memory.cnt - 1; i >= 0; i--) {
-		u64 memblockbase = memblock.memory.region[i].base;
-		u64 memblocksize = memblock.memory.region[i].size;
-
-		if (memblocksize < size)
-			continue;
-		if (max_addr == MEMBLOCK_ALLOC_ANYWHERE)
-			base = memblock_align_down(memblockbase + memblocksize - size, align);
-		else if (memblockbase < max_addr) {
-			base = min(memblockbase + memblocksize, max_addr);
-			base = memblock_align_down(base - size, align);
-		} else
-			continue;
-
-		while (base && memblockbase <= base) {
-			j = memblock_overlaps_region(&memblock.reserved, base, size);
-			if (j < 0) {
-				/* this area isn't reserved, take it */
-				if (memblock_add_region(&memblock.reserved, base, size) < 0)
-					return 0;
-				return base;
-			}
-			res_base = memblock.reserved.region[j].base;
-			if (res_base < size)
-				break;
-			base = memblock_align_down(res_base - size, align);
-		}
+	/* We do a bottom-up search for a region with the right
+	 * nid since that's easier considering how memblock_nid_range()
+	 * works
+	 */
+	for (i = 0; i < mem->cnt; i++) {
+		phys_addr_t ret = memblock_alloc_nid_region(&mem->regions[i],
+					       size, align, nid);
+		if (ret != MEMBLOCK_ERROR)
+			return ret;
 	}
+
 	return 0;
 }
 
-/* You must call memblock_analyze() before this. */
-u64 __init memblock_phys_mem_size(void)
+phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid)
 {
-	return memblock.memory.size;
+	phys_addr_t res = memblock_alloc_nid(size, align, nid);
+
+	if (res)
+		return res;
+	return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE);
 }
 
-u64 memblock_end_of_DRAM(void)
+
+/*
+ * Remaining API functions
+ */
+
+/* You must call memblock_analyze() before this. */
+phys_addr_t __init memblock_phys_mem_size(void)
+{
+	return memblock.memory_size;
+}
+
+phys_addr_t __init_memblock memblock_end_of_DRAM(void)
 {
 	int idx = memblock.memory.cnt - 1;
 
-	return (memblock.memory.region[idx].base + memblock.memory.region[idx].size);
+	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
 }
 
 /* You must call memblock_analyze() after this. */
-void __init memblock_enforce_memory_limit(u64 memory_limit)
+void __init memblock_enforce_memory_limit(phys_addr_t memory_limit)
 {
 	unsigned long i;
-	u64 limit;
-	struct memblock_property *p;
+	phys_addr_t limit;
+	struct memblock_region *p;
 
 	if (!memory_limit)
 		return;
@@ -458,24 +625,21 @@
 	/* Truncate the memblock regions to satisfy the memory limit. */
 	limit = memory_limit;
 	for (i = 0; i < memblock.memory.cnt; i++) {
-		if (limit > memblock.memory.region[i].size) {
-			limit -= memblock.memory.region[i].size;
+		if (limit > memblock.memory.regions[i].size) {
+			limit -= memblock.memory.regions[i].size;
 			continue;
 		}
 
-		memblock.memory.region[i].size = limit;
+		memblock.memory.regions[i].size = limit;
 		memblock.memory.cnt = i + 1;
 		break;
 	}
 
-	if (memblock.memory.region[0].size < memblock.rmo_size)
-		memblock.rmo_size = memblock.memory.region[0].size;
-
 	memory_limit = memblock_end_of_DRAM();
 
 	/* And truncate any reserves above the limit also. */
 	for (i = 0; i < memblock.reserved.cnt; i++) {
-		p = &memblock.reserved.region[i];
+		p = &memblock.reserved.regions[i];
 
 		if (p->base > memory_limit)
 			p->size = 0;
@@ -489,53 +653,190 @@
 	}
 }
 
-int __init memblock_is_reserved(u64 addr)
+static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
 {
-	int i;
+	unsigned int left = 0, right = type->cnt;
 
-	for (i = 0; i < memblock.reserved.cnt; i++) {
-		u64 upper = memblock.reserved.region[i].base +
-			memblock.reserved.region[i].size - 1;
-		if ((addr >= memblock.reserved.region[i].base) && (addr <= upper))
-			return 1;
-	}
-	return 0;
+	do {
+		unsigned int mid = (right + left) / 2;
+
+		if (addr < type->regions[mid].base)
+			right = mid;
+		else if (addr >= (type->regions[mid].base +
+				  type->regions[mid].size))
+			left = mid + 1;
+		else
+			return mid;
+	} while (left < right);
+	return -1;
 }
 
-int memblock_is_region_reserved(u64 base, u64 size)
+int __init memblock_is_reserved(phys_addr_t addr)
+{
+	return memblock_search(&memblock.reserved, addr) != -1;
+}
+
+int __init_memblock memblock_is_memory(phys_addr_t addr)
+{
+	return memblock_search(&memblock.memory, addr) != -1;
+}
+
+int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size)
+{
+	int idx = memblock_search(&memblock.reserved, base);
+
+	if (idx == -1)
+		return 0;
+	return memblock.reserved.regions[idx].base <= base &&
+		(memblock.reserved.regions[idx].base +
+		 memblock.reserved.regions[idx].size) >= (base + size);
+}
+
+int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size)
 {
 	return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
 }
 
-/*
- * Given a <base, len>, find which memory regions belong to this range.
- * Adjust the request and return a contiguous chunk.
- */
-int memblock_find(struct memblock_property *res)
+
+void __init_memblock memblock_set_current_limit(phys_addr_t limit)
+{
+	memblock.current_limit = limit;
+}
+
+static void __init_memblock memblock_dump(struct memblock_type *region, char *name)
+{
+	unsigned long long base, size;
+	int i;
+
+	pr_info(" %s.cnt  = 0x%lx\n", name, region->cnt);
+
+	for (i = 0; i < region->cnt; i++) {
+		base = region->regions[i].base;
+		size = region->regions[i].size;
+
+		pr_info(" %s[%#x]\t[%#016llx-%#016llx], %#llx bytes\n",
+		    name, i, base, base + size - 1, size);
+	}
+}
+
+void __init_memblock memblock_dump_all(void)
+{
+	if (!memblock_debug)
+		return;
+
+	pr_info("MEMBLOCK configuration:\n");
+	pr_info(" memory size = 0x%llx\n", (unsigned long long)memblock.memory_size);
+
+	memblock_dump(&memblock.memory, "memory");
+	memblock_dump(&memblock.reserved, "reserved");
+}
+
+void __init memblock_analyze(void)
 {
 	int i;
-	u64 rstart, rend;
 
-	rstart = res->base;
-	rend = rstart + res->size - 1;
+	/* Check marker in the unused last array entry */
+	WARN_ON(memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS].base
+		!= (phys_addr_t)RED_INACTIVE);
+	WARN_ON(memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS].base
+		!= (phys_addr_t)RED_INACTIVE);
 
-	for (i = 0; i < memblock.memory.cnt; i++) {
-		u64 start = memblock.memory.region[i].base;
-		u64 end = start + memblock.memory.region[i].size - 1;
+	memblock.memory_size = 0;
 
-		if (start > rend)
-			return -1;
+	for (i = 0; i < memblock.memory.cnt; i++)
+		memblock.memory_size += memblock.memory.regions[i].size;
 
-		if ((end >= rstart) && (start < rend)) {
-			/* adjust the request */
-			if (rstart < start)
-				rstart = start;
-			if (rend > end)
-				rend = end;
-			res->base = rstart;
-			res->size = rend - rstart + 1;
-			return 0;
-		}
-	}
-	return -1;
+	/* We allow resizing from there */
+	memblock_can_resize = 1;
 }
+
+void __init memblock_init(void)
+{
+	static int init_done __initdata = 0;
+
+	if (init_done)
+		return;
+	init_done = 1;
+
+	/* Hookup the initial arrays */
+	memblock.memory.regions	= memblock_memory_init_regions;
+	memblock.memory.max		= INIT_MEMBLOCK_REGIONS;
+	memblock.reserved.regions	= memblock_reserved_init_regions;
+	memblock.reserved.max	= INIT_MEMBLOCK_REGIONS;
+
+	/* Write a marker in the unused last array entry */
+	memblock.memory.regions[INIT_MEMBLOCK_REGIONS].base = (phys_addr_t)RED_INACTIVE;
+	memblock.reserved.regions[INIT_MEMBLOCK_REGIONS].base = (phys_addr_t)RED_INACTIVE;
+
+	/* Create a dummy zero size MEMBLOCK which will get coalesced away later.
+	 * This simplifies the memblock_add() code below...
+	 */
+	memblock.memory.regions[0].base = 0;
+	memblock.memory.regions[0].size = 0;
+	memblock.memory.cnt = 1;
+
+	/* Ditto. */
+	memblock.reserved.regions[0].base = 0;
+	memblock.reserved.regions[0].size = 0;
+	memblock.reserved.cnt = 1;
+
+	memblock.current_limit = MEMBLOCK_ALLOC_ANYWHERE;
+}
+
+static int __init early_memblock(char *p)
+{
+	if (p && strstr(p, "debug"))
+		memblock_debug = 1;
+	return 0;
+}
+early_param("memblock", early_memblock);
+
+#if defined(CONFIG_DEBUG_FS) && !defined(ARCH_DISCARD_MEMBLOCK)
+
+static int memblock_debug_show(struct seq_file *m, void *private)
+{
+	struct memblock_type *type = m->private;
+	struct memblock_region *reg;
+	int i;
+
+	for (i = 0; i < type->cnt; i++) {
+		reg = &type->regions[i];
+		seq_printf(m, "%4d: ", i);
+		if (sizeof(phys_addr_t) == 4)
+			seq_printf(m, "0x%08lx..0x%08lx\n",
+				   (unsigned long)reg->base,
+				   (unsigned long)(reg->base + reg->size - 1));
+		else
+			seq_printf(m, "0x%016llx..0x%016llx\n",
+				   (unsigned long long)reg->base,
+				   (unsigned long long)(reg->base + reg->size - 1));
+
+	}
+	return 0;
+}
+
+static int memblock_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, memblock_debug_show, inode->i_private);
+}
+
+static const struct file_operations memblock_debug_fops = {
+	.open = memblock_debug_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int __init memblock_init_debugfs(void)
+{
+	struct dentry *root = debugfs_create_dir("memblock", NULL);
+	if (!root)
+		return -ENXIO;
+	debugfs_create_file("memory", S_IRUGO, root, &memblock.memory, &memblock_debug_fops);
+	debugfs_create_file("reserved", S_IRUGO, root, &memblock.reserved, &memblock_debug_fops);
+
+	return 0;
+}
+__initcall(memblock_init_debugfs);
+
+#endif /* CONFIG_DEBUG_FS */
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 3eed583..9be3cf8 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3587,9 +3587,13 @@
 
 static void mem_cgroup_threshold(struct mem_cgroup *memcg)
 {
-	__mem_cgroup_threshold(memcg, false);
-	if (do_swap_account)
-		__mem_cgroup_threshold(memcg, true);
+	while (memcg) {
+		__mem_cgroup_threshold(memcg, false);
+		if (do_swap_account)
+			__mem_cgroup_threshold(memcg, true);
+
+		memcg = parent_mem_cgroup(memcg);
+	}
 }
 
 static int compare_thresholds(const void *a, const void *b)
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 9c26eec..757f6b0 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -183,7 +183,7 @@
  * signal.
  */
 static int kill_proc_ao(struct task_struct *t, unsigned long addr, int trapno,
-			unsigned long pfn)
+			unsigned long pfn, struct page *page)
 {
 	struct siginfo si;
 	int ret;
@@ -198,7 +198,7 @@
 #ifdef __ARCH_SI_TRAPNO
 	si.si_trapno = trapno;
 #endif
-	si.si_addr_lsb = PAGE_SHIFT;
+	si.si_addr_lsb = compound_order(compound_head(page)) + PAGE_SHIFT;
 	/*
 	 * Don't use force here, it's convenient if the signal
 	 * can be temporarily blocked.
@@ -235,7 +235,7 @@
 		int nr;
 		do {
 			nr = shrink_slab(1000, GFP_KERNEL, 1000);
-			if (page_count(p) == 0)
+			if (page_count(p) == 1)
 				break;
 		} while (nr > 10);
 	}
@@ -327,7 +327,7 @@
  * wrong earlier.
  */
 static void kill_procs_ao(struct list_head *to_kill, int doit, int trapno,
-			  int fail, unsigned long pfn)
+			  int fail, struct page *page, unsigned long pfn)
 {
 	struct to_kill *tk, *next;
 
@@ -352,7 +352,7 @@
 			 * process anyways.
 			 */
 			else if (kill_proc_ao(tk->tsk, tk->addr, trapno,
-					      pfn) < 0)
+					      pfn, page) < 0)
 				printk(KERN_ERR
 		"MCE %#lx: Cannot send advisory machine check signal to %s:%d\n",
 					pfn, tk->tsk->comm, tk->tsk->pid);
@@ -928,7 +928,7 @@
 	 * any accesses to the poisoned memory.
 	 */
 	kill_procs_ao(&tokill, !!PageDirty(hpage), trapno,
-		      ret != SWAP_SUCCESS, pfn);
+		      ret != SWAP_SUCCESS, p, pfn);
 
 	return ret;
 }
diff --git a/mm/memory.c b/mm/memory.c
index 0e18b4d..98b58fe 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3185,7 +3185,7 @@
 		 * with threads.
 		 */
 		if (flags & FAULT_FLAG_WRITE)
-			flush_tlb_page(vma, address);
+			flush_tlb_fix_spurious_fault(vma, address);
 	}
 unlock:
 	pte_unmap_unlock(pte, ptl);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index dd186c1..d4e940a 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -840,7 +840,6 @@
 	ret = 0;
 	if (drain) {
 		lru_add_drain_all();
-		flush_scheduled_work();
 		cond_resched();
 		drain_all_pages();
 	}
@@ -862,7 +861,6 @@
 	}
 	/* drain all zone's lru pagevec, this is asyncronous... */
 	lru_add_drain_all();
-	flush_scheduled_work();
 	yield();
 	/* drain pcp pages , this is synchrouns. */
 	drain_all_pages();
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index a8cfa9c..2a362c5 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -21,6 +21,7 @@
 #include <linux/pagemap.h>
 #include <linux/jiffies.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/kmemcheck.h>
@@ -3636,6 +3637,41 @@
 	}
 }
 
+#ifdef CONFIG_HAVE_MEMBLOCK
+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) {
+		u64 addr;
+		u64 ei_start, ei_last;
+		u64 final_start, final_end;
+
+		ei_last = early_node_map[i].end_pfn;
+		ei_last <<= PAGE_SHIFT;
+		ei_start = early_node_map[i].start_pfn;
+		ei_start <<= PAGE_SHIFT;
+
+		final_start = max(ei_start, goal);
+		final_end = min(ei_last, limit);
+
+		if (final_start >= final_end)
+			continue;
+
+		addr = memblock_find_in_range(final_start, final_end, size, align);
+
+		if (addr == MEMBLOCK_ERROR)
+			continue;
+
+		return addr;
+	}
+
+	return MEMBLOCK_ERROR;
+}
+#endif
+
 int __init add_from_early_node_map(struct range *range, int az,
 				   int nr_range, int nid)
 {
@@ -3655,46 +3691,26 @@
 void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
 					u64 goal, u64 limit)
 {
-	int i;
 	void *ptr;
+	u64 addr;
 
-	if (limit > get_max_mapped())
-		limit = get_max_mapped();
+	if (limit > memblock.current_limit)
+		limit = memblock.current_limit;
 
-	/* need to go over early_node_map to find out good range for node */
-	for_each_active_range_index_in_nid(i, nid) {
-		u64 addr;
-		u64 ei_start, ei_last;
+	addr = find_memory_core_early(nid, size, align, goal, limit);
 
-		ei_last = early_node_map[i].end_pfn;
-		ei_last <<= PAGE_SHIFT;
-		ei_start = early_node_map[i].start_pfn;
-		ei_start <<= PAGE_SHIFT;
-		addr = find_early_area(ei_start, ei_last,
-					 goal, limit, size, align);
+	if (addr == MEMBLOCK_ERROR)
+		return NULL;
 
-		if (addr == -1ULL)
-			continue;
-
-#if 0
-		printk(KERN_DEBUG "alloc (nid=%d %llx - %llx) (%llx - %llx) %llx %llx => %llx\n",
-				nid,
-				ei_start, ei_last, goal, limit, size,
-				align, addr);
-#endif
-
-		ptr = phys_to_virt(addr);
-		memset(ptr, 0, size);
-		reserve_early_without_check(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;
-	}
-
-	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
 
@@ -5182,9 +5198,9 @@
 	if (!table)
 		panic("Failed to allocate %s hash table\n", tablename);
 
-	printk(KERN_INFO "%s hash table entries: %d (order: %d, %lu bytes)\n",
+	printk(KERN_INFO "%s hash table entries: %ld (order: %d, %lu bytes)\n",
 	       tablename,
-	       (1U << log2qty),
+	       (1UL << log2qty),
 	       ilog2(size) - PAGE_SHIFT,
 	       size);
 
diff --git a/mm/percpu-km.c b/mm/percpu-km.c
index df68085..89633fe 100644
--- a/mm/percpu-km.c
+++ b/mm/percpu-km.c
@@ -27,7 +27,7 @@
  *   chunk size is not aligned.  percpu-km code will whine about it.
  */
 
-#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
+#if defined(CONFIG_SMP) && defined(CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK)
 #error "contiguous percpu allocation is incompatible with paged first chunk"
 #endif
 
@@ -35,7 +35,11 @@
 
 static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size)
 {
-	/* noop */
+	unsigned int cpu;
+
+	for_each_possible_cpu(cpu)
+		memset((void *)pcpu_chunk_addr(chunk, cpu, 0) + off, 0, size);
+
 	return 0;
 }
 
diff --git a/mm/percpu.c b/mm/percpu.c
index c76ef38..6fc9015 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -76,6 +76,7 @@
 #define PCPU_SLOT_BASE_SHIFT		5	/* 1-31 shares the same slot */
 #define PCPU_DFL_MAP_ALLOC		16	/* start a map with 16 ents */
 
+#ifdef CONFIG_SMP
 /* default addr <-> pcpu_ptr mapping, override in asm/percpu.h if necessary */
 #ifndef __addr_to_pcpu_ptr
 #define __addr_to_pcpu_ptr(addr)					\
@@ -89,6 +90,11 @@
 			 (unsigned long)pcpu_base_addr -		\
 			 (unsigned long)__per_cpu_start)
 #endif
+#else	/* CONFIG_SMP */
+/* on UP, it's always identity mapped */
+#define __addr_to_pcpu_ptr(addr)	(void __percpu *)(addr)
+#define __pcpu_ptr_to_addr(ptr)		(void __force *)(ptr)
+#endif	/* CONFIG_SMP */
 
 struct pcpu_chunk {
 	struct list_head	list;		/* linked to pcpu_slot lists */
@@ -820,8 +826,8 @@
  * @size: size of area to allocate in bytes
  * @align: alignment of area (max PAGE_SIZE)
  *
- * Allocate percpu area of @size bytes aligned at @align.  Might
- * sleep.  Might trigger writeouts.
+ * Allocate zero-filled percpu area of @size bytes aligned at @align.
+ * Might sleep.  Might trigger writeouts.
  *
  * CONTEXT:
  * Does GFP_KERNEL allocation.
@@ -840,9 +846,10 @@
  * @size: size of area to allocate in bytes
  * @align: alignment of area (max PAGE_SIZE)
  *
- * Allocate percpu area of @size bytes aligned at @align from reserved
- * percpu area if arch has set it up; otherwise, allocation is served
- * from the same dynamic area.  Might sleep.  Might trigger writeouts.
+ * Allocate zero-filled percpu area of @size bytes aligned at @align
+ * from reserved percpu area if arch has set it up; otherwise,
+ * allocation is served from the same dynamic area.  Might sleep.
+ * Might trigger writeouts.
  *
  * CONTEXT:
  * Does GFP_KERNEL allocation.
@@ -949,6 +956,7 @@
  */
 bool is_kernel_percpu_address(unsigned long addr)
 {
+#ifdef CONFIG_SMP
 	const size_t static_size = __per_cpu_end - __per_cpu_start;
 	void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr);
 	unsigned int cpu;
@@ -959,6 +967,8 @@
 		if ((void *)addr >= start && (void *)addr < start + static_size)
 			return true;
         }
+#endif
+	/* on UP, can't distinguish from other static vars, always false */
 	return false;
 }
 
@@ -1067,6 +1077,321 @@
 }
 
 /**
+ * pcpu_dump_alloc_info - print out information about pcpu_alloc_info
+ * @lvl: loglevel
+ * @ai: allocation info to dump
+ *
+ * Print out information about @ai using loglevel @lvl.
+ */
+static void pcpu_dump_alloc_info(const char *lvl,
+				 const struct pcpu_alloc_info *ai)
+{
+	int group_width = 1, cpu_width = 1, width;
+	char empty_str[] = "--------";
+	int alloc = 0, alloc_end = 0;
+	int group, v;
+	int upa, apl;	/* units per alloc, allocs per line */
+
+	v = ai->nr_groups;
+	while (v /= 10)
+		group_width++;
+
+	v = num_possible_cpus();
+	while (v /= 10)
+		cpu_width++;
+	empty_str[min_t(int, cpu_width, sizeof(empty_str) - 1)] = '\0';
+
+	upa = ai->alloc_size / ai->unit_size;
+	width = upa * (cpu_width + 1) + group_width + 3;
+	apl = rounddown_pow_of_two(max(60 / width, 1));
+
+	printk("%spcpu-alloc: s%zu r%zu d%zu u%zu alloc=%zu*%zu",
+	       lvl, ai->static_size, ai->reserved_size, ai->dyn_size,
+	       ai->unit_size, ai->alloc_size / ai->atom_size, ai->atom_size);
+
+	for (group = 0; group < ai->nr_groups; group++) {
+		const struct pcpu_group_info *gi = &ai->groups[group];
+		int unit = 0, unit_end = 0;
+
+		BUG_ON(gi->nr_units % upa);
+		for (alloc_end += gi->nr_units / upa;
+		     alloc < alloc_end; alloc++) {
+			if (!(alloc % apl)) {
+				printk("\n");
+				printk("%spcpu-alloc: ", lvl);
+			}
+			printk("[%0*d] ", group_width, group);
+
+			for (unit_end += upa; unit < unit_end; unit++)
+				if (gi->cpu_map[unit] != NR_CPUS)
+					printk("%0*d ", cpu_width,
+					       gi->cpu_map[unit]);
+				else
+					printk("%s ", empty_str);
+		}
+	}
+	printk("\n");
+}
+
+/**
+ * pcpu_setup_first_chunk - initialize the first percpu chunk
+ * @ai: pcpu_alloc_info describing how to percpu area is shaped
+ * @base_addr: mapped address
+ *
+ * Initialize the first percpu chunk which contains the kernel static
+ * perpcu area.  This function is to be called from arch percpu area
+ * setup path.
+ *
+ * @ai contains all information necessary to initialize the first
+ * chunk and prime the dynamic percpu allocator.
+ *
+ * @ai->static_size is the size of static percpu area.
+ *
+ * @ai->reserved_size, if non-zero, specifies the amount of bytes to
+ * reserve after the static area in the first chunk.  This reserves
+ * the first chunk such that it's available only through reserved
+ * percpu allocation.  This is primarily used to serve module percpu
+ * static areas on architectures where the addressing model has
+ * limited offset range for symbol relocations to guarantee module
+ * percpu symbols fall inside the relocatable range.
+ *
+ * @ai->dyn_size determines the number of bytes available for dynamic
+ * allocation in the first chunk.  The area between @ai->static_size +
+ * @ai->reserved_size + @ai->dyn_size and @ai->unit_size is unused.
+ *
+ * @ai->unit_size specifies unit size and must be aligned to PAGE_SIZE
+ * and equal to or larger than @ai->static_size + @ai->reserved_size +
+ * @ai->dyn_size.
+ *
+ * @ai->atom_size is the allocation atom size and used as alignment
+ * for vm areas.
+ *
+ * @ai->alloc_size is the allocation size and always multiple of
+ * @ai->atom_size.  This is larger than @ai->atom_size if
+ * @ai->unit_size is larger than @ai->atom_size.
+ *
+ * @ai->nr_groups and @ai->groups describe virtual memory layout of
+ * percpu areas.  Units which should be colocated are put into the
+ * same group.  Dynamic VM areas will be allocated according to these
+ * groupings.  If @ai->nr_groups is zero, a single group containing
+ * all units is assumed.
+ *
+ * The caller should have mapped the first chunk at @base_addr and
+ * copied static data to each unit.
+ *
+ * If the first chunk ends up with both reserved and dynamic areas, it
+ * is served by two chunks - one to serve the core static and reserved
+ * areas and the other for the dynamic area.  They share the same vm
+ * and page map but uses different area allocation map to stay away
+ * from each other.  The latter chunk is circulated in the chunk slots
+ * and available for dynamic allocation like any other chunks.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
+				  void *base_addr)
+{
+	static char cpus_buf[4096] __initdata;
+	static int smap[PERCPU_DYNAMIC_EARLY_SLOTS] __initdata;
+	static int dmap[PERCPU_DYNAMIC_EARLY_SLOTS] __initdata;
+	size_t dyn_size = ai->dyn_size;
+	size_t size_sum = ai->static_size + ai->reserved_size + dyn_size;
+	struct pcpu_chunk *schunk, *dchunk = NULL;
+	unsigned long *group_offsets;
+	size_t *group_sizes;
+	unsigned long *unit_off;
+	unsigned int cpu;
+	int *unit_map;
+	int group, unit, i;
+
+	cpumask_scnprintf(cpus_buf, sizeof(cpus_buf), cpu_possible_mask);
+
+#define PCPU_SETUP_BUG_ON(cond)	do {					\
+	if (unlikely(cond)) {						\
+		pr_emerg("PERCPU: failed to initialize, %s", #cond);	\
+		pr_emerg("PERCPU: cpu_possible_mask=%s\n", cpus_buf);	\
+		pcpu_dump_alloc_info(KERN_EMERG, ai);			\
+		BUG();							\
+	}								\
+} while (0)
+
+	/* sanity checks */
+	PCPU_SETUP_BUG_ON(ai->nr_groups <= 0);
+#ifdef CONFIG_SMP
+	PCPU_SETUP_BUG_ON(!ai->static_size);
+#endif
+	PCPU_SETUP_BUG_ON(!base_addr);
+	PCPU_SETUP_BUG_ON(ai->unit_size < size_sum);
+	PCPU_SETUP_BUG_ON(ai->unit_size & ~PAGE_MASK);
+	PCPU_SETUP_BUG_ON(ai->unit_size < PCPU_MIN_UNIT_SIZE);
+	PCPU_SETUP_BUG_ON(ai->dyn_size < PERCPU_DYNAMIC_EARLY_SIZE);
+	PCPU_SETUP_BUG_ON(pcpu_verify_alloc_info(ai) < 0);
+
+	/* process group information and build config tables accordingly */
+	group_offsets = alloc_bootmem(ai->nr_groups * sizeof(group_offsets[0]));
+	group_sizes = alloc_bootmem(ai->nr_groups * sizeof(group_sizes[0]));
+	unit_map = alloc_bootmem(nr_cpu_ids * sizeof(unit_map[0]));
+	unit_off = alloc_bootmem(nr_cpu_ids * sizeof(unit_off[0]));
+
+	for (cpu = 0; cpu < nr_cpu_ids; cpu++)
+		unit_map[cpu] = UINT_MAX;
+	pcpu_first_unit_cpu = NR_CPUS;
+
+	for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) {
+		const struct pcpu_group_info *gi = &ai->groups[group];
+
+		group_offsets[group] = gi->base_offset;
+		group_sizes[group] = gi->nr_units * ai->unit_size;
+
+		for (i = 0; i < gi->nr_units; i++) {
+			cpu = gi->cpu_map[i];
+			if (cpu == NR_CPUS)
+				continue;
+
+			PCPU_SETUP_BUG_ON(cpu > nr_cpu_ids);
+			PCPU_SETUP_BUG_ON(!cpu_possible(cpu));
+			PCPU_SETUP_BUG_ON(unit_map[cpu] != UINT_MAX);
+
+			unit_map[cpu] = unit + i;
+			unit_off[cpu] = gi->base_offset + i * ai->unit_size;
+
+			if (pcpu_first_unit_cpu == NR_CPUS)
+				pcpu_first_unit_cpu = cpu;
+			pcpu_last_unit_cpu = cpu;
+		}
+	}
+	pcpu_nr_units = unit;
+
+	for_each_possible_cpu(cpu)
+		PCPU_SETUP_BUG_ON(unit_map[cpu] == UINT_MAX);
+
+	/* we're done parsing the input, undefine BUG macro and dump config */
+#undef PCPU_SETUP_BUG_ON
+	pcpu_dump_alloc_info(KERN_INFO, ai);
+
+	pcpu_nr_groups = ai->nr_groups;
+	pcpu_group_offsets = group_offsets;
+	pcpu_group_sizes = group_sizes;
+	pcpu_unit_map = unit_map;
+	pcpu_unit_offsets = unit_off;
+
+	/* determine basic parameters */
+	pcpu_unit_pages = ai->unit_size >> PAGE_SHIFT;
+	pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT;
+	pcpu_atom_size = ai->atom_size;
+	pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) +
+		BITS_TO_LONGS(pcpu_unit_pages) * sizeof(unsigned long);
+
+	/*
+	 * Allocate chunk slots.  The additional last slot is for
+	 * empty chunks.
+	 */
+	pcpu_nr_slots = __pcpu_size_to_slot(pcpu_unit_size) + 2;
+	pcpu_slot = alloc_bootmem(pcpu_nr_slots * sizeof(pcpu_slot[0]));
+	for (i = 0; i < pcpu_nr_slots; i++)
+		INIT_LIST_HEAD(&pcpu_slot[i]);
+
+	/*
+	 * Initialize static chunk.  If reserved_size is zero, the
+	 * static chunk covers static area + dynamic allocation area
+	 * in the first chunk.  If reserved_size is not zero, it
+	 * covers static area + reserved area (mostly used for module
+	 * static percpu allocation).
+	 */
+	schunk = alloc_bootmem(pcpu_chunk_struct_size);
+	INIT_LIST_HEAD(&schunk->list);
+	schunk->base_addr = base_addr;
+	schunk->map = smap;
+	schunk->map_alloc = ARRAY_SIZE(smap);
+	schunk->immutable = true;
+	bitmap_fill(schunk->populated, pcpu_unit_pages);
+
+	if (ai->reserved_size) {
+		schunk->free_size = ai->reserved_size;
+		pcpu_reserved_chunk = schunk;
+		pcpu_reserved_chunk_limit = ai->static_size + ai->reserved_size;
+	} else {
+		schunk->free_size = dyn_size;
+		dyn_size = 0;			/* dynamic area covered */
+	}
+	schunk->contig_hint = schunk->free_size;
+
+	schunk->map[schunk->map_used++] = -ai->static_size;
+	if (schunk->free_size)
+		schunk->map[schunk->map_used++] = schunk->free_size;
+
+	/* init dynamic chunk if necessary */
+	if (dyn_size) {
+		dchunk = alloc_bootmem(pcpu_chunk_struct_size);
+		INIT_LIST_HEAD(&dchunk->list);
+		dchunk->base_addr = base_addr;
+		dchunk->map = dmap;
+		dchunk->map_alloc = ARRAY_SIZE(dmap);
+		dchunk->immutable = true;
+		bitmap_fill(dchunk->populated, pcpu_unit_pages);
+
+		dchunk->contig_hint = dchunk->free_size = dyn_size;
+		dchunk->map[dchunk->map_used++] = -pcpu_reserved_chunk_limit;
+		dchunk->map[dchunk->map_used++] = dchunk->free_size;
+	}
+
+	/* link the first chunk in */
+	pcpu_first_chunk = dchunk ?: schunk;
+	pcpu_chunk_relocate(pcpu_first_chunk, -1);
+
+	/* we're done */
+	pcpu_base_addr = base_addr;
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+
+const char *pcpu_fc_names[PCPU_FC_NR] __initdata = {
+	[PCPU_FC_AUTO]	= "auto",
+	[PCPU_FC_EMBED]	= "embed",
+	[PCPU_FC_PAGE]	= "page",
+};
+
+enum pcpu_fc pcpu_chosen_fc __initdata = PCPU_FC_AUTO;
+
+static int __init percpu_alloc_setup(char *str)
+{
+	if (0)
+		/* nada */;
+#ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK
+	else if (!strcmp(str, "embed"))
+		pcpu_chosen_fc = PCPU_FC_EMBED;
+#endif
+#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
+	else if (!strcmp(str, "page"))
+		pcpu_chosen_fc = PCPU_FC_PAGE;
+#endif
+	else
+		pr_warning("PERCPU: unknown allocator %s specified\n", str);
+
+	return 0;
+}
+early_param("percpu_alloc", percpu_alloc_setup);
+
+/*
+ * pcpu_embed_first_chunk() is used by the generic percpu setup.
+ * Build it if needed by the arch config or the generic setup is going
+ * to be used.
+ */
+#if defined(CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK) || \
+	!defined(CONFIG_HAVE_SETUP_PER_CPU_AREA)
+#define BUILD_EMBED_FIRST_CHUNK
+#endif
+
+/* build pcpu_page_first_chunk() iff needed by the arch config */
+#if defined(CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK)
+#define BUILD_PAGE_FIRST_CHUNK
+#endif
+
+/* pcpu_build_alloc_info() is used by both embed and page first chunk */
+#if defined(BUILD_EMBED_FIRST_CHUNK) || defined(BUILD_PAGE_FIRST_CHUNK)
+/**
  * pcpu_build_alloc_info - build alloc_info considering distances between CPUs
  * @reserved_size: the size of reserved percpu area in bytes
  * @dyn_size: minimum free size for dynamic allocation in bytes
@@ -1220,303 +1545,9 @@
 
 	return ai;
 }
+#endif /* BUILD_EMBED_FIRST_CHUNK || BUILD_PAGE_FIRST_CHUNK */
 
-/**
- * pcpu_dump_alloc_info - print out information about pcpu_alloc_info
- * @lvl: loglevel
- * @ai: allocation info to dump
- *
- * Print out information about @ai using loglevel @lvl.
- */
-static void pcpu_dump_alloc_info(const char *lvl,
-				 const struct pcpu_alloc_info *ai)
-{
-	int group_width = 1, cpu_width = 1, width;
-	char empty_str[] = "--------";
-	int alloc = 0, alloc_end = 0;
-	int group, v;
-	int upa, apl;	/* units per alloc, allocs per line */
-
-	v = ai->nr_groups;
-	while (v /= 10)
-		group_width++;
-
-	v = num_possible_cpus();
-	while (v /= 10)
-		cpu_width++;
-	empty_str[min_t(int, cpu_width, sizeof(empty_str) - 1)] = '\0';
-
-	upa = ai->alloc_size / ai->unit_size;
-	width = upa * (cpu_width + 1) + group_width + 3;
-	apl = rounddown_pow_of_two(max(60 / width, 1));
-
-	printk("%spcpu-alloc: s%zu r%zu d%zu u%zu alloc=%zu*%zu",
-	       lvl, ai->static_size, ai->reserved_size, ai->dyn_size,
-	       ai->unit_size, ai->alloc_size / ai->atom_size, ai->atom_size);
-
-	for (group = 0; group < ai->nr_groups; group++) {
-		const struct pcpu_group_info *gi = &ai->groups[group];
-		int unit = 0, unit_end = 0;
-
-		BUG_ON(gi->nr_units % upa);
-		for (alloc_end += gi->nr_units / upa;
-		     alloc < alloc_end; alloc++) {
-			if (!(alloc % apl)) {
-				printk("\n");
-				printk("%spcpu-alloc: ", lvl);
-			}
-			printk("[%0*d] ", group_width, group);
-
-			for (unit_end += upa; unit < unit_end; unit++)
-				if (gi->cpu_map[unit] != NR_CPUS)
-					printk("%0*d ", cpu_width,
-					       gi->cpu_map[unit]);
-				else
-					printk("%s ", empty_str);
-		}
-	}
-	printk("\n");
-}
-
-/**
- * pcpu_setup_first_chunk - initialize the first percpu chunk
- * @ai: pcpu_alloc_info describing how to percpu area is shaped
- * @base_addr: mapped address
- *
- * Initialize the first percpu chunk which contains the kernel static
- * perpcu area.  This function is to be called from arch percpu area
- * setup path.
- *
- * @ai contains all information necessary to initialize the first
- * chunk and prime the dynamic percpu allocator.
- *
- * @ai->static_size is the size of static percpu area.
- *
- * @ai->reserved_size, if non-zero, specifies the amount of bytes to
- * reserve after the static area in the first chunk.  This reserves
- * the first chunk such that it's available only through reserved
- * percpu allocation.  This is primarily used to serve module percpu
- * static areas on architectures where the addressing model has
- * limited offset range for symbol relocations to guarantee module
- * percpu symbols fall inside the relocatable range.
- *
- * @ai->dyn_size determines the number of bytes available for dynamic
- * allocation in the first chunk.  The area between @ai->static_size +
- * @ai->reserved_size + @ai->dyn_size and @ai->unit_size is unused.
- *
- * @ai->unit_size specifies unit size and must be aligned to PAGE_SIZE
- * and equal to or larger than @ai->static_size + @ai->reserved_size +
- * @ai->dyn_size.
- *
- * @ai->atom_size is the allocation atom size and used as alignment
- * for vm areas.
- *
- * @ai->alloc_size is the allocation size and always multiple of
- * @ai->atom_size.  This is larger than @ai->atom_size if
- * @ai->unit_size is larger than @ai->atom_size.
- *
- * @ai->nr_groups and @ai->groups describe virtual memory layout of
- * percpu areas.  Units which should be colocated are put into the
- * same group.  Dynamic VM areas will be allocated according to these
- * groupings.  If @ai->nr_groups is zero, a single group containing
- * all units is assumed.
- *
- * The caller should have mapped the first chunk at @base_addr and
- * copied static data to each unit.
- *
- * If the first chunk ends up with both reserved and dynamic areas, it
- * is served by two chunks - one to serve the core static and reserved
- * areas and the other for the dynamic area.  They share the same vm
- * and page map but uses different area allocation map to stay away
- * from each other.  The latter chunk is circulated in the chunk slots
- * and available for dynamic allocation like any other chunks.
- *
- * RETURNS:
- * 0 on success, -errno on failure.
- */
-int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
-				  void *base_addr)
-{
-	static char cpus_buf[4096] __initdata;
-	static int smap[PERCPU_DYNAMIC_EARLY_SLOTS] __initdata;
-	static int dmap[PERCPU_DYNAMIC_EARLY_SLOTS] __initdata;
-	size_t dyn_size = ai->dyn_size;
-	size_t size_sum = ai->static_size + ai->reserved_size + dyn_size;
-	struct pcpu_chunk *schunk, *dchunk = NULL;
-	unsigned long *group_offsets;
-	size_t *group_sizes;
-	unsigned long *unit_off;
-	unsigned int cpu;
-	int *unit_map;
-	int group, unit, i;
-
-	cpumask_scnprintf(cpus_buf, sizeof(cpus_buf), cpu_possible_mask);
-
-#define PCPU_SETUP_BUG_ON(cond)	do {					\
-	if (unlikely(cond)) {						\
-		pr_emerg("PERCPU: failed to initialize, %s", #cond);	\
-		pr_emerg("PERCPU: cpu_possible_mask=%s\n", cpus_buf);	\
-		pcpu_dump_alloc_info(KERN_EMERG, ai);			\
-		BUG();							\
-	}								\
-} while (0)
-
-	/* sanity checks */
-	PCPU_SETUP_BUG_ON(ai->nr_groups <= 0);
-	PCPU_SETUP_BUG_ON(!ai->static_size);
-	PCPU_SETUP_BUG_ON(!base_addr);
-	PCPU_SETUP_BUG_ON(ai->unit_size < size_sum);
-	PCPU_SETUP_BUG_ON(ai->unit_size & ~PAGE_MASK);
-	PCPU_SETUP_BUG_ON(ai->unit_size < PCPU_MIN_UNIT_SIZE);
-	PCPU_SETUP_BUG_ON(ai->dyn_size < PERCPU_DYNAMIC_EARLY_SIZE);
-	PCPU_SETUP_BUG_ON(pcpu_verify_alloc_info(ai) < 0);
-
-	/* process group information and build config tables accordingly */
-	group_offsets = alloc_bootmem(ai->nr_groups * sizeof(group_offsets[0]));
-	group_sizes = alloc_bootmem(ai->nr_groups * sizeof(group_sizes[0]));
-	unit_map = alloc_bootmem(nr_cpu_ids * sizeof(unit_map[0]));
-	unit_off = alloc_bootmem(nr_cpu_ids * sizeof(unit_off[0]));
-
-	for (cpu = 0; cpu < nr_cpu_ids; cpu++)
-		unit_map[cpu] = UINT_MAX;
-	pcpu_first_unit_cpu = NR_CPUS;
-
-	for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) {
-		const struct pcpu_group_info *gi = &ai->groups[group];
-
-		group_offsets[group] = gi->base_offset;
-		group_sizes[group] = gi->nr_units * ai->unit_size;
-
-		for (i = 0; i < gi->nr_units; i++) {
-			cpu = gi->cpu_map[i];
-			if (cpu == NR_CPUS)
-				continue;
-
-			PCPU_SETUP_BUG_ON(cpu > nr_cpu_ids);
-			PCPU_SETUP_BUG_ON(!cpu_possible(cpu));
-			PCPU_SETUP_BUG_ON(unit_map[cpu] != UINT_MAX);
-
-			unit_map[cpu] = unit + i;
-			unit_off[cpu] = gi->base_offset + i * ai->unit_size;
-
-			if (pcpu_first_unit_cpu == NR_CPUS)
-				pcpu_first_unit_cpu = cpu;
-			pcpu_last_unit_cpu = cpu;
-		}
-	}
-	pcpu_nr_units = unit;
-
-	for_each_possible_cpu(cpu)
-		PCPU_SETUP_BUG_ON(unit_map[cpu] == UINT_MAX);
-
-	/* we're done parsing the input, undefine BUG macro and dump config */
-#undef PCPU_SETUP_BUG_ON
-	pcpu_dump_alloc_info(KERN_INFO, ai);
-
-	pcpu_nr_groups = ai->nr_groups;
-	pcpu_group_offsets = group_offsets;
-	pcpu_group_sizes = group_sizes;
-	pcpu_unit_map = unit_map;
-	pcpu_unit_offsets = unit_off;
-
-	/* determine basic parameters */
-	pcpu_unit_pages = ai->unit_size >> PAGE_SHIFT;
-	pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT;
-	pcpu_atom_size = ai->atom_size;
-	pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) +
-		BITS_TO_LONGS(pcpu_unit_pages) * sizeof(unsigned long);
-
-	/*
-	 * Allocate chunk slots.  The additional last slot is for
-	 * empty chunks.
-	 */
-	pcpu_nr_slots = __pcpu_size_to_slot(pcpu_unit_size) + 2;
-	pcpu_slot = alloc_bootmem(pcpu_nr_slots * sizeof(pcpu_slot[0]));
-	for (i = 0; i < pcpu_nr_slots; i++)
-		INIT_LIST_HEAD(&pcpu_slot[i]);
-
-	/*
-	 * Initialize static chunk.  If reserved_size is zero, the
-	 * static chunk covers static area + dynamic allocation area
-	 * in the first chunk.  If reserved_size is not zero, it
-	 * covers static area + reserved area (mostly used for module
-	 * static percpu allocation).
-	 */
-	schunk = alloc_bootmem(pcpu_chunk_struct_size);
-	INIT_LIST_HEAD(&schunk->list);
-	schunk->base_addr = base_addr;
-	schunk->map = smap;
-	schunk->map_alloc = ARRAY_SIZE(smap);
-	schunk->immutable = true;
-	bitmap_fill(schunk->populated, pcpu_unit_pages);
-
-	if (ai->reserved_size) {
-		schunk->free_size = ai->reserved_size;
-		pcpu_reserved_chunk = schunk;
-		pcpu_reserved_chunk_limit = ai->static_size + ai->reserved_size;
-	} else {
-		schunk->free_size = dyn_size;
-		dyn_size = 0;			/* dynamic area covered */
-	}
-	schunk->contig_hint = schunk->free_size;
-
-	schunk->map[schunk->map_used++] = -ai->static_size;
-	if (schunk->free_size)
-		schunk->map[schunk->map_used++] = schunk->free_size;
-
-	/* init dynamic chunk if necessary */
-	if (dyn_size) {
-		dchunk = alloc_bootmem(pcpu_chunk_struct_size);
-		INIT_LIST_HEAD(&dchunk->list);
-		dchunk->base_addr = base_addr;
-		dchunk->map = dmap;
-		dchunk->map_alloc = ARRAY_SIZE(dmap);
-		dchunk->immutable = true;
-		bitmap_fill(dchunk->populated, pcpu_unit_pages);
-
-		dchunk->contig_hint = dchunk->free_size = dyn_size;
-		dchunk->map[dchunk->map_used++] = -pcpu_reserved_chunk_limit;
-		dchunk->map[dchunk->map_used++] = dchunk->free_size;
-	}
-
-	/* link the first chunk in */
-	pcpu_first_chunk = dchunk ?: schunk;
-	pcpu_chunk_relocate(pcpu_first_chunk, -1);
-
-	/* we're done */
-	pcpu_base_addr = base_addr;
-	return 0;
-}
-
-const char *pcpu_fc_names[PCPU_FC_NR] __initdata = {
-	[PCPU_FC_AUTO]	= "auto",
-	[PCPU_FC_EMBED]	= "embed",
-	[PCPU_FC_PAGE]	= "page",
-};
-
-enum pcpu_fc pcpu_chosen_fc __initdata = PCPU_FC_AUTO;
-
-static int __init percpu_alloc_setup(char *str)
-{
-	if (0)
-		/* nada */;
-#ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK
-	else if (!strcmp(str, "embed"))
-		pcpu_chosen_fc = PCPU_FC_EMBED;
-#endif
-#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
-	else if (!strcmp(str, "page"))
-		pcpu_chosen_fc = PCPU_FC_PAGE;
-#endif
-	else
-		pr_warning("PERCPU: unknown allocator %s specified\n", str);
-
-	return 0;
-}
-early_param("percpu_alloc", percpu_alloc_setup);
-
-#if defined(CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK) || \
-	!defined(CONFIG_HAVE_SETUP_PER_CPU_AREA)
+#if defined(BUILD_EMBED_FIRST_CHUNK)
 /**
  * pcpu_embed_first_chunk - embed the first percpu chunk into bootmem
  * @reserved_size: the size of reserved percpu area in bytes
@@ -1645,10 +1676,9 @@
 		free_bootmem(__pa(areas), areas_size);
 	return rc;
 }
-#endif /* CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK ||
-	  !CONFIG_HAVE_SETUP_PER_CPU_AREA */
+#endif /* BUILD_EMBED_FIRST_CHUNK */
 
-#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
+#ifdef BUILD_PAGE_FIRST_CHUNK
 /**
  * pcpu_page_first_chunk - map the first chunk using PAGE_SIZE pages
  * @reserved_size: the size of reserved percpu area in bytes
@@ -1756,10 +1786,11 @@
 	pcpu_free_alloc_info(ai);
 	return rc;
 }
-#endif /* CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK */
+#endif /* BUILD_PAGE_FIRST_CHUNK */
 
+#ifndef	CONFIG_HAVE_SETUP_PER_CPU_AREA
 /*
- * Generic percpu area setup.
+ * Generic SMP percpu area setup.
  *
  * The embedding helper is used because its behavior closely resembles
  * the original non-dynamic generic percpu area setup.  This is
@@ -1770,7 +1801,6 @@
  * on the physical linear memory mapping which uses large page
  * mappings on applicable archs.
  */
-#ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
 unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
 EXPORT_SYMBOL(__per_cpu_offset);
 
@@ -1799,13 +1829,48 @@
 				    PERCPU_DYNAMIC_RESERVE, PAGE_SIZE, NULL,
 				    pcpu_dfl_fc_alloc, pcpu_dfl_fc_free);
 	if (rc < 0)
-		panic("Failed to initialized percpu areas.");
+		panic("Failed to initialize percpu areas.");
 
 	delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
 	for_each_possible_cpu(cpu)
 		__per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu];
 }
-#endif /* CONFIG_HAVE_SETUP_PER_CPU_AREA */
+#endif	/* CONFIG_HAVE_SETUP_PER_CPU_AREA */
+
+#else	/* CONFIG_SMP */
+
+/*
+ * UP percpu area setup.
+ *
+ * UP always uses km-based percpu allocator with identity mapping.
+ * Static percpu variables are indistinguishable from the usual static
+ * variables and don't require any special preparation.
+ */
+void __init setup_per_cpu_areas(void)
+{
+	const size_t unit_size =
+		roundup_pow_of_two(max_t(size_t, PCPU_MIN_UNIT_SIZE,
+					 PERCPU_DYNAMIC_RESERVE));
+	struct pcpu_alloc_info *ai;
+	void *fc;
+
+	ai = pcpu_alloc_alloc_info(1, 1);
+	fc = __alloc_bootmem(unit_size, PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
+	if (!ai || !fc)
+		panic("Failed to allocate memory for percpu areas.");
+
+	ai->dyn_size = unit_size;
+	ai->unit_size = unit_size;
+	ai->atom_size = unit_size;
+	ai->alloc_size = unit_size;
+	ai->groups[0].nr_units = 1;
+	ai->groups[0].cpu_map[0] = 0;
+
+	if (pcpu_setup_first_chunk(ai, fc) < 0)
+		panic("Failed to initialize percpu areas.");
+}
+
+#endif	/* CONFIG_SMP */
 
 /*
  * First and reserved chunks are initialized with temporary allocation
diff --git a/mm/percpu_up.c b/mm/percpu_up.c
deleted file mode 100644
index db884fa..0000000
--- a/mm/percpu_up.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * mm/percpu_up.c - dummy percpu memory allocator implementation for UP
- */
-
-#include <linux/module.h>
-#include <linux/percpu.h>
-#include <linux/slab.h>
-
-void __percpu *__alloc_percpu(size_t size, size_t align)
-{
-	/*
-	 * Can't easily make larger alignment work with kmalloc.  WARN
-	 * on it.  Larger alignment should only be used for module
-	 * percpu sections on SMP for which this path isn't used.
-	 */
-	WARN_ON_ONCE(align > SMP_CACHE_BYTES);
-	return (void __percpu __force *)kzalloc(size, GFP_KERNEL);
-}
-EXPORT_SYMBOL_GPL(__alloc_percpu);
-
-void free_percpu(void __percpu *p)
-{
-	kfree(this_cpu_ptr(p));
-}
-EXPORT_SYMBOL_GPL(free_percpu);
-
-phys_addr_t per_cpu_ptr_to_phys(void *addr)
-{
-	return __pa(addr);
-}
diff --git a/mm/rmap.c b/mm/rmap.c
index 9d2ba01..92e6757 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -381,7 +381,13 @@
 unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
 {
 	if (PageAnon(page)) {
-		if (vma->anon_vma->root != page_anon_vma(page)->root)
+		struct anon_vma *page__anon_vma = page_anon_vma(page);
+		/*
+		 * Note: swapoff's unuse_vma() is more efficient with this
+		 * check, and needs it to match anon_vma when KSM is active.
+		 */
+		if (!vma->anon_vma || !page__anon_vma ||
+		    vma->anon_vma->root != page__anon_vma->root)
 			return -EFAULT;
 	} else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
 		if (!vma->vm_file ||
diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
index aa33fd6..29d6cbf 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -220,18 +220,7 @@
 
 	if (vmemmap_buf_start) {
 		/* need to free left buf */
-#ifdef CONFIG_NO_BOOTMEM
-		free_early(__pa(vmemmap_buf_start), __pa(vmemmap_buf_end));
-		if (vmemmap_buf_start < vmemmap_buf) {
-			char name[15];
-
-			snprintf(name, sizeof(name), "MEMMAP %d", nodeid);
-			reserve_early_without_check(__pa(vmemmap_buf_start),
-						    __pa(vmemmap_buf), name);
-		}
-#else
 		free_bootmem(__pa(vmemmap_buf), vmemmap_buf_end - vmemmap_buf);
-#endif
 		vmemmap_buf = NULL;
 		vmemmap_buf_end = NULL;
 	}
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 7c703ff..9fc7bac 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -139,7 +139,7 @@
 	nr_blocks = ((sector_t)se->nr_pages - 1) << (PAGE_SHIFT - 9);
 	if (nr_blocks) {
 		err = blkdev_issue_discard(si->bdev, start_block,
-				nr_blocks, GFP_KERNEL, BLKDEV_IFL_WAIT);
+				nr_blocks, GFP_KERNEL, 0);
 		if (err)
 			return err;
 		cond_resched();
@@ -150,7 +150,7 @@
 		nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9);
 
 		err = blkdev_issue_discard(si->bdev, start_block,
-				nr_blocks, GFP_KERNEL, BLKDEV_IFL_WAIT);
+				nr_blocks, GFP_KERNEL, 0);
 		if (err)
 			break;
 
@@ -189,7 +189,7 @@
 			start_block <<= PAGE_SHIFT - 9;
 			nr_blocks <<= PAGE_SHIFT - 9;
 			if (blkdev_issue_discard(si->bdev, start_block,
-				    nr_blocks, GFP_NOIO, BLKDEV_IFL_WAIT))
+				    nr_blocks, GFP_NOIO, 0))
 				break;
 		}
 
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 6b8889d..9f90962 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -517,6 +517,15 @@
 static void purge_fragmented_blocks_allcpus(void);
 
 /*
+ * called before a call to iounmap() if the caller wants vm_area_struct's
+ * immediately freed.
+ */
+void set_iounmap_nonlazy(void)
+{
+	atomic_set(&vmap_lazy_nr, lazy_max_pages()+1);
+}
+
+/*
  * Purges all lazily-freed vmap areas.
  *
  * If sync is 0 then don't purge if there is already a purge in progress.
@@ -2056,6 +2065,7 @@
 }
 EXPORT_SYMBOL_GPL(free_vm_area);
 
+#ifdef CONFIG_SMP
 static struct vmap_area *node_to_va(struct rb_node *n)
 {
 	return n ? rb_entry(n, struct vmap_area, rb_node) : NULL;
@@ -2336,6 +2346,7 @@
 		free_vm_area(vms[i]);
 	kfree(vms);
 }
+#endif	/* CONFIG_SMP */
 
 #ifdef CONFIG_PROC_FS
 static void *s_start(struct seq_file *m, loff_t *pos)
diff --git a/net/802/fc.c b/net/802/fc.c
index 34cf1ee..1e49f2d 100644
--- a/net/802/fc.c
+++ b/net/802/fc.c
@@ -70,7 +70,7 @@
 	if(daddr)
 	{
 		memcpy(fch->daddr,daddr,dev->addr_len);
-		return(hdr_len);
+		return hdr_len;
 	}
 	return -hdr_len;
 }
diff --git a/net/802/fddi.c b/net/802/fddi.c
index 3ef0ab0..94b3ad0 100644
--- a/net/802/fddi.c
+++ b/net/802/fddi.c
@@ -82,10 +82,10 @@
 	if (daddr != NULL)
 	{
 		memcpy(fddi->daddr, daddr, dev->addr_len);
-		return(hl);
+		return hl;
 	}
 
-	return(-hl);
+	return -hl;
 }
 
 
@@ -108,7 +108,7 @@
 	{
 		printk("%s: Don't know how to resolve type %04X addresses.\n",
 		       skb->dev->name, ntohs(fddi->hdr.llc_snap.ethertype));
-		return(0);
+		return 0;
 	}
 }
 
@@ -162,7 +162,7 @@
 
 	/* Assume 802.2 SNAP frames, for now */
 
-	return(type);
+	return type;
 }
 
 EXPORT_SYMBOL(fddi_type_trans);
@@ -170,9 +170,9 @@
 int fddi_change_mtu(struct net_device *dev, int new_mtu)
 {
 	if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN))
-		return(-EINVAL);
+		return -EINVAL;
 	dev->mtu = new_mtu;
-	return(0);
+	return 0;
 }
 EXPORT_SYMBOL(fddi_change_mtu);
 
diff --git a/net/802/hippi.c b/net/802/hippi.c
index cd3e8e9..91aca87 100644
--- a/net/802/hippi.c
+++ b/net/802/hippi.c
@@ -152,7 +152,7 @@
 	if ((new_mtu < 68) || (new_mtu > 65280))
 		return -EINVAL;
 	dev->mtu = new_mtu;
-	return(0);
+	return 0;
 }
 EXPORT_SYMBOL(hippi_change_mtu);
 
diff --git a/net/802/tr.c b/net/802/tr.c
index 1c6e596..5e20cf8 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -145,7 +145,7 @@
 	{
 		memcpy(trh->daddr,daddr,dev->addr_len);
 		tr_source_route(skb, trh, dev);
-		return(hdr_len);
+		return hdr_len;
 	}
 
 	return -hdr_len;
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index a2ad152..05b867e 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -44,9 +44,6 @@
 
 int vlan_net_id __read_mostly;
 
-/* Our listing of VLAN group(s) */
-static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
-
 const char vlan_fullname[] = "802.1Q VLAN Support";
 const char vlan_version[] = DRV_VERSION;
 static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
@@ -59,40 +56,6 @@
 
 /* End of global variables definitions. */
 
-static inline unsigned int vlan_grp_hashfn(unsigned int idx)
-{
-	return ((idx >> VLAN_GRP_HASH_SHIFT) ^ idx) & VLAN_GRP_HASH_MASK;
-}
-
-/* Must be invoked with RCU read lock (no preempt) */
-static struct vlan_group *__vlan_find_group(struct net_device *real_dev)
-{
-	struct vlan_group *grp;
-	struct hlist_node *n;
-	int hash = vlan_grp_hashfn(real_dev->ifindex);
-
-	hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) {
-		if (grp->real_dev == real_dev)
-			return grp;
-	}
-
-	return NULL;
-}
-
-/*  Find the protocol handler.  Assumes VID < VLAN_VID_MASK.
- *
- * Must be invoked with RCU read lock (no preempt)
- */
-struct net_device *__find_vlan_dev(struct net_device *real_dev, u16 vlan_id)
-{
-	struct vlan_group *grp = __vlan_find_group(real_dev);
-
-	if (grp)
-		return vlan_group_get_device(grp, vlan_id);
-
-	return NULL;
-}
-
 static void vlan_group_free(struct vlan_group *grp)
 {
 	int i;
@@ -111,8 +74,6 @@
 		return NULL;
 
 	grp->real_dev = real_dev;
-	hlist_add_head_rcu(&grp->hlist,
-			&vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
 	return grp;
 }
 
@@ -151,7 +112,7 @@
 
 	ASSERT_RTNL();
 
-	grp = __vlan_find_group(real_dev);
+	grp = real_dev->vlgrp;
 	BUG_ON(!grp);
 
 	/* Take it out of our own structures, but be sure to interlock with
@@ -173,11 +134,10 @@
 	if (grp->nr_vlans == 0) {
 		vlan_gvrp_uninit_applicant(real_dev);
 
-		if (real_dev->features & NETIF_F_HW_VLAN_RX)
+		rcu_assign_pointer(real_dev->vlgrp, NULL);
+		if (ops->ndo_vlan_rx_register)
 			ops->ndo_vlan_rx_register(real_dev, NULL);
 
-		hlist_del_rcu(&grp->hlist);
-
 		/* Free the group, after all cpu's are done. */
 		call_rcu(&grp->rcu, vlan_rcu_free);
 	}
@@ -196,18 +156,13 @@
 		return -EOPNOTSUPP;
 	}
 
-	if ((real_dev->features & NETIF_F_HW_VLAN_RX) && !ops->ndo_vlan_rx_register) {
-		pr_info("8021q: device %s has buggy VLAN hw accel\n", name);
-		return -EOPNOTSUPP;
-	}
-
 	if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
 	    (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) {
 		pr_info("8021q: Device %s has buggy VLAN hw accel\n", name);
 		return -EOPNOTSUPP;
 	}
 
-	if (__find_vlan_dev(real_dev, vlan_id) != NULL)
+	if (vlan_find_dev(real_dev, vlan_id) != NULL)
 		return -EEXIST;
 
 	return 0;
@@ -222,7 +177,7 @@
 	struct vlan_group *grp, *ngrp = NULL;
 	int err;
 
-	grp = __vlan_find_group(real_dev);
+	grp = real_dev->vlgrp;
 	if (!grp) {
 		ngrp = grp = vlan_group_alloc(real_dev);
 		if (!grp)
@@ -252,8 +207,11 @@
 	vlan_group_set_device(grp, vlan_id, dev);
 	grp->nr_vlans++;
 
-	if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
-		ops->ndo_vlan_rx_register(real_dev, ngrp);
+	if (ngrp) {
+		if (ops->ndo_vlan_rx_register)
+			ops->ndo_vlan_rx_register(real_dev, ngrp);
+		rcu_assign_pointer(real_dev->vlgrp, ngrp);
+	}
 	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
 		ops->ndo_vlan_rx_add_vid(real_dev, vlan_id);
 
@@ -264,7 +222,6 @@
 		vlan_gvrp_uninit_applicant(real_dev);
 out_free_group:
 	if (ngrp) {
-		hlist_del_rcu(&ngrp->hlist);
 		/* Free the group, after all cpu's are done. */
 		call_rcu(&ngrp->rcu, vlan_rcu_free);
 	}
@@ -321,7 +278,7 @@
 	if (new_dev == NULL)
 		return -ENOBUFS;
 
-	new_dev->real_num_tx_queues = real_dev->real_num_tx_queues;
+	netif_copy_real_num_queues(new_dev, real_dev);
 	dev_net_set(new_dev, net);
 	/* need 4 bytes for extra VLAN header info,
 	 * hope the underlying device can handle it.
@@ -428,7 +385,7 @@
 		dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0);
 	}
 
-	grp = __vlan_find_group(dev);
+	grp = dev->vlgrp;
 	if (!grp)
 		goto out;
 
@@ -439,7 +396,7 @@
 	switch (event) {
 	case NETDEV_CHANGE:
 		/* Propagate real device state to vlan devices */
-		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		for (i = 0; i < VLAN_N_VID; i++) {
 			vlandev = vlan_group_get_device(grp, i);
 			if (!vlandev)
 				continue;
@@ -450,7 +407,7 @@
 
 	case NETDEV_CHANGEADDR:
 		/* Adjust unicast filters on underlying device */
-		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		for (i = 0; i < VLAN_N_VID; i++) {
 			vlandev = vlan_group_get_device(grp, i);
 			if (!vlandev)
 				continue;
@@ -464,7 +421,7 @@
 		break;
 
 	case NETDEV_CHANGEMTU:
-		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		for (i = 0; i < VLAN_N_VID; i++) {
 			vlandev = vlan_group_get_device(grp, i);
 			if (!vlandev)
 				continue;
@@ -478,7 +435,7 @@
 
 	case NETDEV_FEAT_CHANGE:
 		/* Propagate device features to underlying device */
-		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		for (i = 0; i < VLAN_N_VID; i++) {
 			vlandev = vlan_group_get_device(grp, i);
 			if (!vlandev)
 				continue;
@@ -490,7 +447,7 @@
 
 	case NETDEV_DOWN:
 		/* Put all VLANs for this dev in the down state too.  */
-		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		for (i = 0; i < VLAN_N_VID; i++) {
 			vlandev = vlan_group_get_device(grp, i);
 			if (!vlandev)
 				continue;
@@ -508,7 +465,7 @@
 
 	case NETDEV_UP:
 		/* Put all VLANs for this dev in the up state too.  */
-		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		for (i = 0; i < VLAN_N_VID; i++) {
 			vlandev = vlan_group_get_device(grp, i);
 			if (!vlandev)
 				continue;
@@ -525,10 +482,14 @@
 		break;
 
 	case NETDEV_UNREGISTER:
+		/* twiddle thumbs on netns device moves */
+		if (dev->reg_state != NETREG_UNREGISTERING)
+			break;
+
 		/* Delete all VLANs for this dev. */
 		grp->killall = 1;
 
-		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		for (i = 0; i < VLAN_N_VID; i++) {
 			vlandev = vlan_group_get_device(grp, i);
 			if (!vlandev)
 				continue;
@@ -536,7 +497,7 @@
 			/* unregistration of last vlan destroys group, abort
 			 * afterwards */
 			if (grp->nr_vlans == 1)
-				i = VLAN_GROUP_ARRAY_LEN;
+				i = VLAN_N_VID;
 
 			unregister_vlan_dev(vlandev, &list);
 		}
@@ -742,8 +703,6 @@
 
 static void __exit vlan_cleanup_module(void)
 {
-	unsigned int i;
-
 	vlan_ioctl_set(NULL);
 	vlan_netlink_fini();
 
@@ -751,10 +710,6 @@
 
 	dev_remove_pack(&vlan_packet_type);
 
-	/* This table must be empty if there are no module references left. */
-	for (i = 0; i < VLAN_GRP_HASH_SIZE; i++)
-		BUG_ON(!hlist_empty(&vlan_group_hash[i]));
-
 	unregister_pernet_subsys(&vlan_net_ops);
 	rcu_barrier(); /* Wait for completion of call_rcu()'s */
 
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 8d9503a..db01b31 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -72,23 +72,6 @@
 	return netdev_priv(dev);
 }
 
-#define VLAN_GRP_HASH_SHIFT	5
-#define VLAN_GRP_HASH_SIZE	(1 << VLAN_GRP_HASH_SHIFT)
-#define VLAN_GRP_HASH_MASK	(VLAN_GRP_HASH_SIZE - 1)
-
-/*  Find a VLAN device by the MAC address of its Ethernet device, and
- *  it's VLAN ID.  The default configuration is to have VLAN's scope
- *  to be box-wide, so the MAC will be ignored.  The mac will only be
- *  looked at if we are configured to have a separate set of VLANs per
- *  each MAC addressable interface.  Note that this latter option does
- *  NOT follow the spec for VLANs, but may be useful for doing very
- *  large quantities of VLAN MUX/DEMUX onto FrameRelay or ATM PVCs.
- *
- *  Must be invoked with rcu_read_lock (ie preempt disabled)
- *  or with RTNL.
- */
-struct net_device *__find_vlan_dev(struct net_device *real_dev, u16 vlan_id);
-
 /* found in vlan_dev.c */
 int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
 		  struct packet_type *ptype, struct net_device *orig_dev);
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 01ddb04..69b2f79 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -4,50 +4,29 @@
 #include <linux/netpoll.h>
 #include "vlan.h"
 
-/* VLAN rx hw acceleration helper.  This acts like netif_{rx,receive_skb}(). */
-int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
-		      u16 vlan_tci, int polling)
+bool vlan_hwaccel_do_receive(struct sk_buff **skbp)
 {
+	struct sk_buff *skb = *skbp;
+	u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK;
 	struct net_device *vlan_dev;
-	u16 vlan_id;
+	struct vlan_rx_stats *rx_stats;
 
-	if (netpoll_rx(skb))
-		return NET_RX_DROP;
+	vlan_dev = vlan_find_dev(skb->dev, vlan_id);
+	if (!vlan_dev) {
+		if (vlan_id)
+			skb->pkt_type = PACKET_OTHERHOST;
+		return false;
+	}
 
-	if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
-		skb->deliver_no_wcard = 1;
+	skb = *skbp = skb_share_check(skb, GFP_ATOMIC);
+	if (unlikely(!skb))
+		return false;
 
-	skb->skb_iif = skb->dev->ifindex;
-	__vlan_hwaccel_put_tag(skb, vlan_tci);
-	vlan_id = vlan_tci & VLAN_VID_MASK;
-	vlan_dev = vlan_group_get_device(grp, vlan_id);
-
-	if (vlan_dev)
-		skb->dev = vlan_dev;
-	else if (vlan_id)
-		goto drop;
-
-	return (polling ? netif_receive_skb(skb) : netif_rx(skb));
-
-drop:
-	dev_kfree_skb_any(skb);
-	return NET_RX_DROP;
-}
-EXPORT_SYMBOL(__vlan_hwaccel_rx);
-
-int vlan_hwaccel_do_receive(struct sk_buff *skb)
-{
-	struct net_device *dev = skb->dev;
-	struct vlan_rx_stats     *rx_stats;
-
-	skb->dev = vlan_dev_info(dev)->real_dev;
-	netif_nit_deliver(skb);
-
-	skb->dev = dev;
-	skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
+	skb->dev = vlan_dev;
+	skb->priority = vlan_get_ingress_priority(vlan_dev, skb->vlan_tci);
 	skb->vlan_tci = 0;
 
-	rx_stats = this_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats);
+	rx_stats = this_cpu_ptr(vlan_dev_info(vlan_dev)->vlan_rx_stats);
 
 	u64_stats_update_begin(&rx_stats->syncp);
 	rx_stats->rx_packets++;
@@ -64,12 +43,13 @@
 		 * This allows the VLAN to have a different MAC than the
 		 * underlying device, and still route correctly. */
 		if (!compare_ether_addr(eth_hdr(skb)->h_dest,
-					dev->dev_addr))
+					vlan_dev->dev_addr))
 			skb->pkt_type = PACKET_HOST;
 		break;
 	}
 	u64_stats_update_end(&rx_stats->syncp);
-	return 0;
+
+	return true;
 }
 
 struct net_device *vlan_dev_real_dev(const struct net_device *dev)
@@ -84,68 +64,27 @@
 }
 EXPORT_SYMBOL(vlan_dev_vlan_id);
 
-static gro_result_t
-vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
-		unsigned int vlan_tci, struct sk_buff *skb)
+/* VLAN rx hw acceleration helper.  This acts like netif_{rx,receive_skb}(). */
+int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
+		      u16 vlan_tci, int polling)
 {
-	struct sk_buff *p;
-	struct net_device *vlan_dev;
-	u16 vlan_id;
-
-	if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
-		skb->deliver_no_wcard = 1;
-
-	skb->skb_iif = skb->dev->ifindex;
 	__vlan_hwaccel_put_tag(skb, vlan_tci);
-	vlan_id = vlan_tci & VLAN_VID_MASK;
-	vlan_dev = vlan_group_get_device(grp, vlan_id);
-
-	if (vlan_dev)
-		skb->dev = vlan_dev;
-	else if (vlan_id)
-		goto drop;
-
-	for (p = napi->gro_list; p; p = p->next) {
-		NAPI_GRO_CB(p)->same_flow =
-			p->dev == skb->dev && !compare_ether_header(
-				skb_mac_header(p), skb_gro_mac_header(skb));
-		NAPI_GRO_CB(p)->flush = 0;
-	}
-
-	return dev_gro_receive(napi, skb);
-
-drop:
-	return GRO_DROP;
+	return polling ? netif_receive_skb(skb) : netif_rx(skb);
 }
+EXPORT_SYMBOL(__vlan_hwaccel_rx);
 
 gro_result_t vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
 			      unsigned int vlan_tci, struct sk_buff *skb)
 {
-	if (netpoll_rx_on(skb))
-		return vlan_hwaccel_receive_skb(skb, grp, vlan_tci)
-			? GRO_DROP : GRO_NORMAL;
-
-	skb_gro_reset_offset(skb);
-
-	return napi_skb_finish(vlan_gro_common(napi, grp, vlan_tci, skb), skb);
+	__vlan_hwaccel_put_tag(skb, vlan_tci);
+	return napi_gro_receive(napi, skb);
 }
 EXPORT_SYMBOL(vlan_gro_receive);
 
 gro_result_t vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
 			    unsigned int vlan_tci)
 {
-	struct sk_buff *skb = napi_frags_skb(napi);
-
-	if (!skb)
-		return GRO_DROP;
-
-	if (netpoll_rx_on(skb)) {
-		skb->protocol = eth_type_trans(skb, skb->dev);
-		return vlan_hwaccel_receive_skb(skb, grp, vlan_tci)
-			? GRO_DROP : GRO_NORMAL;
-	}
-
-	return napi_frags_finish(napi, skb,
-				 vlan_gro_common(napi, grp, vlan_tci, skb));
+	__vlan_hwaccel_put_tag(napi->skb, vlan_tci);
+	return napi_gro_frags(napi);
 }
 EXPORT_SYMBOL(vlan_gro_frags);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 3bccdd1..14e3d1f 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -158,7 +158,7 @@
 	vlan_id = vlan_tci & VLAN_VID_MASK;
 
 	rcu_read_lock();
-	vlan_dev = __find_vlan_dev(dev, vlan_id);
+	vlan_dev = vlan_find_dev(dev, vlan_id);
 
 	/* If the VLAN device is defined, we use it.
 	 * If not, and the VID is 0, it is a 802.1p packet (not
@@ -177,8 +177,8 @@
 	} else {
 		skb->dev = vlan_dev;
 
-		rx_stats = per_cpu_ptr(vlan_dev_info(skb->dev)->vlan_rx_stats,
-					smp_processor_id());
+		rx_stats = this_cpu_ptr(vlan_dev_info(skb->dev)->vlan_rx_stats);
+
 		u64_stats_update_begin(&rx_stats->syncp);
 		rx_stats->rx_packets++;
 		rx_stats->rx_bytes += skb->len;
@@ -226,12 +226,14 @@
 	}
 
 	netif_rx(skb);
+
 	rcu_read_unlock();
 	return NET_RX_SUCCESS;
 
 err_unlock:
 	rcu_read_unlock();
 err_free:
+	atomic_long_inc(&dev->rx_dropped);
 	kfree_skb(skb);
 	return NET_RX_DROP;
 }
@@ -843,7 +845,7 @@
 			accum.rx_packets += rxpackets;
 			accum.rx_bytes   += rxbytes;
 			accum.rx_multicast += rxmulticast;
-			/* rx_errors is an ulong, not protected by syncp */
+			/* rx_errors is ulong, not protected by syncp */
 			accum.rx_errors  += p->rx_errors;
 		}
 		stats->rx_packets = accum.rx_packets;
diff --git a/net/9p/client.c b/net/9p/client.c
index 9eb7250..83bf0541 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -61,13 +61,13 @@
 
 inline int p9_is_proto_dotl(struct p9_client *clnt)
 {
-	return (clnt->proto_version == p9_proto_2000L);
+	return clnt->proto_version == p9_proto_2000L;
 }
 EXPORT_SYMBOL(p9_is_proto_dotl);
 
 inline int p9_is_proto_dotu(struct p9_client *clnt)
 {
-	return (clnt->proto_version == p9_proto_2000u);
+	return clnt->proto_version == p9_proto_2000u;
 }
 EXPORT_SYMBOL(p9_is_proto_dotu);
 
@@ -671,7 +671,7 @@
 	kfree(fid);
 }
 
-int p9_client_version(struct p9_client *c)
+static int p9_client_version(struct p9_client *c)
 {
 	int err = 0;
 	struct p9_req_t *req;
@@ -730,7 +730,6 @@
 
 	return err;
 }
-EXPORT_SYMBOL(p9_client_version);
 
 struct p9_client *p9_client_create(const char *dev_name, char *options)
 {
@@ -887,54 +886,6 @@
 }
 EXPORT_SYMBOL(p9_client_attach);
 
-struct p9_fid *
-p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname)
-{
-	int err;
-	struct p9_req_t *req;
-	struct p9_qid qid;
-	struct p9_fid *afid;
-
-	P9_DPRINTK(P9_DEBUG_9P, ">>> TAUTH uname %s aname %s\n", uname, aname);
-	err = 0;
-
-	afid = p9_fid_create(clnt);
-	if (IS_ERR(afid)) {
-		err = PTR_ERR(afid);
-		afid = NULL;
-		goto error;
-	}
-
-	req = p9_client_rpc(clnt, P9_TAUTH, "dss?d",
-			afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
-	if (IS_ERR(req)) {
-		err = PTR_ERR(req);
-		goto error;
-	}
-
-	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
-	if (err) {
-		p9pdu_dump(1, req->rc);
-		p9_free_req(clnt, req);
-		goto error;
-	}
-
-	P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n",
-					qid.type,
-					(unsigned long long)qid.path,
-					qid.version);
-
-	memmove(&afid->qid, &qid, sizeof(struct p9_qid));
-	p9_free_req(clnt, req);
-	return afid;
-
-error:
-	if (afid)
-		p9_fid_destroy(afid);
-	return ERR_PTR(err);
-}
-EXPORT_SYMBOL(p9_client_auth);
-
 struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
 	int clone)
 {
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index c85109d..078eb16 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -222,7 +222,7 @@
 	}
 }
 
-static unsigned int
+static int
 p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt)
 {
 	int ret, n;
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
index 0ea20c3..17c5ba7 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -426,8 +426,10 @@
 
 	/* Allocate an fcall for the reply */
 	rpl_context = kmalloc(sizeof *rpl_context, GFP_KERNEL);
-	if (!rpl_context)
+	if (!rpl_context) {
+		err = -ENOMEM;
 		goto err_close;
+	}
 
 	/*
 	 * If the request has a buffer, steal it, otherwise
@@ -445,8 +447,8 @@
 	}
 	rpl_context->rc = req->rc;
 	if (!rpl_context->rc) {
-		kfree(rpl_context);
-		goto err_close;
+		err = -ENOMEM;
+		goto err_free2;
 	}
 
 	/*
@@ -458,11 +460,8 @@
 	 */
 	if (atomic_inc_return(&rdma->rq_count) <= rdma->rq_depth) {
 		err = post_recv(client, rpl_context);
-		if (err) {
-			kfree(rpl_context->rc);
-			kfree(rpl_context);
-			goto err_close;
-		}
+		if (err)
+			goto err_free1;
 	} else
 		atomic_dec(&rdma->rq_count);
 
@@ -471,8 +470,10 @@
 
 	/* Post the request */
 	c = kmalloc(sizeof *c, GFP_KERNEL);
-	if (!c)
-		goto err_close;
+	if (!c) {
+		err = -ENOMEM;
+		goto err_free1;
+	}
 	c->req = req;
 
 	c->busa = ib_dma_map_single(rdma->cm_id->device,
@@ -499,9 +500,15 @@
 	return ib_post_send(rdma->qp, &wr, &bad_wr);
 
  error:
+	kfree(c);
+	kfree(rpl_context->rc);
+	kfree(rpl_context);
 	P9_DPRINTK(P9_DEBUG_ERROR, "EIO\n");
 	return -EIO;
-
+ err_free1:
+	kfree(rpl_context->rc);
+ err_free2:
+	kfree(rpl_context);
  err_close:
 	spin_lock_irqsave(&rdma->req_lock, flags);
 	if (rdma->state < P9_RDMA_CLOSING) {
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index dcfbe99..b885159 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -329,7 +329,8 @@
 
 	mutex_lock(&virtio_9p_lock);
 	list_for_each_entry(chan, &virtio_chan_list, chan_list) {
-		if (!strncmp(devname, chan->tag, chan->tag_len)) {
+		if (!strncmp(devname, chan->tag, chan->tag_len) &&
+		    strlen(devname) == chan->tag_len) {
 			if (!chan->inuse) {
 				chan->inuse = true;
 				found = 1;
diff --git a/net/Kconfig b/net/Kconfig
index e926884..55fd82e 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -293,6 +293,7 @@
 source "net/rfkill/Kconfig"
 source "net/9p/Kconfig"
 source "net/caif/Kconfig"
+source "net/ceph/Kconfig"
 
 
 endif   # if NET
diff --git a/net/Makefile b/net/Makefile
index ea60fbc..6b7bfd7 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -68,3 +68,4 @@
 endif
 obj-$(CONFIG_WIMAX)		+= wimax/
 obj-$(CONFIG_DNS_RESOLVER)	+= dns_resolver/
+obj-$(CONFIG_CEPH_LIB)		+= ceph/
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 651babd..ad2b232 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -399,12 +399,6 @@
 			unregister_netdev(net_dev);
 			free_netdev(net_dev);
 		}
-		read_lock_irq(&devs_lock);
-		if (list_empty(&br2684_devs)) {
-			/* last br2684 device */
-			unregister_atmdevice_notifier(&atm_dev_notifier);
-		}
-		read_unlock_irq(&devs_lock);
 		return;
 	}
 
@@ -675,7 +669,6 @@
 
 	if (list_empty(&br2684_devs)) {
 		/* 1st br2684 device */
-		register_atmdevice_notifier(&atm_dev_notifier);
 		brdev->number = 1;
 	} else
 		brdev->number = BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;
@@ -815,6 +808,7 @@
 		return -ENOMEM;
 #endif
 	register_atm_ioctl(&br2684_ioctl_ops);
+	register_atmdevice_notifier(&atm_dev_notifier);
 	return 0;
 }
 
@@ -830,9 +824,7 @@
 #endif
 
 
-	/* if not already empty */
-	if (!list_empty(&br2684_devs))
-		unregister_atmdevice_notifier(&atm_dev_notifier);
+	unregister_atmdevice_notifier(&atm_dev_notifier);
 
 	while (!list_empty(&br2684_devs)) {
 		net_dev = list_entry_brdev(br2684_devs.next);
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 95fdd11..ff956d1 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -310,9 +310,9 @@
 	return 0;
 }
 
-static u32 clip_hash(const void *pkey, const struct net_device *dev)
+static u32 clip_hash(const void *pkey, const struct net_device *dev, __u32 rnd)
 {
-	return jhash_2words(*(u32 *) pkey, dev->ifindex, clip_tbl.hash_rnd);
+	return jhash_2words(*(u32 *) pkey, dev->ifindex, rnd);
 }
 
 static struct neigh_table clip_tbl = {
diff --git a/net/atm/common.c b/net/atm/common.c
index 940404a..1b9c52a 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -792,7 +792,7 @@
 	default:
 		if (level == SOL_SOCKET)
 			return -EINVAL;
-			break;
+		break;
 	}
 	if (!vcc->dev || !vcc->dev->ops->getsockopt)
 		return -EINVAL;
diff --git a/net/atm/lec.c b/net/atm/lec.c
index d98bde1..181d70c 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -220,7 +220,6 @@
 static int lec_open(struct net_device *dev)
 {
 	netif_start_queue(dev);
-	memset(&dev->stats, 0, sizeof(struct net_device_stats));
 
 	return 0;
 }
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 622b471..74bcc66 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -778,7 +778,7 @@
 	eg->packets_rcvd++;
 	mpc->eg_ops->put(eg);
 
-	memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
+	memset(ATM_SKB(new_skb), 0, sizeof(struct atm_skb_data));
 	netif_rx(new_skb);
 }
 
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 6262aea..f85da077 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -38,6 +38,7 @@
 static const struct file_operations proc_atm_dev_ops = {
 	.owner =	THIS_MODULE,
 	.read =		proc_dev_atm_read,
+	.llseek =	noop_llseek,
 };
 
 static void add_stats(struct seq_file *seq, const char *aal,
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index cfdfd7e..26eaebf 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1103,7 +1103,7 @@
 out:
 	release_sock(sk);
 
-	return 0;
+	return err;
 }
 
 /*
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index 7805945..a169084 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -412,7 +412,7 @@
 {
 	ax25_uid_assoc *user;
 	ax25_route *ax25_rt;
-	int err;
+	int err = 0;
 
 	if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL)
 		return -EHOSTUNREACH;
@@ -453,7 +453,7 @@
 put:
 	ax25_put_route(ax25_rt);
 
-	return 0;
+	return err;
 }
 
 struct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src,
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 421c45b..c4cf3f5 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -265,6 +265,115 @@
 }
 EXPORT_SYMBOL(bt_sock_recvmsg);
 
+static long bt_sock_data_wait(struct sock *sk, long timeo)
+{
+	DECLARE_WAITQUEUE(wait, current);
+
+	add_wait_queue(sk_sleep(sk), &wait);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (!skb_queue_empty(&sk->sk_receive_queue))
+			break;
+
+		if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN))
+			break;
+
+		if (signal_pending(current) || !timeo)
+			break;
+
+		set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+		release_sock(sk);
+		timeo = schedule_timeout(timeo);
+		lock_sock(sk);
+		clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+	}
+
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(sk_sleep(sk), &wait);
+	return timeo;
+}
+
+int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
+			       struct msghdr *msg, size_t size, int flags)
+{
+	struct sock *sk = sock->sk;
+	int err = 0;
+	size_t target, copied = 0;
+	long timeo;
+
+	if (flags & MSG_OOB)
+		return -EOPNOTSUPP;
+
+	msg->msg_namelen = 0;
+
+	BT_DBG("sk %p size %zu", sk, size);
+
+	lock_sock(sk);
+
+	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
+	timeo  = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
+
+	do {
+		struct sk_buff *skb;
+		int chunk;
+
+		skb = skb_dequeue(&sk->sk_receive_queue);
+		if (!skb) {
+			if (copied >= target)
+				break;
+
+			if ((err = sock_error(sk)) != 0)
+				break;
+			if (sk->sk_shutdown & RCV_SHUTDOWN)
+				break;
+
+			err = -EAGAIN;
+			if (!timeo)
+				break;
+
+			timeo = bt_sock_data_wait(sk, timeo);
+
+			if (signal_pending(current)) {
+				err = sock_intr_errno(timeo);
+				goto out;
+			}
+			continue;
+		}
+
+		chunk = min_t(unsigned int, skb->len, size);
+		if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
+			skb_queue_head(&sk->sk_receive_queue, skb);
+			if (!copied)
+				copied = -EFAULT;
+			break;
+		}
+		copied += chunk;
+		size   -= chunk;
+
+		sock_recv_ts_and_drops(msg, sk, skb);
+
+		if (!(flags & MSG_PEEK)) {
+			skb_pull(skb, chunk);
+			if (skb->len) {
+				skb_queue_head(&sk->sk_receive_queue, skb);
+				break;
+			}
+			kfree_skb(skb);
+
+		} else {
+			/* put message back and return */
+			skb_queue_head(&sk->sk_receive_queue, skb);
+			break;
+		}
+	} while (size);
+
+out:
+	release_sock(sk);
+	return copied ? : err;
+}
+EXPORT_SYMBOL(bt_sock_stream_recvmsg);
+
 static inline unsigned int bt_accept_poll(struct sock *parent)
 {
 	struct list_head *p, *n;
@@ -297,13 +406,12 @@
 		mask |= POLLERR;
 
 	if (sk->sk_shutdown & RCV_SHUTDOWN)
-		mask |= POLLRDHUP;
+		mask |= POLLRDHUP | POLLIN | POLLRDNORM;
 
 	if (sk->sk_shutdown == SHUTDOWN_MASK)
 		mask |= POLLHUP;
 
-	if (!skb_queue_empty(&sk->sk_receive_queue) ||
-			(sk->sk_shutdown & RCV_SHUTDOWN))
+	if (!skb_queue_empty(&sk->sk_receive_queue))
 		mask |= POLLIN | POLLRDNORM;
 
 	if (sk->sk_state == BT_CLOSED)
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index d4c6af0..ec0a134 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -321,14 +321,10 @@
 int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
 {
 	struct cmtp_session *session, *s;
-	bdaddr_t src, dst;
 	int i, err;
 
 	BT_DBG("");
 
-	baswap(&src, &bt_sk(sock->sk)->src);
-	baswap(&dst, &bt_sk(sock->sk)->dst);
-
 	session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL);
 	if (!session)
 		return -ENOMEM;
@@ -347,7 +343,7 @@
 
 	BT_DBG("mtu %d", session->mtu);
 
-	sprintf(session->name, "%s", batostr(&dst));
+	sprintf(session->name, "%s", batostr(&bt_sk(sock->sk)->dst));
 
 	session->sock  = sock;
 	session->state = BT_CONFIG;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c52f091..bc2a052 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -562,7 +562,6 @@
 	hci_dev_lock_bh(hdev);
 	inquiry_cache_flush(hdev);
 	hci_conn_hash_flush(hdev);
-	hci_blacklist_clear(hdev);
 	hci_dev_unlock_bh(hdev);
 
 	hci_notify(hdev, HCI_DEV_DOWN);
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 8fb967b..5fce3d6 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -37,9 +37,7 @@
 static ssize_t show_link_address(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct hci_conn *conn = dev_get_drvdata(dev);
-	bdaddr_t bdaddr;
-	baswap(&bdaddr, &conn->dst);
-	return sprintf(buf, "%s\n", batostr(&bdaddr));
+	return sprintf(buf, "%s\n", batostr(&conn->dst));
 }
 
 static ssize_t show_link_features(struct device *dev, struct device_attribute *attr, char *buf)
@@ -196,8 +194,8 @@
 	switch (type) {
 	case HCI_BREDR:
 		return "BR/EDR";
-	case HCI_80211:
-		return "802.11";
+	case HCI_AMP:
+		return "AMP";
 	default:
 		return "UNKNOWN";
 	}
@@ -238,9 +236,7 @@
 static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct hci_dev *hdev = dev_get_drvdata(dev);
-	bdaddr_t bdaddr;
-	baswap(&bdaddr, &hdev->bdaddr);
-	return sprintf(buf, "%s\n", batostr(&bdaddr));
+	return sprintf(buf, "%s\n", batostr(&hdev->bdaddr));
 }
 
 static ssize_t show_features(struct device *dev, struct device_attribute *attr, char *buf)
@@ -408,10 +404,8 @@
 
 	for (e = cache->list; e; e = e->next) {
 		struct inquiry_data *data = &e->data;
-		bdaddr_t bdaddr;
-		baswap(&bdaddr, &data->bdaddr);
 		seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
-			   batostr(&bdaddr),
+			   batostr(&data->bdaddr),
 			   data->pscan_rep_mode, data->pscan_period_mode,
 			   data->pscan_mode, data->dev_class[2],
 			   data->dev_class[1], data->dev_class[0],
@@ -445,13 +439,10 @@
 
 	list_for_each(l, &hdev->blacklist) {
 		struct bdaddr_list *b;
-		bdaddr_t bdaddr;
 
 		b = list_entry(l, struct bdaddr_list, list);
 
-		baswap(&bdaddr, &b->bdaddr);
-
-		seq_printf(f, "%s\n", batostr(&bdaddr));
+		seq_printf(f, "%s\n", batostr(&b->bdaddr));
 	}
 
 	hci_dev_unlock_bh(hdev);
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index bfe641b..c0ee8b3 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -758,7 +758,6 @@
 				struct hidp_connadd_req *req)
 {
 	struct hid_device *hid;
-	bdaddr_t src, dst;
 	int err;
 
 	session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
@@ -781,9 +780,6 @@
 
 	hid->driver_data = session;
 
-	baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
-	baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
-
 	hid->bus     = BUS_BLUETOOTH;
 	hid->vendor  = req->vendor;
 	hid->product = req->product;
@@ -791,8 +787,8 @@
 	hid->country = req->country;
 
 	strncpy(hid->name, req->name, 128);
-	strncpy(hid->phys, batostr(&src), 64);
-	strncpy(hid->uniq, batostr(&dst), 64);
+	strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64);
+	strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64);
 
 	hid->dev.parent = hidp_get_device(session);
 	hid->ll_driver = &hidp_hid_driver;
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index fadf26b..daa7a98 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1008,10 +1008,20 @@
 		goto done;
 	}
 
-	if (la.l2_psm && __le16_to_cpu(la.l2_psm) < 0x1001 &&
-				!capable(CAP_NET_BIND_SERVICE)) {
-		err = -EACCES;
-		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);
@@ -1190,6 +1200,13 @@
 		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;
@@ -1441,33 +1458,23 @@
 
 static void l2cap_streaming_send(struct sock *sk)
 {
-	struct sk_buff *skb, *tx_skb;
+	struct sk_buff *skb;
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	u16 control, fcs;
 
-	while ((skb = sk->sk_send_head)) {
-		tx_skb = skb_clone(skb, GFP_ATOMIC);
-
-		control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+	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, tx_skb->data + L2CAP_HDR_SIZE);
+		put_unaligned_le16(control, 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);
+			fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
+			put_unaligned_le16(fcs, skb->data + skb->len - 2);
 		}
 
-		l2cap_do_send(sk, tx_skb);
+		l2cap_do_send(sk, skb);
 
 		pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
-
-		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);
-
-		skb = skb_dequeue(TX_QUEUE(sk));
-		kfree_skb(skb);
 	}
 }
 
@@ -1645,7 +1652,7 @@
 
 		*frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
 		if (!*frag)
-			return -EFAULT;
+			return err;
 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
 			return -EFAULT;
 
@@ -1671,7 +1678,7 @@
 	skb = bt_skb_send_alloc(sk, count + hlen,
 			msg->msg_flags & MSG_DONTWAIT, &err);
 	if (!skb)
-		return ERR_PTR(-ENOMEM);
+		return ERR_PTR(err);
 
 	/* Create L2CAP header */
 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
@@ -1700,7 +1707,7 @@
 	skb = bt_skb_send_alloc(sk, count + hlen,
 			msg->msg_flags & MSG_DONTWAIT, &err);
 	if (!skb)
-		return ERR_PTR(-ENOMEM);
+		return ERR_PTR(err);
 
 	/* Create L2CAP header */
 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
@@ -1737,7 +1744,7 @@
 	skb = bt_skb_send_alloc(sk, count + hlen,
 			msg->msg_flags & MSG_DONTWAIT, &err);
 	if (!skb)
-		return ERR_PTR(-ENOMEM);
+		return ERR_PTR(err);
 
 	/* Create L2CAP header */
 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
@@ -1944,6 +1951,9 @@
 
 	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);
 }
 
@@ -1960,6 +1970,11 @@
 
 	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;
@@ -2771,10 +2786,10 @@
 		case L2CAP_CONF_MTU:
 			if (val < L2CAP_DEFAULT_MIN_MTU) {
 				*result = L2CAP_CONF_UNACCEPT;
-				pi->omtu = L2CAP_DEFAULT_MIN_MTU;
+				pi->imtu = L2CAP_DEFAULT_MIN_MTU;
 			} else
-				pi->omtu = val;
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+				pi->imtu = val;
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
 			break;
 
 		case L2CAP_CONF_FLUSH_TO:
@@ -2896,7 +2911,7 @@
 	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, *uninitialized_var(sk);
+	struct sock *parent, *sk = NULL;
 	int result, status = L2CAP_CS_NO_INFO;
 
 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
@@ -3005,7 +3020,7 @@
 					L2CAP_INFO_REQ, sizeof(info), &info);
 	}
 
-	if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
+	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;
@@ -3071,6 +3086,17 @@
 	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;
@@ -3088,14 +3114,8 @@
 	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);
+	if (sk->sk_state == BT_DISCONN)
 		goto unlock;
-	}
 
 	/* Reject if config buffer is too small. */
 	len = cmd_len - sizeof(*req);
@@ -3135,9 +3155,7 @@
 		goto unlock;
 
 	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
-		if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
-		    l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
-			l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
+		set_default_fcs(l2cap_pi(sk));
 
 		sk->sk_state = BT_CONNECTED;
 
@@ -3153,6 +3171,7 @@
 
 	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++;
@@ -3225,9 +3244,7 @@
 	l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
 
 	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
-		if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) ||
-		    l2cap_pi(sk)->fcs != L2CAP_FCS_NONE)
-			l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
+		set_default_fcs(l2cap_pi(sk));
 
 		sk->sk_state = BT_CONNECTED;
 		l2cap_pi(sk)->next_tx_seq = 0;
@@ -4647,6 +4664,8 @@
 
 	if (flags & ACL_START) {
 		struct l2cap_hdr *hdr;
+		struct sock *sk;
+		u16 cid;
 		int len;
 
 		if (conn->rx_len) {
@@ -4657,7 +4676,8 @@
 			l2cap_conn_unreliable(conn, ECOMM);
 		}
 
-		if (skb->len < 2) {
+		/* 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;
@@ -4665,6 +4685,7 @@
 
 		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 */
@@ -4681,6 +4702,19 @@
 			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)
diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c
index ad2af58..b826d1b 100644
--- a/net/bluetooth/lib.c
+++ b/net/bluetooth/lib.c
@@ -51,8 +51,8 @@
 
 	i ^= 1;
 	sprintf(str[i], "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
-		ba->b[0], ba->b[1], ba->b[2],
-		ba->b[3], ba->b[4], ba->b[5]);
+		ba->b[5], ba->b[4], ba->b[3],
+		ba->b[2], ba->b[1], ba->b[0]);
 
 	return str[i];
 }
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 7dca91b..39a5d87 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -113,11 +113,10 @@
 #define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1)
 #define __get_rpn_parity(line)    (((line) >> 3) & 0x7)
 
-static inline void rfcomm_schedule(uint event)
+static inline void rfcomm_schedule(void)
 {
 	if (!rfcomm_thread)
 		return;
-	//set_bit(event, &rfcomm_event);
 	set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
 	wake_up_process(rfcomm_thread);
 }
@@ -179,13 +178,13 @@
 /* FCS on 2 bytes */
 static inline u8 __fcs(u8 *data)
 {
-	return (0xff - __crc(data));
+	return 0xff - __crc(data);
 }
 
 /* FCS on 3 bytes */
 static inline u8 __fcs2(u8 *data)
 {
-	return (0xff - rfcomm_crc_table[__crc(data) ^ data[2]]);
+	return 0xff - rfcomm_crc_table[__crc(data) ^ data[2]];
 }
 
 /* Check FCS */
@@ -203,13 +202,13 @@
 static void rfcomm_l2state_change(struct sock *sk)
 {
 	BT_DBG("%p state %d", sk, sk->sk_state);
-	rfcomm_schedule(RFCOMM_SCHED_STATE);
+	rfcomm_schedule();
 }
 
 static void rfcomm_l2data_ready(struct sock *sk, int bytes)
 {
 	BT_DBG("%p bytes %d", sk, bytes);
-	rfcomm_schedule(RFCOMM_SCHED_RX);
+	rfcomm_schedule();
 }
 
 static int rfcomm_l2sock_create(struct socket **sock)
@@ -255,7 +254,7 @@
 	BT_DBG("session %p state %ld", s, s->state);
 
 	set_bit(RFCOMM_TIMED_OUT, &s->flags);
-	rfcomm_schedule(RFCOMM_SCHED_TIMEO);
+	rfcomm_schedule();
 }
 
 static void rfcomm_session_set_timer(struct rfcomm_session *s, long timeout)
@@ -283,7 +282,7 @@
 
 	set_bit(RFCOMM_TIMED_OUT, &d->flags);
 	rfcomm_dlc_put(d);
-	rfcomm_schedule(RFCOMM_SCHED_TIMEO);
+	rfcomm_schedule();
 }
 
 static void rfcomm_dlc_set_timer(struct rfcomm_dlc *d, long timeout)
@@ -465,7 +464,7 @@
 	case BT_CONFIG:
 		if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
 			set_bit(RFCOMM_AUTH_REJECT, &d->flags);
-			rfcomm_schedule(RFCOMM_SCHED_AUTH);
+			rfcomm_schedule();
 			break;
 		}
 		/* Fall through */
@@ -485,7 +484,7 @@
 	case BT_CONNECT2:
 		if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
 			set_bit(RFCOMM_AUTH_REJECT, &d->flags);
-			rfcomm_schedule(RFCOMM_SCHED_AUTH);
+			rfcomm_schedule();
 			break;
 		}
 		/* Fall through */
@@ -533,7 +532,7 @@
 	skb_queue_tail(&d->tx_queue, skb);
 
 	if (!test_bit(RFCOMM_TX_THROTTLED, &d->flags))
-		rfcomm_schedule(RFCOMM_SCHED_TX);
+		rfcomm_schedule();
 	return len;
 }
 
@@ -545,7 +544,7 @@
 		d->v24_sig |= RFCOMM_V24_FC;
 		set_bit(RFCOMM_MSC_PENDING, &d->flags);
 	}
-	rfcomm_schedule(RFCOMM_SCHED_TX);
+	rfcomm_schedule();
 }
 
 void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
@@ -556,7 +555,7 @@
 		d->v24_sig &= ~RFCOMM_V24_FC;
 		set_bit(RFCOMM_MSC_PENDING, &d->flags);
 	}
-	rfcomm_schedule(RFCOMM_SCHED_TX);
+	rfcomm_schedule();
 }
 
 /*
@@ -577,7 +576,7 @@
 	d->v24_sig = v24_sig;
 
 	if (!test_and_set_bit(RFCOMM_MSC_PENDING, &d->flags))
-		rfcomm_schedule(RFCOMM_SCHED_TX);
+		rfcomm_schedule();
 
 	return 0;
 }
@@ -816,7 +815,7 @@
 	cmd->fcs  = __fcs2((u8 *) cmd);
 
 	skb_queue_tail(&d->tx_queue, skb);
-	rfcomm_schedule(RFCOMM_SCHED_TX);
+	rfcomm_schedule();
 	return 0;
 }
 
@@ -1415,8 +1414,8 @@
 		return 0;
 
 	if (len == 1) {
-		/* This is a request, return default settings */
-		bit_rate  = RFCOMM_RPN_BR_115200;
+		/* This is a request, return default (according to ETSI TS 07.10) settings */
+		bit_rate  = RFCOMM_RPN_BR_9600;
 		data_bits = RFCOMM_RPN_DATA_8;
 		stop_bits = RFCOMM_RPN_STOP_1;
 		parity    = RFCOMM_RPN_PARITY_NONE;
@@ -1431,9 +1430,9 @@
 
 	if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_BITRATE)) {
 		bit_rate = rpn->bit_rate;
-		if (bit_rate != RFCOMM_RPN_BR_115200) {
+		if (bit_rate > RFCOMM_RPN_BR_230400) {
 			BT_DBG("RPN bit rate mismatch 0x%x", bit_rate);
-			bit_rate = RFCOMM_RPN_BR_115200;
+			bit_rate = RFCOMM_RPN_BR_9600;
 			rpn_mask ^= RFCOMM_RPN_PM_BITRATE;
 		}
 	}
@@ -1698,7 +1697,7 @@
 		break;
 
 	default:
-		BT_ERR("Unknown packet type 0x%02x\n", type);
+		BT_ERR("Unknown packet type 0x%02x", type);
 		break;
 	}
 	kfree_skb(skb);
@@ -1884,7 +1883,7 @@
 		 * L2CAP MTU minus UIH header and FCS. */
 		s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5;
 
-		rfcomm_schedule(RFCOMM_SCHED_RX);
+		rfcomm_schedule();
 	} else
 		sock_release(nsock);
 }
@@ -2093,7 +2092,7 @@
 
 	rfcomm_session_put(s);
 
-	rfcomm_schedule(RFCOMM_SCHED_AUTH);
+	rfcomm_schedule();
 }
 
 static struct hci_cb rfcomm_cb = {
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 44a6232..aec505f 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -82,11 +82,14 @@
 static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
 {
 	struct sock *sk = d->owner, *parent;
+	unsigned long flags;
+
 	if (!sk)
 		return;
 
 	BT_DBG("dlc %p state %ld err %d", d, d->state, err);
 
+	local_irq_save(flags);
 	bh_lock_sock(sk);
 
 	if (err)
@@ -108,6 +111,7 @@
 	}
 
 	bh_unlock_sock(sk);
+	local_irq_restore(flags);
 
 	if (parent && sock_flag(sk, SOCK_ZAPPED)) {
 		/* We have to drop DLC lock here, otherwise
@@ -617,121 +621,29 @@
 	return sent;
 }
 
-static long rfcomm_sock_data_wait(struct sock *sk, long timeo)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(sk_sleep(sk), &wait);
-	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (!skb_queue_empty(&sk->sk_receive_queue) ||
-		    sk->sk_err ||
-		    (sk->sk_shutdown & RCV_SHUTDOWN) ||
-		    signal_pending(current) ||
-		    !timeo)
-			break;
-
-		set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
-		release_sock(sk);
-		timeo = schedule_timeout(timeo);
-		lock_sock(sk);
-		clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
-	}
-
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(sk_sleep(sk), &wait);
-	return timeo;
-}
-
 static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 			       struct msghdr *msg, size_t size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
-	int err = 0;
-	size_t target, copied = 0;
-	long timeo;
+	int len;
 
 	if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
 		rfcomm_dlc_accept(d);
 		return 0;
 	}
 
-	if (flags & MSG_OOB)
-		return -EOPNOTSUPP;
-
-	msg->msg_namelen = 0;
-
-	BT_DBG("sk %p size %zu", sk, size);
+	len = bt_sock_stream_recvmsg(iocb, sock, msg, size, flags);
 
 	lock_sock(sk);
+	if (!(flags & MSG_PEEK) && len > 0)
+		atomic_sub(len, &sk->sk_rmem_alloc);
 
-	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
-	timeo  = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
-
-	do {
-		struct sk_buff *skb;
-		int chunk;
-
-		skb = skb_dequeue(&sk->sk_receive_queue);
-		if (!skb) {
-			if (copied >= target)
-				break;
-
-			if ((err = sock_error(sk)) != 0)
-				break;
-			if (sk->sk_shutdown & RCV_SHUTDOWN)
-				break;
-
-			err = -EAGAIN;
-			if (!timeo)
-				break;
-
-			timeo = rfcomm_sock_data_wait(sk, timeo);
-
-			if (signal_pending(current)) {
-				err = sock_intr_errno(timeo);
-				goto out;
-			}
-			continue;
-		}
-
-		chunk = min_t(unsigned int, skb->len, size);
-		if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
-			skb_queue_head(&sk->sk_receive_queue, skb);
-			if (!copied)
-				copied = -EFAULT;
-			break;
-		}
-		copied += chunk;
-		size   -= chunk;
-
-		sock_recv_ts_and_drops(msg, sk, skb);
-
-		if (!(flags & MSG_PEEK)) {
-			atomic_sub(chunk, &sk->sk_rmem_alloc);
-
-			skb_pull(skb, chunk);
-			if (skb->len) {
-				skb_queue_head(&sk->sk_receive_queue, skb);
-				break;
-			}
-			kfree_skb(skb);
-
-		} else {
-			/* put message back and return */
-			skb_queue_head(&sk->sk_receive_queue, skb);
-			break;
-		}
-	} while (size);
-
-out:
 	if (atomic_read(&sk->sk_rmem_alloc) <= (sk->sk_rcvbuf >> 2))
 		rfcomm_dlc_unthrottle(rfcomm_pi(sk)->dlc);
-
 	release_sock(sk);
-	return copied ? : err;
+
+	return len;
 }
 
 static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index befc3a5..a9b81f5 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -183,9 +183,7 @@
 static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
 {
 	struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
-	bdaddr_t bdaddr;
-	baswap(&bdaddr, &dev->dst);
-	return sprintf(buf, "%s\n", batostr(&bdaddr));
+	return sprintf(buf, "%s\n", batostr(&dev->dst));
 }
 
 static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf)
@@ -844,10 +842,6 @@
 		BT_DBG("TIOCMIWAIT");
 		break;
 
-	case TIOCGICOUNT:
-		BT_DBG("TIOCGICOUNT");
-		break;
-
 	case TIOCGSERIAL:
 		BT_ERR("TIOCGSERIAL is not supported");
 		return -ENOIOCTLCMD;
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index cf09fe59..17cb0b6 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -212,6 +212,11 @@
 	return 0;
 }
 
+static int br_set_flags(struct net_device *netdev, u32 data)
+{
+	return ethtool_op_set_flags(netdev, data, ETH_FLAG_TXVLAN);
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void br_poll_controller(struct net_device *br_dev)
 {
@@ -304,6 +309,7 @@
 	.get_ufo	= ethtool_op_get_ufo,
 	.set_ufo	= ethtool_op_set_ufo,
 	.get_flags	= ethtool_op_get_flags,
+	.set_flags	= br_set_flags,
 };
 
 static const struct net_device_ops br_netdev_ops = {
@@ -343,5 +349,5 @@
 
 	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
 			NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX |
-			NETIF_F_NETNS_LOCAL | NETIF_F_GSO;
+			NETIF_F_NETNS_LOCAL | NETIF_F_GSO | NETIF_F_HW_VLAN_TX;
 }
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index c03d2c3..89ad25a 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -61,30 +61,27 @@
 }
 
 
-/*
- * Check for port carrier transistions.
- * Called from work queue to allow for calling functions that
- * might sleep (such as speed check), and to debounce.
- */
+/* Check for port carrier transistions. */
 void br_port_carrier_check(struct net_bridge_port *p)
 {
 	struct net_device *dev = p->dev;
 	struct net_bridge *br = p->br;
 
-	if (netif_carrier_ok(dev))
+	if (netif_running(dev) && netif_carrier_ok(dev))
 		p->path_cost = port_cost(dev);
 
-	if (netif_running(br->dev)) {
-		spin_lock_bh(&br->lock);
-		if (netif_carrier_ok(dev)) {
-			if (p->state == BR_STATE_DISABLED)
-				br_stp_enable_port(p);
-		} else {
-			if (p->state != BR_STATE_DISABLED)
-				br_stp_disable_port(p);
-		}
-		spin_unlock_bh(&br->lock);
+	if (!netif_running(br->dev))
+		return;
+
+	spin_lock_bh(&br->lock);
+	if (netif_running(dev) && netif_carrier_ok(dev)) {
+		if (p->state == BR_STATE_DISABLED)
+			br_stp_enable_port(p);
+	} else {
+		if (p->state != BR_STATE_DISABLED)
+			br_stp_disable_port(p);
 	}
+	spin_unlock_bh(&br->lock);
 }
 
 static void release_nbp(struct kobject *kobj)
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 826cd52..25207a1 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -141,7 +141,7 @@
 	const unsigned char *dest = eth_hdr(skb)->h_dest;
 	int (*rhook)(struct sk_buff *skb);
 
-	if (skb->pkt_type == PACKET_LOOPBACK)
+	if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
 		return skb;
 
 	if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
@@ -159,7 +159,7 @@
 			goto drop;
 
 		/* If STP is turned off, then forward */
-		if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0)
+		if (p->br->stp_enabled == BR_NO_STP)
 			goto forward;
 
 		if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 137f232..865fd76 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -64,22 +64,24 @@
 
 static inline __be16 vlan_proto(const struct sk_buff *skb)
 {
-	return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
+	if (vlan_tx_tag_present(skb))
+		return skb->protocol;
+	else if (skb->protocol == htons(ETH_P_8021Q))
+		return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
+	else
+		return 0;
 }
 
 #define IS_VLAN_IP(skb) \
-	(skb->protocol == htons(ETH_P_8021Q) && \
-	 vlan_proto(skb) == htons(ETH_P_IP) && 	\
+	(vlan_proto(skb) == htons(ETH_P_IP) && \
 	 brnf_filter_vlan_tagged)
 
 #define IS_VLAN_IPV6(skb) \
-	(skb->protocol == htons(ETH_P_8021Q) && \
-	 vlan_proto(skb) == htons(ETH_P_IPV6) &&\
+	(vlan_proto(skb) == htons(ETH_P_IPV6) && \
 	 brnf_filter_vlan_tagged)
 
 #define IS_VLAN_ARP(skb) \
-	(skb->protocol == htons(ETH_P_8021Q) &&	\
-	 vlan_proto(skb) == htons(ETH_P_ARP) &&	\
+	(vlan_proto(skb) == htons(ETH_P_ARP) &&	\
 	 brnf_filter_vlan_tagged)
 
 static inline __be16 pppoe_proto(const struct sk_buff *skb)
@@ -106,7 +108,6 @@
 	.family =		AF_INET,
 	.protocol =		cpu_to_be16(ETH_P_IP),
 	.update_pmtu =		fake_update_pmtu,
-	.entries =		ATOMIC_INIT(0),
 };
 
 /*
@@ -209,6 +210,72 @@
 		skb->protocol = htons(ETH_P_PPP_SES);
 }
 
+/* When handing a packet over to the IP layer
+ * check whether we have a skb that is in the
+ * expected format
+ */
+
+static int br_parse_ip_options(struct sk_buff *skb)
+{
+	struct ip_options *opt;
+	struct iphdr *iph;
+	struct net_device *dev = skb->dev;
+	u32 len;
+
+	iph = ip_hdr(skb);
+	opt = &(IPCB(skb)->opt);
+
+	/* Basic sanity checks */
+	if (iph->ihl < 5 || iph->version != 4)
+		goto inhdr_error;
+
+	if (!pskb_may_pull(skb, iph->ihl*4))
+		goto inhdr_error;
+
+	iph = ip_hdr(skb);
+	if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
+		goto inhdr_error;
+
+	len = ntohs(iph->tot_len);
+	if (skb->len < len) {
+		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS);
+		goto drop;
+	} else if (len < (iph->ihl*4))
+		goto inhdr_error;
+
+	if (pskb_trim_rcsum(skb, len)) {
+		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
+		goto drop;
+	}
+
+	/* Zero out the CB buffer if no options present */
+	if (iph->ihl == 5) {
+		memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+		return 0;
+	}
+
+	opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
+	if (ip_options_compile(dev_net(dev), opt, skb))
+		goto inhdr_error;
+
+	/* Check correct handling of SRR option */
+	if (unlikely(opt->srr)) {
+		struct in_device *in_dev = __in_dev_get_rcu(dev);
+		if (in_dev && !IN_DEV_SOURCE_ROUTE(in_dev))
+			goto drop;
+
+		if (ip_options_rcv_srr(skb))
+			goto drop;
+	}
+
+	return 0;
+
+inhdr_error:
+	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
+drop:
+	return -1;
+}
+
 /* Fill in the header for fragmented IP packets handled by
  * the IPv4 connection tracking code.
  */
@@ -549,7 +616,6 @@
 {
 	struct net_bridge_port *p;
 	struct net_bridge *br;
-	struct iphdr *iph;
 	__u32 len = nf_bridge_encap_header_len(skb);
 
 	if (unlikely(!pskb_may_pull(skb, len)))
@@ -578,28 +644,9 @@
 
 	nf_bridge_pull_encap_header_rcsum(skb);
 
-	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-		goto inhdr_error;
-
-	iph = ip_hdr(skb);
-	if (iph->ihl < 5 || iph->version != 4)
-		goto inhdr_error;
-
-	if (!pskb_may_pull(skb, 4 * iph->ihl))
-		goto inhdr_error;
-
-	iph = ip_hdr(skb);
-	if (ip_fast_csum((__u8 *) iph, iph->ihl) != 0)
-		goto inhdr_error;
-
-	len = ntohs(iph->tot_len);
-	if (skb->len < len || len < 4 * iph->ihl)
-		goto inhdr_error;
-
-	pskb_trim_rcsum(skb, len);
-
-	/* BUG: Should really parse the IP options here. */
-	memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+	if (br_parse_ip_options(skb))
+		/* Drop invalid packet */
+		goto out;
 
 	nf_bridge_put(skb->nf_bridge);
 	if (!nf_bridge_alloc(skb))
@@ -614,8 +661,6 @@
 
 	return NF_STOLEN;
 
-inhdr_error:
-//      IP_INC_STATS_BH(IpInHdrErrors);
 out:
 	return NF_DROP;
 }
@@ -759,14 +804,19 @@
 #if defined(CONFIG_NF_CONNTRACK_IPV4) || defined(CONFIG_NF_CONNTRACK_IPV4_MODULE)
 static int br_nf_dev_queue_xmit(struct sk_buff *skb)
 {
+	int ret;
+
 	if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) &&
 	    skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu &&
 	    !skb_is_gso(skb)) {
-		/* BUG: Should really parse the IP options here. */
-		memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
-		return ip_fragment(skb, br_dev_queue_push_xmit);
+		if (br_parse_ip_options(skb))
+			/* Drop invalid packet */
+			return NF_DROP;
+		ret = ip_fragment(skb, br_dev_queue_push_xmit);
 	} else
-		return br_dev_queue_push_xmit(skb);
+		ret = br_dev_queue_push_xmit(skb);
+
+	return ret;
 }
 #else
 static int br_nf_dev_queue_xmit(struct sk_buff *skb)
@@ -954,15 +1004,22 @@
 {
 	int ret;
 
-	ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
+	ret = dst_entries_init(&fake_dst_ops);
 	if (ret < 0)
 		return ret;
+
+	ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
+	if (ret < 0) {
+		dst_entries_destroy(&fake_dst_ops);
+		return ret;
+	}
 #ifdef CONFIG_SYSCTL
 	brnf_sysctl_header = register_sysctl_paths(brnf_path, brnf_table);
 	if (brnf_sysctl_header == NULL) {
 		printk(KERN_WARNING
 		       "br_netfilter: can't register to sysctl.\n");
 		nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
+		dst_entries_destroy(&fake_dst_ops);
 		return -ENOMEM;
 	}
 #endif
@@ -976,4 +1033,5 @@
 #ifdef CONFIG_SYSCTL
 	unregister_sysctl_table(brnf_sysctl_header);
 #endif
+	dst_entries_destroy(&fake_dst_ops);
 }
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index 87b53b3..eae67bf 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -39,8 +39,6 @@
 ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	const struct ebt_vlan_info *info = par->matchinfo;
-	const struct vlan_hdr *fp;
-	struct vlan_hdr _frame;
 
 	unsigned short TCI;	/* Whole TCI, given from parsed frame */
 	unsigned short id;	/* VLAN ID, given from frame TCI */
@@ -48,9 +46,20 @@
 	/* VLAN encapsulated Type/Length field, given from orig frame */
 	__be16 encap;
 
-	fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
-	if (fp == NULL)
-		return false;
+	if (vlan_tx_tag_present(skb)) {
+		TCI = vlan_tx_tag_get(skb);
+		encap = skb->protocol;
+	} else {
+		const struct vlan_hdr *fp;
+		struct vlan_hdr _frame;
+
+		fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
+		if (fp == NULL)
+			return false;
+
+		TCI = ntohs(fp->h_vlan_TCI);
+		encap = fp->h_vlan_encapsulated_proto;
+	}
 
 	/* Tag Control Information (TCI) consists of the following elements:
 	 * - User_priority. The user_priority field is three bits in length,
@@ -59,10 +68,8 @@
 	 * (CFI) is a single bit flag value. Currently ignored.
 	 * - VLAN Identifier (VID). The VID is encoded as
 	 * an unsigned binary number. */
-	TCI = ntohs(fp->h_vlan_TCI);
 	id = TCI & VLAN_VID_MASK;
 	prio = (TCI >> 13) & 0x7;
-	encap = fp->h_vlan_encapsulated_proto;
 
 	/* Checking VLAN Identifier (VID) */
 	if (GET_BITMASK(EBT_VLAN_ID))
@@ -111,10 +118,10 @@
 	 * 0 - The null VLAN ID.
 	 * 1 - The default Port VID (PVID)
 	 * 0x0FFF - Reserved for implementation use.
-	 * if_vlan.h: VLAN_GROUP_ARRAY_LEN 4096. */
+	 * if_vlan.h: VLAN_N_VID 4096. */
 	if (GET_BITMASK(EBT_VLAN_ID)) {
 		if (!!info->id) { /* if id!=0 => check vid range */
-			if (info->id > VLAN_GROUP_ARRAY_LEN) {
+			if (info->id > VLAN_N_VID) {
 				pr_debug("id %d is out of range (1-4096)\n",
 					 info->id);
 				return -EINVAL;
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index bcc102e..a1dcf83 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -124,16 +124,23 @@
 #define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
 /* process standard matches */
 static inline int
-ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h,
+ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb,
                 const struct net_device *in, const struct net_device *out)
 {
+	const struct ethhdr *h = eth_hdr(skb);
+	__be16 ethproto;
 	int verdict, i;
 
+	if (vlan_tx_tag_present(skb))
+		ethproto = htons(ETH_P_8021Q);
+	else
+		ethproto = h->h_proto;
+
 	if (e->bitmask & EBT_802_3) {
-		if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
+		if (FWINV2(ntohs(ethproto) >= 1536, EBT_IPROTO))
 			return 1;
 	} else if (!(e->bitmask & EBT_NOPROTO) &&
-	   FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
+	   FWINV2(e->ethproto != ethproto, EBT_IPROTO))
 		return 1;
 
 	if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
@@ -213,7 +220,7 @@
 	base = private->entries;
 	i = 0;
 	while (i < nentries) {
-		if (ebt_basic_match(point, eth_hdr(skb), in, out))
+		if (ebt_basic_match(point, skb, in, out))
 			goto letscontinue;
 
 		if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0)
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index 0b586e9..b99369a 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -9,6 +9,8 @@
  *  and Sakari Ailus <sakari.ailus@nokia.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -171,7 +173,7 @@
 	net = dev_net(dev);
 	pkt = cfpkt_fromnative(CAIF_DIR_IN, skb);
 	caifd = caif_get(dev);
-	if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd)
+	if (!caifd || !caifd->layer.up || !caifd->layer.up->receive)
 		return NET_RX_DROP;
 
 	if (caifd->layer.up->receive(caifd->layer.up, pkt))
@@ -214,7 +216,7 @@
 
 	switch (what) {
 	case NETDEV_REGISTER:
-		pr_info("CAIF: %s():register %s\n", __func__, dev->name);
+		netdev_info(dev, "register\n");
 		caifd = caif_device_alloc(dev);
 		if (caifd == NULL)
 			break;
@@ -225,14 +227,13 @@
 		break;
 
 	case NETDEV_UP:
-		pr_info("CAIF: %s(): up %s\n", __func__, dev->name);
+		netdev_info(dev, "up\n");
 		caifd = caif_get(dev);
 		if (caifd == NULL)
 			break;
 		caifdev = netdev_priv(dev);
 		if (atomic_read(&caifd->state) == NETDEV_UP) {
-			pr_info("CAIF: %s():%s already up\n",
-				__func__, dev->name);
+			netdev_info(dev, "already up\n");
 			break;
 		}
 		atomic_set(&caifd->state, what);
@@ -273,7 +274,7 @@
 		caifd = caif_get(dev);
 		if (caifd == NULL)
 			break;
-		pr_info("CAIF: %s():going down %s\n", __func__, dev->name);
+		netdev_info(dev, "going down\n");
 
 		if (atomic_read(&caifd->state) == NETDEV_GOING_DOWN ||
 			atomic_read(&caifd->state) == NETDEV_DOWN)
@@ -295,11 +296,10 @@
 		caifd = caif_get(dev);
 		if (caifd == NULL)
 			break;
-		pr_info("CAIF: %s(): down %s\n", __func__, dev->name);
+		netdev_info(dev, "down\n");
 		if (atomic_read(&caifd->in_use))
-			pr_warning("CAIF: %s(): "
-				   "Unregistering an active CAIF device: %s\n",
-				   __func__, dev->name);
+			netdev_warn(dev,
+				    "Unregistering an active CAIF device\n");
 		cfcnfg_del_phy_layer(get_caif_conf(), &caifd->layer);
 		dev_put(dev);
 		atomic_set(&caifd->state, what);
@@ -307,7 +307,7 @@
 
 	case NETDEV_UNREGISTER:
 		caifd = caif_get(dev);
-		pr_info("CAIF: %s(): unregister %s\n", __func__, dev->name);
+		netdev_info(dev, "unregister\n");
 		atomic_set(&caifd->state, what);
 		caif_device_destroy(dev);
 		break;
@@ -391,7 +391,7 @@
 	int result;
 	cfg = cfcnfg_create();
 	if (!cfg) {
-		pr_warning("CAIF: %s(): can't create cfcnfg.\n", __func__);
+		pr_warn("can't create cfcnfg\n");
 		goto err_cfcnfg_create_failed;
 	}
 	result = register_pernet_device(&caif_net_ops);
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 8ce9047..2eca2dd 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -4,6 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -15,7 +17,6 @@
 #include <linux/poll.h>
 #include <linux/tcp.h>
 #include <linux/uaccess.h>
-#include <linux/mutex.h>
 #include <linux/debugfs.h>
 #include <linux/caif/caif_socket.h>
 #include <asm/atomic.h>
@@ -28,9 +29,6 @@
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NETPROTO(AF_CAIF);
 
-#define CAIF_DEF_SNDBUF (4096*10)
-#define CAIF_DEF_RCVBUF (4096*100)
-
 /*
  * CAIF state is re-using the TCP socket states.
  * caif_states stored in sk_state reflect the state as reported by
@@ -157,9 +155,7 @@
 
 	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
 		(unsigned)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) {
-		trace_printk("CAIF: %s():"
-			" sending flow OFF (queue len = %d %d)\n",
-			__func__,
+		pr_debug("sending flow OFF (queue len = %d %d)\n",
 			atomic_read(&cf_sk->sk.sk_rmem_alloc),
 			sk_rcvbuf_lowwater(cf_sk));
 		set_rx_flow_off(cf_sk);
@@ -172,9 +168,7 @@
 		return err;
 	if (!sk_rmem_schedule(sk, skb->truesize) && rx_flow_is_on(cf_sk)) {
 		set_rx_flow_off(cf_sk);
-		trace_printk("CAIF: %s():"
-			" sending flow OFF due to rmem_schedule\n",
-			__func__);
+		pr_debug("sending flow OFF due to rmem_schedule\n");
 		dbfs_atomic_inc(&cnt.num_rx_flow_off);
 		caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ);
 	}
@@ -275,8 +269,7 @@
 		break;
 
 	default:
-		pr_debug("CAIF: %s(): Unexpected flow command %d\n",
-				__func__, flow);
+		pr_debug("Unexpected flow command %d\n", flow);
 	}
 }
 
@@ -536,8 +529,7 @@
 
 		/* Slight paranoia, probably not needed. */
 		if (unlikely(loopcnt++ > 1000)) {
-			pr_warning("CAIF: %s(): transmit retries failed,"
-				" error = %d\n", __func__, ret);
+			pr_warn("transmit retries failed, error = %d\n", ret);
 			break;
 		}
 
@@ -827,6 +819,7 @@
 	long timeo;
 	int err;
 	int ifindex, headroom, tailroom;
+	unsigned int mtu;
 	struct net_device *dev;
 
 	lock_sock(sk);
@@ -896,15 +889,22 @@
 		cf_sk->sk.sk_state = CAIF_DISCONNECTED;
 		goto out;
 	}
-	dev = dev_get_by_index(sock_net(sk), ifindex);
+
+	err = -ENODEV;
+	rcu_read_lock();
+	dev = dev_get_by_index_rcu(sock_net(sk), ifindex);
+	if (!dev) {
+		rcu_read_unlock();
+		goto out;
+	}
 	cf_sk->headroom = LL_RESERVED_SPACE_EXTRA(dev, headroom);
+	mtu = dev->mtu;
+	rcu_read_unlock();
+
 	cf_sk->tailroom = tailroom;
-	cf_sk->maxframe = dev->mtu - (headroom + tailroom);
-	dev_put(dev);
+	cf_sk->maxframe = mtu - (headroom + tailroom);
 	if (cf_sk->maxframe < 1) {
-		pr_warning("CAIF: %s(): CAIF Interface MTU too small (%d)\n",
-			__func__, dev->mtu);
-		err = -ENODEV;
+		pr_warn("CAIF Interface MTU too small (%d)\n", dev->mtu);
 		goto out;
 	}
 
@@ -1123,10 +1123,6 @@
 	/* Store the protocol */
 	sk->sk_protocol = (unsigned char) protocol;
 
-	/* Sendbuf dictates the amount of outbound packets not yet sent */
-	sk->sk_sndbuf = CAIF_DEF_SNDBUF;
-	sk->sk_rcvbuf = CAIF_DEF_RCVBUF;
-
 	/*
 	 * Lock in order to try to stop someone from opening the socket
 	 * too early.
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index 1c29189..41adafd1 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -3,6 +3,9 @@
  * Author:	Sjur Brendeland/sjur.brandeland@stericsson.com
  * License terms: GNU General Public License (GPL) version 2
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/kernel.h>
 #include <linux/stddef.h>
 #include <linux/slab.h>
@@ -78,7 +81,7 @@
 	/* Initiate this layer */
 	this = kzalloc(sizeof(struct cfcnfg), GFP_ATOMIC);
 	if (!this) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return NULL;
 	}
 	this->mux = cfmuxl_create();
@@ -106,7 +109,7 @@
 	layer_set_up(this->ctrl, this);
 	return this;
 out_of_mem:
-	pr_warning("CAIF: %s(): Out of memory\n", __func__);
+	pr_warn("Out of memory\n");
 	kfree(this->mux);
 	kfree(this->ctrl);
 	kfree(this);
@@ -194,7 +197,7 @@
 	caif_assert(adap_layer != NULL);
 	channel_id = adap_layer->id;
 	if (adap_layer->dn == NULL || channel_id == 0) {
-		pr_err("CAIF: %s():adap_layer->id is 0\n", __func__);
+		pr_err("adap_layer->dn == NULL or adap_layer->id is 0\n");
 		ret = -ENOTCONN;
 		goto end;
 	}
@@ -204,9 +207,8 @@
 	layer_set_up(servl, NULL);
 	ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer);
 	if (servl == NULL) {
-		pr_err("CAIF: %s(): PROTOCOL ERROR "
-		       "- Error removing service_layer Channel_Id(%d)",
-			__func__, channel_id);
+		pr_err("PROTOCOL ERROR - Error removing service_layer Channel_Id(%d)",
+		       channel_id);
 		ret = -EINVAL;
 		goto end;
 	}
@@ -216,18 +218,14 @@
 
 		phyinfo = cfcnfg_get_phyinfo(cnfg, phyid);
 		if (phyinfo == NULL) {
-			pr_warning("CAIF: %s(): "
-				"No interface to send disconnect to\n",
-				__func__);
+			pr_warn("No interface to send disconnect to\n");
 			ret = -ENODEV;
 			goto end;
 		}
 		if (phyinfo->id != phyid ||
 			phyinfo->phy_layer->id != phyid ||
 			phyinfo->frm_layer->id != phyid) {
-			pr_err("CAIF: %s(): "
-				"Inconsistency in phy registration\n",
-				__func__);
+			pr_err("Inconsistency in phy registration\n");
 			ret = -EINVAL;
 			goto end;
 		}
@@ -276,21 +274,20 @@
 {
 	struct cflayer *frml;
 	if (adap_layer == NULL) {
-		pr_err("CAIF: %s(): adap_layer is zero", __func__);
+		pr_err("adap_layer is zero\n");
 		return -EINVAL;
 	}
 	if (adap_layer->receive == NULL) {
-		pr_err("CAIF: %s(): adap_layer->receive is NULL", __func__);
+		pr_err("adap_layer->receive is NULL\n");
 		return -EINVAL;
 	}
 	if (adap_layer->ctrlcmd == NULL) {
-		pr_err("CAIF: %s(): adap_layer->ctrlcmd == NULL", __func__);
+		pr_err("adap_layer->ctrlcmd == NULL\n");
 		return -EINVAL;
 	}
 	frml = cnfg->phy_layers[param->phyid].frm_layer;
 	if (frml == NULL) {
-		pr_err("CAIF: %s(): Specified PHY type does not exist!",
-			__func__);
+		pr_err("Specified PHY type does not exist!\n");
 		return -ENODEV;
 	}
 	caif_assert(param->phyid == cnfg->phy_layers[param->phyid].id);
@@ -330,9 +327,7 @@
 	struct net_device *netdev;
 
 	if (adapt_layer == NULL) {
-		pr_debug("CAIF: %s(): link setup response "
-				"but no client exist, send linkdown back\n",
-				__func__);
+		pr_debug("link setup response but no client exist, send linkdown back\n");
 		cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL);
 		return;
 	}
@@ -374,13 +369,11 @@
 		servicel = cfdbgl_create(channel_id, &phyinfo->dev_info);
 		break;
 	default:
-		pr_err("CAIF: %s(): Protocol error. "
-			"Link setup response - unknown channel type\n",
-			__func__);
+		pr_err("Protocol error. Link setup response - unknown channel type\n");
 		return;
 	}
 	if (!servicel) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return;
 	}
 	layer_set_dn(servicel, cnfg->mux);
@@ -418,7 +411,7 @@
 		}
 	}
 	if (*phyid == 0) {
-		pr_err("CAIF: %s(): No Available PHY ID\n", __func__);
+		pr_err("No Available PHY ID\n");
 		return;
 	}
 
@@ -427,7 +420,7 @@
 		phy_driver =
 		    cfserl_create(CFPHYTYPE_FRAG, *phyid, stx);
 		if (!phy_driver) {
-			pr_warning("CAIF: %s(): Out of memory\n", __func__);
+			pr_warn("Out of memory\n");
 			return;
 		}
 
@@ -436,7 +429,7 @@
 		phy_driver = NULL;
 		break;
 	default:
-		pr_err("CAIF: %s(): %d", __func__, phy_type);
+		pr_err("%d\n", phy_type);
 		return;
 		break;
 	}
@@ -455,7 +448,7 @@
 	phy_layer->type = phy_type;
 	frml = cffrml_create(*phyid, fcs);
 	if (!frml) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return;
 	}
 	cnfg->phy_layers[*phyid].frm_layer = frml;
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c
index 563145f..08f267a 100644
--- a/net/caif/cfctrl.c
+++ b/net/caif/cfctrl.c
@@ -4,6 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -36,7 +38,7 @@
 	struct cfctrl *this =
 		kmalloc(sizeof(struct cfctrl), GFP_ATOMIC);
 	if (!this) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return NULL;
 	}
 	caif_assert(offsetof(struct cfctrl, serv.layer) == 0);
@@ -132,9 +134,7 @@
 	list_for_each_entry_safe(p, tmp, &ctrl->list, list) {
 		if (cfctrl_req_eq(req, p)) {
 			if (p != first)
-				pr_warning("CAIF: %s(): Requests are not "
-					"received in order\n",
-					__func__);
+				pr_warn("Requests are not received in order\n");
 
 			atomic_set(&ctrl->rsp_seq_no,
 					 p->sequence_no);
@@ -177,7 +177,7 @@
 	int ret;
 	struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
 	if (!pkt) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return;
 	}
 	caif_assert(offsetof(struct cfctrl, serv.layer) == 0);
@@ -189,8 +189,7 @@
 	ret =
 	    cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
 	if (ret < 0) {
-		pr_err("CAIF: %s(): Could not transmit enum message\n",
-			__func__);
+		pr_err("Could not transmit enum message\n");
 		cfpkt_destroy(pkt);
 	}
 }
@@ -208,7 +207,7 @@
 	char utility_name[16];
 	struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
 	if (!pkt) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return -ENOMEM;
 	}
 	cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP);
@@ -253,13 +252,13 @@
 			       param->u.utility.paramlen);
 		break;
 	default:
-		pr_warning("CAIF: %s():Request setup of bad link type = %d\n",
-			   __func__, param->linktype);
+		pr_warn("Request setup of bad link type = %d\n",
+			param->linktype);
 		return -EINVAL;
 	}
 	req = kzalloc(sizeof(*req), GFP_KERNEL);
 	if (!req) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return -ENOMEM;
 	}
 	req->client_layer = user_layer;
@@ -276,8 +275,7 @@
 	ret =
 	    cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
 	if (ret < 0) {
-		pr_err("CAIF: %s(): Could not transmit linksetup request\n",
-			__func__);
+		pr_err("Could not transmit linksetup request\n");
 		cfpkt_destroy(pkt);
 		return -ENODEV;
 	}
@@ -291,7 +289,7 @@
 	struct cfctrl *cfctrl = container_obj(layer);
 	struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
 	if (!pkt) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return -ENOMEM;
 	}
 	cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY);
@@ -300,8 +298,7 @@
 	ret =
 	    cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
 	if (ret < 0) {
-		pr_err("CAIF: %s(): Could not transmit link-down request\n",
-			__func__);
+		pr_err("Could not transmit link-down request\n");
 		cfpkt_destroy(pkt);
 	}
 	return ret;
@@ -313,7 +310,7 @@
 	struct cfctrl *cfctrl = container_obj(layer);
 	struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
 	if (!pkt) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return;
 	}
 	cfpkt_addbdy(pkt, CFCTRL_CMD_SLEEP);
@@ -330,7 +327,7 @@
 	struct cfctrl *cfctrl = container_obj(layer);
 	struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
 	if (!pkt) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return;
 	}
 	cfpkt_addbdy(pkt, CFCTRL_CMD_WAKE);
@@ -347,7 +344,7 @@
 	struct cfctrl *cfctrl = container_obj(layer);
 	struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
 	if (!pkt) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return;
 	}
 	cfpkt_addbdy(pkt, CFCTRL_CMD_START_REASON);
@@ -364,12 +361,11 @@
 	struct cfctrl_request_info *p, *tmp;
 	struct cfctrl *ctrl = container_obj(layr);
 	spin_lock(&ctrl->info_list_lock);
-	pr_warning("CAIF: %s(): enter\n", __func__);
+	pr_warn("enter\n");
 
 	list_for_each_entry_safe(p, tmp, &ctrl->list, list) {
 		if (p->client_layer == adap_layer) {
-			pr_warning("CAIF: %s(): cancel req :%d\n", __func__,
-					p->sequence_no);
+			pr_warn("cancel req :%d\n", p->sequence_no);
 			list_del(&p->list);
 			kfree(p);
 		}
@@ -520,9 +516,8 @@
 				cfpkt_extr_head(pkt, &param, len);
 				break;
 			default:
-				pr_warning("CAIF: %s(): Request setup "
-					   "- invalid link type (%d)",
-					   __func__, serv);
+				pr_warn("Request setup - invalid link type (%d)\n",
+					serv);
 				goto error;
 			}
 
@@ -532,9 +527,7 @@
 
 			if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) ||
 				cfpkt_erroneous(pkt)) {
-				pr_err("CAIF: %s(): Invalid O/E bit or parse "
-				       "error on CAIF control channel",
-					__func__);
+				pr_err("Invalid O/E bit or parse error on CAIF control channel\n");
 				cfctrl->res.reject_rsp(cfctrl->serv.layer.up,
 						       0,
 						       req ? req->client_layer
@@ -556,8 +549,7 @@
 		cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid);
 		break;
 	case CFCTRL_CMD_LINK_ERR:
-		pr_err("CAIF: %s(): Frame Error Indication received\n",
-			__func__);
+		pr_err("Frame Error Indication received\n");
 		cfctrl->res.linkerror_ind();
 		break;
 	case CFCTRL_CMD_ENUM:
@@ -576,7 +568,7 @@
 		cfctrl->res.radioset_rsp();
 		break;
 	default:
-		pr_err("CAIF: %s(): Unrecognized Control Frame\n", __func__);
+		pr_err("Unrecognized Control Frame\n");
 		goto error;
 		break;
 	}
@@ -595,8 +587,7 @@
 	case CAIF_CTRLCMD_FLOW_OFF_IND:
 		spin_lock(&this->info_list_lock);
 		if (!list_empty(&this->list)) {
-			pr_debug("CAIF: %s(): Received flow off in "
-				   "control layer", __func__);
+			pr_debug("Received flow off in control layer\n");
 		}
 		spin_unlock(&this->info_list_lock);
 		break;
@@ -620,7 +611,7 @@
 			if (!ctrl->loop_linkused[linkid])
 				goto found;
 		spin_unlock(&ctrl->loop_linkid_lock);
-		pr_err("CAIF: %s(): Out of link-ids\n", __func__);
+		pr_err("Out of link-ids\n");
 		return -EINVAL;
 found:
 		if (!ctrl->loop_linkused[linkid])
diff --git a/net/caif/cfdbgl.c b/net/caif/cfdbgl.c
index 676648c..496fda9 100644
--- a/net/caif/cfdbgl.c
+++ b/net/caif/cfdbgl.c
@@ -4,6 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <net/caif/caif_layer.h>
@@ -17,7 +19,7 @@
 {
 	struct cfsrvl *dbg = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
 	if (!dbg) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return NULL;
 	}
 	caif_assert(offsetof(struct cfsrvl, layer) == 0);
diff --git a/net/caif/cfdgml.c b/net/caif/cfdgml.c
index ed9d53aff..d3ed264 100644
--- a/net/caif/cfdgml.c
+++ b/net/caif/cfdgml.c
@@ -4,6 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -26,7 +28,7 @@
 {
 	struct cfsrvl *dgm = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
 	if (!dgm) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return NULL;
 	}
 	caif_assert(offsetof(struct cfsrvl, layer) == 0);
@@ -49,14 +51,14 @@
 	caif_assert(layr->ctrlcmd != NULL);
 
 	if (cfpkt_extr_head(pkt, &cmd, 1) < 0) {
-		pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
+		pr_err("Packet is erroneous!\n");
 		cfpkt_destroy(pkt);
 		return -EPROTO;
 	}
 
 	if ((cmd & DGM_CMD_BIT) == 0) {
 		if (cfpkt_extr_head(pkt, &dgmhdr, 3) < 0) {
-			pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
+			pr_err("Packet is erroneous!\n");
 			cfpkt_destroy(pkt);
 			return -EPROTO;
 		}
@@ -75,8 +77,7 @@
 		return 0;
 	default:
 		cfpkt_destroy(pkt);
-		pr_info("CAIF: %s(): Unknown datagram control %d (0x%x)\n",
-			__func__, cmd, cmd);
+		pr_info("Unknown datagram control %d (0x%x)\n", cmd, cmd);
 		return -EPROTO;
 	}
 }
diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c
index e86a4ca..a445043 100644
--- a/net/caif/cffrml.c
+++ b/net/caif/cffrml.c
@@ -6,6 +6,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -32,7 +34,7 @@
 {
 	struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC);
 	if (!this) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return NULL;
 	}
 	caif_assert(offsetof(struct cffrml, layer) == 0);
@@ -83,7 +85,7 @@
 
 	if (cfpkt_setlen(pkt, len) < 0) {
 		++cffrml_rcv_error;
-		pr_err("CAIF: %s():Framing length error (%d)\n", __func__, len);
+		pr_err("Framing length error (%d)\n", len);
 		cfpkt_destroy(pkt);
 		return -EPROTO;
 	}
@@ -99,14 +101,14 @@
 			cfpkt_add_trail(pkt, &tmp, 2);
 			++cffrml_rcv_error;
 			++cffrml_rcv_checsum_error;
-			pr_info("CAIF: %s(): Frame checksum error "
-				"(0x%x != 0x%x)\n", __func__, hdrchks, pktchks);
+			pr_info("Frame checksum error (0x%x != 0x%x)\n",
+				hdrchks, pktchks);
 			return -EILSEQ;
 		}
 	}
 	if (cfpkt_erroneous(pkt)) {
 		++cffrml_rcv_error;
-		pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
+		pr_err("Packet is erroneous!\n");
 		cfpkt_destroy(pkt);
 		return -EPROTO;
 	}
@@ -132,7 +134,7 @@
 	cfpkt_add_head(pkt, &tmp, 2);
 	cfpkt_info(pkt)->hdr_len += 2;
 	if (cfpkt_erroneous(pkt)) {
-		pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
+		pr_err("Packet is erroneous!\n");
 		return -EPROTO;
 	}
 	ret = layr->dn->transmit(layr->dn, pkt);
diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c
index 80c8d33..46f34b2 100644
--- a/net/caif/cfmuxl.c
+++ b/net/caif/cfmuxl.c
@@ -3,6 +3,9 @@
  * Author:	Sjur Brendeland/sjur.brandeland@stericsson.com
  * License terms: GNU General Public License (GPL) version 2
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -190,7 +193,7 @@
 	u8 id;
 	struct cflayer *up;
 	if (cfpkt_extr_head(pkt, &id, 1) < 0) {
-		pr_err("CAIF: %s(): erroneous Caif Packet\n", __func__);
+		pr_err("erroneous Caif Packet\n");
 		cfpkt_destroy(pkt);
 		return -EPROTO;
 	}
@@ -199,8 +202,8 @@
 	up = get_up(muxl, id);
 	spin_unlock(&muxl->receive_lock);
 	if (up == NULL) {
-		pr_info("CAIF: %s():Received data on unknown link ID = %d "
-			"(0x%x)	 up == NULL", __func__, id, id);
+		pr_info("Received data on unknown link ID = %d (0x%x) up == NULL",
+			id, id);
 		cfpkt_destroy(pkt);
 		/*
 		 * Don't return ERROR, since modem misbehaves and sends out
@@ -223,9 +226,8 @@
 	struct caif_payload_info *info = cfpkt_info(pkt);
 	dn = get_dn(muxl, cfpkt_info(pkt)->dev_info);
 	if (dn == NULL) {
-		pr_warning("CAIF: %s(): Send data on unknown phy "
-			   "ID = %d (0x%x)\n",
-			   __func__, info->dev_info->id, info->dev_info->id);
+		pr_warn("Send data on unknown phy ID = %d (0x%x)\n",
+			info->dev_info->id, info->dev_info->id);
 		return -ENOTCONN;
 	}
 	info->hdr_len += 1;
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c
index c49a669..d7e865e 100644
--- a/net/caif/cfpkt_skbuff.c
+++ b/net/caif/cfpkt_skbuff.c
@@ -4,6 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/hardirq.h>
@@ -12,11 +14,12 @@
 #define PKT_PREFIX  48
 #define PKT_POSTFIX 2
 #define PKT_LEN_WHEN_EXTENDING 128
-#define PKT_ERROR(pkt, errmsg) do {	   \
-    cfpkt_priv(pkt)->erronous = true;	   \
-    skb_reset_tail_pointer(&pkt->skb);	   \
-    pr_warning("CAIF: " errmsg);\
-  } while (0)
+#define PKT_ERROR(pkt, errmsg)		   \
+do {					   \
+	cfpkt_priv(pkt)->erronous = true;  \
+	skb_reset_tail_pointer(&pkt->skb); \
+	pr_warn(errmsg);		   \
+} while (0)
 
 struct cfpktq {
 	struct sk_buff_head head;
@@ -130,13 +133,13 @@
 		return -EPROTO;
 
 	if (unlikely(len > skb->len)) {
-		PKT_ERROR(pkt, "cfpkt_extr_head read beyond end of packet\n");
+		PKT_ERROR(pkt, "read beyond end of packet\n");
 		return -EPROTO;
 	}
 
 	if (unlikely(len > skb_headlen(skb))) {
 		if (unlikely(skb_linearize(skb) != 0)) {
-			PKT_ERROR(pkt, "cfpkt_extr_head linearize failed\n");
+			PKT_ERROR(pkt, "linearize failed\n");
 			return -EPROTO;
 		}
 	}
@@ -156,11 +159,11 @@
 		return -EPROTO;
 
 	if (unlikely(skb_linearize(skb) != 0)) {
-		PKT_ERROR(pkt, "cfpkt_extr_trail linearize failed\n");
+		PKT_ERROR(pkt, "linearize failed\n");
 		return -EPROTO;
 	}
 	if (unlikely(skb->data + len > skb_tail_pointer(skb))) {
-		PKT_ERROR(pkt, "cfpkt_extr_trail read beyond end of packet\n");
+		PKT_ERROR(pkt, "read beyond end of packet\n");
 		return -EPROTO;
 	}
 	from = skb_tail_pointer(skb) - len;
@@ -202,7 +205,7 @@
 
 		/* Make sure data is writable */
 		if (unlikely(skb_cow_data(skb, addlen, &lastskb) < 0)) {
-			PKT_ERROR(pkt, "cfpkt_add_body: cow failed\n");
+			PKT_ERROR(pkt, "cow failed\n");
 			return -EPROTO;
 		}
 		/*
@@ -211,8 +214,7 @@
 		 * lengths of the top SKB.
 		 */
 		if (lastskb != skb) {
-			pr_warning("CAIF: %s(): Packet is non-linear\n",
-				   __func__);
+			pr_warn("Packet is non-linear\n");
 			skb->len += len;
 			skb->data_len += len;
 		}
@@ -242,14 +244,14 @@
 	if (unlikely(is_erronous(pkt)))
 		return -EPROTO;
 	if (unlikely(skb_headroom(skb) < len)) {
-		PKT_ERROR(pkt, "cfpkt_add_head: no headroom\n");
+		PKT_ERROR(pkt, "no headroom\n");
 		return -EPROTO;
 	}
 
 	/* Make sure data is writable */
 	ret = skb_cow_data(skb, 0, &lastskb);
 	if (unlikely(ret < 0)) {
-		PKT_ERROR(pkt, "cfpkt_add_head: cow failed\n");
+		PKT_ERROR(pkt, "cow failed\n");
 		return ret;
 	}
 
@@ -283,7 +285,7 @@
 	if (unlikely(is_erronous(pkt)))
 		return -EPROTO;
 	if (unlikely(skb_linearize(&pkt->skb) != 0)) {
-		PKT_ERROR(pkt, "cfpkt_iterate: linearize failed\n");
+		PKT_ERROR(pkt, "linearize failed\n");
 		return -EPROTO;
 	}
 	return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt));
@@ -309,7 +311,7 @@
 
 	/* Need to expand SKB */
 	if (unlikely(!cfpkt_pad_trail(pkt, len - skb->len)))
-		PKT_ERROR(pkt, "cfpkt_setlen: skb_pad_trail failed\n");
+		PKT_ERROR(pkt, "skb_pad_trail failed\n");
 
 	return cfpkt_getlen(pkt);
 }
@@ -380,8 +382,7 @@
 		return NULL;
 
 	if (skb->data + pos > skb_tail_pointer(skb)) {
-		PKT_ERROR(pkt,
-			  "cfpkt_split: trying to split beyond end of packet");
+		PKT_ERROR(pkt, "trying to split beyond end of packet\n");
 		return NULL;
 	}
 
@@ -455,17 +456,17 @@
 		return -EPROTO;
 	/* Make sure SKB is writable */
 	if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) {
-		PKT_ERROR(pkt, "cfpkt_raw_append: skb_cow_data failed\n");
+		PKT_ERROR(pkt, "skb_cow_data failed\n");
 		return -EPROTO;
 	}
 
 	if (unlikely(skb_linearize(skb) != 0)) {
-		PKT_ERROR(pkt, "cfpkt_raw_append: linearize failed\n");
+		PKT_ERROR(pkt, "linearize failed\n");
 		return -EPROTO;
 	}
 
 	if (unlikely(skb_tailroom(skb) < buflen)) {
-		PKT_ERROR(pkt, "cfpkt_raw_append: buffer too short - failed\n");
+		PKT_ERROR(pkt, "buffer too short - failed\n");
 		return -EPROTO;
 	}
 
@@ -483,14 +484,13 @@
 		return -EPROTO;
 
 	if (unlikely(buflen > skb->len)) {
-		PKT_ERROR(pkt, "cfpkt_raw_extract: buflen too large "
-				"- failed\n");
+		PKT_ERROR(pkt, "buflen too large - failed\n");
 		return -EPROTO;
 	}
 
 	if (unlikely(buflen > skb_headlen(skb))) {
 		if (unlikely(skb_linearize(skb) != 0)) {
-			PKT_ERROR(pkt, "cfpkt_raw_extract: linearize failed\n");
+			PKT_ERROR(pkt, "linearize failed\n");
 			return -EPROTO;
 		}
 	}
diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c
index 9a69924..bde8481 100644
--- a/net/caif/cfrfml.c
+++ b/net/caif/cfrfml.c
@@ -4,6 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -48,7 +50,7 @@
 		kzalloc(sizeof(struct cfrfml), GFP_ATOMIC);
 
 	if (!this) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return NULL;
 	}
 
@@ -178,9 +180,7 @@
 			cfpkt_destroy(rfml->incomplete_frm);
 		rfml->incomplete_frm = NULL;
 
-		pr_info("CAIF: %s(): "
-				"Connection error %d triggered on RFM link\n",
-				__func__, err);
+		pr_info("Connection error %d triggered on RFM link\n", err);
 
 		/* Trigger connection error upon failure.*/
 		layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND,
@@ -280,9 +280,7 @@
 out:
 
 	if (err != 0) {
-		pr_info("CAIF: %s(): "
-				"Connection error %d triggered on RFM link\n",
-				__func__, err);
+		pr_info("Connection error %d triggered on RFM link\n", err);
 		/* Trigger connection error upon failure.*/
 
 		layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND,
diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c
index a11fbd6..9297f7d 100644
--- a/net/caif/cfserl.c
+++ b/net/caif/cfserl.c
@@ -4,6 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -34,7 +36,7 @@
 {
 	struct cfserl *this = kmalloc(sizeof(struct cfserl), GFP_ATOMIC);
 	if (!this) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return NULL;
 	}
 	caif_assert(offsetof(struct cfserl, layer) == 0);
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
index f40939a..ab5e542 100644
--- a/net/caif/cfsrvl.c
+++ b/net/caif/cfsrvl.c
@@ -4,6 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -79,8 +81,7 @@
 		layr->up->ctrlcmd(layr->up, ctrl, phyid);
 		break;
 	default:
-		pr_warning("CAIF: %s(): "
-			   "Unexpected ctrl in cfsrvl (%d)\n", __func__, ctrl);
+		pr_warn("Unexpected ctrl in cfsrvl (%d)\n", ctrl);
 		/* We have both modem and phy flow on, send flow on */
 		layr->up->ctrlcmd(layr->up, ctrl, phyid);
 		service->phy_flow_on = true;
@@ -107,14 +108,12 @@
 			u8 flow_on = SRVL_FLOW_ON;
 			pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
 			if (!pkt) {
-				pr_warning("CAIF: %s(): Out of memory\n",
-					__func__);
+				pr_warn("Out of memory\n");
 				return -ENOMEM;
 			}
 
 			if (cfpkt_add_head(pkt, &flow_on, 1) < 0) {
-				pr_err("CAIF: %s(): Packet is erroneous!\n",
-					__func__);
+				pr_err("Packet is erroneous!\n");
 				cfpkt_destroy(pkt);
 				return -EPROTO;
 			}
@@ -131,14 +130,12 @@
 			u8 flow_off = SRVL_FLOW_OFF;
 			pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
 			if (!pkt) {
-				pr_warning("CAIF: %s(): Out of memory\n",
-					__func__);
+				pr_warn("Out of memory\n");
 				return -ENOMEM;
 			}
 
 			if (cfpkt_add_head(pkt, &flow_off, 1) < 0) {
-				pr_err("CAIF: %s(): Packet is erroneous!\n",
-					__func__);
+				pr_err("Packet is erroneous!\n");
 				cfpkt_destroy(pkt);
 				return -EPROTO;
 			}
diff --git a/net/caif/cfutill.c b/net/caif/cfutill.c
index 02795af..efad410 100644
--- a/net/caif/cfutill.c
+++ b/net/caif/cfutill.c
@@ -4,6 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
@@ -26,7 +28,7 @@
 {
 	struct cfsrvl *util = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
 	if (!util) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return NULL;
 	}
 	caif_assert(offsetof(struct cfsrvl, layer) == 0);
@@ -47,7 +49,7 @@
 	caif_assert(layr->up->receive != NULL);
 	caif_assert(layr->up->ctrlcmd != NULL);
 	if (cfpkt_extr_head(pkt, &cmd, 1) < 0) {
-		pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
+		pr_err("Packet is erroneous!\n");
 		cfpkt_destroy(pkt);
 		return -EPROTO;
 	}
@@ -64,16 +66,14 @@
 		cfpkt_destroy(pkt);
 		return 0;
 	case UTIL_REMOTE_SHUTDOWN:	/* Remote Shutdown Request */
-		pr_err("CAIF: %s(): REMOTE SHUTDOWN REQUEST RECEIVED\n",
-			__func__);
+		pr_err("REMOTE SHUTDOWN REQUEST RECEIVED\n");
 		layr->ctrlcmd(layr, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, 0);
 		service->open = false;
 		cfpkt_destroy(pkt);
 		return 0;
 	default:
 		cfpkt_destroy(pkt);
-		pr_warning("CAIF: %s(): Unknown service control %d (0x%x)\n",
-			   __func__, cmd, cmd);
+		pr_warn("Unknown service control %d (0x%x)\n", cmd, cmd);
 		return -EPROTO;
 	}
 }
diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c
index 77cc09f..3b425b1 100644
--- a/net/caif/cfveil.c
+++ b/net/caif/cfveil.c
@@ -4,6 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <net/caif/caif_layer.h>
@@ -25,7 +27,7 @@
 {
 	struct cfsrvl *vei = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
 	if (!vei) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return NULL;
 	}
 	caif_assert(offsetof(struct cfsrvl, layer) == 0);
@@ -47,7 +49,7 @@
 
 
 	if (cfpkt_extr_head(pkt, &cmd, 1) < 0) {
-		pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
+		pr_err("Packet is erroneous!\n");
 		cfpkt_destroy(pkt);
 		return -EPROTO;
 	}
@@ -67,8 +69,7 @@
 		cfpkt_destroy(pkt);
 		return 0;
 	default:		/* SET RS232 PIN */
-		pr_warning("CAIF: %s():Unknown VEI control packet %d (0x%x)!\n",
-			   __func__, cmd, cmd);
+		pr_warn("Unknown VEI control packet %d (0x%x)!\n", cmd, cmd);
 		cfpkt_destroy(pkt);
 		return -EPROTO;
 	}
@@ -86,7 +87,7 @@
 	caif_assert(layr->dn->transmit != NULL);
 
 	if (cfpkt_add_head(pkt, &tmp, 1) < 0) {
-		pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
+		pr_err("Packet is erroneous!\n");
 		return -EPROTO;
 	}
 
diff --git a/net/caif/cfvidl.c b/net/caif/cfvidl.c
index ada6ee2..bf6fef2 100644
--- a/net/caif/cfvidl.c
+++ b/net/caif/cfvidl.c
@@ -4,6 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
@@ -21,7 +23,7 @@
 {
 	struct cfsrvl *vid = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
 	if (!vid) {
-		pr_warning("CAIF: %s(): Out of memory\n", __func__);
+		pr_warn("Out of memory\n");
 		return NULL;
 	}
 	caif_assert(offsetof(struct cfsrvl, layer) == 0);
@@ -38,7 +40,7 @@
 {
 	u32 videoheader;
 	if (cfpkt_extr_head(pkt, &videoheader, 4) < 0) {
-		pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
+		pr_err("Packet is erroneous!\n");
 		cfpkt_destroy(pkt);
 		return -EPROTO;
 	}
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
index 4293e19..84a422c 100644
--- a/net/caif/chnl_net.c
+++ b/net/caif/chnl_net.c
@@ -5,6 +5,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
+
 #include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/init.h>
@@ -28,9 +30,6 @@
 #define CONNECT_TIMEOUT (5 * HZ)
 #define CAIF_NET_DEFAULT_QUEUE_LEN 500
 
-#undef pr_debug
-#define pr_debug pr_warning
-
 /*This list is protected by the rtnl lock. */
 static LIST_HEAD(chnl_net_list);
 
@@ -142,8 +141,7 @@
 				int phyid)
 {
 	struct chnl_net *priv = container_of(layr, struct chnl_net, chnl);
-	pr_debug("CAIF: %s(): NET flowctrl func called flow: %s\n",
-		__func__,
+	pr_debug("NET flowctrl func called flow: %s\n",
 		flow == CAIF_CTRLCMD_FLOW_ON_IND ? "ON" :
 		flow == CAIF_CTRLCMD_INIT_RSP ? "INIT" :
 		flow == CAIF_CTRLCMD_FLOW_OFF_IND ? "OFF" :
@@ -196,12 +194,12 @@
 	priv = netdev_priv(dev);
 
 	if (skb->len > priv->netdev->mtu) {
-		pr_warning("CAIF: %s(): Size of skb exceeded MTU\n", __func__);
+		pr_warn("Size of skb exceeded MTU\n");
 		return -ENOSPC;
 	}
 
 	if (!priv->flowenabled) {
-		pr_debug("CAIF: %s(): dropping packets flow off\n", __func__);
+		pr_debug("dropping packets flow off\n");
 		return NETDEV_TX_BUSY;
 	}
 
@@ -237,7 +235,7 @@
 	ASSERT_RTNL();
 	priv = netdev_priv(dev);
 	if (!priv) {
-		pr_debug("CAIF: %s(): chnl_net_open: no priv\n", __func__);
+		pr_debug("chnl_net_open: no priv\n");
 		return -ENODEV;
 	}
 
@@ -246,18 +244,17 @@
 		result = caif_connect_client(&priv->conn_req, &priv->chnl,
 					&llifindex, &headroom, &tailroom);
 		if (result != 0) {
-				pr_debug("CAIF: %s(): err: "
-					"Unable to register and open device,"
-					" Err:%d\n",
-					__func__,
-					result);
+				pr_debug("err: "
+					 "Unable to register and open device,"
+					 " Err:%d\n",
+					 result);
 				goto error;
 		}
 
 		lldev = dev_get_by_index(dev_net(dev), llifindex);
 
 		if (lldev == NULL) {
-			pr_debug("CAIF: %s(): no interface?\n", __func__);
+			pr_debug("no interface?\n");
 			result = -ENODEV;
 			goto error;
 		}
@@ -279,9 +276,7 @@
 		dev_put(lldev);
 
 		if (mtu < 100) {
-			pr_warning("CAIF: %s(): "
-				"CAIF Interface MTU too small (%d)\n",
-				__func__, mtu);
+			pr_warn("CAIF Interface MTU too small (%d)\n", mtu);
 			result = -ENODEV;
 			goto error;
 		}
@@ -296,33 +291,32 @@
 	rtnl_lock();
 
 	if (result == -ERESTARTSYS) {
-		pr_debug("CAIF: %s(): wait_event_interruptible"
-			 " woken by a signal\n", __func__);
+		pr_debug("wait_event_interruptible woken by a signal\n");
 		result = -ERESTARTSYS;
 		goto error;
 	}
 
 	if (result == 0) {
-		pr_debug("CAIF: %s(): connect timeout\n", __func__);
+		pr_debug("connect timeout\n");
 		caif_disconnect_client(&priv->chnl);
 		priv->state = CAIF_DISCONNECTED;
-		pr_debug("CAIF: %s(): state disconnected\n", __func__);
+		pr_debug("state disconnected\n");
 		result = -ETIMEDOUT;
 		goto error;
 	}
 
 	if (priv->state != CAIF_CONNECTED) {
-		pr_debug("CAIF: %s(): connect failed\n", __func__);
+		pr_debug("connect failed\n");
 		result = -ECONNREFUSED;
 		goto error;
 	}
-	pr_debug("CAIF: %s(): CAIF Netdevice connected\n", __func__);
+	pr_debug("CAIF Netdevice connected\n");
 	return 0;
 
 error:
 	caif_disconnect_client(&priv->chnl);
 	priv->state = CAIF_DISCONNECTED;
-	pr_debug("CAIF: %s(): state disconnected\n", __func__);
+	pr_debug("state disconnected\n");
 	return result;
 
 }
@@ -413,7 +407,7 @@
 				struct caif_connect_request *conn_req)
 {
 	if (!data) {
-		pr_warning("CAIF: %s: no params data found\n", __func__);
+		pr_warn("no params data found\n");
 		return;
 	}
 	if (data[IFLA_CAIF_IPV4_CONNID])
@@ -442,8 +436,7 @@
 
 	ret = register_netdevice(dev);
 	if (ret)
-		pr_warning("CAIF: %s(): device rtml registration failed\n",
-			   __func__);
+		pr_warn("device rtml registration failed\n");
 	return ret;
 }
 
diff --git a/net/can/raw.c b/net/can/raw.c
index a10e333..e88f610 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -90,23 +90,39 @@
 	can_err_mask_t err_mask;
 };
 
+/*
+ * Return pointer to store the extra msg flags for raw_recvmsg().
+ * We use the space of one unsigned int beyond the 'struct sockaddr_can'
+ * in skb->cb.
+ */
+static inline unsigned int *raw_flags(struct sk_buff *skb)
+{
+	BUILD_BUG_ON(sizeof(skb->cb) <= (sizeof(struct sockaddr_can) +
+					 sizeof(unsigned int)));
+
+	/* return pointer after struct sockaddr_can */
+	return (unsigned int *)(&((struct sockaddr_can *)skb->cb)[1]);
+}
+
 static inline struct raw_sock *raw_sk(const struct sock *sk)
 {
 	return (struct raw_sock *)sk;
 }
 
-static void raw_rcv(struct sk_buff *skb, void *data)
+static void raw_rcv(struct sk_buff *oskb, void *data)
 {
 	struct sock *sk = (struct sock *)data;
 	struct raw_sock *ro = raw_sk(sk);
 	struct sockaddr_can *addr;
+	struct sk_buff *skb;
+	unsigned int *pflags;
 
 	/* check the received tx sock reference */
-	if (!ro->recv_own_msgs && skb->sk == sk)
+	if (!ro->recv_own_msgs && oskb->sk == sk)
 		return;
 
 	/* clone the given skb to be able to enqueue it into the rcv queue */
-	skb = skb_clone(skb, GFP_ATOMIC);
+	skb = skb_clone(oskb, GFP_ATOMIC);
 	if (!skb)
 		return;
 
@@ -123,6 +139,14 @@
 	addr->can_family  = AF_CAN;
 	addr->can_ifindex = skb->dev->ifindex;
 
+	/* add CAN specific message flags for raw_recvmsg() */
+	pflags = raw_flags(skb);
+	*pflags = 0;
+	if (oskb->sk)
+		*pflags |= MSG_DONTROUTE;
+	if (oskb->sk == sk)
+		*pflags |= MSG_CONFIRM;
+
 	if (sock_queue_rcv_skb(sk, skb) < 0)
 		kfree_skb(skb);
 }
@@ -647,12 +671,12 @@
 	err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
 	if (err < 0)
 		goto free_skb;
-	err = sock_tx_timestamp(msg, sk, skb_tx(skb));
+	err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
 	if (err < 0)
 		goto free_skb;
 
 	/* to be able to check the received tx sock reference in raw_rcv() */
-	skb_tx(skb)->prevent_sk_orphan = 1;
+	skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF;
 
 	skb->dev = dev;
 	skb->sk  = sk;
@@ -707,6 +731,9 @@
 		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
 	}
 
+	/* assign the flags that have been recorded in raw_rcv() */
+	msg->msg_flags |= *(raw_flags(skb));
+
 	skb_free_datagram(sk, skb);
 
 	return size;
diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig
new file mode 100644
index 0000000..ad42404
--- /dev/null
+++ b/net/ceph/Kconfig
@@ -0,0 +1,28 @@
+config CEPH_LIB
+        tristate "Ceph core library (EXPERIMENTAL)"
+	depends on INET && EXPERIMENTAL
+	select LIBCRC32C
+	select CRYPTO_AES
+	select CRYPTO
+	default n
+	help
+	  Choose Y or M here to include cephlib, which provides the
+	  common functionality to both the Ceph filesystem and
+	  to the rados block device (rbd).
+
+	  More information at http://ceph.newdream.net/.
+
+	  If unsure, say N.
+
+config CEPH_LIB_PRETTYDEBUG
+	bool "Include file:line in ceph debug output"
+	depends on CEPH_LIB
+	default n
+	help
+	  If you say Y here, debug output will include a filename and
+	  line to aid debugging.  This increases kernel size and slows
+	  execution slightly when debug call sites are enabled (e.g.,
+	  via CONFIG_DYNAMIC_DEBUG).
+
+	  If unsure, say N.
+
diff --git a/net/ceph/Makefile b/net/ceph/Makefile
new file mode 100644
index 0000000..aab1cab
--- /dev/null
+++ b/net/ceph/Makefile
@@ -0,0 +1,37 @@
+#
+# Makefile for CEPH filesystem.
+#
+
+ifneq ($(KERNELRELEASE),)
+
+obj-$(CONFIG_CEPH_LIB) += libceph.o
+
+libceph-objs := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
+	mon_client.o \
+	osd_client.o osdmap.o crush/crush.o crush/mapper.o crush/hash.o \
+	debugfs.o \
+	auth.o auth_none.o \
+	crypto.o armor.o \
+	auth_x.o \
+	ceph_fs.o ceph_strings.o ceph_hash.o \
+	pagevec.o
+
+else
+#Otherwise we were called directly from the command
+# line; invoke the kernel build system.
+
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+default: all
+
+all:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules
+
+modules_install:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules_install
+
+clean:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
+
+endif
diff --git a/fs/ceph/armor.c b/net/ceph/armor.c
similarity index 100%
rename from fs/ceph/armor.c
rename to net/ceph/armor.c
diff --git a/net/ceph/auth.c b/net/ceph/auth.c
new file mode 100644
index 0000000..549c1f4
--- /dev/null
+++ b/net/ceph/auth.c
@@ -0,0 +1,259 @@
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <linux/ceph/types.h>
+#include <linux/ceph/decode.h>
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/messenger.h>
+#include "auth_none.h"
+#include "auth_x.h"
+
+
+/*
+ * get protocol handler
+ */
+static u32 supported_protocols[] = {
+	CEPH_AUTH_NONE,
+	CEPH_AUTH_CEPHX
+};
+
+static int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol)
+{
+	switch (protocol) {
+	case CEPH_AUTH_NONE:
+		return ceph_auth_none_init(ac);
+	case CEPH_AUTH_CEPHX:
+		return ceph_x_init(ac);
+	default:
+		return -ENOENT;
+	}
+}
+
+/*
+ * setup, teardown.
+ */
+struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret)
+{
+	struct ceph_auth_client *ac;
+	int ret;
+
+	dout("auth_init name '%s' secret '%s'\n", name, secret);
+
+	ret = -ENOMEM;
+	ac = kzalloc(sizeof(*ac), GFP_NOFS);
+	if (!ac)
+		goto out;
+
+	ac->negotiating = true;
+	if (name)
+		ac->name = name;
+	else
+		ac->name = CEPH_AUTH_NAME_DEFAULT;
+	dout("auth_init name %s secret %s\n", ac->name, secret);
+	ac->secret = secret;
+	return ac;
+
+out:
+	return ERR_PTR(ret);
+}
+
+void ceph_auth_destroy(struct ceph_auth_client *ac)
+{
+	dout("auth_destroy %p\n", ac);
+	if (ac->ops)
+		ac->ops->destroy(ac);
+	kfree(ac);
+}
+
+/*
+ * Reset occurs when reconnecting to the monitor.
+ */
+void ceph_auth_reset(struct ceph_auth_client *ac)
+{
+	dout("auth_reset %p\n", ac);
+	if (ac->ops && !ac->negotiating)
+		ac->ops->reset(ac);
+	ac->negotiating = true;
+}
+
+int ceph_entity_name_encode(const char *name, void **p, void *end)
+{
+	int len = strlen(name);
+
+	if (*p + 2*sizeof(u32) + len > end)
+		return -ERANGE;
+	ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT);
+	ceph_encode_32(p, len);
+	ceph_encode_copy(p, name, len);
+	return 0;
+}
+
+/*
+ * Initiate protocol negotiation with monitor.  Include entity name
+ * and list supported protocols.
+ */
+int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len)
+{
+	struct ceph_mon_request_header *monhdr = buf;
+	void *p = monhdr + 1, *end = buf + len, *lenp;
+	int i, num;
+	int ret;
+
+	dout("auth_build_hello\n");
+	monhdr->have_version = 0;
+	monhdr->session_mon = cpu_to_le16(-1);
+	monhdr->session_mon_tid = 0;
+
+	ceph_encode_32(&p, 0);  /* no protocol, yet */
+
+	lenp = p;
+	p += sizeof(u32);
+
+	ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
+	ceph_encode_8(&p, 1);
+	num = ARRAY_SIZE(supported_protocols);
+	ceph_encode_32(&p, num);
+	ceph_decode_need(&p, end, num * sizeof(u32), bad);
+	for (i = 0; i < num; i++)
+		ceph_encode_32(&p, supported_protocols[i]);
+
+	ret = ceph_entity_name_encode(ac->name, &p, end);
+	if (ret < 0)
+		return ret;
+	ceph_decode_need(&p, end, sizeof(u64), bad);
+	ceph_encode_64(&p, ac->global_id);
+
+	ceph_encode_32(&lenp, p - lenp - sizeof(u32));
+	return p - buf;
+
+bad:
+	return -ERANGE;
+}
+
+static int ceph_build_auth_request(struct ceph_auth_client *ac,
+				   void *msg_buf, size_t msg_len)
+{
+	struct ceph_mon_request_header *monhdr = msg_buf;
+	void *p = monhdr + 1;
+	void *end = msg_buf + msg_len;
+	int ret;
+
+	monhdr->have_version = 0;
+	monhdr->session_mon = cpu_to_le16(-1);
+	monhdr->session_mon_tid = 0;
+
+	ceph_encode_32(&p, ac->protocol);
+
+	ret = ac->ops->build_request(ac, p + sizeof(u32), end);
+	if (ret < 0) {
+		pr_err("error %d building auth method %s request\n", ret,
+		       ac->ops->name);
+		return ret;
+	}
+	dout(" built request %d bytes\n", ret);
+	ceph_encode_32(&p, ret);
+	return p + ret - msg_buf;
+}
+
+/*
+ * Handle auth message from monitor.
+ */
+int ceph_handle_auth_reply(struct ceph_auth_client *ac,
+			   void *buf, size_t len,
+			   void *reply_buf, size_t reply_len)
+{
+	void *p = buf;
+	void *end = buf + len;
+	int protocol;
+	s32 result;
+	u64 global_id;
+	void *payload, *payload_end;
+	int payload_len;
+	char *result_msg;
+	int result_msg_len;
+	int ret = -EINVAL;
+
+	dout("handle_auth_reply %p %p\n", p, end);
+	ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
+	protocol = ceph_decode_32(&p);
+	result = ceph_decode_32(&p);
+	global_id = ceph_decode_64(&p);
+	payload_len = ceph_decode_32(&p);
+	payload = p;
+	p += payload_len;
+	ceph_decode_need(&p, end, sizeof(u32), bad);
+	result_msg_len = ceph_decode_32(&p);
+	result_msg = p;
+	p += result_msg_len;
+	if (p != end)
+		goto bad;
+
+	dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len,
+	     result_msg, global_id, payload_len);
+
+	payload_end = payload + payload_len;
+
+	if (global_id && ac->global_id != global_id) {
+		dout(" set global_id %lld -> %lld\n", ac->global_id, global_id);
+		ac->global_id = global_id;
+	}
+
+	if (ac->negotiating) {
+		/* server does not support our protocols? */
+		if (!protocol && result < 0) {
+			ret = result;
+			goto out;
+		}
+		/* set up (new) protocol handler? */
+		if (ac->protocol && ac->protocol != protocol) {
+			ac->ops->destroy(ac);
+			ac->protocol = 0;
+			ac->ops = NULL;
+		}
+		if (ac->protocol != protocol) {
+			ret = ceph_auth_init_protocol(ac, protocol);
+			if (ret) {
+				pr_err("error %d on auth protocol %d init\n",
+				       ret, protocol);
+				goto out;
+			}
+		}
+
+		ac->negotiating = false;
+	}
+
+	ret = ac->ops->handle_reply(ac, result, payload, payload_end);
+	if (ret == -EAGAIN) {
+		return ceph_build_auth_request(ac, reply_buf, reply_len);
+	} else if (ret) {
+		pr_err("auth method '%s' error %d\n", ac->ops->name, ret);
+		return ret;
+	}
+	return 0;
+
+bad:
+	pr_err("failed to decode auth msg\n");
+out:
+	return ret;
+}
+
+int ceph_build_auth(struct ceph_auth_client *ac,
+		    void *msg_buf, size_t msg_len)
+{
+	if (!ac->protocol)
+		return ceph_auth_build_hello(ac, msg_buf, msg_len);
+	BUG_ON(!ac->ops);
+	if (ac->ops->should_authenticate(ac))
+		return ceph_build_auth_request(ac, msg_buf, msg_len);
+	return 0;
+}
+
+int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
+{
+	if (!ac->ops)
+		return 0;
+	return ac->ops->is_authenticated(ac);
+}
diff --git a/net/ceph/auth_none.c b/net/ceph/auth_none.c
new file mode 100644
index 0000000..214c2bb
--- /dev/null
+++ b/net/ceph/auth_none.c
@@ -0,0 +1,132 @@
+
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+
+#include <linux/ceph/decode.h>
+#include <linux/ceph/auth.h>
+
+#include "auth_none.h"
+
+static void reset(struct ceph_auth_client *ac)
+{
+	struct ceph_auth_none_info *xi = ac->private;
+
+	xi->starting = true;
+	xi->built_authorizer = false;
+}
+
+static void destroy(struct ceph_auth_client *ac)
+{
+	kfree(ac->private);
+	ac->private = NULL;
+}
+
+static int is_authenticated(struct ceph_auth_client *ac)
+{
+	struct ceph_auth_none_info *xi = ac->private;
+
+	return !xi->starting;
+}
+
+static int should_authenticate(struct ceph_auth_client *ac)
+{
+	struct ceph_auth_none_info *xi = ac->private;
+
+	return xi->starting;
+}
+
+/*
+ * the generic auth code decode the global_id, and we carry no actual
+ * authenticate state, so nothing happens here.
+ */
+static int handle_reply(struct ceph_auth_client *ac, int result,
+			void *buf, void *end)
+{
+	struct ceph_auth_none_info *xi = ac->private;
+
+	xi->starting = false;
+	return result;
+}
+
+/*
+ * build an 'authorizer' with our entity_name and global_id.  we can
+ * reuse a single static copy since it is identical for all services
+ * we connect to.
+ */
+static int ceph_auth_none_create_authorizer(
+	struct ceph_auth_client *ac, int peer_type,
+	struct ceph_authorizer **a,
+	void **buf, size_t *len,
+	void **reply_buf, size_t *reply_len)
+{
+	struct ceph_auth_none_info *ai = ac->private;
+	struct ceph_none_authorizer *au = &ai->au;
+	void *p, *end;
+	int ret;
+
+	if (!ai->built_authorizer) {
+		p = au->buf;
+		end = p + sizeof(au->buf);
+		ceph_encode_8(&p, 1);
+		ret = ceph_entity_name_encode(ac->name, &p, end - 8);
+		if (ret < 0)
+			goto bad;
+		ceph_decode_need(&p, end, sizeof(u64), bad2);
+		ceph_encode_64(&p, ac->global_id);
+		au->buf_len = p - (void *)au->buf;
+		ai->built_authorizer = true;
+		dout("built authorizer len %d\n", au->buf_len);
+	}
+
+	*a = (struct ceph_authorizer *)au;
+	*buf = au->buf;
+	*len = au->buf_len;
+	*reply_buf = au->reply_buf;
+	*reply_len = sizeof(au->reply_buf);
+	return 0;
+
+bad2:
+	ret = -ERANGE;
+bad:
+	return ret;
+}
+
+static void ceph_auth_none_destroy_authorizer(struct ceph_auth_client *ac,
+				      struct ceph_authorizer *a)
+{
+	/* nothing to do */
+}
+
+static const struct ceph_auth_client_ops ceph_auth_none_ops = {
+	.name = "none",
+	.reset = reset,
+	.destroy = destroy,
+	.is_authenticated = is_authenticated,
+	.should_authenticate = should_authenticate,
+	.handle_reply = handle_reply,
+	.create_authorizer = ceph_auth_none_create_authorizer,
+	.destroy_authorizer = ceph_auth_none_destroy_authorizer,
+};
+
+int ceph_auth_none_init(struct ceph_auth_client *ac)
+{
+	struct ceph_auth_none_info *xi;
+
+	dout("ceph_auth_none_init %p\n", ac);
+	xi = kzalloc(sizeof(*xi), GFP_NOFS);
+	if (!xi)
+		return -ENOMEM;
+
+	xi->starting = true;
+	xi->built_authorizer = false;
+
+	ac->protocol = CEPH_AUTH_NONE;
+	ac->private = xi;
+	ac->ops = &ceph_auth_none_ops;
+	return 0;
+}
+
diff --git a/net/ceph/auth_none.h b/net/ceph/auth_none.h
new file mode 100644
index 0000000..ed7d088
--- /dev/null
+++ b/net/ceph/auth_none.h
@@ -0,0 +1,29 @@
+#ifndef _FS_CEPH_AUTH_NONE_H
+#define _FS_CEPH_AUTH_NONE_H
+
+#include <linux/slab.h>
+#include <linux/ceph/auth.h>
+
+/*
+ * null security mode.
+ *
+ * we use a single static authorizer that simply encodes our entity name
+ * and global id.
+ */
+
+struct ceph_none_authorizer {
+	char buf[128];
+	int buf_len;
+	char reply_buf[0];
+};
+
+struct ceph_auth_none_info {
+	bool starting;
+	bool built_authorizer;
+	struct ceph_none_authorizer au;   /* we only need one; it's static */
+};
+
+extern int ceph_auth_none_init(struct ceph_auth_client *ac);
+
+#endif
+
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c
new file mode 100644
index 0000000..7fd5dfc
--- /dev/null
+++ b/net/ceph/auth_x.c
@@ -0,0 +1,688 @@
+
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+
+#include <linux/ceph/decode.h>
+#include <linux/ceph/auth.h>
+
+#include "crypto.h"
+#include "auth_x.h"
+#include "auth_x_protocol.h"
+
+#define TEMP_TICKET_BUF_LEN	256
+
+static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);
+
+static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
+{
+	struct ceph_x_info *xi = ac->private;
+	int need;
+
+	ceph_x_validate_tickets(ac, &need);
+	dout("ceph_x_is_authenticated want=%d need=%d have=%d\n",
+	     ac->want_keys, need, xi->have_keys);
+	return (ac->want_keys & xi->have_keys) == ac->want_keys;
+}
+
+static int ceph_x_should_authenticate(struct ceph_auth_client *ac)
+{
+	struct ceph_x_info *xi = ac->private;
+	int need;
+
+	ceph_x_validate_tickets(ac, &need);
+	dout("ceph_x_should_authenticate want=%d need=%d have=%d\n",
+	     ac->want_keys, need, xi->have_keys);
+	return need != 0;
+}
+
+static int ceph_x_encrypt_buflen(int ilen)
+{
+	return sizeof(struct ceph_x_encrypt_header) + ilen + 16 +
+		sizeof(u32);
+}
+
+static int ceph_x_encrypt(struct ceph_crypto_key *secret,
+			  void *ibuf, int ilen, void *obuf, size_t olen)
+{
+	struct ceph_x_encrypt_header head = {
+		.struct_v = 1,
+		.magic = cpu_to_le64(CEPHX_ENC_MAGIC)
+	};
+	size_t len = olen - sizeof(u32);
+	int ret;
+
+	ret = ceph_encrypt2(secret, obuf + sizeof(u32), &len,
+			    &head, sizeof(head), ibuf, ilen);
+	if (ret)
+		return ret;
+	ceph_encode_32(&obuf, len);
+	return len + sizeof(u32);
+}
+
+static int ceph_x_decrypt(struct ceph_crypto_key *secret,
+			  void **p, void *end, void *obuf, size_t olen)
+{
+	struct ceph_x_encrypt_header head;
+	size_t head_len = sizeof(head);
+	int len, ret;
+
+	len = ceph_decode_32(p);
+	if (*p + len > end)
+		return -EINVAL;
+
+	dout("ceph_x_decrypt len %d\n", len);
+	ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen,
+			    *p, len);
+	if (ret)
+		return ret;
+	if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
+		return -EPERM;
+	*p += len;
+	return olen;
+}
+
+/*
+ * get existing (or insert new) ticket handler
+ */
+static struct ceph_x_ticket_handler *
+get_ticket_handler(struct ceph_auth_client *ac, int service)
+{
+	struct ceph_x_ticket_handler *th;
+	struct ceph_x_info *xi = ac->private;
+	struct rb_node *parent = NULL, **p = &xi->ticket_handlers.rb_node;
+
+	while (*p) {
+		parent = *p;
+		th = rb_entry(parent, struct ceph_x_ticket_handler, node);
+		if (service < th->service)
+			p = &(*p)->rb_left;
+		else if (service > th->service)
+			p = &(*p)->rb_right;
+		else
+			return th;
+	}
+
+	/* add it */
+	th = kzalloc(sizeof(*th), GFP_NOFS);
+	if (!th)
+		return ERR_PTR(-ENOMEM);
+	th->service = service;
+	rb_link_node(&th->node, parent, p);
+	rb_insert_color(&th->node, &xi->ticket_handlers);
+	return th;
+}
+
+static void remove_ticket_handler(struct ceph_auth_client *ac,
+				  struct ceph_x_ticket_handler *th)
+{
+	struct ceph_x_info *xi = ac->private;
+
+	dout("remove_ticket_handler %p %d\n", th, th->service);
+	rb_erase(&th->node, &xi->ticket_handlers);
+	ceph_crypto_key_destroy(&th->session_key);
+	if (th->ticket_blob)
+		ceph_buffer_put(th->ticket_blob);
+	kfree(th);
+}
+
+static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
+				    struct ceph_crypto_key *secret,
+				    void *buf, void *end)
+{
+	struct ceph_x_info *xi = ac->private;
+	int num;
+	void *p = buf;
+	int ret;
+	char *dbuf;
+	char *ticket_buf;
+	u8 reply_struct_v;
+
+	dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
+	if (!dbuf)
+		return -ENOMEM;
+
+	ret = -ENOMEM;
+	ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
+	if (!ticket_buf)
+		goto out_dbuf;
+
+	ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
+	reply_struct_v = ceph_decode_8(&p);
+	if (reply_struct_v != 1)
+		goto bad;
+	num = ceph_decode_32(&p);
+	dout("%d tickets\n", num);
+	while (num--) {
+		int type;
+		u8 tkt_struct_v, blob_struct_v;
+		struct ceph_x_ticket_handler *th;
+		void *dp, *dend;
+		int dlen;
+		char is_enc;
+		struct timespec validity;
+		struct ceph_crypto_key old_key;
+		void *tp, *tpend;
+		struct ceph_timespec new_validity;
+		struct ceph_crypto_key new_session_key;
+		struct ceph_buffer *new_ticket_blob;
+		unsigned long new_expires, new_renew_after;
+		u64 new_secret_id;
+
+		ceph_decode_need(&p, end, sizeof(u32) + 1, bad);
+
+		type = ceph_decode_32(&p);
+		dout(" ticket type %d %s\n", type, ceph_entity_type_name(type));
+
+		tkt_struct_v = ceph_decode_8(&p);
+		if (tkt_struct_v != 1)
+			goto bad;
+
+		th = get_ticket_handler(ac, type);
+		if (IS_ERR(th)) {
+			ret = PTR_ERR(th);
+			goto out;
+		}
+
+		/* blob for me */
+		dlen = ceph_x_decrypt(secret, &p, end, dbuf,
+				      TEMP_TICKET_BUF_LEN);
+		if (dlen <= 0) {
+			ret = dlen;
+			goto out;
+		}
+		dout(" decrypted %d bytes\n", dlen);
+		dend = dbuf + dlen;
+		dp = dbuf;
+
+		tkt_struct_v = ceph_decode_8(&dp);
+		if (tkt_struct_v != 1)
+			goto bad;
+
+		memcpy(&old_key, &th->session_key, sizeof(old_key));
+		ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
+		if (ret)
+			goto out;
+
+		ceph_decode_copy(&dp, &new_validity, sizeof(new_validity));
+		ceph_decode_timespec(&validity, &new_validity);
+		new_expires = get_seconds() + validity.tv_sec;
+		new_renew_after = new_expires - (validity.tv_sec / 4);
+		dout(" expires=%lu renew_after=%lu\n", new_expires,
+		     new_renew_after);
+
+		/* ticket blob for service */
+		ceph_decode_8_safe(&p, end, is_enc, bad);
+		tp = ticket_buf;
+		if (is_enc) {
+			/* encrypted */
+			dout(" encrypted ticket\n");
+			dlen = ceph_x_decrypt(&old_key, &p, end, ticket_buf,
+					      TEMP_TICKET_BUF_LEN);
+			if (dlen < 0) {
+				ret = dlen;
+				goto out;
+			}
+			dlen = ceph_decode_32(&tp);
+		} else {
+			/* unencrypted */
+			ceph_decode_32_safe(&p, end, dlen, bad);
+			ceph_decode_need(&p, end, dlen, bad);
+			ceph_decode_copy(&p, ticket_buf, dlen);
+		}
+		tpend = tp + dlen;
+		dout(" ticket blob is %d bytes\n", dlen);
+		ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
+		blob_struct_v = ceph_decode_8(&tp);
+		new_secret_id = ceph_decode_64(&tp);
+		ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
+		if (ret)
+			goto out;
+
+		/* all is well, update our ticket */
+		ceph_crypto_key_destroy(&th->session_key);
+		if (th->ticket_blob)
+			ceph_buffer_put(th->ticket_blob);
+		th->session_key = new_session_key;
+		th->ticket_blob = new_ticket_blob;
+		th->validity = new_validity;
+		th->secret_id = new_secret_id;
+		th->expires = new_expires;
+		th->renew_after = new_renew_after;
+		dout(" got ticket service %d (%s) secret_id %lld len %d\n",
+		     type, ceph_entity_type_name(type), th->secret_id,
+		     (int)th->ticket_blob->vec.iov_len);
+		xi->have_keys |= th->service;
+	}
+
+	ret = 0;
+out:
+	kfree(ticket_buf);
+out_dbuf:
+	kfree(dbuf);
+	return ret;
+
+bad:
+	ret = -EINVAL;
+	goto out;
+}
+
+static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
+				   struct ceph_x_ticket_handler *th,
+				   struct ceph_x_authorizer *au)
+{
+	int maxlen;
+	struct ceph_x_authorize_a *msg_a;
+	struct ceph_x_authorize_b msg_b;
+	void *p, *end;
+	int ret;
+	int ticket_blob_len =
+		(th->ticket_blob ? th->ticket_blob->vec.iov_len : 0);
+
+	dout("build_authorizer for %s %p\n",
+	     ceph_entity_type_name(th->service), au);
+
+	maxlen = sizeof(*msg_a) + sizeof(msg_b) +
+		ceph_x_encrypt_buflen(ticket_blob_len);
+	dout("  need len %d\n", maxlen);
+	if (au->buf && au->buf->alloc_len < maxlen) {
+		ceph_buffer_put(au->buf);
+		au->buf = NULL;
+	}
+	if (!au->buf) {
+		au->buf = ceph_buffer_new(maxlen, GFP_NOFS);
+		if (!au->buf)
+			return -ENOMEM;
+	}
+	au->service = th->service;
+
+	msg_a = au->buf->vec.iov_base;
+	msg_a->struct_v = 1;
+	msg_a->global_id = cpu_to_le64(ac->global_id);
+	msg_a->service_id = cpu_to_le32(th->service);
+	msg_a->ticket_blob.struct_v = 1;
+	msg_a->ticket_blob.secret_id = cpu_to_le64(th->secret_id);
+	msg_a->ticket_blob.blob_len = cpu_to_le32(ticket_blob_len);
+	if (ticket_blob_len) {
+		memcpy(msg_a->ticket_blob.blob, th->ticket_blob->vec.iov_base,
+		       th->ticket_blob->vec.iov_len);
+	}
+	dout(" th %p secret_id %lld %lld\n", th, th->secret_id,
+	     le64_to_cpu(msg_a->ticket_blob.secret_id));
+
+	p = msg_a + 1;
+	p += ticket_blob_len;
+	end = au->buf->vec.iov_base + au->buf->vec.iov_len;
+
+	get_random_bytes(&au->nonce, sizeof(au->nonce));
+	msg_b.struct_v = 1;
+	msg_b.nonce = cpu_to_le64(au->nonce);
+	ret = ceph_x_encrypt(&th->session_key, &msg_b, sizeof(msg_b),
+			     p, end - p);
+	if (ret < 0)
+		goto out_buf;
+	p += ret;
+	au->buf->vec.iov_len = p - au->buf->vec.iov_base;
+	dout(" built authorizer nonce %llx len %d\n", au->nonce,
+	     (int)au->buf->vec.iov_len);
+	BUG_ON(au->buf->vec.iov_len > maxlen);
+	return 0;
+
+out_buf:
+	ceph_buffer_put(au->buf);
+	au->buf = NULL;
+	return ret;
+}
+
+static int ceph_x_encode_ticket(struct ceph_x_ticket_handler *th,
+				void **p, void *end)
+{
+	ceph_decode_need(p, end, 1 + sizeof(u64), bad);
+	ceph_encode_8(p, 1);
+	ceph_encode_64(p, th->secret_id);
+	if (th->ticket_blob) {
+		const char *buf = th->ticket_blob->vec.iov_base;
+		u32 len = th->ticket_blob->vec.iov_len;
+
+		ceph_encode_32_safe(p, end, len, bad);
+		ceph_encode_copy_safe(p, end, buf, len, bad);
+	} else {
+		ceph_encode_32_safe(p, end, 0, bad);
+	}
+
+	return 0;
+bad:
+	return -ERANGE;
+}
+
+static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed)
+{
+	int want = ac->want_keys;
+	struct ceph_x_info *xi = ac->private;
+	int service;
+
+	*pneed = ac->want_keys & ~(xi->have_keys);
+
+	for (service = 1; service <= want; service <<= 1) {
+		struct ceph_x_ticket_handler *th;
+
+		if (!(ac->want_keys & service))
+			continue;
+
+		if (*pneed & service)
+			continue;
+
+		th = get_ticket_handler(ac, service);
+
+		if (IS_ERR(th)) {
+			*pneed |= service;
+			continue;
+		}
+
+		if (get_seconds() >= th->renew_after)
+			*pneed |= service;
+		if (get_seconds() >= th->expires)
+			xi->have_keys &= ~service;
+	}
+}
+
+
+static int ceph_x_build_request(struct ceph_auth_client *ac,
+				void *buf, void *end)
+{
+	struct ceph_x_info *xi = ac->private;
+	int need;
+	struct ceph_x_request_header *head = buf;
+	int ret;
+	struct ceph_x_ticket_handler *th =
+		get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH);
+
+	if (IS_ERR(th))
+		return PTR_ERR(th);
+
+	ceph_x_validate_tickets(ac, &need);
+
+	dout("build_request want %x have %x need %x\n",
+	     ac->want_keys, xi->have_keys, need);
+
+	if (need & CEPH_ENTITY_TYPE_AUTH) {
+		struct ceph_x_authenticate *auth = (void *)(head + 1);
+		void *p = auth + 1;
+		struct ceph_x_challenge_blob tmp;
+		char tmp_enc[40];
+		u64 *u;
+
+		if (p > end)
+			return -ERANGE;
+
+		dout(" get_auth_session_key\n");
+		head->op = cpu_to_le16(CEPHX_GET_AUTH_SESSION_KEY);
+
+		/* encrypt and hash */
+		get_random_bytes(&auth->client_challenge, sizeof(u64));
+		tmp.client_challenge = auth->client_challenge;
+		tmp.server_challenge = cpu_to_le64(xi->server_challenge);
+		ret = ceph_x_encrypt(&xi->secret, &tmp, sizeof(tmp),
+				     tmp_enc, sizeof(tmp_enc));
+		if (ret < 0)
+			return ret;
+
+		auth->struct_v = 1;
+		auth->key = 0;
+		for (u = (u64 *)tmp_enc; u + 1 <= (u64 *)(tmp_enc + ret); u++)
+			auth->key ^= *(__le64 *)u;
+		dout(" server_challenge %llx client_challenge %llx key %llx\n",
+		     xi->server_challenge, le64_to_cpu(auth->client_challenge),
+		     le64_to_cpu(auth->key));
+
+		/* now encode the old ticket if exists */
+		ret = ceph_x_encode_ticket(th, &p, end);
+		if (ret < 0)
+			return ret;
+
+		return p - buf;
+	}
+
+	if (need) {
+		void *p = head + 1;
+		struct ceph_x_service_ticket_request *req;
+
+		if (p > end)
+			return -ERANGE;
+		head->op = cpu_to_le16(CEPHX_GET_PRINCIPAL_SESSION_KEY);
+
+		ret = ceph_x_build_authorizer(ac, th, &xi->auth_authorizer);
+		if (ret)
+			return ret;
+		ceph_encode_copy(&p, xi->auth_authorizer.buf->vec.iov_base,
+				 xi->auth_authorizer.buf->vec.iov_len);
+
+		req = p;
+		req->keys = cpu_to_le32(need);
+		p += sizeof(*req);
+		return p - buf;
+	}
+
+	return 0;
+}
+
+static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result,
+			       void *buf, void *end)
+{
+	struct ceph_x_info *xi = ac->private;
+	struct ceph_x_reply_header *head = buf;
+	struct ceph_x_ticket_handler *th;
+	int len = end - buf;
+	int op;
+	int ret;
+
+	if (result)
+		return result;  /* XXX hmm? */
+
+	if (xi->starting) {
+		/* it's a hello */
+		struct ceph_x_server_challenge *sc = buf;
+
+		if (len != sizeof(*sc))
+			return -EINVAL;
+		xi->server_challenge = le64_to_cpu(sc->server_challenge);
+		dout("handle_reply got server challenge %llx\n",
+		     xi->server_challenge);
+		xi->starting = false;
+		xi->have_keys &= ~CEPH_ENTITY_TYPE_AUTH;
+		return -EAGAIN;
+	}
+
+	op = le16_to_cpu(head->op);
+	result = le32_to_cpu(head->result);
+	dout("handle_reply op %d result %d\n", op, result);
+	switch (op) {
+	case CEPHX_GET_AUTH_SESSION_KEY:
+		/* verify auth key */
+		ret = ceph_x_proc_ticket_reply(ac, &xi->secret,
+					       buf + sizeof(*head), end);
+		break;
+
+	case CEPHX_GET_PRINCIPAL_SESSION_KEY:
+		th = get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH);
+		if (IS_ERR(th))
+			return PTR_ERR(th);
+		ret = ceph_x_proc_ticket_reply(ac, &th->session_key,
+					       buf + sizeof(*head), end);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	if (ret)
+		return ret;
+	if (ac->want_keys == xi->have_keys)
+		return 0;
+	return -EAGAIN;
+}
+
+static int ceph_x_create_authorizer(
+	struct ceph_auth_client *ac, int peer_type,
+	struct ceph_authorizer **a,
+	void **buf, size_t *len,
+	void **reply_buf, size_t *reply_len)
+{
+	struct ceph_x_authorizer *au;
+	struct ceph_x_ticket_handler *th;
+	int ret;
+
+	th = get_ticket_handler(ac, peer_type);
+	if (IS_ERR(th))
+		return PTR_ERR(th);
+
+	au = kzalloc(sizeof(*au), GFP_NOFS);
+	if (!au)
+		return -ENOMEM;
+
+	ret = ceph_x_build_authorizer(ac, th, au);
+	if (ret) {
+		kfree(au);
+		return ret;
+	}
+
+	*a = (struct ceph_authorizer *)au;
+	*buf = au->buf->vec.iov_base;
+	*len = au->buf->vec.iov_len;
+	*reply_buf = au->reply_buf;
+	*reply_len = sizeof(au->reply_buf);
+	return 0;
+}
+
+static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
+					  struct ceph_authorizer *a, size_t len)
+{
+	struct ceph_x_authorizer *au = (void *)a;
+	struct ceph_x_ticket_handler *th;
+	int ret = 0;
+	struct ceph_x_authorize_reply reply;
+	void *p = au->reply_buf;
+	void *end = p + sizeof(au->reply_buf);
+
+	th = get_ticket_handler(ac, au->service);
+	if (IS_ERR(th))
+		return PTR_ERR(th);
+	ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply));
+	if (ret < 0)
+		return ret;
+	if (ret != sizeof(reply))
+		return -EPERM;
+
+	if (au->nonce + 1 != le64_to_cpu(reply.nonce_plus_one))
+		ret = -EPERM;
+	else
+		ret = 0;
+	dout("verify_authorizer_reply nonce %llx got %llx ret %d\n",
+	     au->nonce, le64_to_cpu(reply.nonce_plus_one), ret);
+	return ret;
+}
+
+static void ceph_x_destroy_authorizer(struct ceph_auth_client *ac,
+				      struct ceph_authorizer *a)
+{
+	struct ceph_x_authorizer *au = (void *)a;
+
+	ceph_buffer_put(au->buf);
+	kfree(au);
+}
+
+
+static void ceph_x_reset(struct ceph_auth_client *ac)
+{
+	struct ceph_x_info *xi = ac->private;
+
+	dout("reset\n");
+	xi->starting = true;
+	xi->server_challenge = 0;
+}
+
+static void ceph_x_destroy(struct ceph_auth_client *ac)
+{
+	struct ceph_x_info *xi = ac->private;
+	struct rb_node *p;
+
+	dout("ceph_x_destroy %p\n", ac);
+	ceph_crypto_key_destroy(&xi->secret);
+
+	while ((p = rb_first(&xi->ticket_handlers)) != NULL) {
+		struct ceph_x_ticket_handler *th =
+			rb_entry(p, struct ceph_x_ticket_handler, node);
+		remove_ticket_handler(ac, th);
+	}
+
+	if (xi->auth_authorizer.buf)
+		ceph_buffer_put(xi->auth_authorizer.buf);
+
+	kfree(ac->private);
+	ac->private = NULL;
+}
+
+static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac,
+				   int peer_type)
+{
+	struct ceph_x_ticket_handler *th;
+
+	th = get_ticket_handler(ac, peer_type);
+	if (!IS_ERR(th))
+		remove_ticket_handler(ac, th);
+}
+
+
+static const struct ceph_auth_client_ops ceph_x_ops = {
+	.name = "x",
+	.is_authenticated = ceph_x_is_authenticated,
+	.should_authenticate = ceph_x_should_authenticate,
+	.build_request = ceph_x_build_request,
+	.handle_reply = ceph_x_handle_reply,
+	.create_authorizer = ceph_x_create_authorizer,
+	.verify_authorizer_reply = ceph_x_verify_authorizer_reply,
+	.destroy_authorizer = ceph_x_destroy_authorizer,
+	.invalidate_authorizer = ceph_x_invalidate_authorizer,
+	.reset =  ceph_x_reset,
+	.destroy = ceph_x_destroy,
+};
+
+
+int ceph_x_init(struct ceph_auth_client *ac)
+{
+	struct ceph_x_info *xi;
+	int ret;
+
+	dout("ceph_x_init %p\n", ac);
+	ret = -ENOMEM;
+	xi = kzalloc(sizeof(*xi), GFP_NOFS);
+	if (!xi)
+		goto out;
+
+	ret = -EINVAL;
+	if (!ac->secret) {
+		pr_err("no secret set (for auth_x protocol)\n");
+		goto out_nomem;
+	}
+
+	ret = ceph_crypto_key_unarmor(&xi->secret, ac->secret);
+	if (ret)
+		goto out_nomem;
+
+	xi->starting = true;
+	xi->ticket_handlers = RB_ROOT;
+
+	ac->protocol = CEPH_AUTH_CEPHX;
+	ac->private = xi;
+	ac->ops = &ceph_x_ops;
+	return 0;
+
+out_nomem:
+	kfree(xi);
+out:
+	return ret;
+}
+
+
diff --git a/net/ceph/auth_x.h b/net/ceph/auth_x.h
new file mode 100644
index 0000000..e02da7a
--- /dev/null
+++ b/net/ceph/auth_x.h
@@ -0,0 +1,50 @@
+#ifndef _FS_CEPH_AUTH_X_H
+#define _FS_CEPH_AUTH_X_H
+
+#include <linux/rbtree.h>
+
+#include <linux/ceph/auth.h>
+
+#include "crypto.h"
+#include "auth_x_protocol.h"
+
+/*
+ * Handle ticket for a single service.
+ */
+struct ceph_x_ticket_handler {
+	struct rb_node node;
+	unsigned service;
+
+	struct ceph_crypto_key session_key;
+	struct ceph_timespec validity;
+
+	u64 secret_id;
+	struct ceph_buffer *ticket_blob;
+
+	unsigned long renew_after, expires;
+};
+
+
+struct ceph_x_authorizer {
+	struct ceph_buffer *buf;
+	unsigned service;
+	u64 nonce;
+	char reply_buf[128];  /* big enough for encrypted blob */
+};
+
+struct ceph_x_info {
+	struct ceph_crypto_key secret;
+
+	bool starting;
+	u64 server_challenge;
+
+	unsigned have_keys;
+	struct rb_root ticket_handlers;
+
+	struct ceph_x_authorizer auth_authorizer;
+};
+
+extern int ceph_x_init(struct ceph_auth_client *ac);
+
+#endif
+
diff --git a/fs/ceph/auth_x_protocol.h b/net/ceph/auth_x_protocol.h
similarity index 100%
rename from fs/ceph/auth_x_protocol.h
rename to net/ceph/auth_x_protocol.h
diff --git a/net/ceph/buffer.c b/net/ceph/buffer.c
new file mode 100644
index 0000000..53d8abf
--- /dev/null
+++ b/net/ceph/buffer.c
@@ -0,0 +1,68 @@
+
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/ceph/buffer.h>
+#include <linux/ceph/decode.h>
+
+struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
+{
+	struct ceph_buffer *b;
+
+	b = kmalloc(sizeof(*b), gfp);
+	if (!b)
+		return NULL;
+
+	b->vec.iov_base = kmalloc(len, gfp | __GFP_NOWARN);
+	if (b->vec.iov_base) {
+		b->is_vmalloc = false;
+	} else {
+		b->vec.iov_base = __vmalloc(len, gfp, PAGE_KERNEL);
+		if (!b->vec.iov_base) {
+			kfree(b);
+			return NULL;
+		}
+		b->is_vmalloc = true;
+	}
+
+	kref_init(&b->kref);
+	b->alloc_len = len;
+	b->vec.iov_len = len;
+	dout("buffer_new %p\n", b);
+	return b;
+}
+EXPORT_SYMBOL(ceph_buffer_new);
+
+void ceph_buffer_release(struct kref *kref)
+{
+	struct ceph_buffer *b = container_of(kref, struct ceph_buffer, kref);
+
+	dout("buffer_release %p\n", b);
+	if (b->vec.iov_base) {
+		if (b->is_vmalloc)
+			vfree(b->vec.iov_base);
+		else
+			kfree(b->vec.iov_base);
+	}
+	kfree(b);
+}
+EXPORT_SYMBOL(ceph_buffer_release);
+
+int ceph_decode_buffer(struct ceph_buffer **b, void **p, void *end)
+{
+	size_t len;
+
+	ceph_decode_need(p, end, sizeof(u32), bad);
+	len = ceph_decode_32(p);
+	dout("decode_buffer len %d\n", (int)len);
+	ceph_decode_need(p, end, len, bad);
+	*b = ceph_buffer_new(len, GFP_NOFS);
+	if (!*b)
+		return -ENOMEM;
+	ceph_decode_copy(p, (*b)->vec.iov_base, len);
+	return 0;
+bad:
+	return -EINVAL;
+}
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
new file mode 100644
index 0000000..f3e4a13
--- /dev/null
+++ b/net/ceph/ceph_common.c
@@ -0,0 +1,529 @@
+
+#include <linux/ceph/ceph_debug.h>
+#include <linux/backing-dev.h>
+#include <linux/ctype.h>
+#include <linux/fs.h>
+#include <linux/inet.h>
+#include <linux/in6.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+#include <linux/parser.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/statfs.h>
+#include <linux/string.h>
+
+
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/debugfs.h>
+#include <linux/ceph/decode.h>
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/auth.h>
+
+
+
+/*
+ * find filename portion of a path (/foo/bar/baz -> baz)
+ */
+const char *ceph_file_part(const char *s, int len)
+{
+	const char *e = s + len;
+
+	while (e != s && *(e-1) != '/')
+		e--;
+	return e;
+}
+EXPORT_SYMBOL(ceph_file_part);
+
+const char *ceph_msg_type_name(int type)
+{
+	switch (type) {
+	case CEPH_MSG_SHUTDOWN: return "shutdown";
+	case CEPH_MSG_PING: return "ping";
+	case CEPH_MSG_AUTH: return "auth";
+	case CEPH_MSG_AUTH_REPLY: return "auth_reply";
+	case CEPH_MSG_MON_MAP: return "mon_map";
+	case CEPH_MSG_MON_GET_MAP: return "mon_get_map";
+	case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe";
+	case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack";
+	case CEPH_MSG_STATFS: return "statfs";
+	case CEPH_MSG_STATFS_REPLY: return "statfs_reply";
+	case CEPH_MSG_MDS_MAP: return "mds_map";
+	case CEPH_MSG_CLIENT_SESSION: return "client_session";
+	case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect";
+	case CEPH_MSG_CLIENT_REQUEST: return "client_request";
+	case CEPH_MSG_CLIENT_REQUEST_FORWARD: return "client_request_forward";
+	case CEPH_MSG_CLIENT_REPLY: return "client_reply";
+	case CEPH_MSG_CLIENT_CAPS: return "client_caps";
+	case CEPH_MSG_CLIENT_CAPRELEASE: return "client_cap_release";
+	case CEPH_MSG_CLIENT_SNAP: return "client_snap";
+	case CEPH_MSG_CLIENT_LEASE: return "client_lease";
+	case CEPH_MSG_OSD_MAP: return "osd_map";
+	case CEPH_MSG_OSD_OP: return "osd_op";
+	case CEPH_MSG_OSD_OPREPLY: return "osd_opreply";
+	default: return "unknown";
+	}
+}
+EXPORT_SYMBOL(ceph_msg_type_name);
+
+/*
+ * Initially learn our fsid, or verify an fsid matches.
+ */
+int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
+{
+	if (client->have_fsid) {
+		if (ceph_fsid_compare(&client->fsid, fsid)) {
+			pr_err("bad fsid, had %pU got %pU",
+			       &client->fsid, fsid);
+			return -1;
+		}
+	} else {
+		pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);
+		memcpy(&client->fsid, fsid, sizeof(*fsid));
+		ceph_debugfs_client_init(client);
+		client->have_fsid = true;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(ceph_check_fsid);
+
+static int strcmp_null(const char *s1, const char *s2)
+{
+	if (!s1 && !s2)
+		return 0;
+	if (s1 && !s2)
+		return -1;
+	if (!s1 && s2)
+		return 1;
+	return strcmp(s1, s2);
+}
+
+int ceph_compare_options(struct ceph_options *new_opt,
+			 struct ceph_client *client)
+{
+	struct ceph_options *opt1 = new_opt;
+	struct ceph_options *opt2 = client->options;
+	int ofs = offsetof(struct ceph_options, mon_addr);
+	int i;
+	int ret;
+
+	ret = memcmp(opt1, opt2, ofs);
+	if (ret)
+		return ret;
+
+	ret = strcmp_null(opt1->name, opt2->name);
+	if (ret)
+		return ret;
+
+	ret = strcmp_null(opt1->secret, opt2->secret);
+	if (ret)
+		return ret;
+
+	/* any matching mon ip implies a match */
+	for (i = 0; i < opt1->num_mon; i++) {
+		if (ceph_monmap_contains(client->monc.monmap,
+				 &opt1->mon_addr[i]))
+			return 0;
+	}
+	return -1;
+}
+EXPORT_SYMBOL(ceph_compare_options);
+
+
+static int parse_fsid(const char *str, struct ceph_fsid *fsid)
+{
+	int i = 0;
+	char tmp[3];
+	int err = -EINVAL;
+	int d;
+
+	dout("parse_fsid '%s'\n", str);
+	tmp[2] = 0;
+	while (*str && i < 16) {
+		if (ispunct(*str)) {
+			str++;
+			continue;
+		}
+		if (!isxdigit(str[0]) || !isxdigit(str[1]))
+			break;
+		tmp[0] = str[0];
+		tmp[1] = str[1];
+		if (sscanf(tmp, "%x", &d) < 1)
+			break;
+		fsid->fsid[i] = d & 0xff;
+		i++;
+		str += 2;
+	}
+
+	if (i == 16)
+		err = 0;
+	dout("parse_fsid ret %d got fsid %pU", err, fsid);
+	return err;
+}
+
+/*
+ * ceph options
+ */
+enum {
+	Opt_osdtimeout,
+	Opt_osdkeepalivetimeout,
+	Opt_mount_timeout,
+	Opt_osd_idle_ttl,
+	Opt_last_int,
+	/* int args above */
+	Opt_fsid,
+	Opt_name,
+	Opt_secret,
+	Opt_ip,
+	Opt_last_string,
+	/* string args above */
+	Opt_noshare,
+	Opt_nocrc,
+};
+
+static match_table_t opt_tokens = {
+	{Opt_osdtimeout, "osdtimeout=%d"},
+	{Opt_osdkeepalivetimeout, "osdkeepalive=%d"},
+	{Opt_mount_timeout, "mount_timeout=%d"},
+	{Opt_osd_idle_ttl, "osd_idle_ttl=%d"},
+	/* int args above */
+	{Opt_fsid, "fsid=%s"},
+	{Opt_name, "name=%s"},
+	{Opt_secret, "secret=%s"},
+	{Opt_ip, "ip=%s"},
+	/* string args above */
+	{Opt_noshare, "noshare"},
+	{Opt_nocrc, "nocrc"},
+	{-1, NULL}
+};
+
+void ceph_destroy_options(struct ceph_options *opt)
+{
+	dout("destroy_options %p\n", opt);
+	kfree(opt->name);
+	kfree(opt->secret);
+	kfree(opt);
+}
+EXPORT_SYMBOL(ceph_destroy_options);
+
+int ceph_parse_options(struct ceph_options **popt, char *options,
+		       const char *dev_name, const char *dev_name_end,
+		       int (*parse_extra_token)(char *c, void *private),
+		       void *private)
+{
+	struct ceph_options *opt;
+	const char *c;
+	int err = -ENOMEM;
+	substring_t argstr[MAX_OPT_ARGS];
+
+	opt = kzalloc(sizeof(*opt), GFP_KERNEL);
+	if (!opt)
+		return err;
+	opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr),
+				GFP_KERNEL);
+	if (!opt->mon_addr)
+		goto out;
+
+	dout("parse_options %p options '%s' dev_name '%s'\n", opt, options,
+	     dev_name);
+
+	/* start with defaults */
+	opt->flags = CEPH_OPT_DEFAULT;
+	opt->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT;
+	opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
+	opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */
+	opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;   /* seconds */
+
+	/* get mon ip(s) */
+	/* ip1[:port1][,ip2[:port2]...] */
+	err = ceph_parse_ips(dev_name, dev_name_end, opt->mon_addr,
+			     CEPH_MAX_MON, &opt->num_mon);
+	if (err < 0)
+		goto out;
+
+	/* parse mount options */
+	while ((c = strsep(&options, ",")) != NULL) {
+		int token, intval, ret;
+		if (!*c)
+			continue;
+		err = -EINVAL;
+		token = match_token((char *)c, opt_tokens, argstr);
+		if (token < 0 && parse_extra_token) {
+			/* extra? */
+			err = parse_extra_token((char *)c, private);
+			if (err < 0) {
+				pr_err("bad option at '%s'\n", c);
+				goto out;
+			}
+			continue;
+		}
+		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);
+				continue;
+			}
+			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_ip:
+			err = ceph_parse_ips(argstr[0].from,
+					     argstr[0].to,
+					     &opt->my_addr,
+					     1, NULL);
+			if (err < 0)
+				goto out;
+			opt->flags |= CEPH_OPT_MYIP;
+			break;
+
+		case Opt_fsid:
+			err = parse_fsid(argstr[0].from, &opt->fsid);
+			if (err == 0)
+				opt->flags |= CEPH_OPT_FSID;
+			break;
+		case Opt_name:
+			opt->name = kstrndup(argstr[0].from,
+					      argstr[0].to-argstr[0].from,
+					      GFP_KERNEL);
+			break;
+		case Opt_secret:
+			opt->secret = kstrndup(argstr[0].from,
+						argstr[0].to-argstr[0].from,
+						GFP_KERNEL);
+			break;
+
+			/* misc */
+		case Opt_osdtimeout:
+			opt->osd_timeout = intval;
+			break;
+		case Opt_osdkeepalivetimeout:
+			opt->osd_keepalive_timeout = intval;
+			break;
+		case Opt_osd_idle_ttl:
+			opt->osd_idle_ttl = intval;
+			break;
+		case Opt_mount_timeout:
+			opt->mount_timeout = intval;
+			break;
+
+		case Opt_noshare:
+			opt->flags |= CEPH_OPT_NOSHARE;
+			break;
+
+		case Opt_nocrc:
+			opt->flags |= CEPH_OPT_NOCRC;
+			break;
+
+		default:
+			BUG_ON(token);
+		}
+	}
+
+	/* success */
+	*popt = opt;
+	return 0;
+
+out:
+	ceph_destroy_options(opt);
+	return err;
+}
+EXPORT_SYMBOL(ceph_parse_options);
+
+u64 ceph_client_id(struct ceph_client *client)
+{
+	return client->monc.auth->global_id;
+}
+EXPORT_SYMBOL(ceph_client_id);
+
+/*
+ * create a fresh client instance
+ */
+struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private)
+{
+	struct ceph_client *client;
+	int err = -ENOMEM;
+
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (client == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	client->private = private;
+	client->options = opt;
+
+	mutex_init(&client->mount_mutex);
+	init_waitqueue_head(&client->auth_wq);
+	client->auth_err = 0;
+
+	client->extra_mon_dispatch = NULL;
+	client->supported_features = CEPH_FEATURE_SUPPORTED_DEFAULT;
+	client->required_features = CEPH_FEATURE_REQUIRED_DEFAULT;
+
+	client->msgr = NULL;
+
+	/* subsystems */
+	err = ceph_monc_init(&client->monc, client);
+	if (err < 0)
+		goto fail;
+	err = ceph_osdc_init(&client->osdc, client);
+	if (err < 0)
+		goto fail_monc;
+
+	return client;
+
+fail_monc:
+	ceph_monc_stop(&client->monc);
+fail:
+	kfree(client);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(ceph_create_client);
+
+void ceph_destroy_client(struct ceph_client *client)
+{
+	dout("destroy_client %p\n", client);
+
+	/* unmount */
+	ceph_osdc_stop(&client->osdc);
+
+	/*
+	 * make sure mds and osd connections close out before destroying
+	 * the auth module, which is needed to free those connections'
+	 * ceph_authorizers.
+	 */
+	ceph_msgr_flush();
+
+	ceph_monc_stop(&client->monc);
+
+	ceph_debugfs_client_cleanup(client);
+
+	if (client->msgr)
+		ceph_messenger_destroy(client->msgr);
+
+	ceph_destroy_options(client->options);
+
+	kfree(client);
+	dout("destroy_client %p done\n", client);
+}
+EXPORT_SYMBOL(ceph_destroy_client);
+
+/*
+ * true if we have the mon map (and have thus joined the cluster)
+ */
+static int have_mon_and_osd_map(struct ceph_client *client)
+{
+	return client->monc.monmap && client->monc.monmap->epoch &&
+	       client->osdc.osdmap && client->osdc.osdmap->epoch;
+}
+
+/*
+ * mount: join the ceph cluster, and open root directory.
+ */
+int __ceph_open_session(struct ceph_client *client, unsigned long started)
+{
+	struct ceph_entity_addr *myaddr = NULL;
+	int err;
+	unsigned long timeout = client->options->mount_timeout * HZ;
+
+	/* initialize the messenger */
+	if (client->msgr == NULL) {
+		if (ceph_test_opt(client, MYIP))
+			myaddr = &client->options->my_addr;
+		client->msgr = ceph_messenger_create(myaddr,
+					client->supported_features,
+					client->required_features);
+		if (IS_ERR(client->msgr)) {
+			client->msgr = NULL;
+			return PTR_ERR(client->msgr);
+		}
+		client->msgr->nocrc = ceph_test_opt(client, NOCRC);
+	}
+
+	/* open session, and wait for mon and osd maps */
+	err = ceph_monc_open_session(&client->monc);
+	if (err < 0)
+		return err;
+
+	while (!have_mon_and_osd_map(client)) {
+		err = -EIO;
+		if (timeout && time_after_eq(jiffies, started + timeout))
+			return err;
+
+		/* wait */
+		dout("mount waiting for mon_map\n");
+		err = wait_event_interruptible_timeout(client->auth_wq,
+			have_mon_and_osd_map(client) || (client->auth_err < 0),
+			timeout);
+		if (err == -EINTR || err == -ERESTARTSYS)
+			return err;
+		if (client->auth_err < 0)
+			return client->auth_err;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(__ceph_open_session);
+
+
+int ceph_open_session(struct ceph_client *client)
+{
+	int ret;
+	unsigned long started = jiffies;  /* note the start time */
+
+	dout("open_session start\n");
+	mutex_lock(&client->mount_mutex);
+
+	ret = __ceph_open_session(client, started);
+
+	mutex_unlock(&client->mount_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(ceph_open_session);
+
+
+static int __init init_ceph_lib(void)
+{
+	int ret = 0;
+
+	ret = ceph_debugfs_init();
+	if (ret < 0)
+		goto out;
+
+	ret = ceph_msgr_init();
+	if (ret < 0)
+		goto out_debugfs;
+
+	pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n",
+		CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL,
+		CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT,
+		CEPH_OSDMAP_INC_VERSION, CEPH_OSDMAP_INC_VERSION_EXT);
+
+	return 0;
+
+out_debugfs:
+	ceph_debugfs_cleanup();
+out:
+	return ret;
+}
+
+static void __exit exit_ceph_lib(void)
+{
+	dout("exit_ceph_lib\n");
+	ceph_msgr_exit();
+	ceph_debugfs_cleanup();
+}
+
+module_init(init_ceph_lib);
+module_exit(exit_ceph_lib);
+
+MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
+MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
+MODULE_AUTHOR("Patience Warnick <patience@newdream.net>");
+MODULE_DESCRIPTION("Ceph filesystem for Linux");
+MODULE_LICENSE("GPL");
diff --git a/net/ceph/ceph_fs.c b/net/ceph/ceph_fs.c
new file mode 100644
index 0000000..a3a3a31
--- /dev/null
+++ b/net/ceph/ceph_fs.c
@@ -0,0 +1,75 @@
+/*
+ * Some non-inline ceph helpers
+ */
+#include <linux/module.h>
+#include <linux/ceph/types.h>
+
+/*
+ * return true if @layout appears to be valid
+ */
+int ceph_file_layout_is_valid(const struct ceph_file_layout *layout)
+{
+	__u32 su = le32_to_cpu(layout->fl_stripe_unit);
+	__u32 sc = le32_to_cpu(layout->fl_stripe_count);
+	__u32 os = le32_to_cpu(layout->fl_object_size);
+
+	/* stripe unit, object size must be non-zero, 64k increment */
+	if (!su || (su & (CEPH_MIN_STRIPE_UNIT-1)))
+		return 0;
+	if (!os || (os & (CEPH_MIN_STRIPE_UNIT-1)))
+		return 0;
+	/* object size must be a multiple of stripe unit */
+	if (os < su || os % su)
+		return 0;
+	/* stripe count must be non-zero */
+	if (!sc)
+		return 0;
+	return 1;
+}
+
+
+int ceph_flags_to_mode(int flags)
+{
+	int mode;
+
+#ifdef O_DIRECTORY  /* fixme */
+	if ((flags & O_DIRECTORY) == O_DIRECTORY)
+		return CEPH_FILE_MODE_PIN;
+#endif
+	if ((flags & O_APPEND) == O_APPEND)
+		flags |= O_WRONLY;
+
+	if ((flags & O_ACCMODE) == O_RDWR)
+		mode = CEPH_FILE_MODE_RDWR;
+	else if ((flags & O_ACCMODE) == O_WRONLY)
+		mode = CEPH_FILE_MODE_WR;
+	else
+		mode = CEPH_FILE_MODE_RD;
+
+#ifdef O_LAZY
+	if (flags & O_LAZY)
+		mode |= CEPH_FILE_MODE_LAZY;
+#endif
+
+	return mode;
+}
+EXPORT_SYMBOL(ceph_flags_to_mode);
+
+int ceph_caps_for_mode(int mode)
+{
+	int caps = CEPH_CAP_PIN;
+
+	if (mode & CEPH_FILE_MODE_RD)
+		caps |= CEPH_CAP_FILE_SHARED |
+			CEPH_CAP_FILE_RD | CEPH_CAP_FILE_CACHE;
+	if (mode & CEPH_FILE_MODE_WR)
+		caps |= CEPH_CAP_FILE_EXCL |
+			CEPH_CAP_FILE_WR | CEPH_CAP_FILE_BUFFER |
+			CEPH_CAP_AUTH_SHARED | CEPH_CAP_AUTH_EXCL |
+			CEPH_CAP_XATTR_SHARED | CEPH_CAP_XATTR_EXCL;
+	if (mode & CEPH_FILE_MODE_LAZY)
+		caps |= CEPH_CAP_FILE_LAZYIO;
+
+	return caps;
+}
+EXPORT_SYMBOL(ceph_caps_for_mode);
diff --git a/net/ceph/ceph_hash.c b/net/ceph/ceph_hash.c
new file mode 100644
index 0000000..815ef88
--- /dev/null
+++ b/net/ceph/ceph_hash.c
@@ -0,0 +1,118 @@
+
+#include <linux/ceph/types.h>
+
+/*
+ * Robert Jenkin's hash function.
+ * http://burtleburtle.net/bob/hash/evahash.html
+ * This is in the public domain.
+ */
+#define mix(a, b, c)						\
+	do {							\
+		a = a - b;  a = a - c;  a = a ^ (c >> 13);	\
+		b = b - c;  b = b - a;  b = b ^ (a << 8);	\
+		c = c - a;  c = c - b;  c = c ^ (b >> 13);	\
+		a = a - b;  a = a - c;  a = a ^ (c >> 12);	\
+		b = b - c;  b = b - a;  b = b ^ (a << 16);	\
+		c = c - a;  c = c - b;  c = c ^ (b >> 5);	\
+		a = a - b;  a = a - c;  a = a ^ (c >> 3);	\
+		b = b - c;  b = b - a;  b = b ^ (a << 10);	\
+		c = c - a;  c = c - b;  c = c ^ (b >> 15);	\
+	} while (0)
+
+unsigned ceph_str_hash_rjenkins(const char *str, unsigned length)
+{
+	const unsigned char *k = (const unsigned char *)str;
+	__u32 a, b, c;  /* the internal state */
+	__u32 len;      /* how many key bytes still need mixing */
+
+	/* Set up the internal state */
+	len = length;
+	a = 0x9e3779b9;      /* the golden ratio; an arbitrary value */
+	b = a;
+	c = 0;               /* variable initialization of internal state */
+
+	/* handle most of the key */
+	while (len >= 12) {
+		a = a + (k[0] + ((__u32)k[1] << 8) + ((__u32)k[2] << 16) +
+			 ((__u32)k[3] << 24));
+		b = b + (k[4] + ((__u32)k[5] << 8) + ((__u32)k[6] << 16) +
+			 ((__u32)k[7] << 24));
+		c = c + (k[8] + ((__u32)k[9] << 8) + ((__u32)k[10] << 16) +
+			 ((__u32)k[11] << 24));
+		mix(a, b, c);
+		k = k + 12;
+		len = len - 12;
+	}
+
+	/* handle the last 11 bytes */
+	c = c + length;
+	switch (len) {            /* all the case statements fall through */
+	case 11:
+		c = c + ((__u32)k[10] << 24);
+	case 10:
+		c = c + ((__u32)k[9] << 16);
+	case 9:
+		c = c + ((__u32)k[8] << 8);
+		/* the first byte of c is reserved for the length */
+	case 8:
+		b = b + ((__u32)k[7] << 24);
+	case 7:
+		b = b + ((__u32)k[6] << 16);
+	case 6:
+		b = b + ((__u32)k[5] << 8);
+	case 5:
+		b = b + k[4];
+	case 4:
+		a = a + ((__u32)k[3] << 24);
+	case 3:
+		a = a + ((__u32)k[2] << 16);
+	case 2:
+		a = a + ((__u32)k[1] << 8);
+	case 1:
+		a = a + k[0];
+		/* case 0: nothing left to add */
+	}
+	mix(a, b, c);
+
+	return c;
+}
+
+/*
+ * linux dcache hash
+ */
+unsigned ceph_str_hash_linux(const char *str, unsigned length)
+{
+	unsigned long hash = 0;
+	unsigned char c;
+
+	while (length--) {
+		c = *str++;
+		hash = (hash + (c << 4) + (c >> 4)) * 11;
+	}
+	return hash;
+}
+
+
+unsigned ceph_str_hash(int type, const char *s, unsigned len)
+{
+	switch (type) {
+	case CEPH_STR_HASH_LINUX:
+		return ceph_str_hash_linux(s, len);
+	case CEPH_STR_HASH_RJENKINS:
+		return ceph_str_hash_rjenkins(s, len);
+	default:
+		return -1;
+	}
+}
+
+const char *ceph_str_hash_name(int type)
+{
+	switch (type) {
+	case CEPH_STR_HASH_LINUX:
+		return "linux";
+	case CEPH_STR_HASH_RJENKINS:
+		return "rjenkins";
+	default:
+		return "unknown";
+	}
+}
diff --git a/net/ceph/ceph_strings.c b/net/ceph/ceph_strings.c
new file mode 100644
index 0000000..3fbda04
--- /dev/null
+++ b/net/ceph/ceph_strings.c
@@ -0,0 +1,84 @@
+/*
+ * Ceph string constants
+ */
+#include <linux/module.h>
+#include <linux/ceph/types.h>
+
+const char *ceph_entity_type_name(int type)
+{
+	switch (type) {
+	case CEPH_ENTITY_TYPE_MDS: return "mds";
+	case CEPH_ENTITY_TYPE_OSD: return "osd";
+	case CEPH_ENTITY_TYPE_MON: return "mon";
+	case CEPH_ENTITY_TYPE_CLIENT: return "client";
+	case CEPH_ENTITY_TYPE_AUTH: return "auth";
+	default: return "unknown";
+	}
+}
+
+const char *ceph_osd_op_name(int op)
+{
+	switch (op) {
+	case CEPH_OSD_OP_READ: return "read";
+	case CEPH_OSD_OP_STAT: return "stat";
+
+	case CEPH_OSD_OP_MASKTRUNC: return "masktrunc";
+
+	case CEPH_OSD_OP_WRITE: return "write";
+	case CEPH_OSD_OP_DELETE: return "delete";
+	case CEPH_OSD_OP_TRUNCATE: return "truncate";
+	case CEPH_OSD_OP_ZERO: return "zero";
+	case CEPH_OSD_OP_WRITEFULL: return "writefull";
+	case CEPH_OSD_OP_ROLLBACK: return "rollback";
+
+	case CEPH_OSD_OP_APPEND: return "append";
+	case CEPH_OSD_OP_STARTSYNC: return "startsync";
+	case CEPH_OSD_OP_SETTRUNC: return "settrunc";
+	case CEPH_OSD_OP_TRIMTRUNC: return "trimtrunc";
+
+	case CEPH_OSD_OP_TMAPUP: return "tmapup";
+	case CEPH_OSD_OP_TMAPGET: return "tmapget";
+	case CEPH_OSD_OP_TMAPPUT: return "tmapput";
+
+	case CEPH_OSD_OP_GETXATTR: return "getxattr";
+	case CEPH_OSD_OP_GETXATTRS: return "getxattrs";
+	case CEPH_OSD_OP_SETXATTR: return "setxattr";
+	case CEPH_OSD_OP_SETXATTRS: return "setxattrs";
+	case CEPH_OSD_OP_RESETXATTRS: return "resetxattrs";
+	case CEPH_OSD_OP_RMXATTR: return "rmxattr";
+	case CEPH_OSD_OP_CMPXATTR: return "cmpxattr";
+
+	case CEPH_OSD_OP_PULL: return "pull";
+	case CEPH_OSD_OP_PUSH: return "push";
+	case CEPH_OSD_OP_BALANCEREADS: return "balance-reads";
+	case CEPH_OSD_OP_UNBALANCEREADS: return "unbalance-reads";
+	case CEPH_OSD_OP_SCRUB: return "scrub";
+
+	case CEPH_OSD_OP_WRLOCK: return "wrlock";
+	case CEPH_OSD_OP_WRUNLOCK: return "wrunlock";
+	case CEPH_OSD_OP_RDLOCK: return "rdlock";
+	case CEPH_OSD_OP_RDUNLOCK: return "rdunlock";
+	case CEPH_OSD_OP_UPLOCK: return "uplock";
+	case CEPH_OSD_OP_DNLOCK: return "dnlock";
+
+	case CEPH_OSD_OP_CALL: return "call";
+
+	case CEPH_OSD_OP_PGLS: return "pgls";
+	}
+	return "???";
+}
+
+
+const char *ceph_pool_op_name(int op)
+{
+	switch (op) {
+	case POOL_OP_CREATE: return "create";
+	case POOL_OP_DELETE: return "delete";
+	case POOL_OP_AUID_CHANGE: return "auid change";
+	case POOL_OP_CREATE_SNAP: return "create snap";
+	case POOL_OP_DELETE_SNAP: return "delete snap";
+	case POOL_OP_CREATE_UNMANAGED_SNAP: return "create unmanaged snap";
+	case POOL_OP_DELETE_UNMANAGED_SNAP: return "delete unmanaged snap";
+	}
+	return "???";
+}
diff --git a/net/ceph/crush/crush.c b/net/ceph/crush/crush.c
new file mode 100644
index 0000000..d6ebb13
--- /dev/null
+++ b/net/ceph/crush/crush.c
@@ -0,0 +1,151 @@
+
+#ifdef __KERNEL__
+# include <linux/slab.h>
+#else
+# include <stdlib.h>
+# include <assert.h>
+# define kfree(x) do { if (x) free(x); } while (0)
+# define BUG_ON(x) assert(!(x))
+#endif
+
+#include <linux/crush/crush.h>
+
+const char *crush_bucket_alg_name(int alg)
+{
+	switch (alg) {
+	case CRUSH_BUCKET_UNIFORM: return "uniform";
+	case CRUSH_BUCKET_LIST: return "list";
+	case CRUSH_BUCKET_TREE: return "tree";
+	case CRUSH_BUCKET_STRAW: return "straw";
+	default: return "unknown";
+	}
+}
+
+/**
+ * crush_get_bucket_item_weight - Get weight of an item in given bucket
+ * @b: bucket pointer
+ * @p: item index in bucket
+ */
+int crush_get_bucket_item_weight(struct crush_bucket *b, int p)
+{
+	if (p >= b->size)
+		return 0;
+
+	switch (b->alg) {
+	case CRUSH_BUCKET_UNIFORM:
+		return ((struct crush_bucket_uniform *)b)->item_weight;
+	case CRUSH_BUCKET_LIST:
+		return ((struct crush_bucket_list *)b)->item_weights[p];
+	case CRUSH_BUCKET_TREE:
+		if (p & 1)
+			return ((struct crush_bucket_tree *)b)->node_weights[p];
+		return 0;
+	case CRUSH_BUCKET_STRAW:
+		return ((struct crush_bucket_straw *)b)->item_weights[p];
+	}
+	return 0;
+}
+
+/**
+ * crush_calc_parents - Calculate parent vectors for the given crush map.
+ * @map: crush_map pointer
+ */
+void crush_calc_parents(struct crush_map *map)
+{
+	int i, b, c;
+
+	for (b = 0; b < map->max_buckets; b++) {
+		if (map->buckets[b] == NULL)
+			continue;
+		for (i = 0; i < map->buckets[b]->size; i++) {
+			c = map->buckets[b]->items[i];
+			BUG_ON(c >= map->max_devices ||
+			       c < -map->max_buckets);
+			if (c >= 0)
+				map->device_parents[c] = map->buckets[b]->id;
+			else
+				map->bucket_parents[-1-c] = map->buckets[b]->id;
+		}
+	}
+}
+
+void crush_destroy_bucket_uniform(struct crush_bucket_uniform *b)
+{
+	kfree(b->h.perm);
+	kfree(b->h.items);
+	kfree(b);
+}
+
+void crush_destroy_bucket_list(struct crush_bucket_list *b)
+{
+	kfree(b->item_weights);
+	kfree(b->sum_weights);
+	kfree(b->h.perm);
+	kfree(b->h.items);
+	kfree(b);
+}
+
+void crush_destroy_bucket_tree(struct crush_bucket_tree *b)
+{
+	kfree(b->node_weights);
+	kfree(b);
+}
+
+void crush_destroy_bucket_straw(struct crush_bucket_straw *b)
+{
+	kfree(b->straws);
+	kfree(b->item_weights);
+	kfree(b->h.perm);
+	kfree(b->h.items);
+	kfree(b);
+}
+
+void crush_destroy_bucket(struct crush_bucket *b)
+{
+	switch (b->alg) {
+	case CRUSH_BUCKET_UNIFORM:
+		crush_destroy_bucket_uniform((struct crush_bucket_uniform *)b);
+		break;
+	case CRUSH_BUCKET_LIST:
+		crush_destroy_bucket_list((struct crush_bucket_list *)b);
+		break;
+	case CRUSH_BUCKET_TREE:
+		crush_destroy_bucket_tree((struct crush_bucket_tree *)b);
+		break;
+	case CRUSH_BUCKET_STRAW:
+		crush_destroy_bucket_straw((struct crush_bucket_straw *)b);
+		break;
+	}
+}
+
+/**
+ * crush_destroy - Destroy a crush_map
+ * @map: crush_map pointer
+ */
+void crush_destroy(struct crush_map *map)
+{
+	int b;
+
+	/* buckets */
+	if (map->buckets) {
+		for (b = 0; b < map->max_buckets; b++) {
+			if (map->buckets[b] == NULL)
+				continue;
+			crush_destroy_bucket(map->buckets[b]);
+		}
+		kfree(map->buckets);
+	}
+
+	/* rules */
+	if (map->rules) {
+		for (b = 0; b < map->max_rules; b++)
+			kfree(map->rules[b]);
+		kfree(map->rules);
+	}
+
+	kfree(map->bucket_parents);
+	kfree(map->device_parents);
+	kfree(map);
+}
+
+
diff --git a/net/ceph/crush/hash.c b/net/ceph/crush/hash.c
new file mode 100644
index 0000000..5bb63e3
--- /dev/null
+++ b/net/ceph/crush/hash.c
@@ -0,0 +1,149 @@
+
+#include <linux/types.h>
+#include <linux/crush/hash.h>
+
+/*
+ * Robert Jenkins' function for mixing 32-bit values
+ * http://burtleburtle.net/bob/hash/evahash.html
+ * a, b = random bits, c = input and output
+ */
+#define crush_hashmix(a, b, c) do {			\
+		a = a-b;  a = a-c;  a = a^(c>>13);	\
+		b = b-c;  b = b-a;  b = b^(a<<8);	\
+		c = c-a;  c = c-b;  c = c^(b>>13);	\
+		a = a-b;  a = a-c;  a = a^(c>>12);	\
+		b = b-c;  b = b-a;  b = b^(a<<16);	\
+		c = c-a;  c = c-b;  c = c^(b>>5);	\
+		a = a-b;  a = a-c;  a = a^(c>>3);	\
+		b = b-c;  b = b-a;  b = b^(a<<10);	\
+		c = c-a;  c = c-b;  c = c^(b>>15);	\
+	} while (0)
+
+#define crush_hash_seed 1315423911
+
+static __u32 crush_hash32_rjenkins1(__u32 a)
+{
+	__u32 hash = crush_hash_seed ^ a;
+	__u32 b = a;
+	__u32 x = 231232;
+	__u32 y = 1232;
+	crush_hashmix(b, x, hash);
+	crush_hashmix(y, a, hash);
+	return hash;
+}
+
+static __u32 crush_hash32_rjenkins1_2(__u32 a, __u32 b)
+{
+	__u32 hash = crush_hash_seed ^ a ^ b;
+	__u32 x = 231232;
+	__u32 y = 1232;
+	crush_hashmix(a, b, hash);
+	crush_hashmix(x, a, hash);
+	crush_hashmix(b, y, hash);
+	return hash;
+}
+
+static __u32 crush_hash32_rjenkins1_3(__u32 a, __u32 b, __u32 c)
+{
+	__u32 hash = crush_hash_seed ^ a ^ b ^ c;
+	__u32 x = 231232;
+	__u32 y = 1232;
+	crush_hashmix(a, b, hash);
+	crush_hashmix(c, x, hash);
+	crush_hashmix(y, a, hash);
+	crush_hashmix(b, x, hash);
+	crush_hashmix(y, c, hash);
+	return hash;
+}
+
+static __u32 crush_hash32_rjenkins1_4(__u32 a, __u32 b, __u32 c, __u32 d)
+{
+	__u32 hash = crush_hash_seed ^ a ^ b ^ c ^ d;
+	__u32 x = 231232;
+	__u32 y = 1232;
+	crush_hashmix(a, b, hash);
+	crush_hashmix(c, d, hash);
+	crush_hashmix(a, x, hash);
+	crush_hashmix(y, b, hash);
+	crush_hashmix(c, x, hash);
+	crush_hashmix(y, d, hash);
+	return hash;
+}
+
+static __u32 crush_hash32_rjenkins1_5(__u32 a, __u32 b, __u32 c, __u32 d,
+				      __u32 e)
+{
+	__u32 hash = crush_hash_seed ^ a ^ b ^ c ^ d ^ e;
+	__u32 x = 231232;
+	__u32 y = 1232;
+	crush_hashmix(a, b, hash);
+	crush_hashmix(c, d, hash);
+	crush_hashmix(e, x, hash);
+	crush_hashmix(y, a, hash);
+	crush_hashmix(b, x, hash);
+	crush_hashmix(y, c, hash);
+	crush_hashmix(d, x, hash);
+	crush_hashmix(y, e, hash);
+	return hash;
+}
+
+
+__u32 crush_hash32(int type, __u32 a)
+{
+	switch (type) {
+	case CRUSH_HASH_RJENKINS1:
+		return crush_hash32_rjenkins1(a);
+	default:
+		return 0;
+	}
+}
+
+__u32 crush_hash32_2(int type, __u32 a, __u32 b)
+{
+	switch (type) {
+	case CRUSH_HASH_RJENKINS1:
+		return crush_hash32_rjenkins1_2(a, b);
+	default:
+		return 0;
+	}
+}
+
+__u32 crush_hash32_3(int type, __u32 a, __u32 b, __u32 c)
+{
+	switch (type) {
+	case CRUSH_HASH_RJENKINS1:
+		return crush_hash32_rjenkins1_3(a, b, c);
+	default:
+		return 0;
+	}
+}
+
+__u32 crush_hash32_4(int type, __u32 a, __u32 b, __u32 c, __u32 d)
+{
+	switch (type) {
+	case CRUSH_HASH_RJENKINS1:
+		return crush_hash32_rjenkins1_4(a, b, c, d);
+	default:
+		return 0;
+	}
+}
+
+__u32 crush_hash32_5(int type, __u32 a, __u32 b, __u32 c, __u32 d, __u32 e)
+{
+	switch (type) {
+	case CRUSH_HASH_RJENKINS1:
+		return crush_hash32_rjenkins1_5(a, b, c, d, e);
+	default:
+		return 0;
+	}
+}
+
+const char *crush_hash_name(int type)
+{
+	switch (type) {
+	case CRUSH_HASH_RJENKINS1:
+		return "rjenkins1";
+	default:
+		return "unknown";
+	}
+}
diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c
new file mode 100644
index 0000000..42599e3
--- /dev/null
+++ b/net/ceph/crush/mapper.c
@@ -0,0 +1,609 @@
+
+#ifdef __KERNEL__
+# include <linux/string.h>
+# include <linux/slab.h>
+# include <linux/bug.h>
+# include <linux/kernel.h>
+# ifndef dprintk
+#  define dprintk(args...)
+# endif
+#else
+# include <string.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <assert.h>
+# define BUG_ON(x) assert(!(x))
+# define dprintk(args...) /* printf(args) */
+# define kmalloc(x, f) malloc(x)
+# define kfree(x) free(x)
+#endif
+
+#include <linux/crush/crush.h>
+#include <linux/crush/hash.h>
+
+/*
+ * Implement the core CRUSH mapping algorithm.
+ */
+
+/**
+ * crush_find_rule - find a crush_rule id for a given ruleset, type, and size.
+ * @map: the crush_map
+ * @ruleset: the storage ruleset id (user defined)
+ * @type: storage ruleset type (user defined)
+ * @size: output set size
+ */
+int crush_find_rule(struct crush_map *map, int ruleset, int type, int size)
+{
+	int i;
+
+	for (i = 0; i < map->max_rules; i++) {
+		if (map->rules[i] &&
+		    map->rules[i]->mask.ruleset == ruleset &&
+		    map->rules[i]->mask.type == type &&
+		    map->rules[i]->mask.min_size <= size &&
+		    map->rules[i]->mask.max_size >= size)
+			return i;
+	}
+	return -1;
+}
+
+
+/*
+ * bucket choose methods
+ *
+ * For each bucket algorithm, we have a "choose" method that, given a
+ * crush input @x and replica position (usually, position in output set) @r,
+ * will produce an item in the bucket.
+ */
+
+/*
+ * Choose based on a random permutation of the bucket.
+ *
+ * We used to use some prime number arithmetic to do this, but it
+ * wasn't very random, and had some other bad behaviors.  Instead, we
+ * calculate an actual random permutation of the bucket members.
+ * Since this is expensive, we optimize for the r=0 case, which
+ * captures the vast majority of calls.
+ */
+static int bucket_perm_choose(struct crush_bucket *bucket,
+			      int x, int r)
+{
+	unsigned pr = r % bucket->size;
+	unsigned i, s;
+
+	/* start a new permutation if @x has changed */
+	if (bucket->perm_x != x || bucket->perm_n == 0) {
+		dprintk("bucket %d new x=%d\n", bucket->id, x);
+		bucket->perm_x = x;
+
+		/* optimize common r=0 case */
+		if (pr == 0) {
+			s = crush_hash32_3(bucket->hash, x, bucket->id, 0) %
+				bucket->size;
+			bucket->perm[0] = s;
+			bucket->perm_n = 0xffff;   /* magic value, see below */
+			goto out;
+		}
+
+		for (i = 0; i < bucket->size; i++)
+			bucket->perm[i] = i;
+		bucket->perm_n = 0;
+	} else if (bucket->perm_n == 0xffff) {
+		/* clean up after the r=0 case above */
+		for (i = 1; i < bucket->size; i++)
+			bucket->perm[i] = i;
+		bucket->perm[bucket->perm[0]] = 0;
+		bucket->perm_n = 1;
+	}
+
+	/* calculate permutation up to pr */
+	for (i = 0; i < bucket->perm_n; i++)
+		dprintk(" perm_choose have %d: %d\n", i, bucket->perm[i]);
+	while (bucket->perm_n <= pr) {
+		unsigned p = bucket->perm_n;
+		/* no point in swapping the final entry */
+		if (p < bucket->size - 1) {
+			i = crush_hash32_3(bucket->hash, x, bucket->id, p) %
+				(bucket->size - p);
+			if (i) {
+				unsigned t = bucket->perm[p + i];
+				bucket->perm[p + i] = bucket->perm[p];
+				bucket->perm[p] = t;
+			}
+			dprintk(" perm_choose swap %d with %d\n", p, p+i);
+		}
+		bucket->perm_n++;
+	}
+	for (i = 0; i < bucket->size; i++)
+		dprintk(" perm_choose  %d: %d\n", i, bucket->perm[i]);
+
+	s = bucket->perm[pr];
+out:
+	dprintk(" perm_choose %d sz=%d x=%d r=%d (%d) s=%d\n", bucket->id,
+		bucket->size, x, r, pr, s);
+	return bucket->items[s];
+}
+
+/* uniform */
+static int bucket_uniform_choose(struct crush_bucket_uniform *bucket,
+				 int x, int r)
+{
+	return bucket_perm_choose(&bucket->h, x, r);
+}
+
+/* list */
+static int bucket_list_choose(struct crush_bucket_list *bucket,
+			      int x, int r)
+{
+	int i;
+
+	for (i = bucket->h.size-1; i >= 0; i--) {
+		__u64 w = crush_hash32_4(bucket->h.hash,x, bucket->h.items[i],
+					 r, bucket->h.id);
+		w &= 0xffff;
+		dprintk("list_choose i=%d x=%d r=%d item %d weight %x "
+			"sw %x rand %llx",
+			i, x, r, bucket->h.items[i], bucket->item_weights[i],
+			bucket->sum_weights[i], w);
+		w *= bucket->sum_weights[i];
+		w = w >> 16;
+		/*dprintk(" scaled %llx\n", w);*/
+		if (w < bucket->item_weights[i])
+			return bucket->h.items[i];
+	}
+
+	BUG_ON(1);
+	return 0;
+}
+
+
+/* (binary) tree */
+static int height(int n)
+{
+	int h = 0;
+	while ((n & 1) == 0) {
+		h++;
+		n = n >> 1;
+	}
+	return h;
+}
+
+static int left(int x)
+{
+	int h = height(x);
+	return x - (1 << (h-1));
+}
+
+static int right(int x)
+{
+	int h = height(x);
+	return x + (1 << (h-1));
+}
+
+static int terminal(int x)
+{
+	return x & 1;
+}
+
+static int bucket_tree_choose(struct crush_bucket_tree *bucket,
+			      int x, int r)
+{
+	int n, l;
+	__u32 w;
+	__u64 t;
+
+	/* start at root */
+	n = bucket->num_nodes >> 1;
+
+	while (!terminal(n)) {
+		/* pick point in [0, w) */
+		w = bucket->node_weights[n];
+		t = (__u64)crush_hash32_4(bucket->h.hash, x, n, r,
+					  bucket->h.id) * (__u64)w;
+		t = t >> 32;
+
+		/* descend to the left or right? */
+		l = left(n);
+		if (t < bucket->node_weights[l])
+			n = l;
+		else
+			n = right(n);
+	}
+
+	return bucket->h.items[n >> 1];
+}
+
+
+/* straw */
+
+static int bucket_straw_choose(struct crush_bucket_straw *bucket,
+			       int x, int r)
+{
+	int i;
+	int high = 0;
+	__u64 high_draw = 0;
+	__u64 draw;
+
+	for (i = 0; i < bucket->h.size; i++) {
+		draw = crush_hash32_3(bucket->h.hash, x, bucket->h.items[i], r);
+		draw &= 0xffff;
+		draw *= bucket->straws[i];
+		if (i == 0 || draw > high_draw) {
+			high = i;
+			high_draw = draw;
+		}
+	}
+	return bucket->h.items[high];
+}
+
+static int crush_bucket_choose(struct crush_bucket *in, int x, int r)
+{
+	dprintk(" crush_bucket_choose %d x=%d r=%d\n", in->id, x, r);
+	switch (in->alg) {
+	case CRUSH_BUCKET_UNIFORM:
+		return bucket_uniform_choose((struct crush_bucket_uniform *)in,
+					  x, r);
+	case CRUSH_BUCKET_LIST:
+		return bucket_list_choose((struct crush_bucket_list *)in,
+					  x, r);
+	case CRUSH_BUCKET_TREE:
+		return bucket_tree_choose((struct crush_bucket_tree *)in,
+					  x, r);
+	case CRUSH_BUCKET_STRAW:
+		return bucket_straw_choose((struct crush_bucket_straw *)in,
+					   x, r);
+	default:
+		BUG_ON(1);
+		return in->items[0];
+	}
+}
+
+/*
+ * true if device is marked "out" (failed, fully offloaded)
+ * of the cluster
+ */
+static int is_out(struct crush_map *map, __u32 *weight, int item, int x)
+{
+	if (weight[item] >= 0x10000)
+		return 0;
+	if (weight[item] == 0)
+		return 1;
+	if ((crush_hash32_2(CRUSH_HASH_RJENKINS1, x, item) & 0xffff)
+	    < weight[item])
+		return 0;
+	return 1;
+}
+
+/**
+ * crush_choose - choose numrep distinct items of given type
+ * @map: the crush_map
+ * @bucket: the bucket we are choose an item from
+ * @x: crush input value
+ * @numrep: the number of items to choose
+ * @type: the type of item to choose
+ * @out: pointer to output vector
+ * @outpos: our position in that vector
+ * @firstn: true if choosing "first n" items, false if choosing "indep"
+ * @recurse_to_leaf: true if we want one device under each item of given type
+ * @out2: second output vector for leaf items (if @recurse_to_leaf)
+ */
+static int crush_choose(struct crush_map *map,
+			struct crush_bucket *bucket,
+			__u32 *weight,
+			int x, int numrep, int type,
+			int *out, int outpos,
+			int firstn, int recurse_to_leaf,
+			int *out2)
+{
+	int rep;
+	int ftotal, flocal;
+	int retry_descent, retry_bucket, skip_rep;
+	struct crush_bucket *in = bucket;
+	int r;
+	int i;
+	int item = 0;
+	int itemtype;
+	int collide, reject;
+	const int orig_tries = 5; /* attempts before we fall back to search */
+
+	dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "",
+		bucket->id, x, outpos, numrep);
+
+	for (rep = outpos; rep < numrep; rep++) {
+		/* keep trying until we get a non-out, non-colliding item */
+		ftotal = 0;
+		skip_rep = 0;
+		do {
+			retry_descent = 0;
+			in = bucket;               /* initial bucket */
+
+			/* choose through intervening buckets */
+			flocal = 0;
+			do {
+				collide = 0;
+				retry_bucket = 0;
+				r = rep;
+				if (in->alg == CRUSH_BUCKET_UNIFORM) {
+					/* be careful */
+					if (firstn || numrep >= in->size)
+						/* r' = r + f_total */
+						r += ftotal;
+					else if (in->size % numrep == 0)
+						/* r'=r+(n+1)*f_local */
+						r += (numrep+1) *
+							(flocal+ftotal);
+					else
+						/* r' = r + n*f_local */
+						r += numrep * (flocal+ftotal);
+				} else {
+					if (firstn)
+						/* r' = r + f_total */
+						r += ftotal;
+					else
+						/* r' = r + n*f_local */
+						r += numrep * (flocal+ftotal);
+				}
+
+				/* bucket choose */
+				if (in->size == 0) {
+					reject = 1;
+					goto reject;
+				}
+				if (flocal >= (in->size>>1) &&
+				    flocal > orig_tries)
+					item = bucket_perm_choose(in, x, r);
+				else
+					item = crush_bucket_choose(in, x, r);
+				BUG_ON(item >= map->max_devices);
+
+				/* desired type? */
+				if (item < 0)
+					itemtype = map->buckets[-1-item]->type;
+				else
+					itemtype = 0;
+				dprintk("  item %d type %d\n", item, itemtype);
+
+				/* keep going? */
+				if (itemtype != type) {
+					BUG_ON(item >= 0 ||
+					       (-1-item) >= map->max_buckets);
+					in = map->buckets[-1-item];
+					retry_bucket = 1;
+					continue;
+				}
+
+				/* collision? */
+				for (i = 0; i < outpos; i++) {
+					if (out[i] == item) {
+						collide = 1;
+						break;
+					}
+				}
+
+				reject = 0;
+				if (recurse_to_leaf) {
+					if (item < 0) {
+						if (crush_choose(map,
+							 map->buckets[-1-item],
+							 weight,
+							 x, outpos+1, 0,
+							 out2, outpos,
+							 firstn, 0,
+							 NULL) <= outpos)
+							/* didn't get leaf */
+							reject = 1;
+					} else {
+						/* we already have a leaf! */
+						out2[outpos] = item;
+					}
+				}
+
+				if (!reject) {
+					/* out? */
+					if (itemtype == 0)
+						reject = is_out(map, weight,
+								item, x);
+					else
+						reject = 0;
+				}
+
+reject:
+				if (reject || collide) {
+					ftotal++;
+					flocal++;
+
+					if (collide && flocal < 3)
+						/* retry locally a few times */
+						retry_bucket = 1;
+					else if (flocal < in->size + orig_tries)
+						/* exhaustive bucket search */
+						retry_bucket = 1;
+					else if (ftotal < 20)
+						/* then retry descent */
+						retry_descent = 1;
+					else
+						/* else give up */
+						skip_rep = 1;
+					dprintk("  reject %d  collide %d  "
+						"ftotal %d  flocal %d\n",
+						reject, collide, ftotal,
+						flocal);
+				}
+			} while (retry_bucket);
+		} while (retry_descent);
+
+		if (skip_rep) {
+			dprintk("skip rep\n");
+			continue;
+		}
+
+		dprintk("CHOOSE got %d\n", item);
+		out[outpos] = item;
+		outpos++;
+	}
+
+	dprintk("CHOOSE returns %d\n", outpos);
+	return outpos;
+}
+
+
+/**
+ * crush_do_rule - calculate a mapping with the given input and rule
+ * @map: the crush_map
+ * @ruleno: the rule id
+ * @x: hash input
+ * @result: pointer to result vector
+ * @result_max: maximum result size
+ * @force: force initial replica choice; -1 for none
+ */
+int crush_do_rule(struct crush_map *map,
+		  int ruleno, int x, int *result, int result_max,
+		  int force, __u32 *weight)
+{
+	int result_len;
+	int force_context[CRUSH_MAX_DEPTH];
+	int force_pos = -1;
+	int a[CRUSH_MAX_SET];
+	int b[CRUSH_MAX_SET];
+	int c[CRUSH_MAX_SET];
+	int recurse_to_leaf;
+	int *w;
+	int wsize = 0;
+	int *o;
+	int osize;
+	int *tmp;
+	struct crush_rule *rule;
+	int step;
+	int i, j;
+	int numrep;
+	int firstn;
+	int rc = -1;
+
+	BUG_ON(ruleno >= map->max_rules);
+
+	rule = map->rules[ruleno];
+	result_len = 0;
+	w = a;
+	o = b;
+
+	/*
+	 * determine hierarchical context of force, if any.  note
+	 * that this may or may not correspond to the specific types
+	 * referenced by the crush rule.
+	 */
+	if (force >= 0) {
+		if (force >= map->max_devices ||
+		    map->device_parents[force] == 0) {
+			/*dprintk("CRUSH: forcefed device dne\n");*/
+			rc = -1;  /* force fed device dne */
+			goto out;
+		}
+		if (!is_out(map, weight, force, x)) {
+			while (1) {
+				force_context[++force_pos] = force;
+				if (force >= 0)
+					force = map->device_parents[force];
+				else
+					force = map->bucket_parents[-1-force];
+				if (force == 0)
+					break;
+			}
+		}
+	}
+
+	for (step = 0; step < rule->len; step++) {
+		firstn = 0;
+		switch (rule->steps[step].op) {
+		case CRUSH_RULE_TAKE:
+			w[0] = rule->steps[step].arg1;
+			if (force_pos >= 0) {
+				BUG_ON(force_context[force_pos] != w[0]);
+				force_pos--;
+			}
+			wsize = 1;
+			break;
+
+		case CRUSH_RULE_CHOOSE_LEAF_FIRSTN:
+		case CRUSH_RULE_CHOOSE_FIRSTN:
+			firstn = 1;
+		case CRUSH_RULE_CHOOSE_LEAF_INDEP:
+		case CRUSH_RULE_CHOOSE_INDEP:
+			BUG_ON(wsize == 0);
+
+			recurse_to_leaf =
+				rule->steps[step].op ==
+				 CRUSH_RULE_CHOOSE_LEAF_FIRSTN ||
+				rule->steps[step].op ==
+				CRUSH_RULE_CHOOSE_LEAF_INDEP;
+
+			/* reset output */
+			osize = 0;
+
+			for (i = 0; i < wsize; i++) {
+				/*
+				 * see CRUSH_N, CRUSH_N_MINUS macros.
+				 * basically, numrep <= 0 means relative to
+				 * the provided result_max
+				 */
+				numrep = rule->steps[step].arg1;
+				if (numrep <= 0) {
+					numrep += result_max;
+					if (numrep <= 0)
+						continue;
+				}
+				j = 0;
+				if (osize == 0 && force_pos >= 0) {
+					/* skip any intermediate types */
+					while (force_pos &&
+					       force_context[force_pos] < 0 &&
+					       rule->steps[step].arg2 !=
+					       map->buckets[-1 -
+					       force_context[force_pos]]->type)
+						force_pos--;
+					o[osize] = force_context[force_pos];
+					if (recurse_to_leaf)
+						c[osize] = force_context[0];
+					j++;
+					force_pos--;
+				}
+				osize += crush_choose(map,
+						      map->buckets[-1-w[i]],
+						      weight,
+						      x, numrep,
+						      rule->steps[step].arg2,
+						      o+osize, j,
+						      firstn,
+						      recurse_to_leaf, c+osize);
+			}
+
+			if (recurse_to_leaf)
+				/* copy final _leaf_ values to output set */
+				memcpy(o, c, osize*sizeof(*o));
+
+			/* swap t and w arrays */
+			tmp = o;
+			o = w;
+			w = tmp;
+			wsize = osize;
+			break;
+
+
+		case CRUSH_RULE_EMIT:
+			for (i = 0; i < wsize && result_len < result_max; i++) {
+				result[result_len] = w[i];
+				result_len++;
+			}
+			wsize = 0;
+			break;
+
+		default:
+			BUG_ON(1);
+		}
+	}
+	rc = result_len;
+
+out:
+	return rc;
+}
+
+
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
new file mode 100644
index 0000000..7b505b0
--- /dev/null
+++ b/net/ceph/crypto.c
@@ -0,0 +1,412 @@
+
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/err.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <crypto/hash.h>
+
+#include <linux/ceph/decode.h>
+#include "crypto.h"
+
+int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end)
+{
+	if (*p + sizeof(u16) + sizeof(key->created) +
+	    sizeof(u16) + key->len > end)
+		return -ERANGE;
+	ceph_encode_16(p, key->type);
+	ceph_encode_copy(p, &key->created, sizeof(key->created));
+	ceph_encode_16(p, key->len);
+	ceph_encode_copy(p, key->key, key->len);
+	return 0;
+}
+
+int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end)
+{
+	ceph_decode_need(p, end, 2*sizeof(u16) + sizeof(key->created), bad);
+	key->type = ceph_decode_16(p);
+	ceph_decode_copy(p, &key->created, sizeof(key->created));
+	key->len = ceph_decode_16(p);
+	ceph_decode_need(p, end, key->len, bad);
+	key->key = kmalloc(key->len, GFP_NOFS);
+	if (!key->key)
+		return -ENOMEM;
+	ceph_decode_copy(p, key->key, key->len);
+	return 0;
+
+bad:
+	dout("failed to decode crypto key\n");
+	return -EINVAL;
+}
+
+int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *inkey)
+{
+	int inlen = strlen(inkey);
+	int blen = inlen * 3 / 4;
+	void *buf, *p;
+	int ret;
+
+	dout("crypto_key_unarmor %s\n", inkey);
+	buf = kmalloc(blen, GFP_NOFS);
+	if (!buf)
+		return -ENOMEM;
+	blen = ceph_unarmor(buf, inkey, inkey+inlen);
+	if (blen < 0) {
+		kfree(buf);
+		return blen;
+	}
+
+	p = buf;
+	ret = ceph_crypto_key_decode(key, &p, p + blen);
+	kfree(buf);
+	if (ret)
+		return ret;
+	dout("crypto_key_unarmor key %p type %d len %d\n", key,
+	     key->type, key->len);
+	return 0;
+}
+
+
+
+#define AES_KEY_SIZE 16
+
+static struct crypto_blkcipher *ceph_crypto_alloc_cipher(void)
+{
+	return crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
+}
+
+static const u8 *aes_iv = (u8 *)CEPH_AES_IV;
+
+static int ceph_aes_encrypt(const void *key, int key_len,
+			    void *dst, size_t *dst_len,
+			    const void *src, size_t src_len)
+{
+	struct scatterlist sg_in[2], sg_out[1];
+	struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
+	struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
+	int ret;
+	void *iv;
+	int ivsize;
+	size_t zero_padding = (0x10 - (src_len & 0x0f));
+	char pad[16];
+
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+
+	memset(pad, zero_padding, zero_padding);
+
+	*dst_len = src_len + zero_padding;
+
+	crypto_blkcipher_setkey((void *)tfm, key, key_len);
+	sg_init_table(sg_in, 2);
+	sg_set_buf(&sg_in[0], src, src_len);
+	sg_set_buf(&sg_in[1], pad, zero_padding);
+	sg_init_table(sg_out, 1);
+	sg_set_buf(sg_out, dst, *dst_len);
+	iv = crypto_blkcipher_crt(tfm)->iv;
+	ivsize = crypto_blkcipher_ivsize(tfm);
+
+	memcpy(iv, aes_iv, ivsize);
+	/*
+	print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1,
+		       key, key_len, 1);
+	print_hex_dump(KERN_ERR, "enc src: ", DUMP_PREFIX_NONE, 16, 1,
+			src, src_len, 1);
+	print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1,
+			pad, zero_padding, 1);
+	*/
+	ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
+				     src_len + zero_padding);
+	crypto_free_blkcipher(tfm);
+	if (ret < 0)
+		pr_err("ceph_aes_crypt failed %d\n", ret);
+	/*
+	print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1,
+		       dst, *dst_len, 1);
+	*/
+	return 0;
+}
+
+static int ceph_aes_encrypt2(const void *key, int key_len, void *dst,
+			     size_t *dst_len,
+			     const void *src1, size_t src1_len,
+			     const void *src2, size_t src2_len)
+{
+	struct scatterlist sg_in[3], sg_out[1];
+	struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
+	struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
+	int ret;
+	void *iv;
+	int ivsize;
+	size_t zero_padding = (0x10 - ((src1_len + src2_len) & 0x0f));
+	char pad[16];
+
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+
+	memset(pad, zero_padding, zero_padding);
+
+	*dst_len = src1_len + src2_len + zero_padding;
+
+	crypto_blkcipher_setkey((void *)tfm, key, key_len);
+	sg_init_table(sg_in, 3);
+	sg_set_buf(&sg_in[0], src1, src1_len);
+	sg_set_buf(&sg_in[1], src2, src2_len);
+	sg_set_buf(&sg_in[2], pad, zero_padding);
+	sg_init_table(sg_out, 1);
+	sg_set_buf(sg_out, dst, *dst_len);
+	iv = crypto_blkcipher_crt(tfm)->iv;
+	ivsize = crypto_blkcipher_ivsize(tfm);
+
+	memcpy(iv, aes_iv, ivsize);
+	/*
+	print_hex_dump(KERN_ERR, "enc  key: ", DUMP_PREFIX_NONE, 16, 1,
+		       key, key_len, 1);
+	print_hex_dump(KERN_ERR, "enc src1: ", DUMP_PREFIX_NONE, 16, 1,
+			src1, src1_len, 1);
+	print_hex_dump(KERN_ERR, "enc src2: ", DUMP_PREFIX_NONE, 16, 1,
+			src2, src2_len, 1);
+	print_hex_dump(KERN_ERR, "enc  pad: ", DUMP_PREFIX_NONE, 16, 1,
+			pad, zero_padding, 1);
+	*/
+	ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
+				     src1_len + src2_len + zero_padding);
+	crypto_free_blkcipher(tfm);
+	if (ret < 0)
+		pr_err("ceph_aes_crypt2 failed %d\n", ret);
+	/*
+	print_hex_dump(KERN_ERR, "enc  out: ", DUMP_PREFIX_NONE, 16, 1,
+		       dst, *dst_len, 1);
+	*/
+	return 0;
+}
+
+static int ceph_aes_decrypt(const void *key, int key_len,
+			    void *dst, size_t *dst_len,
+			    const void *src, size_t src_len)
+{
+	struct scatterlist sg_in[1], sg_out[2];
+	struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
+	struct blkcipher_desc desc = { .tfm = tfm };
+	char pad[16];
+	void *iv;
+	int ivsize;
+	int ret;
+	int last_byte;
+
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+
+	crypto_blkcipher_setkey((void *)tfm, key, key_len);
+	sg_init_table(sg_in, 1);
+	sg_init_table(sg_out, 2);
+	sg_set_buf(sg_in, src, src_len);
+	sg_set_buf(&sg_out[0], dst, *dst_len);
+	sg_set_buf(&sg_out[1], pad, sizeof(pad));
+
+	iv = crypto_blkcipher_crt(tfm)->iv;
+	ivsize = crypto_blkcipher_ivsize(tfm);
+
+	memcpy(iv, aes_iv, ivsize);
+
+	/*
+	print_hex_dump(KERN_ERR, "dec key: ", DUMP_PREFIX_NONE, 16, 1,
+		       key, key_len, 1);
+	print_hex_dump(KERN_ERR, "dec  in: ", DUMP_PREFIX_NONE, 16, 1,
+		       src, src_len, 1);
+	*/
+
+	ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
+	crypto_free_blkcipher(tfm);
+	if (ret < 0) {
+		pr_err("ceph_aes_decrypt failed %d\n", ret);
+		return ret;
+	}
+
+	if (src_len <= *dst_len)
+		last_byte = ((char *)dst)[src_len - 1];
+	else
+		last_byte = pad[src_len - *dst_len - 1];
+	if (last_byte <= 16 && src_len >= last_byte) {
+		*dst_len = src_len - last_byte;
+	} else {
+		pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n",
+		       last_byte, (int)src_len);
+		return -EPERM;  /* bad padding */
+	}
+	/*
+	print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1,
+		       dst, *dst_len, 1);
+	*/
+	return 0;
+}
+
+static int ceph_aes_decrypt2(const void *key, int key_len,
+			     void *dst1, size_t *dst1_len,
+			     void *dst2, size_t *dst2_len,
+			     const void *src, size_t src_len)
+{
+	struct scatterlist sg_in[1], sg_out[3];
+	struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
+	struct blkcipher_desc desc = { .tfm = tfm };
+	char pad[16];
+	void *iv;
+	int ivsize;
+	int ret;
+	int last_byte;
+
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+
+	sg_init_table(sg_in, 1);
+	sg_set_buf(sg_in, src, src_len);
+	sg_init_table(sg_out, 3);
+	sg_set_buf(&sg_out[0], dst1, *dst1_len);
+	sg_set_buf(&sg_out[1], dst2, *dst2_len);
+	sg_set_buf(&sg_out[2], pad, sizeof(pad));
+
+	crypto_blkcipher_setkey((void *)tfm, key, key_len);
+	iv = crypto_blkcipher_crt(tfm)->iv;
+	ivsize = crypto_blkcipher_ivsize(tfm);
+
+	memcpy(iv, aes_iv, ivsize);
+
+	/*
+	print_hex_dump(KERN_ERR, "dec  key: ", DUMP_PREFIX_NONE, 16, 1,
+		       key, key_len, 1);
+	print_hex_dump(KERN_ERR, "dec   in: ", DUMP_PREFIX_NONE, 16, 1,
+		       src, src_len, 1);
+	*/
+
+	ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
+	crypto_free_blkcipher(tfm);
+	if (ret < 0) {
+		pr_err("ceph_aes_decrypt failed %d\n", ret);
+		return ret;
+	}
+
+	if (src_len <= *dst1_len)
+		last_byte = ((char *)dst1)[src_len - 1];
+	else if (src_len <= *dst1_len + *dst2_len)
+		last_byte = ((char *)dst2)[src_len - *dst1_len - 1];
+	else
+		last_byte = pad[src_len - *dst1_len - *dst2_len - 1];
+	if (last_byte <= 16 && src_len >= last_byte) {
+		src_len -= last_byte;
+	} else {
+		pr_err("ceph_aes_decrypt got bad padding %d on src len %d\n",
+		       last_byte, (int)src_len);
+		return -EPERM;  /* bad padding */
+	}
+
+	if (src_len < *dst1_len) {
+		*dst1_len = src_len;
+		*dst2_len = 0;
+	} else {
+		*dst2_len = src_len - *dst1_len;
+	}
+	/*
+	print_hex_dump(KERN_ERR, "dec  out1: ", DUMP_PREFIX_NONE, 16, 1,
+		       dst1, *dst1_len, 1);
+	print_hex_dump(KERN_ERR, "dec  out2: ", DUMP_PREFIX_NONE, 16, 1,
+		       dst2, *dst2_len, 1);
+	*/
+
+	return 0;
+}
+
+
+int ceph_decrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
+		 const void *src, size_t src_len)
+{
+	switch (secret->type) {
+	case CEPH_CRYPTO_NONE:
+		if (*dst_len < src_len)
+			return -ERANGE;
+		memcpy(dst, src, src_len);
+		*dst_len = src_len;
+		return 0;
+
+	case CEPH_CRYPTO_AES:
+		return ceph_aes_decrypt(secret->key, secret->len, dst,
+					dst_len, src, src_len);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+int ceph_decrypt2(struct ceph_crypto_key *secret,
+			void *dst1, size_t *dst1_len,
+			void *dst2, size_t *dst2_len,
+			const void *src, size_t src_len)
+{
+	size_t t;
+
+	switch (secret->type) {
+	case CEPH_CRYPTO_NONE:
+		if (*dst1_len + *dst2_len < src_len)
+			return -ERANGE;
+		t = min(*dst1_len, src_len);
+		memcpy(dst1, src, t);
+		*dst1_len = t;
+		src += t;
+		src_len -= t;
+		if (src_len) {
+			t = min(*dst2_len, src_len);
+			memcpy(dst2, src, t);
+			*dst2_len = t;
+		}
+		return 0;
+
+	case CEPH_CRYPTO_AES:
+		return ceph_aes_decrypt2(secret->key, secret->len,
+					 dst1, dst1_len, dst2, dst2_len,
+					 src, src_len);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+int ceph_encrypt(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
+		 const void *src, size_t src_len)
+{
+	switch (secret->type) {
+	case CEPH_CRYPTO_NONE:
+		if (*dst_len < src_len)
+			return -ERANGE;
+		memcpy(dst, src, src_len);
+		*dst_len = src_len;
+		return 0;
+
+	case CEPH_CRYPTO_AES:
+		return ceph_aes_encrypt(secret->key, secret->len, dst,
+					dst_len, src, src_len);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
+		  const void *src1, size_t src1_len,
+		  const void *src2, size_t src2_len)
+{
+	switch (secret->type) {
+	case CEPH_CRYPTO_NONE:
+		if (*dst_len < src1_len + src2_len)
+			return -ERANGE;
+		memcpy(dst, src1, src1_len);
+		memcpy(dst + src1_len, src2, src2_len);
+		*dst_len = src1_len + src2_len;
+		return 0;
+
+	case CEPH_CRYPTO_AES:
+		return ceph_aes_encrypt2(secret->key, secret->len, dst, dst_len,
+					 src1, src1_len, src2, src2_len);
+
+	default:
+		return -EINVAL;
+	}
+}
diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h
new file mode 100644
index 0000000..f9eccac
--- /dev/null
+++ b/net/ceph/crypto.h
@@ -0,0 +1,48 @@
+#ifndef _FS_CEPH_CRYPTO_H
+#define _FS_CEPH_CRYPTO_H
+
+#include <linux/ceph/types.h>
+#include <linux/ceph/buffer.h>
+
+/*
+ * cryptographic secret
+ */
+struct ceph_crypto_key {
+	int type;
+	struct ceph_timespec created;
+	int len;
+	void *key;
+};
+
+static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
+{
+	kfree(key->key);
+}
+
+extern int ceph_crypto_key_encode(struct ceph_crypto_key *key,
+				  void **p, void *end);
+extern int ceph_crypto_key_decode(struct ceph_crypto_key *key,
+				  void **p, void *end);
+extern int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *in);
+
+/* crypto.c */
+extern int ceph_decrypt(struct ceph_crypto_key *secret,
+			void *dst, size_t *dst_len,
+			const void *src, size_t src_len);
+extern int ceph_encrypt(struct ceph_crypto_key *secret,
+			void *dst, size_t *dst_len,
+			const void *src, size_t src_len);
+extern int ceph_decrypt2(struct ceph_crypto_key *secret,
+			void *dst1, size_t *dst1_len,
+			void *dst2, size_t *dst2_len,
+			const void *src, size_t src_len);
+extern int ceph_encrypt2(struct ceph_crypto_key *secret,
+			 void *dst, size_t *dst_len,
+			 const void *src1, size_t src1_len,
+			 const void *src2, size_t src2_len);
+
+/* armor.c */
+extern int ceph_armor(char *dst, const char *src, const char *end);
+extern int ceph_unarmor(char *dst, const char *src, const char *end);
+
+#endif
diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c
new file mode 100644
index 0000000..27d4ea31
--- /dev/null
+++ b/net/ceph/debugfs.c
@@ -0,0 +1,267 @@
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/auth.h>
+#include <linux/ceph/debugfs.h>
+
+#ifdef CONFIG_DEBUG_FS
+
+/*
+ * Implement /sys/kernel/debug/ceph fun
+ *
+ * /sys/kernel/debug/ceph/client*  - an instance of the ceph client
+ *      .../osdmap      - current osdmap
+ *      .../monmap      - current monmap
+ *      .../osdc        - active osd requests
+ *      .../monc        - mon client state
+ *      .../dentry_lru  - dump contents of dentry lru
+ *      .../caps        - expose cap (reservation) stats
+ *      .../bdi         - symlink to ../../bdi/something
+ */
+
+static struct dentry *ceph_debugfs_dir;
+
+static int monmap_show(struct seq_file *s, void *p)
+{
+	int i;
+	struct ceph_client *client = s->private;
+
+	if (client->monc.monmap == NULL)
+		return 0;
+
+	seq_printf(s, "epoch %d\n", client->monc.monmap->epoch);
+	for (i = 0; i < client->monc.monmap->num_mon; i++) {
+		struct ceph_entity_inst *inst =
+			&client->monc.monmap->mon_inst[i];
+
+		seq_printf(s, "\t%s%lld\t%s\n",
+			   ENTITY_NAME(inst->name),
+			   ceph_pr_addr(&inst->addr.in_addr));
+	}
+	return 0;
+}
+
+static int osdmap_show(struct seq_file *s, void *p)
+{
+	int i;
+	struct ceph_client *client = s->private;
+	struct rb_node *n;
+
+	if (client->osdc.osdmap == NULL)
+		return 0;
+	seq_printf(s, "epoch %d\n", client->osdc.osdmap->epoch);
+	seq_printf(s, "flags%s%s\n",
+		   (client->osdc.osdmap->flags & CEPH_OSDMAP_NEARFULL) ?
+		   " NEARFULL" : "",
+		   (client->osdc.osdmap->flags & CEPH_OSDMAP_FULL) ?
+		   " FULL" : "");
+	for (n = rb_first(&client->osdc.osdmap->pg_pools); n; n = rb_next(n)) {
+		struct ceph_pg_pool_info *pool =
+			rb_entry(n, struct ceph_pg_pool_info, node);
+		seq_printf(s, "pg_pool %d pg_num %d / %d, lpg_num %d / %d\n",
+			   pool->id, pool->v.pg_num, pool->pg_num_mask,
+			   pool->v.lpg_num, pool->lpg_num_mask);
+	}
+	for (i = 0; i < client->osdc.osdmap->max_osd; i++) {
+		struct ceph_entity_addr *addr =
+			&client->osdc.osdmap->osd_addr[i];
+		int state = client->osdc.osdmap->osd_state[i];
+		char sb[64];
+
+		seq_printf(s, "\tosd%d\t%s\t%3d%%\t(%s)\n",
+			   i, ceph_pr_addr(&addr->in_addr),
+			   ((client->osdc.osdmap->osd_weight[i]*100) >> 16),
+			   ceph_osdmap_state_str(sb, sizeof(sb), state));
+	}
+	return 0;
+}
+
+static int monc_show(struct seq_file *s, void *p)
+{
+	struct ceph_client *client = s->private;
+	struct ceph_mon_generic_request *req;
+	struct ceph_mon_client *monc = &client->monc;
+	struct rb_node *rp;
+
+	mutex_lock(&monc->mutex);
+
+	if (monc->have_mdsmap)
+		seq_printf(s, "have mdsmap %u\n", (unsigned)monc->have_mdsmap);
+	if (monc->have_osdmap)
+		seq_printf(s, "have osdmap %u\n", (unsigned)monc->have_osdmap);
+	if (monc->want_next_osdmap)
+		seq_printf(s, "want next osdmap\n");
+
+	for (rp = rb_first(&monc->generic_request_tree); rp; rp = rb_next(rp)) {
+		__u16 op;
+		req = rb_entry(rp, struct ceph_mon_generic_request, node);
+		op = le16_to_cpu(req->request->hdr.type);
+		if (op == CEPH_MSG_STATFS)
+			seq_printf(s, "%lld statfs\n", req->tid);
+		else
+			seq_printf(s, "%lld unknown\n", req->tid);
+	}
+
+	mutex_unlock(&monc->mutex);
+	return 0;
+}
+
+static int osdc_show(struct seq_file *s, void *pp)
+{
+	struct ceph_client *client = s->private;
+	struct ceph_osd_client *osdc = &client->osdc;
+	struct rb_node *p;
+
+	mutex_lock(&osdc->request_mutex);
+	for (p = rb_first(&osdc->requests); p; p = rb_next(p)) {
+		struct ceph_osd_request *req;
+		struct ceph_osd_request_head *head;
+		struct ceph_osd_op *op;
+		int num_ops;
+		int opcode, olen;
+		int i;
+
+		req = rb_entry(p, struct ceph_osd_request, r_node);
+
+		seq_printf(s, "%lld\tosd%d\t%d.%x\t", req->r_tid,
+			   req->r_osd ? req->r_osd->o_osd : -1,
+			   le32_to_cpu(req->r_pgid.pool),
+			   le16_to_cpu(req->r_pgid.ps));
+
+		head = req->r_request->front.iov_base;
+		op = (void *)(head + 1);
+
+		num_ops = le16_to_cpu(head->num_ops);
+		olen = le32_to_cpu(head->object_len);
+		seq_printf(s, "%.*s", olen,
+			   (const char *)(head->ops + num_ops));
+
+		if (req->r_reassert_version.epoch)
+			seq_printf(s, "\t%u'%llu",
+			   (unsigned)le32_to_cpu(req->r_reassert_version.epoch),
+			   le64_to_cpu(req->r_reassert_version.version));
+		else
+			seq_printf(s, "\t");
+
+		for (i = 0; i < num_ops; i++) {
+			opcode = le16_to_cpu(op->op);
+			seq_printf(s, "\t%s", ceph_osd_op_name(opcode));
+			op++;
+		}
+
+		seq_printf(s, "\n");
+	}
+	mutex_unlock(&osdc->request_mutex);
+	return 0;
+}
+
+CEPH_DEFINE_SHOW_FUNC(monmap_show)
+CEPH_DEFINE_SHOW_FUNC(osdmap_show)
+CEPH_DEFINE_SHOW_FUNC(monc_show)
+CEPH_DEFINE_SHOW_FUNC(osdc_show)
+
+int ceph_debugfs_init(void)
+{
+	ceph_debugfs_dir = debugfs_create_dir("ceph", NULL);
+	if (!ceph_debugfs_dir)
+		return -ENOMEM;
+	return 0;
+}
+
+void ceph_debugfs_cleanup(void)
+{
+	debugfs_remove(ceph_debugfs_dir);
+}
+
+int ceph_debugfs_client_init(struct ceph_client *client)
+{
+	int ret = -ENOMEM;
+	char name[80];
+
+	snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid,
+		 client->monc.auth->global_id);
+
+	client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir);
+	if (!client->debugfs_dir)
+		goto out;
+
+	client->monc.debugfs_file = debugfs_create_file("monc",
+						      0600,
+						      client->debugfs_dir,
+						      client,
+						      &monc_show_fops);
+	if (!client->monc.debugfs_file)
+		goto out;
+
+	client->osdc.debugfs_file = debugfs_create_file("osdc",
+						      0600,
+						      client->debugfs_dir,
+						      client,
+						      &osdc_show_fops);
+	if (!client->osdc.debugfs_file)
+		goto out;
+
+	client->debugfs_monmap = debugfs_create_file("monmap",
+					0600,
+					client->debugfs_dir,
+					client,
+					&monmap_show_fops);
+	if (!client->debugfs_monmap)
+		goto out;
+
+	client->debugfs_osdmap = debugfs_create_file("osdmap",
+					0600,
+					client->debugfs_dir,
+					client,
+					&osdmap_show_fops);
+	if (!client->debugfs_osdmap)
+		goto out;
+
+	return 0;
+
+out:
+	ceph_debugfs_client_cleanup(client);
+	return ret;
+}
+
+void ceph_debugfs_client_cleanup(struct ceph_client *client)
+{
+	debugfs_remove(client->debugfs_osdmap);
+	debugfs_remove(client->debugfs_monmap);
+	debugfs_remove(client->osdc.debugfs_file);
+	debugfs_remove(client->monc.debugfs_file);
+	debugfs_remove(client->debugfs_dir);
+}
+
+#else  /* CONFIG_DEBUG_FS */
+
+int ceph_debugfs_init(void)
+{
+	return 0;
+}
+
+void ceph_debugfs_cleanup(void)
+{
+}
+
+int ceph_debugfs_client_init(struct ceph_client *client)
+{
+	return 0;
+}
+
+void ceph_debugfs_client_cleanup(struct ceph_client *client)
+{
+}
+
+#endif  /* CONFIG_DEBUG_FS */
+
+EXPORT_SYMBOL(ceph_debugfs_init);
+EXPORT_SYMBOL(ceph_debugfs_cleanup);
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
new file mode 100644
index 0000000..0e8157e
--- /dev/null
+++ b/net/ceph/messenger.c
@@ -0,0 +1,2453 @@
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/crc32c.h>
+#include <linux/ctype.h>
+#include <linux/highmem.h>
+#include <linux/inet.h>
+#include <linux/kthread.h>
+#include <linux/net.h>
+#include <linux/slab.h>
+#include <linux/socket.h>
+#include <linux/string.h>
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <net/tcp.h>
+
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/messenger.h>
+#include <linux/ceph/decode.h>
+#include <linux/ceph/pagelist.h>
+
+/*
+ * Ceph uses the messenger to exchange ceph_msg messages with other
+ * hosts in the system.  The messenger provides ordered and reliable
+ * delivery.  We tolerate TCP disconnects by reconnecting (with
+ * exponential backoff) in the case of a fault (disconnection, bad
+ * crc, protocol error).  Acks allow sent messages to be discarded by
+ * the sender.
+ */
+
+/* static tag bytes (protocol control messages) */
+static char tag_msg = CEPH_MSGR_TAG_MSG;
+static char tag_ack = CEPH_MSGR_TAG_ACK;
+static char tag_keepalive = CEPH_MSGR_TAG_KEEPALIVE;
+
+#ifdef CONFIG_LOCKDEP
+static struct lock_class_key socket_class;
+#endif
+
+
+static void queue_con(struct ceph_connection *con);
+static void con_work(struct work_struct *);
+static void ceph_fault(struct ceph_connection *con);
+
+/*
+ * nicely render a sockaddr as a string.
+ */
+#define MAX_ADDR_STR 20
+#define MAX_ADDR_STR_LEN 60
+static char addr_str[MAX_ADDR_STR][MAX_ADDR_STR_LEN];
+static DEFINE_SPINLOCK(addr_str_lock);
+static int last_addr_str;
+
+const char *ceph_pr_addr(const struct sockaddr_storage *ss)
+{
+	int i;
+	char *s;
+	struct sockaddr_in *in4 = (void *)ss;
+	struct sockaddr_in6 *in6 = (void *)ss;
+
+	spin_lock(&addr_str_lock);
+	i = last_addr_str++;
+	if (last_addr_str == MAX_ADDR_STR)
+		last_addr_str = 0;
+	spin_unlock(&addr_str_lock);
+	s = addr_str[i];
+
+	switch (ss->ss_family) {
+	case AF_INET:
+		snprintf(s, MAX_ADDR_STR_LEN, "%pI4:%u", &in4->sin_addr,
+			 (unsigned int)ntohs(in4->sin_port));
+		break;
+
+	case AF_INET6:
+		snprintf(s, MAX_ADDR_STR_LEN, "[%pI6c]:%u", &in6->sin6_addr,
+			 (unsigned int)ntohs(in6->sin6_port));
+		break;
+
+	default:
+		sprintf(s, "(unknown sockaddr family %d)", (int)ss->ss_family);
+	}
+
+	return s;
+}
+EXPORT_SYMBOL(ceph_pr_addr);
+
+static void encode_my_addr(struct ceph_messenger *msgr)
+{
+	memcpy(&msgr->my_enc_addr, &msgr->inst.addr, sizeof(msgr->my_enc_addr));
+	ceph_encode_addr(&msgr->my_enc_addr);
+}
+
+/*
+ * work queue for all reading and writing to/from the socket.
+ */
+struct workqueue_struct *ceph_msgr_wq;
+
+int ceph_msgr_init(void)
+{
+	ceph_msgr_wq = create_workqueue("ceph-msgr");
+	if (IS_ERR(ceph_msgr_wq)) {
+		int ret = PTR_ERR(ceph_msgr_wq);
+		pr_err("msgr_init failed to create workqueue: %d\n", ret);
+		ceph_msgr_wq = NULL;
+		return ret;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(ceph_msgr_init);
+
+void ceph_msgr_exit(void)
+{
+	destroy_workqueue(ceph_msgr_wq);
+}
+EXPORT_SYMBOL(ceph_msgr_exit);
+
+void ceph_msgr_flush(void)
+{
+	flush_workqueue(ceph_msgr_wq);
+}
+EXPORT_SYMBOL(ceph_msgr_flush);
+
+
+/*
+ * socket callback functions
+ */
+
+/* data available on socket, or listen socket received a connect */
+static void ceph_data_ready(struct sock *sk, int count_unused)
+{
+	struct ceph_connection *con =
+		(struct ceph_connection *)sk->sk_user_data;
+	if (sk->sk_state != TCP_CLOSE_WAIT) {
+		dout("ceph_data_ready on %p state = %lu, queueing work\n",
+		     con, con->state);
+		queue_con(con);
+	}
+}
+
+/* socket has buffer space for writing */
+static void ceph_write_space(struct sock *sk)
+{
+	struct ceph_connection *con =
+		(struct ceph_connection *)sk->sk_user_data;
+
+	/* only queue to workqueue if there is data we want to write. */
+	if (test_bit(WRITE_PENDING, &con->state)) {
+		dout("ceph_write_space %p queueing write work\n", con);
+		queue_con(con);
+	} else {
+		dout("ceph_write_space %p nothing to write\n", con);
+	}
+
+	/* since we have our own write_space, clear the SOCK_NOSPACE flag */
+	clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+}
+
+/* socket's state has changed */
+static void ceph_state_change(struct sock *sk)
+{
+	struct ceph_connection *con =
+		(struct ceph_connection *)sk->sk_user_data;
+
+	dout("ceph_state_change %p state = %lu sk_state = %u\n",
+	     con, con->state, sk->sk_state);
+
+	if (test_bit(CLOSED, &con->state))
+		return;
+
+	switch (sk->sk_state) {
+	case TCP_CLOSE:
+		dout("ceph_state_change TCP_CLOSE\n");
+	case TCP_CLOSE_WAIT:
+		dout("ceph_state_change TCP_CLOSE_WAIT\n");
+		if (test_and_set_bit(SOCK_CLOSED, &con->state) == 0) {
+			if (test_bit(CONNECTING, &con->state))
+				con->error_msg = "connection failed";
+			else
+				con->error_msg = "socket closed";
+			queue_con(con);
+		}
+		break;
+	case TCP_ESTABLISHED:
+		dout("ceph_state_change TCP_ESTABLISHED\n");
+		queue_con(con);
+		break;
+	}
+}
+
+/*
+ * set up socket callbacks
+ */
+static void set_sock_callbacks(struct socket *sock,
+			       struct ceph_connection *con)
+{
+	struct sock *sk = sock->sk;
+	sk->sk_user_data = (void *)con;
+	sk->sk_data_ready = ceph_data_ready;
+	sk->sk_write_space = ceph_write_space;
+	sk->sk_state_change = ceph_state_change;
+}
+
+
+/*
+ * socket helpers
+ */
+
+/*
+ * initiate connection to a remote socket.
+ */
+static struct socket *ceph_tcp_connect(struct ceph_connection *con)
+{
+	struct sockaddr_storage *paddr = &con->peer_addr.in_addr;
+	struct socket *sock;
+	int ret;
+
+	BUG_ON(con->sock);
+	ret = sock_create_kern(con->peer_addr.in_addr.ss_family, SOCK_STREAM,
+			       IPPROTO_TCP, &sock);
+	if (ret)
+		return ERR_PTR(ret);
+	con->sock = sock;
+	sock->sk->sk_allocation = GFP_NOFS;
+
+#ifdef CONFIG_LOCKDEP
+	lockdep_set_class(&sock->sk->sk_lock, &socket_class);
+#endif
+
+	set_sock_callbacks(sock, con);
+
+	dout("connect %s\n", ceph_pr_addr(&con->peer_addr.in_addr));
+
+	ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr),
+				 O_NONBLOCK);
+	if (ret == -EINPROGRESS) {
+		dout("connect %s EINPROGRESS sk_state = %u\n",
+		     ceph_pr_addr(&con->peer_addr.in_addr),
+		     sock->sk->sk_state);
+		ret = 0;
+	}
+	if (ret < 0) {
+		pr_err("connect %s error %d\n",
+		       ceph_pr_addr(&con->peer_addr.in_addr), ret);
+		sock_release(sock);
+		con->sock = NULL;
+		con->error_msg = "connect error";
+	}
+
+	if (ret < 0)
+		return ERR_PTR(ret);
+	return sock;
+}
+
+static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len)
+{
+	struct kvec iov = {buf, len};
+	struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL };
+
+	return kernel_recvmsg(sock, &msg, &iov, 1, len, msg.msg_flags);
+}
+
+/*
+ * write something.  @more is true if caller will be sending more data
+ * shortly.
+ */
+static int ceph_tcp_sendmsg(struct socket *sock, struct kvec *iov,
+		     size_t kvlen, size_t len, int more)
+{
+	struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL };
+
+	if (more)
+		msg.msg_flags |= MSG_MORE;
+	else
+		msg.msg_flags |= MSG_EOR;  /* superfluous, but what the hell */
+
+	return kernel_sendmsg(sock, &msg, iov, kvlen, len);
+}
+
+
+/*
+ * Shutdown/close the socket for the given connection.
+ */
+static int con_close_socket(struct ceph_connection *con)
+{
+	int rc;
+
+	dout("con_close_socket on %p sock %p\n", con, con->sock);
+	if (!con->sock)
+		return 0;
+	set_bit(SOCK_CLOSED, &con->state);
+	rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR);
+	sock_release(con->sock);
+	con->sock = NULL;
+	clear_bit(SOCK_CLOSED, &con->state);
+	return rc;
+}
+
+/*
+ * Reset a connection.  Discard all incoming and outgoing messages
+ * and clear *_seq state.
+ */
+static void ceph_msg_remove(struct ceph_msg *msg)
+{
+	list_del_init(&msg->list_head);
+	ceph_msg_put(msg);
+}
+static void ceph_msg_remove_list(struct list_head *head)
+{
+	while (!list_empty(head)) {
+		struct ceph_msg *msg = list_first_entry(head, struct ceph_msg,
+							list_head);
+		ceph_msg_remove(msg);
+	}
+}
+
+static void reset_connection(struct ceph_connection *con)
+{
+	/* reset connection, out_queue, msg_ and connect_seq */
+	/* discard existing out_queue and msg_seq */
+	ceph_msg_remove_list(&con->out_queue);
+	ceph_msg_remove_list(&con->out_sent);
+
+	if (con->in_msg) {
+		ceph_msg_put(con->in_msg);
+		con->in_msg = NULL;
+	}
+
+	con->connect_seq = 0;
+	con->out_seq = 0;
+	if (con->out_msg) {
+		ceph_msg_put(con->out_msg);
+		con->out_msg = NULL;
+	}
+	con->out_keepalive_pending = false;
+	con->in_seq = 0;
+	con->in_seq_acked = 0;
+}
+
+/*
+ * mark a peer down.  drop any open connections.
+ */
+void ceph_con_close(struct ceph_connection *con)
+{
+	dout("con_close %p peer %s\n", con,
+	     ceph_pr_addr(&con->peer_addr.in_addr));
+	set_bit(CLOSED, &con->state);  /* in case there's queued work */
+	clear_bit(STANDBY, &con->state);  /* avoid connect_seq bump */
+	clear_bit(LOSSYTX, &con->state);  /* so we retry next connect */
+	clear_bit(KEEPALIVE_PENDING, &con->state);
+	clear_bit(WRITE_PENDING, &con->state);
+	mutex_lock(&con->mutex);
+	reset_connection(con);
+	con->peer_global_seq = 0;
+	cancel_delayed_work(&con->work);
+	mutex_unlock(&con->mutex);
+	queue_con(con);
+}
+EXPORT_SYMBOL(ceph_con_close);
+
+/*
+ * Reopen a closed connection, with a new peer address.
+ */
+void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr)
+{
+	dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr));
+	set_bit(OPENING, &con->state);
+	clear_bit(CLOSED, &con->state);
+	memcpy(&con->peer_addr, addr, sizeof(*addr));
+	con->delay = 0;      /* reset backoff memory */
+	queue_con(con);
+}
+EXPORT_SYMBOL(ceph_con_open);
+
+/*
+ * return true if this connection ever successfully opened
+ */
+bool ceph_con_opened(struct ceph_connection *con)
+{
+	return con->connect_seq > 0;
+}
+
+/*
+ * generic get/put
+ */
+struct ceph_connection *ceph_con_get(struct ceph_connection *con)
+{
+	dout("con_get %p nref = %d -> %d\n", con,
+	     atomic_read(&con->nref), atomic_read(&con->nref) + 1);
+	if (atomic_inc_not_zero(&con->nref))
+		return con;
+	return NULL;
+}
+
+void ceph_con_put(struct ceph_connection *con)
+{
+	dout("con_put %p nref = %d -> %d\n", con,
+	     atomic_read(&con->nref), atomic_read(&con->nref) - 1);
+	BUG_ON(atomic_read(&con->nref) == 0);
+	if (atomic_dec_and_test(&con->nref)) {
+		BUG_ON(con->sock);
+		kfree(con);
+	}
+}
+
+/*
+ * initialize a new connection.
+ */
+void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con)
+{
+	dout("con_init %p\n", con);
+	memset(con, 0, sizeof(*con));
+	atomic_set(&con->nref, 1);
+	con->msgr = msgr;
+	mutex_init(&con->mutex);
+	INIT_LIST_HEAD(&con->out_queue);
+	INIT_LIST_HEAD(&con->out_sent);
+	INIT_DELAYED_WORK(&con->work, con_work);
+}
+EXPORT_SYMBOL(ceph_con_init);
+
+
+/*
+ * We maintain a global counter to order connection attempts.  Get
+ * a unique seq greater than @gt.
+ */
+static u32 get_global_seq(struct ceph_messenger *msgr, u32 gt)
+{
+	u32 ret;
+
+	spin_lock(&msgr->global_seq_lock);
+	if (msgr->global_seq < gt)
+		msgr->global_seq = gt;
+	ret = ++msgr->global_seq;
+	spin_unlock(&msgr->global_seq_lock);
+	return ret;
+}
+
+
+/*
+ * Prepare footer for currently outgoing message, and finish things
+ * off.  Assumes out_kvec* are already valid.. we just add on to the end.
+ */
+static void prepare_write_message_footer(struct ceph_connection *con, int v)
+{
+	struct ceph_msg *m = con->out_msg;
+
+	dout("prepare_write_message_footer %p\n", con);
+	con->out_kvec_is_msg = true;
+	con->out_kvec[v].iov_base = &m->footer;
+	con->out_kvec[v].iov_len = sizeof(m->footer);
+	con->out_kvec_bytes += sizeof(m->footer);
+	con->out_kvec_left++;
+	con->out_more = m->more_to_follow;
+	con->out_msg_done = true;
+}
+
+/*
+ * Prepare headers for the next outgoing message.
+ */
+static void prepare_write_message(struct ceph_connection *con)
+{
+	struct ceph_msg *m;
+	int v = 0;
+
+	con->out_kvec_bytes = 0;
+	con->out_kvec_is_msg = true;
+	con->out_msg_done = false;
+
+	/* Sneak an ack in there first?  If we can get it into the same
+	 * TCP packet that's a good thing. */
+	if (con->in_seq > con->in_seq_acked) {
+		con->in_seq_acked = con->in_seq;
+		con->out_kvec[v].iov_base = &tag_ack;
+		con->out_kvec[v++].iov_len = 1;
+		con->out_temp_ack = cpu_to_le64(con->in_seq_acked);
+		con->out_kvec[v].iov_base = &con->out_temp_ack;
+		con->out_kvec[v++].iov_len = sizeof(con->out_temp_ack);
+		con->out_kvec_bytes = 1 + sizeof(con->out_temp_ack);
+	}
+
+	m = list_first_entry(&con->out_queue,
+		       struct ceph_msg, list_head);
+	con->out_msg = m;
+	if (test_bit(LOSSYTX, &con->state)) {
+		list_del_init(&m->list_head);
+	} else {
+		/* put message on sent list */
+		ceph_msg_get(m);
+		list_move_tail(&m->list_head, &con->out_sent);
+	}
+
+	/*
+	 * only assign outgoing seq # if we haven't sent this message
+	 * yet.  if it is requeued, resend with it's original seq.
+	 */
+	if (m->needs_out_seq) {
+		m->hdr.seq = cpu_to_le64(++con->out_seq);
+		m->needs_out_seq = false;
+	}
+
+	dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n",
+	     m, con->out_seq, le16_to_cpu(m->hdr.type),
+	     le32_to_cpu(m->hdr.front_len), le32_to_cpu(m->hdr.middle_len),
+	     le32_to_cpu(m->hdr.data_len),
+	     m->nr_pages);
+	BUG_ON(le32_to_cpu(m->hdr.front_len) != m->front.iov_len);
+
+	/* tag + hdr + front + middle */
+	con->out_kvec[v].iov_base = &tag_msg;
+	con->out_kvec[v++].iov_len = 1;
+	con->out_kvec[v].iov_base = &m->hdr;
+	con->out_kvec[v++].iov_len = sizeof(m->hdr);
+	con->out_kvec[v++] = m->front;
+	if (m->middle)
+		con->out_kvec[v++] = m->middle->vec;
+	con->out_kvec_left = v;
+	con->out_kvec_bytes += 1 + sizeof(m->hdr) + m->front.iov_len +
+		(m->middle ? m->middle->vec.iov_len : 0);
+	con->out_kvec_cur = con->out_kvec;
+
+	/* fill in crc (except data pages), footer */
+	con->out_msg->hdr.crc =
+		cpu_to_le32(crc32c(0, (void *)&m->hdr,
+				      sizeof(m->hdr) - sizeof(m->hdr.crc)));
+	con->out_msg->footer.flags = CEPH_MSG_FOOTER_COMPLETE;
+	con->out_msg->footer.front_crc =
+		cpu_to_le32(crc32c(0, m->front.iov_base, m->front.iov_len));
+	if (m->middle)
+		con->out_msg->footer.middle_crc =
+			cpu_to_le32(crc32c(0, m->middle->vec.iov_base,
+					   m->middle->vec.iov_len));
+	else
+		con->out_msg->footer.middle_crc = 0;
+	con->out_msg->footer.data_crc = 0;
+	dout("prepare_write_message front_crc %u data_crc %u\n",
+	     le32_to_cpu(con->out_msg->footer.front_crc),
+	     le32_to_cpu(con->out_msg->footer.middle_crc));
+
+	/* is there a data payload? */
+	if (le32_to_cpu(m->hdr.data_len) > 0) {
+		/* initialize page iterator */
+		con->out_msg_pos.page = 0;
+		if (m->pages)
+			con->out_msg_pos.page_pos =
+				le16_to_cpu(m->hdr.data_off) & ~PAGE_MASK;
+		else
+			con->out_msg_pos.page_pos = 0;
+		con->out_msg_pos.data_pos = 0;
+		con->out_msg_pos.did_page_crc = 0;
+		con->out_more = 1;  /* data + footer will follow */
+	} else {
+		/* no, queue up footer too and be done */
+		prepare_write_message_footer(con, v);
+	}
+
+	set_bit(WRITE_PENDING, &con->state);
+}
+
+/*
+ * Prepare an ack.
+ */
+static void prepare_write_ack(struct ceph_connection *con)
+{
+	dout("prepare_write_ack %p %llu -> %llu\n", con,
+	     con->in_seq_acked, con->in_seq);
+	con->in_seq_acked = con->in_seq;
+
+	con->out_kvec[0].iov_base = &tag_ack;
+	con->out_kvec[0].iov_len = 1;
+	con->out_temp_ack = cpu_to_le64(con->in_seq_acked);
+	con->out_kvec[1].iov_base = &con->out_temp_ack;
+	con->out_kvec[1].iov_len = sizeof(con->out_temp_ack);
+	con->out_kvec_left = 2;
+	con->out_kvec_bytes = 1 + sizeof(con->out_temp_ack);
+	con->out_kvec_cur = con->out_kvec;
+	con->out_more = 1;  /* more will follow.. eventually.. */
+	set_bit(WRITE_PENDING, &con->state);
+}
+
+/*
+ * Prepare to write keepalive byte.
+ */
+static void prepare_write_keepalive(struct ceph_connection *con)
+{
+	dout("prepare_write_keepalive %p\n", con);
+	con->out_kvec[0].iov_base = &tag_keepalive;
+	con->out_kvec[0].iov_len = 1;
+	con->out_kvec_left = 1;
+	con->out_kvec_bytes = 1;
+	con->out_kvec_cur = con->out_kvec;
+	set_bit(WRITE_PENDING, &con->state);
+}
+
+/*
+ * Connection negotiation.
+ */
+
+static void prepare_connect_authorizer(struct ceph_connection *con)
+{
+	void *auth_buf;
+	int auth_len = 0;
+	int auth_protocol = 0;
+
+	mutex_unlock(&con->mutex);
+	if (con->ops->get_authorizer)
+		con->ops->get_authorizer(con, &auth_buf, &auth_len,
+					 &auth_protocol, &con->auth_reply_buf,
+					 &con->auth_reply_buf_len,
+					 con->auth_retry);
+	mutex_lock(&con->mutex);
+
+	con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol);
+	con->out_connect.authorizer_len = cpu_to_le32(auth_len);
+
+	con->out_kvec[con->out_kvec_left].iov_base = auth_buf;
+	con->out_kvec[con->out_kvec_left].iov_len = auth_len;
+	con->out_kvec_left++;
+	con->out_kvec_bytes += auth_len;
+}
+
+/*
+ * We connected to a peer and are saying hello.
+ */
+static void prepare_write_banner(struct ceph_messenger *msgr,
+				 struct ceph_connection *con)
+{
+	int len = strlen(CEPH_BANNER);
+
+	con->out_kvec[0].iov_base = CEPH_BANNER;
+	con->out_kvec[0].iov_len = len;
+	con->out_kvec[1].iov_base = &msgr->my_enc_addr;
+	con->out_kvec[1].iov_len = sizeof(msgr->my_enc_addr);
+	con->out_kvec_left = 2;
+	con->out_kvec_bytes = len + sizeof(msgr->my_enc_addr);
+	con->out_kvec_cur = con->out_kvec;
+	con->out_more = 0;
+	set_bit(WRITE_PENDING, &con->state);
+}
+
+static void prepare_write_connect(struct ceph_messenger *msgr,
+				  struct ceph_connection *con,
+				  int after_banner)
+{
+	unsigned global_seq = get_global_seq(con->msgr, 0);
+	int proto;
+
+	switch (con->peer_name.type) {
+	case CEPH_ENTITY_TYPE_MON:
+		proto = CEPH_MONC_PROTOCOL;
+		break;
+	case CEPH_ENTITY_TYPE_OSD:
+		proto = CEPH_OSDC_PROTOCOL;
+		break;
+	case CEPH_ENTITY_TYPE_MDS:
+		proto = CEPH_MDSC_PROTOCOL;
+		break;
+	default:
+		BUG();
+	}
+
+	dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con,
+	     con->connect_seq, global_seq, proto);
+
+	con->out_connect.features = cpu_to_le64(msgr->supported_features);
+	con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT);
+	con->out_connect.connect_seq = cpu_to_le32(con->connect_seq);
+	con->out_connect.global_seq = cpu_to_le32(global_seq);
+	con->out_connect.protocol_version = cpu_to_le32(proto);
+	con->out_connect.flags = 0;
+
+	if (!after_banner) {
+		con->out_kvec_left = 0;
+		con->out_kvec_bytes = 0;
+	}
+	con->out_kvec[con->out_kvec_left].iov_base = &con->out_connect;
+	con->out_kvec[con->out_kvec_left].iov_len = sizeof(con->out_connect);
+	con->out_kvec_left++;
+	con->out_kvec_bytes += sizeof(con->out_connect);
+	con->out_kvec_cur = con->out_kvec;
+	con->out_more = 0;
+	set_bit(WRITE_PENDING, &con->state);
+
+	prepare_connect_authorizer(con);
+}
+
+
+/*
+ * write as much of pending kvecs to the socket as we can.
+ *  1 -> done
+ *  0 -> socket full, but more to do
+ * <0 -> error
+ */
+static int write_partial_kvec(struct ceph_connection *con)
+{
+	int ret;
+
+	dout("write_partial_kvec %p %d left\n", con, con->out_kvec_bytes);
+	while (con->out_kvec_bytes > 0) {
+		ret = ceph_tcp_sendmsg(con->sock, con->out_kvec_cur,
+				       con->out_kvec_left, con->out_kvec_bytes,
+				       con->out_more);
+		if (ret <= 0)
+			goto out;
+		con->out_kvec_bytes -= ret;
+		if (con->out_kvec_bytes == 0)
+			break;            /* done */
+		while (ret > 0) {
+			if (ret >= con->out_kvec_cur->iov_len) {
+				ret -= con->out_kvec_cur->iov_len;
+				con->out_kvec_cur++;
+				con->out_kvec_left--;
+			} else {
+				con->out_kvec_cur->iov_len -= ret;
+				con->out_kvec_cur->iov_base += ret;
+				ret = 0;
+				break;
+			}
+		}
+	}
+	con->out_kvec_left = 0;
+	con->out_kvec_is_msg = false;
+	ret = 1;
+out:
+	dout("write_partial_kvec %p %d left in %d kvecs ret = %d\n", con,
+	     con->out_kvec_bytes, con->out_kvec_left, ret);
+	return ret;  /* done! */
+}
+
+#ifdef CONFIG_BLOCK
+static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg)
+{
+	if (!bio) {
+		*iter = NULL;
+		*seg = 0;
+		return;
+	}
+	*iter = bio;
+	*seg = bio->bi_idx;
+}
+
+static void iter_bio_next(struct bio **bio_iter, int *seg)
+{
+	if (*bio_iter == NULL)
+		return;
+
+	BUG_ON(*seg >= (*bio_iter)->bi_vcnt);
+
+	(*seg)++;
+	if (*seg == (*bio_iter)->bi_vcnt)
+		init_bio_iter((*bio_iter)->bi_next, bio_iter, seg);
+}
+#endif
+
+/*
+ * Write as much message data payload as we can.  If we finish, queue
+ * up the footer.
+ *  1 -> done, footer is now queued in out_kvec[].
+ *  0 -> socket full, but more to do
+ * <0 -> error
+ */
+static int write_partial_msg_pages(struct ceph_connection *con)
+{
+	struct ceph_msg *msg = con->out_msg;
+	unsigned data_len = le32_to_cpu(msg->hdr.data_len);
+	size_t len;
+	int crc = con->msgr->nocrc;
+	int ret;
+	int total_max_write;
+	int in_trail = 0;
+	size_t trail_len = (msg->trail ? msg->trail->length : 0);
+
+	dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n",
+	     con, con->out_msg, con->out_msg_pos.page, con->out_msg->nr_pages,
+	     con->out_msg_pos.page_pos);
+
+#ifdef CONFIG_BLOCK
+	if (msg->bio && !msg->bio_iter)
+		init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg);
+#endif
+
+	while (data_len > con->out_msg_pos.data_pos) {
+		struct page *page = NULL;
+		void *kaddr = NULL;
+		int max_write = PAGE_SIZE;
+		int page_shift = 0;
+
+		total_max_write = data_len - trail_len -
+			con->out_msg_pos.data_pos;
+
+		/*
+		 * if we are calculating the data crc (the default), we need
+		 * to map the page.  if our pages[] has been revoked, use the
+		 * zero page.
+		 */
+
+		/* have we reached the trail part of the data? */
+		if (con->out_msg_pos.data_pos >= data_len - trail_len) {
+			in_trail = 1;
+
+			total_max_write = data_len - con->out_msg_pos.data_pos;
+
+			page = list_first_entry(&msg->trail->head,
+						struct page, lru);
+			if (crc)
+				kaddr = kmap(page);
+			max_write = PAGE_SIZE;
+		} else if (msg->pages) {
+			page = msg->pages[con->out_msg_pos.page];
+			if (crc)
+				kaddr = kmap(page);
+		} else if (msg->pagelist) {
+			page = list_first_entry(&msg->pagelist->head,
+						struct page, lru);
+			if (crc)
+				kaddr = kmap(page);
+#ifdef CONFIG_BLOCK
+		} else if (msg->bio) {
+			struct bio_vec *bv;
+
+			bv = bio_iovec_idx(msg->bio_iter, msg->bio_seg);
+			page = bv->bv_page;
+			page_shift = bv->bv_offset;
+			if (crc)
+				kaddr = kmap(page) + page_shift;
+			max_write = bv->bv_len;
+#endif
+		} else {
+			page = con->msgr->zero_page;
+			if (crc)
+				kaddr = page_address(con->msgr->zero_page);
+		}
+		len = min_t(int, max_write - con->out_msg_pos.page_pos,
+			    total_max_write);
+
+		if (crc && !con->out_msg_pos.did_page_crc) {
+			void *base = kaddr + con->out_msg_pos.page_pos;
+			u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc);
+
+			BUG_ON(kaddr == NULL);
+			con->out_msg->footer.data_crc =
+				cpu_to_le32(crc32c(tmpcrc, base, len));
+			con->out_msg_pos.did_page_crc = 1;
+		}
+		ret = kernel_sendpage(con->sock, page,
+				      con->out_msg_pos.page_pos + page_shift,
+				      len,
+				      MSG_DONTWAIT | MSG_NOSIGNAL |
+				      MSG_MORE);
+
+		if (crc &&
+		    (msg->pages || msg->pagelist || msg->bio || in_trail))
+			kunmap(page);
+
+		if (ret <= 0)
+			goto out;
+
+		con->out_msg_pos.data_pos += ret;
+		con->out_msg_pos.page_pos += ret;
+		if (ret == len) {
+			con->out_msg_pos.page_pos = 0;
+			con->out_msg_pos.page++;
+			con->out_msg_pos.did_page_crc = 0;
+			if (in_trail)
+				list_move_tail(&page->lru,
+					       &msg->trail->head);
+			else if (msg->pagelist)
+				list_move_tail(&page->lru,
+					       &msg->pagelist->head);
+#ifdef CONFIG_BLOCK
+			else if (msg->bio)
+				iter_bio_next(&msg->bio_iter, &msg->bio_seg);
+#endif
+		}
+	}
+
+	dout("write_partial_msg_pages %p msg %p done\n", con, msg);
+
+	/* prepare and queue up footer, too */
+	if (!crc)
+		con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC;
+	con->out_kvec_bytes = 0;
+	con->out_kvec_left = 0;
+	con->out_kvec_cur = con->out_kvec;
+	prepare_write_message_footer(con, 0);
+	ret = 1;
+out:
+	return ret;
+}
+
+/*
+ * write some zeros
+ */
+static int write_partial_skip(struct ceph_connection *con)
+{
+	int ret;
+
+	while (con->out_skip > 0) {
+		struct kvec iov = {
+			.iov_base = page_address(con->msgr->zero_page),
+			.iov_len = min(con->out_skip, (int)PAGE_CACHE_SIZE)
+		};
+
+		ret = ceph_tcp_sendmsg(con->sock, &iov, 1, iov.iov_len, 1);
+		if (ret <= 0)
+			goto out;
+		con->out_skip -= ret;
+	}
+	ret = 1;
+out:
+	return ret;
+}
+
+/*
+ * Prepare to read connection handshake, or an ack.
+ */
+static void prepare_read_banner(struct ceph_connection *con)
+{
+	dout("prepare_read_banner %p\n", con);
+	con->in_base_pos = 0;
+}
+
+static void prepare_read_connect(struct ceph_connection *con)
+{
+	dout("prepare_read_connect %p\n", con);
+	con->in_base_pos = 0;
+}
+
+static void prepare_read_ack(struct ceph_connection *con)
+{
+	dout("prepare_read_ack %p\n", con);
+	con->in_base_pos = 0;
+}
+
+static void prepare_read_tag(struct ceph_connection *con)
+{
+	dout("prepare_read_tag %p\n", con);
+	con->in_base_pos = 0;
+	con->in_tag = CEPH_MSGR_TAG_READY;
+}
+
+/*
+ * Prepare to read a message.
+ */
+static int prepare_read_message(struct ceph_connection *con)
+{
+	dout("prepare_read_message %p\n", con);
+	BUG_ON(con->in_msg != NULL);
+	con->in_base_pos = 0;
+	con->in_front_crc = con->in_middle_crc = con->in_data_crc = 0;
+	return 0;
+}
+
+
+static int read_partial(struct ceph_connection *con,
+			int *to, int size, void *object)
+{
+	*to += size;
+	while (con->in_base_pos < *to) {
+		int left = *to - con->in_base_pos;
+		int have = size - left;
+		int ret = ceph_tcp_recvmsg(con->sock, object + have, left);
+		if (ret <= 0)
+			return ret;
+		con->in_base_pos += ret;
+	}
+	return 1;
+}
+
+
+/*
+ * Read all or part of the connect-side handshake on a new connection
+ */
+static int read_partial_banner(struct ceph_connection *con)
+{
+	int ret, to = 0;
+
+	dout("read_partial_banner %p at %d\n", con, con->in_base_pos);
+
+	/* peer's banner */
+	ret = read_partial(con, &to, strlen(CEPH_BANNER), con->in_banner);
+	if (ret <= 0)
+		goto out;
+	ret = read_partial(con, &to, sizeof(con->actual_peer_addr),
+			   &con->actual_peer_addr);
+	if (ret <= 0)
+		goto out;
+	ret = read_partial(con, &to, sizeof(con->peer_addr_for_me),
+			   &con->peer_addr_for_me);
+	if (ret <= 0)
+		goto out;
+out:
+	return ret;
+}
+
+static int read_partial_connect(struct ceph_connection *con)
+{
+	int ret, to = 0;
+
+	dout("read_partial_connect %p at %d\n", con, con->in_base_pos);
+
+	ret = read_partial(con, &to, sizeof(con->in_reply), &con->in_reply);
+	if (ret <= 0)
+		goto out;
+	ret = read_partial(con, &to, le32_to_cpu(con->in_reply.authorizer_len),
+			   con->auth_reply_buf);
+	if (ret <= 0)
+		goto out;
+
+	dout("read_partial_connect %p tag %d, con_seq = %u, g_seq = %u\n",
+	     con, (int)con->in_reply.tag,
+	     le32_to_cpu(con->in_reply.connect_seq),
+	     le32_to_cpu(con->in_reply.global_seq));
+out:
+	return ret;
+
+}
+
+/*
+ * Verify the hello banner looks okay.
+ */
+static int verify_hello(struct ceph_connection *con)
+{
+	if (memcmp(con->in_banner, CEPH_BANNER, strlen(CEPH_BANNER))) {
+		pr_err("connect to %s got bad banner\n",
+		       ceph_pr_addr(&con->peer_addr.in_addr));
+		con->error_msg = "protocol error, bad banner";
+		return -1;
+	}
+	return 0;
+}
+
+static bool addr_is_blank(struct sockaddr_storage *ss)
+{
+	switch (ss->ss_family) {
+	case AF_INET:
+		return ((struct sockaddr_in *)ss)->sin_addr.s_addr == 0;
+	case AF_INET6:
+		return
+		     ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[0] == 0 &&
+		     ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[1] == 0 &&
+		     ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[2] == 0 &&
+		     ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[3] == 0;
+	}
+	return false;
+}
+
+static int addr_port(struct sockaddr_storage *ss)
+{
+	switch (ss->ss_family) {
+	case AF_INET:
+		return ntohs(((struct sockaddr_in *)ss)->sin_port);
+	case AF_INET6:
+		return ntohs(((struct sockaddr_in6 *)ss)->sin6_port);
+	}
+	return 0;
+}
+
+static void addr_set_port(struct sockaddr_storage *ss, int p)
+{
+	switch (ss->ss_family) {
+	case AF_INET:
+		((struct sockaddr_in *)ss)->sin_port = htons(p);
+	case AF_INET6:
+		((struct sockaddr_in6 *)ss)->sin6_port = htons(p);
+	}
+}
+
+/*
+ * Parse an ip[:port] list into an addr array.  Use the default
+ * monitor port if a port isn't specified.
+ */
+int ceph_parse_ips(const char *c, const char *end,
+		   struct ceph_entity_addr *addr,
+		   int max_count, int *count)
+{
+	int i;
+	const char *p = c;
+
+	dout("parse_ips on '%.*s'\n", (int)(end-c), c);
+	for (i = 0; i < max_count; i++) {
+		const char *ipend;
+		struct sockaddr_storage *ss = &addr[i].in_addr;
+		struct sockaddr_in *in4 = (void *)ss;
+		struct sockaddr_in6 *in6 = (void *)ss;
+		int port;
+		char delim = ',';
+
+		if (*p == '[') {
+			delim = ']';
+			p++;
+		}
+
+		memset(ss, 0, sizeof(*ss));
+		if (in4_pton(p, end - p, (u8 *)&in4->sin_addr.s_addr,
+			     delim, &ipend))
+			ss->ss_family = AF_INET;
+		else if (in6_pton(p, end - p, (u8 *)&in6->sin6_addr.s6_addr,
+				  delim, &ipend))
+			ss->ss_family = AF_INET6;
+		else
+			goto bad;
+		p = ipend;
+
+		if (delim == ']') {
+			if (*p != ']') {
+				dout("missing matching ']'\n");
+				goto bad;
+			}
+			p++;
+		}
+
+		/* port? */
+		if (p < end && *p == ':') {
+			port = 0;
+			p++;
+			while (p < end && *p >= '0' && *p <= '9') {
+				port = (port * 10) + (*p - '0');
+				p++;
+			}
+			if (port > 65535 || port == 0)
+				goto bad;
+		} else {
+			port = CEPH_MON_PORT;
+		}
+
+		addr_set_port(ss, port);
+
+		dout("parse_ips got %s\n", ceph_pr_addr(ss));
+
+		if (p == end)
+			break;
+		if (*p != ',')
+			goto bad;
+		p++;
+	}
+
+	if (p != end)
+		goto bad;
+
+	if (count)
+		*count = i + 1;
+	return 0;
+
+bad:
+	pr_err("parse_ips bad ip '%.*s'\n", (int)(end - c), c);
+	return -EINVAL;
+}
+EXPORT_SYMBOL(ceph_parse_ips);
+
+static int process_banner(struct ceph_connection *con)
+{
+	dout("process_banner on %p\n", con);
+
+	if (verify_hello(con) < 0)
+		return -1;
+
+	ceph_decode_addr(&con->actual_peer_addr);
+	ceph_decode_addr(&con->peer_addr_for_me);
+
+	/*
+	 * Make sure the other end is who we wanted.  note that the other
+	 * end may not yet know their ip address, so if it's 0.0.0.0, give
+	 * them the benefit of the doubt.
+	 */
+	if (memcmp(&con->peer_addr, &con->actual_peer_addr,
+		   sizeof(con->peer_addr)) != 0 &&
+	    !(addr_is_blank(&con->actual_peer_addr.in_addr) &&
+	      con->actual_peer_addr.nonce == con->peer_addr.nonce)) {
+		pr_warning("wrong peer, want %s/%d, got %s/%d\n",
+			   ceph_pr_addr(&con->peer_addr.in_addr),
+			   (int)le32_to_cpu(con->peer_addr.nonce),
+			   ceph_pr_addr(&con->actual_peer_addr.in_addr),
+			   (int)le32_to_cpu(con->actual_peer_addr.nonce));
+		con->error_msg = "wrong peer at address";
+		return -1;
+	}
+
+	/*
+	 * did we learn our address?
+	 */
+	if (addr_is_blank(&con->msgr->inst.addr.in_addr)) {
+		int port = addr_port(&con->msgr->inst.addr.in_addr);
+
+		memcpy(&con->msgr->inst.addr.in_addr,
+		       &con->peer_addr_for_me.in_addr,
+		       sizeof(con->peer_addr_for_me.in_addr));
+		addr_set_port(&con->msgr->inst.addr.in_addr, port);
+		encode_my_addr(con->msgr);
+		dout("process_banner learned my addr is %s\n",
+		     ceph_pr_addr(&con->msgr->inst.addr.in_addr));
+	}
+
+	set_bit(NEGOTIATING, &con->state);
+	prepare_read_connect(con);
+	return 0;
+}
+
+static void fail_protocol(struct ceph_connection *con)
+{
+	reset_connection(con);
+	set_bit(CLOSED, &con->state);  /* in case there's queued work */
+
+	mutex_unlock(&con->mutex);
+	if (con->ops->bad_proto)
+		con->ops->bad_proto(con);
+	mutex_lock(&con->mutex);
+}
+
+static int process_connect(struct ceph_connection *con)
+{
+	u64 sup_feat = con->msgr->supported_features;
+	u64 req_feat = con->msgr->required_features;
+	u64 server_feat = le64_to_cpu(con->in_reply.features);
+
+	dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
+
+	switch (con->in_reply.tag) {
+	case CEPH_MSGR_TAG_FEATURES:
+		pr_err("%s%lld %s feature set mismatch,"
+		       " my %llx < server's %llx, missing %llx\n",
+		       ENTITY_NAME(con->peer_name),
+		       ceph_pr_addr(&con->peer_addr.in_addr),
+		       sup_feat, server_feat, server_feat & ~sup_feat);
+		con->error_msg = "missing required protocol features";
+		fail_protocol(con);
+		return -1;
+
+	case CEPH_MSGR_TAG_BADPROTOVER:
+		pr_err("%s%lld %s protocol version mismatch,"
+		       " my %d != server's %d\n",
+		       ENTITY_NAME(con->peer_name),
+		       ceph_pr_addr(&con->peer_addr.in_addr),
+		       le32_to_cpu(con->out_connect.protocol_version),
+		       le32_to_cpu(con->in_reply.protocol_version));
+		con->error_msg = "protocol version mismatch";
+		fail_protocol(con);
+		return -1;
+
+	case CEPH_MSGR_TAG_BADAUTHORIZER:
+		con->auth_retry++;
+		dout("process_connect %p got BADAUTHORIZER attempt %d\n", con,
+		     con->auth_retry);
+		if (con->auth_retry == 2) {
+			con->error_msg = "connect authorization failure";
+			reset_connection(con);
+			set_bit(CLOSED, &con->state);
+			return -1;
+		}
+		con->auth_retry = 1;
+		prepare_write_connect(con->msgr, con, 0);
+		prepare_read_connect(con);
+		break;
+
+	case CEPH_MSGR_TAG_RESETSESSION:
+		/*
+		 * If we connected with a large connect_seq but the peer
+		 * has no record of a session with us (no connection, or
+		 * connect_seq == 0), they will send RESETSESION to indicate
+		 * that they must have reset their session, and may have
+		 * dropped messages.
+		 */
+		dout("process_connect got RESET peer seq %u\n",
+		     le32_to_cpu(con->in_connect.connect_seq));
+		pr_err("%s%lld %s connection reset\n",
+		       ENTITY_NAME(con->peer_name),
+		       ceph_pr_addr(&con->peer_addr.in_addr));
+		reset_connection(con);
+		prepare_write_connect(con->msgr, con, 0);
+		prepare_read_connect(con);
+
+		/* Tell ceph about it. */
+		mutex_unlock(&con->mutex);
+		pr_info("reset on %s%lld\n", ENTITY_NAME(con->peer_name));
+		if (con->ops->peer_reset)
+			con->ops->peer_reset(con);
+		mutex_lock(&con->mutex);
+		break;
+
+	case CEPH_MSGR_TAG_RETRY_SESSION:
+		/*
+		 * If we sent a smaller connect_seq than the peer has, try
+		 * again with a larger value.
+		 */
+		dout("process_connect got RETRY my seq = %u, peer_seq = %u\n",
+		     le32_to_cpu(con->out_connect.connect_seq),
+		     le32_to_cpu(con->in_connect.connect_seq));
+		con->connect_seq = le32_to_cpu(con->in_connect.connect_seq);
+		prepare_write_connect(con->msgr, con, 0);
+		prepare_read_connect(con);
+		break;
+
+	case CEPH_MSGR_TAG_RETRY_GLOBAL:
+		/*
+		 * If we sent a smaller global_seq than the peer has, try
+		 * again with a larger value.
+		 */
+		dout("process_connect got RETRY_GLOBAL my %u peer_gseq %u\n",
+		     con->peer_global_seq,
+		     le32_to_cpu(con->in_connect.global_seq));
+		get_global_seq(con->msgr,
+			       le32_to_cpu(con->in_connect.global_seq));
+		prepare_write_connect(con->msgr, con, 0);
+		prepare_read_connect(con);
+		break;
+
+	case CEPH_MSGR_TAG_READY:
+		if (req_feat & ~server_feat) {
+			pr_err("%s%lld %s protocol feature mismatch,"
+			       " my required %llx > server's %llx, need %llx\n",
+			       ENTITY_NAME(con->peer_name),
+			       ceph_pr_addr(&con->peer_addr.in_addr),
+			       req_feat, server_feat, req_feat & ~server_feat);
+			con->error_msg = "missing required protocol features";
+			fail_protocol(con);
+			return -1;
+		}
+		clear_bit(CONNECTING, &con->state);
+		con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq);
+		con->connect_seq++;
+		con->peer_features = server_feat;
+		dout("process_connect got READY gseq %d cseq %d (%d)\n",
+		     con->peer_global_seq,
+		     le32_to_cpu(con->in_reply.connect_seq),
+		     con->connect_seq);
+		WARN_ON(con->connect_seq !=
+			le32_to_cpu(con->in_reply.connect_seq));
+
+		if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY)
+			set_bit(LOSSYTX, &con->state);
+
+		prepare_read_tag(con);
+		break;
+
+	case CEPH_MSGR_TAG_WAIT:
+		/*
+		 * If there is a connection race (we are opening
+		 * connections to each other), one of us may just have
+		 * to WAIT.  This shouldn't happen if we are the
+		 * client.
+		 */
+		pr_err("process_connect peer connecting WAIT\n");
+
+	default:
+		pr_err("connect protocol error, will retry\n");
+		con->error_msg = "protocol error, garbage tag during connect";
+		return -1;
+	}
+	return 0;
+}
+
+
+/*
+ * read (part of) an ack
+ */
+static int read_partial_ack(struct ceph_connection *con)
+{
+	int to = 0;
+
+	return read_partial(con, &to, sizeof(con->in_temp_ack),
+			    &con->in_temp_ack);
+}
+
+
+/*
+ * We can finally discard anything that's been acked.
+ */
+static void process_ack(struct ceph_connection *con)
+{
+	struct ceph_msg *m;
+	u64 ack = le64_to_cpu(con->in_temp_ack);
+	u64 seq;
+
+	while (!list_empty(&con->out_sent)) {
+		m = list_first_entry(&con->out_sent, struct ceph_msg,
+				     list_head);
+		seq = le64_to_cpu(m->hdr.seq);
+		if (seq > ack)
+			break;
+		dout("got ack for seq %llu type %d at %p\n", seq,
+		     le16_to_cpu(m->hdr.type), m);
+		ceph_msg_remove(m);
+	}
+	prepare_read_tag(con);
+}
+
+
+
+
+static int read_partial_message_section(struct ceph_connection *con,
+					struct kvec *section,
+					unsigned int sec_len, u32 *crc)
+{
+	int ret, left;
+
+	BUG_ON(!section);
+
+	while (section->iov_len < sec_len) {
+		BUG_ON(section->iov_base == NULL);
+		left = sec_len - section->iov_len;
+		ret = ceph_tcp_recvmsg(con->sock, (char *)section->iov_base +
+				       section->iov_len, left);
+		if (ret <= 0)
+			return ret;
+		section->iov_len += ret;
+		if (section->iov_len == sec_len)
+			*crc = crc32c(0, section->iov_base,
+				      section->iov_len);
+	}
+
+	return 1;
+}
+
+static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con,
+				struct ceph_msg_header *hdr,
+				int *skip);
+
+
+static int read_partial_message_pages(struct ceph_connection *con,
+				      struct page **pages,
+				      unsigned data_len, int datacrc)
+{
+	void *p;
+	int ret;
+	int left;
+
+	left = min((int)(data_len - con->in_msg_pos.data_pos),
+		   (int)(PAGE_SIZE - con->in_msg_pos.page_pos));
+	/* (page) data */
+	BUG_ON(pages == NULL);
+	p = kmap(pages[con->in_msg_pos.page]);
+	ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos,
+			       left);
+	if (ret > 0 && datacrc)
+		con->in_data_crc =
+			crc32c(con->in_data_crc,
+				  p + con->in_msg_pos.page_pos, ret);
+	kunmap(pages[con->in_msg_pos.page]);
+	if (ret <= 0)
+		return ret;
+	con->in_msg_pos.data_pos += ret;
+	con->in_msg_pos.page_pos += ret;
+	if (con->in_msg_pos.page_pos == PAGE_SIZE) {
+		con->in_msg_pos.page_pos = 0;
+		con->in_msg_pos.page++;
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_BLOCK
+static int read_partial_message_bio(struct ceph_connection *con,
+				    struct bio **bio_iter, int *bio_seg,
+				    unsigned data_len, int datacrc)
+{
+	struct bio_vec *bv = bio_iovec_idx(*bio_iter, *bio_seg);
+	void *p;
+	int ret, left;
+
+	if (IS_ERR(bv))
+		return PTR_ERR(bv);
+
+	left = min((int)(data_len - con->in_msg_pos.data_pos),
+		   (int)(bv->bv_len - con->in_msg_pos.page_pos));
+
+	p = kmap(bv->bv_page) + bv->bv_offset;
+
+	ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos,
+			       left);
+	if (ret > 0 && datacrc)
+		con->in_data_crc =
+			crc32c(con->in_data_crc,
+				  p + con->in_msg_pos.page_pos, ret);
+	kunmap(bv->bv_page);
+	if (ret <= 0)
+		return ret;
+	con->in_msg_pos.data_pos += ret;
+	con->in_msg_pos.page_pos += ret;
+	if (con->in_msg_pos.page_pos == bv->bv_len) {
+		con->in_msg_pos.page_pos = 0;
+		iter_bio_next(bio_iter, bio_seg);
+	}
+
+	return ret;
+}
+#endif
+
+/*
+ * read (part of) a message.
+ */
+static int read_partial_message(struct ceph_connection *con)
+{
+	struct ceph_msg *m = con->in_msg;
+	int ret;
+	int to, left;
+	unsigned front_len, middle_len, data_len, data_off;
+	int datacrc = con->msgr->nocrc;
+	int skip;
+	u64 seq;
+
+	dout("read_partial_message con %p msg %p\n", con, m);
+
+	/* header */
+	while (con->in_base_pos < sizeof(con->in_hdr)) {
+		left = sizeof(con->in_hdr) - con->in_base_pos;
+		ret = ceph_tcp_recvmsg(con->sock,
+				       (char *)&con->in_hdr + con->in_base_pos,
+				       left);
+		if (ret <= 0)
+			return ret;
+		con->in_base_pos += ret;
+		if (con->in_base_pos == sizeof(con->in_hdr)) {
+			u32 crc = crc32c(0, (void *)&con->in_hdr,
+				 sizeof(con->in_hdr) - sizeof(con->in_hdr.crc));
+			if (crc != le32_to_cpu(con->in_hdr.crc)) {
+				pr_err("read_partial_message bad hdr "
+				       " crc %u != expected %u\n",
+				       crc, con->in_hdr.crc);
+				return -EBADMSG;
+			}
+		}
+	}
+	front_len = le32_to_cpu(con->in_hdr.front_len);
+	if (front_len > CEPH_MSG_MAX_FRONT_LEN)
+		return -EIO;
+	middle_len = le32_to_cpu(con->in_hdr.middle_len);
+	if (middle_len > CEPH_MSG_MAX_DATA_LEN)
+		return -EIO;
+	data_len = le32_to_cpu(con->in_hdr.data_len);
+	if (data_len > CEPH_MSG_MAX_DATA_LEN)
+		return -EIO;
+	data_off = le16_to_cpu(con->in_hdr.data_off);
+
+	/* verify seq# */
+	seq = le64_to_cpu(con->in_hdr.seq);
+	if ((s64)seq - (s64)con->in_seq < 1) {
+		pr_info("skipping %s%lld %s seq %lld, expected %lld\n",
+			ENTITY_NAME(con->peer_name),
+			ceph_pr_addr(&con->peer_addr.in_addr),
+			seq, con->in_seq + 1);
+		con->in_base_pos = -front_len - middle_len - data_len -
+			sizeof(m->footer);
+		con->in_tag = CEPH_MSGR_TAG_READY;
+		con->in_seq++;
+		return 0;
+	} else if ((s64)seq - (s64)con->in_seq > 1) {
+		pr_err("read_partial_message bad seq %lld expected %lld\n",
+		       seq, con->in_seq + 1);
+		con->error_msg = "bad message sequence # for incoming message";
+		return -EBADMSG;
+	}
+
+	/* allocate message? */
+	if (!con->in_msg) {
+		dout("got hdr type %d front %d data %d\n", con->in_hdr.type,
+		     con->in_hdr.front_len, con->in_hdr.data_len);
+		skip = 0;
+		con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip);
+		if (skip) {
+			/* skip this message */
+			dout("alloc_msg said skip message\n");
+			BUG_ON(con->in_msg);
+			con->in_base_pos = -front_len - middle_len - data_len -
+				sizeof(m->footer);
+			con->in_tag = CEPH_MSGR_TAG_READY;
+			con->in_seq++;
+			return 0;
+		}
+		if (!con->in_msg) {
+			con->error_msg =
+				"error allocating memory for incoming message";
+			return -ENOMEM;
+		}
+		m = con->in_msg;
+		m->front.iov_len = 0;    /* haven't read it yet */
+		if (m->middle)
+			m->middle->vec.iov_len = 0;
+
+		con->in_msg_pos.page = 0;
+		if (m->pages)
+			con->in_msg_pos.page_pos = data_off & ~PAGE_MASK;
+		else
+			con->in_msg_pos.page_pos = 0;
+		con->in_msg_pos.data_pos = 0;
+	}
+
+	/* front */
+	ret = read_partial_message_section(con, &m->front, front_len,
+					   &con->in_front_crc);
+	if (ret <= 0)
+		return ret;
+
+	/* middle */
+	if (m->middle) {
+		ret = read_partial_message_section(con, &m->middle->vec,
+						   middle_len,
+						   &con->in_middle_crc);
+		if (ret <= 0)
+			return ret;
+	}
+#ifdef CONFIG_BLOCK
+	if (m->bio && !m->bio_iter)
+		init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg);
+#endif
+
+	/* (page) data */
+	while (con->in_msg_pos.data_pos < data_len) {
+		if (m->pages) {
+			ret = read_partial_message_pages(con, m->pages,
+						 data_len, datacrc);
+			if (ret <= 0)
+				return ret;
+#ifdef CONFIG_BLOCK
+		} else if (m->bio) {
+
+			ret = read_partial_message_bio(con,
+						 &m->bio_iter, &m->bio_seg,
+						 data_len, datacrc);
+			if (ret <= 0)
+				return ret;
+#endif
+		} else {
+			BUG_ON(1);
+		}
+	}
+
+	/* footer */
+	to = sizeof(m->hdr) + sizeof(m->footer);
+	while (con->in_base_pos < to) {
+		left = to - con->in_base_pos;
+		ret = ceph_tcp_recvmsg(con->sock, (char *)&m->footer +
+				       (con->in_base_pos - sizeof(m->hdr)),
+				       left);
+		if (ret <= 0)
+			return ret;
+		con->in_base_pos += ret;
+	}
+	dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n",
+	     m, front_len, m->footer.front_crc, middle_len,
+	     m->footer.middle_crc, data_len, m->footer.data_crc);
+
+	/* crc ok? */
+	if (con->in_front_crc != le32_to_cpu(m->footer.front_crc)) {
+		pr_err("read_partial_message %p front crc %u != exp. %u\n",
+		       m, con->in_front_crc, m->footer.front_crc);
+		return -EBADMSG;
+	}
+	if (con->in_middle_crc != le32_to_cpu(m->footer.middle_crc)) {
+		pr_err("read_partial_message %p middle crc %u != exp %u\n",
+		       m, con->in_middle_crc, m->footer.middle_crc);
+		return -EBADMSG;
+	}
+	if (datacrc &&
+	    (m->footer.flags & CEPH_MSG_FOOTER_NOCRC) == 0 &&
+	    con->in_data_crc != le32_to_cpu(m->footer.data_crc)) {
+		pr_err("read_partial_message %p data crc %u != exp. %u\n", m,
+		       con->in_data_crc, le32_to_cpu(m->footer.data_crc));
+		return -EBADMSG;
+	}
+
+	return 1; /* done! */
+}
+
+/*
+ * Process message.  This happens in the worker thread.  The callback should
+ * be careful not to do anything that waits on other incoming messages or it
+ * may deadlock.
+ */
+static void process_message(struct ceph_connection *con)
+{
+	struct ceph_msg *msg;
+
+	msg = con->in_msg;
+	con->in_msg = NULL;
+
+	/* if first message, set peer_name */
+	if (con->peer_name.type == 0)
+		con->peer_name = msg->hdr.src;
+
+	con->in_seq++;
+	mutex_unlock(&con->mutex);
+
+	dout("===== %p %llu from %s%lld %d=%s len %d+%d (%u %u %u) =====\n",
+	     msg, le64_to_cpu(msg->hdr.seq),
+	     ENTITY_NAME(msg->hdr.src),
+	     le16_to_cpu(msg->hdr.type),
+	     ceph_msg_type_name(le16_to_cpu(msg->hdr.type)),
+	     le32_to_cpu(msg->hdr.front_len),
+	     le32_to_cpu(msg->hdr.data_len),
+	     con->in_front_crc, con->in_middle_crc, con->in_data_crc);
+	con->ops->dispatch(con, msg);
+
+	mutex_lock(&con->mutex);
+	prepare_read_tag(con);
+}
+
+
+/*
+ * Write something to the socket.  Called in a worker thread when the
+ * socket appears to be writeable and we have something ready to send.
+ */
+static int try_write(struct ceph_connection *con)
+{
+	struct ceph_messenger *msgr = con->msgr;
+	int ret = 1;
+
+	dout("try_write start %p state %lu nref %d\n", con, con->state,
+	     atomic_read(&con->nref));
+
+more:
+	dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes);
+
+	/* open the socket first? */
+	if (con->sock == NULL) {
+		/*
+		 * if we were STANDBY and are reconnecting _this_
+		 * connection, bump connect_seq now.  Always bump
+		 * global_seq.
+		 */
+		if (test_and_clear_bit(STANDBY, &con->state))
+			con->connect_seq++;
+
+		prepare_write_banner(msgr, con);
+		prepare_write_connect(msgr, con, 1);
+		prepare_read_banner(con);
+		set_bit(CONNECTING, &con->state);
+		clear_bit(NEGOTIATING, &con->state);
+
+		BUG_ON(con->in_msg);
+		con->in_tag = CEPH_MSGR_TAG_READY;
+		dout("try_write initiating connect on %p new state %lu\n",
+		     con, con->state);
+		con->sock = ceph_tcp_connect(con);
+		if (IS_ERR(con->sock)) {
+			con->sock = NULL;
+			con->error_msg = "connect error";
+			ret = -1;
+			goto out;
+		}
+	}
+
+more_kvec:
+	/* kvec data queued? */
+	if (con->out_skip) {
+		ret = write_partial_skip(con);
+		if (ret <= 0)
+			goto done;
+		if (ret < 0) {
+			dout("try_write write_partial_skip err %d\n", ret);
+			goto done;
+		}
+	}
+	if (con->out_kvec_left) {
+		ret = write_partial_kvec(con);
+		if (ret <= 0)
+			goto done;
+	}
+
+	/* msg pages? */
+	if (con->out_msg) {
+		if (con->out_msg_done) {
+			ceph_msg_put(con->out_msg);
+			con->out_msg = NULL;   /* we're done with this one */
+			goto do_next;
+		}
+
+		ret = write_partial_msg_pages(con);
+		if (ret == 1)
+			goto more_kvec;  /* we need to send the footer, too! */
+		if (ret == 0)
+			goto done;
+		if (ret < 0) {
+			dout("try_write write_partial_msg_pages err %d\n",
+			     ret);
+			goto done;
+		}
+	}
+
+do_next:
+	if (!test_bit(CONNECTING, &con->state)) {
+		/* is anything else pending? */
+		if (!list_empty(&con->out_queue)) {
+			prepare_write_message(con);
+			goto more;
+		}
+		if (con->in_seq > con->in_seq_acked) {
+			prepare_write_ack(con);
+			goto more;
+		}
+		if (test_and_clear_bit(KEEPALIVE_PENDING, &con->state)) {
+			prepare_write_keepalive(con);
+			goto more;
+		}
+	}
+
+	/* Nothing to do! */
+	clear_bit(WRITE_PENDING, &con->state);
+	dout("try_write nothing else to write.\n");
+done:
+	ret = 0;
+out:
+	dout("try_write done on %p\n", con);
+	return ret;
+}
+
+
+
+/*
+ * Read what we can from the socket.
+ */
+static int try_read(struct ceph_connection *con)
+{
+	int ret = -1;
+
+	if (!con->sock)
+		return 0;
+
+	if (test_bit(STANDBY, &con->state))
+		return 0;
+
+	dout("try_read start on %p\n", con);
+
+more:
+	dout("try_read tag %d in_base_pos %d\n", (int)con->in_tag,
+	     con->in_base_pos);
+	if (test_bit(CONNECTING, &con->state)) {
+		if (!test_bit(NEGOTIATING, &con->state)) {
+			dout("try_read connecting\n");
+			ret = read_partial_banner(con);
+			if (ret <= 0)
+				goto done;
+			if (process_banner(con) < 0) {
+				ret = -1;
+				goto out;
+			}
+		}
+		ret = read_partial_connect(con);
+		if (ret <= 0)
+			goto done;
+		if (process_connect(con) < 0) {
+			ret = -1;
+			goto out;
+		}
+		goto more;
+	}
+
+	if (con->in_base_pos < 0) {
+		/*
+		 * skipping + discarding content.
+		 *
+		 * FIXME: there must be a better way to do this!
+		 */
+		static char buf[1024];
+		int skip = min(1024, -con->in_base_pos);
+		dout("skipping %d / %d bytes\n", skip, -con->in_base_pos);
+		ret = ceph_tcp_recvmsg(con->sock, buf, skip);
+		if (ret <= 0)
+			goto done;
+		con->in_base_pos += ret;
+		if (con->in_base_pos)
+			goto more;
+	}
+	if (con->in_tag == CEPH_MSGR_TAG_READY) {
+		/*
+		 * what's next?
+		 */
+		ret = ceph_tcp_recvmsg(con->sock, &con->in_tag, 1);
+		if (ret <= 0)
+			goto done;
+		dout("try_read got tag %d\n", (int)con->in_tag);
+		switch (con->in_tag) {
+		case CEPH_MSGR_TAG_MSG:
+			prepare_read_message(con);
+			break;
+		case CEPH_MSGR_TAG_ACK:
+			prepare_read_ack(con);
+			break;
+		case CEPH_MSGR_TAG_CLOSE:
+			set_bit(CLOSED, &con->state);   /* fixme */
+			goto done;
+		default:
+			goto bad_tag;
+		}
+	}
+	if (con->in_tag == CEPH_MSGR_TAG_MSG) {
+		ret = read_partial_message(con);
+		if (ret <= 0) {
+			switch (ret) {
+			case -EBADMSG:
+				con->error_msg = "bad crc";
+				ret = -EIO;
+				goto out;
+			case -EIO:
+				con->error_msg = "io error";
+				goto out;
+			default:
+				goto done;
+			}
+		}
+		if (con->in_tag == CEPH_MSGR_TAG_READY)
+			goto more;
+		process_message(con);
+		goto more;
+	}
+	if (con->in_tag == CEPH_MSGR_TAG_ACK) {
+		ret = read_partial_ack(con);
+		if (ret <= 0)
+			goto done;
+		process_ack(con);
+		goto more;
+	}
+
+done:
+	ret = 0;
+out:
+	dout("try_read done on %p\n", con);
+	return ret;
+
+bad_tag:
+	pr_err("try_read bad con->in_tag = %d\n", (int)con->in_tag);
+	con->error_msg = "protocol error, garbage tag";
+	ret = -1;
+	goto out;
+}
+
+
+/*
+ * Atomically queue work on a connection.  Bump @con reference to
+ * avoid races with connection teardown.
+ *
+ * There is some trickery going on with QUEUED and BUSY because we
+ * only want a _single_ thread operating on each connection at any
+ * point in time, but we want to use all available CPUs.
+ *
+ * The worker thread only proceeds if it can atomically set BUSY.  It
+ * clears QUEUED and does it's thing.  When it thinks it's done, it
+ * clears BUSY, then rechecks QUEUED.. if it's set again, it loops
+ * (tries again to set BUSY).
+ *
+ * To queue work, we first set QUEUED, _then_ if BUSY isn't set, we
+ * try to queue work.  If that fails (work is already queued, or BUSY)
+ * we give up (work also already being done or is queued) but leave QUEUED
+ * set so that the worker thread will loop if necessary.
+ */
+static void queue_con(struct ceph_connection *con)
+{
+	if (test_bit(DEAD, &con->state)) {
+		dout("queue_con %p ignoring: DEAD\n",
+		     con);
+		return;
+	}
+
+	if (!con->ops->get(con)) {
+		dout("queue_con %p ref count 0\n", con);
+		return;
+	}
+
+	set_bit(QUEUED, &con->state);
+	if (test_bit(BUSY, &con->state)) {
+		dout("queue_con %p - already BUSY\n", con);
+		con->ops->put(con);
+	} else if (!queue_work(ceph_msgr_wq, &con->work.work)) {
+		dout("queue_con %p - already queued\n", con);
+		con->ops->put(con);
+	} else {
+		dout("queue_con %p\n", con);
+	}
+}
+
+/*
+ * Do some work on a connection.  Drop a connection ref when we're done.
+ */
+static void con_work(struct work_struct *work)
+{
+	struct ceph_connection *con = container_of(work, struct ceph_connection,
+						   work.work);
+	int backoff = 0;
+
+more:
+	if (test_and_set_bit(BUSY, &con->state) != 0) {
+		dout("con_work %p BUSY already set\n", con);
+		goto out;
+	}
+	dout("con_work %p start, clearing QUEUED\n", con);
+	clear_bit(QUEUED, &con->state);
+
+	mutex_lock(&con->mutex);
+
+	if (test_bit(CLOSED, &con->state)) { /* e.g. if we are replaced */
+		dout("con_work CLOSED\n");
+		con_close_socket(con);
+		goto done;
+	}
+	if (test_and_clear_bit(OPENING, &con->state)) {
+		/* reopen w/ new peer */
+		dout("con_work OPENING\n");
+		con_close_socket(con);
+	}
+
+	if (test_and_clear_bit(SOCK_CLOSED, &con->state) ||
+	    try_read(con) < 0 ||
+	    try_write(con) < 0) {
+		mutex_unlock(&con->mutex);
+		backoff = 1;
+		ceph_fault(con);     /* error/fault path */
+		goto done_unlocked;
+	}
+
+done:
+	mutex_unlock(&con->mutex);
+
+done_unlocked:
+	clear_bit(BUSY, &con->state);
+	dout("con->state=%lu\n", con->state);
+	if (test_bit(QUEUED, &con->state)) {
+		if (!backoff || test_bit(OPENING, &con->state)) {
+			dout("con_work %p QUEUED reset, looping\n", con);
+			goto more;
+		}
+		dout("con_work %p QUEUED reset, but just faulted\n", con);
+		clear_bit(QUEUED, &con->state);
+	}
+	dout("con_work %p done\n", con);
+
+out:
+	con->ops->put(con);
+}
+
+
+/*
+ * Generic error/fault handler.  A retry mechanism is used with
+ * exponential backoff
+ */
+static void ceph_fault(struct ceph_connection *con)
+{
+	pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
+	       ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
+	dout("fault %p state %lu to peer %s\n",
+	     con, con->state, ceph_pr_addr(&con->peer_addr.in_addr));
+
+	if (test_bit(LOSSYTX, &con->state)) {
+		dout("fault on LOSSYTX channel\n");
+		goto out;
+	}
+
+	mutex_lock(&con->mutex);
+	if (test_bit(CLOSED, &con->state))
+		goto out_unlock;
+
+	con_close_socket(con);
+
+	if (con->in_msg) {
+		ceph_msg_put(con->in_msg);
+		con->in_msg = NULL;
+	}
+
+	/* Requeue anything that hasn't been acked */
+	list_splice_init(&con->out_sent, &con->out_queue);
+
+	/* If there are no messages in the queue, place the connection
+	 * in a STANDBY state (i.e., don't try to reconnect just yet). */
+	if (list_empty(&con->out_queue) && !con->out_keepalive_pending) {
+		dout("fault setting STANDBY\n");
+		set_bit(STANDBY, &con->state);
+	} else {
+		/* retry after a delay. */
+		if (con->delay == 0)
+			con->delay = BASE_DELAY_INTERVAL;
+		else if (con->delay < MAX_DELAY_INTERVAL)
+			con->delay *= 2;
+		dout("fault queueing %p delay %lu\n", con, con->delay);
+		con->ops->get(con);
+		if (queue_delayed_work(ceph_msgr_wq, &con->work,
+				       round_jiffies_relative(con->delay)) == 0)
+			con->ops->put(con);
+	}
+
+out_unlock:
+	mutex_unlock(&con->mutex);
+out:
+	/*
+	 * in case we faulted due to authentication, invalidate our
+	 * current tickets so that we can get new ones.
+	 */
+	if (con->auth_retry && con->ops->invalidate_authorizer) {
+		dout("calling invalidate_authorizer()\n");
+		con->ops->invalidate_authorizer(con);
+	}
+
+	if (con->ops->fault)
+		con->ops->fault(con);
+}
+
+
+
+/*
+ * create a new messenger instance
+ */
+struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr,
+					     u32 supported_features,
+					     u32 required_features)
+{
+	struct ceph_messenger *msgr;
+
+	msgr = kzalloc(sizeof(*msgr), GFP_KERNEL);
+	if (msgr == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	msgr->supported_features = supported_features;
+	msgr->required_features = required_features;
+
+	spin_lock_init(&msgr->global_seq_lock);
+
+	/* the zero page is needed if a request is "canceled" while the message
+	 * is being written over the socket */
+	msgr->zero_page = __page_cache_alloc(GFP_KERNEL | __GFP_ZERO);
+	if (!msgr->zero_page) {
+		kfree(msgr);
+		return ERR_PTR(-ENOMEM);
+	}
+	kmap(msgr->zero_page);
+
+	if (myaddr)
+		msgr->inst.addr = *myaddr;
+
+	/* select a random nonce */
+	msgr->inst.addr.type = 0;
+	get_random_bytes(&msgr->inst.addr.nonce, sizeof(msgr->inst.addr.nonce));
+	encode_my_addr(msgr);
+
+	dout("messenger_create %p\n", msgr);
+	return msgr;
+}
+EXPORT_SYMBOL(ceph_messenger_create);
+
+void ceph_messenger_destroy(struct ceph_messenger *msgr)
+{
+	dout("destroy %p\n", msgr);
+	kunmap(msgr->zero_page);
+	__free_page(msgr->zero_page);
+	kfree(msgr);
+	dout("destroyed messenger %p\n", msgr);
+}
+EXPORT_SYMBOL(ceph_messenger_destroy);
+
+/*
+ * Queue up an outgoing message on the given connection.
+ */
+void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg)
+{
+	if (test_bit(CLOSED, &con->state)) {
+		dout("con_send %p closed, dropping %p\n", con, msg);
+		ceph_msg_put(msg);
+		return;
+	}
+
+	/* set src+dst */
+	msg->hdr.src = con->msgr->inst.name;
+
+	BUG_ON(msg->front.iov_len != le32_to_cpu(msg->hdr.front_len));
+
+	msg->needs_out_seq = true;
+
+	/* queue */
+	mutex_lock(&con->mutex);
+	BUG_ON(!list_empty(&msg->list_head));
+	list_add_tail(&msg->list_head, &con->out_queue);
+	dout("----- %p to %s%lld %d=%s len %d+%d+%d -----\n", msg,
+	     ENTITY_NAME(con->peer_name), le16_to_cpu(msg->hdr.type),
+	     ceph_msg_type_name(le16_to_cpu(msg->hdr.type)),
+	     le32_to_cpu(msg->hdr.front_len),
+	     le32_to_cpu(msg->hdr.middle_len),
+	     le32_to_cpu(msg->hdr.data_len));
+	mutex_unlock(&con->mutex);
+
+	/* if there wasn't anything waiting to send before, queue
+	 * new work */
+	if (test_and_set_bit(WRITE_PENDING, &con->state) == 0)
+		queue_con(con);
+}
+EXPORT_SYMBOL(ceph_con_send);
+
+/*
+ * Revoke a message that was previously queued for send
+ */
+void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg)
+{
+	mutex_lock(&con->mutex);
+	if (!list_empty(&msg->list_head)) {
+		dout("con_revoke %p msg %p - was on queue\n", con, msg);
+		list_del_init(&msg->list_head);
+		ceph_msg_put(msg);
+		msg->hdr.seq = 0;
+	}
+	if (con->out_msg == msg) {
+		dout("con_revoke %p msg %p - was sending\n", con, msg);
+		con->out_msg = NULL;
+		if (con->out_kvec_is_msg) {
+			con->out_skip = con->out_kvec_bytes;
+			con->out_kvec_is_msg = false;
+		}
+		ceph_msg_put(msg);
+		msg->hdr.seq = 0;
+	}
+	mutex_unlock(&con->mutex);
+}
+
+/*
+ * Revoke a message that we may be reading data into
+ */
+void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg)
+{
+	mutex_lock(&con->mutex);
+	if (con->in_msg && con->in_msg == msg) {
+		unsigned front_len = le32_to_cpu(con->in_hdr.front_len);
+		unsigned middle_len = le32_to_cpu(con->in_hdr.middle_len);
+		unsigned data_len = le32_to_cpu(con->in_hdr.data_len);
+
+		/* skip rest of message */
+		dout("con_revoke_pages %p msg %p revoked\n", con, msg);
+			con->in_base_pos = con->in_base_pos -
+				sizeof(struct ceph_msg_header) -
+				front_len -
+				middle_len -
+				data_len -
+				sizeof(struct ceph_msg_footer);
+		ceph_msg_put(con->in_msg);
+		con->in_msg = NULL;
+		con->in_tag = CEPH_MSGR_TAG_READY;
+		con->in_seq++;
+	} else {
+		dout("con_revoke_pages %p msg %p pages %p no-op\n",
+		     con, con->in_msg, msg);
+	}
+	mutex_unlock(&con->mutex);
+}
+
+/*
+ * Queue a keepalive byte to ensure the tcp connection is alive.
+ */
+void ceph_con_keepalive(struct ceph_connection *con)
+{
+	if (test_and_set_bit(KEEPALIVE_PENDING, &con->state) == 0 &&
+	    test_and_set_bit(WRITE_PENDING, &con->state) == 0)
+		queue_con(con);
+}
+EXPORT_SYMBOL(ceph_con_keepalive);
+
+
+/*
+ * construct a new message with given type, size
+ * the new msg has a ref count of 1.
+ */
+struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags)
+{
+	struct ceph_msg *m;
+
+	m = kmalloc(sizeof(*m), flags);
+	if (m == NULL)
+		goto out;
+	kref_init(&m->kref);
+	INIT_LIST_HEAD(&m->list_head);
+
+	m->hdr.tid = 0;
+	m->hdr.type = cpu_to_le16(type);
+	m->hdr.priority = cpu_to_le16(CEPH_MSG_PRIO_DEFAULT);
+	m->hdr.version = 0;
+	m->hdr.front_len = cpu_to_le32(front_len);
+	m->hdr.middle_len = 0;
+	m->hdr.data_len = 0;
+	m->hdr.data_off = 0;
+	m->hdr.reserved = 0;
+	m->footer.front_crc = 0;
+	m->footer.middle_crc = 0;
+	m->footer.data_crc = 0;
+	m->footer.flags = 0;
+	m->front_max = front_len;
+	m->front_is_vmalloc = false;
+	m->more_to_follow = false;
+	m->pool = NULL;
+
+	/* front */
+	if (front_len) {
+		if (front_len > PAGE_CACHE_SIZE) {
+			m->front.iov_base = __vmalloc(front_len, flags,
+						      PAGE_KERNEL);
+			m->front_is_vmalloc = true;
+		} else {
+			m->front.iov_base = kmalloc(front_len, flags);
+		}
+		if (m->front.iov_base == NULL) {
+			pr_err("msg_new can't allocate %d bytes\n",
+			     front_len);
+			goto out2;
+		}
+	} else {
+		m->front.iov_base = NULL;
+	}
+	m->front.iov_len = front_len;
+
+	/* middle */
+	m->middle = NULL;
+
+	/* data */
+	m->nr_pages = 0;
+	m->pages = NULL;
+	m->pagelist = NULL;
+	m->bio = NULL;
+	m->bio_iter = NULL;
+	m->bio_seg = 0;
+	m->trail = NULL;
+
+	dout("ceph_msg_new %p front %d\n", m, front_len);
+	return m;
+
+out2:
+	ceph_msg_put(m);
+out:
+	pr_err("msg_new can't create type %d front %d\n", type, front_len);
+	return NULL;
+}
+EXPORT_SYMBOL(ceph_msg_new);
+
+/*
+ * Allocate "middle" portion of a message, if it is needed and wasn't
+ * allocated by alloc_msg.  This allows us to read a small fixed-size
+ * per-type header in the front and then gracefully fail (i.e.,
+ * propagate the error to the caller based on info in the front) when
+ * the middle is too large.
+ */
+static int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg)
+{
+	int type = le16_to_cpu(msg->hdr.type);
+	int middle_len = le32_to_cpu(msg->hdr.middle_len);
+
+	dout("alloc_middle %p type %d %s middle_len %d\n", msg, type,
+	     ceph_msg_type_name(type), middle_len);
+	BUG_ON(!middle_len);
+	BUG_ON(msg->middle);
+
+	msg->middle = ceph_buffer_new(middle_len, GFP_NOFS);
+	if (!msg->middle)
+		return -ENOMEM;
+	return 0;
+}
+
+/*
+ * Generic message allocator, for incoming messages.
+ */
+static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con,
+				struct ceph_msg_header *hdr,
+				int *skip)
+{
+	int type = le16_to_cpu(hdr->type);
+	int front_len = le32_to_cpu(hdr->front_len);
+	int middle_len = le32_to_cpu(hdr->middle_len);
+	struct ceph_msg *msg = NULL;
+	int ret;
+
+	if (con->ops->alloc_msg) {
+		mutex_unlock(&con->mutex);
+		msg = con->ops->alloc_msg(con, hdr, skip);
+		mutex_lock(&con->mutex);
+		if (!msg || *skip)
+			return NULL;
+	}
+	if (!msg) {
+		*skip = 0;
+		msg = ceph_msg_new(type, front_len, GFP_NOFS);
+		if (!msg) {
+			pr_err("unable to allocate msg type %d len %d\n",
+			       type, front_len);
+			return NULL;
+		}
+	}
+	memcpy(&msg->hdr, &con->in_hdr, sizeof(con->in_hdr));
+
+	if (middle_len && !msg->middle) {
+		ret = ceph_alloc_middle(con, msg);
+		if (ret < 0) {
+			ceph_msg_put(msg);
+			return NULL;
+		}
+	}
+
+	return msg;
+}
+
+
+/*
+ * Free a generically kmalloc'd message.
+ */
+void ceph_msg_kfree(struct ceph_msg *m)
+{
+	dout("msg_kfree %p\n", m);
+	if (m->front_is_vmalloc)
+		vfree(m->front.iov_base);
+	else
+		kfree(m->front.iov_base);
+	kfree(m);
+}
+
+/*
+ * Drop a msg ref.  Destroy as needed.
+ */
+void ceph_msg_last_put(struct kref *kref)
+{
+	struct ceph_msg *m = container_of(kref, struct ceph_msg, kref);
+
+	dout("ceph_msg_put last one on %p\n", m);
+	WARN_ON(!list_empty(&m->list_head));
+
+	/* drop middle, data, if any */
+	if (m->middle) {
+		ceph_buffer_put(m->middle);
+		m->middle = NULL;
+	}
+	m->nr_pages = 0;
+	m->pages = NULL;
+
+	if (m->pagelist) {
+		ceph_pagelist_release(m->pagelist);
+		kfree(m->pagelist);
+		m->pagelist = NULL;
+	}
+
+	m->trail = NULL;
+
+	if (m->pool)
+		ceph_msgpool_put(m->pool, m);
+	else
+		ceph_msg_kfree(m);
+}
+EXPORT_SYMBOL(ceph_msg_last_put);
+
+void ceph_msg_dump(struct ceph_msg *msg)
+{
+	pr_debug("msg_dump %p (front_max %d nr_pages %d)\n", msg,
+		 msg->front_max, msg->nr_pages);
+	print_hex_dump(KERN_DEBUG, "header: ",
+		       DUMP_PREFIX_OFFSET, 16, 1,
+		       &msg->hdr, sizeof(msg->hdr), true);
+	print_hex_dump(KERN_DEBUG, " front: ",
+		       DUMP_PREFIX_OFFSET, 16, 1,
+		       msg->front.iov_base, msg->front.iov_len, true);
+	if (msg->middle)
+		print_hex_dump(KERN_DEBUG, "middle: ",
+			       DUMP_PREFIX_OFFSET, 16, 1,
+			       msg->middle->vec.iov_base,
+			       msg->middle->vec.iov_len, true);
+	print_hex_dump(KERN_DEBUG, "footer: ",
+		       DUMP_PREFIX_OFFSET, 16, 1,
+		       &msg->footer, sizeof(msg->footer), true);
+}
+EXPORT_SYMBOL(ceph_msg_dump);
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c
new file mode 100644
index 0000000..8a07939
--- /dev/null
+++ b/net/ceph/mon_client.c
@@ -0,0 +1,1027 @@
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/decode.h>
+
+#include <linux/ceph/auth.h>
+
+/*
+ * Interact with Ceph monitor cluster.  Handle requests for new map
+ * versions, and periodically resend as needed.  Also implement
+ * statfs() and umount().
+ *
+ * A small cluster of Ceph "monitors" are responsible for managing critical
+ * cluster configuration and state information.  An odd number (e.g., 3, 5)
+ * of cmon daemons use a modified version of the Paxos part-time parliament
+ * algorithm to manage the MDS map (mds cluster membership), OSD map, and
+ * list of clients who have mounted the file system.
+ *
+ * We maintain an open, active session with a monitor at all times in order to
+ * receive timely MDSMap updates.  We periodically send a keepalive byte on the
+ * TCP socket to ensure we detect a failure.  If the connection does break, we
+ * randomly hunt for a new monitor.  Once the connection is reestablished, we
+ * resend any outstanding requests.
+ */
+
+static const struct ceph_connection_operations mon_con_ops;
+
+static int __validate_auth(struct ceph_mon_client *monc);
+
+/*
+ * Decode a monmap blob (e.g., during mount).
+ */
+struct ceph_monmap *ceph_monmap_decode(void *p, void *end)
+{
+	struct ceph_monmap *m = NULL;
+	int i, err = -EINVAL;
+	struct ceph_fsid fsid;
+	u32 epoch, num_mon;
+	u16 version;
+	u32 len;
+
+	ceph_decode_32_safe(&p, end, len, bad);
+	ceph_decode_need(&p, end, len, bad);
+
+	dout("monmap_decode %p %p len %d\n", p, end, (int)(end-p));
+
+	ceph_decode_16_safe(&p, end, version, bad);
+
+	ceph_decode_need(&p, end, sizeof(fsid) + 2*sizeof(u32), bad);
+	ceph_decode_copy(&p, &fsid, sizeof(fsid));
+	epoch = ceph_decode_32(&p);
+
+	num_mon = ceph_decode_32(&p);
+	ceph_decode_need(&p, end, num_mon*sizeof(m->mon_inst[0]), bad);
+
+	if (num_mon >= CEPH_MAX_MON)
+		goto bad;
+	m = kmalloc(sizeof(*m) + sizeof(m->mon_inst[0])*num_mon, GFP_NOFS);
+	if (m == NULL)
+		return ERR_PTR(-ENOMEM);
+	m->fsid = fsid;
+	m->epoch = epoch;
+	m->num_mon = num_mon;
+	ceph_decode_copy(&p, m->mon_inst, num_mon*sizeof(m->mon_inst[0]));
+	for (i = 0; i < num_mon; i++)
+		ceph_decode_addr(&m->mon_inst[i].addr);
+
+	dout("monmap_decode epoch %d, num_mon %d\n", m->epoch,
+	     m->num_mon);
+	for (i = 0; i < m->num_mon; i++)
+		dout("monmap_decode  mon%d is %s\n", i,
+		     ceph_pr_addr(&m->mon_inst[i].addr.in_addr));
+	return m;
+
+bad:
+	dout("monmap_decode failed with %d\n", err);
+	kfree(m);
+	return ERR_PTR(err);
+}
+
+/*
+ * return true if *addr is included in the monmap.
+ */
+int ceph_monmap_contains(struct ceph_monmap *m, struct ceph_entity_addr *addr)
+{
+	int i;
+
+	for (i = 0; i < m->num_mon; i++)
+		if (memcmp(addr, &m->mon_inst[i].addr, sizeof(*addr)) == 0)
+			return 1;
+	return 0;
+}
+
+/*
+ * Send an auth request.
+ */
+static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len)
+{
+	monc->pending_auth = 1;
+	monc->m_auth->front.iov_len = len;
+	monc->m_auth->hdr.front_len = cpu_to_le32(len);
+	ceph_con_revoke(monc->con, monc->m_auth);
+	ceph_msg_get(monc->m_auth);  /* keep our ref */
+	ceph_con_send(monc->con, monc->m_auth);
+}
+
+/*
+ * Close monitor session, if any.
+ */
+static void __close_session(struct ceph_mon_client *monc)
+{
+	if (monc->con) {
+		dout("__close_session closing mon%d\n", monc->cur_mon);
+		ceph_con_revoke(monc->con, monc->m_auth);
+		ceph_con_close(monc->con);
+		monc->cur_mon = -1;
+		monc->pending_auth = 0;
+		ceph_auth_reset(monc->auth);
+	}
+}
+
+/*
+ * Open a session with a (new) monitor.
+ */
+static int __open_session(struct ceph_mon_client *monc)
+{
+	char r;
+	int ret;
+
+	if (monc->cur_mon < 0) {
+		get_random_bytes(&r, 1);
+		monc->cur_mon = r % monc->monmap->num_mon;
+		dout("open_session num=%d r=%d -> mon%d\n",
+		     monc->monmap->num_mon, r, monc->cur_mon);
+		monc->sub_sent = 0;
+		monc->sub_renew_after = jiffies;  /* i.e., expired */
+		monc->want_next_osdmap = !!monc->want_next_osdmap;
+
+		dout("open_session mon%d opening\n", monc->cur_mon);
+		monc->con->peer_name.type = CEPH_ENTITY_TYPE_MON;
+		monc->con->peer_name.num = cpu_to_le64(monc->cur_mon);
+		ceph_con_open(monc->con,
+			      &monc->monmap->mon_inst[monc->cur_mon].addr);
+
+		/* initiatiate authentication handshake */
+		ret = ceph_auth_build_hello(monc->auth,
+					    monc->m_auth->front.iov_base,
+					    monc->m_auth->front_max);
+		__send_prepared_auth_request(monc, ret);
+	} else {
+		dout("open_session mon%d already open\n", monc->cur_mon);
+	}
+	return 0;
+}
+
+static bool __sub_expired(struct ceph_mon_client *monc)
+{
+	return time_after_eq(jiffies, monc->sub_renew_after);
+}
+
+/*
+ * Reschedule delayed work timer.
+ */
+static void __schedule_delayed(struct ceph_mon_client *monc)
+{
+	unsigned delay;
+
+	if (monc->cur_mon < 0 || __sub_expired(monc))
+		delay = 10 * HZ;
+	else
+		delay = 20 * HZ;
+	dout("__schedule_delayed after %u\n", delay);
+	schedule_delayed_work(&monc->delayed_work, delay);
+}
+
+/*
+ * Send subscribe request for mdsmap and/or osdmap.
+ */
+static void __send_subscribe(struct ceph_mon_client *monc)
+{
+	dout("__send_subscribe sub_sent=%u exp=%u want_osd=%d\n",
+	     (unsigned)monc->sub_sent, __sub_expired(monc),
+	     monc->want_next_osdmap);
+	if ((__sub_expired(monc) && !monc->sub_sent) ||
+	    monc->want_next_osdmap == 1) {
+		struct ceph_msg *msg = monc->m_subscribe;
+		struct ceph_mon_subscribe_item *i;
+		void *p, *end;
+		int num;
+
+		p = msg->front.iov_base;
+		end = p + msg->front_max;
+
+		num = 1 + !!monc->want_next_osdmap + !!monc->want_mdsmap;
+		ceph_encode_32(&p, num);
+
+		if (monc->want_next_osdmap) {
+			dout("__send_subscribe to 'osdmap' %u\n",
+			     (unsigned)monc->have_osdmap);
+			ceph_encode_string(&p, end, "osdmap", 6);
+			i = p;
+			i->have = cpu_to_le64(monc->have_osdmap);
+			i->onetime = 1;
+			p += sizeof(*i);
+			monc->want_next_osdmap = 2;  /* requested */
+		}
+		if (monc->want_mdsmap) {
+			dout("__send_subscribe to 'mdsmap' %u+\n",
+			     (unsigned)monc->have_mdsmap);
+			ceph_encode_string(&p, end, "mdsmap", 6);
+			i = p;
+			i->have = cpu_to_le64(monc->have_mdsmap);
+			i->onetime = 0;
+			p += sizeof(*i);
+		}
+		ceph_encode_string(&p, end, "monmap", 6);
+		i = p;
+		i->have = 0;
+		i->onetime = 0;
+		p += sizeof(*i);
+
+		msg->front.iov_len = p - msg->front.iov_base;
+		msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
+		ceph_con_revoke(monc->con, msg);
+		ceph_con_send(monc->con, ceph_msg_get(msg));
+
+		monc->sub_sent = jiffies | 1;  /* never 0 */
+	}
+}
+
+static void handle_subscribe_ack(struct ceph_mon_client *monc,
+				 struct ceph_msg *msg)
+{
+	unsigned seconds;
+	struct ceph_mon_subscribe_ack *h = msg->front.iov_base;
+
+	if (msg->front.iov_len < sizeof(*h))
+		goto bad;
+	seconds = le32_to_cpu(h->duration);
+
+	mutex_lock(&monc->mutex);
+	if (monc->hunting) {
+		pr_info("mon%d %s session established\n",
+			monc->cur_mon,
+			ceph_pr_addr(&monc->con->peer_addr.in_addr));
+		monc->hunting = false;
+	}
+	dout("handle_subscribe_ack after %d seconds\n", seconds);
+	monc->sub_renew_after = monc->sub_sent + (seconds >> 1)*HZ - 1;
+	monc->sub_sent = 0;
+	mutex_unlock(&monc->mutex);
+	return;
+bad:
+	pr_err("got corrupt subscribe-ack msg\n");
+	ceph_msg_dump(msg);
+}
+
+/*
+ * Keep track of which maps we have
+ */
+int ceph_monc_got_mdsmap(struct ceph_mon_client *monc, u32 got)
+{
+	mutex_lock(&monc->mutex);
+	monc->have_mdsmap = got;
+	mutex_unlock(&monc->mutex);
+	return 0;
+}
+EXPORT_SYMBOL(ceph_monc_got_mdsmap);
+
+int ceph_monc_got_osdmap(struct ceph_mon_client *monc, u32 got)
+{
+	mutex_lock(&monc->mutex);
+	monc->have_osdmap = got;
+	monc->want_next_osdmap = 0;
+	mutex_unlock(&monc->mutex);
+	return 0;
+}
+
+/*
+ * Register interest in the next osdmap
+ */
+void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc)
+{
+	dout("request_next_osdmap have %u\n", monc->have_osdmap);
+	mutex_lock(&monc->mutex);
+	if (!monc->want_next_osdmap)
+		monc->want_next_osdmap = 1;
+	if (monc->want_next_osdmap < 2)
+		__send_subscribe(monc);
+	mutex_unlock(&monc->mutex);
+}
+
+/*
+ *
+ */
+int ceph_monc_open_session(struct ceph_mon_client *monc)
+{
+	if (!monc->con) {
+		monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL);
+		if (!monc->con)
+			return -ENOMEM;
+		ceph_con_init(monc->client->msgr, monc->con);
+		monc->con->private = monc;
+		monc->con->ops = &mon_con_ops;
+	}
+
+	mutex_lock(&monc->mutex);
+	__open_session(monc);
+	__schedule_delayed(monc);
+	mutex_unlock(&monc->mutex);
+	return 0;
+}
+EXPORT_SYMBOL(ceph_monc_open_session);
+
+/*
+ * The monitor responds with mount ack indicate mount success.  The
+ * included client ticket allows the client to talk to MDSs and OSDs.
+ */
+static void ceph_monc_handle_map(struct ceph_mon_client *monc,
+				 struct ceph_msg *msg)
+{
+	struct ceph_client *client = monc->client;
+	struct ceph_monmap *monmap = NULL, *old = monc->monmap;
+	void *p, *end;
+
+	mutex_lock(&monc->mutex);
+
+	dout("handle_monmap\n");
+	p = msg->front.iov_base;
+	end = p + msg->front.iov_len;
+
+	monmap = ceph_monmap_decode(p, end);
+	if (IS_ERR(monmap)) {
+		pr_err("problem decoding monmap, %d\n",
+		       (int)PTR_ERR(monmap));
+		goto out;
+	}
+
+	if (ceph_check_fsid(monc->client, &monmap->fsid) < 0) {
+		kfree(monmap);
+		goto out;
+	}
+
+	client->monc.monmap = monmap;
+	kfree(old);
+
+out:
+	mutex_unlock(&monc->mutex);
+	wake_up_all(&client->auth_wq);
+}
+
+/*
+ * generic requests (e.g., statfs, poolop)
+ */
+static struct ceph_mon_generic_request *__lookup_generic_req(
+	struct ceph_mon_client *monc, u64 tid)
+{
+	struct ceph_mon_generic_request *req;
+	struct rb_node *n = monc->generic_request_tree.rb_node;
+
+	while (n) {
+		req = rb_entry(n, struct ceph_mon_generic_request, node);
+		if (tid < req->tid)
+			n = n->rb_left;
+		else if (tid > req->tid)
+			n = n->rb_right;
+		else
+			return req;
+	}
+	return NULL;
+}
+
+static void __insert_generic_request(struct ceph_mon_client *monc,
+			    struct ceph_mon_generic_request *new)
+{
+	struct rb_node **p = &monc->generic_request_tree.rb_node;
+	struct rb_node *parent = NULL;
+	struct ceph_mon_generic_request *req = NULL;
+
+	while (*p) {
+		parent = *p;
+		req = rb_entry(parent, struct ceph_mon_generic_request, node);
+		if (new->tid < req->tid)
+			p = &(*p)->rb_left;
+		else if (new->tid > req->tid)
+			p = &(*p)->rb_right;
+		else
+			BUG();
+	}
+
+	rb_link_node(&new->node, parent, p);
+	rb_insert_color(&new->node, &monc->generic_request_tree);
+}
+
+static void release_generic_request(struct kref *kref)
+{
+	struct ceph_mon_generic_request *req =
+		container_of(kref, struct ceph_mon_generic_request, kref);
+
+	if (req->reply)
+		ceph_msg_put(req->reply);
+	if (req->request)
+		ceph_msg_put(req->request);
+
+	kfree(req);
+}
+
+static void put_generic_request(struct ceph_mon_generic_request *req)
+{
+	kref_put(&req->kref, release_generic_request);
+}
+
+static void get_generic_request(struct ceph_mon_generic_request *req)
+{
+	kref_get(&req->kref);
+}
+
+static struct ceph_msg *get_generic_reply(struct ceph_connection *con,
+					 struct ceph_msg_header *hdr,
+					 int *skip)
+{
+	struct ceph_mon_client *monc = con->private;
+	struct ceph_mon_generic_request *req;
+	u64 tid = le64_to_cpu(hdr->tid);
+	struct ceph_msg *m;
+
+	mutex_lock(&monc->mutex);
+	req = __lookup_generic_req(monc, tid);
+	if (!req) {
+		dout("get_generic_reply %lld dne\n", tid);
+		*skip = 1;
+		m = NULL;
+	} else {
+		dout("get_generic_reply %lld got %p\n", tid, req->reply);
+		m = ceph_msg_get(req->reply);
+		/*
+		 * we don't need to track the connection reading into
+		 * this reply because we only have one open connection
+		 * at a time, ever.
+		 */
+	}
+	mutex_unlock(&monc->mutex);
+	return m;
+}
+
+static int do_generic_request(struct ceph_mon_client *monc,
+			      struct ceph_mon_generic_request *req)
+{
+	int err;
+
+	/* register request */
+	mutex_lock(&monc->mutex);
+	req->tid = ++monc->last_tid;
+	req->request->hdr.tid = cpu_to_le64(req->tid);
+	__insert_generic_request(monc, req);
+	monc->num_generic_requests++;
+	ceph_con_send(monc->con, ceph_msg_get(req->request));
+	mutex_unlock(&monc->mutex);
+
+	err = wait_for_completion_interruptible(&req->completion);
+
+	mutex_lock(&monc->mutex);
+	rb_erase(&req->node, &monc->generic_request_tree);
+	monc->num_generic_requests--;
+	mutex_unlock(&monc->mutex);
+
+	if (!err)
+		err = req->result;
+	return err;
+}
+
+/*
+ * statfs
+ */
+static void handle_statfs_reply(struct ceph_mon_client *monc,
+				struct ceph_msg *msg)
+{
+	struct ceph_mon_generic_request *req;
+	struct ceph_mon_statfs_reply *reply = msg->front.iov_base;
+	u64 tid = le64_to_cpu(msg->hdr.tid);
+
+	if (msg->front.iov_len != sizeof(*reply))
+		goto bad;
+	dout("handle_statfs_reply %p tid %llu\n", msg, tid);
+
+	mutex_lock(&monc->mutex);
+	req = __lookup_generic_req(monc, tid);
+	if (req) {
+		*(struct ceph_statfs *)req->buf = reply->st;
+		req->result = 0;
+		get_generic_request(req);
+	}
+	mutex_unlock(&monc->mutex);
+	if (req) {
+		complete_all(&req->completion);
+		put_generic_request(req);
+	}
+	return;
+
+bad:
+	pr_err("corrupt generic reply, tid %llu\n", tid);
+	ceph_msg_dump(msg);
+}
+
+/*
+ * Do a synchronous statfs().
+ */
+int ceph_monc_do_statfs(struct ceph_mon_client *monc, struct ceph_statfs *buf)
+{
+	struct ceph_mon_generic_request *req;
+	struct ceph_mon_statfs *h;
+	int err;
+
+	req = kzalloc(sizeof(*req), GFP_NOFS);
+	if (!req)
+		return -ENOMEM;
+
+	kref_init(&req->kref);
+	req->buf = buf;
+	req->buf_len = sizeof(*buf);
+	init_completion(&req->completion);
+
+	err = -ENOMEM;
+	req->request = ceph_msg_new(CEPH_MSG_STATFS, sizeof(*h), GFP_NOFS);
+	if (!req->request)
+		goto out;
+	req->reply = ceph_msg_new(CEPH_MSG_STATFS_REPLY, 1024, GFP_NOFS);
+	if (!req->reply)
+		goto out;
+
+	/* fill out request */
+	h = req->request->front.iov_base;
+	h->monhdr.have_version = 0;
+	h->monhdr.session_mon = cpu_to_le16(-1);
+	h->monhdr.session_mon_tid = 0;
+	h->fsid = monc->monmap->fsid;
+
+	err = do_generic_request(monc, req);
+
+out:
+	kref_put(&req->kref, release_generic_request);
+	return err;
+}
+EXPORT_SYMBOL(ceph_monc_do_statfs);
+
+/*
+ * pool ops
+ */
+static int get_poolop_reply_buf(const char *src, size_t src_len,
+				char *dst, size_t dst_len)
+{
+	u32 buf_len;
+
+	if (src_len != sizeof(u32) + dst_len)
+		return -EINVAL;
+
+	buf_len = le32_to_cpu(*(u32 *)src);
+	if (buf_len != dst_len)
+		return -EINVAL;
+
+	memcpy(dst, src + sizeof(u32), dst_len);
+	return 0;
+}
+
+static void handle_poolop_reply(struct ceph_mon_client *monc,
+				struct ceph_msg *msg)
+{
+	struct ceph_mon_generic_request *req;
+	struct ceph_mon_poolop_reply *reply = msg->front.iov_base;
+	u64 tid = le64_to_cpu(msg->hdr.tid);
+
+	if (msg->front.iov_len < sizeof(*reply))
+		goto bad;
+	dout("handle_poolop_reply %p tid %llu\n", msg, tid);
+
+	mutex_lock(&monc->mutex);
+	req = __lookup_generic_req(monc, tid);
+	if (req) {
+		if (req->buf_len &&
+		    get_poolop_reply_buf(msg->front.iov_base + sizeof(*reply),
+				     msg->front.iov_len - sizeof(*reply),
+				     req->buf, req->buf_len) < 0) {
+			mutex_unlock(&monc->mutex);
+			goto bad;
+		}
+		req->result = le32_to_cpu(reply->reply_code);
+		get_generic_request(req);
+	}
+	mutex_unlock(&monc->mutex);
+	if (req) {
+		complete(&req->completion);
+		put_generic_request(req);
+	}
+	return;
+
+bad:
+	pr_err("corrupt generic reply, tid %llu\n", tid);
+	ceph_msg_dump(msg);
+}
+
+/*
+ * Do a synchronous pool op.
+ */
+int ceph_monc_do_poolop(struct ceph_mon_client *monc, u32 op,
+			u32 pool, u64 snapid,
+			char *buf, int len)
+{
+	struct ceph_mon_generic_request *req;
+	struct ceph_mon_poolop *h;
+	int err;
+
+	req = kzalloc(sizeof(*req), GFP_NOFS);
+	if (!req)
+		return -ENOMEM;
+
+	kref_init(&req->kref);
+	req->buf = buf;
+	req->buf_len = len;
+	init_completion(&req->completion);
+
+	err = -ENOMEM;
+	req->request = ceph_msg_new(CEPH_MSG_POOLOP, sizeof(*h), GFP_NOFS);
+	if (!req->request)
+		goto out;
+	req->reply = ceph_msg_new(CEPH_MSG_POOLOP_REPLY, 1024, GFP_NOFS);
+	if (!req->reply)
+		goto out;
+
+	/* fill out request */
+	req->request->hdr.version = cpu_to_le16(2);
+	h = req->request->front.iov_base;
+	h->monhdr.have_version = 0;
+	h->monhdr.session_mon = cpu_to_le16(-1);
+	h->monhdr.session_mon_tid = 0;
+	h->fsid = monc->monmap->fsid;
+	h->pool = cpu_to_le32(pool);
+	h->op = cpu_to_le32(op);
+	h->auid = 0;
+	h->snapid = cpu_to_le64(snapid);
+	h->name_len = 0;
+
+	err = do_generic_request(monc, req);
+
+out:
+	kref_put(&req->kref, release_generic_request);
+	return err;
+}
+
+int ceph_monc_create_snapid(struct ceph_mon_client *monc,
+			    u32 pool, u64 *snapid)
+{
+	return ceph_monc_do_poolop(monc,  POOL_OP_CREATE_UNMANAGED_SNAP,
+				   pool, 0, (char *)snapid, sizeof(*snapid));
+
+}
+EXPORT_SYMBOL(ceph_monc_create_snapid);
+
+int ceph_monc_delete_snapid(struct ceph_mon_client *monc,
+			    u32 pool, u64 snapid)
+{
+	return ceph_monc_do_poolop(monc,  POOL_OP_CREATE_UNMANAGED_SNAP,
+				   pool, snapid, 0, 0);
+
+}
+
+/*
+ * Resend pending generic requests.
+ */
+static void __resend_generic_request(struct ceph_mon_client *monc)
+{
+	struct ceph_mon_generic_request *req;
+	struct rb_node *p;
+
+	for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) {
+		req = rb_entry(p, struct ceph_mon_generic_request, node);
+		ceph_con_revoke(monc->con, req->request);
+		ceph_con_send(monc->con, ceph_msg_get(req->request));
+	}
+}
+
+/*
+ * Delayed work.  If we haven't mounted yet, retry.  Otherwise,
+ * renew/retry subscription as needed (in case it is timing out, or we
+ * got an ENOMEM).  And keep the monitor connection alive.
+ */
+static void delayed_work(struct work_struct *work)
+{
+	struct ceph_mon_client *monc =
+		container_of(work, struct ceph_mon_client, delayed_work.work);
+
+	dout("monc delayed_work\n");
+	mutex_lock(&monc->mutex);
+	if (monc->hunting) {
+		__close_session(monc);
+		__open_session(monc);  /* continue hunting */
+	} else {
+		ceph_con_keepalive(monc->con);
+
+		__validate_auth(monc);
+
+		if (monc->auth->ops->is_authenticated(monc->auth))
+			__send_subscribe(monc);
+	}
+	__schedule_delayed(monc);
+	mutex_unlock(&monc->mutex);
+}
+
+/*
+ * On startup, we build a temporary monmap populated with the IPs
+ * provided by mount(2).
+ */
+static int build_initial_monmap(struct ceph_mon_client *monc)
+{
+	struct ceph_options *opt = monc->client->options;
+	struct ceph_entity_addr *mon_addr = opt->mon_addr;
+	int num_mon = opt->num_mon;
+	int i;
+
+	/* build initial monmap */
+	monc->monmap = kzalloc(sizeof(*monc->monmap) +
+			       num_mon*sizeof(monc->monmap->mon_inst[0]),
+			       GFP_KERNEL);
+	if (!monc->monmap)
+		return -ENOMEM;
+	for (i = 0; i < num_mon; i++) {
+		monc->monmap->mon_inst[i].addr = mon_addr[i];
+		monc->monmap->mon_inst[i].addr.nonce = 0;
+		monc->monmap->mon_inst[i].name.type =
+			CEPH_ENTITY_TYPE_MON;
+		monc->monmap->mon_inst[i].name.num = cpu_to_le64(i);
+	}
+	monc->monmap->num_mon = num_mon;
+	monc->have_fsid = false;
+	return 0;
+}
+
+int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
+{
+	int err = 0;
+
+	dout("init\n");
+	memset(monc, 0, sizeof(*monc));
+	monc->client = cl;
+	monc->monmap = NULL;
+	mutex_init(&monc->mutex);
+
+	err = build_initial_monmap(monc);
+	if (err)
+		goto out;
+
+	monc->con = NULL;
+
+	/* authentication */
+	monc->auth = ceph_auth_init(cl->options->name,
+				    cl->options->secret);
+	if (IS_ERR(monc->auth))
+		return PTR_ERR(monc->auth);
+	monc->auth->want_keys =
+		CEPH_ENTITY_TYPE_AUTH | CEPH_ENTITY_TYPE_MON |
+		CEPH_ENTITY_TYPE_OSD | CEPH_ENTITY_TYPE_MDS;
+
+	/* msgs */
+	err = -ENOMEM;
+	monc->m_subscribe_ack = ceph_msg_new(CEPH_MSG_MON_SUBSCRIBE_ACK,
+				     sizeof(struct ceph_mon_subscribe_ack),
+				     GFP_NOFS);
+	if (!monc->m_subscribe_ack)
+		goto out_monmap;
+
+	monc->m_subscribe = ceph_msg_new(CEPH_MSG_MON_SUBSCRIBE, 96, GFP_NOFS);
+	if (!monc->m_subscribe)
+		goto out_subscribe_ack;
+
+	monc->m_auth_reply = ceph_msg_new(CEPH_MSG_AUTH_REPLY, 4096, GFP_NOFS);
+	if (!monc->m_auth_reply)
+		goto out_subscribe;
+
+	monc->m_auth = ceph_msg_new(CEPH_MSG_AUTH, 4096, GFP_NOFS);
+	monc->pending_auth = 0;
+	if (!monc->m_auth)
+		goto out_auth_reply;
+
+	monc->cur_mon = -1;
+	monc->hunting = true;
+	monc->sub_renew_after = jiffies;
+	monc->sub_sent = 0;
+
+	INIT_DELAYED_WORK(&monc->delayed_work, delayed_work);
+	monc->generic_request_tree = RB_ROOT;
+	monc->num_generic_requests = 0;
+	monc->last_tid = 0;
+
+	monc->have_mdsmap = 0;
+	monc->have_osdmap = 0;
+	monc->want_next_osdmap = 1;
+	return 0;
+
+out_auth_reply:
+	ceph_msg_put(monc->m_auth_reply);
+out_subscribe:
+	ceph_msg_put(monc->m_subscribe);
+out_subscribe_ack:
+	ceph_msg_put(monc->m_subscribe_ack);
+out_monmap:
+	kfree(monc->monmap);
+out:
+	return err;
+}
+EXPORT_SYMBOL(ceph_monc_init);
+
+void ceph_monc_stop(struct ceph_mon_client *monc)
+{
+	dout("stop\n");
+	cancel_delayed_work_sync(&monc->delayed_work);
+
+	mutex_lock(&monc->mutex);
+	__close_session(monc);
+	if (monc->con) {
+		monc->con->private = NULL;
+		monc->con->ops->put(monc->con);
+		monc->con = NULL;
+	}
+	mutex_unlock(&monc->mutex);
+
+	ceph_auth_destroy(monc->auth);
+
+	ceph_msg_put(monc->m_auth);
+	ceph_msg_put(monc->m_auth_reply);
+	ceph_msg_put(monc->m_subscribe);
+	ceph_msg_put(monc->m_subscribe_ack);
+
+	kfree(monc->monmap);
+}
+EXPORT_SYMBOL(ceph_monc_stop);
+
+static void handle_auth_reply(struct ceph_mon_client *monc,
+			      struct ceph_msg *msg)
+{
+	int ret;
+	int was_auth = 0;
+
+	mutex_lock(&monc->mutex);
+	if (monc->auth->ops)
+		was_auth = monc->auth->ops->is_authenticated(monc->auth);
+	monc->pending_auth = 0;
+	ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base,
+				     msg->front.iov_len,
+				     monc->m_auth->front.iov_base,
+				     monc->m_auth->front_max);
+	if (ret < 0) {
+		monc->client->auth_err = ret;
+		wake_up_all(&monc->client->auth_wq);
+	} else if (ret > 0) {
+		__send_prepared_auth_request(monc, ret);
+	} else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) {
+		dout("authenticated, starting session\n");
+
+		monc->client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT;
+		monc->client->msgr->inst.name.num =
+					cpu_to_le64(monc->auth->global_id);
+
+		__send_subscribe(monc);
+		__resend_generic_request(monc);
+	}
+	mutex_unlock(&monc->mutex);
+}
+
+static int __validate_auth(struct ceph_mon_client *monc)
+{
+	int ret;
+
+	if (monc->pending_auth)
+		return 0;
+
+	ret = ceph_build_auth(monc->auth, monc->m_auth->front.iov_base,
+			      monc->m_auth->front_max);
+	if (ret <= 0)
+		return ret; /* either an error, or no need to authenticate */
+	__send_prepared_auth_request(monc, ret);
+	return 0;
+}
+
+int ceph_monc_validate_auth(struct ceph_mon_client *monc)
+{
+	int ret;
+
+	mutex_lock(&monc->mutex);
+	ret = __validate_auth(monc);
+	mutex_unlock(&monc->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(ceph_monc_validate_auth);
+
+/*
+ * handle incoming message
+ */
+static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
+{
+	struct ceph_mon_client *monc = con->private;
+	int type = le16_to_cpu(msg->hdr.type);
+
+	if (!monc)
+		return;
+
+	switch (type) {
+	case CEPH_MSG_AUTH_REPLY:
+		handle_auth_reply(monc, msg);
+		break;
+
+	case CEPH_MSG_MON_SUBSCRIBE_ACK:
+		handle_subscribe_ack(monc, msg);
+		break;
+
+	case CEPH_MSG_STATFS_REPLY:
+		handle_statfs_reply(monc, msg);
+		break;
+
+	case CEPH_MSG_POOLOP_REPLY:
+		handle_poolop_reply(monc, msg);
+		break;
+
+	case CEPH_MSG_MON_MAP:
+		ceph_monc_handle_map(monc, msg);
+		break;
+
+	case CEPH_MSG_OSD_MAP:
+		ceph_osdc_handle_map(&monc->client->osdc, msg);
+		break;
+
+	default:
+		/* can the chained handler handle it? */
+		if (monc->client->extra_mon_dispatch &&
+		    monc->client->extra_mon_dispatch(monc->client, msg) == 0)
+			break;
+			
+		pr_err("received unknown message type %d %s\n", type,
+		       ceph_msg_type_name(type));
+	}
+	ceph_msg_put(msg);
+}
+
+/*
+ * Allocate memory for incoming message
+ */
+static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con,
+				      struct ceph_msg_header *hdr,
+				      int *skip)
+{
+	struct ceph_mon_client *monc = con->private;
+	int type = le16_to_cpu(hdr->type);
+	int front_len = le32_to_cpu(hdr->front_len);
+	struct ceph_msg *m = NULL;
+
+	*skip = 0;
+
+	switch (type) {
+	case CEPH_MSG_MON_SUBSCRIBE_ACK:
+		m = ceph_msg_get(monc->m_subscribe_ack);
+		break;
+	case CEPH_MSG_POOLOP_REPLY:
+	case CEPH_MSG_STATFS_REPLY:
+		return get_generic_reply(con, hdr, skip);
+	case CEPH_MSG_AUTH_REPLY:
+		m = ceph_msg_get(monc->m_auth_reply);
+		break;
+	case CEPH_MSG_MON_MAP:
+	case CEPH_MSG_MDS_MAP:
+	case CEPH_MSG_OSD_MAP:
+		m = ceph_msg_new(type, front_len, GFP_NOFS);
+		break;
+	}
+
+	if (!m) {
+		pr_info("alloc_msg unknown type %d\n", type);
+		*skip = 1;
+	}
+	return m;
+}
+
+/*
+ * If the monitor connection resets, pick a new monitor and resubmit
+ * any pending requests.
+ */
+static void mon_fault(struct ceph_connection *con)
+{
+	struct ceph_mon_client *monc = con->private;
+
+	if (!monc)
+		return;
+
+	dout("mon_fault\n");
+	mutex_lock(&monc->mutex);
+	if (!con->private)
+		goto out;
+
+	if (monc->con && !monc->hunting)
+		pr_info("mon%d %s session lost, "
+			"hunting for new mon\n", monc->cur_mon,
+			ceph_pr_addr(&monc->con->peer_addr.in_addr));
+
+	__close_session(monc);
+	if (!monc->hunting) {
+		/* start hunting */
+		monc->hunting = true;
+		__open_session(monc);
+	} else {
+		/* already hunting, let's wait a bit */
+		__schedule_delayed(monc);
+	}
+out:
+	mutex_unlock(&monc->mutex);
+}
+
+static const struct ceph_connection_operations mon_con_ops = {
+	.get = ceph_con_get,
+	.put = ceph_con_put,
+	.dispatch = dispatch,
+	.fault = mon_fault,
+	.alloc_msg = mon_alloc_msg,
+};
diff --git a/net/ceph/msgpool.c b/net/ceph/msgpool.c
new file mode 100644
index 0000000..d5f2d97
--- /dev/null
+++ b/net/ceph/msgpool.c
@@ -0,0 +1,64 @@
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+
+#include <linux/ceph/msgpool.h>
+
+static void *alloc_fn(gfp_t gfp_mask, void *arg)
+{
+	struct ceph_msgpool *pool = arg;
+	void *p;
+
+	p = ceph_msg_new(0, pool->front_len, gfp_mask);
+	if (!p)
+		pr_err("msgpool %s alloc failed\n", pool->name);
+	return p;
+}
+
+static void free_fn(void *element, void *arg)
+{
+	ceph_msg_put(element);
+}
+
+int ceph_msgpool_init(struct ceph_msgpool *pool,
+		      int front_len, int size, bool blocking, const char *name)
+{
+	pool->front_len = front_len;
+	pool->pool = mempool_create(size, alloc_fn, free_fn, pool);
+	if (!pool->pool)
+		return -ENOMEM;
+	pool->name = name;
+	return 0;
+}
+
+void ceph_msgpool_destroy(struct ceph_msgpool *pool)
+{
+	mempool_destroy(pool->pool);
+}
+
+struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool,
+				  int front_len)
+{
+	if (front_len > pool->front_len) {
+		pr_err("msgpool_get pool %s need front %d, pool size is %d\n",
+		       pool->name, front_len, pool->front_len);
+		WARN_ON(1);
+
+		/* try to alloc a fresh message */
+		return ceph_msg_new(0, front_len, GFP_NOFS);
+	}
+
+	return mempool_alloc(pool->pool, GFP_NOFS);
+}
+
+void ceph_msgpool_put(struct ceph_msgpool *pool, struct ceph_msg *msg)
+{
+	/* reset msg front_len; user may have changed it */
+	msg->front.iov_len = pool->front_len;
+	msg->hdr.front_len = cpu_to_le32(pool->front_len);
+
+	kref_init(&msg->kref);  /* retake single ref */
+}
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
new file mode 100644
index 0000000..7939199
--- /dev/null
+++ b/net/ceph/osd_client.c
@@ -0,0 +1,1773 @@
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#ifdef CONFIG_BLOCK
+#include <linux/bio.h>
+#endif
+
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/osd_client.h>
+#include <linux/ceph/messenger.h>
+#include <linux/ceph/decode.h>
+#include <linux/ceph/auth.h>
+#include <linux/ceph/pagelist.h>
+
+#define OSD_OP_FRONT_LEN	4096
+#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 int op_needs_trail(int op)
+{
+	switch (op) {
+	case CEPH_OSD_OP_GETXATTR:
+	case CEPH_OSD_OP_SETXATTR:
+	case CEPH_OSD_OP_CMPXATTR:
+	case CEPH_OSD_OP_CALL:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int op_has_extent(int op)
+{
+	return (op == CEPH_OSD_OP_READ ||
+		op == CEPH_OSD_OP_WRITE);
+}
+
+void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
+			struct ceph_file_layout *layout,
+			u64 snapid,
+			u64 off, u64 *plen, u64 *bno,
+			struct ceph_osd_request *req,
+			struct ceph_osd_req_op *op)
+{
+	struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
+	u64 orig_len = *plen;
+	u64 objoff, objlen;    /* extent in object */
+
+	reqhead->snapid = cpu_to_le64(snapid);
+
+	/* object extent? */
+	ceph_calc_file_object_mapping(layout, off, plen, bno,
+				      &objoff, &objlen);
+	if (*plen < orig_len)
+		dout(" skipping last %llu, final file extent %llu~%llu\n",
+		     orig_len - *plen, off, *plen);
+
+	if (op_has_extent(op->op)) {
+		op->extent.offset = objoff;
+		op->extent.length = objlen;
+	}
+	req->r_num_pages = calc_pages_for(off, *plen);
+	if (op->op == CEPH_OSD_OP_WRITE)
+		op->payload_len = *plen;
+
+	dout("calc_layout bno=%llx %llu~%llu (%d pages)\n",
+	     *bno, objoff, objlen, req->r_num_pages);
+
+}
+EXPORT_SYMBOL(ceph_calc_raw_layout);
+
+/*
+ * Implement client access to distributed object storage cluster.
+ *
+ * All data objects are stored within a cluster/cloud of OSDs, or
+ * "object storage devices."  (Note that Ceph OSDs have _nothing_ to
+ * do with the T10 OSD extensions to SCSI.)  Ceph OSDs are simply
+ * remote daemons serving up and coordinating consistent and safe
+ * access to storage.
+ *
+ * Cluster membership and the mapping of data objects onto storage devices
+ * are described by the osd map.
+ *
+ * We keep track of pending OSD requests (read, write), resubmit
+ * requests to different OSDs when the cluster topology/data layout
+ * change, or retry the affected requests when the communications
+ * channel with an OSD is reset.
+ */
+
+/*
+ * calculate the mapping of a file extent onto an object, and fill out the
+ * request accordingly.  shorten extent as necessary if it crosses an
+ * object boundary.
+ *
+ * fill osd op in request message.
+ */
+static void calc_layout(struct ceph_osd_client *osdc,
+			struct ceph_vino vino,
+			struct ceph_file_layout *layout,
+			u64 off, u64 *plen,
+			struct ceph_osd_request *req,
+			struct ceph_osd_req_op *op)
+{
+	u64 bno;
+
+	ceph_calc_raw_layout(osdc, layout, vino.snap, off,
+			     plen, &bno, req, op);
+
+	sprintf(req->r_oid, "%llx.%08llx", vino.ino, bno);
+	req->r_oid_len = strlen(req->r_oid);
+}
+
+/*
+ * requests
+ */
+void ceph_osdc_release_request(struct kref *kref)
+{
+	struct ceph_osd_request *req = container_of(kref,
+						    struct ceph_osd_request,
+						    r_kref);
+
+	if (req->r_request)
+		ceph_msg_put(req->r_request);
+	if (req->r_reply)
+		ceph_msg_put(req->r_reply);
+	if (req->r_con_filling_msg) {
+		dout("release_request revoking pages %p from con %p\n",
+		     req->r_pages, req->r_con_filling_msg);
+		ceph_con_revoke_message(req->r_con_filling_msg,
+				      req->r_reply);
+		ceph_con_put(req->r_con_filling_msg);
+	}
+	if (req->r_own_pages)
+		ceph_release_page_vector(req->r_pages,
+					 req->r_num_pages);
+#ifdef CONFIG_BLOCK
+	if (req->r_bio)
+		bio_put(req->r_bio);
+#endif
+	ceph_put_snap_context(req->r_snapc);
+	if (req->r_trail) {
+		ceph_pagelist_release(req->r_trail);
+		kfree(req->r_trail);
+	}
+	if (req->r_mempool)
+		mempool_free(req, req->r_osdc->req_mempool);
+	else
+		kfree(req);
+}
+EXPORT_SYMBOL(ceph_osdc_release_request);
+
+static int get_num_ops(struct ceph_osd_req_op *ops, int *needs_trail)
+{
+	int i = 0;
+
+	if (needs_trail)
+		*needs_trail = 0;
+	while (ops[i].op) {
+		if (needs_trail && op_needs_trail(ops[i].op))
+			*needs_trail = 1;
+		i++;
+	}
+
+	return i;
+}
+
+struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
+					       int flags,
+					       struct ceph_snap_context *snapc,
+					       struct ceph_osd_req_op *ops,
+					       bool use_mempool,
+					       gfp_t gfp_flags,
+					       struct page **pages,
+					       struct bio *bio)
+{
+	struct ceph_osd_request *req;
+	struct ceph_msg *msg;
+	int needs_trail;
+	int num_op = get_num_ops(ops, &needs_trail);
+	size_t msg_size = sizeof(struct ceph_osd_request_head);
+
+	msg_size += num_op*sizeof(struct ceph_osd_op);
+
+	if (use_mempool) {
+		req = mempool_alloc(osdc->req_mempool, gfp_flags);
+		memset(req, 0, sizeof(*req));
+	} else {
+		req = kzalloc(sizeof(*req), gfp_flags);
+	}
+	if (req == NULL)
+		return NULL;
+
+	req->r_osdc = osdc;
+	req->r_mempool = use_mempool;
+
+	kref_init(&req->r_kref);
+	init_completion(&req->r_completion);
+	init_completion(&req->r_safe_completion);
+	INIT_LIST_HEAD(&req->r_unsafe_item);
+	req->r_flags = flags;
+
+	WARN_ON((flags & (CEPH_OSD_FLAG_READ|CEPH_OSD_FLAG_WRITE)) == 0);
+
+	/* create reply message */
+	if (use_mempool)
+		msg = ceph_msgpool_get(&osdc->msgpool_op_reply, 0);
+	else
+		msg = ceph_msg_new(CEPH_MSG_OSD_OPREPLY,
+				   OSD_OPREPLY_FRONT_LEN, gfp_flags);
+	if (!msg) {
+		ceph_osdc_put_request(req);
+		return NULL;
+	}
+	req->r_reply = msg;
+
+	/* allocate space for the trailing data */
+	if (needs_trail) {
+		req->r_trail = kmalloc(sizeof(struct ceph_pagelist), gfp_flags);
+		if (!req->r_trail) {
+			ceph_osdc_put_request(req);
+			return NULL;
+		}
+		ceph_pagelist_init(req->r_trail);
+	}
+	/* create request message; allow space for oid */
+	msg_size += 40;
+	if (snapc)
+		msg_size += sizeof(u64) * snapc->num_snaps;
+	if (use_mempool)
+		msg = ceph_msgpool_get(&osdc->msgpool_op, 0);
+	else
+		msg = ceph_msg_new(CEPH_MSG_OSD_OP, msg_size, gfp_flags);
+	if (!msg) {
+		ceph_osdc_put_request(req);
+		return NULL;
+	}
+
+	msg->hdr.type = cpu_to_le16(CEPH_MSG_OSD_OP);
+	memset(msg->front.iov_base, 0, msg->front.iov_len);
+
+	req->r_request = msg;
+	req->r_pages = pages;
+#ifdef CONFIG_BLOCK
+	if (bio) {
+		req->r_bio = bio;
+		bio_get(req->r_bio);
+	}
+#endif
+
+	return req;
+}
+EXPORT_SYMBOL(ceph_osdc_alloc_request);
+
+static void osd_req_encode_op(struct ceph_osd_request *req,
+			      struct ceph_osd_op *dst,
+			      struct ceph_osd_req_op *src)
+{
+	dst->op = cpu_to_le16(src->op);
+
+	switch (dst->op) {
+	case CEPH_OSD_OP_READ:
+	case CEPH_OSD_OP_WRITE:
+		dst->extent.offset =
+			cpu_to_le64(src->extent.offset);
+		dst->extent.length =
+			cpu_to_le64(src->extent.length);
+		dst->extent.truncate_size =
+			cpu_to_le64(src->extent.truncate_size);
+		dst->extent.truncate_seq =
+			cpu_to_le32(src->extent.truncate_seq);
+		break;
+
+	case CEPH_OSD_OP_GETXATTR:
+	case CEPH_OSD_OP_SETXATTR:
+	case CEPH_OSD_OP_CMPXATTR:
+		BUG_ON(!req->r_trail);
+
+		dst->xattr.name_len = cpu_to_le32(src->xattr.name_len);
+		dst->xattr.value_len = cpu_to_le32(src->xattr.value_len);
+		dst->xattr.cmp_op = src->xattr.cmp_op;
+		dst->xattr.cmp_mode = src->xattr.cmp_mode;
+		ceph_pagelist_append(req->r_trail, src->xattr.name,
+				     src->xattr.name_len);
+		ceph_pagelist_append(req->r_trail, src->xattr.val,
+				     src->xattr.value_len);
+		break;
+	case CEPH_OSD_OP_CALL:
+		BUG_ON(!req->r_trail);
+
+		dst->cls.class_len = src->cls.class_len;
+		dst->cls.method_len = src->cls.method_len;
+		dst->cls.indata_len = cpu_to_le32(src->cls.indata_len);
+
+		ceph_pagelist_append(req->r_trail, src->cls.class_name,
+				     src->cls.class_len);
+		ceph_pagelist_append(req->r_trail, src->cls.method_name,
+				     src->cls.method_len);
+		ceph_pagelist_append(req->r_trail, src->cls.indata,
+				     src->cls.indata_len);
+		break;
+	case CEPH_OSD_OP_ROLLBACK:
+		dst->snap.snapid = cpu_to_le64(src->snap.snapid);
+		break;
+	case CEPH_OSD_OP_STARTSYNC:
+		break;
+	default:
+		pr_err("unrecognized osd opcode %d\n", dst->op);
+		WARN_ON(1);
+		break;
+	}
+	dst->payload_len = cpu_to_le32(src->payload_len);
+}
+
+/*
+ * build new request AND message
+ *
+ */
+void ceph_osdc_build_request(struct ceph_osd_request *req,
+			     u64 off, u64 *plen,
+			     struct ceph_osd_req_op *src_ops,
+			     struct ceph_snap_context *snapc,
+			     struct timespec *mtime,
+			     const char *oid,
+			     int oid_len)
+{
+	struct ceph_msg *msg = req->r_request;
+	struct ceph_osd_request_head *head;
+	struct ceph_osd_req_op *src_op;
+	struct ceph_osd_op *op;
+	void *p;
+	int num_op = get_num_ops(src_ops, NULL);
+	size_t msg_size = sizeof(*head) + num_op*sizeof(*op);
+	int flags = req->r_flags;
+	u64 data_len = 0;
+	int i;
+
+	head = msg->front.iov_base;
+	op = (void *)(head + 1);
+	p = (void *)(op + num_op);
+
+	req->r_snapc = ceph_get_snap_context(snapc);
+
+	head->client_inc = cpu_to_le32(1); /* always, for now. */
+	head->flags = cpu_to_le32(flags);
+	if (flags & CEPH_OSD_FLAG_WRITE)
+		ceph_encode_timespec(&head->mtime, mtime);
+	head->num_ops = cpu_to_le16(num_op);
+
+
+	/* fill in oid */
+	head->object_len = cpu_to_le32(oid_len);
+	memcpy(p, oid, oid_len);
+	p += oid_len;
+
+	src_op = src_ops;
+	while (src_op->op) {
+		osd_req_encode_op(req, op, src_op);
+		src_op++;
+		op++;
+	}
+
+	if (req->r_trail)
+		data_len += req->r_trail->length;
+
+	if (snapc) {
+		head->snap_seq = cpu_to_le64(snapc->seq);
+		head->num_snaps = cpu_to_le32(snapc->num_snaps);
+		for (i = 0; i < snapc->num_snaps; i++) {
+			put_unaligned_le64(snapc->snaps[i], p);
+			p += sizeof(u64);
+		}
+	}
+
+	if (flags & CEPH_OSD_FLAG_WRITE) {
+		req->r_request->hdr.data_off = cpu_to_le16(off);
+		req->r_request->hdr.data_len = cpu_to_le32(*plen + data_len);
+	} else if (data_len) {
+		req->r_request->hdr.data_off = 0;
+		req->r_request->hdr.data_len = cpu_to_le32(data_len);
+	}
+
+	BUG_ON(p > msg->front.iov_base + msg->front.iov_len);
+	msg_size = p - msg->front.iov_base;
+	msg->front.iov_len = msg_size;
+	msg->hdr.front_len = cpu_to_le32(msg_size);
+	return;
+}
+EXPORT_SYMBOL(ceph_osdc_build_request);
+
+/*
+ * build new request AND message, calculate layout, and adjust file
+ * extent as needed.
+ *
+ * if the file was recently truncated, we include information about its
+ * old and new size so that the object can be updated appropriately.  (we
+ * avoid synchronously deleting truncated objects because it's slow.)
+ *
+ * if @do_sync, include a 'startsync' command so that the osd will flush
+ * data quickly.
+ */
+struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
+					       struct ceph_file_layout *layout,
+					       struct ceph_vino vino,
+					       u64 off, u64 *plen,
+					       int opcode, int flags,
+					       struct ceph_snap_context *snapc,
+					       int do_sync,
+					       u32 truncate_seq,
+					       u64 truncate_size,
+					       struct timespec *mtime,
+					       bool use_mempool, int num_reply)
+{
+	struct ceph_osd_req_op ops[3];
+	struct ceph_osd_request *req;
+
+	ops[0].op = opcode;
+	ops[0].extent.truncate_seq = truncate_seq;
+	ops[0].extent.truncate_size = truncate_size;
+	ops[0].payload_len = 0;
+
+	if (do_sync) {
+		ops[1].op = CEPH_OSD_OP_STARTSYNC;
+		ops[1].payload_len = 0;
+		ops[2].op = 0;
+	} else
+		ops[1].op = 0;
+
+	req = ceph_osdc_alloc_request(osdc, flags,
+					 snapc, ops,
+					 use_mempool,
+					 GFP_NOFS, NULL, NULL);
+	if (IS_ERR(req))
+		return req;
+
+	/* calculate max write size */
+	calc_layout(osdc, vino, layout, off, plen, req, ops);
+	req->r_file_layout = *layout;  /* keep a copy */
+
+	ceph_osdc_build_request(req, off, plen, ops,
+				snapc,
+				mtime,
+				req->r_oid, req->r_oid_len);
+
+	return req;
+}
+EXPORT_SYMBOL(ceph_osdc_new_request);
+
+/*
+ * We keep osd requests in an rbtree, sorted by ->r_tid.
+ */
+static void __insert_request(struct ceph_osd_client *osdc,
+			     struct ceph_osd_request *new)
+{
+	struct rb_node **p = &osdc->requests.rb_node;
+	struct rb_node *parent = NULL;
+	struct ceph_osd_request *req = NULL;
+
+	while (*p) {
+		parent = *p;
+		req = rb_entry(parent, struct ceph_osd_request, r_node);
+		if (new->r_tid < req->r_tid)
+			p = &(*p)->rb_left;
+		else if (new->r_tid > req->r_tid)
+			p = &(*p)->rb_right;
+		else
+			BUG();
+	}
+
+	rb_link_node(&new->r_node, parent, p);
+	rb_insert_color(&new->r_node, &osdc->requests);
+}
+
+static struct ceph_osd_request *__lookup_request(struct ceph_osd_client *osdc,
+						 u64 tid)
+{
+	struct ceph_osd_request *req;
+	struct rb_node *n = osdc->requests.rb_node;
+
+	while (n) {
+		req = rb_entry(n, struct ceph_osd_request, r_node);
+		if (tid < req->r_tid)
+			n = n->rb_left;
+		else if (tid > req->r_tid)
+			n = n->rb_right;
+		else
+			return req;
+	}
+	return NULL;
+}
+
+static struct ceph_osd_request *
+__lookup_request_ge(struct ceph_osd_client *osdc,
+		    u64 tid)
+{
+	struct ceph_osd_request *req;
+	struct rb_node *n = osdc->requests.rb_node;
+
+	while (n) {
+		req = rb_entry(n, struct ceph_osd_request, r_node);
+		if (tid < req->r_tid) {
+			if (!n->rb_left)
+				return req;
+			n = n->rb_left;
+		} else if (tid > req->r_tid) {
+			n = n->rb_right;
+		} else {
+			return req;
+		}
+	}
+	return NULL;
+}
+
+
+/*
+ * If the osd connection drops, we need to resubmit all requests.
+ */
+static void osd_reset(struct ceph_connection *con)
+{
+	struct ceph_osd *osd = con->private;
+	struct ceph_osd_client *osdc;
+
+	if (!osd)
+		return;
+	dout("osd_reset osd%d\n", osd->o_osd);
+	osdc = osd->o_osdc;
+	down_read(&osdc->map_sem);
+	kick_requests(osdc, osd);
+	up_read(&osdc->map_sem);
+}
+
+/*
+ * Track open sessions with osds.
+ */
+static struct ceph_osd *create_osd(struct ceph_osd_client *osdc)
+{
+	struct ceph_osd *osd;
+
+	osd = kzalloc(sizeof(*osd), GFP_NOFS);
+	if (!osd)
+		return NULL;
+
+	atomic_set(&osd->o_ref, 1);
+	osd->o_osdc = osdc;
+	INIT_LIST_HEAD(&osd->o_requests);
+	INIT_LIST_HEAD(&osd->o_osd_lru);
+	osd->o_incarnation = 1;
+
+	ceph_con_init(osdc->client->msgr, &osd->o_con);
+	osd->o_con.private = osd;
+	osd->o_con.ops = &osd_con_ops;
+	osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD;
+
+	INIT_LIST_HEAD(&osd->o_keepalive_item);
+	return osd;
+}
+
+static struct ceph_osd *get_osd(struct ceph_osd *osd)
+{
+	if (atomic_inc_not_zero(&osd->o_ref)) {
+		dout("get_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref)-1,
+		     atomic_read(&osd->o_ref));
+		return osd;
+	} else {
+		dout("get_osd %p FAIL\n", osd);
+		return NULL;
+	}
+}
+
+static void put_osd(struct ceph_osd *osd)
+{
+	dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref),
+	     atomic_read(&osd->o_ref) - 1);
+	if (atomic_dec_and_test(&osd->o_ref)) {
+		struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth;
+
+		if (osd->o_authorizer)
+			ac->ops->destroy_authorizer(ac, osd->o_authorizer);
+		kfree(osd);
+	}
+}
+
+/*
+ * remove an osd from our map
+ */
+static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
+{
+	dout("__remove_osd %p\n", osd);
+	BUG_ON(!list_empty(&osd->o_requests));
+	rb_erase(&osd->o_node, &osdc->osds);
+	list_del_init(&osd->o_osd_lru);
+	ceph_con_close(&osd->o_con);
+	put_osd(osd);
+}
+
+static void __move_osd_to_lru(struct ceph_osd_client *osdc,
+			      struct ceph_osd *osd)
+{
+	dout("__move_osd_to_lru %p\n", osd);
+	BUG_ON(!list_empty(&osd->o_osd_lru));
+	list_add_tail(&osd->o_osd_lru, &osdc->osd_lru);
+	osd->lru_ttl = jiffies + osdc->client->options->osd_idle_ttl * HZ;
+}
+
+static void __remove_osd_from_lru(struct ceph_osd *osd)
+{
+	dout("__remove_osd_from_lru %p\n", osd);
+	if (!list_empty(&osd->o_osd_lru))
+		list_del_init(&osd->o_osd_lru);
+}
+
+static void remove_old_osds(struct ceph_osd_client *osdc, int remove_all)
+{
+	struct ceph_osd *osd, *nosd;
+
+	dout("__remove_old_osds %p\n", osdc);
+	mutex_lock(&osdc->request_mutex);
+	list_for_each_entry_safe(osd, nosd, &osdc->osd_lru, o_osd_lru) {
+		if (!remove_all && time_before(jiffies, osd->lru_ttl))
+			break;
+		__remove_osd(osdc, osd);
+	}
+	mutex_unlock(&osdc->request_mutex);
+}
+
+/*
+ * reset osd connect
+ */
+static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
+{
+	struct ceph_osd_request *req;
+	int ret = 0;
+
+	dout("__reset_osd %p osd%d\n", osd, osd->o_osd);
+	if (list_empty(&osd->o_requests)) {
+		__remove_osd(osdc, osd);
+	} else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd],
+			  &osd->o_con.peer_addr,
+			  sizeof(osd->o_con.peer_addr)) == 0 &&
+		   !ceph_con_opened(&osd->o_con)) {
+		dout(" osd addr hasn't changed and connection never opened,"
+		     " letting msgr retry");
+		/* touch each r_stamp for handle_timeout()'s benfit */
+		list_for_each_entry(req, &osd->o_requests, r_osd_item)
+			req->r_stamp = jiffies;
+		ret = -EAGAIN;
+	} else {
+		ceph_con_close(&osd->o_con);
+		ceph_con_open(&osd->o_con, &osdc->osdmap->osd_addr[osd->o_osd]);
+		osd->o_incarnation++;
+	}
+	return ret;
+}
+
+static void __insert_osd(struct ceph_osd_client *osdc, struct ceph_osd *new)
+{
+	struct rb_node **p = &osdc->osds.rb_node;
+	struct rb_node *parent = NULL;
+	struct ceph_osd *osd = NULL;
+
+	while (*p) {
+		parent = *p;
+		osd = rb_entry(parent, struct ceph_osd, o_node);
+		if (new->o_osd < osd->o_osd)
+			p = &(*p)->rb_left;
+		else if (new->o_osd > osd->o_osd)
+			p = &(*p)->rb_right;
+		else
+			BUG();
+	}
+
+	rb_link_node(&new->o_node, parent, p);
+	rb_insert_color(&new->o_node, &osdc->osds);
+}
+
+static struct ceph_osd *__lookup_osd(struct ceph_osd_client *osdc, int o)
+{
+	struct ceph_osd *osd;
+	struct rb_node *n = osdc->osds.rb_node;
+
+	while (n) {
+		osd = rb_entry(n, struct ceph_osd, o_node);
+		if (o < osd->o_osd)
+			n = n->rb_left;
+		else if (o > osd->o_osd)
+			n = n->rb_right;
+		else
+			return osd;
+	}
+	return NULL;
+}
+
+static void __schedule_osd_timeout(struct ceph_osd_client *osdc)
+{
+	schedule_delayed_work(&osdc->timeout_work,
+			osdc->client->options->osd_keepalive_timeout * HZ);
+}
+
+static void __cancel_osd_timeout(struct ceph_osd_client *osdc)
+{
+	cancel_delayed_work(&osdc->timeout_work);
+}
+
+/*
+ * 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)
+{
+	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);
+
+	dout("register_request %p tid %lld\n", req, req->r_tid);
+	__insert_request(osdc, req);
+	ceph_osdc_get_request(req);
+	osdc->num_requests++;
+
+	if (osdc->num_requests == 1) {
+		dout(" first request, scheduling timeout\n");
+		__schedule_osd_timeout(osdc);
+	}
+	mutex_unlock(&osdc->request_mutex);
+}
+
+/*
+ * called under osdc->request_mutex
+ */
+static void __unregister_request(struct ceph_osd_client *osdc,
+				 struct ceph_osd_request *req)
+{
+	dout("__unregister_request %p tid %lld\n", req, req->r_tid);
+	rb_erase(&req->r_node, &osdc->requests);
+	osdc->num_requests--;
+
+	if (req->r_osd) {
+		/* make sure the original request isn't in flight. */
+		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))
+			__move_osd_to_lru(osdc, req->r_osd);
+		req->r_osd = NULL;
+	}
+
+	ceph_osdc_put_request(req);
+
+	list_del_init(&req->r_req_lru_item);
+	if (osdc->num_requests == 0) {
+		dout(" no requests, canceling timeout\n");
+		__cancel_osd_timeout(osdc);
+	}
+}
+
+/*
+ * Cancel a previously queued request message
+ */
+static void __cancel_request(struct ceph_osd_request *req)
+{
+	if (req->r_sent && req->r_osd) {
+		ceph_con_revoke(&req->r_osd->o_con, req->r_request);
+		req->r_sent = 0;
+	}
+	list_del_init(&req->r_req_lru_item);
+}
+
+/*
+ * 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.
+ *
+ * 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)
+{
+	struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
+	struct ceph_pg pgid;
+	int acting[CEPH_PG_MAX_SIZE];
+	int o = -1, num = 0;
+	int err;
+
+	dout("map_osds %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)
+		return err;
+	pgid = reqhead->layout.ol_pgid;
+	req->r_pgid = pgid;
+
+	err = ceph_calc_pg_acting(osdc->osdmap, pgid, acting);
+	if (err > 0) {
+		o = acting[0];
+		num = err;
+	}
+
+	if ((req->r_osd && req->r_osd->o_osd == o &&
+	     req->r_sent >= req->r_osd->o_incarnation &&
+	     req->r_num_pg_osds == num &&
+	     memcmp(req->r_pg_osds, acting, sizeof(acting[0])*num) == 0) ||
+	    (req->r_osd == NULL && o == -1))
+		return 0;  /* no change */
+
+	dout("map_osds 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);
+
+	/* record full pg acting set */
+	memcpy(req->r_pg_osds, acting, sizeof(acting[0]) * num);
+	req->r_num_pg_osds = num;
+
+	if (req->r_osd) {
+		__cancel_request(req);
+		list_del_init(&req->r_osd_item);
+		req->r_osd = NULL;
+	}
+
+	req->r_osd = __lookup_osd(osdc, o);
+	if (!req->r_osd && o >= 0) {
+		err = -ENOMEM;
+		req->r_osd = create_osd(osdc);
+		if (!req->r_osd)
+			goto out;
+
+		dout("map_osds 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);
+
+		ceph_con_open(&req->r_osd->o_con, &osdc->osdmap->osd_addr[o]);
+	}
+
+	if (req->r_osd) {
+		__remove_osd_from_lru(req->r_osd);
+		list_add(&req->r_osd_item, &req->r_osd->o_requests);
+	}
+	err = 1;   /* osd or pg changed */
+
+out:
+	return err;
+}
+
+/*
+ * caller should hold map_sem (for read) and request_mutex
+ */
+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);
+
+	reqhead = req->r_request->front.iov_base;
+	reqhead->osdmap_epoch = cpu_to_le32(osdc->osdmap->epoch);
+	reqhead->flags |= cpu_to_le32(req->r_flags);  /* e.g., RETRY */
+	reqhead->reassert_version = req->r_reassert_version;
+
+	req->r_stamp = jiffies;
+	list_move_tail(&req->r_req_lru_item, &osdc->req_lru);
+
+	ceph_msg_get(req->r_request); /* send consumes a ref */
+	ceph_con_send(&req->r_osd->o_con, req->r_request);
+	req->r_sent = req->r_osd->o_incarnation;
+	return 0;
+}
+
+/*
+ * 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
+ * ensure any communications channel reset is detected.  Reset the
+ * request timeouts another N seconds in the future as we go.
+ * Reschedule the timeout event another N seconds in future (unless
+ * there are no open requests).
+ */
+static void handle_timeout(struct work_struct *work)
+{
+	struct ceph_osd_client *osdc =
+		container_of(work, struct ceph_osd_client, timeout_work.work);
+	struct ceph_osd_request *req, *last_req = NULL;
+	struct ceph_osd *osd;
+	unsigned long timeout = osdc->client->options->osd_timeout * HZ;
+	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
+	 * is a failsafe measure.. we really shouldn't be getting to
+	 * this point if the system is working properly.  the monitors
+	 * should mark the osd as failed and we should find out about
+	 * it from an updated osd map.
+	 */
+	while (timeout && !list_empty(&osdc->req_lru)) {
+		req = list_entry(osdc->req_lru.next, struct ceph_osd_request,
+				 r_req_lru_item);
+
+		if (time_before(jiffies, req->r_stamp + timeout))
+			break;
+
+		BUG_ON(req == last_req && req->r_stamp == last_stamp);
+		last_req = req;
+		last_stamp = req->r_stamp;
+
+		osd = req->r_osd;
+		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);
+	}
+
+	/*
+	 * ping osds that are a bit slow.  this ensures that if there
+	 * is a break in the TCP connection we will notice, and reopen
+	 * a connection with that osd (from the fault callback).
+	 */
+	INIT_LIST_HEAD(&slow_osds);
+	list_for_each_entry(req, &osdc->req_lru, r_req_lru_item) {
+		if (time_before(jiffies, req->r_stamp + keepalive))
+			break;
+
+		osd = req->r_osd;
+		BUG_ON(!osd);
+		dout(" tid %llu is slow, will send keepalive on osd%d\n",
+		     req->r_tid, osd->o_osd);
+		list_move_tail(&osd->o_keepalive_item, &slow_osds);
+	}
+	while (!list_empty(&slow_osds)) {
+		osd = list_entry(slow_osds.next, struct ceph_osd,
+				 o_keepalive_item);
+		list_del_init(&osd->o_keepalive_item);
+		ceph_con_keepalive(&osd->o_con);
+	}
+
+	__schedule_osd_timeout(osdc);
+	mutex_unlock(&osdc->request_mutex);
+
+	up_read(&osdc->map_sem);
+}
+
+static void handle_osds_timeout(struct work_struct *work)
+{
+	struct ceph_osd_client *osdc =
+		container_of(work, struct ceph_osd_client,
+			     osds_timeout_work.work);
+	unsigned long delay =
+		osdc->client->options->osd_idle_ttl * HZ >> 2;
+
+	dout("osds timeout\n");
+	down_read(&osdc->map_sem);
+	remove_old_osds(osdc, 0);
+	up_read(&osdc->map_sem);
+
+	schedule_delayed_work(&osdc->osds_timeout_work,
+			      round_jiffies_relative(delay));
+}
+
+/*
+ * handle osd op reply.  either call the callback if it is specified,
+ * or do the completion to wake up the waiting thread.
+ */
+static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
+			 struct ceph_connection *con)
+{
+	struct ceph_osd_reply_head *rhead = msg->front.iov_base;
+	struct ceph_osd_request *req;
+	u64 tid;
+	int numops, object_len, flags;
+	s32 result;
+
+	tid = le64_to_cpu(msg->hdr.tid);
+	if (msg->front.iov_len < sizeof(*rhead))
+		goto bad;
+	numops = le32_to_cpu(rhead->num_ops);
+	object_len = le32_to_cpu(rhead->object_len);
+	result = le32_to_cpu(rhead->result);
+	if (msg->front.iov_len != sizeof(*rhead) + object_len +
+	    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);
+	if (req == NULL) {
+		dout("handle_reply tid %llu dne\n", tid);
+		mutex_unlock(&osdc->request_mutex);
+		return;
+	}
+	ceph_osdc_get_request(req);
+	flags = le32_to_cpu(rhead->flags);
+
+	/*
+	 * if this connection filled our message, drop our reference now, to
+	 * avoid a (safe but slower) revoke later.
+	 */
+	if (req->r_con_filling_msg == con && req->r_reply == msg) {
+		dout(" dropping con_filling_msg ref %p\n", con);
+		req->r_con_filling_msg = NULL;
+		ceph_con_put(con);
+	}
+
+	if (!req->r_got_reply) {
+		unsigned bytes;
+
+		req->r_result = le32_to_cpu(rhead->result);
+		bytes = le32_to_cpu(msg->hdr.data_len);
+		dout("handle_reply result %d bytes %d\n", req->r_result,
+		     bytes);
+		if (req->r_result == 0)
+			req->r_result = bytes;
+
+		/* in case this is a write and we need to replay, */
+		req->r_reassert_version = rhead->reassert_version;
+
+		req->r_got_reply = 1;
+	} else if ((flags & CEPH_OSD_FLAG_ONDISK) == 0) {
+		dout("handle_reply tid %llu dup ack\n", tid);
+		mutex_unlock(&osdc->request_mutex);
+		goto done;
+	}
+
+	dout("handle_reply tid %llu flags %d\n", tid, flags);
+
+	/* either this is a read, or we got the safe response */
+	if (result < 0 ||
+	    (flags & CEPH_OSD_FLAG_ONDISK) ||
+	    ((flags & CEPH_OSD_FLAG_WRITE) == 0))
+		__unregister_request(osdc, req);
+
+	mutex_unlock(&osdc->request_mutex);
+
+	if (req->r_callback)
+		req->r_callback(req, msg);
+	else
+		complete_all(&req->r_completion);
+
+	if (flags & CEPH_OSD_FLAG_ONDISK) {
+		if (req->r_safe_callback)
+			req->r_safe_callback(req, msg);
+		complete_all(&req->r_safe_completion);  /* fsync waiter */
+	}
+
+done:
+	ceph_osdc_put_request(req);
+	return;
+
+bad:
+	pr_err("corrupt osd_op_reply got %d %d expected %d\n",
+	       (int)msg->front.iov_len, le32_to_cpu(msg->hdr.front_len),
+	       (int)sizeof(*rhead));
+	ceph_msg_dump(msg);
+}
+
+
+static int __kick_requests(struct ceph_osd_client *osdc,
+			  struct ceph_osd *kickosd)
+{
+	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->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_osds(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;
+		}
+		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,
+		     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;
+		}
+	}
+
+	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.
+ *
+ * The message contains any number of incremental and full maps, normally
+ * indicating some sort of topology change in the cluster.  Kick requests
+ * off to different OSDs as needed.
+ */
+void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
+{
+	void *p, *end, *next;
+	u32 nr_maps, maplen;
+	u32 epoch;
+	struct ceph_osdmap *newmap = NULL, *oldmap;
+	int err;
+	struct ceph_fsid fsid;
+
+	dout("handle_map have %u\n", osdc->osdmap ? osdc->osdmap->epoch : 0);
+	p = msg->front.iov_base;
+	end = p + msg->front.iov_len;
+
+	/* verify fsid */
+	ceph_decode_need(&p, end, sizeof(fsid), bad);
+	ceph_decode_copy(&p, &fsid, sizeof(fsid));
+	if (ceph_check_fsid(osdc->client, &fsid) < 0)
+		return;
+
+	down_write(&osdc->map_sem);
+
+	/* incremental maps */
+	ceph_decode_32_safe(&p, end, nr_maps, bad);
+	dout(" %d inc maps\n", nr_maps);
+	while (nr_maps > 0) {
+		ceph_decode_need(&p, end, 2*sizeof(u32), bad);
+		epoch = ceph_decode_32(&p);
+		maplen = ceph_decode_32(&p);
+		ceph_decode_need(&p, end, maplen, bad);
+		next = p + maplen;
+		if (osdc->osdmap && osdc->osdmap->epoch+1 == epoch) {
+			dout("applying incremental map %u len %d\n",
+			     epoch, maplen);
+			newmap = osdmap_apply_incremental(&p, next,
+							  osdc->osdmap,
+							  osdc->client->msgr);
+			if (IS_ERR(newmap)) {
+				err = PTR_ERR(newmap);
+				goto bad;
+			}
+			BUG_ON(!newmap);
+			if (newmap != osdc->osdmap) {
+				ceph_osdmap_destroy(osdc->osdmap);
+				osdc->osdmap = newmap;
+			}
+		} else {
+			dout("ignoring incremental map %u len %d\n",
+			     epoch, maplen);
+		}
+		p = next;
+		nr_maps--;
+	}
+	if (newmap)
+		goto done;
+
+	/* full maps */
+	ceph_decode_32_safe(&p, end, nr_maps, bad);
+	dout(" %d full maps\n", nr_maps);
+	while (nr_maps) {
+		ceph_decode_need(&p, end, 2*sizeof(u32), bad);
+		epoch = ceph_decode_32(&p);
+		maplen = ceph_decode_32(&p);
+		ceph_decode_need(&p, end, maplen, bad);
+		if (nr_maps > 1) {
+			dout("skipping non-latest full map %u len %d\n",
+			     epoch, maplen);
+		} else if (osdc->osdmap && osdc->osdmap->epoch >= epoch) {
+			dout("skipping full map %u len %d, "
+			     "older than our %u\n", epoch, maplen,
+			     osdc->osdmap->epoch);
+		} else {
+			dout("taking full map %u len %d\n", epoch, maplen);
+			newmap = osdmap_decode(&p, p+maplen);
+			if (IS_ERR(newmap)) {
+				err = PTR_ERR(newmap);
+				goto bad;
+			}
+			BUG_ON(!newmap);
+			oldmap = osdc->osdmap;
+			osdc->osdmap = newmap;
+			if (oldmap)
+				ceph_osdmap_destroy(oldmap);
+		}
+		p += maplen;
+		nr_maps--;
+	}
+
+done:
+	downgrade_write(&osdc->map_sem);
+	ceph_monc_got_osdmap(&osdc->client->monc, osdc->osdmap->epoch);
+	if (newmap)
+		kick_requests(osdc, NULL);
+	up_read(&osdc->map_sem);
+	wake_up_all(&osdc->client->auth_wq);
+	return;
+
+bad:
+	pr_err("osdc handle_map corrupt msg\n");
+	ceph_msg_dump(msg);
+	up_write(&osdc->map_sem);
+	return;
+}
+
+/*
+ * Register request, send initial attempt.
+ */
+int ceph_osdc_start_request(struct ceph_osd_client *osdc,
+			    struct ceph_osd_request *req,
+			    bool nofail)
+{
+	int rc = 0;
+
+	req->r_request->pages = req->r_pages;
+	req->r_request->nr_pages = req->r_num_pages;
+#ifdef CONFIG_BLOCK
+	req->r_request->bio = req->r_bio;
+#endif
+	req->r_request->trail = req->r_trail;
+
+	register_request(osdc, req);
+
+	down_read(&osdc->map_sem);
+	mutex_lock(&osdc->request_mutex);
+	/*
+	 * a racing kick_requests() may have sent the message for us
+	 * while we dropped request_mutex above, so only send now if
+	 * 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);
+			}
+		}
+	}
+	mutex_unlock(&osdc->request_mutex);
+	up_read(&osdc->map_sem);
+	return rc;
+}
+EXPORT_SYMBOL(ceph_osdc_start_request);
+
+/*
+ * wait for a request to complete
+ */
+int ceph_osdc_wait_request(struct ceph_osd_client *osdc,
+			   struct ceph_osd_request *req)
+{
+	int rc;
+
+	rc = wait_for_completion_interruptible(&req->r_completion);
+	if (rc < 0) {
+		mutex_lock(&osdc->request_mutex);
+		__cancel_request(req);
+		__unregister_request(osdc, req);
+		mutex_unlock(&osdc->request_mutex);
+		dout("wait_request tid %llu canceled/timed out\n", req->r_tid);
+		return rc;
+	}
+
+	dout("wait_request tid %llu result %d\n", req->r_tid, req->r_result);
+	return req->r_result;
+}
+EXPORT_SYMBOL(ceph_osdc_wait_request);
+
+/*
+ * sync - wait for all in-flight requests to flush.  avoid starvation.
+ */
+void ceph_osdc_sync(struct ceph_osd_client *osdc)
+{
+	struct ceph_osd_request *req;
+	u64 last_tid, next_tid = 0;
+
+	mutex_lock(&osdc->request_mutex);
+	last_tid = osdc->last_tid;
+	while (1) {
+		req = __lookup_request_ge(osdc, next_tid);
+		if (!req)
+			break;
+		if (req->r_tid > last_tid)
+			break;
+
+		next_tid = req->r_tid + 1;
+		if ((req->r_flags & CEPH_OSD_FLAG_WRITE) == 0)
+			continue;
+
+		ceph_osdc_get_request(req);
+		mutex_unlock(&osdc->request_mutex);
+		dout("sync waiting on tid %llu (last is %llu)\n",
+		     req->r_tid, last_tid);
+		wait_for_completion(&req->r_safe_completion);
+		mutex_lock(&osdc->request_mutex);
+		ceph_osdc_put_request(req);
+	}
+	mutex_unlock(&osdc->request_mutex);
+	dout("sync done (thru tid %llu)\n", last_tid);
+}
+EXPORT_SYMBOL(ceph_osdc_sync);
+
+/*
+ * init, shutdown
+ */
+int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client)
+{
+	int err;
+
+	dout("init\n");
+	osdc->client = client;
+	osdc->osdmap = NULL;
+	init_rwsem(&osdc->map_sem);
+	init_completion(&osdc->map_waiters);
+	osdc->last_requested_map = 0;
+	mutex_init(&osdc->request_mutex);
+	osdc->last_tid = 0;
+	osdc->osds = RB_ROOT;
+	INIT_LIST_HEAD(&osdc->osd_lru);
+	osdc->requests = RB_ROOT;
+	INIT_LIST_HEAD(&osdc->req_lru);
+	osdc->num_requests = 0;
+	INIT_DELAYED_WORK(&osdc->timeout_work, handle_timeout);
+	INIT_DELAYED_WORK(&osdc->osds_timeout_work, handle_osds_timeout);
+
+	schedule_delayed_work(&osdc->osds_timeout_work,
+	   round_jiffies_relative(osdc->client->options->osd_idle_ttl * HZ));
+
+	err = -ENOMEM;
+	osdc->req_mempool = mempool_create_kmalloc_pool(10,
+					sizeof(struct ceph_osd_request));
+	if (!osdc->req_mempool)
+		goto out;
+
+	err = ceph_msgpool_init(&osdc->msgpool_op, OSD_OP_FRONT_LEN, 10, true,
+				"osd_op");
+	if (err < 0)
+		goto out_mempool;
+	err = ceph_msgpool_init(&osdc->msgpool_op_reply,
+				OSD_OPREPLY_FRONT_LEN, 10, true,
+				"osd_op_reply");
+	if (err < 0)
+		goto out_msgpool;
+	return 0;
+
+out_msgpool:
+	ceph_msgpool_destroy(&osdc->msgpool_op);
+out_mempool:
+	mempool_destroy(osdc->req_mempool);
+out:
+	return err;
+}
+EXPORT_SYMBOL(ceph_osdc_init);
+
+void ceph_osdc_stop(struct ceph_osd_client *osdc)
+{
+	cancel_delayed_work_sync(&osdc->timeout_work);
+	cancel_delayed_work_sync(&osdc->osds_timeout_work);
+	if (osdc->osdmap) {
+		ceph_osdmap_destroy(osdc->osdmap);
+		osdc->osdmap = NULL;
+	}
+	remove_old_osds(osdc, 1);
+	mempool_destroy(osdc->req_mempool);
+	ceph_msgpool_destroy(&osdc->msgpool_op);
+	ceph_msgpool_destroy(&osdc->msgpool_op_reply);
+}
+EXPORT_SYMBOL(ceph_osdc_stop);
+
+/*
+ * Read some contiguous pages.  If we cross a stripe boundary, shorten
+ * *plen.  Return number of bytes read, or error.
+ */
+int ceph_osdc_readpages(struct ceph_osd_client *osdc,
+			struct ceph_vino vino, struct ceph_file_layout *layout,
+			u64 off, u64 *plen,
+			u32 truncate_seq, u64 truncate_size,
+			struct page **pages, int num_pages)
+{
+	struct ceph_osd_request *req;
+	int rc = 0;
+
+	dout("readpages on ino %llx.%llx on %llu~%llu\n", vino.ino,
+	     vino.snap, off, *plen);
+	req = ceph_osdc_new_request(osdc, layout, vino, off, plen,
+				    CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ,
+				    NULL, 0, truncate_seq, truncate_size, NULL,
+				    false, 1);
+	if (!req)
+		return -ENOMEM;
+
+	/* it may be a short read due to an object boundary */
+	req->r_pages = pages;
+
+	dout("readpages  final extent is %llu~%llu (%d pages)\n",
+	     off, *plen, req->r_num_pages);
+
+	rc = ceph_osdc_start_request(osdc, req, false);
+	if (!rc)
+		rc = ceph_osdc_wait_request(osdc, req);
+
+	ceph_osdc_put_request(req);
+	dout("readpages result %d\n", rc);
+	return rc;
+}
+EXPORT_SYMBOL(ceph_osdc_readpages);
+
+/*
+ * do a synchronous write on N pages
+ */
+int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino,
+			 struct ceph_file_layout *layout,
+			 struct ceph_snap_context *snapc,
+			 u64 off, u64 len,
+			 u32 truncate_seq, u64 truncate_size,
+			 struct timespec *mtime,
+			 struct page **pages, int num_pages,
+			 int flags, int do_sync, bool nofail)
+{
+	struct ceph_osd_request *req;
+	int rc = 0;
+
+	BUG_ON(vino.snap != CEPH_NOSNAP);
+	req = ceph_osdc_new_request(osdc, layout, vino, off, &len,
+				    CEPH_OSD_OP_WRITE,
+				    flags | CEPH_OSD_FLAG_ONDISK |
+					    CEPH_OSD_FLAG_WRITE,
+				    snapc, do_sync,
+				    truncate_seq, truncate_size, mtime,
+				    nofail, 1);
+	if (!req)
+		return -ENOMEM;
+
+	/* it may be a short write due to an object boundary */
+	req->r_pages = pages;
+	dout("writepages %llu~%llu (%d pages)\n", off, len,
+	     req->r_num_pages);
+
+	rc = ceph_osdc_start_request(osdc, req, nofail);
+	if (!rc)
+		rc = ceph_osdc_wait_request(osdc, req);
+
+	ceph_osdc_put_request(req);
+	if (rc == 0)
+		rc = len;
+	dout("writepages result %d\n", rc);
+	return rc;
+}
+EXPORT_SYMBOL(ceph_osdc_writepages);
+
+/*
+ * handle incoming message
+ */
+static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
+{
+	struct ceph_osd *osd = con->private;
+	struct ceph_osd_client *osdc;
+	int type = le16_to_cpu(msg->hdr.type);
+
+	if (!osd)
+		goto out;
+	osdc = osd->o_osdc;
+
+	switch (type) {
+	case CEPH_MSG_OSD_MAP:
+		ceph_osdc_handle_map(osdc, msg);
+		break;
+	case CEPH_MSG_OSD_OPREPLY:
+		handle_reply(osdc, msg, con);
+		break;
+
+	default:
+		pr_err("received unknown message type %d %s\n", type,
+		       ceph_msg_type_name(type));
+	}
+out:
+	ceph_msg_put(msg);
+}
+
+/*
+ * lookup and return message for incoming reply.  set up reply message
+ * pages.
+ */
+static struct ceph_msg *get_reply(struct ceph_connection *con,
+				  struct ceph_msg_header *hdr,
+				  int *skip)
+{
+	struct ceph_osd *osd = con->private;
+	struct ceph_osd_client *osdc = osd->o_osdc;
+	struct ceph_msg *m;
+	struct ceph_osd_request *req;
+	int front = le32_to_cpu(hdr->front_len);
+	int data_len = le32_to_cpu(hdr->data_len);
+	u64 tid;
+
+	tid = le64_to_cpu(hdr->tid);
+	mutex_lock(&osdc->request_mutex);
+	req = __lookup_request(osdc, tid);
+	if (!req) {
+		*skip = 1;
+		m = NULL;
+		pr_info("get_reply unknown tid %llu from osd%d\n", tid,
+			osd->o_osd);
+		goto out;
+	}
+
+	if (req->r_con_filling_msg) {
+		dout("get_reply revoking msg %p from old con %p\n",
+		     req->r_reply, req->r_con_filling_msg);
+		ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply);
+		ceph_con_put(req->r_con_filling_msg);
+		req->r_con_filling_msg = NULL;
+	}
+
+	if (front > req->r_reply->front.iov_len) {
+		pr_warning("get_reply front %d > preallocated %d\n",
+			   front, (int)req->r_reply->front.iov_len);
+		m = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, front, GFP_NOFS);
+		if (!m)
+			goto out;
+		ceph_msg_put(req->r_reply);
+		req->r_reply = m;
+	}
+	m = ceph_msg_get(req->r_reply);
+
+	if (data_len > 0) {
+		unsigned data_off = le16_to_cpu(hdr->data_off);
+		int want = calc_pages_for(data_off & ~PAGE_MASK, data_len);
+
+		if (unlikely(req->r_num_pages < want)) {
+			pr_warning("tid %lld reply %d > expected %d pages\n",
+				   tid, want, m->nr_pages);
+			*skip = 1;
+			ceph_msg_put(m);
+			m = NULL;
+			goto out;
+		}
+		m->pages = req->r_pages;
+		m->nr_pages = req->r_num_pages;
+#ifdef CONFIG_BLOCK
+		m->bio = req->r_bio;
+#endif
+	}
+	*skip = 0;
+	req->r_con_filling_msg = ceph_con_get(con);
+	dout("get_reply tid %lld %p\n", tid, m);
+
+out:
+	mutex_unlock(&osdc->request_mutex);
+	return m;
+
+}
+
+static struct ceph_msg *alloc_msg(struct ceph_connection *con,
+				  struct ceph_msg_header *hdr,
+				  int *skip)
+{
+	struct ceph_osd *osd = con->private;
+	int type = le16_to_cpu(hdr->type);
+	int front = le32_to_cpu(hdr->front_len);
+
+	switch (type) {
+	case CEPH_MSG_OSD_MAP:
+		return ceph_msg_new(type, front, GFP_NOFS);
+	case CEPH_MSG_OSD_OPREPLY:
+		return get_reply(con, hdr, skip);
+	default:
+		pr_info("alloc_msg unexpected msg type %d from osd%d\n", type,
+			osd->o_osd);
+		*skip = 1;
+		return NULL;
+	}
+}
+
+/*
+ * Wrappers to refcount containing ceph_osd struct
+ */
+static struct ceph_connection *get_osd_con(struct ceph_connection *con)
+{
+	struct ceph_osd *osd = con->private;
+	if (get_osd(osd))
+		return con;
+	return NULL;
+}
+
+static void put_osd_con(struct ceph_connection *con)
+{
+	struct ceph_osd *osd = con->private;
+	put_osd(osd);
+}
+
+/*
+ * authentication
+ */
+static int get_authorizer(struct ceph_connection *con,
+			  void **buf, int *len, int *proto,
+			  void **reply_buf, int *reply_len, int force_new)
+{
+	struct ceph_osd *o = con->private;
+	struct ceph_osd_client *osdc = o->o_osdc;
+	struct ceph_auth_client *ac = osdc->client->monc.auth;
+	int ret = 0;
+
+	if (force_new && o->o_authorizer) {
+		ac->ops->destroy_authorizer(ac, o->o_authorizer);
+		o->o_authorizer = NULL;
+	}
+	if (o->o_authorizer == NULL) {
+		ret = ac->ops->create_authorizer(
+			ac, CEPH_ENTITY_TYPE_OSD,
+			&o->o_authorizer,
+			&o->o_authorizer_buf,
+			&o->o_authorizer_buf_len,
+			&o->o_authorizer_reply_buf,
+			&o->o_authorizer_reply_buf_len);
+		if (ret)
+			return ret;
+	}
+
+	*proto = ac->protocol;
+	*buf = o->o_authorizer_buf;
+	*len = o->o_authorizer_buf_len;
+	*reply_buf = o->o_authorizer_reply_buf;
+	*reply_len = o->o_authorizer_reply_buf_len;
+	return 0;
+}
+
+
+static int verify_authorizer_reply(struct ceph_connection *con, int len)
+{
+	struct ceph_osd *o = con->private;
+	struct ceph_osd_client *osdc = o->o_osdc;
+	struct ceph_auth_client *ac = osdc->client->monc.auth;
+
+	return ac->ops->verify_authorizer_reply(ac, o->o_authorizer, len);
+}
+
+static int invalidate_authorizer(struct ceph_connection *con)
+{
+	struct ceph_osd *o = con->private;
+	struct ceph_osd_client *osdc = o->o_osdc;
+	struct ceph_auth_client *ac = osdc->client->monc.auth;
+
+	if (ac->ops->invalidate_authorizer)
+		ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD);
+
+	return ceph_monc_validate_auth(&osdc->client->monc);
+}
+
+static const struct ceph_connection_operations osd_con_ops = {
+	.get = get_osd_con,
+	.put = put_osd_con,
+	.dispatch = dispatch,
+	.get_authorizer = get_authorizer,
+	.verify_authorizer_reply = verify_authorizer_reply,
+	.invalidate_authorizer = invalidate_authorizer,
+	.alloc_msg = alloc_msg,
+	.fault = osd_reset,
+};
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
new file mode 100644
index 0000000..d73f3f6
--- /dev/null
+++ b/net/ceph/osdmap.c
@@ -0,0 +1,1128 @@
+
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/div64.h>
+
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/osdmap.h>
+#include <linux/ceph/decode.h>
+#include <linux/crush/hash.h>
+#include <linux/crush/mapper.h>
+
+char *ceph_osdmap_state_str(char *str, int len, int state)
+{
+	int flag = 0;
+
+	if (!len)
+		goto done;
+
+	*str = '\0';
+	if (state) {
+		if (state & CEPH_OSD_EXISTS) {
+			snprintf(str, len, "exists");
+			flag = 1;
+		}
+		if (state & CEPH_OSD_UP) {
+			snprintf(str, len, "%s%s%s", str, (flag ? ", " : ""),
+				 "up");
+			flag = 1;
+		}
+	} else {
+		snprintf(str, len, "doesn't exist");
+	}
+done:
+	return str;
+}
+
+/* maps */
+
+static int calc_bits_of(unsigned t)
+{
+	int b = 0;
+	while (t) {
+		t = t >> 1;
+		b++;
+	}
+	return b;
+}
+
+/*
+ * the foo_mask is the smallest value 2^n-1 that is >= foo.
+ */
+static void calc_pg_masks(struct ceph_pg_pool_info *pi)
+{
+	pi->pg_num_mask = (1 << calc_bits_of(le32_to_cpu(pi->v.pg_num)-1)) - 1;
+	pi->pgp_num_mask =
+		(1 << calc_bits_of(le32_to_cpu(pi->v.pgp_num)-1)) - 1;
+	pi->lpg_num_mask =
+		(1 << calc_bits_of(le32_to_cpu(pi->v.lpg_num)-1)) - 1;
+	pi->lpgp_num_mask =
+		(1 << calc_bits_of(le32_to_cpu(pi->v.lpgp_num)-1)) - 1;
+}
+
+/*
+ * decode crush map
+ */
+static int crush_decode_uniform_bucket(void **p, void *end,
+				       struct crush_bucket_uniform *b)
+{
+	dout("crush_decode_uniform_bucket %p to %p\n", *p, end);
+	ceph_decode_need(p, end, (1+b->h.size) * sizeof(u32), bad);
+	b->item_weight = ceph_decode_32(p);
+	return 0;
+bad:
+	return -EINVAL;
+}
+
+static int crush_decode_list_bucket(void **p, void *end,
+				    struct crush_bucket_list *b)
+{
+	int j;
+	dout("crush_decode_list_bucket %p to %p\n", *p, end);
+	b->item_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS);
+	if (b->item_weights == NULL)
+		return -ENOMEM;
+	b->sum_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS);
+	if (b->sum_weights == NULL)
+		return -ENOMEM;
+	ceph_decode_need(p, end, 2 * b->h.size * sizeof(u32), bad);
+	for (j = 0; j < b->h.size; j++) {
+		b->item_weights[j] = ceph_decode_32(p);
+		b->sum_weights[j] = ceph_decode_32(p);
+	}
+	return 0;
+bad:
+	return -EINVAL;
+}
+
+static int crush_decode_tree_bucket(void **p, void *end,
+				    struct crush_bucket_tree *b)
+{
+	int j;
+	dout("crush_decode_tree_bucket %p to %p\n", *p, end);
+	ceph_decode_32_safe(p, end, b->num_nodes, bad);
+	b->node_weights = kcalloc(b->num_nodes, sizeof(u32), GFP_NOFS);
+	if (b->node_weights == NULL)
+		return -ENOMEM;
+	ceph_decode_need(p, end, b->num_nodes * sizeof(u32), bad);
+	for (j = 0; j < b->num_nodes; j++)
+		b->node_weights[j] = ceph_decode_32(p);
+	return 0;
+bad:
+	return -EINVAL;
+}
+
+static int crush_decode_straw_bucket(void **p, void *end,
+				     struct crush_bucket_straw *b)
+{
+	int j;
+	dout("crush_decode_straw_bucket %p to %p\n", *p, end);
+	b->item_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS);
+	if (b->item_weights == NULL)
+		return -ENOMEM;
+	b->straws = kcalloc(b->h.size, sizeof(u32), GFP_NOFS);
+	if (b->straws == NULL)
+		return -ENOMEM;
+	ceph_decode_need(p, end, 2 * b->h.size * sizeof(u32), bad);
+	for (j = 0; j < b->h.size; j++) {
+		b->item_weights[j] = ceph_decode_32(p);
+		b->straws[j] = ceph_decode_32(p);
+	}
+	return 0;
+bad:
+	return -EINVAL;
+}
+
+static struct crush_map *crush_decode(void *pbyval, void *end)
+{
+	struct crush_map *c;
+	int err = -EINVAL;
+	int i, j;
+	void **p = &pbyval;
+	void *start = pbyval;
+	u32 magic;
+
+	dout("crush_decode %p to %p len %d\n", *p, end, (int)(end - *p));
+
+	c = kzalloc(sizeof(*c), GFP_NOFS);
+	if (c == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	ceph_decode_need(p, end, 4*sizeof(u32), bad);
+	magic = ceph_decode_32(p);
+	if (magic != CRUSH_MAGIC) {
+		pr_err("crush_decode magic %x != current %x\n",
+		       (unsigned)magic, (unsigned)CRUSH_MAGIC);
+		goto bad;
+	}
+	c->max_buckets = ceph_decode_32(p);
+	c->max_rules = ceph_decode_32(p);
+	c->max_devices = ceph_decode_32(p);
+
+	c->device_parents = kcalloc(c->max_devices, sizeof(u32), GFP_NOFS);
+	if (c->device_parents == NULL)
+		goto badmem;
+	c->bucket_parents = kcalloc(c->max_buckets, sizeof(u32), GFP_NOFS);
+	if (c->bucket_parents == NULL)
+		goto badmem;
+
+	c->buckets = kcalloc(c->max_buckets, sizeof(*c->buckets), GFP_NOFS);
+	if (c->buckets == NULL)
+		goto badmem;
+	c->rules = kcalloc(c->max_rules, sizeof(*c->rules), GFP_NOFS);
+	if (c->rules == NULL)
+		goto badmem;
+
+	/* buckets */
+	for (i = 0; i < c->max_buckets; i++) {
+		int size = 0;
+		u32 alg;
+		struct crush_bucket *b;
+
+		ceph_decode_32_safe(p, end, alg, bad);
+		if (alg == 0) {
+			c->buckets[i] = NULL;
+			continue;
+		}
+		dout("crush_decode bucket %d off %x %p to %p\n",
+		     i, (int)(*p-start), *p, end);
+
+		switch (alg) {
+		case CRUSH_BUCKET_UNIFORM:
+			size = sizeof(struct crush_bucket_uniform);
+			break;
+		case CRUSH_BUCKET_LIST:
+			size = sizeof(struct crush_bucket_list);
+			break;
+		case CRUSH_BUCKET_TREE:
+			size = sizeof(struct crush_bucket_tree);
+			break;
+		case CRUSH_BUCKET_STRAW:
+			size = sizeof(struct crush_bucket_straw);
+			break;
+		default:
+			err = -EINVAL;
+			goto bad;
+		}
+		BUG_ON(size == 0);
+		b = c->buckets[i] = kzalloc(size, GFP_NOFS);
+		if (b == NULL)
+			goto badmem;
+
+		ceph_decode_need(p, end, 4*sizeof(u32), bad);
+		b->id = ceph_decode_32(p);
+		b->type = ceph_decode_16(p);
+		b->alg = ceph_decode_8(p);
+		b->hash = ceph_decode_8(p);
+		b->weight = ceph_decode_32(p);
+		b->size = ceph_decode_32(p);
+
+		dout("crush_decode bucket size %d off %x %p to %p\n",
+		     b->size, (int)(*p-start), *p, end);
+
+		b->items = kcalloc(b->size, sizeof(__s32), GFP_NOFS);
+		if (b->items == NULL)
+			goto badmem;
+		b->perm = kcalloc(b->size, sizeof(u32), GFP_NOFS);
+		if (b->perm == NULL)
+			goto badmem;
+		b->perm_n = 0;
+
+		ceph_decode_need(p, end, b->size*sizeof(u32), bad);
+		for (j = 0; j < b->size; j++)
+			b->items[j] = ceph_decode_32(p);
+
+		switch (b->alg) {
+		case CRUSH_BUCKET_UNIFORM:
+			err = crush_decode_uniform_bucket(p, end,
+				  (struct crush_bucket_uniform *)b);
+			if (err < 0)
+				goto bad;
+			break;
+		case CRUSH_BUCKET_LIST:
+			err = crush_decode_list_bucket(p, end,
+			       (struct crush_bucket_list *)b);
+			if (err < 0)
+				goto bad;
+			break;
+		case CRUSH_BUCKET_TREE:
+			err = crush_decode_tree_bucket(p, end,
+				(struct crush_bucket_tree *)b);
+			if (err < 0)
+				goto bad;
+			break;
+		case CRUSH_BUCKET_STRAW:
+			err = crush_decode_straw_bucket(p, end,
+				(struct crush_bucket_straw *)b);
+			if (err < 0)
+				goto bad;
+			break;
+		}
+	}
+
+	/* rules */
+	dout("rule vec is %p\n", c->rules);
+	for (i = 0; i < c->max_rules; i++) {
+		u32 yes;
+		struct crush_rule *r;
+
+		ceph_decode_32_safe(p, end, yes, bad);
+		if (!yes) {
+			dout("crush_decode NO rule %d off %x %p to %p\n",
+			     i, (int)(*p-start), *p, end);
+			c->rules[i] = NULL;
+			continue;
+		}
+
+		dout("crush_decode rule %d off %x %p to %p\n",
+		     i, (int)(*p-start), *p, end);
+
+		/* len */
+		ceph_decode_32_safe(p, end, yes, bad);
+#if BITS_PER_LONG == 32
+		err = -EINVAL;
+		if (yes > ULONG_MAX / sizeof(struct crush_rule_step))
+			goto bad;
+#endif
+		r = c->rules[i] = kmalloc(sizeof(*r) +
+					  yes*sizeof(struct crush_rule_step),
+					  GFP_NOFS);
+		if (r == NULL)
+			goto badmem;
+		dout(" rule %d is at %p\n", i, r);
+		r->len = yes;
+		ceph_decode_copy_safe(p, end, &r->mask, 4, bad); /* 4 u8's */
+		ceph_decode_need(p, end, r->len*3*sizeof(u32), bad);
+		for (j = 0; j < r->len; j++) {
+			r->steps[j].op = ceph_decode_32(p);
+			r->steps[j].arg1 = ceph_decode_32(p);
+			r->steps[j].arg2 = ceph_decode_32(p);
+		}
+	}
+
+	/* ignore trailing name maps. */
+
+	dout("crush_decode success\n");
+	return c;
+
+badmem:
+	err = -ENOMEM;
+bad:
+	dout("crush_decode fail %d\n", err);
+	crush_destroy(c);
+	return ERR_PTR(err);
+}
+
+/*
+ * rbtree of pg_mapping for handling pg_temp (explicit mapping of pgid
+ * to a set of osds)
+ */
+static int pgid_cmp(struct ceph_pg l, struct ceph_pg r)
+{
+	u64 a = *(u64 *)&l;
+	u64 b = *(u64 *)&r;
+
+	if (a < b)
+		return -1;
+	if (a > b)
+		return 1;
+	return 0;
+}
+
+static int __insert_pg_mapping(struct ceph_pg_mapping *new,
+			       struct rb_root *root)
+{
+	struct rb_node **p = &root->rb_node;
+	struct rb_node *parent = NULL;
+	struct ceph_pg_mapping *pg = NULL;
+	int c;
+
+	while (*p) {
+		parent = *p;
+		pg = rb_entry(parent, struct ceph_pg_mapping, node);
+		c = pgid_cmp(new->pgid, pg->pgid);
+		if (c < 0)
+			p = &(*p)->rb_left;
+		else if (c > 0)
+			p = &(*p)->rb_right;
+		else
+			return -EEXIST;
+	}
+
+	rb_link_node(&new->node, parent, p);
+	rb_insert_color(&new->node, root);
+	return 0;
+}
+
+static struct ceph_pg_mapping *__lookup_pg_mapping(struct rb_root *root,
+						   struct ceph_pg pgid)
+{
+	struct rb_node *n = root->rb_node;
+	struct ceph_pg_mapping *pg;
+	int c;
+
+	while (n) {
+		pg = rb_entry(n, struct ceph_pg_mapping, node);
+		c = pgid_cmp(pgid, pg->pgid);
+		if (c < 0)
+			n = n->rb_left;
+		else if (c > 0)
+			n = n->rb_right;
+		else
+			return pg;
+	}
+	return NULL;
+}
+
+/*
+ * rbtree of pg pool info
+ */
+static int __insert_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *new)
+{
+	struct rb_node **p = &root->rb_node;
+	struct rb_node *parent = NULL;
+	struct ceph_pg_pool_info *pi = NULL;
+
+	while (*p) {
+		parent = *p;
+		pi = rb_entry(parent, struct ceph_pg_pool_info, node);
+		if (new->id < pi->id)
+			p = &(*p)->rb_left;
+		else if (new->id > pi->id)
+			p = &(*p)->rb_right;
+		else
+			return -EEXIST;
+	}
+
+	rb_link_node(&new->node, parent, p);
+	rb_insert_color(&new->node, root);
+	return 0;
+}
+
+static struct ceph_pg_pool_info *__lookup_pg_pool(struct rb_root *root, int id)
+{
+	struct ceph_pg_pool_info *pi;
+	struct rb_node *n = root->rb_node;
+
+	while (n) {
+		pi = rb_entry(n, struct ceph_pg_pool_info, node);
+		if (id < pi->id)
+			n = n->rb_left;
+		else if (id > pi->id)
+			n = n->rb_right;
+		else
+			return pi;
+	}
+	return NULL;
+}
+
+int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name)
+{
+	struct rb_node *rbp;
+
+	for (rbp = rb_first(&map->pg_pools); rbp; rbp = rb_next(rbp)) {
+		struct ceph_pg_pool_info *pi =
+			rb_entry(rbp, struct ceph_pg_pool_info, node);
+		if (pi->name && strcmp(pi->name, name) == 0)
+			return pi->id;
+	}
+	return -ENOENT;
+}
+EXPORT_SYMBOL(ceph_pg_poolid_by_name);
+
+static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi)
+{
+	rb_erase(&pi->node, root);
+	kfree(pi->name);
+	kfree(pi);
+}
+
+static int __decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi)
+{
+	unsigned n, m;
+
+	ceph_decode_copy(p, &pi->v, sizeof(pi->v));
+	calc_pg_masks(pi);
+
+	/* num_snaps * snap_info_t */
+	n = le32_to_cpu(pi->v.num_snaps);
+	while (n--) {
+		ceph_decode_need(p, end, sizeof(u64) + 1 + sizeof(u64) +
+				 sizeof(struct ceph_timespec), bad);
+		*p += sizeof(u64) +       /* key */
+			1 + sizeof(u64) + /* u8, snapid */
+			sizeof(struct ceph_timespec);
+		m = ceph_decode_32(p);    /* snap name */
+		*p += m;
+	}
+
+	*p += le32_to_cpu(pi->v.num_removed_snap_intervals) * sizeof(u64) * 2;
+	return 0;
+
+bad:
+	return -EINVAL;
+}
+
+static int __decode_pool_names(void **p, void *end, struct ceph_osdmap *map)
+{
+	struct ceph_pg_pool_info *pi;
+	u32 num, len, pool;
+
+	ceph_decode_32_safe(p, end, num, bad);
+	dout(" %d pool names\n", num);
+	while (num--) {
+		ceph_decode_32_safe(p, end, pool, bad);
+		ceph_decode_32_safe(p, end, len, bad);
+		dout("  pool %d len %d\n", pool, len);
+		pi = __lookup_pg_pool(&map->pg_pools, pool);
+		if (pi) {
+			kfree(pi->name);
+			pi->name = kmalloc(len + 1, GFP_NOFS);
+			if (pi->name) {
+				memcpy(pi->name, *p, len);
+				pi->name[len] = '\0';
+				dout("  name is %s\n", pi->name);
+			}
+		}
+		*p += len;
+	}
+	return 0;
+
+bad:
+	return -EINVAL;
+}
+
+/*
+ * osd map
+ */
+void ceph_osdmap_destroy(struct ceph_osdmap *map)
+{
+	dout("osdmap_destroy %p\n", map);
+	if (map->crush)
+		crush_destroy(map->crush);
+	while (!RB_EMPTY_ROOT(&map->pg_temp)) {
+		struct ceph_pg_mapping *pg =
+			rb_entry(rb_first(&map->pg_temp),
+				 struct ceph_pg_mapping, node);
+		rb_erase(&pg->node, &map->pg_temp);
+		kfree(pg);
+	}
+	while (!RB_EMPTY_ROOT(&map->pg_pools)) {
+		struct ceph_pg_pool_info *pi =
+			rb_entry(rb_first(&map->pg_pools),
+				 struct ceph_pg_pool_info, node);
+		__remove_pg_pool(&map->pg_pools, pi);
+	}
+	kfree(map->osd_state);
+	kfree(map->osd_weight);
+	kfree(map->osd_addr);
+	kfree(map);
+}
+
+/*
+ * adjust max osd value.  reallocate arrays.
+ */
+static int osdmap_set_max_osd(struct ceph_osdmap *map, int max)
+{
+	u8 *state;
+	struct ceph_entity_addr *addr;
+	u32 *weight;
+
+	state = kcalloc(max, sizeof(*state), GFP_NOFS);
+	addr = kcalloc(max, sizeof(*addr), GFP_NOFS);
+	weight = kcalloc(max, sizeof(*weight), GFP_NOFS);
+	if (state == NULL || addr == NULL || weight == NULL) {
+		kfree(state);
+		kfree(addr);
+		kfree(weight);
+		return -ENOMEM;
+	}
+
+	/* copy old? */
+	if (map->osd_state) {
+		memcpy(state, map->osd_state, map->max_osd*sizeof(*state));
+		memcpy(addr, map->osd_addr, map->max_osd*sizeof(*addr));
+		memcpy(weight, map->osd_weight, map->max_osd*sizeof(*weight));
+		kfree(map->osd_state);
+		kfree(map->osd_addr);
+		kfree(map->osd_weight);
+	}
+
+	map->osd_state = state;
+	map->osd_weight = weight;
+	map->osd_addr = addr;
+	map->max_osd = max;
+	return 0;
+}
+
+/*
+ * decode a full map.
+ */
+struct ceph_osdmap *osdmap_decode(void **p, void *end)
+{
+	struct ceph_osdmap *map;
+	u16 version;
+	u32 len, max, i;
+	u8 ev;
+	int err = -EINVAL;
+	void *start = *p;
+	struct ceph_pg_pool_info *pi;
+
+	dout("osdmap_decode %p to %p len %d\n", *p, end, (int)(end - *p));
+
+	map = kzalloc(sizeof(*map), GFP_NOFS);
+	if (map == NULL)
+		return ERR_PTR(-ENOMEM);
+	map->pg_temp = RB_ROOT;
+
+	ceph_decode_16_safe(p, end, version, bad);
+	if (version > CEPH_OSDMAP_VERSION) {
+		pr_warning("got unknown v %d > %d of osdmap\n", version,
+			   CEPH_OSDMAP_VERSION);
+		goto bad;
+	}
+
+	ceph_decode_need(p, end, 2*sizeof(u64)+6*sizeof(u32), bad);
+	ceph_decode_copy(p, &map->fsid, sizeof(map->fsid));
+	map->epoch = ceph_decode_32(p);
+	ceph_decode_copy(p, &map->created, sizeof(map->created));
+	ceph_decode_copy(p, &map->modified, sizeof(map->modified));
+
+	ceph_decode_32_safe(p, end, max, bad);
+	while (max--) {
+		ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad);
+		pi = kzalloc(sizeof(*pi), GFP_NOFS);
+		if (!pi)
+			goto bad;
+		pi->id = ceph_decode_32(p);
+		ev = ceph_decode_8(p); /* encoding version */
+		if (ev > CEPH_PG_POOL_VERSION) {
+			pr_warning("got unknown v %d > %d of ceph_pg_pool\n",
+				   ev, CEPH_PG_POOL_VERSION);
+			kfree(pi);
+			goto bad;
+		}
+		err = __decode_pool(p, end, pi);
+		if (err < 0)
+			goto bad;
+		__insert_pg_pool(&map->pg_pools, pi);
+	}
+
+	if (version >= 5 && __decode_pool_names(p, end, map) < 0)
+		goto bad;
+
+	ceph_decode_32_safe(p, end, map->pool_max, bad);
+
+	ceph_decode_32_safe(p, end, map->flags, bad);
+
+	max = ceph_decode_32(p);
+
+	/* (re)alloc osd arrays */
+	err = osdmap_set_max_osd(map, max);
+	if (err < 0)
+		goto bad;
+	dout("osdmap_decode max_osd = %d\n", map->max_osd);
+
+	/* osds */
+	err = -EINVAL;
+	ceph_decode_need(p, end, 3*sizeof(u32) +
+			 map->max_osd*(1 + sizeof(*map->osd_weight) +
+				       sizeof(*map->osd_addr)), bad);
+	*p += 4; /* skip length field (should match max) */
+	ceph_decode_copy(p, map->osd_state, map->max_osd);
+
+	*p += 4; /* skip length field (should match max) */
+	for (i = 0; i < map->max_osd; i++)
+		map->osd_weight[i] = ceph_decode_32(p);
+
+	*p += 4; /* skip length field (should match max) */
+	ceph_decode_copy(p, map->osd_addr, map->max_osd*sizeof(*map->osd_addr));
+	for (i = 0; i < map->max_osd; i++)
+		ceph_decode_addr(&map->osd_addr[i]);
+
+	/* pg_temp */
+	ceph_decode_32_safe(p, end, len, bad);
+	for (i = 0; i < len; i++) {
+		int n, j;
+		struct ceph_pg pgid;
+		struct ceph_pg_mapping *pg;
+
+		ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad);
+		ceph_decode_copy(p, &pgid, sizeof(pgid));
+		n = ceph_decode_32(p);
+		ceph_decode_need(p, end, n * sizeof(u32), bad);
+		err = -ENOMEM;
+		pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS);
+		if (!pg)
+			goto bad;
+		pg->pgid = pgid;
+		pg->len = n;
+		for (j = 0; j < n; j++)
+			pg->osds[j] = ceph_decode_32(p);
+
+		err = __insert_pg_mapping(pg, &map->pg_temp);
+		if (err)
+			goto bad;
+		dout(" added pg_temp %llx len %d\n", *(u64 *)&pgid, len);
+	}
+
+	/* crush */
+	ceph_decode_32_safe(p, end, len, bad);
+	dout("osdmap_decode crush len %d from off 0x%x\n", len,
+	     (int)(*p - start));
+	ceph_decode_need(p, end, len, bad);
+	map->crush = crush_decode(*p, end);
+	*p += len;
+	if (IS_ERR(map->crush)) {
+		err = PTR_ERR(map->crush);
+		map->crush = NULL;
+		goto bad;
+	}
+
+	/* ignore the rest of the map */
+	*p = end;
+
+	dout("osdmap_decode done %p %p\n", *p, end);
+	return map;
+
+bad:
+	dout("osdmap_decode fail\n");
+	ceph_osdmap_destroy(map);
+	return ERR_PTR(err);
+}
+
+/*
+ * decode and apply an incremental map update.
+ */
+struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
+					     struct ceph_osdmap *map,
+					     struct ceph_messenger *msgr)
+{
+	struct crush_map *newcrush = NULL;
+	struct ceph_fsid fsid;
+	u32 epoch = 0;
+	struct ceph_timespec modified;
+	u32 len, pool;
+	__s32 new_pool_max, new_flags, max;
+	void *start = *p;
+	int err = -EINVAL;
+	u16 version;
+	struct rb_node *rbp;
+
+	ceph_decode_16_safe(p, end, version, bad);
+	if (version > CEPH_OSDMAP_INC_VERSION) {
+		pr_warning("got unknown v %d > %d of inc osdmap\n", version,
+			   CEPH_OSDMAP_INC_VERSION);
+		goto bad;
+	}
+
+	ceph_decode_need(p, end, sizeof(fsid)+sizeof(modified)+2*sizeof(u32),
+			 bad);
+	ceph_decode_copy(p, &fsid, sizeof(fsid));
+	epoch = ceph_decode_32(p);
+	BUG_ON(epoch != map->epoch+1);
+	ceph_decode_copy(p, &modified, sizeof(modified));
+	new_pool_max = ceph_decode_32(p);
+	new_flags = ceph_decode_32(p);
+
+	/* full map? */
+	ceph_decode_32_safe(p, end, len, bad);
+	if (len > 0) {
+		dout("apply_incremental full map len %d, %p to %p\n",
+		     len, *p, end);
+		return osdmap_decode(p, min(*p+len, end));
+	}
+
+	/* new crush? */
+	ceph_decode_32_safe(p, end, len, bad);
+	if (len > 0) {
+		dout("apply_incremental new crush map len %d, %p to %p\n",
+		     len, *p, end);
+		newcrush = crush_decode(*p, min(*p+len, end));
+		if (IS_ERR(newcrush))
+			return ERR_CAST(newcrush);
+		*p += len;
+	}
+
+	/* new flags? */
+	if (new_flags >= 0)
+		map->flags = new_flags;
+	if (new_pool_max >= 0)
+		map->pool_max = new_pool_max;
+
+	ceph_decode_need(p, end, 5*sizeof(u32), bad);
+
+	/* new max? */
+	max = ceph_decode_32(p);
+	if (max >= 0) {
+		err = osdmap_set_max_osd(map, max);
+		if (err < 0)
+			goto bad;
+	}
+
+	map->epoch++;
+	map->modified = map->modified;
+	if (newcrush) {
+		if (map->crush)
+			crush_destroy(map->crush);
+		map->crush = newcrush;
+		newcrush = NULL;
+	}
+
+	/* new_pool */
+	ceph_decode_32_safe(p, end, len, bad);
+	while (len--) {
+		__u8 ev;
+		struct ceph_pg_pool_info *pi;
+
+		ceph_decode_32_safe(p, end, pool, bad);
+		ceph_decode_need(p, end, 1 + sizeof(pi->v), bad);
+		ev = ceph_decode_8(p);  /* encoding version */
+		if (ev > CEPH_PG_POOL_VERSION) {
+			pr_warning("got unknown v %d > %d of ceph_pg_pool\n",
+				   ev, CEPH_PG_POOL_VERSION);
+			goto bad;
+		}
+		pi = __lookup_pg_pool(&map->pg_pools, pool);
+		if (!pi) {
+			pi = kzalloc(sizeof(*pi), GFP_NOFS);
+			if (!pi) {
+				err = -ENOMEM;
+				goto bad;
+			}
+			pi->id = pool;
+			__insert_pg_pool(&map->pg_pools, pi);
+		}
+		err = __decode_pool(p, end, pi);
+		if (err < 0)
+			goto bad;
+	}
+	if (version >= 5 && __decode_pool_names(p, end, map) < 0)
+		goto bad;
+
+	/* old_pool */
+	ceph_decode_32_safe(p, end, len, bad);
+	while (len--) {
+		struct ceph_pg_pool_info *pi;
+
+		ceph_decode_32_safe(p, end, pool, bad);
+		pi = __lookup_pg_pool(&map->pg_pools, pool);
+		if (pi)
+			__remove_pg_pool(&map->pg_pools, pi);
+	}
+
+	/* new_up */
+	err = -EINVAL;
+	ceph_decode_32_safe(p, end, len, bad);
+	while (len--) {
+		u32 osd;
+		struct ceph_entity_addr addr;
+		ceph_decode_32_safe(p, end, osd, bad);
+		ceph_decode_copy_safe(p, end, &addr, sizeof(addr), bad);
+		ceph_decode_addr(&addr);
+		pr_info("osd%d up\n", osd);
+		BUG_ON(osd >= map->max_osd);
+		map->osd_state[osd] |= CEPH_OSD_UP;
+		map->osd_addr[osd] = addr;
+	}
+
+	/* new_down */
+	ceph_decode_32_safe(p, end, len, bad);
+	while (len--) {
+		u32 osd;
+		ceph_decode_32_safe(p, end, osd, bad);
+		(*p)++;  /* clean flag */
+		pr_info("osd%d down\n", osd);
+		if (osd < map->max_osd)
+			map->osd_state[osd] &= ~CEPH_OSD_UP;
+	}
+
+	/* new_weight */
+	ceph_decode_32_safe(p, end, len, bad);
+	while (len--) {
+		u32 osd, off;
+		ceph_decode_need(p, end, sizeof(u32)*2, bad);
+		osd = ceph_decode_32(p);
+		off = ceph_decode_32(p);
+		pr_info("osd%d weight 0x%x %s\n", osd, off,
+		     off == CEPH_OSD_IN ? "(in)" :
+		     (off == CEPH_OSD_OUT ? "(out)" : ""));
+		if (osd < map->max_osd)
+			map->osd_weight[osd] = off;
+	}
+
+	/* new_pg_temp */
+	rbp = rb_first(&map->pg_temp);
+	ceph_decode_32_safe(p, end, len, bad);
+	while (len--) {
+		struct ceph_pg_mapping *pg;
+		int j;
+		struct ceph_pg pgid;
+		u32 pglen;
+		ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad);
+		ceph_decode_copy(p, &pgid, sizeof(pgid));
+		pglen = ceph_decode_32(p);
+
+		/* remove any? */
+		while (rbp && pgid_cmp(rb_entry(rbp, struct ceph_pg_mapping,
+						node)->pgid, pgid) <= 0) {
+			struct ceph_pg_mapping *cur =
+				rb_entry(rbp, struct ceph_pg_mapping, node);
+
+			rbp = rb_next(rbp);
+			dout(" removed pg_temp %llx\n", *(u64 *)&cur->pgid);
+			rb_erase(&cur->node, &map->pg_temp);
+			kfree(cur);
+		}
+
+		if (pglen) {
+			/* insert */
+			ceph_decode_need(p, end, pglen*sizeof(u32), bad);
+			pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS);
+			if (!pg) {
+				err = -ENOMEM;
+				goto bad;
+			}
+			pg->pgid = pgid;
+			pg->len = pglen;
+			for (j = 0; j < pglen; j++)
+				pg->osds[j] = ceph_decode_32(p);
+			err = __insert_pg_mapping(pg, &map->pg_temp);
+			if (err) {
+				kfree(pg);
+				goto bad;
+			}
+			dout(" added pg_temp %llx len %d\n", *(u64 *)&pgid,
+			     pglen);
+		}
+	}
+	while (rbp) {
+		struct ceph_pg_mapping *cur =
+			rb_entry(rbp, struct ceph_pg_mapping, node);
+
+		rbp = rb_next(rbp);
+		dout(" removed pg_temp %llx\n", *(u64 *)&cur->pgid);
+		rb_erase(&cur->node, &map->pg_temp);
+		kfree(cur);
+	}
+
+	/* ignore the rest */
+	*p = end;
+	return map;
+
+bad:
+	pr_err("corrupt inc osdmap epoch %d off %d (%p of %p-%p)\n",
+	       epoch, (int)(*p - start), *p, start, end);
+	print_hex_dump(KERN_DEBUG, "osdmap: ",
+		       DUMP_PREFIX_OFFSET, 16, 1,
+		       start, end - start, true);
+	if (newcrush)
+		crush_destroy(newcrush);
+	return ERR_PTR(err);
+}
+
+
+
+
+/*
+ * calculate file layout from given offset, length.
+ * fill in correct oid, logical length, and object extent
+ * offset, length.
+ *
+ * for now, we write only a single su, until we can
+ * pass a stride back to the caller.
+ */
+void ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
+				   u64 off, u64 *plen,
+				   u64 *ono,
+				   u64 *oxoff, u64 *oxlen)
+{
+	u32 osize = le32_to_cpu(layout->fl_object_size);
+	u32 su = le32_to_cpu(layout->fl_stripe_unit);
+	u32 sc = le32_to_cpu(layout->fl_stripe_count);
+	u32 bl, stripeno, stripepos, objsetno;
+	u32 su_per_object;
+	u64 t, su_offset;
+
+	dout("mapping %llu~%llu  osize %u fl_su %u\n", off, *plen,
+	     osize, su);
+	su_per_object = osize / su;
+	dout("osize %u / su %u = su_per_object %u\n", osize, su,
+	     su_per_object);
+
+	BUG_ON((su & ~PAGE_MASK) != 0);
+	/* bl = *off / su; */
+	t = off;
+	do_div(t, su);
+	bl = t;
+	dout("off %llu / su %u = bl %u\n", off, su, bl);
+
+	stripeno = bl / sc;
+	stripepos = bl % sc;
+	objsetno = stripeno / su_per_object;
+
+	*ono = objsetno * sc + stripepos;
+	dout("objset %u * sc %u = ono %u\n", objsetno, sc, (unsigned)*ono);
+
+	/* *oxoff = *off % layout->fl_stripe_unit;  # offset in su */
+	t = off;
+	su_offset = do_div(t, su);
+	*oxoff = su_offset + (stripeno % su_per_object) * su;
+
+	/*
+	 * Calculate the length of the extent being written to the selected
+	 * object. This is the minimum of the full length requested (plen) or
+	 * the remainder of the current stripe being written to.
+	 */
+	*oxlen = min_t(u64, *plen, su - su_offset);
+	*plen = *oxlen;
+
+	dout(" obj extent %llu~%llu\n", *oxoff, *oxlen);
+}
+EXPORT_SYMBOL(ceph_calc_file_object_mapping);
+
+/*
+ * calculate an object layout (i.e. pgid) from an oid,
+ * file_layout, and osdmap
+ */
+int ceph_calc_object_layout(struct ceph_object_layout *ol,
+			    const char *oid,
+			    struct ceph_file_layout *fl,
+			    struct ceph_osdmap *osdmap)
+{
+	unsigned num, num_mask;
+	struct ceph_pg pgid;
+	s32 preferred = (s32)le32_to_cpu(fl->fl_pg_preferred);
+	int poolid = le32_to_cpu(fl->fl_pg_pool);
+	struct ceph_pg_pool_info *pool;
+	unsigned ps;
+
+	BUG_ON(!osdmap);
+
+	pool = __lookup_pg_pool(&osdmap->pg_pools, poolid);
+	if (!pool)
+		return -EIO;
+	ps = ceph_str_hash(pool->v.object_hash, oid, strlen(oid));
+	if (preferred >= 0) {
+		ps += preferred;
+		num = le32_to_cpu(pool->v.lpg_num);
+		num_mask = pool->lpg_num_mask;
+	} else {
+		num = le32_to_cpu(pool->v.pg_num);
+		num_mask = pool->pg_num_mask;
+	}
+
+	pgid.ps = cpu_to_le16(ps);
+	pgid.preferred = cpu_to_le16(preferred);
+	pgid.pool = fl->fl_pg_pool;
+	if (preferred >= 0)
+		dout("calc_object_layout '%s' pgid %d.%xp%d\n", oid, poolid, ps,
+		     (int)preferred);
+	else
+		dout("calc_object_layout '%s' pgid %d.%x\n", oid, poolid, ps);
+
+	ol->ol_pgid = pgid;
+	ol->ol_stripe_unit = fl->fl_object_stripe_unit;
+	return 0;
+}
+EXPORT_SYMBOL(ceph_calc_object_layout);
+
+/*
+ * Calculate raw osd vector for the given pgid.  Return pointer to osd
+ * array, or NULL on failure.
+ */
+static int *calc_pg_raw(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
+			int *osds, int *num)
+{
+	struct ceph_pg_mapping *pg;
+	struct ceph_pg_pool_info *pool;
+	int ruleno;
+	unsigned poolid, ps, pps;
+	int preferred;
+
+	/* pg_temp? */
+	pg = __lookup_pg_mapping(&osdmap->pg_temp, pgid);
+	if (pg) {
+		*num = pg->len;
+		return pg->osds;
+	}
+
+	/* crush */
+	poolid = le32_to_cpu(pgid.pool);
+	ps = le16_to_cpu(pgid.ps);
+	preferred = (s16)le16_to_cpu(pgid.preferred);
+
+	/* don't forcefeed bad device ids to crush */
+	if (preferred >= osdmap->max_osd ||
+	    preferred >= osdmap->crush->max_devices)
+		preferred = -1;
+
+	pool = __lookup_pg_pool(&osdmap->pg_pools, poolid);
+	if (!pool)
+		return NULL;
+	ruleno = crush_find_rule(osdmap->crush, pool->v.crush_ruleset,
+				 pool->v.type, pool->v.size);
+	if (ruleno < 0) {
+		pr_err("no crush rule pool %d ruleset %d type %d size %d\n",
+		       poolid, pool->v.crush_ruleset, pool->v.type,
+		       pool->v.size);
+		return NULL;
+	}
+
+	if (preferred >= 0)
+		pps = ceph_stable_mod(ps,
+				      le32_to_cpu(pool->v.lpgp_num),
+				      pool->lpgp_num_mask);
+	else
+		pps = ceph_stable_mod(ps,
+				      le32_to_cpu(pool->v.pgp_num),
+				      pool->pgp_num_mask);
+	pps += poolid;
+	*num = crush_do_rule(osdmap->crush, ruleno, pps, osds,
+			     min_t(int, pool->v.size, *num),
+			     preferred, osdmap->osd_weight);
+	return osds;
+}
+
+/*
+ * Return acting set for given pgid.
+ */
+int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
+			int *acting)
+{
+	int rawosds[CEPH_PG_MAX_SIZE], *osds;
+	int i, o, num = CEPH_PG_MAX_SIZE;
+
+	osds = calc_pg_raw(osdmap, pgid, rawosds, &num);
+	if (!osds)
+		return -1;
+
+	/* primary is first up osd */
+	o = 0;
+	for (i = 0; i < num; i++)
+		if (ceph_osd_is_up(osdmap, osds[i]))
+			acting[o++] = osds[i];
+	return o;
+}
+
+/*
+ * Return primary osd for given pgid, or -1 if none.
+ */
+int ceph_calc_pg_primary(struct ceph_osdmap *osdmap, struct ceph_pg pgid)
+{
+	int rawosds[CEPH_PG_MAX_SIZE], *osds;
+	int i, num = CEPH_PG_MAX_SIZE;
+
+	osds = calc_pg_raw(osdmap, pgid, rawosds, &num);
+	if (!osds)
+		return -1;
+
+	/* primary is first up osd */
+	for (i = 0; i < num; i++)
+		if (ceph_osd_is_up(osdmap, osds[i]))
+			return osds[i];
+	return -1;
+}
+EXPORT_SYMBOL(ceph_calc_pg_primary);
diff --git a/net/ceph/pagelist.c b/net/ceph/pagelist.c
new file mode 100644
index 0000000..13cb409
--- /dev/null
+++ b/net/ceph/pagelist.c
@@ -0,0 +1,154 @@
+
+#include <linux/module.h>
+#include <linux/gfp.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/ceph/pagelist.h>
+
+static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl)
+{
+	if (pl->mapped_tail) {
+		struct page *page = list_entry(pl->head.prev, struct page, lru);
+		kunmap(page);
+		pl->mapped_tail = NULL;
+	}
+}
+
+int ceph_pagelist_release(struct ceph_pagelist *pl)
+{
+	ceph_pagelist_unmap_tail(pl);
+	while (!list_empty(&pl->head)) {
+		struct page *page = list_first_entry(&pl->head, struct page,
+						     lru);
+		list_del(&page->lru);
+		__free_page(page);
+	}
+	ceph_pagelist_free_reserve(pl);
+	return 0;
+}
+EXPORT_SYMBOL(ceph_pagelist_release);
+
+static int ceph_pagelist_addpage(struct ceph_pagelist *pl)
+{
+	struct page *page;
+
+	if (!pl->num_pages_free) {
+		page = __page_cache_alloc(GFP_NOFS);
+	} else {
+		page = list_first_entry(&pl->free_list, struct page, lru);
+		list_del(&page->lru);
+		--pl->num_pages_free;
+	}
+	if (!page)
+		return -ENOMEM;
+	pl->room += PAGE_SIZE;
+	ceph_pagelist_unmap_tail(pl);
+	list_add_tail(&page->lru, &pl->head);
+	pl->mapped_tail = kmap(page);
+	return 0;
+}
+
+int ceph_pagelist_append(struct ceph_pagelist *pl, const void *buf, size_t len)
+{
+	while (pl->room < len) {
+		size_t bit = pl->room;
+		int ret;
+
+		memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK),
+		       buf, bit);
+		pl->length += bit;
+		pl->room -= bit;
+		buf += bit;
+		len -= bit;
+		ret = ceph_pagelist_addpage(pl);
+		if (ret)
+			return ret;
+	}
+
+	memcpy(pl->mapped_tail + (pl->length & ~PAGE_CACHE_MASK), buf, len);
+	pl->length += len;
+	pl->room -= len;
+	return 0;
+}
+EXPORT_SYMBOL(ceph_pagelist_append);
+
+/**
+ * Allocate enough pages for a pagelist to append the given amount
+ * of data without without allocating.
+ * Returns: 0 on success, -ENOMEM on error.
+ */
+int ceph_pagelist_reserve(struct ceph_pagelist *pl, size_t space)
+{
+	if (space <= pl->room)
+		return 0;
+	space -= pl->room;
+	space = (space + PAGE_SIZE - 1) >> PAGE_SHIFT;   /* conv to num pages */
+
+	while (space > pl->num_pages_free) {
+		struct page *page = __page_cache_alloc(GFP_NOFS);
+		if (!page)
+			return -ENOMEM;
+		list_add_tail(&page->lru, &pl->free_list);
+		++pl->num_pages_free;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(ceph_pagelist_reserve);
+
+/**
+ * Free any pages that have been preallocated.
+ */
+int ceph_pagelist_free_reserve(struct ceph_pagelist *pl)
+{
+	while (!list_empty(&pl->free_list)) {
+		struct page *page = list_first_entry(&pl->free_list,
+						     struct page, lru);
+		list_del(&page->lru);
+		__free_page(page);
+		--pl->num_pages_free;
+	}
+	BUG_ON(pl->num_pages_free);
+	return 0;
+}
+EXPORT_SYMBOL(ceph_pagelist_free_reserve);
+
+/**
+ * Create a truncation point.
+ */
+void ceph_pagelist_set_cursor(struct ceph_pagelist *pl,
+			      struct ceph_pagelist_cursor *c)
+{
+	c->pl = pl;
+	c->page_lru = pl->head.prev;
+	c->room = pl->room;
+}
+EXPORT_SYMBOL(ceph_pagelist_set_cursor);
+
+/**
+ * Truncate a pagelist to the given point. Move extra pages to reserve.
+ * This won't sleep.
+ * Returns: 0 on success,
+ *          -EINVAL if the pagelist doesn't match the trunc point pagelist
+ */
+int ceph_pagelist_truncate(struct ceph_pagelist *pl,
+			   struct ceph_pagelist_cursor *c)
+{
+	struct page *page;
+
+	if (pl != c->pl)
+		return -EINVAL;
+	ceph_pagelist_unmap_tail(pl);
+	while (pl->head.prev != c->page_lru) {
+		page = list_entry(pl->head.prev, struct page, lru);
+		list_del(&page->lru);                /* remove from pagelist */
+		list_add_tail(&page->lru, &pl->free_list); /* add to reserve */
+		++pl->num_pages_free;
+	}
+	pl->room = c->room;
+	if (!list_empty(&pl->head)) {
+		page = list_entry(pl->head.prev, struct page, lru);
+		pl->mapped_tail = kmap(page);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(ceph_pagelist_truncate);
diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c
new file mode 100644
index 0000000..54caf06
--- /dev/null
+++ b/net/ceph/pagevec.c
@@ -0,0 +1,223 @@
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/namei.h>
+#include <linux/writeback.h>
+
+#include <linux/ceph/libceph.h>
+
+/*
+ * build a vector of user pages
+ */
+struct page **ceph_get_direct_page_vector(const char __user *data,
+						 int num_pages,
+						 loff_t off, size_t len)
+{
+	struct page **pages;
+	int rc;
+
+	pages = kmalloc(sizeof(*pages) * num_pages, GFP_NOFS);
+	if (!pages)
+		return ERR_PTR(-ENOMEM);
+
+	down_read(&current->mm->mmap_sem);
+	rc = get_user_pages(current, current->mm, (unsigned long)data,
+			    num_pages, 0, 0, pages, NULL);
+	up_read(&current->mm->mmap_sem);
+	if (rc < 0)
+		goto fail;
+	return pages;
+
+fail:
+	kfree(pages);
+	return ERR_PTR(rc);
+}
+EXPORT_SYMBOL(ceph_get_direct_page_vector);
+
+void ceph_put_page_vector(struct page **pages, int num_pages)
+{
+	int i;
+
+	for (i = 0; i < num_pages; i++)
+		put_page(pages[i]);
+	kfree(pages);
+}
+EXPORT_SYMBOL(ceph_put_page_vector);
+
+void ceph_release_page_vector(struct page **pages, int num_pages)
+{
+	int i;
+
+	for (i = 0; i < num_pages; i++)
+		__free_pages(pages[i], 0);
+	kfree(pages);
+}
+EXPORT_SYMBOL(ceph_release_page_vector);
+
+/*
+ * allocate a vector new pages
+ */
+struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags)
+{
+	struct page **pages;
+	int i;
+
+	pages = kmalloc(sizeof(*pages) * num_pages, flags);
+	if (!pages)
+		return ERR_PTR(-ENOMEM);
+	for (i = 0; i < num_pages; i++) {
+		pages[i] = __page_cache_alloc(flags);
+		if (pages[i] == NULL) {
+			ceph_release_page_vector(pages, i);
+			return ERR_PTR(-ENOMEM);
+		}
+	}
+	return pages;
+}
+EXPORT_SYMBOL(ceph_alloc_page_vector);
+
+/*
+ * copy user data into a page vector
+ */
+int ceph_copy_user_to_page_vector(struct page **pages,
+					 const char __user *data,
+					 loff_t off, size_t len)
+{
+	int i = 0;
+	int po = off & ~PAGE_CACHE_MASK;
+	int left = len;
+	int l, bad;
+
+	while (left > 0) {
+		l = min_t(int, PAGE_CACHE_SIZE-po, left);
+		bad = copy_from_user(page_address(pages[i]) + po, data, l);
+		if (bad == l)
+			return -EFAULT;
+		data += l - bad;
+		left -= l - bad;
+		po += l - bad;
+		if (po == PAGE_CACHE_SIZE) {
+			po = 0;
+			i++;
+		}
+	}
+	return len;
+}
+EXPORT_SYMBOL(ceph_copy_user_to_page_vector);
+
+int ceph_copy_to_page_vector(struct page **pages,
+				    const char *data,
+				    loff_t off, size_t len)
+{
+	int i = 0;
+	size_t po = off & ~PAGE_CACHE_MASK;
+	size_t left = len;
+	size_t l;
+
+	while (left > 0) {
+		l = min_t(size_t, PAGE_CACHE_SIZE-po, left);
+		memcpy(page_address(pages[i]) + po, data, l);
+		data += l;
+		left -= l;
+		po += l;
+		if (po == PAGE_CACHE_SIZE) {
+			po = 0;
+			i++;
+		}
+	}
+	return len;
+}
+EXPORT_SYMBOL(ceph_copy_to_page_vector);
+
+int ceph_copy_from_page_vector(struct page **pages,
+				    char *data,
+				    loff_t off, size_t len)
+{
+	int i = 0;
+	size_t po = off & ~PAGE_CACHE_MASK;
+	size_t left = len;
+	size_t l;
+
+	while (left > 0) {
+		l = min_t(size_t, PAGE_CACHE_SIZE-po, left);
+		memcpy(data, page_address(pages[i]) + po, l);
+		data += l;
+		left -= l;
+		po += l;
+		if (po == PAGE_CACHE_SIZE) {
+			po = 0;
+			i++;
+		}
+	}
+	return len;
+}
+EXPORT_SYMBOL(ceph_copy_from_page_vector);
+
+/*
+ * copy user data from a page vector into a user pointer
+ */
+int ceph_copy_page_vector_to_user(struct page **pages,
+					 char __user *data,
+					 loff_t off, size_t len)
+{
+	int i = 0;
+	int po = off & ~PAGE_CACHE_MASK;
+	int left = len;
+	int l, bad;
+
+	while (left > 0) {
+		l = min_t(int, left, PAGE_CACHE_SIZE-po);
+		bad = copy_to_user(data, page_address(pages[i]) + po, l);
+		if (bad == l)
+			return -EFAULT;
+		data += l - bad;
+		left -= l - bad;
+		if (po) {
+			po += l - bad;
+			if (po == PAGE_CACHE_SIZE)
+				po = 0;
+		}
+		i++;
+	}
+	return len;
+}
+EXPORT_SYMBOL(ceph_copy_page_vector_to_user);
+
+/*
+ * Zero an extent within a page vector.  Offset is relative to the
+ * start of the first page.
+ */
+void ceph_zero_page_vector_range(int off, int len, struct page **pages)
+{
+	int i = off >> PAGE_CACHE_SHIFT;
+
+	off &= ~PAGE_CACHE_MASK;
+
+	dout("zero_page_vector_page %u~%u\n", off, len);
+
+	/* leading partial page? */
+	if (off) {
+		int end = min((int)PAGE_CACHE_SIZE, off + len);
+		dout("zeroing %d %p head from %d\n", i, pages[i],
+		     (int)off);
+		zero_user_segment(pages[i], off, end);
+		len -= (end - off);
+		i++;
+	}
+	while (len >= PAGE_CACHE_SIZE) {
+		dout("zeroing %d %p len=%d\n", i, pages[i], len);
+		zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE);
+		len -= PAGE_CACHE_SIZE;
+		i++;
+	}
+	/* trailing partial page? */
+	if (len) {
+		dout("zeroing %d %p tail to %d\n", i, pages[i], (int)len);
+		zero_user_segment(pages[i], 0, len);
+	}
+}
+EXPORT_SYMBOL(ceph_zero_page_vector_range);
+
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 251997a..cd1e039 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -243,6 +243,7 @@
 	unlock_sock_fast(sk, slow);
 
 	/* skb is now orphaned, can be freed outside of locked section */
+	trace_kfree_skb(skb, skb_free_datagram_locked);
 	__kfree_skb(skb);
 }
 EXPORT_SYMBOL(skb_free_datagram_locked);
@@ -746,13 +747,12 @@
 	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
 		mask |= POLLERR;
 	if (sk->sk_shutdown & RCV_SHUTDOWN)
-		mask |= POLLRDHUP;
+		mask |= POLLRDHUP | POLLIN | POLLRDNORM;
 	if (sk->sk_shutdown == SHUTDOWN_MASK)
 		mask |= POLLHUP;
 
 	/* readable? */
-	if (!skb_queue_empty(&sk->sk_receive_queue) ||
-	    (sk->sk_shutdown & RCV_SHUTDOWN))
+	if (!skb_queue_empty(&sk->sk_receive_queue))
 		mask |= POLLIN | POLLRDNORM;
 
 	/* Connection-based need to check for termination and startup */
diff --git a/net/core/dev.c b/net/core/dev.c
index 660dd41..78b5a89 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -128,7 +128,10 @@
 #include <linux/jhash.h>
 #include <linux/random.h>
 #include <trace/events/napi.h>
+#include <trace/events/net.h>
+#include <trace/events/skb.h>
 #include <linux/pci.h>
+#include <linux/inetdevice.h>
 
 #include "net-sysfs.h"
 
@@ -371,6 +374,14 @@
  *							--ANK (980803)
  */
 
+static inline struct list_head *ptype_head(const struct packet_type *pt)
+{
+	if (pt->type == htons(ETH_P_ALL))
+		return &ptype_all;
+	else
+		return &ptype_base[ntohs(pt->type) & PTYPE_HASH_MASK];
+}
+
 /**
  *	dev_add_pack - add packet handler
  *	@pt: packet type declaration
@@ -386,16 +397,11 @@
 
 void dev_add_pack(struct packet_type *pt)
 {
-	int hash;
+	struct list_head *head = ptype_head(pt);
 
-	spin_lock_bh(&ptype_lock);
-	if (pt->type == htons(ETH_P_ALL))
-		list_add_rcu(&pt->list, &ptype_all);
-	else {
-		hash = ntohs(pt->type) & PTYPE_HASH_MASK;
-		list_add_rcu(&pt->list, &ptype_base[hash]);
-	}
-	spin_unlock_bh(&ptype_lock);
+	spin_lock(&ptype_lock);
+	list_add_rcu(&pt->list, head);
+	spin_unlock(&ptype_lock);
 }
 EXPORT_SYMBOL(dev_add_pack);
 
@@ -414,15 +420,10 @@
  */
 void __dev_remove_pack(struct packet_type *pt)
 {
-	struct list_head *head;
+	struct list_head *head = ptype_head(pt);
 	struct packet_type *pt1;
 
-	spin_lock_bh(&ptype_lock);
-
-	if (pt->type == htons(ETH_P_ALL))
-		head = &ptype_all;
-	else
-		head = &ptype_base[ntohs(pt->type) & PTYPE_HASH_MASK];
+	spin_lock(&ptype_lock);
 
 	list_for_each_entry(pt1, head, list) {
 		if (pt == pt1) {
@@ -433,7 +434,7 @@
 
 	printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt);
 out:
-	spin_unlock_bh(&ptype_lock);
+	spin_unlock(&ptype_lock);
 }
 EXPORT_SYMBOL(__dev_remove_pack);
 
@@ -1484,8 +1485,9 @@
 	skb_orphan(skb);
 	nf_reset(skb);
 
-	if (!(dev->flags & IFF_UP) ||
-	    (skb->len > (dev->mtu + dev->hard_header_len))) {
+	if (unlikely(!(dev->flags & IFF_UP) ||
+		     (skb->len > (dev->mtu + dev->hard_header_len + VLAN_HLEN)))) {
+		atomic_long_inc(&dev->rx_dropped);
 		kfree_skb(skb);
 		return NET_RX_DROP;
 	}
@@ -1553,21 +1555,56 @@
  * 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.
  */
-void netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
+int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
 {
-	unsigned int real_num = dev->real_num_tx_queues;
+	if (txq < 1 || txq > dev->num_tx_queues)
+		return -EINVAL;
 
-	if (unlikely(txq > dev->num_tx_queues))
-		;
-	else if (txq > real_num)
-		dev->real_num_tx_queues = txq;
-	else if (txq < real_num) {
-		dev->real_num_tx_queues = txq;
-		qdisc_reset_all_tx_gt(dev, txq);
+	if (dev->reg_state == NETREG_REGISTERED) {
+		ASSERT_RTNL();
+
+		if (txq < dev->real_num_tx_queues)
+			qdisc_reset_all_tx_gt(dev, txq);
 	}
+
+	dev->real_num_tx_queues = txq;
+	return 0;
 }
 EXPORT_SYMBOL(netif_set_real_num_tx_queues);
 
+#ifdef CONFIG_RPS
+/**
+ *	netif_set_real_num_rx_queues - set actual number of RX queues used
+ *	@dev: Network device
+ *	@rxq: Actual number of RX queues
+ *
+ *	This must be called either with the rtnl_lock held or before
+ *	registration of the net device.  Returns 0 on success, or a
+ *	negative error code.  If called before registration, it always
+ *	succeeds.
+ */
+int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq)
+{
+	int rc;
+
+	if (rxq < 1 || rxq > dev->num_rx_queues)
+		return -EINVAL;
+
+	if (dev->reg_state == NETREG_REGISTERED) {
+		ASSERT_RTNL();
+
+		rc = net_rx_queue_update_kobjects(dev, dev->real_num_rx_queues,
+						  rxq);
+		if (rc)
+			return rc;
+	}
+
+	dev->real_num_rx_queues = rxq;
+	return 0;
+}
+EXPORT_SYMBOL(netif_set_real_num_rx_queues);
+#endif
+
 static inline void __netif_reschedule(struct Qdisc *q)
 {
 	struct softnet_data *sd;
@@ -1659,7 +1696,12 @@
 
 static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb)
 {
-	if (can_checksum_protocol(dev->features, skb->protocol))
+	int features = dev->features;
+
+	if (vlan_tx_tag_present(skb))
+		features &= dev->vlan_features;
+
+	if (can_checksum_protocol(features, skb->protocol))
 		return true;
 
 	if (skb->protocol == htons(ETH_P_8021Q)) {
@@ -1758,6 +1800,16 @@
 	__be16 type = skb->protocol;
 	int err;
 
+	if (type == htons(ETH_P_8021Q)) {
+		struct vlan_ethhdr *veh;
+
+		if (unlikely(!pskb_may_pull(skb, VLAN_ETH_HLEN)))
+			return ERR_PTR(-EINVAL);
+
+		veh = (struct vlan_ethhdr *)skb->data;
+		type = veh->h_vlan_encapsulated_proto;
+	}
+
 	skb_reset_mac_header(skb);
 	skb->mac_len = skb->network_header - skb->mac_header;
 	__skb_pull(skb, skb->mac_len);
@@ -1902,14 +1954,14 @@
 
 /*
  * Try to orphan skb early, right before transmission by the device.
- * We cannot orphan skb if tx timestamp is requested, since
- * drivers need to call skb_tstamp_tx() to send the timestamp.
+ * We cannot orphan skb if tx timestamp is requested or the sk-reference
+ * is needed on driver level for other reasons, e.g. see net/can/raw.c
  */
 static inline void skb_orphan_try(struct sk_buff *skb)
 {
 	struct sock *sk = skb->sk;
 
-	if (sk && !skb_tx(skb)->flags) {
+	if (sk && !skb_shinfo(skb)->tx_flags) {
 		/* skb_tx_hash() wont be able to get sk.
 		 * We copy sk_hash into skb->rxhash
 		 */
@@ -1929,9 +1981,14 @@
 static inline int skb_needs_linearize(struct sk_buff *skb,
 				      struct net_device *dev)
 {
+	int features = dev->features;
+
+	if (skb->protocol == htons(ETH_P_8021Q) || vlan_tx_tag_present(skb))
+		features &= dev->vlan_features;
+
 	return skb_is_nonlinear(skb) &&
-	       ((skb_has_frags(skb) && !(dev->features & NETIF_F_FRAGLIST)) ||
-	        (skb_shinfo(skb)->nr_frags && (!(dev->features & NETIF_F_SG) ||
+	       ((skb_has_frag_list(skb) && !(features & NETIF_F_FRAGLIST)) ||
+		(skb_shinfo(skb)->nr_frags && (!(features & NETIF_F_SG) ||
 					      illegal_highdma(dev, skb))));
 }
 
@@ -1954,6 +2011,15 @@
 
 		skb_orphan_try(skb);
 
+		if (vlan_tx_tag_present(skb) &&
+		    !(dev->features & NETIF_F_HW_VLAN_TX)) {
+			skb = __vlan_put_tag(skb, vlan_tx_tag_get(skb));
+			if (unlikely(!skb))
+				goto out;
+
+			skb->vlan_tci = 0;
+		}
+
 		if (netif_needs_gso(dev, skb)) {
 			if (unlikely(dev_gso_segment(skb)))
 				goto out_kfree_skb;
@@ -1978,6 +2044,7 @@
 		}
 
 		rc = ops->ndo_start_xmit(skb, dev);
+		trace_net_dev_xmit(skb, rc);
 		if (rc == NETDEV_TX_OK)
 			txq_trans_update(txq);
 		return rc;
@@ -1998,6 +2065,7 @@
 			skb_dst_drop(nskb);
 
 		rc = ops->ndo_start_xmit(nskb, dev);
+		trace_net_dev_xmit(nskb, rc);
 		if (unlikely(rc != NETDEV_TX_OK)) {
 			if (rc & ~NETDEV_TX_MASK)
 				goto out_kfree_gso_skb;
@@ -2015,6 +2083,7 @@
 		skb->destructor = DEV_GSO_CB(skb)->destructor;
 out_kfree_skb:
 	kfree_skb(skb);
+out:
 	return rc;
 }
 
@@ -2143,6 +2212,9 @@
 	return rc;
 }
 
+static DEFINE_PER_CPU(int, xmit_recursion);
+#define RECURSION_LIMIT 3
+
 /**
  *	dev_queue_xmit - transmit a buffer
  *	@skb: buffer to transmit
@@ -2186,6 +2258,7 @@
 #ifdef CONFIG_NET_CLS_ACT
 	skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
 #endif
+	trace_net_dev_queue(skb);
 	if (q->enqueue) {
 		rc = __dev_xmit_skb(skb, q, dev, txq);
 		goto out;
@@ -2208,10 +2281,15 @@
 
 		if (txq->xmit_lock_owner != cpu) {
 
+			if (__this_cpu_read(xmit_recursion) > RECURSION_LIMIT)
+				goto recursion_alert;
+
 			HARD_TX_LOCK(dev, txq, cpu);
 
 			if (!netif_tx_queue_stopped(txq)) {
+				__this_cpu_inc(xmit_recursion);
 				rc = dev_hard_start_xmit(skb, dev, txq);
+				__this_cpu_dec(xmit_recursion);
 				if (dev_xmit_complete(rc)) {
 					HARD_TX_UNLOCK(dev, txq);
 					goto out;
@@ -2223,7 +2301,9 @@
 				       "queue packet!\n", dev->name);
 		} else {
 			/* Recursion is detected! It is possible,
-			 * unfortunately */
+			 * unfortunately
+			 */
+recursion_alert:
 			if (net_ratelimit())
 				printk(KERN_CRIT "Dead loop on virtual device "
 				       "%s, fix it urgently!\n", dev->name);
@@ -2259,6 +2339,77 @@
 	__raise_softirq_irqoff(NET_RX_SOFTIRQ);
 }
 
+/*
+ * __skb_get_rxhash: calculate a flow hash based on src/dst addresses
+ * and src/dst port numbers. Returns a non-zero hash number on success
+ * and 0 on failure.
+ */
+__u32 __skb_get_rxhash(struct sk_buff *skb)
+{
+	int nhoff, hash = 0, poff;
+	struct ipv6hdr *ip6;
+	struct iphdr *ip;
+	u8 ip_proto;
+	u32 addr1, addr2, ihl;
+	union {
+		u32 v32;
+		u16 v16[2];
+	} ports;
+
+	nhoff = skb_network_offset(skb);
+
+	switch (skb->protocol) {
+	case __constant_htons(ETH_P_IP):
+		if (!pskb_may_pull(skb, sizeof(*ip) + nhoff))
+			goto done;
+
+		ip = (struct iphdr *) (skb->data + nhoff);
+		if (ip->frag_off & htons(IP_MF | IP_OFFSET))
+			ip_proto = 0;
+		else
+			ip_proto = ip->protocol;
+		addr1 = (__force u32) ip->saddr;
+		addr2 = (__force u32) ip->daddr;
+		ihl = ip->ihl;
+		break;
+	case __constant_htons(ETH_P_IPV6):
+		if (!pskb_may_pull(skb, sizeof(*ip6) + nhoff))
+			goto done;
+
+		ip6 = (struct ipv6hdr *) (skb->data + nhoff);
+		ip_proto = ip6->nexthdr;
+		addr1 = (__force u32) ip6->saddr.s6_addr32[3];
+		addr2 = (__force u32) ip6->daddr.s6_addr32[3];
+		ihl = (40 >> 2);
+		break;
+	default:
+		goto done;
+	}
+
+	ports.v32 = 0;
+	poff = proto_ports_offset(ip_proto);
+	if (poff >= 0) {
+		nhoff += ihl * 4 + poff;
+		if (pskb_may_pull(skb, nhoff + 4)) {
+			ports.v32 = * (__force u32 *) (skb->data + nhoff);
+			if (ports.v16[1] < ports.v16[0])
+				swap(ports.v16[0], ports.v16[1]);
+		}
+	}
+
+	/* get a consistent hash (same value on both flow directions) */
+	if (addr2 < addr1)
+		swap(addr1, addr2);
+
+	hash = jhash_3words(addr1, addr2, ports.v32, hashrnd);
+	if (!hash)
+		hash = 1;
+
+done:
+	return hash;
+}
+EXPORT_SYMBOL(__skb_get_rxhash);
+
 #ifdef CONFIG_RPS
 
 /* One global table that all flow-based protocols share. */
@@ -2273,90 +2424,42 @@
 static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
 		       struct rps_dev_flow **rflowp)
 {
-	struct ipv6hdr *ip6;
-	struct iphdr *ip;
 	struct netdev_rx_queue *rxqueue;
-	struct rps_map *map;
+	struct rps_map *map = NULL;
 	struct rps_dev_flow_table *flow_table;
 	struct rps_sock_flow_table *sock_flow_table;
 	int cpu = -1;
-	u8 ip_proto;
 	u16 tcpu;
-	u32 addr1, addr2, ihl;
-	union {
-		u32 v32;
-		u16 v16[2];
-	} ports;
 
 	if (skb_rx_queue_recorded(skb)) {
 		u16 index = skb_get_rx_queue(skb);
-		if (unlikely(index >= dev->num_rx_queues)) {
-			WARN_ONCE(dev->num_rx_queues > 1, "%s received packet "
-				"on queue %u, but number of RX queues is %u\n",
-				dev->name, index, dev->num_rx_queues);
+		if (unlikely(index >= dev->real_num_rx_queues)) {
+			WARN_ONCE(dev->real_num_rx_queues > 1,
+				  "%s received packet on queue %u, but number "
+				  "of RX queues is %u\n",
+				  dev->name, index, dev->real_num_rx_queues);
 			goto done;
 		}
 		rxqueue = dev->_rx + index;
 	} else
 		rxqueue = dev->_rx;
 
-	if (!rxqueue->rps_map && !rxqueue->rps_flow_table)
-		goto done;
-
-	if (skb->rxhash)
-		goto got_hash; /* Skip hash computation on packet header */
-
-	switch (skb->protocol) {
-	case __constant_htons(ETH_P_IP):
-		if (!pskb_may_pull(skb, sizeof(*ip)))
+	if (rxqueue->rps_map) {
+		map = rcu_dereference(rxqueue->rps_map);
+		if (map && map->len == 1) {
+			tcpu = map->cpus[0];
+			if (cpu_online(tcpu))
+				cpu = tcpu;
 			goto done;
-
-		ip = (struct iphdr *) skb->data;
-		ip_proto = ip->protocol;
-		addr1 = (__force u32) ip->saddr;
-		addr2 = (__force u32) ip->daddr;
-		ihl = ip->ihl;
-		break;
-	case __constant_htons(ETH_P_IPV6):
-		if (!pskb_may_pull(skb, sizeof(*ip6)))
-			goto done;
-
-		ip6 = (struct ipv6hdr *) skb->data;
-		ip_proto = ip6->nexthdr;
-		addr1 = (__force u32) ip6->saddr.s6_addr32[3];
-		addr2 = (__force u32) ip6->daddr.s6_addr32[3];
-		ihl = (40 >> 2);
-		break;
-	default:
-		goto done;
-	}
-	switch (ip_proto) {
-	case IPPROTO_TCP:
-	case IPPROTO_UDP:
-	case IPPROTO_DCCP:
-	case IPPROTO_ESP:
-	case IPPROTO_AH:
-	case IPPROTO_SCTP:
-	case IPPROTO_UDPLITE:
-		if (pskb_may_pull(skb, (ihl * 4) + 4)) {
-			ports.v32 = * (__force u32 *) (skb->data + (ihl * 4));
-			if (ports.v16[1] < ports.v16[0])
-				swap(ports.v16[0], ports.v16[1]);
-			break;
 		}
-	default:
-		ports.v32 = 0;
-		break;
+	} else if (!rxqueue->rps_flow_table) {
+		goto done;
 	}
 
-	/* get a consistent hash (same value on both flow directions) */
-	if (addr2 < addr1)
-		swap(addr1, addr2);
-	skb->rxhash = jhash_3words(addr1, addr2, ports.v32, hashrnd);
-	if (!skb->rxhash)
-		skb->rxhash = 1;
+	skb_reset_network_header(skb);
+	if (!skb_get_rxhash(skb))
+		goto done;
 
-got_hash:
 	flow_table = rcu_dereference(rxqueue->rps_flow_table);
 	sock_flow_table = rcu_dereference(rps_sock_flow_table);
 	if (flow_table && sock_flow_table) {
@@ -2396,7 +2499,6 @@
 		}
 	}
 
-	map = rcu_dereference(rxqueue->rps_map);
 	if (map) {
 		tcpu = map->cpus[((u64) skb->rxhash * map->len) >> 32];
 
@@ -2482,6 +2584,7 @@
 
 	local_irq_restore(flags);
 
+	atomic_long_inc(&skb->dev->rx_dropped);
 	kfree_skb(skb);
 	return NET_RX_DROP;
 }
@@ -2512,6 +2615,7 @@
 	if (netdev_tstamp_prequeue)
 		net_timestamp_check(skb);
 
+	trace_netif_rx(skb);
 #ifdef CONFIG_RPS
 	{
 		struct rps_dev_flow voidflow, *rflow = &voidflow;
@@ -2571,6 +2675,7 @@
 			clist = clist->next;
 
 			WARN_ON(atomic_read(&skb->users));
+			trace_kfree_skb(skb, net_tx_action);
 			__kfree_skb(skb);
 		}
 	}
@@ -2636,11 +2741,10 @@
  * the ingress scheduler, you just cant add policies on ingress.
  *
  */
-static int ing_filter(struct sk_buff *skb)
+static int ing_filter(struct sk_buff *skb, struct netdev_queue *rxq)
 {
 	struct net_device *dev = skb->dev;
 	u32 ttl = G_TC_RTTL(skb->tc_verd);
-	struct netdev_queue *rxq;
 	int result = TC_ACT_OK;
 	struct Qdisc *q;
 
@@ -2654,8 +2758,6 @@
 	skb->tc_verd = SET_TC_RTTL(skb->tc_verd, ttl);
 	skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_INGRESS);
 
-	rxq = &dev->rx_queue;
-
 	q = rxq->qdisc;
 	if (q != &noop_qdisc) {
 		spin_lock(qdisc_lock(q));
@@ -2671,7 +2773,9 @@
 					 struct packet_type **pt_prev,
 					 int *ret, struct net_device *orig_dev)
 {
-	if (skb->dev->rx_queue.qdisc == &noop_qdisc)
+	struct netdev_queue *rxq = rcu_dereference(skb->dev->ingress_queue);
+
+	if (!rxq || rxq->qdisc == &noop_qdisc)
 		goto out;
 
 	if (*pt_prev) {
@@ -2679,7 +2783,7 @@
 		*pt_prev = NULL;
 	}
 
-	switch (ing_filter(skb)) {
+	switch (ing_filter(skb, rxq)) {
 	case TC_ACT_SHOT:
 	case TC_ACT_STOLEN:
 		kfree_skb(skb);
@@ -2692,33 +2796,6 @@
 }
 #endif
 
-/*
- * 	netif_nit_deliver - deliver received packets to network taps
- * 	@skb: buffer
- *
- * 	This function is used to deliver incoming packets to network
- * 	taps. It should be used when the normal netif_receive_skb path
- * 	is bypassed, for example because of VLAN acceleration.
- */
-void netif_nit_deliver(struct sk_buff *skb)
-{
-	struct packet_type *ptype;
-
-	if (list_empty(&ptype_all))
-		return;
-
-	skb_reset_network_header(skb);
-	skb_reset_transport_header(skb);
-	skb->mac_len = skb->network_header - skb->mac_header;
-
-	rcu_read_lock();
-	list_for_each_entry_rcu(ptype, &ptype_all, list) {
-		if (!ptype->dev || ptype->dev == skb->dev)
-			deliver_skb(skb, ptype, skb->dev);
-	}
-	rcu_read_unlock();
-}
-
 /**
  *	netdev_rx_handler_register - register receive handler
  *	@dev: device to register a handler for
@@ -2828,8 +2905,7 @@
 	if (!netdev_tstamp_prequeue)
 		net_timestamp_check(skb);
 
-	if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb))
-		return NET_RX_SUCCESS;
+	trace_netif_receive_skb(skb);
 
 	/* if we've gotten here through NAPI, check netpoll */
 	if (netpoll_receive_skb(skb))
@@ -2843,8 +2919,7 @@
 	 * 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.  The vlan accel path may have
-	 * already set the deliver_no_wcard flag.
+	 * be dropped at the handler.
 	 */
 	null_or_orig = NULL;
 	orig_dev = skb->dev;
@@ -2903,6 +2978,18 @@
 			goto out;
 	}
 
+	if (vlan_tx_tag_present(skb)) {
+		if (pt_prev) {
+			ret = deliver_skb(skb, pt_prev, orig_dev);
+			pt_prev = NULL;
+		}
+		if (vlan_hwaccel_do_receive(&skb)) {
+			ret = __netif_receive_skb(skb);
+			goto out;
+		} else if (unlikely(!skb))
+			goto out;
+	}
+
 	/*
 	 * Make sure frames received on VLAN interfaces stacked on
 	 * bonding interfaces still make their way to any base bonding
@@ -2930,6 +3017,7 @@
 	if (pt_prev) {
 		ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
 	} else {
+		atomic_long_inc(&skb->dev->rx_dropped);
 		kfree_skb(skb);
 		/* Jamal, now you will not able to escape explaining
 		 * me how you were going to use this. :-)
@@ -3050,7 +3138,7 @@
 	return netif_receive_skb(skb);
 }
 
-static void napi_gro_flush(struct napi_struct *napi)
+inline void napi_gro_flush(struct napi_struct *napi)
 {
 	struct sk_buff *skb, *next;
 
@@ -3063,6 +3151,7 @@
 	napi->gro_count = 0;
 	napi->gro_list = NULL;
 }
+EXPORT_SYMBOL(napi_gro_flush);
 
 enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
@@ -3077,7 +3166,7 @@
 	if (!(skb->dev->features & NETIF_F_GRO) || netpoll_rx_on(skb))
 		goto normal;
 
-	if (skb_is_gso(skb) || skb_has_frags(skb))
+	if (skb_is_gso(skb) || skb_has_frag_list(skb))
 		goto normal;
 
 	rcu_read_lock();
@@ -3156,16 +3245,19 @@
 }
 EXPORT_SYMBOL(dev_gro_receive);
 
-static gro_result_t
+static inline gro_result_t
 __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
 	struct sk_buff *p;
 
 	for (p = napi->gro_list; p; p = p->next) {
-		NAPI_GRO_CB(p)->same_flow =
-			(p->dev == skb->dev) &&
-			!compare_ether_header(skb_mac_header(p),
+		unsigned long diffs;
+
+		diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
+		diffs |= p->vlan_tci ^ skb->vlan_tci;
+		diffs |= compare_ether_header(skb_mac_header(p),
 					      skb_gro_mac_header(skb));
+		NAPI_GRO_CB(p)->same_flow = !diffs;
 		NAPI_GRO_CB(p)->flush = 0;
 	}
 
@@ -3218,14 +3310,14 @@
 }
 EXPORT_SYMBOL(napi_gro_receive);
 
-void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
+static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
 {
 	__skb_pull(skb, skb_headlen(skb));
 	skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb));
+	skb->vlan_tci = 0;
 
 	napi->skb = skb;
 }
-EXPORT_SYMBOL(napi_reuse_skb);
 
 struct sk_buff *napi_get_frags(struct napi_struct *napi)
 {
@@ -4859,21 +4951,6 @@
 	rollback_registered_many(&single);
 }
 
-static void __netdev_init_queue_locks_one(struct net_device *dev,
-					  struct netdev_queue *dev_queue,
-					  void *_unused)
-{
-	spin_lock_init(&dev_queue->_xmit_lock);
-	netdev_set_xmit_lockdep_class(&dev_queue->_xmit_lock, dev->type);
-	dev_queue->xmit_lock_owner = -1;
-}
-
-static void netdev_init_queue_locks(struct net_device *dev)
-{
-	netdev_for_each_tx_queue(dev, __netdev_init_queue_locks_one, NULL);
-	__netdev_init_queue_locks_one(dev, &dev->rx_queue, NULL);
-}
-
 unsigned long netdev_fix_features(unsigned long features, const char *name)
 {
 	/* Fix illegal SG+CSUM combinations. */
@@ -4941,6 +5018,66 @@
 }
 EXPORT_SYMBOL(netif_stacked_transfer_operstate);
 
+static int netif_alloc_rx_queues(struct net_device *dev)
+{
+#ifdef CONFIG_RPS
+	unsigned int i, count = dev->num_rx_queues;
+	struct netdev_rx_queue *rx;
+
+	BUG_ON(count < 1);
+
+	rx = kcalloc(count, sizeof(struct netdev_rx_queue), GFP_KERNEL);
+	if (!rx) {
+		pr_err("netdev: Unable to allocate %u rx queues.\n", count);
+		return -ENOMEM;
+	}
+	dev->_rx = rx;
+
+	/*
+	 * Set a pointer to first element in the array which holds the
+	 * reference count.
+	 */
+	for (i = 0; i < count; i++)
+		rx[i].first = rx;
+#endif
+	return 0;
+}
+
+static int netif_alloc_netdev_queues(struct net_device *dev)
+{
+	unsigned int count = dev->num_tx_queues;
+	struct netdev_queue *tx;
+
+	BUG_ON(count < 1);
+
+	tx = kcalloc(count, sizeof(struct netdev_queue), GFP_KERNEL);
+	if (!tx) {
+		pr_err("netdev: Unable to allocate %u tx queues.\n",
+		       count);
+		return -ENOMEM;
+	}
+	dev->_tx = tx;
+	return 0;
+}
+
+static void netdev_init_one_queue(struct net_device *dev,
+				  struct netdev_queue *queue,
+				  void *_unused)
+{
+	queue->dev = dev;
+
+	/* Initialize queue lock */
+	spin_lock_init(&queue->_xmit_lock);
+	netdev_set_xmit_lockdep_class(&queue->_xmit_lock, dev->type);
+	queue->xmit_lock_owner = -1;
+}
+
+static void netdev_init_queues(struct net_device *dev)
+{
+	netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL);
+	spin_lock_init(&dev->tx_global_lock);
+}
+
 /**
  *	register_netdevice	- register a network device
  *	@dev: device to register
@@ -4974,28 +5111,19 @@
 
 	spin_lock_init(&dev->addr_list_lock);
 	netdev_set_addr_lockdep_class(dev);
-	netdev_init_queue_locks(dev);
 
 	dev->iflink = -1;
 
-#ifdef CONFIG_RPS
-	if (!dev->num_rx_queues) {
-		/*
-		 * Allocate a single RX queue if driver never called
-		 * alloc_netdev_mq
-		 */
+	ret = netif_alloc_rx_queues(dev);
+	if (ret)
+		goto out;
 
-		dev->_rx = kzalloc(sizeof(struct netdev_rx_queue), GFP_KERNEL);
-		if (!dev->_rx) {
-			ret = -ENOMEM;
-			goto out;
-		}
+	ret = netif_alloc_netdev_queues(dev);
+	if (ret)
+		goto out;
 
-		dev->_rx->first = dev->_rx;
-		atomic_set(&dev->_rx->count, 1);
-		dev->num_rx_queues = 1;
-	}
-#endif
+	netdev_init_queues(dev);
+
 	/* Init, if this function is available */
 	if (dev->netdev_ops->ndo_init) {
 		ret = dev->netdev_ops->ndo_init(dev);
@@ -5035,6 +5163,12 @@
 	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.
+	 */
+	dev->vlan_features |= (NETIF_F_GRO | NETIF_F_HIGHDMA);
+
 	ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev);
 	ret = notifier_to_errno(ret);
 	if (ret)
@@ -5105,9 +5239,6 @@
 	 */
 	dev->reg_state = NETREG_DUMMY;
 
-	/* initialize the ref count */
-	atomic_set(&dev->refcnt, 1);
-
 	/* NAPI wants this */
 	INIT_LIST_HEAD(&dev->napi_list);
 
@@ -5115,6 +5246,11 @@
 	set_bit(__LINK_STATE_PRESENT, &dev->state);
 	set_bit(__LINK_STATE_START, &dev->state);
 
+	/* Note : We dont allocate pcpu_refcnt for dummy devices,
+	 * because users of this 'device' dont need to change
+	 * its refcount.
+	 */
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(init_dummy_netdev);
@@ -5156,6 +5292,16 @@
 }
 EXPORT_SYMBOL(register_netdev);
 
+int netdev_refcnt_read(const struct net_device *dev)
+{
+	int i, refcnt = 0;
+
+	for_each_possible_cpu(i)
+		refcnt += *per_cpu_ptr(dev->pcpu_refcnt, i);
+	return refcnt;
+}
+EXPORT_SYMBOL(netdev_refcnt_read);
+
 /*
  * netdev_wait_allrefs - wait until all references are gone.
  *
@@ -5170,11 +5316,14 @@
 static void netdev_wait_allrefs(struct net_device *dev)
 {
 	unsigned long rebroadcast_time, warning_time;
+	int refcnt;
 
 	linkwatch_forget_dev(dev);
 
 	rebroadcast_time = warning_time = jiffies;
-	while (atomic_read(&dev->refcnt) != 0) {
+	refcnt = netdev_refcnt_read(dev);
+
+	while (refcnt != 0) {
 		if (time_after(jiffies, rebroadcast_time + 1 * HZ)) {
 			rtnl_lock();
 
@@ -5201,11 +5350,13 @@
 
 		msleep(250);
 
+		refcnt = netdev_refcnt_read(dev);
+
 		if (time_after(jiffies, warning_time + 10 * HZ)) {
 			printk(KERN_EMERG "unregister_netdevice: "
 			       "waiting for %s to become free. Usage "
 			       "count = %d\n",
-			       dev->name, atomic_read(&dev->refcnt));
+			       dev->name, refcnt);
 			warning_time = jiffies;
 		}
 	}
@@ -5263,8 +5414,8 @@
 		netdev_wait_allrefs(dev);
 
 		/* paranoia */
-		BUG_ON(atomic_read(&dev->refcnt));
-		WARN_ON(dev->ip_ptr);
+		BUG_ON(netdev_refcnt_read(dev));
+		WARN_ON(rcu_dereference_raw(dev->ip_ptr));
 		WARN_ON(dev->ip6_ptr);
 		WARN_ON(dev->dn_ptr);
 
@@ -5342,30 +5493,34 @@
 
 	if (ops->ndo_get_stats64) {
 		memset(storage, 0, sizeof(*storage));
-		return ops->ndo_get_stats64(dev, storage);
-	}
-	if (ops->ndo_get_stats) {
+		ops->ndo_get_stats64(dev, storage);
+	} else if (ops->ndo_get_stats) {
 		netdev_stats_to_stats64(storage, ops->ndo_get_stats(dev));
-		return storage;
+	} else {
+		netdev_stats_to_stats64(storage, &dev->stats);
+		dev_txq_stats_fold(dev, storage);
 	}
-	netdev_stats_to_stats64(storage, &dev->stats);
-	dev_txq_stats_fold(dev, storage);
+	storage->rx_dropped += atomic_long_read(&dev->rx_dropped);
 	return storage;
 }
 EXPORT_SYMBOL(dev_get_stats);
 
-static void netdev_init_one_queue(struct net_device *dev,
-				  struct netdev_queue *queue,
-				  void *_unused)
+struct netdev_queue *dev_ingress_queue_create(struct net_device *dev)
 {
-	queue->dev = dev;
-}
+	struct netdev_queue *queue = dev_ingress_queue(dev);
 
-static void netdev_init_queues(struct net_device *dev)
-{
-	netdev_init_one_queue(dev, &dev->rx_queue, NULL);
-	netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL);
-	spin_lock_init(&dev->tx_global_lock);
+#ifdef CONFIG_NET_CLS_ACT
+	if (queue)
+		return queue;
+	queue = kzalloc(sizeof(*queue), GFP_KERNEL);
+	if (!queue)
+		return NULL;
+	netdev_init_one_queue(dev, queue, NULL);
+	queue->qdisc = &noop_qdisc;
+	queue->qdisc_sleeping = &noop_qdisc;
+	rcu_assign_pointer(dev->ingress_queue, queue);
+#endif
+	return queue;
 }
 
 /**
@@ -5382,17 +5537,18 @@
 struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
 		void (*setup)(struct net_device *), unsigned int queue_count)
 {
-	struct netdev_queue *tx;
 	struct net_device *dev;
 	size_t alloc_size;
 	struct net_device *p;
-#ifdef CONFIG_RPS
-	struct netdev_rx_queue *rx;
-	int i;
-#endif
 
 	BUG_ON(strlen(name) >= sizeof(dev->name));
 
+	if (queue_count < 1) {
+		pr_err("alloc_netdev: Unable to allocate device "
+		       "with zero queues.\n");
+		return NULL;
+	}
+
 	alloc_size = sizeof(struct net_device);
 	if (sizeof_priv) {
 		/* ensure 32-byte alignment of private area */
@@ -5408,55 +5564,31 @@
 		return NULL;
 	}
 
-	tx = kcalloc(queue_count, sizeof(struct netdev_queue), GFP_KERNEL);
-	if (!tx) {
-		printk(KERN_ERR "alloc_netdev: Unable to allocate "
-		       "tx qdiscs.\n");
-		goto free_p;
-	}
-
-#ifdef CONFIG_RPS
-	rx = kcalloc(queue_count, sizeof(struct netdev_rx_queue), GFP_KERNEL);
-	if (!rx) {
-		printk(KERN_ERR "alloc_netdev: Unable to allocate "
-		       "rx queues.\n");
-		goto free_tx;
-	}
-
-	atomic_set(&rx->count, queue_count);
-
-	/*
-	 * Set a pointer to first element in the array which holds the
-	 * reference count.
-	 */
-	for (i = 0; i < queue_count; i++)
-		rx[i].first = rx;
-#endif
-
 	dev = PTR_ALIGN(p, NETDEV_ALIGN);
 	dev->padded = (char *)dev - (char *)p;
 
+	dev->pcpu_refcnt = alloc_percpu(int);
+	if (!dev->pcpu_refcnt)
+		goto free_p;
+
 	if (dev_addr_init(dev))
-		goto free_rx;
+		goto free_pcpu;
 
 	dev_mc_init(dev);
 	dev_uc_init(dev);
 
 	dev_net_set(dev, &init_net);
 
-	dev->_tx = tx;
 	dev->num_tx_queues = queue_count;
 	dev->real_num_tx_queues = queue_count;
 
 #ifdef CONFIG_RPS
-	dev->_rx = rx;
 	dev->num_rx_queues = queue_count;
+	dev->real_num_rx_queues = queue_count;
 #endif
 
 	dev->gso_max_size = GSO_MAX_SIZE;
 
-	netdev_init_queues(dev);
-
 	INIT_LIST_HEAD(&dev->ethtool_ntuple_list.list);
 	dev->ethtool_ntuple_list.count = 0;
 	INIT_LIST_HEAD(&dev->napi_list);
@@ -5467,12 +5599,8 @@
 	strcpy(dev->name, name);
 	return dev;
 
-free_rx:
-#ifdef CONFIG_RPS
-	kfree(rx);
-free_tx:
-#endif
-	kfree(tx);
+free_pcpu:
+	free_percpu(dev->pcpu_refcnt);
 free_p:
 	kfree(p);
 	return NULL;
@@ -5495,6 +5623,8 @@
 
 	kfree(dev->_tx);
 
+	kfree(rcu_dereference_raw(dev->ingress_queue));
+
 	/* Flush device addresses */
 	dev_addr_flush(dev);
 
@@ -5504,6 +5634,9 @@
 	list_for_each_entry_safe(p, n, &dev->napi_list, dev_list)
 		netif_napi_del(p);
 
+	free_percpu(dev->pcpu_refcnt);
+	dev->pcpu_refcnt = NULL;
+
 	/*  Compatibility with error handling in drivers */
 	if (dev->reg_state == NETREG_UNINITIALIZED) {
 		kfree((char *)dev - dev->padded);
@@ -5658,6 +5791,10 @@
 
 	/* Notify protocols, that we are about to destroy
 	   this device. They should clean all the things.
+
+	   Note that dev->reg_state stays at NETREG_REGISTERED.
+	   This is wanted because this way 8021q and macvlan know
+	   the device is just moving and can keep their slaves up.
 	*/
 	call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
 	call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev);
diff --git a/net/core/dst.c b/net/core/dst.c
index 6c41b1f..8abe628 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -168,7 +168,7 @@
 {
 	struct dst_entry *dst;
 
-	if (ops->gc && atomic_read(&ops->entries) > ops->gc_thresh) {
+	if (ops->gc && dst_entries_get_fast(ops) > ops->gc_thresh) {
 		if (ops->gc(ops))
 			return NULL;
 	}
@@ -183,7 +183,7 @@
 #if RT_CACHE_DEBUG >= 2
 	atomic_inc(&dst_total);
 #endif
-	atomic_inc(&ops->entries);
+	dst_entries_add(ops, 1);
 	return dst;
 }
 EXPORT_SYMBOL(dst_alloc);
@@ -228,15 +228,15 @@
 	child = dst->child;
 
 	dst->hh = NULL;
-	if (hh && atomic_dec_and_test(&hh->hh_refcnt))
-		kfree(hh);
+	if (hh)
+		hh_cache_put(hh);
 
 	if (neigh) {
 		dst->neighbour = NULL;
 		neigh_release(neigh);
 	}
 
-	atomic_dec(&dst->ops->entries);
+	dst_entries_add(dst->ops, -1);
 
 	if (dst->ops->destroy)
 		dst->ops->destroy(dst);
@@ -271,13 +271,40 @@
 	if (dst) {
 		int newrefcnt;
 
-		smp_mb__before_atomic_dec();
 		newrefcnt = atomic_dec_return(&dst->__refcnt);
 		WARN_ON(newrefcnt < 0);
+		if (unlikely(dst->flags & DST_NOCACHE) && !newrefcnt) {
+			dst = dst_destroy(dst);
+			if (dst)
+				__dst_free(dst);
+		}
 	}
 }
 EXPORT_SYMBOL(dst_release);
 
+/**
+ * skb_dst_set_noref - sets skb dst, without a reference
+ * @skb: buffer
+ * @dst: dst entry
+ *
+ * Sets skb dst, assuming a reference was not taken on dst
+ * skb_dst_drop() should not dst_release() this dst
+ */
+void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst)
+{
+	WARN_ON(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
+	/* If dst not in cache, we must take a reference, because
+	 * dst_release() will destroy dst as soon as its refcount becomes zero
+	 */
+	if (unlikely(dst->flags & DST_NOCACHE)) {
+		dst_hold(dst);
+		skb_dst_set(skb, dst);
+	} else {
+		skb->_skb_refdst = (unsigned long)dst | SKB_DST_NOREF;
+	}
+}
+EXPORT_SYMBOL(skb_dst_set_noref);
+
 /* Dirty hack. We did it in 2.2 (in __dst_free),
  * we have _very_ good reasons not to repeat
  * this mistake in 2.3, but we have no choice
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 7a85367..956a9f4 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -19,6 +19,7 @@
 #include <linux/netdevice.h>
 #include <linux/bitops.h>
 #include <linux/uaccess.h>
+#include <linux/vmalloc.h>
 #include <linux/slab.h>
 
 /*
@@ -131,7 +132,8 @@
  * NETIF_F_xxx values in include/linux/netdevice.h
  */
 static const u32 flags_dup_features =
-	(ETH_FLAG_LRO | ETH_FLAG_NTUPLE | ETH_FLAG_RXHASH);
+	(ETH_FLAG_LRO | ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | ETH_FLAG_NTUPLE |
+	 ETH_FLAG_RXHASH);
 
 u32 ethtool_op_get_flags(struct net_device *dev)
 {
@@ -205,18 +207,24 @@
 	struct ethtool_drvinfo info;
 	const struct ethtool_ops *ops = dev->ethtool_ops;
 
-	if (!ops->get_drvinfo)
-		return -EOPNOTSUPP;
-
 	memset(&info, 0, sizeof(info));
 	info.cmd = ETHTOOL_GDRVINFO;
-	ops->get_drvinfo(dev, &info);
+	if (ops && ops->get_drvinfo) {
+		ops->get_drvinfo(dev, &info);
+	} else if (dev->dev.parent && dev->dev.parent->driver) {
+		strlcpy(info.bus_info, dev_name(dev->dev.parent),
+			sizeof(info.bus_info));
+		strlcpy(info.driver, dev->dev.parent->driver->name,
+			sizeof(info.driver));
+	} else {
+		return -EOPNOTSUPP;
+	}
 
 	/*
 	 * this method of obtaining string set info is deprecated;
 	 * Use ETHTOOL_GSSET_INFO instead.
 	 */
-	if (ops->get_sset_count) {
+	if (ops && ops->get_sset_count) {
 		int rc;
 
 		rc = ops->get_sset_count(dev, ETH_SS_TEST);
@@ -229,9 +237,9 @@
 		if (rc >= 0)
 			info.n_priv_flags = rc;
 	}
-	if (ops->get_regs_len)
+	if (ops && ops->get_regs_len)
 		info.regdump_len = ops->get_regs_len(dev);
-	if (ops->get_eeprom_len)
+	if (ops && ops->get_eeprom_len)
 		info.eedump_len = ops->get_eeprom_len(dev);
 
 	if (copy_to_user(useraddr, &info, sizeof(info)))
@@ -348,7 +356,7 @@
 	if (info.cmd == ETHTOOL_GRXCLSRLALL) {
 		if (info.rule_cnt > 0) {
 			if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32))
-				rule_buf = kmalloc(info.rule_cnt * sizeof(u32),
+				rule_buf = kzalloc(info.rule_cnt * sizeof(u32),
 						   GFP_USER);
 			if (!rule_buf)
 				return -ENOMEM;
@@ -397,7 +405,7 @@
 	    (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index))
 		return -ENOMEM;
 	full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size;
-	indir = kmalloc(full_size, GFP_USER);
+	indir = kzalloc(full_size, GFP_USER);
 	if (!indir)
 		return -ENOMEM;
 
@@ -479,6 +487,38 @@
 	list->count++;
 }
 
+/*
+ * ethtool does not (or did not) set masks for flow parameters that are
+ * not specified, so if both value and mask are 0 then this must be
+ * treated as equivalent to a mask with all bits set.  Implement that
+ * here rather than in drivers.
+ */
+static void rx_ntuple_fix_masks(struct ethtool_rx_ntuple_flow_spec *fs)
+{
+	struct ethtool_tcpip4_spec *entry = &fs->h_u.tcp_ip4_spec;
+	struct ethtool_tcpip4_spec *mask = &fs->m_u.tcp_ip4_spec;
+
+	if (fs->flow_type != TCP_V4_FLOW &&
+	    fs->flow_type != UDP_V4_FLOW &&
+	    fs->flow_type != SCTP_V4_FLOW)
+		return;
+
+	if (!(entry->ip4src | mask->ip4src))
+		mask->ip4src = htonl(0xffffffff);
+	if (!(entry->ip4dst | mask->ip4dst))
+		mask->ip4dst = htonl(0xffffffff);
+	if (!(entry->psrc | mask->psrc))
+		mask->psrc = htons(0xffff);
+	if (!(entry->pdst | mask->pdst))
+		mask->pdst = htons(0xffff);
+	if (!(entry->tos | mask->tos))
+		mask->tos = 0xff;
+	if (!(fs->vlan_tag | fs->vlan_tag_mask))
+		fs->vlan_tag_mask = 0xffff;
+	if (!(fs->data | fs->data_mask))
+		fs->data_mask = 0xffffffffffffffffULL;
+}
+
 static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
 						    void __user *useraddr)
 {
@@ -493,6 +533,8 @@
 	if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
 		return -EFAULT;
 
+	rx_ntuple_fix_masks(&cmd.fs);
+
 	/*
 	 * Cache filter in dev struct for GET operation only if
 	 * the underlying driver doesn't have its own GET operation, and
@@ -538,7 +580,7 @@
 
 	gstrings.len = ret;
 
-	data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
+	data = kzalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
 	if (!data)
 		return -ENOMEM;
 
@@ -667,19 +709,19 @@
 			break;
 		case IP_USER_FLOW:
 			sprintf(p, "\tSrc IP addr: 0x%x\n",
-				fsc->fs.h_u.raw_ip4_spec.ip4src);
+				fsc->fs.h_u.usr_ip4_spec.ip4src);
 			p += ETH_GSTRING_LEN;
 			num_strings++;
 			sprintf(p, "\tSrc IP mask: 0x%x\n",
-				fsc->fs.m_u.raw_ip4_spec.ip4src);
+				fsc->fs.m_u.usr_ip4_spec.ip4src);
 			p += ETH_GSTRING_LEN;
 			num_strings++;
 			sprintf(p, "\tDest IP addr: 0x%x\n",
-				fsc->fs.h_u.raw_ip4_spec.ip4dst);
+				fsc->fs.h_u.usr_ip4_spec.ip4dst);
 			p += ETH_GSTRING_LEN;
 			num_strings++;
 			sprintf(p, "\tDest IP mask: 0x%x\n",
-				fsc->fs.m_u.raw_ip4_spec.ip4dst);
+				fsc->fs.m_u.usr_ip4_spec.ip4dst);
 			p += ETH_GSTRING_LEN;
 			num_strings++;
 			break;
@@ -775,7 +817,7 @@
 	if (regs.len > reglen)
 		regs.len = reglen;
 
-	regbuf = kmalloc(reglen, GFP_USER);
+	regbuf = vmalloc(reglen);
 	if (!regbuf)
 		return -ENOMEM;
 
@@ -790,7 +832,7 @@
 	ret = 0;
 
  out:
-	kfree(regbuf);
+	vfree(regbuf);
 	return ret;
 }
 
@@ -1175,8 +1217,11 @@
 		return -EFAULT;
 
 	if (edata.data) {
-		if (!dev->ethtool_ops->get_rx_csum ||
-		    !dev->ethtool_ops->get_rx_csum(dev))
+		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
@@ -1402,14 +1447,22 @@
 	if (!dev || !netif_device_present(dev))
 		return -ENODEV;
 
-	if (!dev->ethtool_ops)
-		return -EOPNOTSUPP;
-
 	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
 		return -EFAULT;
 
+	if (!dev->ethtool_ops) {
+		/* ETHTOOL_GDRVINFO does not require any driver support.
+		 * It is also unprivileged and does not change anything,
+		 * so we can take a shortcut to it. */
+		if (ethcmd == ETHTOOL_GDRVINFO)
+			return ethtool_get_drvinfo(dev, useraddr);
+		else
+			return -EOPNOTSUPP;
+	}
+
 	/* Allow some commands to be done by anyone */
 	switch (ethcmd) {
+	case ETHTOOL_GSET:
 	case ETHTOOL_GDRVINFO:
 	case ETHTOOL_GMSGLVL:
 	case ETHTOOL_GCOALESCE:
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 42e84e0..1bc3f25 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -144,7 +144,7 @@
 }
 EXPORT_SYMBOL_GPL(fib_rules_register);
 
-void fib_rules_cleanup_ops(struct fib_rules_ops *ops)
+static void fib_rules_cleanup_ops(struct fib_rules_ops *ops)
 {
 	struct fib_rule *rule, *tmp;
 
@@ -153,7 +153,6 @@
 		fib_rule_put(rule);
 	}
 }
-EXPORT_SYMBOL_GPL(fib_rules_cleanup_ops);
 
 static void fib_rules_put_rcu(struct rcu_head *head)
 {
@@ -182,7 +181,8 @@
 {
 	int ret = 0;
 
-	if (rule->iifindex && (rule->iifindex != fl->iif))
+	if (rule->iifindex && (rule->iifindex != fl->iif) &&
+	    !(fl->flags & FLOWI_FLAG_MATCH_ANY_IIF))
 		goto out;
 
 	if (rule->oifindex && (rule->oifindex != fl->oif))
@@ -225,9 +225,12 @@
 			err = ops->action(rule, fl, flags, arg);
 
 		if (err != -EAGAIN) {
-			fib_rule_get(rule);
-			arg->rule = rule;
-			goto out;
+			if ((arg->flags & FIB_LOOKUP_NOREF) ||
+			    likely(atomic_inc_not_zero(&rule->refcnt))) {
+				arg->rule = rule;
+				goto out;
+			}
+			break;
 		}
 	}
 
@@ -491,7 +494,6 @@
 			}
 		}
 
-		synchronize_rcu();
 		notify_rule_change(RTM_DELRULE, rule, ops, nlh,
 				   NETLINK_CB(skb).pid);
 		fib_rule_put(rule);
diff --git a/net/core/filter.c b/net/core/filter.c
index 52b051f..7adf503 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -638,10 +638,9 @@
 		return err;
 	}
 
-	rcu_read_lock_bh();
-	old_fp = rcu_dereference_bh(sk->sk_filter);
+	old_fp = rcu_dereference_protected(sk->sk_filter,
+					   sock_owned_by_user(sk));
 	rcu_assign_pointer(sk->sk_filter, fp);
-	rcu_read_unlock_bh();
 
 	if (old_fp)
 		sk_filter_delayed_uncharge(sk, old_fp);
@@ -654,14 +653,13 @@
 	int ret = -ENOENT;
 	struct sk_filter *filter;
 
-	rcu_read_lock_bh();
-	filter = rcu_dereference_bh(sk->sk_filter);
+	filter = rcu_dereference_protected(sk->sk_filter,
+					   sock_owned_by_user(sk));
 	if (filter) {
 		rcu_assign_pointer(sk->sk_filter, NULL);
 		sk_filter_delayed_uncharge(sk, filter);
 		ret = 0;
 	}
-	rcu_read_unlock_bh();
 	return ret;
 }
 EXPORT_SYMBOL_GPL(sk_detach_filter);
diff --git a/net/core/flow.c b/net/core/flow.c
index f67dcbf..127c8a7 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -53,8 +53,7 @@
 
 struct flow_cache {
 	u32				hash_shift;
-	unsigned long			order;
-	struct flow_cache_percpu	*percpu;
+	struct flow_cache_percpu __percpu *percpu;
 	struct notifier_block		hotcpu_notifier;
 	int				low_watermark;
 	int				high_watermark;
@@ -64,7 +63,7 @@
 atomic_t flow_cache_genid = ATOMIC_INIT(0);
 EXPORT_SYMBOL(flow_cache_genid);
 static struct flow_cache flow_cache_global;
-static struct kmem_cache *flow_cachep;
+static struct kmem_cache *flow_cachep __read_mostly;
 
 static DEFINE_SPINLOCK(flow_cache_gc_lock);
 static LIST_HEAD(flow_cache_gc_list);
@@ -177,15 +176,11 @@
 {
 	u32 *k = (u32 *) key;
 
-	return (jhash2(k, (sizeof(*key) / sizeof(u32)), fcp->hash_rnd)
-		& (flow_cache_hash_size(fc) - 1));
+	return jhash2(k, (sizeof(*key) / sizeof(u32)), fcp->hash_rnd)
+		& (flow_cache_hash_size(fc) - 1);
 }
 
-#if (BITS_PER_LONG == 64)
-typedef u64 flow_compare_t;
-#else
-typedef u32 flow_compare_t;
-#endif
+typedef unsigned long flow_compare_t;
 
 /* I hear what you're saying, use memcmp.  But memcmp cannot make
  * important assumptions that we can here, such as alignment and
@@ -357,62 +352,73 @@
 	put_online_cpus();
 }
 
-static void __init flow_cache_cpu_prepare(struct flow_cache *fc,
-					  struct flow_cache_percpu *fcp)
+static int __cpuinit flow_cache_cpu_prepare(struct flow_cache *fc, int cpu)
 {
-	fcp->hash_table = (struct hlist_head *)
-		__get_free_pages(GFP_KERNEL|__GFP_ZERO, fc->order);
-	if (!fcp->hash_table)
-		panic("NET: failed to allocate flow cache order %lu\n", fc->order);
+	struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu);
+	size_t sz = sizeof(struct hlist_head) * flow_cache_hash_size(fc);
 
-	fcp->hash_rnd_recalc = 1;
-	fcp->hash_count = 0;
-	tasklet_init(&fcp->flush_tasklet, flow_cache_flush_tasklet, 0);
+	if (!fcp->hash_table) {
+		fcp->hash_table = kzalloc_node(sz, GFP_KERNEL, cpu_to_node(cpu));
+		if (!fcp->hash_table) {
+			pr_err("NET: failed to allocate flow cache sz %zu\n", sz);
+			return -ENOMEM;
+		}
+		fcp->hash_rnd_recalc = 1;
+		fcp->hash_count = 0;
+		tasklet_init(&fcp->flush_tasklet, flow_cache_flush_tasklet, 0);
+	}
+	return 0;
 }
 
-static int flow_cache_cpu(struct notifier_block *nfb,
+static int __cpuinit flow_cache_cpu(struct notifier_block *nfb,
 			  unsigned long action,
 			  void *hcpu)
 {
 	struct flow_cache *fc = container_of(nfb, struct flow_cache, hotcpu_notifier);
-	int cpu = (unsigned long) hcpu;
+	int res, cpu = (unsigned long) hcpu;
 	struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu);
 
-	if (action == CPU_DEAD || action == CPU_DEAD_FROZEN)
+	switch (action) {
+	case CPU_UP_PREPARE:
+	case CPU_UP_PREPARE_FROZEN:
+		res = flow_cache_cpu_prepare(fc, cpu);
+		if (res)
+			return notifier_from_errno(res);
+		break;
+	case CPU_DEAD:
+	case CPU_DEAD_FROZEN:
 		__flow_cache_shrink(fc, fcp, 0);
+		break;
+	}
 	return NOTIFY_OK;
 }
 
-static int flow_cache_init(struct flow_cache *fc)
+static int __init flow_cache_init(struct flow_cache *fc)
 {
-	unsigned long order;
 	int i;
 
 	fc->hash_shift = 10;
 	fc->low_watermark = 2 * flow_cache_hash_size(fc);
 	fc->high_watermark = 4 * flow_cache_hash_size(fc);
 
-	for (order = 0;
-	     (PAGE_SIZE << order) <
-		     (sizeof(struct hlist_head)*flow_cache_hash_size(fc));
-	     order++)
-		/* NOTHING */;
-	fc->order = order;
 	fc->percpu = alloc_percpu(struct flow_cache_percpu);
+	if (!fc->percpu)
+		return -ENOMEM;
+
+	for_each_online_cpu(i) {
+		if (flow_cache_cpu_prepare(fc, i))
+			return -ENOMEM;
+	}
+	fc->hotcpu_notifier = (struct notifier_block){
+		.notifier_call = flow_cache_cpu,
+	};
+	register_hotcpu_notifier(&fc->hotcpu_notifier);
 
 	setup_timer(&fc->rnd_timer, flow_cache_new_hashrnd,
 		    (unsigned long) fc);
 	fc->rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
 	add_timer(&fc->rnd_timer);
 
-	for_each_possible_cpu(i)
-		flow_cache_cpu_prepare(fc, per_cpu_ptr(fc->percpu, i));
-
-	fc->hotcpu_notifier = (struct notifier_block){
-		.notifier_call = flow_cache_cpu,
-	};
-	register_hotcpu_notifier(&fc->hotcpu_notifier);
-
 	return 0;
 }
 
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index 6743146..7c23733 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -274,9 +274,9 @@
 	while ((e = gen_find_node(bstats, rate_est))) {
 		rb_erase(&e->node, &est_root);
 
-		write_lock_bh(&est_lock);
+		write_lock(&est_lock);
 		e->bstats = NULL;
-		write_unlock_bh(&est_lock);
+		write_unlock(&est_lock);
 
 		list_del_rcu(&e->list);
 		call_rcu(&e->e_rcu, __gen_kill_estimator);
diff --git a/net/core/iovec.c b/net/core/iovec.c
index 1cd98df..72aceb1 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -35,13 +35,16 @@
  *	in any case.
  */
 
-int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)
+long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)
 {
-	int size, err, ct;
+	int size, ct;
+	long err;
 
 	if (m->msg_namelen) {
 		if (mode == VERIFY_READ) {
-			err = move_addr_to_kernel(m->msg_name, m->msg_namelen,
+			void __user *namep;
+			namep = (void __user __force *) m->msg_name;
+			err = move_addr_to_kernel(namep, m->msg_namelen,
 						  address);
 			if (err < 0)
 				return err;
@@ -52,7 +55,7 @@
 	}
 
 	size = m->msg_iovlen * sizeof(struct iovec);
-	if (copy_from_user(iov, m->msg_iov, size))
+	if (copy_from_user(iov, (void __user __force *) m->msg_iov, size))
 		return -EFAULT;
 
 	m->msg_iov = iov;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index a4e0a74..8cc8f9a 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -122,7 +122,7 @@
 
 unsigned long neigh_rand_reach_time(unsigned long base)
 {
-	return (base ? (net_random() % base) + (base >> 1) : 0);
+	return base ? (net_random() % base) + (base >> 1) : 0;
 }
 EXPORT_SYMBOL(neigh_rand_reach_time);
 
@@ -131,15 +131,20 @@
 {
 	int shrunk = 0;
 	int i;
+	struct neigh_hash_table *nht;
 
 	NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
 
 	write_lock_bh(&tbl->lock);
-	for (i = 0; i <= tbl->hash_mask; i++) {
-		struct neighbour *n, **np;
+	nht = rcu_dereference_protected(tbl->nht,
+					lockdep_is_held(&tbl->lock));
+	for (i = 0; i <= nht->hash_mask; i++) {
+		struct neighbour *n;
+		struct neighbour __rcu **np;
 
-		np = &tbl->hash_buckets[i];
-		while ((n = *np) != NULL) {
+		np = &nht->hash_buckets[i];
+		while ((n = rcu_dereference_protected(*np,
+					lockdep_is_held(&tbl->lock))) != NULL) {
 			/* Neighbour record may be discarded if:
 			 * - nobody refers to it.
 			 * - it is not permanent
@@ -147,7 +152,9 @@
 			write_lock(&n->lock);
 			if (atomic_read(&n->refcnt) == 1 &&
 			    !(n->nud_state & NUD_PERMANENT)) {
-				*np	= n->next;
+				rcu_assign_pointer(*np,
+					rcu_dereference_protected(n->next,
+						  lockdep_is_held(&tbl->lock)));
 				n->dead = 1;
 				shrunk	= 1;
 				write_unlock(&n->lock);
@@ -199,16 +206,24 @@
 static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
 {
 	int i;
+	struct neigh_hash_table *nht;
 
-	for (i = 0; i <= tbl->hash_mask; i++) {
-		struct neighbour *n, **np = &tbl->hash_buckets[i];
+	nht = rcu_dereference_protected(tbl->nht,
+					lockdep_is_held(&tbl->lock));
 
-		while ((n = *np) != NULL) {
+	for (i = 0; i <= nht->hash_mask; i++) {
+		struct neighbour *n;
+		struct neighbour __rcu **np = &nht->hash_buckets[i];
+
+		while ((n = rcu_dereference_protected(*np,
+					lockdep_is_held(&tbl->lock))) != NULL) {
 			if (dev && n->dev != dev) {
 				np = &n->next;
 				continue;
 			}
-			*np = n->next;
+			rcu_assign_pointer(*np,
+				   rcu_dereference_protected(n->next,
+						lockdep_is_held(&tbl->lock)));
 			write_lock(&n->lock);
 			neigh_del_timer(n);
 			n->dead = 1;
@@ -279,6 +294,7 @@
 
 	skb_queue_head_init(&n->arp_queue);
 	rwlock_init(&n->lock);
+	seqlock_init(&n->ha_lock);
 	n->updated	  = n->used = now;
 	n->nud_state	  = NUD_NONE;
 	n->output	  = neigh_blackhole;
@@ -297,64 +313,86 @@
 	goto out;
 }
 
-static struct neighbour **neigh_hash_alloc(unsigned int entries)
+static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries)
 {
-	unsigned long size = entries * sizeof(struct neighbour *);
-	struct neighbour **ret;
+	size_t size = entries * sizeof(struct neighbour *);
+	struct neigh_hash_table *ret;
+	struct neighbour **buckets;
 
-	if (size <= PAGE_SIZE) {
-		ret = kzalloc(size, GFP_ATOMIC);
-	} else {
-		ret = (struct neighbour **)
-		      __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size));
+	ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
+	if (!ret)
+		return NULL;
+	if (size <= PAGE_SIZE)
+		buckets = kzalloc(size, GFP_ATOMIC);
+	else
+		buckets = (struct neighbour **)
+			  __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_mask = entries - 1;
+	get_random_bytes(&ret->hash_rnd, sizeof(ret->hash_rnd));
 	return ret;
 }
 
-static void neigh_hash_free(struct neighbour **hash, unsigned int entries)
+static void neigh_hash_free_rcu(struct rcu_head *head)
 {
-	unsigned long size = entries * sizeof(struct neighbour *);
+	struct neigh_hash_table *nht = container_of(head,
+						    struct neigh_hash_table,
+						    rcu);
+	size_t size = (nht->hash_mask + 1) * sizeof(struct neighbour *);
+	struct neighbour **buckets = nht->hash_buckets;
 
 	if (size <= PAGE_SIZE)
-		kfree(hash);
+		kfree(buckets);
 	else
-		free_pages((unsigned long)hash, get_order(size));
+		free_pages((unsigned long)buckets, get_order(size));
+	kfree(nht);
 }
 
-static void neigh_hash_grow(struct neigh_table *tbl, unsigned long new_entries)
+static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
+						unsigned long new_entries)
 {
-	struct neighbour **new_hash, **old_hash;
-	unsigned int i, new_hash_mask, old_entries;
+	unsigned int i, hash;
+	struct neigh_hash_table *new_nht, *old_nht;
 
 	NEIGH_CACHE_STAT_INC(tbl, hash_grows);
 
 	BUG_ON(!is_power_of_2(new_entries));
-	new_hash = neigh_hash_alloc(new_entries);
-	if (!new_hash)
-		return;
+	old_nht = rcu_dereference_protected(tbl->nht,
+					    lockdep_is_held(&tbl->lock));
+	new_nht = neigh_hash_alloc(new_entries);
+	if (!new_nht)
+		return old_nht;
 
-	old_entries = tbl->hash_mask + 1;
-	new_hash_mask = new_entries - 1;
-	old_hash = tbl->hash_buckets;
-
-	get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
-	for (i = 0; i < old_entries; i++) {
+	for (i = 0; i <= old_nht->hash_mask; i++) {
 		struct neighbour *n, *next;
 
-		for (n = old_hash[i]; n; n = next) {
-			unsigned int hash_val = tbl->hash(n->primary_key, n->dev);
+		for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
+						   lockdep_is_held(&tbl->lock));
+		     n != NULL;
+		     n = next) {
+			hash = tbl->hash(n->primary_key, n->dev,
+					 new_nht->hash_rnd);
 
-			hash_val &= new_hash_mask;
-			next = n->next;
+			hash &= new_nht->hash_mask;
+			next = rcu_dereference_protected(n->next,
+						lockdep_is_held(&tbl->lock));
 
-			n->next = new_hash[hash_val];
-			new_hash[hash_val] = n;
+			rcu_assign_pointer(n->next,
+					   rcu_dereference_protected(
+						new_nht->hash_buckets[hash],
+						lockdep_is_held(&tbl->lock)));
+			rcu_assign_pointer(new_nht->hash_buckets[hash], n);
 		}
 	}
-	tbl->hash_buckets = new_hash;
-	tbl->hash_mask = new_hash_mask;
 
-	neigh_hash_free(old_hash, old_entries);
+	rcu_assign_pointer(tbl->nht, new_nht);
+	call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
+	return new_nht;
 }
 
 struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
@@ -363,19 +401,26 @@
 	struct neighbour *n;
 	int key_len = tbl->key_len;
 	u32 hash_val;
+	struct neigh_hash_table *nht;
 
 	NEIGH_CACHE_STAT_INC(tbl, lookups);
 
-	read_lock_bh(&tbl->lock);
-	hash_val = tbl->hash(pkey, dev);
-	for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
+	rcu_read_lock_bh();
+	nht = rcu_dereference_bh(tbl->nht);
+	hash_val = tbl->hash(pkey, dev, nht->hash_rnd) & nht->hash_mask;
+
+	for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
+	     n != NULL;
+	     n = rcu_dereference_bh(n->next)) {
 		if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
-			neigh_hold(n);
+			if (!atomic_inc_not_zero(&n->refcnt))
+				n = NULL;
 			NEIGH_CACHE_STAT_INC(tbl, hits);
 			break;
 		}
 	}
-	read_unlock_bh(&tbl->lock);
+
+	rcu_read_unlock_bh();
 	return n;
 }
 EXPORT_SYMBOL(neigh_lookup);
@@ -386,20 +431,27 @@
 	struct neighbour *n;
 	int key_len = tbl->key_len;
 	u32 hash_val;
+	struct neigh_hash_table *nht;
 
 	NEIGH_CACHE_STAT_INC(tbl, lookups);
 
-	read_lock_bh(&tbl->lock);
-	hash_val = tbl->hash(pkey, NULL);
-	for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
+	rcu_read_lock_bh();
+	nht = rcu_dereference_bh(tbl->nht);
+	hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) & nht->hash_mask;
+
+	for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
+	     n != NULL;
+	     n = rcu_dereference_bh(n->next)) {
 		if (!memcmp(n->primary_key, pkey, key_len) &&
 		    net_eq(dev_net(n->dev), net)) {
-			neigh_hold(n);
+			if (!atomic_inc_not_zero(&n->refcnt))
+				n = NULL;
 			NEIGH_CACHE_STAT_INC(tbl, hits);
 			break;
 		}
 	}
-	read_unlock_bh(&tbl->lock);
+
+	rcu_read_unlock_bh();
 	return n;
 }
 EXPORT_SYMBOL(neigh_lookup_nodev);
@@ -411,6 +463,7 @@
 	int key_len = tbl->key_len;
 	int error;
 	struct neighbour *n1, *rc, *n = neigh_alloc(tbl);
+	struct neigh_hash_table *nht;
 
 	if (!n) {
 		rc = ERR_PTR(-ENOBUFS);
@@ -437,18 +490,24 @@
 	n->confirmed = jiffies - (n->parms->base_reachable_time << 1);
 
 	write_lock_bh(&tbl->lock);
+	nht = rcu_dereference_protected(tbl->nht,
+					lockdep_is_held(&tbl->lock));
 
-	if (atomic_read(&tbl->entries) > (tbl->hash_mask + 1))
-		neigh_hash_grow(tbl, (tbl->hash_mask + 1) << 1);
+	if (atomic_read(&tbl->entries) > (nht->hash_mask + 1))
+		nht = neigh_hash_grow(tbl, (nht->hash_mask + 1) << 1);
 
-	hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;
+	hash_val = tbl->hash(pkey, dev, nht->hash_rnd) & nht->hash_mask;
 
 	if (n->parms->dead) {
 		rc = ERR_PTR(-EINVAL);
 		goto out_tbl_unlock;
 	}
 
-	for (n1 = tbl->hash_buckets[hash_val]; n1; n1 = n1->next) {
+	for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
+					    lockdep_is_held(&tbl->lock));
+	     n1 != NULL;
+	     n1 = rcu_dereference_protected(n1->next,
+			lockdep_is_held(&tbl->lock))) {
 		if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
 			neigh_hold(n1);
 			rc = n1;
@@ -456,10 +515,12 @@
 		}
 	}
 
-	n->next = tbl->hash_buckets[hash_val];
-	tbl->hash_buckets[hash_val] = n;
 	n->dead = 0;
 	neigh_hold(n);
+	rcu_assign_pointer(n->next,
+			   rcu_dereference_protected(nht->hash_buckets[hash_val],
+						     lockdep_is_held(&tbl->lock)));
+	rcu_assign_pointer(nht->hash_buckets[hash_val], n);
 	write_unlock_bh(&tbl->lock);
 	NEIGH_PRINTK2("neigh %p is created.\n", n);
 	rc = n;
@@ -616,6 +677,12 @@
 		neigh_parms_destroy(parms);
 }
 
+static void neigh_destroy_rcu(struct rcu_head *head)
+{
+	struct neighbour *neigh = container_of(head, struct neighbour, rcu);
+
+	kmem_cache_free(neigh->tbl->kmem_cachep, neigh);
+}
 /*
  *	neighbour must already be out of the table;
  *
@@ -643,8 +710,7 @@
 		write_seqlock_bh(&hh->hh_lock);
 		hh->hh_output = neigh_blackhole;
 		write_sequnlock_bh(&hh->hh_lock);
-		if (atomic_dec_and_test(&hh->hh_refcnt))
-			kfree(hh);
+		hh_cache_put(hh);
 	}
 
 	skb_queue_purge(&neigh->arp_queue);
@@ -655,7 +721,7 @@
 	NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh);
 
 	atomic_dec(&neigh->tbl->entries);
-	kmem_cache_free(neigh->tbl->kmem_cachep, neigh);
+	call_rcu(&neigh->rcu, neigh_destroy_rcu);
 }
 EXPORT_SYMBOL(neigh_destroy);
 
@@ -696,12 +762,16 @@
 static void neigh_periodic_work(struct work_struct *work)
 {
 	struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
-	struct neighbour *n, **np;
+	struct neighbour *n;
+	struct neighbour __rcu **np;
 	unsigned int i;
+	struct neigh_hash_table *nht;
 
 	NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
 
 	write_lock_bh(&tbl->lock);
+	nht = rcu_dereference_protected(tbl->nht,
+					lockdep_is_held(&tbl->lock));
 
 	/*
 	 *	periodically recompute ReachableTime from random function
@@ -715,10 +785,11 @@
 				neigh_rand_reach_time(p->base_reachable_time);
 	}
 
-	for (i = 0 ; i <= tbl->hash_mask; i++) {
-		np = &tbl->hash_buckets[i];
+	for (i = 0 ; i <= nht->hash_mask; i++) {
+		np = &nht->hash_buckets[i];
 
-		while ((n = *np) != NULL) {
+		while ((n = rcu_dereference_protected(*np,
+				lockdep_is_held(&tbl->lock))) != NULL) {
 			unsigned int state;
 
 			write_lock(&n->lock);
@@ -766,9 +837,9 @@
 static __inline__ int neigh_max_probes(struct neighbour *n)
 {
 	struct neigh_parms *p = n->parms;
-	return (n->nud_state & NUD_PROBE ?
+	return (n->nud_state & NUD_PROBE) ?
 		p->ucast_probes :
-		p->ucast_probes + p->app_probes + p->mcast_probes);
+		p->ucast_probes + p->app_probes + p->mcast_probes;
 }
 
 static void neigh_invalidate(struct neighbour *neigh)
@@ -945,7 +1016,7 @@
 }
 EXPORT_SYMBOL(__neigh_event_send);
 
-static void neigh_update_hhs(struct neighbour *neigh)
+static void neigh_update_hhs(const struct neighbour *neigh)
 {
 	struct hh_cache *hh;
 	void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
@@ -1081,7 +1152,9 @@
 	}
 
 	if (lladdr != neigh->ha) {
+		write_seqlock(&neigh->ha_lock);
 		memcpy(&neigh->ha, lladdr, dev->addr_len);
+		write_sequnlock(&neigh->ha_lock);
 		neigh_update_hhs(neigh);
 		if (!(new & NUD_CONNECTED))
 			neigh->confirmed = jiffies -
@@ -1139,44 +1212,73 @@
 }
 EXPORT_SYMBOL(neigh_event_ns);
 
+static inline bool neigh_hh_lookup(struct neighbour *n, struct dst_entry *dst,
+				   __be16 protocol)
+{
+	struct hh_cache *hh;
+
+	smp_rmb(); /* paired with smp_wmb() in neigh_hh_init() */
+	for (hh = n->hh; hh; hh = hh->hh_next) {
+		if (hh->hh_type == protocol) {
+			atomic_inc(&hh->hh_refcnt);
+			if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL))
+				hh_cache_put(hh);
+			return true;
+		}
+	}
+	return false;
+}
+
+/* called with read_lock_bh(&n->lock); */
 static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
 			  __be16 protocol)
 {
 	struct hh_cache	*hh;
 	struct net_device *dev = dst->dev;
 
-	for (hh = n->hh; hh; hh = hh->hh_next)
-		if (hh->hh_type == protocol)
-			break;
+	if (likely(neigh_hh_lookup(n, dst, protocol)))
+		return;
 
-	if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
-		seqlock_init(&hh->hh_lock);
-		hh->hh_type = protocol;
-		atomic_set(&hh->hh_refcnt, 0);
-		hh->hh_next = NULL;
+	/* slow path */
+	hh = kzalloc(sizeof(*hh), GFP_ATOMIC);
+	if (!hh)
+		return;
 
-		if (dev->header_ops->cache(n, hh)) {
-			kfree(hh);
-			hh = NULL;
-		} else {
-			atomic_inc(&hh->hh_refcnt);
-			hh->hh_next = n->hh;
-			n->hh	    = hh;
-			if (n->nud_state & NUD_CONNECTED)
-				hh->hh_output = n->ops->hh_output;
-			else
-				hh->hh_output = n->ops->output;
-		}
+	seqlock_init(&hh->hh_lock);
+	hh->hh_type = protocol;
+	atomic_set(&hh->hh_refcnt, 2);
+
+	if (dev->header_ops->cache(n, hh)) {
+		kfree(hh);
+		return;
 	}
-	if (hh)	{
-		atomic_inc(&hh->hh_refcnt);
-		dst->hh = hh;
+
+	write_lock_bh(&n->lock);
+
+	/* must check if another thread already did the insert */
+	if (neigh_hh_lookup(n, dst, protocol)) {
+		kfree(hh);
+		goto end;
 	}
+
+	if (n->nud_state & NUD_CONNECTED)
+		hh->hh_output = n->ops->hh_output;
+	else
+		hh->hh_output = n->ops->output;
+
+	hh->hh_next = n->hh;
+	smp_wmb(); /* paired with smp_rmb() in neigh_hh_lookup() */
+	n->hh	    = hh;
+
+	if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL))
+		hh_cache_put(hh);
+end:
+	write_unlock_bh(&n->lock);
 }
 
 /* This function can be used in contexts, where only old dev_queue_xmit
-   worked, f.e. if you want to override normal output path (eql, shaper),
-   but resolution is not made yet.
+ * worked, f.e. if you want to override normal output path (eql, shaper),
+ * but resolution is not made yet.
  */
 
 int neigh_compat_output(struct sk_buff *skb)
@@ -1210,19 +1312,19 @@
 	if (!neigh_event_send(neigh, skb)) {
 		int err;
 		struct net_device *dev = neigh->dev;
-		if (dev->header_ops->cache && !dst->hh) {
-			write_lock_bh(&neigh->lock);
-			if (!dst->hh)
-				neigh_hh_init(neigh, dst, dst->ops->protocol);
+		unsigned int seq;
+
+		if (dev->header_ops->cache &&
+		    !dst->hh &&
+		    !(dst->flags & DST_NOCACHE))
+			neigh_hh_init(neigh, dst, dst->ops->protocol);
+
+		do {
+			seq = read_seqbegin(&neigh->ha_lock);
 			err = dev_hard_header(skb, dev, ntohs(skb->protocol),
 					      neigh->ha, NULL, skb->len);
-			write_unlock_bh(&neigh->lock);
-		} else {
-			read_lock_bh(&neigh->lock);
-			err = dev_hard_header(skb, dev, ntohs(skb->protocol),
-					      neigh->ha, NULL, skb->len);
-			read_unlock_bh(&neigh->lock);
-		}
+		} while (read_seqretry(&neigh->ha_lock, seq));
+
 		if (err >= 0)
 			rc = neigh->ops->queue_xmit(skb);
 		else
@@ -1248,13 +1350,16 @@
 	struct dst_entry *dst = skb_dst(skb);
 	struct neighbour *neigh = dst->neighbour;
 	struct net_device *dev = neigh->dev;
+	unsigned int seq;
 
 	__skb_pull(skb, skb_network_offset(skb));
 
-	read_lock_bh(&neigh->lock);
-	err = dev_hard_header(skb, dev, ntohs(skb->protocol),
-			      neigh->ha, NULL, skb->len);
-	read_unlock_bh(&neigh->lock);
+	do {
+		seq = read_seqbegin(&neigh->ha_lock);
+		err = dev_hard_header(skb, dev, ntohs(skb->protocol),
+				      neigh->ha, NULL, skb->len);
+	} while (read_seqretry(&neigh->ha_lock, seq));
+
 	if (err >= 0)
 		err = neigh->ops->queue_xmit(skb);
 	else {
@@ -1436,17 +1541,14 @@
 		panic("cannot create neighbour proc dir entry");
 #endif
 
-	tbl->hash_mask = 1;
-	tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
+	tbl->nht = neigh_hash_alloc(8);
 
 	phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
 	tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
 
-	if (!tbl->hash_buckets || !tbl->phash_buckets)
+	if (!tbl->nht || !tbl->phash_buckets)
 		panic("cannot allocate neighbour cache hashes");
 
-	get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
-
 	rwlock_init(&tbl->lock);
 	INIT_DELAYED_WORK_DEFERRABLE(&tbl->gc_work, neigh_periodic_work);
 	schedule_delayed_work(&tbl->gc_work, tbl->parms.reachable_time);
@@ -1486,8 +1588,7 @@
 	struct neigh_table **tp;
 
 	/* It is not clean... Fix it to unload IPv6 module safely */
-	cancel_delayed_work(&tbl->gc_work);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&tbl->gc_work);
 	del_timer_sync(&tbl->proxy_timer);
 	pneigh_queue_purge(&tbl->proxy_queue);
 	neigh_ifdown(tbl, NULL);
@@ -1502,8 +1603,8 @@
 	}
 	write_unlock(&neigh_tbl_lock);
 
-	neigh_hash_free(tbl->hash_buckets, tbl->hash_mask + 1);
-	tbl->hash_buckets = NULL;
+	call_rcu(&tbl->nht->rcu, neigh_hash_free_rcu);
+	tbl->nht = NULL;
 
 	kfree(tbl->phash_buckets);
 	tbl->phash_buckets = NULL;
@@ -1529,6 +1630,7 @@
 	struct net_device *dev = NULL;
 	int err = -EINVAL;
 
+	ASSERT_RTNL();
 	if (nlmsg_len(nlh) < sizeof(*ndm))
 		goto out;
 
@@ -1538,7 +1640,7 @@
 
 	ndm = nlmsg_data(nlh);
 	if (ndm->ndm_ifindex) {
-		dev = dev_get_by_index(net, ndm->ndm_ifindex);
+		dev = __dev_get_by_index(net, ndm->ndm_ifindex);
 		if (dev == NULL) {
 			err = -ENODEV;
 			goto out;
@@ -1554,34 +1656,31 @@
 		read_unlock(&neigh_tbl_lock);
 
 		if (nla_len(dst_attr) < tbl->key_len)
-			goto out_dev_put;
+			goto out;
 
 		if (ndm->ndm_flags & NTF_PROXY) {
 			err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
-			goto out_dev_put;
+			goto out;
 		}
 
 		if (dev == NULL)
-			goto out_dev_put;
+			goto out;
 
 		neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
 		if (neigh == NULL) {
 			err = -ENOENT;
-			goto out_dev_put;
+			goto out;
 		}
 
 		err = neigh_update(neigh, NULL, NUD_FAILED,
 				   NEIGH_UPDATE_F_OVERRIDE |
 				   NEIGH_UPDATE_F_ADMIN);
 		neigh_release(neigh);
-		goto out_dev_put;
+		goto out;
 	}
 	read_unlock(&neigh_tbl_lock);
 	err = -EAFNOSUPPORT;
 
-out_dev_put:
-	if (dev)
-		dev_put(dev);
 out:
 	return err;
 }
@@ -1595,6 +1694,7 @@
 	struct net_device *dev = NULL;
 	int err;
 
+	ASSERT_RTNL();
 	err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
 	if (err < 0)
 		goto out;
@@ -1605,14 +1705,14 @@
 
 	ndm = nlmsg_data(nlh);
 	if (ndm->ndm_ifindex) {
-		dev = dev_get_by_index(net, ndm->ndm_ifindex);
+		dev = __dev_get_by_index(net, ndm->ndm_ifindex);
 		if (dev == NULL) {
 			err = -ENODEV;
 			goto out;
 		}
 
 		if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
-			goto out_dev_put;
+			goto out;
 	}
 
 	read_lock(&neigh_tbl_lock);
@@ -1626,7 +1726,7 @@
 		read_unlock(&neigh_tbl_lock);
 
 		if (nla_len(tb[NDA_DST]) < tbl->key_len)
-			goto out_dev_put;
+			goto out;
 		dst = nla_data(tb[NDA_DST]);
 		lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
 
@@ -1639,29 +1739,29 @@
 				pn->flags = ndm->ndm_flags;
 				err = 0;
 			}
-			goto out_dev_put;
+			goto out;
 		}
 
 		if (dev == NULL)
-			goto out_dev_put;
+			goto out;
 
 		neigh = neigh_lookup(tbl, dst, dev);
 		if (neigh == NULL) {
 			if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
 				err = -ENOENT;
-				goto out_dev_put;
+				goto out;
 			}
 
 			neigh = __neigh_lookup_errno(tbl, dst, dev);
 			if (IS_ERR(neigh)) {
 				err = PTR_ERR(neigh);
-				goto out_dev_put;
+				goto out;
 			}
 		} else {
 			if (nlh->nlmsg_flags & NLM_F_EXCL) {
 				err = -EEXIST;
 				neigh_release(neigh);
-				goto out_dev_put;
+				goto out;
 			}
 
 			if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
@@ -1674,15 +1774,11 @@
 		} else
 			err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
 		neigh_release(neigh);
-		goto out_dev_put;
+		goto out;
 	}
 
 	read_unlock(&neigh_tbl_lock);
 	err = -EAFNOSUPPORT;
-
-out_dev_put:
-	if (dev)
-		dev_put(dev);
 out:
 	return err;
 }
@@ -1748,18 +1844,22 @@
 		unsigned long now = jiffies;
 		unsigned int flush_delta = now - tbl->last_flush;
 		unsigned int rand_delta = now - tbl->last_rand;
-
+		struct neigh_hash_table *nht;
 		struct ndt_config ndc = {
 			.ndtc_key_len		= tbl->key_len,
 			.ndtc_entry_size	= tbl->entry_size,
 			.ndtc_entries		= atomic_read(&tbl->entries),
 			.ndtc_last_flush	= jiffies_to_msecs(flush_delta),
 			.ndtc_last_rand		= jiffies_to_msecs(rand_delta),
-			.ndtc_hash_rnd		= tbl->hash_rnd,
-			.ndtc_hash_mask		= tbl->hash_mask,
 			.ndtc_proxy_qlen	= tbl->proxy_queue.qlen,
 		};
 
+		rcu_read_lock_bh();
+		nht = rcu_dereference_bh(tbl->nht);
+		ndc.ndtc_hash_rnd = nht->hash_rnd;
+		ndc.ndtc_hash_mask = nht->hash_mask;
+		rcu_read_unlock_bh();
+
 		NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc);
 	}
 
@@ -2056,10 +2156,14 @@
 
 	read_lock_bh(&neigh->lock);
 	ndm->ndm_state	 = neigh->nud_state;
-	if ((neigh->nud_state & NUD_VALID) &&
-	    nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, neigh->ha) < 0) {
-		read_unlock_bh(&neigh->lock);
-		goto nla_put_failure;
+	if (neigh->nud_state & NUD_VALID) {
+		char haddr[MAX_ADDR_LEN];
+
+		neigh_ha_snapshot(haddr, neigh, neigh->dev);
+		if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
+			read_unlock_bh(&neigh->lock);
+			goto nla_put_failure;
+		}
 	}
 
 	ci.ndm_used	 = jiffies_to_clock_t(now - neigh->used);
@@ -2087,18 +2191,23 @@
 static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 			    struct netlink_callback *cb)
 {
-	struct net * net = sock_net(skb->sk);
+	struct net *net = sock_net(skb->sk);
 	struct neighbour *n;
 	int rc, h, s_h = cb->args[1];
 	int idx, s_idx = idx = cb->args[2];
+	struct neigh_hash_table *nht;
 
-	read_lock_bh(&tbl->lock);
-	for (h = 0; h <= tbl->hash_mask; h++) {
+	rcu_read_lock_bh();
+	nht = rcu_dereference_bh(tbl->nht);
+
+	for (h = 0; h <= nht->hash_mask; h++) {
 		if (h < s_h)
 			continue;
 		if (h > s_h)
 			s_idx = 0;
-		for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) {
+		for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
+		     n != NULL;
+		     n = rcu_dereference_bh(n->next)) {
 			if (!net_eq(dev_net(n->dev), net))
 				continue;
 			if (idx < s_idx)
@@ -2107,17 +2216,16 @@
 					    cb->nlh->nlmsg_seq,
 					    RTM_NEWNEIGH,
 					    NLM_F_MULTI) <= 0) {
-				read_unlock_bh(&tbl->lock);
 				rc = -1;
 				goto out;
 			}
-		next:
+next:
 			idx++;
 		}
 	}
-	read_unlock_bh(&tbl->lock);
 	rc = skb->len;
 out:
+	rcu_read_unlock_bh();
 	cb->args[1] = h;
 	cb->args[2] = idx;
 	return rc;
@@ -2150,15 +2258,22 @@
 void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
 {
 	int chain;
+	struct neigh_hash_table *nht;
 
-	read_lock_bh(&tbl->lock);
-	for (chain = 0; chain <= tbl->hash_mask; chain++) {
+	rcu_read_lock_bh();
+	nht = rcu_dereference_bh(tbl->nht);
+
+	read_lock(&tbl->lock); /* avoid resizes */
+	for (chain = 0; chain <= nht->hash_mask; chain++) {
 		struct neighbour *n;
 
-		for (n = tbl->hash_buckets[chain]; n; n = n->next)
+		for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
+		     n != NULL;
+		     n = rcu_dereference_bh(n->next))
 			cb(n, cookie);
 	}
-	read_unlock_bh(&tbl->lock);
+	read_unlock(&tbl->lock);
+	rcu_read_unlock_bh();
 }
 EXPORT_SYMBOL(neigh_for_each);
 
@@ -2167,18 +2282,25 @@
 			      int (*cb)(struct neighbour *))
 {
 	int chain;
+	struct neigh_hash_table *nht;
 
-	for (chain = 0; chain <= tbl->hash_mask; chain++) {
-		struct neighbour *n, **np;
+	nht = rcu_dereference_protected(tbl->nht,
+					lockdep_is_held(&tbl->lock));
+	for (chain = 0; chain <= nht->hash_mask; chain++) {
+		struct neighbour *n;
+		struct neighbour __rcu **np;
 
-		np = &tbl->hash_buckets[chain];
-		while ((n = *np) != NULL) {
+		np = &nht->hash_buckets[chain];
+		while ((n = rcu_dereference_protected(*np,
+					lockdep_is_held(&tbl->lock))) != NULL) {
 			int release;
 
 			write_lock(&n->lock);
 			release = cb(n);
 			if (release) {
-				*np = n->next;
+				rcu_assign_pointer(*np,
+					rcu_dereference_protected(n->next,
+						lockdep_is_held(&tbl->lock)));
 				n->dead = 1;
 			} else
 				np = &n->next;
@@ -2196,13 +2318,13 @@
 {
 	struct neigh_seq_state *state = seq->private;
 	struct net *net = seq_file_net(seq);
-	struct neigh_table *tbl = state->tbl;
+	struct neigh_hash_table *nht = state->nht;
 	struct neighbour *n = NULL;
 	int bucket = state->bucket;
 
 	state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
-	for (bucket = 0; bucket <= tbl->hash_mask; bucket++) {
-		n = tbl->hash_buckets[bucket];
+	for (bucket = 0; bucket <= nht->hash_mask; bucket++) {
+		n = rcu_dereference_bh(nht->hash_buckets[bucket]);
 
 		while (n) {
 			if (!net_eq(dev_net(n->dev), net))
@@ -2219,8 +2341,8 @@
 				break;
 			if (n->nud_state & ~NUD_NOARP)
 				break;
-		next:
-			n = n->next;
+next:
+			n = rcu_dereference_bh(n->next);
 		}
 
 		if (n)
@@ -2237,14 +2359,14 @@
 {
 	struct neigh_seq_state *state = seq->private;
 	struct net *net = seq_file_net(seq);
-	struct neigh_table *tbl = state->tbl;
+	struct neigh_hash_table *nht = state->nht;
 
 	if (state->neigh_sub_iter) {
 		void *v = state->neigh_sub_iter(state, n, pos);
 		if (v)
 			return n;
 	}
-	n = n->next;
+	n = rcu_dereference_bh(n->next);
 
 	while (1) {
 		while (n) {
@@ -2261,17 +2383,17 @@
 
 			if (n->nud_state & ~NUD_NOARP)
 				break;
-		next:
-			n = n->next;
+next:
+			n = rcu_dereference_bh(n->next);
 		}
 
 		if (n)
 			break;
 
-		if (++state->bucket > tbl->hash_mask)
+		if (++state->bucket > nht->hash_mask)
 			break;
 
-		n = tbl->hash_buckets[state->bucket];
+		n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
 	}
 
 	if (n && pos)
@@ -2369,7 +2491,7 @@
 }
 
 void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
-	__acquires(tbl->lock)
+	__acquires(rcu_bh)
 {
 	struct neigh_seq_state *state = seq->private;
 
@@ -2377,7 +2499,8 @@
 	state->bucket = 0;
 	state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
 
-	read_lock_bh(&tbl->lock);
+	rcu_read_lock_bh();
+	state->nht = rcu_dereference_bh(tbl->nht);
 
 	return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
 }
@@ -2411,12 +2534,9 @@
 EXPORT_SYMBOL(neigh_seq_next);
 
 void neigh_seq_stop(struct seq_file *seq, void *v)
-	__releases(tbl->lock)
+	__releases(rcu_bh)
 {
-	struct neigh_seq_state *state = seq->private;
-	struct neigh_table *tbl = state->tbl;
-
-	read_unlock_bh(&tbl->lock);
+	rcu_read_unlock_bh();
 }
 EXPORT_SYMBOL(neigh_seq_stop);
 
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index af4dfba..b143173 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -515,7 +515,7 @@
 	return attribute->store(queue, attribute, buf, count);
 }
 
-static struct sysfs_ops rx_queue_sysfs_ops = {
+static const struct sysfs_ops rx_queue_sysfs_ops = {
 	.show = rx_queue_attr_show,
 	.store = rx_queue_attr_store,
 };
@@ -726,6 +726,7 @@
 static int rx_queue_add_kobject(struct net_device *net, int index)
 {
 	struct netdev_rx_queue *queue = net->_rx + index;
+	struct netdev_rx_queue *first = queue->first;
 	struct kobject *kobj = &queue->kobj;
 	int error = 0;
 
@@ -738,38 +739,43 @@
 	}
 
 	kobject_uevent(kobj, KOBJ_ADD);
+	atomic_inc(&first->count);
+
+	return error;
+}
+
+int
+net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num)
+{
+	int i;
+	int error = 0;
+
+	for (i = old_num; i < new_num; i++) {
+		error = rx_queue_add_kobject(net, i);
+		if (error) {
+			new_num = old_num;
+			break;
+		}
+	}
+
+	while (--i >= new_num)
+		kobject_put(&net->_rx[i].kobj);
 
 	return error;
 }
 
 static int rx_queue_register_kobjects(struct net_device *net)
 {
-	int i;
-	int error = 0;
-
 	net->queues_kset = kset_create_and_add("queues",
 	    NULL, &net->dev.kobj);
 	if (!net->queues_kset)
 		return -ENOMEM;
-	for (i = 0; i < net->num_rx_queues; i++) {
-		error = rx_queue_add_kobject(net, i);
-		if (error)
-			break;
-	}
-
-	if (error)
-		while (--i >= 0)
-			kobject_put(&net->_rx[i].kobj);
-
-	return error;
+	return net_rx_queue_update_kobjects(net, 0, net->real_num_rx_queues);
 }
 
 static void rx_queue_remove_kobjects(struct net_device *net)
 {
-	int i;
-
-	for (i = 0; i < net->num_rx_queues; i++)
-		kobject_put(&net->_rx[i].kobj);
+	net_rx_queue_update_kobjects(net, net->real_num_rx_queues, 0);
 	kset_unregister(net->queues_kset);
 }
 #endif /* CONFIG_RPS */
@@ -789,12 +795,13 @@
 	return sock_net(sk);
 }
 
-static struct kobj_ns_type_operations net_ns_type_operations = {
+struct kobj_ns_type_operations net_ns_type_operations = {
 	.type = KOBJ_NS_TYPE_NET,
 	.current_ns = net_current_ns,
 	.netlink_ns = net_netlink_ns,
 	.initial_ns = net_initial_ns,
 };
+EXPORT_SYMBOL_GPL(net_ns_type_operations);
 
 static void net_kobj_ns_exit(struct net *net)
 {
diff --git a/net/core/net-sysfs.h b/net/core/net-sysfs.h
index 805555e..778e157 100644
--- a/net/core/net-sysfs.h
+++ b/net/core/net-sysfs.h
@@ -4,4 +4,8 @@
 int netdev_kobject_init(void);
 int netdev_register_kobject(struct net_device *);
 void netdev_unregister_kobject(struct net_device *);
+#ifdef CONFIG_RPS
+int net_rx_queue_update_kobjects(struct net_device *, int old_num, int new_num);
+#endif
+
 #endif
diff --git a/net/core/net-traces.c b/net/core/net-traces.c
index afa6380..7f1bb2a 100644
--- a/net/core/net-traces.c
+++ b/net/core/net-traces.c
@@ -26,6 +26,7 @@
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/skb.h>
+#include <trace/events/net.h>
 #include <trace/events/napi.h>
 
 EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 537e01a..4e98ffa 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -288,11 +288,11 @@
 	return 0;
 }
 
-void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
+void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
+			     struct net_device *dev)
 {
 	int status = NETDEV_TX_BUSY;
 	unsigned long tries;
-	struct net_device *dev = np->dev;
 	const struct net_device_ops *ops = dev->netdev_ops;
 	/* It is up to the caller to keep npinfo alive. */
 	struct netpoll_info *npinfo = np->dev->npinfo;
@@ -346,7 +346,7 @@
 		schedule_delayed_work(&npinfo->tx_work,0);
 	}
 }
-EXPORT_SYMBOL(netpoll_send_skb);
+EXPORT_SYMBOL(netpoll_send_skb_on_dev);
 
 void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 {
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 10a1ea7..2c0df0f 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -729,16 +729,14 @@
 	*num = 0;
 
 	for (; i < maxlen; i++) {
+		int value;
 		char c;
 		*num <<= 4;
 		if (get_user(c, &user_buffer[i]))
 			return -EFAULT;
-		if ((c >= '0') && (c <= '9'))
-			*num |= c - '0';
-		else if ((c >= 'a') && (c <= 'f'))
-			*num |= c - 'a' + 10;
-		else if ((c >= 'A') && (c <= 'F'))
-			*num |= c - 'A' + 10;
+		value = hex_to_bin(c);
+		if (value >= 0)
+			*num |= value;
 		else
 			break;
 	}
@@ -3907,8 +3905,6 @@
 {
 	struct pktgen_thread *t;
 	struct list_head *q, *n;
-	wait_queue_head_t queue;
-	init_waitqueue_head(&queue);
 
 	/* Stop all interfaces & threads */
 
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index f78d821..8121268 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -299,14 +299,6 @@
 	unregister_netdevice_many(&list_kill);
 }
 
-void rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
-{
-	rtnl_lock();
-	__rtnl_kill_links(net, ops);
-	rtnl_unlock();
-}
-EXPORT_SYMBOL_GPL(rtnl_kill_links);
-
 /**
  * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
  * @ops: struct rtnl_link_ops * to unregister
@@ -612,36 +604,7 @@
 
 static void copy_rtnl_link_stats64(void *v, const struct rtnl_link_stats64 *b)
 {
-	struct rtnl_link_stats64 a;
-
-	a.rx_packets = b->rx_packets;
-	a.tx_packets = b->tx_packets;
-	a.rx_bytes = b->rx_bytes;
-	a.tx_bytes = b->tx_bytes;
-	a.rx_errors = b->rx_errors;
-	a.tx_errors = b->tx_errors;
-	a.rx_dropped = b->rx_dropped;
-	a.tx_dropped = b->tx_dropped;
-
-	a.multicast = b->multicast;
-	a.collisions = b->collisions;
-
-	a.rx_length_errors = b->rx_length_errors;
-	a.rx_over_errors = b->rx_over_errors;
-	a.rx_crc_errors = b->rx_crc_errors;
-	a.rx_frame_errors = b->rx_frame_errors;
-	a.rx_fifo_errors = b->rx_fifo_errors;
-	a.rx_missed_errors = b->rx_missed_errors;
-
-	a.tx_aborted_errors = b->tx_aborted_errors;
-	a.tx_carrier_errors = b->tx_carrier_errors;
-	a.tx_fifo_errors = b->tx_fifo_errors;
-	a.tx_heartbeat_errors = b->tx_heartbeat_errors;
-	a.tx_window_errors = b->tx_window_errors;
-
-	a.rx_compressed = b->rx_compressed;
-	a.tx_compressed = b->tx_compressed;
-	memcpy(v, &a, sizeof(a));
+	memcpy(v, b, sizeof(*b));
 }
 
 /* All VF info */
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index c83b421..104f844 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -202,8 +202,6 @@
 	skb->data = data;
 	skb_reset_tail_pointer(skb);
 	skb->end = skb->tail + size;
-	kmemcheck_annotate_bitfield(skb, flags1);
-	kmemcheck_annotate_bitfield(skb, flags2);
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
 	skb->mac_header = ~0U;
 #endif
@@ -249,10 +247,9 @@
 struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
 		unsigned int length, gfp_t gfp_mask)
 {
-	int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
 	struct sk_buff *skb;
 
-	skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node);
+	skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, NUMA_NO_NODE);
 	if (likely(skb)) {
 		skb_reserve(skb, NET_SKB_PAD);
 		skb->dev = dev;
@@ -261,16 +258,6 @@
 }
 EXPORT_SYMBOL(__netdev_alloc_skb);
 
-struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask)
-{
-	int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
-	struct page *page;
-
-	page = alloc_pages_node(node, gfp_mask, 0);
-	return page;
-}
-EXPORT_SYMBOL(__netdev_alloc_page);
-
 void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
 		int size)
 {
@@ -340,7 +327,7 @@
 				put_page(skb_shinfo(skb)->frags[i].page);
 		}
 
-		if (skb_has_frags(skb))
+		if (skb_has_frag_list(skb))
 			skb_drop_fraglist(skb);
 
 		kfree(skb->head);
@@ -466,6 +453,7 @@
 		smp_rmb();
 	else if (likely(!atomic_dec_and_test(&skb->users)))
 		return;
+	trace_consume_skb(skb);
 	__kfree_skb(skb);
 }
 EXPORT_SYMBOL(consume_skb);
@@ -685,16 +673,10 @@
 
 struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
 {
-	int headerlen = skb->data - skb->head;
-	/*
-	 *	Allocate the copy buffer
-	 */
-	struct sk_buff *n;
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-	n = alloc_skb(skb->end + skb->data_len, gfp_mask);
-#else
-	n = alloc_skb(skb->end - skb->head + skb->data_len, gfp_mask);
-#endif
+	int headerlen = skb_headroom(skb);
+	unsigned int size = (skb_end_pointer(skb) - skb->head) + skb->data_len;
+	struct sk_buff *n = alloc_skb(size, gfp_mask);
+
 	if (!n)
 		return NULL;
 
@@ -726,20 +708,14 @@
 
 struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)
 {
-	/*
-	 *	Allocate the copy buffer
-	 */
-	struct sk_buff *n;
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-	n = alloc_skb(skb->end, gfp_mask);
-#else
-	n = alloc_skb(skb->end - skb->head, gfp_mask);
-#endif
+	unsigned int size = skb_end_pointer(skb) - skb->head;
+	struct sk_buff *n = alloc_skb(size, gfp_mask);
+
 	if (!n)
 		goto out;
 
 	/* Set the data pointer */
-	skb_reserve(n, skb->data - skb->head);
+	skb_reserve(n, skb_headroom(skb));
 	/* Set the tail pointer and length */
 	skb_put(n, skb_headlen(skb));
 	/* Copy the bytes */
@@ -759,7 +735,7 @@
 		skb_shinfo(n)->nr_frags = i;
 	}
 
-	if (skb_has_frags(skb)) {
+	if (skb_has_frag_list(skb)) {
 		skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list;
 		skb_clone_fraglist(n);
 	}
@@ -791,12 +767,9 @@
 {
 	int i;
 	u8 *data;
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-	int size = nhead + skb->end + ntail;
-#else
-	int size = nhead + (skb->end - skb->head) + ntail;
-#endif
+	int size = nhead + (skb_end_pointer(skb) - skb->head) + ntail;
 	long off;
+	bool fastpath;
 
 	BUG_ON(nhead < 0);
 
@@ -810,23 +783,36 @@
 		goto nodata;
 
 	/* Copy only real data... and, alas, header. This should be
-	 * optimized for the cases when header is void. */
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-	memcpy(data + nhead, skb->head, skb->tail);
-#else
-	memcpy(data + nhead, skb->head, skb->tail - skb->head);
-#endif
-	memcpy(data + size, skb_end_pointer(skb),
+	 * optimized for the cases when header is void.
+	 */
+	memcpy(data + nhead, skb->head, skb_tail_pointer(skb) - skb->head);
+
+	memcpy((struct skb_shared_info *)(data + size),
+	       skb_shinfo(skb),
 	       offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags]));
 
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-		get_page(skb_shinfo(skb)->frags[i].page);
+	/* Check if we can avoid taking references on fragments if we own
+	 * the last reference on skb->head. (see skb_release_data())
+	 */
+	if (!skb->cloned)
+		fastpath = true;
+	else {
+		int delta = skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1;
 
-	if (skb_has_frags(skb))
-		skb_clone_fraglist(skb);
+		fastpath = atomic_read(&skb_shinfo(skb)->dataref) == delta;
+	}
 
-	skb_release_data(skb);
+	if (fastpath) {
+		kfree(skb->head);
+	} else {
+		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+			get_page(skb_shinfo(skb)->frags[i].page);
 
+		if (skb_has_frag_list(skb))
+			skb_clone_fraglist(skb);
+
+		skb_release_data(skb);
+	}
 	off = (data + nhead) - skb->head;
 
 	skb->head     = data;
@@ -1099,7 +1085,7 @@
 		for (; i < nfrags; i++)
 			put_page(skb_shinfo(skb)->frags[i].page);
 
-		if (skb_has_frags(skb))
+		if (skb_has_frag_list(skb))
 			skb_drop_fraglist(skb);
 		goto done;
 	}
@@ -1194,7 +1180,7 @@
 	/* Optimization: no fragments, no reasons to preestimate
 	 * size of pulled pages. Superb.
 	 */
-	if (!skb_has_frags(skb))
+	if (!skb_has_frag_list(skb))
 		goto pull_pages;
 
 	/* Estimate size of pulled pages. */
@@ -2323,7 +2309,7 @@
 		st->frag_data = NULL;
 	}
 
-	if (st->root_skb == st->cur_skb && skb_has_frags(st->root_skb)) {
+	if (st->root_skb == st->cur_skb && skb_has_frag_list(st->root_skb)) {
 		st->cur_skb = skb_shinfo(st->root_skb)->frag_list;
 		st->frag_idx = 0;
 		goto next_skb;
@@ -2893,7 +2879,7 @@
 		return -ENOMEM;
 
 	/* Easy case. Most of packets will go this way. */
-	if (!skb_has_frags(skb)) {
+	if (!skb_has_frag_list(skb)) {
 		/* A little of trouble, not enough of space for trailer.
 		 * This should not happen, when stack is tuned to generate
 		 * good frames. OK, on miss we reallocate and reserve even more
@@ -2928,7 +2914,7 @@
 
 		if (skb1->next == NULL && tailbits) {
 			if (skb_shinfo(skb1)->nr_frags ||
-			    skb_has_frags(skb1) ||
+			    skb_has_frag_list(skb1) ||
 			    skb_tailroom(skb1) < tailbits)
 				ntail = tailbits + 128;
 		}
@@ -2937,7 +2923,7 @@
 		    skb_cloned(skb1) ||
 		    ntail ||
 		    skb_shinfo(skb1)->nr_frags ||
-		    skb_has_frags(skb1)) {
+		    skb_has_frag_list(skb1)) {
 			struct sk_buff *skb2;
 
 			/* Fuck, we are miserable poor guys... */
@@ -3020,7 +3006,7 @@
 	} else {
 		/*
 		 * no hardware time stamps available,
-		 * so keep the skb_shared_tx and only
+		 * so keep the shared tx_flags and only
 		 * store software time stamp
 		 */
 		skb->tstamp = ktime_get_real();
diff --git a/net/core/sock.c b/net/core/sock.c
index b05b9b6..11db436 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1078,8 +1078,11 @@
 #ifdef CONFIG_CGROUPS
 void sock_update_classid(struct sock *sk)
 {
-	u32 classid = task_cls_classid(current);
+	u32 classid;
 
+	rcu_read_lock();  /* doing current task, which cannot vanish. */
+	classid = task_cls_classid(current);
+	rcu_read_unlock();
 	if (classid && classid != sk->sk_classid)
 		sk->sk_classid = classid;
 }
@@ -1351,9 +1354,9 @@
 {
 	int uid;
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : 0;
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 	return uid;
 }
 EXPORT_SYMBOL(sock_i_uid);
@@ -1362,9 +1365,9 @@
 {
 	unsigned long ino;
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0;
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 	return ino;
 }
 EXPORT_SYMBOL(sock_i_ino);
@@ -1557,6 +1560,8 @@
 EXPORT_SYMBOL(sock_alloc_send_skb);
 
 static void __lock_sock(struct sock *sk)
+	__releases(&sk->sk_lock.slock)
+	__acquires(&sk->sk_lock.slock)
 {
 	DEFINE_WAIT(wait);
 
@@ -1573,6 +1578,8 @@
 }
 
 static void __release_sock(struct sock *sk)
+	__releases(&sk->sk_lock.slock)
+	__acquires(&sk->sk_lock.slock)
 {
 	struct sk_buff *skb = sk->sk_backlog.head;
 
diff --git a/net/core/stream.c b/net/core/stream.c
index d959e0f..f5df85d 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -141,10 +141,10 @@
 
 		set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 		sk->sk_write_pending++;
-		sk_wait_event(sk, &current_timeo, !sk->sk_err &&
-						  !(sk->sk_shutdown & SEND_SHUTDOWN) &&
-						  sk_stream_memory_free(sk) &&
-						  vm_wait);
+		sk_wait_event(sk, &current_timeo, sk->sk_err ||
+						  (sk->sk_shutdown & SEND_SHUTDOWN) ||
+						  (sk_stream_memory_free(sk) &&
+						  !vm_wait));
 		sk->sk_write_pending--;
 
 		if (vm_wait) {
diff --git a/net/core/utils.c b/net/core/utils.c
index f418544..5fea0ab 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -75,7 +75,7 @@
 				str++;
 		}
 	}
-	return(htonl(l));
+	return htonl(l);
 }
 EXPORT_SYMBOL(in_aton);
 
@@ -92,18 +92,19 @@
 
 static inline int xdigit2bin(char c, int delim)
 {
+	int val;
+
 	if (c == delim || c == '\0')
 		return IN6PTON_DELIM;
 	if (c == ':')
 		return IN6PTON_COLON_MASK;
 	if (c == '.')
 		return IN6PTON_DOT;
-	if (c >= '0' && c <= '9')
-		return (IN6PTON_XDIGIT | IN6PTON_DIGIT| (c - '0'));
-	if (c >= 'a' && c <= 'f')
-		return (IN6PTON_XDIGIT | (c - 'a' + 10));
-	if (c >= 'A' && c <= 'F')
-		return (IN6PTON_XDIGIT | (c - 'A' + 10));
+
+	val = hex_to_bin(c);
+	if (val >= 0)
+		return val | IN6PTON_XDIGIT | (val < 10 ? IN6PTON_DIGIT : 0);
+
 	if (delim == -1)
 		return IN6PTON_DELIM;
 	return IN6PTON_UNKNOWN;
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index 6df6f8a..117fb09 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -62,22 +62,18 @@
 	void		(*ccid_hc_tx_exit)(struct sock *sk);
 	void		(*ccid_hc_rx_packet_recv)(struct sock *sk,
 						  struct sk_buff *skb);
-	int		(*ccid_hc_rx_parse_options)(struct sock *sk,
-						    unsigned char option,
-						    unsigned char len, u16 idx,
-						    unsigned char* value);
+	int		(*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt,
+						    u8 opt, u8 *val, u8 len);
 	int		(*ccid_hc_rx_insert_options)(struct sock *sk,
 						     struct sk_buff *skb);
 	void		(*ccid_hc_tx_packet_recv)(struct sock *sk,
 						  struct sk_buff *skb);
-	int		(*ccid_hc_tx_parse_options)(struct sock *sk,
-						    unsigned char option,
-						    unsigned char len, u16 idx,
-						    unsigned char* value);
+	int		(*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt,
+						    u8 opt, u8 *val, u8 len);
 	int		(*ccid_hc_tx_send_packet)(struct sock *sk,
 						  struct sk_buff *skb);
 	void		(*ccid_hc_tx_packet_sent)(struct sock *sk,
-						  int more, unsigned int len);
+						  unsigned int len);
 	void		(*ccid_hc_rx_get_info)(struct sock *sk,
 					       struct tcp_info *info);
 	void		(*ccid_hc_tx_get_info)(struct sock *sk,
@@ -148,10 +144,10 @@
 }
 
 static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
-					  int more, unsigned int len)
+					  unsigned int len)
 {
 	if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
-		ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, more, len);
+		ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, len);
 }
 
 static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
@@ -168,27 +164,31 @@
 		ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
 }
 
+/**
+ * ccid_hc_tx_parse_options  -  Parse CCID-specific options sent by the receiver
+ * @pkt: type of packet that @opt appears on (RFC 4340, 5.1)
+ * @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3)
+ * @val: value of @opt
+ * @len: length of @val in bytes
+ */
 static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
-					   unsigned char option,
-					   unsigned char len, u16 idx,
-					   unsigned char* value)
+					   u8 pkt, u8 opt, u8 *val, u8 len)
 {
-	int rc = 0;
-	if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL)
-		rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx,
-						    value);
-	return rc;
+	if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL)
+		return 0;
+	return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
 }
 
+/**
+ * ccid_hc_rx_parse_options  -  Parse CCID-specific options sent by the sender
+ * Arguments are analogous to ccid_hc_tx_parse_options()
+ */
 static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
-					   unsigned char option,
-					   unsigned char len, u16 idx,
-					   unsigned char* value)
+					   u8 pkt, u8 opt, u8 *val, u8 len)
 {
-	int rc = 0;
-	if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL)
-		rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value);
-	return rc;
+	if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL)
+		return 0;
+	return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
 }
 
 static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig
index 8408398..0581143 100644
--- a/net/dccp/ccids/Kconfig
+++ b/net/dccp/ccids/Kconfig
@@ -47,37 +47,6 @@
 
 	  If in doubt, say N.
 
-config IP_DCCP_CCID3_RTO
-	  int "Use higher bound for nofeedback timer"
-	  default 100
-	  depends on IP_DCCP_CCID3 && EXPERIMENTAL
-	  ---help---
-	    Use higher lower bound for nofeedback timer expiration.
-
-	    The TFRC nofeedback timer normally expires after the maximum of 4
-	    RTTs and twice the current send interval (RFC 3448, 4.3). On LANs
-	    with a small RTT this can mean a high processing load and reduced
-	    performance, since then the nofeedback timer is triggered very
-	    frequently.
-
-	    This option enables to set a higher lower bound for the nofeedback
-	    value. Values in units of milliseconds can be set here.
-
-	    A value of 0 disables this feature by enforcing the value specified
-	    in RFC 3448. The following values have been suggested as bounds for
-	    experimental use:
-		* 16-20ms to match the typical multimedia inter-frame interval
-		* 100ms as a reasonable compromise [default]
-		* 1000ms corresponds to the lower TCP RTO bound (RFC 2988, 2.4)
-
-	    The default of 100ms is a compromise between a large value for
-	    efficient DCCP implementations, and a small value to avoid disrupting
-	    the network in times of congestion.
-
-	    The purpose of the nofeedback timer is to slow DCCP down when there
-	    is serious network congestion: experimenting with larger values should
-	    therefore not be performed on WANs.
-
 config IP_DCCP_TFRC_LIB
 	def_bool y if IP_DCCP_CCID3
 
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 9b3ae99..d850e29 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -25,59 +25,14 @@
  */
 #include <linux/slab.h>
 #include "../feat.h"
-#include "../ccid.h"
-#include "../dccp.h"
 #include "ccid2.h"
 
 
 #ifdef CONFIG_IP_DCCP_CCID2_DEBUG
 static int ccid2_debug;
 #define ccid2_pr_debug(format, a...)	DCCP_PR_DEBUG(ccid2_debug, format, ##a)
-
-static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hc)
-{
-	int len = 0;
-	int pipe = 0;
-	struct ccid2_seq *seqp = hc->tx_seqh;
-
-	/* there is data in the chain */
-	if (seqp != hc->tx_seqt) {
-		seqp = seqp->ccid2s_prev;
-		len++;
-		if (!seqp->ccid2s_acked)
-			pipe++;
-
-		while (seqp != hc->tx_seqt) {
-			struct ccid2_seq *prev = seqp->ccid2s_prev;
-
-			len++;
-			if (!prev->ccid2s_acked)
-				pipe++;
-
-			/* packets are sent sequentially */
-			BUG_ON(dccp_delta_seqno(seqp->ccid2s_seq,
-						prev->ccid2s_seq ) >= 0);
-			BUG_ON(time_before(seqp->ccid2s_sent,
-					   prev->ccid2s_sent));
-
-			seqp = prev;
-		}
-	}
-
-	BUG_ON(pipe != hc->tx_pipe);
-	ccid2_pr_debug("len of chain=%d\n", len);
-
-	do {
-		seqp = seqp->ccid2s_prev;
-		len++;
-	} while (seqp != hc->tx_seqh);
-
-	ccid2_pr_debug("total len=%d\n", len);
-	BUG_ON(len != hc->tx_seqbufc * CCID2_SEQBUF_LEN);
-}
 #else
 #define ccid2_pr_debug(format, a...)
-#define ccid2_hc_tx_check_sanity(hc)
 #endif
 
 static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hc)
@@ -156,19 +111,10 @@
 	dp->dccps_l_ack_ratio = val;
 }
 
-static void ccid2_change_srtt(struct ccid2_hc_tx_sock *hc, long val)
-{
-	ccid2_pr_debug("change SRTT to %ld\n", val);
-	hc->tx_srtt = val;
-}
-
-static void ccid2_start_rto_timer(struct sock *sk);
-
 static void ccid2_hc_tx_rto_expire(unsigned long data)
 {
 	struct sock *sk = (struct sock *)data;
 	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
-	long s;
 
 	bh_lock_sock(sk);
 	if (sock_owned_by_user(sk)) {
@@ -178,23 +124,19 @@
 
 	ccid2_pr_debug("RTO_EXPIRE\n");
 
-	ccid2_hc_tx_check_sanity(hc);
-
 	/* back-off timer */
 	hc->tx_rto <<= 1;
+	if (hc->tx_rto > DCCP_RTO_MAX)
+		hc->tx_rto = DCCP_RTO_MAX;
 
-	s = hc->tx_rto / HZ;
-	if (s > 60)
-		hc->tx_rto = 60 * HZ;
-
-	ccid2_start_rto_timer(sk);
+	sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
 
 	/* adjust pipe, cwnd etc */
 	hc->tx_ssthresh = hc->tx_cwnd / 2;
 	if (hc->tx_ssthresh < 2)
 		hc->tx_ssthresh = 2;
-	hc->tx_cwnd	 = 1;
-	hc->tx_pipe	 = 0;
+	hc->tx_cwnd	= 1;
+	hc->tx_pipe	= 0;
 
 	/* clear state about stuff we sent */
 	hc->tx_seqt = hc->tx_seqh;
@@ -204,23 +146,12 @@
 	hc->tx_rpseq    = 0;
 	hc->tx_rpdupack = -1;
 	ccid2_change_l_ack_ratio(sk, 1);
-	ccid2_hc_tx_check_sanity(hc);
 out:
 	bh_unlock_sock(sk);
 	sock_put(sk);
 }
 
-static void ccid2_start_rto_timer(struct sock *sk)
-{
-	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
-
-	ccid2_pr_debug("setting RTO timeout=%ld\n", hc->tx_rto);
-
-	BUG_ON(timer_pending(&hc->tx_rtotimer));
-	sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
-}
-
-static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)
+static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
 {
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
@@ -230,7 +161,7 @@
 
 	hc->tx_seqh->ccid2s_seq   = dp->dccps_gss;
 	hc->tx_seqh->ccid2s_acked = 0;
-	hc->tx_seqh->ccid2s_sent  = jiffies;
+	hc->tx_seqh->ccid2s_sent  = ccid2_time_stamp;
 
 	next = hc->tx_seqh->ccid2s_next;
 	/* check if we need to alloc more space */
@@ -296,23 +227,20 @@
 	}
 #endif
 
-	/* setup RTO timer */
-	if (!timer_pending(&hc->tx_rtotimer))
-		ccid2_start_rto_timer(sk);
+	sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
 
 #ifdef CONFIG_IP_DCCP_CCID2_DEBUG
 	do {
 		struct ccid2_seq *seqp = hc->tx_seqt;
 
 		while (seqp != hc->tx_seqh) {
-			ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",
+			ccid2_pr_debug("out seq=%llu acked=%d time=%u\n",
 				       (unsigned long long)seqp->ccid2s_seq,
 				       seqp->ccid2s_acked, seqp->ccid2s_sent);
 			seqp = seqp->ccid2s_next;
 		}
 	} while (0);
 	ccid2_pr_debug("=========\n");
-	ccid2_hc_tx_check_sanity(hc);
 #endif
 }
 
@@ -378,17 +306,87 @@
 	return -1;
 }
 
-static void ccid2_hc_tx_kill_rto_timer(struct sock *sk)
+/**
+ * ccid2_rtt_estimator - Sample RTT and compute RTO using RFC2988 algorithm
+ * This code is almost identical with TCP's tcp_rtt_estimator(), since
+ * - it has a higher sampling frequency (recommended by RFC 1323),
+ * - the RTO does not collapse into RTT due to RTTVAR going towards zero,
+ * - it is simple (cf. more complex proposals such as Eifel timer or research
+ *   which suggests that the gain should be set according to window size),
+ * - in tests it was found to work well with CCID2 [gerrit].
+ */
+static void ccid2_rtt_estimator(struct sock *sk, const long mrtt)
 {
 	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
+	long m = mrtt ? : 1;
 
-	sk_stop_timer(sk, &hc->tx_rtotimer);
-	ccid2_pr_debug("deleted RTO timer\n");
+	if (hc->tx_srtt == 0) {
+		/* First measurement m */
+		hc->tx_srtt = m << 3;
+		hc->tx_mdev = m << 1;
+
+		hc->tx_mdev_max = max(hc->tx_mdev, tcp_rto_min(sk));
+		hc->tx_rttvar   = hc->tx_mdev_max;
+
+		hc->tx_rtt_seq  = dccp_sk(sk)->dccps_gss;
+	} else {
+		/* Update scaled SRTT as SRTT += 1/8 * (m - SRTT) */
+		m -= (hc->tx_srtt >> 3);
+		hc->tx_srtt += m;
+
+		/* Similarly, update scaled mdev with regard to |m| */
+		if (m < 0) {
+			m = -m;
+			m -= (hc->tx_mdev >> 2);
+			/*
+			 * This neutralises RTO increase when RTT < SRTT - mdev
+			 * (see P. Sarolahti, A. Kuznetsov,"Congestion Control
+			 * in Linux TCP", USENIX 2002, pp. 49-62).
+			 */
+			if (m > 0)
+				m >>= 3;
+		} else {
+			m -= (hc->tx_mdev >> 2);
+		}
+		hc->tx_mdev += m;
+
+		if (hc->tx_mdev > hc->tx_mdev_max) {
+			hc->tx_mdev_max = hc->tx_mdev;
+			if (hc->tx_mdev_max > hc->tx_rttvar)
+				hc->tx_rttvar = hc->tx_mdev_max;
+		}
+
+		/*
+		 * Decay RTTVAR at most once per flight, exploiting that
+		 *  1) pipe <= cwnd <= Sequence_Window = W  (RFC 4340, 7.5.2)
+		 *  2) AWL = GSS-W+1 <= GAR <= GSS          (RFC 4340, 7.5.1)
+		 * GAR is a useful bound for FlightSize = pipe.
+		 * AWL is probably too low here, as it over-estimates pipe.
+		 */
+		if (after48(dccp_sk(sk)->dccps_gar, hc->tx_rtt_seq)) {
+			if (hc->tx_mdev_max < hc->tx_rttvar)
+				hc->tx_rttvar -= (hc->tx_rttvar -
+						  hc->tx_mdev_max) >> 2;
+			hc->tx_rtt_seq  = dccp_sk(sk)->dccps_gss;
+			hc->tx_mdev_max = tcp_rto_min(sk);
+		}
+	}
+
+	/*
+	 * Set RTO from SRTT and RTTVAR
+	 * As in TCP, 4 * RTTVAR >= TCP_RTO_MIN, giving a minimum RTO of 200 ms.
+	 * This agrees with RFC 4341, 5:
+	 *	"Because DCCP does not retransmit data, DCCP does not require
+	 *	 TCP's recommended minimum timeout of one second".
+	 */
+	hc->tx_rto = (hc->tx_srtt >> 3) + hc->tx_rttvar;
+
+	if (hc->tx_rto > DCCP_RTO_MAX)
+		hc->tx_rto = DCCP_RTO_MAX;
 }
 
-static inline void ccid2_new_ack(struct sock *sk,
-				 struct ccid2_seq *seqp,
-				 unsigned int *maxincr)
+static void ccid2_new_ack(struct sock *sk, struct ccid2_seq *seqp,
+			  unsigned int *maxincr)
 {
 	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
 
@@ -402,93 +400,27 @@
 			hc->tx_cwnd += 1;
 			hc->tx_packets_acked = 0;
 	}
-
-	/* update RTO */
-	if (hc->tx_srtt == -1 ||
-	    time_after(jiffies, hc->tx_lastrtt + hc->tx_srtt)) {
-		unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent;
-		int s;
-
-		/* first measurement */
-		if (hc->tx_srtt == -1) {
-			ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
-				       r, jiffies,
-				       (unsigned long long)seqp->ccid2s_seq);
-			ccid2_change_srtt(hc, r);
-			hc->tx_rttvar = r >> 1;
-		} else {
-			/* RTTVAR */
-			long tmp = hc->tx_srtt - r;
-			long srtt;
-
-			if (tmp < 0)
-				tmp *= -1;
-
-			tmp >>= 2;
-			hc->tx_rttvar *= 3;
-			hc->tx_rttvar >>= 2;
-			hc->tx_rttvar += tmp;
-
-			/* SRTT */
-			srtt = hc->tx_srtt;
-			srtt *= 7;
-			srtt >>= 3;
-			tmp = r >> 3;
-			srtt += tmp;
-			ccid2_change_srtt(hc, srtt);
-		}
-		s = hc->tx_rttvar << 2;
-		/* clock granularity is 1 when based on jiffies */
-		if (!s)
-			s = 1;
-		hc->tx_rto = hc->tx_srtt + s;
-
-		/* must be at least a second */
-		s = hc->tx_rto / HZ;
-		/* DCCP doesn't require this [but I like it cuz my code sux] */
-#if 1
-		if (s < 1)
-			hc->tx_rto = HZ;
-#endif
-		/* max 60 seconds */
-		if (s > 60)
-			hc->tx_rto = HZ * 60;
-
-		hc->tx_lastrtt = jiffies;
-
-		ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n",
-			       hc->tx_srtt, hc->tx_rttvar,
-			       hc->tx_rto, HZ, r);
-	}
-
-	/* we got a new ack, so re-start RTO timer */
-	ccid2_hc_tx_kill_rto_timer(sk);
-	ccid2_start_rto_timer(sk);
-}
-
-static void ccid2_hc_tx_dec_pipe(struct sock *sk)
-{
-	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
-
-	if (hc->tx_pipe == 0)
-		DCCP_BUG("pipe == 0");
-	else
-		hc->tx_pipe--;
-
-	if (hc->tx_pipe == 0)
-		ccid2_hc_tx_kill_rto_timer(sk);
+	/*
+	 * FIXME: RTT is sampled several times per acknowledgment (for each
+	 * entry in the Ack Vector), instead of once per Ack (as in TCP SACK).
+	 * This causes the RTT to be over-estimated, since the older entries
+	 * in the Ack Vector have earlier sending times.
+	 * The cleanest solution is to not use the ccid2s_sent field at all
+	 * and instead use DCCP timestamps: requires changes in other places.
+	 */
+	ccid2_rtt_estimator(sk, ccid2_time_stamp - seqp->ccid2s_sent);
 }
 
 static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp)
 {
 	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
 
-	if (time_before(seqp->ccid2s_sent, hc->tx_last_cong)) {
+	if ((s32)(seqp->ccid2s_sent - hc->tx_last_cong) < 0) {
 		ccid2_pr_debug("Multiple losses in an RTT---treating as one\n");
 		return;
 	}
 
-	hc->tx_last_cong = jiffies;
+	hc->tx_last_cong = ccid2_time_stamp;
 
 	hc->tx_cwnd      = hc->tx_cwnd / 2 ? : 1U;
 	hc->tx_ssthresh  = max(hc->tx_cwnd, 2U);
@@ -510,7 +442,6 @@
 	int done = 0;
 	unsigned int maxincr = 0;
 
-	ccid2_hc_tx_check_sanity(hc);
 	/* check reverse path congestion */
 	seqno = DCCP_SKB_CB(skb)->dccpd_seq;
 
@@ -620,7 +551,7 @@
 					seqp->ccid2s_acked = 1;
 					ccid2_pr_debug("Got ack for %llu\n",
 						       (unsigned long long)seqp->ccid2s_seq);
-					ccid2_hc_tx_dec_pipe(sk);
+					hc->tx_pipe--;
 				}
 				if (seqp == hc->tx_seqt) {
 					done = 1;
@@ -677,7 +608,7 @@
 				 * one ack vector.
 				 */
 				ccid2_congestion_event(sk, seqp);
-				ccid2_hc_tx_dec_pipe(sk);
+				hc->tx_pipe--;
 			}
 			if (seqp == hc->tx_seqt)
 				break;
@@ -695,7 +626,11 @@
 		hc->tx_seqt = hc->tx_seqt->ccid2s_next;
 	}
 
-	ccid2_hc_tx_check_sanity(hc);
+	/* restart RTO timer if not all outstanding data has been acked */
+	if (hc->tx_pipe == 0)
+		sk_stop_timer(sk, &hc->tx_rtotimer);
+	else
+		sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
 }
 
 static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
@@ -707,12 +642,8 @@
 	/* RFC 4341, 5: initialise ssthresh to arbitrarily high (max) value */
 	hc->tx_ssthresh = ~0U;
 
-	/*
-	 * RFC 4341, 5: "The cwnd parameter is initialized to at most four
-	 * packets for new connections, following the rules from [RFC3390]".
-	 * We need to convert the bytes of RFC3390 into the packets of RFC 4341.
-	 */
-	hc->tx_cwnd = clamp(4380U / dp->dccps_mss_cache, 2U, 4U);
+	/* Use larger initial windows (RFC 4341, section 5). */
+	hc->tx_cwnd = rfc3390_bytes_to_packets(dp->dccps_mss_cache);
 
 	/* Make sure that Ack Ratio is enabled and within bounds. */
 	max_ratio = DIV_ROUND_UP(hc->tx_cwnd, 2);
@@ -723,15 +654,11 @@
 	if (ccid2_hc_tx_alloc_seq(hc))
 		return -ENOMEM;
 
-	hc->tx_rto	 = 3 * HZ;
-	ccid2_change_srtt(hc, -1);
-	hc->tx_rttvar    = -1;
+	hc->tx_rto	 = DCCP_TIMEOUT_INIT;
 	hc->tx_rpdupack  = -1;
-	hc->tx_last_cong = jiffies;
+	hc->tx_last_cong = ccid2_time_stamp;
 	setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire,
 			(unsigned long)sk);
-
-	ccid2_hc_tx_check_sanity(hc);
 	return 0;
 }
 
@@ -740,7 +667,7 @@
 	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
 	int i;
 
-	ccid2_hc_tx_kill_rto_timer(sk);
+	sk_stop_timer(sk, &hc->tx_rtotimer);
 
 	for (i = 0; i < hc->tx_seqbufc; i++)
 		kfree(hc->tx_seqbuf[i]);
diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h
index 1ec6a30..9731c2d 100644
--- a/net/dccp/ccids/ccid2.h
+++ b/net/dccp/ccids/ccid2.h
@@ -18,18 +18,23 @@
 #ifndef _DCCP_CCID2_H_
 #define _DCCP_CCID2_H_
 
-#include <linux/dccp.h>
 #include <linux/timer.h>
 #include <linux/types.h>
 #include "../ccid.h"
+#include "../dccp.h"
+
+/*
+ * CCID-2 timestamping faces the same issues as TCP timestamping.
+ * Hence we reuse/share as much of the code as possible.
+ */
+#define ccid2_time_stamp	tcp_time_stamp
+
 /* NUMDUPACK parameter from RFC 4341, p. 6 */
 #define NUMDUPACK	3
 
-struct sock;
-
 struct ccid2_seq {
 	u64			ccid2s_seq;
-	unsigned long		ccid2s_sent;
+	u32			ccid2s_sent;
 	int			ccid2s_acked;
 	struct ccid2_seq	*ccid2s_prev;
 	struct ccid2_seq	*ccid2s_next;
@@ -42,7 +47,12 @@
  * struct ccid2_hc_tx_sock - CCID2 TX half connection
  * @tx_{cwnd,ssthresh,pipe}: as per RFC 4341, section 5
  * @tx_packets_acked:	     Ack counter for deriving cwnd growth (RFC 3465)
- * @tx_lastrtt:		     time RTT was last measured
+ * @tx_srtt:		     smoothed RTT estimate, scaled by 2^3
+ * @tx_mdev:		     smoothed RTT variation, scaled by 2^2
+ * @tx_mdev_max:	     maximum of @mdev during one flight
+ * @tx_rttvar:		     moving average/maximum of @mdev_max
+ * @tx_rto:		     RTO value deriving from SRTT and RTTVAR (RFC 2988)
+ * @tx_rtt_seq:		     to decay RTTVAR at most once per flight
  * @tx_rpseq:		     last consecutive seqno
  * @tx_rpdupack:	     dupacks since rpseq
  */
@@ -55,14 +65,19 @@
 	int			tx_seqbufc;
 	struct ccid2_seq	*tx_seqh;
 	struct ccid2_seq	*tx_seqt;
-	long			tx_rto;
-	long			tx_srtt;
-	long			tx_rttvar;
-	unsigned long		tx_lastrtt;
+
+	/* RTT measurement: variables/principles are the same as in TCP */
+	u32			tx_srtt,
+				tx_mdev,
+				tx_mdev_max,
+				tx_rttvar,
+				tx_rto;
+	u64			tx_rtt_seq:48;
 	struct timer_list	tx_rtotimer;
+
 	u64			tx_rpseq;
 	int			tx_rpdupack;
-	unsigned long		tx_last_cong;
+	u32			tx_last_cong;
 	u64			tx_high_ack;
 };
 
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 95f7529..3060a60 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -54,7 +54,6 @@
 	[TFRC_SSTATE_NO_SENT]  = "NO_SENT",
 	[TFRC_SSTATE_NO_FBACK] = "NO_FBACK",
 	[TFRC_SSTATE_FBACK]    = "FBACK",
-	[TFRC_SSTATE_TERM]     = "TERM",
 	};
 
 	return ccid3_state_names[state];
@@ -91,19 +90,16 @@
 	return scaled_div(w_init << 6, hc->tx_rtt);
 }
 
-/*
- * Recalculate t_ipi and delta (should be called whenever X changes)
+/**
+ * ccid3_update_send_interval  -  Calculate new t_ipi = s / X_inst
+ * This respects the granularity of X_inst (64 * bytes/second).
  */
 static void ccid3_update_send_interval(struct ccid3_hc_tx_sock *hc)
 {
-	/* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
 	hc->tx_t_ipi = scaled_div32(((u64)hc->tx_s) << 6, hc->tx_x);
 
-	/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
-	hc->tx_delta = min_t(u32, hc->tx_t_ipi / 2, TFRC_OPSYS_HALF_TIME_GRAN);
-
-	ccid3_pr_debug("t_ipi=%u, delta=%u, s=%u, X=%u\n", hc->tx_t_ipi,
-		       hc->tx_delta, hc->tx_s, (unsigned)(hc->tx_x >> 6));
+	ccid3_pr_debug("t_ipi=%u, s=%u, X=%u\n", hc->tx_t_ipi,
+		       hc->tx_s, (unsigned)(hc->tx_x >> 6));
 }
 
 static u32 ccid3_hc_tx_idle_rtt(struct ccid3_hc_tx_sock *hc, ktime_t now)
@@ -211,16 +207,19 @@
 	ccid3_pr_debug("%s(%p, state=%s) - entry\n", dccp_role(sk), sk,
 		       ccid3_tx_state_name(hc->tx_state));
 
+	/* Ignore and do not restart after leaving the established state */
+	if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN))
+		goto out;
+
+	/* Reset feedback state to "no feedback received" */
 	if (hc->tx_state == TFRC_SSTATE_FBACK)
 		ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
-	else if (hc->tx_state != TFRC_SSTATE_NO_FBACK)
-		goto out;
 
 	/*
 	 * Determine new allowed sending rate X as per draft rfc3448bis-00, 4.4
+	 * RTO is 0 if and only if no feedback has been received yet.
 	 */
-	if (hc->tx_t_rto == 0 ||	/* no feedback received yet */
-	    hc->tx_p == 0) {
+	if (hc->tx_t_rto == 0 || hc->tx_p == 0) {
 
 		/* halve send rate directly */
 		hc->tx_x = max(hc->tx_x / 2,
@@ -256,7 +255,7 @@
 	 * Set new timeout for the nofeedback timer.
 	 * See comments in packet_recv() regarding the value of t_RTO.
 	 */
-	if (unlikely(hc->tx_t_rto == 0))	/* no feedback yet */
+	if (unlikely(hc->tx_t_rto == 0))	/* no feedback received yet */
 		t_nfb = TFRC_INITIAL_TIMEOUT;
 	else
 		t_nfb = max(hc->tx_t_rto, 2 * hc->tx_t_ipi);
@@ -290,8 +289,7 @@
 	if (unlikely(skb->len == 0))
 		return -EBADMSG;
 
-	switch (hc->tx_state) {
-	case TFRC_SSTATE_NO_SENT:
+	if (hc->tx_state == TFRC_SSTATE_NO_SENT) {
 		sk_reset_timer(sk, &hc->tx_no_feedback_timer, (jiffies +
 			       usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));
 		hc->tx_last_win_count	= 0;
@@ -326,27 +324,22 @@
 		ccid3_update_send_interval(hc);
 
 		ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
-		break;
-	case TFRC_SSTATE_NO_FBACK:
-	case TFRC_SSTATE_FBACK:
+
+	} else {
 		delay = ktime_us_delta(hc->tx_t_nom, now);
 		ccid3_pr_debug("delay=%ld\n", (long)delay);
 		/*
-		 *	Scheduling of packet transmissions [RFC 3448, 4.6]
+		 *	Scheduling of packet transmissions (RFC 5348, 8.3)
 		 *
 		 * if (t_now > t_nom - delta)
 		 *       // send the packet now
 		 * else
 		 *       // send the packet in (t_nom - t_now) milliseconds.
 		 */
-		if (delay - (s64)hc->tx_delta >= 1000)
-			return (u32)delay / 1000L;
+		if (delay >= TFRC_T_DELTA)
+			return (u32)delay / USEC_PER_MSEC;
 
 		ccid3_hc_tx_update_win_count(hc, now);
-		break;
-	case TFRC_SSTATE_TERM:
-		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
-		return -EINVAL;
 	}
 
 	/* prepare to send now (add options etc.) */
@@ -358,8 +351,7 @@
 	return 0;
 }
 
-static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,
-				    unsigned int len)
+static void ccid3_hc_tx_packet_sent(struct sock *sk, unsigned int len)
 {
 	struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
 
@@ -372,48 +364,34 @@
 static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
 {
 	struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
-	struct ccid3_options_received *opt_recv;
+	struct tfrc_tx_hist_entry *acked;
 	ktime_t now;
 	unsigned long t_nfb;
-	u32 pinv, r_sample;
+	u32 r_sample;
 
 	/* we are only interested in ACKs */
 	if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK ||
 	      DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK))
 		return;
-	/* ... and only in the established state */
-	if (hc->tx_state != TFRC_SSTATE_FBACK &&
-	    hc->tx_state != TFRC_SSTATE_NO_FBACK)
-		return;
-
-	opt_recv = &hc->tx_options_received;
-	now = ktime_get_real();
-
-	/* Estimate RTT from history if ACK number is valid */
-	r_sample = tfrc_tx_hist_rtt(hc->tx_hist,
-				    DCCP_SKB_CB(skb)->dccpd_ack_seq, now);
-	if (r_sample == 0) {
-		DCCP_WARN("%s(%p): %s with bogus ACK-%llu\n", dccp_role(sk), sk,
-			  dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type),
-			  (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq);
-		return;
-	}
-
-	/* Update receive rate in units of 64 * bytes/second */
-	hc->tx_x_recv = opt_recv->ccid3or_receive_rate;
-	hc->tx_x_recv <<= 6;
-
-	/* Update loss event rate (which is scaled by 1e6) */
-	pinv = opt_recv->ccid3or_loss_event_rate;
-	if (pinv == ~0U || pinv == 0)	       /* see RFC 4342, 8.5   */
-		hc->tx_p = 0;
-	else				       /* can not exceed 100% */
-		hc->tx_p = scaled_div(1, pinv);
 	/*
-	 * Validate new RTT sample and update moving average
+	 * Locate the acknowledged packet in the TX history.
+	 *
+	 * Returning "entry not found" here can for instance happen when
+	 *  - the host has not sent out anything (e.g. a passive server),
+	 *  - the Ack is outdated (packet with higher Ack number was received),
+	 *  - it is a bogus Ack (for a packet not sent on this connection).
 	 */
-	r_sample = dccp_sample_rtt(sk, r_sample);
+	acked = tfrc_tx_hist_find_entry(hc->tx_hist, dccp_hdr_ack_seq(skb));
+	if (acked == NULL)
+		return;
+	/* For the sake of RTT sampling, ignore/remove all older entries */
+	tfrc_tx_hist_purge(&acked->next);
+
+	/* Update the moving average for the RTT estimate (RFC 3448, 4.3) */
+	now	  = ktime_get_real();
+	r_sample  = dccp_sample_rtt(sk, ktime_us_delta(now, acked->stamp));
 	hc->tx_rtt = tfrc_ewma(hc->tx_rtt, r_sample, 9);
+
 	/*
 	 * Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3
 	 */
@@ -461,13 +439,12 @@
 	sk->sk_write_space(sk);
 
 	/*
-	 * Update timeout interval for the nofeedback timer.
-	 * We use a configuration option to increase the lower bound.
-	 * This can help avoid triggering the nofeedback timer too
-	 * often ('spinning') on LANs with small RTTs.
+	 * Update timeout interval for the nofeedback timer. In order to control
+	 * rate halving on networks with very low RTTs (<= 1 ms), use per-route
+	 * tunable RTAX_RTO_MIN value as the lower bound.
 	 */
-	hc->tx_t_rto = max_t(u32, 4 * hc->tx_rtt, (CONFIG_IP_DCCP_CCID3_RTO *
-						       (USEC_PER_SEC / 1000)));
+	hc->tx_t_rto = max_t(u32, 4 * hc->tx_rtt,
+				  USEC_PER_SEC/HZ * tcp_rto_min(sk));
 	/*
 	 * Schedule no feedback timer to expire in
 	 * max(t_RTO, 2 * s/X)  =  max(t_RTO, 2 * t_ipi)
@@ -482,66 +459,41 @@
 			   jiffies + usecs_to_jiffies(t_nfb));
 }
 
-static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
-				     unsigned char len, u16 idx,
-				     unsigned char *value)
+static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type,
+				     u8 option, u8 *optval, u8 optlen)
 {
-	int rc = 0;
-	const struct dccp_sock *dp = dccp_sk(sk);
 	struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
-	struct ccid3_options_received *opt_recv;
 	__be32 opt_val;
 
-	opt_recv = &hc->tx_options_received;
-
-	if (opt_recv->ccid3or_seqno != dp->dccps_gsr) {
-		opt_recv->ccid3or_seqno		     = dp->dccps_gsr;
-		opt_recv->ccid3or_loss_event_rate    = ~0;
-		opt_recv->ccid3or_loss_intervals_idx = 0;
-		opt_recv->ccid3or_loss_intervals_len = 0;
-		opt_recv->ccid3or_receive_rate	     = 0;
-	}
-
 	switch (option) {
-	case TFRC_OPT_LOSS_EVENT_RATE:
-		if (unlikely(len != 4)) {
-			DCCP_WARN("%s(%p), invalid len %d "
-				  "for TFRC_OPT_LOSS_EVENT_RATE\n",
-				  dccp_role(sk), sk, len);
-			rc = -EINVAL;
-		} else {
-			opt_val = get_unaligned((__be32 *)value);
-			opt_recv->ccid3or_loss_event_rate = ntohl(opt_val);
-			ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
-				       dccp_role(sk), sk,
-				       opt_recv->ccid3or_loss_event_rate);
-		}
-		break;
-	case TFRC_OPT_LOSS_INTERVALS:
-		opt_recv->ccid3or_loss_intervals_idx = idx;
-		opt_recv->ccid3or_loss_intervals_len = len;
-		ccid3_pr_debug("%s(%p), LOSS_INTERVALS=(%u, %u)\n",
-			       dccp_role(sk), sk,
-			       opt_recv->ccid3or_loss_intervals_idx,
-			       opt_recv->ccid3or_loss_intervals_len);
-		break;
 	case TFRC_OPT_RECEIVE_RATE:
-		if (unlikely(len != 4)) {
-			DCCP_WARN("%s(%p), invalid len %d "
-				  "for TFRC_OPT_RECEIVE_RATE\n",
-				  dccp_role(sk), sk, len);
-			rc = -EINVAL;
-		} else {
-			opt_val = get_unaligned((__be32 *)value);
-			opt_recv->ccid3or_receive_rate = ntohl(opt_val);
-			ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
-				       dccp_role(sk), sk,
-				       opt_recv->ccid3or_receive_rate);
+	case TFRC_OPT_LOSS_EVENT_RATE:
+		/* Must be ignored on Data packets, cf. RFC 4342 8.3 and 8.5 */
+		if (packet_type == DCCP_PKT_DATA)
+			break;
+		if (unlikely(optlen != 4)) {
+			DCCP_WARN("%s(%p), invalid len %d for %u\n",
+				  dccp_role(sk), sk, optlen, option);
+			return -EINVAL;
 		}
-		break;
-	}
+		opt_val = ntohl(get_unaligned((__be32 *)optval));
 
-	return rc;
+		if (option == TFRC_OPT_RECEIVE_RATE) {
+			/* Receive Rate is kept in units of 64 bytes/second */
+			hc->tx_x_recv = opt_val;
+			hc->tx_x_recv <<= 6;
+
+			ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
+				       dccp_role(sk), sk, opt_val);
+		} else {
+			/* Update the fixpoint Loss Event Rate fraction */
+			hc->tx_p = tfrc_invert_loss_event_rate(opt_val);
+
+			ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
+				       dccp_role(sk), sk, opt_val);
+		}
+	}
+	return 0;
 }
 
 static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
@@ -559,42 +511,36 @@
 {
 	struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
 
-	ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM);
 	sk_stop_timer(sk, &hc->tx_no_feedback_timer);
-
 	tfrc_tx_hist_purge(&hc->tx_hist);
 }
 
 static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
 {
-	struct ccid3_hc_tx_sock *hc;
-
-	/* Listen socks doesn't have a private CCID block */
-	if (sk->sk_state == DCCP_LISTEN)
-		return;
-
-	hc = ccid3_hc_tx_sk(sk);
-	info->tcpi_rto = hc->tx_t_rto;
-	info->tcpi_rtt = hc->tx_rtt;
+	info->tcpi_rto = ccid3_hc_tx_sk(sk)->tx_t_rto;
+	info->tcpi_rtt = ccid3_hc_tx_sk(sk)->tx_rtt;
 }
 
 static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
 				  u32 __user *optval, int __user *optlen)
 {
-	const struct ccid3_hc_tx_sock *hc;
+	const struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
+	struct tfrc_tx_info tfrc;
 	const void *val;
 
-	/* Listen socks doesn't have a private CCID block */
-	if (sk->sk_state == DCCP_LISTEN)
-		return -EINVAL;
-
-	hc = ccid3_hc_tx_sk(sk);
 	switch (optname) {
 	case DCCP_SOCKOPT_CCID_TX_INFO:
-		if (len < sizeof(hc->tx_tfrc))
+		if (len < sizeof(tfrc))
 			return -EINVAL;
-		len = sizeof(hc->tx_tfrc);
-		val = &hc->tx_tfrc;
+		tfrc.tfrctx_x	   = hc->tx_x;
+		tfrc.tfrctx_x_recv = hc->tx_x_recv;
+		tfrc.tfrctx_x_calc = hc->tx_x_calc;
+		tfrc.tfrctx_rtt	   = hc->tx_rtt;
+		tfrc.tfrctx_p	   = hc->tx_p;
+		tfrc.tfrctx_rto	   = hc->tx_t_rto;
+		tfrc.tfrctx_ipi	   = hc->tx_t_ipi;
+		len = sizeof(tfrc);
+		val = &tfrc;
 		break;
 	default:
 		return -ENOPROTOOPT;
@@ -624,7 +570,6 @@
 	static const char *const ccid3_rx_state_names[] = {
 	[TFRC_RSTATE_NO_DATA] = "NO_DATA",
 	[TFRC_RSTATE_DATA]    = "DATA",
-	[TFRC_RSTATE_TERM]    = "TERM",
 	};
 
 	return ccid3_rx_state_names[state];
@@ -650,14 +595,9 @@
 {
 	struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk);
 	struct dccp_sock *dp = dccp_sk(sk);
-	ktime_t now;
+	ktime_t now = ktime_get_real();
 	s64 delta = 0;
 
-	if (unlikely(hc->rx_state == TFRC_RSTATE_TERM))
-		return;
-
-	now = ktime_get_real();
-
 	switch (fbtype) {
 	case CCID3_FBACK_INITIAL:
 		hc->rx_x_recv = 0;
@@ -701,14 +641,12 @@
 
 static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
 {
-	const struct ccid3_hc_rx_sock *hc;
+	const struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk);
 	__be32 x_recv, pinv;
 
 	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
 		return 0;
 
-	hc = ccid3_hc_rx_sk(sk);
-
 	if (dccp_packet_without_ack(skb))
 		return 0;
 
@@ -749,10 +687,11 @@
 	x_recv = scaled_div32(hc->rx_bytes_recv, delta);
 	if (x_recv == 0) {		/* would also trigger divide-by-zero */
 		DCCP_WARN("X_recv==0\n");
-		if ((x_recv = hc->rx_x_recv) == 0) {
+		if (hc->rx_x_recv == 0) {
 			DCCP_BUG("stored value of X_recv is zero");
 			return ~0U;
 		}
+		x_recv = hc->rx_x_recv;
 	}
 
 	fval = scaled_div(hc->rx_s, hc->rx_rtt);
@@ -862,46 +801,31 @@
 {
 	struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk);
 
-	ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
-
 	tfrc_rx_hist_purge(&hc->rx_hist);
 	tfrc_lh_cleanup(&hc->rx_li_hist);
 }
 
 static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
 {
-	const struct ccid3_hc_rx_sock *hc;
-
-	/* Listen socks doesn't have a private CCID block */
-	if (sk->sk_state == DCCP_LISTEN)
-		return;
-
-	hc = ccid3_hc_rx_sk(sk);
-	info->tcpi_ca_state = hc->rx_state;
+	info->tcpi_ca_state = ccid3_hc_rx_sk(sk)->rx_state;
 	info->tcpi_options  |= TCPI_OPT_TIMESTAMPS;
-	info->tcpi_rcv_rtt  = hc->rx_rtt;
+	info->tcpi_rcv_rtt  = ccid3_hc_rx_sk(sk)->rx_rtt;
 }
 
 static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,
 				  u32 __user *optval, int __user *optlen)
 {
-	const struct ccid3_hc_rx_sock *hc;
+	const struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk);
 	struct tfrc_rx_info rx_info;
 	const void *val;
 
-	/* Listen socks doesn't have a private CCID block */
-	if (sk->sk_state == DCCP_LISTEN)
-		return -EINVAL;
-
-	hc = ccid3_hc_rx_sk(sk);
 	switch (optname) {
 	case DCCP_SOCKOPT_CCID_RX_INFO:
 		if (len < sizeof(rx_info))
 			return -EINVAL;
 		rx_info.tfrcrx_x_recv = hc->rx_x_recv;
 		rx_info.tfrcrx_rtt    = hc->rx_rtt;
-		rx_info.tfrcrx_p      = hc->rx_pinv == 0 ? ~0U :
-					   scaled_div(1, hc->rx_pinv);
+		rx_info.tfrcrx_p      = tfrc_invert_loss_event_rate(hc->rx_pinv);
 		len = sizeof(rx_info);
 		val = &rx_info;
 		break;
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 0326357..1a9933c 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -42,35 +42,36 @@
 #include "lib/tfrc.h"
 #include "../ccid.h"
 
-/* Two seconds as per RFC 3448 4.2 */
+/* Two seconds as per RFC 5348, 4.2 */
 #define TFRC_INITIAL_TIMEOUT	   (2 * USEC_PER_SEC)
 
-/* In usecs - half the scheduling granularity as per RFC3448 4.6 */
-#define TFRC_OPSYS_HALF_TIME_GRAN  (USEC_PER_SEC / (2 * HZ))
-
 /* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */
 #define TFRC_T_MBI		   64
 
+/*
+ * The t_delta parameter (RFC 5348, 8.3): delays of less than %USEC_PER_MSEC are
+ * rounded down to 0, since sk_reset_timer() here uses millisecond granularity.
+ * Hence we can use a constant t_delta = %USEC_PER_MSEC when HZ >= 500. A coarse
+ * resolution of HZ < 500 means that the error is below one timer tick (t_gran)
+ * when using the constant t_delta  =  t_gran / 2  =  %USEC_PER_SEC / (2 * HZ).
+ */
+#if (HZ >= 500)
+# define TFRC_T_DELTA		   USEC_PER_MSEC
+#else
+# define TFRC_T_DELTA		   (USEC_PER_SEC / (2 * HZ))
+#endif
+
 enum ccid3_options {
 	TFRC_OPT_LOSS_EVENT_RATE = 192,
 	TFRC_OPT_LOSS_INTERVALS	 = 193,
 	TFRC_OPT_RECEIVE_RATE	 = 194,
 };
 
-struct ccid3_options_received {
-	u64 ccid3or_seqno:48,
-	    ccid3or_loss_intervals_idx:16;
-	u16 ccid3or_loss_intervals_len;
-	u32 ccid3or_loss_event_rate;
-	u32 ccid3or_receive_rate;
-};
-
 /* TFRC sender states */
 enum ccid3_hc_tx_states {
 	TFRC_SSTATE_NO_SENT = 1,
 	TFRC_SSTATE_NO_FBACK,
 	TFRC_SSTATE_FBACK,
-	TFRC_SSTATE_TERM,
 };
 
 /**
@@ -90,19 +91,16 @@
  * @tx_no_feedback_timer: Handle to no feedback timer
  * @tx_t_ld:		  Time last doubled during slow start
  * @tx_t_nom:		  Nominal send time of next packet
- * @tx_delta:		  Send timer delta (RFC 3448, 4.6) in usecs
  * @tx_hist:		  Packet history
- * @tx_options_received:  Parsed set of retrieved options
  */
 struct ccid3_hc_tx_sock {
-	struct tfrc_tx_info		tx_tfrc;
-#define tx_x				tx_tfrc.tfrctx_x
-#define tx_x_recv			tx_tfrc.tfrctx_x_recv
-#define tx_x_calc			tx_tfrc.tfrctx_x_calc
-#define tx_rtt				tx_tfrc.tfrctx_rtt
-#define tx_p				tx_tfrc.tfrctx_p
-#define tx_t_rto			tx_tfrc.tfrctx_rto
-#define tx_t_ipi			tx_tfrc.tfrctx_ipi
+	u64				tx_x;
+	u64				tx_x_recv;
+	u32				tx_x_calc;
+	u32				tx_rtt;
+	u32				tx_p;
+	u32				tx_t_rto;
+	u32				tx_t_ipi;
 	u16				tx_s;
 	enum ccid3_hc_tx_states		tx_state:8;
 	u8				tx_last_win_count;
@@ -110,9 +108,7 @@
 	struct timer_list		tx_no_feedback_timer;
 	ktime_t				tx_t_ld;
 	ktime_t				tx_t_nom;
-	u32				tx_delta;
 	struct tfrc_tx_hist_entry	*tx_hist;
-	struct ccid3_options_received	tx_options_received;
 };
 
 static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
@@ -126,21 +122,16 @@
 enum ccid3_hc_rx_states {
 	TFRC_RSTATE_NO_DATA = 1,
 	TFRC_RSTATE_DATA,
-	TFRC_RSTATE_TERM    = 127,
 };
 
 /**
  * struct ccid3_hc_rx_sock - CCID3 receiver half-connection socket
- * @rx_x_recv:		     Receiver estimate of send rate (RFC 3448 4.3)
- * @rx_rtt:		     Receiver estimate of rtt (non-standard)
- * @rx_p:		     Current loss event rate (RFC 3448 5.4)
  * @rx_last_counter:	     Tracks window counter (RFC 4342, 8.1)
  * @rx_state:		     Receiver state, one of %ccid3_hc_rx_states
  * @rx_bytes_recv:	     Total sum of DCCP payload bytes
  * @rx_x_recv:		     Receiver estimate of send rate (RFC 3448, sec. 4.3)
  * @rx_rtt:		     Receiver estimate of RTT
  * @rx_tstamp_last_feedback: Time at which last feedback was sent
- * @rx_tstamp_last_ack:	     Time at which last feedback was sent
  * @rx_hist:		     Packet history (loss detection + RTT sampling)
  * @rx_li_hist:		     Loss Interval database
  * @rx_s:		     Received packet size in bytes
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 8fc3cbf..497723c 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -116,7 +116,7 @@
 	cur->li_length = len;
 	tfrc_lh_calc_i_mean(lh);
 
-	return (lh->i_mean < old_i_mean);
+	return lh->i_mean < old_i_mean;
 }
 
 /* Determine if `new_loss' does begin a new loss interval [RFC 4342, 10.2] */
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index 3a4f414..de8fe29 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -38,18 +38,6 @@
 #include "packet_history.h"
 #include "../../dccp.h"
 
-/**
- *  tfrc_tx_hist_entry  -  Simple singly-linked TX history list
- *  @next:  next oldest entry (LIFO order)
- *  @seqno: sequence number of this entry
- *  @stamp: send time of packet with sequence number @seqno
- */
-struct tfrc_tx_hist_entry {
-	struct tfrc_tx_hist_entry *next;
-	u64			  seqno;
-	ktime_t			  stamp;
-};
-
 /*
  * Transmitter History Routines
  */
@@ -71,15 +59,6 @@
 	}
 }
 
-static struct tfrc_tx_hist_entry *
-	tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)
-{
-	while (head != NULL && head->seqno != seqno)
-		head = head->next;
-
-	return head;
-}
-
 int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno)
 {
 	struct tfrc_tx_hist_entry *entry = kmem_cache_alloc(tfrc_tx_hist_slab, gfp_any());
@@ -107,24 +86,6 @@
 	*headp = NULL;
 }
 
-u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head, const u64 seqno,
-		     const ktime_t now)
-{
-	u32 rtt = 0;
-	struct tfrc_tx_hist_entry *packet = tfrc_tx_hist_find_entry(head, seqno);
-
-	if (packet != NULL) {
-		rtt = ktime_us_delta(now, packet->stamp);
-		/*
-		 * Garbage-collect older (irrelevant) entries:
-		 */
-		tfrc_tx_hist_purge(&packet->next);
-	}
-
-	return rtt;
-}
-
-
 /*
  *	Receiver History Routines
  */
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 7df6c52..7ee4a9d 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -40,12 +40,28 @@
 #include <linux/slab.h>
 #include "tfrc.h"
 
-struct tfrc_tx_hist_entry;
+/**
+ *  tfrc_tx_hist_entry  -  Simple singly-linked TX history list
+ *  @next:  next oldest entry (LIFO order)
+ *  @seqno: sequence number of this entry
+ *  @stamp: send time of packet with sequence number @seqno
+ */
+struct tfrc_tx_hist_entry {
+	struct tfrc_tx_hist_entry *next;
+	u64			  seqno;
+	ktime_t			  stamp;
+};
+
+static inline struct tfrc_tx_hist_entry *
+	tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)
+{
+	while (head != NULL && head->seqno != seqno)
+		head = head->next;
+	return head;
+}
 
 extern int  tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno);
 extern void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp);
-extern u32  tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head,
-			     const u64 seqno, const ktime_t now);
 
 /* Subtraction a-b modulo-16, respects circular wrap-around */
 #define SUB16(a, b) (((a) + 16 - (b)) & 0xF)
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
index 01bb48e..f8ee3f5 100644
--- a/net/dccp/ccids/lib/tfrc.h
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -57,6 +57,7 @@
 
 extern u32  tfrc_calc_x(u16 s, u32 R, u32 p);
 extern u32  tfrc_calc_x_reverse_lookup(u32 fvalue);
+extern u32  tfrc_invert_loss_event_rate(u32 loss_event_rate);
 
 extern int  tfrc_tx_packet_history_init(void);
 extern void tfrc_tx_packet_history_exit(void);
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
index 22ca1cf..a052a43 100644
--- a/net/dccp/ccids/lib/tfrc_equation.c
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -687,3 +687,17 @@
 	index = tfrc_binsearch(fvalue, 0);
 	return (index + 1) * 1000000 / TFRC_CALC_X_ARRSIZE;
 }
+
+/**
+ * tfrc_invert_loss_event_rate  -  Compute p so that 10^6 corresponds to 100%
+ * When @loss_event_rate is large, there is a chance that p is truncated to 0.
+ * To avoid re-entering slow-start in that case, we set p = TFRC_SMALLEST_P > 0.
+ */
+u32 tfrc_invert_loss_event_rate(u32 loss_event_rate)
+{
+	if (loss_event_rate == UINT_MAX)		/* see RFC 4342, 8.5 */
+		return 0;
+	if (unlikely(loss_event_rate == 0))		/* map 1/0 into 100% */
+		return 1000000;
+	return max_t(u32, scaled_div(1, loss_event_rate), TFRC_SMALLEST_P);
+}
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 3ccef1b..3eb264b 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -153,18 +153,27 @@
 }
 
 /**
- * dccp_loss_free  -  Evaluates condition for data loss from RFC 4340, 7.7.1
- * @s1:	 start sequence number
- * @s2:  end sequence number
+ * dccp_loss_count - Approximate the number of lost data packets in a burst loss
+ * @s1:  last known sequence number before the loss ('hole')
+ * @s2:  first sequence number seen after the 'hole'
  * @ndp: NDP count on packet with sequence number @s2
- * Returns true if the sequence range s1...s2 has no data loss.
  */
-static inline bool dccp_loss_free(const u64 s1, const u64 s2, const u64 ndp)
+static inline u64 dccp_loss_count(const u64 s1, const u64 s2, const u64 ndp)
 {
 	s64 delta = dccp_delta_seqno(s1, s2);
 
 	WARN_ON(delta < 0);
-	return (u64)delta <= ndp + 1;
+	delta -= ndp + 1;
+
+	return delta > 0 ? delta : 0;
+}
+
+/**
+ * dccp_loss_free - Evaluate condition for data loss from RFC 4340, 7.7.1
+ */
+static inline bool dccp_loss_free(const u64 s1, const u64 s2, const u64 ndp)
+{
+	return dccp_loss_count(s1, s2, ndp) == 0;
 }
 
 enum {
@@ -246,7 +255,6 @@
 extern unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu);
 
 extern const char *dccp_packet_name(const int type);
-extern const char *dccp_state_name(const int state);
 
 extern void dccp_set_state(struct sock *sk, const int state);
 extern void dccp_done(struct sock *sk);
@@ -415,6 +423,23 @@
 	dp->dccps_gsr = seq;
 	/* Sequence validity window depends on remote Sequence Window (7.5.1) */
 	dp->dccps_swl = SUB48(ADD48(dp->dccps_gsr, 1), dp->dccps_r_seq_win / 4);
+	/*
+	 * Adjust SWL so that it is not below ISR. In contrast to RFC 4340,
+	 * 7.5.1 we perform this check beyond the initial handshake: W/W' are
+	 * always > 32, so for the first W/W' packets in the lifetime of a
+	 * connection we always have to adjust SWL.
+	 * A second reason why we are doing this is that the window depends on
+	 * the feature-remote value of Sequence Window: nothing stops the peer
+	 * from updating this value while we are busy adjusting SWL for the
+	 * first W packets (we would have to count from scratch again then).
+	 * Therefore it is safer to always make sure that the Sequence Window
+	 * is not artificially extended by a peer who grows SWL downwards by
+	 * continually updating the feature-remote Sequence-Window.
+	 * If sequence numbers wrap it is bad luck. But that will take a while
+	 * (48 bit), and this measure prevents Sequence-number attacks.
+	 */
+	if (before48(dp->dccps_swl, dp->dccps_isr))
+		dp->dccps_swl = dp->dccps_isr;
 	dp->dccps_swh = ADD48(dp->dccps_gsr, (3 * dp->dccps_r_seq_win) / 4);
 }
 
@@ -425,14 +450,16 @@
 	dp->dccps_gss = seq;
 	/* Ack validity window depends on local Sequence Window value (7.5.1) */
 	dp->dccps_awl = SUB48(ADD48(dp->dccps_gss, 1), dp->dccps_l_seq_win);
+	/* Adjust AWL so that it is not below ISS - see comment above for SWL */
+	if (before48(dp->dccps_awl, dp->dccps_iss))
+		dp->dccps_awl = dp->dccps_iss;
 	dp->dccps_awh = dp->dccps_gss;
 }
 
 static inline int dccp_ack_pending(const struct sock *sk)
 {
 	const struct dccp_sock *dp = dccp_sk(sk);
-	return dp->dccps_timestamp_echo != 0 ||
-	       (dp->dccps_hc_rx_ackvec != NULL &&
+	return (dp->dccps_hc_rx_ackvec != NULL &&
 		dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) ||
 	       inet_csk_ack_scheduled(sk);
 }
@@ -449,7 +476,6 @@
 extern int dccp_insert_option_elapsed_time(struct sk_buff *skb, u32 elapsed);
 extern u32 dccp_timestamp(void);
 extern void dccp_timestamping_init(void);
-extern int dccp_insert_option_timestamp(struct sk_buff *skb);
 extern int dccp_insert_option(struct sk_buff *skb, unsigned char option,
 			      const void *value, unsigned char len);
 
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index df7dd26..568def9 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -730,16 +730,6 @@
 				  0, list, len);
 }
 
-/* Analogous to dccp_feat_register_sp(), but for non-negotiable values */
-int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val)
-{
-	/* any changes must be registered before establishing the connection */
-	if (sk->sk_state != DCCP_CLOSED)
-		return -EISCONN;
-	if (dccp_feat_type(feat) != FEAT_NN)
-		return -EINVAL;
-	return __feat_register_nn(&dccp_sk(sk)->dccps_featneg, feat, 0, val);
-}
 
 /*
  *	Tracking features whose value depend on the choice of CCID
diff --git a/net/dccp/feat.h b/net/dccp/feat.h
index f967216..e56a4e5 100644
--- a/net/dccp/feat.h
+++ b/net/dccp/feat.h
@@ -111,7 +111,6 @@
 extern void dccp_feat_initialise_sysctls(void);
 extern int  dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local,
 				  u8 const *list, u8 len);
-extern int  dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val);
 extern int  dccp_feat_parse_options(struct sock *, struct dccp_request_sock *,
 				    u8 mand, u8 opt, u8 feat, u8 *val, u8 len);
 extern int  dccp_feat_clone_list(struct list_head const *, struct list_head *);
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 10c957a..2659853 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -259,7 +259,7 @@
 				      sysctl_dccp_sync_ratelimit)))
 			return 0;
 
-		DCCP_WARN("DCCP: Step 6 failed for %s packet, "
+		DCCP_WARN("Step 6 failed for %s packet, "
 			  "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and "
 			  "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), "
 			  "sending SYNC...\n",  dccp_packet_name(dh->dccph_type),
@@ -441,20 +441,14 @@
 		kfree_skb(sk->sk_send_head);
 		sk->sk_send_head = NULL;
 
-		dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq;
-		dccp_update_gsr(sk, dp->dccps_isr);
 		/*
-		 * SWL and AWL are initially adjusted so that they are not less than
-		 * the initial Sequence Numbers received and sent, respectively:
-		 *	SWL := max(GSR + 1 - floor(W/4), ISR),
-		 *	AWL := max(GSS - W' + 1, ISS).
-		 * These adjustments MUST be applied only at the beginning of the
-		 * connection.
-		 *
-		 * AWL was adjusted in dccp_v4_connect -acme
+		 * Set ISR, GSR from packet. ISS was set in dccp_v{4,6}_connect
+		 * and GSS in dccp_transmit_skb(). Setting AWL/AWH and SWL/SWH
+		 * is done as part of activating the feature values below, since
+		 * these settings depend on the local/remote Sequence Window
+		 * features, which were undefined or not confirmed until now.
 		 */
-		dccp_set_seqno(&dp->dccps_swl,
-			       max48(dp->dccps_swl, dp->dccps_isr));
+		dp->dccps_gsr = dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq;
 
 		dccp_sync_mss(sk, icsk->icsk_pmtu_cookie);
 
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index d4a166f..3f69ea1 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -392,7 +392,7 @@
 
 	newsk = dccp_create_openreq_child(sk, req, skb);
 	if (newsk == NULL)
-		goto exit;
+		goto exit_nonewsk;
 
 	sk_setup_caps(newsk, dst);
 
@@ -409,16 +409,20 @@
 
 	dccp_sync_mss(newsk, dst_mtu(dst));
 
+	if (__inet_inherit_port(sk, newsk) < 0) {
+		sock_put(newsk);
+		goto exit;
+	}
 	__inet_hash_nolisten(newsk, NULL);
-	__inet_inherit_port(sk, newsk);
 
 	return newsk;
 
 exit_overflow:
 	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
+exit_nonewsk:
+	dst_release(dst);
 exit:
 	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
-	dst_release(dst);
 	return NULL;
 }
 
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 6e3f325..dca711d 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -564,7 +564,7 @@
 
 	newsk = dccp_create_openreq_child(sk, req, skb);
 	if (newsk == NULL)
-		goto out;
+		goto out_nonewsk;
 
 	/*
 	 * No need to charge this sock to the relevant IPv6 refcnt debug socks
@@ -632,18 +632,22 @@
 	newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
 	newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
 
+	if (__inet_inherit_port(sk, newsk) < 0) {
+		sock_put(newsk);
+		goto out;
+	}
 	__inet6_hash(newsk, NULL);
-	__inet_inherit_port(sk, newsk);
 
 	return newsk;
 
 out_overflow:
 	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
+out_nonewsk:
+	dst_release(dst);
 out:
 	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
 	if (opt != NULL && opt != np->opt)
 		sock_kfree_s(sk, opt, opt->tot_len);
-	dst_release(dst);
 	return NULL;
 }
 
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 128b089..d7041a0 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -121,30 +121,18 @@
 		 *
 		 *    Choose S.ISS (initial seqno) or set from Init Cookies
 		 *    Initialize S.GAR := S.ISS
-		 *    Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookies
+		 *    Set S.ISR, S.GSR from packet (or Init Cookies)
+		 *
+		 *    Setting AWL/AWH and SWL/SWH happens as part of the feature
+		 *    activation below, as these windows all depend on the local
+		 *    and remote Sequence Window feature values (7.5.2).
 		 */
-		newdp->dccps_gar = newdp->dccps_iss = dreq->dreq_iss;
-		dccp_update_gss(newsk, dreq->dreq_iss);
-
-		newdp->dccps_isr = dreq->dreq_isr;
-		dccp_update_gsr(newsk, dreq->dreq_isr);
+		newdp->dccps_gss = newdp->dccps_iss = dreq->dreq_iss;
+		newdp->dccps_gar = newdp->dccps_iss;
+		newdp->dccps_gsr = newdp->dccps_isr = dreq->dreq_isr;
 
 		/*
-		 * SWL and AWL are initially adjusted so that they are not less than
-		 * the initial Sequence Numbers received and sent, respectively:
-		 *	SWL := max(GSR + 1 - floor(W/4), ISR),
-		 *	AWL := max(GSS - W' + 1, ISS).
-		 * These adjustments MUST be applied only at the beginning of the
-		 * connection.
-		 */
-		dccp_set_seqno(&newdp->dccps_swl,
-			       max48(newdp->dccps_swl, newdp->dccps_isr));
-		dccp_set_seqno(&newdp->dccps_awl,
-			       max48(newdp->dccps_awl, newdp->dccps_iss));
-
-		/*
-		 * Activate features after initialising the sequence numbers,
-		 * since CCID initialisation may depend on GSS, ISR, ISS etc.
+		 * Activate features: initialise CCIDs, sequence windows etc.
 		 */
 		if (dccp_feat_activate_values(newsk, &dreq->dreq_featneg)) {
 			/* It is still raw copy of parent, so invalidate
diff --git a/net/dccp/options.c b/net/dccp/options.c
index bfda087..cd30618 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -96,18 +96,11 @@
 		}
 
 		/*
-		 * CCID-Specific Options (from RFC 4340, sec. 10.3):
-		 *
-		 * Option numbers 128 through 191 are for options sent from the
-		 * HC-Sender to the HC-Receiver; option numbers 192 through 255
-		 * are for options sent from the HC-Receiver to	the HC-Sender.
-		 *
 		 * CCID-specific options are ignored during connection setup, as
 		 * negotiation may still be in progress (see RFC 4340, 10.3).
 		 * The same applies to Ack Vectors, as these depend on the CCID.
-		 *
 		 */
-		if (dreq != NULL && (opt >= 128 ||
+		if (dreq != NULL && (opt >= DCCPO_MIN_RX_CCID_SPECIFIC ||
 		    opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1))
 			goto ignore_option;
 
@@ -170,6 +163,8 @@
 				      dccp_role(sk), ntohl(opt_val),
 				      (unsigned long long)
 				      DCCP_SKB_CB(skb)->dccpd_ack_seq);
+			/* schedule an Ack in case this sender is quiescent */
+			inet_csk_schedule_ack(sk);
 			break;
 		case DCCPO_TIMESTAMP_ECHO:
 			if (len != 4 && len != 6 && len != 8)
@@ -226,23 +221,15 @@
 			dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n",
 				      dccp_role(sk), elapsed_time);
 			break;
-		case 128 ... 191: {
-			const u16 idx = value - options;
-
+		case DCCPO_MIN_RX_CCID_SPECIFIC ... DCCPO_MAX_RX_CCID_SPECIFIC:
 			if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk,
-						     opt, len, idx,
-						     value) != 0)
+						     pkt_type, opt, value, len))
 				goto out_invalid_option;
-		}
 			break;
-		case 192 ... 255: {
-			const u16 idx = value - options;
-
+		case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC:
 			if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
-						     opt, len, idx,
-						     value) != 0)
+						     pkt_type, opt, value, len))
 				goto out_invalid_option;
-		}
 			break;
 		default:
 			DCCP_CRIT("DCCP(%p): option %d(len=%d) not "
@@ -384,7 +371,7 @@
 
 EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
 
-int dccp_insert_option_timestamp(struct sk_buff *skb)
+static int dccp_insert_option_timestamp(struct sk_buff *skb)
 {
 	__be32 now = htonl(dccp_timestamp());
 	/* yes this will overflow but that is the point as we want a
@@ -393,8 +380,6 @@
 	return dccp_insert_option(skb, DCCPO_TIMESTAMP, &now, sizeof(now));
 }
 
-EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp);
-
 static int dccp_insert_option_timestamp_echo(struct dccp_sock *dp,
 					     struct dccp_request_sock *dreq,
 					     struct sk_buff *skb)
diff --git a/net/dccp/output.c b/net/dccp/output.c
index aadbdb5..a988fe9 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -304,7 +304,7 @@
 				dcb->dccpd_type = DCCP_PKT_DATA;
 
 			err = dccp_transmit_skb(sk, skb);
-			ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len);
+			ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, len);
 			if (err)
 				DCCP_BUG("err=%d after ccid_hc_tx_packet_sent",
 					 err);
@@ -474,8 +474,9 @@
 /*
  * Do all connect socket setups that can be done AF independent.
  */
-static inline void dccp_connect_init(struct sock *sk)
+int dccp_connect(struct sock *sk)
 {
+	struct sk_buff *skb;
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct dst_entry *dst = __sk_dst_get(sk);
 	struct inet_connection_sock *icsk = inet_csk(sk);
@@ -485,22 +486,12 @@
 
 	dccp_sync_mss(sk, dst_mtu(dst));
 
-	/* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */
-	dp->dccps_gar = dp->dccps_iss;
-
-	icsk->icsk_retransmits = 0;
-}
-
-int dccp_connect(struct sock *sk)
-{
-	struct sk_buff *skb;
-	struct inet_connection_sock *icsk = inet_csk(sk);
-
 	/* do not connect if feature negotiation setup fails */
 	if (dccp_feat_finalise_settings(dccp_sk(sk)))
 		return -EPROTO;
 
-	dccp_connect_init(sk);
+	/* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */
+	dp->dccps_gar = dp->dccps_iss;
 
 	skb = alloc_skb(sk->sk_prot->max_header, sk->sk_allocation);
 	if (unlikely(skb == NULL))
@@ -516,6 +507,7 @@
 	DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
 
 	/* Timer for repeating the REQUEST until an answer. */
+	icsk->icsk_retransmits = 0;
 	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
 				  icsk->icsk_rto, DCCP_RTO_MAX);
 	return 0;
diff --git a/net/dccp/probe.c b/net/dccp/probe.c
index 078e48d..33d0e62 100644
--- a/net/dccp/probe.c
+++ b/net/dccp/probe.c
@@ -149,6 +149,7 @@
 	.owner	 = THIS_MODULE,
 	.open	 = dccpprobe_open,
 	.read    = dccpprobe_read,
+	.llseek  = noop_llseek,
 };
 
 static __init int dccpprobe_init(void)
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 096250d..7e5fc04 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -50,6 +50,30 @@
 /* the maximum queue length for tx in packets. 0 is no limit */
 int sysctl_dccp_tx_qlen __read_mostly = 5;
 
+#ifdef CONFIG_IP_DCCP_DEBUG
+static const char *dccp_state_name(const int state)
+{
+	static const char *const dccp_state_names[] = {
+	[DCCP_OPEN]		= "OPEN",
+	[DCCP_REQUESTING]	= "REQUESTING",
+	[DCCP_PARTOPEN]		= "PARTOPEN",
+	[DCCP_LISTEN]		= "LISTEN",
+	[DCCP_RESPOND]		= "RESPOND",
+	[DCCP_CLOSING]		= "CLOSING",
+	[DCCP_ACTIVE_CLOSEREQ]	= "CLOSEREQ",
+	[DCCP_PASSIVE_CLOSE]	= "PASSIVE_CLOSE",
+	[DCCP_PASSIVE_CLOSEREQ]	= "PASSIVE_CLOSEREQ",
+	[DCCP_TIME_WAIT]	= "TIME_WAIT",
+	[DCCP_CLOSED]		= "CLOSED",
+	};
+
+	if (state >= DCCP_MAX_STATES)
+		return "INVALID STATE!";
+	else
+		return dccp_state_names[state];
+}
+#endif
+
 void dccp_set_state(struct sock *sk, const int state)
 {
 	const int oldstate = sk->sk_state;
@@ -146,30 +170,6 @@
 
 EXPORT_SYMBOL_GPL(dccp_packet_name);
 
-const char *dccp_state_name(const int state)
-{
-	static const char *const dccp_state_names[] = {
-	[DCCP_OPEN]		= "OPEN",
-	[DCCP_REQUESTING]	= "REQUESTING",
-	[DCCP_PARTOPEN]		= "PARTOPEN",
-	[DCCP_LISTEN]		= "LISTEN",
-	[DCCP_RESPOND]		= "RESPOND",
-	[DCCP_CLOSING]		= "CLOSING",
-	[DCCP_ACTIVE_CLOSEREQ]	= "CLOSEREQ",
-	[DCCP_PASSIVE_CLOSE]	= "PASSIVE_CLOSE",
-	[DCCP_PASSIVE_CLOSEREQ]	= "PASSIVE_CLOSEREQ",
-	[DCCP_TIME_WAIT]	= "TIME_WAIT",
-	[DCCP_CLOSED]		= "CLOSED",
-	};
-
-	if (state >= DCCP_MAX_STATES)
-		return "INVALID STATE!";
-	else
-		return dccp_state_names[state];
-}
-
-EXPORT_SYMBOL_GPL(dccp_state_name);
-
 int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
 {
 	struct dccp_sock *dp = dccp_sk(sk);
@@ -944,7 +944,7 @@
 
 	if (data_was_unread) {
 		/* Unread data was tossed, send an appropriate Reset Code */
-		DCCP_WARN("DCCP: ABORT -- %u bytes unread\n", data_was_unread);
+		DCCP_WARN("ABORT with %u bytes unread\n", data_was_unread);
 		dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED);
 		dccp_set_state(sk, DCCP_CLOSED);
 	} else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 0363bb95..a085dbc 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -48,7 +48,6 @@
 #include <net/dn_neigh.h>
 #include <net/dn_route.h>
 
-static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev);
 static int dn_neigh_construct(struct neighbour *);
 static void dn_long_error_report(struct neighbour *, struct sk_buff *);
 static void dn_short_error_report(struct neighbour *, struct sk_buff *);
@@ -93,6 +92,13 @@
 	.queue_xmit =		dev_queue_xmit
 };
 
+static u32 dn_neigh_hash(const void *pkey,
+			 const struct net_device *dev,
+			 __u32 hash_rnd)
+{
+	return jhash_2words(*(__u16 *)pkey, 0, hash_rnd);
+}
+
 struct neigh_table dn_neigh_table = {
 	.family =			PF_DECnet,
 	.entry_size =			sizeof(struct dn_neigh),
@@ -122,11 +128,6 @@
 	.gc_thresh3 =			1024,
 };
 
-static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev)
-{
-	return jhash_2words(*(__u16 *)pkey, 0, dn_neigh_table.hash_rnd);
-}
-
 static int dn_neigh_construct(struct neighbour *neigh)
 {
 	struct net_device *dev = neigh->dev;
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c
index baeb1ea..2ef1152 100644
--- a/net/decnet/dn_nsp_out.c
+++ b/net/decnet/dn_nsp_out.c
@@ -693,22 +693,22 @@
 	aux = scp->accessdata.acc_userl;
 	*skb_put(skb, 1) = aux;
 	if (aux > 0)
-	memcpy(skb_put(skb, aux), scp->accessdata.acc_user, aux);
+		memcpy(skb_put(skb, aux), scp->accessdata.acc_user, aux);
 
 	aux = scp->accessdata.acc_passl;
 	*skb_put(skb, 1) = aux;
 	if (aux > 0)
-	memcpy(skb_put(skb, aux), scp->accessdata.acc_pass, aux);
+		memcpy(skb_put(skb, aux), scp->accessdata.acc_pass, aux);
 
 	aux = scp->accessdata.acc_accl;
 	*skb_put(skb, 1) = aux;
 	if (aux > 0)
-	memcpy(skb_put(skb, aux), scp->accessdata.acc_acc, aux);
+		memcpy(skb_put(skb, aux), scp->accessdata.acc_acc, aux);
 
 	aux = (__u8)le16_to_cpu(scp->conndata_out.opt_optl);
 	*skb_put(skb, 1) = aux;
 	if (aux > 0)
-	memcpy(skb_put(skb,aux), scp->conndata_out.opt_data, aux);
+		memcpy(skb_put(skb, aux), scp->conndata_out.opt_data, aux);
 
 	scp->persist = dn_nsp_persist(sk);
 	scp->persist_fxn = dn_nsp_retrans_conninit;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 6585ea6..df0f3e5 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -132,7 +132,6 @@
 	.negative_advice =	dn_dst_negative_advice,
 	.link_failure =		dn_dst_link_failure,
 	.update_pmtu =		dn_dst_update_pmtu,
-	.entries =		ATOMIC_INIT(0),
 };
 
 static __inline__ unsigned dn_hash(__le16 src, __le16 dst)
@@ -1758,6 +1757,7 @@
 	dn_dst_ops.kmem_cachep =
 		kmem_cache_create("dn_dst_cache", sizeof(struct dn_route), 0,
 				  SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
+	dst_entries_init(&dn_dst_ops);
 	setup_timer(&dn_route_timer, dn_dst_check_expire, 0);
 	dn_route_timer.expires = jiffies + decnet_dst_gc_interval * HZ;
 	add_timer(&dn_route_timer);
@@ -1816,5 +1816,6 @@
 	dn_run_flush(0);
 
 	proc_net_remove(&init_net, "decnet_cache");
+	dst_entries_destroy(&dn_dst_ops);
 }
 
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index dc54bd0..f8c1ae4 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -392,7 +392,7 @@
 		dev_queue_xmit(skb);
 		dev_put(dev);
 		mutex_unlock(&econet_mutex);
-		return(len);
+		return len;
 
 	out_free:
 		kfree_skb(skb);
@@ -637,7 +637,7 @@
 	eo->num = protocol;
 
 	econet_insert_socket(&econet_sklist, sk);
-	return(0);
+	return 0;
 out:
 	return err;
 }
@@ -1009,7 +1009,6 @@
 	struct sockaddr_in sin;
 
 	skb_queue_head_init(&aun_queue);
-	spin_lock_init(&aun_queue_lock);
 	setup_timer(&ab_cleanup_timer, ab_cleanup, 0);
 	ab_cleanup_timer.expires = jiffies + (HZ*2);
 	add_timer(&ab_cleanup_timer);
@@ -1167,7 +1166,6 @@
 		goto out;
 	sock_register(&econet_family_ops);
 #ifdef CONFIG_ECONET_AUNUDP
-	spin_lock_init(&aun_queue_lock);
 	aun_udp_initialise();
 #endif
 #ifdef CONFIG_ECONET_NATIVE
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 215c839..f00ef2f 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -367,7 +367,7 @@
 EXPORT_SYMBOL(alloc_etherdev_mq);
 
 static size_t _format_mac_addr(char *buf, int buflen,
-				const unsigned char *addr, int len)
+			       const unsigned char *addr, int len)
 {
 	int i;
 	char *cp = buf;
@@ -376,7 +376,7 @@
 		cp += scnprintf(cp, buflen - (cp - buf), "%02x", addr[i]);
 		if (i == len - 1)
 			break;
-		cp += strlcpy(cp, ":", buflen - (cp - buf));
+		cp += scnprintf(cp, buflen - (cp - buf), ":");
 	}
 	return cp - buf;
 }
@@ -386,7 +386,7 @@
 	size_t l;
 
 	l = _format_mac_addr(buf, PAGE_SIZE, addr, len);
-	l += strlcpy(buf + l, "\n", PAGE_SIZE - l);
-	return ((ssize_t) l);
+	l += scnprintf(buf + l, PAGE_SIZE - l, "\n");
+	return (ssize_t)l;
 }
 EXPORT_SYMBOL(sysfs_format_mac);
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 571f895..e848e6c 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -215,8 +215,15 @@
 	  be inserted in and removed from the running kernel whenever you
 	  want). Most people won't need this and can say N.
 
+config NET_IPGRE_DEMUX
+	tristate "IP: GRE demultiplexer"
+	help
+	 This is helper module to demultiplex GRE packets on GRE version field criteria.
+	 Required by ip_gre and pptp modules.
+
 config NET_IPGRE
 	tristate "IP: GRE tunnels over IP"
+	depends on (IPV6 || IPV6=n) && NET_IPGRE_DEMUX
 	help
 	  Tunneling means encapsulating data of one protocol type within
 	  another protocol and sending it over a channel that understands the
@@ -412,7 +419,7 @@
 	  If unsure, say Y.
 
 config INET_LRO
-	bool "Large Receive Offload (ipv4/tcp)"
+	tristate "Large Receive Offload (ipv4/tcp)"
 	default y
 	---help---
 	  Support for Large Receive Offload (ipv4/tcp).
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 80ff87c..4978d22 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -20,6 +20,7 @@
 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
 obj-$(CONFIG_IP_MROUTE) += ipmr.o
 obj-$(CONFIG_NET_IPIP) += ipip.o
+obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o
 obj-$(CONFIG_NET_IPGRE) += ip_gre.o
 obj-$(CONFIG_SYN_COOKIES) += syncookies.o
 obj-$(CONFIG_INET_AH) += ah4.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 6a1100c..f581f77 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -227,18 +227,16 @@
 
 /*
  * inet_ehash_secret must be set exactly once
- * Instead of using a dedicated spinlock, we (ab)use inetsw_lock
  */
 void build_ehash_secret(void)
 {
 	u32 rnd;
+
 	do {
 		get_random_bytes(&rnd, sizeof(rnd));
 	} while (rnd == 0);
-	spin_lock_bh(&inetsw_lock);
-	if (!inet_ehash_secret)
-		inet_ehash_secret = rnd;
-	spin_unlock_bh(&inetsw_lock);
+
+	cmpxchg(&inet_ehash_secret, 0, rnd);
 }
 EXPORT_SYMBOL(build_ehash_secret);
 
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 96c1955..d8e540c 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -55,7 +55,7 @@
  *		Stuart Cheshire	:	Metricom and grat arp fixes
  *					*** FOR 2.1 clean this up ***
  *		Lawrence V. Stefani: (08/12/96) Added FDDI support.
- *		Alan Cox 	:	Took the AP1000 nasty FDDI hack and
+ *		Alan Cox	:	Took the AP1000 nasty FDDI hack and
  *					folded into the mainstream FDDI code.
  *					Ack spit, Linus how did you allow that
  *					one in...
@@ -120,14 +120,14 @@
 #endif
 
 #include <asm/system.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <linux/netfilter_arp.h>
 
 /*
  *	Interface to generic neighbour cache.
  */
-static u32 arp_hash(const void *pkey, const struct net_device *dev);
+static u32 arp_hash(const void *pkey, const struct net_device *dev, __u32 rnd);
 static int arp_constructor(struct neighbour *neigh);
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb);
 static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb);
@@ -161,7 +161,7 @@
 	.queue_xmit =		dev_queue_xmit,
 };
 
-const struct neigh_ops arp_broken_ops = {
+static const struct neigh_ops arp_broken_ops = {
 	.family =		AF_INET,
 	.solicit =		arp_solicit,
 	.error_report =		arp_error_report,
@@ -170,35 +170,34 @@
 	.hh_output =		dev_queue_xmit,
 	.queue_xmit =		dev_queue_xmit,
 };
-EXPORT_SYMBOL(arp_broken_ops);
 
 struct neigh_table arp_tbl = {
-	.family =	AF_INET,
-	.entry_size =	sizeof(struct neighbour) + 4,
-	.key_len =	4,
-	.hash =		arp_hash,
-	.constructor =	arp_constructor,
-	.proxy_redo =	parp_redo,
-	.id =		"arp_cache",
-	.parms = {
-		.tbl =			&arp_tbl,
-		.base_reachable_time =	30 * HZ,
-		.retrans_time =	1 * HZ,
-		.gc_staletime =	60 * HZ,
-		.reachable_time =		30 * HZ,
-		.delay_probe_time =	5 * HZ,
-		.queue_len =		3,
-		.ucast_probes =	3,
-		.mcast_probes =	3,
-		.anycast_delay =	1 * HZ,
-		.proxy_delay =		(8 * HZ) / 10,
-		.proxy_qlen =		64,
-		.locktime =		1 * HZ,
+	.family		= AF_INET,
+	.entry_size	= sizeof(struct neighbour) + 4,
+	.key_len	= 4,
+	.hash		= arp_hash,
+	.constructor	= arp_constructor,
+	.proxy_redo	= parp_redo,
+	.id		= "arp_cache",
+	.parms		= {
+		.tbl			= &arp_tbl,
+		.base_reachable_time	= 30 * HZ,
+		.retrans_time		= 1 * HZ,
+		.gc_staletime		= 60 * HZ,
+		.reachable_time		= 30 * HZ,
+		.delay_probe_time	= 5 * HZ,
+		.queue_len		= 3,
+		.ucast_probes		= 3,
+		.mcast_probes		= 3,
+		.anycast_delay		= 1 * HZ,
+		.proxy_delay		= (8 * HZ) / 10,
+		.proxy_qlen		= 64,
+		.locktime		= 1 * HZ,
 	},
-	.gc_interval =	30 * HZ,
-	.gc_thresh1 =	128,
-	.gc_thresh2 =	512,
-	.gc_thresh3 =	1024,
+	.gc_interval	= 30 * HZ,
+	.gc_thresh1	= 128,
+	.gc_thresh2	= 512,
+	.gc_thresh3	= 1024,
 };
 EXPORT_SYMBOL(arp_tbl);
 
@@ -226,14 +225,16 @@
 }
 
 
-static u32 arp_hash(const void *pkey, const struct net_device *dev)
+static u32 arp_hash(const void *pkey,
+		    const struct net_device *dev,
+		    __u32 hash_rnd)
 {
-	return jhash_2words(*(u32 *)pkey, dev->ifindex, arp_tbl.hash_rnd);
+	return jhash_2words(*(u32 *)pkey, dev->ifindex, hash_rnd);
 }
 
 static int arp_constructor(struct neighbour *neigh)
 {
-	__be32 addr = *(__be32*)neigh->primary_key;
+	__be32 addr = *(__be32 *)neigh->primary_key;
 	struct net_device *dev = neigh->dev;
 	struct in_device *in_dev;
 	struct neigh_parms *parms;
@@ -296,16 +297,19 @@
 			neigh->ops = &arp_broken_ops;
 			neigh->output = neigh->ops->output;
 			return 0;
+#else
+			break;
 #endif
-		;}
+		}
 #endif
 		if (neigh->type == RTN_MULTICAST) {
 			neigh->nud_state = NUD_NOARP;
 			arp_mc_map(addr, neigh->ha, dev, 1);
-		} else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
+		} else if (dev->flags & (IFF_NOARP | IFF_LOOPBACK)) {
 			neigh->nud_state = NUD_NOARP;
 			memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
-		} else if (neigh->type == RTN_BROADCAST || dev->flags&IFF_POINTOPOINT) {
+		} else if (neigh->type == RTN_BROADCAST ||
+			   (dev->flags & IFF_POINTOPOINT)) {
 			neigh->nud_state = NUD_NOARP;
 			memcpy(neigh->ha, dev->broadcast, dev->addr_len);
 		}
@@ -315,7 +319,7 @@
 		else
 			neigh->ops = &arp_generic_ops;
 
-		if (neigh->nud_state&NUD_VALID)
+		if (neigh->nud_state & NUD_VALID)
 			neigh->output = neigh->ops->connected_output;
 		else
 			neigh->output = neigh->ops->output;
@@ -334,7 +338,7 @@
 	__be32 saddr = 0;
 	u8  *dst_ha = NULL;
 	struct net_device *dev = neigh->dev;
-	__be32 target = *(__be32*)neigh->primary_key;
+	__be32 target = *(__be32 *)neigh->primary_key;
 	int probes = atomic_read(&neigh->probes);
 	struct in_device *in_dev;
 
@@ -347,7 +351,8 @@
 	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
 	default:
 	case 0:		/* By default announce any local IP */
-		if (skb && inet_addr_type(dev_net(dev), ip_hdr(skb)->saddr) == RTN_LOCAL)
+		if (skb && inet_addr_type(dev_net(dev),
+					  ip_hdr(skb)->saddr) == RTN_LOCAL)
 			saddr = ip_hdr(skb)->saddr;
 		break;
 	case 1:		/* Restrict announcements of saddr in same subnet */
@@ -369,16 +374,21 @@
 	if (!saddr)
 		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
 
-	if ((probes -= neigh->parms->ucast_probes) < 0) {
-		if (!(neigh->nud_state&NUD_VALID))
-			printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n");
+	probes -= neigh->parms->ucast_probes;
+	if (probes < 0) {
+		if (!(neigh->nud_state & NUD_VALID))
+			printk(KERN_DEBUG
+			       "trying to ucast probe in NUD_INVALID\n");
 		dst_ha = neigh->ha;
 		read_lock_bh(&neigh->lock);
-	} else if ((probes -= neigh->parms->app_probes) < 0) {
+	} else {
+		probes -= neigh->parms->app_probes;
+		if (probes < 0) {
 #ifdef CONFIG_ARPD
-		neigh_app_ns(neigh);
+			neigh_app_ns(neigh);
 #endif
-		return;
+			return;
+		}
 	}
 
 	arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
@@ -451,7 +461,8 @@
  *	is allowed to use this function, it is scheduled to be removed. --ANK
  */
 
-static int arp_set_predefined(int addr_hint, unsigned char * haddr, __be32 paddr, struct net_device * dev)
+static int arp_set_predefined(int addr_hint, unsigned char *haddr,
+			      __be32 paddr, struct net_device *dev)
 {
 	switch (addr_hint) {
 	case RTN_LOCAL:
@@ -483,17 +494,16 @@
 
 	paddr = skb_rtable(skb)->rt_gateway;
 
-	if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr, paddr, dev))
+	if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr,
+			       paddr, dev))
 		return 0;
 
 	n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
 
 	if (n) {
 		n->used = jiffies;
-		if (n->nud_state&NUD_VALID || neigh_event_send(n, skb) == 0) {
-			read_lock_bh(&n->lock);
-			memcpy(haddr, n->ha, dev->addr_len);
-			read_unlock_bh(&n->lock);
+		if (n->nud_state & NUD_VALID || neigh_event_send(n, skb) == 0) {
+			neigh_ha_snapshot(haddr, n, dev);
 			neigh_release(n);
 			return 0;
 		}
@@ -515,13 +525,14 @@
 		return -EINVAL;
 	if (n == NULL) {
 		__be32 nexthop = ((struct rtable *)dst)->rt_gateway;
-		if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
+		if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
 			nexthop = 0;
 		n = __neigh_lookup_errno(
 #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-		    dev->type == ARPHRD_ATM ? clip_tbl_hook :
+					 dev->type == ARPHRD_ATM ?
+					 clip_tbl_hook :
 #endif
-		    &arp_tbl, &nexthop, dev);
+					 &arp_tbl, &nexthop, dev);
 		if (IS_ERR(n))
 			return PTR_ERR(n);
 		dst->neighbour = n;
@@ -543,8 +554,8 @@
 
 	if (!IN_DEV_PROXY_ARP(in_dev))
 		return 0;
-
-	if ((imi = IN_DEV_MEDIUM_ID(in_dev)) == 0)
+	imi = IN_DEV_MEDIUM_ID(in_dev);
+	if (imi == 0)
 		return 1;
 	if (imi == -1)
 		return 0;
@@ -555,7 +566,7 @@
 	if (out_dev)
 		omi = IN_DEV_MEDIUM_ID(out_dev);
 
-	return (omi != imi && omi != -1);
+	return omi != imi && omi != -1;
 }
 
 /*
@@ -685,7 +696,7 @@
 	arp->ar_pln = 4;
 	arp->ar_op = htons(type);
 
-	arp_ptr=(unsigned char *)(arp+1);
+	arp_ptr = (unsigned char *)(arp + 1);
 
 	memcpy(arp_ptr, src_hw, dev->addr_len);
 	arp_ptr += dev->addr_len;
@@ -735,9 +746,8 @@
 
 	skb = arp_create(type, ptype, dest_ip, dev, src_ip,
 			 dest_hw, src_hw, target_hw);
-	if (skb == NULL) {
+	if (skb == NULL)
 		return;
-	}
 
 	arp_xmit(skb);
 }
@@ -815,7 +825,7 @@
 /*
  *	Extract fields
  */
-	arp_ptr= (unsigned char *)(arp+1);
+	arp_ptr = (unsigned char *)(arp + 1);
 	sha	= arp_ptr;
 	arp_ptr += dev->addr_len;
 	memcpy(&sip, arp_ptr, 4);
@@ -869,16 +879,17 @@
 		addr_type = rt->rt_type;
 
 		if (addr_type == RTN_LOCAL) {
-			int dont_send = 0;
+			int dont_send;
 
-			if (!dont_send)
-				dont_send |= arp_ignore(in_dev,sip,tip);
+			dont_send = arp_ignore(in_dev, sip, tip);
 			if (!dont_send && IN_DEV_ARPFILTER(in_dev))
-				dont_send |= arp_filter(sip,tip,dev);
+				dont_send |= arp_filter(sip, tip, dev);
 			if (!dont_send) {
 				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
 				if (n) {
-					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+					arp_send(ARPOP_REPLY, ETH_P_ARP, sip,
+						 dev, tip, sha, dev->dev_addr,
+						 sha);
 					neigh_release(n);
 				}
 			}
@@ -887,8 +898,7 @@
 			if (addr_type == RTN_UNICAST  &&
 			    (arp_fwd_proxy(in_dev, dev, rt) ||
 			     arp_fwd_pvlan(in_dev, dev, rt, sip, tip) ||
-			     pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))
-			{
+			     pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) {
 				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
 				if (n)
 					neigh_release(n);
@@ -896,9 +906,12 @@
 				if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED ||
 				    skb->pkt_type == PACKET_HOST ||
 				    in_dev->arp_parms->proxy_delay == 0) {
-					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+					arp_send(ARPOP_REPLY, ETH_P_ARP, sip,
+						 dev, tip, sha, dev->dev_addr,
+						 sha);
 				} else {
-					pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb);
+					pneigh_enqueue(&arp_tbl,
+						       in_dev->arp_parms, skb);
 					return 0;
 				}
 				goto out;
@@ -939,7 +952,8 @@
 		if (arp->ar_op != htons(ARPOP_REPLY) ||
 		    skb->pkt_type != PACKET_HOST)
 			state = NUD_STALE;
-		neigh_update(n, sha, state, override ? NEIGH_UPDATE_F_OVERRIDE : 0);
+		neigh_update(n, sha, state,
+			     override ? NEIGH_UPDATE_F_OVERRIDE : 0);
 		neigh_release(n);
 	}
 
@@ -975,7 +989,8 @@
 	    arp->ar_pln != 4)
 		goto freeskb;
 
-	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (skb == NULL)
 		goto out_of_mem;
 
 	memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
@@ -1019,7 +1034,7 @@
 		return -EINVAL;
 	if (!dev && (r->arp_flags & ATF_COM)) {
 		dev = dev_getbyhwaddr(net, r->arp_ha.sa_family,
-				r->arp_ha.sa_data);
+				      r->arp_ha.sa_data);
 		if (!dev)
 			return -ENODEV;
 	}
@@ -1033,7 +1048,7 @@
 }
 
 static int arp_req_set(struct net *net, struct arpreq *r,
-		struct net_device * dev)
+		       struct net_device *dev)
 {
 	__be32 ip;
 	struct neighbour *neigh;
@@ -1046,10 +1061,11 @@
 	if (r->arp_flags & ATF_PERM)
 		r->arp_flags |= ATF_COM;
 	if (dev == NULL) {
-		struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,
-							 .tos = RTO_ONLINK } } };
-		struct rtable * rt;
-		if ((err = ip_route_output_key(net, &rt, &fl)) != 0)
+		struct flowi fl = { .nl_u.ip4_u = { .daddr = ip,
+						    .tos = RTO_ONLINK } };
+		struct rtable *rt;
+		err = ip_route_output_key(net, &rt, &fl);
+		if (err != 0)
 			return err;
 		dev = rt->dst.dev;
 		ip_rt_put(rt);
@@ -1083,9 +1099,9 @@
 		unsigned state = NUD_STALE;
 		if (r->arp_flags & ATF_PERM)
 			state = NUD_PERMANENT;
-		err = neigh_update(neigh, (r->arp_flags&ATF_COM) ?
+		err = neigh_update(neigh, (r->arp_flags & ATF_COM) ?
 				   r->arp_ha.sa_data : NULL, state,
-				   NEIGH_UPDATE_F_OVERRIDE|
+				   NEIGH_UPDATE_F_OVERRIDE |
 				   NEIGH_UPDATE_F_ADMIN);
 		neigh_release(neigh);
 	}
@@ -1094,12 +1110,12 @@
 
 static unsigned arp_state_to_flags(struct neighbour *neigh)
 {
-	unsigned flags = 0;
 	if (neigh->nud_state&NUD_PERMANENT)
-		flags = ATF_PERM|ATF_COM;
+		return ATF_PERM | ATF_COM;
 	else if (neigh->nud_state&NUD_VALID)
-		flags = ATF_COM;
-	return flags;
+		return ATF_COM;
+	else
+		return 0;
 }
 
 /*
@@ -1142,7 +1158,7 @@
 }
 
 static int arp_req_delete(struct net *net, struct arpreq *r,
-		struct net_device * dev)
+			  struct net_device *dev)
 {
 	int err;
 	__be32 ip;
@@ -1153,10 +1169,11 @@
 
 	ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
 	if (dev == NULL) {
-		struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,
-							 .tos = RTO_ONLINK } } };
-		struct rtable * rt;
-		if ((err = ip_route_output_key(net, &rt, &fl)) != 0)
+		struct flowi fl = { .nl_u.ip4_u = { .daddr = ip,
+						    .tos = RTO_ONLINK } };
+		struct rtable *rt;
+		err = ip_route_output_key(net, &rt, &fl);
+		if (err != 0)
 			return err;
 		dev = rt->dst.dev;
 		ip_rt_put(rt);
@@ -1166,7 +1183,7 @@
 	err = -ENXIO;
 	neigh = neigh_lookup(&arp_tbl, &ip, dev);
 	if (neigh) {
-		if (neigh->nud_state&~NUD_NOARP)
+		if (neigh->nud_state & ~NUD_NOARP)
 			err = neigh_update(neigh, NULL, NUD_FAILED,
 					   NEIGH_UPDATE_F_OVERRIDE|
 					   NEIGH_UPDATE_F_ADMIN);
@@ -1186,24 +1203,24 @@
 	struct net_device *dev = NULL;
 
 	switch (cmd) {
-		case SIOCDARP:
-		case SIOCSARP:
-			if (!capable(CAP_NET_ADMIN))
-				return -EPERM;
-		case SIOCGARP:
-			err = copy_from_user(&r, arg, sizeof(struct arpreq));
-			if (err)
-				return -EFAULT;
-			break;
-		default:
-			return -EINVAL;
+	case SIOCDARP:
+	case SIOCSARP:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+	case SIOCGARP:
+		err = copy_from_user(&r, arg, sizeof(struct arpreq));
+		if (err)
+			return -EFAULT;
+		break;
+	default:
+		return -EINVAL;
 	}
 
 	if (r.arp_pa.sa_family != AF_INET)
 		return -EPFNOSUPPORT;
 
 	if (!(r.arp_flags & ATF_PUBL) &&
-	    (r.arp_flags & (ATF_NETMASK|ATF_DONTPUB)))
+	    (r.arp_flags & (ATF_NETMASK | ATF_DONTPUB)))
 		return -EINVAL;
 	if (!(r.arp_flags & ATF_NETMASK))
 		((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr =
@@ -1211,7 +1228,8 @@
 	rtnl_lock();
 	if (r.arp_dev[0]) {
 		err = -ENODEV;
-		if ((dev = __dev_get_by_name(net, r.arp_dev)) == NULL)
+		dev = __dev_get_by_name(net, r.arp_dev);
+		if (dev == NULL)
 			goto out;
 
 		/* Mmmm... It is wrong... ARPHRD_NETROM==0 */
@@ -1243,7 +1261,8 @@
 	return err;
 }
 
-static int arp_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
+static int arp_netdev_event(struct notifier_block *this, unsigned long event,
+			    void *ptr)
 {
 	struct net_device *dev = ptr;
 
@@ -1311,12 +1330,13 @@
 	for (n = 0, s = buf; n < 6; n++) {
 		c = (a->ax25_call[n] >> 1) & 0x7F;
 
-		if (c != ' ') *s++ = c;
+		if (c != ' ')
+			*s++ = c;
 	}
 
 	*s++ = '-';
-
-	if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
+	n = (a->ax25_call[6] >> 1) & 0x0F;
+	if (n > 9) {
 		*s++ = '1';
 		n -= 10;
 	}
@@ -1325,10 +1345,9 @@
 	*s++ = '\0';
 
 	if (*buf == '\0' || *buf == '-')
-	   return "*";
+		return "*";
 
 	return buf;
-
 }
 #endif /* CONFIG_AX25 */
 
@@ -1408,10 +1427,10 @@
 /* ------------------------------------------------------------------------ */
 
 static const struct seq_operations arp_seq_ops = {
-	.start  = arp_seq_start,
-	.next   = neigh_seq_next,
-	.stop   = neigh_seq_stop,
-	.show   = arp_seq_show,
+	.start	= arp_seq_start,
+	.next	= neigh_seq_next,
+	.stop	= neigh_seq_stop,
+	.show	= arp_seq_show,
 };
 
 static int arp_seq_open(struct inode *inode, struct file *file)
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index 721a8a3..174be6c 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -73,6 +73,6 @@
 	inet->inet_id = jiffies;
 
 	sk_dst_set(sk, &rt->dst);
-	return(0);
+	return 0;
 }
 EXPORT_SYMBOL(ip4_datagram_connect);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index da14c49..dc94b03 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -209,7 +209,7 @@
 		inet_free_ifa(ifa);
 	}
 
-	dev->ip_ptr = NULL;
+	rcu_assign_pointer(dev->ip_ptr, NULL);
 
 	devinet_sysctl_unregister(in_dev);
 	neigh_parms_release(&arp_tbl, in_dev->arp_parms);
@@ -403,6 +403,9 @@
 	return inet_insert_ifa(ifa);
 }
 
+/* Caller must hold RCU or RTNL :
+ * We dont take a reference on found in_device
+ */
 struct in_device *inetdev_by_index(struct net *net, int ifindex)
 {
 	struct net_device *dev;
@@ -411,7 +414,7 @@
 	rcu_read_lock();
 	dev = dev_get_by_index_rcu(net, ifindex);
 	if (dev)
-		in_dev = in_dev_get(dev);
+		in_dev = rcu_dereference_rtnl(dev->ip_ptr);
 	rcu_read_unlock();
 	return in_dev;
 }
@@ -453,8 +456,6 @@
 		goto errout;
 	}
 
-	__in_dev_put(in_dev);
-
 	for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
 	     ifap = &ifa->ifa_next) {
 		if (tb[IFA_LOCAL] &&
@@ -1059,7 +1060,7 @@
 	switch (event) {
 	case NETDEV_REGISTER:
 		printk(KERN_DEBUG "inetdev_event: bug\n");
-		dev->ip_ptr = NULL;
+		rcu_assign_pointer(dev->ip_ptr, NULL);
 		break;
 	case NETDEV_UP:
 		if (!inetdev_valid_mtu(dev->mtu))
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 7d02a9f..36e27c2 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -147,35 +147,43 @@
 		rt_cache_flush(net, -1);
 }
 
-/*
- *	Find the first device with a given source address.
+/**
+ * __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)
+struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
 {
-	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
-	struct fib_result res;
+	struct flowi fl = {
+		.nl_u = {
+			.ip4_u = {
+				.daddr = addr
+			}
+		},
+		.flags = FLOWI_FLAG_MATCH_ANY_IIF
+	};
+	struct fib_result res = { 0 };
 	struct net_device *dev = NULL;
-	struct fib_table *local_table;
 
-#ifdef CONFIG_IP_MULTIPLE_TABLES
-	res.r = NULL;
-#endif
-
-	local_table = fib_get_table(net, RT_TABLE_LOCAL);
-	if (!local_table || fib_table_lookup(local_table, &fl, &res))
+	rcu_read_lock();
+	if (fib_lookup(net, &fl, &res)) {
+		rcu_read_unlock();
 		return NULL;
+	}
 	if (res.type != RTN_LOCAL)
 		goto out;
 	dev = FIB_RES_DEV(res);
 
-	if (dev)
+	if (dev && devref)
 		dev_hold(dev);
 out:
-	fib_res_put(&res);
+	rcu_read_unlock();
 	return dev;
 }
-EXPORT_SYMBOL(ip_dev_find);
+EXPORT_SYMBOL(__ip_dev_find);
 
 /*
  * Find address type as if only "dev" was present in the system. If
@@ -202,11 +210,12 @@
 	local_table = fib_get_table(net, RT_TABLE_LOCAL);
 	if (local_table) {
 		ret = RTN_UNICAST;
-		if (!fib_table_lookup(local_table, &fl, &res)) {
+		rcu_read_lock();
+		if (!fib_table_lookup(local_table, &fl, &res, FIB_LOOKUP_NOREF)) {
 			if (!dev || dev == res.fi->fib_dev)
 				ret = res.type;
-			fib_res_put(&res);
 		}
+		rcu_read_unlock();
 	}
 	return ret;
 }
@@ -220,30 +229,34 @@
 unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev,
 				__be32 addr)
 {
-       return __inet_dev_addr_type(net, dev, addr);
+	return __inet_dev_addr_type(net, dev, addr);
 }
 EXPORT_SYMBOL(inet_dev_addr_type);
 
 /* Given (packet source, input interface) and optional (dst, oif, tos):
-   - (main) check, that source is valid i.e. not broadcast or our local
-     address.
-   - figure out what "logical" interface this packet arrived
-     and calculate "specific destination" address.
-   - check, that packet arrived from expected physical interface.
+ * - (main) check, that source is valid i.e. not broadcast or our local
+ *   address.
+ * - figure out what "logical" interface this packet arrived
+ *   and calculate "specific destination" address.
+ * - check, that packet arrived from expected physical interface.
+ * called with rcu_read_lock()
  */
-
 int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
 			struct net_device *dev, __be32 *spec_dst,
 			u32 *itag, u32 mark)
 {
 	struct in_device *in_dev;
-	struct flowi fl = { .nl_u = { .ip4_u =
-				      { .daddr = src,
-					.saddr = dst,
-					.tos = tos } },
-			    .mark = mark,
-			    .iif = oif };
-
+	struct flowi fl = {
+		.nl_u = {
+			.ip4_u = {
+				.daddr = src,
+				.saddr = dst,
+				.tos = tos
+			}
+		},
+		.mark = mark,
+		.iif = oif
+	};
 	struct fib_result res;
 	int no_addr, rpf, accept_local;
 	bool dev_match;
@@ -251,7 +264,6 @@
 	struct net *net;
 
 	no_addr = rpf = accept_local = 0;
-	rcu_read_lock();
 	in_dev = __in_dev_get_rcu(dev);
 	if (in_dev) {
 		no_addr = in_dev->ifa_list == NULL;
@@ -260,7 +272,6 @@
 		if (mark && !IN_DEV_SRC_VMARK(in_dev))
 			fl.mark = 0;
 	}
-	rcu_read_unlock();
 
 	if (in_dev == NULL)
 		goto e_inval;
@@ -270,7 +281,7 @@
 		goto last_resort;
 	if (res.type != RTN_UNICAST) {
 		if (res.type != RTN_LOCAL || !accept_local)
-			goto e_inval_res;
+			goto e_inval;
 	}
 	*spec_dst = FIB_RES_PREFSRC(res);
 	fib_combine_itag(itag, &res);
@@ -291,10 +302,8 @@
 #endif
 	if (dev_match) {
 		ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
-		fib_res_put(&res);
 		return ret;
 	}
-	fib_res_put(&res);
 	if (no_addr)
 		goto last_resort;
 	if (rpf == 1)
@@ -307,7 +316,6 @@
 			*spec_dst = FIB_RES_PREFSRC(res);
 			ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
 		}
-		fib_res_put(&res);
 	}
 	return ret;
 
@@ -318,8 +326,6 @@
 	*itag = 0;
 	return 0;
 
-e_inval_res:
-	fib_res_put(&res);
 e_inval:
 	return -EINVAL;
 e_rpf:
@@ -472,9 +478,9 @@
 }
 
 /*
- *	Handle IP routing ioctl calls. These are used to manipulate the routing tables
+ * Handle IP routing ioctl calls.
+ * These are used to manipulate the routing tables
  */
-
 int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 {
 	struct fib_config cfg;
@@ -518,7 +524,7 @@
 	return -EINVAL;
 }
 
-const struct nla_policy rtm_ipv4_policy[RTA_MAX+1] = {
+const struct nla_policy rtm_ipv4_policy[RTA_MAX + 1] = {
 	[RTA_DST]		= { .type = NLA_U32 },
 	[RTA_SRC]		= { .type = NLA_U32 },
 	[RTA_IIF]		= { .type = NLA_U32 },
@@ -532,7 +538,7 @@
 };
 
 static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
-			    struct nlmsghdr *nlh, struct fib_config *cfg)
+			     struct nlmsghdr *nlh, struct fib_config *cfg)
 {
 	struct nlattr *attr;
 	int err, remaining;
@@ -687,12 +693,11 @@
 }
 
 /* Prepare and feed intra-kernel routing request.
-   Really, it should be netlink message, but :-( netlink
-   can be not configured, so that we feed it directly
-   to fib engine. It is legal, because all events occur
-   only when netlink is already locked.
+ * Really, it should be netlink message, but :-( netlink
+ * can be not configured, so that we feed it directly
+ * to fib engine. It is legal, because all events occur
+ * only when netlink is already locked.
  */
-
 static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
 {
 	struct net *net = dev_net(ifa->ifa_dev->dev);
@@ -738,9 +743,9 @@
 	struct in_ifaddr *prim = ifa;
 	__be32 mask = ifa->ifa_mask;
 	__be32 addr = ifa->ifa_local;
-	__be32 prefix = ifa->ifa_address&mask;
+	__be32 prefix = ifa->ifa_address & mask;
 
-	if (ifa->ifa_flags&IFA_F_SECONDARY) {
+	if (ifa->ifa_flags & IFA_F_SECONDARY) {
 		prim = inet_ifa_byprefix(in_dev, prefix, mask);
 		if (prim == NULL) {
 			printk(KERN_WARNING "fib_add_ifaddr: bug: prim == NULL\n");
@@ -750,22 +755,24 @@
 
 	fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);
 
-	if (!(dev->flags&IFF_UP))
+	if (!(dev->flags & IFF_UP))
 		return;
 
 	/* Add broadcast address, if it is explicitly assigned. */
 	if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF))
 		fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
 
-	if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&
+	if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) &&
 	    (prefix != addr || ifa->ifa_prefixlen < 32)) {
-		fib_magic(RTM_NEWROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
-			  RTN_UNICAST, prefix, ifa->ifa_prefixlen, prim);
+		fib_magic(RTM_NEWROUTE,
+			  dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
+			  prefix, ifa->ifa_prefixlen, prim);
 
 		/* Add network specific broadcasts, when it takes a sense */
 		if (ifa->ifa_prefixlen < 31) {
 			fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim);
-			fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix|~mask, 32, prim);
+			fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix | ~mask,
+				  32, prim);
 		}
 	}
 }
@@ -776,17 +783,18 @@
 	struct net_device *dev = in_dev->dev;
 	struct in_ifaddr *ifa1;
 	struct in_ifaddr *prim = ifa;
-	__be32 brd = ifa->ifa_address|~ifa->ifa_mask;
-	__be32 any = ifa->ifa_address&ifa->ifa_mask;
+	__be32 brd = ifa->ifa_address | ~ifa->ifa_mask;
+	__be32 any = ifa->ifa_address & ifa->ifa_mask;
 #define LOCAL_OK	1
 #define BRD_OK		2
 #define BRD0_OK		4
 #define BRD1_OK		8
 	unsigned ok = 0;
 
-	if (!(ifa->ifa_flags&IFA_F_SECONDARY))
-		fib_magic(RTM_DELROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
-			  RTN_UNICAST, any, ifa->ifa_prefixlen, prim);
+	if (!(ifa->ifa_flags & IFA_F_SECONDARY))
+		fib_magic(RTM_DELROUTE,
+			  dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
+			  any, ifa->ifa_prefixlen, prim);
 	else {
 		prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask);
 		if (prim == NULL) {
@@ -796,9 +804,9 @@
 	}
 
 	/* Deletion is more complicated than add.
-	   We should take care of not to delete too much :-)
-
-	   Scan address list to be sure that addresses are really gone.
+	 * We should take care of not to delete too much :-)
+	 *
+	 * Scan address list to be sure that addresses are really gone.
 	 */
 
 	for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {
@@ -812,23 +820,23 @@
 			ok |= BRD0_OK;
 	}
 
-	if (!(ok&BRD_OK))
+	if (!(ok & BRD_OK))
 		fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
-	if (!(ok&BRD1_OK))
+	if (!(ok & BRD1_OK))
 		fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim);
-	if (!(ok&BRD0_OK))
+	if (!(ok & BRD0_OK))
 		fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim);
-	if (!(ok&LOCAL_OK)) {
+	if (!(ok & LOCAL_OK)) {
 		fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
 
 		/* Check, that this local address finally disappeared. */
 		if (inet_addr_type(dev_net(dev), ifa->ifa_local) != RTN_LOCAL) {
 			/* And the last, but not the least thing.
-			   We must flush stray FIB entries.
-
-			   First of all, we scan fib_info list searching
-			   for stray nexthop entries, then ignite fib_flush.
-			*/
+			 * We must flush stray FIB entries.
+			 *
+			 * First of all, we scan fib_info list searching
+			 * for stray nexthop entries, then ignite fib_flush.
+			 */
 			if (fib_sync_down_addr(dev_net(dev), ifa->ifa_local))
 				fib_flush(dev_net(dev));
 		}
@@ -839,14 +847,20 @@
 #undef BRD1_OK
 }
 
-static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
+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,
-				       .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
-							    .tos = frn->fl_tos,
-							    .scope = frn->fl_scope } } };
+	struct flowi            fl = {
+		.mark = frn->fl_mark,
+		.nl_u = {
+			.ip4_u = {
+				.daddr = frn->fl_addr,
+				.tos = frn->fl_tos,
+				.scope = frn->fl_scope
+			}
+		}
+	};
 
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	res.r = NULL;
@@ -857,15 +871,16 @@
 		local_bh_disable();
 
 		frn->tb_id = tb->tb_id;
-		frn->err = fib_table_lookup(tb, &fl, &res);
+		rcu_read_lock();
+		frn->err = fib_table_lookup(tb, &fl, &res, FIB_LOOKUP_NOREF);
 
 		if (!frn->err) {
 			frn->prefixlen = res.prefixlen;
 			frn->nh_sel = res.nh_sel;
 			frn->type = res.type;
 			frn->scope = res.scope;
-			fib_res_put(&res);
 		}
+		rcu_read_unlock();
 		local_bh_enable();
 	}
 }
@@ -894,8 +909,8 @@
 
 	nl_fib_lookup(frn, tb);
 
-	pid = NETLINK_CB(skb).pid;       /* pid of sending process */
-	NETLINK_CB(skb).pid = 0;         /* from kernel */
+	pid = NETLINK_CB(skb).pid;      /* pid of sending process */
+	NETLINK_CB(skb).pid = 0;        /* from kernel */
 	NETLINK_CB(skb).dst_group = 0;  /* unicast */
 	netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT);
 }
@@ -942,7 +957,7 @@
 		fib_del_ifaddr(ifa);
 		if (ifa->ifa_dev->ifa_list == NULL) {
 			/* Last address was deleted from this interface.
-			   Disable IP.
+			 * Disable IP.
 			 */
 			fib_disable_ip(dev, 1, 0);
 		} else {
@@ -1001,16 +1016,15 @@
 static int __net_init ip_fib_net_init(struct net *net)
 {
 	int err;
-	unsigned int i;
+	size_t size = sizeof(struct hlist_head) * FIB_TABLE_HASHSZ;
 
-	net->ipv4.fib_table_hash = kzalloc(
-			sizeof(struct hlist_head)*FIB_TABLE_HASHSZ, GFP_KERNEL);
+	/* Avoid false sharing : Use at least a full cache line */
+	size = max_t(size_t, size, L1_CACHE_BYTES);
+
+	net->ipv4.fib_table_hash = kzalloc(size, GFP_KERNEL);
 	if (net->ipv4.fib_table_hash == NULL)
 		return -ENOMEM;
 
-	for (i = 0; i < FIB_TABLE_HASHSZ; i++)
-		INIT_HLIST_HEAD(&net->ipv4.fib_table_hash[i]);
-
 	err = fib4_rules_init(net);
 	if (err < 0)
 		goto fail;
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 4ed7e0d..43e1c59 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -54,36 +54,37 @@
 	struct fib_alias        fn_embedded_alias;
 };
 
+#define EMBEDDED_HASH_SIZE (L1_CACHE_BYTES / sizeof(struct hlist_head))
+
 struct fn_zone {
-	struct fn_zone		*fz_next;	/* Next not empty zone	*/
-	struct hlist_head	*fz_hash;	/* Hash table pointer	*/
-	int			fz_nent;	/* Number of entries	*/
-
-	int			fz_divisor;	/* Hash divisor		*/
+	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)	*/
-#define FZ_HASHMASK(fz)		((fz)->fz_hashmask)
 
-	int			fz_order;	/* Zone order		*/
-	__be32			fz_mask;
+	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)	*/
 };
 
-/* NOTE. On fast computers evaluation of fz_hashmask and fz_mask
- * can be cheaper than memory lookup, so that FZ_* macros are used.
- */
-
 struct fn_hash {
-	struct fn_zone	*fn_zones[33];
-	struct fn_zone	*fn_zone_list;
+	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)>>(32 - fz->fz_order);
+	u32 h = ntohl(key) >> fz->fz_revorder;
 	h ^= (h>>20);
 	h ^= (h>>10);
 	h ^= (h>>5);
-	h &= FZ_HASHMASK(fz);
+	h &= fz->fz_hashmask;
 	return h;
 }
 
@@ -92,7 +93,6 @@
 	return dst & FZ_MASK(fz);
 }
 
-static DEFINE_RWLOCK(fib_hash_lock);
 static unsigned int fib_hash_genid;
 
 #define FZ_MAX_DIVISOR ((PAGE_SIZE<<MAX_ORDER) / sizeof(struct hlist_head))
@@ -101,12 +101,11 @@
 {
 	unsigned long size = divisor * sizeof(struct hlist_head);
 
-	if (size <= PAGE_SIZE) {
+	if (size <= PAGE_SIZE)
 		return kzalloc(size, GFP_KERNEL);
-	} else {
-		return (struct hlist_head *)
-			__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(size));
-	}
+
+	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. */
@@ -121,12 +120,12 @@
 		struct fib_node *f;
 
 		hlist_for_each_entry_safe(f, node, n, &old_ht[i], fn_hash) {
-			struct hlist_head *new_head;
+			struct hlist_head __rcu *new_head;
 
-			hlist_del(&f->fn_hash);
+			hlist_del_rcu(&f->fn_hash);
 
 			new_head = &fz->fz_hash[fn_hash(f->fn_key, fz)];
-			hlist_add_head(&f->fn_hash, new_head);
+			hlist_add_head_rcu(&f->fn_hash, new_head);
 		}
 	}
 }
@@ -147,14 +146,14 @@
 	int old_divisor, new_divisor;
 	u32 new_hashmask;
 
-	old_divisor = fz->fz_divisor;
+	new_divisor = old_divisor = fz->fz_divisor;
 
 	switch (old_divisor) {
-	case 16:
-		new_divisor = 256;
+	case EMBEDDED_HASH_SIZE:
+		new_divisor *= EMBEDDED_HASH_SIZE;
 		break;
-	case 256:
-		new_divisor = 1024;
+	case EMBEDDED_HASH_SIZE*EMBEDDED_HASH_SIZE:
+		new_divisor *= (EMBEDDED_HASH_SIZE/2);
 		break;
 	default:
 		if ((old_divisor << 1) > FZ_MAX_DIVISOR) {
@@ -175,31 +174,55 @@
 	ht = fz_hash_alloc(new_divisor);
 
 	if (ht)	{
-		write_lock_bh(&fib_hash_lock);
+		struct fn_zone nfz;
+
+		memcpy(&nfz, fz, sizeof(nfz));
+
+		write_seqlock_bh(&fz->fz_lock);
 		old_ht = fz->fz_hash;
-		fz->fz_hash = ht;
+		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;
-		fn_rebuild_zone(fz, old_ht, old_divisor);
-		fib_hash_genid++;
-		write_unlock_bh(&fib_hash_lock);
+		write_sequnlock_bh(&fz->fz_lock);
 
-		fz_hash_free(old_ht, old_divisor);
+		if (old_ht != fz->fz_embedded_hash) {
+			synchronize_rcu();
+			fz_hash_free(old_ht, old_divisor);
+		}
 	}
 }
 
-static inline void fn_free_node(struct fib_node * f)
+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
-		kmem_cache_free(fn_alias_kmem, fa);
+		call_rcu(&fa->rcu, fn_free_alias_rcu);
 }
 
 static struct fn_zone *
@@ -210,68 +233,71 @@
 	if (!fz)
 		return NULL;
 
-	if (z) {
-		fz->fz_divisor = 16;
-	} else {
-		fz->fz_divisor = 1;
-	}
-	fz->fz_hashmask = (fz->fz_divisor - 1);
-	fz->fz_hash = fz_hash_alloc(fz->fz_divisor);
-	if (!fz->fz_hash) {
-		kfree(fz);
-		return NULL;
-	}
+	seqlock_init(&fz->fz_lock);
+	fz->fz_divisor = z ? EMBEDDED_HASH_SIZE : 1;
+	fz->fz_hashmask = fz->fz_divisor - 1;
+	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++)
+	for (i = z + 1; i <= 32; i++)
 		if (table->fn_zones[i])
 			break;
-	write_lock_bh(&fib_hash_lock);
-	if (i>32) {
+	if (i > 32) {
 		/* No more specific masks, we are the first. */
-		fz->fz_next = table->fn_zone_list;
-		table->fn_zone_list = fz;
+		rcu_assign_pointer(fz->fz_next,
+				   rtnl_dereference(table->fn_zone_list));
+		rcu_assign_pointer(table->fn_zone_list, fz);
 	} else {
-		fz->fz_next = table->fn_zones[i]->fz_next;
-		table->fn_zones[i]->fz_next = fz;
+		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++;
-	write_unlock_bh(&fib_hash_lock);
 	return fz;
 }
 
 int fib_table_lookup(struct fib_table *tb,
-		     const struct flowi *flp, struct fib_result *res)
+		     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;
 
-	read_lock(&fib_hash_lock);
-	for (fz = t->fn_zone_list; fz; fz = fz->fz_next) {
-		struct hlist_head *head;
+	rcu_read_lock();
+	for (fz = rcu_dereference(t->fn_zone_list);
+	     fz != NULL;
+	     fz = rcu_dereference(fz->fz_next)) {
+		struct hlist_head __rcu *head;
 		struct hlist_node *node;
 		struct fib_node *f;
-		__be32 k = fz_key(flp->fl4_dst, fz);
+		__be32 k;
+		unsigned int seq;
 
-		head = &fz->fz_hash[fn_hash(k, fz)];
-		hlist_for_each_entry(f, node, head, fn_hash) {
-			if (f->fn_key != k)
-				continue;
+		do {
+			seq = read_seqbegin(&fz->fz_lock);
+			k = fz_key(flp->fl4_dst, fz);
 
-			err = fib_semantic_match(&f->fn_alias,
+			head = &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);
-			if (err <= 0)
-				goto out;
-		}
+						 fz->fz_order, fib_flags);
+				if (err <= 0)
+					goto out;
+			}
+		} while (read_seqretry(&fz->fz_lock, seq));
 	}
 	err = 1;
 out:
-	read_unlock(&fib_hash_lock);
+	rcu_read_unlock();
 	return err;
 }
 
@@ -293,11 +319,11 @@
 	last_resort = NULL;
 	order = -1;
 
-	read_lock(&fib_hash_lock);
-	hlist_for_each_entry(f, node, &fz->fz_hash[0], fn_hash) {
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(f, node, &fz->fz_hash[0], fn_hash) {
 		struct fib_alias *fa;
 
-		list_for_each_entry(fa, &f->fn_alias, fa_list) {
+		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 ||
@@ -309,7 +335,8 @@
 			if (!next_fi->fib_nh[0].nh_gw ||
 			    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
 				continue;
-			fa->fa_state |= FA_S_ACCESSED;
+
+			fib_alias_accessed(fa);
 
 			if (fi == NULL) {
 				if (next_fi != res->fi)
@@ -341,7 +368,7 @@
 		fib_result_assign(res, last_resort);
 	tb->tb_default = last_idx;
 out:
-	read_unlock(&fib_hash_lock);
+	rcu_read_unlock();
 }
 
 /* Insert node F to FZ. */
@@ -349,7 +376,7 @@
 {
 	struct hlist_head *head = &fz->fz_hash[fn_hash(f->fn_key, fz)];
 
-	hlist_add_head(&f->fn_hash, head);
+	hlist_add_head_rcu(&f->fn_hash, head);
 }
 
 /* Return the node in FZ matching KEY. */
@@ -359,7 +386,7 @@
 	struct hlist_node *node;
 	struct fib_node *f;
 
-	hlist_for_each_entry(f, node, head, fn_hash) {
+	hlist_for_each_entry_rcu(f, node, head, fn_hash) {
 		if (f->fn_key == key)
 			return f;
 	}
@@ -367,6 +394,17 @@
 	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;
@@ -451,7 +489,6 @@
 		}
 
 		if (cfg->fc_nlflags & NLM_F_REPLACE) {
-			struct fib_info *fi_drop;
 			u8 state;
 
 			fa = fa_first;
@@ -460,21 +497,25 @@
 					err = 0;
 				goto out;
 			}
-			write_lock_bh(&fib_hash_lock);
-			fi_drop = fa->fa_info;
-			fa->fa_info = fi;
-			fa->fa_type = cfg->fc_type;
-			fa->fa_scope = cfg->fc_scope;
-			state = fa->fa_state;
-			fa->fa_state &= ~FA_S_ACCESSED;
-			fib_hash_genid++;
-			write_unlock_bh(&fib_hash_lock);
+			err = -ENOBUFS;
+			new_fa = fib_fast_alloc(f);
+			if (new_fa == NULL)
+				goto out;
 
-			fib_release_info(fi_drop);
+			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, fa, cfg->fc_dst_len, tb->tb_id,
-				  &cfg->fc_nlinfo, NLM_F_REPLACE);
+			rtmsg_fib(RTM_NEWROUTE, key, new_fa, cfg->fc_dst_len,
+				  tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
 			return 0;
 		}
 
@@ -506,12 +547,10 @@
 		f = new_f;
 	}
 
-	new_fa = &f->fn_embedded_alias;
-	if (new_fa->fa_info != NULL) {
-		new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
-		if (new_fa == NULL)
-			goto out;
-	}
+	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;
@@ -522,13 +561,11 @@
 	 * Insert new entry to the list.
 	 */
 
-	write_lock_bh(&fib_hash_lock);
 	if (new_f)
 		fib_insert_node(fz, new_f);
-	list_add_tail(&new_fa->fa_list,
+	list_add_tail_rcu(&new_fa->fa_list,
 		 (fa ? &fa->fa_list : &f->fn_alias));
 	fib_hash_genid++;
-	write_unlock_bh(&fib_hash_lock);
 
 	if (new_f)
 		fz->fz_nent++;
@@ -603,14 +640,12 @@
 			  tb->tb_id, &cfg->fc_nlinfo, 0);
 
 		kill_fn = 0;
-		write_lock_bh(&fib_hash_lock);
-		list_del(&fa->fa_list);
+		list_del_rcu(&fa->fa_list);
 		if (list_empty(&f->fn_alias)) {
-			hlist_del(&f->fn_hash);
+			hlist_del_rcu(&f->fn_hash);
 			kill_fn = 1;
 		}
 		fib_hash_genid++;
-		write_unlock_bh(&fib_hash_lock);
 
 		if (fa->fa_state & FA_S_ACCESSED)
 			rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
@@ -641,14 +676,12 @@
 			struct fib_info *fi = fa->fa_info;
 
 			if (fi && (fi->fib_flags&RTNH_F_DEAD)) {
-				write_lock_bh(&fib_hash_lock);
-				list_del(&fa->fa_list);
+				list_del_rcu(&fa->fa_list);
 				if (list_empty(&f->fn_alias)) {
-					hlist_del(&f->fn_hash);
+					hlist_del_rcu(&f->fn_hash);
 					kill_f = 1;
 				}
 				fib_hash_genid++;
-				write_unlock_bh(&fib_hash_lock);
 
 				fn_free_alias(fa, f);
 				found++;
@@ -662,13 +695,16 @@
 	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 = table->fn_zone_list; fz; fz = fz->fz_next) {
+	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--)
@@ -690,10 +726,10 @@
 
 	s_i = cb->args[4];
 	i = 0;
-	hlist_for_each_entry(f, node, head, fn_hash) {
+	hlist_for_each_entry_rcu(f, node, head, fn_hash) {
 		struct fib_alias *fa;
 
-		list_for_each_entry(fa, &f->fn_alias, fa_list) {
+		list_for_each_entry_rcu(fa, &f->fn_alias, fa_list) {
 			if (i < s_i)
 				goto next;
 
@@ -711,7 +747,7 @@
 				cb->args[4] = i;
 				return -1;
 			}
-		next:
+next:
 			i++;
 		}
 	}
@@ -746,23 +782,26 @@
 int fib_table_dump(struct fib_table *tb, struct sk_buff *skb,
 		   struct netlink_callback *cb)
 {
-	int m, s_m;
+	int m = 0, s_m;
 	struct fn_zone *fz;
 	struct fn_hash *table = (struct fn_hash *)tb->tb_data;
 
 	s_m = cb->args[2];
-	read_lock(&fib_hash_lock);
-	for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) {
-		if (m < s_m) continue;
+	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;
-			read_unlock(&fib_hash_lock);
+			rcu_read_unlock();
 			return -1;
 		}
 		memset(&cb->args[3], 0,
 		       sizeof(cb->args) - 3*sizeof(cb->args[0]));
 	}
-	read_unlock(&fib_hash_lock);
+	rcu_read_unlock();
 	cb->args[2] = m;
 	return skb->len;
 }
@@ -825,8 +864,9 @@
 	iter->genid	= fib_hash_genid;
 	iter->valid	= 1;
 
-	for (iter->zone = table->fn_zone_list; iter->zone;
-	     iter->zone = iter->zone->fz_next) {
+	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)
@@ -911,7 +951,7 @@
 			}
 		}
 
-		iter->zone = iter->zone->fz_next;
+		iter->zone = rcu_dereference(iter->zone->fz_next);
 
 		if (!iter->zone)
 			goto out;
@@ -950,11 +990,11 @@
 }
 
 static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
-	__acquires(fib_hash_lock)
+	__acquires(RCU)
 {
 	void *v = NULL;
 
-	read_lock(&fib_hash_lock);
+	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;
@@ -967,15 +1007,16 @@
 }
 
 static void fib_seq_stop(struct seq_file *seq, void *v)
-	__releases(fib_hash_lock)
+	__releases(RCU)
 {
-	read_unlock(&fib_hash_lock);
+	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,
+		[7] = RTF_REJECT,
+		[8] = RTF_REJECT,
 	};
 	unsigned flags = type2flags[type];
 
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index 637b133..a29edf2 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -12,17 +12,22 @@
 	u8			fa_type;
 	u8			fa_scope;
 	u8			fa_state;
-#ifdef CONFIG_IP_FIB_TRIE
 	struct rcu_head		rcu;
-#endif
 };
 
 #define FA_S_ACCESSED	0x01
 
+/* Dont write on fa_state unless needed, to keep it shared on all cpus */
+static inline void fib_alias_accessed(struct fib_alias *fa)
+{
+	if (!(fa->fa_state & FA_S_ACCESSED))
+		fa->fa_state |= FA_S_ACCESSED;
+}
+
 /* Exported by fib_semantics.c */
 extern int fib_semantic_match(struct list_head *head,
 			      const struct flowi *flp,
-			      struct fib_result *res, int prefixlen);
+			      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);
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 76daeb5..7981a24 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -6,7 +6,7 @@
  *		IPv4 Forwarding Information Base: policy rules.
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
- * 		Thomas Graf <tgraf@suug.ch>
+ *		Thomas Graf <tgraf@suug.ch>
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -14,7 +14,7 @@
  *		2 of the License, or (at your option) any later version.
  *
  * Fixes:
- * 		Rani Assaf	:	local_rule cannot be deleted
+ *		Rani Assaf	:	local_rule cannot be deleted
  *		Marc Boucher	:	routing by fwmark
  */
 
@@ -32,8 +32,7 @@
 #include <net/ip_fib.h>
 #include <net/fib_rules.h>
 
-struct fib4_rule
-{
+struct fib4_rule {
 	struct fib_rule		common;
 	u8			dst_len;
 	u8			src_len;
@@ -58,6 +57,7 @@
 {
 	struct fib_lookup_arg arg = {
 		.result = res,
+		.flags = FIB_LOOKUP_NOREF,
 	};
 	int err;
 
@@ -91,10 +91,11 @@
 		goto errout;
 	}
 
-	if ((tbl = fib_get_table(rule->fr_net, rule->table)) == NULL)
+	tbl = fib_get_table(rule->fr_net, rule->table);
+	if (!tbl)
 		goto errout;
 
-	err = fib_table_lookup(tbl, flp, (struct fib_result *) arg->result);
+	err = fib_table_lookup(tbl, flp, (struct fib_result *) arg->result, arg->flags);
 	if (err > 0)
 		err = -EAGAIN;
 errout:
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 20f09c5..3e0da3e 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -60,21 +60,30 @@
 
 static DEFINE_SPINLOCK(fib_multipath_lock);
 
-#define for_nexthops(fi) { int nhsel; const struct fib_nh * nh; \
-for (nhsel=0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
+#define for_nexthops(fi) {						\
+	int nhsel; const struct fib_nh *nh;				\
+	for (nhsel = 0, nh = (fi)->fib_nh;				\
+	     nhsel < (fi)->fib_nhs;					\
+	     nh++, nhsel++)
 
-#define change_nexthops(fi) { int nhsel; struct fib_nh *nexthop_nh; \
-for (nhsel=0, nexthop_nh = (struct fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nexthop_nh++, nhsel++)
+#define change_nexthops(fi) {						\
+	int nhsel; struct fib_nh *nexthop_nh;				\
+	for (nhsel = 0,	nexthop_nh = (struct fib_nh *)((fi)->fib_nh);	\
+	     nhsel < (fi)->fib_nhs;					\
+	     nexthop_nh++, nhsel++)
 
 #else /* CONFIG_IP_ROUTE_MULTIPATH */
 
 /* Hope, that gcc will optimize it to get rid of dummy loop */
 
-#define for_nexthops(fi) { int nhsel = 0; const struct fib_nh * nh = (fi)->fib_nh; \
-for (nhsel=0; nhsel < 1; nhsel++)
+#define for_nexthops(fi) {						\
+	int nhsel; const struct fib_nh *nh = (fi)->fib_nh;		\
+	for (nhsel = 0; nhsel < 1; nhsel++)
 
-#define change_nexthops(fi) { int nhsel = 0; struct fib_nh *nexthop_nh = (struct fib_nh *)((fi)->fib_nh); \
-for (nhsel=0; nhsel < 1; nhsel++)
+#define change_nexthops(fi) {						\
+	int nhsel;							\
+	struct fib_nh *nexthop_nh = (struct fib_nh *)((fi)->fib_nh);	\
+	for (nhsel = 0; nhsel < 1; nhsel++)
 
 #endif /* CONFIG_IP_ROUTE_MULTIPATH */
 
@@ -86,63 +95,70 @@
 	int	error;
 	u8	scope;
 } fib_props[RTN_MAX + 1] = {
-	{
+	[RTN_UNSPEC] = {
 		.error	= 0,
 		.scope	= RT_SCOPE_NOWHERE,
-	},	/* RTN_UNSPEC */
-	{
+	},
+	[RTN_UNICAST] = {
 		.error	= 0,
 		.scope	= RT_SCOPE_UNIVERSE,
-	},	/* RTN_UNICAST */
-	{
+	},
+	[RTN_LOCAL] = {
 		.error	= 0,
 		.scope	= RT_SCOPE_HOST,
-	},	/* RTN_LOCAL */
-	{
+	},
+	[RTN_BROADCAST] = {
 		.error	= 0,
 		.scope	= RT_SCOPE_LINK,
-	},	/* RTN_BROADCAST */
-	{
+	},
+	[RTN_ANYCAST] = {
 		.error	= 0,
 		.scope	= RT_SCOPE_LINK,
-	},	/* RTN_ANYCAST */
-	{
+	},
+	[RTN_MULTICAST] = {
 		.error	= 0,
 		.scope	= RT_SCOPE_UNIVERSE,
-	},	/* RTN_MULTICAST */
-	{
+	},
+	[RTN_BLACKHOLE] = {
 		.error	= -EINVAL,
 		.scope	= RT_SCOPE_UNIVERSE,
-	},	/* RTN_BLACKHOLE */
-	{
+	},
+	[RTN_UNREACHABLE] = {
 		.error	= -EHOSTUNREACH,
 		.scope	= RT_SCOPE_UNIVERSE,
-	},	/* RTN_UNREACHABLE */
-	{
+	},
+	[RTN_PROHIBIT] = {
 		.error	= -EACCES,
 		.scope	= RT_SCOPE_UNIVERSE,
-	},	/* RTN_PROHIBIT */
-	{
+	},
+	[RTN_THROW] = {
 		.error	= -EAGAIN,
 		.scope	= RT_SCOPE_UNIVERSE,
-	},	/* RTN_THROW */
-	{
+	},
+	[RTN_NAT] = {
 		.error	= -EINVAL,
 		.scope	= RT_SCOPE_NOWHERE,
-	},	/* RTN_NAT */
-	{
+	},
+	[RTN_XRESOLVE] = {
 		.error	= -EINVAL,
 		.scope	= RT_SCOPE_NOWHERE,
-	},	/* RTN_XRESOLVE */
+	},
 };
 
 
 /* Release a nexthop info record */
 
+static void free_fib_info_rcu(struct rcu_head *head)
+{
+	struct fib_info *fi = container_of(head, struct fib_info, rcu);
+
+	kfree(fi);
+}
+
 void free_fib_info(struct fib_info *fi)
 {
 	if (fi->fib_dead == 0) {
-		printk(KERN_WARNING "Freeing alive fib_info %p\n", fi);
+		pr_warning("Freeing alive fib_info %p\n", fi);
 		return;
 	}
 	change_nexthops(fi) {
@@ -152,7 +168,7 @@
 	} endfor_nexthops(fi);
 	fib_info_cnt--;
 	release_net(fi->fib_net);
-	kfree(fi);
+	call_rcu(&fi->rcu, free_fib_info_rcu);
 }
 
 void fib_release_info(struct fib_info *fi)
@@ -173,7 +189,7 @@
 	spin_unlock_bh(&fib_info_lock);
 }
 
-static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi)
+static inline int nh_comp(const struct fib_info *fi, const struct fib_info *ofi)
 {
 	const struct fib_nh *onh = ofi->fib_nh;
 
@@ -187,7 +203,7 @@
 #ifdef CONFIG_NET_CLS_ROUTE
 		    nh->nh_tclassid != onh->nh_tclassid ||
 #endif
-		    ((nh->nh_flags^onh->nh_flags)&~RTNH_F_DEAD))
+		    ((nh->nh_flags ^ onh->nh_flags) & ~RTNH_F_DEAD))
 			return -1;
 		onh++;
 	} endfor_nexthops(fi);
@@ -238,7 +254,7 @@
 		    nfi->fib_priority == fi->fib_priority &&
 		    memcmp(nfi->fib_metrics, fi->fib_metrics,
 			   sizeof(fi->fib_metrics)) == 0 &&
-		    ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
+		    ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 &&
 		    (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0))
 			return fi;
 	}
@@ -247,9 +263,8 @@
 }
 
 /* Check, that the gateway is already configured.
-   Used only by redirect accept routine.
+ * Used only by redirect accept routine.
  */
-
 int ip_fib_check_default(__be32 gw, struct net_device *dev)
 {
 	struct hlist_head *head;
@@ -264,7 +279,7 @@
 	hlist_for_each_entry(nh, node, head, nh_hash) {
 		if (nh->nh_dev == dev &&
 		    nh->nh_gw == gw &&
-		    !(nh->nh_flags&RTNH_F_DEAD)) {
+		    !(nh->nh_flags & RTNH_F_DEAD)) {
 			spin_unlock(&fib_info_lock);
 			return 0;
 		}
@@ -362,10 +377,10 @@
 	}
 	if (state == NUD_REACHABLE)
 		return 0;
-	if ((state&NUD_VALID) && order != dflt)
+	if ((state & NUD_VALID) && order != dflt)
 		return 0;
-	if ((state&NUD_VALID) ||
-	    (*last_idx<0 && order > dflt)) {
+	if ((state & NUD_VALID) ||
+	    (*last_idx < 0 && order > dflt)) {
 		*last_resort = fi;
 		*last_idx = order;
 	}
@@ -476,75 +491,76 @@
 
 
 /*
-   Picture
-   -------
-
-   Semantics of nexthop is very messy by historical reasons.
-   We have to take into account, that:
-   a) gateway can be actually local interface address,
-      so that gatewayed route is direct.
-   b) gateway must be on-link address, possibly
-      described not by an ifaddr, but also by a direct route.
-   c) If both gateway and interface are specified, they should not
-      contradict.
-   d) If we use tunnel routes, gateway could be not on-link.
-
-   Attempt to reconcile all of these (alas, self-contradictory) conditions
-   results in pretty ugly and hairy code with obscure logic.
-
-   I chose to generalized it instead, so that the size
-   of code does not increase practically, but it becomes
-   much more general.
-   Every prefix is assigned a "scope" value: "host" is local address,
-   "link" is direct route,
-   [ ... "site" ... "interior" ... ]
-   and "universe" is true gateway route with global meaning.
-
-   Every prefix refers to a set of "nexthop"s (gw, oif),
-   where gw must have narrower scope. This recursion stops
-   when gw has LOCAL scope or if "nexthop" is declared ONLINK,
-   which means that gw is forced to be on link.
-
-   Code is still hairy, but now it is apparently logically
-   consistent and very flexible. F.e. as by-product it allows
-   to co-exists in peace independent exterior and interior
-   routing processes.
-
-   Normally it looks as following.
-
-   {universe prefix}  -> (gw, oif) [scope link]
-			  |
-			  |-> {link prefix} -> (gw, oif) [scope local]
-						|
-						|-> {local prefix} (terminal node)
+ * Picture
+ * -------
+ *
+ * Semantics of nexthop is very messy by historical reasons.
+ * We have to take into account, that:
+ * a) gateway can be actually local interface address,
+ *    so that gatewayed route is direct.
+ * b) gateway must be on-link address, possibly
+ *    described not by an ifaddr, but also by a direct route.
+ * c) If both gateway and interface are specified, they should not
+ *    contradict.
+ * d) If we use tunnel routes, gateway could be not on-link.
+ *
+ * Attempt to reconcile all of these (alas, self-contradictory) conditions
+ * results in pretty ugly and hairy code with obscure logic.
+ *
+ * I chose to generalized it instead, so that the size
+ * of code does not increase practically, but it becomes
+ * much more general.
+ * Every prefix is assigned a "scope" value: "host" is local address,
+ * "link" is direct route,
+ * [ ... "site" ... "interior" ... ]
+ * and "universe" is true gateway route with global meaning.
+ *
+ * Every prefix refers to a set of "nexthop"s (gw, oif),
+ * where gw must have narrower scope. This recursion stops
+ * when gw has LOCAL scope or if "nexthop" is declared ONLINK,
+ * which means that gw is forced to be on link.
+ *
+ * Code is still hairy, but now it is apparently logically
+ * consistent and very flexible. F.e. as by-product it allows
+ * to co-exists in peace independent exterior and interior
+ * routing processes.
+ *
+ * Normally it looks as following.
+ *
+ * {universe prefix}  -> (gw, oif) [scope link]
+ *		  |
+ *		  |-> {link prefix} -> (gw, oif) [scope local]
+ *					|
+ *					|-> {local prefix} (terminal node)
  */
-
 static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
 			struct fib_nh *nh)
 {
 	int err;
 	struct net *net;
+	struct net_device *dev;
 
 	net = cfg->fc_nlinfo.nl_net;
 	if (nh->nh_gw) {
 		struct fib_result res;
 
-		if (nh->nh_flags&RTNH_F_ONLINK) {
-			struct net_device *dev;
+		if (nh->nh_flags & RTNH_F_ONLINK) {
 
 			if (cfg->fc_scope >= RT_SCOPE_LINK)
 				return -EINVAL;
 			if (inet_addr_type(net, nh->nh_gw) != RTN_UNICAST)
 				return -EINVAL;
-			if ((dev = __dev_get_by_index(net, nh->nh_oif)) == NULL)
+			dev = __dev_get_by_index(net, nh->nh_oif);
+			if (!dev)
 				return -ENODEV;
-			if (!(dev->flags&IFF_UP))
+			if (!(dev->flags & IFF_UP))
 				return -ENETDOWN;
 			nh->nh_dev = dev;
 			dev_hold(dev);
 			nh->nh_scope = RT_SCOPE_LINK;
 			return 0;
 		}
+		rcu_read_lock();
 		{
 			struct flowi fl = {
 				.nl_u = {
@@ -559,50 +575,53 @@
 			/* It is not necessary, but requires a bit of thinking */
 			if (fl.fl4_scope < RT_SCOPE_LINK)
 				fl.fl4_scope = RT_SCOPE_LINK;
-			if ((err = fib_lookup(net, &fl, &res)) != 0)
+			err = fib_lookup(net, &fl, &res);
+			if (err) {
+				rcu_read_unlock();
 				return err;
+			}
 		}
 		err = -EINVAL;
 		if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
 			goto out;
 		nh->nh_scope = res.scope;
 		nh->nh_oif = FIB_RES_OIF(res);
-		if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL)
+		nh->nh_dev = dev = FIB_RES_DEV(res);
+		if (!dev)
 			goto out;
-		dev_hold(nh->nh_dev);
-		err = -ENETDOWN;
-		if (!(nh->nh_dev->flags & IFF_UP))
-			goto out;
-		err = 0;
-out:
-		fib_res_put(&res);
-		return err;
+		dev_hold(dev);
+		err = (dev->flags & IFF_UP) ? 0 : -ENETDOWN;
 	} else {
 		struct in_device *in_dev;
 
-		if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK))
+		if (nh->nh_flags & (RTNH_F_PERVASIVE | RTNH_F_ONLINK))
 			return -EINVAL;
 
+		rcu_read_lock();
+		err = -ENODEV;
 		in_dev = inetdev_by_index(net, nh->nh_oif);
 		if (in_dev == NULL)
-			return -ENODEV;
-		if (!(in_dev->dev->flags&IFF_UP)) {
-			in_dev_put(in_dev);
-			return -ENETDOWN;
-		}
+			goto out;
+		err = -ENETDOWN;
+		if (!(in_dev->dev->flags & IFF_UP))
+			goto out;
 		nh->nh_dev = in_dev->dev;
 		dev_hold(nh->nh_dev);
 		nh->nh_scope = RT_SCOPE_HOST;
-		in_dev_put(in_dev);
+		err = 0;
 	}
-	return 0;
+out:
+	rcu_read_unlock();
+	return err;
 }
 
 static inline unsigned int fib_laddr_hashfn(__be32 val)
 {
 	unsigned int mask = (fib_hash_size - 1);
 
-	return ((__force u32)val ^ ((__force u32)val >> 7) ^ ((__force u32)val >> 14)) & mask;
+	return ((__force u32)val ^
+		((__force u32)val >> 7) ^
+		((__force u32)val >> 14)) & mask;
 }
 
 static struct hlist_head *fib_hash_alloc(int bytes)
@@ -611,7 +630,8 @@
 		return kzalloc(bytes, GFP_KERNEL);
 	else
 		return (struct hlist_head *)
-			__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(bytes));
+			__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+					 get_order(bytes));
 }
 
 static void fib_hash_free(struct hlist_head *hash, int bytes)
@@ -806,7 +826,8 @@
 			goto failure;
 	} else {
 		change_nexthops(fi) {
-			if ((err = fib_check_nh(cfg, fi, nexthop_nh)) != 0)
+			err = fib_check_nh(cfg, fi, nexthop_nh);
+			if (err != 0)
 				goto failure;
 		} endfor_nexthops(fi)
 	}
@@ -819,7 +840,8 @@
 	}
 
 link_it:
-	if ((ofi = fib_find_info(fi)) != NULL) {
+	ofi = fib_find_info(fi);
+	if (ofi) {
 		fi->fib_dead = 1;
 		free_fib_info(fi);
 		ofi->fib_treeref++;
@@ -864,7 +886,7 @@
 
 /* Note! fib_semantic_match intentionally uses  RCU list functions. */
 int fib_semantic_match(struct list_head *head, const struct flowi *flp,
-		       struct fib_result *res, int prefixlen)
+		       struct fib_result *res, int prefixlen, int fib_flags)
 {
 	struct fib_alias *fa;
 	int nh_sel = 0;
@@ -879,7 +901,7 @@
 		if (fa->fa_scope < flp->fl4_scope)
 			continue;
 
-		fa->fa_state |= FA_S_ACCESSED;
+		fib_alias_accessed(fa);
 
 		err = fib_props[fa->fa_type].error;
 		if (err == 0) {
@@ -895,7 +917,7 @@
 			case RTN_ANYCAST:
 			case RTN_MULTICAST:
 				for_nexthops(fi) {
-					if (nh->nh_flags&RTNH_F_DEAD)
+					if (nh->nh_flags & RTNH_F_DEAD)
 						continue;
 					if (!flp->oif || flp->oif == nh->nh_oif)
 						break;
@@ -906,16 +928,15 @@
 					goto out_fill_res;
 				}
 #else
-				if (nhsel < 1) {
+				if (nhsel < 1)
 					goto out_fill_res;
-				}
 #endif
 				endfor_nexthops(fi);
 				continue;
 
 			default:
-				printk(KERN_WARNING "fib_semantic_match bad type %#x\n",
-					fa->fa_type);
+				pr_warning("fib_semantic_match bad type %#x\n",
+					   fa->fa_type);
 				return -EINVAL;
 			}
 		}
@@ -929,7 +950,8 @@
 	res->type = fa->fa_type;
 	res->scope = fa->fa_scope;
 	res->fi = fa->fa_info;
-	atomic_inc(&res->fi->fib_clntref);
+	if (!(fib_flags & FIB_LOOKUP_NOREF))
+		atomic_inc(&res->fi->fib_clntref);
 	return 0;
 }
 
@@ -1028,10 +1050,10 @@
 }
 
 /*
-   Update FIB if:
-   - local address disappeared -> we must delete all the entries
-     referring to it.
-   - device went down -> we must shutdown all nexthops going via it.
+ * Update FIB if:
+ * - local address disappeared -> we must delete all the entries
+ *   referring to it.
+ * - device went down -> we must shutdown all nexthops going via it.
  */
 int fib_sync_down_addr(struct net *net, __be32 local)
 {
@@ -1078,7 +1100,7 @@
 		prev_fi = fi;
 		dead = 0;
 		change_nexthops(fi) {
-			if (nexthop_nh->nh_flags&RTNH_F_DEAD)
+			if (nexthop_nh->nh_flags & RTNH_F_DEAD)
 				dead++;
 			else if (nexthop_nh->nh_dev == dev &&
 				 nexthop_nh->nh_scope != scope) {
@@ -1110,10 +1132,9 @@
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 
 /*
-   Dead device goes up. We wake up dead nexthops.
-   It takes sense only on multipath routes.
+ * Dead device goes up. We wake up dead nexthops.
+ * It takes sense only on multipath routes.
  */
-
 int fib_sync_up(struct net_device *dev)
 {
 	struct fib_info *prev_fi;
@@ -1123,7 +1144,7 @@
 	struct fib_nh *nh;
 	int ret;
 
-	if (!(dev->flags&IFF_UP))
+	if (!(dev->flags & IFF_UP))
 		return 0;
 
 	prev_fi = NULL;
@@ -1142,12 +1163,12 @@
 		prev_fi = fi;
 		alive = 0;
 		change_nexthops(fi) {
-			if (!(nexthop_nh->nh_flags&RTNH_F_DEAD)) {
+			if (!(nexthop_nh->nh_flags & RTNH_F_DEAD)) {
 				alive++;
 				continue;
 			}
 			if (nexthop_nh->nh_dev == NULL ||
-			    !(nexthop_nh->nh_dev->flags&IFF_UP))
+			    !(nexthop_nh->nh_dev->flags & IFF_UP))
 				continue;
 			if (nexthop_nh->nh_dev != dev ||
 			    !__in_dev_get_rtnl(dev))
@@ -1169,10 +1190,9 @@
 }
 
 /*
-   The algorithm is suboptimal, but it provides really
-   fair weighted route distribution.
+ * The algorithm is suboptimal, but it provides really
+ * fair weighted route distribution.
  */
-
 void fib_select_multipath(const struct flowi *flp, struct fib_result *res)
 {
 	struct fib_info *fi = res->fi;
@@ -1182,7 +1202,7 @@
 	if (fi->fib_power <= 0) {
 		int power = 0;
 		change_nexthops(fi) {
-			if (!(nexthop_nh->nh_flags&RTNH_F_DEAD)) {
+			if (!(nexthop_nh->nh_flags & RTNH_F_DEAD)) {
 				power += nexthop_nh->nh_weight;
 				nexthop_nh->nh_power = nexthop_nh->nh_weight;
 			}
@@ -1198,15 +1218,16 @@
 
 
 	/* w should be random number [0..fi->fib_power-1],
-	   it is pretty bad approximation.
+	 * it is pretty bad approximation.
 	 */
 
 	w = jiffies % fi->fib_power;
 
 	change_nexthops(fi) {
-		if (!(nexthop_nh->nh_flags&RTNH_F_DEAD) &&
+		if (!(nexthop_nh->nh_flags & RTNH_F_DEAD) &&
 		    nexthop_nh->nh_power) {
-			if ((w -= nexthop_nh->nh_power) <= 0) {
+			w -= nexthop_nh->nh_power;
+			if (w <= 0) {
 				nexthop_nh->nh_power--;
 				fi->fib_power--;
 				res->nh_sel = nhsel;
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 4a8e370..cd5e13a 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -186,9 +186,7 @@
 {
 	struct tnode *ret = node_parent(node);
 
-	return rcu_dereference_check(ret,
-				     rcu_read_lock_held() ||
-				     lockdep_rtnl_is_held());
+	return rcu_dereference_rtnl(ret);
 }
 
 /* Same as rcu_assign_pointer
@@ -211,9 +209,7 @@
 {
 	struct node *ret = tnode_get_child(tn, i);
 
-	return rcu_dereference_check(ret,
-				     rcu_read_lock_held() ||
-				     lockdep_rtnl_is_held());
+	return rcu_dereference_rtnl(ret);
 }
 
 static inline int tnode_child_length(const struct tnode *tn)
@@ -459,8 +455,8 @@
 		tn->empty_children = 1<<bits;
 	}
 
-	pr_debug("AT %p s=%u %lu\n", tn, (unsigned int) sizeof(struct tnode),
-		 (unsigned long) (sizeof(struct node) << bits));
+	pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode),
+		 sizeof(struct node) << bits);
 	return tn;
 }
 
@@ -609,11 +605,10 @@
 
 	/* Keep root node larger  */
 
-	if (!node_parent((struct node*) tn)) {
+	if (!node_parent((struct node *)tn)) {
 		inflate_threshold_use = inflate_threshold_root;
 		halve_threshold_use = halve_threshold_root;
-	}
-	else {
+	} else {
 		inflate_threshold_use = inflate_threshold;
 		halve_threshold_use = halve_threshold;
 	}
@@ -639,7 +634,7 @@
 	check_tnode(tn);
 
 	/* Return if at least one inflate is run */
-	if( max_work != MAX_WORK)
+	if (max_work != MAX_WORK)
 		return (struct node *) tn;
 
 	/*
@@ -966,9 +961,7 @@
 	struct node *n;
 
 	pos = 0;
-	n = rcu_dereference_check(t->trie,
-				  rcu_read_lock_held() ||
-				  lockdep_rtnl_is_held());
+	n = rcu_dereference_rtnl(t->trie);
 
 	while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {
 		tn = (struct tnode *) n;
@@ -1349,7 +1342,7 @@
 /* should be called with rcu_read_lock */
 static int check_leaf(struct trie *t, struct leaf *l,
 		      t_key key,  const struct flowi *flp,
-		      struct fib_result *res)
+		      struct fib_result *res, int fib_flags)
 {
 	struct leaf_info *li;
 	struct hlist_head *hhead = &l->list;
@@ -1363,7 +1356,7 @@
 		if (l->key != (key & ntohl(mask)))
 			continue;
 
-		err = fib_semantic_match(&li->falh, flp, res, plen);
+		err = fib_semantic_match(&li->falh, flp, res, plen, fib_flags);
 
 #ifdef CONFIG_IP_FIB_TRIE_STATS
 		if (err <= 0)
@@ -1379,7 +1372,7 @@
 }
 
 int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
-		     struct fib_result *res)
+		     struct fib_result *res, int fib_flags)
 {
 	struct trie *t = (struct trie *) tb->tb_data;
 	int ret;
@@ -1391,8 +1384,7 @@
 	t_key cindex = 0;
 	int current_prefix_length = KEYLENGTH;
 	struct tnode *cn;
-	t_key node_prefix, key_prefix, pref_mismatch;
-	int mp;
+	t_key pref_mismatch;
 
 	rcu_read_lock();
 
@@ -1406,7 +1398,7 @@
 
 	/* Just a leaf? */
 	if (IS_LEAF(n)) {
-		ret = check_leaf(t, (struct leaf *)n, key, flp, res);
+		ret = check_leaf(t, (struct leaf *)n, key, flp, res, fib_flags);
 		goto found;
 	}
 
@@ -1431,7 +1423,7 @@
 		}
 
 		if (IS_LEAF(n)) {
-			ret = check_leaf(t, (struct leaf *)n, key, flp, res);
+			ret = check_leaf(t, (struct leaf *)n, key, flp, res, fib_flags);
 			if (ret > 0)
 				goto backtrace;
 			goto found;
@@ -1507,10 +1499,7 @@
 		 * matching prefix.
 		 */
 
-		node_prefix = mask_pfx(cn->key, cn->pos);
-		key_prefix = mask_pfx(key, cn->pos);
-		pref_mismatch = key_prefix^node_prefix;
-		mp = 0;
+		pref_mismatch = mask_pfx(cn->key ^ key, cn->pos);
 
 		/*
 		 * In short: If skipped bits in this node do not match
@@ -1518,13 +1507,9 @@
 		 * state.directly.
 		 */
 		if (pref_mismatch) {
-			while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) {
-				mp++;
-				pref_mismatch = pref_mismatch << 1;
-			}
-			key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp);
+			int mp = KEYLENGTH - fls(pref_mismatch);
 
-			if (key_prefix != 0)
+			if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0)
 				goto backtrace;
 
 			if (current_prefix_length >= cn->pos)
@@ -1748,16 +1733,14 @@
 
 		/* Node empty, walk back up to parent */
 		c = (struct node *) p;
-	} while ( (p = node_parent_rcu(c)) != NULL);
+	} while ((p = node_parent_rcu(c)) != NULL);
 
 	return NULL; /* Root of trie */
 }
 
 static struct leaf *trie_firstleaf(struct trie *t)
 {
-	struct tnode *n = (struct tnode *) rcu_dereference_check(t->trie,
-							rcu_read_lock_held() ||
-							lockdep_rtnl_is_held());
+	struct tnode *n = (struct tnode *)rcu_dereference_rtnl(t->trie);
 
 	if (!n)
 		return NULL;
@@ -1855,7 +1838,8 @@
 		if (!next_fi->fib_nh[0].nh_gw ||
 		    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
 			continue;
-		fa->fa_state |= FA_S_ACCESSED;
+
+		fib_alias_accessed(fa);
 
 		if (fi == NULL) {
 			if (next_fi != res->fi)
@@ -2043,14 +2027,14 @@
 	struct seq_net_private p;
 	struct fib_table *tb;
 	struct tnode *tnode;
-	unsigned index;
-	unsigned depth;
+	unsigned int index;
+	unsigned int depth;
 };
 
 static struct node *fib_trie_get_next(struct fib_trie_iter *iter)
 {
 	struct tnode *tn = iter->tnode;
-	unsigned cindex = iter->index;
+	unsigned int cindex = iter->index;
 	struct tnode *p;
 
 	/* A single entry routing table */
@@ -2159,7 +2143,7 @@
  */
 static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
 {
-	unsigned i, max, pointers, bytes, avdepth;
+	unsigned int i, max, pointers, bytes, avdepth;
 
 	if (stat->leaves)
 		avdepth = stat->totdepth*100 / stat->leaves;
@@ -2356,7 +2340,8 @@
 
 static void seq_indent(struct seq_file *seq, int n)
 {
-	while (n-- > 0) seq_puts(seq, "   ");
+	while (n-- > 0)
+		seq_puts(seq, "   ");
 }
 
 static inline const char *rtn_scope(char *buf, size_t len, enum rt_scope_t s)
@@ -2388,7 +2373,7 @@
 	[RTN_XRESOLVE] = "XRESOLVE",
 };
 
-static inline const char *rtn_type(char *buf, size_t len, unsigned t)
+static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
 {
 	if (t < __RTN_MAX && rtn_type_names[t])
 		return rtn_type_names[t];
@@ -2544,13 +2529,12 @@
 	rcu_read_unlock();
 }
 
-static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
+static unsigned int fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
 {
-	static unsigned type2flags[RTN_MAX + 1] = {
-		[7] = RTF_REJECT, [8] = RTF_REJECT,
-	};
-	unsigned flags = type2flags[type];
+	unsigned int flags = 0;
 
+	if (type == RTN_UNREACHABLE || type == RTN_PROHIBIT)
+		flags = RTF_REJECT;
 	if (fi && fi->fib_nh->nh_gw)
 		flags |= RTF_GATEWAY;
 	if (mask == htonl(0xFFFFFFFF))
@@ -2562,7 +2546,7 @@
 /*
  *	This outputs /proc/net/route.
  *	The format of the file is not supposed to be changed
- * 	and needs to be same as fib_hash output to avoid breaking
+ *	and needs to be same as fib_hash output to avoid breaking
  *	legacy utilities
  */
 static int fib_route_seq_show(struct seq_file *seq, void *v)
@@ -2587,7 +2571,7 @@
 
 		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
 			const struct fib_info *fi = fa->fa_info;
-			unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
+			unsigned int flags = fib_flag_trans(fa->fa_type, mask, fi);
 			int len;
 
 			if (fa->fa_type == RTN_BROADCAST
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c
new file mode 100644
index 0000000..caea688
--- /dev/null
+++ b/net/ipv4/gre.c
@@ -0,0 +1,151 @@
+/*
+ *	GRE over IPv4 demultiplexer driver
+ *
+ *	Authors: Dmitry Kozlov (xeb@mail.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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <net/protocol.h>
+#include <net/gre.h>
+
+
+static const struct gre_protocol *gre_proto[GREPROTO_MAX] __read_mostly;
+static DEFINE_SPINLOCK(gre_proto_lock);
+
+int gre_add_protocol(const struct gre_protocol *proto, u8 version)
+{
+	if (version >= GREPROTO_MAX)
+		goto err_out;
+
+	spin_lock(&gre_proto_lock);
+	if (gre_proto[version])
+		goto err_out_unlock;
+
+	rcu_assign_pointer(gre_proto[version], proto);
+	spin_unlock(&gre_proto_lock);
+	return 0;
+
+err_out_unlock:
+	spin_unlock(&gre_proto_lock);
+err_out:
+	return -1;
+}
+EXPORT_SYMBOL_GPL(gre_add_protocol);
+
+int gre_del_protocol(const struct gre_protocol *proto, u8 version)
+{
+	if (version >= GREPROTO_MAX)
+		goto err_out;
+
+	spin_lock(&gre_proto_lock);
+	if (gre_proto[version] != proto)
+		goto err_out_unlock;
+	rcu_assign_pointer(gre_proto[version], NULL);
+	spin_unlock(&gre_proto_lock);
+	synchronize_rcu();
+	return 0;
+
+err_out_unlock:
+	spin_unlock(&gre_proto_lock);
+err_out:
+	return -1;
+}
+EXPORT_SYMBOL_GPL(gre_del_protocol);
+
+static int gre_rcv(struct sk_buff *skb)
+{
+	const struct gre_protocol *proto;
+	u8 ver;
+	int ret;
+
+	if (!pskb_may_pull(skb, 12))
+		goto drop;
+
+	ver = skb->data[1]&0x7f;
+	if (ver >= GREPROTO_MAX)
+		goto drop;
+
+	rcu_read_lock();
+	proto = rcu_dereference(gre_proto[ver]);
+	if (!proto || !proto->handler)
+		goto drop_unlock;
+	ret = proto->handler(skb);
+	rcu_read_unlock();
+	return ret;
+
+drop_unlock:
+	rcu_read_unlock();
+drop:
+	kfree_skb(skb);
+	return NET_RX_DROP;
+}
+
+static void gre_err(struct sk_buff *skb, u32 info)
+{
+	const struct gre_protocol *proto;
+	u8 ver;
+
+	if (!pskb_may_pull(skb, 12))
+		goto drop;
+
+	ver = skb->data[1]&0x7f;
+	if (ver >= GREPROTO_MAX)
+		goto drop;
+
+	rcu_read_lock();
+	proto = rcu_dereference(gre_proto[ver]);
+	if (!proto || !proto->err_handler)
+		goto drop_unlock;
+	proto->err_handler(skb, info);
+	rcu_read_unlock();
+	return;
+
+drop_unlock:
+	rcu_read_unlock();
+drop:
+	kfree_skb(skb);
+}
+
+static const struct net_protocol net_gre_protocol = {
+	.handler     = gre_rcv,
+	.err_handler = gre_err,
+	.netns_ok    = 1,
+};
+
+static int __init gre_init(void)
+{
+	pr_info("GRE over IPv4 demultiplexor driver");
+
+	if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) {
+		pr_err("gre: can't add protocol\n");
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static void __exit gre_exit(void)
+{
+	inet_del_protocol(&net_gre_protocol, IPPROTO_GRE);
+}
+
+module_init(gre_init);
+module_exit(gre_exit);
+
+MODULE_DESCRIPTION("GRE over IPv4 demultiplexer driver");
+MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
+MODULE_LICENSE("GPL");
+
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index a0d847c..96bc7f9 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -379,7 +379,7 @@
 	inet->tos = ip_hdr(skb)->tos;
 	daddr = ipc.addr = rt->rt_src;
 	ipc.opt = NULL;
-	ipc.shtx.flags = 0;
+	ipc.tx_flags = 0;
 	if (icmp_param->replyopts.optlen) {
 		ipc.opt = &icmp_param->replyopts;
 		if (ipc.opt->srr)
@@ -538,7 +538,7 @@
 	inet_sk(sk)->tos = tos;
 	ipc.addr = iph->saddr;
 	ipc.opt = &icmp_param.replyopts;
-	ipc.shtx.flags = 0;
+	ipc.tx_flags = 0;
 
 	{
 		struct flowi fl = {
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 1fdcacd..c8877c6 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -834,7 +834,7 @@
 	int			mark = 0;
 
 
-	if (len == 8 || IGMP_V2_SEEN(in_dev)) {
+	if (len == 8) {
 		if (ih->code == 0) {
 			/* Alas, old v1 router presents here. */
 
@@ -856,6 +856,18 @@
 		igmpv3_clear_delrec(in_dev);
 	} else if (len < 12) {
 		return;	/* ignore bogus packet; freed by caller */
+	} else if (IGMP_V1_SEEN(in_dev)) {
+		/* This is a v3 query with v1 queriers present */
+		max_delay = IGMP_Query_Response_Interval;
+		group = 0;
+	} else if (IGMP_V2_SEEN(in_dev)) {
+		/* this is a v3 query with v2 queriers present;
+		 * Interpretation of the max_delay code is problematic here.
+		 * A real v2 host would use ih_code directly, while v3 has a
+		 * different encoding. We use the v3 encoding as more likely
+		 * to be intended in a v3 query.
+		 */
+		max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE);
 	} else { /* v3 */
 		if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)))
 			return;
@@ -1257,14 +1269,14 @@
 	if (im->multiaddr == IGMP_ALL_HOSTS)
 		return;
 
-	if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) {
-		igmp_mod_timer(im, IGMP_Initial_Report_Delay);
-		return;
-	}
-	/* else, v3 */
-	im->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
-		IGMP_Unsolicited_Report_Count;
-	igmp_ifc_event(in_dev);
+	/* a failover is happening and switches
+	 * must be notified immediately */
+	if (IGMP_V1_SEEN(in_dev))
+		igmp_send_report(in_dev, im, IGMP_HOST_MEMBERSHIP_REPORT);
+	else if (IGMP_V2_SEEN(in_dev))
+		igmp_send_report(in_dev, im, IGMPV2_HOST_MEMBERSHIP_REPORT);
+	else
+		igmp_send_report(in_dev, im, IGMPV3_HOST_MEMBERSHIP_REPORT);
 #endif
 }
 EXPORT_SYMBOL(ip_mc_rejoin_group);
@@ -1406,6 +1418,7 @@
 	write_unlock_bh(&in_dev->mc_list_lock);
 }
 
+/* RTNL is locked */
 static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
 {
 	struct flowi fl = { .nl_u = { .ip4_u =
@@ -1416,15 +1429,12 @@
 
 	if (imr->imr_ifindex) {
 		idev = inetdev_by_index(net, imr->imr_ifindex);
-		if (idev)
-			__in_dev_put(idev);
 		return idev;
 	}
 	if (imr->imr_address.s_addr) {
-		dev = ip_dev_find(net, imr->imr_address.s_addr);
+		dev = __ip_dev_find(net, imr->imr_address.s_addr, false);
 		if (!dev)
 			return NULL;
-		dev_put(dev);
 	}
 
 	if (!dev && !ip_route_output_key(net, &rt, &fl)) {
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index e5fa2dd..ba80426 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -425,7 +425,7 @@
 			bc += op->no;
 		}
 	}
-	return (len == 0);
+	return len == 0;
 }
 
 static int valid_cc(const void *bc, int len, int cc)
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index fb7ad5a..1b344f3 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -101,19 +101,43 @@
 }
 EXPORT_SYMBOL(inet_put_port);
 
-void __inet_inherit_port(struct sock *sk, struct sock *child)
+int __inet_inherit_port(struct sock *sk, struct sock *child)
 {
 	struct inet_hashinfo *table = sk->sk_prot->h.hashinfo;
-	const int bhash = inet_bhashfn(sock_net(sk), inet_sk(child)->inet_num,
+	unsigned short port = inet_sk(child)->inet_num;
+	const int bhash = inet_bhashfn(sock_net(sk), port,
 			table->bhash_size);
 	struct inet_bind_hashbucket *head = &table->bhash[bhash];
 	struct inet_bind_bucket *tb;
 
 	spin_lock(&head->lock);
 	tb = inet_csk(sk)->icsk_bind_hash;
+	if (tb->port != port) {
+		/* NOTE: using tproxy and redirecting skbs to a proxy
+		 * on a different listener port breaks the assumption
+		 * that the listener socket's icsk_bind_hash is the same
+		 * as that of the child socket. We have to look up or
+		 * create a new bind bucket for the child here. */
+		struct hlist_node *node;
+		inet_bind_bucket_for_each(tb, node, &head->chain) {
+			if (net_eq(ib_net(tb), sock_net(sk)) &&
+			    tb->port == port)
+				break;
+		}
+		if (!node) {
+			tb = inet_bind_bucket_create(table->bind_bucket_cachep,
+						     sock_net(sk), head, port);
+			if (!tb) {
+				spin_unlock(&head->lock);
+				return -ENOMEM;
+			}
+		}
+	}
 	sk_add_bind_node(child, &tb->owners);
 	inet_csk(child)->icsk_bind_hash = tb;
 	spin_unlock(&head->lock);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(__inet_inherit_port);
 
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index b7c4165..1684408 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -116,11 +116,11 @@
 	struct ip4_create_arg *arg = a;
 
 	qp = container_of(q, struct ipq, q);
-	return (qp->id == arg->iph->id &&
+	return	qp->id == arg->iph->id &&
 			qp->saddr == arg->iph->saddr &&
 			qp->daddr == arg->iph->daddr &&
 			qp->protocol == arg->iph->protocol &&
-			qp->user == arg->user);
+			qp->user == arg->user;
 }
 
 /* Memory Tracking Functions. */
@@ -542,7 +542,7 @@
 	/* If the first fragment is fragmented itself, we split
 	 * it to two chunks: the first with data and paged part
 	 * and the second, holding only fragments. */
-	if (skb_has_frags(head)) {
+	if (skb_has_frag_list(head)) {
 		struct sk_buff *clone;
 		int i, plen = 0;
 
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 945b20a..d0ffcbe 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -44,8 +44,9 @@
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 #include <net/rtnetlink.h>
+#include <net/gre.h>
 
-#ifdef CONFIG_IPV6
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 #include <net/ipv6.h>
 #include <net/ip6_fib.h>
 #include <net/ip6_route.h>
@@ -63,13 +64,13 @@
    We cannot track such dead loops during route installation,
    it is infeasible task. The most general solutions would be
    to keep skb->encapsulation counter (sort of local ttl),
-   and silently drop packet when it expires. It is the best
+   and silently drop packet when it expires. It is a good
    solution, but it supposes maintaing new variable in ALL
    skb, even if no tunneling is used.
 
-   Current solution: HARD_TX_LOCK lock breaks dead loops.
-
-
+   Current solution: xmit_recursion breaks dead loops. This is a percpu
+   counter, since when we enter the first ndo_xmit(), cpu migration is
+   forbidden. We force an exit if this counter reaches RECURSION_LIMIT
 
    2. Networking dead loops would not kill routers, but would really
    kill network. IP hop limit plays role of "t->recursion" in this case,
@@ -128,7 +129,7 @@
 
 static int ipgre_net_id __read_mostly;
 struct ipgre_net {
-	struct ip_tunnel *tunnels[4][HASH_SIZE];
+	struct ip_tunnel __rcu *tunnels[4][HASH_SIZE];
 
 	struct net_device *fb_tunnel_dev;
 };
@@ -158,13 +159,40 @@
 #define tunnels_l	tunnels[1]
 #define tunnels_wc	tunnels[0]
 /*
- * Locking : hash tables are protected by RCU and a spinlock
+ * Locking : hash tables are protected by RCU and RTNL
  */
-static DEFINE_SPINLOCK(ipgre_lock);
 
 #define for_each_ip_tunnel_rcu(start) \
 	for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
 
+/* often modified stats are per cpu, other are shared (netdev->stats) */
+struct pcpu_tstats {
+	unsigned long	rx_packets;
+	unsigned long	rx_bytes;
+	unsigned long	tx_packets;
+	unsigned long	tx_bytes;
+};
+
+static struct net_device_stats *ipgre_get_stats(struct net_device *dev)
+{
+	struct pcpu_tstats sum = { 0 };
+	int i;
+
+	for_each_possible_cpu(i) {
+		const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
+
+		sum.rx_packets += tstats->rx_packets;
+		sum.rx_bytes   += tstats->rx_bytes;
+		sum.tx_packets += tstats->tx_packets;
+		sum.tx_bytes   += tstats->tx_bytes;
+	}
+	dev->stats.rx_packets = sum.rx_packets;
+	dev->stats.rx_bytes   = sum.rx_bytes;
+	dev->stats.tx_packets = sum.tx_packets;
+	dev->stats.tx_bytes   = sum.tx_bytes;
+	return &dev->stats;
+}
+
 /* Given src, dst and key, find appropriate for input tunnel. */
 
 static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
@@ -173,8 +201,8 @@
 {
 	struct net *net = dev_net(dev);
 	int link = dev->ifindex;
-	unsigned h0 = HASH(remote);
-	unsigned h1 = HASH(key);
+	unsigned int h0 = HASH(remote);
+	unsigned int h1 = HASH(key);
 	struct ip_tunnel *t, *cand = NULL;
 	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
 	int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
@@ -289,13 +317,13 @@
 	return NULL;
 }
 
-static struct ip_tunnel **__ipgre_bucket(struct ipgre_net *ign,
+static struct ip_tunnel __rcu **__ipgre_bucket(struct ipgre_net *ign,
 		struct ip_tunnel_parm *parms)
 {
 	__be32 remote = parms->iph.daddr;
 	__be32 local = parms->iph.saddr;
 	__be32 key = parms->i_key;
-	unsigned h = HASH(key);
+	unsigned int h = HASH(key);
 	int prio = 0;
 
 	if (local)
@@ -308,7 +336,7 @@
 	return &ign->tunnels[prio][h];
 }
 
-static inline struct ip_tunnel **ipgre_bucket(struct ipgre_net *ign,
+static inline struct ip_tunnel __rcu **ipgre_bucket(struct ipgre_net *ign,
 		struct ip_tunnel *t)
 {
 	return __ipgre_bucket(ign, &t->parms);
@@ -316,23 +344,22 @@
 
 static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t)
 {
-	struct ip_tunnel **tp = ipgre_bucket(ign, t);
+	struct ip_tunnel __rcu **tp = ipgre_bucket(ign, t);
 
-	spin_lock_bh(&ipgre_lock);
-	t->next = *tp;
+	rcu_assign_pointer(t->next, rtnl_dereference(*tp));
 	rcu_assign_pointer(*tp, t);
-	spin_unlock_bh(&ipgre_lock);
 }
 
 static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
 {
-	struct ip_tunnel **tp;
+	struct ip_tunnel __rcu **tp;
+	struct ip_tunnel *iter;
 
-	for (tp = ipgre_bucket(ign, t); *tp; tp = &(*tp)->next) {
-		if (t == *tp) {
-			spin_lock_bh(&ipgre_lock);
-			*tp = t->next;
-			spin_unlock_bh(&ipgre_lock);
+	for (tp = ipgre_bucket(ign, t);
+	     (iter = rtnl_dereference(*tp)) != NULL;
+	     tp = &iter->next) {
+		if (t == iter) {
+			rcu_assign_pointer(*tp, t->next);
 			break;
 		}
 	}
@@ -346,10 +373,13 @@
 	__be32 local = parms->iph.saddr;
 	__be32 key = parms->i_key;
 	int link = parms->link;
-	struct ip_tunnel *t, **tp;
+	struct ip_tunnel *t;
+	struct ip_tunnel __rcu **tp;
 	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
 
-	for (tp = __ipgre_bucket(ign, parms); (t = *tp) != NULL; tp = &t->next)
+	for (tp = __ipgre_bucket(ign, parms);
+	     (t = rtnl_dereference(*tp)) != NULL;
+	     tp = &t->next)
 		if (local == t->parms.iph.saddr &&
 		    remote == t->parms.iph.daddr &&
 		    key == t->parms.i_key &&
@@ -360,7 +390,7 @@
 	return t;
 }
 
-static struct ip_tunnel * ipgre_tunnel_locate(struct net *net,
+static struct ip_tunnel *ipgre_tunnel_locate(struct net *net,
 		struct ip_tunnel_parm *parms, int create)
 {
 	struct ip_tunnel *t, *nt;
@@ -582,7 +612,7 @@
 	if ((tunnel = ipgre_tunnel_lookup(skb->dev,
 					  iph->saddr, iph->daddr, key,
 					  gre_proto))) {
-		struct net_device_stats *stats = &tunnel->dev->stats;
+		struct pcpu_tstats *tstats;
 
 		secpath_reset(skb);
 
@@ -606,22 +636,22 @@
 			/* Looped back packet, drop it! */
 			if (skb_rtable(skb)->fl.iif == 0)
 				goto drop;
-			stats->multicast++;
+			tunnel->dev->stats.multicast++;
 			skb->pkt_type = PACKET_BROADCAST;
 		}
 #endif
 
 		if (((flags&GRE_CSUM) && csum) ||
 		    (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) {
-			stats->rx_crc_errors++;
-			stats->rx_errors++;
+			tunnel->dev->stats.rx_crc_errors++;
+			tunnel->dev->stats.rx_errors++;
 			goto drop;
 		}
 		if (tunnel->parms.i_flags&GRE_SEQ) {
 			if (!(flags&GRE_SEQ) ||
 			    (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) {
-				stats->rx_fifo_errors++;
-				stats->rx_errors++;
+				tunnel->dev->stats.rx_fifo_errors++;
+				tunnel->dev->stats.rx_errors++;
 				goto drop;
 			}
 			tunnel->i_seqno = seqno + 1;
@@ -630,8 +660,8 @@
 		/* Warning: All skb pointers will be invalidated! */
 		if (tunnel->dev->type == ARPHRD_ETHER) {
 			if (!pskb_may_pull(skb, ETH_HLEN)) {
-				stats->rx_length_errors++;
-				stats->rx_errors++;
+				tunnel->dev->stats.rx_length_errors++;
+				tunnel->dev->stats.rx_errors++;
 				goto drop;
 			}
 
@@ -640,14 +670,19 @@
 			skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
 		}
 
-		skb_tunnel_rx(skb, tunnel->dev);
+		tstats = this_cpu_ptr(tunnel->dev->tstats);
+		tstats->rx_packets++;
+		tstats->rx_bytes += skb->len;
+
+		__skb_tunnel_rx(skb, tunnel->dev);
 
 		skb_reset_network_header(skb);
 		ipgre_ecn_decapsulate(iph, skb);
 
 		netif_rx(skb);
+
 		rcu_read_unlock();
-		return(0);
+		return 0;
 	}
 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 
@@ -655,20 +690,19 @@
 	rcu_read_unlock();
 drop_nolock:
 	kfree_skb(skb);
-	return(0);
+	return 0;
 }
 
 static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
-	struct net_device_stats *stats = &dev->stats;
-	struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+	struct pcpu_tstats *tstats;
 	struct iphdr  *old_iph = ip_hdr(skb);
 	struct iphdr  *tiph;
 	u8     tos;
 	__be16 df;
 	struct rtable *rt;     			/* Route to the other host */
-	struct net_device *tdev;			/* Device to other host */
+	struct net_device *tdev;		/* Device to other host */
 	struct iphdr  *iph;			/* Our new IP header */
 	unsigned int max_headroom;		/* The extra header space needed */
 	int    gre_hlen;
@@ -690,7 +724,7 @@
 		/* NBMA tunnel */
 
 		if (skb_dst(skb) == NULL) {
-			stats->tx_fifo_errors++;
+			dev->stats.tx_fifo_errors++;
 			goto tx_error;
 		}
 
@@ -699,7 +733,7 @@
 			if ((dst = rt->rt_gateway) == 0)
 				goto tx_error_icmp;
 		}
-#ifdef CONFIG_IPV6
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 		else if (skb->protocol == htons(ETH_P_IPV6)) {
 			struct in6_addr *addr6;
 			int addr_type;
@@ -736,14 +770,20 @@
 	}
 
 	{
-		struct flowi fl = { .oif = tunnel->parms.link,
-				    .nl_u = { .ip4_u =
-					      { .daddr = dst,
-						.saddr = tiph->saddr,
-						.tos = RT_TOS(tos) } },
-				    .proto = IPPROTO_GRE };
+		struct flowi fl = {
+			.oif = tunnel->parms.link,
+			.nl_u = {
+				.ip4_u = {
+					.daddr = dst,
+					.saddr = tiph->saddr,
+					.tos = RT_TOS(tos)
+				}
+			},
+			.proto = IPPROTO_GRE
+		}
+;
 		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
-			stats->tx_carrier_errors++;
+			dev->stats.tx_carrier_errors++;
 			goto tx_error;
 		}
 	}
@@ -751,7 +791,7 @@
 
 	if (tdev == dev) {
 		ip_rt_put(rt);
-		stats->collisions++;
+		dev->stats.collisions++;
 		goto tx_error;
 	}
 
@@ -774,7 +814,7 @@
 			goto tx_error;
 		}
 	}
-#ifdef CONFIG_IPV6
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	else if (skb->protocol == htons(ETH_P_IPV6)) {
 		struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
 
@@ -814,7 +854,7 @@
 			dev->needed_headroom = max_headroom;
 		if (!new_skb) {
 			ip_rt_put(rt);
-			txq->tx_dropped++;
+			dev->stats.tx_dropped++;
 			dev_kfree_skb(skb);
 			return NETDEV_TX_OK;
 		}
@@ -850,7 +890,7 @@
 	if ((iph->ttl = tiph->ttl) == 0) {
 		if (skb->protocol == htons(ETH_P_IP))
 			iph->ttl = old_iph->ttl;
-#ifdef CONFIG_IPV6
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 		else if (skb->protocol == htons(ETH_P_IPV6))
 			iph->ttl = ((struct ipv6hdr *)old_iph)->hop_limit;
 #endif
@@ -881,15 +921,15 @@
 	}
 
 	nf_reset(skb);
-
-	IPTUNNEL_XMIT();
+	tstats = this_cpu_ptr(dev->tstats);
+	__IPTUNNEL_XMIT(tstats, &dev->stats);
 	return NETDEV_TX_OK;
 
 tx_error_icmp:
 	dst_link_failure(skb);
 
 tx_error:
-	stats->tx_errors++;
+	dev->stats.tx_errors++;
 	dev_kfree_skb(skb);
 	return NETDEV_TX_OK;
 }
@@ -909,13 +949,19 @@
 	/* Guess output device to choose reasonable mtu and needed_headroom */
 
 	if (iph->daddr) {
-		struct flowi fl = { .oif = tunnel->parms.link,
-				    .nl_u = { .ip4_u =
-					      { .daddr = iph->daddr,
-						.saddr = iph->saddr,
-						.tos = RT_TOS(iph->tos) } },
-				    .proto = IPPROTO_GRE };
+		struct flowi fl = {
+			.oif = tunnel->parms.link,
+			.nl_u = {
+				.ip4_u = {
+					.daddr = iph->daddr,
+					.saddr = iph->saddr,
+					.tos = RT_TOS(iph->tos)
+				}
+			},
+			.proto = IPPROTO_GRE
+		};
 		struct rtable *rt;
+
 		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
 			tdev = rt->dst.dev;
 			ip_rt_put(rt);
@@ -1012,7 +1058,7 @@
 					break;
 				}
 			} else {
-				unsigned nflags = 0;
+				unsigned int nflags = 0;
 
 				t = netdev_priv(dev);
 
@@ -1125,7 +1171,7 @@
 
 static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
 			unsigned short type,
-			const void *daddr, const void *saddr, unsigned len)
+			const void *daddr, const void *saddr, unsigned int len)
 {
 	struct ip_tunnel *t = netdev_priv(dev);
 	struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen);
@@ -1167,13 +1213,19 @@
 	struct ip_tunnel *t = netdev_priv(dev);
 
 	if (ipv4_is_multicast(t->parms.iph.daddr)) {
-		struct flowi fl = { .oif = t->parms.link,
-				    .nl_u = { .ip4_u =
-					      { .daddr = t->parms.iph.daddr,
-						.saddr = t->parms.iph.saddr,
-						.tos = RT_TOS(t->parms.iph.tos) } },
-				    .proto = IPPROTO_GRE };
+		struct flowi fl = {
+			.oif = t->parms.link,
+			.nl_u = {
+				.ip4_u = {
+					.daddr = t->parms.iph.daddr,
+					.saddr = t->parms.iph.saddr,
+					.tos = RT_TOS(t->parms.iph.tos)
+				}
+			},
+			.proto = IPPROTO_GRE
+		};
 		struct rtable *rt;
+
 		if (ip_route_output_key(dev_net(dev), &rt, &fl))
 			return -EADDRNOTAVAIL;
 		dev = rt->dst.dev;
@@ -1193,10 +1245,8 @@
 	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
 		struct in_device *in_dev;
 		in_dev = inetdev_by_index(dev_net(dev), t->mlink);
-		if (in_dev) {
+		if (in_dev)
 			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
-			in_dev_put(in_dev);
-		}
 	}
 	return 0;
 }
@@ -1213,12 +1263,19 @@
 	.ndo_start_xmit		= ipgre_tunnel_xmit,
 	.ndo_do_ioctl		= ipgre_tunnel_ioctl,
 	.ndo_change_mtu		= ipgre_tunnel_change_mtu,
+	.ndo_get_stats		= ipgre_get_stats,
 };
 
+static void ipgre_dev_free(struct net_device *dev)
+{
+	free_percpu(dev->tstats);
+	free_netdev(dev);
+}
+
 static void ipgre_tunnel_setup(struct net_device *dev)
 {
 	dev->netdev_ops		= &ipgre_netdev_ops;
-	dev->destructor 	= free_netdev;
+	dev->destructor 	= ipgre_dev_free;
 
 	dev->type		= ARPHRD_IPGRE;
 	dev->needed_headroom 	= LL_MAX_HEADER + sizeof(struct iphdr) + 4;
@@ -1256,6 +1313,10 @@
 	} else
 		dev->header_ops = &ipgre_header_ops;
 
+	dev->tstats = alloc_percpu(struct pcpu_tstats);
+	if (!dev->tstats)
+		return -ENOMEM;
+
 	return 0;
 }
 
@@ -1274,14 +1335,13 @@
 	tunnel->hlen		= sizeof(struct iphdr) + 4;
 
 	dev_hold(dev);
-	ign->tunnels_wc[0]	= tunnel;
+	rcu_assign_pointer(ign->tunnels_wc[0], tunnel);
 }
 
 
-static const struct net_protocol ipgre_protocol = {
-	.handler	=	ipgre_rcv,
-	.err_handler	=	ipgre_err,
-	.netns_ok	=	1,
+static const struct gre_protocol ipgre_protocol = {
+	.handler     = ipgre_rcv,
+	.err_handler = ipgre_err,
 };
 
 static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head)
@@ -1291,11 +1351,13 @@
 	for (prio = 0; prio < 4; prio++) {
 		int h;
 		for (h = 0; h < HASH_SIZE; h++) {
-			struct ip_tunnel *t = ign->tunnels[prio][h];
+			struct ip_tunnel *t;
+
+			t = rtnl_dereference(ign->tunnels[prio][h]);
 
 			while (t != NULL) {
 				unregister_netdevice_queue(t->dev, head);
-				t = t->next;
+				t = rtnl_dereference(t->next);
 			}
 		}
 	}
@@ -1441,6 +1503,10 @@
 
 	ipgre_tunnel_bind_dev(dev);
 
+	dev->tstats = alloc_percpu(struct pcpu_tstats);
+	if (!dev->tstats)
+		return -ENOMEM;
+
 	return 0;
 }
 
@@ -1451,6 +1517,7 @@
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= ipgre_tunnel_change_mtu,
+	.ndo_get_stats		= ipgre_get_stats,
 };
 
 static void ipgre_tap_setup(struct net_device *dev)
@@ -1459,7 +1526,7 @@
 	ether_setup(dev);
 
 	dev->netdev_ops		= &ipgre_tap_netdev_ops;
-	dev->destructor 	= free_netdev;
+	dev->destructor 	= ipgre_dev_free;
 
 	dev->iflink		= 0;
 	dev->features		|= NETIF_F_NETNS_LOCAL;
@@ -1487,6 +1554,10 @@
 	if (!tb[IFLA_MTU])
 		dev->mtu = mtu;
 
+	/* Can use a lockless transmit, unless we generate output sequences */
+	if (!(nt->parms.o_flags & GRE_SEQ))
+		dev->features |= NETIF_F_LLTX;
+
 	err = register_netdevice(dev);
 	if (err)
 		goto out;
@@ -1522,7 +1593,7 @@
 		t = nt;
 
 		if (dev->type != ARPHRD_ETHER) {
-			unsigned nflags = 0;
+			unsigned int nflags = 0;
 
 			if (ipv4_is_multicast(p.iph.daddr))
 				nflags = IFF_BROADCAST;
@@ -1663,7 +1734,7 @@
 	if (err < 0)
 		return err;
 
-	err = inet_add_protocol(&ipgre_protocol, IPPROTO_GRE);
+	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
 	if (err < 0) {
 		printk(KERN_INFO "ipgre init: can't add protocol\n");
 		goto add_proto_failed;
@@ -1683,7 +1754,7 @@
 tap_ops_failed:
 	rtnl_link_unregister(&ipgre_link_ops);
 rtnl_link_failed:
-	inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
+	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
 add_proto_failed:
 	unregister_pernet_device(&ipgre_net_ops);
 	goto out;
@@ -1693,7 +1764,7 @@
 {
 	rtnl_link_unregister(&ipgre_tap_ops);
 	rtnl_link_unregister(&ipgre_link_ops);
-	if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
+	if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0)
 		printk(KERN_INFO "ipgre close: can't remove protocol\n");
 	unregister_pernet_device(&ipgre_net_ops);
 }
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index ba9836c..1906fa3 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -466,7 +466,7 @@
 	}
 	return -EINVAL;
 }
-
+EXPORT_SYMBOL(ip_options_compile);
 
 /*
  *	Undo all the changes done by ip_options_compile().
@@ -646,3 +646,4 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL(ip_options_rcv_srr);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 04b6989..439d2a3 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -487,10 +487,9 @@
 	 * LATER: this step can be merged to real generation of fragments,
 	 * we can switch to copy when see the first bad fragment.
 	 */
-	if (skb_has_frags(skb)) {
-		struct sk_buff *frag;
+	if (skb_has_frag_list(skb)) {
+		struct sk_buff *frag, *frag2;
 		int first_len = skb_pagelen(skb);
-		int truesizes = 0;
 
 		if (first_len - hlen > mtu ||
 		    ((first_len - hlen) & 7) ||
@@ -503,18 +502,18 @@
 			if (frag->len > mtu ||
 			    ((frag->len & 7) && frag->next) ||
 			    skb_headroom(frag) < hlen)
-			    goto slow_path;
+				goto slow_path_clean;
 
 			/* Partially cloned skb? */
 			if (skb_shared(frag))
-				goto slow_path;
+				goto slow_path_clean;
 
 			BUG_ON(frag->sk);
 			if (skb->sk) {
 				frag->sk = skb->sk;
 				frag->destructor = sock_wfree;
 			}
-			truesizes += frag->truesize;
+			skb->truesize -= frag->truesize;
 		}
 
 		/* Everything is OK. Generate! */
@@ -524,7 +523,6 @@
 		frag = skb_shinfo(skb)->frag_list;
 		skb_frag_list_init(skb);
 		skb->data_len = first_len - skb_headlen(skb);
-		skb->truesize -= truesizes;
 		skb->len = first_len;
 		iph->tot_len = htons(first_len);
 		iph->frag_off = htons(IP_MF);
@@ -576,6 +574,15 @@
 		}
 		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
 		return err;
+
+slow_path_clean:
+		skb_walk_frags(skb, frag2) {
+			if (frag2 == frag)
+				break;
+			frag2->sk = NULL;
+			frag2->destructor = NULL;
+			skb->truesize += frag2->truesize;
+		}
 	}
 
 slow_path:
@@ -837,10 +844,9 @@
 		inet->cork.length = 0;
 		sk->sk_sndmsg_page = NULL;
 		sk->sk_sndmsg_off = 0;
-		if ((exthdrlen = rt->dst.header_len) != 0) {
-			length += exthdrlen;
-			transhdrlen += exthdrlen;
-		}
+		exthdrlen = rt->dst.header_len;
+		length += exthdrlen;
+		transhdrlen += exthdrlen;
 	} else {
 		rt = (struct rtable *)inet->cork.dst;
 		if (inet->cork.flags & IPCORK_OPT)
@@ -927,16 +933,19 @@
 			    !(rt->dst.dev->features&NETIF_F_SG))
 				alloclen = mtu;
 			else
-				alloclen = datalen + fragheaderlen;
+				alloclen = fraglen;
 
 			/* The last fragment gets additional space at tail.
 			 * Note, with MSG_MORE we overallocate on fragments,
 			 * because we have no idea what fragment will be
 			 * the last.
 			 */
-			if (datalen == length + fraggap)
+			if (datalen == length + fraggap) {
 				alloclen += rt->dst.trailer_len;
-
+				/* make sure mtu is not reached */
+				if (datalen > mtu - fragheaderlen - rt->dst.trailer_len)
+					datalen -= ALIGN(rt->dst.trailer_len, 8);
+			}
 			if (transhdrlen) {
 				skb = sock_alloc_send_skb(sk,
 						alloclen + hh_len + 15,
@@ -953,7 +962,7 @@
 				else
 					/* only the initial fragment is
 					   time stamped */
-					ipc->shtx.flags = 0;
+					ipc->tx_flags = 0;
 			}
 			if (skb == NULL)
 				goto error;
@@ -964,7 +973,7 @@
 			skb->ip_summed = csummode;
 			skb->csum = 0;
 			skb_reserve(skb, hh_len);
-			*skb_tx(skb) = ipc->shtx;
+			skb_shinfo(skb)->tx_flags = ipc->tx_flags;
 
 			/*
 			 *	Find where to start putting bytes.
@@ -1384,7 +1393,7 @@
 
 	daddr = ipc.addr = rt->rt_src;
 	ipc.opt = NULL;
-	ipc.shtx.flags = 0;
+	ipc.tx_flags = 0;
 
 	if (replyopts.opt.optlen) {
 		ipc.opt = &replyopts.opt;
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index ec03673..e9b816e 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -122,31 +122,59 @@
 
 static int ipip_net_id __read_mostly;
 struct ipip_net {
-	struct ip_tunnel *tunnels_r_l[HASH_SIZE];
-	struct ip_tunnel *tunnels_r[HASH_SIZE];
-	struct ip_tunnel *tunnels_l[HASH_SIZE];
-	struct ip_tunnel *tunnels_wc[1];
-	struct ip_tunnel **tunnels[4];
+	struct ip_tunnel __rcu *tunnels_r_l[HASH_SIZE];
+	struct ip_tunnel __rcu *tunnels_r[HASH_SIZE];
+	struct ip_tunnel __rcu *tunnels_l[HASH_SIZE];
+	struct ip_tunnel __rcu *tunnels_wc[1];
+	struct ip_tunnel __rcu **tunnels[4];
 
 	struct net_device *fb_tunnel_dev;
 };
 
-static void ipip_tunnel_init(struct net_device *dev);
+static int ipip_tunnel_init(struct net_device *dev);
 static void ipip_tunnel_setup(struct net_device *dev);
+static void ipip_dev_free(struct net_device *dev);
 
 /*
- * Locking : hash tables are protected by RCU and a spinlock
+ * Locking : hash tables are protected by RCU and RTNL
  */
-static DEFINE_SPINLOCK(ipip_lock);
 
 #define for_each_ip_tunnel_rcu(start) \
 	for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
 
+/* often modified stats are per cpu, other are shared (netdev->stats) */
+struct pcpu_tstats {
+	unsigned long	rx_packets;
+	unsigned long	rx_bytes;
+	unsigned long	tx_packets;
+	unsigned long	tx_bytes;
+};
+
+static struct net_device_stats *ipip_get_stats(struct net_device *dev)
+{
+	struct pcpu_tstats sum = { 0 };
+	int i;
+
+	for_each_possible_cpu(i) {
+		const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
+
+		sum.rx_packets += tstats->rx_packets;
+		sum.rx_bytes   += tstats->rx_bytes;
+		sum.tx_packets += tstats->tx_packets;
+		sum.tx_bytes   += tstats->tx_bytes;
+	}
+	dev->stats.rx_packets = sum.rx_packets;
+	dev->stats.rx_bytes   = sum.rx_bytes;
+	dev->stats.tx_packets = sum.tx_packets;
+	dev->stats.tx_bytes   = sum.tx_bytes;
+	return &dev->stats;
+}
+
 static struct ip_tunnel * ipip_tunnel_lookup(struct net *net,
 		__be32 remote, __be32 local)
 {
-	unsigned h0 = HASH(remote);
-	unsigned h1 = HASH(local);
+	unsigned int h0 = HASH(remote);
+	unsigned int h1 = HASH(local);
 	struct ip_tunnel *t;
 	struct ipip_net *ipn = net_generic(net, ipip_net_id);
 
@@ -169,12 +197,12 @@
 	return NULL;
 }
 
-static struct ip_tunnel **__ipip_bucket(struct ipip_net *ipn,
+static struct ip_tunnel __rcu **__ipip_bucket(struct ipip_net *ipn,
 		struct ip_tunnel_parm *parms)
 {
 	__be32 remote = parms->iph.daddr;
 	__be32 local = parms->iph.saddr;
-	unsigned h = 0;
+	unsigned int h = 0;
 	int prio = 0;
 
 	if (remote) {
@@ -188,7 +216,7 @@
 	return &ipn->tunnels[prio][h];
 }
 
-static inline struct ip_tunnel **ipip_bucket(struct ipip_net *ipn,
+static inline struct ip_tunnel __rcu **ipip_bucket(struct ipip_net *ipn,
 		struct ip_tunnel *t)
 {
 	return __ipip_bucket(ipn, &t->parms);
@@ -196,13 +224,14 @@
 
 static void ipip_tunnel_unlink(struct ipip_net *ipn, struct ip_tunnel *t)
 {
-	struct ip_tunnel **tp;
+	struct ip_tunnel __rcu **tp;
+	struct ip_tunnel *iter;
 
-	for (tp = ipip_bucket(ipn, t); *tp; tp = &(*tp)->next) {
-		if (t == *tp) {
-			spin_lock_bh(&ipip_lock);
-			*tp = t->next;
-			spin_unlock_bh(&ipip_lock);
+	for (tp = ipip_bucket(ipn, t);
+	     (iter = rtnl_dereference(*tp)) != NULL;
+	     tp = &iter->next) {
+		if (t == iter) {
+			rcu_assign_pointer(*tp, t->next);
 			break;
 		}
 	}
@@ -210,12 +239,10 @@
 
 static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t)
 {
-	struct ip_tunnel **tp = ipip_bucket(ipn, t);
+	struct ip_tunnel __rcu **tp = ipip_bucket(ipn, t);
 
-	spin_lock_bh(&ipip_lock);
-	t->next = *tp;
+	rcu_assign_pointer(t->next, rtnl_dereference(*tp));
 	rcu_assign_pointer(*tp, t);
-	spin_unlock_bh(&ipip_lock);
 }
 
 static struct ip_tunnel * ipip_tunnel_locate(struct net *net,
@@ -223,12 +250,15 @@
 {
 	__be32 remote = parms->iph.daddr;
 	__be32 local = parms->iph.saddr;
-	struct ip_tunnel *t, **tp, *nt;
+	struct ip_tunnel *t, *nt;
+	struct ip_tunnel __rcu **tp;
 	struct net_device *dev;
 	char name[IFNAMSIZ];
 	struct ipip_net *ipn = net_generic(net, ipip_net_id);
 
-	for (tp = __ipip_bucket(ipn, parms); (t = *tp) != NULL; tp = &t->next) {
+	for (tp = __ipip_bucket(ipn, parms);
+		 (t = rtnl_dereference(*tp)) != NULL;
+		 tp = &t->next) {
 		if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr)
 			return t;
 	}
@@ -238,7 +268,7 @@
 	if (parms->name[0])
 		strlcpy(name, parms->name, IFNAMSIZ);
 	else
-		sprintf(name, "tunl%%d");
+		strcpy(name, "tunl%d");
 
 	dev = alloc_netdev(sizeof(*t), name, ipip_tunnel_setup);
 	if (dev == NULL)
@@ -254,7 +284,8 @@
 	nt = netdev_priv(dev);
 	nt->parms = *parms;
 
-	ipip_tunnel_init(dev);
+	if (ipip_tunnel_init(dev) < 0)
+		goto failed_free;
 
 	if (register_netdevice(dev) < 0)
 		goto failed_free;
@@ -264,20 +295,19 @@
 	return nt;
 
 failed_free:
-	free_netdev(dev);
+	ipip_dev_free(dev);
 	return NULL;
 }
 
+/* called with RTNL */
 static void ipip_tunnel_uninit(struct net_device *dev)
 {
 	struct net *net = dev_net(dev);
 	struct ipip_net *ipn = net_generic(net, ipip_net_id);
 
-	if (dev == ipn->fb_tunnel_dev) {
-		spin_lock_bh(&ipip_lock);
-		ipn->tunnels_wc[0] = NULL;
-		spin_unlock_bh(&ipip_lock);
-	} else
+	if (dev == ipn->fb_tunnel_dev)
+		rcu_assign_pointer(ipn->tunnels_wc[0], NULL);
+	else
 		ipip_tunnel_unlink(ipn, netdev_priv(dev));
 	dev_put(dev);
 }
@@ -359,8 +389,10 @@
 	const struct iphdr *iph = ip_hdr(skb);
 
 	rcu_read_lock();
-	if ((tunnel = ipip_tunnel_lookup(dev_net(skb->dev),
-					iph->saddr, iph->daddr)) != NULL) {
+	tunnel = ipip_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr);
+	if (tunnel != NULL) {
+		struct pcpu_tstats *tstats;
+
 		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
 			rcu_read_unlock();
 			kfree_skb(skb);
@@ -374,10 +406,16 @@
 		skb->protocol = htons(ETH_P_IP);
 		skb->pkt_type = PACKET_HOST;
 
-		skb_tunnel_rx(skb, tunnel->dev);
+		tstats = this_cpu_ptr(tunnel->dev->tstats);
+		tstats->rx_packets++;
+		tstats->rx_bytes += skb->len;
+
+		__skb_tunnel_rx(skb, tunnel->dev);
 
 		ipip_ecn_decapsulate(iph, skb);
+
 		netif_rx(skb);
+
 		rcu_read_unlock();
 		return 0;
 	}
@@ -394,13 +432,12 @@
 static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
-	struct net_device_stats *stats = &dev->stats;
-	struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+	struct pcpu_tstats *tstats;
 	struct iphdr  *tiph = &tunnel->parms.iph;
 	u8     tos = tunnel->parms.iph.tos;
 	__be16 df = tiph->frag_off;
 	struct rtable *rt;     			/* Route to the other host */
-	struct net_device *tdev;			/* Device to other host */
+	struct net_device *tdev;		/* Device to other host */
 	struct iphdr  *old_iph = ip_hdr(skb);
 	struct iphdr  *iph;			/* Our new IP header */
 	unsigned int max_headroom;		/* The extra header space needed */
@@ -410,13 +447,13 @@
 	if (skb->protocol != htons(ETH_P_IP))
 		goto tx_error;
 
-	if (tos&1)
+	if (tos & 1)
 		tos = old_iph->tos;
 
 	if (!dst) {
 		/* NBMA tunnel */
 		if ((rt = skb_rtable(skb)) == NULL) {
-			stats->tx_fifo_errors++;
+			dev->stats.tx_fifo_errors++;
 			goto tx_error;
 		}
 		if ((dst = rt->rt_gateway) == 0)
@@ -424,14 +461,20 @@
 	}
 
 	{
-		struct flowi fl = { .oif = tunnel->parms.link,
-				    .nl_u = { .ip4_u =
-					      { .daddr = dst,
-						.saddr = tiph->saddr,
-						.tos = RT_TOS(tos) } },
-				    .proto = IPPROTO_IPIP };
+		struct flowi fl = {
+			.oif = tunnel->parms.link,
+			.nl_u = {
+				.ip4_u = {
+					.daddr = dst,
+					.saddr = tiph->saddr,
+					.tos = RT_TOS(tos)
+				}
+			},
+			.proto = IPPROTO_IPIP
+		};
+
 		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
-			stats->tx_carrier_errors++;
+			dev->stats.tx_carrier_errors++;
 			goto tx_error_icmp;
 		}
 	}
@@ -439,7 +482,7 @@
 
 	if (tdev == dev) {
 		ip_rt_put(rt);
-		stats->collisions++;
+		dev->stats.collisions++;
 		goto tx_error;
 	}
 
@@ -449,7 +492,7 @@
 		mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr);
 
 		if (mtu < 68) {
-			stats->collisions++;
+			dev->stats.collisions++;
 			ip_rt_put(rt);
 			goto tx_error;
 		}
@@ -485,7 +528,7 @@
 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 		if (!new_skb) {
 			ip_rt_put(rt);
-			txq->tx_dropped++;
+			dev->stats.tx_dropped++;
 			dev_kfree_skb(skb);
 			return NETDEV_TX_OK;
 		}
@@ -522,14 +565,14 @@
 		iph->ttl	=	old_iph->ttl;
 
 	nf_reset(skb);
-
-	IPTUNNEL_XMIT();
+	tstats = this_cpu_ptr(dev->tstats);
+	__IPTUNNEL_XMIT(tstats, &dev->stats);
 	return NETDEV_TX_OK;
 
 tx_error_icmp:
 	dst_link_failure(skb);
 tx_error:
-	stats->tx_errors++;
+	dev->stats.tx_errors++;
 	dev_kfree_skb(skb);
 	return NETDEV_TX_OK;
 }
@@ -544,13 +587,19 @@
 	iph = &tunnel->parms.iph;
 
 	if (iph->daddr) {
-		struct flowi fl = { .oif = tunnel->parms.link,
-				    .nl_u = { .ip4_u =
-					      { .daddr = iph->daddr,
-						.saddr = iph->saddr,
-						.tos = RT_TOS(iph->tos) } },
-				    .proto = IPPROTO_IPIP };
+		struct flowi fl = {
+			.oif = tunnel->parms.link,
+			.nl_u = {
+				.ip4_u = {
+					.daddr = iph->daddr,
+					.saddr = iph->saddr,
+					.tos = RT_TOS(iph->tos)
+				}
+			},
+			.proto = IPPROTO_IPIP
+		};
 		struct rtable *rt;
+
 		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
 			tdev = rt->dst.dev;
 			ip_rt_put(rt);
@@ -696,13 +745,19 @@
 	.ndo_start_xmit	= ipip_tunnel_xmit,
 	.ndo_do_ioctl	= ipip_tunnel_ioctl,
 	.ndo_change_mtu	= ipip_tunnel_change_mtu,
-
+	.ndo_get_stats  = ipip_get_stats,
 };
 
+static void ipip_dev_free(struct net_device *dev)
+{
+	free_percpu(dev->tstats);
+	free_netdev(dev);
+}
+
 static void ipip_tunnel_setup(struct net_device *dev)
 {
 	dev->netdev_ops		= &ipip_netdev_ops;
-	dev->destructor		= free_netdev;
+	dev->destructor		= ipip_dev_free;
 
 	dev->type		= ARPHRD_TUNNEL;
 	dev->hard_header_len 	= LL_MAX_HEADER + sizeof(struct iphdr);
@@ -711,10 +766,11 @@
 	dev->iflink		= 0;
 	dev->addr_len		= 4;
 	dev->features		|= NETIF_F_NETNS_LOCAL;
+	dev->features		|= NETIF_F_LLTX;
 	dev->priv_flags		&= ~IFF_XMIT_DST_RELEASE;
 }
 
-static void ipip_tunnel_init(struct net_device *dev)
+static int ipip_tunnel_init(struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 
@@ -725,9 +781,15 @@
 	memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
 
 	ipip_tunnel_bind_dev(dev);
+
+	dev->tstats = alloc_percpu(struct pcpu_tstats);
+	if (!dev->tstats)
+		return -ENOMEM;
+
+	return 0;
 }
 
-static void __net_init ipip_fb_tunnel_init(struct net_device *dev)
+static int __net_init ipip_fb_tunnel_init(struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	struct iphdr *iph = &tunnel->parms.iph;
@@ -740,11 +802,16 @@
 	iph->protocol		= IPPROTO_IPIP;
 	iph->ihl		= 5;
 
+	dev->tstats = alloc_percpu(struct pcpu_tstats);
+	if (!dev->tstats)
+		return -ENOMEM;
+
 	dev_hold(dev);
-	ipn->tunnels_wc[0]	= tunnel;
+	rcu_assign_pointer(ipn->tunnels_wc[0], tunnel);
+	return 0;
 }
 
-static struct xfrm_tunnel ipip_handler = {
+static struct xfrm_tunnel ipip_handler __read_mostly = {
 	.handler	=	ipip_rcv,
 	.err_handler	=	ipip_err,
 	.priority	=	1,
@@ -760,11 +827,12 @@
 	for (prio = 1; prio < 4; prio++) {
 		int h;
 		for (h = 0; h < HASH_SIZE; h++) {
-			struct ip_tunnel *t = ipn->tunnels[prio][h];
+			struct ip_tunnel *t;
 
+			t = rtnl_dereference(ipn->tunnels[prio][h]);
 			while (t != NULL) {
 				unregister_netdevice_queue(t->dev, head);
-				t = t->next;
+				t = rtnl_dereference(t->next);
 			}
 		}
 	}
@@ -789,7 +857,9 @@
 	}
 	dev_net_set(ipn->fb_tunnel_dev, net);
 
-	ipip_fb_tunnel_init(ipn->fb_tunnel_dev);
+	err = ipip_fb_tunnel_init(ipn->fb_tunnel_dev);
+	if (err)
+		goto err_reg_dev;
 
 	if ((err = register_netdev(ipn->fb_tunnel_dev)))
 		goto err_reg_dev;
@@ -797,7 +867,7 @@
 	return 0;
 
 err_reg_dev:
-	free_netdev(ipn->fb_tunnel_dev);
+	ipip_dev_free(ipn->fb_tunnel_dev);
 err_alloc_dev:
 	/* nothing */
 	return err;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 179fcab..86dd569 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -75,7 +75,7 @@
 	struct net		*net;
 #endif
 	u32			id;
-	struct sock		*mroute_sk;
+	struct sock __rcu	*mroute_sk;
 	struct timer_list	ipmr_expire_timer;
 	struct list_head	mfc_unres_queue;
 	struct list_head	mfc_cache_array[MFC_LINES];
@@ -98,7 +98,7 @@
 };
 
 /* Big lock, protecting vif table, mrt cache and mroute socket state.
-   Note that the changes are semaphored via rtnl_lock.
+ * Note that the changes are semaphored via rtnl_lock.
  */
 
 static DEFINE_RWLOCK(mrt_lock);
@@ -113,11 +113,11 @@
 static DEFINE_SPINLOCK(mfc_unres_lock);
 
 /* We return to original Alan's scheme. Hash table of resolved
-   entries is changed only in process context and protected
-   with weak lock mrt_lock. Queue of unresolved entries is protected
-   with strong spinlock mfc_unres_lock.
-
-   In this case data path is free of exclusive locks at all.
+ * entries is changed only in process context and protected
+ * with weak lock mrt_lock. Queue of unresolved entries is protected
+ * with strong spinlock mfc_unres_lock.
+ *
+ * In this case data path is free of exclusive locks at all.
  */
 
 static struct kmem_cache *mrt_cachep __read_mostly;
@@ -396,9 +396,9 @@
 			set_fs(KERNEL_DS);
 			err = ops->ndo_do_ioctl(dev, &ifr, SIOCADDTUNNEL);
 			set_fs(oldfs);
-		} else
+		} else {
 			err = -EOPNOTSUPP;
-
+		}
 		dev = NULL;
 
 		if (err == 0 &&
@@ -495,7 +495,8 @@
 	dev->iflink = 0;
 
 	rcu_read_lock();
-	if ((in_dev = __in_dev_get_rcu(dev)) == NULL) {
+	in_dev = __in_dev_get_rcu(dev);
+	if (!in_dev) {
 		rcu_read_unlock();
 		goto failure;
 	}
@@ -552,9 +553,10 @@
 		mrt->mroute_reg_vif_num = -1;
 #endif
 
-	if (vifi+1 == mrt->maxvif) {
+	if (vifi + 1 == mrt->maxvif) {
 		int tmp;
-		for (tmp=vifi-1; tmp>=0; tmp--) {
+
+		for (tmp = vifi - 1; tmp >= 0; tmp--) {
 			if (VIF_EXISTS(mrt, tmp))
 				break;
 		}
@@ -565,25 +567,33 @@
 
 	dev_set_allmulti(dev, -1);
 
-	if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) {
+	in_dev = __in_dev_get_rtnl(dev);
+	if (in_dev) {
 		IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--;
 		ip_rt_multicast_event(in_dev);
 	}
 
-	if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER) && !notify)
+	if (v->flags & (VIFF_TUNNEL | VIFF_REGISTER) && !notify)
 		unregister_netdevice_queue(dev, head);
 
 	dev_put(dev);
 	return 0;
 }
 
-static inline void ipmr_cache_free(struct mfc_cache *c)
+static void ipmr_cache_free_rcu(struct rcu_head *head)
 {
+	struct mfc_cache *c = container_of(head, struct mfc_cache, rcu);
+
 	kmem_cache_free(mrt_cachep, c);
 }
 
+static inline void ipmr_cache_free(struct mfc_cache *c)
+{
+	call_rcu(&c->rcu, ipmr_cache_free_rcu);
+}
+
 /* Destroy an unresolved cache entry, killing queued skbs
-   and reporting error to netlink readers.
+ * and reporting error to netlink readers.
  */
 
 static void ipmr_destroy_unres(struct mr_table *mrt, struct mfc_cache *c)
@@ -605,8 +615,9 @@
 			memset(&e->msg, 0, sizeof(e->msg));
 
 			rtnl_unicast(skb, net, NETLINK_CB(skb).pid);
-		} else
+		} else {
 			kfree_skb(skb);
+		}
 	}
 
 	ipmr_cache_free(c);
@@ -724,13 +735,13 @@
 	case 0:
 		if (vifc->vifc_flags == VIFF_USE_IFINDEX) {
 			dev = dev_get_by_index(net, vifc->vifc_lcl_ifindex);
-			if (dev && dev->ip_ptr == NULL) {
+			if (dev && __in_dev_get_rtnl(dev) == NULL) {
 				dev_put(dev);
 				return -EADDRNOTAVAIL;
 			}
-		} else
+		} else {
 			dev = ip_dev_find(net, vifc->vifc_lcl_addr.s_addr);
-
+		}
 		if (!dev)
 			return -EADDRNOTAVAIL;
 		err = dev_set_allmulti(dev, 1);
@@ -743,16 +754,16 @@
 		return -EINVAL;
 	}
 
-	if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) {
+	in_dev = __in_dev_get_rtnl(dev);
+	if (!in_dev) {
 		dev_put(dev);
 		return -EADDRNOTAVAIL;
 	}
 	IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++;
 	ip_rt_multicast_event(in_dev);
 
-	/*
-	 *	Fill in the VIF structures
-	 */
+	/* Fill in the VIF structures */
+
 	v->rate_limit = vifc->vifc_rate_limit;
 	v->local = vifc->vifc_lcl_addr.s_addr;
 	v->remote = vifc->vifc_rmt_addr.s_addr;
@@ -765,14 +776,14 @@
 	v->pkt_in = 0;
 	v->pkt_out = 0;
 	v->link = dev->ifindex;
-	if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER))
+	if (v->flags & (VIFF_TUNNEL | VIFF_REGISTER))
 		v->link = dev->iflink;
 
 	/* And finish update writing critical data */
 	write_lock_bh(&mrt_lock);
 	v->dev = dev;
 #ifdef CONFIG_IP_PIMSM
-	if (v->flags&VIFF_REGISTER)
+	if (v->flags & VIFF_REGISTER)
 		mrt->mroute_reg_vif_num = vifi;
 #endif
 	if (vifi+1 > mrt->maxvif)
@@ -781,6 +792,7 @@
 	return 0;
 }
 
+/* called with rcu_read_lock() */
 static struct mfc_cache *ipmr_cache_find(struct mr_table *mrt,
 					 __be32 origin,
 					 __be32 mcastgrp)
@@ -788,7 +800,7 @@
 	int line = MFC_HASH(mcastgrp, origin);
 	struct mfc_cache *c;
 
-	list_for_each_entry(c, &mrt->mfc_cache_array[line], list) {
+	list_for_each_entry_rcu(c, &mrt->mfc_cache_array[line], list) {
 		if (c->mfc_origin == origin && c->mfc_mcastgrp == mcastgrp)
 			return c;
 	}
@@ -801,19 +813,20 @@
 static struct mfc_cache *ipmr_cache_alloc(void)
 {
 	struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
-	if (c == NULL)
-		return NULL;
-	c->mfc_un.res.minvif = MAXVIFS;
+
+	if (c)
+		c->mfc_un.res.minvif = MAXVIFS;
 	return c;
 }
 
 static struct mfc_cache *ipmr_cache_alloc_unres(void)
 {
 	struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
-	if (c == NULL)
-		return NULL;
-	skb_queue_head_init(&c->mfc_un.unres.unresolved);
-	c->mfc_un.unres.expires = jiffies + 10*HZ;
+
+	if (c) {
+		skb_queue_head_init(&c->mfc_un.unres.unresolved);
+		c->mfc_un.unres.expires = jiffies + 10*HZ;
+	}
 	return c;
 }
 
@@ -827,17 +840,15 @@
 	struct sk_buff *skb;
 	struct nlmsgerr *e;
 
-	/*
-	 *	Play the pending entries through our router
-	 */
+	/* Play the pending entries through our router */
 
 	while ((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) {
 		if (ip_hdr(skb)->version == 0) {
 			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
 
 			if (__ipmr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) {
-				nlh->nlmsg_len = (skb_tail_pointer(skb) -
-						  (u8 *)nlh);
+				nlh->nlmsg_len = skb_tail_pointer(skb) -
+						 (u8 *)nlh;
 			} else {
 				nlh->nlmsg_type = NLMSG_ERROR;
 				nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
@@ -848,8 +859,9 @@
 			}
 
 			rtnl_unicast(skb, net, NETLINK_CB(skb).pid);
-		} else
+		} else {
 			ip_mr_forward(net, mrt, skb, c, 0);
+		}
 	}
 }
 
@@ -867,6 +879,7 @@
 	const int ihl = ip_hdrlen(pkt);
 	struct igmphdr *igmp;
 	struct igmpmsg *msg;
+	struct sock *mroute_sk;
 	int ret;
 
 #ifdef CONFIG_IP_PIMSM
@@ -882,9 +895,9 @@
 #ifdef CONFIG_IP_PIMSM
 	if (assert == IGMPMSG_WHOLEPKT) {
 		/* Ugly, but we have no choice with this interface.
-		   Duplicate old header, fix ihl, length etc.
-		   And all this only to mangle msg->im_msgtype and
-		   to set msg->im_mbz to "mbz" :-)
+		 * Duplicate old header, fix ihl, length etc.
+		 * And all this only to mangle msg->im_msgtype and
+		 * to set msg->im_mbz to "mbz" :-)
 		 */
 		skb_push(skb, sizeof(struct iphdr));
 		skb_reset_network_header(skb);
@@ -901,39 +914,38 @@
 #endif
 	{
 
-	/*
-	 *	Copy the IP header
-	 */
+	/* Copy the IP header */
 
 	skb->network_header = skb->tail;
 	skb_put(skb, ihl);
 	skb_copy_to_linear_data(skb, pkt->data, ihl);
-	ip_hdr(skb)->protocol = 0;			/* Flag to the kernel this is a route add */
+	ip_hdr(skb)->protocol = 0;	/* Flag to the kernel this is a route add */
 	msg = (struct igmpmsg *)skb_network_header(skb);
 	msg->im_vif = vifi;
 	skb_dst_set(skb, dst_clone(skb_dst(pkt)));
 
-	/*
-	 *	Add our header
-	 */
+	/* Add our header */
 
-	igmp=(struct igmphdr *)skb_put(skb, sizeof(struct igmphdr));
+	igmp = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr));
 	igmp->type	=
 	msg->im_msgtype = assert;
-	igmp->code 	=	0;
-	ip_hdr(skb)->tot_len = htons(skb->len);			/* Fix the length */
+	igmp->code	= 0;
+	ip_hdr(skb)->tot_len = htons(skb->len);		/* Fix the length */
 	skb->transport_header = skb->network_header;
 	}
 
-	if (mrt->mroute_sk == NULL) {
+	rcu_read_lock();
+	mroute_sk = rcu_dereference(mrt->mroute_sk);
+	if (mroute_sk == NULL) {
+		rcu_read_unlock();
 		kfree_skb(skb);
 		return -EINVAL;
 	}
 
-	/*
-	 *	Deliver to mrouted
-	 */
-	ret = sock_queue_rcv_skb(mrt->mroute_sk, skb);
+	/* Deliver to mrouted */
+
+	ret = sock_queue_rcv_skb(mroute_sk, skb);
+	rcu_read_unlock();
 	if (ret < 0) {
 		if (net_ratelimit())
 			printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n");
@@ -965,9 +977,7 @@
 	}
 
 	if (!found) {
-		/*
-		 *	Create a new entry if allowable
-		 */
+		/* Create a new entry if allowable */
 
 		if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
 		    (c = ipmr_cache_alloc_unres()) == NULL) {
@@ -977,16 +987,14 @@
 			return -ENOBUFS;
 		}
 
-		/*
-		 *	Fill in the new cache entry
-		 */
+		/* Fill in the new cache entry */
+
 		c->mfc_parent	= -1;
 		c->mfc_origin	= iph->saddr;
 		c->mfc_mcastgrp	= iph->daddr;
 
-		/*
-		 *	Reflect first query at mrouted.
-		 */
+		/* Reflect first query at mrouted. */
+
 		err = ipmr_cache_report(mrt, skb, vifi, IGMPMSG_NOCACHE);
 		if (err < 0) {
 			/* If the report failed throw the cache entry
@@ -1006,10 +1014,9 @@
 			mod_timer(&mrt->ipmr_expire_timer, c->mfc_un.unres.expires);
 	}
 
-	/*
-	 *	See if we can append the packet
-	 */
-	if (c->mfc_un.unres.unresolved.qlen>3) {
+	/* See if we can append the packet */
+
+	if (c->mfc_un.unres.unresolved.qlen > 3) {
 		kfree_skb(skb);
 		err = -ENOBUFS;
 	} else {
@@ -1035,9 +1042,7 @@
 	list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[line], list) {
 		if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
 		    c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) {
-			write_lock_bh(&mrt_lock);
-			list_del(&c->list);
-			write_unlock_bh(&mrt_lock);
+			list_del_rcu(&c->list);
 
 			ipmr_cache_free(c);
 			return 0;
@@ -1090,9 +1095,7 @@
 	if (!mrtsock)
 		c->mfc_flags |= MFC_STATIC;
 
-	write_lock_bh(&mrt_lock);
-	list_add(&c->list, &mrt->mfc_cache_array[line]);
-	write_unlock_bh(&mrt_lock);
+	list_add_rcu(&c->list, &mrt->mfc_cache_array[line]);
 
 	/*
 	 *	Check to see if we resolved a queued list. If so we
@@ -1130,26 +1133,21 @@
 	LIST_HEAD(list);
 	struct mfc_cache *c, *next;
 
-	/*
-	 *	Shut down all active vif entries
-	 */
+	/* Shut down all active vif entries */
+
 	for (i = 0; i < mrt->maxvif; i++) {
-		if (!(mrt->vif_table[i].flags&VIFF_STATIC))
+		if (!(mrt->vif_table[i].flags & VIFF_STATIC))
 			vif_delete(mrt, i, 0, &list);
 	}
 	unregister_netdevice_many(&list);
 
-	/*
-	 *	Wipe the cache
-	 */
+	/* Wipe the cache */
+
 	for (i = 0; i < MFC_LINES; i++) {
 		list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[i], list) {
-			if (c->mfc_flags&MFC_STATIC)
+			if (c->mfc_flags & MFC_STATIC)
 				continue;
-			write_lock_bh(&mrt_lock);
-			list_del(&c->list);
-			write_unlock_bh(&mrt_lock);
-
+			list_del_rcu(&c->list);
 			ipmr_cache_free(c);
 		}
 	}
@@ -1164,6 +1162,9 @@
 	}
 }
 
+/* called from ip_ra_control(), before an RCU grace period,
+ * we dont need to call synchronize_rcu() here
+ */
 static void mrtsock_destruct(struct sock *sk)
 {
 	struct net *net = sock_net(sk);
@@ -1171,13 +1172,9 @@
 
 	rtnl_lock();
 	ipmr_for_each_table(mrt, net) {
-		if (sk == mrt->mroute_sk) {
+		if (sk == rtnl_dereference(mrt->mroute_sk)) {
 			IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
-
-			write_lock_bh(&mrt_lock);
-			mrt->mroute_sk = NULL;
-			write_unlock_bh(&mrt_lock);
-
+			rcu_assign_pointer(mrt->mroute_sk, NULL);
 			mroute_clean_tables(mrt);
 		}
 	}
@@ -1204,7 +1201,8 @@
 		return -ENOENT;
 
 	if (optname != MRT_INIT) {
-		if (sk != mrt->mroute_sk && !capable(CAP_NET_ADMIN))
+		if (sk != rcu_dereference_raw(mrt->mroute_sk) &&
+		    !capable(CAP_NET_ADMIN))
 			return -EACCES;
 	}
 
@@ -1217,23 +1215,20 @@
 			return -ENOPROTOOPT;
 
 		rtnl_lock();
-		if (mrt->mroute_sk) {
+		if (rtnl_dereference(mrt->mroute_sk)) {
 			rtnl_unlock();
 			return -EADDRINUSE;
 		}
 
 		ret = ip_ra_control(sk, 1, mrtsock_destruct);
 		if (ret == 0) {
-			write_lock_bh(&mrt_lock);
-			mrt->mroute_sk = sk;
-			write_unlock_bh(&mrt_lock);
-
+			rcu_assign_pointer(mrt->mroute_sk, sk);
 			IPV4_DEVCONF_ALL(net, MC_FORWARDING)++;
 		}
 		rtnl_unlock();
 		return ret;
 	case MRT_DONE:
-		if (sk != mrt->mroute_sk)
+		if (sk != rcu_dereference_raw(mrt->mroute_sk))
 			return -EACCES;
 		return ip_ra_control(sk, 0, NULL);
 	case MRT_ADD_VIF:
@@ -1246,7 +1241,8 @@
 			return -ENFILE;
 		rtnl_lock();
 		if (optname == MRT_ADD_VIF) {
-			ret = vif_add(net, mrt, &vif, sk == mrt->mroute_sk);
+			ret = vif_add(net, mrt, &vif,
+				      sk == rtnl_dereference(mrt->mroute_sk));
 		} else {
 			ret = vif_delete(mrt, vif.vifc_vifi, 0, NULL);
 		}
@@ -1267,7 +1263,8 @@
 		if (optname == MRT_DEL_MFC)
 			ret = ipmr_mfc_delete(mrt, &mfc);
 		else
-			ret = ipmr_mfc_add(net, mrt, &mfc, sk == mrt->mroute_sk);
+			ret = ipmr_mfc_add(net, mrt, &mfc,
+					   sk == rtnl_dereference(mrt->mroute_sk));
 		rtnl_unlock();
 		return ret;
 		/*
@@ -1276,7 +1273,7 @@
 	case MRT_ASSERT:
 	{
 		int v;
-		if (get_user(v,(int __user *)optval))
+		if (get_user(v, (int __user *)optval))
 			return -EFAULT;
 		mrt->mroute_do_assert = (v) ? 1 : 0;
 		return 0;
@@ -1286,7 +1283,7 @@
 	{
 		int v;
 
-		if (get_user(v,(int __user *)optval))
+		if (get_user(v, (int __user *)optval))
 			return -EFAULT;
 		v = (v) ? 1 : 0;
 
@@ -1309,14 +1306,16 @@
 			return -EINVAL;
 		if (get_user(v, (u32 __user *)optval))
 			return -EFAULT;
-		if (sk == mrt->mroute_sk)
-			return -EBUSY;
 
 		rtnl_lock();
 		ret = 0;
-		if (!ipmr_new_table(net, v))
-			ret = -ENOMEM;
-		raw_sk(sk)->ipmr_table = v;
+		if (sk == rtnl_dereference(mrt->mroute_sk)) {
+			ret = -EBUSY;
+		} else {
+			if (!ipmr_new_table(net, v))
+				ret = -ENOMEM;
+			raw_sk(sk)->ipmr_table = v;
+		}
 		rtnl_unlock();
 		return ret;
 	}
@@ -1347,9 +1346,9 @@
 
 	if (optname != MRT_VERSION &&
 #ifdef CONFIG_IP_PIMSM
-	   optname!=MRT_PIM &&
+	   optname != MRT_PIM &&
 #endif
-	   optname!=MRT_ASSERT)
+	   optname != MRT_ASSERT)
 		return -ENOPROTOOPT;
 
 	if (get_user(olr, optlen))
@@ -1416,19 +1415,19 @@
 		if (copy_from_user(&sr, arg, sizeof(sr)))
 			return -EFAULT;
 
-		read_lock(&mrt_lock);
+		rcu_read_lock();
 		c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr);
 		if (c) {
 			sr.pktcnt = c->mfc_un.res.pkt;
 			sr.bytecnt = c->mfc_un.res.bytes;
 			sr.wrong_if = c->mfc_un.res.wrong_if;
-			read_unlock(&mrt_lock);
+			rcu_read_unlock();
 
 			if (copy_to_user(arg, &sr, sizeof(sr)))
 				return -EFAULT;
 			return 0;
 		}
-		read_unlock(&mrt_lock);
+		rcu_read_unlock();
 		return -EADDRNOTAVAIL;
 	default:
 		return -ENOIOCTLCMD;
@@ -1465,7 +1464,7 @@
 };
 
 /*
- * 	Encapsulate a packet by attaching a valid IPIP header to it.
+ *	Encapsulate a packet by attaching a valid IPIP header to it.
  *	This avoids tunnel drivers and other mess and gives us the speed so
  *	important for multicast video.
  */
@@ -1480,7 +1479,7 @@
 	skb_reset_network_header(skb);
 	iph = ip_hdr(skb);
 
-	iph->version	= 	4;
+	iph->version	=	4;
 	iph->tos	=	old_iph->tos;
 	iph->ttl	=	old_iph->ttl;
 	iph->frag_off	=	0;
@@ -1498,7 +1497,7 @@
 
 static inline int ipmr_forward_finish(struct sk_buff *skb)
 {
-	struct ip_options * opt	= &(IPCB(skb)->opt);
+	struct ip_options *opt = &(IPCB(skb)->opt);
 
 	IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
 
@@ -1535,22 +1534,34 @@
 	}
 #endif
 
-	if (vif->flags&VIFF_TUNNEL) {
-		struct flowi fl = { .oif = vif->link,
-				    .nl_u = { .ip4_u =
-					      { .daddr = vif->remote,
-						.saddr = vif->local,
-						.tos = RT_TOS(iph->tos) } },
-				    .proto = IPPROTO_IPIP };
+	if (vif->flags & VIFF_TUNNEL) {
+		struct flowi fl = {
+			.oif = vif->link,
+			.nl_u = {
+				.ip4_u = {
+					.daddr = vif->remote,
+					.saddr = vif->local,
+					.tos = RT_TOS(iph->tos)
+				}
+			},
+			.proto = IPPROTO_IPIP
+		};
+
 		if (ip_route_output_key(net, &rt, &fl))
 			goto out_free;
 		encap = sizeof(struct iphdr);
 	} else {
-		struct flowi fl = { .oif = vif->link,
-				    .nl_u = { .ip4_u =
-					      { .daddr = iph->daddr,
-						.tos = RT_TOS(iph->tos) } },
-				    .proto = IPPROTO_IPIP };
+		struct flowi fl = {
+			.oif = vif->link,
+			.nl_u = {
+				.ip4_u = {
+					.daddr = iph->daddr,
+					.tos = RT_TOS(iph->tos)
+				}
+			},
+			.proto = IPPROTO_IPIP
+		};
+
 		if (ip_route_output_key(net, &rt, &fl))
 			goto out_free;
 	}
@@ -1559,8 +1570,8 @@
 
 	if (skb->len+encap > dst_mtu(&rt->dst) && (ntohs(iph->frag_off) & IP_DF)) {
 		/* Do not fragment multicasts. Alas, IPv4 does not
-		   allow to send ICMP, so that packets will disappear
-		   to blackhole.
+		 * allow to send ICMP, so that packets will disappear
+		 * to blackhole.
 		 */
 
 		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
@@ -1583,7 +1594,8 @@
 	ip_decrease_ttl(ip_hdr(skb));
 
 	/* FIXME: forward and output firewalls used to be called here.
-	 * What do we do with netfilter? -- RR */
+	 * What do we do with netfilter? -- RR
+	 */
 	if (vif->flags & VIFF_TUNNEL) {
 		ip_encap(skb, vif->local, vif->remote);
 		/* FIXME: extra output firewall step used to be here. --RR */
@@ -1644,15 +1656,15 @@
 
 		if (skb_rtable(skb)->fl.iif == 0) {
 			/* It is our own packet, looped back.
-			   Very complicated situation...
-
-			   The best workaround until routing daemons will be
-			   fixed is not to redistribute packet, if it was
-			   send through wrong interface. It means, that
-			   multicast applications WILL NOT work for
-			   (S,G), which have default multicast route pointing
-			   to wrong oif. In any case, it is not a good
-			   idea to use multicasting applications on router.
+			 * Very complicated situation...
+			 *
+			 * The best workaround until routing daemons will be
+			 * fixed is not to redistribute packet, if it was
+			 * send through wrong interface. It means, that
+			 * multicast applications WILL NOT work for
+			 * (S,G), which have default multicast route pointing
+			 * to wrong oif. In any case, it is not a good
+			 * idea to use multicasting applications on router.
 			 */
 			goto dont_forward;
 		}
@@ -1662,9 +1674,9 @@
 
 		if (true_vifi >= 0 && mrt->mroute_do_assert &&
 		    /* pimsm uses asserts, when switching from RPT to SPT,
-		       so that we cannot check that packet arrived on an oif.
-		       It is bad, but otherwise we would need to move pretty
-		       large chunk of pimd to kernel. Ough... --ANK
+		     * so that we cannot check that packet arrived on an oif.
+		     * It is bad, but otherwise we would need to move pretty
+		     * large chunk of pimd to kernel. Ough... --ANK
 		     */
 		    (mrt->mroute_do_pim ||
 		     cache->mfc_un.res.ttls[true_vifi] < 255) &&
@@ -1682,10 +1694,12 @@
 	/*
 	 *	Forward the frame
 	 */
-	for (ct = cache->mfc_un.res.maxvif-1; ct >= cache->mfc_un.res.minvif; ct--) {
+	for (ct = cache->mfc_un.res.maxvif - 1;
+	     ct >= cache->mfc_un.res.minvif; ct--) {
 		if (ip_hdr(skb)->ttl > cache->mfc_un.res.ttls[ct]) {
 			if (psend != -1) {
 				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+
 				if (skb2)
 					ipmr_queue_xmit(net, mrt, skb2, cache,
 							psend);
@@ -1696,6 +1710,7 @@
 	if (psend != -1) {
 		if (local) {
 			struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+
 			if (skb2)
 				ipmr_queue_xmit(net, mrt, skb2, cache, psend);
 		} else {
@@ -1713,6 +1728,7 @@
 
 /*
  *	Multicast packets for forwarding arrive here
+ *	Called with rcu_read_lock();
  */
 
 int ip_mr_input(struct sk_buff *skb)
@@ -1724,9 +1740,9 @@
 	int err;
 
 	/* Packet is looped back after forward, it should not be
-	   forwarded second time, but still can be delivered locally.
+	 * forwarded second time, but still can be delivered locally.
 	 */
-	if (IPCB(skb)->flags&IPSKB_FORWARDED)
+	if (IPCB(skb)->flags & IPSKB_FORWARDED)
 		goto dont_forward;
 
 	err = ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt);
@@ -1736,28 +1752,28 @@
 	}
 
 	if (!local) {
-		    if (IPCB(skb)->opt.router_alert) {
-			    if (ip_call_ra_chain(skb))
-				    return 0;
-		    } else if (ip_hdr(skb)->protocol == IPPROTO_IGMP){
-			    /* IGMPv1 (and broken IGMPv2 implementations sort of
-			       Cisco IOS <= 11.2(8)) do not put router alert
-			       option to IGMP packets destined to routable
-			       groups. It is very bad, because it means
-			       that we can forward NO IGMP messages.
-			     */
-			    read_lock(&mrt_lock);
-			    if (mrt->mroute_sk) {
-				    nf_reset(skb);
-				    raw_rcv(mrt->mroute_sk, skb);
-				    read_unlock(&mrt_lock);
-				    return 0;
-			    }
-			    read_unlock(&mrt_lock);
+		if (IPCB(skb)->opt.router_alert) {
+			if (ip_call_ra_chain(skb))
+				return 0;
+		} else if (ip_hdr(skb)->protocol == IPPROTO_IGMP) {
+			/* IGMPv1 (and broken IGMPv2 implementations sort of
+			 * Cisco IOS <= 11.2(8)) do not put router alert
+			 * option to IGMP packets destined to routable
+			 * groups. It is very bad, because it means
+			 * that we can forward NO IGMP messages.
+			 */
+			struct sock *mroute_sk;
+
+			mroute_sk = rcu_dereference(mrt->mroute_sk);
+			if (mroute_sk) {
+				nf_reset(skb);
+				raw_rcv(mroute_sk, skb);
+				return 0;
+			}
 		    }
 	}
 
-	read_lock(&mrt_lock);
+	/* already under rcu_read_lock() */
 	cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
 
 	/*
@@ -1769,13 +1785,12 @@
 		if (local) {
 			struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
 			ip_local_deliver(skb);
-			if (skb2 == NULL) {
-				read_unlock(&mrt_lock);
+			if (skb2 == NULL)
 				return -ENOBUFS;
-			}
 			skb = skb2;
 		}
 
+		read_lock(&mrt_lock);
 		vif = ipmr_find_vif(mrt, skb->dev);
 		if (vif >= 0) {
 			int err2 = ipmr_cache_unresolved(mrt, vif, skb);
@@ -1788,8 +1803,8 @@
 		return -ENODEV;
 	}
 
+	read_lock(&mrt_lock);
 	ip_mr_forward(net, mrt, skb, cache, local);
-
 	read_unlock(&mrt_lock);
 
 	if (local)
@@ -1805,6 +1820,7 @@
 }
 
 #ifdef CONFIG_IP_PIMSM
+/* called with rcu_read_lock() */
 static int __pim_rcv(struct mr_table *mrt, struct sk_buff *skb,
 		     unsigned int pimlen)
 {
@@ -1813,10 +1829,10 @@
 
 	encap = (struct iphdr *)(skb_transport_header(skb) + pimlen);
 	/*
-	   Check that:
-	   a. packet is really destinted to a multicast group
-	   b. packet is not a NULL-REGISTER
-	   c. packet is not truncated
+	 * Check that:
+	 * a. packet is really sent to a multicast group
+	 * b. packet is not a NULL-REGISTER
+	 * c. packet is not truncated
 	 */
 	if (!ipv4_is_multicast(encap->daddr) ||
 	    encap->tot_len == 0 ||
@@ -1826,26 +1842,23 @@
 	read_lock(&mrt_lock);
 	if (mrt->mroute_reg_vif_num >= 0)
 		reg_dev = mrt->vif_table[mrt->mroute_reg_vif_num].dev;
-	if (reg_dev)
-		dev_hold(reg_dev);
 	read_unlock(&mrt_lock);
 
 	if (reg_dev == NULL)
 		return 1;
 
 	skb->mac_header = skb->network_header;
-	skb_pull(skb, (u8*)encap - skb->data);
+	skb_pull(skb, (u8 *)encap - skb->data);
 	skb_reset_network_header(skb);
 	skb->protocol = htons(ETH_P_IP);
-	skb->ip_summed = 0;
+	skb->ip_summed = CHECKSUM_NONE;
 	skb->pkt_type = PACKET_HOST;
 
 	skb_tunnel_rx(skb, reg_dev);
 
 	netif_rx(skb);
-	dev_put(reg_dev);
 
-	return 0;
+	return NET_RX_SUCCESS;
 }
 #endif
 
@@ -1854,7 +1867,7 @@
  * Handle IGMP messages of PIMv1
  */
 
-int pim_rcv_v1(struct sk_buff * skb)
+int pim_rcv_v1(struct sk_buff *skb)
 {
 	struct igmphdr *pim;
 	struct net *net = dev_net(skb->dev);
@@ -1881,7 +1894,7 @@
 #endif
 
 #ifdef CONFIG_IP_PIMSM_V2
-static int pim_rcv(struct sk_buff * skb)
+static int pim_rcv(struct sk_buff *skb)
 {
 	struct pimreghdr *pim;
 	struct net *net = dev_net(skb->dev);
@@ -1891,8 +1904,8 @@
 		goto drop;
 
 	pim = (struct pimreghdr *)skb_transport_header(skb);
-	if (pim->type != ((PIM_VERSION<<4)|(PIM_REGISTER)) ||
-	    (pim->flags&PIM_NULL_REGISTER) ||
+	if (pim->type != ((PIM_VERSION << 4) | (PIM_REGISTER)) ||
+	    (pim->flags & PIM_NULL_REGISTER) ||
 	    (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 &&
 	     csum_fold(skb_checksum(skb, 0, skb->len, 0))))
 		goto drop;
@@ -1958,28 +1971,33 @@
 	if (mrt == NULL)
 		return -ENOENT;
 
-	read_lock(&mrt_lock);
+	rcu_read_lock();
 	cache = ipmr_cache_find(mrt, rt->rt_src, rt->rt_dst);
 
 	if (cache == NULL) {
 		struct sk_buff *skb2;
 		struct iphdr *iph;
 		struct net_device *dev;
-		int vif;
+		int vif = -1;
 
 		if (nowait) {
-			read_unlock(&mrt_lock);
+			rcu_read_unlock();
 			return -EAGAIN;
 		}
 
 		dev = skb->dev;
-		if (dev == NULL || (vif = ipmr_find_vif(mrt, dev)) < 0) {
+		read_lock(&mrt_lock);
+		if (dev)
+			vif = ipmr_find_vif(mrt, dev);
+		if (vif < 0) {
 			read_unlock(&mrt_lock);
+			rcu_read_unlock();
 			return -ENODEV;
 		}
 		skb2 = skb_clone(skb, GFP_ATOMIC);
 		if (!skb2) {
 			read_unlock(&mrt_lock);
+			rcu_read_unlock();
 			return -ENOMEM;
 		}
 
@@ -1992,13 +2010,16 @@
 		iph->version = 0;
 		err = ipmr_cache_unresolved(mrt, vif, skb2);
 		read_unlock(&mrt_lock);
+		rcu_read_unlock();
 		return err;
 	}
 
-	if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY))
+	read_lock(&mrt_lock);
+	if (!nowait && (rtm->rtm_flags & RTM_F_NOTIFY))
 		cache->mfc_flags |= MFC_NOTIFY;
 	err = __ipmr_fill_mroute(mrt, skb, cache, rtm);
 	read_unlock(&mrt_lock);
+	rcu_read_unlock();
 	return err;
 }
 
@@ -2050,14 +2071,14 @@
 	s_h = cb->args[1];
 	s_e = cb->args[2];
 
-	read_lock(&mrt_lock);
+	rcu_read_lock();
 	ipmr_for_each_table(mrt, net) {
 		if (t < s_t)
 			goto next_table;
 		if (t > s_t)
 			s_h = 0;
 		for (h = s_h; h < MFC_LINES; h++) {
-			list_for_each_entry(mfc, &mrt->mfc_cache_array[h], list) {
+			list_for_each_entry_rcu(mfc, &mrt->mfc_cache_array[h], list) {
 				if (e < s_e)
 					goto next_entry;
 				if (ipmr_fill_mroute(mrt, skb,
@@ -2075,7 +2096,7 @@
 		t++;
 	}
 done:
-	read_unlock(&mrt_lock);
+	rcu_read_unlock();
 
 	cb->args[2] = e;
 	cb->args[1] = h;
@@ -2086,7 +2107,8 @@
 
 #ifdef CONFIG_PROC_FS
 /*
- *	The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif
+ *	The /proc interfaces to multicast routing :
+ *	/proc/net/ip_mr_cache & /proc/net/ip_mr_vif
  */
 struct ipmr_vif_iter {
 	struct seq_net_private p;
@@ -2208,14 +2230,14 @@
 	struct mr_table *mrt = it->mrt;
 	struct mfc_cache *mfc;
 
-	read_lock(&mrt_lock);
+	rcu_read_lock();
 	for (it->ct = 0; it->ct < MFC_LINES; it->ct++) {
 		it->cache = &mrt->mfc_cache_array[it->ct];
-		list_for_each_entry(mfc, it->cache, list)
+		list_for_each_entry_rcu(mfc, it->cache, list)
 			if (pos-- == 0)
 				return mfc;
 	}
-	read_unlock(&mrt_lock);
+	rcu_read_unlock();
 
 	spin_lock_bh(&mfc_unres_lock);
 	it->cache = &mrt->mfc_unres_queue;
@@ -2274,7 +2296,7 @@
 	}
 
 	/* exhausted cache_array, show unresolved */
-	read_unlock(&mrt_lock);
+	rcu_read_unlock();
 	it->cache = &mrt->mfc_unres_queue;
 	it->ct = 0;
 
@@ -2282,7 +2304,7 @@
 	if (!list_empty(it->cache))
 		return list_first_entry(it->cache, struct mfc_cache, list);
 
- end_of_list:
+end_of_list:
 	spin_unlock_bh(&mfc_unres_lock);
 	it->cache = NULL;
 
@@ -2297,7 +2319,7 @@
 	if (it->cache == &mrt->mfc_unres_queue)
 		spin_unlock_bh(&mfc_unres_lock);
 	else if (it->cache == &mrt->mfc_cache_array[it->ct])
-		read_unlock(&mrt_lock);
+		rcu_read_unlock();
 }
 
 static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
@@ -2323,7 +2345,7 @@
 				   mfc->mfc_un.res.bytes,
 				   mfc->mfc_un.res.wrong_if);
 			for (n = mfc->mfc_un.res.minvif;
-			     n < mfc->mfc_un.res.maxvif; n++ ) {
+			     n < mfc->mfc_un.res.maxvif; n++) {
 				if (VIF_EXISTS(mrt, n) &&
 				    mfc->mfc_un.res.ttls[n] < 255)
 					seq_printf(seq,
@@ -2421,7 +2443,7 @@
 
 	mrt_cachep = kmem_cache_create("ip_mrt_cache",
 				       sizeof(struct mfc_cache),
-				       0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
+				       0, SLAB_HWCACHE_ALIGN | SLAB_PANIC,
 				       NULL);
 	if (!mrt_cachep)
 		return -ENOMEM;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 1833bdb..8e33506 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -324,10 +324,10 @@
 
 config IP_NF_TARGET_TTL
 	tristate '"TTL" target support'
-	depends on NETFILTER_ADVANCED
+	depends on NETFILTER_ADVANCED && IP_NF_MANGLE
 	select NETFILTER_XT_TARGET_HL
 	---help---
-	This is a backwards-compat option for the user's convenience
+	This is a backwards-compatible option for the user's convenience
 	(e.g. when running oldconfig). It selects
 	CONFIG_NETFILTER_XT_TARGET_HL.
 
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index e8f4f9a..3cad259 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -72,7 +72,7 @@
 	for (i = 0; i < len; i++)
 		ret |= (hdr_addr[i] ^ ap->addr[i]) & ap->mask[i];
 
-	return (ret != 0);
+	return ret != 0;
 }
 
 /*
@@ -228,7 +228,7 @@
 	return NF_DROP;
 }
 
-static inline const struct arpt_entry_target *
+static inline const struct xt_entry_target *
 arpt_get_target_c(const struct arpt_entry *e)
 {
 	return arpt_get_target((struct arpt_entry *)e);
@@ -282,7 +282,7 @@
 
 	arp = arp_hdr(skb);
 	do {
-		const struct arpt_entry_target *t;
+		const struct xt_entry_target *t;
 
 		if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) {
 			e = arpt_next_entry(e);
@@ -297,10 +297,10 @@
 		if (!t->u.kernel.target->target) {
 			int v;
 
-			v = ((struct arpt_standard_target *)t)->verdict;
+			v = ((struct xt_standard_target *)t)->verdict;
 			if (v < 0) {
 				/* Pop from stack? */
-				if (v != ARPT_RETURN) {
+				if (v != XT_RETURN) {
 					verdict = (unsigned)(-v) - 1;
 					break;
 				}
@@ -332,7 +332,7 @@
 		/* Target might have changed stuff. */
 		arp = arp_hdr(skb);
 
-		if (verdict == ARPT_CONTINUE)
+		if (verdict == XT_CONTINUE)
 			e = arpt_next_entry(e);
 		else
 			/* Verdict */
@@ -377,7 +377,7 @@
 		e->counters.pcnt = pos;
 
 		for (;;) {
-			const struct arpt_standard_target *t
+			const struct xt_standard_target *t
 				= (void *)arpt_get_target_c(e);
 			int visited = e->comefrom & (1 << hook);
 
@@ -392,13 +392,13 @@
 			/* Unconditional return/END. */
 			if ((e->target_offset == sizeof(struct arpt_entry) &&
 			     (strcmp(t->target.u.user.name,
-				     ARPT_STANDARD_TARGET) == 0) &&
+				     XT_STANDARD_TARGET) == 0) &&
 			     t->verdict < 0 && unconditional(&e->arp)) ||
 			    visited) {
 				unsigned int oldpos, size;
 
 				if ((strcmp(t->target.u.user.name,
-					    ARPT_STANDARD_TARGET) == 0) &&
+					    XT_STANDARD_TARGET) == 0) &&
 				    t->verdict < -NF_MAX_VERDICT - 1) {
 					duprintf("mark_source_chains: bad "
 						"negative verdict (%i)\n",
@@ -433,7 +433,7 @@
 				int newpos = t->verdict;
 
 				if (strcmp(t->target.u.user.name,
-					   ARPT_STANDARD_TARGET) == 0 &&
+					   XT_STANDARD_TARGET) == 0 &&
 				    newpos >= 0) {
 					if (newpos > newinfo->size -
 						sizeof(struct arpt_entry)) {
@@ -464,14 +464,14 @@
 
 static inline int check_entry(const struct arpt_entry *e, const char *name)
 {
-	const struct arpt_entry_target *t;
+	const struct xt_entry_target *t;
 
 	if (!arp_checkentry(&e->arp)) {
 		duprintf("arp_tables: arp check failed %p %s.\n", e, name);
 		return -EINVAL;
 	}
 
-	if (e->target_offset + sizeof(struct arpt_entry_target) > e->next_offset)
+	if (e->target_offset + sizeof(struct xt_entry_target) > e->next_offset)
 		return -EINVAL;
 
 	t = arpt_get_target_c(e);
@@ -483,7 +483,7 @@
 
 static inline int check_target(struct arpt_entry *e, const char *name)
 {
-	struct arpt_entry_target *t = arpt_get_target(e);
+	struct xt_entry_target *t = arpt_get_target(e);
 	int ret;
 	struct xt_tgchk_param par = {
 		.table     = name,
@@ -506,7 +506,7 @@
 static inline int
 find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
 {
-	struct arpt_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_target *target;
 	int ret;
 
@@ -536,7 +536,7 @@
 
 static bool check_underflow(const struct arpt_entry *e)
 {
-	const struct arpt_entry_target *t;
+	const struct xt_entry_target *t;
 	unsigned int verdict;
 
 	if (!unconditional(&e->arp))
@@ -544,7 +544,7 @@
 	t = arpt_get_target_c(e);
 	if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
 		return false;
-	verdict = ((struct arpt_standard_target *)t)->verdict;
+	verdict = ((struct xt_standard_target *)t)->verdict;
 	verdict = -verdict - 1;
 	return verdict == NF_DROP || verdict == NF_ACCEPT;
 }
@@ -566,7 +566,7 @@
 	}
 
 	if (e->next_offset
-	    < sizeof(struct arpt_entry) + sizeof(struct arpt_entry_target)) {
+	    < sizeof(struct arpt_entry) + sizeof(struct xt_entry_target)) {
 		duprintf("checking: element %p size %u\n",
 			 e, e->next_offset);
 		return -EINVAL;
@@ -598,7 +598,7 @@
 static inline void cleanup_entry(struct arpt_entry *e)
 {
 	struct xt_tgdtor_param par;
-	struct arpt_entry_target *t;
+	struct xt_entry_target *t;
 
 	t = arpt_get_target(e);
 	par.target   = t->u.kernel.target;
@@ -794,7 +794,7 @@
 	/* FIXME: use iterator macros --RR */
 	/* ... then go back and fix counters and names */
 	for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
-		const struct arpt_entry_target *t;
+		const struct xt_entry_target *t;
 
 		e = (struct arpt_entry *)(loc_cpu_entry + off);
 		if (copy_to_user(userptr + off
@@ -807,7 +807,7 @@
 
 		t = arpt_get_target_c(e);
 		if (copy_to_user(userptr + off + e->target_offset
-				 + offsetof(struct arpt_entry_target,
+				 + offsetof(struct xt_entry_target,
 					    u.user.name),
 				 t->u.kernel.target->name,
 				 strlen(t->u.kernel.target->name)+1) != 0) {
@@ -844,7 +844,7 @@
 			     const struct xt_table_info *info,
 			     const void *base, struct xt_table_info *newinfo)
 {
-	const struct arpt_entry_target *t;
+	const struct xt_entry_target *t;
 	unsigned int entry_offset;
 	int off, i, ret;
 
@@ -895,7 +895,7 @@
 static int get_info(struct net *net, void __user *user,
                     const int *len, int compat)
 {
-	char name[ARPT_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 	struct xt_table *t;
 	int ret;
 
@@ -908,7 +908,7 @@
 	if (copy_from_user(name, user, sizeof(name)) != 0)
 		return -EFAULT;
 
-	name[ARPT_TABLE_MAXNAMELEN-1] = '\0';
+	name[XT_TABLE_MAXNAMELEN-1] = '\0';
 #ifdef CONFIG_COMPAT
 	if (compat)
 		xt_compat_lock(NFPROTO_ARP);
@@ -1204,7 +1204,7 @@
 #ifdef CONFIG_COMPAT
 static inline void compat_release_entry(struct compat_arpt_entry *e)
 {
-	struct arpt_entry_target *t;
+	struct xt_entry_target *t;
 
 	t = compat_arpt_get_target(e);
 	module_put(t->u.kernel.target->me);
@@ -1220,7 +1220,7 @@
 				  const unsigned int *underflows,
 				  const char *name)
 {
-	struct arpt_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_target *target;
 	unsigned int entry_offset;
 	int ret, off, h;
@@ -1288,7 +1288,7 @@
 			    unsigned int *size, const char *name,
 			    struct xt_table_info *newinfo, unsigned char *base)
 {
-	struct arpt_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_target *target;
 	struct arpt_entry *de;
 	unsigned int origsize;
@@ -1474,7 +1474,7 @@
 }
 
 struct compat_arpt_replace {
-	char				name[ARPT_TABLE_MAXNAMELEN];
+	char				name[XT_TABLE_MAXNAMELEN];
 	u32				valid_hooks;
 	u32				num_entries;
 	u32				size;
@@ -1567,7 +1567,7 @@
 				     struct xt_counters *counters,
 				     unsigned int i)
 {
-	struct arpt_entry_target *t;
+	struct xt_entry_target *t;
 	struct compat_arpt_entry __user *ce;
 	u_int16_t target_offset, next_offset;
 	compat_uint_t origsize;
@@ -1628,7 +1628,7 @@
 }
 
 struct compat_arpt_get_entries {
-	char name[ARPT_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 	compat_uint_t size;
 	struct compat_arpt_entry entrytable[0];
 };
@@ -1828,7 +1828,7 @@
 /* The built-in targets: standard (NULL) and error. */
 static struct xt_target arpt_builtin_tg[] __read_mostly = {
 	{
-		.name             = ARPT_STANDARD_TARGET,
+		.name             = XT_STANDARD_TARGET,
 		.targetsize       = sizeof(int),
 		.family           = NFPROTO_ARP,
 #ifdef CONFIG_COMPAT
@@ -1838,9 +1838,9 @@
 #endif
 	},
 	{
-		.name             = ARPT_ERROR_TARGET,
+		.name             = XT_ERROR_TARGET,
 		.target           = arpt_error,
-		.targetsize       = ARPT_FUNCTION_MAXNAMELEN,
+		.targetsize       = XT_FUNCTION_MAXNAMELEN,
 		.family           = NFPROTO_ARP,
 	},
 };
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index e1be7dd..b8ddcc4 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -63,7 +63,7 @@
 		return false;
 
 	if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT &&
-	   mangle->target != ARPT_CONTINUE)
+	   mangle->target != XT_CONTINUE)
 		return false;
 	return true;
 }
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index d163f2e..d31b007 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -186,7 +186,7 @@
 }
 
 /* for const-correctness */
-static inline const struct ipt_entry_target *
+static inline const struct xt_entry_target *
 ipt_get_target_c(const struct ipt_entry *e)
 {
 	return ipt_get_target((struct ipt_entry *)e);
@@ -230,9 +230,9 @@
 		      const char *hookname, const char **chainname,
 		      const char **comment, unsigned int *rulenum)
 {
-	const struct ipt_standard_target *t = (void *)ipt_get_target_c(s);
+	const struct xt_standard_target *t = (void *)ipt_get_target_c(s);
 
-	if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
+	if (strcmp(t->target.u.kernel.target->name, XT_ERROR_TARGET) == 0) {
 		/* Head of user chain: ERROR target with chainname */
 		*chainname = t->target.data;
 		(*rulenum) = 0;
@@ -241,7 +241,7 @@
 
 		if (s->target_offset == sizeof(struct ipt_entry) &&
 		    strcmp(t->target.u.kernel.target->name,
-			   IPT_STANDARD_TARGET) == 0 &&
+			   XT_STANDARD_TARGET) == 0 &&
 		   t->verdict < 0 &&
 		   unconditional(&s->ip)) {
 			/* Tail of chains: STANDARD target (return/policy) */
@@ -346,7 +346,7 @@
 		 get_entry(table_base, private->underflow[hook]));
 
 	do {
-		const struct ipt_entry_target *t;
+		const struct xt_entry_target *t;
 		const struct xt_entry_match *ematch;
 
 		IP_NF_ASSERT(e);
@@ -380,10 +380,10 @@
 		if (!t->u.kernel.target->target) {
 			int v;
 
-			v = ((struct ipt_standard_target *)t)->verdict;
+			v = ((struct xt_standard_target *)t)->verdict;
 			if (v < 0) {
 				/* Pop from stack? */
-				if (v != IPT_RETURN) {
+				if (v != XT_RETURN) {
 					verdict = (unsigned)(-v) - 1;
 					break;
 				}
@@ -421,7 +421,7 @@
 		verdict = t->u.kernel.target->target(skb, &acpar);
 		/* Target might have changed stuff. */
 		ip = ip_hdr(skb);
-		if (verdict == IPT_CONTINUE)
+		if (verdict == XT_CONTINUE)
 			e = ipt_next_entry(e);
 		else
 			/* Verdict */
@@ -461,7 +461,7 @@
 		e->counters.pcnt = pos;
 
 		for (;;) {
-			const struct ipt_standard_target *t
+			const struct xt_standard_target *t
 				= (void *)ipt_get_target_c(e);
 			int visited = e->comefrom & (1 << hook);
 
@@ -475,13 +475,13 @@
 			/* Unconditional return/END. */
 			if ((e->target_offset == sizeof(struct ipt_entry) &&
 			     (strcmp(t->target.u.user.name,
-				     IPT_STANDARD_TARGET) == 0) &&
+				     XT_STANDARD_TARGET) == 0) &&
 			     t->verdict < 0 && unconditional(&e->ip)) ||
 			    visited) {
 				unsigned int oldpos, size;
 
 				if ((strcmp(t->target.u.user.name,
-			    		    IPT_STANDARD_TARGET) == 0) &&
+			    		    XT_STANDARD_TARGET) == 0) &&
 				    t->verdict < -NF_MAX_VERDICT - 1) {
 					duprintf("mark_source_chains: bad "
 						"negative verdict (%i)\n",
@@ -524,7 +524,7 @@
 				int newpos = t->verdict;
 
 				if (strcmp(t->target.u.user.name,
-					   IPT_STANDARD_TARGET) == 0 &&
+					   XT_STANDARD_TARGET) == 0 &&
 				    newpos >= 0) {
 					if (newpos > newinfo->size -
 						sizeof(struct ipt_entry)) {
@@ -552,7 +552,7 @@
 	return 1;
 }
 
-static void cleanup_match(struct ipt_entry_match *m, struct net *net)
+static void cleanup_match(struct xt_entry_match *m, struct net *net)
 {
 	struct xt_mtdtor_param par;
 
@@ -568,14 +568,14 @@
 static int
 check_entry(const struct ipt_entry *e, const char *name)
 {
-	const struct ipt_entry_target *t;
+	const struct xt_entry_target *t;
 
 	if (!ip_checkentry(&e->ip)) {
 		duprintf("ip check failed %p %s.\n", e, par->match->name);
 		return -EINVAL;
 	}
 
-	if (e->target_offset + sizeof(struct ipt_entry_target) >
+	if (e->target_offset + sizeof(struct xt_entry_target) >
 	    e->next_offset)
 		return -EINVAL;
 
@@ -587,7 +587,7 @@
 }
 
 static int
-check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
+check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
 {
 	const struct ipt_ip *ip = par->entryinfo;
 	int ret;
@@ -605,7 +605,7 @@
 }
 
 static int
-find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
+find_check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
 {
 	struct xt_match *match;
 	int ret;
@@ -630,7 +630,7 @@
 
 static int check_target(struct ipt_entry *e, struct net *net, const char *name)
 {
-	struct ipt_entry_target *t = ipt_get_target(e);
+	struct xt_entry_target *t = ipt_get_target(e);
 	struct xt_tgchk_param par = {
 		.net       = net,
 		.table     = name,
@@ -656,7 +656,7 @@
 find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
 		 unsigned int size)
 {
-	struct ipt_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_target *target;
 	int ret;
 	unsigned int j;
@@ -707,7 +707,7 @@
 
 static bool check_underflow(const struct ipt_entry *e)
 {
-	const struct ipt_entry_target *t;
+	const struct xt_entry_target *t;
 	unsigned int verdict;
 
 	if (!unconditional(&e->ip))
@@ -715,7 +715,7 @@
 	t = ipt_get_target_c(e);
 	if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
 		return false;
-	verdict = ((struct ipt_standard_target *)t)->verdict;
+	verdict = ((struct xt_standard_target *)t)->verdict;
 	verdict = -verdict - 1;
 	return verdict == NF_DROP || verdict == NF_ACCEPT;
 }
@@ -738,7 +738,7 @@
 	}
 
 	if (e->next_offset
-	    < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
+	    < sizeof(struct ipt_entry) + sizeof(struct xt_entry_target)) {
 		duprintf("checking: element %p size %u\n",
 			 e, e->next_offset);
 		return -EINVAL;
@@ -771,7 +771,7 @@
 cleanup_entry(struct ipt_entry *e, struct net *net)
 {
 	struct xt_tgdtor_param par;
-	struct ipt_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_entry_match *ematch;
 
 	/* Cleanup all matches */
@@ -972,8 +972,8 @@
 	/* ... then go back and fix counters and names */
 	for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
 		unsigned int i;
-		const struct ipt_entry_match *m;
-		const struct ipt_entry_target *t;
+		const struct xt_entry_match *m;
+		const struct xt_entry_target *t;
 
 		e = (struct ipt_entry *)(loc_cpu_entry + off);
 		if (copy_to_user(userptr + off
@@ -990,7 +990,7 @@
 			m = (void *)e + i;
 
 			if (copy_to_user(userptr + off + i
-					 + offsetof(struct ipt_entry_match,
+					 + offsetof(struct xt_entry_match,
 						    u.user.name),
 					 m->u.kernel.match->name,
 					 strlen(m->u.kernel.match->name)+1)
@@ -1002,7 +1002,7 @@
 
 		t = ipt_get_target_c(e);
 		if (copy_to_user(userptr + off + e->target_offset
-				 + offsetof(struct ipt_entry_target,
+				 + offsetof(struct xt_entry_target,
 					    u.user.name),
 				 t->u.kernel.target->name,
 				 strlen(t->u.kernel.target->name)+1) != 0) {
@@ -1040,7 +1040,7 @@
 			     const void *base, struct xt_table_info *newinfo)
 {
 	const struct xt_entry_match *ematch;
-	const struct ipt_entry_target *t;
+	const struct xt_entry_target *t;
 	unsigned int entry_offset;
 	int off, i, ret;
 
@@ -1092,7 +1092,7 @@
 static int get_info(struct net *net, void __user *user,
                     const int *len, int compat)
 {
-	char name[IPT_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 	struct xt_table *t;
 	int ret;
 
@@ -1105,7 +1105,7 @@
 	if (copy_from_user(name, user, sizeof(name)) != 0)
 		return -EFAULT;
 
-	name[IPT_TABLE_MAXNAMELEN-1] = '\0';
+	name[XT_TABLE_MAXNAMELEN-1] = '\0';
 #ifdef CONFIG_COMPAT
 	if (compat)
 		xt_compat_lock(AF_INET);
@@ -1400,14 +1400,14 @@
 
 #ifdef CONFIG_COMPAT
 struct compat_ipt_replace {
-	char			name[IPT_TABLE_MAXNAMELEN];
+	char			name[XT_TABLE_MAXNAMELEN];
 	u32			valid_hooks;
 	u32			num_entries;
 	u32			size;
 	u32			hook_entry[NF_INET_NUMHOOKS];
 	u32			underflow[NF_INET_NUMHOOKS];
 	u32			num_counters;
-	compat_uptr_t		counters;	/* struct ipt_counters * */
+	compat_uptr_t		counters;	/* struct xt_counters * */
 	struct compat_ipt_entry	entries[0];
 };
 
@@ -1416,7 +1416,7 @@
 			  unsigned int *size, struct xt_counters *counters,
 			  unsigned int i)
 {
-	struct ipt_entry_target *t;
+	struct xt_entry_target *t;
 	struct compat_ipt_entry __user *ce;
 	u_int16_t target_offset, next_offset;
 	compat_uint_t origsize;
@@ -1451,7 +1451,7 @@
 }
 
 static int
-compat_find_calc_match(struct ipt_entry_match *m,
+compat_find_calc_match(struct xt_entry_match *m,
 		       const char *name,
 		       const struct ipt_ip *ip,
 		       unsigned int hookmask,
@@ -1473,7 +1473,7 @@
 
 static void compat_release_entry(struct compat_ipt_entry *e)
 {
-	struct ipt_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_entry_match *ematch;
 
 	/* Cleanup all matches */
@@ -1494,7 +1494,7 @@
 				  const char *name)
 {
 	struct xt_entry_match *ematch;
-	struct ipt_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_target *target;
 	unsigned int entry_offset;
 	unsigned int j;
@@ -1576,7 +1576,7 @@
 			    unsigned int *size, const char *name,
 			    struct xt_table_info *newinfo, unsigned char *base)
 {
-	struct ipt_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_target *target;
 	struct ipt_entry *de;
 	unsigned int origsize;
@@ -1884,7 +1884,7 @@
 }
 
 struct compat_ipt_get_entries {
-	char name[IPT_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 	compat_uint_t size;
 	struct compat_ipt_entry entrytable[0];
 };
@@ -2039,7 +2039,7 @@
 
 	case IPT_SO_GET_REVISION_MATCH:
 	case IPT_SO_GET_REVISION_TARGET: {
-		struct ipt_get_revision rev;
+		struct xt_get_revision rev;
 		int target;
 
 		if (*len != sizeof(rev)) {
@@ -2176,7 +2176,7 @@
 
 static struct xt_target ipt_builtin_tg[] __read_mostly = {
 	{
-		.name             = IPT_STANDARD_TARGET,
+		.name             = XT_STANDARD_TARGET,
 		.targetsize       = sizeof(int),
 		.family           = NFPROTO_IPV4,
 #ifdef CONFIG_COMPAT
@@ -2186,9 +2186,9 @@
 #endif
 	},
 	{
-		.name             = IPT_ERROR_TARGET,
+		.name             = XT_ERROR_TARGET,
 		.target           = ipt_error,
-		.targetsize       = IPT_FUNCTION_MAXNAMELEN,
+		.targetsize       = XT_FUNCTION_MAXNAMELEN,
 		.family           = NFPROTO_IPV4,
 	},
 };
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 3a43cf3..1e26a48 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -29,6 +29,7 @@
 #include <net/netfilter/nf_conntrack.h>
 #include <net/net_namespace.h>
 #include <net/checksum.h>
+#include <net/ip.h>
 
 #define CLUSTERIP_VERSION "0.8"
 
@@ -231,24 +232,22 @@
 {
 	const struct iphdr *iph = ip_hdr(skb);
 	unsigned long hashval;
-	u_int16_t sport, dport;
-	const u_int16_t *ports;
+	u_int16_t sport = 0, dport = 0;
+	int poff;
 
-	switch (iph->protocol) {
-	case IPPROTO_TCP:
-	case IPPROTO_UDP:
-	case IPPROTO_UDPLITE:
-	case IPPROTO_SCTP:
-	case IPPROTO_DCCP:
-	case IPPROTO_ICMP:
-		ports = (const void *)iph+iph->ihl*4;
-		sport = ports[0];
-		dport = ports[1];
-		break;
-	default:
+	poff = proto_ports_offset(iph->protocol);
+	if (poff >= 0) {
+		const u_int16_t *ports;
+		u16 _ports[2];
+
+		ports = skb_header_pointer(skb, iph->ihl * 4 + poff, 4, _ports);
+		if (ports) {
+			sport = ports[0];
+			dport = ports[1];
+		}
+	} else {
 		if (net_ratelimit())
 			pr_info("unknown protocol %u\n", iph->protocol);
-		sport = dport = 0;
 	}
 
 	switch (config->hash_mode) {
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 915fc17..72ffc8f 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -24,16 +24,15 @@
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ipt_LOG.h>
 #include <net/netfilter/nf_log.h>
+#include <net/netfilter/xt_log.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("Xtables: IPv4 packet logging to syslog");
 
-/* Use lock to serialize, so printks don't overlap */
-static DEFINE_SPINLOCK(log_lock);
-
 /* One level of recursion won't kill us */
-static void dump_packet(const struct nf_loginfo *info,
+static void dump_packet(struct sbuff *m,
+			const struct nf_loginfo *info,
 			const struct sk_buff *skb,
 			unsigned int iphoff)
 {
@@ -48,32 +47,32 @@
 
 	ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
 	if (ih == NULL) {
-		printk("TRUNCATED");
+		sb_add(m, "TRUNCATED");
 		return;
 	}
 
 	/* Important fields:
 	 * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
 	/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
-	printk("SRC=%pI4 DST=%pI4 ",
+	sb_add(m, "SRC=%pI4 DST=%pI4 ",
 	       &ih->saddr, &ih->daddr);
 
 	/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
-	printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
+	sb_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
 	       ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
 	       ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));
 
 	/* Max length: 6 "CE DF MF " */
 	if (ntohs(ih->frag_off) & IP_CE)
-		printk("CE ");
+		sb_add(m, "CE ");
 	if (ntohs(ih->frag_off) & IP_DF)
-		printk("DF ");
+		sb_add(m, "DF ");
 	if (ntohs(ih->frag_off) & IP_MF)
-		printk("MF ");
+		sb_add(m, "MF ");
 
 	/* Max length: 11 "FRAG:65535 " */
 	if (ntohs(ih->frag_off) & IP_OFFSET)
-		printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
+		sb_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
 
 	if ((logflags & IPT_LOG_IPOPT) &&
 	    ih->ihl * 4 > sizeof(struct iphdr)) {
@@ -85,15 +84,15 @@
 		op = skb_header_pointer(skb, iphoff+sizeof(_iph),
 					optsize, _opt);
 		if (op == NULL) {
-			printk("TRUNCATED");
+			sb_add(m, "TRUNCATED");
 			return;
 		}
 
 		/* Max length: 127 "OPT (" 15*4*2chars ") " */
-		printk("OPT (");
+		sb_add(m, "OPT (");
 		for (i = 0; i < optsize; i++)
-			printk("%02X", op[i]);
-		printk(") ");
+			sb_add(m, "%02X", op[i]);
+		sb_add(m, ") ");
 	}
 
 	switch (ih->protocol) {
@@ -102,7 +101,7 @@
 		const struct tcphdr *th;
 
 		/* Max length: 10 "PROTO=TCP " */
-		printk("PROTO=TCP ");
+		sb_add(m, "PROTO=TCP ");
 
 		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
@@ -111,41 +110,41 @@
 		th = skb_header_pointer(skb, iphoff + ih->ihl * 4,
 					sizeof(_tcph), &_tcph);
 		if (th == NULL) {
-			printk("INCOMPLETE [%u bytes] ",
+			sb_add(m, "INCOMPLETE [%u bytes] ",
 			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Max length: 20 "SPT=65535 DPT=65535 " */
-		printk("SPT=%u DPT=%u ",
+		sb_add(m, "SPT=%u DPT=%u ",
 		       ntohs(th->source), ntohs(th->dest));
 		/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
 		if (logflags & IPT_LOG_TCPSEQ)
-			printk("SEQ=%u ACK=%u ",
+			sb_add(m, "SEQ=%u ACK=%u ",
 			       ntohl(th->seq), ntohl(th->ack_seq));
 		/* Max length: 13 "WINDOW=65535 " */
-		printk("WINDOW=%u ", ntohs(th->window));
+		sb_add(m, "WINDOW=%u ", ntohs(th->window));
 		/* Max length: 9 "RES=0x3F " */
-		printk("RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
+		sb_add(m, "RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
 		/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
 		if (th->cwr)
-			printk("CWR ");
+			sb_add(m, "CWR ");
 		if (th->ece)
-			printk("ECE ");
+			sb_add(m, "ECE ");
 		if (th->urg)
-			printk("URG ");
+			sb_add(m, "URG ");
 		if (th->ack)
-			printk("ACK ");
+			sb_add(m, "ACK ");
 		if (th->psh)
-			printk("PSH ");
+			sb_add(m, "PSH ");
 		if (th->rst)
-			printk("RST ");
+			sb_add(m, "RST ");
 		if (th->syn)
-			printk("SYN ");
+			sb_add(m, "SYN ");
 		if (th->fin)
-			printk("FIN ");
+			sb_add(m, "FIN ");
 		/* Max length: 11 "URGP=65535 " */
-		printk("URGP=%u ", ntohs(th->urg_ptr));
+		sb_add(m, "URGP=%u ", ntohs(th->urg_ptr));
 
 		if ((logflags & IPT_LOG_TCPOPT) &&
 		    th->doff * 4 > sizeof(struct tcphdr)) {
@@ -158,15 +157,15 @@
 						iphoff+ih->ihl*4+sizeof(_tcph),
 						optsize, _opt);
 			if (op == NULL) {
-				printk("TRUNCATED");
+				sb_add(m, "TRUNCATED");
 				return;
 			}
 
 			/* Max length: 127 "OPT (" 15*4*2chars ") " */
-			printk("OPT (");
+			sb_add(m, "OPT (");
 			for (i = 0; i < optsize; i++)
-				printk("%02X", op[i]);
-			printk(") ");
+				sb_add(m, "%02X", op[i]);
+			sb_add(m, ") ");
 		}
 		break;
 	}
@@ -177,9 +176,9 @@
 
 		if (ih->protocol == IPPROTO_UDP)
 			/* Max length: 10 "PROTO=UDP "     */
-			printk("PROTO=UDP " );
+			sb_add(m, "PROTO=UDP " );
 		else	/* Max length: 14 "PROTO=UDPLITE " */
-			printk("PROTO=UDPLITE ");
+			sb_add(m, "PROTO=UDPLITE ");
 
 		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
@@ -188,13 +187,13 @@
 		uh = skb_header_pointer(skb, iphoff+ih->ihl*4,
 					sizeof(_udph), &_udph);
 		if (uh == NULL) {
-			printk("INCOMPLETE [%u bytes] ",
+			sb_add(m, "INCOMPLETE [%u bytes] ",
 			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Max length: 20 "SPT=65535 DPT=65535 " */
-		printk("SPT=%u DPT=%u LEN=%u ",
+		sb_add(m, "SPT=%u DPT=%u LEN=%u ",
 		       ntohs(uh->source), ntohs(uh->dest),
 		       ntohs(uh->len));
 		break;
@@ -221,7 +220,7 @@
 			    [ICMP_ADDRESSREPLY] = 12 };
 
 		/* Max length: 11 "PROTO=ICMP " */
-		printk("PROTO=ICMP ");
+		sb_add(m, "PROTO=ICMP ");
 
 		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
@@ -230,19 +229,19 @@
 		ich = skb_header_pointer(skb, iphoff + ih->ihl * 4,
 					 sizeof(_icmph), &_icmph);
 		if (ich == NULL) {
-			printk("INCOMPLETE [%u bytes] ",
+			sb_add(m, "INCOMPLETE [%u bytes] ",
 			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Max length: 18 "TYPE=255 CODE=255 " */
-		printk("TYPE=%u CODE=%u ", ich->type, ich->code);
+		sb_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code);
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
 		if (ich->type <= NR_ICMP_TYPES &&
 		    required_len[ich->type] &&
 		    skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
-			printk("INCOMPLETE [%u bytes] ",
+			sb_add(m, "INCOMPLETE [%u bytes] ",
 			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
@@ -251,35 +250,35 @@
 		case ICMP_ECHOREPLY:
 		case ICMP_ECHO:
 			/* Max length: 19 "ID=65535 SEQ=65535 " */
-			printk("ID=%u SEQ=%u ",
+			sb_add(m, "ID=%u SEQ=%u ",
 			       ntohs(ich->un.echo.id),
 			       ntohs(ich->un.echo.sequence));
 			break;
 
 		case ICMP_PARAMETERPROB:
 			/* Max length: 14 "PARAMETER=255 " */
-			printk("PARAMETER=%u ",
+			sb_add(m, "PARAMETER=%u ",
 			       ntohl(ich->un.gateway) >> 24);
 			break;
 		case ICMP_REDIRECT:
 			/* Max length: 24 "GATEWAY=255.255.255.255 " */
-			printk("GATEWAY=%pI4 ", &ich->un.gateway);
+			sb_add(m, "GATEWAY=%pI4 ", &ich->un.gateway);
 			/* Fall through */
 		case ICMP_DEST_UNREACH:
 		case ICMP_SOURCE_QUENCH:
 		case ICMP_TIME_EXCEEDED:
 			/* Max length: 3+maxlen */
 			if (!iphoff) { /* Only recurse once. */
-				printk("[");
-				dump_packet(info, skb,
+				sb_add(m, "[");
+				dump_packet(m, info, skb,
 					    iphoff + ih->ihl*4+sizeof(_icmph));
-				printk("] ");
+				sb_add(m, "] ");
 			}
 
 			/* Max length: 10 "MTU=65535 " */
 			if (ich->type == ICMP_DEST_UNREACH &&
 			    ich->code == ICMP_FRAG_NEEDED)
-				printk("MTU=%u ", ntohs(ich->un.frag.mtu));
+				sb_add(m, "MTU=%u ", ntohs(ich->un.frag.mtu));
 		}
 		break;
 	}
@@ -292,19 +291,19 @@
 			break;
 
 		/* Max length: 9 "PROTO=AH " */
-		printk("PROTO=AH ");
+		sb_add(m, "PROTO=AH ");
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
 		ah = skb_header_pointer(skb, iphoff+ih->ihl*4,
 					sizeof(_ahdr), &_ahdr);
 		if (ah == NULL) {
-			printk("INCOMPLETE [%u bytes] ",
+			sb_add(m, "INCOMPLETE [%u bytes] ",
 			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Length: 15 "SPI=0xF1234567 " */
-		printk("SPI=0x%x ", ntohl(ah->spi));
+		sb_add(m, "SPI=0x%x ", ntohl(ah->spi));
 		break;
 	}
 	case IPPROTO_ESP: {
@@ -312,7 +311,7 @@
 		const struct ip_esp_hdr *eh;
 
 		/* Max length: 10 "PROTO=ESP " */
-		printk("PROTO=ESP ");
+		sb_add(m, "PROTO=ESP ");
 
 		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
@@ -321,25 +320,25 @@
 		eh = skb_header_pointer(skb, iphoff+ih->ihl*4,
 					sizeof(_esph), &_esph);
 		if (eh == NULL) {
-			printk("INCOMPLETE [%u bytes] ",
+			sb_add(m, "INCOMPLETE [%u bytes] ",
 			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Length: 15 "SPI=0xF1234567 " */
-		printk("SPI=0x%x ", ntohl(eh->spi));
+		sb_add(m, "SPI=0x%x ", ntohl(eh->spi));
 		break;
 	}
 	/* Max length: 10 "PROTO 255 " */
 	default:
-		printk("PROTO=%u ", ih->protocol);
+		sb_add(m, "PROTO=%u ", ih->protocol);
 	}
 
 	/* Max length: 15 "UID=4294967295 " */
 	if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) {
 		read_lock_bh(&skb->sk->sk_callback_lock);
 		if (skb->sk->sk_socket && skb->sk->sk_socket->file)
-			printk("UID=%u GID=%u ",
+			sb_add(m, "UID=%u GID=%u ",
 				skb->sk->sk_socket->file->f_cred->fsuid,
 				skb->sk->sk_socket->file->f_cred->fsgid);
 		read_unlock_bh(&skb->sk->sk_callback_lock);
@@ -347,7 +346,7 @@
 
 	/* Max length: 16 "MARK=0xFFFFFFFF " */
 	if (!iphoff && skb->mark)
-		printk("MARK=0x%x ", skb->mark);
+		sb_add(m, "MARK=0x%x ", skb->mark);
 
 	/* Proto    Max log string length */
 	/* IP:      40+46+6+11+127 = 230 */
@@ -364,7 +363,8 @@
 	/* maxlen = 230+   91  + 230 + 252 = 803 */
 }
 
-static void dump_mac_header(const struct nf_loginfo *info,
+static void dump_mac_header(struct sbuff *m,
+			    const struct nf_loginfo *info,
 			    const struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dev;
@@ -378,7 +378,7 @@
 
 	switch (dev->type) {
 	case ARPHRD_ETHER:
-		printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
+		sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
 		       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
 		       ntohs(eth_hdr(skb)->h_proto));
 		return;
@@ -387,17 +387,17 @@
 	}
 
 fallback:
-	printk("MAC=");
+	sb_add(m, "MAC=");
 	if (dev->hard_header_len &&
 	    skb->mac_header != skb->network_header) {
 		const unsigned char *p = skb_mac_header(skb);
 		unsigned int i;
 
-		printk("%02x", *p++);
+		sb_add(m, "%02x", *p++);
 		for (i = 1; i < dev->hard_header_len; i++, p++)
-			printk(":%02x", *p);
+			sb_add(m, ":%02x", *p);
 	}
-	printk(" ");
+	sb_add(m, " ");
 }
 
 static struct nf_loginfo default_loginfo = {
@@ -419,11 +419,12 @@
 	       const struct nf_loginfo *loginfo,
 	       const char *prefix)
 {
+	struct sbuff *m = sb_open();
+
 	if (!loginfo)
 		loginfo = &default_loginfo;
 
-	spin_lock_bh(&log_lock);
-	printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
+	sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
 	       prefix,
 	       in ? in->name : "",
 	       out ? out->name : "");
@@ -434,20 +435,20 @@
 
 		physindev = skb->nf_bridge->physindev;
 		if (physindev && in != physindev)
-			printk("PHYSIN=%s ", physindev->name);
+			sb_add(m, "PHYSIN=%s ", physindev->name);
 		physoutdev = skb->nf_bridge->physoutdev;
 		if (physoutdev && out != physoutdev)
-			printk("PHYSOUT=%s ", physoutdev->name);
+			sb_add(m, "PHYSOUT=%s ", physoutdev->name);
 	}
 #endif
 
 	/* MAC logging for input path only. */
 	if (in && !out)
-		dump_mac_header(loginfo, skb);
+		dump_mac_header(m, loginfo, skb);
 
-	dump_packet(loginfo, skb, 0);
-	printk("\n");
-	spin_unlock_bh(&log_lock);
+	dump_packet(m, loginfo, skb, 0);
+
+	sb_close(m);
 }
 
 static unsigned int
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index b254daf..43eec80 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -112,6 +112,7 @@
 	/* ip_route_me_harder expects skb->dst to be set */
 	skb_dst_set_noref(nskb, skb_dst(oldskb));
 
+	nskb->protocol = htons(ETH_P_IP);
 	if (ip_route_me_harder(nskb, addr_type))
 		goto free_nskb;
 
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 244f7cb..37f8adb 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -11,6 +11,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/percpu.h>
+#include <linux/security.h>
 #include <net/net_namespace.h>
 
 #include <linux/netfilter.h>
@@ -87,6 +88,29 @@
 	rcu_read_unlock();
 }
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
+{
+	int ret;
+	u32 len;
+	char *secctx;
+
+	ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+	if (ret)
+		return ret;
+
+	ret = seq_printf(s, "secctx=%s ", secctx);
+
+	security_release_secctx(secctx, len);
+	return ret;
+}
+#else
+static inline int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
+{
+	return 0;
+}
+#endif
+
 static int ct_seq_show(struct seq_file *s, void *v)
 {
 	struct nf_conntrack_tuple_hash *hash = v;
@@ -148,10 +172,8 @@
 		goto release;
 #endif
 
-#ifdef CONFIG_NF_CONNTRACK_SECMARK
-	if (seq_printf(s, "secmark=%u ", ct->secmark))
+	if (ct_show_secctx(s, ct))
 		goto release;
-#endif
 
 	if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
 		goto release;
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index eab8de3..f3a9b42 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -66,9 +66,11 @@
 					  const struct net_device *out,
 					  int (*okfn)(struct sk_buff *))
 {
+	struct sock *sk = skb->sk;
 	struct inet_sock *inet = inet_sk(skb->sk);
 
-	if (inet && inet->nodefrag)
+	if (sk && (sk->sk_family == PF_INET) &&
+	    inet->nodefrag)
 		return NF_ACCEPT;
 
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c
index c31b876..0f23b3f 100644
--- a/net/ipv4/netfilter/nf_nat_amanda.c
+++ b/net/ipv4/netfilter/nf_nat_amanda.c
@@ -44,9 +44,16 @@
 
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+		int ret;
+
 		exp->tuple.dst.u.tcp.port = htons(port);
-		if (nf_ct_expect_related(exp) == 0)
+		ret = nf_ct_expect_related(exp);
+		if (ret == 0)
 			break;
+		else if (ret != -EBUSY) {
+			port = 0;
+			break;
+		}
 	}
 
 	if (port == 0)
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 8c8632d..295c974 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -38,7 +38,7 @@
 static struct nf_conntrack_l3proto *l3proto __read_mostly;
 
 #define MAX_IP_NAT_PROTO 256
-static const struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO]
+static const struct nf_nat_protocol __rcu *nf_nat_protos[MAX_IP_NAT_PROTO]
 						__read_mostly;
 
 static inline const struct nf_nat_protocol *
@@ -47,7 +47,7 @@
 	return rcu_dereference(nf_nat_protos[protonum]);
 }
 
-const struct nf_nat_protocol *
+static const struct nf_nat_protocol *
 nf_nat_proto_find_get(u_int8_t protonum)
 {
 	const struct nf_nat_protocol *p;
@@ -60,14 +60,12 @@
 
 	return p;
 }
-EXPORT_SYMBOL_GPL(nf_nat_proto_find_get);
 
-void
+static void
 nf_nat_proto_put(const struct nf_nat_protocol *p)
 {
 	module_put(p->me);
 }
-EXPORT_SYMBOL_GPL(nf_nat_proto_put);
 
 /* We keep an extra hash for each conntrack, for fast searching. */
 static inline unsigned int
@@ -262,11 +260,17 @@
 	proto = __nf_nat_proto_find(orig_tuple->dst.protonum);
 
 	/* Only bother mapping if it's not already in range and unique */
-	if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM) &&
-	    (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||
-	     proto->in_range(tuple, maniptype, &range->min, &range->max)) &&
-	    !nf_nat_used_tuple(tuple, ct))
-		goto out;
+	if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {
+		if (range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+			if (proto->in_range(tuple, maniptype, &range->min,
+					    &range->max) &&
+			    (range->min.all == range->max.all ||
+			     !nf_nat_used_tuple(tuple, ct)))
+				goto out;
+		} else if (!nf_nat_used_tuple(tuple, ct)) {
+			goto out;
+		}
+	}
 
 	/* Last change: get protocol to try to obtain unique tuple. */
 	proto->unique_tuple(tuple, range, maniptype, ct);
@@ -458,6 +462,18 @@
 			return 0;
 	}
 
+	if (manip == IP_NAT_MANIP_SRC)
+		statusbit = IPS_SRC_NAT;
+	else
+		statusbit = IPS_DST_NAT;
+
+	/* Invert if this is reply dir. */
+	if (dir == IP_CT_DIR_REPLY)
+		statusbit ^= IPS_NAT_MASK;
+
+	if (!(ct->status & statusbit))
+		return 1;
+
 	pr_debug("icmp_reply_translation: translating error %p manip %u "
 		 "dir %s\n", skb, manip,
 		 dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
@@ -492,20 +508,9 @@
 
 	/* Change outer to look the reply to an incoming packet
 	 * (proto 0 means don't invert per-proto part). */
-	if (manip == IP_NAT_MANIP_SRC)
-		statusbit = IPS_SRC_NAT;
-	else
-		statusbit = IPS_DST_NAT;
-
-	/* Invert if this is reply dir. */
-	if (dir == IP_CT_DIR_REPLY)
-		statusbit ^= IPS_NAT_MASK;
-
-	if (ct->status & statusbit) {
-		nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
-		if (!manip_pkt(0, skb, 0, &target, manip))
-			return 0;
-	}
+	nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
+	if (!manip_pkt(0, skb, 0, &target, manip))
+		return 0;
 
 	return 1;
 }
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c
index 86e0e84f..dc73abb 100644
--- a/net/ipv4/netfilter/nf_nat_ftp.c
+++ b/net/ipv4/netfilter/nf_nat_ftp.c
@@ -79,9 +79,16 @@
 
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+		int ret;
+
 		exp->tuple.dst.u.tcp.port = htons(port);
-		if (nf_ct_expect_related(exp) == 0)
+		ret = nf_ct_expect_related(exp);
+		if (ret == 0)
 			break;
+		else if (ret != -EBUSY) {
+			port = 0;
+			break;
+		}
 	}
 
 	if (port == 0)
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index 5045196..790f316 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -222,13 +222,24 @@
 	/* Try to get a pair of ports. */
 	for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
 	     nated_port != 0; nated_port += 2) {
+		int ret;
+
 		rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
-		if (nf_ct_expect_related(rtp_exp) == 0) {
+		ret = nf_ct_expect_related(rtp_exp);
+		if (ret == 0) {
 			rtcp_exp->tuple.dst.u.udp.port =
 			    htons(nated_port + 1);
-			if (nf_ct_expect_related(rtcp_exp) == 0)
+			ret = nf_ct_expect_related(rtcp_exp);
+			if (ret == 0)
 				break;
-			nf_ct_unexpect_related(rtp_exp);
+			else if (ret != -EBUSY) {
+				nf_ct_unexpect_related(rtp_exp);
+				nated_port = 0;
+				break;
+			}
+		} else if (ret != -EBUSY) {
+			nated_port = 0;
+			break;
 		}
 	}
 
@@ -284,9 +295,16 @@
 
 	/* Try to get same port: if not, try to change it. */
 	for (; nated_port != 0; nated_port++) {
+		int ret;
+
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_ct_expect_related(exp) == 0)
+		ret = nf_ct_expect_related(exp);
+		if (ret == 0)
 			break;
+		else if (ret != -EBUSY) {
+			nated_port = 0;
+			break;
+		}
 	}
 
 	if (nated_port == 0) {	/* No port available */
@@ -334,9 +352,16 @@
 
 	/* Try to get same port: if not, try to change it. */
 	for (; nated_port != 0; nated_port++) {
+		int ret;
+
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_ct_expect_related(exp) == 0)
+		ret = nf_ct_expect_related(exp);
+		if (ret == 0)
 			break;
+		else if (ret != -EBUSY) {
+			nated_port = 0;
+			break;
+		}
 	}
 
 	if (nated_port == 0) {	/* No port available */
@@ -418,9 +443,16 @@
 
 	/* Try to get same port: if not, try to change it. */
 	for (; nated_port != 0; nated_port++) {
+		int ret;
+
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_ct_expect_related(exp) == 0)
+		ret = nf_ct_expect_related(exp);
+		if (ret == 0)
 			break;
+		else if (ret != -EBUSY) {
+			nated_port = 0;
+			break;
+		}
 	}
 
 	if (nated_port == 0) {	/* No port available */
@@ -500,9 +532,16 @@
 
 	/* Try to get same port: if not, try to change it. */
 	for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
+		int ret;
+
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_ct_expect_related(exp) == 0)
+		ret = nf_ct_expect_related(exp);
+		if (ret == 0)
 			break;
+		else if (ret != -EBUSY) {
+			nated_port = 0;
+			break;
+		}
 	}
 
 	if (nated_port == 0) {	/* No port available */
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 4a0c6b5..31427fb 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -153,6 +153,35 @@
 }
 EXPORT_SYMBOL_GPL(nf_nat_set_seq_adjust);
 
+static void nf_nat_csum(struct sk_buff *skb, struct iphdr *iph, void *data,
+			int datalen, __sum16 *check, int oldlen)
+{
+	struct rtable *rt = skb_rtable(skb);
+
+	if (skb->ip_summed != CHECKSUM_PARTIAL) {
+		if (!(rt->rt_flags & RTCF_LOCAL) &&
+		    skb->dev->features & NETIF_F_V4_CSUM) {
+			skb->ip_summed = CHECKSUM_PARTIAL;
+			skb->csum_start = skb_headroom(skb) +
+					  skb_network_offset(skb) +
+					  iph->ihl * 4;
+			skb->csum_offset = (void *)check - data;
+			*check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+						    datalen, iph->protocol, 0);
+		} else {
+			*check = 0;
+			*check = csum_tcpudp_magic(iph->saddr, iph->daddr,
+						   datalen, iph->protocol,
+						   csum_partial(data, datalen,
+								0));
+			if (iph->protocol == IPPROTO_UDP && !*check)
+				*check = CSUM_MANGLED_0;
+		}
+	} else
+		inet_proto_csum_replace2(check, skb,
+					 htons(oldlen), htons(datalen), 1);
+}
+
 /* Generic function for mangling variable-length address changes inside
  * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
  * command in FTP).
@@ -169,7 +198,6 @@
 			       const char *rep_buffer,
 			       unsigned int rep_len, bool adjust)
 {
-	struct rtable *rt = skb_rtable(skb);
 	struct iphdr *iph;
 	struct tcphdr *tcph;
 	int oldlen, datalen;
@@ -192,26 +220,7 @@
 			match_offset, match_len, rep_buffer, rep_len);
 
 	datalen = skb->len - iph->ihl*4;
-	if (skb->ip_summed != CHECKSUM_PARTIAL) {
-		if (!(rt->rt_flags & RTCF_LOCAL) &&
-		    skb->dev->features & NETIF_F_V4_CSUM) {
-			skb->ip_summed = CHECKSUM_PARTIAL;
-			skb->csum_start = skb_headroom(skb) +
-					  skb_network_offset(skb) +
-					  iph->ihl * 4;
-			skb->csum_offset = offsetof(struct tcphdr, check);
-			tcph->check = ~tcp_v4_check(datalen,
-						    iph->saddr, iph->daddr, 0);
-		} else {
-			tcph->check = 0;
-			tcph->check = tcp_v4_check(datalen,
-						   iph->saddr, iph->daddr,
-						   csum_partial(tcph,
-								datalen, 0));
-		}
-	} else
-		inet_proto_csum_replace2(&tcph->check, skb,
-					 htons(oldlen), htons(datalen), 1);
+	nf_nat_csum(skb, iph, tcph, datalen, &tcph->check, oldlen);
 
 	if (adjust && rep_len != match_len)
 		nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq,
@@ -240,7 +249,6 @@
 			 const char *rep_buffer,
 			 unsigned int rep_len)
 {
-	struct rtable *rt = skb_rtable(skb);
 	struct iphdr *iph;
 	struct udphdr *udph;
 	int datalen, oldlen;
@@ -274,29 +282,7 @@
 	if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL)
 		return 1;
 
-	if (skb->ip_summed != CHECKSUM_PARTIAL) {
-		if (!(rt->rt_flags & RTCF_LOCAL) &&
-		    skb->dev->features & NETIF_F_V4_CSUM) {
-			skb->ip_summed = CHECKSUM_PARTIAL;
-			skb->csum_start = skb_headroom(skb) +
-					  skb_network_offset(skb) +
-					  iph->ihl * 4;
-			skb->csum_offset = offsetof(struct udphdr, check);
-			udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
-							 datalen, IPPROTO_UDP,
-							 0);
-		} else {
-			udph->check = 0;
-			udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
-							datalen, IPPROTO_UDP,
-							csum_partial(udph,
-								     datalen, 0));
-			if (!udph->check)
-				udph->check = CSUM_MANGLED_0;
-		}
-	} else
-		inet_proto_csum_replace2(&udph->check, skb,
-					 htons(oldlen), htons(datalen), 1);
+	nf_nat_csum(skb, iph, udph, datalen, &udph->check, oldlen);
 
 	return 1;
 }
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c
index ea83a88..535e1a8 100644
--- a/net/ipv4/netfilter/nf_nat_irc.c
+++ b/net/ipv4/netfilter/nf_nat_irc.c
@@ -45,9 +45,16 @@
 
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+		int ret;
+
 		exp->tuple.dst.u.tcp.port = htons(port);
-		if (nf_ct_expect_related(exp) == 0)
+		ret = nf_ct_expect_related(exp);
+		if (ret == 0)
 			break;
+		else if (ret != -EBUSY) {
+			port = 0;
+			break;
+		}
 	}
 
 	if (port == 0)
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index ebbd319..21c3042 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -106,16 +106,15 @@
 {
 	/* Force range to this IP; let proto decide mapping for
 	   per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
-	   Use reply in case it's already been mangled (eg local packet).
 	*/
-	__be32 ip
-		= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
-		   ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip
-		   : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
-	struct nf_nat_range range
-		= { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } };
+	struct nf_nat_range range;
 
-	pr_debug("Allocating NULL binding for %p (%pI4)\n", ct, &ip);
+	range.flags = 0;
+	pr_debug("Allocating NULL binding for %p (%pI4)\n", ct,
+		 HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC ?
+		 &ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip :
+		 &ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
+
 	return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
 }
 
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index 11b538d..e40cf78 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -307,9 +307,16 @@
 	exp->expectfn = ip_nat_sip_expected;
 
 	for (; port != 0; port++) {
+		int ret;
+
 		exp->tuple.dst.u.udp.port = htons(port);
-		if (nf_ct_expect_related(exp) == 0)
+		ret = nf_ct_expect_related(exp);
+		if (ret == 0)
 			break;
+		else if (ret != -EBUSY) {
+			port = 0;
+			break;
+		}
 	}
 
 	if (port == 0)
@@ -480,13 +487,25 @@
 	/* Try to get same pair of ports: if not, try to change them. */
 	for (port = ntohs(rtp_exp->tuple.dst.u.udp.port);
 	     port != 0; port += 2) {
+		int ret;
+
 		rtp_exp->tuple.dst.u.udp.port = htons(port);
-		if (nf_ct_expect_related(rtp_exp) != 0)
+		ret = nf_ct_expect_related(rtp_exp);
+		if (ret == -EBUSY)
 			continue;
-		rtcp_exp->tuple.dst.u.udp.port = htons(port + 1);
-		if (nf_ct_expect_related(rtcp_exp) == 0)
+		else if (ret < 0) {
+			port = 0;
 			break;
-		nf_ct_unexpect_related(rtp_exp);
+		}
+		rtcp_exp->tuple.dst.u.udp.port = htons(port + 1);
+		ret = nf_ct_expect_related(rtcp_exp);
+		if (ret == 0)
+			break;
+		else if (ret != -EBUSY) {
+			nf_ct_unexpect_related(rtp_exp);
+			port = 0;
+			break;
+		}
 	}
 
 	if (port == 0)
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index 1679e2c..ee5f419 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -893,13 +893,15 @@
 	unsigned char s[4];
 
 	if (offset & 1) {
-		s[0] = s[2] = 0;
+		s[0] = ~0;
 		s[1] = ~*optr;
+		s[2] = 0;
 		s[3] = *nptr;
 	} else {
-		s[1] = s[3] = 0;
 		s[0] = ~*optr;
+		s[1] = ~0;
 		s[2] = *nptr;
+		s[3] = 0;
 	}
 
 	*csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c
index f2d2973..65699c2 100644
--- a/net/ipv4/protocol.c
+++ b/net/ipv4/protocol.c
@@ -28,8 +28,7 @@
 #include <linux/spinlock.h>
 #include <net/protocol.h>
 
-const struct net_protocol *inet_protos[MAX_INET_PROTOS] ____cacheline_aligned_in_smp;
-static DEFINE_SPINLOCK(inet_proto_lock);
+const struct net_protocol *inet_protos[MAX_INET_PROTOS] __read_mostly;
 
 /*
  *	Add a protocol handler to the hash tables
@@ -37,20 +36,9 @@
 
 int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
 {
-	int hash, ret;
+	int hash = protocol & (MAX_INET_PROTOS - 1);
 
-	hash = protocol & (MAX_INET_PROTOS - 1);
-
-	spin_lock_bh(&inet_proto_lock);
-	if (inet_protos[hash]) {
-		ret = -1;
-	} else {
-		inet_protos[hash] = prot;
-		ret = 0;
-	}
-	spin_unlock_bh(&inet_proto_lock);
-
-	return ret;
+	return !cmpxchg(&inet_protos[hash], NULL, prot) ? 0 : -1;
 }
 EXPORT_SYMBOL(inet_add_protocol);
 
@@ -60,18 +48,9 @@
 
 int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol)
 {
-	int hash, ret;
+	int ret, hash = protocol & (MAX_INET_PROTOS - 1);
 
-	hash = protocol & (MAX_INET_PROTOS - 1);
-
-	spin_lock_bh(&inet_proto_lock);
-	if (inet_protos[hash] == prot) {
-		inet_protos[hash] = NULL;
-		ret = 0;
-	} else {
-		ret = -1;
-	}
-	spin_unlock_bh(&inet_proto_lock);
+	ret = (cmpxchg(&inet_protos[hash], prot, NULL) == prot) ? 0 : -1;
 
 	synchronize_net();
 
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 009a7b2..1f85ef2 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -505,7 +505,7 @@
 
 	ipc.addr = inet->inet_saddr;
 	ipc.opt = NULL;
-	ipc.shtx.flags = 0;
+	ipc.tx_flags = 0;
 	ipc.oif = sk->sk_bound_dev_if;
 
 	if (msg->msg_controllen) {
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 6298f75..d6cb2bf 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -159,7 +159,6 @@
 	.link_failure =		ipv4_link_failure,
 	.update_pmtu =		ip_rt_update_pmtu,
 	.local_out =		__ip_local_out,
-	.entries =		ATOMIC_INIT(0),
 };
 
 #define ECN_OR_COST(class)	TC_PRIO_##class
@@ -466,7 +465,7 @@
 
 	seq_printf(seq,"%08x  %08x %08x %08x %08x %08x %08x %08x "
 		   " %08x %08x %08x %08x %08x %08x %08x %08x %08x \n",
-		   atomic_read(&ipv4_dst_ops.entries),
+		   dst_entries_get_slow(&ipv4_dst_ops),
 		   st->in_hit,
 		   st->in_slow_tot,
 		   st->in_slow_mc,
@@ -945,6 +944,7 @@
 	struct rtable *rth, **rthp;
 	unsigned long now = jiffies;
 	int goal;
+	int entries = dst_entries_get_fast(&ipv4_dst_ops);
 
 	/*
 	 * Garbage collection is pretty expensive,
@@ -954,28 +954,28 @@
 	RT_CACHE_STAT_INC(gc_total);
 
 	if (now - last_gc < ip_rt_gc_min_interval &&
-	    atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size) {
+	    entries < ip_rt_max_size) {
 		RT_CACHE_STAT_INC(gc_ignored);
 		goto out;
 	}
 
+	entries = dst_entries_get_slow(&ipv4_dst_ops);
 	/* Calculate number of entries, which we want to expire now. */
-	goal = atomic_read(&ipv4_dst_ops.entries) -
-		(ip_rt_gc_elasticity << rt_hash_log);
+	goal = entries - (ip_rt_gc_elasticity << rt_hash_log);
 	if (goal <= 0) {
 		if (equilibrium < ipv4_dst_ops.gc_thresh)
 			equilibrium = ipv4_dst_ops.gc_thresh;
-		goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
+		goal = entries - equilibrium;
 		if (goal > 0) {
 			equilibrium += min_t(unsigned int, goal >> 1, rt_hash_mask + 1);
-			goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
+			goal = entries - equilibrium;
 		}
 	} else {
 		/* We are in dangerous area. Try to reduce cache really
 		 * aggressively.
 		 */
 		goal = max_t(unsigned int, goal >> 1, rt_hash_mask + 1);
-		equilibrium = atomic_read(&ipv4_dst_ops.entries) - goal;
+		equilibrium = entries - goal;
 	}
 
 	if (now - last_gc >= ip_rt_gc_min_interval)
@@ -1032,14 +1032,16 @@
 		expire >>= 1;
 #if RT_CACHE_DEBUG >= 2
 		printk(KERN_DEBUG "expire>> %u %d %d %d\n", expire,
-				atomic_read(&ipv4_dst_ops.entries), goal, i);
+				dst_entries_get_fast(&ipv4_dst_ops), goal, i);
 #endif
 
-		if (atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
+		if (dst_entries_get_fast(&ipv4_dst_ops) < ip_rt_max_size)
 			goto out;
 	} while (!in_softirq() && time_before_eq(jiffies, now));
 
-	if (atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
+	if (dst_entries_get_fast(&ipv4_dst_ops) < ip_rt_max_size)
+		goto out;
+	if (dst_entries_get_slow(&ipv4_dst_ops) < ip_rt_max_size)
 		goto out;
 	if (net_ratelimit())
 		printk(KERN_WARNING "dst cache overflow\n");
@@ -1049,11 +1051,12 @@
 work_done:
 	expire += ip_rt_gc_min_interval;
 	if (expire > ip_rt_gc_timeout ||
-	    atomic_read(&ipv4_dst_ops.entries) < ipv4_dst_ops.gc_thresh)
+	    dst_entries_get_fast(&ipv4_dst_ops) < ipv4_dst_ops.gc_thresh ||
+	    dst_entries_get_slow(&ipv4_dst_ops) < ipv4_dst_ops.gc_thresh)
 		expire = ip_rt_gc_timeout;
 #if RT_CACHE_DEBUG >= 2
 	printk(KERN_DEBUG "expire++ %u %d %d %d\n", expire,
-			atomic_read(&ipv4_dst_ops.entries), goal, rover);
+			dst_entries_get_fast(&ipv4_dst_ops), goal, rover);
 #endif
 out:	return 0;
 }
@@ -1102,23 +1105,23 @@
 		 * Note that we do rt_free on this new route entry, so that
 		 * once its refcount hits zero, we are still able to reap it
 		 * (Thanks Alexey)
-		 * Note also the rt_free uses call_rcu.  We don't actually
-		 * need rcu protection here, this is just our path to get
-		 * on the route gc list.
+		 * Note: To avoid expensive rcu stuff for this uncached dst,
+		 * we set DST_NOCACHE so that dst_release() can free dst without
+		 * waiting a grace period.
 		 */
 
+		rt->dst.flags |= DST_NOCACHE;
 		if (rt->rt_type == RTN_UNICAST || rt->fl.iif == 0) {
 			int err = arp_bind_neighbour(&rt->dst);
 			if (err) {
 				if (net_ratelimit())
 					printk(KERN_WARNING
 					    "Neighbour table failure & not caching routes.\n");
-				rt_drop(rt);
+				ip_rt_put(rt);
 				return err;
 			}
 		}
 
-		rt_free(rt);
 		goto skip_hashing;
 	}
 
@@ -1231,7 +1234,7 @@
 			}
 
 			if (net_ratelimit())
-				printk(KERN_WARNING "Neighbour table overflow.\n");
+				printk(KERN_WARNING "ipv4: Neighbour table overflow.\n");
 			rt_drop(rt);
 			return -ENOBUFS;
 		}
@@ -1268,18 +1271,11 @@
 
 void rt_bind_peer(struct rtable *rt, int create)
 {
-	static DEFINE_SPINLOCK(rt_peer_lock);
 	struct inet_peer *peer;
 
 	peer = inet_getpeer(rt->rt_dst, create);
 
-	spin_lock_bh(&rt_peer_lock);
-	if (rt->peer == NULL) {
-		rt->peer = peer;
-		peer = NULL;
-	}
-	spin_unlock_bh(&rt_peer_lock);
-	if (peer)
+	if (peer && cmpxchg(&rt->peer, NULL, peer) != NULL)
 		inet_putpeer(peer);
 }
 
@@ -1779,12 +1775,15 @@
 
 	if (rt->fl.iif == 0)
 		src = rt->rt_src;
-	else if (fib_lookup(dev_net(rt->dst.dev), &rt->fl, &res) == 0) {
-		src = FIB_RES_PREFSRC(res);
-		fib_res_put(&res);
-	} else
-		src = inet_select_addr(rt->dst.dev, rt->rt_gateway,
+	else {
+		rcu_read_lock();
+		if (fib_lookup(dev_net(rt->dst.dev), &rt->fl, &res) == 0)
+			src = FIB_RES_PREFSRC(res);
+		else
+			src = inet_select_addr(rt->dst.dev, rt->rt_gateway,
 					RT_SCOPE_UNIVERSE);
+		rcu_read_unlock();
+	}
 	memcpy(addr, &src, 4);
 }
 
@@ -2087,6 +2086,7 @@
  *	Such approach solves two big problems:
  *	1. Not simplex devices are handled properly.
  *	2. IP spoofing attempts are filtered with 100% of guarantee.
+ *	called with rcu_read_lock()
  */
 
 static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
@@ -2108,7 +2108,6 @@
 	unsigned	hash;
 	__be32		spec_dst;
 	int		err = -EINVAL;
-	int		free_res = 0;
 	struct net    * net = dev_net(dev);
 
 	/* IP on this device is disabled. */
@@ -2124,7 +2123,7 @@
 	    ipv4_is_loopback(saddr))
 		goto martian_source;
 
-	if (daddr == htonl(0xFFFFFFFF) || (saddr == 0 && daddr == 0))
+	if (ipv4_is_lbcast(daddr) || (saddr == 0 && daddr == 0))
 		goto brd_input;
 
 	/* Accept zero addresses only to limited broadcast;
@@ -2133,19 +2132,18 @@
 	if (ipv4_is_zeronet(saddr))
 		goto martian_source;
 
-	if (ipv4_is_lbcast(daddr) || ipv4_is_zeronet(daddr) ||
-	    ipv4_is_loopback(daddr))
+	if (ipv4_is_zeronet(daddr) || ipv4_is_loopback(daddr))
 		goto martian_destination;
 
 	/*
 	 *	Now we are ready to route packet.
 	 */
-	if ((err = fib_lookup(net, &fl, &res)) != 0) {
+	err = fib_lookup(net, &fl, &res);
+	if (err != 0) {
 		if (!IN_DEV_FORWARD(in_dev))
 			goto e_hostunreach;
 		goto no_route;
 	}
-	free_res = 1;
 
 	RT_CACHE_STAT_INC(in_slow_tot);
 
@@ -2154,8 +2152,8 @@
 
 	if (res.type == RTN_LOCAL) {
 		err = fib_validate_source(saddr, daddr, tos,
-					     net->loopback_dev->ifindex,
-					     dev, &spec_dst, &itag, skb->mark);
+					  net->loopback_dev->ifindex,
+					  dev, &spec_dst, &itag, skb->mark);
 		if (err < 0)
 			goto martian_source_keep_err;
 		if (err)
@@ -2170,9 +2168,6 @@
 		goto martian_destination;
 
 	err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);
-done:
-	if (free_res)
-		fib_res_put(&res);
 out:	return err;
 
 brd_input:
@@ -2232,7 +2227,7 @@
 	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);
-	goto done;
+	goto out;
 
 no_route:
 	RT_CACHE_STAT_INC(in_no_route);
@@ -2255,21 +2250,21 @@
 
 e_hostunreach:
 	err = -EHOSTUNREACH;
-	goto done;
+	goto out;
 
 e_inval:
 	err = -EINVAL;
-	goto done;
+	goto out;
 
 e_nobufs:
 	err = -ENOBUFS;
-	goto done;
+	goto out;
 
 martian_source:
 	err = -EINVAL;
 martian_source_keep_err:
 	ip_handle_martian_source(dev, in_dev, skb, daddr, saddr);
-	goto done;
+	goto out;
 }
 
 int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,
@@ -2355,6 +2350,7 @@
 }
 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,
@@ -2365,53 +2361,47 @@
 	struct rtable *rth;
 	struct in_device *in_dev;
 	u32 tos = RT_FL_TOS(oldflp);
-	int err = 0;
 
-	if (ipv4_is_loopback(fl->fl4_src) && !(dev_out->flags&IFF_LOOPBACK))
+	if (ipv4_is_loopback(fl->fl4_src) && !(dev_out->flags & IFF_LOOPBACK))
 		return -EINVAL;
 
-	if (fl->fl4_dst == htonl(0xFFFFFFFF))
+	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_lbcast(fl->fl4_dst) || ipv4_is_zeronet(fl->fl4_dst))
+	else if (ipv4_is_zeronet(fl->fl4_dst))
 		return -EINVAL;
 
 	if (dev_out->flags & IFF_LOOPBACK)
 		flags |= RTCF_LOCAL;
 
-	/* get work reference to inet device */
-	in_dev = in_dev_get(dev_out);
+	in_dev = __in_dev_get_rcu(dev_out);
 	if (!in_dev)
 		return -EINVAL;
 
 	if (res->type == RTN_BROADCAST) {
 		flags |= RTCF_BROADCAST | RTCF_LOCAL;
-		if (res->fi) {
-			fib_info_put(res->fi);
-			res->fi = NULL;
-		}
+		res->fi = NULL;
 	} else if (res->type == RTN_MULTICAST) {
-		flags |= RTCF_MULTICAST|RTCF_LOCAL;
+		flags |= RTCF_MULTICAST | RTCF_LOCAL;
 		if (!ip_check_mc(in_dev, oldflp->fl4_dst, oldflp->fl4_src,
 				 oldflp->proto))
 			flags &= ~RTCF_LOCAL;
 		/* If multicast route do not exist use
-		   default one, but do not gateway in this case.
-		   Yes, it is hack.
+		 * default one, but do not gateway in this case.
+		 * Yes, it is hack.
 		 */
-		if (res->fi && res->prefixlen < 4) {
-			fib_info_put(res->fi);
+		if (res->fi && res->prefixlen < 4)
 			res->fi = NULL;
-		}
 	}
 
 
 	rth = dst_alloc(&ipv4_dst_ops);
-	if (!rth) {
-		err = -ENOBUFS;
-		goto cleanup;
-	}
+	if (!rth)
+		return -ENOBUFS;
+
+	in_dev_hold(in_dev);
+	rth->idev = in_dev;
 
 	atomic_set(&rth->dst.__refcnt, 1);
 	rth->dst.flags= DST_HOST;
@@ -2432,7 +2422,6 @@
 	   cache entry */
 	rth->dst.dev	= dev_out;
 	dev_hold(dev_out);
-	rth->idev	= in_dev_get(dev_out);
 	rth->rt_gateway = fl->fl4_dst;
 	rth->rt_spec_dst= fl->fl4_src;
 
@@ -2467,15 +2456,11 @@
 	rt_set_nexthop(rth, res, 0);
 
 	rth->rt_flags = flags;
-
 	*result = rth;
- cleanup:
-	/* release work reference to inet device */
-	in_dev_put(in_dev);
-
-	return err;
+	return 0;
 }
 
+/* called with rcu_read_lock() */
 static int ip_mkroute_output(struct rtable **rp,
 			     struct fib_result *res,
 			     const struct flowi *fl,
@@ -2497,6 +2482,7 @@
 
 /*
  * Major route resolver routine.
+ * called with rcu_read_lock();
  */
 
 static int ip_route_output_slow(struct net *net, struct rtable **rp,
@@ -2515,9 +2501,8 @@
 			    .iif = net->loopback_dev->ifindex,
 			    .oif = oldflp->oif };
 	struct fib_result res;
-	unsigned flags = 0;
+	unsigned int flags = 0;
 	struct net_device *dev_out = NULL;
-	int free_res = 0;
 	int err;
 
 
@@ -2543,9 +2528,9 @@
 
 		if (oldflp->oif == 0 &&
 		    (ipv4_is_multicast(oldflp->fl4_dst) ||
-		     oldflp->fl4_dst == htonl(0xFFFFFFFF))) {
+		     ipv4_is_lbcast(oldflp->fl4_dst))) {
 			/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
-			dev_out = ip_dev_find(net, oldflp->fl4_src);
+			dev_out = __ip_dev_find(net, oldflp->fl4_src, false);
 			if (dev_out == NULL)
 				goto out;
 
@@ -2570,29 +2555,24 @@
 
 		if (!(oldflp->flags & FLOWI_FLAG_ANYSRC)) {
 			/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
-			dev_out = ip_dev_find(net, oldflp->fl4_src);
-			if (dev_out == NULL)
+			if (!__ip_dev_find(net, oldflp->fl4_src, false))
 				goto out;
-			dev_put(dev_out);
-			dev_out = NULL;
 		}
 	}
 
 
 	if (oldflp->oif) {
-		dev_out = dev_get_by_index(net, oldflp->oif);
+		dev_out = dev_get_by_index_rcu(net, oldflp->oif);
 		err = -ENODEV;
 		if (dev_out == NULL)
 			goto out;
 
 		/* RACE: Check return value of inet_select_addr instead. */
-		if (__in_dev_get_rtnl(dev_out) == NULL) {
-			dev_put(dev_out);
+		if (rcu_dereference(dev_out->ip_ptr) == NULL)
 			goto out;	/* Wrong error code */
-		}
 
 		if (ipv4_is_local_multicast(oldflp->fl4_dst) ||
-		    oldflp->fl4_dst == htonl(0xFFFFFFFF)) {
+		    ipv4_is_lbcast(oldflp->fl4_dst)) {
 			if (!fl.fl4_src)
 				fl.fl4_src = inet_select_addr(dev_out, 0,
 							      RT_SCOPE_LINK);
@@ -2612,10 +2592,7 @@
 		fl.fl4_dst = fl.fl4_src;
 		if (!fl.fl4_dst)
 			fl.fl4_dst = fl.fl4_src = htonl(INADDR_LOOPBACK);
-		if (dev_out)
-			dev_put(dev_out);
 		dev_out = net->loopback_dev;
-		dev_hold(dev_out);
 		fl.oif = net->loopback_dev->ifindex;
 		res.type = RTN_LOCAL;
 		flags |= RTCF_LOCAL;
@@ -2649,23 +2626,15 @@
 			res.type = RTN_UNICAST;
 			goto make_route;
 		}
-		if (dev_out)
-			dev_put(dev_out);
 		err = -ENETUNREACH;
 		goto out;
 	}
-	free_res = 1;
 
 	if (res.type == RTN_LOCAL) {
 		if (!fl.fl4_src)
 			fl.fl4_src = fl.fl4_dst;
-		if (dev_out)
-			dev_put(dev_out);
 		dev_out = net->loopback_dev;
-		dev_hold(dev_out);
 		fl.oif = dev_out->ifindex;
-		if (res.fi)
-			fib_info_put(res.fi);
 		res.fi = NULL;
 		flags |= RTCF_LOCAL;
 		goto make_route;
@@ -2682,28 +2651,21 @@
 	if (!fl.fl4_src)
 		fl.fl4_src = FIB_RES_PREFSRC(res);
 
-	if (dev_out)
-		dev_put(dev_out);
 	dev_out = FIB_RES_DEV(res);
-	dev_hold(dev_out);
 	fl.oif = dev_out->ifindex;
 
 
 make_route:
 	err = ip_mkroute_output(rp, &res, &fl, oldflp, dev_out, flags);
 
-
-	if (free_res)
-		fib_res_put(&res);
-	if (dev_out)
-		dev_put(dev_out);
 out:	return err;
 }
 
 int __ip_route_output_key(struct net *net, struct rtable **rp,
 			  const struct flowi *flp)
 {
-	unsigned hash;
+	unsigned int hash;
+	int res;
 	struct rtable *rth;
 
 	if (!rt_caching(net))
@@ -2734,7 +2696,10 @@
 	rcu_read_unlock_bh();
 
 slow_output:
-	return ip_route_output_slow(net, rp, flp);
+	rcu_read_lock();
+	res = ip_route_output_slow(net, rp, flp);
+	rcu_read_unlock();
+	return res;
 }
 EXPORT_SYMBOL_GPL(__ip_route_output_key);
 
@@ -2753,7 +2718,6 @@
 	.destroy		=	ipv4_dst_destroy,
 	.check			=	ipv4_blackhole_dst_check,
 	.update_pmtu		=	ipv4_rt_blackhole_update_pmtu,
-	.entries		=	ATOMIC_INIT(0),
 };
 
 
@@ -2798,7 +2762,7 @@
 
 	dst_release(&(*rp)->dst);
 	*rp = rt;
-	return (rt ? 0 : -ENOMEM);
+	return rt ? 0 : -ENOMEM;
 }
 
 int ip_route_output_flow(struct net *net, struct rtable **rp, struct flowi *flp,
@@ -3323,6 +3287,12 @@
 
 	ipv4_dst_blackhole_ops.kmem_cachep = ipv4_dst_ops.kmem_cachep;
 
+	if (dst_entries_init(&ipv4_dst_ops) < 0)
+		panic("IP: failed to allocate ipv4_dst_ops counter\n");
+
+	if (dst_entries_init(&ipv4_dst_blackhole_ops) < 0)
+		panic("IP: failed to allocate ipv4_dst_blackhole_ops counter\n");
+
 	rt_hash_table = (struct rt_hash_bucket *)
 		alloc_large_system_hash("IP route cache",
 					sizeof(struct rt_hash_bucket),
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 3fb1428..1664a05 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -386,8 +386,6 @@
 	 */
 
 	mask = 0;
-	if (sk->sk_err)
-		mask = POLLERR;
 
 	/*
 	 * POLLHUP is certainly not done right. But poll() doesn't
@@ -457,6 +455,11 @@
 		if (tp->urg_data & TCP_URG_VALID)
 			mask |= POLLPRI;
 	}
+	/* This barrier is coupled with smp_wmb() in tcp_reset() */
+	smp_rmb();
+	if (sk->sk_err)
+		mask |= POLLERR;
+
 	return mask;
 }
 EXPORT_SYMBOL(tcp_poll);
@@ -940,7 +943,7 @@
 	sg = sk->sk_route_caps & NETIF_F_SG;
 
 	while (--iovlen >= 0) {
-		int seglen = iov->iov_len;
+		size_t seglen = iov->iov_len;
 		unsigned char __user *from = iov->iov_base;
 
 		iov++;
@@ -2389,7 +2392,12 @@
 		err = tp->af_specific->md5_parse(sk, optval, optlen);
 		break;
 #endif
-
+	case TCP_USER_TIMEOUT:
+		/* Cap the max timeout in ms TCP will retry/retrans
+		 * before giving up and aborting (ETIMEDOUT) a connection.
+		 */
+		icsk->icsk_user_timeout = msecs_to_jiffies(val);
+		break;
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -2608,6 +2616,10 @@
 	case TCP_THIN_DUPACK:
 		val = tp->thin_dupack;
 		break;
+
+	case TCP_USER_TIMEOUT:
+		val = jiffies_to_msecs(icsk->icsk_user_timeout);
+		break;
 	default:
 		return -ENOPROTOOPT;
 	}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index e663b78..ee0df48 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -182,7 +182,7 @@
 		icsk->icsk_ack.quick = min(quickacks, TCP_MAX_QUICKACKS);
 }
 
-void tcp_enter_quickack_mode(struct sock *sk)
+static void tcp_enter_quickack_mode(struct sock *sk)
 {
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	tcp_incr_quickack(sk);
@@ -805,25 +805,12 @@
 	}
 }
 
-/* Numbers are taken from RFC3390.
- *
- * John Heffner states:
- *
- *	The RFC specifies a window of no more than 4380 bytes
- *	unless 2*MSS > 4380.  Reading the pseudocode in the RFC
- *	is a bit misleading because they use a clamp at 4380 bytes
- *	rather than use a multiplier in the relevant range.
- */
 __u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst)
 {
 	__u32 cwnd = (dst ? dst_metric(dst, RTAX_INITCWND) : 0);
 
-	if (!cwnd) {
-		if (tp->mss_cache > 1460)
-			cwnd = 2;
-		else
-			cwnd = (tp->mss_cache > 1095) ? 3 : 4;
-	}
+	if (!cwnd)
+		cwnd = rfc3390_bytes_to_packets(tp->mss_cache);
 	return min_t(__u32, cwnd, tp->snd_cwnd_clamp);
 }
 
@@ -2314,7 +2301,7 @@
 
 static inline int tcp_skb_timedout(struct sock *sk, struct sk_buff *skb)
 {
-	return (tcp_time_stamp - TCP_SKB_CB(skb)->when > inet_csk(sk)->icsk_rto);
+	return tcp_time_stamp - TCP_SKB_CB(skb)->when > inet_csk(sk)->icsk_rto;
 }
 
 static inline int tcp_head_timedout(struct sock *sk)
@@ -2508,7 +2495,7 @@
 /* Mark head of queue up as lost. With RFC3517 SACK, the packets is
  * is against sacked "cnt", otherwise it's against facked "cnt"
  */
-static void tcp_mark_head_lost(struct sock *sk, int packets)
+static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sk_buff *skb;
@@ -2516,13 +2503,13 @@
 	int err;
 	unsigned int mss;
 
-	if (packets == 0)
-		return;
-
 	WARN_ON(packets > tp->packets_out);
 	if (tp->lost_skb_hint) {
 		skb = tp->lost_skb_hint;
 		cnt = tp->lost_cnt_hint;
+		/* Head already handled? */
+		if (mark_head && skb != tcp_write_queue_head(sk))
+			return;
 	} else {
 		skb = tcp_write_queue_head(sk);
 		cnt = 0;
@@ -2545,7 +2532,8 @@
 			cnt += tcp_skb_pcount(skb);
 
 		if (cnt > packets) {
-			if (tcp_is_sack(tp) || (oldcnt >= packets))
+			if ((tcp_is_sack(tp) && !tcp_is_fack(tp)) ||
+			    (oldcnt >= packets))
 				break;
 
 			mss = skb_shinfo(skb)->gso_size;
@@ -2556,6 +2544,9 @@
 		}
 
 		tcp_skb_mark_lost(tp, skb);
+
+		if (mark_head)
+			break;
 	}
 	tcp_verify_left_out(tp);
 }
@@ -2567,17 +2558,18 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 
 	if (tcp_is_reno(tp)) {
-		tcp_mark_head_lost(sk, 1);
+		tcp_mark_head_lost(sk, 1, 1);
 	} else if (tcp_is_fack(tp)) {
 		int lost = tp->fackets_out - tp->reordering;
 		if (lost <= 0)
 			lost = 1;
-		tcp_mark_head_lost(sk, lost);
+		tcp_mark_head_lost(sk, lost, 0);
 	} else {
 		int sacked_upto = tp->sacked_out - tp->reordering;
-		if (sacked_upto < fast_rexmit)
-			sacked_upto = fast_rexmit;
-		tcp_mark_head_lost(sk, sacked_upto);
+		if (sacked_upto >= 0)
+			tcp_mark_head_lost(sk, sacked_upto, 0);
+		else if (fast_rexmit)
+			tcp_mark_head_lost(sk, 1, 1);
 	}
 
 	tcp_timeout_skbs(sk);
@@ -2886,7 +2878,7 @@
 		       icsk->icsk_mtup.probe_size;
 	tp->snd_cwnd_cnt = 0;
 	tp->snd_cwnd_stamp = tcp_time_stamp;
-	tp->rcv_ssthresh = tcp_current_ssthresh(sk);
+	tp->snd_ssthresh = tcp_current_ssthresh(sk);
 
 	icsk->icsk_mtup.search_low = icsk->icsk_mtup.probe_size;
 	icsk->icsk_mtup.probe_size = 0;
@@ -2983,7 +2975,7 @@
 	    before(tp->snd_una, tp->high_seq) &&
 	    icsk->icsk_ca_state != TCP_CA_Open &&
 	    tp->fackets_out > tp->reordering) {
-		tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering);
+		tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering, 0);
 		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSS);
 	}
 
@@ -3411,8 +3403,8 @@
 
 static inline int tcp_ack_is_dubious(const struct sock *sk, const int flag)
 {
-	return (!(flag & FLAG_NOT_DUP) || (flag & FLAG_CA_ALERT) ||
-		inet_csk(sk)->icsk_ca_state != TCP_CA_Open);
+	return !(flag & FLAG_NOT_DUP) || (flag & FLAG_CA_ALERT) ||
+		inet_csk(sk)->icsk_ca_state != TCP_CA_Open;
 }
 
 static inline int tcp_may_raise_cwnd(const struct sock *sk, const int flag)
@@ -3429,9 +3421,9 @@
 					const u32 ack, const u32 ack_seq,
 					const u32 nwin)
 {
-	return (after(ack, tp->snd_una) ||
+	return	after(ack, tp->snd_una) ||
 		after(ack_seq, tp->snd_wl1) ||
-		(ack_seq == tp->snd_wl1 && nwin > tp->snd_wnd));
+		(ack_seq == tp->snd_wl1 && nwin > tp->snd_wnd);
 }
 
 /* Update our send window.
@@ -4048,6 +4040,8 @@
 	default:
 		sk->sk_err = ECONNRESET;
 	}
+	/* This barrier is coupled with smp_rmb() in tcp_poll() */
+	smp_wmb();
 
 	if (!sock_flag(sk, SOCK_DEAD))
 		sk->sk_error_report(sk);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 0207662..8f8527d 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1422,7 +1422,7 @@
 
 	newsk = tcp_create_openreq_child(sk, req, skb);
 	if (!newsk)
-		goto exit;
+		goto exit_nonewsk;
 
 	newsk->sk_gso_type = SKB_GSO_TCPV4;
 	sk_setup_caps(newsk, dst);
@@ -1469,16 +1469,20 @@
 	}
 #endif
 
+	if (__inet_inherit_port(sk, newsk) < 0) {
+		sock_put(newsk);
+		goto exit;
+	}
 	__inet_hash_nolisten(newsk, NULL);
-	__inet_inherit_port(sk, newsk);
 
 	return newsk;
 
 exit_overflow:
 	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
+exit_nonewsk:
+	dst_release(dst);
 exit:
 	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
-	dst_release(dst);
 	return NULL;
 }
 EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
@@ -2571,7 +2575,6 @@
 
 	return tcp_gro_receive(head, skb);
 }
-EXPORT_SYMBOL(tcp4_gro_receive);
 
 int tcp4_gro_complete(struct sk_buff *skb)
 {
@@ -2584,7 +2587,6 @@
 
 	return tcp_gro_complete(skb);
 }
-EXPORT_SYMBOL(tcp4_gro_complete);
 
 struct proto tcp_prot = {
 	.name			= "TCP",
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index f25b56c..43cf901 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -55,7 +55,7 @@
 		return 1;
 	if (after(end_seq, s_win) && before(seq, e_win))
 		return 1;
-	return (seq == e_win && seq == end_seq);
+	return seq == e_win && seq == end_seq;
 }
 
 /*
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index de3bd84..05b1ecf 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -224,16 +224,10 @@
 		}
 	}
 
-	/* Set initial window to value enough for senders,
-	 * following RFC2414. Senders, not following this RFC,
-	 * will be satisfied with 2.
-	 */
+	/* Set initial window to value enough for senders, following RFC5681. */
 	if (mss > (1 << *rcv_wscale)) {
-		int init_cwnd = 4;
-		if (mss > 1460 * 3)
-			init_cwnd = 2;
-		else if (mss > 1460)
-			init_cwnd = 3;
+		int init_cwnd = rfc3390_bytes_to_packets(mss);
+
 		/* when initializing use the value from init_rcv_wnd
 		 * rather than the default from above
 		 */
@@ -1376,9 +1370,9 @@
 				  const struct sk_buff *skb,
 				  unsigned mss_now, int nonagle)
 {
-	return (skb->len < mss_now &&
+	return skb->len < mss_now &&
 		((nonagle & TCP_NAGLE_CORK) ||
-		 (!nonagle && tp->packets_out && tcp_minshall_check(tp))));
+		 (!nonagle && tp->packets_out && tcp_minshall_check(tp)));
 }
 
 /* Return non-zero if the Nagle test allows this packet to be
@@ -1449,10 +1443,10 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sk_buff *skb = tcp_send_head(sk);
 
-	return (skb &&
+	return skb &&
 		tcp_snd_test(sk, skb, tcp_current_mss(sk),
 			     (tcp_skb_is_last(sk, skb) ?
-			      tp->nonagle : TCP_NAGLE_PUSH)));
+			      tp->nonagle : TCP_NAGLE_PUSH));
 }
 
 /* Trim TSO SKB to LEN bytes, put the remaining data into a new packet
@@ -2429,6 +2423,12 @@
 		__u8 rcv_wscale;
 		/* Set this up on the first call only */
 		req->window_clamp = tp->window_clamp ? : dst_metric(dst, RTAX_WINDOW);
+
+		/* limit the window selection if the user enforce a smaller rx buffer */
+		if (sk->sk_userlocks & SOCK_RCVBUF_LOCK &&
+		    (req->window_clamp > tcp_full_space(sk) || req->window_clamp == 0))
+			req->window_clamp = tcp_full_space(sk);
+
 		/* tcp_full_space because it is guaranteed to be the first packet */
 		tcp_select_initial_window(tcp_full_space(sk),
 			mss - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
@@ -2555,6 +2555,11 @@
 
 	tcp_initialize_rcv_mss(sk);
 
+	/* limit the window selection if the user enforce a smaller rx buffer */
+	if (sk->sk_userlocks & SOCK_RCVBUF_LOCK &&
+	    (tp->window_clamp > tcp_full_space(sk) || tp->window_clamp == 0))
+		tp->window_clamp = tcp_full_space(sk);
+
 	tcp_select_initial_window(tcp_full_space(sk),
 				  tp->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
 				  &tp->rcv_wnd,
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index f8efada..6211e21 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -214,6 +214,7 @@
 	.owner	 = THIS_MODULE,
 	.open	 = tcpprobe_open,
 	.read    = tcpprobe_read,
+	.llseek  = noop_llseek,
 };
 
 static __init int tcpprobe_init(void)
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index c35b469..74a6aa0 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -135,13 +135,16 @@
 
 /* This function calculates a "timeout" which is equivalent to the timeout of a
  * TCP connection after "boundary" unsuccessful, exponentially backed-off
- * retransmissions with an initial RTO of TCP_RTO_MIN.
+ * retransmissions with an initial RTO of TCP_RTO_MIN or TCP_TIMEOUT_INIT if
+ * syn_set flag is set.
  */
 static bool retransmits_timed_out(struct sock *sk,
-				  unsigned int boundary)
+				  unsigned int boundary,
+				  unsigned int timeout,
+				  bool syn_set)
 {
-	unsigned int timeout, linear_backoff_thresh;
-	unsigned int start_ts;
+	unsigned int linear_backoff_thresh, start_ts;
+	unsigned int rto_base = syn_set ? TCP_TIMEOUT_INIT : TCP_RTO_MIN;
 
 	if (!inet_csk(sk)->icsk_retransmits)
 		return false;
@@ -151,14 +154,15 @@
 	else
 		start_ts = tcp_sk(sk)->retrans_stamp;
 
-	linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN);
+	if (likely(timeout == 0)) {
+		linear_backoff_thresh = ilog2(TCP_RTO_MAX/rto_base);
 
-	if (boundary <= linear_backoff_thresh)
-		timeout = ((2 << boundary) - 1) * TCP_RTO_MIN;
-	else
-		timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN +
-			  (boundary - linear_backoff_thresh) * TCP_RTO_MAX;
-
+		if (boundary <= linear_backoff_thresh)
+			timeout = ((2 << boundary) - 1) * rto_base;
+		else
+			timeout = ((2 << linear_backoff_thresh) - 1) * rto_base +
+				(boundary - linear_backoff_thresh) * TCP_RTO_MAX;
+	}
 	return (tcp_time_stamp - start_ts) >= timeout;
 }
 
@@ -167,14 +171,15 @@
 {
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	int retry_until;
-	bool do_reset;
+	bool do_reset, syn_set = 0;
 
 	if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
 		if (icsk->icsk_retransmits)
 			dst_negative_advice(sk);
 		retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries;
+		syn_set = 1;
 	} else {
-		if (retransmits_timed_out(sk, sysctl_tcp_retries1)) {
+		if (retransmits_timed_out(sk, sysctl_tcp_retries1, 0, 0)) {
 			/* Black hole detection */
 			tcp_mtu_probing(icsk, sk);
 
@@ -187,14 +192,15 @@
 
 			retry_until = tcp_orphan_retries(sk, alive);
 			do_reset = alive ||
-				   !retransmits_timed_out(sk, retry_until);
+				!retransmits_timed_out(sk, retry_until, 0, 0);
 
 			if (tcp_out_of_resources(sk, do_reset))
 				return 1;
 		}
 	}
 
-	if (retransmits_timed_out(sk, retry_until)) {
+	if (retransmits_timed_out(sk, retry_until,
+				  syn_set ? 0 : icsk->icsk_user_timeout, syn_set)) {
 		/* Has it gone just too far? */
 		tcp_write_err(sk);
 		return 1;
@@ -361,18 +367,19 @@
 	if (icsk->icsk_retransmits == 0) {
 		int mib_idx;
 
-		if (icsk->icsk_ca_state == TCP_CA_Disorder) {
-			if (tcp_is_sack(tp))
-				mib_idx = LINUX_MIB_TCPSACKFAILURES;
-			else
-				mib_idx = LINUX_MIB_TCPRENOFAILURES;
-		} else if (icsk->icsk_ca_state == TCP_CA_Recovery) {
+		if (icsk->icsk_ca_state == TCP_CA_Recovery) {
 			if (tcp_is_sack(tp))
 				mib_idx = LINUX_MIB_TCPSACKRECOVERYFAIL;
 			else
 				mib_idx = LINUX_MIB_TCPRENORECOVERYFAIL;
 		} else if (icsk->icsk_ca_state == TCP_CA_Loss) {
 			mib_idx = LINUX_MIB_TCPLOSSFAILURES;
+		} else if ((icsk->icsk_ca_state == TCP_CA_Disorder) ||
+			   tp->sacked_out) {
+			if (tcp_is_sack(tp))
+				mib_idx = LINUX_MIB_TCPSACKFAILURES;
+			else
+				mib_idx = LINUX_MIB_TCPRENOFAILURES;
 		} else {
 			mib_idx = LINUX_MIB_TCPTIMEOUTS;
 		}
@@ -436,7 +443,7 @@
 		icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);
 	}
 	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX);
-	if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1))
+	if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1, 0, 0))
 		__sk_dst_reset(sk);
 
 out:;
@@ -556,7 +563,14 @@
 	elapsed = keepalive_time_elapsed(tp);
 
 	if (elapsed >= keepalive_time_when(tp)) {
-		if (icsk->icsk_probes_out >= keepalive_probes(tp)) {
+		/* If the TCP_USER_TIMEOUT option is enabled, use that
+		 * to determine when to timeout instead.
+		 */
+		if ((icsk->icsk_user_timeout != 0 &&
+		    elapsed >= icsk->icsk_user_timeout &&
+		    icsk->icsk_probes_out > 0) ||
+		    (icsk->icsk_user_timeout == 0 &&
+		    icsk->icsk_probes_out >= keepalive_probes(tp))) {
 			tcp_send_active_reset(sk, GFP_ATOMIC);
 			tcp_write_err(sk);
 			goto out;
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c
index 20151d6..a534dda 100644
--- a/net/ipv4/tcp_westwood.c
+++ b/net/ipv4/tcp_westwood.c
@@ -80,7 +80,7 @@
  */
 static inline u32 westwood_do_filter(u32 a, u32 b)
 {
-	return (((7 * a) + b) >> 3);
+	return ((7 * a) + b) >> 3;
 }
 
 static void westwood_filter(struct westwood *w, u32 delta)
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index 59186ca..9a17bd2 100644
--- a/net/ipv4/tunnel4.c
+++ b/net/ipv4/tunnel4.c
@@ -14,8 +14,8 @@
 #include <net/protocol.h>
 #include <net/xfrm.h>
 
-static struct xfrm_tunnel *tunnel4_handlers;
-static struct xfrm_tunnel *tunnel64_handlers;
+static struct xfrm_tunnel *tunnel4_handlers __read_mostly;
+static struct xfrm_tunnel *tunnel64_handlers __read_mostly;
 static DEFINE_MUTEX(tunnel4_mutex);
 
 static inline struct xfrm_tunnel **fam_handlers(unsigned short family)
@@ -39,7 +39,7 @@
 	}
 
 	handler->next = *pprev;
-	*pprev = handler;
+	rcu_assign_pointer(*pprev, handler);
 
 	ret = 0;
 
@@ -73,6 +73,11 @@
 }
 EXPORT_SYMBOL(xfrm4_tunnel_deregister);
 
+#define for_each_tunnel_rcu(head, handler)		\
+	for (handler = rcu_dereference(head);		\
+	     handler != NULL;				\
+	     handler = rcu_dereference(handler->next))	\
+	
 static int tunnel4_rcv(struct sk_buff *skb)
 {
 	struct xfrm_tunnel *handler;
@@ -80,7 +85,7 @@
 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 		goto drop;
 
-	for (handler = tunnel4_handlers; handler; handler = handler->next)
+	for_each_tunnel_rcu(tunnel4_handlers, handler)
 		if (!handler->handler(skb))
 			return 0;
 
@@ -99,7 +104,7 @@
 	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
 		goto drop;
 
-	for (handler = tunnel64_handlers; handler; handler = handler->next)
+	for_each_tunnel_rcu(tunnel64_handlers, handler)
 		if (!handler->handler(skb))
 			return 0;
 
@@ -115,7 +120,7 @@
 {
 	struct xfrm_tunnel *handler;
 
-	for (handler = tunnel4_handlers; handler; handler = handler->next)
+	for_each_tunnel_rcu(tunnel4_handlers, handler)
 		if (!handler->err_handler(skb, info))
 			break;
 }
@@ -125,7 +130,7 @@
 {
 	struct xfrm_tunnel *handler;
 
-	for (handler = tunnel64_handlers; handler; handler = handler->next)
+	for_each_tunnel_rcu(tunnel64_handlers, handler)
 		if (!handler->err_handler(skb, info))
 			break;
 }
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index fb23c2e..b3f7e8c 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -797,7 +797,7 @@
 		return -EOPNOTSUPP;
 
 	ipc.opt = NULL;
-	ipc.shtx.flags = 0;
+	ipc.tx_flags = 0;
 
 	if (up->pending) {
 		/*
@@ -845,7 +845,7 @@
 	ipc.addr = inet->inet_saddr;
 
 	ipc.oif = sk->sk_bound_dev_if;
-	err = sock_tx_timestamp(msg, sk, &ipc.shtx);
+	err = sock_tx_timestamp(sk, &ipc.tx_flags);
 	if (err)
 		return err;
 	if (msg->msg_controllen) {
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 869078d..4464f3b 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -61,7 +61,7 @@
 
 static int xfrm4_get_tos(struct flowi *fl)
 {
-	return fl->fl4_tos;
+	return IPTOS_RT_MASK & fl->fl4_tos; /* Strip ECN bits */
 }
 
 static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst,
@@ -174,7 +174,7 @@
 	struct net *net = container_of(ops, struct net, xfrm.xfrm4_dst_ops);
 
 	xfrm4_policy_afinfo.garbage_collect(net);
-	return (atomic_read(&ops->entries) > ops->gc_thresh * 2);
+	return (dst_entries_get_slow(ops) > ops->gc_thresh * 2);
 }
 
 static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu)
@@ -232,7 +232,6 @@
 	.ifdown =		xfrm4_dst_ifdown,
 	.local_out =		__ip_local_out,
 	.gc_thresh =		1024,
-	.entries =		ATOMIC_INIT(0),
 };
 
 static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
@@ -288,6 +287,7 @@
 	 * and start cleaning when were 1/2 full
 	 */
 	xfrm4_dst_ops.gc_thresh = rt_max_size/2;
+	dst_entries_init(&xfrm4_dst_ops);
 
 	xfrm4_state_init();
 	xfrm4_policy_init();
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 1ef1366..4794762 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -21,21 +21,25 @@
 }
 
 static void
-__xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
-		     struct xfrm_tmpl *tmpl,
-		     xfrm_address_t *daddr, xfrm_address_t *saddr)
+__xfrm4_init_tempsel(struct xfrm_selector *sel, struct flowi *fl)
 {
-	x->sel.daddr.a4 = fl->fl4_dst;
-	x->sel.saddr.a4 = fl->fl4_src;
-	x->sel.dport = xfrm_flowi_dport(fl);
-	x->sel.dport_mask = htons(0xffff);
-	x->sel.sport = xfrm_flowi_sport(fl);
-	x->sel.sport_mask = htons(0xffff);
-	x->sel.family = AF_INET;
-	x->sel.prefixlen_d = 32;
-	x->sel.prefixlen_s = 32;
-	x->sel.proto = fl->proto;
-	x->sel.ifindex = fl->oif;
+	sel->daddr.a4 = fl->fl4_dst;
+	sel->saddr.a4 = fl->fl4_src;
+	sel->dport = xfrm_flowi_dport(fl);
+	sel->dport_mask = htons(0xffff);
+	sel->sport = xfrm_flowi_sport(fl);
+	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;
+}
+
+static void
+xfrm4_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl,
+		   xfrm_address_t *daddr, xfrm_address_t *saddr)
+{
 	x->id = tmpl->id;
 	if (x->id.daddr.a4 == 0)
 		x->id.daddr.a4 = daddr->a4;
@@ -70,6 +74,7 @@
 	.owner			= THIS_MODULE,
 	.init_flags		= xfrm4_init_flags,
 	.init_tempsel		= __xfrm4_init_tempsel,
+	.init_temprop		= xfrm4_init_temprop,
 	.output			= xfrm4_output,
 	.extract_input		= xfrm4_extract_input,
 	.extract_output		= xfrm4_extract_output,
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 41f5982..8280645 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -58,14 +58,14 @@
 	return -ENOENT;
 }
 
-static struct xfrm_tunnel xfrm_tunnel_handler = {
+static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = {
 	.handler	=	xfrm_tunnel_rcv,
 	.err_handler	=	xfrm_tunnel_err,
 	.priority	=	2,
 };
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static struct xfrm_tunnel xfrm64_tunnel_handler = {
+static struct xfrm_tunnel xfrm64_tunnel_handler __read_mostly = {
 	.handler	=	xfrm_tunnel_rcv,
 	.err_handler	=	xfrm_tunnel_err,
 	.priority	=	2,
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index ab70a3f..ec7a91d 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -243,7 +243,7 @@
 /* Check if a route is valid prefix route */
 static inline int addrconf_is_prefix_route(const struct rt6_info *rt)
 {
-	return ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0);
+	return (rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0;
 }
 
 static void addrconf_del_timer(struct inet6_ifaddr *ifp)
@@ -1544,7 +1544,7 @@
 	return 0;
 }
 
-int __ipv6_isatap_ifid(u8 *eui, __be32 addr)
+static int __ipv6_isatap_ifid(u8 *eui, __be32 addr)
 {
 	if (addr == 0)
 		return -1;
@@ -1560,7 +1560,6 @@
 	memcpy(eui + 4, &addr, 4);
 	return 0;
 }
-EXPORT_SYMBOL(__ipv6_isatap_ifid);
 
 static int addrconf_ifid_sit(u8 *eui, struct net_device *dev)
 {
@@ -2964,7 +2963,8 @@
 	   start sending router solicitations.
 	 */
 
-	if (ifp->idev->cnf.forwarding == 0 &&
+	if ((ifp->idev->cnf.forwarding == 0 ||
+	     ifp->idev->cnf.forwarding == 2) &&
 	    ifp->idev->cnf.rtr_solicits > 0 &&
 	    (dev->flags&IFF_LOOPBACK) == 0 &&
 	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
@@ -4637,10 +4637,12 @@
 	if (err < 0) {
 		printk(KERN_CRIT "IPv6 Addrconf:"
 		       " cannot initialize default policy table: %d.\n", err);
-		return err;
+		goto out;
 	}
 
-	register_pernet_subsys(&addrconf_ops);
+	err = register_pernet_subsys(&addrconf_ops);
+	if (err < 0)
+		goto out_addrlabel;
 
 	/* The addrconf netdev notifier requires that loopback_dev
 	 * has it's ipv6 private information allocated and setup
@@ -4692,7 +4694,9 @@
 	unregister_netdevice_notifier(&ipv6_dev_notf);
 errlo:
 	unregister_pernet_subsys(&addrconf_ops);
-
+out_addrlabel:
+	ipv6_addr_label_cleanup();
+out:
 	return err;
 }
 
@@ -4703,6 +4707,7 @@
 
 	unregister_netdevice_notifier(&ipv6_dev_notf);
 	unregister_pernet_subsys(&addrconf_ops);
+	ipv6_addr_label_cleanup();
 
 	rtnl_lock();
 
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index f0e774c..c8993e5 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -393,6 +393,11 @@
 	return register_pernet_subsys(&ipv6_addr_label_ops);
 }
 
+void ipv6_addr_label_cleanup(void)
+{
+	unregister_pernet_subsys(&ipv6_addr_label_ops);
+}
+
 static const struct nla_policy ifal_policy[IFAL_MAX+1] = {
 	[IFAL_ADDRESS]		= { .len = sizeof(struct in6_addr), },
 	[IFAL_LABEL]		= { .len = sizeof(u32), },
@@ -513,10 +518,9 @@
 
 static inline int ip6addrlbl_msgsize(void)
 {
-	return (NLMSG_ALIGN(sizeof(struct ifaddrlblmsg))
+	return NLMSG_ALIGN(sizeof(struct ifaddrlblmsg))
 		+ nla_total_size(16)	/* IFAL_ADDRESS */
-		+ nla_total_size(4)	/* IFAL_LABEL */
-	);
+		+ nla_total_size(4);	/* IFAL_LABEL */
 }
 
 static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh,
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 56b9bf2..54e8e42 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -343,7 +343,8 @@
 			 */
 			v4addr = LOOPBACK4_IPV6;
 			if (!(addr_type & IPV6_ADDR_MULTICAST))	{
-				if (!ipv6_chk_addr(net, &addr->sin6_addr,
+				if (!inet->transparent &&
+				    !ipv6_chk_addr(net, &addr->sin6_addr,
 						   dev, 0)) {
 					err = -EADDRNOTAVAIL;
 					goto out_unlock;
@@ -467,7 +468,7 @@
 	if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
 		sin->sin6_scope_id = sk->sk_bound_dev_if;
 	*uaddr_len = sizeof(*sin);
-	return(0);
+	return 0;
 }
 
 EXPORT_SYMBOL(inet6_getname);
@@ -488,7 +489,7 @@
 	case SIOCADDRT:
 	case SIOCDELRT:
 
-		return(ipv6_route_ioctl(net, cmd, (void __user *)arg));
+		return ipv6_route_ioctl(net, cmd, (void __user *)arg);
 
 	case SIOCSIFADDR:
 		return addrconf_add_ifaddr(net, (void __user *) arg);
@@ -502,7 +503,7 @@
 		return sk->sk_prot->ioctl(sk, cmd, arg);
 	}
 	/*NOTREACHED*/
-	return(0);
+	return 0;
 }
 
 EXPORT_SYMBOL(inet6_ioctl);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index ef371aa..320bdb8 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -577,6 +577,25 @@
 		u8 *ptr = nh + opt->dst1;
 		put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr);
 	}
+	if (np->rxopt.bits.rxorigdstaddr) {
+		struct sockaddr_in6 sin6;
+		u16 *ports = (u16 *) skb_transport_header(skb);
+
+		if (skb_transport_offset(skb) + 4 <= skb->len) {
+			/* All current transport protocols have the port numbers in the
+			 * first four bytes of the transport header and this function is
+			 * written with this assumption in mind.
+			 */
+
+			sin6.sin6_family = AF_INET6;
+			ipv6_addr_copy(&sin6.sin6_addr, &ipv6_hdr(skb)->daddr);
+			sin6.sin6_port = ports[1];
+			sin6.sin6_flowinfo = 0;
+			sin6.sin6_scope_id = 0;
+
+			put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6);
+		}
+	}
 	return 0;
 }
 
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index e1caa5d..14ed0a9 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -13,12 +13,12 @@
 	/*
 	 * find out if nexthdr is an extension header or a protocol
 	 */
-	return ( (nexthdr == NEXTHDR_HOP)	||
+	return   (nexthdr == NEXTHDR_HOP)	||
 		 (nexthdr == NEXTHDR_ROUTING)	||
 		 (nexthdr == NEXTHDR_FRAGMENT)	||
 		 (nexthdr == NEXTHDR_AUTH)	||
 		 (nexthdr == NEXTHDR_NONE)	||
-		 (nexthdr == NEXTHDR_DEST) );
+		 (nexthdr == NEXTHDR_DEST);
 }
 
 /*
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index b1108ed..d829874 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -34,11 +34,10 @@
 {
 	struct fib_lookup_arg arg = {
 		.lookup_ptr = lookup,
+		.flags = FIB_LOOKUP_NOREF,
 	};
 
 	fib_rules_lookup(net->ipv6.fib6_rules_ops, fl, flags, &arg);
-	if (arg.rule)
-		fib_rule_put(arg.rule);
 
 	if (arg.result)
 		return arg.result;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index b6a5859..de38211 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1500,15 +1500,18 @@
 
 static int __net_init fib6_net_init(struct net *net)
 {
+	size_t size = sizeof(struct hlist_head) * FIB6_TABLE_HASHSZ;
+
 	setup_timer(&net->ipv6.ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)net);
 
 	net->ipv6.rt6_stats = kzalloc(sizeof(*net->ipv6.rt6_stats), GFP_KERNEL);
 	if (!net->ipv6.rt6_stats)
 		goto out_timer;
 
-	net->ipv6.fib_table_hash = kcalloc(FIB6_TABLE_HASHSZ,
-					   sizeof(*net->ipv6.fib_table_hash),
-					   GFP_KERNEL);
+	/* Avoid false sharing : Use at least a full cache line */
+	size = max_t(size_t, size, L1_CACHE_BYTES);
+
+	net->ipv6.fib_table_hash = kzalloc(size, GFP_KERNEL);
 	if (!net->ipv6.fib_table_hash)
 		goto out_rt6_stats;
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index d40b330..99157b4 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -637,9 +637,9 @@
 	}
 	mtu -= hlen + sizeof(struct frag_hdr);
 
-	if (skb_has_frags(skb)) {
+	if (skb_has_frag_list(skb)) {
 		int first_len = skb_pagelen(skb);
-		int truesizes = 0;
+		struct sk_buff *frag2;
 
 		if (first_len - hlen > mtu ||
 		    ((first_len - hlen) & 7) ||
@@ -651,18 +651,18 @@
 			if (frag->len > mtu ||
 			    ((frag->len & 7) && frag->next) ||
 			    skb_headroom(frag) < hlen)
-			    goto slow_path;
+				goto slow_path_clean;
 
 			/* Partially cloned skb? */
 			if (skb_shared(frag))
-				goto slow_path;
+				goto slow_path_clean;
 
 			BUG_ON(frag->sk);
 			if (skb->sk) {
 				frag->sk = skb->sk;
 				frag->destructor = sock_wfree;
-				truesizes += frag->truesize;
 			}
+			skb->truesize -= frag->truesize;
 		}
 
 		err = 0;
@@ -693,7 +693,6 @@
 
 		first_len = skb_pagelen(skb);
 		skb->data_len = first_len - skb_headlen(skb);
-		skb->truesize -= truesizes;
 		skb->len = first_len;
 		ipv6_hdr(skb)->payload_len = htons(first_len -
 						   sizeof(struct ipv6hdr));
@@ -756,6 +755,15 @@
 			      IPSTATS_MIB_FRAGFAILS);
 		dst_release(&rt->dst);
 		return err;
+
+slow_path_clean:
+		skb_walk_frags(skb, frag2) {
+			if (frag2 == frag)
+				break;
+			frag2->sk = NULL;
+			frag2->destructor = NULL;
+			skb->truesize += frag2->truesize;
+		}
 	}
 
 slow_path:
@@ -870,8 +878,8 @@
 			       struct in6_addr *fl_addr,
 			       struct in6_addr *addr_cache)
 {
-	return ((rt_key->plen != 128 || !ipv6_addr_equal(fl_addr, &rt_key->addr)) &&
-		(addr_cache == NULL || !ipv6_addr_equal(fl_addr, addr_cache)));
+	return (rt_key->plen != 128 || !ipv6_addr_equal(fl_addr, &rt_key->addr)) &&
+		(addr_cache == NULL || !ipv6_addr_equal(fl_addr, addr_cache));
 }
 
 static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 0fd027f..c2c0f89 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -75,7 +75,7 @@
 		     (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \
 		    (HASH_SIZE - 1))
 
-static void ip6_tnl_dev_init(struct net_device *dev);
+static int ip6_tnl_dev_init(struct net_device *dev);
 static void ip6_tnl_dev_setup(struct net_device *dev);
 
 static int ip6_tnl_net_id __read_mostly;
@@ -83,15 +83,42 @@
 	/* the IPv6 tunnel fallback device */
 	struct net_device *fb_tnl_dev;
 	/* lists for storing tunnels in use */
-	struct ip6_tnl *tnls_r_l[HASH_SIZE];
-	struct ip6_tnl *tnls_wc[1];
-	struct ip6_tnl **tnls[2];
+	struct ip6_tnl __rcu *tnls_r_l[HASH_SIZE];
+	struct ip6_tnl __rcu *tnls_wc[1];
+	struct ip6_tnl __rcu **tnls[2];
 };
 
+/* often modified stats are per cpu, other are shared (netdev->stats) */
+struct pcpu_tstats {
+	unsigned long	rx_packets;
+	unsigned long	rx_bytes;
+	unsigned long	tx_packets;
+	unsigned long	tx_bytes;
+};
+
+static struct net_device_stats *ip6_get_stats(struct net_device *dev)
+{
+	struct pcpu_tstats sum = { 0 };
+	int i;
+
+	for_each_possible_cpu(i) {
+		const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
+
+		sum.rx_packets += tstats->rx_packets;
+		sum.rx_bytes   += tstats->rx_bytes;
+		sum.tx_packets += tstats->tx_packets;
+		sum.tx_bytes   += tstats->tx_bytes;
+	}
+	dev->stats.rx_packets = sum.rx_packets;
+	dev->stats.rx_bytes   = sum.rx_bytes;
+	dev->stats.tx_packets = sum.tx_packets;
+	dev->stats.tx_bytes   = sum.tx_bytes;
+	return &dev->stats;
+}
+
 /*
- * Locking : hash tables are protected by RCU and a spinlock
+ * Locking : hash tables are protected by RCU and RTNL
  */
-static DEFINE_SPINLOCK(ip6_tnl_lock);
 
 static inline struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t)
 {
@@ -138,8 +165,8 @@
 static struct ip6_tnl *
 ip6_tnl_lookup(struct net *net, struct in6_addr *remote, struct in6_addr *local)
 {
-	unsigned h0 = HASH(remote);
-	unsigned h1 = HASH(local);
+	unsigned int h0 = HASH(remote);
+	unsigned int h1 = HASH(local);
 	struct ip6_tnl *t;
 	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
 
@@ -167,7 +194,7 @@
  * Return: head of IPv6 tunnel list
  **/
 
-static struct ip6_tnl **
+static struct ip6_tnl __rcu **
 ip6_tnl_bucket(struct ip6_tnl_net *ip6n, struct ip6_tnl_parm *p)
 {
 	struct in6_addr *remote = &p->raddr;
@@ -190,12 +217,10 @@
 static void
 ip6_tnl_link(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
 {
-	struct ip6_tnl **tp = ip6_tnl_bucket(ip6n, &t->parms);
+	struct ip6_tnl __rcu **tp = ip6_tnl_bucket(ip6n, &t->parms);
 
-	spin_lock_bh(&ip6_tnl_lock);
-	t->next = *tp;
+	rcu_assign_pointer(t->next , rtnl_dereference(*tp));
 	rcu_assign_pointer(*tp, t);
-	spin_unlock_bh(&ip6_tnl_lock);
 }
 
 /**
@@ -206,18 +231,25 @@
 static void
 ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
 {
-	struct ip6_tnl **tp;
+	struct ip6_tnl __rcu **tp;
+	struct ip6_tnl *iter;
 
-	for (tp = ip6_tnl_bucket(ip6n, &t->parms); *tp; tp = &(*tp)->next) {
-		if (t == *tp) {
-			spin_lock_bh(&ip6_tnl_lock);
-			*tp = t->next;
-			spin_unlock_bh(&ip6_tnl_lock);
+	for (tp = ip6_tnl_bucket(ip6n, &t->parms);
+	     (iter = rtnl_dereference(*tp)) != NULL;
+	     tp = &iter->next) {
+		if (t == iter) {
+			rcu_assign_pointer(*tp, t->next);
 			break;
 		}
 	}
 }
 
+static void ip6_dev_free(struct net_device *dev)
+{
+	free_percpu(dev->tstats);
+	free_netdev(dev);
+}
+
 /**
  * ip6_tnl_create() - create a new tunnel
  *   @p: tunnel parameters
@@ -256,7 +288,9 @@
 
 	t = netdev_priv(dev);
 	t->parms = *p;
-	ip6_tnl_dev_init(dev);
+	err = ip6_tnl_dev_init(dev);
+	if (err < 0)
+		goto failed_free;
 
 	if ((err = register_netdevice(dev)) < 0)
 		goto failed_free;
@@ -266,7 +300,7 @@
 	return t;
 
 failed_free:
-	free_netdev(dev);
+	ip6_dev_free(dev);
 failed:
 	return NULL;
 }
@@ -290,10 +324,13 @@
 {
 	struct in6_addr *remote = &p->raddr;
 	struct in6_addr *local = &p->laddr;
+	struct ip6_tnl __rcu **tp;
 	struct ip6_tnl *t;
 	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
 
-	for (t = *ip6_tnl_bucket(ip6n, p); t; t = t->next) {
+	for (tp = ip6_tnl_bucket(ip6n, p);
+	     (t = rtnl_dereference(*tp)) != NULL;
+	     tp = &t->next) {
 		if (ipv6_addr_equal(local, &t->parms.laddr) &&
 		    ipv6_addr_equal(remote, &t->parms.raddr))
 			return t;
@@ -318,13 +355,10 @@
 	struct net *net = dev_net(dev);
 	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
 
-	if (dev == ip6n->fb_tnl_dev) {
-		spin_lock_bh(&ip6_tnl_lock);
-		ip6n->tnls_wc[0] = NULL;
-		spin_unlock_bh(&ip6_tnl_lock);
-	} else {
+	if (dev == ip6n->fb_tnl_dev)
+		rcu_assign_pointer(ip6n->tnls_wc[0], NULL);
+	else
 		ip6_tnl_unlink(ip6n, t);
-	}
 	ip6_tnl_dst_reset(t);
 	dev_put(dev);
 }
@@ -702,6 +736,8 @@
 
 	if ((t = ip6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr,
 					&ipv6h->daddr)) != NULL) {
+		struct pcpu_tstats *tstats;
+
 		if (t->parms.proto != ipproto && t->parms.proto != 0) {
 			rcu_read_unlock();
 			goto discard;
@@ -724,10 +760,16 @@
 		skb->pkt_type = PACKET_HOST;
 		memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
 
-		skb_tunnel_rx(skb, t->dev);
+		tstats = this_cpu_ptr(t->dev->tstats);
+		tstats->rx_packets++;
+		tstats->rx_bytes += skb->len;
+
+		__skb_tunnel_rx(skb, t->dev);
 
 		dscp_ecn_decapsulate(t, ipv6h, skb);
+
 		netif_rx(skb);
+
 		rcu_read_unlock();
 		return 0;
 	}
@@ -934,8 +976,10 @@
 	err = ip6_local_out(skb);
 
 	if (net_xmit_eval(err) == 0) {
-		stats->tx_bytes += pkt_len;
-		stats->tx_packets++;
+		struct pcpu_tstats *tstats = this_cpu_ptr(t->dev->tstats);
+
+		tstats->tx_bytes += pkt_len;
+		tstats->tx_packets++;
 	} else {
 		stats->tx_errors++;
 		stats->tx_aborted_errors++;
@@ -1300,12 +1344,14 @@
 
 
 static const struct net_device_ops ip6_tnl_netdev_ops = {
-	.ndo_uninit = ip6_tnl_dev_uninit,
+	.ndo_uninit	= ip6_tnl_dev_uninit,
 	.ndo_start_xmit = ip6_tnl_xmit,
-	.ndo_do_ioctl = ip6_tnl_ioctl,
+	.ndo_do_ioctl	= ip6_tnl_ioctl,
 	.ndo_change_mtu = ip6_tnl_change_mtu,
+	.ndo_get_stats	= ip6_get_stats,
 };
 
+
 /**
  * ip6_tnl_dev_setup - setup virtual tunnel device
  *   @dev: virtual device associated with tunnel
@@ -1317,7 +1363,7 @@
 static void ip6_tnl_dev_setup(struct net_device *dev)
 {
 	dev->netdev_ops = &ip6_tnl_netdev_ops;
-	dev->destructor = free_netdev;
+	dev->destructor = ip6_dev_free;
 
 	dev->type = ARPHRD_TUNNEL6;
 	dev->hard_header_len = LL_MAX_HEADER + sizeof (struct ipv6hdr);
@@ -1333,12 +1379,17 @@
  *   @dev: virtual device associated with tunnel
  **/
 
-static inline void
+static inline int
 ip6_tnl_dev_init_gen(struct net_device *dev)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
+
 	t->dev = dev;
 	strcpy(t->parms.name, dev->name);
+	dev->tstats = alloc_percpu(struct pcpu_tstats);
+	if (!dev->tstats)
+		return -ENOMEM;
+	return 0;
 }
 
 /**
@@ -1346,11 +1397,15 @@
  *   @dev: virtual device associated with tunnel
  **/
 
-static void ip6_tnl_dev_init(struct net_device *dev)
+static int ip6_tnl_dev_init(struct net_device *dev)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
-	ip6_tnl_dev_init_gen(dev);
+	int err = ip6_tnl_dev_init_gen(dev);
+
+	if (err)
+		return err;
 	ip6_tnl_link_config(t);
+	return 0;
 }
 
 /**
@@ -1360,25 +1415,29 @@
  * Return: 0
  **/
 
-static void __net_init ip6_fb_tnl_dev_init(struct net_device *dev)
+static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct net *net = dev_net(dev);
 	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+	int err = ip6_tnl_dev_init_gen(dev);
 
-	ip6_tnl_dev_init_gen(dev);
+	if (err)
+		return err;
+
 	t->parms.proto = IPPROTO_IPV6;
 	dev_hold(dev);
-	ip6n->tnls_wc[0] = t;
+	rcu_assign_pointer(ip6n->tnls_wc[0], t);
+	return 0;
 }
 
-static struct xfrm6_tunnel ip4ip6_handler = {
+static struct xfrm6_tunnel ip4ip6_handler __read_mostly = {
 	.handler	= ip4ip6_rcv,
 	.err_handler	= ip4ip6_err,
 	.priority	=	1,
 };
 
-static struct xfrm6_tunnel ip6ip6_handler = {
+static struct xfrm6_tunnel ip6ip6_handler __read_mostly = {
 	.handler	= ip6ip6_rcv,
 	.err_handler	= ip6ip6_err,
 	.priority	=	1,
@@ -1391,14 +1450,14 @@
 	LIST_HEAD(list);
 
 	for (h = 0; h < HASH_SIZE; h++) {
-		t = ip6n->tnls_r_l[h];
+		t = rtnl_dereference(ip6n->tnls_r_l[h]);
 		while (t != NULL) {
 			unregister_netdevice_queue(t->dev, &list);
-			t = t->next;
+			t = rtnl_dereference(t->next);
 		}
 	}
 
-	t = ip6n->tnls_wc[0];
+	t = rtnl_dereference(ip6n->tnls_wc[0]);
 	unregister_netdevice_queue(t->dev, &list);
 	unregister_netdevice_many(&list);
 }
@@ -1419,7 +1478,9 @@
 		goto err_alloc_dev;
 	dev_net_set(ip6n->fb_tnl_dev, net);
 
-	ip6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
+	err = ip6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
+	if (err < 0)
+		goto err_register;
 
 	err = register_netdev(ip6n->fb_tnl_dev);
 	if (err < 0)
@@ -1427,7 +1488,7 @@
 	return 0;
 
 err_register:
-	free_netdev(ip6n->fb_tnl_dev);
+	ip6_dev_free(ip6n->fb_tnl_dev);
 err_alloc_dev:
 	return err;
 }
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 66078da..6f32ffc 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -667,6 +667,7 @@
 	skb_tunnel_rx(skb, reg_dev);
 
 	netif_rx(skb);
+
 	dev_put(reg_dev);
 	return 0;
  drop:
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index a7f66bc..0553867 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -342,6 +342,21 @@
 		retv = 0;
 		break;
 
+	case IPV6_TRANSPARENT:
+		if (optlen < sizeof(int))
+			goto e_inval;
+		/* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
+		inet_sk(sk)->transparent = valbool;
+		retv = 0;
+		break;
+
+	case IPV6_RECVORIGDSTADDR:
+		if (optlen < sizeof(int))
+			goto e_inval;
+		np->rxopt.bits.rxorigdstaddr = valbool;
+		retv = 0;
+		break;
+
 	case IPV6_HOPOPTS:
 	case IPV6_RTHDRDSTOPTS:
 	case IPV6_RTHDR:
@@ -1104,6 +1119,14 @@
 		break;
 	}
 
+	case IPV6_TRANSPARENT:
+		val = inet_sk(sk)->transparent;
+		break;
+
+	case IPV6_RECVORIGDSTADDR:
+		val = np->rxopt.bits.rxorigdstaddr;
+		break;
+
 	case IPV6_UNICAST_HOPS:
 	case IPV6_MULTICAST_HOPS:
 	{
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 58841c4..998d6d2 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -91,7 +91,9 @@
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv6.h>
 
-static u32 ndisc_hash(const void *pkey, const struct net_device *dev);
+static u32 ndisc_hash(const void *pkey,
+		      const struct net_device *dev,
+		      __u32 rnd);
 static int ndisc_constructor(struct neighbour *neigh);
 static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
@@ -228,12 +230,12 @@
 	do {
 		cur = ((void *)cur) + (cur->nd_opt_len << 3);
 	} while(cur < end && cur->nd_opt_type != type);
-	return (cur <= end && cur->nd_opt_type == type ? cur : NULL);
+	return cur <= end && cur->nd_opt_type == type ? cur : NULL;
 }
 
 static inline int ndisc_is_useropt(struct nd_opt_hdr *opt)
 {
-	return (opt->nd_opt_type == ND_OPT_RDNSS);
+	return opt->nd_opt_type == ND_OPT_RDNSS;
 }
 
 static struct nd_opt_hdr *ndisc_next_useropt(struct nd_opt_hdr *cur,
@@ -244,7 +246,7 @@
 	do {
 		cur = ((void *)cur) + (cur->nd_opt_len << 3);
 	} while(cur < end && !ndisc_is_useropt(cur));
-	return (cur <= end && ndisc_is_useropt(cur) ? cur : NULL);
+	return cur <= end && ndisc_is_useropt(cur) ? cur : NULL;
 }
 
 static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
@@ -319,7 +321,7 @@
 	int prepad = ndisc_addr_option_pad(dev->type);
 	if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))
 		return NULL;
-	return (lladdr + prepad);
+	return lladdr + prepad;
 }
 
 int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
@@ -350,7 +352,9 @@
 
 EXPORT_SYMBOL(ndisc_mc_map);
 
-static u32 ndisc_hash(const void *pkey, const struct net_device *dev)
+static u32 ndisc_hash(const void *pkey,
+		      const struct net_device *dev,
+		      __u32 hash_rnd)
 {
 	const u32 *p32 = pkey;
 	u32 addr_hash, i;
@@ -359,7 +363,7 @@
 	for (i = 0; i < (sizeof(struct in6_addr) / sizeof(u32)); i++)
 		addr_hash ^= *p32++;
 
-	return jhash_2words(addr_hash, dev->ifindex, nd_tbl.hash_rnd);
+	return jhash_2words(addr_hash, dev->ifindex, hash_rnd);
 }
 
 static int ndisc_constructor(struct neighbour *neigh)
@@ -1105,6 +1109,18 @@
 	rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err);
 }
 
+static inline int accept_ra(struct inet6_dev *in6_dev)
+{
+	/*
+	 * If forwarding is enabled, RA are not accepted unless the special
+	 * hybrid mode (accept_ra=2) is enabled.
+	 */
+	if (in6_dev->cnf.forwarding && in6_dev->cnf.accept_ra < 2)
+		return 0;
+
+	return in6_dev->cnf.accept_ra;
+}
+
 static void ndisc_router_discovery(struct sk_buff *skb)
 {
 	struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb);
@@ -1158,8 +1174,7 @@
 		return;
 	}
 
-	/* skip route and link configuration on routers */
-	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
+	if (!accept_ra(in6_dev))
 		goto skip_linkparms;
 
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
@@ -1309,8 +1324,7 @@
 			     NEIGH_UPDATE_F_ISROUTER);
 	}
 
-	/* skip route and link configuration on routers */
-	if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra)
+	if (!accept_ra(in6_dev))
 		goto out;
 
 #ifdef CONFIG_IPV6_ROUTE_INFO
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 29d643b..44d2eea 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -132,10 +132,10 @@
 # The targets
 config IP6_NF_TARGET_HL
 	tristate '"HL" hoplimit target support'
-	depends on NETFILTER_ADVANCED
+	depends on NETFILTER_ADVANCED && IP6_NF_MANGLE
 	select NETFILTER_XT_TARGET_HL
 	---help---
-	This is a backwards-compat option for the user's convenience
+	This is a backwards-compatible option for the user's convenience
 	(e.g. when running oldconfig). It selects
 	CONFIG_NETFILTER_XT_TARGET_HL.
 
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index aafbba3..3f8e4a3 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -11,10 +11,11 @@
 obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o
 
 # objects for l3 independent conntrack
-nf_conntrack_ipv6-objs  :=  nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
+nf_conntrack_ipv6-objs  :=  nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o
+nf_defrag_ipv6-objs := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
 
 # l3 independent conntrack
-obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o
+obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o
 
 # matches
 obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 8e754be..51df035 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -82,13 +82,13 @@
 int
 ip6t_ext_hdr(u8 nexthdr)
 {
-	return ( (nexthdr == IPPROTO_HOPOPTS)   ||
-		 (nexthdr == IPPROTO_ROUTING)   ||
-		 (nexthdr == IPPROTO_FRAGMENT)  ||
-		 (nexthdr == IPPROTO_ESP)       ||
-		 (nexthdr == IPPROTO_AH)        ||
-		 (nexthdr == IPPROTO_NONE)      ||
-		 (nexthdr == IPPROTO_DSTOPTS) );
+	return  (nexthdr == IPPROTO_HOPOPTS)   ||
+		(nexthdr == IPPROTO_ROUTING)   ||
+		(nexthdr == IPPROTO_FRAGMENT)  ||
+		(nexthdr == IPPROTO_ESP)       ||
+		(nexthdr == IPPROTO_AH)        ||
+		(nexthdr == IPPROTO_NONE)      ||
+		(nexthdr == IPPROTO_DSTOPTS);
 }
 
 /* Returns whether matches rule or not. */
@@ -215,7 +215,7 @@
 	return memcmp(ipv6, &uncond, sizeof(uncond)) == 0;
 }
 
-static inline const struct ip6t_entry_target *
+static inline const struct xt_entry_target *
 ip6t_get_target_c(const struct ip6t_entry *e)
 {
 	return ip6t_get_target((struct ip6t_entry *)e);
@@ -260,9 +260,9 @@
 		      const char *hookname, const char **chainname,
 		      const char **comment, unsigned int *rulenum)
 {
-	const struct ip6t_standard_target *t = (void *)ip6t_get_target_c(s);
+	const struct xt_standard_target *t = (void *)ip6t_get_target_c(s);
 
-	if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
+	if (strcmp(t->target.u.kernel.target->name, XT_ERROR_TARGET) == 0) {
 		/* Head of user chain: ERROR target with chainname */
 		*chainname = t->target.data;
 		(*rulenum) = 0;
@@ -271,7 +271,7 @@
 
 		if (s->target_offset == sizeof(struct ip6t_entry) &&
 		    strcmp(t->target.u.kernel.target->name,
-			   IP6T_STANDARD_TARGET) == 0 &&
+			   XT_STANDARD_TARGET) == 0 &&
 		    t->verdict < 0 &&
 		    unconditional(&s->ipv6)) {
 			/* Tail of chains: STANDARD target (return/policy) */
@@ -369,7 +369,7 @@
 	e = get_entry(table_base, private->hook_entry[hook]);
 
 	do {
-		const struct ip6t_entry_target *t;
+		const struct xt_entry_target *t;
 		const struct xt_entry_match *ematch;
 
 		IP_NF_ASSERT(e);
@@ -403,10 +403,10 @@
 		if (!t->u.kernel.target->target) {
 			int v;
 
-			v = ((struct ip6t_standard_target *)t)->verdict;
+			v = ((struct xt_standard_target *)t)->verdict;
 			if (v < 0) {
 				/* Pop from stack? */
-				if (v != IP6T_RETURN) {
+				if (v != XT_RETURN) {
 					verdict = (unsigned)(-v) - 1;
 					break;
 				}
@@ -434,7 +434,7 @@
 		acpar.targinfo = t->data;
 
 		verdict = t->u.kernel.target->target(skb, &acpar);
-		if (verdict == IP6T_CONTINUE)
+		if (verdict == XT_CONTINUE)
 			e = ip6t_next_entry(e);
 		else
 			/* Verdict */
@@ -474,7 +474,7 @@
 		e->counters.pcnt = pos;
 
 		for (;;) {
-			const struct ip6t_standard_target *t
+			const struct xt_standard_target *t
 				= (void *)ip6t_get_target_c(e);
 			int visited = e->comefrom & (1 << hook);
 
@@ -488,13 +488,13 @@
 			/* Unconditional return/END. */
 			if ((e->target_offset == sizeof(struct ip6t_entry) &&
 			     (strcmp(t->target.u.user.name,
-				     IP6T_STANDARD_TARGET) == 0) &&
+				     XT_STANDARD_TARGET) == 0) &&
 			     t->verdict < 0 &&
 			     unconditional(&e->ipv6)) || visited) {
 				unsigned int oldpos, size;
 
 				if ((strcmp(t->target.u.user.name,
-					    IP6T_STANDARD_TARGET) == 0) &&
+					    XT_STANDARD_TARGET) == 0) &&
 				    t->verdict < -NF_MAX_VERDICT - 1) {
 					duprintf("mark_source_chains: bad "
 						"negative verdict (%i)\n",
@@ -537,7 +537,7 @@
 				int newpos = t->verdict;
 
 				if (strcmp(t->target.u.user.name,
-					   IP6T_STANDARD_TARGET) == 0 &&
+					   XT_STANDARD_TARGET) == 0 &&
 				    newpos >= 0) {
 					if (newpos > newinfo->size -
 						sizeof(struct ip6t_entry)) {
@@ -565,7 +565,7 @@
 	return 1;
 }
 
-static void cleanup_match(struct ip6t_entry_match *m, struct net *net)
+static void cleanup_match(struct xt_entry_match *m, struct net *net)
 {
 	struct xt_mtdtor_param par;
 
@@ -581,14 +581,14 @@
 static int
 check_entry(const struct ip6t_entry *e, const char *name)
 {
-	const struct ip6t_entry_target *t;
+	const struct xt_entry_target *t;
 
 	if (!ip6_checkentry(&e->ipv6)) {
 		duprintf("ip_tables: ip check failed %p %s.\n", e, name);
 		return -EINVAL;
 	}
 
-	if (e->target_offset + sizeof(struct ip6t_entry_target) >
+	if (e->target_offset + sizeof(struct xt_entry_target) >
 	    e->next_offset)
 		return -EINVAL;
 
@@ -599,7 +599,7 @@
 	return 0;
 }
 
-static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
+static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
 {
 	const struct ip6t_ip6 *ipv6 = par->entryinfo;
 	int ret;
@@ -618,7 +618,7 @@
 }
 
 static int
-find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
+find_check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
 {
 	struct xt_match *match;
 	int ret;
@@ -643,7 +643,7 @@
 
 static int check_target(struct ip6t_entry *e, struct net *net, const char *name)
 {
-	struct ip6t_entry_target *t = ip6t_get_target(e);
+	struct xt_entry_target *t = ip6t_get_target(e);
 	struct xt_tgchk_param par = {
 		.net       = net,
 		.table     = name,
@@ -670,7 +670,7 @@
 find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
 		 unsigned int size)
 {
-	struct ip6t_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_target *target;
 	int ret;
 	unsigned int j;
@@ -721,7 +721,7 @@
 
 static bool check_underflow(const struct ip6t_entry *e)
 {
-	const struct ip6t_entry_target *t;
+	const struct xt_entry_target *t;
 	unsigned int verdict;
 
 	if (!unconditional(&e->ipv6))
@@ -729,7 +729,7 @@
 	t = ip6t_get_target_c(e);
 	if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
 		return false;
-	verdict = ((struct ip6t_standard_target *)t)->verdict;
+	verdict = ((struct xt_standard_target *)t)->verdict;
 	verdict = -verdict - 1;
 	return verdict == NF_DROP || verdict == NF_ACCEPT;
 }
@@ -752,7 +752,7 @@
 	}
 
 	if (e->next_offset
-	    < sizeof(struct ip6t_entry) + sizeof(struct ip6t_entry_target)) {
+	    < sizeof(struct ip6t_entry) + sizeof(struct xt_entry_target)) {
 		duprintf("checking: element %p size %u\n",
 			 e, e->next_offset);
 		return -EINVAL;
@@ -784,7 +784,7 @@
 static void cleanup_entry(struct ip6t_entry *e, struct net *net)
 {
 	struct xt_tgdtor_param par;
-	struct ip6t_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_entry_match *ematch;
 
 	/* Cleanup all matches */
@@ -985,8 +985,8 @@
 	/* ... then go back and fix counters and names */
 	for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
 		unsigned int i;
-		const struct ip6t_entry_match *m;
-		const struct ip6t_entry_target *t;
+		const struct xt_entry_match *m;
+		const struct xt_entry_target *t;
 
 		e = (struct ip6t_entry *)(loc_cpu_entry + off);
 		if (copy_to_user(userptr + off
@@ -1003,7 +1003,7 @@
 			m = (void *)e + i;
 
 			if (copy_to_user(userptr + off + i
-					 + offsetof(struct ip6t_entry_match,
+					 + offsetof(struct xt_entry_match,
 						    u.user.name),
 					 m->u.kernel.match->name,
 					 strlen(m->u.kernel.match->name)+1)
@@ -1015,7 +1015,7 @@
 
 		t = ip6t_get_target_c(e);
 		if (copy_to_user(userptr + off + e->target_offset
-				 + offsetof(struct ip6t_entry_target,
+				 + offsetof(struct xt_entry_target,
 					    u.user.name),
 				 t->u.kernel.target->name,
 				 strlen(t->u.kernel.target->name)+1) != 0) {
@@ -1053,7 +1053,7 @@
 			     const void *base, struct xt_table_info *newinfo)
 {
 	const struct xt_entry_match *ematch;
-	const struct ip6t_entry_target *t;
+	const struct xt_entry_target *t;
 	unsigned int entry_offset;
 	int off, i, ret;
 
@@ -1105,7 +1105,7 @@
 static int get_info(struct net *net, void __user *user,
                     const int *len, int compat)
 {
-	char name[IP6T_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 	struct xt_table *t;
 	int ret;
 
@@ -1118,7 +1118,7 @@
 	if (copy_from_user(name, user, sizeof(name)) != 0)
 		return -EFAULT;
 
-	name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
+	name[XT_TABLE_MAXNAMELEN-1] = '\0';
 #ifdef CONFIG_COMPAT
 	if (compat)
 		xt_compat_lock(AF_INET6);
@@ -1415,14 +1415,14 @@
 
 #ifdef CONFIG_COMPAT
 struct compat_ip6t_replace {
-	char			name[IP6T_TABLE_MAXNAMELEN];
+	char			name[XT_TABLE_MAXNAMELEN];
 	u32			valid_hooks;
 	u32			num_entries;
 	u32			size;
 	u32			hook_entry[NF_INET_NUMHOOKS];
 	u32			underflow[NF_INET_NUMHOOKS];
 	u32			num_counters;
-	compat_uptr_t		counters;	/* struct ip6t_counters * */
+	compat_uptr_t		counters;	/* struct xt_counters * */
 	struct compat_ip6t_entry entries[0];
 };
 
@@ -1431,7 +1431,7 @@
 			  unsigned int *size, struct xt_counters *counters,
 			  unsigned int i)
 {
-	struct ip6t_entry_target *t;
+	struct xt_entry_target *t;
 	struct compat_ip6t_entry __user *ce;
 	u_int16_t target_offset, next_offset;
 	compat_uint_t origsize;
@@ -1466,7 +1466,7 @@
 }
 
 static int
-compat_find_calc_match(struct ip6t_entry_match *m,
+compat_find_calc_match(struct xt_entry_match *m,
 		       const char *name,
 		       const struct ip6t_ip6 *ipv6,
 		       unsigned int hookmask,
@@ -1488,7 +1488,7 @@
 
 static void compat_release_entry(struct compat_ip6t_entry *e)
 {
-	struct ip6t_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_entry_match *ematch;
 
 	/* Cleanup all matches */
@@ -1509,7 +1509,7 @@
 				  const char *name)
 {
 	struct xt_entry_match *ematch;
-	struct ip6t_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_target *target;
 	unsigned int entry_offset;
 	unsigned int j;
@@ -1591,7 +1591,7 @@
 			    unsigned int *size, const char *name,
 			    struct xt_table_info *newinfo, unsigned char *base)
 {
-	struct ip6t_entry_target *t;
+	struct xt_entry_target *t;
 	struct xt_target *target;
 	struct ip6t_entry *de;
 	unsigned int origsize;
@@ -1899,7 +1899,7 @@
 }
 
 struct compat_ip6t_get_entries {
-	char name[IP6T_TABLE_MAXNAMELEN];
+	char name[XT_TABLE_MAXNAMELEN];
 	compat_uint_t size;
 	struct compat_ip6t_entry entrytable[0];
 };
@@ -2054,7 +2054,7 @@
 
 	case IP6T_SO_GET_REVISION_MATCH:
 	case IP6T_SO_GET_REVISION_TARGET: {
-		struct ip6t_get_revision rev;
+		struct xt_get_revision rev;
 		int target;
 
 		if (*len != sizeof(rev)) {
@@ -2191,7 +2191,7 @@
 /* The built-in targets: standard (NULL) and error. */
 static struct xt_target ip6t_builtin_tg[] __read_mostly = {
 	{
-		.name             = IP6T_STANDARD_TARGET,
+		.name             = XT_STANDARD_TARGET,
 		.targetsize       = sizeof(int),
 		.family           = NFPROTO_IPV6,
 #ifdef CONFIG_COMPAT
@@ -2201,9 +2201,9 @@
 #endif
 	},
 	{
-		.name             = IP6T_ERROR_TARGET,
+		.name             = XT_ERROR_TARGET,
 		.target           = ip6t_error,
-		.targetsize       = IP6T_FUNCTION_MAXNAMELEN,
+		.targetsize       = XT_FUNCTION_MAXNAMELEN,
 		.family           = NFPROTO_IPV6,
 	},
 };
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 0a07ae7..09c8889 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -23,6 +23,7 @@
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <net/netfilter/nf_log.h>
+#include <net/netfilter/xt_log.h>
 
 MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
 MODULE_DESCRIPTION("Xtables: IPv6 packet logging to syslog");
@@ -32,11 +33,9 @@
 #include <net/route.h>
 #include <linux/netfilter_ipv6/ip6t_LOG.h>
 
-/* Use lock to serialize, so printks don't overlap */
-static DEFINE_SPINLOCK(log_lock);
-
 /* One level of recursion won't kill us */
-static void dump_packet(const struct nf_loginfo *info,
+static void dump_packet(struct sbuff *m,
+			const struct nf_loginfo *info,
 			const struct sk_buff *skb, unsigned int ip6hoff,
 			int recurse)
 {
@@ -55,15 +54,15 @@
 
 	ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
 	if (ih == NULL) {
-		printk("TRUNCATED");
+		sb_add(m, "TRUNCATED");
 		return;
 	}
 
 	/* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
-	printk("SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
+	sb_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
 
 	/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
-	printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
+	sb_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
 	       ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
 	       (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
 	       ih->hop_limit,
@@ -78,35 +77,35 @@
 
 		hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
 		if (hp == NULL) {
-			printk("TRUNCATED");
+			sb_add(m, "TRUNCATED");
 			return;
 		}
 
 		/* Max length: 48 "OPT (...) " */
 		if (logflags & IP6T_LOG_IPOPT)
-			printk("OPT ( ");
+			sb_add(m, "OPT ( ");
 
 		switch (currenthdr) {
 		case IPPROTO_FRAGMENT: {
 			struct frag_hdr _fhdr;
 			const struct frag_hdr *fh;
 
-			printk("FRAG:");
+			sb_add(m, "FRAG:");
 			fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
 						&_fhdr);
 			if (fh == NULL) {
-				printk("TRUNCATED ");
+				sb_add(m, "TRUNCATED ");
 				return;
 			}
 
 			/* Max length: 6 "65535 " */
-			printk("%u ", ntohs(fh->frag_off) & 0xFFF8);
+			sb_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8);
 
 			/* Max length: 11 "INCOMPLETE " */
 			if (fh->frag_off & htons(0x0001))
-				printk("INCOMPLETE ");
+				sb_add(m, "INCOMPLETE ");
 
-			printk("ID:%08x ", ntohl(fh->identification));
+			sb_add(m, "ID:%08x ", ntohl(fh->identification));
 
 			if (ntohs(fh->frag_off) & 0xFFF8)
 				fragment = 1;
@@ -120,7 +119,7 @@
 		case IPPROTO_HOPOPTS:
 			if (fragment) {
 				if (logflags & IP6T_LOG_IPOPT)
-					printk(")");
+					sb_add(m, ")");
 				return;
 			}
 			hdrlen = ipv6_optlen(hp);
@@ -132,10 +131,10 @@
 				const struct ip_auth_hdr *ah;
 
 				/* Max length: 3 "AH " */
-				printk("AH ");
+				sb_add(m, "AH ");
 
 				if (fragment) {
-					printk(")");
+					sb_add(m, ")");
 					return;
 				}
 
@@ -146,13 +145,13 @@
 					 * Max length: 26 "INCOMPLETE [65535
 					 *  bytes] )"
 					 */
-					printk("INCOMPLETE [%u bytes] )",
+					sb_add(m, "INCOMPLETE [%u bytes] )",
 					       skb->len - ptr);
 					return;
 				}
 
 				/* Length: 15 "SPI=0xF1234567 */
-				printk("SPI=0x%x ", ntohl(ah->spi));
+				sb_add(m, "SPI=0x%x ", ntohl(ah->spi));
 
 			}
 
@@ -164,10 +163,10 @@
 				const struct ip_esp_hdr *eh;
 
 				/* Max length: 4 "ESP " */
-				printk("ESP ");
+				sb_add(m, "ESP ");
 
 				if (fragment) {
-					printk(")");
+					sb_add(m, ")");
 					return;
 				}
 
@@ -177,23 +176,23 @@
 				eh = skb_header_pointer(skb, ptr, sizeof(_esph),
 							&_esph);
 				if (eh == NULL) {
-					printk("INCOMPLETE [%u bytes] )",
+					sb_add(m, "INCOMPLETE [%u bytes] )",
 					       skb->len - ptr);
 					return;
 				}
 
 				/* Length: 16 "SPI=0xF1234567 )" */
-				printk("SPI=0x%x )", ntohl(eh->spi) );
+				sb_add(m, "SPI=0x%x )", ntohl(eh->spi) );
 
 			}
 			return;
 		default:
 			/* Max length: 20 "Unknown Ext Hdr 255" */
-			printk("Unknown Ext Hdr %u", currenthdr);
+			sb_add(m, "Unknown Ext Hdr %u", currenthdr);
 			return;
 		}
 		if (logflags & IP6T_LOG_IPOPT)
-			printk(") ");
+			sb_add(m, ") ");
 
 		currenthdr = hp->nexthdr;
 		ptr += hdrlen;
@@ -205,7 +204,7 @@
 		const struct tcphdr *th;
 
 		/* Max length: 10 "PROTO=TCP " */
-		printk("PROTO=TCP ");
+		sb_add(m, "PROTO=TCP ");
 
 		if (fragment)
 			break;
@@ -213,40 +212,40 @@
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
 		th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph);
 		if (th == NULL) {
-			printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+			sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr);
 			return;
 		}
 
 		/* Max length: 20 "SPT=65535 DPT=65535 " */
-		printk("SPT=%u DPT=%u ",
+		sb_add(m, "SPT=%u DPT=%u ",
 		       ntohs(th->source), ntohs(th->dest));
 		/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
 		if (logflags & IP6T_LOG_TCPSEQ)
-			printk("SEQ=%u ACK=%u ",
+			sb_add(m, "SEQ=%u ACK=%u ",
 			       ntohl(th->seq), ntohl(th->ack_seq));
 		/* Max length: 13 "WINDOW=65535 " */
-		printk("WINDOW=%u ", ntohs(th->window));
+		sb_add(m, "WINDOW=%u ", ntohs(th->window));
 		/* Max length: 9 "RES=0x3C " */
-		printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
+		sb_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
 		/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
 		if (th->cwr)
-			printk("CWR ");
+			sb_add(m, "CWR ");
 		if (th->ece)
-			printk("ECE ");
+			sb_add(m, "ECE ");
 		if (th->urg)
-			printk("URG ");
+			sb_add(m, "URG ");
 		if (th->ack)
-			printk("ACK ");
+			sb_add(m, "ACK ");
 		if (th->psh)
-			printk("PSH ");
+			sb_add(m, "PSH ");
 		if (th->rst)
-			printk("RST ");
+			sb_add(m, "RST ");
 		if (th->syn)
-			printk("SYN ");
+			sb_add(m, "SYN ");
 		if (th->fin)
-			printk("FIN ");
+			sb_add(m, "FIN ");
 		/* Max length: 11 "URGP=65535 " */
-		printk("URGP=%u ", ntohs(th->urg_ptr));
+		sb_add(m, "URGP=%u ", ntohs(th->urg_ptr));
 
 		if ((logflags & IP6T_LOG_TCPOPT) &&
 		    th->doff * 4 > sizeof(struct tcphdr)) {
@@ -260,15 +259,15 @@
 						ptr + sizeof(struct tcphdr),
 						optsize, _opt);
 			if (op == NULL) {
-				printk("OPT (TRUNCATED)");
+				sb_add(m, "OPT (TRUNCATED)");
 				return;
 			}
 
 			/* Max length: 127 "OPT (" 15*4*2chars ") " */
-			printk("OPT (");
+			sb_add(m, "OPT (");
 			for (i =0; i < optsize; i++)
-				printk("%02X", op[i]);
-			printk(") ");
+				sb_add(m, "%02X", op[i]);
+			sb_add(m, ") ");
 		}
 		break;
 	}
@@ -279,9 +278,9 @@
 
 		if (currenthdr == IPPROTO_UDP)
 			/* Max length: 10 "PROTO=UDP "     */
-			printk("PROTO=UDP " );
+			sb_add(m, "PROTO=UDP " );
 		else	/* Max length: 14 "PROTO=UDPLITE " */
-			printk("PROTO=UDPLITE ");
+			sb_add(m, "PROTO=UDPLITE ");
 
 		if (fragment)
 			break;
@@ -289,12 +288,12 @@
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
 		uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph);
 		if (uh == NULL) {
-			printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+			sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr);
 			return;
 		}
 
 		/* Max length: 20 "SPT=65535 DPT=65535 " */
-		printk("SPT=%u DPT=%u LEN=%u ",
+		sb_add(m, "SPT=%u DPT=%u LEN=%u ",
 		       ntohs(uh->source), ntohs(uh->dest),
 		       ntohs(uh->len));
 		break;
@@ -304,7 +303,7 @@
 		const struct icmp6hdr *ic;
 
 		/* Max length: 13 "PROTO=ICMPv6 " */
-		printk("PROTO=ICMPv6 ");
+		sb_add(m, "PROTO=ICMPv6 ");
 
 		if (fragment)
 			break;
@@ -312,18 +311,18 @@
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
 		ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
 		if (ic == NULL) {
-			printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+			sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr);
 			return;
 		}
 
 		/* Max length: 18 "TYPE=255 CODE=255 " */
-		printk("TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code);
+		sb_add(m, "TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code);
 
 		switch (ic->icmp6_type) {
 		case ICMPV6_ECHO_REQUEST:
 		case ICMPV6_ECHO_REPLY:
 			/* Max length: 19 "ID=65535 SEQ=65535 " */
-			printk("ID=%u SEQ=%u ",
+			sb_add(m, "ID=%u SEQ=%u ",
 				ntohs(ic->icmp6_identifier),
 				ntohs(ic->icmp6_sequence));
 			break;
@@ -334,35 +333,35 @@
 
 		case ICMPV6_PARAMPROB:
 			/* Max length: 17 "POINTER=ffffffff " */
-			printk("POINTER=%08x ", ntohl(ic->icmp6_pointer));
+			sb_add(m, "POINTER=%08x ", ntohl(ic->icmp6_pointer));
 			/* Fall through */
 		case ICMPV6_DEST_UNREACH:
 		case ICMPV6_PKT_TOOBIG:
 		case ICMPV6_TIME_EXCEED:
 			/* Max length: 3+maxlen */
 			if (recurse) {
-				printk("[");
-				dump_packet(info, skb, ptr + sizeof(_icmp6h),
-					    0);
-				printk("] ");
+				sb_add(m, "[");
+				dump_packet(m, info, skb,
+					    ptr + sizeof(_icmp6h), 0);
+				sb_add(m, "] ");
 			}
 
 			/* Max length: 10 "MTU=65535 " */
 			if (ic->icmp6_type == ICMPV6_PKT_TOOBIG)
-				printk("MTU=%u ", ntohl(ic->icmp6_mtu));
+				sb_add(m, "MTU=%u ", ntohl(ic->icmp6_mtu));
 		}
 		break;
 	}
 	/* Max length: 10 "PROTO=255 " */
 	default:
-		printk("PROTO=%u ", currenthdr);
+		sb_add(m, "PROTO=%u ", currenthdr);
 	}
 
 	/* Max length: 15 "UID=4294967295 " */
 	if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) {
 		read_lock_bh(&skb->sk->sk_callback_lock);
 		if (skb->sk->sk_socket && skb->sk->sk_socket->file)
-			printk("UID=%u GID=%u ",
+			sb_add(m, "UID=%u GID=%u ",
 				skb->sk->sk_socket->file->f_cred->fsuid,
 				skb->sk->sk_socket->file->f_cred->fsgid);
 		read_unlock_bh(&skb->sk->sk_callback_lock);
@@ -370,10 +369,11 @@
 
 	/* Max length: 16 "MARK=0xFFFFFFFF " */
 	if (!recurse && skb->mark)
-		printk("MARK=0x%x ", skb->mark);
+		sb_add(m, "MARK=0x%x ", skb->mark);
 }
 
-static void dump_mac_header(const struct nf_loginfo *info,
+static void dump_mac_header(struct sbuff *m,
+			    const struct nf_loginfo *info,
 			    const struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dev;
@@ -387,7 +387,7 @@
 
 	switch (dev->type) {
 	case ARPHRD_ETHER:
-		printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
+		sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
 		       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
 		       ntohs(eth_hdr(skb)->h_proto));
 		return;
@@ -396,7 +396,7 @@
 	}
 
 fallback:
-	printk("MAC=");
+	sb_add(m, "MAC=");
 	if (dev->hard_header_len &&
 	    skb->mac_header != skb->network_header) {
 		const unsigned char *p = skb_mac_header(skb);
@@ -408,19 +408,19 @@
 			p = NULL;
 
 		if (p != NULL) {
-			printk("%02x", *p++);
+			sb_add(m, "%02x", *p++);
 			for (i = 1; i < len; i++)
-				printk(":%02x", p[i]);
+				sb_add(m, ":%02x", p[i]);
 		}
-		printk(" ");
+		sb_add(m, " ");
 
 		if (dev->type == ARPHRD_SIT) {
 			const struct iphdr *iph =
 				(struct iphdr *)skb_mac_header(skb);
-			printk("TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr);
+			sb_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr);
 		}
 	} else
-		printk(" ");
+		sb_add(m, " ");
 }
 
 static struct nf_loginfo default_loginfo = {
@@ -442,22 +442,23 @@
 		const struct nf_loginfo *loginfo,
 		const char *prefix)
 {
+	struct sbuff *m = sb_open();
+
 	if (!loginfo)
 		loginfo = &default_loginfo;
 
-	spin_lock_bh(&log_lock);
-	printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
-		prefix,
-		in ? in->name : "",
-		out ? out->name : "");
+	sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
+	       prefix,
+	       in ? in->name : "",
+	       out ? out->name : "");
 
 	/* MAC logging for input path only. */
 	if (in && !out)
-		dump_mac_header(loginfo, skb);
+		dump_mac_header(m, loginfo, skb);
 
-	dump_packet(loginfo, skb, skb_network_offset(skb), 1);
-	printk("\n");
-	spin_unlock_bh(&log_lock);
+	dump_packet(m, loginfo, skb, skb_network_offset(skb), 1);
+
+	sb_close(m);
 }
 
 static unsigned int
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index ff43461..c8af58b 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/icmp.h>
-#include <linux/sysctl.h>
 #include <net/ipv6.h>
 #include <net/inet_frag.h>
 
@@ -29,6 +28,7 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_zones.h>
 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
 #include <net/netfilter/nf_log.h>
 
 static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
@@ -189,53 +189,6 @@
 	return nf_conntrack_confirm(skb);
 }
 
-static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
-						struct sk_buff *skb)
-{
-	u16 zone = NF_CT_DEFAULT_ZONE;
-
-	if (skb->nfct)
-		zone = nf_ct_zone((struct nf_conn *)skb->nfct);
-
-#ifdef CONFIG_BRIDGE_NETFILTER
-	if (skb->nf_bridge &&
-	    skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
-		return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
-#endif
-	if (hooknum == NF_INET_PRE_ROUTING)
-		return IP6_DEFRAG_CONNTRACK_IN + zone;
-	else
-		return IP6_DEFRAG_CONNTRACK_OUT + zone;
-
-}
-
-static unsigned int ipv6_defrag(unsigned int hooknum,
-				struct sk_buff *skb,
-				const struct net_device *in,
-				const struct net_device *out,
-				int (*okfn)(struct sk_buff *))
-{
-	struct sk_buff *reasm;
-
-	/* Previously seen (loopback)?  */
-	if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
-		return NF_ACCEPT;
-
-	reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
-	/* queued */
-	if (reasm == NULL)
-		return NF_STOLEN;
-
-	/* error occured or not fragmented */
-	if (reasm == skb)
-		return NF_ACCEPT;
-
-	nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
-			   (struct net_device *)out, okfn);
-
-	return NF_STOLEN;
-}
-
 static unsigned int __ipv6_conntrack_in(struct net *net,
 					unsigned int hooknum,
 					struct sk_buff *skb,
@@ -288,13 +241,6 @@
 
 static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
 	{
-		.hook		= ipv6_defrag,
-		.owner		= THIS_MODULE,
-		.pf		= NFPROTO_IPV6,
-		.hooknum	= NF_INET_PRE_ROUTING,
-		.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
-	},
-	{
 		.hook		= ipv6_conntrack_in,
 		.owner		= THIS_MODULE,
 		.pf		= NFPROTO_IPV6,
@@ -309,13 +255,6 @@
 		.priority	= NF_IP6_PRI_CONNTRACK,
 	},
 	{
-		.hook		= ipv6_defrag,
-		.owner		= THIS_MODULE,
-		.pf		= NFPROTO_IPV6,
-		.hooknum	= NF_INET_LOCAL_OUT,
-		.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
-	},
-	{
 		.hook		= ipv6_confirm,
 		.owner		= THIS_MODULE,
 		.pf		= NFPROTO_IPV6,
@@ -387,10 +326,6 @@
 	.nlattr_to_tuple	= ipv6_nlattr_to_tuple,
 	.nla_policy		= ipv6_nla_policy,
 #endif
-#ifdef CONFIG_SYSCTL
-	.ctl_table_path		= nf_net_netfilter_sysctl_path,
-	.ctl_table		= nf_ct_ipv6_sysctl_table,
-#endif
 	.me			= THIS_MODULE,
 };
 
@@ -403,16 +338,12 @@
 	int ret = 0;
 
 	need_conntrack();
+	nf_defrag_ipv6_enable();
 
-	ret = nf_ct_frag6_init();
-	if (ret < 0) {
-		pr_err("nf_conntrack_ipv6: can't initialize frag6.\n");
-		return ret;
-	}
 	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6);
 	if (ret < 0) {
 		pr_err("nf_conntrack_ipv6: can't register tcp.\n");
-		goto cleanup_frag6;
+		return ret;
 	}
 
 	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6);
@@ -450,8 +381,6 @@
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
  cleanup_tcp:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
- cleanup_frag6:
-	nf_ct_frag6_cleanup();
 	return ret;
 }
 
@@ -463,7 +392,6 @@
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
-	nf_ct_frag6_cleanup();
 }
 
 module_init(nf_conntrack_l3proto_ipv6_init);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 578f3c1..489d71b 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -73,7 +73,7 @@
 static struct netns_frags nf_init_frags;
 
 #ifdef CONFIG_SYSCTL
-struct ctl_table nf_ct_ipv6_sysctl_table[] = {
+struct ctl_table nf_ct_frag6_sysctl_table[] = {
 	{
 		.procname	= "nf_conntrack_frag6_timeout",
 		.data		= &nf_init_frags.timeout,
@@ -97,6 +97,8 @@
 	},
 	{ }
 };
+
+static struct ctl_table_header *nf_ct_frag6_sysctl_header;
 #endif
 
 static unsigned int nf_hashfn(struct inet_frag_queue *q)
@@ -363,7 +365,7 @@
 	/* If the first fragment is fragmented itself, we split
 	 * it to two chunks: the first with data and paged part
 	 * and the second, holding only fragments. */
-	if (skb_has_frags(head)) {
+	if (skb_has_frag_list(head)) {
 		struct sk_buff *clone;
 		int i, plen = 0;
 
@@ -623,11 +625,21 @@
 	inet_frags_init_net(&nf_init_frags);
 	inet_frags_init(&nf_frags);
 
+	nf_ct_frag6_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path,
+							  nf_ct_frag6_sysctl_table);
+	if (!nf_ct_frag6_sysctl_header) {
+		inet_frags_fini(&nf_frags);
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 
 void nf_ct_frag6_cleanup(void)
 {
+	unregister_sysctl_table(nf_ct_frag6_sysctl_header);
+	nf_ct_frag6_sysctl_header = NULL;
+
 	inet_frags_fini(&nf_frags);
 
 	nf_init_frags.low_thresh = 0;
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
new file mode 100644
index 0000000..99abfb5
--- /dev/null
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -0,0 +1,131 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2004 Netfilter Core Team <coreteam@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.
+ */
+
+#include <linux/types.h>
+#include <linux/ipv6.h>
+#include <linux/in6.h>
+#include <linux/netfilter.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/icmp.h>
+#include <linux/sysctl.h>
+#include <net/ipv6.h>
+#include <net/inet_frag.h>
+
+#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter_bridge.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_zones.h>
+#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
+
+static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
+						struct sk_buff *skb)
+{
+	u16 zone = NF_CT_DEFAULT_ZONE;
+
+	if (skb->nfct)
+		zone = nf_ct_zone((struct nf_conn *)skb->nfct);
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (skb->nf_bridge &&
+	    skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
+		return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
+#endif
+	if (hooknum == NF_INET_PRE_ROUTING)
+		return IP6_DEFRAG_CONNTRACK_IN + zone;
+	else
+		return IP6_DEFRAG_CONNTRACK_OUT + zone;
+
+}
+
+static unsigned int ipv6_defrag(unsigned int hooknum,
+				struct sk_buff *skb,
+				const struct net_device *in,
+				const struct net_device *out,
+				int (*okfn)(struct sk_buff *))
+{
+	struct sk_buff *reasm;
+
+	/* Previously seen (loopback)?	*/
+	if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
+		return NF_ACCEPT;
+
+	reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
+	/* queued */
+	if (reasm == NULL)
+		return NF_STOLEN;
+
+	/* error occured or not fragmented */
+	if (reasm == skb)
+		return NF_ACCEPT;
+
+	nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
+			   (struct net_device *)out, okfn);
+
+	return NF_STOLEN;
+}
+
+static struct nf_hook_ops ipv6_defrag_ops[] = {
+	{
+		.hook		= ipv6_defrag,
+		.owner		= THIS_MODULE,
+		.pf		= NFPROTO_IPV6,
+		.hooknum	= NF_INET_PRE_ROUTING,
+		.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
+	},
+	{
+		.hook		= ipv6_defrag,
+		.owner		= THIS_MODULE,
+		.pf		= NFPROTO_IPV6,
+		.hooknum	= NF_INET_LOCAL_OUT,
+		.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
+	},
+};
+
+static int __init nf_defrag_init(void)
+{
+	int ret = 0;
+
+	ret = nf_ct_frag6_init();
+	if (ret < 0) {
+		pr_err("nf_defrag_ipv6: can't initialize frag6.\n");
+		return ret;
+	}
+	ret = nf_register_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
+	if (ret < 0) {
+		pr_err("nf_defrag_ipv6: can't register hooks\n");
+		goto cleanup_frag6;
+	}
+	return ret;
+
+cleanup_frag6:
+	nf_ct_frag6_cleanup();
+	return ret;
+
+}
+
+static void __exit nf_defrag_fini(void)
+{
+	nf_unregister_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
+	nf_ct_frag6_cleanup();
+}
+
+void nf_defrag_ipv6_enable(void)
+{
+}
+EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable);
+
+module_init(nf_defrag_init);
+module_exit(nf_defrag_fini);
+
+MODULE_LICENSE("GPL");
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c
index 1fa3468..9bb936a 100644
--- a/net/ipv6/protocol.c
+++ b/net/ipv6/protocol.c
@@ -25,28 +25,14 @@
 #include <linux/spinlock.h>
 #include <net/protocol.h>
 
-const struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
-static DEFINE_SPINLOCK(inet6_proto_lock);
-
+const struct inet6_protocol *inet6_protos[MAX_INET_PROTOS] __read_mostly;
 
 int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol)
 {
-	int ret, hash = protocol & (MAX_INET_PROTOS - 1);
+	int hash = protocol & (MAX_INET_PROTOS - 1);
 
-	spin_lock_bh(&inet6_proto_lock);
-
-	if (inet6_protos[hash]) {
-		ret = -1;
-	} else {
-		inet6_protos[hash] = prot;
-		ret = 0;
-	}
-
-	spin_unlock_bh(&inet6_proto_lock);
-
-	return ret;
+	return !cmpxchg(&inet6_protos[hash], NULL, prot) ? 0 : -1;
 }
-
 EXPORT_SYMBOL(inet6_add_protocol);
 
 /*
@@ -57,20 +43,10 @@
 {
 	int ret, hash = protocol & (MAX_INET_PROTOS - 1);
 
-	spin_lock_bh(&inet6_proto_lock);
-
-	if (inet6_protos[hash] != prot) {
-		ret = -1;
-	} else {
-		inet6_protos[hash] = NULL;
-		ret = 0;
-	}
-
-	spin_unlock_bh(&inet6_proto_lock);
+	ret = (cmpxchg(&inet6_protos[hash], prot, NULL) == prot) ? 0 : -1;
 
 	synchronize_net();
 
 	return ret;
 }
-
 EXPORT_SYMBOL(inet6_del_protocol);
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index e677937..45e6efb7 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -764,7 +764,7 @@
 			return -EINVAL;
 
 		if (sin6->sin6_family && sin6->sin6_family != AF_INET6)
-			return(-EAFNOSUPPORT);
+			return -EAFNOSUPPORT;
 
 		/* port is the proto value [0..255] carried in nexthdr */
 		proto = ntohs(sin6->sin6_port);
@@ -772,10 +772,10 @@
 		if (!proto)
 			proto = inet->inet_num;
 		else if (proto != inet->inet_num)
-			return(-EINVAL);
+			return -EINVAL;
 
 		if (proto > 255)
-			return(-EINVAL);
+			return -EINVAL;
 
 		daddr = &sin6->sin6_addr;
 		if (np->sndflow) {
@@ -985,7 +985,7 @@
 			/* You may get strange result with a positive odd offset;
 			   RFC2292bis agrees with me. */
 			if (val > 0 && (val&1))
-				return(-EINVAL);
+				return -EINVAL;
 			if (val < 0) {
 				rp->checksum = 0;
 			} else {
@@ -997,7 +997,7 @@
 			break;
 
 		default:
-			return(-ENOPROTOOPT);
+			return -ENOPROTOOPT;
 	}
 }
 
@@ -1190,7 +1190,7 @@
 	default:
 		break;
 	}
-	return(0);
+	return 0;
 }
 
 struct proto rawv6_prot = {
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 64cfef1..c7ba314 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -458,7 +458,7 @@
 	/* If the first fragment is fragmented itself, we split
 	 * it to two chunks: the first with data and paged part
 	 * and the second, holding only fragments. */
-	if (skb_has_frags(head)) {
+	if (skb_has_frag_list(head)) {
 		struct sk_buff *clone;
 		int i, plen = 0;
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index d126365..25661f9 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -109,7 +109,6 @@
 	.link_failure		=	ip6_link_failure,
 	.update_pmtu		=	ip6_rt_update_pmtu,
 	.local_out		=	__ip6_local_out,
-	.entries		=	ATOMIC_INIT(0),
 };
 
 static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
@@ -122,7 +121,6 @@
 	.destroy		=	ip6_dst_destroy,
 	.check			=	ip6_dst_check,
 	.update_pmtu		=	ip6_rt_blackhole_update_pmtu,
-	.entries		=	ATOMIC_INIT(0),
 };
 
 static struct rt6_info ip6_null_entry_template = {
@@ -217,14 +215,14 @@
 
 static __inline__ int rt6_check_expired(const struct rt6_info *rt)
 {
-	return (rt->rt6i_flags & RTF_EXPIRES &&
-		time_after(jiffies, rt->rt6i_expires));
+	return (rt->rt6i_flags & RTF_EXPIRES) &&
+		time_after(jiffies, rt->rt6i_expires);
 }
 
 static inline int rt6_need_strict(struct in6_addr *daddr)
 {
-	return (ipv6_addr_type(daddr) &
-		(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK));
+	return ipv6_addr_type(daddr) &
+		(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
 }
 
 /*
@@ -440,7 +438,7 @@
 		  __func__, match);
 
 	net = dev_net(rt0->rt6i_dev);
-	return (match ? match : net->ipv6.ip6_null_entry);
+	return match ? match : net->ipv6.ip6_null_entry;
 }
 
 #ifdef CONFIG_IPV6_ROUTE_INFO
@@ -670,7 +668,7 @@
 
 			if (net_ratelimit())
 				printk(KERN_WARNING
-				       "Neighbour table overflow.\n");
+				       "ipv6: Neighbour table overflow.\n");
 			dst_free(&rt->dst);
 			return NULL;
 		}
@@ -859,7 +857,7 @@
 
 	dst_release(*dstp);
 	*dstp = new;
-	return (new ? 0 : -ENOMEM);
+	return new ? 0 : -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(ip6_dst_blackhole);
 
@@ -1058,19 +1056,22 @@
 	int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
 	int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout;
 	unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc;
+	int entries;
 
+	entries = dst_entries_get_fast(ops);
 	if (time_after(rt_last_gc + rt_min_interval, now) &&
-	    atomic_read(&ops->entries) <= rt_max_size)
+	    entries <= rt_max_size)
 		goto out;
 
 	net->ipv6.ip6_rt_gc_expire++;
 	fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net);
 	net->ipv6.ip6_rt_last_gc = now;
-	if (atomic_read(&ops->entries) < ops->gc_thresh)
+	entries = dst_entries_get_slow(ops);
+	if (entries < ops->gc_thresh)
 		net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
 out:
 	net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity;
-	return (atomic_read(&ops->entries) > rt_max_size);
+	return entries > rt_max_size;
 }
 
 /* Clean host part of a prefix. Not necessary in radix tree,
@@ -1169,6 +1170,8 @@
 
 	if (addr_type & IPV6_ADDR_MULTICAST)
 		rt->dst.input = ip6_mc_input;
+	else if (cfg->fc_flags & RTF_LOCAL)
+		rt->dst.input = ip6_input;
 	else
 		rt->dst.input = ip6_forward;
 
@@ -1190,7 +1193,8 @@
 	   they would result in kernel looping; promote them to reject routes
 	 */
 	if ((cfg->fc_flags & RTF_REJECT) ||
-	    (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
+	    (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK)
+					      && !(cfg->fc_flags&RTF_LOCAL))) {
 		/* hold loopback dev/idev if we haven't done so. */
 		if (dev != net->loopback_dev) {
 			if (dev) {
@@ -1556,14 +1560,13 @@
  *	i.e. Path MTU discovery
  */
 
-void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
-			struct net_device *dev, u32 pmtu)
+static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr,
+			     struct net *net, u32 pmtu, int ifindex)
 {
 	struct rt6_info *rt, *nrt;
-	struct net *net = dev_net(dev);
 	int allfrag = 0;
 
-	rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0);
+	rt = rt6_lookup(net, daddr, saddr, ifindex, 0);
 	if (rt == NULL)
 		return;
 
@@ -1631,6 +1634,27 @@
 	dst_release(&rt->dst);
 }
 
+void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
+			struct net_device *dev, u32 pmtu)
+{
+	struct net *net = dev_net(dev);
+
+	/*
+	 * RFC 1981 states that a node "MUST reduce the size of the packets it
+	 * is sending along the path" that caused the Packet Too Big message.
+	 * Since it's not possible in the general case to determine which
+	 * interface was used to send the original packet, we update the MTU
+	 * on the interface that will be used to send future packets. We also
+	 * update the MTU on the interface that received the Packet Too Big in
+	 * case the original packet was forced out that interface with
+	 * SO_BINDTODEVICE or similar. This is the next best thing to the
+	 * correct behaviour, which would be to update the MTU on all
+	 * interfaces.
+	 */
+	rt6_do_pmtu_disc(daddr, saddr, net, pmtu, 0);
+	rt6_do_pmtu_disc(daddr, saddr, net, pmtu, dev->ifindex);
+}
+
 /*
  *	Misc support functions
  */
@@ -2082,6 +2106,9 @@
 	if (rtm->rtm_type == RTN_UNREACHABLE)
 		cfg->fc_flags |= RTF_REJECT;
 
+	if (rtm->rtm_type == RTN_LOCAL)
+		cfg->fc_flags |= RTF_LOCAL;
+
 	cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
 	cfg->fc_nlinfo.nlh = nlh;
 	cfg->fc_nlinfo.nl_net = sock_net(skb->sk);
@@ -2202,6 +2229,8 @@
 	NLA_PUT_U32(skb, RTA_TABLE, table);
 	if (rt->rt6i_flags&RTF_REJECT)
 		rtm->rtm_type = RTN_UNREACHABLE;
+	else if (rt->rt6i_flags&RTF_LOCAL)
+		rtm->rtm_type = RTN_LOCAL;
 	else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK))
 		rtm->rtm_type = RTN_LOCAL;
 	else
@@ -2496,7 +2525,7 @@
 		   net->ipv6.rt6_stats->fib_rt_alloc,
 		   net->ipv6.rt6_stats->fib_rt_entries,
 		   net->ipv6.rt6_stats->fib_rt_cache,
-		   atomic_read(&net->ipv6.ip6_dst_ops.entries),
+		   dst_entries_get_slow(&net->ipv6.ip6_dst_ops),
 		   net->ipv6.rt6_stats->fib_discarded_routes);
 
 	return 0;
@@ -2638,11 +2667,14 @@
 	memcpy(&net->ipv6.ip6_dst_ops, &ip6_dst_ops_template,
 	       sizeof(net->ipv6.ip6_dst_ops));
 
+	if (dst_entries_init(&net->ipv6.ip6_dst_ops) < 0)
+		goto out_ip6_dst_ops;
+
 	net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
 					   sizeof(*net->ipv6.ip6_null_entry),
 					   GFP_KERNEL);
 	if (!net->ipv6.ip6_null_entry)
-		goto out_ip6_dst_ops;
+		goto out_ip6_dst_entries;
 	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;
@@ -2692,6 +2724,8 @@
 out_ip6_null_entry:
 	kfree(net->ipv6.ip6_null_entry);
 #endif
+out_ip6_dst_entries:
+	dst_entries_destroy(&net->ipv6.ip6_dst_ops);
 out_ip6_dst_ops:
 	goto out;
 }
@@ -2730,10 +2764,14 @@
 	if (!ip6_dst_ops_template.kmem_cachep)
 		goto out;
 
-	ret = register_pernet_subsys(&ip6_route_net_ops);
+	ret = dst_entries_init(&ip6_dst_blackhole_ops);
 	if (ret)
 		goto out_kmem_cache;
 
+	ret = register_pernet_subsys(&ip6_route_net_ops);
+	if (ret)
+		goto out_dst_entries;
+
 	ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
 
 	/* Registering of the loopback is done before this portion of code,
@@ -2780,6 +2818,8 @@
 	fib6_gc_cleanup();
 out_register_subsys:
 	unregister_pernet_subsys(&ip6_route_net_ops);
+out_dst_entries:
+	dst_entries_destroy(&ip6_dst_blackhole_ops);
 out_kmem_cache:
 	kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
 	goto out;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 4699cd3..367a6cc 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -63,36 +63,63 @@
 #define HASH_SIZE  16
 #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
 
-static void ipip6_tunnel_init(struct net_device *dev);
+static int ipip6_tunnel_init(struct net_device *dev);
 static void ipip6_tunnel_setup(struct net_device *dev);
+static void ipip6_dev_free(struct net_device *dev);
 
 static int sit_net_id __read_mostly;
 struct sit_net {
-	struct ip_tunnel *tunnels_r_l[HASH_SIZE];
-	struct ip_tunnel *tunnels_r[HASH_SIZE];
-	struct ip_tunnel *tunnels_l[HASH_SIZE];
-	struct ip_tunnel *tunnels_wc[1];
-	struct ip_tunnel **tunnels[4];
+	struct ip_tunnel __rcu *tunnels_r_l[HASH_SIZE];
+	struct ip_tunnel __rcu *tunnels_r[HASH_SIZE];
+	struct ip_tunnel __rcu *tunnels_l[HASH_SIZE];
+	struct ip_tunnel __rcu *tunnels_wc[1];
+	struct ip_tunnel __rcu **tunnels[4];
 
 	struct net_device *fb_tunnel_dev;
 };
 
 /*
- * Locking : hash tables are protected by RCU and a spinlock
+ * Locking : hash tables are protected by RCU and RTNL
  */
-static DEFINE_SPINLOCK(ipip6_lock);
 
 #define for_each_ip_tunnel_rcu(start) \
 	for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
 
+/* often modified stats are per cpu, other are shared (netdev->stats) */
+struct pcpu_tstats {
+	unsigned long	rx_packets;
+	unsigned long	rx_bytes;
+	unsigned long	tx_packets;
+	unsigned long	tx_bytes;
+};
+
+static struct net_device_stats *ipip6_get_stats(struct net_device *dev)
+{
+	struct pcpu_tstats sum = { 0 };
+	int i;
+
+	for_each_possible_cpu(i) {
+		const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
+
+		sum.rx_packets += tstats->rx_packets;
+		sum.rx_bytes   += tstats->rx_bytes;
+		sum.tx_packets += tstats->tx_packets;
+		sum.tx_bytes   += tstats->tx_bytes;
+	}
+	dev->stats.rx_packets = sum.rx_packets;
+	dev->stats.rx_bytes   = sum.rx_bytes;
+	dev->stats.tx_packets = sum.tx_packets;
+	dev->stats.tx_bytes   = sum.tx_bytes;
+	return &dev->stats;
+}
 /*
  * Must be invoked with rcu_read_lock
  */
 static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net,
 		struct net_device *dev, __be32 remote, __be32 local)
 {
-	unsigned h0 = HASH(remote);
-	unsigned h1 = HASH(local);
+	unsigned int h0 = HASH(remote);
+	unsigned int h1 = HASH(local);
 	struct ip_tunnel *t;
 	struct sit_net *sitn = net_generic(net, sit_net_id);
 
@@ -121,12 +148,12 @@
 	return NULL;
 }
 
-static struct ip_tunnel **__ipip6_bucket(struct sit_net *sitn,
+static struct ip_tunnel __rcu **__ipip6_bucket(struct sit_net *sitn,
 		struct ip_tunnel_parm *parms)
 {
 	__be32 remote = parms->iph.daddr;
 	__be32 local = parms->iph.saddr;
-	unsigned h = 0;
+	unsigned int h = 0;
 	int prio = 0;
 
 	if (remote) {
@@ -140,7 +167,7 @@
 	return &sitn->tunnels[prio][h];
 }
 
-static inline struct ip_tunnel **ipip6_bucket(struct sit_net *sitn,
+static inline struct ip_tunnel __rcu **ipip6_bucket(struct sit_net *sitn,
 		struct ip_tunnel *t)
 {
 	return __ipip6_bucket(sitn, &t->parms);
@@ -148,13 +175,14 @@
 
 static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t)
 {
-	struct ip_tunnel **tp;
+	struct ip_tunnel __rcu **tp;
+	struct ip_tunnel *iter;
 
-	for (tp = ipip6_bucket(sitn, t); *tp; tp = &(*tp)->next) {
-		if (t == *tp) {
-			spin_lock_bh(&ipip6_lock);
-			*tp = t->next;
-			spin_unlock_bh(&ipip6_lock);
+	for (tp = ipip6_bucket(sitn, t);
+	     (iter = rtnl_dereference(*tp)) != NULL;
+	     tp = &iter->next) {
+		if (t == iter) {
+			rcu_assign_pointer(*tp, t->next);
 			break;
 		}
 	}
@@ -162,12 +190,10 @@
 
 static void ipip6_tunnel_link(struct sit_net *sitn, struct ip_tunnel *t)
 {
-	struct ip_tunnel **tp = ipip6_bucket(sitn, t);
+	struct ip_tunnel __rcu **tp = ipip6_bucket(sitn, t);
 
-	spin_lock_bh(&ipip6_lock);
-	t->next = *tp;
+	rcu_assign_pointer(t->next, rtnl_dereference(*tp));
 	rcu_assign_pointer(*tp, t);
-	spin_unlock_bh(&ipip6_lock);
 }
 
 static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn)
@@ -187,17 +213,20 @@
 #endif
 }
 
-static struct ip_tunnel * ipip6_tunnel_locate(struct net *net,
+static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
 		struct ip_tunnel_parm *parms, int create)
 {
 	__be32 remote = parms->iph.daddr;
 	__be32 local = parms->iph.saddr;
-	struct ip_tunnel *t, **tp, *nt;
+	struct ip_tunnel *t, *nt;
+	struct ip_tunnel __rcu **tp;
 	struct net_device *dev;
 	char name[IFNAMSIZ];
 	struct sit_net *sitn = net_generic(net, sit_net_id);
 
-	for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) {
+	for (tp = __ipip6_bucket(sitn, parms);
+	    (t = rtnl_dereference(*tp)) != NULL;
+	     tp = &t->next) {
 		if (local == t->parms.iph.saddr &&
 		    remote == t->parms.iph.daddr &&
 		    parms->link == t->parms.link) {
@@ -213,7 +242,7 @@
 	if (parms->name[0])
 		strlcpy(name, parms->name, IFNAMSIZ);
 	else
-		sprintf(name, "sit%%d");
+		strcpy(name, "sit%d");
 
 	dev = alloc_netdev(sizeof(*t), name, ipip6_tunnel_setup);
 	if (dev == NULL)
@@ -229,7 +258,8 @@
 	nt = netdev_priv(dev);
 
 	nt->parms = *parms;
-	ipip6_tunnel_init(dev);
+	if (ipip6_tunnel_init(dev) < 0)
+		goto failed_free;
 	ipip6_tunnel_clone_6rd(dev, sitn);
 
 	if (parms->i_flags & SIT_ISATAP)
@@ -244,7 +274,7 @@
 	return nt;
 
 failed_free:
-	free_netdev(dev);
+	ipip6_dev_free(dev);
 failed:
 	return NULL;
 }
@@ -340,7 +370,7 @@
 
 	ASSERT_RTNL();
 
-	for (p = t->prl; p; p = p->next) {
+	for (p = rtnl_dereference(t->prl); p; p = rtnl_dereference(p->next)) {
 		if (p->addr == a->addr) {
 			if (chg) {
 				p->flags = a->flags;
@@ -451,15 +481,12 @@
 	struct sit_net *sitn = net_generic(net, sit_net_id);
 
 	if (dev == sitn->fb_tunnel_dev) {
-		spin_lock_bh(&ipip6_lock);
-		sitn->tunnels_wc[0] = NULL;
-		spin_unlock_bh(&ipip6_lock);
-		dev_put(dev);
+		rcu_assign_pointer(sitn->tunnels_wc[0], NULL);
 	} else {
 		ipip6_tunnel_unlink(sitn, netdev_priv(dev));
 		ipip6_tunnel_del_prl(netdev_priv(dev), NULL);
-		dev_put(dev);
 	}
+	dev_put(dev);
 }
 
 
@@ -548,6 +575,8 @@
 	tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
 				     iph->saddr, iph->daddr);
 	if (tunnel != NULL) {
+		struct pcpu_tstats *tstats;
+
 		secpath_reset(skb);
 		skb->mac_header = skb->network_header;
 		skb_reset_network_header(skb);
@@ -563,10 +592,16 @@
 			return 0;
 		}
 
-		skb_tunnel_rx(skb, tunnel->dev);
+		tstats = this_cpu_ptr(tunnel->dev->tstats);
+		tstats->rx_packets++;
+		tstats->rx_bytes += skb->len;
+
+		__skb_tunnel_rx(skb, tunnel->dev);
 
 		ipip6_ecn_decapsulate(iph, skb);
+
 		netif_rx(skb);
+
 		rcu_read_unlock();
 		return 0;
 	}
@@ -590,7 +625,7 @@
 #ifdef CONFIG_IPV6_SIT_6RD
 	if (ipv6_prefix_equal(v6dst, &tunnel->ip6rd.prefix,
 			      tunnel->ip6rd.prefixlen)) {
-		unsigned pbw0, pbi0;
+		unsigned int pbw0, pbi0;
 		int pbi1;
 		u32 d;
 
@@ -625,14 +660,13 @@
 				     struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
-	struct net_device_stats *stats = &dev->stats;
-	struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+	struct pcpu_tstats *tstats;
 	struct iphdr  *tiph = &tunnel->parms.iph;
 	struct ipv6hdr *iph6 = ipv6_hdr(skb);
 	u8     tos = tunnel->parms.iph.tos;
 	__be16 df = tiph->frag_off;
 	struct rtable *rt;     			/* Route to the other host */
-	struct net_device *tdev;			/* Device to other host */
+	struct net_device *tdev;		/* Device to other host */
 	struct iphdr  *iph;			/* Our new IP header */
 	unsigned int max_headroom;		/* The extra header space needed */
 	__be32 dst = tiph->daddr;
@@ -703,20 +737,20 @@
 				    .oif = tunnel->parms.link,
 				    .proto = IPPROTO_IPV6 };
 		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
-			stats->tx_carrier_errors++;
+			dev->stats.tx_carrier_errors++;
 			goto tx_error_icmp;
 		}
 	}
 	if (rt->rt_type != RTN_UNICAST) {
 		ip_rt_put(rt);
-		stats->tx_carrier_errors++;
+		dev->stats.tx_carrier_errors++;
 		goto tx_error_icmp;
 	}
 	tdev = rt->dst.dev;
 
 	if (tdev == dev) {
 		ip_rt_put(rt);
-		stats->collisions++;
+		dev->stats.collisions++;
 		goto tx_error;
 	}
 
@@ -724,7 +758,7 @@
 		mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr);
 
 		if (mtu < 68) {
-			stats->collisions++;
+			dev->stats.collisions++;
 			ip_rt_put(rt);
 			goto tx_error;
 		}
@@ -763,7 +797,7 @@
 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 		if (!new_skb) {
 			ip_rt_put(rt);
-			txq->tx_dropped++;
+			dev->stats.tx_dropped++;
 			dev_kfree_skb(skb);
 			return NETDEV_TX_OK;
 		}
@@ -799,14 +833,14 @@
 		iph->ttl	=	iph6->hop_limit;
 
 	nf_reset(skb);
-
-	IPTUNNEL_XMIT();
+	tstats = this_cpu_ptr(dev->tstats);
+	__IPTUNNEL_XMIT(tstats, &dev->stats);
 	return NETDEV_TX_OK;
 
 tx_error_icmp:
 	dst_link_failure(skb);
 tx_error:
-	stats->tx_errors++;
+	dev->stats.tx_errors++;
 	dev_kfree_skb(skb);
 	return NETDEV_TX_OK;
 }
@@ -1083,12 +1117,19 @@
 	.ndo_start_xmit	= ipip6_tunnel_xmit,
 	.ndo_do_ioctl	= ipip6_tunnel_ioctl,
 	.ndo_change_mtu	= ipip6_tunnel_change_mtu,
+	.ndo_get_stats	= ipip6_get_stats,
 };
 
+static void ipip6_dev_free(struct net_device *dev)
+{
+	free_percpu(dev->tstats);
+	free_netdev(dev);
+}
+
 static void ipip6_tunnel_setup(struct net_device *dev)
 {
 	dev->netdev_ops		= &ipip6_netdev_ops;
-	dev->destructor 	= free_netdev;
+	dev->destructor 	= ipip6_dev_free;
 
 	dev->type		= ARPHRD_SIT;
 	dev->hard_header_len 	= LL_MAX_HEADER + sizeof(struct iphdr);
@@ -1098,9 +1139,10 @@
 	dev->iflink		= 0;
 	dev->addr_len		= 4;
 	dev->features		|= NETIF_F_NETNS_LOCAL;
+	dev->features		|= NETIF_F_LLTX;
 }
 
-static void ipip6_tunnel_init(struct net_device *dev)
+static int ipip6_tunnel_init(struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 
@@ -1111,9 +1153,14 @@
 	memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
 
 	ipip6_tunnel_bind_dev(dev);
+	dev->tstats = alloc_percpu(struct pcpu_tstats);
+	if (!dev->tstats)
+		return -ENOMEM;
+
+	return 0;
 }
 
-static void __net_init ipip6_fb_tunnel_init(struct net_device *dev)
+static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	struct iphdr *iph = &tunnel->parms.iph;
@@ -1128,11 +1175,15 @@
 	iph->ihl		= 5;
 	iph->ttl		= 64;
 
+	dev->tstats = alloc_percpu(struct pcpu_tstats);
+	if (!dev->tstats)
+		return -ENOMEM;
 	dev_hold(dev);
 	sitn->tunnels_wc[0]	= tunnel;
+	return 0;
 }
 
-static struct xfrm_tunnel sit_handler = {
+static struct xfrm_tunnel sit_handler __read_mostly = {
 	.handler	=	ipip6_rcv,
 	.err_handler	=	ipip6_err,
 	.priority	=	1,
@@ -1173,7 +1224,10 @@
 	}
 	dev_net_set(sitn->fb_tunnel_dev, net);
 
-	ipip6_fb_tunnel_init(sitn->fb_tunnel_dev);
+	err = ipip6_fb_tunnel_init(sitn->fb_tunnel_dev);
+	if (err)
+		goto err_dev_free;
+
 	ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn);
 
 	if ((err = register_netdev(sitn->fb_tunnel_dev)))
@@ -1183,7 +1237,8 @@
 
 err_reg_dev:
 	dev_put(sitn->fb_tunnel_dev);
-	free_netdev(sitn->fb_tunnel_dev);
+err_dev_free:
+	ipip6_dev_free(sitn->fb_tunnel_dev);
 err_alloc_dev:
 	return err;
 }
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index fe6d404..7e41e2c 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -139,7 +139,7 @@
 		return -EINVAL;
 
 	if (usin->sin6_family != AF_INET6)
-		return(-EAFNOSUPPORT);
+		return -EAFNOSUPPORT;
 
 	memset(&fl, 0, sizeof(fl));
 
@@ -1409,7 +1409,7 @@
 
 	newsk = tcp_create_openreq_child(sk, req, skb);
 	if (newsk == NULL)
-		goto out;
+		goto out_nonewsk;
 
 	/*
 	 * No need to charge this sock to the relevant IPv6 refcnt debug socks
@@ -1497,18 +1497,22 @@
 	}
 #endif
 
+	if (__inet_inherit_port(sk, newsk) < 0) {
+		sock_put(newsk);
+		goto out;
+	}
 	__inet6_hash(newsk, NULL);
-	__inet_inherit_port(sk, newsk);
 
 	return newsk;
 
 out_overflow:
 	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
-out:
-	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
+out_nonewsk:
 	if (opt && opt != np->opt)
 		sock_kfree_s(sk, opt, opt->tot_len);
 	dst_release(dst);
+out:
+	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
 	return NULL;
 }
 
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
index fc3c86a..d986472 100644
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -30,8 +30,8 @@
 #include <net/protocol.h>
 #include <net/xfrm.h>
 
-static struct xfrm6_tunnel *tunnel6_handlers;
-static struct xfrm6_tunnel *tunnel46_handlers;
+static struct xfrm6_tunnel *tunnel6_handlers __read_mostly;
+static struct xfrm6_tunnel *tunnel46_handlers __read_mostly;
 static DEFINE_MUTEX(tunnel6_mutex);
 
 int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family)
@@ -51,7 +51,7 @@
 	}
 
 	handler->next = *pprev;
-	*pprev = handler;
+	rcu_assign_pointer(*pprev, handler);
 
 	ret = 0;
 
@@ -88,6 +88,11 @@
 
 EXPORT_SYMBOL(xfrm6_tunnel_deregister);
 
+#define for_each_tunnel_rcu(head, handler)		\
+	for (handler = rcu_dereference(head);		\
+	     handler != NULL;				\
+	     handler = rcu_dereference(handler->next))	\
+
 static int tunnel6_rcv(struct sk_buff *skb)
 {
 	struct xfrm6_tunnel *handler;
@@ -95,7 +100,7 @@
 	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
 		goto drop;
 
-	for (handler = tunnel6_handlers; handler; handler = handler->next)
+	for_each_tunnel_rcu(tunnel6_handlers, handler)
 		if (!handler->handler(skb))
 			return 0;
 
@@ -113,7 +118,7 @@
 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 		goto drop;
 
-	for (handler = tunnel46_handlers; handler; handler = handler->next)
+	for_each_tunnel_rcu(tunnel46_handlers, handler)
 		if (!handler->handler(skb))
 			return 0;
 
@@ -129,7 +134,7 @@
 {
 	struct xfrm6_tunnel *handler;
 
-	for (handler = tunnel6_handlers; handler; handler = handler->next)
+	for_each_tunnel_rcu(tunnel6_handlers, handler)
 		if (!handler->err_handler(skb, opt, type, code, offset, info))
 			break;
 }
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 5acb356..c84dad4 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -122,8 +122,8 @@
 
 static inline int compute_score(struct sock *sk, struct net *net,
 				unsigned short hnum,
-				struct in6_addr *saddr, __be16 sport,
-				struct in6_addr *daddr, __be16 dport,
+				const struct in6_addr *saddr, __be16 sport,
+				const struct in6_addr *daddr, __be16 dport,
 				int dif)
 {
 	int score = -1;
@@ -239,8 +239,8 @@
 }
 
 static struct sock *__udp6_lib_lookup(struct net *net,
-				      struct in6_addr *saddr, __be16 sport,
-				      struct in6_addr *daddr, __be16 dport,
+				      const struct in6_addr *saddr, __be16 sport,
+				      const struct in6_addr *daddr, __be16 dport,
 				      int dif, struct udp_table *udptable)
 {
 	struct sock *sk, *result;
@@ -320,6 +320,14 @@
 				 udptable);
 }
 
+struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
+			     const struct in6_addr *daddr, __be16 dport, int dif)
+{
+	return __udp6_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table);
+}
+EXPORT_SYMBOL_GPL(udp6_lib_lookup);
+
+
 /*
  * 	This should be easy, if there is something there we
  * 	return it, otherwise we block.
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 6baeabb..7e74023 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -199,7 +199,7 @@
 	struct net *net = container_of(ops, struct net, xfrm.xfrm6_dst_ops);
 
 	xfrm6_policy_afinfo.garbage_collect(net);
-	return (atomic_read(&ops->entries) > ops->gc_thresh * 2);
+	return dst_entries_get_fast(ops) > ops->gc_thresh * 2;
 }
 
 static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu)
@@ -255,7 +255,6 @@
 	.ifdown =		xfrm6_dst_ifdown,
 	.local_out =		__ip6_local_out,
 	.gc_thresh =		1024,
-	.entries =		ATOMIC_INIT(0),
 };
 
 static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
@@ -312,11 +311,13 @@
 	 */
 	gc_thresh = FIB6_TABLE_HASHSZ * 8;
 	xfrm6_dst_ops.gc_thresh = (gc_thresh < 1024) ? 1024 : gc_thresh;
+	dst_entries_init(&xfrm6_dst_ops);
 
 	ret = xfrm6_policy_init();
-	if (ret)
+	if (ret) {
+		dst_entries_destroy(&xfrm6_dst_ops);
 		goto out;
-
+	}
 	ret = xfrm6_state_init();
 	if (ret)
 		goto out_policy;
@@ -341,4 +342,5 @@
 	//xfrm6_input_fini();
 	xfrm6_policy_fini();
 	xfrm6_state_fini();
+	dst_entries_destroy(&xfrm6_dst_ops);
 }
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index f417b77..a67575d 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -20,23 +20,27 @@
 #include <net/addrconf.h>
 
 static void
-__xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
-		     struct xfrm_tmpl *tmpl,
-		     xfrm_address_t *daddr, xfrm_address_t *saddr)
+__xfrm6_init_tempsel(struct xfrm_selector *sel, struct flowi *fl)
 {
 	/* Initialize temporary selector matching only
 	 * to current session. */
-	ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
-	ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
-	x->sel.dport = xfrm_flowi_dport(fl);
-	x->sel.dport_mask = htons(0xffff);
-	x->sel.sport = xfrm_flowi_sport(fl);
-	x->sel.sport_mask = htons(0xffff);
-	x->sel.family = AF_INET6;
-	x->sel.prefixlen_d = 128;
-	x->sel.prefixlen_s = 128;
-	x->sel.proto = fl->proto;
-	x->sel.ifindex = fl->oif;
+	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);
+	sel->dport_mask = htons(0xffff);
+	sel->sport = xfrm_flowi_sport(fl);
+	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;
+}
+
+static void
+xfrm6_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl,
+		   xfrm_address_t *daddr, xfrm_address_t *saddr)
+{
 	x->id = tmpl->id;
 	if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
 		memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr));
@@ -168,6 +172,7 @@
 	.eth_proto		= htons(ETH_P_IPV6),
 	.owner			= THIS_MODULE,
 	.init_tempsel		= __xfrm6_init_tempsel,
+	.init_temprop		= xfrm6_init_temprop,
 	.tmpl_sort		= __xfrm6_tmpl_sort,
 	.state_sort		= __xfrm6_state_sort,
 	.output			= xfrm6_output,
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 2ce3a82..2969cad 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -199,7 +199,7 @@
 			container_of(head, struct xfrm6_tunnel_spi, rcu_head));
 }
 
-void xfrm6_tunnel_free_spi(struct net *net, xfrm_address_t *saddr)
+static void xfrm6_tunnel_free_spi(struct net *net, xfrm_address_t *saddr)
 {
 	struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net);
 	struct xfrm6_tunnel_spi *x6spi;
@@ -223,8 +223,6 @@
 	spin_unlock_bh(&xfrm6_tunnel_spi_lock);
 }
 
-EXPORT_SYMBOL(xfrm6_tunnel_free_spi);
-
 static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	skb_push(skb, -skb_network_offset(skb));
@@ -317,13 +315,13 @@
 	.output		= xfrm6_tunnel_output,
 };
 
-static struct xfrm6_tunnel xfrm6_tunnel_handler = {
+static struct xfrm6_tunnel xfrm6_tunnel_handler __read_mostly = {
 	.handler	= xfrm6_tunnel_rcv,
 	.err_handler	= xfrm6_tunnel_err,
 	.priority	= 2,
 };
 
-static struct xfrm6_tunnel xfrm46_tunnel_handler = {
+static struct xfrm6_tunnel xfrm46_tunnel_handler __read_mostly = {
 	.handler	= xfrm6_tunnel_rcv,
 	.err_handler	= xfrm6_tunnel_err,
 	.priority	= 2,
diff --git a/net/ipx/Kconfig b/net/ipx/Kconfig
index e9ad006..02549cb 100644
--- a/net/ipx/Kconfig
+++ b/net/ipx/Kconfig
@@ -3,6 +3,7 @@
 #
 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/irda/af_irda.c b/net/irda/af_irda.c
index fd55b51..7f097989 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -573,9 +573,9 @@
 		/* Requested object/attribute doesn't exist */
 		if((self->errno == IAS_CLASS_UNKNOWN) ||
 		   (self->errno == IAS_ATTRIB_UNKNOWN))
-			return (-EADDRNOTAVAIL);
+			return -EADDRNOTAVAIL;
 		else
-			return (-EHOSTUNREACH);
+			return -EHOSTUNREACH;
 	}
 
 	/* Get the remote TSAP selector */
@@ -663,7 +663,7 @@
 					   __func__, name);
 				self->daddr = DEV_ADDR_ANY;
 				kfree(discoveries);
-				return(-ENOTUNIQ);
+				return -ENOTUNIQ;
 			}
 			/* First time we found that one, save it ! */
 			daddr = self->daddr;
@@ -677,7 +677,7 @@
 			IRDA_DEBUG(0, "%s(), unexpected IAS query failure\n", __func__);
 			self->daddr = DEV_ADDR_ANY;
 			kfree(discoveries);
-			return(-EHOSTUNREACH);
+			return -EHOSTUNREACH;
 			break;
 		}
 	}
@@ -689,7 +689,7 @@
 		IRDA_DEBUG(1, "%s(), cannot discover service ''%s'' in any device !!!\n",
 			   __func__, name);
 		self->daddr = DEV_ADDR_ANY;
-		return(-EADDRNOTAVAIL);
+		return -EADDRNOTAVAIL;
 	}
 
 	/* Revert back to discovered device & service */
@@ -715,14 +715,11 @@
 	struct sockaddr_irda saddr;
 	struct sock *sk = sock->sk;
 	struct irda_sock *self = irda_sk(sk);
-	int err;
 
-	lock_kernel();
 	memset(&saddr, 0, sizeof(saddr));
 	if (peer) {
-		err  = -ENOTCONN;
 		if (sk->sk_state != TCP_ESTABLISHED)
-			goto out;
+			return -ENOTCONN;
 
 		saddr.sir_family = AF_IRDA;
 		saddr.sir_lsap_sel = self->dtsap_sel;
@@ -739,10 +736,8 @@
 	/* uaddr_len come to us uninitialised */
 	*uaddr_len = sizeof (struct sockaddr_irda);
 	memcpy(uaddr, &saddr, *uaddr_len);
-	err = 0;
-out:
-	unlock_kernel();
-	return err;
+
+	return 0;
 }
 
 /*
@@ -758,7 +753,8 @@
 
 	IRDA_DEBUG(2, "%s()\n", __func__);
 
-	lock_kernel();
+	lock_sock(sk);
+
 	if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) &&
 	    (sk->sk_type != SOCK_DGRAM))
 		goto out;
@@ -770,7 +766,7 @@
 		err = 0;
 	}
 out:
-	unlock_kernel();
+	release_sock(sk);
 
 	return err;
 }
@@ -793,7 +789,7 @@
 	if (addr_len != sizeof(struct sockaddr_irda))
 		return -EINVAL;
 
-	lock_kernel();
+	lock_sock(sk);
 #ifdef CONFIG_IRDA_ULTRA
 	/* Special care for Ultra sockets */
 	if ((sk->sk_type == SOCK_DGRAM) &&
@@ -836,7 +832,7 @@
 
 	err = 0;
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return err;
 }
 
@@ -856,12 +852,13 @@
 
 	IRDA_DEBUG(2, "%s()\n", __func__);
 
-	lock_kernel();
 	err = irda_create(sock_net(sk), newsock, sk->sk_protocol, 0);
 	if (err)
-		goto out;
+		return err;
 
 	err = -EINVAL;
+
+	lock_sock(sk);
 	if (sock->state != SS_UNCONNECTED)
 		goto out;
 
@@ -947,7 +944,7 @@
 	irda_connect_response(new);
 	err = 0;
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return err;
 }
 
@@ -981,7 +978,7 @@
 
 	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
 
-	lock_kernel();
+	lock_sock(sk);
 	/* Don't allow connect for Ultra sockets */
 	err = -ESOCKTNOSUPPORT;
 	if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA))
@@ -1072,6 +1069,8 @@
 
 	if (sk->sk_state != TCP_ESTABLISHED) {
 		sock->state = SS_UNCONNECTED;
+		if (sk->sk_prot->disconnect(sk, flags))
+			sock->state = SS_DISCONNECTING;
 		err = sock_error(sk);
 		if (!err)
 			err = -ECONNRESET;
@@ -1084,7 +1083,7 @@
 	self->saddr = irttp_get_saddr(self->tsap);
 	err = 0;
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return err;
 }
 
@@ -1231,7 +1230,6 @@
 	if (sk == NULL)
 		return 0;
 
-	lock_kernel();
 	lock_sock(sk);
 	sk->sk_state       = TCP_CLOSE;
 	sk->sk_shutdown   |= SEND_SHUTDOWN;
@@ -1250,7 +1248,6 @@
 	/* Destroy networking socket if we are the last reference on it,
 	 * i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */
 	sock_put(sk);
-	unlock_kernel();
 
 	/* Notes on socket locking and deallocation... - Jean II
 	 * In theory we should put pairs of sock_hold() / sock_put() to
@@ -1298,7 +1295,6 @@
 
 	IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
 
-	lock_kernel();
 	/* Note : socket.c set MSG_EOR on SEQPACKET sockets */
 	if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT |
 			       MSG_NOSIGNAL)) {
@@ -1306,6 +1302,8 @@
 		goto out;
 	}
 
+	lock_sock(sk);
+
 	if (sk->sk_shutdown & SEND_SHUTDOWN)
 		goto out_err;
 
@@ -1361,14 +1359,14 @@
 		goto out_err;
 	}
 
-	unlock_kernel();
+	release_sock(sk);
 	/* Tell client how much data we actually sent */
 	return len;
 
 out_err:
 	err = sk_stream_error(sk, msg->msg_flags, err);
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return err;
 
 }
@@ -1390,14 +1388,10 @@
 
 	IRDA_DEBUG(4, "%s()\n", __func__);
 
-	lock_kernel();
-	if ((err = sock_error(sk)) < 0)
-		goto out;
-
 	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
 				flags & MSG_DONTWAIT, &err);
 	if (!skb)
-		goto out;
+		return err;
 
 	skb_reset_transport_header(skb);
 	copied = skb->len;
@@ -1425,12 +1419,8 @@
 			irttp_flow_request(self->tsap, FLOW_START);
 		}
 	}
-	unlock_kernel();
-	return copied;
 
-out:
-	unlock_kernel();
-	return err;
+	return copied;
 }
 
 /*
@@ -1448,17 +1438,15 @@
 
 	IRDA_DEBUG(3, "%s()\n", __func__);
 
-	lock_kernel();
 	if ((err = sock_error(sk)) < 0)
-		goto out;
+		return err;
 
-	err = -EINVAL;
 	if (sock->flags & __SO_ACCEPTCON)
-		goto out;
+		return -EINVAL;
 
 	err =-EOPNOTSUPP;
 	if (flags & MSG_OOB)
-		goto out;
+		return -EOPNOTSUPP;
 
 	err = 0;
 	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
@@ -1500,7 +1488,7 @@
 			finish_wait(sk_sleep(sk), &wait);
 
 			if (err)
-				goto out;
+				return err;
 			if (sk->sk_shutdown & RCV_SHUTDOWN)
 				break;
 
@@ -1553,9 +1541,7 @@
 		}
 	}
 
-out:
-	unlock_kernel();
-	return err ? : copied;
+	return copied;
 }
 
 /*
@@ -1573,13 +1559,12 @@
 	struct sk_buff *skb;
 	int err;
 
-	lock_kernel();
-
 	IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
 
-	err = -EINVAL;
 	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
-		goto out;
+		return -EINVAL;
+
+	lock_sock(sk);
 
 	if (sk->sk_shutdown & SEND_SHUTDOWN) {
 		send_sig(SIGPIPE, current, 0);
@@ -1630,10 +1615,12 @@
 		IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
 		goto out;
 	}
-	unlock_kernel();
+
+	release_sock(sk);
 	return len;
+
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return err;
 }
 
@@ -1656,10 +1643,11 @@
 
 	IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
 
-	lock_kernel();
 	err = -EINVAL;
 	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
-		goto out;
+		return -EINVAL;
+
+	lock_sock(sk);
 
 	err = -EPIPE;
 	if (sk->sk_shutdown & SEND_SHUTDOWN) {
@@ -1732,7 +1720,7 @@
 	if (err)
 		IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return err ? : len;
 }
 #endif /* CONFIG_IRDA_ULTRA */
@@ -1747,7 +1735,7 @@
 
 	IRDA_DEBUG(1, "%s(%p)\n", __func__, self);
 
-	lock_kernel();
+	lock_sock(sk);
 
 	sk->sk_state       = TCP_CLOSE;
 	sk->sk_shutdown   |= SEND_SHUTDOWN;
@@ -1769,7 +1757,7 @@
 	self->daddr = DEV_ADDR_ANY;	/* Until we get re-connected */
 	self->saddr = 0x0;		/* so IrLMP assign us any link */
 
-	unlock_kernel();
+	release_sock(sk);
 
 	return 0;
 }
@@ -1786,7 +1774,6 @@
 
 	IRDA_DEBUG(4, "%s()\n", __func__);
 
-	lock_kernel();
 	poll_wait(file, sk_sleep(sk), wait);
 	mask = 0;
 
@@ -1834,22 +1821,10 @@
 	default:
 		break;
 	}
-	unlock_kernel();
+
 	return mask;
 }
 
-static unsigned int irda_datagram_poll(struct file *file, struct socket *sock,
-			   poll_table *wait)
-{
-	int err;
-
-	lock_kernel();
-	err = datagram_poll(file, sock, wait);
-	unlock_kernel();
-
-	return err;
-}
-
 /*
  * Function irda_ioctl (sock, cmd, arg)
  */
@@ -1860,7 +1835,6 @@
 
 	IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd);
 
-	lock_kernel();
 	err = -EINVAL;
 	switch (cmd) {
 	case TIOCOUTQ: {
@@ -1903,7 +1877,6 @@
 		IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__);
 		err = -ENOIOCTLCMD;
 	}
-	unlock_kernel();
 
 	return err;
 }
@@ -1927,7 +1900,7 @@
  *    Set some options for the socket
  *
  */
-static int __irda_setsockopt(struct socket *sock, int level, int optname,
+static int irda_setsockopt(struct socket *sock, int level, int optname,
 			   char __user *optval, unsigned int optlen)
 {
 	struct sock *sk = sock->sk;
@@ -1935,13 +1908,15 @@
 	struct irda_ias_set    *ias_opt;
 	struct ias_object      *ias_obj;
 	struct ias_attrib *	ias_attr;	/* Attribute in IAS object */
-	int opt, free_ias = 0;
+	int opt, free_ias = 0, err = 0;
 
 	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
 
 	if (level != SOL_IRLMP)
 		return -ENOPROTOOPT;
 
+	lock_sock(sk);
+
 	switch (optname) {
 	case IRLMP_IAS_SET:
 		/* The user want to add an attribute to an existing IAS object
@@ -1951,17 +1926,22 @@
 		 * create the right attribute...
 		 */
 
-		if (optlen != sizeof(struct irda_ias_set))
-			return -EINVAL;
+		if (optlen != sizeof(struct irda_ias_set)) {
+			err = -EINVAL;
+			goto out;
+		}
 
 		ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC);
-		if (ias_opt == NULL)
-			return -ENOMEM;
+		if (ias_opt == NULL) {
+			err = -ENOMEM;
+			goto out;
+		}
 
 		/* Copy query to the driver. */
 		if (copy_from_user(ias_opt, optval, optlen)) {
 			kfree(ias_opt);
-			return -EFAULT;
+			err = -EFAULT;
+			goto out;
 		}
 
 		/* Find the object we target.
@@ -1971,7 +1951,8 @@
 		if(ias_opt->irda_class_name[0] == '\0') {
 			if(self->ias_obj == NULL) {
 				kfree(ias_opt);
-				return -EINVAL;
+				err = -EINVAL;
+				goto out;
 			}
 			ias_obj = self->ias_obj;
 		} else
@@ -1983,7 +1964,8 @@
 		if((!capable(CAP_NET_ADMIN)) &&
 		   ((ias_obj == NULL) || (ias_obj != self->ias_obj))) {
 			kfree(ias_opt);
-			return -EPERM;
+			err = -EPERM;
+			goto out;
 		}
 
 		/* If the object doesn't exist, create it */
@@ -1993,7 +1975,8 @@
 						   jiffies);
 			if (ias_obj == NULL) {
 				kfree(ias_opt);
-				return -ENOMEM;
+				err = -ENOMEM;
+				goto out;
 			}
 			free_ias = 1;
 		}
@@ -2005,7 +1988,8 @@
 				kfree(ias_obj->name);
 				kfree(ias_obj);
 			}
-			return -EINVAL;
+			err = -EINVAL;
+			goto out;
 		}
 
 		/* Look at the type */
@@ -2028,7 +2012,8 @@
 					kfree(ias_obj);
 				}
 
-				return -EINVAL;
+				err = -EINVAL;
+				goto out;
 			}
 			/* Add an octet sequence attribute */
 			irias_add_octseq_attrib(
@@ -2060,7 +2045,8 @@
 				kfree(ias_obj->name);
 				kfree(ias_obj);
 			}
-			return -EINVAL;
+			err = -EINVAL;
+			goto out;
 		}
 		irias_insert_object(ias_obj);
 		kfree(ias_opt);
@@ -2071,17 +2057,22 @@
 		 * object is not owned by the kernel and delete it.
 		 */
 
-		if (optlen != sizeof(struct irda_ias_set))
-			return -EINVAL;
+		if (optlen != sizeof(struct irda_ias_set)) {
+			err = -EINVAL;
+			goto out;
+		}
 
 		ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC);
-		if (ias_opt == NULL)
-			return -ENOMEM;
+		if (ias_opt == NULL) {
+			err = -ENOMEM;
+			goto out;
+		}
 
 		/* Copy query to the driver. */
 		if (copy_from_user(ias_opt, optval, optlen)) {
 			kfree(ias_opt);
-			return -EFAULT;
+			err = -EFAULT;
+			goto out;
 		}
 
 		/* Find the object we target.
@@ -2094,7 +2085,8 @@
 			ias_obj = irias_find_object(ias_opt->irda_class_name);
 		if(ias_obj == (struct ias_object *) NULL) {
 			kfree(ias_opt);
-			return -EINVAL;
+			err = -EINVAL;
+			goto out;
 		}
 
 		/* Only ROOT can mess with the global IAS database.
@@ -2103,7 +2095,8 @@
 		if((!capable(CAP_NET_ADMIN)) &&
 		   ((ias_obj == NULL) || (ias_obj != self->ias_obj))) {
 			kfree(ias_opt);
-			return -EPERM;
+			err = -EPERM;
+			goto out;
 		}
 
 		/* Find the attribute (in the object) we target */
@@ -2111,14 +2104,16 @@
 					     ias_opt->irda_attrib_name);
 		if(ias_attr == (struct ias_attrib *) NULL) {
 			kfree(ias_opt);
-			return -EINVAL;
+			err = -EINVAL;
+			goto out;
 		}
 
 		/* Check is the user space own the object */
 		if(ias_attr->value->owner != IAS_USER_ATTR) {
 			IRDA_DEBUG(1, "%s(), attempting to delete a kernel attribute\n", __func__);
 			kfree(ias_opt);
-			return -EPERM;
+			err = -EPERM;
+			goto out;
 		}
 
 		/* Remove the attribute (and maybe the object) */
@@ -2126,11 +2121,15 @@
 		kfree(ias_opt);
 		break;
 	case IRLMP_MAX_SDU_SIZE:
-		if (optlen < sizeof(int))
-			return -EINVAL;
+		if (optlen < sizeof(int)) {
+			err = -EINVAL;
+			goto out;
+		}
 
-		if (get_user(opt, (int __user *)optval))
-			return -EFAULT;
+		if (get_user(opt, (int __user *)optval)) {
+			err = -EFAULT;
+			goto out;
+		}
 
 		/* Only possible for a seqpacket service (TTP with SAR) */
 		if (sk->sk_type != SOCK_SEQPACKET) {
@@ -2140,16 +2139,21 @@
 		} else {
 			IRDA_WARNING("%s: not allowed to set MAXSDUSIZE for this socket type!\n",
 				     __func__);
-			return -ENOPROTOOPT;
+			err = -ENOPROTOOPT;
+			goto out;
 		}
 		break;
 	case IRLMP_HINTS_SET:
-		if (optlen < sizeof(int))
-			return -EINVAL;
+		if (optlen < sizeof(int)) {
+			err = -EINVAL;
+			goto out;
+		}
 
 		/* The input is really a (__u8 hints[2]), easier as an int */
-		if (get_user(opt, (int __user *)optval))
-			return -EFAULT;
+		if (get_user(opt, (int __user *)optval)) {
+			err = -EFAULT;
+			goto out;
+		}
 
 		/* Unregister any old registration */
 		if (self->skey)
@@ -2163,12 +2167,16 @@
 		 * making a discovery (nodes which don't match any hint
 		 * bit in the mask are not reported).
 		 */
-		if (optlen < sizeof(int))
-			return -EINVAL;
+		if (optlen < sizeof(int)) {
+			err = -EINVAL;
+			goto out;
+		}
 
 		/* The input is really a (__u8 hints[2]), easier as an int */
-		if (get_user(opt, (int __user *)optval))
-			return -EFAULT;
+		if (get_user(opt, (int __user *)optval)) {
+			err = -EFAULT;
+			goto out;
+		}
 
 		/* Set the new hint mask */
 		self->mask.word = (__u16) opt;
@@ -2180,19 +2188,12 @@
 
 		break;
 	default:
-		return -ENOPROTOOPT;
+		err = -ENOPROTOOPT;
+		break;
 	}
-	return 0;
-}
 
-static int irda_setsockopt(struct socket *sock, int level, int optname,
-			   char __user *optval, unsigned int optlen)
-{
-	int err;
-
-	lock_kernel();
-	err = __irda_setsockopt(sock, level, optname, optval, optlen);
-	unlock_kernel();
+out:
+	release_sock(sk);
 
 	return err;
 }
@@ -2249,7 +2250,7 @@
 /*
  * Function irda_getsockopt (sock, level, optname, optval, optlen)
  */
-static int __irda_getsockopt(struct socket *sock, int level, int optname,
+static int irda_getsockopt(struct socket *sock, int level, int optname,
 			   char __user *optval, int __user *optlen)
 {
 	struct sock *sk = sock->sk;
@@ -2262,7 +2263,7 @@
 	int daddr = DEV_ADDR_ANY;	/* Dest address for IAS queries */
 	int val = 0;
 	int len = 0;
-	int err;
+	int err = 0;
 	int offset, total;
 
 	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
@@ -2276,15 +2277,18 @@
 	if(len < 0)
 		return -EINVAL;
 
+	lock_sock(sk);
+
 	switch (optname) {
 	case IRLMP_ENUMDEVICES:
 		/* Ask lmp for the current discovery log */
 		discoveries = irlmp_get_discoveries(&list.len, self->mask.word,
 						    self->nslots);
 		/* Check if the we got some results */
-		if (discoveries == NULL)
-			return -EAGAIN;		/* Didn't find any devices */
-		err = 0;
+		if (discoveries == NULL) {
+			err = -EAGAIN;
+			goto out;		/* Didn't find any devices */
+		}
 
 		/* Write total list length back to client */
 		if (copy_to_user(optval, &list,
@@ -2297,8 +2301,7 @@
 			sizeof(struct irda_device_info);
 
 		/* Copy the list itself - watch for overflow */
-		if(list.len > 2048)
-		{
+		if (list.len > 2048) {
 			err = -EINVAL;
 			goto bed;
 		}
@@ -2314,17 +2317,20 @@
 bed:
 		/* Free up our buffer */
 		kfree(discoveries);
-		if (err)
-			return err;
 		break;
 	case IRLMP_MAX_SDU_SIZE:
 		val = self->max_data_size;
 		len = sizeof(int);
-		if (put_user(len, optlen))
-			return -EFAULT;
+		if (put_user(len, optlen)) {
+			err = -EFAULT;
+			goto out;
+		}
 
-		if (copy_to_user(optval, &val, len))
-			return -EFAULT;
+		if (copy_to_user(optval, &val, len)) {
+			err = -EFAULT;
+			goto out;
+		}
+
 		break;
 	case IRLMP_IAS_GET:
 		/* The user want an object from our local IAS database.
@@ -2332,17 +2338,22 @@
 		 * that we found */
 
 		/* Check that the user has allocated the right space for us */
-		if (len != sizeof(struct irda_ias_set))
-			return -EINVAL;
+		if (len != sizeof(struct irda_ias_set)) {
+			err = -EINVAL;
+			goto out;
+		}
 
 		ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC);
-		if (ias_opt == NULL)
-			return -ENOMEM;
+		if (ias_opt == NULL) {
+			err = -ENOMEM;
+			goto out;
+		}
 
 		/* Copy query to the driver. */
 		if (copy_from_user(ias_opt, optval, len)) {
 			kfree(ias_opt);
-			return -EFAULT;
+			err = -EFAULT;
+			goto out;
 		}
 
 		/* Find the object we target.
@@ -2355,7 +2366,8 @@
 			ias_obj = irias_find_object(ias_opt->irda_class_name);
 		if(ias_obj == (struct ias_object *) NULL) {
 			kfree(ias_opt);
-			return -EINVAL;
+			err = -EINVAL;
+			goto out;
 		}
 
 		/* Find the attribute (in the object) we target */
@@ -2363,21 +2375,23 @@
 					     ias_opt->irda_attrib_name);
 		if(ias_attr == (struct ias_attrib *) NULL) {
 			kfree(ias_opt);
-			return -EINVAL;
+			err = -EINVAL;
+			goto out;
 		}
 
 		/* Translate from internal to user structure */
 		err = irda_extract_ias_value(ias_opt, ias_attr->value);
 		if(err) {
 			kfree(ias_opt);
-			return err;
+			goto out;
 		}
 
 		/* Copy reply to the user */
 		if (copy_to_user(optval, ias_opt,
 				 sizeof(struct irda_ias_set))) {
 			kfree(ias_opt);
-			return -EFAULT;
+			err = -EFAULT;
+			goto out;
 		}
 		/* Note : don't need to put optlen, we checked it */
 		kfree(ias_opt);
@@ -2388,17 +2402,22 @@
 		 * then wait for the answer to come back. */
 
 		/* Check that the user has allocated the right space for us */
-		if (len != sizeof(struct irda_ias_set))
-			return -EINVAL;
+		if (len != sizeof(struct irda_ias_set)) {
+			err = -EINVAL;
+			goto out;
+		}
 
 		ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC);
-		if (ias_opt == NULL)
-			return -ENOMEM;
+		if (ias_opt == NULL) {
+			err = -ENOMEM;
+			goto out;
+		}
 
 		/* Copy query to the driver. */
 		if (copy_from_user(ias_opt, optval, len)) {
 			kfree(ias_opt);
-			return -EFAULT;
+			err = -EFAULT;
+			goto out;
 		}
 
 		/* At this point, there are two cases...
@@ -2419,7 +2438,8 @@
 			daddr = ias_opt->daddr;
 			if((!daddr) || (daddr == DEV_ADDR_ANY)) {
 				kfree(ias_opt);
-				return -EINVAL;
+				err = -EINVAL;
+				goto out;
 			}
 		}
 
@@ -2428,7 +2448,8 @@
 			IRDA_WARNING("%s: busy with a previous query\n",
 				     __func__);
 			kfree(ias_opt);
-			return -EBUSY;
+			err = -EBUSY;
+			goto out;
 		}
 
 		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
@@ -2436,7 +2457,8 @@
 
 		if (self->iriap == NULL) {
 			kfree(ias_opt);
-			return -ENOMEM;
+			err = -ENOMEM;
+			goto out;
 		}
 
 		/* Treat unexpected wakeup as disconnect */
@@ -2455,7 +2477,8 @@
 			 * we can free it regardless! */
 			kfree(ias_opt);
 			/* Treat signals as disconnect */
-			return -EHOSTUNREACH;
+			err = -EHOSTUNREACH;
+			goto out;
 		}
 
 		/* Check what happened */
@@ -2465,9 +2488,11 @@
 			/* Requested object/attribute doesn't exist */
 			if((self->errno == IAS_CLASS_UNKNOWN) ||
 			   (self->errno == IAS_ATTRIB_UNKNOWN))
-				return (-EADDRNOTAVAIL);
+				err = -EADDRNOTAVAIL;
 			else
-				return (-EHOSTUNREACH);
+				err = -EHOSTUNREACH;
+
+			goto out;
 		}
 
 		/* Translate from internal to user structure */
@@ -2476,14 +2501,15 @@
 			irias_delete_value(self->ias_result);
 		if (err) {
 			kfree(ias_opt);
-			return err;
+			goto out;
 		}
 
 		/* Copy reply to the user */
 		if (copy_to_user(optval, ias_opt,
 				 sizeof(struct irda_ias_set))) {
 			kfree(ias_opt);
-			return -EFAULT;
+			err = -EFAULT;
+			goto out;
 		}
 		/* Note : don't need to put optlen, we checked it */
 		kfree(ias_opt);
@@ -2504,11 +2530,15 @@
 		 */
 
 		/* Check that the user is passing us an int */
-		if (len != sizeof(int))
-			return -EINVAL;
+		if (len != sizeof(int)) {
+			err = -EINVAL;
+			goto out;
+		}
 		/* Get timeout in ms (max time we block the caller) */
-		if (get_user(val, (int __user *)optval))
-			return -EFAULT;
+		if (get_user(val, (int __user *)optval)) {
+			err = -EFAULT;
+			goto out;
+		}
 
 		/* Tell IrLMP we want to be notified */
 		irlmp_update_client(self->ckey, self->mask.word,
@@ -2520,8 +2550,6 @@
 
 		/* Wait until a node is discovered */
 		if (!self->cachedaddr) {
-			int ret = 0;
-
 			IRDA_DEBUG(1, "%s(), nothing discovered yet, going to sleep...\n", __func__);
 
 			/* Set watchdog timer to expire in <val> ms. */
@@ -2534,7 +2562,7 @@
 			/* Wait for IR-LMP to call us back */
 			__wait_event_interruptible(self->query_wait,
 			      (self->cachedaddr != 0 || self->errno == -ETIME),
-						   ret);
+						   err);
 
 			/* If watchdog is still activated, kill it! */
 			if(timer_pending(&(self->watchdog)))
@@ -2542,8 +2570,8 @@
 
 			IRDA_DEBUG(1, "%s(), ...waking up !\n", __func__);
 
-			if (ret != 0)
-				return ret;
+			if (err != 0)
+				goto out;
 		}
 		else
 			IRDA_DEBUG(1, "%s(), found immediately !\n",
@@ -2566,25 +2594,19 @@
 		 * If the user want more details, he should query
 		 * the whole discovery log and pick one device...
 		 */
-		if (put_user(daddr, (int __user *)optval))
-			return -EFAULT;
+		if (put_user(daddr, (int __user *)optval)) {
+			err = -EFAULT;
+			goto out;
+		}
 
 		break;
 	default:
-		return -ENOPROTOOPT;
+		err = -ENOPROTOOPT;
 	}
 
-	return 0;
-}
+out:
 
-static int irda_getsockopt(struct socket *sock, int level, int optname,
-			   char __user *optval, int __user *optlen)
-{
-	int err;
-
-	lock_kernel();
-	err = __irda_getsockopt(sock, level, optname, optval, optlen);
-	unlock_kernel();
+	release_sock(sk);
 
 	return err;
 }
@@ -2628,7 +2650,7 @@
 	.socketpair =	sock_no_socketpair,
 	.accept =	irda_accept,
 	.getname =	irda_getname,
-	.poll =		irda_datagram_poll,
+	.poll =		datagram_poll,
 	.ioctl =	irda_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl =	irda_compat_ioctl,
@@ -2652,7 +2674,7 @@
 	.socketpair =	sock_no_socketpair,
 	.accept =	irda_accept,
 	.getname =	irda_getname,
-	.poll =		irda_datagram_poll,
+	.poll =		datagram_poll,
 	.ioctl =	irda_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl =	irda_compat_ioctl,
@@ -2677,7 +2699,7 @@
 	.socketpair =	sock_no_socketpair,
 	.accept =	sock_no_accept,
 	.getname =	irda_getname,
-	.poll =		irda_datagram_poll,
+	.poll =		datagram_poll,
 	.ioctl =	irda_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl =	irda_compat_ioctl,
diff --git a/net/irda/discovery.c b/net/irda/discovery.c
index c1c8ae9..36c3f03 100644
--- a/net/irda/discovery.c
+++ b/net/irda/discovery.c
@@ -315,7 +315,7 @@
 
 	/* Get the actual number of device in the buffer and return */
 	*pn = i;
-	return(buffer);
+	return buffer;
 }
 
 #ifdef CONFIG_PROC_FS
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index faa82ca..a39cca8 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -449,8 +449,8 @@
 		}
 
 #ifdef SERIAL_DO_RESTART
-		return ((self->flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
+		return (self->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS;
 #else
 		return -EAGAIN;
 #endif
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index fce364c..5b743bd 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -502,7 +502,8 @@
 		IRDA_DEBUG(4, "%s(), strlen=%d\n", __func__, value_len);
 
 		/* Make sure the string is null-terminated */
-		fp[n+value_len] = 0x00;
+		if (n + value_len < skb->len)
+			fp[n + value_len] = 0x00;
 		IRDA_DEBUG(4, "Got string %s\n", fp+n);
 
 		/* Will truncate to IAS_MAX_STRING bytes */
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
index 5bb8353..8ee1ff6 100644
--- a/net/irda/irlan/irlan_eth.c
+++ b/net/irda/irlan/irlan_eth.c
@@ -45,13 +45,11 @@
 static netdev_tx_t  irlan_eth_xmit(struct sk_buff *skb,
 					 struct net_device *dev);
 static void irlan_eth_set_multicast_list( struct net_device *dev);
-static struct net_device_stats *irlan_eth_get_stats(struct net_device *dev);
 
 static const struct net_device_ops irlan_eth_netdev_ops = {
 	.ndo_open               = irlan_eth_open,
 	.ndo_stop               = irlan_eth_close,
 	.ndo_start_xmit    	= irlan_eth_xmit,
-	.ndo_get_stats	        = irlan_eth_get_stats,
 	.ndo_set_multicast_list = irlan_eth_set_multicast_list,
 	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
@@ -208,10 +206,10 @@
 		 * tried :-) DB
 		 */
 		/* irttp_data_request already free the packet */
-		self->stats.tx_dropped++;
+		dev->stats.tx_dropped++;
 	} else {
-		self->stats.tx_packets++;
-		self->stats.tx_bytes += len;
+		dev->stats.tx_packets++;
+		dev->stats.tx_bytes += len;
 	}
 
 	return NETDEV_TX_OK;
@@ -226,15 +224,16 @@
 int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
 {
 	struct irlan_cb *self = instance;
+	struct net_device *dev = self->dev;
 
 	if (skb == NULL) {
-		++self->stats.rx_dropped;
+		dev->stats.rx_dropped++;
 		return 0;
 	}
 	if (skb->len < ETH_HLEN) {
 		IRDA_DEBUG(0, "%s() : IrLAN frame too short (%d)\n",
 			   __func__, skb->len);
-		++self->stats.rx_dropped;
+		dev->stats.rx_dropped++;
 		dev_kfree_skb(skb);
 		return 0;
 	}
@@ -244,10 +243,10 @@
 	 * might have been previously set by the low level IrDA network
 	 * device driver
 	 */
-	skb->protocol = eth_type_trans(skb, self->dev); /* Remove eth header */
+	skb->protocol = eth_type_trans(skb, dev); /* Remove eth header */
 
-	self->stats.rx_packets++;
-	self->stats.rx_bytes += skb->len;
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += skb->len;
 
 	netif_rx(skb);   /* Eat it! */
 
@@ -348,16 +347,3 @@
 	else
 		irlan_set_broadcast_filter(self, FALSE);
 }
-
-/*
- * Function irlan_get_stats (dev)
- *
- *    Get the current statistics for this device
- *
- */
-static struct net_device_stats *irlan_eth_get_stats(struct net_device *dev)
-{
-	struct irlan_cb *self = netdev_priv(dev);
-
-	return &self->stats;
-}
diff --git a/net/irda/irlan/irlan_event.c b/net/irda/irlan/irlan_event.c
index cbcb4eb..43f1604 100644
--- a/net/irda/irlan/irlan_event.c
+++ b/net/irda/irlan/irlan_event.c
@@ -24,7 +24,7 @@
 
 #include <net/irda/irlan_event.h>
 
-char *irlan_state[] = {
+const char * const irlan_state[] = {
 	"IRLAN_IDLE",
 	"IRLAN_QUERY",
 	"IRLAN_CONN",
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 0e7d8bd..6115a44 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -939,7 +939,7 @@
 	}
 
 	/* Return current cached discovery log */
-	return(irlmp_copy_discoveries(irlmp->cachelog, pn, mask, TRUE));
+	return irlmp_copy_discoveries(irlmp->cachelog, pn, mask, TRUE);
 }
 EXPORT_SYMBOL(irlmp_get_discoveries);
 
diff --git a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c
index 3750884..062e63b 100644
--- a/net/irda/irlmp_frame.c
+++ b/net/irda/irlmp_frame.c
@@ -448,7 +448,7 @@
 	    (self->cache.slsap_sel == slsap_sel) &&
 	    (self->cache.dlsap_sel == dlsap_sel))
 	{
-		return (self->cache.lsap);
+		return self->cache.lsap;
 	}
 #endif
 
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h
index 4300df3..0d82ff5 100644
--- a/net/irda/irnet/irnet.h
+++ b/net/irda/irnet/irnet.h
@@ -458,6 +458,8 @@
   int			disco_index;	/* Last read in the discovery log */
   int			disco_number;	/* Size of the discovery log */
 
+  struct mutex		lock;
+
 } irnet_socket;
 
 /*
diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
index e98e40d..7f17a80 100644
--- a/net/irda/irnet/irnet_irda.c
+++ b/net/irda/irnet/irnet_irda.c
@@ -238,7 +238,7 @@
   DEXIT(IRDA_SR_TRACE, "\n");
 
   /* Return the TSAP */
-  return(dtsap_sel);
+  return dtsap_sel;
 }
 
 /*------------------------------------------------------------------*/
@@ -301,7 +301,7 @@
     {
       clear_bit(0, &self->ttp_connect);
       DERROR(IRDA_SR_ERROR, "connect aborted!\n");
-      return(err);
+      return err;
     }
 
   /* Connect to remote device */
@@ -312,7 +312,7 @@
     {
       clear_bit(0, &self->ttp_connect);
       DERROR(IRDA_SR_ERROR, "connect aborted!\n");
-      return(err);
+      return err;
     }
 
   /* The above call is non-blocking.
@@ -321,7 +321,7 @@
    * See you there ;-) */
 
   DEXIT(IRDA_SR_TRACE, "\n");
-  return(err);
+  return err;
 }
 
 /*------------------------------------------------------------------*/
@@ -362,10 +362,10 @@
       /* The above request is non-blocking.
        * After a while, IrDA will call us back in irnet_discovervalue_confirm()
        * We will then call irnet_ias_to_tsap() and come back here again... */
-      return(0);
+      return 0;
     }
   else
-    return(1);
+    return 1;
 }
 
 /*------------------------------------------------------------------*/
@@ -436,7 +436,7 @@
   /* Follow me in irnet_discovervalue_confirm() */
 
   DEXIT(IRDA_SR_TRACE, "\n");
-  return(0);
+  return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -485,7 +485,7 @@
   /* No luck ! */
   DEBUG(IRDA_SR_INFO, "cannot discover device ``%s'' !!!\n", self->rname);
   kfree(discoveries);
-  return(-EADDRNOTAVAIL);
+  return -EADDRNOTAVAIL;
 }
 
 
@@ -527,7 +527,7 @@
   INIT_WORK(&self->disconnect_work, irnet_ppp_disconnect);
 
   DEXIT(IRDA_SOCK_TRACE, "\n");
-  return(0);
+  return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -601,7 +601,7 @@
    * We will finish the connection procedure in irnet_connect_tsap().
    */
   DEXIT(IRDA_SOCK_TRACE, "\n");
-  return(0);
+  return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -733,7 +733,7 @@
   /* No luck ! */
   DEXIT(IRDA_SERV_INFO, ": cannot discover device 0x%08x !!!\n", self->daddr);
   kfree(discoveries);
-  return(-EADDRNOTAVAIL);
+  return -EADDRNOTAVAIL;
 }
 
 /*------------------------------------------------------------------*/
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c
index dfe7b38..0993bd4 100644
--- a/net/irda/irnet/irnet_ppp.c
+++ b/net/irda/irnet/irnet_ppp.c
@@ -166,7 +166,7 @@
     }
 
   /* Success : we have parsed all commands successfully */
-  return(count);
+  return count;
 }
 
 #ifdef INITIAL_DISCOVERY
@@ -300,7 +300,7 @@
 	}
 
       DEXIT(CTRL_TRACE, "\n");
-      return(strlen(event));
+      return strlen(event);
     }
 #endif /* INITIAL_DISCOVERY */
 
@@ -409,7 +409,7 @@
     }
 
   DEXIT(CTRL_TRACE, "\n");
-  return(strlen(event));
+  return strlen(event);
 }
 
 /*------------------------------------------------------------------*/
@@ -480,7 +480,6 @@
   ap = kzalloc(sizeof(*ap), GFP_KERNEL);
   DABORT(ap == NULL, -ENOMEM, FS_ERROR, "Can't allocate struct irnet...\n");
 
-  lock_kernel();
   /* initialize the irnet structure */
   ap->file = file;
 
@@ -502,18 +501,20 @@
     {
       DERROR(FS_ERROR, "Can't setup IrDA link...\n");
       kfree(ap);
-      unlock_kernel();
+
       return err;
     }
 
   /* For the control channel */
   ap->event_index = irnet_events.index;	/* Cancel all past events */
 
+  mutex_init(&ap->lock);
+
   /* Put our stuff where we will be able to find it later */
   file->private_data = ap;
 
   DEXIT(FS_TRACE, " - ap=0x%p\n", ap);
-  unlock_kernel();
+
   return 0;
 }
 
@@ -623,7 +624,7 @@
     mask |= irnet_ctrl_poll(ap, file, wait);
 
   DEXIT(FS_TRACE, " - mask=0x%X\n", mask);
-  return(mask);
+  return mask;
 }
 
 /*------------------------------------------------------------------*/
@@ -664,7 +665,9 @@
 	{
 	  DEBUG(FS_INFO, "Entering PPP discipline.\n");
 	  /* PPP channel setup (ap->chan in configued in dev_irnet_open())*/
-	  lock_kernel();
+	  if (mutex_lock_interruptible(&ap->lock))
+		  return -EINTR;
+
 	  err = ppp_register_channel(&ap->chan);
 	  if(err == 0)
 	    {
@@ -677,14 +680,17 @@
 	    }
 	  else
 	    DERROR(FS_ERROR, "Can't setup PPP channel...\n");
-          unlock_kernel();
+
+          mutex_unlock(&ap->lock);
 	}
       else
 	{
 	  /* In theory, should be N_TTY */
 	  DEBUG(FS_INFO, "Exiting PPP discipline.\n");
 	  /* Disconnect from the generic PPP layer */
-	  lock_kernel();
+	  if (mutex_lock_interruptible(&ap->lock))
+		  return -EINTR;
+
 	  if(ap->ppp_open)
 	    {
 	      ap->ppp_open = 0;
@@ -693,24 +699,31 @@
 	  else
 	    DERROR(FS_ERROR, "Channel not registered !\n");
 	  err = 0;
-	  unlock_kernel();
+
+	  mutex_unlock(&ap->lock);
 	}
       break;
 
       /* Query PPP channel and unit number */
     case PPPIOCGCHAN:
-      lock_kernel();
+      if (mutex_lock_interruptible(&ap->lock))
+	      return -EINTR;
+
       if(ap->ppp_open && !put_user(ppp_channel_index(&ap->chan),
 						(int __user *)argp))
 	err = 0;
-      unlock_kernel();
+
+      mutex_unlock(&ap->lock);
       break;
     case PPPIOCGUNIT:
-      lock_kernel();
+      if (mutex_lock_interruptible(&ap->lock))
+	      return -EINTR;
+
       if(ap->ppp_open && !put_user(ppp_unit_number(&ap->chan),
 						(int __user *)argp))
         err = 0;
-      unlock_kernel();
+
+      mutex_unlock(&ap->lock);
       break;
 
       /* All these ioctls can be passed both directly and from ppp_generic,
@@ -730,9 +743,12 @@
       if(!capable(CAP_NET_ADMIN))
 	err = -EPERM;
       else {
-	lock_kernel();
+	if (mutex_lock_interruptible(&ap->lock))
+	      return -EINTR;
+
 	err = ppp_irnet_ioctl(&ap->chan, cmd, arg);
-	unlock_kernel();
+
+	mutex_unlock(&ap->lock);
       }
       break;
 
@@ -740,7 +756,9 @@
       /* Get termios */
     case TCGETS:
       DEBUG(FS_INFO, "Get termios.\n");
-      lock_kernel();
+      if (mutex_lock_interruptible(&ap->lock))
+	      return -EINTR;
+
 #ifndef TCGETS2
       if(!kernel_termios_to_user_termios((struct termios __user *)argp, &ap->termios))
 	err = 0;
@@ -748,12 +766,15 @@
       if(kernel_termios_to_user_termios_1((struct termios __user *)argp, &ap->termios))
 	err = 0;
 #endif
-      unlock_kernel();
+
+      mutex_unlock(&ap->lock);
       break;
       /* Set termios */
     case TCSETSF:
       DEBUG(FS_INFO, "Set termios.\n");
-      lock_kernel();
+      if (mutex_lock_interruptible(&ap->lock))
+	      return -EINTR;
+
 #ifndef TCGETS2
       if(!user_termios_to_kernel_termios(&ap->termios, (struct termios __user *)argp))
 	err = 0;
@@ -761,7 +782,8 @@
       if(!user_termios_to_kernel_termios_1(&ap->termios, (struct termios __user *)argp))
 	err = 0;
 #endif
-      unlock_kernel();
+
+      mutex_unlock(&ap->lock);
       break;
 
       /* Set DTR/RTS */
@@ -784,9 +806,10 @@
        * We should also worry that we don't accept junk here and that
        * we get rid of our own buffers */
 #ifdef FLUSH_TO_PPP
-      lock_kernel();
+      if (mutex_lock_interruptible(&ap->lock))
+	      return -EINTR;
       ppp_output_wakeup(&ap->chan);
-      unlock_kernel();
+      mutex_unlock(&ap->lock);
 #endif /* FLUSH_TO_PPP */
       err = 0;
       break;
diff --git a/net/irda/irnet/irnet_ppp.h b/net/irda/irnet/irnet_ppp.h
index b5df241..9402258 100644
--- a/net/irda/irnet/irnet_ppp.h
+++ b/net/irda/irnet/irnet_ppp.h
@@ -103,7 +103,8 @@
 	.poll		= dev_irnet_poll,
 	.unlocked_ioctl	= dev_irnet_ioctl,
 	.open		= dev_irnet_open,
-	.release	= dev_irnet_close
+	.release	= dev_irnet_close,
+	.llseek		= noop_llseek,
   /* Also : llseek, readdir, mmap, flush, fsync, fasync, lock, readv, writev */
 };
 
diff --git a/net/irda/parameters.c b/net/irda/parameters.c
index fc1a205..71cd38c 100644
--- a/net/irda/parameters.c
+++ b/net/irda/parameters.c
@@ -298,6 +298,8 @@
 
 	p.pi = pi;     /* In case handler needs to know */
 	p.pl = buf[1]; /* Extract length of value */
+	if (p.pl > 32)
+		p.pl = 32;
 
 	IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d\n", __func__,
 		   p.pi, p.pl);
@@ -318,7 +320,7 @@
 		   (__u8) str[0], (__u8) str[1]);
 
 	/* Null terminate string */
-	str[p.pl+1] = '\0';
+	str[p.pl] = '\0';
 
 	p.pv.c = str; /* Handler will need to take a copy */
 
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 43040e9..d87c22d 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -565,12 +565,12 @@
 
 static uint8_t pfkey_proto_to_xfrm(uint8_t proto)
 {
-	return (proto == IPSEC_PROTO_ANY ? 0 : proto);
+	return proto == IPSEC_PROTO_ANY ? 0 : proto;
 }
 
 static uint8_t pfkey_proto_from_xfrm(uint8_t proto)
 {
-	return (proto ? proto : IPSEC_PROTO_ANY);
+	return proto ? proto : IPSEC_PROTO_ANY;
 }
 
 static inline int pfkey_sockaddr_len(sa_family_t family)
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index 1ae6976..8d9ce0a 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -144,7 +144,6 @@
 	nf_reset(skb);
 
 	if (dev_forward_skb(dev, skb) == NET_RX_SUCCESS) {
-		dev->last_rx = jiffies;
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += data_len;
 	} else
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 226a0ae..1c770c0 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -65,9 +65,7 @@
 			continue;
 
 		if ((l2tp->conn_id == tunnel_id) &&
-#ifdef CONFIG_NET_NS
-		    (sk->sk_net == net) &&
-#endif
+		    net_eq(sock_net(sk), net) &&
 		    !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) &&
 		    !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
 			goto found;
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index ff954b3..39a21d0 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -1768,7 +1768,7 @@
 	.ioctl		= pppox_ioctl,
 };
 
-static struct pppox_proto pppol2tp_proto = {
+static const struct pppox_proto pppol2tp_proto = {
 	.create		= pppol2tp_create,
 	.ioctl		= pppol2tp_ioctl
 };
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index a87cb3b..d2b03e0 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -138,10 +138,8 @@
 	struct crypto_cipher *tfm;
 
 	tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(tfm))
-		return NULL;
-
-	crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN);
+	if (!IS_ERR(tfm))
+		crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN);
 
 	return tfm;
 }
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c
index 3d097b3..b4d66cc 100644
--- a/net/mac80211/aes_cmac.c
+++ b/net/mac80211/aes_cmac.c
@@ -119,10 +119,8 @@
 	struct crypto_cipher *tfm;
 
 	tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(tfm))
-		return NULL;
-
-	crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN);
+	if (!IS_ERR(tfm))
+		crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN);
 
 	return tfm;
 }
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 965b272..720b7a8 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -56,7 +56,7 @@
 }
 
 void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
-				     u16 initiator, u16 reason)
+				     u16 initiator, u16 reason, bool tx)
 {
 	struct ieee80211_local *local = sta->local;
 	struct tid_ampdu_rx *tid_rx;
@@ -81,20 +81,21 @@
 				"aggregation for tid %d\n", tid);
 
 	/* check if this is a self generated aggregation halt */
-	if (initiator == WLAN_BACK_RECIPIENT)
+	if (initiator == WLAN_BACK_RECIPIENT && tx)
 		ieee80211_send_delba(sta->sdata, sta->sta.addr,
 				     tid, 0, reason);
 
 	del_timer_sync(&tid_rx->session_timer);
+	del_timer_sync(&tid_rx->reorder_timer);
 
 	call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
 }
 
 void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
-				    u16 initiator, u16 reason)
+				    u16 initiator, u16 reason, bool tx)
 {
 	mutex_lock(&sta->ampdu_mlme.mtx);
-	___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason);
+	___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, tx);
 	mutex_unlock(&sta->ampdu_mlme.mtx);
 }
 
@@ -120,6 +121,20 @@
 	ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
 }
 
+static void sta_rx_agg_reorder_timer_expired(unsigned long data)
+{
+	u8 *ptid = (u8 *)data;
+	u8 *timer_to_id = ptid - *ptid;
+	struct sta_info *sta = container_of(timer_to_id, struct sta_info,
+			timer_to_tid[0]);
+
+	rcu_read_lock();
+	spin_lock(&sta->lock);
+	ieee80211_release_reorder_timeout(sta, *ptid);
+	spin_unlock(&sta->lock);
+	rcu_read_unlock();
+}
+
 static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
 				      u8 dialog_token, u16 status, u16 policy,
 				      u16 buf_size, u16 timeout)
@@ -251,11 +266,18 @@
 		goto end;
 	}
 
+	spin_lock_init(&tid_agg_rx->reorder_lock);
+
 	/* rx timer */
 	tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired;
 	tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid];
 	init_timer(&tid_agg_rx->session_timer);
 
+	/* rx reorder timer */
+	tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired;
+	tid_agg_rx->reorder_timer.data = (unsigned long)&sta->timer_to_tid[tid];
+	init_timer(&tid_agg_rx->reorder_timer);
+
 	/* prepare reordering buffer */
 	tid_agg_rx->reorder_buf =
 		kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC);
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index c893f23..d4679b2 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -145,7 +145,8 @@
 }
 
 int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
-				    enum ieee80211_back_parties initiator)
+				    enum ieee80211_back_parties initiator,
+				    bool tx)
 {
 	struct ieee80211_local *local = sta->local;
 	struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid];
@@ -175,6 +176,8 @@
 
 	set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
 
+	del_timer_sync(&tid_tx->addba_resp_timer);
+
 	/*
 	 * After this packets are no longer handed right through
 	 * to the driver but are put onto tid_tx->pending instead,
@@ -183,6 +186,7 @@
 	clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
 
 	tid_tx->stop_initiator = initiator;
+	tid_tx->tx_stop = tx;
 
 	ret = drv_ampdu_action(local, sta->sdata,
 			       IEEE80211_AMPDU_TX_STOP,
@@ -575,13 +579,14 @@
 EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
 
 int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
-				   enum ieee80211_back_parties initiator)
+				   enum ieee80211_back_parties initiator,
+				   bool tx)
 {
 	int ret;
 
 	mutex_lock(&sta->ampdu_mlme.mtx);
 
-	ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator);
+	ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator, tx);
 
 	mutex_unlock(&sta->ampdu_mlme.mtx);
 
@@ -670,7 +675,7 @@
 		goto unlock_sta;
 	}
 
-	if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR)
+	if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR && tid_tx->tx_stop)
 		ieee80211_send_delba(sta->sdata, ra, tid,
 			WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
 
@@ -770,7 +775,8 @@
 
 		sta->ampdu_mlme.addba_req_num[tid] = 0;
 	} else {
-		___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
+		___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR,
+						true);
 	}
 
  out:
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 29ac8e1..18bd0e5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -19,33 +19,6 @@
 #include "rate.h"
 #include "mesh.h"
 
-static bool nl80211_type_check(enum nl80211_iftype type)
-{
-	switch (type) {
-	case NL80211_IFTYPE_ADHOC:
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_MONITOR:
-#ifdef CONFIG_MAC80211_MESH
-	case NL80211_IFTYPE_MESH_POINT:
-#endif
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_AP_VLAN:
-	case NL80211_IFTYPE_WDS:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static bool nl80211_params_check(enum nl80211_iftype type,
-				 struct vif_params *params)
-{
-	if (!nl80211_type_check(type))
-		return false;
-
-	return true;
-}
-
 static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
 			       enum nl80211_iftype type, u32 *flags,
 			       struct vif_params *params)
@@ -55,9 +28,6 @@
 	struct ieee80211_sub_if_data *sdata;
 	int err;
 
-	if (!nl80211_params_check(type, params))
-		return -EINVAL;
-
 	err = ieee80211_if_add(local, name, &dev, type, params);
 	if (err || type != NL80211_IFTYPE_MONITOR || !flags)
 		return err;
@@ -82,12 +52,6 @@
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	int ret;
 
-	if (ieee80211_sdata_running(sdata))
-		return -EBUSY;
-
-	if (!nl80211_params_check(type, params))
-		return -EINVAL;
-
 	ret = ieee80211_if_change_type(sdata, type);
 	if (ret)
 		return ret;
@@ -104,54 +68,71 @@
 		 params && params->use_4addr >= 0)
 		sdata->u.mgd.use_4addr = params->use_4addr;
 
-	if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags)
-		sdata->u.mntr_flags = *flags;
+	if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) {
+		struct ieee80211_local *local = sdata->local;
+
+		if (ieee80211_sdata_running(sdata)) {
+			/*
+			 * Prohibit MONITOR_FLAG_COOK_FRAMES to be
+			 * changed while the interface is up.
+			 * Else we would need to add a lot of cruft
+			 * to update everything:
+			 *	cooked_mntrs, monitor and all fif_* counters
+			 *	reconfigure hardware
+			 */
+			if ((*flags & MONITOR_FLAG_COOK_FRAMES) !=
+			    (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES))
+				return -EBUSY;
+
+			ieee80211_adjust_monitor_flags(sdata, -1);
+			sdata->u.mntr_flags = *flags;
+			ieee80211_adjust_monitor_flags(sdata, 1);
+
+			ieee80211_configure_filter(local);
+		} else {
+			/*
+			 * Because the interface is down, ieee80211_do_stop
+			 * and ieee80211_do_open take care of "everything"
+			 * mentioned in the comment above.
+			 */
+			sdata->u.mntr_flags = *flags;
+		}
+	}
 
 	return 0;
 }
 
 static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
-			     u8 key_idx, const u8 *mac_addr,
+			     u8 key_idx, bool pairwise, const u8 *mac_addr,
 			     struct key_params *params)
 {
-	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct sta_info *sta = NULL;
-	enum ieee80211_key_alg alg;
 	struct ieee80211_key *key;
 	int err;
 
-	if (!netif_running(dev))
+	if (!ieee80211_sdata_running(sdata))
 		return -ENETDOWN;
 
-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
+	/* reject WEP and TKIP keys if WEP failed to initialize */
 	switch (params->cipher) {
 	case WLAN_CIPHER_SUITE_WEP40:
-	case WLAN_CIPHER_SUITE_WEP104:
-		alg = ALG_WEP;
-		break;
 	case WLAN_CIPHER_SUITE_TKIP:
-		alg = ALG_TKIP;
-		break;
-	case WLAN_CIPHER_SUITE_CCMP:
-		alg = ALG_CCMP;
-		break;
-	case WLAN_CIPHER_SUITE_AES_CMAC:
-		alg = ALG_AES_CMAC;
+	case WLAN_CIPHER_SUITE_WEP104:
+		if (IS_ERR(sdata->local->wep_tx_tfm))
+			return -EINVAL;
 		break;
 	default:
-		return -EINVAL;
+		break;
 	}
 
-	/* reject WEP and TKIP keys if WEP failed to initialize */
-	if ((alg == ALG_WEP || alg == ALG_TKIP) &&
-	    IS_ERR(sdata->local->wep_tx_tfm))
-		return -EINVAL;
+	key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len,
+				  params->key, params->seq_len, params->seq);
+	if (IS_ERR(key))
+		return PTR_ERR(key);
 
-	key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key,
-				  params->seq_len, params->seq);
-	if (!key)
-		return -ENOMEM;
+	if (pairwise)
+		key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
 
 	mutex_lock(&sdata->local->sta_mtx);
 
@@ -164,9 +145,10 @@
 		}
 	}
 
-	ieee80211_key_link(key, sdata, sta);
+	err = ieee80211_key_link(key, sdata, sta);
+	if (err)
+		ieee80211_key_free(sdata->local, key);
 
-	err = 0;
  out_unlock:
 	mutex_unlock(&sdata->local->sta_mtx);
 
@@ -174,7 +156,7 @@
 }
 
 static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
-			     u8 key_idx, const u8 *mac_addr)
+			     u8 key_idx, bool pairwise, const u8 *mac_addr)
 {
 	struct ieee80211_sub_if_data *sdata;
 	struct sta_info *sta;
@@ -191,10 +173,17 @@
 		if (!sta)
 			goto out_unlock;
 
-		if (sta->key) {
-			ieee80211_key_free(sdata->local, sta->key);
-			WARN_ON(sta->key);
-			ret = 0;
+		if (pairwise) {
+			if (sta->ptk) {
+				ieee80211_key_free(sdata->local, sta->ptk);
+				ret = 0;
+			}
+		} else {
+			if (sta->gtk[key_idx]) {
+				ieee80211_key_free(sdata->local,
+						   sta->gtk[key_idx]);
+				ret = 0;
+			}
 		}
 
 		goto out_unlock;
@@ -216,7 +205,8 @@
 }
 
 static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
-			     u8 key_idx, const u8 *mac_addr, void *cookie,
+			     u8 key_idx, bool pairwise, const u8 *mac_addr,
+			     void *cookie,
 			     void (*callback)(void *cookie,
 					      struct key_params *params))
 {
@@ -224,7 +214,7 @@
 	struct sta_info *sta = NULL;
 	u8 seq[6] = {0};
 	struct key_params params;
-	struct ieee80211_key *key;
+	struct ieee80211_key *key = NULL;
 	u32 iv32;
 	u16 iv16;
 	int err = -ENOENT;
@@ -238,7 +228,10 @@
 		if (!sta)
 			goto out;
 
-		key = sta->key;
+		if (pairwise)
+			key = sta->ptk;
+		else if (key_idx < NUM_DEFAULT_KEYS)
+			key = sta->gtk[key_idx];
 	} else
 		key = sdata->keys[key_idx];
 
@@ -247,10 +240,10 @@
 
 	memset(&params, 0, sizeof(params));
 
-	switch (key->conf.alg) {
-	case ALG_TKIP:
-		params.cipher = WLAN_CIPHER_SUITE_TKIP;
+	params.cipher = key->conf.cipher;
 
+	switch (key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_TKIP:
 		iv32 = key->u.tkip.tx.iv32;
 		iv16 = key->u.tkip.tx.iv16;
 
@@ -268,8 +261,7 @@
 		params.seq = seq;
 		params.seq_len = 6;
 		break;
-	case ALG_CCMP:
-		params.cipher = WLAN_CIPHER_SUITE_CCMP;
+	case WLAN_CIPHER_SUITE_CCMP:
 		seq[0] = key->u.ccmp.tx_pn[5];
 		seq[1] = key->u.ccmp.tx_pn[4];
 		seq[2] = key->u.ccmp.tx_pn[3];
@@ -279,14 +271,7 @@
 		params.seq = seq;
 		params.seq_len = 6;
 		break;
-	case ALG_WEP:
-		if (key->conf.keylen == 5)
-			params.cipher = WLAN_CIPHER_SUITE_WEP40;
-		else
-			params.cipher = WLAN_CIPHER_SUITE_WEP104;
-		break;
-	case ALG_AES_CMAC:
-		params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
 		seq[0] = key->u.aes_cmac.tx_pn[5];
 		seq[1] = key->u.aes_cmac.tx_pn[4];
 		seq[2] = key->u.aes_cmac.tx_pn[3];
@@ -342,13 +327,19 @@
 			STATION_INFO_TX_BYTES |
 			STATION_INFO_RX_PACKETS |
 			STATION_INFO_TX_PACKETS |
-			STATION_INFO_TX_BITRATE;
+			STATION_INFO_TX_RETRIES |
+			STATION_INFO_TX_FAILED |
+			STATION_INFO_TX_BITRATE |
+			STATION_INFO_RX_DROP_MISC;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 	sinfo->rx_packets = sta->rx_packets;
 	sinfo->tx_packets = sta->tx_packets;
+	sinfo->tx_retries = sta->tx_retry_count;
+	sinfo->tx_failed = sta->tx_retry_failed;
+	sinfo->rx_dropped_misc = sta->rx_dropped;
 
 	if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
 	    (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
@@ -634,6 +625,7 @@
 				 struct sta_info *sta,
 				 struct station_parameters *params)
 {
+	unsigned long flags;
 	u32 rates;
 	int i, j;
 	struct ieee80211_supported_band *sband;
@@ -642,7 +634,7 @@
 
 	sband = local->hw.wiphy->bands[local->oper_channel->band];
 
-	spin_lock_bh(&sta->lock);
+	spin_lock_irqsave(&sta->flaglock, flags);
 	mask = params->sta_flags_mask;
 	set = params->sta_flags_set;
 
@@ -669,7 +661,7 @@
 		if (set & BIT(NL80211_STA_FLAG_MFP))
 			sta->flags |= WLAN_STA_MFP;
 	}
-	spin_unlock_bh(&sta->lock);
+	spin_unlock_irqrestore(&sta->flaglock, flags);
 
 	/*
 	 * cfg80211 validates this (1-2007) and allows setting the AID
@@ -1143,9 +1135,9 @@
 	p.uapsd = false;
 
 	if (drv_conf_tx(local, params->queue, &p)) {
-		printk(KERN_DEBUG "%s: failed to set TX queue "
-		       "parameters for queue %d\n",
-		       wiphy_name(local->hw.wiphy), params->queue);
+		wiphy_debug(local->hw.wiphy,
+			    "failed to set TX queue parameters for queue %d\n",
+			    params->queue);
 		return -EINVAL;
 	}
 
@@ -1207,15 +1199,26 @@
 			  struct net_device *dev,
 			  struct cfg80211_scan_request *req)
 {
-	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-	    sdata->vif.type != NL80211_IFTYPE_ADHOC &&
-	    sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
-	    (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon))
+	switch (ieee80211_vif_type_p2p(&sdata->vif)) {
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_MESH_POINT:
+	case NL80211_IFTYPE_P2P_CLIENT:
+		break;
+	case NL80211_IFTYPE_P2P_GO:
+		if (sdata->local->ops->hw_scan)
+			break;
+		/* FIXME: implement NoA while scanning in software */
 		return -EOPNOTSUPP;
+	case NL80211_IFTYPE_AP:
+		if (sdata->u.ap.beacon)
+			return -EOPNOTSUPP;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
 
 	return ieee80211_request_scan(sdata, req);
 }
@@ -1362,7 +1365,7 @@
 }
 
 static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
-				  u8 *addr)
+				  const u8 *addr)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
@@ -1411,7 +1414,7 @@
 	if (!sdata->u.mgd.associated ||
 	    sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) {
 		mutex_lock(&sdata->local->iflist_mtx);
-		ieee80211_recalc_smps(sdata->local, sdata);
+		ieee80211_recalc_smps(sdata->local);
 		mutex_unlock(&sdata->local->iflist_mtx);
 		return 0;
 	}
@@ -1541,11 +1544,11 @@
 	return ieee80211_wk_cancel_remain_on_channel(sdata, cookie);
 }
 
-static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev,
-			    struct ieee80211_channel *chan,
-			    enum nl80211_channel_type channel_type,
-			    bool channel_type_valid,
-			    const u8 *buf, size_t len, u64 *cookie)
+static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
+			     struct ieee80211_channel *chan,
+			     enum nl80211_channel_type channel_type,
+			     bool channel_type_valid,
+			     const u8 *buf, size_t len, u64 *cookie)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = sdata->local;
@@ -1566,7 +1569,11 @@
 
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_ADHOC:
-		if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_P2P_GO:
+		if (!ieee80211_is_action(mgmt->frame_control) ||
+		    mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)
 			break;
 		rcu_read_lock();
 		sta = sta_info_get(sdata, mgmt->da);
@@ -1575,8 +1582,7 @@
 			return -ENOLINK;
 		break;
 	case NL80211_IFTYPE_STATION:
-		if (!(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED))
-			flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+	case NL80211_IFTYPE_P2P_CLIENT:
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -1598,6 +1604,23 @@
 	return 0;
 }
 
+static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
+					  struct net_device *dev,
+					  u16 frame_type, bool reg)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
+		return;
+
+	if (reg)
+		local->probe_req_reg++;
+	else
+		local->probe_req_reg--;
+
+	ieee80211_queue_work(&local->hw, &local->reconfig_filter);
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -1647,6 +1670,7 @@
 	.set_bitrate_mask = ieee80211_set_bitrate_mask,
 	.remain_on_channel = ieee80211_remain_on_channel,
 	.cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
-	.action = ieee80211_action,
+	.mgmt_tx = ieee80211_mgmt_tx,
 	.set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
+	.mgmt_frame_register = ieee80211_mgmt_frame_register,
 };
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 32be11e..5b24740 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -11,7 +11,7 @@
 {
 	struct ieee80211_sub_if_data *sdata;
 
-	WARN_ON(!mutex_is_locked(&local->iflist_mtx));
+	lockdep_assert_held(&local->iflist_mtx);
 
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		if (sdata == ignore)
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index a694c59..18260aa 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -36,6 +36,7 @@
 static const struct file_operations name## _ops = {			\
 	.read = name## _read,						\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 };
 
 #define DEBUGFS_ADD(name)						\
@@ -85,13 +86,15 @@
 	if (strncmp(buf, "reset", 5) == 0) {
 		if (local->ops->reset_tsf) {
 			drv_reset_tsf(local);
-			printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy));
+			wiphy_info(local->hw.wiphy, "debugfs reset TSF\n");
 		}
 	} else {
 		tsf = simple_strtoul(buf, NULL, 0);
 		if (local->ops->set_tsf) {
 			drv_set_tsf(local, tsf);
-			printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf);
+			wiphy_info(local->hw.wiphy,
+				   "debugfs set TSF to %#018llx\n", tsf);
+
 		}
 	}
 
@@ -101,7 +104,8 @@
 static const struct file_operations tsf_ops = {
 	.read = tsf_read,
 	.write = tsf_write,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t reset_write(struct file *file, const char __user *user_buf,
@@ -120,6 +124,7 @@
 static const struct file_operations reset_ops = {
 	.write = reset_write,
 	.open = mac80211_open_file_generic,
+	.llseek = noop_llseek,
 };
 
 static ssize_t noack_read(struct file *file, char __user *user_buf,
@@ -155,7 +160,8 @@
 static const struct file_operations noack_ops = {
 	.read = noack_read,
 	.write = noack_write,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf,
@@ -201,7 +207,8 @@
 static const struct file_operations uapsd_queues_ops = {
 	.read = uapsd_queues_read,
 	.write = uapsd_queues_write,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf,
@@ -247,7 +254,8 @@
 static const struct file_operations uapsd_max_sp_len_ops = {
 	.read = uapsd_max_sp_len_read,
 	.write = uapsd_max_sp_len_write,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t channel_type_read(struct file *file, char __user *user_buf,
@@ -279,7 +287,8 @@
 
 static const struct file_operations channel_type_ops = {
 	.read = channel_type_read,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t queues_read(struct file *file, char __user *user_buf,
@@ -302,7 +311,8 @@
 
 static const struct file_operations queues_ops = {
 	.read = queues_read,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 /* statistics stuff */
@@ -346,6 +356,7 @@
 static const struct file_operations stats_ ##name## _ops = {		\
 	.read = stats_ ##name## _read,					\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 };
 
 #define DEBUGFS_STATS_ADD(name, field)					\
@@ -366,7 +377,6 @@
 	if (!phyd)
 		return;
 
-	local->debugfs.stations = debugfs_create_dir("stations", phyd);
 	local->debugfs.keys = debugfs_create_dir("keys", phyd);
 
 	DEBUGFS_ADD(frequency);
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index fa5e76e..4aa47d0 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -32,6 +32,7 @@
 static const struct file_operations key_ ##name## _ops = {		\
 	.read = key_##name##_read,					\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 }
 
 #define KEY_FILE(name, format)						\
@@ -46,6 +47,7 @@
 static const struct file_operations key_ ##name## _ops = {		\
 	.read = key_conf_##name##_read,					\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 }
 
 #define KEY_CONF_FILE(name, format)					\
@@ -64,26 +66,13 @@
 				  char __user *userbuf,
 				  size_t count, loff_t *ppos)
 {
-	char *alg;
+	char buf[15];
 	struct ieee80211_key *key = file->private_data;
+	u32 c = key->conf.cipher;
 
-	switch (key->conf.alg) {
-	case ALG_WEP:
-		alg = "WEP\n";
-		break;
-	case ALG_TKIP:
-		alg = "TKIP\n";
-		break;
-	case ALG_CCMP:
-		alg = "CCMP\n";
-		break;
-	case ALG_AES_CMAC:
-		alg = "AES-128-CMAC\n";
-		break;
-	default:
-		return 0;
-	}
-	return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg));
+	sprintf(buf, "%.2x-%.2x-%.2x:%d\n",
+		c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff);
+	return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
 }
 KEY_OPS(algorithm);
 
@@ -95,21 +84,22 @@
 	int len;
 	struct ieee80211_key *key = file->private_data;
 
-	switch (key->conf.alg) {
-	case ALG_WEP:
+	switch (key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
 		len = scnprintf(buf, sizeof(buf), "\n");
 		break;
-	case ALG_TKIP:
+	case WLAN_CIPHER_SUITE_TKIP:
 		len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
 				key->u.tkip.tx.iv32,
 				key->u.tkip.tx.iv16);
 		break;
-	case ALG_CCMP:
+	case WLAN_CIPHER_SUITE_CCMP:
 		tpn = key->u.ccmp.tx_pn;
 		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
 				tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
 		break;
-	case ALG_AES_CMAC:
+	case WLAN_CIPHER_SUITE_AES_CMAC:
 		tpn = key->u.aes_cmac.tx_pn;
 		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
 				tpn[0], tpn[1], tpn[2], tpn[3], tpn[4],
@@ -130,11 +120,12 @@
 	int i, len;
 	const u8 *rpn;
 
-	switch (key->conf.alg) {
-	case ALG_WEP:
+	switch (key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
 		len = scnprintf(buf, sizeof(buf), "\n");
 		break;
-	case ALG_TKIP:
+	case WLAN_CIPHER_SUITE_TKIP:
 		for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
 			p += scnprintf(p, sizeof(buf)+buf-p,
 				       "%08x %04x\n",
@@ -142,7 +133,7 @@
 				       key->u.tkip.rx[i].iv16);
 		len = p - buf;
 		break;
-	case ALG_CCMP:
+	case WLAN_CIPHER_SUITE_CCMP:
 		for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) {
 			rpn = key->u.ccmp.rx_pn[i];
 			p += scnprintf(p, sizeof(buf)+buf-p,
@@ -152,7 +143,7 @@
 		}
 		len = p - buf;
 		break;
-	case ALG_AES_CMAC:
+	case WLAN_CIPHER_SUITE_AES_CMAC:
 		rpn = key->u.aes_cmac.rx_pn;
 		p += scnprintf(p, sizeof(buf)+buf-p,
 			       "%02x%02x%02x%02x%02x%02x\n",
@@ -174,11 +165,11 @@
 	char buf[20];
 	int len;
 
-	switch (key->conf.alg) {
-	case ALG_CCMP:
+	switch (key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_CCMP:
 		len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
 		break;
-	case ALG_AES_CMAC:
+	case WLAN_CIPHER_SUITE_AES_CMAC:
 		len = scnprintf(buf, sizeof(buf), "%u\n",
 				key->u.aes_cmac.replays);
 		break;
@@ -196,8 +187,8 @@
 	char buf[20];
 	int len;
 
-	switch (key->conf.alg) {
-	case ALG_AES_CMAC:
+	switch (key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_AES_CMAC:
 		len = scnprintf(buf, sizeof(buf), "%u\n",
 				key->u.aes_cmac.icverrors);
 		break;
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 20b2998..cbdf36d 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -121,6 +121,7 @@
 	.read = ieee80211_if_read_##name,				\
 	.write = (_write),						\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 }
 
 #define __IEEE80211_IF_FILE_W(name)					\
@@ -409,6 +410,9 @@
 	sprintf(buf, "netdev:%s", sdata->name);
 	sdata->debugfs.dir = debugfs_create_dir(buf,
 		sdata->local->hw.wiphy->debugfsdir);
+	if (sdata->debugfs.dir)
+		sdata->debugfs.subdir_stations = debugfs_create_dir("stations",
+			sdata->debugfs.dir);
 	add_files(sdata);
 }
 
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 76839d4..4601fea 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -36,6 +36,7 @@
 static const struct file_operations sta_ ##name## _ops = {		\
 	.read = sta_##name##_read,					\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 }
 
 #define STA_OPS_RW(name)						\
@@ -43,6 +44,7 @@
 	.read = sta_##name##_read,					\
 	.write = sta_##name##_write,					\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 }
 
 #define STA_FILE(name, field, format)					\
@@ -196,7 +198,8 @@
 		else
 			ret = ieee80211_stop_tx_ba_session(&sta->sta, tid);
 	} else {
-		__ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, 3);
+		__ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
+					       3, true);
 		ret = 0;
 	}
 
@@ -300,7 +303,7 @@
 
 void ieee80211_sta_debugfs_add(struct sta_info *sta)
 {
-	struct dentry *stations_dir = sta->local->debugfs.stations;
+	struct dentry *stations_dir = sta->sdata->debugfs.subdir_stations;
 	u8 mac[3*ETH_ALEN];
 
 	sta->debugfs.add_has_run = true;
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 14123dc..1698382 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -54,6 +54,20 @@
 	return ret;
 }
 
+static inline int drv_change_interface(struct ieee80211_local *local,
+				       struct ieee80211_sub_if_data *sdata,
+				       enum nl80211_iftype type, bool p2p)
+{
+	int ret;
+
+	might_sleep();
+
+	trace_drv_change_interface(local, sdata, type, p2p);
+	ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p);
+	trace_drv_return_int(local, ret);
+	return ret;
+}
+
 static inline void drv_remove_interface(struct ieee80211_local *local,
 					struct ieee80211_vif *vif)
 {
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 5d5d2a9..6831fb1 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -25,12 +25,14 @@
 #define STA_PR_FMT	" sta:%pM"
 #define STA_PR_ARG	__entry->sta_addr
 
-#define VIF_ENTRY	__field(enum nl80211_iftype, vif_type) __field(void *, sdata) \
+#define VIF_ENTRY	__field(enum nl80211_iftype, vif_type) __field(void *, sdata)	\
+			__field(bool, p2p)						\
 			__string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>")
-#define VIF_ASSIGN	__entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \
+#define VIF_ASSIGN	__entry->vif_type = sdata->vif.type; __entry->sdata = sdata;	\
+			__entry->p2p = sdata->vif.p2p;					\
 			__assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>")
-#define VIF_PR_FMT	" vif:%s(%d)"
-#define VIF_PR_ARG	__get_str(vif_name), __entry->vif_type
+#define VIF_PR_FMT	" vif:%s(%d%s)"
+#define VIF_PR_ARG	__get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
 
 /*
  * Tracing for driver callbacks.
@@ -136,6 +138,34 @@
 	)
 );
 
+TRACE_EVENT(drv_change_interface,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata,
+		 enum nl80211_iftype type, bool p2p),
+
+	TP_ARGS(local, sdata, type, p2p),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		VIF_ENTRY
+		__field(u32, new_type)
+		__field(bool, new_p2p)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		VIF_ASSIGN;
+		__entry->new_type = type;
+		__entry->new_p2p = p2p;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT  VIF_PR_FMT " new type:%d%s",
+		LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type,
+		__entry->new_p2p ? "/p2p" : ""
+	)
+);
+
 TRACE_EVENT(drv_remove_interface,
 	TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata),
 
@@ -336,7 +366,7 @@
 		LOCAL_ENTRY
 		VIF_ENTRY
 		STA_ENTRY
-		__field(enum ieee80211_key_alg, alg)
+		__field(u32, cipher)
 		__field(u8, hw_key_idx)
 		__field(u8, flags)
 		__field(s8, keyidx)
@@ -346,7 +376,7 @@
 		LOCAL_ASSIGN;
 		VIF_ASSIGN;
 		STA_ASSIGN;
-		__entry->alg = key->alg;
+		__entry->cipher = key->cipher;
 		__entry->flags = key->flags;
 		__entry->keyidx = key->keyidx;
 		__entry->hw_key_idx = key->hw_key_idx;
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 9d101fb..75d679d 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -101,16 +101,16 @@
 		ht_cap->mcs.rx_mask[32/8] |= 1;
 }
 
-void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta)
+void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx)
 {
 	int i;
 
 	cancel_work_sync(&sta->ampdu_mlme.work);
 
 	for (i = 0; i <  STA_TID_NUM; i++) {
-		__ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR);
+		__ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx);
 		__ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT,
-					       WLAN_REASON_QSTA_LEAVE_QBSS);
+					       WLAN_REASON_QSTA_LEAVE_QBSS, tx);
 	}
 }
 
@@ -135,7 +135,7 @@
 		if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired))
 			___ieee80211_stop_rx_ba_session(
 				sta, tid, WLAN_BACK_RECIPIENT,
-				WLAN_REASON_QSTA_TIMEOUT);
+				WLAN_REASON_QSTA_TIMEOUT, true);
 
 		tid_tx = sta->ampdu_mlme.tid_tx[tid];
 		if (!tid_tx)
@@ -146,7 +146,8 @@
 		else if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP,
 					    &tid_tx->state))
 			___ieee80211_stop_tx_ba_session(sta, tid,
-							WLAN_BACK_INITIATOR);
+							WLAN_BACK_INITIATOR,
+							true);
 	}
 	mutex_unlock(&sta->ampdu_mlme.mtx);
 }
@@ -214,9 +215,11 @@
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
 	if (initiator == WLAN_BACK_INITIATOR)
-		__ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0);
+		__ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0,
+					       true);
 	else
-		__ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT);
+		__ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
+					       true);
 }
 
 int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
@@ -265,3 +268,33 @@
 
 	return 0;
 }
+
+void ieee80211_request_smps_work(struct work_struct *work)
+{
+	struct ieee80211_sub_if_data *sdata =
+		container_of(work, struct ieee80211_sub_if_data,
+			     u.mgd.request_smps_work);
+
+	mutex_lock(&sdata->u.mgd.mtx);
+	__ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode);
+	mutex_unlock(&sdata->u.mgd.mtx);
+}
+
+void ieee80211_request_smps(struct ieee80211_vif *vif,
+			    enum ieee80211_smps_mode smps_mode)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+	if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
+		return;
+
+	if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF))
+		smps_mode = IEEE80211_SMPS_AUTOMATIC;
+
+	sdata->u.mgd.driver_smps_mode = smps_mode;
+
+	ieee80211_queue_work(&sdata->local->hw,
+			     &sdata->u.mgd.request_smps_work);
+}
+/* this might change ... don't want non-open drivers using it */
+EXPORT_SYMBOL_GPL(ieee80211_request_smps);
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index c691780..ff60c02 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -173,6 +173,19 @@
 		memcpy(skb_put(skb, ifibss->ie_len),
 		       ifibss->ie, ifibss->ie_len);
 
+	if (local->hw.queues >= 4) {
+		pos = skb_put(skb, 9);
+		*pos++ = WLAN_EID_VENDOR_SPECIFIC;
+		*pos++ = 7; /* len */
+		*pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
+		*pos++ = 0x50;
+		*pos++ = 0xf2;
+		*pos++ = 2; /* WME */
+		*pos++ = 0; /* WME info */
+		*pos++ = 1; /* WME ver */
+		*pos++ = 0; /* U-APSD no in use */
+	}
+
 	rcu_assign_pointer(ifibss->presp, skb);
 
 	sdata->vif.bss_conf.beacon_int = beacon_int;
@@ -266,37 +279,45 @@
 	if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
 		return;
 
-	if (sdata->vif.type == NL80211_IFTYPE_ADHOC && elems->supp_rates &&
+	if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
 	    memcmp(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) {
-		supp_rates = ieee80211_sta_get_rates(local, elems, band);
 
 		rcu_read_lock();
-
 		sta = sta_info_get(sdata, mgmt->sa);
-		if (sta) {
-			u32 prev_rates;
 
-			prev_rates = sta->sta.supp_rates[band];
-			/* make sure mandatory rates are always added */
-			sta->sta.supp_rates[band] = supp_rates |
-				ieee80211_mandatory_rates(local, band);
+		if (elems->supp_rates) {
+			supp_rates = ieee80211_sta_get_rates(local, elems,
+							     band);
+			if (sta) {
+				u32 prev_rates;
 
-			if (sta->sta.supp_rates[band] != prev_rates) {
+				prev_rates = sta->sta.supp_rates[band];
+				/* make sure mandatory rates are always added */
+				sta->sta.supp_rates[band] = supp_rates |
+					ieee80211_mandatory_rates(local, band);
+
+				if (sta->sta.supp_rates[band] != prev_rates) {
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
-				printk(KERN_DEBUG "%s: updated supp_rates set "
-				    "for %pM based on beacon/probe_response "
-				    "(0x%x -> 0x%x)\n",
-				    sdata->name, sta->sta.addr,
-				    prev_rates, sta->sta.supp_rates[band]);
+					printk(KERN_DEBUG
+						"%s: updated supp_rates set "
+						"for %pM based on beacon"
+						"/probe_resp (0x%x -> 0x%x)\n",
+						sdata->name, sta->sta.addr,
+						prev_rates,
+						sta->sta.supp_rates[band]);
 #endif
-				rate_control_rate_init(sta);
-			}
-			rcu_read_unlock();
-		} else {
-			rcu_read_unlock();
-			ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
-					       supp_rates, GFP_KERNEL);
+					rate_control_rate_init(sta);
+				}
+			} else
+				sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
+						mgmt->sa, supp_rates,
+						GFP_ATOMIC);
 		}
+
+		if (sta && elems->wmm_info)
+			set_sta_flags(sta, WLAN_STA_WME);
+
+		rcu_read_unlock();
 	}
 
 	bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
@@ -427,8 +448,8 @@
 		return NULL;
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n",
-	       wiphy_name(local->hw.wiphy), addr, sdata->name);
+	wiphy_debug(local->hw.wiphy, "Adding new IBSS station %pM (dev=%s)\n",
+		    addr, sdata->name);
 #endif
 
 	sta = sta_info_alloc(sdata, addr, gfp);
@@ -920,12 +941,14 @@
 	memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
 	sdata->u.ibss.ssid_len = params->ssid_len;
 
+	mutex_unlock(&sdata->u.ibss.mtx);
+
+	mutex_lock(&sdata->local->mtx);
 	ieee80211_recalc_idle(sdata->local);
+	mutex_unlock(&sdata->local->mtx);
 
 	ieee80211_queue_work(&sdata->local->hw, &sdata->work);
 
-	mutex_unlock(&sdata->u.ibss.mtx);
-
 	return 0;
 }
 
@@ -980,7 +1003,9 @@
 
 	mutex_unlock(&sdata->u.ibss.mtx);
 
+	mutex_lock(&local->mtx);
 	ieee80211_recalc_idle(sdata->local);
+	mutex_unlock(&local->mtx);
 
 	return 0;
 }
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 65e0ed6..b80c386 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -50,12 +50,6 @@
  * increased memory use (about 2 kB of RAM per entry). */
 #define IEEE80211_FRAGMENT_MAX 4
 
-/*
- * Time after which we ignore scan results and no longer report/use
- * them in any way.
- */
-#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
-
 #define TU_TO_EXP_TIME(x)	(jiffies + usecs_to_jiffies((x) * 1024))
 
 #define IEEE80211_DEFAULT_UAPSD_QUEUES \
@@ -165,12 +159,37 @@
 #define RX_DROP_MONITOR		((__force ieee80211_rx_result) 2u)
 #define RX_QUEUED		((__force ieee80211_rx_result) 3u)
 
-#define IEEE80211_RX_IN_SCAN		BIT(0)
-/* frame is destined to interface currently processed (incl. multicast frames) */
-#define IEEE80211_RX_RA_MATCH		BIT(1)
-#define IEEE80211_RX_AMSDU		BIT(2)
-#define IEEE80211_RX_FRAGMENTED		BIT(3)
-/* only add flags here that do not change with subframes of an aMPDU */
+/**
+ * enum ieee80211_packet_rx_flags - packet RX flags
+ * @IEEE80211_RX_RA_MATCH: frame is destined to interface currently processed
+ *	(incl. multicast frames)
+ * @IEEE80211_RX_IN_SCAN: received while scanning
+ * @IEEE80211_RX_FRAGMENTED: fragmented frame
+ * @IEEE80211_RX_AMSDU: a-MSDU packet
+ * @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed
+ *
+ * These are per-frame flags that are attached to a frame in the
+ * @rx_flags field of &struct ieee80211_rx_status.
+ */
+enum ieee80211_packet_rx_flags {
+	IEEE80211_RX_IN_SCAN			= BIT(0),
+	IEEE80211_RX_RA_MATCH			= BIT(1),
+	IEEE80211_RX_FRAGMENTED			= BIT(2),
+	IEEE80211_RX_AMSDU			= BIT(3),
+	IEEE80211_RX_MALFORMED_ACTION_FRM	= BIT(4),
+};
+
+/**
+ * enum ieee80211_rx_flags - RX data flags
+ *
+ * @IEEE80211_RX_CMNTR: received on cooked monitor already
+ *
+ * These flags are used across handling multiple interfaces
+ * for a single frame.
+ */
+enum ieee80211_rx_flags {
+	IEEE80211_RX_CMNTR		= BIT(0),
+};
 
 struct ieee80211_rx_data {
 	struct sk_buff *skb;
@@ -343,10 +362,14 @@
 	unsigned long timers_running; /* used for quiesce/restart */
 	bool powersave; /* powersave requested for this iface */
 	enum ieee80211_smps_mode req_smps, /* requested smps mode */
-				 ap_smps; /* smps mode AP thinks we're in */
+				 ap_smps, /* smps mode AP thinks we're in */
+				 driver_smps_mode; /* smps mode request */
+
+	struct work_struct request_smps_work;
 
 	unsigned int flags;
 
+	bool beacon_crc_valid;
 	u32 beacon_crc;
 
 	enum {
@@ -371,6 +394,13 @@
 	int ave_beacon_signal;
 
 	/*
+	 * Number of Beacon frames used in ave_beacon_signal. This can be used
+	 * to avoid generating less reliable cqm events that would be based
+	 * only on couple of received frames.
+	 */
+	unsigned int count_beacon_signal;
+
+	/*
 	 * Last Beacon frame signal strength average (ave_beacon_signal / 16)
 	 * that triggered a cqm event. 0 indicates that no event has been
 	 * generated for the current association.
@@ -474,6 +504,19 @@
 	IEEE80211_SDATA_DONT_BRIDGE_PACKETS	= BIT(3),
 };
 
+/**
+ * enum ieee80211_sdata_state_bits - virtual interface state bits
+ * @SDATA_STATE_RUNNING: virtual interface is up & running; this
+ *	mirrors netif_running() but is separate for interface type
+ *	change handling while the interface is up
+ * @SDATA_STATE_OFFCHANNEL: This interface is currently in offchannel
+ *	mode, so queues are stopped
+ */
+enum ieee80211_sdata_state_bits {
+	SDATA_STATE_RUNNING,
+	SDATA_STATE_OFFCHANNEL,
+};
+
 struct ieee80211_sub_if_data {
 	struct list_head list;
 
@@ -487,6 +530,8 @@
 
 	unsigned int flags;
 
+	unsigned long state;
+
 	int drop_unencrypted;
 
 	char name[IFNAMSIZ];
@@ -497,17 +542,20 @@
 	 */
 	bool ht_opmode_valid;
 
+	/* to detect idle changes */
+	bool old_idle;
+
 	/* Fragment table for host-based reassembly */
 	struct ieee80211_fragment_entry	fragments[IEEE80211_FRAGMENT_MAX];
 	unsigned int fragment_next;
 
-#define NUM_DEFAULT_KEYS 4
-#define NUM_DEFAULT_MGMT_KEYS 2
 	struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
 	struct ieee80211_key *default_key;
 	struct ieee80211_key *default_mgmt_key;
 
 	u16 sequence_number;
+	__be16 control_port_protocol;
+	bool control_port_no_encrypt;
 
 	struct work_struct work;
 	struct sk_buff_head skb_queue;
@@ -539,6 +587,7 @@
 #ifdef CONFIG_MAC80211_DEBUGFS
 	struct {
 		struct dentry *dir;
+		struct dentry *subdir_stations;
 		struct dentry *default_key;
 		struct dentry *default_mgmt_key;
 	} debugfs;
@@ -595,11 +644,17 @@
  *	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
+ *	a scan complete for an aborted scan.
  */
 enum {
 	SCAN_SW_SCANNING,
 	SCAN_HW_SCANNING,
 	SCAN_OFF_CHANNEL,
+	SCAN_COMPLETED,
+	SCAN_ABORTED,
 };
 
 /**
@@ -634,7 +689,6 @@
 	/*
 	 * work stuff, potentially off-channel (in the future)
 	 */
-	struct mutex work_mtx;
 	struct list_head work_list;
 	struct timer_list work_timer;
 	struct work_struct work_work;
@@ -653,9 +707,13 @@
 	int open_count;
 	int monitors, cooked_mntrs;
 	/* number of interfaces with corresponding FIF_ flags */
-	int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll;
+	int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
+	    fif_probe_req;
+	int probe_req_reg;
 	unsigned int filter_flags; /* FIF_* */
 
+	bool wiphy_ciphers_allocated;
+
 	/* protects the aggregated multicast list and filter calls */
 	spinlock_t filter_lock;
 
@@ -746,9 +804,10 @@
 	 */
 	struct mutex key_mtx;
 
+	/* mutex for scan and work locking */
+	struct mutex mtx;
 
 	/* Scanning and BSS list */
-	struct mutex scan_mtx;
 	unsigned long scanning;
 	struct cfg80211_ssid scan_ssid;
 	struct cfg80211_scan_request *int_scan_req;
@@ -866,10 +925,14 @@
 #ifdef CONFIG_MAC80211_DEBUGFS
 	struct local_debugfsdentries {
 		struct dentry *rcdir;
-		struct dentry *stations;
 		struct dentry *keys;
 	} debugfs;
 #endif
+
+	/* dummy netdev for use w/ NAPI */
+	struct net_device napi_dev;
+
+	struct napi_struct napi;
 };
 
 static inline struct ieee80211_sub_if_data *
@@ -1003,6 +1066,8 @@
 void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
 void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 				  struct sk_buff *skb);
+void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata);
+void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
 
 /* IBSS code */
 void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
@@ -1068,10 +1133,12 @@
 void ieee80211_remove_interfaces(struct ieee80211_local *local);
 u32 __ieee80211_recalc_idle(struct ieee80211_local *local);
 void ieee80211_recalc_idle(struct ieee80211_local *local);
+void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
+				    const int offset);
 
 static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
 {
-	return netif_running(sdata->dev);
+	return test_bit(SDATA_STATE_RUNNING, &sdata->state);
 }
 
 /* tx handling */
@@ -1105,12 +1172,13 @@
 int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
 			       enum ieee80211_smps_mode smps, const u8 *da,
 			       const u8 *bssid);
+void ieee80211_request_smps_work(struct work_struct *work);
 
 void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
-				     u16 initiator, u16 reason);
+				     u16 initiator, u16 reason, bool stop);
 void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
-				    u16 initiator, u16 reason);
-void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta);
+				    u16 initiator, u16 reason, bool stop);
+void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx);
 void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
 			     struct sta_info *sta,
 			     struct ieee80211_mgmt *mgmt, size_t len);
@@ -1124,13 +1192,16 @@
 				     size_t len);
 
 int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
-				   enum ieee80211_back_parties initiator);
+				   enum ieee80211_back_parties initiator,
+				   bool tx);
 int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
-				    enum ieee80211_back_parties initiator);
+				    enum ieee80211_back_parties initiator,
+				    bool tx);
 void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid);
 void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid);
 void ieee80211_ba_session_work(struct work_struct *work);
 void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid);
+void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid);
 
 /* Spectrum management */
 void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
@@ -1146,6 +1217,12 @@
 
 static inline int __ieee80211_resume(struct ieee80211_hw *hw)
 {
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
+		"%s: resume with hardware scan still in progress\n",
+		wiphy_name(hw->wiphy));
+
 	return ieee80211_reconfig(hw_to_local(hw));
 }
 #else
@@ -1208,7 +1285,8 @@
 			 const u8 *key, u8 key_len, u8 key_idx);
 int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 			     const u8 *ie, size_t ie_len,
-			     enum ieee80211_band band);
+			     enum ieee80211_band band, u32 rate_mask,
+			     u8 channel);
 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 			      const u8 *ssid, size_t ssid_len,
 			      const u8 *ie, size_t ie_len);
@@ -1221,8 +1299,7 @@
 			    enum ieee80211_band band);
 int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
 			     enum ieee80211_smps_mode smps_mode);
-void ieee80211_recalc_smps(struct ieee80211_local *local,
-			   struct ieee80211_sub_if_data *forsdata);
+void ieee80211_recalc_smps(struct ieee80211_local *local);
 
 size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
 			  const u8 *ids, int n_ids, size_t offset);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index ebbe264..f9163b1 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -24,6 +24,7 @@
 #include "led.h"
 #include "driver-ops.h"
 #include "wme.h"
+#include "rate.h"
 
 /**
  * DOC: Interface list locking
@@ -94,21 +95,14 @@
 			 type2 == NL80211_IFTYPE_AP_VLAN));
 }
 
-static int ieee80211_open(struct net_device *dev)
+static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
+					    enum nl80211_iftype iftype)
 {
-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	struct ieee80211_sub_if_data *nsdata;
 	struct ieee80211_local *local = sdata->local;
-	struct sta_info *sta;
-	u32 changed = 0;
-	int res;
-	u32 hw_reconf_flags = 0;
-	u8 null_addr[ETH_ALEN] = {0};
+	struct ieee80211_sub_if_data *nsdata;
+	struct net_device *dev = sdata->dev;
 
-	/* fail early if user set an invalid address */
-	if (compare_ether_addr(dev->dev_addr, null_addr) &&
-	    !is_valid_ether_addr(dev->dev_addr))
-		return -EADDRNOTAVAIL;
+	ASSERT_RTNL();
 
 	/* we hold the RTNL here so can safely walk the list */
 	list_for_each_entry(nsdata, &local->interfaces, list) {
@@ -125,7 +119,7 @@
 			 * belonging to the same hardware. Then, however, we're
 			 * faced with having to adopt two different TSF timers...
 			 */
-			if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
+			if (iftype == NL80211_IFTYPE_ADHOC &&
 			    nsdata->vif.type == NL80211_IFTYPE_ADHOC)
 				return -EBUSY;
 
@@ -139,19 +133,56 @@
 			/*
 			 * check whether it may have the same address
 			 */
-			if (!identical_mac_addr_allowed(sdata->vif.type,
+			if (!identical_mac_addr_allowed(iftype,
 							nsdata->vif.type))
 				return -ENOTUNIQ;
 
 			/*
 			 * can only add VLANs to enabled APs
 			 */
-			if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+			if (iftype == NL80211_IFTYPE_AP_VLAN &&
 			    nsdata->vif.type == NL80211_IFTYPE_AP)
 				sdata->bss = &nsdata->u.ap;
 		}
 	}
 
+	return 0;
+}
+
+void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
+				    const int offset)
+{
+	struct ieee80211_local *local = sdata->local;
+	u32 flags = sdata->u.mntr_flags;
+
+#define ADJUST(_f, _s)	do {					\
+	if (flags & MONITOR_FLAG_##_f)				\
+		local->fif_##_s += offset;			\
+	} while (0)
+
+	ADJUST(FCSFAIL, fcsfail);
+	ADJUST(PLCPFAIL, plcpfail);
+	ADJUST(CONTROL, control);
+	ADJUST(CONTROL, pspoll);
+	ADJUST(OTHER_BSS, other_bss);
+
+#undef ADJUST
+}
+
+/*
+ * NOTE: Be very careful when changing this function, it must NOT return
+ * an error on interface type changes that have been pre-checked, so most
+ * checks should be in ieee80211_check_concurrent_iface.
+ */
+static int ieee80211_do_open(struct net_device *dev, bool coming_up)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_local *local = sdata->local;
+	struct sta_info *sta;
+	u32 changed = 0;
+	int res;
+	u32 hw_reconf_flags = 0;
+
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_WDS:
 		if (!is_valid_ether_addr(sdata->u.wds.remote_addr))
@@ -177,7 +208,9 @@
 		/* no special treatment */
 		break;
 	case NL80211_IFTYPE_UNSPECIFIED:
-	case __NL80211_IFTYPE_AFTER_LAST:
+	case NUM_NL80211_IFTYPES:
+	case NL80211_IFTYPE_P2P_CLIENT:
+	case NL80211_IFTYPE_P2P_GO:
 		/* cannot happen */
 		WARN_ON(1);
 		break;
@@ -187,39 +220,30 @@
 		res = drv_start(local);
 		if (res)
 			goto err_del_bss;
+		if (local->ops->napi_poll)
+			napi_enable(&local->napi);
 		/* we're brought up, everything changes */
 		hw_reconf_flags = ~0;
 		ieee80211_led_radio(local, true);
 	}
 
 	/*
-	 * Check all interfaces and copy the hopefully now-present
-	 * MAC address to those that have the special null one.
+	 * Copy the hopefully now-present MAC address to
+	 * this interface, if it has the special null one.
 	 */
-	list_for_each_entry(nsdata, &local->interfaces, list) {
-		struct net_device *ndev = nsdata->dev;
+	if (is_zero_ether_addr(dev->dev_addr)) {
+		memcpy(dev->dev_addr,
+		       local->hw.wiphy->perm_addr,
+		       ETH_ALEN);
+		memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
 
-		/*
-		 * No need to check running since we do not allow
-		 * it to start up with this invalid address.
-		 */
-		if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) {
-			memcpy(ndev->dev_addr,
-			       local->hw.wiphy->perm_addr,
-			       ETH_ALEN);
-			memcpy(ndev->perm_addr, ndev->dev_addr, ETH_ALEN);
+		if (!is_valid_ether_addr(dev->dev_addr)) {
+			if (!local->open_count)
+				drv_stop(local);
+			return -EADDRNOTAVAIL;
 		}
 	}
 
-	/*
-	 * Validate the MAC address for this device.
-	 */
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		if (!local->open_count)
-			drv_stop(local);
-		return -EADDRNOTAVAIL;
-	}
-
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_AP_VLAN:
 		/* no need to tell driver */
@@ -237,25 +261,17 @@
 			hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
 		}
 
-		if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
-			local->fif_fcsfail++;
-		if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
-			local->fif_plcpfail++;
-		if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) {
-			local->fif_control++;
-			local->fif_pspoll++;
-		}
-		if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
-			local->fif_other_bss++;
-
+		ieee80211_adjust_monitor_flags(sdata, 1);
 		ieee80211_configure_filter(local);
 
 		netif_carrier_on(dev);
 		break;
 	default:
-		res = drv_add_interface(local, &sdata->vif);
-		if (res)
-			goto err_stop;
+		if (coming_up) {
+			res = drv_add_interface(local, &sdata->vif);
+			if (res)
+				goto err_stop;
+		}
 
 		if (ieee80211_vif_is_mesh(&sdata->vif)) {
 			local->fif_other_bss++;
@@ -264,8 +280,11 @@
 			ieee80211_start_mesh(sdata);
 		} else if (sdata->vif.type == NL80211_IFTYPE_AP) {
 			local->fif_pspoll++;
+			local->fif_probe_req++;
 
 			ieee80211_configure_filter(local);
+		} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+			local->fif_probe_req++;
 		}
 
 		changed |= ieee80211_reset_erp_info(sdata);
@@ -277,6 +296,8 @@
 			netif_carrier_on(dev);
 	}
 
+	set_bit(SDATA_STATE_RUNNING, &sdata->state);
+
 	if (sdata->vif.type == NL80211_IFTYPE_WDS) {
 		/* Create STA entry for the WDS peer */
 		sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
@@ -294,6 +315,8 @@
 			/* STA has been freed */
 			goto err_del_interface;
 		}
+
+		rate_control_rate_init(sta);
 	}
 
 	/*
@@ -307,9 +330,13 @@
 	if (sdata->flags & IEEE80211_SDATA_PROMISC)
 		atomic_inc(&local->iff_promiscs);
 
+	mutex_lock(&local->mtx);
 	hw_reconf_flags |= __ieee80211_recalc_idle(local);
+	mutex_unlock(&local->mtx);
 
-	local->open_count++;
+	if (coming_up)
+		local->open_count++;
+
 	if (hw_reconf_flags) {
 		ieee80211_hw_config(local, hw_reconf_flags);
 		/*
@@ -334,22 +361,42 @@
 	sdata->bss = NULL;
 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 		list_del(&sdata->u.vlan.list);
+	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
 	return res;
 }
 
-static int ieee80211_stop(struct net_device *dev)
+static int ieee80211_open(struct net_device *dev)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	int err;
+
+	/* fail early if user set an invalid address */
+	if (!is_zero_ether_addr(dev->dev_addr) &&
+	    !is_valid_ether_addr(dev->dev_addr))
+		return -EADDRNOTAVAIL;
+
+	err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type);
+	if (err)
+		return err;
+
+	return ieee80211_do_open(dev, true);
+}
+
+static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
+			      bool going_down)
+{
 	struct ieee80211_local *local = sdata->local;
 	unsigned long flags;
 	struct sk_buff *skb, *tmp;
 	u32 hw_reconf_flags = 0;
 	int i;
 
+	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
+
 	/*
 	 * Stop TX on this interface first.
 	 */
-	netif_tx_stop_all_queues(dev);
+	netif_tx_stop_all_queues(sdata->dev);
 
 	/*
 	 * Purge work for this interface.
@@ -366,12 +413,9 @@
 	 * (because if we remove a STA after ops->remove_interface()
 	 * the driver will have removed the vif info already!)
 	 *
-	 * We could relax this and only unlink the stations from the
-	 * hash table and list but keep them on a per-sdata list that
-	 * will be inserted back again when the interface is brought
-	 * up again, but I don't currently see a use case for that,
-	 * except with WDS which gets a STA entry created when it is
-	 * brought up.
+	 * This is relevant only in AP, WDS and mesh modes, since in
+	 * all other modes we've already removed all stations when
+	 * disconnecting etc.
 	 */
 	sta_info_flush(local, sdata);
 
@@ -387,14 +431,19 @@
 	if (sdata->flags & IEEE80211_SDATA_PROMISC)
 		atomic_dec(&local->iff_promiscs);
 
-	if (sdata->vif.type == NL80211_IFTYPE_AP)
+	if (sdata->vif.type == NL80211_IFTYPE_AP) {
 		local->fif_pspoll--;
+		local->fif_probe_req--;
+	} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+		local->fif_probe_req--;
+	}
 
-	netif_addr_lock_bh(dev);
+	netif_addr_lock_bh(sdata->dev);
 	spin_lock_bh(&local->filter_lock);
-	__hw_addr_unsync(&local->mc_list, &dev->mc, dev->addr_len);
+	__hw_addr_unsync(&local->mc_list, &sdata->dev->mc,
+			 sdata->dev->addr_len);
 	spin_unlock_bh(&local->filter_lock);
-	netif_addr_unlock_bh(dev);
+	netif_addr_unlock_bh(sdata->dev);
 
 	ieee80211_configure_filter(local);
 
@@ -406,11 +455,21 @@
 		struct ieee80211_sub_if_data *vlan, *tmpsdata;
 		struct beacon_data *old_beacon = sdata->u.ap.beacon;
 
+		/* sdata_running will return false, so this will disable */
+		ieee80211_bss_info_change_notify(sdata,
+						 BSS_CHANGED_BEACON_ENABLED);
+
 		/* remove beacon */
 		rcu_assign_pointer(sdata->u.ap.beacon, NULL);
 		synchronize_rcu();
 		kfree(old_beacon);
 
+		/* free all potentially still buffered bcast frames */
+		while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
+			local->total_ps_buffered--;
+			dev_kfree_skb(skb);
+		}
+
 		/* down all dependent devices, that is VLANs */
 		list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
 					 u.vlan.list)
@@ -418,7 +477,8 @@
 		WARN_ON(!list_empty(&sdata->u.ap.vlans));
 	}
 
-	local->open_count--;
+	if (going_down)
+		local->open_count--;
 
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_AP_VLAN:
@@ -437,40 +497,9 @@
 			hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
 		}
 
-		if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
-			local->fif_fcsfail--;
-		if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
-			local->fif_plcpfail--;
-		if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) {
-			local->fif_pspoll--;
-			local->fif_control--;
-		}
-		if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
-			local->fif_other_bss--;
-
+		ieee80211_adjust_monitor_flags(sdata, -1);
 		ieee80211_configure_filter(local);
 		break;
-	case NL80211_IFTYPE_STATION:
-		del_timer_sync(&sdata->u.mgd.chswitch_timer);
-		del_timer_sync(&sdata->u.mgd.timer);
-		del_timer_sync(&sdata->u.mgd.conn_mon_timer);
-		del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
-		/*
-		 * If any of the timers fired while we waited for it, it will
-		 * have queued its work. Now the work will be running again
-		 * but will not rearm the timer again because it checks
-		 * whether the interface is running, which, at this point,
-		 * it no longer is.
-		 */
-		cancel_work_sync(&sdata->u.mgd.chswitch_work);
-		cancel_work_sync(&sdata->u.mgd.monitor_work);
-		cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work);
-
-		/* fall through */
-	case NL80211_IFTYPE_ADHOC:
-		if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
-			del_timer_sync(&sdata->u.ibss.timer);
-		/* fall through */
 	case NL80211_IFTYPE_MESH_POINT:
 		if (ieee80211_vif_is_mesh(&sdata->vif)) {
 			/* other_bss and allmulti are always set on mesh
@@ -498,27 +527,34 @@
 			ieee80211_scan_cancel(local);
 
 		/*
-		 * Disable beaconing for AP and mesh, IBSS can't
-		 * still be joined to a network at this point.
+		 * Disable beaconing here for mesh only, AP and IBSS
+		 * are already taken care of.
 		 */
-		if (sdata->vif.type == NL80211_IFTYPE_AP ||
-		    sdata->vif.type == NL80211_IFTYPE_MESH_POINT) {
+		if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
 			ieee80211_bss_info_change_notify(sdata,
 				BSS_CHANGED_BEACON_ENABLED);
-		}
 
-		/* free all remaining keys, there shouldn't be any */
+		/*
+		 * Free all remaining keys, there shouldn't be any,
+		 * except maybe group keys in AP more or WDS?
+		 */
 		ieee80211_free_keys(sdata);
-		drv_remove_interface(local, &sdata->vif);
+
+		if (going_down)
+			drv_remove_interface(local, &sdata->vif);
 	}
 
 	sdata->bss = NULL;
 
+	mutex_lock(&local->mtx);
 	hw_reconf_flags |= __ieee80211_recalc_idle(local);
+	mutex_unlock(&local->mtx);
 
 	ieee80211_recalc_ps(local, -1);
 
 	if (local->open_count == 0) {
+		if (local->ops->napi_poll)
+			napi_disable(&local->napi);
 		ieee80211_clear_tx_pending(local);
 		ieee80211_stop_device(local);
 
@@ -541,6 +577,13 @@
 		}
 	}
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+}
+
+static int ieee80211_stop(struct net_device *dev)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	ieee80211_do_stop(sdata, true);
 
 	return 0;
 }
@@ -585,8 +628,6 @@
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = sdata->local;
-	struct beacon_data *beacon;
-	struct sk_buff *skb;
 	int flushed;
 	int i;
 
@@ -599,37 +640,8 @@
 		__skb_queue_purge(&sdata->fragments[i].skb_list);
 	sdata->fragment_next = 0;
 
-	switch (sdata->vif.type) {
-	case NL80211_IFTYPE_AP:
-		beacon = sdata->u.ap.beacon;
-		rcu_assign_pointer(sdata->u.ap.beacon, NULL);
-		synchronize_rcu();
-		kfree(beacon);
-
-		while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
-			local->total_ps_buffered--;
-			dev_kfree_skb(skb);
-		}
-
-		break;
-	case NL80211_IFTYPE_MESH_POINT:
-		if (ieee80211_vif_is_mesh(&sdata->vif))
-			mesh_rmc_free(sdata);
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		if (WARN_ON(sdata->u.ibss.presp))
-			kfree_skb(sdata->u.ibss.presp);
-		break;
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_WDS:
-	case NL80211_IFTYPE_AP_VLAN:
-	case NL80211_IFTYPE_MONITOR:
-		break;
-	case NL80211_IFTYPE_UNSPECIFIED:
-	case __NL80211_IFTYPE_AFTER_LAST:
-		BUG();
-		break;
-	}
+	if (ieee80211_vif_is_mesh(&sdata->vif))
+		mesh_rmc_free(sdata);
 
 	flushed = sta_info_flush(local, sdata);
 	WARN_ON(flushed);
@@ -791,7 +803,8 @@
 
 				__ieee80211_stop_rx_ba_session(
 					sta, tid, WLAN_BACK_RECIPIENT,
-					WLAN_REASON_QSTA_REQUIRE_SETUP);
+					WLAN_REASON_QSTA_REQUIRE_SETUP,
+					true);
 			}
 			mutex_unlock(&local->sta_mtx);
 		} else switch (sdata->vif.type) {
@@ -844,9 +857,13 @@
 
 	/* and set some type-dependent values */
 	sdata->vif.type = type;
+	sdata->vif.p2p = false;
 	sdata->dev->netdev_ops = &ieee80211_dataif_ops;
 	sdata->wdev.iftype = type;
 
+	sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
+	sdata->control_port_no_encrypt = false;
+
 	/* only monitor differs */
 	sdata->dev->type = ARPHRD_ETHER;
 
@@ -854,10 +871,20 @@
 	INIT_WORK(&sdata->work, ieee80211_iface_work);
 
 	switch (type) {
+	case NL80211_IFTYPE_P2P_GO:
+		type = NL80211_IFTYPE_AP;
+		sdata->vif.type = type;
+		sdata->vif.p2p = true;
+		/* fall through */
 	case NL80211_IFTYPE_AP:
 		skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
 		INIT_LIST_HEAD(&sdata->u.ap.vlans);
 		break;
+	case NL80211_IFTYPE_P2P_CLIENT:
+		type = NL80211_IFTYPE_STATION;
+		sdata->vif.type = type;
+		sdata->vif.p2p = true;
+		/* fall through */
 	case NL80211_IFTYPE_STATION:
 		ieee80211_sta_setup_sdata(sdata);
 		break;
@@ -878,7 +905,7 @@
 	case NL80211_IFTYPE_AP_VLAN:
 		break;
 	case NL80211_IFTYPE_UNSPECIFIED:
-	case __NL80211_IFTYPE_AFTER_LAST:
+	case NUM_NL80211_IFTYPES:
 		BUG();
 		break;
 	}
@@ -886,12 +913,85 @@
 	ieee80211_debugfs_add_netdev(sdata);
 }
 
+static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
+					   enum nl80211_iftype type)
+{
+	struct ieee80211_local *local = sdata->local;
+	int ret, err;
+	enum nl80211_iftype internal_type = type;
+	bool p2p = false;
+
+	ASSERT_RTNL();
+
+	if (!local->ops->change_interface)
+		return -EBUSY;
+
+	switch (sdata->vif.type) {
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_ADHOC:
+		/*
+		 * Could maybe also all others here?
+		 * Just not sure how that interacts
+		 * with the RX/config path e.g. for
+		 * mesh.
+		 */
+		break;
+	default:
+		return -EBUSY;
+	}
+
+	switch (type) {
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_ADHOC:
+		/*
+		 * Could probably support everything
+		 * but WDS here (WDS do_open can fail
+		 * under memory pressure, which this
+		 * code isn't prepared to handle).
+		 */
+		break;
+	case NL80211_IFTYPE_P2P_CLIENT:
+		p2p = true;
+		internal_type = NL80211_IFTYPE_STATION;
+		break;
+	case NL80211_IFTYPE_P2P_GO:
+		p2p = true;
+		internal_type = NL80211_IFTYPE_AP;
+		break;
+	default:
+		return -EBUSY;
+	}
+
+	ret = ieee80211_check_concurrent_iface(sdata, internal_type);
+	if (ret)
+		return ret;
+
+	ieee80211_do_stop(sdata, false);
+
+	ieee80211_teardown_sdata(sdata->dev);
+
+	ret = drv_change_interface(local, sdata, internal_type, p2p);
+	if (ret)
+		type = sdata->vif.type;
+
+	ieee80211_setup_sdata(sdata, type);
+
+	err = ieee80211_do_open(sdata->dev, false);
+	WARN(err, "type change: do_open returned %d", err);
+
+	return ret;
+}
+
 int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
 			     enum nl80211_iftype type)
 {
+	int ret;
+
 	ASSERT_RTNL();
 
-	if (type == sdata->vif.type)
+	if (type == ieee80211_vif_type_p2p(&sdata->vif))
 		return 0;
 
 	/* Setting ad-hoc mode on non-IBSS channel is not supported. */
@@ -899,18 +999,15 @@
 	    type == NL80211_IFTYPE_ADHOC)
 		return -EOPNOTSUPP;
 
-	/*
-	 * We could, here, on changes between IBSS/STA/MESH modes,
-	 * invoke an MLME function instead that disassociates etc.
-	 * and goes into the requested mode.
-	 */
-
-	if (ieee80211_sdata_running(sdata))
-		return -EBUSY;
-
-	/* Purge and reset type-dependent state. */
-	ieee80211_teardown_sdata(sdata->dev);
-	ieee80211_setup_sdata(sdata, type);
+	if (ieee80211_sdata_running(sdata)) {
+		ret = ieee80211_runtime_change_iftype(sdata, type);
+		if (ret)
+			return ret;
+	} else {
+		/* Purge and reset type-dependent state. */
+		ieee80211_teardown_sdata(sdata->dev);
+		ieee80211_setup_sdata(sdata, type);
+	}
 
 	/* reset some values that shouldn't be kept across type changes */
 	sdata->vif.bss_conf.basic_rates =
@@ -1167,8 +1264,7 @@
 		return 0;
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: device no longer idle - %s\n",
-	       wiphy_name(local->hw.wiphy), reason);
+	wiphy_debug(local->hw.wiphy, "device no longer idle - %s\n", reason);
 #endif
 
 	local->hw.conf.flags &= ~IEEE80211_CONF_IDLE;
@@ -1181,8 +1277,7 @@
 		return 0;
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: device now idle\n",
-	       wiphy_name(local->hw.wiphy));
+	wiphy_debug(local->hw.wiphy, "device now idle\n");
 #endif
 
 	drv_flush(local, false);
@@ -1195,28 +1290,61 @@
 {
 	struct ieee80211_sub_if_data *sdata;
 	int count = 0;
+	bool working = false, scanning = false;
+	struct ieee80211_work *wk;
 
-	if (!list_empty(&local->work_list))
-		return ieee80211_idle_off(local, "working");
-
-	if (local->scanning)
-		return ieee80211_idle_off(local, "scanning");
+#ifdef CONFIG_PROVE_LOCKING
+	WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
+		!lockdep_is_held(&local->iflist_mtx));
+#endif
+	lockdep_assert_held(&local->mtx);
 
 	list_for_each_entry(sdata, &local->interfaces, list) {
-		if (!ieee80211_sdata_running(sdata))
+		if (!ieee80211_sdata_running(sdata)) {
+			sdata->vif.bss_conf.idle = true;
 			continue;
+		}
+
+		sdata->old_idle = sdata->vif.bss_conf.idle;
+
 		/* do not count disabled managed interfaces */
 		if (sdata->vif.type == NL80211_IFTYPE_STATION &&
-		    !sdata->u.mgd.associated)
+		    !sdata->u.mgd.associated) {
+			sdata->vif.bss_conf.idle = true;
 			continue;
+		}
 		/* do not count unused IBSS interfaces */
 		if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
-		    !sdata->u.ibss.ssid_len)
+		    !sdata->u.ibss.ssid_len) {
+			sdata->vif.bss_conf.idle = true;
 			continue;
+		}
 		/* count everything else */
 		count++;
 	}
 
+	list_for_each_entry(wk, &local->work_list, list) {
+		working = true;
+		wk->sdata->vif.bss_conf.idle = false;
+	}
+
+	if (local->scan_sdata) {
+		scanning = true;
+		local->scan_sdata->vif.bss_conf.idle = false;
+	}
+
+	list_for_each_entry(sdata, &local->interfaces, list) {
+		if (sdata->old_idle == sdata->vif.bss_conf.idle)
+			continue;
+		if (!ieee80211_sdata_running(sdata))
+			continue;
+		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
+	}
+
+	if (working)
+		return ieee80211_idle_off(local, "working");
+	if (scanning)
+		return ieee80211_idle_off(local, "scanning");
 	if (!count)
 		return ieee80211_idle_on(local);
 	else
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 1b9d87e..ccd676b 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -49,7 +49,7 @@
 
 static void assert_key_lock(struct ieee80211_local *local)
 {
-	WARN_ON(!mutex_is_locked(&local->key_mtx));
+	lockdep_assert_held(&local->key_mtx);
 }
 
 static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
@@ -60,7 +60,7 @@
 	return NULL;
 }
 
-static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
+static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 {
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_sta *sta;
@@ -69,12 +69,20 @@
 	might_sleep();
 
 	if (!key->local->ops->set_key)
-		return;
+		goto out_unsupported;
 
 	assert_key_lock(key->local);
 
 	sta = get_sta_for_key(key);
 
+	/*
+	 * If this is a per-STA GTK, check if it
+	 * is supported; if not, return.
+	 */
+	if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) &&
+	    !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK))
+		goto out_unsupported;
+
 	sdata = key->sdata;
 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 		sdata = container_of(sdata->bss,
@@ -83,14 +91,28 @@
 
 	ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
 
-	if (!ret)
+	if (!ret) {
 		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
+		return 0;
+	}
 
-	if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
-		printk(KERN_ERR "mac80211-%s: failed to set key "
-		       "(%d, %pM) to hardware (%d)\n",
-		       wiphy_name(key->local->hw.wiphy),
-		       key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
+	if (ret != -ENOSPC && ret != -EOPNOTSUPP)
+		wiphy_err(key->local->hw.wiphy,
+			  "failed to set key (%d, %pM) to hardware (%d)\n",
+			  key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
+
+ out_unsupported:
+	switch (key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+	case WLAN_CIPHER_SUITE_TKIP:
+	case WLAN_CIPHER_SUITE_CCMP:
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+		/* all of these we can do in software */
+		return 0;
+	default:
+		return -EINVAL;
+	}
 }
 
 static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
@@ -121,14 +143,33 @@
 			  sta, &key->conf);
 
 	if (ret)
-		printk(KERN_ERR "mac80211-%s: failed to remove key "
-		       "(%d, %pM) from hardware (%d)\n",
-		       wiphy_name(key->local->hw.wiphy),
-		       key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
+		wiphy_err(key->local->hw.wiphy,
+			  "failed to remove key (%d, %pM) from hardware (%d)\n",
+			  key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
 
 	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
 }
 
+void ieee80211_key_removed(struct ieee80211_key_conf *key_conf)
+{
+	struct ieee80211_key *key;
+
+	key = container_of(key_conf, struct ieee80211_key, conf);
+
+	might_sleep();
+	assert_key_lock(key->local);
+
+	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
+
+	/*
+	 * Flush TX path to avoid attempts to use this key
+	 * after this function returns. Until then, drivers
+	 * must be prepared to handle the key.
+	 */
+	synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(ieee80211_key_removed);
+
 static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
 					int idx)
 {
@@ -184,6 +225,7 @@
 
 static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
 				    struct sta_info *sta,
+				    bool pairwise,
 				    struct ieee80211_key *old,
 				    struct ieee80211_key *new)
 {
@@ -192,8 +234,14 @@
 	if (new)
 		list_add(&new->list, &sdata->key_list);
 
-	if (sta) {
-		rcu_assign_pointer(sta->key, new);
+	if (sta && pairwise) {
+		rcu_assign_pointer(sta->ptk, new);
+	} else if (sta) {
+		if (old)
+			idx = old->conf.keyidx;
+		else
+			idx = new->conf.keyidx;
+		rcu_assign_pointer(sta->gtk[idx], new);
 	} else {
 		WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
 
@@ -227,20 +275,18 @@
 	}
 }
 
-struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
-					  int idx,
-					  size_t key_len,
+struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 					  const u8 *key_data,
 					  size_t seq_len, const u8 *seq)
 {
 	struct ieee80211_key *key;
-	int i, j;
+	int i, j, err;
 
 	BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
 
 	key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
 	if (!key)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	/*
 	 * Default to software encryption; we'll later upload the
@@ -249,15 +295,16 @@
 	key->conf.flags = 0;
 	key->flags = 0;
 
-	key->conf.alg = alg;
+	key->conf.cipher = cipher;
 	key->conf.keyidx = idx;
 	key->conf.keylen = key_len;
-	switch (alg) {
-	case ALG_WEP:
+	switch (cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
 		key->conf.iv_len = WEP_IV_LEN;
 		key->conf.icv_len = WEP_ICV_LEN;
 		break;
-	case ALG_TKIP:
+	case WLAN_CIPHER_SUITE_TKIP:
 		key->conf.iv_len = TKIP_IV_LEN;
 		key->conf.icv_len = TKIP_ICV_LEN;
 		if (seq) {
@@ -269,7 +316,7 @@
 			}
 		}
 		break;
-	case ALG_CCMP:
+	case WLAN_CIPHER_SUITE_CCMP:
 		key->conf.iv_len = CCMP_HDR_LEN;
 		key->conf.icv_len = CCMP_MIC_LEN;
 		if (seq) {
@@ -278,42 +325,38 @@
 					key->u.ccmp.rx_pn[i][j] =
 						seq[CCMP_PN_LEN - j - 1];
 		}
-		break;
-	case ALG_AES_CMAC:
-		key->conf.iv_len = 0;
-		key->conf.icv_len = sizeof(struct ieee80211_mmie);
-		if (seq)
-			for (j = 0; j < 6; j++)
-				key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
-		break;
-	}
-	memcpy(key->conf.key, key_data, key_len);
-	INIT_LIST_HEAD(&key->list);
-
-	if (alg == ALG_CCMP) {
 		/*
 		 * Initialize AES key state here as an optimization so that
 		 * it does not need to be initialized for every packet.
 		 */
 		key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
-		if (!key->u.ccmp.tfm) {
+		if (IS_ERR(key->u.ccmp.tfm)) {
+			err = PTR_ERR(key->u.ccmp.tfm);
 			kfree(key);
-			return NULL;
+			key = ERR_PTR(err);
 		}
-	}
-
-	if (alg == ALG_AES_CMAC) {
+		break;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+		key->conf.iv_len = 0;
+		key->conf.icv_len = sizeof(struct ieee80211_mmie);
+		if (seq)
+			for (j = 0; j < 6; j++)
+				key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
 		/*
 		 * Initialize AES key state here as an optimization so that
 		 * it does not need to be initialized for every packet.
 		 */
 		key->u.aes_cmac.tfm =
 			ieee80211_aes_cmac_key_setup(key_data);
-		if (!key->u.aes_cmac.tfm) {
+		if (IS_ERR(key->u.aes_cmac.tfm)) {
+			err = PTR_ERR(key->u.aes_cmac.tfm);
 			kfree(key);
-			return NULL;
+			key = ERR_PTR(err);
 		}
+		break;
 	}
+	memcpy(key->conf.key, key_data, key_len);
+	INIT_LIST_HEAD(&key->list);
 
 	return key;
 }
@@ -326,9 +369,9 @@
 	if (key->local)
 		ieee80211_key_disable_hw_accel(key);
 
-	if (key->conf.alg == ALG_CCMP)
+	if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP)
 		ieee80211_aes_key_free(key->u.ccmp.tfm);
-	if (key->conf.alg == ALG_AES_CMAC)
+	if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
 		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
 	if (key->local)
 		ieee80211_debugfs_key_remove(key);
@@ -336,12 +379,13 @@
 	kfree(key);
 }
 
-void ieee80211_key_link(struct ieee80211_key *key,
-			struct ieee80211_sub_if_data *sdata,
-			struct sta_info *sta)
+int ieee80211_key_link(struct ieee80211_key *key,
+		       struct ieee80211_sub_if_data *sdata,
+		       struct sta_info *sta)
 {
 	struct ieee80211_key *old_key;
-	int idx;
+	int idx, ret;
+	bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
 
 	BUG_ON(!sdata);
 	BUG_ON(!key);
@@ -358,13 +402,6 @@
 		 */
 		if (test_sta_flags(sta, WLAN_STA_WME))
 			key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
-
-		/*
-		 * This key is for a specific sta interface,
-		 * inform the driver that it should try to store
-		 * this key as pairwise key.
-		 */
-		key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
 	} else {
 		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
 			struct sta_info *ap;
@@ -386,19 +423,23 @@
 
 	mutex_lock(&sdata->local->key_mtx);
 
-	if (sta)
-		old_key = sta->key;
+	if (sta && pairwise)
+		old_key = sta->ptk;
+	else if (sta)
+		old_key = sta->gtk[idx];
 	else
 		old_key = sdata->keys[idx];
 
-	__ieee80211_key_replace(sdata, sta, old_key, key);
+	__ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
 	__ieee80211_key_destroy(old_key);
 
 	ieee80211_debugfs_key_add(key);
 
-	ieee80211_key_enable_hw_accel(key);
+	ret = ieee80211_key_enable_hw_accel(key);
 
 	mutex_unlock(&sdata->local->key_mtx);
+
+	return ret;
 }
 
 static void __ieee80211_key_free(struct ieee80211_key *key)
@@ -408,7 +449,8 @@
 	 */
 	if (key->sdata)
 		__ieee80211_key_replace(key->sdata, key->sta,
-					key, NULL);
+				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
+				key, NULL);
 	__ieee80211_key_destroy(key);
 }
 
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index b665bbb..0db1c0f 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -16,6 +16,9 @@
 #include <linux/rcupdate.h>
 #include <net/mac80211.h>
 
+#define NUM_DEFAULT_KEYS 4
+#define NUM_DEFAULT_MGMT_KEYS 2
+
 #define WEP_IV_LEN		4
 #define WEP_ICV_LEN		4
 #define ALG_TKIP_KEY_LEN	32
@@ -123,18 +126,16 @@
 	struct ieee80211_key_conf conf;
 };
 
-struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
-					  int idx,
-					  size_t key_len,
+struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 					  const u8 *key_data,
 					  size_t seq_len, const u8 *seq);
 /*
  * Insert a key into data structures (sdata, sta if necessary)
  * to make it used, free old key.
  */
-void ieee80211_key_link(struct ieee80211_key *key,
-			struct ieee80211_sub_if_data *sdata,
-			struct sta_info *sta);
+int __must_check ieee80211_key_link(struct ieee80211_key *key,
+				    struct ieee80211_sub_if_data *sdata,
+				    struct sta_info *sta);
 void ieee80211_key_free(struct ieee80211_local *local,
 			struct ieee80211_key *key);
 void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ded5c38..22bc42b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -54,6 +54,9 @@
 	if (local->monitors || local->scanning)
 		new_flags |= FIF_BCN_PRBRESP_PROMISC;
 
+	if (local->fif_probe_req || local->probe_req_reg)
+		new_flags |= FIF_PROBE_REQ;
+
 	if (local->fif_fcsfail)
 		new_flags |= FIF_FCSFAIL;
 
@@ -99,16 +102,19 @@
 	int ret = 0;
 	int power;
 	enum nl80211_channel_type channel_type;
+	u32 offchannel_flag;
 
 	might_sleep();
 
 	scan_chan = local->scan_channel;
 
+	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) {
+	} else if (local->tmp_channel &&
+		   local->oper_channel != local->tmp_channel) {
 		chan = scan_chan = local->tmp_channel;
 		channel_type = local->tmp_channel_type;
 		local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
@@ -117,8 +123,9 @@
 		channel_type = local->_oper_channel_type;
 		local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
 	}
+	offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
 
-	if (chan != local->hw.conf.channel ||
+	if (offchannel_flag || chan != local->hw.conf.channel ||
 	    channel_type != local->hw.conf.channel_type) {
 		local->hw.conf.channel = chan;
 		local->hw.conf.channel_type = channel_type;
@@ -197,6 +204,8 @@
 		sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
 	else if (sdata->vif.type == NL80211_IFTYPE_AP)
 		sdata->vif.bss_conf.bssid = sdata->vif.addr;
+	else if (sdata->vif.type == NL80211_IFTYPE_WDS)
+		sdata->vif.bss_conf.bssid = NULL;
 	else if (ieee80211_vif_is_mesh(&sdata->vif)) {
 		sdata->vif.bss_conf.bssid = zero;
 	} else {
@@ -207,6 +216,7 @@
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_WDS:
 	case NL80211_IFTYPE_MESH_POINT:
 		break;
 	default:
@@ -291,7 +301,16 @@
 	struct ieee80211_local *local =
 		container_of(work, struct ieee80211_local, restart_work);
 
+	/* wait for scan work complete */
+	flush_workqueue(local->workqueue);
+
+	mutex_lock(&local->mtx);
+	WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
+		"%s called with hardware scan in progress\n", __func__);
+	mutex_unlock(&local->mtx);
+
 	rtnl_lock();
+	ieee80211_scan_cancel(local);
 	ieee80211_reconfig(local);
 	rtnl_unlock();
 }
@@ -302,7 +321,7 @@
 
 	trace_api_restart_hw(local);
 
-	/* use this reason, __ieee80211_resume will unblock it */
+	/* use this reason, ieee80211_reconfig will unblock it */
 	ieee80211_stop_queues_by_reason(hw,
 		IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
@@ -316,7 +335,7 @@
 		container_of(work, struct ieee80211_local, recalc_smps);
 
 	mutex_lock(&local->iflist_mtx);
-	ieee80211_recalc_smps(local, NULL);
+	ieee80211_recalc_smps(local);
 	mutex_unlock(&local->iflist_mtx);
 }
 
@@ -336,9 +355,6 @@
 	struct ieee80211_if_managed *ifmgd;
 	int c = 0;
 
-	if (!netif_running(ndev))
-		return NOTIFY_DONE;
-
 	/* Make sure it's our interface that got changed */
 	if (!wdev)
 		return NOTIFY_DONE;
@@ -349,11 +365,14 @@
 	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
 	bss_conf = &sdata->vif.bss_conf;
 
+	if (!ieee80211_sdata_running(sdata))
+		return NOTIFY_DONE;
+
 	/* ARP filtering is only supported in managed mode */
 	if (sdata->vif.type != NL80211_IFTYPE_STATION)
 		return NOTIFY_DONE;
 
-	idev = sdata->dev->ip_ptr;
+	idev = __in_dev_get_rtnl(sdata->dev);
 	if (!idev)
 		return NOTIFY_DONE;
 
@@ -390,6 +409,80 @@
 }
 #endif
 
+static int ieee80211_napi_poll(struct napi_struct *napi, int budget)
+{
+	struct ieee80211_local *local =
+		container_of(napi, struct ieee80211_local, napi);
+
+	return local->ops->napi_poll(&local->hw, budget);
+}
+
+void ieee80211_napi_schedule(struct ieee80211_hw *hw)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	napi_schedule(&local->napi);
+}
+EXPORT_SYMBOL(ieee80211_napi_schedule);
+
+void ieee80211_napi_complete(struct ieee80211_hw *hw)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	napi_complete(&local->napi);
+}
+EXPORT_SYMBOL(ieee80211_napi_complete);
+
+/* There isn't a lot of sense in it, but you can transmit anything you like */
+static const struct ieee80211_txrx_stypes
+ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+	[NL80211_IFTYPE_ADHOC] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4),
+	},
+	[NL80211_IFTYPE_STATION] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+			BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+	},
+	[NL80211_IFTYPE_AP] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+			BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+			BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+			BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+			BIT(IEEE80211_STYPE_AUTH >> 4) |
+			BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+			BIT(IEEE80211_STYPE_ACTION >> 4),
+	},
+	[NL80211_IFTYPE_AP_VLAN] = {
+		/* copy AP */
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+			BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+			BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+			BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+			BIT(IEEE80211_STYPE_AUTH >> 4) |
+			BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+			BIT(IEEE80211_STYPE_ACTION >> 4),
+	},
+	[NL80211_IFTYPE_P2P_CLIENT] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+			BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+	},
+	[NL80211_IFTYPE_P2P_GO] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+			BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+			BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+			BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+			BIT(IEEE80211_STYPE_AUTH >> 4) |
+			BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+			BIT(IEEE80211_STYPE_ACTION >> 4),
+	},
+};
+
 struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 					const struct ieee80211_ops *ops)
 {
@@ -419,6 +512,8 @@
 	if (!wiphy)
 		return NULL;
 
+	wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes;
+
 	wiphy->flags |= WIPHY_FLAG_NETNS_OK |
 			WIPHY_FLAG_4ADDR_AP |
 			WIPHY_FLAG_4ADDR_STATION;
@@ -444,6 +539,7 @@
 	/* set up some defaults */
 	local->hw.queues = 1;
 	local->hw.max_rates = 1;
+	local->hw.max_report_rates = 0;
 	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;
@@ -455,7 +551,7 @@
 	__hw_addr_init(&local->mc_list);
 
 	mutex_init(&local->iflist_mtx);
-	mutex_init(&local->scan_mtx);
+	mutex_init(&local->mtx);
 
 	mutex_init(&local->key_mtx);
 	spin_lock_init(&local->filter_lock);
@@ -494,6 +590,9 @@
 	skb_queue_head_init(&local->skb_queue);
 	skb_queue_head_init(&local->skb_queue_unreliable);
 
+	/* init dummy netdev for use w/ NAPI */
+	init_dummy_netdev(&local->napi_dev);
+
 	return local_to_hw(local);
 }
 EXPORT_SYMBOL(ieee80211_alloc_hw);
@@ -506,6 +605,7 @@
 	int channels, max_bitrates;
 	bool supp_ht;
 	static const u32 cipher_suites[] = {
+		/* keep WEP first, it may be removed below */
 		WLAN_CIPHER_SUITE_WEP40,
 		WLAN_CIPHER_SUITE_WEP104,
 		WLAN_CIPHER_SUITE_TKIP,
@@ -515,6 +615,9 @@
 		WLAN_CIPHER_SUITE_AES_CMAC
 	};
 
+	if (hw->max_report_rates == 0)
+		hw->max_report_rates = hw->max_rates;
+
 	/*
 	 * generic code guarantees at least one band,
 	 * set this very early because much code assumes
@@ -554,6 +657,14 @@
 	/* mac80211 always supports monitor */
 	local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
 
+#ifndef CONFIG_MAC80211_MESH
+	/* mesh depends on Kconfig, but drivers should set it if they want */
+	local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
+#endif
+
+	/* mac80211 supports control port protocol changing */
+	local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
+
 	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
 		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
 	else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
@@ -589,10 +700,41 @@
 	if (local->hw.wiphy->max_scan_ie_len)
 		local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
 
-	local->hw.wiphy->cipher_suites = cipher_suites;
-	local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
-	if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
-		local->hw.wiphy->n_cipher_suites--;
+	/* Set up cipher suites unless driver already did */
+	if (!local->hw.wiphy->cipher_suites) {
+		local->hw.wiphy->cipher_suites = cipher_suites;
+		local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+		if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
+			local->hw.wiphy->n_cipher_suites--;
+	}
+	if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) {
+		if (local->hw.wiphy->cipher_suites == cipher_suites) {
+			local->hw.wiphy->cipher_suites += 2;
+			local->hw.wiphy->n_cipher_suites -= 2;
+		} else {
+			u32 *suites;
+			int r, w = 0;
+
+			/* Filter out WEP */
+
+			suites = kmemdup(
+				local->hw.wiphy->cipher_suites,
+				sizeof(u32) * local->hw.wiphy->n_cipher_suites,
+				GFP_KERNEL);
+			if (!suites)
+				return -ENOMEM;
+			for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
+				u32 suite = local->hw.wiphy->cipher_suites[r];
+				if (suite == WLAN_CIPHER_SUITE_WEP40 ||
+				    suite == WLAN_CIPHER_SUITE_WEP104)
+					continue;
+				suites[w++] = suite;
+			}
+			local->hw.wiphy->cipher_suites = suites;
+			local->hw.wiphy->n_cipher_suites = w;
+			local->wiphy_ciphers_allocated = true;
+		}
+	}
 
 	result = wiphy_register(local->hw.wiphy);
 	if (result < 0)
@@ -641,16 +783,16 @@
 
 	result = ieee80211_wep_init(local);
 	if (result < 0)
-		printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
-		       wiphy_name(local->hw.wiphy), result);
+		wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
+			    result);
 
 	rtnl_lock();
 
 	result = ieee80211_init_rate_ctrl_alg(local,
 					      hw->rate_control_algorithm);
 	if (result < 0) {
-		printk(KERN_DEBUG "%s: Failed to initialize rate control "
-		       "algorithm\n", wiphy_name(local->hw.wiphy));
+		wiphy_debug(local->hw.wiphy,
+			    "Failed to initialize rate control algorithm\n");
 		goto fail_rate;
 	}
 
@@ -659,8 +801,8 @@
 		result = ieee80211_if_add(local, "wlan%d", NULL,
 					  NL80211_IFTYPE_STATION, NULL);
 		if (result)
-			printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
-			       wiphy_name(local->hw.wiphy));
+			wiphy_warn(local->hw.wiphy,
+				   "Failed to add default virtual iface\n");
 	}
 
 	rtnl_unlock();
@@ -683,6 +825,9 @@
 		goto fail_ifa;
 #endif
 
+	netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll,
+			local->hw.napi_weight);
+
 	return 0;
 
 #ifdef CONFIG_INET
@@ -703,6 +848,8 @@
  fail_workqueue:
 	wiphy_unregister(local->hw.wiphy);
  fail_wiphy_register:
+	if (local->wiphy_ciphers_allocated)
+		kfree(local->hw.wiphy->cipher_suites);
 	kfree(local->int_scan_req);
 	return result;
 }
@@ -738,6 +885,7 @@
 	 */
 	del_timer_sync(&local->work_timer);
 
+	cancel_work_sync(&local->restart_work);
 	cancel_work_sync(&local->reconfig_filter);
 
 	ieee80211_clear_tx_pending(local);
@@ -746,8 +894,7 @@
 
 	if (skb_queue_len(&local->skb_queue) ||
 	    skb_queue_len(&local->skb_queue_unreliable))
-		printk(KERN_WARNING "%s: skb_queue not empty\n",
-		       wiphy_name(local->hw.wiphy));
+		wiphy_warn(local->hw.wiphy, "skb_queue not empty\n");
 	skb_queue_purge(&local->skb_queue);
 	skb_queue_purge(&local->skb_queue_unreliable);
 
@@ -764,7 +911,10 @@
 	struct ieee80211_local *local = hw_to_local(hw);
 
 	mutex_destroy(&local->iflist_mtx);
-	mutex_destroy(&local->scan_mtx);
+	mutex_destroy(&local->mtx);
+
+	if (local->wiphy_ciphers_allocated)
+		kfree(local->hw.wiphy->cipher_suites);
 
 	wiphy_free(local->hw.wiphy);
 }
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index ea13a80..1c91f0f 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -412,7 +412,7 @@
 	enum plink_event event;
 	enum plink_frame_type ftype;
 	size_t baselen;
-	bool deactivated;
+	bool deactivated, matches_local = true;
 	u8 ie_len;
 	u8 *baseaddr;
 	__le16 plid, llid, reason;
@@ -487,6 +487,7 @@
 	/* Now we will figure out the appropriate event... */
 	event = PLINK_UNDEFINED;
 	if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) {
+		matches_local = false;
 		switch (ftype) {
 		case PLINK_OPEN:
 			event = OPN_RJCT;
@@ -498,7 +499,15 @@
 			/* avoid warning */
 			break;
 		}
-		spin_lock_bh(&sta->lock);
+	}
+
+	if (!sta && !matches_local) {
+		rcu_read_unlock();
+		reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
+		llid = 0;
+		mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid,
+				    plid, reason);
+		return;
 	} else if (!sta) {
 		/* ftype == PLINK_OPEN */
 		u32 rates;
@@ -522,7 +531,7 @@
 		}
 		event = OPN_ACPT;
 		spin_lock_bh(&sta->lock);
-	} else {
+	} else if (matches_local) {
 		spin_lock_bh(&sta->lock);
 		switch (ftype) {
 		case PLINK_OPEN:
@@ -564,6 +573,8 @@
 			rcu_read_unlock();
 			return;
 		}
+	} else {
+		spin_lock_bh(&sta->lock);
 	}
 
 	mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b6c163a..a3a9421 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -54,6 +54,12 @@
  */
 #define IEEE80211_SIGNAL_AVE_WEIGHT	3
 
+/*
+ * How many Beacon frames need to have been used in average signal strength
+ * before starting to indicate signal change events.
+ */
+#define IEEE80211_SIGNAL_AVE_MIN_COUNT	4
+
 #define TMR_RUNNING_TIMER	0
 #define TMR_RUNNING_CHANSW	1
 
@@ -86,7 +92,7 @@
 /* utils */
 static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
 {
-	WARN_ON(!mutex_is_locked(&ifmgd->mtx));
+	lockdep_assert_held(&ifmgd->mtx);
 }
 
 /*
@@ -109,7 +115,7 @@
 		mod_timer(&ifmgd->timer, timeout);
 }
 
-static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata)
+void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
 {
 	if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER)
 		return;
@@ -118,6 +124,19 @@
 		  round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME));
 }
 
+void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+	if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
+		return;
+
+	mod_timer(&sdata->u.mgd.conn_mon_timer,
+		  round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
+
+	ifmgd->probe_send_count = 0;
+}
+
 static int ecw2cw(int ecw)
 {
 	return (1 << ecw) - 1;
@@ -778,16 +797,17 @@
 		params.uapsd = uapsd;
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-		printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
-		       "cWmin=%d cWmax=%d txop=%d uapsd=%d\n",
-		       wiphy_name(local->hw.wiphy), queue, aci, acm,
-		       params.aifs, params.cw_min, params.cw_max, params.txop,
-		       params.uapsd);
+		wiphy_debug(local->hw.wiphy,
+			    "WMM queue=%d aci=%d acm=%d aifs=%d "
+			    "cWmin=%d cWmax=%d txop=%d uapsd=%d\n",
+			    queue, aci, acm,
+			    params.aifs, params.cw_min, params.cw_max,
+			    params.txop, params.uapsd);
 #endif
 		if (drv_conf_tx(local, queue, &params))
-			printk(KERN_DEBUG "%s: failed to set TX queue "
-			       "parameters for queue %d\n",
-			       wiphy_name(local->hw.wiphy), queue);
+			wiphy_debug(local->hw.wiphy,
+				    "failed to set TX queue parameters for queue %d\n",
+				    queue);
 	}
 
 	/* enable WMM or activate new settings */
@@ -860,14 +880,6 @@
 	sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
 				IEEE80211_STA_BEACON_POLL);
 
-	/*
-	 * Always handle WMM once after association regardless
-	 * of the first value the AP uses. Setting -1 here has
-	 * that effect because the AP values is an unsigned
-	 * 4-bit value.
-	 */
-	sdata->u.mgd.wmm_last_param_set = -1;
-
 	ieee80211_led_assoc(local, 1);
 
 	if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
@@ -901,7 +913,7 @@
 
 	mutex_lock(&local->iflist_mtx);
 	ieee80211_recalc_ps(local, -1);
-	ieee80211_recalc_smps(local, sdata);
+	ieee80211_recalc_smps(local);
 	mutex_unlock(&local->iflist_mtx);
 
 	netif_tx_start_all_queues(sdata->dev);
@@ -909,7 +921,7 @@
 }
 
 static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
-				   bool remove_sta)
+				   bool remove_sta, bool tx)
 {
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	struct ieee80211_local *local = sdata->local;
@@ -948,7 +960,7 @@
 	sta = sta_info_get(sdata, bssid);
 	if (sta) {
 		set_sta_flags(sta, WLAN_STA_BLOCK_BA);
-		ieee80211_sta_tear_down_BA_sessions(sta);
+		ieee80211_sta_tear_down_BA_sessions(sta, tx);
 	}
 	mutex_unlock(&local->sta_mtx);
 
@@ -990,6 +1002,11 @@
 
 	if (remove_sta)
 		sta_info_destroy_addr(sdata, bssid);
+
+	del_timer_sync(&sdata->u.mgd.conn_mon_timer);
+	del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
+	del_timer_sync(&sdata->u.mgd.timer);
+	del_timer_sync(&sdata->u.mgd.chswitch_timer);
 }
 
 void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -1006,21 +1023,26 @@
 	if (is_multicast_ether_addr(hdr->addr1))
 		return;
 
-	if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
-		return;
-
-	mod_timer(&sdata->u.mgd.conn_mon_timer,
-		  round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
+	ieee80211_sta_reset_conn_monitor(sdata);
 }
 
 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);
+
+	/*
+	 * Try sending broadcast probe requests for the last three
+	 * probe requests after the first ones failed since some
+	 * buggy APs only support broadcast probe requests.
+	 */
+	if (ifmgd->probe_send_count >= unicast_limit)
+		dst = NULL;
 
 	ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
-	ieee80211_send_probe_req(sdata, ifmgd->associated->bssid,
-				 ssid + 2, ssid[1], NULL, 0);
+	ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0);
 
 	ifmgd->probe_send_count++;
 	ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
@@ -1102,9 +1124,12 @@
 
 	printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);
 
-	ieee80211_set_disassoc(sdata, true);
-	ieee80211_recalc_idle(local);
+	ieee80211_set_disassoc(sdata, true, true);
 	mutex_unlock(&ifmgd->mtx);
+
+	mutex_lock(&local->mtx);
+	ieee80211_recalc_idle(local);
+	mutex_unlock(&local->mtx);
 	/*
 	 * must be outside lock due to cfg80211,
 	 * but that's not a problem.
@@ -1172,8 +1197,10 @@
 	printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
 			sdata->name, bssid, reason_code);
 
-	ieee80211_set_disassoc(sdata, true);
+	ieee80211_set_disassoc(sdata, true, false);
+	mutex_lock(&sdata->local->mtx);
 	ieee80211_recalc_idle(sdata->local);
+	mutex_unlock(&sdata->local->mtx);
 
 	return RX_MGMT_CFG80211_DEAUTH;
 }
@@ -1202,8 +1229,10 @@
 	printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
 			sdata->name, mgmt->sa, reason_code);
 
-	ieee80211_set_disassoc(sdata, true);
+	ieee80211_set_disassoc(sdata, true, false);
+	mutex_lock(&sdata->local->mtx);
 	ieee80211_recalc_idle(sdata->local);
+	mutex_unlock(&sdata->local->mtx);
 	return RX_MGMT_CFG80211_DISASSOC;
 }
 
@@ -1262,7 +1291,7 @@
 
 	rates = 0;
 	basic_rates = 0;
-	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+	sband = local->hw.wiphy->bands[wk->chan->band];
 
 	for (i = 0; i < elems.supp_rates_len; i++) {
 		int rate = (elems.supp_rates[i] & 0x7f) * 5;
@@ -1298,11 +1327,11 @@
 		}
 	}
 
-	sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
+	sta->sta.supp_rates[wk->chan->band] = rates;
 	sdata->vif.bss_conf.basic_rates = basic_rates;
 
 	/* cf. IEEE 802.11 9.2.12 */
-	if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
+	if (wk->chan->band == IEEE80211_BAND_2GHZ &&
 	    have_higher_than_11mbit)
 		sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
 	else
@@ -1330,6 +1359,14 @@
 		return false;
 	}
 
+	/*
+	 * Always handle WMM once after association regardless
+	 * of the first value the AP uses. Setting -1 here has
+	 * that effect because the AP values is an unsigned
+	 * 4-bit value.
+	 */
+	ifmgd->wmm_last_param_set = -1;
+
 	if (elems.wmm_param)
 		ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
 					 elems.wmm_param_len);
@@ -1362,7 +1399,7 @@
 	 * Also start the timer that will detect beacon loss.
 	 */
 	ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
-	mod_beacon_timer(sdata);
+	ieee80211_sta_reset_beacon_monitor(sdata);
 
 	return true;
 }
@@ -1465,7 +1502,7 @@
 		 * we have or will be receiving any beacons or data, so let's
 		 * schedule the timers again, just in case.
 		 */
-		mod_beacon_timer(sdata);
+		ieee80211_sta_reset_beacon_monitor(sdata);
 
 		mod_timer(&ifmgd->conn_mon_timer,
 			  round_jiffies_up(jiffies +
@@ -1540,15 +1577,18 @@
 	ifmgd->last_beacon_signal = rx_status->signal;
 	if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
 		ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
-		ifmgd->ave_beacon_signal = rx_status->signal;
+		ifmgd->ave_beacon_signal = rx_status->signal * 16;
 		ifmgd->last_cqm_event_signal = 0;
+		ifmgd->count_beacon_signal = 1;
 	} else {
 		ifmgd->ave_beacon_signal =
 			(IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 +
 			 (16 - IEEE80211_SIGNAL_AVE_WEIGHT) *
 			 ifmgd->ave_beacon_signal) / 16;
+		ifmgd->count_beacon_signal++;
 	}
 	if (bss_conf->cqm_rssi_thold &&
+	    ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT &&
 	    !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) {
 		int sig = ifmgd->ave_beacon_signal / 16;
 		int last_event = ifmgd->last_cqm_event_signal;
@@ -1588,7 +1628,7 @@
 	 * Push the beacon loss detection into the future since
 	 * we are processing a beacon from the AP just now.
 	 */
-	mod_beacon_timer(sdata);
+	ieee80211_sta_reset_beacon_monitor(sdata);
 
 	ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
 	ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
@@ -1599,7 +1639,7 @@
 		directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len,
 						   ifmgd->aid);
 
-	if (ncrc != ifmgd->beacon_crc) {
+	if (ncrc != ifmgd->beacon_crc || !ifmgd->beacon_crc_valid) {
 		ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems,
 				      true);
 
@@ -1630,9 +1670,10 @@
 		}
 	}
 
-	if (ncrc == ifmgd->beacon_crc)
+	if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
 		return;
 	ifmgd->beacon_crc = ncrc;
+	ifmgd->beacon_crc_valid = true;
 
 	if (elems.erp_info && elems.erp_info_len >= 1) {
 		erp_valid = true;
@@ -1751,7 +1792,7 @@
 		struct ieee80211_local *local = sdata->local;
 		struct ieee80211_work *wk;
 
-		mutex_lock(&local->work_mtx);
+		mutex_lock(&local->mtx);
 		list_for_each_entry(wk, &local->work_list, list) {
 			if (wk->sdata != sdata)
 				continue;
@@ -1783,7 +1824,7 @@
 			free_work(wk);
 			break;
 		}
-		mutex_unlock(&local->work_mtx);
+		mutex_unlock(&local->mtx);
 
 		cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
 	}
@@ -1823,10 +1864,12 @@
 
 		else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-			printk(KERN_DEBUG "No probe response from AP %pM"
-				" after %dms, try %d\n", bssid,
-				(1000 * IEEE80211_PROBE_WAIT)/HZ,
-				ifmgd->probe_send_count);
+			wiphy_debug(local->hw.wiphy,
+				    "%s: No probe response from AP %pM"
+				    " after %dms, try %d\n",
+				    sdata->name,
+				    bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ,
+				    ifmgd->probe_send_count);
 #endif
 			ieee80211_mgd_probe_ap_send(sdata);
 		} else {
@@ -1836,12 +1879,16 @@
 			 */
 			ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
 					  IEEE80211_STA_BEACON_POLL);
-			printk(KERN_DEBUG "No probe response from AP %pM"
-				" after %dms, disconnecting.\n",
-				bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
-			ieee80211_set_disassoc(sdata, true);
-			ieee80211_recalc_idle(local);
+			wiphy_debug(local->hw.wiphy,
+				    "%s: No probe response from AP %pM"
+				    " after %dms, disconnecting.\n",
+				    sdata->name,
+				    bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
+			ieee80211_set_disassoc(sdata, true, true);
 			mutex_unlock(&ifmgd->mtx);
+			mutex_lock(&local->mtx);
+			ieee80211_recalc_idle(local);
+			mutex_unlock(&local->mtx);
 			/*
 			 * must be outside lock due to cfg80211,
 			 * but that's not a problem.
@@ -1917,6 +1964,8 @@
 	 * time -- the code here is properly synchronised.
 	 */
 
+	cancel_work_sync(&ifmgd->request_smps_work);
+
 	cancel_work_sync(&ifmgd->beacon_connection_loss_work);
 	if (del_timer_sync(&ifmgd->timer))
 		set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
@@ -1952,6 +2001,7 @@
 	INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
 	INIT_WORK(&ifmgd->beacon_connection_loss_work,
 		  ieee80211_beacon_connection_loss_work);
+	INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work);
 	setup_timer(&ifmgd->timer, ieee80211_sta_timer,
 		    (unsigned long) sdata);
 	setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
@@ -2158,7 +2208,7 @@
 		}
 
 		/* Trying to reassociate - clear previous association state */
-		ieee80211_set_disassoc(sdata, true);
+		ieee80211_set_disassoc(sdata, true, false);
 	}
 	mutex_unlock(&ifmgd->mtx);
 
@@ -2169,6 +2219,8 @@
 	ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;
 	ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
 
+	ifmgd->beacon_crc_valid = false;
+
 	for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
 		if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
 		    req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
@@ -2249,6 +2301,9 @@
 	else
 		ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
 
+	sdata->control_port_protocol = req->crypto.control_port_ethertype;
+	sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
+
 	ieee80211_add_work(wk);
 	return 0;
 }
@@ -2267,7 +2322,7 @@
 
 	memcpy(bssid, req->bss->bssid, ETH_ALEN);
 	if (ifmgd->associated == req->bss) {
-		ieee80211_set_disassoc(sdata, false);
+		ieee80211_set_disassoc(sdata, false, true);
 		mutex_unlock(&ifmgd->mtx);
 		assoc_bss = true;
 	} else {
@@ -2275,7 +2330,7 @@
 
 		mutex_unlock(&ifmgd->mtx);
 
-		mutex_lock(&local->work_mtx);
+		mutex_lock(&local->mtx);
 		list_for_each_entry(wk, &local->work_list, list) {
 			if (wk->sdata != sdata)
 				continue;
@@ -2294,7 +2349,7 @@
 			free_work(wk);
 			break;
 		}
-		mutex_unlock(&local->work_mtx);
+		mutex_unlock(&local->mtx);
 
 		/*
 		 * If somebody requests authentication and we haven't
@@ -2319,7 +2374,9 @@
 	if (assoc_bss)
 		sta_info_destroy_addr(sdata, bssid);
 
+	mutex_lock(&sdata->local->mtx);
 	ieee80211_recalc_idle(sdata->local);
+	mutex_unlock(&sdata->local->mtx);
 
 	return 0;
 }
@@ -2348,7 +2405,7 @@
 	       sdata->name, req->bss->bssid, req->reason_code);
 
 	memcpy(bssid, req->bss->bssid, ETH_ALEN);
-	ieee80211_set_disassoc(sdata, false);
+	ieee80211_set_disassoc(sdata, false, true);
 
 	mutex_unlock(&ifmgd->mtx);
 
@@ -2357,7 +2414,9 @@
 			cookie, !req->local_state_change);
 	sta_info_destroy_addr(sdata, bssid);
 
+	mutex_lock(&sdata->local->mtx);
 	ieee80211_recalc_idle(sdata->local);
+	mutex_unlock(&sdata->local->mtx);
 
 	return 0;
 }
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index c36b191..4b56409 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -22,12 +22,16 @@
 static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
 	local->offchannel_ps_enabled = false;
 
 	/* FIXME: what to do when local->pspolling is true? */
 
 	del_timer_sync(&local->dynamic_ps_timer);
+	del_timer_sync(&ifmgd->bcn_mon_timer);
+	del_timer_sync(&ifmgd->conn_mon_timer);
+
 	cancel_work_sync(&local->dynamic_ps_enable_work);
 
 	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
@@ -85,6 +89,9 @@
 		mod_timer(&local->dynamic_ps_timer, jiffies +
 			  msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
 	}
+
+	ieee80211_sta_reset_beacon_monitor(sdata);
+	ieee80211_sta_reset_conn_monitor(sdata);
 }
 
 void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local)
@@ -112,8 +119,10 @@
 		 * used from user space controlled off-channel operations.
 		 */
 		if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-		    sdata->vif.type != NL80211_IFTYPE_MONITOR)
+		    sdata->vif.type != NL80211_IFTYPE_MONITOR) {
+			set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
 			netif_tx_stop_all_queues(sdata->dev);
+		}
 	}
 	mutex_unlock(&local->iflist_mtx);
 }
@@ -131,6 +140,7 @@
 			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);
@@ -155,8 +165,20 @@
 				ieee80211_offchannel_ps_disable(sdata);
 		}
 
-		if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
+		if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
+			clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
+			/*
+			 * This may wake up queues even though the driver
+			 * currently has them stopped. This is not very
+			 * likely, since the driver won't have gotten any
+			 * (or hardly any) new packets while we weren't
+			 * on the right channel, and even if it happens
+			 * it will at most lead to queueing up one more
+			 * packet per queue in mac80211 rather than on
+			 * the interface qdisc.
+			 */
 			netif_tx_wake_all_queues(sdata->dev);
+		}
 
 		/* re-enable beaconing */
 		if (enable_beaconing &&
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index d287fde..e373551 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -45,7 +45,7 @@
 	list_for_each_entry(sta, &local->sta_list, list) {
 		if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
 			set_sta_flags(sta, WLAN_STA_BLOCK_BA);
-			ieee80211_sta_tear_down_BA_sessions(sta);
+			ieee80211_sta_tear_down_BA_sessions(sta, true);
 		}
 
 		if (sta->uploaded) {
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index be04d461..809cf23 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -145,6 +145,7 @@
 static const struct file_operations rcname_ops = {
 	.read = rcname_read,
 	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 #endif
 
@@ -207,7 +208,7 @@
 
 	fc = hdr->frame_control;
 
-	return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc));
+	return (info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc);
 }
 
 static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u8 max_rate_idx)
@@ -368,8 +369,8 @@
 
 	ref = rate_control_alloc(name, local);
 	if (!ref) {
-		printk(KERN_WARNING "%s: Failed to select rate control "
-		       "algorithm\n", wiphy_name(local->hw.wiphy));
+		wiphy_warn(local->hw.wiphy,
+			   "Failed to select rate control algorithm\n");
 		return -ENOENT;
 	}
 
@@ -380,9 +381,8 @@
 		sta_info_flush(local, NULL);
 	}
 
-	printk(KERN_DEBUG "%s: Selected rate control "
-	       "algorithm '%s'\n", wiphy_name(local->hw.wiphy),
-	       ref->ops->name);
+	wiphy_debug(local->hw.wiphy, "Selected rate control algorithm '%s'\n",
+		    ref->ops->name);
 
 	return 0;
 }
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index 241e76f..a290ad23 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -122,6 +122,7 @@
 	.open = minstrel_stats_open,
 	.read = minstrel_stats_read,
 	.release = minstrel_stats_release,
+	.llseek = default_llseek,
 };
 
 void
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index c5b4659..2a18d66 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -397,8 +397,9 @@
 	    !(info->flags & IEEE80211_TX_STAT_AMPDU))
 		return;
 
-	if (!info->status.ampdu_len) {
-		info->status.ampdu_ack_len = 1;
+	if (!(info->flags & IEEE80211_TX_STAT_AMPDU)) {
+		info->status.ampdu_ack_len =
+			(info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0);
 		info->status.ampdu_len = 1;
 	}
 
@@ -426,7 +427,7 @@
 		group = minstrel_ht_get_group_idx(&ar[i]);
 		rate = &mi->groups[group].rates[ar[i].idx % 8];
 
-		if (last && (info->flags & IEEE80211_TX_STAT_ACK))
+		if (last)
 			rate->success += info->status.ampdu_ack_len;
 
 		rate->attempts += ar[i].count * info->status.ampdu_len;
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 4a5a4b3..cefcb5d 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -90,7 +90,7 @@
 		MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
 	ms->len = p - ms->buf;
 
-	return 0;
+	return nonseekable_open(inode, file);
 }
 
 static const struct file_operations minstrel_ht_stat_fops = {
@@ -98,6 +98,7 @@
 	.open = minstrel_ht_stats_open,
 	.read = minstrel_stats_read,
 	.release = minstrel_stats_release,
+	.llseek = no_llseek,
 };
 
 void
diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c
index 47438b4..4851e9e 100644
--- a/net/mac80211/rc80211_pid_debugfs.c
+++ b/net/mac80211/rc80211_pid_debugfs.c
@@ -162,7 +162,7 @@
 	file_info->next_entry = (file_info->next_entry + 1) %
 				RC_PID_EVENT_RING_SIZE;
 
-	/* Print information about the event. Note that userpace needs to
+	/* Print information about the event. Note that userspace needs to
 	 * provide large enough buffers. */
 	length = length < RC_PID_PRINT_BUF_SIZE ?
 		 length : RC_PID_PRINT_BUF_SIZE;
@@ -206,6 +206,7 @@
 	.poll = rate_control_pid_events_poll,
 	.open = rate_control_pid_events_open,
 	.release = rate_control_pid_events_release,
+	.llseek = noop_llseek,
 };
 
 void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index fa0f37e..902b03ee 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -315,6 +315,7 @@
 static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
 	int tid;
 
 	/* does the frame have a qos control field? */
@@ -323,9 +324,7 @@
 		/* frame has qos control */
 		tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
 		if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
-			rx->flags |= IEEE80211_RX_AMSDU;
-		else
-			rx->flags &= ~IEEE80211_RX_AMSDU;
+			status->rx_flags |= IEEE80211_RX_AMSDU;
 	} else {
 		/*
 		 * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"):
@@ -387,26 +386,25 @@
 ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_local *local = rx->local;
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
 	struct sk_buff *skb = rx->skb;
 
-	if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning)))
+	if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN)))
+		return RX_CONTINUE;
+
+	if (test_bit(SCAN_HW_SCANNING, &local->scanning))
 		return ieee80211_scan_rx(rx->sdata, skb);
 
-	if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning) &&
-		     (rx->flags & IEEE80211_RX_IN_SCAN))) {
+	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;
 	}
 
-	if (unlikely(rx->flags & IEEE80211_RX_IN_SCAN)) {
-		/* scanning finished during invoking of handlers */
-		I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
-		return RX_DROP_UNUSABLE;
-	}
-
-	return RX_CONTINUE;
+	/* scanning finished during invoking of handlers */
+	I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
+	return RX_DROP_UNUSABLE;
 }
 
 
@@ -538,20 +536,12 @@
 					    int index,
 					    struct sk_buff_head *frames)
 {
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_rate *rate = NULL;
 	struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
-	struct ieee80211_rx_status *status;
 
 	if (!skb)
 		goto no_frame;
 
-	status = IEEE80211_SKB_RXCB(skb);
-
-	/* release the reordered frames to stack */
-	sband = hw->wiphy->bands[status->band];
-	if (!(status->flag & RX_FLAG_HT))
-		rate = &sband->bitrates[status->rate_idx];
+	/* release the frame from the reorder ring buffer */
 	tid_agg_rx->stored_mpdu_num--;
 	tid_agg_rx->reorder_buf[index] = NULL;
 	__skb_queue_tail(frames, skb);
@@ -580,9 +570,102 @@
  * frames that have not yet been received are assumed to be lost and the skb
  * can be released for processing. This may also release other skb's from the
  * reorder buffer if there are no additional gaps between the frames.
+ *
+ * Callers must hold tid_agg_rx->reorder_lock.
  */
 #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
 
+static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
+					  struct tid_ampdu_rx *tid_agg_rx,
+					  struct sk_buff_head *frames)
+{
+	int index, j;
+
+	/* release the buffer until next missing frame */
+	index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
+						tid_agg_rx->buf_size;
+	if (!tid_agg_rx->reorder_buf[index] &&
+	    tid_agg_rx->stored_mpdu_num > 1) {
+		/*
+		 * No buffers ready to be released, but check whether any
+		 * frames in the reorder buffer have timed out.
+		 */
+		int skipped = 1;
+		for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
+		     j = (j + 1) % tid_agg_rx->buf_size) {
+			if (!tid_agg_rx->reorder_buf[j]) {
+				skipped++;
+				continue;
+			}
+			if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
+					HT_RX_REORDER_BUF_TIMEOUT))
+				goto set_release_timer;
+
+#ifdef CONFIG_MAC80211_HT_DEBUG
+			if (net_ratelimit())
+				wiphy_debug(hw->wiphy,
+					    "release an RX reorder frame due to timeout on earlier frames\n");
+#endif
+			ieee80211_release_reorder_frame(hw, tid_agg_rx,
+							j, frames);
+
+			/*
+			 * Increment the head seq# also for the skipped slots.
+			 */
+			tid_agg_rx->head_seq_num =
+				(tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;
+			skipped = 0;
+		}
+	} else while (tid_agg_rx->reorder_buf[index]) {
+		ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames);
+		index =	seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
+							tid_agg_rx->buf_size;
+	}
+
+	/*
+	 * Disable the reorder release timer for now.
+	 *
+	 * The current implementation lacks a proper locking scheme
+	 * which would protect vital statistic and debug counters
+	 * from being updated by two different but concurrent BHs.
+	 *
+	 * More information about the topic is available from:
+	 * - thread: http://marc.info/?t=128635927000001
+	 *
+	 * What was wrong:
+	 * =>  http://marc.info/?l=linux-wireless&m=128636170811964
+	 * "Basically the thing is that until your patch, the data
+	 *  in the struct didn't actually need locking because it
+	 *  was accessed by the RX path only which is not concurrent."
+	 *
+	 * List of what needs to be fixed:
+	 * => http://marc.info/?l=linux-wireless&m=128656352920957
+	 *
+
+	if (tid_agg_rx->stored_mpdu_num) {
+		j = index = seq_sub(tid_agg_rx->head_seq_num,
+				    tid_agg_rx->ssn) % tid_agg_rx->buf_size;
+
+		for (; j != (index - 1) % tid_agg_rx->buf_size;
+		     j = (j + 1) % tid_agg_rx->buf_size) {
+			if (tid_agg_rx->reorder_buf[j])
+				break;
+		}
+
+ set_release_timer:
+
+		mod_timer(&tid_agg_rx->reorder_timer,
+			  tid_agg_rx->reorder_time[j] +
+			  HT_RX_REORDER_BUF_TIMEOUT);
+	} else {
+		del_timer(&tid_agg_rx->reorder_timer);
+	}
+	*/
+
+set_release_timer:
+	return;
+}
+
 /*
  * As this function belongs to the RX path it must be under
  * rcu_read_lock protection. It returns false if the frame
@@ -598,14 +681,16 @@
 	u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
 	u16 head_seq_num, buf_size;
 	int index;
+	bool ret = true;
 
 	buf_size = tid_agg_rx->buf_size;
 	head_seq_num = tid_agg_rx->head_seq_num;
 
+	spin_lock(&tid_agg_rx->reorder_lock);
 	/* frame with out of date sequence number */
 	if (seq_less(mpdu_seq_num, head_seq_num)) {
 		dev_kfree_skb(skb);
-		return true;
+		goto out;
 	}
 
 	/*
@@ -626,7 +711,7 @@
 	/* check if we already stored this frame */
 	if (tid_agg_rx->reorder_buf[index]) {
 		dev_kfree_skb(skb);
-		return true;
+		goto out;
 	}
 
 	/*
@@ -636,58 +721,19 @@
 	if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
 	    tid_agg_rx->stored_mpdu_num == 0) {
 		tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
-		return false;
+		ret = false;
+		goto out;
 	}
 
 	/* put the frame in the reordering buffer */
 	tid_agg_rx->reorder_buf[index] = skb;
 	tid_agg_rx->reorder_time[index] = jiffies;
 	tid_agg_rx->stored_mpdu_num++;
-	/* release the buffer until next missing frame */
-	index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
-						tid_agg_rx->buf_size;
-	if (!tid_agg_rx->reorder_buf[index] &&
-	    tid_agg_rx->stored_mpdu_num > 1) {
-		/*
-		 * No buffers ready to be released, but check whether any
-		 * frames in the reorder buffer have timed out.
-		 */
-		int j;
-		int skipped = 1;
-		for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
-		     j = (j + 1) % tid_agg_rx->buf_size) {
-			if (!tid_agg_rx->reorder_buf[j]) {
-				skipped++;
-				continue;
-			}
-			if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
-					HT_RX_REORDER_BUF_TIMEOUT))
-				break;
+	ieee80211_sta_reorder_release(hw, tid_agg_rx, frames);
 
-#ifdef CONFIG_MAC80211_HT_DEBUG
-			if (net_ratelimit())
-				printk(KERN_DEBUG "%s: release an RX reorder "
-				       "frame due to timeout on earlier "
-				       "frames\n",
-				       wiphy_name(hw->wiphy));
-#endif
-			ieee80211_release_reorder_frame(hw, tid_agg_rx,
-							j, frames);
-
-			/*
-			 * Increment the head seq# also for the skipped slots.
-			 */
-			tid_agg_rx->head_seq_num =
-				(tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;
-			skipped = 0;
-		}
-	} else while (tid_agg_rx->reorder_buf[index]) {
-		ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames);
-		index =	seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
-							tid_agg_rx->buf_size;
-	}
-
-	return true;
+ out:
+	spin_unlock(&tid_agg_rx->reorder_lock);
+	return ret;
 }
 
 /*
@@ -761,13 +807,14 @@
 ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
 
 	/* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
 	if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
 		if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
 			     rx->sta->last_seq_ctrl[rx->queue] ==
 			     hdr->seq_ctrl)) {
-			if (rx->flags & IEEE80211_RX_RA_MATCH) {
+			if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
 				rx->local->dot11FrameDuplicateCount++;
 				rx->sta->num_duplicates++;
 			}
@@ -796,11 +843,12 @@
 	if (unlikely((ieee80211_is_data(hdr->frame_control) ||
 		      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)) ||
-		    !(rx->flags & IEEE80211_RX_RA_MATCH)) {
+		    !(status->rx_flags & IEEE80211_RX_RA_MATCH)) {
 			/* Drop IBSS frames and frames for other hosts
 			 * silently. */
 			return RX_DROP_MONITOR;
@@ -822,7 +870,7 @@
 	int keyidx;
 	int hdrlen;
 	ieee80211_rx_result result = RX_DROP_UNUSABLE;
-	struct ieee80211_key *stakey = NULL;
+	struct ieee80211_key *sta_ptk = NULL;
 	int mmie_keyidx = -1;
 	__le16 fc;
 
@@ -857,22 +905,25 @@
 	 * No point in finding a key and decrypting if the frame is neither
 	 * addressed to us nor a multicast frame.
 	 */
-	if (!(rx->flags & IEEE80211_RX_RA_MATCH))
+	if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
 		return RX_CONTINUE;
 
 	/* start without a key */
 	rx->key = NULL;
 
 	if (rx->sta)
-		stakey = rcu_dereference(rx->sta->key);
+		sta_ptk = rcu_dereference(rx->sta->ptk);
 
 	fc = hdr->frame_control;
 
 	if (!ieee80211_has_protected(fc))
 		mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
 
-	if (!is_multicast_ether_addr(hdr->addr1) && stakey) {
-		rx->key = stakey;
+	if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) {
+		rx->key = sta_ptk;
+		if ((status->flag & RX_FLAG_DECRYPTED) &&
+		    (status->flag & RX_FLAG_IV_STRIPPED))
+			return RX_CONTINUE;
 		/* Skip decryption if the frame is not protected. */
 		if (!ieee80211_has_protected(fc))
 			return RX_CONTINUE;
@@ -885,7 +936,10 @@
 		if (mmie_keyidx < NUM_DEFAULT_KEYS ||
 		    mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
 			return RX_DROP_MONITOR; /* unexpected BIP keyidx */
-		rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
+		if (rx->sta)
+			rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]);
+		if (!rx->key)
+			rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
 	} else if (!ieee80211_has_protected(fc)) {
 		/*
 		 * The frame was not protected, so skip decryption. However, we
@@ -928,16 +982,25 @@
 		skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
 		keyidx = keyid >> 6;
 
-		rx->key = rcu_dereference(rx->sdata->keys[keyidx]);
+		/* check per-station GTK first, if multicast packet */
+		if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
+			rx->key = rcu_dereference(rx->sta->gtk[keyidx]);
 
-		/*
-		 * RSNA-protected unicast frames should always be sent with
-		 * pairwise or station-to-station keys, but for WEP we allow
-		 * using a key index as well.
-		 */
-		if (rx->key && rx->key->conf.alg != ALG_WEP &&
-		    !is_multicast_ether_addr(hdr->addr1))
-			rx->key = NULL;
+		/* if not found, try default key */
+		if (!rx->key) {
+			rx->key = rcu_dereference(rx->sdata->keys[keyidx]);
+
+			/*
+			 * RSNA-protected unicast frames should always be
+			 * sent with pairwise or station-to-station keys,
+			 * but for WEP we allow using a key index as well.
+			 */
+			if (rx->key &&
+			    rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 &&
+			    rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 &&
+			    !is_multicast_ether_addr(hdr->addr1))
+				rx->key = NULL;
+		}
 	}
 
 	if (rx->key) {
@@ -951,8 +1014,9 @@
 		return RX_DROP_UNUSABLE;
 	/* the hdr variable is invalid now! */
 
-	switch (rx->key->conf.alg) {
-	case ALG_WEP:
+	switch (rx->key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
 		/* Check for weak IVs if possible */
 		if (rx->sta && ieee80211_is_data(fc) &&
 		    (!(status->flag & RX_FLAG_IV_STRIPPED) ||
@@ -962,15 +1026,21 @@
 
 		result = ieee80211_crypto_wep_decrypt(rx);
 		break;
-	case ALG_TKIP:
+	case WLAN_CIPHER_SUITE_TKIP:
 		result = ieee80211_crypto_tkip_decrypt(rx);
 		break;
-	case ALG_CCMP:
+	case WLAN_CIPHER_SUITE_CCMP:
 		result = ieee80211_crypto_ccmp_decrypt(rx);
 		break;
-	case ALG_AES_CMAC:
+	case WLAN_CIPHER_SUITE_AES_CMAC:
 		result = ieee80211_crypto_aes_cmac_decrypt(rx);
 		break;
+	default:
+		/*
+		 * We can reach here only with HW-only algorithms
+		 * but why didn't it decrypt the frame?!
+		 */
+		return RX_DROP_UNUSABLE;
 	}
 
 	/* either the frame has been decrypted or will be dropped */
@@ -1079,7 +1149,7 @@
 		sta->last_rx = jiffies;
 	}
 
-	if (!(rx->flags & IEEE80211_RX_RA_MATCH))
+	if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
 		return RX_CONTINUE;
 
 	if (rx->sdata->vif.type == NL80211_IFTYPE_STATION)
@@ -1236,6 +1306,7 @@
 	unsigned int frag, seq;
 	struct ieee80211_fragment_entry *entry;
 	struct sk_buff *skb;
+	struct ieee80211_rx_status *status;
 
 	hdr = (struct ieee80211_hdr *)rx->skb->data;
 	fc = hdr->frame_control;
@@ -1265,7 +1336,7 @@
 		/* This is the first fragment of a new frame. */
 		entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
 						 rx->queue, &(rx->skb));
-		if (rx->key && rx->key->conf.alg == ALG_CCMP &&
+		if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP &&
 		    ieee80211_has_protected(fc)) {
 			int queue = ieee80211_is_mgmt(fc) ?
 				NUM_RX_DATA_QUEUES : rx->queue;
@@ -1294,7 +1365,7 @@
 		int i;
 		u8 pn[CCMP_PN_LEN], *rpn;
 		int queue;
-		if (!rx->key || rx->key->conf.alg != ALG_CCMP)
+		if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP)
 			return RX_DROP_UNUSABLE;
 		memcpy(pn, entry->last_pn, CCMP_PN_LEN);
 		for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
@@ -1335,7 +1406,8 @@
 	}
 
 	/* Complete frame has been reassembled - process it now */
-	rx->flags |= IEEE80211_RX_FRAGMENTED;
+	status = IEEE80211_SKB_RXCB(rx->skb);
+	status->rx_flags |= IEEE80211_RX_FRAGMENTED;
 
  out:
 	if (rx->sta)
@@ -1352,9 +1424,10 @@
 {
 	struct ieee80211_sub_if_data *sdata = rx->sdata;
 	__le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control;
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
 
 	if (likely(!rx->sta || !ieee80211_is_pspoll(fc) ||
-		   !(rx->flags & IEEE80211_RX_RA_MATCH)))
+		   !(status->rx_flags & IEEE80211_RX_RA_MATCH)))
 		return RX_CONTINUE;
 
 	if ((sdata->vif.type != NL80211_IFTYPE_AP) &&
@@ -1492,7 +1565,7 @@
 	 * Allow EAPOL frames to us/the PAE group address regardless
 	 * of whether the frame was encrypted or not.
 	 */
-	if (ehdr->h_proto == htons(ETH_P_PAE) &&
+	if (ehdr->h_proto == rx->sdata->control_port_protocol &&
 	    (compare_ether_addr(ehdr->h_dest, rx->sdata->vif.addr) == 0 ||
 	     compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0))
 		return true;
@@ -1515,6 +1588,7 @@
 	struct sk_buff *skb, *xmit_skb;
 	struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
 	struct sta_info *dsta;
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
 
 	skb = rx->skb;
 	xmit_skb = NULL;
@@ -1522,7 +1596,7 @@
 	if ((sdata->vif.type == NL80211_IFTYPE_AP ||
 	     sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
 	    !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
-	    (rx->flags & IEEE80211_RX_RA_MATCH) &&
+	    (status->rx_flags & IEEE80211_RX_RA_MATCH) &&
 	    (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
 		if (is_multicast_ether_addr(ehdr->h_dest)) {
 			/*
@@ -1599,6 +1673,7 @@
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	__le16 fc = hdr->frame_control;
 	struct sk_buff_head frame_list;
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
 
 	if (unlikely(!ieee80211_is_data(fc)))
 		return RX_CONTINUE;
@@ -1606,7 +1681,7 @@
 	if (unlikely(!ieee80211_is_data_present(fc)))
 		return RX_DROP_MONITOR;
 
-	if (!(rx->flags & IEEE80211_RX_AMSDU))
+	if (!(status->rx_flags & IEEE80211_RX_AMSDU))
 		return RX_CONTINUE;
 
 	if (ieee80211_has_a4(hdr->frame_control) &&
@@ -1657,6 +1732,7 @@
 	struct sk_buff *skb = rx->skb, *fwd_skb;
 	struct ieee80211_local *local = rx->local;
 	struct ieee80211_sub_if_data *sdata = rx->sdata;
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
 	hdr = (struct ieee80211_hdr *) skb->data;
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
@@ -1702,7 +1778,7 @@
 
 	mesh_hdr->ttl--;
 
-	if (rx->flags & IEEE80211_RX_RA_MATCH) {
+	if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
 		if (!mesh_hdr->ttl)
 			IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh,
 						     dropped_frames_ttl);
@@ -1909,13 +1985,38 @@
 }
 
 static ieee80211_rx_result debug_noinline
+ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
+{
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+
+	/*
+	 * From here on, look only at management frames.
+	 * Data and control frames are already handled,
+	 * and unknown (reserved) frames are useless.
+	 */
+	if (rx->skb->len < 24)
+		return RX_DROP_MONITOR;
+
+	if (!ieee80211_is_mgmt(mgmt->frame_control))
+		return RX_DROP_MONITOR;
+
+	if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
+		return RX_DROP_MONITOR;
+
+	if (ieee80211_drop_unencrypted_mgmt(rx))
+		return RX_DROP_UNUSABLE;
+
+	return RX_CONTINUE;
+}
+
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_local *local = rx->local;
 	struct ieee80211_sub_if_data *sdata = rx->sdata;
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
-	struct sk_buff *nskb;
-	struct ieee80211_rx_status *status;
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
 	int len = rx->skb->len;
 
 	if (!ieee80211_is_action(mgmt->frame_control))
@@ -1928,10 +2029,7 @@
 	if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
 		return RX_DROP_UNUSABLE;
 
-	if (!(rx->flags & IEEE80211_RX_RA_MATCH))
-		return RX_DROP_UNUSABLE;
-
-	if (ieee80211_drop_unencrypted_mgmt(rx))
+	if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
 		return RX_DROP_UNUSABLE;
 
 	switch (mgmt->u.action.category) {
@@ -2024,17 +2122,36 @@
 		goto queue;
 	}
 
+	return RX_CONTINUE;
+
  invalid:
-	/*
-	 * For AP mode, hostapd is responsible for handling any action
-	 * frames that we didn't handle, including returning unknown
-	 * ones. For all other modes we will return them to the sender,
-	 * setting the 0x80 bit in the action category, as required by
-	 * 802.11-2007 7.3.1.11.
-	 */
-	if (sdata->vif.type == NL80211_IFTYPE_AP ||
-	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-		return RX_DROP_MONITOR;
+	status->rx_flags |= IEEE80211_RX_MALFORMED_ACTION_FRM;
+	/* will return in the next handlers */
+	return RX_CONTINUE;
+
+ handled:
+	if (rx->sta)
+		rx->sta->rx_packets++;
+	dev_kfree_skb(rx->skb);
+	return RX_QUEUED;
+
+ queue:
+	rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
+	skb_queue_tail(&sdata->skb_queue, rx->skb);
+	ieee80211_queue_work(&local->hw, &sdata->work);
+	if (rx->sta)
+		rx->sta->rx_packets++;
+	return RX_QUEUED;
+}
+
+static ieee80211_rx_result debug_noinline
+ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
+{
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+
+	/* skip known-bad action frames and return them in the next handler */
+	if (status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM)
+		return RX_CONTINUE;
 
 	/*
 	 * Getting here means the kernel doesn't know how to handle
@@ -2042,12 +2159,46 @@
 	 * so userspace can register for those to know whether ones
 	 * it transmitted were processed or returned.
 	 */
-	status = IEEE80211_SKB_RXCB(rx->skb);
 
-	if (cfg80211_rx_action(rx->sdata->dev, status->freq,
-			       rx->skb->data, rx->skb->len,
-			       GFP_ATOMIC))
-		goto handled;
+	if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq,
+			     rx->skb->data, rx->skb->len,
+			     GFP_ATOMIC)) {
+		if (rx->sta)
+			rx->sta->rx_packets++;
+		dev_kfree_skb(rx->skb);
+		return RX_QUEUED;
+	}
+
+
+	return RX_CONTINUE;
+}
+
+static ieee80211_rx_result debug_noinline
+ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
+{
+	struct ieee80211_local *local = rx->local;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
+	struct sk_buff *nskb;
+	struct ieee80211_sub_if_data *sdata = rx->sdata;
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+
+	if (!ieee80211_is_action(mgmt->frame_control))
+		return RX_CONTINUE;
+
+	/*
+	 * For AP mode, hostapd is responsible for handling any action
+	 * frames that we didn't handle, including returning unknown
+	 * ones. For all other modes we will return them to the sender,
+	 * setting the 0x80 bit in the action category, as required by
+	 * 802.11-2007 7.3.1.11.
+	 * Newer versions of hostapd shall also use the management frame
+	 * registration mechanisms, but older ones still use cooked
+	 * monitor interfaces so push all frames there.
+	 */
+	if (!(status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM) &&
+	    (sdata->vif.type == NL80211_IFTYPE_AP ||
+	     sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
+		return RX_DROP_MONITOR;
 
 	/* do not return rejected action frames */
 	if (mgmt->u.action.category & 0x80)
@@ -2066,20 +2217,8 @@
 
 		ieee80211_tx_skb(rx->sdata, nskb);
 	}
-
- handled:
-	if (rx->sta)
-		rx->sta->rx_packets++;
 	dev_kfree_skb(rx->skb);
 	return RX_QUEUED;
-
- queue:
-	rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
-	skb_queue_tail(&sdata->skb_queue, rx->skb);
-	ieee80211_queue_work(&local->hw, &sdata->work);
-	if (rx->sta)
-		rx->sta->rx_packets++;
-	return RX_QUEUED;
 }
 
 static ieee80211_rx_result debug_noinline
@@ -2090,15 +2229,6 @@
 	struct ieee80211_mgmt *mgmt = (void *)rx->skb->data;
 	__le16 stype;
 
-	if (!(rx->flags & IEEE80211_RX_RA_MATCH))
-		return RX_DROP_MONITOR;
-
-	if (rx->skb->len < 24)
-		return RX_DROP_MONITOR;
-
-	if (ieee80211_drop_unencrypted_mgmt(rx))
-		return RX_DROP_UNUSABLE;
-
 	rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb);
 	if (rxs != RX_CONTINUE)
 		return rxs;
@@ -2199,8 +2329,13 @@
 	struct net_device *prev_dev = NULL;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
-	if (status->flag & RX_FLAG_INTERNAL_CMTR)
+	/*
+	 * If cooked monitor has been processed already, then
+	 * don't do it again. If not, set the flag.
+	 */
+	if (rx->flags & IEEE80211_RX_CMNTR)
 		goto out_free_skb;
+	rx->flags |= IEEE80211_RX_CMNTR;
 
 	if (skb_headroom(skb) < sizeof(*rthdr) &&
 	    pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC))
@@ -2256,30 +2391,53 @@
 	if (prev_dev) {
 		skb->dev = prev_dev;
 		netif_receive_skb(skb);
-		skb = NULL;
-	} else
-		goto out_free_skb;
-
-	status->flag |= RX_FLAG_INTERNAL_CMTR;
-	return;
+		return;
+	}
 
  out_free_skb:
 	dev_kfree_skb(skb);
 }
 
-
-static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
-					 struct ieee80211_rx_data *rx,
-					 struct sk_buff *skb,
-					 struct ieee80211_rate *rate)
+static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
+					 ieee80211_rx_result res)
 {
-	struct sk_buff_head reorder_release;
+	switch (res) {
+	case RX_DROP_MONITOR:
+		I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop);
+		if (rx->sta)
+			rx->sta->rx_dropped++;
+		/* fall through */
+	case RX_CONTINUE: {
+		struct ieee80211_rate *rate = NULL;
+		struct ieee80211_supported_band *sband;
+		struct ieee80211_rx_status *status;
+
+		status = IEEE80211_SKB_RXCB((rx->skb));
+
+		sband = rx->local->hw.wiphy->bands[status->band];
+		if (!(status->flag & RX_FLAG_HT))
+			rate = &sband->bitrates[status->rate_idx];
+
+		ieee80211_rx_cooked_monitor(rx, rate);
+		break;
+		}
+	case RX_DROP_UNUSABLE:
+		I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop);
+		if (rx->sta)
+			rx->sta->rx_dropped++;
+		dev_kfree_skb(rx->skb);
+		break;
+	case RX_QUEUED:
+		I802_DEBUG_INC(rx->sdata->local->rx_handlers_queued);
+		break;
+	}
+}
+
+static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
+				  struct sk_buff_head *frames)
+{
 	ieee80211_rx_result res = RX_DROP_MONITOR;
-
-	__skb_queue_head_init(&reorder_release);
-
-	rx->skb = skb;
-	rx->sdata = sdata;
+	struct sk_buff *skb;
 
 #define CALL_RXH(rxh)			\
 	do {				\
@@ -2288,23 +2446,14 @@
 			goto rxh_next;  \
 	} while (0);
 
-	/*
-	 * NB: the rxh_next label works even if we jump
-	 *     to it from here because then the list will
-	 *     be empty, which is a trivial check
-	 */
-	CALL_RXH(ieee80211_rx_h_passive_scan)
-	CALL_RXH(ieee80211_rx_h_check)
-
-	ieee80211_rx_reorder_ampdu(rx, &reorder_release);
-
-	while ((skb = __skb_dequeue(&reorder_release))) {
+	while ((skb = __skb_dequeue(frames))) {
 		/*
 		 * all the other fields are valid across frames
 		 * that belong to an aMPDU since they are on the
 		 * same TID from the same station
 		 */
 		rx->skb = skb;
+		rx->flags = 0;
 
 		CALL_RXH(ieee80211_rx_h_decrypt)
 		CALL_RXH(ieee80211_rx_h_check_more_data)
@@ -2316,50 +2465,92 @@
 		CALL_RXH(ieee80211_rx_h_remove_qos_control)
 		CALL_RXH(ieee80211_rx_h_amsdu)
 #ifdef CONFIG_MAC80211_MESH
-		if (ieee80211_vif_is_mesh(&sdata->vif))
+		if (ieee80211_vif_is_mesh(&rx->sdata->vif))
 			CALL_RXH(ieee80211_rx_h_mesh_fwding);
 #endif
 		CALL_RXH(ieee80211_rx_h_data)
 
 		/* special treatment -- needs the queue */
-		res = ieee80211_rx_h_ctrl(rx, &reorder_release);
+		res = ieee80211_rx_h_ctrl(rx, frames);
 		if (res != RX_CONTINUE)
 			goto rxh_next;
 
+		CALL_RXH(ieee80211_rx_h_mgmt_check)
 		CALL_RXH(ieee80211_rx_h_action)
+		CALL_RXH(ieee80211_rx_h_userspace_mgmt)
+		CALL_RXH(ieee80211_rx_h_action_return)
 		CALL_RXH(ieee80211_rx_h_mgmt)
 
+ rxh_next:
+		ieee80211_rx_handlers_result(rx, res);
+
 #undef CALL_RXH
+	}
+}
+
+static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
+{
+	struct sk_buff_head reorder_release;
+	ieee80211_rx_result res = RX_DROP_MONITOR;
+
+	__skb_queue_head_init(&reorder_release);
+
+#define CALL_RXH(rxh)			\
+	do {				\
+		res = rxh(rx);		\
+		if (res != RX_CONTINUE)	\
+			goto rxh_next;  \
+	} while (0);
+
+	CALL_RXH(ieee80211_rx_h_passive_scan)
+	CALL_RXH(ieee80211_rx_h_check)
+
+	ieee80211_rx_reorder_ampdu(rx, &reorder_release);
+
+	ieee80211_rx_handlers(rx, &reorder_release);
+	return;
 
  rxh_next:
-		switch (res) {
-		case RX_DROP_MONITOR:
-			I802_DEBUG_INC(sdata->local->rx_handlers_drop);
-			if (rx->sta)
-				rx->sta->rx_dropped++;
-			/* fall through */
-		case RX_CONTINUE:
-			ieee80211_rx_cooked_monitor(rx, rate);
-			break;
-		case RX_DROP_UNUSABLE:
-			I802_DEBUG_INC(sdata->local->rx_handlers_drop);
-			if (rx->sta)
-				rx->sta->rx_dropped++;
-			dev_kfree_skb(rx->skb);
-			break;
-		case RX_QUEUED:
-			I802_DEBUG_INC(sdata->local->rx_handlers_queued);
-			break;
-		}
-	}
+	ieee80211_rx_handlers_result(rx, res);
+
+#undef CALL_RXH
+}
+
+/*
+ * This function makes calls into the RX path. Therefore the
+ * caller must hold the sta_info->lock and everything has to
+ * be under rcu_read_lock protection as well.
+ */
+void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
+{
+	struct sk_buff_head frames;
+	struct ieee80211_rx_data rx = {
+		.sta = sta,
+		.sdata = sta->sdata,
+		.local = sta->local,
+		.queue = tid,
+	};
+	struct tid_ampdu_rx *tid_agg_rx;
+
+	tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
+	if (!tid_agg_rx)
+		return;
+
+	__skb_queue_head_init(&frames);
+
+	spin_lock(&tid_agg_rx->reorder_lock);
+	ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx, &frames);
+	spin_unlock(&tid_agg_rx->reorder_lock);
+
+	ieee80211_rx_handlers(&rx, &frames);
 }
 
 /* main receive path */
 
-static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
-				struct ieee80211_rx_data *rx,
+static int prepare_for_handlers(struct ieee80211_rx_data *rx,
 				struct ieee80211_hdr *hdr)
 {
+	struct ieee80211_sub_if_data *sdata = rx->sdata;
 	struct sk_buff *skb = rx->skb;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
@@ -2373,7 +2564,7 @@
 		    compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) {
 			if (!(sdata->dev->flags & IFF_PROMISC))
 				return 0;
-			rx->flags &= ~IEEE80211_RX_RA_MATCH;
+			status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
 		}
 		break;
 	case NL80211_IFTYPE_ADHOC:
@@ -2383,15 +2574,15 @@
 			return 1;
 		}
 		else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
-			if (!(rx->flags & IEEE80211_RX_IN_SCAN))
+			if (!(status->rx_flags & IEEE80211_RX_IN_SCAN))
 				return 0;
-			rx->flags &= ~IEEE80211_RX_RA_MATCH;
+			status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
 		} else if (!multicast &&
 			   compare_ether_addr(sdata->vif.addr,
 					      hdr->addr1) != 0) {
 			if (!(sdata->dev->flags & IFF_PROMISC))
 				return 0;
-			rx->flags &= ~IEEE80211_RX_RA_MATCH;
+			status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
 		} else if (!rx->sta) {
 			int rate_idx;
 			if (status->flag & RX_FLAG_HT)
@@ -2409,7 +2600,7 @@
 			if (!(sdata->dev->flags & IFF_PROMISC))
 				return 0;
 
-			rx->flags &= ~IEEE80211_RX_RA_MATCH;
+			status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
 		}
 		break;
 	case NL80211_IFTYPE_AP_VLAN:
@@ -2420,9 +2611,9 @@
 				return 0;
 		} else if (!ieee80211_bssid_match(bssid,
 					sdata->vif.addr)) {
-			if (!(rx->flags & IEEE80211_RX_IN_SCAN))
+			if (!(status->rx_flags & IEEE80211_RX_IN_SCAN))
 				return 0;
-			rx->flags &= ~IEEE80211_RX_RA_MATCH;
+			status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
 		}
 		break;
 	case NL80211_IFTYPE_WDS:
@@ -2431,9 +2622,7 @@
 		if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))
 			return 0;
 		break;
-	case NL80211_IFTYPE_MONITOR:
-	case NL80211_IFTYPE_UNSPECIFIED:
-	case __NL80211_IFTYPE_AFTER_LAST:
+	default:
 		/* should never get here */
 		WARN_ON(1);
 		break;
@@ -2443,12 +2632,56 @@
 }
 
 /*
+ * This function returns whether or not the SKB
+ * was destined for RX processing or not, which,
+ * if consume is true, is equivalent to whether
+ * or not the skb was consumed.
+ */
+static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
+					    struct sk_buff *skb, bool consume)
+{
+	struct ieee80211_local *local = rx->local;
+	struct ieee80211_sub_if_data *sdata = rx->sdata;
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+	struct ieee80211_hdr *hdr = (void *)skb->data;
+	int prepares;
+
+	rx->skb = skb;
+	status->rx_flags |= IEEE80211_RX_RA_MATCH;
+	prepares = prepare_for_handlers(rx, hdr);
+
+	if (!prepares)
+		return false;
+
+	if (status->flag & RX_FLAG_MMIC_ERROR) {
+		if (status->rx_flags & IEEE80211_RX_RA_MATCH)
+			ieee80211_rx_michael_mic_report(hdr, rx);
+		return false;
+	}
+
+	if (!consume) {
+		skb = skb_copy(skb, GFP_ATOMIC);
+		if (!skb) {
+			if (net_ratelimit())
+				wiphy_debug(local->hw.wiphy,
+					"failed to copy multicast frame for %s\n",
+					sdata->name);
+			return true;
+		}
+
+		rx->skb = skb;
+	}
+
+	ieee80211_invoke_rx_handlers(rx);
+	return true;
+}
+
+/*
  * This is the actual Rx frames handler. as it blongs to Rx path it must
  * be called with rcu_read_lock protection.
  */
 static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
-					 struct sk_buff *skb,
-					 struct ieee80211_rate *rate)
+					 struct sk_buff *skb)
 {
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct ieee80211_local *local = hw_to_local(hw);
@@ -2456,11 +2689,8 @@
 	struct ieee80211_hdr *hdr;
 	__le16 fc;
 	struct ieee80211_rx_data rx;
-	int prepares;
-	struct ieee80211_sub_if_data *prev = NULL;
-	struct sk_buff *skb_new;
-	struct sta_info *sta, *tmp;
-	bool found_sta = false;
+	struct ieee80211_sub_if_data *prev;
+	struct sta_info *sta, *tmp, *prev_sta;
 	int err = 0;
 
 	fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
@@ -2473,7 +2703,7 @@
 
 	if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
 		     test_bit(SCAN_OFF_CHANNEL, &local->scanning)))
-		rx.flags |= IEEE80211_RX_IN_SCAN;
+		status->rx_flags |= IEEE80211_RX_IN_SCAN;
 
 	if (ieee80211_is_mgmt(fc))
 		err = skb_linearize(skb);
@@ -2490,91 +2720,67 @@
 	ieee80211_verify_alignment(&rx);
 
 	if (ieee80211_is_data(fc)) {
+		prev_sta = NULL;
+
 		for_each_sta_info(local, hdr->addr2, sta, tmp) {
-			rx.sta = sta;
-			found_sta = true;
-			rx.sdata = sta->sdata;
-
-			rx.flags |= IEEE80211_RX_RA_MATCH;
-			prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
-			if (prepares) {
-				if (status->flag & RX_FLAG_MMIC_ERROR) {
-					if (rx.flags & IEEE80211_RX_RA_MATCH)
-						ieee80211_rx_michael_mic_report(hdr, &rx);
-				} else
-					prev = rx.sdata;
+			if (!prev_sta) {
+				prev_sta = sta;
+				continue;
 			}
+
+			rx.sta = prev_sta;
+			rx.sdata = prev_sta->sdata;
+			ieee80211_prepare_and_rx_handle(&rx, skb, false);
+
+			prev_sta = sta;
+		}
+
+		if (prev_sta) {
+			rx.sta = prev_sta;
+			rx.sdata = prev_sta->sdata;
+
+			if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
+				return;
 		}
 	}
-	if (!found_sta) {
-		list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-			if (!ieee80211_sdata_running(sdata))
-				continue;
 
-			if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
-			    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-				continue;
+	prev = NULL;
 
-			/*
-			 * frame is destined for this interface, but if it's
-			 * not also for the previous one we handle that after
-			 * the loop to avoid copying the SKB once too much
-			 */
+	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+		if (!ieee80211_sdata_running(sdata))
+			continue;
 
-			if (!prev) {
-				prev = sdata;
-				continue;
-			}
+		if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+		    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+			continue;
 
-			rx.sta = sta_info_get_bss(prev, hdr->addr2);
+		/*
+		 * frame is destined for this interface, but if it's
+		 * not also for the previous one we handle that after
+		 * the loop to avoid copying the SKB once too much
+		 */
 
-			rx.flags |= IEEE80211_RX_RA_MATCH;
-			prepares = prepare_for_handlers(prev, &rx, hdr);
-
-			if (!prepares)
-				goto next;
-
-			if (status->flag & RX_FLAG_MMIC_ERROR) {
-				rx.sdata = prev;
-				if (rx.flags & IEEE80211_RX_RA_MATCH)
-					ieee80211_rx_michael_mic_report(hdr,
-									&rx);
-				goto next;
-			}
-
-			/*
-			 * frame was destined for the previous interface
-			 * so invoke RX handlers for it
-			 */
-
-			skb_new = skb_copy(skb, GFP_ATOMIC);
-			if (!skb_new) {
-				if (net_ratelimit())
-					printk(KERN_DEBUG "%s: failed to copy "
-					       "multicast frame for %s\n",
-					       wiphy_name(local->hw.wiphy),
-					       prev->name);
-				goto next;
-			}
-			ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
-next:
+		if (!prev) {
 			prev = sdata;
+			continue;
 		}
 
-		if (prev) {
-			rx.sta = sta_info_get_bss(prev, hdr->addr2);
+		rx.sta = sta_info_get_bss(prev, hdr->addr2);
+		rx.sdata = prev;
+		ieee80211_prepare_and_rx_handle(&rx, skb, false);
 
-			rx.flags |= IEEE80211_RX_RA_MATCH;
-			prepares = prepare_for_handlers(prev, &rx, hdr);
-
-			if (!prepares)
-				prev = NULL;
-		}
+		prev = sdata;
 	}
-	if (prev)
-		ieee80211_invoke_rx_handlers(prev, &rx, skb, rate);
-	else
-		dev_kfree_skb(skb);
+
+	if (prev) {
+		rx.sta = sta_info_get_bss(prev, hdr->addr2);
+		rx.sdata = prev;
+
+		if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
+			return;
+	}
+
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -2615,30 +2821,41 @@
 	if (WARN_ON(!local->started))
 		goto drop;
 
-	if (status->flag & RX_FLAG_HT) {
+	if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) {
 		/*
-		 * rate_idx is MCS index, which can be [0-76] as documented on:
-		 *
-		 * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n
-		 *
-		 * Anything else would be some sort of driver or hardware error.
-		 * The driver should catch hardware errors.
+		 * Validate the rate, unless a PLCP error means that
+		 * we probably can't have a valid rate here anyway.
 		 */
-		if (WARN((status->rate_idx < 0 ||
-			 status->rate_idx > 76),
-			 "Rate marked as an HT rate but passed "
-			 "status->rate_idx is not "
-			 "an MCS index [0-76]: %d (0x%02x)\n",
-			 status->rate_idx,
-			 status->rate_idx))
-			goto drop;
-	} else {
-		if (WARN_ON(status->rate_idx < 0 ||
-			    status->rate_idx >= sband->n_bitrates))
-			goto drop;
-		rate = &sband->bitrates[status->rate_idx];
+
+		if (status->flag & RX_FLAG_HT) {
+			/*
+			 * rate_idx is MCS index, which can be [0-76]
+			 * as documented on:
+			 *
+			 * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n
+			 *
+			 * Anything else would be some sort of driver or
+			 * hardware error. The driver should catch hardware
+			 * errors.
+			 */
+			if (WARN((status->rate_idx < 0 ||
+				 status->rate_idx > 76),
+				 "Rate marked as an HT rate but passed "
+				 "status->rate_idx is not "
+				 "an MCS index [0-76]: %d (0x%02x)\n",
+				 status->rate_idx,
+				 status->rate_idx))
+				goto drop;
+		} else {
+			if (WARN_ON(status->rate_idx < 0 ||
+				    status->rate_idx >= sband->n_bitrates))
+				goto drop;
+			rate = &sband->bitrates[status->rate_idx];
+		}
 	}
 
+	status->rx_flags = 0;
+
 	/*
 	 * key references and virtual interfaces are protected using RCU
 	 * and this requires that we are in a read-side RCU section during
@@ -2658,7 +2875,7 @@
 		return;
 	}
 
-	__ieee80211_rx_handle_packet(hw, skb, rate);
+	__ieee80211_rx_handle_packet(hw, skb);
 
 	rcu_read_unlock();
 
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 872d7b6..fb274db 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -242,20 +242,19 @@
 	local->hw_scan_req->n_channels = n_chans;
 
 	ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
-					 req->ie, req->ie_len, band);
+					 req->ie, req->ie_len, band, (u32) -1,
+					 0);
 	local->hw_scan_req->ie_len = ielen;
 
 	return true;
 }
 
-void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
+static bool __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
+				       bool was_hw_scan)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
-	bool was_hw_scan;
 
-	trace_api_scan_completed(local, aborted);
-
-	mutex_lock(&local->scan_mtx);
+	lockdep_assert_held(&local->mtx);
 
 	/*
 	 * It's ok to abort a not-yet-running scan (that
@@ -266,17 +265,13 @@
 	if (WARN_ON(!local->scanning && !aborted))
 		aborted = true;
 
-	if (WARN_ON(!local->scan_req)) {
-		mutex_unlock(&local->scan_mtx);
-		return;
-	}
+	if (WARN_ON(!local->scan_req))
+		return false;
 
-	was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
 	if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
-		ieee80211_queue_delayed_work(&local->hw,
-					     &local->scan_work, 0);
-		mutex_unlock(&local->scan_mtx);
-		return;
+		int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req);
+		if (rc == 0)
+			return false;
 	}
 
 	kfree(local->hw_scan_req);
@@ -290,26 +285,42 @@
 	local->scanning = 0;
 	local->scan_channel = NULL;
 
-	/* we only have to protect scan_req and hw/sw scan */
-	mutex_unlock(&local->scan_mtx);
+	return true;
+}
+
+static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw,
+					      bool was_hw_scan)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
 
 	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
-	if (was_hw_scan)
-		goto done;
+	if (!was_hw_scan) {
+		ieee80211_configure_filter(local);
+		drv_sw_scan_complete(local);
+		ieee80211_offchannel_return(local, true);
+	}
 
-	ieee80211_configure_filter(local);
-
-	drv_sw_scan_complete(local);
-
-	ieee80211_offchannel_return(local, true);
-
- done:
+	mutex_lock(&local->mtx);
 	ieee80211_recalc_idle(local);
+	mutex_unlock(&local->mtx);
+
 	ieee80211_mlme_notify_scan_completed(local);
 	ieee80211_ibss_notify_scan_completed(local);
 	ieee80211_mesh_notify_scan_completed(local);
 	ieee80211_queue_work(&local->hw, &local->work_work);
 }
+
+void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	trace_api_scan_completed(local, aborted);
+
+	set_bit(SCAN_COMPLETED, &local->scanning);
+	if (aborted)
+		set_bit(SCAN_ABORTED, &local->scanning);
+	ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
+}
 EXPORT_SYMBOL(ieee80211_scan_completed);
 
 static int ieee80211_start_sw_scan(struct ieee80211_local *local)
@@ -353,6 +364,8 @@
 	struct ieee80211_local *local = sdata->local;
 	int rc;
 
+	lockdep_assert_held(&local->mtx);
+
 	if (local->scan_req)
 		return -EBUSY;
 
@@ -434,8 +447,8 @@
 	return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
 }
 
-static int ieee80211_scan_state_decision(struct ieee80211_local *local,
-					 unsigned long *next_delay)
+static void ieee80211_scan_state_decision(struct ieee80211_local *local,
+					  unsigned long *next_delay)
 {
 	bool associated = false;
 	bool tx_empty = true;
@@ -445,12 +458,6 @@
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_channel *next_chan;
 
-	/* if no more bands/channels left, complete scan and advance to the idle state */
-	if (local->scan_channel_idx >= local->scan_req->n_channels) {
-		ieee80211_scan_completed(&local->hw, false);
-		return 1;
-	}
-
 	/*
 	 * check if at least one STA interface is associated,
 	 * check if at least one STA interface has pending tx frames
@@ -522,7 +529,6 @@
 	}
 
 	*next_delay = 0;
-	return 0;
 }
 
 static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
@@ -638,20 +644,17 @@
 		container_of(work, struct ieee80211_local, scan_work.work);
 	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
 	unsigned long next_delay = 0;
+	bool aborted, hw_scan, finish;
 
-	mutex_lock(&local->scan_mtx);
-	if (!sdata || !local->scan_req) {
-		mutex_unlock(&local->scan_mtx);
-		return;
+	mutex_lock(&local->mtx);
+
+	if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) {
+		aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
+		goto out_complete;
 	}
 
-	if (local->hw_scan_req) {
-		int rc = drv_hw_scan(local, sdata, local->hw_scan_req);
-		mutex_unlock(&local->scan_mtx);
-		if (rc)
-			ieee80211_scan_completed(&local->hw, true);
-		return;
-	}
+	if (!sdata || !local->scan_req)
+		goto out;
 
 	if (local->scan_req && !local->scanning) {
 		struct cfg80211_scan_request *req = local->scan_req;
@@ -661,21 +664,21 @@
 		local->scan_sdata = NULL;
 
 		rc = __ieee80211_start_scan(sdata, req);
-		mutex_unlock(&local->scan_mtx);
-
-		if (rc)
-			ieee80211_scan_completed(&local->hw, true);
-		return;
+		if (rc) {
+			/* need to complete scan in cfg80211 */
+			local->scan_req = req;
+			aborted = true;
+			goto out_complete;
+		} else
+			goto out;
 	}
 
-	mutex_unlock(&local->scan_mtx);
-
 	/*
 	 * Avoid re-scheduling when the sdata is going away.
 	 */
 	if (!ieee80211_sdata_running(sdata)) {
-		ieee80211_scan_completed(&local->hw, true);
-		return;
+		aborted = true;
+		goto out_complete;
 	}
 
 	/*
@@ -685,8 +688,12 @@
 	do {
 		switch (local->next_scan_state) {
 		case SCAN_DECISION:
-			if (ieee80211_scan_state_decision(local, &next_delay))
-				return;
+			/* if no more bands/channels left, complete scan */
+			if (local->scan_channel_idx >= local->scan_req->n_channels) {
+				aborted = false;
+				goto out_complete;
+			}
+			ieee80211_scan_state_decision(local, &next_delay);
 			break;
 		case SCAN_SET_CHANNEL:
 			ieee80211_scan_state_set_channel(local, &next_delay);
@@ -704,6 +711,19 @@
 	} while (next_delay == 0);
 
 	ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
+	mutex_unlock(&local->mtx);
+	return;
+
+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;
+
+out:
+	mutex_unlock(&local->mtx);
 }
 
 int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
@@ -711,9 +731,9 @@
 {
 	int res;
 
-	mutex_lock(&sdata->local->scan_mtx);
+	mutex_lock(&sdata->local->mtx);
 	res = __ieee80211_start_scan(sdata, req);
-	mutex_unlock(&sdata->local->scan_mtx);
+	mutex_unlock(&sdata->local->mtx);
 
 	return res;
 }
@@ -726,7 +746,7 @@
 	int ret = -EBUSY;
 	enum ieee80211_band band;
 
-	mutex_lock(&local->scan_mtx);
+	mutex_lock(&local->mtx);
 
 	/* busy scanning */
 	if (local->scan_req)
@@ -761,25 +781,44 @@
 
 	ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
  unlock:
-	mutex_unlock(&local->scan_mtx);
+	mutex_unlock(&local->mtx);
 	return ret;
 }
 
+/*
+ * Only call this function when a scan can't be queued -- under RTNL.
+ */
 void ieee80211_scan_cancel(struct ieee80211_local *local)
 {
 	bool abortscan;
-
-	cancel_delayed_work_sync(&local->scan_work);
+	bool finish = false;
 
 	/*
-	 * Only call this function when a scan can't be
-	 * queued -- mostly at suspend under RTNL.
+	 * We are only canceling software scan, or deferred scan that was not
+	 * yet really started (see __ieee80211_start_scan ).
+	 *
+	 * Regarding hardware scan:
+	 * - we can not call  __ieee80211_scan_completed() as when
+	 *   SCAN_HW_SCANNING bit is set this function change
+	 *   local->hw_scan_req to operate on 5G band, what race with
+	 *   driver which can use local->hw_scan_req
+	 *
+	 * - we can not cancel scan_work since driver can schedule it
+	 *   by ieee80211_scan_completed(..., true) to finish scan
+	 *
+	 * Hence low lever driver is responsible for canceling HW scan.
 	 */
-	mutex_lock(&local->scan_mtx);
-	abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
-		    (!local->scanning && local->scan_req);
-	mutex_unlock(&local->scan_mtx);
 
+	mutex_lock(&local->mtx);
+	abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning);
 	if (abortscan)
-		ieee80211_scan_completed(&local->hw, true);
+		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);
+	}
+	if (finish)
+		__ieee80211_scan_completed_finish(&local->hw, false);
 }
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 6d86f0c..6d8f897 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -125,7 +125,7 @@
 				    lockdep_is_held(&local->sta_mtx));
 	while (sta) {
 		if ((sta->sdata == sdata ||
-		     sta->sdata->bss == sdata->bss) &&
+		     (sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&
 		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
 			break;
 		sta = rcu_dereference_check(sta->hnext,
@@ -174,8 +174,7 @@
 	}
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: Destroyed STA %pM\n",
-	       wiphy_name(local->hw.wiphy), sta->sta.addr);
+	wiphy_debug(local->hw.wiphy, "Destroyed STA %pM\n", sta->sta.addr);
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 
 	kfree(sta);
@@ -262,8 +261,7 @@
 		sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX);
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: Allocated STA %pM\n",
-	       wiphy_name(local->hw.wiphy), sta->sta.addr);
+	wiphy_debug(local->hw.wiphy, "Allocated STA %pM\n", sta->sta.addr);
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 
 #ifdef CONFIG_MAC80211_MESH
@@ -282,7 +280,7 @@
 	unsigned long flags;
 	int err = 0;
 
-	WARN_ON(!mutex_is_locked(&local->sta_mtx));
+	lockdep_assert_held(&local->sta_mtx);
 
 	/* notify driver */
 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
@@ -300,8 +298,9 @@
 		sta->uploaded = true;
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 		if (async)
-			printk(KERN_DEBUG "%s: Finished adding IBSS STA %pM\n",
-			       wiphy_name(local->hw.wiphy), sta->sta.addr);
+			wiphy_debug(local->hw.wiphy,
+				    "Finished adding IBSS STA %pM\n",
+				    sta->sta.addr);
 #endif
 	}
 
@@ -411,8 +410,8 @@
 		spin_unlock_irqrestore(&local->sta_lock, flags);
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-		printk(KERN_DEBUG "%s: Added IBSS STA %pM\n",
-		       wiphy_name(local->hw.wiphy), sta->sta.addr);
+		wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n",
+			    sta->sta.addr);
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 
 		ieee80211_queue_work(&local->hw, &local->sta_finish_work);
@@ -459,8 +458,7 @@
 	}
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: Inserted STA %pM\n",
-	       wiphy_name(local->hw.wiphy), sta->sta.addr);
+	wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr);
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 
 	/* move reference to rcu-protected */
@@ -618,7 +616,7 @@
 	struct ieee80211_sub_if_data *sdata;
 	struct sk_buff *skb;
 	unsigned long flags;
-	int ret;
+	int ret, i;
 
 	might_sleep();
 
@@ -635,7 +633,7 @@
 	 * will be sufficient.
 	 */
 	set_sta_flags(sta, WLAN_STA_BLOCK_BA);
-	ieee80211_sta_tear_down_BA_sessions(sta);
+	ieee80211_sta_tear_down_BA_sessions(sta, true);
 
 	spin_lock_irqsave(&local->sta_lock, flags);
 	ret = sta_info_hash_del(local, sta);
@@ -646,10 +644,10 @@
 	if (ret)
 		return ret;
 
-	if (sta->key) {
-		ieee80211_key_free(local, sta->key);
-		WARN_ON(sta->key);
-	}
+	for (i = 0; i < NUM_DEFAULT_KEYS; i++)
+		ieee80211_key_free(local, sta->gtk[i]);
+	if (sta->ptk)
+		ieee80211_key_free(local, sta->ptk);
 
 	sta->dead = true;
 
@@ -690,8 +688,7 @@
 #endif
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-	printk(KERN_DEBUG "%s: Removed STA %pM\n",
-	       wiphy_name(local->hw.wiphy), sta->sta.addr);
+	wiphy_debug(local->hw.wiphy, "Removed STA %pM\n", sta->sta.addr);
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 	cancel_work_sync(&sta->drv_unblock_wk);
 
@@ -841,13 +838,20 @@
 	mutex_unlock(&local->sta_mtx);
 }
 
-struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
-					       const u8 *addr)
+struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
+					       const u8 *addr,
+					       const u8 *localaddr)
 {
 	struct sta_info *sta, *nxt;
 
-	/* Just return a random station ... first in list ... */
+	/*
+	 * Just return a random station if localaddr is NULL
+	 * ... first in list.
+	 */
 	for_each_sta_info(hw_to_local(hw), addr, sta, nxt) {
+		if (localaddr &&
+		    compare_ether_addr(sta->sdata->vif.addr, localaddr) != 0)
+			continue;
 		if (!sta->uploaded)
 			return NULL;
 		return &sta->sta;
@@ -855,7 +859,7 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
+EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_ifaddr);
 
 struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
 					 const u8 *addr)
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 54262e7..9265aca 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -79,6 +79,7 @@
  * @dialog_token: dialog token for aggregation session
  * @state: session state (see above)
  * @stop_initiator: initiator of a session stop
+ * @tx_stop: TX DelBA frame when stopping
  *
  * This structure is protected by RCU and the per-station
  * spinlock. Assignments to the array holding it must hold
@@ -95,6 +96,7 @@
 	unsigned long state;
 	u8 dialog_token;
 	u8 stop_initiator;
+	bool tx_stop;
 };
 
 /**
@@ -103,6 +105,7 @@
  * @reorder_buf: buffer to reorder incoming aggregated MPDUs
  * @reorder_time: jiffies when skb was added
  * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
+ * @reorder_timer: releases expired frames from the reorder buffer.
  * @head_seq_num: head sequence number in reordering buffer.
  * @stored_mpdu_num: number of MPDUs in reordering buffer
  * @ssn: Starting Sequence Number expected to be aggregated.
@@ -110,20 +113,25 @@
  * @timeout: reset timer value (in TUs).
  * @dialog_token: dialog token for aggregation session
  * @rcu_head: RCU head used for freeing this struct
+ * @reorder_lock: serializes access to reorder buffer, see below.
  *
  * This structure is protected by RCU and the per-station
  * spinlock. Assignments to the array holding it must hold
- * the spinlock, only the RX path can access it under RCU
- * lock-free. The RX path, since it is single-threaded,
- * can even modify the structure without locking since the
- * only other modifications to it are done when the struct
- * can not yet or no longer be found by the RX path.
+ * the spinlock.
+ *
+ * The @reorder_lock is used to protect the variables and
+ * arrays such as @reorder_buf, @reorder_time, @head_seq_num,
+ * @stored_mpdu_num and @reorder_time from being corrupted by
+ * concurrent access of the RX path and the expired frame
+ * release timer.
  */
 struct tid_ampdu_rx {
 	struct rcu_head rcu_head;
+	spinlock_t reorder_lock;
 	struct sk_buff **reorder_buf;
 	unsigned long *reorder_time;
 	struct timer_list session_timer;
+	struct timer_list reorder_timer;
 	u16 head_seq_num;
 	u16 stored_mpdu_num;
 	u16 ssn;
@@ -191,7 +199,8 @@
  * @hnext: hash table linked list pointer
  * @local: pointer to the global information
  * @sdata: virtual interface this station belongs to
- * @key: peer key negotiated with this station, if any
+ * @ptk: peer key negotiated with this station, if any
+ * @gtk: group keys negotiated with this station, if any
  * @rate_ctrl: rate control algorithm reference
  * @rate_ctrl_priv: rate control private per-STA pointer
  * @last_tx_rate: rate used for last transmit, to report to userspace as
@@ -246,7 +255,8 @@
 	struct sta_info *hnext;
 	struct ieee80211_local *local;
 	struct ieee80211_sub_if_data *sdata;
-	struct ieee80211_key *key;
+	struct ieee80211_key *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
+	struct ieee80211_key *ptk;
 	struct rate_control_ref *rate_ctrl;
 	void *rate_ctrl_priv;
 	spinlock_t lock;
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 10caec5..3153c19 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -58,6 +58,7 @@
 	info->control.vif = &sta->sdata->vif;
 	info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
 		       IEEE80211_TX_INTFL_RETRANSMISSION;
+	info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
 
 	sta->tx_filtered_count++;
 
@@ -114,11 +115,10 @@
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 	if (net_ratelimit())
-		printk(KERN_DEBUG "%s: dropped TX filtered frame, "
-		       "queue_len=%d PS=%d @%lu\n",
-		       wiphy_name(local->hw.wiphy),
-		       skb_queue_len(&sta->tx_filtered),
-		       !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies);
+		wiphy_debug(local->hw.wiphy,
+			    "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n",
+			    skb_queue_len(&sta->tx_filtered),
+			    !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies);
 #endif
 	dev_kfree_skb(skb);
 }
@@ -176,7 +176,7 @@
 
 	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
 		/* the HW cannot have attempted that rate */
-		if (i >= hw->max_rates) {
+		if (i >= hw->max_report_rates) {
 			info->status.rates[i].idx = -1;
 			info->status.rates[i].count = 0;
 		} else if (info->status.rates[i].idx >= 0) {
@@ -296,7 +296,7 @@
 	}
 
 	if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX)
-		cfg80211_action_tx_status(
+		cfg80211_mgmt_tx_status(
 			skb->dev, (unsigned long) skb, skb->data, skb->len,
 			!!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
 
@@ -377,7 +377,7 @@
 				skb2 = skb_clone(skb, GFP_ATOMIC);
 				if (skb2) {
 					skb2->dev = prev_dev;
-					netif_receive_skb(skb2);
+					netif_rx(skb2);
 				}
 			}
 
@@ -386,7 +386,7 @@
 	}
 	if (prev_dev) {
 		skb->dev = prev_dev;
-		netif_receive_skb(skb);
+		netif_rx(skb);
 		skb = NULL;
 	}
 	rcu_read_unlock();
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c54db96..96c5943 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -273,6 +273,9 @@
 		 */
 		return TX_DROP;
 
+	if (tx->sdata->vif.type == NL80211_IFTYPE_WDS)
+		return TX_CONTINUE;
+
 	if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
 		return TX_CONTINUE;
 
@@ -351,8 +354,8 @@
 
 	local->total_ps_buffered = total;
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-	printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n",
-	       wiphy_name(local->hw.wiphy), purged);
+	wiphy_debug(local->hw.wiphy, "PS buffers full - purged %d frames\n",
+		    purged);
 #endif
 }
 
@@ -509,6 +512,18 @@
 }
 
 static ieee80211_tx_result debug_noinline
+ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
+{
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+
+	if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol &&
+		     tx->sdata->control_port_no_encrypt))
+		info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+
+	return TX_CONTINUE;
+}
+
+static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
 {
 	struct ieee80211_key *key = NULL;
@@ -517,7 +532,7 @@
 
 	if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
 		tx->key = NULL;
-	else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
+	else if (tx->sta && (key = rcu_dereference(tx->sta->ptk)))
 		tx->key = key;
 	else if (ieee80211_is_mgmt(hdr->frame_control) &&
 		 is_multicast_ether_addr(hdr->addr1) &&
@@ -527,7 +542,7 @@
 	else if ((key = rcu_dereference(tx->sdata->default_key)))
 		tx->key = key;
 	else if (tx->sdata->drop_unencrypted &&
-		 (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) &&
+		 (tx->skb->protocol != tx->sdata->control_port_protocol) &&
 		 !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
 		 (!ieee80211_is_robust_mgmt_frame(hdr) ||
 		  (ieee80211_is_action(hdr->frame_control) &&
@@ -543,15 +558,16 @@
 		tx->key->tx_rx_count++;
 		/* TODO: add threshold stuff again */
 
-		switch (tx->key->conf.alg) {
-		case ALG_WEP:
+		switch (tx->key->conf.cipher) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
 			if (ieee80211_is_auth(hdr->frame_control))
 				break;
-		case ALG_TKIP:
+		case WLAN_CIPHER_SUITE_TKIP:
 			if (!ieee80211_is_data_present(hdr->frame_control))
 				tx->key = NULL;
 			break;
-		case ALG_CCMP:
+		case WLAN_CIPHER_SUITE_CCMP:
 			if (!ieee80211_is_data_present(hdr->frame_control) &&
 			    !ieee80211_use_mfp(hdr->frame_control, tx->sta,
 					       tx->skb))
@@ -561,7 +577,7 @@
 					   IEEE80211_KEY_FLAG_SW_MGMT) &&
 					ieee80211_is_mgmt(hdr->frame_control);
 			break;
-		case ALG_AES_CMAC:
+		case WLAN_CIPHER_SUITE_AES_CMAC:
 			if (!ieee80211_is_mgmt(hdr->frame_control))
 				tx->key = NULL;
 			break;
@@ -946,22 +962,31 @@
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
 {
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+
 	if (!tx->key)
 		return TX_CONTINUE;
 
-	switch (tx->key->conf.alg) {
-	case ALG_WEP:
+	switch (tx->key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
 		return ieee80211_crypto_wep_encrypt(tx);
-	case ALG_TKIP:
+	case WLAN_CIPHER_SUITE_TKIP:
 		return ieee80211_crypto_tkip_encrypt(tx);
-	case ALG_CCMP:
+	case WLAN_CIPHER_SUITE_CCMP:
 		return ieee80211_crypto_ccmp_encrypt(tx);
-	case ALG_AES_CMAC:
+	case WLAN_CIPHER_SUITE_AES_CMAC:
 		return ieee80211_crypto_aes_cmac_encrypt(tx);
+	default:
+		/* handle hw-only algorithm */
+		if (info->control.hw_key) {
+			ieee80211_tx_set_protected(tx);
+			return TX_CONTINUE;
+		}
+		break;
+
 	}
 
-	/* not reached */
-	WARN_ON(1);
 	return TX_DROP;
 }
 
@@ -1339,6 +1364,7 @@
 	CALL_TXH(ieee80211_tx_h_dynamic_ps);
 	CALL_TXH(ieee80211_tx_h_check_assoc);
 	CALL_TXH(ieee80211_tx_h_ps_buf);
+	CALL_TXH(ieee80211_tx_h_check_control_port_protocol);
 	CALL_TXH(ieee80211_tx_h_select_key);
 	if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
 		CALL_TXH(ieee80211_tx_h_rate_ctrl);
@@ -1511,8 +1537,8 @@
 		I802_DEBUG_INC(local->tx_expand_skb_head);
 
 	if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) {
-		printk(KERN_DEBUG "%s: failed to reallocate TX buffer\n",
-		       wiphy_name(local->hw.wiphy));
+		wiphy_debug(local->hw.wiphy,
+			    "failed to reallocate TX buffer\n");
 		return -ENOMEM;
 	}
 
@@ -1586,6 +1612,7 @@
 		return;
 	}
 
+	hdr = (struct ieee80211_hdr *) skb->data;
 	info->control.vif = &sdata->vif;
 
 	if (ieee80211_vif_is_mesh(&sdata->vif) &&
@@ -1699,7 +1726,7 @@
 	u16 ethertype, hdrlen,  meshhdrlen = 0;
 	__le16 fc;
 	struct ieee80211_hdr hdr;
-	struct ieee80211s_hdr mesh_hdr;
+	struct ieee80211s_hdr mesh_hdr __maybe_unused;
 	const u8 *encaps_data;
 	int encaps_len, skip_header_bytes;
 	int nh_pos, h_pos;
@@ -1816,7 +1843,8 @@
 #endif
 	case NL80211_IFTYPE_STATION:
 		memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
-		if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) {
+		if (sdata->u.mgd.use_4addr &&
+		    cpu_to_be16(ethertype) != sdata->control_port_protocol) {
 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
 			/* RA TA DA SA */
 			memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
@@ -1869,7 +1897,7 @@
 	if (!ieee80211_vif_is_mesh(&sdata->vif) &&
 		unlikely(!is_multicast_ether_addr(hdr.addr1) &&
 		      !(sta_flags & WLAN_STA_AUTHORIZED) &&
-		      !(ethertype == ETH_P_PAE &&
+		      !(cpu_to_be16(ethertype) == sdata->control_port_protocol &&
 		       compare_ether_addr(sdata->vif.addr,
 					  skb->data + ETH_ALEN) == 0))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -2068,8 +2096,7 @@
 
 		if (skb_queue_empty(&local->pending[i]))
 			list_for_each_entry_rcu(sdata, &local->interfaces, list)
-				netif_tx_wake_queue(
-					netdev_get_tx_queue(sdata->dev, i));
+				netif_wake_subqueue(sdata->dev, i);
 	}
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 748387d..0b6fc92 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -283,8 +283,11 @@
 
 	if (skb_queue_empty(&local->pending[queue])) {
 		rcu_read_lock();
-		list_for_each_entry_rcu(sdata, &local->interfaces, list)
-			netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue));
+		list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+			if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
+				continue;
+			netif_wake_subqueue(sdata->dev, queue);
+		}
 		rcu_read_unlock();
 	} else
 		tasklet_schedule(&local->tx_pending_tasklet);
@@ -323,7 +326,7 @@
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(sdata, &local->interfaces, list)
-		netif_tx_stop_queue(netdev_get_tx_queue(sdata->dev, queue));
+		netif_stop_subqueue(sdata->dev, queue);
 	rcu_read_unlock();
 }
 
@@ -471,16 +474,10 @@
 
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		switch (sdata->vif.type) {
-		case __NL80211_IFTYPE_AFTER_LAST:
-		case NL80211_IFTYPE_UNSPECIFIED:
 		case NL80211_IFTYPE_MONITOR:
 		case NL80211_IFTYPE_AP_VLAN:
 			continue;
-		case NL80211_IFTYPE_AP:
-		case NL80211_IFTYPE_STATION:
-		case NL80211_IFTYPE_ADHOC:
-		case NL80211_IFTYPE_WDS:
-		case NL80211_IFTYPE_MESH_POINT:
+		default:
 			break;
 		}
 		if (ieee80211_sdata_running(sdata))
@@ -505,16 +502,10 @@
 
 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 		switch (sdata->vif.type) {
-		case __NL80211_IFTYPE_AFTER_LAST:
-		case NL80211_IFTYPE_UNSPECIFIED:
 		case NL80211_IFTYPE_MONITOR:
 		case NL80211_IFTYPE_AP_VLAN:
 			continue;
-		case NL80211_IFTYPE_AP:
-		case NL80211_IFTYPE_STATION:
-		case NL80211_IFTYPE_ADHOC:
-		case NL80211_IFTYPE_WDS:
-		case NL80211_IFTYPE_MESH_POINT:
+		default:
 			break;
 		}
 		if (ieee80211_sdata_running(sdata))
@@ -904,26 +895,34 @@
 
 int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 			     const u8 *ie, size_t ie_len,
-			     enum ieee80211_band band)
+			     enum ieee80211_band band, u32 rate_mask,
+			     u8 channel)
 {
 	struct ieee80211_supported_band *sband;
 	u8 *pos;
 	size_t offset = 0, noffset;
 	int supp_rates_len, i;
+	u8 rates[32];
+	int num_rates;
+	int ext_rates_len;
 
 	sband = local->hw.wiphy->bands[band];
 
 	pos = buffer;
 
-	supp_rates_len = min_t(int, sband->n_bitrates, 8);
+	num_rates = 0;
+	for (i = 0; i < sband->n_bitrates; i++) {
+		if ((BIT(i) & rate_mask) == 0)
+			continue; /* skip rate */
+		rates[num_rates++] = (u8) (sband->bitrates[i].bitrate / 5);
+	}
+
+	supp_rates_len = min_t(int, num_rates, 8);
 
 	*pos++ = WLAN_EID_SUPP_RATES;
 	*pos++ = supp_rates_len;
-
-	for (i = 0; i < supp_rates_len; i++) {
-		int rate = sband->bitrates[i].bitrate;
-		*pos++ = (u8) (rate / 5);
-	}
+	memcpy(pos, rates, supp_rates_len);
+	pos += supp_rates_len;
 
 	/* insert "request information" if in custom IEs */
 	if (ie && ie_len) {
@@ -941,14 +940,18 @@
 		offset = noffset;
 	}
 
-	if (sband->n_bitrates > i) {
+	ext_rates_len = num_rates - supp_rates_len;
+	if (ext_rates_len > 0) {
 		*pos++ = WLAN_EID_EXT_SUPP_RATES;
-		*pos++ = sband->n_bitrates - i;
+		*pos++ = ext_rates_len;
+		memcpy(pos, rates + supp_rates_len, ext_rates_len);
+		pos += ext_rates_len;
+	}
 
-		for (; i < sband->n_bitrates; i++) {
-			int rate = sband->bitrates[i].bitrate;
-			*pos++ = (u8) (rate / 5);
-		}
+	if (channel && sband->band == IEEE80211_BAND_2GHZ) {
+		*pos++ = WLAN_EID_DS_PARAMS;
+		*pos++ = 1;
+		*pos++ = channel;
 	}
 
 	/* insert custom IEs that go before HT */
@@ -1017,6 +1020,7 @@
 	struct ieee80211_mgmt *mgmt;
 	size_t buf_len;
 	u8 *buf;
+	u8 chan;
 
 	/* FIXME: come up with a proper value */
 	buf = kmalloc(200 + ie_len, GFP_KERNEL);
@@ -1026,8 +1030,14 @@
 		return;
 	}
 
+	chan = ieee80211_frequency_to_channel(
+		local->hw.conf.channel->center_freq);
+
 	buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
-					   local->hw.conf.channel->band);
+					   local->hw.conf.channel->band,
+					   sdata->rc_rateidx_mask
+					   [local->hw.conf.channel->band],
+					   chan);
 
 	skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
 				     ssid, ssid_len,
@@ -1189,7 +1199,9 @@
 			/* ignore virtual */
 			break;
 		case NL80211_IFTYPE_UNSPECIFIED:
-		case __NL80211_IFTYPE_AFTER_LAST:
+		case NUM_NL80211_IFTYPES:
+		case NL80211_IFTYPE_P2P_CLIENT:
+		case NL80211_IFTYPE_P2P_GO:
 			WARN_ON(1);
 			break;
 		}
@@ -1209,7 +1221,7 @@
 		mutex_lock(&local->sta_mtx);
 
 		list_for_each_entry(sta, &local->sta_list, list) {
-			ieee80211_sta_tear_down_BA_sessions(sta);
+			ieee80211_sta_tear_down_BA_sessions(sta, true);
 			clear_sta_flags(sta, WLAN_STA_BLOCK_BA);
 		}
 
@@ -1285,17 +1297,13 @@
 }
 
 /* must hold iflist_mtx */
-void ieee80211_recalc_smps(struct ieee80211_local *local,
-			   struct ieee80211_sub_if_data *forsdata)
+void ieee80211_recalc_smps(struct ieee80211_local *local)
 {
 	struct ieee80211_sub_if_data *sdata;
 	enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF;
 	int count = 0;
 
-	if (forsdata)
-		WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx));
-
-	WARN_ON(!mutex_is_locked(&local->iflist_mtx));
+	lockdep_assert_held(&local->iflist_mtx);
 
 	/*
 	 * This function could be improved to handle multiple
@@ -1308,22 +1316,12 @@
 	 */
 
 	list_for_each_entry(sdata, &local->interfaces, list) {
-		if (!netif_running(sdata->dev))
+		if (!ieee80211_sdata_running(sdata))
 			continue;
 		if (sdata->vif.type != NL80211_IFTYPE_STATION)
 			goto set;
-		if (sdata != forsdata) {
-			/*
-			 * This nested is ok -- we are holding the iflist_mtx
-			 * so can't get here twice or so. But it's required
-			 * since normally we acquire it first and then the
-			 * iflist_mtx.
-			 */
-			mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING);
-			count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
-			mutex_unlock(&sdata->u.mgd.mtx);
-		} else
-			count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
+
+		count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
 
 		if (count > 1) {
 			smps_mode = IEEE80211_SMPS_OFF;
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index 9ebc8d8..2ff6d1e 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -222,7 +222,7 @@
 				 struct ieee80211_key *key)
 {
 	u32 klen;
-	u8 *rc4key;
+	u8 rc4key[3 + WLAN_KEY_LEN_WEP104];
 	u8 keyidx;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	unsigned int hdrlen;
@@ -240,15 +240,11 @@
 
 	keyidx = skb->data[hdrlen + 3] >> 6;
 
-	if (!key || keyidx != key->conf.keyidx || key->conf.alg != ALG_WEP)
+	if (!key || keyidx != key->conf.keyidx)
 		return -1;
 
 	klen = 3 + key->conf.keylen;
 
-	rc4key = kmalloc(klen, GFP_ATOMIC);
-	if (!rc4key)
-		return -1;
-
 	/* Prepend 24-bit IV to RC4 key */
 	memcpy(rc4key, skb->data + hdrlen, 3);
 
@@ -260,8 +256,6 @@
 				       len))
 		ret = -1;
 
-	kfree(rc4key);
-
 	/* Trim ICV */
 	skb_trim(skb, skb->len - WEP_ICV_LEN);
 
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 81d4ad6..ae344d1 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -43,7 +43,7 @@
 /* utils */
 static inline void ASSERT_WORK_MTX(struct ieee80211_local *local)
 {
-	WARN_ON(!mutex_is_locked(&local->work_mtx));
+	lockdep_assert_held(&local->mtx);
 }
 
 /*
@@ -757,7 +757,7 @@
 	mgmt = (struct ieee80211_mgmt *) skb->data;
 	fc = le16_to_cpu(mgmt->frame_control);
 
-	mutex_lock(&local->work_mtx);
+	mutex_lock(&local->mtx);
 
 	list_for_each_entry(wk, &local->work_list, list) {
 		const u8 *bssid = NULL;
@@ -833,7 +833,7 @@
 		WARN(1, "unexpected: %d", rma);
 	}
 
-	mutex_unlock(&local->work_mtx);
+	mutex_unlock(&local->mtx);
 
 	if (rma != WORK_ACT_DONE)
 		goto out;
@@ -845,9 +845,9 @@
 	case WORK_DONE_REQUEUE:
 		synchronize_rcu();
 		wk->started = false; /* restart */
-		mutex_lock(&local->work_mtx);
+		mutex_lock(&local->mtx);
 		list_add_tail(&wk->list, &local->work_list);
-		mutex_unlock(&local->work_mtx);
+		mutex_unlock(&local->mtx);
 	}
 
  out:
@@ -888,9 +888,9 @@
 	while ((skb = skb_dequeue(&local->work_skb_queue)))
 		ieee80211_work_rx_queued_mgmt(local, skb);
 
-	ieee80211_recalc_idle(local);
+	mutex_lock(&local->mtx);
 
-	mutex_lock(&local->work_mtx);
+	ieee80211_recalc_idle(local);
 
 	list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
 		bool started = wk->started;
@@ -995,20 +995,16 @@
 		run_again(local, jiffies + HZ/2);
 	}
 
-	mutex_lock(&local->scan_mtx);
-
 	if (list_empty(&local->work_list) && local->scan_req &&
 	    !local->scanning)
 		ieee80211_queue_delayed_work(&local->hw,
 					     &local->scan_work,
 					     round_jiffies_relative(0));
 
-	mutex_unlock(&local->scan_mtx);
-
-	mutex_unlock(&local->work_mtx);
-
 	ieee80211_recalc_idle(local);
 
+	mutex_unlock(&local->mtx);
+
 	list_for_each_entry_safe(wk, tmp, &free_work, list) {
 		wk->done(wk, NULL);
 		list_del(&wk->list);
@@ -1035,16 +1031,15 @@
 	wk->started = false;
 
 	local = wk->sdata->local;
-	mutex_lock(&local->work_mtx);
+	mutex_lock(&local->mtx);
 	list_add_tail(&wk->list, &local->work_list);
-	mutex_unlock(&local->work_mtx);
+	mutex_unlock(&local->mtx);
 
 	ieee80211_queue_work(&local->hw, &local->work_work);
 }
 
 void ieee80211_work_init(struct ieee80211_local *local)
 {
-	mutex_init(&local->work_mtx);
 	INIT_LIST_HEAD(&local->work_list);
 	setup_timer(&local->work_timer, ieee80211_work_timer,
 		    (unsigned long)local);
@@ -1057,7 +1052,7 @@
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_work *wk;
 
-	mutex_lock(&local->work_mtx);
+	mutex_lock(&local->mtx);
 	list_for_each_entry(wk, &local->work_list, list) {
 		if (wk->sdata != sdata)
 			continue;
@@ -1065,19 +1060,19 @@
 		wk->started = true;
 		wk->timeout = jiffies;
 	}
-	mutex_unlock(&local->work_mtx);
+	mutex_unlock(&local->mtx);
 
 	/* run cleanups etc. */
 	ieee80211_work_work(&local->work_work);
 
-	mutex_lock(&local->work_mtx);
+	mutex_lock(&local->mtx);
 	list_for_each_entry(wk, &local->work_list, list) {
 		if (wk->sdata != sdata)
 			continue;
 		WARN_ON(1);
 		break;
 	}
-	mutex_unlock(&local->work_mtx);
+	mutex_unlock(&local->mtx);
 }
 
 ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
@@ -1163,7 +1158,7 @@
 	struct ieee80211_work *wk, *tmp;
 	bool found = false;
 
-	mutex_lock(&local->work_mtx);
+	mutex_lock(&local->mtx);
 	list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
 		if ((unsigned long) wk == cookie) {
 			wk->timeout = jiffies;
@@ -1171,7 +1166,7 @@
 			break;
 		}
 	}
-	mutex_unlock(&local->work_mtx);
+	mutex_unlock(&local->mtx);
 
 	if (!found)
 		return -ENOENT;
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 8d59d27..bee230d 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -36,8 +36,8 @@
 	int tail;
 
 	hdr = (struct ieee80211_hdr *)skb->data;
-	if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 ||
-	    !ieee80211_is_data_present(hdr->frame_control))
+	if (!tx->key || tx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
+	    skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control))
 		return TX_CONTINUE;
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
@@ -94,7 +94,7 @@
 	if (status->flag & RX_FLAG_MMIC_STRIPPED)
 		return RX_CONTINUE;
 
-	if (!rx->key || rx->key->conf.alg != ALG_TKIP ||
+	if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
 	    !ieee80211_has_protected(hdr->frame_control) ||
 	    !ieee80211_is_data_present(hdr->frame_control))
 		return RX_CONTINUE;
@@ -117,7 +117,7 @@
 	key = &rx->key->conf.key[key_offset];
 	michael_mic(key, hdr, data, data_len, mic);
 	if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
-		if (!(rx->flags & IEEE80211_RX_RA_MATCH))
+		if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
 			return RX_DROP_UNUSABLE;
 
 		mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx,
@@ -221,19 +221,13 @@
 	if (!rx->sta || skb->len - hdrlen < 12)
 		return RX_DROP_UNUSABLE;
 
-	if (status->flag & RX_FLAG_DECRYPTED) {
-		if (status->flag & RX_FLAG_IV_STRIPPED) {
-			/*
-			 * Hardware took care of all processing, including
-			 * replay protection, and stripped the ICV/IV so
-			 * we cannot do any checks here.
-			 */
-			return RX_CONTINUE;
-		}
-
-		/* let TKIP code verify IV, but skip decryption */
+	/*
+	 * Let TKIP code verify IV, but skip decryption.
+	 * In the case where hardware checks the IV as well,
+	 * we don't even get here, see ieee80211_rx_h_decrypt()
+	 */
+	if (status->flag & RX_FLAG_DECRYPTED)
 		hwaccel = 1;
-	}
 
 	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
 					  key, skb->data + hdrlen,
@@ -447,10 +441,6 @@
 	if (!rx->sta || data_len < 0)
 		return RX_DROP_UNUSABLE;
 
-	if ((status->flag & RX_FLAG_DECRYPTED) &&
-	    (status->flag & RX_FLAG_IV_STRIPPED))
-		return RX_CONTINUE;
-
 	ccmp_hdr2pn(pn, skb->data + hdrlen);
 
 	queue = ieee80211_is_mgmt(hdr->frame_control) ?
@@ -564,10 +554,6 @@
 	if (!ieee80211_is_mgmt(hdr->frame_control))
 		return RX_CONTINUE;
 
-	if ((status->flag & RX_FLAG_DECRYPTED) &&
-	    (status->flag & RX_FLAG_IV_STRIPPED))
-		return RX_CONTINUE;
-
 	if (skb->len < 24 + sizeof(*mmie))
 		return RX_DROP_UNUSABLE;
 
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 78b505d..85dabb8 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -27,7 +27,7 @@
 
 static DEFINE_MUTEX(afinfo_mutex);
 
-const struct nf_afinfo *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
+const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
 EXPORT_SYMBOL(nf_afinfo);
 
 int nf_register_afinfo(const struct nf_afinfo *afinfo)
@@ -105,10 +105,8 @@
 
 void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
 {
-	unsigned int i;
-
-	for (i = 0; i < n; i++)
-		nf_unregister_hook(&reg[i]);
+	while (n-- > 0)
+		nf_unregister_hook(&reg[n]);
 }
 EXPORT_SYMBOL(nf_unregister_hooks);
 
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig
index 46a77d5..a22dac2 100644
--- a/net/netfilter/ipvs/Kconfig
+++ b/net/netfilter/ipvs/Kconfig
@@ -3,7 +3,7 @@
 #
 menuconfig IP_VS
 	tristate "IP virtual server support"
-	depends on NET && INET && NETFILTER && NF_CONNTRACK
+	depends on NET && INET && NETFILTER
 	---help---
 	  IP Virtual Server support will let you build a high-performance
 	  virtual server based on cluster of two or more real servers. This
@@ -235,7 +235,8 @@
 
 config	IP_VS_FTP
   	tristate "FTP protocol helper"
-        depends on IP_VS_PROTO_TCP && NF_NAT
+        depends on IP_VS_PROTO_TCP && NF_CONNTRACK && NF_NAT
+	select IP_VS_NFCT
 	---help---
 	  FTP is a protocol that transfers IP address and/or port number in
 	  the payload. In the virtual server via Network Address Translation,
@@ -247,4 +248,19 @@
 	  If you want to compile it in kernel, say Y. To compile it as a
 	  module, choose M here. If unsure, say N.
 
+config	IP_VS_NFCT
+	bool "Netfilter connection tracking"
+	depends on NF_CONNTRACK
+	---help---
+	  The Netfilter connection tracking support allows the IPVS
+	  connection state to be exported to the Netfilter framework
+	  for filtering purposes.
+
+config	IP_VS_PE_SIP
+	tristate "SIP persistence engine"
+        depends on IP_VS_PROTO_UDP
+	depends on NF_CONNTRACK_SIP
+	---help---
+	  Allow persistence based on the SIP Call-ID
+
 endif # IP_VS
diff --git a/net/netfilter/ipvs/Makefile b/net/netfilter/ipvs/Makefile
index e3baefd..34ee602 100644
--- a/net/netfilter/ipvs/Makefile
+++ b/net/netfilter/ipvs/Makefile
@@ -9,10 +9,13 @@
 ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_AH_ESP) += ip_vs_proto_ah_esp.o
 ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_SCTP) += ip_vs_proto_sctp.o
 
+ip_vs-extra_objs-y :=
+ip_vs-extra_objs-$(CONFIG_IP_VS_NFCT) += ip_vs_nfct.o
+
 ip_vs-objs :=	ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o	   \
 		ip_vs_xmit.o ip_vs_app.o ip_vs_sync.o	   		   \
-		ip_vs_est.o ip_vs_proto.o 				   \
-		$(ip_vs_proto-objs-y)
+		ip_vs_est.o ip_vs_proto.o ip_vs_pe.o			   \
+		$(ip_vs_proto-objs-y) $(ip_vs-extra_objs-y)
 
 
 # IPVS core
@@ -32,3 +35,6 @@
 
 # IPVS application helpers
 obj-$(CONFIG_IP_VS_FTP) += ip_vs_ftp.o
+
+# IPVS connection template retrievers
+obj-$(CONFIG_IP_VS_PE_SIP) += ip_vs_pe_sip.o
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index e76f87f..a475ede 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -103,8 +103,8 @@
 		goto out;
 
 	list_add(&inc->a_list, &app->incs_list);
-	IP_VS_DBG(9, "%s application %s:%u registered\n",
-		  pp->name, inc->name, inc->port);
+	IP_VS_DBG(9, "%s App %s:%u registered\n",
+		  pp->name, inc->name, ntohs(inc->port));
 
 	return 0;
 
@@ -130,7 +130,7 @@
 		pp->unregister_app(inc);
 
 	IP_VS_DBG(9, "%s App %s:%u unregistered\n",
-		  pp->name, inc->name, inc->port);
+		  pp->name, inc->name, ntohs(inc->port));
 
 	list_del(&inc->a_list);
 
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index b71c69a..e9adecd 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -148,6 +148,42 @@
 		& ip_vs_conn_tab_mask;
 }
 
+static unsigned int ip_vs_conn_hashkey_param(const struct ip_vs_conn_param *p,
+					     bool inverse)
+{
+	const union nf_inet_addr *addr;
+	__be16 port;
+
+	if (p->pe_data && p->pe->hashkey_raw)
+		return p->pe->hashkey_raw(p, ip_vs_conn_rnd, inverse) &
+			ip_vs_conn_tab_mask;
+
+	if (likely(!inverse)) {
+		addr = p->caddr;
+		port = p->cport;
+	} else {
+		addr = p->vaddr;
+		port = p->vport;
+	}
+
+	return ip_vs_conn_hashkey(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);
+
+	if (cp->dest && cp->dest->svc->pe) {
+		p.pe = cp->dest->svc->pe;
+		p.pe_data = cp->pe_data;
+		p.pe_data_len = cp->pe_data_len;
+	}
+
+	return ip_vs_conn_hashkey_param(&p, false);
+}
 
 /*
  *	Hashes ip_vs_conn in ip_vs_conn_tab by proto,addr,port.
@@ -162,7 +198,7 @@
 		return 0;
 
 	/* Hash by protocol, client address and port */
-	hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
+	hash = ip_vs_conn_hashkey_conn(cp);
 
 	ct_write_lock(hash);
 	spin_lock(&cp->lock);
@@ -195,7 +231,7 @@
 	int ret;
 
 	/* unhash it and decrease its reference counter */
-	hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
+	hash = ip_vs_conn_hashkey_conn(cp);
 
 	ct_write_lock(hash);
 	spin_lock(&cp->lock);
@@ -218,27 +254,26 @@
 /*
  *  Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
  *  Called for pkts coming from OUTside-to-INside.
- *	s_addr, s_port: pkt source address (foreign host)
- *	d_addr, d_port: pkt dest address (load balancer)
+ *	p->caddr, p->cport: pkt source address (foreign host)
+ *	p->vaddr, p->vport: pkt dest address (load balancer)
  */
-static inline struct ip_vs_conn *__ip_vs_conn_in_get
-(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
- const union nf_inet_addr *d_addr, __be16 d_port)
+static inline struct ip_vs_conn *
+__ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
 {
 	unsigned hash;
 	struct ip_vs_conn *cp;
 
-	hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);
+	hash = ip_vs_conn_hashkey_param(p, false);
 
 	ct_read_lock(hash);
 
 	list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
-		if (cp->af == af &&
-		    ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
-		    ip_vs_addr_equal(af, d_addr, &cp->vaddr) &&
-		    s_port == cp->cport && d_port == cp->vport &&
-		    ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
-		    protocol == cp->protocol) {
+		if (cp->af == p->af &&
+		    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) {
 			/* HIT */
 			atomic_inc(&cp->refcnt);
 			ct_read_unlock(hash);
@@ -251,99 +286,111 @@
 	return NULL;
 }
 
-struct ip_vs_conn *ip_vs_conn_in_get
-(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
- const union nf_inet_addr *d_addr, __be16 d_port)
+struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
 {
 	struct ip_vs_conn *cp;
 
-	cp = __ip_vs_conn_in_get(af, protocol, s_addr, s_port, d_addr, d_port);
-	if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt))
-		cp = __ip_vs_conn_in_get(af, protocol, s_addr, 0, d_addr,
-					 d_port);
+	cp = __ip_vs_conn_in_get(p);
+	if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt)) {
+		struct ip_vs_conn_param cport_zero_p = *p;
+		cport_zero_p.cport = 0;
+		cp = __ip_vs_conn_in_get(&cport_zero_p);
+	}
 
 	IP_VS_DBG_BUF(9, "lookup/in %s %s:%d->%s:%d %s\n",
-		      ip_vs_proto_name(protocol),
-		      IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
-		      IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
+		      ip_vs_proto_name(p->protocol),
+		      IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
+		      IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
 		      cp ? "hit" : "not hit");
 
 	return cp;
 }
 
+static int
+ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
+			    const struct ip_vs_iphdr *iph,
+			    unsigned int proto_off, int inverse,
+			    struct ip_vs_conn_param *p)
+{
+	__be16 _ports[2], *pptr;
+
+	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);
+	else
+		ip_vs_conn_fill_param(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)
 {
-	__be16 _ports[2], *pptr;
+	struct ip_vs_conn_param p;
 
-	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
-	if (pptr == NULL)
+	if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
 		return NULL;
 
-	if (likely(!inverse))
-		return ip_vs_conn_in_get(af, iph->protocol,
-					 &iph->saddr, pptr[0],
-					 &iph->daddr, pptr[1]);
-	else
-		return ip_vs_conn_in_get(af, iph->protocol,
-					 &iph->daddr, pptr[1],
-					 &iph->saddr, pptr[0]);
+	return ip_vs_conn_in_get(&p);
 }
 EXPORT_SYMBOL_GPL(ip_vs_conn_in_get_proto);
 
 /* Get reference to connection template */
-struct ip_vs_conn *ip_vs_ct_in_get
-(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
- const union nf_inet_addr *d_addr, __be16 d_port)
+struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p)
 {
 	unsigned hash;
 	struct ip_vs_conn *cp;
 
-	hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);
+	hash = ip_vs_conn_hashkey_param(p, false);
 
 	ct_read_lock(hash);
 
 	list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
-		if (cp->af == af &&
-		    ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
-		    /* protocol should only be IPPROTO_IP if
-		     * d_addr is a fwmark */
-		    ip_vs_addr_equal(protocol == IPPROTO_IP ? AF_UNSPEC : af,
-		                     d_addr, &cp->vaddr) &&
-		    s_port == cp->cport && d_port == cp->vport &&
-		    cp->flags & IP_VS_CONN_F_TEMPLATE &&
-		    protocol == cp->protocol) {
-			/* HIT */
-			atomic_inc(&cp->refcnt);
-			goto out;
+		if (p->pe_data && p->pe->ct_match) {
+			if (p->pe->ct_match(p, cp))
+				goto out;
+			continue;
 		}
+
+		if (cp->af == p->af &&
+		    ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
+		    /* protocol should only be IPPROTO_IP if
+		     * p->vaddr is a fwmark */
+		    ip_vs_addr_equal(p->protocol == IPPROTO_IP ? AF_UNSPEC :
+				     p->af, p->vaddr, &cp->vaddr) &&
+		    p->cport == cp->cport && p->vport == cp->vport &&
+		    cp->flags & IP_VS_CONN_F_TEMPLATE &&
+		    p->protocol == cp->protocol)
+			goto out;
 	}
 	cp = NULL;
 
   out:
+	if (cp)
+		atomic_inc(&cp->refcnt);
 	ct_read_unlock(hash);
 
 	IP_VS_DBG_BUF(9, "template lookup/in %s %s:%d->%s:%d %s\n",
-		      ip_vs_proto_name(protocol),
-		      IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
-		      IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
+		      ip_vs_proto_name(p->protocol),
+		      IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
+		      IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
 		      cp ? "hit" : "not hit");
 
 	return cp;
 }
 
-/*
- *  Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
- *  Called for pkts coming from inside-to-OUTside.
- *	s_addr, s_port: pkt source address (inside host)
- *	d_addr, d_port: pkt dest address (foreign host)
- */
-struct ip_vs_conn *ip_vs_conn_out_get
-(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
- const union nf_inet_addr *d_addr, __be16 d_port)
+/* Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
+ * Called for pkts coming from inside-to-OUTside.
+ *	p->caddr, p->cport: pkt source address (inside host)
+ *	p->vaddr, p->vport: pkt dest address (foreign host) */
+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;
@@ -351,16 +398,16 @@
 	/*
 	 *	Check for "full" addressed entries
 	 */
-	hash = ip_vs_conn_hashkey(af, protocol, d_addr, d_port);
+	hash = ip_vs_conn_hashkey_param(p, true);
 
 	ct_read_lock(hash);
 
 	list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
-		if (cp->af == af &&
-		    ip_vs_addr_equal(af, d_addr, &cp->caddr) &&
-		    ip_vs_addr_equal(af, s_addr, &cp->daddr) &&
-		    d_port == cp->cport && s_port == cp->dport &&
-		    protocol == cp->protocol) {
+		if (cp->af == p->af &&
+		    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) {
 			/* HIT */
 			atomic_inc(&cp->refcnt);
 			ret = cp;
@@ -371,9 +418,9 @@
 	ct_read_unlock(hash);
 
 	IP_VS_DBG_BUF(9, "lookup/out %s %s:%d->%s:%d %s\n",
-		      ip_vs_proto_name(protocol),
-		      IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
-		      IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
+		      ip_vs_proto_name(p->protocol),
+		      IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
+		      IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
 		      ret ? "hit" : "not hit");
 
 	return ret;
@@ -385,20 +432,12 @@
 			 const struct ip_vs_iphdr *iph,
 			 unsigned int proto_off, int inverse)
 {
-	__be16 _ports[2], *pptr;
+	struct ip_vs_conn_param p;
 
-	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
-	if (pptr == NULL)
+	if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
 		return NULL;
 
-	if (likely(!inverse))
-		return ip_vs_conn_out_get(af, iph->protocol,
-					  &iph->saddr, pptr[0],
-					  &iph->daddr, pptr[1]);
-	else
-		return ip_vs_conn_out_get(af, iph->protocol,
-					  &iph->daddr, pptr[1],
-					  &iph->saddr, pptr[0]);
+	return ip_vs_conn_out_get(&p);
 }
 EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto);
 
@@ -505,6 +544,8 @@
 static inline void
 ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
 {
+	unsigned int conn_flags;
+
 	/* if dest is NULL, then return directly */
 	if (!dest)
 		return;
@@ -512,16 +553,20 @@
 	/* Increase the refcnt counter of the dest */
 	atomic_inc(&dest->refcnt);
 
+	conn_flags = atomic_read(&dest->conn_flags);
+	if (cp->protocol != IPPROTO_UDP)
+		conn_flags &= ~IP_VS_CONN_F_ONE_PACKET;
 	/* Bind with the destination and its corresponding transmitter */
-	if ((cp->flags & IP_VS_CONN_F_SYNC) &&
-	    (!(cp->flags & IP_VS_CONN_F_TEMPLATE)))
+	if (cp->flags & IP_VS_CONN_F_SYNC) {
 		/* if the connection is not template and is created
 		 * by sync, preserve the activity flag.
 		 */
-		cp->flags |= atomic_read(&dest->conn_flags) &
-			     (~IP_VS_CONN_F_INACTIVE);
-	else
-		cp->flags |= atomic_read(&dest->conn_flags);
+		if (!(cp->flags & IP_VS_CONN_F_TEMPLATE))
+			conn_flags &= ~IP_VS_CONN_F_INACTIVE;
+		/* connections inherit forwarding method from dest */
+		cp->flags &= ~IP_VS_CONN_F_FWD_MASK;
+	}
+	cp->flags |= conn_flags;
 	cp->dest = dest;
 
 	IP_VS_DBG_BUF(7, "Bind-dest %s c:%s:%d v:%s:%d "
@@ -717,6 +762,10 @@
 		if (cp->control)
 			ip_vs_control_del(cp);
 
+		if (cp->flags & IP_VS_CONN_F_NFCT)
+			ip_vs_conn_drop_conntrack(cp);
+
+		kfree(cp->pe_data);
 		if (unlikely(cp->app != NULL))
 			ip_vs_unbind_app(cp);
 		ip_vs_unbind_dest(cp);
@@ -751,13 +800,12 @@
  *	Create a new connection entry and hash it into the ip_vs_conn_tab
  */
 struct ip_vs_conn *
-ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
-	       const union nf_inet_addr *vaddr, __be16 vport,
+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_conn *cp;
-	struct ip_vs_protocol *pp = ip_vs_proto_get(proto);
+	struct ip_vs_protocol *pp = ip_vs_proto_get(p->protocol);
 
 	cp = kmem_cache_zalloc(ip_vs_conn_cachep, GFP_ATOMIC);
 	if (cp == NULL) {
@@ -767,17 +815,21 @@
 
 	INIT_LIST_HEAD(&cp->c_list);
 	setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
-	cp->af		   = af;
-	cp->protocol	   = proto;
-	ip_vs_addr_copy(af, &cp->caddr, caddr);
-	cp->cport	   = cport;
-	ip_vs_addr_copy(af, &cp->vaddr, vaddr);
-	cp->vport	   = vport;
+	cp->af		   = p->af;
+	cp->protocol	   = p->protocol;
+	ip_vs_addr_copy(p->af, &cp->caddr, p->caddr);
+	cp->cport	   = p->cport;
+	ip_vs_addr_copy(p->af, &cp->vaddr, p->vaddr);
+	cp->vport	   = p->vport;
 	/* proto should only be IPPROTO_IP if d_addr is a fwmark */
-	ip_vs_addr_copy(proto == IPPROTO_IP ? AF_UNSPEC : af,
+	ip_vs_addr_copy(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
 			&cp->daddr, daddr);
 	cp->dport          = dport;
 	cp->flags	   = flags;
+	if (flags & IP_VS_CONN_F_TEMPLATE && p->pe_data) {
+		cp->pe_data = p->pe_data;
+		cp->pe_data_len = p->pe_data_len;
+	}
 	spin_lock_init(&cp->lock);
 
 	/*
@@ -803,7 +855,7 @@
 
 	/* Bind its packet transmitter */
 #ifdef CONFIG_IP_VS_IPV6
-	if (af == AF_INET6)
+	if (p->af == AF_INET6)
 		ip_vs_bind_xmit_v6(cp);
 	else
 #endif
@@ -812,13 +864,22 @@
 	if (unlikely(pp && atomic_read(&pp->appcnt)))
 		ip_vs_bind_app(cp, pp);
 
+	/*
+	 * Allow conntrack to be preserved. By default, conntrack
+	 * is created and destroyed for every packet.
+	 * Sometimes keeping conntrack can be useful for
+	 * IP_VS_CONN_F_ONE_PACKET too.
+	 */
+
+	if (ip_vs_conntrack_enabled())
+		cp->flags |= IP_VS_CONN_F_NFCT;
+
 	/* Hash it in the ip_vs_conn_tab finally */
 	ip_vs_conn_hash(cp);
 
 	return cp;
 }
 
-
 /*
  *	/proc/net/ip_vs_conn entries
  */
@@ -834,7 +895,7 @@
 		list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) {
 			if (pos-- == 0) {
 				seq->private = &ip_vs_conn_tab[idx];
-				return cp;
+			return cp;
 			}
 		}
 		ct_read_unlock_bh(idx);
@@ -891,30 +952,45 @@
 
 	if (v == SEQ_START_TOKEN)
 		seq_puts(seq,
-   "Pro FromIP   FPrt ToIP     TPrt DestIP   DPrt State       Expires\n");
+   "Pro FromIP   FPrt ToIP     TPrt DestIP   DPrt State       Expires PEName PEData\n");
 	else {
 		const struct ip_vs_conn *cp = v;
+		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) {
+			pe_data[0] = ' ';
+			len = strlen(cp->dest->svc->pe->name);
+			memcpy(pe_data + 1, cp->dest->svc->pe->name, len);
+			pe_data[len + 1] = ' ';
+			len += 2;
+			len += cp->dest->svc->pe->show_pe_data(cp,
+							       pe_data + len);
+		}
+		pe_data[len] = '\0';
 
 #ifdef CONFIG_IP_VS_IPV6
 		if (cp->af == AF_INET6)
-			seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X %pI6 %04X %-11s %7lu\n",
+			seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X "
+				"%pI6 %04X %-11s %7lu%s\n",
 				ip_vs_proto_name(cp->protocol),
 				&cp->caddr.in6, ntohs(cp->cport),
 				&cp->vaddr.in6, ntohs(cp->vport),
 				&cp->daddr.in6, ntohs(cp->dport),
 				ip_vs_state_name(cp->protocol, cp->state),
-				(cp->timer.expires-jiffies)/HZ);
+				(cp->timer.expires-jiffies)/HZ, pe_data);
 		else
 #endif
 			seq_printf(seq,
 				"%-3s %08X %04X %08X %04X"
-				" %08X %04X %-11s %7lu\n",
+				" %08X %04X %-11s %7lu%s\n",
 				ip_vs_proto_name(cp->protocol),
 				ntohl(cp->caddr.ip), ntohs(cp->cport),
 				ntohl(cp->vaddr.ip), ntohs(cp->vport),
 				ntohl(cp->daddr.ip), ntohs(cp->dport),
 				ip_vs_state_name(cp->protocol, cp->state),
-				(cp->timer.expires-jiffies)/HZ);
+				(cp->timer.expires-jiffies)/HZ, pe_data);
 	}
 	return 0;
 }
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 4c2f89d..b4e51e9 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -40,6 +40,7 @@
 #include <net/udp.h>
 #include <net/icmp.h>                   /* for icmp_send */
 #include <net/route.h>
+#include <net/ip6_checksum.h>
 
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
@@ -47,6 +48,7 @@
 #ifdef CONFIG_IP_VS_IPV6
 #include <net/ipv6.h>
 #include <linux/netfilter_ipv6.h>
+#include <net/ip6_route.h>
 #endif
 
 #include <net/ip_vs.h>
@@ -175,6 +177,18 @@
 	return pp->state_transition(cp, direction, skb, pp);
 }
 
+static inline void
+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);
+	p->pe = svc->pe;
+	if (p->pe && p->pe->fill_param)
+		p->pe->fill_param(p, skb);
+}
 
 /*
  *  IPVS persistent scheduling function
@@ -185,15 +199,16 @@
  */
 static struct ip_vs_conn *
 ip_vs_sched_persist(struct ip_vs_service *svc,
-		    const struct sk_buff *skb,
+		    struct sk_buff *skb,
 		    __be16 ports[2])
 {
 	struct ip_vs_conn *cp = NULL;
 	struct ip_vs_iphdr iph;
 	struct ip_vs_dest *dest;
 	struct ip_vs_conn *ct;
-	__be16  dport;			/* destination port to forward */
-	__be16  flags;
+	__be16 dport = 0;		/* destination port to forward */
+	unsigned int flags;
+	struct ip_vs_conn_param param;
 	union nf_inet_addr snet;	/* source network of the client,
 					   after masking */
 
@@ -226,120 +241,75 @@
 	 * service, and a template like <caddr, 0, vaddr, vport, daddr, dport>
 	 * is created for other persistent services.
 	 */
-	if (ports[1] == svc->port) {
-		/* Check if a template already exists */
-		if (svc->port != FTPPORT)
-			ct = ip_vs_ct_in_get(svc->af, iph.protocol, &snet, 0,
-					     &iph.daddr, ports[1]);
-		else
-			ct = ip_vs_ct_in_get(svc->af, iph.protocol, &snet, 0,
-					     &iph.daddr, 0);
+	{
+		int protocol = iph.protocol;
+		const union nf_inet_addr *vaddr = &iph.daddr;
+		const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
+		__be16 vport = 0;
 
-		if (!ct || !ip_vs_check_template(ct)) {
-			/*
-			 * No template found or the dest of the connection
-			 * template is not available.
-			 */
-			dest = svc->scheduler->schedule(svc, skb);
-			if (dest == NULL) {
-				IP_VS_DBG(1, "p-schedule: no dest found.\n");
-				return NULL;
-			}
-
-			/*
-			 * Create a template like <protocol,caddr,0,
-			 * vaddr,vport,daddr,dport> for non-ftp service,
-			 * and <protocol,caddr,0,vaddr,0,daddr,0>
-			 * for ftp service.
+		if (ports[1] == 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)
-				ct = ip_vs_conn_new(svc->af, iph.protocol,
-						    &snet, 0,
-						    &iph.daddr,
-						    ports[1],
-						    &dest->addr, dest->port,
-						    IP_VS_CONN_F_TEMPLATE,
-						    dest);
-			else
-				ct = ip_vs_conn_new(svc->af, iph.protocol,
-						    &snet, 0,
-						    &iph.daddr, 0,
-						    &dest->addr, 0,
-						    IP_VS_CONN_F_TEMPLATE,
-						    dest);
-			if (ct == NULL)
-				return NULL;
-
-			ct->timeout = svc->timeout;
+				vport = ports[1];
 		} else {
-			/* set destination with the found template */
-			dest = ct->dest;
-		}
-		dport = dest->port;
-	} else {
-		/*
-		 * Note: persistent fwmark-based services and persistent
-		 * port zero service are handled here.
-		 * fwmark template: <IPPROTO_IP,caddr,0,fwmark,0,daddr,0>
-		 * port zero template: <protocol,caddr,0,vaddr,0,daddr,0>
-		 */
-		if (svc->fwmark) {
-			union nf_inet_addr fwmark = {
-				.ip = htonl(svc->fwmark)
-			};
-
-			ct = ip_vs_ct_in_get(svc->af, IPPROTO_IP, &snet, 0,
-					     &fwmark, 0);
-		} else
-			ct = ip_vs_ct_in_get(svc->af, iph.protocol, &snet, 0,
-					     &iph.daddr, 0);
-
-		if (!ct || !ip_vs_check_template(ct)) {
-			/*
-			 * If it is not persistent port zero, return NULL,
-			 * otherwise create a connection template.
-			 */
-			if (svc->port)
-				return NULL;
-
-			dest = svc->scheduler->schedule(svc, skb);
-			if (dest == NULL) {
-				IP_VS_DBG(1, "p-schedule: no dest found.\n");
-				return NULL;
-			}
-
-			/*
-			 * Create a template according to the service
+			/* Note: persistent fwmark-based services and
+			 * persistent port zero service are handled here.
+			 * fwmark template:
+			 * <IPPROTO_IP,caddr,0,fwmark,0,daddr,0>
+			 * port zero template:
+			 * <protocol,caddr,0,vaddr,0,daddr,0>
 			 */
 			if (svc->fwmark) {
-				union nf_inet_addr fwmark = {
-					.ip = htonl(svc->fwmark)
-				};
-
-				ct = ip_vs_conn_new(svc->af, IPPROTO_IP,
-						    &snet, 0,
-						    &fwmark, 0,
-						    &dest->addr, 0,
-						    IP_VS_CONN_F_TEMPLATE,
-						    dest);
-			} else
-				ct = ip_vs_conn_new(svc->af, iph.protocol,
-						    &snet, 0,
-						    &iph.daddr, 0,
-						    &dest->addr, 0,
-						    IP_VS_CONN_F_TEMPLATE,
-						    dest);
-			if (ct == NULL)
-				return NULL;
-
-			ct->timeout = svc->timeout;
-		} else {
-			/* set destination with the found template */
-			dest = ct->dest;
+				protocol = IPPROTO_IP;
+				vaddr = &fwmark;
+			}
 		}
-		dport = ports[1];
+		ip_vs_conn_fill_param_persist(svc, skb, protocol, &snet, 0,
+					      vaddr, vport, &param);
 	}
 
+	/* 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
+		 * template is not available.
+		 */
+		dest = svc->scheduler->schedule(svc, skb);
+		if (!dest) {
+			IP_VS_DBG(1, "p-schedule: no dest found.\n");
+			kfree(param.pe_data);
+			return NULL;
+		}
+
+		if (ports[1] == svc->port && svc->port != FTPPORT)
+			dport = dest->port;
+
+		/* Create a template
+		 * This adds param.pe_data to the template,
+		 * 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);
+		if (ct == NULL) {
+			kfree(param.pe_data);
+			return NULL;
+		}
+
+		ct->timeout = svc->timeout;
+	} else {
+		/* set destination with the found template */
+		dest = ct->dest;
+		kfree(param.pe_data);
+	}
+
+	dport = ports[1];
+	if (dport == svc->port && dest->port)
+		dport = dest->port;
+
 	flags = (svc->flags & IP_VS_SVC_F_ONEPACKET
 		 && iph.protocol == IPPROTO_UDP)?
 		IP_VS_CONN_F_ONE_PACKET : 0;
@@ -347,12 +317,9 @@
 	/*
 	 *    Create a new connection according to the template
 	 */
-	cp = ip_vs_conn_new(svc->af, iph.protocol,
-			    &iph.saddr, ports[0],
-			    &iph.daddr, ports[1],
-			    &dest->addr, dport,
-			    flags,
-			    dest);
+	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);
 	if (cp == NULL) {
 		ip_vs_conn_put(ct);
 		return NULL;
@@ -376,23 +343,53 @@
  *  Protocols supported: TCP, UDP
  */
 struct ip_vs_conn *
-ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
+ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
+	       struct ip_vs_protocol *pp, int *ignored)
 {
 	struct ip_vs_conn *cp = NULL;
 	struct ip_vs_iphdr iph;
 	struct ip_vs_dest *dest;
-	__be16 _ports[2], *pptr, flags;
+	__be16 _ports[2], *pptr;
+	unsigned int flags;
 
+	*ignored = 1;
 	ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
 	pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports);
 	if (pptr == NULL)
 		return NULL;
 
 	/*
+	 * FTPDATA needs this check when using local real server.
+	 * Never schedule Active FTPDATA connections from real server.
+	 * For LVS-NAT they must be already created. For other methods
+	 * with persistence the connection is created on SYN+ACK.
+	 */
+	if (pptr[0] == FTPDATA) {
+		IP_VS_DBG_PKT(12, svc->af, pp, skb, 0,
+			      "Not scheduling FTPDATA");
+		return NULL;
+	}
+
+	/*
+	 * Do not schedule replies from local real server. It is risky
+	 * for fwmark services but mostly for persistent services.
+	 */
+	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))) {
+		IP_VS_DBG_PKT(12, svc->af, pp, skb, 0,
+			      "Not scheduling reply for existing connection");
+		__ip_vs_conn_put(cp);
+		return NULL;
+	}
+
+	/*
 	 *    Persistent service
 	 */
-	if (svc->flags & IP_VS_SVC_F_PERSISTENT)
+	if (svc->flags & IP_VS_SVC_F_PERSISTENT) {
+		*ignored = 0;
 		return ip_vs_sched_persist(svc, skb, pptr);
+	}
 
 	/*
 	 *    Non-persistent service
@@ -405,6 +402,8 @@
 		return NULL;
 	}
 
+	*ignored = 0;
+
 	dest = svc->scheduler->schedule(svc, skb);
 	if (dest == NULL) {
 		IP_VS_DBG(1, "Schedule: no dest found.\n");
@@ -418,14 +417,16 @@
 	/*
 	 *    Create a connection entry.
 	 */
-	cp = ip_vs_conn_new(svc->af, iph.protocol,
-			    &iph.saddr, pptr[0],
-			    &iph.daddr, pptr[1],
-			    &dest->addr, dest->port ? dest->port : pptr[1],
-			    flags,
-			    dest);
-	if (cp == NULL)
-		return NULL;
+	{
+		struct ip_vs_conn_param p;
+		ip_vs_conn_fill_param(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)
+			return NULL;
+	}
 
 	IP_VS_DBG_BUF(6, "Schedule fwd:%c c:%s:%u v:%s:%u "
 		      "d:%s:%u conn->flags:%X conn->refcnt:%d\n",
@@ -472,23 +473,26 @@
 	if (sysctl_ip_vs_cache_bypass && svc->fwmark && unicast) {
 		int ret, cs;
 		struct ip_vs_conn *cp;
-		__u16 flags = (svc->flags & IP_VS_SVC_F_ONEPACKET &&
-				iph.protocol == IPPROTO_UDP)?
-				IP_VS_CONN_F_ONE_PACKET : 0;
+		unsigned int flags = (svc->flags & IP_VS_SVC_F_ONEPACKET &&
+				      iph.protocol == IPPROTO_UDP)?
+				      IP_VS_CONN_F_ONE_PACKET : 0;
 		union nf_inet_addr daddr =  { .all = { 0, 0, 0, 0 } };
 
 		ip_vs_service_put(svc);
 
 		/* create a new connection entry */
 		IP_VS_DBG(6, "%s(): create a cache_bypass entry\n", __func__);
-		cp = ip_vs_conn_new(svc->af, iph.protocol,
-				    &iph.saddr, pptr[0],
-				    &iph.daddr, pptr[1],
-				    &daddr, 0,
-				    IP_VS_CONN_F_BYPASS | flags,
-				    NULL);
-		if (cp == NULL)
-			return NF_DROP;
+		{
+			struct ip_vs_conn_param p;
+			ip_vs_conn_fill_param(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);
+			if (!cp)
+				return NF_DROP;
+		}
 
 		/* statistics */
 		ip_vs_in_stats(cp, skb);
@@ -526,9 +530,14 @@
 	 * ICMP_PORT_UNREACH is sent here no matter it is TCP/UDP. --WZ
 	 */
 #ifdef CONFIG_IP_VS_IPV6
-	if (svc->af == AF_INET6)
+	if (svc->af == AF_INET6) {
+		if (!skb->dev) {
+			struct net *net = dev_net(skb_dst(skb)->dev);
+
+			skb->dev = net->loopback_dev;
+		}
 		icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
-	else
+	} else
 #endif
 		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 
@@ -540,6 +549,15 @@
 	return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
 }
 
+static inline enum ip_defrag_users ip_vs_defrag_user(unsigned int hooknum)
+{
+	if (NF_INET_LOCAL_IN == hooknum)
+		return IP_DEFRAG_VS_IN;
+	if (NF_INET_FORWARD == hooknum)
+		return IP_DEFRAG_VS_FWD;
+	return IP_DEFRAG_VS_OUT;
+}
+
 static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
 {
 	int err = ip_defrag(skb, user);
@@ -600,10 +618,10 @@
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 	if (inout)
-		IP_VS_DBG_PKT(11, pp, skb, (void *)ciph - (void *)iph,
+		IP_VS_DBG_PKT(11, AF_INET, pp, skb, (void *)ciph - (void *)iph,
 			"Forwarding altered outgoing ICMP");
 	else
-		IP_VS_DBG_PKT(11, pp, skb, (void *)ciph - (void *)iph,
+		IP_VS_DBG_PKT(11, AF_INET, pp, skb, (void *)ciph - (void *)iph,
 			"Forwarding altered incoming ICMP");
 }
 
@@ -637,17 +655,21 @@
 	}
 
 	/* And finally the ICMP checksum */
-	icmph->icmp6_cksum = 0;
-	/* TODO IPv6: is this correct for ICMPv6? */
-	ip_vs_checksum_complete(skb, icmp_offset);
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	icmph->icmp6_cksum = ~csum_ipv6_magic(&iph->saddr, &iph->daddr,
+					      skb->len - icmp_offset,
+					      IPPROTO_ICMPV6, 0);
+	skb->csum_start = skb_network_header(skb) - skb->head + icmp_offset;
+	skb->csum_offset = offsetof(struct icmp6hdr, icmp6_cksum);
+	skb->ip_summed = CHECKSUM_PARTIAL;
 
 	if (inout)
-		IP_VS_DBG_PKT(11, pp, skb, (void *)ciph - (void *)iph,
-			"Forwarding altered outgoing ICMPv6");
+		IP_VS_DBG_PKT(11, AF_INET6, pp, skb,
+			      (void *)ciph - (void *)iph,
+			      "Forwarding altered outgoing ICMPv6");
 	else
-		IP_VS_DBG_PKT(11, pp, skb, (void *)ciph - (void *)iph,
-			"Forwarding altered incoming ICMPv6");
+		IP_VS_DBG_PKT(11, AF_INET6, pp, skb,
+			      (void *)ciph - (void *)iph,
+			      "Forwarding altered incoming ICMPv6");
 }
 #endif
 
@@ -688,10 +710,25 @@
 #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;
+
 	/* do the statistics and put it back */
 	ip_vs_out_stats(cp, skb);
 
 	skb->ipvs_property = 1;
+	if (!(cp->flags & IP_VS_CONN_F_NFCT))
+		ip_vs_notrack(skb);
+	else
+		ip_vs_update_conntrack(skb, cp, 0);
 	verdict = NF_ACCEPT;
 
 out:
@@ -705,7 +742,8 @@
  *	Find any that might be relevant, check against existing connections.
  *	Currently handles error types - unreachable, quench, ttl exceeded.
  */
-static int ip_vs_out_icmp(struct sk_buff *skb, int *related)
+static int ip_vs_out_icmp(struct sk_buff *skb, int *related,
+			  unsigned int hooknum)
 {
 	struct iphdr *iph;
 	struct icmphdr	_icmph, *ic;
@@ -720,7 +758,7 @@
 
 	/* reassemble IP fragments */
 	if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
-		if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
+		if (ip_vs_gather_frags(skb, ip_vs_defrag_user(hooknum)))
 			return NF_STOLEN;
 	}
 
@@ -763,7 +801,8 @@
 		     pp->dont_defrag))
 		return NF_ACCEPT;
 
-	IP_VS_DBG_PKT(11, pp, skb, offset, "Checking outgoing ICMP for");
+	IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+		      "Checking outgoing ICMP for");
 
 	offset += cih->ihl * 4;
 
@@ -779,7 +818,8 @@
 }
 
 #ifdef CONFIG_IP_VS_IPV6
-static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related)
+static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
+			     unsigned int hooknum)
 {
 	struct ipv6hdr *iph;
 	struct icmp6hdr	_icmph, *ic;
@@ -795,7 +835,7 @@
 
 	/* reassemble IP fragments */
 	if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) {
-		if (ip_vs_gather_frags_v6(skb, IP_DEFRAG_VS_OUT))
+		if (ip_vs_gather_frags_v6(skb, ip_vs_defrag_user(hooknum)))
 			return NF_STOLEN;
 	}
 
@@ -838,7 +878,8 @@
 	if (unlikely(cih->nexthdr == IPPROTO_FRAGMENT && pp->dont_defrag))
 		return NF_ACCEPT;
 
-	IP_VS_DBG_PKT(11, pp, skb, offset, "Checking outgoing ICMPv6 for");
+	IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offset,
+		      "Checking outgoing ICMPv6 for");
 
 	offset += sizeof(struct ipv6hdr);
 
@@ -886,7 +927,7 @@
 handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 		struct ip_vs_conn *cp, int ihl)
 {
-	IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet");
+	IP_VS_DBG_PKT(11, af, pp, skb, 0, "Outgoing packet");
 
 	if (!skb_make_writable(skb, ihl))
 		goto drop;
@@ -905,6 +946,15 @@
 		ip_send_check(ip_hdr(skb));
 	}
 
+	/*
+	 * nf_iterate does not expect change in the skb->dst->dev.
+	 * It looks like it is not fatal to enable this code for hooks
+	 * where our handlers are at the end of the chain list and
+	 * when all next handlers use skb->dst->dev and not outdev.
+	 * It will definitely route properly the inout NAT traffic
+	 * when multiple paths are used.
+	 */
+
 	/* For policy routing, packets originating from this
 	 * machine itself may be routed differently to packets
 	 * passing through.  We want this packet to be routed as
@@ -913,21 +963,25 @@
 	 */
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6) {
-		if (ip6_route_me_harder(skb) != 0)
+		if (sysctl_ip_vs_snat_reroute && ip6_route_me_harder(skb) != 0)
 			goto drop;
 	} else
 #endif
-		if (ip_route_me_harder(skb, RTN_LOCAL) != 0)
+		if ((sysctl_ip_vs_snat_reroute ||
+		     skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
+		    ip_route_me_harder(skb, RTN_LOCAL) != 0)
 			goto drop;
 
-	IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT");
+	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_update_conntrack(skb, cp, 0);
-	ip_vs_conn_put(cp);
-
 	skb->ipvs_property = 1;
+	if (!(cp->flags & IP_VS_CONN_F_NFCT))
+		ip_vs_notrack(skb);
+	else
+		ip_vs_update_conntrack(skb, cp, 0);
+	ip_vs_conn_put(cp);
 
 	LeaveFunction(11);
 	return NF_ACCEPT;
@@ -935,35 +989,46 @@
 drop:
 	ip_vs_conn_put(cp);
 	kfree_skb(skb);
+	LeaveFunction(11);
 	return NF_STOLEN;
 }
 
 /*
- *	It is hooked at the NF_INET_FORWARD chain, used only for VS/NAT.
  *	Check if outgoing packet belongs to the established ip_vs_conn.
  */
 static unsigned int
-ip_vs_out(unsigned int hooknum, struct sk_buff *skb,
-	  const struct net_device *in, const struct net_device *out,
-	  int (*okfn)(struct sk_buff *))
+ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
 {
 	struct ip_vs_iphdr iph;
 	struct ip_vs_protocol *pp;
 	struct ip_vs_conn *cp;
-	int af;
 
 	EnterFunction(11);
 
-	af = (skb->protocol == htons(ETH_P_IP)) ? AF_INET : AF_INET6;
-
+	/* Already marked as IPVS request or reply? */
 	if (skb->ipvs_property)
 		return NF_ACCEPT;
 
+	/* Bad... Do not break raw sockets */
+	if (unlikely(skb->sk != NULL && hooknum == NF_INET_LOCAL_OUT &&
+		     af == AF_INET)) {
+		struct sock *sk = skb->sk;
+		struct inet_sock *inet = inet_sk(skb->sk);
+
+		if (inet && sk->sk_family == PF_INET && inet->nodefrag)
+			return NF_ACCEPT;
+	}
+
+	if (unlikely(!skb_dst(skb)))
+		return NF_ACCEPT;
+
 	ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6) {
 		if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
-			int related, verdict = ip_vs_out_icmp_v6(skb, &related);
+			int related;
+			int verdict = ip_vs_out_icmp_v6(skb, &related,
+							hooknum);
 
 			if (related)
 				return verdict;
@@ -972,7 +1037,8 @@
 	} else
 #endif
 		if (unlikely(iph.protocol == IPPROTO_ICMP)) {
-			int related, verdict = ip_vs_out_icmp(skb, &related);
+			int related;
+			int verdict = ip_vs_out_icmp(skb, &related, hooknum);
 
 			if (related)
 				return verdict;
@@ -986,19 +1052,19 @@
 	/* reassemble IP fragments */
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6) {
-		if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
-			int related, verdict = ip_vs_out_icmp_v6(skb, &related);
-
-			if (related)
-				return verdict;
-
-			ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+		if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) {
+			if (ip_vs_gather_frags_v6(skb,
+						  ip_vs_defrag_user(hooknum)))
+				return NF_STOLEN;
 		}
+
+		ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
 	} else
 #endif
 		if (unlikely(ip_hdr(skb)->frag_off & htons(IP_MF|IP_OFFSET) &&
 			     !pp->dont_defrag)) {
-			if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT))
+			if (ip_vs_gather_frags(skb,
+					       ip_vs_defrag_user(hooknum)))
 				return NF_STOLEN;
 
 			ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
@@ -1009,55 +1075,123 @@
 	 */
 	cp = pp->conn_out_get(af, skb, pp, &iph, iph.len, 0);
 
-	if (unlikely(!cp)) {
-		if (sysctl_ip_vs_nat_icmp_send &&
-		    (pp->protocol == IPPROTO_TCP ||
-		     pp->protocol == IPPROTO_UDP ||
-		     pp->protocol == IPPROTO_SCTP)) {
-			__be16 _ports[2], *pptr;
+	if (likely(cp))
+		return handle_response(af, skb, pp, cp, iph.len);
+	if (sysctl_ip_vs_nat_icmp_send &&
+	    (pp->protocol == IPPROTO_TCP ||
+	     pp->protocol == IPPROTO_UDP ||
+	     pp->protocol == IPPROTO_SCTP)) {
+		__be16 _ports[2], *pptr;
 
-			pptr = skb_header_pointer(skb, iph.len,
-						  sizeof(_ports), _ports);
-			if (pptr == NULL)
-				return NF_ACCEPT;	/* Not for me */
-			if (ip_vs_lookup_real_service(af, iph.protocol,
-						      &iph.saddr,
-						      pptr[0])) {
-				/*
-				 * Notify the real server: there is no
-				 * existing entry if it is not RST
-				 * packet or not TCP packet.
-				 */
-				if ((iph.protocol != IPPROTO_TCP &&
-				     iph.protocol != IPPROTO_SCTP)
-				     || ((iph.protocol == IPPROTO_TCP
-					  && !is_tcp_reset(skb, iph.len))
-					 || (iph.protocol == IPPROTO_SCTP
-						&& !is_sctp_abort(skb,
-							iph.len)))) {
+		pptr = skb_header_pointer(skb, iph.len,
+					  sizeof(_ports), _ports);
+		if (pptr == NULL)
+			return NF_ACCEPT;	/* Not for me */
+		if (ip_vs_lookup_real_service(af, iph.protocol,
+					      &iph.saddr,
+					      pptr[0])) {
+			/*
+			 * Notify the real server: there is no
+			 * existing entry if it is not RST
+			 * packet or not TCP packet.
+			 */
+			if ((iph.protocol != IPPROTO_TCP &&
+			     iph.protocol != IPPROTO_SCTP)
+			     || ((iph.protocol == IPPROTO_TCP
+				  && !is_tcp_reset(skb, iph.len))
+				 || (iph.protocol == IPPROTO_SCTP
+					&& !is_sctp_abort(skb,
+						iph.len)))) {
 #ifdef CONFIG_IP_VS_IPV6
-					if (af == AF_INET6)
-						icmpv6_send(skb,
-							    ICMPV6_DEST_UNREACH,
-							    ICMPV6_PORT_UNREACH,
-							    0);
-					else
+				if (af == AF_INET6) {
+					struct net *net =
+						dev_net(skb_dst(skb)->dev);
+
+					if (!skb->dev)
+						skb->dev = net->loopback_dev;
+					icmpv6_send(skb,
+						    ICMPV6_DEST_UNREACH,
+						    ICMPV6_PORT_UNREACH,
+						    0);
+				} else
 #endif
-						icmp_send(skb,
-							  ICMP_DEST_UNREACH,
-							  ICMP_PORT_UNREACH, 0);
-					return NF_DROP;
-				}
+					icmp_send(skb,
+						  ICMP_DEST_UNREACH,
+						  ICMP_PORT_UNREACH, 0);
+				return NF_DROP;
 			}
 		}
-		IP_VS_DBG_PKT(12, pp, skb, 0,
-			      "packet continues traversal as normal");
-		return NF_ACCEPT;
 	}
-
-	return handle_response(af, skb, pp, cp, iph.len);
+	IP_VS_DBG_PKT(12, af, pp, skb, 0,
+		      "ip_vs_out: packet continues traversal as normal");
+	return NF_ACCEPT;
 }
 
+/*
+ *	It is hooked at the NF_INET_FORWARD and NF_INET_LOCAL_IN chain,
+ *	used only for VS/NAT.
+ *	Check if packet is reply for established ip_vs_conn.
+ */
+static unsigned int
+ip_vs_reply4(unsigned int hooknum, struct sk_buff *skb,
+	     const struct net_device *in, const struct net_device *out,
+	     int (*okfn)(struct sk_buff *))
+{
+	return ip_vs_out(hooknum, skb, AF_INET);
+}
+
+/*
+ *	It is hooked at the NF_INET_LOCAL_OUT chain, used only for VS/NAT.
+ *	Check if packet is reply for established ip_vs_conn.
+ */
+static unsigned int
+ip_vs_local_reply4(unsigned int hooknum, struct sk_buff *skb,
+		   const struct net_device *in, const struct net_device *out,
+		   int (*okfn)(struct sk_buff *))
+{
+	unsigned int verdict;
+
+	/* Disable BH in LOCAL_OUT until all places are fixed */
+	local_bh_disable();
+	verdict = ip_vs_out(hooknum, skb, AF_INET);
+	local_bh_enable();
+	return verdict;
+}
+
+#ifdef CONFIG_IP_VS_IPV6
+
+/*
+ *	It is hooked at the NF_INET_FORWARD and NF_INET_LOCAL_IN chain,
+ *	used only for VS/NAT.
+ *	Check if packet is reply for established ip_vs_conn.
+ */
+static unsigned int
+ip_vs_reply6(unsigned int hooknum, struct sk_buff *skb,
+	     const struct net_device *in, const struct net_device *out,
+	     int (*okfn)(struct sk_buff *))
+{
+	return ip_vs_out(hooknum, skb, AF_INET6);
+}
+
+/*
+ *	It is hooked at the NF_INET_LOCAL_OUT chain, used only for VS/NAT.
+ *	Check if packet is reply for established ip_vs_conn.
+ */
+static unsigned int
+ip_vs_local_reply6(unsigned int hooknum, struct sk_buff *skb,
+		   const struct net_device *in, const struct net_device *out,
+		   int (*okfn)(struct sk_buff *))
+{
+	unsigned int verdict;
+
+	/* Disable BH in LOCAL_OUT until all places are fixed */
+	local_bh_disable();
+	verdict = ip_vs_out(hooknum, skb, AF_INET6);
+	local_bh_enable();
+	return verdict;
+}
+
+#endif
 
 /*
  *	Handle ICMP messages in the outside-to-inside direction (incoming).
@@ -1081,8 +1215,7 @@
 
 	/* reassemble IP fragments */
 	if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
-		if (ip_vs_gather_frags(skb, hooknum == NF_INET_LOCAL_IN ?
-					    IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD))
+		if (ip_vs_gather_frags(skb, ip_vs_defrag_user(hooknum)))
 			return NF_STOLEN;
 	}
 
@@ -1125,7 +1258,8 @@
 		     pp->dont_defrag))
 		return NF_ACCEPT;
 
-	IP_VS_DBG_PKT(11, pp, skb, offset, "Checking incoming ICMP for");
+	IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
+		      "Checking incoming ICMP for");
 
 	offset += cih->ihl * 4;
 
@@ -1159,7 +1293,14 @@
 	if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
 		offset += 2 * sizeof(__u16);
 	verdict = ip_vs_icmp_xmit(skb, cp, pp, offset);
-	/* do not touch skb anymore */
+	/* LOCALNODE from FORWARD hook is not supported */
+	if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD &&
+	    skb_rtable(skb)->rt_flags & RTCF_LOCAL) {
+		IP_VS_DBG(1, "%s(): "
+			  "local delivery to %pI4 but in FORWARD\n",
+			  __func__, &skb_rtable(skb)->rt_dst);
+		verdict = NF_DROP;
+	}
 
   out:
 	__ip_vs_conn_put(cp);
@@ -1180,14 +1321,13 @@
 	struct ip_vs_protocol *pp;
 	unsigned int offset, verdict;
 	union nf_inet_addr snet;
+	struct rt6_info *rt;
 
 	*related = 1;
 
 	/* reassemble IP fragments */
 	if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) {
-		if (ip_vs_gather_frags_v6(skb, hooknum == NF_INET_LOCAL_IN ?
-					       IP_DEFRAG_VS_IN :
-					       IP_DEFRAG_VS_FWD))
+		if (ip_vs_gather_frags_v6(skb, ip_vs_defrag_user(hooknum)))
 			return NF_STOLEN;
 	}
 
@@ -1230,7 +1370,8 @@
 	if (unlikely(cih->nexthdr == IPPROTO_FRAGMENT && pp->dont_defrag))
 		return NF_ACCEPT;
 
-	IP_VS_DBG_PKT(11, pp, skb, offset, "Checking incoming ICMPv6 for");
+	IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offset,
+		      "Checking incoming ICMPv6 for");
 
 	offset += sizeof(struct ipv6hdr);
 
@@ -1258,7 +1399,15 @@
 	    IPPROTO_SCTP == cih->nexthdr)
 		offset += 2 * sizeof(__u16);
 	verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset);
-	/* do not touch skb anymore */
+	/* LOCALNODE from FORWARD hook is not supported */
+	if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD &&
+	    (rt = (struct rt6_info *) skb_dst(skb)) &&
+	    rt->rt6i_dev && rt->rt6i_dev->flags & IFF_LOOPBACK) {
+		IP_VS_DBG(1, "%s(): "
+			  "local delivery to %pI6 but in FORWARD\n",
+			  __func__, &rt->rt6i_dst);
+		verdict = NF_DROP;
+	}
 
 	__ip_vs_conn_put(cp);
 
@@ -1272,35 +1421,49 @@
  *	and send it on its way...
  */
 static unsigned int
-ip_vs_in(unsigned int hooknum, struct sk_buff *skb,
-	 const struct net_device *in, const struct net_device *out,
-	 int (*okfn)(struct sk_buff *))
+ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
 {
 	struct ip_vs_iphdr iph;
 	struct ip_vs_protocol *pp;
 	struct ip_vs_conn *cp;
-	int ret, restart, af, pkts;
+	int ret, restart, pkts;
 
-	af = (skb->protocol == htons(ETH_P_IP)) ? AF_INET : AF_INET6;
-
-	ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+	/* Already marked as IPVS request or reply? */
+	if (skb->ipvs_property)
+		return NF_ACCEPT;
 
 	/*
-	 *	Big tappo: only PACKET_HOST, including loopback for local client
-	 *	Don't handle local packets on IPv6 for now
+	 *	Big tappo:
+	 *	- remote client: only PACKET_HOST
+	 *	- route: used for struct net when skb->dev is unset
 	 */
-	if (unlikely(skb->pkt_type != PACKET_HOST)) {
-		IP_VS_DBG_BUF(12, "packet type=%d proto=%d daddr=%s ignored\n",
-			      skb->pkt_type,
-			      iph.protocol,
-			      IP_VS_DBG_ADDR(af, &iph.daddr));
+	if (unlikely((skb->pkt_type != PACKET_HOST &&
+		      hooknum != NF_INET_LOCAL_OUT) ||
+		     !skb_dst(skb))) {
+		ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+		IP_VS_DBG_BUF(12, "packet type=%d proto=%d daddr=%s"
+			      " ignored in hook %u\n",
+			      skb->pkt_type, iph.protocol,
+			      IP_VS_DBG_ADDR(af, &iph.daddr), hooknum);
 		return NF_ACCEPT;
 	}
+	ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+
+	/* Bad... Do not break raw sockets */
+	if (unlikely(skb->sk != NULL && hooknum == NF_INET_LOCAL_OUT &&
+		     af == AF_INET)) {
+		struct sock *sk = skb->sk;
+		struct inet_sock *inet = inet_sk(skb->sk);
+
+		if (inet && sk->sk_family == PF_INET && inet->nodefrag)
+			return NF_ACCEPT;
+	}
 
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6) {
 		if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
-			int related, verdict = ip_vs_in_icmp_v6(skb, &related, hooknum);
+			int related;
+			int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum);
 
 			if (related)
 				return verdict;
@@ -1309,7 +1472,8 @@
 	} else
 #endif
 		if (unlikely(iph.protocol == IPPROTO_ICMP)) {
-			int related, verdict = ip_vs_in_icmp(skb, &related, hooknum);
+			int related;
+			int verdict = ip_vs_in_icmp(skb, &related, hooknum);
 
 			if (related)
 				return verdict;
@@ -1329,23 +1493,18 @@
 	if (unlikely(!cp)) {
 		int v;
 
-		/* For local client packets, it could be a response */
-		cp = pp->conn_out_get(af, skb, pp, &iph, iph.len, 0);
-		if (cp)
-			return handle_response(af, skb, pp, cp, iph.len);
-
 		if (!pp->conn_schedule(af, skb, pp, &v, &cp))
 			return v;
 	}
 
 	if (unlikely(!cp)) {
 		/* sorry, all this trouble for a no-hit :) */
-		IP_VS_DBG_PKT(12, pp, skb, 0,
-			      "packet continues traversal as normal");
+		IP_VS_DBG_PKT(12, af, pp, skb, 0,
+			      "ip_vs_in: packet continues traversal as normal");
 		return NF_ACCEPT;
 	}
 
-	IP_VS_DBG_PKT(11, pp, skb, 0, "Incoming packet");
+	IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet");
 
 	/* Check the server status */
 	if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
@@ -1381,8 +1540,7 @@
 	if (af == AF_INET && (ip_vs_sync_state & IP_VS_STATE_MASTER) &&
 	    cp->protocol == IPPROTO_SCTP) {
 		if ((cp->state == IP_VS_SCTP_S_ESTABLISHED &&
-			(atomic_read(&cp->in_pkts) %
-			 sysctl_ip_vs_sync_threshold[1]
+			(pkts % sysctl_ip_vs_sync_threshold[1]
 			 == sysctl_ip_vs_sync_threshold[0])) ||
 				(cp->old_state != cp->state &&
 				 ((cp->state == IP_VS_SCTP_S_CLOSED) ||
@@ -1393,7 +1551,8 @@
 		}
 	}
 
-	if (af == AF_INET &&
+	/* 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) &&
 	    (((cp->protocol != IPPROTO_TCP ||
 	       cp->state == IP_VS_TCP_S_ESTABLISHED) &&
@@ -1412,6 +1571,72 @@
 	return ret;
 }
 
+/*
+ *	AF_INET handler in NF_INET_LOCAL_IN chain
+ *	Schedule and forward packets from remote clients
+ */
+static unsigned int
+ip_vs_remote_request4(unsigned int hooknum, struct sk_buff *skb,
+		      const struct net_device *in,
+		      const struct net_device *out,
+		      int (*okfn)(struct sk_buff *))
+{
+	return ip_vs_in(hooknum, skb, AF_INET);
+}
+
+/*
+ *	AF_INET handler in NF_INET_LOCAL_OUT chain
+ *	Schedule and forward packets from local clients
+ */
+static unsigned int
+ip_vs_local_request4(unsigned int hooknum, struct sk_buff *skb,
+		     const struct net_device *in, const struct net_device *out,
+		     int (*okfn)(struct sk_buff *))
+{
+	unsigned int verdict;
+
+	/* Disable BH in LOCAL_OUT until all places are fixed */
+	local_bh_disable();
+	verdict = ip_vs_in(hooknum, skb, AF_INET);
+	local_bh_enable();
+	return verdict;
+}
+
+#ifdef CONFIG_IP_VS_IPV6
+
+/*
+ *	AF_INET6 handler in NF_INET_LOCAL_IN chain
+ *	Schedule and forward packets from remote clients
+ */
+static unsigned int
+ip_vs_remote_request6(unsigned int hooknum, struct sk_buff *skb,
+		      const struct net_device *in,
+		      const struct net_device *out,
+		      int (*okfn)(struct sk_buff *))
+{
+	return ip_vs_in(hooknum, skb, AF_INET6);
+}
+
+/*
+ *	AF_INET6 handler in NF_INET_LOCAL_OUT chain
+ *	Schedule and forward packets from local clients
+ */
+static unsigned int
+ip_vs_local_request6(unsigned int hooknum, struct sk_buff *skb,
+		     const struct net_device *in, const struct net_device *out,
+		     int (*okfn)(struct sk_buff *))
+{
+	unsigned int verdict;
+
+	/* Disable BH in LOCAL_OUT until all places are fixed */
+	local_bh_disable();
+	verdict = ip_vs_in(hooknum, skb, AF_INET6);
+	local_bh_enable();
+	return verdict;
+}
+
+#endif
+
 
 /*
  *	It is hooked at the NF_INET_FORWARD chain, in order to catch ICMP
@@ -1452,23 +1677,39 @@
 
 
 static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
+	/* After packet filtering, change source only for VS/NAT */
+	{
+		.hook		= ip_vs_reply4,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_INET_LOCAL_IN,
+		.priority	= 99,
+	},
 	/* After packet filtering, forward packet through VS/DR, VS/TUN,
 	 * or VS/NAT(change destination), so that filtering rules can be
 	 * applied to IPVS. */
 	{
-		.hook		= ip_vs_in,
+		.hook		= ip_vs_remote_request4,
 		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
-		.hooknum        = NF_INET_LOCAL_IN,
-		.priority       = 100,
+		.hooknum	= NF_INET_LOCAL_IN,
+		.priority	= 101,
 	},
-	/* After packet filtering, change source only for VS/NAT */
+	/* Before ip_vs_in, change source only for VS/NAT */
 	{
-		.hook		= ip_vs_out,
+		.hook		= ip_vs_local_reply4,
 		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
-		.hooknum        = NF_INET_FORWARD,
-		.priority       = 100,
+		.hooknum	= NF_INET_LOCAL_OUT,
+		.priority	= -99,
+	},
+	/* After mangle, schedule and forward local requests */
+	{
+		.hook		= ip_vs_local_request4,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_INET_LOCAL_OUT,
+		.priority	= -98,
 	},
 	/* After packet filtering (but before ip_vs_out_icmp), catch icmp
 	 * destined for 0.0.0.0/0, which is for incoming IPVS connections */
@@ -1476,27 +1717,51 @@
 		.hook		= ip_vs_forward_icmp,
 		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
-		.hooknum        = NF_INET_FORWARD,
-		.priority       = 99,
+		.hooknum	= NF_INET_FORWARD,
+		.priority	= 99,
+	},
+	/* After packet filtering, change source only for VS/NAT */
+	{
+		.hook		= ip_vs_reply4,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_INET_FORWARD,
+		.priority	= 100,
 	},
 #ifdef CONFIG_IP_VS_IPV6
+	/* After packet filtering, change source only for VS/NAT */
+	{
+		.hook		= ip_vs_reply6,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET6,
+		.hooknum	= NF_INET_LOCAL_IN,
+		.priority	= 99,
+	},
 	/* After packet filtering, forward packet through VS/DR, VS/TUN,
 	 * or VS/NAT(change destination), so that filtering rules can be
 	 * applied to IPVS. */
 	{
-		.hook		= ip_vs_in,
+		.hook		= ip_vs_remote_request6,
 		.owner		= THIS_MODULE,
 		.pf		= PF_INET6,
-		.hooknum        = NF_INET_LOCAL_IN,
-		.priority       = 100,
+		.hooknum	= NF_INET_LOCAL_IN,
+		.priority	= 101,
 	},
-	/* After packet filtering, change source only for VS/NAT */
+	/* Before ip_vs_in, change source only for VS/NAT */
 	{
-		.hook		= ip_vs_out,
+		.hook		= ip_vs_local_reply6,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_INET_LOCAL_OUT,
+		.priority	= -99,
+	},
+	/* After mangle, schedule and forward local requests */
+	{
+		.hook		= ip_vs_local_request6,
 		.owner		= THIS_MODULE,
 		.pf		= PF_INET6,
-		.hooknum        = NF_INET_FORWARD,
-		.priority       = 100,
+		.hooknum	= NF_INET_LOCAL_OUT,
+		.priority	= -98,
 	},
 	/* After packet filtering (but before ip_vs_out_icmp), catch icmp
 	 * destined for 0.0.0.0/0, which is for incoming IPVS connections */
@@ -1504,8 +1769,16 @@
 		.hook		= ip_vs_forward_icmp_v6,
 		.owner		= THIS_MODULE,
 		.pf		= PF_INET6,
-		.hooknum        = NF_INET_FORWARD,
-		.priority       = 99,
+		.hooknum	= NF_INET_FORWARD,
+		.priority	= 99,
+	},
+	/* After packet filtering, change source only for VS/NAT */
+	{
+		.hook		= ip_vs_reply6,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET6,
+		.hooknum	= NF_INET_FORWARD,
+		.priority	= 100,
 	},
 #endif
 };
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 0f0c079..5f5daa3 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -61,7 +61,7 @@
 static DEFINE_RWLOCK(__ip_vs_rs_lock);
 
 /* lock for state and timeout tables */
-static DEFINE_RWLOCK(__ip_vs_securetcp_lock);
+static DEFINE_SPINLOCK(ip_vs_securetcp_lock);
 
 /* lock for drop entry handling */
 static DEFINE_SPINLOCK(__ip_vs_dropentry_lock);
@@ -88,6 +88,10 @@
 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
@@ -204,7 +208,7 @@
 	spin_unlock(&__ip_vs_droppacket_lock);
 
 	/* secure_tcp */
-	write_lock(&__ip_vs_securetcp_lock);
+	spin_lock(&ip_vs_securetcp_lock);
 	switch (sysctl_ip_vs_secure_tcp) {
 	case 0:
 		if (old_secure_tcp >= 2)
@@ -238,7 +242,7 @@
 	old_secure_tcp = sysctl_ip_vs_secure_tcp;
 	if (to_change >= 0)
 		ip_vs_protocol_timeout_change(sysctl_ip_vs_secure_tcp>1);
-	write_unlock(&__ip_vs_securetcp_lock);
+	spin_unlock(&ip_vs_securetcp_lock);
 
 	local_bh_enable();
 }
@@ -401,7 +405,7 @@
  *	Get service by {proto,addr,port} in the service table.
  */
 static inline struct ip_vs_service *
-__ip_vs_service_get(int af, __u16 protocol, const union nf_inet_addr *vaddr,
+__ip_vs_service_find(int af, __u16 protocol, const union nf_inet_addr *vaddr,
 		    __be16 vport)
 {
 	unsigned hash;
@@ -416,7 +420,6 @@
 		    && (svc->port == vport)
 		    && (svc->protocol == protocol)) {
 			/* HIT */
-			atomic_inc(&svc->usecnt);
 			return svc;
 		}
 	}
@@ -429,7 +432,7 @@
  *	Get service by {fwmark} in the service table.
  */
 static inline struct ip_vs_service *
-__ip_vs_svc_fwm_get(int af, __u32 fwmark)
+__ip_vs_svc_fwm_find(int af, __u32 fwmark)
 {
 	unsigned hash;
 	struct ip_vs_service *svc;
@@ -440,7 +443,6 @@
 	list_for_each_entry(svc, &ip_vs_svc_fwm_table[hash], f_list) {
 		if (svc->fwmark == fwmark && svc->af == af) {
 			/* HIT */
-			atomic_inc(&svc->usecnt);
 			return svc;
 		}
 	}
@@ -459,14 +461,14 @@
 	/*
 	 *	Check the table hashed by fwmark first
 	 */
-	if (fwmark && (svc = __ip_vs_svc_fwm_get(af, fwmark)))
+	if (fwmark && (svc = __ip_vs_svc_fwm_find(af, fwmark)))
 		goto out;
 
 	/*
 	 *	Check the table hashed by <protocol,addr,port>
 	 *	for "full" addressed entries
 	 */
-	svc = __ip_vs_service_get(af, protocol, vaddr, vport);
+	svc = __ip_vs_service_find(af, protocol, vaddr, vport);
 
 	if (svc == NULL
 	    && protocol == IPPROTO_TCP
@@ -476,7 +478,7 @@
 		 * Check if ftp service entry exists, the packet
 		 * might belong to FTP data connections.
 		 */
-		svc = __ip_vs_service_get(af, protocol, vaddr, FTPPORT);
+		svc = __ip_vs_service_find(af, protocol, vaddr, FTPPORT);
 	}
 
 	if (svc == NULL
@@ -484,10 +486,12 @@
 		/*
 		 * Check if the catch-all port (port zero) exists
 		 */
-		svc = __ip_vs_service_get(af, protocol, vaddr, 0);
+		svc = __ip_vs_service_find(af, protocol, vaddr, 0);
 	}
 
   out:
+	if (svc)
+		atomic_inc(&svc->usecnt);
 	read_unlock(&__ip_vs_svc_lock);
 
 	IP_VS_DBG_BUF(9, "lookup service: fwm %u %s %s:%u %s\n",
@@ -506,14 +510,19 @@
 	dest->svc = svc;
 }
 
-static inline void
+static void
 __ip_vs_unbind_svc(struct ip_vs_dest *dest)
 {
 	struct ip_vs_service *svc = dest->svc;
 
 	dest->svc = NULL;
-	if (atomic_dec_and_test(&svc->refcnt))
+	if (atomic_dec_and_test(&svc->refcnt)) {
+		IP_VS_DBG_BUF(3, "Removing service %u/%s:%u usecnt=%d\n",
+			      svc->fwmark,
+			      IP_VS_DBG_ADDR(svc->af, &svc->addr),
+			      ntohs(svc->port), atomic_read(&svc->usecnt));
 		kfree(svc);
+	}
 }
 
 
@@ -758,31 +767,18 @@
  *	Update a destination in the given service
  */
 static void
-__ip_vs_update_dest(struct ip_vs_service *svc,
-		    struct ip_vs_dest *dest, struct ip_vs_dest_user_kern *udest)
+__ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
+		    struct ip_vs_dest_user_kern *udest, int add)
 {
 	int conn_flags;
 
 	/* set the weight and the flags */
 	atomic_set(&dest->weight, udest->weight);
-	conn_flags = udest->conn_flags | IP_VS_CONN_F_INACTIVE;
-
-	/* check if local node and update the flags */
-#ifdef CONFIG_IP_VS_IPV6
-	if (svc->af == AF_INET6) {
-		if (__ip_vs_addr_is_local_v6(&udest->addr.in6)) {
-			conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK)
-				| IP_VS_CONN_F_LOCALNODE;
-		}
-	} else
-#endif
-		if (inet_addr_type(&init_net, udest->addr.ip) == RTN_LOCAL) {
-			conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK)
-				| IP_VS_CONN_F_LOCALNODE;
-		}
+	conn_flags = udest->conn_flags & IP_VS_CONN_F_DEST_MASK;
+	conn_flags |= IP_VS_CONN_F_INACTIVE;
 
 	/* set the IP_VS_CONN_F_NOOUTPUT flag if not masquerading/NAT */
-	if ((conn_flags & IP_VS_CONN_F_FWD_MASK) != 0) {
+	if ((conn_flags & IP_VS_CONN_F_FWD_MASK) != IP_VS_CONN_F_MASQ) {
 		conn_flags |= IP_VS_CONN_F_NOOUTPUT;
 	} else {
 		/*
@@ -813,6 +809,29 @@
 		dest->flags &= ~IP_VS_DEST_F_OVERLOAD;
 	dest->u_threshold = udest->u_threshold;
 	dest->l_threshold = udest->l_threshold;
+
+	spin_lock(&dest->dst_lock);
+	ip_vs_dst_reset(dest);
+	spin_unlock(&dest->dst_lock);
+
+	if (add)
+		ip_vs_new_estimator(&dest->stats);
+
+	write_lock_bh(&__ip_vs_svc_lock);
+
+	/* Wait until all other svc users go away */
+	IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 0);
+
+	if (add) {
+		list_add(&dest->n_list, &svc->destinations);
+		svc->num_dests++;
+	}
+
+	/* call the update_service, because server weight may be changed */
+	if (svc->scheduler->update_service)
+		svc->scheduler->update_service(svc);
+
+	write_unlock_bh(&__ip_vs_svc_lock);
 }
 
 
@@ -843,7 +862,7 @@
 			return -EINVAL;
 	}
 
-	dest = kzalloc(sizeof(struct ip_vs_dest), GFP_ATOMIC);
+	dest = kzalloc(sizeof(struct ip_vs_dest), GFP_KERNEL);
 	if (dest == NULL) {
 		pr_err("%s(): no memory.\n", __func__);
 		return -ENOMEM;
@@ -860,13 +879,12 @@
 	atomic_set(&dest->activeconns, 0);
 	atomic_set(&dest->inactconns, 0);
 	atomic_set(&dest->persistconns, 0);
-	atomic_set(&dest->refcnt, 0);
+	atomic_set(&dest->refcnt, 1);
 
 	INIT_LIST_HEAD(&dest->d_list);
 	spin_lock_init(&dest->dst_lock);
 	spin_lock_init(&dest->stats.lock);
-	__ip_vs_update_dest(svc, dest, udest);
-	ip_vs_new_estimator(&dest->stats);
+	__ip_vs_update_dest(svc, dest, udest, 1);
 
 	*dest_p = dest;
 
@@ -926,65 +944,22 @@
 			      IP_VS_DBG_ADDR(svc->af, &dest->vaddr),
 			      ntohs(dest->vport));
 
-		__ip_vs_update_dest(svc, dest, udest);
-
 		/*
 		 * Get the destination from the trash
 		 */
 		list_del(&dest->n_list);
 
-		ip_vs_new_estimator(&dest->stats);
-
-		write_lock_bh(&__ip_vs_svc_lock);
-
+		__ip_vs_update_dest(svc, dest, udest, 1);
+		ret = 0;
+	} else {
 		/*
-		 * Wait until all other svc users go away.
+		 * Allocate and initialize the dest structure
 		 */
-		IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 1);
-
-		list_add(&dest->n_list, &svc->destinations);
-		svc->num_dests++;
-
-		/* call the update_service function of its scheduler */
-		if (svc->scheduler->update_service)
-			svc->scheduler->update_service(svc);
-
-		write_unlock_bh(&__ip_vs_svc_lock);
-		return 0;
+		ret = ip_vs_new_dest(svc, udest, &dest);
 	}
-
-	/*
-	 * Allocate and initialize the dest structure
-	 */
-	ret = ip_vs_new_dest(svc, udest, &dest);
-	if (ret) {
-		return ret;
-	}
-
-	/*
-	 * Add the dest entry into the list
-	 */
-	atomic_inc(&dest->refcnt);
-
-	write_lock_bh(&__ip_vs_svc_lock);
-
-	/*
-	 * Wait until all other svc users go away.
-	 */
-	IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 1);
-
-	list_add(&dest->n_list, &svc->destinations);
-	svc->num_dests++;
-
-	/* call the update_service function of its scheduler */
-	if (svc->scheduler->update_service)
-		svc->scheduler->update_service(svc);
-
-	write_unlock_bh(&__ip_vs_svc_lock);
-
 	LeaveFunction(2);
 
-	return 0;
+	return ret;
 }
 
 
@@ -1023,19 +998,7 @@
 		return -ENOENT;
 	}
 
-	__ip_vs_update_dest(svc, dest, udest);
-
-	write_lock_bh(&__ip_vs_svc_lock);
-
-	/* Wait until all other svc users go away */
-	IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 1);
-
-	/* call the update_service, because server weight may be changed */
-	if (svc->scheduler->update_service)
-		svc->scheduler->update_service(svc);
-
-	write_unlock_bh(&__ip_vs_svc_lock);
-
+	__ip_vs_update_dest(svc, dest, udest, 0);
 	LeaveFunction(2);
 
 	return 0;
@@ -1062,6 +1025,10 @@
 	 *  the destination into the trash.
 	 */
 	if (atomic_dec_and_test(&dest->refcnt)) {
+		IP_VS_DBG_BUF(3, "Removing destination %u/%s:%u\n",
+			      dest->vfwmark,
+			      IP_VS_DBG_ADDR(dest->af, &dest->addr),
+			      ntohs(dest->port));
 		ip_vs_dst_reset(dest);
 		/* simply decrease svc->refcnt here, let the caller check
 		   and release the service if nobody refers to it.
@@ -1128,7 +1095,7 @@
 	/*
 	 *	Wait until all other svc users go away.
 	 */
-	IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 1);
+	IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 0);
 
 	/*
 	 *	Unlink dest from the service
@@ -1157,6 +1124,7 @@
 {
 	int ret = 0;
 	struct ip_vs_scheduler *sched = NULL;
+	struct ip_vs_pe *pe = NULL;
 	struct ip_vs_service *svc = NULL;
 
 	/* increase the module use count */
@@ -1167,7 +1135,17 @@
 	if (sched == NULL) {
 		pr_info("Scheduler module ip_vs_%s not found\n", u->sched_name);
 		ret = -ENOENT;
-		goto out_mod_dec;
+		goto out_err;
+	}
+
+	if (u->pe_name && *u->pe_name) {
+		pe = ip_vs_pe_get(u->pe_name);
+		if (pe == NULL) {
+			pr_info("persistence engine module ip_vs_pe_%s "
+				"not found\n", u->pe_name);
+			ret = -ENOENT;
+			goto out_err;
+		}
 	}
 
 #ifdef CONFIG_IP_VS_IPV6
@@ -1177,7 +1155,7 @@
 	}
 #endif
 
-	svc = kzalloc(sizeof(struct ip_vs_service), GFP_ATOMIC);
+	svc = kzalloc(sizeof(struct ip_vs_service), GFP_KERNEL);
 	if (svc == NULL) {
 		IP_VS_DBG(1, "%s(): no memory\n", __func__);
 		ret = -ENOMEM;
@@ -1185,7 +1163,7 @@
 	}
 
 	/* I'm the first user of the service */
-	atomic_set(&svc->usecnt, 1);
+	atomic_set(&svc->usecnt, 0);
 	atomic_set(&svc->refcnt, 0);
 
 	svc->af = u->af;
@@ -1207,6 +1185,10 @@
 		goto out_err;
 	sched = NULL;
 
+	/* Bind the ct retriever */
+	ip_vs_bind_pe(svc, pe);
+	pe = NULL;
+
 	/* Update the virtual service counters */
 	if (svc->port == FTPPORT)
 		atomic_inc(&ip_vs_ftpsvc_counter);
@@ -1227,10 +1209,9 @@
 	*svc_p = svc;
 	return 0;
 
-  out_err:
+ out_err:
 	if (svc != NULL) {
-		if (svc->scheduler)
-			ip_vs_unbind_scheduler(svc);
+		ip_vs_unbind_scheduler(svc);
 		if (svc->inc) {
 			local_bh_disable();
 			ip_vs_app_inc_put(svc->inc);
@@ -1239,8 +1220,8 @@
 		kfree(svc);
 	}
 	ip_vs_scheduler_put(sched);
+	ip_vs_pe_put(pe);
 
-  out_mod_dec:
 	/* decrease the module use count */
 	ip_vs_use_count_dec();
 
@@ -1255,6 +1236,7 @@
 ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
 {
 	struct ip_vs_scheduler *sched, *old_sched;
+	struct ip_vs_pe *pe = NULL, *old_pe = NULL;
 	int ret = 0;
 
 	/*
@@ -1267,6 +1249,17 @@
 	}
 	old_sched = sched;
 
+	if (u->pe_name && *u->pe_name) {
+		pe = ip_vs_pe_get(u->pe_name);
+		if (pe == NULL) {
+			pr_info("persistence engine module ip_vs_pe_%s "
+				"not found\n", u->pe_name);
+			ret = -ENOENT;
+			goto out;
+		}
+		old_pe = pe;
+	}
+
 #ifdef CONFIG_IP_VS_IPV6
 	if (u->af == AF_INET6 && (u->netmask < 1 || u->netmask > 128)) {
 		ret = -EINVAL;
@@ -1279,7 +1272,7 @@
 	/*
 	 * Wait until all other svc users go away.
 	 */
-	IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 1);
+	IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 0);
 
 	/*
 	 * Set the flags and timeout value
@@ -1318,15 +1311,17 @@
 		}
 	}
 
+	old_pe = svc->pe;
+	if (pe != old_pe) {
+		ip_vs_unbind_pe(svc);
+		ip_vs_bind_pe(svc, pe);
+	}
+
   out_unlock:
 	write_unlock_bh(&__ip_vs_svc_lock);
-#ifdef CONFIG_IP_VS_IPV6
   out:
-#endif
-
-	if (old_sched)
-		ip_vs_scheduler_put(old_sched);
-
+	ip_vs_scheduler_put(old_sched);
+	ip_vs_pe_put(old_pe);
 	return ret;
 }
 
@@ -1340,6 +1335,9 @@
 {
 	struct ip_vs_dest *dest, *nxt;
 	struct ip_vs_scheduler *old_sched;
+	struct ip_vs_pe *old_pe;
+
+	pr_info("%s: enter\n", __func__);
 
 	/* Count only IPv4 services for old get/setsockopt interface */
 	if (svc->af == AF_INET)
@@ -1350,8 +1348,12 @@
 	/* Unbind scheduler */
 	old_sched = svc->scheduler;
 	ip_vs_unbind_scheduler(svc);
-	if (old_sched)
-		ip_vs_scheduler_put(old_sched);
+	ip_vs_scheduler_put(old_sched);
+
+	/* Unbind persistence engine */
+	old_pe = svc->pe;
+	ip_vs_unbind_pe(svc);
+	ip_vs_pe_put(old_pe);
 
 	/* Unbind app inc */
 	if (svc->inc) {
@@ -1378,21 +1380,23 @@
 	/*
 	 *    Free the service if nobody refers to it
 	 */
-	if (atomic_read(&svc->refcnt) == 0)
+	if (atomic_read(&svc->refcnt) == 0) {
+		IP_VS_DBG_BUF(3, "Removing service %u/%s:%u usecnt=%d\n",
+			      svc->fwmark,
+			      IP_VS_DBG_ADDR(svc->af, &svc->addr),
+			      ntohs(svc->port), atomic_read(&svc->usecnt));
 		kfree(svc);
+	}
 
 	/* decrease the module use count */
 	ip_vs_use_count_dec();
 }
 
 /*
- *	Delete a service from the service list
+ * Unlink a service from list and try to delete it if its refcnt reached 0
  */
-static int ip_vs_del_service(struct ip_vs_service *svc)
+static void ip_vs_unlink_service(struct ip_vs_service *svc)
 {
-	if (svc == NULL)
-		return -EEXIST;
-
 	/*
 	 * Unhash it from the service table
 	 */
@@ -1403,11 +1407,21 @@
 	/*
 	 * Wait until all the svc users go away.
 	 */
-	IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 1);
+	IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 0);
 
 	__ip_vs_del_service(svc);
 
 	write_unlock_bh(&__ip_vs_svc_lock);
+}
+
+/*
+ *	Delete a service from the service list
+ */
+static int ip_vs_del_service(struct ip_vs_service *svc)
+{
+	if (svc == NULL)
+		return -EEXIST;
+	ip_vs_unlink_service(svc);
 
 	return 0;
 }
@@ -1426,14 +1440,7 @@
 	 */
 	for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
 		list_for_each_entry_safe(svc, nxt, &ip_vs_svc_table[idx], s_list) {
-			write_lock_bh(&__ip_vs_svc_lock);
-			ip_vs_svc_unhash(svc);
-			/*
-			 * Wait until all the svc users go away.
-			 */
-			IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 0);
-			__ip_vs_del_service(svc);
-			write_unlock_bh(&__ip_vs_svc_lock);
+			ip_vs_unlink_service(svc);
 		}
 	}
 
@@ -1443,14 +1450,7 @@
 	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) {
-			write_lock_bh(&__ip_vs_svc_lock);
-			ip_vs_svc_unhash(svc);
-			/*
-			 * Wait until all the svc users go away.
-			 */
-			IP_VS_WAIT_WHILE(atomic_read(&svc->usecnt) > 0);
-			__ip_vs_del_service(svc);
-			write_unlock_bh(&__ip_vs_svc_lock);
+			ip_vs_unlink_service(svc);
 		}
 	}
 
@@ -1579,6 +1579,15 @@
 		.mode		= 0644,
 		.proc_handler	= proc_do_defense_mode,
 	},
+#ifdef CONFIG_IP_VS_NFCT
+	{
+		.procname	= "conntrack",
+		.data		= &sysctl_ip_vs_conntrack,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+#endif
 	{
 		.procname	= "secure_tcp",
 		.data		= &sysctl_ip_vs_secure_tcp,
@@ -1586,6 +1595,13 @@
 		.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,
+	},
 #if 0
 	{
 		.procname	= "timeout_established",
@@ -2041,6 +2057,8 @@
 static void ip_vs_copy_usvc_compat(struct ip_vs_service_user_kern *usvc,
 				  struct ip_vs_service_user *usvc_compat)
 {
+	memset(usvc, 0, sizeof(*usvc));
+
 	usvc->af		= AF_INET;
 	usvc->protocol		= usvc_compat->protocol;
 	usvc->addr.ip		= usvc_compat->addr;
@@ -2058,6 +2076,8 @@
 static void ip_vs_copy_udest_compat(struct ip_vs_dest_user_kern *udest,
 				   struct ip_vs_dest_user *udest_compat)
 {
+	memset(udest, 0, sizeof(*udest));
+
 	udest->addr.ip		= udest_compat->addr;
 	udest->port		= udest_compat->port;
 	udest->conn_flags	= udest_compat->conn_flags;
@@ -2147,10 +2167,10 @@
 
 	/* Lookup the exact service by <protocol, addr, port> or fwmark */
 	if (usvc.fwmark == 0)
-		svc = __ip_vs_service_get(usvc.af, usvc.protocol,
-					  &usvc.addr, usvc.port);
+		svc = __ip_vs_service_find(usvc.af, usvc.protocol,
+					   &usvc.addr, usvc.port);
 	else
-		svc = __ip_vs_svc_fwm_get(usvc.af, usvc.fwmark);
+		svc = __ip_vs_svc_fwm_find(usvc.af, usvc.fwmark);
 
 	if (cmd != IP_VS_SO_SET_ADD
 	    && (svc == NULL || svc->protocol != usvc.protocol)) {
@@ -2189,9 +2209,6 @@
 		ret = -EINVAL;
 	}
 
-	if (svc)
-		ip_vs_service_put(svc);
-
   out_unlock:
 	mutex_unlock(&__ip_vs_mutex);
   out_dec:
@@ -2284,10 +2301,10 @@
 	int ret = 0;
 
 	if (get->fwmark)
-		svc = __ip_vs_svc_fwm_get(AF_INET, get->fwmark);
+		svc = __ip_vs_svc_fwm_find(AF_INET, get->fwmark);
 	else
-		svc = __ip_vs_service_get(AF_INET, get->protocol, &addr,
-					  get->port);
+		svc = __ip_vs_service_find(AF_INET, get->protocol, &addr,
+					   get->port);
 
 	if (svc) {
 		int count = 0;
@@ -2315,7 +2332,6 @@
 			}
 			count++;
 		}
-		ip_vs_service_put(svc);
 	} else
 		ret = -ESRCH;
 	return ret;
@@ -2436,15 +2452,14 @@
 		entry = (struct ip_vs_service_entry *)arg;
 		addr.ip = entry->addr;
 		if (entry->fwmark)
-			svc = __ip_vs_svc_fwm_get(AF_INET, entry->fwmark);
+			svc = __ip_vs_svc_fwm_find(AF_INET, entry->fwmark);
 		else
-			svc = __ip_vs_service_get(AF_INET, entry->protocol,
-						  &addr, entry->port);
+			svc = __ip_vs_service_find(AF_INET, entry->protocol,
+						   &addr, entry->port);
 		if (svc) {
 			ip_vs_copy_service(entry, svc);
 			if (copy_to_user(user, entry, sizeof(*entry)) != 0)
 				ret = -EFAULT;
-			ip_vs_service_put(svc);
 		} else
 			ret = -ESRCH;
 	}
@@ -2559,6 +2574,8 @@
 	[IPVS_SVC_ATTR_FWMARK]		= { .type = NLA_U32 },
 	[IPVS_SVC_ATTR_SCHED_NAME]	= { .type = NLA_NUL_STRING,
 					    .len = IP_VS_SCHEDNAME_MAXLEN },
+	[IPVS_SVC_ATTR_PE_NAME]		= { .type = NLA_NUL_STRING,
+					    .len = IP_VS_PENAME_MAXLEN },
 	[IPVS_SVC_ATTR_FLAGS]		= { .type = NLA_BINARY,
 					    .len = sizeof(struct ip_vs_flags) },
 	[IPVS_SVC_ATTR_TIMEOUT]		= { .type = NLA_U32 },
@@ -2635,6 +2652,8 @@
 	}
 
 	NLA_PUT_STRING(skb, IPVS_SVC_ATTR_SCHED_NAME, svc->scheduler->name);
+	if (svc->pe)
+		NLA_PUT_STRING(skb, IPVS_SVC_ATTR_PE_NAME, svc->pe->name);
 	NLA_PUT(skb, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags);
 	NLA_PUT_U32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ);
 	NLA_PUT_U32(skb, IPVS_SVC_ATTR_NETMASK, svc->netmask);
@@ -2711,10 +2730,12 @@
 }
 
 static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc,
-				    struct nlattr *nla, int full_entry)
+				    struct nlattr *nla, int full_entry,
+				    struct ip_vs_service **ret_svc)
 {
 	struct nlattr *attrs[IPVS_SVC_ATTR_MAX + 1];
 	struct nlattr *nla_af, *nla_port, *nla_fwmark, *nla_protocol, *nla_addr;
+	struct ip_vs_service *svc;
 
 	/* Parse mandatory identifying service fields first */
 	if (nla == NULL ||
@@ -2750,14 +2771,21 @@
 		usvc->fwmark = 0;
 	}
 
+	if (usvc->fwmark)
+		svc = __ip_vs_svc_fwm_find(usvc->af, usvc->fwmark);
+	else
+		svc = __ip_vs_service_find(usvc->af, usvc->protocol,
+					   &usvc->addr, usvc->port);
+	*ret_svc = svc;
+
 	/* If a full entry was requested, check for the additional fields */
 	if (full_entry) {
-		struct nlattr *nla_sched, *nla_flags, *nla_timeout,
+		struct nlattr *nla_sched, *nla_flags, *nla_pe, *nla_timeout,
 			      *nla_netmask;
 		struct ip_vs_flags flags;
-		struct ip_vs_service *svc;
 
 		nla_sched = attrs[IPVS_SVC_ATTR_SCHED_NAME];
+		nla_pe = attrs[IPVS_SVC_ATTR_PE_NAME];
 		nla_flags = attrs[IPVS_SVC_ATTR_FLAGS];
 		nla_timeout = attrs[IPVS_SVC_ATTR_TIMEOUT];
 		nla_netmask = attrs[IPVS_SVC_ATTR_NETMASK];
@@ -2768,21 +2796,14 @@
 		nla_memcpy(&flags, nla_flags, sizeof(flags));
 
 		/* prefill flags from service if it already exists */
-		if (usvc->fwmark)
-			svc = __ip_vs_svc_fwm_get(usvc->af, usvc->fwmark);
-		else
-			svc = __ip_vs_service_get(usvc->af, usvc->protocol,
-						  &usvc->addr, usvc->port);
-		if (svc) {
+		if (svc)
 			usvc->flags = svc->flags;
-			ip_vs_service_put(svc);
-		} else
-			usvc->flags = 0;
 
 		/* set new flags from userland */
 		usvc->flags = (usvc->flags & ~flags.mask) |
 			      (flags.flags & flags.mask);
 		usvc->sched_name = nla_data(nla_sched);
+		usvc->pe_name = nla_pe ? nla_data(nla_pe) : NULL;
 		usvc->timeout = nla_get_u32(nla_timeout);
 		usvc->netmask = nla_get_u32(nla_netmask);
 	}
@@ -2793,17 +2814,11 @@
 static struct ip_vs_service *ip_vs_genl_find_service(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);
-	if (ret)
-		return ERR_PTR(ret);
-
-	if (usvc.fwmark)
-		return __ip_vs_svc_fwm_get(usvc.af, usvc.fwmark);
-	else
-		return __ip_vs_service_get(usvc.af, usvc.protocol,
-					   &usvc.addr, usvc.port);
+	ret = ip_vs_genl_parse_service(&usvc, nla, 0, &svc);
+	return ret ? ERR_PTR(ret) : svc;
 }
 
 static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)
@@ -2894,7 +2909,6 @@
 
 nla_put_failure:
 	cb->args[0] = idx;
-	ip_vs_service_put(svc);
 
 out_err:
 	mutex_unlock(&__ip_vs_mutex);
@@ -3107,17 +3121,10 @@
 
 	ret = ip_vs_genl_parse_service(&usvc,
 				       info->attrs[IPVS_CMD_ATTR_SERVICE],
-				       need_full_svc);
+				       need_full_svc, &svc);
 	if (ret)
 		goto out;
 
-	/* Lookup the exact service by <protocol, addr, port> or fwmark */
-	if (usvc.fwmark == 0)
-		svc = __ip_vs_service_get(usvc.af, usvc.protocol,
-					  &usvc.addr, usvc.port);
-	else
-		svc = __ip_vs_svc_fwm_get(usvc.af, usvc.fwmark);
-
 	/* Unless we're adding a new service, the service must already exist */
 	if ((cmd != IPVS_CMD_NEW_SERVICE) && (svc == NULL)) {
 		ret = -ESRCH;
@@ -3151,6 +3158,7 @@
 		break;
 	case IPVS_CMD_DEL_SERVICE:
 		ret = ip_vs_del_service(svc);
+		/* do not use svc, it can be freed */
 		break;
 	case IPVS_CMD_NEW_DEST:
 		ret = ip_vs_add_dest(svc, &udest);
@@ -3169,8 +3177,6 @@
 	}
 
 out:
-	if (svc)
-		ip_vs_service_put(svc);
 	mutex_unlock(&__ip_vs_mutex);
 
 	return ret;
@@ -3216,7 +3222,6 @@
 			goto out_err;
 		} else if (svc) {
 			ret = ip_vs_genl_fill_service(msg, svc);
-			ip_vs_service_put(svc);
 			if (ret)
 				goto nla_put_failure;
 		} else {
@@ -3385,6 +3390,16 @@
 
 	EnterFunction(2);
 
+	/* Initialize ip_vs_svc_table, ip_vs_svc_fwm_table, ip_vs_rtable */
+	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]);
+	}
+	smp_wmb();
+
 	ret = nf_register_sockopt(&ip_vs_sockopts);
 	if (ret) {
 		pr_err("cannot register sockopt.\n");
@@ -3403,15 +3418,6 @@
 
 	sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars);
 
-	/* Initialize ip_vs_svc_table, ip_vs_svc_fwm_table, ip_vs_rtable */
-	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]);
-	}
-
 	ip_vs_new_estimator(&ip_vs_stats);
 
 	/* Hook the defense timer */
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index 7e9af5b..7545500 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -20,17 +20,6 @@
  *
  * Author:	Wouter Gadeyne
  *
- *
- * Code for ip_vs_expect_related and ip_vs_expect_callback is taken from
- * http://www.ssi.bg/~ja/nfct/:
- *
- * ip_vs_nfct.c:	Netfilter connection tracking support for IPVS
- *
- * Portions Copyright (C) 2001-2002
- * Antefacto Ltd, 181 Parnell St, Dublin 1, Ireland.
- *
- * Portions Copyright (C) 2003-2008
- * Julian Anastasov
  */
 
 #define KMSG_COMPONENT "IPVS"
@@ -58,16 +47,6 @@
 #define SERVER_STRING "227 Entering Passive Mode ("
 #define CLIENT_STRING "PORT "
 
-#define FMT_TUPLE	"%pI4:%u->%pI4:%u/%u"
-#define ARG_TUPLE(T)	&(T)->src.u3.ip, ntohs((T)->src.u.all), \
-			&(T)->dst.u3.ip, ntohs((T)->dst.u.all), \
-			(T)->dst.protonum
-
-#define FMT_CONN	"%pI4:%u->%pI4:%u->%pI4:%u/%u:%u"
-#define ARG_CONN(C)	&((C)->caddr.ip), ntohs((C)->cport), \
-			&((C)->vaddr.ip), ntohs((C)->vport), \
-			&((C)->daddr.ip), ntohs((C)->dport), \
-			(C)->protocol, (C)->state
 
 /*
  * List of ports (up to IP_VS_APP_MAX_PORTS) to be handled by helper
@@ -85,6 +64,8 @@
 static int
 ip_vs_ftp_init_conn(struct ip_vs_app *app, struct ip_vs_conn *cp)
 {
+	/* We use connection tracking for the command connection */
+	cp->flags |= IP_VS_CONN_F_NFCT;
 	return 0;
 }
 
@@ -149,120 +130,6 @@
 }
 
 /*
- * Called from init_conntrack() as expectfn handler.
- */
-static void
-ip_vs_expect_callback(struct nf_conn *ct,
-		      struct nf_conntrack_expect *exp)
-{
-	struct nf_conntrack_tuple *orig, new_reply;
-	struct ip_vs_conn *cp;
-
-	if (exp->tuple.src.l3num != PF_INET)
-		return;
-
-	/*
-	 * We assume that no NF locks are held before this callback.
-	 * ip_vs_conn_out_get and ip_vs_conn_in_get should match their
-	 * expectations even if they use wildcard values, now we provide the
-	 * actual values from the newly created original conntrack direction.
-	 * The conntrack is confirmed when packet reaches IPVS hooks.
-	 */
-
-	/* RS->CLIENT */
-	orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
-	cp = ip_vs_conn_out_get(exp->tuple.src.l3num, orig->dst.protonum,
-				&orig->src.u3, orig->src.u.tcp.port,
-				&orig->dst.u3, orig->dst.u.tcp.port);
-	if (cp) {
-		/* Change reply CLIENT->RS to CLIENT->VS */
-		new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-		IP_VS_DBG(7, "%s(): ct=%p, status=0x%lX, tuples=" FMT_TUPLE ", "
-			  FMT_TUPLE ", found inout cp=" FMT_CONN "\n",
-			  __func__, ct, ct->status,
-			  ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
-			  ARG_CONN(cp));
-		new_reply.dst.u3 = cp->vaddr;
-		new_reply.dst.u.tcp.port = cp->vport;
-		IP_VS_DBG(7, "%s(): ct=%p, new tuples=" FMT_TUPLE ", " FMT_TUPLE
-			  ", inout cp=" FMT_CONN "\n",
-			  __func__, ct,
-			  ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
-			  ARG_CONN(cp));
-		goto alter;
-	}
-
-	/* CLIENT->VS */
-	cp = ip_vs_conn_in_get(exp->tuple.src.l3num, orig->dst.protonum,
-			       &orig->src.u3, orig->src.u.tcp.port,
-			       &orig->dst.u3, orig->dst.u.tcp.port);
-	if (cp) {
-		/* Change reply VS->CLIENT to RS->CLIENT */
-		new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-		IP_VS_DBG(7, "%s(): ct=%p, status=0x%lX, tuples=" FMT_TUPLE ", "
-			  FMT_TUPLE ", found outin cp=" FMT_CONN "\n",
-			  __func__, ct, ct->status,
-			  ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
-			  ARG_CONN(cp));
-		new_reply.src.u3 = cp->daddr;
-		new_reply.src.u.tcp.port = cp->dport;
-		IP_VS_DBG(7, "%s(): ct=%p, new tuples=" FMT_TUPLE ", "
-			  FMT_TUPLE ", outin cp=" FMT_CONN "\n",
-			  __func__, ct,
-			  ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
-			  ARG_CONN(cp));
-		goto alter;
-	}
-
-	IP_VS_DBG(7, "%s(): ct=%p, status=0x%lX, tuple=" FMT_TUPLE
-		  " - unknown expect\n",
-		  __func__, ct, ct->status, ARG_TUPLE(orig));
-	return;
-
-alter:
-	/* Never alter conntrack for non-NAT conns */
-	if (IP_VS_FWD_METHOD(cp) == IP_VS_CONN_F_MASQ)
-		nf_conntrack_alter_reply(ct, &new_reply);
-	ip_vs_conn_put(cp);
-	return;
-}
-
-/*
- * Create NF conntrack expectation with wildcard (optional) source port.
- * Then the default callback function will alter the reply and will confirm
- * the conntrack entry when the first packet comes.
- */
-static void
-ip_vs_expect_related(struct sk_buff *skb, struct nf_conn *ct,
-		     struct ip_vs_conn *cp, u_int8_t proto,
-		     const __be16 *port, int from_rs)
-{
-	struct nf_conntrack_expect *exp;
-
-	BUG_ON(!ct || ct == &nf_conntrack_untracked);
-
-	exp = nf_ct_expect_alloc(ct);
-	if (!exp)
-		return;
-
-	if (from_rs)
-		nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
-				  nf_ct_l3num(ct), &cp->daddr, &cp->caddr,
-				  proto, port, &cp->cport);
-	else
-		nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
-				  nf_ct_l3num(ct), &cp->caddr, &cp->vaddr,
-				  proto, port, &cp->vport);
-
-	exp->expectfn = ip_vs_expect_callback;
-
-	IP_VS_DBG(7, "%s(): ct=%p, expect tuple=" FMT_TUPLE "\n",
-		  __func__, ct, ARG_TUPLE(&exp->tuple));
-	nf_ct_expect_related(exp);
-	nf_ct_expect_put(exp);
-}
-
-/*
  * Look at outgoing ftp packets to catch the response to a PASV command
  * from the server (inside-to-outside).
  * When we see one, we build a connection entry with the client address,
@@ -328,14 +195,19 @@
 		/*
 		 * Now update or create an connection entry for it
 		 */
-		n_cp = ip_vs_conn_out_get(AF_INET, iph->protocol, &from, port,
-					  &cp->caddr, 0);
+		{
+			struct ip_vs_conn_param p;
+			ip_vs_conn_fill_param(AF_INET, iph->protocol,
+					      &from, port, &cp->caddr, 0, &p);
+			n_cp = ip_vs_conn_out_get(&p);
+		}
 		if (!n_cp) {
-			n_cp = ip_vs_conn_new(AF_INET, IPPROTO_TCP,
-					      &cp->caddr, 0,
-					      &cp->vaddr, port,
-					      &from, port,
-					      IP_VS_CONN_F_NO_CPORT,
+			struct ip_vs_conn_param p;
+			ip_vs_conn_fill_param(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);
 			if (!n_cp)
 				return 0;
@@ -370,9 +242,14 @@
 			ret = nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
 						       start-data, end-start,
 						       buf, buf_len);
-			if (ret)
-				ip_vs_expect_related(skb, ct, n_cp,
-						     IPPROTO_TCP, NULL, 0);
+			if (ret) {
+				ip_vs_nfct_expect_related(skb, ct, n_cp,
+							  IPPROTO_TCP, 0, 0);
+				if (skb->ip_summed == CHECKSUM_COMPLETE)
+					skb->ip_summed = CHECKSUM_UNNECESSARY;
+				/* csum is updated */
+				ret = 1;
+			}
 		}
 
 		/*
@@ -479,21 +356,22 @@
 		  ip_vs_proto_name(iph->protocol),
 		  &to.ip, ntohs(port), &cp->vaddr.ip, 0);
 
-	n_cp = ip_vs_conn_in_get(AF_INET, iph->protocol,
-				 &to, port,
-				 &cp->vaddr, htons(ntohs(cp->vport)-1));
-	if (!n_cp) {
-		n_cp = ip_vs_conn_new(AF_INET, IPPROTO_TCP,
-				      &to, port,
+	{
+		struct ip_vs_conn_param p;
+		ip_vs_conn_fill_param(AF_INET, iph->protocol, &to, port,
 				      &cp->vaddr, htons(ntohs(cp->vport)-1),
-				      &cp->daddr, htons(ntohs(cp->dport)-1),
-				      0,
-				      cp->dest);
-		if (!n_cp)
-			return 0;
+				      &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);
+			if (!n_cp)
+				return 0;
 
-		/* add its controller */
-		ip_vs_control_add(n_cp, cp);
+			/* add its controller */
+			ip_vs_control_add(n_cp, cp);
+		}
 	}
 
 	/*
diff --git a/net/netfilter/ipvs/ip_vs_nfct.c b/net/netfilter/ipvs/ip_vs_nfct.c
new file mode 100644
index 0000000..4680647
--- /dev/null
+++ b/net/netfilter/ipvs/ip_vs_nfct.c
@@ -0,0 +1,292 @@
+/*
+ * ip_vs_nfct.c:	Netfilter connection tracking support for IPVS
+ *
+ * Portions Copyright (C) 2001-2002
+ * Antefacto Ltd, 181 Parnell St, Dublin 1, Ireland.
+ *
+ * Portions Copyright (C) 2003-2010
+ * Julian Anastasov
+ *
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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:
+ * Ben North <ben@redfrontdoor.org>
+ * Julian Anastasov <ja@ssi.bg>		Reorganize and sync with latest kernels
+ * Hannes Eder <heder@google.com>	Extend NFCT support for FTP, ipvs match
+ *
+ *
+ * Current status:
+ *
+ * - provide conntrack confirmation for new and related connections, by
+ * this way we can see their proper conntrack state in all hooks
+ * - support for all forwarding methods, not only NAT
+ * - FTP support (NAT), ability to support other NAT apps with expectations
+ * - to correctly create expectations for related NAT connections the proper
+ * NF conntrack support must be already installed, eg. ip_vs_ftp requires
+ * nf_conntrack_ftp ... iptables_nat for the same ports (but no iptables
+ * NAT rules are needed)
+ * - alter reply for NAT when forwarding packet in original direction:
+ * conntrack from client in NEW or RELATED (Passive FTP DATA) state or
+ * when RELATED conntrack is created from real server (Active FTP DATA)
+ * - if iptables_nat is not loaded the Passive FTP will not work (the
+ * PASV response can not be NAT-ed) but Active FTP should work
+ *
+ */
+
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/compiler.h>
+#include <linux/vmalloc.h>
+#include <linux/skbuff.h>
+#include <net/ip.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <net/ip_vs.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_zones.h>
+
+
+#define FMT_TUPLE	"%pI4:%u->%pI4:%u/%u"
+#define ARG_TUPLE(T)	&(T)->src.u3.ip, ntohs((T)->src.u.all), \
+			&(T)->dst.u3.ip, ntohs((T)->dst.u.all), \
+			(T)->dst.protonum
+
+#define FMT_CONN	"%pI4:%u->%pI4:%u->%pI4:%u/%u:%u"
+#define ARG_CONN(C)	&((C)->caddr.ip), ntohs((C)->cport), \
+			&((C)->vaddr.ip), ntohs((C)->vport), \
+			&((C)->daddr.ip), ntohs((C)->dport), \
+			(C)->protocol, (C)->state
+
+void
+ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
+{
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+	struct nf_conntrack_tuple new_tuple;
+
+	if (ct == NULL || nf_ct_is_confirmed(ct) || nf_ct_is_untracked(ct) ||
+	    nf_ct_is_dying(ct))
+		return;
+
+	/* Never alter conntrack for non-NAT conns */
+	if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
+		return;
+
+	/* Alter reply only in original direction */
+	if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
+		return;
+
+	/*
+	 * The connection is not yet in the hashtable, so we update it.
+	 * CIP->VIP will remain the same, so leave the tuple in
+	 * IP_CT_DIR_ORIGINAL untouched.  When the reply comes back from the
+	 * real-server we will see RIP->DIP.
+	 */
+	new_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+	/*
+	 * This will also take care of UDP and other protocols.
+	 */
+	if (outin) {
+		new_tuple.src.u3 = cp->daddr;
+		if (new_tuple.dst.protonum != IPPROTO_ICMP &&
+		    new_tuple.dst.protonum != IPPROTO_ICMPV6)
+			new_tuple.src.u.tcp.port = cp->dport;
+	} else {
+		new_tuple.dst.u3 = cp->vaddr;
+		if (new_tuple.dst.protonum != IPPROTO_ICMP &&
+		    new_tuple.dst.protonum != IPPROTO_ICMPV6)
+			new_tuple.dst.u.tcp.port = cp->vport;
+	}
+	IP_VS_DBG(7, "%s: Updating conntrack ct=%p, status=0x%lX, "
+		  "ctinfo=%d, old reply=" FMT_TUPLE
+		  ", new reply=" FMT_TUPLE ", cp=" FMT_CONN "\n",
+		  __func__, ct, ct->status, ctinfo,
+		  ARG_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple),
+		  ARG_TUPLE(&new_tuple), ARG_CONN(cp));
+	nf_conntrack_alter_reply(ct, &new_tuple);
+}
+
+int ip_vs_confirm_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp)
+{
+	return nf_conntrack_confirm(skb);
+}
+
+/*
+ * Called from init_conntrack() as expectfn handler.
+ */
+static void ip_vs_nfct_expect_callback(struct nf_conn *ct,
+	struct nf_conntrack_expect *exp)
+{
+	struct nf_conntrack_tuple *orig, new_reply;
+	struct ip_vs_conn *cp;
+	struct ip_vs_conn_param p;
+
+	if (exp->tuple.src.l3num != PF_INET)
+		return;
+
+	/*
+	 * We assume that no NF locks are held before this callback.
+	 * ip_vs_conn_out_get and ip_vs_conn_in_get should match their
+	 * expectations even if they use wildcard values, now we provide the
+	 * actual values from the newly created original conntrack direction.
+	 * The conntrack is confirmed when packet reaches IPVS hooks.
+	 */
+
+	/* RS->CLIENT */
+	orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+	ip_vs_conn_fill_param(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);
+	if (cp) {
+		/* Change reply CLIENT->RS to CLIENT->VS */
+		new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+		IP_VS_DBG(7, "%s: ct=%p, status=0x%lX, tuples=" FMT_TUPLE ", "
+			  FMT_TUPLE ", found inout cp=" FMT_CONN "\n",
+			  __func__, ct, ct->status,
+			  ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
+			  ARG_CONN(cp));
+		new_reply.dst.u3 = cp->vaddr;
+		new_reply.dst.u.tcp.port = cp->vport;
+		IP_VS_DBG(7, "%s: ct=%p, new tuples=" FMT_TUPLE ", " FMT_TUPLE
+			  ", inout cp=" FMT_CONN "\n",
+			  __func__, ct,
+			  ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
+			  ARG_CONN(cp));
+		goto alter;
+	}
+
+	/* CLIENT->VS */
+	cp = ip_vs_conn_in_get(&p);
+	if (cp) {
+		/* Change reply VS->CLIENT to RS->CLIENT */
+		new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+		IP_VS_DBG(7, "%s: ct=%p, status=0x%lX, tuples=" FMT_TUPLE ", "
+			  FMT_TUPLE ", found outin cp=" FMT_CONN "\n",
+			  __func__, ct, ct->status,
+			  ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
+			  ARG_CONN(cp));
+		new_reply.src.u3 = cp->daddr;
+		new_reply.src.u.tcp.port = cp->dport;
+		IP_VS_DBG(7, "%s: ct=%p, new tuples=" FMT_TUPLE ", "
+			  FMT_TUPLE ", outin cp=" FMT_CONN "\n",
+			  __func__, ct,
+			  ARG_TUPLE(orig), ARG_TUPLE(&new_reply),
+			  ARG_CONN(cp));
+		goto alter;
+	}
+
+	IP_VS_DBG(7, "%s: ct=%p, status=0x%lX, tuple=" FMT_TUPLE
+		  " - unknown expect\n",
+		  __func__, ct, ct->status, ARG_TUPLE(orig));
+	return;
+
+alter:
+	/* Never alter conntrack for non-NAT conns */
+	if (IP_VS_FWD_METHOD(cp) == IP_VS_CONN_F_MASQ)
+		nf_conntrack_alter_reply(ct, &new_reply);
+	ip_vs_conn_put(cp);
+	return;
+}
+
+/*
+ * Create NF conntrack expectation with wildcard (optional) source port.
+ * Then the default callback function will alter the reply and will confirm
+ * the conntrack entry when the first packet comes.
+ * Use port 0 to expect connection from any port.
+ */
+void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct,
+			       struct ip_vs_conn *cp, u_int8_t proto,
+			       const __be16 port, int from_rs)
+{
+	struct nf_conntrack_expect *exp;
+
+	if (ct == NULL || nf_ct_is_untracked(ct))
+		return;
+
+	exp = nf_ct_expect_alloc(ct);
+	if (!exp)
+		return;
+
+	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+			from_rs ? &cp->daddr : &cp->caddr,
+			from_rs ? &cp->caddr : &cp->vaddr,
+			proto, port ? &port : NULL,
+			from_rs ? &cp->cport : &cp->vport);
+
+	exp->expectfn = ip_vs_nfct_expect_callback;
+
+	IP_VS_DBG(7, "%s: ct=%p, expect tuple=" FMT_TUPLE "\n",
+		__func__, ct, ARG_TUPLE(&exp->tuple));
+	nf_ct_expect_related(exp);
+	nf_ct_expect_put(exp);
+}
+EXPORT_SYMBOL(ip_vs_nfct_expect_related);
+
+/*
+ * Our connection was terminated, try to drop the conntrack immediately
+ */
+void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp)
+{
+	struct nf_conntrack_tuple_hash *h;
+	struct nf_conn *ct;
+	struct nf_conntrack_tuple tuple;
+
+	if (!cp->cport)
+		return;
+
+	tuple = (struct nf_conntrack_tuple) {
+		.dst = { .protonum = cp->protocol, .dir = IP_CT_DIR_ORIGINAL } };
+	tuple.src.u3 = cp->caddr;
+	tuple.src.u.all = cp->cport;
+	tuple.src.l3num = cp->af;
+	tuple.dst.u3 = cp->vaddr;
+	tuple.dst.u.all = cp->vport;
+
+	IP_VS_DBG(7, "%s: dropping conntrack with tuple=" FMT_TUPLE
+		" for conn " FMT_CONN "\n",
+		__func__, ARG_TUPLE(&tuple), ARG_CONN(cp));
+
+	h = nf_conntrack_find_get(&init_net, NF_CT_DEFAULT_ZONE, &tuple);
+	if (h) {
+		ct = nf_ct_tuplehash_to_ctrack(h);
+		/* Show what happens instead of calling nf_ct_kill() */
+		if (del_timer(&ct->timeout)) {
+			IP_VS_DBG(7, "%s: ct=%p, deleted conntrack timer for tuple="
+				FMT_TUPLE "\n",
+				__func__, ct, ARG_TUPLE(&tuple));
+			if (ct->timeout.function)
+				ct->timeout.function(ct->timeout.data);
+		} else {
+			IP_VS_DBG(7, "%s: ct=%p, no conntrack timer for tuple="
+				FMT_TUPLE "\n",
+				__func__, ct, ARG_TUPLE(&tuple));
+		}
+		nf_ct_put(ct);
+	} else {
+		IP_VS_DBG(7, "%s: no conntrack for tuple=" FMT_TUPLE "\n",
+			__func__, ARG_TUPLE(&tuple));
+	}
+}
+
diff --git a/net/netfilter/ipvs/ip_vs_pe.c b/net/netfilter/ipvs/ip_vs_pe.c
new file mode 100644
index 0000000..3414af7
--- /dev/null
+++ b/net/netfilter/ipvs/ip_vs_pe.c
@@ -0,0 +1,147 @@
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <asm/string.h>
+#include <linux/kmod.h>
+#include <linux/sysctl.h>
+
+#include <net/ip_vs.h>
+
+/* IPVS pe list */
+static LIST_HEAD(ip_vs_pe);
+
+/* lock for service table */
+static DEFINE_SPINLOCK(ip_vs_pe_lock);
+
+/* Bind a service with a pe */
+void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe)
+{
+	svc->pe = pe;
+}
+
+/* Unbind a service from its pe */
+void ip_vs_unbind_pe(struct ip_vs_service *svc)
+{
+	svc->pe = NULL;
+}
+
+/* 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 *pe;
+
+	IP_VS_DBG(2, "%s(): pe_name \"%s\"\n", __func__,
+		  pe_name);
+
+	spin_lock_bh(&ip_vs_pe_lock);
+
+	list_for_each_entry(pe, &ip_vs_pe, n_list) {
+		/* Test and get the modules atomically */
+		if (pe->module &&
+		    !try_module_get(pe->module)) {
+			/* This pe is just deleted */
+			continue;
+		}
+		if (strcmp(pe_name, pe->name)==0) {
+			/* HIT */
+			spin_unlock_bh(&ip_vs_pe_lock);
+			return pe;
+		}
+		if (pe->module)
+			module_put(pe->module);
+	}
+
+	spin_unlock_bh(&ip_vs_pe_lock);
+	return NULL;
+}
+
+/* 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 *pe;
+
+	/* Search for the pe by 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);
+	}
+
+	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)
+{
+	struct ip_vs_pe *tmp;
+
+	/* increase the module use count */
+	ip_vs_use_count_inc();
+
+	spin_lock_bh(&ip_vs_pe_lock);
+
+	if (!list_empty(&pe->n_list)) {
+		spin_unlock_bh(&ip_vs_pe_lock);
+		ip_vs_use_count_dec();
+		pr_err("%s(): [%s] pe already linked\n",
+		       __func__, pe->name);
+		return -EINVAL;
+	}
+
+	/* Make sure that the pe with this name doesn't exist
+	 * in the pe list.
+	 */
+	list_for_each_entry(tmp, &ip_vs_pe, n_list) {
+		if (strcmp(tmp->name, pe->name) == 0) {
+			spin_unlock_bh(&ip_vs_pe_lock);
+			ip_vs_use_count_dec();
+			pr_err("%s(): [%s] pe already existed "
+			       "in the system\n", __func__, pe->name);
+			return -EINVAL;
+		}
+	}
+	/* Add it into the d-linked pe list */
+	list_add(&pe->n_list, &ip_vs_pe);
+	spin_unlock_bh(&ip_vs_pe_lock);
+
+	pr_info("[%s] pe registered.\n", pe->name);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(register_ip_vs_pe);
+
+/* Unregister a pe from the pe list */
+int unregister_ip_vs_pe(struct ip_vs_pe *pe)
+{
+	spin_lock_bh(&ip_vs_pe_lock);
+	if (list_empty(&pe->n_list)) {
+		spin_unlock_bh(&ip_vs_pe_lock);
+		pr_err("%s(): [%s] pe is not in the list. failed\n",
+		       __func__, pe->name);
+		return -EINVAL;
+	}
+
+	/* Remove it from the d-linked pe list */
+	list_del(&pe->n_list);
+	spin_unlock_bh(&ip_vs_pe_lock);
+
+	/* decrease the module use count */
+	ip_vs_use_count_dec();
+
+	pr_info("[%s] pe unregistered.\n", pe->name);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(unregister_ip_vs_pe);
diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c
new file mode 100644
index 0000000..b8b4e96
--- /dev/null
+++ b/net/netfilter/ipvs/ip_vs_pe_sip.c
@@ -0,0 +1,169 @@
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <net/ip_vs.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <linux/netfilter/nf_conntrack_sip.h>
+
+#ifdef CONFIG_IP_VS_DEBUG
+static const char *ip_vs_dbg_callid(char *buf, size_t buf_len,
+				    const char *callid, size_t callid_len,
+				    int *idx)
+{
+	size_t len = min(min(callid_len, (size_t)64), buf_len - *idx - 1);
+	memcpy(buf + *idx, callid, len);
+	buf[*idx+len] = '\0';
+	*idx += len + 1;
+	return buf + *idx - len;
+}
+
+#define IP_VS_DEBUG_CALLID(callid, len)					\
+	ip_vs_dbg_callid(ip_vs_dbg_buf, sizeof(ip_vs_dbg_buf),		\
+			 callid, len, &ip_vs_dbg_idx)
+#endif
+
+static int get_callid(const char *dptr, unsigned int dataoff,
+		      unsigned int datalen,
+		      unsigned int *matchoff, unsigned int *matchlen)
+{
+	/* Find callid */
+	while (1) {
+		int ret = ct_sip_get_header(NULL, dptr, dataoff, datalen,
+					    SIP_HDR_CALL_ID, matchoff,
+					    matchlen);
+		if (ret > 0)
+			break;
+		if (!ret)
+			return 0;
+		dataoff += *matchoff;
+	}
+
+	/* Empty callid is useless */
+	if (!*matchlen)
+		return -EINVAL;
+
+	/* Too large is useless */
+	if (*matchlen > IP_VS_PEDATA_MAXLEN)
+		return -EINVAL;
+
+	/* SIP headers are always followed by a line terminator */
+	if (*matchoff + *matchlen == datalen)
+		return -EINVAL;
+
+	/* RFC 2543 allows lines to be terminated with CR, LF or CRLF,
+	 * RFC 3261 allows only CRLF, we support both. */
+	if (*(dptr + *matchoff + *matchlen) != '\r' &&
+	    *(dptr + *matchoff + *matchlen) != '\n')
+		return -EINVAL;
+
+	IP_VS_DBG_BUF(9, "SIP callid %s (%d bytes)\n",
+		      IP_VS_DEBUG_CALLID(dptr + *matchoff, *matchlen),
+		      *matchlen);
+	return 0;
+}
+
+static int
+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;
+
+	ip_vs_fill_iphdr(p->af, skb_network_header(skb), &iph);
+
+	/* Only useful with UDP */
+	if (iph.protocol != IPPROTO_UDP)
+		return -EINVAL;
+
+	/* No Data ? */
+	dataoff = iph.len + sizeof(struct udphdr);
+	if (dataoff >= skb->len)
+		return -EINVAL;
+
+	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_len = matchlen;
+
+	return 0;
+}
+
+static bool ip_vs_sip_ct_match(const struct ip_vs_conn_param *p,
+				  struct ip_vs_conn *ct)
+
+{
+	bool ret = 0;
+
+	if (ct->af == p->af &&
+	    ip_vs_addr_equal(p->af, p->caddr, &ct->caddr) &&
+	    /* protocol should only be IPPROTO_IP if
+	     * d_addr is a fwmark */
+	    ip_vs_addr_equal(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
+			     p->vaddr, &ct->vaddr) &&
+	    ct->vport == p->vport &&
+	    ct->flags & IP_VS_CONN_F_TEMPLATE &&
+	    ct->protocol == p->protocol &&
+	    ct->pe_data && ct->pe_data_len == p->pe_data_len &&
+	    !memcmp(ct->pe_data, p->pe_data, p->pe_data_len))
+		ret = 1;
+
+	IP_VS_DBG_BUF(9, "SIP template match %s %s->%s:%d %s\n",
+		      ip_vs_proto_name(p->protocol),
+		      IP_VS_DEBUG_CALLID(p->pe_data, p->pe_data_len),
+		      IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
+		      ret ? "hit" : "not hit");
+
+	return ret;
+}
+
+static u32 ip_vs_sip_hashkey_raw(const struct ip_vs_conn_param *p,
+				 u32 initval, bool inverse)
+{
+	return jhash(p->pe_data, p->pe_data_len, initval);
+}
+
+static int ip_vs_sip_show_pe_data(const struct ip_vs_conn *cp, char *buf)
+{
+	memcpy(buf, cp->pe_data, cp->pe_data_len);
+	return cp->pe_data_len;
+}
+
+static struct ip_vs_pe ip_vs_sip_pe =
+{
+	.name =			"sip",
+	.refcnt =		ATOMIC_INIT(0),
+	.module =		THIS_MODULE,
+	.n_list =		LIST_HEAD_INIT(ip_vs_sip_pe.n_list),
+	.fill_param =		ip_vs_sip_fill_param,
+	.ct_match =		ip_vs_sip_ct_match,
+	.hashkey_raw =		ip_vs_sip_hashkey_raw,
+	.show_pe_data =		ip_vs_sip_show_pe_data,
+};
+
+static int __init ip_vs_sip_init(void)
+{
+	return register_ip_vs_pe(&ip_vs_sip_pe);
+}
+
+static void __exit ip_vs_sip_cleanup(void)
+{
+	unregister_ip_vs_pe(&ip_vs_sip_pe);
+}
+
+module_init(ip_vs_sip_init);
+module_exit(ip_vs_sip_cleanup);
+MODULE_LICENSE("GPL");
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index 027f654..c539983 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -172,8 +172,8 @@
 	else if (ih->frag_off & htons(IP_OFFSET))
 		sprintf(buf, "%pI4->%pI4 frag", &ih->saddr, &ih->daddr);
 	else {
-		__be16 _ports[2], *pptr
-;
+		__be16 _ports[2], *pptr;
+
 		pptr = skb_header_pointer(skb, offset + ih->ihl*4,
 					  sizeof(_ports), _ports);
 		if (pptr == NULL)
@@ -223,13 +223,13 @@
 
 
 void
-ip_vs_tcpudp_debug_packet(struct ip_vs_protocol *pp,
+ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
 			  const struct sk_buff *skb,
 			  int offset,
 			  const char *msg)
 {
 #ifdef CONFIG_IP_VS_IPV6
-	if (skb->protocol == htons(ETH_P_IPV6))
+	if (af == AF_INET6)
 		ip_vs_tcpudp_debug_packet_v6(pp, skb, offset, msg);
 	else
 #endif
diff --git a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
index 1892dfc..3a04611 100644
--- a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
@@ -40,6 +40,19 @@
 
 #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)
+{
+	if (likely(!inverse))
+		ip_vs_conn_fill_param(af, IPPROTO_UDP,
+				      &iph->saddr, htons(PORT_ISAKMP),
+				      &iph->daddr, htons(PORT_ISAKMP), p);
+	else
+		ip_vs_conn_fill_param(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,
@@ -47,21 +60,10 @@
 		   int inverse)
 {
 	struct ip_vs_conn *cp;
+	struct ip_vs_conn_param p;
 
-	if (likely(!inverse)) {
-		cp = ip_vs_conn_in_get(af, IPPROTO_UDP,
-				       &iph->saddr,
-				       htons(PORT_ISAKMP),
-				       &iph->daddr,
-				       htons(PORT_ISAKMP));
-	} else {
-		cp = ip_vs_conn_in_get(af, IPPROTO_UDP,
-				       &iph->daddr,
-				       htons(PORT_ISAKMP),
-				       &iph->saddr,
-				       htons(PORT_ISAKMP));
-	}
-
+	ah_esp_conn_fill_param_proto(af, iph, inverse, &p);
+	cp = ip_vs_conn_in_get(&p);
 	if (!cp) {
 		/*
 		 * We are not sure if the packet is from our
@@ -87,21 +89,10 @@
 		    int inverse)
 {
 	struct ip_vs_conn *cp;
+	struct ip_vs_conn_param p;
 
-	if (likely(!inverse)) {
-		cp = ip_vs_conn_out_get(af, IPPROTO_UDP,
-					&iph->saddr,
-					htons(PORT_ISAKMP),
-					&iph->daddr,
-					htons(PORT_ISAKMP));
-	} else {
-		cp = ip_vs_conn_out_get(af, IPPROTO_UDP,
-					&iph->daddr,
-					htons(PORT_ISAKMP),
-					&iph->saddr,
-					htons(PORT_ISAKMP));
-	}
-
+	ah_esp_conn_fill_param_proto(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",
@@ -126,54 +117,6 @@
 	return 0;
 }
 
-
-static void
-ah_esp_debug_packet_v4(struct ip_vs_protocol *pp, const struct sk_buff *skb,
-		       int offset, const char *msg)
-{
-	char buf[256];
-	struct iphdr _iph, *ih;
-
-	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
-	if (ih == NULL)
-		sprintf(buf, "TRUNCATED");
-	else
-		sprintf(buf, "%pI4->%pI4", &ih->saddr, &ih->daddr);
-
-	pr_debug("%s: %s %s\n", msg, pp->name, buf);
-}
-
-#ifdef CONFIG_IP_VS_IPV6
-static void
-ah_esp_debug_packet_v6(struct ip_vs_protocol *pp, const struct sk_buff *skb,
-		       int offset, const char *msg)
-{
-	char buf[256];
-	struct ipv6hdr _iph, *ih;
-
-	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
-	if (ih == NULL)
-		sprintf(buf, "TRUNCATED");
-	else
-		sprintf(buf, "%pI6->%pI6", &ih->saddr, &ih->daddr);
-
-	pr_debug("%s: %s %s\n", msg, pp->name, buf);
-}
-#endif
-
-static void
-ah_esp_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb,
-		    int offset, const char *msg)
-{
-#ifdef CONFIG_IP_VS_IPV6
-	if (skb->protocol == htons(ETH_P_IPV6))
-		ah_esp_debug_packet_v6(pp, skb, offset, msg);
-	else
-#endif
-		ah_esp_debug_packet_v4(pp, skb, offset, msg);
-}
-
-
 static void ah_esp_init(struct ip_vs_protocol *pp)
 {
 	/* nothing to do now */
@@ -204,7 +147,7 @@
 	.register_app =		NULL,
 	.unregister_app =	NULL,
 	.app_conn_bind =	NULL,
-	.debug_packet =		ah_esp_debug_packet,
+	.debug_packet =		ip_vs_tcpudp_debug_packet,
 	.timeout_change =	NULL,		/* ISAKMP */
 	.set_state_timeout =	NULL,
 };
@@ -228,7 +171,7 @@
 	.register_app =		NULL,
 	.unregister_app =	NULL,
 	.app_conn_bind =	NULL,
-	.debug_packet =		ah_esp_debug_packet,
+	.debug_packet =		ip_vs_tcpudp_debug_packet,
 	.timeout_change =	NULL,		/* ISAKMP */
 };
 #endif
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index 4c0855c..1ea96bcd 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -31,6 +31,8 @@
 	if ((sch->type == SCTP_CID_INIT) &&
 	    (svc = ip_vs_service_get(af, skb->mark, iph.protocol,
 				     &iph.daddr, sh->dest))) {
+		int ignored;
+
 		if (ip_vs_todrop()) {
 			/*
 			 * It seems that we are very loaded.
@@ -44,8 +46,8 @@
 		 * Let the virtual server select a real server for the
 		 * incoming connection, and create a connection entry.
 		 */
-		*cpp = ip_vs_schedule(svc, skb);
-		if (!*cpp) {
+		*cpp = ip_vs_schedule(svc, skb, pp, &ignored);
+		if (!*cpp && !ignored) {
 			*verdict = ip_vs_leave(svc, skb, pp);
 			return 0;
 		}
@@ -61,6 +63,7 @@
 {
 	sctp_sctphdr_t *sctph;
 	unsigned int sctphoff;
+	struct sk_buff *iter;
 	__be32 crc32;
 
 #ifdef CONFIG_IP_VS_IPV6
@@ -89,8 +92,8 @@
 
 	/* Calculate the checksum */
 	crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff);
-	for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
-		crc32 = sctp_update_cksum((u8 *) skb->data, skb_headlen(skb),
+	skb_walk_frags(skb, iter)
+		crc32 = sctp_update_cksum((u8 *) iter->data, skb_headlen(iter),
 				          crc32);
 	crc32 = sctp_end_cksum(crc32);
 	sctph->checksum = crc32;
@@ -102,9 +105,9 @@
 sctp_dnat_handler(struct sk_buff *skb,
 		  struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
 {
-
 	sctp_sctphdr_t *sctph;
 	unsigned int sctphoff;
+	struct sk_buff *iter;
 	__be32 crc32;
 
 #ifdef CONFIG_IP_VS_IPV6
@@ -133,8 +136,8 @@
 
 	/* Calculate the checksum */
 	crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff);
-	for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
-		crc32 = sctp_update_cksum((u8 *) skb->data, skb_headlen(skb),
+	skb_walk_frags(skb, iter)
+		crc32 = sctp_update_cksum((u8 *) iter->data, skb_headlen(iter),
 					  crc32);
 	crc32 = sctp_end_cksum(crc32);
 	sctph->checksum = crc32;
@@ -145,9 +148,9 @@
 static int
 sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
 {
-	struct sk_buff *list = skb_shinfo(skb)->frag_list;
 	unsigned int sctphoff;
 	struct sctphdr *sh, _sctph;
+	struct sk_buff *iter;
 	__le32 cmp;
 	__le32 val;
 	__u32 tmp;
@@ -166,15 +169,15 @@
 	cmp = sh->checksum;
 
 	tmp = sctp_start_cksum((__u8 *) sh, skb_headlen(skb));
-	for (; list; list = list->next)
-		tmp = sctp_update_cksum((__u8 *) list->data,
-					skb_headlen(list), tmp);
+	skb_walk_frags(skb, iter)
+		tmp = sctp_update_cksum((__u8 *) iter->data,
+					skb_headlen(iter), tmp);
 
 	val = sctp_end_cksum(tmp);
 
 	if (val != cmp) {
 		/* CRC failure, dump it. */
-		IP_VS_DBG_RL_PKT(0, pp, skb, 0,
+		IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
 				"Failed checksum for");
 		return 0;
 	}
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index 282d24d..f6c5200 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -43,9 +43,12 @@
 		return 0;
 	}
 
+	/* 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))) {
+		int ignored;
+
 		if (ip_vs_todrop()) {
 			/*
 			 * It seems that we are very loaded.
@@ -60,8 +63,8 @@
 		 * Let the virtual server select a real server for the
 		 * incoming connection, and create a connection entry.
 		 */
-		*cpp = ip_vs_schedule(svc, skb);
-		if (!*cpp) {
+		*cpp = ip_vs_schedule(svc, skb, pp, &ignored);
+		if (!*cpp && !ignored) {
 			*verdict = ip_vs_leave(svc, skb, pp);
 			return 0;
 		}
@@ -101,15 +104,15 @@
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6)
 		tcph->check =
-			csum_fold(ip_vs_check_diff16(oldip->ip6, newip->ip6,
+			~csum_fold(ip_vs_check_diff16(oldip->ip6, newip->ip6,
 					 ip_vs_check_diff2(oldlen, newlen,
-						~csum_unfold(tcph->check))));
+						csum_unfold(tcph->check))));
 	else
 #endif
 	tcph->check =
-		csum_fold(ip_vs_check_diff4(oldip->ip, newip->ip,
+		~csum_fold(ip_vs_check_diff4(oldip->ip, newip->ip,
 				ip_vs_check_diff2(oldlen, newlen,
-						~csum_unfold(tcph->check))));
+						csum_unfold(tcph->check))));
 }
 
 
@@ -120,6 +123,7 @@
 	struct tcphdr *tcph;
 	unsigned int tcphoff;
 	int oldlen;
+	int payload_csum = 0;
 
 #ifdef CONFIG_IP_VS_IPV6
 	if (cp->af == AF_INET6)
@@ -134,13 +138,20 @@
 		return 0;
 
 	if (unlikely(cp->app != NULL)) {
+		int ret;
+
 		/* Some checks before mangling */
 		if (pp->csum_check && !pp->csum_check(cp->af, skb, pp))
 			return 0;
 
 		/* Call application helper if needed */
-		if (!ip_vs_app_pkt_out(cp, skb))
+		if (!(ret = ip_vs_app_pkt_out(cp, skb)))
 			return 0;
+		/* ret=2: csum update is needed after payload mangling */
+		if (ret == 1)
+			oldlen = skb->len - tcphoff;
+		else
+			payload_csum = 1;
 	}
 
 	tcph = (void *)skb_network_header(skb) + tcphoff;
@@ -151,12 +162,13 @@
 		tcp_partial_csum_update(cp->af, tcph, &cp->daddr, &cp->vaddr,
 					htons(oldlen),
 					htons(skb->len - tcphoff));
-	} else if (!cp->app) {
+	} else if (!payload_csum) {
 		/* Only port and addr are changed, do fast csum update */
 		tcp_fast_csum_update(cp->af, tcph, &cp->daddr, &cp->vaddr,
 				     cp->dport, cp->vport);
 		if (skb->ip_summed == CHECKSUM_COMPLETE)
-			skb->ip_summed = CHECKSUM_NONE;
+			skb->ip_summed = (cp->app && pp->csum_check) ?
+					 CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
 	} else {
 		/* full checksum calculation */
 		tcph->check = 0;
@@ -174,6 +186,7 @@
 							skb->len - tcphoff,
 							cp->protocol,
 							skb->csum);
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 		IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
 			  pp->name, tcph->check,
@@ -190,6 +203,7 @@
 	struct tcphdr *tcph;
 	unsigned int tcphoff;
 	int oldlen;
+	int payload_csum = 0;
 
 #ifdef CONFIG_IP_VS_IPV6
 	if (cp->af == AF_INET6)
@@ -204,6 +218,8 @@
 		return 0;
 
 	if (unlikely(cp->app != NULL)) {
+		int ret;
+
 		/* Some checks before mangling */
 		if (pp->csum_check && !pp->csum_check(cp->af, skb, pp))
 			return 0;
@@ -212,8 +228,13 @@
 		 *	Attempt ip_vs_app call.
 		 *	It will fix ip_vs_conn and iph ack_seq stuff
 		 */
-		if (!ip_vs_app_pkt_in(cp, skb))
+		if (!(ret = ip_vs_app_pkt_in(cp, skb)))
 			return 0;
+		/* ret=2: csum update is needed after payload mangling */
+		if (ret == 1)
+			oldlen = skb->len - tcphoff;
+		else
+			payload_csum = 1;
 	}
 
 	tcph = (void *)skb_network_header(skb) + tcphoff;
@@ -223,15 +244,16 @@
 	 *	Adjust TCP checksums
 	 */
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		tcp_partial_csum_update(cp->af, tcph, &cp->daddr, &cp->vaddr,
+		tcp_partial_csum_update(cp->af, tcph, &cp->vaddr, &cp->daddr,
 					htons(oldlen),
 					htons(skb->len - tcphoff));
-	} else if (!cp->app) {
+	} else if (!payload_csum) {
 		/* Only port and addr are changed, do fast csum update */
 		tcp_fast_csum_update(cp->af, tcph, &cp->vaddr, &cp->daddr,
 				     cp->vport, cp->dport);
 		if (skb->ip_summed == CHECKSUM_COMPLETE)
-			skb->ip_summed = CHECKSUM_NONE;
+			skb->ip_summed = (cp->app && pp->csum_check) ?
+					 CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
 	} else {
 		/* full checksum calculation */
 		tcph->check = 0;
@@ -278,7 +300,7 @@
 					    skb->len - tcphoff,
 					    ipv6_hdr(skb)->nexthdr,
 					    skb->csum)) {
-				IP_VS_DBG_RL_PKT(0, pp, skb, 0,
+				IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
 						 "Failed checksum for");
 				return 0;
 			}
@@ -289,7 +311,7 @@
 					      skb->len - tcphoff,
 					      ip_hdr(skb)->protocol,
 					      skb->csum)) {
-				IP_VS_DBG_RL_PKT(0, pp, skb, 0,
+				IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
 						 "Failed checksum for");
 				return 0;
 			}
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index 8553231..9d106a0 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -46,6 +46,8 @@
 	svc = ip_vs_service_get(af, skb->mark, iph.protocol,
 				&iph.daddr, uh->dest);
 	if (svc) {
+		int ignored;
+
 		if (ip_vs_todrop()) {
 			/*
 			 * It seems that we are very loaded.
@@ -60,8 +62,8 @@
 		 * Let the virtual server select a real server for the
 		 * incoming connection, and create a connection entry.
 		 */
-		*cpp = ip_vs_schedule(svc, skb);
-		if (!*cpp) {
+		*cpp = ip_vs_schedule(svc, skb, pp, &ignored);
+		if (!*cpp && !ignored) {
 			*verdict = ip_vs_leave(svc, skb, pp);
 			return 0;
 		}
@@ -102,15 +104,15 @@
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6)
 		uhdr->check =
-			csum_fold(ip_vs_check_diff16(oldip->ip6, newip->ip6,
+			~csum_fold(ip_vs_check_diff16(oldip->ip6, newip->ip6,
 					 ip_vs_check_diff2(oldlen, newlen,
-						~csum_unfold(uhdr->check))));
+						csum_unfold(uhdr->check))));
 	else
 #endif
 	uhdr->check =
-		csum_fold(ip_vs_check_diff4(oldip->ip, newip->ip,
+		~csum_fold(ip_vs_check_diff4(oldip->ip, newip->ip,
 				ip_vs_check_diff2(oldlen, newlen,
-						~csum_unfold(uhdr->check))));
+						csum_unfold(uhdr->check))));
 }
 
 
@@ -121,6 +123,7 @@
 	struct udphdr *udph;
 	unsigned int udphoff;
 	int oldlen;
+	int payload_csum = 0;
 
 #ifdef CONFIG_IP_VS_IPV6
 	if (cp->af == AF_INET6)
@@ -135,6 +138,8 @@
 		return 0;
 
 	if (unlikely(cp->app != NULL)) {
+		int ret;
+
 		/* Some checks before mangling */
 		if (pp->csum_check && !pp->csum_check(cp->af, skb, pp))
 			return 0;
@@ -142,8 +147,13 @@
 		/*
 		 *	Call application helper if needed
 		 */
-		if (!ip_vs_app_pkt_out(cp, skb))
+		if (!(ret = ip_vs_app_pkt_out(cp, skb)))
 			return 0;
+		/* ret=2: csum update is needed after payload mangling */
+		if (ret == 1)
+			oldlen = skb->len - udphoff;
+		else
+			payload_csum = 1;
 	}
 
 	udph = (void *)skb_network_header(skb) + udphoff;
@@ -156,12 +166,13 @@
 		udp_partial_csum_update(cp->af, udph, &cp->daddr, &cp->vaddr,
 					htons(oldlen),
 					htons(skb->len - udphoff));
-	} else if (!cp->app && (udph->check != 0)) {
+	} else if (!payload_csum && (udph->check != 0)) {
 		/* Only port and addr are changed, do fast csum update */
 		udp_fast_csum_update(cp->af, udph, &cp->daddr, &cp->vaddr,
 				     cp->dport, cp->vport);
 		if (skb->ip_summed == CHECKSUM_COMPLETE)
-			skb->ip_summed = CHECKSUM_NONE;
+			skb->ip_summed = (cp->app && pp->csum_check) ?
+					 CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
 	} else {
 		/* full checksum calculation */
 		udph->check = 0;
@@ -181,6 +192,7 @@
 							skb->csum);
 		if (udph->check == 0)
 			udph->check = CSUM_MANGLED_0;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
 		IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
 			  pp->name, udph->check,
 			  (char*)&(udph->check) - (char*)udph);
@@ -196,6 +208,7 @@
 	struct udphdr *udph;
 	unsigned int udphoff;
 	int oldlen;
+	int payload_csum = 0;
 
 #ifdef CONFIG_IP_VS_IPV6
 	if (cp->af == AF_INET6)
@@ -210,6 +223,8 @@
 		return 0;
 
 	if (unlikely(cp->app != NULL)) {
+		int ret;
+
 		/* Some checks before mangling */
 		if (pp->csum_check && !pp->csum_check(cp->af, skb, pp))
 			return 0;
@@ -218,8 +233,13 @@
 		 *	Attempt ip_vs_app call.
 		 *	It will fix ip_vs_conn
 		 */
-		if (!ip_vs_app_pkt_in(cp, skb))
+		if (!(ret = ip_vs_app_pkt_in(cp, skb)))
 			return 0;
+		/* ret=2: csum update is needed after payload mangling */
+		if (ret == 1)
+			oldlen = skb->len - udphoff;
+		else
+			payload_csum = 1;
 	}
 
 	udph = (void *)skb_network_header(skb) + udphoff;
@@ -229,15 +249,16 @@
 	 *	Adjust UDP checksums
 	 */
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		udp_partial_csum_update(cp->af, udph, &cp->daddr, &cp->vaddr,
+		udp_partial_csum_update(cp->af, udph, &cp->vaddr, &cp->daddr,
 					htons(oldlen),
 					htons(skb->len - udphoff));
-	} else if (!cp->app && (udph->check != 0)) {
+	} else if (!payload_csum && (udph->check != 0)) {
 		/* Only port and addr are changed, do fast csum update */
 		udp_fast_csum_update(cp->af, udph, &cp->vaddr, &cp->daddr,
 				     cp->vport, cp->dport);
 		if (skb->ip_summed == CHECKSUM_COMPLETE)
-			skb->ip_summed = CHECKSUM_NONE;
+			skb->ip_summed = (cp->app && pp->csum_check) ?
+					 CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
 	} else {
 		/* full checksum calculation */
 		udph->check = 0;
@@ -293,7 +314,7 @@
 						    skb->len - udphoff,
 						    ipv6_hdr(skb)->nexthdr,
 						    skb->csum)) {
-					IP_VS_DBG_RL_PKT(0, pp, skb, 0,
+					IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
 							 "Failed checksum for");
 					return 0;
 				}
@@ -304,7 +325,7 @@
 						      skb->len - udphoff,
 						      ip_hdr(skb)->protocol,
 						      skb->csum)) {
-					IP_VS_DBG_RL_PKT(0, pp, skb, 0,
+					IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
 							 "Failed checksum for");
 					return 0;
 				}
diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
index bbc1ac7..076ebe0 100644
--- a/net/netfilter/ipvs/ip_vs_sched.c
+++ b/net/netfilter/ipvs/ip_vs_sched.c
@@ -35,7 +35,7 @@
 static LIST_HEAD(ip_vs_schedulers);
 
 /* lock for service table */
-static DEFINE_RWLOCK(__ip_vs_sched_lock);
+static DEFINE_SPINLOCK(ip_vs_sched_lock);
 
 
 /*
@@ -46,15 +46,6 @@
 {
 	int ret;
 
-	if (svc == NULL) {
-		pr_err("%s(): svc arg NULL\n", __func__);
-		return -EINVAL;
-	}
-	if (scheduler == NULL) {
-		pr_err("%s(): scheduler arg NULL\n", __func__);
-		return -EINVAL;
-	}
-
 	svc->scheduler = scheduler;
 
 	if (scheduler->init_service) {
@@ -74,18 +65,10 @@
  */
 int ip_vs_unbind_scheduler(struct ip_vs_service *svc)
 {
-	struct ip_vs_scheduler *sched;
+	struct ip_vs_scheduler *sched = svc->scheduler;
 
-	if (svc == NULL) {
-		pr_err("%s(): svc arg NULL\n", __func__);
-		return -EINVAL;
-	}
-
-	sched = svc->scheduler;
-	if (sched == NULL) {
-		pr_err("%s(): svc isn't bound\n", __func__);
-		return -EINVAL;
-	}
+	if (!sched)
+		return 0;
 
 	if (sched->done_service) {
 		if (sched->done_service(svc) != 0) {
@@ -108,7 +91,7 @@
 
 	IP_VS_DBG(2, "%s(): sched_name \"%s\"\n", __func__, sched_name);
 
-	read_lock_bh(&__ip_vs_sched_lock);
+	spin_lock_bh(&ip_vs_sched_lock);
 
 	list_for_each_entry(sched, &ip_vs_schedulers, n_list) {
 		/*
@@ -122,14 +105,14 @@
 		}
 		if (strcmp(sched_name, sched->name)==0) {
 			/* HIT */
-			read_unlock_bh(&__ip_vs_sched_lock);
+			spin_unlock_bh(&ip_vs_sched_lock);
 			return sched;
 		}
 		if (sched->module)
 			module_put(sched->module);
 	}
 
-	read_unlock_bh(&__ip_vs_sched_lock);
+	spin_unlock_bh(&ip_vs_sched_lock);
 	return NULL;
 }
 
@@ -159,7 +142,7 @@
 
 void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler)
 {
-	if (scheduler->module)
+	if (scheduler && scheduler->module)
 		module_put(scheduler->module);
 }
 
@@ -184,10 +167,10 @@
 	/* increase the module use count */
 	ip_vs_use_count_inc();
 
-	write_lock_bh(&__ip_vs_sched_lock);
+	spin_lock_bh(&ip_vs_sched_lock);
 
 	if (!list_empty(&scheduler->n_list)) {
-		write_unlock_bh(&__ip_vs_sched_lock);
+		spin_unlock_bh(&ip_vs_sched_lock);
 		ip_vs_use_count_dec();
 		pr_err("%s(): [%s] scheduler already linked\n",
 		       __func__, scheduler->name);
@@ -200,7 +183,7 @@
 	 */
 	list_for_each_entry(sched, &ip_vs_schedulers, n_list) {
 		if (strcmp(scheduler->name, sched->name) == 0) {
-			write_unlock_bh(&__ip_vs_sched_lock);
+			spin_unlock_bh(&ip_vs_sched_lock);
 			ip_vs_use_count_dec();
 			pr_err("%s(): [%s] scheduler already existed "
 			       "in the system\n", __func__, scheduler->name);
@@ -211,7 +194,7 @@
 	 *	Add it into the d-linked scheduler list
 	 */
 	list_add(&scheduler->n_list, &ip_vs_schedulers);
-	write_unlock_bh(&__ip_vs_sched_lock);
+	spin_unlock_bh(&ip_vs_sched_lock);
 
 	pr_info("[%s] scheduler registered.\n", scheduler->name);
 
@@ -229,9 +212,9 @@
 		return -EINVAL;
 	}
 
-	write_lock_bh(&__ip_vs_sched_lock);
+	spin_lock_bh(&ip_vs_sched_lock);
 	if (list_empty(&scheduler->n_list)) {
-		write_unlock_bh(&__ip_vs_sched_lock);
+		spin_unlock_bh(&ip_vs_sched_lock);
 		pr_err("%s(): [%s] scheduler is not in the list. failed\n",
 		       __func__, scheduler->name);
 		return -EINVAL;
@@ -241,7 +224,7 @@
 	 *	Remove it from the d-linked scheduler list
 	 */
 	list_del(&scheduler->n_list);
-	write_unlock_bh(&__ip_vs_sched_lock);
+	spin_unlock_bh(&ip_vs_sched_lock);
 
 	/* decrease the module use count */
 	ip_vs_use_count_dec();
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 7ba0693..ab85aed 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -288,6 +288,16 @@
 		ip_vs_sync_conn(cp->control);
 }
 
+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)
+{
+	/* XXX: Need to take into account persistence engine */
+	ip_vs_conn_fill_param(af, protocol, caddr, cport, vaddr, vport, p);
+	return 0;
+}
 
 /*
  *      Process received multicast message and create the corresponding
@@ -301,6 +311,7 @@
 	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;
 
@@ -370,18 +381,20 @@
 			}
 		}
 
-		if (!(flags & IP_VS_CONN_F_TEMPLATE))
-			cp = ip_vs_conn_in_get(AF_INET, s->protocol,
-					       (union nf_inet_addr *)&s->caddr,
-					       s->cport,
-					       (union nf_inet_addr *)&s->vaddr,
-					       s->vport);
-		else
-			cp = ip_vs_ct_in_get(AF_INET, s->protocol,
-					     (union nf_inet_addr *)&s->caddr,
-					     s->cport,
-					     (union nf_inet_addr *)&s->vaddr,
-					     s->vport);
+		{
+			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;
+			}
+			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.
@@ -406,14 +419,9 @@
 				else
 					flags &= ~IP_VS_CONN_F_INACTIVE;
 			}
-			cp = ip_vs_conn_new(AF_INET, s->protocol,
-					    (union nf_inet_addr *)&s->caddr,
-					    s->cport,
-					    (union nf_inet_addr *)&s->vaddr,
-					    s->vport,
+			cp = ip_vs_conn_new(&param,
 					    (union nf_inet_addr *)&s->daddr,
-					    s->dport,
-					    flags, dest);
+					    s->dport, flags, dest);
 			if (dest)
 				atomic_dec(&dest->refcnt);
 			if (!cp) {
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 49df6be..de04ea3 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -11,6 +11,16 @@
  *
  * Changes:
  *
+ * Description of forwarding methods:
+ * - all transmitters are called from LOCAL_IN (remote clients) and
+ * LOCAL_OUT (local clients) but for ICMP can be called from FORWARD
+ * - not all connections have destination server, for example,
+ * connections in backup server when fwmark is used
+ * - bypass connections use daddr from packet
+ * LOCAL_OUT rules:
+ * - skb->dev is NULL, skb->protocol is not set (both are set in POST_ROUTING)
+ * - skb->pkt_type is not set yet
+ * - the only place where we can see skb->sk != NULL
  */
 
 #define KMSG_COMPONENT "IPVS"
@@ -26,9 +36,9 @@
 #include <net/route.h>                  /* for ip_route_output */
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
+#include <net/addrconf.h>
 #include <linux/icmpv6.h>
 #include <linux/netfilter.h>
-#include <net/netfilter/nf_conntrack.h>
 #include <linux/netfilter_ipv4.h>
 
 #include <net/ip_vs.h>
@@ -38,26 +48,27 @@
  *      Destination cache to speed up outgoing route lookup
  */
 static inline void
-__ip_vs_dst_set(struct ip_vs_dest *dest, u32 rtos, struct dst_entry *dst)
+__ip_vs_dst_set(struct ip_vs_dest *dest, u32 rtos, struct dst_entry *dst,
+		u32 dst_cookie)
 {
 	struct dst_entry *old_dst;
 
 	old_dst = dest->dst_cache;
 	dest->dst_cache = dst;
 	dest->dst_rtos = rtos;
+	dest->dst_cookie = dst_cookie;
 	dst_release(old_dst);
 }
 
 static inline struct dst_entry *
-__ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos, u32 cookie)
+__ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos)
 {
 	struct dst_entry *dst = dest->dst_cache;
 
 	if (!dst)
 		return NULL;
-	if ((dst->obsolete
-	     || (dest->af == AF_INET && rtos != dest->dst_rtos)) &&
-	    dst->ops->check(dst, cookie) == NULL) {
+	if ((dst->obsolete || rtos != dest->dst_rtos) &&
+	    dst->ops->check(dst, dest->dst_cookie) == NULL) {
 		dest->dst_cache = NULL;
 		dst_release(dst);
 		return NULL;
@@ -66,16 +77,24 @@
 	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
+ */
 static struct rtable *
-__ip_vs_get_out_rt(struct ip_vs_conn *cp, u32 rtos)
+__ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest,
+		   __be32 daddr, u32 rtos, int rt_mode)
 {
+	struct net *net = dev_net(skb_dst(skb)->dev);
 	struct rtable *rt;			/* Route to the other host */
-	struct ip_vs_dest *dest = cp->dest;
+	struct rtable *ort;			/* Original route */
+	int local;
 
 	if (dest) {
 		spin_lock(&dest->dst_lock);
 		if (!(rt = (struct rtable *)
-		      __ip_vs_dst_check(dest, rtos, 0))) {
+		      __ip_vs_dst_check(dest, rtos))) {
 			struct flowi fl = {
 				.oif = 0,
 				.nl_u = {
@@ -85,13 +104,13 @@
 						.tos = rtos, } },
 			};
 
-			if (ip_route_output_key(&init_net, &rt, &fl)) {
+			if (ip_route_output_key(net, &rt, &fl)) {
 				spin_unlock(&dest->dst_lock);
 				IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
 					     &dest->addr.ip);
 				return NULL;
 			}
-			__ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst));
+			__ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0);
 			IP_VS_DBG(10, "new dst %pI4, refcnt=%d, rtos=%X\n",
 				  &dest->addr.ip,
 				  atomic_read(&rt->dst.__refcnt), rtos);
@@ -102,78 +121,199 @@
 			.oif = 0,
 			.nl_u = {
 				.ip4_u = {
-					.daddr = cp->daddr.ip,
+					.daddr = daddr,
 					.saddr = 0,
 					.tos = rtos, } },
 		};
 
-		if (ip_route_output_key(&init_net, &rt, &fl)) {
+		if (ip_route_output_key(net, &rt, &fl)) {
 			IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
-				     &cp->daddr.ip);
+				     &daddr);
 			return NULL;
 		}
 	}
 
+	local = rt->rt_flags & RTCF_LOCAL;
+	if (!((local ? 1 : 2) & 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)) {
+		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);
+		ip_rt_put(rt);
+		return NULL;
+	}
+	if (unlikely(!local && ipv4_is_loopback(ip_hdr(skb)->saddr))) {
+		IP_VS_DBG_RL("Stopping traffic from loopback address %pI4 "
+			     "to non-local address, dest: %pI4\n",
+			     &ip_hdr(skb)->saddr, &rt->rt_dst);
+		ip_rt_put(rt);
+		return NULL;
+	}
+
 	return rt;
 }
 
-#ifdef CONFIG_IP_VS_IPV6
-static struct rt6_info *
-__ip_vs_get_out_rt_v6(struct ip_vs_conn *cp)
+/* Reroute packet to local IPv4 stack after DNAT */
+static int
+__ip_vs_reroute_locally(struct sk_buff *skb)
 {
-	struct rt6_info *rt;			/* Route to the other host */
-	struct ip_vs_dest *dest = cp->dest;
+	struct rtable *rt = skb_rtable(skb);
+	struct net_device *dev = rt->dst.dev;
+	struct net *net = dev_net(dev);
+	struct iphdr *iph = ip_hdr(skb);
 
-	if (dest) {
-		spin_lock(&dest->dst_lock);
-		rt = (struct rt6_info *)__ip_vs_dst_check(dest, 0, 0);
-		if (!rt) {
-			struct flowi fl = {
-				.oif = 0,
-				.nl_u = {
-					.ip6_u = {
-						.daddr = dest->addr.in6,
-						.saddr = {
-							.s6_addr32 =
-								{ 0, 0, 0, 0 },
-						},
-					},
-				},
-			};
+	if (rt->fl.iif) {
+		unsigned long orefdst = skb->_skb_refdst;
 
-			rt = (struct rt6_info *)ip6_route_output(&init_net,
-								 NULL, &fl);
-			if (!rt) {
-				spin_unlock(&dest->dst_lock);
-				IP_VS_DBG_RL("ip6_route_output error, dest: %pI6\n",
-					     &dest->addr.in6);
-				return NULL;
-			}
-			__ip_vs_dst_set(dest, 0, dst_clone(&rt->dst));
-			IP_VS_DBG(10, "new dst %pI6, refcnt=%d\n",
-				  &dest->addr.in6,
-				  atomic_read(&rt->dst.__refcnt));
-		}
-		spin_unlock(&dest->dst_lock);
+		if (ip_route_input(skb, iph->daddr, iph->saddr,
+				   iph->tos, skb->dev))
+			return 0;
+		refdst_drop(orefdst);
 	} else {
 		struct flowi fl = {
 			.oif = 0,
 			.nl_u = {
-				.ip6_u = {
-					.daddr = cp->daddr.in6,
-					.saddr = {
-						.s6_addr32 = { 0, 0, 0, 0 },
-					},
-				},
+				.ip4_u = {
+					.daddr = iph->daddr,
+					.saddr = iph->saddr,
+					.tos = RT_TOS(iph->tos),
+				}
 			},
+			.mark = skb->mark,
 		};
+		struct rtable *rt;
 
-		rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl);
-		if (!rt) {
-			IP_VS_DBG_RL("ip6_route_output error, dest: %pI6\n",
-				     &cp->daddr.in6);
-			return NULL;
+		if (ip_route_output_key(net, &rt, &fl))
+			return 0;
+		if (!(rt->rt_flags & RTCF_LOCAL)) {
+			ip_rt_put(rt);
+			return 0;
 		}
+		/* Drop old route. */
+		skb_dst_drop(skb);
+		skb_dst_set(skb, &rt->dst);
+	}
+	return 1;
+}
+
+#ifdef CONFIG_IP_VS_IPV6
+
+static inline int __ip_vs_is_local_route6(struct rt6_info *rt)
+{
+	return rt->rt6i_dev && rt->rt6i_dev->flags & IFF_LOOPBACK;
+}
+
+static struct dst_entry *
+__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 = {
+		.oif = 0,
+		.nl_u = {
+			.ip6_u = {
+				.daddr = *daddr,
+			},
+		},
+	};
+
+	dst = ip6_route_output(net, NULL, &fl);
+	if (dst->error)
+		goto out_err;
+	if (!ret_saddr)
+		return dst;
+	if (ipv6_addr_any(&fl.fl6_src) &&
+	    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)
+		goto out_err;
+	ipv6_addr_copy(ret_saddr, &fl.fl6_src);
+	return dst;
+
+out_err:
+	dst_release(dst);
+	IP_VS_DBG_RL("ip6_route_output error, dest: %pI6\n", daddr);
+	return NULL;
+}
+
+/*
+ * 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
+ */
+static struct rt6_info *
+__ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest,
+		      struct in6_addr *daddr, struct in6_addr *ret_saddr,
+		      int do_xfrm, int rt_mode)
+{
+	struct net *net = dev_net(skb_dst(skb)->dev);
+	struct rt6_info *rt;			/* Route to the other host */
+	struct rt6_info *ort;			/* Original route */
+	struct dst_entry *dst;
+	int local;
+
+	if (dest) {
+		spin_lock(&dest->dst_lock);
+		rt = (struct rt6_info *)__ip_vs_dst_check(dest, 0);
+		if (!rt) {
+			u32 cookie;
+
+			dst = __ip_vs_route_output_v6(net, &dest->addr.in6,
+						      &dest->dst_saddr,
+						      do_xfrm);
+			if (!dst) {
+				spin_unlock(&dest->dst_lock);
+				return NULL;
+			}
+			rt = (struct rt6_info *) dst;
+			cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
+			__ip_vs_dst_set(dest, 0, dst_clone(&rt->dst), cookie);
+			IP_VS_DBG(10, "new dst %pI6, src %pI6, refcnt=%d\n",
+				  &dest->addr.in6, &dest->dst_saddr,
+				  atomic_read(&rt->dst.__refcnt));
+		}
+		if (ret_saddr)
+			ipv6_addr_copy(ret_saddr, &dest->dst_saddr);
+		spin_unlock(&dest->dst_lock);
+	} else {
+		dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm);
+		if (!dst)
+			return NULL;
+		rt = (struct rt6_info *) dst;
+	}
+
+	local = __ip_vs_is_local_route6(rt);
+	if (!((local ? 1 : 2) & rt_mode)) {
+		IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI6\n",
+			     local ? "local":"non-local", daddr);
+		dst_release(&rt->dst);
+		return NULL;
+	}
+	if (local && !(rt_mode & 4) &&
+	    !((ort = (struct rt6_info *) skb_dst(skb)) &&
+	      __ip_vs_is_local_route6(ort))) {
+		IP_VS_DBG_RL("Redirect from non-local address %pI6 to local "
+			     "requires NAT method, dest: %pI6\n",
+			     &ipv6_hdr(skb)->daddr, daddr);
+		dst_release(&rt->dst);
+		return NULL;
+	}
+	if (unlikely(!local && (!skb->dev || skb->dev->flags & IFF_LOOPBACK) &&
+		     ipv6_addr_type(&ipv6_hdr(skb)->saddr) &
+				    IPV6_ADDR_LOOPBACK)) {
+		IP_VS_DBG_RL("Stopping traffic from loopback address %pI6 "
+			     "to non-local address, dest: %pI6\n",
+			     &ipv6_hdr(skb)->saddr, daddr);
+		dst_release(&rt->dst);
+		return NULL;
 	}
 
 	return rt;
@@ -194,12 +334,44 @@
 	dst_release(old_dst);
 }
 
-#define IP_VS_XMIT(pf, skb, rt)				\
+#define IP_VS_XMIT_TUNNEL(skb, cp)				\
+({								\
+	int __ret = NF_ACCEPT;					\
+								\
+	(skb)->ipvs_property = 1;				\
+	if (unlikely((cp)->flags & IP_VS_CONN_F_NFCT))		\
+		__ret = ip_vs_confirm_conntrack(skb, cp);	\
+	if (__ret == NF_ACCEPT) {				\
+		nf_reset(skb);					\
+		skb_forward_csum(skb);				\
+	}							\
+	__ret;							\
+})
+
+#define IP_VS_XMIT_NAT(pf, skb, cp, local)		\
 do {							\
 	(skb)->ipvs_property = 1;			\
+	if (likely(!((cp)->flags & IP_VS_CONN_F_NFCT)))	\
+		ip_vs_notrack(skb);			\
+	else						\
+		ip_vs_update_conntrack(skb, cp, 1);	\
+	if (local)					\
+		return NF_ACCEPT;			\
 	skb_forward_csum(skb);				\
 	NF_HOOK(pf, NF_INET_LOCAL_OUT, (skb), NULL,	\
-		(rt)->dst.dev, dst_output);		\
+		skb_dst(skb)->dev, dst_output);		\
+} while (0)
+
+#define IP_VS_XMIT(pf, skb, cp, local)			\
+do {							\
+	(skb)->ipvs_property = 1;			\
+	if (likely(!((cp)->flags & IP_VS_CONN_F_NFCT)))	\
+		ip_vs_notrack(skb);			\
+	if (local)					\
+		return NF_ACCEPT;			\
+	skb_forward_csum(skb);				\
+	NF_HOOK(pf, NF_INET_LOCAL_OUT, (skb), NULL,	\
+		skb_dst(skb)->dev, dst_output);		\
 } while (0)
 
 
@@ -211,7 +383,7 @@
 		struct ip_vs_protocol *pp)
 {
 	/* we do not touch skb and do not need pskb ptr */
-	return NF_ACCEPT;
+	IP_VS_XMIT(NFPROTO_IPV4, skb, cp, 1);
 }
 
 
@@ -226,24 +398,13 @@
 {
 	struct rtable *rt;			/* Route to the other host */
 	struct iphdr  *iph = ip_hdr(skb);
-	u8     tos = iph->tos;
 	int    mtu;
-	struct flowi fl = {
-		.oif = 0,
-		.nl_u = {
-			.ip4_u = {
-				.daddr = iph->daddr,
-				.saddr = 0,
-				.tos = RT_TOS(tos), } },
-	};
 
 	EnterFunction(10);
 
-	if (ip_route_output_key(&init_net, &rt, &fl)) {
-		IP_VS_DBG_RL("%s(): ip_route_output error, dest: %pI4\n",
-			     __func__, &iph->daddr);
+	if (!(rt = __ip_vs_get_out_rt(skb, NULL, iph->daddr,
+				      RT_TOS(iph->tos), 2)))
 		goto tx_error_icmp;
-	}
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
@@ -271,7 +432,7 @@
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-	IP_VS_XMIT(NFPROTO_IPV4, skb, rt);
+	IP_VS_XMIT(NFPROTO_IPV4, skb, cp, 0);
 
 	LeaveFunction(10);
 	return NF_STOLEN;
@@ -292,28 +453,22 @@
 	struct rt6_info *rt;			/* Route to the other host */
 	struct ipv6hdr  *iph = ipv6_hdr(skb);
 	int    mtu;
-	struct flowi fl = {
-		.oif = 0,
-		.nl_u = {
-			.ip6_u = {
-				.daddr = iph->daddr,
-				.saddr = { .s6_addr32 = {0, 0, 0, 0} }, } },
-	};
 
 	EnterFunction(10);
 
-	rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl);
-	if (!rt) {
-		IP_VS_DBG_RL("%s(): ip6_route_output error, dest: %pI6\n",
-			     __func__, &iph->daddr);
+	if (!(rt = __ip_vs_get_out_rt_v6(skb, NULL, &iph->daddr, NULL, 0, 2)))
 		goto tx_error_icmp;
-	}
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
 	if (skb->len > mtu) {
-		dst_release(&rt->dst);
+		if (!skb->dev) {
+			struct net *net = dev_net(skb_dst(skb)->dev);
+
+			skb->dev = net->loopback_dev;
+		}
 		icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+		dst_release(&rt->dst);
 		IP_VS_DBG_RL("%s(): frag needed\n", __func__);
 		goto tx_error;
 	}
@@ -335,7 +490,7 @@
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-	IP_VS_XMIT(NFPROTO_IPV6, skb, rt);
+	IP_VS_XMIT(NFPROTO_IPV6, skb, cp, 0);
 
 	LeaveFunction(10);
 	return NF_STOLEN;
@@ -349,36 +504,6 @@
 }
 #endif
 
-void
-ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
-{
-	struct nf_conn *ct = (struct nf_conn *)skb->nfct;
-	struct nf_conntrack_tuple new_tuple;
-
-	if (ct == NULL || nf_ct_is_untracked(ct) || nf_ct_is_confirmed(ct))
-		return;
-
-	/*
-	 * The connection is not yet in the hashtable, so we update it.
-	 * CIP->VIP will remain the same, so leave the tuple in
-	 * IP_CT_DIR_ORIGINAL untouched.  When the reply comes back from the
-	 * real-server we will see RIP->DIP.
-	 */
-	new_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-	if (outin)
-		new_tuple.src.u3 = cp->daddr;
-	else
-		new_tuple.dst.u3 = cp->vaddr;
-	/*
-	 * This will also take care of UDP and other protocols.
-	 */
-	if (outin)
-		new_tuple.src.u.tcp.port = cp->dport;
-	else
-		new_tuple.dst.u.tcp.port = cp->vport;
-	nf_conntrack_alter_reply(ct, &new_tuple);
-}
-
 /*
  *      NAT transmitter (only for outside-to-inside nat forwarding)
  *      Not used for related ICMP
@@ -390,6 +515,7 @@
 	struct rtable *rt;		/* Route to the other host */
 	int mtu;
 	struct iphdr *iph = ip_hdr(skb);
+	int local;
 
 	EnterFunction(10);
 
@@ -403,16 +529,42 @@
 		IP_VS_DBG(10, "filled cport=%d\n", ntohs(*p));
 	}
 
-	if (!(rt = __ip_vs_get_out_rt(cp, RT_TOS(iph->tos))))
+	if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
+				      RT_TOS(iph->tos), 1|2|4)))
 		goto tx_error_icmp;
+	local = rt->rt_flags & RTCF_LOCAL;
+	/*
+	 * Avoid duplicate tuple in reply direction for NAT traffic
+	 * to local address when connection is sync-ed
+	 */
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+	if (cp->flags & IP_VS_CONN_F_SYNC && local) {
+		enum ip_conntrack_info ctinfo;
+		struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+
+		if (ct && !nf_ct_is_untracked(ct)) {
+			IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, 0,
+					 "ip_vs_nat_xmit(): "
+					 "stopping DNAT to local address");
+			goto tx_error_put;
+		}
+	}
+#endif
+
+	/* From world but DNAT to loopback address? */
+	if (local && ipv4_is_loopback(rt->rt_dst) && skb_rtable(skb)->fl.iif) {
+		IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, 0, "ip_vs_nat_xmit(): "
+				 "stopping DNAT to loopback address");
+		goto tx_error_put;
+	}
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
 	if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF))) {
-		ip_rt_put(rt);
 		icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
-		IP_VS_DBG_RL_PKT(0, pp, skb, 0, "ip_vs_nat_xmit(): frag needed for");
-		goto tx_error;
+		IP_VS_DBG_RL_PKT(0, AF_INET, pp, skb, 0,
+				 "ip_vs_nat_xmit(): frag needed for");
+		goto tx_error_put;
 	}
 
 	/* copy-on-write the packet before mangling it */
@@ -422,19 +574,28 @@
 	if (skb_cow(skb, rt->dst.dev->hard_header_len))
 		goto tx_error_put;
 
-	/* drop old route */
-	skb_dst_drop(skb);
-	skb_dst_set(skb, &rt->dst);
-
 	/* mangle the packet */
 	if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp))
-		goto tx_error;
+		goto tx_error_put;
 	ip_hdr(skb)->daddr = cp->daddr.ip;
 	ip_send_check(ip_hdr(skb));
 
-	IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
+	if (!local) {
+		/* drop old route */
+		skb_dst_drop(skb);
+		skb_dst_set(skb, &rt->dst);
+	} else {
+		ip_rt_put(rt);
+		/*
+		 * Some IPv4 replies get local address from routes,
+		 * not from iph, so while we DNAT after routing
+		 * we need this second input/output route.
+		 */
+		if (!__ip_vs_reroute_locally(skb))
+			goto tx_error;
+	}
 
-	ip_vs_update_conntrack(skb, cp, 1);
+	IP_VS_DBG_PKT(10, AF_INET, pp, skb, 0, "After DNAT");
 
 	/* FIXME: when application helper enlarges the packet and the length
 	   is larger than the MTU of outgoing device, there will be still
@@ -443,7 +604,7 @@
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-	IP_VS_XMIT(NFPROTO_IPV4, skb, rt);
+	IP_VS_XMIT_NAT(NFPROTO_IPV4, skb, cp, local);
 
 	LeaveFunction(10);
 	return NF_STOLEN;
@@ -451,8 +612,8 @@
   tx_error_icmp:
 	dst_link_failure(skb);
   tx_error:
-	LeaveFunction(10);
 	kfree_skb(skb);
+	LeaveFunction(10);
 	return NF_STOLEN;
   tx_error_put:
 	ip_rt_put(rt);
@@ -466,6 +627,7 @@
 {
 	struct rt6_info *rt;		/* Route to the other host */
 	int mtu;
+	int local;
 
 	EnterFunction(10);
 
@@ -480,18 +642,49 @@
 		IP_VS_DBG(10, "filled cport=%d\n", ntohs(*p));
 	}
 
-	rt = __ip_vs_get_out_rt_v6(cp);
-	if (!rt)
+	if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL,
+					 0, 1|2|4)))
 		goto tx_error_icmp;
+	local = __ip_vs_is_local_route6(rt);
+	/*
+	 * Avoid duplicate tuple in reply direction for NAT traffic
+	 * to local address when connection is sync-ed
+	 */
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+	if (cp->flags & IP_VS_CONN_F_SYNC && local) {
+		enum ip_conntrack_info ctinfo;
+		struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+
+		if (ct && !nf_ct_is_untracked(ct)) {
+			IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, 0,
+					 "ip_vs_nat_xmit_v6(): "
+					 "stopping DNAT to local address");
+			goto tx_error_put;
+		}
+	}
+#endif
+
+	/* From world but DNAT to loopback address? */
+	if (local && skb->dev && !(skb->dev->flags & IFF_LOOPBACK) &&
+	    ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_LOOPBACK) {
+		IP_VS_DBG_RL_PKT(1, AF_INET6, pp, skb, 0,
+				 "ip_vs_nat_xmit_v6(): "
+				 "stopping DNAT to loopback address");
+		goto tx_error_put;
+	}
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
 	if (skb->len > mtu) {
-		dst_release(&rt->dst);
+		if (!skb->dev) {
+			struct net *net = dev_net(skb_dst(skb)->dev);
+
+			skb->dev = net->loopback_dev;
+		}
 		icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
-		IP_VS_DBG_RL_PKT(0, pp, skb, 0,
+		IP_VS_DBG_RL_PKT(0, AF_INET6, pp, skb, 0,
 				 "ip_vs_nat_xmit_v6(): frag needed for");
-		goto tx_error;
+		goto tx_error_put;
 	}
 
 	/* copy-on-write the packet before mangling it */
@@ -501,18 +694,21 @@
 	if (skb_cow(skb, rt->dst.dev->hard_header_len))
 		goto tx_error_put;
 
-	/* drop old route */
-	skb_dst_drop(skb);
-	skb_dst_set(skb, &rt->dst);
-
 	/* mangle the packet */
 	if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp))
 		goto tx_error;
-	ipv6_hdr(skb)->daddr = cp->daddr.in6;
+	ipv6_addr_copy(&ipv6_hdr(skb)->daddr, &cp->daddr.in6);
 
-	IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
+	if (!local || !skb->dev) {
+		/* drop the old route when skb is not shared */
+		skb_dst_drop(skb);
+		skb_dst_set(skb, &rt->dst);
+	} else {
+		/* destined to loopback, do we need to change route? */
+		dst_release(&rt->dst);
+	}
 
-	ip_vs_update_conntrack(skb, cp, 1);
+	IP_VS_DBG_PKT(10, AF_INET6, pp, skb, 0, "After DNAT");
 
 	/* FIXME: when application helper enlarges the packet and the length
 	   is larger than the MTU of outgoing device, there will be still
@@ -521,7 +717,7 @@
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-	IP_VS_XMIT(NFPROTO_IPV6, skb, rt);
+	IP_VS_XMIT_NAT(NFPROTO_IPV6, skb, cp, local);
 
 	LeaveFunction(10);
 	return NF_STOLEN;
@@ -567,30 +763,27 @@
 	struct iphdr  *old_iph = ip_hdr(skb);
 	u8     tos = old_iph->tos;
 	__be16 df = old_iph->frag_off;
-	sk_buff_data_t old_transport_header = skb->transport_header;
 	struct iphdr  *iph;			/* Our new IP header */
 	unsigned int max_headroom;		/* The extra header space needed */
 	int    mtu;
+	int ret;
 
 	EnterFunction(10);
 
-	if (skb->protocol != htons(ETH_P_IP)) {
-		IP_VS_DBG_RL("%s(): protocol error, "
-			     "ETH_P_IP: %d, skb protocol: %d\n",
-			     __func__, htons(ETH_P_IP), skb->protocol);
-		goto tx_error;
-	}
-
-	if (!(rt = __ip_vs_get_out_rt(cp, RT_TOS(tos))))
+	if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
+				      RT_TOS(tos), 1|2)))
 		goto tx_error_icmp;
+	if (rt->rt_flags & RTCF_LOCAL) {
+		ip_rt_put(rt);
+		IP_VS_XMIT(NFPROTO_IPV4, skb, cp, 1);
+	}
 
 	tdev = rt->dst.dev;
 
 	mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr);
 	if (mtu < 68) {
-		ip_rt_put(rt);
 		IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__);
-		goto tx_error;
+		goto tx_error_put;
 	}
 	if (skb_dst(skb))
 		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
@@ -600,9 +793,8 @@
 	if ((old_iph->frag_off & htons(IP_DF))
 	    && mtu < ntohs(old_iph->tot_len)) {
 		icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
-		ip_rt_put(rt);
 		IP_VS_DBG_RL("%s(): frag needed\n", __func__);
-		goto tx_error;
+		goto tx_error_put;
 	}
 
 	/*
@@ -625,7 +817,7 @@
 		old_iph = ip_hdr(skb);
 	}
 
-	skb->transport_header = old_transport_header;
+	skb->transport_header = skb->network_header;
 
 	/* fix old IP header checksum */
 	ip_send_check(old_iph);
@@ -655,7 +847,11 @@
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-	ip_local_out(skb);
+	ret = IP_VS_XMIT_TUNNEL(skb, cp);
+	if (ret == NF_ACCEPT)
+		ip_local_out(skb);
+	else if (ret == NF_DROP)
+		kfree_skb(skb);
 
 	LeaveFunction(10);
 
@@ -667,6 +863,9 @@
 	kfree_skb(skb);
 	LeaveFunction(10);
 	return NF_STOLEN;
+tx_error_put:
+	ip_rt_put(rt);
+	goto tx_error;
 }
 
 #ifdef CONFIG_IP_VS_IPV6
@@ -675,43 +874,44 @@
 		     struct ip_vs_protocol *pp)
 {
 	struct rt6_info *rt;		/* Route to the other host */
+	struct in6_addr saddr;		/* Source for tunnel */
 	struct net_device *tdev;	/* Device to other host */
 	struct ipv6hdr  *old_iph = ipv6_hdr(skb);
-	sk_buff_data_t old_transport_header = skb->transport_header;
 	struct ipv6hdr  *iph;		/* Our new IP header */
 	unsigned int max_headroom;	/* The extra header space needed */
 	int    mtu;
+	int ret;
 
 	EnterFunction(10);
 
-	if (skb->protocol != htons(ETH_P_IPV6)) {
-		IP_VS_DBG_RL("%s(): protocol error, "
-			     "ETH_P_IPV6: %d, skb protocol: %d\n",
-			     __func__, htons(ETH_P_IPV6), skb->protocol);
-		goto tx_error;
-	}
-
-	rt = __ip_vs_get_out_rt_v6(cp);
-	if (!rt)
+	if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6,
+					 &saddr, 1, 1|2)))
 		goto tx_error_icmp;
+	if (__ip_vs_is_local_route6(rt)) {
+		dst_release(&rt->dst);
+		IP_VS_XMIT(NFPROTO_IPV6, skb, cp, 1);
+	}
 
 	tdev = rt->dst.dev;
 
 	mtu = dst_mtu(&rt->dst) - sizeof(struct ipv6hdr);
-	/* TODO IPv6: do we need this check in IPv6? */
-	if (mtu < 1280) {
-		dst_release(&rt->dst);
-		IP_VS_DBG_RL("%s(): mtu less than 1280\n", __func__);
-		goto tx_error;
+	if (mtu < IPV6_MIN_MTU) {
+		IP_VS_DBG_RL("%s(): mtu less than %d\n", __func__,
+			     IPV6_MIN_MTU);
+		goto tx_error_put;
 	}
 	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 (!skb->dev) {
+			struct net *net = dev_net(skb_dst(skb)->dev);
+
+			skb->dev = net->loopback_dev;
+		}
 		icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
-		dst_release(&rt->dst);
 		IP_VS_DBG_RL("%s(): frag needed\n", __func__);
-		goto tx_error;
+		goto tx_error_put;
 	}
 
 	/*
@@ -734,7 +934,7 @@
 		old_iph = ipv6_hdr(skb);
 	}
 
-	skb->transport_header = old_transport_header;
+	skb->transport_header = skb->network_header;
 
 	skb_push(skb, sizeof(struct ipv6hdr));
 	skb_reset_network_header(skb);
@@ -754,14 +954,18 @@
 	be16_add_cpu(&iph->payload_len, sizeof(*old_iph));
 	iph->priority		=	old_iph->priority;
 	memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl));
-	iph->daddr		=	rt->rt6i_dst.addr;
-	iph->saddr		=	cp->vaddr.in6; /* rt->rt6i_src.addr; */
+	ipv6_addr_copy(&iph->daddr, &cp->daddr.in6);
+	ipv6_addr_copy(&iph->saddr, &saddr);
 	iph->hop_limit		=	old_iph->hop_limit;
 
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-	ip6_local_out(skb);
+	ret = IP_VS_XMIT_TUNNEL(skb, cp);
+	if (ret == NF_ACCEPT)
+		ip6_local_out(skb);
+	else if (ret == NF_DROP)
+		kfree_skb(skb);
 
 	LeaveFunction(10);
 
@@ -773,6 +977,9 @@
 	kfree_skb(skb);
 	LeaveFunction(10);
 	return NF_STOLEN;
+tx_error_put:
+	dst_release(&rt->dst);
+	goto tx_error;
 }
 #endif
 
@@ -791,8 +998,13 @@
 
 	EnterFunction(10);
 
-	if (!(rt = __ip_vs_get_out_rt(cp, RT_TOS(iph->tos))))
+	if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
+				      RT_TOS(iph->tos), 1|2)))
 		goto tx_error_icmp;
+	if (rt->rt_flags & RTCF_LOCAL) {
+		ip_rt_put(rt);
+		IP_VS_XMIT(NFPROTO_IPV4, skb, cp, 1);
+	}
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
@@ -820,7 +1032,7 @@
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-	IP_VS_XMIT(NFPROTO_IPV4, skb, rt);
+	IP_VS_XMIT(NFPROTO_IPV4, skb, cp, 0);
 
 	LeaveFunction(10);
 	return NF_STOLEN;
@@ -843,13 +1055,22 @@
 
 	EnterFunction(10);
 
-	rt = __ip_vs_get_out_rt_v6(cp);
-	if (!rt)
+	if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL,
+					 0, 1|2)))
 		goto tx_error_icmp;
+	if (__ip_vs_is_local_route6(rt)) {
+		dst_release(&rt->dst);
+		IP_VS_XMIT(NFPROTO_IPV6, skb, cp, 1);
+	}
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
 	if (skb->len > mtu) {
+		if (!skb->dev) {
+			struct net *net = dev_net(skb_dst(skb)->dev);
+
+			skb->dev = net->loopback_dev;
+		}
 		icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
 		dst_release(&rt->dst);
 		IP_VS_DBG_RL("%s(): frag needed\n", __func__);
@@ -873,7 +1094,7 @@
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-	IP_VS_XMIT(NFPROTO_IPV6, skb, rt);
+	IP_VS_XMIT(NFPROTO_IPV6, skb, cp, 0);
 
 	LeaveFunction(10);
 	return NF_STOLEN;
@@ -899,6 +1120,7 @@
 	struct rtable	*rt;	/* Route to the other host */
 	int mtu;
 	int rc;
+	int local;
 
 	EnterFunction(10);
 
@@ -919,16 +1141,43 @@
 	 * mangle and send the packet here (only for VS/NAT)
 	 */
 
-	if (!(rt = __ip_vs_get_out_rt(cp, RT_TOS(ip_hdr(skb)->tos))))
+	if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
+				      RT_TOS(ip_hdr(skb)->tos), 1|2|4)))
 		goto tx_error_icmp;
+	local = rt->rt_flags & RTCF_LOCAL;
+
+	/*
+	 * Avoid duplicate tuple in reply direction for NAT traffic
+	 * to local address when connection is sync-ed
+	 */
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+	if (cp->flags & IP_VS_CONN_F_SYNC && local) {
+		enum ip_conntrack_info ctinfo;
+		struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+
+		if (ct && !nf_ct_is_untracked(ct)) {
+			IP_VS_DBG(10, "%s(): "
+				  "stopping DNAT to local address %pI4\n",
+				  __func__, &cp->daddr.ip);
+			goto tx_error_put;
+		}
+	}
+#endif
+
+	/* From world but DNAT to loopback address? */
+	if (local && ipv4_is_loopback(rt->rt_dst) && skb_rtable(skb)->fl.iif) {
+		IP_VS_DBG(1, "%s(): "
+			  "stopping DNAT to loopback %pI4\n",
+			  __func__, &cp->daddr.ip);
+		goto tx_error_put;
+	}
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
 	if ((skb->len > mtu) && (ip_hdr(skb)->frag_off & htons(IP_DF))) {
-		ip_rt_put(rt);
 		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
 		IP_VS_DBG_RL("%s(): frag needed\n", __func__);
-		goto tx_error;
+		goto tx_error_put;
 	}
 
 	/* copy-on-write the packet before mangling it */
@@ -938,16 +1187,27 @@
 	if (skb_cow(skb, rt->dst.dev->hard_header_len))
 		goto tx_error_put;
 
-	/* drop the old route when skb is not shared */
-	skb_dst_drop(skb);
-	skb_dst_set(skb, &rt->dst);
-
 	ip_vs_nat_icmp(skb, pp, cp, 0);
 
+	if (!local) {
+		/* drop the old route when skb is not shared */
+		skb_dst_drop(skb);
+		skb_dst_set(skb, &rt->dst);
+	} else {
+		ip_rt_put(rt);
+		/*
+		 * Some IPv4 replies get local address from routes,
+		 * not from iph, so while we DNAT after routing
+		 * we need this second input/output route.
+		 */
+		if (!__ip_vs_reroute_locally(skb))
+			goto tx_error;
+	}
+
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-	IP_VS_XMIT(NFPROTO_IPV4, skb, rt);
+	IP_VS_XMIT_NAT(NFPROTO_IPV4, skb, cp, local);
 
 	rc = NF_STOLEN;
 	goto out;
@@ -973,6 +1233,7 @@
 	struct rt6_info	*rt;	/* Route to the other host */
 	int mtu;
 	int rc;
+	int local;
 
 	EnterFunction(10);
 
@@ -993,17 +1254,49 @@
 	 * mangle and send the packet here (only for VS/NAT)
 	 */
 
-	rt = __ip_vs_get_out_rt_v6(cp);
-	if (!rt)
+	if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL,
+					 0, 1|2|4)))
 		goto tx_error_icmp;
 
+	local = __ip_vs_is_local_route6(rt);
+	/*
+	 * Avoid duplicate tuple in reply direction for NAT traffic
+	 * to local address when connection is sync-ed
+	 */
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+	if (cp->flags & IP_VS_CONN_F_SYNC && local) {
+		enum ip_conntrack_info ctinfo;
+		struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+
+		if (ct && !nf_ct_is_untracked(ct)) {
+			IP_VS_DBG(10, "%s(): "
+				  "stopping DNAT to local address %pI6\n",
+				  __func__, &cp->daddr.in6);
+			goto tx_error_put;
+		}
+	}
+#endif
+
+	/* From world but DNAT to loopback address? */
+	if (local && skb->dev && !(skb->dev->flags & IFF_LOOPBACK) &&
+	    ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_LOOPBACK) {
+		IP_VS_DBG(1, "%s(): "
+			  "stopping DNAT to loopback %pI6\n",
+			  __func__, &cp->daddr.in6);
+		goto tx_error_put;
+	}
+
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
 	if (skb->len > mtu) {
-		dst_release(&rt->dst);
+		if (!skb->dev) {
+			struct net *net = dev_net(skb_dst(skb)->dev);
+
+			skb->dev = net->loopback_dev;
+		}
 		icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
 		IP_VS_DBG_RL("%s(): frag needed\n", __func__);
-		goto tx_error;
+		goto tx_error_put;
 	}
 
 	/* copy-on-write the packet before mangling it */
@@ -1013,16 +1306,21 @@
 	if (skb_cow(skb, rt->dst.dev->hard_header_len))
 		goto tx_error_put;
 
-	/* drop the old route when skb is not shared */
-	skb_dst_drop(skb);
-	skb_dst_set(skb, &rt->dst);
-
 	ip_vs_nat_icmp_v6(skb, pp, cp, 0);
 
+	if (!local || !skb->dev) {
+		/* drop the old route when skb is not shared */
+		skb_dst_drop(skb);
+		skb_dst_set(skb, &rt->dst);
+	} else {
+		/* destined to loopback, do we need to change route? */
+		dst_release(&rt->dst);
+	}
+
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-	IP_VS_XMIT(NFPROTO_IPV6, skb, rt);
+	IP_VS_XMIT_NAT(NFPROTO_IPV6, skb, cp, local);
 
 	rc = NF_STOLEN;
 	goto out;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index df3eedb..1eacf8d 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -65,32 +65,42 @@
 DEFINE_PER_CPU(struct nf_conn, nf_conntrack_untracked);
 EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked);
 
-static int nf_conntrack_hash_rnd_initted;
-static unsigned int nf_conntrack_hash_rnd;
+static unsigned int nf_conntrack_hash_rnd __read_mostly;
 
-static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple,
-				  u16 zone, unsigned int size, unsigned int rnd)
+static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, u16 zone)
 {
 	unsigned int n;
-	u_int32_t h;
 
 	/* The direction must be ignored, so we hash everything up to the
 	 * destination ports (which is a multiple of 4) and treat the last
 	 * three bytes manually.
 	 */
 	n = (sizeof(tuple->src) + sizeof(tuple->dst.u3)) / sizeof(u32);
-	h = jhash2((u32 *)tuple, n,
-		   zone ^ rnd ^ (((__force __u16)tuple->dst.u.all << 16) |
-				 tuple->dst.protonum));
+	return jhash2((u32 *)tuple, n, zone ^ nf_conntrack_hash_rnd ^
+		      (((__force __u16)tuple->dst.u.all << 16) |
+		      tuple->dst.protonum));
+}
 
-	return ((u64)h * size) >> 32;
+static u32 __hash_bucket(u32 hash, unsigned int size)
+{
+	return ((u64)hash * size) >> 32;
+}
+
+static u32 hash_bucket(u32 hash, const struct net *net)
+{
+	return __hash_bucket(hash, net->ct.htable_size);
+}
+
+static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple,
+				  u16 zone, unsigned int size)
+{
+	return __hash_bucket(hash_conntrack_raw(tuple, zone), size);
 }
 
 static inline u_int32_t hash_conntrack(const struct net *net, u16 zone,
 				       const struct nf_conntrack_tuple *tuple)
 {
-	return __hash_conntrack(tuple, zone, net->ct.htable_size,
-				nf_conntrack_hash_rnd);
+	return __hash_conntrack(tuple, zone, net->ct.htable_size);
 }
 
 bool
@@ -292,20 +302,20 @@
  * OR
  * - Caller must lock nf_conntrack_lock before calling this function
  */
-struct nf_conntrack_tuple_hash *
-__nf_conntrack_find(struct net *net, u16 zone,
-		    const struct nf_conntrack_tuple *tuple)
+static struct nf_conntrack_tuple_hash *
+____nf_conntrack_find(struct net *net, u16 zone,
+		      const struct nf_conntrack_tuple *tuple, u32 hash)
 {
 	struct nf_conntrack_tuple_hash *h;
 	struct hlist_nulls_node *n;
-	unsigned int hash = hash_conntrack(net, zone, tuple);
+	unsigned int bucket = hash_bucket(hash, net);
 
 	/* Disable BHs the entire time since we normally need to disable them
 	 * at least once for the stats anyway.
 	 */
 	local_bh_disable();
 begin:
-	hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) {
+	hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[bucket], hnnode) {
 		if (nf_ct_tuple_equal(tuple, &h->tuple) &&
 		    nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) {
 			NF_CT_STAT_INC(net, found);
@@ -319,7 +329,7 @@
 	 * not the expected one, we must restart lookup.
 	 * We probably met an item that was moved to another chain.
 	 */
-	if (get_nulls_value(n) != hash) {
+	if (get_nulls_value(n) != bucket) {
 		NF_CT_STAT_INC(net, search_restart);
 		goto begin;
 	}
@@ -327,19 +337,27 @@
 
 	return NULL;
 }
+
+struct nf_conntrack_tuple_hash *
+__nf_conntrack_find(struct net *net, u16 zone,
+		    const struct nf_conntrack_tuple *tuple)
+{
+	return ____nf_conntrack_find(net, zone, tuple,
+				     hash_conntrack_raw(tuple, zone));
+}
 EXPORT_SYMBOL_GPL(__nf_conntrack_find);
 
 /* Find a connection corresponding to a tuple. */
-struct nf_conntrack_tuple_hash *
-nf_conntrack_find_get(struct net *net, u16 zone,
-		      const struct nf_conntrack_tuple *tuple)
+static struct nf_conntrack_tuple_hash *
+__nf_conntrack_find_get(struct net *net, u16 zone,
+			const struct nf_conntrack_tuple *tuple, u32 hash)
 {
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conn *ct;
 
 	rcu_read_lock();
 begin:
-	h = __nf_conntrack_find(net, zone, tuple);
+	h = ____nf_conntrack_find(net, zone, tuple, hash);
 	if (h) {
 		ct = nf_ct_tuplehash_to_ctrack(h);
 		if (unlikely(nf_ct_is_dying(ct) ||
@@ -357,6 +375,14 @@
 
 	return h;
 }
+
+struct nf_conntrack_tuple_hash *
+nf_conntrack_find_get(struct net *net, u16 zone,
+		      const struct nf_conntrack_tuple *tuple)
+{
+	return __nf_conntrack_find_get(net, zone, tuple,
+				       hash_conntrack_raw(tuple, zone));
+}
 EXPORT_SYMBOL_GPL(nf_conntrack_find_get);
 
 static void __nf_conntrack_hash_insert(struct nf_conn *ct,
@@ -409,8 +435,11 @@
 		return NF_ACCEPT;
 
 	zone = nf_ct_zone(ct);
-	hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-	repl_hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+	/* reuse the hash saved before */
+	hash = *(unsigned long *)&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev;
+	hash = hash_bucket(hash, net);
+	repl_hash = hash_conntrack(net, zone,
+				   &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
 
 	/* We're not in hash table, and we refuse to set up related
 	   connections for unconfirmed conns.  But packet copies and
@@ -567,17 +596,29 @@
 	return dropped;
 }
 
-struct nf_conn *nf_conntrack_alloc(struct net *net, u16 zone,
-				   const struct nf_conntrack_tuple *orig,
-				   const struct nf_conntrack_tuple *repl,
-				   gfp_t gfp)
+static struct nf_conn *
+__nf_conntrack_alloc(struct net *net, u16 zone,
+		     const struct nf_conntrack_tuple *orig,
+		     const struct nf_conntrack_tuple *repl,
+		     gfp_t gfp, u32 hash)
 {
 	struct nf_conn *ct;
 
-	if (unlikely(!nf_conntrack_hash_rnd_initted)) {
-		get_random_bytes(&nf_conntrack_hash_rnd,
-				sizeof(nf_conntrack_hash_rnd));
-		nf_conntrack_hash_rnd_initted = 1;
+	if (unlikely(!nf_conntrack_hash_rnd)) {
+		unsigned int rand;
+
+		/*
+		 * Why not initialize nf_conntrack_rnd in a "init()" function ?
+		 * Because there isn't enough entropy when system initializing,
+		 * and we initialize it as late as possible.
+		 */
+		do {
+			get_random_bytes(&rand, sizeof(rand));
+		} while (!rand);
+		cmpxchg(&nf_conntrack_hash_rnd, 0, rand);
+
+		/* recompute the hash as nf_conntrack_hash_rnd is initialized */
+		hash = hash_conntrack_raw(orig, zone);
 	}
 
 	/* We don't want any race condition at early drop stage */
@@ -585,8 +626,7 @@
 
 	if (nf_conntrack_max &&
 	    unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) {
-		unsigned int hash = hash_conntrack(net, zone, orig);
-		if (!early_drop(net, hash)) {
+		if (!early_drop(net, hash_bucket(hash, net))) {
 			atomic_dec(&net->ct.count);
 			if (net_ratelimit())
 				printk(KERN_WARNING
@@ -616,7 +656,8 @@
 	ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
 	ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL;
 	ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl;
-	ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev = NULL;
+	/* save hash for reusing when confirming */
+	*(unsigned long *)(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev) = hash;
 	/* Don't set timer yet: wait for confirmation */
 	setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct);
 	write_pnet(&ct->ct_net, net);
@@ -643,6 +684,14 @@
 	return ERR_PTR(-ENOMEM);
 #endif
 }
+
+struct nf_conn *nf_conntrack_alloc(struct net *net, u16 zone,
+				   const struct nf_conntrack_tuple *orig,
+				   const struct nf_conntrack_tuple *repl,
+				   gfp_t gfp)
+{
+	return __nf_conntrack_alloc(net, zone, orig, repl, gfp, 0);
+}
 EXPORT_SYMBOL_GPL(nf_conntrack_alloc);
 
 void nf_conntrack_free(struct nf_conn *ct)
@@ -664,7 +713,7 @@
 	       struct nf_conntrack_l3proto *l3proto,
 	       struct nf_conntrack_l4proto *l4proto,
 	       struct sk_buff *skb,
-	       unsigned int dataoff)
+	       unsigned int dataoff, u32 hash)
 {
 	struct nf_conn *ct;
 	struct nf_conn_help *help;
@@ -678,7 +727,8 @@
 		return NULL;
 	}
 
-	ct = nf_conntrack_alloc(net, zone, tuple, &repl_tuple, GFP_ATOMIC);
+	ct = __nf_conntrack_alloc(net, zone, tuple, &repl_tuple, GFP_ATOMIC,
+				  hash);
 	if (IS_ERR(ct)) {
 		pr_debug("Can't allocate conntrack.\n");
 		return (struct nf_conntrack_tuple_hash *)ct;
@@ -755,6 +805,7 @@
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conn *ct;
 	u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE;
+	u32 hash;
 
 	if (!nf_ct_get_tuple(skb, skb_network_offset(skb),
 			     dataoff, l3num, protonum, &tuple, l3proto,
@@ -764,10 +815,11 @@
 	}
 
 	/* look for tuple match */
-	h = nf_conntrack_find_get(net, zone, &tuple);
+	hash = hash_conntrack_raw(&tuple, zone);
+	h = __nf_conntrack_find_get(net, zone, &tuple, hash);
 	if (!h) {
 		h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto,
-				   skb, dataoff);
+				   skb, dataoff, hash);
 		if (!h)
 			return NULL;
 		if (IS_ERR(h))
@@ -1307,8 +1359,7 @@
 			ct = nf_ct_tuplehash_to_ctrack(h);
 			hlist_nulls_del_rcu(&h->hnnode);
 			bucket = __hash_conntrack(&h->tuple, nf_ct_zone(ct),
-						  hashsize,
-						  nf_conntrack_hash_rnd);
+						  hashsize);
 			hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]);
 		}
 	}
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index cdcc764..5702de3 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -26,10 +26,10 @@
 
 static DEFINE_MUTEX(nf_ct_ecache_mutex);
 
-struct nf_ct_event_notifier *nf_conntrack_event_cb __read_mostly;
+struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb __read_mostly;
 EXPORT_SYMBOL_GPL(nf_conntrack_event_cb);
 
-struct nf_exp_event_notifier *nf_expect_event_cb __read_mostly;
+struct nf_exp_event_notifier __rcu *nf_expect_event_cb __read_mostly;
 EXPORT_SYMBOL_GPL(nf_expect_event_cb);
 
 /* deliver cached events and clear cache entry - must be called with locally
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index acb29cc..46e8966 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -38,25 +38,30 @@
 
 static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
 
+static HLIST_HEAD(nf_ct_userspace_expect_list);
+
 /* nf_conntrack_expect helper functions */
-void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
+void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
+				u32 pid, int report)
 {
 	struct nf_conn_help *master_help = nfct_help(exp->master);
 	struct net *net = nf_ct_exp_net(exp);
 
-	NF_CT_ASSERT(master_help);
 	NF_CT_ASSERT(!timer_pending(&exp->timeout));
 
 	hlist_del_rcu(&exp->hnode);
 	net->ct.expect_count--;
 
 	hlist_del(&exp->lnode);
-	master_help->expecting[exp->class]--;
+	if (!(exp->flags & NF_CT_EXPECT_USERSPACE))
+		master_help->expecting[exp->class]--;
+
+	nf_ct_expect_event_report(IPEXP_DESTROY, exp, pid, report);
 	nf_ct_expect_put(exp);
 
 	NF_CT_STAT_INC(net, expect_delete);
 }
-EXPORT_SYMBOL_GPL(nf_ct_unlink_expect);
+EXPORT_SYMBOL_GPL(nf_ct_unlink_expect_report);
 
 static void nf_ct_expectation_timed_out(unsigned long ul_expect)
 {
@@ -320,16 +325,21 @@
 
 	atomic_inc(&exp->use);
 
-	hlist_add_head(&exp->lnode, &master_help->expectations);
-	master_help->expecting[exp->class]++;
+	if (master_help) {
+		hlist_add_head(&exp->lnode, &master_help->expectations);
+		master_help->expecting[exp->class]++;
+	} else if (exp->flags & NF_CT_EXPECT_USERSPACE)
+		hlist_add_head(&exp->lnode, &nf_ct_userspace_expect_list);
 
 	hlist_add_head_rcu(&exp->hnode, &net->ct.expect_hash[h]);
 	net->ct.expect_count++;
 
 	setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
 		    (unsigned long)exp);
-	p = &master_help->helper->expect_policy[exp->class];
-	exp->timeout.expires = jiffies + p->timeout * HZ;
+	if (master_help) {
+		p = &master_help->helper->expect_policy[exp->class];
+		exp->timeout.expires = jiffies + p->timeout * HZ;
+	}
 	add_timer(&exp->timeout);
 
 	atomic_inc(&exp->use);
@@ -380,7 +390,9 @@
 	unsigned int h;
 	int ret = 1;
 
-	if (!master_help->helper) {
+	/* Don't allow expectations created from kernel-space with no helper */
+	if (!(expect->flags & NF_CT_EXPECT_USERSPACE) &&
+	    (!master_help || (master_help && !master_help->helper))) {
 		ret = -ESHUTDOWN;
 		goto out;
 	}
@@ -398,13 +410,16 @@
 		}
 	}
 	/* Will be over limit? */
-	p = &master_help->helper->expect_policy[expect->class];
-	if (p->max_expected &&
-	    master_help->expecting[expect->class] >= p->max_expected) {
-		evict_oldest_expect(master, expect);
-		if (master_help->expecting[expect->class] >= p->max_expected) {
-			ret = -EMFILE;
-			goto out;
+	if (master_help) {
+		p = &master_help->helper->expect_policy[expect->class];
+		if (p->max_expected &&
+		    master_help->expecting[expect->class] >= p->max_expected) {
+			evict_oldest_expect(master, expect);
+			if (master_help->expecting[expect->class]
+						>= p->max_expected) {
+				ret = -EMFILE;
+				goto out;
+			}
 		}
 	}
 
@@ -439,6 +454,21 @@
 }
 EXPORT_SYMBOL_GPL(nf_ct_expect_related_report);
 
+void nf_ct_remove_userspace_expectations(void)
+{
+	struct nf_conntrack_expect *exp;
+	struct hlist_node *n, *next;
+
+	hlist_for_each_entry_safe(exp, n, next,
+				  &nf_ct_userspace_expect_list, lnode) {
+		if (del_timer(&exp->timeout)) {
+			nf_ct_unlink_expect(exp);
+			nf_ct_expect_put(exp);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(nf_ct_remove_userspace_expectations);
+
 #ifdef CONFIG_PROC_FS
 struct ct_expect_iter_state {
 	struct seq_net_private p;
@@ -529,8 +559,12 @@
 		seq_printf(s, "PERMANENT");
 		delim = ",";
 	}
-	if (expect->flags & NF_CT_EXPECT_INACTIVE)
+	if (expect->flags & NF_CT_EXPECT_INACTIVE) {
 		seq_printf(s, "%sINACTIVE", delim);
+		delim = ",";
+	}
+	if (expect->flags & NF_CT_EXPECT_USERSPACE)
+		seq_printf(s, "%sUSERSPACE", delim);
 
 	helper = rcu_dereference(nfct_help(expect->master)->helper);
 	if (helper) {
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
index 7dcf7a4..bd82450 100644
--- a/net/netfilter/nf_conntrack_extend.c
+++ b/net/netfilter/nf_conntrack_extend.c
@@ -16,7 +16,7 @@
 #include <linux/skbuff.h>
 #include <net/netfilter/nf_conntrack_extend.h>
 
-static struct nf_ct_ext_type *nf_ct_ext_types[NF_CT_EXT_NUM];
+static struct nf_ct_ext_type __rcu *nf_ct_ext_types[NF_CT_EXT_NUM];
 static DEFINE_MUTEX(nf_ct_ext_type_mutex);
 
 void __nf_ct_ext_destroy(struct nf_conn *ct)
@@ -48,15 +48,17 @@
 {
 	unsigned int off, len;
 	struct nf_ct_ext_type *t;
+	size_t alloc_size;
 
 	rcu_read_lock();
 	t = rcu_dereference(nf_ct_ext_types[id]);
 	BUG_ON(t == NULL);
 	off = ALIGN(sizeof(struct nf_ct_ext), t->align);
 	len = off + t->len;
+	alloc_size = t->alloc_size;
 	rcu_read_unlock();
 
-	*ext = kzalloc(t->alloc_size, gfp);
+	*ext = kzalloc(alloc_size, gfp);
 	if (!*ext)
 		return NULL;
 
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 5bae1cd..b729ace 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -22,6 +22,7 @@
 #include <linux/rculist_nulls.h>
 #include <linux/types.h>
 #include <linux/timer.h>
+#include <linux/security.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
 #include <linux/netlink.h>
@@ -245,16 +246,31 @@
 
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 static inline int
-ctnetlink_dump_secmark(struct sk_buff *skb, const struct nf_conn *ct)
+ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
 {
-	NLA_PUT_BE32(skb, CTA_SECMARK, htonl(ct->secmark));
-	return 0;
+	struct nlattr *nest_secctx;
+	int len, ret;
+	char *secctx;
 
+	ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+	if (ret)
+		return ret;
+
+	ret = -1;
+	nest_secctx = nla_nest_start(skb, CTA_SECCTX | NLA_F_NESTED);
+	if (!nest_secctx)
+		goto nla_put_failure;
+
+	NLA_PUT_STRING(skb, CTA_SECCTX_NAME, secctx);
+	nla_nest_end(skb, nest_secctx);
+
+	ret = 0;
 nla_put_failure:
-	return -1;
+	security_release_secctx(secctx, len);
+	return ret;
 }
 #else
-#define ctnetlink_dump_secmark(a, b) (0)
+#define ctnetlink_dump_secctx(a, b) (0)
 #endif
 
 #define master_tuple(ct) &(ct->master->tuplehash[IP_CT_DIR_ORIGINAL].tuple)
@@ -391,7 +407,7 @@
 	    ctnetlink_dump_protoinfo(skb, ct) < 0 ||
 	    ctnetlink_dump_helpinfo(skb, ct) < 0 ||
 	    ctnetlink_dump_mark(skb, ct) < 0 ||
-	    ctnetlink_dump_secmark(skb, ct) < 0 ||
+	    ctnetlink_dump_secctx(skb, ct) < 0 ||
 	    ctnetlink_dump_id(skb, ct) < 0 ||
 	    ctnetlink_dump_use(skb, ct) < 0 ||
 	    ctnetlink_dump_master(skb, ct) < 0 ||
@@ -437,6 +453,17 @@
 	       ;
 }
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+static int ctnetlink_nlmsg_secctx_size(const struct nf_conn *ct)
+{
+	int len;
+
+	security_secid_to_secctx(ct->secmark, NULL, &len);
+
+	return sizeof(char) * len;
+}
+#endif
+
 static inline size_t
 ctnetlink_nlmsg_size(const struct nf_conn *ct)
 {
@@ -453,7 +480,8 @@
 	       + nla_total_size(0) /* CTA_HELP */
 	       + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
-	       + nla_total_size(sizeof(u_int32_t)) /* CTA_SECMARK */
+	       + nla_total_size(0) /* CTA_SECCTX */
+	       + nla_total_size(ctnetlink_nlmsg_secctx_size(ct)) /* CTA_SECCTX_NAME */
 #endif
 #ifdef CONFIG_NF_NAT_NEEDED
 	       + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */
@@ -556,7 +584,7 @@
 
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 		if ((events & (1 << IPCT_SECMARK) || ct->secmark)
-		    && ctnetlink_dump_secmark(skb, ct) < 0)
+		    && ctnetlink_dump_secctx(skb, ct) < 0)
 			goto nla_put_failure;
 #endif
 
@@ -1560,8 +1588,8 @@
 			  const struct nf_conntrack_expect *exp)
 {
 	struct nf_conn *master = exp->master;
-	struct nf_conntrack_helper *helper;
 	long timeout = (exp->timeout.expires - jiffies) / HZ;
+	struct nf_conn_help *help;
 
 	if (timeout < 0)
 		timeout = 0;
@@ -1577,9 +1605,15 @@
 
 	NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout));
 	NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp));
-	helper = rcu_dereference(nfct_help(master)->helper);
-	if (helper)
-		NLA_PUT_STRING(skb, CTA_EXPECT_HELP_NAME, helper->name);
+	NLA_PUT_BE32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags));
+	help = nfct_help(master);
+	if (help) {
+		struct nf_conntrack_helper *helper;
+
+		helper = rcu_dereference(help->helper);
+		if (helper)
+			NLA_PUT_STRING(skb, CTA_EXPECT_HELP_NAME, helper->name);
+	}
 
 	return 0;
 
@@ -1626,17 +1660,20 @@
 	struct nlmsghdr *nlh;
 	struct nfgenmsg *nfmsg;
 	struct sk_buff *skb;
-	unsigned int type;
+	unsigned int type, group;
 	int flags = 0;
 
-	if (events & (1 << IPEXP_NEW)) {
+	if (events & (1 << IPEXP_DESTROY)) {
+		type = IPCTNL_MSG_EXP_DELETE;
+		group = NFNLGRP_CONNTRACK_EXP_DESTROY;
+	} else if (events & (1 << IPEXP_NEW)) {
 		type = IPCTNL_MSG_EXP_NEW;
 		flags = NLM_F_CREATE|NLM_F_EXCL;
+		group = NFNLGRP_CONNTRACK_EXP_NEW;
 	} else
 		return 0;
 
-	if (!item->report &&
-	    !nfnetlink_has_listeners(net, NFNLGRP_CONNTRACK_EXP_NEW))
+	if (!item->report && !nfnetlink_has_listeners(net, group))
 		return 0;
 
 	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
@@ -1659,8 +1696,7 @@
 	rcu_read_unlock();
 
 	nlmsg_end(skb, nlh);
-	nfnetlink_send(skb, net, item->pid, NFNLGRP_CONNTRACK_EXP_NEW,
-		       item->report, GFP_ATOMIC);
+	nfnetlink_send(skb, net, item->pid, group, item->report, GFP_ATOMIC);
 	return 0;
 
 nla_put_failure:
@@ -1733,6 +1769,8 @@
 	[CTA_EXPECT_TIMEOUT]	= { .type = NLA_U32 },
 	[CTA_EXPECT_ID]		= { .type = NLA_U32 },
 	[CTA_EXPECT_HELP_NAME]	= { .type = NLA_NUL_STRING },
+	[CTA_EXPECT_ZONE]	= { .type = NLA_U16 },
+	[CTA_EXPECT_FLAGS]	= { .type = NLA_U32 },
 };
 
 static int
@@ -1841,7 +1879,13 @@
 		}
 
 		/* after list removal, usage count == 1 */
-		nf_ct_unexpect_related(exp);
+		spin_lock_bh(&nf_conntrack_lock);
+		if (del_timer(&exp->timeout)) {
+			nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).pid,
+						   nlmsg_report(nlh));
+			nf_ct_expect_put(exp);
+		}
+		spin_unlock_bh(&nf_conntrack_lock);
 		/* have to put what we 'get' above.
 		 * after this line usage count == 0 */
 		nf_ct_expect_put(exp);
@@ -1858,7 +1902,9 @@
 				m_help = nfct_help(exp->master);
 				if (!strcmp(m_help->helper->name, name) &&
 				    del_timer(&exp->timeout)) {
-					nf_ct_unlink_expect(exp);
+					nf_ct_unlink_expect_report(exp,
+							NETLINK_CB(skb).pid,
+							nlmsg_report(nlh));
 					nf_ct_expect_put(exp);
 				}
 			}
@@ -1872,7 +1918,9 @@
 						  &net->ct.expect_hash[i],
 						  hnode) {
 				if (del_timer(&exp->timeout)) {
-					nf_ct_unlink_expect(exp);
+					nf_ct_unlink_expect_report(exp,
+							NETLINK_CB(skb).pid,
+							nlmsg_report(nlh));
 					nf_ct_expect_put(exp);
 				}
 			}
@@ -1918,23 +1966,35 @@
 	if (!h)
 		return -ENOENT;
 	ct = nf_ct_tuplehash_to_ctrack(h);
-	help = nfct_help(ct);
-
-	if (!help || !help->helper) {
-		/* such conntrack hasn't got any helper, abort */
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
 	exp = nf_ct_expect_alloc(ct);
 	if (!exp) {
 		err = -ENOMEM;
 		goto out;
 	}
+	help = nfct_help(ct);
+	if (!help) {
+		if (!cda[CTA_EXPECT_TIMEOUT]) {
+			err = -EINVAL;
+			goto out;
+		}
+		exp->timeout.expires =
+		  jiffies + ntohl(nla_get_be32(cda[CTA_EXPECT_TIMEOUT])) * HZ;
+
+		exp->flags = NF_CT_EXPECT_USERSPACE;
+		if (cda[CTA_EXPECT_FLAGS]) {
+			exp->flags |=
+				ntohl(nla_get_be32(cda[CTA_EXPECT_FLAGS]));
+		}
+	} else {
+		if (cda[CTA_EXPECT_FLAGS]) {
+			exp->flags = ntohl(nla_get_be32(cda[CTA_EXPECT_FLAGS]));
+			exp->flags &= ~NF_CT_EXPECT_USERSPACE;
+		} else
+			exp->flags = 0;
+	}
 
 	exp->class = 0;
 	exp->expectfn = NULL;
-	exp->flags = 0;
 	exp->master = ct;
 	exp->helper = NULL;
 	memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
@@ -2102,6 +2162,7 @@
 {
 	pr_info("ctnetlink: unregistering from nfnetlink.\n");
 
+	nf_ct_remove_userspace_expectations();
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
 	nf_ct_expect_unregister_notifier(&ctnl_notifier_exp);
 	nf_conntrack_unregister_notifier(&ctnl_notifier);
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 5886ba1..ed6d929 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -28,8 +28,8 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 
-static struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly;
-struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX] __read_mostly;
+static struct nf_conntrack_l4proto __rcu **nf_ct_protos[PF_MAX] __read_mostly;
+struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX] __read_mostly;
 EXPORT_SYMBOL_GPL(nf_ct_l3protos);
 
 static DEFINE_MUTEX(nf_ct_proto_mutex);
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 53d8922..bcf47eb 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -130,6 +130,44 @@
 	return len;
 }
 
+static int iswordc(const char c)
+{
+	if (isalnum(c) || c == '!' || c == '"' || c == '%' ||
+	    (c >= '(' && c <= '/') || c == ':' || c == '<' || c == '>' ||
+	    c == '?' || (c >= '[' && c <= ']') || c == '_' || c == '`' ||
+	    c == '{' || c == '}' || c == '~')
+		return 1;
+	return 0;
+}
+
+static int word_len(const char *dptr, const char *limit)
+{
+	int len = 0;
+	while (dptr < limit && iswordc(*dptr)) {
+		dptr++;
+		len++;
+	}
+	return len;
+}
+
+static int callid_len(const struct nf_conn *ct, const char *dptr,
+		      const char *limit, int *shift)
+{
+	int len, domain_len;
+
+	len = word_len(dptr, limit);
+	dptr += len;
+	if (!len || dptr == limit || *dptr != '@')
+		return len;
+	dptr++;
+	len++;
+
+	domain_len = word_len(dptr, limit);
+	if (!domain_len)
+		return 0;
+	return len + domain_len;
+}
+
 /* get media type + port length */
 static int media_len(const struct nf_conn *ct, const char *dptr,
 		     const char *limit, int *shift)
@@ -152,6 +190,9 @@
 	const char *end;
 	int ret = 0;
 
+	if (!ct)
+		return 0;
+
 	memset(addr, 0, sizeof(*addr));
 	switch (nf_ct_l3num(ct)) {
 	case AF_INET:
@@ -296,6 +337,7 @@
 	[SIP_HDR_VIA_TCP]		= SIP_HDR("Via", "v", "TCP ", epaddr_len),
 	[SIP_HDR_EXPIRES]		= SIP_HDR("Expires", NULL, NULL, digits_len),
 	[SIP_HDR_CONTENT_LENGTH]	= SIP_HDR("Content-Length", "l", NULL, digits_len),
+	[SIP_HDR_CALL_ID]		= SIP_HDR("Call-Id", "i", NULL, callid_len),
 };
 
 static const char *sip_follow_continuation(const char *dptr, const char *limit)
@@ -1376,7 +1418,7 @@
 	unsigned int msglen, origlen;
 	const char *dptr, *end;
 	s16 diff, tdiff = 0;
-	int ret;
+	int ret = NF_ACCEPT;
 	typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust;
 
 	if (ctinfo != IP_CT_ESTABLISHED &&
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index eb973fc..0fb6570 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -15,6 +15,7 @@
 #include <linux/seq_file.h>
 #include <linux/percpu.h>
 #include <linux/netdevice.h>
+#include <linux/security.h>
 #include <net/net_namespace.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
@@ -108,6 +109,29 @@
 	rcu_read_unlock();
 }
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+static int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
+{
+	int ret;
+	u32 len;
+	char *secctx;
+
+	ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+	if (ret)
+		return ret;
+
+	ret = seq_printf(s, "secctx=%s ", secctx);
+
+	security_release_secctx(secctx, len);
+	return ret;
+}
+#else
+static inline int ct_show_secctx(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)
 {
@@ -168,10 +192,8 @@
 		goto release;
 #endif
 
-#ifdef CONFIG_NF_CONNTRACK_SECMARK
-	if (seq_printf(s, "secmark=%u ", ct->secmark))
+	if (ct_show_secctx(s, ct))
 		goto release;
-#endif
 
 #ifdef CONFIG_NF_CONNTRACK_ZONES
 	if (seq_printf(s, "zone=%u ", nf_ct_zone(ct)))
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 7df37fd..b07393e 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -16,7 +16,7 @@
 #define NF_LOG_PREFIXLEN		128
 #define NFLOGGER_NAME_LEN		64
 
-static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly;
+static const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO] __read_mostly;
 static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly;
 static DEFINE_MUTEX(nf_log_mutex);
 
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 78b3cf9c..74aebed5 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -18,7 +18,7 @@
  * long term mutex.  The handler must provide an an outfn() to accept packets
  * for queueing and must reinject all packets it receives, no matter what.
  */
-static const struct nf_queue_handler *queue_handler[NFPROTO_NUMPROTO] __read_mostly;
+static const struct nf_queue_handler __rcu *queue_handler[NFPROTO_NUMPROTO] __read_mostly;
 
 static DEFINE_MUTEX(queue_handler_mutex);
 
diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c
index 5490fc3..4d87bef 100644
--- a/net/netfilter/nf_tproxy_core.c
+++ b/net/netfilter/nf_tproxy_core.c
@@ -18,41 +18,6 @@
 #include <net/udp.h>
 #include <net/netfilter/nf_tproxy_core.h>
 
-struct sock *
-nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
-		      const __be32 saddr, const __be32 daddr,
-		      const __be16 sport, const __be16 dport,
-		      const struct net_device *in, bool listening_only)
-{
-	struct sock *sk;
-
-	/* look up socket */
-	switch (protocol) {
-	case IPPROTO_TCP:
-		if (listening_only)
-			sk = __inet_lookup_listener(net, &tcp_hashinfo,
-						    daddr, ntohs(dport),
-						    in->ifindex);
-		else
-			sk = __inet_lookup(net, &tcp_hashinfo,
-					   saddr, sport, daddr, dport,
-					   in->ifindex);
-		break;
-	case IPPROTO_UDP:
-		sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
-				     in->ifindex);
-		break;
-	default:
-		WARN_ON(1);
-		sk = NULL;
-	}
-
-	pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, listener only: %d, sock %p\n",
-		 protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), listening_only, sk);
-
-	return sk;
-}
-EXPORT_SYMBOL_GPL(nf_tproxy_get_sock_v4);
 
 static void
 nf_tproxy_destructor(struct sk_buff *skb)
@@ -70,7 +35,11 @@
 int
 nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
 {
-	if (inet_sk(sk)->transparent) {
+	bool transparent = (sk->sk_state == TCP_TIME_WAIT) ?
+				inet_twsk(sk)->tw_transparent :
+				inet_sk(sk)->transparent;
+
+	if (transparent) {
 		skb_orphan(skb);
 		skb->sk = sk;
 		skb->destructor = nf_tproxy_destructor;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index e34622f..80463507 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -116,10 +116,8 @@
 void
 xt_unregister_targets(struct xt_target *target, unsigned int n)
 {
-	unsigned int i;
-
-	for (i = 0; i < n; i++)
-		xt_unregister_target(&target[i]);
+	while (n-- > 0)
+		xt_unregister_target(&target[n]);
 }
 EXPORT_SYMBOL(xt_unregister_targets);
 
@@ -174,10 +172,8 @@
 void
 xt_unregister_matches(struct xt_match *match, unsigned int n)
 {
-	unsigned int i;
-
-	for (i = 0; i < n; i++)
-		xt_unregister_match(&match[i]);
+	while (n-- > 0)
+		xt_unregister_match(&match[n]);
 }
 EXPORT_SYMBOL(xt_unregister_matches);
 
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 0cb6053..782e519 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/skbuff.h>
-#include <linux/selinux.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter/x_tables.h>
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index 23b2d6c..9faf5e0 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -14,8 +14,8 @@
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/module.h>
+#include <linux/security.h>
 #include <linux/skbuff.h>
-#include <linux/selinux.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_SECMARK.h>
 
@@ -39,9 +39,8 @@
 
 	switch (mode) {
 	case SECMARK_MODE_SEL:
-		secmark = info->u.sel.selsid;
+		secmark = info->secid;
 		break;
-
 	default:
 		BUG();
 	}
@@ -50,33 +49,33 @@
 	return XT_CONTINUE;
 }
 
-static int checkentry_selinux(struct xt_secmark_target_info *info)
+static int checkentry_lsm(struct xt_secmark_target_info *info)
 {
 	int err;
-	struct xt_secmark_target_selinux_info *sel = &info->u.sel;
 
-	sel->selctx[SECMARK_SELCTX_MAX - 1] = '\0';
+	info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
+	info->secid = 0;
 
-	err = selinux_string_to_sid(sel->selctx, &sel->selsid);
+	err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
+				       &info->secid);
 	if (err) {
 		if (err == -EINVAL)
-			pr_info("invalid SELinux context \'%s\'\n",
-				sel->selctx);
+			pr_info("invalid security context \'%s\'\n", info->secctx);
 		return err;
 	}
 
-	if (!sel->selsid) {
-		pr_info("unable to map SELinux context \'%s\'\n", sel->selctx);
+	if (!info->secid) {
+		pr_info("unable to map security context \'%s\'\n", info->secctx);
 		return -ENOENT;
 	}
 
-	err = selinux_secmark_relabel_packet_permission(sel->selsid);
+	err = security_secmark_relabel_packet(info->secid);
 	if (err) {
 		pr_info("unable to obtain relabeling permission\n");
 		return err;
 	}
 
-	selinux_secmark_refcount_inc();
+	security_secmark_refcount_inc();
 	return 0;
 }
 
@@ -100,16 +99,16 @@
 
 	switch (info->mode) {
 	case SECMARK_MODE_SEL:
-		err = checkentry_selinux(info);
-		if (err <= 0)
-			return err;
 		break;
-
 	default:
 		pr_info("invalid mode: %hu\n", info->mode);
 		return -EINVAL;
 	}
 
+	err = checkentry_lsm(info);
+	if (err)
+		return err;
+
 	if (!mode)
 		mode = info->mode;
 	return 0;
@@ -119,7 +118,7 @@
 {
 	switch (mode) {
 	case SECMARK_MODE_SEL:
-		selinux_secmark_refcount_dec();
+		security_secmark_refcount_dec();
 	}
 }
 
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index c61294d..19c482c 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -1,7 +1,7 @@
 /*
  * Transparent proxy support for Linux/iptables
  *
- * Copyright (c) 2006-2007 BalaBit IT Ltd.
+ * Copyright (c) 2006-2010 BalaBit IT Ltd.
  * Author: Balazs Scheidler, Krisztian Kovacs
  *
  * This program is free software; you can redistribute it and/or modify
@@ -16,19 +16,96 @@
 #include <net/checksum.h>
 #include <net/udp.h>
 #include <net/inet_sock.h>
-
+#include <linux/inetdevice.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter/xt_TPROXY.h>
 
 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
-#include <net/netfilter/nf_tproxy_core.h>
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#include <net/if_inet6.h>
+#include <net/addrconf.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
+#endif
 
-static unsigned int
-tproxy_tg(struct sk_buff *skb, const struct xt_action_param *par)
+#include <net/netfilter/nf_tproxy_core.h>
+#include <linux/netfilter/xt_TPROXY.h>
+
+static inline __be32
+tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr)
+{
+	struct in_device *indev;
+	__be32 laddr;
+
+	if (user_laddr)
+		return user_laddr;
+
+	laddr = 0;
+	rcu_read_lock();
+	indev = __in_dev_get_rcu(skb->dev);
+	for_primary_ifa(indev) {
+		laddr = ifa->ifa_local;
+		break;
+	} endfor_ifa(indev);
+	rcu_read_unlock();
+
+	return laddr ? laddr : daddr;
+}
+
+/**
+ * tproxy_handle_time_wait4() - handle IPv4 TCP TIME_WAIT reopen redirections
+ * @skb:	The skb being processed.
+ * @laddr:	IPv4 address to redirect to or zero.
+ * @lport:	TCP port to redirect to or zero.
+ * @sk:		The TIME_WAIT TCP socket found by the lookup.
+ *
+ * We have to handle SYN packets arriving to TIME_WAIT sockets
+ * differently: instead of reopening the connection we should rather
+ * redirect the new connection to the proxy if there's a listener
+ * socket present.
+ *
+ * tproxy_handle_time_wait4() consumes the socket reference passed in.
+ *
+ * Returns the listener socket if there's one, the TIME_WAIT socket if
+ * no such listener is found, or NULL if the TCP header is incomplete.
+ */
+static struct sock *
+tproxy_handle_time_wait4(struct sk_buff *skb, __be32 laddr, __be16 lport,
+			struct sock *sk)
 {
 	const struct iphdr *iph = ip_hdr(skb);
-	const struct xt_tproxy_target_info *tgi = par->targinfo;
+	struct tcphdr _hdr, *hp;
+
+	hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
+	if (hp == NULL) {
+		inet_twsk_put(inet_twsk(sk));
+		return NULL;
+	}
+
+	if (hp->syn && !hp->rst && !hp->ack && !hp->fin) {
+		/* SYN to a TIME_WAIT socket, we'd rather redirect it
+		 * to a listener socket if there's one */
+		struct sock *sk2;
+
+		sk2 = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
+					    iph->saddr, laddr ? laddr : iph->daddr,
+					    hp->source, lport ? lport : hp->dest,
+					    skb->dev, NFT_LOOKUP_LISTENER);
+		if (sk2) {
+			inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
+			inet_twsk_put(inet_twsk(sk));
+			sk = sk2;
+		}
+	}
+
+	return sk;
+}
+
+static unsigned int
+tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport,
+	   u_int32_t mark_mask, u_int32_t mark_value)
+{
+	const struct iphdr *iph = ip_hdr(skb);
 	struct udphdr _hdr, *hp;
 	struct sock *sk;
 
@@ -36,12 +113,195 @@
 	if (hp == NULL)
 		return NF_DROP;
 
+	/* check if there's an ongoing connection on the packet
+	 * addresses, this happens if the redirect already happened
+	 * and the current packet belongs to an already established
+	 * connection */
 	sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
-				   iph->saddr,
-				   tgi->laddr ? tgi->laddr : iph->daddr,
-				   hp->source,
-				   tgi->lport ? tgi->lport : hp->dest,
-				   par->in, true);
+				   iph->saddr, iph->daddr,
+				   hp->source, hp->dest,
+				   skb->dev, NFT_LOOKUP_ESTABLISHED);
+
+	laddr = tproxy_laddr4(skb, laddr, iph->daddr);
+	if (!lport)
+		lport = hp->dest;
+
+	/* UDP has no TCP_TIME_WAIT state, so we never enter here */
+	if (sk && sk->sk_state == TCP_TIME_WAIT)
+		/* reopening a TIME_WAIT connection needs special handling */
+		sk = tproxy_handle_time_wait4(skb, laddr, lport, sk);
+	else if (!sk)
+		/* no, there's no established connection, check if
+		 * there's a listener on the redirected addr/port */
+		sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
+					   iph->saddr, laddr,
+					   hp->source, lport,
+					   skb->dev, NFT_LOOKUP_LISTENER);
+
+	/* NOTE: assign_sock consumes our sk reference */
+	if (sk && nf_tproxy_assign_sock(skb, sk)) {
+		/* This should be in a separate target, but we don't do multiple
+		   targets on the same rule yet */
+		skb->mark = (skb->mark & ~mark_mask) ^ mark_value;
+
+		pr_debug("redirecting: proto %hhu %pI4:%hu -> %pI4:%hu, mark: %x\n",
+			 iph->protocol, &iph->daddr, ntohs(hp->dest),
+			 &laddr, ntohs(lport), skb->mark);
+		return NF_ACCEPT;
+	}
+
+	pr_debug("no socket, dropping: proto %hhu %pI4:%hu -> %pI4:%hu, mark: %x\n",
+		 iph->protocol, &iph->saddr, ntohs(hp->source),
+		 &iph->daddr, ntohs(hp->dest), skb->mark);
+	return NF_DROP;
+}
+
+static unsigned int
+tproxy_tg4_v0(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_tproxy_target_info *tgi = par->targinfo;
+
+	return tproxy_tg4(skb, tgi->laddr, tgi->lport, tgi->mark_mask, tgi->mark_value);
+}
+
+static unsigned int
+tproxy_tg4_v1(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
+
+	return tproxy_tg4(skb, tgi->laddr.ip, tgi->lport, tgi->mark_mask, tgi->mark_value);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
+static inline const struct in6_addr *
+tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr,
+	      const struct in6_addr *daddr)
+{
+	struct inet6_dev *indev;
+	struct inet6_ifaddr *ifa;
+	struct in6_addr *laddr;
+
+	if (!ipv6_addr_any(user_laddr))
+		return user_laddr;
+	laddr = NULL;
+
+	rcu_read_lock();
+	indev = __in6_dev_get(skb->dev);
+	if (indev)
+		list_for_each_entry(ifa, &indev->addr_list, if_list) {
+			if (ifa->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
+				continue;
+
+			laddr = &ifa->addr;
+			break;
+		}
+	rcu_read_unlock();
+
+	return laddr ? laddr : daddr;
+}
+
+/**
+ * tproxy_handle_time_wait6() - handle IPv6 TCP TIME_WAIT reopen redirections
+ * @skb:	The skb being processed.
+ * @tproto:	Transport protocol.
+ * @thoff:	Transport protocol header offset.
+ * @par:	Iptables target parameters.
+ * @sk:		The TIME_WAIT TCP socket found by the lookup.
+ *
+ * We have to handle SYN packets arriving to TIME_WAIT sockets
+ * differently: instead of reopening the connection we should rather
+ * redirect the new connection to the proxy if there's a listener
+ * socket present.
+ *
+ * tproxy_handle_time_wait6() consumes the socket reference passed in.
+ *
+ * Returns the listener socket if there's one, the TIME_WAIT socket if
+ * no such listener is found, or NULL if the TCP header is incomplete.
+ */
+static struct sock *
+tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff,
+			 const struct xt_action_param *par,
+			 struct sock *sk)
+{
+	const struct ipv6hdr *iph = ipv6_hdr(skb);
+	struct tcphdr _hdr, *hp;
+	const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
+
+	hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
+	if (hp == NULL) {
+		inet_twsk_put(inet_twsk(sk));
+		return NULL;
+	}
+
+	if (hp->syn && !hp->rst && !hp->ack && !hp->fin) {
+		/* SYN to a TIME_WAIT socket, we'd rather redirect it
+		 * to a listener socket if there's one */
+		struct sock *sk2;
+
+		sk2 = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
+					    &iph->saddr,
+					    tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr),
+					    hp->source,
+					    tgi->lport ? tgi->lport : hp->dest,
+					    skb->dev, NFT_LOOKUP_LISTENER);
+		if (sk2) {
+			inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
+			inet_twsk_put(inet_twsk(sk));
+			sk = sk2;
+		}
+	}
+
+	return sk;
+}
+
+static unsigned int
+tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct ipv6hdr *iph = ipv6_hdr(skb);
+	const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
+	struct udphdr _hdr, *hp;
+	struct sock *sk;
+	const struct in6_addr *laddr;
+	__be16 lport;
+	int thoff;
+	int tproto;
+
+	tproto = ipv6_find_hdr(skb, &thoff, -1, NULL);
+	if (tproto < 0) {
+		pr_debug("unable to find transport header in IPv6 packet, dropping\n");
+		return NF_DROP;
+	}
+
+	hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
+	if (hp == NULL) {
+		pr_debug("unable to grab transport header contents in IPv6 packet, dropping\n");
+		return NF_DROP;
+	}
+
+	/* check if there's an ongoing connection on the packet
+	 * addresses, this happens if the redirect already happened
+	 * and the current packet belongs to an already established
+	 * connection */
+	sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
+				   &iph->saddr, &iph->daddr,
+				   hp->source, hp->dest,
+				   par->in, NFT_LOOKUP_ESTABLISHED);
+
+	laddr = tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr);
+	lport = tgi->lport ? tgi->lport : hp->dest;
+
+	/* UDP has no TCP_TIME_WAIT state, so we never enter here */
+	if (sk && sk->sk_state == TCP_TIME_WAIT)
+		/* reopening a TIME_WAIT connection needs special handling */
+		sk = tproxy_handle_time_wait6(skb, tproto, thoff, par, sk);
+	else if (!sk)
+		/* no there's no established connection, check if
+		 * there's a listener on the redirected addr/port */
+		sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
+					   &iph->saddr, laddr,
+					   hp->source, lport,
+					   par->in, NFT_LOOKUP_LISTENER);
 
 	/* NOTE: assign_sock consumes our sk reference */
 	if (sk && nf_tproxy_assign_sock(skb, sk)) {
@@ -49,19 +309,34 @@
 		   targets on the same rule yet */
 		skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value;
 
-		pr_debug("redirecting: proto %u %08x:%u -> %08x:%u, mark: %x\n",
-			 iph->protocol, ntohl(iph->daddr), ntohs(hp->dest),
-			 ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark);
+		pr_debug("redirecting: proto %hhu %pI6:%hu -> %pI6:%hu, mark: %x\n",
+			 tproto, &iph->saddr, ntohs(hp->source),
+			 laddr, ntohs(lport), skb->mark);
 		return NF_ACCEPT;
 	}
 
-	pr_debug("no socket, dropping: proto %u %08x:%u -> %08x:%u, mark: %x\n",
-		 iph->protocol, ntohl(iph->daddr), ntohs(hp->dest),
-		 ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark);
+	pr_debug("no socket, dropping: proto %hhu %pI6:%hu -> %pI6:%hu, mark: %x\n",
+		 tproto, &iph->saddr, ntohs(hp->source),
+		 &iph->daddr, ntohs(hp->dest), skb->mark);
+
 	return NF_DROP;
 }
 
-static int tproxy_tg_check(const struct xt_tgchk_param *par)
+static int tproxy_tg6_check(const struct xt_tgchk_param *par)
+{
+	const struct ip6t_ip6 *i = par->entryinfo;
+
+	if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
+	    && !(i->flags & IP6T_INV_PROTO))
+		return 0;
+
+	pr_info("Can be used only in combination with "
+		"either -p tcp or -p udp\n");
+	return -EINVAL;
+}
+#endif
+
+static int tproxy_tg4_check(const struct xt_tgchk_param *par)
 {
 	const struct ipt_ip *i = par->entryinfo;
 
@@ -74,31 +349,64 @@
 	return -EINVAL;
 }
 
-static struct xt_target tproxy_tg_reg __read_mostly = {
-	.name		= "TPROXY",
-	.family		= AF_INET,
-	.table		= "mangle",
-	.target		= tproxy_tg,
-	.targetsize	= sizeof(struct xt_tproxy_target_info),
-	.checkentry	= tproxy_tg_check,
-	.hooks		= 1 << NF_INET_PRE_ROUTING,
-	.me		= THIS_MODULE,
+static struct xt_target tproxy_tg_reg[] __read_mostly = {
+	{
+		.name		= "TPROXY",
+		.family		= NFPROTO_IPV4,
+		.table		= "mangle",
+		.target		= tproxy_tg4_v0,
+		.revision	= 0,
+		.targetsize	= sizeof(struct xt_tproxy_target_info),
+		.checkentry	= tproxy_tg4_check,
+		.hooks		= 1 << NF_INET_PRE_ROUTING,
+		.me		= THIS_MODULE,
+	},
+	{
+		.name		= "TPROXY",
+		.family		= NFPROTO_IPV4,
+		.table		= "mangle",
+		.target		= tproxy_tg4_v1,
+		.revision	= 1,
+		.targetsize	= sizeof(struct xt_tproxy_target_info_v1),
+		.checkentry	= tproxy_tg4_check,
+		.hooks		= 1 << NF_INET_PRE_ROUTING,
+		.me		= THIS_MODULE,
+	},
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	{
+		.name		= "TPROXY",
+		.family		= NFPROTO_IPV6,
+		.table		= "mangle",
+		.target		= tproxy_tg6_v1,
+		.revision	= 1,
+		.targetsize	= sizeof(struct xt_tproxy_target_info_v1),
+		.checkentry	= tproxy_tg6_check,
+		.hooks		= 1 << NF_INET_PRE_ROUTING,
+		.me		= THIS_MODULE,
+	},
+#endif
+
 };
 
 static int __init tproxy_tg_init(void)
 {
 	nf_defrag_ipv4_enable();
-	return xt_register_target(&tproxy_tg_reg);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	nf_defrag_ipv6_enable();
+#endif
+
+	return xt_register_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));
 }
 
 static void __exit tproxy_tg_exit(void)
 {
-	xt_unregister_target(&tproxy_tg_reg);
+	xt_unregister_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));
 }
 
 module_init(tproxy_tg_init);
 module_exit(tproxy_tg_exit);
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Krisztian Kovacs");
+MODULE_AUTHOR("Balazs Scheidler, Krisztian Kovacs");
 MODULE_DESCRIPTION("Netfilter transparent proxy (TPROXY) target module.");
 MODULE_ALIAS("ipt_TPROXY");
+MODULE_ALIAS("ip6t_TPROXY");
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index b46a839..9228ee0d 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -448,6 +448,7 @@
 {
 	__be16 _ports[2], *ports;
 	u8 nexthdr;
+	int poff;
 
 	memset(dst, 0, sizeof(*dst));
 
@@ -492,19 +493,13 @@
 		return 0;
 	}
 
-	switch (nexthdr) {
-	case IPPROTO_TCP:
-	case IPPROTO_UDP:
-	case IPPROTO_UDPLITE:
-	case IPPROTO_SCTP:
-	case IPPROTO_DCCP:
-		ports = skb_header_pointer(skb, protoff, sizeof(_ports),
+	poff = proto_ports_offset(nexthdr);
+	if (poff >= 0) {
+		ports = skb_header_pointer(skb, protoff + poff, sizeof(_ports),
 					   &_ports);
-		break;
-	default:
+	} else {
 		_ports[0] = _ports[1] = 0;
 		ports = _ports;
-		break;
 	}
 	if (!ports)
 		return -1;
diff --git a/net/netfilter/xt_ipvs.c b/net/netfilter/xt_ipvs.c
index 7a4d66db..9127a3d 100644
--- a/net/netfilter/xt_ipvs.c
+++ b/net/netfilter/xt_ipvs.c
@@ -16,7 +16,6 @@
 #include <linux/ip_vs.h>
 #include <linux/types.h>
 #include <linux/netfilter/x_tables.h>
-#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_ipvs.h>
 #include <net/netfilter/nf_conntrack.h>
 
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index 76aec6a..d2ff15a 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -567,6 +567,7 @@
 	.write   = recent_mt_proc_write,
 	.release = seq_release_private,
 	.owner   = THIS_MODULE,
+	.llseek = seq_lseek,
 };
 
 static int __net_init recent_proc_net_init(struct net *net)
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index 1ca8990..2dbd4c8 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -14,6 +14,7 @@
 #include <linux/skbuff.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
 #include <net/tcp.h>
 #include <net/udp.h>
 #include <net/icmp.h>
@@ -21,6 +22,7 @@
 #include <net/inet_sock.h>
 #include <net/netfilter/nf_tproxy_core.h>
 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
 
 #include <linux/netfilter/xt_socket.h>
 
@@ -30,7 +32,7 @@
 #endif
 
 static int
-extract_icmp_fields(const struct sk_buff *skb,
+extract_icmp4_fields(const struct sk_buff *skb,
 		    u8 *protocol,
 		    __be32 *raddr,
 		    __be32 *laddr,
@@ -86,7 +88,6 @@
 	return 0;
 }
 
-
 static bool
 socket_match(const struct sk_buff *skb, struct xt_action_param *par,
 	     const struct xt_socket_mtinfo1 *info)
@@ -115,7 +116,7 @@
 		dport = hp->dest;
 
 	} else if (iph->protocol == IPPROTO_ICMP) {
-		if (extract_icmp_fields(skb, &protocol, &saddr, &daddr,
+		if (extract_icmp4_fields(skb, &protocol, &saddr, &daddr,
 					&sport, &dport))
 			return false;
 	} else {
@@ -142,7 +143,7 @@
 #endif
 
 	sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol,
-				   saddr, daddr, sport, dport, par->in, false);
+				   saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY);
 	if (sk != NULL) {
 		bool wildcard;
 		bool transparent = true;
@@ -165,32 +166,157 @@
 			sk = NULL;
 	}
 
-	pr_debug("proto %u %08x:%u -> %08x:%u (orig %08x:%u) sock %p\n",
-		 protocol, ntohl(saddr), ntohs(sport),
-		 ntohl(daddr), ntohs(dport),
-		 ntohl(iph->daddr), hp ? ntohs(hp->dest) : 0, sk);
+	pr_debug("proto %hhu %pI4:%hu -> %pI4:%hu (orig %pI4:%hu) sock %p\n",
+		 protocol, &saddr, ntohs(sport),
+		 &daddr, ntohs(dport),
+		 &iph->daddr, hp ? ntohs(hp->dest) : 0, sk);
 
 	return (sk != NULL);
 }
 
 static bool
-socket_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
+socket_mt4_v0(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	return socket_match(skb, par, NULL);
 }
 
 static bool
-socket_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
+socket_mt4_v1(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	return socket_match(skb, par, par->matchinfo);
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
+static int
+extract_icmp6_fields(const struct sk_buff *skb,
+		     unsigned int outside_hdrlen,
+		     u8 *protocol,
+		     struct in6_addr **raddr,
+		     struct in6_addr **laddr,
+		     __be16 *rport,
+		     __be16 *lport)
+{
+	struct ipv6hdr *inside_iph, _inside_iph;
+	struct icmp6hdr *icmph, _icmph;
+	__be16 *ports, _ports[2];
+	u8 inside_nexthdr;
+	int inside_hdrlen;
+
+	icmph = skb_header_pointer(skb, outside_hdrlen,
+				   sizeof(_icmph), &_icmph);
+	if (icmph == NULL)
+		return 1;
+
+	if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK)
+		return 1;
+
+	inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), sizeof(_inside_iph), &_inside_iph);
+	if (inside_iph == NULL)
+		return 1;
+	inside_nexthdr = inside_iph->nexthdr;
+
+	inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph), &inside_nexthdr);
+	if (inside_hdrlen < 0)
+		return 1; /* hjm: Packet has no/incomplete transport layer headers. */
+
+	if (inside_nexthdr != IPPROTO_TCP &&
+	    inside_nexthdr != IPPROTO_UDP)
+		return 1;
+
+	ports = skb_header_pointer(skb, inside_hdrlen,
+				   sizeof(_ports), &_ports);
+	if (ports == NULL)
+		return 1;
+
+	/* the inside IP packet is the one quoted from our side, thus
+	 * its saddr is the local address */
+	*protocol = inside_nexthdr;
+	*laddr = &inside_iph->saddr;
+	*lport = ports[0];
+	*raddr = &inside_iph->daddr;
+	*rport = ports[1];
+
+	return 0;
+}
+
+static bool
+socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	struct ipv6hdr *iph = ipv6_hdr(skb);
+	struct udphdr _hdr, *hp = NULL;
+	struct sock *sk;
+	struct in6_addr *daddr, *saddr;
+	__be16 dport, sport;
+	int thoff;
+	u8 tproto;
+	const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
+
+	tproto = ipv6_find_hdr(skb, &thoff, -1, NULL);
+	if (tproto < 0) {
+		pr_debug("unable to find transport header in IPv6 packet, dropping\n");
+		return NF_DROP;
+	}
+
+	if (tproto == IPPROTO_UDP || tproto == IPPROTO_TCP) {
+		hp = skb_header_pointer(skb, thoff,
+					sizeof(_hdr), &_hdr);
+		if (hp == NULL)
+			return false;
+
+		saddr = &iph->saddr;
+		sport = hp->source;
+		daddr = &iph->daddr;
+		dport = hp->dest;
+
+	} else if (tproto == IPPROTO_ICMPV6) {
+		if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr,
+					 &sport, &dport))
+			return false;
+	} else {
+		return false;
+	}
+
+	sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
+				   saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY);
+	if (sk != NULL) {
+		bool wildcard;
+		bool transparent = true;
+
+		/* Ignore sockets listening on INADDR_ANY */
+		wildcard = (sk->sk_state != TCP_TIME_WAIT &&
+			    ipv6_addr_any(&inet6_sk(sk)->rcv_saddr));
+
+		/* Ignore non-transparent sockets,
+		   if XT_SOCKET_TRANSPARENT is used */
+		if (info && info->flags & XT_SOCKET_TRANSPARENT)
+			transparent = ((sk->sk_state != TCP_TIME_WAIT &&
+					inet_sk(sk)->transparent) ||
+				       (sk->sk_state == TCP_TIME_WAIT &&
+					inet_twsk(sk)->tw_transparent));
+
+		nf_tproxy_put_sock(sk);
+
+		if (wildcard || !transparent)
+			sk = NULL;
+	}
+
+	pr_debug("proto %hhu %pI6:%hu -> %pI6:%hu "
+		 "(orig %pI6:%hu) sock %p\n",
+		 tproto, saddr, ntohs(sport),
+		 daddr, ntohs(dport),
+		 &iph->daddr, hp ? ntohs(hp->dest) : 0, sk);
+
+	return (sk != NULL);
+}
+#endif
+
 static struct xt_match socket_mt_reg[] __read_mostly = {
 	{
 		.name		= "socket",
 		.revision	= 0,
 		.family		= NFPROTO_IPV4,
-		.match		= socket_mt_v0,
+		.match		= socket_mt4_v0,
 		.hooks		= (1 << NF_INET_PRE_ROUTING) |
 				  (1 << NF_INET_LOCAL_IN),
 		.me		= THIS_MODULE,
@@ -199,17 +325,33 @@
 		.name		= "socket",
 		.revision	= 1,
 		.family		= NFPROTO_IPV4,
-		.match		= socket_mt_v1,
+		.match		= socket_mt4_v1,
 		.matchsize	= sizeof(struct xt_socket_mtinfo1),
 		.hooks		= (1 << NF_INET_PRE_ROUTING) |
 				  (1 << NF_INET_LOCAL_IN),
 		.me		= THIS_MODULE,
 	},
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	{
+		.name		= "socket",
+		.revision	= 1,
+		.family		= NFPROTO_IPV6,
+		.match		= socket_mt6_v1,
+		.matchsize	= sizeof(struct xt_socket_mtinfo1),
+		.hooks		= (1 << NF_INET_PRE_ROUTING) |
+				  (1 << NF_INET_LOCAL_IN),
+		.me		= THIS_MODULE,
+	},
+#endif
 };
 
 static int __init socket_mt_init(void)
 {
 	nf_defrag_ipv4_enable();
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	nf_defrag_ipv6_enable();
+#endif
+
 	return xt_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg));
 }
 
@@ -225,3 +367,4 @@
 MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler");
 MODULE_DESCRIPTION("x_tables socket match module");
 MODULE_ALIAS("ipt_socket");
+MODULE_ALIAS("ip6t_socket");
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 26ed3e8..1781d99 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -547,8 +547,20 @@
 	info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
 	info.attrs = family->attrbuf;
 	genl_info_net_set(&info, net);
+	memset(&info.user_ptr, 0, sizeof(info.user_ptr));
 
-	return ops->doit(skb, &info);
+	if (family->pre_doit) {
+		err = family->pre_doit(ops, skb, &info);
+		if (err)
+			return err;
+	}
+
+	err = ops->doit(skb, &info);
+
+	if (family->post_doit)
+		family->post_doit(ops, skb, &info);
+
+	return err;
 }
 
 static void genl_rcv(struct sk_buff *skb)
diff --git a/net/nonet.c b/net/nonet.c
index 92e7664..b1a73fd 100644
--- a/net/nonet.c
+++ b/net/nonet.c
@@ -22,4 +22,5 @@
 const struct file_operations bad_sock_fops = {
 	.owner = THIS_MODULE,
 	.open = sock_no_open,
+	.llseek = noop_llseek,
 };
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 9a17f28..3616f27b 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -488,7 +488,7 @@
 	skb->dev = dev;
 	skb->priority = sk->sk_priority;
 	skb->mark = sk->sk_mark;
-	err = sock_tx_timestamp(msg, sk, skb_tx(skb));
+	err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
 	if (err < 0)
 		goto out_unlock;
 
@@ -1209,7 +1209,7 @@
 	err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len);
 	if (err)
 		goto out_free;
-	err = sock_tx_timestamp(msg, sk, skb_tx(skb));
+	err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
 	if (err < 0)
 		goto out_free;
 
diff --git a/net/phonet/Kconfig b/net/phonet/Kconfig
index 6ec7d55..0d9b8a2 100644
--- a/net/phonet/Kconfig
+++ b/net/phonet/Kconfig
@@ -14,3 +14,15 @@
 
 	  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 73aee7f..fd95beb 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -251,6 +251,16 @@
 	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) {
+		/* Resource routing (small race until phonet_rcv()) */
+		struct sock *sk = pn_find_sock_by_res(net,
+							target->spn_resource);
+		if (sk)	{
+			sock_put(sk);
+			dev = phonet_device_get(net);
+			skb->pkt_type = PACKET_LOOPBACK;
+		} else
+			dev = phonet_route_output(net, daddr);
 	} else
 		dev = phonet_route_output(net, daddr);
 
@@ -383,6 +393,13 @@
 		goto out;
 	}
 
+	/* resource routing */
+	if (pn_sockaddr_get_object(&sa) == 0) {
+		struct sock *sk = pn_find_sock_by_res(net, sa.spn_resource);
+		if (sk)
+			return sk_receive_skb(sk, skb, 0);
+	}
+
 	/* check if we are the destination */
 	if (phonet_address_lookup(net, pn_sockaddr_get_addr(&sa)) == 0) {
 		/* Phonet packet input */
diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c
index 1bd38db..2f03238 100644
--- a/net/phonet/datagram.c
+++ b/net/phonet/datagram.c
@@ -52,6 +52,19 @@
 		answ = skb ? skb->len : 0;
 		release_sock(sk);
 		return put_user(answ, (int __user *)arg);
+
+	case SIOCPNADDRESOURCE:
+	case SIOCPNDELRESOURCE: {
+			u32 res;
+			if (get_user(res, (u32 __user *)arg))
+				return -EFAULT;
+			if (res >= 256)
+				return -EINVAL;
+			if (cmd == SIOCPNADDRESOURCE)
+				return pn_sock_bind_res(sk, res);
+			else
+				return pn_sock_unbind_res(sk, res);
+		}
 	}
 
 	return -ENOIOCTLCMD;
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index b2a3ae6..3e60f2e 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -109,6 +109,210 @@
 }
 
 #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;
+}
+
+static int pipe_handler_send_req(struct sock *sk, u8 utid,
+		u8 msg_id, gfp_t priority)
+{
+	int len;
+	struct pnpipehdr *ph;
+	struct sk_buff *skb;
+	struct pep_sock *pn = pep_sk(sk);
+
+	static const u8 data[4] = {
+		PAD, PAD, PAD, PAD,
+	};
+
+	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);
+	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;
+
+	return pn_skb_send(sk, skb, &pn->remote_pep);
+}
+
+static int pipe_handler_send_created_ind(struct sock *sk,
+		u8 utid, u8 msg_id)
+{
+	int err_code;
+	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);
+	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->pipe_handle = pn->pipe_handle;
+	ph->error_code = err_code;
+
+	return pn_skb_send(sk, skb, &pn->remote_pep);
+}
+
+static int pipe_handler_send_ind(struct sock *sk, u8 utid, u8 msg_id)
+{
+	int err_code;
+	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);
+	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->pipe_handle = pn->pipe_handle;
+	ph->error_code = err_code;
+
+	return pn_skb_send(sk, skb, &pn->remote_pep);
+}
+
+static int pipe_handler_enable_pipe(struct sock *sk, int enable)
+{
+	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);
+}
+#endif
+
 static int pep_accept_conn(struct sock *sk, struct sk_buff *skb)
 {
 	static const u8 data[20] = {
@@ -192,7 +396,11 @@
 	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
 }
 
 /* Send our RX flow control information to the sender.
@@ -225,12 +433,13 @@
 static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
 {
 	struct pep_sock *pn = pep_sk(sk);
-	struct pnpipehdr *hdr = pnp_hdr(skb);
+	struct pnpipehdr *hdr;
 	int wake = 0;
 
 	if (!pskb_may_pull(skb, sizeof(*hdr) + 4))
 		return -EINVAL;
 
+	hdr = pnp_hdr(skb);
 	if (hdr->data[0] != PN_PEP_TYPE_COMMON) {
 		LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP type: %u\n",
 				(unsigned)hdr->data[0]);
@@ -323,11 +532,35 @@
 			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:
@@ -346,6 +579,17 @@
 		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);
@@ -437,6 +681,42 @@
 	skb_queue_purge(&pn->ctrlreq_queue);
 }
 
+#ifdef CONFIG_PHONET_PIPECTRLR
+static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb)
+{
+	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);
+
+	ret = pipe_handler_send_created_ind(sk,
+			PNS_PIPE_CREATED_IND_UTID,
+			PNS_PIPE_CREATED_IND
+			);
+
+	return ret;
+}
+#endif
+
 static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	struct sock *newsk;
@@ -600,6 +880,12 @@
 		err = pep_connreq_rcv(sk, skb);
 		break;
 
+#ifdef CONFIG_PHONET_PIPECTRLR
+	case PNS_PEP_CONNECT_RESP:
+		err = pep_connresp_rcv(sk, skb);
+		break;
+#endif
+
 	case PNS_PEP_DISCONNECT_REQ:
 		pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
 		break;
@@ -620,6 +906,28 @@
 	return err;
 }
 
+static int pipe_do_remove(struct sock *sk)
+{
+	struct pep_sock *pn = pep_sk(sk);
+	struct pnpipehdr *ph;
+	struct sk_buff *skb;
+
+	skb = alloc_skb(MAX_PNPIPE_HEADER, 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);
+}
+
 /* associated socket ceases to exist */
 static void pep_sock_close(struct sock *sk, long timeout)
 {
@@ -638,7 +946,22 @@
 		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;
 	}
+#endif
+
 	ifindex = pn->ifindex;
 	pn->ifindex = 0;
 	release_sock(sk);
@@ -715,6 +1038,20 @@
 	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));
+
+	return pipe_handler_send_req(sk,
+			PNS_PEP_CONNECT_UTID, PNS_PEP_CONNECT_REQ,
+			GFP_ATOMIC);
+}
+#endif
+
 static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
 	struct pep_sock *pn = pep_sk(sk);
@@ -766,6 +1103,18 @@
 
 	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;
@@ -791,6 +1140,17 @@
 			err = 0;
 		}
 		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;
 	}
@@ -815,9 +1175,19 @@
 	case PNPIPE_ENCAP:
 		val = pn->ifindex ? PNPIPE_ENCAP_IP : PNPIPE_ENCAP_NONE;
 		break;
+
 	case PNPIPE_IFINDEX:
 		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;
+		break;
+#endif
+
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -834,6 +1204,7 @@
 {
 	struct pep_sock *pn = pep_sk(sk);
 	struct pnpipehdr *ph;
+	int err;
 
 	if (pn_flow_safe(pn->tx_fc) &&
 	    !atomic_add_unless(&pn->tx_credits, -1, 0)) {
@@ -851,8 +1222,16 @@
 	} 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
 
-	return pn_skb_send(sk, skb, &pipe_srv);
+	if (err && pn_flow_safe(pn->tx_fc))
+		atomic_inc(&pn->tx_credits);
+	return err;
+
 }
 
 static int pep_sendmsg(struct kiocb *iocb, struct sock *sk,
@@ -872,7 +1251,7 @@
 	skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len,
 					flags & MSG_DONTWAIT, &err);
 	if (!skb)
-		return -ENOBUFS;
+		return err;
 
 	skb_reserve(skb, MAX_PHONET_HEADER + 3);
 	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
@@ -1044,6 +1423,8 @@
 	struct sock *skparent = NULL;
 
 	lock_sock(sk);
+
+#ifndef CONFIG_PHONET_PIPECTRLR
 	if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) {
 		skparent = pn->listener;
 		release_sock(sk);
@@ -1053,6 +1434,7 @@
 		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))
@@ -1066,6 +1448,9 @@
 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/pn_dev.c b/net/phonet/pn_dev.c
index b18e48f..947038d 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -292,8 +292,7 @@
 	if (bitmap_empty(deleted, 64))
 		return; /* short-circuit RCU */
 	synchronize_rcu();
-	for (i = find_first_bit(deleted, 64); i < 64;
-			i = find_next_bit(deleted, 64, i + 1)) {
+	for_each_set_bit(i, deleted, 64) {
 		rtm_phonet_notify(RTM_DELROUTE, dev, i);
 		dev_put(dev);
 	}
@@ -374,6 +373,7 @@
 	if (err)
 		return err;
 
+	proc_net_fops_create(&init_net, "pnresource", 0, &pn_res_seq_fops);
 	register_netdevice_notifier(&phonet_device_notifier);
 	err = phonet_netlink_register();
 	if (err)
@@ -386,6 +386,7 @@
 	rtnl_unregister_all(PF_PHONET);
 	unregister_netdevice_notifier(&phonet_device_notifier);
 	unregister_pernet_device(&phonet_net_ops);
+	proc_net_remove(&init_net, "pnresource");
 }
 
 int phonet_route_add(struct net_device *dev, u8 daddr)
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index 6e9848bf..25f746d 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -158,6 +158,7 @@
 	spin_lock_bh(&pnsocks.lock);
 	sk_del_node_init(sk);
 	spin_unlock_bh(&pnsocks.lock);
+	pn_sock_unbind_all_res(sk);
 }
 EXPORT_SYMBOL(pn_sock_unhash);
 
@@ -224,6 +225,101 @@
 	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 sockaddr_pn *spn = (struct sockaddr_pn *)addr;
+	long timeo;
+	int err;
+
+	if (len < sizeof(struct sockaddr_pn))
+		return -EINVAL;
+	if (spn->spn_family != AF_PHONET)
+		return -EAFNOSUPPORT;
+
+	lock_sock(sk);
+
+	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;
+			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;
+	}
+	sk->sk_state = TCP_CLOSE;
+	sk_stream_kill_queues(sk);
+
+	sock->state = SS_CONNECTING;
+	err = sk->sk_prot->connect(sk, addr, len);
+	if (err < 0) {
+		sock->state = SS_UNCONNECTED;
+		sk->sk_state = TCP_CLOSE;
+		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 */
+
+	err = -ETIMEDOUT;
+	if (timeo == 0 && sk->sk_state != TCP_SYN_RECV)
+		goto out;
+
+	if (sk->sk_state != TCP_SYN_RECV) {
+		sock->state = SS_UNCONNECTED;
+		err = sock_error(sk);
+		if (!err)
+			err = -ECONNREFUSED;
+		goto out;
+	}
+	sock->state = SS_CONNECTED;
+	err = 0;
+
+out:
+	release_sock(sk);
+	return err;
+}
+#endif
+
 static int pn_socket_accept(struct socket *sock, struct socket *newsock,
 				int flags)
 {
@@ -281,7 +377,9 @@
 	if (!mask && sk->sk_state == TCP_CLOSE_WAIT)
 		return POLLHUP;
 
-	if (sk->sk_state == TCP_ESTABLISHED && atomic_read(&pn->tx_credits))
+	if (sk->sk_state == TCP_ESTABLISHED &&
+		atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf &&
+		atomic_read(&pn->tx_credits))
 		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
 
 	return mask;
@@ -390,7 +488,11 @@
 	.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,
@@ -563,3 +665,188 @@
 	.release = seq_release_net,
 };
 #endif
+
+static struct  {
+	struct sock *sk[256];
+} pnres;
+
+/*
+ * Find and hold socket based on resource.
+ */
+struct sock *pn_find_sock_by_res(struct net *net, u8 res)
+{
+	struct sock *sk;
+
+	if (!net_eq(net, &init_net))
+		return NULL;
+
+	rcu_read_lock();
+	sk = rcu_dereference(pnres.sk[res]);
+	if (sk)
+		sock_hold(sk);
+	rcu_read_unlock();
+	return sk;
+}
+
+static DEFINE_MUTEX(resource_mutex);
+
+int pn_sock_bind_res(struct sock *sk, u8 res)
+{
+	int ret = -EADDRINUSE;
+
+	if (!net_eq(sock_net(sk), &init_net))
+		return -ENOIOCTLCMD;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (pn_socket_autobind(sk->sk_socket))
+		return -EAGAIN;
+
+	mutex_lock(&resource_mutex);
+	if (pnres.sk[res] == NULL) {
+		sock_hold(sk);
+		rcu_assign_pointer(pnres.sk[res], sk);
+		ret = 0;
+	}
+	mutex_unlock(&resource_mutex);
+	return ret;
+}
+
+int pn_sock_unbind_res(struct sock *sk, u8 res)
+{
+	int ret = -ENOENT;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	mutex_lock(&resource_mutex);
+	if (pnres.sk[res] == sk) {
+		rcu_assign_pointer(pnres.sk[res], NULL);
+		ret = 0;
+	}
+	mutex_unlock(&resource_mutex);
+
+	if (ret == 0) {
+		synchronize_rcu();
+		sock_put(sk);
+	}
+	return ret;
+}
+
+void pn_sock_unbind_all_res(struct sock *sk)
+{
+	unsigned res, match = 0;
+
+	mutex_lock(&resource_mutex);
+	for (res = 0; res < 256; res++) {
+		if (pnres.sk[res] == sk) {
+			rcu_assign_pointer(pnres.sk[res], NULL);
+			match++;
+		}
+	}
+	mutex_unlock(&resource_mutex);
+
+	if (match == 0)
+		return;
+	synchronize_rcu();
+	while (match > 0) {
+		sock_put(sk);
+		match--;
+	}
+}
+
+#ifdef CONFIG_PROC_FS
+static struct sock **pn_res_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct net *net = seq_file_net(seq);
+	unsigned i;
+
+	if (!net_eq(net, &init_net))
+		return NULL;
+
+	for (i = 0; i < 256; i++) {
+		if (pnres.sk[i] == NULL)
+			continue;
+		if (!pos)
+			return pnres.sk + i;
+		pos--;
+	}
+	return NULL;
+}
+
+static struct sock **pn_res_get_next(struct seq_file *seq, struct sock **sk)
+{
+	struct net *net = seq_file_net(seq);
+	unsigned i;
+
+	BUG_ON(!net_eq(net, &init_net));
+
+	for (i = (sk - pnres.sk) + 1; i < 256; i++)
+		if (pnres.sk[i])
+			return pnres.sk + i;
+	return NULL;
+}
+
+static void *pn_res_seq_start(struct seq_file *seq, loff_t *pos)
+	__acquires(resource_mutex)
+{
+	mutex_lock(&resource_mutex);
+	return *pos ? pn_res_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+}
+
+static void *pn_res_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct sock **sk;
+
+	if (v == SEQ_START_TOKEN)
+		sk = pn_res_get_idx(seq, 0);
+	else
+		sk = pn_res_get_next(seq, v);
+	(*pos)++;
+	return sk;
+}
+
+static void pn_res_seq_stop(struct seq_file *seq, void *v)
+	__releases(resource_mutex)
+{
+	mutex_unlock(&resource_mutex);
+}
+
+static int pn_res_seq_show(struct seq_file *seq, void *v)
+{
+	int len;
+
+	if (v == SEQ_START_TOKEN)
+		seq_printf(seq, "%s%n", "rs   uid inode", &len);
+	else {
+		struct sock **psk = v;
+		struct sock *sk = *psk;
+
+		seq_printf(seq, "%02X %5d %lu%n",
+			   (int) (psk - pnres.sk), sock_i_uid(sk),
+			   sock_i_ino(sk), &len);
+	}
+	seq_printf(seq, "%*s\n", 63 - len, "");
+	return 0;
+}
+
+static const struct seq_operations pn_res_seq_ops = {
+	.start = pn_res_seq_start,
+	.next = pn_res_seq_next,
+	.stop = pn_res_seq_stop,
+	.show = pn_res_seq_show,
+};
+
+static int pn_res_open(struct inode *inode, struct file *file)
+{
+	return seq_open_net(inode, file, &pn_res_seq_ops,
+				sizeof(struct seq_net_private));
+}
+
+const struct file_operations pn_res_seq_fops = {
+	.owner = THIS_MODULE,
+	.open = pn_res_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release_net,
+};
+#endif
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c
index aebfecb..bb6ad81 100644
--- a/net/rds/af_rds.c
+++ b/net/rds/af_rds.c
@@ -39,7 +39,15 @@
 #include <net/sock.h>
 
 #include "rds.h"
-#include "rdma.h"
+
+char *rds_str_array(char **array, size_t elements, size_t index)
+{
+	if ((index < elements) && array[index])
+		return array[index];
+	else
+		return "unknown";
+}
+EXPORT_SYMBOL(rds_str_array);
 
 /* this is just used for stats gathering :/ */
 static DEFINE_SPINLOCK(rds_sock_lock);
@@ -62,7 +70,7 @@
 	struct rds_sock *rs;
 	unsigned long flags;
 
-	if (sk == NULL)
+	if (!sk)
 		goto out;
 
 	rs = rds_sk_to_rs(sk);
@@ -73,7 +81,15 @@
 	 * with the socket. */
 	rds_clear_recv_queue(rs);
 	rds_cong_remove_socket(rs);
+
+	/*
+	 * the binding lookup hash uses rcu, we need to
+	 * make sure we sychronize_rcu before we free our
+	 * entry
+	 */
 	rds_remove_bound(rs);
+	synchronize_rcu();
+
 	rds_send_drop_to(rs, NULL);
 	rds_rdma_drop_keys(rs);
 	rds_notify_queue_get(rs, NULL);
@@ -83,6 +99,8 @@
 	rds_sock_count--;
 	spin_unlock_irqrestore(&rds_sock_lock, flags);
 
+	rds_trans_put(rs->rs_transport);
+
 	sock->sk = NULL;
 	sock_put(sk);
 out:
@@ -514,7 +532,7 @@
 	spin_unlock_irqrestore(&rds_sock_lock, flags);
 }
 
-static void __exit rds_exit(void)
+static void rds_exit(void)
 {
 	sock_unregister(rds_family_ops.family);
 	proto_unregister(&rds_proto);
@@ -529,7 +547,7 @@
 }
 module_exit(rds_exit);
 
-static int __init rds_init(void)
+static int rds_init(void)
 {
 	int ret;
 
diff --git a/net/rds/bind.c b/net/rds/bind.c
index 5d95fc0..2f6b3fc 100644
--- a/net/rds/bind.c
+++ b/net/rds/bind.c
@@ -34,45 +34,52 @@
 #include <net/sock.h>
 #include <linux/in.h>
 #include <linux/if_arp.h>
+#include <linux/jhash.h>
 #include "rds.h"
 
-/*
- * XXX this probably still needs more work.. no INADDR_ANY, and rbtrees aren't
- * particularly zippy.
- *
- * This is now called for every incoming frame so we arguably care much more
- * about it than we used to.
- */
+#define BIND_HASH_SIZE 1024
+static struct hlist_head bind_hash_table[BIND_HASH_SIZE];
 static DEFINE_SPINLOCK(rds_bind_lock);
-static struct rb_root rds_bind_tree = RB_ROOT;
 
-static struct rds_sock *rds_bind_tree_walk(__be32 addr, __be16 port,
-					   struct rds_sock *insert)
+static struct hlist_head *hash_to_bucket(__be32 addr, __be16 port)
 {
-	struct rb_node **p = &rds_bind_tree.rb_node;
-	struct rb_node *parent = NULL;
+	return bind_hash_table + (jhash_2words((u32)addr, (u32)port, 0) &
+				  (BIND_HASH_SIZE - 1));
+}
+
+static struct rds_sock *rds_bind_lookup(__be32 addr, __be16 port,
+					struct rds_sock *insert)
+{
 	struct rds_sock *rs;
+	struct hlist_node *node;
+	struct hlist_head *head = hash_to_bucket(addr, port);
 	u64 cmp;
 	u64 needle = ((u64)be32_to_cpu(addr) << 32) | be16_to_cpu(port);
 
-	while (*p) {
-		parent = *p;
-		rs = rb_entry(parent, struct rds_sock, rs_bound_node);
-
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(rs, node, head, rs_bound_node) {
 		cmp = ((u64)be32_to_cpu(rs->rs_bound_addr) << 32) |
 		      be16_to_cpu(rs->rs_bound_port);
 
-		if (needle < cmp)
-			p = &(*p)->rb_left;
-		else if (needle > cmp)
-			p = &(*p)->rb_right;
-		else
+		if (cmp == needle) {
+			rcu_read_unlock();
 			return rs;
+		}
 	}
+	rcu_read_unlock();
 
 	if (insert) {
-		rb_link_node(&insert->rs_bound_node, parent, p);
-		rb_insert_color(&insert->rs_bound_node, &rds_bind_tree);
+		/*
+		 * make sure our addr and port are set before
+		 * we are added to the list, other people
+		 * in rcu will find us as soon as the
+		 * hlist_add_head_rcu is done
+		 */
+		insert->rs_bound_addr = addr;
+		insert->rs_bound_port = port;
+		rds_sock_addref(insert);
+
+		hlist_add_head_rcu(&insert->rs_bound_node, head);
 	}
 	return NULL;
 }
@@ -86,15 +93,13 @@
 struct rds_sock *rds_find_bound(__be32 addr, __be16 port)
 {
 	struct rds_sock *rs;
-	unsigned long flags;
 
-	spin_lock_irqsave(&rds_bind_lock, flags);
-	rs = rds_bind_tree_walk(addr, port, NULL);
+	rs = rds_bind_lookup(addr, port, NULL);
+
 	if (rs && !sock_flag(rds_rs_to_sk(rs), SOCK_DEAD))
 		rds_sock_addref(rs);
 	else
 		rs = NULL;
-	spin_unlock_irqrestore(&rds_bind_lock, flags);
 
 	rdsdebug("returning rs %p for %pI4:%u\n", rs, &addr,
 		ntohs(port));
@@ -121,22 +126,15 @@
 	do {
 		if (rover == 0)
 			rover++;
-		if (rds_bind_tree_walk(addr, cpu_to_be16(rover), rs) == NULL) {
-			*port = cpu_to_be16(rover);
+		if (!rds_bind_lookup(addr, cpu_to_be16(rover), rs)) {
+			*port = rs->rs_bound_port;
 			ret = 0;
+			rdsdebug("rs %p binding to %pI4:%d\n",
+			  rs, &addr, (int)ntohs(*port));
 			break;
 		}
 	} while (rover++ != last);
 
-	if (ret == 0)  {
-		rs->rs_bound_addr = addr;
-		rs->rs_bound_port = *port;
-		rds_sock_addref(rs);
-
-		rdsdebug("rs %p binding to %pI4:%d\n",
-		  rs, &addr, (int)ntohs(*port));
-	}
-
 	spin_unlock_irqrestore(&rds_bind_lock, flags);
 
 	return ret;
@@ -153,7 +151,7 @@
 		  rs, &rs->rs_bound_addr,
 		  ntohs(rs->rs_bound_port));
 
-		rb_erase(&rs->rs_bound_node, &rds_bind_tree);
+		hlist_del_init_rcu(&rs->rs_bound_node);
 		rds_sock_put(rs);
 		rs->rs_bound_addr = 0;
 	}
@@ -184,7 +182,7 @@
 		goto out;
 
 	trans = rds_trans_get_preferred(sin->sin_addr.s_addr);
-	if (trans == NULL) {
+	if (!trans) {
 		ret = -EADDRNOTAVAIL;
 		rds_remove_bound(rs);
 		if (printk_ratelimit())
@@ -198,5 +196,9 @@
 
 out:
 	release_sock(sk);
+
+	/* we might have called rds_remove_bound on error */
+	if (ret)
+		synchronize_rcu();
 	return ret;
 }
diff --git a/net/rds/cong.c b/net/rds/cong.c
index 0871a29f..75ea686 100644
--- a/net/rds/cong.c
+++ b/net/rds/cong.c
@@ -141,7 +141,7 @@
 	unsigned long flags;
 
 	map = kzalloc(sizeof(struct rds_cong_map), GFP_KERNEL);
-	if (map == NULL)
+	if (!map)
 		return NULL;
 
 	map->m_addr = addr;
@@ -159,7 +159,7 @@
 	ret = rds_cong_tree_walk(addr, map);
 	spin_unlock_irqrestore(&rds_cong_lock, flags);
 
-	if (ret == NULL) {
+	if (!ret) {
 		ret = map;
 		map = NULL;
 	}
@@ -205,7 +205,7 @@
 	conn->c_lcong = rds_cong_from_addr(conn->c_laddr);
 	conn->c_fcong = rds_cong_from_addr(conn->c_faddr);
 
-	if (conn->c_lcong == NULL || conn->c_fcong == NULL)
+	if (!(conn->c_lcong && conn->c_fcong))
 		return -ENOMEM;
 
 	return 0;
@@ -221,7 +221,7 @@
 	list_for_each_entry(conn, &map->m_conn_list, c_map_item) {
 		if (!test_and_set_bit(0, &conn->c_map_queued)) {
 			rds_stats_inc(s_cong_update_queued);
-			queue_delayed_work(rds_wq, &conn->c_send_w, 0);
+			rds_send_xmit(conn);
 		}
 	}
 
diff --git a/net/rds/connection.c b/net/rds/connection.c
index 7619b67..9334d89 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -37,7 +37,6 @@
 
 #include "rds.h"
 #include "loop.h"
-#include "rdma.h"
 
 #define RDS_CONNECTION_HASH_BITS 12
 #define RDS_CONNECTION_HASH_ENTRIES (1 << RDS_CONNECTION_HASH_BITS)
@@ -63,18 +62,7 @@
 		var |= RDS_INFO_CONNECTION_FLAG_##suffix;	\
 } while (0)
 
-static inline int rds_conn_is_sending(struct rds_connection *conn)
-{
-	int ret = 0;
-
-	if (!mutex_trylock(&conn->c_send_lock))
-		ret = 1;
-	else
-		mutex_unlock(&conn->c_send_lock);
-
-	return ret;
-}
-
+/* rcu read lock must be held or the connection spinlock */
 static struct rds_connection *rds_conn_lookup(struct hlist_head *head,
 					      __be32 laddr, __be32 faddr,
 					      struct rds_transport *trans)
@@ -82,7 +70,7 @@
 	struct rds_connection *conn, *ret = NULL;
 	struct hlist_node *pos;
 
-	hlist_for_each_entry(conn, pos, head, c_hash_node) {
+	hlist_for_each_entry_rcu(conn, pos, head, c_hash_node) {
 		if (conn->c_faddr == faddr && conn->c_laddr == laddr &&
 				conn->c_trans == trans) {
 			ret = conn;
@@ -100,7 +88,7 @@
  * and receiving over this connection again in the future.  It is up to
  * the transport to have serialized this call with its send and recv.
  */
-void rds_conn_reset(struct rds_connection *conn)
+static void rds_conn_reset(struct rds_connection *conn)
 {
 	rdsdebug("connection %pI4 to %pI4 reset\n",
 	  &conn->c_laddr, &conn->c_faddr);
@@ -129,10 +117,11 @@
 {
 	struct rds_connection *conn, *parent = NULL;
 	struct hlist_head *head = rds_conn_bucket(laddr, faddr);
+	struct rds_transport *loop_trans;
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&rds_conn_lock, flags);
+	rcu_read_lock();
 	conn = rds_conn_lookup(head, laddr, faddr, trans);
 	if (conn && conn->c_loopback && conn->c_trans != &rds_loop_transport &&
 	    !is_outgoing) {
@@ -143,12 +132,12 @@
 		parent = conn;
 		conn = parent->c_passive;
 	}
-	spin_unlock_irqrestore(&rds_conn_lock, flags);
+	rcu_read_unlock();
 	if (conn)
 		goto out;
 
 	conn = kmem_cache_zalloc(rds_conn_slab, gfp);
-	if (conn == NULL) {
+	if (!conn) {
 		conn = ERR_PTR(-ENOMEM);
 		goto out;
 	}
@@ -159,7 +148,7 @@
 	spin_lock_init(&conn->c_lock);
 	conn->c_next_tx_seq = 1;
 
-	mutex_init(&conn->c_send_lock);
+	init_waitqueue_head(&conn->c_waitq);
 	INIT_LIST_HEAD(&conn->c_send_queue);
 	INIT_LIST_HEAD(&conn->c_retrans);
 
@@ -175,7 +164,9 @@
 	 * can bind to the destination address then we'd rather the messages
 	 * flow through loopback rather than either transport.
 	 */
-	if (rds_trans_get_preferred(faddr)) {
+	loop_trans = rds_trans_get_preferred(faddr);
+	if (loop_trans) {
+		rds_trans_put(loop_trans);
 		conn->c_loopback = 1;
 		if (is_outgoing && trans->t_prefer_loopback) {
 			/* "outgoing" connection - and the transport
@@ -238,7 +229,7 @@
 			kmem_cache_free(rds_conn_slab, conn);
 			conn = found;
 		} else {
-			hlist_add_head(&conn->c_hash_node, head);
+			hlist_add_head_rcu(&conn->c_hash_node, head);
 			rds_cong_add_conn(conn);
 			rds_conn_count++;
 		}
@@ -263,21 +254,91 @@
 }
 EXPORT_SYMBOL_GPL(rds_conn_create_outgoing);
 
+void rds_conn_shutdown(struct rds_connection *conn)
+{
+	/* shut it down unless it's down already */
+	if (!rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_DOWN)) {
+		/*
+		 * Quiesce the connection mgmt handlers before we start tearing
+		 * things down. We don't hold the mutex for the entire
+		 * duration of the shutdown operation, else we may be
+		 * deadlocking with the CM handler. Instead, the CM event
+		 * handler is supposed to check for state DISCONNECTING
+		 */
+		mutex_lock(&conn->c_cm_lock);
+		if (!rds_conn_transition(conn, RDS_CONN_UP, RDS_CONN_DISCONNECTING)
+		 && !rds_conn_transition(conn, RDS_CONN_ERROR, RDS_CONN_DISCONNECTING)) {
+			rds_conn_error(conn, "shutdown called in state %d\n",
+					atomic_read(&conn->c_state));
+			mutex_unlock(&conn->c_cm_lock);
+			return;
+		}
+		mutex_unlock(&conn->c_cm_lock);
+
+		wait_event(conn->c_waitq,
+			   !test_bit(RDS_IN_XMIT, &conn->c_flags));
+
+		conn->c_trans->conn_shutdown(conn);
+		rds_conn_reset(conn);
+
+		if (!rds_conn_transition(conn, RDS_CONN_DISCONNECTING, RDS_CONN_DOWN)) {
+			/* This can happen - eg when we're in the middle of tearing
+			 * down the connection, and someone unloads the rds module.
+			 * Quite reproduceable with loopback connections.
+			 * Mostly harmless.
+			 */
+			rds_conn_error(conn,
+				"%s: failed to transition to state DOWN, "
+				"current state is %d\n",
+				__func__,
+				atomic_read(&conn->c_state));
+			return;
+		}
+	}
+
+	/* Then reconnect if it's still live.
+	 * The passive side of an IB loopback connection is never added
+	 * to the conn hash, so we never trigger a reconnect on this
+	 * conn - the reconnect is always triggered by the active peer. */
+	cancel_delayed_work_sync(&conn->c_conn_w);
+	rcu_read_lock();
+	if (!hlist_unhashed(&conn->c_hash_node)) {
+		rcu_read_unlock();
+		rds_queue_reconnect(conn);
+	} else {
+		rcu_read_unlock();
+	}
+}
+
+/*
+ * Stop and free a connection.
+ *
+ * This can only be used in very limited circumstances.  It assumes that once
+ * the conn has been shutdown that no one else is referencing the connection.
+ * We can only ensure this in the rmmod path in the current code.
+ */
 void rds_conn_destroy(struct rds_connection *conn)
 {
 	struct rds_message *rm, *rtmp;
+	unsigned long flags;
 
 	rdsdebug("freeing conn %p for %pI4 -> "
 		 "%pI4\n", conn, &conn->c_laddr,
 		 &conn->c_faddr);
 
-	hlist_del_init(&conn->c_hash_node);
+	/* Ensure conn will not be scheduled for reconnect */
+	spin_lock_irq(&rds_conn_lock);
+	hlist_del_init_rcu(&conn->c_hash_node);
+	spin_unlock_irq(&rds_conn_lock);
+	synchronize_rcu();
 
-	/* wait for the rds thread to shut it down */
-	atomic_set(&conn->c_state, RDS_CONN_ERROR);
-	cancel_delayed_work(&conn->c_conn_w);
-	queue_work(rds_wq, &conn->c_down_w);
-	flush_workqueue(rds_wq);
+	/* shut the connection down */
+	rds_conn_drop(conn);
+	flush_work(&conn->c_down_w);
+
+	/* make sure lingering queued work won't try to ref the conn */
+	cancel_delayed_work_sync(&conn->c_send_w);
+	cancel_delayed_work_sync(&conn->c_recv_w);
 
 	/* tear down queued messages */
 	list_for_each_entry_safe(rm, rtmp,
@@ -302,7 +363,9 @@
 	BUG_ON(!list_empty(&conn->c_retrans));
 	kmem_cache_free(rds_conn_slab, conn);
 
+	spin_lock_irqsave(&rds_conn_lock, flags);
 	rds_conn_count--;
+	spin_unlock_irqrestore(&rds_conn_lock, flags);
 }
 EXPORT_SYMBOL_GPL(rds_conn_destroy);
 
@@ -316,23 +379,23 @@
 	struct list_head *list;
 	struct rds_connection *conn;
 	struct rds_message *rm;
-	unsigned long flags;
 	unsigned int total = 0;
+	unsigned long flags;
 	size_t i;
 
 	len /= sizeof(struct rds_info_message);
 
-	spin_lock_irqsave(&rds_conn_lock, flags);
+	rcu_read_lock();
 
 	for (i = 0, head = rds_conn_hash; i < ARRAY_SIZE(rds_conn_hash);
 	     i++, head++) {
-		hlist_for_each_entry(conn, pos, head, c_hash_node) {
+		hlist_for_each_entry_rcu(conn, pos, head, c_hash_node) {
 			if (want_send)
 				list = &conn->c_send_queue;
 			else
 				list = &conn->c_retrans;
 
-			spin_lock(&conn->c_lock);
+			spin_lock_irqsave(&conn->c_lock, flags);
 
 			/* XXX too lazy to maintain counts.. */
 			list_for_each_entry(rm, list, m_conn_item) {
@@ -343,11 +406,10 @@
 							  conn->c_faddr, 0);
 			}
 
-			spin_unlock(&conn->c_lock);
+			spin_unlock_irqrestore(&conn->c_lock, flags);
 		}
 	}
-
-	spin_unlock_irqrestore(&rds_conn_lock, flags);
+	rcu_read_unlock();
 
 	lens->nr = total;
 	lens->each = sizeof(struct rds_info_message);
@@ -377,19 +439,17 @@
 	uint64_t buffer[(item_len + 7) / 8];
 	struct hlist_head *head;
 	struct hlist_node *pos;
-	struct hlist_node *tmp;
 	struct rds_connection *conn;
-	unsigned long flags;
 	size_t i;
 
-	spin_lock_irqsave(&rds_conn_lock, flags);
+	rcu_read_lock();
 
 	lens->nr = 0;
 	lens->each = item_len;
 
 	for (i = 0, head = rds_conn_hash; i < ARRAY_SIZE(rds_conn_hash);
 	     i++, head++) {
-		hlist_for_each_entry_safe(conn, pos, tmp, head, c_hash_node) {
+		hlist_for_each_entry_rcu(conn, pos, head, c_hash_node) {
 
 			/* XXX no c_lock usage.. */
 			if (!visitor(conn, buffer))
@@ -405,8 +465,7 @@
 			lens->nr++;
 		}
 	}
-
-	spin_unlock_irqrestore(&rds_conn_lock, flags);
+	rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(rds_for_each_conn_info);
 
@@ -423,8 +482,8 @@
 		sizeof(cinfo->transport));
 	cinfo->flags = 0;
 
-	rds_conn_info_set(cinfo->flags,
-			  rds_conn_is_sending(conn), SENDING);
+	rds_conn_info_set(cinfo->flags, test_bit(RDS_IN_XMIT, &conn->c_flags),
+			  SENDING);
 	/* XXX Future: return the state rather than these funky bits */
 	rds_conn_info_set(cinfo->flags,
 			  atomic_read(&conn->c_state) == RDS_CONN_CONNECTING,
@@ -444,12 +503,12 @@
 				sizeof(struct rds_info_connection));
 }
 
-int __init rds_conn_init(void)
+int rds_conn_init(void)
 {
 	rds_conn_slab = kmem_cache_create("rds_connection",
 					  sizeof(struct rds_connection),
 					  0, 0, NULL);
-	if (rds_conn_slab == NULL)
+	if (!rds_conn_slab)
 		return -ENOMEM;
 
 	rds_info_register_func(RDS_INFO_CONNECTIONS, rds_conn_info);
@@ -487,6 +546,18 @@
 EXPORT_SYMBOL_GPL(rds_conn_drop);
 
 /*
+ * If the connection is down, trigger a connect. We may have scheduled a
+ * delayed reconnect however - in this case we should not interfere.
+ */
+void rds_conn_connect_if_down(struct rds_connection *conn)
+{
+	if (rds_conn_state(conn) == RDS_CONN_DOWN &&
+	    !test_and_set_bit(RDS_RECONNECT_PENDING, &conn->c_flags))
+		queue_delayed_work(rds_wq, &conn->c_conn_w, 0);
+}
+EXPORT_SYMBOL_GPL(rds_conn_connect_if_down);
+
+/*
  * An error occurred on the connection
  */
 void
diff --git a/net/rds/ib.c b/net/rds/ib.c
index 8f2d6dd..4123967 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -42,7 +42,7 @@
 #include "rds.h"
 #include "ib.h"
 
-unsigned int fmr_pool_size = RDS_FMR_POOL_SIZE;
+static unsigned int fmr_pool_size = RDS_FMR_POOL_SIZE;
 unsigned int fmr_message_size = RDS_FMR_SIZE + 1; /* +1 allows for unaligned MRs */
 unsigned int rds_ib_retry_count = RDS_IB_DEFAULT_RETRY_COUNT;
 
@@ -53,13 +53,72 @@
 module_param(rds_ib_retry_count, int, 0444);
 MODULE_PARM_DESC(rds_ib_retry_count, " Number of hw retries before reporting an error");
 
+/*
+ * we have a clumsy combination of RCU and a rwsem protecting this list
+ * because it is used both in the get_mr fast path and while blocking in
+ * the FMR flushing path.
+ */
+DECLARE_RWSEM(rds_ib_devices_lock);
 struct list_head rds_ib_devices;
 
 /* NOTE: if also grabbing ibdev lock, grab this first */
 DEFINE_SPINLOCK(ib_nodev_conns_lock);
 LIST_HEAD(ib_nodev_conns);
 
-void rds_ib_add_one(struct ib_device *device)
+static void rds_ib_nodev_connect(void)
+{
+	struct rds_ib_connection *ic;
+
+	spin_lock(&ib_nodev_conns_lock);
+	list_for_each_entry(ic, &ib_nodev_conns, ib_node)
+		rds_conn_connect_if_down(ic->conn);
+	spin_unlock(&ib_nodev_conns_lock);
+}
+
+static void rds_ib_dev_shutdown(struct rds_ib_device *rds_ibdev)
+{
+	struct rds_ib_connection *ic;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rds_ibdev->spinlock, flags);
+	list_for_each_entry(ic, &rds_ibdev->conn_list, ib_node)
+		rds_conn_drop(ic->conn);
+	spin_unlock_irqrestore(&rds_ibdev->spinlock, flags);
+}
+
+/*
+ * rds_ib_destroy_mr_pool() blocks on a few things and mrs drop references
+ * from interrupt context so we push freing off into a work struct in krdsd.
+ */
+static void rds_ib_dev_free(struct work_struct *work)
+{
+	struct rds_ib_ipaddr *i_ipaddr, *i_next;
+	struct rds_ib_device *rds_ibdev = container_of(work,
+					struct rds_ib_device, free_work);
+
+	if (rds_ibdev->mr_pool)
+		rds_ib_destroy_mr_pool(rds_ibdev->mr_pool);
+	if (rds_ibdev->mr)
+		ib_dereg_mr(rds_ibdev->mr);
+	if (rds_ibdev->pd)
+		ib_dealloc_pd(rds_ibdev->pd);
+
+	list_for_each_entry_safe(i_ipaddr, i_next, &rds_ibdev->ipaddr_list, list) {
+		list_del(&i_ipaddr->list);
+		kfree(i_ipaddr);
+	}
+
+	kfree(rds_ibdev);
+}
+
+void rds_ib_dev_put(struct rds_ib_device *rds_ibdev)
+{
+	BUG_ON(atomic_read(&rds_ibdev->refcount) <= 0);
+	if (atomic_dec_and_test(&rds_ibdev->refcount))
+		queue_work(rds_wq, &rds_ibdev->free_work);
+}
+
+static void rds_ib_add_one(struct ib_device *device)
 {
 	struct rds_ib_device *rds_ibdev;
 	struct ib_device_attr *dev_attr;
@@ -77,11 +136,14 @@
 		goto free_attr;
 	}
 
-	rds_ibdev = kmalloc(sizeof *rds_ibdev, GFP_KERNEL);
+	rds_ibdev = kzalloc_node(sizeof(struct rds_ib_device), GFP_KERNEL,
+				 ibdev_to_node(device));
 	if (!rds_ibdev)
 		goto free_attr;
 
 	spin_lock_init(&rds_ibdev->spinlock);
+	atomic_set(&rds_ibdev->refcount, 1);
+	INIT_WORK(&rds_ibdev->free_work, rds_ib_dev_free);
 
 	rds_ibdev->max_wrs = dev_attr->max_qp_wr;
 	rds_ibdev->max_sge = min(dev_attr->max_sge, RDS_IB_MAX_SGE);
@@ -91,68 +153,107 @@
 			min_t(unsigned int, dev_attr->max_fmr, fmr_pool_size) :
 			fmr_pool_size;
 
+	rds_ibdev->max_initiator_depth = dev_attr->max_qp_init_rd_atom;
+	rds_ibdev->max_responder_resources = dev_attr->max_qp_rd_atom;
+
 	rds_ibdev->dev = device;
 	rds_ibdev->pd = ib_alloc_pd(device);
-	if (IS_ERR(rds_ibdev->pd))
-		goto free_dev;
+	if (IS_ERR(rds_ibdev->pd)) {
+		rds_ibdev->pd = NULL;
+		goto put_dev;
+	}
 
-	rds_ibdev->mr = ib_get_dma_mr(rds_ibdev->pd,
-				      IB_ACCESS_LOCAL_WRITE);
-	if (IS_ERR(rds_ibdev->mr))
-		goto err_pd;
+	rds_ibdev->mr = ib_get_dma_mr(rds_ibdev->pd, IB_ACCESS_LOCAL_WRITE);
+	if (IS_ERR(rds_ibdev->mr)) {
+		rds_ibdev->mr = NULL;
+		goto put_dev;
+	}
 
 	rds_ibdev->mr_pool = rds_ib_create_mr_pool(rds_ibdev);
 	if (IS_ERR(rds_ibdev->mr_pool)) {
 		rds_ibdev->mr_pool = NULL;
-		goto err_mr;
+		goto put_dev;
 	}
 
 	INIT_LIST_HEAD(&rds_ibdev->ipaddr_list);
 	INIT_LIST_HEAD(&rds_ibdev->conn_list);
-	list_add_tail(&rds_ibdev->list, &rds_ib_devices);
+
+	down_write(&rds_ib_devices_lock);
+	list_add_tail_rcu(&rds_ibdev->list, &rds_ib_devices);
+	up_write(&rds_ib_devices_lock);
+	atomic_inc(&rds_ibdev->refcount);
 
 	ib_set_client_data(device, &rds_ib_client, rds_ibdev);
+	atomic_inc(&rds_ibdev->refcount);
 
-	goto free_attr;
+	rds_ib_nodev_connect();
 
-err_mr:
-	ib_dereg_mr(rds_ibdev->mr);
-err_pd:
-	ib_dealloc_pd(rds_ibdev->pd);
-free_dev:
-	kfree(rds_ibdev);
+put_dev:
+	rds_ib_dev_put(rds_ibdev);
 free_attr:
 	kfree(dev_attr);
 }
 
-void rds_ib_remove_one(struct ib_device *device)
+/*
+ * New connections use this to find the device to associate with the
+ * connection.  It's not in the fast path so we're not concerned about the
+ * performance of the IB call.  (As of this writing, it uses an interrupt
+ * blocking spinlock to serialize walking a per-device list of all registered
+ * clients.)
+ *
+ * RCU is used to handle incoming connections racing with device teardown.
+ * Rather than use a lock to serialize removal from the client_data and
+ * getting a new reference, we use an RCU grace period.  The destruction
+ * path removes the device from client_data and then waits for all RCU
+ * readers to finish.
+ *
+ * A new connection can get NULL from this if its arriving on a
+ * device that is in the process of being removed.
+ */
+struct rds_ib_device *rds_ib_get_client_data(struct ib_device *device)
 {
 	struct rds_ib_device *rds_ibdev;
-	struct rds_ib_ipaddr *i_ipaddr, *i_next;
+
+	rcu_read_lock();
+	rds_ibdev = ib_get_client_data(device, &rds_ib_client);
+	if (rds_ibdev)
+		atomic_inc(&rds_ibdev->refcount);
+	rcu_read_unlock();
+	return rds_ibdev;
+}
+
+/*
+ * The IB stack is letting us know that a device is going away.  This can
+ * happen if the underlying HCA driver is removed or if PCI hotplug is removing
+ * the pci function, for example.
+ *
+ * This can be called at any time and can be racing with any other RDS path.
+ */
+static void rds_ib_remove_one(struct ib_device *device)
+{
+	struct rds_ib_device *rds_ibdev;
 
 	rds_ibdev = ib_get_client_data(device, &rds_ib_client);
 	if (!rds_ibdev)
 		return;
 
-	list_for_each_entry_safe(i_ipaddr, i_next, &rds_ibdev->ipaddr_list, list) {
-		list_del(&i_ipaddr->list);
-		kfree(i_ipaddr);
-	}
+	rds_ib_dev_shutdown(rds_ibdev);
 
-	rds_ib_destroy_conns(rds_ibdev);
+	/* stop connection attempts from getting a reference to this device. */
+	ib_set_client_data(device, &rds_ib_client, NULL);
 
-	if (rds_ibdev->mr_pool)
-		rds_ib_destroy_mr_pool(rds_ibdev->mr_pool);
+	down_write(&rds_ib_devices_lock);
+	list_del_rcu(&rds_ibdev->list);
+	up_write(&rds_ib_devices_lock);
 
-	ib_dereg_mr(rds_ibdev->mr);
-
-	while (ib_dealloc_pd(rds_ibdev->pd)) {
-		rdsdebug("Failed to dealloc pd %p\n", rds_ibdev->pd);
-		msleep(1);
-	}
-
-	list_del(&rds_ibdev->list);
-	kfree(rds_ibdev);
+	/*
+	 * This synchronize rcu is waiting for readers of both the ib
+	 * client data and the devices list to finish before we drop
+	 * both of those references.
+	 */
+	synchronize_rcu();
+	rds_ib_dev_put(rds_ibdev);
+	rds_ib_dev_put(rds_ibdev);
 }
 
 struct ib_client rds_ib_client = {
@@ -186,7 +287,7 @@
 		rdma_addr_get_sgid(dev_addr, (union ib_gid *) &iinfo->src_gid);
 		rdma_addr_get_dgid(dev_addr, (union ib_gid *) &iinfo->dst_gid);
 
-		rds_ibdev = ib_get_client_data(ic->i_cm_id->device, &rds_ib_client);
+		rds_ibdev = ic->rds_ibdev;
 		iinfo->max_send_wr = ic->i_send_ring.w_nr;
 		iinfo->max_recv_wr = ic->i_recv_ring.w_nr;
 		iinfo->max_send_sge = rds_ibdev->max_sge;
@@ -248,29 +349,36 @@
 	return ret;
 }
 
+static void rds_ib_unregister_client(void)
+{
+	ib_unregister_client(&rds_ib_client);
+	/* wait for rds_ib_dev_free() to complete */
+	flush_workqueue(rds_wq);
+}
+
 void rds_ib_exit(void)
 {
 	rds_info_deregister_func(RDS_INFO_IB_CONNECTIONS, rds_ib_ic_info);
+	rds_ib_unregister_client();
 	rds_ib_destroy_nodev_conns();
-	ib_unregister_client(&rds_ib_client);
 	rds_ib_sysctl_exit();
 	rds_ib_recv_exit();
 	rds_trans_unregister(&rds_ib_transport);
+	rds_ib_fmr_exit();
 }
 
 struct rds_transport rds_ib_transport = {
 	.laddr_check		= rds_ib_laddr_check,
 	.xmit_complete		= rds_ib_xmit_complete,
 	.xmit			= rds_ib_xmit,
-	.xmit_cong_map		= NULL,
 	.xmit_rdma		= rds_ib_xmit_rdma,
+	.xmit_atomic		= rds_ib_xmit_atomic,
 	.recv			= rds_ib_recv,
 	.conn_alloc		= rds_ib_conn_alloc,
 	.conn_free		= rds_ib_conn_free,
 	.conn_connect		= rds_ib_conn_connect,
 	.conn_shutdown		= rds_ib_conn_shutdown,
 	.inc_copy_to_user	= rds_ib_inc_copy_to_user,
-	.inc_purge		= rds_ib_inc_purge,
 	.inc_free		= rds_ib_inc_free,
 	.cm_initiate_connect	= rds_ib_cm_initiate_connect,
 	.cm_handle_connect	= rds_ib_cm_handle_connect,
@@ -286,16 +394,20 @@
 	.t_type			= RDS_TRANS_IB
 };
 
-int __init rds_ib_init(void)
+int rds_ib_init(void)
 {
 	int ret;
 
 	INIT_LIST_HEAD(&rds_ib_devices);
 
-	ret = ib_register_client(&rds_ib_client);
+	ret = rds_ib_fmr_init();
 	if (ret)
 		goto out;
 
+	ret = ib_register_client(&rds_ib_client);
+	if (ret)
+		goto out_fmr_exit;
+
 	ret = rds_ib_sysctl_init();
 	if (ret)
 		goto out_ibreg;
@@ -317,7 +429,9 @@
 out_sysctl:
 	rds_ib_sysctl_exit();
 out_ibreg:
-	ib_unregister_client(&rds_ib_client);
+	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 64df4e7..e34ad03 100644
--- a/net/rds/ib.h
+++ b/net/rds/ib.h
@@ -3,11 +3,13 @@
 
 #include <rdma/ib_verbs.h>
 #include <rdma/rdma_cm.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
 #include "rds.h"
 #include "rdma_transport.h"
 
 #define RDS_FMR_SIZE			256
-#define RDS_FMR_POOL_SIZE		4096
+#define RDS_FMR_POOL_SIZE		8192
 
 #define RDS_IB_MAX_SGE			8
 #define RDS_IB_RECV_SGE 		2
@@ -19,6 +21,9 @@
 
 #define RDS_IB_SUPPORTED_PROTOCOLS	0x00000003	/* minor versions supported */
 
+#define RDS_IB_RECYCLE_BATCH_COUNT	32
+
+extern struct rw_semaphore rds_ib_devices_lock;
 extern struct list_head rds_ib_devices;
 
 /*
@@ -26,20 +31,29 @@
  * try and minimize the amount of memory tied up both the device and
  * socket receive queues.
  */
-/* page offset of the final full frag that fits in the page */
-#define RDS_PAGE_LAST_OFF (((PAGE_SIZE  / RDS_FRAG_SIZE) - 1) * RDS_FRAG_SIZE)
 struct rds_page_frag {
 	struct list_head	f_item;
-	struct page		*f_page;
-	unsigned long		f_offset;
-	dma_addr_t 		f_mapped;
+	struct list_head	f_cache_entry;
+	struct scatterlist	f_sg;
 };
 
 struct rds_ib_incoming {
 	struct list_head	ii_frags;
+	struct list_head	ii_cache_entry;
 	struct rds_incoming	ii_inc;
 };
 
+struct rds_ib_cache_head {
+	struct list_head *first;
+	unsigned long count;
+};
+
+struct rds_ib_refill_cache {
+	struct rds_ib_cache_head *percpu;
+	struct list_head	 *xfer;
+	struct list_head	 *ready;
+};
+
 struct rds_ib_connect_private {
 	/* Add new fields at the end, and don't permute existing fields. */
 	__be32			dp_saddr;
@@ -53,8 +67,7 @@
 };
 
 struct rds_ib_send_work {
-	struct rds_message	*s_rm;
-	struct rds_rdma_op	*s_op;
+	void			*s_op;
 	struct ib_send_wr	s_wr;
 	struct ib_sge		s_sge[RDS_IB_MAX_SGE];
 	unsigned long		s_queued;
@@ -92,10 +105,11 @@
 
 	/* tx */
 	struct rds_ib_work_ring	i_send_ring;
-	struct rds_message	*i_rm;
+	struct rm_data_op	*i_data_op;
 	struct rds_header	*i_send_hdrs;
 	u64			i_send_hdrs_dma;
 	struct rds_ib_send_work *i_sends;
+	atomic_t		i_signaled_sends;
 
 	/* rx */
 	struct tasklet_struct	i_recv_tasklet;
@@ -106,8 +120,9 @@
 	struct rds_header	*i_recv_hdrs;
 	u64			i_recv_hdrs_dma;
 	struct rds_ib_recv_work *i_recvs;
-	struct rds_page_frag	i_frag;
 	u64			i_ack_recv;	/* last ACK received */
+	struct rds_ib_refill_cache i_cache_incs;
+	struct rds_ib_refill_cache i_cache_frags;
 
 	/* sending acks */
 	unsigned long		i_ack_flags;
@@ -138,7 +153,6 @@
 
 	/* Batched completions */
 	unsigned int		i_unsignaled_wrs;
-	long			i_unsignaled_bytes;
 };
 
 /* This assumes that atomic_t is at least 32 bits */
@@ -164,9 +178,17 @@
 	unsigned int		max_fmrs;
 	int			max_sge;
 	unsigned int		max_wrs;
+	unsigned int		max_initiator_depth;
+	unsigned int		max_responder_resources;
 	spinlock_t		spinlock;	/* protect the above */
+	atomic_t		refcount;
+	struct work_struct	free_work;
 };
 
+#define pcidev_to_node(pcidev) pcibus_to_node(pcidev->bus)
+#define ibdev_to_node(ibdev) pcidev_to_node(to_pci_dev(ibdev->dma_device))
+#define rdsibdev_to_node(rdsibdev) ibdev_to_node(rdsibdev->dev)
+
 /* bits for i_ack_flags */
 #define IB_ACK_IN_FLIGHT	0
 #define IB_ACK_REQUESTED	1
@@ -202,6 +224,8 @@
 	uint64_t	s_ib_rdma_mr_pool_flush;
 	uint64_t	s_ib_rdma_mr_pool_wait;
 	uint64_t	s_ib_rdma_mr_pool_depleted;
+	uint64_t	s_ib_atomic_cswp;
+	uint64_t	s_ib_atomic_fadd;
 };
 
 extern struct workqueue_struct *rds_ib_wq;
@@ -241,11 +265,10 @@
 
 /* ib.c */
 extern struct rds_transport rds_ib_transport;
-extern void rds_ib_add_one(struct ib_device *device);
-extern void rds_ib_remove_one(struct ib_device *device);
+struct rds_ib_device *rds_ib_get_client_data(struct ib_device *device);
+void rds_ib_dev_put(struct rds_ib_device *rds_ibdev);
 extern struct ib_client rds_ib_client;
 
-extern unsigned int fmr_pool_size;
 extern unsigned int fmr_message_size;
 extern unsigned int rds_ib_retry_count;
 
@@ -258,7 +281,7 @@
 int rds_ib_conn_connect(struct rds_connection *conn);
 void rds_ib_conn_shutdown(struct rds_connection *conn);
 void rds_ib_state_change(struct sock *sk);
-int __init rds_ib_listen_init(void);
+int rds_ib_listen_init(void);
 void rds_ib_listen_stop(void);
 void __rds_ib_conn_error(struct rds_connection *conn, const char *, ...);
 int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
@@ -275,15 +298,7 @@
 int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr);
 void rds_ib_add_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn);
 void rds_ib_remove_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn);
-void __rds_ib_destroy_conns(struct list_head *list, spinlock_t *list_lock);
-static inline void rds_ib_destroy_nodev_conns(void)
-{
-	__rds_ib_destroy_conns(&ib_nodev_conns, &ib_nodev_conns_lock);
-}
-static inline void rds_ib_destroy_conns(struct rds_ib_device *rds_ibdev)
-{
-	__rds_ib_destroy_conns(&rds_ibdev->conn_list, &rds_ibdev->spinlock);
-}
+void rds_ib_destroy_nodev_conns(void);
 struct rds_ib_mr_pool *rds_ib_create_mr_pool(struct rds_ib_device *);
 void rds_ib_get_mr_info(struct rds_ib_device *rds_ibdev, struct rds_info_rdma_connection *iinfo);
 void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *);
@@ -292,14 +307,16 @@
 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 __init rds_ib_recv_init(void);
+int rds_ib_recv_init(void);
 void rds_ib_recv_exit(void);
 int rds_ib_recv(struct rds_connection *conn);
-int rds_ib_recv_refill(struct rds_connection *conn, gfp_t kptr_gfp,
-		       gfp_t page_gfp, int prefill);
-void rds_ib_inc_purge(struct rds_incoming *inc);
+int rds_ib_recv_alloc_caches(struct rds_ib_connection *ic);
+void rds_ib_recv_free_caches(struct rds_ib_connection *ic);
+void rds_ib_recv_refill(struct rds_connection *conn, int prefill);
 void rds_ib_inc_free(struct rds_incoming *inc);
 int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov,
 			     size_t size);
@@ -325,17 +342,19 @@
 extern wait_queue_head_t rds_ib_ring_empty_wait;
 
 /* ib_send.c */
+char *rds_ib_wc_status_str(enum ib_wc_status status);
 void rds_ib_xmit_complete(struct rds_connection *conn);
 int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
 		unsigned int hdr_off, unsigned int sg, unsigned int off);
 void rds_ib_send_cq_comp_handler(struct ib_cq *cq, void *context);
 void rds_ib_send_init_ring(struct rds_ib_connection *ic);
 void rds_ib_send_clear_ring(struct rds_ib_connection *ic);
-int rds_ib_xmit_rdma(struct rds_connection *conn, struct rds_rdma_op *op);
+int rds_ib_xmit_rdma(struct rds_connection *conn, struct rm_rdma_op *op);
 void rds_ib_send_add_credits(struct rds_connection *conn, unsigned int credits);
 void rds_ib_advertise_credits(struct rds_connection *conn, unsigned int posted);
 int rds_ib_send_grab_credits(struct rds_ib_connection *ic, u32 wanted,
 			     u32 *adv_credits, int need_posted, int max_posted);
+int rds_ib_xmit_atomic(struct rds_connection *conn, struct rm_atomic_op *op);
 
 /* ib_stats.c */
 DECLARE_PER_CPU(struct rds_ib_statistics, rds_ib_stats);
@@ -344,7 +363,7 @@
 				    unsigned int avail);
 
 /* ib_sysctl.c */
-int __init rds_ib_sysctl_init(void);
+int rds_ib_sysctl_init(void);
 void rds_ib_sysctl_exit(void);
 extern unsigned long rds_ib_sysctl_max_send_wr;
 extern unsigned long rds_ib_sysctl_max_recv_wr;
@@ -352,30 +371,5 @@
 extern unsigned long rds_ib_sysctl_max_unsig_bytes;
 extern unsigned long rds_ib_sysctl_max_recv_allocation;
 extern unsigned int rds_ib_sysctl_flow_control;
-extern ctl_table rds_ib_sysctl_table[];
-
-/*
- * Helper functions for getting/setting the header and data SGEs in
- * RDS packets (not RDMA)
- *
- * From version 3.1 onwards, header is in front of data in the sge.
- */
-static inline struct ib_sge *
-rds_ib_header_sge(struct rds_ib_connection *ic, struct ib_sge *sge)
-{
-	if (ic->conn->c_version > RDS_PROTOCOL_3_0)
-		return &sge[0];
-	else
-		return &sge[1];
-}
-
-static inline struct ib_sge *
-rds_ib_data_sge(struct rds_ib_connection *ic, struct ib_sge *sge)
-{
-	if (ic->conn->c_version > RDS_PROTOCOL_3_0)
-		return &sge[1];
-	else
-		return &sge[0];
-}
 
 #endif
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c
index f688327..ee369d2 100644
--- a/net/rds/ib_cm.c
+++ b/net/rds/ib_cm.c
@@ -38,6 +38,36 @@
 #include "rds.h"
 #include "ib.h"
 
+static char *rds_ib_event_type_strings[] = {
+#define RDS_IB_EVENT_STRING(foo) \
+		[IB_EVENT_##foo] = __stringify(IB_EVENT_##foo)
+	RDS_IB_EVENT_STRING(CQ_ERR),
+	RDS_IB_EVENT_STRING(QP_FATAL),
+	RDS_IB_EVENT_STRING(QP_REQ_ERR),
+	RDS_IB_EVENT_STRING(QP_ACCESS_ERR),
+	RDS_IB_EVENT_STRING(COMM_EST),
+	RDS_IB_EVENT_STRING(SQ_DRAINED),
+	RDS_IB_EVENT_STRING(PATH_MIG),
+	RDS_IB_EVENT_STRING(PATH_MIG_ERR),
+	RDS_IB_EVENT_STRING(DEVICE_FATAL),
+	RDS_IB_EVENT_STRING(PORT_ACTIVE),
+	RDS_IB_EVENT_STRING(PORT_ERR),
+	RDS_IB_EVENT_STRING(LID_CHANGE),
+	RDS_IB_EVENT_STRING(PKEY_CHANGE),
+	RDS_IB_EVENT_STRING(SM_CHANGE),
+	RDS_IB_EVENT_STRING(SRQ_ERR),
+	RDS_IB_EVENT_STRING(SRQ_LIMIT_REACHED),
+	RDS_IB_EVENT_STRING(QP_LAST_WQE_REACHED),
+	RDS_IB_EVENT_STRING(CLIENT_REREGISTER),
+#undef RDS_IB_EVENT_STRING
+};
+
+static char *rds_ib_event_str(enum ib_event_type type)
+{
+	return rds_str_array(rds_ib_event_type_strings,
+			     ARRAY_SIZE(rds_ib_event_type_strings), type);
+};
+
 /*
  * Set the selected protocol version
  */
@@ -95,7 +125,6 @@
 {
 	const struct rds_ib_connect_private *dp = NULL;
 	struct rds_ib_connection *ic = conn->c_transport_data;
-	struct rds_ib_device *rds_ibdev;
 	struct ib_qp_attr qp_attr;
 	int err;
 
@@ -111,11 +140,21 @@
 		}
 	}
 
-	printk(KERN_NOTICE "RDS/IB: connected to %pI4 version %u.%u%s\n",
-			&conn->c_faddr,
-			RDS_PROTOCOL_MAJOR(conn->c_version),
-			RDS_PROTOCOL_MINOR(conn->c_version),
-			ic->i_flowctl ? ", flow control" : "");
+	if (conn->c_version < RDS_PROTOCOL(3,1)) {
+		printk(KERN_NOTICE "RDS/IB: Connection to %pI4 version %u.%u failed,"
+		       " no longer supported\n",
+		       &conn->c_faddr,
+		       RDS_PROTOCOL_MAJOR(conn->c_version),
+		       RDS_PROTOCOL_MINOR(conn->c_version));
+		rds_conn_destroy(conn);
+		return;
+	} else {
+		printk(KERN_NOTICE "RDS/IB: connected to %pI4 version %u.%u%s\n",
+		       &conn->c_faddr,
+		       RDS_PROTOCOL_MAJOR(conn->c_version),
+		       RDS_PROTOCOL_MINOR(conn->c_version),
+		       ic->i_flowctl ? ", flow control" : "");
+	}
 
 	/*
 	 * Init rings and fill recv. this needs to wait until protocol negotiation
@@ -125,7 +164,7 @@
 	rds_ib_recv_init_ring(ic);
 	/* Post receive buffers - as a side effect, this will update
 	 * the posted credit count. */
-	rds_ib_recv_refill(conn, GFP_KERNEL, GFP_HIGHUSER, 1);
+	rds_ib_recv_refill(conn, 1);
 
 	/* Tune RNR behavior */
 	rds_ib_tune_rnr(ic, &qp_attr);
@@ -135,12 +174,11 @@
 	if (err)
 		printk(KERN_NOTICE "ib_modify_qp(IB_QP_STATE, RTS): err=%d\n", err);
 
-	/* update ib_device with this local ipaddr & conn */
-	rds_ibdev = ib_get_client_data(ic->i_cm_id->device, &rds_ib_client);
-	err = rds_ib_update_ipaddr(rds_ibdev, conn->c_laddr);
+	/* update ib_device with this local ipaddr */
+	err = rds_ib_update_ipaddr(ic->rds_ibdev, conn->c_laddr);
 	if (err)
-		printk(KERN_ERR "rds_ib_update_ipaddr failed (%d)\n", err);
-	rds_ib_add_conn(rds_ibdev, conn);
+		printk(KERN_ERR "rds_ib_update_ipaddr failed (%d)\n",
+			err);
 
 	/* If the peer gave us the last packet it saw, process this as if
 	 * we had received a regular ACK. */
@@ -153,18 +191,23 @@
 static void rds_ib_cm_fill_conn_param(struct rds_connection *conn,
 			struct rdma_conn_param *conn_param,
 			struct rds_ib_connect_private *dp,
-			u32 protocol_version)
+			u32 protocol_version,
+			u32 max_responder_resources,
+			u32 max_initiator_depth)
 {
+	struct rds_ib_connection *ic = conn->c_transport_data;
+	struct rds_ib_device *rds_ibdev = ic->rds_ibdev;
+
 	memset(conn_param, 0, sizeof(struct rdma_conn_param));
-	/* XXX tune these? */
-	conn_param->responder_resources = 1;
-	conn_param->initiator_depth = 1;
+
+	conn_param->responder_resources =
+		min_t(u32, rds_ibdev->max_responder_resources, max_responder_resources);
+	conn_param->initiator_depth =
+		min_t(u32, rds_ibdev->max_initiator_depth, max_initiator_depth);
 	conn_param->retry_count = min_t(unsigned int, rds_ib_retry_count, 7);
 	conn_param->rnr_retry_count = 7;
 
 	if (dp) {
-		struct rds_ib_connection *ic = conn->c_transport_data;
-
 		memset(dp, 0, sizeof(*dp));
 		dp->dp_saddr = conn->c_laddr;
 		dp->dp_daddr = conn->c_faddr;
@@ -189,7 +232,8 @@
 
 static void rds_ib_cq_event_handler(struct ib_event *event, void *data)
 {
-	rdsdebug("event %u data %p\n", event->event, data);
+	rdsdebug("event %u (%s) data %p\n",
+		 event->event, rds_ib_event_str(event->event), data);
 }
 
 static void rds_ib_qp_event_handler(struct ib_event *event, void *data)
@@ -197,16 +241,18 @@
 	struct rds_connection *conn = data;
 	struct rds_ib_connection *ic = conn->c_transport_data;
 
-	rdsdebug("conn %p ic %p event %u\n", conn, ic, event->event);
+	rdsdebug("conn %p ic %p event %u (%s)\n", conn, ic, event->event,
+		 rds_ib_event_str(event->event));
 
 	switch (event->event) {
 	case IB_EVENT_COMM_EST:
 		rdma_notify(ic->i_cm_id, IB_EVENT_COMM_EST);
 		break;
 	default:
-		rdsdebug("Fatal QP Event %u "
+		rdsdebug("Fatal QP Event %u (%s) "
 			"- connection %pI4->%pI4, reconnecting\n",
-			event->event, &conn->c_laddr, &conn->c_faddr);
+			event->event, rds_ib_event_str(event->event),
+			&conn->c_laddr, &conn->c_faddr);
 		rds_conn_drop(conn);
 		break;
 	}
@@ -224,18 +270,16 @@
 	struct rds_ib_device *rds_ibdev;
 	int ret;
 
-	/* rds_ib_add_one creates a rds_ib_device object per IB device,
-	 * and allocates a protection domain, memory range and FMR pool
-	 * for each.  If that fails for any reason, it will not register
-	 * the rds_ibdev at all.
+	/*
+	 * It's normal to see a null device if an incoming connection races
+	 * with device removal, so we don't print a warning.
 	 */
-	rds_ibdev = ib_get_client_data(dev, &rds_ib_client);
-	if (rds_ibdev == NULL) {
-		if (printk_ratelimit())
-			printk(KERN_NOTICE "RDS/IB: No client_data for device %s\n",
-					dev->name);
+	rds_ibdev = rds_ib_get_client_data(dev);
+	if (!rds_ibdev)
 		return -EOPNOTSUPP;
-	}
+
+	/* add the conn now so that connection establishment has the dev */
+	rds_ib_add_conn(rds_ibdev, conn);
 
 	if (rds_ibdev->max_wrs < ic->i_send_ring.w_nr + 1)
 		rds_ib_ring_resize(&ic->i_send_ring, rds_ibdev->max_wrs - 1);
@@ -306,7 +350,7 @@
 					   ic->i_send_ring.w_nr *
 						sizeof(struct rds_header),
 					   &ic->i_send_hdrs_dma, GFP_KERNEL);
-	if (ic->i_send_hdrs == NULL) {
+	if (!ic->i_send_hdrs) {
 		ret = -ENOMEM;
 		rdsdebug("ib_dma_alloc_coherent send failed\n");
 		goto out;
@@ -316,7 +360,7 @@
 					   ic->i_recv_ring.w_nr *
 						sizeof(struct rds_header),
 					   &ic->i_recv_hdrs_dma, GFP_KERNEL);
-	if (ic->i_recv_hdrs == NULL) {
+	if (!ic->i_recv_hdrs) {
 		ret = -ENOMEM;
 		rdsdebug("ib_dma_alloc_coherent recv failed\n");
 		goto out;
@@ -324,22 +368,24 @@
 
 	ic->i_ack = ib_dma_alloc_coherent(dev, sizeof(struct rds_header),
 				       &ic->i_ack_dma, GFP_KERNEL);
-	if (ic->i_ack == NULL) {
+	if (!ic->i_ack) {
 		ret = -ENOMEM;
 		rdsdebug("ib_dma_alloc_coherent ack failed\n");
 		goto out;
 	}
 
-	ic->i_sends = vmalloc(ic->i_send_ring.w_nr * sizeof(struct rds_ib_send_work));
-	if (ic->i_sends == NULL) {
+	ic->i_sends = vmalloc_node(ic->i_send_ring.w_nr * sizeof(struct rds_ib_send_work),
+				   ibdev_to_node(dev));
+	if (!ic->i_sends) {
 		ret = -ENOMEM;
 		rdsdebug("send allocation failed\n");
 		goto out;
 	}
 	memset(ic->i_sends, 0, ic->i_send_ring.w_nr * sizeof(struct rds_ib_send_work));
 
-	ic->i_recvs = vmalloc(ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work));
-	if (ic->i_recvs == NULL) {
+	ic->i_recvs = vmalloc_node(ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work),
+				   ibdev_to_node(dev));
+	if (!ic->i_recvs) {
 		ret = -ENOMEM;
 		rdsdebug("recv allocation failed\n");
 		goto out;
@@ -352,6 +398,7 @@
 		 ic->i_send_cq, ic->i_recv_cq);
 
 out:
+	rds_ib_dev_put(rds_ibdev);
 	return ret;
 }
 
@@ -409,7 +456,7 @@
 	struct rds_ib_connection *ic = NULL;
 	struct rdma_conn_param conn_param;
 	u32 version;
-	int err, destroy = 1;
+	int err = 1, destroy = 1;
 
 	/* Check whether the remote protocol version matches ours. */
 	version = rds_ib_protocol_compatible(event);
@@ -448,7 +495,6 @@
 			/* Wait and see - our connect may still be succeeding */
 			rds_ib_stats_inc(s_ib_connect_raced);
 		}
-		mutex_unlock(&conn->c_cm_lock);
 		goto out;
 	}
 
@@ -475,24 +521,23 @@
 	err = rds_ib_setup_qp(conn);
 	if (err) {
 		rds_ib_conn_error(conn, "rds_ib_setup_qp failed (%d)\n", err);
-		mutex_unlock(&conn->c_cm_lock);
 		goto out;
 	}
 
-	rds_ib_cm_fill_conn_param(conn, &conn_param, &dp_rep, version);
+	rds_ib_cm_fill_conn_param(conn, &conn_param, &dp_rep, version,
+		event->param.conn.responder_resources,
+		event->param.conn.initiator_depth);
 
 	/* rdma_accept() calls rdma_reject() internally if it fails */
 	err = rdma_accept(cm_id, &conn_param);
-	mutex_unlock(&conn->c_cm_lock);
-	if (err) {
+	if (err)
 		rds_ib_conn_error(conn, "rdma_accept failed (%d)\n", err);
-		goto out;
-	}
-
-	return 0;
 
 out:
-	rdma_reject(cm_id, NULL, 0);
+	if (conn)
+		mutex_unlock(&conn->c_cm_lock);
+	if (err)
+		rdma_reject(cm_id, NULL, 0);
 	return destroy;
 }
 
@@ -516,8 +561,8 @@
 		goto out;
 	}
 
-	rds_ib_cm_fill_conn_param(conn, &conn_param, &dp, RDS_PROTOCOL_VERSION);
-
+	rds_ib_cm_fill_conn_param(conn, &conn_param, &dp, RDS_PROTOCOL_VERSION,
+		UINT_MAX, UINT_MAX);
 	ret = rdma_connect(cm_id, &conn_param);
 	if (ret)
 		rds_ib_conn_error(conn, "rdma_connect failed (%d)\n", ret);
@@ -601,9 +646,19 @@
 				ic->i_cm_id, err);
 		}
 
+		/*
+		 * We want to wait for tx and rx completion to finish
+		 * before we tear down the connection, but we have to be
+		 * careful not to get stuck waiting on a send ring that
+		 * only has unsignaled sends in it.  We've shutdown new
+		 * sends before getting here so by waiting for signaled
+		 * sends to complete we're ensured that there will be no
+		 * more tx processing.
+		 */
 		wait_event(rds_ib_ring_empty_wait,
-			rds_ib_ring_empty(&ic->i_send_ring) &&
-			rds_ib_ring_empty(&ic->i_recv_ring));
+			   rds_ib_ring_empty(&ic->i_recv_ring) &&
+			   (atomic_read(&ic->i_signaled_sends) == 0));
+		tasklet_kill(&ic->i_recv_tasklet);
 
 		if (ic->i_send_hdrs)
 			ib_dma_free_coherent(dev,
@@ -654,9 +709,12 @@
 	BUG_ON(ic->rds_ibdev);
 
 	/* Clear pending transmit */
-	if (ic->i_rm) {
-		rds_message_put(ic->i_rm);
-		ic->i_rm = NULL;
+	if (ic->i_data_op) {
+		struct rds_message *rm;
+
+		rm = container_of(ic->i_data_op, struct rds_message, data);
+		rds_message_put(rm);
+		ic->i_data_op = NULL;
 	}
 
 	/* Clear the ACK state */
@@ -690,12 +748,19 @@
 {
 	struct rds_ib_connection *ic;
 	unsigned long flags;
+	int ret;
 
 	/* XXX too lazy? */
 	ic = kzalloc(sizeof(struct rds_ib_connection), GFP_KERNEL);
-	if (ic == NULL)
+	if (!ic)
 		return -ENOMEM;
 
+	ret = rds_ib_recv_alloc_caches(ic);
+	if (ret) {
+		kfree(ic);
+		return ret;
+	}
+
 	INIT_LIST_HEAD(&ic->ib_node);
 	tasklet_init(&ic->i_recv_tasklet, rds_ib_recv_tasklet_fn,
 		     (unsigned long) ic);
@@ -703,6 +768,7 @@
 #ifndef KERNEL_HAS_ATOMIC64
 	spin_lock_init(&ic->i_ack_lock);
 #endif
+	atomic_set(&ic->i_signaled_sends, 0);
 
 	/*
 	 * rds_ib_conn_shutdown() waits for these to be emptied so they
@@ -744,6 +810,8 @@
 	list_del(&ic->ib_node);
 	spin_unlock_irq(lock_ptr);
 
+	rds_ib_recv_free_caches(ic);
+
 	kfree(ic);
 }
 
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
index a54cd63..18a833c 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -32,11 +32,16 @@
  */
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/rculist.h>
 
 #include "rds.h"
-#include "rdma.h"
 #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
 
 /*
  * This is stored as mr->r_trans_private.
@@ -45,7 +50,11 @@
 	struct rds_ib_device	*device;
 	struct rds_ib_mr_pool	*pool;
 	struct ib_fmr		*fmr;
-	struct list_head	list;
+
+	struct xlist_head	xlist;
+
+	/* unmap_list is for freeing */
+	struct list_head	unmap_list;
 	unsigned int		remap_count;
 
 	struct scatterlist	*sg;
@@ -59,14 +68,16 @@
  */
 struct rds_ib_mr_pool {
 	struct mutex		flush_lock;		/* serialize fmr invalidate */
-	struct work_struct	flush_worker;		/* flush worker */
+	struct delayed_work	flush_worker;		/* flush worker */
 
-	spinlock_t		list_lock;		/* protect variables below */
 	atomic_t		item_count;		/* total # of MRs */
 	atomic_t		dirty_count;		/* # dirty of MRs */
-	struct list_head	drop_list;		/* MRs that have reached their max_maps limit */
-	struct list_head	free_list;		/* unused MRs */
-	struct list_head	clean_list;		/* unused & unamapped MRs */
+
+	struct xlist_head	drop_list;		/* MRs that have reached their max_maps limit */
+	struct xlist_head	free_list;		/* unused MRs */
+	struct xlist_head	clean_list;		/* global unused & unamapped MRs */
+	wait_queue_head_t	flush_wait;
+
 	atomic_t		free_pinned;		/* memory pinned by free MRs */
 	unsigned long		max_items;
 	unsigned long		max_items_soft;
@@ -74,7 +85,7 @@
 	struct ib_fmr_attr	fmr_attr;
 };
 
-static int rds_ib_flush_mr_pool(struct rds_ib_mr_pool *pool, int free_all);
+static int rds_ib_flush_mr_pool(struct rds_ib_mr_pool *pool, int free_all, struct rds_ib_mr **);
 static void rds_ib_teardown_mr(struct rds_ib_mr *ibmr);
 static void rds_ib_mr_pool_flush_worker(struct work_struct *work);
 
@@ -83,16 +94,17 @@
 	struct rds_ib_device *rds_ibdev;
 	struct rds_ib_ipaddr *i_ipaddr;
 
-	list_for_each_entry(rds_ibdev, &rds_ib_devices, list) {
-		spin_lock_irq(&rds_ibdev->spinlock);
-		list_for_each_entry(i_ipaddr, &rds_ibdev->ipaddr_list, list) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(rds_ibdev, &rds_ib_devices, list) {
+		list_for_each_entry_rcu(i_ipaddr, &rds_ibdev->ipaddr_list, list) {
 			if (i_ipaddr->ipaddr == ipaddr) {
-				spin_unlock_irq(&rds_ibdev->spinlock);
+				atomic_inc(&rds_ibdev->refcount);
+				rcu_read_unlock();
 				return rds_ibdev;
 			}
 		}
-		spin_unlock_irq(&rds_ibdev->spinlock);
 	}
+	rcu_read_unlock();
 
 	return NULL;
 }
@@ -108,7 +120,7 @@
 	i_ipaddr->ipaddr = ipaddr;
 
 	spin_lock_irq(&rds_ibdev->spinlock);
-	list_add_tail(&i_ipaddr->list, &rds_ibdev->ipaddr_list);
+	list_add_tail_rcu(&i_ipaddr->list, &rds_ibdev->ipaddr_list);
 	spin_unlock_irq(&rds_ibdev->spinlock);
 
 	return 0;
@@ -116,17 +128,24 @@
 
 static void rds_ib_remove_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr)
 {
-	struct rds_ib_ipaddr *i_ipaddr, *next;
+	struct rds_ib_ipaddr *i_ipaddr;
+	struct rds_ib_ipaddr *to_free = NULL;
+
 
 	spin_lock_irq(&rds_ibdev->spinlock);
-	list_for_each_entry_safe(i_ipaddr, next, &rds_ibdev->ipaddr_list, list) {
+	list_for_each_entry_rcu(i_ipaddr, &rds_ibdev->ipaddr_list, list) {
 		if (i_ipaddr->ipaddr == ipaddr) {
-			list_del(&i_ipaddr->list);
-			kfree(i_ipaddr);
+			list_del_rcu(&i_ipaddr->list);
+			to_free = i_ipaddr;
 			break;
 		}
 	}
 	spin_unlock_irq(&rds_ibdev->spinlock);
+
+	if (to_free) {
+		synchronize_rcu();
+		kfree(to_free);
+	}
 }
 
 int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr)
@@ -134,8 +153,10 @@
 	struct rds_ib_device *rds_ibdev_old;
 
 	rds_ibdev_old = rds_ib_get_device(ipaddr);
-	if (rds_ibdev_old)
+	if (rds_ibdev_old) {
 		rds_ib_remove_ipaddr(rds_ibdev_old, ipaddr);
+		rds_ib_dev_put(rds_ibdev_old);
+	}
 
 	return rds_ib_add_ipaddr(rds_ibdev, ipaddr);
 }
@@ -150,12 +171,13 @@
 	BUG_ON(list_empty(&ic->ib_node));
 	list_del(&ic->ib_node);
 
-	spin_lock_irq(&rds_ibdev->spinlock);
+	spin_lock(&rds_ibdev->spinlock);
 	list_add_tail(&ic->ib_node, &rds_ibdev->conn_list);
-	spin_unlock_irq(&rds_ibdev->spinlock);
+	spin_unlock(&rds_ibdev->spinlock);
 	spin_unlock_irq(&ib_nodev_conns_lock);
 
 	ic->rds_ibdev = rds_ibdev;
+	atomic_inc(&rds_ibdev->refcount);
 }
 
 void rds_ib_remove_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn)
@@ -175,18 +197,18 @@
 	spin_unlock(&ib_nodev_conns_lock);
 
 	ic->rds_ibdev = NULL;
+	rds_ib_dev_put(rds_ibdev);
 }
 
-void __rds_ib_destroy_conns(struct list_head *list, spinlock_t *list_lock)
+void rds_ib_destroy_nodev_conns(void)
 {
 	struct rds_ib_connection *ic, *_ic;
 	LIST_HEAD(tmp_list);
 
 	/* avoid calling conn_destroy with irqs off */
-	spin_lock_irq(list_lock);
-	list_splice(list, &tmp_list);
-	INIT_LIST_HEAD(list);
-	spin_unlock_irq(list_lock);
+	spin_lock_irq(&ib_nodev_conns_lock);
+	list_splice(&ib_nodev_conns, &tmp_list);
+	spin_unlock_irq(&ib_nodev_conns_lock);
 
 	list_for_each_entry_safe(ic, _ic, &tmp_list, ib_node)
 		rds_conn_destroy(ic->conn);
@@ -200,12 +222,12 @@
 	if (!pool)
 		return ERR_PTR(-ENOMEM);
 
-	INIT_LIST_HEAD(&pool->free_list);
-	INIT_LIST_HEAD(&pool->drop_list);
-	INIT_LIST_HEAD(&pool->clean_list);
+	INIT_XLIST_HEAD(&pool->free_list);
+	INIT_XLIST_HEAD(&pool->drop_list);
+	INIT_XLIST_HEAD(&pool->clean_list);
 	mutex_init(&pool->flush_lock);
-	spin_lock_init(&pool->list_lock);
-	INIT_WORK(&pool->flush_worker, rds_ib_mr_pool_flush_worker);
+	init_waitqueue_head(&pool->flush_wait);
+	INIT_DELAYED_WORK(&pool->flush_worker, rds_ib_mr_pool_flush_worker);
 
 	pool->fmr_attr.max_pages = fmr_message_size;
 	pool->fmr_attr.max_maps = rds_ibdev->fmr_max_remaps;
@@ -233,34 +255,60 @@
 
 void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *pool)
 {
-	flush_workqueue(rds_wq);
-	rds_ib_flush_mr_pool(pool, 1);
+	cancel_delayed_work_sync(&pool->flush_worker);
+	rds_ib_flush_mr_pool(pool, 1, NULL);
 	WARN_ON(atomic_read(&pool->item_count));
 	WARN_ON(atomic_read(&pool->free_pinned));
 	kfree(pool);
 }
 
+static void refill_local(struct rds_ib_mr_pool *pool, struct xlist_head *xl,
+			 struct rds_ib_mr **ibmr_ret)
+{
+	struct xlist_head *ibmr_xl;
+	ibmr_xl = xlist_del_head_fast(xl);
+	*ibmr_ret = list_entry(ibmr_xl, struct rds_ib_mr, xlist);
+}
+
 static inline struct rds_ib_mr *rds_ib_reuse_fmr(struct rds_ib_mr_pool *pool)
 {
 	struct rds_ib_mr *ibmr = NULL;
-	unsigned long flags;
+	struct xlist_head *ret;
+	unsigned long *flag;
 
-	spin_lock_irqsave(&pool->list_lock, flags);
-	if (!list_empty(&pool->clean_list)) {
-		ibmr = list_entry(pool->clean_list.next, struct rds_ib_mr, list);
-		list_del_init(&ibmr->list);
-	}
-	spin_unlock_irqrestore(&pool->list_lock, flags);
+	preempt_disable();
+	flag = &__get_cpu_var(clean_list_grace);
+	set_bit(CLEAN_LIST_BUSY_BIT, flag);
+	ret = xlist_del_head(&pool->clean_list);
+	if (ret)
+		ibmr = list_entry(ret, struct rds_ib_mr, xlist);
 
+	clear_bit(CLEAN_LIST_BUSY_BIT, flag);
+	preempt_enable();
 	return ibmr;
 }
 
+static inline void wait_clean_list_grace(void)
+{
+	int cpu;
+	unsigned long *flag;
+
+	for_each_online_cpu(cpu) {
+		flag = &per_cpu(clean_list_grace, cpu);
+		while (test_bit(CLEAN_LIST_BUSY_BIT, flag))
+			cpu_relax();
+	}
+}
+
 static struct rds_ib_mr *rds_ib_alloc_fmr(struct rds_ib_device *rds_ibdev)
 {
 	struct rds_ib_mr_pool *pool = rds_ibdev->mr_pool;
 	struct rds_ib_mr *ibmr = NULL;
 	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);
+
 	while (1) {
 		ibmr = rds_ib_reuse_fmr(pool);
 		if (ibmr)
@@ -287,19 +335,24 @@
 
 		/* We do have some empty MRs. Flush them out. */
 		rds_ib_stats_inc(s_ib_rdma_mr_pool_wait);
-		rds_ib_flush_mr_pool(pool, 0);
+		rds_ib_flush_mr_pool(pool, 0, &ibmr);
+		if (ibmr)
+			return ibmr;
 	}
 
-	ibmr = kzalloc(sizeof(*ibmr), GFP_KERNEL);
+	ibmr = kzalloc_node(sizeof(*ibmr), GFP_KERNEL, rdsibdev_to_node(rds_ibdev));
 	if (!ibmr) {
 		err = -ENOMEM;
 		goto out_no_cigar;
 	}
 
+	memset(ibmr, 0, sizeof(*ibmr));
+
 	ibmr->fmr = ib_alloc_fmr(rds_ibdev->pd,
 			(IB_ACCESS_LOCAL_WRITE |
 			 IB_ACCESS_REMOTE_READ |
-			 IB_ACCESS_REMOTE_WRITE),
+			 IB_ACCESS_REMOTE_WRITE|
+			 IB_ACCESS_REMOTE_ATOMIC),
 			&pool->fmr_attr);
 	if (IS_ERR(ibmr->fmr)) {
 		err = PTR_ERR(ibmr->fmr);
@@ -367,7 +420,8 @@
 	if (page_cnt > fmr_message_size)
 		return -EINVAL;
 
-	dma_pages = kmalloc(sizeof(u64) * page_cnt, GFP_ATOMIC);
+	dma_pages = kmalloc_node(sizeof(u64) * page_cnt, GFP_ATOMIC,
+				 rdsibdev_to_node(rds_ibdev));
 	if (!dma_pages)
 		return -ENOMEM;
 
@@ -441,7 +495,7 @@
 
 			/* FIXME we need a way to tell a r/w MR
 			 * from a r/o MR */
-			BUG_ON(in_interrupt());
+			BUG_ON(irqs_disabled());
 			set_page_dirty(page);
 			put_page(page);
 		}
@@ -477,33 +531,109 @@
 }
 
 /*
+ * given an xlist of mrs, put them all into the list_head for more processing
+ */
+static void xlist_append_to_list(struct xlist_head *xlist, struct list_head *list)
+{
+	struct rds_ib_mr *ibmr;
+	struct xlist_head splice;
+	struct xlist_head *cur;
+	struct xlist_head *next;
+
+	splice.next = NULL;
+	xlist_splice(xlist, &splice);
+	cur = splice.next;
+	while (cur) {
+		next = cur->next;
+		ibmr = list_entry(cur, struct rds_ib_mr, xlist);
+		list_add_tail(&ibmr->unmap_list, list);
+		cur = next;
+	}
+}
+
+/*
+ * this takes a list head of mrs and turns it into an xlist of clusters.
+ * each cluster has an xlist of MR_CLUSTER_SIZE mrs that are ready for
+ * reuse.
+ */
+static void list_append_to_xlist(struct rds_ib_mr_pool *pool,
+				struct list_head *list, struct xlist_head *xlist,
+				struct xlist_head **tail_ret)
+{
+	struct rds_ib_mr *ibmr;
+	struct xlist_head *cur_mr = xlist;
+	struct xlist_head *tail_mr = NULL;
+
+	list_for_each_entry(ibmr, list, unmap_list) {
+		tail_mr = &ibmr->xlist;
+		tail_mr->next = NULL;
+		cur_mr->next = tail_mr;
+		cur_mr = tail_mr;
+	}
+	*tail_ret = tail_mr;
+}
+
+/*
  * Flush our pool of MRs.
  * At a minimum, all currently unused MRs are unmapped.
  * If the number of MRs allocated exceeds the limit, we also try
  * to free as many MRs as needed to get back to this limit.
  */
-static int rds_ib_flush_mr_pool(struct rds_ib_mr_pool *pool, int free_all)
+static int rds_ib_flush_mr_pool(struct rds_ib_mr_pool *pool,
+			        int free_all, struct rds_ib_mr **ibmr_ret)
 {
 	struct rds_ib_mr *ibmr, *next;
+	struct xlist_head clean_xlist;
+	struct xlist_head *clean_tail;
 	LIST_HEAD(unmap_list);
 	LIST_HEAD(fmr_list);
 	unsigned long unpinned = 0;
-	unsigned long flags;
 	unsigned int nfreed = 0, ncleaned = 0, free_goal;
 	int ret = 0;
 
 	rds_ib_stats_inc(s_ib_rdma_mr_pool_flush);
 
-	mutex_lock(&pool->flush_lock);
+	if (ibmr_ret) {
+		DEFINE_WAIT(wait);
+		while(!mutex_trylock(&pool->flush_lock)) {
+			ibmr = rds_ib_reuse_fmr(pool);
+			if (ibmr) {
+				*ibmr_ret = ibmr;
+				finish_wait(&pool->flush_wait, &wait);
+				goto out_nolock;
+			}
 
-	spin_lock_irqsave(&pool->list_lock, flags);
+			prepare_to_wait(&pool->flush_wait, &wait,
+					TASK_UNINTERRUPTIBLE);
+			if (xlist_empty(&pool->clean_list))
+				schedule();
+
+			ibmr = rds_ib_reuse_fmr(pool);
+			if (ibmr) {
+				*ibmr_ret = ibmr;
+				finish_wait(&pool->flush_wait, &wait);
+				goto out_nolock;
+			}
+		}
+		finish_wait(&pool->flush_wait, &wait);
+	} else
+		mutex_lock(&pool->flush_lock);
+
+	if (ibmr_ret) {
+		ibmr = rds_ib_reuse_fmr(pool);
+		if (ibmr) {
+			*ibmr_ret = ibmr;
+			goto out;
+		}
+	}
+
 	/* Get the list of all MRs to be dropped. Ordering matters -
-	 * we want to put drop_list ahead of free_list. */
-	list_splice_init(&pool->free_list, &unmap_list);
-	list_splice_init(&pool->drop_list, &unmap_list);
+	 * we want to put drop_list ahead of free_list.
+	 */
+	xlist_append_to_list(&pool->drop_list, &unmap_list);
+	xlist_append_to_list(&pool->free_list, &unmap_list);
 	if (free_all)
-		list_splice_init(&pool->clean_list, &unmap_list);
-	spin_unlock_irqrestore(&pool->list_lock, flags);
+		xlist_append_to_list(&pool->clean_list, &unmap_list);
 
 	free_goal = rds_ib_flush_goal(pool, free_all);
 
@@ -511,19 +641,20 @@
 		goto out;
 
 	/* String all ib_mr's onto one list and hand them to ib_unmap_fmr */
-	list_for_each_entry(ibmr, &unmap_list, list)
+	list_for_each_entry(ibmr, &unmap_list, unmap_list)
 		list_add(&ibmr->fmr->list, &fmr_list);
+
 	ret = ib_unmap_fmr(&fmr_list);
 	if (ret)
 		printk(KERN_WARNING "RDS/IB: ib_unmap_fmr failed (err=%d)\n", ret);
 
 	/* Now we can destroy the DMA mapping and unpin any pages */
-	list_for_each_entry_safe(ibmr, next, &unmap_list, list) {
+	list_for_each_entry_safe(ibmr, next, &unmap_list, unmap_list) {
 		unpinned += ibmr->sg_len;
 		__rds_ib_teardown_mr(ibmr);
 		if (nfreed < free_goal || ibmr->remap_count >= pool->fmr_attr.max_maps) {
 			rds_ib_stats_inc(s_ib_rdma_mr_free);
-			list_del(&ibmr->list);
+			list_del(&ibmr->unmap_list);
 			ib_dealloc_fmr(ibmr->fmr);
 			kfree(ibmr);
 			nfreed++;
@@ -531,9 +662,27 @@
 		ncleaned++;
 	}
 
-	spin_lock_irqsave(&pool->list_lock, flags);
-	list_splice(&unmap_list, &pool->clean_list);
-	spin_unlock_irqrestore(&pool->list_lock, flags);
+	if (!list_empty(&unmap_list)) {
+		/* we have to make sure that none of the things we're about
+		 * to put on the clean list would race with other cpus trying
+		 * to pull items off.  The xlist would explode if we managed to
+		 * remove something from the clean list and then add it back again
+		 * while another CPU was spinning on that same item in xlist_del_head.
+		 *
+		 * This is pretty unlikely, but just in case  wait for an xlist grace period
+		 * here before adding anything back into the clean list.
+		 */
+		wait_clean_list_grace();
+
+		list_append_to_xlist(pool, &unmap_list, &clean_xlist, &clean_tail);
+		if (ibmr_ret)
+			refill_local(pool, &clean_xlist, ibmr_ret);
+
+		/* refill_local may have emptied our list */
+		if (!xlist_empty(&clean_xlist))
+			xlist_add(clean_xlist.next, clean_tail, &pool->clean_list);
+
+	}
 
 	atomic_sub(unpinned, &pool->free_pinned);
 	atomic_sub(ncleaned, &pool->dirty_count);
@@ -541,14 +690,35 @@
 
 out:
 	mutex_unlock(&pool->flush_lock);
+	if (waitqueue_active(&pool->flush_wait))
+		wake_up(&pool->flush_wait);
+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);
+	struct rds_ib_mr_pool *pool = container_of(work, struct rds_ib_mr_pool, flush_worker.work);
 
-	rds_ib_flush_mr_pool(pool, 0);
+	rds_ib_flush_mr_pool(pool, 0, NULL);
 }
 
 void rds_ib_free_mr(void *trans_private, int invalidate)
@@ -556,47 +726,49 @@
 	struct rds_ib_mr *ibmr = trans_private;
 	struct rds_ib_device *rds_ibdev = ibmr->device;
 	struct rds_ib_mr_pool *pool = rds_ibdev->mr_pool;
-	unsigned long flags;
 
 	rdsdebug("RDS/IB: free_mr nents %u\n", ibmr->sg_len);
 
 	/* Return it to the pool's free list */
-	spin_lock_irqsave(&pool->list_lock, flags);
 	if (ibmr->remap_count >= pool->fmr_attr.max_maps)
-		list_add(&ibmr->list, &pool->drop_list);
+		xlist_add(&ibmr->xlist, &ibmr->xlist, &pool->drop_list);
 	else
-		list_add(&ibmr->list, &pool->free_list);
+		xlist_add(&ibmr->xlist, &ibmr->xlist, &pool->free_list);
 
 	atomic_add(ibmr->sg_len, &pool->free_pinned);
 	atomic_inc(&pool->dirty_count);
-	spin_unlock_irqrestore(&pool->list_lock, flags);
 
 	/* 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_work(rds_wq, &pool->flush_worker);
+		queue_delayed_work(rds_ib_fmr_wq, &pool->flush_worker, 10);
 
 	if (invalidate) {
 		if (likely(!in_interrupt())) {
-			rds_ib_flush_mr_pool(pool, 0);
+			rds_ib_flush_mr_pool(pool, 0, NULL);
 		} else {
 			/* We get here if the user created a MR marked
 			 * as use_once and invalidate at the same time. */
-			queue_work(rds_wq, &pool->flush_worker);
+			queue_delayed_work(rds_ib_fmr_wq,
+					   &pool->flush_worker, 10);
 		}
 	}
+
+	rds_ib_dev_put(rds_ibdev);
 }
 
 void rds_ib_flush_mrs(void)
 {
 	struct rds_ib_device *rds_ibdev;
 
+	down_read(&rds_ib_devices_lock);
 	list_for_each_entry(rds_ibdev, &rds_ib_devices, list) {
 		struct rds_ib_mr_pool *pool = rds_ibdev->mr_pool;
 
 		if (pool)
-			rds_ib_flush_mr_pool(pool, 0);
+			rds_ib_flush_mr_pool(pool, 0, NULL);
 	}
+	up_read(&rds_ib_devices_lock);
 }
 
 void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
@@ -628,6 +800,7 @@
 		printk(KERN_WARNING "RDS/IB: map_fmr failed (errno=%d)\n", ret);
 
 	ibmr->device = rds_ibdev;
+	rds_ibdev = NULL;
 
  out:
 	if (ret) {
@@ -635,5 +808,8 @@
 			rds_ib_free_mr(ibmr, 0);
 		ibmr = ERR_PTR(ret);
 	}
+	if (rds_ibdev)
+		rds_ib_dev_put(rds_ibdev);
 	return ibmr;
 }
+
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c
index c74e990..e29e0ca 100644
--- a/net/rds/ib_recv.c
+++ b/net/rds/ib_recv.c
@@ -43,42 +43,6 @@
 static struct kmem_cache *rds_ib_frag_slab;
 static atomic_t	rds_ib_allocation = ATOMIC_INIT(0);
 
-static void rds_ib_frag_drop_page(struct rds_page_frag *frag)
-{
-	rdsdebug("frag %p page %p\n", frag, frag->f_page);
-	__free_page(frag->f_page);
-	frag->f_page = NULL;
-}
-
-static void rds_ib_frag_free(struct rds_page_frag *frag)
-{
-	rdsdebug("frag %p page %p\n", frag, frag->f_page);
-	BUG_ON(frag->f_page != NULL);
-	kmem_cache_free(rds_ib_frag_slab, frag);
-}
-
-/*
- * We map a page at a time.  Its fragments are posted in order.  This
- * is called in fragment order as the fragments get send completion events.
- * Only the last frag in the page performs the unmapping.
- *
- * It's OK for ring cleanup to call this in whatever order it likes because
- * DMA is not in flight and so we can unmap while other ring entries still
- * hold page references in their frags.
- */
-static void rds_ib_recv_unmap_page(struct rds_ib_connection *ic,
-				   struct rds_ib_recv_work *recv)
-{
-	struct rds_page_frag *frag = recv->r_frag;
-
-	rdsdebug("recv %p frag %p page %p\n", recv, frag, frag->f_page);
-	if (frag->f_mapped)
-		ib_dma_unmap_page(ic->i_cm_id->device,
-			       frag->f_mapped,
-			       RDS_FRAG_SIZE, DMA_FROM_DEVICE);
-	frag->f_mapped = 0;
-}
-
 void rds_ib_recv_init_ring(struct rds_ib_connection *ic)
 {
 	struct rds_ib_recv_work *recv;
@@ -95,18 +59,163 @@
 		recv->r_wr.sg_list = recv->r_sge;
 		recv->r_wr.num_sge = RDS_IB_RECV_SGE;
 
-		sge = rds_ib_data_sge(ic, recv->r_sge);
-		sge->addr = 0;
-		sge->length = RDS_FRAG_SIZE;
-		sge->lkey = ic->i_mr->lkey;
-
-		sge = rds_ib_header_sge(ic, recv->r_sge);
+		sge = &recv->r_sge[0];
 		sge->addr = ic->i_recv_hdrs_dma + (i * sizeof(struct rds_header));
 		sge->length = sizeof(struct rds_header);
 		sge->lkey = ic->i_mr->lkey;
+
+		sge = &recv->r_sge[1];
+		sge->addr = 0;
+		sge->length = RDS_FRAG_SIZE;
+		sge->lkey = ic->i_mr->lkey;
 	}
 }
 
+/*
+ * The entire 'from' list, including the from element itself, is put on
+ * to the tail of the 'to' list.
+ */
+static void list_splice_entire_tail(struct list_head *from,
+				    struct list_head *to)
+{
+	struct list_head *from_last = from->prev;
+
+	list_splice_tail(from_last, to);
+	list_add_tail(from_last, to);
+}
+
+static void rds_ib_cache_xfer_to_ready(struct rds_ib_refill_cache *cache)
+{
+	struct list_head *tmp;
+
+	tmp = xchg(&cache->xfer, NULL);
+	if (tmp) {
+		if (cache->ready)
+			list_splice_entire_tail(tmp, cache->ready);
+		else
+			cache->ready = tmp;
+	}
+}
+
+static int rds_ib_recv_alloc_cache(struct rds_ib_refill_cache *cache)
+{
+	struct rds_ib_cache_head *head;
+	int cpu;
+
+	cache->percpu = alloc_percpu(struct rds_ib_cache_head);
+	if (!cache->percpu)
+	       return -ENOMEM;
+
+	for_each_possible_cpu(cpu) {
+		head = per_cpu_ptr(cache->percpu, cpu);
+		head->first = NULL;
+		head->count = 0;
+	}
+	cache->xfer = NULL;
+	cache->ready = NULL;
+
+	return 0;
+}
+
+int rds_ib_recv_alloc_caches(struct rds_ib_connection *ic)
+{
+	int ret;
+
+	ret = rds_ib_recv_alloc_cache(&ic->i_cache_incs);
+	if (!ret) {
+		ret = rds_ib_recv_alloc_cache(&ic->i_cache_frags);
+		if (ret)
+			free_percpu(ic->i_cache_incs.percpu);
+	}
+
+	return ret;
+}
+
+static void rds_ib_cache_splice_all_lists(struct rds_ib_refill_cache *cache,
+					  struct list_head *caller_list)
+{
+	struct rds_ib_cache_head *head;
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		head = per_cpu_ptr(cache->percpu, cpu);
+		if (head->first) {
+			list_splice_entire_tail(head->first, caller_list);
+			head->first = NULL;
+		}
+	}
+
+	if (cache->ready) {
+		list_splice_entire_tail(cache->ready, caller_list);
+		cache->ready = NULL;
+	}
+}
+
+void rds_ib_recv_free_caches(struct rds_ib_connection *ic)
+{
+	struct rds_ib_incoming *inc;
+	struct rds_ib_incoming *inc_tmp;
+	struct rds_page_frag *frag;
+	struct rds_page_frag *frag_tmp;
+	LIST_HEAD(list);
+
+	rds_ib_cache_xfer_to_ready(&ic->i_cache_incs);
+	rds_ib_cache_splice_all_lists(&ic->i_cache_incs, &list);
+	free_percpu(ic->i_cache_incs.percpu);
+
+	list_for_each_entry_safe(inc, inc_tmp, &list, ii_cache_entry) {
+		list_del(&inc->ii_cache_entry);
+		WARN_ON(!list_empty(&inc->ii_frags));
+		kmem_cache_free(rds_ib_incoming_slab, inc);
+	}
+
+	rds_ib_cache_xfer_to_ready(&ic->i_cache_frags);
+	rds_ib_cache_splice_all_lists(&ic->i_cache_frags, &list);
+	free_percpu(ic->i_cache_frags.percpu);
+
+	list_for_each_entry_safe(frag, frag_tmp, &list, f_cache_entry) {
+		list_del(&frag->f_cache_entry);
+		WARN_ON(!list_empty(&frag->f_item));
+		kmem_cache_free(rds_ib_frag_slab, frag);
+	}
+}
+
+/* fwd decl */
+static void rds_ib_recv_cache_put(struct list_head *new_item,
+				  struct rds_ib_refill_cache *cache);
+static struct list_head *rds_ib_recv_cache_get(struct rds_ib_refill_cache *cache);
+
+
+/* Recycle frag and attached recv buffer f_sg */
+static void rds_ib_frag_free(struct rds_ib_connection *ic,
+			     struct rds_page_frag *frag)
+{
+	rdsdebug("frag %p page %p\n", frag, sg_page(&frag->f_sg));
+
+	rds_ib_recv_cache_put(&frag->f_cache_entry, &ic->i_cache_frags);
+}
+
+/* Recycle inc after freeing attached frags */
+void rds_ib_inc_free(struct rds_incoming *inc)
+{
+	struct rds_ib_incoming *ibinc;
+	struct rds_page_frag *frag;
+	struct rds_page_frag *pos;
+	struct rds_ib_connection *ic = inc->i_conn->c_transport_data;
+
+	ibinc = container_of(inc, struct rds_ib_incoming, ii_inc);
+
+	/* Free attached frags */
+	list_for_each_entry_safe(frag, pos, &ibinc->ii_frags, f_item) {
+		list_del_init(&frag->f_item);
+		rds_ib_frag_free(ic, frag);
+	}
+	BUG_ON(!list_empty(&ibinc->ii_frags));
+
+	rdsdebug("freeing ibinc %p inc %p\n", ibinc, inc);
+	rds_ib_recv_cache_put(&ibinc->ii_cache_entry, &ic->i_cache_incs);
+}
+
 static void rds_ib_recv_clear_one(struct rds_ib_connection *ic,
 				  struct rds_ib_recv_work *recv)
 {
@@ -115,10 +224,8 @@
 		recv->r_ibinc = NULL;
 	}
 	if (recv->r_frag) {
-		rds_ib_recv_unmap_page(ic, recv);
-		if (recv->r_frag->f_page)
-			rds_ib_frag_drop_page(recv->r_frag);
-		rds_ib_frag_free(recv->r_frag);
+		ib_dma_unmap_sg(ic->i_cm_id->device, &recv->r_frag->f_sg, 1, DMA_FROM_DEVICE);
+		rds_ib_frag_free(ic, recv->r_frag);
 		recv->r_frag = NULL;
 	}
 }
@@ -129,84 +236,111 @@
 
 	for (i = 0; i < ic->i_recv_ring.w_nr; i++)
 		rds_ib_recv_clear_one(ic, &ic->i_recvs[i]);
+}
 
-	if (ic->i_frag.f_page)
-		rds_ib_frag_drop_page(&ic->i_frag);
+static struct rds_ib_incoming *rds_ib_refill_one_inc(struct rds_ib_connection *ic,
+						     gfp_t slab_mask)
+{
+	struct rds_ib_incoming *ibinc;
+	struct list_head *cache_item;
+	int avail_allocs;
+
+	cache_item = rds_ib_recv_cache_get(&ic->i_cache_incs);
+	if (cache_item) {
+		ibinc = container_of(cache_item, struct rds_ib_incoming, ii_cache_entry);
+	} else {
+		avail_allocs = atomic_add_unless(&rds_ib_allocation,
+						 1, rds_ib_sysctl_max_recv_allocation);
+		if (!avail_allocs) {
+			rds_ib_stats_inc(s_ib_rx_alloc_limit);
+			return NULL;
+		}
+		ibinc = kmem_cache_alloc(rds_ib_incoming_slab, slab_mask);
+		if (!ibinc) {
+			atomic_dec(&rds_ib_allocation);
+			return NULL;
+		}
+	}
+	INIT_LIST_HEAD(&ibinc->ii_frags);
+	rds_inc_init(&ibinc->ii_inc, ic->conn, ic->conn->c_faddr);
+
+	return ibinc;
+}
+
+static struct rds_page_frag *rds_ib_refill_one_frag(struct rds_ib_connection *ic,
+						    gfp_t slab_mask, gfp_t page_mask)
+{
+	struct rds_page_frag *frag;
+	struct list_head *cache_item;
+	int ret;
+
+	cache_item = rds_ib_recv_cache_get(&ic->i_cache_frags);
+	if (cache_item) {
+		frag = container_of(cache_item, struct rds_page_frag, f_cache_entry);
+	} else {
+		frag = kmem_cache_alloc(rds_ib_frag_slab, slab_mask);
+		if (!frag)
+			return NULL;
+
+		sg_init_table(&frag->f_sg, 1);
+		ret = rds_page_remainder_alloc(&frag->f_sg,
+					       RDS_FRAG_SIZE, page_mask);
+		if (ret) {
+			kmem_cache_free(rds_ib_frag_slab, frag);
+			return NULL;
+		}
+	}
+
+	INIT_LIST_HEAD(&frag->f_item);
+
+	return frag;
 }
 
 static int rds_ib_recv_refill_one(struct rds_connection *conn,
-				  struct rds_ib_recv_work *recv,
-				  gfp_t kptr_gfp, gfp_t page_gfp)
+				  struct rds_ib_recv_work *recv, int prefill)
 {
 	struct rds_ib_connection *ic = conn->c_transport_data;
-	dma_addr_t dma_addr;
 	struct ib_sge *sge;
 	int ret = -ENOMEM;
+	gfp_t slab_mask = GFP_NOWAIT;
+	gfp_t page_mask = GFP_NOWAIT;
 
-	if (recv->r_ibinc == NULL) {
-		if (!atomic_add_unless(&rds_ib_allocation, 1, rds_ib_sysctl_max_recv_allocation)) {
-			rds_ib_stats_inc(s_ib_rx_alloc_limit);
-			goto out;
-		}
-		recv->r_ibinc = kmem_cache_alloc(rds_ib_incoming_slab,
-						 kptr_gfp);
-		if (recv->r_ibinc == NULL) {
-			atomic_dec(&rds_ib_allocation);
-			goto out;
-		}
-		INIT_LIST_HEAD(&recv->r_ibinc->ii_frags);
-		rds_inc_init(&recv->r_ibinc->ii_inc, conn, conn->c_faddr);
+	if (prefill) {
+		slab_mask = GFP_KERNEL;
+		page_mask = GFP_HIGHUSER;
 	}
 
-	if (recv->r_frag == NULL) {
-		recv->r_frag = kmem_cache_alloc(rds_ib_frag_slab, kptr_gfp);
-		if (recv->r_frag == NULL)
-			goto out;
-		INIT_LIST_HEAD(&recv->r_frag->f_item);
-		recv->r_frag->f_page = NULL;
-	}
-
-	if (ic->i_frag.f_page == NULL) {
-		ic->i_frag.f_page = alloc_page(page_gfp);
-		if (ic->i_frag.f_page == NULL)
-			goto out;
-		ic->i_frag.f_offset = 0;
-	}
-
-	dma_addr = ib_dma_map_page(ic->i_cm_id->device,
-				  ic->i_frag.f_page,
-				  ic->i_frag.f_offset,
-				  RDS_FRAG_SIZE,
-				  DMA_FROM_DEVICE);
-	if (ib_dma_mapping_error(ic->i_cm_id->device, dma_addr))
-		goto out;
+	if (!ic->i_cache_incs.ready)
+		rds_ib_cache_xfer_to_ready(&ic->i_cache_incs);
+	if (!ic->i_cache_frags.ready)
+		rds_ib_cache_xfer_to_ready(&ic->i_cache_frags);
 
 	/*
-	 * Once we get the RDS_PAGE_LAST_OFF frag then rds_ib_frag_unmap()
-	 * must be called on this recv.  This happens as completions hit
-	 * in order or on connection shutdown.
+	 * ibinc was taken from recv if recv contained the start of a message.
+	 * recvs that were continuations will still have this allocated.
 	 */
-	recv->r_frag->f_page = ic->i_frag.f_page;
-	recv->r_frag->f_offset = ic->i_frag.f_offset;
-	recv->r_frag->f_mapped = dma_addr;
+	if (!recv->r_ibinc) {
+		recv->r_ibinc = rds_ib_refill_one_inc(ic, slab_mask);
+		if (!recv->r_ibinc)
+			goto out;
+	}
 
-	sge = rds_ib_data_sge(ic, recv->r_sge);
-	sge->addr = dma_addr;
-	sge->length = RDS_FRAG_SIZE;
+	WARN_ON(recv->r_frag); /* leak! */
+	recv->r_frag = rds_ib_refill_one_frag(ic, slab_mask, page_mask);
+	if (!recv->r_frag)
+		goto out;
 
-	sge = rds_ib_header_sge(ic, recv->r_sge);
+	ret = ib_dma_map_sg(ic->i_cm_id->device, &recv->r_frag->f_sg,
+			    1, DMA_FROM_DEVICE);
+	WARN_ON(ret != 1);
+
+	sge = &recv->r_sge[0];
 	sge->addr = ic->i_recv_hdrs_dma + (recv - ic->i_recvs) * sizeof(struct rds_header);
 	sge->length = sizeof(struct rds_header);
 
-	get_page(recv->r_frag->f_page);
-
-	if (ic->i_frag.f_offset < RDS_PAGE_LAST_OFF) {
-		ic->i_frag.f_offset += RDS_FRAG_SIZE;
-	} else {
-		put_page(ic->i_frag.f_page);
-		ic->i_frag.f_page = NULL;
-		ic->i_frag.f_offset = 0;
-	}
+	sge = &recv->r_sge[1];
+	sge->addr = sg_dma_address(&recv->r_frag->f_sg);
+	sge->length = sg_dma_len(&recv->r_frag->f_sg);
 
 	ret = 0;
 out:
@@ -216,13 +350,11 @@
 /*
  * This tries to allocate and post unused work requests after making sure that
  * they have all the allocations they need to queue received fragments into
- * sockets.  The i_recv_mutex is held here so that ring_alloc and _unalloc
- * pairs don't go unmatched.
+ * sockets.
  *
  * -1 is returned if posting fails due to temporary resource exhaustion.
  */
-int rds_ib_recv_refill(struct rds_connection *conn, gfp_t kptr_gfp,
-		       gfp_t page_gfp, int prefill)
+void rds_ib_recv_refill(struct rds_connection *conn, int prefill)
 {
 	struct rds_ib_connection *ic = conn->c_transport_data;
 	struct rds_ib_recv_work *recv;
@@ -236,28 +368,25 @@
 		if (pos >= ic->i_recv_ring.w_nr) {
 			printk(KERN_NOTICE "Argh - ring alloc returned pos=%u\n",
 					pos);
-			ret = -EINVAL;
 			break;
 		}
 
 		recv = &ic->i_recvs[pos];
-		ret = rds_ib_recv_refill_one(conn, recv, kptr_gfp, page_gfp);
+		ret = rds_ib_recv_refill_one(conn, recv, prefill);
 		if (ret) {
-			ret = -1;
 			break;
 		}
 
 		/* XXX when can this fail? */
 		ret = ib_post_recv(ic->i_cm_id->qp, &recv->r_wr, &failed_wr);
 		rdsdebug("recv %p ibinc %p page %p addr %lu ret %d\n", recv,
-			 recv->r_ibinc, recv->r_frag->f_page,
-			 (long) recv->r_frag->f_mapped, ret);
+			 recv->r_ibinc, sg_page(&recv->r_frag->f_sg),
+			 (long) sg_dma_address(&recv->r_frag->f_sg), ret);
 		if (ret) {
 			rds_ib_conn_error(conn, "recv post on "
 			       "%pI4 returned %d, disconnecting and "
 			       "reconnecting\n", &conn->c_faddr,
 			       ret);
-			ret = -1;
 			break;
 		}
 
@@ -270,37 +399,73 @@
 
 	if (ret)
 		rds_ib_ring_unalloc(&ic->i_recv_ring, 1);
-	return ret;
 }
 
-void rds_ib_inc_purge(struct rds_incoming *inc)
+/*
+ * We want to recycle several types of recv allocations, like incs and frags.
+ * To use this, the *_free() function passes in the ptr to a list_head within
+ * the recyclee, as well as the cache to put it on.
+ *
+ * First, we put the memory on a percpu list. When this reaches a certain size,
+ * We move it to an intermediate non-percpu list in a lockless manner, with some
+ * xchg/compxchg wizardry.
+ *
+ * N.B. Instead of a list_head as the anchor, we use a single pointer, which can
+ * be NULL and xchg'd. The list is actually empty when the pointer is NULL, and
+ * list_empty() will return true with one element is actually present.
+ */
+static void rds_ib_recv_cache_put(struct list_head *new_item,
+				 struct rds_ib_refill_cache *cache)
 {
-	struct rds_ib_incoming *ibinc;
-	struct rds_page_frag *frag;
-	struct rds_page_frag *pos;
+	unsigned long flags;
+	struct rds_ib_cache_head *chp;
+	struct list_head *old;
 
-	ibinc = container_of(inc, struct rds_ib_incoming, ii_inc);
-	rdsdebug("purging ibinc %p inc %p\n", ibinc, inc);
+	local_irq_save(flags);
 
-	list_for_each_entry_safe(frag, pos, &ibinc->ii_frags, f_item) {
-		list_del_init(&frag->f_item);
-		rds_ib_frag_drop_page(frag);
-		rds_ib_frag_free(frag);
+	chp = per_cpu_ptr(cache->percpu, smp_processor_id());
+	if (!chp->first)
+		INIT_LIST_HEAD(new_item);
+	else /* put on front */
+		list_add_tail(new_item, chp->first);
+	chp->first = new_item;
+	chp->count++;
+
+	if (chp->count < RDS_IB_RECYCLE_BATCH_COUNT)
+		goto end;
+
+	/*
+	 * Return our per-cpu first list to the cache's xfer by atomically
+	 * grabbing the current xfer list, appending it to our per-cpu list,
+	 * and then atomically returning that entire list back to the
+	 * cache's xfer list as long as it's still empty.
+	 */
+	do {
+		old = xchg(&cache->xfer, NULL);
+		if (old)
+			list_splice_entire_tail(old, chp->first);
+		old = cmpxchg(&cache->xfer, NULL, chp->first);
+	} while (old);
+
+	chp->first = NULL;
+	chp->count = 0;
+end:
+	local_irq_restore(flags);
+}
+
+static struct list_head *rds_ib_recv_cache_get(struct rds_ib_refill_cache *cache)
+{
+	struct list_head *head = cache->ready;
+
+	if (head) {
+		if (!list_empty(head)) {
+			cache->ready = head->next;
+			list_del_init(head);
+		} else
+			cache->ready = NULL;
 	}
-}
 
-void rds_ib_inc_free(struct rds_incoming *inc)
-{
-	struct rds_ib_incoming *ibinc;
-
-	ibinc = container_of(inc, struct rds_ib_incoming, ii_inc);
-
-	rds_ib_inc_purge(inc);
-	rdsdebug("freeing ibinc %p inc %p\n", ibinc, inc);
-	BUG_ON(!list_empty(&ibinc->ii_frags));
-	kmem_cache_free(rds_ib_incoming_slab, ibinc);
-	atomic_dec(&rds_ib_allocation);
-	BUG_ON(atomic_read(&rds_ib_allocation) < 0);
+	return head;
 }
 
 int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov,
@@ -336,13 +501,13 @@
 		to_copy = min_t(unsigned long, to_copy, len - copied);
 
 		rdsdebug("%lu bytes to user [%p, %zu] + %lu from frag "
-			 "[%p, %lu] + %lu\n",
+			 "[%p, %u] + %lu\n",
 			 to_copy, iov->iov_base, iov->iov_len, iov_off,
-			 frag->f_page, frag->f_offset, frag_off);
+			 sg_page(&frag->f_sg), frag->f_sg.offset, frag_off);
 
 		/* XXX needs + offset for multiple recvs per page */
-		ret = rds_page_copy_to_user(frag->f_page,
-					    frag->f_offset + frag_off,
+		ret = rds_page_copy_to_user(sg_page(&frag->f_sg),
+					    frag->f_sg.offset + frag_off,
 					    iov->iov_base + iov_off,
 					    to_copy);
 		if (ret) {
@@ -557,47 +722,6 @@
 	return rds_ib_get_ack(ic);
 }
 
-static struct rds_header *rds_ib_get_header(struct rds_connection *conn,
-					    struct rds_ib_recv_work *recv,
-					    u32 data_len)
-{
-	struct rds_ib_connection *ic = conn->c_transport_data;
-	void *hdr_buff = &ic->i_recv_hdrs[recv - ic->i_recvs];
-	void *addr;
-	u32 misplaced_hdr_bytes;
-
-	/*
-	 * Support header at the front (RDS 3.1+) as well as header-at-end.
-	 *
-	 * Cases:
-	 * 1) header all in header buff (great!)
-	 * 2) header all in data page (copy all to header buff)
-	 * 3) header split across hdr buf + data page
-	 *    (move bit in hdr buff to end before copying other bit from data page)
-	 */
-	if (conn->c_version > RDS_PROTOCOL_3_0 || data_len == RDS_FRAG_SIZE)
-	        return hdr_buff;
-
-	if (data_len <= (RDS_FRAG_SIZE - sizeof(struct rds_header))) {
-		addr = kmap_atomic(recv->r_frag->f_page, KM_SOFTIRQ0);
-		memcpy(hdr_buff,
-		       addr + recv->r_frag->f_offset + data_len,
-		       sizeof(struct rds_header));
-		kunmap_atomic(addr, KM_SOFTIRQ0);
-		return hdr_buff;
-	}
-
-	misplaced_hdr_bytes = (sizeof(struct rds_header) - (RDS_FRAG_SIZE - data_len));
-
-	memmove(hdr_buff + misplaced_hdr_bytes, hdr_buff, misplaced_hdr_bytes);
-
-	addr = kmap_atomic(recv->r_frag->f_page, KM_SOFTIRQ0);
-	memcpy(hdr_buff, addr + recv->r_frag->f_offset + data_len,
-	       sizeof(struct rds_header) - misplaced_hdr_bytes);
-	kunmap_atomic(addr, KM_SOFTIRQ0);
-	return hdr_buff;
-}
-
 /*
  * It's kind of lame that we're copying from the posted receive pages into
  * long-lived bitmaps.  We could have posted the bitmaps and rdma written into
@@ -639,7 +763,7 @@
 		to_copy = min(RDS_FRAG_SIZE - frag_off, PAGE_SIZE - map_off);
 		BUG_ON(to_copy & 7); /* Must be 64bit aligned. */
 
-		addr = kmap_atomic(frag->f_page, KM_SOFTIRQ0);
+		addr = kmap_atomic(sg_page(&frag->f_sg), KM_SOFTIRQ0);
 
 		src = addr + frag_off;
 		dst = (void *)map->m_page_addrs[map_page] + map_off;
@@ -710,7 +834,7 @@
 	}
 	data_len -= sizeof(struct rds_header);
 
-	ihdr = rds_ib_get_header(conn, recv, data_len);
+	ihdr = &ic->i_recv_hdrs[recv - ic->i_recvs];
 
 	/* Validate the checksum. */
 	if (!rds_message_verify_checksum(ihdr)) {
@@ -742,12 +866,12 @@
 		 * the inc is freed.  We don't go that route, so we have to drop the
 		 * page ref ourselves.  We can't just leave the page on the recv
 		 * because that confuses the dma mapping of pages and each recv's use
-		 * of a partial page.  We can leave the frag, though, it will be
-		 * reused.
+		 * of a partial page.
 		 *
 		 * FIXME: Fold this into the code path below.
 		 */
-		rds_ib_frag_drop_page(recv->r_frag);
+		rds_ib_frag_free(ic, recv->r_frag);
+		recv->r_frag = NULL;
 		return;
 	}
 
@@ -757,7 +881,7 @@
 	 * into the inc and save the inc so we can hang upcoming fragments
 	 * off its list.
 	 */
-	if (ibinc == NULL) {
+	if (!ibinc) {
 		ibinc = recv->r_ibinc;
 		recv->r_ibinc = NULL;
 		ic->i_ibinc = ibinc;
@@ -842,32 +966,38 @@
 	struct rds_ib_recv_work *recv;
 
 	while (ib_poll_cq(ic->i_recv_cq, 1, &wc) > 0) {
-		rdsdebug("wc wr_id 0x%llx status %u byte_len %u imm_data %u\n",
-			 (unsigned long long)wc.wr_id, wc.status, wc.byte_len,
+		rdsdebug("wc wr_id 0x%llx status %u (%s) byte_len %u imm_data %u\n",
+			 (unsigned long long)wc.wr_id, wc.status,
+			 rds_ib_wc_status_str(wc.status), wc.byte_len,
 			 be32_to_cpu(wc.ex.imm_data));
 		rds_ib_stats_inc(s_ib_rx_cq_event);
 
 		recv = &ic->i_recvs[rds_ib_ring_oldest(&ic->i_recv_ring)];
 
-		rds_ib_recv_unmap_page(ic, recv);
+		ib_dma_unmap_sg(ic->i_cm_id->device, &recv->r_frag->f_sg, 1, DMA_FROM_DEVICE);
 
 		/*
 		 * Also process recvs in connecting state because it is possible
 		 * to get a recv completion _before_ the rdmacm ESTABLISHED
 		 * event is processed.
 		 */
-		if (rds_conn_up(conn) || rds_conn_connecting(conn)) {
+		if (wc.status == IB_WC_SUCCESS) {
+			rds_ib_process_recv(conn, recv, wc.byte_len, state);
+		} else {
 			/* We expect errors as the qp is drained during shutdown */
-			if (wc.status == IB_WC_SUCCESS) {
-				rds_ib_process_recv(conn, recv, wc.byte_len, state);
-			} else {
-				rds_ib_conn_error(conn, "recv completion on "
-				       "%pI4 had status %u, disconnecting and "
-				       "reconnecting\n", &conn->c_faddr,
-				       wc.status);
-			}
+			if (rds_conn_up(conn) || rds_conn_connecting(conn))
+				rds_ib_conn_error(conn, "recv completion on %pI4 had "
+						  "status %u (%s), disconnecting and "
+						  "reconnecting\n", &conn->c_faddr,
+						  wc.status,
+						  rds_ib_wc_status_str(wc.status));
 		}
 
+		/*
+		 * It's very important that we only free this ring entry if we've truly
+		 * freed the resources allocated to the entry.  The refilling path can
+		 * leak if we don't.
+		 */
 		rds_ib_ring_free(&ic->i_recv_ring, 1);
 	}
 }
@@ -897,11 +1027,8 @@
 	if (rds_ib_ring_empty(&ic->i_recv_ring))
 		rds_ib_stats_inc(s_ib_rx_ring_empty);
 
-	/*
-	 * If the ring is running low, then schedule the thread to refill.
-	 */
 	if (rds_ib_ring_low(&ic->i_recv_ring))
-		queue_delayed_work(rds_wq, &conn->c_recv_w, 0);
+		rds_ib_recv_refill(conn, 0);
 }
 
 int rds_ib_recv(struct rds_connection *conn)
@@ -910,25 +1037,13 @@
 	int ret = 0;
 
 	rdsdebug("conn %p\n", conn);
-
-	/*
-	 * If we get a temporary posting failure in this context then
-	 * we're really low and we want the caller to back off for a bit.
-	 */
-	mutex_lock(&ic->i_recv_mutex);
-	if (rds_ib_recv_refill(conn, GFP_KERNEL, GFP_HIGHUSER, 0))
-		ret = -ENOMEM;
-	else
-		rds_ib_stats_inc(s_ib_rx_refill_from_thread);
-	mutex_unlock(&ic->i_recv_mutex);
-
 	if (rds_conn_up(conn))
 		rds_ib_attempt_ack(ic);
 
 	return ret;
 }
 
-int __init rds_ib_recv_init(void)
+int rds_ib_recv_init(void)
 {
 	struct sysinfo si;
 	int ret = -ENOMEM;
@@ -939,14 +1054,14 @@
 
 	rds_ib_incoming_slab = kmem_cache_create("rds_ib_incoming",
 					sizeof(struct rds_ib_incoming),
-					0, 0, NULL);
-	if (rds_ib_incoming_slab == NULL)
+					0, SLAB_HWCACHE_ALIGN, NULL);
+	if (!rds_ib_incoming_slab)
 		goto out;
 
 	rds_ib_frag_slab = kmem_cache_create("rds_ib_frag",
 					sizeof(struct rds_page_frag),
-					0, 0, NULL);
-	if (rds_ib_frag_slab == NULL)
+					0, SLAB_HWCACHE_ALIGN, NULL);
+	if (!rds_ib_frag_slab)
 		kmem_cache_destroy(rds_ib_incoming_slab);
 	else
 		ret = 0;
diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c
index 17fa808..71f373c 100644
--- a/net/rds/ib_send.c
+++ b/net/rds/ib_send.c
@@ -36,11 +36,49 @@
 #include <linux/dmapool.h>
 
 #include "rds.h"
-#include "rdma.h"
 #include "ib.h"
 
-static void rds_ib_send_rdma_complete(struct rds_message *rm,
-				      int wc_status)
+static char *rds_ib_wc_status_strings[] = {
+#define RDS_IB_WC_STATUS_STR(foo) \
+		[IB_WC_##foo] = __stringify(IB_WC_##foo)
+	RDS_IB_WC_STATUS_STR(SUCCESS),
+	RDS_IB_WC_STATUS_STR(LOC_LEN_ERR),
+	RDS_IB_WC_STATUS_STR(LOC_QP_OP_ERR),
+	RDS_IB_WC_STATUS_STR(LOC_EEC_OP_ERR),
+	RDS_IB_WC_STATUS_STR(LOC_PROT_ERR),
+	RDS_IB_WC_STATUS_STR(WR_FLUSH_ERR),
+	RDS_IB_WC_STATUS_STR(MW_BIND_ERR),
+	RDS_IB_WC_STATUS_STR(BAD_RESP_ERR),
+	RDS_IB_WC_STATUS_STR(LOC_ACCESS_ERR),
+	RDS_IB_WC_STATUS_STR(REM_INV_REQ_ERR),
+	RDS_IB_WC_STATUS_STR(REM_ACCESS_ERR),
+	RDS_IB_WC_STATUS_STR(REM_OP_ERR),
+	RDS_IB_WC_STATUS_STR(RETRY_EXC_ERR),
+	RDS_IB_WC_STATUS_STR(RNR_RETRY_EXC_ERR),
+	RDS_IB_WC_STATUS_STR(LOC_RDD_VIOL_ERR),
+	RDS_IB_WC_STATUS_STR(REM_INV_RD_REQ_ERR),
+	RDS_IB_WC_STATUS_STR(REM_ABORT_ERR),
+	RDS_IB_WC_STATUS_STR(INV_EECN_ERR),
+	RDS_IB_WC_STATUS_STR(INV_EEC_STATE_ERR),
+	RDS_IB_WC_STATUS_STR(FATAL_ERR),
+	RDS_IB_WC_STATUS_STR(RESP_TIMEOUT_ERR),
+	RDS_IB_WC_STATUS_STR(GENERAL_ERR),
+#undef RDS_IB_WC_STATUS_STR
+};
+
+char *rds_ib_wc_status_str(enum ib_wc_status status)
+{
+	return rds_str_array(rds_ib_wc_status_strings,
+			     ARRAY_SIZE(rds_ib_wc_status_strings), status);
+}
+
+/*
+ * Convert IB-specific error message to RDS error message and call core
+ * completion handler.
+ */
+static void rds_ib_send_complete(struct rds_message *rm,
+				 int wc_status,
+				 void (*complete)(struct rds_message *rm, int status))
 {
 	int notify_status;
 
@@ -60,69 +98,125 @@
 		notify_status = RDS_RDMA_OTHER_ERROR;
 		break;
 	}
-	rds_rdma_send_complete(rm, notify_status);
+	complete(rm, notify_status);
+}
+
+static void rds_ib_send_unmap_data(struct rds_ib_connection *ic,
+				   struct rm_data_op *op,
+				   int wc_status)
+{
+	if (op->op_nents)
+		ib_dma_unmap_sg(ic->i_cm_id->device,
+				op->op_sg, op->op_nents,
+				DMA_TO_DEVICE);
 }
 
 static void rds_ib_send_unmap_rdma(struct rds_ib_connection *ic,
-				   struct rds_rdma_op *op)
+				   struct rm_rdma_op *op,
+				   int wc_status)
 {
-	if (op->r_mapped) {
+	if (op->op_mapped) {
 		ib_dma_unmap_sg(ic->i_cm_id->device,
-			op->r_sg, op->r_nents,
-			op->r_write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		op->r_mapped = 0;
+				op->op_sg, op->op_nents,
+				op->op_write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		op->op_mapped = 0;
 	}
+
+	/* If the user asked for a completion notification on this
+	 * message, we can implement three different semantics:
+	 *  1.	Notify when we received the ACK on the RDS message
+	 *	that was queued with the RDMA. This provides reliable
+	 *	notification of RDMA status at the expense of a one-way
+	 *	packet delay.
+	 *  2.	Notify when the IB stack gives us the completion event for
+	 *	the RDMA operation.
+	 *  3.	Notify when the IB stack gives us the completion event for
+	 *	the accompanying RDS messages.
+	 * Here, we implement approach #3. To implement approach #2,
+	 * we would need to take an event for the rdma WR. To implement #1,
+	 * don't call rds_rdma_send_complete at all, and fall back to the notify
+	 * handling in the ACK processing code.
+	 *
+	 * Note: There's no need to explicitly sync any RDMA buffers using
+	 * ib_dma_sync_sg_for_cpu - the completion for the RDMA
+	 * operation itself unmapped the RDMA buffers, which takes care
+	 * of synching.
+	 */
+	rds_ib_send_complete(container_of(op, struct rds_message, rdma),
+			     wc_status, rds_rdma_send_complete);
+
+	if (op->op_write)
+		rds_stats_add(s_send_rdma_bytes, op->op_bytes);
+	else
+		rds_stats_add(s_recv_rdma_bytes, op->op_bytes);
 }
 
-static void rds_ib_send_unmap_rm(struct rds_ib_connection *ic,
-			  struct rds_ib_send_work *send,
-			  int wc_status)
+static void rds_ib_send_unmap_atomic(struct rds_ib_connection *ic,
+				     struct rm_atomic_op *op,
+				     int wc_status)
 {
-	struct rds_message *rm = send->s_rm;
-
-	rdsdebug("ic %p send %p rm %p\n", ic, send, rm);
-
-	ib_dma_unmap_sg(ic->i_cm_id->device,
-		     rm->m_sg, rm->m_nents,
-		     DMA_TO_DEVICE);
-
-	if (rm->m_rdma_op != NULL) {
-		rds_ib_send_unmap_rdma(ic, rm->m_rdma_op);
-
-		/* If the user asked for a completion notification on this
-		 * message, we can implement three different semantics:
-		 *  1.	Notify when we received the ACK on the RDS message
-		 *	that was queued with the RDMA. This provides reliable
-		 *	notification of RDMA status at the expense of a one-way
-		 *	packet delay.
-		 *  2.	Notify when the IB stack gives us the completion event for
-		 *	the RDMA operation.
-		 *  3.	Notify when the IB stack gives us the completion event for
-		 *	the accompanying RDS messages.
-		 * Here, we implement approach #3. To implement approach #2,
-		 * call rds_rdma_send_complete from the cq_handler. To implement #1,
-		 * don't call rds_rdma_send_complete at all, and fall back to the notify
-		 * handling in the ACK processing code.
-		 *
-		 * Note: There's no need to explicitly sync any RDMA buffers using
-		 * ib_dma_sync_sg_for_cpu - the completion for the RDMA
-		 * operation itself unmapped the RDMA buffers, which takes care
-		 * of synching.
-		 */
-		rds_ib_send_rdma_complete(rm, wc_status);
-
-		if (rm->m_rdma_op->r_write)
-			rds_stats_add(s_send_rdma_bytes, rm->m_rdma_op->r_bytes);
-		else
-			rds_stats_add(s_recv_rdma_bytes, rm->m_rdma_op->r_bytes);
+	/* unmap atomic recvbuf */
+	if (op->op_mapped) {
+		ib_dma_unmap_sg(ic->i_cm_id->device, op->op_sg, 1,
+				DMA_FROM_DEVICE);
+		op->op_mapped = 0;
 	}
 
-	/* If anyone waited for this message to get flushed out, wake
-	 * them up now */
-	rds_message_unmapped(rm);
+	rds_ib_send_complete(container_of(op, struct rds_message, atomic),
+			     wc_status, rds_atomic_send_complete);
 
-	rds_message_put(rm);
-	send->s_rm = NULL;
+	if (op->op_type == RDS_ATOMIC_TYPE_CSWP)
+		rds_ib_stats_inc(s_ib_atomic_cswp);
+	else
+		rds_ib_stats_inc(s_ib_atomic_fadd);
+}
+
+/*
+ * Unmap the resources associated with a struct send_work.
+ *
+ * Returns the rm for no good reason other than it is unobtainable
+ * other than by switching on wr.opcode, currently, and the caller,
+ * the event handler, needs it.
+ */
+static struct rds_message *rds_ib_send_unmap_op(struct rds_ib_connection *ic,
+						struct rds_ib_send_work *send,
+						int wc_status)
+{
+	struct rds_message *rm = NULL;
+
+	/* In the error case, wc.opcode sometimes contains garbage */
+	switch (send->s_wr.opcode) {
+	case IB_WR_SEND:
+		if (send->s_op) {
+			rm = container_of(send->s_op, struct rds_message, data);
+			rds_ib_send_unmap_data(ic, send->s_op, wc_status);
+		}
+		break;
+	case IB_WR_RDMA_WRITE:
+	case IB_WR_RDMA_READ:
+		if (send->s_op) {
+			rm = container_of(send->s_op, struct rds_message, rdma);
+			rds_ib_send_unmap_rdma(ic, send->s_op, wc_status);
+		}
+		break;
+	case IB_WR_ATOMIC_FETCH_AND_ADD:
+	case IB_WR_ATOMIC_CMP_AND_SWP:
+		if (send->s_op) {
+			rm = container_of(send->s_op, struct rds_message, atomic);
+			rds_ib_send_unmap_atomic(ic, send->s_op, wc_status);
+		}
+		break;
+	default:
+		if (printk_ratelimit())
+			printk(KERN_NOTICE
+			       "RDS/IB: %s: unexpected opcode 0x%x in WR!\n",
+			       __func__, send->s_wr.opcode);
+		break;
+	}
+
+	send->s_wr.opcode = 0xdead;
+
+	return rm;
 }
 
 void rds_ib_send_init_ring(struct rds_ib_connection *ic)
@@ -133,23 +227,18 @@
 	for (i = 0, send = ic->i_sends; i < ic->i_send_ring.w_nr; i++, send++) {
 		struct ib_sge *sge;
 
-		send->s_rm = NULL;
 		send->s_op = NULL;
 
 		send->s_wr.wr_id = i;
 		send->s_wr.sg_list = send->s_sge;
-		send->s_wr.num_sge = 1;
-		send->s_wr.opcode = IB_WR_SEND;
-		send->s_wr.send_flags = 0;
 		send->s_wr.ex.imm_data = 0;
 
-		sge = rds_ib_data_sge(ic, send->s_sge);
-		sge->lkey = ic->i_mr->lkey;
-
-		sge = rds_ib_header_sge(ic, send->s_sge);
+		sge = &send->s_sge[0];
 		sge->addr = ic->i_send_hdrs_dma + (i * sizeof(struct rds_header));
 		sge->length = sizeof(struct rds_header);
 		sge->lkey = ic->i_mr->lkey;
+
+		send->s_sge[1].lkey = ic->i_mr->lkey;
 	}
 }
 
@@ -159,16 +248,24 @@
 	u32 i;
 
 	for (i = 0, send = ic->i_sends; i < ic->i_send_ring.w_nr; i++, send++) {
-		if (send->s_wr.opcode == 0xdead)
-			continue;
-		if (send->s_rm)
-			rds_ib_send_unmap_rm(ic, send, IB_WC_WR_FLUSH_ERR);
-		if (send->s_op)
-			rds_ib_send_unmap_rdma(ic, send->s_op);
+		if (send->s_op && send->s_wr.opcode != 0xdead)
+			rds_ib_send_unmap_op(ic, send, IB_WC_WR_FLUSH_ERR);
 	}
 }
 
 /*
+ * The only fast path caller always has a non-zero nr, so we don't
+ * bother testing nr before performing the atomic sub.
+ */
+static void rds_ib_sub_signaled(struct rds_ib_connection *ic, int nr)
+{
+	if ((atomic_sub_return(nr, &ic->i_signaled_sends) == 0) &&
+	    waitqueue_active(&rds_ib_ring_empty_wait))
+		wake_up(&rds_ib_ring_empty_wait);
+	BUG_ON(atomic_read(&ic->i_signaled_sends) < 0);
+}
+
+/*
  * The _oldest/_free ring operations here race cleanly with the alloc/unalloc
  * operations performed in the send path.  As the sender allocs and potentially
  * unallocs the next free entry in the ring it doesn't alter which is
@@ -178,12 +275,14 @@
 {
 	struct rds_connection *conn = context;
 	struct rds_ib_connection *ic = conn->c_transport_data;
+	struct rds_message *rm = NULL;
 	struct ib_wc wc;
 	struct rds_ib_send_work *send;
 	u32 completed;
 	u32 oldest;
 	u32 i = 0;
 	int ret;
+	int nr_sig = 0;
 
 	rdsdebug("cq %p conn %p\n", cq, conn);
 	rds_ib_stats_inc(s_ib_tx_cq_call);
@@ -192,8 +291,9 @@
 		rdsdebug("ib_req_notify_cq send failed: %d\n", ret);
 
 	while (ib_poll_cq(cq, 1, &wc) > 0) {
-		rdsdebug("wc wr_id 0x%llx status %u byte_len %u imm_data %u\n",
-			 (unsigned long long)wc.wr_id, wc.status, wc.byte_len,
+		rdsdebug("wc wr_id 0x%llx status %u (%s) byte_len %u imm_data %u\n",
+			 (unsigned long long)wc.wr_id, wc.status,
+			 rds_ib_wc_status_str(wc.status), wc.byte_len,
 			 be32_to_cpu(wc.ex.imm_data));
 		rds_ib_stats_inc(s_ib_tx_cq_event);
 
@@ -210,51 +310,30 @@
 
 		for (i = 0; i < completed; i++) {
 			send = &ic->i_sends[oldest];
+			if (send->s_wr.send_flags & IB_SEND_SIGNALED)
+				nr_sig++;
 
-			/* In the error case, wc.opcode sometimes contains garbage */
-			switch (send->s_wr.opcode) {
-			case IB_WR_SEND:
-				if (send->s_rm)
-					rds_ib_send_unmap_rm(ic, send, wc.status);
-				break;
-			case IB_WR_RDMA_WRITE:
-			case IB_WR_RDMA_READ:
-				/* Nothing to be done - the SG list will be unmapped
-				 * when the SEND completes. */
-				break;
-			default:
-				if (printk_ratelimit())
-					printk(KERN_NOTICE
-						"RDS/IB: %s: unexpected opcode 0x%x in WR!\n",
-						__func__, send->s_wr.opcode);
-				break;
-			}
+			rm = rds_ib_send_unmap_op(ic, send, wc.status);
 
-			send->s_wr.opcode = 0xdead;
-			send->s_wr.num_sge = 1;
 			if (send->s_queued + HZ/2 < jiffies)
 				rds_ib_stats_inc(s_ib_tx_stalled);
 
-			/* If a RDMA operation produced an error, signal this right
-			 * away. If we don't, the subsequent SEND that goes with this
-			 * RDMA will be canceled with ERR_WFLUSH, and the application
-			 * never learn that the RDMA failed. */
-			if (unlikely(wc.status == IB_WC_REM_ACCESS_ERR && send->s_op)) {
-				struct rds_message *rm;
-
-				rm = rds_send_get_message(conn, send->s_op);
-				if (rm) {
-					if (rm->m_rdma_op)
-						rds_ib_send_unmap_rdma(ic, rm->m_rdma_op);
-					rds_ib_send_rdma_complete(rm, wc.status);
-					rds_message_put(rm);
+			if (send->s_op) {
+				if (send->s_op == rm->m_final_op) {
+					/* If anyone waited for this message to get flushed out, wake
+					 * them up now */
+					rds_message_unmapped(rm);
 				}
+				rds_message_put(rm);
+				send->s_op = NULL;
 			}
 
 			oldest = (oldest + 1) % ic->i_send_ring.w_nr;
 		}
 
 		rds_ib_ring_free(&ic->i_send_ring, completed);
+		rds_ib_sub_signaled(ic, nr_sig);
+		nr_sig = 0;
 
 		if (test_and_clear_bit(RDS_LL_SEND_FULL, &conn->c_flags) ||
 		    test_bit(0, &conn->c_map_queued))
@@ -262,10 +341,10 @@
 
 		/* We expect errors as the qp is drained during shutdown */
 		if (wc.status != IB_WC_SUCCESS && rds_conn_up(conn)) {
-			rds_ib_conn_error(conn,
-				"send completion on %pI4 "
-				"had status %u, disconnecting and reconnecting\n",
-				&conn->c_faddr, wc.status);
+			rds_ib_conn_error(conn, "send completion on %pI4 had status "
+					  "%u (%s), disconnecting and reconnecting\n",
+					  &conn->c_faddr, wc.status,
+					  rds_ib_wc_status_str(wc.status));
 		}
 	}
 }
@@ -294,7 +373,7 @@
  * credits (see rds_ib_send_add_credits below).
  *
  * The RDS send code is essentially single-threaded; rds_send_xmit
- * grabs c_send_lock to ensure exclusive access to the send ring.
+ * sets RDS_IN_XMIT to ensure exclusive access to the send ring.
  * However, the ACK sending code is independent and can race with
  * message SENDs.
  *
@@ -413,40 +492,21 @@
 		set_bit(IB_ACK_REQUESTED, &ic->i_ack_flags);
 }
 
-static inline void
-rds_ib_xmit_populate_wr(struct rds_ib_connection *ic,
-		struct rds_ib_send_work *send, unsigned int pos,
-		unsigned long buffer, unsigned int length,
-		int send_flags)
+static inline int rds_ib_set_wr_signal_state(struct rds_ib_connection *ic,
+					     struct rds_ib_send_work *send,
+					     bool notify)
 {
-	struct ib_sge *sge;
-
-	WARN_ON(pos != send - ic->i_sends);
-
-	send->s_wr.send_flags = send_flags;
-	send->s_wr.opcode = IB_WR_SEND;
-	send->s_wr.num_sge = 2;
-	send->s_wr.next = NULL;
-	send->s_queued = jiffies;
-	send->s_op = NULL;
-
-	if (length != 0) {
-		sge = rds_ib_data_sge(ic, send->s_sge);
-		sge->addr = buffer;
-		sge->length = length;
-		sge->lkey = ic->i_mr->lkey;
-
-		sge = rds_ib_header_sge(ic, send->s_sge);
-	} else {
-		/* We're sending a packet with no payload. There is only
-		 * one SGE */
-		send->s_wr.num_sge = 1;
-		sge = &send->s_sge[0];
+	/*
+	 * We want to delay signaling completions just enough to get
+	 * the batching benefits but not so much that we create dead time
+	 * on the wire.
+	 */
+	if (ic->i_unsignaled_wrs-- == 0 || notify) {
+		ic->i_unsignaled_wrs = rds_ib_sysctl_max_unsig_wrs;
+		send->s_wr.send_flags |= IB_SEND_SIGNALED;
+		return 1;
 	}
-
-	sge->addr = ic->i_send_hdrs_dma + (pos * sizeof(struct rds_header));
-	sge->length = sizeof(struct rds_header);
-	sge->lkey = ic->i_mr->lkey;
+	return 0;
 }
 
 /*
@@ -475,13 +535,14 @@
 	u32 pos;
 	u32 i;
 	u32 work_alloc;
-	u32 credit_alloc;
+	u32 credit_alloc = 0;
 	u32 posted;
 	u32 adv_credits = 0;
 	int send_flags = 0;
-	int sent;
+	int bytes_sent = 0;
 	int ret;
 	int flow_controlled = 0;
+	int nr_sig = 0;
 
 	BUG_ON(off % RDS_FRAG_SIZE);
 	BUG_ON(hdr_off != 0 && hdr_off != sizeof(struct rds_header));
@@ -507,14 +568,13 @@
 		goto out;
 	}
 
-	credit_alloc = work_alloc;
 	if (ic->i_flowctl) {
 		credit_alloc = rds_ib_send_grab_credits(ic, work_alloc, &posted, 0, RDS_MAX_ADV_CREDIT);
 		adv_credits += posted;
 		if (credit_alloc < work_alloc) {
 			rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc - credit_alloc);
 			work_alloc = credit_alloc;
-			flow_controlled++;
+			flow_controlled = 1;
 		}
 		if (work_alloc == 0) {
 			set_bit(RDS_LL_SEND_FULL, &conn->c_flags);
@@ -525,31 +585,25 @@
 	}
 
 	/* map the message the first time we see it */
-	if (ic->i_rm == NULL) {
-		/*
-		printk(KERN_NOTICE "rds_ib_xmit prep msg dport=%u flags=0x%x len=%d\n",
-				be16_to_cpu(rm->m_inc.i_hdr.h_dport),
-				rm->m_inc.i_hdr.h_flags,
-				be32_to_cpu(rm->m_inc.i_hdr.h_len));
-		   */
-		if (rm->m_nents) {
-			rm->m_count = ib_dma_map_sg(dev,
-					 rm->m_sg, rm->m_nents, DMA_TO_DEVICE);
-			rdsdebug("ic %p mapping rm %p: %d\n", ic, rm, rm->m_count);
-			if (rm->m_count == 0) {
+	if (!ic->i_data_op) {
+		if (rm->data.op_nents) {
+			rm->data.op_count = ib_dma_map_sg(dev,
+							  rm->data.op_sg,
+							  rm->data.op_nents,
+							  DMA_TO_DEVICE);
+			rdsdebug("ic %p mapping rm %p: %d\n", ic, rm, rm->data.op_count);
+			if (rm->data.op_count == 0) {
 				rds_ib_stats_inc(s_ib_tx_sg_mapping_failure);
 				rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc);
 				ret = -ENOMEM; /* XXX ? */
 				goto out;
 			}
 		} else {
-			rm->m_count = 0;
+			rm->data.op_count = 0;
 		}
 
-		ic->i_unsignaled_wrs = rds_ib_sysctl_max_unsig_wrs;
-		ic->i_unsignaled_bytes = rds_ib_sysctl_max_unsig_bytes;
 		rds_message_addref(rm);
-		ic->i_rm = rm;
+		ic->i_data_op = &rm->data;
 
 		/* Finalize the header */
 		if (test_bit(RDS_MSG_ACK_REQUIRED, &rm->m_flags))
@@ -559,10 +613,10 @@
 
 		/* If it has a RDMA op, tell the peer we did it. This is
 		 * used by the peer to release use-once RDMA MRs. */
-		if (rm->m_rdma_op) {
+		if (rm->rdma.op_active) {
 			struct rds_ext_header_rdma ext_hdr;
 
-			ext_hdr.h_rdma_rkey = cpu_to_be32(rm->m_rdma_op->r_key);
+			ext_hdr.h_rdma_rkey = cpu_to_be32(rm->rdma.op_rkey);
 			rds_message_add_extension(&rm->m_inc.i_hdr,
 					RDS_EXTHDR_RDMA, &ext_hdr, sizeof(ext_hdr));
 		}
@@ -582,99 +636,77 @@
 		/*
 		 * Update adv_credits since we reset the ACK_REQUIRED bit.
 		 */
-		rds_ib_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits);
-		adv_credits += posted;
-		BUG_ON(adv_credits > 255);
+		if (ic->i_flowctl) {
+			rds_ib_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits);
+			adv_credits += posted;
+			BUG_ON(adv_credits > 255);
+		}
 	}
 
-	send = &ic->i_sends[pos];
-	first = send;
-	prev = NULL;
-	scat = &rm->m_sg[sg];
-	sent = 0;
-	i = 0;
-
 	/* Sometimes you want to put a fence between an RDMA
 	 * READ and the following SEND.
 	 * We could either do this all the time
 	 * or when requested by the user. Right now, we let
 	 * the application choose.
 	 */
-	if (rm->m_rdma_op && rm->m_rdma_op->r_fence)
+	if (rm->rdma.op_active && rm->rdma.op_fence)
 		send_flags = IB_SEND_FENCE;
 
-	/*
-	 * We could be copying the header into the unused tail of the page.
-	 * That would need to be changed in the future when those pages might
-	 * be mapped userspace pages or page cache pages.  So instead we always
-	 * use a second sge and our long-lived ring of mapped headers.  We send
-	 * the header after the data so that the data payload can be aligned on
-	 * the receiver.
-	 */
+	/* Each frag gets a header. Msgs may be 0 bytes */
+	send = &ic->i_sends[pos];
+	first = send;
+	prev = NULL;
+	scat = &ic->i_data_op->op_sg[sg];
+	i = 0;
+	do {
+		unsigned int len = 0;
 
-	/* handle a 0-len message */
-	if (be32_to_cpu(rm->m_inc.i_hdr.h_len) == 0) {
-		rds_ib_xmit_populate_wr(ic, send, pos, 0, 0, send_flags);
-		goto add_header;
-	}
+		/* Set up the header */
+		send->s_wr.send_flags = send_flags;
+		send->s_wr.opcode = IB_WR_SEND;
+		send->s_wr.num_sge = 1;
+		send->s_wr.next = NULL;
+		send->s_queued = jiffies;
+		send->s_op = NULL;
 
-	/* if there's data reference it with a chain of work reqs */
-	for (; i < work_alloc && scat != &rm->m_sg[rm->m_count]; i++) {
-		unsigned int len;
+		send->s_sge[0].addr = ic->i_send_hdrs_dma
+			+ (pos * sizeof(struct rds_header));
+		send->s_sge[0].length = sizeof(struct rds_header);
 
-		send = &ic->i_sends[pos];
+		memcpy(&ic->i_send_hdrs[pos], &rm->m_inc.i_hdr, sizeof(struct rds_header));
 
-		len = min(RDS_FRAG_SIZE, ib_sg_dma_len(dev, scat) - off);
-		rds_ib_xmit_populate_wr(ic, send, pos,
-				ib_sg_dma_address(dev, scat) + off, len,
-				send_flags);
+		/* Set up the data, if present */
+		if (i < work_alloc
+		    && scat != &rm->data.op_sg[rm->data.op_count]) {
+			len = min(RDS_FRAG_SIZE, ib_sg_dma_len(dev, scat) - off);
+			send->s_wr.num_sge = 2;
 
-		/*
-		 * We want to delay signaling completions just enough to get
-		 * the batching benefits but not so much that we create dead time
-		 * on the wire.
-		 */
-		if (ic->i_unsignaled_wrs-- == 0) {
-			ic->i_unsignaled_wrs = rds_ib_sysctl_max_unsig_wrs;
-			send->s_wr.send_flags |= IB_SEND_SIGNALED | IB_SEND_SOLICITED;
+			send->s_sge[1].addr = ib_sg_dma_address(dev, scat) + off;
+			send->s_sge[1].length = len;
+
+			bytes_sent += len;
+			off += len;
+			if (off == ib_sg_dma_len(dev, scat)) {
+				scat++;
+				off = 0;
+			}
 		}
 
-		ic->i_unsignaled_bytes -= len;
-		if (ic->i_unsignaled_bytes <= 0) {
-			ic->i_unsignaled_bytes = rds_ib_sysctl_max_unsig_bytes;
-			send->s_wr.send_flags |= IB_SEND_SIGNALED | IB_SEND_SOLICITED;
-		}
+		rds_ib_set_wr_signal_state(ic, send, 0);
 
 		/*
 		 * Always signal the last one if we're stopping due to flow control.
 		 */
-		if (flow_controlled && i == (work_alloc-1))
+		if (ic->i_flowctl && flow_controlled && i == (work_alloc-1))
 			send->s_wr.send_flags |= IB_SEND_SIGNALED | IB_SEND_SOLICITED;
 
+		if (send->s_wr.send_flags & IB_SEND_SIGNALED)
+			nr_sig++;
+
 		rdsdebug("send %p wr %p num_sge %u next %p\n", send,
 			 &send->s_wr, send->s_wr.num_sge, send->s_wr.next);
 
-		sent += len;
-		off += len;
-		if (off == ib_sg_dma_len(dev, scat)) {
-			scat++;
-			off = 0;
-		}
-
-add_header:
-		/* Tack on the header after the data. The header SGE should already
-		 * have been set up to point to the right header buffer. */
-		memcpy(&ic->i_send_hdrs[pos], &rm->m_inc.i_hdr, sizeof(struct rds_header));
-
-		if (0) {
-			struct rds_header *hdr = &ic->i_send_hdrs[pos];
-
-			printk(KERN_NOTICE "send WR dport=%u flags=0x%x len=%d\n",
-				be16_to_cpu(hdr->h_dport),
-				hdr->h_flags,
-				be32_to_cpu(hdr->h_len));
-		}
-		if (adv_credits) {
+		if (ic->i_flowctl && adv_credits) {
 			struct rds_header *hdr = &ic->i_send_hdrs[pos];
 
 			/* add credit and redo the header checksum */
@@ -689,20 +721,25 @@
 		prev = send;
 
 		pos = (pos + 1) % ic->i_send_ring.w_nr;
-	}
+		send = &ic->i_sends[pos];
+		i++;
+
+	} while (i < work_alloc
+		 && scat != &rm->data.op_sg[rm->data.op_count]);
 
 	/* Account the RDS header in the number of bytes we sent, but just once.
 	 * The caller has no concept of fragmentation. */
 	if (hdr_off == 0)
-		sent += sizeof(struct rds_header);
+		bytes_sent += sizeof(struct rds_header);
 
 	/* if we finished the message then send completion owns it */
-	if (scat == &rm->m_sg[rm->m_count]) {
-		prev->s_rm = ic->i_rm;
-		prev->s_wr.send_flags |= IB_SEND_SIGNALED | IB_SEND_SOLICITED;
-		ic->i_rm = NULL;
+	if (scat == &rm->data.op_sg[rm->data.op_count]) {
+		prev->s_op = ic->i_data_op;
+		prev->s_wr.send_flags |= IB_SEND_SOLICITED;
+		ic->i_data_op = NULL;
 	}
 
+	/* Put back wrs & credits we didn't use */
 	if (i < work_alloc) {
 		rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc - i);
 		work_alloc = i;
@@ -710,6 +747,9 @@
 	if (ic->i_flowctl && i < credit_alloc)
 		rds_ib_send_add_credits(conn, credit_alloc - i);
 
+	if (nr_sig)
+		atomic_add(nr_sig, &ic->i_signaled_sends);
+
 	/* XXX need to worry about failed_wr and partial sends. */
 	failed_wr = &first->s_wr;
 	ret = ib_post_send(ic->i_cm_id->qp, &first->s_wr, &failed_wr);
@@ -720,32 +760,127 @@
 		printk(KERN_WARNING "RDS/IB: ib_post_send to %pI4 "
 		       "returned %d\n", &conn->c_faddr, ret);
 		rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc);
-		if (prev->s_rm) {
-			ic->i_rm = prev->s_rm;
-			prev->s_rm = NULL;
+		rds_ib_sub_signaled(ic, nr_sig);
+		if (prev->s_op) {
+			ic->i_data_op = prev->s_op;
+			prev->s_op = NULL;
 		}
 
 		rds_ib_conn_error(ic->conn, "ib_post_send failed\n");
 		goto out;
 	}
 
-	ret = sent;
+	ret = bytes_sent;
 out:
 	BUG_ON(adv_credits);
 	return ret;
 }
 
-int rds_ib_xmit_rdma(struct rds_connection *conn, struct rds_rdma_op *op)
+/*
+ * Issue atomic operation.
+ * A simplified version of the rdma case, we always map 1 SG, and
+ * only 8 bytes, for the return value from the atomic operation.
+ */
+int rds_ib_xmit_atomic(struct rds_connection *conn, struct rm_atomic_op *op)
+{
+	struct rds_ib_connection *ic = conn->c_transport_data;
+	struct rds_ib_send_work *send = NULL;
+	struct ib_send_wr *failed_wr;
+	struct rds_ib_device *rds_ibdev;
+	u32 pos;
+	u32 work_alloc;
+	int ret;
+	int nr_sig = 0;
+
+	rds_ibdev = ib_get_client_data(ic->i_cm_id->device, &rds_ib_client);
+
+	work_alloc = rds_ib_ring_alloc(&ic->i_send_ring, 1, &pos);
+	if (work_alloc != 1) {
+		rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc);
+		rds_ib_stats_inc(s_ib_tx_ring_full);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* address of send request in ring */
+	send = &ic->i_sends[pos];
+	send->s_queued = jiffies;
+
+	if (op->op_type == RDS_ATOMIC_TYPE_CSWP) {
+		send->s_wr.opcode = IB_WR_MASKED_ATOMIC_CMP_AND_SWP;
+		send->s_wr.wr.atomic.compare_add = op->op_m_cswp.compare;
+		send->s_wr.wr.atomic.swap = op->op_m_cswp.swap;
+		send->s_wr.wr.atomic.compare_add_mask = op->op_m_cswp.compare_mask;
+		send->s_wr.wr.atomic.swap_mask = op->op_m_cswp.swap_mask;
+	} else { /* FADD */
+		send->s_wr.opcode = IB_WR_MASKED_ATOMIC_FETCH_AND_ADD;
+		send->s_wr.wr.atomic.compare_add = op->op_m_fadd.add;
+		send->s_wr.wr.atomic.swap = 0;
+		send->s_wr.wr.atomic.compare_add_mask = op->op_m_fadd.nocarry_mask;
+		send->s_wr.wr.atomic.swap_mask = 0;
+	}
+	nr_sig = rds_ib_set_wr_signal_state(ic, send, op->op_notify);
+	send->s_wr.num_sge = 1;
+	send->s_wr.next = NULL;
+	send->s_wr.wr.atomic.remote_addr = op->op_remote_addr;
+	send->s_wr.wr.atomic.rkey = op->op_rkey;
+	send->s_op = op;
+	rds_message_addref(container_of(send->s_op, struct rds_message, atomic));
+
+	/* map 8 byte retval buffer to the device */
+	ret = ib_dma_map_sg(ic->i_cm_id->device, op->op_sg, 1, DMA_FROM_DEVICE);
+	rdsdebug("ic %p mapping atomic op %p. mapped %d pg\n", ic, op, ret);
+	if (ret != 1) {
+		rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc);
+		rds_ib_stats_inc(s_ib_tx_sg_mapping_failure);
+		ret = -ENOMEM; /* XXX ? */
+		goto out;
+	}
+
+	/* Convert our struct scatterlist to struct ib_sge */
+	send->s_sge[0].addr = ib_sg_dma_address(ic->i_cm_id->device, op->op_sg);
+	send->s_sge[0].length = ib_sg_dma_len(ic->i_cm_id->device, op->op_sg);
+	send->s_sge[0].lkey = ic->i_mr->lkey;
+
+	rdsdebug("rva %Lx rpa %Lx len %u\n", op->op_remote_addr,
+		 send->s_sge[0].addr, send->s_sge[0].length);
+
+	if (nr_sig)
+		atomic_add(nr_sig, &ic->i_signaled_sends);
+
+	failed_wr = &send->s_wr;
+	ret = ib_post_send(ic->i_cm_id->qp, &send->s_wr, &failed_wr);
+	rdsdebug("ic %p send %p (wr %p) ret %d wr %p\n", ic,
+		 send, &send->s_wr, ret, failed_wr);
+	BUG_ON(failed_wr != &send->s_wr);
+	if (ret) {
+		printk(KERN_WARNING "RDS/IB: atomic ib_post_send to %pI4 "
+		       "returned %d\n", &conn->c_faddr, ret);
+		rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc);
+		rds_ib_sub_signaled(ic, nr_sig);
+		goto out;
+	}
+
+	if (unlikely(failed_wr != &send->s_wr)) {
+		printk(KERN_WARNING "RDS/IB: atomic ib_post_send() rc=%d, but failed_wqe updated!\n", ret);
+		BUG_ON(failed_wr != &send->s_wr);
+	}
+
+out:
+	return ret;
+}
+
+int rds_ib_xmit_rdma(struct rds_connection *conn, struct rm_rdma_op *op)
 {
 	struct rds_ib_connection *ic = conn->c_transport_data;
 	struct rds_ib_send_work *send = NULL;
 	struct rds_ib_send_work *first;
 	struct rds_ib_send_work *prev;
 	struct ib_send_wr *failed_wr;
-	struct rds_ib_device *rds_ibdev;
 	struct scatterlist *scat;
 	unsigned long len;
-	u64 remote_addr = op->r_remote_addr;
+	u64 remote_addr = op->op_remote_addr;
+	u32 max_sge = ic->rds_ibdev->max_sge;
 	u32 pos;
 	u32 work_alloc;
 	u32 i;
@@ -753,29 +888,28 @@
 	int sent;
 	int ret;
 	int num_sge;
+	int nr_sig = 0;
 
-	rds_ibdev = ib_get_client_data(ic->i_cm_id->device, &rds_ib_client);
-
-	/* map the message the first time we see it */
-	if (!op->r_mapped) {
-		op->r_count = ib_dma_map_sg(ic->i_cm_id->device,
-					op->r_sg, op->r_nents, (op->r_write) ?
-					DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		rdsdebug("ic %p mapping op %p: %d\n", ic, op, op->r_count);
-		if (op->r_count == 0) {
+	/* map the op the first time we see it */
+	if (!op->op_mapped) {
+		op->op_count = ib_dma_map_sg(ic->i_cm_id->device,
+					     op->op_sg, op->op_nents, (op->op_write) ?
+					     DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		rdsdebug("ic %p mapping op %p: %d\n", ic, op, op->op_count);
+		if (op->op_count == 0) {
 			rds_ib_stats_inc(s_ib_tx_sg_mapping_failure);
 			ret = -ENOMEM; /* XXX ? */
 			goto out;
 		}
 
-		op->r_mapped = 1;
+		op->op_mapped = 1;
 	}
 
 	/*
 	 * Instead of knowing how to return a partial rdma read/write we insist that there
 	 * be enough work requests to send the entire message.
 	 */
-	i = ceil(op->r_count, rds_ibdev->max_sge);
+	i = ceil(op->op_count, max_sge);
 
 	work_alloc = rds_ib_ring_alloc(&ic->i_send_ring, i, &pos);
 	if (work_alloc != i) {
@@ -788,30 +922,24 @@
 	send = &ic->i_sends[pos];
 	first = send;
 	prev = NULL;
-	scat = &op->r_sg[0];
+	scat = &op->op_sg[0];
 	sent = 0;
-	num_sge = op->r_count;
+	num_sge = op->op_count;
 
-	for (i = 0; i < work_alloc && scat != &op->r_sg[op->r_count]; i++) {
+	for (i = 0; i < work_alloc && scat != &op->op_sg[op->op_count]; i++) {
 		send->s_wr.send_flags = 0;
 		send->s_queued = jiffies;
-		/*
-		 * We want to delay signaling completions just enough to get
-		 * the batching benefits but not so much that we create dead time on the wire.
-		 */
-		if (ic->i_unsignaled_wrs-- == 0) {
-			ic->i_unsignaled_wrs = rds_ib_sysctl_max_unsig_wrs;
-			send->s_wr.send_flags = IB_SEND_SIGNALED;
-		}
+		send->s_op = NULL;
 
-		send->s_wr.opcode = op->r_write ? IB_WR_RDMA_WRITE : IB_WR_RDMA_READ;
+		nr_sig += rds_ib_set_wr_signal_state(ic, send, op->op_notify);
+
+		send->s_wr.opcode = op->op_write ? IB_WR_RDMA_WRITE : IB_WR_RDMA_READ;
 		send->s_wr.wr.rdma.remote_addr = remote_addr;
-		send->s_wr.wr.rdma.rkey = op->r_key;
-		send->s_op = op;
+		send->s_wr.wr.rdma.rkey = op->op_rkey;
 
-		if (num_sge > rds_ibdev->max_sge) {
-			send->s_wr.num_sge = rds_ibdev->max_sge;
-			num_sge -= rds_ibdev->max_sge;
+		if (num_sge > max_sge) {
+			send->s_wr.num_sge = max_sge;
+			num_sge -= max_sge;
 		} else {
 			send->s_wr.num_sge = num_sge;
 		}
@@ -821,7 +949,7 @@
 		if (prev)
 			prev->s_wr.next = &send->s_wr;
 
-		for (j = 0; j < send->s_wr.num_sge && scat != &op->r_sg[op->r_count]; j++) {
+		for (j = 0; j < send->s_wr.num_sge && scat != &op->op_sg[op->op_count]; j++) {
 			len = ib_sg_dma_len(ic->i_cm_id->device, scat);
 			send->s_sge[j].addr =
 				 ib_sg_dma_address(ic->i_cm_id->device, scat);
@@ -843,15 +971,20 @@
 			send = ic->i_sends;
 	}
 
-	/* if we finished the message then send completion owns it */
-	if (scat == &op->r_sg[op->r_count])
-		prev->s_wr.send_flags = IB_SEND_SIGNALED;
+	/* give a reference to the last op */
+	if (scat == &op->op_sg[op->op_count]) {
+		prev->s_op = op;
+		rds_message_addref(container_of(op, struct rds_message, rdma));
+	}
 
 	if (i < work_alloc) {
 		rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc - i);
 		work_alloc = i;
 	}
 
+	if (nr_sig)
+		atomic_add(nr_sig, &ic->i_signaled_sends);
+
 	failed_wr = &first->s_wr;
 	ret = ib_post_send(ic->i_cm_id->qp, &first->s_wr, &failed_wr);
 	rdsdebug("ic %p first %p (wr %p) ret %d wr %p\n", ic,
@@ -861,6 +994,7 @@
 		printk(KERN_WARNING "RDS/IB: rdma ib_post_send to %pI4 "
 		       "returned %d\n", &conn->c_faddr, ret);
 		rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc);
+		rds_ib_sub_signaled(ic, nr_sig);
 		goto out;
 	}
 
diff --git a/net/rds/ib_stats.c b/net/rds/ib_stats.c
index d2c904d..2d5965d 100644
--- a/net/rds/ib_stats.c
+++ b/net/rds/ib_stats.c
@@ -67,6 +67,8 @@
 	"ib_rdma_mr_pool_flush",
 	"ib_rdma_mr_pool_wait",
 	"ib_rdma_mr_pool_depleted",
+	"ib_atomic_cswp",
+	"ib_atomic_fadd",
 };
 
 unsigned int rds_ib_stats_info_copy(struct rds_info_iterator *iter,
diff --git a/net/rds/ib_sysctl.c b/net/rds/ib_sysctl.c
index 03f01cb..1253b00 100644
--- a/net/rds/ib_sysctl.c
+++ b/net/rds/ib_sysctl.c
@@ -49,10 +49,6 @@
 static unsigned long rds_ib_sysctl_max_unsig_wr_min = 1;
 static unsigned long rds_ib_sysctl_max_unsig_wr_max = 64;
 
-unsigned long rds_ib_sysctl_max_unsig_bytes = (16 << 20);
-static unsigned long rds_ib_sysctl_max_unsig_bytes_min = 1;
-static unsigned long rds_ib_sysctl_max_unsig_bytes_max = ~0UL;
-
 /*
  * This sysctl does nothing.
  *
@@ -65,7 +61,7 @@
  */
 unsigned int rds_ib_sysctl_flow_control = 0;
 
-ctl_table rds_ib_sysctl_table[] = {
+static ctl_table rds_ib_sysctl_table[] = {
 	{
 		.procname       = "max_send_wr",
 		.data		= &rds_ib_sysctl_max_send_wr,
@@ -94,15 +90,6 @@
 		.extra2		= &rds_ib_sysctl_max_unsig_wr_max,
 	},
 	{
-		.procname       = "max_unsignaled_bytes",
-		.data		= &rds_ib_sysctl_max_unsig_bytes,
-		.maxlen         = sizeof(unsigned long),
-		.mode           = 0644,
-		.proc_handler   = proc_doulongvec_minmax,
-		.extra1		= &rds_ib_sysctl_max_unsig_bytes_min,
-		.extra2		= &rds_ib_sysctl_max_unsig_bytes_max,
-	},
-	{
 		.procname       = "max_recv_allocation",
 		.data		= &rds_ib_sysctl_max_recv_allocation,
 		.maxlen         = sizeof(unsigned long),
@@ -132,10 +119,10 @@
 		unregister_sysctl_table(rds_ib_sysctl_hdr);
 }
 
-int __init rds_ib_sysctl_init(void)
+int rds_ib_sysctl_init(void)
 {
 	rds_ib_sysctl_hdr = register_sysctl_paths(rds_ib_sysctl_path, rds_ib_sysctl_table);
-	if (rds_ib_sysctl_hdr == NULL)
+	if (!rds_ib_sysctl_hdr)
 		return -ENOMEM;
 	return 0;
 }
diff --git a/net/rds/info.c b/net/rds/info.c
index c45c417..4fdf1b6 100644
--- a/net/rds/info.c
+++ b/net/rds/info.c
@@ -76,7 +76,7 @@
 	BUG_ON(optname < RDS_INFO_FIRST || optname > RDS_INFO_LAST);
 
 	spin_lock(&rds_info_lock);
-	BUG_ON(rds_info_funcs[offset] != NULL);
+	BUG_ON(rds_info_funcs[offset]);
 	rds_info_funcs[offset] = func;
 	spin_unlock(&rds_info_lock);
 }
@@ -102,7 +102,7 @@
  */
 void rds_info_iter_unmap(struct rds_info_iterator *iter)
 {
-	if (iter->addr != NULL) {
+	if (iter->addr) {
 		kunmap_atomic(iter->addr, KM_USER0);
 		iter->addr = NULL;
 	}
@@ -117,7 +117,7 @@
 	unsigned long this;
 
 	while (bytes) {
-		if (iter->addr == NULL)
+		if (!iter->addr)
 			iter->addr = kmap_atomic(*iter->pages, KM_USER0);
 
 		this = min(bytes, PAGE_SIZE - iter->offset);
@@ -188,7 +188,7 @@
 			>> PAGE_SHIFT;
 
 	pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
-	if (pages == NULL) {
+	if (!pages) {
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -206,7 +206,7 @@
 
 call_func:
 	func = rds_info_funcs[optname - RDS_INFO_FIRST];
-	if (func == NULL) {
+	if (!func) {
 		ret = -ENOPROTOOPT;
 		goto out;
 	}
@@ -234,7 +234,7 @@
 		ret = -EFAULT;
 
 out:
-	for (i = 0; pages != NULL && i < nr_pages; i++)
+	for (i = 0; pages && i < nr_pages; i++)
 		put_page(pages[i]);
 	kfree(pages);
 
diff --git a/net/rds/iw.c b/net/rds/iw.c
index c8f3d35..5a9676f 100644
--- a/net/rds/iw.c
+++ b/net/rds/iw.c
@@ -56,7 +56,7 @@
 DEFINE_SPINLOCK(iw_nodev_conns_lock);
 LIST_HEAD(iw_nodev_conns);
 
-void rds_iw_add_one(struct ib_device *device)
+static void rds_iw_add_one(struct ib_device *device)
 {
 	struct rds_iw_device *rds_iwdev;
 	struct ib_device_attr *dev_attr;
@@ -124,7 +124,7 @@
 	kfree(dev_attr);
 }
 
-void rds_iw_remove_one(struct ib_device *device)
+static void rds_iw_remove_one(struct ib_device *device)
 {
 	struct rds_iw_device *rds_iwdev;
 	struct rds_iw_cm_id *i_cm_id, *next;
@@ -264,7 +264,6 @@
 	.laddr_check		= rds_iw_laddr_check,
 	.xmit_complete		= rds_iw_xmit_complete,
 	.xmit			= rds_iw_xmit,
-	.xmit_cong_map		= NULL,
 	.xmit_rdma		= rds_iw_xmit_rdma,
 	.recv			= rds_iw_recv,
 	.conn_alloc		= rds_iw_conn_alloc,
@@ -272,7 +271,6 @@
 	.conn_connect		= rds_iw_conn_connect,
 	.conn_shutdown		= rds_iw_conn_shutdown,
 	.inc_copy_to_user	= rds_iw_inc_copy_to_user,
-	.inc_purge		= rds_iw_inc_purge,
 	.inc_free		= rds_iw_inc_free,
 	.cm_initiate_connect	= rds_iw_cm_initiate_connect,
 	.cm_handle_connect	= rds_iw_cm_handle_connect,
@@ -289,7 +287,7 @@
 	.t_prefer_loopback	= 1,
 };
 
-int __init rds_iw_init(void)
+int rds_iw_init(void)
 {
 	int ret;
 
diff --git a/net/rds/iw.h b/net/rds/iw.h
index eef2f0c..9015192 100644
--- a/net/rds/iw.h
+++ b/net/rds/iw.h
@@ -70,7 +70,7 @@
 	struct rds_message	*s_rm;
 
 	/* We should really put these into a union: */
-	struct rds_rdma_op	*s_op;
+	struct rm_rdma_op	*s_op;
 	struct rds_iw_mapping	*s_mapping;
 	struct ib_mr		*s_mr;
 	struct ib_fast_reg_page_list *s_page_list;
@@ -268,8 +268,6 @@
 
 /* ib.c */
 extern struct rds_transport rds_iw_transport;
-extern void rds_iw_add_one(struct ib_device *device);
-extern void rds_iw_remove_one(struct ib_device *device);
 extern struct ib_client rds_iw_client;
 
 extern unsigned int fastreg_pool_size;
@@ -284,7 +282,7 @@
 int rds_iw_conn_connect(struct rds_connection *conn);
 void rds_iw_conn_shutdown(struct rds_connection *conn);
 void rds_iw_state_change(struct sock *sk);
-int __init rds_iw_listen_init(void);
+int rds_iw_listen_init(void);
 void rds_iw_listen_stop(void);
 void __rds_iw_conn_error(struct rds_connection *conn, const char *, ...);
 int rds_iw_cm_handle_connect(struct rdma_cm_id *cm_id,
@@ -318,15 +316,13 @@
 void rds_iw_sync_mr(void *trans_private, int dir);
 void rds_iw_free_mr(void *trans_private, int invalidate);
 void rds_iw_flush_mrs(void);
-void rds_iw_remove_cm_id(struct rds_iw_device *rds_iwdev, struct rdma_cm_id *cm_id);
 
 /* ib_recv.c */
-int __init rds_iw_recv_init(void);
+int rds_iw_recv_init(void);
 void rds_iw_recv_exit(void);
 int rds_iw_recv(struct rds_connection *conn);
 int rds_iw_recv_refill(struct rds_connection *conn, gfp_t kptr_gfp,
 		       gfp_t page_gfp, int prefill);
-void rds_iw_inc_purge(struct rds_incoming *inc);
 void rds_iw_inc_free(struct rds_incoming *inc);
 int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov,
 			     size_t size);
@@ -358,7 +354,7 @@
 void rds_iw_send_cq_comp_handler(struct ib_cq *cq, void *context);
 void rds_iw_send_init_ring(struct rds_iw_connection *ic);
 void rds_iw_send_clear_ring(struct rds_iw_connection *ic);
-int rds_iw_xmit_rdma(struct rds_connection *conn, struct rds_rdma_op *op);
+int rds_iw_xmit_rdma(struct rds_connection *conn, struct rm_rdma_op *op);
 void rds_iw_send_add_credits(struct rds_connection *conn, unsigned int credits);
 void rds_iw_advertise_credits(struct rds_connection *conn, unsigned int posted);
 int rds_iw_send_grab_credits(struct rds_iw_connection *ic, u32 wanted,
@@ -371,7 +367,7 @@
 				    unsigned int avail);
 
 /* ib_sysctl.c */
-int __init rds_iw_sysctl_init(void);
+int rds_iw_sysctl_init(void);
 void rds_iw_sysctl_exit(void);
 extern unsigned long rds_iw_sysctl_max_send_wr;
 extern unsigned long rds_iw_sysctl_max_recv_wr;
@@ -379,7 +375,6 @@
 extern unsigned long rds_iw_sysctl_max_unsig_bytes;
 extern unsigned long rds_iw_sysctl_max_recv_allocation;
 extern unsigned int rds_iw_sysctl_flow_control;
-extern ctl_table rds_iw_sysctl_table[];
 
 /*
  * Helper functions for getting/setting the header and data SGEs in
diff --git a/net/rds/iw_cm.c b/net/rds/iw_cm.c
index b5dd6ac..712cf2d 100644
--- a/net/rds/iw_cm.c
+++ b/net/rds/iw_cm.c
@@ -257,7 +257,7 @@
 	 * the rds_iwdev at all.
 	 */
 	rds_iwdev = ib_get_client_data(dev, &rds_iw_client);
-	if (rds_iwdev == NULL) {
+	if (!rds_iwdev) {
 		if (printk_ratelimit())
 			printk(KERN_NOTICE "RDS/IW: No client_data for device %s\n",
 					dev->name);
@@ -292,7 +292,7 @@
 					   ic->i_send_ring.w_nr *
 						sizeof(struct rds_header),
 					   &ic->i_send_hdrs_dma, GFP_KERNEL);
-	if (ic->i_send_hdrs == NULL) {
+	if (!ic->i_send_hdrs) {
 		ret = -ENOMEM;
 		rdsdebug("ib_dma_alloc_coherent send failed\n");
 		goto out;
@@ -302,7 +302,7 @@
 					   ic->i_recv_ring.w_nr *
 						sizeof(struct rds_header),
 					   &ic->i_recv_hdrs_dma, GFP_KERNEL);
-	if (ic->i_recv_hdrs == NULL) {
+	if (!ic->i_recv_hdrs) {
 		ret = -ENOMEM;
 		rdsdebug("ib_dma_alloc_coherent recv failed\n");
 		goto out;
@@ -310,14 +310,14 @@
 
 	ic->i_ack = ib_dma_alloc_coherent(dev, sizeof(struct rds_header),
 				       &ic->i_ack_dma, GFP_KERNEL);
-	if (ic->i_ack == NULL) {
+	if (!ic->i_ack) {
 		ret = -ENOMEM;
 		rdsdebug("ib_dma_alloc_coherent ack failed\n");
 		goto out;
 	}
 
 	ic->i_sends = vmalloc(ic->i_send_ring.w_nr * sizeof(struct rds_iw_send_work));
-	if (ic->i_sends == NULL) {
+	if (!ic->i_sends) {
 		ret = -ENOMEM;
 		rdsdebug("send allocation failed\n");
 		goto out;
@@ -325,7 +325,7 @@
 	rds_iw_send_init_ring(ic);
 
 	ic->i_recvs = vmalloc(ic->i_recv_ring.w_nr * sizeof(struct rds_iw_recv_work));
-	if (ic->i_recvs == NULL) {
+	if (!ic->i_recvs) {
 		ret = -ENOMEM;
 		rdsdebug("recv allocation failed\n");
 		goto out;
@@ -696,7 +696,7 @@
 
 	/* XXX too lazy? */
 	ic = kzalloc(sizeof(struct rds_iw_connection), GFP_KERNEL);
-	if (ic == NULL)
+	if (!ic)
 		return -ENOMEM;
 
 	INIT_LIST_HEAD(&ic->iw_node);
diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c
index 13dc186..59509e9 100644
--- a/net/rds/iw_rdma.c
+++ b/net/rds/iw_rdma.c
@@ -34,7 +34,6 @@
 #include <linux/slab.h>
 
 #include "rds.h"
-#include "rdma.h"
 #include "iw.h"
 
 
@@ -158,7 +157,8 @@
 	return 0;
 }
 
-void rds_iw_remove_cm_id(struct rds_iw_device *rds_iwdev, struct rdma_cm_id *cm_id)
+static void rds_iw_remove_cm_id(struct rds_iw_device *rds_iwdev,
+				struct rdma_cm_id *cm_id)
 {
 	struct rds_iw_cm_id *i_cm_id;
 
@@ -207,9 +207,9 @@
 	BUG_ON(list_empty(&ic->iw_node));
 	list_del(&ic->iw_node);
 
-	spin_lock_irq(&rds_iwdev->spinlock);
+	spin_lock(&rds_iwdev->spinlock);
 	list_add_tail(&ic->iw_node, &rds_iwdev->conn_list);
-	spin_unlock_irq(&rds_iwdev->spinlock);
+	spin_unlock(&rds_iwdev->spinlock);
 	spin_unlock_irq(&iw_nodev_conns_lock);
 
 	ic->rds_iwdev = rds_iwdev;
diff --git a/net/rds/iw_recv.c b/net/rds/iw_recv.c
index 3d47906..5e57347 100644
--- a/net/rds/iw_recv.c
+++ b/net/rds/iw_recv.c
@@ -53,7 +53,7 @@
 static void rds_iw_frag_free(struct rds_page_frag *frag)
 {
 	rdsdebug("frag %p page %p\n", frag, frag->f_page);
-	BUG_ON(frag->f_page != NULL);
+	BUG_ON(frag->f_page);
 	kmem_cache_free(rds_iw_frag_slab, frag);
 }
 
@@ -143,14 +143,14 @@
 	struct ib_sge *sge;
 	int ret = -ENOMEM;
 
-	if (recv->r_iwinc == NULL) {
+	if (!recv->r_iwinc) {
 		if (!atomic_add_unless(&rds_iw_allocation, 1, rds_iw_sysctl_max_recv_allocation)) {
 			rds_iw_stats_inc(s_iw_rx_alloc_limit);
 			goto out;
 		}
 		recv->r_iwinc = kmem_cache_alloc(rds_iw_incoming_slab,
 						 kptr_gfp);
-		if (recv->r_iwinc == NULL) {
+		if (!recv->r_iwinc) {
 			atomic_dec(&rds_iw_allocation);
 			goto out;
 		}
@@ -158,17 +158,17 @@
 		rds_inc_init(&recv->r_iwinc->ii_inc, conn, conn->c_faddr);
 	}
 
-	if (recv->r_frag == NULL) {
+	if (!recv->r_frag) {
 		recv->r_frag = kmem_cache_alloc(rds_iw_frag_slab, kptr_gfp);
-		if (recv->r_frag == NULL)
+		if (!recv->r_frag)
 			goto out;
 		INIT_LIST_HEAD(&recv->r_frag->f_item);
 		recv->r_frag->f_page = NULL;
 	}
 
-	if (ic->i_frag.f_page == NULL) {
+	if (!ic->i_frag.f_page) {
 		ic->i_frag.f_page = alloc_page(page_gfp);
-		if (ic->i_frag.f_page == NULL)
+		if (!ic->i_frag.f_page)
 			goto out;
 		ic->i_frag.f_offset = 0;
 	}
@@ -273,7 +273,7 @@
 	return ret;
 }
 
-void rds_iw_inc_purge(struct rds_incoming *inc)
+static void rds_iw_inc_purge(struct rds_incoming *inc)
 {
 	struct rds_iw_incoming *iwinc;
 	struct rds_page_frag *frag;
@@ -716,7 +716,7 @@
 	 * into the inc and save the inc so we can hang upcoming fragments
 	 * off its list.
 	 */
-	if (iwinc == NULL) {
+	if (!iwinc) {
 		iwinc = recv->r_iwinc;
 		recv->r_iwinc = NULL;
 		ic->i_iwinc = iwinc;
@@ -887,7 +887,7 @@
 	return ret;
 }
 
-int __init rds_iw_recv_init(void)
+int rds_iw_recv_init(void)
 {
 	struct sysinfo si;
 	int ret = -ENOMEM;
@@ -899,13 +899,13 @@
 	rds_iw_incoming_slab = kmem_cache_create("rds_iw_incoming",
 					sizeof(struct rds_iw_incoming),
 					0, 0, NULL);
-	if (rds_iw_incoming_slab == NULL)
+	if (!rds_iw_incoming_slab)
 		goto out;
 
 	rds_iw_frag_slab = kmem_cache_create("rds_iw_frag",
 					sizeof(struct rds_page_frag),
 					0, 0, NULL);
-	if (rds_iw_frag_slab == NULL)
+	if (!rds_iw_frag_slab)
 		kmem_cache_destroy(rds_iw_incoming_slab);
 	else
 		ret = 0;
diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c
index 52182ff..6280ea0 100644
--- a/net/rds/iw_send.c
+++ b/net/rds/iw_send.c
@@ -36,7 +36,6 @@
 #include <linux/dmapool.h>
 
 #include "rds.h"
-#include "rdma.h"
 #include "iw.h"
 
 static void rds_iw_send_rdma_complete(struct rds_message *rm,
@@ -64,13 +63,13 @@
 }
 
 static void rds_iw_send_unmap_rdma(struct rds_iw_connection *ic,
-				   struct rds_rdma_op *op)
+				   struct rm_rdma_op *op)
 {
-	if (op->r_mapped) {
+	if (op->op_mapped) {
 		ib_dma_unmap_sg(ic->i_cm_id->device,
-			op->r_sg, op->r_nents,
-			op->r_write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		op->r_mapped = 0;
+			op->op_sg, op->op_nents,
+			op->op_write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		op->op_mapped = 0;
 	}
 }
 
@@ -83,11 +82,11 @@
 	rdsdebug("ic %p send %p rm %p\n", ic, send, rm);
 
 	ib_dma_unmap_sg(ic->i_cm_id->device,
-		     rm->m_sg, rm->m_nents,
+		     rm->data.op_sg, rm->data.op_nents,
 		     DMA_TO_DEVICE);
 
-	if (rm->m_rdma_op != NULL) {
-		rds_iw_send_unmap_rdma(ic, rm->m_rdma_op);
+	if (rm->rdma.op_active) {
+		rds_iw_send_unmap_rdma(ic, &rm->rdma);
 
 		/* If the user asked for a completion notification on this
 		 * message, we can implement three different semantics:
@@ -111,10 +110,10 @@
 		 */
 		rds_iw_send_rdma_complete(rm, wc_status);
 
-		if (rm->m_rdma_op->r_write)
-			rds_stats_add(s_send_rdma_bytes, rm->m_rdma_op->r_bytes);
+		if (rm->rdma.op_write)
+			rds_stats_add(s_send_rdma_bytes, rm->rdma.op_bytes);
 		else
-			rds_stats_add(s_recv_rdma_bytes, rm->m_rdma_op->r_bytes);
+			rds_stats_add(s_recv_rdma_bytes, rm->rdma.op_bytes);
 	}
 
 	/* If anyone waited for this message to get flushed out, wake
@@ -556,25 +555,27 @@
 	}
 
 	/* map the message the first time we see it */
-	if (ic->i_rm == NULL) {
+	if (!ic->i_rm) {
 		/*
 		printk(KERN_NOTICE "rds_iw_xmit prep msg dport=%u flags=0x%x len=%d\n",
 				be16_to_cpu(rm->m_inc.i_hdr.h_dport),
 				rm->m_inc.i_hdr.h_flags,
 				be32_to_cpu(rm->m_inc.i_hdr.h_len));
 		   */
-		if (rm->m_nents) {
-			rm->m_count = ib_dma_map_sg(dev,
-					 rm->m_sg, rm->m_nents, DMA_TO_DEVICE);
-			rdsdebug("ic %p mapping rm %p: %d\n", ic, rm, rm->m_count);
-			if (rm->m_count == 0) {
+		if (rm->data.op_nents) {
+			rm->data.op_count = ib_dma_map_sg(dev,
+							  rm->data.op_sg,
+							  rm->data.op_nents,
+							  DMA_TO_DEVICE);
+			rdsdebug("ic %p mapping rm %p: %d\n", ic, rm, rm->data.op_count);
+			if (rm->data.op_count == 0) {
 				rds_iw_stats_inc(s_iw_tx_sg_mapping_failure);
 				rds_iw_ring_unalloc(&ic->i_send_ring, work_alloc);
 				ret = -ENOMEM; /* XXX ? */
 				goto out;
 			}
 		} else {
-			rm->m_count = 0;
+			rm->data.op_count = 0;
 		}
 
 		ic->i_unsignaled_wrs = rds_iw_sysctl_max_unsig_wrs;
@@ -590,10 +591,10 @@
 
 		/* If it has a RDMA op, tell the peer we did it. This is
 		 * used by the peer to release use-once RDMA MRs. */
-		if (rm->m_rdma_op) {
+		if (rm->rdma.op_active) {
 			struct rds_ext_header_rdma ext_hdr;
 
-			ext_hdr.h_rdma_rkey = cpu_to_be32(rm->m_rdma_op->r_key);
+			ext_hdr.h_rdma_rkey = cpu_to_be32(rm->rdma.op_rkey);
 			rds_message_add_extension(&rm->m_inc.i_hdr,
 					RDS_EXTHDR_RDMA, &ext_hdr, sizeof(ext_hdr));
 		}
@@ -621,7 +622,7 @@
 	send = &ic->i_sends[pos];
 	first = send;
 	prev = NULL;
-	scat = &rm->m_sg[sg];
+	scat = &rm->data.op_sg[sg];
 	sent = 0;
 	i = 0;
 
@@ -631,7 +632,7 @@
 	 * or when requested by the user. Right now, we let
 	 * the application choose.
 	 */
-	if (rm->m_rdma_op && rm->m_rdma_op->r_fence)
+	if (rm->rdma.op_active && rm->rdma.op_fence)
 		send_flags = IB_SEND_FENCE;
 
 	/*
@@ -650,7 +651,7 @@
 	}
 
 	/* if there's data reference it with a chain of work reqs */
-	for (; i < work_alloc && scat != &rm->m_sg[rm->m_count]; i++) {
+	for (; i < work_alloc && scat != &rm->data.op_sg[rm->data.op_count]; i++) {
 		unsigned int len;
 
 		send = &ic->i_sends[pos];
@@ -728,7 +729,7 @@
 		sent += sizeof(struct rds_header);
 
 	/* if we finished the message then send completion owns it */
-	if (scat == &rm->m_sg[rm->m_count]) {
+	if (scat == &rm->data.op_sg[rm->data.op_count]) {
 		prev->s_rm = ic->i_rm;
 		prev->s_wr.send_flags |= IB_SEND_SIGNALED | IB_SEND_SOLICITED;
 		ic->i_rm = NULL;
@@ -784,7 +785,7 @@
 	ib_update_fast_reg_key(send->s_mr, send->s_remap_count++);
 }
 
-int rds_iw_xmit_rdma(struct rds_connection *conn, struct rds_rdma_op *op)
+int rds_iw_xmit_rdma(struct rds_connection *conn, struct rm_rdma_op *op)
 {
 	struct rds_iw_connection *ic = conn->c_transport_data;
 	struct rds_iw_send_work *send = NULL;
@@ -794,7 +795,7 @@
 	struct rds_iw_device *rds_iwdev;
 	struct scatterlist *scat;
 	unsigned long len;
-	u64 remote_addr = op->r_remote_addr;
+	u64 remote_addr = op->op_remote_addr;
 	u32 pos, fr_pos;
 	u32 work_alloc;
 	u32 i;
@@ -806,21 +807,21 @@
 	rds_iwdev = ib_get_client_data(ic->i_cm_id->device, &rds_iw_client);
 
 	/* map the message the first time we see it */
-	if (!op->r_mapped) {
-		op->r_count = ib_dma_map_sg(ic->i_cm_id->device,
-					op->r_sg, op->r_nents, (op->r_write) ?
-					DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		rdsdebug("ic %p mapping op %p: %d\n", ic, op, op->r_count);
-		if (op->r_count == 0) {
+	if (!op->op_mapped) {
+		op->op_count = ib_dma_map_sg(ic->i_cm_id->device,
+					     op->op_sg, op->op_nents, (op->op_write) ?
+					     DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		rdsdebug("ic %p mapping op %p: %d\n", ic, op, op->op_count);
+		if (op->op_count == 0) {
 			rds_iw_stats_inc(s_iw_tx_sg_mapping_failure);
 			ret = -ENOMEM; /* XXX ? */
 			goto out;
 		}
 
-		op->r_mapped = 1;
+		op->op_mapped = 1;
 	}
 
-	if (!op->r_write) {
+	if (!op->op_write) {
 		/* Alloc space on the send queue for the fastreg */
 		work_alloc = rds_iw_ring_alloc(&ic->i_send_ring, 1, &fr_pos);
 		if (work_alloc != 1) {
@@ -835,7 +836,7 @@
 	 * Instead of knowing how to return a partial rdma read/write we insist that there
 	 * be enough work requests to send the entire message.
 	 */
-	i = ceil(op->r_count, rds_iwdev->max_sge);
+	i = ceil(op->op_count, rds_iwdev->max_sge);
 
 	work_alloc = rds_iw_ring_alloc(&ic->i_send_ring, i, &pos);
 	if (work_alloc != i) {
@@ -846,17 +847,17 @@
 	}
 
 	send = &ic->i_sends[pos];
-	if (!op->r_write) {
+	if (!op->op_write) {
 		first = prev = &ic->i_sends[fr_pos];
 	} else {
 		first = send;
 		prev = NULL;
 	}
-	scat = &op->r_sg[0];
+	scat = &op->op_sg[0];
 	sent = 0;
-	num_sge = op->r_count;
+	num_sge = op->op_count;
 
-	for (i = 0; i < work_alloc && scat != &op->r_sg[op->r_count]; i++) {
+	for (i = 0; i < work_alloc && scat != &op->op_sg[op->op_count]; i++) {
 		send->s_wr.send_flags = 0;
 		send->s_queued = jiffies;
 
@@ -873,13 +874,13 @@
 		 * for local access after RDS is finished with it, using
 		 * IB_WR_RDMA_READ_WITH_INV will invalidate it after the read has completed.
 		 */
-		if (op->r_write)
+		if (op->op_write)
 			send->s_wr.opcode = IB_WR_RDMA_WRITE;
 		else
 			send->s_wr.opcode = IB_WR_RDMA_READ_WITH_INV;
 
 		send->s_wr.wr.rdma.remote_addr = remote_addr;
-		send->s_wr.wr.rdma.rkey = op->r_key;
+		send->s_wr.wr.rdma.rkey = op->op_rkey;
 		send->s_op = op;
 
 		if (num_sge > rds_iwdev->max_sge) {
@@ -893,7 +894,7 @@
 		if (prev)
 			prev->s_wr.next = &send->s_wr;
 
-		for (j = 0; j < send->s_wr.num_sge && scat != &op->r_sg[op->r_count]; j++) {
+		for (j = 0; j < send->s_wr.num_sge && scat != &op->op_sg[op->op_count]; j++) {
 			len = ib_sg_dma_len(ic->i_cm_id->device, scat);
 
 			if (send->s_wr.opcode == IB_WR_RDMA_READ_WITH_INV)
@@ -927,7 +928,7 @@
 	}
 
 	/* if we finished the message then send completion owns it */
-	if (scat == &op->r_sg[op->r_count])
+	if (scat == &op->op_sg[op->op_count])
 		first->s_wr.send_flags = IB_SEND_SIGNALED;
 
 	if (i < work_alloc) {
@@ -941,9 +942,9 @@
 	 * adapters do not allow using the lkey for this at all.  To bypass this use a
 	 * fastreg_mr (or possibly a dma_mr)
 	 */
-	if (!op->r_write) {
+	if (!op->op_write) {
 		rds_iw_build_send_fastreg(rds_iwdev, ic, &ic->i_sends[fr_pos],
-			op->r_count, sent, conn->c_xmit_rm->m_rs->rs_user_addr);
+			op->op_count, sent, conn->c_xmit_rm->m_rs->rs_user_addr);
 		work_alloc++;
 	}
 
diff --git a/net/rds/iw_sysctl.c b/net/rds/iw_sysctl.c
index 1c4428a..e2e4717 100644
--- a/net/rds/iw_sysctl.c
+++ b/net/rds/iw_sysctl.c
@@ -55,7 +55,7 @@
 
 unsigned int rds_iw_sysctl_flow_control = 1;
 
-ctl_table rds_iw_sysctl_table[] = {
+static ctl_table rds_iw_sysctl_table[] = {
 	{
 		.procname       = "max_send_wr",
 		.data		= &rds_iw_sysctl_max_send_wr,
@@ -122,10 +122,10 @@
 		unregister_sysctl_table(rds_iw_sysctl_hdr);
 }
 
-int __init rds_iw_sysctl_init(void)
+int rds_iw_sysctl_init(void)
 {
 	rds_iw_sysctl_hdr = register_sysctl_paths(rds_iw_sysctl_path, rds_iw_sysctl_table);
-	if (rds_iw_sysctl_hdr == NULL)
+	if (!rds_iw_sysctl_hdr)
 		return -ENOMEM;
 	return 0;
 }
diff --git a/net/rds/loop.c b/net/rds/loop.c
index dd98793..c390156 100644
--- a/net/rds/loop.c
+++ b/net/rds/loop.c
@@ -61,10 +61,17 @@
 			 unsigned int hdr_off, unsigned int sg,
 			 unsigned int off)
 {
+	/* Do not send cong updates to loopback */
+	if (rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) {
+		rds_cong_map_updated(conn->c_fcong, ~(u64) 0);
+		return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES;
+	}
+
 	BUG_ON(hdr_off || sg || off);
 
 	rds_inc_init(&rm->m_inc, conn, conn->c_laddr);
-	rds_message_addref(rm); /* for the inc */
+	/* For the embedded inc. Matching put is in loop_inc_free() */
+	rds_message_addref(rm);
 
 	rds_recv_incoming(conn, conn->c_laddr, conn->c_faddr, &rm->m_inc,
 			  GFP_KERNEL, KM_USER0);
@@ -77,16 +84,14 @@
 	return sizeof(struct rds_header) + be32_to_cpu(rm->m_inc.i_hdr.h_len);
 }
 
-static int rds_loop_xmit_cong_map(struct rds_connection *conn,
-				  struct rds_cong_map *map,
-				  unsigned long offset)
+/*
+ * See rds_loop_xmit(). Since our inc is embedded in the rm, we
+ * make sure the rm lives at least until the inc is done.
+ */
+static void rds_loop_inc_free(struct rds_incoming *inc)
 {
-	BUG_ON(offset);
-	BUG_ON(map != conn->c_lcong);
-
-	rds_cong_map_updated(conn->c_fcong, ~(u64) 0);
-
-	return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES;
+        struct rds_message *rm = container_of(inc, struct rds_message, m_inc);
+        rds_message_put(rm);
 }
 
 /* we need to at least give the thread something to succeed */
@@ -112,7 +117,7 @@
 	unsigned long flags;
 
 	lc = kzalloc(sizeof(struct rds_loop_connection), GFP_KERNEL);
-	if (lc == NULL)
+	if (!lc)
 		return -ENOMEM;
 
 	INIT_LIST_HEAD(&lc->loop_node);
@@ -169,14 +174,12 @@
  */
 struct rds_transport rds_loop_transport = {
 	.xmit			= rds_loop_xmit,
-	.xmit_cong_map		= rds_loop_xmit_cong_map,
 	.recv			= rds_loop_recv,
 	.conn_alloc		= rds_loop_conn_alloc,
 	.conn_free		= rds_loop_conn_free,
 	.conn_connect		= rds_loop_conn_connect,
 	.conn_shutdown		= rds_loop_conn_shutdown,
 	.inc_copy_to_user	= rds_message_inc_copy_to_user,
-	.inc_purge		= rds_message_inc_purge,
-	.inc_free		= rds_message_inc_free,
+	.inc_free		= rds_loop_inc_free,
 	.t_name			= "loopback",
 };
diff --git a/net/rds/message.c b/net/rds/message.c
index 9a1d67e..a84545d 100644
--- a/net/rds/message.c
+++ b/net/rds/message.c
@@ -34,9 +34,6 @@
 #include <linux/slab.h>
 
 #include "rds.h"
-#include "rdma.h"
-
-static DECLARE_WAIT_QUEUE_HEAD(rds_message_flush_waitq);
 
 static unsigned int	rds_exthdr_size[__RDS_EXTHDR_MAX] = {
 [RDS_EXTHDR_NONE]	= 0,
@@ -63,29 +60,31 @@
 	if (unlikely(test_bit(RDS_MSG_PAGEVEC, &rm->m_flags)))
 		return;
 
-	for (i = 0; i < rm->m_nents; i++) {
-		rdsdebug("putting data page %p\n", (void *)sg_page(&rm->m_sg[i]));
+	for (i = 0; i < rm->data.op_nents; i++) {
+		rdsdebug("putting data page %p\n", (void *)sg_page(&rm->data.op_sg[i]));
 		/* XXX will have to put_page for page refs */
-		__free_page(sg_page(&rm->m_sg[i]));
+		__free_page(sg_page(&rm->data.op_sg[i]));
 	}
-	rm->m_nents = 0;
+	rm->data.op_nents = 0;
 
-	if (rm->m_rdma_op)
-		rds_rdma_free_op(rm->m_rdma_op);
-	if (rm->m_rdma_mr)
-		rds_mr_put(rm->m_rdma_mr);
-}
+	if (rm->rdma.op_active)
+		rds_rdma_free_op(&rm->rdma);
+	if (rm->rdma.op_rdma_mr)
+		rds_mr_put(rm->rdma.op_rdma_mr);
 
-void rds_message_inc_purge(struct rds_incoming *inc)
-{
-	struct rds_message *rm = container_of(inc, struct rds_message, m_inc);
-	rds_message_purge(rm);
+	if (rm->atomic.op_active)
+		rds_atomic_free_op(&rm->atomic);
+	if (rm->atomic.op_rdma_mr)
+		rds_mr_put(rm->atomic.op_rdma_mr);
 }
 
 void rds_message_put(struct rds_message *rm)
 {
 	rdsdebug("put rm %p ref %d\n", rm, atomic_read(&rm->m_refcount));
-
+	if (atomic_read(&rm->m_refcount) == 0) {
+printk(KERN_CRIT "danger refcount zero on %p\n", rm);
+WARN_ON(1);
+	}
 	if (atomic_dec_and_test(&rm->m_refcount)) {
 		BUG_ON(!list_empty(&rm->m_sock_item));
 		BUG_ON(!list_empty(&rm->m_conn_item));
@@ -96,12 +95,6 @@
 }
 EXPORT_SYMBOL_GPL(rds_message_put);
 
-void rds_message_inc_free(struct rds_incoming *inc)
-{
-	struct rds_message *rm = container_of(inc, struct rds_message, m_inc);
-	rds_message_put(rm);
-}
-
 void rds_message_populate_header(struct rds_header *hdr, __be16 sport,
 				 __be16 dport, u64 seq)
 {
@@ -113,8 +106,8 @@
 }
 EXPORT_SYMBOL_GPL(rds_message_populate_header);
 
-int rds_message_add_extension(struct rds_header *hdr,
-		unsigned int type, const void *data, unsigned int len)
+int rds_message_add_extension(struct rds_header *hdr, unsigned int type,
+			      const void *data, unsigned int len)
 {
 	unsigned int ext_len = sizeof(u8) + len;
 	unsigned char *dst;
@@ -184,26 +177,6 @@
 	return RDS_EXTHDR_NONE;
 }
 
-int rds_message_add_version_extension(struct rds_header *hdr, unsigned int version)
-{
-	struct rds_ext_header_version ext_hdr;
-
-	ext_hdr.h_version = cpu_to_be32(version);
-	return rds_message_add_extension(hdr, RDS_EXTHDR_VERSION, &ext_hdr, sizeof(ext_hdr));
-}
-
-int rds_message_get_version_extension(struct rds_header *hdr, unsigned int *version)
-{
-	struct rds_ext_header_version ext_hdr;
-	unsigned int pos = 0, len = sizeof(ext_hdr);
-
-	/* We assume the version extension is the only one present */
-	if (rds_message_next_extension(hdr, &pos, &ext_hdr, &len) != RDS_EXTHDR_VERSION)
-		return 0;
-	*version = be32_to_cpu(ext_hdr.h_version);
-	return 1;
-}
-
 int rds_message_add_rdma_dest_extension(struct rds_header *hdr, u32 r_key, u32 offset)
 {
 	struct rds_ext_header_rdma_dest ext_hdr;
@@ -214,41 +187,68 @@
 }
 EXPORT_SYMBOL_GPL(rds_message_add_rdma_dest_extension);
 
-struct rds_message *rds_message_alloc(unsigned int nents, gfp_t gfp)
+/*
+ * Each rds_message is allocated with extra space for the scatterlist entries
+ * rds ops will need. This is to minimize memory allocation count. Then, each rds op
+ * can grab SGs when initializing its part of the rds_message.
+ */
+struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp)
 {
 	struct rds_message *rm;
 
-	rm = kzalloc(sizeof(struct rds_message) +
-		     (nents * sizeof(struct scatterlist)), gfp);
+	rm = kzalloc(sizeof(struct rds_message) + extra_len, gfp);
 	if (!rm)
 		goto out;
 
-	if (nents)
-		sg_init_table(rm->m_sg, nents);
+	rm->m_used_sgs = 0;
+	rm->m_total_sgs = extra_len / sizeof(struct scatterlist);
+
 	atomic_set(&rm->m_refcount, 1);
 	INIT_LIST_HEAD(&rm->m_sock_item);
 	INIT_LIST_HEAD(&rm->m_conn_item);
 	spin_lock_init(&rm->m_rs_lock);
+	init_waitqueue_head(&rm->m_flush_wait);
 
 out:
 	return rm;
 }
 
+/*
+ * RDS ops use this to grab SG entries from the rm's sg pool.
+ */
+struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents)
+{
+	struct scatterlist *sg_first = (struct scatterlist *) &rm[1];
+	struct scatterlist *sg_ret;
+
+	WARN_ON(rm->m_used_sgs + nents > rm->m_total_sgs);
+	WARN_ON(!nents);
+
+	sg_ret = &sg_first[rm->m_used_sgs];
+	sg_init_table(sg_ret, nents);
+	rm->m_used_sgs += nents;
+
+	return sg_ret;
+}
+
 struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned int total_len)
 {
 	struct rds_message *rm;
 	unsigned int i;
+	int num_sgs = ceil(total_len, PAGE_SIZE);
+	int extra_bytes = num_sgs * sizeof(struct scatterlist);
 
-	rm = rds_message_alloc(ceil(total_len, PAGE_SIZE), GFP_KERNEL);
-	if (rm == NULL)
+	rm = rds_message_alloc(extra_bytes, GFP_NOWAIT);
+	if (!rm)
 		return ERR_PTR(-ENOMEM);
 
 	set_bit(RDS_MSG_PAGEVEC, &rm->m_flags);
 	rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);
-	rm->m_nents = ceil(total_len, PAGE_SIZE);
+	rm->data.op_nents = ceil(total_len, PAGE_SIZE);
+	rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs);
 
-	for (i = 0; i < rm->m_nents; ++i) {
-		sg_set_page(&rm->m_sg[i],
+	for (i = 0; i < rm->data.op_nents; ++i) {
+		sg_set_page(&rm->data.op_sg[i],
 				virt_to_page(page_addrs[i]),
 				PAGE_SIZE, 0);
 	}
@@ -256,40 +256,33 @@
 	return rm;
 }
 
-struct rds_message *rds_message_copy_from_user(struct iovec *first_iov,
+int rds_message_copy_from_user(struct rds_message *rm, struct iovec *first_iov,
 					       size_t total_len)
 {
 	unsigned long to_copy;
 	unsigned long iov_off;
 	unsigned long sg_off;
-	struct rds_message *rm;
 	struct iovec *iov;
 	struct scatterlist *sg;
-	int ret;
-
-	rm = rds_message_alloc(ceil(total_len, PAGE_SIZE), GFP_KERNEL);
-	if (rm == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	int ret = 0;
 
 	rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);
 
 	/*
 	 * now allocate and copy in the data payload.
 	 */
-	sg = rm->m_sg;
+	sg = rm->data.op_sg;
 	iov = first_iov;
 	iov_off = 0;
 	sg_off = 0; /* Dear gcc, sg->page will be null from kzalloc. */
 
 	while (total_len) {
-		if (sg_page(sg) == NULL) {
+		if (!sg_page(sg)) {
 			ret = rds_page_remainder_alloc(sg, total_len,
 						       GFP_HIGHUSER);
 			if (ret)
 				goto out;
-			rm->m_nents++;
+			rm->data.op_nents++;
 			sg_off = 0;
 		}
 
@@ -320,14 +313,8 @@
 			sg++;
 	}
 
-	ret = 0;
 out:
-	if (ret) {
-		if (rm)
-			rds_message_put(rm);
-		rm = ERR_PTR(ret);
-	}
-	return rm;
+	return ret;
 }
 
 int rds_message_inc_copy_to_user(struct rds_incoming *inc,
@@ -348,7 +335,7 @@
 
 	iov = first_iov;
 	iov_off = 0;
-	sg = rm->m_sg;
+	sg = rm->data.op_sg;
 	vec_off = 0;
 	copied = 0;
 
@@ -394,15 +381,14 @@
  */
 void rds_message_wait(struct rds_message *rm)
 {
-	wait_event(rds_message_flush_waitq,
+	wait_event_interruptible(rm->m_flush_wait,
 			!test_bit(RDS_MSG_MAPPED, &rm->m_flags));
 }
 
 void rds_message_unmapped(struct rds_message *rm)
 {
 	clear_bit(RDS_MSG_MAPPED, &rm->m_flags);
-	if (waitqueue_active(&rds_message_flush_waitq))
-		wake_up(&rds_message_flush_waitq);
+	wake_up_interruptible(&rm->m_flush_wait);
 }
 EXPORT_SYMBOL_GPL(rds_message_unmapped);
 
diff --git a/net/rds/page.c b/net/rds/page.c
index 595a952..d8acdeb 100644
--- a/net/rds/page.c
+++ b/net/rds/page.c
@@ -40,7 +40,8 @@
 	unsigned long	r_offset;
 };
 
-DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_page_remainder, rds_page_remainders);
+static DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_page_remainder,
+				     rds_page_remainders);
 
 /*
  * returns 0 on success or -errno on failure.
@@ -57,30 +58,17 @@
 	unsigned long ret;
 	void *addr;
 
-	if (to_user)
+	addr = kmap(page);
+	if (to_user) {
 		rds_stats_add(s_copy_to_user, bytes);
-	else
+		ret = copy_to_user(ptr, addr + offset, bytes);
+	} else {
 		rds_stats_add(s_copy_from_user, bytes);
-
-	addr = kmap_atomic(page, KM_USER0);
-	if (to_user)
-		ret = __copy_to_user_inatomic(ptr, addr + offset, bytes);
-	else
-		ret = __copy_from_user_inatomic(addr + offset, ptr, bytes);
-	kunmap_atomic(addr, KM_USER0);
-
-	if (ret) {
-		addr = kmap(page);
-		if (to_user)
-			ret = copy_to_user(ptr, addr + offset, bytes);
-		else
-			ret = copy_from_user(addr + offset, ptr, bytes);
-		kunmap(page);
-		if (ret)
-			return -EFAULT;
+		ret = copy_from_user(addr + offset, ptr, bytes);
 	}
+	kunmap(page);
 
-	return 0;
+	return ret ? -EFAULT : 0;
 }
 EXPORT_SYMBOL_GPL(rds_page_copy_user);
 
@@ -116,7 +104,7 @@
 	/* jump straight to allocation if we're trying for a huge page */
 	if (bytes >= PAGE_SIZE) {
 		page = alloc_page(gfp);
-		if (page == NULL) {
+		if (!page) {
 			ret = -ENOMEM;
 		} else {
 			sg_set_page(scat, page, PAGE_SIZE, 0);
@@ -162,7 +150,7 @@
 		rem = &per_cpu(rds_page_remainders, get_cpu());
 		local_irq_save(flags);
 
-		if (page == NULL) {
+		if (!page) {
 			ret = -ENOMEM;
 			break;
 		}
@@ -186,6 +174,7 @@
 		 ret ? 0 : scat->length);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(rds_page_remainder_alloc);
 
 static int rds_page_remainder_cpu_notify(struct notifier_block *self,
 					 unsigned long action, void *hcpu)
diff --git a/net/rds/rdma.c b/net/rds/rdma.c
index 75fd13b..1a41deb 100644
--- a/net/rds/rdma.c
+++ b/net/rds/rdma.c
@@ -35,7 +35,7 @@
 #include <linux/rbtree.h>
 #include <linux/dma-mapping.h> /* for DMA_*_DEVICE */
 
-#include "rdma.h"
+#include "rds.h"
 
 /*
  * XXX
@@ -130,14 +130,22 @@
 {
 	struct rds_mr *mr;
 	struct rb_node *node;
+	unsigned long flags;
 
 	/* Release any MRs associated with this socket */
+	spin_lock_irqsave(&rs->rs_rdma_lock, flags);
 	while ((node = rb_first(&rs->rs_rdma_keys))) {
 		mr = container_of(node, struct rds_mr, r_rb_node);
 		if (mr->r_trans == rs->rs_transport)
 			mr->r_invalidate = 0;
+		rb_erase(&mr->r_rb_node, &rs->rs_rdma_keys);
+		RB_CLEAR_NODE(&mr->r_rb_node);
+		spin_unlock_irqrestore(&rs->rs_rdma_lock, flags);
+		rds_destroy_mr(mr);
 		rds_mr_put(mr);
+		spin_lock_irqsave(&rs->rs_rdma_lock, flags);
 	}
+	spin_unlock_irqrestore(&rs->rs_rdma_lock, flags);
 
 	if (rs->rs_transport && rs->rs_transport->flush_mrs)
 		rs->rs_transport->flush_mrs();
@@ -181,7 +189,7 @@
 		goto out;
 	}
 
-	if (rs->rs_transport->get_mr == NULL) {
+	if (!rs->rs_transport->get_mr) {
 		ret = -EOPNOTSUPP;
 		goto out;
 	}
@@ -197,13 +205,13 @@
 
 	/* XXX clamp nr_pages to limit the size of this alloc? */
 	pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
-	if (pages == NULL) {
+	if (!pages) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	mr = kzalloc(sizeof(struct rds_mr), GFP_KERNEL);
-	if (mr == NULL) {
+	if (!mr) {
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -230,13 +238,13 @@
 	 * r/o or r/w. We need to assume r/w, or we'll do a lot of RDMA to
 	 * the zero page.
 	 */
-	ret = rds_pin_pages(args->vec.addr & PAGE_MASK, nr_pages, pages, 1);
+	ret = rds_pin_pages(args->vec.addr, nr_pages, pages, 1);
 	if (ret < 0)
 		goto out;
 
 	nents = ret;
 	sg = kcalloc(nents, sizeof(*sg), GFP_KERNEL);
-	if (sg == NULL) {
+	if (!sg) {
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -406,68 +414,127 @@
 
 	spin_lock_irqsave(&rs->rs_rdma_lock, flags);
 	mr = rds_mr_tree_walk(&rs->rs_rdma_keys, r_key, NULL);
-	if (mr && (mr->r_use_once || force)) {
+	if (!mr) {
+		printk(KERN_ERR "rds: trying to unuse MR with unknown r_key %u!\n", r_key);
+		spin_unlock_irqrestore(&rs->rs_rdma_lock, flags);
+		return;
+	}
+
+	if (mr->r_use_once || force) {
 		rb_erase(&mr->r_rb_node, &rs->rs_rdma_keys);
 		RB_CLEAR_NODE(&mr->r_rb_node);
 		zot_me = 1;
-	} else if (mr)
-		atomic_inc(&mr->r_refcount);
+	}
 	spin_unlock_irqrestore(&rs->rs_rdma_lock, flags);
 
 	/* May have to issue a dma_sync on this memory region.
 	 * Note we could avoid this if the operation was a RDMA READ,
 	 * but at this point we can't tell. */
-	if (mr != NULL) {
-		if (mr->r_trans->sync_mr)
-			mr->r_trans->sync_mr(mr->r_trans_private, DMA_FROM_DEVICE);
+	if (mr->r_trans->sync_mr)
+		mr->r_trans->sync_mr(mr->r_trans_private, DMA_FROM_DEVICE);
 
-		/* If the MR was marked as invalidate, this will
-		 * trigger an async flush. */
-		if (zot_me)
-			rds_destroy_mr(mr);
-		rds_mr_put(mr);
-	}
+	/* If the MR was marked as invalidate, this will
+	 * trigger an async flush. */
+	if (zot_me)
+		rds_destroy_mr(mr);
+	rds_mr_put(mr);
 }
 
-void rds_rdma_free_op(struct rds_rdma_op *ro)
+void rds_rdma_free_op(struct rm_rdma_op *ro)
 {
 	unsigned int i;
 
-	for (i = 0; i < ro->r_nents; i++) {
-		struct page *page = sg_page(&ro->r_sg[i]);
+	for (i = 0; i < ro->op_nents; i++) {
+		struct page *page = sg_page(&ro->op_sg[i]);
 
 		/* Mark page dirty if it was possibly modified, which
 		 * is the case for a RDMA_READ which copies from remote
 		 * to local memory */
-		if (!ro->r_write) {
-			BUG_ON(in_interrupt());
+		if (!ro->op_write) {
+			BUG_ON(irqs_disabled());
 			set_page_dirty(page);
 		}
 		put_page(page);
 	}
 
-	kfree(ro->r_notifier);
-	kfree(ro);
+	kfree(ro->op_notifier);
+	ro->op_notifier = NULL;
+	ro->op_active = 0;
+}
+
+void rds_atomic_free_op(struct rm_atomic_op *ao)
+{
+	struct page *page = sg_page(ao->op_sg);
+
+	/* Mark page dirty if it was possibly modified, which
+	 * is the case for a RDMA_READ which copies from remote
+	 * to local memory */
+	set_page_dirty(page);
+	put_page(page);
+
+	kfree(ao->op_notifier);
+	ao->op_notifier = NULL;
+	ao->op_active = 0;
+}
+
+
+/*
+ * Count the number of pages needed to describe an incoming iovec.
+ */
+static int rds_rdma_pages(struct rds_rdma_args *args)
+{
+	struct rds_iovec vec;
+	struct rds_iovec __user *local_vec;
+	unsigned int tot_pages = 0;
+	unsigned int nr_pages;
+	unsigned int i;
+
+	local_vec = (struct rds_iovec __user *)(unsigned long) args->local_vec_addr;
+
+	/* figure out the number of pages in the vector */
+	for (i = 0; i < args->nr_local; i++) {
+		if (copy_from_user(&vec, &local_vec[i],
+				   sizeof(struct rds_iovec)))
+			return -EFAULT;
+
+		nr_pages = rds_pages_in_vec(&vec);
+		if (nr_pages == 0)
+			return -EINVAL;
+
+		tot_pages += nr_pages;
+	}
+
+	return tot_pages;
+}
+
+int rds_rdma_extra_size(struct rds_rdma_args *args)
+{
+	return rds_rdma_pages(args) * sizeof(struct scatterlist);
 }
 
 /*
- * args is a pointer to an in-kernel copy in the sendmsg cmsg.
+ * The application asks for a RDMA transfer.
+ * Extract all arguments and set up the rdma_op
  */
-static struct rds_rdma_op *rds_rdma_prepare(struct rds_sock *rs,
-					    struct rds_rdma_args *args)
+int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
+			  struct cmsghdr *cmsg)
 {
+	struct rds_rdma_args *args;
 	struct rds_iovec vec;
-	struct rds_rdma_op *op = NULL;
-	unsigned int nr_pages;
-	unsigned int max_pages;
+	struct rm_rdma_op *op = &rm->rdma;
+	int nr_pages;
 	unsigned int nr_bytes;
 	struct page **pages = NULL;
 	struct rds_iovec __user *local_vec;
-	struct scatterlist *sg;
 	unsigned int nr;
 	unsigned int i, j;
-	int ret;
+	int ret = 0;
 
+	if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct rds_rdma_args))
+	    || rm->rdma.op_active)
+		return -EINVAL;
+
+	args = CMSG_DATA(cmsg);
 
 	if (rs->rs_bound_addr == 0) {
 		ret = -ENOTCONN; /* XXX not a great errno */
@@ -479,61 +546,38 @@
 		goto out;
 	}
 
-	nr_pages = 0;
-	max_pages = 0;
+	nr_pages = rds_rdma_pages(args);
+	if (nr_pages < 0)
+		goto out;
 
-	local_vec = (struct rds_iovec __user *)(unsigned long) args->local_vec_addr;
-
-	/* figure out the number of pages in the vector */
-	for (i = 0; i < args->nr_local; i++) {
-		if (copy_from_user(&vec, &local_vec[i],
-				   sizeof(struct rds_iovec))) {
-			ret = -EFAULT;
-			goto out;
-		}
-
-		nr = rds_pages_in_vec(&vec);
-		if (nr == 0) {
-			ret = -EINVAL;
-			goto out;
-		}
-
-		max_pages = max(nr, max_pages);
-		nr_pages += nr;
-	}
-
-	pages = kcalloc(max_pages, sizeof(struct page *), GFP_KERNEL);
-	if (pages == NULL) {
+	pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
+	if (!pages) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	op = kzalloc(offsetof(struct rds_rdma_op, r_sg[nr_pages]), GFP_KERNEL);
-	if (op == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	op->r_write = !!(args->flags & RDS_RDMA_READWRITE);
-	op->r_fence = !!(args->flags & RDS_RDMA_FENCE);
-	op->r_notify = !!(args->flags & RDS_RDMA_NOTIFY_ME);
-	op->r_recverr = rs->rs_recverr;
+	op->op_write = !!(args->flags & RDS_RDMA_READWRITE);
+	op->op_fence = !!(args->flags & RDS_RDMA_FENCE);
+	op->op_notify = !!(args->flags & RDS_RDMA_NOTIFY_ME);
+	op->op_silent = !!(args->flags & RDS_RDMA_SILENT);
+	op->op_active = 1;
+	op->op_recverr = rs->rs_recverr;
 	WARN_ON(!nr_pages);
-	sg_init_table(op->r_sg, nr_pages);
+	op->op_sg = rds_message_alloc_sgs(rm, nr_pages);
 
-	if (op->r_notify || op->r_recverr) {
+	if (op->op_notify || op->op_recverr) {
 		/* We allocate an uninitialized notifier here, because
 		 * we don't want to do that in the completion handler. We
 		 * would have to use GFP_ATOMIC there, and don't want to deal
 		 * with failed allocations.
 		 */
-		op->r_notifier = kmalloc(sizeof(struct rds_notifier), GFP_KERNEL);
-		if (!op->r_notifier) {
+		op->op_notifier = kmalloc(sizeof(struct rds_notifier), GFP_KERNEL);
+		if (!op->op_notifier) {
 			ret = -ENOMEM;
 			goto out;
 		}
-		op->r_notifier->n_user_token = args->user_token;
-		op->r_notifier->n_status = RDS_RDMA_SUCCESS;
+		op->op_notifier->n_user_token = args->user_token;
+		op->op_notifier->n_status = RDS_RDMA_SUCCESS;
 	}
 
 	/* The cookie contains the R_Key of the remote memory region, and
@@ -543,15 +587,17 @@
 	 * destination address (which is really an offset into the MR)
 	 * FIXME: We may want to move this into ib_rdma.c
 	 */
-	op->r_key = rds_rdma_cookie_key(args->cookie);
-	op->r_remote_addr = args->remote_vec.addr + rds_rdma_cookie_offset(args->cookie);
+	op->op_rkey = rds_rdma_cookie_key(args->cookie);
+	op->op_remote_addr = args->remote_vec.addr + rds_rdma_cookie_offset(args->cookie);
 
 	nr_bytes = 0;
 
 	rdsdebug("RDS: rdma prepare nr_local %llu rva %llx rkey %x\n",
 	       (unsigned long long)args->nr_local,
 	       (unsigned long long)args->remote_vec.addr,
-	       op->r_key);
+	       op->op_rkey);
+
+	local_vec = (struct rds_iovec __user *)(unsigned long) args->local_vec_addr;
 
 	for (i = 0; i < args->nr_local; i++) {
 		if (copy_from_user(&vec, &local_vec[i],
@@ -569,15 +615,10 @@
 		rs->rs_user_addr = vec.addr;
 		rs->rs_user_bytes = vec.bytes;
 
-		/* did the user change the vec under us? */
-		if (nr > max_pages || op->r_nents + nr > nr_pages) {
-			ret = -EINVAL;
-			goto out;
-		}
 		/* If it's a WRITE operation, we want to pin the pages for reading.
 		 * If it's a READ operation, we need to pin the pages for writing.
 		 */
-		ret = rds_pin_pages(vec.addr & PAGE_MASK, nr, pages, !op->r_write);
+		ret = rds_pin_pages(vec.addr, nr, pages, !op->op_write);
 		if (ret < 0)
 			goto out;
 
@@ -588,8 +629,9 @@
 
 		for (j = 0; j < nr; j++) {
 			unsigned int offset = vec.addr & ~PAGE_MASK;
+			struct scatterlist *sg;
 
-			sg = &op->r_sg[op->r_nents + j];
+			sg = &op->op_sg[op->op_nents + j];
 			sg_set_page(sg, pages[j],
 					min_t(unsigned int, vec.bytes, PAGE_SIZE - offset),
 					offset);
@@ -601,10 +643,9 @@
 			vec.bytes -= sg->length;
 		}
 
-		op->r_nents += nr;
+		op->op_nents += nr;
 	}
 
-
 	if (nr_bytes > args->remote_vec.bytes) {
 		rdsdebug("RDS nr_bytes %u remote_bytes %u do not match\n",
 				nr_bytes,
@@ -612,38 +653,17 @@
 		ret = -EINVAL;
 		goto out;
 	}
-	op->r_bytes = nr_bytes;
+	op->op_bytes = nr_bytes;
 
 	ret = 0;
 out:
 	kfree(pages);
-	if (ret) {
-		if (op)
-			rds_rdma_free_op(op);
-		op = ERR_PTR(ret);
-	}
-	return op;
-}
+	if (ret)
+		rds_rdma_free_op(op);
 
-/*
- * The application asks for a RDMA transfer.
- * Extract all arguments and set up the rdma_op
- */
-int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
-			  struct cmsghdr *cmsg)
-{
-	struct rds_rdma_op *op;
-
-	if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct rds_rdma_args)) ||
-	    rm->m_rdma_op != NULL)
-		return -EINVAL;
-
-	op = rds_rdma_prepare(rs, CMSG_DATA(cmsg));
-	if (IS_ERR(op))
-		return PTR_ERR(op);
 	rds_stats_inc(s_send_rdma);
-	rm->m_rdma_op = op;
-	return 0;
+
+	return ret;
 }
 
 /*
@@ -673,7 +693,7 @@
 
 	spin_lock_irqsave(&rs->rs_rdma_lock, flags);
 	mr = rds_mr_tree_walk(&rs->rs_rdma_keys, r_key, NULL);
-	if (mr == NULL)
+	if (!mr)
 		err = -EINVAL;	/* invalid r_key */
 	else
 		atomic_inc(&mr->r_refcount);
@@ -681,7 +701,7 @@
 
 	if (mr) {
 		mr->r_trans->sync_mr(mr->r_trans_private, DMA_TO_DEVICE);
-		rm->m_rdma_mr = mr;
+		rm->rdma.op_rdma_mr = mr;
 	}
 	return err;
 }
@@ -699,5 +719,98 @@
 	    rm->m_rdma_cookie != 0)
 		return -EINVAL;
 
-	return __rds_rdma_map(rs, CMSG_DATA(cmsg), &rm->m_rdma_cookie, &rm->m_rdma_mr);
+	return __rds_rdma_map(rs, CMSG_DATA(cmsg), &rm->m_rdma_cookie, &rm->rdma.op_rdma_mr);
+}
+
+/*
+ * Fill in rds_message for an atomic request.
+ */
+int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
+		    struct cmsghdr *cmsg)
+{
+	struct page *page = NULL;
+	struct rds_atomic_args *args;
+	int ret = 0;
+
+	if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct rds_atomic_args))
+	 || rm->atomic.op_active)
+		return -EINVAL;
+
+	args = CMSG_DATA(cmsg);
+
+	/* Nonmasked & masked cmsg ops converted to masked hw ops */
+	switch (cmsg->cmsg_type) {
+	case RDS_CMSG_ATOMIC_FADD:
+		rm->atomic.op_type = RDS_ATOMIC_TYPE_FADD;
+		rm->atomic.op_m_fadd.add = args->fadd.add;
+		rm->atomic.op_m_fadd.nocarry_mask = 0;
+		break;
+	case RDS_CMSG_MASKED_ATOMIC_FADD:
+		rm->atomic.op_type = RDS_ATOMIC_TYPE_FADD;
+		rm->atomic.op_m_fadd.add = args->m_fadd.add;
+		rm->atomic.op_m_fadd.nocarry_mask = args->m_fadd.nocarry_mask;
+		break;
+	case RDS_CMSG_ATOMIC_CSWP:
+		rm->atomic.op_type = RDS_ATOMIC_TYPE_CSWP;
+		rm->atomic.op_m_cswp.compare = args->cswp.compare;
+		rm->atomic.op_m_cswp.swap = args->cswp.swap;
+		rm->atomic.op_m_cswp.compare_mask = ~0;
+		rm->atomic.op_m_cswp.swap_mask = ~0;
+		break;
+	case RDS_CMSG_MASKED_ATOMIC_CSWP:
+		rm->atomic.op_type = RDS_ATOMIC_TYPE_CSWP;
+		rm->atomic.op_m_cswp.compare = args->m_cswp.compare;
+		rm->atomic.op_m_cswp.swap = args->m_cswp.swap;
+		rm->atomic.op_m_cswp.compare_mask = args->m_cswp.compare_mask;
+		rm->atomic.op_m_cswp.swap_mask = args->m_cswp.swap_mask;
+		break;
+	default:
+		BUG(); /* should never happen */
+	}
+
+	rm->atomic.op_notify = !!(args->flags & RDS_RDMA_NOTIFY_ME);
+	rm->atomic.op_silent = !!(args->flags & RDS_RDMA_SILENT);
+	rm->atomic.op_active = 1;
+	rm->atomic.op_recverr = rs->rs_recverr;
+	rm->atomic.op_sg = rds_message_alloc_sgs(rm, 1);
+
+	/* verify 8 byte-aligned */
+	if (args->local_addr & 0x7) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	ret = rds_pin_pages(args->local_addr, 1, &page, 1);
+	if (ret != 1)
+		goto err;
+	ret = 0;
+
+	sg_set_page(rm->atomic.op_sg, page, 8, offset_in_page(args->local_addr));
+
+	if (rm->atomic.op_notify || rm->atomic.op_recverr) {
+		/* We allocate an uninitialized notifier here, because
+		 * we don't want to do that in the completion handler. We
+		 * would have to use GFP_ATOMIC there, and don't want to deal
+		 * with failed allocations.
+		 */
+		rm->atomic.op_notifier = kmalloc(sizeof(*rm->atomic.op_notifier), GFP_KERNEL);
+		if (!rm->atomic.op_notifier) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		rm->atomic.op_notifier->n_user_token = args->user_token;
+		rm->atomic.op_notifier->n_status = RDS_RDMA_SUCCESS;
+	}
+
+	rm->atomic.op_rkey = rds_rdma_cookie_key(args->cookie);
+	rm->atomic.op_remote_addr = args->remote_addr + rds_rdma_cookie_offset(args->cookie);
+
+	return ret;
+err:
+	if (page)
+		put_page(page);
+	kfree(rm->atomic.op_notifier);
+
+	return ret;
 }
diff --git a/net/rds/rdma.h b/net/rds/rdma.h
deleted file mode 100644
index 909c398..0000000
--- a/net/rds/rdma.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef _RDS_RDMA_H
-#define _RDS_RDMA_H
-
-#include <linux/rbtree.h>
-#include <linux/spinlock.h>
-#include <linux/scatterlist.h>
-
-#include "rds.h"
-
-struct rds_mr {
-	struct rb_node		r_rb_node;
-	atomic_t		r_refcount;
-	u32			r_key;
-
-	/* A copy of the creation flags */
-	unsigned int		r_use_once:1;
-	unsigned int		r_invalidate:1;
-	unsigned int		r_write:1;
-
-	/* This is for RDS_MR_DEAD.
-	 * It would be nice & consistent to make this part of the above
-	 * bit field here, but we need to use test_and_set_bit.
-	 */
-	unsigned long		r_state;
-	struct rds_sock		*r_sock; /* back pointer to the socket that owns us */
-	struct rds_transport	*r_trans;
-	void			*r_trans_private;
-};
-
-/* Flags for mr->r_state */
-#define RDS_MR_DEAD		0
-
-struct rds_rdma_op {
-	u32			r_key;
-	u64			r_remote_addr;
-	unsigned int		r_write:1;
-	unsigned int		r_fence:1;
-	unsigned int		r_notify:1;
-	unsigned int		r_recverr:1;
-	unsigned int		r_mapped:1;
-	struct rds_notifier	*r_notifier;
-	unsigned int		r_bytes;
-	unsigned int		r_nents;
-	unsigned int		r_count;
-	struct scatterlist	r_sg[0];
-};
-
-static inline rds_rdma_cookie_t rds_rdma_make_cookie(u32 r_key, u32 offset)
-{
-	return r_key | (((u64) offset) << 32);
-}
-
-static inline u32 rds_rdma_cookie_key(rds_rdma_cookie_t cookie)
-{
-	return cookie;
-}
-
-static inline u32 rds_rdma_cookie_offset(rds_rdma_cookie_t cookie)
-{
-	return cookie >> 32;
-}
-
-int rds_get_mr(struct rds_sock *rs, char __user *optval, int optlen);
-int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen);
-int rds_free_mr(struct rds_sock *rs, char __user *optval, int optlen);
-void rds_rdma_drop_keys(struct rds_sock *rs);
-int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
-			  struct cmsghdr *cmsg);
-int rds_cmsg_rdma_dest(struct rds_sock *rs, struct rds_message *rm,
-			  struct cmsghdr *cmsg);
-int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
-			  struct cmsghdr *cmsg);
-int rds_cmsg_rdma_map(struct rds_sock *rs, struct rds_message *rm,
-			  struct cmsghdr *cmsg);
-void rds_rdma_free_op(struct rds_rdma_op *ro);
-void rds_rdma_send_complete(struct rds_message *rm, int);
-
-extern void __rds_put_mr_final(struct rds_mr *mr);
-static inline void rds_mr_put(struct rds_mr *mr)
-{
-	if (atomic_dec_and_test(&mr->r_refcount))
-		__rds_put_mr_final(mr);
-}
-
-#endif
diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c
index e599ba2..4195a05 100644
--- a/net/rds/rdma_transport.c
+++ b/net/rds/rdma_transport.c
@@ -36,6 +36,34 @@
 
 static struct rdma_cm_id *rds_rdma_listen_id;
 
+static char *rds_cm_event_strings[] = {
+#define RDS_CM_EVENT_STRING(foo) \
+		[RDMA_CM_EVENT_##foo] = __stringify(RDMA_CM_EVENT_##foo)
+	RDS_CM_EVENT_STRING(ADDR_RESOLVED),
+	RDS_CM_EVENT_STRING(ADDR_ERROR),
+	RDS_CM_EVENT_STRING(ROUTE_RESOLVED),
+	RDS_CM_EVENT_STRING(ROUTE_ERROR),
+	RDS_CM_EVENT_STRING(CONNECT_REQUEST),
+	RDS_CM_EVENT_STRING(CONNECT_RESPONSE),
+	RDS_CM_EVENT_STRING(CONNECT_ERROR),
+	RDS_CM_EVENT_STRING(UNREACHABLE),
+	RDS_CM_EVENT_STRING(REJECTED),
+	RDS_CM_EVENT_STRING(ESTABLISHED),
+	RDS_CM_EVENT_STRING(DISCONNECTED),
+	RDS_CM_EVENT_STRING(DEVICE_REMOVAL),
+	RDS_CM_EVENT_STRING(MULTICAST_JOIN),
+	RDS_CM_EVENT_STRING(MULTICAST_ERROR),
+	RDS_CM_EVENT_STRING(ADDR_CHANGE),
+	RDS_CM_EVENT_STRING(TIMEWAIT_EXIT),
+#undef RDS_CM_EVENT_STRING
+};
+
+static char *rds_cm_event_str(enum rdma_cm_event_type type)
+{
+	return rds_str_array(rds_cm_event_strings,
+			     ARRAY_SIZE(rds_cm_event_strings), type);
+};
+
 int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
 			      struct rdma_cm_event *event)
 {
@@ -44,8 +72,8 @@
 	struct rds_transport *trans;
 	int ret = 0;
 
-	rdsdebug("conn %p id %p handling event %u\n", conn, cm_id,
-		 event->event);
+	rdsdebug("conn %p id %p handling event %u (%s)\n", conn, cm_id,
+		 event->event, rds_cm_event_str(event->event));
 
 	if (cm_id->device->node_type == RDMA_NODE_RNIC)
 		trans = &rds_iw_transport;
@@ -109,7 +137,8 @@
 
 	default:
 		/* things like device disconnect? */
-		printk(KERN_ERR "RDS: unknown event %u!\n", event->event);
+		printk(KERN_ERR "RDS: unknown event %u (%s)!\n",
+		       event->event, rds_cm_event_str(event->event));
 		break;
 	}
 
@@ -117,12 +146,13 @@
 	if (conn)
 		mutex_unlock(&conn->c_cm_lock);
 
-	rdsdebug("id %p event %u handling ret %d\n", cm_id, event->event, ret);
+	rdsdebug("id %p event %u (%s) handling ret %d\n", cm_id, event->event,
+		 rds_cm_event_str(event->event), ret);
 
 	return ret;
 }
 
-static int __init rds_rdma_listen_init(void)
+static int rds_rdma_listen_init(void)
 {
 	struct sockaddr_in sin;
 	struct rdma_cm_id *cm_id;
@@ -177,7 +207,7 @@
 	}
 }
 
-int __init rds_rdma_init(void)
+static int rds_rdma_init(void)
 {
 	int ret;
 
@@ -204,7 +234,7 @@
 }
 module_init(rds_rdma_init);
 
-void rds_rdma_exit(void)
+static void rds_rdma_exit(void)
 {
 	/* stop listening first to ensure no new connections are attempted */
 	rds_rdma_listen_stop();
diff --git a/net/rds/rdma_transport.h b/net/rds/rdma_transport.h
index 2f2c7d9..faba4e3 100644
--- a/net/rds/rdma_transport.h
+++ b/net/rds/rdma_transport.h
@@ -11,10 +11,6 @@
 int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id,
 			      struct rdma_cm_event *event);
 
-/* from rdma_transport.c */
-int rds_rdma_init(void);
-void rds_rdma_exit(void);
-
 /* from ib.c */
 extern struct rds_transport rds_ib_transport;
 int rds_ib_init(void);
diff --git a/net/rds/rds.h b/net/rds/rds.h
index c224b5b..9542449 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -80,6 +80,7 @@
 /* Bits for c_flags */
 #define RDS_LL_SEND_FULL	0
 #define RDS_RECONNECT_PENDING	1
+#define RDS_IN_XMIT		2
 
 struct rds_connection {
 	struct hlist_node	c_hash_node;
@@ -91,12 +92,13 @@
 	struct rds_cong_map	*c_lcong;
 	struct rds_cong_map	*c_fcong;
 
-	struct mutex		c_send_lock;	/* protect send ring */
 	struct rds_message	*c_xmit_rm;
 	unsigned long		c_xmit_sg;
 	unsigned int		c_xmit_hdr_off;
 	unsigned int		c_xmit_data_off;
+	unsigned int		c_xmit_atomic_sent;
 	unsigned int		c_xmit_rdma_sent;
+	unsigned int		c_xmit_data_sent;
 
 	spinlock_t		c_lock;		/* protect msg queues */
 	u64			c_next_tx_seq;
@@ -116,11 +118,10 @@
 	struct delayed_work	c_conn_w;
 	struct work_struct	c_down_w;
 	struct mutex		c_cm_lock;	/* protect conn state & cm */
+	wait_queue_head_t	c_waitq;
 
 	struct list_head	c_map_item;
 	unsigned long		c_map_queued;
-	unsigned long		c_map_offset;
-	unsigned long		c_map_bytes;
 
 	unsigned int		c_unacked_packets;
 	unsigned int		c_unacked_bytes;
@@ -206,6 +207,48 @@
 	rds_rdma_cookie_t	i_rdma_cookie;
 };
 
+struct rds_mr {
+	struct rb_node		r_rb_node;
+	atomic_t		r_refcount;
+	u32			r_key;
+
+	/* A copy of the creation flags */
+	unsigned int		r_use_once:1;
+	unsigned int		r_invalidate:1;
+	unsigned int		r_write:1;
+
+	/* This is for RDS_MR_DEAD.
+	 * It would be nice & consistent to make this part of the above
+	 * bit field here, but we need to use test_and_set_bit.
+	 */
+	unsigned long		r_state;
+	struct rds_sock		*r_sock; /* back pointer to the socket that owns us */
+	struct rds_transport	*r_trans;
+	void			*r_trans_private;
+};
+
+/* Flags for mr->r_state */
+#define RDS_MR_DEAD		0
+
+static inline rds_rdma_cookie_t rds_rdma_make_cookie(u32 r_key, u32 offset)
+{
+	return r_key | (((u64) offset) << 32);
+}
+
+static inline u32 rds_rdma_cookie_key(rds_rdma_cookie_t cookie)
+{
+	return cookie;
+}
+
+static inline u32 rds_rdma_cookie_offset(rds_rdma_cookie_t cookie)
+{
+	return cookie >> 32;
+}
+
+/* atomic operation types */
+#define RDS_ATOMIC_TYPE_CSWP		0
+#define RDS_ATOMIC_TYPE_FADD		1
+
 /*
  * m_sock_item and m_conn_item are on lists that are serialized under
  * conn->c_lock.  m_sock_item has additional meaning in that once it is empty
@@ -258,13 +301,71 @@
 	 *   -> rs->rs_lock
 	 */
 	spinlock_t		m_rs_lock;
+	wait_queue_head_t	m_flush_wait;
+
 	struct rds_sock		*m_rs;
-	struct rds_rdma_op	*m_rdma_op;
+
+	/* cookie to send to remote, in rds header */
 	rds_rdma_cookie_t	m_rdma_cookie;
-	struct rds_mr		*m_rdma_mr;
-	unsigned int		m_nents;
-	unsigned int		m_count;
-	struct scatterlist	m_sg[0];
+
+	unsigned int		m_used_sgs;
+	unsigned int		m_total_sgs;
+
+	void			*m_final_op;
+
+	struct {
+		struct rm_atomic_op {
+			int			op_type;
+			union {
+				struct {
+					uint64_t	compare;
+					uint64_t	swap;
+					uint64_t	compare_mask;
+					uint64_t	swap_mask;
+				} op_m_cswp;
+				struct {
+					uint64_t	add;
+					uint64_t	nocarry_mask;
+				} op_m_fadd;
+			};
+
+			u32			op_rkey;
+			u64			op_remote_addr;
+			unsigned int		op_notify:1;
+			unsigned int		op_recverr:1;
+			unsigned int		op_mapped:1;
+			unsigned int		op_silent:1;
+			unsigned int		op_active:1;
+			struct scatterlist	*op_sg;
+			struct rds_notifier	*op_notifier;
+
+			struct rds_mr		*op_rdma_mr;
+		} atomic;
+		struct rm_rdma_op {
+			u32			op_rkey;
+			u64			op_remote_addr;
+			unsigned int		op_write:1;
+			unsigned int		op_fence:1;
+			unsigned int		op_notify:1;
+			unsigned int		op_recverr:1;
+			unsigned int		op_mapped:1;
+			unsigned int		op_silent:1;
+			unsigned int		op_active:1;
+			unsigned int		op_bytes;
+			unsigned int		op_nents;
+			unsigned int		op_count;
+			struct scatterlist	*op_sg;
+			struct rds_notifier	*op_notifier;
+
+			struct rds_mr		*op_rdma_mr;
+		} rdma;
+		struct rm_data_op {
+			unsigned int		op_active:1;
+			unsigned int		op_nents;
+			unsigned int		op_count;
+			struct scatterlist	*op_sg;
+		} data;
+	};
 };
 
 /*
@@ -305,10 +406,6 @@
  *                 transport is responsible for other serialization, including
  *                 rds_recv_incoming().  This is called in process context but
  *                 should try hard not to block.
- *
- * @xmit_cong_map: This asks the transport to send the local bitmap down the
- * 		   given connection.  XXX get a better story about the bitmap
- * 		   flag and header.
  */
 
 #define RDS_TRANS_IB	0
@@ -332,13 +429,11 @@
 	void (*xmit_complete)(struct rds_connection *conn);
 	int (*xmit)(struct rds_connection *conn, struct rds_message *rm,
 		    unsigned int hdr_off, unsigned int sg, unsigned int off);
-	int (*xmit_cong_map)(struct rds_connection *conn,
-			     struct rds_cong_map *map, unsigned long offset);
-	int (*xmit_rdma)(struct rds_connection *conn, struct rds_rdma_op *op);
+	int (*xmit_rdma)(struct rds_connection *conn, struct rm_rdma_op *op);
+	int (*xmit_atomic)(struct rds_connection *conn, struct rm_atomic_op *op);
 	int (*recv)(struct rds_connection *conn);
 	int (*inc_copy_to_user)(struct rds_incoming *inc, struct iovec *iov,
 				size_t size);
-	void (*inc_purge)(struct rds_incoming *inc);
 	void (*inc_free)(struct rds_incoming *inc);
 
 	int (*cm_handle_connect)(struct rdma_cm_id *cm_id,
@@ -367,17 +462,11 @@
 	 * bound_addr used for both incoming and outgoing, no INADDR_ANY
 	 * support.
 	 */
-	struct rb_node		rs_bound_node;
+	struct hlist_node	rs_bound_node;
 	__be32			rs_bound_addr;
 	__be32			rs_conn_addr;
 	__be16			rs_bound_port;
 	__be16			rs_conn_port;
-
-	/*
-	 * This is only used to communicate the transport between bind and
-	 * initiating connections.  All other trans use is referenced through
-	 * the connection.
-	 */
 	struct rds_transport    *rs_transport;
 
 	/*
@@ -466,8 +555,8 @@
 	uint64_t	s_recv_ping;
 	uint64_t	s_send_queue_empty;
 	uint64_t	s_send_queue_full;
-	uint64_t	s_send_sem_contention;
-	uint64_t	s_send_sem_queue_raced;
+	uint64_t	s_send_lock_contention;
+	uint64_t	s_send_lock_queue_raced;
 	uint64_t	s_send_immediate_retry;
 	uint64_t	s_send_delayed_retry;
 	uint64_t	s_send_drop_acked;
@@ -487,6 +576,7 @@
 };
 
 /* af_rds.c */
+char *rds_str_array(char **array, size_t elements, size_t index);
 void rds_sock_addref(struct rds_sock *rs);
 void rds_sock_put(struct rds_sock *rs);
 void rds_wake_sk_sleep(struct rds_sock *rs);
@@ -521,15 +611,16 @@
 struct rds_message *rds_cong_update_alloc(struct rds_connection *conn);
 
 /* conn.c */
-int __init rds_conn_init(void);
+int rds_conn_init(void);
 void rds_conn_exit(void);
 struct rds_connection *rds_conn_create(__be32 laddr, __be32 faddr,
 				       struct rds_transport *trans, gfp_t gfp);
 struct rds_connection *rds_conn_create_outgoing(__be32 laddr, __be32 faddr,
 			       struct rds_transport *trans, gfp_t gfp);
+void rds_conn_shutdown(struct rds_connection *conn);
 void rds_conn_destroy(struct rds_connection *conn);
-void rds_conn_reset(struct rds_connection *conn);
 void rds_conn_drop(struct rds_connection *conn);
+void rds_conn_connect_if_down(struct rds_connection *conn);
 void rds_for_each_conn_info(struct socket *sock, unsigned int len,
 			  struct rds_info_iterator *iter,
 			  struct rds_info_lengths *lens,
@@ -566,7 +657,8 @@
 
 /* message.c */
 struct rds_message *rds_message_alloc(unsigned int nents, gfp_t gfp);
-struct rds_message *rds_message_copy_from_user(struct iovec *first_iov,
+struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents);
+int rds_message_copy_from_user(struct rds_message *rm, struct iovec *first_iov,
 					       size_t total_len);
 struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned int total_len);
 void rds_message_populate_header(struct rds_header *hdr, __be16 sport,
@@ -575,12 +667,9 @@
 			      unsigned int type, const void *data, unsigned int len);
 int rds_message_next_extension(struct rds_header *hdr,
 			       unsigned int *pos, void *buf, unsigned int *buflen);
-int rds_message_add_version_extension(struct rds_header *hdr, unsigned int version);
-int rds_message_get_version_extension(struct rds_header *hdr, unsigned int *version);
 int rds_message_add_rdma_dest_extension(struct rds_header *hdr, u32 r_key, u32 offset);
 int rds_message_inc_copy_to_user(struct rds_incoming *inc,
 				 struct iovec *first_iov, size_t size);
-void rds_message_inc_purge(struct rds_incoming *inc);
 void rds_message_inc_free(struct rds_incoming *inc);
 void rds_message_addref(struct rds_message *rm);
 void rds_message_put(struct rds_message *rm);
@@ -614,7 +703,6 @@
 /* recv.c */
 void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
 		  __be32 saddr);
-void rds_inc_addref(struct rds_incoming *inc);
 void rds_inc_put(struct rds_incoming *inc);
 void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr,
 		       struct rds_incoming *inc, gfp_t gfp, enum km_type km);
@@ -636,14 +724,38 @@
 typedef int (*is_acked_func)(struct rds_message *rm, uint64_t ack);
 void rds_send_drop_acked(struct rds_connection *conn, u64 ack,
 			 is_acked_func is_acked);
-int rds_send_acked_before(struct rds_connection *conn, u64 seq);
-void rds_send_remove_from_sock(struct list_head *messages, int status);
 int rds_send_pong(struct rds_connection *conn, __be16 dport);
 struct rds_message *rds_send_get_message(struct rds_connection *,
-					 struct rds_rdma_op *);
+					 struct rm_rdma_op *);
 
 /* rdma.c */
 void rds_rdma_unuse(struct rds_sock *rs, u32 r_key, int force);
+int rds_get_mr(struct rds_sock *rs, char __user *optval, int optlen);
+int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen);
+int rds_free_mr(struct rds_sock *rs, char __user *optval, int optlen);
+void rds_rdma_drop_keys(struct rds_sock *rs);
+int rds_rdma_extra_size(struct rds_rdma_args *args);
+int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
+			  struct cmsghdr *cmsg);
+int rds_cmsg_rdma_dest(struct rds_sock *rs, struct rds_message *rm,
+			  struct cmsghdr *cmsg);
+int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
+			  struct cmsghdr *cmsg);
+int rds_cmsg_rdma_map(struct rds_sock *rs, struct rds_message *rm,
+			  struct cmsghdr *cmsg);
+void rds_rdma_free_op(struct rm_rdma_op *ro);
+void rds_atomic_free_op(struct rm_atomic_op *ao);
+void rds_rdma_send_complete(struct rds_message *rm, int wc_status);
+void rds_atomic_send_complete(struct rds_message *rm, int wc_status);
+int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
+		    struct cmsghdr *cmsg);
+
+extern void __rds_put_mr_final(struct rds_mr *mr);
+static inline void rds_mr_put(struct rds_mr *mr)
+{
+	if (atomic_dec_and_test(&mr->r_refcount))
+		__rds_put_mr_final(mr);
+}
 
 /* stats.c */
 DECLARE_PER_CPU_SHARED_ALIGNED(struct rds_statistics, rds_stats);
@@ -657,14 +769,14 @@
 	put_cpu();					\
 } while (0)
 #define rds_stats_add(member, count) rds_stats_add_which(rds_stats, member, count)
-int __init rds_stats_init(void);
+int rds_stats_init(void);
 void rds_stats_exit(void);
 void rds_stats_info_copy(struct rds_info_iterator *iter,
 			 uint64_t *values, const char *const *names,
 			 size_t nr);
 
 /* sysctl.c */
-int __init rds_sysctl_init(void);
+int rds_sysctl_init(void);
 void rds_sysctl_exit(void);
 extern unsigned long rds_sysctl_sndbuf_min;
 extern unsigned long rds_sysctl_sndbuf_default;
@@ -678,9 +790,10 @@
 extern unsigned int  rds_sysctl_trace_level;
 
 /* threads.c */
-int __init rds_threads_init(void);
+int rds_threads_init(void);
 void rds_threads_exit(void);
 extern struct workqueue_struct *rds_wq;
+void rds_queue_reconnect(struct rds_connection *conn);
 void rds_connect_worker(struct work_struct *);
 void rds_shutdown_worker(struct work_struct *);
 void rds_send_worker(struct work_struct *);
@@ -691,9 +804,10 @@
 int rds_trans_register(struct rds_transport *trans);
 void rds_trans_unregister(struct rds_transport *trans);
 struct rds_transport *rds_trans_get_preferred(__be32 addr);
+void rds_trans_put(struct rds_transport *trans);
 unsigned int rds_trans_stats_info_copy(struct rds_info_iterator *iter,
 				       unsigned int avail);
-int __init rds_trans_init(void);
+int rds_trans_init(void);
 void rds_trans_exit(void);
 
 #endif
diff --git a/net/rds/recv.c b/net/rds/recv.c
index c93588c..596689e 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -36,7 +36,6 @@
 #include <linux/in.h>
 
 #include "rds.h"
-#include "rdma.h"
 
 void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
 		  __be32 saddr)
@@ -49,12 +48,11 @@
 }
 EXPORT_SYMBOL_GPL(rds_inc_init);
 
-void rds_inc_addref(struct rds_incoming *inc)
+static void rds_inc_addref(struct rds_incoming *inc)
 {
 	rdsdebug("addref inc %p ref %d\n", inc, atomic_read(&inc->i_refcount));
 	atomic_inc(&inc->i_refcount);
 }
-EXPORT_SYMBOL_GPL(rds_inc_addref);
 
 void rds_inc_put(struct rds_incoming *inc)
 {
@@ -210,7 +208,7 @@
 	}
 
 	rs = rds_find_bound(daddr, inc->i_hdr.h_dport);
-	if (rs == NULL) {
+	if (!rs) {
 		rds_stats_inc(s_recv_drop_no_sock);
 		goto out;
 	}
@@ -251,7 +249,7 @@
 {
 	unsigned long flags;
 
-	if (*inc == NULL) {
+	if (!*inc) {
 		read_lock_irqsave(&rs->rs_recv_lock, flags);
 		if (!list_empty(&rs->rs_recv_queue)) {
 			*inc = list_entry(rs->rs_recv_queue.next,
@@ -334,10 +332,10 @@
 
 		if (msghdr) {
 			cmsg.user_token = notifier->n_user_token;
-			cmsg.status  = notifier->n_status;
+			cmsg.status = notifier->n_status;
 
 			err = put_cmsg(msghdr, SOL_RDS, RDS_CMSG_RDMA_STATUS,
-					sizeof(cmsg), &cmsg);
+				       sizeof(cmsg), &cmsg);
 			if (err)
 				break;
 		}
diff --git a/net/rds/send.c b/net/rds/send.c
index 9c1c6bc..0bc9db1 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -37,7 +37,6 @@
 #include <linux/list.h>
 
 #include "rds.h"
-#include "rdma.h"
 
 /* When transmitting messages in rds_send_xmit, we need to emerge from
  * time to time and briefly release the CPU. Otherwise the softlock watchdog
@@ -53,8 +52,11 @@
 module_param(send_batch_count, int, 0444);
 MODULE_PARM_DESC(send_batch_count, " batch factor when working the send queue");
 
+static void rds_send_remove_from_sock(struct list_head *messages, int status);
+
 /*
- * Reset the send state. Caller must hold c_send_lock when calling here.
+ * Reset the send state.  Callers must ensure that this doesn't race with
+ * rds_send_xmit().
  */
 void rds_send_reset(struct rds_connection *conn)
 {
@@ -62,18 +64,22 @@
 	unsigned long flags;
 
 	if (conn->c_xmit_rm) {
+		rm = conn->c_xmit_rm;
+		conn->c_xmit_rm = NULL;
 		/* Tell the user the RDMA op is no longer mapped by the
 		 * transport. This isn't entirely true (it's flushed out
 		 * independently) but as the connection is down, there's
 		 * no ongoing RDMA to/from that memory */
-		rds_message_unmapped(conn->c_xmit_rm);
-		rds_message_put(conn->c_xmit_rm);
-		conn->c_xmit_rm = NULL;
+		rds_message_unmapped(rm);
+		rds_message_put(rm);
 	}
+
 	conn->c_xmit_sg = 0;
 	conn->c_xmit_hdr_off = 0;
 	conn->c_xmit_data_off = 0;
+	conn->c_xmit_atomic_sent = 0;
 	conn->c_xmit_rdma_sent = 0;
+	conn->c_xmit_data_sent = 0;
 
 	conn->c_map_queued = 0;
 
@@ -90,6 +96,25 @@
 	spin_unlock_irqrestore(&conn->c_lock, flags);
 }
 
+static int acquire_in_xmit(struct rds_connection *conn)
+{
+	return test_and_set_bit(RDS_IN_XMIT, &conn->c_flags) == 0;
+}
+
+static void release_in_xmit(struct rds_connection *conn)
+{
+	clear_bit(RDS_IN_XMIT, &conn->c_flags);
+	smp_mb__after_clear_bit();
+	/*
+	 * We don't use wait_on_bit()/wake_up_bit() because our waking is in a
+	 * hot path and finding waiters is very rare.  We don't want to walk
+	 * the system-wide hashed waitqueue buckets in the fast path only to
+	 * almost never find waiters.
+	 */
+	if (waitqueue_active(&conn->c_waitq))
+		wake_up_all(&conn->c_waitq);
+}
+
 /*
  * We're making the concious trade-off here to only send one message
  * down the connection at a time.
@@ -109,102 +134,69 @@
 	struct rds_message *rm;
 	unsigned long flags;
 	unsigned int tmp;
-	unsigned int send_quota = send_batch_count;
 	struct scatterlist *sg;
 	int ret = 0;
-	int was_empty = 0;
 	LIST_HEAD(to_be_dropped);
 
+restart:
+
 	/*
 	 * sendmsg calls here after having queued its message on the send
 	 * queue.  We only have one task feeding the connection at a time.  If
 	 * another thread is already feeding the queue then we back off.  This
 	 * avoids blocking the caller and trading per-connection data between
 	 * caches per message.
-	 *
-	 * The sem holder will issue a retry if they notice that someone queued
-	 * a message after they stopped walking the send queue but before they
-	 * dropped the sem.
 	 */
-	if (!mutex_trylock(&conn->c_send_lock)) {
-		rds_stats_inc(s_send_sem_contention);
+	if (!acquire_in_xmit(conn)) {
+		rds_stats_inc(s_send_lock_contention);
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	/*
+	 * rds_conn_shutdown() sets the conn state and then tests RDS_IN_XMIT,
+	 * we do the opposite to avoid races.
+	 */
+	if (!rds_conn_up(conn)) {
+		release_in_xmit(conn);
+		ret = 0;
+		goto out;
+	}
+
 	if (conn->c_trans->xmit_prepare)
 		conn->c_trans->xmit_prepare(conn);
 
 	/*
 	 * spin trying to push headers and data down the connection until
-	 * the connection doens't make forward progress.
+	 * the connection doesn't make forward progress.
 	 */
-	while (--send_quota) {
-		/*
-		 * See if need to send a congestion map update if we're
-		 * between sending messages.  The send_sem protects our sole
-		 * use of c_map_offset and _bytes.
-		 * Note this is used only by transports that define a special
-		 * xmit_cong_map function. For all others, we create allocate
-		 * a cong_map message and treat it just like any other send.
-		 */
-		if (conn->c_map_bytes) {
-			ret = conn->c_trans->xmit_cong_map(conn, conn->c_lcong,
-						conn->c_map_offset);
-			if (ret <= 0)
-				break;
+	while (1) {
 
-			conn->c_map_offset += ret;
-			conn->c_map_bytes -= ret;
-			if (conn->c_map_bytes)
-				continue;
-		}
-
-		/* If we're done sending the current message, clear the
-		 * offset and S/G temporaries.
-		 */
 		rm = conn->c_xmit_rm;
-		if (rm != NULL &&
-		    conn->c_xmit_hdr_off == sizeof(struct rds_header) &&
-		    conn->c_xmit_sg == rm->m_nents) {
-			conn->c_xmit_rm = NULL;
-			conn->c_xmit_sg = 0;
-			conn->c_xmit_hdr_off = 0;
-			conn->c_xmit_data_off = 0;
-			conn->c_xmit_rdma_sent = 0;
 
-			/* Release the reference to the previous message. */
-			rds_message_put(rm);
-			rm = NULL;
-		}
-
-		/* If we're asked to send a cong map update, do so.
+		/*
+		 * If between sending messages, we can send a pending congestion
+		 * map update.
 		 */
-		if (rm == NULL && test_and_clear_bit(0, &conn->c_map_queued)) {
-			if (conn->c_trans->xmit_cong_map != NULL) {
-				conn->c_map_offset = 0;
-				conn->c_map_bytes = sizeof(struct rds_header) +
-					RDS_CONG_MAP_BYTES;
-				continue;
-			}
-
+		if (!rm && test_and_clear_bit(0, &conn->c_map_queued)) {
 			rm = rds_cong_update_alloc(conn);
 			if (IS_ERR(rm)) {
 				ret = PTR_ERR(rm);
 				break;
 			}
+			rm->data.op_active = 1;
 
 			conn->c_xmit_rm = rm;
 		}
 
 		/*
-		 * Grab the next message from the send queue, if there is one.
+		 * If not already working on one, grab the next message.
 		 *
 		 * c_xmit_rm holds a ref while we're sending this message down
 		 * the connction.  We can use this ref while holding the
 		 * send_sem.. rds_send_reset() is serialized with it.
 		 */
-		if (rm == NULL) {
+		if (!rm) {
 			unsigned int len;
 
 			spin_lock_irqsave(&conn->c_lock, flags);
@@ -224,10 +216,8 @@
 
 			spin_unlock_irqrestore(&conn->c_lock, flags);
 
-			if (rm == NULL) {
-				was_empty = 1;
+			if (!rm)
 				break;
-			}
 
 			/* Unfortunately, the way Infiniband deals with
 			 * RDMA to a bad MR key is by moving the entire
@@ -236,13 +226,12 @@
 			 * connection.
 			 * Therefore, we never retransmit messages with RDMA ops.
 			 */
-			if (rm->m_rdma_op &&
+			if (rm->rdma.op_active &&
 			    test_bit(RDS_MSG_RETRANSMITTED, &rm->m_flags)) {
 				spin_lock_irqsave(&conn->c_lock, flags);
 				if (test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags))
 					list_move(&rm->m_conn_item, &to_be_dropped);
 				spin_unlock_irqrestore(&conn->c_lock, flags);
-				rds_message_put(rm);
 				continue;
 			}
 
@@ -263,23 +252,55 @@
 			conn->c_xmit_rm = rm;
 		}
 
-		/*
-		 * Try and send an rdma message.  Let's see if we can
-		 * keep this simple and require that the transport either
-		 * send the whole rdma or none of it.
-		 */
-		if (rm->m_rdma_op && !conn->c_xmit_rdma_sent) {
-			ret = conn->c_trans->xmit_rdma(conn, rm->m_rdma_op);
+		/* The transport either sends the whole rdma or none of it */
+		if (rm->rdma.op_active && !conn->c_xmit_rdma_sent) {
+			rm->m_final_op = &rm->rdma;
+			ret = conn->c_trans->xmit_rdma(conn, &rm->rdma);
 			if (ret)
 				break;
 			conn->c_xmit_rdma_sent = 1;
+
 			/* The transport owns the mapped memory for now.
 			 * You can't unmap it while it's on the send queue */
 			set_bit(RDS_MSG_MAPPED, &rm->m_flags);
 		}
 
-		if (conn->c_xmit_hdr_off < sizeof(struct rds_header) ||
-		    conn->c_xmit_sg < rm->m_nents) {
+		if (rm->atomic.op_active && !conn->c_xmit_atomic_sent) {
+			rm->m_final_op = &rm->atomic;
+			ret = conn->c_trans->xmit_atomic(conn, &rm->atomic);
+			if (ret)
+				break;
+			conn->c_xmit_atomic_sent = 1;
+
+			/* The transport owns the mapped memory for now.
+			 * You can't unmap it while it's on the send queue */
+			set_bit(RDS_MSG_MAPPED, &rm->m_flags);
+		}
+
+		/*
+		 * A number of cases require an RDS header to be sent
+		 * even if there is no data.
+		 * We permit 0-byte sends; rds-ping depends on this.
+		 * However, if there are exclusively attached silent ops,
+		 * we skip the hdr/data send, to enable silent operation.
+		 */
+		if (rm->data.op_nents == 0) {
+			int ops_present;
+			int all_ops_are_silent = 1;
+
+			ops_present = (rm->atomic.op_active || rm->rdma.op_active);
+			if (rm->atomic.op_active && !rm->atomic.op_silent)
+				all_ops_are_silent = 0;
+			if (rm->rdma.op_active && !rm->rdma.op_silent)
+				all_ops_are_silent = 0;
+
+			if (ops_present && all_ops_are_silent
+			    && !rm->m_rdma_cookie)
+				rm->data.op_active = 0;
+		}
+
+		if (rm->data.op_active && !conn->c_xmit_data_sent) {
+			rm->m_final_op = &rm->data;
 			ret = conn->c_trans->xmit(conn, rm,
 						  conn->c_xmit_hdr_off,
 						  conn->c_xmit_sg,
@@ -295,7 +316,7 @@
 				ret -= tmp;
 			}
 
-			sg = &rm->m_sg[conn->c_xmit_sg];
+			sg = &rm->data.op_sg[conn->c_xmit_sg];
 			while (ret) {
 				tmp = min_t(int, ret, sg->length -
 						      conn->c_xmit_data_off);
@@ -306,49 +327,63 @@
 					sg++;
 					conn->c_xmit_sg++;
 					BUG_ON(ret != 0 &&
-					       conn->c_xmit_sg == rm->m_nents);
+					       conn->c_xmit_sg == rm->data.op_nents);
 				}
 			}
+
+			if (conn->c_xmit_hdr_off == sizeof(struct rds_header) &&
+			    (conn->c_xmit_sg == rm->data.op_nents))
+				conn->c_xmit_data_sent = 1;
+		}
+
+		/*
+		 * A rm will only take multiple times through this loop
+		 * if there is a data op. Thus, if the data is sent (or there was
+		 * none), then we're done with the rm.
+		 */
+		if (!rm->data.op_active || conn->c_xmit_data_sent) {
+			conn->c_xmit_rm = NULL;
+			conn->c_xmit_sg = 0;
+			conn->c_xmit_hdr_off = 0;
+			conn->c_xmit_data_off = 0;
+			conn->c_xmit_rdma_sent = 0;
+			conn->c_xmit_atomic_sent = 0;
+			conn->c_xmit_data_sent = 0;
+
+			rds_message_put(rm);
 		}
 	}
 
-	/* Nuke any messages we decided not to retransmit. */
-	if (!list_empty(&to_be_dropped))
-		rds_send_remove_from_sock(&to_be_dropped, RDS_RDMA_DROPPED);
-
 	if (conn->c_trans->xmit_complete)
 		conn->c_trans->xmit_complete(conn);
 
-	/*
-	 * We might be racing with another sender who queued a message but
-	 * backed off on noticing that we held the c_send_lock.  If we check
-	 * for queued messages after dropping the sem then either we'll
-	 * see the queued message or the queuer will get the sem.  If we
-	 * notice the queued message then we trigger an immediate retry.
-	 *
-	 * We need to be careful only to do this when we stopped processing
-	 * the send queue because it was empty.  It's the only way we
-	 * stop processing the loop when the transport hasn't taken
-	 * responsibility for forward progress.
-	 */
-	mutex_unlock(&conn->c_send_lock);
+	release_in_xmit(conn);
 
-	if (conn->c_map_bytes || (send_quota == 0 && !was_empty)) {
-		/* We exhausted the send quota, but there's work left to
-		 * do. Return and (re-)schedule the send worker.
-		 */
-		ret = -EAGAIN;
+	/* Nuke any messages we decided not to retransmit. */
+	if (!list_empty(&to_be_dropped)) {
+		/* irqs on here, so we can put(), unlike above */
+		list_for_each_entry(rm, &to_be_dropped, m_conn_item)
+			rds_message_put(rm);
+		rds_send_remove_from_sock(&to_be_dropped, RDS_RDMA_DROPPED);
 	}
 
-	if (ret == 0 && was_empty) {
-		/* A simple bit test would be way faster than taking the
-		 * spin lock */
-		spin_lock_irqsave(&conn->c_lock, flags);
+	/*
+	 * Other senders can queue a message after we last test the send queue
+	 * but before we clear RDS_IN_XMIT.  In that case they'd back off and
+	 * not try and send their newly queued message.  We need to check the
+	 * send queue after having cleared RDS_IN_XMIT so that their message
+	 * doesn't get stuck on the send queue.
+	 *
+	 * If the transport cannot continue (i.e ret != 0), then it must
+	 * call us when more room is available, such as from the tx
+	 * completion handler.
+	 */
+	if (ret == 0) {
+		smp_mb();
 		if (!list_empty(&conn->c_send_queue)) {
-			rds_stats_inc(s_send_sem_queue_raced);
-			ret = -EAGAIN;
+			rds_stats_inc(s_send_lock_queue_raced);
+			goto restart;
 		}
-		spin_unlock_irqrestore(&conn->c_lock, flags);
 	}
 out:
 	return ret;
@@ -376,35 +411,6 @@
 }
 
 /*
- * Returns true if there are no messages on the send and retransmit queues
- * which have a sequence number greater than or equal to the given sequence
- * number.
- */
-int rds_send_acked_before(struct rds_connection *conn, u64 seq)
-{
-	struct rds_message *rm, *tmp;
-	int ret = 1;
-
-	spin_lock(&conn->c_lock);
-
-	list_for_each_entry_safe(rm, tmp, &conn->c_retrans, m_conn_item) {
-		if (be64_to_cpu(rm->m_inc.i_hdr.h_sequence) < seq)
-			ret = 0;
-		break;
-	}
-
-	list_for_each_entry_safe(rm, tmp, &conn->c_send_queue, m_conn_item) {
-		if (be64_to_cpu(rm->m_inc.i_hdr.h_sequence) < seq)
-			ret = 0;
-		break;
-	}
-
-	spin_unlock(&conn->c_lock);
-
-	return ret;
-}
-
-/*
  * This is pretty similar to what happens below in the ACK
  * handling code - except that we call here as soon as we get
  * the IB send completion on the RDMA op and the accompanying
@@ -413,15 +419,16 @@
 void rds_rdma_send_complete(struct rds_message *rm, int status)
 {
 	struct rds_sock *rs = NULL;
-	struct rds_rdma_op *ro;
+	struct rm_rdma_op *ro;
 	struct rds_notifier *notifier;
+	unsigned long flags;
 
-	spin_lock(&rm->m_rs_lock);
+	spin_lock_irqsave(&rm->m_rs_lock, flags);
 
-	ro = rm->m_rdma_op;
+	ro = &rm->rdma;
 	if (test_bit(RDS_MSG_ON_SOCK, &rm->m_flags) &&
-	    ro && ro->r_notify && ro->r_notifier) {
-		notifier = ro->r_notifier;
+	    ro->op_active && ro->op_notify && ro->op_notifier) {
+		notifier = ro->op_notifier;
 		rs = rm->m_rs;
 		sock_hold(rds_rs_to_sk(rs));
 
@@ -430,10 +437,10 @@
 		list_add_tail(&notifier->n_list, &rs->rs_notify_queue);
 		spin_unlock(&rs->rs_lock);
 
-		ro->r_notifier = NULL;
+		ro->op_notifier = NULL;
 	}
 
-	spin_unlock(&rm->m_rs_lock);
+	spin_unlock_irqrestore(&rm->m_rs_lock, flags);
 
 	if (rs) {
 		rds_wake_sk_sleep(rs);
@@ -443,20 +450,64 @@
 EXPORT_SYMBOL_GPL(rds_rdma_send_complete);
 
 /*
+ * Just like above, except looks at atomic op
+ */
+void rds_atomic_send_complete(struct rds_message *rm, int status)
+{
+	struct rds_sock *rs = NULL;
+	struct rm_atomic_op *ao;
+	struct rds_notifier *notifier;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rm->m_rs_lock, flags);
+
+	ao = &rm->atomic;
+	if (test_bit(RDS_MSG_ON_SOCK, &rm->m_flags)
+	    && ao->op_active && ao->op_notify && ao->op_notifier) {
+		notifier = ao->op_notifier;
+		rs = rm->m_rs;
+		sock_hold(rds_rs_to_sk(rs));
+
+		notifier->n_status = status;
+		spin_lock(&rs->rs_lock);
+		list_add_tail(&notifier->n_list, &rs->rs_notify_queue);
+		spin_unlock(&rs->rs_lock);
+
+		ao->op_notifier = NULL;
+	}
+
+	spin_unlock_irqrestore(&rm->m_rs_lock, flags);
+
+	if (rs) {
+		rds_wake_sk_sleep(rs);
+		sock_put(rds_rs_to_sk(rs));
+	}
+}
+EXPORT_SYMBOL_GPL(rds_atomic_send_complete);
+
+/*
  * This is the same as rds_rdma_send_complete except we
  * don't do any locking - we have all the ingredients (message,
  * socket, socket lock) and can just move the notifier.
  */
 static inline void
-__rds_rdma_send_complete(struct rds_sock *rs, struct rds_message *rm, int status)
+__rds_send_complete(struct rds_sock *rs, struct rds_message *rm, int status)
 {
-	struct rds_rdma_op *ro;
+	struct rm_rdma_op *ro;
+	struct rm_atomic_op *ao;
 
-	ro = rm->m_rdma_op;
-	if (ro && ro->r_notify && ro->r_notifier) {
-		ro->r_notifier->n_status = status;
-		list_add_tail(&ro->r_notifier->n_list, &rs->rs_notify_queue);
-		ro->r_notifier = NULL;
+	ro = &rm->rdma;
+	if (ro->op_active && ro->op_notify && ro->op_notifier) {
+		ro->op_notifier->n_status = status;
+		list_add_tail(&ro->op_notifier->n_list, &rs->rs_notify_queue);
+		ro->op_notifier = NULL;
+	}
+
+	ao = &rm->atomic;
+	if (ao->op_active && ao->op_notify && ao->op_notifier) {
+		ao->op_notifier->n_status = status;
+		list_add_tail(&ao->op_notifier->n_list, &rs->rs_notify_queue);
+		ao->op_notifier = NULL;
 	}
 
 	/* No need to wake the app - caller does this */
@@ -468,7 +519,7 @@
  * So speed is not an issue here.
  */
 struct rds_message *rds_send_get_message(struct rds_connection *conn,
-					 struct rds_rdma_op *op)
+					 struct rm_rdma_op *op)
 {
 	struct rds_message *rm, *tmp, *found = NULL;
 	unsigned long flags;
@@ -476,7 +527,7 @@
 	spin_lock_irqsave(&conn->c_lock, flags);
 
 	list_for_each_entry_safe(rm, tmp, &conn->c_retrans, m_conn_item) {
-		if (rm->m_rdma_op == op) {
+		if (&rm->rdma == op) {
 			atomic_inc(&rm->m_refcount);
 			found = rm;
 			goto out;
@@ -484,7 +535,7 @@
 	}
 
 	list_for_each_entry_safe(rm, tmp, &conn->c_send_queue, m_conn_item) {
-		if (rm->m_rdma_op == op) {
+		if (&rm->rdma == op) {
 			atomic_inc(&rm->m_refcount);
 			found = rm;
 			break;
@@ -506,7 +557,7 @@
  * removing the messages from the 'messages' list regardless of if it found
  * the messages on the socket list or not.
  */
-void rds_send_remove_from_sock(struct list_head *messages, int status)
+static void rds_send_remove_from_sock(struct list_head *messages, int status)
 {
 	unsigned long flags;
 	struct rds_sock *rs = NULL;
@@ -544,19 +595,20 @@
 		spin_lock(&rs->rs_lock);
 
 		if (test_and_clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) {
-			struct rds_rdma_op *ro = rm->m_rdma_op;
+			struct rm_rdma_op *ro = &rm->rdma;
 			struct rds_notifier *notifier;
 
 			list_del_init(&rm->m_sock_item);
 			rds_send_sndbuf_remove(rs, rm);
 
-			if (ro && ro->r_notifier && (status || ro->r_notify)) {
-				notifier = ro->r_notifier;
+			if (ro->op_active && ro->op_notifier &&
+			       (ro->op_notify || (ro->op_recverr && status))) {
+				notifier = ro->op_notifier;
 				list_add_tail(&notifier->n_list,
 						&rs->rs_notify_queue);
 				if (!notifier->n_status)
 					notifier->n_status = status;
-				rm->m_rdma_op->r_notifier = NULL;
+				rm->rdma.op_notifier = NULL;
 			}
 			was_on_sock = 1;
 			rm->m_rs = NULL;
@@ -619,9 +671,8 @@
 {
 	struct rds_message *rm, *tmp;
 	struct rds_connection *conn;
-	unsigned long flags, flags2;
+	unsigned long flags;
 	LIST_HEAD(list);
-	int wake = 0;
 
 	/* get all the messages we're dropping under the rs lock */
 	spin_lock_irqsave(&rs->rs_lock, flags);
@@ -631,59 +682,54 @@
 			     dest->sin_port != rm->m_inc.i_hdr.h_dport))
 			continue;
 
-		wake = 1;
 		list_move(&rm->m_sock_item, &list);
 		rds_send_sndbuf_remove(rs, rm);
 		clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags);
 	}
 
 	/* order flag updates with the rs lock */
-	if (wake)
-		smp_mb__after_clear_bit();
+	smp_mb__after_clear_bit();
 
 	spin_unlock_irqrestore(&rs->rs_lock, flags);
 
-	conn = NULL;
+	if (list_empty(&list))
+		return;
 
-	/* now remove the messages from the conn list as needed */
+	/* Remove the messages from the conn */
 	list_for_each_entry(rm, &list, m_sock_item) {
-		/* We do this here rather than in the loop above, so that
-		 * we don't have to nest m_rs_lock under rs->rs_lock */
-		spin_lock_irqsave(&rm->m_rs_lock, flags2);
-		/* If this is a RDMA operation, notify the app. */
-		spin_lock(&rs->rs_lock);
-		__rds_rdma_send_complete(rs, rm, RDS_RDMA_CANCELED);
-		spin_unlock(&rs->rs_lock);
-		rm->m_rs = NULL;
-		spin_unlock_irqrestore(&rm->m_rs_lock, flags2);
 
+		conn = rm->m_inc.i_conn;
+
+		spin_lock_irqsave(&conn->c_lock, flags);
 		/*
-		 * If we see this flag cleared then we're *sure* that someone
-		 * else beat us to removing it from the conn.  If we race
-		 * with their flag update we'll get the lock and then really
-		 * see that the flag has been cleared.
+		 * Maybe someone else beat us to removing rm from the conn.
+		 * If we race with their flag update we'll get the lock and
+		 * then really see that the flag has been cleared.
 		 */
-		if (!test_bit(RDS_MSG_ON_CONN, &rm->m_flags))
+		if (!test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags)) {
+			spin_unlock_irqrestore(&conn->c_lock, flags);
 			continue;
-
-		if (conn != rm->m_inc.i_conn) {
-			if (conn)
-				spin_unlock_irqrestore(&conn->c_lock, flags);
-			conn = rm->m_inc.i_conn;
-			spin_lock_irqsave(&conn->c_lock, flags);
 		}
-
-		if (test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags)) {
-			list_del_init(&rm->m_conn_item);
-			rds_message_put(rm);
-		}
-	}
-
-	if (conn)
+		list_del_init(&rm->m_conn_item);
 		spin_unlock_irqrestore(&conn->c_lock, flags);
 
-	if (wake)
-		rds_wake_sk_sleep(rs);
+		/*
+		 * Couldn't grab m_rs_lock in top loop (lock ordering),
+		 * but we can now.
+		 */
+		spin_lock_irqsave(&rm->m_rs_lock, flags);
+
+		spin_lock(&rs->rs_lock);
+		__rds_send_complete(rs, rm, RDS_RDMA_CANCELED);
+		spin_unlock(&rs->rs_lock);
+
+		rm->m_rs = NULL;
+		spin_unlock_irqrestore(&rm->m_rs_lock, flags);
+
+		rds_message_put(rm);
+	}
+
+	rds_wake_sk_sleep(rs);
 
 	while (!list_empty(&list)) {
 		rm = list_entry(list.next, struct rds_message, m_sock_item);
@@ -763,6 +809,63 @@
 	return *queued;
 }
 
+/*
+ * rds_message is getting to be quite complicated, and we'd like to allocate
+ * it all in one go. This figures out how big it needs to be up front.
+ */
+static int rds_rm_size(struct msghdr *msg, int data_len)
+{
+	struct cmsghdr *cmsg;
+	int size = 0;
+	int cmsg_groups = 0;
+	int retval;
+
+	for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+		if (!CMSG_OK(msg, cmsg))
+			return -EINVAL;
+
+		if (cmsg->cmsg_level != SOL_RDS)
+			continue;
+
+		switch (cmsg->cmsg_type) {
+		case RDS_CMSG_RDMA_ARGS:
+			cmsg_groups |= 1;
+			retval = rds_rdma_extra_size(CMSG_DATA(cmsg));
+			if (retval < 0)
+				return retval;
+			size += retval;
+
+			break;
+
+		case RDS_CMSG_RDMA_DEST:
+		case RDS_CMSG_RDMA_MAP:
+			cmsg_groups |= 2;
+			/* these are valid but do no add any size */
+			break;
+
+		case RDS_CMSG_ATOMIC_CSWP:
+		case RDS_CMSG_ATOMIC_FADD:
+		case RDS_CMSG_MASKED_ATOMIC_CSWP:
+		case RDS_CMSG_MASKED_ATOMIC_FADD:
+			cmsg_groups |= 1;
+			size += sizeof(struct scatterlist);
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+	}
+
+	size += ceil(data_len, PAGE_SIZE) * sizeof(struct scatterlist);
+
+	/* Ensure (DEST, MAP) are never used with (ARGS, ATOMIC) */
+	if (cmsg_groups == 3)
+		return -EINVAL;
+
+	return size;
+}
+
 static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm,
 			 struct msghdr *msg, int *allocated_mr)
 {
@@ -777,7 +880,7 @@
 			continue;
 
 		/* As a side effect, RDMA_DEST and RDMA_MAP will set
-		 * rm->m_rdma_cookie and rm->m_rdma_mr.
+		 * rm->rdma.m_rdma_cookie and rm->rdma.m_rdma_mr.
 		 */
 		switch (cmsg->cmsg_type) {
 		case RDS_CMSG_RDMA_ARGS:
@@ -793,6 +896,12 @@
 			if (!ret)
 				*allocated_mr = 1;
 			break;
+		case RDS_CMSG_ATOMIC_CSWP:
+		case RDS_CMSG_ATOMIC_FADD:
+		case RDS_CMSG_MASKED_ATOMIC_CSWP:
+		case RDS_CMSG_MASKED_ATOMIC_FADD:
+			ret = rds_cmsg_atomic(rs, rm, cmsg);
+			break;
 
 		default:
 			return -EINVAL;
@@ -850,13 +959,26 @@
 		goto out;
 	}
 
-	rm = rds_message_copy_from_user(msg->msg_iov, payload_len);
-	if (IS_ERR(rm)) {
-		ret = PTR_ERR(rm);
-		rm = NULL;
+	/* size of rm including all sgs */
+	ret = rds_rm_size(msg, payload_len);
+	if (ret < 0)
+		goto out;
+
+	rm = rds_message_alloc(ret, GFP_KERNEL);
+	if (!rm) {
+		ret = -ENOMEM;
 		goto out;
 	}
 
+	/* Attach data to the rm */
+	if (payload_len) {
+		rm->data.op_sg = rds_message_alloc_sgs(rm, ceil(payload_len, PAGE_SIZE));
+		ret = rds_message_copy_from_user(rm, msg->msg_iov, payload_len);
+		if (ret)
+			goto out;
+	}
+	rm->data.op_active = 1;
+
 	rm->m_daddr = daddr;
 
 	/* rds_conn_create has a spinlock that runs with IRQ off.
@@ -879,22 +1001,23 @@
 	if (ret)
 		goto out;
 
-	if ((rm->m_rdma_cookie || rm->m_rdma_op) &&
-	    conn->c_trans->xmit_rdma == NULL) {
+	if (rm->rdma.op_active && !conn->c_trans->xmit_rdma) {
 		if (printk_ratelimit())
 			printk(KERN_NOTICE "rdma_op %p conn xmit_rdma %p\n",
-				rm->m_rdma_op, conn->c_trans->xmit_rdma);
+			       &rm->rdma, conn->c_trans->xmit_rdma);
 		ret = -EOPNOTSUPP;
 		goto out;
 	}
 
-	/* If the connection is down, trigger a connect. We may
-	 * have scheduled a delayed reconnect however - in this case
-	 * we should not interfere.
-	 */
-	if (rds_conn_state(conn) == RDS_CONN_DOWN &&
-	    !test_and_set_bit(RDS_RECONNECT_PENDING, &conn->c_flags))
-		queue_delayed_work(rds_wq, &conn->c_conn_w, 0);
+	if (rm->atomic.op_active && !conn->c_trans->xmit_atomic) {
+		if (printk_ratelimit())
+			printk(KERN_NOTICE "atomic_op %p conn xmit_atomic %p\n",
+			       &rm->atomic, conn->c_trans->xmit_atomic);
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	rds_conn_connect_if_down(conn);
 
 	ret = rds_cong_wait(conn->c_fcong, dport, nonblock, rs);
 	if (ret) {
@@ -938,7 +1061,7 @@
 	rds_stats_inc(s_send_queued);
 
 	if (!test_bit(RDS_LL_SEND_FULL, &conn->c_flags))
-		rds_send_worker(&conn->c_send_w.work);
+		rds_send_xmit(conn);
 
 	rds_message_put(rm);
 	return payload_len;
@@ -966,20 +1089,15 @@
 	int ret = 0;
 
 	rm = rds_message_alloc(0, GFP_ATOMIC);
-	if (rm == NULL) {
+	if (!rm) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	rm->m_daddr = conn->c_faddr;
+	rm->data.op_active = 1;
 
-	/* If the connection is down, trigger a connect. We may
-	 * have scheduled a delayed reconnect however - in this case
-	 * we should not interfere.
-	 */
-	if (rds_conn_state(conn) == RDS_CONN_DOWN &&
-	    !test_and_set_bit(RDS_RECONNECT_PENDING, &conn->c_flags))
-		queue_delayed_work(rds_wq, &conn->c_conn_w, 0);
+	rds_conn_connect_if_down(conn);
 
 	ret = rds_cong_wait(conn->c_fcong, dport, 1, NULL);
 	if (ret)
@@ -999,7 +1117,9 @@
 	rds_stats_inc(s_send_queued);
 	rds_stats_inc(s_send_pong);
 
-	queue_delayed_work(rds_wq, &conn->c_send_w, 0);
+	if (!test_bit(RDS_LL_SEND_FULL, &conn->c_flags))
+		rds_send_xmit(conn);
+
 	rds_message_put(rm);
 	return 0;
 
diff --git a/net/rds/stats.c b/net/rds/stats.c
index 7598eb0..10c759c 100644
--- a/net/rds/stats.c
+++ b/net/rds/stats.c
@@ -57,8 +57,8 @@
 	"recv_ping",
 	"send_queue_empty",
 	"send_queue_full",
-	"send_sem_contention",
-	"send_sem_queue_raced",
+	"send_lock_contention",
+	"send_lock_queue_raced",
 	"send_immediate_retry",
 	"send_delayed_retry",
 	"send_drop_acked",
@@ -143,7 +143,7 @@
 	rds_info_deregister_func(RDS_INFO_COUNTERS, rds_stats_info);
 }
 
-int __init rds_stats_init(void)
+int rds_stats_init(void)
 {
 	rds_info_register_func(RDS_INFO_COUNTERS, rds_stats_info);
 	return 0;
diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c
index 7829a20..25ad0c7 100644
--- a/net/rds/sysctl.c
+++ b/net/rds/sysctl.c
@@ -105,13 +105,13 @@
 		unregister_sysctl_table(rds_sysctl_reg_table);
 }
 
-int __init rds_sysctl_init(void)
+int rds_sysctl_init(void)
 {
 	rds_sysctl_reconnect_min = msecs_to_jiffies(1);
 	rds_sysctl_reconnect_min_jiffies = rds_sysctl_reconnect_min;
 
 	rds_sysctl_reg_table = register_sysctl_paths(rds_sysctl_path, rds_sysctl_rds_table);
-	if (rds_sysctl_reg_table == NULL)
+	if (!rds_sysctl_reg_table)
 		return -ENOMEM;
 	return 0;
 }
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index babf457..08a8c6c 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -41,7 +41,7 @@
 /* only for info exporting */
 static DEFINE_SPINLOCK(rds_tcp_tc_list_lock);
 static LIST_HEAD(rds_tcp_tc_list);
-unsigned int rds_tcp_tc_count;
+static unsigned int rds_tcp_tc_count;
 
 /* Track rds_tcp_connection structs so they can be cleaned up */
 static DEFINE_SPINLOCK(rds_tcp_conn_lock);
@@ -200,7 +200,7 @@
 	struct rds_tcp_connection *tc;
 
 	tc = kmem_cache_alloc(rds_tcp_conn_slab, gfp);
-	if (tc == NULL)
+	if (!tc)
 		return -ENOMEM;
 
 	tc->t_sock = NULL;
@@ -243,7 +243,7 @@
 	}
 }
 
-void rds_tcp_exit(void)
+static void rds_tcp_exit(void)
 {
 	rds_info_deregister_func(RDS_INFO_TCP_SOCKETS, rds_tcp_tc_info);
 	rds_tcp_listen_stop();
@@ -258,7 +258,6 @@
 	.laddr_check		= rds_tcp_laddr_check,
 	.xmit_prepare		= rds_tcp_xmit_prepare,
 	.xmit_complete		= rds_tcp_xmit_complete,
-	.xmit_cong_map		= rds_tcp_xmit_cong_map,
 	.xmit			= rds_tcp_xmit,
 	.recv			= rds_tcp_recv,
 	.conn_alloc		= rds_tcp_conn_alloc,
@@ -266,7 +265,6 @@
 	.conn_connect		= rds_tcp_conn_connect,
 	.conn_shutdown		= rds_tcp_conn_shutdown,
 	.inc_copy_to_user	= rds_tcp_inc_copy_to_user,
-	.inc_purge		= rds_tcp_inc_purge,
 	.inc_free		= rds_tcp_inc_free,
 	.stats_info_copy	= rds_tcp_stats_info_copy,
 	.exit			= rds_tcp_exit,
@@ -276,14 +274,14 @@
 	.t_prefer_loopback	= 1,
 };
 
-int __init rds_tcp_init(void)
+static int rds_tcp_init(void)
 {
 	int ret;
 
 	rds_tcp_conn_slab = kmem_cache_create("rds_tcp_connection",
 					      sizeof(struct rds_tcp_connection),
 					      0, 0, NULL);
-	if (rds_tcp_conn_slab == NULL) {
+	if (!rds_tcp_conn_slab) {
 		ret = -ENOMEM;
 		goto out;
 	}
diff --git a/net/rds/tcp.h b/net/rds/tcp.h
index 844fa6b..9cf2927 100644
--- a/net/rds/tcp.h
+++ b/net/rds/tcp.h
@@ -43,8 +43,6 @@
 };
 
 /* tcp.c */
-int __init rds_tcp_init(void);
-void rds_tcp_exit(void);
 void rds_tcp_tune(struct socket *sock);
 void rds_tcp_nonagle(struct socket *sock);
 void rds_tcp_set_callbacks(struct socket *sock, struct rds_connection *conn);
@@ -61,16 +59,15 @@
 void rds_tcp_state_change(struct sock *sk);
 
 /* tcp_listen.c */
-int __init rds_tcp_listen_init(void);
+int rds_tcp_listen_init(void);
 void rds_tcp_listen_stop(void);
 void rds_tcp_listen_data_ready(struct sock *sk, int bytes);
 
 /* tcp_recv.c */
-int __init rds_tcp_recv_init(void);
+int rds_tcp_recv_init(void);
 void rds_tcp_recv_exit(void);
 void rds_tcp_data_ready(struct sock *sk, int bytes);
 int rds_tcp_recv(struct rds_connection *conn);
-void rds_tcp_inc_purge(struct rds_incoming *inc);
 void rds_tcp_inc_free(struct rds_incoming *inc);
 int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov,
 			     size_t size);
@@ -81,8 +78,6 @@
 int rds_tcp_xmit(struct rds_connection *conn, struct rds_message *rm,
 	         unsigned int hdr_off, unsigned int sg, unsigned int off);
 void rds_tcp_write_space(struct sock *sk);
-int rds_tcp_xmit_cong_map(struct rds_connection *conn,
-			  struct rds_cong_map *map, unsigned long offset);
 
 /* tcp_stats.c */
 DECLARE_PER_CPU(struct rds_tcp_statistics, rds_tcp_stats);
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c
index c397524..af95c8e 100644
--- a/net/rds/tcp_connect.c
+++ b/net/rds/tcp_connect.c
@@ -43,9 +43,9 @@
 	struct rds_connection *conn;
 	struct rds_tcp_connection *tc;
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	conn = sk->sk_user_data;
-	if (conn == NULL) {
+	if (!conn) {
 		state_change = sk->sk_state_change;
 		goto out;
 	}
@@ -68,7 +68,7 @@
 			break;
 	}
 out:
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 	state_change(sk);
 }
 
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c
index 975183f..8b5cc4a 100644
--- a/net/rds/tcp_listen.c
+++ b/net/rds/tcp_listen.c
@@ -114,9 +114,9 @@
 
 	rdsdebug("listen data ready sk %p\n", sk);
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	ready = sk->sk_user_data;
-	if (ready == NULL) { /* check for teardown race */
+	if (!ready) { /* check for teardown race */
 		ready = sk->sk_data_ready;
 		goto out;
 	}
@@ -131,11 +131,11 @@
 		queue_work(rds_wq, &rds_tcp_listen_work);
 
 out:
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 	ready(sk, bytes);
 }
 
-int __init rds_tcp_listen_init(void)
+int rds_tcp_listen_init(void)
 {
 	struct sockaddr_in sin;
 	struct socket *sock = NULL;
@@ -178,7 +178,7 @@
 	struct socket *sock = rds_tcp_listen_sock;
 	struct sock *sk;
 
-	if (sock == NULL)
+	if (!sock)
 		return;
 
 	sk = sock->sk;
diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c
index 1aba687..78205e2 100644
--- a/net/rds/tcp_recv.c
+++ b/net/rds/tcp_recv.c
@@ -39,7 +39,7 @@
 
 static struct kmem_cache *rds_tcp_incoming_slab;
 
-void rds_tcp_inc_purge(struct rds_incoming *inc)
+static void rds_tcp_inc_purge(struct rds_incoming *inc)
 {
 	struct rds_tcp_incoming *tinc;
 	tinc = container_of(inc, struct rds_tcp_incoming, ti_inc);
@@ -190,10 +190,10 @@
 	 * processing.
 	 */
 	while (left) {
-		if (tinc == NULL) {
+		if (!tinc) {
 			tinc = kmem_cache_alloc(rds_tcp_incoming_slab,
 					        arg->gfp);
-			if (tinc == NULL) {
+			if (!tinc) {
 				desc->error = -ENOMEM;
 				goto out;
 			}
@@ -229,7 +229,7 @@
 
 		if (left && tc->t_tinc_data_rem) {
 			clone = skb_clone(skb, arg->gfp);
-			if (clone == NULL) {
+			if (!clone) {
 				desc->error = -ENOMEM;
 				goto out;
 			}
@@ -272,7 +272,8 @@
 }
 
 /* the caller has to hold the sock lock */
-int rds_tcp_read_sock(struct rds_connection *conn, gfp_t gfp, enum km_type km)
+static int rds_tcp_read_sock(struct rds_connection *conn, gfp_t gfp,
+			     enum km_type km)
 {
 	struct rds_tcp_connection *tc = conn->c_transport_data;
 	struct socket *sock = tc->t_sock;
@@ -324,9 +325,9 @@
 
 	rdsdebug("data ready sk %p bytes %d\n", sk, bytes);
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	conn = sk->sk_user_data;
-	if (conn == NULL) { /* check for teardown race */
+	if (!conn) { /* check for teardown race */
 		ready = sk->sk_data_ready;
 		goto out;
 	}
@@ -338,16 +339,16 @@
 	if (rds_tcp_read_sock(conn, GFP_ATOMIC, KM_SOFTIRQ0) == -ENOMEM)
 		queue_delayed_work(rds_wq, &conn->c_recv_w, 0);
 out:
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 	ready(sk, bytes);
 }
 
-int __init rds_tcp_recv_init(void)
+int rds_tcp_recv_init(void)
 {
 	rds_tcp_incoming_slab = kmem_cache_create("rds_tcp_incoming",
 					sizeof(struct rds_tcp_incoming),
 					0, 0, NULL);
-	if (rds_tcp_incoming_slab == NULL)
+	if (!rds_tcp_incoming_slab)
 		return -ENOMEM;
 	return 0;
 }
diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c
index a28b895..1b4fd68 100644
--- a/net/rds/tcp_send.c
+++ b/net/rds/tcp_send.c
@@ -63,7 +63,7 @@
 }
 
 /* the core send_sem serializes this with other xmit and shutdown */
-int rds_tcp_sendmsg(struct socket *sock, void *data, unsigned int len)
+static int rds_tcp_sendmsg(struct socket *sock, void *data, unsigned int len)
 {
 	struct kvec vec = {
                 .iov_base = data,
@@ -77,56 +77,6 @@
 }
 
 /* the core send_sem serializes this with other xmit and shutdown */
-int rds_tcp_xmit_cong_map(struct rds_connection *conn,
-			  struct rds_cong_map *map, unsigned long offset)
-{
-	static struct rds_header rds_tcp_map_header = {
-		.h_flags = RDS_FLAG_CONG_BITMAP,
-	};
-	struct rds_tcp_connection *tc = conn->c_transport_data;
-	unsigned long i;
-	int ret;
-	int copied = 0;
-
-	/* Some problem claims cpu_to_be32(constant) isn't a constant. */
-	rds_tcp_map_header.h_len = cpu_to_be32(RDS_CONG_MAP_BYTES);
-
-	if (offset < sizeof(struct rds_header)) {
-		ret = rds_tcp_sendmsg(tc->t_sock,
-				      (void *)&rds_tcp_map_header + offset,
-				      sizeof(struct rds_header) - offset);
-		if (ret <= 0)
-			return ret;
-		offset += ret;
-		copied = ret;
-		if (offset < sizeof(struct rds_header))
-			return ret;
-	}
-
-	offset -= sizeof(struct rds_header);
-	i = offset / PAGE_SIZE;
-	offset = offset % PAGE_SIZE;
-	BUG_ON(i >= RDS_CONG_MAP_PAGES);
-
-	do {
-		ret = tc->t_sock->ops->sendpage(tc->t_sock,
-					virt_to_page(map->m_page_addrs[i]),
-					offset, PAGE_SIZE - offset,
-					MSG_DONTWAIT);
-		if (ret <= 0)
-			break;
-		copied += ret;
-		offset += ret;
-		if (offset == PAGE_SIZE) {
-			offset = 0;
-			i++;
-		}
-	} while (i < RDS_CONG_MAP_PAGES);
-
-        return copied ? copied : ret;
-}
-
-/* the core send_sem serializes this with other xmit and shutdown */
 int rds_tcp_xmit(struct rds_connection *conn, struct rds_message *rm,
 	         unsigned int hdr_off, unsigned int sg, unsigned int off)
 {
@@ -166,21 +116,21 @@
 			goto out;
 	}
 
-	while (sg < rm->m_nents) {
+	while (sg < rm->data.op_nents) {
 		ret = tc->t_sock->ops->sendpage(tc->t_sock,
-						sg_page(&rm->m_sg[sg]),
-						rm->m_sg[sg].offset + off,
-						rm->m_sg[sg].length - off,
+						sg_page(&rm->data.op_sg[sg]),
+						rm->data.op_sg[sg].offset + off,
+						rm->data.op_sg[sg].length - off,
 						MSG_DONTWAIT|MSG_NOSIGNAL);
-		rdsdebug("tcp sendpage %p:%u:%u ret %d\n", (void *)sg_page(&rm->m_sg[sg]),
-			 rm->m_sg[sg].offset + off, rm->m_sg[sg].length - off,
+		rdsdebug("tcp sendpage %p:%u:%u ret %d\n", (void *)sg_page(&rm->data.op_sg[sg]),
+			 rm->data.op_sg[sg].offset + off, rm->data.op_sg[sg].length - off,
 			 ret);
 		if (ret <= 0)
 			break;
 
 		off += ret;
 		done += ret;
-		if (off == rm->m_sg[sg].length) {
+		if (off == rm->data.op_sg[sg].length) {
 			off = 0;
 			sg++;
 		}
@@ -224,9 +174,9 @@
 	struct rds_connection *conn;
 	struct rds_tcp_connection *tc;
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	conn = sk->sk_user_data;
-	if (conn == NULL) {
+	if (!conn) {
 		write_space = sk->sk_write_space;
 		goto out;
 	}
@@ -244,7 +194,7 @@
 		queue_delayed_work(rds_wq, &conn->c_send_w, 0);
 
 out:
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 
 	/*
 	 * write_space is only called when data leaves tcp's send queue if
diff --git a/net/rds/threads.c b/net/rds/threads.c
index 786c20e..0fd90f8 100644
--- a/net/rds/threads.c
+++ b/net/rds/threads.c
@@ -61,7 +61,7 @@
  *
  * Transition to state DISCONNECTING/DOWN:
  *  -	Inside the shutdown worker; synchronizes with xmit path
- *	through c_send_lock, and with connection management callbacks
+ *	through RDS_IN_XMIT, and with connection management callbacks
  *	via c_cm_lock.
  *
  *	For receive callbacks, we rely on the underlying transport
@@ -110,7 +110,7 @@
  * We should *always* start with a random backoff; otherwise a broken connection
  * will always take several iterations to be re-established.
  */
-static void rds_queue_reconnect(struct rds_connection *conn)
+void rds_queue_reconnect(struct rds_connection *conn)
 {
 	unsigned long rand;
 
@@ -156,58 +156,6 @@
 	}
 }
 
-void rds_shutdown_worker(struct work_struct *work)
-{
-	struct rds_connection *conn = container_of(work, struct rds_connection, c_down_w);
-
-	/* shut it down unless it's down already */
-	if (!rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_DOWN)) {
-		/*
-		 * Quiesce the connection mgmt handlers before we start tearing
-		 * things down. We don't hold the mutex for the entire
-		 * duration of the shutdown operation, else we may be
-		 * deadlocking with the CM handler. Instead, the CM event
-		 * handler is supposed to check for state DISCONNECTING
-		 */
-		mutex_lock(&conn->c_cm_lock);
-		if (!rds_conn_transition(conn, RDS_CONN_UP, RDS_CONN_DISCONNECTING) &&
-		    !rds_conn_transition(conn, RDS_CONN_ERROR, RDS_CONN_DISCONNECTING)) {
-			rds_conn_error(conn, "shutdown called in state %d\n",
-					atomic_read(&conn->c_state));
-			mutex_unlock(&conn->c_cm_lock);
-			return;
-		}
-		mutex_unlock(&conn->c_cm_lock);
-
-		mutex_lock(&conn->c_send_lock);
-		conn->c_trans->conn_shutdown(conn);
-		rds_conn_reset(conn);
-		mutex_unlock(&conn->c_send_lock);
-
-		if (!rds_conn_transition(conn, RDS_CONN_DISCONNECTING, RDS_CONN_DOWN)) {
-			/* This can happen - eg when we're in the middle of tearing
-			 * down the connection, and someone unloads the rds module.
-			 * Quite reproduceable with loopback connections.
-			 * Mostly harmless.
-			 */
-			rds_conn_error(conn,
-				"%s: failed to transition to state DOWN, "
-				"current state is %d\n",
-				__func__,
-				atomic_read(&conn->c_state));
-			return;
-		}
-	}
-
-	/* Then reconnect if it's still live.
-	 * The passive side of an IB loopback connection is never added
-	 * to the conn hash, so we never trigger a reconnect on this
-	 * conn - the reconnect is always triggered by the active peer. */
-	cancel_delayed_work(&conn->c_conn_w);
-	if (!hlist_unhashed(&conn->c_hash_node))
-		rds_queue_reconnect(conn);
-}
-
 void rds_send_worker(struct work_struct *work)
 {
 	struct rds_connection *conn = container_of(work, struct rds_connection, c_send_w.work);
@@ -252,15 +200,22 @@
 	}
 }
 
+void rds_shutdown_worker(struct work_struct *work)
+{
+	struct rds_connection *conn = container_of(work, struct rds_connection, c_down_w);
+
+	rds_conn_shutdown(conn);
+}
+
 void rds_threads_exit(void)
 {
 	destroy_workqueue(rds_wq);
 }
 
-int __init rds_threads_init(void)
+int rds_threads_init(void)
 {
-	rds_wq = create_workqueue("krdsd");
-	if (rds_wq == NULL)
+	rds_wq = create_singlethread_workqueue("krdsd");
+	if (!rds_wq)
 		return -ENOMEM;
 
 	return 0;
diff --git a/net/rds/transport.c b/net/rds/transport.c
index 7e10679..7f2ac4f 100644
--- a/net/rds/transport.c
+++ b/net/rds/transport.c
@@ -71,19 +71,28 @@
 }
 EXPORT_SYMBOL_GPL(rds_trans_unregister);
 
+void rds_trans_put(struct rds_transport *trans)
+{
+	if (trans && trans->t_owner)
+		module_put(trans->t_owner);
+}
+
 struct rds_transport *rds_trans_get_preferred(__be32 addr)
 {
 	struct rds_transport *ret = NULL;
-	int i;
+	struct rds_transport *trans;
+	unsigned int i;
 
 	if (IN_LOOPBACK(ntohl(addr)))
 		return &rds_loop_transport;
 
 	down_read(&rds_trans_sem);
-	for (i = 0; i < RDS_TRANS_COUNT; i++)
-	{
-		if (transports[i] && (transports[i]->laddr_check(addr) == 0)) {
-			ret = transports[i];
+	for (i = 0; i < RDS_TRANS_COUNT; i++) {
+		trans = transports[i];
+
+		if (trans && (trans->laddr_check(addr) == 0) &&
+		    (!trans->t_owner || try_module_get(trans->t_owner))) {
+			ret = trans;
 			break;
 		}
 	}
diff --git a/net/rds/xlist.h b/net/rds/xlist.h
new file mode 100644
index 0000000..e6b5190
--- /dev/null
+++ b/net/rds/xlist.h
@@ -0,0 +1,80 @@
+#ifndef _LINUX_XLIST_H
+#define _LINUX_XLIST_H
+
+#include <linux/stddef.h>
+#include <linux/poison.h>
+#include <linux/prefetch.h>
+#include <asm/system.h>
+
+struct xlist_head {
+	struct xlist_head *next;
+};
+
+static inline void INIT_XLIST_HEAD(struct xlist_head *list)
+{
+	list->next = NULL;
+}
+
+static inline int xlist_empty(struct xlist_head *head)
+{
+	return head->next == NULL;
+}
+
+static inline void xlist_add(struct xlist_head *new, struct xlist_head *tail,
+			     struct xlist_head *head)
+{
+	struct xlist_head *cur;
+	struct xlist_head *check;
+
+	while (1) {
+		cur = head->next;
+		tail->next = cur;
+		check = cmpxchg(&head->next, cur, new);
+		if (check == cur)
+			break;
+	}
+}
+
+static inline struct xlist_head *xlist_del_head(struct xlist_head *head)
+{
+	struct xlist_head *cur;
+	struct xlist_head *check;
+	struct xlist_head *next;
+
+	while (1) {
+		cur = head->next;
+		if (!cur)
+			goto out;
+
+		next = cur->next;
+		check = cmpxchg(&head->next, cur, next);
+		if (check == cur)
+			goto out;
+	}
+out:
+	return cur;
+}
+
+static inline struct xlist_head *xlist_del_head_fast(struct xlist_head *head)
+{
+	struct xlist_head *cur;
+
+	cur = head->next;
+	if (!cur)
+		return NULL;
+
+	head->next = cur->next;
+	return cur;
+}
+
+static inline void xlist_splice(struct xlist_head *list,
+				struct xlist_head *head)
+{
+	struct xlist_head *cur;
+
+	WARN_ON(head->next);
+	cur = xchg(&list->next, NULL);
+	head->next = cur;
+}
+
+#endif
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 51875a0..04f5990 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -1241,6 +1241,7 @@
 	.unlocked_ioctl	= rfkill_fop_ioctl,
 	.compat_ioctl	= rfkill_fop_ioctl,
 #endif
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice rfkill_miscdev = {
diff --git a/net/rfkill/input.c b/net/rfkill/input.c
index 3713d7e..1bca6d4 100644
--- a/net/rfkill/input.c
+++ b/net/rfkill/input.c
@@ -142,7 +142,7 @@
 static unsigned long rfkill_ratelimit(const unsigned long last)
 {
 	const unsigned long delay = msecs_to_jiffies(RFKILL_OPS_DELAY);
-	return (time_after(jiffies, last + delay)) ? 0 : delay;
+	return time_after(jiffies, last + delay) ? 0 : delay;
 }
 
 static void rfkill_schedule_ratelimited(void)
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 8e45e76..d952e7e 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -679,7 +679,7 @@
 	if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)
 		return -EINVAL;
 
-	if (addr->srose_ndigis > ROSE_MAX_DIGIS)
+	if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)
 		return -EINVAL;
 
 	if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) {
@@ -739,7 +739,7 @@
 	if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)
 		return -EINVAL;
 
-	if (addr->srose_ndigis > ROSE_MAX_DIGIS)
+	if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)
 		return -EINVAL;
 
 	/* Source + Destination digis should not exceed ROSE_MAX_DIGIS */
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
index a750a28..fa5f564 100644
--- a/net/rose/rose_link.c
+++ b/net/rose/rose_link.c
@@ -114,7 +114,7 @@
 	if (ax25s)
 		ax25_cb_put(ax25s);
 
-	return (neigh->ax25 != NULL);
+	return neigh->ax25 != NULL;
 }
 
 /*
@@ -137,7 +137,7 @@
 	if (ax25s)
 		ax25_cb_put(ax25s);
 
-	return (neigh->ax25 != NULL);
+	return neigh->ax25 != NULL;
 }
 
 /*
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 2f691fb..a36270a 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -518,6 +518,16 @@
 	  To compile this code as a module, choose M here: the
 	  module will be called act_skbedit.
 
+config NET_ACT_CSUM
+        tristate "Checksum Updating"
+        depends on NET_CLS_ACT && INET
+        ---help---
+	  Say Y here to update some common checksum after some direct
+	  packet alterations.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called act_csum.
+
 config NET_CLS_IND
 	bool "Incoming device classification"
 	depends on NET_CLS_U32 || NET_CLS_FW
diff --git a/net/sched/Makefile b/net/sched/Makefile
index f14e71b..960f5db 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_NET_ACT_PEDIT)	+= act_pedit.o
 obj-$(CONFIG_NET_ACT_SIMP)	+= act_simple.o
 obj-$(CONFIG_NET_ACT_SKBEDIT)	+= act_skbedit.o
+obj-$(CONFIG_NET_ACT_CSUM)	+= act_csum.o
 obj-$(CONFIG_NET_SCH_FIFO)	+= sch_fifo.o
 obj-$(CONFIG_NET_SCH_CBQ)	+= sch_cbq.o
 obj-$(CONFIG_NET_SCH_HTB)	+= sch_htb.o
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
new file mode 100644
index 0000000..67dc7ce
--- /dev/null
+++ b/net/sched/act_csum.c
@@ -0,0 +1,595 @@
+/*
+ * Checksum updating actions
+ *
+ * Copyright (c) 2010 Gregoire Baron <baronchon@n7mm.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+#include <linux/netlink.h>
+#include <net/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <linux/skbuff.h>
+
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/icmp.h>
+#include <linux/icmpv6.h>
+#include <linux/igmp.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/ip6_checksum.h>
+
+#include <net/act_api.h>
+
+#include <linux/tc_act/tc_csum.h>
+#include <net/tc_act/tc_csum.h>
+
+#define CSUM_TAB_MASK 15
+static struct tcf_common *tcf_csum_ht[CSUM_TAB_MASK + 1];
+static u32 csum_idx_gen;
+static DEFINE_RWLOCK(csum_lock);
+
+static struct tcf_hashinfo csum_hash_info = {
+	.htab	= tcf_csum_ht,
+	.hmask	= CSUM_TAB_MASK,
+	.lock	= &csum_lock,
+};
+
+static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = {
+	[TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), },
+};
+
+static int tcf_csum_init(struct nlattr *nla, struct nlattr *est,
+			 struct tc_action *a, int ovr, int bind)
+{
+	struct nlattr *tb[TCA_CSUM_MAX + 1];
+	struct tc_csum *parm;
+	struct tcf_common *pc;
+	struct tcf_csum *p;
+	int ret = 0, err;
+
+	if (nla == NULL)
+		return -EINVAL;
+
+	err = nla_parse_nested(tb, TCA_CSUM_MAX, nla,csum_policy);
+	if (err < 0)
+		return err;
+
+	if (tb[TCA_CSUM_PARMS] == NULL)
+		return -EINVAL;
+	parm = nla_data(tb[TCA_CSUM_PARMS]);
+
+	pc = tcf_hash_check(parm->index, a, bind, &csum_hash_info);
+	if (!pc) {
+		pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind,
+				     &csum_idx_gen, &csum_hash_info);
+		if (IS_ERR(pc))
+			return PTR_ERR(pc);
+		p = to_tcf_csum(pc);
+		ret = ACT_P_CREATED;
+	} else {
+		p = to_tcf_csum(pc);
+		if (!ovr) {
+			tcf_hash_release(pc, bind, &csum_hash_info);
+			return -EEXIST;
+		}
+	}
+
+	spin_lock_bh(&p->tcf_lock);
+	p->tcf_action = parm->action;
+	p->update_flags = parm->update_flags;
+	spin_unlock_bh(&p->tcf_lock);
+
+	if (ret == ACT_P_CREATED)
+		tcf_hash_insert(pc, &csum_hash_info);
+
+	return ret;
+}
+
+static int tcf_csum_cleanup(struct tc_action *a, int bind)
+{
+	struct tcf_csum *p = a->priv;
+	return tcf_hash_release(&p->common, bind, &csum_hash_info);
+}
+
+/**
+ * tcf_csum_skb_nextlayer - Get next layer pointer
+ * @skb: sk_buff to use
+ * @ihl: previous summed headers length
+ * @ipl: complete packet length
+ * @jhl: next header length
+ *
+ * Check the expected next layer availability in the specified sk_buff.
+ * Return the next layer pointer if pass, NULL otherwise.
+ */
+static void *tcf_csum_skb_nextlayer(struct sk_buff *skb,
+				    unsigned int ihl, unsigned int ipl,
+				    unsigned int jhl)
+{
+	int ntkoff = skb_network_offset(skb);
+	int hl = ihl + jhl;
+
+	if (!pskb_may_pull(skb, ipl + ntkoff) || (ipl < hl) ||
+	    (skb_cloned(skb) &&
+	     !skb_clone_writable(skb, hl + ntkoff) &&
+	     pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+		return NULL;
+	else
+		return (void *)(skb_network_header(skb) + ihl);
+}
+
+static int tcf_csum_ipv4_icmp(struct sk_buff *skb,
+			      unsigned int ihl, unsigned int ipl)
+{
+	struct icmphdr *icmph;
+
+	icmph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*icmph));
+	if (icmph == NULL)
+		return 0;
+
+	icmph->checksum = 0;
+	skb->csum = csum_partial(icmph, ipl - ihl, 0);
+	icmph->checksum = csum_fold(skb->csum);
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+	return 1;
+}
+
+static int tcf_csum_ipv4_igmp(struct sk_buff *skb,
+			      unsigned int ihl, unsigned int ipl)
+{
+	struct igmphdr *igmph;
+
+	igmph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*igmph));
+	if (igmph == NULL)
+		return 0;
+
+	igmph->csum = 0;
+	skb->csum = csum_partial(igmph, ipl - ihl, 0);
+	igmph->csum = csum_fold(skb->csum);
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+	return 1;
+}
+
+static int tcf_csum_ipv6_icmp(struct sk_buff *skb, struct ipv6hdr *ip6h,
+			      unsigned int ihl, unsigned int ipl)
+{
+	struct icmp6hdr *icmp6h;
+
+	icmp6h = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*icmp6h));
+	if (icmp6h == NULL)
+		return 0;
+
+	icmp6h->icmp6_cksum = 0;
+	skb->csum = csum_partial(icmp6h, ipl - ihl, 0);
+	icmp6h->icmp6_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+					      ipl - ihl, IPPROTO_ICMPV6,
+					      skb->csum);
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+	return 1;
+}
+
+static int tcf_csum_ipv4_tcp(struct sk_buff *skb, struct iphdr *iph,
+			     unsigned int ihl, unsigned int ipl)
+{
+	struct tcphdr *tcph;
+
+	tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph));
+	if (tcph == NULL)
+		return 0;
+
+	tcph->check = 0;
+	skb->csum = csum_partial(tcph, ipl - ihl, 0);
+	tcph->check = tcp_v4_check(ipl - ihl,
+				   iph->saddr, iph->daddr, skb->csum);
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+	return 1;
+}
+
+static int tcf_csum_ipv6_tcp(struct sk_buff *skb, struct ipv6hdr *ip6h,
+			     unsigned int ihl, unsigned int ipl)
+{
+	struct tcphdr *tcph;
+
+	tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph));
+	if (tcph == NULL)
+		return 0;
+
+	tcph->check = 0;
+	skb->csum = csum_partial(tcph, ipl - ihl, 0);
+	tcph->check = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+				      ipl - ihl, IPPROTO_TCP,
+				      skb->csum);
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+	return 1;
+}
+
+static int tcf_csum_ipv4_udp(struct sk_buff *skb, struct iphdr *iph,
+			     unsigned int ihl, unsigned int ipl, int udplite)
+{
+	struct udphdr *udph;
+	u16 ul;
+
+	/*
+	 * Support both UDP and UDPLITE checksum algorithms, Don't use
+	 * udph->len to get the real length without any protocol check,
+	 * UDPLITE uses udph->len for another thing,
+	 * Use iph->tot_len, or just ipl.
+	 */
+
+	udph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*udph));
+	if (udph == NULL)
+		return 0;
+
+	ul = ntohs(udph->len);
+
+	if (udplite || udph->check) {
+
+		udph->check = 0;
+
+		if (udplite) {
+			if (ul == 0)
+				skb->csum = csum_partial(udph, ipl - ihl, 0);
+			else if ((ul >= sizeof(*udph)) && (ul <= ipl - ihl))
+				skb->csum = csum_partial(udph, ul, 0);
+			else
+				goto ignore_obscure_skb;
+		} else {
+			if (ul != ipl - ihl)
+				goto ignore_obscure_skb;
+
+			skb->csum = csum_partial(udph, ul, 0);
+		}
+
+		udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
+						ul, iph->protocol,
+						skb->csum);
+
+		if (!udph->check)
+			udph->check = CSUM_MANGLED_0;
+	}
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+ignore_obscure_skb:
+	return 1;
+}
+
+static int tcf_csum_ipv6_udp(struct sk_buff *skb, struct ipv6hdr *ip6h,
+			     unsigned int ihl, unsigned int ipl, int udplite)
+{
+	struct udphdr *udph;
+	u16 ul;
+
+	/*
+	 * Support both UDP and UDPLITE checksum algorithms, Don't use
+	 * udph->len to get the real length without any protocol check,
+	 * UDPLITE uses udph->len for another thing,
+	 * Use ip6h->payload_len + sizeof(*ip6h) ... , or just ipl.
+	 */
+
+	udph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*udph));
+	if (udph == NULL)
+		return 0;
+
+	ul = ntohs(udph->len);
+
+	udph->check = 0;
+
+	if (udplite) {
+		if (ul == 0)
+			skb->csum = csum_partial(udph, ipl - ihl, 0);
+
+		else if ((ul >= sizeof(*udph)) && (ul <= ipl - ihl))
+			skb->csum = csum_partial(udph, ul, 0);
+
+		else
+			goto ignore_obscure_skb;
+	} else {
+		if (ul != ipl - ihl)
+			goto ignore_obscure_skb;
+
+		skb->csum = csum_partial(udph, ul, 0);
+	}
+
+	udph->check = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, ul,
+				      udplite ? IPPROTO_UDPLITE : IPPROTO_UDP,
+				      skb->csum);
+
+	if (!udph->check)
+		udph->check = CSUM_MANGLED_0;
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+ignore_obscure_skb:
+	return 1;
+}
+
+static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags)
+{
+	struct iphdr *iph;
+	int ntkoff;
+
+	ntkoff = skb_network_offset(skb);
+
+	if (!pskb_may_pull(skb, sizeof(*iph) + ntkoff))
+		goto fail;
+
+	iph = ip_hdr(skb);
+
+	switch (iph->frag_off & htons(IP_OFFSET) ? 0 : iph->protocol) {
+	case IPPROTO_ICMP:
+		if (update_flags & TCA_CSUM_UPDATE_FLAG_ICMP)
+			if (!tcf_csum_ipv4_icmp(skb, iph->ihl * 4,
+						ntohs(iph->tot_len)))
+				goto fail;
+		break;
+	case IPPROTO_IGMP:
+		if (update_flags & TCA_CSUM_UPDATE_FLAG_IGMP)
+			if (!tcf_csum_ipv4_igmp(skb, iph->ihl * 4,
+						ntohs(iph->tot_len)))
+				goto fail;
+		break;
+	case IPPROTO_TCP:
+		if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP)
+			if (!tcf_csum_ipv4_tcp(skb, iph, iph->ihl * 4,
+					       ntohs(iph->tot_len)))
+				goto fail;
+		break;
+	case IPPROTO_UDP:
+		if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP)
+			if (!tcf_csum_ipv4_udp(skb, iph, iph->ihl * 4,
+					       ntohs(iph->tot_len), 0))
+				goto fail;
+		break;
+	case IPPROTO_UDPLITE:
+		if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE)
+			if (!tcf_csum_ipv4_udp(skb, iph, iph->ihl * 4,
+					       ntohs(iph->tot_len), 1))
+				goto fail;
+		break;
+	}
+
+	if (update_flags & TCA_CSUM_UPDATE_FLAG_IPV4HDR) {
+		if (skb_cloned(skb) &&
+		    !skb_clone_writable(skb, sizeof(*iph) + ntkoff) &&
+		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+			goto fail;
+
+		ip_send_check(iph);
+	}
+
+	return 1;
+
+fail:
+	return 0;
+}
+
+static int tcf_csum_ipv6_hopopts(struct ipv6_opt_hdr *ip6xh,
+				 unsigned int ixhl, unsigned int *pl)
+{
+	int off, len, optlen;
+	unsigned char *xh = (void *)ip6xh;
+
+	off = sizeof(*ip6xh);
+	len = ixhl - off;
+
+	while (len > 1) {
+		switch (xh[off]) {
+		case IPV6_TLV_PAD0:
+			optlen = 1;
+			break;
+		case IPV6_TLV_JUMBO:
+			optlen = xh[off + 1] + 2;
+			if (optlen != 6 || len < 6 || (off & 3) != 2)
+				/* wrong jumbo option length/alignment */
+				return 0;
+			*pl = ntohl(*(__be32 *)(xh + off + 2));
+			goto done;
+		default:
+			optlen = xh[off + 1] + 2;
+			if (optlen > len)
+				/* ignore obscure options */
+				goto done;
+			break;
+		}
+		off += optlen;
+		len -= optlen;
+	}
+
+done:
+	return 1;
+}
+
+static int tcf_csum_ipv6(struct sk_buff *skb, u32 update_flags)
+{
+	struct ipv6hdr *ip6h;
+	struct ipv6_opt_hdr *ip6xh;
+	unsigned int hl, ixhl;
+	unsigned int pl;
+	int ntkoff;
+	u8 nexthdr;
+
+	ntkoff = skb_network_offset(skb);
+
+	hl = sizeof(*ip6h);
+
+	if (!pskb_may_pull(skb, hl + ntkoff))
+		goto fail;
+
+	ip6h = ipv6_hdr(skb);
+
+	pl = ntohs(ip6h->payload_len);
+	nexthdr = ip6h->nexthdr;
+
+	do {
+		switch (nexthdr) {
+		case NEXTHDR_FRAGMENT:
+			goto ignore_skb;
+		case NEXTHDR_ROUTING:
+		case NEXTHDR_HOP:
+		case NEXTHDR_DEST:
+			if (!pskb_may_pull(skb, hl + sizeof(*ip6xh) + ntkoff))
+				goto fail;
+			ip6xh = (void *)(skb_network_header(skb) + hl);
+			ixhl = ipv6_optlen(ip6xh);
+			if (!pskb_may_pull(skb, hl + ixhl + ntkoff))
+				goto fail;
+			if ((nexthdr == NEXTHDR_HOP) &&
+			    !(tcf_csum_ipv6_hopopts(ip6xh, ixhl, &pl)))
+				goto fail;
+			nexthdr = ip6xh->nexthdr;
+			hl += ixhl;
+			break;
+		case IPPROTO_ICMPV6:
+			if (update_flags & TCA_CSUM_UPDATE_FLAG_ICMP)
+				if (!tcf_csum_ipv6_icmp(skb, ip6h,
+							hl, pl + sizeof(*ip6h)))
+					goto fail;
+			goto done;
+		case IPPROTO_TCP:
+			if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP)
+				if (!tcf_csum_ipv6_tcp(skb, ip6h,
+						       hl, pl + sizeof(*ip6h)))
+					goto fail;
+			goto done;
+		case IPPROTO_UDP:
+			if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP)
+				if (!tcf_csum_ipv6_udp(skb, ip6h, hl,
+						       pl + sizeof(*ip6h), 0))
+					goto fail;
+			goto done;
+		case IPPROTO_UDPLITE:
+			if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE)
+				if (!tcf_csum_ipv6_udp(skb, ip6h, hl,
+						       pl + sizeof(*ip6h), 1))
+					goto fail;
+			goto done;
+		default:
+			goto ignore_skb;
+		}
+	} while (pskb_may_pull(skb, hl + 1 + ntkoff));
+
+done:
+ignore_skb:
+	return 1;
+
+fail:
+	return 0;
+}
+
+static int tcf_csum(struct sk_buff *skb,
+		    struct tc_action *a, struct tcf_result *res)
+{
+	struct tcf_csum *p = a->priv;
+	int action;
+	u32 update_flags;
+
+	spin_lock(&p->tcf_lock);
+	p->tcf_tm.lastuse = jiffies;
+	p->tcf_bstats.bytes += qdisc_pkt_len(skb);
+	p->tcf_bstats.packets++;
+	action = p->tcf_action;
+	update_flags = p->update_flags;
+	spin_unlock(&p->tcf_lock);
+
+	if (unlikely(action == TC_ACT_SHOT))
+		goto drop;
+
+	switch (skb->protocol) {
+	case cpu_to_be16(ETH_P_IP):
+		if (!tcf_csum_ipv4(skb, update_flags))
+			goto drop;
+		break;
+	case cpu_to_be16(ETH_P_IPV6):
+		if (!tcf_csum_ipv6(skb, update_flags))
+			goto drop;
+		break;
+	}
+
+	return action;
+
+drop:
+	spin_lock(&p->tcf_lock);
+	p->tcf_qstats.drops++;
+	spin_unlock(&p->tcf_lock);
+	return TC_ACT_SHOT;
+}
+
+static int tcf_csum_dump(struct sk_buff *skb,
+			 struct tc_action *a, int bind, int ref)
+{
+	unsigned char *b = skb_tail_pointer(skb);
+	struct tcf_csum *p = a->priv;
+	struct tc_csum opt = {
+		.update_flags = p->update_flags,
+		.index   = p->tcf_index,
+		.action  = p->tcf_action,
+		.refcnt  = p->tcf_refcnt - ref,
+		.bindcnt = p->tcf_bindcnt - bind,
+	};
+	struct tcf_t t;
+
+	NLA_PUT(skb, TCA_CSUM_PARMS, sizeof(opt), &opt);
+	t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install);
+	t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse);
+	t.expires = jiffies_to_clock_t(p->tcf_tm.expires);
+	NLA_PUT(skb, TCA_CSUM_TM, sizeof(t), &t);
+
+	return skb->len;
+
+nla_put_failure:
+	nlmsg_trim(skb, b);
+	return -1;
+}
+
+static struct tc_action_ops act_csum_ops = {
+	.kind		= "csum",
+	.hinfo		= &csum_hash_info,
+	.type		= TCA_ACT_CSUM,
+	.capab		= TCA_CAP_NONE,
+	.owner		= THIS_MODULE,
+	.act		= tcf_csum,
+	.dump		= tcf_csum_dump,
+	.cleanup	= tcf_csum_cleanup,
+	.lookup		= tcf_hash_search,
+	.init		= tcf_csum_init,
+	.walk		= tcf_generic_walker
+};
+
+MODULE_DESCRIPTION("Checksum updating actions");
+MODULE_LICENSE("GPL");
+
+static int __init csum_init_module(void)
+{
+	return tcf_register_action(&act_csum_ops);
+}
+
+static void __exit csum_cleanup_module(void)
+{
+	tcf_unregister_action(&act_csum_ops);
+}
+
+module_init(csum_init_module);
+module_exit(csum_cleanup_module);
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index c7e59e6..8daef96 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -39,7 +39,7 @@
 	.lock	=	&ipt_lock,
 };
 
-static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
+static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int hook)
 {
 	struct xt_tgchk_param par;
 	struct xt_target *target;
@@ -66,7 +66,7 @@
 	return 0;
 }
 
-static void ipt_destroy_target(struct ipt_entry_target *t)
+static void ipt_destroy_target(struct xt_entry_target *t)
 {
 	struct xt_tgdtor_param par = {
 		.target   = t->u.kernel.target,
@@ -99,7 +99,7 @@
 	[TCA_IPT_TABLE]	= { .type = NLA_STRING, .len = IFNAMSIZ },
 	[TCA_IPT_HOOK]	= { .type = NLA_U32 },
 	[TCA_IPT_INDEX]	= { .type = NLA_U32 },
-	[TCA_IPT_TARG]	= { .len = sizeof(struct ipt_entry_target) },
+	[TCA_IPT_TARG]	= { .len = sizeof(struct xt_entry_target) },
 };
 
 static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,
@@ -108,7 +108,7 @@
 	struct nlattr *tb[TCA_IPT_MAX + 1];
 	struct tcf_ipt *ipt;
 	struct tcf_common *pc;
-	struct ipt_entry_target *td, *t;
+	struct xt_entry_target *td, *t;
 	char *tname;
 	int ret = 0, err;
 	u32 hook = 0;
@@ -126,7 +126,7 @@
 	if (tb[TCA_IPT_TARG] == NULL)
 		return -EINVAL;
 
-	td = (struct ipt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
+	td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
 	if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size)
 		return -EINVAL;
 
@@ -230,7 +230,7 @@
 		result = TC_ACT_SHOT;
 		ipt->tcf_qstats.drops++;
 		break;
-	case IPT_CONTINUE:
+	case XT_CONTINUE:
 		result = TC_ACT_PIPE;
 		break;
 	default:
@@ -249,7 +249,7 @@
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tcf_ipt *ipt = a->priv;
-	struct ipt_entry_target *t;
+	struct xt_entry_target *t;
 	struct tcf_t tm;
 	struct tc_cnt c;
 
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 78ef2c5..37dff78 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -123,7 +123,7 @@
 	 * calls by looking at the number of nested bh disable calls because
 	 * softirqs always disables bh.
 	 */
-	if (softirq_count() != SOFTIRQ_OFFSET) {
+	if (in_serving_softirq()) {
 		/* If there is an sk_classid we'll use that. */
 		if (!skb->sk)
 			return -1;
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index e17096e..5b271a1 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -111,44 +111,41 @@
 	}
 }
 
-static int has_ports(u8 protocol)
-{
-	switch (protocol) {
-	case IPPROTO_TCP:
-	case IPPROTO_UDP:
-	case IPPROTO_UDPLITE:
-	case IPPROTO_SCTP:
-	case IPPROTO_DCCP:
-	case IPPROTO_ESP:
-		return 1;
-	default:
-		return 0;
-	}
-}
-
 static u32 flow_get_proto_src(struct sk_buff *skb)
 {
 	switch (skb->protocol) {
 	case htons(ETH_P_IP): {
 		struct iphdr *iph;
+		int poff;
 
 		if (!pskb_network_may_pull(skb, sizeof(*iph)))
 			break;
 		iph = ip_hdr(skb);
-		if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
-		    has_ports(iph->protocol) &&
-		    pskb_network_may_pull(skb, iph->ihl * 4 + 2))
-			return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4));
+		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 + 2 + poff)) {
+			iph = ip_hdr(skb);
+			return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 +
+						 poff));
+		}
 		break;
 	}
 	case htons(ETH_P_IPV6): {
 		struct ipv6hdr *iph;
+		int poff;
 
-		if (!pskb_network_may_pull(skb, sizeof(*iph) + 2))
+		if (!pskb_network_may_pull(skb, sizeof(*iph)))
 			break;
 		iph = ipv6_hdr(skb);
-		if (has_ports(iph->nexthdr))
-			return ntohs(*(__be16 *)&iph[1]);
+		poff = proto_ports_offset(iph->nexthdr);
+		if (poff >= 0 &&
+		    pskb_network_may_pull(skb, sizeof(*iph) + poff + 2)) {
+			iph = ipv6_hdr(skb);
+			return ntohs(*(__be16 *)((void *)iph + sizeof(*iph) +
+						 poff));
+		}
 		break;
 	}
 	}
@@ -161,24 +158,36 @@
 	switch (skb->protocol) {
 	case htons(ETH_P_IP): {
 		struct iphdr *iph;
+		int poff;
 
 		if (!pskb_network_may_pull(skb, sizeof(*iph)))
 			break;
 		iph = ip_hdr(skb);
-		if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
-		    has_ports(iph->protocol) &&
-		    pskb_network_may_pull(skb, iph->ihl * 4 + 4))
-			return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + 2));
+		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);
+			return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 +
+						 2 + poff));
+		}
 		break;
 	}
 	case htons(ETH_P_IPV6): {
 		struct ipv6hdr *iph;
+		int poff;
 
-		if (!pskb_network_may_pull(skb, sizeof(*iph) + 4))
+		if (!pskb_network_may_pull(skb, sizeof(*iph)))
 			break;
 		iph = ipv6_hdr(skb);
-		if (has_ports(iph->nexthdr))
-			return ntohs(*(__be16 *)((void *)&iph[1] + 2));
+		poff = proto_ports_offset(iph->nexthdr);
+		if (poff >= 0 &&
+		    pskb_network_may_pull(skb, sizeof(*iph) + poff + 4)) {
+			iph = ipv6_hdr(skb);
+			return ntohs(*(__be16 *)((void *)iph + sizeof(*iph) +
+						 poff + 2));
+		}
 		break;
 	}
 	}
@@ -297,6 +306,11 @@
 	return tag & VLAN_VID_MASK;
 }
 
+static u32 flow_get_rxhash(struct sk_buff *skb)
+{
+	return skb_get_rxhash(skb);
+}
+
 static u32 flow_key_get(struct sk_buff *skb, int key)
 {
 	switch (key) {
@@ -334,6 +348,8 @@
 		return flow_get_skgid(skb);
 	case FLOW_KEY_VLAN_TAG:
 		return flow_get_vlan_tag(skb);
+	case FLOW_KEY_RXHASH:
+		return flow_get_rxhash(skb);
 	default:
 		WARN_ON(1);
 		return 0;
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 7416a5c..b0c2a82 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -137,7 +137,7 @@
 			int toff = off + key->off + (off2 & key->offmask);
 			__be32 *data, _data;
 
-			if (skb_headroom(skb) + toff < 0)
+			if (skb_headroom(skb) + toff > INT_MAX)
 				goto out;
 
 			data = skb_header_pointer(skb, toff, 4, &_data);
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 3bcac8a..34da5e2 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -223,6 +223,11 @@
 	dst->value = skb->mac_len;
 }
 
+META_COLLECTOR(int_rxhash)
+{
+	dst->value = skb_get_rxhash(skb);
+}
+
 /**************************************************************************
  * Netfilter
  **************************************************************************/
@@ -541,6 +546,7 @@
 		[META_ID(SK_SENDMSG_OFF)]	= META_FUNC(int_sk_sendmsg_off),
 		[META_ID(SK_WRITE_PENDING)]	= META_FUNC(int_sk_write_pend),
 		[META_ID(VLAN_TAG)]		= META_FUNC(int_vlan_tag),
+		[META_ID(RXHASH)]		= META_FUNC(int_rxhash),
 	}
 };
 
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 408eea7..b22ca2d 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -240,7 +240,10 @@
 	if (q)
 		goto out;
 
-	q = qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle);
+	if (dev_ingress_queue(dev))
+		q = qdisc_match_from_root(
+			dev_ingress_queue(dev)->qdisc_sleeping,
+			handle);
 out:
 	return q;
 }
@@ -360,7 +363,7 @@
 		tsize = nla_len(tb[TCA_STAB_DATA]) / sizeof(u16);
 	}
 
-	if (!s || tsize != s->tsize || (!tab && tsize > 0))
+	if (tsize != s->tsize || (!tab && tsize > 0))
 		return ERR_PTR(-EINVAL);
 
 	spin_lock(&qdisc_stab_lock);
@@ -690,6 +693,8 @@
 		    (new && new->flags & TCQ_F_INGRESS)) {
 			num_q = 1;
 			ingress = 1;
+			if (!dev_ingress_queue(dev))
+				return -ENOENT;
 		}
 
 		if (dev->flags & IFF_UP)
@@ -701,7 +706,7 @@
 		}
 
 		for (i = 0; i < num_q; i++) {
-			struct netdev_queue *dev_queue = &dev->rx_queue;
+			struct netdev_queue *dev_queue = dev_ingress_queue(dev);
 
 			if (!ingress)
 				dev_queue = netdev_get_tx_queue(dev, i);
@@ -979,7 +984,8 @@
 					return -ENOENT;
 				q = qdisc_leaf(p, clid);
 			} else { /* ingress */
-				q = dev->rx_queue.qdisc_sleeping;
+				if (dev_ingress_queue(dev))
+					q = dev_ingress_queue(dev)->qdisc_sleeping;
 			}
 		} else {
 			q = dev->qdisc;
@@ -1043,8 +1049,9 @@
 				if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
 					return -ENOENT;
 				q = qdisc_leaf(p, clid);
-			} else { /*ingress */
-				q = dev->rx_queue.qdisc_sleeping;
+			} else { /* ingress */
+				if (dev_ingress_queue_create(dev))
+					q = dev_ingress_queue(dev)->qdisc_sleeping;
 			}
 		} else {
 			q = dev->qdisc;
@@ -1123,11 +1130,14 @@
 create_n_graft:
 	if (!(n->nlmsg_flags&NLM_F_CREATE))
 		return -ENOENT;
-	if (clid == TC_H_INGRESS)
-		q = qdisc_create(dev, &dev->rx_queue, p,
-				 tcm->tcm_parent, tcm->tcm_parent,
-				 tca, &err);
-	else {
+	if (clid == TC_H_INGRESS) {
+		if (dev_ingress_queue(dev))
+			q = qdisc_create(dev, dev_ingress_queue(dev), p,
+					 tcm->tcm_parent, tcm->tcm_parent,
+					 tca, &err);
+		else
+			err = -ENOENT;
+	} else {
 		struct netdev_queue *dev_queue;
 
 		if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue)
@@ -1304,8 +1314,10 @@
 		if (tc_dump_qdisc_root(dev->qdisc, skb, cb, &q_idx, s_q_idx) < 0)
 			goto done;
 
-		dev_queue = &dev->rx_queue;
-		if (tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, cb, &q_idx, s_q_idx) < 0)
+		dev_queue = dev_ingress_queue(dev);
+		if (dev_queue &&
+		    tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, cb,
+				       &q_idx, s_q_idx) < 0)
 			goto done;
 
 cont:
@@ -1595,8 +1607,10 @@
 	if (tc_dump_tclass_root(dev->qdisc, skb, tcm, cb, &t, s_t) < 0)
 		goto done;
 
-	dev_queue = &dev->rx_queue;
-	if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0)
+	dev_queue = dev_ingress_queue(dev);
+	if (dev_queue &&
+	    tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb,
+				&t, s_t) < 0)
 		goto done;
 
 done:
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 6318e11..2825407 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -275,8 +275,7 @@
 		goto err_out;
 	}
 	flow->filter_list = NULL;
-	flow->q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-				    &pfifo_qdisc_ops, classid);
+	flow->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid);
 	if (!flow->q)
 		flow->q = &noop_qdisc;
 	pr_debug("atm_tc_change: qdisc %p\n", flow->q);
@@ -543,7 +542,7 @@
 	INIT_LIST_HEAD(&p->flows);
 	INIT_LIST_HEAD(&p->link.list);
 	list_add(&p->link.list, &p->flows);
-	p->link.q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
+	p->link.q = qdisc_create_dflt(sch->dev_queue,
 				      &pfifo_qdisc_ops, sch->handle);
 	if (!p->link.q)
 		p->link.q = &noop_qdisc;
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 28c01ef..eb76315 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1379,9 +1379,9 @@
 	q->link.sibling = &q->link;
 	q->link.common.classid = sch->handle;
 	q->link.qdisc = sch;
-	if (!(q->link.q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-					    &pfifo_qdisc_ops,
-					    sch->handle)))
+	q->link.q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+				      sch->handle);
+	if (!q->link.q)
 		q->link.q = &noop_qdisc;
 
 	q->link.priority = TC_CBQ_MAXPRIO-1;
@@ -1623,7 +1623,7 @@
 	struct cbq_class *cl = (struct cbq_class*)arg;
 
 	if (new == NULL) {
-		new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
+		new = qdisc_create_dflt(sch->dev_queue,
 					&pfifo_qdisc_ops, cl->common.classid);
 		if (new == NULL)
 			return -ENOBUFS;
@@ -1874,8 +1874,8 @@
 	cl->R_tab = rtab;
 	rtab = NULL;
 	cl->refcnt = 1;
-	if (!(cl->q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-					&pfifo_qdisc_ops, classid)))
+	cl->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid);
+	if (!cl->q)
 		cl->q = &noop_qdisc;
 	cl->common.classid = classid;
 	cl->tparent = parent;
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index b74046a..aa8b531 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -110,7 +110,7 @@
 	cl->refcnt	   = 1;
 	cl->common.classid = classid;
 	cl->quantum	   = quantum;
-	cl->qdisc	   = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
+	cl->qdisc	   = qdisc_create_dflt(sch->dev_queue,
 					       &pfifo_qdisc_ops, classid);
 	if (cl->qdisc == NULL)
 		cl->qdisc = &noop_qdisc;
@@ -218,7 +218,7 @@
 	struct drr_class *cl = (struct drr_class *)arg;
 
 	if (new == NULL) {
-		new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
+		new = qdisc_create_dflt(sch->dev_queue,
 					&pfifo_qdisc_ops, cl->common.classid);
 		if (new == NULL)
 			new = &noop_qdisc;
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 63d41f8..1d295d6 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -61,8 +61,7 @@
 		sch, p, new, old);
 
 	if (new == NULL) {
-		new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-					&pfifo_qdisc_ops,
+		new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
 					sch->handle);
 		if (new == NULL)
 			new = &noop_qdisc;
@@ -384,8 +383,7 @@
 	p->default_index = default_index;
 	p->set_tc_index = nla_get_flag(tb[TCA_DSMARK_SET_TC_INDEX]);
 
-	p->q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-				 &pfifo_qdisc_ops, sch->handle);
+	p->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, sch->handle);
 	if (p->q == NULL)
 		p->q = &noop_qdisc;
 
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index 5948baf..4dfecb0 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -172,8 +172,7 @@
 	struct Qdisc *q;
 	int err = -ENOMEM;
 
-	q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-			      ops, TC_H_MAKE(sch->handle, 1));
+	q = qdisc_create_dflt(sch->dev_queue, ops, TC_H_MAKE(sch->handle, 1));
 	if (q) {
 		err = fifo_set_limit(q, limit);
 		if (err < 0) {
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 2aeb3a4..5dbb3cd 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -383,6 +383,7 @@
 	.list		=	LIST_HEAD_INIT(noop_qdisc.list),
 	.q.lock		=	__SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock),
 	.dev_queue	=	&noop_netdev_queue,
+	.busylock	=	__SPIN_LOCK_UNLOCKED(noop_qdisc.busylock),
 };
 EXPORT_SYMBOL(noop_qdisc);
 
@@ -409,6 +410,7 @@
 	.list		=	LIST_HEAD_INIT(noqueue_qdisc.list),
 	.q.lock		=	__SPIN_LOCK_UNLOCKED(noqueue_qdisc.q.lock),
 	.dev_queue	=	&noqueue_netdev_queue,
+	.busylock	=	__SPIN_LOCK_UNLOCKED(noqueue_qdisc.busylock),
 };
 
 
@@ -574,10 +576,8 @@
 	return ERR_PTR(err);
 }
 
-struct Qdisc * qdisc_create_dflt(struct net_device *dev,
-				 struct netdev_queue *dev_queue,
-				 struct Qdisc_ops *ops,
-				 unsigned int parentid)
+struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
+				struct Qdisc_ops *ops, unsigned int parentid)
 {
 	struct Qdisc *sch;
 
@@ -682,7 +682,7 @@
 	struct Qdisc *qdisc;
 
 	if (dev->tx_queue_len) {
-		qdisc = qdisc_create_dflt(dev, dev_queue,
+		qdisc = qdisc_create_dflt(dev_queue,
 					  &pfifo_fast_ops, TC_H_ROOT);
 		if (!qdisc) {
 			printk(KERN_INFO "%s: activation failed\n", dev->name);
@@ -709,7 +709,7 @@
 		dev->qdisc = txq->qdisc_sleeping;
 		atomic_inc(&dev->qdisc->refcnt);
 	} else {
-		qdisc = qdisc_create_dflt(dev, txq, &mq_qdisc_ops, TC_H_ROOT);
+		qdisc = qdisc_create_dflt(txq, &mq_qdisc_ops, TC_H_ROOT);
 		if (qdisc) {
 			qdisc->ops->attach(qdisc);
 			dev->qdisc = qdisc;
@@ -753,7 +753,8 @@
 
 	need_watchdog = 0;
 	netdev_for_each_tx_queue(dev, transition_one_qdisc, &need_watchdog);
-	transition_one_qdisc(dev, &dev->rx_queue, NULL);
+	if (dev_ingress_queue(dev))
+		transition_one_qdisc(dev, dev_ingress_queue(dev), NULL);
 
 	if (need_watchdog) {
 		dev->trans_start = jiffies;
@@ -812,7 +813,8 @@
 void dev_deactivate(struct net_device *dev)
 {
 	netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc);
-	dev_deactivate_queue(dev, &dev->rx_queue, &noop_qdisc);
+	if (dev_ingress_queue(dev))
+		dev_deactivate_queue(dev, dev_ingress_queue(dev), &noop_qdisc);
 
 	dev_watchdog_down(dev);
 
@@ -838,7 +840,8 @@
 {
 	dev->qdisc = &noop_qdisc;
 	netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc);
-	dev_init_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc);
+	if (dev_ingress_queue(dev))
+		dev_init_scheduler_queue(dev, dev_ingress_queue(dev), &noop_qdisc);
 
 	setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev);
 }
@@ -861,7 +864,8 @@
 void dev_shutdown(struct net_device *dev)
 {
 	netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc);
-	shutdown_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc);
+	if (dev_ingress_queue(dev))
+		shutdown_scheduler_queue(dev, dev_ingress_queue(dev), &noop_qdisc);
 	qdisc_destroy(dev->qdisc);
 	dev->qdisc = &noop_qdisc;
 
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 4749609..069c62b 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1088,7 +1088,7 @@
 	cl->refcnt    = 1;
 	cl->sched     = q;
 	cl->cl_parent = parent;
-	cl->qdisc = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
+	cl->qdisc = qdisc_create_dflt(sch->dev_queue,
 				      &pfifo_qdisc_ops, classid);
 	if (cl->qdisc == NULL)
 		cl->qdisc = &noop_qdisc;
@@ -1209,8 +1209,7 @@
 	if (cl->level > 0)
 		return -EINVAL;
 	if (new == NULL) {
-		new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-					&pfifo_qdisc_ops,
+		new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
 					cl->cl_common.classid);
 		if (new == NULL)
 			new = &noop_qdisc;
@@ -1452,8 +1451,7 @@
 	q->root.cl_common.classid = sch->handle;
 	q->root.refcnt  = 1;
 	q->root.sched   = q;
-	q->root.qdisc = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-					  &pfifo_qdisc_ops,
+	q->root.qdisc = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
 					  sch->handle);
 	if (q->root.qdisc == NULL)
 		q->root.qdisc = &noop_qdisc;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 4be8d04..01b519d 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1121,8 +1121,7 @@
 	if (cl->level)
 		return -EINVAL;
 	if (new == NULL &&
-	    (new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-				     &pfifo_qdisc_ops,
+	    (new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
 				     cl->common.classid)) == NULL)
 		return -ENOBUFS;
 
@@ -1247,8 +1246,7 @@
 		return -EBUSY;
 
 	if (!cl->level && htb_parent_last_child(cl)) {
-		new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-					  &pfifo_qdisc_ops,
+		new_q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
 					  cl->parent->common.classid);
 		last_child = 1;
 	}
@@ -1302,14 +1300,14 @@
 	struct htb_class *cl = (struct htb_class *)*arg, *parent;
 	struct nlattr *opt = tca[TCA_OPTIONS];
 	struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
-	struct nlattr *tb[TCA_HTB_RTAB + 1];
+	struct nlattr *tb[__TCA_HTB_MAX];
 	struct tc_htb_opt *hopt;
 
 	/* extract all subattrs from opt attr */
 	if (!opt)
 		goto failure;
 
-	err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy);
+	err = nla_parse_nested(tb, TCA_HTB_MAX, opt, htb_policy);
 	if (err < 0)
 		goto failure;
 
@@ -1377,7 +1375,7 @@
 		/* 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 */
-		new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
+		new_q = qdisc_create_dflt(sch->dev_queue,
 					  &pfifo_qdisc_ops, classid);
 		sch_tree_lock(sch);
 		if (parent && !parent->level) {
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index fe91e50..ecc302f 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -56,7 +56,7 @@
 
 	for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
 		dev_queue = netdev_get_tx_queue(dev, ntx);
-		qdisc = qdisc_create_dflt(dev, dev_queue, &pfifo_fast_ops,
+		qdisc = qdisc_create_dflt(dev_queue, &pfifo_fast_ops,
 					  TC_H_MAKE(TC_H_MAJ(sch->handle),
 						    TC_H_MIN(ntx + 1)));
 		if (qdisc == NULL)
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 6ae2512..32690de 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -227,8 +227,7 @@
 	for (i = 0; i < q->bands; i++) {
 		if (q->queues[i] == &noop_qdisc) {
 			struct Qdisc *child, *old;
-			child = qdisc_create_dflt(qdisc_dev(sch),
-						  sch->dev_queue,
+			child = qdisc_create_dflt(sch->dev_queue,
 						  &pfifo_qdisc_ops,
 						  TC_H_MAKE(sch->handle,
 							    i + 1));
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 4714ff1..e5593c0 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -538,8 +538,7 @@
 
 	qdisc_watchdog_init(&q->watchdog, sch);
 
-	q->qdisc = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
-				     &tfifo_qdisc_ops,
+	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");
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 0748fb1..b1c95bc 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -200,7 +200,7 @@
 	for (i=0; i<q->bands; i++) {
 		if (q->queues[i] == &noop_qdisc) {
 			struct Qdisc *child, *old;
-			child = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
+			child = qdisc_create_dflt(sch->dev_queue,
 						  &pfifo_qdisc_ops,
 						  TC_H_MAKE(sch->handle, i + 1));
 			if (child) {
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 201cbac..3cf478d 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -123,40 +123,39 @@
 	case htons(ETH_P_IP):
 	{
 		const struct iphdr *iph;
+		int poff;
 
 		if (!pskb_network_may_pull(skb, sizeof(*iph)))
 			goto err;
 		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)) &&
-		    (iph->protocol == IPPROTO_TCP ||
-		     iph->protocol == IPPROTO_UDP ||
-		     iph->protocol == IPPROTO_UDPLITE ||
-		     iph->protocol == IPPROTO_SCTP ||
-		     iph->protocol == IPPROTO_DCCP ||
-		     iph->protocol == IPPROTO_ESP) &&
-		     pskb_network_may_pull(skb, iph->ihl * 4 + 4))
-			h2 ^= *(((u32*)iph) + iph->ihl);
+		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);
+		}
 		break;
 	}
 	case htons(ETH_P_IPV6):
 	{
 		struct ipv6hdr *iph;
+		int poff;
 
 		if (!pskb_network_may_pull(skb, sizeof(*iph)))
 			goto err;
 		iph = ipv6_hdr(skb);
 		h = (__force u32)iph->daddr.s6_addr32[3];
 		h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr;
-		if ((iph->nexthdr == IPPROTO_TCP ||
-		     iph->nexthdr == IPPROTO_UDP ||
-		     iph->nexthdr == IPPROTO_UDPLITE ||
-		     iph->nexthdr == IPPROTO_SCTP ||
-		     iph->nexthdr == IPPROTO_DCCP ||
-		     iph->nexthdr == IPPROTO_ESP) &&
-		    pskb_network_may_pull(skb, sizeof(*iph) + 4))
-			h2 ^= *(u32*)&iph[1];
+		poff = proto_ports_offset(iph->nexthdr);
+		if (poff >= 0 &&
+		    pskb_network_may_pull(skb, sizeof(*iph) + 4 + poff)) {
+			iph = ipv6_hdr(skb);
+			h2 ^= *(u32*)((void *)iph + sizeof(*iph) + poff);
+		}
 		break;
 	}
 	default:
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index feaabc1..401af95 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -241,11 +241,11 @@
 	}
 	if (neigh_event_send(n, skb_res) == 0) {
 		int err;
+		char haddr[MAX_ADDR_LEN];
 
-		read_lock(&n->lock);
-		err = dev_hard_header(skb, dev, ntohs(skb->protocol),
-				      n->ha, NULL, skb->len);
-		read_unlock(&n->lock);
+		neigh_ha_snapshot(haddr, n, dev);
+		err = dev_hard_header(skb, dev, ntohs(skb->protocol), haddr,
+				      NULL, skb->len);
 
 		if (err < 0) {
 			neigh_release(n);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 0b85e52..5f1fb8b 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -48,6 +48,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/poll.h>
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index 8636639..ddbbf7c 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -543,16 +543,20 @@
 		id = ntohs(hmacs->hmac_ids[i]);
 
 		/* Check the id is in the supported range */
-		if (id > SCTP_AUTH_HMAC_ID_MAX)
+		if (id > SCTP_AUTH_HMAC_ID_MAX) {
+			id = 0;
 			continue;
+		}
 
 		/* See is we support the id.  Supported IDs have name and
 		 * length fields set, so that we can allocated and use
 		 * them.  We can safely just check for name, for without the
 		 * name, we can't allocate the TFM.
 		 */
-		if (!sctp_hmac_list[id].hmac_name)
+		if (!sctp_hmac_list[id].hmac_name) {
+			id = 0;
 			continue;
+		}
 
 		break;
 	}
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 476caaf..6c85564 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -37,6 +37,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/net.h>
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index ccb6dc4..397296f 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -43,6 +43,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 #include <linux/interrupt.h>
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 7326891..95e0c8e 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -47,6 +47,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -336,7 +338,7 @@
 		memcpy(saddr, baddr, sizeof(union sctp_addr));
 		SCTP_DEBUG_PRINTK("saddr: %pI6\n", &saddr->v6.sin6_addr);
 	} else {
-		printk(KERN_ERR "%s: asoc:%p Could not find a valid source "
+		pr_err("%s: asoc:%p Could not find a valid source "
 		       "address for the dest:%pI6\n",
 		       __func__, asoc, &daddr->v6.sin6_addr);
 	}
diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c
index f73ec0e..8ef8e7d 100644
--- a/net/sctp/objcnt.c
+++ b/net/sctp/objcnt.c
@@ -38,6 +38,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <net/sctp/sctp.h>
 
@@ -134,8 +136,7 @@
 	ent = proc_create("sctp_dbg_objcnt", 0,
 			  proc_net_sctp, &sctp_objcnt_ops);
 	if (!ent)
-		printk(KERN_WARNING
-			"sctp_dbg_objcnt: Unable to create /proc entry.\n");
+		pr_warn("sctp_dbg_objcnt: Unable to create /proc entry.\n");
 }
 
 /* Cleanup the objcount entry in the proc filesystem.  */
diff --git a/net/sctp/output.c b/net/sctp/output.c
index bcc4590..60600d3 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -41,6 +41,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/wait.h>
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index c04b2eb..8c6d379 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -46,6 +46,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/list.h>   /* For struct list_head */
 #include <linux/socket.h>
@@ -1463,23 +1465,23 @@
 					/* Display the end of the
 					 * current range.
 					 */
-					SCTP_DEBUG_PRINTK("-%08x",
-							  dbg_last_ack_tsn);
+					SCTP_DEBUG_PRINTK_CONT("-%08x",
+							       dbg_last_ack_tsn);
 				}
 
 				/* Start a new range.  */
-				SCTP_DEBUG_PRINTK(",%08x", tsn);
+				SCTP_DEBUG_PRINTK_CONT(",%08x", tsn);
 				dbg_ack_tsn = tsn;
 				break;
 
 			case 1:	/* The last TSN was NOT ACKed. */
 				if (dbg_last_kept_tsn != dbg_kept_tsn) {
 					/* Display the end of current range. */
-					SCTP_DEBUG_PRINTK("-%08x",
-							  dbg_last_kept_tsn);
+					SCTP_DEBUG_PRINTK_CONT("-%08x",
+							       dbg_last_kept_tsn);
 				}
 
-				SCTP_DEBUG_PRINTK("\n");
+				SCTP_DEBUG_PRINTK_CONT("\n");
 
 				/* FALL THROUGH... */
 			default:
@@ -1526,18 +1528,18 @@
 					break;
 
 				if (dbg_last_kept_tsn != dbg_kept_tsn)
-					SCTP_DEBUG_PRINTK("-%08x",
-							  dbg_last_kept_tsn);
+					SCTP_DEBUG_PRINTK_CONT("-%08x",
+							       dbg_last_kept_tsn);
 
-				SCTP_DEBUG_PRINTK(",%08x", tsn);
+				SCTP_DEBUG_PRINTK_CONT(",%08x", tsn);
 				dbg_kept_tsn = tsn;
 				break;
 
 			case 0:
 				if (dbg_last_ack_tsn != dbg_ack_tsn)
-					SCTP_DEBUG_PRINTK("-%08x",
-							  dbg_last_ack_tsn);
-				SCTP_DEBUG_PRINTK("\n");
+					SCTP_DEBUG_PRINTK_CONT("-%08x",
+							       dbg_last_ack_tsn);
+				SCTP_DEBUG_PRINTK_CONT("\n");
 
 				/* FALL THROUGH... */
 			default:
@@ -1556,17 +1558,17 @@
 	switch (dbg_prt_state) {
 	case 0:
 		if (dbg_last_ack_tsn != dbg_ack_tsn) {
-			SCTP_DEBUG_PRINTK("-%08x\n", dbg_last_ack_tsn);
+			SCTP_DEBUG_PRINTK_CONT("-%08x\n", dbg_last_ack_tsn);
 		} else {
-			SCTP_DEBUG_PRINTK("\n");
+			SCTP_DEBUG_PRINTK_CONT("\n");
 		}
 	break;
 
 	case 1:
 		if (dbg_last_kept_tsn != dbg_kept_tsn) {
-			SCTP_DEBUG_PRINTK("-%08x\n", dbg_last_kept_tsn);
+			SCTP_DEBUG_PRINTK_CONT("-%08x\n", dbg_last_kept_tsn);
 		} else {
-			SCTP_DEBUG_PRINTK("\n");
+			SCTP_DEBUG_PRINTK_CONT("\n");
 		}
 	}
 #endif /* SCTP_DEBUG */
diff --git a/net/sctp/probe.c b/net/sctp/probe.c
index db3a42b..bc6cd75 100644
--- a/net/sctp/probe.c
+++ b/net/sctp/probe.c
@@ -22,6 +22,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
 #include <linux/socket.h>
@@ -117,6 +119,7 @@
 	.owner	= THIS_MODULE,
 	.open	= sctpprobe_open,
 	.read	= sctpprobe_read,
+	.llseek = noop_llseek,
 };
 
 sctp_disposition_t jsctp_sf_eat_sack(const struct sctp_endpoint *ep,
@@ -192,7 +195,7 @@
 	if (ret)
 		goto remove_proc;
 
-	pr_info("SCTP probe registered (port=%d)\n", port);
+	pr_info("probe registered (port=%d)\n", port);
 
 	return 0;
 
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 5027b83..1ef29c7 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -46,6 +46,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
@@ -707,8 +709,7 @@
 					   &init_net);
 
 	if (err < 0) {
-		printk(KERN_ERR
-		       "SCTP: Failed to create the SCTP control socket.\n");
+		pr_err("Failed to create the SCTP control socket\n");
 		return err;
 	}
 	return 0;
@@ -798,7 +799,7 @@
 static int sctp_inet_af_supported(sa_family_t family, struct sctp_sock *sp)
 {
 	/* PF_INET only supports AF_INET addresses. */
-	return (AF_INET == family);
+	return AF_INET == family;
 }
 
 /* Address matching with wildcards allowed. */
@@ -1206,7 +1207,7 @@
 					__get_free_pages(GFP_ATOMIC, order);
 	} while (!sctp_assoc_hashtable && --order > 0);
 	if (!sctp_assoc_hashtable) {
-		printk(KERN_ERR "SCTP: Failed association hash alloc.\n");
+		pr_err("Failed association hash alloc\n");
 		status = -ENOMEM;
 		goto err_ahash_alloc;
 	}
@@ -1220,7 +1221,7 @@
 	sctp_ep_hashtable = (struct sctp_hashbucket *)
 		kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
 	if (!sctp_ep_hashtable) {
-		printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n");
+		pr_err("Failed endpoint_hash alloc\n");
 		status = -ENOMEM;
 		goto err_ehash_alloc;
 	}
@@ -1239,7 +1240,7 @@
 					__get_free_pages(GFP_ATOMIC, order);
 	} while (!sctp_port_hashtable && --order > 0);
 	if (!sctp_port_hashtable) {
-		printk(KERN_ERR "SCTP: Failed bind hash alloc.");
+		pr_err("Failed bind hash alloc\n");
 		status = -ENOMEM;
 		goto err_bhash_alloc;
 	}
@@ -1248,8 +1249,7 @@
 		INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
 	}
 
-	printk(KERN_INFO "SCTP: Hash tables configured "
-			 "(established %d bind %d)\n",
+	pr_info("Hash tables configured (established %d bind %d)\n",
 		sctp_assoc_hashsize, sctp_port_hashsize);
 
 	/* Disable ADDIP by default. */
@@ -1290,8 +1290,7 @@
 
 	/* Initialize the control inode/socket for handling OOTB packets.  */
 	if ((status = sctp_ctl_sock_init())) {
-		printk (KERN_ERR
-			"SCTP: Failed to initialize the SCTP control sock.\n");
+		pr_err("Failed to initialize the SCTP control sock\n");
 		goto err_ctl_sock_init;
 	}
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 246f929..2cc46f0 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -50,6 +50,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/ip.h>
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index f5e5e27..b21b218 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -47,6 +47,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/skbuff.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -1146,26 +1148,23 @@
 
 	case SCTP_DISPOSITION_VIOLATION:
 		if (net_ratelimit())
-			printk(KERN_ERR "sctp protocol violation state %d "
-			       "chunkid %d\n", state, subtype.chunk);
+			pr_err("protocol violation state %d chunkid %d\n",
+			       state, subtype.chunk);
 		break;
 
 	case SCTP_DISPOSITION_NOT_IMPL:
-		printk(KERN_WARNING "sctp unimplemented feature in state %d, "
-		       "event_type %d, event_id %d\n",
-		       state, event_type, subtype.chunk);
+		pr_warn("unimplemented feature in state %d, event_type %d, event_id %d\n",
+			state, event_type, subtype.chunk);
 		break;
 
 	case SCTP_DISPOSITION_BUG:
-		printk(KERN_ERR "sctp bug in state %d, "
-		       "event_type %d, event_id %d\n",
+		pr_err("bug in state %d, event_type %d, event_id %d\n",
 		       state, event_type, subtype.chunk);
 		BUG();
 		break;
 
 	default:
-		printk(KERN_ERR "sctp impossible disposition %d "
-		       "in state %d, event_type %d, event_id %d\n",
+		pr_err("impossible disposition %d in state %d, event_type %d, event_id %d\n",
 		       status, state, event_type, subtype.chunk);
 		BUG();
 		break;
@@ -1679,8 +1678,8 @@
 			sctp_cmd_send_asconf(asoc);
 			break;
 		default:
-			printk(KERN_WARNING "Impossible command: %u, %p\n",
-			       cmd->verb, cmd->obj.ptr);
+			pr_warn("Impossible command: %u, %p\n",
+				cmd->verb, cmd->obj.ptr);
 			break;
 		}
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index d344dc4..4b4eb7c 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -50,6 +50,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/ip.h>
@@ -1138,18 +1140,16 @@
 	if (unlikely(!link)) {
 		if (from_addr.sa.sa_family == AF_INET6) {
 			if (net_ratelimit())
-				printk(KERN_WARNING
-				    "%s association %p could not find address %pI6\n",
-				    __func__,
-				    asoc,
-				    &from_addr.v6.sin6_addr);
+				pr_warn("%s association %p could not find address %pI6\n",
+					__func__,
+					asoc,
+					&from_addr.v6.sin6_addr);
 		} else {
 			if (net_ratelimit())
-				printk(KERN_WARNING
-				    "%s association %p could not find address %pI4\n",
-				    __func__,
-				    asoc,
-				    &from_addr.v4.sin_addr.s_addr);
+				pr_warn("%s association %p could not find address %pI4\n",
+					__func__,
+					asoc,
+					&from_addr.v4.sin_addr.s_addr);
 		}
 		return SCTP_DISPOSITION_DISCARD;
 	}
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 6d9b3aa..546d4387 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -46,6 +46,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/skbuff.h>
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
@@ -66,15 +68,19 @@
 	.name = "sctp_sf_bug"
 };
 
-#define DO_LOOKUP(_max, _type, _table) \
-	if ((event_subtype._type > (_max))) { \
-		printk(KERN_WARNING \
-		       "sctp table %p possible attack:" \
-		       " event %d exceeds max %d\n", \
-		       _table, event_subtype._type, _max); \
-		return &bug; \
-	} \
-	return &_table[event_subtype._type][(int)state];
+#define DO_LOOKUP(_max, _type, _table)					\
+({									\
+	const sctp_sm_table_entry_t *rtn;				\
+									\
+	if ((event_subtype._type > (_max))) {				\
+		pr_warn("table %p possible attack: event %d exceeds max %d\n", \
+			_table, event_subtype._type, _max);		\
+	        rtn = &bug;						\
+	} else								\
+		rtn = &_table[event_subtype._type][(int)state];		\
+									\
+	rtn;								\
+})
 
 const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
 						  sctp_state_t state,
@@ -83,21 +89,15 @@
 	switch (event_type) {
 	case SCTP_EVENT_T_CHUNK:
 		return sctp_chunk_event_lookup(event_subtype.chunk, state);
-		break;
 	case SCTP_EVENT_T_TIMEOUT:
-		DO_LOOKUP(SCTP_EVENT_TIMEOUT_MAX, timeout,
-			  timeout_event_table);
-		break;
-
+		return DO_LOOKUP(SCTP_EVENT_TIMEOUT_MAX, timeout,
+				 timeout_event_table);
 	case SCTP_EVENT_T_OTHER:
-		DO_LOOKUP(SCTP_EVENT_OTHER_MAX, other, other_event_table);
-		break;
-
+		return DO_LOOKUP(SCTP_EVENT_OTHER_MAX, other,
+				 other_event_table);
 	case SCTP_EVENT_T_PRIMITIVE:
-		DO_LOOKUP(SCTP_EVENT_PRIMITIVE_MAX, primitive,
-			  primitive_event_table);
-		break;
-
+		return DO_LOOKUP(SCTP_EVENT_PRIMITIVE_MAX, primitive,
+				 primitive_event_table);
 	default:
 		/* Yikes!  We got an illegal event type.  */
 		return &bug;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index ca44917..e34ca9c 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -57,6 +57,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/wait.h>
@@ -916,6 +918,11 @@
 	/* Walk through the addrs buffer and count the number of addresses. */
 	addr_buf = kaddrs;
 	while (walk_size < addrs_size) {
+		if (walk_size + sizeof(sa_family_t) > addrs_size) {
+			kfree(kaddrs);
+			return -EINVAL;
+		}
+
 		sa_addr = (struct sockaddr *)addr_buf;
 		af = sctp_get_af_specific(sa_addr->sa_family);
 
@@ -1002,9 +1009,13 @@
 	/* Walk through the addrs buffer and count the number of addresses. */
 	addr_buf = kaddrs;
 	while (walk_size < addrs_size) {
+		if (walk_size + sizeof(sa_family_t) > addrs_size) {
+			err = -EINVAL;
+			goto out_free;
+		}
+
 		sa_addr = (union sctp_addr *)addr_buf;
 		af = sctp_get_af_specific(sa_addr->sa.sa_family);
-		port = ntohs(sa_addr->v4.sin_port);
 
 		/* If the address family is not supported or if this address
 		 * causes the address buffer to overflow return EINVAL.
@@ -1014,6 +1025,8 @@
 			goto out_free;
 		}
 
+		port = ntohs(sa_addr->v4.sin_port);
+
 		/* Save current address so we can work with it */
 		memcpy(&to, sa_addr, af->sockaddr_len);
 
@@ -2458,9 +2471,8 @@
 		if (params.sack_delay == 0 && params.sack_freq == 0)
 			return 0;
 	} else if (optlen == sizeof(struct sctp_assoc_value)) {
-		printk(KERN_WARNING "SCTP: Use of struct sctp_assoc_value "
-		       "in delayed_ack socket option deprecated\n");
-		printk(KERN_WARNING "SCTP: Use struct sctp_sack_info instead\n");
+		pr_warn("Use of struct sctp_assoc_value in delayed_ack socket option deprecated\n");
+		pr_warn("Use struct sctp_sack_info instead\n");
 		if (copy_from_user(&params, optval, optlen))
 			return -EFAULT;
 
@@ -2868,10 +2880,8 @@
 	int val;
 
 	if (optlen == sizeof(int)) {
-		printk(KERN_WARNING
-		   "SCTP: Use of int in maxseg socket option deprecated\n");
-		printk(KERN_WARNING
-		   "SCTP: Use struct sctp_assoc_value instead\n");
+		pr_warn("Use of int in maxseg socket option deprecated\n");
+		pr_warn("Use struct sctp_assoc_value instead\n");
 		if (copy_from_user(&val, optval, optlen))
 			return -EFAULT;
 		params.assoc_id = 0;
@@ -3121,10 +3131,8 @@
 	int assoc_id = 0;
 
 	if (optlen == sizeof(int)) {
-		printk(KERN_WARNING
-		   "SCTP: Use of int in max_burst socket option deprecated\n");
-		printk(KERN_WARNING
-		   "SCTP: Use struct sctp_assoc_value instead\n");
+		pr_warn("Use of int in max_burst socket option deprecated\n");
+		pr_warn("Use struct sctp_assoc_value instead\n");
 		if (copy_from_user(&val, optval, optlen))
 			return -EFAULT;
 	} else if (optlen == sizeof(struct sctp_assoc_value)) {
@@ -3595,7 +3603,40 @@
 /* The SCTP ioctl handler. */
 SCTP_STATIC int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-	return -ENOIOCTLCMD;
+	int rc = -ENOTCONN;
+
+	sctp_lock_sock(sk);
+
+	/*
+	 * SEQPACKET-style sockets in LISTENING state are valid, for
+	 * SCTP, so only discard TCP-style sockets in LISTENING state.
+	 */
+	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
+		goto out;
+
+	switch (cmd) {
+	case SIOCINQ: {
+		struct sk_buff *skb;
+		unsigned int amount = 0;
+
+		skb = skb_peek(&sk->sk_receive_queue);
+		if (skb != NULL) {
+			/*
+			 * We will only return the amount of this packet since
+			 * that is all that will be read.
+			 */
+			amount = skb->len;
+		}
+		rc = put_user(amount, (int __user *)arg);
+		break;
+	}
+	default:
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+out:
+	sctp_release_sock(sk);
+	return rc;
 }
 
 /* This is the function which gets called during socket creation to
@@ -3854,7 +3895,7 @@
 	}
 
 out:
-	return (retval);
+	return retval;
 }
 
 
@@ -3910,7 +3951,7 @@
 	}
 
 out:
-	return (retval);
+	return retval;
 }
 
 /* 7.1.12 Enable/Disable message fragmentation (SCTP_DISABLE_FRAGMENTS)
@@ -4281,9 +4322,8 @@
 		if (copy_from_user(&params, optval, len))
 			return -EFAULT;
 	} else if (len == sizeof(struct sctp_assoc_value)) {
-		printk(KERN_WARNING "SCTP: Use of struct sctp_assoc_value "
-		       "in delayed_ack socket option deprecated\n");
-		printk(KERN_WARNING "SCTP: Use struct sctp_sack_info instead\n");
+		pr_warn("Use of struct sctp_assoc_value in delayed_ack socket option deprecated\n");
+		pr_warn("Use struct sctp_sack_info instead\n");
 		if (copy_from_user(&params, optval, len))
 			return -EFAULT;
 	} else
@@ -4929,10 +4969,8 @@
 	struct sctp_association *asoc;
 
 	if (len == sizeof(int)) {
-		printk(KERN_WARNING
-		   "SCTP: Use of int in maxseg socket option deprecated\n");
-		printk(KERN_WARNING
-		   "SCTP: Use struct sctp_assoc_value instead\n");
+		pr_warn("Use of int in maxseg socket option deprecated\n");
+		pr_warn("Use struct sctp_assoc_value instead\n");
 		params.assoc_id = 0;
 	} else if (len >= sizeof(struct sctp_assoc_value)) {
 		len = sizeof(struct sctp_assoc_value);
@@ -5023,10 +5061,8 @@
 	struct sctp_association *asoc;
 
 	if (len == sizeof(int)) {
-		printk(KERN_WARNING
-		   "SCTP: Use of int in max_burst socket option deprecated\n");
-		printk(KERN_WARNING
-		   "SCTP: Use struct sctp_assoc_value instead\n");
+		pr_warn("Use of int in max_burst socket option deprecated\n");
+		pr_warn("Use struct sctp_assoc_value instead\n");
 		params.assoc_id = 0;
 	} else if (len >= sizeof(struct sctp_assoc_value)) {
 		len = sizeof(struct sctp_assoc_value);
@@ -5569,7 +5605,7 @@
 	/* Note: sk->sk_num gets filled in if ephemeral port request. */
 	ret = sctp_get_port_local(sk, &addr);
 
-	return (ret ? 1 : 0);
+	return ret ? 1 : 0;
 }
 
 /*
@@ -5586,8 +5622,7 @@
 		tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC);
 		if (IS_ERR(tfm)) {
 			if (net_ratelimit()) {
-				printk(KERN_INFO
-				       "SCTP: failed to load transform for %s: %ld\n",
+				pr_info("failed to load transform for %s: %ld\n",
 					sctp_hmac_alg, PTR_ERR(tfm));
 			}
 			return -ENOSYS;
@@ -5716,13 +5751,12 @@
 	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
 		mask |= POLLERR;
 	if (sk->sk_shutdown & RCV_SHUTDOWN)
-		mask |= POLLRDHUP;
+		mask |= POLLRDHUP | POLLIN | POLLRDNORM;
 	if (sk->sk_shutdown == SHUTDOWN_MASK)
 		mask |= POLLHUP;
 
 	/* Is it readable?  Reconsider this code with TCP-style support.  */
-	if (!skb_queue_empty(&sk->sk_receive_queue) ||
-	    (sk->sk_shutdown & RCV_SHUTDOWN))
+	if (!skb_queue_empty(&sk->sk_receive_queue))
 		mask |= POLLIN | POLLRDNORM;
 
 	/* The association is either gone or not ready.  */
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 132046c..d3ae493 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -48,6 +48,8 @@
  * be incorporated into the next SCTP release.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/random.h>
@@ -244,10 +246,9 @@
 	struct dst_entry *dst;
 
 	if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
-		printk(KERN_WARNING "%s: Reported pmtu %d too low, "
-		       "using default minimum of %d\n",
-		       __func__, pmtu,
-		       SCTP_DEFAULT_MINSEGMENT);
+		pr_warn("%s: Reported pmtu %d too low, using default minimum of %d\n",
+			__func__, pmtu,
+			SCTP_DEFAULT_MINSEGMENT);
 		/* Use default minimum segment size and disable
 		 * pmtu discovery on this transport.
 		 */
diff --git a/net/socket.c b/net/socket.c
index 2270b94..abf3e25 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -209,8 +209,8 @@
  *	specified. Zero is returned for a success.
  */
 
-int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr,
-		      int __user *ulen)
+static int move_addr_to_user(struct sockaddr *kaddr, int klen,
+			     void __user *uaddr, int __user *ulen)
 {
 	int err;
 	int len;
@@ -502,6 +502,7 @@
 const struct file_operations bad_sock_fops = {
 	.owner = THIS_MODULE,
 	.open = sock_no_open,
+	.llseek = noop_llseek,
 };
 
 /**
@@ -535,14 +536,13 @@
 }
 EXPORT_SYMBOL(sock_release);
 
-int sock_tx_timestamp(struct msghdr *msg, struct sock *sk,
-		      union skb_shared_tx *shtx)
+int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
 {
-	shtx->flags = 0;
+	*tx_flags = 0;
 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
-		shtx->hardware = 1;
+		*tx_flags |= SKBTX_HW_TSTAMP;
 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
-		shtx->software = 1;
+		*tx_flags |= SKBTX_SW_TSTAMP;
 	return 0;
 }
 EXPORT_SYMBOL(sock_tx_timestamp);
@@ -662,7 +662,8 @@
 }
 EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
 
-inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
+static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
+				   struct sk_buff *skb)
 {
 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
@@ -1919,7 +1920,8 @@
 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
 		 * checking falls down on this.
 		 */
-		if (copy_from_user(ctl_buf, (void __user *)msg_sys.msg_control,
+		if (copy_from_user(ctl_buf,
+				   (void __user __force *)msg_sys.msg_control,
 				   ctl_len))
 			goto out_freectl;
 		msg_sys.msg_control = ctl_buf;
@@ -3054,14 +3056,19 @@
 			char *optval, int *optlen)
 {
 	mm_segment_t oldfs = get_fs();
+	char __user *uoptval;
+	int __user *uoptlen;
 	int err;
 
+	uoptval = (char __user __force *) optval;
+	uoptlen = (int __user __force *) optlen;
+
 	set_fs(KERNEL_DS);
 	if (level == SOL_SOCKET)
-		err = sock_getsockopt(sock, level, optname, optval, optlen);
+		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
 	else
-		err = sock->ops->getsockopt(sock, level, optname, optval,
-					    optlen);
+		err = sock->ops->getsockopt(sock, level, optname, uoptval,
+					    uoptlen);
 	set_fs(oldfs);
 	return err;
 }
@@ -3071,13 +3078,16 @@
 			char *optval, unsigned int optlen)
 {
 	mm_segment_t oldfs = get_fs();
+	char __user *uoptval;
 	int err;
 
+	uoptval = (char __user __force *) optval;
+
 	set_fs(KERNEL_DS);
 	if (level == SOL_SOCKET)
-		err = sock_setsockopt(sock, level, optname, optval, optlen);
+		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
 	else
-		err = sock->ops->setsockopt(sock, level, optname, optval,
+		err = sock->ops->setsockopt(sock, level, optname, uoptval,
 					    optlen);
 	set_fs(oldfs);
 	return err;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 12c4859..3835ce3 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1050,7 +1050,7 @@
 out:
 	if (acred->machine_cred != gss_cred->gc_machine_cred)
 		return 0;
-	return (rc->cr_uid == acred->uid);
+	return rc->cr_uid == acred->uid;
 }
 
 /*
diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c
index 310b78e..c586e92 100644
--- a/net/sunrpc/auth_gss/gss_generic_token.c
+++ b/net/sunrpc/auth_gss/gss_generic_token.c
@@ -76,19 +76,19 @@
 der_length_size( int length)
 {
 	if (length < (1<<7))
-		return(1);
+		return 1;
 	else if (length < (1<<8))
-		return(2);
+		return 2;
 #if (SIZEOF_INT == 2)
 	else
-		return(3);
+		return 3;
 #else
 	else if (length < (1<<16))
-		return(3);
+		return 3;
 	else if (length < (1<<24))
-		return(4);
+		return 4;
 	else
-		return(5);
+		return 5;
 #endif
 }
 
@@ -121,14 +121,14 @@
 	int ret;
 
 	if (*bufsize < 1)
-		return(-1);
+		return -1;
 	sf = *(*buf)++;
 	(*bufsize)--;
 	if (sf & 0x80) {
 		if ((sf &= 0x7f) > ((*bufsize)-1))
-			return(-1);
+			return -1;
 		if (sf > SIZEOF_INT)
-			return (-1);
+			return -1;
 		ret = 0;
 		for (; sf; sf--) {
 			ret = (ret<<8) + (*(*buf)++);
@@ -138,7 +138,7 @@
 		ret = sf;
 	}
 
-	return(ret);
+	return ret;
 }
 
 /* returns the length of a token, given the mech oid and the body size */
@@ -148,7 +148,7 @@
 {
 	/* set body_size to sequence contents size */
 	body_size += 2 + (int) mech->len;         /* NEED overflow check */
-	return(1 + der_length_size(body_size) + body_size);
+	return 1 + der_length_size(body_size) + body_size;
 }
 
 EXPORT_SYMBOL_GPL(g_token_size);
@@ -186,27 +186,27 @@
 	int ret = 0;
 
 	if ((toksize-=1) < 0)
-		return(G_BAD_TOK_HEADER);
+		return G_BAD_TOK_HEADER;
 	if (*buf++ != 0x60)
-		return(G_BAD_TOK_HEADER);
+		return G_BAD_TOK_HEADER;
 
 	if ((seqsize = der_read_length(&buf, &toksize)) < 0)
-		return(G_BAD_TOK_HEADER);
+		return G_BAD_TOK_HEADER;
 
 	if (seqsize != toksize)
-		return(G_BAD_TOK_HEADER);
+		return G_BAD_TOK_HEADER;
 
 	if ((toksize-=1) < 0)
-		return(G_BAD_TOK_HEADER);
+		return G_BAD_TOK_HEADER;
 	if (*buf++ != 0x06)
-		return(G_BAD_TOK_HEADER);
+		return G_BAD_TOK_HEADER;
 
 	if ((toksize-=1) < 0)
-		return(G_BAD_TOK_HEADER);
+		return G_BAD_TOK_HEADER;
 	toid.len = *buf++;
 
 	if ((toksize-=toid.len) < 0)
-		return(G_BAD_TOK_HEADER);
+		return G_BAD_TOK_HEADER;
 	toid.data = buf;
 	buf+=toid.len;
 
@@ -217,17 +217,17 @@
       to return G_BAD_TOK_HEADER if the token header is in fact bad */
 
 	if ((toksize-=2) < 0)
-		return(G_BAD_TOK_HEADER);
+		return G_BAD_TOK_HEADER;
 
 	if (ret)
-		return(ret);
+		return ret;
 
 	if (!ret) {
 		*buf_in = buf;
 		*body_size = toksize;
 	}
 
-	return(ret);
+	return ret;
 }
 
 EXPORT_SYMBOL_GPL(g_verify_token_header);
diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
index 415c013..62ac90c 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
@@ -162,5 +162,5 @@
 	*seqnum = ((plain[0]) |
 		   (plain[1] << 8) | (plain[2] << 16) | (plain[3] << 24));
 
-	return (0);
+	return 0;
 }
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 2689de3..8b40610 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -331,7 +331,7 @@
 			*context_handle);
 
 	if (!*context_handle)
-		return(GSS_S_NO_CONTEXT);
+		return GSS_S_NO_CONTEXT;
 	if ((*context_handle)->internal_ctx_id)
 		(*context_handle)->mech_type->gm_ops
 			->gss_delete_sec_context((*context_handle)
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 2b06410..7dce81a 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -28,7 +28,6 @@
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <asm/ioctls.h>
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/cache.h>
@@ -1348,15 +1347,10 @@
 static long cache_ioctl_procfs(struct file *filp,
 			       unsigned int cmd, unsigned long arg)
 {
-	long ret;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct cache_detail *cd = PDE(inode)->data;
 
-	lock_kernel();
-	ret = cache_ioctl(inode, filp, cmd, arg, cd);
-	unlock_kernel();
-
-	return ret;
+	return cache_ioctl(inode, filp, cmd, arg, cd);
 }
 
 static int cache_open_procfs(struct inode *inode, struct file *filp)
@@ -1441,6 +1435,7 @@
 	.read		= read_flush_procfs,
 	.write		= write_flush_procfs,
 	.release	= release_flush_procfs,
+	.llseek		= no_llseek,
 };
 
 static void remove_cache_proc_entries(struct cache_detail *cd)
@@ -1555,13 +1550,8 @@
 {
 	struct inode *inode = filp->f_dentry->d_inode;
 	struct cache_detail *cd = RPC_I(inode)->private;
-	long ret;
 
-	lock_kernel();
-	ret = cache_ioctl(inode, filp, cmd, arg, cd);
-	unlock_kernel();
-
-	return ret;
+	return cache_ioctl(inode, filp, cmd, arg, cd);
 }
 
 static int cache_open_pipefs(struct inode *inode, struct file *filp)
@@ -1646,6 +1636,7 @@
 	.read		= read_flush_pipefs,
 	.write		= write_flush_pipefs,
 	.release	= release_flush_pipefs,
+	.llseek		= no_llseek,
 };
 
 int sunrpc_cache_register_pipefs(struct dentry *parent,
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 8c8eef2..28bcd52 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -27,7 +27,6 @@
 #include <linux/workqueue.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
 #include <linux/sunrpc/cache.h>
-#include <linux/smp_lock.h>
 
 static struct vfsmount *rpc_mount __read_mostly;
 static int rpc_mount_count;
@@ -309,40 +308,33 @@
 	return mask;
 }
 
-static int
-rpc_pipe_ioctl_unlocked(struct file *filp, unsigned int cmd, unsigned long arg)
+static long
+rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-	struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
+	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct rpc_inode *rpci = RPC_I(inode);
 	int len;
 
 	switch (cmd) {
 	case FIONREAD:
-		if (rpci->ops == NULL)
+		spin_lock(&inode->i_lock);
+		if (rpci->ops == NULL) {
+			spin_unlock(&inode->i_lock);
 			return -EPIPE;
+		}
 		len = rpci->pipelen;
 		if (filp->private_data) {
 			struct rpc_pipe_msg *msg;
 			msg = (struct rpc_pipe_msg *)filp->private_data;
 			len += msg->len - msg->copied;
 		}
+		spin_unlock(&inode->i_lock);
 		return put_user(len, (int __user *)arg);
 	default:
 		return -EINVAL;
 	}
 }
 
-static long
-rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	long ret;
-
-	lock_kernel();
-	ret = rpc_pipe_ioctl_unlocked(filp, cmd, arg);
-	unlock_kernel();
-
-	return ret;
-}
-
 static const struct file_operations rpc_pipe_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index cace604..aa5dbda 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -376,7 +376,7 @@
 	spin_lock_bh(&queue->lock);
 	res = queue->qlen;
 	spin_unlock_bh(&queue->lock);
-	return (res == 0);
+	return res == 0;
 }
 EXPORT_SYMBOL_GPL(rpc_queue_empty);
 
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index b6309db..fe9306b 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -800,7 +800,7 @@
 	u32 _xid;
 	__be32 *xp;
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	dprintk("RPC:       xs_udp_data_ready...\n");
 	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
@@ -852,7 +852,7 @@
  dropit:
 	skb_free_datagram(sk, skb);
  out:
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
@@ -1229,7 +1229,7 @@
 
 	dprintk("RPC:       xs_tcp_data_ready...\n");
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
 	if (xprt->shutdown)
@@ -1248,7 +1248,7 @@
 		read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
 	} while (read > 0);
 out:
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 }
 
 /*
@@ -1301,7 +1301,7 @@
 {
 	struct rpc_xprt *xprt;
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
 	dprintk("RPC:       xs_tcp_state_change client %p...\n", xprt);
@@ -1313,7 +1313,7 @@
 
 	switch (sk->sk_state) {
 	case TCP_ESTABLISHED:
-		spin_lock_bh(&xprt->transport_lock);
+		spin_lock(&xprt->transport_lock);
 		if (!xprt_test_and_set_connected(xprt)) {
 			struct sock_xprt *transport = container_of(xprt,
 					struct sock_xprt, xprt);
@@ -1327,7 +1327,7 @@
 
 			xprt_wake_pending_tasks(xprt, -EAGAIN);
 		}
-		spin_unlock_bh(&xprt->transport_lock);
+		spin_unlock(&xprt->transport_lock);
 		break;
 	case TCP_FIN_WAIT1:
 		/* The client initiated a shutdown of the socket */
@@ -1365,7 +1365,7 @@
 		xs_sock_mark_closed(xprt);
 	}
  out:
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 }
 
 /**
@@ -1376,7 +1376,7 @@
 {
 	struct rpc_xprt *xprt;
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
 	dprintk("RPC:       %s client %p...\n"
@@ -1384,7 +1384,7 @@
 			__func__, xprt, sk->sk_err);
 	xprt_wake_pending_tasks(xprt, -EAGAIN);
 out:
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static void xs_write_space(struct sock *sk)
@@ -1416,13 +1416,13 @@
  */
 static void xs_udp_write_space(struct sock *sk)
 {
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 
 	/* from net/core/sock.c:sock_def_write_space */
 	if (sock_writeable(sk))
 		xs_write_space(sk);
 
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 }
 
 /**
@@ -1437,13 +1437,13 @@
  */
 static void xs_tcp_write_space(struct sock *sk)
 {
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 
 	/* from net/core/stream.c:sk_stream_write_space */
 	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
 		xs_write_space(sk);
 
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
diff --git a/net/tipc/addr.c b/net/tipc/addr.c
index c048543..8a2e89b 100644
--- a/net/tipc/addr.c
+++ b/net/tipc/addr.c
@@ -41,11 +41,6 @@
 #include "cluster.h"
 #include "net.h"
 
-u32 tipc_get_addr(void)
-{
-	return tipc_own_addr;
-}
-
 /**
  * tipc_addr_domain_valid - validates a network domain address
  *
@@ -89,7 +84,7 @@
 
 int tipc_addr_node_valid(u32 addr)
 {
-	return (tipc_addr_domain_valid(addr) && tipc_node(addr));
+	return tipc_addr_domain_valid(addr) && tipc_node(addr);
 }
 
 int tipc_in_scope(u32 domain, u32 addr)
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index a008c66..22a60fc 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -121,6 +121,9 @@
 
 const char tipc_bclink_name[] = "broadcast-link";
 
+static void tipc_nmap_diff(struct tipc_node_map *nm_a,
+			   struct tipc_node_map *nm_b,
+			   struct tipc_node_map *nm_diff);
 
 static u32 buf_seqno(struct sk_buff *buf)
 {
@@ -143,6 +146,19 @@
 }
 
 
+static void bclink_set_last_sent(void)
+{
+	if (bcl->next_out)
+		bcl->fsm_msg_cnt = mod(buf_seqno(bcl->next_out) - 1);
+	else
+		bcl->fsm_msg_cnt = mod(bcl->next_out_no - 1);
+}
+
+u32 tipc_bclink_get_last_sent(void)
+{
+	return bcl->fsm_msg_cnt;
+}
+
 /**
  * bclink_set_gap - set gap according to contents of current deferred pkt queue
  *
@@ -171,7 +187,7 @@
 
 static int bclink_ack_allowed(u32 n)
 {
-	return((n % TIPC_MIN_LINK_WIN) == tipc_own_tag);
+	return (n % TIPC_MIN_LINK_WIN) == tipc_own_tag;
 }
 
 
@@ -237,8 +253,10 @@
 
 	/* Try resolving broadcast link congestion, if necessary */
 
-	if (unlikely(bcl->next_out))
+	if (unlikely(bcl->next_out)) {
 		tipc_link_push_queue(bcl);
+		bclink_set_last_sent();
+	}
 	if (unlikely(released && !list_empty(&bcl->waiting_ports)))
 		tipc_link_wakeup_ports(bcl, 0);
 	spin_unlock_bh(&bc_lock);
@@ -272,7 +290,7 @@
 	if (!less(n_ptr->bclink.gap_after, n_ptr->bclink.gap_to))
 		return;
 
-	buf = buf_acquire(INT_H_SIZE);
+	buf = tipc_buf_acquire(INT_H_SIZE);
 	if (buf) {
 		msg = buf_msg(buf);
 		tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG,
@@ -395,7 +413,7 @@
 	if (unlikely(res == -ELINKCONG))
 		buf_discard(buf);
 	else
-		bcl->stats.sent_info++;
+		bclink_set_last_sent();
 
 	if (bcl->out_queue_size > bcl->stats.max_queue_sz)
 		bcl->stats.max_queue_sz = bcl->out_queue_size;
@@ -529,15 +547,6 @@
 	tipc_node_unlock(node);
 }
 
-u32 tipc_bclink_get_last_sent(void)
-{
-	u32 last_sent = mod(bcl->next_out_no - 1);
-
-	if (bcl->next_out)
-		last_sent = mod(buf_seqno(bcl->next_out) - 1);
-	return last_sent;
-}
-
 u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr)
 {
 	return (n_ptr->bclink.supported &&
@@ -570,6 +579,7 @@
 		msg = buf_msg(buf);
 		msg_set_non_seq(msg, 1);
 		msg_set_mc_netid(msg, tipc_net_id);
+		bcl->stats.sent_info++;
 	}
 
 	/* Send buffer over bearers until all targets reached */
@@ -609,11 +619,13 @@
 		bcbearer->remains = bcbearer->remains_new;
 	}
 
-	/* Unable to reach all targets */
+	/*
+	 * Unable to reach all targets (indicate success, since currently
+	 * there isn't code in place to properly block & unblock the
+	 * pseudo-bearer used by the broadcast link)
+	 */
 
-	bcbearer->bearer.publ.blocked = 1;
-	bcl->stats.bearer_congs++;
-	return 1;
+	return TIPC_OK;
 }
 
 /**
@@ -862,8 +874,9 @@
  * @nm_diff: output node map A-B (i.e. nodes of A that are not in B)
  */
 
-void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b,
-				  struct tipc_node_map *nm_diff)
+static void tipc_nmap_diff(struct tipc_node_map *nm_a,
+			   struct tipc_node_map *nm_b,
+			   struct tipc_node_map *nm_diff)
 {
 	int stop = ARRAY_SIZE(nm_a->map);
 	int w;
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index e8c2b81..011c03f 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -84,9 +84,6 @@
 	return !memcmp(nm_a, nm_b, sizeof(*nm_a));
 }
 
-void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b,
-				  struct tipc_node_map *nm_diff);
-
 void tipc_port_list_add(struct port_list *pl_ptr, u32 port);
 void tipc_port_list_free(struct port_list *pl_ptr);
 
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 52ae17b..9927d1d 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -63,7 +63,7 @@
 	len = strlen(name);
 	if ((len + 1) > TIPC_MAX_MEDIA_NAME)
 		return 0;
-	return (strspn(name, tipc_alphabet) == len);
+	return strspn(name, tipc_alphabet) == len;
 }
 
 /**
@@ -288,9 +288,6 @@
 	struct bearer *b_ptr;
 	u32 i;
 
-	if (tipc_mode != TIPC_NET_MODE)
-		return NULL;
-
 	for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
 		if (b_ptr->active && (!strcmp(b_ptr->publ.name, name)))
 			return b_ptr;
@@ -559,8 +556,6 @@
 	}
 
 	b_ptr = &tipc_bearers[bearer_id];
-	memset(b_ptr, 0, sizeof(struct bearer));
-
 	strcpy(b_ptr->publ.name, name);
 	res = m_ptr->enable_bearer(&b_ptr->publ);
 	if (res) {
@@ -630,30 +625,17 @@
  * Note: This routine assumes caller holds tipc_net_lock.
  */
 
-static int bearer_disable(const char *name)
+static int bearer_disable(struct bearer *b_ptr)
 {
-	struct bearer *b_ptr;
 	struct link *l_ptr;
 	struct link *temp_l_ptr;
 
-	b_ptr = bearer_find(name);
-	if (!b_ptr) {
-		warn("Attempt to disable unknown bearer <%s>\n", name);
-		return -EINVAL;
-	}
-
-	info("Disabling bearer <%s>\n", name);
+	info("Disabling bearer <%s>\n", b_ptr->publ.name);
 	tipc_disc_stop_link_req(b_ptr->link_req);
 	spin_lock_bh(&b_ptr->publ.lock);
 	b_ptr->link_req = NULL;
 	b_ptr->publ.blocked = 1;
-	if (b_ptr->media->disable_bearer) {
-		spin_unlock_bh(&b_ptr->publ.lock);
-		write_unlock_bh(&tipc_net_lock);
-		b_ptr->media->disable_bearer(&b_ptr->publ);
-		write_lock_bh(&tipc_net_lock);
-		spin_lock_bh(&b_ptr->publ.lock);
-	}
+	b_ptr->media->disable_bearer(&b_ptr->publ);
 	list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
 		tipc_link_delete(l_ptr);
 	}
@@ -664,10 +646,16 @@
 
 int tipc_disable_bearer(const char *name)
 {
+	struct bearer *b_ptr;
 	int res;
 
 	write_lock_bh(&tipc_net_lock);
-	res = bearer_disable(name);
+	b_ptr = bearer_find(name);
+	if (b_ptr == NULL) {
+		warn("Attempt to disable unknown bearer <%s>\n", name);
+		res = -EINVAL;
+	} else
+		res = bearer_disable(b_ptr);
 	write_unlock_bh(&tipc_net_lock);
 	return res;
 }
@@ -680,13 +668,7 @@
 
 	for (i = 0; i < MAX_BEARERS; i++) {
 		if (tipc_bearers[i].active)
-			tipc_bearers[i].publ.blocked = 1;
-	}
-	for (i = 0; i < MAX_BEARERS; i++) {
-		if (tipc_bearers[i].active)
-			bearer_disable(tipc_bearers[i].publ.name);
+			bearer_disable(&tipc_bearers[i]);
 	}
 	media_count = 0;
 }
-
-
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c
index e68f705..7fea14b 100644
--- a/net/tipc/cluster.c
+++ b/net/tipc/cluster.c
@@ -113,25 +113,6 @@
 	kfree(c_ptr);
 }
 
-u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr)
-{
-	struct tipc_node *n_ptr;
-	u32 n_num = tipc_node(addr) + 1;
-
-	if (!c_ptr)
-		return addr;
-	for (; n_num <= c_ptr->highest_node; n_num++) {
-		n_ptr = c_ptr->nodes[n_num];
-		if (n_ptr && tipc_node_has_active_links(n_ptr))
-			return n_ptr->addr;
-	}
-	for (n_num = 1; n_num < tipc_node(addr); n_num++) {
-		n_ptr = c_ptr->nodes[n_num];
-		if (n_ptr && tipc_node_has_active_links(n_ptr))
-			return n_ptr->addr;
-	}
-	return 0;
-}
 
 void tipc_cltr_attach_node(struct cluster *c_ptr, struct tipc_node *n_ptr)
 {
@@ -232,7 +213,7 @@
 static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest)
 {
 	u32 size = INT_H_SIZE + data_size;
-	struct sk_buff *buf = buf_acquire(size);
+	struct sk_buff *buf = tipc_buf_acquire(size);
 	struct tipc_msg *msg;
 
 	if (buf) {
diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h
index 333efb0..32636d9 100644
--- a/net/tipc/cluster.h
+++ b/net/tipc/cluster.h
@@ -75,7 +75,7 @@
 void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest);
 void tipc_cltr_broadcast(struct sk_buff *buf);
 int tipc_cltr_init(void);
-u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr);
+
 void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
 void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest);
 void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
diff --git a/net/tipc/config.c b/net/tipc/config.c
index 961d1b0..50a6133 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -95,7 +95,7 @@
 	return 1;
 }
 
-struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value)
+static struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value)
 {
 	struct sk_buff *buf;
 	__be32 value_net;
@@ -109,6 +109,11 @@
 	return buf;
 }
 
+static struct sk_buff *tipc_cfg_reply_unsigned(u32 value)
+{
+	return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
+}
+
 struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string)
 {
 	struct sk_buff *buf;
@@ -120,139 +125,6 @@
 	return buf;
 }
 
-
-#if 0
-
-/* Now obsolete code for handling commands not yet implemented the new way */
-
-/*
- * Some of this code assumed that the manager structure contains two added
- * fields:
- *	u32 link_subscriptions;
- *	struct list_head link_subscribers;
- * which are currently not present.  These fields may need to be re-introduced
- * if and when support for link subscriptions is added.
- */
-
-void tipc_cfg_link_event(u32 addr, char *name, int up)
-{
-	/* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */
-}
-
-int tipc_cfg_cmd(const struct tipc_cmd_msg * msg,
-		 char *data,
-		 u32 sz,
-		 u32 *ret_size,
-		 struct tipc_portid *orig)
-{
-	int rv = -EINVAL;
-	u32 cmd = msg->cmd;
-
-	*ret_size = 0;
-	switch (cmd) {
-	case TIPC_REMOVE_LINK:
-	case TIPC_CMD_BLOCK_LINK:
-	case TIPC_CMD_UNBLOCK_LINK:
-		if (!cfg_check_connection(orig))
-			rv = link_control(msg->argv.link_name, msg->cmd, 0);
-		break;
-	case TIPC_ESTABLISH:
-		{
-			int connected;
-
-			tipc_isconnected(mng.conn_port_ref, &connected);
-			if (connected || !orig) {
-				rv = TIPC_FAILURE;
-				break;
-			}
-			rv = tipc_connect2port(mng.conn_port_ref, orig);
-			if (rv == TIPC_OK)
-				orig = 0;
-			break;
-		}
-	case TIPC_GET_PEER_ADDRESS:
-		*ret_size = link_peer_addr(msg->argv.link_name, data, sz);
-		break;
-	case TIPC_GET_ROUTES:
-		rv = TIPC_OK;
-		break;
-	default: {}
-	}
-	if (*ret_size)
-		rv = TIPC_OK;
-	return rv;
-}
-
-static void cfg_cmd_event(struct tipc_cmd_msg *msg,
-			  char *data,
-			  u32 sz,
-			  struct tipc_portid const *orig)
-{
-	int rv = -EINVAL;
-	struct tipc_cmd_result_msg rmsg;
-	struct iovec msg_sect[2];
-	int *arg;
-
-	msg->cmd = ntohl(msg->cmd);
-
-	cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect,
-			    data, 0);
-	if (ntohl(msg->magic) != TIPC_MAGIC)
-		goto exit;
-
-	switch (msg->cmd) {
-	case TIPC_CREATE_LINK:
-		if (!cfg_check_connection(orig))
-			rv = disc_create_link(&msg->argv.create_link);
-		break;
-	case TIPC_LINK_SUBSCRIBE:
-		{
-			struct subscr_data *sub;
-
-			if (mng.link_subscriptions > 64)
-				break;
-			sub = kmalloc(sizeof(*sub),
-							    GFP_ATOMIC);
-			if (sub == NULL) {
-				warn("Memory squeeze; dropped remote link subscription\n");
-				break;
-			}
-			INIT_LIST_HEAD(&sub->subd_list);
-			tipc_createport(mng.user_ref,
-					(void *)sub,
-					TIPC_HIGH_IMPORTANCE,
-					0,
-					0,
-					(tipc_conn_shutdown_event)cfg_linksubscr_cancel,
-					0,
-					0,
-					(tipc_conn_msg_event)cfg_linksubscr_cancel,
-					0,
-					&sub->port_ref);
-			if (!sub->port_ref) {
-				kfree(sub);
-				break;
-			}
-			memcpy(sub->usr_handle,msg->usr_handle,
-			       sizeof(sub->usr_handle));
-			sub->domain = msg->argv.domain;
-			list_add_tail(&sub->subd_list, &mng.link_subscribers);
-			tipc_connect2port(sub->port_ref, orig);
-			rmsg.retval = TIPC_OK;
-			tipc_send(sub->port_ref, 2u, msg_sect);
-			mng.link_subscriptions++;
-			return;
-		}
-	default:
-		rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig);
-	}
-exit:
-	rmsg.result_len = htonl(msg_sect[1].iov_len);
-	rmsg.retval = htonl(rv);
-	tipc_cfg_respond(msg_sect, 2u, orig);
-}
-#endif
-
 #define MAX_STATS_INFO 2000
 
 static struct sk_buff *tipc_show_stats(void)
@@ -557,14 +429,6 @@
 	case TIPC_CMD_SHOW_PORTS:
 		rep_tlv_buf = tipc_port_get_ports();
 		break;
-#if 0
-	case TIPC_CMD_SHOW_PORT_STATS:
-		rep_tlv_buf = port_show_stats(req_tlv_area, req_tlv_space);
-		break;
-	case TIPC_CMD_RESET_PORT_STATS:
-		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED);
-		break;
-#endif
 	case TIPC_CMD_SET_LOG_SIZE:
 		rep_tlv_buf = tipc_log_resize_cmd(req_tlv_area, req_tlv_space);
 		break;
diff --git a/net/tipc/config.h b/net/tipc/config.h
index 5cd7cc5..481e12e 100644
--- a/net/tipc/config.h
+++ b/net/tipc/config.h
@@ -45,7 +45,6 @@
 struct sk_buff *tipc_cfg_reply_alloc(int payload_size);
 int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
 			void *tlv_data, int tlv_data_size);
-struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value);
 struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string);
 
 static inline struct sk_buff *tipc_cfg_reply_none(void)
@@ -53,11 +52,6 @@
 	return tipc_cfg_reply_alloc(0);
 }
 
-static inline struct sk_buff *tipc_cfg_reply_unsigned(u32 value)
-{
-	return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
-}
-
 static inline struct sk_buff *tipc_cfg_reply_error_string(char *string)
 {
 	return tipc_cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string);
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 6964681..e2a09eb 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -96,13 +96,8 @@
 int tipc_remote_management;
 
 
-int tipc_get_mode(void)
-{
-	return tipc_mode;
-}
-
 /**
- * buf_acquire - creates a TIPC message buffer
+ * tipc_buf_acquire - creates a TIPC message buffer
  * @size: message size (including TIPC header)
  *
  * Returns a new buffer with data pointers set to the specified size.
@@ -111,7 +106,7 @@
  *       There may also be unrequested tailroom present at the buffer's end.
  */
 
-struct sk_buff *buf_acquire(u32 size)
+struct sk_buff *tipc_buf_acquire(u32 size)
 {
 	struct sk_buff *skb;
 	unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
@@ -129,7 +124,7 @@
  * tipc_core_stop_net - shut down TIPC networking sub-systems
  */
 
-void tipc_core_stop_net(void)
+static void tipc_core_stop_net(void)
 {
 	tipc_eth_media_stop();
 	tipc_net_stop();
@@ -154,7 +149,7 @@
  * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode
  */
 
-void tipc_core_stop(void)
+static void tipc_core_stop(void)
 {
 	if (tipc_mode != TIPC_NODE_MODE)
 		return;
@@ -169,13 +164,14 @@
 	tipc_nametbl_stop();
 	tipc_ref_table_stop();
 	tipc_socket_stop();
+	tipc_log_resize(0);
 }
 
 /**
  * tipc_core_start - switch TIPC from NOT RUNNING to SINGLE NODE mode
  */
 
-int tipc_core_start(void)
+static int tipc_core_start(void)
 {
 	int res;
 
@@ -203,7 +199,9 @@
 {
 	int res;
 
-	tipc_log_resize(CONFIG_TIPC_LOG);
+	if (tipc_log_resize(CONFIG_TIPC_LOG) != 0)
+		warn("Unable to create log buffer\n");
+
 	info("Activated (version " TIPC_MOD_VER
 	     " compiled " __DATE__ " " __TIME__ ")\n");
 
@@ -230,7 +228,6 @@
 	tipc_core_stop_net();
 	tipc_core_stop();
 	info("Deactivated\n");
-	tipc_log_resize(0);
 }
 
 module_init(tipc_init);
@@ -244,8 +241,6 @@
 
 EXPORT_SYMBOL(tipc_attach);
 EXPORT_SYMBOL(tipc_detach);
-EXPORT_SYMBOL(tipc_get_addr);
-EXPORT_SYMBOL(tipc_get_mode);
 EXPORT_SYMBOL(tipc_createport);
 EXPORT_SYMBOL(tipc_deleteport);
 EXPORT_SYMBOL(tipc_ownidentity);
@@ -260,23 +255,10 @@
 EXPORT_SYMBOL(tipc_connect2port);
 EXPORT_SYMBOL(tipc_disconnect);
 EXPORT_SYMBOL(tipc_shutdown);
-EXPORT_SYMBOL(tipc_isconnected);
-EXPORT_SYMBOL(tipc_peer);
-EXPORT_SYMBOL(tipc_ref_valid);
 EXPORT_SYMBOL(tipc_send);
-EXPORT_SYMBOL(tipc_send_buf);
 EXPORT_SYMBOL(tipc_send2name);
-EXPORT_SYMBOL(tipc_forward2name);
-EXPORT_SYMBOL(tipc_send_buf2name);
-EXPORT_SYMBOL(tipc_forward_buf2name);
 EXPORT_SYMBOL(tipc_send2port);
-EXPORT_SYMBOL(tipc_forward2port);
-EXPORT_SYMBOL(tipc_send_buf2port);
-EXPORT_SYMBOL(tipc_forward_buf2port);
 EXPORT_SYMBOL(tipc_multicast);
-/* EXPORT_SYMBOL(tipc_multicast_buf); not available yet */
-EXPORT_SYMBOL(tipc_ispublished);
-EXPORT_SYMBOL(tipc_available_nodes);
 
 /* TIPC API for external bearers (see tipc_bearer.h) */
 
@@ -293,6 +275,4 @@
 EXPORT_SYMBOL(tipc_reject_msg);
 EXPORT_SYMBOL(tipc_send_buf_fast);
 EXPORT_SYMBOL(tipc_acknowledge);
-EXPORT_SYMBOL(tipc_get_port);
-EXPORT_SYMBOL(tipc_get_handle);
 
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 1887990..e19389e 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -83,9 +83,7 @@
  * Note: TIPC_LOG is configured to echo its output to the system console;
  *       user-defined buffers can be configured to do the same thing.
  */
-
 extern struct print_buf *const TIPC_NULL;
-extern struct print_buf *const TIPC_CONS;
 extern struct print_buf *const TIPC_LOG;
 
 void tipc_printf(struct print_buf *, const char *fmt, ...);
@@ -204,10 +202,7 @@
  * Routines available to privileged subsystems
  */
 
-extern int  tipc_core_start(void);
-extern void tipc_core_stop(void);
-extern int  tipc_core_start_net(unsigned long addr);
-extern void tipc_core_stop_net(void);
+extern int tipc_core_start_net(unsigned long);
 extern int  tipc_handler_start(void);
 extern void tipc_handler_stop(void);
 extern int  tipc_netlink_start(void);
@@ -328,7 +323,7 @@
 	return (struct tipc_msg *)skb->data;
 }
 
-extern struct sk_buff *buf_acquire(u32 size);
+extern struct sk_buff *tipc_buf_acquire(u32 size);
 
 /**
  * buf_discard - frees a TIPC message buffer
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
index 1885a7e..46f51d2 100644
--- a/net/tipc/dbg.c
+++ b/net/tipc/dbg.c
@@ -52,7 +52,7 @@
 struct print_buf *const TIPC_NULL = &null_buf;
 
 static struct print_buf cons_buf = { NULL, 0, NULL, 1 };
-struct print_buf *const TIPC_CONS = &cons_buf;
+static struct print_buf *const TIPC_CONS = &cons_buf;
 
 static struct print_buf log_buf = { NULL, 0, NULL, 1 };
 struct print_buf *const TIPC_LOG = &log_buf;
@@ -76,6 +76,10 @@
 static char print_string[TIPC_PB_MAX_STR];
 static DEFINE_SPINLOCK(print_lock);
 
+static void tipc_printbuf_reset(struct print_buf *pb);
+static int  tipc_printbuf_empty(struct print_buf *pb);
+static void tipc_printbuf_move(struct print_buf *pb_to,
+			       struct print_buf *pb_from);
 
 #define FORMAT(PTR,LEN,FMT) \
 {\
@@ -116,7 +120,7 @@
  * @pb: pointer to print buffer structure
  */
 
-void tipc_printbuf_reset(struct print_buf *pb)
+static void tipc_printbuf_reset(struct print_buf *pb)
 {
 	if (pb->buf) {
 		pb->crs = pb->buf;
@@ -132,9 +136,9 @@
  * Returns non-zero if print buffer is empty.
  */
 
-int tipc_printbuf_empty(struct print_buf *pb)
+static int tipc_printbuf_empty(struct print_buf *pb)
 {
-	return (!pb->buf || (pb->crs == pb->buf));
+	return !pb->buf || (pb->crs == pb->buf);
 }
 
 /**
@@ -169,7 +173,7 @@
 			tipc_printf(pb, err);
 		}
 	}
-	return (pb->crs - pb->buf + 1);
+	return pb->crs - pb->buf + 1;
 }
 
 /**
@@ -181,7 +185,8 @@
  * Source print buffer becomes empty if a successful move occurs.
  */
 
-void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
+static void tipc_printbuf_move(struct print_buf *pb_to,
+			       struct print_buf *pb_from)
 {
 	int len;
 
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h
index 5ef1bc8..3ba6ba8 100644
--- a/net/tipc/dbg.h
+++ b/net/tipc/dbg.h
@@ -56,10 +56,7 @@
 #define TIPC_PB_MAX_STR 512	/* max printable string (with trailing NUL) */
 
 void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 size);
-void tipc_printbuf_reset(struct print_buf *pb);
-int  tipc_printbuf_empty(struct print_buf *pb);
 int  tipc_printbuf_validate(struct print_buf *pb);
-void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from);
 
 int tipc_log_resize(int log_size);
 
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index fc1fcf5..4a7cd37 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -46,16 +46,6 @@
 #define TIPC_LINK_REQ_FAST	2000	/* normal delay if bearer has no links */
 #define TIPC_LINK_REQ_SLOW	600000	/* normal delay if bearer has links */
 
-#if 0
-#define  GET_NODE_INFO         300
-#define  GET_NODE_INFO_RESULT  301
-#define  FORWARD_LINK_PROBE    302
-#define  LINK_REQUEST_REJECTED 303
-#define  LINK_REQUEST_ACCEPTED 304
-#define  DROP_LINK_REQUEST     305
-#define  CHECK_LINK_COUNT      306
-#endif
-
 /*
  * TODO: Most of the inter-cluster setup stuff should be
  * rewritten, and be made conformant with specification.
@@ -78,30 +68,6 @@
 	unsigned int timer_intv;
 };
 
-
-#if 0
-int disc_create_link(const struct tipc_link_create *argv)
-{
-	/*
-	 * Code for inter cluster link setup here
-	 */
-	return TIPC_OK;
-}
-#endif
-
-/*
- * disc_lost_link(): A link has lost contact
- */
-
-void tipc_disc_link_event(u32 addr, char *name, int up)
-{
-	if (in_own_cluster(addr))
-		return;
-	/*
-	 * Code for inter cluster link setup here
-	 */
-}
-
 /**
  * tipc_disc_init_msg - initialize a link setup message
  * @type: message type (request or response)
@@ -115,7 +81,7 @@
 					  u32 dest_domain,
 					  struct bearer *b_ptr)
 {
-	struct sk_buff *buf = buf_acquire(DSC_H_SIZE);
+	struct sk_buff *buf = tipc_buf_acquire(DSC_H_SIZE);
 	struct tipc_msg *msg;
 
 	if (buf) {
@@ -203,6 +169,14 @@
 				return;
 		}
 		spin_lock_bh(&n_ptr->lock);
+
+		/* Don't talk to neighbor during cleanup after last session */
+
+		if (n_ptr->cleanup_required) {
+			spin_unlock_bh(&n_ptr->lock);
+			return;
+		}
+
 		link = n_ptr->links[b_ptr->identity];
 		if (!link) {
 			dbg("creating link\n");
diff --git a/net/tipc/discover.h b/net/tipc/discover.h
index c36eaeb..f8e7506 100644
--- a/net/tipc/discover.h
+++ b/net/tipc/discover.h
@@ -50,9 +50,4 @@
 
 void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr);
 
-void tipc_disc_link_event(u32 addr, char *name, int up);
-#if 0
-int  disc_create_link(const struct tipc_link_create *argv);
-#endif
-
 #endif
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 6230d16..6e988ba 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -72,17 +72,26 @@
 {
 	struct sk_buff *clone;
 	struct net_device *dev;
+	int delta;
 
 	clone = skb_clone(buf, GFP_ATOMIC);
-	if (clone) {
-		skb_reset_network_header(clone);
-		dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev;
-		clone->dev = dev;
-		dev_hard_header(clone, dev, ETH_P_TIPC,
-				 &dest->dev_addr.eth_addr,
-				 dev->dev_addr, clone->len);
-		dev_queue_xmit(clone);
+	if (!clone)
+		return 0;
+
+	dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev;
+	delta = dev->hard_header_len - skb_headroom(buf);
+
+	if ((delta > 0) &&
+	    pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
+		kfree_skb(clone);
+		return 0;
 	}
+
+	skb_reset_network_header(clone);
+	clone->dev = dev;
+	dev_hard_header(clone, dev, ETH_P_TIPC, &dest->dev_addr.eth_addr,
+			dev->dev_addr, clone->len);
+	dev_queue_xmit(clone);
 	return 0;
 }
 
@@ -92,15 +101,12 @@
  * Accept only packets explicitly sent to this node, or broadcast packets;
  * ignores packets sent using Ethernet multicast, and traffic sent to other
  * nodes (which can happen if interface is running in promiscuous mode).
- * Routine truncates any Ethernet padding/CRC appended to the message,
- * and ensures message size matches actual length
  */
 
 static int recv_msg(struct sk_buff *buf, struct net_device *dev,
 		    struct packet_type *pt, struct net_device *orig_dev)
 {
 	struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv;
-	u32 size;
 
 	if (!net_eq(dev_net(dev), &init_net)) {
 		kfree_skb(buf);
@@ -109,13 +115,9 @@
 
 	if (likely(eb_ptr->bearer)) {
 		if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
-			size = msg_size((struct tipc_msg *)buf->data);
-			skb_trim(buf, size);
-			if (likely(buf->len == size)) {
-				buf->next = NULL;
-				tipc_recv_msg(buf, eb_ptr->bearer);
-				return 0;
-			}
+			buf->next = NULL;
+			tipc_recv_msg(buf, eb_ptr->bearer);
+			return 0;
 		}
 	}
 	kfree_skb(buf);
@@ -133,6 +135,16 @@
 	struct eth_bearer *eb_ptr = &eth_bearers[0];
 	struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
 	char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
+	int pending_dev = 0;
+
+	/* Find unused Ethernet bearer structure */
+
+	while (eb_ptr->dev) {
+		if (!eb_ptr->bearer)
+			pending_dev++;
+		if (++eb_ptr == stop)
+			return pending_dev ? -EAGAIN : -EDQUOT;
+	}
 
 	/* Find device with specified name */
 
diff --git a/net/tipc/link.c b/net/tipc/link.c
index a3616b9..b31992c 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -99,23 +99,6 @@
 	char if_peer[TIPC_MAX_IF_NAME];
 };
 
-#if 0
-
-/* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */
-
-/**
- * struct link_event - link up/down event notification
- */
-
-struct link_event {
-	u32 addr;
-	int up;
-	void (*fcn)(u32, char *, int);
-	char name[TIPC_MAX_LINK_NAME];
-};
-
-#endif
-
 static void link_handle_out_of_seq_msg(struct link *l_ptr,
 				       struct sk_buff *buf);
 static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf);
@@ -129,6 +112,9 @@
 static void link_reset_statistics(struct link *l_ptr);
 static void link_print(struct link *l_ptr, struct print_buf *buf,
 		       const char *str);
+static void link_start(struct link *l_ptr);
+static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf);
+
 
 /*
  * Debugging code used by link routines only
@@ -239,13 +225,13 @@
 {
 	if (!l_ptr)
 		return 0;
-	return (link_working_working(l_ptr) || link_working_unknown(l_ptr));
+	return link_working_working(l_ptr) || link_working_unknown(l_ptr);
 }
 
 int tipc_link_is_active(struct link *l_ptr)
 {
-	return ((l_ptr->owner->active_links[0] == l_ptr) ||
-		(l_ptr->owner->active_links[1] == l_ptr));
+	return	(l_ptr->owner->active_links[0] == l_ptr) ||
+		(l_ptr->owner->active_links[1] == l_ptr);
 }
 
 /**
@@ -459,7 +445,7 @@
 
 	k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr);
 	list_add_tail(&l_ptr->link_list, &b_ptr->links);
-	tipc_k_signal((Handler)tipc_link_start, (unsigned long)l_ptr);
+	tipc_k_signal((Handler)link_start, (unsigned long)l_ptr);
 
 	dbg("tipc_link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n",
 	    l_ptr->tolerance, l_ptr->continuity_interval, l_ptr->abort_limit);
@@ -499,9 +485,9 @@
 	kfree(l_ptr);
 }
 
-void tipc_link_start(struct link *l_ptr)
+static void link_start(struct link *l_ptr)
 {
-	dbg("tipc_link_start %x\n", l_ptr);
+	dbg("link_start %x\n", l_ptr);
 	link_state_event(l_ptr, STARTING_EVT);
 }
 
@@ -634,39 +620,9 @@
 	l_ptr->proto_msg_queue = NULL;
 }
 
-#if 0
-
 /* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */
-
-static void link_recv_event(struct link_event *ev)
-{
-	ev->fcn(ev->addr, ev->name, ev->up);
-	kfree(ev);
-}
-
-static void link_send_event(void (*fcn)(u32 a, char *n, int up),
-			    struct link *l_ptr, int up)
-{
-	struct link_event *ev;
-
-	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
-	if (!ev) {
-		warn("Link event allocation failure\n");
-		return;
-	}
-	ev->addr = l_ptr->addr;
-	ev->up = up;
-	ev->fcn = fcn;
-	memcpy(ev->name, l_ptr->name, TIPC_MAX_LINK_NAME);
-	tipc_k_signal((Handler)link_recv_event, (unsigned long)ev);
-}
-
-#else
-
 #define link_send_event(fcn, l_ptr, up) do { } while (0)
 
-#endif
-
 void tipc_link_reset(struct link *l_ptr)
 {
 	struct sk_buff *buf;
@@ -690,10 +646,7 @@
 
 	tipc_node_link_down(l_ptr->owner, l_ptr);
 	tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);
-#if 0
-	tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name);
-	dbg_link_dump();
-#endif
+
 	if (was_active_link && tipc_node_has_active_links(l_ptr->owner) &&
 	    l_ptr->owner->permit_changeover) {
 		l_ptr->reset_checkpoint = checkpoint;
@@ -1050,7 +1003,7 @@
 	/* Fragmentation needed ? */
 
 	if (size > max_packet)
-		return tipc_link_send_long_buf(l_ptr, buf);
+		return link_send_long_buf(l_ptr, buf);
 
 	/* Packet can be queued or sent: */
 
@@ -1086,7 +1039,7 @@
 		/* Try creating a new bundle */
 
 		if (size <= max_packet * 2 / 3) {
-			struct sk_buff *bundler = buf_acquire(max_packet);
+			struct sk_buff *bundler = tipc_buf_acquire(max_packet);
 			struct tipc_msg bundler_hdr;
 
 			if (bundler) {
@@ -1362,7 +1315,7 @@
 
 	/* Prepare header of first fragment: */
 
-	buf_chain = buf = buf_acquire(max_pkt);
+	buf_chain = buf = tipc_buf_acquire(max_pkt);
 	if (!buf)
 		return -ENOMEM;
 	buf->next = NULL;
@@ -1419,7 +1372,7 @@
 			msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE);
 			msg_set_fragm_no(&fragm_hdr, ++fragm_no);
 			prev = buf;
-			buf = buf_acquire(fragm_sz + INT_H_SIZE);
+			buf = tipc_buf_acquire(fragm_sz + INT_H_SIZE);
 			if (!buf)
 				goto error;
 
@@ -1802,6 +1755,15 @@
 	return pskb_may_pull(buf, hdr_size);
 }
 
+/**
+ * tipc_recv_msg - process TIPC messages arriving from off-node
+ * @head: pointer to message buffer chain
+ * @tb_ptr: pointer to bearer message arrived on
+ *
+ * Invoked with no locks held.  Bearer pointer must point to a valid bearer
+ * structure (i.e. cannot be NULL), but bearer can be inactive.
+ */
+
 void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
 {
 	read_lock_bh(&tipc_net_lock);
@@ -1819,6 +1781,11 @@
 
 		head = head->next;
 
+		/* Ensure bearer is still enabled */
+
+		if (unlikely(!b_ptr->active))
+			goto cont;
+
 		/* Ensure message is well-formed */
 
 		if (unlikely(!link_recv_buf_validate(buf)))
@@ -1855,13 +1822,22 @@
 				goto cont;
 		}
 
-		/* Locate unicast link endpoint that should handle message */
+		/* Locate neighboring node that sent message */
 
 		n_ptr = tipc_node_find(msg_prevnode(msg));
 		if (unlikely(!n_ptr))
 			goto cont;
 		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);
+			goto cont;
+		}
+
+		/* Locate unicast link endpoint that should handle message */
+
 		l_ptr = n_ptr->links[b_ptr->identity];
 		if (unlikely(!l_ptr)) {
 			tipc_node_unlock(n_ptr);
@@ -2172,7 +2148,7 @@
 	if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) {
 		if (!l_ptr->proto_msg_queue) {
 			l_ptr->proto_msg_queue =
-				buf_acquire(sizeof(l_ptr->proto_msg));
+				tipc_buf_acquire(sizeof(l_ptr->proto_msg));
 		}
 		buf = l_ptr->proto_msg_queue;
 		if (!buf)
@@ -2186,7 +2162,7 @@
 
 	msg_dbg(msg, ">>");
 
-	buf = buf_acquire(msg_size);
+	buf = tipc_buf_acquire(msg_size);
 	if (!buf)
 		return;
 
@@ -2345,10 +2321,10 @@
  * tipc_link_tunnel(): Send one message via a link belonging to
  * another bearer. Owner node is locked.
  */
-void tipc_link_tunnel(struct link *l_ptr,
-		      struct tipc_msg *tunnel_hdr,
-		      struct tipc_msg  *msg,
-		      u32 selector)
+static void tipc_link_tunnel(struct link *l_ptr,
+			     struct tipc_msg *tunnel_hdr,
+			     struct tipc_msg  *msg,
+			     u32 selector)
 {
 	struct link *tunnel;
 	struct sk_buff *buf;
@@ -2361,7 +2337,7 @@
 		return;
 	}
 	msg_set_size(tunnel_hdr, length + INT_H_SIZE);
-	buf = buf_acquire(length + INT_H_SIZE);
+	buf = tipc_buf_acquire(length + INT_H_SIZE);
 	if (!buf) {
 		warn("Link changeover error, "
 		     "unable to send tunnel msg\n");
@@ -2407,7 +2383,7 @@
 	if (!l_ptr->first_out) {
 		struct sk_buff *buf;
 
-		buf = buf_acquire(INT_H_SIZE);
+		buf = tipc_buf_acquire(INT_H_SIZE);
 		if (buf) {
 			skb_copy_to_linear_data(buf, &tunnel_hdr, INT_H_SIZE);
 			msg_set_size(&tunnel_hdr, INT_H_SIZE);
@@ -2468,7 +2444,7 @@
 		msg_set_ack(msg, mod(l_ptr->next_in_no - 1));	/* Update */
 		msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
 		msg_set_size(&tunnel_hdr, length + INT_H_SIZE);
-		outbuf = buf_acquire(length + INT_H_SIZE);
+		outbuf = tipc_buf_acquire(length + INT_H_SIZE);
 		if (outbuf == NULL) {
 			warn("Link changeover error, "
 			     "unable to send duplicate msg\n");
@@ -2504,7 +2480,7 @@
 	u32 size = msg_size(msg);
 	struct sk_buff *eb;
 
-	eb = buf_acquire(size);
+	eb = tipc_buf_acquire(size);
 	if (eb)
 		skb_copy_to_linear_data(eb, msg, size);
 	return eb;
@@ -2632,11 +2608,11 @@
 
 
 /*
- * tipc_link_send_long_buf: Entry for buffers needing fragmentation.
+ * link_send_long_buf: Entry for buffers needing fragmentation.
  * The buffer is complete, inclusive total message length.
  * Returns user data length.
  */
-int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
+static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
 {
 	struct tipc_msg *inmsg = buf_msg(buf);
 	struct tipc_msg fragm_hdr;
@@ -2675,7 +2651,7 @@
 			fragm_sz = rest;
 			msg_set_type(&fragm_hdr, LAST_FRAGMENT);
 		}
-		fragm = buf_acquire(fragm_sz + INT_H_SIZE);
+		fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE);
 		if (fragm == NULL) {
 			warn("Link unable to fragment message\n");
 			dsz = -ENOMEM;
@@ -2780,7 +2756,7 @@
 			buf_discard(fbuf);
 			return 0;
 		}
-		pbuf = buf_acquire(msg_size(imsg));
+		pbuf = tipc_buf_acquire(msg_size(imsg));
 		if (pbuf != NULL) {
 			pbuf->next = *pending;
 			*pending = pbuf;
@@ -3174,44 +3150,6 @@
 	return buf;
 }
 
-#if 0
-int link_control(const char *name, u32 op, u32 val)
-{
-	int res = -EINVAL;
-	struct link *l_ptr;
-	u32 bearer_id;
-	struct tipc_node * node;
-	u32 a;
-
-	a = link_name2addr(name, &bearer_id);
-	read_lock_bh(&tipc_net_lock);
-	node = tipc_node_find(a);
-	if (node) {
-		tipc_node_lock(node);
-		l_ptr = node->links[bearer_id];
-		if (l_ptr) {
-			if (op == TIPC_REMOVE_LINK) {
-				struct bearer *b_ptr = l_ptr->b_ptr;
-				spin_lock_bh(&b_ptr->publ.lock);
-				tipc_link_delete(l_ptr);
-				spin_unlock_bh(&b_ptr->publ.lock);
-			}
-			if (op == TIPC_CMD_BLOCK_LINK) {
-				tipc_link_reset(l_ptr);
-				l_ptr->blocked = 1;
-			}
-			if (op == TIPC_CMD_UNBLOCK_LINK) {
-				l_ptr->blocked = 0;
-			}
-			res = 0;
-		}
-		tipc_node_unlock(node);
-	}
-	read_unlock_bh(&tipc_net_lock);
-	return res;
-}
-#endif
-
 /**
  * tipc_link_get_max_pkt - get maximum packet size to use when sending to destination
  * @dest: network address of destination node
@@ -3242,28 +3180,6 @@
 	return res;
 }
 
-#if 0
-static void link_dump_rec_queue(struct link *l_ptr)
-{
-	struct sk_buff *crs;
-
-	if (!l_ptr->oldest_deferred_in) {
-		info("Reception queue empty\n");
-		return;
-	}
-	info("Contents of Reception queue:\n");
-	crs = l_ptr->oldest_deferred_in;
-	while (crs) {
-		if (crs->data == (void *)0x0000a3a3) {
-			info("buffer %x invalid\n", crs);
-			return;
-		}
-		msg_dbg(buf_msg(crs), "In rec queue:\n");
-		crs = crs->next;
-	}
-}
-#endif
-
 static void link_dump_send_queue(struct link *l_ptr)
 {
 	if (l_ptr->next_out) {
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 2e5385c..f98bc61 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -210,10 +210,6 @@
 		u32 msg_length_counts;
 		u32 msg_lengths_total;
 		u32 msg_length_profile[7];
-#if 0
-		u32 sent_tunneled;
-		u32 recv_tunneled;
-#endif
 	} stats;
 
 	struct print_buf print_buf;
@@ -229,7 +225,6 @@
 void tipc_link_reset_fragments(struct link *l_ptr);
 int tipc_link_is_up(struct link *l_ptr);
 int tipc_link_is_active(struct link *l_ptr);
-void tipc_link_start(struct link *l_ptr);
 u32 tipc_link_push_packet(struct link *l_ptr);
 void tipc_link_stop(struct link *l_ptr);
 struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd);
@@ -243,9 +238,6 @@
 				 struct iovec const *msg_sect,
 				 const u32 num_sect,
 				 u32 destnode);
-int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf);
-void tipc_link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr,
-		      struct tipc_msg *msg, u32 selector);
 void tipc_link_recv_bundle(struct sk_buff *buf);
 int  tipc_link_recv_fragment(struct sk_buff **pending,
 			     struct sk_buff **fb,
@@ -279,12 +271,12 @@
 
 static inline int less_eq(u32 left, u32 right)
 {
-	return (mod(right - left) < 32768u);
+	return mod(right - left) < 32768u;
 }
 
 static inline int less(u32 left, u32 right)
 {
-	return (less_eq(left, right) && (mod(right) != mod(left)));
+	return less_eq(left, right) && (mod(right) != mod(left));
 }
 
 static inline u32 lesser(u32 left, u32 right)
@@ -299,32 +291,32 @@
 
 static inline int link_working_working(struct link *l_ptr)
 {
-	return (l_ptr->state == WORKING_WORKING);
+	return l_ptr->state == WORKING_WORKING;
 }
 
 static inline int link_working_unknown(struct link *l_ptr)
 {
-	return (l_ptr->state == WORKING_UNKNOWN);
+	return l_ptr->state == WORKING_UNKNOWN;
 }
 
 static inline int link_reset_unknown(struct link *l_ptr)
 {
-	return (l_ptr->state == RESET_UNKNOWN);
+	return l_ptr->state == RESET_UNKNOWN;
 }
 
 static inline int link_reset_reset(struct link *l_ptr)
 {
-	return (l_ptr->state == RESET_RESET);
+	return l_ptr->state == RESET_RESET;
 }
 
 static inline int link_blocked(struct link *l_ptr)
 {
-	return (l_ptr->exp_msg_count || l_ptr->blocked);
+	return l_ptr->exp_msg_count || l_ptr->blocked;
 }
 
 static inline int link_congested(struct link *l_ptr)
 {
-	return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]);
+	return l_ptr->out_queue_size >= l_ptr->queue_limit[0];
 }
 
 #endif
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 3810638..ecb532f 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -112,7 +112,7 @@
 		return dsz;
 	}
 
-	*buf = buf_acquire(sz);
+	*buf = tipc_buf_acquire(sz);
 	if (!(*buf))
 		return -ENOMEM;
 	skb_copy_to_linear_data(*buf, hdr, hsz);
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 995d2da..031aad1 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -104,7 +104,7 @@
 
 static inline u32 msg_isdata(struct tipc_msg *m)
 {
-	return (msg_user(m) <= TIPC_CRITICAL_IMPORTANCE);
+	return msg_user(m) <= TIPC_CRITICAL_IMPORTANCE;
 }
 
 static inline void msg_set_user(struct tipc_msg *m, u32 n)
@@ -289,7 +289,7 @@
 
 static inline int msg_is_dest(struct tipc_msg *m, u32 d)
 {
-	return(msg_short(m) || (msg_destnode(m) == d));
+	return msg_short(m) || (msg_destnode(m) == d);
 }
 
 static inline u32 msg_routed(struct tipc_msg *m)
@@ -632,7 +632,7 @@
 
 static inline u32 msg_max_pkt(struct tipc_msg *m)
 {
-	return (msg_bits(m, 9, 16, 0xffff) * 4);
+	return msg_bits(m, 9, 16, 0xffff) * 4;
 }
 
 static inline void msg_set_max_pkt(struct tipc_msg *m, u32 n)
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 6ac3c54..7b90717 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -98,7 +98,7 @@
 
 static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest)
 {
-	struct sk_buff *buf = buf_acquire(LONG_H_SIZE + size);
+	struct sk_buff *buf = tipc_buf_acquire(LONG_H_SIZE + size);
 	struct tipc_msg *msg;
 
 	if (buf != NULL) {
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 8ba7962..3a8de43 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -116,7 +116,7 @@
 
 static int hash(int x)
 {
-	return(x & (tipc_nametbl_size - 1));
+	return x & (tipc_nametbl_size - 1);
 }
 
 /**
@@ -613,8 +613,7 @@
 }
 
 /*
- * tipc_nametbl_translate(): Translate tipc_name -> tipc_portid.
- *                      Very time-critical.
+ * tipc_nametbl_translate - translate name to port id
  *
  * Note: on entry 'destnode' is the search domain used during translation;
  *       on exit it passes back the node address of the matching port (if any)
@@ -685,7 +684,6 @@
 	}
 	spin_unlock_bh(&seq->lock);
 not_found:
-	*destnode = 0;
 	read_unlock_bh(&tipc_nametbl_lock);
 	return 0;
 }
@@ -877,7 +875,7 @@
 			u32 index)
 {
 	char portIdStr[27];
-	char *scopeStr;
+	const char *scope_str[] = {"", " zone", " cluster", " node"};
 	struct publication *publ = sseq->zone_list;
 
 	tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper);
@@ -893,15 +891,8 @@
 			 tipc_node(publ->node), publ->ref);
 		tipc_printf(buf, "%-26s ", portIdStr);
 		if (depth > 3) {
-			if (publ->node != tipc_own_addr)
-				scopeStr = "";
-			else if (publ->scope == TIPC_NODE_SCOPE)
-				scopeStr = "node";
-			else if (publ->scope == TIPC_CLUSTER_SCOPE)
-				scopeStr = "cluster";
-			else
-				scopeStr = "zone";
-			tipc_printf(buf, "%-10u %s", publ->key, scopeStr);
+			tipc_printf(buf, "%-10u %s", publ->key,
+				    scope_str[publ->scope]);
 		}
 
 		publ = publ->zone_list_next;
@@ -951,24 +942,19 @@
 
 static void nametbl_header(struct print_buf *buf, u32 depth)
 {
-	tipc_printf(buf, "Type       ");
+	const char *header[] = {
+		"Type       ",
+		"Lower      Upper      ",
+		"Port Identity              ",
+		"Publication Scope"
+	};
 
-	if (depth > 1)
-		tipc_printf(buf, "Lower      Upper      ");
-	if (depth > 2)
-		tipc_printf(buf, "Port Identity              ");
-	if (depth > 3)
-		tipc_printf(buf, "Publication");
+	int i;
 
-	tipc_printf(buf, "\n-----------");
-
-	if (depth > 1)
-		tipc_printf(buf, "--------------------- ");
-	if (depth > 2)
-		tipc_printf(buf, "-------------------------- ");
-	if (depth > 3)
-		tipc_printf(buf, "------------------");
-
+	if (depth > 4)
+		depth = 4;
+	for (i = 0; i < depth; i++)
+		tipc_printf(buf, header[i]);
 	tipc_printf(buf, "\n");
 }
 
@@ -1023,16 +1009,6 @@
 	}
 }
 
-#if 0
-void tipc_nametbl_print(struct print_buf *buf, const char *str)
-{
-	tipc_printf(buf, str);
-	read_lock_bh(&tipc_nametbl_lock);
-	nametbl_list(buf, 0, 0, 0, 0);
-	read_unlock_bh(&tipc_nametbl_lock);
-}
-#endif
-
 #define MAX_NAME_TBL_QUERY 32768
 
 struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
@@ -1065,13 +1041,6 @@
 	return buf;
 }
 
-#if 0
-void tipc_nametbl_dump(void)
-{
-	nametbl_list(TIPC_CONS, 0, 0, 0, 0);
-}
-#endif
-
 int tipc_nametbl_init(void)
 {
 	table.types = kcalloc(tipc_nametbl_size, sizeof(struct hlist_head),
diff --git a/net/tipc/net.c b/net/tipc/net.c
index f61b769..1a621cf 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -129,15 +129,6 @@
 	return tipc_zone_select_router(tipc_net.zones[tipc_zone(addr)], addr, ref);
 }
 
-#if 0
-u32 tipc_net_next_node(u32 a)
-{
-	if (tipc_net.zones[tipc_zone(a)])
-		return tipc_zone_next_node(a);
-	return 0;
-}
-#endif
-
 void tipc_net_remove_as_router(u32 router)
 {
 	u32 z_num;
@@ -248,6 +239,7 @@
 
 	/* Handle message for another node */
 	msg_dbg(msg, "NET>SEND>: ");
+	skb_trim(buf, msg_size(msg));
 	tipc_link_send(buf, dnode, msg_link_selector(msg));
 }
 
diff --git a/net/tipc/node.c b/net/tipc/node.c
index b634942..b4d87eb 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -50,7 +50,8 @@
 static void node_lost_contact(struct tipc_node *n_ptr);
 static void node_established_contact(struct tipc_node *n_ptr);
 
-struct tipc_node *tipc_nodes = NULL;	/* sorted list of nodes within cluster */
+/* sorted list of nodes within cluster */
+static struct tipc_node *tipc_nodes = NULL;
 
 static DEFINE_SPINLOCK(node_create_lock);
 
@@ -125,16 +126,6 @@
 	if (!n_ptr)
 		return;
 
-#if 0
-	/* Not needed because links are already deleted via tipc_bearer_stop() */
-
-	u32 l_num;
-
-	for (l_num = 0; l_num < MAX_BEARERS; l_num++) {
-		link_delete(n_ptr->links[l_num]);
-	}
-#endif
-
 	dbg("node %x deleted\n", n_ptr->addr);
 	kfree(n_ptr);
 }
@@ -237,23 +228,22 @@
 
 int tipc_node_has_active_links(struct tipc_node *n_ptr)
 {
-	return (n_ptr &&
-		((n_ptr->active_links[0]) || (n_ptr->active_links[1])));
+	return n_ptr->active_links[0] != NULL;
 }
 
 int tipc_node_has_redundant_links(struct tipc_node *n_ptr)
 {
-	return (n_ptr->working_links > 1);
+	return n_ptr->working_links > 1;
 }
 
 static int tipc_node_has_active_routes(struct tipc_node *n_ptr)
 {
-	return (n_ptr && (n_ptr->last_router >= 0));
+	return n_ptr && (n_ptr->last_router >= 0);
 }
 
 int tipc_node_is_up(struct tipc_node *n_ptr)
 {
-	return (tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr));
+	return tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr);
 }
 
 struct tipc_node *tipc_node_attach_link(struct link *l_ptr)
@@ -384,6 +374,20 @@
 				  tipc_highest_allowed_slave);
 }
 
+static void node_cleanup_finished(unsigned long node_addr)
+{
+	struct tipc_node *n_ptr;
+
+	read_lock_bh(&tipc_net_lock);
+	n_ptr = tipc_node_find(node_addr);
+	if (n_ptr) {
+		tipc_node_lock(n_ptr);
+		n_ptr->cleanup_required = 0;
+		tipc_node_unlock(n_ptr);
+	}
+	read_unlock_bh(&tipc_net_lock);
+}
+
 static void node_lost_contact(struct tipc_node *n_ptr)
 {
 	struct cluster *c_ptr;
@@ -458,6 +462,11 @@
 		tipc_k_signal((Handler)ns->handle_node_down,
 			      (unsigned long)ns->usr_handle);
 	}
+
+	/* Prevent re-contact with node until all cleanup is done */
+
+	n_ptr->cleanup_required = 1;
+	tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr);
 }
 
 /**
@@ -579,38 +588,6 @@
 		node_lost_contact(n_ptr);
 }
 
-#if 0
-void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str)
-{
-	u32 i;
-
-	tipc_printf(buf, "\n\n%s", str);
-	for (i = 0; i < MAX_BEARERS; i++) {
-		if (!n_ptr->links[i])
-			continue;
-		tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]);
-	}
-	tipc_printf(buf, "Active links: [%x,%x]\n",
-		    n_ptr->active_links[0], n_ptr->active_links[1]);
-}
-#endif
-
-u32 tipc_available_nodes(const u32 domain)
-{
-	struct tipc_node *n_ptr;
-	u32 cnt = 0;
-
-	read_lock_bh(&tipc_net_lock);
-	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
-		if (!tipc_in_scope(domain, n_ptr->addr))
-			continue;
-		if (tipc_node_is_up(n_ptr))
-			cnt++;
-	}
-	read_unlock_bh(&tipc_net_lock);
-	return cnt;
-}
-
 struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
 {
 	u32 domain;
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 6f990da..fff331b 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -52,6 +52,7 @@
  * @active_links: pointers to active links to node
  * @links: pointers to all links to node
  * @working_links: number of working links to node (both active and standby)
+ * @cleanup_required: non-zero if cleaning up after a prior loss of contact
  * @link_cnt: number of links to node
  * @permit_changeover: non-zero if node has redundant links to this system
  * @routers: bitmap (used for multicluster communication)
@@ -78,6 +79,7 @@
 	struct link *links[MAX_BEARERS];
 	int link_cnt;
 	int working_links;
+	int cleanup_required;
 	int permit_changeover;
 	u32 routers[512/32];
 	int last_router;
@@ -94,7 +96,6 @@
 	} bclink;
 };
 
-extern struct tipc_node *tipc_nodes;
 extern u32 tipc_own_tag;
 
 struct tipc_node *tipc_node_create(u32 addr);
diff --git a/net/tipc/port.c b/net/tipc/port.c
index 0737680..82092ea 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -293,34 +293,6 @@
 	return 0;
 }
 
-/**
- * tipc_get_port() - return port associated with 'ref'
- *
- * Note: Port is not locked.
- */
-
-struct tipc_port *tipc_get_port(const u32 ref)
-{
-	return (struct tipc_port *)tipc_ref_deref(ref);
-}
-
-/**
- * tipc_get_handle - return user handle associated to port 'ref'
- */
-
-void *tipc_get_handle(const u32 ref)
-{
-	struct port *p_ptr;
-	void * handle;
-
-	p_ptr = tipc_port_lock(ref);
-	if (!p_ptr)
-		return NULL;
-	handle = p_ptr->publ.usr_handle;
-	tipc_port_unlock(p_ptr);
-	return handle;
-}
-
 static int port_unreliable(struct port *p_ptr)
 {
 	return msg_src_droppable(&p_ptr->publ.phdr);
@@ -392,7 +364,7 @@
 	struct sk_buff *buf;
 	struct tipc_msg *msg;
 
-	buf = buf_acquire(LONG_H_SIZE);
+	buf = tipc_buf_acquire(LONG_H_SIZE);
 	if (buf) {
 		msg = buf_msg(buf);
 		tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode);
@@ -433,7 +405,7 @@
 		hdr_sz = MCAST_H_SIZE;
 	else
 		hdr_sz = LONG_H_SIZE;
-	rbuf = buf_acquire(data_sz + hdr_sz);
+	rbuf = tipc_buf_acquire(data_sz + hdr_sz);
 	if (rbuf == NULL) {
 		buf_discard(buf);
 		return data_sz;
@@ -588,19 +560,10 @@
 	if (!p_ptr) {
 		err = TIPC_ERR_NO_PORT;
 	} else if (p_ptr->publ.connected) {
-		if (port_peernode(p_ptr) != msg_orignode(msg))
+		if ((port_peernode(p_ptr) != msg_orignode(msg)) ||
+		    (port_peerport(p_ptr) != msg_origport(msg))) {
 			err = TIPC_ERR_NO_PORT;
-		if (port_peerport(p_ptr) != msg_origport(msg))
-			err = TIPC_ERR_NO_PORT;
-		if (!err && msg_routed(msg)) {
-			u32 seqno = msg_transp_seqno(msg);
-			u32 myno =  ++p_ptr->last_in_seqno;
-			if (seqno != myno) {
-				err = TIPC_ERR_NO_PORT;
-				abort_buf = port_build_self_abort_msg(p_ptr, err);
-			}
-		}
-		if (msg_type(msg) == CONN_ACK) {
+		} else if (msg_type(msg) == CONN_ACK) {
 			int wakeup = tipc_port_congested(p_ptr) &&
 				     p_ptr->publ.congested &&
 				     p_ptr->wakeup;
@@ -719,50 +682,6 @@
 	return buf;
 }
 
-#if 0
-
-#define MAX_PORT_STATS 2000
-
-struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space)
-{
-	u32 ref;
-	struct port *p_ptr;
-	struct sk_buff *buf;
-	struct tlv_desc *rep_tlv;
-	struct print_buf pb;
-	int str_len;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_PORT_REF))
-		return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
-	ref = *(u32 *)TLV_DATA(req_tlv_area);
-	ref = ntohl(ref);
-
-	p_ptr = tipc_port_lock(ref);
-	if (!p_ptr)
-		return cfg_reply_error_string("port not found");
-
-	buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_STATS));
-	if (!buf) {
-		tipc_port_unlock(p_ptr);
-		return NULL;
-	}
-	rep_tlv = (struct tlv_desc *)buf->data;
-
-	tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_STATS);
-	port_print(p_ptr, &pb, 1);
-	/* NEED TO FILL IN ADDITIONAL PORT STATISTICS HERE */
-	tipc_port_unlock(p_ptr);
-	str_len = tipc_printbuf_validate(&pb);
-
-	skb_put(buf, TLV_SPACE(str_len));
-	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
-
-	return buf;
-}
-
-#endif
-
 void tipc_port_reinit(void)
 {
 	struct port *p_ptr;
@@ -1295,50 +1214,13 @@
 	return tipc_disconnect(ref);
 }
 
-int tipc_isconnected(u32 ref, int *isconnected)
-{
-	struct port *p_ptr;
-
-	p_ptr = tipc_port_lock(ref);
-	if (!p_ptr)
-		return -EINVAL;
-	*isconnected = p_ptr->publ.connected;
-	tipc_port_unlock(p_ptr);
-	return 0;
-}
-
-int tipc_peer(u32 ref, struct tipc_portid *peer)
-{
-	struct port *p_ptr;
-	int res;
-
-	p_ptr = tipc_port_lock(ref);
-	if (!p_ptr)
-		return -EINVAL;
-	if (p_ptr->publ.connected) {
-		peer->ref = port_peerport(p_ptr);
-		peer->node = port_peernode(p_ptr);
-		res = 0;
-	} else
-		res = -ENOTCONN;
-	tipc_port_unlock(p_ptr);
-	return res;
-}
-
-int tipc_ref_valid(u32 ref)
-{
-	/* Works irrespective of type */
-	return !!tipc_ref_deref(ref);
-}
-
-
 /*
  *  tipc_port_recv_sections(): Concatenate and deliver sectioned
  *                        message for this node.
  */
 
-int tipc_port_recv_sections(struct port *sender, unsigned int num_sect,
-		       struct iovec const *msg_sect)
+static int tipc_port_recv_sections(struct port *sender, unsigned int num_sect,
+				   struct iovec const *msg_sect)
 {
 	struct sk_buff *buf;
 	int res;
@@ -1389,65 +1271,16 @@
 }
 
 /**
- * tipc_send_buf - send message buffer on connection
- */
-
-int tipc_send_buf(u32 ref, struct sk_buff *buf, unsigned int dsz)
-{
-	struct port *p_ptr;
-	struct tipc_msg *msg;
-	u32 destnode;
-	u32 hsz;
-	u32 sz;
-	u32 res;
-
-	p_ptr = tipc_port_deref(ref);
-	if (!p_ptr || !p_ptr->publ.connected)
-		return -EINVAL;
-
-	msg = &p_ptr->publ.phdr;
-	hsz = msg_hdr_sz(msg);
-	sz = hsz + dsz;
-	msg_set_size(msg, sz);
-	if (skb_cow(buf, hsz))
-		return -ENOMEM;
-
-	skb_push(buf, hsz);
-	skb_copy_to_linear_data(buf, msg, hsz);
-	destnode = msg_destnode(msg);
-	p_ptr->publ.congested = 1;
-	if (!tipc_port_congested(p_ptr)) {
-		if (likely(destnode != tipc_own_addr))
-			res = tipc_send_buf_fast(buf, destnode);
-		else {
-			tipc_port_recv_msg(buf);
-			res = sz;
-		}
-		if (likely(res != -ELINKCONG)) {
-			port_incr_out_seqno(p_ptr);
-			p_ptr->sent++;
-			p_ptr->publ.congested = 0;
-			return res;
-		}
-	}
-	if (port_unreliable(p_ptr)) {
-		p_ptr->publ.congested = 0;
-		return dsz;
-	}
-	return -ELINKCONG;
-}
-
-/**
  * tipc_forward2name - forward message sections to port name
  */
 
-int tipc_forward2name(u32 ref,
-		      struct tipc_name const *name,
-		      u32 domain,
-		      u32 num_sect,
-		      struct iovec const *msg_sect,
-		      struct tipc_portid const *orig,
-		      unsigned int importance)
+static int tipc_forward2name(u32 ref,
+			     struct tipc_name const *name,
+			     u32 domain,
+			     u32 num_sect,
+			     struct iovec const *msg_sect,
+			     struct tipc_portid const *orig,
+			     unsigned int importance)
 {
 	struct port *p_ptr;
 	struct tipc_msg *msg;
@@ -1473,7 +1306,7 @@
 	msg_set_destnode(msg, destnode);
 	msg_set_destport(msg, destport);
 
-	if (likely(destport || destnode)) {
+	if (likely(destport)) {
 		p_ptr->sent++;
 		if (likely(destnode == tipc_own_addr))
 			return tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
@@ -1510,89 +1343,15 @@
 }
 
 /**
- * tipc_forward_buf2name - forward message buffer to port name
- */
-
-int tipc_forward_buf2name(u32 ref,
-			  struct tipc_name const *name,
-			  u32 domain,
-			  struct sk_buff *buf,
-			  unsigned int dsz,
-			  struct tipc_portid const *orig,
-			  unsigned int importance)
-{
-	struct port *p_ptr;
-	struct tipc_msg *msg;
-	u32 destnode = domain;
-	u32 destport;
-	int res;
-
-	p_ptr = (struct port *)tipc_ref_deref(ref);
-	if (!p_ptr || p_ptr->publ.connected)
-		return -EINVAL;
-
-	msg = &p_ptr->publ.phdr;
-	if (importance <= TIPC_CRITICAL_IMPORTANCE)
-		msg_set_importance(msg, importance);
-	msg_set_type(msg, TIPC_NAMED_MSG);
-	msg_set_orignode(msg, orig->node);
-	msg_set_origport(msg, orig->ref);
-	msg_set_nametype(msg, name->type);
-	msg_set_nameinst(msg, name->instance);
-	msg_set_lookup_scope(msg, tipc_addr_scope(domain));
-	msg_set_hdr_sz(msg, LONG_H_SIZE);
-	msg_set_size(msg, LONG_H_SIZE + dsz);
-	destport = tipc_nametbl_translate(name->type, name->instance, &destnode);
-	msg_set_destnode(msg, destnode);
-	msg_set_destport(msg, destport);
-	msg_dbg(msg, "forw2name ==> ");
-	if (skb_cow(buf, LONG_H_SIZE))
-		return -ENOMEM;
-	skb_push(buf, LONG_H_SIZE);
-	skb_copy_to_linear_data(buf, msg, LONG_H_SIZE);
-	msg_dbg(buf_msg(buf),"PREP:");
-	if (likely(destport || destnode)) {
-		p_ptr->sent++;
-		if (destnode == tipc_own_addr)
-			return tipc_port_recv_msg(buf);
-		res = tipc_send_buf_fast(buf, destnode);
-		if (likely(res != -ELINKCONG))
-			return res;
-		if (port_unreliable(p_ptr))
-			return dsz;
-		return -ELINKCONG;
-	}
-	return tipc_reject_msg(buf, TIPC_ERR_NO_NAME);
-}
-
-/**
- * tipc_send_buf2name - send message buffer to port name
- */
-
-int tipc_send_buf2name(u32 ref,
-		       struct tipc_name const *dest,
-		       u32 domain,
-		       struct sk_buff *buf,
-		       unsigned int dsz)
-{
-	struct tipc_portid orig;
-
-	orig.ref = ref;
-	orig.node = tipc_own_addr;
-	return tipc_forward_buf2name(ref, dest, domain, buf, dsz, &orig,
-				     TIPC_PORT_IMPORTANCE);
-}
-
-/**
  * tipc_forward2port - forward message sections to port identity
  */
 
-int tipc_forward2port(u32 ref,
-		      struct tipc_portid const *dest,
-		      unsigned int num_sect,
-		      struct iovec const *msg_sect,
-		      struct tipc_portid const *orig,
-		      unsigned int importance)
+static int tipc_forward2port(u32 ref,
+			     struct tipc_portid const *dest,
+			     unsigned int num_sect,
+			     struct iovec const *msg_sect,
+			     struct tipc_portid const *orig,
+			     unsigned int importance)
 {
 	struct port *p_ptr;
 	struct tipc_msg *msg;
@@ -1644,12 +1403,12 @@
 /**
  * tipc_forward_buf2port - forward message buffer to port identity
  */
-int tipc_forward_buf2port(u32 ref,
-			  struct tipc_portid const *dest,
-			  struct sk_buff *buf,
-			  unsigned int dsz,
-			  struct tipc_portid const *orig,
-			  unsigned int importance)
+static int tipc_forward_buf2port(u32 ref,
+				 struct tipc_portid const *dest,
+				 struct sk_buff *buf,
+				 unsigned int dsz,
+				 struct tipc_portid const *orig,
+				 unsigned int importance)
 {
 	struct port *p_ptr;
 	struct tipc_msg *msg;
diff --git a/net/tipc/port.h b/net/tipc/port.h
index 8d1652a..73bbf44 100644
--- a/net/tipc/port.h
+++ b/net/tipc/port.h
@@ -109,8 +109,6 @@
 extern spinlock_t tipc_port_list_lock;
 struct port_list;
 
-int tipc_port_recv_sections(struct port *p_ptr, u32 num_sect,
-			    struct iovec const *msg_sect);
 int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
 			      struct iovec const *msg_sect, u32 num_sect,
 			      int err);
@@ -157,7 +155,7 @@
 
 static inline int tipc_port_congested(struct port *p_ptr)
 {
-	return((p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2));
+	return (p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2);
 }
 
 /**
diff --git a/net/tipc/ref.c b/net/tipc/ref.c
index 8dea665..ab8ad32 100644
--- a/net/tipc/ref.c
+++ b/net/tipc/ref.c
@@ -282,23 +282,6 @@
 	return NULL;
 }
 
-/**
- * tipc_ref_unlock - unlock referenced object
- */
-
-void tipc_ref_unlock(u32 ref)
-{
-	if (likely(tipc_ref_table.entries)) {
-		struct reference *entry;
-
-		entry = &tipc_ref_table.entries[ref &
-						tipc_ref_table.index_mask];
-		if (likely((entry->ref == ref) && (entry->object)))
-			spin_unlock_bh(&entry->lock);
-		else
-			err("Attempt to unlock non-existent reference\n");
-	}
-}
 
 /**
  * tipc_ref_deref - return pointer referenced object (without locking it)
diff --git a/net/tipc/ref.h b/net/tipc/ref.h
index 7e3798e..5bc8e7a 100644
--- a/net/tipc/ref.h
+++ b/net/tipc/ref.h
@@ -44,7 +44,6 @@
 void tipc_ref_discard(u32 ref);
 
 void *tipc_ref_lock(u32 ref);
-void tipc_ref_unlock(u32 ref);
 void *tipc_ref_deref(u32 ref);
 
 #endif
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 66e889b..33217fc 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -64,6 +64,7 @@
 	struct sock sk;
 	struct tipc_port *p;
 	struct tipc_portid peer_name;
+	long conn_timeout;
 };
 
 #define tipc_sk(sk) ((struct tipc_sock *)(sk))
@@ -240,9 +241,9 @@
 	sock->state = state;
 
 	sock_init_data(sock, sk);
-	sk->sk_rcvtimeo = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT);
 	sk->sk_backlog_rcv = backlog_rcv;
 	tipc_sk(sk)->p = tp_ptr;
+	tipc_sk(sk)->conn_timeout = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT);
 
 	spin_unlock_bh(tp_ptr->lock);
 
@@ -429,36 +430,55 @@
  * to handle any preventable race conditions, so TIPC will do the same ...
  *
  * TIPC sets the returned events as follows:
- * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
- *    or if a connection-oriented socket is does not have an active connection
- *    (i.e. a read operation will not block).
- * b) POLLOUT is set except when a socket's connection has been terminated
- *    (i.e. a write operation will not block).
- * c) POLLHUP is set when a socket's connection has been terminated.
  *
- * IMPORTANT: The fact that a read or write operation will not block does NOT
- * imply that the operation will succeed!
+ * socket state		flags set
+ * ------------		---------
+ * unconnected		no read flags
+ *			no write flags
+ *
+ * connecting		POLLIN/POLLRDNORM if ACK/NACK in rx queue
+ *			no write flags
+ *
+ * connected		POLLIN/POLLRDNORM if data in rx queue
+ *			POLLOUT if port is not congested
+ *
+ * disconnecting	POLLIN/POLLRDNORM/POLLHUP
+ *			no write flags
+ *
+ * listening		POLLIN if SYN in rx queue
+ *			no write flags
+ *
+ * ready		POLLIN/POLLRDNORM if data in rx queue
+ * [connectionless]	POLLOUT (since port cannot be congested)
+ *
+ * IMPORTANT: The fact that a read or write operation is indicated does NOT
+ * imply that the operation will succeed, merely that it should be performed
+ * and will not block.
  */
 
 static unsigned int poll(struct file *file, struct socket *sock,
 			 poll_table *wait)
 {
 	struct sock *sk = sock->sk;
-	u32 mask;
+	u32 mask = 0;
 
 	poll_wait(file, sk_sleep(sk), wait);
 
-	if (!skb_queue_empty(&sk->sk_receive_queue) ||
-	    (sock->state == SS_UNCONNECTED) ||
-	    (sock->state == SS_DISCONNECTING))
-		mask = (POLLRDNORM | POLLIN);
-	else
-		mask = 0;
-
-	if (sock->state == SS_DISCONNECTING)
-		mask |= POLLHUP;
-	else
-		mask |= POLLOUT;
+	switch ((int)sock->state) {
+	case SS_READY:
+	case SS_CONNECTED:
+		if (!tipc_sk_port(sk)->congested)
+			mask |= POLLOUT;
+		/* fall thru' */
+	case SS_CONNECTING:
+	case SS_LISTENING:
+		if (!skb_queue_empty(&sk->sk_receive_queue))
+			mask |= (POLLIN | POLLRDNORM);
+		break;
+	case SS_DISCONNECTING:
+		mask = (POLLIN | POLLRDNORM | POLLHUP);
+		break;
+	}
 
 	return mask;
 }
@@ -1026,9 +1046,8 @@
 	struct sk_buff *buf;
 	struct tipc_msg *msg;
 	unsigned int sz;
-	int sz_to_copy;
+	int sz_to_copy, target, needed;
 	int sz_copied = 0;
-	int needed;
 	char __user *crs = m->msg_iov->iov_base;
 	unsigned char *buf_crs;
 	u32 err;
@@ -1050,6 +1069,8 @@
 		goto exit;
 	}
 
+	target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
+
 restart:
 
 	/* Look for a message in receive queue; wait if necessary */
@@ -1138,7 +1159,7 @@
 
 	if ((sz_copied < buf_len) &&	/* didn't get all requested data */
 	    (!skb_queue_empty(&sk->sk_receive_queue) ||
-	     (flags & MSG_WAITALL)) &&	/* and more is ready or required */
+	    (sz_copied < target)) &&	/* and more is ready or required */
 	    (!(flags & MSG_PEEK)) &&	/* and aren't just peeking at data */
 	    (!err))			/* and haven't reached a FIN */
 		goto restart;
@@ -1174,7 +1195,7 @@
 	if (msg_connected(msg))
 		threshold *= 4;
 
-	return (queue_size >= threshold);
+	return queue_size >= threshold;
 }
 
 /**
@@ -1365,6 +1386,7 @@
 	struct msghdr m = {NULL,};
 	struct sk_buff *buf;
 	struct tipc_msg *msg;
+	long timeout;
 	int res;
 
 	lock_sock(sk);
@@ -1379,7 +1401,7 @@
 	/* For now, TIPC does not support the non-blocking form of connect() */
 
 	if (flags & O_NONBLOCK) {
-		res = -EWOULDBLOCK;
+		res = -EOPNOTSUPP;
 		goto exit;
 	}
 
@@ -1425,11 +1447,12 @@
 
 	/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
 
+	timeout = tipc_sk(sk)->conn_timeout;
 	release_sock(sk);
 	res = wait_event_interruptible_timeout(*sk_sleep(sk),
 			(!skb_queue_empty(&sk->sk_receive_queue) ||
 			(sock->state != SS_CONNECTING)),
-			sk->sk_rcvtimeo);
+			timeout ? timeout : MAX_SCHEDULE_TIMEOUT);
 	lock_sock(sk);
 
 	if (res > 0) {
@@ -1692,7 +1715,7 @@
 		res = tipc_set_portunreturnable(tport->ref, value);
 		break;
 	case TIPC_CONN_TIMEOUT:
-		sk->sk_rcvtimeo = msecs_to_jiffies(value);
+		tipc_sk(sk)->conn_timeout = msecs_to_jiffies(value);
 		/* no need to set "res", since already 0 at this point */
 		break;
 	default:
@@ -1747,7 +1770,7 @@
 		res = tipc_portunreturnable(tport->ref, &value);
 		break;
 	case TIPC_CONN_TIMEOUT:
-		value = jiffies_to_msecs(sk->sk_rcvtimeo);
+		value = jiffies_to_msecs(tipc_sk(sk)->conn_timeout);
 		/* no need to set "res", since already 0 at this point */
 		break;
 	 case TIPC_NODE_RECVQ_DEPTH:
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index ab6eab4..3331396 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -76,6 +76,19 @@
 static struct top_srv topsrv = { 0 };
 
 /**
+ * htohl - convert value to endianness used by destination
+ * @in: value to convert
+ * @swap: non-zero if endianness must be reversed
+ *
+ * Returns converted value
+ */
+
+static u32 htohl(u32 in, int swap)
+{
+	return swap ? swab32(in) : in;
+}
+
+/**
  * subscr_send_event - send a message containing a tipc_event to the subscriber
  *
  * Note: Must not hold subscriber's server port lock, since tipc_send() will
@@ -94,11 +107,11 @@
 	msg_sect.iov_base = (void *)&sub->evt;
 	msg_sect.iov_len = sizeof(struct tipc_event);
 
-	sub->evt.event = htonl(event);
-	sub->evt.found_lower = htonl(found_lower);
-	sub->evt.found_upper = htonl(found_upper);
-	sub->evt.port.ref = htonl(port_ref);
-	sub->evt.port.node = htonl(node);
+	sub->evt.event = htohl(event, sub->swap);
+	sub->evt.found_lower = htohl(found_lower, sub->swap);
+	sub->evt.found_upper = htohl(found_upper, sub->swap);
+	sub->evt.port.ref = htohl(port_ref, sub->swap);
+	sub->evt.port.node = htohl(node, sub->swap);
 	tipc_send(sub->server_ref, 1, &msg_sect);
 }
 
@@ -274,29 +287,16 @@
 {
 	struct subscription *sub;
 	struct subscription *sub_temp;
-	__u32 type, lower, upper, timeout, filter;
 	int found = 0;
 
 	/* Find first matching subscription, exit if not found */
 
-	type = ntohl(s->seq.type);
-	lower = ntohl(s->seq.lower);
-	upper = ntohl(s->seq.upper);
-	timeout = ntohl(s->timeout);
-	filter = ntohl(s->filter) & ~TIPC_SUB_CANCEL;
-
 	list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
 				 subscription_list) {
-			if ((type == sub->seq.type) &&
-			    (lower == sub->seq.lower) &&
-			    (upper == sub->seq.upper) &&
-			    (timeout == sub->timeout) &&
-                            (filter == sub->filter) &&
-                             !memcmp(s->usr_handle,sub->evt.s.usr_handle,
-				     sizeof(s->usr_handle)) ){
-				found = 1;
-				break;
-			}
+		if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) {
+			found = 1;
+			break;
+		}
 	}
 	if (!found)
 		return;
@@ -310,7 +310,7 @@
 		k_term_timer(&sub->timer);
 		spin_lock_bh(subscriber->lock);
 	}
-	dbg("Cancel: removing sub %u,%u,%u from subscriber %p list\n",
+	dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n",
 	    sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
 	subscr_del(sub);
 }
@@ -325,10 +325,16 @@
 					     struct subscriber *subscriber)
 {
 	struct subscription *sub;
+	int swap;
+
+	/* Determine subscriber's endianness */
+
+	swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE));
 
 	/* Detect & process a subscription cancellation request */
 
-	if (ntohl(s->filter) & TIPC_SUB_CANCEL) {
+	if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) {
+		s->filter &= ~htohl(TIPC_SUB_CANCEL, swap);
 		subscr_cancel(s, subscriber);
 		return NULL;
 	}
@@ -353,12 +359,13 @@
 
 	/* Initialize subscription object */
 
-	sub->seq.type = ntohl(s->seq.type);
-	sub->seq.lower = ntohl(s->seq.lower);
-	sub->seq.upper = ntohl(s->seq.upper);
-	sub->timeout = ntohl(s->timeout);
-	sub->filter = ntohl(s->filter);
-	if ((sub->filter && (sub->filter != TIPC_SUB_PORTS)) ||
+	sub->seq.type = htohl(s->seq.type, swap);
+	sub->seq.lower = htohl(s->seq.lower, swap);
+	sub->seq.upper = htohl(s->seq.upper, swap);
+	sub->timeout = htohl(s->timeout, swap);
+	sub->filter = htohl(s->filter, swap);
+	if ((!(sub->filter & TIPC_SUB_PORTS) ==
+	     !(sub->filter & TIPC_SUB_SERVICE)) ||
 	    (sub->seq.lower > sub->seq.upper)) {
 		warn("Subscription rejected, illegal request\n");
 		kfree(sub);
@@ -369,6 +376,7 @@
 	INIT_LIST_HEAD(&sub->nameseq_list);
 	list_add(&sub->subscription_list, &subscriber->subscription_list);
 	sub->server_ref = subscriber->port_ref;
+	sub->swap = swap;
 	memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr));
 	atomic_inc(&topsrv.subscription_count);
 	if (sub->timeout != TIPC_WAIT_FOREVER) {
@@ -598,12 +606,3 @@
 		topsrv.user_ref = 0;
 	}
 }
-
-
-int tipc_ispublished(struct tipc_name const *name)
-{
-	u32 domain = 0;
-
-	return(tipc_nametbl_translate(name->type, name->instance,&domain) != 0);
-}
-
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h
index c20f496..45d89bf 100644
--- a/net/tipc/subscr.h
+++ b/net/tipc/subscr.h
@@ -53,6 +53,7 @@
  * @nameseq_list: adjacent subscriptions in name sequence's subscription list
  * @subscription_list: adjacent subscriptions in subscriber's subscription list
  * @server_ref: object reference of server port associated with subscription
+ * @swap: indicates if subscriber uses opposite endianness in its messages
  * @evt: template for events generated by subscription
  */
 
@@ -65,6 +66,7 @@
 	struct list_head nameseq_list;
 	struct list_head subscription_list;
 	u32 server_ref;
+	int swap;
 	struct tipc_event evt;
 };
 
diff --git a/net/tipc/zone.c b/net/tipc/zone.c
index 2c01ba2..83f8b5e 100644
--- a/net/tipc/zone.c
+++ b/net/tipc/zone.c
@@ -160,14 +160,3 @@
 	}
 	return 0;
 }
-
-
-u32 tipc_zone_next_node(u32 addr)
-{
-	struct cluster *c_ptr = tipc_cltr_find(addr);
-
-	if (c_ptr)
-		return tipc_cltr_next_node(c_ptr, addr);
-	return 0;
-}
-
diff --git a/net/tipc/zone.h b/net/tipc/zone.h
index 7bdc340..bd1c20c 100644
--- a/net/tipc/zone.h
+++ b/net/tipc/zone.h
@@ -61,7 +61,6 @@
 struct _zone *tipc_zone_create(u32 addr);
 void tipc_zone_delete(struct _zone *z_ptr);
 void tipc_zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr);
-u32 tipc_zone_next_node(u32 addr);
 
 static inline struct _zone *tipc_zone_find(u32 addr)
 {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 0b39b24..0ebc777 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1511,6 +1511,8 @@
 		goto restart;
 	}
 
+	if (sock_flag(other, SOCK_RCVTSTAMP))
+		__net_timestamp(skb);
 	skb_queue_tail(&other->sk_receive_queue, skb);
 	unix_state_unlock(other);
 	other->sk_data_ready(other, len);
@@ -1722,6 +1724,9 @@
 	if (err)
 		goto out_free;
 
+	if (sock_flag(sk, SOCK_RCVTSTAMP))
+		__sock_recv_timestamp(msg, sk, skb);
+
 	if (!siocb->scm) {
 		siocb->scm = &tmp_scm;
 		memset(&tmp_scm, 0, sizeof(tmp_scm));
@@ -2033,11 +2038,10 @@
 	if (sk->sk_shutdown == SHUTDOWN_MASK)
 		mask |= POLLHUP;
 	if (sk->sk_shutdown & RCV_SHUTDOWN)
-		mask |= POLLRDHUP;
+		mask |= POLLRDHUP | POLLIN | POLLRDNORM;
 
 	/* readable? */
-	if (!skb_queue_empty(&sk->sk_receive_queue) ||
-	    (sk->sk_shutdown & RCV_SHUTDOWN))
+	if (!skb_queue_empty(&sk->sk_receive_queue))
 		mask |= POLLIN | POLLRDNORM;
 
 	/* Connection-based need to check for termination and startup */
diff --git a/net/wireless/core.c b/net/wireless/core.c
index d6d046b..9c21ebf 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -253,11 +253,16 @@
 			WARN_ON(err);
 			wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
 		}
+
+		return err;
 	}
 
 	wiphy_net_set(&rdev->wiphy, net);
 
-	return err;
+	err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev));
+	WARN_ON(err);
+
+	return 0;
 }
 
 static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
@@ -428,7 +433,7 @@
 
 	/* sanity check ifmodes */
 	WARN_ON(!ifmodes);
-	ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1;
+	ifmodes &= ((1 << NUM_NL80211_IFTYPES) - 1) & ~1;
 	if (WARN_ON(ifmodes != wiphy->interface_modes))
 		wiphy->interface_modes = ifmodes;
 
@@ -683,8 +688,8 @@
 		INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
 		INIT_LIST_HEAD(&wdev->event_list);
 		spin_lock_init(&wdev->event_lock);
-		INIT_LIST_HEAD(&wdev->action_registrations);
-		spin_lock_init(&wdev->action_registrations_lock);
+		INIT_LIST_HEAD(&wdev->mgmt_registrations);
+		spin_lock_init(&wdev->mgmt_registrations_lock);
 
 		mutex_lock(&rdev->devlist_mtx);
 		list_add_rcu(&wdev->list, &rdev->netdev_list);
@@ -724,6 +729,7 @@
 			dev->ethtool_ops = &cfg80211_ethtool_ops;
 
 		if ((wdev->iftype == NL80211_IFTYPE_STATION ||
+		     wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
 		     wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
 			dev->priv_flags |= IFF_DONT_BRIDGE;
 		break;
@@ -732,6 +738,7 @@
 		case NL80211_IFTYPE_ADHOC:
 			cfg80211_leave_ibss(rdev, dev, true);
 			break;
+		case NL80211_IFTYPE_P2P_CLIENT:
 		case NL80211_IFTYPE_STATION:
 			wdev_lock(wdev);
 #ifdef CONFIG_CFG80211_WEXT
@@ -804,7 +811,7 @@
 			sysfs_remove_link(&dev->dev.kobj, "phy80211");
 			list_del_rcu(&wdev->list);
 			rdev->devlist_generation++;
-			cfg80211_mlme_purge_actions(wdev);
+			cfg80211_mlme_purge_registrations(wdev);
 #ifdef CONFIG_CFG80211_WEXT
 			kfree(wdev->wext.keys);
 #endif
@@ -910,52 +917,3 @@
 	destroy_workqueue(cfg80211_wq);
 }
 module_exit(cfg80211_exit);
-
-static int ___wiphy_printk(const char *level, const struct wiphy *wiphy,
-			   struct va_format *vaf)
-{
-	if (!wiphy)
-		return printk("%s(NULL wiphy *): %pV", level, vaf);
-
-	return printk("%s%s: %pV", level, wiphy_name(wiphy), vaf);
-}
-
-int __wiphy_printk(const char *level, const struct wiphy *wiphy,
-		   const char *fmt, ...)
-{
-	struct va_format vaf;
-	va_list args;
-	int r;
-
-	va_start(args, fmt);
-
-	vaf.fmt = fmt;
-	vaf.va = &args;
-
-	r = ___wiphy_printk(level, wiphy, &vaf);
-	va_end(args);
-
-	return r;
-}
-EXPORT_SYMBOL(__wiphy_printk);
-
-#define define_wiphy_printk_level(func, kern_level)		\
-int func(const struct wiphy *wiphy, const char *fmt, ...)	\
-{								\
-	struct va_format vaf;					\
-	va_list args;						\
-	int r;							\
-								\
-	va_start(args, fmt);					\
-								\
-	vaf.fmt = fmt;						\
-	vaf.va = &args;						\
-								\
-	r = ___wiphy_printk(kern_level, wiphy, &vaf);		\
-	va_end(args);						\
-								\
-	return r;						\
-}								\
-EXPORT_SYMBOL(func);
-
-define_wiphy_printk_level(wiphy_debug, KERN_DEBUG);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 63d57ae..6583cca 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -86,7 +86,7 @@
 static inline
 bool wiphy_idx_valid(int wiphy_idx)
 {
-	return (wiphy_idx >= 0);
+	return wiphy_idx >= 0;
 }
 
 
@@ -95,7 +95,10 @@
 extern struct list_head cfg80211_rdev_list;
 extern int cfg80211_rdev_list_generation;
 
-#define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex))
+static inline void assert_cfg80211_lock(void)
+{
+	lockdep_assert_held(&cfg80211_mutex);
+}
 
 /*
  * You can use this to mark a wiphy_idx as not having an associated wiphy.
@@ -202,8 +205,8 @@
 	mutex_unlock(&wdev->mtx);
 }
 
-#define ASSERT_RDEV_LOCK(rdev) WARN_ON(!mutex_is_locked(&(rdev)->mtx));
-#define ASSERT_WDEV_LOCK(wdev) WARN_ON(!mutex_is_locked(&(wdev)->mtx));
+#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx)
+#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
 
 enum cfg80211_event_type {
 	EVENT_CONNECT_RESULT,
@@ -331,16 +334,17 @@
 			       const u8 *resp_ie, size_t resp_ie_len,
 			       u16 status, bool wextev,
 			       struct cfg80211_bss *bss);
-int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid,
-				  const u8 *match_data, int match_len);
-void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid);
-void cfg80211_mlme_purge_actions(struct wireless_dev *wdev);
-int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
-			 struct net_device *dev,
-			 struct ieee80211_channel *chan,
-			 enum nl80211_channel_type channel_type,
-			 bool channel_type_valid,
-			 const u8 *buf, size_t len, u64 *cookie);
+int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
+				u16 frame_type, const u8 *match_data,
+				int match_len);
+void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
+void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
+int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
+			  struct net_device *dev,
+			  struct ieee80211_channel *chan,
+			  enum nl80211_channel_type channel_type,
+			  bool channel_type_valid,
+			  const u8 *buf, size_t len, u64 *cookie);
 
 /* SME */
 int __cfg80211_connect(struct cfg80211_registered_device *rdev,
@@ -371,7 +375,7 @@
 /* internal helpers */
 int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
 				   struct key_params *params, int key_idx,
-				   const u8 *mac_addr);
+				   bool pairwise, const u8 *mac_addr);
 void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
 			     size_t ie_len, u16 reason, bool from_ap);
 void cfg80211_sme_scan_done(struct net_device *dev);
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index a4991a3..39765bc 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -34,6 +34,7 @@
 static const struct file_operations name## _ops = {			\
 	.read = name## _read,						\
 	.open = cfg80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 };
 
 DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
@@ -102,6 +103,7 @@
 static const struct file_operations ht40allow_map_ops = {
 	.read = ht40allow_map_read,
 	.open = cfg80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 #define DEBUGFS_ADD(name)						\
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 27a8ce9..f33fbb7 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -88,6 +88,25 @@
 	if (wdev->ssid_len)
 		return -EALREADY;
 
+	if (!params->basic_rates) {
+		/*
+		* If no rates were explicitly configured,
+		* use the mandatory rate set for 11b or
+		* 11a for maximum compatibility.
+		*/
+		struct ieee80211_supported_band *sband =
+			rdev->wiphy.bands[params->channel->band];
+		int j;
+		u32 flag = params->channel->band == IEEE80211_BAND_5GHZ ?
+			IEEE80211_RATE_MANDATORY_A :
+			IEEE80211_RATE_MANDATORY_B;
+
+		for (j = 0; j < sband->n_bitrates; j++) {
+			if (sband->bitrates[j].flags & flag)
+				params->basic_rates |= BIT(j);
+		}
+	}
+
 	if (WARN_ON(wdev->connect_keys))
 		kfree(wdev->connect_keys);
 	wdev->connect_keys = connkeys;
@@ -141,7 +160,7 @@
 	 */
 	if (rdev->ops->del_key)
 		for (i = 0; i < 6; i++)
-			rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
+			rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
 
 	if (wdev->current_bss) {
 		cfg80211_unhold_bss(wdev->current_bss);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index d1a3fb9..26838d9 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -149,7 +149,7 @@
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
 	const u8 *bssid = mgmt->bssid;
 	int i;
-	bool found = false;
+	bool found = false, was_current = false;
 
 	ASSERT_WDEV_LOCK(wdev);
 
@@ -159,6 +159,7 @@
 		cfg80211_put_bss(&wdev->current_bss->pub);
 		wdev->current_bss = NULL;
 		found = true;
+		was_current = true;
 	} else for (i = 0; i < MAX_AUTH_BSSES; i++) {
 		if (wdev->auth_bsses[i] &&
 		    memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
@@ -183,7 +184,7 @@
 
 	nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
 
-	if (wdev->sme_state == CFG80211_SME_CONNECTED) {
+	if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) {
 		u16 reason_code;
 		bool from_ap;
 
@@ -747,31 +748,53 @@
 }
 EXPORT_SYMBOL(cfg80211_new_sta);
 
-struct cfg80211_action_registration {
+struct cfg80211_mgmt_registration {
 	struct list_head list;
 
 	u32 nlpid;
 
 	int match_len;
 
+	__le16 frame_type;
+
 	u8 match[];
 };
 
-int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid,
-				  const u8 *match_data, int match_len)
+int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
+				u16 frame_type, const u8 *match_data,
+				int match_len)
 {
-	struct cfg80211_action_registration *reg, *nreg;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+	struct cfg80211_mgmt_registration *reg, *nreg;
 	int err = 0;
+	u16 mgmt_type;
+
+	if (!wdev->wiphy->mgmt_stypes)
+		return -EOPNOTSUPP;
+
+	if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
+		return -EINVAL;
+
+	if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
+		return -EINVAL;
+
+	mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
+	if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type)))
+		return -EINVAL;
 
 	nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
 	if (!nreg)
 		return -ENOMEM;
 
-	spin_lock_bh(&wdev->action_registrations_lock);
+	spin_lock_bh(&wdev->mgmt_registrations_lock);
 
-	list_for_each_entry(reg, &wdev->action_registrations, list) {
+	list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
 		int mlen = min(match_len, reg->match_len);
 
+		if (frame_type != le16_to_cpu(reg->frame_type))
+			continue;
+
 		if (memcmp(reg->match, match_data, mlen) == 0) {
 			err = -EALREADY;
 			break;
@@ -786,140 +809,212 @@
 	memcpy(nreg->match, match_data, match_len);
 	nreg->match_len = match_len;
 	nreg->nlpid = snd_pid;
-	list_add(&nreg->list, &wdev->action_registrations);
+	nreg->frame_type = cpu_to_le16(frame_type);
+	list_add(&nreg->list, &wdev->mgmt_registrations);
+
+	if (rdev->ops->mgmt_frame_register)
+		rdev->ops->mgmt_frame_register(wiphy, wdev->netdev,
+					       frame_type, true);
 
  out:
-	spin_unlock_bh(&wdev->action_registrations_lock);
+	spin_unlock_bh(&wdev->mgmt_registrations_lock);
+
 	return err;
 }
 
-void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid)
+void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid)
 {
-	struct cfg80211_action_registration *reg, *tmp;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+	struct cfg80211_mgmt_registration *reg, *tmp;
 
-	spin_lock_bh(&wdev->action_registrations_lock);
+	spin_lock_bh(&wdev->mgmt_registrations_lock);
 
-	list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
-		if (reg->nlpid == nlpid) {
-			list_del(&reg->list);
-			kfree(reg);
+	list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
+		if (reg->nlpid != nlpid)
+			continue;
+
+		if (rdev->ops->mgmt_frame_register) {
+			u16 frame_type = le16_to_cpu(reg->frame_type);
+
+			rdev->ops->mgmt_frame_register(wiphy, wdev->netdev,
+						       frame_type, false);
 		}
-	}
 
-	spin_unlock_bh(&wdev->action_registrations_lock);
-}
-
-void cfg80211_mlme_purge_actions(struct wireless_dev *wdev)
-{
-	struct cfg80211_action_registration *reg, *tmp;
-
-	spin_lock_bh(&wdev->action_registrations_lock);
-
-	list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) {
 		list_del(&reg->list);
 		kfree(reg);
 	}
 
-	spin_unlock_bh(&wdev->action_registrations_lock);
+	spin_unlock_bh(&wdev->mgmt_registrations_lock);
 }
 
-int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
-			 struct net_device *dev,
-			 struct ieee80211_channel *chan,
-			 enum nl80211_channel_type channel_type,
-			 bool channel_type_valid,
-			 const u8 *buf, size_t len, u64 *cookie)
+void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
+{
+	struct cfg80211_mgmt_registration *reg, *tmp;
+
+	spin_lock_bh(&wdev->mgmt_registrations_lock);
+
+	list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
+		list_del(&reg->list);
+		kfree(reg);
+	}
+
+	spin_unlock_bh(&wdev->mgmt_registrations_lock);
+}
+
+int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
+			  struct net_device *dev,
+			  struct ieee80211_channel *chan,
+			  enum nl80211_channel_type channel_type,
+			  bool channel_type_valid,
+			  const u8 *buf, size_t len, u64 *cookie)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	const struct ieee80211_mgmt *mgmt;
+	u16 stype;
 
-	if (rdev->ops->action == NULL)
+	if (!wdev->wiphy->mgmt_stypes)
 		return -EOPNOTSUPP;
+
+	if (!rdev->ops->mgmt_tx)
+		return -EOPNOTSUPP;
+
 	if (len < 24 + 1)
 		return -EINVAL;
 
 	mgmt = (const struct ieee80211_mgmt *) buf;
-	if (!ieee80211_is_action(mgmt->frame_control))
+
+	if (!ieee80211_is_mgmt(mgmt->frame_control))
 		return -EINVAL;
-	if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
-		/* Verify that we are associated with the destination AP */
+
+	stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
+	if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4)))
+		return -EINVAL;
+
+	if (ieee80211_is_action(mgmt->frame_control) &&
+	    mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
+		int err = 0;
+
 		wdev_lock(wdev);
 
-		if (!wdev->current_bss ||
-		    memcmp(wdev->current_bss->pub.bssid, mgmt->bssid,
-			   ETH_ALEN) != 0 ||
-		    (wdev->iftype == NL80211_IFTYPE_STATION &&
-		     memcmp(wdev->current_bss->pub.bssid, mgmt->da,
-			    ETH_ALEN) != 0)) {
-			wdev_unlock(wdev);
-			return -ENOTCONN;
-		}
+		switch (wdev->iftype) {
+		case NL80211_IFTYPE_ADHOC:
+		case NL80211_IFTYPE_STATION:
+		case NL80211_IFTYPE_P2P_CLIENT:
+			if (!wdev->current_bss) {
+				err = -ENOTCONN;
+				break;
+			}
 
+			if (memcmp(wdev->current_bss->pub.bssid,
+				   mgmt->bssid, ETH_ALEN)) {
+				err = -ENOTCONN;
+				break;
+			}
+
+			/*
+			 * check for IBSS DA must be done by driver as
+			 * cfg80211 doesn't track the stations
+			 */
+			if (wdev->iftype == NL80211_IFTYPE_ADHOC)
+				break;
+
+			/* for station, check that DA is the AP */
+			if (memcmp(wdev->current_bss->pub.bssid,
+				   mgmt->da, ETH_ALEN)) {
+				err = -ENOTCONN;
+				break;
+			}
+			break;
+		case NL80211_IFTYPE_AP:
+		case NL80211_IFTYPE_P2P_GO:
+		case NL80211_IFTYPE_AP_VLAN:
+			if (memcmp(mgmt->bssid, dev->dev_addr, ETH_ALEN))
+				err = -EINVAL;
+			break;
+		default:
+			err = -EOPNOTSUPP;
+			break;
+		}
 		wdev_unlock(wdev);
+
+		if (err)
+			return err;
 	}
 
 	if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0)
 		return -EINVAL;
 
 	/* Transmit the Action frame as requested by user space */
-	return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type,
-				 channel_type_valid, buf, len, cookie);
+	return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, channel_type,
+				  channel_type_valid, buf, len, cookie);
 }
 
-bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf,
-			size_t len, gfp_t gfp)
+bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
+		      size_t len, gfp_t gfp)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct wiphy *wiphy = wdev->wiphy;
 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-	struct cfg80211_action_registration *reg;
-	const u8 *action_data;
-	int action_data_len;
+	struct cfg80211_mgmt_registration *reg;
+	const struct ieee80211_txrx_stypes *stypes =
+		&wiphy->mgmt_stypes[wdev->iftype];
+	struct ieee80211_mgmt *mgmt = (void *)buf;
+	const u8 *data;
+	int data_len;
 	bool result = false;
+	__le16 ftype = mgmt->frame_control &
+		cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
+	u16 stype;
 
-	/* frame length - min size excluding category */
-	action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1);
+	stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4;
 
-	/* action data starts with category */
-	action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1;
+	if (!(stypes->rx & BIT(stype)))
+		return false;
 
-	spin_lock_bh(&wdev->action_registrations_lock);
+	data = buf + ieee80211_hdrlen(mgmt->frame_control);
+	data_len = len - ieee80211_hdrlen(mgmt->frame_control);
 
-	list_for_each_entry(reg, &wdev->action_registrations, list) {
-		if (reg->match_len > action_data_len)
+	spin_lock_bh(&wdev->mgmt_registrations_lock);
+
+	list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
+		if (reg->frame_type != ftype)
 			continue;
 
-		if (memcmp(reg->match, action_data, reg->match_len))
+		if (reg->match_len > data_len)
+			continue;
+
+		if (memcmp(reg->match, data, reg->match_len))
 			continue;
 
 		/* found match! */
 
 		/* Indicate the received Action frame to user space */
-		if (nl80211_send_action(rdev, dev, reg->nlpid, freq,
-					buf, len, gfp))
+		if (nl80211_send_mgmt(rdev, dev, reg->nlpid, freq,
+				      buf, len, gfp))
 			continue;
 
 		result = true;
 		break;
 	}
 
-	spin_unlock_bh(&wdev->action_registrations_lock);
+	spin_unlock_bh(&wdev->mgmt_registrations_lock);
 
 	return result;
 }
-EXPORT_SYMBOL(cfg80211_rx_action);
+EXPORT_SYMBOL(cfg80211_rx_mgmt);
 
-void cfg80211_action_tx_status(struct net_device *dev, u64 cookie,
-			       const u8 *buf, size_t len, bool ack, gfp_t gfp)
+void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie,
+			     const u8 *buf, size_t len, bool ack, gfp_t gfp)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct wiphy *wiphy = wdev->wiphy;
 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
 	/* Indicate TX status of the Action frame to user space */
-	nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp);
+	nl80211_send_mgmt_tx_status(rdev, dev, cookie, buf, len, ack, gfp);
 }
-EXPORT_SYMBOL(cfg80211_action_tx_status);
+EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
 
 void cfg80211_cqm_rssi_notify(struct net_device *dev,
 			      enum nl80211_cqm_rssi_threshold_event rssi_event,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 37902a5..c506241 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -23,6 +23,11 @@
 #include "nl80211.h"
 #include "reg.h"
 
+static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
+			    struct genl_info *info);
+static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
+			      struct genl_info *info);
+
 /* the netlink family */
 static struct genl_family nl80211_fam = {
 	.id = GENL_ID_GENERATE,	/* don't bother with a hardcoded ID */
@@ -31,6 +36,8 @@
 	.version = 1,		/* no particular meaning now */
 	.maxattr = NL80211_ATTR_MAX,
 	.netnsok = true,
+	.pre_doit = nl80211_pre_doit,
+	.post_doit = nl80211_post_doit,
 };
 
 /* internal helper: get rdev and dev */
@@ -86,6 +93,7 @@
 	[NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
 	[NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
 	[NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
+	[NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 },
 
 	[NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
 	[NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
@@ -136,6 +144,8 @@
 		.len = sizeof(struct nl80211_sta_flag_update),
 	},
 	[NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
+	[NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 },
+	[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
 	[NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
 	[NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
 	[NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
@@ -156,9 +166,10 @@
 
 	[NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
 	[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
+	[NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 },
 };
 
-/* policy for the attributes */
+/* policy for the key attributes */
 static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
 	[NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
 	[NL80211_KEY_IDX] = { .type = NLA_U8 },
@@ -166,6 +177,7 @@
 	[NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
 	[NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
 	[NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
+	[NL80211_KEY_TYPE] = { .type = NLA_U32 },
 };
 
 /* ifidx get helper */
@@ -188,6 +200,47 @@
 	return res;
 }
 
+static int nl80211_prepare_netdev_dump(struct sk_buff *skb,
+				       struct netlink_callback *cb,
+				       struct cfg80211_registered_device **rdev,
+				       struct net_device **dev)
+{
+	int ifidx = cb->args[0];
+	int err;
+
+	if (!ifidx)
+		ifidx = nl80211_get_ifidx(cb);
+	if (ifidx < 0)
+		return ifidx;
+
+	cb->args[0] = ifidx;
+
+	rtnl_lock();
+
+	*dev = __dev_get_by_index(sock_net(skb->sk), ifidx);
+	if (!*dev) {
+		err = -ENODEV;
+		goto out_rtnl;
+	}
+
+	*rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
+	if (IS_ERR(dev)) {
+		err = PTR_ERR(dev);
+		goto out_rtnl;
+	}
+
+	return 0;
+ out_rtnl:
+	rtnl_unlock();
+	return err;
+}
+
+static void nl80211_finish_netdev_dump(struct cfg80211_registered_device *rdev)
+{
+	cfg80211_unlock_rdev(rdev);
+	rtnl_unlock();
+}
+
 /* IE validation */
 static bool is_valid_ie_attr(const struct nlattr *attr)
 {
@@ -255,6 +308,7 @@
 struct key_parse {
 	struct key_params p;
 	int idx;
+	int type;
 	bool def, defmgmt;
 };
 
@@ -285,6 +339,12 @@
 	if (tb[NL80211_KEY_CIPHER])
 		k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
 
+	if (tb[NL80211_KEY_TYPE]) {
+		k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
+		if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
+			return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -309,6 +369,12 @@
 	k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
 	k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
 
+	if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
+		k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
+		if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
+			return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -318,6 +384,7 @@
 
 	memset(k, 0, sizeof(*k));
 	k->idx = -1;
+	k->type = -1;
 
 	if (info->attrs[NL80211_ATTR_KEY])
 		err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k);
@@ -382,7 +449,7 @@
 		} else if (parse.defmgmt)
 			goto error;
 		err = cfg80211_validate_key_settings(rdev, &parse.p,
-						     parse.idx, NULL);
+						     parse.idx, false, NULL);
 		if (err)
 			goto error;
 		result->params[parse.idx].cipher = parse.p.cipher;
@@ -401,18 +468,17 @@
 {
 	ASSERT_WDEV_LOCK(wdev);
 
-	if (!netif_running(wdev->netdev))
-		return -ENETDOWN;
-
 	switch (wdev->iftype) {
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_P2P_GO:
 		break;
 	case NL80211_IFTYPE_ADHOC:
 		if (!wdev->current_bss)
 			return -ENOLINK;
 		break;
 	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_P2P_CLIENT:
 		if (wdev->sme_state != CFG80211_SME_CONNECTED)
 			return -ENOLINK;
 		break;
@@ -437,6 +503,8 @@
 	struct ieee80211_rate *rate;
 	int i;
 	u16 ifmodes = dev->wiphy.interface_modes;
+	const struct ieee80211_txrx_stypes *mgmt_stypes =
+				dev->wiphy.mgmt_stypes;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
 	if (!hdr)
@@ -464,6 +532,9 @@
 	NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
 		    dev->wiphy.max_scan_ie_len);
 
+	if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)
+		NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN);
+
 	NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
 		sizeof(u32) * dev->wiphy.n_cipher_suites,
 		dev->wiphy.cipher_suites);
@@ -471,6 +542,9 @@
 	NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
 		   dev->wiphy.max_num_pmkids);
 
+	if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL)
+		NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE);
+
 	nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
 	if (!nl_modes)
 		goto nla_put_failure;
@@ -587,12 +661,13 @@
 	CMD(flush_pmksa, FLUSH_PMKSA);
 	CMD(remain_on_channel, REMAIN_ON_CHANNEL);
 	CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
-	CMD(action, ACTION);
+	CMD(mgmt_tx, FRAME);
 	if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
 		i++;
 		NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
 	}
 	CMD(set_channel, SET_CHANNEL);
+	CMD(set_wds_peer, SET_WDS_PEER);
 
 #undef CMD
 
@@ -608,6 +683,55 @@
 
 	nla_nest_end(msg, nl_cmds);
 
+	if (mgmt_stypes) {
+		u16 stypes;
+		struct nlattr *nl_ftypes, *nl_ifs;
+		enum nl80211_iftype ift;
+
+		nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES);
+		if (!nl_ifs)
+			goto nla_put_failure;
+
+		for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
+			nl_ftypes = nla_nest_start(msg, ift);
+			if (!nl_ftypes)
+				goto nla_put_failure;
+			i = 0;
+			stypes = mgmt_stypes[ift].tx;
+			while (stypes) {
+				if (stypes & 1)
+					NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE,
+						    (i << 4) | IEEE80211_FTYPE_MGMT);
+				stypes >>= 1;
+				i++;
+			}
+			nla_nest_end(msg, nl_ftypes);
+		}
+
+		nla_nest_end(msg, nl_ifs);
+
+		nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES);
+		if (!nl_ifs)
+			goto nla_put_failure;
+
+		for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) {
+			nl_ftypes = nla_nest_start(msg, ift);
+			if (!nl_ftypes)
+				goto nla_put_failure;
+			i = 0;
+			stypes = mgmt_stypes[ift].rx;
+			while (stypes) {
+				if (stypes & 1)
+					NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE,
+						    (i << 4) | IEEE80211_FTYPE_MGMT);
+				stypes >>= 1;
+				i++;
+			}
+			nla_nest_end(msg, nl_ftypes);
+		}
+		nla_nest_end(msg, nl_ifs);
+	}
+
 	return genlmsg_end(msg, hdr);
 
  nla_put_failure:
@@ -644,28 +768,18 @@
 static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
 {
 	struct sk_buff *msg;
-	struct cfg80211_registered_device *dev;
-
-	dev = cfg80211_get_dev_from_info(info);
-	if (IS_ERR(dev))
-		return PTR_ERR(dev);
+	struct cfg80211_registered_device *dev = info->user_ptr[0];
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 	if (!msg)
-		goto out_err;
+		return -ENOMEM;
 
-	if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
-		goto out_free;
-
-	cfg80211_unlock_rdev(dev);
+	if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0) {
+		nlmsg_free(msg);
+		return -ENOBUFS;
+	}
 
 	return genlmsg_reply(msg, info);
-
- out_free:
-	nlmsg_free(msg);
- out_err:
-	cfg80211_unlock_rdev(dev);
-	return -ENOBUFS;
 }
 
 static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
@@ -709,7 +823,8 @@
 		wdev->iftype == NL80211_IFTYPE_AP ||
 		wdev->iftype == NL80211_IFTYPE_WDS ||
 		wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
-		wdev->iftype == NL80211_IFTYPE_MONITOR;
+		wdev->iftype == NL80211_IFTYPE_MONITOR ||
+		wdev->iftype == NL80211_IFTYPE_P2P_GO;
 }
 
 static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
@@ -753,38 +868,48 @@
 
 static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *netdev;
-	int result;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *netdev = info->user_ptr[1];
 
-	rtnl_lock();
-
-	result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev);
-	if (result)
-		goto unlock;
-
-	result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info);
-
- unlock:
-	rtnl_unlock();
-
-	return result;
+	return __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info);
 }
 
+static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	const u8 *bssid;
+
+	if (!info->attrs[NL80211_ATTR_MAC])
+		return -EINVAL;
+
+	if (netif_running(dev))
+		return -EBUSY;
+
+	if (!rdev->ops->set_wds_peer)
+		return -EOPNOTSUPP;
+
+	if (wdev->iftype != NL80211_IFTYPE_WDS)
+		return -EOPNOTSUPP;
+
+	bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
+	return rdev->ops->set_wds_peer(wdev->wiphy, dev, bssid);
+}
+
+
 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev;
 	struct net_device *netdev = NULL;
 	struct wireless_dev *wdev;
-	int result, rem_txq_params = 0;
+	int result = 0, rem_txq_params = 0;
 	struct nlattr *nl_txq_params;
 	u32 changed;
 	u8 retry_short = 0, retry_long = 0;
 	u32 frag_threshold = 0, rts_threshold = 0;
 	u8 coverage_class = 0;
 
-	rtnl_lock();
-
 	/*
 	 * Try to find the wiphy and netdev. Normally this
 	 * function shouldn't need the netdev, but this is
@@ -811,8 +936,7 @@
 		rdev = __cfg80211_rdev_from_info(info);
 		if (IS_ERR(rdev)) {
 			mutex_unlock(&cfg80211_mutex);
-			result = PTR_ERR(rdev);
-			goto unlock;
+			return PTR_ERR(rdev);
 		}
 		wdev = NULL;
 		netdev = NULL;
@@ -994,8 +1118,6 @@
 	mutex_unlock(&rdev->mtx);
 	if (netdev)
 		dev_put(netdev);
- unlock:
-	rtnl_unlock();
 	return result;
 }
 
@@ -1075,33 +1197,20 @@
 static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
 {
 	struct sk_buff *msg;
-	struct cfg80211_registered_device *dev;
-	struct net_device *netdev;
-	int err;
-
-	err = get_rdev_dev_by_info_ifindex(info, &dev, &netdev);
-	if (err)
-		return err;
+	struct cfg80211_registered_device *dev = info->user_ptr[0];
+	struct net_device *netdev = info->user_ptr[1];
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 	if (!msg)
-		goto out_err;
+		return -ENOMEM;
 
 	if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
-			       dev, netdev) < 0)
-		goto out_free;
-
-	dev_put(netdev);
-	cfg80211_unlock_rdev(dev);
+			       dev, netdev) < 0) {
+		nlmsg_free(msg);
+		return -ENOBUFS;
+	}
 
 	return genlmsg_reply(msg, info);
-
- out_free:
-	nlmsg_free(msg);
- out_err:
-	dev_put(netdev);
-	cfg80211_unlock_rdev(dev);
-	return -ENOBUFS;
 }
 
 static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
@@ -1161,39 +1270,29 @@
 
 static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct vif_params params;
 	int err;
 	enum nl80211_iftype otype, ntype;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	u32 _flags, *flags = NULL;
 	bool change = false;
 
 	memset(&params, 0, sizeof(params));
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
 	otype = ntype = dev->ieee80211_ptr->iftype;
 
 	if (info->attrs[NL80211_ATTR_IFTYPE]) {
 		ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
 		if (otype != ntype)
 			change = true;
-		if (ntype > NL80211_IFTYPE_MAX) {
-			err = -EINVAL;
-			goto unlock;
-		}
+		if (ntype > NL80211_IFTYPE_MAX)
+			return -EINVAL;
 	}
 
 	if (info->attrs[NL80211_ATTR_MESH_ID]) {
-		if (ntype != NL80211_IFTYPE_MESH_POINT) {
-			err = -EINVAL;
-			goto unlock;
-		}
+		if (ntype != NL80211_IFTYPE_MESH_POINT)
+			return -EINVAL;
 		params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
 		params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
 		change = true;
@@ -1204,20 +1303,18 @@
 		change = true;
 		err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
 		if (err)
-			goto unlock;
+			return err;
 	} else {
 		params.use_4addr = -1;
 	}
 
 	if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
-		if (ntype != NL80211_IFTYPE_MONITOR) {
-			err = -EINVAL;
-			goto unlock;
-		}
+		if (ntype != NL80211_IFTYPE_MONITOR)
+			return -EINVAL;
 		err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
 					  &_flags);
 		if (err)
-			goto unlock;
+			return err;
 
 		flags = &_flags;
 		change = true;
@@ -1231,17 +1328,12 @@
 	if (!err && params.use_4addr != -1)
 		dev->ieee80211_ptr->use_4addr = params.use_4addr;
 
- unlock:
-	dev_put(dev);
-	cfg80211_unlock_rdev(rdev);
- unlock_rtnl:
-	rtnl_unlock();
 	return err;
 }
 
 static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct vif_params params;
 	int err;
 	enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
@@ -1258,19 +1350,9 @@
 			return -EINVAL;
 	}
 
-	rtnl_lock();
-
-	rdev = cfg80211_get_dev_from_info(info);
-	if (IS_ERR(rdev)) {
-		err = PTR_ERR(rdev);
-		goto unlock_rtnl;
-	}
-
 	if (!rdev->ops->add_virtual_intf ||
-	    !(rdev->wiphy.interface_modes & (1 << type))) {
-		err = -EOPNOTSUPP;
-		goto unlock;
-	}
+	    !(rdev->wiphy.interface_modes & (1 << type)))
+		return -EOPNOTSUPP;
 
 	if (type == NL80211_IFTYPE_MESH_POINT &&
 	    info->attrs[NL80211_ATTR_MESH_ID]) {
@@ -1282,7 +1364,7 @@
 		params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
 		err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
 		if (err)
-			goto unlock;
+			return err;
 	}
 
 	err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
@@ -1292,38 +1374,18 @@
 		nla_data(info->attrs[NL80211_ATTR_IFNAME]),
 		type, err ? NULL : &flags, &params);
 
- unlock:
-	cfg80211_unlock_rdev(rdev);
- unlock_rtnl:
-	rtnl_unlock();
 	return err;
 }
 
 static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	int err;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 
-	rtnl_lock();
+	if (!rdev->ops->del_virtual_intf)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->del_virtual_intf) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	err = rdev->ops->del_virtual_intf(&rdev->wiphy, dev);
-
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- unlock_rtnl:
-	rtnl_unlock();
-	return err;
+	return rdev->ops->del_virtual_intf(&rdev->wiphy, dev);
 }
 
 struct get_key_cookie {
@@ -1376,11 +1438,12 @@
 
 static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	int err;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	u8 key_idx = 0;
-	u8 *mac_addr = NULL;
+	const u8 *mac_addr = NULL;
+	bool pairwise;
 	struct get_key_cookie cookie = {
 		.error = 0,
 	};
@@ -1396,30 +1459,28 @@
 	if (info->attrs[NL80211_ATTR_MAC])
 		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->get_key) {
-		err = -EOPNOTSUPP;
-		goto out;
+	pairwise = !!mac_addr;
+	if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
+		u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
+		if (kt >= NUM_NL80211_KEYTYPES)
+			return -EINVAL;
+		if (kt != NL80211_KEYTYPE_GROUP &&
+		    kt != NL80211_KEYTYPE_PAIRWISE)
+			return -EINVAL;
+		pairwise = kt == NL80211_KEYTYPE_PAIRWISE;
 	}
 
+	if (!rdev->ops->get_key)
+		return -EOPNOTSUPP;
+
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!msg) {
-		err = -ENOMEM;
-		goto out;
-	}
+	if (!msg)
+		return -ENOMEM;
 
 	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
 			     NL80211_CMD_NEW_KEY);
-
-	if (IS_ERR(hdr)) {
-		err = PTR_ERR(hdr);
-		goto free_msg;
-	}
+	if (IS_ERR(hdr))
+		return PTR_ERR(hdr);
 
 	cookie.msg = msg;
 	cookie.idx = key_idx;
@@ -1429,8 +1490,12 @@
 	if (mac_addr)
 		NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
 
-	err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, mac_addr,
-				&cookie, get_key_callback);
+	if (pairwise && mac_addr &&
+	    !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
+		return -ENOENT;
+
+	err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, pairwise,
+				 mac_addr, &cookie, get_key_callback);
 
 	if (err)
 		goto free_msg;
@@ -1439,28 +1504,21 @@
 		goto nla_put_failure;
 
 	genlmsg_end(msg, hdr);
-	err = genlmsg_reply(msg, info);
-	goto out;
+	return genlmsg_reply(msg, info);
 
  nla_put_failure:
 	err = -ENOBUFS;
  free_msg:
 	nlmsg_free(msg);
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- unlock_rtnl:
-	rtnl_unlock();
-
 	return err;
 }
 
 static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct key_parse key;
 	int err;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	int (*func)(struct wiphy *wiphy, struct net_device *netdev,
 		    u8 key_index);
 
@@ -1475,21 +1533,13 @@
 	if (!key.def && !key.defmgmt)
 		return -EINVAL;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
 	if (key.def)
 		func = rdev->ops->set_default_key;
 	else
 		func = rdev->ops->set_default_mgmt_key;
 
-	if (!func) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!func)
+		return -EOPNOTSUPP;
 
 	wdev_lock(dev->ieee80211_ptr);
 	err = nl80211_key_allowed(dev->ieee80211_ptr);
@@ -1506,23 +1556,16 @@
 #endif
 	wdev_unlock(dev->ieee80211_ptr);
 
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-
- unlock_rtnl:
-	rtnl_unlock();
-
 	return err;
 }
 
 static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	int err;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	struct key_parse key;
-	u8 *mac_addr = NULL;
+	const u8 *mac_addr = NULL;
 
 	err = nl80211_parse_key(info, &key);
 	if (err)
@@ -1534,43 +1577,42 @@
 	if (info->attrs[NL80211_ATTR_MAC])
 		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->add_key) {
-		err = -EOPNOTSUPP;
-		goto out;
+	if (key.type == -1) {
+		if (mac_addr)
+			key.type = NL80211_KEYTYPE_PAIRWISE;
+		else
+			key.type = NL80211_KEYTYPE_GROUP;
 	}
 
-	if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) {
-		err = -EINVAL;
-		goto out;
-	}
+	/* for now */
+	if (key.type != NL80211_KEYTYPE_PAIRWISE &&
+	    key.type != NL80211_KEYTYPE_GROUP)
+		return -EINVAL;
+
+	if (!rdev->ops->add_key)
+		return -EOPNOTSUPP;
+
+	if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
+					   key.type == NL80211_KEYTYPE_PAIRWISE,
+					   mac_addr))
+		return -EINVAL;
 
 	wdev_lock(dev->ieee80211_ptr);
 	err = nl80211_key_allowed(dev->ieee80211_ptr);
 	if (!err)
 		err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx,
+					 key.type == NL80211_KEYTYPE_PAIRWISE,
 					 mac_addr, &key.p);
 	wdev_unlock(dev->ieee80211_ptr);
 
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- unlock_rtnl:
-	rtnl_unlock();
-
 	return err;
 }
 
 static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	int err;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	u8 *mac_addr = NULL;
 	struct key_parse key;
 
@@ -1581,21 +1623,32 @@
 	if (info->attrs[NL80211_ATTR_MAC])
 		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->del_key) {
-		err = -EOPNOTSUPP;
-		goto out;
+	if (key.type == -1) {
+		if (mac_addr)
+			key.type = NL80211_KEYTYPE_PAIRWISE;
+		else
+			key.type = NL80211_KEYTYPE_GROUP;
 	}
 
+	/* for now */
+	if (key.type != NL80211_KEYTYPE_PAIRWISE &&
+	    key.type != NL80211_KEYTYPE_GROUP)
+		return -EINVAL;
+
+	if (!rdev->ops->del_key)
+		return -EOPNOTSUPP;
+
 	wdev_lock(dev->ieee80211_ptr);
 	err = nl80211_key_allowed(dev->ieee80211_ptr);
+
+	if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr &&
+	    !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
+		err = -ENOENT;
+
 	if (!err)
-		err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr);
+		err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx,
+					 key.type == NL80211_KEYTYPE_PAIRWISE,
+					 mac_addr);
 
 #ifdef CONFIG_CFG80211_WEXT
 	if (!err) {
@@ -1607,13 +1660,6 @@
 #endif
 	wdev_unlock(dev->ieee80211_ptr);
 
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-
- unlock_rtnl:
-	rtnl_unlock();
-
 	return err;
 }
 
@@ -1621,35 +1667,25 @@
 {
         int (*call)(struct wiphy *wiphy, struct net_device *dev,
 		    struct beacon_parameters *info);
-	struct cfg80211_registered_device *rdev;
-	int err;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct beacon_parameters params;
 	int haveinfo = 0;
 
 	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]))
 		return -EINVAL;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EOPNOTSUPP;
 
 	switch (info->genlhdr->cmd) {
 	case NL80211_CMD_NEW_BEACON:
 		/* these are required for NEW_BEACON */
 		if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
 		    !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
-		    !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
-			err = -EINVAL;
-			goto out;
-		}
+		    !info->attrs[NL80211_ATTR_BEACON_HEAD])
+			return -EINVAL;
 
 		call = rdev->ops->add_beacon;
 		break;
@@ -1658,14 +1694,11 @@
 		break;
 	default:
 		WARN_ON(1);
-		err = -EOPNOTSUPP;
-		goto out;
+		return -EOPNOTSUPP;
 	}
 
-	if (!call) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!call)
+		return -EOPNOTSUPP;
 
 	memset(&params, 0, sizeof(params));
 
@@ -1695,52 +1728,25 @@
 		haveinfo = 1;
 	}
 
-	if (!haveinfo) {
-		err = -EINVAL;
-		goto out;
-	}
+	if (!haveinfo)
+		return -EINVAL;
 
-	err = call(&rdev->wiphy, dev, &params);
-
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- unlock_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return call(&rdev->wiphy, dev, &params);
 }
 
 static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	int err;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 
-	rtnl_lock();
+	if (!rdev->ops->del_beacon)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EOPNOTSUPP;
 
-	if (!rdev->ops->del_beacon) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-	err = rdev->ops->del_beacon(&rdev->wiphy, dev);
-
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- unlock_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return rdev->ops->del_beacon(&rdev->wiphy, dev);
 }
 
 static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
@@ -1861,6 +1867,12 @@
 	if (sinfo->filled & STATION_INFO_TX_PACKETS)
 		NLA_PUT_U32(msg, NL80211_STA_INFO_TX_PACKETS,
 			    sinfo->tx_packets);
+	if (sinfo->filled & STATION_INFO_TX_RETRIES)
+		NLA_PUT_U32(msg, NL80211_STA_INFO_TX_RETRIES,
+			    sinfo->tx_retries);
+	if (sinfo->filled & STATION_INFO_TX_FAILED)
+		NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED,
+			    sinfo->tx_failed);
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);
@@ -1877,28 +1889,12 @@
 	struct cfg80211_registered_device *dev;
 	struct net_device *netdev;
 	u8 mac_addr[ETH_ALEN];
-	int ifidx = cb->args[0];
 	int sta_idx = cb->args[1];
 	int err;
 
-	if (!ifidx)
-		ifidx = nl80211_get_ifidx(cb);
-	if (ifidx < 0)
-		return ifidx;
-
-	rtnl_lock();
-
-	netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
-	if (!netdev) {
-		err = -ENODEV;
-		goto out_rtnl;
-	}
-
-	dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
-	if (IS_ERR(dev)) {
-		err = PTR_ERR(dev);
-		goto out_rtnl;
-	}
+	err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
+	if (err)
+		return err;
 
 	if (!dev->ops->dump_station) {
 		err = -EOPNOTSUPP;
@@ -1928,21 +1924,19 @@
 	cb->args[1] = sta_idx;
 	err = skb->len;
  out_err:
-	cfg80211_unlock_rdev(dev);
- out_rtnl:
-	rtnl_unlock();
+	nl80211_finish_netdev_dump(dev);
 
 	return err;
 }
 
 static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	int err;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct station_info sinfo;
 	struct sk_buff *msg;
 	u8 *mac_addr = NULL;
+	int err;
 
 	memset(&sinfo, 0, sizeof(sinfo));
 
@@ -1951,41 +1945,24 @@
 
 	mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
-
-	if (!rdev->ops->get_station) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!rdev->ops->get_station)
+		return -EOPNOTSUPP;
 
 	err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo);
 	if (err)
-		goto out;
+		return err;
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
-				 dev, mac_addr, &sinfo) < 0)
-		goto out_free;
+				 dev, mac_addr, &sinfo) < 0) {
+		nlmsg_free(msg);
+		return -ENOBUFS;
+	}
 
-	err = genlmsg_reply(msg, info);
-	goto out;
-
- out_free:
-	nlmsg_free(msg);
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return genlmsg_reply(msg, info);
 }
 
 /*
@@ -2015,9 +1992,9 @@
 
 static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	int err;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	struct station_parameters params;
 	u8 *mac_addr = NULL;
 
@@ -2055,12 +2032,6 @@
 		params.plink_action =
 		    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
-
 	err = get_vlan(info, rdev, &params.vlan);
 	if (err)
 		goto out;
@@ -2071,10 +2042,12 @@
 	switch (dev->ieee80211_ptr->iftype) {
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_P2P_GO:
 		/* disallow mesh-specific things */
 		if (params.plink_action)
 			err = -EINVAL;
 		break;
+	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_STATION:
 		/* disallow everything but AUTHORIZED flag */
 		if (params.plink_action)
@@ -2120,19 +2093,15 @@
  out:
 	if (params.vlan)
 		dev_put(params.vlan);
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
 
 	return err;
 }
 
 static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	int err;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	struct station_parameters params;
 	u8 *mac_addr = NULL;
 
@@ -2169,17 +2138,10 @@
 	if (parse_station_flags(info, &params))
 		return -EINVAL;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
-
 	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
-	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) {
-		err = -EINVAL;
-		goto out;
-	}
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EINVAL;
 
 	err = get_vlan(info, rdev, &params.vlan);
 	if (err)
@@ -2193,61 +2155,33 @@
 		goto out;
 	}
 
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
-
 	err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, &params);
 
  out:
 	if (params.vlan)
 		dev_put(params.vlan);
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
 	return err;
 }
 
 static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	int err;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	u8 *mac_addr = NULL;
 
 	if (info->attrs[NL80211_ATTR_MAC])
 		mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
-
 	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
 	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
-	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
-		err = -EINVAL;
-		goto out;
-	}
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EINVAL;
 
-	if (!rdev->ops->del_station) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!rdev->ops->del_station)
+		return -EOPNOTSUPP;
 
-	err = rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
-
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
 }
 
 static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
@@ -2310,28 +2244,12 @@
 	struct net_device *netdev;
 	u8 dst[ETH_ALEN];
 	u8 next_hop[ETH_ALEN];
-	int ifidx = cb->args[0];
 	int path_idx = cb->args[1];
 	int err;
 
-	if (!ifidx)
-		ifidx = nl80211_get_ifidx(cb);
-	if (ifidx < 0)
-		return ifidx;
-
-	rtnl_lock();
-
-	netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
-	if (!netdev) {
-		err = -ENODEV;
-		goto out_rtnl;
-	}
-
-	dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
-	if (IS_ERR(dev)) {
-		err = PTR_ERR(dev);
-		goto out_rtnl;
-	}
+	err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
+	if (err)
+		return err;
 
 	if (!dev->ops->dump_mpath) {
 		err = -EOPNOTSUPP;
@@ -2365,18 +2283,15 @@
 	cb->args[1] = path_idx;
 	err = skb->len;
  out_err:
-	cfg80211_unlock_rdev(dev);
- out_rtnl:
-	rtnl_unlock();
-
+	nl80211_finish_netdev_dump(dev);
 	return err;
 }
 
 static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	int err;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	struct mpath_info pinfo;
 	struct sk_buff *msg;
 	u8 *dst = NULL;
@@ -2389,53 +2304,33 @@
 
 	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-	rtnl_lock();
+	if (!rdev->ops->get_mpath)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
-
-	if (!rdev->ops->get_mpath) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
+		return -EOPNOTSUPP;
 
 	err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo);
 	if (err)
-		goto out;
+		return err;
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
-				 dev, dst, next_hop, &pinfo) < 0)
-		goto out_free;
+				 dev, dst, next_hop, &pinfo) < 0) {
+		nlmsg_free(msg);
+		return -ENOBUFS;
+	}
 
-	err = genlmsg_reply(msg, info);
-	goto out;
-
- out_free:
-	nlmsg_free(msg);
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return genlmsg_reply(msg, info);
 }
 
 static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	int err;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	u8 *dst = NULL;
 	u8 *next_hop = NULL;
 
@@ -2448,42 +2343,19 @@
 	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
 	next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
 
-	rtnl_lock();
+	if (!rdev->ops->change_mpath)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
+		return -EOPNOTSUPP;
 
-	if (!rdev->ops->change_mpath) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
-
-	err = rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
-
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
 }
+
 static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	int err;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	u8 *dst = NULL;
 	u8 *next_hop = NULL;
 
@@ -2496,75 +2368,34 @@
 	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
 	next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
 
-	rtnl_lock();
+	if (!rdev->ops->add_mpath)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
+		return -EOPNOTSUPP;
 
-	if (!rdev->ops->add_mpath) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
-
-	err = rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
-
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
 }
 
 static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	int err;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	u8 *dst = NULL;
 
 	if (info->attrs[NL80211_ATTR_MAC])
 		dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-	rtnl_lock();
+	if (!rdev->ops->del_mpath)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
-
-	if (!rdev->ops->del_mpath) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	err = rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
-
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
 }
 
 static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	int err;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct bss_parameters params;
 
 	memset(&params, 0, sizeof(params));
@@ -2592,31 +2423,14 @@
 	if (info->attrs[NL80211_ATTR_AP_ISOLATE])
 		params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
 
-	rtnl_lock();
+	if (!rdev->ops->change_bss)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EOPNOTSUPP;
 
-	if (!rdev->ops->change_bss) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	err = rdev->ops->change_bss(&rdev->wiphy, dev, &params);
-
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return rdev->ops->change_bss(&rdev->wiphy, dev, &params);
 }
 
 static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
@@ -2695,37 +2509,26 @@
 static int nl80211_get_mesh_params(struct sk_buff *skb,
 	struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct mesh_config cur_params;
 	int err;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	void *hdr;
 	struct nlattr *pinfoattr;
 	struct sk_buff *msg;
 
-	rtnl_lock();
-
-	/* Look up our device */
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
-
-	if (!rdev->ops->get_mesh_params) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!rdev->ops->get_mesh_params)
+		return -EOPNOTSUPP;
 
 	/* Get the mesh params */
 	err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params);
 	if (err)
-		goto out;
+		return err;
 
 	/* Draw up a netlink message to send back */
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!msg) {
-		err = -ENOBUFS;
-		goto out;
-	}
+	if (!msg)
+		return -ENOMEM;
 	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
 			     NL80211_CMD_GET_MESH_PARAMS);
 	if (!hdr)
@@ -2764,21 +2567,12 @@
 			cur_params.dot11MeshHWMPRootMode);
 	nla_nest_end(msg, pinfoattr);
 	genlmsg_end(msg, hdr);
-	err = genlmsg_reply(msg, info);
-	goto out;
+	return genlmsg_reply(msg, info);
 
  nla_put_failure:
 	genlmsg_cancel(msg, hdr);
 	nlmsg_free(msg);
-	err = -EMSGSIZE;
- out:
-	/* Cleanup */
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return -ENOBUFS;
 }
 
 #define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \
@@ -2808,10 +2602,9 @@
 
 static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
 {
-	int err;
 	u32 mask;
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct mesh_config cfg;
 	struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
 	struct nlattr *parent_attr;
@@ -2823,16 +2616,8 @@
 			parent_attr, nl80211_meshconf_params_policy))
 		return -EINVAL;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
-
-	if (!rdev->ops->set_mesh_params) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!rdev->ops->set_mesh_params)
+		return -EOPNOTSUPP;
 
 	/* This makes sure that there aren't more than 32 mesh config
 	 * parameters (otherwise our bitfield scheme would not work.) */
@@ -2878,16 +2663,7 @@
 			nla_get_u8);
 
 	/* Apply changes */
-	err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
-
- out:
-	/* cleanup */
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
 }
 
 #undef FILL_IN_MESH_PARAM_IF_SET
@@ -3070,8 +2846,8 @@
 
 static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct cfg80211_scan_request *request;
 	struct cfg80211_ssid *ssid;
 	struct ieee80211_channel *channel;
@@ -3084,36 +2860,19 @@
 	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
 		return -EINVAL;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
-
 	wiphy = &rdev->wiphy;
 
-	if (!rdev->ops->scan) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!rdev->ops->scan)
+		return -EOPNOTSUPP;
 
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
-
-	if (rdev->scan_req) {
-		err = -EBUSY;
-		goto out;
-	}
+	if (rdev->scan_req)
+		return -EBUSY;
 
 	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
 		n_channels = validate_scan_freqs(
 				info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
-		if (!n_channels) {
-			err = -EINVAL;
-			goto out;
-		}
+		if (!n_channels)
+			return -EINVAL;
 	} else {
 		n_channels = 0;
 
@@ -3126,29 +2885,23 @@
 		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
 			n_ssids++;
 
-	if (n_ssids > wiphy->max_scan_ssids) {
-		err = -EINVAL;
-		goto out;
-	}
+	if (n_ssids > wiphy->max_scan_ssids)
+		return -EINVAL;
 
 	if (info->attrs[NL80211_ATTR_IE])
 		ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
 	else
 		ie_len = 0;
 
-	if (ie_len > wiphy->max_scan_ie_len) {
-		err = -EINVAL;
-		goto out;
-	}
+	if (ie_len > wiphy->max_scan_ie_len)
+		return -EINVAL;
 
 	request = kzalloc(sizeof(*request)
 			+ sizeof(*ssid) * n_ssids
 			+ sizeof(channel) * n_channels
 			+ ie_len, GFP_KERNEL);
-	if (!request) {
-		err = -ENOMEM;
-		goto out;
-	}
+	if (!request)
+		return -ENOMEM;
 
 	if (n_ssids)
 		request->ssids = (void *)&request->channels[n_channels];
@@ -3236,18 +2989,11 @@
 	if (!err) {
 		nl80211_send_scan_start(rdev, dev);
 		dev_hold(dev);
-	}
-
+	} else {
  out_free:
-	if (err) {
 		rdev->scan_req = NULL;
 		kfree(request);
 	}
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
 
 	return err;
 }
@@ -3306,6 +3052,7 @@
 	}
 
 	switch (wdev->iftype) {
+	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_STATION:
 		if (intbss == wdev->current_bss)
 			NLA_PUT_U32(msg, NL80211_BSS_STATUS,
@@ -3343,25 +3090,12 @@
 	struct net_device *dev;
 	struct cfg80211_internal_bss *scan;
 	struct wireless_dev *wdev;
-	int ifidx = cb->args[0];
 	int start = cb->args[1], idx = 0;
 	int err;
 
-	if (!ifidx)
-		ifidx = nl80211_get_ifidx(cb);
-	if (ifidx < 0)
-		return ifidx;
-	cb->args[0] = ifidx;
-
-	dev = dev_get_by_index(sock_net(skb->sk), ifidx);
-	if (!dev)
-		return -ENODEV;
-
-	rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
-	if (IS_ERR(rdev)) {
-		err = PTR_ERR(rdev);
-		goto out_put_netdev;
-	}
+	err = nl80211_prepare_netdev_dump(skb, cb, &rdev, &dev);
+	if (err)
+		return err;
 
 	wdev = dev->ieee80211_ptr;
 
@@ -3377,21 +3111,17 @@
 				cb->nlh->nlmsg_seq, NLM_F_MULTI,
 				rdev, wdev, scan) < 0) {
 			idx--;
-			goto out;
+			break;
 		}
 	}
 
- out:
 	spin_unlock_bh(&rdev->bss_lock);
 	wdev_unlock(wdev);
 
 	cb->args[1] = idx;
-	err = skb->len;
-	cfg80211_unlock_rdev(rdev);
- out_put_netdev:
-	dev_put(dev);
+	nl80211_finish_netdev_dump(rdev);
 
-	return err;
+	return skb->len;
 }
 
 static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq,
@@ -3421,6 +3151,23 @@
 	if (survey->filled & SURVEY_INFO_NOISE_DBM)
 		NLA_PUT_U8(msg, NL80211_SURVEY_INFO_NOISE,
 			    survey->noise);
+	if (survey->filled & SURVEY_INFO_IN_USE)
+		NLA_PUT_FLAG(msg, NL80211_SURVEY_INFO_IN_USE);
+	if (survey->filled & SURVEY_INFO_CHANNEL_TIME)
+		NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME,
+			    survey->channel_time);
+	if (survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
+		NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
+			    survey->channel_time_busy);
+	if (survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
+		NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
+			    survey->channel_time_ext_busy);
+	if (survey->filled & SURVEY_INFO_CHANNEL_TIME_RX)
+		NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
+			    survey->channel_time_rx);
+	if (survey->filled & SURVEY_INFO_CHANNEL_TIME_TX)
+		NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
+			    survey->channel_time_tx);
 
 	nla_nest_end(msg, infoattr);
 
@@ -3437,29 +3184,12 @@
 	struct survey_info survey;
 	struct cfg80211_registered_device *dev;
 	struct net_device *netdev;
-	int ifidx = cb->args[0];
 	int survey_idx = cb->args[1];
 	int res;
 
-	if (!ifidx)
-		ifidx = nl80211_get_ifidx(cb);
-	if (ifidx < 0)
-		return ifidx;
-	cb->args[0] = ifidx;
-
-	rtnl_lock();
-
-	netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
-	if (!netdev) {
-		res = -ENODEV;
-		goto out_rtnl;
-	}
-
-	dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
-	if (IS_ERR(dev)) {
-		res = PTR_ERR(dev);
-		goto out_rtnl;
-	}
+	res = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
+	if (res)
+		return res;
 
 	if (!dev->ops->dump_survey) {
 		res = -EOPNOTSUPP;
@@ -3487,10 +3217,7 @@
 	cb->args[1] = survey_idx;
 	res = skb->len;
  out_err:
-	cfg80211_unlock_rdev(dev);
- out_rtnl:
-	rtnl_unlock();
-
+	nl80211_finish_netdev_dump(dev);
 	return res;
 }
 
@@ -3523,8 +3250,8 @@
 
 static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct ieee80211_channel *chan;
 	const u8 *bssid, *ssid, *ie = NULL;
 	int err, ssid_len, ie_len = 0;
@@ -3552,6 +3279,8 @@
 		return err;
 
 	if (key.idx >= 0) {
+		if (key.type != -1 && key.type != NL80211_KEYTYPE_GROUP)
+			return -EINVAL;
 		if (!key.p.key || !key.p.key_len)
 			return -EINVAL;
 		if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
@@ -3566,34 +3295,31 @@
 		key.p.key = NULL;
 	}
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->auth) {
-		err = -EOPNOTSUPP;
-		goto out;
+	if (key.idx >= 0) {
+		int i;
+		bool ok = false;
+		for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
+			if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
+				ok = true;
+				break;
+			}
+		}
+		if (!ok)
+			return -EINVAL;
 	}
 
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!rdev->ops->auth)
+		return -EOPNOTSUPP;
 
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
+		return -EOPNOTSUPP;
 
 	bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
 	chan = ieee80211_get_channel(&rdev->wiphy,
 		nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
-	if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) {
-		err = -EINVAL;
-		goto out;
-	}
+	if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED))
+		return -EINVAL;
 
 	ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
 	ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
@@ -3604,27 +3330,19 @@
 	}
 
 	auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
-	if (!nl80211_valid_auth_type(auth_type)) {
-		err = -EINVAL;
-		goto out;
-	}
+	if (!nl80211_valid_auth_type(auth_type))
+		return -EINVAL;
 
 	local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
 
-	err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
-				 ssid, ssid_len, ie, ie_len,
-				 key.p.key, key.p.key_len, key.idx,
-				 local_state_change);
-
-out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-unlock_rtnl:
-	rtnl_unlock();
-	return err;
+	return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
+				  ssid, ssid_len, ie, ie_len,
+				  key.p.key, key.p.key_len, key.idx,
+				  local_state_change);
 }
 
-static int nl80211_crypto_settings(struct genl_info *info,
+static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
+				   struct genl_info *info,
 				   struct cfg80211_crypto_settings *settings,
 				   int cipher_limit)
 {
@@ -3632,6 +3350,19 @@
 
 	settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
 
+	if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
+		u16 proto;
+		proto = nla_get_u16(
+			info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
+		settings->control_port_ethertype = cpu_to_be16(proto);
+		if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
+		    proto != ETH_P_PAE)
+			return -EINVAL;
+		if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT])
+			settings->control_port_no_encrypt = true;
+	} else
+		settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE);
+
 	if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
 		void *data;
 		int len, i;
@@ -3691,8 +3422,8 @@
 
 static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct cfg80211_crypto_settings crypto;
 	struct ieee80211_channel *chan;
 	const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
@@ -3707,35 +3438,19 @@
 	    !info->attrs[NL80211_ATTR_WIPHY_FREQ])
 		return -EINVAL;
 
-	rtnl_lock();
+	if (!rdev->ops->assoc)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->assoc) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
+		return -EOPNOTSUPP;
 
 	bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
 	chan = ieee80211_get_channel(&rdev->wiphy,
 		nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
-	if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) {
-		err = -EINVAL;
-		goto out;
-	}
+	if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED))
+		return -EINVAL;
 
 	ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
 	ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
@@ -3750,35 +3465,28 @@
 			nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
 		if (mfp == NL80211_MFP_REQUIRED)
 			use_mfp = true;
-		else if (mfp != NL80211_MFP_NO) {
-			err = -EINVAL;
-			goto out;
-		}
+		else if (mfp != NL80211_MFP_NO)
+			return -EINVAL;
 	}
 
 	if (info->attrs[NL80211_ATTR_PREV_BSSID])
 		prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
 
-	err = nl80211_crypto_settings(info, &crypto, 1);
+	err = nl80211_crypto_settings(rdev, info, &crypto, 1);
 	if (!err)
 		err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
 					  ssid, ssid_len, ie, ie_len, use_mfp,
 					  &crypto);
 
-out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-unlock_rtnl:
-	rtnl_unlock();
 	return err;
 }
 
 static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	const u8 *ie = NULL, *bssid;
-	int err, ie_len = 0;
+	int ie_len = 0;
 	u16 reason_code;
 	bool local_state_change;
 
@@ -3791,34 +3499,19 @@
 	if (!info->attrs[NL80211_ATTR_REASON_CODE])
 		return -EINVAL;
 
-	rtnl_lock();
+	if (!rdev->ops->deauth)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->deauth) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
+		return -EOPNOTSUPP;
 
 	bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
 	reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
 	if (reason_code == 0) {
 		/* Reason Code 0 is reserved */
-		err = -EINVAL;
-		goto out;
+		return -EINVAL;
 	}
 
 	if (info->attrs[NL80211_ATTR_IE]) {
@@ -3828,23 +3521,16 @@
 
 	local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
 
-	err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
-				   local_state_change);
-
-out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-unlock_rtnl:
-	rtnl_unlock();
-	return err;
+	return cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
+				    local_state_change);
 }
 
 static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	const u8 *ie = NULL, *bssid;
-	int err, ie_len = 0;
+	int ie_len = 0;
 	u16 reason_code;
 	bool local_state_change;
 
@@ -3857,34 +3543,19 @@
 	if (!info->attrs[NL80211_ATTR_REASON_CODE])
 		return -EINVAL;
 
-	rtnl_lock();
+	if (!rdev->ops->disassoc)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->disassoc) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
+		return -EOPNOTSUPP;
 
 	bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
 	reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
 	if (reason_code == 0) {
 		/* Reason Code 0 is reserved */
-		err = -EINVAL;
-		goto out;
+		return -EINVAL;
 	}
 
 	if (info->attrs[NL80211_ATTR_IE]) {
@@ -3894,21 +3565,14 @@
 
 	local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
 
-	err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
-				     local_state_change);
-
-out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-unlock_rtnl:
-	rtnl_unlock();
-	return err;
+	return cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
+				      local_state_change);
 }
 
 static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct cfg80211_ibss_params ibss;
 	struct wiphy *wiphy;
 	struct cfg80211_cached_keys *connkeys = NULL;
@@ -3933,26 +3597,11 @@
 			return -EINVAL;
 	}
 
-	rtnl_lock();
+	if (!rdev->ops->join_ibss)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->join_ibss) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
+		return -EOPNOTSUPP;
 
 	wiphy = &rdev->wiphy;
 
@@ -3970,24 +3619,12 @@
 		nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
 	if (!ibss.channel ||
 	    ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
-	    ibss.channel->flags & IEEE80211_CHAN_DISABLED) {
-		err = -EINVAL;
-		goto out;
-	}
+	    ibss.channel->flags & IEEE80211_CHAN_DISABLED)
+		return -EINVAL;
 
 	ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
 	ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
 
-	if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
-		connkeys = nl80211_parse_connkeys(rdev,
-					info->attrs[NL80211_ATTR_KEYS]);
-		if (IS_ERR(connkeys)) {
-			err = PTR_ERR(connkeys);
-			connkeys = NULL;
-			goto out;
-		}
-	}
-
 	if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
 		u8 *rates =
 			nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
@@ -3997,10 +3634,8 @@
 			wiphy->bands[ibss.channel->band];
 		int i, j;
 
-		if (n_rates == 0) {
-			err = -EINVAL;
-			goto out;
-		}
+		if (n_rates == 0)
+			return -EINVAL;
 
 		for (i = 0; i < n_rates; i++) {
 			int rate = (rates[i] & 0x7f) * 5;
@@ -4013,77 +3648,36 @@
 					break;
 				}
 			}
-			if (!found) {
-				err = -EINVAL;
-				goto out;
-			}
-		}
-	} else {
-		/*
-		* If no rates were explicitly configured,
-		* use the mandatory rate set for 11b or
-		* 11a for maximum compatibility.
-		*/
-		struct ieee80211_supported_band *sband =
-			wiphy->bands[ibss.channel->band];
-		int j;
-		u32 flag = ibss.channel->band == IEEE80211_BAND_5GHZ ?
-			IEEE80211_RATE_MANDATORY_A :
-			IEEE80211_RATE_MANDATORY_B;
-
-		for (j = 0; j < sband->n_bitrates; j++) {
-			if (sband->bitrates[j].flags & flag)
-				ibss.basic_rates |= BIT(j);
+			if (!found)
+				return -EINVAL;
 		}
 	}
 
-	err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
+	if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
+		connkeys = nl80211_parse_connkeys(rdev,
+					info->attrs[NL80211_ATTR_KEYS]);
+		if (IS_ERR(connkeys))
+			return PTR_ERR(connkeys);
+	}
 
-out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-unlock_rtnl:
+	err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
 	if (err)
 		kfree(connkeys);
-	rtnl_unlock();
 	return err;
 }
 
 static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
-	int err;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 
-	rtnl_lock();
+	if (!rdev->ops->leave_ibss)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
+		return -EOPNOTSUPP;
 
-	if (!rdev->ops->leave_ibss) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
-
-	err = cfg80211_leave_ibss(rdev, dev, false);
-
-out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-unlock_rtnl:
-	rtnl_unlock();
-	return err;
+	return cfg80211_leave_ibss(rdev, dev, false);
 }
 
 #ifdef CONFIG_NL80211_TESTMODE
@@ -4093,20 +3687,12 @@
 
 static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	int err;
 
 	if (!info->attrs[NL80211_ATTR_TESTDATA])
 		return -EINVAL;
 
-	rtnl_lock();
-
-	rdev = cfg80211_get_dev_from_info(info);
-	if (IS_ERR(rdev)) {
-		err = PTR_ERR(rdev);
-		goto unlock_rtnl;
-	}
-
 	err = -EOPNOTSUPP;
 	if (rdev->ops->testmode_cmd) {
 		rdev->testmode_info = info;
@@ -4116,10 +3702,6 @@
 		rdev->testmode_info = NULL;
 	}
 
-	cfg80211_unlock_rdev(rdev);
-
- unlock_rtnl:
-	rtnl_unlock();
 	return err;
 }
 
@@ -4210,8 +3792,8 @@
 
 static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct cfg80211_connect_params connect;
 	struct wiphy *wiphy;
 	struct cfg80211_cached_keys *connkeys = NULL;
@@ -4236,25 +3818,14 @@
 
 	connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
 
-	err = nl80211_crypto_settings(info, &connect.crypto,
+	err = nl80211_crypto_settings(rdev, info, &connect.crypto,
 				      NL80211_MAX_NR_CIPHER_SUITES);
 	if (err)
 		return err;
-	rtnl_lock();
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
+		return -EOPNOTSUPP;
 
 	wiphy = &rdev->wiphy;
 
@@ -4273,39 +3844,27 @@
 			ieee80211_get_channel(wiphy,
 			    nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
 		if (!connect.channel ||
-		    connect.channel->flags & IEEE80211_CHAN_DISABLED) {
-			err = -EINVAL;
-			goto out;
-		}
+		    connect.channel->flags & IEEE80211_CHAN_DISABLED)
+			return -EINVAL;
 	}
 
 	if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
 		connkeys = nl80211_parse_connkeys(rdev,
 					info->attrs[NL80211_ATTR_KEYS]);
-		if (IS_ERR(connkeys)) {
-			err = PTR_ERR(connkeys);
-			connkeys = NULL;
-			goto out;
-		}
+		if (IS_ERR(connkeys))
+			return PTR_ERR(connkeys);
 	}
 
 	err = cfg80211_connect(rdev, dev, &connect, connkeys);
-
-out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-unlock_rtnl:
 	if (err)
 		kfree(connkeys);
-	rtnl_unlock();
 	return err;
 }
 
 static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
-	int err;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	u16 reason;
 
 	if (!info->attrs[NL80211_ATTR_REASON_CODE])
@@ -4316,35 +3875,16 @@
 	if (reason == 0)
 		return -EINVAL;
 
-	rtnl_lock();
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
-
-	err = cfg80211_disconnect(rdev, dev, reason, true);
-
-out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-unlock_rtnl:
-	rtnl_unlock();
-	return err;
+	return cfg80211_disconnect(rdev, dev, reason, true);
 }
 
 static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct net *net;
 	int err;
 	u32 pid;
@@ -4354,43 +3894,26 @@
 
 	pid = nla_get_u32(info->attrs[NL80211_ATTR_PID]);
 
-	rtnl_lock();
-
-	rdev = cfg80211_get_dev_from_info(info);
-	if (IS_ERR(rdev)) {
-		err = PTR_ERR(rdev);
-		goto out_rtnl;
-	}
-
 	net = get_net_ns_by_pid(pid);
-	if (IS_ERR(net)) {
-		err = PTR_ERR(net);
-		goto out;
-	}
+	if (IS_ERR(net))
+		return PTR_ERR(net);
 
 	err = 0;
 
 	/* check if anything to do */
-	if (net_eq(wiphy_net(&rdev->wiphy), net))
-		goto out_put_net;
+	if (!net_eq(wiphy_net(&rdev->wiphy), net))
+		err = cfg80211_switch_netns(rdev, net);
 
-	err = cfg80211_switch_netns(rdev, net);
- out_put_net:
 	put_net(net);
- out:
-	cfg80211_unlock_rdev(rdev);
- out_rtnl:
-	rtnl_unlock();
 	return err;
 }
 
 static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
 			struct cfg80211_pmksa *pmksa) = NULL;
-	int err;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	struct cfg80211_pmksa pmksa;
 
 	memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
@@ -4401,19 +3924,12 @@
 	if (!info->attrs[NL80211_ATTR_PMKID])
 		return -EINVAL;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
-
 	pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
 	pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
+		return -EOPNOTSUPP;
 
 	switch (info->genlhdr->cmd) {
 	case NL80211_CMD_SET_PMKSA:
@@ -4427,61 +3943,32 @@
 		break;
 	}
 
-	if (!rdev_ops) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!rdev_ops)
+		return -EOPNOTSUPP;
 
-	err = rdev_ops(&rdev->wiphy, dev, &pmksa);
-
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
-	return err;
+	return rdev_ops(&rdev->wiphy, dev, &pmksa);
 }
 
 static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	int err;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 
-	rtnl_lock();
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
+		return -EOPNOTSUPP;
 
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto out_rtnl;
+	if (!rdev->ops->flush_pmksa)
+		return -EOPNOTSUPP;
 
-	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!rdev->ops->flush_pmksa) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	err = rdev->ops->flush_pmksa(&rdev->wiphy, dev);
-
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- out_rtnl:
-	rtnl_unlock();
-
-	return err;
-
+	return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
 }
 
 static int nl80211_remain_on_channel(struct sk_buff *skb,
 				     struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct ieee80211_channel *chan;
 	struct sk_buff *msg;
 	void *hdr;
@@ -4503,21 +3990,8 @@
 	if (!duration || !msecs_to_jiffies(duration) || duration > 5000)
 		return -EINVAL;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->remain_on_channel) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
+	if (!rdev->ops->remain_on_channel)
+		return -EOPNOTSUPP;
 
 	if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
 		channel_type = nla_get_u32(
@@ -4525,24 +3999,18 @@
 		if (channel_type != NL80211_CHAN_NO_HT &&
 		    channel_type != NL80211_CHAN_HT20 &&
 		    channel_type != NL80211_CHAN_HT40PLUS &&
-		    channel_type != NL80211_CHAN_HT40MINUS) {
-			err = -EINVAL;
-			goto out;
-		}
+		    channel_type != NL80211_CHAN_HT40MINUS)
+			return -EINVAL;
 	}
 
 	freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
 	chan = rdev_freq_to_chan(rdev, freq, channel_type);
-	if (chan == NULL) {
-		err = -EINVAL;
-		goto out;
-	}
+	if (chan == NULL)
+		return -EINVAL;
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!msg) {
-		err = -ENOMEM;
-		goto out;
-	}
+	if (!msg)
+		return -ENOMEM;
 
 	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
 			     NL80211_CMD_REMAIN_ON_CHANNEL);
@@ -4561,58 +4029,32 @@
 	NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
 
 	genlmsg_end(msg, hdr);
-	err = genlmsg_reply(msg, info);
-	goto out;
+
+	return genlmsg_reply(msg, info);
 
  nla_put_failure:
 	err = -ENOBUFS;
  free_msg:
 	nlmsg_free(msg);
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- unlock_rtnl:
-	rtnl_unlock();
 	return err;
 }
 
 static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
 					    struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	u64 cookie;
-	int err;
 
 	if (!info->attrs[NL80211_ATTR_COOKIE])
 		return -EINVAL;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->cancel_remain_on_channel) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
+	if (!rdev->ops->cancel_remain_on_channel)
+		return -EOPNOTSUPP;
 
 	cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
 
-	err = rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie);
-
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- unlock_rtnl:
-	rtnl_unlock();
-	return err;
+	return rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie);
 }
 
 static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
@@ -4648,26 +4090,18 @@
 				       struct genl_info *info)
 {
 	struct nlattr *tb[NL80211_TXRATE_MAX + 1];
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct cfg80211_bitrate_mask mask;
-	int err, rem, i;
-	struct net_device *dev;
+	int rem, i;
+	struct net_device *dev = info->user_ptr[1];
 	struct nlattr *tx_rates;
 	struct ieee80211_supported_band *sband;
 
 	if (info->attrs[NL80211_ATTR_TX_RATES] == NULL)
 		return -EINVAL;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->set_bitrate_mask) {
-		err = -EOPNOTSUPP;
-		goto unlock;
-	}
+	if (!rdev->ops->set_bitrate_mask)
+		return -EOPNOTSUPP;
 
 	memset(&mask, 0, sizeof(mask));
 	/* Default to all rates enabled */
@@ -4684,15 +4118,11 @@
 	nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
 	{
 		enum ieee80211_band band = nla_type(tx_rates);
-		if (band < 0 || band >= IEEE80211_NUM_BANDS) {
-			err = -EINVAL;
-			goto unlock;
-		}
+		if (band < 0 || band >= IEEE80211_NUM_BANDS)
+			return -EINVAL;
 		sband = rdev->wiphy.bands[band];
-		if (sband == NULL) {
-			err = -EINVAL;
-			goto unlock;
-		}
+		if (sband == NULL)
+			return -EINVAL;
 		nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
 			  nla_len(tx_rates), nl80211_txattr_policy);
 		if (tb[NL80211_TXRATE_LEGACY]) {
@@ -4700,68 +4130,48 @@
 				sband,
 				nla_data(tb[NL80211_TXRATE_LEGACY]),
 				nla_len(tb[NL80211_TXRATE_LEGACY]));
-			if (mask.control[band].legacy == 0) {
-				err = -EINVAL;
-				goto unlock;
-			}
+			if (mask.control[band].legacy == 0)
+				return -EINVAL;
 		}
 	}
 
-	err = rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask);
-
- unlock:
-	dev_put(dev);
-	cfg80211_unlock_rdev(rdev);
- unlock_rtnl:
-	rtnl_unlock();
-	return err;
+	return rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask);
 }
 
-static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info)
+static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
-	int err;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
 
 	if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
 		return -EINVAL;
 
-	if (nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]) < 1)
-		return -EINVAL;
-
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
+	if (info->attrs[NL80211_ATTR_FRAME_TYPE])
+		frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
 
 	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
-	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EOPNOTSUPP;
 
 	/* not much point in registering if we can't reply */
-	if (!rdev->ops->action) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!rdev->ops->mgmt_tx)
+		return -EOPNOTSUPP;
 
-	err = cfg80211_mlme_register_action(dev->ieee80211_ptr, info->snd_pid,
+	return cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid,
+			frame_type,
 			nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
 			nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
- unlock_rtnl:
-	rtnl_unlock();
-	return err;
 }
 
-static int nl80211_action(struct sk_buff *skb, struct genl_info *info)
+static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
-	struct net_device *dev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
 	struct ieee80211_channel *chan;
 	enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
 	bool channel_type_valid = false;
@@ -4775,27 +4185,16 @@
 	    !info->attrs[NL80211_ATTR_WIPHY_FREQ])
 		return -EINVAL;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
-	if (!rdev->ops->action) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!rdev->ops->mgmt_tx)
+		return -EOPNOTSUPP;
 
 	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
-	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		err = -ENETDOWN;
-		goto out;
-	}
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EOPNOTSUPP;
 
 	if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
 		channel_type = nla_get_u32(
@@ -4803,147 +4202,104 @@
 		if (channel_type != NL80211_CHAN_NO_HT &&
 		    channel_type != NL80211_CHAN_HT20 &&
 		    channel_type != NL80211_CHAN_HT40PLUS &&
-		    channel_type != NL80211_CHAN_HT40MINUS) {
-			err = -EINVAL;
-			goto out;
-		}
+		    channel_type != NL80211_CHAN_HT40MINUS)
+			return -EINVAL;
 		channel_type_valid = true;
 	}
 
 	freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
 	chan = rdev_freq_to_chan(rdev, freq, channel_type);
-	if (chan == NULL) {
-		err = -EINVAL;
-		goto out;
-	}
+	if (chan == NULL)
+		return -EINVAL;
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!msg) {
-		err = -ENOMEM;
-		goto out;
-	}
+	if (!msg)
+		return -ENOMEM;
 
 	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
-			     NL80211_CMD_ACTION);
+			     NL80211_CMD_FRAME);
 
 	if (IS_ERR(hdr)) {
 		err = PTR_ERR(hdr);
 		goto free_msg;
 	}
-	err = cfg80211_mlme_action(rdev, dev, chan, channel_type,
-				   channel_type_valid,
-				   nla_data(info->attrs[NL80211_ATTR_FRAME]),
-				   nla_len(info->attrs[NL80211_ATTR_FRAME]),
-				   &cookie);
+	err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, channel_type,
+				    channel_type_valid,
+				    nla_data(info->attrs[NL80211_ATTR_FRAME]),
+				    nla_len(info->attrs[NL80211_ATTR_FRAME]),
+				    &cookie);
 	if (err)
 		goto free_msg;
 
 	NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
 
 	genlmsg_end(msg, hdr);
-	err = genlmsg_reply(msg, info);
-	goto out;
+	return genlmsg_reply(msg, info);
 
  nla_put_failure:
 	err = -ENOBUFS;
  free_msg:
 	nlmsg_free(msg);
- out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-unlock_rtnl:
-	rtnl_unlock();
 	return err;
 }
 
 static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct wireless_dev *wdev;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	u8 ps_state;
 	bool state;
 	int err;
 
-	if (!info->attrs[NL80211_ATTR_PS_STATE]) {
-		err = -EINVAL;
-		goto out;
-	}
+	if (!info->attrs[NL80211_ATTR_PS_STATE])
+		return -EINVAL;
 
 	ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
 
-	if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rdev;
+	if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED)
+		return -EINVAL;
 
 	wdev = dev->ieee80211_ptr;
 
-	if (!rdev->ops->set_power_mgmt) {
-		err = -EOPNOTSUPP;
-		goto unlock_rdev;
-	}
+	if (!rdev->ops->set_power_mgmt)
+		return -EOPNOTSUPP;
 
 	state = (ps_state == NL80211_PS_ENABLED) ? true : false;
 
 	if (state == wdev->ps)
-		goto unlock_rdev;
+		return 0;
 
-	wdev->ps = state;
-
-	if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, wdev->ps,
-				      wdev->ps_timeout))
-		/* assume this means it's off */
-		wdev->ps = false;
-
-unlock_rdev:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-	rtnl_unlock();
-
-out:
+	err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, state,
+					wdev->ps_timeout);
+	if (!err)
+		wdev->ps = state;
 	return err;
 }
 
 static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	enum nl80211_ps_state ps_state;
 	struct wireless_dev *wdev;
-	struct net_device *dev;
+	struct net_device *dev = info->user_ptr[1];
 	struct sk_buff *msg;
 	void *hdr;
 	int err;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rtnl;
-
 	wdev = dev->ieee80211_ptr;
 
-	if (!rdev->ops->set_power_mgmt) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (!rdev->ops->set_power_mgmt)
+		return -EOPNOTSUPP;
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!msg) {
-		err = -ENOMEM;
-		goto out;
-	}
+	if (!msg)
+		return -ENOMEM;
 
 	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
 			     NL80211_CMD_GET_POWER_SAVE);
 	if (!hdr) {
-		err = -ENOMEM;
+		err = -ENOBUFS;
 		goto free_msg;
 	}
 
@@ -4955,22 +4311,12 @@
 	NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state);
 
 	genlmsg_end(msg, hdr);
-	err = genlmsg_reply(msg, info);
-	goto out;
+	return genlmsg_reply(msg, info);
 
-nla_put_failure:
+ nla_put_failure:
 	err = -ENOBUFS;
-
-free_msg:
+ free_msg:
 	nlmsg_free(msg);
-
-out:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-
-unlock_rtnl:
-	rtnl_unlock();
-
 	return err;
 }
 
@@ -4984,41 +4330,24 @@
 static int nl80211_set_cqm_rssi(struct genl_info *info,
 				s32 threshold, u32 hysteresis)
 {
-	struct cfg80211_registered_device *rdev;
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct wireless_dev *wdev;
-	struct net_device *dev;
-	int err;
+	struct net_device *dev = info->user_ptr[1];
 
 	if (threshold > 0)
 		return -EINVAL;
 
-	rtnl_lock();
-
-	err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
-	if (err)
-		goto unlock_rdev;
-
 	wdev = dev->ieee80211_ptr;
 
-	if (!rdev->ops->set_cqm_rssi_config) {
-		err = -EOPNOTSUPP;
-		goto unlock_rdev;
-	}
+	if (!rdev->ops->set_cqm_rssi_config)
+		return -EOPNOTSUPP;
 
-	if (wdev->iftype != NL80211_IFTYPE_STATION) {
-		err = -EOPNOTSUPP;
-		goto unlock_rdev;
-	}
+	if (wdev->iftype != NL80211_IFTYPE_STATION &&
+	    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
+		return -EOPNOTSUPP;
 
-	err = rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev,
-					     threshold, hysteresis);
-
-unlock_rdev:
-	cfg80211_unlock_rdev(rdev);
-	dev_put(dev);
-	rtnl_unlock();
-
-	return err;
+	return rdev->ops->set_cqm_rssi_config(wdev->wiphy, dev,
+					      threshold, hysteresis);
 }
 
 static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
@@ -5052,6 +4381,65 @@
 	return err;
 }
 
+#define NL80211_FLAG_NEED_WIPHY		0x01
+#define NL80211_FLAG_NEED_NETDEV	0x02
+#define NL80211_FLAG_NEED_RTNL		0x04
+#define NL80211_FLAG_CHECK_NETDEV_UP	0x08
+#define NL80211_FLAG_NEED_NETDEV_UP	(NL80211_FLAG_NEED_NETDEV |\
+					 NL80211_FLAG_CHECK_NETDEV_UP)
+
+static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
+			    struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev;
+	struct net_device *dev;
+	int err;
+	bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL;
+
+	if (rtnl)
+		rtnl_lock();
+
+	if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
+		rdev = cfg80211_get_dev_from_info(info);
+		if (IS_ERR(rdev)) {
+			if (rtnl)
+				rtnl_unlock();
+			return PTR_ERR(rdev);
+		}
+		info->user_ptr[0] = rdev;
+	} else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
+		err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
+		if (err) {
+			if (rtnl)
+				rtnl_unlock();
+			return err;
+		}
+		if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
+		    !netif_running(dev)) {
+			cfg80211_unlock_rdev(rdev);
+			dev_put(dev);
+			if (rtnl)
+				rtnl_unlock();
+			return -ENETDOWN;
+		}
+		info->user_ptr[0] = rdev;
+		info->user_ptr[1] = dev;
+	}
+
+	return 0;
+}
+
+static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
+			      struct genl_info *info)
+{
+	if (info->user_ptr[0])
+		cfg80211_unlock_rdev(info->user_ptr[0]);
+	if (info->user_ptr[1])
+		dev_put(info->user_ptr[1]);
+	if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
+		rtnl_unlock();
+}
+
 static struct genl_ops nl80211_ops[] = {
 	{
 		.cmd = NL80211_CMD_GET_WIPHY,
@@ -5059,12 +4447,14 @@
 		.dumpit = nl80211_dump_wiphy,
 		.policy = nl80211_policy,
 		/* can be retrieved by unprivileged users */
+		.internal_flags = NL80211_FLAG_NEED_WIPHY,
 	},
 	{
 		.cmd = NL80211_CMD_SET_WIPHY,
 		.doit = nl80211_set_wiphy,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_GET_INTERFACE,
@@ -5072,90 +4462,119 @@
 		.dumpit = nl80211_dump_interface,
 		.policy = nl80211_policy,
 		/* can be retrieved by unprivileged users */
+		.internal_flags = NL80211_FLAG_NEED_NETDEV,
 	},
 	{
 		.cmd = NL80211_CMD_SET_INTERFACE,
 		.doit = nl80211_set_interface,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_NEW_INTERFACE,
 		.doit = nl80211_new_interface,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_WIPHY |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_DEL_INTERFACE,
 		.doit = nl80211_del_interface,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_GET_KEY,
 		.doit = nl80211_get_key,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_SET_KEY,
 		.doit = nl80211_set_key,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_NEW_KEY,
 		.doit = nl80211_new_key,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_DEL_KEY,
 		.doit = nl80211_del_key,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_SET_BEACON,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
 		.doit = nl80211_addset_beacon,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_NEW_BEACON,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
 		.doit = nl80211_addset_beacon,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_DEL_BEACON,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
 		.doit = nl80211_del_beacon,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_GET_STATION,
 		.doit = nl80211_get_station,
 		.dumpit = nl80211_dump_station,
 		.policy = nl80211_policy,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_SET_STATION,
 		.doit = nl80211_set_station,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_NEW_STATION,
 		.doit = nl80211_new_station,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_DEL_STATION,
 		.doit = nl80211_del_station,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_GET_MPATH,
@@ -5163,30 +4582,40 @@
 		.dumpit = nl80211_dump_mpath,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_SET_MPATH,
 		.doit = nl80211_set_mpath,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_NEW_MPATH,
 		.doit = nl80211_new_mpath,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_DEL_MPATH,
 		.doit = nl80211_del_mpath,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_SET_BSS,
 		.doit = nl80211_set_bss,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_GET_REG,
@@ -5211,18 +4640,24 @@
 		.doit = nl80211_get_mesh_params,
 		.policy = nl80211_policy,
 		/* can be retrieved by unprivileged users */
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_SET_MESH_PARAMS,
 		.doit = nl80211_set_mesh_params,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_TRIGGER_SCAN,
 		.doit = nl80211_trigger_scan,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_GET_SCAN,
@@ -5234,36 +4669,48 @@
 		.doit = nl80211_authenticate,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_ASSOCIATE,
 		.doit = nl80211_associate,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_DEAUTHENTICATE,
 		.doit = nl80211_deauthenticate,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_DISASSOCIATE,
 		.doit = nl80211_disassociate,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_JOIN_IBSS,
 		.doit = nl80211_join_ibss,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_LEAVE_IBSS,
 		.doit = nl80211_leave_ibss,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 #ifdef CONFIG_NL80211_TESTMODE
 	{
@@ -5271,6 +4718,8 @@
 		.doit = nl80211_testmode_do,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_WIPHY |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 #endif
 	{
@@ -5278,18 +4727,24 @@
 		.doit = nl80211_connect,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_DISCONNECT,
 		.doit = nl80211_disconnect,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_SET_WIPHY_NETNS,
 		.doit = nl80211_wiphy_netns,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_WIPHY |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_GET_SURVEY,
@@ -5301,72 +4756,104 @@
 		.doit = nl80211_setdel_pmksa,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_DEL_PMKSA,
 		.doit = nl80211_setdel_pmksa,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_FLUSH_PMKSA,
 		.doit = nl80211_flush_pmksa,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
 		.doit = nl80211_remain_on_channel,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
 		.doit = nl80211_cancel_remain_on_channel,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
 		.doit = nl80211_set_tx_bitrate_mask,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
-		.cmd = NL80211_CMD_REGISTER_ACTION,
-		.doit = nl80211_register_action,
+		.cmd = NL80211_CMD_REGISTER_FRAME,
+		.doit = nl80211_register_mgmt,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
-		.cmd = NL80211_CMD_ACTION,
-		.doit = nl80211_action,
+		.cmd = NL80211_CMD_FRAME,
+		.doit = nl80211_tx_mgmt,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_SET_POWER_SAVE,
 		.doit = nl80211_set_power_save,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_GET_POWER_SAVE,
 		.doit = nl80211_get_power_save,
 		.policy = nl80211_policy,
 		/* can be retrieved by unprivileged users */
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_SET_CQM,
 		.doit = nl80211_set_cqm,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
 		.cmd = NL80211_CMD_SET_CHANNEL,
 		.doit = nl80211_set_channel,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
+	},
+	{
+		.cmd = NL80211_CMD_SET_WDS_PEER,
+		.doit = nl80211_set_wds_peer,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
 	},
 };
 
@@ -6040,9 +5527,9 @@
 				nl80211_mlme_mcgrp.id, gfp);
 }
 
-int nl80211_send_action(struct cfg80211_registered_device *rdev,
-			struct net_device *netdev, u32 nlpid,
-			int freq, const u8 *buf, size_t len, gfp_t gfp)
+int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
+		      struct net_device *netdev, u32 nlpid,
+		      int freq, const u8 *buf, size_t len, gfp_t gfp)
 {
 	struct sk_buff *msg;
 	void *hdr;
@@ -6052,7 +5539,7 @@
 	if (!msg)
 		return -ENOMEM;
 
-	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION);
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
 	if (!hdr) {
 		nlmsg_free(msg);
 		return -ENOMEM;
@@ -6080,10 +5567,10 @@
 	return -ENOBUFS;
 }
 
-void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev,
-				   struct net_device *netdev, u64 cookie,
-				   const u8 *buf, size_t len, bool ack,
-				   gfp_t gfp)
+void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
+				 struct net_device *netdev, u64 cookie,
+				 const u8 *buf, size_t len, bool ack,
+				 gfp_t gfp)
 {
 	struct sk_buff *msg;
 	void *hdr;
@@ -6092,7 +5579,7 @@
 	if (!msg)
 		return;
 
-	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION_TX_STATUS);
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME_TX_STATUS);
 	if (!hdr) {
 		nlmsg_free(msg);
 		return;
@@ -6179,7 +5666,7 @@
 
 	list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list)
 		list_for_each_entry_rcu(wdev, &rdev->netdev_list, list)
-			cfg80211_mlme_unregister_actions(wdev, notify->pid);
+			cfg80211_mlme_unregister_socket(wdev, notify->pid);
 
 	rcu_read_unlock();
 
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 2ad7fbc..30d2f93 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -74,13 +74,13 @@
 			    struct net_device *dev, const u8 *mac_addr,
 			    struct station_info *sinfo, gfp_t gfp);
 
-int nl80211_send_action(struct cfg80211_registered_device *rdev,
-			struct net_device *netdev, u32 nlpid, int freq,
-			const u8 *buf, size_t len, gfp_t gfp);
-void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev,
-				   struct net_device *netdev, u64 cookie,
-				   const u8 *buf, size_t len, bool ack,
-				   gfp_t gfp);
+int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
+		      struct net_device *netdev, u32 nlpid, int freq,
+		      const u8 *buf, size_t len, gfp_t gfp);
+void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
+				 struct net_device *netdev, u64 cookie,
+				 const u8 *buf, size_t len, bool ack,
+				 gfp_t gfp);
 
 void
 nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c
index 1332c44..dbe35e1 100644
--- a/net/wireless/radiotap.c
+++ b/net/wireless/radiotap.c
@@ -14,6 +14,7 @@
  * See COPYING for more details.
  */
 
+#include <linux/kernel.h>
 #include <net/cfg80211.h>
 #include <net/ieee80211_radiotap.h>
 #include <asm/unaligned.h>
@@ -45,7 +46,7 @@
 };
 
 static const struct ieee80211_radiotap_namespace radiotap_ns = {
-	.n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]),
+	.n_bits = ARRAY_SIZE(rtap_namespace_sizes),
 	.align_size = rtap_namespace_sizes,
 };
 
@@ -200,7 +201,7 @@
 {
 	while (1) {
 		int hit = 0;
-		int pad, align, size, subns, vnslen;
+		int pad, align, size, subns;
 		uint32_t oui;
 
 		/* if no more EXT bits, that's it */
@@ -260,6 +261,27 @@
 		if (pad)
 			iterator->_arg += align - pad;
 
+		if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) {
+			int vnslen;
+
+			if ((unsigned long)iterator->_arg + size -
+			    (unsigned long)iterator->_rtheader >
+			    (unsigned long)iterator->_max_length)
+				return -EINVAL;
+
+			oui = (*iterator->_arg << 16) |
+				(*(iterator->_arg + 1) << 8) |
+				*(iterator->_arg + 2);
+			subns = *(iterator->_arg + 3);
+
+			find_ns(iterator, oui, subns);
+
+			vnslen = get_unaligned_le16(iterator->_arg + 4);
+			iterator->_next_ns_data = iterator->_arg + size + vnslen;
+			if (!iterator->current_namespace)
+				size += vnslen;
+		}
+
 		/*
 		 * this is what we will return to user, but we need to
 		 * move on first so next call has something fresh to test
@@ -286,40 +308,25 @@
 		/* these special ones are valid in each bitmap word */
 		switch (iterator->_arg_index % 32) {
 		case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
-			iterator->_bitmap_shifter >>= 1;
-			iterator->_arg_index++;
-
 			iterator->_reset_on_ext = 1;
 
-			vnslen = get_unaligned_le16(iterator->this_arg + 4);
-			iterator->_next_ns_data = iterator->_arg + vnslen;
-			oui = (*iterator->this_arg << 16) |
-				(*(iterator->this_arg + 1) << 8) |
-				*(iterator->this_arg + 2);
-			subns = *(iterator->this_arg + 3);
-
-			find_ns(iterator, oui, subns);
-
 			iterator->is_radiotap_ns = 0;
-			/* allow parsers to show this information */
+			/*
+			 * If parser didn't register this vendor
+			 * namespace with us, allow it to show it
+			 * as 'raw. Do do that, set argument index
+			 * to vendor namespace.
+			 */
 			iterator->this_arg_index =
 				IEEE80211_RADIOTAP_VENDOR_NAMESPACE;
-			iterator->this_arg_size += vnslen;
-			if ((unsigned long)iterator->this_arg +
-			    iterator->this_arg_size -
-			    (unsigned long)iterator->_rtheader >
-			    (unsigned long)(unsigned long)iterator->_max_length)
-				return -EINVAL;
-			hit = 1;
-			break;
+			if (!iterator->current_namespace)
+				hit = 1;
+			goto next_entry;
 		case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
-			iterator->_bitmap_shifter >>= 1;
-			iterator->_arg_index++;
-
 			iterator->_reset_on_ext = 1;
 			iterator->current_namespace = &radiotap_ns;
 			iterator->is_radiotap_ns = 1;
-			break;
+			goto next_entry;
 		case IEEE80211_RADIOTAP_EXT:
 			/*
 			 * bit 31 was set, there is more
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index f180db0..d14bbf9 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/random.h>
+#include <linux/ctype.h>
 #include <linux/nl80211.h>
 #include <linux/platform_device.h>
 #include <net/cfg80211.h>
@@ -73,7 +74,11 @@
  *     - last_request
  */
 static DEFINE_MUTEX(reg_mutex);
-#define assert_reg_lock() WARN_ON(!mutex_is_locked(&reg_mutex))
+
+static inline void assert_reg_lock(void)
+{
+	lockdep_assert_held(&reg_mutex);
+}
 
 /* Used to queue up regulatory hints */
 static LIST_HEAD(reg_requests_list);
@@ -181,14 +186,6 @@
 	return false;
 }
 
-static bool is_alpha_upper(char letter)
-{
-	/* ASCII A - Z */
-	if (letter >= 65 && letter <= 90)
-		return true;
-	return false;
-}
-
 static bool is_unknown_alpha2(const char *alpha2)
 {
 	if (!alpha2)
@@ -220,7 +217,7 @@
 {
 	if (!alpha2)
 		return false;
-	if (is_alpha_upper(alpha2[0]) && is_alpha_upper(alpha2[1]))
+	if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
 		return true;
 	return false;
 }
@@ -1399,6 +1396,11 @@
 
 static void queue_regulatory_request(struct regulatory_request *request)
 {
+	if (isalpha(request->alpha2[0]))
+		request->alpha2[0] = toupper(request->alpha2[0]);
+	if (isalpha(request->alpha2[1]))
+		request->alpha2[1] = toupper(request->alpha2[1]);
+
 	spin_lock(&reg_requests_lock);
 	list_add_tail(&request->list, &reg_requests_list);
 	spin_unlock(&reg_requests_lock);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 5ca8c71..503ebb8 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -650,14 +650,14 @@
 	bss = container_of(pub, struct cfg80211_internal_bss, pub);
 
 	spin_lock_bh(&dev->bss_lock);
+	if (!list_empty(&bss->list)) {
+		list_del_init(&bss->list);
+		dev->bss_generation++;
+		rb_erase(&bss->rbn, &dev->bss_tree);
 
-	list_del(&bss->list);
-	dev->bss_generation++;
-	rb_erase(&bss->rbn, &dev->bss_tree);
-
+		kref_put(&bss->ref, bss_release);
+	}
 	spin_unlock_bh(&dev->bss_lock);
-
-	kref_put(&bss->ref, bss_release);
 }
 EXPORT_SYMBOL(cfg80211_unlink_bss);
 
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index a8c2d6b..e17b0be 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -411,7 +411,8 @@
 
 	ASSERT_WDEV_LOCK(wdev);
 
-	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
+		    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
 		return;
 
 	if (wdev->sme_state != CFG80211_SME_CONNECTING)
@@ -548,7 +549,8 @@
 
 	ASSERT_WDEV_LOCK(wdev);
 
-	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
+		    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
 		return;
 
 	if (wdev->sme_state != CFG80211_SME_CONNECTED)
@@ -644,7 +646,8 @@
 
 	ASSERT_WDEV_LOCK(wdev);
 
-	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
+	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
+		    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
 		return;
 
 	if (wdev->sme_state != CFG80211_SME_CONNECTED)
@@ -695,7 +698,7 @@
 	 */
 	if (rdev->ops->del_key)
 		for (i = 0; i < 6; i++)
-			rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
+			rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
 
 #ifdef CONFIG_CFG80211_WEXT
 	memset(&wrqu, 0, sizeof(wrqu));
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index 9f2cef3..4294fa2 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -35,6 +35,14 @@
 SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
 SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
 
+static ssize_t name_show(struct device *dev,
+			 struct device_attribute *attr,
+			 char *buf) {
+	struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
+	return sprintf(buf, "%s\n", dev_name(&wiphy->dev));
+}
+
+
 static ssize_t addresses_show(struct device *dev,
 			      struct device_attribute *attr,
 			      char *buf)
@@ -57,6 +65,7 @@
 	__ATTR_RO(macaddress),
 	__ATTR_RO(address_mask),
 	__ATTR_RO(addresses),
+	__ATTR_RO(name),
 	{}
 };
 
@@ -110,6 +119,13 @@
 	return ret;
 }
 
+static const void *wiphy_namespace(struct device *d)
+{
+	struct wiphy *wiphy = container_of(d, struct wiphy, dev);
+
+	return wiphy_net(wiphy);
+}
+
 struct class ieee80211_class = {
 	.name = "ieee80211",
 	.owner = THIS_MODULE,
@@ -120,6 +136,8 @@
 #endif
 	.suspend = wiphy_suspend,
 	.resume = wiphy_resume,
+	.ns_type = &net_ns_type_operations,
+	.namespace = wiphy_namespace,
 };
 
 int wiphy_sysfs_init(void)
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 0c8a1e8..76120ae 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -144,19 +144,25 @@
 
 int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
 				   struct key_params *params, int key_idx,
-				   const u8 *mac_addr)
+				   bool pairwise, const u8 *mac_addr)
 {
 	int i;
 
 	if (key_idx > 5)
 		return -EINVAL;
 
+	if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
+		return -EINVAL;
+
+	if (pairwise && !mac_addr)
+		return -EINVAL;
+
 	/*
 	 * 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)
 	 */
-	if (mac_addr && key_idx &&
+	if (pairwise && key_idx &&
 	    params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
 	    params->cipher != WLAN_CIPHER_SUITE_WEP104)
 		return -EINVAL;
@@ -183,7 +189,14 @@
 			return -EINVAL;
 		break;
 	default:
-		return -EINVAL;
+		/*
+		 * We don't know anything about this algorithm,
+		 * allow using it -- but the driver must check
+		 * all parameters! We still check below whether
+		 * or not the driver supports this algorithm,
+		 * of course.
+		 */
+		break;
 	}
 
 	if (params->seq) {
@@ -221,7 +234,7 @@
 	{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
 EXPORT_SYMBOL(bridge_tunnel_header);
 
-unsigned int ieee80211_hdrlen(__le16 fc)
+unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc)
 {
 	unsigned int hdrlen = 24;
 
@@ -319,7 +332,8 @@
 		cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
 	case cpu_to_le16(IEEE80211_FCTL_TODS):
 		if (unlikely(iftype != NL80211_IFTYPE_AP &&
-			     iftype != NL80211_IFTYPE_AP_VLAN))
+			     iftype != NL80211_IFTYPE_AP_VLAN &&
+			     iftype != NL80211_IFTYPE_P2P_GO))
 			return -1;
 		break;
 	case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
@@ -347,7 +361,8 @@
 		break;
 	case cpu_to_le16(IEEE80211_FCTL_FROMDS):
 		if ((iftype != NL80211_IFTYPE_STATION &&
-		    iftype != NL80211_IFTYPE_MESH_POINT) ||
+		     iftype != NL80211_IFTYPE_P2P_CLIENT &&
+		     iftype != NL80211_IFTYPE_MESH_POINT) ||
 		    (is_multicast_ether_addr(dst) &&
 		     !compare_ether_addr(src, addr)))
 			return -1;
@@ -424,6 +439,7 @@
 	switch (iftype) {
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_P2P_GO:
 		fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
 		/* DA BSSID SA */
 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
@@ -432,6 +448,7 @@
 		hdrlen = 24;
 		break;
 	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_P2P_CLIENT:
 		fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
 		/* BSSID SA DA */
 		memcpy(hdr.addr1, bssid, ETH_ALEN);
@@ -666,7 +683,7 @@
 	for (i = 0; i < 6; i++) {
 		if (!wdev->connect_keys->params[i].cipher)
 			continue;
-		if (rdev->ops->add_key(wdev->wiphy, dev, i, NULL,
+		if (rdev->ops->add_key(wdev->wiphy, dev, i, false, NULL,
 					&wdev->connect_keys->params[i])) {
 			printk(KERN_ERR "%s: failed to set key %d\n",
 				dev->name, i);
@@ -771,7 +788,9 @@
 
 	/* if it's part of a bridge, reject changing type to station/ibss */
 	if ((dev->priv_flags & IFF_BRIDGE_PORT) &&
-	    (ntype == NL80211_IFTYPE_ADHOC || ntype == NL80211_IFTYPE_STATION))
+	    (ntype == NL80211_IFTYPE_ADHOC ||
+	     ntype == NL80211_IFTYPE_STATION ||
+	     ntype == NL80211_IFTYPE_P2P_CLIENT))
 		return -EBUSY;
 
 	if (ntype != otype) {
@@ -782,6 +801,7 @@
 			cfg80211_leave_ibss(rdev, dev, false);
 			break;
 		case NL80211_IFTYPE_STATION:
+		case NL80211_IFTYPE_P2P_CLIENT:
 			cfg80211_disconnect(rdev, dev,
 					    WLAN_REASON_DEAUTH_LEAVING, true);
 			break;
@@ -810,9 +830,11 @@
 			if (dev->ieee80211_ptr->use_4addr)
 				break;
 			/* fall through */
+		case NL80211_IFTYPE_P2P_CLIENT:
 		case NL80211_IFTYPE_ADHOC:
 			dev->priv_flags |= IFF_DONT_BRIDGE;
 			break;
+		case NL80211_IFTYPE_P2P_GO:
 		case NL80211_IFTYPE_AP:
 		case NL80211_IFTYPE_AP_VLAN:
 		case NL80211_IFTYPE_WDS:
@@ -823,7 +845,7 @@
 			/* monitor can't bridge anyway */
 			break;
 		case NL80211_IFTYPE_UNSPECIFIED:
-		case __NL80211_IFTYPE_AFTER_LAST:
+		case NUM_NL80211_IFTYPES:
 			/* not happening */
 			break;
 		}
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 7e5c3a4..12222ee 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -432,14 +432,17 @@
 EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
 
 static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
-				     struct net_device *dev, const u8 *addr,
-				     bool remove, bool tx_key, int idx,
-				     struct key_params *params)
+				     struct net_device *dev, bool pairwise,
+				     const u8 *addr, bool remove, bool tx_key,
+				     int idx, struct key_params *params)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	int err, i;
 	bool rejoin = false;
 
+	if (pairwise && !addr)
+		return -EINVAL;
+
 	if (!wdev->wext.keys) {
 		wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
 					      GFP_KERNEL);
@@ -478,7 +481,13 @@
 				__cfg80211_leave_ibss(rdev, wdev->netdev, true);
 				rejoin = true;
 			}
-			err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
+
+			if (!pairwise && addr &&
+			    !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
+				err = -ENOENT;
+			else
+				err = rdev->ops->del_key(&rdev->wiphy, dev, idx,
+							 pairwise, addr);
 		}
 		wdev->wext.connect.privacy = false;
 		/*
@@ -507,12 +516,13 @@
 	if (addr)
 		tx_key = false;
 
-	if (cfg80211_validate_key_settings(rdev, params, idx, addr))
+	if (cfg80211_validate_key_settings(rdev, params, idx, pairwise, addr))
 		return -EINVAL;
 
 	err = 0;
 	if (wdev->current_bss)
-		err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
+		err = rdev->ops->add_key(&rdev->wiphy, dev, idx,
+					 pairwise, addr, params);
 	if (err)
 		return err;
 
@@ -563,17 +573,17 @@
 }
 
 static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
-				   struct net_device *dev, const u8 *addr,
-				   bool remove, bool tx_key, int idx,
-				   struct key_params *params)
+				   struct net_device *dev, bool pairwise,
+				   const u8 *addr, bool remove, bool tx_key,
+				   int idx, struct key_params *params)
 {
 	int err;
 
 	/* devlist mutex needed for possible IBSS re-join */
 	mutex_lock(&rdev->devlist_mtx);
 	wdev_lock(dev->ieee80211_ptr);
-	err = __cfg80211_set_encryption(rdev, dev, addr, remove,
-					tx_key, idx, params);
+	err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
+					remove, tx_key, idx, params);
 	wdev_unlock(dev->ieee80211_ptr);
 	mutex_unlock(&rdev->devlist_mtx);
 
@@ -635,7 +645,7 @@
 	else if (!remove)
 		return -EINVAL;
 
-	return cfg80211_set_encryption(rdev, dev, NULL, remove,
+	return cfg80211_set_encryption(rdev, dev, false, NULL, remove,
 				       wdev->wext.default_key == -1,
 				       idx, &params);
 }
@@ -725,7 +735,9 @@
 	}
 
 	return cfg80211_set_encryption(
-			rdev, dev, addr, remove,
+			rdev, dev,
+			!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
+			addr, remove,
 			ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
 			idx, &params);
 }
@@ -1354,6 +1366,10 @@
 	}
 
 	wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
+	if (sinfo.filled & STATION_INFO_RX_DROP_MISC)
+		wstats.discard.misc = sinfo.rx_dropped_misc;
+	if (sinfo.filled & STATION_INFO_TX_FAILED)
+		wstats.discard.retries = sinfo.tx_failed;
 
 	return &wstats;
 }
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index 8f5116f..dc675a3 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -611,7 +611,7 @@
 #endif
 
 #ifdef CONFIG_CFG80211_WEXT
-	if (dev->ieee80211_ptr && dev->ieee80211_ptr &&
+	if (dev->ieee80211_ptr &&
 	    dev->ieee80211_ptr->wiphy &&
 	    dev->ieee80211_ptr->wiphy->wext &&
 	    dev->ieee80211_ptr->wiphy->wext->get_wireless_stats)
diff --git a/net/wireless/wext-priv.c b/net/wireless/wext-priv.c
index 3feb28e..674d426 100644
--- a/net/wireless/wext-priv.c
+++ b/net/wireless/wext-priv.c
@@ -152,7 +152,7 @@
 	} else if (!iwp->pointer)
 		return -EFAULT;
 
-	extra = kmalloc(extra_size, GFP_KERNEL);
+	extra = kzalloc(extra_size, GFP_KERNEL);
 	if (!extra)
 		return -ENOMEM;
 
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 9818198..6fffe62 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -197,6 +197,8 @@
 	wdev->wext.connect.ssid_len = len;
 
 	wdev->wext.connect.crypto.control_port = false;
+	wdev->wext.connect.crypto.control_port_ethertype =
+					cpu_to_be16(ETH_P_PAE);
 
 	err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
diff --git a/net/x25/Kconfig b/net/x25/Kconfig
index e6759c9..2196e55 100644
--- a/net/x25/Kconfig
+++ b/net/x25/Kconfig
@@ -5,6 +5,7 @@
 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 5e86d4e..f7af98d 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -507,14 +507,14 @@
 	struct sock *sk = sock->sk;
 	int rc = -EOPNOTSUPP;
 
-	lock_kernel();
+	lock_sock(sk);
 	if (sk->sk_state != TCP_LISTEN) {
 		memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN);
 		sk->sk_max_ack_backlog = backlog;
 		sk->sk_state           = TCP_LISTEN;
 		rc = 0;
 	}
-	unlock_kernel();
+	release_sock(sk);
 
 	return rc;
 }
@@ -688,7 +688,6 @@
 	struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
 	int len, i, rc = 0;
 
-	lock_kernel();
 	if (!sock_flag(sk, SOCK_ZAPPED) ||
 	    addr_len != sizeof(struct sockaddr_x25) ||
 	    addr->sx25_family != AF_X25) {
@@ -704,12 +703,13 @@
 		}
 	}
 
+	lock_sock(sk);
 	x25_sk(sk)->source_addr = addr->sx25_addr;
 	x25_insert_socket(sk);
 	sock_reset_flag(sk, SOCK_ZAPPED);
+	release_sock(sk);
 	SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
 out:
-	unlock_kernel();
 	return rc;
 }
 
@@ -751,7 +751,6 @@
 	struct x25_route *rt;
 	int rc = 0;
 
-	lock_kernel();
 	lock_sock(sk);
 	if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
 		sock->state = SS_CONNECTED;
@@ -829,7 +828,6 @@
 	x25_route_put(rt);
 out:
 	release_sock(sk);
-	unlock_kernel();
 	return rc;
 }
 
@@ -869,8 +867,7 @@
 	struct sk_buff *skb;
 	int rc = -EINVAL;
 
-	lock_kernel();
-	if (!sk || sk->sk_state != TCP_LISTEN)
+	if (!sk)
 		goto out;
 
 	rc = -EOPNOTSUPP;
@@ -878,6 +875,10 @@
 		goto out;
 
 	lock_sock(sk);
+	rc = -EINVAL;
+	if (sk->sk_state != TCP_LISTEN)
+		goto out2;
+
 	rc = x25_wait_for_data(sk, sk->sk_rcvtimeo);
 	if (rc)
 		goto out2;
@@ -897,7 +898,6 @@
 out2:
 	release_sock(sk);
 out:
-	unlock_kernel();
 	return rc;
 }
 
@@ -909,7 +909,6 @@
 	struct x25_sock *x25 = x25_sk(sk);
 	int rc = 0;
 
-	lock_kernel();
 	if (peer) {
 		if (sk->sk_state != TCP_ESTABLISHED) {
 			rc = -ENOTCONN;
@@ -923,19 +922,6 @@
 	*uaddr_len = sizeof(*sx25);
 
 out:
-	unlock_kernel();
-	return rc;
-}
-
-static unsigned int x25_datagram_poll(struct file *file, struct socket *sock,
-			   poll_table *wait)
-{
-	int rc;
-
-	lock_kernel();
-	rc = datagram_poll(file, sock, wait);
-	unlock_kernel();
-
 	return rc;
 }
 
@@ -1746,7 +1732,7 @@
 	.socketpair =	sock_no_socketpair,
 	.accept =	x25_accept,
 	.getname =	x25_getname,
-	.poll =		x25_datagram_poll,
+	.poll =		datagram_poll,
 	.ioctl =	x25_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = compat_x25_ioctl,
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 2b3ed7a..044e778 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -50,6 +50,9 @@
 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 struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
 						int dir);
@@ -1175,9 +1178,8 @@
 		    tmpl->mode == XFRM_MODE_BEET) {
 			remote = &tmpl->id.daddr;
 			local = &tmpl->saddr;
-			family = tmpl->encap_family;
-			if (xfrm_addr_any(local, family)) {
-				error = xfrm_get_saddr(net, &tmp, remote, family);
+			if (xfrm_addr_any(local, tmpl->encap_family)) {
+				error = xfrm_get_saddr(net, &tmp, remote, tmpl->encap_family);
 				if (error)
 					goto fail;
 				local = &tmp;
@@ -2277,7 +2279,7 @@
  * still valid.
  */
 
-int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
+static int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
 		struct flowi *fl, int family, int strict)
 {
 	struct dst_entry *dst = &first->u.dst;
@@ -2359,8 +2361,6 @@
 	return 1;
 }
 
-EXPORT_SYMBOL(xfrm_bundle_ok);
-
 int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
 	struct net *net;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 5208b12f..eb96ce5 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -656,15 +656,23 @@
 EXPORT_SYMBOL(xfrm_sad_getinfo);
 
 static int
-xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
-		  struct xfrm_tmpl *tmpl,
-		  xfrm_address_t *daddr, xfrm_address_t *saddr,
-		  unsigned short family)
+xfrm_init_tempstate(struct xfrm_state *x, struct flowi *fl,
+		    struct xfrm_tmpl *tmpl,
+		    xfrm_address_t *daddr, xfrm_address_t *saddr,
+		    unsigned short family)
 {
 	struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
 	if (!afinfo)
 		return -1;
-	afinfo->init_tempsel(x, fl, tmpl, daddr, saddr);
+	afinfo->init_tempsel(&x->sel, fl);
+
+	if (family != tmpl->encap_family) {
+		xfrm_state_put_afinfo(afinfo);
+		afinfo = xfrm_state_get_afinfo(tmpl->encap_family);
+		if (!afinfo)
+			return -1;
+	}
+	afinfo->init_temprop(x, tmpl, daddr, saddr);
 	xfrm_state_put_afinfo(afinfo);
 	return 0;
 }
@@ -790,37 +798,38 @@
 	int error = 0;
 	struct xfrm_state *best = NULL;
 	u32 mark = pol->mark.v & pol->mark.m;
+	unsigned short encap_family = tmpl->encap_family;
 
 	to_put = NULL;
 
 	spin_lock_bh(&xfrm_state_lock);
-	h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, family);
+	h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family);
 	hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
-		if (x->props.family == family &&
+		if (x->props.family == encap_family &&
 		    x->props.reqid == tmpl->reqid &&
 		    (mark & x->mark.m) == x->mark.v &&
 		    !(x->props.flags & XFRM_STATE_WILDRECV) &&
-		    xfrm_state_addr_check(x, daddr, saddr, family) &&
+		    xfrm_state_addr_check(x, daddr, saddr, encap_family) &&
 		    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, family, daddr, saddr,
+			xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr,
 					   &best, &acquire_in_progress, &error);
 	}
 	if (best)
 		goto found;
 
-	h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family);
+	h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, encap_family);
 	hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) {
-		if (x->props.family == family &&
+		if (x->props.family == encap_family &&
 		    x->props.reqid == tmpl->reqid &&
 		    (mark & x->mark.m) == x->mark.v &&
 		    !(x->props.flags & XFRM_STATE_WILDRECV) &&
-		    xfrm_state_addr_check(x, daddr, saddr, family) &&
+		    xfrm_state_addr_check(x, daddr, saddr, encap_family) &&
 		    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, family, daddr, saddr,
+			xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr,
 					   &best, &acquire_in_progress, &error);
 	}
 
@@ -829,7 +838,7 @@
 	if (!x && !error && !acquire_in_progress) {
 		if (tmpl->id.spi &&
 		    (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi,
-					      tmpl->id.proto, family)) != NULL) {
+					      tmpl->id.proto, encap_family)) != NULL) {
 			to_put = x0;
 			error = -EEXIST;
 			goto out;
@@ -839,9 +848,9 @@
 			error = -ENOMEM;
 			goto out;
 		}
-		/* Initialize temporary selector matching only
+		/* Initialize temporary state matching only
 		 * to current session. */
-		xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
+		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);
@@ -856,10 +865,10 @@
 			x->km.state = XFRM_STATE_ACQ;
 			list_add(&x->km.all, &net->xfrm.state_all);
 			hlist_add_head(&x->bydst, net->xfrm.state_bydst+h);
-			h = xfrm_src_hash(net, daddr, saddr, family);
+			h = xfrm_src_hash(net, daddr, saddr, encap_family);
 			hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h);
 			if (x->id.spi) {
-				h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, family);
+				h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, encap_family);
 				hlist_add_head(&x->byspi, net->xfrm.state_byspi+h);
 			}
 			x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
diff --git a/samples/kfifo/bytestream-example.c b/samples/kfifo/bytestream-example.c
index 178061e..cfe40ad 100644
--- a/samples/kfifo/bytestream-example.c
+++ b/samples/kfifo/bytestream-example.c
@@ -148,6 +148,7 @@
 	.owner		= THIS_MODULE,
 	.read		= fifo_read,
 	.write		= fifo_write,
+	.llseek		= noop_llseek,
 };
 
 static int __init example_init(void)
diff --git a/samples/kfifo/dma-example.c b/samples/kfifo/dma-example.c
index ee03a4f..0647379 100644
--- a/samples/kfifo/dma-example.c
+++ b/samples/kfifo/dma-example.c
@@ -24,6 +24,7 @@
 {
 	int			i;
 	unsigned int		ret;
+	unsigned int		nents;
 	struct scatterlist	sg[10];
 
 	printk(KERN_INFO "DMA fifo test start\n");
@@ -61,9 +62,9 @@
 	 * byte at the beginning, after the kfifo_skip().
 	 */
 	sg_init_table(sg, ARRAY_SIZE(sg));
-	ret = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
-	printk(KERN_INFO "DMA sgl entries: %d\n", ret);
-	if (!ret) {
+	nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE);
+	printk(KERN_INFO "DMA sgl entries: %d\n", nents);
+	if (!nents) {
 		/* fifo is full and no sgl was created */
 		printk(KERN_WARNING "error kfifo_dma_in_prepare\n");
 		return -EIO;
@@ -71,7 +72,7 @@
 
 	/* receive data */
 	printk(KERN_INFO "scatterlist for receive:\n");
-	for (i = 0; i < ARRAY_SIZE(sg); i++) {
+	for (i = 0; i < nents; i++) {
 		printk(KERN_INFO
 		"sg[%d] -> "
 		"page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",
@@ -91,16 +92,16 @@
 	kfifo_dma_in_finish(&fifo, ret);
 
 	/* Prepare to transmit data, example: 8 bytes */
-	ret = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
-	printk(KERN_INFO "DMA sgl entries: %d\n", ret);
-	if (!ret) {
+	nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8);
+	printk(KERN_INFO "DMA sgl entries: %d\n", nents);
+	if (!nents) {
 		/* no data was available and no sgl was created */
 		printk(KERN_WARNING "error kfifo_dma_out_prepare\n");
 		return -EIO;
 	}
 
 	printk(KERN_INFO "scatterlist for transmit:\n");
-	for (i = 0; i < ARRAY_SIZE(sg); i++) {
+	for (i = 0; i < nents; i++) {
 		printk(KERN_INFO
 		"sg[%d] -> "
 		"page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n",
diff --git a/samples/kfifo/inttype-example.c b/samples/kfifo/inttype-example.c
index 71b2aab..6f8e79e 100644
--- a/samples/kfifo/inttype-example.c
+++ b/samples/kfifo/inttype-example.c
@@ -141,6 +141,7 @@
 	.owner		= THIS_MODULE,
 	.read		= fifo_read,
 	.write		= fifo_write,
+	.llseek		= noop_llseek,
 };
 
 static int __init example_init(void)
diff --git a/samples/kfifo/record-example.c b/samples/kfifo/record-example.c
index e68bd16..2d7529e 100644
--- a/samples/kfifo/record-example.c
+++ b/samples/kfifo/record-example.c
@@ -155,6 +155,7 @@
 	.owner		= THIS_MODULE,
 	.read		= fifo_read,
 	.write		= fifo_write,
+	.llseek		= noop_llseek,
 };
 
 static int __init example_init(void)
diff --git a/samples/tracepoints/tracepoint-sample.c b/samples/tracepoints/tracepoint-sample.c
index 26fab33..f4d89e0 100644
--- a/samples/tracepoints/tracepoint-sample.c
+++ b/samples/tracepoints/tracepoint-sample.c
@@ -30,6 +30,7 @@
 
 static const struct file_operations mark_ops = {
 	.open = my_open,
+	.llseek = noop_llseek,
 };
 
 static int __init sample_init(void)
diff --git a/scripts/Makefile b/scripts/Makefile
index 842dbc2..2e08810 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -11,6 +11,7 @@
 hostprogs-$(CONFIG_LOGO)         += pnmtologo
 hostprogs-$(CONFIG_VT)           += conmakehash
 hostprogs-$(CONFIG_IKCONFIG)     += bin2c
+hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
 
 always		:= $(hostprogs-y) $(hostprogs-m)
 
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index a1a5cf9..5ad25e1 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -209,12 +209,23 @@
 endif
 
 ifdef CONFIG_FTRACE_MCOUNT_RECORD
+ifdef BUILD_C_RECORDMCOUNT
+# Due to recursion, we must skip empty.o.
+# The empty.o file is created in the make process in order to determine
+#  the target endianness and word size. It is made before all other C
+#  files, including recordmcount.
+cmd_record_mcount = if [ $(@) != "scripts/mod/empty.o" ]; then			\
+			$(objtree)/scripts/recordmcount "$(@)";			\
+		    fi;
+else
 cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
 	"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
 	"$(if $(CONFIG_64BIT),64,32)" \
-	"$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
+	"$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
+	"$(LD)" "$(NM)" "$(RM)" "$(MV)" \
 	"$(if $(part-of-module),1,0)" "$(@)";
 endif
+endif
 
 define rule_cc_o_c
 	$(call echo-cmd,checksrc) $(cmd_checksrc)			  \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 54fd1b7..7bfcf1a 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -101,14 +101,6 @@
 modname_flags  = $(if $(filter 1,$(words $(modname))),\
                  -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
 
-#hash values
-ifdef CONFIG_DYNAMIC_DEBUG
-debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\
-              -D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"
-else
-debug_flags =
-endif
-
 orig_c_flags   = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
                  $(ccflags-y) $(CFLAGS_$(basetarget).o)
 _c_flags       = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
@@ -152,8 +144,7 @@
 
 c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
 		 $(__c_flags) $(modkern_cflags)                           \
-		 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \
-		  $(debug_flags)
+		 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
 
 a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
 		 $(__a_flags) $(modkern_aflags)
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
index 0955995..4c324a1 100644
--- a/scripts/basic/Makefile
+++ b/scripts/basic/Makefile
@@ -9,7 +9,7 @@
 # fixdep: 	 Used to generate dependency information during build process
 # docproc:	 Used in Documentation/DocBook
 
-hostprogs-y	:= fixdep docproc hash
+hostprogs-y	:= fixdep docproc
 always		:= $(hostprogs-y)
 
 # fixdep is needed to compile other host programs
diff --git a/scripts/basic/hash.c b/scripts/basic/hash.c
deleted file mode 100644
index 2ef5d3f..0000000
--- a/scripts/basic/hash.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define DYNAMIC_DEBUG_HASH_BITS 6
-
-static const char *program;
-
-static void usage(void)
-{
-	printf("Usage: %s <djb2|r5> <modname>\n", program);
-	exit(1);
-}
-
-/* djb2 hashing algorithm by Dan Bernstein. From:
- * http://www.cse.yorku.ca/~oz/hash.html
- */
-
-static unsigned int djb2_hash(char *str)
-{
-	unsigned long hash = 5381;
-	int c;
-
-	c = *str;
-	while (c) {
-		hash = ((hash << 5) + hash) + c;
-		c = *++str;
-	}
-	return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
-}
-
-static unsigned int r5_hash(char *str)
-{
-	unsigned long hash = 0;
-	int c;
-
-	c = *str;
-	while (c) {
-		hash = (hash + (c << 4) + (c >> 4)) * 11;
-		c = *++str;
-	}
-	return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
-}
-
-int main(int argc, char *argv[])
-{
-	program = argv[0];
-
-	if (argc != 3)
-		usage();
-	if (!strcmp(argv[1], "djb2"))
-		printf("%d\n", djb2_hash(argv[2]));
-	else if (!strcmp(argv[1], "r5"))
-		printf("%d\n", r5_hash(argv[2]));
-	else
-		usage();
-	exit(0);
-}
-
diff --git a/scripts/gcc-goto.sh b/scripts/gcc-goto.sh
new file mode 100644
index 0000000..520d16b
--- /dev/null
+++ b/scripts/gcc-goto.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# Test for gcc 'asm goto' suport
+# Copyright (C) 2010, Jason Baron <jbaron@redhat.com>
+
+echo "int main(void) { entry: asm goto (\"\"::::entry); return 0; }" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 5b7c86e..7ef429c 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -427,7 +427,7 @@
 				if (sym->name && !sym_is_choice_value(sym)) {
 					printf("CONFIG_%s\n", sym->name);
 				}
-			} else {
+			} else if (input_mode != oldnoconfig) {
 				if (!conf_cnt++)
 					printf(_("*\n* Restart config...\n*\n"));
 				rootEntry = menu_get_parent_menu(menu);
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 6ee2e4f..170459c 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -165,7 +165,6 @@
 	struct symbol *sym;
 	struct property *prompt;
 	struct expr *dep;
-	struct expr *dir_dep;
 	unsigned int flags;
 	char *help;
 	struct file *file;
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 4fb5902..edda8b4 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -107,7 +107,6 @@
 void menu_add_dep(struct expr *dep)
 {
 	current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
-	current_entry->dir_dep = current_entry->dep;
 }
 
 void menu_set_type(int type)
@@ -291,10 +290,6 @@
 		for (menu = parent->list; menu; menu = menu->next)
 			menu_finalize(menu);
 	} else if (sym) {
-		/* ignore inherited dependencies for dir_dep */
-		sym->dir_dep.expr = expr_transform(expr_copy(parent->dir_dep));
-		sym->dir_dep.expr = expr_eliminate_dups(sym->dir_dep.expr);
-
 		basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
 		basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
 		basedep = expr_eliminate_dups(expr_transform(basedep));
@@ -325,6 +320,8 @@
 			parent->next = last_menu->next;
 			last_menu->next = NULL;
 		}
+
+		sym->dir_dep.expr = parent->dep;
 	}
 	for (menu = parent->list; menu; menu = menu->next) {
 		if (sym && sym_is_choice(sym) &&
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 943712c..1f8b305 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -350,6 +350,7 @@
 				}
 			}
 		calc_newval:
+#if 0
 			if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
 				fprintf(stderr, "warning: (");
 				expr_fprint(sym->rev_dep.expr, stderr);
@@ -358,6 +359,7 @@
 				expr_fprint(sym->dir_dep.expr, stderr);
 				fprintf(stderr, ")\n");
 			}
+#endif
 			newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
 		}
 		if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
new file mode 100644
index 0000000..26e1271
--- /dev/null
+++ b/scripts/recordmcount.c
@@ -0,0 +1,363 @@
+/*
+ * recordmcount.c: construct a table of the locations of calls to 'mcount'
+ * so that ftrace can find them quickly.
+ * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>.  All rights reserved.
+ * Licensed under the GNU General Public License, version 2 (GPLv2).
+ *
+ * Restructured to fit Linux format, as well as other updates:
+ *  Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+ */
+
+/*
+ * Strategy: alter the .o file in-place.
+ *
+ * Append a new STRTAB that has the new section names, followed by a new array
+ * ElfXX_Shdr[] that has the new section headers, followed by the section
+ * contents for __mcount_loc and its relocations.  The old shstrtab strings,
+ * and the old ElfXX_Shdr[] array, remain as "garbage" (commonly, a couple
+ * kilobytes.)  Subsequent processing by /bin/ld (or the kernel module loader)
+ * will ignore the garbage regions, because they are not designated by the
+ * new .e_shoff nor the new ElfXX_Shdr[].  [In order to remove the garbage,
+ * then use "ld -r" to create a new file that omits the garbage.]
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <elf.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int fd_map;	/* File descriptor for file being modified. */
+static int mmap_failed; /* Boolean flag. */
+static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
+static char gpfx;	/* prefix for global symbol name (sometimes '_') */
+static struct stat sb;	/* Remember .st_size, etc. */
+static jmp_buf jmpenv;	/* setjmp/longjmp per-file error escape */
+
+/* setjmp() return values */
+enum {
+	SJ_SETJMP = 0,  /* hardwired first return */
+	SJ_FAIL,
+	SJ_SUCCEED
+};
+
+/* Per-file resource cleanup when multiple files. */
+static void
+cleanup(void)
+{
+	if (!mmap_failed)
+		munmap(ehdr_curr, sb.st_size);
+	else
+		free(ehdr_curr);
+	close(fd_map);
+}
+
+static void __attribute__((noreturn))
+fail_file(void)
+{
+	cleanup();
+	longjmp(jmpenv, SJ_FAIL);
+}
+
+static void __attribute__((noreturn))
+succeed_file(void)
+{
+	cleanup();
+	longjmp(jmpenv, SJ_SUCCEED);
+}
+
+/* ulseek, uread, ...:  Check return value for errors. */
+
+static off_t
+ulseek(int const fd, off_t const offset, int const whence)
+{
+	off_t const w = lseek(fd, offset, whence);
+	if ((off_t)-1 == w) {
+		perror("lseek");
+		fail_file();
+	}
+	return w;
+}
+
+static size_t
+uread(int const fd, void *const buf, size_t const count)
+{
+	size_t const n = read(fd, buf, count);
+	if (n != count) {
+		perror("read");
+		fail_file();
+	}
+	return n;
+}
+
+static size_t
+uwrite(int const fd, void const *const buf, size_t const count)
+{
+	size_t const n = write(fd, buf, count);
+	if (n != count) {
+		perror("write");
+		fail_file();
+	}
+	return n;
+}
+
+static void *
+umalloc(size_t size)
+{
+	void *const addr = malloc(size);
+	if (0 == addr) {
+		fprintf(stderr, "malloc failed: %zu bytes\n", size);
+		fail_file();
+	}
+	return addr;
+}
+
+/*
+ * Get the whole file as a programming convenience in order to avoid
+ * malloc+lseek+read+free of many pieces.  If successful, then mmap
+ * avoids copying unused pieces; else just read the whole file.
+ * Open for both read and write; new info will be appended to the file.
+ * Use MAP_PRIVATE so that a few changes to the in-memory ElfXX_Ehdr
+ * do not propagate to the file until an explicit overwrite at the last.
+ * This preserves most aspects of consistency (all except .st_size)
+ * for simultaneous readers of the file while we are appending to it.
+ * However, multiple writers still are bad.  We choose not to use
+ * locking because it is expensive and the use case of kernel build
+ * makes multiple writers unlikely.
+ */
+static void *mmap_file(char const *fname)
+{
+	void *addr;
+
+	fd_map = open(fname, O_RDWR);
+	if (0 > fd_map || 0 > fstat(fd_map, &sb)) {
+		perror(fname);
+		fail_file();
+	}
+	if (!S_ISREG(sb.st_mode)) {
+		fprintf(stderr, "not a regular file: %s\n", fname);
+		fail_file();
+	}
+	addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+		    fd_map, 0);
+	mmap_failed = 0;
+	if (MAP_FAILED == addr) {
+		mmap_failed = 1;
+		addr = umalloc(sb.st_size);
+		uread(fd_map, addr, sb.st_size);
+	}
+	return addr;
+}
+
+/* w8rev, w8nat, ...: Handle endianness. */
+
+static uint64_t w8rev(uint64_t const x)
+{
+	return   ((0xff & (x >> (0 * 8))) << (7 * 8))
+	       | ((0xff & (x >> (1 * 8))) << (6 * 8))
+	       | ((0xff & (x >> (2 * 8))) << (5 * 8))
+	       | ((0xff & (x >> (3 * 8))) << (4 * 8))
+	       | ((0xff & (x >> (4 * 8))) << (3 * 8))
+	       | ((0xff & (x >> (5 * 8))) << (2 * 8))
+	       | ((0xff & (x >> (6 * 8))) << (1 * 8))
+	       | ((0xff & (x >> (7 * 8))) << (0 * 8));
+}
+
+static uint32_t w4rev(uint32_t const x)
+{
+	return   ((0xff & (x >> (0 * 8))) << (3 * 8))
+	       | ((0xff & (x >> (1 * 8))) << (2 * 8))
+	       | ((0xff & (x >> (2 * 8))) << (1 * 8))
+	       | ((0xff & (x >> (3 * 8))) << (0 * 8));
+}
+
+static uint32_t w2rev(uint16_t const x)
+{
+	return   ((0xff & (x >> (0 * 8))) << (1 * 8))
+	       | ((0xff & (x >> (1 * 8))) << (0 * 8));
+}
+
+static uint64_t w8nat(uint64_t const x)
+{
+	return x;
+}
+
+static uint32_t w4nat(uint32_t const x)
+{
+	return x;
+}
+
+static uint32_t w2nat(uint16_t const x)
+{
+	return x;
+}
+
+static uint64_t (*w8)(uint64_t);
+static uint32_t (*w)(uint32_t);
+static uint32_t (*w2)(uint16_t);
+
+/* Names of the sections that could contain calls to mcount. */
+static int
+is_mcounted_section_name(char const *const txtname)
+{
+	return 0 == strcmp(".text",          txtname) ||
+		0 == strcmp(".sched.text",    txtname) ||
+		0 == strcmp(".spinlock.text", txtname) ||
+		0 == strcmp(".irqentry.text", txtname) ||
+		0 == strcmp(".text.unlikely", txtname);
+}
+
+/* 32 bit and 64 bit are very similar */
+#include "recordmcount.h"
+#define RECORD_MCOUNT_64
+#include "recordmcount.h"
+
+static void
+do_file(char const *const fname)
+{
+	Elf32_Ehdr *const ehdr = mmap_file(fname);
+	unsigned int reltype = 0;
+
+	ehdr_curr = ehdr;
+	w = w4nat;
+	w2 = w2nat;
+	w8 = w8nat;
+	switch (ehdr->e_ident[EI_DATA]) {
+		static unsigned int const endian = 1;
+	default: {
+		fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
+			ehdr->e_ident[EI_DATA], fname);
+		fail_file();
+	} break;
+	case ELFDATA2LSB: {
+		if (1 != *(unsigned char const *)&endian) {
+			/* main() is big endian, file.o is little endian. */
+			w = w4rev;
+			w2 = w2rev;
+			w8 = w8rev;
+		}
+	} break;
+	case ELFDATA2MSB: {
+		if (0 != *(unsigned char const *)&endian) {
+			/* main() is little endian, file.o is big endian. */
+			w = w4rev;
+			w2 = w2rev;
+			w8 = w8rev;
+		}
+	} break;
+	}  /* end switch */
+	if (0 != memcmp(ELFMAG, ehdr->e_ident, SELFMAG)
+	||  ET_REL != w2(ehdr->e_type)
+	||  EV_CURRENT != ehdr->e_ident[EI_VERSION]) {
+		fprintf(stderr, "unrecognized ET_REL file %s\n", fname);
+		fail_file();
+	}
+
+	gpfx = 0;
+	switch (w2(ehdr->e_machine)) {
+	default: {
+		fprintf(stderr, "unrecognized e_machine %d %s\n",
+			w2(ehdr->e_machine), fname);
+		fail_file();
+	} break;
+	case EM_386:	 reltype = R_386_32;                   break;
+	case EM_ARM:	 reltype = R_ARM_ABS32;                break;
+	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
+	case EM_PPC:	 reltype = R_PPC_ADDR32;   gpfx = '_'; break;
+	case EM_PPC64:	 reltype = R_PPC64_ADDR64; gpfx = '_'; break;
+	case EM_S390:    /* reltype: e_class    */ gpfx = '_'; break;
+	case EM_SH:	 reltype = R_SH_DIR32;                 break;
+	case EM_SPARCV9: reltype = R_SPARC_64;     gpfx = '_'; break;
+	case EM_X86_64:	 reltype = R_X86_64_64;                break;
+	}  /* end switch */
+
+	switch (ehdr->e_ident[EI_CLASS]) {
+	default: {
+		fprintf(stderr, "unrecognized ELF class %d %s\n",
+			ehdr->e_ident[EI_CLASS], fname);
+		fail_file();
+	} break;
+	case ELFCLASS32: {
+		if (sizeof(Elf32_Ehdr) != w2(ehdr->e_ehsize)
+		||  sizeof(Elf32_Shdr) != w2(ehdr->e_shentsize)) {
+			fprintf(stderr,
+				"unrecognized ET_REL file: %s\n", fname);
+			fail_file();
+		}
+		if (EM_S390 == w2(ehdr->e_machine))
+			reltype = R_390_32;
+		do32(ehdr, fname, reltype);
+	} break;
+	case ELFCLASS64: {
+		Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
+		if (sizeof(Elf64_Ehdr) != w2(ghdr->e_ehsize)
+		||  sizeof(Elf64_Shdr) != w2(ghdr->e_shentsize)) {
+			fprintf(stderr,
+				"unrecognized ET_REL file: %s\n", fname);
+			fail_file();
+		}
+		if (EM_S390 == w2(ghdr->e_machine))
+			reltype = R_390_64;
+		do64(ghdr, fname, reltype);
+	} break;
+	}  /* end switch */
+
+	cleanup();
+}
+
+int
+main(int argc, char const *argv[])
+{
+	const char ftrace[] = "kernel/trace/ftrace.o";
+	int ftrace_size = sizeof(ftrace) - 1;
+	int n_error = 0;  /* gcc-4.3.0 false positive complaint */
+
+	if (argc <= 1) {
+		fprintf(stderr, "usage: recordmcount file.o...\n");
+		return 0;
+	}
+
+	/* Process each file in turn, allowing deep failure. */
+	for (--argc, ++argv; 0 < argc; --argc, ++argv) {
+		int const sjval = setjmp(jmpenv);
+		int len;
+
+		/*
+		 * The file kernel/trace/ftrace.o references the mcount
+		 * function but does not call it. Since ftrace.o should
+		 * not be traced anyway, we just skip it.
+		 */
+		len = strlen(argv[0]);
+		if (len >= ftrace_size &&
+		    strcmp(argv[0] + (len - ftrace_size), ftrace) == 0)
+			continue;
+
+		switch (sjval) {
+		default: {
+			fprintf(stderr, "internal error: %s\n", argv[0]);
+			exit(1);
+		} break;
+		case SJ_SETJMP: {  /* normal sequence */
+			/* Avoid problems if early cleanup() */
+			fd_map = -1;
+			ehdr_curr = NULL;
+			mmap_failed = 1;
+			do_file(argv[0]);
+		} break;
+		case SJ_FAIL: {  /* error in do_file or below */
+			++n_error;
+		} break;
+		case SJ_SUCCEED: {  /* premature success */
+			/* do nothing */
+		} break;
+		}  /* end switch */
+	}
+	return !!n_error;
+}
+
+
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
new file mode 100644
index 0000000..7f39d09
--- /dev/null
+++ b/scripts/recordmcount.h
@@ -0,0 +1,366 @@
+/*
+ * recordmcount.h
+ *
+ * This code was taken out of recordmcount.c written by
+ * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>.  All rights reserved.
+ *
+ * The original code had the same algorithms for both 32bit
+ * and 64bit ELF files, but the code was duplicated to support
+ * the difference in structures that were used. This
+ * file creates a macro of everything that is different between
+ * the 64 and 32 bit code, such that by including this header
+ * twice we can create both sets of functions by including this
+ * header once with RECORD_MCOUNT_64 undefined, and again with
+ * it defined.
+ *
+ * This conversion to macros was done by:
+ * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+ *
+ * Licensed under the GNU General Public License, version 2 (GPLv2).
+ */
+#undef append_func
+#undef sift_rel_mcount
+#undef find_secsym_ndx
+#undef __has_rel_mcount
+#undef has_rel_mcount
+#undef tot_relsize
+#undef do_func
+#undef Elf_Ehdr
+#undef Elf_Shdr
+#undef Elf_Rel
+#undef Elf_Rela
+#undef Elf_Sym
+#undef ELF_R_SYM
+#undef ELF_R_INFO
+#undef ELF_ST_BIND
+#undef uint_t
+#undef _w
+#undef _align
+#undef _size
+
+#ifdef RECORD_MCOUNT_64
+# define append_func		append64
+# define sift_rel_mcount	sift64_rel_mcount
+# define find_secsym_ndx	find64_secsym_ndx
+# define __has_rel_mcount	__has64_rel_mcount
+# define has_rel_mcount		has64_rel_mcount
+# define tot_relsize		tot64_relsize
+# define do_func		do64
+# define Elf_Ehdr		Elf64_Ehdr
+# define Elf_Shdr		Elf64_Shdr
+# define Elf_Rel		Elf64_Rel
+# define Elf_Rela		Elf64_Rela
+# define Elf_Sym		Elf64_Sym
+# define ELF_R_SYM		ELF64_R_SYM
+# define ELF_R_INFO		ELF64_R_INFO
+# define ELF_ST_BIND		ELF64_ST_BIND
+# define uint_t			uint64_t
+# define _w			w8
+# define _align			7u
+# define _size			8
+#else
+# define append_func		append32
+# define sift_rel_mcount	sift32_rel_mcount
+# define find_secsym_ndx	find32_secsym_ndx
+# define __has_rel_mcount	__has32_rel_mcount
+# define has_rel_mcount		has32_rel_mcount
+# define tot_relsize		tot32_relsize
+# define do_func		do32
+# define Elf_Ehdr		Elf32_Ehdr
+# define Elf_Shdr		Elf32_Shdr
+# define Elf_Rel		Elf32_Rel
+# define Elf_Rela		Elf32_Rela
+# define Elf_Sym		Elf32_Sym
+# define ELF_R_SYM		ELF32_R_SYM
+# define ELF_R_INFO		ELF32_R_INFO
+# define ELF_ST_BIND		ELF32_ST_BIND
+# define uint_t			uint32_t
+# define _w			w
+# define _align			3u
+# define _size			4
+#endif
+
+/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
+static void append_func(Elf_Ehdr *const ehdr,
+			Elf_Shdr *const shstr,
+			uint_t const *const mloc0,
+			uint_t const *const mlocp,
+			Elf_Rel const *const mrel0,
+			Elf_Rel const *const mrelp,
+			unsigned int const rel_entsize,
+			unsigned int const symsec_sh_link)
+{
+	/* Begin constructing output file */
+	Elf_Shdr mcsec;
+	char const *mc_name = (sizeof(Elf_Rela) == rel_entsize)
+		? ".rela__mcount_loc"
+		:  ".rel__mcount_loc";
+	unsigned const old_shnum = w2(ehdr->e_shnum);
+	uint_t const old_shoff = _w(ehdr->e_shoff);
+	uint_t const old_shstr_sh_size   = _w(shstr->sh_size);
+	uint_t const old_shstr_sh_offset = _w(shstr->sh_offset);
+	uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size);
+	uint_t new_e_shoff;
+
+	shstr->sh_size = _w(t);
+	shstr->sh_offset = _w(sb.st_size);
+	t += sb.st_size;
+	t += (_align & -t);  /* word-byte align */
+	new_e_shoff = t;
+
+	/* body for new shstrtab */
+	ulseek(fd_map, sb.st_size, SEEK_SET);
+	uwrite(fd_map, old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size);
+	uwrite(fd_map, mc_name, 1 + strlen(mc_name));
+
+	/* old(modified) Elf_Shdr table, word-byte aligned */
+	ulseek(fd_map, t, SEEK_SET);
+	t += sizeof(Elf_Shdr) * old_shnum;
+	uwrite(fd_map, old_shoff + (void *)ehdr,
+	       sizeof(Elf_Shdr) * old_shnum);
+
+	/* new sections __mcount_loc and .rel__mcount_loc */
+	t += 2*sizeof(mcsec);
+	mcsec.sh_name = w((sizeof(Elf_Rela) == rel_entsize) + strlen(".rel")
+		+ old_shstr_sh_size);
+	mcsec.sh_type = w(SHT_PROGBITS);
+	mcsec.sh_flags = _w(SHF_ALLOC);
+	mcsec.sh_addr = 0;
+	mcsec.sh_offset = _w(t);
+	mcsec.sh_size = _w((void *)mlocp - (void *)mloc0);
+	mcsec.sh_link = 0;
+	mcsec.sh_info = 0;
+	mcsec.sh_addralign = _w(_size);
+	mcsec.sh_entsize = _w(_size);
+	uwrite(fd_map, &mcsec, sizeof(mcsec));
+
+	mcsec.sh_name = w(old_shstr_sh_size);
+	mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize)
+		? w(SHT_RELA)
+		: w(SHT_REL);
+	mcsec.sh_flags = 0;
+	mcsec.sh_addr = 0;
+	mcsec.sh_offset = _w((void *)mlocp - (void *)mloc0 + t);
+	mcsec.sh_size   = _w((void *)mrelp - (void *)mrel0);
+	mcsec.sh_link = w(symsec_sh_link);
+	mcsec.sh_info = w(old_shnum);
+	mcsec.sh_addralign = _w(_size);
+	mcsec.sh_entsize = _w(rel_entsize);
+	uwrite(fd_map, &mcsec, sizeof(mcsec));
+
+	uwrite(fd_map, mloc0, (void *)mlocp - (void *)mloc0);
+	uwrite(fd_map, mrel0, (void *)mrelp - (void *)mrel0);
+
+	ehdr->e_shoff = _w(new_e_shoff);
+	ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum));  /* {.rel,}__mcount_loc */
+	ulseek(fd_map, 0, SEEK_SET);
+	uwrite(fd_map, ehdr, sizeof(*ehdr));
+}
+
+
+/*
+ * Look at the relocations in order to find the calls to mcount.
+ * Accumulate the section offsets that are found, and their relocation info,
+ * onto the end of the existing arrays.
+ */
+static uint_t *sift_rel_mcount(uint_t *mlocp,
+			       unsigned const offbase,
+			       Elf_Rel **const mrelpp,
+			       Elf_Shdr const *const relhdr,
+			       Elf_Ehdr const *const ehdr,
+			       unsigned const recsym,
+			       uint_t const recval,
+			       unsigned const reltype)
+{
+	uint_t *const mloc0 = mlocp;
+	Elf_Rel *mrelp = *mrelpp;
+	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+		+ (void *)ehdr);
+	unsigned const symsec_sh_link = w(relhdr->sh_link);
+	Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
+	Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
+		+ (void *)ehdr);
+
+	Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
+	char const *const str0 = (char const *)(_w(strsec->sh_offset)
+		+ (void *)ehdr);
+
+	Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset)
+		+ (void *)ehdr);
+	unsigned rel_entsize = _w(relhdr->sh_entsize);
+	unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
+	Elf_Rel const *relp = rel0;
+
+	unsigned mcountsym = 0;
+	unsigned t;
+
+	for (t = nrel; t; --t) {
+		if (!mcountsym) {
+			Elf_Sym const *const symp =
+				&sym0[ELF_R_SYM(_w(relp->r_info))];
+			char const *symname = &str0[w(symp->st_name)];
+
+			if ('.' == symname[0])
+				++symname;  /* ppc64 hack */
+			if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
+					symname))
+				mcountsym = ELF_R_SYM(_w(relp->r_info));
+		}
+
+		if (mcountsym == ELF_R_SYM(_w(relp->r_info))) {
+			uint_t const addend = _w(_w(relp->r_offset) - recval);
+
+			mrelp->r_offset = _w(offbase
+				+ ((void *)mlocp - (void *)mloc0));
+			mrelp->r_info = _w(ELF_R_INFO(recsym, reltype));
+			if (sizeof(Elf_Rela) == rel_entsize) {
+				((Elf_Rela *)mrelp)->r_addend = addend;
+				*mlocp++ = 0;
+			} else
+				*mlocp++ = addend;
+
+			mrelp = (Elf_Rel *)(rel_entsize + (void *)mrelp);
+		}
+		relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
+	}
+	*mrelpp = mrelp;
+	return mlocp;
+}
+
+
+/*
+ * Find a symbol in the given section, to be used as the base for relocating
+ * the table of offsets of calls to mcount.  A local or global symbol suffices,
+ * but avoid a Weak symbol because it may be overridden; the change in value
+ * would invalidate the relocations of the offsets of the calls to mcount.
+ * Often the found symbol will be the unnamed local symbol generated by
+ * GNU 'as' for the start of each section.  For example:
+ *    Num:    Value  Size Type    Bind   Vis      Ndx Name
+ *      2: 00000000     0 SECTION LOCAL  DEFAULT    1
+ */
+static unsigned find_secsym_ndx(unsigned const txtndx,
+				char const *const txtname,
+				uint_t *const recvalp,
+				Elf_Shdr const *const symhdr,
+				Elf_Ehdr const *const ehdr)
+{
+	Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset)
+		+ (void *)ehdr);
+	unsigned const nsym = _w(symhdr->sh_size) / _w(symhdr->sh_entsize);
+	Elf_Sym const *symp;
+	unsigned t;
+
+	for (symp = sym0, t = nsym; t; --t, ++symp) {
+		unsigned int const st_bind = ELF_ST_BIND(symp->st_info);
+
+		if (txtndx == w2(symp->st_shndx)
+			/* avoid STB_WEAK */
+		    && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) {
+			*recvalp = _w(symp->st_value);
+			return symp - sym0;
+		}
+	}
+	fprintf(stderr, "Cannot find symbol for section %d: %s.\n",
+		txtndx, txtname);
+	fail_file();
+}
+
+
+/* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */
+static char const *
+__has_rel_mcount(Elf_Shdr const *const relhdr,  /* is SHT_REL or SHT_RELA */
+		 Elf_Shdr const *const shdr0,
+		 char const *const shstrtab,
+		 char const *const fname)
+{
+	/* .sh_info depends on .sh_type == SHT_REL[,A] */
+	Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
+	char const *const txtname = &shstrtab[w(txthdr->sh_name)];
+
+	if (0 == strcmp("__mcount_loc", txtname)) {
+		fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
+			fname);
+		succeed_file();
+	}
+	if (SHT_PROGBITS != w(txthdr->sh_type) ||
+	    !is_mcounted_section_name(txtname))
+		return NULL;
+	return txtname;
+}
+
+static char const *has_rel_mcount(Elf_Shdr const *const relhdr,
+				  Elf_Shdr const *const shdr0,
+				  char const *const shstrtab,
+				  char const *const fname)
+{
+	if (SHT_REL  != w(relhdr->sh_type) && SHT_RELA != w(relhdr->sh_type))
+		return NULL;
+	return __has_rel_mcount(relhdr, shdr0, shstrtab, fname);
+}
+
+
+static unsigned tot_relsize(Elf_Shdr const *const shdr0,
+			    unsigned nhdr,
+			    const char *const shstrtab,
+			    const char *const fname)
+{
+	unsigned totrelsz = 0;
+	Elf_Shdr const *shdrp = shdr0;
+
+	for (; nhdr; --nhdr, ++shdrp) {
+		if (has_rel_mcount(shdrp, shdr0, shstrtab, fname))
+			totrelsz += _w(shdrp->sh_size);
+	}
+	return totrelsz;
+}
+
+
+/* Overall supervision for Elf32 ET_REL file. */
+static void
+do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
+{
+	Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
+		+ (void *)ehdr);
+	unsigned const nhdr = w2(ehdr->e_shnum);
+	Elf_Shdr *const shstr = &shdr0[w2(ehdr->e_shstrndx)];
+	char const *const shstrtab = (char const *)(_w(shstr->sh_offset)
+		+ (void *)ehdr);
+
+	Elf_Shdr const *relhdr;
+	unsigned k;
+
+	/* Upper bound on space: assume all relevant relocs are for mcount. */
+	unsigned const totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
+	Elf_Rel *const mrel0 = umalloc(totrelsz);
+	Elf_Rel *      mrelp = mrel0;
+
+	/* 2*sizeof(address) <= sizeof(Elf_Rel) */
+	uint_t *const mloc0 = umalloc(totrelsz>>1);
+	uint_t *      mlocp = mloc0;
+
+	unsigned rel_entsize = 0;
+	unsigned symsec_sh_link = 0;
+
+	for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
+		char const *const txtname = has_rel_mcount(relhdr, shdr0,
+			shstrtab, fname);
+		if (txtname) {
+			uint_t recval = 0;
+			unsigned const recsym = find_secsym_ndx(
+				w(relhdr->sh_info), txtname, &recval,
+				&shdr0[symsec_sh_link = w(relhdr->sh_link)],
+				ehdr);
+
+			rel_entsize = _w(relhdr->sh_entsize);
+			mlocp = sift_rel_mcount(mlocp,
+				(void *)mlocp - (void *)mloc0, &mrelp,
+				relhdr, ehdr, recsym, recval, reltype);
+		}
+	}
+	if (mloc0 != mlocp) {
+		append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
+			    rel_entsize, symsec_sh_link);
+	}
+	free(mrel0);
+	free(mloc0);
+}
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index e67f0548..1d7963f 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -270,6 +270,8 @@
 } elsif ($arch eq "arm") {
     $alignment = 2;
     $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
+			"\\s+(__gnu_mcount_nc|mcount)\$";
 
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
index 0a0a99f..4d995ae 100644
--- a/security/apparmor/.gitignore
+++ b/security/apparmor/.gitignore
@@ -3,3 +3,4 @@
 #
 af_names.h
 capability_names.h
+rlim_names.h
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 7320331..0848292 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -29,7 +29,7 @@
  * aa_simple_write_to_buffer - common routine for getting policy from user
  * @op: operation doing the user buffer copy
  * @userbuf: user buffer to copy data from  (NOT NULL)
- * @alloc_size: size of user buffer
+ * @alloc_size: size of user buffer (REQUIRES: @alloc_size >= @copy_size)
  * @copy_size: size of data to copy from user buffer
  * @pos: position write is at in the file (NOT NULL)
  *
@@ -42,6 +42,8 @@
 {
 	char *data;
 
+	BUG_ON(copy_size > alloc_size);
+
 	if (*pos != 0)
 		/* only writes from pos 0, that is complete writes */
 		return ERR_PTR(-ESPIPE);
@@ -86,7 +88,8 @@
 }
 
 static const struct file_operations aa_fs_profile_load = {
-	.write = profile_load
+	.write = profile_load,
+	.llseek = default_llseek,
 };
 
 /* .replace file hook fn to load and/or replace policy */
@@ -107,7 +110,8 @@
 }
 
 static const struct file_operations aa_fs_profile_replace = {
-	.write = profile_replace
+	.write = profile_replace,
+	.llseek = default_llseek,
 };
 
 /* .remove file hook fn to remove loaded policy */
@@ -134,7 +138,8 @@
 }
 
 static const struct file_operations aa_fs_profile_remove = {
-	.write = profile_remove
+	.write = profile_remove,
+	.llseek = default_llseek,
 };
 
 /** Base file system setup **/
diff --git a/security/capability.c b/security/capability.c
index 95a6599..30ae00f 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -677,7 +677,18 @@
 {
 }
 
+static int cap_secmark_relabel_packet(u32 secid)
+{
+	return 0;
+}
 
+static void cap_secmark_refcount_inc(void)
+{
+}
+
+static void cap_secmark_refcount_dec(void)
+{
+}
 
 static void cap_req_classify_flow(const struct request_sock *req,
 				  struct flowi *fl)
@@ -777,7 +788,8 @@
 
 static int cap_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
-	return -EOPNOTSUPP;
+	*secid = 0;
+	return 0;
 }
 
 static void cap_release_secctx(char *secdata, u32 seclen)
@@ -1018,6 +1030,9 @@
 	set_to_cap_if_null(ops, inet_conn_request);
 	set_to_cap_if_null(ops, inet_csk_clone);
 	set_to_cap_if_null(ops, inet_conn_established);
+	set_to_cap_if_null(ops, secmark_relabel_packet);
+	set_to_cap_if_null(ops, secmark_refcount_inc);
+	set_to_cap_if_null(ops, secmark_refcount_dec);
 	set_to_cap_if_null(ops, req_classify_flow);
 	set_to_cap_if_null(ops, tun_dev_create);
 	set_to_cap_if_null(ops, tun_dev_post_create);
diff --git a/security/commoncap.c b/security/commoncap.c
index 9d172e6..5e632b4 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -719,14 +719,11 @@
 /**
  * cap_task_setscheduler - Detemine if scheduler policy change is permitted
  * @p: The task to affect
- * @policy: The policy to effect
- * @lp: The parameters to the scheduling policy
  *
  * Detemine if the requested scheduler policy change is permitted for the
  * specified task, returning 0 if permission is granted, -ve if denied.
  */
-int cap_task_setscheduler(struct task_struct *p, int policy,
-			   struct sched_param *lp)
+int cap_task_setscheduler(struct task_struct *p)
 {
 	return cap_safe_nice(p);
 }
diff --git a/security/inode.c b/security/inode.c
index 8c777f0..8883986 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -53,6 +53,7 @@
 	.read =		default_read_file,
 	.write =	default_write_file,
 	.open =		default_open,
+	.llseek =	noop_llseek,
 };
 
 static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
diff --git a/security/security.c b/security/security.c
index c53949f..b50f472 100644
--- a/security/security.c
+++ b/security/security.c
@@ -89,20 +89,12 @@
  * Return true if:
  *	-The passed LSM is the one chosen by user at boot time,
  *	-or the passed LSM is configured as the default and the user did not
- *	 choose an alternate LSM at boot time,
- *	-or there is no default LSM set and the user didn't specify a
- *	 specific LSM and we're the first to ask for registration permission,
- *	-or the passed LSM is currently loaded.
+ *	 choose an alternate LSM at boot time.
  * Otherwise, return false.
  */
 int __init security_module_enable(struct security_operations *ops)
 {
-	if (!*chosen_lsm)
-		strncpy(chosen_lsm, ops->name, SECURITY_NAME_MAX);
-	else if (strncmp(ops->name, chosen_lsm, SECURITY_NAME_MAX))
-		return 0;
-
-	return 1;
+	return !strcmp(ops->name, chosen_lsm);
 }
 
 /**
@@ -786,10 +778,9 @@
 	return security_ops->task_setrlimit(p, resource, new_rlim);
 }
 
-int security_task_setscheduler(struct task_struct *p,
-				int policy, struct sched_param *lp)
+int security_task_setscheduler(struct task_struct *p)
 {
-	return security_ops->task_setscheduler(p, policy, lp);
+	return security_ops->task_setscheduler(p);
 }
 
 int security_task_getscheduler(struct task_struct *p)
@@ -1145,6 +1136,24 @@
 	security_ops->inet_conn_established(sk, skb);
 }
 
+int security_secmark_relabel_packet(u32 secid)
+{
+	return security_ops->secmark_relabel_packet(secid);
+}
+EXPORT_SYMBOL(security_secmark_relabel_packet);
+
+void security_secmark_refcount_inc(void)
+{
+	security_ops->secmark_refcount_inc();
+}
+EXPORT_SYMBOL(security_secmark_refcount_inc);
+
+void security_secmark_refcount_dec(void)
+{
+	security_ops->secmark_refcount_dec();
+}
+EXPORT_SYMBOL(security_secmark_refcount_dec);
+
 int security_tun_dev_create(void)
 {
 	return security_ops->tun_dev_create();
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index 58d80f3..ad5cd76 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -2,25 +2,20 @@
 # Makefile for building the SELinux module as part of the kernel tree.
 #
 
-obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
+obj-$(CONFIG_SECURITY_SELINUX) := selinux.o
 
-selinux-y := avc.o \
-	     hooks.o \
-	     selinuxfs.o \
-	     netlink.o \
-	     nlmsgtab.o \
-	     netif.o \
-	     netnode.o \
-	     netport.o \
-	     exports.o
+selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \
+	     netnode.o netport.o exports.o \
+	     ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \
+	     ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/status.o
 
 selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
 
 selinux-$(CONFIG_NETLABEL) += netlabel.o
 
-EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include
+ccflags-y := -Isecurity/selinux -Isecurity/selinux/include
 
-$(obj)/avc.o: $(obj)/flask.h
+$(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h
 
 quiet_cmd_flask = GEN     $(obj)/flask.h $(obj)/av_permissions.h
       cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h
diff --git a/security/selinux/exports.c b/security/selinux/exports.c
index c0a454a..9066438 100644
--- a/security/selinux/exports.c
+++ b/security/selinux/exports.c
@@ -11,58 +11,9 @@
  * 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/module.h>
-#include <linux/selinux.h>
-#include <linux/fs.h>
-#include <linux/ipc.h>
-#include <asm/atomic.h>
 
 #include "security.h"
-#include "objsec.h"
-
-/* SECMARK reference count */
-extern atomic_t selinux_secmark_refcount;
-
-int selinux_string_to_sid(char *str, u32 *sid)
-{
-	if (selinux_enabled)
-		return security_context_to_sid(str, strlen(str), sid);
-	else {
-		*sid = 0;
-		return 0;
-	}
-}
-EXPORT_SYMBOL_GPL(selinux_string_to_sid);
-
-int selinux_secmark_relabel_packet_permission(u32 sid)
-{
-	if (selinux_enabled) {
-		const struct task_security_struct *__tsec;
-		u32 tsid;
-
-		__tsec = current_security();
-		tsid = __tsec->sid;
-
-		return avc_has_perm(tsid, sid, SECCLASS_PACKET,
-				    PACKET__RELABELTO, NULL);
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(selinux_secmark_relabel_packet_permission);
-
-void selinux_secmark_refcount_inc(void)
-{
-	atomic_inc(&selinux_secmark_refcount);
-}
-EXPORT_SYMBOL_GPL(selinux_secmark_refcount_inc);
-
-void selinux_secmark_refcount_dec(void)
-{
-	atomic_dec(&selinux_secmark_refcount);
-}
-EXPORT_SYMBOL_GPL(selinux_secmark_refcount_dec);
 
 bool selinux_is_enabled(void)
 {
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4796ddd..d9154cf 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3354,11 +3354,11 @@
 	return 0;
 }
 
-static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
+static int selinux_task_setscheduler(struct task_struct *p)
 {
 	int rc;
 
-	rc = cap_task_setscheduler(p, policy, lp);
+	rc = cap_task_setscheduler(p);
 	if (rc)
 		return rc;
 
@@ -4279,6 +4279,27 @@
 	selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
 }
 
+static int selinux_secmark_relabel_packet(u32 sid)
+{
+	const struct task_security_struct *__tsec;
+	u32 tsid;
+
+	__tsec = current_security();
+	tsid = __tsec->sid;
+
+	return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
+}
+
+static void selinux_secmark_refcount_inc(void)
+{
+	atomic_inc(&selinux_secmark_refcount);
+}
+
+static void selinux_secmark_refcount_dec(void)
+{
+	atomic_dec(&selinux_secmark_refcount);
+}
+
 static void selinux_req_classify_flow(const struct request_sock *req,
 				      struct flowi *fl)
 {
@@ -5533,6 +5554,9 @@
 	.inet_conn_request =		selinux_inet_conn_request,
 	.inet_csk_clone =		selinux_inet_csk_clone,
 	.inet_conn_established =	selinux_inet_conn_established,
+	.secmark_relabel_packet =	selinux_secmark_relabel_packet,
+	.secmark_refcount_inc =		selinux_secmark_refcount_inc,
+	.secmark_refcount_dec =		selinux_secmark_refcount_dec,
 	.req_classify_flow =		selinux_req_classify_flow,
 	.tun_dev_create =		selinux_tun_dev_create,
 	.tun_dev_post_create = 		selinux_tun_dev_post_create,
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index b4c9eb4..8858d2b 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -17,7 +17,7 @@
 	  { "compute_av", "compute_create", "compute_member",
 	    "check_context", "load_policy", "compute_relabel",
 	    "compute_user", "setenforce", "setbool", "setsecparam",
-	    "setcheckreqprot", NULL } },
+	    "setcheckreqprot", "read_policy", NULL } },
 	{ "process",
 	  { "fork", "transition", "sigchld", "sigkill",
 	    "sigstop", "signull", "signal", "ptrace", "getsched", "setsched",
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 1f7c249..671273e 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -9,6 +9,7 @@
 #define _SELINUX_SECURITY_H_
 
 #include <linux/magic.h>
+#include <linux/types.h>
 #include "flask.h"
 
 #define SECSID_NULL			0x00000000 /* unspecified SID */
@@ -82,6 +83,8 @@
 int security_mls_enabled(void);
 
 int security_load_policy(void *data, size_t len);
+int security_read_policy(void **data, ssize_t *len);
+size_t security_policydb_len(void);
 
 int security_policycap_supported(unsigned int req_cap);
 
@@ -191,5 +194,25 @@
 
 const char *security_get_initial_sid_context(u32 sid);
 
+/*
+ * status notifier using mmap interface
+ */
+extern struct page *selinux_kernel_status_page(void);
+
+#define SELINUX_KERNEL_STATUS_VERSION	1
+struct selinux_kernel_status {
+	u32	version;	/* version number of thie structure */
+	u32	sequence;	/* sequence number of seqlock logic */
+	u32	enforcing;	/* current setting of enforcing mode */
+	u32	policyload;	/* times of policy reloaded */
+	u32	deny_unknown;	/* current setting of deny_unknown */
+	/*
+	 * The version > 0 supports above members.
+	 */
+} __attribute__((packed));
+
+extern void selinux_status_update_setenforce(int enforcing);
+extern void selinux_status_update_policyload(int seqno);
+
 #endif /* _SELINUX_SECURITY_H_ */
 
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 79a1bb6..87e0556 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -68,6 +68,8 @@
 static struct dentry *class_dir;
 static unsigned long last_class_ino;
 
+static char policy_opened;
+
 /* global data for policy capabilities */
 static struct dentry *policycap_dir;
 
@@ -110,6 +112,8 @@
 	SEL_COMPAT_NET,	/* whether to use old compat network packet controls */
 	SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */
 	SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */
+	SEL_STATUS,	/* export current status using mmap() */
+	SEL_POLICY,	/* allow userspace to read the in kernel policy */
 	SEL_INO_NEXT,	/* The next inode number to use */
 };
 
@@ -171,6 +175,7 @@
 		if (selinux_enforcing)
 			avc_ss_reset(0);
 		selnl_notify_setenforce(selinux_enforcing);
+		selinux_status_update_setenforce(selinux_enforcing);
 	}
 	length = count;
 out:
@@ -205,6 +210,59 @@
 	.llseek		= generic_file_llseek,
 };
 
+static int sel_open_handle_status(struct inode *inode, struct file *filp)
+{
+	struct page    *status = selinux_kernel_status_page();
+
+	if (!status)
+		return -ENOMEM;
+
+	filp->private_data = status;
+
+	return 0;
+}
+
+static ssize_t sel_read_handle_status(struct file *filp, char __user *buf,
+				      size_t count, loff_t *ppos)
+{
+	struct page    *status = filp->private_data;
+
+	BUG_ON(!status);
+
+	return simple_read_from_buffer(buf, count, ppos,
+				       page_address(status),
+				       sizeof(struct selinux_kernel_status));
+}
+
+static int sel_mmap_handle_status(struct file *filp,
+				  struct vm_area_struct *vma)
+{
+	struct page    *status = filp->private_data;
+	unsigned long	size = vma->vm_end - vma->vm_start;
+
+	BUG_ON(!status);
+
+	/* only allows one page from the head */
+	if (vma->vm_pgoff > 0 || size != PAGE_SIZE)
+		return -EIO;
+	/* disallow writable mapping */
+	if (vma->vm_flags & VM_WRITE)
+		return -EPERM;
+	/* disallow mprotect() turns it into writable */
+	vma->vm_flags &= ~VM_MAYWRITE;
+
+	return remap_pfn_range(vma, vma->vm_start,
+			       page_to_pfn(status),
+			       size, vma->vm_page_prot);
+}
+
+static const struct file_operations sel_handle_status_ops = {
+	.open		= sel_open_handle_status,
+	.read		= sel_read_handle_status,
+	.mmap		= sel_mmap_handle_status,
+	.llseek		= generic_file_llseek,
+};
+
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
 static ssize_t sel_write_disable(struct file *file, const char __user *buf,
 				 size_t count, loff_t *ppos)
@@ -296,6 +354,141 @@
 	.llseek		= generic_file_llseek,
 };
 
+struct policy_load_memory {
+	size_t len;
+	void *data;
+};
+
+static int sel_open_policy(struct inode *inode, struct file *filp)
+{
+	struct policy_load_memory *plm = NULL;
+	int rc;
+
+	BUG_ON(filp->private_data);
+
+	mutex_lock(&sel_mutex);
+
+	rc = task_has_security(current, SECURITY__READ_POLICY);
+	if (rc)
+		goto err;
+
+	rc = -EBUSY;
+	if (policy_opened)
+		goto err;
+
+	rc = -ENOMEM;
+	plm = kzalloc(sizeof(*plm), GFP_KERNEL);
+	if (!plm)
+		goto err;
+
+	if (i_size_read(inode) != security_policydb_len()) {
+		mutex_lock(&inode->i_mutex);
+		i_size_write(inode, security_policydb_len());
+		mutex_unlock(&inode->i_mutex);
+	}
+
+	rc = security_read_policy(&plm->data, &plm->len);
+	if (rc)
+		goto err;
+
+	policy_opened = 1;
+
+	filp->private_data = plm;
+
+	mutex_unlock(&sel_mutex);
+
+	return 0;
+err:
+	mutex_unlock(&sel_mutex);
+
+	if (plm)
+		vfree(plm->data);
+	kfree(plm);
+	return rc;
+}
+
+static int sel_release_policy(struct inode *inode, struct file *filp)
+{
+	struct policy_load_memory *plm = filp->private_data;
+
+	BUG_ON(!plm);
+
+	policy_opened = 0;
+
+	vfree(plm->data);
+	kfree(plm);
+
+	return 0;
+}
+
+static ssize_t sel_read_policy(struct file *filp, char __user *buf,
+			       size_t count, loff_t *ppos)
+{
+	struct policy_load_memory *plm = filp->private_data;
+	int ret;
+
+	mutex_lock(&sel_mutex);
+
+	ret = task_has_security(current, SECURITY__READ_POLICY);
+	if (ret)
+		goto out;
+
+	ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len);
+out:
+	mutex_unlock(&sel_mutex);
+	return ret;
+}
+
+static int sel_mmap_policy_fault(struct vm_area_struct *vma,
+				 struct vm_fault *vmf)
+{
+	struct policy_load_memory *plm = vma->vm_file->private_data;
+	unsigned long offset;
+	struct page *page;
+
+	if (vmf->flags & (FAULT_FLAG_MKWRITE | FAULT_FLAG_WRITE))
+		return VM_FAULT_SIGBUS;
+
+	offset = vmf->pgoff << PAGE_SHIFT;
+	if (offset >= roundup(plm->len, PAGE_SIZE))
+		return VM_FAULT_SIGBUS;
+
+	page = vmalloc_to_page(plm->data + offset);
+	get_page(page);
+
+	vmf->page = page;
+
+	return 0;
+}
+
+static struct vm_operations_struct sel_mmap_policy_ops = {
+	.fault = sel_mmap_policy_fault,
+	.page_mkwrite = sel_mmap_policy_fault,
+};
+
+int sel_mmap_policy(struct file *filp, struct vm_area_struct *vma)
+{
+	if (vma->vm_flags & VM_SHARED) {
+		/* do not allow mprotect to make mapping writable */
+		vma->vm_flags &= ~VM_MAYWRITE;
+
+		if (vma->vm_flags & VM_WRITE)
+			return -EACCES;
+	}
+
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_ops = &sel_mmap_policy_ops;
+
+	return 0;
+}
+
+static const struct file_operations sel_policy_ops = {
+	.open		= sel_open_policy,
+	.read		= sel_read_policy,
+	.mmap		= sel_mmap_policy,
+	.release	= sel_release_policy,
+};
+
 static ssize_t sel_write_load(struct file *file, const char __user *buf,
 			      size_t count, loff_t *ppos)
 
@@ -1612,6 +1805,8 @@
 		[SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
 		[SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
 		[SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
+		[SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO},
+		[SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUSR},
 		/* last one */ {""}
 	};
 	ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
diff --git a/security/selinux/ss/Makefile b/security/selinux/ss/Makefile
deleted file mode 100644
index 15d4e62..0000000
--- a/security/selinux/ss/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for building the SELinux security server as part of the kernel tree.
-#
-
-EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include
-obj-y := ss.o
-
-ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o
-
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index 929480c..a3dd9fa 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -266,8 +266,8 @@
 	if (shift > 2)
 		shift = shift - 2;
 	nslot = 1 << shift;
-	if (nslot > MAX_AVTAB_SIZE)
-		nslot = MAX_AVTAB_SIZE;
+	if (nslot > MAX_AVTAB_HASH_BUCKETS)
+		nslot = MAX_AVTAB_HASH_BUCKETS;
 	mask = nslot - 1;
 
 	h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL);
@@ -501,6 +501,48 @@
 	goto out;
 }
 
+int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp)
+{
+	__le16 buf16[4];
+	__le32 buf32[1];
+	int rc;
+
+	buf16[0] = cpu_to_le16(cur->key.source_type);
+	buf16[1] = cpu_to_le16(cur->key.target_type);
+	buf16[2] = cpu_to_le16(cur->key.target_class);
+	buf16[3] = cpu_to_le16(cur->key.specified);
+	rc = put_entry(buf16, sizeof(u16), 4, fp);
+	if (rc)
+		return rc;
+	buf32[0] = cpu_to_le32(cur->datum.data);
+	rc = put_entry(buf32, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+	return 0;
+}
+
+int avtab_write(struct policydb *p, struct avtab *a, void *fp)
+{
+	unsigned int i;
+	int rc = 0;
+	struct avtab_node *cur;
+	__le32 buf[1];
+
+	buf[0] = cpu_to_le32(a->nel);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < a->nslot; i++) {
+		for (cur = a->htable[i]; cur; cur = cur->next) {
+			rc = avtab_write_item(p, cur, fp);
+			if (rc)
+				return rc;
+		}
+	}
+
+	return rc;
+}
 void avtab_cache_init(void)
 {
 	avtab_node_cachep = kmem_cache_create("avtab_node",
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index cd4f734..dff0c75 100644
--- a/security/selinux/ss/avtab.h
+++ b/security/selinux/ss/avtab.h
@@ -71,6 +71,8 @@
 		    void *p);
 
 int avtab_read(struct avtab *a, void *fp, struct policydb *pol);
+int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp);
+int avtab_write(struct policydb *p, struct avtab *a, void *fp);
 
 struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
 					  struct avtab_datum *datum);
@@ -85,7 +87,6 @@
 #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)
-#define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS
 
 #endif	/* _SS_AVTAB_H_ */
 
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index c91e150..655fe1c 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -490,6 +490,129 @@
 	return rc;
 }
 
+int cond_write_bool(void *vkey, void *datum, void *ptr)
+{
+	char *key = vkey;
+	struct cond_bool_datum *booldatum = datum;
+	struct policy_data *pd = ptr;
+	void *fp = pd->fp;
+	__le32 buf[3];
+	u32 len;
+	int rc;
+
+	len = strlen(key);
+	buf[0] = cpu_to_le32(booldatum->value);
+	buf[1] = cpu_to_le32(booldatum->state);
+	buf[2] = cpu_to_le32(len);
+	rc = put_entry(buf, sizeof(u32), 3, fp);
+	if (rc)
+		return rc;
+	rc = put_entry(key, 1, len, fp);
+	if (rc)
+		return rc;
+	return 0;
+}
+
+/*
+ * cond_write_cond_av_list doesn't write out the av_list nodes.
+ * Instead it writes out the key/value pairs from the avtab. This
+ * is necessary because there is no way to uniquely identifying rules
+ * in the avtab so it is not possible to associate individual rules
+ * in the avtab with a conditional without saving them as part of
+ * the conditional. This means that the avtab with the conditional
+ * rules will not be saved but will be rebuilt on policy load.
+ */
+static int cond_write_av_list(struct policydb *p,
+			      struct cond_av_list *list, struct policy_file *fp)
+{
+	__le32 buf[1];
+	struct cond_av_list *cur_list;
+	u32 len;
+	int rc;
+
+	len = 0;
+	for (cur_list = list; cur_list != NULL; cur_list = cur_list->next)
+		len++;
+
+	buf[0] = cpu_to_le32(len);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+
+	if (len == 0)
+		return 0;
+
+	for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
+		rc = avtab_write_item(p, cur_list->node, fp);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
+
+int cond_write_node(struct policydb *p, struct cond_node *node,
+		    struct policy_file *fp)
+{
+	struct cond_expr *cur_expr;
+	__le32 buf[2];
+	int rc;
+	u32 len = 0;
+
+	buf[0] = cpu_to_le32(node->cur_state);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+
+	for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next)
+		len++;
+
+	buf[0] = cpu_to_le32(len);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+
+	for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) {
+		buf[0] = cpu_to_le32(cur_expr->expr_type);
+		buf[1] = cpu_to_le32(cur_expr->bool);
+		rc = put_entry(buf, sizeof(u32), 2, fp);
+		if (rc)
+			return rc;
+	}
+
+	rc = cond_write_av_list(p, node->true_list, fp);
+	if (rc)
+		return rc;
+	rc = cond_write_av_list(p, node->false_list, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+int cond_write_list(struct policydb *p, struct cond_node *list, void *fp)
+{
+	struct cond_node *cur;
+	u32 len;
+	__le32 buf[1];
+	int rc;
+
+	len = 0;
+	for (cur = list; cur != NULL; cur = cur->next)
+		len++;
+	buf[0] = cpu_to_le32(len);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+
+	for (cur = list; cur != NULL; cur = cur->next) {
+		rc = cond_write_node(p, cur, fp);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
 /* Determine whether additional permissions are granted by the conditional
  * av table, and if so, add them to the result
  */
diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h
index 53ddb01..3f209c6 100644
--- a/security/selinux/ss/conditional.h
+++ b/security/selinux/ss/conditional.h
@@ -69,6 +69,8 @@
 
 int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp);
 int cond_read_list(struct policydb *p, void *fp);
+int cond_write_bool(void *key, void *datum, void *ptr);
+int cond_write_list(struct policydb *p, struct cond_node *list, void *fp);
 
 void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd);
 
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 04b6145..d42951f 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -22,6 +22,8 @@
 #include "ebitmap.h"
 #include "policydb.h"
 
+#define BITS_PER_U64	(sizeof(u64) * 8)
+
 int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
 {
 	struct ebitmap_node *n1, *n2;
@@ -363,10 +365,10 @@
 	e->highbit = le32_to_cpu(buf[1]);
 	count = le32_to_cpu(buf[2]);
 
-	if (mapunit != sizeof(u64) * 8) {
+	if (mapunit != BITS_PER_U64) {
 		printk(KERN_ERR "SELinux: ebitmap: map size %u does not "
 		       "match my size %Zd (high bit was %d)\n",
-		       mapunit, sizeof(u64) * 8, e->highbit);
+		       mapunit, BITS_PER_U64, e->highbit);
 		goto bad;
 	}
 
@@ -446,3 +448,78 @@
 	ebitmap_destroy(e);
 	goto out;
 }
+
+int ebitmap_write(struct ebitmap *e, void *fp)
+{
+	struct ebitmap_node *n;
+	u32 count;
+	__le32 buf[3];
+	u64 map;
+	int bit, last_bit, last_startbit, rc;
+
+	buf[0] = cpu_to_le32(BITS_PER_U64);
+
+	count = 0;
+	last_bit = 0;
+	last_startbit = -1;
+	ebitmap_for_each_positive_bit(e, n, bit) {
+		if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
+			count++;
+			last_startbit = rounddown(bit, BITS_PER_U64);
+		}
+		last_bit = roundup(bit + 1, BITS_PER_U64);
+	}
+	buf[1] = cpu_to_le32(last_bit);
+	buf[2] = cpu_to_le32(count);
+
+	rc = put_entry(buf, sizeof(u32), 3, fp);
+	if (rc)
+		return rc;
+
+	map = 0;
+	last_startbit = INT_MIN;
+	ebitmap_for_each_positive_bit(e, n, bit) {
+		if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
+			__le64 buf64[1];
+
+			/* this is the very first bit */
+			if (!map) {
+				last_startbit = rounddown(bit, BITS_PER_U64);
+				map = (u64)1 << (bit - last_startbit);
+				continue;
+			}
+
+			/* write the last node */
+			buf[0] = cpu_to_le32(last_startbit);
+			rc = put_entry(buf, sizeof(u32), 1, fp);
+			if (rc)
+				return rc;
+
+			buf64[0] = cpu_to_le64(map);
+			rc = put_entry(buf64, sizeof(u64), 1, fp);
+			if (rc)
+				return rc;
+
+			/* set up for the next node */
+			map = 0;
+			last_startbit = rounddown(bit, BITS_PER_U64);
+		}
+		map |= (u64)1 << (bit - last_startbit);
+	}
+	/* write the last node */
+	if (map) {
+		__le64 buf64[1];
+
+		/* write the last node */
+		buf[0] = cpu_to_le32(last_startbit);
+		rc = put_entry(buf, sizeof(u32), 1, fp);
+		if (rc)
+			return rc;
+
+		buf64[0] = cpu_to_le64(map);
+		rc = put_entry(buf64, sizeof(u64), 1, fp);
+		if (rc)
+			return rc;
+	}
+	return 0;
+}
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index f283b43..1f4e93c 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -123,6 +123,7 @@
 int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
 void ebitmap_destroy(struct ebitmap *e);
 int ebitmap_read(struct ebitmap *e, void *fp);
+int ebitmap_write(struct ebitmap *e, void *fp);
 
 #ifdef CONFIG_NETLABEL
 int ebitmap_netlbl_export(struct ebitmap *ebmap,
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 3a29704..94f630d 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -37,6 +37,7 @@
 #include "policydb.h"
 #include "conditional.h"
 #include "mls.h"
+#include "services.h"
 
 #define _DEBUG_HASHES
 
@@ -185,9 +186,19 @@
 static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
 {
 	const struct range_trans *key1 = k1, *key2 = k2;
-	return (key1->source_type != key2->source_type ||
-		key1->target_type != key2->target_type ||
-		key1->target_class != key2->target_class);
+	int v;
+
+	v = key1->source_type - key2->source_type;
+	if (v)
+		return v;
+
+	v = key1->target_type - key2->target_type;
+	if (v)
+		return v;
+
+	v = key1->target_class - key2->target_class;
+
+	return v;
 }
 
 /*
@@ -1624,11 +1635,11 @@
 
 static int type_bounds_sanity_check(void *key, void *datum, void *datap)
 {
-	struct type_datum *upper, *type;
+	struct type_datum *upper;
 	struct policydb *p = datap;
 	int depth = 0;
 
-	upper = type = datum;
+	upper = datum;
 	while (upper->bounds) {
 		if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
 			printk(KERN_ERR "SELinux: type %s: "
@@ -2306,3 +2317,843 @@
 	policydb_destroy(p);
 	goto out;
 }
+
+/*
+ * Write a MLS level structure to a policydb binary
+ * representation file.
+ */
+static int mls_write_level(struct mls_level *l, void *fp)
+{
+	__le32 buf[1];
+	int rc;
+
+	buf[0] = cpu_to_le32(l->sens);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+
+	rc = ebitmap_write(&l->cat, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+/*
+ * Write a MLS range structure to a policydb binary
+ * representation file.
+ */
+static int mls_write_range_helper(struct mls_range *r, void *fp)
+{
+	__le32 buf[3];
+	size_t items;
+	int rc, eq;
+
+	eq = mls_level_eq(&r->level[1], &r->level[0]);
+
+	if (eq)
+		items = 2;
+	else
+		items = 3;
+	buf[0] = cpu_to_le32(items-1);
+	buf[1] = cpu_to_le32(r->level[0].sens);
+	if (!eq)
+		buf[2] = cpu_to_le32(r->level[1].sens);
+
+	BUG_ON(items > (sizeof(buf)/sizeof(buf[0])));
+
+	rc = put_entry(buf, sizeof(u32), items, fp);
+	if (rc)
+		return rc;
+
+	rc = ebitmap_write(&r->level[0].cat, fp);
+	if (rc)
+		return rc;
+	if (!eq) {
+		rc = ebitmap_write(&r->level[1].cat, fp);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
+
+static int sens_write(void *vkey, void *datum, void *ptr)
+{
+	char *key = vkey;
+	struct level_datum *levdatum = datum;
+	struct policy_data *pd = ptr;
+	void *fp = pd->fp;
+	__le32 buf[2];
+	size_t len;
+	int rc;
+
+	len = strlen(key);
+	buf[0] = cpu_to_le32(len);
+	buf[1] = cpu_to_le32(levdatum->isalias);
+	rc = put_entry(buf, sizeof(u32), 2, fp);
+	if (rc)
+		return rc;
+
+	rc = put_entry(key, 1, len, fp);
+	if (rc)
+		return rc;
+
+	rc = mls_write_level(levdatum->level, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int cat_write(void *vkey, void *datum, void *ptr)
+{
+	char *key = vkey;
+	struct cat_datum *catdatum = datum;
+	struct policy_data *pd = ptr;
+	void *fp = pd->fp;
+	__le32 buf[3];
+	size_t len;
+	int rc;
+
+	len = strlen(key);
+	buf[0] = cpu_to_le32(len);
+	buf[1] = cpu_to_le32(catdatum->value);
+	buf[2] = cpu_to_le32(catdatum->isalias);
+	rc = put_entry(buf, sizeof(u32), 3, fp);
+	if (rc)
+		return rc;
+
+	rc = put_entry(key, 1, len, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int role_trans_write(struct role_trans *r, void *fp)
+{
+	struct role_trans *tr;
+	u32 buf[3];
+	size_t nel;
+	int rc;
+
+	nel = 0;
+	for (tr = r; tr; tr = tr->next)
+		nel++;
+	buf[0] = cpu_to_le32(nel);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+	for (tr = r; tr; tr = tr->next) {
+		buf[0] = cpu_to_le32(tr->role);
+		buf[1] = cpu_to_le32(tr->type);
+		buf[2] = cpu_to_le32(tr->new_role);
+		rc = put_entry(buf, sizeof(u32), 3, fp);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
+
+static int role_allow_write(struct role_allow *r, void *fp)
+{
+	struct role_allow *ra;
+	u32 buf[2];
+	size_t nel;
+	int rc;
+
+	nel = 0;
+	for (ra = r; ra; ra = ra->next)
+		nel++;
+	buf[0] = cpu_to_le32(nel);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+	for (ra = r; ra; ra = ra->next) {
+		buf[0] = cpu_to_le32(ra->role);
+		buf[1] = cpu_to_le32(ra->new_role);
+		rc = put_entry(buf, sizeof(u32), 2, fp);
+		if (rc)
+			return rc;
+	}
+	return 0;
+}
+
+/*
+ * Write a security context structure
+ * to a policydb binary representation file.
+ */
+static int context_write(struct policydb *p, struct context *c,
+			 void *fp)
+{
+	int rc;
+	__le32 buf[3];
+
+	buf[0] = cpu_to_le32(c->user);
+	buf[1] = cpu_to_le32(c->role);
+	buf[2] = cpu_to_le32(c->type);
+
+	rc = put_entry(buf, sizeof(u32), 3, fp);
+	if (rc)
+		return rc;
+
+	rc = mls_write_range_helper(&c->range, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+/*
+ * The following *_write functions are used to
+ * write the symbol data to a policy database
+ * binary representation file.
+ */
+
+static int perm_write(void *vkey, void *datum, void *fp)
+{
+	char *key = vkey;
+	struct perm_datum *perdatum = datum;
+	__le32 buf[2];
+	size_t len;
+	int rc;
+
+	len = strlen(key);
+	buf[0] = cpu_to_le32(len);
+	buf[1] = cpu_to_le32(perdatum->value);
+	rc = put_entry(buf, sizeof(u32), 2, fp);
+	if (rc)
+		return rc;
+
+	rc = put_entry(key, 1, len, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int common_write(void *vkey, void *datum, void *ptr)
+{
+	char *key = vkey;
+	struct common_datum *comdatum = datum;
+	struct policy_data *pd = ptr;
+	void *fp = pd->fp;
+	__le32 buf[4];
+	size_t len;
+	int rc;
+
+	len = strlen(key);
+	buf[0] = cpu_to_le32(len);
+	buf[1] = cpu_to_le32(comdatum->value);
+	buf[2] = cpu_to_le32(comdatum->permissions.nprim);
+	buf[3] = cpu_to_le32(comdatum->permissions.table->nel);
+	rc = put_entry(buf, sizeof(u32), 4, fp);
+	if (rc)
+		return rc;
+
+	rc = put_entry(key, 1, len, fp);
+	if (rc)
+		return rc;
+
+	rc = hashtab_map(comdatum->permissions.table, perm_write, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int write_cons_helper(struct policydb *p, struct constraint_node *node,
+			     void *fp)
+{
+	struct constraint_node *c;
+	struct constraint_expr *e;
+	__le32 buf[3];
+	u32 nel;
+	int rc;
+
+	for (c = node; c; c = c->next) {
+		nel = 0;
+		for (e = c->expr; e; e = e->next)
+			nel++;
+		buf[0] = cpu_to_le32(c->permissions);
+		buf[1] = cpu_to_le32(nel);
+		rc = put_entry(buf, sizeof(u32), 2, fp);
+		if (rc)
+			return rc;
+		for (e = c->expr; e; e = e->next) {
+			buf[0] = cpu_to_le32(e->expr_type);
+			buf[1] = cpu_to_le32(e->attr);
+			buf[2] = cpu_to_le32(e->op);
+			rc = put_entry(buf, sizeof(u32), 3, fp);
+			if (rc)
+				return rc;
+
+			switch (e->expr_type) {
+			case CEXPR_NAMES:
+				rc = ebitmap_write(&e->names, fp);
+				if (rc)
+					return rc;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int class_write(void *vkey, void *datum, void *ptr)
+{
+	char *key = vkey;
+	struct class_datum *cladatum = datum;
+	struct policy_data *pd = ptr;
+	void *fp = pd->fp;
+	struct policydb *p = pd->p;
+	struct constraint_node *c;
+	__le32 buf[6];
+	u32 ncons;
+	size_t len, len2;
+	int rc;
+
+	len = strlen(key);
+	if (cladatum->comkey)
+		len2 = strlen(cladatum->comkey);
+	else
+		len2 = 0;
+
+	ncons = 0;
+	for (c = cladatum->constraints; c; c = c->next)
+		ncons++;
+
+	buf[0] = cpu_to_le32(len);
+	buf[1] = cpu_to_le32(len2);
+	buf[2] = cpu_to_le32(cladatum->value);
+	buf[3] = cpu_to_le32(cladatum->permissions.nprim);
+	if (cladatum->permissions.table)
+		buf[4] = cpu_to_le32(cladatum->permissions.table->nel);
+	else
+		buf[4] = 0;
+	buf[5] = cpu_to_le32(ncons);
+	rc = put_entry(buf, sizeof(u32), 6, fp);
+	if (rc)
+		return rc;
+
+	rc = put_entry(key, 1, len, fp);
+	if (rc)
+		return rc;
+
+	if (cladatum->comkey) {
+		rc = put_entry(cladatum->comkey, 1, len2, fp);
+		if (rc)
+			return rc;
+	}
+
+	rc = hashtab_map(cladatum->permissions.table, perm_write, fp);
+	if (rc)
+		return rc;
+
+	rc = write_cons_helper(p, cladatum->constraints, fp);
+	if (rc)
+		return rc;
+
+	/* write out the validatetrans rule */
+	ncons = 0;
+	for (c = cladatum->validatetrans; c; c = c->next)
+		ncons++;
+
+	buf[0] = cpu_to_le32(ncons);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+
+	rc = write_cons_helper(p, cladatum->validatetrans, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int role_write(void *vkey, void *datum, void *ptr)
+{
+	char *key = vkey;
+	struct role_datum *role = datum;
+	struct policy_data *pd = ptr;
+	void *fp = pd->fp;
+	struct policydb *p = pd->p;
+	__le32 buf[3];
+	size_t items, len;
+	int rc;
+
+	len = strlen(key);
+	items = 0;
+	buf[items++] = cpu_to_le32(len);
+	buf[items++] = cpu_to_le32(role->value);
+	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
+		buf[items++] = cpu_to_le32(role->bounds);
+
+	BUG_ON(items > (sizeof(buf)/sizeof(buf[0])));
+
+	rc = put_entry(buf, sizeof(u32), items, fp);
+	if (rc)
+		return rc;
+
+	rc = put_entry(key, 1, len, fp);
+	if (rc)
+		return rc;
+
+	rc = ebitmap_write(&role->dominates, fp);
+	if (rc)
+		return rc;
+
+	rc = ebitmap_write(&role->types, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int type_write(void *vkey, void *datum, void *ptr)
+{
+	char *key = vkey;
+	struct type_datum *typdatum = datum;
+	struct policy_data *pd = ptr;
+	struct policydb *p = pd->p;
+	void *fp = pd->fp;
+	__le32 buf[4];
+	int rc;
+	size_t items, len;
+
+	len = strlen(key);
+	items = 0;
+	buf[items++] = cpu_to_le32(len);
+	buf[items++] = cpu_to_le32(typdatum->value);
+	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
+		u32 properties = 0;
+
+		if (typdatum->primary)
+			properties |= TYPEDATUM_PROPERTY_PRIMARY;
+
+		if (typdatum->attribute)
+			properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
+
+		buf[items++] = cpu_to_le32(properties);
+		buf[items++] = cpu_to_le32(typdatum->bounds);
+	} else {
+		buf[items++] = cpu_to_le32(typdatum->primary);
+	}
+	BUG_ON(items > (sizeof(buf) / sizeof(buf[0])));
+	rc = put_entry(buf, sizeof(u32), items, fp);
+	if (rc)
+		return rc;
+
+	rc = put_entry(key, 1, len, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int user_write(void *vkey, void *datum, void *ptr)
+{
+	char *key = vkey;
+	struct user_datum *usrdatum = datum;
+	struct policy_data *pd = ptr;
+	struct policydb *p = pd->p;
+	void *fp = pd->fp;
+	__le32 buf[3];
+	size_t items, len;
+	int rc;
+
+	len = strlen(key);
+	items = 0;
+	buf[items++] = cpu_to_le32(len);
+	buf[items++] = cpu_to_le32(usrdatum->value);
+	if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
+		buf[items++] = cpu_to_le32(usrdatum->bounds);
+	BUG_ON(items > (sizeof(buf) / sizeof(buf[0])));
+	rc = put_entry(buf, sizeof(u32), items, fp);
+	if (rc)
+		return rc;
+
+	rc = put_entry(key, 1, len, fp);
+	if (rc)
+		return rc;
+
+	rc = ebitmap_write(&usrdatum->roles, fp);
+	if (rc)
+		return rc;
+
+	rc = mls_write_range_helper(&usrdatum->range, fp);
+	if (rc)
+		return rc;
+
+	rc = mls_write_level(&usrdatum->dfltlevel, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int (*write_f[SYM_NUM]) (void *key, void *datum,
+				void *datap) =
+{
+	common_write,
+	class_write,
+	role_write,
+	type_write,
+	user_write,
+	cond_write_bool,
+	sens_write,
+	cat_write,
+};
+
+static int ocontext_write(struct policydb *p, struct policydb_compat_info *info,
+			  void *fp)
+{
+	unsigned int i, j, rc;
+	size_t nel, len;
+	__le32 buf[3];
+	u32 nodebuf[8];
+	struct ocontext *c;
+	for (i = 0; i < info->ocon_num; i++) {
+		nel = 0;
+		for (c = p->ocontexts[i]; c; c = c->next)
+			nel++;
+		buf[0] = cpu_to_le32(nel);
+		rc = put_entry(buf, sizeof(u32), 1, fp);
+		if (rc)
+			return rc;
+		for (c = p->ocontexts[i]; c; c = c->next) {
+			switch (i) {
+			case OCON_ISID:
+				buf[0] = cpu_to_le32(c->sid[0]);
+				rc = put_entry(buf, sizeof(u32), 1, fp);
+				if (rc)
+					return rc;
+				rc = context_write(p, &c->context[0], fp);
+				if (rc)
+					return rc;
+				break;
+			case OCON_FS:
+			case OCON_NETIF:
+				len = strlen(c->u.name);
+				buf[0] = cpu_to_le32(len);
+				rc = put_entry(buf, sizeof(u32), 1, fp);
+				if (rc)
+					return rc;
+				rc = put_entry(c->u.name, 1, len, fp);
+				if (rc)
+					return rc;
+				rc = context_write(p, &c->context[0], fp);
+				if (rc)
+					return rc;
+				rc = context_write(p, &c->context[1], fp);
+				if (rc)
+					return rc;
+				break;
+			case OCON_PORT:
+				buf[0] = cpu_to_le32(c->u.port.protocol);
+				buf[1] = cpu_to_le32(c->u.port.low_port);
+				buf[2] = cpu_to_le32(c->u.port.high_port);
+				rc = put_entry(buf, sizeof(u32), 3, fp);
+				if (rc)
+					return rc;
+				rc = context_write(p, &c->context[0], fp);
+				if (rc)
+					return rc;
+				break;
+			case OCON_NODE:
+				nodebuf[0] = c->u.node.addr; /* network order */
+				nodebuf[1] = c->u.node.mask; /* network order */
+				rc = put_entry(nodebuf, sizeof(u32), 2, fp);
+				if (rc)
+					return rc;
+				rc = context_write(p, &c->context[0], fp);
+				if (rc)
+					return rc;
+				break;
+			case OCON_FSUSE:
+				buf[0] = cpu_to_le32(c->v.behavior);
+				len = strlen(c->u.name);
+				buf[1] = cpu_to_le32(len);
+				rc = put_entry(buf, sizeof(u32), 2, fp);
+				if (rc)
+					return rc;
+				rc = put_entry(c->u.name, 1, len, fp);
+				if (rc)
+					return rc;
+				rc = context_write(p, &c->context[0], fp);
+				if (rc)
+					return rc;
+				break;
+			case OCON_NODE6:
+				for (j = 0; j < 4; j++)
+					nodebuf[j] = c->u.node6.addr[j]; /* network order */
+				for (j = 0; j < 4; j++)
+					nodebuf[j + 4] = c->u.node6.mask[j]; /* network order */
+				rc = put_entry(nodebuf, sizeof(u32), 8, fp);
+				if (rc)
+					return rc;
+				rc = context_write(p, &c->context[0], fp);
+				if (rc)
+					return rc;
+				break;
+			}
+		}
+	}
+	return 0;
+}
+
+static int genfs_write(struct policydb *p, void *fp)
+{
+	struct genfs *genfs;
+	struct ocontext *c;
+	size_t len;
+	__le32 buf[1];
+	int rc;
+
+	len = 0;
+	for (genfs = p->genfs; genfs; genfs = genfs->next)
+		len++;
+	buf[0] = cpu_to_le32(len);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+	for (genfs = p->genfs; genfs; genfs = genfs->next) {
+		len = strlen(genfs->fstype);
+		buf[0] = cpu_to_le32(len);
+		rc = put_entry(buf, sizeof(u32), 1, fp);
+		if (rc)
+			return rc;
+		rc = put_entry(genfs->fstype, 1, len, fp);
+		if (rc)
+			return rc;
+		len = 0;
+		for (c = genfs->head; c; c = c->next)
+			len++;
+		buf[0] = cpu_to_le32(len);
+		rc = put_entry(buf, sizeof(u32), 1, fp);
+		if (rc)
+			return rc;
+		for (c = genfs->head; c; c = c->next) {
+			len = strlen(c->u.name);
+			buf[0] = cpu_to_le32(len);
+			rc = put_entry(buf, sizeof(u32), 1, fp);
+			if (rc)
+				return rc;
+			rc = put_entry(c->u.name, 1, len, fp);
+			if (rc)
+				return rc;
+			buf[0] = cpu_to_le32(c->v.sclass);
+			rc = put_entry(buf, sizeof(u32), 1, fp);
+			if (rc)
+				return rc;
+			rc = context_write(p, &c->context[0], fp);
+			if (rc)
+				return rc;
+		}
+	}
+	return 0;
+}
+
+static int range_count(void *key, void *data, void *ptr)
+{
+	int *cnt = ptr;
+	*cnt = *cnt + 1;
+
+	return 0;
+}
+
+static int range_write_helper(void *key, void *data, void *ptr)
+{
+	__le32 buf[2];
+	struct range_trans *rt = key;
+	struct mls_range *r = data;
+	struct policy_data *pd = ptr;
+	void *fp = pd->fp;
+	struct policydb *p = pd->p;
+	int rc;
+
+	buf[0] = cpu_to_le32(rt->source_type);
+	buf[1] = cpu_to_le32(rt->target_type);
+	rc = put_entry(buf, sizeof(u32), 2, fp);
+	if (rc)
+		return rc;
+	if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) {
+		buf[0] = cpu_to_le32(rt->target_class);
+		rc = put_entry(buf, sizeof(u32), 1, fp);
+		if (rc)
+			return rc;
+	}
+	rc = mls_write_range_helper(r, fp);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int range_write(struct policydb *p, void *fp)
+{
+	size_t nel;
+	__le32 buf[1];
+	int rc;
+	struct policy_data pd;
+
+	pd.p = p;
+	pd.fp = fp;
+
+	/* count the number of entries in the hashtab */
+	nel = 0;
+	rc = hashtab_map(p->range_tr, range_count, &nel);
+	if (rc)
+		return rc;
+
+	buf[0] = cpu_to_le32(nel);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+
+	/* actually write all of the entries */
+	rc = hashtab_map(p->range_tr, range_write_helper, &pd);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+/*
+ * Write the configuration data in a policy database
+ * structure to a policy database binary representation
+ * file.
+ */
+int policydb_write(struct policydb *p, void *fp)
+{
+	unsigned int i, num_syms;
+	int rc;
+	__le32 buf[4];
+	u32 config;
+	size_t len;
+	struct policydb_compat_info *info;
+
+	/*
+	 * refuse to write policy older than compressed avtab
+	 * to simplify the writer.  There are other tests dropped
+	 * since we assume this throughout the writer code.  Be
+	 * careful if you ever try to remove this restriction
+	 */
+	if (p->policyvers < POLICYDB_VERSION_AVTAB) {
+		printk(KERN_ERR "SELinux: refusing to write policy version %d."
+		       "  Because it is less than version %d\n", p->policyvers,
+		       POLICYDB_VERSION_AVTAB);
+		return -EINVAL;
+	}
+
+	config = 0;
+	if (p->mls_enabled)
+		config |= POLICYDB_CONFIG_MLS;
+
+	if (p->reject_unknown)
+		config |= REJECT_UNKNOWN;
+	if (p->allow_unknown)
+		config |= ALLOW_UNKNOWN;
+
+	/* Write the magic number and string identifiers. */
+	buf[0] = cpu_to_le32(POLICYDB_MAGIC);
+	len = strlen(POLICYDB_STRING);
+	buf[1] = cpu_to_le32(len);
+	rc = put_entry(buf, sizeof(u32), 2, fp);
+	if (rc)
+		return rc;
+	rc = put_entry(POLICYDB_STRING, 1, len, fp);
+	if (rc)
+		return rc;
+
+	/* Write the version, config, and table sizes. */
+	info = policydb_lookup_compat(p->policyvers);
+	if (!info) {
+		printk(KERN_ERR "SELinux: compatibility lookup failed for policy "
+		    "version %d", p->policyvers);
+		return rc;
+	}
+
+	buf[0] = cpu_to_le32(p->policyvers);
+	buf[1] = cpu_to_le32(config);
+	buf[2] = cpu_to_le32(info->sym_num);
+	buf[3] = cpu_to_le32(info->ocon_num);
+
+	rc = put_entry(buf, sizeof(u32), 4, fp);
+	if (rc)
+		return rc;
+
+	if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
+		rc = ebitmap_write(&p->policycaps, fp);
+		if (rc)
+			return rc;
+	}
+
+	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) {
+		rc = ebitmap_write(&p->permissive_map, fp);
+		if (rc)
+			return rc;
+	}
+
+	num_syms = info->sym_num;
+	for (i = 0; i < num_syms; i++) {
+		struct policy_data pd;
+
+		pd.fp = fp;
+		pd.p = p;
+
+		buf[0] = cpu_to_le32(p->symtab[i].nprim);
+		buf[1] = cpu_to_le32(p->symtab[i].table->nel);
+
+		rc = put_entry(buf, sizeof(u32), 2, fp);
+		if (rc)
+			return rc;
+		rc = hashtab_map(p->symtab[i].table, write_f[i], &pd);
+		if (rc)
+			return rc;
+	}
+
+	rc = avtab_write(p, &p->te_avtab, fp);
+	if (rc)
+		return rc;
+
+	rc = cond_write_list(p, p->cond_list, fp);
+	if (rc)
+		return rc;
+
+	rc = role_trans_write(p->role_tr, fp);
+	if (rc)
+		return rc;
+
+	rc = role_allow_write(p->role_allow, fp);
+	if (rc)
+		return rc;
+
+	rc = ocontext_write(p, info, fp);
+	if (rc)
+		return rc;
+
+	rc = genfs_write(p, fp);
+	if (rc)
+		return rc;
+
+	rc = range_write(p, fp);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < p->p_types.nprim; i++) {
+		struct ebitmap *e = flex_array_get(p->type_attr_map_array, i);
+
+		BUG_ON(!e);
+		rc = ebitmap_write(e, fp);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 310e944..95d3d7d 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -254,6 +254,9 @@
 
 	struct ebitmap permissive_map;
 
+	/* length of this policy when it was loaded */
+	size_t len;
+
 	unsigned int policyvers;
 
 	unsigned int reject_unknown : 1;
@@ -270,6 +273,7 @@
 extern int policydb_type_isvalid(struct policydb *p, unsigned int type);
 extern int policydb_role_isvalid(struct policydb *p, unsigned int role);
 extern int policydb_read(struct policydb *p, void *fp);
+extern int policydb_write(struct policydb *p, void *fp);
 
 #define PERM_SYMTAB_SIZE 32
 
@@ -290,6 +294,11 @@
 	size_t len;
 };
 
+struct policy_data {
+	struct policydb *p;
+	void *fp;
+};
+
 static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
 {
 	if (bytes > fp->len)
@@ -301,6 +310,17 @@
 	return 0;
 }
 
+static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file *fp)
+{
+	size_t len = bytes * num;
+
+	memcpy(fp->data, buf, len);
+	fp->data += len;
+	fp->len -= len;
+
+	return 0;
+}
+
 extern u16 string_to_security_class(struct policydb *p, const char *name);
 extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name);
 
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 9ea2fec..223c1ff 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -51,6 +51,7 @@
 #include <linux/mutex.h>
 #include <linux/selinux.h>
 #include <linux/flex_array.h>
+#include <linux/vmalloc.h>
 #include <net/netlabel.h>
 
 #include "flask.h"
@@ -991,7 +992,8 @@
 {
 	char *scontextp;
 
-	*scontext = NULL;
+	if (scontext)
+		*scontext = NULL;
 	*scontext_len = 0;
 
 	if (context->len) {
@@ -1008,6 +1010,9 @@
 	*scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
 	*scontext_len += mls_compute_context_len(context);
 
+	if (!scontext)
+		return 0;
+
 	/* Allocate space for the context; caller must free this space. */
 	scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
 	if (!scontextp)
@@ -1047,7 +1052,8 @@
 	struct context *context;
 	int rc = 0;
 
-	*scontext = NULL;
+	if (scontext)
+		*scontext = NULL;
 	*scontext_len  = 0;
 
 	if (!ss_initialized) {
@@ -1055,6 +1061,8 @@
 			char *scontextp;
 
 			*scontext_len = strlen(initial_sid_to_string[sid]) + 1;
+			if (!scontext)
+				goto out;
 			scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
 			if (!scontextp) {
 				rc = -ENOMEM;
@@ -1769,6 +1777,7 @@
 			return rc;
 		}
 
+		policydb.len = len;
 		rc = selinux_set_mapping(&policydb, secclass_map,
 					 &current_mapping,
 					 &current_mapping_size);
@@ -1791,6 +1800,7 @@
 		selinux_complete_init();
 		avc_ss_reset(seqno);
 		selnl_notify_policyload(seqno);
+		selinux_status_update_policyload(seqno);
 		selinux_netlbl_cache_invalidate();
 		selinux_xfrm_notify_policyload();
 		return 0;
@@ -1804,6 +1814,7 @@
 	if (rc)
 		return rc;
 
+	newpolicydb.len = len;
 	/* If switching between different policy types, log MLS status */
 	if (policydb.mls_enabled && !newpolicydb.mls_enabled)
 		printk(KERN_INFO "SELinux: Disabling MLS support...\n");
@@ -1870,6 +1881,7 @@
 
 	avc_ss_reset(seqno);
 	selnl_notify_policyload(seqno);
+	selinux_status_update_policyload(seqno);
 	selinux_netlbl_cache_invalidate();
 	selinux_xfrm_notify_policyload();
 
@@ -1883,6 +1895,17 @@
 
 }
 
+size_t security_policydb_len(void)
+{
+	size_t len;
+
+	read_lock(&policy_rwlock);
+	len = policydb.len;
+	read_unlock(&policy_rwlock);
+
+	return len;
+}
+
 /**
  * security_port_sid - Obtain the SID for a port.
  * @protocol: protocol number
@@ -2374,6 +2397,7 @@
 	if (!rc) {
 		avc_ss_reset(seqno);
 		selnl_notify_policyload(seqno);
+		selinux_status_update_policyload(seqno);
 		selinux_xfrm_notify_policyload();
 	}
 	return rc;
@@ -3129,3 +3153,38 @@
 	return rc;
 }
 #endif /* CONFIG_NETLABEL */
+
+/**
+ * security_read_policy - read the policy.
+ * @data: binary policy data
+ * @len: length of data in bytes
+ *
+ */
+int security_read_policy(void **data, ssize_t *len)
+{
+	int rc;
+	struct policy_file fp;
+
+	if (!ss_initialized)
+		return -EINVAL;
+
+	*len = security_policydb_len();
+
+	*data = vmalloc_user(*len);
+	if (!*data)
+		return -ENOMEM;
+
+	fp.data = *data;
+	fp.len = *len;
+
+	read_lock(&policy_rwlock);
+	rc = policydb_write(&policydb, &fp);
+	read_unlock(&policy_rwlock);
+
+	if (rc)
+		return rc;
+
+	*len = (unsigned long)fp.data - (unsigned long)*data;
+	return 0;
+
+}
diff --git a/security/selinux/ss/status.c b/security/selinux/ss/status.c
new file mode 100644
index 0000000..d982365
--- /dev/null
+++ b/security/selinux/ss/status.c
@@ -0,0 +1,126 @@
+/*
+ * mmap based event notifications for SELinux
+ *
+ * Author: KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * Copyright (C) 2010 NEC corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include "avc.h"
+#include "services.h"
+
+/*
+ * The selinux_status_page shall be exposed to userspace applications
+ * using mmap interface on /selinux/status.
+ * It enables to notify applications a few events that will cause reset
+ * of userspace access vector without context switching.
+ *
+ * The selinux_kernel_status structure on the head of status page is
+ * protected from concurrent accesses using seqlock logic, so userspace
+ * application should reference the status page according to the seqlock
+ * logic.
+ *
+ * Typically, application checks status->sequence at the head of access
+ * control routine. If it is odd-number, kernel is updating the status,
+ * so please wait for a moment. If it is changed from the last sequence
+ * number, it means something happen, so application will reset userspace
+ * avc, if needed.
+ * In most cases, application shall confirm the kernel status is not
+ * changed without any system call invocations.
+ */
+static struct page *selinux_status_page;
+static DEFINE_MUTEX(selinux_status_lock);
+
+/*
+ * selinux_kernel_status_page
+ *
+ * It returns a reference to selinux_status_page. If the status page is
+ * not allocated yet, it also tries to allocate it at the first time.
+ */
+struct page *selinux_kernel_status_page(void)
+{
+	struct selinux_kernel_status   *status;
+	struct page		       *result = NULL;
+
+	mutex_lock(&selinux_status_lock);
+	if (!selinux_status_page) {
+		selinux_status_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
+
+		if (selinux_status_page) {
+			status = page_address(selinux_status_page);
+
+			status->version = SELINUX_KERNEL_STATUS_VERSION;
+			status->sequence = 0;
+			status->enforcing = selinux_enforcing;
+			/*
+			 * NOTE: the next policyload event shall set
+			 * a positive value on the status->policyload,
+			 * although it may not be 1, but never zero.
+			 * So, application can know it was updated.
+			 */
+			status->policyload = 0;
+			status->deny_unknown = !security_get_allow_unknown();
+		}
+	}
+	result = selinux_status_page;
+	mutex_unlock(&selinux_status_lock);
+
+	return result;
+}
+
+/*
+ * selinux_status_update_setenforce
+ *
+ * It updates status of the current enforcing/permissive mode.
+ */
+void selinux_status_update_setenforce(int enforcing)
+{
+	struct selinux_kernel_status   *status;
+
+	mutex_lock(&selinux_status_lock);
+	if (selinux_status_page) {
+		status = page_address(selinux_status_page);
+
+		status->sequence++;
+		smp_wmb();
+
+		status->enforcing = enforcing;
+
+		smp_wmb();
+		status->sequence++;
+	}
+	mutex_unlock(&selinux_status_lock);
+}
+
+/*
+ * selinux_status_update_policyload
+ *
+ * It updates status of the times of policy reloaded, and current
+ * setting of deny_unknown.
+ */
+void selinux_status_update_policyload(int seqno)
+{
+	struct selinux_kernel_status   *status;
+
+	mutex_lock(&selinux_status_lock);
+	if (selinux_status_page) {
+		status = page_address(selinux_status_page);
+
+		status->sequence++;
+		smp_wmb();
+
+		status->policyload = seqno;
+		status->deny_unknown = !security_get_allow_unknown();
+
+		smp_wmb();
+		status->sequence++;
+	}
+	mutex_unlock(&selinux_status_lock);
+}
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index c448d57..bc39f40 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1281,12 +1281,11 @@
  *
  * Return 0 if read access is permitted
  */
-static int smack_task_setscheduler(struct task_struct *p, int policy,
-				   struct sched_param *lp)
+static int smack_task_setscheduler(struct task_struct *p)
 {
 	int rc;
 
-	rc = cap_task_setscheduler(p, policy, lp);
+	rc = cap_task_setscheduler(p);
 	if (rc == 0)
 		rc = smk_curacc_on_task(p, MAY_WRITE);
 	return rc;
@@ -3005,7 +3004,8 @@
 {
 	char *sp = smack_from_secid(secid);
 
-	*secdata = sp;
+	if (secdata)
+		*secdata = sp;
 	*seclen = strlen(sp);
 	return 0;
 }
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index a2b72d7..7512502 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -968,6 +968,7 @@
 static const struct file_operations smk_doi_ops = {
 	.read		= smk_read_doi,
 	.write		= smk_write_doi,
+	.llseek		= default_llseek,
 };
 
 /**
@@ -1031,6 +1032,7 @@
 static const struct file_operations smk_direct_ops = {
 	.read		= smk_read_direct,
 	.write		= smk_write_direct,
+	.llseek		= default_llseek,
 };
 
 /**
@@ -1112,6 +1114,7 @@
 static const struct file_operations smk_ambient_ops = {
 	.read		= smk_read_ambient,
 	.write		= smk_write_ambient,
+	.llseek		= default_llseek,
 };
 
 /**
@@ -1191,6 +1194,7 @@
 static const struct file_operations smk_onlycap_ops = {
 	.read		= smk_read_onlycap,
 	.write		= smk_write_onlycap,
+	.llseek		= default_llseek,
 };
 
 /**
@@ -1255,6 +1259,7 @@
 static const struct file_operations smk_logging_ops = {
 	.read		= smk_read_logging,
 	.write		= smk_write_logging,
+	.llseek		= default_llseek,
 };
 /**
  * smk_fill_super - fill the /smackfs superblock
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index ef43995..7556315 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -768,8 +768,10 @@
 		return true; /* Do nothing if open(O_WRONLY). */
 	memset(&head->r, 0, sizeof(head->r));
 	head->r.print_this_domain_only = true;
-	head->r.eof = !domain;
-	head->r.domain = &domain->list;
+	if (domain)
+		head->r.domain = &domain->list;
+	else
+		head->r.eof = 1;
 	tomoyo_io_printf(head, "# select %s\n", data);
 	if (domain && domain->is_deleted)
 		tomoyo_io_printf(head, "# This is a deleted domain.\n");
@@ -1416,15 +1418,19 @@
 	const pid_t gpid = task_pid_nr(current);
 	static const int tomoyo_buffer_len = 4096;
 	char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
+	pid_t ppid;
 	if (!buffer)
 		return NULL;
 	do_gettimeofday(&tv);
+	rcu_read_lock();
+	ppid = task_tgid_vnr(current->real_parent);
+	rcu_read_unlock();
 	snprintf(buffer, tomoyo_buffer_len - 1,
 		 "#timestamp=%lu profile=%u mode=%s (global-pid=%u)"
 		 " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u"
 		 " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }",
 		 tv.tv_sec, r->profile, tomoyo_mode[r->mode], gpid,
-		 (pid_t) sys_getpid(), (pid_t) sys_getppid(),
+		 task_tgid_vnr(current), ppid,
 		 current_uid(), current_gid(), current_euid(),
 		 current_egid(), current_suid(), current_sgid(),
 		 current_fsuid(), current_fsgid());
@@ -2047,13 +2053,22 @@
 		const u8 profile = domain->profile;
 		if (tomoyo_profile_ptr[profile])
 			continue;
+		printk(KERN_ERR "You need to define profile %u before using it.\n",
+		       profile);
+		printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.3/ "
+		       "for more information.\n");
 		panic("Profile %u (used by '%s') not defined.\n",
 		      profile, domain->domainname->name);
 	}
 	tomoyo_read_unlock(idx);
-	if (tomoyo_profile_version != 20090903)
+	if (tomoyo_profile_version != 20090903) {
+		printk(KERN_ERR "You need to install userland programs for "
+		       "TOMOYO 2.3 and initialize policy configuration.\n");
+		printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.3/ "
+		       "for more information.\n");
 		panic("Profile version %u is not supported.\n",
 		      tomoyo_profile_version);
+	}
 	printk(KERN_INFO "TOMOYO: 2.3.0\n");
 	printk(KERN_INFO "Mandatory Access Control activated.\n");
 }
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 04454cb7b..7c66bd8 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -689,9 +689,6 @@
 
 /********** Function prototypes. **********/
 
-extern asmlinkage long sys_getpid(void);
-extern asmlinkage long sys_getppid(void);
-
 /* Check whether the given string starts with the given keyword. */
 bool tomoyo_str_starts(char **src, const char *find);
 /* Get tomoyo_realpath() of current process. */
diff --git a/sound/core/control.c b/sound/core/control.c
index 070aab4..45a8180 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -31,6 +31,7 @@
 
 /* max number of user-defined controls */
 #define MAX_USER_CONTROLS	32
+#define MAX_CONTROL_COUNT	1028
 
 struct snd_kctl_ioctl {
 	struct list_head list;		/* list of all ioctls */
@@ -195,6 +196,10 @@
 	
 	if (snd_BUG_ON(!control || !control->count))
 		return NULL;
+
+	if (control->count > MAX_CONTROL_COUNT)
+		return NULL;
+
 	kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL);
 	if (kctl == NULL) {
 		snd_printk(KERN_ERR "Cannot allocate control instance\n");
diff --git a/sound/core/init.c b/sound/core/init.c
index ec4a50c..f7c3df8 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -395,12 +395,10 @@
 		snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
 
 	snd_info_card_disconnect(card);
-#ifndef CONFIG_SYSFS_DEPRECATED
 	if (card->card_dev) {
 		device_unregister(card->card_dev);
 		card->card_dev = NULL;
 	}
-#endif
 #ifdef CONFIG_PM
 	wake_up(&card->power_sleep);
 #endif
@@ -573,7 +571,6 @@
 }
 EXPORT_SYMBOL(snd_card_set_id);
 
-#ifndef CONFIG_SYSFS_DEPRECATED
 static ssize_t
 card_id_show_attr(struct device *dev,
 		  struct device_attribute *attr, char *buf)
@@ -630,7 +627,6 @@
 
 static struct device_attribute card_number_attrs =
 	__ATTR(number, S_IRUGO, card_number_show_attr, NULL);
-#endif /* CONFIG_SYSFS_DEPRECATED */
 
 /**
  *  snd_card_register - register the soundcard
@@ -649,7 +645,7 @@
 
 	if (snd_BUG_ON(!card))
 		return -EINVAL;
-#ifndef CONFIG_SYSFS_DEPRECATED
+
 	if (!card->card_dev) {
 		card->card_dev = device_create(sound_class, card->dev,
 					       MKDEV(0, 0), card,
@@ -657,7 +653,7 @@
 		if (IS_ERR(card->card_dev))
 			card->card_dev = NULL;
 	}
-#endif
+
 	if ((err = snd_device_register_all(card)) < 0)
 		return err;
 	mutex_lock(&snd_card_mutex);
@@ -674,7 +670,6 @@
 	if (snd_mixer_oss_notify_callback)
 		snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
 #endif
-#ifndef CONFIG_SYSFS_DEPRECATED
 	if (card->card_dev) {
 		err = device_create_file(card->card_dev, &card_id_attrs);
 		if (err < 0)
@@ -683,7 +678,7 @@
 		if (err < 0)
 			return err;
 	}
-#endif
+
 	return 0;
 }
 
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index a7868ad..cbbed0d 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -535,13 +535,15 @@
 {
 	struct snd_rawmidi_file *rfile;
 	struct snd_rawmidi *rmidi;
+	struct module *module;
 
 	rfile = file->private_data;
 	rmidi = rfile->rmidi;
 	rawmidi_release_priv(rfile);
 	kfree(rfile);
+	module = rmidi->card->module;
 	snd_card_file_remove(rmidi->card, file);
-	module_put(rmidi->card->module);
+	module_put(module);
 	return 0;
 }
 
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index f25e3cc..a1f1a2f 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -220,6 +220,7 @@
 	.poll =		odev_poll,
 	.unlocked_ioctl =	odev_ioctl,
 	.compat_ioctl =	odev_ioctl_compat,
+	.llseek =	noop_llseek,
 };
 
 static int __init
diff --git a/sound/core/sound.c b/sound/core/sound.c
index ac42af4..62a093e 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -184,7 +184,8 @@
 static const struct file_operations snd_fops =
 {
 	.owner =	THIS_MODULE,
-	.open =		snd_open
+	.open =		snd_open,
+	.llseek =	noop_llseek,
 };
 
 #ifdef CONFIG_SND_DYNAMIC_MINORS
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 1adb8a3..42d7844 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -900,7 +900,7 @@
 	return 0;
 }
 #else /* !CONFIG_PROC_FS */
-static int proc_init(struct snd_akm4xxx *ak) {}
+static int proc_init(struct snd_akm4xxx *ak) { return 0; }
 #endif
 
 int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index 2e48b17..ca942f7 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -1117,6 +1117,7 @@
 	.unlocked_ioctl	= dev_ioctl,
 	.open		= dev_open,
 	.release	= dev_release,
+	.llseek		= noop_llseek,
 };
 
 static int reset_dsp(void)
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 92aa762..07f803e 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -391,11 +391,11 @@
 	case SND_DEV_DSP:
 	case SND_DEV_DSP16:
 	case SND_DEV_AUDIO:
-		return audio_ioctl(dev, file, cmd, p);
+		ret = audio_ioctl(dev, file, cmd, p);
 		break;
 
 	case SND_DEV_MIDIN:
-		return MIDIbuf_ioctl(dev, file, cmd, p);
+		ret = MIDIbuf_ioctl(dev, file, cmd, p);
 		break;
 
 	}
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index b697fd2..10bbbaf 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3641,6 +3641,7 @@
 	/* Lenovo Thinkpad T61/X61 */
 	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
 	SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
+	SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP),
 	{}
 };
 
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index a1312a6..a432e6e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1594,12 +1594,22 @@
 	}
 
 	if (spec->autocfg.dig_in_pin) {
-		hda_nid_t dig_nid;
-		err = snd_hda_get_connections(codec,
-					      spec->autocfg.dig_in_pin,
-					      &dig_nid, 1);
-		if (err > 0)
-			spec->dig_in_nid = dig_nid;
+		dig_nid = codec->start_nid;
+		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
+			unsigned int wcaps = get_wcaps(codec, dig_nid);
+			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
+				continue;
+			if (!(wcaps & AC_WCAP_DIGITAL))
+				continue;
+			if (!(wcaps & AC_WCAP_CONN_LIST))
+				continue;
+			err = get_connection_index(codec, dig_nid,
+						   spec->autocfg.dig_in_pin);
+			if (err >= 0) {
+				spec->dig_in_nid = dig_nid;
+				break;
+			}
+		}
 	}
 }
 
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 95148e5..c16c5ba 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1747,6 +1747,8 @@
 		      "HP dv6", STAC_HP_DV5),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061,
 		      "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x363e,
+		      "HP DV6", STAC_HP_DV5),
 	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010,
 		      "HP", STAC_HP_DV5),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 289cb4d..6c0a11a 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -543,6 +543,10 @@
 		chip->model.suspend = claro_suspend;
 		chip->model.resume = claro_resume;
 		chip->model.set_adc_params = set_ak5385_params;
+		chip->model.device_config = PLAYBACK_0_TO_I2S |
+					    PLAYBACK_1_TO_SPDIF |
+					    CAPTURE_0_FROM_I2S_2 |
+					    CAPTURE_1_FROM_SPDIF;
 		break;
 	}
 	if (id->driver_data == MODEL_MERIDIAN ||
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index b92adef..d6fa7bf 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -4609,6 +4609,7 @@
 		if (err < 0)
 			return err;
 
+		memset(&info, 0, sizeof(info));
 		spin_lock_irqsave(&hdsp->lock, flags);
 		info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp);
 		info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 547b713..0c98ef9 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -4127,6 +4127,7 @@
 
 	case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
 
+		memset(&info, 0, sizeof(info));
 		spin_lock_irq(&hdspm->lock);
 		info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
 		info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 7ab9174a..8cc4733 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -142,10 +142,9 @@
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->resource[0]->end = 16;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-	link->conf.ConfigIndex = 1;
-	link->conf.Present = PRESENT_OPTION;
+	link->config_flags = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
+	link->config_index = 1;
+	link->config_regs = PRESENT_OPTION;
 
 	return pdacf_config(link);
 }
@@ -217,7 +216,8 @@
 	int ret;
 
 	snd_printdd(KERN_DEBUG "pdacf_config called\n");
-	link->conf.ConfigIndex = 0x5;
+	link->config_index = 0x5;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
 
 	ret = pcmcia_request_io(link);
 	if (ret)
@@ -227,7 +227,7 @@
 	if (ret)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -287,9 +287,7 @@
 
 static struct pcmcia_driver pdacf_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "snd-pdaudiocf",
-	},
+	.name		= "snd-pdaudiocf",
 	.probe		= snd_pdacf_probe,
 	.remove		= snd_pdacf_detach,
 	.id_table	= snd_pdacf_ids,
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
index 5cc3e45..bd26e09 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h
@@ -24,7 +24,6 @@
 #include <sound/pcm.h>
 #include <asm/io.h>
 #include <linux/interrupt.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index a6edfc3..80000d6 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -2,7 +2,7 @@
  * Driver for Digigram VXpocket V2/440 soundcards
  *
  * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.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
@@ -162,10 +162,9 @@
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->resource[0]->end = 16;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-	link->conf.ConfigIndex = 1;
-	link->conf.Present = PRESENT_OPTION;
+	link->config_flags |= CONF_ENABLE_IRQ;
+	link->config_index = 1;
+	link->config_regs = PRESENT_OPTION;
 
 	*chip_ret = vxp;
 	return 0;
@@ -234,7 +233,7 @@
 	if (ret)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -359,9 +358,7 @@
 
 static struct pcmcia_driver vxp_cs_driver = {
 	.owner		= THIS_MODULE,
-	.drv		= {
-		.name	= "snd-vxpocket",
-	},
+	.name		= "snd-vxpocket",
 	.probe		= vxpocket_probe,
 	.remove		= vxpocket_detach,
 	.id_table	= vxp_ids,
diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h
index d911066..13d658c 100644
--- a/sound/pcmcia/vx/vxpocket.h
+++ b/sound/pcmcia/vx/vxpocket.h
@@ -23,7 +23,6 @@
 
 #include <sound/vx_core.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c
index b823a5c..87e2b7fc 100644
--- a/sound/soc/sh/migor.c
+++ b/sound/soc/sh/migor.c
@@ -12,6 +12,7 @@
 #include <linux/firmware.h>
 #include <linux/module.h>
 
+#include <asm/clkdev.h>
 #include <asm/clock.h>
 
 #include <cpu/sh7722.h>
@@ -40,12 +41,12 @@
 };
 
 static struct clk siumckb_clk = {
-	.name		= "siumckb_clk",
-	.id		= -1,
 	.ops		= &siumckb_clk_ops,
 	.rate		= 0, /* initialised at run-time */
 };
 
+static struct clk_lookup *siumckb_lookup;
+
 static int migor_hw_params(struct snd_pcm_substream *substream,
 			   struct snd_pcm_hw_params *params)
 {
@@ -180,6 +181,13 @@
 	if (ret < 0)
 		return ret;
 
+	siumckb_lookup = clkdev_alloc(&siumckb_clk, "siumckb_clk", NULL);
+	if (!siumckb_lookup) {
+		ret = -ENOMEM;
+		goto eclkdevalloc;
+	}
+	clkdev_add(siumckb_lookup);
+
 	/* Port number used on this machine: port B */
 	migor_snd_device = platform_device_alloc("soc-audio", 1);
 	if (!migor_snd_device) {
@@ -200,12 +208,15 @@
 epdevadd:
 	platform_device_put(migor_snd_device);
 epdevalloc:
+	clkdev_drop(siumckb_lookup);
+eclkdevalloc:
 	clk_unregister(&siumckb_clk);
 	return ret;
 }
 
 static void __exit migor_exit(void)
 {
+	clkdev_drop(siumckb_lookup);
 	clk_unregister(&siumckb_clk);
 	platform_device_unregister(migor_snd_device);
 }
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index adbc68c..f6b0d28 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -203,8 +203,9 @@
 	data[1] = (value >> 8) & 0xff;
 	data[2] = value & 0xff;
 
-	if (!snd_soc_codec_volatile_register(codec, reg))
-		reg_cache[reg] = value;
+	if (!snd_soc_codec_volatile_register(codec, reg)
+		&& reg < codec->reg_cache_size)
+			reg_cache[reg] = value;
 
 	if (codec->cache_only) {
 		codec->cache_sync = 1;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index acc91da..4057d35 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -223,6 +223,7 @@
 	.open = codec_reg_open_file,
 	.read = codec_reg_read_file,
 	.write = codec_reg_write_file,
+	.llseek = default_llseek,
 };
 
 static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 03cb7c0..72a53d0 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1089,6 +1089,7 @@
 static const struct file_operations dapm_widget_power_fops = {
 	.open = dapm_widget_power_open_file,
 	.read = dapm_widget_power_read_file,
+	.llseek = default_llseek,
 };
 
 void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
diff --git a/sound/sound_core.c b/sound/sound_core.c
index cb61317..c03bbae 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -165,6 +165,7 @@
 	/* We must have an owner or the module locking fails */
 	.owner	= THIS_MODULE,
 	.open	= soundcore_open,
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index 5164a65..b2c6330 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -8,7 +8,7 @@
 SYNOPSIS
 --------
 [verse]
-'perf annotate' [-i <file> | --input=file] symbol_name
+'perf annotate' [-i <file> | --input=file] [symbol_name]
 
 DESCRIPTION
 -----------
@@ -24,6 +24,13 @@
 --input=::
         Input file name. (default: perf.data)
 
+--stdio:: Use the stdio interface.
+
+--tui:: Use the TUI interface Use of --tui requires a tty, if one is not
+	present, as when piping to other commands, the stdio interface is
+	used. This interfaces starts by centering on the line with more
+	samples, TAB/UNTAB cycles thru the lines with more samples.
+
 SEE ALSO
 --------
-linkperf:perf-record[1]
+linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index abfabe9..12052c9 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -65,6 +65,13 @@
 		 the tree is considered as a new profiled object. +
 	Default: fractal,0.5.
 
+--stdio:: Use the stdio interface.
+
+--tui:: Use the TUI interface, that is integrated with annotate and allows
+        zooming into DSOs or threads, among other features. Use of --tui
+	requires a tty, if one is not present, as when piping to other
+	commands, the stdio interface is used.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 4f1fa77..d1db0f6 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -313,6 +313,9 @@
 
 SCRIPT_SH += perf-archive.sh
 
+grep-libs = $(filter -l%,$(1))
+strip-libs = $(filter-out -l%,$(1))
+
 #
 # No Perl scripts right now:
 #
@@ -588,14 +591,17 @@
 ifdef NO_LIBPERL
 	BASIC_CFLAGS += -DNO_LIBPERL
 else
-	PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts 2>/dev/null`
+       PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
+       PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
+       PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
 	PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
 	FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
 
 	ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED)),y)
 		BASIC_CFLAGS += -DNO_LIBPERL
 	else
-		ALL_LDFLAGS += $(PERL_EMBED_LDOPTS)
+               ALL_LDFLAGS += $(PERL_EMBED_LDFLAGS)
+               EXTLIBS += $(PERL_EMBED_LIBADD)
 		LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
 		LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
 	endif
@@ -604,13 +610,16 @@
 ifdef NO_LIBPYTHON
 	BASIC_CFLAGS += -DNO_LIBPYTHON
 else
-	PYTHON_EMBED_LDOPTS = `python-config --ldflags 2>/dev/null`
+       PYTHON_EMBED_LDOPTS = $(shell python-config --ldflags 2>/dev/null)
+       PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
+       PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
 	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)
 		BASIC_CFLAGS += -DNO_LIBPYTHON
 	else
-		ALL_LDFLAGS += $(PYTHON_EMBED_LDOPTS)
+               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
 	endif
@@ -653,6 +662,15 @@
 	endif
 endif
 
+
+ifdef NO_STRLCPY
+	BASIC_CFLAGS += -DNO_STRLCPY
+else
+	ifneq ($(call try-cc,$(SOURCE_STRLCPY),),y)
+		BASIC_CFLAGS += -DNO_STRLCPY
+	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
@@ -910,8 +928,8 @@
 		$(ALL_CFLAGS) -c $(filter %.c,$^) -o $@
 
 $(OUTPUT)perf$X: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
-	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(OUTPUT)perf.o \
-		$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
+	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(OUTPUT)perf.o \
+               $(BUILTIN_OBJS) $(LIBS) -o $@
 
 $(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
 	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
@@ -1017,7 +1035,7 @@
 # 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.
 DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
-$(DIRECTORY_DEPS): $(sort $(dir $(DIRECTORY_DEPS)))
+$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
 # In the second step, we make a rule to actually create these directories
 $(sort $(dir $(DIRECTORY_DEPS))):
 	$(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1478dc6..6d5604d8d 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -28,7 +28,7 @@
 
 static char		const *input_name = "perf.data";
 
-static bool		force;
+static bool		force, use_tui, use_stdio;
 
 static bool		full_paths;
 
@@ -321,7 +321,7 @@
 
 static void hists__find_annotations(struct hists *self)
 {
-	struct rb_node *first = rb_first(&self->entries), *nd = first;
+	struct rb_node *nd = rb_first(&self->entries), *next;
 	int key = KEY_RIGHT;
 
 	while (nd) {
@@ -343,20 +343,19 @@
 
 		if (use_browser > 0) {
 			key = hist_entry__tui_annotate(he);
-			if (is_exit_key(key))
-				break;
 			switch (key) {
 			case KEY_RIGHT:
-			case '\t':
-				nd = rb_next(nd);
+				next = rb_next(nd);
 				break;
 			case KEY_LEFT:
-				if (nd == first)
-					continue;
-				nd = rb_prev(nd);
-			default:
+				next = rb_prev(nd);
 				break;
+			default:
+				return;
 			}
+
+			if (next != NULL)
+				nd = next;
 		} else {
 			hist_entry__tty_annotate(he);
 			nd = rb_next(nd);
@@ -428,6 +427,8 @@
 		    "be more verbose (show symbol address, etc)"),
 	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
 		    "dump raw trace in ASCII"),
+	OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"),
+	OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
 	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
 		   "file", "vmlinux pathname"),
 	OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
@@ -443,6 +444,11 @@
 {
 	argc = parse_options(argc, argv, options, annotate_usage, 0);
 
+	if (use_stdio)
+		use_browser = 0;
+	else if (use_tui)
+		use_browser = 1;
+
 	setup_browser();
 
 	symbol_conf.priv_size = sizeof(struct sym_priv);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 55fc1f4..5de405d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -32,7 +32,7 @@
 
 static char		const *input_name = "perf.data";
 
-static bool		force;
+static bool		force, use_tui, use_stdio;
 static bool		hide_unresolved;
 static bool		dont_use_callchains;
 
@@ -107,7 +107,8 @@
 		goto out_free_syms;
 	err = 0;
 	if (symbol_conf.use_callchain) {
-		err = append_chain(he->callchain, data->callchain, syms, data->period);
+		err = callchain_append(he->callchain, data->callchain, syms,
+				       data->period);
 		if (err)
 			goto out_free_syms;
 	}
@@ -450,6 +451,8 @@
 		    "Show per-thread event counters"),
 	OPT_STRING(0, "pretty", &pretty_printing_style, "key",
 		   "pretty printing style key: normal raw"),
+	OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"),
+	OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
 	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
 		   "sort by key(s): pid, comm, dso, symbol, parent"),
 	OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
@@ -482,8 +485,15 @@
 {
 	argc = parse_options(argc, argv, options, report_usage, 0);
 
+	if (use_stdio)
+		use_browser = 0;
+	else if (use_tui)
+		use_browser = 1;
+
 	if (strcmp(input_name, "-") != 0)
 		setup_browser();
+	else
+		use_browser = 0;
 	/*
 	 * Only in the newt browser we are doing integrated annotation,
 	 * so don't allocate extra space that won't be used in the stdio
diff --git a/tools/perf/feature-tests.mak b/tools/perf/feature-tests.mak
index 7a7b608..b253db6 100644
--- a/tools/perf/feature-tests.mak
+++ b/tools/perf/feature-tests.mak
@@ -110,6 +110,17 @@
 }
 endef
 
+define SOURCE_STRLCPY
+#include <stdlib.h>
+extern size_t strlcpy(char *dest, const char *src, size_t size);
+
+int main(void)
+{
+	strlcpy(NULL, NULL, 0);
+	return 0;
+}
+endef
+
 # try-cc
 # Usage: option = $(call try-cc, source-to-build, cc-options)
 try-cc = $(shell sh -c						  \
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index ef7aa0a..95aaf56 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -73,6 +73,18 @@
 #define cpu_relax()	asm volatile("":::"memory")
 #endif
 
+#ifdef __mips__
+#include "../../arch/mips/include/asm/unistd.h"
+#define rmb()		asm volatile(					\
+				".set	mips2\n\t"			\
+				"sync\n\t"				\
+				".set	mips0"				\
+				: /* no output */			\
+				: /* no input */			\
+				: "memory")
+#define cpu_relax()	asm volatile("" ::: "memory")
+#endif
+
 #include <time.h>
 #include <unistd.h>
 #include <sys/types.h>
diff --git a/tools/perf/scripts/python/bin/netdev-times-record b/tools/perf/scripts/python/bin/netdev-times-record
new file mode 100644
index 0000000..d931a82
--- /dev/null
+++ b/tools/perf/scripts/python/bin/netdev-times-record
@@ -0,0 +1,8 @@
+#!/bin/bash
+perf record -a -e net:net_dev_xmit -e net:net_dev_queue		\
+		-e net:netif_receive_skb -e net:netif_rx		\
+		-e skb:consume_skb -e skb:kfree_skb			\
+		-e skb:skb_copy_datagram_iovec -e napi:napi_poll	\
+		-e irq:irq_handler_entry -e irq:irq_handler_exit	\
+		-e irq:softirq_entry -e irq:softirq_exit		\
+		-e irq:softirq_raise $@
diff --git a/tools/perf/scripts/python/bin/netdev-times-report b/tools/perf/scripts/python/bin/netdev-times-report
new file mode 100644
index 0000000..c3d0a63
--- /dev/null
+++ b/tools/perf/scripts/python/bin/netdev-times-report
@@ -0,0 +1,5 @@
+#!/bin/bash
+# description: display a process of packet and processing time
+# args: [tx] [rx] [dev=] [debug]
+
+perf trace -s ~/libexec/perf-core/scripts/python/netdev-times.py $@
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
new file mode 100644
index 0000000..9aa0a32
--- /dev/null
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -0,0 +1,464 @@
+# Display a process of packets and processed time.
+# It helps us to investigate networking or network device.
+#
+# options
+# tx: show only tx chart
+# rx: show only rx chart
+# dev=: show only thing related to specified device
+# debug: work with debug mode. It shows buffer status.
+
+import os
+import sys
+
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
+
+from perf_trace_context import *
+from Core import *
+from Util import *
+
+all_event_list = []; # insert all tracepoint event related with this script
+irq_dic = {}; # key is cpu and value is a list which stacks irqs
+              # which raise NET_RX softirq
+net_rx_dic = {}; # key is cpu and value include time of NET_RX softirq-entry
+		 # and a list which stacks receive
+receive_hunk_list = []; # a list which include a sequence of receive events
+rx_skb_list = []; # received packet list for matching
+		       # skb_copy_datagram_iovec
+
+buffer_budget = 65536; # the budget of rx_skb_list, tx_queue_list and
+		       # tx_xmit_list
+of_count_rx_skb_list = 0; # overflow count
+
+tx_queue_list = []; # list of packets which pass through dev_queue_xmit
+of_count_tx_queue_list = 0; # overflow count
+
+tx_xmit_list = [];  # list of packets which pass through dev_hard_start_xmit
+of_count_tx_xmit_list = 0; # overflow count
+
+tx_free_list = [];  # list of packets which is freed
+
+# options
+show_tx = 0;
+show_rx = 0;
+dev = 0; # store a name of device specified by option "dev="
+debug = 0;
+
+# indices of event_info tuple
+EINFO_IDX_NAME=   0
+EINFO_IDX_CONTEXT=1
+EINFO_IDX_CPU=    2
+EINFO_IDX_TIME=   3
+EINFO_IDX_PID=    4
+EINFO_IDX_COMM=   5
+
+# Calculate a time interval(msec) from src(nsec) to dst(nsec)
+def diff_msec(src, dst):
+	return (dst - src) / 1000000.0
+
+# Display a process of transmitting a packet
+def print_transmit(hunk):
+	if dev != 0 and hunk['dev'].find(dev) < 0:
+		return
+	print "%7s %5d %6d.%06dsec %12.3fmsec      %12.3fmsec" % \
+		(hunk['dev'], hunk['len'],
+		nsecs_secs(hunk['queue_t']),
+		nsecs_nsecs(hunk['queue_t'])/1000,
+		diff_msec(hunk['queue_t'], hunk['xmit_t']),
+		diff_msec(hunk['xmit_t'], hunk['free_t']))
+
+# Format for displaying rx packet processing
+PF_IRQ_ENTRY= "  irq_entry(+%.3fmsec irq=%d:%s)"
+PF_SOFT_ENTRY="  softirq_entry(+%.3fmsec)"
+PF_NAPI_POLL= "  napi_poll_exit(+%.3fmsec %s)"
+PF_JOINT=     "         |"
+PF_WJOINT=    "         |            |"
+PF_NET_RECV=  "         |---netif_receive_skb(+%.3fmsec skb=%x len=%d)"
+PF_NET_RX=    "         |---netif_rx(+%.3fmsec skb=%x)"
+PF_CPY_DGRAM= "         |      skb_copy_datagram_iovec(+%.3fmsec %d:%s)"
+PF_KFREE_SKB= "         |      kfree_skb(+%.3fmsec location=%x)"
+PF_CONS_SKB=  "         |      consume_skb(+%.3fmsec)"
+
+# Display a process of received packets and interrputs associated with
+# a NET_RX softirq
+def print_receive(hunk):
+	show_hunk = 0
+	irq_list = hunk['irq_list']
+	cpu = irq_list[0]['cpu']
+	base_t = irq_list[0]['irq_ent_t']
+	# check if this hunk should be showed
+	if dev != 0:
+		for i in range(len(irq_list)):
+			if irq_list[i]['name'].find(dev) >= 0:
+				show_hunk = 1
+				break
+	else:
+		show_hunk = 1
+	if show_hunk == 0:
+		return
+
+	print "%d.%06dsec cpu=%d" % \
+		(nsecs_secs(base_t), nsecs_nsecs(base_t)/1000, cpu)
+	for i in range(len(irq_list)):
+		print PF_IRQ_ENTRY % \
+			(diff_msec(base_t, irq_list[i]['irq_ent_t']),
+			irq_list[i]['irq'], irq_list[i]['name'])
+		print PF_JOINT
+		irq_event_list = irq_list[i]['event_list']
+		for j in range(len(irq_event_list)):
+			irq_event = irq_event_list[j]
+			if irq_event['event'] == 'netif_rx':
+				print PF_NET_RX % \
+					(diff_msec(base_t, irq_event['time']),
+					irq_event['skbaddr'])
+				print PF_JOINT
+	print PF_SOFT_ENTRY % \
+		diff_msec(base_t, hunk['sirq_ent_t'])
+	print PF_JOINT
+	event_list = hunk['event_list']
+	for i in range(len(event_list)):
+		event = event_list[i]
+		if event['event_name'] == 'napi_poll':
+			print PF_NAPI_POLL % \
+			    (diff_msec(base_t, event['event_t']), event['dev'])
+			if i == len(event_list) - 1:
+				print ""
+			else:
+				print PF_JOINT
+		else:
+			print PF_NET_RECV % \
+			    (diff_msec(base_t, event['event_t']), event['skbaddr'],
+				event['len'])
+			if 'comm' in event.keys():
+				print PF_WJOINT
+				print PF_CPY_DGRAM % \
+					(diff_msec(base_t, event['comm_t']),
+					event['pid'], event['comm'])
+			elif 'handle' in event.keys():
+				print PF_WJOINT
+				if event['handle'] == "kfree_skb":
+					print PF_KFREE_SKB % \
+						(diff_msec(base_t,
+						event['comm_t']),
+						event['location'])
+				elif event['handle'] == "consume_skb":
+					print PF_CONS_SKB % \
+						diff_msec(base_t,
+							event['comm_t'])
+			print PF_JOINT
+
+def trace_begin():
+	global show_tx
+	global show_rx
+	global dev
+	global debug
+
+	for i in range(len(sys.argv)):
+		if i == 0:
+			continue
+		arg = sys.argv[i]
+		if arg == 'tx':
+			show_tx = 1
+		elif arg =='rx':
+			show_rx = 1
+		elif arg.find('dev=',0, 4) >= 0:
+			dev = arg[4:]
+		elif arg == 'debug':
+			debug = 1
+	if show_tx == 0  and show_rx == 0:
+		show_tx = 1
+		show_rx = 1
+
+def trace_end():
+	# order all events in time
+	all_event_list.sort(lambda a,b :cmp(a[EINFO_IDX_TIME],
+					    b[EINFO_IDX_TIME]))
+	# process all events
+	for i in range(len(all_event_list)):
+		event_info = all_event_list[i]
+		name = event_info[EINFO_IDX_NAME]
+		if name == 'irq__softirq_exit':
+			handle_irq_softirq_exit(event_info)
+		elif name == 'irq__softirq_entry':
+			handle_irq_softirq_entry(event_info)
+		elif name == 'irq__softirq_raise':
+			handle_irq_softirq_raise(event_info)
+		elif name == 'irq__irq_handler_entry':
+			handle_irq_handler_entry(event_info)
+		elif name == 'irq__irq_handler_exit':
+			handle_irq_handler_exit(event_info)
+		elif name == 'napi__napi_poll':
+			handle_napi_poll(event_info)
+		elif name == 'net__netif_receive_skb':
+			handle_netif_receive_skb(event_info)
+		elif name == 'net__netif_rx':
+			handle_netif_rx(event_info)
+		elif name == 'skb__skb_copy_datagram_iovec':
+			handle_skb_copy_datagram_iovec(event_info)
+		elif name == 'net__net_dev_queue':
+			handle_net_dev_queue(event_info)
+		elif name == 'net__net_dev_xmit':
+			handle_net_dev_xmit(event_info)
+		elif name == 'skb__kfree_skb':
+			handle_kfree_skb(event_info)
+		elif name == 'skb__consume_skb':
+			handle_consume_skb(event_info)
+	# display receive hunks
+	if show_rx:
+		for i in range(len(receive_hunk_list)):
+			print_receive(receive_hunk_list[i])
+	# display transmit hunks
+	if show_tx:
+		print "   dev    len      Qdisc        " \
+			"       netdevice             free"
+		for i in range(len(tx_free_list)):
+			print_transmit(tx_free_list[i])
+	if debug:
+		print "debug buffer status"
+		print "----------------------------"
+		print "xmit Qdisc:remain:%d overflow:%d" % \
+			(len(tx_queue_list), of_count_tx_queue_list)
+		print "xmit netdevice:remain:%d overflow:%d" % \
+			(len(tx_xmit_list), of_count_tx_xmit_list)
+		print "receive:remain:%d overflow:%d" % \
+			(len(rx_skb_list), of_count_rx_skb_list)
+
+# called from perf, when it finds a correspoinding event
+def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec):
+	if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
+		return
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
+	all_event_list.append(event_info)
+
+def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec):
+	if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
+		return
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
+	all_event_list.append(event_info)
+
+def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec):
+	if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
+		return
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
+	all_event_list.append(event_info)
+
+def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
+			irq, irq_name):
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+			irq, irq_name)
+	all_event_list.append(event_info)
+
+def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret):
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
+	all_event_list.append(event_info)
+
+def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name):
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+			napi, dev_name)
+	all_event_list.append(event_info)
+
+def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+			skblen, dev_name):
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+			skbaddr, skblen, dev_name)
+	all_event_list.append(event_info)
+
+def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+			skblen, dev_name):
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+			skbaddr, skblen, dev_name)
+	all_event_list.append(event_info)
+
+def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm,
+			skbaddr, skblen, dev_name):
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+			skbaddr, skblen, dev_name)
+	all_event_list.append(event_info)
+
+def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm,
+			skbaddr, skblen, rc, dev_name):
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+			skbaddr, skblen, rc ,dev_name)
+	all_event_list.append(event_info)
+
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+			skbaddr, protocol, location):
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+			skbaddr, protocol, location)
+	all_event_list.append(event_info)
+
+def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr):
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+			skbaddr)
+	all_event_list.append(event_info)
+
+def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm,
+	skbaddr, skblen):
+	event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
+			skbaddr, skblen)
+	all_event_list.append(event_info)
+
+def handle_irq_handler_entry(event_info):
+	(name, context, cpu, time, pid, comm, irq, irq_name) = event_info
+	if cpu not in irq_dic.keys():
+		irq_dic[cpu] = []
+	irq_record = {'irq':irq, 'name':irq_name, 'cpu':cpu, 'irq_ent_t':time}
+	irq_dic[cpu].append(irq_record)
+
+def handle_irq_handler_exit(event_info):
+	(name, context, cpu, time, pid, comm, irq, ret) = event_info
+	if cpu not in irq_dic.keys():
+		return
+	irq_record = irq_dic[cpu].pop()
+	if irq != irq_record['irq']:
+		return
+	irq_record.update({'irq_ext_t':time})
+	# if an irq doesn't include NET_RX softirq, drop.
+	if 'event_list' in irq_record.keys():
+		irq_dic[cpu].append(irq_record)
+
+def handle_irq_softirq_raise(event_info):
+	(name, context, cpu, time, pid, comm, vec) = event_info
+	if cpu not in irq_dic.keys() \
+	or len(irq_dic[cpu]) == 0:
+		return
+	irq_record = irq_dic[cpu].pop()
+	if 'event_list' in irq_record.keys():
+		irq_event_list = irq_record['event_list']
+	else:
+		irq_event_list = []
+	irq_event_list.append({'time':time, 'event':'sirq_raise'})
+	irq_record.update({'event_list':irq_event_list})
+	irq_dic[cpu].append(irq_record)
+
+def handle_irq_softirq_entry(event_info):
+	(name, context, cpu, time, pid, comm, vec) = event_info
+	net_rx_dic[cpu] = {'sirq_ent_t':time, 'event_list':[]}
+
+def handle_irq_softirq_exit(event_info):
+	(name, context, cpu, time, pid, comm, vec) = event_info
+	irq_list = []
+	event_list = 0
+	if cpu in irq_dic.keys():
+		irq_list = irq_dic[cpu]
+		del irq_dic[cpu]
+	if cpu in net_rx_dic.keys():
+		sirq_ent_t = net_rx_dic[cpu]['sirq_ent_t']
+		event_list = net_rx_dic[cpu]['event_list']
+		del net_rx_dic[cpu]
+	if irq_list == [] or event_list == 0:
+		return
+	rec_data = {'sirq_ent_t':sirq_ent_t, 'sirq_ext_t':time,
+		    'irq_list':irq_list, 'event_list':event_list}
+	# merge information realted to a NET_RX softirq
+	receive_hunk_list.append(rec_data)
+
+def handle_napi_poll(event_info):
+	(name, context, cpu, time, pid, comm, napi, dev_name) = event_info
+	if cpu in net_rx_dic.keys():
+		event_list = net_rx_dic[cpu]['event_list']
+		rec_data = {'event_name':'napi_poll',
+				'dev':dev_name, 'event_t':time}
+		event_list.append(rec_data)
+
+def handle_netif_rx(event_info):
+	(name, context, cpu, time, pid, comm,
+		skbaddr, skblen, dev_name) = event_info
+	if cpu not in irq_dic.keys() \
+	or len(irq_dic[cpu]) == 0:
+		return
+	irq_record = irq_dic[cpu].pop()
+	if 'event_list' in irq_record.keys():
+		irq_event_list = irq_record['event_list']
+	else:
+		irq_event_list = []
+	irq_event_list.append({'time':time, 'event':'netif_rx',
+		'skbaddr':skbaddr, 'skblen':skblen, 'dev_name':dev_name})
+	irq_record.update({'event_list':irq_event_list})
+	irq_dic[cpu].append(irq_record)
+
+def handle_netif_receive_skb(event_info):
+	global of_count_rx_skb_list
+
+	(name, context, cpu, time, pid, comm,
+		skbaddr, skblen, dev_name) = event_info
+	if cpu in net_rx_dic.keys():
+		rec_data = {'event_name':'netif_receive_skb',
+			    'event_t':time, 'skbaddr':skbaddr, 'len':skblen}
+		event_list = net_rx_dic[cpu]['event_list']
+		event_list.append(rec_data)
+		rx_skb_list.insert(0, rec_data)
+		if len(rx_skb_list) > buffer_budget:
+			rx_skb_list.pop()
+			of_count_rx_skb_list += 1
+
+def handle_net_dev_queue(event_info):
+	global of_count_tx_queue_list
+
+	(name, context, cpu, time, pid, comm,
+		skbaddr, skblen, dev_name) = event_info
+	skb = {'dev':dev_name, 'skbaddr':skbaddr, 'len':skblen, 'queue_t':time}
+	tx_queue_list.insert(0, skb)
+	if len(tx_queue_list) > buffer_budget:
+		tx_queue_list.pop()
+		of_count_tx_queue_list += 1
+
+def handle_net_dev_xmit(event_info):
+	global of_count_tx_xmit_list
+
+	(name, context, cpu, time, pid, comm,
+		skbaddr, skblen, rc, dev_name) = event_info
+	if rc == 0: # NETDEV_TX_OK
+		for i in range(len(tx_queue_list)):
+			skb = tx_queue_list[i]
+			if skb['skbaddr'] == skbaddr:
+				skb['xmit_t'] = time
+				tx_xmit_list.insert(0, skb)
+				del tx_queue_list[i]
+				if len(tx_xmit_list) > buffer_budget:
+					tx_xmit_list.pop()
+					of_count_tx_xmit_list += 1
+				return
+
+def handle_kfree_skb(event_info):
+	(name, context, cpu, time, pid, comm,
+		skbaddr, protocol, location) = event_info
+	for i in range(len(tx_queue_list)):
+		skb = tx_queue_list[i]
+		if skb['skbaddr'] == skbaddr:
+			del tx_queue_list[i]
+			return
+	for i in range(len(tx_xmit_list)):
+		skb = tx_xmit_list[i]
+		if skb['skbaddr'] == skbaddr:
+			skb['free_t'] = time
+			tx_free_list.append(skb)
+			del tx_xmit_list[i]
+			return
+	for i in range(len(rx_skb_list)):
+		rec_data = rx_skb_list[i]
+		if rec_data['skbaddr'] == skbaddr:
+			rec_data.update({'handle':"kfree_skb",
+					'comm':comm, 'pid':pid, 'comm_t':time})
+			del rx_skb_list[i]
+			return
+
+def handle_consume_skb(event_info):
+	(name, context, cpu, time, pid, comm, skbaddr) = event_info
+	for i in range(len(tx_xmit_list)):
+		skb = tx_xmit_list[i]
+		if skb['skbaddr'] == skbaddr:
+			skb['free_t'] = time
+			tx_free_list.append(skb)
+			del tx_xmit_list[i]
+			return
+
+def handle_skb_copy_datagram_iovec(event_info):
+	(name, context, cpu, time, pid, comm, skbaddr, skblen) = event_info
+	for i in range(len(rx_skb_list)):
+		rec_data = rx_skb_list[i]
+		if skbaddr == rec_data['skbaddr']:
+			rec_data.update({'handle':"skb_copy_datagram_iovec",
+					'comm':comm, 'pid':pid, 'comm_t':time})
+			del rx_skb_list[i]
+			return
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 27e9ebe..a772979 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -82,6 +82,8 @@
 extern char *perf_pathdup(const char *fmt, ...)
 	__attribute__((format (printf, 1, 2)));
 
+#ifdef NO_STRLCPY
 extern size_t strlcpy(char *dest, const char *src, size_t size);
+#endif
 
 #endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index f231f43..e12d539 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -28,6 +28,9 @@
 #define chain_for_each_child(child, parent)	\
 	list_for_each_entry(child, &parent->children, brothers)
 
+#define chain_for_each_child_safe(child, next, parent)	\
+	list_for_each_entry_safe(child, next, &parent->children, brothers)
+
 static void
 rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
 		    enum chain_mode mode)
@@ -86,10 +89,10 @@
  * sort them by hit
  */
 static void
-sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
+sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
 		u64 min_hit, struct callchain_param *param __used)
 {
-	__sort_chain_flat(rb_root, node, min_hit);
+	__sort_chain_flat(rb_root, &root->node, min_hit);
 }
 
 static void __sort_chain_graph_abs(struct callchain_node *node,
@@ -108,11 +111,11 @@
 }
 
 static void
-sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_node *chain_root,
+sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
 		     u64 min_hit, struct callchain_param *param __used)
 {
-	__sort_chain_graph_abs(chain_root, min_hit);
-	rb_root->rb_node = chain_root->rb_root.rb_node;
+	__sort_chain_graph_abs(&chain_root->node, min_hit);
+	rb_root->rb_node = chain_root->node.rb_root.rb_node;
 }
 
 static void __sort_chain_graph_rel(struct callchain_node *node,
@@ -133,11 +136,11 @@
 }
 
 static void
-sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_node *chain_root,
+sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
 		     u64 min_hit __used, struct callchain_param *param)
 {
-	__sort_chain_graph_rel(chain_root, param->min_percent / 100.0);
-	rb_root->rb_node = chain_root->rb_root.rb_node;
+	__sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0);
+	rb_root->rb_node = chain_root->node.rb_root.rb_node;
 }
 
 int register_callchain_param(struct callchain_param *param)
@@ -284,19 +287,18 @@
 }
 
 static int
-__append_chain(struct callchain_node *root, struct resolved_chain *chain,
-	       unsigned int start, u64 period);
+append_chain(struct callchain_node *root, struct resolved_chain *chain,
+	     unsigned int start, 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 resolved_chain *chain,
+		      unsigned int start, 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, chain, start, period);
 
 		if (!ret)
 			goto inc_children_hit;
@@ -309,8 +311,8 @@
 }
 
 static int
-__append_chain(struct callchain_node *root, struct resolved_chain *chain,
-	       unsigned int start, u64 period)
+append_chain(struct callchain_node *root, struct resolved_chain *chain,
+	     unsigned int start, u64 period)
 {
 	struct callchain_list *cnode;
 	unsigned int i = start;
@@ -357,7 +359,7 @@
 	}
 
 	/* We match the node and still have a part remaining */
-	__append_chain_children(root, chain, i, period);
+	append_chain_children(root, chain, i, period);
 
 	return 0;
 }
@@ -380,8 +382,8 @@
 }
 
 
-int append_chain(struct callchain_node *root, struct ip_callchain *chain,
-		 struct map_symbol *syms, u64 period)
+int callchain_append(struct callchain_root *root, struct ip_callchain *chain,
+		     struct map_symbol *syms, u64 period)
 {
 	struct resolved_chain *filtered;
 
@@ -398,9 +400,65 @@
 	if (!filtered->nr)
 		goto end;
 
-	__append_chain_children(root, filtered, 0, period);
+	append_chain_children(&root->node, filtered, 0, period);
+
+	if (filtered->nr > root->max_depth)
+		root->max_depth = filtered->nr;
 end:
 	free(filtered);
 
 	return 0;
 }
+
+static int
+merge_chain_branch(struct callchain_node *dst, struct callchain_node *src,
+		   struct resolved_chain *chain)
+{
+	struct callchain_node *child, *next_child;
+	struct callchain_list *list, *next_list;
+	int old_pos = chain->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++;
+		list_del(&list->list);
+		free(list);
+	}
+
+	if (src->hit)
+		append_chain_children(dst, chain, 0, src->hit);
+
+	chain_for_each_child_safe(child, next_child, src) {
+		err = merge_chain_branch(dst, child, chain);
+		if (err)
+			break;
+
+		list_del(&child->brothers);
+		free(child);
+	}
+
+	chain->nr = old_pos;
+
+	return err;
+}
+
+int callchain_merge(struct callchain_root *dst, struct callchain_root *src)
+{
+	struct resolved_chain *chain;
+	int err;
+
+	chain = malloc(sizeof(*chain) +
+		       src->max_depth * sizeof(struct resolved_ip));
+	if (!chain)
+		return -ENOMEM;
+
+	chain->nr = 0;
+
+	err = merge_chain_branch(&dst->node, &src->node, chain);
+
+	free(chain);
+
+	return err;
+}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 6de4313..c15fb8c 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -26,9 +26,14 @@
 	u64			children_hit;
 };
 
+struct callchain_root {
+	u64			max_depth;
+	struct callchain_node	node;
+};
+
 struct callchain_param;
 
-typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *,
+typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
 				 u64, struct callchain_param *);
 
 struct callchain_param {
@@ -44,15 +49,16 @@
 	struct list_head	list;
 };
 
-static inline void callchain_init(struct callchain_node *node)
+static inline void callchain_init(struct callchain_root *root)
 {
-	INIT_LIST_HEAD(&node->brothers);
-	INIT_LIST_HEAD(&node->children);
-	INIT_LIST_HEAD(&node->val);
+	INIT_LIST_HEAD(&root->node.brothers);
+	INIT_LIST_HEAD(&root->node.children);
+	INIT_LIST_HEAD(&root->node.val);
 
-	node->children_hit = 0;
-	node->parent = NULL;
-	node->hit = 0;
+	root->node.parent = NULL;
+	root->node.hit = 0;
+	root->node.children_hit = 0;
+	root->max_depth = 0;
 }
 
 static inline u64 cumul_hits(struct callchain_node *node)
@@ -61,8 +67,9 @@
 }
 
 int register_callchain_param(struct callchain_param *param);
-int append_chain(struct callchain_node *root, struct ip_callchain *chain,
-		 struct map_symbol *syms, u64 period);
+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);
 
 bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event);
 #endif	/* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index be22ae6..2022e87 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -87,7 +87,7 @@
 
 static struct hist_entry *hist_entry__new(struct hist_entry *template)
 {
-	size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_node) : 0;
+	size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0;
 	struct hist_entry *self = malloc(sizeof(*self) + callchain_size);
 
 	if (self != NULL) {
@@ -226,6 +226,8 @@
 
 		if (!cmp) {
 			iter->period += he->period;
+			if (symbol_conf.use_callchain)
+				callchain_merge(iter->callchain, he->callchain);
 			hist_entry__free(he);
 			return false;
 		}
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index 58a470d..bd74977 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -22,6 +22,7 @@
 	return ".";
 }
 
+#ifdef NO_STRLCPY
 size_t strlcpy(char *dest, const char *src, size_t size)
 {
 	size_t ret = strlen(src);
@@ -33,7 +34,7 @@
 	}
 	return ret;
 }
-
+#endif
 
 static char *get_pathname(void)
 {
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 46e531d..0b91053 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -70,7 +70,7 @@
 		struct hist_entry *pair;
 		struct rb_root	  sorted_chain;
 	};
-	struct callchain_node	callchain[0];
+	struct callchain_root	callchain[0];
 };
 
 enum sort_type {
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index b2f5ae9..b39f499 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -388,6 +388,20 @@
 	return fprintf(fp, "%s", sbuild_id);
 }
 
+size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp)
+{
+	size_t ret = 0;
+	struct rb_node *nd;
+	struct symbol_name_rb_node *pos;
+
+	for (nd = rb_first(&self->symbol_names[type]); nd; nd = rb_next(nd)) {
+		pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
+		fprintf(fp, "%s\n", pos->sym.name);
+	}
+
+	return ret;
+}
+
 size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
 {
 	struct rb_node *nd;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index ea95c27..038f220 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -182,6 +182,7 @@
 size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits);
 
 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 {
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 7ea983a..f7af2fc 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -97,7 +97,7 @@
 	register_python_scripting(&python_scripting_unsupported_ops);
 }
 #else
-struct scripting_ops python_scripting_ops;
+extern struct scripting_ops python_scripting_ops;
 
 void setup_python_scripting(void)
 {
@@ -158,7 +158,7 @@
 	register_perl_scripting(&perl_scripting_unsupported_ops);
 }
 #else
-struct scripting_ops perl_scripting_ops;
+extern struct scripting_ops perl_scripting_ops;
 
 void setup_perl_scripting(void)
 {
diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c
index 66f2d58..6d0df80 100644
--- a/tools/perf/util/ui/browser.c
+++ b/tools/perf/util/ui/browser.c
@@ -1,16 +1,6 @@
-#define _GNU_SOURCE
-#include <stdio.h>
-#undef _GNU_SOURCE
-/*
- * slang versions <= 2.0.6 have a "#if HAVE_LONG_LONG" that breaks
- * the build if it isn't defined. Use the equivalent one that glibc
- * has on features.h.
- */
-#include <features.h>
-#ifndef HAVE_LONG_LONG
-#define HAVE_LONG_LONG __GLIBC_HAVE_LONG_LONG
-#endif
 #include <slang.h>
+#include "libslang.h"
+#include <linux/compiler.h>
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <stdlib.h>
@@ -19,17 +9,9 @@
 #include "helpline.h"
 #include "../color.h"
 #include "../util.h"
+#include <stdio.h>
 
-#if SLANG_VERSION < 20104
-#define sltt_set_color(obj, name, fg, bg) \
-	SLtt_set_color(obj,(char *)name, (char *)fg, (char *)bg)
-#else
-#define sltt_set_color SLtt_set_color
-#endif
-
-newtComponent newt_form__new(void);
-
-int ui_browser__percent_color(double percent, bool current)
+static int ui_browser__percent_color(double percent, bool current)
 {
 	if (current)
 		return HE_COLORSET_SELECTED;
@@ -40,6 +22,23 @@
 	return HE_COLORSET_NORMAL;
 }
 
+void ui_browser__set_color(struct ui_browser *self __used, int color)
+{
+	SLsmg_set_color(color);
+}
+
+void ui_browser__set_percent_color(struct ui_browser *self,
+				   double percent, bool current)
+{
+	 int color = ui_browser__percent_color(percent, current);
+	 ui_browser__set_color(self, color);
+}
+
+void ui_browser__gotorc(struct ui_browser *self, int y, int x)
+{
+	SLsmg_gotorc(self->y + y, self->x + x);
+}
+
 void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence)
 {
 	struct list_head *head = self->entries;
@@ -111,7 +110,7 @@
 	nd = self->top;
 
 	while (nd != NULL) {
-		SLsmg_gotorc(self->y + row, self->x);
+		ui_browser__gotorc(self, row, 0);
 		self->write(self, nd, row);
 		if (++row == self->height)
 			break;
@@ -131,13 +130,10 @@
 	int cols, rows;
 	newtGetScreenSize(&cols, &rows);
 
-	if (self->width > cols - 4)
-		self->width = cols - 4;
-	self->height = rows - 5;
-	if (self->height > self->nr_entries)
-		self->height = self->nr_entries;
-	self->y  = (rows - self->height) / 2;
-	self->x = (cols - self->width) / 2;
+	self->width = cols - 1;
+	self->height = rows - 2;
+	self->y = 1;
+	self->x = 0;
 }
 
 void ui_browser__reset_index(struct ui_browser *self)
@@ -146,34 +142,48 @@
 	self->seek(self, 0, SEEK_SET);
 }
 
+void ui_browser__add_exit_key(struct ui_browser *self, int key)
+{
+	newtFormAddHotKey(self->form, key);
+}
+
+void ui_browser__add_exit_keys(struct ui_browser *self, int keys[])
+{
+	int i = 0;
+
+	while (keys[i] && i < 64) {
+		ui_browser__add_exit_key(self, keys[i]);
+		++i;
+	}
+}
+
 int ui_browser__show(struct ui_browser *self, const char *title,
 		     const char *helpline, ...)
 {
 	va_list ap;
+	int keys[] = { NEWT_KEY_UP, NEWT_KEY_DOWN, NEWT_KEY_PGUP,
+		       NEWT_KEY_PGDN, NEWT_KEY_HOME, NEWT_KEY_END, ' ',
+		       NEWT_KEY_LEFT, NEWT_KEY_ESCAPE, 'q', CTRL('c'), 0 };
 
-	if (self->form != NULL) {
+	if (self->form != NULL)
 		newtFormDestroy(self->form);
-		newtPopWindow();
-	}
+
 	ui_browser__refresh_dimensions(self);
-	newtCenteredWindow(self->width, self->height, title);
-	self->form = newt_form__new();
+	self->form = newtForm(NULL, NULL, 0);
 	if (self->form == NULL)
 		return -1;
 
-	self->sb = newtVerticalScrollbar(self->width, 0, self->height,
+	self->sb = newtVerticalScrollbar(self->width, 1, self->height,
 					 HE_COLORSET_NORMAL,
 					 HE_COLORSET_SELECTED);
 	if (self->sb == NULL)
 		return -1;
 
-	newtFormAddHotKey(self->form, NEWT_KEY_UP);
-	newtFormAddHotKey(self->form, NEWT_KEY_DOWN);
-	newtFormAddHotKey(self->form, NEWT_KEY_PGUP);
-	newtFormAddHotKey(self->form, NEWT_KEY_PGDN);
-	newtFormAddHotKey(self->form, NEWT_KEY_HOME);
-	newtFormAddHotKey(self->form, NEWT_KEY_END);
-	newtFormAddHotKey(self->form, ' ');
+	SLsmg_gotorc(0, 0);
+	ui_browser__set_color(self, NEWT_COLORSET_ROOT);
+	slsmg_write_nstring(title, self->width);
+
+	ui_browser__add_exit_keys(self, keys);
 	newtFormAddComponent(self->form, self->sb);
 
 	va_start(ap, helpline);
@@ -185,7 +195,6 @@
 void ui_browser__hide(struct ui_browser *self)
 {
 	newtFormDestroy(self->form);
-	newtPopWindow();
 	self->form = NULL;
 	ui_helpline__pop();
 }
@@ -196,28 +205,28 @@
 
 	newtScrollbarSet(self->sb, self->index, self->nr_entries - 1);
 	row = self->refresh(self);
-	SLsmg_set_color(HE_COLORSET_NORMAL);
+	ui_browser__set_color(self, HE_COLORSET_NORMAL);
 	SLsmg_fill_region(self->y + row, self->x,
 			  self->height - row, self->width, ' ');
 
 	return 0;
 }
 
-int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es)
+int ui_browser__run(struct ui_browser *self)
 {
+	struct newtExitStruct es;
+
 	if (ui_browser__refresh(self) < 0)
 		return -1;
 
 	while (1) {
 		off_t offset;
 
-		newtFormRun(self->form, es);
+		newtFormRun(self->form, &es);
 
-		if (es->reason != NEWT_EXIT_HOTKEY)
+		if (es.reason != NEWT_EXIT_HOTKEY)
 			break;
-		if (is_exit_key(es->u.key))
-			return es->u.key;
-		switch (es->u.key) {
+		switch (es.u.key) {
 		case NEWT_KEY_DOWN:
 			if (self->index == self->nr_entries - 1)
 				break;
@@ -274,12 +283,12 @@
 			self->seek(self, -offset, SEEK_END);
 			break;
 		default:
-			return es->u.key;
+			return es.u.key;
 		}
 		if (ui_browser__refresh(self) < 0)
 			return -1;
 	}
-	return 0;
+	return -1;
 }
 
 unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
@@ -294,7 +303,7 @@
 	pos = self->top;
 
 	list_for_each_from(pos, head) {
-		SLsmg_gotorc(self->y + row, self->x);
+		ui_browser__gotorc(self, row, 0);
 		self->write(self, pos, row);
 		if (++row == self->height)
 			break;
diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h
index 0b9f829..0dc7e4d 100644
--- a/tools/perf/util/ui/browser.h
+++ b/tools/perf/util/ui/browser.h
@@ -25,16 +25,21 @@
 };
 
 
-int ui_browser__percent_color(double percent, bool current);
+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);
 bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row);
 void ui_browser__refresh_dimensions(struct ui_browser *self);
 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[]);
 int ui_browser__show(struct ui_browser *self, const char *title,
 		     const char *helpline, ...);
 void ui_browser__hide(struct ui_browser *self);
 int ui_browser__refresh(struct ui_browser *self);
-int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es);
+int ui_browser__run(struct ui_browser *self);
 
 void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence);
 unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self);
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index a90273e..82b78f9 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -40,14 +40,12 @@
 
 	if (ol->offset != -1) {
 		struct objdump_line_rb_node *olrb = objdump_line__rb(ol);
-		int color = ui_browser__percent_color(olrb->percent, current_entry);
-		SLsmg_set_color(color);
+		ui_browser__set_percent_color(self, olrb->percent, current_entry);
 		slsmg_printf(" %7.2f ", olrb->percent);
 		if (!current_entry)
-			SLsmg_set_color(HE_COLORSET_CODE);
+			ui_browser__set_color(self, HE_COLORSET_CODE);
 	} else {
-		int color = ui_browser__percent_color(0, current_entry);
-		SLsmg_set_color(color);
+		ui_browser__set_percent_color(self, 0, current_entry);
 		slsmg_write_nstring(" ", 9);
 	}
 
@@ -135,32 +133,31 @@
 	self->curr_hot = nd;
 }
 
-static int annotate_browser__run(struct annotate_browser *self,
-				 struct newtExitStruct *es)
+static int annotate_browser__run(struct annotate_browser *self)
 {
 	struct rb_node *nd;
 	struct hist_entry *he = self->b.priv;
+	int key;
 
 	if (ui_browser__show(&self->b, he->ms.sym->name,
-			     "<- or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0)
+			     "<-, -> or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0)
 		return -1;
-
-	newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT);
-	newtFormAddHotKey(self->b.form, NEWT_KEY_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);
 
 	nd = self->curr_hot;
 	if (nd) {
-		newtFormAddHotKey(self->b.form, NEWT_KEY_TAB);
-		newtFormAddHotKey(self->b.form, NEWT_KEY_UNTAB);
+		int tabs[] = { NEWT_KEY_TAB, NEWT_KEY_UNTAB, 0 };
+		ui_browser__add_exit_keys(&self->b, tabs);
 	}
 
 	while (1) {
-		ui_browser__run(&self->b, es);
+		key = ui_browser__run(&self->b);
 
-		if (es->reason != NEWT_EXIT_HOTKEY)
-			break;
-
-		switch (es->u.key) {
+		switch (key) {
 		case NEWT_KEY_TAB:
 			nd = rb_prev(nd);
 			if (nd == NULL)
@@ -179,12 +176,11 @@
 	}
 out:
 	ui_browser__hide(&self->b);
-	return es->u.key;
+	return key;
 }
 
 int hist_entry__tui_annotate(struct hist_entry *self)
 {
-	struct newtExitStruct es;
 	struct objdump_line *pos, *n;
 	struct objdump_line_rb_node *rbpos;
 	LIST_HEAD(head);
@@ -232,7 +228,7 @@
 		annotate_browser__set_top(&browser, browser.curr_hot);
 
 	browser.b.width += 18; /* Percentage */
-	ret = annotate_browser__run(&browser, &es);
+	ret = annotate_browser__run(&browser);
 	list_for_each_entry_safe(pos, n, &head, 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 dafdf67..ebda8c3 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -58,6 +58,11 @@
 	return map_symbol__folded(&self->ms);
 }
 
+static void map_symbol__set_folding(struct map_symbol *self, bool unfold)
+{
+	self->unfolded = unfold ? self->has_children : false;
+}
+
 static int callchain_node__count_rows_rb_tree(struct callchain_node *self)
 {
 	int n = 0;
@@ -129,16 +134,16 @@
 	for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) {
 		struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
 		struct callchain_list *chain;
-		int first = true;
+		bool first = true;
 
 		list_for_each_entry(chain, &child->val, list) {
 			if (first) {
 				first = false;
 				chain->ms.has_children = chain->list.next != &child->val ||
-							 rb_first(&child->rb_root) != NULL;
+							 !RB_EMPTY_ROOT(&child->rb_root);
 			} else
 				chain->ms.has_children = chain->list.next == &child->val &&
-							 rb_first(&child->rb_root) != NULL;
+							 !RB_EMPTY_ROOT(&child->rb_root);
 		}
 
 		callchain_node__init_have_children_rb_tree(child);
@@ -150,7 +155,7 @@
 	struct callchain_list *chain;
 
 	list_for_each_entry(chain, &self->val, list)
-		chain->ms.has_children = rb_first(&self->rb_root) != NULL;
+		chain->ms.has_children = !RB_EMPTY_ROOT(&self->rb_root);
 
 	callchain_node__init_have_children_rb_tree(self);
 }
@@ -168,6 +173,7 @@
 static void hist_entry__init_have_children(struct hist_entry *self)
 {
 	if (!self->init_have_children) {
+		self->ms.has_children = !RB_EMPTY_ROOT(&self->sorted_chain);
 		callchain__init_have_children(&self->sorted_chain);
 		self->init_have_children = true;
 	}
@@ -195,43 +201,114 @@
 	return false;
 }
 
-static int hist_browser__run(struct hist_browser *self, const char *title,
-			     struct newtExitStruct *es)
+static int callchain_node__set_folding_rb_tree(struct callchain_node *self, bool unfold)
 {
-	char str[256], unit;
-	unsigned long nr_events = self->hists->stats.nr_events[PERF_RECORD_SAMPLE];
+	int n = 0;
+	struct rb_node *nd;
+
+	for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) {
+		struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
+		struct callchain_list *chain;
+		bool has_children = false;
+
+		list_for_each_entry(chain, &child->val, list) {
+			++n;
+			map_symbol__set_folding(&chain->ms, unfold);
+			has_children = chain->ms.has_children;
+		}
+
+		if (has_children)
+			n += callchain_node__set_folding_rb_tree(child, unfold);
+	}
+
+	return n;
+}
+
+static int callchain_node__set_folding(struct callchain_node *node, bool unfold)
+{
+	struct callchain_list *chain;
+	bool has_children = false;
+	int n = 0;
+
+	list_for_each_entry(chain, &node->val, list) {
+		++n;
+		map_symbol__set_folding(&chain->ms, unfold);
+		has_children = chain->ms.has_children;
+	}
+
+	if (has_children)
+		n += callchain_node__set_folding_rb_tree(node, unfold);
+
+	return n;
+}
+
+static int callchain__set_folding(struct rb_root *chain, bool unfold)
+{
+	struct rb_node *nd;
+	int n = 0;
+
+	for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
+		struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
+		n += callchain_node__set_folding(node, unfold);
+	}
+
+	return n;
+}
+
+static void hist_entry__set_folding(struct hist_entry *self, bool unfold)
+{
+	hist_entry__init_have_children(self);
+	map_symbol__set_folding(&self->ms, unfold);
+
+	if (self->ms.has_children) {
+		int n = callchain__set_folding(&self->sorted_chain, unfold);
+		self->nr_rows = unfold ? n : 0;
+	} else
+		self->nr_rows = 0;
+}
+
+static void hists__set_folding(struct hists *self, bool unfold)
+{
+	struct rb_node *nd;
+
+	self->nr_entries = 0;
+
+	for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
+		struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
+		hist_entry__set_folding(he, unfold);
+		self->nr_entries += 1 + he->nr_rows;
+	}
+}
+
+static void hist_browser__set_folding(struct hist_browser *self, bool unfold)
+{
+	hists__set_folding(self->hists, unfold);
+	self->b.nr_entries = self->hists->nr_entries;
+	/* Go to the start, we may be way after valid entries after a collapse */
+	ui_browser__reset_index(&self->b);
+}
+
+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, };
 
 	self->b.entries = &self->hists->entries;
 	self->b.nr_entries = self->hists->nr_entries;
 
 	hist_browser__refresh_dimensions(self);
 
-	nr_events = convert_unit(nr_events, &unit);
-	snprintf(str, sizeof(str), "Events: %lu%c                            ",
-		 nr_events, unit);
-	newtDrawRootText(0, 0, str);
-
 	if (ui_browser__show(&self->b, title,
 			     "Press '?' for help on key bindings") < 0)
 		return -1;
 
-	newtFormAddHotKey(self->b.form, 'a');
-	newtFormAddHotKey(self->b.form, '?');
-	newtFormAddHotKey(self->b.form, 'h');
-	newtFormAddHotKey(self->b.form, 'd');
-	newtFormAddHotKey(self->b.form, 'D');
-	newtFormAddHotKey(self->b.form, 't');
-
-	newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT);
-	newtFormAddHotKey(self->b.form, NEWT_KEY_RIGHT);
-	newtFormAddHotKey(self->b.form, NEWT_KEY_ENTER);
+	ui_browser__add_exit_keys(&self->b, exit_keys);
 
 	while (1) {
-		ui_browser__run(&self->b, es);
+		key = ui_browser__run(&self->b);
 
-		if (es->reason != NEWT_EXIT_HOTKEY)
-			break;
-		switch (es->u.key) {
+		switch (key) {
 		case 'D': { /* Debug */
 			static int seq;
 			struct hist_entry *h = rb_entry(self->b.top,
@@ -245,18 +322,26 @@
 					   self->b.top_idx,
 					   h->row_offset, h->nr_rows);
 		}
-			continue;
+			break;
+		case 'C':
+			/* Collapse the whole world. */
+			hist_browser__set_folding(self, false);
+			break;
+		case 'E':
+			/* Expand the whole world. */
+			hist_browser__set_folding(self, true);
+			break;
 		case NEWT_KEY_ENTER:
 			if (hist_browser__toggle_fold(self))
 				break;
 			/* fall thru */
 		default:
-			return 0;
+			goto out;
 		}
 	}
-
+out:
 	ui_browser__hide(&self->b);
-	return 0;
+	return key;
 }
 
 static char *callchain_list__sym_name(struct callchain_list *self,
@@ -306,15 +391,10 @@
 			int color;
 			bool was_first = first;
 
-			if (first) {
+			if (first)
 				first = false;
-				chain->ms.has_children = chain->list.next != &child->val ||
-							 rb_first(&child->rb_root) != NULL;
-			} else {
+			else
 				extra_offset = LEVEL_OFFSET_STEP;
-				chain->ms.has_children = chain->list.next == &child->val &&
-							 rb_first(&child->rb_root) != NULL;
-			}
 
 			folded_sign = callchain_list__folded(chain);
 			if (*row_offset != 0) {
@@ -341,8 +421,8 @@
 				*is_current_entry = true;
 			}
 
-			SLsmg_set_color(color);
-			SLsmg_gotorc(self->b.y + row, self->b.x);
+			ui_browser__set_color(&self->b, color);
+			ui_browser__gotorc(&self->b, row, 0);
 			slsmg_write_nstring(" ", offset + extra_offset);
 			slsmg_printf("%c ", folded_sign);
 			slsmg_write_nstring(str, width);
@@ -384,12 +464,7 @@
 	list_for_each_entry(chain, &node->val, list) {
 		char ipstr[BITS_PER_LONG / 4 + 1], *s;
 		int color;
-		/*
-		 * FIXME: This should be moved to somewhere else,
-		 * probably when the callchain is created, so as not to
-		 * traverse it all over again
-		 */
-		chain->ms.has_children = rb_first(&node->rb_root) != NULL;
+
 		folded_sign = callchain_list__folded(chain);
 
 		if (*row_offset != 0) {
@@ -405,8 +480,8 @@
 		}
 
 		s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
-		SLsmg_gotorc(self->b.y + row, self->b.x);
-		SLsmg_set_color(color);
+		ui_browser__gotorc(&self->b, row, 0);
+		ui_browser__set_color(&self->b, color);
 		slsmg_write_nstring(" ", offset);
 		slsmg_printf("%c ", folded_sign);
 		slsmg_write_nstring(s, width - 2);
@@ -465,7 +540,7 @@
 	}
 
 	if (symbol_conf.use_callchain) {
-		entry->ms.has_children = !RB_EMPTY_ROOT(&entry->sorted_chain);
+		hist_entry__init_have_children(entry);
 		folded_sign = hist_entry__folded(entry);
 	}
 
@@ -484,8 +559,8 @@
 				color = HE_COLORSET_NORMAL;
 		}
 
-		SLsmg_set_color(color);
-		SLsmg_gotorc(self->b.y + row, self->b.x);
+		ui_browser__set_color(&self->b, color);
+		ui_browser__gotorc(&self->b, row, 0);
 		if (symbol_conf.use_callchain) {
 			slsmg_printf("%c ", folded_sign);
 			width -= 2;
@@ -687,8 +762,6 @@
 
 static void hist_browser__delete(struct hist_browser *self)
 {
-	newtFormDestroy(self->b.form);
-	newtPopWindow();
 	free(self);
 }
 
@@ -702,21 +775,26 @@
 	return self->he_selection->thread;
 }
 
-static int hist_browser__title(char *bf, size_t size, const char *ev_name,
-			       const struct dso *dso, const struct thread *thread)
+static int hists__browser_title(struct hists *self, char *bf, size_t size,
+				const char *ev_name, const struct dso *dso,
+				const struct thread *thread)
 {
-	int printed = 0;
+	char unit;
+	int printed;
+	unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE];
+
+	nr_events = convert_unit(nr_events, &unit);
+	printed = snprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name);
 
 	if (thread)
 		printed += snprintf(bf + printed, size - printed,
-				    "Thread: %s(%d)",
-				    (thread->comm_set ?  thread->comm : ""),
+				    ", Thread: %s(%d)",
+				    (thread->comm_set ? thread->comm : ""),
 				    thread->pid);
 	if (dso)
 		printed += snprintf(bf + printed, size - printed,
-				    "%sDSO: %s", thread ? " " : "",
-				    dso->short_name);
-	return printed ?: snprintf(bf, size, "Event: %s", ev_name);
+				    ", DSO: %s", dso->short_name);
+	return printed;
 }
 
 int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
@@ -725,7 +803,6 @@
 	struct pstack *fstack;
 	const struct thread *thread_filter = NULL;
 	const struct dso *dso_filter = NULL;
-	struct newtExitStruct es;
 	char msg[160];
 	int key = -1;
 
@@ -738,9 +815,8 @@
 
 	ui_helpline__push(helpline);
 
-	hist_browser__title(msg, sizeof(msg), ev_name,
-			    dso_filter, thread_filter);
-
+	hists__browser_title(self, msg, sizeof(msg), ev_name,
+			     dso_filter, thread_filter);
 	while (1) {
 		const struct thread *thread;
 		const struct dso *dso;
@@ -749,70 +825,63 @@
 		    annotate = -2, zoom_dso = -2, zoom_thread = -2,
 		    browse_map = -2;
 
-		if (hist_browser__run(browser, msg, &es))
-			break;
+		key = hist_browser__run(browser, msg);
 
 		thread = hist_browser__selected_thread(browser);
 		dso = browser->selection->map ? browser->selection->map->dso : NULL;
 
-		if (es.reason == NEWT_EXIT_HOTKEY) {
-			key = es.u.key;
-
-			switch (key) {
-			case NEWT_KEY_F1:
-				goto do_help;
-			case NEWT_KEY_TAB:
-			case NEWT_KEY_UNTAB:
-				/*
-				 * Exit the browser, let hists__browser_tree
-				 * go to the next or previous
-				 */
-				goto out_free_stack;
-			default:;
-			}
-
-			switch (key) {
-			case 'a':
-				if (browser->selection->map == NULL &&
-				    browser->selection->map->dso->annotate_warned)
-					continue;
-				goto do_annotate;
-			case 'd':
-				goto zoom_dso;
-			case 't':
-				goto zoom_thread;
-			case 'h':
-			case '?':
-do_help:
-				ui__help_window("->        Zoom into DSO/Threads & Annotate current symbol\n"
-						"<-        Zoom out\n"
-						"a         Annotate current symbol\n"
-						"h/?/F1    Show this window\n"
-						"d         Zoom into current DSO\n"
-						"t         Zoom into current Thread\n"
-						"q/CTRL+C  Exit browser");
+		switch (key) {
+		case NEWT_KEY_TAB:
+		case NEWT_KEY_UNTAB:
+			/*
+			 * Exit the browser, let hists__browser_tree
+			 * go to the next or previous
+			 */
+			goto out_free_stack;
+		case 'a':
+			if (browser->selection->map == NULL &&
+			    browser->selection->map->dso->annotate_warned)
 				continue;
-			default:;
-			}
-			if (is_exit_key(key)) {
-				if (key == NEWT_KEY_ESCAPE &&
-				    !ui__dialog_yesno("Do you really want to exit?"))
-					continue;
-				break;
-			}
+			goto do_annotate;
+		case 'd':
+			goto zoom_dso;
+		case 't':
+			goto zoom_thread;
+		case NEWT_KEY_F1:
+		case 'h':
+		case '?':
+			ui__help_window("->        Zoom into DSO/Threads & Annotate current symbol\n"
+					"<-        Zoom out\n"
+					"a         Annotate current symbol\n"
+					"h/?/F1    Show this window\n"
+					"C         Collapse all callchains\n"
+					"E         Expand all callchains\n"
+					"d         Zoom into current DSO\n"
+					"t         Zoom into current Thread\n"
+					"q/CTRL+C  Exit browser");
+			continue;
+		case NEWT_KEY_ENTER:
+		case NEWT_KEY_RIGHT:
+			/* menu */
+			break;
+		case NEWT_KEY_LEFT: {
+			const void *top;
 
-			if (es.u.key == NEWT_KEY_LEFT) {
-				const void *top;
-
-				if (pstack__empty(fstack))
-					continue;
-				top = pstack__pop(fstack);
-				if (top == &dso_filter)
-					goto zoom_out_dso;
-				if (top == &thread_filter)
-					goto zoom_out_thread;
+			if (pstack__empty(fstack))
 				continue;
-			}
+			top = pstack__pop(fstack);
+			if (top == &dso_filter)
+				goto zoom_out_dso;
+			if (top == &thread_filter)
+				goto zoom_out_thread;
+			continue;
+		}
+		case NEWT_KEY_ESCAPE:
+			if (!ui__dialog_yesno("Do you really want to exit?"))
+				continue;
+			/* Fall thru */
+		default:
+			goto out_free_stack;
 		}
 
 		if (browser->selection->sym != NULL &&
@@ -885,8 +954,8 @@
 				pstack__push(fstack, &dso_filter);
 			}
 			hists__filter_by_dso(self, dso_filter);
-			hist_browser__title(msg, sizeof(msg), ev_name,
-					    dso_filter, thread_filter);
+			hists__browser_title(self, msg, sizeof(msg), ev_name,
+					     dso_filter, thread_filter);
 			hist_browser__reset(browser);
 		} else if (choice == zoom_thread) {
 zoom_thread:
@@ -903,8 +972,8 @@
 				pstack__push(fstack, &thread_filter);
 			}
 			hists__filter_by_thread(self, thread_filter);
-			hist_browser__title(msg, sizeof(msg), ev_name,
-					    dso_filter, thread_filter);
+			hists__browser_title(self, msg, sizeof(msg), ev_name,
+					     dso_filter, thread_filter);
 			hist_browser__reset(browser);
 		}
 	}
@@ -925,10 +994,6 @@
 		const char *ev_name = __event_name(hists->type, hists->config);
 
 		key = hists__browse(hists, help, ev_name);
-
-		if (is_exit_key(key))
-			break;
-
 		switch (key) {
 		case NEWT_KEY_TAB:
 			next = rb_next(nd);
@@ -940,7 +1005,7 @@
 				continue;
 			nd = rb_prev(nd);
 		default:
-			break;
+			return key;
 		}
 	}
 
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
index 142b825..e35437d 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/util/ui/browsers/map.c
@@ -1,6 +1,5 @@
 #include "../libslang.h"
 #include <elf.h>
-#include <newt.h>
 #include <sys/ttydefaults.h>
 #include <ctype.h>
 #include <string.h>
@@ -47,7 +46,6 @@
 struct map_browser {
 	struct ui_browser b;
 	struct map	  *map;
-	u16		  namelen;
 	u8		  addrlen;
 };
 
@@ -56,14 +54,16 @@
 	struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
 	struct map_browser *mb = container_of(self, struct map_browser, b);
 	bool current_entry = ui_browser__is_current_entry(self, row);
-	int color = ui_browser__percent_color(0, current_entry);
+	int width;
 
-	SLsmg_set_color(color);
+	ui_browser__set_percent_color(self, 0, current_entry);
 	slsmg_printf("%*llx %*llx %c ",
 		     mb->addrlen, sym->start, mb->addrlen, sym->end,
 		     sym->binding == STB_GLOBAL ? 'g' :
 		     sym->binding == STB_LOCAL  ? 'l' : 'w');
-	slsmg_write_nstring(sym->name, mb->namelen);
+	width = self->width - ((mb->addrlen * 2) + 4);
+	if (width > 0)
+		slsmg_write_nstring(sym->name, width);
 }
 
 /* FIXME uber-kludgy, see comment on cmd_report... */
@@ -98,31 +98,29 @@
 	return 0;
 }
 
-static int map_browser__run(struct map_browser *self, struct newtExitStruct *es)
+static int map_browser__run(struct map_browser *self)
 {
+	int key;
+
 	if (ui_browser__show(&self->b, self->map->dso->long_name,
 			     "Press <- or ESC to exit, %s / to search",
 			     verbose ? "" : "restart with -v to use") < 0)
 		return -1;
 
-	newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT);
-	newtFormAddHotKey(self->b.form, NEWT_KEY_ENTER);
 	if (verbose)
-		newtFormAddHotKey(self->b.form, '/');
+		ui_browser__add_exit_key(&self->b, '/');
 
 	while (1) {
-		ui_browser__run(&self->b, es);
+		key = ui_browser__run(&self->b);
 
-		if (es->reason != NEWT_EXIT_HOTKEY)
-			break;
-		if (verbose && es->u.key == '/')
+		if (verbose && key == '/')
 			map_browser__search(self);
 		else
 			break;
 	}
 
 	ui_browser__hide(&self->b);
-	return 0;
+	return key;
 }
 
 int map__browse(struct map *self)
@@ -136,7 +134,6 @@
 		},
 		.map = self,
 	};
-	struct newtExitStruct es;
 	struct rb_node *nd;
 	char tmp[BITS_PER_LONG / 4];
 	u64 maxaddr = 0;
@@ -144,8 +141,6 @@
 	for (nd = rb_first(mb.b.entries); nd; nd = rb_next(nd)) {
 		struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
 
-		if (mb.namelen < pos->namelen)
-			mb.namelen = pos->namelen;
 		if (maxaddr < pos->end)
 			maxaddr = pos->end;
 		if (verbose) {
@@ -156,6 +151,5 @@
 	}
 
 	mb.addrlen = snprintf(tmp, sizeof(tmp), "%llx", maxaddr);
-	mb.b.width += mb.addrlen * 2 + 4 + mb.namelen;
-	return map_browser__run(&mb, &es);
+	return map_browser__run(&mb);
 }
diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c
index 04600e2..9706d9d 100644
--- a/tools/perf/util/ui/util.c
+++ b/tools/perf/util/ui/util.c
@@ -11,8 +11,6 @@
 #include "helpline.h"
 #include "util.h"
 
-newtComponent newt_form__new(void);
-
 static void newt_form__set_exit_keys(newtComponent self)
 {
 	newtFormAddHotKey(self, NEWT_KEY_LEFT);
@@ -22,7 +20,7 @@
 	newtFormAddHotKey(self, CTRL('c'));
 }
 
-newtComponent newt_form__new(void)
+static newtComponent newt_form__new(void)
 {
 	newtComponent self = newtForm(NULL, NULL, 0);
 	if (self)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index f380fed..7562707 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -266,19 +266,6 @@
 bool strlazymatch(const char *str, const char *pat);
 unsigned long convert_unit(unsigned long value, char *unit);
 
-#ifndef ESC
-#define ESC 27
-#endif
-
-static inline bool is_exit_key(int key)
-{
-	char up;
-	if (key == CTRL('c') || key == ESC)
-		return true;
-	up = toupper(key);
-	return up == 'Q';
-}
-
 #define _STR(x) #x
 #define STR(x) _STR(x)
 
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 5186e72..60e5e46 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1305,6 +1305,7 @@
 	.unlocked_ioctl = kvm_vcpu_ioctl,
 	.compat_ioctl   = kvm_vcpu_ioctl,
 	.mmap           = kvm_vcpu_mmap,
+	.llseek		= noop_llseek,
 };
 
 /*
@@ -1774,6 +1775,7 @@
 	.compat_ioctl   = kvm_vm_compat_ioctl,
 #endif
 	.mmap           = kvm_vm_mmap,
+	.llseek		= noop_llseek,
 };
 
 static int kvm_dev_ioctl_create_vm(void)
@@ -1867,6 +1869,7 @@
 static struct file_operations kvm_chardev_ops = {
 	.unlocked_ioctl = kvm_dev_ioctl,
 	.compat_ioctl   = kvm_dev_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice kvm_dev = {